[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.{v,js,css}]\nindent_style = tab\n\n[*.{bat,cmd}]\n# BAT/CMD ~ DOS/Win requires BAT/CMD files to have CRLF EOLNs\nend_of_line = crlf\n\n[*.{yml,yaml}]\nindent_style = space\nindent_size = 2\n\n[*.md]\ntrim_trailing_whitespace = false\n# lines that are too long will trigger an error in cmd/tools/vcheck-md.v\n# run v check-md [folder/file] to test markdown files\n# the longest normal line is specified with this constant:\n# `too_long_line_length_other     = 100`\nmax_line_length = 100\n\n[*.{txt,out}]\ninsert_final_newline = false\n\n[{Makefile,GNUmakefile}]\nindent_style = tab\n"
  },
  {
    "path": ".git/HEAD",
    "content": "ref: refs/heads/master\n"
  },
  {
    "path": ".git/config",
    "content": "[core]\n\trepositoryformatversion = 1\n\tfilemode = true\n\tbare = false\n\tlogallrefupdates = true\n[remote \"origin\"]\n\turl = https://github.com/vlang/v\n\ttagOpt = --no-tags\n\tfetch = +refs/heads/master:refs/remotes/origin/master\n\tpromisor = true\n\tpartialclonefilter = blob:limit=1048576\n[branch \"master\"]\n\tremote = origin\n\tmerge = refs/heads/master\n"
  },
  {
    "path": ".git/description",
    "content": "Unnamed repository; edit this file 'description' to name the repository.\n"
  },
  {
    "path": ".git/hooks/applypatch-msg.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to check the commit log message taken by\n# applypatch from an e-mail message.\n#\n# The hook should exit with non-zero status after issuing an\n# appropriate message if it wants to stop the commit.  The hook is\n# allowed to edit the commit message file.\n#\n# To enable this hook, rename this file to \"applypatch-msg\".\n\n. git-sh-setup\ncommitmsg=\"$(git rev-parse --git-path hooks/commit-msg)\"\ntest -x \"$commitmsg\" && exec \"$commitmsg\" ${1+\"$@\"}\n:\n"
  },
  {
    "path": ".git/hooks/commit-msg.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to check the commit log message.\n# Called by \"git commit\" with one argument, the name of the file\n# that has the commit message.  The hook should exit with non-zero\n# status after issuing an appropriate message if it wants to stop the\n# commit.  The hook is allowed to edit the commit message file.\n#\n# To enable this hook, rename this file to \"commit-msg\".\n\n# Uncomment the below to add a Signed-off-by line to the message.\n# Doing this in a hook is a bad idea in general, but the prepare-commit-msg\n# hook is more suited to it.\n#\n# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\\(.*>\\).*$/Signed-off-by: \\1/p')\n# grep -qs \"^$SOB\" \"$1\" || echo \"$SOB\" >> \"$1\"\n\n# This example catches duplicate Signed-off-by lines.\n\ntest \"\" = \"$(grep '^Signed-off-by: ' \"$1\" |\n\t sort | uniq -c | sed -e '/^[ \t]*1[ \t]/d')\" || {\n\techo >&2 Duplicate Signed-off-by lines.\n\texit 1\n}\n"
  },
  {
    "path": ".git/hooks/fsmonitor-watchman.sample",
    "content": "#!/usr/bin/perl\n\nuse strict;\nuse warnings;\nuse IPC::Open2;\n\n# An example hook script to integrate Watchman\n# (https://facebook.github.io/watchman/) with git to speed up detecting\n# new and modified files.\n#\n# The hook is passed a version (currently 2) and last update token\n# formatted as a string and outputs to stdout a new update token and\n# all files that have been modified since the update token. Paths must\n# be relative to the root of the working tree and separated by a single NUL.\n#\n# To enable this hook, rename this file to \"query-watchman\" and set\n# 'git config core.fsmonitor .git/hooks/query-watchman'\n#\nmy ($version, $last_update_token) = @ARGV;\n\n# Uncomment for debugging\n# print STDERR \"$0 $version $last_update_token\\n\";\n\n# Check the hook interface version\nif ($version ne 2) {\n\tdie \"Unsupported query-fsmonitor hook version '$version'.\\n\" .\n\t    \"Falling back to scanning...\\n\";\n}\n\nmy $git_work_tree = get_working_dir();\n\nmy $retry = 1;\n\nmy $json_pkg;\neval {\n\trequire JSON::XS;\n\t$json_pkg = \"JSON::XS\";\n\t1;\n} or do {\n\trequire JSON::PP;\n\t$json_pkg = \"JSON::PP\";\n};\n\nlaunch_watchman();\n\nsub launch_watchman {\n\tmy $o = watchman_query();\n\tif (is_work_tree_watched($o)) {\n\t\toutput_result($o->{clock}, @{$o->{files}});\n\t}\n}\n\nsub output_result {\n\tmy ($clockid, @files) = @_;\n\n\t# Uncomment for debugging watchman output\n\t# open (my $fh, \">\", \".git/watchman-output.out\");\n\t# binmode $fh, \":utf8\";\n\t# print $fh \"$clockid\\n@files\\n\";\n\t# close $fh;\n\n\tbinmode STDOUT, \":utf8\";\n\tprint $clockid;\n\tprint \"\\0\";\n\tlocal $, = \"\\0\";\n\tprint @files;\n}\n\nsub watchman_clock {\n\tmy $response = qx/watchman clock \"$git_work_tree\"/;\n\tdie \"Failed to get clock id on '$git_work_tree'.\\n\" .\n\t\t\"Falling back to scanning...\\n\" if $? != 0;\n\n\treturn $json_pkg->new->utf8->decode($response);\n}\n\nsub watchman_query {\n\tmy $pid = open2(\\*CHLD_OUT, \\*CHLD_IN, 'watchman -j --no-pretty')\n\tor die \"open2() failed: $!\\n\" .\n\t\"Falling back to scanning...\\n\";\n\n\t# In the query expression below we're asking for names of files that\n\t# changed since $last_update_token but not from the .git folder.\n\t#\n\t# To accomplish this, we're using the \"since\" generator to use the\n\t# recency index to select candidate nodes and \"fields\" to limit the\n\t# output to file names only. Then we're using the \"expression\" term to\n\t# further constrain the results.\n\tmy $last_update_line = \"\";\n\tif (substr($last_update_token, 0, 1) eq \"c\") {\n\t\t$last_update_token = \"\\\"$last_update_token\\\"\";\n\t\t$last_update_line = qq[\\n\"since\": $last_update_token,];\n\t}\n\tmy $query = <<\"\tEND\";\n\t\t[\"query\", \"$git_work_tree\", {$last_update_line\n\t\t\t\"fields\": [\"name\"],\n\t\t\t\"expression\": [\"not\", [\"dirname\", \".git\"]]\n\t\t}]\n\tEND\n\n\t# Uncomment for debugging the watchman query\n\t# open (my $fh, \">\", \".git/watchman-query.json\");\n\t# print $fh $query;\n\t# close $fh;\n\n\tprint CHLD_IN $query;\n\tclose CHLD_IN;\n\tmy $response = do {local $/; <CHLD_OUT>};\n\n\t# Uncomment for debugging the watch response\n\t# open ($fh, \">\", \".git/watchman-response.json\");\n\t# print $fh $response;\n\t# close $fh;\n\n\tdie \"Watchman: command returned no output.\\n\" .\n\t\"Falling back to scanning...\\n\" if $response eq \"\";\n\tdie \"Watchman: command returned invalid output: $response\\n\" .\n\t\"Falling back to scanning...\\n\" unless $response =~ /^\\{/;\n\n\treturn $json_pkg->new->utf8->decode($response);\n}\n\nsub is_work_tree_watched {\n\tmy ($output) = @_;\n\tmy $error = $output->{error};\n\tif ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {\n\t\t$retry--;\n\t\tmy $response = qx/watchman watch \"$git_work_tree\"/;\n\t\tdie \"Failed to make watchman watch '$git_work_tree'.\\n\" .\n\t\t    \"Falling back to scanning...\\n\" if $? != 0;\n\t\t$output = $json_pkg->new->utf8->decode($response);\n\t\t$error = $output->{error};\n\t\tdie \"Watchman: $error.\\n\" .\n\t\t\"Falling back to scanning...\\n\" if $error;\n\n\t\t# Uncomment for debugging watchman output\n\t\t# open (my $fh, \">\", \".git/watchman-output.out\");\n\t\t# close $fh;\n\n\t\t# Watchman will always return all files on the first query so\n\t\t# return the fast \"everything is dirty\" flag to git and do the\n\t\t# Watchman query just to get it over with now so we won't pay\n\t\t# the cost in git to look up each individual file.\n\t\tmy $o = watchman_clock();\n\t\t$error = $output->{error};\n\n\t\tdie \"Watchman: $error.\\n\" .\n\t\t\"Falling back to scanning...\\n\" if $error;\n\n\t\toutput_result($o->{clock}, (\"/\"));\n\t\t$last_update_token = $o->{clock};\n\n\t\teval { launch_watchman() };\n\t\treturn 0;\n\t}\n\n\tdie \"Watchman: $error.\\n\" .\n\t\"Falling back to scanning...\\n\" if $error;\n\n\treturn 1;\n}\n\nsub get_working_dir {\n\tmy $working_dir;\n\tif ($^O =~ 'msys' || $^O =~ 'cygwin') {\n\t\t$working_dir = Win32::GetCwd();\n\t\t$working_dir =~ tr/\\\\/\\//;\n\t} else {\n\t\trequire Cwd;\n\t\t$working_dir = Cwd::cwd();\n\t}\n\n\treturn $working_dir;\n}\n"
  },
  {
    "path": ".git/hooks/post-update.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to prepare a packed repository for use over\n# dumb transports.\n#\n# To enable this hook, rename this file to \"post-update\".\n\nexec git update-server-info\n"
  },
  {
    "path": ".git/hooks/pre-applypatch.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to verify what is about to be committed\n# by applypatch from an e-mail message.\n#\n# The hook should exit with non-zero status after issuing an\n# appropriate message if it wants to stop the commit.\n#\n# To enable this hook, rename this file to \"pre-applypatch\".\n\n. git-sh-setup\nprecommit=\"$(git rev-parse --git-path hooks/pre-commit)\"\ntest -x \"$precommit\" && exec \"$precommit\" ${1+\"$@\"}\n:\n"
  },
  {
    "path": ".git/hooks/pre-commit.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to verify what is about to be committed.\n# Called by \"git commit\" with no arguments.  The hook should\n# exit with non-zero status after issuing an appropriate message if\n# it wants to stop the commit.\n#\n# To enable this hook, rename this file to \"pre-commit\".\n\nif git rev-parse --verify HEAD >/dev/null 2>&1\nthen\n\tagainst=HEAD\nelse\n\t# Initial commit: diff against an empty tree object\n\tagainst=$(git hash-object -t tree /dev/null)\nfi\n\n# If you want to allow non-ASCII filenames set this variable to true.\nallownonascii=$(git config --type=bool hooks.allownonascii)\n\n# Redirect output to stderr.\nexec 1>&2\n\n# Cross platform projects tend to avoid non-ASCII filenames; prevent\n# them from being added to the repository. We exploit the fact that the\n# printable range starts at the space character and ends with tilde.\nif [ \"$allownonascii\" != \"true\" ] &&\n\t# Note that the use of brackets around a tr range is ok here, (it's\n\t# even required, for portability to Solaris 10's /usr/bin/tr), since\n\t# the square bracket bytes happen to fall in the designated range.\n\ttest $(git diff-index --cached --name-only --diff-filter=A -z $against |\n\t  LC_ALL=C tr -d '[ -~]\\0' | wc -c) != 0\nthen\n\tcat <<\\EOF\nError: Attempt to add a non-ASCII file name.\n\nThis can cause problems if you want to work with people on other platforms.\n\nTo be portable it is advisable to rename the file.\n\nIf you know what you are doing you can disable this check using:\n\n  git config hooks.allownonascii true\nEOF\n\texit 1\nfi\n\n# If there are whitespace errors, print the offending file names and fail.\nexec git diff-index --check --cached $against --\n"
  },
  {
    "path": ".git/hooks/pre-merge-commit.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to verify what is about to be committed.\n# Called by \"git merge\" with no arguments.  The hook should\n# exit with non-zero status after issuing an appropriate message to\n# stderr if it wants to stop the merge commit.\n#\n# To enable this hook, rename this file to \"pre-merge-commit\".\n\n. git-sh-setup\ntest -x \"$GIT_DIR/hooks/pre-commit\" &&\n        exec \"$GIT_DIR/hooks/pre-commit\"\n:\n"
  },
  {
    "path": ".git/hooks/pre-push.sample",
    "content": "#!/bin/sh\n\n# An example hook script to verify what is about to be pushed.  Called by \"git\n# push\" after it has checked the remote status, but before anything has been\n# pushed.  If this script exits with a non-zero status nothing will be pushed.\n#\n# This hook is called with the following parameters:\n#\n# $1 -- Name of the remote to which the push is being done\n# $2 -- URL to which the push is being done\n#\n# If pushing without using a named remote those arguments will be equal.\n#\n# Information about the commits which are being pushed is supplied as lines to\n# the standard input in the form:\n#\n#   <local ref> <local oid> <remote ref> <remote oid>\n#\n# This sample shows how to prevent push of commits where the log message starts\n# with \"WIP\" (work in progress).\n\nremote=\"$1\"\nurl=\"$2\"\n\nzero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')\n\nwhile read local_ref local_oid remote_ref remote_oid\ndo\n\tif test \"$local_oid\" = \"$zero\"\n\tthen\n\t\t# Handle delete\n\t\t:\n\telse\n\t\tif test \"$remote_oid\" = \"$zero\"\n\t\tthen\n\t\t\t# New branch, examine all commits\n\t\t\trange=\"$local_oid\"\n\t\telse\n\t\t\t# Update to existing branch, examine new commits\n\t\t\trange=\"$remote_oid..$local_oid\"\n\t\tfi\n\n\t\t# Check for WIP commit\n\t\tcommit=$(git rev-list -n 1 --grep '^WIP' \"$range\")\n\t\tif test -n \"$commit\"\n\t\tthen\n\t\t\techo >&2 \"Found WIP commit in $local_ref, not pushing\"\n\t\t\texit 1\n\t\tfi\n\tfi\ndone\n\nexit 0\n"
  },
  {
    "path": ".git/hooks/pre-rebase.sample",
    "content": "#!/bin/sh\n#\n# Copyright (c) 2006, 2008 Junio C Hamano\n#\n# The \"pre-rebase\" hook is run just before \"git rebase\" starts doing\n# its job, and can prevent the command from running by exiting with\n# non-zero status.\n#\n# The hook is called with the following parameters:\n#\n# $1 -- the upstream the series was forked from.\n# $2 -- the branch being rebased (or empty when rebasing the current branch).\n#\n# This sample shows how to prevent topic branches that are already\n# merged to 'next' branch from getting rebased, because allowing it\n# would result in rebasing already published history.\n\npublish=next\nbasebranch=\"$1\"\nif test \"$#\" = 2\nthen\n\ttopic=\"refs/heads/$2\"\nelse\n\ttopic=`git symbolic-ref HEAD` ||\n\texit 0 ;# we do not interrupt rebasing detached HEAD\nfi\n\ncase \"$topic\" in\nrefs/heads/??/*)\n\t;;\n*)\n\texit 0 ;# we do not interrupt others.\n\t;;\nesac\n\n# Now we are dealing with a topic branch being rebased\n# on top of master.  Is it OK to rebase it?\n\n# Does the topic really exist?\ngit show-ref -q \"$topic\" || {\n\techo >&2 \"No such branch $topic\"\n\texit 1\n}\n\n# Is topic fully merged to master?\nnot_in_master=`git rev-list --pretty=oneline ^master \"$topic\"`\nif test -z \"$not_in_master\"\nthen\n\techo >&2 \"$topic is fully merged to master; better remove it.\"\n\texit 1 ;# we could allow it, but there is no point.\nfi\n\n# Is topic ever merged to next?  If so you should not be rebasing it.\nonly_next_1=`git rev-list ^master \"^$topic\" ${publish} | sort`\nonly_next_2=`git rev-list ^master           ${publish} | sort`\nif test \"$only_next_1\" = \"$only_next_2\"\nthen\n\tnot_in_topic=`git rev-list \"^$topic\" master`\n\tif test -z \"$not_in_topic\"\n\tthen\n\t\techo >&2 \"$topic is already up to date with master\"\n\t\texit 1 ;# we could allow it, but there is no point.\n\telse\n\t\texit 0\n\tfi\nelse\n\tnot_in_next=`git rev-list --pretty=oneline ^${publish} \"$topic\"`\n\t/usr/bin/perl -e '\n\t\tmy $topic = $ARGV[0];\n\t\tmy $msg = \"* $topic has commits already merged to public branch:\\n\";\n\t\tmy (%not_in_next) = map {\n\t\t\t/^([0-9a-f]+) /;\n\t\t\t($1 => 1);\n\t\t} split(/\\n/, $ARGV[1]);\n\t\tfor my $elem (map {\n\t\t\t\t/^([0-9a-f]+) (.*)$/;\n\t\t\t\t[$1 => $2];\n\t\t\t} split(/\\n/, $ARGV[2])) {\n\t\t\tif (!exists $not_in_next{$elem->[0]}) {\n\t\t\t\tif ($msg) {\n\t\t\t\t\tprint STDERR $msg;\n\t\t\t\t\tundef $msg;\n\t\t\t\t}\n\t\t\t\tprint STDERR \" $elem->[1]\\n\";\n\t\t\t}\n\t\t}\n\t' \"$topic\" \"$not_in_next\" \"$not_in_master\"\n\texit 1\nfi\n\n<<\\DOC_END\n\nThis sample hook safeguards topic branches that have been\npublished from being rewound.\n\nThe workflow assumed here is:\n\n * Once a topic branch forks from \"master\", \"master\" is never\n   merged into it again (either directly or indirectly).\n\n * Once a topic branch is fully cooked and merged into \"master\",\n   it is deleted.  If you need to build on top of it to correct\n   earlier mistakes, a new topic branch is created by forking at\n   the tip of the \"master\".  This is not strictly necessary, but\n   it makes it easier to keep your history simple.\n\n * Whenever you need to test or publish your changes to topic\n   branches, merge them into \"next\" branch.\n\nThe script, being an example, hardcodes the publish branch name\nto be \"next\", but it is trivial to make it configurable via\n$GIT_DIR/config mechanism.\n\nWith this workflow, you would want to know:\n\n(1) ... if a topic branch has ever been merged to \"next\".  Young\n    topic branches can have stupid mistakes you would rather\n    clean up before publishing, and things that have not been\n    merged into other branches can be easily rebased without\n    affecting other people.  But once it is published, you would\n    not want to rewind it.\n\n(2) ... if a topic branch has been fully merged to \"master\".\n    Then you can delete it.  More importantly, you should not\n    build on top of it -- other people may already want to\n    change things related to the topic as patches against your\n    \"master\", so if you need further changes, it is better to\n    fork the topic (perhaps with the same name) afresh from the\n    tip of \"master\".\n\nLet's look at this example:\n\n\t\t   o---o---o---o---o---o---o---o---o---o \"next\"\n\t\t  /       /           /           /\n\t\t /   a---a---b A     /           /\n\t\t/   /               /           /\n\t       /   /   c---c---c---c B         /\n\t      /   /   /             \\         /\n\t     /   /   /   b---b C     \\       /\n\t    /   /   /   /             \\     /\n    ---o---o---o---o---o---o---o---o---o---o---o \"master\"\n\n\nA, B and C are topic branches.\n\n * A has one fix since it was merged up to \"next\".\n\n * B has finished.  It has been fully merged up to \"master\" and \"next\",\n   and is ready to be deleted.\n\n * C has not merged to \"next\" at all.\n\nWe would want to allow C to be rebased, refuse A, and encourage\nB to be deleted.\n\nTo compute (1):\n\n\tgit rev-list ^master ^topic next\n\tgit rev-list ^master        next\n\n\tif these match, topic has not merged in next at all.\n\nTo compute (2):\n\n\tgit rev-list master..topic\n\n\tif this is empty, it is fully merged to \"master\".\n\nDOC_END\n"
  },
  {
    "path": ".git/hooks/pre-receive.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to make use of push options.\n# The example simply echoes all push options that start with 'echoback='\n# and rejects all pushes when the \"reject\" push option is used.\n#\n# To enable this hook, rename this file to \"pre-receive\".\n\nif test -n \"$GIT_PUSH_OPTION_COUNT\"\nthen\n\ti=0\n\twhile test \"$i\" -lt \"$GIT_PUSH_OPTION_COUNT\"\n\tdo\n\t\teval \"value=\\$GIT_PUSH_OPTION_$i\"\n\t\tcase \"$value\" in\n\t\techoback=*)\n\t\t\techo \"echo from the pre-receive-hook: ${value#*=}\" >&2\n\t\t\t;;\n\t\treject)\n\t\t\texit 1\n\t\tesac\n\t\ti=$((i + 1))\n\tdone\nfi\n"
  },
  {
    "path": ".git/hooks/prepare-commit-msg.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to prepare the commit log message.\n# Called by \"git commit\" with the name of the file that has the\n# commit message, followed by the description of the commit\n# message's source.  The hook's purpose is to edit the commit\n# message file.  If the hook fails with a non-zero status,\n# the commit is aborted.\n#\n# To enable this hook, rename this file to \"prepare-commit-msg\".\n\n# This hook includes three examples. The first one removes the\n# \"# Please enter the commit message...\" help message.\n#\n# The second includes the output of \"git diff --name-status -r\"\n# into the message, just before the \"git status\" output.  It is\n# commented because it doesn't cope with --amend or with squashed\n# commits.\n#\n# The third example adds a Signed-off-by line to the message, that can\n# still be edited.  This is rarely a good idea.\n\nCOMMIT_MSG_FILE=$1\nCOMMIT_SOURCE=$2\nSHA1=$3\n\n/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' \"$COMMIT_MSG_FILE\"\n\n# case \"$COMMIT_SOURCE,$SHA1\" in\n#  ,|template,)\n#    /usr/bin/perl -i.bak -pe '\n#       print \"\\n\" . `git diff --cached --name-status -r`\n# \t if /^#/ && $first++ == 0' \"$COMMIT_MSG_FILE\" ;;\n#  *) ;;\n# esac\n\n# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\\(.*>\\).*$/Signed-off-by: \\1/p')\n# git interpret-trailers --in-place --trailer \"$SOB\" \"$COMMIT_MSG_FILE\"\n# if test -z \"$COMMIT_SOURCE\"\n# then\n#   /usr/bin/perl -i.bak -pe 'print \"\\n\" if !$first_line++' \"$COMMIT_MSG_FILE\"\n# fi\n"
  },
  {
    "path": ".git/hooks/push-to-checkout.sample",
    "content": "#!/bin/sh\n\n# An example hook script to update a checked-out tree on a git push.\n#\n# This hook is invoked by git-receive-pack(1) when it reacts to git\n# push and updates reference(s) in its repository, and when the push\n# tries to update the branch that is currently checked out and the\n# receive.denyCurrentBranch configuration variable is set to\n# updateInstead.\n#\n# By default, such a push is refused if the working tree and the index\n# of the remote repository has any difference from the currently\n# checked out commit; when both the working tree and the index match\n# the current commit, they are updated to match the newly pushed tip\n# of the branch. This hook is to be used to override the default\n# behaviour; however the code below reimplements the default behaviour\n# as a starting point for convenient modification.\n#\n# The hook receives the commit with which the tip of the current\n# branch is going to be updated:\ncommit=$1\n\n# It can exit with a non-zero status to refuse the push (when it does\n# so, it must not modify the index or the working tree).\ndie () {\n\techo >&2 \"$*\"\n\texit 1\n}\n\n# Or it can make any necessary changes to the working tree and to the\n# index to bring them to the desired state when the tip of the current\n# branch is updated to the new commit, and exit with a zero status.\n#\n# For example, the hook can simply run git read-tree -u -m HEAD \"$1\"\n# in order to emulate git fetch that is run in the reverse direction\n# with git push, as the two-tree form of git read-tree -u -m is\n# essentially the same as git switch or git checkout that switches\n# branches while keeping the local changes in the working tree that do\n# not interfere with the difference between the branches.\n\n# The below is a more-or-less exact translation to shell of the C code\n# for the default behaviour for git's push-to-checkout hook defined in\n# the push_to_deploy() function in builtin/receive-pack.c.\n#\n# Note that the hook will be executed from the repository directory,\n# not from the working tree, so if you want to perform operations on\n# the working tree, you will have to adapt your code accordingly, e.g.\n# by adding \"cd ..\" or using relative paths.\n\nif ! git update-index -q --ignore-submodules --refresh\nthen\n\tdie \"Up-to-date check failed\"\nfi\n\nif ! git diff-files --quiet --ignore-submodules --\nthen\n\tdie \"Working directory has unstaged changes\"\nfi\n\n# This is a rough translation of:\n#\n#   head_has_history() ? \"HEAD\" : EMPTY_TREE_SHA1_HEX\nif git cat-file -e HEAD 2>/dev/null\nthen\n\thead=HEAD\nelse\n\thead=$(git hash-object -t tree --stdin </dev/null)\nfi\n\nif ! git diff-index --quiet --cached --ignore-submodules $head --\nthen\n\tdie \"Working directory has staged changes\"\nfi\n\nif ! git read-tree -u -m \"$commit\"\nthen\n\tdie \"Could not update working tree to new HEAD\"\nfi\n"
  },
  {
    "path": ".git/hooks/sendemail-validate.sample",
    "content": "#!/bin/sh\n\n# An example hook script to validate a patch (and/or patch series) before\n# sending it via email.\n#\n# The hook should exit with non-zero status after issuing an appropriate\n# message if it wants to prevent the email(s) from being sent.\n#\n# To enable this hook, rename this file to \"sendemail-validate\".\n#\n# By default, it will only check that the patch(es) can be applied on top of\n# the default upstream branch without conflicts in a secondary worktree. After\n# validation (successful or not) of the last patch of a series, the worktree\n# will be deleted.\n#\n# The following config variables can be set to change the default remote and\n# remote ref that are used to apply the patches against:\n#\n#   sendemail.validateRemote (default: origin)\n#   sendemail.validateRemoteRef (default: HEAD)\n#\n# Replace the TODO placeholders with appropriate checks according to your\n# needs.\n\nvalidate_cover_letter () {\n\tfile=\"$1\"\n\t# TODO: Replace with appropriate checks (e.g. spell checking).\n\ttrue\n}\n\nvalidate_patch () {\n\tfile=\"$1\"\n\t# Ensure that the patch applies without conflicts.\n\tgit am -3 \"$file\" || return\n\t# TODO: Replace with appropriate checks for this patch\n\t# (e.g. checkpatch.pl).\n\ttrue\n}\n\nvalidate_series () {\n\t# TODO: Replace with appropriate checks for the whole series\n\t# (e.g. quick build, coding style checks, etc.).\n\ttrue\n}\n\n# main -------------------------------------------------------------------------\n\nif test \"$GIT_SENDEMAIL_FILE_COUNTER\" = 1\nthen\n\tremote=$(git config --default origin --get sendemail.validateRemote) &&\n\tref=$(git config --default HEAD --get sendemail.validateRemoteRef) &&\n\tworktree=$(mktemp --tmpdir -d sendemail-validate.XXXXXXX) &&\n\tgit worktree add -fd --checkout \"$worktree\" \"refs/remotes/$remote/$ref\" &&\n\tgit config --replace-all sendemail.validateWorktree \"$worktree\"\nelse\n\tworktree=$(git config --get sendemail.validateWorktree)\nfi || {\n\techo \"sendemail-validate: error: failed to prepare worktree\" >&2\n\texit 1\n}\n\nunset GIT_DIR GIT_WORK_TREE\ncd \"$worktree\" &&\n\nif grep -q \"^diff --git \" \"$1\"\nthen\n\tvalidate_patch \"$1\"\nelse\n\tvalidate_cover_letter \"$1\"\nfi &&\n\nif test \"$GIT_SENDEMAIL_FILE_COUNTER\" = \"$GIT_SENDEMAIL_FILE_TOTAL\"\nthen\n\tgit config --unset-all sendemail.validateWorktree &&\n\ttrap 'git worktree remove -ff \"$worktree\"' EXIT &&\n\tvalidate_series\nfi\n"
  },
  {
    "path": ".git/hooks/update.sample",
    "content": "#!/bin/sh\n#\n# An example hook script to block unannotated tags from entering.\n# Called by \"git receive-pack\" with arguments: refname sha1-old sha1-new\n#\n# To enable this hook, rename this file to \"update\".\n#\n# Config\n# ------\n# hooks.allowunannotated\n#   This boolean sets whether unannotated tags will be allowed into the\n#   repository.  By default they won't be.\n# hooks.allowdeletetag\n#   This boolean sets whether deleting tags will be allowed in the\n#   repository.  By default they won't be.\n# hooks.allowmodifytag\n#   This boolean sets whether a tag may be modified after creation. By default\n#   it won't be.\n# hooks.allowdeletebranch\n#   This boolean sets whether deleting branches will be allowed in the\n#   repository.  By default they won't be.\n# hooks.denycreatebranch\n#   This boolean sets whether remotely creating branches will be denied\n#   in the repository.  By default this is allowed.\n#\n\n# --- Command line\nrefname=\"$1\"\noldrev=\"$2\"\nnewrev=\"$3\"\n\n# --- Safety check\nif [ -z \"$GIT_DIR\" ]; then\n\techo \"Don't run this script from the command line.\" >&2\n\techo \" (if you want, you could supply GIT_DIR then run\" >&2\n\techo \"  $0 <ref> <oldrev> <newrev>)\" >&2\n\texit 1\nfi\n\nif [ -z \"$refname\" -o -z \"$oldrev\" -o -z \"$newrev\" ]; then\n\techo \"usage: $0 <ref> <oldrev> <newrev>\" >&2\n\texit 1\nfi\n\n# --- Config\nallowunannotated=$(git config --type=bool hooks.allowunannotated)\nallowdeletebranch=$(git config --type=bool hooks.allowdeletebranch)\ndenycreatebranch=$(git config --type=bool hooks.denycreatebranch)\nallowdeletetag=$(git config --type=bool hooks.allowdeletetag)\nallowmodifytag=$(git config --type=bool hooks.allowmodifytag)\n\n# check for no description\nprojectdesc=$(sed -e '1q' \"$GIT_DIR/description\")\ncase \"$projectdesc\" in\n\"Unnamed repository\"* | \"\")\n\techo \"*** Project description file hasn't been set\" >&2\n\texit 1\n\t;;\nesac\n\n# --- Check types\n# if $newrev is 0000...0000, it's a commit to delete a ref.\nzero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')\nif [ \"$newrev\" = \"$zero\" ]; then\n\tnewrev_type=delete\nelse\n\tnewrev_type=$(git cat-file -t $newrev)\nfi\n\ncase \"$refname\",\"$newrev_type\" in\n\trefs/tags/*,commit)\n\t\t# un-annotated tag\n\t\tshort_refname=${refname##refs/tags/}\n\t\tif [ \"$allowunannotated\" != \"true\" ]; then\n\t\t\techo \"*** The un-annotated tag, $short_refname, is not allowed in this repository\" >&2\n\t\t\techo \"*** Use 'git tag [ -a | -s ]' for tags you want to propagate.\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\trefs/tags/*,delete)\n\t\t# delete tag\n\t\tif [ \"$allowdeletetag\" != \"true\" ]; then\n\t\t\techo \"*** Deleting a tag is not allowed in this repository\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\trefs/tags/*,tag)\n\t\t# annotated tag\n\t\tif [ \"$allowmodifytag\" != \"true\" ] && git rev-parse $refname > /dev/null 2>&1\n\t\tthen\n\t\t\techo \"*** Tag '$refname' already exists.\" >&2\n\t\t\techo \"*** Modifying a tag is not allowed in this repository.\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\trefs/heads/*,commit)\n\t\t# branch\n\t\tif [ \"$oldrev\" = \"$zero\" -a \"$denycreatebranch\" = \"true\" ]; then\n\t\t\techo \"*** Creating a branch is not allowed in this repository\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\trefs/heads/*,delete)\n\t\t# delete branch\n\t\tif [ \"$allowdeletebranch\" != \"true\" ]; then\n\t\t\techo \"*** Deleting a branch is not allowed in this repository\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\trefs/remotes/*,commit)\n\t\t# tracking branch\n\t\t;;\n\trefs/remotes/*,delete)\n\t\t# delete tracking branch\n\t\tif [ \"$allowdeletebranch\" != \"true\" ]; then\n\t\t\techo \"*** Deleting a tracking branch is not allowed in this repository\" >&2\n\t\t\texit 1\n\t\tfi\n\t\t;;\n\t*)\n\t\t# Anything else (is there anything else?)\n\t\techo \"*** Update hook: unknown type of update to ref $refname of type $newrev_type\" >&2\n\t\texit 1\n\t\t;;\nesac\n\n# --- Finished\nexit 0\n"
  },
  {
    "path": ".git/info/exclude",
    "content": "# git ls-files --others --exclude-from=.git/info/exclude\n# Lines that start with '#' are comments.\n# For a project mostly in C, the following would be a good set of\n# exclude patterns (uncomment them if you want to use them):\n# *.[oa]\n# *~\n"
  },
  {
    "path": ".git/logs/HEAD",
    "content": "0000000000000000000000000000000000000000 cdfc0bba9081099a0a6a62fcbbe7f364ba38231b appuser <appuser@3c7b4ea3b59f.(none)> 1773985664 +0000\tclone: from https://github.com/vlang/v\n"
  },
  {
    "path": ".git/logs/refs/heads/master",
    "content": "0000000000000000000000000000000000000000 cdfc0bba9081099a0a6a62fcbbe7f364ba38231b appuser <appuser@3c7b4ea3b59f.(none)> 1773985664 +0000\tclone: from https://github.com/vlang/v\n"
  },
  {
    "path": ".git/logs/refs/remotes/origin/HEAD",
    "content": "0000000000000000000000000000000000000000 cdfc0bba9081099a0a6a62fcbbe7f364ba38231b appuser <appuser@3c7b4ea3b59f.(none)> 1773985664 +0000\tclone: from https://github.com/vlang/v\n"
  },
  {
    "path": ".git/objects/pack/pack-4c5eb4b01e8d20d1b77462674426e18b34b3eb8d.promisor",
    "content": "cdfc0bba9081099a0a6a62fcbbe7f364ba38231b refs/heads/master\n"
  },
  {
    "path": ".git/objects/pack/pack-a119d32135c98d4d3e4374ad1ecd525e9b537c4c.promisor",
    "content": ""
  },
  {
    "path": ".git/packed-refs",
    "content": "# pack-refs with: peeled fully-peeled sorted \ncdfc0bba9081099a0a6a62fcbbe7f364ba38231b refs/remotes/origin/master\n"
  },
  {
    "path": ".git/refs/heads/master",
    "content": "cdfc0bba9081099a0a6a62fcbbe7f364ba38231b\n"
  },
  {
    "path": ".git/refs/remotes/origin/HEAD",
    "content": "ref: refs/remotes/origin/master\n"
  },
  {
    "path": ".git/shallow",
    "content": "cdfc0bba9081099a0a6a62fcbbe7f364ba38231b\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto eol=lf\n*.bat eol=crlf\n\n*.v linguist-language=V\n*.vv linguist-language=V\n*.vsh linguist-language=V\nv.mod linguist-language=V\n.vdocignore linguist-language=ignore\n\nDockerfile.* linguist-language=Dockerfile\n"
  },
  {
    "path": ".github/.prettierrc",
    "content": "{\n  \"singleQuote\": true\n}\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\nopen_collective: vlang\npatreon: vlang\ngithub: [medvednikov]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: true\ncontact_links:\n  - name: 💬 General Questions and Answers about V\n    url: https://github.com/vlang/v/discussions/categories/questions-and-answers\n    about: You can ask and answer questions about V in the discussions forum.\n\n  - name: 💬 Discord Server\n    url: https://discord.gg/vlang\n    about: You can join our Discord server for real time discussion and support\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/documentation.yml",
    "content": "name: 📕 Documentation Issue\ndescription: Report an issue in the Reference documentation or Developer Guide\nlabels: ['Unit: Documentation']\nbody:\n  - type: textarea\n    id: description\n    attributes:\n      label: Describe the issue\n      description: A clear and concise description of the issue.\n    validations:\n      required: true\n\n  - type: textarea\n    id: links\n    attributes:\n      label: Links\n      description: Include links to affected documentation page(s).\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.yml",
    "content": "name: 🚀 Feature Request\ndescription: Suggest an idea for this project\nlabels: [Feature Request]\nbody:\n  - type: textarea\n    id: description\n    attributes:\n      label: Describe the feature\n      description: A clear and concise description of the feature you are proposing.\n    validations:\n      required: true\n\n  - type: textarea\n    id: use-case\n    attributes:\n      label: Use Case\n      description: |\n        Why do you need this feature? For example: \"I'm always frustrated when...\"\n    validations:\n      required: true\n\n  - type: textarea\n    id: solution\n    attributes:\n      label: Proposed Solution\n      description: Suggest how to implement the addition or change. Please include prototype/workaround/sketch/reference implementation.\n    validations:\n      required: false\n\n  - type: textarea\n    id: other\n    attributes:\n      label: Other Information\n      description: Any alternative solutions or features you considered, a more detailed explanation, stack traces, related issues, links for context, etc.\n    validations:\n      required: false\n\n  - type: checkboxes\n    id: ack\n    attributes:\n      label: Acknowledgements\n      options:\n        - label: I may be able to implement this feature request\n          required: false\n\n        - label: This feature might incur a breaking change\n          required: false\n\n  - type: input\n    id: version\n    attributes:\n      label: Version used\n      description: Please provide the version of the repository or tool you are using.\n    validations:\n      required: true\n\n  - type: textarea\n    id: environment\n    attributes:\n      label: Environment details (OS name and version, etc.)\n      description: You can use `v doctor` to fill up this section.\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE",
    "content": "\n<!--\n\nPlease title your PR as follows: `module: description` (e.g. `time: fix date format`).\nAlways start with the thing you are fixing, then describe the fix.\nDon't use past tense (e.g. \"fixed foo bar\").\n\nExplain what your PR does and why.\n\nIf you are adding a new function, please document it and add tests:\n\n```\n// foo does foo and bar\nfn foo() {\n\n// file_test.v\nfn test_foo() {\n    assert foo() == ...\n    ...\n}\n```\n\nIf you are fixing a bug, please add a test that covers it.\n\nBefore submitting a PR, please run `v test-all` .\nSee also `TESTS.md`.\n\nI try to process PRs as soon as possible. They should be handled within 24 hours.\n\nApplying labels to PRs is not needed.\n\nThanks a lot for your contribution!\n\n-->\n"
  },
  {
    "path": ".github/actions/cache-apt-packages-action/action.yml",
    "content": "name: 'Cache Apt Packages'\ndescription: 'Cache all commonly used apt packages to speed up CI jobs'\n\n# imagemagick              : convert, mogrify\n# xvfb                     : xvfb\n# openimageio-tools        : idiff\n# libxcursor-dev libxi-dev : V gfx deps\n# libgl1-mesa-dri          : For headless rendering on the CI / software DRI driver (LIBGL_ALWAYS_SOFTWARE=true)\n# freeglut3-dev            : Fixes graphic apps compilation with tcc\n# sdl2                     : needed for Puzzle Vibes & Chocolate Doom\n# libsodium-dev            : needed for Gitly and C2V\n\nruns:\n  using: 'composite'\n  steps:\n    - uses: awalsh128/cache-apt-pkgs-action@v1.5.3\n      with:\n        version: 1.0\n        packages: expect binutils postgresql sqlite3 clang valgrind \\\n          imagemagick openimageio-tools xvfb xsel xclip \\\n          libsodium-dev libpq-dev libssl-dev libsqlite3-dev \\\n          libfreetype6-dev libxi-dev libxcursor-dev \\\n          libgl-dev libxrandr-dev libasound2-dev \\\n          libx11-dev freeglut3-dev mesa-common-dev libgl1-mesa-dev libgl1-mesa-dri \\\n          libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev libsdl2-net-dev \\\n          libpng-dev libsamplerate0-dev \\\n          xfonts-75dpi xfonts-base\n    - name: Install common packages\n      run: echo \"done installing packages\"\n      shell: bash\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: 'github-actions'\n    directory: '/'\n    schedule:\n      interval: 'daily'\n"
  },
  {
    "path": ".github/problem-matchers/register_all.vsh",
    "content": "// The task of this program, is to register all available .json files\n// in this folder with Github Actions, so that it can make annotations\n// for all found notices/warnings/errors produced by the V compiler\n// while running the CI jobs.\n// Those annotations provide a way to get a quick overview for failures,\n// without having to scroll into the detailed logs produced by each job.\n\nconst github_job = getenv('GITHUB_JOB')\n\nif github_job == '' {\n\texit(0)\n}\n\ndump(github_job)\nchdir(@VEXEROOT)!\nfor f in walk_ext('.github/problem-matchers/', '.json').sorted() {\n\tprintln('::add-matcher::${real_path(f)}')\n\tprintln('registered matcher: `${f}`')\n}\n"
  },
  {
    "path": ".github/problem-matchers/v.json",
    "content": "{\n    \"__comment\": \"Based on https://github.com/python/cpython/blob/main/.github/problem-matchers/gcc.json\",\n    \"problemMatcher\": [\n        {\n            \"owner\": \"v-problem-matcher\",\n            \"pattern\": [\n                {\n                    \"regexp\": \"^(.*):(\\\\d+):(\\\\d+):\\\\s+(?:fatal\\\\s+)?(warning|error|notice):\\\\s+(.*)$\",\n                    \"file\": 1,\n                    \"line\": 2,\n                    \"column\": 3,\n                    \"severity\": 4,\n                    \"message\": 5\n                }\n            ]\n        }\n    ]\n}\n"
  },
  {
    "path": ".github/workflows/Dockerfile.ci_alpine_local",
    "content": "#######################################################################################\n## The goal of this file, is to provide an easy and reproducible way to check *locally*\n## the CI job `docker-alpine-musl-gcc`\n## Building the docker image:\n##    docker build -t ci_alpine_local - < .github/workflows/Dockerfile.ci_alpine_local\n## Running the docker image, after building it:\n##    docker run --rm -it -v .:/opt/vlang -w /opt/vlang ci_alpine_local\n## Once it is running, inside the container you can:\n##    make && v -e 'println(2+2)'\n## ... then do whatever you need to reproduce the CI test failure.\n## Note: after you are finished, and exit the container, run `make` again, otherwise \n## you will be using V (and potentially V tools) that were compiled with musl.\n#######################################################################################\nFROM thevlang/vlang:alpine-build\n\nLABEL maintainer=\"spytheman <spytheman@bulsynt.org>\"\n\nWORKDIR /opt/vlang\n\nENV PATH /opt/vlang:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n\n## install development packages\nRUN apk --no-cache add \\\n  musl-dev libc-dev libc6-compat gcompat \\\n  libunwind-dev libunwind-static \\\n  gc gc-dev \\\n  binutils diffutils elfutils \\\n  strace gdb \\\n  pcre bash fzf fzf-vim tmux less file colordiff \\\n  vim vim-editorconfig \\\n  nano nano-syntax \\\n  micro\n\nRUN git config --global --add safe.directory /opt/vlang &&\\\n    git config --global --add safe.directory /opt/vlang/vc &&\\\n    git config --global --add safe.directory /opt/vlang/thirdparty/tcc &&\\\n    find /usr/share/nano/ -iname \"*.nanorc\" -exec echo include {} \\; >> ~/.nanorc &&\\\n    micro -plugin install detectindent &&\\\n    micro -plugin install editorconfig &&\\\n    micro -plugin install monokai-dark &&\\\n    micro -plugin install quickfix &&\\\n    micro -plugin install runit &&\\\n    micro -plugin install cheat &&\\\n    micro -plugin install jump &&\\\n    true\n\n## setup runtime environment for v and bash:\nENV VTMP     /tmp/v\nENV VMODULES /tmp/vmodules\nENV VFLAGS  \"-d dynamic_boehm\"\n\nCMD [\"bash\"]\n"
  },
  {
    "path": ".github/workflows/add-voting-info.yml",
    "content": "name: Add voting info to new issue\n\non:\n  issues:\n    types:\n      - opened\n\njobs:\n  add-voting-info:\n    runs-on: ubuntu-latest\n    permissions:\n      issues: write\n    steps:\n      - name: Append voting info to issue body\n        uses: julien-deramond/update-issue-body@v1\n        with:\n          issue-number: ${{ github.event.issue.number }}\n          body: |\n            > [!NOTE]\n            > You can use the 👍 reaction to increase the issue's priority for developers.\n            >\n            > Please note that only the 👍 reaction to the issue itself counts as a vote.\n            > Other reactions and those to comments will not be taken into account.\n          edit-mode: append\n          append-separator: newline\n"
  },
  {
    "path": ".github/workflows/alpine.build.sh",
    "content": "#!/bin/sh -l\n\nset -e\n\npwd\n\nuname -a\n\nmake -j4\n\n./v version\n\ndu -s .\n\necho \"DONE\"\n"
  },
  {
    "path": ".github/workflows/alpine.test.sh",
    "content": "#!/bin/sh -l\n\nset -e\n\npwd\n\nuname -a\n\ndu -s .\n\nls -lat \n\n##./v -silent test-all\n\n## try running the known failing tests first to get faster feedback\n./v vlib/builtin/string_test.v\n./v vlib/strings/builder_test.v\n\n./v -silent test-cleancode\n\n./v -silent test-self\n\n./v build-vbinaries\n\necho \"DONE\"\n"
  },
  {
    "path": ".github/workflows/android_cross_compile.vsh",
    "content": "#!/usr/bin/env -S v\n\nmodule main\n\nimport os\nimport vab.vxt\nimport vab.android.ndk\n\nfn main() {\n\tassert ndk.found()\n\tassert vxt.found()\n\n\twork_dir := os.join_path(os.vtmp_dir(), 'android_cross_compile_test')\n\tos.rm(work_dir) or {}\n\tos.mkdir_all(work_dir) or { panic(err) }\n\tvexe := vxt.vexe()\n\n\texamples_dir := os.join_path(vxt.home(), 'examples')\n\tv_example := os.join_path(examples_dir, 'toml.v')\n\n\tndk_version := ndk.default_version()\n\n\tsysroot_path := ndk.sysroot_path(ndk_version) or { panic(err) }\n\tinclude_path := os.join_path(sysroot_path, 'usr', 'include')\n\tandroid_include_path := os.join_path(include_path, 'android')\n\n\t//'-I\"${include_path}\"'\n\tcflags := ['-I\"${android_include_path}\"', '-Wno-unused-value', '-Wno-implicit-function-declaration',\n\t\t'-Wno-int-conversion']\n\tfor arch in ndk.supported_archs {\n\t\tfor level in ['min', 'max'] {\n\t\t\tcompiler_api := match level {\n\t\t\t\t'min' {\n\t\t\t\t\tndk.compiler_min_api(.c, ndk_version, arch) or { panic(err) }\n\t\t\t\t}\n\t\t\t\t'max' {\n\t\t\t\t\tndk.compiler_max_api(.c, ndk_version, arch) or { panic(err) }\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tpanic('invalid min/max level')\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tos.setenv('VCROSS_COMPILER_NAME', compiler_api, true)\n\t\t\tc_file := os.join_path(work_dir, arch + '-' + level + '.c')\n\t\t\to_file := os.join_path(work_dir, arch + '-' + level + '.o')\n\n\t\t\t// x.v -> x.c\n\t\t\tv_compile_cmd := '${vexe} -o ${c_file} -os android -gc none ${v_example}'\n\t\t\tvres := os.execute(v_compile_cmd)\n\t\t\tif vres.exit_code != 0 {\n\t\t\t\tpanic('\"${v_compile_cmd}\" failed: ${vres.output}')\n\t\t\t}\n\t\t\tassert os.exists(c_file)\n\n\t\t\t// x.c -> x.o\n\t\t\tcompile_cmd := '${compiler_api} ${cflags.join(' ')} -c ${c_file} -o ${o_file}'\n\t\t\tcres := os.execute(compile_cmd)\n\t\t\tif cres.exit_code != 0 {\n\t\t\t\tpanic('\"${compile_cmd}\" failed: ${cres.output}')\n\t\t\t}\n\t\t\tassert os.exists(o_file)\n\t\t\tcompiler_exe_name := os.file_name(compiler_api)\n\t\t\tprintln('Compiled examples/toml.v successfully for (${level}) ${arch} ${compiler_exe_name}')\n\t\t}\n\t}\n}\n"
  },
  {
    "path": ".github/workflows/benchmark_footprint_json_decode.yml",
    "content": "name: json decoder benchmark CI\n\non:\n  push:\n    paths:\n      - 'vlib/x/json2/**' # Trigger on changes in this folder\n\njobs:\n  json-encode-benchmark:\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v6\n\n      - name: Build V\n        run: make -j4 && ./v symlink\n\n      - name: Run V benchmark and save output\n        run: (echo '```txt'; v -prod crun vlib/x/json2/tests/bench.v; echo '```') > vlib/x/json2/tests/bench_out.md\n\n      - name: Upload result file\n        uses: actions/upload-artifact@v7\n        with:\n          name: program-output\n          path: vlib/x/json2/tests/bench_out.md\n"
  },
  {
    "path": ".github/workflows/benchmark_footprint_json_encode.yml",
    "content": "name: json encoder benchmark CI\n\non:\n  push:\n    paths:\n      - 'vlib/x/json2/**' # Trigger on changes in this folder\n      - '!vlib/x/json2/strict/**' # Ignore\n      - '!vlib/x/json2/tests/**' # Ignore\n\njobs:\n  json-encode-benchmark:\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v6\n\n      - name: Build V\n        run: make -j4 && ./v symlink\n\n      - name: Run V benchmark and save output\n        run: (echo '```sh'; v -prod crun vlib/v/tests/bench/bench_json_vs_json2.v; echo '```') > vlib/v/tests/bench/bench_json_vs_json2_out.md\n\n      - name: Upload result file\n        uses: actions/upload-artifact@v7\n        with:\n          name: program-output\n          path: vlib/v/tests/bench/bench_json_vs_json2_out.md\n"
  },
  {
    "path": ".github/workflows/bootstrapping_ci.yml",
    "content": "name: Bootstrapping CI\n\non:\n  workflow_dispatch:\n  push:\n    paths-ignore:\n      - '**.yml'\n      - '**.md'\n      - '**.vv'\n      - '**.out'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n      - '!cmd/tools/vup.v'\n      - '!**/bootstrapping_ci.yml'\n  pull_request:\n    paths-ignore:\n      - '**.yml'\n      - '**.md'\n      - '**.vv'\n      - '**.out'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n      - '!cmd/tools/vup.v'\n      - '!**/bootstrapping_ci.yml'\n\nconcurrency:\n  group: bootstrapping-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  bootstrap-v:\n    strategy:\n      matrix:\n        os: [ubuntu-latest, macos-14]\n      fail-fast: false\n    runs-on: ${{ matrix.os }}\n    timeout-minutes: 20\n    env:\n      VFLAGS: -no-parallel\n      B_LFLAGS: -lm -lpthread\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n      - name: Build V\n        run: make -j4\n      - name: Test bootstrapping (v.c can be compiled and run with -os cross)\n        run: |\n          ls -la v vc/v.c\n          ./v -os cross -o vc/v.c cmd/v\n          # shellcheck disable=SC2086\n          cc -o v_from_vc vc/v.c $B_LFLAGS\n          ls -lart v_from_vc\n          ./v_from_vc version\n          ./v_from_vc run examples/hello_world.v\n          ./v_from_vc -o v_from_vc_produced_native_v cmd/v\n          ./v_from_vc_produced_native_v run examples/hello_world.v\n          ### the next make invocation will simulate building V from scratch\n          make local=1\n          ls -la v vc/v.c v_from_vc v_from_vc_produced_native_v\n          ./v_from_vc_produced_native_v -os cross -o vc/v.c cmd/v\n          ### do it a second time, just in case:\n          # shellcheck disable=SC2086\n          clang -o v_from_vc2 vc/v.c $B_LFLAGS\n          ls -lart v_from_vc2\n          ./v_from_vc2 version\n          ./v_from_vc2 run examples/hello_world.v\n          ./v_from_vc2 -o v_from_vc_produced_native_v2 cmd/v\n          ./v_from_vc_produced_native_v2 run examples/hello_world.v\n          make local=1\n          ls -la v vc/v.c\n          ls -la v_from_vc v_from_vc_produced_native_v\n          ls -la v_from_vc2 v_from_vc_produced_native_v2\n      - name: Ensure V master is available\n        if: github.ref_name != 'master'\n        run: git branch master remotes/origin/master\n      - name: Test `v up`\n        run: |\n          # Derive a commit sha from an older successful fast workflow on master that was able to build V.\n          # The workflow used below is `Path Testing CI` (18477644).\n          recent_good_commit=$(curl -L \\\n            -H \"Accept: application/vnd.github+json\" \\\n            -H \"Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}\" \\\n            -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n            \"https://api.github.com/repos/vlang/v/actions/workflows/18477644/runs?branch=master&status=success&event=push&per_page=5&page=2\" \\\n            | jq -r '.workflow_runs[4].head_sha')\n          echo \"recent_good_commit=$recent_good_commit\"\n          # Build oldv at recent_good_commit.\n          ./v run cmd/tools/oldv.v -v \"$recent_good_commit\"\n          cd \"$HOME/.cache/oldv/v_at_$recent_good_commit\"\n          # Test updating\n          ./v version && ./v -v up && ./v version\n          ./v -o v2 cmd/v && ./v2 -o v3 cmd/v\n"
  },
  {
    "path": ".github/workflows/build_on_ubuntu_25_ci.yml",
    "content": "name: CI Ubuntu 25 GCC 14.2\n\non:\n  workflow_dispatch:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/build_on_ubuntu_25_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/build_on_ubuntu_25_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\njobs:\n  ubuntu-25-gcc-14-2-build:\n    runs-on: ubuntu-latest\n    timeout-minutes: 30\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build and test in Ubuntu 25.04 with GCC 14.2\n        run: |\n          set -o xtrace\n          echo \"$PWD\"\n          whoami\n          touch outside_docker.txt\n          git log -n4\n          echo \"running docker ...\"\n          docker run --rm \\\n            --mount type=bind,source=/home/runner/work/v/v,destination=/src \\\n            -w /src ubuntu:25.04 bash -c '\n            set -o xtrace\n            echo \"running inside docker\"\n            whoami\n            cp -r /src ~/vproject; cd ~/vproject\n            touch inside_docker.txt\n            ls -la\n            git log -n4\n            apt update -y -qq\n            apt install -y -qq git build-essential make\n            git config --global --add safe.directory /src/vc\n            git config --global --add safe.directory /src/thirdparty/tcc\n            make\n            ./v symlink\n            v run examples/hello_world.v\n            v run examples/primes.v\n          '\n"
  },
  {
    "path": ".github/workflows/build_vinix_locally.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nV=$PWD/v\n\nif [[ -x \"$V\" ]]\nthen\n\techo \"The v executable exists.\"\nelse\n\techo \"This script should be run from the top level folder of a V repository\"\n\techo \"i.e. the folder where your V executable is.\"\n\texit 1\nfi\n\nBUILD=$PWD/vinix_build\n\necho \"Creating $BUILD folder...\"\nrm -rf $BUILD\nmkdir -p $BUILD\n\ncd $BUILD\necho \"Clone current Vinix\"\n./v retry -- git clone --depth=1 https://github.com/vlang/vinix.git\n\ncd $BUILD\necho \"Clone current mlibc\"\n./v retry -- git clone --depth=1 https://github.com/managarm/mlibc.git\n\ncd $BUILD\necho \"Patch mlibc for Vinix\"\ncd mlibc\npatch -p3 < ../vinix/patches/mlibc/mlibc.patch\n\ncd $BUILD\necho \"Install mlibc headers\"\nmkdir mlibc-build\ncd mlibc-build\nmeson --cross-file ../vinix/cross_file.txt --prefix=/ -Dheaders_only=true ../mlibc\nninja\nmkdir ../mlibc-headers\nDESTDIR=`realpath ../mlibc-headers` ninja install\n\ncd $BUILD\necho \"Attempt to build the Vinix kernel (debug)\"\ncd vinix/kernel\nmake PROD=false CFLAGS=\"-D__vinix__ -O2 -g -pipe -I../../mlibc-headers/include\"\nmake clean\n\ncd $BUILD\necho \"Attempt to build the Vinix kernel (prod)\"\ncd vinix/kernel\nmake PROD=true  CFLAGS=\"-D__vinix__ -O2 -g -pipe -I../../mlibc-headers/include\"\nmake clean\n\nrm -rf $BUILD\n"
  },
  {
    "path": ".github/workflows/c2v_ci.yml",
    "content": "name: C2V apps\n\non:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/c2v_ci.yml'\n      - 'doc/**'\n      - 'examples/**'\n      - 'tutorials/**'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/c2v_ci.yml'\n      - 'doc/**'\n      - 'examples/**'\n      - 'tutorials/**'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\nconcurrency:\n  group: c2v-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build-doom:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 30\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make && ./v symlink\n\n      - name: Set 8.8.8.8 as dns server\n        run: |\n          sudo sed -i 's/#DNS=/DNS=8.8.8.8 8.8.4.4/g' /etc/systemd/resolved.conf\n          sudo systemctl daemon-reload\n          sudo systemctl restart systemd-networkd\n          sudo systemctl restart systemd-resolved\n          dig distro.ibiblio.org\n\n      - name: Install C2V\n        run: |\n          v retry -- v install --git https://github.com/vlang/c2v\n          v -g ~/.vmodules/c2v/ || true\n      - name: Install dependencies\n        run: |\n          if [ \"${{ runner.os }}\" == \"Linux\" ]; then\n            .github/workflows/disable_azure_mirror.sh\n            v retry -- sudo apt update -y -qq\n            v retry -- sudo apt install libsdl2-dev libsdl2-mixer-dev libsdl2-net-dev libpng-dev libsamplerate0-dev\n          else\n            v retry -- brew install sdl2 sdl2_mixer sdl2_net libpng libsamplerate\n          fi\n      - name: Build original Chocolate Doom\n        run: |\n          v retry -- git clone --quiet --depth 1 https://github.com/vlang/doom ~/code/doom\n          cd ~/code/doom/chocolate-doom\n          cmake -DCMAKE_BUILD_TYPE=Debug .\n          make chocolate-doom\n      - name: Translate the whole game in project/folder mode and compile it\n        run: |\n          touch ~/DOOM1.WAD\n          WAD_FILE=~/DOOM1.WAD ~/code/doom/build_whole_project.sh\n\n  test-regression:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    env:\n      VFLAGS: -cc tcc\n      DISPLAY: :99\n      LIBGL_ALWAYS_SOFTWARE: true\n      VTMP: /tmp\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make && ./v symlink\n\n      - name: Set 8.8.8.8 as dns server\n        run: |\n          sudo sed -i 's/#DNS=/DNS=8.8.8.8 8.8.4.4/g' /etc/systemd/resolved.conf\n          sudo systemctl daemon-reload\n          sudo systemctl restart systemd-networkd\n          sudo systemctl restart systemd-resolved\n          dig distro.ibiblio.org\n\n      - name: Install C2V\n        run: |\n          v retry -- v install --git https://github.com/vlang/c2v\n          v -g ~/.vmodules/c2v/ || true\n      - name: Install dependencies\n        run: |\n          .github/workflows/disable_azure_mirror.sh\t\t  \n          v retry -- sudo apt update -y -qq\n          v retry -- sudo apt install libsdl2-dev libsdl2-mixer-dev libsdl2-net-dev libpng-dev libsamplerate0-dev\n          # c2v / DOOM dependencies\n          # vgret dependencies\n          # imagemagick              : convert, mogrify, import\n          # xvfb                     : For starting X11 Virtual FrameBuffers\n          # openimageio-tools        : idiff\n          # libgl1-mesa-dri          : For headless rendering / software DRI driver (LIBGL_ALWAYS_SOFTWARE=true)\n          # freeglut3-dev            : Fixes graphic apps compilation with tcc\n          v retry -- sudo apt install imagemagick openimageio-tools freeglut3-dev libgl1-mesa-dri xvfb xsel xclip\n      - name: Setup test tools\n        run: |\n          # Fetch the free ~4MB DOOM1.WAD from the link at https://doomwiki.org/wiki/DOOM1.WAD\n          v retry -- v download https://distro.ibiblio.org/slitaz/sources/packages/d/doom1.wad\n          mv doom1.wad ~/doom1.wad\n          # Get imgur upload script\n          v retry -- v download https://raw.githubusercontent.com/tremby/imgur.sh/c98345d/imgur.sh\n          chmod +x ./imgur.sh\n          # Get regression images to test against\n          v retry -- git clone https://github.com/Larpon/doom-regression-images\n      - name: Build original Chocolate Doom\n        run: |\n          v retry -- git clone --quiet --depth 1 https://github.com/vlang/doom ~/code/doom\n          cd ~/code/doom/chocolate-doom\n          cmake -DCMAKE_BUILD_TYPE=Debug .\n          make chocolate-doom\n      - name: Translate the whole game in project/folder mode\n        run: WAD_FILE=~/doom1.wad ~/code/doom/build_whole_project.sh\n      - name: Sample and compare with vgret\n        id: compare\n        continue-on-error: true\n        run: |\n          Xvfb \"$DISPLAY\" -screen 0 800x600x24 -fbdir /var/tmp/ &\n          sleep 2; while [ ! -f /var/tmp/Xvfb_screen0 ]; do sleep 0.5; done # give xvfb time to start, even on slow CI runs\n          sleep 5; v gret -r ~/code/doom -t ./doom-regression-images/vgret.doom.toml -v ./doom-sample_images ./doom-regression-images\n      - name: Upload regression to imgur\n        if: steps.compare.outcome != 'success'\n        run: |\n          ./imgur.sh /tmp/fail.png\n          ./imgur.sh /tmp/diff.png\n          exit 1\n"
  },
  {
    "path": ".github/workflows/compare_pr_to_master.v",
    "content": "import os\nimport time\n\nconst compare_prod = '-prod' in os.args\n\nconst cleanup_tmp = '-no-cleanup' !in os.args\n\nconst fetch_remote = '-no-fetch' !in os.args\n\nfn gbranch() string {\n\treturn os.execute(r'git branch --list|grep ^\\*').output.trim_left('* ').trim_space()\n}\n\nfn gcommit() string {\n\treturn os.execute(r'git rev-parse --short=7 HEAD').output.trim_left('* ').trim_space()\n}\n\nfn r(cmd string) {\n\tres := os.system(cmd)\n\tif res != 0 {\n\t\teprintln('> failed running: `${cmd}`')\n\t\texit(1)\n\t}\n}\n\nfn xtime(cmd string) {\n\t$if linux {\n\t\tr('/usr/bin/time -f \"CPU: %Us\\tReal: %es\\tElapsed: %E\\tRAM: %MKB\\t%C\" ${cmd}')\n\t\treturn\n\t}\n\t$if macos {\n\t\tr('/opt/homebrew/bin/gtime -f \"CPU: %Us\\tReal: %es\\tElapsed: %E\\tRAM: %MKB\\t%C\" ${cmd}')\n\t\treturn\n\t}\n\t// Pure V fallback - no memory stats, but better than nothing ...\n\tbefore := time.now()\n\tr(cmd)\n\tafter := time.now()\n\tdelta_time := after - before\n\tprintln('> Elapsed time: ${delta_time.milliseconds()} ms, for cmd: ${cmd}')\n}\n\nfn show_size(fpath string) {\n\tprintln('>Size of ${fpath:20s}: ${os.file_size(fpath):10}')\n}\n\nfn compare_size(fpath1 string, fpath2 string) {\n\tsize1 := os.file_size(fpath1)\n\tsize2 := os.file_size(fpath2)\n\tdiff_ := i64(size2) - i64(size1)\n\tprintln('>>>>>> size(\"${fpath2:17}\") - size(\"${fpath1:17}\") = ${size2:10} - ${size1:10} = ${diff_:10}')\n}\n\nfn vcompare(vold string, vnew string) {\n\tr(\"v repeat --nmaxs 7 -R 3 '${vold} -check-syntax           examples/hello_world.v' '${vnew} -check-syntax           examples/hello_world.v'\")\n\tr(\"v repeat --nmaxs 7 -R 3 '${vold} -check                  examples/hello_world.v' '${vnew} -check                  examples/hello_world.v'\")\n\tr(\"v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ohw.c   examples/hello_world.v' '${vnew} -no-parallel -o nhw.c   examples/hello_world.v'\")\n\tcompare_size('ohw.c', 'nhw.c')\n\tr(\"v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ohw.exe examples/hello_world.v' '${vnew} -no-parallel -o nhw.exe examples/hello_world.v'\")\n\tcompare_size('ohw.exe', 'nhw.exe')\n\n\tr(\"v repeat --nmaxs 7 -R 3 '${vold} -check-syntax           cmd/v' '${vnew} -check-syntax           cmd/v'\")\n\tr(\"v repeat --nmaxs 7 -R 3 '${vold} -check                  cmd/v' '${vnew} -check                  cmd/v'\")\n\tr(\"v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ov.c    cmd/v' '${vnew} -no-parallel -o nv.c    cmd/v'\")\n\tcompare_size('ov.c', 'nv.c')\n\tr(\"v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ov.exe  cmd/v' '${vnew} -no-parallel -o nv.exe  cmd/v'\")\n\tcompare_size('ov.exe', 'nv.exe')\n}\n\nfn hline(header_message string) {\n\tprintln('='.repeat(98))\n\tprintln(header_message)\n}\n\nfn main() {\n\t// The starting point, when this program should be started, is just after `gh pr checkout NUMBER`.\n\tstart := time.now()\n\tpr_branch := gbranch()\n\tpr_commit := gcommit()\n\thline('Current git branch: ${pr_branch}, commit: ${pr_commit}')\n\tprintln('    Compiling new V executables from PR branch: ${pr_branch}, commit: ${pr_commit} ...')\n\t// *not* using v self here is deliberate, so that the `v` executable itself, is not changed after running this script\n\txtime('./v     -o vnew1 cmd/v')\n\txtime('./vnew1 -o vnew2 cmd/v')\n\txtime('./vnew2 -no-parallel -o vnew cmd/v')\n\txtime('./vnew -no-parallel -o nhw_current.c examples/hello_world.v')\n\txtime('./vnew -no-parallel -o nhw_current_gcc.c -cc gcc examples/hello_world.v')\n\txtime('./vnew -no-parallel -o nv_current.c cmd/v')\n\tif compare_prod {\n\t\txtime('./vnew -no-parallel -prod -o vnew_prod cmd/v')\n\t}\n\tshow_size('nhw_current.c')\n\tshow_size('nhw_current_gcc.c')\n\tshow_size('nv_current.c')\n\tshow_size('vnew')\n\tif compare_prod {\n\t\tshow_size('vnew_prod')\n\t}\n\tr('rm -rf vnew1 vnew2')\n\n\tif fetch_remote {\n\t\t// make sure to always compare against the main V repo's master branch by default:\n\t\tos.execute('git -C . remote add V_REPO https://github.com/vlang/v.git')\n\t\tos.execute('git -C . fetch V_REPO')\n\t\tos.execute('git branch -D v_repo_master')\n\t\tos.execute('git branch -f --track v_repo_master V_REPO/master')\n\t}\n\n\tr('git checkout v_repo_master')\n\tmaster_branch := gbranch()\n\thline('    Compiling old V executables from branch: ${master_branch}, commit: ${gcommit()} ...')\n\txtime('./v     -o vold1 cmd/v')\n\txtime('./vold1 -o vold2 cmd/v')\n\txtime('./vold2 -no-parallel -o vold cmd/v')\n\txtime('./vold -no-parallel -o ohw_master.c examples/hello_world.v')\n\txtime('./vold -no-parallel -o ohw_master_gcc.c -cc gcc examples/hello_world.v')\n\txtime('./vold -no-parallel -o ov_master.c  cmd/v')\n\tif compare_prod {\n\t\txtime('./vold -no-parallel -prod -o vold_prod cmd/v')\n\t\tshow_size('vold_prod')\n\t}\n\tshow_size('ohw_master.c')\n\tshow_size('ohw_master_gcc.c')\n\tshow_size('ov_master.c')\n\tshow_size('vold')\n\tif compare_prod {\n\t\tshow_size('vold_prod')\n\t}\n\tr('rm -rf vold1 vold2')\n\n\thline('File sizes so far ...')\n\tcompare_size('ohw_master.c', 'nhw_current.c')\n\tcompare_size('ohw_master_gcc.c', 'nhw_current_gcc.c')\n\tcompare_size('ov_master.c', 'nv_current.c')\n\tcompare_size('vold', 'vnew')\n\n\tr('git checkout ${pr_branch}')\n\t// we are on the PR branch again\n\thline('    Measuring at PR branch: ${pr_branch}, commit: ${gcommit()} ...')\n\tif compare_prod {\n\t\tvcompare('./vold_prod', './vnew_prod')\n\t} else {\n\t\tvcompare('./vold', './vnew')\n\t}\n\tprintln('Done. Total time: ${(time.now() - start).seconds()} s.')\n\n\thline('Final summary for file diff sizes on their own branches:')\n\tcompare_size('ohw_master.c', 'nhw_current.c')\n\tcompare_size('ohw_master_gcc.c', 'nhw_current_gcc.c')\n\tcompare_size('ov_master.c', 'nv_current.c')\n\tcompare_size('vold', 'vnew')\n\tif compare_prod {\n\t\tcompare_size('vold_prod', 'vnew_prod')\n\t}\n\n\thline('Final summary for file diff sizes for generated files on the *current* branch:')\n\tcompare_size('ohw.c', 'nhw.c')\n\tcompare_size('ov.c', 'nv.c')\n\tcompare_size('ohw.exe', 'nhw.exe')\n\tcompare_size('ov.exe', 'nv.exe')\n\n\t// After all the measurements are done, delete all the generated temporary files,\n\t// except the `vold` and `vnew` compilers, so that they can be used later in manual\n\t// experiments:\n\tif cleanup_tmp {\n\t\tr('rm -rf ohw* nhw* nv* ov*')\n\t}\n}\n"
  },
  {
    "path": ".github/workflows/compile_discordv.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nfunction show() {\n\tprintf \"\\u001b[35m$1\\u001b[0m\\n\"\n}\n\nrm -rf discord/\n\nshow \"Clone https://github.com/vcv88/discord.v\"\nv retry -- git clone --filter=blob:none --quiet https://github.com/vcv88/discord.v discord/\ncd discord/\nshow \"Checkout last known good commit\"\ngit checkout ce9ff457fce92d5bb15df2974440cd8292457ee0\nshow \"Execute Tests\"\nv test .\ncd ..\nrm -rf discord/\n"
  },
  {
    "path": ".github/workflows/compile_herolib.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nfunction show() {\n\tprintf \"\\u001b[35m$1\\u001b[0m\\n\"\n}\n\nrm -rf herolib/\n\nshow \"Clone https://github.com/freeflowuniverse/herolib\"\nv retry -- git clone --filter=blob:none --quiet https://github.com/freeflowuniverse/herolib herolib\ncd herolib\ngit checkout development\n\nmkdir -p ~/.vmodules/freeflowuniverse\nln -s $(pwd)/lib ~/.vmodules/freeflowuniverse/herolib\ncd cli\n\nshow \"Checkout last known good commit\"\ngit checkout ca8799af39228a5678a7be81128c5b0c342c9efc\n\nv wipe-cache\nshow \"Build project no parallel (gcc)\"\nv -cc gcc -cg -enable-globals -w -n hero.v \nshow \"Checking build\"\nls -l ./hero\n\nv wipe-cache\nshow \"Build project no parallel (clang)\"\nv -cc clang -cg -enable-globals -w -n hero.v \nshow \"Checking build\"\nls -l ./hero\n\nv wipe-cache\nshow \"Build project with -parallel-cc (clang)\"\nv -cc clang -cg -enable-globals -parallel-cc -w -n hero.v \nshow \"Checking gcc build\"\nls -l ./hero\n\nv wipe-cache\nshow \"Build project with -parallel-cc (gcc)\"\nv -cc gcc -cg -enable-globals -parallel-cc -w -n hero.v \nshow \"Checking clang build\"\nls -l ./hero\n\nrm -rf ../../herolib\n"
  },
  {
    "path": ".github/workflows/compile_shaders_in_examples.sh",
    "content": "#!/usr/bin/env bash\n\nfor f in examples/sokol/*/ ; do\n\techo \"compiling shaders for $f ...\";\n\ttime ./v shader $f;\n\techo \"done\";\ndone;\n"
  },
  {
    "path": ".github/workflows/compile_v_with_vtcc.sh",
    "content": "#!/usr/bin/env bash\n\nset -ex\n\nfunction show() {\n\tprintf \"\\u001b[35m$1\\u001b[0m\\n\"\n}\n\nshow \"Prepare\"\nrm -rf vtcc/\n\nshow \"Clone vtcc\"\n.github/workflows/retry.sh git clone https://github.com/felipensp/vtcc --branch stable --quiet vtcc/\ndu -s vtcc/\n## TODO: just `./v vtcc`, later will cause V, to detect the compiler as tcc (which it is), and add `-fwrapv`, which causes the vtcc compiler to panic currently\nshow \"Compile vtcc\"\ncd vtcc/\nv run make.vsh\ncd ..\n\nls -la vtcc/vtcc\n./vtcc/vtcc --version\n\nshow \"Generate the C file, for the current V version\"\n./v -o vlang.c cmd/v\nls -la vlang.c\n\nshow \"Compile the C file with vtcc\"\n./vtcc/vtcc -o v_compiled_with_vtcc vlang.c -lpthread\nls -la v_compiled_with_vtcc\n\nshow \"Test the resulting V compiler\"\n./v_compiled_with_vtcc version\n\nshow \"Compile and run hello with vtcc\"\n./v_compiled_with_vtcc -cc vtcc/vtcc -showcc run examples/hello_world.v\n\nshow \"Remove the generated temporary files, so the script can be re-run cleanly\"\nrm -rf v_compiled_with_vtcc vlang.c vtcc/\n"
  },
  {
    "path": ".github/workflows/compile_vlang_gui_examples.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nfunction show() {\n\tprintf \"\\u001b[35m$1\\u001b[0m\\n\"\n}\n\nrm -rf ~/.vmodules/gui/\n\nexport VJOBS=1\nshow \"Clone https://github.com/vlang/gui\"\nv retry -- git clone --filter=blob:none --quiet https://github.com/vlang/gui ~/.vmodules/gui/\nshow \"Checkout last known good commit\"\ngit -C ~/.vmodules/gui/ checkout b4e3716b042ee6352efedff64c5b92cbf0e81ded\nshow \"Check module for syntax and semantic errors\"\nv -shared -check ~/.vmodules/gui\nshow \"Execute Tests\"\nv test ~/.vmodules/gui/\nshow \"Compile Examples\"\nv should-compile-all -no-parallel ~/.vmodules/gui/examples/\nrm -rf ~/.vmodules/gui/\n"
  },
  {
    "path": ".github/workflows/cross_ci.yml",
    "content": "name: Cross CI\n\non:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/cross_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/cross_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\nconcurrency:\n  group: cross-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  cross-macos:\n    runs-on: macos-latest\n    timeout-minutes: 20\n    env:\n      VFLAGS: -cc clang\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 10\n      - name: Build V\n        run: make -j4 && ./v symlink\n\n      - name: Install dependencies\n        run: |\n          ./v retry -- brew install mingw-w64\n          export LIBRARY_PATH=\"$LIBRARY_PATH:/usr/local/opt/openssl/lib/\"\n\n      - name: Test symlink\n        run: ./v symlink\n\n      - name: Cross-compilation to Linux\n        run: |\n          ./v -os linux cmd/v\n          # TODO: fix this: ./v -os linux examples/2048/2048.v\n\n      - name: Cross-compilation of veb app to Linux with -d use_openssl\n        run: ./v -d use_openssl -os linux examples/veb/veb_example.v\n\n      - name: Cross-compilation to Windows\n        run: |\n          ./v -os windows cmd/v\n          ./v -os windows examples/2048/2048.v\n\n  cross-linux:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    env:\n      VFLAGS: -cc tcc -no-retry-compilation\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 10\n      - name: Build v\n        run: make -j4 && ./v symlink\n\n      - name: Install dependencies\n        run: |\n          .github/workflows/disable_azure_mirror.sh\n          ./v retry -- sudo apt update -y -qq\n          ./v retry -- sudo apt install --quiet -y mingw-w64 wine wine64 winetricks libssl-dev sqlite3 libsqlite3-dev\n\n      - name: Show diagnostics for wine\n        run: |\n          which wine\n          # shellcheck disable=SC2046\n          ls -la $(realpath $(which wine))\n\n      - name: v.c can be compiled and run with -os cross\n        run: |\n          ./v -os cross -o /tmp/v.c cmd/v\n          gcc  -g -std=gnu11 -w -o v_from_vc /tmp/v.c  -lm -lpthread\n          ls -lart v_from_vc\n          ./v_from_vc version\n\n      - name: v_win.c can be compiled and run with -os windows\n        run: |\n          ./v -cc msvc -os windows -o /tmp/v_win.c cmd/v\n          x86_64-w64-mingw32-gcc /tmp/v_win.c -std=c99 -w -municode -o v_from_vc.exe -lws2_32\n          ls -lart v_from_vc.exe\n          wine ./v_from_vc.exe version\n\n      - name: hello_world.v can be cross compiled to hello_world.exe\n        run: |\n          ./v -os windows examples/hello_world.v\n          ls -lart examples/hello_world.exe\n          wine examples/hello_world.exe\n\n      - name: 2048.v can be cross compiled to 2048.exe\n        run: |\n          ./v -os windows examples/2048/2048.v\n          ls -lart examples/2048/2048.exe\n\n  cross-windows:\n    runs-on: windows-2025\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build\n        run: |\n          echo %VFLAGS%\n          echo $VFLAGS\n          .\\make.bat -msvc\n      - name: TODO v_win.c can be compiled and run with -os windows\n        run: |\n          .\\v.exe -os windows -cc msvc -showcc -o v2.exe cmd\\v\n          .\\v.exe -os windows -cc msvc -o v_win.c cmd\\v\n          dir v2.exe\n          dir v_win.c\n          .\\v2.exe version\n"
  },
  {
    "path": ".github/workflows/debug.yml",
    "content": "name: Debug CI\n\non: [workflow_dispatch]\n\njobs:\n  debug-msvc:\n    runs-on: windows-2025\n    timeout-minutes: 121\n    env:\n      VFLAGS: -cc msvc\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build\n        run: |\n          echo %VFLAGS%\n          echo $VFLAGS\n          .\\make.bat -msvc\n          .\\v.exe -cflags /WX self\n      - name: Install dependencies\n        run: |\n          .\\v.exe setup-freetype\n          .\\.github\\workflows\\windows-install-sqlite.bat\n      - name: v doctor\n        run: ./v doctor\n      - name: Verify `v test` works\n        run: |\n          ./v cmd/tools/test_if_v_test_system_works.v\n          ./cmd/tools/test_if_v_test_system_works\n      - name: All code is formatted\n        run: ./v -silent test-cleancode\n      - name: Self tests\n        run: ./v -silent test-self\n      - name: Test v->js\n        run: ./v -o hi.js examples/js_hello_world.v && node hi.js\n      - name: Test v binaries\n        run: ./v build-vbinaries\n      - name: Build examples\n        run: ./v -silent build-examples\n      - name: v2 self compilation\n        run: .\\v.exe -o v2.exe cmd/v && .\\v2.exe -o v3.exe cmd/v\n"
  },
  {
    "path": ".github/workflows/disable_azure_mirror.sh",
    "content": "#!/bin/bash\necho \"APT MIRRORS BEFORE:\"; cat /etc/apt/apt-mirrors.txt\nsudo sed -i 's@http://azure.archive.ubuntu.com@http://archive.ubuntu.com@gm' /etc/apt/apt-mirrors.txt\necho \"APT MIRRORS  AFTER:\"; cat /etc/apt/apt-mirrors.txt\n\necho \"ls -la /etc/apt/sources.list.d/\"; ls -la /etc/apt/sources.list.d/\nfor f in /etc/apt/sources.list.d/*; do echo \"####### $f ######\"; cat $f; done\n\necho \"APT SOURCES BEFORE:\"; echo \"ls -la /etc/apt/sources.list\"; ls -la /etc/apt/sources.list; cat /etc/apt/sources.list\nsudo sed -i 's@http://azure.archive.ubuntu.com@http://archive.ubuntu.com@gm' /etc/apt/sources.list\necho \"APT SOURCES  AFTER:\"; echo \"ls -la /etc/apt/sources.list\"; ls -la /etc/apt/sources.list; cat /etc/apt/sources.list\n"
  },
  {
    "path": ".github/workflows/docker_ci.yml",
    "content": "name: Docker CI\n\non:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/docker_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/docker_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\nconcurrency:\n  group: docker-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\nenv:\n  V_CI_MUSL: 1\n\njobs:\n  docker-alpine-musl-gcc:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 241\n    container:\n      image: thevlang/vlang:alpine-build\n      env:\n        VFLAGS: -cc gcc\n      volumes:\n        - ${{github.workspace}}:/opt/vlang\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n      - name: Show Environment\n        run: |\n          echo \"PWD:\"\n          pwd\n          echo \"ENVIRONMENT:\"\n          env\n          echo \"C Compiler:\"\n          gcc --version\n      - name: Add dependencies\n        run: apk add libc6-compat gcompat gc gc-dev binutils diffutils elfutils\n      - name: Build V\n        run: CC=gcc make\n      - name: All code is formatted\n        run: ./v -silent test-cleancode\n      - name: Run only essential tests\n        run: VTEST_JUST_ESSENTIAL=1 ./v -silent test-self\n\n  docker-alpine-musl-tcc:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 241\n    container:\n      image: thevlang/vlang:alpine-build\n      volumes:\n        - ${{github.workspace}}:/opt/vlang\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n      - name: Add dependencies\n        run: apk add musl-dev libatomic_ops-dev libatomic openssl libc6-compat gcompat gc gc-dev binutils diffutils elfutils\n      - name: Build V\n        run: make\n      - name: Check if vpm compiles with tcc\n        run: ./v -show-c-output -showcc -no-retry-compilation -cc tcc cmd/tools/vpm\n      - name: Run only builtin and math tests\n        run: ./v test vlib/builtin\n\n  docker-ubuntu-musl:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 121\n    container:\n      image: thevlang/vlang:ubuntu-build\n      env:\n        V_CI_UBUNTU_MUSL: 1\n        VFLAGS: -cc musl-gcc -gc none\n      volumes:\n        - ${{github.workspace}}:/opt/vlang\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n      - name: Build V\n        run: echo \"$VFLAGS\" && make -j4 && ./v -cg -o v cmd/v\n      - name: Verify `v test` works\n        run: |\n          echo \"$VFLAGS\"\n          ./v cmd/tools/test_if_v_test_system_works.v\n          ./cmd/tools/test_if_v_test_system_works\n      - name: Add dependencies\n        run: apt install libsqlite3-dev\n      - name: All code is formatted\n        run: ./v -silent test-cleancode\n      - name: Test V fixed tests\n        run: ./v -silent test-self vlib\n"
  },
  {
    "path": ".github/workflows/docs_ci.yml",
    "content": "name: Docs CI\n\n### Run on *EVERY* .v or .md related commit.\n### The documentation *SHOULD* stay valid, and the developers should receive\n### early warning, if they break it.\n\non:\n  push:\n    paths-ignore:\n      - '**.yml'\n      - '!**/docs_ci.yml'\n      - 'cmd/tools/vrepl.v'\n  pull_request:\n    paths-ignore:\n      - '**.yml'\n      - '!**/docs_ci.yml'\n      - 'cmd/tools/vrepl.v'\n\nconcurrency:\n  group: docs-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  check-markdown:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make\n      - name: Install dependencies (some examples show how to use sqlite and the x11 clipboard)\n        run: ./v retry -- sudo apt install --quiet -y libx11-dev libssl-dev sqlite3 libsqlite3-dev\n      - name: Check markdown line length & code examples\n        run: ./v check-md -hide-warnings .\n        ## NB: -hide-warnings is used here, so that the output is less noisy,\n        ## thus real errors are easier to spot.\n\n  report-missing-fn-doc:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 5\n    env:\n      MOPTIONS: --diff --deprecated --relative-paths --exclude /vlib/v/ --exclude /vlib/v2/ --exclude /builtin/linux_bare/ --exclude /testdata/ --exclude /tests/ --exclude /vlib/sokol/ --exclude /vlib/x/\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make\n\n      - name: Checkout previous v\n        uses: actions/checkout@v6\n        with:\n          repository: vlang/v\n          ref: master\n          path: pv\n\n      - name: Check against parent commit\n        run: |\n          # shellcheck disable=SC2086\n          ./v missdoc $MOPTIONS pv/vlib vlib\n\n  report-missing-dots-in-doc-comments:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make\n      - name: Check doc comment dots for some key modules\n        run: ./v run cmd/tools/find_doc_comments_with_no_dots.v \\\n          vlib/builtin/ vlib/arrays/ vlib/flag/ \\\n          vlib/bitfield/ vlib/term/ vlib/strings/ \\\n          vlib/rand/ vlib/compress/ vlib/clipboard/ \\\n          vlib/time/ \\\n          vlib/os\n\n  report-wrong-examples-in-doc-comments:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make\n      - name: Check examples in the doc comments for all vlib modules\n        run: VJOBS=1 ./v doc -check-examples -f none vlib/\n"
  },
  {
    "path": ".github/workflows/download_full_toml_test_suites.sh",
    "content": "#!/usr/bin/env bash\n\nset -ex\n\nrm -rf vlib/toml/tests/testdata/iarna vlib/toml/tests/testdata/toml_rs vlib/toml/tests/testdata/toml_lang vlib/toml/tests/testdata/large_toml_file_test.toml\n\n./v retry -- ./v download -o vlib/toml/tests/testdata/large_toml_file_test.toml https://gist.githubusercontent.com/Larpon/89b0e3d94c6903851ff15559e5df7a05/raw/62a1f87a4e37bf157f2e0bfb32d85d840c98e422/large_toml_file_test.toml\n\n./v retry -- git clone -n https://github.com/iarna/toml-spec-tests.git vlib/toml/tests/testdata/iarna\ngit -C vlib/toml/tests/testdata/iarna checkout 1880b1a\n\n./v retry -- git clone -n https://github.com/toml-lang/toml-test.git vlib/toml/tests/testdata/toml_lang\ngit -C vlib/toml/tests/testdata/toml_lang checkout 229ce2e\n\n# A few history notes of toml-rs (previously alexcrichton):\n#  commit 7f5472c the test-suite dir moves to the crates/ sub-directory\n#  commit 8461f7c *a lot* of test files are removed in *hope* that they are covered by the compliance test suite (assumed to be BurntSushi/toml-test, later toml-lang/toml-test)\n#  commit 9bd454c the last known good commit we can test against\n./v retry -- git clone -n https://github.com/toml-rs/toml.git vlib/toml/tests/testdata/toml_rs\ngit -C vlib/toml/tests/testdata/toml_rs reset --hard 9bd454c\n"
  },
  {
    "path": ".github/workflows/find_openssl.bat",
    "content": "@echo off\r\nsetlocal EnableDelayedExpansion\r\nREM Find every openssl.exe reachable through PATH:\r\nfor /f \"delims=\" %%F in ('where openssl 2^>nul') do (\r\n    set \"OPENSSL_DIR=%%~dpF\"\r\n    echo OpenSSL lives in: \"!OPENSSL_DIR!\"\r\n    goto :end\r\n)\r\necho OpenSSL not found in: \"!PATH!\"\r\n:end\r\n"
  },
  {
    "path": ".github/workflows/freebsd_ci.yml",
    "content": "name: CI FreeBSD\n\non:\n  workflow_dispatch:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - 'cmd/tools/**'\n      - '!**/freebsd_ci.yml'\n      - '!ci/freebsd_ci.vsh'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - 'cmd/tools/**'\n      - '!**/freebsd_ci.yml'\n      - '!ci/freebsd_ci.vsh'\n      - '!cmd/tools/builders/**.v'\n\n### See https://github.com/cross-platform-actions/action\n### for a description of the used fields here\n\njobs:\n  tcc-freebsd:\n    runs-on: ubuntu-latest\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n      - name: Tests on FreeBSD with tcc\n        id: tests-freebsd-tcc\n        uses: cross-platform-actions/action@v0.32.0\n        with:\n          operating_system: freebsd\n          version: '15.0'\n          memory: 4G\n          shell: sh\n          sync_files: runner-to-vm\n          run: |\n            sudo pkg install -y git sqlite3 gmake boehm-gc-threaded libiconv\n            # Install DB packages needed to build examples\n            sudo pkg install -y mariadb118-client postgresql18-client\n            # Install packages needed by Sokol to build examples\n            sudo pkg install -y alsa-lib libglvnd libXi libXcursor\n            # Mandatory: hostname not set in VM => some tests fail\n            sudo hostname -s freebsd-ci\n            echo \"### OS infos\"\n            uname -a\n            git config --global --add safe.directory .\n            echo \"### Build V\"\n            gmake\n            sudo ./v symlink\n            export VTEST_SHOW_LONGEST_BY_RUNTIME=3\n            export VTEST_SHOW_LONGEST_BY_COMPTIME=3\n            export VTEST_SHOW_LONGEST_BY_TOTALTIME=3\n            export VFLAGS='-cc tcc -no-retry-compilation'\n            ./v run ci/freebsd_ci.vsh all\n\n  clang-freebsd:\n    runs-on: ubuntu-latest\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n      - name: Tests on FreeBSD with clang\n        id: tests-freebsd-clang\n        uses: cross-platform-actions/action@v0.32.0\n        with:\n          operating_system: freebsd\n          version: '15.0'\n          memory: 4G\n          shell: sh\n          sync_files: runner-to-vm\n          run: |\n            sudo pkg install -y git sqlite3 gmake boehm-gc-threaded libiconv\n            # Install DB packages needed to build examples\n            sudo pkg install -y mariadb118-client postgresql18-client\n            # Install packages needed by Sokol to build examples\n            sudo pkg install -y alsa-lib libglvnd libXi libXcursor\n            # Mandatory: hostname not set in VM => some tests fail\n            sudo hostname -s freebsd-ci\n            echo \"### OS infos\"\n            uname -a\n            git config --global --add safe.directory .\n            echo \"### Build V\"\n            gmake\n            sudo ./v symlink\n            export VTEST_SHOW_LONGEST_BY_RUNTIME=3\n            export VTEST_SHOW_LONGEST_BY_COMPTIME=3\n            export VTEST_SHOW_LONGEST_BY_TOTALTIME=3\n            export VFLAGS='-cc clang'\n            ./v run ci/freebsd_ci.vsh all\n\n  gcc-freebsd:\n    runs-on: ubuntu-latest\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n      - name: Tests on FreeBSD with gcc\n        id: tests-freebsd-gcc\n        uses: cross-platform-actions/action@v0.32.0\n        with:\n          operating_system: freebsd\n          version: '15.0'\n          memory: 4G\n          shell: sh\n          sync_files: runner-to-vm\n          run: |\n            sudo pkg install -y git sqlite3 gmake boehm-gc-threaded libiconv gcc\n            # Install DB packages needed to build examples\n            sudo pkg install -y mariadb118-client postgresql18-client\n            # Install packages needed by Sokol to build examples\n            sudo pkg install -y alsa-lib libglvnd libXi libXcursor\n            # Mandatory: hostname not set in VM => some tests fail\n            sudo hostname -s freebsd-ci\n            echo \"### OS infos\"\n            uname -a\n            git config --global --add safe.directory .\n            echo \"### Build V\"\n            gmake\n            sudo ./v symlink\n            export VTEST_SHOW_LONGEST_BY_RUNTIME=3\n            export VTEST_SHOW_LONGEST_BY_COMPTIME=3\n            export VTEST_SHOW_LONGEST_BY_TOTALTIME=3\n            export VFLAGS='-cc gcc'\n            ./v run ci/freebsd_ci.vsh all\n"
  },
  {
    "path": ".github/workflows/gen_vc_ci.yml",
    "content": "name: VC gen\n\non:\n  workflow_dispatch:\n  pull_request:\n    paths-ignore:\n      - '**.vv'\n      - '**.out'\n      - '**.md'\n      - '**.yml'\n      - '!**/gen_vc_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  push:\n    paths-ignore:\n      - '**.vv'\n      - '**.out'\n      - '**.md'\n      - '**.yml'\n      - '!**/gen_vc_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\n# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.\n# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.\nconcurrency:\n  group: gen_vc-${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: ${{ !contains(github.ref, 'master')}}\n\njobs:\n  build-vc:\n    runs-on: ubuntu-latest\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4\n      - name: Regenerate v.c and v_win.c\n        run: |\n          git config --global user.email \"vlang-bot@users.noreply.github.com\"\n          git config --global user.name \"vlang-bot\"\n\n          COMMIT_HASH=\"$(git rev-parse HEAD)\"\n          COMMIT_MSG=\"$(git log -1 --oneline --pretty='%s' HEAD)\"\n\n          rm -rf vc\n          ./v retry -- git clone --depth=1 \"https://vlang-bot:${{ secrets.VLANG_BOT_SECRET }}@github.com/vlang/vc.git\"\n\n          rm -rf vc/v.c vc/v_win.c\n          ./v -o vc/v.c     -cross               cmd/v\n          ./v -o vc/v_win.c -os windows -cc msvc cmd/v\n\n          sed -i \"1s/^/#define V_COMMIT_HASH \\\"$COMMIT_HASH\\\"\\n/\" vc/v.c\n          sed -i \"1s/^/#define V_COMMIT_HASH \\\"$COMMIT_HASH\\\"\\n/\" vc/v_win.c\n\n          # do some sanity checks for the generated v.c file:\n          grep 'Turned ON custom defines: no_backtrace,cross'  vc/v.c\n          grep '#define CUSTOM_DEFINE_cross' vc/v.c\n\n          # ensure the generated C files for the compiler, are over 5000 lines long, as a safety measure\n          [ \"$(wc -l < vc/v.c)\" -gt 5000 ]\n          [ \"$(wc -l < vc/v_win.c)\" -gt 5000 ]\n\n          git -C vc add v.c v_win.c\n          git -C vc commit -m \"[v:master] $COMMIT_HASH - $COMMIT_MSG\"\n\n          # in case there are recent commits:\n          ./v retry -- git -C vc pull --rebase origin master\n          git -C vc log -3\n\n      - name: Deploy\n        if: github.event_name == 'push' && github.repository == 'vlang/v' && github.ref == 'refs/heads/master'\n        run: git -C vc push || true\n"
  },
  {
    "path": ".github/workflows/gg_regressions_ci.yml",
    "content": "name: Graphics CI\n\non:\n  push:\n    paths:\n      - 'vlib/**'\n      - 'thirdparty/**'\n      - 'cmd/tools/builders/**.v'\n      - '**/gg_regressions_ci.yml'\n      - '!**.md'\n  pull_request:\n    paths:\n      - 'vlib/**'\n      - 'thirdparty/**'\n      - 'cmd/tools/builders/**.v'\n      - '**/gg_regressions_ci.yml'\n      - '!**.md'\n\nconcurrency:\n  group: gg-regressions-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  gg-regressions:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    env:\n      VFLAGS: -cc tcc\n      DISPLAY: :99\n      LIBGL_ALWAYS_SOFTWARE: true\n      VTMP: /tmp\n    steps:\n      - name: Checkout V\n        uses: actions/checkout@v6\n\n      - name: Build local v\n        run: make -j4 && ./v symlink\n\n      - name: Clear module cache\n        run: ./v wipe-cache\n\n      - name: Setup dependencies\n        run: |\n          # imagemagick              : convert, mogrify\n          # xvfb                     : xvfb\n          # openimageio-tools        : idiff\n          # libxcursor-dev libxi-dev : V gfx deps\n          # libgl1-mesa-dri          : For headless rendering / software DRI driver (LIBGL_ALWAYS_SOFTWARE=true)\n          # freeglut3-dev            : Fixes graphic apps compilation with tcc\n          # libx11-dev               : X11 headers for clipboard and sokol (default backend on Linux)\n          .github/workflows/disable_azure_mirror.sh\n          ./v retry -- sudo apt update\n          ./v retry -- sudo apt install imagemagick openimageio-tools libgl1-mesa-dri xvfb libxcursor-dev libxi-dev libxrandr-dev freeglut3-dev xsel xclip libx11-dev libegl-dev\n          ./v retry -- ./v download https://raw.githubusercontent.com/tremby/imgur.sh/c98345d/imgur.sh\n          ./v retry -- git clone https://github.com/Larpon/gg-regression-images gg-regression-images\n          chmod +x ./imgur.sh\n\n      - name: Sample and compare\n        id: compare\n        continue-on-error: true\n        run: |\n          Xvfb \"$DISPLAY\" -screen 0 1280x1024x24 -fbdir /var/tmp/ &\n          sleep 2; while [ ! -f /var/tmp/Xvfb_screen0 ]; do sleep 0.5; done # give xvfb time to start, even on slow CI runs\n          sleep 5; ./v gret -t ./gg-regression-images/vgret.v_examples.toml -v ./gg-sample_images ./gg-regression-images\n\n      - name: Upload regression to imgur\n        if: steps.compare.outcome != 'success'\n        run: |\n          ./imgur.sh /tmp/fail.png\n          ./imgur.sh /tmp/diff.png\n          exit 1\n"
  },
  {
    "path": ".github/workflows/gh_restart_failed.v",
    "content": "import os\nimport json\nimport term\nimport time\n\nconst c = term.colorize\nconst tg = term.green\nconst tm = term.magenta\nconst tb = term.bold\n\nstruct Check {\n\tname     string\n\tbucket   string\n\tstate    string\n\tlink     string\n\tworkflow string\n}\n\nfn (c Check) is_failed() bool {\n\treturn c.bucket == 'fail' || c.state in ['FAILURE', 'TIMED_OUT']\n}\n\nfn (c Check) is_cancelled() bool {\n\treturn c.bucket == 'cancel' || c.state == 'CANCELLED'\n}\n\nstruct GhCheckRun {\n\tname       string\n\tstatus     string\n\tconclusion string\n\thtml_url   string @[json: html_url]\n}\n\nstruct GhCheckRunsResponse {\n\tcheck_runs []GhCheckRun @[json: check_runs]\n}\n\nfn main() {\n\tunbuffer_stdout()\n\targ := os.args[1] or {\n\t\tprintln('Usage: v run gh_restart_failed.v <PR_NUMBER|REF>')\n\t\treturn\n\t}\n\tis_pr := arg.len < 6 && arg.bytes().all(it.is_digit())\n\tchecks := if is_pr { get_checks_for_pr(arg.int()) } else { get_checks_for_commit(arg) }\n\tmut failed := []Check{}\n\tmut cancelled := []Check{}\n\tmut succeeded := 0\n\tmut in_progress := 0\n\tfor check in checks {\n\t\tif check.is_failed() {\n\t\t\tfailed << check\n\t\t} else if check.is_cancelled() {\n\t\t\tcancelled << check\n\t\t} else if check.bucket == 'pass' || check.state == 'SUCCESS' {\n\t\t\tsucceeded++\n\t\t} else {\n\t\t\tin_progress++\n\t\t}\n\t}\n\tmut to_restart := []Check{}\n\tto_restart << failed\n\tto_restart << cancelled\n\tmut restarted_count := 0\n\tif to_restart.len > 0 {\n\t\tprintln('Found ${to_restart.len} failed or cancelled jobs:')\n\t\tfor job in to_restart {\n\t\t\tprintln('- ${job.workflow} / ${job.name} (${job.state})')\n\t\t}\n\t\tprintln('\\n' + c(tg, 'Do you want to restart these ${to_restart.len} jobs? [y/N]: '))\n\t\tif os.input('').to_lower().trim_space() == 'y' {\n\t\t\tprintln('')\n\t\t\tfor job in to_restart {\n\t\t\t\trun_id, job_id := parse_ids(job.link)\n\t\t\t\tif run_id == '' || job_id == '' {\n\t\t\t\t\tprintln('Could not parse IDs from link: ${job.link} (Skipping)')\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tprint('Restarting ${job.name} (Run: ${run_id}, Job: ${job_id})... ')\n\t\t\t\tres := execute_with_progress('gh run rerun ${run_id} --job ${job_id}')\n\t\t\t\tif res.exit_code == 0 {\n\t\t\t\t\trestarted_count++\n\t\t\t\t} else {\n\t\t\t\t\tprintln('  Error: ${res.output.trim_space()}')\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tprintln('Aborted restart.')\n\t\t}\n\t} else {\n\t\tprintln('No failed or cancelled jobs found.')\n\t}\n\tprintln('\\n' + c(tg, 'Summary:'))\n\tprintln('Total jobs:   ${m(checks.len)}')\n\tprintln('Failed:       ${m(failed.len)}')\n\tprintln('Cancelled:    ${m(cancelled.len)}')\n\tprintln('Succeeded:    ${m(succeeded)}')\n\tprintln('In Progress:  ${m(in_progress)}')\n\tprintln('Restarted:    ${m(restarted_count)}')\n}\n\nfn m(n int) string {\n\treturn c(tb, n.str())\n}\n\nfn parse_ids(link string) (string, string) {\n\tparts := link.split('/')\n\truns_idx := parts.index('runs')\n\tjob_idx := parts.index('job')\n\tmut run_id := ''\n\tmut job_id := ''\n\tif runs_idx != -1 && runs_idx + 1 < parts.len {\n\t\trun_id = parts[runs_idx + 1]\n\t}\n\tif job_idx != -1 && job_idx + 1 < parts.len {\n\t\tjob_id = parts[job_idx + 1]\n\t}\n\treturn run_id, job_id\n}\n\nfn get_checks_for_pr(pr_number int) []Check {\n\tprintln(c(tg, 'Fetching checks for PR ${m(pr_number)}...'))\n\tres := execute_with_progress('gh pr checks ${pr_number} --json name,bucket,state,link,workflow')\n\tif res.exit_code != 0 {\n\t\tprintln('Error: ${res.output}')\n\t\texit(1)\n\t}\n\treturn json.decode([]Check, res.output) or { exit(1) }\n}\n\nfn get_checks_for_commit(commit string) []Check {\n\tprintln(c(tg, 'Fetching checks for ref ${c(tb, commit)}...'))\n\tres := execute_with_progress('gh api repos/:owner/:repo/commits/${commit}/check-runs?per_page=100')\n\tif res.exit_code != 0 {\n\t\tprintln('Error: ${res.output}')\n\t\texit(1)\n\t}\n\tresp := json.decode(GhCheckRunsResponse, res.output) or { exit(1) }\n\tmut checks := []Check{}\n\tfor cr in resp.check_runs {\n\t\tchecks << Check{\n\t\t\tname:     cr.name\n\t\t\tbucket:   if cr.conclusion == 'failure' {\n\t\t\t\t'fail'\n\t\t\t} else if cr.conclusion == 'cancelled' {\n\t\t\t\t'cancel'\n\t\t\t} else if cr.conclusion == 'success' {\n\t\t\t\t'pass'\n\t\t\t} else {\n\t\t\t\t'pending'\n\t\t\t}\n\t\t\tstate:    if cr.conclusion != '' {\n\t\t\t\tcr.conclusion.to_upper()\n\t\t\t} else {\n\t\t\t\tcr.status.to_upper()\n\t\t\t}\n\t\t\tlink:     cr.html_url\n\t\t\tworkflow: 'Actions'\n\t\t}\n\t}\n\treturn checks\n}\n\nfn execute_with_progress(cmd string) os.Result {\n\tstart := time.now()\n\tmut stop := false\n\tspawn fn (cmd string, start time.Time, mut stop &bool) {\n\t\tstart_str := start.hhmmss()\n\t\tfor !*stop {\n\t\t\telapsed := time.since(start).seconds()\n\t\t\tprint('\\rRunning ${c(tm, cmd)} [${start_str}] ... ${elapsed:.1f}s')\n\t\t\tos.flush()\n\t\t\ttime.sleep(100 * time.millisecond)\n\t\t}\n\t}(cmd, start, mut &stop)\n\tres := os.execute(cmd)\n\telapsed := time.since(start).seconds()\n\tstop = true\n\ttime.sleep(100 * time.millisecond)\n\tstatus := if res.exit_code == 0 { 'OK' } else { 'Failed' }\n\tprint('\\r')\n\tprintln('Command ${c(tm, cmd)} done in ${elapsed:.1f}s. ${status}')\n\treturn res\n}\n"
  },
  {
    "path": ".github/workflows/hub_docker_ci.yml",
    "content": "name: hub_docker_ci\n\n### NB: avoid caching things here, since the action is rare (once per week),\n### and the potential benefits are less than the complexity of debugging\n### cache invalidation issues...\n## Trigger on both new release tags, and on weekly tags.\n## Allow for manual override too:\non:\n  workflow_dispatch:\n  push:\n    tags:\n      - '[0-9].[0-9]+.[0-9]+'\n      - 'weekly.*'\n\nconcurrency:\n  group: 'hub_docker_ci-${{ github.ref }}'\n  cancel-in-progress: true\n\njobs:\n  publish-new-docker-images:\n    strategy:\n      matrix:\n        os: [debian, alpine]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          repository: 'vlang/docker'\n\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@v4\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v4\n\n      - name: Login to hub.docker.com\n        uses: docker/login-action@v4\n        with:\n          username: ${{ secrets.DOCKER_USERNAME }}\n          password: ${{ secrets.DOCKER_PASSWORD }}\n\n      - name: Create & bootstrap persistent builder\n        run: |\n          docker buildx create --name gh-builder --driver docker-container --use\n          docker buildx inspect --bootstrap\n\n      - name: generate tags conditionally\n        id: gen_tags\n        run: |\n          if [[ \"${{ matrix.os }}\" == 'debian' ]]; then\n            echo 'TAGS=thevlang/vlang:latest,thevlang/vlang:${{ matrix.os }}' >> \"$GITHUB_OUTPUT\"\n          else\n            echo 'TAGS=thevlang/vlang:${{ matrix.os }}' >> \"$GITHUB_OUTPUT\"\n          fi\n\n      - uses: docker/build-push-action@v7\n        name: Build and deploy v image\n        with:\n          builder: gh-builder\n          context: .\n          platforms: linux/amd64,linux/arm64\n          tags: ${{ steps.gen_tags.outputs.TAGS }}\n          file: docker/vlang/Dockerfile.${{ matrix.os }}\n          push: true\n          build-args: 'USER=thevlang'\n          ## cache-from: type=registry,ref=thevlang/vlang:${{ matrix.os }}-buildcache\n          ## cache-to: type=registry,ref=thevlang/vlang:${{ matrix.os }}-buildcache,mode=max\n\n      - uses: docker/build-push-action@v7\n        name: Build and deploy developer build\n        with:\n          builder: gh-builder\n          context: .\n          platforms: linux/amd64,linux/arm64\n          tags: thevlang/vlang:${{ matrix.os }}-dev\n          file: docker/vlang/Dockerfile.${{ matrix.os }}.dev-full\n          push: true\n          build-args: 'USER=thevlang'\n          ## cache-from: type=registry,ref=thevlang/vlang:${{ matrix.os }}-dev-buildcache\n          ## cache-to: type=registry,ref=thevlang/vlang:${{ matrix.os }}-dev-buildcache,mode=max\n"
  },
  {
    "path": ".github/workflows/linux_ci.yml",
    "content": "name: CI Linux\n\non:\n  workflow_dispatch:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/linux_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/linux_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\nconcurrency:\n  group: linux-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  tcc-linux:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 121\n    env:\n      VFLAGS: -cc tcc -no-retry-compilation\n      VTEST_SHOW_LONGEST_BY_RUNTIME: 3\n      VTEST_SHOW_LONGEST_BY_COMPTIME: 3\n      VTEST_SHOW_LONGEST_BY_TOTALTIME: 3\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build v\n        run: make -j4 && ./v symlink\n      - name: Build v with -prealloc\n        run: v run ci/linux_ci.vsh build_v_with_prealloc\n      - name: All code is formatted\n        run: v run ci/linux_ci.vsh all_code_is_formatted_tcc\n      - name: Install dependencies for examples and tools\n        run: v run ci/linux_ci.vsh install_dependencies_for_examples_and_tools_tcc\n      - name: Test v->c\n        run: v run ci/linux_ci.vsh test_v_to_c_tcc\n      - name: v self compilation\n        run: v run ci/linux_ci.vsh v_self_compilation_tcc\n      - name: v doctor\n        run: v run ci/linux_ci.vsh v_doctor_tcc\n      - name: Verify `v test` works\n        run: v run ci/linux_ci.vsh verify_v_test_works_tcc\n      - name: Test pure V math module\n        run: v run ci/linux_ci.vsh test_pure_v_math_module_tcc\n      - name: Test inline assembly on linux\n        run: v run ci/linux_ci.vsh test_inline_assembly\n      - name: Self tests\n        run: v run ci/linux_ci.vsh self_tests_tcc\n      - name: Build examples\n        run: v run ci/linux_ci.vsh build_examples_tcc\n      - name: Run the submodule example, using a relative path\n        run: v run ci/linux_ci.vsh run_submodule_example_tcc\n      - name: Build v tools\n        run: v run ci/linux_ci.vsh build_tools_tcc\n      - name: Build v binaries\n        run: v run ci/linux_ci.vsh build_vbinaries_tcc\n      - name: Build benches\n        run: v run ci/linux_ci.vsh build_benches_tcc\n      - name: Run a VSH script\n        run: v run ci/linux_ci.vsh run_vsh_script_tcc\n      - name: Test v tutorials\n        run: v run ci/linux_ci.vsh test_v_tutorials_tcc\n      - name: Build cmd/tools/fast\n        run: v run ci/linux_ci.vsh build_fast_tcc\n      - name: V self compilation with -usecache\n        run: v run ci/linux_ci.vsh v_self_compilation_usecache_tcc\n      - name: Test password input\n        run: v run ci/linux_ci.vsh test_password_input_tcc\n      - name: Test readline\n        run: v run ci/linux_ci.vsh test_readline_tcc\n      - name: Test leak detector\n        run: v run ci/linux_ci.vsh test_leak_detector_tcc\n      - name: Test leak detector not being active for normal compile\n        run: v run ci/linux_ci.vsh test_leak_detector_not_active_tcc\n      - name: native cross compilation to macos\n        run: v run ci/linux_ci.vsh native_cross_compilation_to_macos\n\n  gcc-linux:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 121\n    env:\n      VTEST_SHOW_LONGEST_BY_RUNTIME: 3\n      VTEST_SHOW_LONGEST_BY_COMPTIME: 3\n      VTEST_SHOW_LONGEST_BY_TOTALTIME: 3\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4 && ./v symlink\n      - name: All code is formatted\n        run: v run ci/linux_ci.vsh all_code_is_formatted_gcc\n      - name: Install dependencies for examples and tools\n        run: v run ci/linux_ci.vsh install_dependencies_for_examples_and_tools_gcc\n      - name: Recompile V with -cstrict and gcc\n        run: v run ci/linux_ci.vsh recompile_v_with_cstrict_gcc\n      - name: Valgrind v.c\n        run: v run ci/linux_ci.vsh valgrind_v_c_gcc\n      - name: Run sanitizers\n        run: v run ci/linux_ci.vsh run_sanitizers_gcc\n      - name: v self compilation\n        run: v run ci/linux_ci.vsh v_self_compilation_gcc\n      - name: v self compilation with -usecache\n        run: v run ci/linux_ci.vsh v_self_compilation_usecache_gcc\n      - name: Verify `v test` works\n        run: v run ci/linux_ci.vsh verify_v_test_works_gcc\n      - name: Test pure V math module\n        run: v run ci/linux_ci.vsh test_pure_v_math_module_gcc\n      - name: Self tests\n        run: v run ci/linux_ci.vsh self_tests_gcc\n      - name: Self tests (-prod)\n        run: v run ci/linux_ci.vsh self_tests_prod_gcc\n      - name: Self tests (-cstrict)\n        run: v run ci/linux_ci.vsh self_tests_cstrict_gcc\n      - name: Build examples\n        run: v run ci/linux_ci.vsh build_examples_gcc\n      - name: Build tetris with -autofree\n        run: v run ci/linux_ci.vsh build_tetris_autofree_gcc\n      - name: Build blog tutorial with -autofree\n        run: v run ci/linux_ci.vsh build_blog_autofree_gcc\n      - name: Build option_test.c.v with -autofree\n        run: v run ci/linux_ci.vsh build_option_test_autofree_gcc\n      - name: V self compilation with -parallel-cc\n        run: v run ci/linux_ci.vsh v_self_compilation_parallel_cc_gcc\n      - name: Build modules\n        run: v run ci/linux_ci.vsh build_modules_gcc\n      - name: native machine code generation\n        run: v run ci/linux_ci.vsh native_machine_code_generation_gcc\n      - name: native cross compilation to macos\n        run: v run ci/linux_ci.vsh native_cross_compilation_to_macos\n      - name: compile vdoctor.v with -prod\n        run: v run ci/linux_ci.vsh compile_vdoctor_prod_gcc\n      - name: compile vup.v with -prod\n        run: v run ci/linux_ci.vsh compile_vup_prod_gcc\n\n  clang-linux:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 121\n    env:\n      VFLAGS: -cc clang\n      VTEST_SHOW_LONGEST_BY_RUNTIME: 3\n      VTEST_SHOW_LONGEST_BY_COMPTIME: 3\n      VTEST_SHOW_LONGEST_BY_TOTALTIME: 3\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4 && ./v symlink\n      - name: All code is formatted\n        run: v run ci/linux_ci.vsh all_code_is_formatted_clang\n      - name: Install dependencies for examples and tools\n        run: v run ci/linux_ci.vsh install_dependencies_for_examples_and_tools_clang\n      - name: Recompile V with -cstrict and clang\n        run: v run ci/linux_ci.vsh recompile_v_with_cstrict_clang\n      - name: Valgrind\n        run: v run ci/linux_ci.vsh valgrind_clang\n      - name: Run sanitizers\n        run: v run ci/linux_ci.vsh run_sanitizers_clang\n      - name: v self compilation\n        run: v run ci/linux_ci.vsh v_self_compilation_clang\n      - name: v self compilation with -usecache\n        run: v run ci/linux_ci.vsh v_self_compilation_usecache_clang\n      - name: Verify `v test` works\n        run: v run ci/linux_ci.vsh verify_v_test_works_clang\n      - name: Test pure V math module\n        run: v run ci/linux_ci.vsh test_pure_v_math_module_clang\n      - name: Self tests\n        run: v run ci/linux_ci.vsh self_tests_clang\n      - name: Self tests (vprod)\n        run: v run ci/linux_ci.vsh self_tests_vprod_clang\n      - name: Self tests (-cstrict)\n        run: v run ci/linux_ci.vsh self_tests_cstrict_clang\n      - name: Build examples\n        run: v run ci/linux_ci.vsh build_examples_clang\n      - name: Build examples with -autofree\n        run: v run ci/linux_ci.vsh build_examples_autofree_clang\n      - name: Build modules\n        run: v run ci/linux_ci.vsh build_modules_clang\n      - name: native machine code generation\n        run: v run ci/linux_ci.vsh native_machine_code_generation_clang\n      - name: native cross compilation to macos\n        run: v run ci/linux_ci.vsh native_cross_compilation_to_macos\n"
  },
  {
    "path": ".github/workflows/macos_ci.yml",
    "content": "name: CI macOS\n\non:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/macos_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/macos_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\nconcurrency:\n  group: macos-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  clang-macos:\n    strategy:\n      matrix:\n        os: [macos-14]\n      fail-fast: false\n    runs-on: ${{ matrix.os }}\n    timeout-minutes: 151\n    env:\n      VFLAGS: -cc clang\n      VTEST_SHOW_LONGEST_BY_RUNTIME: 3\n      VTEST_SHOW_LONGEST_BY_COMPTIME: 3\n      VTEST_SHOW_LONGEST_BY_TOTALTIME: 3\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4 && ./v symlink\n      - name: Test symlink\n        run: v run ci/macos_ci.vsh test_symlink\n      - name: v doctor\n        run: v run ci/macos_ci.vsh v_doctor\n      - name: Build v with -prealloc\n        run: v run ci/macos_ci.vsh build_v_with_prealloc\n      - name: Test cross compilation to Linux\n        run: v run ci/macos_ci.vsh test_cross_compilation\n      - name: Test inline assembly on macos\n        run: v run ci/macos_ci.vsh test_inline_assembly\n      - name: Build V with -cstrict\n        run: v run ci/macos_ci.vsh build_with_cstrict\n      - name: All code is formatted\n        run: v run ci/macos_ci.vsh all_code_is_formatted\n      - name: Run sanitizers\n        run: v run ci/macos_ci.vsh run_sanitizers\n      - name: Build V using V\n        run: v run ci/macos_ci.vsh build_using_v\n      - name: Verify `v test` works\n        run: v run ci/macos_ci.vsh verify_v_test_works\n      - name: Install iconv for encoding.iconv\n        run: v run ci/macos_ci.vsh install_iconv\n      - name: Test pure V math module\n        run: v run ci/macos_ci.vsh test_pure_v_math_module\n      - name: Self tests\n        run: v run ci/macos_ci.vsh self_tests\n      - name: Build examples\n        run: v run ci/macos_ci.vsh build_examples\n      - name: Build tetris with -autofree\n        run: v run ci/macos_ci.vsh build_tetris_autofree\n      - name: Build blog tutorial with -autofree\n        run: v run ci/macos_ci.vsh build_blog_autofree\n      - name: Build examples with -prod\n        run: v run ci/macos_ci.vsh build_examples_prod\n      - name: Build examples with V build with tcc\n        run: v run ci/macos_ci.vsh build_examples_v_compiled_with_tcc\n      ##      - name: V self compilation with -usecache\n      ##        run: v run ci/macos_ci.vsh v_self_compilation_usecache\n      - name: V self compilation with -parallel-cc\n        run: v run ci/macos_ci.vsh v_self_compilation_parallel_cc\n      - name: Test password input\n        run: v run ci/macos_ci.vsh test_password_input\n      - name: Test readline\n        run: v run ci/macos_ci.vsh test_readline\n"
  },
  {
    "path": ".github/workflows/make_sure_ci_run_with_32bit_compiler_test.v",
    "content": "fn test_ci_run_with_32bit_compiler() {\n\t$if x64 && tinyc {\n\t\t// TODO: uncomment that next assert when tcc32 vs tcc64 detection on windows works reliably\n\t\t// assert false\n\t\tassert true\n\t}\n}\n"
  },
  {
    "path": ".github/workflows/make_sure_ci_run_with_64bit_compiler_test.v",
    "content": "fn test_ci_run_with_64bit_compiler() {\n    $if x32 {\n        assert false\n    }\t\n}\n"
  },
  {
    "path": ".github/workflows/module_docs_ci.yml",
    "content": "name: vlib modules CI\n\non:\n  pull_request:\n    paths:\n      - 'vlib/**.v'\n      - 'vlib/**.md'\n      - 'cmd/tools/vdoc/**.v'\n      - 'cmd/tools/vdoc/theme/**.js'\n      - 'cmd/tools/vdoc/theme/**.css'\n      - 'cmd/tools/vdoc/theme/**.svg'\n      - 'cmd/tools/vdoc/theme/**.html'\n      - '**/module_docs_ci.yml'\n  push:\n    paths:\n      - 'vlib/**.v'\n      - 'vlib/**.md'\n      - 'cmd/tools/vdoc/**.v'\n      - 'cmd/tools/vdoc/theme/**.js'\n      - 'cmd/tools/vdoc/theme/**.css'\n      - 'cmd/tools/vdoc/theme/**.svg'\n      - 'cmd/tools/vdoc/theme/**.html'\n      - '**/module_docs_ci.yml'\n\n# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.\n# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.\nconcurrency:\n  group: module_docs-${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: ${{ !contains(github.ref, 'master')}}\n\njobs:\n  build-module-docs:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4 && ./v symlink\n      - name: Update packages, before running apt install\n        run: .github/workflows/disable_azure_mirror.sh && v retry -- sudo apt update -y -qq\n      - name: Install dependencies (some modules wrap C libs)\n        run: v retry -- sudo apt install --quiet -y libpq-dev\n          libsodium-dev libasound2-dev libssl-dev \\\n          sqlite3 libsqlite3-dev libfreetype6-dev \\\n          libx11-dev libxi-dev freeglut3-dev \\\n          libgl1-mesa-dri libxcursor-dev libgl-dev libxrandr-dev libegl-dev\n      - name: Install markdown from vpm\n        run: v retry -- v install markdown\n      - name: Test v doc\n        run: VJOBS=1 ./v test cmd/tools/vdoc/\n      - name: Build module documentation and check the examples in the comments\n        run: VJOBS=1 ./v doc -m -f html -unsafe-run-examples -time vlib/\n      - name: Deploy docs to vercel\n        if: github.event_name == 'push' && github.repository == 'vlang/v' && github.ref == 'refs/heads/master'\n        run: npx vercel --confirm --prod --name vmodules --token ${{ secrets.VERCEL_TOKEN }} vlib/_docs/ || true\n"
  },
  {
    "path": ".github/workflows/module_docs_lint.yml",
    "content": "name: Code CI vlib modules\n\non:\n  push:\n    paths:\n      - '**/cmd/tools/vdoc/theme/**'\n  pull_request:\n    paths:\n      - '**/cmd/tools/vdoc/theme/**'\n\njobs:\n  lint-module-docs:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - name: Check Formatting\n        uses: creyD/prettier_action@v4.6\n        with:\n          prettier_options: --check cmd/tools/vdoc/theme\n"
  },
  {
    "path": ".github/workflows/more_extensive_but_slower_tests_ci.yml",
    "content": "name: More extensive but slower tests\n\non:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/more_extensive_but_slower_tests_ci.yml'\n      - 'examples/**'\n      - 'cmd/tools/**'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/more_extensive_but_slower_tests_ci.yml'\n      - 'examples/**'\n      - 'cmd/tools/**'\n\nconcurrency:\n  group: slower_tests-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  more-tests:\n    strategy:\n      matrix:\n        os: [ubuntu-latest, macos-14, windows-latest]\n    runs-on: ${{ matrix.os }}\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Build V\n        if: runner.os != 'Windows'\n        run: make -j4 && ./v symlink\n      - name: Build V (Windows)\n        if: runner.os == 'Windows'\n        run: ./make.bat && ./v symlink\n\n      - name: Run additional crypto tests\n        run: |\n          v retry -- git clone --depth 1 https://github.com/vlang/slower_tests\n          v test slower_tests/\n"
  },
  {
    "path": ".github/workflows/native_backend_ci.yml",
    "content": "name: native backend CI\n\non:\n  push:\n    paths:\n      - '!**'\n      - '!**.md'\n      - 'vlib/v/gen/native/'\n      - 'cmd/tools/builders/**.v'\n      - 'vlib/builtin/**.v'\n      - 'vlib/v/ast/**.v'\n      - 'vlib/v/scanner/**.v'\n      - 'vlib/v/parser/**.v'\n      - 'vlib/v/checker/**.v'\n      - 'vlib/v/gen/c/**.v'\n      - 'vlib/v/builder/**.v'\n      - 'vlib/v/cflag/**.v'\n      - 'vlib/v/live/**.v'\n      - 'vlib/v/util/**.v'\n      - 'vlib/v/markused/**.v'\n      - 'vlib/v/preludes/**.v'\n      - 'vlib/v/gen/native/**.v'\n      - 'vlib/v/gen/native/tests/**.v'\n      - '.github/workflows/native_backend_ci.yml'\n  pull_request:\n    paths:\n      - '!**'\n      - '!**.md'\n      - 'vlib/v/gen/native/'\n      - 'cmd/tools/builders/**.v'\n      - 'vlib/builtin/**.v'\n      - 'vlib/v/ast/**.v'\n      - 'vlib/v/scanner/**.v'\n      - 'vlib/v/parser/**.v'\n      - 'vlib/v/checker/**.v'\n      - 'vlib/v/gen/c/**.v'\n      - 'vlib/v/builder/**.v'\n      - 'vlib/v/cflag/**.v'\n      - 'vlib/v/live/**.v'\n      - 'vlib/v/util/**.v'\n      - 'vlib/v/markused/**.v'\n      - 'vlib/v/preludes/**.v'\n      - 'vlib/v/gen/native/**.v'\n      - 'vlib/v/gen/native/tests/**.v'\n      - '.github/workflows/native_backend_ci.yml'\n\nconcurrency:\n  group: native_backend-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  native-backend-ubuntu:\n    runs-on: ubuntu-24.04\n    env:\n      VJOBS: 1\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make && ./v symlink\n      - name: Install linker\n        run: v retry -- sudo apt -qq install binutils\n      - name: Rebuild V with -g, for better stacktraces on compiler panics\n        run: v -g self\n      - name: Run the native backend tests serially with more details\n        run: v test vlib/v/gen/native/\n\n  native-backend-windows:\n    runs-on: windows-2022\n    env:\n      VJOBS: 1\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V (Windows)\n        run: ./make.bat && ./v symlink\n      - name: Rebuild V with -g, for better stacktraces on compiler panics\n        run: v -g self\n      - name: Run the native backend tests serially with more details\n        run: v test vlib/v/gen/native/\n"
  },
  {
    "path": ".github/workflows/openbsd_ci.yml",
    "content": "name: CI OpenBSD\n\non:\n  workflow_dispatch:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - 'cmd/tools/**'\n      - '!**/openbsd_ci.yml'\n      - '!ci/openbsd_ci.vsh'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - 'cmd/tools/**'\n      - '!**/openbsd_ci.yml'\n      - '!ci/openbsd_ci.vsh'\n      - '!cmd/tools/builders/**.v'\n\n### See https://github.com/cross-platform-actions/action\n### for a description of the used fields here\n\njobs:\n  tcc-openbsd:\n    runs-on: ubuntu-latest\n    timeout-minutes: 30\n    steps:\n      - uses: actions/checkout@v6\n      - name: Tests on OpenBSD with tcc\n        id: tests-openbsd-tcc\n        uses: cross-platform-actions/action@v0.32.0\n        with:\n          operating_system: openbsd\n          version: '7.8'\n          memory: 4G\n          shell: sh\n          sync_files: runner-to-vm\n          run: |\n            sudo pkg_add git sqlite3 gmake boehm-gc libiconv\n            # Install packages needed to build examples\n            sudo pkg_add mariadb-client postgresql-client\n            # Mandatory: hostname not set in VM => some tests fail\n            sudo hostname -s openbsd-ci\n            echo \"### OS infos\"\n            uname -a\n            git config --global --add safe.directory .\n            echo \"### Build V\"\n            gmake\n            sudo ./v symlink\n            export VTEST_SHOW_LONGEST_BY_RUNTIME=3\n            export VTEST_SHOW_LONGEST_BY_COMPTIME=3\n            export VTEST_SHOW_LONGEST_BY_TOTALTIME=3\n            export VFLAGS='-cc tcc -no-retry-compilation'\n            ./v run ci/openbsd_ci.vsh all\n\n  clang-openbsd:\n    runs-on: ubuntu-latest\n    timeout-minutes: 30\n    steps:\n      - uses: actions/checkout@v6\n      - name: Tests on OpenBSD with clang\n        id: tests-openbsd-clang\n        uses: cross-platform-actions/action@v0.32.0\n        with:\n          operating_system: openbsd\n          version: '7.8'\n          memory: 4G\n          shell: sh\n          sync_files: runner-to-vm\n          run: |\n            sudo pkg_add git sqlite3 gmake boehm-gc libiconv\n            # Install packages needed to build examples\n            sudo pkg_add mariadb-client postgresql-client\n            # Mandatory: hostname not set in VM => some tests fail\n            sudo hostname -s openbsd-ci\n            echo \"### OS infos\"\n            uname -a\n            git config --global --add safe.directory .\n            echo \"### Build V\"\n            gmake\n            sudo ./v symlink\n            export VTEST_SHOW_LONGEST_BY_RUNTIME=3\n            export VTEST_SHOW_LONGEST_BY_COMPTIME=3\n            export VTEST_SHOW_LONGEST_BY_TOTALTIME=3\n            export VFLAGS='-cc clang'\n            ./v run ci/openbsd_ci.vsh all\n"
  },
  {
    "path": ".github/workflows/other_ci.yml",
    "content": "name: Other CI\n\non:\n  workflow_dispatch:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/other_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/other_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\nconcurrency:\n  group: other-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  performance-compare-with-master:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 30\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n      - name: Environment info\n        run: echo \"$VFLAGS $GITHUB_SHA $GITHUB_REF\"\n      - name: Name the local git branch\n        run: git checkout -b the_v_pr_branch\n      - name: Build local v\n        run: make && ./v symlink\n      - name: V version\n        run: ./v version\n      - name: Build the repeat tool\n        run: ./v cmd/tools/vrepeat.v\n      - name: Run compare_pr_to_master.v\n        run: VREPEAT_SILENT=1 ./v run .github/workflows/compare_pr_to_master.v\n\n  prevent-gpl-licenses:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    steps:\n      - name: Checkout V ${{ github.head_ref }}\n        uses: actions/checkout@v6\n        with:\n          path: v\n      - name: Checkout V master\n        uses: actions/checkout@v6\n        with:\n          repository: vlang/v\n          path: vmaster\n      - name: Detect potentially added GPL licensed code\n        run: |\n          gpl_search_cmd=\"grep 'GPL' -r --exclude-dir=.git --exclude=*.yml --exclude=*.md --exclude=*.vv --exclude=*_test.v .\"\n          cd vmaster\n          eval \"$gpl_search_cmd\" > ../gpl_res_vmaster\n          cd ../v\n          eval \"$gpl_search_cmd\" > ../gpl_res_vnew\n          cd ..\n          diff -d -a -U 2 --color=always gpl_res_vmaster gpl_res_vnew\n\n  code-formatting:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    env:\n      VFLAGS: -cc gcc\n    steps:\n      - uses: actions/checkout@v6\n      - name: Environment info\n        run: echo \"$VFLAGS $GITHUB_SHA $GITHUB_REF\"\n      - name: Build local v\n        run: make -j4 && ./v symlink\n      - name: v test-cleancode\n        run: ./v -silent test-cleancode\n      - name: v test-fmt\n        run: ./v -silent test-fmt\n\n  performance-regressions:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    env:\n      VFLAGS: -cc gcc\n    steps:\n      - uses: actions/checkout@v6\n      - name: Environment info\n        run: echo \"$VFLAGS $GITHUB_SHA $GITHUB_REF\"\n      - name: Build local v\n        run: make -j4 && ./v symlink\n      - name: Clone & Build previous vmaster/v\n        run: |\n          ./v retry -- git clone --depth=1 https://github.com/vlang/v vmaster/\n          (cd vmaster; make -j4)\n      - name: V versions\n        run: ./v version && ./vmaster/v version\n      - name: Build the repeat tool\n        run: ./v cmd/tools/vrepeat.v\n      - name: Repeat -o hw.c examples/hello_world.v\n        run: ./v repeat --max_time 251 --series 3 --runs 20 --nmins 2 --nmaxs 5 --warmup 3 --fail_percent 10 -t 'cd {T} ; ./v -o hw.c examples/hello_world.v' . ./vmaster\n      - name: Repeat -o v.c cmd/v\n        run: ./v repeat --max_time 1731 --series 3 --runs 20 --nmins 2 --nmaxs 5 --warmup 3 --fail_percent 10 -t 'cd {T} ; ./v -o v.c cmd/v' . ./vmaster\n\n  misc-tooling:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    env:\n      VFLAGS: -cc tcc -no-retry-compilation\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 10\n      - name: Build v\n        run: make -j4 && ./v symlink\n\n      - name: Install dependencies\n        run: |\n          .github/workflows/disable_azure_mirror.sh\n          ./v retry -- sudo apt update\n          ./v retry -- sudo apt install --quiet -y libsodium-dev libssl-dev sqlite3 libsqlite3-dev postgresql libpq-dev valgrind\n          ./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev xfonts-75dpi xfonts-base libegl-dev\n          ./v retry -- sudo apt install --quiet -y g++-9 g++-10\n\n      - name: g++-9 version\n        run: g++-9 --version\n      - name: V self compilation with g++ and -std=c++11\n        run: ./v -cc g++-9 -no-std -cflags -std=c++11 -o v2 cmd/v && ./v2 -cc g++-9 -no-std -cflags -std=c++11 -o v3 cmd/v\n\n      - name: g++-10 version\n        run: g++-10 --version\n      - name: V self compilation with g++ and -std=c++20\n        run: ./v -cc g++-10 -no-std -cflags -std=c++20 -o v2 cmd/v && ./v2 -cc g++-10 -no-std -cflags -std=c++20 -o v3 cmd/v\n\n      # NB: this does not mean it runs, but at least keeps it from regressing\n      - name: Ensure V can be compiled with -autofree\n        run: ./v -autofree cmd/v\n\n      - name: Ensure V can be compiled with -no-closures\n        run: ./v -no-closures cmd/v\n\n      - name: Shader examples can be built\n        run: |\n          .github/workflows/compile_shaders_in_examples.sh\n          ./v should-compile-all examples/sokol/*.v examples/sokol/0?*/*.v\n\n  parser-silent:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 30\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build local v\n        run: |\n          make -j4 && ./v symlink\n          ./v -g -d trace_parse_stmt cmd/tools/vtest-parser.v\n      - name: Install zzuf\n        run: ./v retry -- sudo apt install -qq zzuf\n      - name: Run test-parser\n        run: |\n          ./v test-parser --show_source --linear examples/hello_world.v\n          ./v test-parser --show_source --linear examples/hanoi.v\n          ./v test-parser --show_source --linear examples/fibonacci.v\n          ./v test-parser --show_source --linear examples/cli.v\n          ./v test-parser --show_source --linear examples/json.v\n          ./v test-parser --show_source --linear examples/vmod.v\n          ./v test-parser --show_source --linear examples/regex/regex_example.v\n          ./v test-parser --show_source --linear examples/2048/2048.v\n\n      - name: Run test-parser over fuzzed files\n        run: |\n          zzuf -R '\\x00-\\x20\\x7f-\\xff' -r0.01 < examples/hello_world.v > examples/hello_world_fuzz.v\n          zzuf -R '\\x00-\\x20\\x7f-\\xff' -r0.01 < examples/hanoi.v > examples/hanoi_fuzz.v\n          zzuf -R '\\x00-\\x20\\x7f-\\xff' -r0.01 < examples/fibonacci.v > examples/fibonacci_fuzz.v\n          zzuf -R '\\x00-\\x20\\x7f-\\xff' -r0.01 < examples/cli.v > examples/cli_fuzz.v\n          zzuf -R '\\x00-\\x20\\x7f-\\xff' -r0.01 < examples/json.v > examples/json_fuzz.v\n          zzuf -R '\\x00-\\x20\\x7f-\\xff' -r0.01 < examples/vmod.v > examples/vmod_fuzz.v\n          zzuf -R '\\x00-\\x20\\x7f-\\xff' -r0.01 < examples/regex/regex_example.v > examples/regex_example_fuzz.v\n          zzuf -R '\\x00-\\x20\\x7f-\\xff' -r0.01 < examples/2048/2048.v > examples/2048/2048_fuzz.v\n          ./v test-parser --show_source --linear examples/hello_world_fuzz.v\n          ./v test-parser --show_source --linear examples/fibonacci_fuzz.v\n          ./v test-parser --show_source --linear examples/hanoi_fuzz.v\n          ./v test-parser --show_source --linear examples/cli_fuzz.v\n          ./v test-parser --show_source --linear examples/json_fuzz.v\n          ./v test-parser --show_source --linear examples/vmod_fuzz.v\n          ./v test-parser --show_source --linear examples/regex_example_fuzz.v\n          ./v test-parser --show_source --linear examples/2048/2048_fuzz.v\n"
  },
  {
    "path": ".github/workflows/paths_ci.yml",
    "content": "name: Path Testing CI\n\non:\n  workflow_dispatch:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/paths_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/paths_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\nconcurrency:\n  group: paths-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  space-paths-linux:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          persist-credentials: false\n          path: '你好 my $path, @с интервали'\n      - name: Build V\n        run: |\n          # shellcheck disable=SC2016\n          echo '你好 my $path, @с интервали'\n          ls -la\n          # shellcheck disable=SC2016\n          cd '你好 my $path, @с интервали'\n          ls -la\n          make\n      - name: v doctor\n        run: |\n          # shellcheck disable=SC2016\n          cd '你好 my $path, @с интервали'\n          ./v doctor\n      - name: v tests\n        run: |\n          # shellcheck disable=SC2016\n          cd '你好 my $path, @с интервали'\n          ./v test vlib/builtin vlib/os\n\n  space-paths-macos:\n    runs-on: macos-14\n    timeout-minutes: 30\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          path: '你好 my $path, @с интервали'\n          persist-credentials: false\n      - name: Build V\n        run: |\n          # shellcheck disable=SC2016\n          echo '你好 my $path, @с интервали'\n          ls -la\n          # shellcheck disable=SC2016\n          cd '你好 my $path, @с интервали'\n          ls -la\n          make\n          ## prebuild cmd/tools/builders/js_builder, to minimise the\n          ## chances of a sporadic \"Killed\" when running the tests later\n          ./v -b js run examples/hello_world.v\n      - name: v doctor\n        run: |\n          # shellcheck disable=SC2016\n          cd '你好 my $path, @с интервали'\n          ./v doctor\n      - name: v tests\n        run: |\n          # shellcheck disable=SC2016\n          cd '你好 my $path, @с интервали'\n          ./v test vlib/builtin vlib/os\n\n  space-paths-windows:\n    runs-on: windows-2022\n    timeout-minutes: 30\n    ## NB: the following paths do not work for now:\n    ##### MY_V_PATH: '你好 my $path, @с интервали'\n    ##### MY_V_PATH: 'path with some $punctuation, and some spaces '\n    ## tcc has a problem interpreting paths with non latin letters in them,\n    ## by default, but that can be solved with passing -Bthirdparty/tcc\n    ## but after that V fails self building with:\n    ####### builder error: cannot write to folder\n    ####### D:\\a\\v\\v\\你好 my $path, @с интервали: No such file or directory\n    ## and that happens even for gcc builds, not just tcc ones\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          path: 'path with some $punctuation, and some spaces'\n          persist-credentials: false\n      - name: Build V\n        run: |\n          echo 'path with some $punctuation, and some spaces'\n          dir\n          cd 'path with some $punctuation, and some spaces'\n          dir\n          .\\make.bat -tcc\n      - name: v doctor\n        run: |\n          cd 'path with some $punctuation, and some spaces'\n          ./v doctor\n      - name: v tests\n        run: |\n          cd 'path with some $punctuation, and some spaces'\n          ./v test vlib/builtin vlib/os\n"
  },
  {
    "path": ".github/workflows/periodic_ci.yml",
    "content": "name: Periodic CI\n\non:\n  schedule:\n    - cron: '0 */6 * * *'\n  push:\n    paths:\n      - '**/periodic_ci.yml'\n  pull_request:\n    paths:\n      - '**/periodic_ci.yml'\n\njobs:\n  periodic-network:\n    strategy:\n      matrix:\n        include:\n          - os: ubuntu-latest\n            cc: tcc\n          - os: windows-latest\n            cc: msvc\n          - os: macos-latest\n            cc: clang\n      fail-fast: false\n    runs-on: ${{ matrix.os }}\n    if: github.event_name != 'schedule' || (github.ref == 'refs/heads/master' && github.repository == 'vlang/v')\n    timeout-minutes: 30\n    env:\n      VFLAGS: -cc ${{ matrix.cc }}\n      V_CI_PERIODIC: 1\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build\n        if: runner.os != 'Windows'\n        run: make -j4 && ./v -showcc -o v cmd/v && ./v doctor\n      - name: Build V (Windows)\n        if: runner.os == 'Windows'\n        run: ./make.bat -msvc && ./v -o v2.exe cmd/v && ./v2 -showcc -o v.exe cmd/v && ./v doctor\n      - name: Test\n        run: ./v -d network -silent test-self vlib/net\n"
  },
  {
    "path": ".github/workflows/prebuilt.yml",
    "content": "name: Test prebuilt binaries\n\non:\n  workflow_dispatch:\n  release:\n    types: [edited, published]\n\njobs:\n  prebuilt-linux:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 5\n    steps:\n      - name: Download V\n        run: |\n          .github/workflows/retry.sh wget https://github.com/vlang/v/releases/latest/download/v_linux.zip\n          unzip v_linux.zip\n          cd v\n          ./v -version\n      - name: Test V\n        run: |\n          cd v\n          ./v run examples/hello_world.v\n          ./v -showcc -gc none -cc tcc -no-retry-compilation run examples/hello_world.v\n\n  prebuilt-macos-arm64:\n    ## macos-14 is a m1 runner\n    runs-on: macos-14\n    timeout-minutes: 5\n    steps:\n      - name: Download V\n        run: |\n          .github/workflows/retry.sh wget https://github.com/vlang/v/releases/latest/download/v_macos_arm64.zip\n          unzip v_macos_arm64.zip\n          cd v\n          ./v -version\n      - name: Test V\n        run: |\n          cd v\n          ./v run examples/hello_world.v\n          ./v -showcc -gc none -cc tcc -no-retry-compilation run examples/hello_world.v\n\n  prebuilt-macos-x86_64:\n    runs-on: macos-latest\n    timeout-minutes: 5\n    steps:\n      - name: Download V\n        run: |\n          .github/workflows/retry.sh wget https://github.com/vlang/v/releases/latest/download/v_macos_x86_64.zip\n          unzip v_macos_x86_64.zip\n          cd v\n          ./v -version\n      - name: Test V\n        run: |\n          cd v\n          ./v run examples/hello_world.v\n\n  prebuilt-windows:\n    runs-on: windows-latest\n    timeout-minutes: 5\n    steps:\n      - name: Download V\n        run: |\n          curl -L https://github.com/vlang/v/releases/latest/download/v_windows.zip -o v_windows.zip\n          unzip .\\v_windows.zip\n          cd v\n          .\\v.exe -version\n      - name: Test V\n        run: |\n          cd v\n          .\\v.exe run .\\examples\\hello_world.v\n          .\\v.exe -showcc -gc none -cc tcc -no-retry-compilation run .\\examples/hello_world.v\n"
  },
  {
    "path": ".github/workflows/puzzle_vibes_ci.yml",
    "content": "name: Shy and PV CI\n\non:\n  workflow_dispatch:\n  push:\n    paths:\n      - 'vlib/v/checker/**.v'\n      - 'vlib/v/gen/c/**.v'\n      - 'thirdparty/**'\n      - 'cmd/tools/builders/**.v'\n      - 'cmd/tools/vshader.v'\n      - '**/puzzle_vibes_ci.yml'\n      - '!**_test.v'\n      - '!**.md'\n  pull_request:\n    paths:\n      - 'vlib/v/checker/**'\n      - 'vlib/v/gen/c/**'\n      - 'thirdparty/**'\n      - 'cmd/tools/builders/**.v'\n      - 'cmd/tools/vshader.v'\n      - '**/puzzle_vibes_ci.yml'\n      - '!**_test.v'\n      - '!**.md'\n\nconcurrency:\n  group: puzzle_vibes-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  v-compiles-puzzle-vibes:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n      - uses: ./.github/actions/cache-apt-packages-action\n\n      - name: Build V\n        run: make && ./v symlink\n\n      - name: Install & Setup SDL\n        run: v retry -- v install sdl && v ~/.vmodules/sdl/setup.vsh\n\n      - name: Install Shy\n        run: v retry -- v install https://github.com/larpon/shy\n\n      - name: Clone Puzzle Vibes\n        run: v retry -- git clone https://github.com/larpon/puzzle_vibes/\n\n      - name: Check PV compiles with -g\n        run: cd puzzle_vibes && v -g .\n\n      - name: Check PV compiles\n        run: cd puzzle_vibes && v .\n\n      - name: Check PV compiles with -prod\n        run: cd puzzle_vibes && v -prod    -no-prod-options .\n\n      - name: Check PV compiles with -prod and -g\n        run: cd puzzle_vibes && v -prod -g -no-prod-options .\n"
  },
  {
    "path": ".github/workflows/release_ci.yml",
    "content": "name: Release CI\n\non:\n  workflow_dispatch:\n  pull_request:\n    paths:\n      - '.github/workflows/release_ci.yml'\n  push:\n    paths:\n      - '.github/workflows/release_ci.yml'\n    tags:\n      - weekly.**\n      - 0.**\n\nconcurrency:\n  group: release-${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: ${{ github.ref_type != 'tag' }}\n\npermissions:\n  contents: write\n\njobs:\n  release-build:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os:\n          [\n            ubuntu-22.04,\n            ubuntu-22.04-arm,\n            macos-15-intel,\n            macos-15,\n            windows-latest,\n          ]\n        include:\n          - os: ubuntu-22.04\n            cc: gcc\n            target: linux\n            artifact: v_linux.zip\n          - os: ubuntu-22.04-arm\n            cc: gcc\n            target: linux_arm64\n            artifact: v_linux_arm64.zip\n          - os: macos-15-intel\n            cc: clang\n            target: macos_x86_64\n            artifact: v_macos_x86_64.zip\n          - os: macos-15\n            cc: clang\n            target: macos_arm64\n            artifact: v_macos_arm64.zip\n          - os: windows-latest\n            cc: msvc\n            target: windows\n            artifact: v_windows.zip\n      fail-fast: false\n    steps:\n      - uses: actions/checkout@v6\n      - name: Compile release binaries\n        if: runner.os != 'Windows'\n        run: |\n          make\n          ./v -cc ${{ matrix.cc }} ${{ matrix.cflags }} -prod -o v cmd/v\n          ./v -cc ${{ matrix.cc }} ${{ matrix.cflags }} -prod cmd/tools/vup.v\n          ./v -cc ${{ matrix.cc }} ${{ matrix.cflags }} -prod cmd/tools/vdoctor.v\n      - name: Compile release binaries (Windows)\n        if: runner.os == 'Windows'\n        run: |\n          ./make.bat -msvc\n          ./v -prod -cc msvc -o cmd/vprod.exe cmd/v\n          ./v -prod -cc msvc cmd/tools/vup.v\n          ./v -prod -cc msvc cmd/tools/vdoctor.v\n          del ./*.exe\n          del ./*.tmp.obj\n          move cmd/vprod.exe v.exe\n      - name: Prepare artifact\n        shell: bash\n        run: |\n          if [[ ${{ matrix.os }} == 'macos-14' ]]; then\n            rm -rf thirdparty/tcc\n            git clone --branch thirdparty-macos-arm64 --depth=1 https://github.com/vlang/tccbin thirdparty/tcc\n          fi\n          # Remove excluded\n          if [[ $RUNNER_OS == 'Windows' ]]; then\n            find . -type f \\( -name \"*.ilk\" -o -name \"*.pdb\" \\) -exec rm -rf {} +\n            rm -rf v_old.exe\n          fi\n          find . -type d -name \".git\" -exec rm -rf {} +\n          rm -rf vc/\n          rm -rf v_old\n          rm -rf vlib/v/tests/bench/gcboehm/*.svg.xz\n      - name: Create ZIP archive\n        shell: bash\n        run: |\n          cd ..\n          if [[ $RUNNER_OS == 'Windows' ]]; then\n            7z a -tzip ${{ matrix.artifact }} v/\n          else\n            zip -r9 --symlinks ${{ matrix.artifact }} v/\n          fi\n          zipinfo ${{ matrix.artifact }}\n          mv ${{ matrix.artifact }} v/\n          cd v/\n      - name: Create artifact\n        uses: actions/upload-artifact@v7\n        with:\n          name: ${{ matrix.target }}\n          path: ${{ matrix.artifact }}\n\n  release-publish:\n    if: github.ref_type == 'tag'\n    needs: release-build\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/download-artifact@v8\n      - name: Create release\n        uses: ncipollo/release-action@v1\n        with:\n          artifacts: |\n            ~/work/v/v/windows/v_windows.zip\n            ~/work/v/v/linux/v_linux.zip\n            ~/work/v/v/linux_arm64/v_linux_arm64.zip\n            ~/work/v/v/macos_arm64/v_macos_arm64.zip\n            ~/work/v/v/macos_x86_64/v_macos_x86_64.zip\n          tag: ${{ github.ref_name }}\n          name: ${{ github.ref_name }}\n          draft: false\n          prerelease: false\n"
  },
  {
    "path": ".github/workflows/retry.sh",
    "content": "#!/usr/bin/env bash\n\ncmd=$@\n\nfunction elog() {\n\tmessage=$1\n\tprintf \"%(%Y/%m/%d %H:%M:%S)T | retry.sh $1\\n\"\n}\n\ndeclare -i iteration=0\ndeclare -i max_iterations=9\nfor((iteration=1;iteration<=max_iterations;iteration++)); do\n\telog \"iteration: $iteration/$max_iterations, cmd: $cmd\"\n\tif $cmd; then\n\t\texit 0\n\tfi\n\telog \"command failed, retrying ...\";\n\tsleep 1;\ndone;\n\nelog \"failed doing $max_iterations iterations of command: $cmd\"\nexit 1\n"
  },
  {
    "path": ".github/workflows/riscv64_linux_ci.yml",
    "content": "name: riscv64 CI\n\non:\n  workflow_dispatch:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/riscv64_linux_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/riscv64_linux_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\njobs:\n  riscv64_linux:\n    # The host should always be Linux\n    runs-on: ubuntu-24.04\n    timeout-minutes: 30\n    name: Build on ubuntu-24.04 riscv64\n    steps:\n      - uses: actions/checkout@v6\n      - uses: uraimo/run-on-arch-action@v3\n        name: Run commands\n        id: runcmd\n        with:\n          arch: riscv64\n          distro: ubuntu24.04\n          base_image: --platform=linux/riscv64 riscv64/ubuntu:24.04\n          # The token tag here is not required, but speeds up builds,\n          # by allowing caching of the installed dependencies, which is ~2.5min:\n          githubToken: ${{ github.token }}\n          shell: /bin/bash\n          install: |\n            apt-get update -q -y\n            apt-get install -q -y make gcc git file coreutils binutils\n          run: |\n            uname -a\n            make --version\n            gcc --version\n            ls -la\n            export LDFLAGS=\"-latomic\"\n            export VFLAGS=\"-gc none -no-retry-compilation -cc cc\"\n            make\n            file ./v\n            ls -la ./v\n            ./v test vlib/builtin vlib/os vlib/encoding/binary\n            ./v test vlib/v/slow_tests/assembly\n            VTEST_ONLY=closure ./v test vlib/v/tests\n"
  },
  {
    "path": ".github/workflows/run_sanitizers.sh",
    "content": "#!/usr/bin/env bash\n\nexport PS4='\\033[0;33m+ >>>>> (${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }\\033[0m'\n\nset -xe\n\necho \"    Setup environment ...\"\nexport DEBUG_OPTS=${DEBUG_OPTS:-\"-keepc -cg -cflags -fno-omit-frame-pointer\"}\nexport VFLAGS=${VFLAGS:-\"-cc clang\"}\nv version\nv -show-c-output -cflags --version -e ';' || true\n\necho \"    Compile and run sanitizers ...\"\n\nv ${VFLAGS} ${DEBUG_OPTS} -o v2 cmd/v -cflags -fsanitize=memory\nUBSAN_OPTIONS=\"print_stacktrace=1:halt_on_error=1\" ./v2 -o v.c cmd/v\n\nv ${VFLAGS} ${DEBUG_OPTS} -o v3 cmd/v -cflags -fsanitize=thread\nTSAN_OPTIONS=\"suppressions=.github/workflows/run_sanitizers_thread.suppressions\" UBSAN_OPTIONS=\"print_stacktrace=1:halt_on_error=1\" ./v3 -o v.c cmd/v\n\nv ${VFLAGS} ${DEBUG_OPTS} -o v4 cmd/v -cflags -fsanitize=undefined\nUBSAN_OPTIONS=\"suppressions=.github/workflows/run_sanitizers_undefined.suppressions:print_stacktrace=1:halt_on_error=1\" ./v4 -o v.c cmd/v\n\nv ${VFLAGS} ${DEBUG_OPTS} -o v5 cmd/v -cflags -fsanitize=address,pointer-compare,pointer-subtract\nASAN_OPTIONS=\"detect_leaks=0\" UBSAN_OPTIONS=\"print_stacktrace=1:halt_on_error=1\" ./v5 -o v.c cmd/v\n"
  },
  {
    "path": ".github/workflows/run_sanitizers_leak.suppressions",
    "content": "# websocket tests\nleak:mbedtls_ssl_setup\n\n# sqlite tests\nleak:*sqlite*\n\n# v\nleak:v__*\nleak:os__*\nleak:string__plus\nleak:malloc_uncollectable\nleak:new_array_from_c_array\nleak:_vinit\n"
  },
  {
    "path": ".github/workflows/run_sanitizers_thread.suppressions",
    "content": "## See https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions\n## and https://clang.llvm.org/docs/ThreadSanitizer.html\n## The sync__stdatomic__add_i64 and sync__stdatomic__sub_i64 suppressions below, are needed for clang-10 to clang-12; clang-18 is fine without them\nrace:sync__stdatomic__add_i64\nrace:sync__stdatomic__sub_i64\n"
  },
  {
    "path": ".github/workflows/run_sanitizers_undefined.suppressions",
    "content": "## See https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html\n## Most of the supressed functions here use asserts, that in turn use an indirection through an interface. TODO: if that is solved, most of these can be removed.\n## Usually they contain a __test_ in their name, but not always (see the x.ttf ones like vlib/x/ttf/ttf_test.v ).\n## TODO: extract the common part of the assertions to a VDO_ function (1 for pass and 1 for failure), so that they can be whitelisted here just once.\nfunction:map_exists\nfunction:map_get\nfunction:IError_str\n\nshift-exponent:math__bits__rotate_left_64\nshift-exponent:math__bits__div_64\nfunction:math__big__Integer_general_radix_str\nfunction:math__big__Integer_div_mod_internal\nfunction:math__bits__test_bits\nfunction:math__bits__test_div_64_edge_cases\nfunction:math__test_nan\n\nalignment:rand__read_64\nfunction:rand__internal_ulid_at_millisecond\nfunction:rand__internal_string_from_set\nfunction:rand__internal_uuid_v4\nfunction:rand__deinit\nfunction:rand__read_internal\nfunction:rand__read_64\nfunction:rand__PRNG_f64\n\nfunction:rand__cuid2__test_cuid2\n\nfunction:sync__pool__process_in_thread\nfunction:sync__Once_do_slow_with_param\n\nfunction:v__type_resolver__TypeResolver_resolve_fn_generic_args\nfunction:v__type_resolver__TypeResolver_unwrap_generic_expr\nfunction:v__type_resolver__TypeResolver_get_type\n\n## these have asserts in them, and trigger due to the used indirection; TODO: remove them, when a more general solution is found for all interfaces\nfunction:x__ttf__TTF_File_get_glyph_offset\nfunction:x__ttf__TTF_File_get_horizontal_metrics\nfunction:x__ttf__TTF_File_glyph_count\nfunction:x__ttf__TTF_File_read_glyph\nfunction:x__ttf__TTF_File_read_simple_glyph\nfunction:x__ttf__TTF_File_read_kern_table\nfunction:x__ttf__TTF_File_read_hhea_table\nfunction:x__ttf__TTF_File_read_cmap_table\nfunction:x__ttf__TTF_File_read_name_table\nfunction:x__ttf__TTF_File_read_head_table\nfunction:x__ttf__TTF_File_read_offset_tables\n\nfunction:net__unix__select_deadline\nfunction:net__select_deadline\nfunction:net__socks__test_parse_ipv4\nfunction:net__http__download_file_with_progress\nfunction:net__http__download_progres_cb\nfunction:net__http__check_headers\nfunction:net__http__test_str\nfunction:net__http__test_int\nfunction:net__http__test_is_valid\nfunction:net__http__test_is_error\nfunction:net__http__test_is_success\nfunction:net__http__test_parse_response_with_weird_cookie\nfunction:net__http__test_parse_response_with_cookies\nfunction:net__http__test_parse_response\nfunction:net__http__test_response_bytestr_1\nfunction:net__http__test_response_bytestr_2\nfunction:net__http__test_parse_large_body\nfunction:net__http__test_multipart_form_body\nfunction:net__http__test_parse_multipart_form2\nfunction:net__http__test_parse_request_no_headers\nfunction:net__http__test_parse_multipart_form\nfunction:net__http__test_parse_form\nfunction:net__http__test_parse_request_line\nfunction:net__http__test_parse_request_body\nfunction:net__http__test_parse_request_two_header_values\nfunction:net__http__test_parse_request_no_headers\nfunction:net__http__test_parse_request_two_headers\nfunction:net__http__test_proxy_fields\nfunction:net__http__test_proxy_headers\nfunction:net__http__test_set_cookie\nfunction:net__http__test_parse_headers\nfunction:net__http__parse_headers_test\nfunction:net__http__test_header_join\nfunction:net__http__test_header_from_map\nfunction:net__http__test_custom_header_from_map\nfunction:net__http__test_render_coerce_canonicalize\nfunction:net__http__test_render_canonicalize\nfunction:net__http__test_render_version\nfunction:net__http__test_coerce_canonicalize_custom\nfunction:net__http__test_coerce_custom\nfunction:net__http__test_coerce_canonicalize\nfunction:net__http__test_coerce\nfunction:net__http__test_custom_values\nfunction:net__http__test_starting_with\nfunction:net__http__test_get_custom\nfunction:net__http__test_contains_custom\nfunction:net__http__test_custom_header\nfunction:net__http__test_delete_header\nfunction:net__http__test_header_delete_not_existing\nfunction:net__http__test_header_delete\nfunction:net__http__test_header_set\nfunction:net__http__test_header_get\nfunction:net__http__test_header_adds_multiple\nfunction:net__http__test_header_new\nfunction:net__test_ip6_str\nfunction:net__test_ip_str\nfunction:net__test_sizes_unix\nfunction:net__test_sizes_ipv4\nfunction:net__test_sizes_ipv6\nfunction:net__test_offsets_unix\nfunction:net__test_offsets_ipv4\nfunction:net__test_offsets_ipv6\nfunction:net__test_sizes_unix_sun_path\nfunction:net__test_diagnostics\nfunction:net__test_ip_port\nfunction:net__websocket__delete_client_cb\nfunction:net__websocket__Server_listen\nfunction:net__websocket__Server_serve_client\nfunction:net__websocket__Server_parse_client_handshake\nfunction:net__websocket__Client_listen\nfunction:net__websocket__Client_send_message_event\nfunction:net__websocket__Client_send_close_event\nfunction:net__websocket__Client_debug_log\nfunction:net__websocket__Client_connect\n\nfunction:io__BufferedReader_fill_buffer\nfunction:io__read_all\n\nfunction:log__info\nfunction:log__debug\nfunction:log__warn\nfunction:log__error\nfunction:log__set_level\nfunction:log__Log_log_stream\nfunction:log__free_logger\n\nfunction:picoev__Picoev_poll_once\nfunction:picoev__Picoev_set_timeout\nfunction:picoev__Picoev_update_events\nfunction:picoev__test_if_all_file_descriptors_are_properly_initialized\n\nfunction:vweb__tests__vweb_test_server__App_index\nfunction:vweb__tests__vweb_test_server__start_in_background\nfunction:vweb__RoutePair_test_param\nfunction:veb__RoutePair_test_param\nfunction:veb__test_load_files_translations\n\n## needed for tests; TODO: move the test specific setup code into its own separate VDO_tests function, so only it can be added here\nfunction:main\n\nfunction:crypto__sha3__test_0_length_hash\nfunction:crypto__sha3__test_0_length_xof\nfunction:crypto__sha3__test_200_length_hash\nfunction:crypto__sha3__test_200_length_xof\n\nfunction:crypto__sha3__test_2_x_24_rounds_on_zero\nfunction:crypto__sha3__test_stepping_functions_on_zero\nfunction:crypto__sha3__test_zero_state\nfunction:crypto__sha3__test_rho_offsets\nfunction:crypto__sha3__test_to_from_bytes\nfunction:crypto__sha3__test_round_constants\n\nfunction:crypto__pem__test_decode_rfc1421\nfunction:crypto__pem__test_decode\nfunction:crypto__pem__test_encode_rfc1421\nfunction:crypto__pem__test_encode\n\nfunction:crypto__hmac__test_hmac_equal\nfunction:crypto__hmac__test_hmac_sha3_224\nfunction:crypto__hmac__test_hmac_sha3_256\nfunction:crypto__hmac__test_hmac_sha3_384\nfunction:crypto__hmac__test_hmac_sha3_512\nfunction:crypto__hmac__test_hmac_blake3_256\nfunction:crypto__hmac__test_hmac_blake2b_160\nfunction:crypto__hmac__test_hmac_blake2b_256\nfunction:crypto__hmac__test_hmac_blake2b_384\nfunction:crypto__hmac__test_hmac_blake2b_512\nfunction:crypto__hmac__test_hmac_blake2s_128\nfunction:crypto__hmac__test_hmac_blake2s_160\nfunction:crypto__hmac__test_hmac_blake2s_224\nfunction:crypto__hmac__test_hmac_blake2s_256\nfunction:crypto__hmac__test_hmac_sha512\nfunction:crypto__hmac__test_hmac_sha384\nfunction:crypto__hmac__test_hmac_sha256\nfunction:crypto__hmac__test_hmac_sha224\nfunction:crypto__hmac__test_hmac_sha1\nfunction:crypto__hmac__test_hmac_md5\n\nfunction:crypto__ed25519__internal__edwards25519__sc_reduce\nfunction:crypto__ed25519__internal__edwards25519__sc_reduce\n"
  },
  {
    "path": ".github/workflows/s390x_linux_ci.yml",
    "content": "name: s390 CI\n\non:\n  workflow_dispatch:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/s390x_linux_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/s390x_linux_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\njobs:\n  s390x_linux:\n    # The host should always be Linux\n    runs-on: ubuntu-22.04\n    timeout-minutes: 30\n    name: Build on ubuntu-22.04 s390x\n    steps:\n      - uses: actions/checkout@v6\n      - uses: uraimo/run-on-arch-action@v3\n        name: Run commands\n        id: runcmd\n        with:\n          arch: s390x\n          distro: ubuntu22.04\n          base_image: --platform=linux/s390x s390x/ubuntu:22.04\n          # The token tag here is not required, but speeds up builds,\n          # by allowing caching of the installed dependencies, which is ~2.5min:\n          githubToken: ${{ github.token }}\n          shell: /bin/bash\n          install: |\n            apt-get update -q -y\n            apt-get install -q -y make gcc git file coreutils binutils\n          run: |\n            uname -a\n            make --version\n            gcc --version\n            ls -la\n            make\n            file ./v\n            ls -la ./v\n            ./v test vlib/builtin vlib/os vlib/encoding/binary\n            ./v test vlib/v/tests/fns/closure_test.v\n"
  },
  {
    "path": ".github/workflows/sanitized_ci.yml",
    "content": "name: Sanitized CI\n\n## Running these jobs is slow (over ~1 hour, sometimes even 2)\n## so we run them only when there is a chance that the generated\n## C code could have changed, or for some critical vlib modules,\n## like `builtin`, `os`, `sync`, where they have demonstrated\n## their usefulness by catching actual very hard to find bugs.\n## The cost of this selective running is delayed feedback when\n## there are bugs in other V modules.\n## The positive is *much faster CI runs* for most V contributors,\n## that make PRs that are not concerning V itself, or the critical\n## V modules.\n\non:\n  workflow_dispatch:\n  push:\n    paths:\n      - '!**'\n      - '!**.md'\n      - '!**.yml'\n      - 'vlib/builtin/**.v'\n      - 'vlib/strconv/**.v'\n      - 'vlib/strings/**.v'\n      - 'vlib/math/**.v'\n      - 'vlib/math/big/**.v'\n      - 'vlib/arrays/**.v'\n      - 'vlib/crypto/ecdsa/**.v'\n      - 'vlib/datatypes/**.v'\n      - 'vlib/os/**.v'\n      - 'vlib/sync/**.v'\n      - 'vlib/v/tests/**.v'\n      - 'vlib/v/ast/**.v'\n      - 'vlib/v/scanner/**.v'\n      - 'vlib/v/parser/**.v'\n      - 'vlib/v/checker/**.v'\n      - 'vlib/v/gen/c/**.v'\n      - 'vlib/v/builder/**.v'\n      - 'vlib/v/cflag/**.v'\n      - 'vlib/v/live/**.v'\n      - 'vlib/v/util/**.v'\n      - 'vlib/v/markused/**.v'\n      - 'vlib/v/preludes/**.v'\n      - 'vlib/v/embed_file/**.v'\n      - 'vlib/x/json2/**.v'\n      - '**/sanitized_ci.yml'\n  pull_request:\n    paths:\n      - '!**'\n      - 'vlib/builtin/**.v'\n      - 'vlib/strconv/**.v'\n      - 'vlib/strings/**.v'\n      - 'vlib/math/**.v'\n      - 'vlib/math/big/**.v'\n      - 'vlib/arrays/**.v'\n      - 'vlib/crypto/ecdsa/**.v'\n      - 'vlib/datatypes/**.v'\n      - 'vlib/os/**.v'\n      - 'vlib/sync/**.v'\n      - 'vlib/v/tests/**.v'\n      - 'vlib/v/ast/**.v'\n      - 'vlib/v/scanner/**.v'\n      - 'vlib/v/parser/**.v'\n      - 'vlib/v/checker/**.v'\n      - 'vlib/v/gen/c/**.v'\n      - 'vlib/v/builder/**.v'\n      - 'vlib/v/cflag/**.v'\n      - 'vlib/v/live/**.v'\n      - 'vlib/v/util/**.v'\n      - 'vlib/v/markused/**.v'\n      - 'vlib/v/preludes/**.v'\n      - 'vlib/v/embed_file/**.v'\n      - 'vlib/x/json2/**.v'\n      - '**/sanitized_ci.yml'\n\nconcurrency:\n  group: sanitized-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  sanitize-undefined-clang:\n    runs-on: ubuntu-22.04\n    timeout-minutes: 120\n    env:\n      VFLAGS: -cc clang -cflags -fno-omit-frame-pointer\n      VJOBS: 1\n      UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1:print_suppressions=0:suppressions=/home/runner/work/v/v/.github/workflows/run_sanitizers_undefined.suppressions\n      VNATIVE_SKIP_LIBC_VV: 1\n      VTEST_SHOW_LONGEST_BY_RUNTIME: 3\n      VTEST_SHOW_LONGEST_BY_COMPTIME: 3\n      VTEST_SHOW_LONGEST_BY_TOTALTIME: 3\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4 && ./v symlink\n      - name: V doctor\n        run: ./v doctor\n      - name: Ensure code is well formatted\n        run: ./v -silent test-cleancode\n      - name: Install dependencies\n        run: |\n          .github/workflows/disable_azure_mirror.sh\n          ./v retry -- sudo apt update\n          ./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind\n          ./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev\n          ./v retry -- sudo apt install clang\n      - name: Recompile V with -cstrict\n        run: ./v -cg -cstrict -o v cmd/v\n      - name: Self tests (-fsanitize=undefined)\n        run: |\n          ./v -cflags -fsanitize=undefined -o v2 cmd/v\n          ./v2 -cflags -fsanitize=undefined -silent test-self vlib\n      - name: Build examples (V compiled with -fsanitize=undefined)\n        run: ./v2 -silent build-examples\n\n  sanitize-undefined-gcc:\n    runs-on: ubuntu-22.04\n    timeout-minutes: 120\n    env:\n      VFLAGS: -cc gcc -cflags -fno-omit-frame-pointer\n      VJOBS: 1\n      UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1:print_suppressions=0:suppressions=/home/runner/work/v/v/.github/workflows/run_sanitizers_undefined.suppressions\n      VNATIVE_SKIP_LIBC_VV: 1\n      VTEST_SHOW_LONGEST_BY_RUNTIME: 3\n      VTEST_SHOW_LONGEST_BY_COMPTIME: 3\n      VTEST_SHOW_LONGEST_BY_TOTALTIME: 3\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4 && ./v symlink\n      - name: V doctor\n        run: ./v doctor\n      - name: Ensure code is well formatted\n        run: ./v -silent test-cleancode\n      - name: Install dependencies\n        run: |\n          .github/workflows/disable_azure_mirror.sh\n          ./v retry -- sudo apt update\n          ./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind\n          ./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev\n      - name: Recompile V with -cstrict\n        run: ./v -cg -cstrict -o v cmd/v\n      - name: Self tests (-fsanitize=undefined)\n        run: |\n          ./v  -cflags -fsanitize=undefined -o v2 cmd/v\n          ./v2 -cflags -fsanitize=undefined -silent test-self vlib\n      - name: Build examples (V compiled with -fsanitize=undefined)\n        run: ./v2 -silent build-examples\n\n  sanitize-address-clang:\n    runs-on: ubuntu-22.04\n    timeout-minutes: 300\n    env:\n      VFLAGS: -cc clang -cflags -fno-omit-frame-pointer\n      VJOBS: 1\n      ASAN_OPTIONS: detect_leaks=1\n      LSAN_OPTIONS: max_leaks=1:print_suppressions=0:suppressions=/home/runner/work/v/v/.github/workflows/run_sanitizers_leak.suppressions\n      VNATIVE_SKIP_LIBC_VV: 1\n      VTEST_SHOW_LONGEST_BY_RUNTIME: 3\n      VTEST_SHOW_LONGEST_BY_COMPTIME: 3\n      VTEST_SHOW_LONGEST_BY_TOTALTIME: 3\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4 && ./v symlink\n      - name: V doctor\n        run: ./v doctor\n      - name: Ensure code is well formatted\n        run: ./v -silent test-cleancode\n      - name: Install dependencies\n        run: |\n          .github/workflows/disable_azure_mirror.sh\n          ./v retry -- sudo apt update\n          ./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind\n          ./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev\n          ./v retry -- sudo apt install clang\n      - name: Recompile V with -cstrict\n        run: ./v -cg -cstrict -o v cmd/v\n      - name: Self tests (-fsanitize=address)\n        run: ./v -cflags -fsanitize=address,pointer-compare,pointer-subtract -silent test-self vlib\n      - name: Test vlib/v/tests/ (V compiled with -fsanitize=address)\n        run: |\n          ./v -cflags -fsanitize=address -o v cmd/v\n          ./v -cc tcc -silent test-self -asan-compiler vlib/v/tests/\n      - name: Build examples (V compiled with -fsanitize=address)\n        run: ./v -silent build-examples\n\n  sanitize-address-msvc:\n    runs-on: windows-2025\n    timeout-minutes: 30\n    env:\n      VFLAGS: -cc msvc\n      VJOBS: 1\n      VNATIVE_SKIP_LIBC_VV: 1\n      VTEST_SHOW_LONGEST_BY_RUNTIME: 3\n      VTEST_SHOW_LONGEST_BY_COMPTIME: 3\n      VTEST_SHOW_LONGEST_BY_TOTALTIME: 3\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build\n        run: |\n          echo %VFLAGS%\n          echo $VFLAGS\n          .\\make.bat -msvc\n          .\\v.exe self\n      - name: V doctor\n        run: .\\v.exe doctor\n      - name: Ensure code is well formatted\n        run: .\\v.exe -silent test-cleancode\n        # - name: Install dependencies\n        #   run: |\n        #     .\\v.exe setup-freetype\n        #     .\\.github\\workflows\\windows-install-sqlite.bat\n        # - name: Self tests (/fsanitize=address) # TODO:\n        #   run: .\\v.exe -cflags \"/fsanitize=address\" -silent test-self vlib\n\n  sanitize-address-gcc:\n    runs-on: ubuntu-22.04\n    timeout-minutes: 300\n    env:\n      VFLAGS: -cc gcc -cflags -fno-omit-frame-pointer\n      VJOBS: 1\n      ASAN_OPTIONS: detect_leaks=1\n      LSAN_OPTIONS: max_leaks=1:print_suppressions=0:suppressions=/home/runner/work/v/v/.github/workflows/run_sanitizers_leak.suppressions\n      VNATIVE_SKIP_LIBC_VV: 1\n      VTEST_SHOW_LONGEST_BY_RUNTIME: 3\n      VTEST_SHOW_LONGEST_BY_COMPTIME: 3\n      VTEST_SHOW_LONGEST_BY_TOTALTIME: 3\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4 && ./v symlink\n      - name: V doctor\n        run: ./v doctor\n      - name: Ensure code is well formatted\n        run: ./v -silent test-cleancode\n      - name: Install dependencies\n        run: |\n          .github/workflows/disable_azure_mirror.sh\n          ./v retry -- sudo apt update\n          ./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind\n          ./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev\n          ./v retry -- sudo apt install clang\n      - name: Recompile V with -cstrict\n        run: ./v -cg -cstrict -o v cmd/v\n      - name: Self tests (-fsanitize=address)\n        run: ./v -cflags -fsanitize=address -silent test-self vlib\n      - name: Test vlib/v/tests/ (V compiled with -fsanitize=address)\n        run: |\n          ./v -cflags -fsanitize=address,pointer-compare,pointer-subtract -o v cmd/v\n          ./v -cc tcc -silent test-self -asan-compiler vlib/v/tests/\n      - name: Build examples (V compiled with -fsanitize=address)\n        run: ./v -silent build-examples\n\n  sanitize-memory-clang:\n    runs-on: ubuntu-22.04\n    timeout-minutes: 240\n    env:\n      VFLAGS: -cc clang -gc none -cflags -fno-omit-frame-pointer\n      VJOBS: 1\n      VNATIVE_SKIP_LIBC_VV: 1\n      VTEST_SHOW_LONGEST_BY_RUNTIME: 3\n      VTEST_SHOW_LONGEST_BY_COMPTIME: 3\n      VTEST_SHOW_LONGEST_BY_TOTALTIME: 3\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4 && ./v symlink\n      - name: V doctor\n        run: ./v doctor\n      - name: Ensure code is well formatted\n        run: ./v -silent test-cleancode\n      - name: Install dependencies\n        run: |\n          .github/workflows/disable_azure_mirror.sh\n          ./v retry -- sudo apt update\n          ./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind\n          ./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev\n          ./v retry -- sudo apt install clang\n      - name: Recompile V with clang and -cstrict\n        run: ./v -cc clang -cg -cstrict -o v cmd/v\n      - name: Self tests (-fsanitize=memory)\n        run: ./v -cflags -fsanitize=memory -silent test-self -msan-compiler vlib\n      - name: Test vlib/v/tests/ (V compiled with -fsanitize=memory)\n        run: |\n          ./v -cflags -fsanitize=memory -o v cmd/v\n          ./v -cc tcc -silent test-self -msan-compiler vlib/v/tests/\n      - name: Build examples (V compiled with -fsanitize=memory)\n        run: ./v -silent build-examples\n\n  sanitize-address-clang-without-gc:\n    runs-on: ubuntu-22.04\n    timeout-minutes: 300\n    env:\n      VFLAGS: -cc clang -gc none -cflags -fno-omit-frame-pointer\n      VJOBS: 1\n      LSAN_OPTIONS: detect_leaks=0\n      VNATIVE_SKIP_LIBC_VV: 1\n      VTEST_SHOW_LONGEST_BY_RUNTIME: 3\n      VTEST_SHOW_LONGEST_BY_COMPTIME: 3\n      VTEST_SHOW_LONGEST_BY_TOTALTIME: 3\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4 && ./v symlink\n      - name: V doctor\n        run: ./v doctor\n      - name: Ensure code is well formatted\n        run: ./v -silent test-cleancode\n      - name: Install dependencies\n        run: |\n          .github/workflows/disable_azure_mirror.sh\n          ./v retry -- sudo apt update\n          ./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind\n          ./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev\n          ./v retry -- sudo apt install clang\n      - name: Recompile V with -cstrict\n        run: ./v -cg -cstrict -o v cmd/v\n      - name: Self tests (-fsanitize=address)\n        run: ./v -cflags -fsanitize=address -silent test-self vlib\n"
  },
  {
    "path": ".github/workflows/sdl_ci.yml",
    "content": "name: sdl CI\n\non:\n  workflow_dispatch:\n  push:\n    paths:\n      - 'vlib/**'\n      - 'thirdparty/**'\n      - 'cmd/tools/builders/**.v'\n      - 'cmd/tools/vshader.v'\n      - '**/sdl_ci.yml'\n      - '!**.md'\n  pull_request:\n    paths:\n      - 'vlib/**'\n      - 'thirdparty/**'\n      - 'cmd/tools/builders/**.v'\n      - 'cmd/tools/vshader.v'\n      - '**/sdl_ci.yml'\n      - '!**.md'\n\nconcurrency:\n  group: sdl-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  v-compiles-sdl-examples:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    env:\n      VFLAGS: -cc tcc\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make && sudo ./v symlink\n\n      - name: Install dependencies\n        run: |\n          .github/workflows/disable_azure_mirror.sh\t\t\n          v retry 'sudo apt update'\n          v retry 'sudo apt install -y libsdl2-dev libsdl2-ttf-dev'\n          v retry 'sudo apt install -y libsdl2-mixer-dev libsdl2-image-dev'\n\n      - name: Clone sdl into .vmodules\n        run: |\n          v retry 'git clone --filter=blob:none https://github.com/vlang/sdl'\n          cd sdl\n          mkdir -p ~/.vmodules\n          ln -s \"$(pwd)\" ~/.vmodules/sdl\n\n      - name: Ensure SDL setup works\n        run: ./v ~/.vmodules/sdl/setup.vsh\n\n      - name: Run tests\n        run: ./v test sdl\n\n      - name: Build sdl shared\n        run: ./v -shared -g sdl\n\n      - name: Build sdl examples\n        run: |\n          v shader sdl/examples/sdl_opengl_and_sokol\n          v should-compile-all sdl/examples/\n          ~/.vmodules/sdl/examples/versions/main\n\n      - name: Check SDL works, when installed through vpm\n        run: |\n          rm -rf sdl/\n          rm -rf ~/.vmodules/sdl\n          v retry 'v install sdl'\n          ls -la ~/.vmodules/sdl/\n          v ~/.vmodules/sdl/setup.vsh\n          v run ~/.vmodules/sdl/examples/versions\n"
  },
  {
    "path": ".github/workflows/show_manual_release_cmd.vsh",
    "content": "import os\nimport time\nimport term\n\nnow := time.now()\nyear := now.year\nweek := now.strftime('%V')\n\nmut remote_name := 'origin'\nmut release_tag := 'weekly.${year:04}.${week:02}'\n\nif os.args.len > 1 {\n\tremote_name = os.args[1]\n}\n\nif os.args.len > 2 {\n\trelease_tag = os.args[2]\n}\n\nprintln('## Usage: show_manual_release_cmd.vsh [REMOTE] [TAGNAME]')\nprintln('##         current remote_name: ${remote_name}')\nprintln('##         current release_tag: ${release_tag}')\nprintln('##  ▼▼▼ ${term.ecolorize(term.yellow, 'run the following, to make a new github release')} ▼▼▼ ')\n\ngit_cmd := 'git tag -s -m \"releases: ${release_tag}\" ${release_tag} && git push --atomic ${remote_name} ${release_tag}'\nprintln(git_cmd)\n"
  },
  {
    "path": ".github/workflows/ssa_backends_ci.yml.disabled",
    "content": "name: SSA backends CI\n\non:\n  push:\n    paths:\n      - 'vlib/v2/**'\n      - 'cmd/tinyv/**'\n      - '.github/workflows/ssa_backends_ci.yml'\n  pull_request:\n    paths:\n      - 'vlib/v2/**'\n      - 'cmd/tinyv/**'\n      - '.github/workflows/ssa_backends_ci.yml'\n\nconcurrency:\n  group: ssa_backends-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  ssa-backends-linux:\n    runs-on: ubuntu-24.04\n    env:\n      VJOBS: 1\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make && ./v symlink\n      - name: Test native x64 backend\n        run: v run cmd/tinyv/test_ssa_backends.v\n      - name: Test cleanc backend\n        run: v run cmd/tinyv/test_ssa_backends.v cleanc\n      - name: Test c-ssa backend\n        run: v run cmd/tinyv/test_ssa_backends.v c\n\n  ssa-backends-macos:\n    runs-on: macos-14\n    env:\n      VJOBS: 1\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4 && ./v symlink\n      - name: Test native arm64 backend\n        run: v run cmd/tinyv/test_ssa_backends.v\n      - name: Test cleanc backend\n        run: v run cmd/tinyv/test_ssa_backends.v cleanc\n      - name: Test c-ssa backend\n        run: v run cmd/tinyv/test_ssa_backends.v c\n"
  },
  {
    "path": ".github/workflows/symlink_ci.yml",
    "content": "name: Symlink CI\n\non:\n  workflow_dispatch:\n  push:\n    paths:\n      - 'cmd/tools/vsymlink/**.v'\n      - '.github/workflows/symlink_ci.yml'\n  pull_request:\n    paths:\n      - 'cmd/tools/vsymlink/**.v'\n      - '.github/workflows/symlink_ci.yml'\n\nconcurrency:\n  group: symlink-${{ github.workflow }}-${{ github.ref_name == 'master' && github.sha || github.ref_name }}\n  cancel-in-progress: true\n\njobs:\n  symlink-unix:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os: [ubuntu-latest, macos-latest]\n      fail-fast: false\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4\n      - name: Symlink\n        run: |\n          ./v symlink\n          cd /tmp/ && v version\n          cd ~ && v version\n          echo 'println(123)' > hi.v\n          v run hi.v\n      - name: Unlink\n        run: |\n          rm \"$(which v)\"\n          v --version && exit 1 || exit 0\n      - name: Symlink (sudo)\n        run: |\n          sudo ./v symlink\n          cd /tmp/ && v version\n          cd ~ && v version\n          echo 'println(123)' > hi.v\n          v run hi.v\n      - name: Unlink\n        run: |\n          rm \"$(which v)\"\n          v --version && exit 1 || exit 0\n      - name: Symlink (-githubci)\n        run: ./v symlink -githubci\n      - name: Test after symlink with -githubci (in a separate script)\n        run: |\n          cd /tmp/ && v version\n          cd ~ && v version\n          echo 'println(123)' > hi.v\n          v run hi.v\n\n  symlink-windows:\n    runs-on: windows-2025\n    strategy:\n      matrix:\n        flags: ['', '-githubci']\n      fail-fast: false\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: ./make.bat\n      - name: Symlink\n        run: ./v symlink ${{ matrix.flags }}\n      - name: Check if V is usable\n        run: |\n          cd $RUNNER_TEMP && pwd && v version\n          cd ~ && pwd && v version\n          echo 'println(123)' > hi.v\n          v run hi.v\n"
  },
  {
    "path": ".github/workflows/termux_ci.yml",
    "content": "name: CI Termux\n\non:\n  workflow_dispatch:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/termux_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/termux_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\njobs:\n  termux-build:\n    runs-on: ubuntu-latest\n    timeout-minutes: 30\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build and test in Termux\n        run: |\n          set -o xtrace\n          echo \"$PWD\"\n          whoami\n          touch outside_docker.txt\n          git log -n4\n          echo \"running docker ...\"\n          docker run --rm --mount type=bind,source=/home/runner/work/v/v,destination=/src -w /src termux/termux-docker:latest bash -c '\n            set -o xtrace\n            echo \"running inside docker\"\n            whoami\n            cp -r /src ~/vproject; cd ~/vproject\n            touch inside_docker.txt\n            ls -la\n            echo \"previous TERMUX_VERSION: $TERMUX_VERSION\"\n            export TERMUX_VERSION=0.118.3\n            echo \"explicit TERMUX_VERSION: $TERMUX_VERSION\"\n            .github/workflows/retry.sh pkg update -y\n            .github/workflows/retry.sh pkg install -y clang libexecinfo libgc libgc-static make git\n            git log -n4\n            VFLAGS=\"-cc cc\" make\n            ./v symlink\n            v run examples/hello_world.v\n            v run examples/primes.v\n            v -e \"import os; dump( os.user_os() )\"\n          '\n"
  },
  {
    "path": ".github/workflows/time_ci.yml",
    "content": "name: Time CI\n\non:\n  push:\n    paths:\n      - 'vlib/**'\n      - 'cmd/tools/builders/**.v'\n      - '**/time_ci.yml'\n      - '!**.md'\n  pull_request:\n    paths:\n      - 'vlib/**'\n      - 'cmd/tools/builders/**.v'\n      - '**/time_ci.yml'\n      - '!**.md'\n\nconcurrency:\n  group: time-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  time-linux:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make\n      - name: Test time functions in a timezone UTC-12\n        run: TZ=Etc/GMT+12 ./v test vlib/time/\n      - name: Test time functions in a timezone UTC-3\n        run: TZ=Etc/GMT+3 ./v test vlib/time/\n      - name: Test time functions in a timezone UTC+3\n        run: TZ=Etc/GMT-3 ./v test vlib/time/\n      - name: Test time functions in a timezone UTC+12\n        run: TZ=Etc/GMT-12 ./v test vlib/time/\n      - name: Test in a timezone using daylight saving (Europe/Paris)\n        run: TZ=Europe/Paris ./v test vlib/time/\n\n  time-macos:\n    runs-on: macos-14\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make\n      - name: Test time functions in a timezone UTC-12\n        run: TZ=Etc/GMT+12 ./v test vlib/time/\n      - name: Test time functions in a timezone UTC-3\n        run: TZ=Etc/GMT+3 ./v test vlib/time/\n      - name: Test time functions in a timezone UTC+3\n        run: TZ=Etc/GMT-3 ./v test vlib/time/\n      - name: Test time functions in a timezone UTC+12\n        run: TZ=Etc/GMT-12 ./v test vlib/time/\n      - name: Test in a timezone using daylight saving (Europe/Paris)\n        run: TZ=Europe/Paris ./v test vlib/time/\n\n  time-windows:\n    runs-on: windows-2025\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: .\\make.bat\n      - name: Test time functions in a timezone UTC-12\n        run: tzutil /s \"Dateline Standard Time\" && ./v test vlib/time/\n      - name: Test time functions in a timezone UTC-3\n        run: tzutil /s \"Greenland Standard Time\" && ./v test vlib/time/\n      - name: Test time functions in a timezone UTC+3\n        run: tzutil /s \"Russian Standard Time\" && ./v test vlib/time/\n      - name: Test time functions in a timezone UTC+12\n        run: tzutil /s \"New Zealand Standard Time\" && ./v test vlib/time/\n      - name: Test in a timezone using daylight saving (Europe/Paris)\n        run: tzutil /s \"W. Europe Standard Time\" && ./v test vlib/time/\n"
  },
  {
    "path": ".github/workflows/toml_ci.yml",
    "content": "name: toml CI\n\non:\n  push:\n    paths:\n      - 'vlib/**'\n      - '**/toml_ci.yml'\n      - '!**.md'\n  pull_request:\n    paths:\n      - 'vlib/**'\n      - '**/toml_ci.yml'\n      - '!**.md'\n\nconcurrency:\n  group: toml-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  toml-module-pass-external-test-suites:\n    runs-on: ubuntu-latest\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4 && ./v symlink\n      - name: Install dependencies\n        run: |\n          v retry -- v download https://github.com/jqlang/jq/releases/download/jq-1.6/jq-linux64\n          sudo chmod 755 jq-linux64\n          sudo mv jq-linux64 /usr/bin/jq\n\n      - name: Show JQ Version\n        run: jq --version\n\n      - name: Download more TOML testsuits\n        run: .github/workflows/download_full_toml_test_suites.sh\n\n      - name: Run TOML tests\n        run: VTEST_TOML_DO_YAML_CONVERSION=1 VTEST_TOML_DO_LARGE_FILES=1 ./v test vlib/toml\n"
  },
  {
    "path": ".github/workflows/tools_ci.yml",
    "content": "name: Tools CI\n\non:\n  push:\n    paths:\n      - 'cmd/**'\n      - '!cmd/tools/vpm/**'\n      - 'vlib/**'\n      - 'thirdparty/**'\n      - '!**.md'\n      - '**/tools_ci.yml'\n  pull_request:\n    paths:\n      - 'cmd/**'\n      - '!cmd/tools/vpm/**'\n      - 'vlib/**'\n      - 'thirdparty/**'\n      - '!**.md'\n      - '**/tools_ci.yml'\n\nconcurrency:\n  group: tools-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  tools-linux:\n    runs-on: ubuntu-22.04\n    timeout-minutes: 20\n    strategy:\n      matrix:\n        cc: [tcc, gcc, clang]\n      fail-fast: false\n    env:\n      VFLAGS: -cc ${{ matrix.cc }}\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make && ./v -showcc -o v cmd/v && ./v symlink && ./v doctor\n      - name: Code in cmd/ is formatted\n        run: ./v fmt -verify cmd/\n      - name: Check build-tools\n        run: ./v -silent -N -W -check build-tools\n      - name: Test tools\n        run: ./v -silent test-self cmd\n      - name: Test tools (-cstrict)\n        if: ${{ matrix.cc != 'tcc' }}\n        run: ./v -silent -W -cstrict test-self cmd\n      - name: Test sanitized\n        if: ${{ matrix.cc != 'tcc' }}\n        run: |\n          export VNATIVE_SKIP_LIBC_VV=1\n          if [[ ${{ matrix.cc }} == \"clang\" ]]; then\n            cmd=\"./v -silent -cc clang -cflags -fsanitize=undefined test-self -ubsan-compiler cmd\"\n            echo \"$cmd\" && $cmd\n            cmd=\"./v -silent -cc clang -cflags -fsanitize=memory    test-self -msan-compiler cmd\"\n            echo \"$cmd\" && $cmd\n          else\n            cmd=\"./v -silent -cc gcc -cflags -fsanitize=thread test-self cmd\"\n            echo \"$cmd\" && $cmd\n            cmd=\"./v -silent -cc gcc -cflags -fsanitize=address,leak,undefined,shift,shift-exponent,shift-base,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,bounds-strict,alignment,object-size,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr test-self -asan-compiler cmd/tools\"\n            echo \"$cmd\" && $cmd\n            ## cmd=\"./v -silent -cc gcc -cflags -fsanitize=kernel-address test-self -asan-compiler cmd\"\n            ## echo \"$cmd\" && $cmd\n          fi\n\n  tools-macos:\n    runs-on: macos-14\n    timeout-minutes: 20\n    strategy:\n      matrix:\n        cc: [clang]\n      fail-fast: false\n    env:\n      VFLAGS: -cc ${{ matrix.cc }}\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make && ./v -showcc -o v cmd/v && ./v symlink && ./v doctor\n      - name: Check build-tools\n        run: ./v -silent -N -W -check build-tools\n      - name: Test tools\n        run: ./v -silent test-self cmd\n      - name: Test tools (-cstrict)\n        run: ./v -silent -W -cstrict test-self cmd\n\n  tools-windows:\n    runs-on: windows-2025\n    timeout-minutes: 20\n    strategy:\n      matrix:\n        cc: [tcc, gcc, msvc]\n      fail-fast: false\n    env:\n      VFLAGS: -cc ${{ matrix.cc }}\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: ./make.bat -${{ matrix.cc }} && ./v -o v2.exe cmd/v && ./v2 -showcc -o v.exe cmd/v && ./v symlink && ./v doctor\n      - name: Check build tools\n        run: ./v build-tools\n      - name: Test tools\n        run: ./v -silent test-self cmd\n      - name: Test tools (-cstrict)\n        if: ${{ matrix.cc == 'msvc' }}\n        run: ./v -silent -W -cstrict test-self cmd\n\n  tools-docker-ubuntu-musl:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    container:\n      image: thevlang/vlang:ubuntu-build\n      env:\n        V_CI_MUSL: 1\n        V_CI_UBUNTU_MUSL: 1\n        VFLAGS: -cc musl-gcc -gc none\n      volumes:\n        - ${{github.workspace}}:/opt/vlang\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n      - name: Build V\n        run: make && ./v -cg -o v cmd/v && ./v symlink\n      - name: Ensure git commands can be used with no prompts on modern Git versions\n        run: git config --global --add safe.directory /__w/v/v\n      - name: Verify `v test` works\n        run: |\n          ./v cmd/tools/test_if_v_test_system_works.v\n          ./cmd/tools/test_if_v_test_system_works\n      - name: Check build tools\n        run: ./v -silent -N -W -check build-tools\n      - name: Test tools\n        run: ./v -silent test-self cmd\n      - name: Test tools (-cstrict)\n        run: ./v -silent -W -cstrict test-self cmd\n\n  tools-freebsd:\n    runs-on: ubuntu-latest\n    timeout-minutes: 20\n    strategy:\n      matrix:\n        cc: [tcc, gcc, clang]\n      fail-fast: false\n    env:\n      VFLAGS: -cc ${{ matrix.cc }}\n    steps:\n      - uses: actions/checkout@v6\n      - name: Tests tools on FreeBSD with ${{ matrix.cc }}\n        uses: cross-platform-actions/action@v0.32.0\n        with:\n          operating_system: freebsd\n          version: '15.0'\n          memory: 4G\n          shell: sh\n          sync_files: runner-to-vm\n          environment_variables: VFLAGS\n          run: |\n            sudo pkg install -y git sqlite3 gmake boehm-gc-threaded libiconv\n            if [ \"$VFLAGS\" = \"-cc gcc\" ]; then\n              sudo pkg install -y gcc\n            fi\n            # Mandatory: hostname not set in VM => some tests fail\n            sudo hostname -s freebsd-ci\n            echo \"### OS infos\"\n            uname -a\n            git config --global --add safe.directory .\n            # Build V\n            echo \"### Build V\"\n            printf \"VFLAGS = %s\\n\" \"$VFLAGS\"\n            gmake && ./v -showcc -o v cmd/v && sudo ./v symlink && ./v doctor\n            # Code in cmd/ is formatted\n            echo \"### Check code in cmd/ is formatted\"\n            ./v fmt -verify cmd/\n            # Check build-tools\n            echo \"### Check build tools\"\n            ./v -silent -N -W -check build-tools\n            # Test tools\n            echo \"### Test tools\"\n            ./v -silent test-self cmd\n            # Test tools (-cstrict)\n            if [ \"$VFLAGS\" != \"-cc tcc\" ]; then\n              echo \"### Test tools (-cstrict)\"\n              ./v -silent -W -cstrict test-self cmd\n            fi\n\n  tools-openbsd:\n    runs-on: ubuntu-latest\n    timeout-minutes: 20\n    strategy:\n      matrix:\n        cc: [tcc, clang]\n      fail-fast: false\n    env:\n      VFLAGS: -cc ${{ matrix.cc }}\n    steps:\n      - uses: actions/checkout@v6\n      - name: Tests tools on OpenBSD with ${{ matrix.cc }}\n        uses: cross-platform-actions/action@v0.32.0\n        with:\n          operating_system: openbsd\n          version: '7.8'\n          memory: 4G\n          shell: sh\n          sync_files: runner-to-vm\n          environment_variables: VFLAGS\n          run: |\n            sudo pkg_add git sqlite3 gmake boehm-gc libiconv\n            # Mandatory: hostname not set in VM => some tests fail\n            sudo hostname -s openbsd-ci\n            echo \"### OS infos\"\n            uname -a\n            git config --global --add safe.directory .\n            # Build V\n            echo \"### Build V\"\n            printf \"VFLAGS = %s\\n\" \"$VFLAGS\"\n            gmake && ./v -showcc -o v cmd/v && sudo ./v symlink && ./v doctor\n            # Code in cmd/ is formatted\n            echo \"### Check code in cmd/ is formatted\"\n            ./v fmt -verify cmd/\n            # Check build-tools\n            echo \"### Check build tools\"\n            ./v -silent -N -W -check build-tools\n            # Test tools\n            echo \"### Test tools\"\n            ./v -silent test-self cmd\n            # Test tools (-cstrict)\n            if [ \"$VFLAGS\" != \"-cc tcc\" ]; then\n              echo \"### Test tools (-cstrict)\"\n              ./v -silent -W -cstrict test-self cmd\n            fi\n"
  },
  {
    "path": ".github/workflows/v_apps_and_modules_compile_ci.yml",
    "content": "name: V Apps and Modules\n\non:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/v_apps_and_modules_compile_ci.yml'\n      - 'examples/**'\n      - 'cmd/tools/vrepl.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/v_apps_and_modules_compile_ci.yml'\n      - 'examples/**'\n      - 'cmd/tools/vrepl.v'\n\nconcurrency:\n  group: v_apps-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  v-apps-compile:\n    strategy:\n      matrix:\n        os: [ubuntu-latest, macos-14]\n      fail-fast: false\n    runs-on: ${{ matrix.os }}\n    timeout-minutes: 60\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Build V\n        id: build\n        run: make && sudo ./v symlink\n\n      - name: Install dependencies\n        run: |\n          if [ \"$RUNNER_OS\" == 'Linux' ]; then\n            .github/workflows/disable_azure_mirror.sh\n            v retry -- sudo apt -qq update\n            v retry -- sudo apt -qq install libgc-dev libsodium-dev libssl-dev sqlite3 libsqlite3-dev\n            v retry -- sudo apt -qq install libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev xfonts-75dpi xfonts-base libegl-dev\n            v retry -- sudo apt -qq install sassc libgit2-dev # needed by gitly\n          else\n            v retry brew install sassc libgit2\n          fi\n\n      - name: Build docs generator\n        run: |\n          v retry -- v install markdown\n          v retry -- git clone https://github.com/vlang/docs --branch generator --depth 1\n          cd docs\n          v .\n\n      - name: Test vtcc\n        if: runner.os == 'Linux'\n        run: .github/workflows/compile_v_with_vtcc.sh\n\n      - name: Test vsql compilation and examples\n        if: ${{ false && !cancelled() && steps.build.outcome == 'success' }}\n        run: |\n          echo \"Install vsql\"\n          v retry -- v install elliotchance.vsql\n          cd ~/.vmodules/elliotchance/vsql\n          echo \"Compile vsql\"\n          make bin/vsql\n          echo \"Run examples\"\n          make examples\n          echo \"Run vsql/connection_test.v\"\n          v vsql/connection_test.v\n\n      - name: Test vlang/gui\n        if: ${{ !cancelled() && steps.build.outcome == 'success' }}\n        run: .github/workflows/compile_vlang_gui_examples.sh\n      - name: Test discord.v\n        if: ${{ !cancelled() && steps.build.outcome == 'success' }}\n        run: .github/workflows/compile_discordv.sh\n      - name: Build herolib\n        if: ${{ false && !cancelled() && steps.build.outcome == 'success' }}\n        run: .github/workflows/compile_herolib.sh\n      - name: Build vlang/vab\n        if: ${{ !cancelled() && steps.build.outcome == 'success' }}\n        run: |\n          echo \"Install VAB\"\n          v retry -- v install vab\n          echo \"Build vab\"\n          v ~/.vmodules/vab\n          echo \"Build vab with -g\"\n          v -g ~/.vmodules/vab\n\n      - name: Build vlang/ved\n        if: ${{ !cancelled() && steps.build.outcome == 'success' }}\n        run: |\n          v retry -- git clone --depth 1 https://github.com/vlang/ved\n          cd ved && v -o ved .\n          echo \"Build\"\n          v .\n          echo \"Build with -autofree ...\"\n          v -autofree .\n          echo \"Build with -prod ...\"\n          v -prod .\n          cd ..\n\n      - name: Build vlang/pdf\n        if: ${{ !cancelled() && steps.build.outcome == 'success' }}\n        run: |\n          v retry -- v install pdf\n          echo \"PDF examples should compile\"\n          v should-compile-all ~/.vmodules/pdf/examples\n\n      - name: Build vlang/libsodium\n        if: ${{ !cancelled() && steps.build.outcome == 'success' }}\n        run: |\n          echo \"Install the libsodium wrapper\"\n          v retry -- v install libsodium\n          echo \"Test libsodium\"\n          VJOBS=1 v test ~/.vmodules/libsodium\n\n      - name: Build vlang/coreutils\n        if: ${{ !cancelled() && steps.build.outcome == 'success' }}\n        run: |\n          echo \"Clone Coreutils\"\n          v retry -- git clone --depth 1 https://github.com/vlang/coreutils /tmp/coreutils\n          echo \"Build Coreutils\"\n          cd /tmp/coreutils; make\n\n      - name: Build vlang/gitly\n        if: ${{ !cancelled() && steps.build.outcome == 'success' }}\n        run: |\n          echo \"Install markdown\"\n          v retry -- v install markdown\n          echo \"Install pcre\"\n          v retry -- v install pcre\n          echo \"Clone Gitly\"\n          v retry -- git clone https://github.com/vlang/gitly /tmp/gitly\n          echo \"Build Gitly\"\n          v -cc gcc /tmp/gitly\n          ## echo \"Build Gitly with -autofree\"\n          ## v -cc gcc -autofree /tmp/gitly\n          echo \"Compile gitly.css from gitly.scss\"\n          sassc /tmp/gitly/src/static/css/gitly.scss > /tmp/gitly/src/static/css/gitly.css\n          # echo \"Run first_run.v\"\n          # v -cc gcc run /tmp/gitly/tests/first_run.v\n          # # /tmp/gitly/gitly -ci_run\n\n      - name: Build V UI examples\n        if: ${{ !cancelled() && steps.build.outcome == 'success' }}\n        run: |\n          v retry -- v install ui\n          v -no-parallel ~/.vmodules/ui/examples/rectangles.v\n          v -no-parallel ~/.vmodules/ui/examples/users.v\n          # v run ~/.vmodules/ui/examples/build_examples.vsh\n\n      - name: Build vlang/v-analyzer\n        if: ${{ !cancelled() && steps.build.outcome == 'success' }}\n        run: |\n          echo \"Clone v-analyzer\"\n          v retry -- git clone --depth=1 --filter=blob:none --recursive --shallow-submodules https://github.com/vlang/v-analyzer /tmp/v-analyzer\n          cd /tmp/v-analyzer\n          echo \"Installing dependencies\"\n          v install\n          echo \"Build v-analyzer debug\"\n          v build.vsh debug\n          echo \"Build v-analyzer release\"\n          v build.vsh release\n\n      - name: Format vlang/v-analyzer\n        if: ${{ !cancelled() && steps.build.outcome == 'success' }}\n        run: |\n          cd /tmp/v-analyzer\n          set +e\n          v fmt -c .\n          exit_code=$?\n          if [[ $exit_code -ne 0 && $exit_code -ne 5 ]]; then\n            # Don't fail if there are only internal errors (exit code 5).\n            v fmt -diff .\n            exit 1\n          fi\n\n      - name: Build vlang/go2v\n        if: ${{ !cancelled() && steps.build.outcome == 'success' && matrix.os != 'macos-14' }}\n        run: |\n          echo \"Clone Go2V\"\n          v retry -- git clone --depth=1 https://github.com/vlang/go2v /tmp/go2v/\n          echo \"Build Go2V\"\n          v /tmp/go2v/\n          echo \"Run Go2V tests\"\n          VJOBS=1 v test /tmp/go2v/\n\n      - name: Install UI through VPM and make sure its examples compile\n        if: ${{ !cancelled() && steps.build.outcome == 'success' }}\n        run: |\n          echo \"Official VPM modules should be installable\"\n          v retry -- v install ui\n          echo \"Examples of UI should compile\"\n          v ~/.vmodules/ui/examples/build_examples.vsh\n\n      - name: Build vlang/adventofcode\n        if: ${{ !cancelled() && steps.build.outcome == 'success' }}\n        run: |\n          echo \"Clone the AdventOfCode repo\"\n          v retry -- git clone --depth 1 https://github.com/vlang/adventofcode  /tmp/adventofcode\n          echo \"Install dependencies\"\n          v retry -- v install pcre\n          echo \"Execute Tests\"\n          cd /tmp/adventofcode && v run verify.v\n\n      - name: Build vlang/msgpack\n        if: ${{ !cancelled() && steps.build.outcome == 'success' }}\n        run: |\n          echo \"Install msgpack\"\n          v retry -- v install msgpack\n          echo \"Build msgpack\"\n          v -shared ~/.vmodules/msgpack/\n          echo \"Run msgpack tests\"\n          v test ~/.vmodules/msgpack/\n          echo \"MessagePack examples should compile\"\n          v should-compile-all ~/.vmodules/msgpack/examples\n\n      # - name: Build VEX\n      #   if: ${{ !cancelled() }} && steps.build.outcome == 'success'\n      #   run: |\n      #     echo \"Install Vex\"\n      #     v retry -- v install nedpals.vex\n      #     echo \"Compile all of the Vex examples\"\n      #     v should-compile-all ~/.vmodules/nedpals/vex/examples\n      #     echo \"Compile the simple Vex example\"\n      #     v ~/.vmodules/nedpals/vex/examples/simple_example.v\n      #     echo \"Run Vex Tests\"\n      #     v test ~/.vmodules/nedpals/vex\n\n  vpm-site-compile:\n    strategy:\n      matrix:\n        os: [ubuntu-24.04, macos-14]\n      fail-fast: false\n    runs-on: ${{ matrix.os }}\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make && ./v symlink\n      - name: Build vpm\n        run: |\n          v retry -- v install markdown\n          v retry -- git clone --depth 1 https://github.com/vlang/vpm\n          cd vpm && v .\n"
  },
  {
    "path": ".github/workflows/vab_ci.yml",
    "content": "name: vab CI\n\non:\n  workflow_call:\n  push:\n    paths:\n      - 'vlib/**'\n      - 'thirdparty/**'\n      - 'cmd/tools/builders/**.v'\n      - '**/vab_ci.yml'\n      - '!**.md'\n  pull_request:\n    paths:\n      - 'vlib/**'\n      - 'thirdparty/**'\n      - 'cmd/tools/builders/**.v'\n      - '**/vab_ci.yml'\n      - '!**.md'\n\nconcurrency:\n  group: vab-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  vab-compiles-v-examples:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    env:\n      VAB_FLAGS: --api 30 --build-tools 29.0.0 -v 3\n    steps:\n      - uses: actions/setup-java@v5\n        with:\n          distribution: 'temurin'\n          java-version: 11\n\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4 && ./v symlink\n\n      - name: Install vab\n        run: |\n          v retry -- v install vab\n          v -g ~/.vmodules/vab\n          sudo ln -s ~/.vmodules/vab/vab /usr/local/bin/vab\n\n      - name: Run tests\n        run: v -g test ~/.vmodules/vab\n\n      - name: Run vab --help\n        run: vab --help\n\n      - name: Run vab doctor\n        run: |\n          vab doctor\n          which d8 || true\n          which dx || true\n\n      - name: Build graphical V examples as APK\n        run: |\n          declare -a v_examples=('flappylearning' '2048' 'fireworks' 'tetris' 'sokol/particles' 'sokol/drawing.v' 'sokol/freetype_raven.v' 'gg/polygons.v' 'gg/raven_text_rendering.v' 'gg/rectangles.v' 'gg/stars.v' 'gg/worker_thread.v')\n          mkdir apks\n          for example in \"${v_examples[@]}\"; do\n            safe_name=$(echo \"$example\" | sed 's%/%-%' | sed 's%\\.%-%' )\n            vab \"examples/$example\" -o \"apks/$safe_name.apk\"\n          done\n\n  v-compiles-os-android:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4 && ./v symlink\n\n      - name: Install vab\n        run: |\n          v retry -- v install vab\n          v -g ~/.vmodules/vab\n          sudo ln -s ~/.vmodules/vab/vab /usr/local/bin/vab\n\n      - name: Run vab --help\n        run: vab --help\n\n      - name: Run vab doctor\n        run: vab doctor\n\n      - name: Check `v -os android` *without* -apk flag\n        run: .github/workflows/android_cross_compile.vsh\n"
  },
  {
    "path": ".github/workflows/vinix_ci.yml",
    "content": "name: Build Vinix\n\non:\n  workflow_call:\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/vinix_ci.yml'\n      - 'cmd/tools/vrepl.v'\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/vinix_ci.yml'\n      - 'cmd/tools/vrepl.v'\n\nconcurrency:\n  group: vinix-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  vinix-build:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        run: make -j4 && ./v symlink\n\n      - name: Install dependencies\n        run: |\n          .github/workflows/disable_azure_mirror.sh\n          v retry -- sudo apt update\n          v retry -- sudo apt install build-essential -y\n\n      - name: Clone current Vinix\n        run: v retry -- git clone --depth=1 https://github.com/vlang/vinix.git\n\n      - name: Download Vinix kernel dependencies\n        run: cd vinix/kernel && v retry -- ./get-deps\n\n      - name: Attempt to build the Vinix kernel (debug)\n        run: |\n          set -e\n          cd vinix/kernel\n          make PROD=false \\\n            CFLAGS=\"-Ulinux -U__linux -U__linux__ -U__gnu_linux__ -D__vinix__ -O2 -g -pipe\" \\\n            V=\"$(realpath ../../v)\"\n          make clean\n\n      - name: Attempt to build the Vinix kernel (prod)\n        run: |\n          set -e\n          cd vinix/kernel\n          make PROD=true \\\n            CFLAGS=\"-Ulinux -U__linux -U__linux__ -U__gnu_linux__ -D__vinix__ -O2 -g -pipe\" \\\n            V=\"$(realpath ../../v)\"\n          make clean\n\n      - name: Attempt to build the util-vinix (debug)\n        run: |\n          set -e\n          cd vinix/util-vinix\n          make PROD=false \\\n            VFLAGS=\"-os vinix -gc none\" \\\n            CFLAGS=\"-Ulinux -U__linux -U__linux__ -U__gnu_linux__ -D__vinix__ -O2 -g -pipe\" \\\n            V=\"$(realpath ../../v)\"\n          make clean\n\n      - name: Attempt to build the util-vinix (prod)\n        run: |\n          set -e\n          cd vinix/util-vinix\n          make PROD=true \\\n            VFLAGS=\"-os vinix -gc none\" \\\n            CFLAGS=\"-Ulinux -U__linux -U__linux__ -U__gnu_linux__ -D__vinix__ -O2 -g -pipe\" \\\n            V=\"$(realpath ../../v)\"\n          make clean\n"
  },
  {
    "path": ".github/workflows/vpm_ci.yml",
    "content": "name: VPM CI\n\non:\n  push:\n    paths:\n      - '**/vpm_ci.yml'\n      - '**/cmd/tools/vpm/**'\n  pull_request:\n    paths:\n      - '**/vpm_ci.yml'\n      - '**/cmd/tools/vpm/**'\n\nconcurrency:\n  group: vpm-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  setup-vpm:\n    strategy:\n      matrix:\n        os: [ubuntu-latest, windows-latest, macos-latest]\n      fail-fast: false\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          path: vlang\n      - name: Show git version\n        run: git version\n      - name: Build V\n        if: runner.os != 'Windows'\n        run: cd vlang && make -j4 && ./v doctor\n      - name: Build V (Windows)\n        if: runner.os == 'Windows'\n        run: cd vlang && ./make.bat && ./v doctor\n      - name: Cache V\n        uses: actions/cache/save@v5\n        with:\n          path: vlang\n          key: ${{ runner.os }}-${{ github.sha }}\n\n  test-vpm:\n    needs: setup-vpm\n    strategy:\n      matrix:\n        include:\n          - os: ubuntu-latest\n            cc: tcc\n          - os: ubuntu-latest\n            cc: gcc\n          - os: ubuntu-latest\n            cc: clang\n          - os: macos-latest\n            cc: clang\n          - os: windows-latest\n            cc: tcc\n          - os: windows-latest\n            cc: gcc\n          - os: windows-latest\n            cc: msvc\n      fail-fast: false\n    runs-on: ${{ matrix.os }}\n    steps:\n      - name: Restore V cache\n        uses: actions/cache/restore@v5\n        with:\n          path: vlang\n          key: ${{ runner.os }}-${{ github.sha }}\n      - name: Show git version\n        run: git version\n      - name: Build and test VPM\n        run: |\n          cd vlang\n          ./v -W -N cmd/tools/vpm\n          ./v -cc ${{ matrix.cc }} -d network test cmd/tools/vpm\n"
  },
  {
    "path": ".github/workflows/vsl_and_vtl_compile_ci.yml",
    "content": "name: VSL and VTL\n\non:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/vsl_and_vtl_compile_ci.yml'\n      - 'examples/**'\n      - 'cmd/tools/vrepl.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/vsl_and_vtl_compile_ci.yml'\n      - 'examples/**'\n      - 'cmd/tools/vrepl.v'\n\nconcurrency:\n  group: vsl-vtl-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  vsl-compiles:\n    strategy:\n      matrix:\n        os: [ubuntu-24.04, macos-14]\n      fail-fast: false\n    runs-on: ${{ matrix.os }}\n    timeout-minutes: 25\n    env:\n      VFLAGS: -no-parallel\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        id: build\n        run: make && sudo ./v symlink\n      - name: Install dependencies\n        run: |\n          if [ \"$RUNNER_OS\" == 'Linux' ]; then\n          .github/workflows/disable_azure_mirror.sh\n          v retry -- sudo apt -qq update\n          v retry -- sudo apt -qq install \\\n            libgc-dev libgl1-mesa-dev mesa-common-dev liblapacke-dev libopenblas-dev libopenmpi-dev \\\n            opencl-headers libxcursor-dev libxi-dev libxrandr-dev libhdf5-cpp-103-1t64 libhdf5-dev libhdf5-mpi-dev hdf5-tools\n          else\n            v retry brew install coreutils hdf5 open-mpi openblas lapack opencl-headers\n          fi\n      - name: Install vsl\n        run: v retry -- v install vsl\n      - name: Test with Pure V Backend\n        run: ~/.vmodules/vsl/bin/test\n      - name: Test with Pure V Backend and Pure V Math\n        run: ~/.vmodules/vsl/bin/test --use-cblas\n\n  vtl-compiles:\n    strategy:\n      matrix:\n        os: [ubuntu-24.04, macos-14]\n      fail-fast: false\n    runs-on: ${{ matrix.os }}\n    timeout-minutes: 25\n    env:\n      VFLAGS: -no-parallel\n      # Fixes complaints about $TERM not being set when running the vtl test script\n      # (a warning on Linux, but an error on macOS).\n      TERM: xterm\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build V\n        id: build\n        run: make && sudo ./v symlink\n      - name: Install dependencies\n        run: |\n          if [ \"$RUNNER_OS\" == 'Linux' ]; then\n            .github/workflows/disable_azure_mirror.sh\n            v retry -- sudo apt -qq update\n            v retry -- sudo apt -qq install \\\n              libgc-dev libgl1-mesa-dev mesa-common-dev liblapacke-dev libopenblas-dev libopenmpi-dev\n          else\n            v retry brew install coreutils hdf5 open-mpi openblas lapack opencl-headers\n          fi\n          v retry v install vsl\n      - name: Install vtl\n        run: v retry v install vtl\n      - name: Test with Pure V Backend\n        run: ~/.vmodules/vtl/bin/test\n      - name: Test with Pure V Backend and Pure V Math\n        run: ~/.vmodules/vtl/bin/test --use-cblas\n"
  },
  {
    "path": ".github/workflows/vup_works.yml",
    "content": "name: Upgrading from a previous release with v up works\n\non:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '**.vv'\n      - '**.out'\n      - '!**/vup_works.yml'\n      - '!cmd/tools/vup.v'\n      - 'cmd/tools/vrepl.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '**.vv'\n      - '**.out'\n      - '!**/vup_works.yml'\n      - '!cmd/tools/vup.v'\n      - 'cmd/tools/vrepl.v'\n\nconcurrency:\n  group: vup-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  v-up-works-nix:\n    strategy:\n      fail-fast: false\n      matrix:\n        include:\n          - os: ubuntu-latest\n            zip: v_linux.zip\n          - os: macos-15-intel\n            zip: v_macos_x86_64.zip\n          - os: macos-latest\n            zip: v_macos_arm64.zip\n    runs-on: ${{ matrix.os }}\n    timeout-minutes: 20\n    env:\n      VDIR: /tmp/v_from_release_zip\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build v\n        run: make && ./v symlink && ./v version\n\n      - name: Download latest release ZIP\n        run: ./v retry -- ./v download --sha256 https://github.com/vlang/v/releases/latest/download/${{ matrix.zip }}\n\n      - name: Extract ZIP 1, no changes\n        run: |\n          rm -rf \"$VDIR\" && unzip -q -d v_from_release/ ${{ matrix.zip }} && mv v_from_release \"$VDIR\"\n          cd \"$VDIR/v\"\n          ./v version\n          ./v up\n          echo \"Updated ./v version: $(./v version) | Current   v version: $(v version)\"\n\n      - name: Extract ZIP 2, with local changes\n        run: |\n          rm -rf \"$VDIR\" && unzip -q -d v_from_release/ ${{ matrix.zip }} && mv v_from_release \"$VDIR\"\n          touch \"$VDIR/v/vlib/v/pref/local_file_not_present_in_master.c.v\" && rm \"$VDIR/v/examples/hello_world.v\"\n          cd \"$VDIR/v\"\n          ./v version\n          ./v up\n          echo \"Updated ./v version: $(./v version) | Current   v version: $(v version)\"\n\n      - name: Extract ZIP 3, with current vup.v in the extract\n        run: |\n          rm -rf \"$VDIR\" && unzip -q -d v_from_release/ ${{ matrix.zip }} && mv v_from_release \"$VDIR\"\n          rm -rf \"$VDIR/v/cmd/tools/vup\" && cp cmd/tools/vup.v \"$VDIR/v/cmd/tools/vup.v\"\n          cd \"$VDIR/v\"\n          ./v version\n          ./v up\n          echo \"Updated ./v version: $(./v version) | Current   v version: $(v version)\"\n\n      - name: Extract ZIP 4, with local changes, and with current vup.v\n        run: |\n          rm -rf \"$VDIR\" && unzip -q -d v_from_release/ ${{ matrix.zip }} && mv v_from_release \"$VDIR\"\n          rm -rf \"$VDIR/v/cmd/tools/vup\" && cp cmd/tools/vup.v \"$VDIR/v/cmd/tools/vup.v\"\n          touch \"$VDIR/v/vlib/v/pref/local_file_not_present_in_master.c.v\" && rm \"$VDIR/v/examples/hello_world.v\"\n          cd \"$VDIR/v\"\n          ./v version\n          ./v up\n          echo \"Updated ./v version: $(./v version) | Current   v version: $(v version)\"\n"
  },
  {
    "path": ".github/workflows/wasm_backend_ci.yml",
    "content": "name: wasm backend CI\n\non:\n  push:\n    paths:\n      - 'cmd/tools/builders/**.v'\n      - 'vlib/builtin/**.v'\n      - 'vlib/v/ast/**.v'\n      - 'vlib/v/scanner/**.v'\n      - 'vlib/v/parser/**.v'\n      - 'vlib/v/checker/**.v'\n      - 'vlib/v/gen/c/**.v'\n      - 'vlib/v/builder/**.v'\n      - 'vlib/v/cflag/**.v'\n      - 'vlib/v/live/**.v'\n      - 'vlib/v/util/**.v'\n      - 'vlib/v/markused/**.v'\n      - 'vlib/v/preludes/**.v'\n      - 'vlib/v/gen/wasm/**.v'\n      - 'vlib/v/gen/wasm/tests/**.v'\n      - 'vlib/v/gen/wasm/tests/**.vv'\n      - 'vlib/v/gen/wasm/tests_decompile/**.v'\n      - 'vlib/v/gen/wasm/tests_decompile/**.vv'\n      - '**/wasm_backend_ci.yml'\n  pull_request:\n    paths:\n      - 'cmd/tools/builders/**.v'\n      - 'vlib/builtin/**.v'\n      - 'vlib/v/ast/**.v'\n      - 'vlib/v/scanner/**.v'\n      - 'vlib/v/parser/**.v'\n      - 'vlib/v/checker/**.v'\n      - 'vlib/v/gen/c/**.v'\n      - 'vlib/v/builder/**.v'\n      - 'vlib/v/cflag/**.v'\n      - 'vlib/v/live/**.v'\n      - 'vlib/v/util/**.v'\n      - 'vlib/v/markused/**.v'\n      - 'vlib/v/preludes/**.v'\n      - 'vlib/v/gen/wasm/**.v'\n      - 'vlib/v/gen/wasm/tests/**.v'\n      - 'vlib/v/gen/wasm/tests/**.vv'\n      - 'vlib/v/gen/wasm/tests_decompile/**.v'\n      - 'vlib/v/gen/wasm/tests_decompile/**.vv'\n      - '**/wasm_backend_ci.yml'\n\nconcurrency:\n  group: wasm-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  wasm-backend:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os: [ubuntu-22.04, windows-2022]\n      fail-fast: false\n    timeout-minutes: 20\n    env:\n      VTEST_ONLY: wasm\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Build V\n        if: runner.os != 'Windows'\n        run: make -j4\n      - name: Build V (Windows)\n        if: runner.os == 'Windows'\n        run: ./make.bat\n\n      - name: Install WABT to get wasm-decompile\n        if: runner.os != 'Windows'\n        run: ./v retry -- sudo apt install wabt\n\n      - name: Setup Wasmer\n        uses: wasmerio/setup-wasmer@v3.1\n\n      - name: Prebuild the WASM backend\n        run: ./v cmd/tools/builders/wasm_builder.v\n\n      - name: Test the WASM backend\n        run: ./v test vlib/v/gen/wasm/\n\n      - name: Build examples\n        run: ./v build-examples\n"
  },
  {
    "path": ".github/workflows/websockets_ci.yml",
    "content": "name: Websockets CI\n\non:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/websockets_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**/websockets_ci.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\nconcurrency:\n  group: websockets-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  websocket_tests:\n    runs-on: ubuntu-24.04\n    timeout-minutes: 121\n    env:\n      VFLAGS: -cc tcc -no-retry-compilation\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build v\n        run: |\n          echo \"$VFLAGS\"\n          sudo ln -s \"$PWD/thirdparty/tcc/tcc.exe\" /usr/local/bin/tcc ## TODO: remove\n          make -j4 && ./v symlink\n          ./v -g -o v cmd/v\n      - name: Install dependencies\n        run: v retry -- sudo apt install --quiet -y libssl-dev\n      - name: v doctor\n        run: ./v doctor\n      - name: Run websockets tests\n        run: ./v -g test vlib/net/websocket/\n\n      ## Autobahn integrations tests\n      - name: Run autobahn services\n        run: docker compose -f ${{github.workspace}}/vlib/net/websocket/tests/autobahn/docker-compose.yml up -d\n\n      - name: Wait for the service to start\n        run: sleep 10s\n\n      - name: Build client test\n        run: docker exec autobahn_client \"/src/v\" \"/src/vlib/net/websocket/tests/autobahn/autobahn_client.v\"\n      - name: Run client test\n        run: docker exec autobahn_client \"/src/vlib/net/websocket/tests/autobahn/autobahn_client\"\n\n      - name: Build client wss test\n        run: docker exec autobahn_client \"/src/v\" \"/src/vlib/net/websocket/tests/autobahn/autobahn_client_wss.v\"\n\n      - name: Run client wss test\n        run: docker exec autobahn_client \"/src/vlib/net/websocket/tests/autobahn/autobahn_client_wss\"\n      - name: Run server test\n        run: docker exec autobahn_server \"wstest\" \"-m\" \"fuzzingclient\" \"-s\" \"/config/fuzzingclient.json\"\n\n      - name: Copy reports\n        run: docker cp autobahn_server:/reports ${{github.workspace}}/reports\n      - name: Copy reports wss\n        run: docker cp autobahn_server_wss:/reports ${{github.workspace}}/reports_wss\n      - name: Test success\n        run: docker exec autobahn_server \"python\" \"/check_results.py\"\n      - name: Test success WSS\n        run: docker exec autobahn_server_wss \"python\" \"/check_results.py\"\n\n      - name: Publish all reports\n        uses: actions/upload-artifact@v7\n        with:\n          name: full report\n          path: ${{github.workspace}}/reports\n\n      - name: Publish report client\n        uses: actions/upload-artifact@v7\n        with:\n          name: client\n          path: ${{github.workspace}}/reports/clients/index.html\n\n      - name: Publish report server\n        uses: actions/upload-artifact@v7\n        with:\n          name: server\n          path: ${{github.workspace}}/reports/servers/index.html\n\n      - name: Publish all reports WSS\n        uses: actions/upload-artifact@v7\n        with:\n          name: full report wss\n          path: ${{github.workspace}}/reports_wss\n\n      - name: Publish report client wss\n        uses: actions/upload-artifact@v7\n        with:\n          name: client wss\n          path: ${{github.workspace}}/reports_wss/clients/index.html\n"
  },
  {
    "path": ".github/workflows/windows-install-sdl.bat",
    "content": "@echo off\r\n\r\ncurl -L https://www.libsdl.org/release/SDL2-devel-2.0.10-VC.zip -o SDL2.zip\r\ncurl -L https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-devel-2.0.15-VC.zip -o SDL2_ttf.zip\r\ncurl -L https://www.libsdl.org/projects/SDL_image/release/SDL2_image-devel-2.0.5-VC.zip -o SDL2_image.zip\r\ncurl -L https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-devel-2.0.4-VC.zip -o SDL2_mixer.zip\r\n\r\nunzip SDL2.zip -d thirdparty/\r\nunzip SDL2_ttf.zip -d thirdparty/\r\nunzip SDL2_image.zip -d thirdparty/\r\nunzip SDL2_mixer.zip -d thirdparty/\r\n\r\nmove /y thirdparty/SDL2-2.0.10 thirdparty/SDL2\r\nmove /y thirdparty/SDL2_ttf-2.0.15 thirdparty/SDL2_ttf\r\nmove /y thirdparty/SDL2_image-2.0.5 thirdparty/SDL2_image\r\nmove /y thirdparty/SDL2_mixer-2.0.4 thirdparty/SDL2_mixer\r\n"
  },
  {
    "path": ".github/workflows/windows-install-sqlite.bat",
    "content": "REM This file should be run from the top folder of the V compiler itself.\r\n\r\nv vlib/db/sqlite/install_thirdparty_sqlite.vsh\r\n"
  },
  {
    "path": ".github/workflows/windows_ci_gcc.yml",
    "content": "name: CI Windows GCC\n\non:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**.bat'\n      - '!**/windows_ci_gcc.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**.bat'\n      - '!**/windows_ci_gcc.yml'\n      - '!**/windows-install-sqlite.bat'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\nconcurrency:\n  group: windows-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  gcc-windows:\n    runs-on: windows-2025\n    timeout-minutes: 110\n    env:\n      VFLAGS: -cc gcc\n      VTEST_SHOW_LONGEST_BY_RUNTIME: 3\n      VTEST_SHOW_LONGEST_BY_COMPTIME: 3\n      VTEST_SHOW_LONGEST_BY_TOTALTIME: 3\n    steps:\n      - uses: actions/checkout@v6\n      - name: Show tool versions\n        run: |\n          gcc --version\n          pkg-config --version\n          openssl version\n          echo \"Flags for openssl:\"\n          pkg-config openssl --cflags\n          echo \"Flags for openssl libs:\"\n          pkg-config openssl --libs\n          .github/workflows/find_openssl.bat\n          echo \"OpenSSL files:\"\n          where.exe /R \"C:\\Program Files\\OpenSSL\" *.*\n          echo \"Include files for openssl:\"\n          dir \"c:/Program Files/OpenSSL/include\"\n          echo \"Lib Include files for openssl:\"\n          dir \"c:/Program Files/OpenSSL/lib/VC/x64/\"\n      - name: Build\n        run: |\n          .\\make.bat -gcc\n          .\\v.exe symlink\n          .\\v.exe -stats vlib/crypto/ecdsa/ecdsa_test.v\n      - name: Test v binaries\n        run: v build-vbinaries\n      - name: All code is formatted\n        run: v -silent test-cleancode\n      - name: Test new v.c\n        run: |\n          v -o v.c cmd/v\n          gcc -Werror -municode -w v.c -lws2_32 -std=c99\n      - name: Install dependencies\n        run: |\n          v retry -- v setup-freetype\n          .\\.github\\workflows\\windows-install-sqlite.bat\n      - name: v doctor\n        run: |\n          v doctor\n      - name: Verify `v test` works\n        run: |\n          echo $VFLAGS\n          v cmd/tools/test_if_v_test_system_works.v\n          ./cmd/tools/test_if_v_test_system_works\n      - name: Test pure V math module\n        run: v -silent -exclude @vlib/math/*.c.v test vlib/math/\n      - name: Self tests\n        run: v -silent test-self vlib\n      - name: Build option_test.c.v with -autofree\n        run: v -autofree vlib/v/tests/options/option_test.c.v\n      - name: Test v->js\n        run: v -o hi.js examples/js_hello_world.v && node hi.js\n      - name: Build examples\n        run: v build-examples\n      - name: v2 self compilation\n        run: v -o v2.exe cmd/v && .\\v2.exe -o v3.exe cmd/v\n      - name: compile vdoctor.v with -prod\n        run: v -showcc -prod cmd/tools/vdoctor.v\n      - name: compile vup.v with -prod\n        run: v -showcc -prod cmd/tools/vup.v\n"
  },
  {
    "path": ".github/workflows/windows_ci_msvc.yml",
    "content": "name: CI Windows MSVC\n\non:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**.bat'\n      - '!**/windows_ci_msvc.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**.bat'\n      - '!**/windows_ci_msvc.yml'\n      - '!**/windows-install-sqlite.bat'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\nconcurrency:\n  group: windows-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  msvc-windows:\n    runs-on: windows-2022\n    timeout-minutes: 70\n    env:\n      VFLAGS: -cc msvc\n      VTEST_SHOW_LONGEST_BY_RUNTIME: 3\n      VTEST_SHOW_LONGEST_BY_COMPTIME: 3\n      VTEST_SHOW_LONGEST_BY_TOTALTIME: 3\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build\n        run: |\n          echo %VFLAGS%\n          echo $VFLAGS\n          .\\make.bat -msvc\n          .\\v.exe symlink\n      - name: Build V with WX\n        run: v -cflags /WX self\n      - name: All code is formatted\n        run: v -silent test-cleancode\n      - name: Test -cc msvc works\n        run: v -no-retry-compilation run examples/hello_world.v\n      - name: Install dependencies\n        run: |\n          v retry -- v setup-freetype\n          .\\.github\\workflows\\windows-install-sqlite.bat\n      - name: v doctor\n        run: |\n          v doctor\n      - name: Verify `v test` works\n        run: |\n          echo $VFLAGS\n          v cmd/tools/test_if_v_test_system_works.v\n          ./cmd/tools/test_if_v_test_system_works\n      - name: Test pure V math module\n        run: v -silent -exclude @vlib/math/*.c.v test vlib/math/\n      - name: Self tests\n        run: v -silent test-self vlib\n      - name: Test v->js\n        run: v -o hi.js examples/js_hello_world.v && node hi.js\n      - name: Test v binaries\n        run: v build-vbinaries\n      - name: Build examples\n        run: v build-examples\n      - name: v2 self compilation\n        run: v -o v2.exe cmd/v && .\\v2.exe -o v3.exe cmd/v\n"
  },
  {
    "path": ".github/workflows/windows_ci_tcc.yml",
    "content": "name: CI Windows TCC\n\non:\n  push:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**.bat'\n      - '!**/windows_ci_tcc.yml'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n  pull_request:\n    paths-ignore:\n      - '**.md'\n      - '**.yml'\n      - '!**.bat'\n      - '!**/windows_ci_tcc.yml'\n      - '!**/windows-install-sqlite.bat'\n      - 'cmd/tools/**'\n      - '!cmd/tools/builders/**.v'\n\nconcurrency:\n  group: windows-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  tcc-windows:\n    runs-on: windows-2022\n    timeout-minutes: 60\n    env:\n      VFLAGS: -cc tcc -no-retry-compilation\n      VTEST_SHOW_LONGEST_BY_RUNTIME: 3\n      VTEST_SHOW_LONGEST_BY_COMPTIME: 3\n      VTEST_SHOW_LONGEST_BY_TOTALTIME: 3\n    steps:\n      - uses: actions/checkout@v6\n      - name: Build with make.bat -tcc\n        run: |\n          .\\make.bat -tcc\n          .\\v.exe symlink\n      - name: All code is formatted\n        run: v -silent test-cleancode\n      - name: Test new v.c\n        run: |\n          v -o v.c cmd/v\n          .\\thirdparty\\tcc\\tcc.exe -Werror -w -ladvapi32 -lws2_32 -bt10 v.c\n      - name: Install dependencies\n        run: |\n          v retry -- v setup-freetype\n          .\\.github\\workflows\\windows-install-sqlite.bat\n      - name: v -g self\n        run: v -g self\n      - name: v doctor\n        run: |\n          v doctor\n      - name: Verify `v test` works\n        run: |\n          v cmd/tools/test_if_v_test_system_works.v\n          .\\cmd\\tools\\test_if_v_test_system_works.exe\n      - name: Verify `v vlib/v/gen/c/coutput_test.v` works\n        run: v vlib/v/gen/c/coutput_test.v\n      - name: Make sure running TCC64 instead of TCC32\n        run: v test .github\\workflows\\make_sure_ci_run_with_64bit_compiler_test.v\n      - name: Test ./v doc -v clipboard *BEFORE building tools*\n        run: v doc -v clipboard\n      - name: Test v build-tools\n        run: v -silent -W build-tools\n      - name: Test pure V math module\n        run: v -silent -exclude @vlib/math/*.c.v test vlib/math/\n      - name: Self tests\n        run: v -silent test-self vlib\n      - name: Test v->js\n        run: v -o hi.js examples/js_hello_world.v && node hi.js\n      - name: Test v binaries\n        run: v build-vbinaries\n      - name: Build examples\n        run: v build-examples\n      - name: v2 self compilation\n        run: v -o v2.exe cmd/v && .\\v2.exe -o v3.exe cmd/v && .\\v3.exe -o v4.exe cmd/v\n"
  },
  {
    "path": ".github/workflows/workflow_lint.yml",
    "content": "name: Workflow Lint\n\n## Note: to install `prettier` locally, see https://prettier.io/docs/en/install,\n## or just: `npm install --save-dev --save-exact prettier`\n\n## If you already have `prettier` installed, to run it locally,\n## just run: `npx prettier --check **.yml` .\n\non:\n  push:\n    paths:\n      - '**.yml'\n  pull_request:\n    paths:\n      - '**.yml'\n\njobs:\n  lint-yml-workflows:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - name: Verify formatting\n        uses: creyD/prettier_action@v4.6\n        with:\n          prettier_options: --check **.yml\n"
  },
  {
    "path": ".gitignore",
    "content": "# ignore sub-level build binaries and v binary\n*/**/*\nv\nv.exe\nv2\nv2.exe\nvdbg\nvdbg.exe\n!*/\n!*.*\n*.exe\n*.o\n*.so\n.*.c\n*.tmp.c\n*.obj\n*.exp\n*.ilk\n*.pdb\n*.dll\n*.lib\n*.bak\n*.dylib\na.out\n.noprefix.vrepl_temp\n\n# ignore v build files\n/vc\n/v.c\n/v.*.c\n/v.c.out\n/v_old\n/v_old.exe\n/vold\n/vold.exe\n/vnew\n/vnew.exe\n/vprod\n/vprod_gcc\n/vprod_clang\n/vprod.exe\n/vprod_gcc.exe\n/vprod_clang.exe\n/vprod_msvc.exe\n.vrepl_temp.v\nfns.txt\n.noprefix.vrepl_temp.v\n\n# ignore temp and cache directories\ntemp/\ntmp/\ncache/\n\n# unignore special files without extension\n!.github/PULL_REQUEST_TEMPLATE\n!.editorconfig\n!.gitattributes\n!.gitignore\n!BSDmakefile\n!Dockerfile\n!Dockerfile.alpine\n!Dockerfile.cross\n!LICENSE\n!Makefile\n!GNUmakefile\n\n# ignore editor files\n.idea\n.project\n.classpath\n.c9\n.vs\n*.launch\n.settings/\n*.sublime-workspace\n.vscode/\n*.code-workspace\n*~\n~*\n.sesskey\ntmp*\n*.db\n*.swp\n*.swo\n*.swn\n.env\n\n# ignore debugger files\ncachegrind.out.*\n.gdb_history\n*.dSYM\n*.def\nvgcore.*\n\n# ignore system files\n.DS_Store\n._*\nthumbs.db\n/.symlink\n/.bin\n\n_docs\n\n# ignore vs databases\n*.suo\n*.VC.db\n*.rsp\n\n# ignore cmd/tools/.disable_autorecompilation, which some package managers use.\ncmd/tools/.disable_autorecompilation\n\ntest.bin\n\n# ignore codespace env\n.venv/\n.direnv/\nshell.nix\ndefault.nix\nflake.nix\n.envrc\n\n# generated by thirdparty/stdatomic/nix/cpp/gen.v\nthirdparty/stdatomic/nix/cpp/*.h\n\n# ignore thirdparty libs that are distributed separately\nthirdparty/binaryen*\nthirdparty/wabt*\nthirdparty/tcc/\nthirdparty/sqlite/\n\n# ignore VLS log\nvls.log\n\n# ignore v2go tmperror files\n*.tmperr\n\n*/**/tmp.*\n\n# ignore Intellij files\n.idea/\n/*.iml\n\n#ignore generated files:\nwasm.v\n\n# ignore large GTK *.gir files\nGtk-4.0.gir\n*.gir\n\nvlib/builtin/js/*.js\nvlib/v/tests/*.js\n\n#ignore tags indexes, used by emacs/vim:\nETAGS\nTAGS\ntags\n\n# ignore the old regexp based v.ctags file (people using universal ctags < 6.1.0, can still benefit from them)\n.ctags.d/v.ctags\n\n# ignore .NET7.0 Assembly Files\nbench/vectors/bin\nbench/vectors/obj\n\nautofuzz.log\n.project.gf\n.aider*\n\n#ignore common file names for bugs/reproductions\nbug*\nissue*\n\n# ignore cmd2/v stuff\ncmd/v2/*.txt\ncmd/v2/*.json\n"
  },
  {
    "path": "AGENTS.md",
    "content": "<!-- V_AGENTS.md  v1.1  2026-02-04 -->\n\n# V Repo Guide\n\nPractical quick reference for the V compiler, standard library, and tools.\nWritten for AI coding agents; useful for humans too.\n\n## Contents\n* Quick Start\n* Top Rules\n* Agent Rules\n* Safety (Do Not Brick the Repo)\n* Divergences From Repo Docs\n* Quick Decisions\n* Common Workflow\n* Reporting\n* Prerequisites\n* Build & Rebuild\n* Run Programs\n* Testing\n* Code Style\n* Modules and Imports\n* C/JS Interop Hygiene\n* Environment-Specific Code (files and `$if`)\n* Compile-Time Code and Reflection\n* Debug\n* Compiler Architecture\n* Key Directories\n* Test Locations\n* Error Reporting (checker/parser)\n* Option/Result Types\n* Tools\n* Commits and PRs\n* Environment Variables\n* Gotchas\n\n## Quick Start\nGet operational from the repo root in three steps:\n\n1. Build once (only if `./v` is missing): `make`\n2. Build a working compiler:\n   * Debug-friendly (recommended): `./v -g -keepc -o ./vnew cmd/v`\n3. Use `./vnew` for everything:\n   * Run a file: `./vnew run examples/hello_world.v`\n   * Run tests: `./vnew -silent test vlib/v/`\n   * Format: `./vnew fmt -w path/to/file.v`\n\nThen read Top Rules and Agent Rules before making changes.\n\n## Top Rules\n* Use `./v` only to build `./vnew`; use `./vnew` for everything else.\n* Put all V flags immediately after `./vnew` and before the\n  subcommand/file, e.g. `./vnew -g run file.v`\n  (not `./vnew run file.v -g`); flags after the subcommand are passed\n  to that subcommand.\n* Rebuild `./vnew` after compiler or core module changes\n  (see Build & Rebuild).\n* Run the smallest relevant tests; see Testing for triggers and\n  minimums.\n* Ask before large refactors or wide file touches (see Agent Rules).\n* Do not stash or modify unrelated files unless explicitly instructed.\n* This guide assumes agents run locally, not in CI; CI notes are\n  informational only.\n* When a summary is required, include behavior change, tests run, and\n  touched file paths.\n* If instructions overlap, prefer Build & Rebuild, Testing, and\n  Reporting.\n* If duplicates drift, treat Build & Rebuild, Testing, and Reporting as\n  canonical and align other sections to them.\n\n## Agent Rules\n\n### Repo root\nAll commands assume the repo root as the working directory. The default\nlocation is `/opt/v`, but this may differ in your environment. If a\ncommand fails due to missing paths, verify with `pwd` and adjust\naccordingly. Use a per-command workdir only when a task requires a\nsubdir.\n\n### Tone and output\n* Be concise by default. If the user asks for depth, provide it while\n  keeping structure tight.\n* Keep output easy to scan: short sections, bullets when listing,\n  commands in backticks, no filler.\n* Use a strict, operational tone unless higher-priority instructions\n  override it.\n* Ask only when required. If information is missing, ask a direct\n  question.\n\n### File access and edit scope\n* You may read and edit all files in the V repo without asking for\n  permission. This is file access, not change scope; scope is\n  constrained below. Reading is always OK.\n  Edits to `ci/` or `Dockerfile*` still require an explicit ask.\n* Run build, test, and format commands without asking for permission.\n  These are validation steps, not code changes. Only ask about edit\n  scope, not about running `fmt`, targeted tests, or `check-md`.\n* Only modify files required for the user request; avoid unrelated\n  refactors. If duplication is harmful, small refactors to remove it\n  are OK only when needed. Only refactor duplication in code you are\n  already touching, and only when it directly supports the request or\n  fixes a bug there. \"Touching\" means files already modified for the\n  request.\n* Avoid unrelated file changes; call them out if present.\n* Avoid touching `thirdparty/` unless explicitly requested. If changes\n  are needed there, ask for approval before proceeding.\n\n### When to ask\n* Ask before large refactors or wide file touches (more than 5 files,\n  or changes across multiple repo-root directories like `cmd/`, `vlib/`,\n  `doc/`, `examples/`).\n  Exception: docs-only changes across many files are OK without asking;\n  call them out in the summary.\n* Ask before large behavioral changes within a single subsystem or file,\n  even if the file count is small. Examples: changes to parser rules,\n  checker resolution, codegen output shape, diagnostic text/ordering, or\n  tool CLI behavior. Large means user-visible changes in CLI flags,\n  output, diagnostics, or codegen shape. If unsure whether a change is\n  \"large,\" ask.\n* Ask before touching `ci/` or `Dockerfile*` unless explicitly\n  requested. If changes are needed there, confirm whether local\n  validation is expected or if CI-only coverage is acceptable.\n\n### Bootstrap\n* Bootstrap/compiler usage rules: see Top Rules and Build & Rebuild.\n\n### Completeness and summaries\n* If you cannot complete a requested step, state the blocker and partial\n  progress (what was attempted and what remains).\n* After substantial work, provide a short summary and list touched file\n  paths. Substantial work means any behavioral change, or changes in\n  more than one file. Always include tests run (or \"Not run\" with\n  reason) in the summary.\n* Never change tests just to silence failures. Update expectations only\n  when behavior changes are intended, and note the rationale in the\n  summary.\n\n### New files and deeper guidance\n* New file checklist: format with `./vnew fmt -w`, add doc comments for\n  any public functions, run `./vnew check-md` for markdown files, and\n  keep Markdown lines <= 100 chars. Add or update tests when introducing\n  a new public API.\n* For deeper edge cases, consult `CONTRIBUTING.md` and `TESTS.md`.\n\n## Safety (Do Not Brick the Repo)\n* Do not overwrite the working `./v` binary.\n  * Never run `./v self` without `-o`.\n  * Build with `./v -o ./vnew cmd/v`, then use `./vnew` for all checks.\n* Keep generated C when debugging backend issues: add `-keepc`.\n* Avoid hidden/bidirectional Unicode characters in source/markdown\n  files.\n* If the compiler becomes unusable, recover with:\n  1. `git stash`\n  2. `make`\n  3. `git stash apply`\n  Check `git status` before stashing to avoid hiding unrelated work.\n  Do not stash unless explicitly instructed or the compiler is bricked.\n\n## Divergences From Repo Docs\nThe repo docs use `v` in examples. In this environment:\n* Use `./v -g -keepc -o ./vnew cmd/v` instead of `v self`.\n* Use `./vnew` for all builds, runs, and tests.\n* `TESTS.md` suggests `v test-all` before PRs; ask before running\n  `./vnew test-all`.\nThese overrides exist to keep agent workflows reproducible and to avoid\nbreaking the bootstrap compiler.\n\n## Quick Decisions\n* For rebuild and test choices, follow Build & Rebuild and Testing.\n* Follow Common Workflow for the default execution order.\n* For broader workflow guidance, see `CONTRIBUTING.md`.\n\n### Compact decision table (rebuild/tests)\nUse this table to pick the minimum rebuild/tests quickly. See Build &\nRebuild and Testing for full details and edge cases.\nCommands omit `./vnew` for brevity; assume the `./vnew` prefix.\nThis table is the minimum set; check Testing for additional triggers.\nREPL and backend changes have additional triggers in Testing.\nNote: `cmd/v/` is compiler scope; treat changes there as compiler\nchanges.\nWhen in doubt, ask before proceeding.\nIf you read only one section for tests, **read Testing**.\n\n| Change area | Rebuild? | Minimum tests to run |\n| --- | --- | --- |\n| Docs only (`.md`) | No | `check-md file.md` |\n| Compiler (`vlib/v/`, `cmd/v/`) | Yes | `-silent vlib/v/compiler_errors_test.v`; `test vlib/v/` |\n| Core modules (builtin/strings/os/strconv/time) | Yes | Smallest relevant tests |\n| Parser-only (`vlib/v/parser/`) | Yes | `test vlib/v/parser/` |\n| Checker-only (`vlib/v/checker/`) | Yes | `test vlib/v/checker/` |\n| Comptime (`vlib/v/comptime/`) | Yes | `test vlib/v/tests/`; comptime-related tests |\n| vlib (non-compiler) | No | Nearest `*_test.v` or `test vlib/path/` |\n| Tools (`cmd/tools/`) | No | Tool-specific test; else nearest `*_test.v` |\n| Diagnostic/output changes | Yes | `vlib/v/slow_tests/inout/compiler_test.v` |\n| C codegen (`vlib/v/gen/c/`) | Yes | `vlib/v/gen/c/coutput_test.v` |\n\n## Common Workflow\n0. Before work: `git status`; ensure `./vnew` exists; rebuild if needed.\n   If `./vnew` is missing, see Quick Start or Build & Rebuild.\n1. Edit the relevant files.\n2. If compiler sources or core modules changed, rebuild `./vnew` with\n   `./v -g -keepc -o ./vnew cmd/v` (see Build & Rebuild).\n3. Format touched `.v`/`.vsh` files and run `./vnew check-md` on\n   touched markdown.\n4. Run the smallest relevant tests for the change scope (see Testing).\n\nSee Build & Rebuild for rebuild triggers and flags.\n\n## Reporting\n* When a summary is required (see Agent Rules), it must include:\n  * Behavior changes (or \"No behavior change\").\n  * Tests run (or \"Not run\" with a reason).\n  * Touched file paths.\n  * Note unrelated changes if present.\n  * Note doc updates if public behavior/tool output changed.\n* If public behavior or tool output changes, update relevant docs\n  (README.md, `doc/`, `tutorials/`) and note it.\n  For example: README.md for top-level CLI usage, `doc/` for\n  compiler/tool docs, `tutorials/` for learning material.\n* If you add or change a public API, update module docs or README and\n  note it. Public API includes stdlib functions/types and user-visible\n  compiler flags, diagnostics, tool CLI behavior (including `cmd/tools`\n  and stdlib CLI tools), or output formats.\n* Update `CHANGELOG.md` or `ROADMAP.md` only when explicitly requested.\n* Public behavior includes compiler output, diagnostics, user-facing\n  CLI, and stdlib API. This includes developer-facing flags, error\n  codes, or output ordering changes.\n* Internal refactors with no public behavior change do not require doc\n  updates.\n* If unsure whether behavior is public, ask the user before updating\n  docs.\n* Acceptable reasons for not running tests: docs-only change, no\n  relevant tests, or environment constraints. Be specific.\n* Docs-only changes: run `./vnew check-md file.md`; no other tests\n  required unless a test explicitly reads those docs.\n  No rebuild is needed unless compiler or core modules changed.\n* For docs-only, explicitly mention `check-md` in the summary.\n* If you update `.out` files, state the rationale in the summary.\n* Do not update `.out` files unless a behavior change is intended;\n  otherwise treat mismatches as regressions.\n* Example summary line: `Behavior change: none` or\n  `Behavior change: fixed X`.\n* Behavior change includes output, API, error messages, and test\n  expectations.\n* If blocked, note what was attempted and why it failed.\n* If tooling/network restrictions block a step, state the restriction\n  and the closest viable alternative.\n* Use `git status` to confirm touched files before reporting.\n\n## Prerequisites\n* Toolchain: `make`, `git`, and a C compiler (`clang` or `gcc`).\n* Windows: use `make.bat` for the initial build.\n\n## Build & Rebuild\n* Initial build (only if `./v` is missing): `make`\n  (Windows: `make.bat`).\n* Build `./vnew` (debug-friendly, recommended for agent workflows):\n  `./v -g -keepc -o ./vnew cmd/v`\n* Never run `./v self` directly; only build `./vnew` with the commands\n  above.\n* If `./v` is missing, run `make` first, then build `./vnew`.\n* If `./vnew` is missing but `./v` exists, run `./v -o ./vnew cmd/v`.\n* This section is the source of truth for rebuild triggers.\n  If a rule appears elsewhere, defer to this section.\n* Rebuild triggers:\n  * Compiler sources in `vlib/v/` or `cmd/v/`.\n  * Core modules: `builtin`, `strings`, `os`, `strconv`, `time`.\n* If `./v` exists but compiler sources changed, still rebuild `./vnew`\n  before tests.\n* If unsure whether compiler/core changes happened, rebuild `./vnew`.\n* Common flags:\n  * `-g` debug info (V line numbers).\n  * `-cg` debug info (C line numbers); often combined with `-keepc`.\n  * `-keepc` keep generated C file(s).\n  * `-prod` optimized build.\n  * `-o file` output path/name.\n  * `-cc clang` pick a C compiler.\n  * `-cstrict` be stricter about the generated C.\n  * `-b js|native|wasm` select a backend.\n  * `-os <os>` cross-compile target selection (when supported).\n\n## Code Style\n* Comments: add succinct comments only when code is not self-explanatory.\n  Do not delete existing comments unless they are incorrect; you may fix\n  grammar or spelling without changing meaning.\n  Add V doc comments right before each new or modified public function\n  or method.\n  The V doc comments should start with the name of the fn,\n  example: `// the_name does ...`\n* Copy pasta: avoid copy pasta. If there's duplicate logic, move to a\n  function only when it is required for the request and within code you\n  are already touching.\n* Avoid using `unsafe{ code }` blocks where possible, and minimize\n  their scope. `unsafe` is acceptable for low-level interop (e.g. C\n  pointer casts, manual memory management) but should never wrap\n  ordinary V logic. When `unsafe` is required, keep the block as small\n  as possible and add a comment explaining why it is necessary.\n* Keep Markdown lines <= 100 chars (the checker is strict).\n  Apply to touched lines in modified Markdown files.\n* Avoid hidden/bidirectional Unicode characters in source/markdown\n  files.\n* Non-V files: keep existing formatting; only reformat if required by\n  the change.\n* Treat `.vv` files in `vlib/v/slow_tests/inout/` as fixtures; avoid\n  formatting unless a behavior change is intended and output\n  expectations are updated.\n* Formatting and check commands are in Tools.\n\n## Modules and Imports\n* Module names must match their directory name (no hierarchy in the\n  `module` line). Mismatches cause silent import failures.\n* Imports follow the folder hierarchy (e.g. `import abc.def`).\n\n## C/JS Interop Hygiene\n* Avoid using `C.` or `JS.` symbols in plain `.v` files.\n  * Use `.c.v` / `.js.v` files.\n  * Enable `-Wimpure-v` to catch accidental impurity.\n* Do not refactor existing `C.`/`JS.` uses in `.v` files unless\n  required. If you must change those lines, prefer moving the interop\n  code to `.c.v`/`.js.v`.\n* For C interop, use correct `const_` prefixes in C function\n  redeclarations when needed (helps with `-cstrict` and C static\n  analysis tooling).\n\n## Environment-Specific Code (files and `$if`)\nV supports environment-specific file suffixes. Prefer them when the\nwhole file is platform/backend specific.\n\nCommon patterns:\n* Backend splits:\n  * `*.c.v` (C backend), `*.js.v` (JS backend), `*.native.v` (native\n    backend), `*.wasm.v` (WASM backend)\n* OS splits:\n  * `*_windows.c.v`, `*_linux.c.v`, `*_nix.c.v`, with `*_default.c.v`\n    as fallback\n* Flag splits:\n  * `*_d_customflag.v` is included only with `-d customflag`\n  * `*_notd_customflag.v` is included only when that flag is NOT passed\n\nNotes:\n* Do not use combinatorial suffixes like `_d_flag_linux.c.v`; use\n  `_d_flag.v` plus `$if linux {}` inside the file.\n* For smaller platform differences, use compile-time `$if` blocks:\n  * `$if windows { ... } $else { ... }`\n* See Compile-Time Code and Reflection for the full `$if` reference.\n\n## Compile-Time Code and Reflection\nV uses `$` as a prefix for compile-time (comptime) operations. These\nare evaluated by the compiler, not at runtime. AI agents frequently\nconfuse comptime and runtime constructs; this section clarifies the\nboundaries.\n\n### Compile-time `$if`\n`$if` evaluates conditions at compile time. It is not a runtime `if`.\nUse it for platform, compiler, and custom-flag checks:\n* `$if windows { ... } $else $if linux { ... } $else { ... }`\n* `$if debug { ... }` (enabled by `-g` or `-cg`)\n* `$if prod { ... }` (enabled by `-prod`)\n* `$if custom_flag ? { ... }` (enabled by `-d custom_flag`)\n\nFull list of builtin `$if` options: see the table at\n<https://docs.vlang.io/conditional-compilation.html>.\n\nCommon mistakes:\n* Using runtime `if` where `$if` is needed for platform-specific code.\n  Runtime `if` will fail to compile if it references platform-specific\n  symbols; `$if` excludes the block entirely on non-matching platforms.\n* Forgetting the `?` suffix for custom flags: `$if myflag ? { ... }`.\n  Without `?`, the compiler treats it as a builtin option and silently\n  ignores it.\n\n### Compile-time `$for`\n`$for` iterates over type metadata at compile time. It works with:\n* `StructType.fields` - iterate struct fields\n* `StructType.methods` - iterate struct methods\n* `EnumType.values` - iterate enum values\n* `StructType.attributes` - iterate struct attributes\n* `SumType.variants` - iterate sum type variants\n* `method.params` - iterate method parameters\n\nInside `$for` blocks, use `$if` to branch on field/method types:\n```v oksyntax\nfn main() {\n\t$for field in MyStruct.fields {\n\t\t$if field.typ is string {\n\t\t\tprintln(field.name)\n\t\t}\n\t}\n}\n```\n\nAlso works with generics: `T.fields`, `param.fields` where\n`fn gen[T](param T) {}`.\n\nCommon mistakes:\n* Using runtime `for` to iterate struct fields. This does not work;\n  V has no runtime reflection. Always use `$for`.\n* Calling `obj.$method()` outside a `$for m in Type.methods` block.\n  The `$method()` call is only valid inside a comptime method\n  iteration.\n* Assuming comptime `$for` produces a runtime loop. It does not; the\n  compiler unrolls it into concrete code for each field/method/variant.\n\n### Compile-time functions\nOnly the following `$`-prefixed functions are supported:\n* `$embed_file('path')` - embed a file's contents into the binary.\n  Paths can be absolute, relative to the source file, or use pseudo\n  variables like `@VEXEROOT` or `@VMODROOT`.\n* `$tmpl('path')` - compile a V template file (used by vweb/veb).\n* `$env('VAR')` - read an environment variable at compile time.\n* `$d('ident', default)` - read a `-d ident=value` compile-time\n  define, with a default fallback.\n* `$res('path')` - embed a resource (Android).\n* `$compile_error('msg')` - emit a compile-time error.\n* `$compile_warn('msg')` - emit a compile-time warning.\n* `$pkgconfig('name')` - query pkg-config at compile time.\n\nCommon mistakes:\n* Inventing comptime functions that do not exist (e.g. `$typeof`,\n  `$sizeof` as comptime calls). Use `typeof(expr).name` and\n  `sizeof(Type)` instead; these are builtins, not `$`-prefixed.\n* Assuming `$embed_file` returns a string. It returns an\n  `EmbedFileData` object; use `.to_string()` or `.to_bytes()`.\n* Using `$env` where a runtime `os.getenv` is appropriate, or vice\n  versa. `$env` is baked in at compile time and cannot change at\n  runtime.\n\n### Compile-time pseudo variables\nThese are `@`-prefixed identifiers substituted at compile time:\n* `@FN` - current function name.\n* `@METHOD` - `ReceiverType.MethodName`.\n* `@MOD` - current module name.\n* `@STRUCT` - current struct name.\n* `@FILE`, `@DIR`, `@LINE`, `@COLUMN`, `@FILE_LINE` - source\n  location.\n* `@LOCATION` - file, line, and current type+method; good for logging.\n* `@VEXE`, `@VEXEROOT` - path to the V compiler and its directory.\n* `@VHASH`, `@VCURRENTHASH` - compiler commit hashes.\n* `@VMOD_FILE`, `@VMODHASH`, `@VMODROOT` - nearest `v.mod` info.\n* `@BUILD_DATE`, `@BUILD_TIME`, `@BUILD_TIMESTAMP` - build time (UTC).\n  Override with the `SOURCE_DATE_EPOCH` env var for reproducible\n  builds.\n* `@OS`, `@CCOMPILER`, `@BACKEND`, `@PLATFORM` - build environment.\n\n### Compile-time type groups\nComptime type groups combine multiple types into a higher-level type\nfor use in generic or comptime `$if` checks:\n* `$int` - all integer types\n* `$float` - all float types\n* `$array` - all array types\n* `$map` - all map types\n* `$struct` - all struct types\n* `$enum` - all enum types\n* `$alias` - all type aliases\n* `$sumtype` - all sum types\n* `$function` - all function types\n* `$interface` - all interface types\n* `$option` - all option types\n\nExample: `$if field.typ is $int { ... }`\n\n### Comptime changes and testing\nComptime logic lives in `vlib/v/comptime/` and is exercised by the\nchecker, parser, and cgen stages. Changes here require a rebuild of\n`./vnew` and should be tested with `./vnew -silent test vlib/v/tests/` plus\nany comptime-specific tests. See the decision table and Testing.\n\n## Run Programs\n* Compile and run: `./vnew run file.v`.\n* Just compile: `./vnew file.v` (creates executable).\n* With debug info: `./vnew -g run file.v`.\n* Debug run (C line numbers): `./vnew -keepc -cg run file.v`.\n* Example: `./vnew run examples/hello_world.v`.\n\n## Testing\nRun:\n* File (shows test output): `./vnew path/to/file_test.v`.\n* File (test runner report only): `./vnew test path/to/file_test.v`.\n* Dir: `./vnew -silent test path/to/dir/`.\n* Dir with statistics/metrics: `./vnew -stats test path/to/dir/`.\n* Compiler: `./vnew -silent vlib/v/compiler_errors_test.v`.\n* Fix outputs (only when intended):\n  `VAUTOFIX=1 ./vnew -silent vlib/v/compiler_errors_test.v`.\n* All: `./vnew test-all`.\n  Ask before running `./vnew test-all` unless explicitly requested.\n\nWhen:\n* Rule of thumb: for localized changes, run the smallest relevant\n  tests. If any trigger below matches, run the listed tests.\n* Minimum tests listed are the floor, not the ceiling; add targeted\n  tests for cross-cutting changes.\n* If unsure which tests apply, ask the user before proceeding.\n* If in doubt, prefer the smallest targeted test and ask.\n* Run all tests that apply. Start with the smallest targeted tests;\n  add slow tests as needed. Order does not matter.\n* Compiler changes (`vlib/v/` or `cmd/v/`):\n  Run `./vnew -silent vlib/v/compiler_errors_test.v`,\n  `./vnew -silent test vlib/v/`.\n* Parser-only changes (`vlib/v/parser/`):\n  Run `./vnew -silent test vlib/v/parser/`.\n* Checker-only changes (`vlib/v/checker`):\n  Run `./vnew -silent test vlib/v/checker/`.\n* vlib changes: Run nearest `*_test.v` or\n  `./vnew -silent test vlib/path/`.\n* Tool changes (`cmd/tools/`): Run tool-specific tests. If none exist,\n  run the smallest relevant `*_test.v` that exercises the tool.\n  Note: `cmd/v/` is compiler scope, not tools.\n  Examples: `cmd/tools/vfmt` -> `vlib/v/fmt/fmt_test.v` .\n  `cmd/tools/vdoc` -> `cmd/tools/vdoc/vdoc_test.v`.\n* Diagnostic/output changes:\n  Run `./vnew -silent vlib/v/slow_tests/inout/compiler_test.v`.\n* C codegen changes: Run `./vnew -silent vlib/v/gen/c/coutput_test.v`.\n  Consider a stricter validation pass:\n  `./vnew -cstrict -cc clang -silent test vlib/v/`.\n* REPL changes: Run `./vnew -silent vlib/v/slow_tests/repl/repl_test.v`.\n* Broad refactors: Run `./vnew -silent test-all`.\n* Backend-specific changes: run the smallest relevant tests for the\n  affected backend. JS/native/WASM backends are incomplete, so avoid\n  broad `-b <backend> test vlib/` runs. Prefer targeted `*_test.v`\n  files or small test dirs with `-b js|native|wasm`.\n\nIf time-constrained, prioritize\n`./vnew -silent vlib/v/compiler_errors_test.v` and the smallest targeted tests.\nRun `vlib/v/slow_tests/inout/compiler_test.v`\nand `vlib/v/gen/c/coutput_test.v` when output or codegen changes are\nlikely.\nSee `TESTS.md` for more guidance on test selection and output\nexpectations.\nSee `CONTRIBUTING.md` for broader workflow guidance.\n\nConcrete triggers:\n* `vlib/v/slow_tests/inout/compiler_test.v` when error text or output\n  formatting changes, or changes in checker/parser error reporting.\n* `vlib/v/gen/c/coutput_test.v` for changes under `vlib/v/gen/c/` or\n  C codegen output paths.\n\nTypes:\n* Standard: `*_test.v` files with `test_` functions.\n* Output: `.vv` source + `.out` expected output in\n  `vlib/v/slow_tests/inout/`.\n  Example: `./vnew -silent vlib/v/slow_tests/inout/compiler_test.v`.\n* `vlib/v/tests/**` may use `.run.out` expectations; run with\n  `./vnew -silent test vlib/v/tests`.\n\nDocs-only guidance: see Reporting.\nIf time-boxed, run at least the smallest relevant test and note\nskipped coverage in the summary.\n\n### Useful env variables and flags while testing\n* `VAUTOFIX=1` - Auto-update .out files when tests fail (run twice).\n  Use only when a behavior change is intended.\n* `VTEST_ONLY=glob_pattern` - Run only tests matching pattern.\n* `VTEST_HIDE_OK=1` - Hide successful tests, show only failures.\n* `./vnew -silent test path/to/dir/` - Show only failed tests (if any), and a summary report.\n* `-cc tcc` can speed test builds when TCC is available.\n* Output expectations: update `.out` files only when behavior changes\n  are intended; note the rationale in the summary.\n\n## Debug\n* See what the C compiler is doing:\n  * `-showcc` prints the C compile command.\n  * `-show-c-output` prints the C compiler output.\n* Build a temporary compiler for debug flags:\n  * `./vnew -o ./w -d trace_checker cmd/v`\n  * Then run: `./w file.v`\n* Keep and inspect generated C:\n  * `-keepc -cg` is the common combo.\n  * `-printfn <name> -o file.c` emits only the named C function to standart\n    output. The `name` uses the `modulename__fnname` format (e.g.\n    `main__main`). This flag can be repeated to print multiple\n    functions. Methods/generics may use more complex C names; use\n    `-keepc` to confirm exact symbols.\n* Trace stages:\n  `-d trace_scanner|trace_parser|trace_checker|trace_gen`.\n  These flags can help diagnose a problem when a stage stops earlier\n  than expected.\n* Time stages: `-d time_parsing|time_checking`.\n* V panics: `-keepc -g`.\n* C segfaults: `-keepc -cg -cc clang`.\n* JS/native/wasm: prefer small, focused test files with\n  `-b js|native|wasm` and `-show-c-output` where applicable; avoid\n  broad `-b <backend> test vlib/`.\n* Quick code location technique:\n  When debugging code generation issues, add unique comment tags to\n  relevant code generation points (e.g., `/*tom51*/`) in the compiler\n  source. Rebuild and generate C code, then search the generated file for these\n  tags to quickly map generated C code back to the exact compiler source\n  location. This is especially useful when multiple code paths generate\n  similar-looking output and you need to identify which path is actually used.\n  Example:\n  ```v\n  // In vlib/v/gen/c/assign.v:\n  g.write('builtin___option_ok/*tom51*/(&(${styp}[]) { ')\n\n  // After rebuild, search generated C code for \"tom51\":\n  // builtin___option_ok/*tom51*/(&(int[]) { ... });\n  ```\n  Remember to remove these debug tags after fixing the issue.\n\n## Compiler Architecture\nThe V compiler has the following stages, orchestrated by the\n`v.builder` module:\n`v.scanner` -> `v.parser` -> `v.checker` -> `v.transformer` ->\n`v.markused` -> `v.gen.c`\nTheir corresponding folders are: vlib/v/scanner, vlib/v/parser,\nvlib/v/checker, vlib/v/transformer, vlib/v/markused, vlib/v/gen/c .\nThere are additional subsystems (supporting or optional compiler\nmodules) like v.comptime, v.generics, v.pref, v.reflection,\nv.callgraph, etc.\n\n### Key Directories\n* `vlib/`: Standard library (changes here can affect the compiler\n  itself).\n* `cmd/v/v.v`: Compiler entry.\n* `cmd/tools/`: vfmt, vdoc, vup, vquest, etc.\n* `examples/`: Example programs.\n* `thirdparty/`: Bundled C libraries (tcc, mbedtls, sokol, etc.).\n* `vlib/v/`: Compiler modules.\n  * ast/ - AST node definitions\n  * fmt/ - Code formatter\n  * scanner/ - Tokenizer\n  * token/ - Token definitions\n  * parser/ - Produces AST from tokens\n  * checker/ - Type checking and resolution\n  * comptime/ - Compile-time evaluation support\n  * transformer/ - Common optimisations and simplifications, makes the\n    backends simpler\n  * markused/ - Dead code eliminator\n  * gen/c/ - C code generation (primary backend, known as cgen)\n  * gen/js/ - JavaScript backend\n  * gen/native/ - Machine code generation (ELF, Mach-O)\n  * gen/wasm/ - WebAssembly backend\n\n### Test Locations\n* `vlib/v/tests/`: Compiler feature tests (including comptime).\n* `vlib/v/slow_tests/`: Output-matching and slow tests for the\n  compiler.\n* `vlib/v/slow_tests/inout/` - Output comparison tests\n  (.vv + .out pairs)\n* `vlib/v/parser/` - Parser error tests\n* `vlib/v/checker/` - Checker error tests\n* `vlib/v/gen/c/testdata/` - C codegen tests (.vv + .c.must_have)\n* `examples/compiletime/` - Comptime usage examples (including\n  `reflection.v`)\n\n## Error Reporting (checker/parser)\n* Error: `c.error('message', pos)` - hard error, stops compilation.\n* Warning: `c.warn('message', pos)` - warning, allows compilation.\n* Notice: `c.note('message', pos)` - informational only.\n* Pattern: Most checker methods use `fn (mut c Checker)` receiver.\n* Location: `vlib/v/checker/errors.v`.\n\n## Option/Result Types\n* Syntax: `?Type` (optional, can be none) vs `!Type` (result, can\n  error).\n* Common bugs: Unwrapping in if guards, struct init with option fields,\n  ternaries with options.\n* When changing option/result behavior, add a regression test in\n  `vlib/v/tests/`.\n* Tests: Search `vlib/v/tests/` for option/result test files.\n* Pitfall: Options in ternaries, SQL statements, and fixed arrays need\n  special handling in cgen.\n\n## Tools\n* Note: if a rule overlaps with Testing, follow Testing.\n* Format: `./vnew fmt -w <file>` for touched `.v` and `.vsh` files.\n  Format only touched files unless explicitly asked to reformat broader\n  scope.\n* Treat new files as touched for formatting and markdown checks.\n* Check *all* files are formatted: `./vnew -silent test-fmt`.\n  Run only when asked or when validating the full tree.\n* Check markdown: `./vnew check-md file.md` for touched `.md` files\n  (required before commits).\n* Code style checker: `./vnew vet vlib/v`\n  Run only when asked or when making broad checker changes (more than\n  3 files in `vlib/v/checker/`).\n* Module docs: `./vnew doc -readme -all -l module_name`.\n* Search: `rg pattern` (or `git grep`); list files: `rg --files`.\n* Auto-format hook: `./vnew git-fmt-hook install`.\n\n## Commits and PRs\n* See `CONTRIBUTING.md` for full commit message conventions and PR\n  workflow.\n* Keep commits focused: one logical change per commit.\n* If your branch has diverged and a rebase or merge is needed, do not\n  force-push or drop hunks without asking. State the conflict and let\n  the user decide the resolution strategy. When in doubt, prefer\n  `git rebase` over `git merge` for a linear history, but always ask\n  if the situation is ambiguous.\n\n## Environment Variables\n* VFLAGS: Pass flags to all V invocations\n  (e.g., `VFLAGS='-g' ./vnew test-all`).\n* VEXE: Path to V compiler executable (useful in CI/scripts).\n* TMPDIR: Controls where `.tmp.c` files are written (V uses\n  `TMPDIR/v/`).\n* SOURCE_DATE_EPOCH: Override build timestamp for reproducible builds\n  (affects `@BUILD_DATE`, `@BUILD_TIME`, `@BUILD_TIMESTAMP`).\n* V2-specific: `V2CC`, `V2CFLAGS`, `V2VERBOSE` (for v2 development).\n\n## Gotchas\n* Core modules (`builtin`, `strings`, `os`, `strconv`, `time`) can\n  affect the compiler because it is a V program. Rebuild `./vnew` when\n  they change.\n* Module names must match their directory name; mismatches cause silent\n  import failures. See Modules and Imports.\n* Some V programs and tools hardcode `os.execute('v ...')` in their\n  source. The `./vnew` workflow does not protect against these; if you\n  encounter unexpected behavior from such calls, check whether the\n  code is invoking the system `v` instead of `./vnew` and adjust\n  accordingly.\n* Stale `./vnew` can cause confusing failures; rebuild if behavior\n  seems off.\n* Output tests require exact matches; whitespace changes break tests.\n* Formatting reminders: follow Code Style for `fmt` and `check-md`.\n* C compilation errors? Check generated C with `-keepc`\n  (creates `/tmp/*.tmp.c`; see also TMPDIR in Environment Variables).\n* Compile-time code (`$if`, `$for`, `$embed_file`, etc.) is a common\n  source of AI mistakes. See Compile-Time Code and Reflection for\n  correct usage and pitfalls.\n* Broken compiler? See Safety for the recovery sequence.\n* Consult `CONTRIBUTING.md` and `TESTS.md` for:\n  * New tests or test infra changes.\n  * Output tests or `.out` updates.\n  * Broad refactors or compiler-wide changes.\n  * Unsure which slow test runner applies to your change.\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## V 0.5.1\n\n*9 Mar 2026*\n\n#### Improvements in the language\n\n- New clean and fast v2 backends: cleanc (similar to the old C backend), ssa/arm64, ssa/amd64,\n  cleanc backend can already self host!\n- Add a new generic solver stage (gated behind `-new-generic-solver`) (#26280)\n- Refactor $var to ${var} across entire repository, make vfmt always output the newer form\n  `${expr}` (#26494)\n- Fix support for match exprs with nested if exprs (#26599)\n- Add OS-specific headers support for #include directives (#26654) (fixes #26562)\n\n#### Checker improvements/fixes\n\n- Fix compiler panic on wrong arg count with or block (#26665)\n- Support gotodef for fn param and []Type (#26193)\n- Error for unwrapped option/result types used with in operator (fix #26208) (#26223)\n- Expand @VEXEROOT, @VMODROOT, DIR, $d(), $env() inside $embed_file(path) too (#26319)\n- Fix global empty const type check (fix #26324) (#26332)\n- Add error message call stack support (requested by #16127, #24575, etc) (#26356)\n- Fix option in struct member infix expr and swapped none comparion (fix #26351) (#26373)\n- Disallow `foo()? == foo` where foo returns `!string` (fix #26383) (#26403)\n- Unset `@VCURRENTHASH` for V build/bootstrapped outside of a Git repository (fix #26407) (#26426)\n- Check generic struct fields and initialisation (fix #26433) (fix #26436) (#26450)\n- Preserve mut in other non-none if branch (fix #26491) (#26495)\n- Fix sql statement using an unwrapped option value from an if guard (fix #26496) (#26505)\n- Add type checking for param of fn passed as generic arg (fix #26195) (#26257)\n- Add warning for `fn f(x u8) {} f(999)` (fix #26584) (fix #26585) (#26586)\n- Add passes for top level decls (fix #26306) (#26589)\n- Avoid panic on unresolved infix operand types in -check (fixes #26458) (#26607)\n- Fix shared array slice type with implicit clone (fixes #26663) (#26666)\n- Fix autofree crash with option/result method chains (#26694)\n\n#### Parser improvements\n\n- Disallow `[3]!int{}` (fix #26244) (#26249)\n- Get correct generics for generics struct fn with generic param (fix #26191) (#26251)\n- Fix dump() free bug for v.ast.TypeSymbol (fix #26282) (#26283)\n- Disallow `[T]` as fn return type  (#26530)\n- Show where another declaration is located (fixes #26483)\n- Fix `pub:` not being detected in structs in -vls-mode (#26581)\n- Fix anonymous function name collisions across files (#26642)\n- Remove @[minify] from structs with enum fields (#26661)\n\n#### Compiler internals\n\n- v.comptime,v.generics: unwrap receiver type, support more generic comptime exprs (#26350)\n- v.generic: improve new generic stage, unwrap generic ident info, set ct_expr to false if solved,\n  update receiver_type generic flag (#26366)\n- v.generics: improve the new generics stage, by fixing unwrapping in nested generic struct, also\n  fix suggestions from previous PR (#26430)\n- table: fix generics crash (fix #26438)\n- markused: add array method map and filter support (fix #26233) (#26238)\n- v.pref: exit early with an error message, if coroutines are not supported yet on the current\n  platform, instead of producing a cgen error (#26342)\n- builder: fix compile error message for -m32 (fix #16639) (#26353)\n- v.builder: add -stats for top level statements and non-vlib top level statements (#26451)\n- v.pref: improve musl detection; fixes __atomic_thread_fence for all musl nixes (fix #26449)\n  (#26460)\n- v.builder: always apply -fno-strict-aliasing too, on `-cc gcc -prod` to avoid the need for the\n  `-cflags -fno-inline-small-functions` workaround with gcc > 12.0 (fix #26512) (#26552)\n- v.scanner: optimise ident_dec_number, ident_oct_number, ident_hex_number, by using precomputed\n  digit_table and letter_table consts, instead of u8 method calls\n- v.scanner: eliminate str_helper_tokens changes outside string interpolation (fix speed loss after\n  106da40)\n- markused: add typ==0 guard for MapInit to fix panic in comptime $else branch (#26652)\n\n#### Standard library\n\n- builtin.closure: improve ppc64le closure if PIE (#26172)\n- rand.xoroshiro128pp: prevent generation of extra zeros in u16() (#26229)\n- thirdparty: fix tcc __atomic_thread_fence (fix #25856) (fix #26158) (#26185)\n- builtin.closure: use volatile register for s390x (fix #24383) (#26256)\n- thirdparty: update zstd patch with commit 8aa0369 (#26312)\n- regex.pcre: add non-greedy quantifiers like `*?`, `+?`, `??` (fix #26579) (#26582)\n- regex.pcre: optimise for speed the PCRE implementation (#26609)\n- atomic: and/or bitwise ops (#26646)\n- x.json2: add a `strict: true` mode for x.json2.decode(), that rejects string-to-number type\n  casting during decoding (fix #26082) (#26220)\n- builtin: add array.last_index() (#26252)\n- bitfield: fix pop_count(), add test (#26262)\n- io: deprecate the `io.string_reader` module (not used in vlib, with confusing and under\n  tested/documented API - see #25713 ) (#26274)\n- time: add Duration.times/1\n- os: add Pipe.write_string/1 (#26286)\n- gg: add .draw_ellipse_filled_rotate and .draw_ellipse_empty_rotate APIs (#26309)\n- gg: add draw_ellipse_thick and draw_ellipse_thick_rotate (#26327)\n- os: fix args quoting in win_spawn_process (fix #26261) (#26339)\n- gg: optimize ellipses draw functions (#26340)\n- gg: text_width_f\n- math: fix acosh() for 0.0 (#26360)\n- math: rewrite round() to match closely the Go version (and mpfr's one), update test (#26381)\n- gg: optimise the ``draw_rounded_rect_filled`` function (#26390)\n- os: add missing is_opened checks to File.read* functions (fix #26096) (#26413)\n- x.json2: add `@[json: name]` attr support for enum values (fix #26437) (#26441)\n- x.json2: rename Any.arr() to Any.as_array() for consistency with as_map(), as_map_of_string();\n  deprecate Any.arr() (#26455)\n- breaking,x.ttf: extract vlib/x/ttf/render_sokol_cpu.v in a separate module x.ttf.render_sokol,\n  to enable headless programs, that do not use gg, to not depend on OpenGL, DX12, Metal etc, through\n  sokol (#26477)\n- crypto.blake3: add @[direct_array_access] and improve f() performance (#26480)\n- crypto.rc4: add `@[direct_array_access]` (#26507)\n- x.crypto.slhdsa: fix slh signature testing on latest version (fix #24086) (#26519)\n- crypto.pbkdf2: replace a panic with an error return (#26526)\n- regex: fixed missing OR operation on anchor flag (#26540)\n- regex: new PCRE compliant regex submodule written in pure V, available through\n  `import regex.pcre` (#26545)\n- x.json2: fix decoding wrong value depending on field order (fix #26503) (#26571)\n- crypto: add shake128 and shake256 entries into crypto.Hash enum (#26576)\n- vlib: add x.atomics - implement native_x86-64_atomics in V and assembly, without depending on an\n  external C library (impl #26474) (#26529)\n- os: use _dyld_get_image_name() to increase compatibility with older versions of Mac OS X like\n  10.4 (#26617)\n- crypto: move up AEAD interface from experimental namespace to `cipher.AEAD` (#26632)\n- builtin: fix `camel_to_snake` underscore placement in uppercase runs (#26634)\n- time: parse_http_header_string (#26636)\n- flag: add DocOptions/Show to FlagParser (#26630)\n- runtime: fix issues with nr_cpus() (#26679)\n- thirdparty,sokol: add wayland support (#26682)\n- thirdparty,sokol: fix frame pacing issues on xwayland sessions, prevent sending some keycode\n  events on wayland (#26706)\n\n#### Web\n\n- net: add raw sockets support (implement feature request from #19565) (#26237)\n- veb: remove 2 clones of response bodies; reduce the GC load for the most common case (fix #25423)\n  (#26236)\n- wasm: support basic match keyword handling (#26246)\n- wasm: fix infinite loop using continue in C-like for loops (#26250)\n- wasm: add basic `for x in start .. end {` support (#26248)\n- wasm: implement basic string operations (#26260)\n- veb: fix double-send error when after-middleware sends response (#26270)\n- builder,wasm: fix pointer size to 4 for `-b wasm` before the checker stage (#26281)\n- wasm: support basic string interpolation (#26288)\n- wasm: fix string plus assign with call expr (#26287)\n- wasm: handle `for` in strings and FixedArrays (#26290)\n- wasm: support WASI program arguments and IO functions (#26294)\n- net.mbedtls: increase default timeout to 10s (like in Go): 550ms was too low\n- net: add jsonrpc module (#26330)\n- fasthttp,veb: static files via sendfile\n- wasm: fix size of pointers in structs (#26357)\n- thirdparty.mbedtls: upgrade to v3.6.5 (#26365)\n- wasm: only compile `.wasm.v`, and platform independent `.v` files (#26386)\n- fasthttp: fix sendfile (#26402)\n- wasm: add run support with wasm-micro-runtime/iwasm (#26417)\n- veb: fix unset Content-Length header, in responses with an empty body (#26431)\n- veb: fix error lines for html templates via source to source mapping\n- net.http: enable test for relative redirects (#26513)\n- fasthttp: fix IPv6 support (fix #26548) (#26549)\n- mbedtls: better ux around client timeout by mentioning the mbedtls_client_read_timeout_ms flag\n  (#26574)\n- Document `$veb.html()` too in the compiler error messages, as a known comptime function (#26605)\n- fasthttp: remove zero-byte initialization in read buffer #26640\n- net.http: stop reading after Content-Length bytes on keep-alive responses (#26669)\n\n#### ORM\n\n- Add explicit JOIN support (INNER, LEFT, RIGHT, FULL OUTER) (fix #21635) (#26400)\n- Support embedded structs\n- Make work with generic structs\n- Fix generic struct creation inside a generic function\n- Resolve generic inserting object type\n- Cgen bug fix (fixes #25847)\n- Handle inserting enum fields (#26680)\n- Add aggregate function support (#26697)\n- Add transaction API with savepoint-backed nesting (#26707)\n\n#### Database drivers\n\n- mysql: use correct link flag for both tcc and msvc (#26539)\n- pg: exec_no_null(); gx: remove deprecated test; parser/tmpl: %raw translations;\n  veb: time_to_render()\n- fix(db.sqlite): replace vstring() with tos_clone() to prevent use-after-free (#26700)\n- feat(db.sqlite): add Row.names, get_string/get_int, and improve exec_map (#26702)\n\n#### C backend\n\n- Fix multi dim fixed array with opt elem (fix #26243) (#26258)\n- Fix array.contains() when right is ref (fix #26253) (#26255)\n- Ast,checker,cgen,parser: fix comptime $if assign expr (fix #26061) (#26242)\n- Promote non generic sumtype pointer initialiations to the heap too (#26285)\n- Fix generic function error propagation type mismatch (fix #26263) (#26295)\n- Fix interface pass string ref arg (fix #26293) (#26296)\n- Fix shared array assigned call expr with fixed array (#26320)\n- Fix fixed array of option with different size (#26326)\n- Fix call with fixed array of builtin struct (#26328)\n- Fix array init with option array (fix #26329) (#26331)\n- Fix alias indent (fix #26272) (#26333)\n- Fix chan autostr (fix #26337) (#26338)\n- Transformer,markused,cgen: fix some problem for array init when use `-new-transformer` (#26341)\n- Fix `-assert backtraces` after e317c63\n- Fix for function-like macro '_BIONIC_AVAILABILITY_GUARD' which is not defined in older termux\n  releases (#26345)\n- Fix empty shared struct init (fix #16234) (#26354)\n- Add rv32 inline assembly support (#26362)\n- Fix fn arg for struct nested fields (fix #26346) (#26349)\n- Fix `+=` overloading for aliases, regression after 29e60da #23967 (fix #26416) (#26423)\n- Fix unused functions returning fixed arrays of custom structs (fix #26439) (#26440)\n- Fix or-block with fixed array constants with GCC 15.2 (fix #26442) (#26443)\n- Fix uninitialized interface bug (closes #17372)\n- Fix regression in `./v test vlib/toml` after 38ac4e6 (#26485)\n- Fix generation of struct initialisers for structs with option fields, inside ternaries (fix\n  #26476) (#26493)\n- Fix the saving of g.skip_stmt_pos and g.stmt_path_pos when generating anonymous fns (fix #26498)\n  (#26508)\n- Fix generic type handling bugs\n- Fix -autofree used for code doing \"string ${f(@VEXE)} interpolation\" (#26521)\n- Fix multi-return match in closure (fix #26558) (#26566)\n- Fix alias for interface and option types (fix #26551) (#26565)\n- Autofree fix generic math.min[T] used with time.Time (fix #26575) (#26577)\n- Fix extra dereference when indexing array of fns passed by pointer (fix #26556) (#26591)\n- Fix orm shared conn on sql expr (fixes #26479) (#26610)\n- Fix comptime match assign in generic fn, T.name string intp (fix #26053) (#26597)\n- Fix bit-field generation for option/result types in minified st… (#26670)\n- Use unsigned int for enum bit fields or unspecified size in @[minify] structs (#26678)\n- Fix auto-deref var in autofree string re-assignment (#26689)\n\n#### vfmt\n\n- Fix parser failing on duplicate methods in $if/$else blocks (fix #26271) (#26278)\n\n#### Tools\n\n- vwatch: fix process handle leak in kill_pgroup() (#26269)\n- vwatch: fix `-o` short flag conflict that broke hot reload (fix #26221) (#26277)\n- vcomplete: add git-fmt-hook command (#26396)\n- vrepl: fix handling of `//` inside string literals (fix #25603) (#26240)\n- v.help: add help for git-fmt-hook tool (#26394)\n- Add support for `v missdoc @vlib`\n- Add support for `v quest`\n- Add support for `v install --local gui`\n- Support .vcheckignore pattern files for `v check-md .` (#26623)\n\n#### Operating System support\n\n- msvc: split multi-token -I/-L values from pkg-config (#26637)\n- wasm: fix path separator in windows (#26264)\n- time: fix overflow in time.sys_mono_now() on windows (#26273)\n- sokol: fix errors for audio unsupported on OpenBSD (fix #26299) (#26305)\n- db.pg: improve support on OpenBSD (#26316)\n- os: fix get_raw_line for EOF on OpenBSD (fix #26361) (#26368)\n- Add support for vgit-fmt-hook on OpenBSD (fix #26344) (#26388)\n- builtin: use -Xlinker flags on macos, for compilers != tcc, to pass the rpath folder (fix for\n  folders with spaces)\n- builtin: fix for tcc builds on paths with spaces on linux\n- os: implement readlink/1 on !windows (#26405)\n- builtin: fix compilation with tcc on OpenBSD using libgc (fix #26447) (#26448)\n- fasthttp: multi threading fix reads in the socket in linux (#26478)\n- time: prevent linux time functions from being included in non-linux platforms (#26596)\n- Fix hanging when printing to console in a `-subsystem windows` executable (#26572)\n- builder: fix Windows pkgconfig paths and MSVC flags (#26631)\n- net.vschannel: chunk large TLS payloads to fix 16KB EncryptMessage crash on Windows (#26681)\n\n#### Examples\n\n- examples,strings: add a new `strings.lorem` module; use it in the Markov chain text generator\n  example (#26387)\n- Add examples/gg/pong/pong.v (#26528)\n- Improve pidigits.v using a much faster spigot algorithm\n- sokol: fix `v run examples/2048/` on macos (regressed after 5d6de17) (#26705)\n\n## V 0.5.0\n\n*31 Dec 2025*\n\n#### Improvements in the language\n\n- Add comptime `if is shared` support (fix #25600) (#25602)\n- Make `defer{}` scoped by default, use `defer(fn){}` to get the old behavior #25639) (#25665)\n- Add gotodef support for nested struct members, fn return types, etc (#26131)\n- Add a new v.comptime stage `COMPTIME`, that runs after the checker (`CHECK`), and before the\n  transformer (`TRANSFORM`), to simplify the work that later stages do #26068 (#26161)\n\n#### Checker improvements/fixes\n\n- Correctly detect variadic arg passed to struct fn (fix #25504) (#25509)\n- Fix $(field.name) access on closure fn (fix #25513) (#25514)\n- vls: skip unrelated files (#25531)\n- Fix mutability in `for in` loops with pointer values (fix #25520) (#25536)\n- Fix type inference, when pushing an empty array to a 2D array (fix #23854) (#25508)\n- Prevent array.insert for array of references when non-reference is passed (fix #25511) (#25557)\n- Add more support for mod autocomplete, allow for .vv files too (#25562)\n- Fix cast from an empty struct to option (fix #25566) (#25581)\n- Ensure ?Struct is not parsed as ??Struct when param is ?T (fix #25559) (#25564)\n- Fix if branch type nr_muls mismatch (fix #25556) (fix #25555) (#25571)\n- Fix comptime else branch handling (fix #25586) (#25589)\n- Smart detect `or {}` inside loop when using `c <-val` (fix #24550) (#25435)\n- Vls fix goto definition (#25595)\n- Fix generic resolve for external module generic static method call (fix #21476) (#25634)\n- Correctly detect type, when prepending to generic array (fix #25585) (#25645)\n- Allow cast from voidptr to sumtype in unsafe block (fix #25652) (#25657)\n- Disallow calls to a shared receiver method, on a non-shared var (fix #25577) (#25656)\n- Fix or block endwiths expr (fix #25329) (#25667)\n- Set ast file fallbacks for vls (fix #25678) (#25679)\n- Error/warn when using `defer(fn)` inside function-scope and `lock` stmts (#25681)\n- Maintain correct ref level in generic fn (fix #25676) (#25687)\n- In vls mode, make ensure_type_exists return true (#25695)\n- Only collect/hoist inner vars, when `defer` is function-scoped (#25693)\n- Improve type checking for sumtypes with generics (fix #25690) (#25699)\n- Unwrap for base type if ft.typ and inferred_typ are both opt (fix #25517) (#25728)\n- Disallow deference of nil (fix #25740) (#25746)\n- Fix comptime main fn (#25747)\n- Parser,fmt,checker: use a trie for matching the generic array methods `all`, `any`, `count`,\n  `filter`, `map`, `sort` and `sorted` (#25759)\n- Fix array fixed unresolved return check and resolver (fix #25774) (#25790)\n- Allow explicit sumtype to option casts (fix #25796) (#25812)\n- Fix possible race on expected arg types unwrapping on cgen (#25815)\n- Skip init check for options (fix #25798) (#25830)\n- Fix module var set at change_current_file() (fix #25845) (#25846)\n- Improve handling of array decompose for dynamic arrays and array init (fix #25838) (#25843)\n- Force all fn declarations to follow after all other top level statements (fix #25889) (#25890)\n- Fix used features tracking when printing pointer values (fix #25899) (#25901)\n- Match type when auto deref occurs (fix #25913) (#25916)\n- Relax the redundant () check to a notice, to enable a future `v -W test vlib/builtin` job on the\n  CI\n- remove () from match branch exprs (fix #25950) (#25952)\n- Fix array map anon fn return fixed array (fix #25928) (#25977)\n- Cleanup the output of `v new --web abcd` after feedback from https://youtu.be/IuE6Bo1klK0?t=555\n- Allow assign to a shared int var (fix #25986) (#25988)\n- Ensure type of global exists (fix #25910) (#25998)\n- Ensure fn pointer cannot be used as non-fn argument (fix #26017) (#26022)\n- Make sure  `$for` eval body statements at least once to set types and avoid markused issues later\n  (fix #26058) (#26063)\n- Fix return static method name (fix #26105) (#26110)\n- Support gotodef for struct init and sumtype rhs (#26157)\n- Detect circular type references in sumtype declarations (fix #24511) (#26162)\n- Add interface type handling and new testcase (fix #24116) (#26165)\n- Allow enum fields to reference previously declared fields (fix #25241) (#26173)\n- Clear all ref from autostr receiver_type (needed by #25857) (#26202)\n- Allow for `_` being used as both `import x as _` and `fn f(_ int) {` (fix (#26219) #26230\n\n#### Parser improvements\n\n- Fix vls mode strut mut keyword (fix #25548) (#25551)\n- Fix vfmt comment in struct init after the update expr (fix #24361) (#25668)\n- Fix infix expr comment in middle (fix #24183) (#25671)\n- Disallow using generic functions as a field type name inside struct decl (fix #25452) (#25705)\n- Warn on `@[deprecated_after]` used without a corresponding `@[deprecated]` attribute (#25712)\n- Fix last stmt is fn call in or_expr (fix #25732) (#25739)\n- Allow for `|mut x, y|expr` (fix #25734) (#25735)\n- Allow using `a`, `b` and `it` as var names, when using the builtin array methods (fix #25729)\n  (#25755)\n- Disallow generic function to be exported (fix #25794) (#25806)\n- Support `-d trace_parse` to ease diagnosing problems related to the order of parsing of .v files\n  in modules\n- Fix the language support for a nested anonymous C.struct (fix #25807) (#25789)\n- Disallow untyped `chan` used as a fn parameter type (fix #25818) (#25854)\n- Improve the unused import warning message (add fixing alternatives) (#25880)\n- checker,parser,ast: make `type MyBuilder = strings.Builder` work (part 1); add `mod` fields to\n  ast.SumTypeDecl and ast.AliasTypeDecl (#25943)\n- Remove dead code in Parser.is_array_type/0 (#26080)\n- Check invalid struct name in struct_init() (fix #26030) (#26093)\n- Remove the support for the obsolete generic fn call syntax f<T>() (first deprecated in 2022/11)\n  (#26126)\n- Fix comptime for lock shared field (fix #26143) (#26146)\n- checker,parser: add multifile gotodef support for -line-info (#26167)\n- Optmize Parser.call_kind (#26196)\n\n#### Compiler internals\n\n- markused: fix markused struct heap (#25542)\n- markused: fix array.prepend C code dependency (fix #25573) (#25582)\n- markused: fix fn marked as used when variable and fn uses same name (fix #25649) (#25650)\n- checker,transformer: add always true/false branch detection for the `if` and `match` constructs\n  (#25674)\n- v.util: measure more precisely how long a new tool recompilation lasts in launch_tool, when using\n  `v -d trace_launch_tool self`\n- transformer: fix struct init comparison turning into boolean (#25724)\n- v.builder: support V_NO_RM_CLEANUP_FILES=1, to ease debugging of -usecache issues\n- v.builder: make it easier to reproduce the exact specific stages of -usecache module compilation\n  by logging the full CLI options for each\n- v.builder: fix `.vsh` mode doing an implicit `import os`, now only for .vsh file itself (fix\n  issue spotted in #25736) (#25745)\n- v.builder: improve diagnostic information for a failed build_thirdparty_obj_file\n- transformer: transform ArrayInit into a function call for C and native backends (part 1)\n- builder,pref: add  `-file-list` support (implement feature #25707) (#25749)\n- pref: for -usecache, set .parallel_cc = false and .no_parallel = true to make compilations more\n  deterministic and ease CI diagnostics\n- markused: fix missing builtin__memdup definition, when an option struct field is used (fix\n  #25801) (#25802)\n- transformer: move array logic to array.v\n- v.builder: improve the error message for failing cgen; suggest `-g` and `-show-c-output`\n- v.pref: fix GitHub download URL for the photonwrapper .so file (fix #25708) (#25831)\n- v.pref: use `v download` for downloading the prebuilt `photonwrapper` shared library (#25849)\n- markused: fix const as fn mark as used (fix #25888) (#25895)\n- transformer: disable generic str_intp opt (fix #25896) (#25897)\n- v.scanner: remove obsolete .is_crlf and .is_vh fields (#25918)\n- v.scanner: use a named return for decode_XXX_escape_single methods, to reduce the generated C diff\n  churn, during scanner code updates\n- markused: add new auto_str() used funcs for bootstrap (#25938)\n- v.builder: provide more detailed error message, on `msvc: failed to build a thirdparty object`,\n  not just the failed command\n- v.builder: improve formatting of the `failed to build a thirdparty object` message for msvc\n- scanner: remove old generic check logic (fix #25959) (#25997)\n- transformer: fix the setting of a generic flag for fixed array type with `-new-transformer` (\n  #26009)\n- transformer: add file/line info for fn with `expand_simple_interpolation` (#26135)\n- transformer: add early return to avoid transform getting applied twice for a `for x < y {` body (\n  #26153)\n- markused: fix option none markused (fix #26147) (#26151)\n- v.builder: enable gc back with msvc, build separate `.debug.obj` thirdparty files when -g is\n  passed, to prevent linking issues (#26215)\n- v.builder: support compiling asm .S files to .o files, mentioned in #flag directives (needed for\n  #26185) (#26211)\n- v.builder: fix compile asm file, followup of PR #26211 (#26227)\n\n#### Standard library\n\n- arrays: fix rotate_left() and rotate_right(), add test (#25539)\n- encoding.base58: fix encoding, add test (#25538)\n- x.crypto.chacha20poly1305: move up responsibility for allocs into higher caller (#25574)\n- crypto.cipher: fix decryption in CBC mode, add test (#25584)\n- os: use `@[noinline]` on os.create/1 to workaround a `-cc gcc -prod` panic (fix #25549)\n- time: fix non-digit checks for parse_rfc3339() (#25597)\n- gg: add explicit bounds checking for image caching methods in gg (fix #25590) (#25591)\n- time: fix quarter calculation in custom_format() (#25608)\n- rand: fix randomness in shuffle() (#25617)\n- gg: destroy unused GPU resources before replacing cached images (#25615)\n- encoding.binary: fix serialize skip struct shared fields (related to issue #25600) (#25613)\n- x.crypto.chacha20poly1305: make implementation use fixed sized arrays more (#25627)\n- builtin: make result string end with null in `u8(x).repeat(y)` (fix regression after #22100) (\n  #25625)\n- gg: fix address of const warnings for `v -experimental program_using_gg.v`\n- builtin: add .hex() methods to the `rune` and `char` types too (#25635)\n- datatypes: fix insert() and delete() for items in second half of DoubleLinkedList[T]{}, add test (\n  #25647)\n- builtin: use an explicit loop to determine min_common_indent in string.trim_indent/0 to reduce\n  allocations and reduce the reasons for misfires of the closure detection heuristic\n- vlib: use `defer(fn) {` syntax where appropriate (part 2 of #25639) (#25653)\n- x.json2: fix decode_number not initializing value to zero (fix #25641) (#25675)\n- crypto.hmac: optimize hmac.new, support calculations with a blocksize > 256 (#25686)\n- math.unsigned: fix put_bytes(), add test (#25718)\n- builtin: reset .len and .cap to 0 too, in the array.free() method (#25717)\n- os: add pipe and stdio_capture support (implement #25714) (#25716)\n- encoding.utf8.validate: fix validation, add test (#25748)\n- crypto.blake2b,crypto.blake2s: add `@[direct_array_access]` to hot functions (#25750)\n- strconv: fix handling of subnormal numbers like `'1.23e-308'.f64()` (fix #25751) (#25752)\n- crypto.sha3: remove `import math` (just for int_max), to improve compilation time and complexity\n  for code that uses sha3\n- builtin: add declarations for C.GetCurrentThreadId(), C.gettid() and C.pthread_self()\n- builtin: add pid: and tid: fields to the panic reports (part 2 of #25808) (#25809)\n- gg: add doc comments for the FN** types (#25814)\n- rand: add missing i8() utility function (#25819)\n- builtin: fix C.SYSTEM_INFO (fix #25788) (#25823)\n- builtin: support `-d no_getpid` and `-d no_gettid` for systems that lack proper process management\n  APIs\n- math: fix vec2,3,4 project not using the right formulas (fix #25811) (#25813)\n- math.vec: swap u and v in the .project() method of Vec2,Vec3,Vec4 (#25841)\n- crypto.cipher: fix xor_key_stream() for OFB mode, add test (#25844)\n- encoding.binary: use unions for small speed increase and readability (#25867)\n- math.complex: replace `==` with eq_epsilon() in equals() (#25873)\n- crypto.cipher: fix xor_key_stream() for CTR mode, add test vector created with OpenSSL (#25866)\n- os: enhance os.cp() to mimic Python's shutil.copy2() (#25893)\n- io.util: use correct TempDirOptions parameter type name in temp_dir() (#25904)\n- builtin,sync: eliminate calls to _us32_lt in new_map/6, and in the spinloops in\n  Channel.try_push_priv, Channel.try_pop (#25912)\n- rand: restore error margin in dist_test.v back to 0.05 (the updated seeds were found by @tankf33er\n  in #25907)\n- builtin: reduce the max size of string representations of integers (#25919)\n- builtin: remove commented code, improve comments\n- x.crypto.chacha20: fix deprecation warning during compilation of Cipher.rekey/2\n- math.easing: fix in_out_expo(), add test (#25944)\n- builtin: split builtin.v and builtin.c.v into smaller, and more focused .v files, to ease working\n  on unrelated subsystems (#25965)\n- transformer: fix `v -new-transformer vlib/strconv/atoi_test.v` (#26021)\n- gg: add more documentation for color substraction (fix #21549) (#26023)\n- toml: fix for single `\\r` occurence in multi-line `\"\"\"` strings (`\\r\\n` is still allowed) (#26029)\n- toml: remove workarounds + `TODO`s for fixed issue #9507 (#26037)\n- x.json2: fix decode_number for u8 (fix #26027) (#26033)\n- rand.wyrand: switch to using the original C._wymix() as a performance optimisation (#26051)\n- strconv: fix float scientific notation (fix #26045) (#26046)\n- x.json2: fix decoding of float values in scientific notation (fix #26043) (fix #26062) (#26060)\n- builtin: add a declaration for C.memchr too (#26054)\n- toml: add compliance up until official toml-lang/toml-test@c6a78f1 (#26067)\n- builtin: fix some C fn parameter types (#26069)\n- toml: add compliance to official toml-lang/toml-test@8bb8d9c (#26070)\n- toml: remove special cases for `jq` normalization (#26092)\n- toml: fix remaining valid `key/*` exceptions (#26125)\n- builtin: make string.index_ public, to simplify code using a redundant\n  `x := s.index(sub) or { -1 }` pattern (#26123)\n- builtin: add declarations for C.memmem and C.mempcpy (#26129)\n- builtin: speed up, fix and test impl_utf8_to_utf32 (#26109)\n- toml: fix remaining valid `array/*` exception (#26138)\n- toml: fix unicode decoding panic on invalid TOML `key/duplicate-keys-06.toml` (#26140)\n- toml: allow `true` and `false` as keys when parsing root table (#26144)\n- toml: allow dotted key lengths > 2 within nested arrays of arrays (#26145)\n- flag: fix `v vet -W vlib/flag/` (fix remaining doc comments)\n- x.json2: fix memory access error, when decoding string enum values (fix #26176) (fix #26179) (\n  #26178)\n- toml: fix invalid exception by erroring on duplicate keys in inline table (#26177)\n- time: implement faster and simpler `push_http_header` (#26155)\n- toml: fix remaining invalid exceptions for `table/*` (#26189)\n- toml: reach 100% TOML v1.0.0 compliance with the official test suite (#26203)\n- x.json2: remove workaround_cast(), add isize usize decode support (#26210)\n\n#### Web\n\n- net: fix cookie parsing when `;` is used (fix #25544) (#25561)\n- veb: new fasthttp module with -d new_veb (multithreaded, epoll/kqueue): makes veb multithreaded\n  and fixes frequent hangs\n- veb: fix gzip middleware decode/encode (fix #20865) (fix #25753) (#25754)\n- veb: gzip support for StaticHandler (fix #20859) (#25758)\n- veb: support markdown content negotiation, compliant with https://llmstxt.org/ (#25782)\n- fasthttp: move kqueue related code to a separate file\n- veb: add zstd compression support (#25816)\n- veb: remove println('send_file ct=...') leftover (#25834)\n- ci: reduce false positives for veb_should_listen_on_both_ipv4_and_ipv6_by_default_test.v by\n  retrying it 3 times (since sometimes binding to the port it listens to fails)\n- veb: add an early startup panic error message, when the result type of route handler methods *is\n  not* `veb.Result` (fix #25970) (#25973)\n- net.mbedtls: make errors more verbose, to ease remote diagnosis of issues\n- net.openssl: make errors more verbose, to ease remote diagnosis of issues\n- veb: improve the before_request documentation\n- veb: add method.location too, to the invalid return type error, to ease diagnosing problems while\n  prototyping\n- wasm: fix const reference another const (fix #25722) (#26010)\n- fasthttp: fixes and improvements (#25906)\n- wasm: export pub fns in main module when targeting wasi (#26041)\n- net.http: use error_with_code in download_file() (fix #26056) (#26057)\n- net.http,veb: fix detection of the headers/body boundary in parse_request_head_str (fix #26091) (\n  #26112)\n- fasthttp: expand http request parser (related to #26091 part1) (#26104)\n- net.ftp: fix get() command conversation, add test (fix #18858) (#26194)\n- x.sessions: verify HMAC signatures when extracting sessions IDs from cookies (#26199)\n- net.http: fix a panic in parse_multipart_form, for small/incomplete form data (fix #26204)\n- net.http: support keep-alive connections in server (fix #26136) (#26218)\n\n#### ORM\n\n- Mark orm_where_in_test.v to be skipped in the sanitize-memory-clang job\n- Fix fkey insert as assigment expr (fix #25568) (#25575)\n- Fix double fkey insert and update (fix #25593) (#25606)\n- Add index attr support (#25604)\n- Fix autofree detection for is_or with block style (fix #25969) (#26089)\n- Allow multiple set() in one update() call (fix #26116) (#26117)\n- Add check for invalid index field name (#26142)\n- Supoprt DISTINCT keyword (#26163)\n\n#### Database drivers\n\n- db.sqlite: fix orm f32 field retrieval for sqlite (fix #25583) (#25592)\n- db.pg: support returning `Result` type with column names (#25737)\n- db.sqlite: allow for\n  `mut db := sqlite.connect_full(\":memory:\", [.readwrite, .create, .fullmutex], \"\")!` defaulting to\n  unix/win32 depending on the platform\n- db.pg: support LISTEN/NOTIFY (implement feature #23983) (#26133)\n- db.pg: fix `v check-md vlib/db/pg/README.md`\n- Revert \"db.sqlite: support calling exec_param_many with [][]string or []string (it now accepts a\n  sumtype of both) (#26100)\"\n- Reapply \"db.sqlite: support calling exec_param_many with [][]string or []string (it now accepts a\n  sumtype of both) (#26100)\"\n\n#### Native backend\n\n- Fixed array, `-new-transformer` dynamic array (#25817)\n- Add `$if trace_native_todos ? {` to reduce noise in `v test-all`\n\n#### C backend\n\n- Fix resolution type Map[string]T when T is AliasToMap (fix #25494) (#25510)\n- Fix markused for option generic param (fix #25501) (#25525)\n- Fix empty struct initializer for clang (fix #25467) (#25526)\n- Fix match codegen for option match case (fix #25533) (#25537)\n- Fix codegen for alias for array fixed initialization (fix #25512) (#25540)\n- Ensure option none/ok state is also compared (#25532)\n- Fix match codegen for option expr on case (fix #25545) (#25553)\n- Add `-no-closures` option to detect closure usage earlier (for emscripten or for less well\n  supported platforms) (#25565)\n- Create ctemp before lockexpr gen (fix #25576) (#25612)\n- Fix if expr with condition that requires temporary variable (fix #19584) (fix #23903) (#25621)\n- Fix multi return of a fixed array (fix #25626) (#25628)\n- Fix generic multiple indirections on print (fix #22793) (#25633)\n- Fix `fn (d Struct) a[T]() T { return d }` when T is a sumtype (#25644)\n- Minimize code generated for asserts (generate the common parts for the pass/fail case once) (\n  #25642)\n- Handle pointers in json map decode/encode (fix #25632) (#25646)\n- Fix `defer` stmts with `if` exprs and `or` blocks that return a value (#25651)\n- Fix infix expr ComptimeSelector type (fix #25659) (#25662)\n- Fix passing sumtype child to generic function taking sumtype parent (fix #25660) (#25664)\n- Fix multi generics fn name (fix #23886) (#25673)\n- Fix `defer` generation within comptime `$if`/`$match`/`$for` (#25677)\n- Fix codegen for if comptime and array fixed (fix #25691) (#25697)\n- Correct function definitions for callbacks in imported modules (fix #25700) (#25719)\n- Improve codegen for array fixed init for g++ compiler (fix #25723) (#25725)\n- Fix codegen for operator overload method_name on alias to builtin types (fix #25709) (#25726)\n- Fix missing cast if fixed array is surrounded in brackets (fix #25629) (#25741)\n- Fix comptime for types not being recognized with maps correctly (fix #25742) (#25743)\n- Fix dump(ptr_to_fixed_array_value) - it now returns the argument directly (thanks @tankf33der) (\n  #25764)\n- Cast member variables to correct types in comptime $for (fix #25771) (#25773)\n- Include `ast.ComptimeSelector` in fixed array checks (fix #25767) (#25777)\n- Checker,cgen,type_resolver: prevent stale type cast on comptime `$for`, handle in dumpexpr (fix\n  #25781) (#25784)\n- Reduce the nested expr level complexity of Gen.ident\n- Fix tcc __attribute__, fix os.notify (followup to #25779) (#25804)\n- Ensure array of string is not cloned with depth 0 (fix #25783) (#25793)\n- Support `-d trace_check` and `-d trace_cgen` to help diagnose checker and cgen ordering issues\n- Support `-d trace_cgen_fn_decl` and `-d trace_cgen_gen_fn_decl` too\n- Show the v_gettid() hex with `-d trace_cgen_fn_decl` and `-d trace_cgen_gen_fn_decl`\n- Use variadic_count == 1 when passing variadic to call of same array type (fix #25827) (#25837)\n- Fix nested or in assign decl (fix #25864) (#25865)\n- Fix variadic on translated (fix #25862) (#25876)\n- Allow @[cinit] for const variables (#25881)\n- Fallback to field type when default_expr_typ is 0 (fix #25891) (#25903)\n- Fix map value init with array fixed const (fix #25887) (#25902)\n- Fix cast type changed before last stmt in `stmts_with_tmp_var` (#25915)\n- Update wyhash to version 4.2 (#25907)\n- Use final_sym for elem_sym in index_of_array (fix #25960) (#25961)\n- Fix variadic call on sumtype with array of itself (fix #25898) (#25964)\n- Correct T{} init for []Type aliases (fix #25962) (#25963)\n- Fix array init with fixed array from return call (fix #25954) (#25971)\n- Fix fntype unwrap on ifguard (fix #25911) (#25914)\n- Add a source .location field to `$for method in Type.methods {` (#25976)\n- Fix iterator on alias to fn ptr (fix #25911) (#25978)\n- Fix shared int string intp (fix #25984) (#25989)\n- Allow init shared field with default value (fix #25990) (#25991)\n- Allow init of struct from struct with array of optional values (fix #26000) (#26005)\n- Fix default value in if/else or block (fix #26002) (#26020)\n- Fix fnptr indirections declaration (fix #25940) (#25987)\n- Fix bool cast from value (fix #26028) (#26031)\n- Fix cast() generic type bug (fix #26065) (#26066)\n- Fix fn_var_signature() support nr_muls (fix #26049) (#26075)\n- Fix cast_expr() for alias (fix #26076) (#26079)\n- Handle CallExpr in dumpexpr (fix #26084) (#26087)\n- Clean code in return stmt (fix #25968) (#26118)\n- Fix cast to array (fix #26099) (#26102)\n- Fix fn_var_signature() allow option type (fix #26088) (#26120)\n- Fix scoped struct array fixed generation (fix #26111) (#26114)\n- Fix option array init with non option values (fix #26148) (#26170)\n- Fix heap fixed array assign (fix #26149) (#26169)\n- Fix stack overflow for `@[heap]` structs with large fixed arrays (fix #22690) (#26183)\n- Fix print interface when arg0 is function call (fix #26184) (#26188)\n- Checker,table,cgen: fix generic interface confusion (fix #25478) (#26181)\n\n#### vfmt\n\n- Force conversion of []Type{init: it} -> []Type{init: index} (#26201)\n\n#### Tools\n\n- ci: run `v doc` with VJOBS=1 on the CI, to make remote diagnosing of failures easier\n- Remove unused `sw := time.new_stopwatch()` call\n- Add support for VTEST_SHOW_CMD=1 in `v test .` too\n- ci: use VJOBS=1 for the `v test cmd/tools/vdoc` step too, to ease diagnosing remote CI failures\n- ci: bump cross-platform-actions/action from 0.29.0 to 0.30.0 (#25666)\n- Fix showing the *failed* compilation output with `v -silent test .`\n- ci: bump all `timeout-minutes: 15` to `timeout-minutes: 20` to reduce false positives due to\n  network timeouts (mostly for the Termux job)\n- Note about `v help check-md` when `v check-md .` fails\n- ci: skip invalid_utf8_string.vv in compiler_errors_test.v for msvc\n- ci: reduce annotation noise, remove dead code\n- ci: skip the multistage v->v2->v3 -usecache checks for now (reduce false positives on the CI for\n  unrelated PRs, until the root cause is fixed)\n- ci: add new job `sanitize-address-clang-without-gc` that passes `-gc none` through VFLAGS (#25780)\n- Support\n  ```\n  VTEST_SHOW_LONGEST_BY_RUNTIME=5 \\\n  VTEST_SHOW_LONGEST_BY_COMPTIME=5 \\\n  VTEST_SHOW_LONGEST_BY_TOTALTIME=5 \\\n  v test .\n  ```\n- Print total time at the *end* of the `v test-all` output to ease visual comparisons in separate\n  shells, without scrolling\n- Use unbuffer_stdout in TestSession.test, to ensure consistent output on the CI jobs\n- v.builder: remove the obsolete check for V_NO_C_ERROR_INFO (VQUIET=1 replaced it in 2023); add\n  VQUIET to the `-q` description\n- Make `v search` failures easier to diagnose (on the CI)\n- Support `v download -o some/folder/local.toml TOML_URL`, in addition to --target-folder\n- Add `--sha3-256` support for checksumming the content that `v download` saves\n- Add a watchdog timer in test_if_v_test_system_works.v to speedup the failure of stuck CI jobs\n- Use local `vtest build:` tags to eliminate the need for the skip_fsanitize_too_slow list in\n  vtest-self.v\n- ci,vpm: make dependency_test.v more robust, and easier to diagnose remotely\n- ci: set VTMP too in set_test_env/1, to avoid cloning conflicts during parallel test executions\n- v.builder: do not produce `If the code is in a folder with multiple .v files` for temp V REPL\n  files, to improve messages for `'asdas'.starts_wiz('xyz')`\n- Add a `-new-transformer` task to `v test-all`. Remove `-skip-unused` flags (it is the default\n  for ~1 year).\n- Improve development experience for `v -W -silent test-self vlib` (especially on CIs); *always*\n  show compilation errors for failures\n- Support `VTEST_KEEP_SESSION=1 ./v test vlib/math`\n- vet: use new annotation syntax ([] -> @[]) (#26026)\n- ci: bump cross-platform-actions/action from 0.31.0 to 0.32.0 (#26074)\n- Make the `is_sqlite3_present` check more robust (work with the system packaged sqlite library\n  again too)\n\n#### Operating System support\n\n- ci: fix gcc-windows -std=c99 (#25534)\n- os: add windows stdin_write() support (#25546)\n- ci: use `macos-14` instead of `macos-13` (the older runner is being deprecated) (#25670)\n- v.builder: fix json-errors with a windows path separator (#25680)\n- ci: fix unsetting of VFLAGS in `v run ci/linux_ci.vsh v_self_compilation_usecache_clang`\n- ci: stop unsetting VFLAGS completely in ci/linux_ci.vsh and ci/macos_ci.vsh\n- builtin,os: fix windows execute ANSI encoding result, make msvc error messages readable in a\n  Chinese locale (fix #25727) (#25736)\n- db.sqlite: update windows version to https://sqlite.org/2025/sqlite-amalgamation-3510000.zip (\n  #25766)\n- os.notify: fix struct epoll_event alignment on ARM64/Linux (fix #25778) (#25779)\n- fasthttp: Linux/epoll support\n- math: reduce the nested level of expressions, to reduce the chances of stack overflows on windows\n- net.http,ci,db.sqlite: rewrite .github/workflows/windows-install-sqlite.bat in .vsh, fix vschannel\n  on windows downloading content > 32KB (#25792)\n- v.builder: bump the default stack size for executables, when compiling with msvc on windows, to\n  32MB (#25824)\n- ci: reduce the chances of false positives due to hangs of use_net_and_net_unix_together_test.v on\n  windows\n- doc: add subsections about using SQLite on windows and about installing the self contained\n  `sqlite` module.\n- v.builder: switch to using `-std=c99`, instead of `-std=gnu99` to avoid name colisions with C\n  `linux` macros defined by gcc/clang (#25848)\n- gg: set more sensible and user friendly defaults for the width, height and the title of new\n  windows\n- thirdparty: update thirdparty-openbsd-amd64_tcc.sh (#25945)\n- ci: install plain gcc on the OpenBSD jobs\n- ci: use `gcc` as the name of the compiler instead of `egcc` on OpenBSD\n- ci: remove the gcc-openbsd job, until OpenBSD people fix their broken conventions on 7.8\n- ci: run `v -W -silent test-self vlib` on linux, so deprecations/warnings introduced in PRs, can\n  fail (and be fixed) earlier (#25955)\n- ci: use VTEST_SHOW_LONGEST_BY_* vars on OpenBSD (#25958)\n- ci: update to use FreeBSD version 15.0 (#25985)\n- crypto.ecdsa: update to test and use OpenSSL 3.5 on OpenBSD (#25995)\n- x.crypto.slhdsa: add support on OpenBSD using OpenSSL 3.5 (#25996)\n- ci: reduce failure rate for the gcc-windows job, in test_if_v_test_system_works.v\n- ci: skip use_net_and_net_unix_together_test.v on gcc-windows (many weird timeouts on unrelated\n  PRs)\n- db.sqlite: fix exec_param_many on linux for the case of a [][]string parameter\n- v.util: add `-d max_suggestions_limit=140` for v itself, to improve handling of large .v files\n  with many thousands of lines on windows\n- v.util: bump max_suggestions_limit to 200, to account for windows\n- ci: extract windows_ci_msvc.yml from windows_ci.yml to enable finer grained workflow/job control\n- ci: extract and split windows_ci_tcc.yml and windows_ci_gcc.yml from windows_ci.yml for improved\n  job control\n\n#### Examples\n\n- Handle closing of the window in the event manager in examples/viewer (#25522)\n- ci: add a report-wrong-examples-in-doc-comments job, that runs\n  `./v doc -check-examples -f none vlib/` (#25554)\n- Make reproduction of failed examples easier (make sure that all the checked sources have an ending\n  \\n)\n- Use math.vec in path_tracing.v and in vyper.v\n- Support `v -d trace_execution run examples/brainvuck.v mandlebrot.bf`\n- ci: do not use `-silent` for the `v build-examples` task on windows, to make it easier to diagnose\n  recent gcc-windows timeouts\n- doc: add an example for reading from a non empty buffered channel, after closing it\n- Fix and improve vanilla_http_server (#25905)\n- ci: remove `-silent` from the macos build_examples task too, to make remote diagnosing of CI\n  timeouts easier\n- Add optional `update_fn: fn (dt f32, ctx &gg.Context)` to gg.Context and gg.Config . Pass\n  consistently the current GG context to *all* callback functions, instead of nil.\n- Add expanding_rect.v (modeled after the example from https://love2d.org/wiki/love), add generic\n  helpers gg.frgb/3 gg.frgba/4\n- tools,examples,veb: fix `v -d trace_before_request run examples/veb/veb_example.v` after feedback\n  from https://youtu.be/IuE6Bo1klK0?t=2100\n- Move flag/ .v files 1 level up, to prevent module lookup confusion for unrelated examples\n- Add a Lorem Ipsum Generator (#26036)\n- examples,net.ftp,v.builder: remove remaining matches of\n  `rg --multiline --multiline-dotall \"continue\\n\\t+\\}\\n\\t+\\}\\n\\t+return\" -B3 -A3 `\n- Update lorem.v with a Markov algorithm for better text generation (#26085)\n- fasthttp: fix the correctness of the minimal server example, when tested with curl (#26072)\n- v.gen.native: fix `v -os macos -experimental -b native -o hw.macos examples/hello_world.v` on\n  linux\n- tutorials: remove newline in the example for c2v's cc compilation to `doomv` (#26200)\n- Make all the labels fit in the default window size header in minesweeper.v\n\n## V 0.4.12\n\n*19 Sep 2025*\n\n#### Improvements in the language\n\n- json2: replace encoder with a new implementation. It's 70% faster than the old json2, and 110%\n  faster than json that is based on cJSON (#25224)\n- Virtual C consts with custom types (const C.MY_CONST u8)\n- Support `-div-by-zero-is-zero`, which allows for `x / 0 == 0` and `x % 0 == x`, avoiding division\n  by zero traps/panics (#24981)\n- Limit -div-by-zero-is-zero influence to just the integer types (for f32 and f64, / produces a +inf\n  or -inf value, and the program continues to run)\n- VLS mode for the language server in pure V\n- Add support for `@OS`, `@CCOMPILER` `@BACKEND` and `@PLATFORM` (#25174)\n\n#### Breaking changes\n\n- Deprecate `gx` and replace all occurences with `gg` (which now contains all the functionality of\n  `gx`) (#24966)\n\n#### Checker improvements/fixes\n\n- Fix `sizeof(T)` usage in generic struct (fix #24806) (#24808)\n- Add `$if sizeof(T) == int_literal {` support (#24831)\n- Improve virtual C consts\n- Markused,checker: fix hello world size after the introduction of `builtin.closure` in 2d87ac4 (\n  #24989)\n- Remove dump() dependency from ComptimeFor (#25000)\n- Cleanup - remove unused c.using_new_err_struct (#25036)\n- Cleanup `err` removal (#25043)\n- Add comptime support for s390x, ppc64le and loongarch64 platforms (#25048)\n- Allow for `v -is_o -o x mm.v`, where `mm.v` starts with `module abc` (i.e. not just `module main`)\n- Fix calls with result propagation, using other consts, in const declaration expressions (fix\n  #21609) (#25060)\n- Fix array init with interface (fix #24255) (#25073)\n- Fix missing map float key duplicated checking (fix #25098) (#25117)\n- Fix missing check for struct generic init from call (fix #25084) (#25119)\n- Fix missing check for empty array to generic param (fix #25056) (#25118)\n- Rewrite comptime_if_cond() to support comptime if cond evaluate (fix #24938) (fix #25099) (#25122)\n- Add error for struct not init (fix #24893) (#25134)\n- Fix sql insert expr propagate result (fix #24833) (#25136)\n- Fix checking return type call disregarding unwrapping (fix #25140) (#25143)\n- Ensure the defer behavior matches that of cgen (fix #25148) (#25146)\n- Nil check for c.table.cur_fn in gen_branch_context_string() (fix #25170) (#25171)\n- Relax the \"unreachable code after a @[noreturn] call\" error to a warning to reduce prototyping\n  friction (#25173)\n- Fix multi return arg passing checking (fix #25167) (fix #25180) (#25177)\n- Use keywords matcher trie for imported symbol presence checks, instead of\n  `x in p.imported_symbol` (#25201)\n- Fix iteration over mutable option (fix #24860) (#25199)\n- Add `T.typ` and `T.unaliased_typ` checking to `$match` (fix #25200) (#25202)\n- Add more checks for map.delete (fix #25204) (#25205)\n- Fix static init var (fix #25203) (#25209)\n- Add top level comptime support for `$match @OS {` too (#25222)\n- Comptime match only eval true branch (fix #25223) (#25225)\n- Fix multi return var passing to fn arg (potential fix for #24870) (#25250)\n- Prevent usage of imported module name prefix as identifier names, to avoid cgen collisions (\n  #25280)\n- Disallow duplicate export names (fix #25301) (#25302)\n- Reduce the verboseness of `unsupported size ... for global` messages, for\n  `v -b native examples/hello_world.v`\n\n#### Parser improvements\n\n- Split parser methods to files based on topic (#24786)\n- Fix arch loongarch64 comptime support (fix #24906) (#24907)\n- Fix const error\n- pref,parser: implement support for `-force-bounds-checking` to enable easier testing of functions\n  tagged with `@[direct_array_access]` (essentially turning off that flag)\n- Allow keyword as struct param key on fn call (fix #24957) (#24958)\n- Fix syntax error for `for c in [othermod.Struct{field: 255}] {` (fix #24943) (#24978)\n- Reduce calls to util.contains_capital\n- Fix overriding of fn names in `-translated` mode (fix #25024) (#25061)\n- Fix asm modifier parsing (allow for `=r, =&r, +r, +&r,=m,=rm,=@ccl, =*r`) (fix #25070) (#25072)\n- Allow using aliased types in interface method implementations (provide backwards compatibility to\n  `ui`, during the migration of code from `gx` to `gg`) (#25106)\n- Fix interface method declaration with fixed array return type (fix #25137) (#25145)\n- Prepare for eliminating a warning for `v -cross -o vc/v.c cmd/v` (part 1) (reduce CI annotation\n  noise)\n- Add duplicate import symbol detect (fix #25185) (#25187)\n- vfmt,parser: move mark used from vfmt to parser (#25190)\n- v.ast: add a `mod` field to ast.FnTypeDecl too\n\n#### Compiler internals\n\n- scanner: fix multi-level string interpolation in if/match branch (#24805)\n- markused: fix mark for array init from sumtype (fix #24887) (#24889)\n- markused: whitelist `_option_none` too (fix #24862) (#24885)\n- markused: remove `@[markused]` from option and result fns (#24900)\n- markused: skip unused symbols, dump fns and generic specialization (fix #24921) (fix #24927) (\n  #24924)\n- parser,markused: support `@[markused]` for interface declarations too (#24963)\n- markused: fix interface fields and chan usage (fix #24961) (#24962)\n- v.builder: add a clearer error message for `v -shared run empty.v` (issue found by Felipe Pena)\n- markused: use eprintln for `PANIC DEPS` too (for consistency and easier redirection for the whole\n  trace)\n- v.util: add support for setting VUTIL_RETRY_MAX_COUNT=1 to ease the workflow for developing\n  backends\n- markused: improve the tracking of used closures (#25009)\n- markused: improve array resources tracking + remove all_fns loop for orm (#25007)\n- markused: fix generic map index (fix #25012) (#25022)\n- markused: improve array tracking (range, gated) (#25023)\n- markused: fix option tracking on sumtype (fix #25025) (#25028)\n- markused: fix thread type mark by go/spawn expr (fix #25049) (#25054)\n- scanner: refactor string interpolation (fix #24198) (#25053)\n- markused: fix array append c code dependency (fix #25057) (#25058)\n- markused: fix option array element (fix #23089) (#25179)\n- markused: fix option map value (fix #25186) (#25188)\n- parser,fmt,markused: add top level comptime `$if` support (enable\n  `$if platform { import module struct Abc {} }`) (#25216)\n- v.builder: add -DNO_DEBUGGING in addition to -DNDEBUG, when compiling with -prod\n- v.builder: support `-d trace_type_symbols_after_checker`\n- scanner: uncomment working rune test  (#25305)\n- v.util: fix handling of \"start \\u005c${...} end\" in cgen (fix #25304) (#25306)\n- markused: fix marking of mutable generic method calls (fix #25312) (#25314)\n\n#### Standard library\n\n- x.crypto: initial addition of curve25519 module (#24748)\n- thirdparty: add NDEBUG check before glGetErrorCode if-statement in sokol_gfx.h (#24754)\n- math.big: remove unnecessary code from / and % (the same is done in div_mod, which they call) (\n  #24766)\n- builtin: add a rune iterator method to strings, allowing `for for i, r in s.runes_iterator() {`\n  without first allocating an array for all the runes (#24769)\n- builtin: support `-d builtin_free_nop` to help diagnose problems with too early manual free()\n  calls\n- builtin: use s.runes_iterator() in trim_runes/2 to avoid needless allocation\n- builtin: add string.expand_tabs() (#24781)\n- os: do not resolve symlinks in os.find_abs_path_of_executable/1 (fix #24759) (#24761)\n- os: improve documentation (#24790)\n- gg: allow for `-d gg_memory_trace_frame` to be used in combination with\n  `-prealloc -d prealloc_dump`\n- sync: add SpinLock (#24788)\n- os: fix documentation for environ function (#24796)\n- sync: fix documentation for new_spin_lock function (#24795)\n- sync: add implementation for WaitGroup.go/1, add test (#24797)\n- sync: improve documentation (#24799)\n- sync: fix spin lock, add destroy() and try_lock(), add valgrind annotate support (#24798)\n- os: add os.write_bytes/2 as a complement to os.read_bytes/1, add test\n- sync: use SpinLock for channel (fix #24680) (#24802)\n- crypto: fix ambiguous expressions in DES implementation (#24814)\n- sync: use an atomic counter in test_waitgroup_go in waitgroup_test.v\n- datatypes: add lockfree version of counter and ringbuffer (#24839)\n- sync: add thread local storage (TLS) support (#24849)\n- math.unsigned: fix rotate_left() for uint256, add test (#24872)\n- math.unsigned: replace untested comments for uint256 public APIs (#24873)\n- log: use `@[noinline]` for level_from_tag/1 and target_from_label/1 to avoid triggering panics for\n  programs using `log`, compiled with -prod and -cc gcc>10 (fix #24874)\n- math.big: fix toom-cook 3-way multiplication (#24888)\n- runtime: add used_memory() (#24897)\n- runtime: add note for the availability of the used_memory implementation (#24913)\n- os: remove commented code in home_dir() function (#24929)\n- math.big: fix the order of calculations in mod_pow() to improve performance (#24935)\n- math.big: add shrink zeros to karatsuba and toom-cook (#24937)\n- math.big: fix big_mod_pow() (#24939)\n- os,runtime: move some C struct and fn def to `builtin` (#24942)\n- math.big: fix validate_string and integer_from_regular_string (check for characters.len > 0,\n  before accessing characters[0])\n- builtin: prepare for adding a `-force-bounds-checking` option\n- strconv: fix bounds check bug, discovered by the equivalent of\n  `./v -g -force-bounds-checking test vlib/toml/` (thanks to tankf33der)\n- builtin: fix OOB bugs in s.is_bin, s.is_oct, s.is_hex, discovered through\n  `./v -force-bounds-checking test vlib/builtin/`\n- regex: fix OOB bug discovered through `./v -g -force-bounds-checking vlib/regex/` (fix by\n  @penguindark) (#24960)\n- time: fix custom_format panic (fix #24977) (#24987)\n- time: fix more panics in the supported specifiers in Time.custom_format/1 (#24988)\n- vlib: add `archive.tar` module to enable reading of .tar ang .tar.gz files (#24995)\n- builtin: fix warnings for `./v doc -m -f html vlib/builtin/`\n- sokol.gfx: set the missed array_count field too in the `set_vert_uniform` and\n  `set_frag_uniform` APIs (#25019)\n- builtin: fix `assert \"ä ö å æ ã ø ô é ë\".title() == \"Ä Ö Å Æ Ã Ø Ô É Ë\"`\n  (fix #25017) (#25026)\n- Apply `@[markused]` to builtin_init, remove its heuristic from markused.v\n- gg: improve drawing effect and logic of draw_rounded_rect_empty (#25062)\n- math.bits: add asm implementations for some 64 bit ops (#25020)\n- vls: autocomplete for module functions: e.g. `os. ...`\n- math.big: move from u32 to u60 digits (#25018)\n- os: simplify file.c.v using cross platform f.seek/2 calls, add EINTR handling to\n  f.write_full_buffer/2 (fix #25107) (#25110)\n- builtin: add arr.pop_left() func (#25133)\n- math.big: refactor add_digit_array() (#25138)\n- math.big: optimize add_digit_array() (#25139)\n- math.big: optimize subtract_digit_array() (#25142)\n- strconv: produce a maximum of 8 digits after the `.` for f32.str() (fix #25141) (#25144)\n- math.big: restore and refactor str() and integer_from_string() (#25154)\n- os: remove `unknown host OS` panic from os.get_host_os()\n- flag: fix tail/single bool flag error condition logic in `flag_to.v` (fix #25166) (#25172)\n- flag: improve the fix for #25166 tail/single bool flag error in `flag_to.v` (#25189)\n- readline: fix wide char display width for Chinese characters (fix #25219) (#25220)\n- repl: fix handling of lines with comments like `math.pi // comment` (fix #25229)\n- time: always return utc() timezone for Time.unix/0 (fix #17784) (#25233)\n- builtin: fix C prefix for proc_pidpath() (#25239)\n- math.big: replace division with Knuth, improve performance (#25242)\n- time: move the nanosecond comparison before the rest in the Time == Time implementation\n- builtin: add a temporary ctovstring_impl/1 API to enable `ui` to compile cleanly for PR#25264,\n  part 1\n- json2: replace encoder with new implementation (#25224)\n- json2: improve enum decoding; fix handling of required fields at the end of a json string (#25289)\n- json2: improve checker with better EOF detection (#25075)\n- json2: prepare for moving into json2 (#25039)\n- json2: fix remaining json2 discrepancies (#25029)\n- json2: support custom decoders (#25021)\n- json2: fix number decoding and improve errors (#25015)\n- json2: add support for decoding utf-16 surrogates, produced by some JSON encoder implementations (\n  Python, Java, C#) (#25193)\n\n- x.crypto: add a new `ascon` cryptographic module, based\n  on https://doi.org/10.6028/NIST.SP.800-232 (Lightweight Cryptography Standards for Constrained\n  Devices) (#25260)\n- x.crypto.ascon: improve the core of Ascon permutation routine (#25278)\n- x.crypto.ascon: improve single-shot functions of ascon hashing variant; add benchmark (#25282)\n- x.crypto.chacha20: improves the internals of chacha20, add a bench (#25311)\n\n### V interpreter\n\n- Add comptime-if support (#24919)\n- Reset return value after const eval and fix if-expr (#24955)\n- Add more infix op support; fix early func return (#24965)\n- Fix if-else; add infix op; fix func calls (#24972)\n\n#### Web\n\n- picoev: fix documentation (#24811)\n- veb: fix `app.text()` -> `ctx.text()` in `README.md`\n- net.http: fix panic in parse_multipart_form for invalid boundary (fix #24974) (#24976)\n- net.http: remove debug println statement from post_multipart_form (#25030)\n- net.http: reduce the false positives on the CI for server_test.v, let\n  test_host_header_sent_to_server return early, when the server can not start\n- net: improve tracing output for `-d trace_tcp`; move `error_code()` calls right after the\n  corresponding C APIs (errno is a global that should be read immediately to be valid)\n- veb: fix a spurious error with Chromium, for POST requests, split into 2 parts, 1st with only http\n  headers, without body (fix #25191) (#25195)\n- net.http: Use a full url when using a proxy, instead of only the path (#25228)\n- net.http.file: allow for serving requests to static files with cache busting suffixes like\n  `/dist/littlejs.js?1117`\n- veb: fix generic field access from alias (fix #25215) (#25246)\n- ci: change url to http://archive.ubuntu.com in .github/workflows/disable_azure_mirror.sh\n\n#### ORM\n\n- Support lowercase operators `like`, `in`, `not in` etc (fix #25032) (#25035)\n- Fix sub_structs (fix #25104) (#25105)\n\n#### Database drivers\n\n- db: modify mysql/pg/sqlite interface for pool working (#24780)\n- db.sqlite: fix get_text trimming data after (including) first 0 character (#25040)\n\n#### Native backend\n\n- Add comptime cpu archs support (#24956)\n- Add support for (elf) globals  (#25016)\n- Improve consts, support more assigns (#25277)\n- Structs multi_assign and multi_return (#25281)\n- Support more assign ops, reduce code duplication (#25283)\n- Begin array support, `a := []Type{len: x, cap: y}` and `a[i]` read/write (#25299)\n\n#### C backend\n\n- Only run freestanding_module_import on amd64 (#24763)\n- Fix sumtype option unwrapping (fix #24746) (#24770)\n- Protect against unlimited recursion in type_default_impl, by converting to a verror/1 call instead\n- Fix `static` and `volatile` var deref (fix #24778) (fix #24779) (#24807)\n- Fix codegen for interface method closure get (fix #24810) (#24818)\n- Fix codegen for multi return assignment with option type (fix #24812) (#24817)\n- Fix if codegen when func parameter is option type (fix #24813) (#24816)\n- Skip `struct none {` in cgen, if `none` is not used by V code reachable from `fn main() {` (\n  #24824)\n- Skip `struct map {` and related type declarations, when no V maps are used (#24826)\n- Fix anon struct encode (fix #24836) (#24852)\n- Fix json decode option alias (fix #24843) (#24853)\n- Fix const indexexpr dep (fix #24850) (#24851)\n- Fix codegen for generic interface with multi return generic type (fix #24838) (#24858)\n- Fix anon struct init passing (fix #24879) (#24884)\n- Allow alias to map `type Dict = map[string]string` (fix #24878) (#24883)\n- Builtin,cgen,markused: add struct @[aligned] support for structs allocated on the heap too (\n  #24886)\n- Add a `__closure_init` call for sokol/gg programs on android as well (#24892)\n- Allow alias types to be iterated if parent type has `next` method (fix #24890) (#24894)\n- Use alias `next` method if defined in `for x in iterator {` (#24905)\n- Fix const fixed array with type alias (fix #24936) (#24946)\n- Fix callback codegen on generic struct resolution (fix #24947) (#24948)\n- Move sort fn after interface definitions(fix #24465) (#24967)\n- Fix struct field init within fn without result type (fix #24970) (#24973)\n- Move closure C code to V code under vlib/builtin/closure/ (#24912)\n- Parser,ast,checker,cgen: use enum comparisons instead of string ones on\n  ast.ComptimeCall.method_name (#25003)\n- Fix generic key's type with `in` operation (fix #24983) (#25011)\n- Remove unused enum declarations too (#25033)\n- Parser,checker,cgen: remove unused `err` declaration or `or { }` blocks (#25034)\n- Add a test for builtin_init being present (part 2 of 4a6941a)\n- Fix closures on s390x, ppc64le, loongarch64 platforms, add test to s390x CI (#25047)\n- Fix anon fn checking adding unresolved generic type on codegen (fix #25050) (#25055)\n- Fix building on Termux after fa904c4\n- Use `#if defined __BIONIC_AVAILABILITY_GUARD && ...` to be compatible with more Termux versions\n- Fix asm stmt separators (#25067)\n- Fix translated file fixed-array assignment (#25080)\n- Fix codegen for passing int from selector to voidptr expect arg (fix #25081) (#25083)\n- Fix codegen for option void fn return block unwrap (fix #25074) (#25082)\n- Fix alias to sumtype cast initialization (fix #25086) (#25091)\n- Allow alias sumtype smartcasting (fix #25085) (#25096)\n- Fix codegen for generic struct field array option (fix #25093) (#25097)\n- Fix mutable sumtype (fix #25108) (#25111)\n- Fix generic return assign to ComptimeSelector (fix #25125) (#25131)\n- Fix address of call with `cast(&(arr.last() as Type))` (fix #23528) (#25132)\n- Fix eq for anon C structs (#25152)\n- Fix generated str method for enums that have C values (use ifs, instead of switch) (fix #25135) (\n  #25157)\n- Fix autofree with option array (fix #25124) (#25149)\n- Fix assigning fn address (fix #24537) (#25158)\n- Fix veb alias type identification and generic CastExpr (fix #24895) (#25155)\n- Revert \"checker,cgen: evaluate comptime `$if` results in checker *only* (fix #25123) (fix\n  #25156) (#25150)\"\n- Evaluate comptime if results in checker only (with fixed -cross compilation) (#25162)\n- Fix generic_fn_name generating incorrect names for C structs (#25164)\n- Add comptime match support (#25165)\n- Fix resolving generic interface field from generic struct (fix #23556) (#25182)\n- Fix autofree used vars on return (fix #25196) (#25198)\n- Fix hash stmt code generation (fix #25184) (#25207)\n- Expose is_embed in FieldData (#25232)\n- Fix alias enum used in comptime `$for` (fix #25211) (#25212)\n- Ensure variable names do not conflict with builtin methods (fix #25063) (#25178)\"\n- Add `@[reused]` attribute to mark methods, reusing the receiver memory on return (needed for\n  autofree) (fix #25221) (#25235)\n- Fix gen_struct_equality_fn null pointer crash (fix #25237) (#25231)\n- Allow generic alias enum comptime (fix #25249) (#25251)\n- Fix big IntegerLiteral LL postfix (fix #25269) (#25275)\n- Prefix `builtin` APIs with `builtin__` (#25264)\n- Fix fixed-array const initializer (fix #25291) (#25293)\n- Fix generic cast to sumtype of empty struct (fix #25263) (#25290)\n- Fix option variadic arg passing (fix #25261) (#25273)\n- Support for 64bit int 1 (#25236)\n- Cgen,parser,markused: add export const support (fix #25300) (#25303)\n- Fix i64 enum as a map key, when the enum values are too small (fix #25294) (#25310)\n\n#### JavaScript backend\n\n- Simplify comptime if; catch up with cgen (fix #25295) (#25313)\n\n#### vfmt\n\n- Fix `if x := g() { x } else { return }` adding newline after `return` (fix #24908) (#24945)\n- Fix eating the attribute from `@[deprecated] pub type Alias = int` (fix #24968), workaround\n  -usecache bug (#24969)\n- Fix call expr with single line comment in or expr (fix #24659) (#25159)\n- Fix comment line number in file with crlf line separator (fix #23524) (#25163)\n- Add support for 64bit int with `-new_int` (part 2) (#25298)\n\n#### Tools\n\n- v.vmod,tools: support a repo_branch property in v.mod files, in addition to the existing repo_url\n  property, to allow for backlinks to repos that use `main` instead of `master` as their core branch\n- Make the output of `v should-compile-all` more immediately useful in CI jobs (turn off stdout\n  buffering)\n- Add support for `// vtest vflags: -w` in `_test.v` files, to allow `v -W test .` later, for files,\n  that have known warnings\n- ci: make sure the generator for vlang/docs can be compiled with latest V (prevent silent doc\n  update stops, after breaking changes)\n- Add cmd/tools/gg_split_memdump_to_frames.vsh to ease working with memdump.bin files generated by\n  gg programs (split by frames)\n- Add find_doc_comments_with_no_dots.v\n- Improve summary output of find_doc_comments_with_no_dots.v\n- Skip _test.v and _test.c.v files in find_doc_comments_with_no_dots.v\n- ci: add report-missing-dots-in-doc-comments job\n- ci: mark tcp_test.v and unix_socket_test.v as flaky (they still fail sporadically on the CI,\n  although very rarely now)\n- ci: add `-prealloc` self compilation checks on more platforms (#24891)\n- docs,ci: check more vlib modules in the report-missing-dots-in-doc-comments job (#24928)\n- ci: add a watchdog timer thread to ringbuffer_test.v, to make sure the program exits in a\n  reasonable time (~10s). Let the test be retried 2 times in a row if it fails.\n- ci: bump cross-platform-actions/action from 0.28.0 to 0.29.0 (#24952)\n- ci: retry session_app_test.v 2 times, since it is network dependent, and sometimes (rarely) fails\n- v.help: document the new `-force-bounds-checking` option\n- Improve alignment for `v repeat \"program\" \"program_that_is_over_10x_faster\"`\n- ci: add checks for compilation of vlang/gui to v_apps_and_modules_compile_ci.yml\n- ci: retry 2 times vlib/net/http/server_test.v to avoid false positives for unrelated commits/PRs\n- ci: force changes to vlib/x/json2 to trigger the full sanitized checks (the implementation there\n  uses unsafe blocks and vmemcmp/3...)\n- ci: workaround -usecache issue afte 2d87ac4\n- ci: add a performance-compare-with-master job\n- Fix `return\"\"` in vdoc html output (fix #24979)\n- ci,tools: implement support for VREPEAT_SILENT=1 and `v repeat -S`, to only show the summary of\n  the runs, without the progress lines\n- ci: fix the performance-compare-with-master job, when run on PRs (#25014)\n- ci: trigger updates to the module docs, even if just only the static files for the doc generator\n  are changed\n- ci: make sure to always compare with the latest commit on the main V repo's master branch, when\n  running .github/workflows/compare_pr_to_master.v\n- ci: compare the sizes of small programs like hello_world.v, but generated with `-cc gcc` too\n- ci: improve the alignment of the results of file size comparisons in compare_pr_to_master.v\n- Improve the output of `./v doc -m -f html vlib/`\n- Use `Copying` instead of `Generating` for the static resources in `./v doc -m -f html vlib/`\n- ci: bump actions/download-artifact from 4 to 5 (#25051)\n- v.help: document the `-is_o option` (in `v help build-c`) and add a test for it (#25052)\n- ci: add experimental support for building V and testing on a Termux docker container (#25059)\n- ci: use retry.sh for the `pkg install` in termux_ci.yml to reduce false positives.\n- ci: update vlang/gui commit its latest e5cc33fe816fef33d718cb1b91f66d6bd38fb4a4\n- ci: bump actions/checkout from 4 to 5 (#25095)\n- ci: retry 3 times vdoc_file_test.v\n- ci: add a build_on_ubuntu_25_ci.yml script, for testing bootstrapping with GCC 14.2.0 (#25109)\n- ci: define TERMUX_VERSION in .github/workflows/termux_ci.yml instead of using `-os termux`, to\n  make the emulation closer to a real Termux (#25128)\n- ci: reduce timeout-minutes for CI jobs that are normally fast to help detect anomalies earlier (\n  #25129)\n- ci: add a disable_azure_mirror.sh script, and use it before `apt update` to reduce the recent\n  timeouts during installing dependencies (#25147)\n- ci: bump timeout-minutes to 15 in termux_ci.yml\n- ci: bump actions/setup-java from 4 to 5 (#25153)\n- ci: retry vlib/v/eval/interpret_test.v 2 times\n- ci: bump retry time from 10 to 15 minutes (reduce false positives for slow dependency\n  installations on the CI)\n- ci: change the azure mirror URL in /etc/apt/sources.list too\n- ci: use `awalsh128/cache-apt-pkgs-action@v1.5.3` instead of a manual `apt update/apt install`\n  step, to leverage caching more (#25256)\n- ci: check if `awalsh128/cache-apt-pkgs-action@v1.5.3` works on master (#25257)\n- ci: extract .github/actions/cache-apt-packages-action/action.yml, use it in puzzle_vibes_ci.yml\n\n#### Operating System support\n\n- docs: add section in README for compilation on OpenBSD (#24775)\n- crypto.ecdsa: add support for OpenSSL on OpenBSD (#24772)\n- picoev: add implementation for OpenBSD using kqueue (#24801)\n- log: fix `Unhandled Exception` on windows 7 (#24803)\n- ci: migrate the remaining jobs from the deprecated windows-2019 image to windows-2022 (#24825)\n- os: fix windows get_error_msg() leak (#24899)\n- runtime: reduce allocations done in runtime.used_memory/0 on linux (#24901)\n- ci: skip checking vlib/datatypes/lockfree/ringbuffer_test.v on the gcc-windows job for now\n- runtime: add used_memory() implementation for FreeBSD (#24909)\n- runtime: add used_memory implementation for OpenBSD (#24918)\n- ci: skip ringbuffer_test.v in the tcc-windows and msvc-windows jobs too, to avoid flakyness for\n  unrelated commits/PRs.\n- ci: use FreeBSD version 14.3 after the bump of cross-platform-actions/action to 0.29.0 (#24953)\n- time: fix timezone test on windows\n- ci: add a release build for Linux on arm64 to release_ci.yml (#25064)\n- thirdparty: add `thirdparty-linux-armv7_bdwgc.sh` for building `libgc.a` on ARMv7 CPUs (#25077)\n- ci: bump retry count for server_test.v to 5 (reduce false positives on windows)\n- ci: use `v build-tools` without flags for the tools-windows job\n- os: eliminate warning for `v -cross -o vc/v.c cmd/v` on linux (part 2, see also 037a3b4)\n- os,sync: enable running `v -cross -o x.c cmd/v` on windows too (part 1, fix V errors)\n- ci: run .github/workflows/disable_azure_mirror.sh before all `apt update` commands, in\n  ci/linux_ci.vsh, when run in a github CI runner\n- ci: retry 3 times cmd/tools/vtimeout_test.v on windows, before failing\n- os,ci: use a conditional include, instead of a platform file, to include libproc.h on macos only\n- ci: run input_rune_iterator_test.v only on linux for now\n- builtin: fix thread naming issue on Windows by ignoring RaiseException (0x406D1388) (#25270)\n\n#### Examples\n\n- Fix for `v build-tools` and `v build-examples` running on a i686 (the problem was discovered by\n  @tankf33der)\n- Add examples/sokol/sounds/simple_keyboard_synth.v\n- builtin,markused: consider println of non string to use .str() method calls too, reduce generated\n  C code for `v -cc gcc examples/hello_world.v` (#24996)\n- Use a sieve of Eratosthenes in primes.v, to handle bigger inputs more efficiently\n- vdoc: make -run-examples compatible with all output modes, not just the plaintext one\n- vdoc: extract vdoc_run_examples_test.v from vdoc_file_test.v\n- vdoc: implement -unsafe-run-examples and -check-examples support, add tests and document them\n- builtin,vdoc: fix the examples for the builtin methods, so that\n  `v doc -check-examples -time -f ansi vlib/builtin/` pass\n- builtin,vdoc: make `v doc -unsafe-run-examples -time -f ansi vlib/builtin/` pass too\n- vdoc: improve failed example report\n- vdoc: support `v doc -check-examples -f none vlib/builtin`\n- bitfield: fix `v doc -unsafe-run-examples -f none vlib/bitfield/` too\n- arrays.parallel: fix `v doc -unsafe-run-examples -f none vlib/arrays/parallel/` too\n- arrays: fix `v doc -unsafe-run-examples -f none vlib/arrays/` too\n- compress.deflate,compress.gzip,compress.zlib,compress.zstd: fix\n  `v doc -unsafe-run-examples -f none vlib/compress/` too\n- sokol.audio: fix doc comment examples\n- encoding.base64: fix doc comment examples\n- math: fix doc comment examples\n- readline: fix doc comment example by removing it\n- semver: fix doc comment examples\n- vdoc: enable example lines that have explicit imports too, fixup the remaining vlib examples, so\n  `v doc -v -unsafe-run-examples -f none vlib/` could be added to the CI\n- Add euler.v\n- examples,gg: add examples/gg/grid_of_rectangles.v; add gg.Context.draw_rect_filled_no_context/5\n  and gg.Context.draw_rect_empty_no_context/5\n- veb.auth: update the README.md example (#25245)\n- builtin: fix `v -W -Wimpure-v examples/hello_world.v` (move ctovstring_impl to builtin.c.v)\n- Fix rune casting from u32 in rune.v (#25307)\n\n## V 0.4.11\n\n*19 Jun 2025*\n\n#### Improvements in the language\n\n- Support a new CPU architecture s390x (#24107)\n- Add initial support for ppc64le (#24287)\n- Add initial support for loongarch64 (#24343)\n- Support `js\"string literal\"` for JavaScript strings (#24653)\n- VLS mode in the parser for the new language server in pure V\n\n#### Breaking changes\n\n- Remove deprecations made before 2024-11-06\n- Add a deprecation note for `any` arg, prevent `any` from being used as map key,value or array\n  type (#24277)\n\n#### Checker improvements/fixes\n\n- Fix chan element type validation with inexistent type (fix #23978) (#24008)\n- Do not allow auto (de)reference in PrefixExpr *\n- Fix check for pushing on an unwrapped option array (fix #24073) (#24093)\n- Fix wrong type hint on predicate arg type mismatch (fix #24122) (#24123)\n- Fix array generic return checking (fix #24104) (#24214)\n- Fix stack var outside usage when var is a mutable param (#24249)\n- Fix codegen for multi return with array fixed (fix #24280) (#24282)\n- Check anon struct field valid case (partial fix of #24284) (#24286)\n- Add check for recursive array init on struct (fix #21195) (#24278)\n- Fix inherited var turning in auto heap (fix #24306) (#24312)\n- Remove redundant callexpr `c.expr(mut node.left)` rechecks for `ast.CallExpr` (fix #24353) (\n  #24380)\n- Do not allow &u8(0), force nil like we do with &Type(0)\n- Relax the new warning, allow for `pub const pname = &char(C.SDL_POINTER)` to fix the clean\n  compilation of code using vlang/sdl3\n- Fix for with mut generic value (fix #24360) (#24426)\n- Add check for decomposing to interface (fix #24441) (#24453)\n- Fix generic option array arg passing to `[]T` (fix #24423) (#24457)\n- Fix resolver for returning struct generic (fix #24493) (#24506)\n- Reallow passing closures as voidptr parameters with no warning, to enable convenient interfacing\n  with C libs\n- Disallow invalid expr for `filter`, `count`, `any`, `all` (fix #24508) (#24540)\n- Replace warning by notice for UTF8 strings validation (fix #24538) (#24543)\n- Revise logic for reporting import conflicts with module names (#24539)\n- Fix struct update expr checking, when an alias is used (fix #24581) (#24582)\n- Fix fn var resolver (fix #24525) (#24542)\n- Fix checking for int to array of interface (fix #24624) (#24625)\n- Cycle through all `ast.ParExpr` first in `prefix_expr` (fix #24584) (#24588)\n- Move `arr <<` logic to `check_append()`\n- Fix mutable const bug (fix #14916)\n- Allow for calling main() inside _test.v files\n- Fix missing type bounding to match expr on `or{}` expr (fix #24656) (#24658)\n- Add error for `if mut x != none {`, when `x` is an immutable option (fix #24692) (#24694)\n- Fix compound selector smartcasting/option unwrapping (fix #24662) (#24712)\n- Fix mutable option (fix #18818) (fix #24622) (fix #24101) (#19100)\n\n#### Parser improvements\n\n- Fix parse_cflag() support other flags between allowed_flags (fix #24121) (#24146)\n- Minimise allocations done for the common case in find_struct_field\n- Fix orm generic struct table type parsing (fix #24049) (#24149)\n- Fix mutiple imports at one line (#24241)\n- Fix range expr precedence on compound logical and operator (fix #24252) (#24275)\n- Fix invalid field name checking (fix #24279) (#24283)\n- Fix wrong string parsing (fix #24297) (#24298)\n- Fix panic for `struct Abc { pub mut: }` (fix #24404) (#24403)\n- Allow `mut static counter := 0` inside `unsafe {}` blocks (prepare for removing a `-translated`\n  mode quirk)\n- Fix duplicate mod imports (fix #24552) (#24559)\n- Reduce memory usage of ast.ScopeObject and ast.Ident instances (#24704)\n\n#### Comptime\n\n- comptime: fix comptime parameter resolve for `unsafe { nil }` to be `voidptr` (fix #25558) (\n  #25570)\n- comptime: fix codegen ptr field reading from comptimeselector (fix #25616) (#25620)\n- comptime: dont emit empty blocks (#26171)\n- comptime: support type interpolation in the msg argument of `$compile_warn(msg)` and\n  `$compile_error(msg)` (#24992)\n- comptime: fix $match with fn type (#25271)\n- Support `$if T is $pointer {` and `$if T is $voidptr {`, to make it easier to implement a pure V\n  dump(), without cgen specific code (#24628)\n- i32 is now `$int` too (fix #24346) (#24378)\n- Fix `$dbg` with `@[heap]` structs (fix #23979) (#23989)\n- Check invalid comptime field name assignment (fix #24415) (#24421)\n- Enable s390x + docs (#24114)\n\n#### Compiler internals\n\n- Remove closure usage from the compiler frontend (simplify bootstrapping/porting on more exotic\n  platforms)\n- markused: support orm or expr (fix #24040) (#24059)\n- markused: fix for gated index range on string (fix #24187) (#24200)\n- v.util.version: fix output for V full version when VCURRENTHASH not defined (#24264)\n- markused: fix generic method call mark (fix #24395) (#24399)\n- v.pref: add get_build_facts_and_defines/0 and set_build_flags_and_defines/2\n- v.util.version: fix output for V full version (followup on issue #24263 and PR #24264) (#24478)\n- v.util: use internal diff (#24495)\n- v.pref: prevent overriding backend (fix #21758) (#24526)\n- markused: fix for generic ptr receiver on method call (fix #24555) (#24558)\n- markused: fix `x := t.wait()`, when `t := go fn () string {` (fix #24577) (#24580)\n- markused: fix printing smartcasted interface values (fix #24579) (#24583)\n- pref: avoid changing the backend with `.js.v` when `-backend` has already been used (fix #7840) (\n  #24654)\n- Remove dump() calls inside the compiler itself (make bootstrapping of dump() implemented before\n  cgen easier)\n\n#### Standard library\n\n- builtin: string.index_after() ?int\n- cli: account for initial indent on subcommands (#23985)\n- Remove `strings.Builder.clear()`, fix `array.clear()` not working in the JS backend (#23992)\n- gg: make draw_rect_empty/5 draw more exact borders, independent of the device, and fitting the\n  draw_rect_filled/5 shapes (#24024)\n- sync: fix a helgrind false positive, for a data race, on PoolProcessor (#24023)\n- sync.pool: restore the parallel operation (surrounding the cb call in process_in_thread in a lock\n  in 1b52538, effectively disabled parallelism)\n- x.crypto.chacha20: change internal cipher to support a 64 bit counter (related to #23904) (#24039)\n- os: fix swap_bytes_u64 (#24033)\n- x.crypto.chacha20: fix `xor_key_stream` failing after a while (fix #24043) (#24046)\n- crypto.sha3: be big-endian friendly (#24045)\n- x.crypto.chacha20: makes the underlying cipher routine aware of the 64-bit counter (#24050)\n- x.crypto.chacha20: enable support for 64-bit counter (fix #23904) (#24053)\n- x.crypto.slhdsa: add a SLH-DSA implementation, a stateless hash-based DSA, a post quantum\n  cryptographic module (#24086)\n- encoding.binary: add encode_binary()/decode_binary() generic functions (#24106)\n- crypto.rc4: change the return type of `new_cipher` to be `!&Cipher` (#24113)\n- crypto: add a `crypto.ripemd160` module (#24119)\n- encoding.iconv: fix iconv on termux (fix #23597) (#24147)\n- sync: remove the call to C.pthread_rwlockattr_setpshared (not needed, since it is the default on\n  POSIX) (#24166)\n- pkgconfig, termios: Support NetBSD (#24176)\n- encoding.binary: fix serialize map struct (fix #24190) (#24192)\n- builtin,v.gen.wasm: support `-b wasm -d no_imports` (#24188)\n- datatypes: add a Set.array/0 method to help get all the elements from a set as an array (#24206)\n- json: fix option time (fix #24242) (fix #24175) (#24243)\n- log: add local time / utc time selection support (#24268)\n- json: link with libm (fix #24272) (#24273)\n- rand: add uuid_v7(), session function, simplify uuid_v4() (#24313)\n- toml: fix handling of multiline string with CRLF (fix #24321) (#24322)\n- toml: fix crlf escape check (fix #24328) (#24329)\n- x.json2: add u16(),u32() (fix #24337) (#24342)\n- rand: fix uuid_v7 seperator (#24348)\n- rand: check the separators for the generated UUIDs in random_identifiers_test.v\n- builtin: add string.is_identifier() (#24350)\n- x.crypto.chacha20: add a check counter overflow to set_counter for standard mode (#24365)\n- comptime: fix `$if var.return_type == 1 {` (fix #24391) (#24393)\n- comptime: enable ppc64le, add docs (#24433)\n- toml: add compile error when passing `encode/1` types of T != struct (fix #24435) (#24443)\n- sync.stdatomic: workaround for libatomic.a indirect symbols tcc bug (fix #23924) (#24472)\n- math.big: fix the + operator for big.Integer for negative numbers, add test (#24487)\n- math.big: respect the sign of the dividend in % operator, add test (#24489)\n- os: add note for the availability of the debugger_present implementation (#24492)\n- term: add writeln_color() (#24463)\n- math.big: add missing assert for test_multiply_karatsuba_02 (#24534)\n- builtin: fix mix prod and debug ucrt lib (#24498)\n- math.big: fix Karatsuba's add_in_place() function, add carry handler on exit (#24541)\n- math: add `exp_decay` to `interpolation.v` (#24545)\n- math.big: optimize divide_array_by_digit() (#24566)\n- sync.stdatomic: add atomic types (#24561)\n- sync.stdatomic: turn panic() in new_atomic[T]() into a $compile_error() (#24573)\n- sync: add condition support (#24574)\n- builtin: flush stdout on panic (#24606)\n- Document the behaviour of % for negative numbers; in V: -10 % 7 == -3 (#24604)\n- math.big: remove unnecessary casting from Integer.is_power_of_2/0 (#24614)\n- math.big: make is_power_of_2() be false for negatives (it now matches Julia's ispow2/1) (#24619)\n- vlib: vanilla_http_server (#24202)\n- os: support `dotfiles := os.walk_ext('.', '', hidden: true)` (#24617)\n- builtin: remove playground related code (the current playground uses a container/sandbox) (#24632)\n- comptime: fix `T.indirections` comparison (fix #24630) (#24636)\n- math.big: add test for radix_str() and integer_from_radix() (#24644)\n- runtime: make free_memory() and total_memory() return Result types to allow for reporting errors (\n  #24651)\n- math.big: improve the performance of radix_str() ~9 times (#24666)\n- math.big: speed up ~10x integer_from_radix() (#24674)\n- sync.stdatomic: fix bug with add() and sub() returning the new values, add voidptr support, add\n  swap() and compare_and_swap() (#24685)\n- sync.stdatomic: add atomic_thread_fence(), cpu_relax() (#24690)\n- v: support `@DIR` (as a comptime equivalent to `os.dir(@FILE))` at runtime) (#24742)\n- thirdparty: print the glGetError() code on failure too in sokol_gfx.h, to make diagnostic easier\n- builtin: make array.ensure_cap/1 public\n- os.font: fixes for `-os android`\n- vlib: add a pool module (#24661)\n- zstd: make the api more V like\n- szip: fix panic on empty files (#24335)\n\n#### Web\n\n- net: add `read_ptr/2` (from `read/1`) to `UdpConn` for consistency with `TcpConn` (#24000)\n- net: make `close/0`, `select/2` and `remote/0` methods of `UdpSocket` `pub` (#24004)\n- Fix $dbg on function that uses veb comptimecall (fix #23999) (#24088)\n- veb: allow route methods, that are tagged with `@[unsafe]`\n- veb: support `-d veb_max_read_bytes=16384`, `-d veb_max_write_bytes=16384`,\n  `-d veb_default_port=1234`, `-d veb_max_http_post_size_bytes=8388608`\n- net.http: support `v -http -d http_folder=vlib/_docs` (allow customizing the folder, port, and\n  index file through CLI arguments to v -http)\n- thirdparty: upgrade to mbedtls v3.6.3.1, add a .patch file with the local changes (#24602)\n- veb: fix handling of default CorsOptions.allowed_headers (#24703)\n\n#### ORM\n\n- orm: fix default value quote (fix #24052) (#24057)\n- orm: fix type alias not supported in table columns (fix #15478) (#24062)\n- orm: fix gen sql complex where (fix #24136) (#24138)\n- orm: skip orm_complex_where_test.v for `sanitize-memory-clang` too\n- orm: add function call based builder API for dynamic queries (fix #24178) (#24196)\n- orm: set default value for require field if database value is null (fix #24221) (#24222)\n- orm: fix option field with default null value (fix #24222) (#24228)\n- orm: add or_where() method to the builder (fix #24244) (#24250)\n- orm: add IN and NOT IN (#24634)\n- orm: add `in` and `not in` to orm_func (fix #24639) (#24642)\n- breaking,orm: add table attrs; add table/field comment support for mysql and pg (#24744)\n\n#### Database drivers\n\n- db.mysql: use mysql datatype for alloc string_binds_map, not orm's (#24126)\n- db.mysql: fix handling of nullable timestamp (fix #24120) (#24125)\n- db.mysql: add null result support (fix #24130) (#24131)\n- db.mysql: use hardcoded const declare (fix #22086) (#24162)\n- db: connection pool (#24161)\n- db: mysql,pg,sqlite add transaction support (fix #24290) (#24352)\n- db.pg: fix incompatible fn signature (#24549)\n- db: add redis (#24730)\n\n#### Native backend\n\n- native: use builtin exit function (#24578)\n- native: improve string support (#24600)\n- native: implement `for in string` for amd64 (#24613)\n- native: support nested structs, improve support for right expr of IndexExpr (#24627)\n- native: leave only the unique paths in g.linker_include_paths, before doing lookups\n- native: support C constants (#24660)\n- native: add a temporary special case for `C.EOF` (#24724)\n\n#### C backend\n\n- Fix parallel cached_type_to_str access (fix #23980) (#23998)\n- Fix codegen to make mutable sumtype working (fix #23982, part 1, needed for bootstrapping) (\n  #23988)\n- Fix arm64 asm operand position; fix arm64 asm imm; support arm64 dot instruction (#24017)\n- Fix mutable ptr sumtype  (#24021)\n- Fix asm comments of arm32 (#24025)\n- Allow asserts inside fns, called in const/global initialization, in test files (fix #24029) (\n  #24031)\n- Fix codegen for option return unwrapping on last statement (fix #24026) (#24030)\n- Fix match option with case non option (fix #24047) (fix #24048) (#24051)\n- Support measuring programs, that use multiple threads in the new profiler column (turn\n  `prof_measured_time` into a thread local, for the supported C compilers) (#24061)\n- Fix `@[keep_args_alive]` with ptr (fix #23973) (#24058)\n- Remove unused macro V64_PRINTFORMAT\n- Fix option array push on unwrapped array (fix #24073) (#24079)\n- Fix nested array support for the orm (fix #19327) (#24080)\n- Fix `x in [...]!` operator with fixed arrays (fix #24082) (#24083)\n- Fix codegen for comptime multiline attr (fix #23964) (#24087)\n- Fix codegen for selector with embed field option (fix #24084) (#24085)\n- Fix generic result return (fix #24097) (#24100)\n- Fix showing the expression, as literal value, in case of `assert s[x..y] == \"literal\"` (fix\n  #24103) (#24105)\n- Fix codegen for option unwrapped var passed to generic option type (fix #23972) (#24096)\n- Fix selector option unwrapping on infix (fix #24108) (#24115)\n- Sort the paths, used in coutput_test.v\n- Skip emitting mman.h and pthreads related code, for freestanding builds (#24118)\n- Add s390x assembly support + test (#24129)\n- Parser,checker,cgen: fix wrong auto heap deref of auto `index` loop var (fix #24117) (#24124)\n- Fix non-voidptr to voidptr on `-cstrict` + notice about such usage (fix #24139) (#24143)\n- Fix multi return with option type (#24144)\n- Remove obfuscation (`strip` should be used instead); temporary fix for usecache + toml\n- Fix zero left padding (fix #24199) (#24201)\n- Fix variadic sumtype args passing (fix #24150) (#24207)\n- Fix codegen for const to c string (fix #24235) (#24248)\n- Fix codegen for fixed array init with init using structinit (#24269)\n- Fix missing braces for const init with castexpr from option unwrapping expr (#24276)\n- Fix codegen for index expr on for loop with branchstmt (fix #22760) (#24289)\n- Fix codegen for assigning fixed array on defer var (fix #24300) (#24305)\n- Fix codegen for multi return with aliased fixed array (fix #24280) (#24295)\n- Fix codegen for nested selector unwrapping on lhs (fix #24292) (#24293)\n- Add ppc64le assembly support + test (#24299)\n- Fix s390x closure thunk (use floating point register) (#24258)\n- Fix riscv64 closure thunk (use floating point register) (#24315)\n- Fix codegen for writing on unwrapped selector (fix #24316) (#24323)\n- Fix codegen for thread.call() on var auto heap (fix #24326) (#24327)\n- Fix codegen for handling multiple return result type on call (fix #24341) (#24344)\n- Fix codegen for nested selector option ptr (fix #24339) (#24345)\n- Fix arm64 closure + remove stub in test (#24332)\n- Workaround tcc aarch64 bug (fix #24331) (#24354)\n- Fix riscv32 closure (#24355)\n- Fix codegen for anon option fn struct field init (fix #24392) (#24400)\n- Fix `if mut var != none {` for optional interface values (fix #24351) (#24410)\n- Fix interface `unsafe {nil}` comparison and initialization (fix #24374) (#24411)\n- Ast,cgen,parser,pref: support loongarch64 inline assembly, add test (#24440)\n- Fix array init with interface element type (fix #24442) (#24454)\n- Fix const declaration dependant mapping when using update_expr (fix #24437) (#24455)\n- Fix comptimecall with map receiver (fix #24448) (#24449)\n- Fix assign from `for mut var in arr {` to pointer (fix #24432) (#24456)\n- Workaround tcc aarch64 fn call bug (fix #24473) (#24477)\n- Workaround tcc aarch64 spawn call bug (fix #24482) (#24483)\n- Fix map of fixed array value in if guard (fix #24488) (#24496)\n- Fix codegen for assigning `nil` or `0` to option ptr field (fix #24447) (fix #24500) (#24502)\n- Fix codegen for array of option element auto eq `a == [?int(none)]` (#24504)\n- Fix codegen inconsistency handling `nil` param to arg expecting ptr (fix #24491) (#24503)\n- Fix pattern generated by `const_init_or_block.vv` in `vlib/v/gen/c/coutput_test.v`, when\n  VFLAGS=-no-parallel is used\n- Fix tmp var redeclaration on const inited later (fix #24521) (fix #24517) (#24524)\n- Fix generic name handling for struct generic (fix #24530) (#24565)\n- Fix initialize error object in or_block (fix #24529) (#24576)\n- Improve the readability of `switch() {` statements, generated by `match() {` ones (#24618)\n- Reduce v.c size by ~4% by removing comments and using shorter literals\n- Fix enumval str() call on stringinterliteral (fix #24702) (#24705)\n\n#### JavaScript backend\n\n- Fix array type checking in sum type match expressions (fix #24237 ) (#24259)\n- js: fix callbacks in structure parameters (fix #24260) (#24324)\n- Fix array initialization with \"index\" and \"it\" (fix #24397) (#24429)\n- Cannot assign unsafe nil values (fix #24407, #24436) (#24458)\n- Fix alias type initalization (fix #24475) (#24480)\n- Fix casting (fix #24512) (#24519)\n- Alias types are not properly resolved (fix #24486) (fix #24507) (#24514)\n- Implement Map.keys() and Map.values() methods (fix #24209) (#24608)\n- Fix string.runes method (fix #20500) (#24609)\n- Fix direct map key access and map.len (fix #24616, fix #24605) (#24620)\n- Fix map to string fails on rune keys (fix #24637) (#24638)\n- Fix maps being always constructed using string keys (fix #24607) (fix #24671) (#24673)\n- Fix slightly incorrect JS (esbuild was broken on master) (fix #23711) (#24676)\n\n#### vfmt\n\n- Convert `\"hello\".str` => `c\"hello\"` (fix #24635) (#24652)\n\n#### Tools\n\n- Let test_os_process.v use `unbuffer_stdout()` to make the output more reliable\n- os,tools: make easier analyzing process_test.v failures on the CI\n- ci: fix build conditions that had `sanitize-memory-clang?` instead of `sanitize-memory-clang`\n- ci: skip running the `s390 CI` job for simple doc/yml changes (#24160)\n- ci: fix shell script issues reported by actionlint (#24168)\n- Remove the `src` subdir from projects, created by `v new` (#24236)\n- Add support for `// vtest build: !os_id_ubuntu?` tags in the _test.v files, detected by `v test`\n- ci: fix `v -o v2 -usecache cmd/v` after ad5b829\n- Fix vrepl for `import mod { f }` (#24340)\n- ci: debug hub_docker_ci.yml issue (try 1, disable cache, run linters)\n- ci: debug hub_docker_ci.yml issue (try 2, add concurrency group, add a persistent single builder\n  `gh-builder`)\n- ci: debug hub_docker_ci.yml issue (try 3, restore the cache-from:/cache-to: lines)\n- ci: fix hub_docker_ci.yml issue - comment out the cache-from:/cache-to: lines again\n- Support vreduce timeout, vreduce custom run command (#24359)\n- Rewrite `v timeout`, support killing the child process on timeout by default (#24367)\n- Use breadth first search in vreduce (#24369)\n- Vreduce fix var names (#24373)\n- Fix `v timeout 2 sleep 5`\n- Fix `./v -d network test cmd/tools/vpm`\n- ci: reduce false positives for cover_test.v and vdoc_test.v\n- Save the modified content more frequently in `v reduce`, fix timeout leaks (#24405)\n- Reduce padding for `v doc` produced html nodes too\n- ci: reduce the noise in check annotations for github PR reviews, due to the new warning in\n  option_test.c.v\n- Improve show_ancient_deprecations.v, by ignoring false positives for deprecation tags in //\n  comments\n- Check for Git repository in `v doctor` (packaged V versions often lack a .git/ folder) (fix\n  #24419) (#24420)\n- vlib,tools: add an `arrays.diff` module, implement a simple platform independent tool\n  `v diff file1.txt file2.txt` using it (#24428)\n- ci: bump creyD/prettier_action from 4.3 to 4.5 (#24439)\n- ci: use `v retry` to reduce the false positives for retrieving the dependencies for vinix too\n- ci: show `hg version` too, to ease the diagnosing of install_version_test.v failures\n- Let cmd/tools/vpm/install_test.v use a .hg/hgrc file too\n- repl: fix typeof(a) with warning (fix #24499) (#24515)\n- Make `v doctor` show CFLAGS and LDFLAGS too (if set)\n- Make `v search ui` work again through the vpm site (fix #23966) (#24535)\n- ci: fix unused var warning in cmd/tools/vpm/common.v\n- ci: prevent future changes to cmd/tools/vpm/common.v, that introduce warnings/notices to pass in\n  PRs\n- x.benchmark: align the output of BenchmarkResult.print/0\n- Ease diagnosing CI failures of vtimeout_test.v\n- ci: make sure that only one copy of native_test.v is executed at once, when run through\n  `v test vlib` (fix #24505)\n- Ignore .db and .sqlite files by default in `v watch` (such DB files are very likely to change\n  during prototyping)\n- .gitignore: ignore .db and .sesskey files as well\n- ci: bump creyD/prettier_action from 4.5 to 4.6 (#24687)\n- Make  `v doc -f md module` output useful by default (#24737)\n- ci: fix native_backend_ci.yml concurrency group setting (prevent jobs for different commits on\n  master to cancel each other)\n- Fix overflow detected in the sanitized runs on the CI (#24064)\n- ci: reduce code duplication in linux_ci.vsh\n\n#### Operating System support\n\n- os: implement Process.is_pending() on windows (fix #23990) (#23993)\n- os: support .set_environment() on windows too (fix #10628) (#23996)\n- thirdparty: update thirdparty-linux-amd64_tcc.sh, to also record its own full invocation command,\n  and commit the changes automatically\n- thirdparty: add thirdparty/build_scripts/thirdparty-freebsd-amd64_tcc.sh\n- ci: reduce false positives for slow runs of the gcc-windows job\n- gg: fix screen_size() on macos with multiple displays\n- ci: add riscv64_linux_ci.yml (based on QEMU) as well (#24181)\n- ci: use `apt update` before `apt install` in cross_ci.yml, to make the linux job more robust\n- thirdparty: add thirdparty/build_scripts/thirdparty-macos-arm64_tcc.sh for compiling tcc on\n  macos (first draft)\n- Simplify the implementation of get_linux_os_name in `v doctor`\n- os.filelock: compile without warnings with gcc on windows\n- ci: use windows-2025 for the gcc-windows job (since it has gcc 14.2.0) (#24304)\n- ci: skip option_ptr_unwrap_test.v on windows with msvc (#24320)\n- os: fix windows rmdir GetLastError() (fix #24356) (#24357)\n- Enable windows tcc_backtrace() support (#24377)\n- ci: reduce false positives for init_global_test.v on windows (retry it 2 times)\n- ci: reduce false positives for orm_func_test.v on windows (retry it 2 times)\n- os: force using `C.CREATE_NO_WINDOW` on windows in os.raw_execute/1 (fix #24390) (#24418)\n- Fix v doctor output on FreeBSD ; do not run ldd to get the glibc version (#24427)\n- runtime: improve free_memory implementation for OpenBSD, by getting the stats from its UVM\n  system (#24431)\n- runtime: fix cast error in free_memory implementation for OpenBSD (#24445)\n- Use a `.hg/hgrc` file for install_version_test.v (workaround windows failure)\n- os: add debugger_present implementation for OpenBSD (fix #23603) (#24490)\n- veb: reduce veb_max_write_bytes from 16KB to 2KB (fix sending large dynamic responses from veb on\n  macos/freebsd) (fix #24523) (#24522)\n- os: fix os.File's tell/0 method for windows (fix #24217) (#24218)\n- net.openssl: replace SSL_get1_peer_certificate by SSL_get_peer_certificate for OpenBSD (#24556)\n- net.mbedtls: disable AES-NI on OpenBSD with tcc (fix #22239) (#24560)\n- net.mbedtls: enable MBEDTLS_THREADING_C and MBEDTLS_THREADING_PTHREAD on OpenBSD (#24572)\n- thirdparty: add thirdparty/build_scripts/thirdparty-openbsd-amd64_tcc.sh for compiling tcc on\n  OpenBSD (#24592)\n- v.builder: enable -fwrap for C compilation on OpenBSD too (#24585)\n- v.pkgconfig: add the default `/opt/local/lib/pkgconfig` for MacPorts on macos (#24626)\n- sync: increase retries for vlib/sync/select_close_test.v to 3, to reduce CI false positives in the\n  gcc-windows job\n- ci: remove script to build tcc on FreeBSD (obsoleted by\n  thirdparty/build_scripts/thirdparty-freebsd-amd64_tcc.sh) (#24681)\n- encoding.iconv: add path for iconv library on FreeBSD (#24682)\n- native: skip linux.vv too, for the sanitized jobs (similar to libc.vv)\n- ci: migrate from windows-2019 runner to windows-2025 runner in most jobs (github deprecated the\n  2019 runner) (#24672)\n- runtime: fix -cstrict compilation (use usize() cast in free_memory) on OpenBSD (#24696)\n- Remove specific case for FreeBSD in `cmd/tools/vtest_test.v` (#24707)\n- docs: add section in README for compilation on FreeBSD (#24706)\n- thirdparty: add script to build libgc on FreeBSD/amd64 (#24717)\n- builtin: use local static libgc for FreeBSD with tcc (fix #24710) (fix #24683) (#24720)\n- ci: update and improve FreeBSD CI (#24726)\n- ci: add CI for OpenBSD (#24732)\n- gg: fix .char event handling for backspace, delete, tab and enter for linux/x11 (send appropriate\n  .char codes to the apps, similar to macos)\n- Add aarch64 atomics support in thirdparty/stdatomic/nix/atomic.h (fix #24294) (#24296)\n- v.trace_calls: now musl has gettid(), there is no need for the shim on newer Alpine etc (#24245)\n\n#### Examples\n\n- Fix `v -os wasm32_emscripten -o ms.html examples/gg/minesweeper.v` (use os.asset to load the font,\n  avoid the implicit closures for the frame/event callbacks)'\n- Update rotating_textured_quad.v with instructions on how to compile/run it with emscripten and a\n  browser\n- Add a small examples/gg/bouncing_balls.v simulation of falling balls\n- Fetch 30 stories instead of 10 in examples/news_fetcher.v\n- Add sync_pool.v for easier testing/diagnosing issues with the `sync.pool` implementation on\n  different platforms\n- Add a `-profile` report column, to show only the func time, *excluding* the accumulated children\n  calls time (usable through `./v -profile - run a.v |sort -nk3` for example) (#24056)\n- doc: improve Shared and Channels's topics, add more examples (#24155)\n- orm: fix option type, convert from int to i8, add examples, etc (fix #24211) (#24213)\n- Fix optional callback parameter and improve examples (fix #24325) (#24336)\n- Reduce padding for code examples, to fit more examples on the same screen without scrolling\n- Cleanup unsafe{} blocks that are not needed anymore in examples/sokol/08_sdf/sdf.v\n- Show the number of pushes in sokoban too\n- os.asset: add read_text/2 too, use it to simplify the sokoban example\n- Support directly loading sokoban level files by path\n- Add more Sokoban levels\n- Support boxoban style collections of levels files (\n  from https://github.com/google-deepmind/boxoban-levels/)\n- Add a simple sudoku solver\n- Add primes.v, that shows how to get command line arguments, and use loops and functions\n- Add a small memory game (#24643)\n- Cleanup memory.v (reduce it to 135 lines)\n- builtin,os: enable no warnings for gg programs like\n  `v -gc boehm_leak -cg -keepc run examples/gg/minimal.v` (part 1 - before the `gg` loop) (#24749)\n\n## V 0.4.10\n\n*20 Mar 2025*\n\n#### Improvements in the language\n\n- Implement assignable anonymous struct (fix #23855) (#23857)\n- Remove ancient deprecations (#23479)\n\n#### Breaking changes\n\n- Make old `[attr]` syntax an error (`@[attr]` has to be used instead)\n- builtin: `string.index_after()` now returns an Option (like `string.index()`), use\n  `string.index_after_()` for the old behavior\n- Vweb is now deprecated in favor of faster and more stable and easy to use veb\n\n#### Checker improvements/fixes\n\n- Allow `none` to be passed to `?T` param (fix #23381) (#23385)\n- Fix `for` iterator method `.next()`, not marked as used (fix #23312) (#23321)\n- Fix generic var inferring to be passed to `[]T` (fix #23315) (#23322)\n- Clean up and optimise infix - reduce `as` casting (#23327)\n- Fix structinit validation on nested generic Map[K]V (fix #23329) (#23332)\n- Fix comptime indexexpr resolving (#23333)\n- Fix comptime evaluation on infix expr (fix #23341) (#23344)\n- Fix alias to fixed array w/ size defined by constant (fix #23356) (#23357)\n- Fix missing option variable checking when casting using `as` operator (fix #23349) (#23358)\n- Fix assign expected type on rechecking enum assigns (fix #23366) (#23367)\n- Allow calling `foo(?i64(123))` for `fn foo(x ?I64) {` and `type I64 = i64` (#23373)\n- Cache `node.args[0]` on `fixed_array_builtin_method_call` and `array_builtin_method_call` (#23411)\n- Fix missing check for invalid prefixexpr expression `&(&var)` (fix #23365) (#23418)\n- Disallow `&((&a))` and similar expressions, with innermost `ast.PrefixExpr` (enhance #23418) (\n  #23419)\n- Fix call with mut arg with different pointer levels (fix #23157) (#23428)\n- Fix missing detection for `return` in lockexpr stmts (fix #23434) (#23435)\n- Do not allow auto reference of voidptr params\n- Check if unwrapped `m[key]` if m is `Option` (fix #23446) (#23459)\n- Builtin,checker: remove `@[markused]` from `fn isnil()`, set\n  `c.table.used_features.auto_str_ptr = true` instead (#23464)\n- Fix checker generic alias type (fix #23474) (#23475)\n- Fix missing check for `a := [none]` (fix #23457) (#23504)\n- Fix missing check for concrete type on match branch expr (fix #23506) (#23508)\n- Fix missing check for invalid argument for builtin (fix #23511) (#23515)\n- Fix selector nested unwrapping (fix #23519) (#23521)\n- Fix message with old attr syntax (#23529)\n- Cache repeated `node.args.len`, `method.generic_names.len`, `node.concrete_types.len` and\n  `node.op.str()` (#23536)\n- Disallow `expr is Type` if expr is Optional (fix #23486) (#23510)\n- Make `option_var.str()` an error, when done without unwrapping it first (fix #23557, fix #23558) (\n  #23563)\n- Fix private symbol visibility checking (fix #23518) (#23543)\n- Disallow constant modification on unsafe {} (#23588)\n- Fix sumtype variant option type mismatch (#23659)\n- Disallow `arr = voidptr(0)` (fix #23675) (#23687)\n- Allow for `module no_main` programs, that can redefine their own main function, or not define any\n  of their own as well\n- Fix match branch checking of nonreturn call on last expr (fix #23698) (#23699)\n- Check and error for invalid utf8 string literals (#23721)\n- Fix call from unknown enum (fix #23728) (#23730)\n- Add checker for passing multi return as arg to func that expects less param (fix #23735) (#23744)\n- Fix spreed operator ref field validation (fix #23759) (#23760)\n- Fix missing check for method that returns veb.Result (fix #23647) (#23762)\n- Allow generic operators to be called in fn (fix #23773) (#23774)\n- Fix missing struct cast validation (fix #23748) (#23788)\n- Fix map when casting to interface (fix #23790) (#23799)\n- Allow for `pub type C.HINSTANCE = voidptr`, being used in\n  ```\n  @[export: \"wWinMain\"]\n  fn mymain(x C.HINSTANCE, xprev C.HINSTANCE, lpcmdline &C.WCHAR, cmdshow int) int {\n  ```\n  in `module no_main` programs (#23812)\n- Add option type inference on if expr (implement most of #23827, except the error for\n  `v := if c { none } else { none }`) (#23829)\n- Add missing check for IfExpr and MatchExpr with no valid type (#23832)\n- Fix MatchExpr type inferring, when `none` is used (fix #23831) (#23833)\n- Add missing check for generic fntype type names (fix #23453) (#23850)\n- Add checking for comptime assign without comptime if checking (fix #23796) (#23848)\n- Fix option ptr field assign checking (fix #23879) (#23880)\n- Add missing `any` type validation on assignment (fix #23905) (#23906)\n- Add fntype casting validations (#23872)\n- Fix signed integer literal overflow error, when most significant bit occupies signed bit (fix\n  #23782) (#23919)\n- Add missing check for casting generic type to literal values (#23915)\n- Check if next() method infers generic type correctly (fix #23927) (#23932)\n- Disallow references to constants (fix #23935) (#23942)\n- Fix typeof evaluation for generic reference (fix #23951) (fix #23952) (#23958)\n\n#### Parser improvements\n\n- Reduce allocations in empty_comptime_const_expr (#23324)\n- Add error for array init of Results `[]!type{}` (fix #23360) (#23375)\n- Allow map cast syntax `map[k]v(expr)` (#23401)\n- Inline some commonly used fns (#23535)\n- Fix anon fn return type option/result followed by comment parsing in vfmt mode (fix #23607) (\n  #23608)\n- Keep track of the number of all scanned tokens too, and show it with `-stats`\n- Fix the error message position, for a `struct Abc`, that lacks a body (#23627)\n- Prevent unused warning on `import mod { Sym }`, when `Sym` is later used, for more cases (fix\n  #23412) (#23626)\n- Add support for `-d trace_parse_file_path_and_mod`, to help diagnosing module lookup problems\n- Allow for `@[has_globals]` to be used for all V programs, turn the `@[wasm_import_namespace]`\n  error into a notice\n- Remove table dep for script main check\n- Fix enum value parsing inside array initialization (fix #23937) (#23941)\n- Fix the registration of fixed arrays, when size_expr is a const (fix #23946) (#23949)\n- Disallow invalid expr in comptime `$for` (fix #23953) (#23959)\n\n#### Compiler internals\n\n- markused: fix `-skip-unused` on a short program, that prints array (fix #23436) (#23437)\n- markused: fix `eprintln(err)` on imported module on short program (related: #23498) (#23499)\n- markused: fix markused auto str detection (fix #23501) (#23503)\n- markused: fix option ptr printing (fix #23559) (#23562)\n- checker,markused: add identification for sumtype.type_name() call (fix #23732) (#23739)\n- markused: improve stability (avoid runtime crash) when processing generic functions (partial fix\n  for #23927)\n- markused: fix markused behavior on array / map index getter / setter / slice (#23931)\n- markused: fix markused behavior on struct field's default expression (fix #23909) (#23933)\n- builder: do not search for msvc when it is not needed (#23386)\n- pref: stop parsing CLI options, on encountering `--` (#23470)\n- util: show `unknown command` suggestions, for more misspelled variants, like `v sefl`; make\n  util.new_suggestion calls parametrizable\n- pref: add Preferences.vroot_file/1 (done here, without using it, to ease the bootstrapping of the\n  cheaders extraction, that will follow next)\n- pref: fix panic in parse_args_and_show_errors, called with no args (fix #23713) (#23794)\n- pref: allow for `-os wasm32_emscripten` and filtering `_d_wasm32_emscripten.c.v` and\n  `_notd_wasm32_emscripten.c.v` files. (#23797)\n- v.builder: show the last line of the C compiler output, in case of errors, in addition to the\n  truncated first lines (the last line is useful, since it usually has an error counter)\n- os,v.transformer: fix warnings for\n  `./v -os cross -o vc/v.c cmd/v && clang-18 -o v_from_vc vc/v.c -lpthread`\n- util: fix stack overflow during parsing of `#flag -DName=$d(...)` (#23895)\n- builder: extract Builder.show_parsed_files/0 to make it easier to debug import/parsing issues\n- builder: remove forgotten b.show_parsed_files/0 call\n- util.version: centralise the use of `@VCURRENTHASH`, to minimise the vlang/vc diffs for each\n  commit\n- builder: support `-d trace_parsed_files`\n- util: shorten the V paths used in the C `#line` directives with tcc (the ../../../.. etc is no\n  longer needed with newer tcc) (#23974)\n\n#### Standard library\n\n- json: fix default struct field initialization with long array (#23355)\n- markused,builtin,strconv,vlib: reduce generated C sizes for compilers != tcc, for short programs,\n  by simplifying the generation of backtraces, and reducing string interpolations in panics (#23380)\n- thirdparty/sokol: allow `-cflags -D_SGL_DEFAULT_MAX_VERTICES=4194304` to customize how many\n  vertices you can send through gg/sokol in a frame\n- crypto.ecdsa: expand ecdsa module, to support other curves like secp384r1, secp521r1, secp256k1 (\n  #23407)\n- crypto.ecdsa: fix memleaks, reported by the CI sanitizer jobs (#23450)\n- ci: force the checking of changed vlib/crypto/ecdsa files with the sanitizer jobs\n- builtin: add a `@[markused]` tag to `isnil()`, because cgen generates calls to it in some cases (\n  #23462)\n- builtin: reduce a bit the generated #if defined checks for small programs (#23484)\n- crypto.ecdsa: improve safety checking, unify signing (and verifying) api to accept options (\n  #23463)\n- regex: fix misspelled word \"firts\" in replace_n description (#23514)\n- os: add split_path/1: `os.split_path('/usr/lib/test.so') -> ('/usr/lib','test','.so')`; fix\n  platform dependent behaviour of os.dir/1, os.base/1, os.file_name/1 (#23532)\n- breaking,log: set stderr as default log output, add .set_output_stream() to allow for opting in\n  the old default of stdout (#23444)\n- builtin: add `-prealloc -d prealloc_memset -d prealloc_memset_value=65 -d prealloc_dump`, to\n  better analyze the memory patterns of running V programs\n- builtin: change the default builder size used for string interpolations, from 256 bytes to 64\n  bytes\n- gg: mark create_image_with_size as deprecated (image resizing is done by `stbi.resize_uint8/3`,\n  with a different fn signature) (#23580)\n- crypto.ecdsa: split out the C wrapper to a new .c.v file (#23595)\n- builtin: add &u8.free() (fix #23592) (#23598)\n- crypto.ecdsa: fix bug in .with_no_hash handling (#23612)\n- crypto.ecdsa: fix handling of sign() with custom_hash (#23619)\n- runtime: add note for the availability of the free_memory/0 implementation (#23620)\n- builtin: make public the `FnGC_WarnCB` alias (#23633)\n- os: add disk_usage/1 (#23634)\n- builtin: add string.split_by_space() (#23651)\n- crypto.ecdsa: migrate `ecdsa.PrivateKey.new()` to use a high level API (#23640)\n- gg: fix incorrect Event.mouse_x and Event.mouse_y on gg.Context.event_fn and gg.Context.on_event\n  on HiDPI displays (#23668)\n- crypto.ecdsa: migrate generate_key and simplify it (part 3) (#23662)\n- encoding.csv: add support for multithreading to `encoding.csv.RandomAccessReader` (#23677)\n- v.builder: add` os.quoted_path()` to os.system calls using v.pref.out_name, for the compress\n  flag (fix #23685) (#23686)\n- time: reduce chances of failures on the CI, by time_test.c.v; make the failure diagnostic easier\n- time: improve the robustness of time_test.c.v (check if the diff is within ±1 second of the\n  current timezone difference)\n- crypto.ecdsa: migrate core routines for signing (and verifying), it now requires using OpenSSL 3 (\n  #23705)\n- all: use arguments() instead of os.args in some files\n- math.big: fix 1/115792089237316195423570985008687907853269984665640564039457584007908834671663\n  leading to panic (fix #23771)\n- v.cflag: support `#flag $when_first_existing(libABC.a, /some/path/libABC.a, ...)`, without\n  panicing (unlike `#flag $first_existing(...)`) (#23780)\n- term: add more comments in vlib/term/README.md\n- log: fix panic on mutex destroy, when exiting a program, while a thread is still logging\n- log: fix valgrind_test.v failure\n- math.vec: add `rotate_around_*` (cw/ccw) functions to `vec.Vec2[T]` (#23807)\n- math.big: bump newton_division_limit to 1_000_000 (workaround issue #23806)\n- math.big: add vlib/math/big/big_division_test.v (follow-up to 270941a)\n- strconv: fix strconv.atof64() inconsistency with the other .ato functions; make it return an error\n  by default, when it detects an extra non number character after a number (#23815)\n- os: add File.write_u8/1 and File.read_u8/0 helper methods\n- ci,os: fix bootstrapping with `-os cross -o vc/v.c` (avoid the generic calls in the new write_u8\n  and read_u8)\n- log: remove the notice about the stdout -> stderr migration (#23837)\n- veb: fix \"error parsing request: io.Eof\" when expecting a request body, but the data is not ready\n  yet (fix #22464) (#23842)\n- json: fix json.decode autofree codegen (fix #23834) (#23839)\n- time: add .week_of_year() method for time.Time instances (#23838)\n- time: add documentation for remaining time-related functions and ISO 8601 parsing (#23867)\n- crypto: add missing doc comments for public methods (#23864)\n- builtin,os: fix warnings for `./v -os cross -o vc/v.c cmd/v && cc -o v_from_vc vc/v.c -lpthread`\n- crypto.ecdsa: migrate new_key_from_seed to use high opaque, simplify the logic (#23876)\n- math: fix `./v -prod -cstrict -cc gcc-11 vlib/math/math_bench_test.v` (use unions to implement\n  f64_bits/1 and f64_from_bits/1 for compilers != tcc)\n- crypto.ecdsa: complete the migration to the newer OpenSSL APIs (follow up to #23876) (#23877)\n- x.json2: add a convenience Any.as_map_of_strings/0 method\n- cli: add missing struct members to str() method and fix some comments (#23893)\n- crypto.ecda: improvement the performance of `PrivateKey.new` by avoiding match+assignments (\n  #23899)\n- crypto.ecdsa: improves internal function of `calc_digest_with_evpkey` (#23901)\n- crypto.aes: fix notices about order of operations (fix #23898) (#23902)\n- Revert \"math.bits: port changes from e66e996, so that `-cstrict -cc gcc-11` passes for `markdown`\n  as well\"\n- crypto.ecdsa: improve the performance of the `.public_key` method of `PrivateKey` (#23920)\n- gg: add is_key_down/1 helper method\n- datatypes: optimize linkedlist (fix #23928) (#23934)\n- x.json2: fix \"\\\\\" scanner bug, disallow (ch < 0x20) unescaped control characters (#23954)\n- crypto.ecdsa: improve internal `sign_digest` routine (#23960)\n\n#### Web\n\n- veb: add `ctx.no_content()` + prevent content-type being set if the mime type is empty (#23425)\n- net.ftp: use unsafe { nil }\n- net.smtp: make public the Attachment fields (to be used as plain structs in initialisation) (\n  #23477)\n- x.vweb: remove the entire module (it's now veb)\n- ci: fix failure of the docker-ubuntu-musl job (keep vlib/vweb/vweb_app_test.v in the skip_files)\n- picoev: enable running veb services on Termux\n- thirdparty: improve `-cstrict -cc clang-18 -prod` compatibility for programs that do\n  `import net.mbedtls`\n- net.http.file: use urllib decode uri, to handle urls to files that have unicode characters in\n  their name (fix #23683) (#23684)\n- veb.csrf: do not print anything by default, add an `verbose: true` option, to restore the old\n  behavior if needed (#23725)\n- net.unix: make unix_socket_test.v trace its actions more thoroughly\n- veb.request_id: new middleware that implements request ID tracking (#23727)\n- veb: update the blog tutorial\n- net.openssl: use proper library search path for local installations of OpenSSL 3, use\n  `SSL_get1_peer_certificate` instead of the deprecated `SSL_get_peer_certificate` .\n- ci: fix vweb_run_at.run.out and vweb_run_at.skip_unused.run.out, ensure stable ordering of\n  stdout/stderr for `v run file.v`, in case of compiling a program with warnings/notices.\n- veb: handle sendfile errors, when the connection is canceled, before the file is completely\n  transferred (#23891)\n\n#### ORM\n\n- orm: fix codegen for option fk (fix #23383) (#23400)\n\n#### Database drivers\n\n- db.sqlite: add tracing for more calls, when using `-d trace_sqlite`, not just for the ORM\n- db.pg: add support for prepared statement, with db.prepare/3 and db.exec_prepared/2 (#23442)\n- db.mysql: add SSL support; turn ConnectionFlag into `@[flag]` (#23975)\n\n#### Native backend\n\n- native: fix convert_int_to_string, add comments in the verbose (-v) mode (#23743)\n- native: fix int prints (#23747)\n- native: for statement : add support for all expressions handled by g.condition (#23752)\n- native: fix inc and improve support for i32 (#23753)\n- native: support negative integer literals (#23755)\n- native: fix missing symbols CaptureStackBackTrace and __debugbreak (#23765)\n- native: fibonacci test\n- native: add support for enums of different types (#23786)\n- native: fix unsigned and signed int comparison (#23808)\n\n#### C backend\n\n- Fix type_default for option type, when the default expr is `none` (fix #23318) (#23320)\n- Remove double string cloning (#23331)\n- Fix type_default for array init >= 8 items (spotted while building the vhamll project) (#23334)\n- Fix codegen for alias struct embed (fix #23347) (#23353)\n- Fix codegen for sumtype casting on selector on as cast with non pointer field (fix #23387) (\n  #23391)\n- Fix generic alias option assigning (fix #23382) (#23393)\n- Fix codegen for selector on shared var with embed (fix #23378) (#23394)\n- Fix codegen for nested selectorexpr on unwrapped option (fix #23406) (#23409)\n- Cache return_stmt()'s node.exprs[0] and node.types[0] (#23408)\n- Fix codegen for indexing generic map (fix #23376) (#23402)\n- Support `-d trace_unused_by_main` and `-d trace_skip_unused_just_unused_fns`, to find out\n  potentially obsolete functions that are not used at all in a project\n- Fix shared array indexing (fix #23410) (#23413)\n- Fix shared array fixed initializing with `-cstrict` (fix build of chip8-v project) (#23414)\n- Fix codegen for array fixed comparison on MatchExpr (fix #23403) (#23415)\n- Fix struct init for anon struct field on C structs (fix #23421) (#23422)\n- Fix shared array slice (fix #23426) (#23427)\n- Fix array of sumtype initialization with var string (fix #23429) (#23432)\n- Fix codegen for ifguard indexing array of option (fix #23438) (#23439)\n- Fix assigning option of array index (fix #23451) (#23455)\n- Fix compilation for a project using a lot of json, threads, embeds + parallel-cc (#23467)\n- Fix cgen error for `instance.t.wait()` on default 0 initialized thread field `t` (fix #23390)\n  #23392\n- Fix array decomposing on variadic call (found while working on solving #23474) (#23476)\n- Fix option var nested unwrapping from sumtype (fix #23478) (#23485)\n- Fix option unwrapping on heap var (#23489)\n- Fix codegen for indexing anon_fn (fix #23493) (#23495)\n- Fix nested option selector unwrapping (fix #23500) (#23497)\n- Fix interface casting in anon fn (fix #23530) (#23533)\n- Fix codegen for spawn with interface on submodule (fix #23471) (#23517)\n- Parser,ast,cgen: support nested unions with `field union {`, to improve interoperability with C (\n  similar to `field struct {`) (#23539)\n- Fix unwrapping option interface field (fix #23540) (#23541)\n- Fix codegen for assign from unsafe fn returning fixed array (fix #23546) (#23548)\n- Fix codegen for a fixed array init with different node types (fix #23545) (#23547)\n- Fix return on last statement of return IfExpr (fix #23550) (#23551)\n- Fix auto str which expects ptr for ptr type (fix #23552) (#23553)\n- Fix codegen for assigning from infixexpr with generic operand (fix #23560) (#23561)\n- Fix codegen for array's .grow_cap and .grow_len methods for generic arrays (fix #23566) (#23568)\n- Fix codegen for const fixed array initialization with another const as item (fix #23565) (#23572)\n- Fix codegen for unwrapping option comptime var (fix #23590) (#23591)\n- Fix hash functions for `map[Enum]Value`, and `enum Enum as u64 {` (fix #23630) (#23632)\n- Fix unwrap option ptr selector (fix #23631) (#23638)\n- Fix codegen for `for` or-block (fix #23625) (#23644)\n- Fix codegen for option value on `map_set` (fix #23650) (#23652)\n- Fix codegen for option sumtype with option variant (fix #23653) (#23656)\n- Remove commented code blocks using `if true {`\n- Reduce interpolations when a method is not found in Table.find_method/2; merge rand.constants back\n  to rand.v (#23660)\n- Fix `$if typeof[T]().idx`, `$if typeof[T]().unaliased_typ` checking (#23665)\n- Fix codegen for sumtype cast from option variants on map_set (fix #23654) (#23669)\n- Fix codegen for a const assigned a fixed array, initialized with unsafe exprs (fix #23674) (\n  #23676)\n- Fix `@[sql: serial]` and `@[serial]` are not the same (fix #23346) (#23678)\n- Improve support for `v -path bootstrap_alternative_backend/ run simple.v` (#23679)\n- Fix codegen for array fixed on if and match expr (fix #23577, fix #23589) (#23682)\n- Add support for a `#postinclude` directive\n- Fix #preinclude, add test case for #postinclude too\n- Fix codegen for returning an initialised fixed array (fix #23693) (#23700)\n- Use `global_g.out << g.out` instead of `global_g.out.write(g.out) or { panic(err) }`\n- Fix issues found with the stricter sanitizers in clang-18 on Ubuntu 24.04 (#23710)\n- Fix codegen for nested if on return (fix #23723) (#23729)\n- Fix sumtype smartcasted var as inherited var (fix #23716) (#23731)\n- Fix map with an Enum as key type, with size < 4 bytes on tcc (fix #23714) (#23738)\n- Fix codegen for match with sumtype ptrptr (fix #23776) (#23785)\n- Fix aggregate var handling on match branch (fix #23768) (#23787)\n- Fix gowrapper codegen for receiver ptrptr (fix #23798) (#23800)\n- Fix regression, preventing the use of `-gc none -d no_main -no-builtin -no-preludes` to compile C\n  style V programs\n- Fix array fixed assignment for `@[keep_args_alive]` (partial fix for #23804) (#23805)\n- Fix nested option fixed array (fix #23708) (#23845)\n- Fix codegen for match on return (fix #23661) (#23851)\n- Fix casting primitive type to alias, where option alias is expected (fix #23859) (#23860)\n- Fix interface method list ordering to make test buildable with `g++` (fix #23701) (#23870)\n- Make `./v -prod -cstrict -cc gcc-11 test vlib/math/` pass cleanly (workaround a problem in V's\n  cgen, that -cstrict discovered)\n- Fix codegen for global array passed as mut (fix #23873) (#23881)\n- Fix msvc build filename, remove temp files (#23890)\n- Improve the stability of generated code for auto string methods\n- Fix codegen for array of anon struct (fix #23896) (#23907)\n- Make sure to call the overridden `pub fn (mut a []string) free() {` method, NOT the generic\n  `fn (a &array) free() {` one. (#23911)\n- Fix generic container init (fix #23910) (#23912)\n- Fix codegen for generic structinit and generic array return (fix #23916) (#23943)\n- Implement alias operator overloading for generic struct parent type (fix #23965) (#23967)\n- Add `T.key_type`, `typeof(expr).key_type`, `T.value_type`, `typeof(expr).value_type`,\n  `T.element_type`, `typeof(expr).element_type` for getting `Map[K]V` and `[]T` types (fix #23914) (\n  #23962)\n- Builtin,markused,pref,cgen: improve markused for small programs\n\n#### vfmt\n\n- Fix formatting for an option array of anon structs (fix #23841) (#23844)\n- Fix comment handling on ending of struct decl (fix #23947) (#23948)\n\n#### Tools\n\n- ci, vc: use the full V repo commit hash, when generating vlang/vc commit messages\n- Support `v should-compile-all folder/`, where `folder/` contains project subfolders (containing\n  v.mod files and multiple top level .v files)\n- Improve `v should-compile-all .` with support for compiling .wasm.v and .js.v files; skip\n  `module name` files, compile projects that have .glsl files\n- Improve `v bug` report wording\n- v.help: improve message formatting (#23363)\n- Restore `emcc --version` diagnostic in `v doctor`, when emcc is present\n- ci: fix `v -W build-tools` (#23368)\n- ci: force all tools to build without warnings/notices in tools_ci.yml (#23371)\n- Fix `v buf file.v`, when run in a folder != vroot\n- Improve output of `v bug file.v`, fix `v bug /long/abs/path/file.v` too\n- ci: make show_manual_release_cmd.vsh use a fixed weekly.YYY.WW format for the weekly release tags\n- ci: make easier the debugging of the `docker-alpine-musl-gcc` job (#23399)\n- vvet: fix for `v vet folder/` + new features (track long fns, empty fns and repeated code),\n  enabled by the new -F and -r flags (#23405)\n- v.help: add a message for `v help crun` (#23431)\n- Make cmd/tools/vretry_test.v independent from the presence of git (fix issue #23398)\n- ci: add compile_herolib.sh, use it to make sure it keeps working (related #23467) (#23469)\n- ci: fix toml-module-pass-external-test-suites after the CI image runner upgraded jq to version\n  1.7, by downloading and using the release version of jq-1.6\n- ci: fix failure of the check-markdown job\n- vet: add an `-I` option to notice fns, with the potential to be inlined (#23534)\n- ci: update last known good commit hash for herolib to ca8799af39228a5678a7be81128c5b0c342c9efc\n- Make `v check-md .` print the actual length of lines too, when reporting errors/warnings about\n  them (#23606)\n- Restore previous behavior of `v download` (show progress on stdout, when it is connected to an\n  interactive terminal; hide log stdout->stderr notice)\n- ci: fix `CI=name ./v -d network test cmd/tools/vpm/` ; update the image runners in vpm_ci.yml (\n  #23628)\n- Add `v reduce program.v`, in order to make smaller reproductions (`rpdc.v` files), before filing\n  cgen bugs (#23636)\n- Add a small utility script `cmd/tools/vrun`, to make it easier to use .vsh scripts on systems,\n  with `/usr/bin/env` still not supporting `-S`\n- Describe a more direct way to use a `v run` shebang in cmd/tools/vrun\n- Fix show_manual_release_cmd.vsh, use .strftime(%V) for calculating the proper default week number\n- Improve the `v reduce` parser for functions, and add more loops to reduce more (#23694)\n- Improve `v reduce` output; bump version, warn on failed string_reproduces/3, but continue to run (\n  #23697)\n- Fix warnings in `v reduce` (#23709)\n- Move `cmd/tools/vdoc/doc` to `cmd/tools/vdoc/document`, so that it can be imported from other\n  programs through `-path`, without conflicting with the top level `doc/` folder in the main repo (\n  #23733)\n- ci: avoid duplicating work by removing the remaining `-skip-unused` tasks, since that is the new\n  default (#23746)\n- ci: use distinct names for the jobs, for easier filtering/searching in the Github's UI\n- ci: fix job names in cmd/tools/modules/testing/common.v as well\n- ci: fix github job names in cmd/tools/vtest-self.v\n- ci: update the remaining runners from ubuntu-20.04 to ubuntu-22.04 and ubuntu-24.04 (#23754)\n- ci: rebuild V with `v -g self` in .github/workflows/native_backend_ci.yml, to improve remote\n  diagnosis of panics in PRs\n- ci: use `-silent` for the longer test runs (suppress most OK lines, to reduce scrolling on\n  failure)\n- .gitignore: ignore the project settings file for gf2 (a very nice GUI gdb frontend)\n- vrepl: fix slow response for empty line input (after just pressing 'enter/return') (fix #23856) (\n  #23858)\n- Make `v repeat failing_cmd` show the error output *just once*, but also still measure the time it\n  took to execute\n- Add --check flag to `v ast` (#23938)\n- Add `v timeout` to be able to later use `v timeout 5.1 git -C . fetch V_REPO` in `v doctor` and\n  other tools.\n- Add a custom timeout of 5s for the network using command `git -C . fetch V_REPO` in `v doctor` (it\n  normally takes <1s) (fix #23955)\n- Support `v doctor -skip-github` to fully skip the fetching step, in places that have limited\n  connectivity (alternative fix/workaround for #23955)\n- ci: use -silent in more jobs that produce a lot of OK lines normally (for test-cleancode,\n  test-self, build-examples, build-tools)\n\n#### Operating System support\n\n- Avoid os.glob, in favour of os.walk_ext (which works consistently even on windows)\n- gg: add linux support for `fn screen_size() Size` (fix #23146) (#23326)\n- Define _GNU_SOURCE on Linux (#23364)\n- Fix `v doctor` format, fixes for windows, tcc and others (#23361)\n- picoev: fix for windows apps with veb in a thread, parallel to a webview, that opens a lot of file\n  descriptors (#23492)\n- v.pref: set `DYLD_FALLBACK_LIBRARY_PATH` on macos, when `-use-coroutines` is used, so that `v run`\n  can work, and the executable can find the downloaded photonwrapper shared library (#23516)\n- encoding.iconv: add flag for OpenBSD to find iconv include and library (fix #23573) (#23575)\n- runtime: add free_memory/0 implementation for OpenBSD (fix #23579) (#23583)\n- Fix `v doctor` output on OpenBSD: get gcc version from egcc; do not run ldd to get the glibc\n  version (fix #23576) (#23578)\n- make.bat: add note about antivirus programs on windows and compilation slowdowns (#23586)\n- runtime: add free_memory/0 implementation for FreeBSD too (fix #23581) (#23594)\n- log,sync: fix macos CI failure when log.ThreadSafeLog is used explicitly in `v download` (#23613)\n- Let `v test .` show the running _test.v files each minute (set by\n  `VTEST_REPORT_RUNNING_PERIOD_MS`); diagnose stuck windows gcc CI jobs (#23649)\n- ci: run FreeBSD on a VM in github ci, instead of on the Cirrus service (which stopped working\n  today) (#23692)\n- cgen,builder: fix windows 32bit dll function name mangle (fix #23689) (#23690)\n- ci: update linux image runners from `ubuntu-20.04` to `ubuntu-24.04` (#23706)\n- ci: do not use `VJOBS: 1` in the windows tcc job anymore\n- make: use .exe only on Windows\n- ci: reduce the timeouts in windows_ci.yml to 60 minutes (V is now faster, and the runners use\n  faster hardware as well)\n- native: allow for searching for wine system32/ .dlls, and for adding more paths for .dll lookups,\n  by setting `VNATIVE_PE_DLL_PATH`, to make it easier to diagnose problems with PE generation on non\n  windows platforms (#23756)\n- ci: skip fibonacci_native.vv on windows for now\n- sync: support x86_64-alt-linux gcc paths too when tcc is used (needed for ALT Linux)\n- ci: make freebsd_ci.yml runnable on personal forked repos, that are not named `v` (#23779)\n- ci: remove the VJOBS=1 restriction for test-cleancode on linux (#23801)\n- os: fix buffer overflow in os.get_raw_line under Windows (#23816)\n- ci: move test in pe_test.v to native_test.v (both used `-b native`, competing the creation of the\n  backend executable => CI failures on the gcc-windows job)\n- Make `v install` avoid using `--filter=blob:none --shallow-submodules --also-filter-submodules` on\n  windows (#23840)\n- os: fix get_raw_line() on windows (fix #23843) (#23846)\n- ci: add a limit of 20 minutes to the test-on-freebsd-14-2-x86 CI job\n- Support `// vtest build: !do_not_test ?`, `// vtest build: !windows && tinyc` to skip files during\n  testing on specific platforms, without having to keep centralised skip lists (#23900)\n- cgen,dl: remove workaround in `dl`, generate a DllMain() in cgen instead for `-shared` on\n  windows (#23961)\n\n#### Examples\n\n- Allow for passing arbitrary compiler flags to `v bug`, for example: `v bug -cg -autofree file.v` (\n  #23335)\n- examples,builtin,cgen,live: fix windows hot reload with `-cc tcc`, improve the infrastructure, use\n  a V global instead of a C one (fix #23214) (#23350)\n- Fix unused db.pg import warning for examples/database/psql/customer.v\n- gg,sokol,examples: add example of overriding _SGL_DEFAULT_MAX_VERTICES in code\n- Mention also the RAM usage increase in many_thousands_of_circles_overriding_max_vertices.v\n- gg: enable clean compilation without notices for `./v -check-unused-fn-args examples/tetris/`\n- Add vascii.v showing a table of the first 128 ASCII characters with their names and codes in dec,\n  oct, hex, bin formats (#23466)\n- Add a solution to the \"1 Billion Row Challenge\" (#23458)\n- examples,io: add sha256sum_with_io_cp.v, make the size of the buffer used by io.cp\n  parametrisable (#23585)\n- log: add `log.use_stdout()`, use it to silence the transition note for the most commonly used V\n  tools/examples (#23642)\n- Implement an -s option for `v ast`, to skip all nodes with default values like [], {}, 0, false;\n  with it `v ast -pts examples/hello_world.v | wc -l` is 36 lines\n- gg: fix `./v -gc none -autofree run examples/tetris/` (avoid `return s1 + s2 + s3`, clone the\n  arrays, passed to the fontstash wrapper)\n- examples,gg: modify all remaining calls to fons.add_font_mem/3 to use an array.clone()\n- Add examples/hot_reload/tunnel.v\n- Add minimal_c_like_program_using_puts.v showing how to produce a much smaller executable on Linux,\n  using clang, mold and sstrip.\n- Build examples, that start with `module no_main` as well\n- ci: fix `v build-examples` failure on gcc-windows\n- Support `module no_main` based examples in `v should-compile-all`\n- term: make the second example in the README.md compilable as well\n- Show how to use a v file server for the wasm version of 2048, instead of emrun\n- sokol: allow for `v -os wasm32_emscripten -o examples/tetris/tetris.html examples/tetris/` (avoid\n  using `-sMODULARIZE`) (#23814)\n- Fix poll_coindesk_bitcoin_vs_usd_rate.v, use the new v2 API endpoint\n- math,examples: add examples/sokol/sounds/simple_sin_tone_using_audio_push.v, cleanup math\n- Add a small breakout game, supporting keyboard and touch controls (#23861)\n- Cleanup snek.v, by using `math.vec`, the builtin array support, instead of `datatypes`, and by\n  removing casts that are no longer needed\n- Fix `v -cstrict -cc gcc-11 examples/sokol/particles` and the same but with clang-18 too\n- Fix more compilation errors with `-cstrict -cc clang-18` for the sokol examples\n- Fix `VFLAGS='-no-skip-unused -cstrict -cc clang-18' v should-compile-all examples/sokol/` too\n- Add a small minesweeper game in examples/gg/minesweeper.v\n- Add a small Sokoban puzzle game with levels (see https://en.wikipedia.org/wiki/Sokoban)\n- Use textures in the sokoban game, instead of colors\n- Shorten the periodic output of examples/hot_reload/message.v\n- Fix (ball->side edge of brick) collision detection in breakout.v\n- Add subtle light and shadow effects to the breakout game, to give it a little depth (#23885)\n- Run the update method of breakout on its own frame independent rate\n- gg,examples: use a timer to limit the rate of updates in breakout, instead of a separate thread,\n  restore ability to run in a browser through emscripten\n- Make the tetris update rate, independent from the frame rate too\n- Make the 2048 game update rate, independent from the frame rate as well\n- Fix panic, discovered by fuzzing examples/2048/2048.v with zzuf on the CI\n- Add `vanilla_http_server` - a fast, multi-threaded, non-blocking, port and host reuse,\n  thread-safe, epoll server (#23094)\n- v.build_constraint: support comments too, for example `linux&&gcc // some comment`\n- Make `v repeat -R 5 -r 10 \"v run examples/hello_world.v\"` also show the time it took for all runs\n  in each repeat\n- Add an asteroids game (it is currently < 400 lines of V, using gg)\n- Remove the generic alias type overloaded operator workaround, after 29e60da\n- Fix `v should-compile-all examples/`\n\n## V 0.4.9\n\n*22 Dec 2024*\n\n#### Improvements in the language\n\n- `-skip-unused` is now on by default resulting in much smaller cgen and binaries. 70% reduction for\n  hello world.\n- `-parallel-cc` for speeding up `-prod` and `-cc clang/gcc` compilation by up to 14 times!\n- C functions no longer need to be manually defined. An `#include \"foo.c\"` is enough (behind\n  `-experimental` for now).\n- Fixed arrays now have `.index .any .all .map .sort .sorted` methods\n- Remove inline sum types completely\n- Support `in` expr with number ranges: `if var in 1..4 {` (fix #20352) (#22754)\n- Optimize literal string comparison (`match`, `in` and `==`) (#22643)\n- Allow `map[k]()?` and `map[k]()()` (#22740)\n- Add selector option unwrapping inside `if tree.root != none {` (#22895)\n- Add `array.count` as a method that accepts a predicate, similar to filter, but returning just the\n  number of matches (#23054)\n- Allow option array element comparison `==` and `!=` (fix #23108) (#23113)\n\n#### Breaking changes\n\n- time: rewrite parse_rfc3339/1 to improve performance, reject partial timestamps, that miss date\n  info like `22:47:08Z` (#22585)\n\n#### Checker improvements/fixes\n\n- Optimize identical type checking (#22596)\n- Fix `T.unaliased_typ` if branch evaluation (fix #22587) (#22598)\n- Fix lambda expr with fntype params and restore fixed_array_any_all_test.v (#22625)\n- Check fixed array builtin method args mismatch (#22626)\n- Fix generic fn call return type resolve on var assignment (fix #22612) (#22627)\n- Improve checking parameter mismatches for fixed array builtin methods (#22630)\n- Add tests for checking the new errors for fixed arrays .sort() calls (#22656)\n- Fix index expr that left is if expr (fix #22654) (#22661)\n- Fix return type checks, when returning struct values, implementing IError in non-result fn (fix\n  #22659) (fix #22658) (#22660)\n- `App.method` field initialisation, for fn fields, initialised with generic methods (#22665)\n- Allow for `f() or { T{} }` in a generic method, for `fn f() ?T {`, being called with `T`, being a\n  container like []int etc, not just a primitive type like int (#22672)\n- Allow for `f() or { T{} }` part 2, see also cc55aa5 (handle the case of an ignored result as\n  well) (#22687)\n- Fix selector with prefixed `&` structinit (#22689)\n- Fix missing check for fn var with generic return inherited to anon fn (fix #19045) (#22683)\n- Check for receiver name clashing with global var (fix #22698) (#22708)\n- Fix none check for match expr with option (fix #22728) (#22732)\n- Fix option map fn type and missing check for result param type (fix #22736) (#22738)\n- Fix missing info about generic fn var usage without concrete types (fix #22733, #22734) (#22743)\n- Fix missing check for stack pointer return (fix #22726) (#22756)\n- Improve static method call resolution (fix #22773) (#22787)\n- Skip redundant message for int overflows, while casting integer literals (fix #22761) (#22788)\n- Fix callexpr after auto C func identification (fix #22800) (#22809)\n- Fix missing auto `from_string` type restriction (related to #22783) (#22803)\n- Fix match expr with empty array init expression (#22832)\n- Disallow `foo[T]` as a value  (#22820)\n- Fix if expr with empty array init expression (related #22832) (#22841)\n- Improve the position underlining, for last statements in branches of `if` expressions  (#22845)\n- Fix generic fn call with empty array argument (fix #22843) (#22846)\n- Fix missing or-block check for callexpr (fix #22835) (#22840)\n- Check array builtin method calls, that do need a mutable receiver, but are called on an immutable\n  one (fix #22850) (#22853)\n- Check alias of array op overloading and fix op overloading (fix #22851) (#22854)\n- Disallow struct init with `mutable_field: const_array` (fix #22862) (#22863)\n- Check struct aliased field unsign type assigning negative value (fix #22868) (#22871)\n- Fix alias to struct generic type (fix #22866) (#22872)\n- Fix `json.encode_pretty` with a struct init expression argument (#22897)\n- Fix codegen for fixed array initialization with a fn call (fix #22887) (#22891)\n- Fix or-expr check on invalid method call (fix #22949) (#22950)\n- Fix mut var option unwrap with `!= none`, support `if mut x != none {` too (fix #22936) (#22943)\n- Prevent a compiler panic, while running `v -check file.v` on files with parser errors (fix\n  #22981) (#22982)\n- Allow array sort with callexpr (#22989)\n- Fix `$res()` used in `defer {}` blocks with more statements, add a test (#22998)\n- Fix generec fn returning generic closure (#23047)\n- Fix generic fn returning generic closure (related #23047) (#23055)\n- Fix missing checker for cast from mut var to non-ptr type (fix #23017) (#23056)\n- Check fn call argument mismatch (fix #23016) (#23061)\n- Fix empty array append multi dims (fix #23092) (#23096)\n- Fix selector generic or block (fix #23088) (#23102)\n- Fix veb route method param with non ctx name (fix #23105) (#23107)\n- Allow fixed array where voidptr is expected (fix #23090) (#23100)\n- Fix immutable to mutable reference (fix #22653) (#22663)\n- Fix missing check on range expr when high var is same iteration value var (#23130)\n- Allow `[]Enum{len: 10, init: .thing}` (fix #23077) (#23165)\n- Fix option unwrapping and call from option struct field (#23182)\n- Add a notice for global variable redeclarations (#23162)\n- Fix assign check, when rechecking for another concrete type (#23212)\n\n#### Parser improvements\n\n- Fix generic struct init detection `T{}` (#22682)\n- Improve the assert informations (related #22668) (#22679)\n- Make C struct fields public and mutable by default (fix #22695) (#22706)\n- Fix enum redeclaration error (fix #22759) (#22766)\n- Fix struct field name using keyword (fix #22826) (#22829)\n- Optimise mark_var_as_used calls, by moving it to an ast.Scope method (#22842)\n- Optimize method parameter detection in used check (#22915)\n- Fix block position's last line (#22913)\n- Support `@[must_use]` tag for fns/methods, and an experimental `-check-result` option (#22983)\n- Allow `type` as field type on params struct construction (fix #23091) (#23098)\n- Allow `type` and other keywords as plain attr value (fix #23150) (#23154)\n- Support `@[tag]` for hash statements, like `#define` and `#flag` (#23210)\n\n#### Compiler internals\n\n- Add `:parse_text` to the paths of .v files, printed by `-print-v-files`, for parse time generated\n  snippets\n- v.pref: support a `_wasm32_emscripten.c.v` suffix for platform files too\n- builder: fix msvc build thirdparty obj file from .cpp (fix #22772) (#22789)\n- v.util: use temporary workaround for the vinix build problem (when VFLAGS is set, and `-ldflags `\n  is passed at the same time)\n- Allow getting notified about unused function params (#22879)\n- v.scanner: remove `Scanner.is_started` field (#22918)\n- v.scanner: fix string interpolation for float e format (fix #22429) (#23147)\n- cbuilder: remove flto with parallel-cc, it slowed down linking 10x\n- cbuilder: store split up C files in vtmp\n- v.builder: integrate more compile/linker options into parallel_cc.v (#23190)\n- v.builder: prevent passing `-x objective-c` with `-parallel-cc` for now\n- v.builder: move filtering logic for `-parallel-cc` to parallel_cc.v\n- v.pref: support `-debug` and `-cdebug`, as more explicit alternative names for `-g` and `-cg` (\n  #23208)\n- v.builder: fail the whole v compilation, if linking or compiling during `-parallel-cc` fails (\n  #23211)\n- v.pref: implement `-no-prod-options` to turn off passing `-O3 -flto`, while still keeping the\n  `$if prod {` branches (passing custom flags with `-cflags -Os` already works)\n- v.builder: support `-no-prod-options` with `-cc msvc` as well\n\n#### Standard library\n\n- builtin: improve performance of `string.starts_with/1` and `string.ends_with/1`, when compiled\n  with tcc (#22620)\n- builtin: improve `fixed_array_any_all_test.v` (related #22609) (#22621)\n- builtin: temporary fix fixed_array_any_all_test.v (#22624)\n- builtin: support `-d no_gc_threads` for turning off passing `-DGC_THREADS=1` while compiling the\n  GC library\n- encoding.utf8: fix is_punct func (fix #22646) (#22647)\n- log,time: improve performance for writing a line to a log, add Time.format_rfc3339_micro/0 (\n  #22662)\n- flag: add missing short flag match in `flag.to_struct`, add test (#22696)\n- bitfield: add `shift_left/1` and `shift_right/1` methods to `BitField` (#22700)\n- x.json2: pre-arranging the replacement of the decoder, to\n  match https://github.com/enghitalo/v/tree/decoder2_to_json2 (#22729)\n- builtin: improve fixed_array_any_all_test.v (#22746)\n- builtin: add `string.is_pure_ascii()` (#22748)\n- os: document the various enum values in os.Signal (#22770)\n- builtin: fix runes.to_upper() (fix #22742) (#22755)\n- ci: use os.system to redirect output\n- vlib: initial addition of `x.encoding.asn1` (#22783)\n- os: work towards being able to again use `-autofree` while recompiling the V compiler several\n  times\n- x.encoding.asn1: fix time creation to also accommodate negative timezone offsets (#22861)\n- vlib: remove modules/functions/fields, deprecated in 2023 (#22750)\n- term: improve performance of repeated can_show_color_on_stdout and can_show_color_on_stderr calls,\n  by caching their results (#22893)\n- builtin: make int_min/2 and int_max/2 public\n- json: mark json_print_pretty/1 with `@[markused]` (used by cgen)\n- math.big: use `@[manualfree]` to workaround -autofree compilation issues with gitly, and other\n  projects using `crypto.rand` and `math.big`\n- x.encoding.asn1: improve performance (#22948)\n- gg: use a larger fontstash text atlas by default (2048x2048, and customizable), instead of\n  512x512 (fix #21610) (#22959)\n- Revert \"os: deprecate `os.getwd` in favor of `os.get_current_dir` (part 1) (#22966)\"\n- log: tag log.fatal with @[noreturn] (#22986)\n- runtime: force runtime.nr_jobs() to return 1, while V is bootstrapping itself, from vc/ source,\n  that was compiled with `-os cross` (fix #22991)\n- json: fix decode codegen for []&type (fix #23007) (#23010)\n- os: add os.get_trimmed_lines() too\n- crypto.sha3: add support for Keccak-256 and Keccak-512 (#23058)\n- rand: add missing i32 APIs, corresponding to the int ones\n- math.big: fix `assert big.integer_from_int(1) == big.integer_from_bytes([u8(0), 0, 0, 0, 1])` (fix\n  #23115) (#23124)\n- math: use libc wrappers for math.log2/1, math.log10/1, math.log1p/1 and math.log_b/1; make\n  `assert math.log10(10) == 1.0` pass in the common case (#23129)\n- gg: add `icon` field to gg.Config, for easier access (fix #23135) (#23138)\n- math: fix math.log10() for `-exclude @vlib/math/*.c.v` (fix #23136) (#23140)\n- json: add primitive type validation (fix #23021) (#23142)\n- json: fix memory leak on result messages (checked with `json_option_raw_test.v`, compiled with\n  `-fsanitize=address,pointer-compare,pointer-subtract`) (#23172)\n- vlib: add new `rand.cuid2` module (#23181)\n- json: fix memleak on sumtype decoding (#23197)\n- vlib: enable more satnitized memleak detection runs without false positives on the CI (#23200)\n- json: fix argument freeing for json.encode and json.encode_pretty calls (#22781)\n\n#### Web\n\n- veb: translations via %translation_key\n- picoev,net.http: use Time.http_header_string method, to improve performance (#22619)\n- Do `import veb`, only for templates that do use functions defined in `veb`\n- picoev: support `-d picoev_verbose_errors`, do not use any naked `eprintln` by default, since that\n  is a low level module\n- picoev: fix the incompatible pointer type cast error in the C.epoll_wait call (#22785)\n- net.mbedtls: define MBEDTLS_THREADING_PTHREAD, in mbedtls_config.h; call\n  C.mbedtls_ssl_conf_read_timeout explicitly in the wrapper, with a shorter timeout value of 317ms (\n  determined experimentally)\n- veb: fix large file transfer timeout (fix #22489) (#22924)\n- net.http: send Host headers with port (when the port is != 80 or 443) (fix #22941) (#22942)\n- net.mbedtls: support compiling with `-d mbedtls_client_read_timeout_ms=7000`,\n  `-d mbedtls_server_read_timeout_ms=60000`, and `-d trace_mbedtls_timeouts`\n- net.urllib: fix parse of url relative address (fix #21061) (#23180)\n- veb: fix key value and translation file name (#23203)\n\n#### ORM\n\n- Fix orm.Connection only allowing immutable Connections (#22684)\n- Fix order by with custom column name (#22813)\n- Support plain `@[serial]` attribute for marking struct fields (#22814)\n- Fix crash when working with array field (fix #22822) (#22824)\n- Fix list generation and escape loose backtick (#23039)\n- Fix mark as used var on insert statement (fix #23032) (#23038)\n- Fix update stmt with enum value (fix #23031) (#23037)\n\n#### C backend\n\n- Fix codegen for fixed array contains - `[1,2]! in a` (fix #22559) (#22579)\n- Improve fixed array literal in operation and index calls (#22590)\n- Add codegen for auto free methods for interface type (#22555)\n- Add test for #22586 (#22600)\n- Parser,ast,cgen: do is_builtin sym marking during parse time just *once*, to save multiple checks\n  later (#22580)\n- Cache the results of g.base_type/1 (#22613)\n- Add caching to contains_ptr return (#22605)\n- Add .write2/2 and .writeln2/2 methods to reduce consecutive write calls (#22610)\n- Optimise the generated code for returning literal values and option/result values (#22622)\n- Optimize literal string comparison (string__eq -> vmemcmp) (#22614)\n- Fix selector indexexpr with fntype on assignment (fix #22635) (#22637)\n- Fix anon fn with `&` prefix (fix #22628) (#22638)\n- Fix struct field init with fixed array using index (fix #22616) (#22641)\n- Fix interface conversion codegen race issue (fix #22640, #17943) (#22655)\n- Fix waiter funcs declarations (fix #22640) (#22649)\n- Improve the assert informations (fix #22666) (#22668)\n- Fix dump of alias to option fn type (fix #22670) (#22676)\n- Fix array append map value with or expr (fix #22674) (#22678)\n- Ensure proper saving/restoring of cgen `map[k] := fn ()` state, when assigning anonymous fns (fix\n  #22705) (#22707)\n- Implement methods sort_with_compare()/sorted_with_compare() for fixed arrays (#22702)\n- Implement methods reverse()/reverse_in_place() for fixed arrays (#22712)\n- Fix ptr field encoding for `json` (fix #22717) (#22720)\n- Fix `[1, 2, 3]!.map(it * 2)` (#22722)\n- Fix `assert [1, 2, 3]!.contains(2)` (#22725)\n- Fix `assert [1, 2, 3]!.index(2) == 1` (#22727)\n- Fix spawn with non-pointer receiver (fix #22718) (#22719)\n- Fix `assert [1, 2, 3]!.reverse() == [3, 2, 1]!` (#22745)\n- Fix codegen for `-no-builtin` flag (when used separately from `-d no_main`) (#22765)\n- Apply the `a in [x,y,z]` optimisation for `ast.IndexExpr` and `ast.SelectorExpr` again (#22767)\n- Fix codegen to emit callexpr one time for `in` expr optimization (#22764)\n- Fix c codegen formatting for return match (#22768)\n- Avoid generation of empty `or` blocks for `f() or {}` (#22775)\n- Fix struct field name using c keyword `typeof` (fix #22779) (#22782)\n- Remove unused code generated for unwrapping temp var from callexpr (detect unused return value\n  from CallExpr), fix parser bugs (#22769)\n- Enable if guard to add `err` var on else branch, after last `else if` (fix #22784) (#22786)\n- Fix option struct default value init with `-cstrict` (spotted in #22783) (#22802)\n- Fix codegen for fn fixed array param w/ size defined by const (fix #22811) (#22812)\n- Fix wrong type resolution on infix (#22804)\n- Fix default `T{}` when `T` is ref type + dereferencing issue when comparing int alias to int (fix\n  #22795) (#22807)\n- Fix generation of a missing return in `return if cond { x } else { return missing }` (fix\n  #22838) (#22839)\n- Fix generic static method call return type resolution (#22865)\n- Fix array fixed code generation for more than 1 dimension (fix #22866) (#22876)\n- Fix codegen for `$if` in an if expression, when compiled with `-g` (fix #22873) (#22888)\n- Make errors more informative (resolve empty panics) (related: #21184) (#22898)\n- Generate json array line on uniform indent lvl (#22899)\n- Fix codegen for returning a fixed array as a result (fix #22894) (#22896)\n- Fix codegen for alias type interface methods (fix #22901) (#22902)\n- Fix codegen for assigning aliased fixed array (fix #22907) (#22909)\n- Fix codegen for returning option aliased fixed array (fix #22910, fix #22911) (#22912)\n- Fix aliases of fixed array infix expression (fix #22925) (#22928)\n- Fix aliases of fixed array append to array (fix #22926) (#22929)\n- Fix option unwrap for fields of interface type (fixes #22930) (#22931)\n- Fix aliased fixed array option fn call (fix #22927) (#22934)\n- Move the `msvc compiler does not support inline assembly` to cgen (so it will only get triggered,\n  when ASM blocks are still present, in what is passed to cgen)\n- Fix dump fixed array on array append (fix #22935) (#22940)\n- Fix enum value string interpolation, like its declared enum underlying type (fix #22938) (#22945)\n- Allow unwrapping of `x as string` expr, when `x` is a `?string` value (#22953)\n- Fix codegen for result/option propagation out of fn context (fix #22961) (#22963)\n- Fix codegen for option on concatexpr (fix #22951) (#22964)\n- Reduce code for returning and extra whitespaces on `return` (#22967)\n- Allow unwrapping of `foo.bar as string`, where `foo.bar` is `?string` (fix #22960) (#22973)\n- Add thread timing stats too, on `-show-timings -stats` (#22990)\n- Patch missing `gettid()` on glibc < 2.30 (#22987)\n- Fix array fixed on update expr and alias type to multi dimension of fixed array (fix #22971) (\n  #22972)\n- Fix sumtype with embedded struct of option field (fix #22984) (#22996)\n- Fix autostr for interface with circular type (fix #23022) (#23026)\n- Fix array.delete_many() codegen (fix #23024) (#23025)\n- Fix callexpr or-expr codegen on const decl (fix #23029) (#23043)\n- Fix struct update embed expr for fixed arrays (fix #22999) (#23040)\n- Fix update expr with embed fixed array with multiple dimensions (fix #23048) (#23049)\n- Fix cast interface value in match expr (#23068)\n- Prevent too long lines in array initialisations (#23074)\n- Fix smartcast codegen for msvc (#23084)\n- Fix option codegen for accept IError value (fix #23076) (#23085)\n- Fixed for in loop with generic fixed array (fix #23075) (#23101)\n- Fix printing fn call of returning c struct value (fix #23104) (#23106)\n- Fix array fixed comparison from fn return (fix #23071) (#23114)\n- Fix array map to fixed array (fix #23116) (#23118)\n- Fix codegen for returning different option alias type (fix #23087) (#23125)\n- Fix for in for interface type (fix #23119) (#23127)\n- Fix codegen for generic selector expr (fix #22974) (#23132)\n- Fix different option alias type as fn arg (fix #23086) (#23131)\n- Fix codegen for returning option reference from indexexpr (fix #23133) (#23139)\n- Fix array fixed auto str on `-cstrict` (#23144)\n- Fix codegen for array append on indexexpr (fix #23156) (#23160)\n- Fix assert for alias to fixed array (fix #23149) (#23161)\"\n- Fix auto eq for fixed array (fix #23149) (#23169)\n- Fix fixed array option cast with `none` (fix #23164) (#23168)\n- Fix selector call with reserved c name (fix #23170) (#23175)\n- Parser,checker,cgen,fmt: fix array fixed option initialization (`none`) (complete #23164) (#23176)\n- Fix option fn with voidptr arg (fix #23170 for !=tcc too) (#23179)\n- Fix missing validation for selector unwrapping + fix default `return none` for unwrapping (#23183)\n- Fix assign optional aliases of fixed array (fix #23185) (#23188)\n- Fix struct field init with optional fixed array (fix #23193, fix #23195) (#23199)\n- Reduce RAM usage, by avoiding a .str() call, for the final string builder, containing the final C\n  program, used to write it to a file (#23226)\n\n#### vfmt\n\n- Add support for comments inside `sql db { ... }` blocks (fix #22601) (#22602)\n- Fix formatting fixed array size of struct member (#22815)\n- Fix formating non-unsafe blocks with break line (fix #22900) (#22903)\n- Fix shared receiver formatting (fix #23151) (#23153)\n\n#### Tools\n\n- ci: add benchmark_footprint_json_decode.yml and benchmark_footprint_json_encode.yml (#22592)\n- Use a `~same~` label, when the results in `v repeat` are not different enough\n- Allow for fast exiting in compare_pr_to_master.v through Ctrl-C (or any failed command)\n- ci: fix failing jobs after 4ed9d13 (#22606)\n- Discard the top 7 results for each 10 runs, from `v repeat` runs, done by compare_pr_to_master.v,\n  to reduce σ on machines with more varied load\n- Allow for `v repeat -N ./cmd/tools/vtest_test`, by adding a -N/--no_vexe_reset option to\n  `v repeat`\n- Show more details in compare_pr_to_master.v\n- ci: fix failing musl jobs after 2684ef9 (#22667)\n- ci: run `zizmor .github/workflows/paths_ci.yml` and fix reported issues (#22681)\n- Show the full test output, on known flaky test failure with `v test folder/` (#22716)\n- Change `v test` to allow for `// vtest hide_retries` so that retry_test.v can hide its own (\n  deliberate) retries\n- ci: rename one of the duplicate `main_test.v` files, to reduce false positives (workaround)\n- Fix `v doctor` output for missing `cc`. Add a diagnostic line checking for `emcc --version` too\n- ci: run `v fmt -w vlib/v/pref/should_compile.v`\n- ci: reduce flakyness of cmd/tools/vcover/cover_test.v (workaround for a race condition while\n  updating the OK tasks counter in `v test`)\n- Improve the diagnostic output of compare_pr_to_master.v\n- ci: add a problem matcher support, to get error/warning/notice annotations in V CI jobs (#22790)\n- Bump default `v retry` timeout to 10 minutes, clarify the usage of its `--timeout` option.\n- ci: fix Build V\n- ci: silence compilation warning for bench_string_key_in_map_vs_string_value_in_array.v\n- ci: fix vinix_ci.yml for latest Vinix commits (#22818)\n- Improve output of compare_pr_to_master.v\n- Use `v retry` in more places, that do network operations that can fail temporarily (#22836)\n- Allow for `v download -RD URL/script.vsh`, to download `script.vsh`, then run it locally, then\n  remove it, in a single command\n- v.help: add topic for `v help retry`\n- v.help: add help topic for `v help repeat`\n- ci,v.help: work around -autofree bugs, fix `./v -autofree -o v2 cmd/v`\n- ci: add .yml file for testing compilation of Larpon's Shy library and the Puzzle Vibes game (\n  #22874)\n- ci: check more compile flag combinations in puzzle_vibes_ci.yml\n- Fix compilation of hw with vnew -> vold, in compare_pr_to_master.v\n- ci: fix for `v build-tools`\n- ci: check that more apps/modules do compile with -skip-unused (#22904)\n- vet: make `v vet` produce a nicer note, including the offending files, instead of `file.v` (\n  #22957)\n- ci: extract the VTL&VSL jobs from v_apps_and_modules_compile_ci.yml to vsl_and_vtl_compile_ci.yml\n- Make oldv aware of when to pass -no-parallel when bootstrapping V from v.c (fix #22990, part 2)\n- markused: only add .vtest_ functions, *when* compiling _test.v files (#23003)\n- Improve oldv compatibility for using new stricter C compilers like clang-18, to compile older V\n  versions from 2020 and 2019\n- Use -Wno-error=incompatible-pointer-types in oldv, which is more permissive than just\n  -Wno-error=incompatible-function-pointer-types, and works with gcc too, not just clang\n- Describe more precisely what commands are used by `oldv`, so it can fail early, with a meaningful\n  error message, if they are not present.\n- ci: fix ROADMAP.md checks (#23059)\n- vrepl: shrink .repl inputs, so repl_test.v runs faster\n- ci: update compile_v_with_vtcc.sh, enable its CI task again (#23063)\n- ci: extract .github/workflows/compile_discordv.sh, enable its CI step again\n- json2.decoder2: prepare decoder in json2 to be replaced by json2.decode2 (#23078)\n- Let oldv fail early, when git fails to do network operations or checkouts\n- ci: fix for `-cc tcc -no-retry-compilation`, do not use more complex constants, but functions in\n  vlib/math/vec/vec2_test.v\n- ci: fix option_fn_voidptr_test.v after a200c45\n- ci: make the CI more robust, by retrying commands and `v download` instead of wget (#23196)\n- ci: use `v retry -- v setup-freetype` to make the CI more robust against random network failures\n- ci: change exec name for parallel cc\n- ci: speed up again sanitizer runs (#23222)\n\n#### Operating System support\n\n- builder: change linuxroot repo URL to https://github.com/vlang/linuxroot\n- ci: test -os linux cross compilation on macOS\n- ci: test the cross compilation from macos to linux sooner, show more information\n- ci: move the macos->linux check even higher, to make easier testing and diagnosing linuxroot\n  update failures\n- orm: cross compile pg to linux; openssl: make cross compile work\n- ci: use `macos-14` instead of `macos-12` because\n  of https://github.com/actions/runner-images/issues/10721\n- ci: macos_ci.vsh\n- ci: fmt macos_ci.vsh\n- ci: use thew new macos_ci.vsh (github)\n- ci: improve output of macos_ci.vsh\n- ci: extract `ci/common/runner.v`, use it to simplify ci/macos_ci.vsh even more\n- ci: fix spurious failures for printing_struct_with_thread_field.vv on windows\n- net.http: ensure that http.download_file_with_progress/3 works (in a degraded mode), on windows,\n  even without passing `-d no_vschannel`\n- builder: fix cross compiling from linux to windows, when passing -g/-cg\n- docs: update the documentation of the @[console] tag, add advice to use `-subsystem windows`\n  instead\n- Make compare_pr_to_master.v use /opt/homebrew/bin/gtime on macos, and a pure V fallback, not just\n  for windows\n- ci,thirdparty: enable MBEDTLS_THREADING_PTHREAD and MBEDTLS_THREADING_C only on Linux for now (fix\n  windows CI)\n- thirdparty: enable MBEDTLS_THREADING_C and MBEDTLS_THREADING_PTHREAD on FreeBSD too\n- os: use _wputenv instead of _putenv to stay in sync with _wgetenv (fix changing env variables with\n  non ASCII content on windows) (#22920)\n- ci: avoid false positives for the existing PRs, by comment out the task\n  `V self compilation with -usecache` on macos for now (#23145)\n- ci: linux_ci.vsh; cgen: parallel-cc fixes\n- ci: remove extra EOL from linux_ci.yml (#23187)\n- Fix profile time on windows  (#23227)\n\n#### Comptime\n\n- Add `typeof(var).indirections` and `T.indirections` (#22805)\n- Add `typeof(expr).unaliased_typ` (#22806)\n- Allow sumtype init by variant comptime var `T(v)` / `SumType(v)` (#22664)\n- Fix missing bool AttributeKind.kind (#23159)\n- Fix comptime `T.methods`  with generic types and interface checking with `is` operator (fix\n  #22721) (#22724)\n\n#### Examples\n\n- Fix some of the instructions in `examples/thread_safety/` (#22571)\n- builder,pref: fix `./v -os linux examples/json.v` on macos (#22651)\n- Add examples/assets/v.svg and examples/assets/v_16x16.svg\n- v.comptime: fix compilation of `examples/veb/veb_example.v` with V compiled with tcc on macos\n- ci: ensure that all examples can still be compiled, by `v` compiled with tcc on macos\n- Add poll_coindesk_bitcoin_vs_usd_rate.v\n- Simplify and reorder output of poll_coindesk_bitcoin_vs_usd_rate.v\n- builtin: fix `v -skip-unused -cc tcc examples/hello_world.v` on *BSD\n- net.mbedtls: bump mbedtls_ssl_conf_read_timeout value to 550ms (tested with\n  `v run examples/net_t.v`)\n- Add a cpu_features/ folder, with several examples, using SSE and MMX assembly instructions (\n  #22645)\n- v.builder: fix `./v -check -stats examples/hello_world.v`\n- docs: add a small sumtype match example in the Match section too\n- Add TextScanner .skip_whitespace/0, .peek_u8/0, .peek_n_u8/0, add\n  examples/mini_calculator_recursive_descent.v (#23001)\n- Reduce completion friction, when doing the very common `v run examples/hello_world.v` in a shell\n\n## V 0.4.8\n\n*28 Sep 2024*\n\n#### Improvements in the language\n\n- A new `implements` keyword for explicit interface implementation\n- Allow multi return as fn argument (#21991)\n- Define a default sumtype value (based on the first variant type) (#22039)\n- Remove the obsolete .code and .msg fields of IError (#22066)\n- Fix generic lambda type binding and resolution (#22083)\n- Comptime support for traversing the method parameters with `$for param in method.params {` (\n  #22229)\n- Show missing variants in the sum type error\n- A much better and detailed unmatched fn arg error\n- Add support for `@BUILD_DATE`, `@BUILD_TIME` and `@BUILD_TIMESTAMP`, all using\n  v.util.get_build_time(), and overridable through SOURCE_DATE_EPOCH (#22213)\n\n#### Breaking changes\n\n- Deprecate `x.vweb` and `vweb` in favor of `veb`, a faster, easier, and more stable framework.\n\n#### Checker improvements/fixes\n\n- Disallow static fn call when receiver type is unknown  (#21970)\n- Fix sumtype checking for voidptr variant (#21955)\n- Check comptime veb.html('index.html') (#21961)\n- Check if a parent generic struct has concrete types or not  (#21962)\n- Add support for static methods in `@FN` and `@METHOD`  (#21990)\n- Add a deprecation warning for `const ()` groups (an error after 2025-01-01) (#22019)\n- Improve `-d trace_checker` and error diagnostic information on compiler panics\n- Add error when initializing sumtype with struct as first type (#22067)\n- Add infix checks for nil  (#22045)\n- Fix map generic fn arg passing (#22071)\n- Disallow using a preexisting const name in a for loop, as either a key or value ident (#22108)\n- Fix generic lambda type binding resolution (fix #22109) (#22115)\n- Fix array alias (#22175)\n- Restrict multiple union fields initialised at once with a nicer checker error, instead of\n  producing an enigmatic error at cgen time (#22196)\n- Fix compilation of vlib/v/slow_tests/assembly/asm_test.amd64.v (regression after dfc0c91)\n- Add missing check for ref passing to non-ref (#22194)\n- Check struct implements non interface type (fix #22200) (#22218)\n- Suggest using the `@[_allow_multiple_values]` attribute, when declaring enums that have duplicate\n  values (#22224)\n- Check for duplicate interface names in the `implements` parts of struct declarations (#22230)\n- Fix missing struct field type checking for type mismatch (ref vs non-ref in\n  `mt sync.Mutex = sync.new_mutex()`) (fix #18088) (#21949)\n- Fix fntype var marked as auto heap (#22290)\n- Check array.delete() argument mismatch (#22307)\n- Add missing check for duplicated items on in expr (fix #22305) (#22308)\n- Disallow infix expr on left side of assign  (#22322)\n- Fix array fixed return type for interface methods (#22320)\n- Check arguments mismatch of array.sorted_with_compare() (fix #22327) (#22328)\n- Add an error for returning an `any` value in pure V code (prevents invalid cgen) (fix #12623) (\n  #22334)\n- Cleanup the checking of array method calls (#22338)\n- Fix voidptr type checking  (#21923)\n\n#### Parser improvements\n\n- Fix lots of parser panics, discovered through fuzzing with radamsa\n- Improve the error for keyword `lock`, used as a variable name (#21937)\n- Improve the error message position for invalid array attr keys (#21944)\n- Fix const field str() (#21998)\n- Update `@include` in templates, to work with relative paths & prevent recursive calls (#21943)\n- Check fn call args without comma between them (related #22021) (#22075)\n- parser,scanner,ast: make the scanner and parser more robust, by implementing more limits (\n  preventing panics, discovered by fuzzing)\n- Protect against too deep recursion in Expr.pos() calls\n- Check too many layers embedded generic type (fix #22089) (#22091)\n- Cache ident lookups for consts in ast Expr str (#22101)\n- Improve Type and TypeFlag related operations (#22107)\n- Fix parsing map value inside or expr (fix #12164) (#22180)\n- Fix const field str() (#22192)\n- Fix `.${var}` used in a template, compiled by `$tmpl()` (fix #22231) (#22270)\n- Check enum method duplicated (fix #20924) (#22294)\n\n#### Compiler internals\n\n- scanner: guard against scanner panic, discovered by fuzzing in PR#22016\n- v.builder: show the thirdparty object compilation commands too, when using `-showcc` (when the\n  cache is empty)\n- builder: allow for `v -dump-defines - -check cmd/v`, which is faster, because it can skip code\n  generation\n- Reduce allocations for the most common cases (#22142)\n- transformer: add support for instrumenting the V compiler with `-d trace_transformer`\n\n#### Standard library\n\n- encoding.base58: fix notice for slice creation (#21935)\n- gg: reset ctx.mouse_d? and ctx.scroll_? at the end of each frame (fix #21945) (#21946)\n- builtin: v_segmentation_fault_handler signal_number i32\n- builtin: fix 'aaaa'.split('aa') (fix #21936) (#21951)\n- builtin: panic on trying to grow arrays with capacity bigger than 2^31, instead of overflowing\n  a.cap (partial fix for #21918) (#21947)\n- gg: add a note that Context.new_streaming_image has to be called after Sokol's setup\n- gg: add more documentation comments for gg.Config (the parameters of gg.start and gg.new_context)\n- regex: fix regex.split() (fix #16876) (#21953)\n- json: increase test cases before enabling sumtype decode in all json libraries (#21958)\n- gg: change the type of gg.DrawImageConfig.rotate from `int` to `f32`\n- gg: deprecate gg.DrawImageConfig.rotate, in favor of gg.DrawImageConfig.rotation, improve the\n  documentation comments (#21963)\n- x.crypto.chacha20: make Cipher struct public (fix #21967) (#21968)\n- tmpl: fix an extra newline in @for; builtin: some i64 fixes\n- gg: add an optional size: parameter to the .draw_pixels and .draw_pixel methods (defaults to 1.0)\n- sokol: update to match upstream at c0e0563 (#21971)\n- Add support for `Any` in `decode_struct`, `encode_struct` and `to_any` (#21972)\n- crypto.cipher: make Stream.xor_key_stream implementers require a mutable receiver (#21974)\n- sokol.audio: fix `./v -cc clang-18 -gc none simple_bytebeat.v` (the audio depends on threads)\n- time: `d`,`c`,`dd`,`ddd`,`dddd` pattern support for parse_format() (#22003)\n- flag: add optional value description to string parameters (#22024)\n- flag: add custom value descriptions for bool, int, and float flags too (#22032)\n- flag: fix assigning to `@[tail]` field when no fields has been matched yet in `flag.parse[T]()` (\n  #22043)\n- crypto: add a crypto.pbkdf2 module (#22047)\n- hash: add more methods to the hash.Hash interface, to match the ones in Go (#22001)\n- arrays: simplify arrays.sum and arrays.reduce (#22076)\n- x.json2: support @[skip] as well (#22077)\n- builtin,thirdparty: fix compilation of libgc with `-cc msvc -gc boehm` (thanks to @Ekopalypse)\n- stbi: change Image.data from voidptr to &u8, to reduce casts (#21977)\n- time: update parse_format comment description in parse.c.v (#22104)\n- vlib: add an `arrays.parallel` module, containing `parallel.run/3` and `parallel.amap/3`\n  implementations (#22090)\n- builtin: support `-d builtin_print_use_fprintf`, make the C fn declarations stricter (#22137)\n- builtin: fix map.clear() not resetting map's metas and keys blocks (fix #22139) (#22140)\n- builtin: fix incomplete m.clear(), allowing the map to have a duplicated entry for its first key (\n  fix #22143) (#22144)\n- builtin: fix m.clear() having different observable behavior to `m = {}`, after multiple iterations\n  of setting keys and clearing (fix #22145) (#22146)\n- builtin: fix bug in .clear() caused by sizeof(u32) being 4, not 2 (fix #22148)\n- flag: add support for parsing `flag.FlagParser` style flags in `to_struct[T]` (#22152)\n- flag: fix parse_bool_value() (#22160)\n- flag: correct bool logic, add test (#22162)\n- flag: fix parsing `flag.FlagParser` style short flags in `to_struct[T]` (#22172)\n- gg: change the type of PenConfig.thickness to f32\n- builtin: remove remaining references to v_calloc in function comments (#22179)\n- builtin: remove string interpolation from panic/1, to be able to use tools like cbmc in more\n  cases (#22182)\n- flag: add a relaxed parsing mode, that turn flag match errors into `no_match` entries instead (\n  #22191)\n- encoding.binary: add `u16`/`u32`/`u64` -> `[]u8` conversion functions  (#22193)\n- crypto.sha1, crypto.sha256, crypto.sha3, crypto.sha512: improve performance for non prod builds,\n  by tagging the block_generic functions with `@[direct_array_access]`\n- builtin: fix string.trim() (fix #13021) (#22205)\n- crypto.bcrypt: reduce runtime cost for running bcrypt_test.v, by reducing the iteration count\n- crypto.scrypt: add a new `scrypt` module to vlib/crypto (#22216)\n- sync.stdatomic: add OpenSUSE paths for libatomic\n- crypto.scrypt: add missing comment of source for test vector (#22222)\n- json: allow passing an anon struct as a decode type (#22228)\n- flag: fix parse_bool_value() with different order short args (fix #22176) (#22242)\n- builtin: drop C in int.v (#22245)\n- strconv: fix format_fl()/format_es() (fix #13210) (#22244)\n- json: fix decoding of structs with embeds (#22264)\n- crypto.rand: add support for convenient generation of a random big integer in the interval\n  `[0, n)` (#22266)\n- json: fix json encode/decode with embed support (#22277)\n- io: add a BufferedWriter and supporting methods (#22265)\n- vlib: add a go like `x.benchmark` module, that estimates automatically how many iterations are\n  needed, to get a statistically significant result (#22215)\n- math: document q_rsqrt\n- io: make buffered_writer_test.v more robust\n- builtin: enable GC lib on rv64 build (#22319)\n- json: support null sum types in decode()\n- crypto: ecdsa module (on top of openssl)\n- bench: crypto/ecdsa.v\n- math.big: fix `a + b` and `a - b`, when the signs are different, add more test cases (#22330)\n\n#### Web\n\n- Check for using comptime $veb.html()/$vweb.html(), without importing veb or vweb (#21957)\n- net: add net.Dialer and net.Connection interfaces, abstracting the different types of connections,\n  already supported by the V network stack (#21657)\n- net.mbedtls: support Server Name Indication (SNI) (#22012)\n- veb: extract constants into consts.v (#22132)\n- vweb: mark vweb as deprecated in its README, recommending using veb instead (#22131)\n- veb: fix `vweb_livereload` reference to `veb_livereload` (#22171)\n- veb: fix a few minor errors in the README.md (#22177)\n- net.mbedtls: store the client ip (for ipv4), shutdown on handshake failure, in .accept() (#22184)\n- veb: implicit context\n- veb: make implicit context work with custom user types\n- net.websocket: use retrying on EINTR in Client.listen() (#22279)\n- net: allow ipv6 address with brackets (fix #22313) (#22316)\n\n#### Database drivers\n\n- db.sqlite: add instructions for installing SQLite's amalgamation or development package, if it is\n  missing\n\n#### C backend\n\n- Fix struct ref field with no ref structinit (#21932)\n- Define a flexible vint_t type (32 bit int on 32 bit systems, 64 bit otherwise)\n- Fix generic sumtype with repeated concrete type (#21948)\n- Fix array.map with closure var fn (#22002)\n- Fix generation of closures from methods on aliases (#22004)\n- Reduce indentation level for generated defer statements\n- Fix selector with interface var (#22006)\n- Fix free method generation for option struct (#22060)\n- Fix fixed array with default init (#22059)\n- Fix for loop with array fixed returned from fn (#22069)\n- Fix free method for option fields (#22070)\n- Fix auto free method for option map (fix #22081) (#22094)\n- Return early from autofree related functions, when -autofree is not used\n- Fix shared object method call (fix #22121) (#22125)\n- Fix array fixed initialization from map indexing (fix #22133) (#22149)\n- Fix generic options with reserved ident (#22164)\n- Fix struct field with default optional value (fix #11119) (#22167)\n- Fix array of fns index call with embeded array index (fix #17381) (#22198)\n- Fix match with mut cond variable (#22207)\n- Fix code generated for indexexpr with complex assigning (#22203)\n- Fix interface type generation for generic struct (fix #22186) (#22189)\n- Fix wrong type of vint_t and const riscv64 (#22251)\n- Fix code for C ident when ptr is expected (#22259)\n- Fix C name mangling with inherited closure vars (fix #22262) (#22263)\n- Fix codegen for alias to charptr passed as ptr (fix #9679) (#22271)\n- Fix codegen for option fntype used in a match (fix #22278) (#22280)\n- Fix option cast from fntype (fix #22283, #22284) (#22285)\n- Fix codegen for method call on rangeexpr (fix #12610) (#22291)\n- Fix operation overload for type aliases of fixed arrays (fix #22297) (#22304)\n- Fix codegen for assign from unsafeexpr resulting fixed array (fix #22301) (#22309)\n- Fix variadic arg var passed to another call which expects variadic (fix #22315) (#22317)\n- Fix aliases of array insert(...)/prepend(...) (fix #22323) (#22324)\n- Fix codegen for interface method call which returns a fixed array (fix #22326) (#22331)\n- Add `asm` to c_reserved, fixes compilation of `struct Abc { @asm int }` (#22340)\n- Fix interface method call after smartcast (fix #17056) (#22335)\n- Fix codegen for address of range (fix #18528) (#22336)\n\n#### vfmt\n\n- Allow align threshold to be parametrized in calls to add_new_info (#21942)\n- Fix and simplify align of struct fields (#21995)\n- Fix alignment of enumeration types (#21999)\n- Fix enum fields with one empty line (#22007)\n- Fix fmt of enum fields with empty line (#22015)\n- Fix alignment of struct init fields (#22025)\n- Keep empty newlines in between interface fields/methods (#22040)\n- Fix interface fields or methods with empty newlines (#22046)\n- Fix enum/struct_decl/struct_init fields with empty newlines (#22051)\n- Fix interface fields/methods alignment (#22055)\n- Remove the prefixed module name of const names, that are in the same module (related #22183) (\n  #22185)\n- Fix import selective with interface implements (fix formatting part of #22200) (#22209)\n- Add a test for fn with c binding type args (#22212)\n- Fix formating a file in an oscillating manner (fix #22223, fix #22026) (#22232)\n\n#### Tools\n\n- Implement a `-repeats/-R N` option to `v repeat`, to eliminate another need for platform dependent\n  scripting\n- ci: add hub_docker_ci.yml, for building docker images (triggered manually for now) (#22302)\n- ci: use `docker compose` instead of `docker-compose` (\n  see https://github.com/orgs/community/discussions/116610) (#21992)\n- vrepl: suppress the welcome message, if VQUIET is set (#21941)\n- Make `v where` ignore .git/ folders (they contain binary files); let `-dir .` work recursively, so\n  that `-dir vlib` works\n- Sort the match results in the vwhere test, to make it less flaky (#22033)\n- Add an amalgamate tool and description of usage (#22034)\n- Add a few missing v command entries and their flags in `v complete` (#22041)\n- Colorise the output of cmd/tools/show_ancient_deprecations.v, reduce false positives (#22048)\n- docs: clarify the .precision specification section for string interpolation of floats (#22061)\n- docs: add a copy code function (top/right copy icon) on doc examples (#22114)\n- Allow passing parameters to fuzz_v_parser_with_radamsa.sh, so that it could be run in several\n  processes from the same folder\n- Use separate .autofuzz.log files too for the separate invocations of fuzz_v_parser_with_radamsa.sh\n- Extract .github/workflows/run_sanitizers.sh to ease local testing with different options\n- parser,ast: protect against more overflows/panics, by forcing early returns on deeply nested\n  expressions and scopes (#22098)\n- Improve the output of `v repeat command`, by coloring the `faster/slower` label\n- Add diagnostic in `v repeat` for invalid combinations of -r, -i and -a flags\n- Fix `v doc` truncating code blocks, that lack a specific language (fix #22017)\n- v.util: add get_build_time/0, supporting https://reproducible-builds.org/docs/source-date-epoch/\n- Fix `v doc` not converting `<s>` in plain code blocks into encoded html entities in its .html\n  output\n- ci: run `npx prettier --write **.yml`; ensure it is run on all .yml files, not just the ones in\n  the .github/workflows/ folder\n- docs: add implements keyword for explicit interface implementations (#22214)\n- Make fast_job.v more robust (setup a custom PATH) and informative on fast.v failures (compile it\n  with -g)\n- Make fast.v and fast_job.v more self sufficient\n- ci: add cache and trigger for pushes, in the Hub docker action (#22314)\n\n#### Operating System support\n\n- docs: streamline the installation instructions and notes for Windows and Ubuntu\n- v.builder: fix errors in cstrict mode on OpenBSD with clang (#22154)\n- thirdparty: fix compilation of programs using miniz.h on macos\n- crypto.rand: fix compilation on macos with `-cc tcc -no-retry-compilation -gc none`\n- thirdparty: fix compilation of thirdparty/mbedtls with tcc on macos m1\n- v.pkgconfig: fix parser, when `includedir=` lines, had trailing spaces (fix `-d use_openssl` for\n  openssl 3.3.2 installed through brew on macos)\n- builtin: fix compilation with tcc on OpenBSD using libgc (#22234)\n- docs: add FreeBSD in cross compilation section (#22249)\n- v.builder: enable LTO for clang on OpenBSD (#22247)\n- thirdparty: fix compilation of programs using miniz.h on OpenBSD (#22254)\n- net: fix compilation on windows (use casts to int for net.error_eintr etc)\n- net: use explicit int casts for net.error_eintr etc in the unix implementation too for consistency\n  with the windows one\n\n#### Examples\n\n- Remove drag_n_drop.v from the list of examples, that are checked for visual differences with\n  vgret, since it now uses the default gg font\n- docs: add more C interop notes and examples (#21965)\n- cleanup obsolete unsafe{} usages in examples/sokol/sounds\n- cleanup & fix the sound produced by melody.v\n- add a simplified bytebeat player to show how to use sokol.audio, and that does not depend on gg\n- make `rotating_textured_quad.v` compile and run on Android (#21987)\n- veb: change example description, to avoid repetitive wording (ease debugging of issue#22017)\n- eval: fix `./v interpret examples/hanoi.v`\n- add examples/ttf_font/draw_static_text.v, to make it easier to test x.ttf with different fonts,\n  and texts\n- make draw_static_text.v show the font name too, for easier comparisons\n- prevent cliping of long font names in draw_static_text.v\n- docs: add an example on how to use Options/Results, when returning multiple values from a\n  function (#22099)\n- add examples/gg/draw_unicode_text_with_gg.v, for easy comparison of how different fonts and\n  unicode texts will look, when rendered by gg\n- add examples/veb/websocket, to show how to use http connection upgrade to a websocket, from a\n  `veb` route (#22128)\n- migrate vweb examples to veb\n- fix type in veb_example.v\n- add `gc_is_enabled()` check to `2048` to prevent crash in Android emulator (#22274)\n- make `gg/rectangles.v` Android friendly (#22275)\n- make `gg/stars.v` run on android (#22276)\n- examples,os: add an os.asset module, use it to simplify code in examples/, by removing\n  `$if android {` checks (#22281)\n- add a consistent background to flappylearning, shown when the height of the view is very high (on\n  Android)\n\n## V 0.4.7\n\n*26 Jul 2024*\n\n#### Improvements in the language\n\n- Add support for `-d ident=value` and retrieval in code via `$d('ident', <default value>)`\n- `-warn-about-allocs` for debugging allocations when using manual memory management\n- `@[freed]` attribute for assign statements (for the above mode)\n- Implement `&&=` and `||=` operators  (#21678)\n- Improve C var args interop, allow for `fn f(some int, ...) {` (#21812)\n- A new flag `-n` for skipping notes (similar to `-w` for skipping warnings)\n- Cross compilation to FreeBSD\n\n#### Breaking changes\n\n**none**\n\n#### Checker improvements/fixes\n\n- Fix unknown fixed array size for `const n = int(sizeof(u64)); _ = [n]int{}` (fix #21544) (#21548)\n- Fix checking of default field initialisations, that are part of unions of structs tagged with\n  `@[noinit]` (#21587)\n- Disallow sum type with `Result` variants (#21620)\n- Add error for `field map` (i.e. a plain untyped map), used inside a struct (#21625)\n- Fix missing concrete type checking on a generic type specifier (#21614)\n- Fix missing option and result wrong type return type definition (#21626)\n- Turn warnings for private fields into errors (#21296)\n- Support nested labeled for statements (#21658)\n- Fix the return type of overloaded operators, defined on aliases of primitive types (fix #21654) (\n  #21663)\n- Fix match expr with auto promote number (#21696)\n- Fix sorting compare fn with mut reference parameter (fix #21662) (#21706)\n- Fix `$if x {` condition, using `const x = $d('ident', false)` (fix #21709) (#21713)\n- Fix generic variable resolution on generic func return assignment (#21712)\n- Fix result call or_block with multi-statements (fix #21504) (#21717)\n- Allow `\\uxxxxx` in raw strings (#21724)\n- Limit recursion in Checker.ensure_type_exists/2 to 40 levels (it is usually 4 or less) (#21734)\n- Add error for `field [$d('x', 2)]int = [1, 2]!` (#21741)\n- Fix nested if expr method call (#21773)\n- Fix generic inference in if expressions used in assignments (#21781)\n- Disallow nil in non-nil arrays and vice versa  (#21786)\n- Check expr evaluated but not used (fix #21436) (#21816)\n- Fix wrong receiver generic resolution with embed types (#21833)\n- Check mismatch of fn call mut argument (fix #21857) (#21873)\n- Fix global fixed array key resolution when it is a constant ident (#21900)\n- Improve checks for embed in anon struct  (#21877)\n- Fix builtin fn var resolving (#21899)\n- Fix spawn when calling undefined function (#21906)\n- Require enum values to be declared, before using them in other enum values (#21913)\n- Check enum field value duplicate (#21920)\n- Allow embed of type alias anon struct  (#21928)\n\n#### Parser improvements\n\n- Register selective import aliases as used (#21613)\n- Allow multiple flag values in enum.from() for flag enums (fix #21569) (#21615)\n- Disallow duplicate operator overload  (#21675)\n- Support `[$d('s', 4)]int{}`, move resolving to method on `ComptimeCall` (#21701)\n- Support `$d()` in fixed size array `struct` fields (#21731)\n- Suggest using type alias when defining methods on non-local types (#21803)\n- Sugggest map initialization with the correct syntax  (#21817)\n- Fix parameter collision for generated `@[flag]` enum methods, with modules named `flag` (#21844)\n- Fix high order generic fn resolution (#21871)\n- Fix recognition of `mod.Enum.val` inside fn args (#21908)\n\n#### Compiler internals\n\n- tools,cgen,pref: add `-coverage` support + `vcover`  tool (#21154)\n- v.utils: allow to set the names of the compared items, when diffing strings (#21650)\n- v.pref: fix regression of command flags not working, when there is a subfolder, named after the\n  command, in the current working folder (#21647)\n- transformer: handle `enum_variant = some_const + 10` (fix #21777) (#21779)\n- v.builder: print the suggestion for using `v xyz` instead of `v xyz.v` just once (#21801)\n- v.builder: improve the C compilation output on cgen errors (#21885)\n- v.scanner: use table lookups for very frequently done character checks (#21931)\n- markused: mark explicitly all used array and map methods with `-skip-unused` (fix #21907) (#21914)\n\n#### Standard library\n\n- builtin,v: reduce overhead and memory usage for very frequently called methods (#21540)\n- builtin: reduce allocations in s.index_kmp/1 and s.replace/2 (#21561)\n- os: remove mut declarions for unchanged vars in `os_nix.c.v` (#21564)\n- os: make minior improvement to C function semantics and related code (#21565)\n- builtin: simplify splint_nth methods (#21563)\n- toml: fix `@[toml: ]`, support `@[skip]` (#21571)\n- builtin:  update `last_index_u8`, deprecate `index_u8_last` string methods, make consistent with\n  `last_index` (#21604)\n- builtin: implement a JS version of `string.split_any` (#21612)\n- crypto: add a `crypto.sha3` hash and extended output functions (#21664)\n- crypto.sha3: remove unnecessary return at the end of the write function (#21669)\n- builtin: fix string.find_between(), when not found end string return '' (#21670)\n- builtin: add string.camel_to_snake/0 and string.snake_to_camel/0 methods (#21679)\n- cgen,x.json2: fix generic map decoding (#21704)\n- encoding.base32: fix warning of implicit clone of array, by using an explicit unsafe block (\n  #21728)\n- vlib: simplify byte character conditions by using methods like is_capital, is_lower, is_letter\n  etc (#21725)\n- gg: add Context.draw_cubic_bezier_recursive/2 and Context.draw_cubic_bezier_recursive_scalar/9 (\n  #21749)\n- ci: fix deprecations_consts.out (the warning for math.max_i8 is now an error; it was deprecated\n  since 2023-12-31)\n- math: add divide_truncated/2, divide_euclid/2, divide_floored/2 and modulo_truncated/2,\n  modulo_euclid/2, modulo_floored/2 (#21759)\n- math: avoid unused calculations for math.modulo_floored/2 and math.modulo_euclid/2\n- crypto.blowfish: apply `@[direct_array_access]` to very commonly used functions (#21771)\n- encoding.binary: little_endian_f32_at\n- arrays: add arrays.chunk_while/2, where\n  `arrays.chunk_while([0,9,2,2,3,2],fn(x int,y int)bool{return x<=y})==[[0,9],[2,2,3],[2]]`\n- sokol: reduce _SGL_DEFAULT_MAX_VERTICES back to 1<<17 (1<<22 in 811ac12, leads to ~140MB of memory\n  usage for gg/minimal.v, instead of just ~38MB)\n- vrepl: fix os.input() (#21811)\n- Improve consistency and behavior regarding explicit mutability (#21566)\n- builtin: add `pub fn arguments() []string {`; make `os.args` use it, remove edge case in cgen (\n  #21852)\n- builtin: support `-d use_bundled_libgc` to make it easier to debug/upgrade reliably libgc cloned\n  from ivmai/bdwgc (#21869)\n- time: increase http_header_string performance (#21894)\n- builtin: add s.trim_space_left/0 and s.trim_space_right/0 methods (#21903)\n- strconv,math.bits: eliminate bounds checking in commonly used routines\n- arrays: fix arrays.fold, when the `init` value in the call, is an array (#21921)\n- string: fix leak in replace_once\n\n#### Web\n\n- net.http: change default http.Server listening address to :9009, to avoid conflicts with tools,\n  that start their own http servers on 8080 like bytehound (#21570)\n- net.urllib: update parse host to allow for better error handling (#21602)\n- net.html: quick workaround for a cgen problem for `const x = int(0x80000000)`\n- net.http:  implement http.download_file_with_progress/2, saving each chunk, as it is received,\n  without growing the memory usage (#21633)\n- veb: update import name in docs (#21668)\n- Add `m3u8` MIME type `application/vnd.apple.mpegurl` for multimedia playlists (#21688)\n- veb.auth: use constant time comparison in compare_password_with_hash (#21693)\n- net.http: correct `Response.status()` method comment, to indicate returning of a `Status` enum\n  field, instead of struct (#21735)\n- net: fix TcpConn.peer_ip/0 to only return the ip address, without the port number (#21831)\n- Add mime type `text/x-vlang`, for `.v` and `.vsh` file extensions (#21851)\n- net.conv: add conv.reverse_bytes_u64/u32/u16 (#21917)\n\n#### ORM\n\n- orm: fix subquery without where expr (#21598)\n- orm: ilike for case insensitive text search\n- orm: update readme with more specifics (#21697)\n\n#### Database drivers\n\n#### Native backend\n\n#### C backend\n\n- Fix printing of floating point values in asserts (#21538)\n- Fix array fixed initialization on struct from call (#21568)\n- Put the `Interface(unsafe{nil})` change for now behind -experimental (#21593)\n- Fix indexexpr with orexpr (fix #21591) (#21592)\n- Fix generic struct init when it is a reference &T (fix #21594) (#21596)\n- Fix generated code for handling fn call with result/option return on match conditional (#21608)\n- Fix missing call to a function returning option, when called inside a print (fix #21616) (#21623)\n- Support a `-d no_bool` option, for cgen compatibility with the C23 language standard (since `bool`\n  is a builtin type and a keyword in it) (#21637)\n- Fix or expr with non option fn call return (fix #21660) (#21661)\n- Generate pragmas for gcc-14, to make it more relaxed by default. Support `-no-relaxed-gcc14` for\n  turning them off. (#21680)\n- Fix spawn code generated when calling conditional function (fix #19352) (#21681)\n- Fix comptime generic arg resolution (allow several different struct fields in generic functions\n  using comptime) (fix #18110) (#21682)\n- Fix dumping array of reference (#21694)\n- Implement g.trace_last_lines/2 to help debugging cgen problems\n- Support inc cond for c style for loop with alias types  (#21708)\n- Fix fn call with mut reference args (fix #21265) (#21719)\n- Fix auto dereference mut variable in if expr (fix #21309) (#21720)\n- Fix smartcasting a reference to a sumtype value (#21730)\n- Fix assert checking fn option ret with `none` (#21726)\n- Fix generics map with the reference argument (#21737)\n- Fix shortcircuiting of infix and/or expressions (#21740)\n- Simplify in infix_expr_and_or_op() (#21745)\n- Fix reference variable str() method call (#21753)\n- Fix scope command when `$dbg` breakpoint is on or-expr (fix #21772) (#21747)\n- Fix array fixed empty struct code generated on clang (fix #21761) (#21764)\n- Allow alias to array fixed to be initialized like `[n]int{}` (#21785)\n- Fix comptime call argument auto conversion for indexexpr (fix #15232) (#21796)\n- Fix const name without main prefix in `-translated` mode (#21789)\n- Fix closure variable with optional reference params (fix #21827) (#21829)\n- Fix auto str for fn struct member (#21825)\n- Fix option string struct member init with autofree (#21859)\n- Fix fn mut argument of sumtype reference (#21874)\n- Fix generic type init syntax for primitive types  (#21872)\n- Fix missing `&` in string representation of `map[X]&Y` (#21890)\n- Fix optional closure direct call (#21892)\n- Fix wrong missing unsafe block checking when calling generic functions with @[unsafe] attr (\n  #21898)\n- Fix typeof(var.typ) with comptime $for variables (#21901)\n- Fix enum with const value (#21919)\n- Fix generic option/result reference return (#21922)\n\n#### vfmt\n\n- Allow single line `defer {}`, just like `or {}`\n- Don't break `it` variable name in match expression function calls (#21600)\n- Exit with error code if encountering diffs with `-diff` flag (#21603)\n- Add fn_with_mut_ref_params_keep.vv (#21711)\n- Implement wrapping function's super long arguments  (fix #15545, fix #21643) (#21782)\n- Keep manual newlines after fn parameters in fn declarations, do not auto wrap (#21795)\n\n#### Tools\n\n- Fix spurious ending quote in the output of show_manual_release_cmd.vsh\n- Dockerfile.alpine: update to alpine:3.20, add more tools like gdb, libunwind, gc, to ease\n  producing and debugging static executable in more situations (#21583)\n- Add `v download URL` for downloading single files, to avoid curl/wget etc, which are not available\n  uniformly. (#21597)\n- ci: use shebang with better portability in shell scripts, format shell scripts (#21605)\n- Don't write vpm logfiles in CI runs (#21649)\n- ci: make vmodules_overrides_test.v failures more informative\n- Fix measurements for `./v repeat \"./vold -o x project/\" \"./vnew -o x project/\"`\n- Make the summary output of `v repeat` more informative\n- Disallow self referencing function alias types like `type FnType = fn(string) FnType` and\n  `type FnType = fn (FnType) string` (#21733)\n- vrepl: fix method call (fix #21788) (#21792)\n- ci: restore v_apps_and_modules_compile_ci.yml (#21791)\n- vrepl: fix output of the fn call (related #21792) (#21800)\n- vrepl: fix variable name starts with print (#21806)\n- v.pref: make pref_test.v be less sensitive on the specific C compiler used as a backend (#21813)\n- vrepl: fix arbitrary script execute (#21818)\n- ci: disable c2v_ci.yml temporarily, until it is fixed\n- vrepl: lots of fixes in REPL\n- Add a TOTAL line, to the output of -show-timings, to minimise the need for external tools on\n  windows (#21847)\n\n#### Operating System support\n\n- veb: support sendfile() syscall on FreeBSD (#21541)\n- os: use 1 instead of C.SW_SHOWNORMAL to workaround a cross compilation issue from linux to windows\n- v.builder: minimise the amount of linked libs for cross compilation to FreeBSD\n- v.builder: support downloading the FreeBSD cross compilation files on first use\n- Add a test for crosscompiling hw, on linux and macos, to FreeBSD (#21553)\n- vlib: make `./v -Wimpure-v -W test vlib/` pass on Linux (#21554)\n- os: fix debugger_present() for non Windows OSes (#21573)\n- ci: extend coverage, move app test from macos_ci to v_apps_and_modules_ci (#21584)\n- gc: fix tcc on macos\n- os.font: return the \"segoeui.ttf\" font, if its file exists on Windows (#21655)\n- readline: fix s := read_line('Message\\nName:') on unix/linux (#21930)\n\n## V 0.4.6\n\n*20 May 2024*\n\n#### Improvements in the language\n\n- Experimental `x.vweb` is now `veb`, the official and recommended way to build web apps in V. Built\n  on top of pico.v.\n- autofree: -print_autofree_vars command line flag for printing variables autofree couldn't free\n- Add `@VMODHASH` comptime variable to store the commit sha of a V module (#21091)\n- Fix sumtype support for option variant types (#21101)\n- Utilize new diff functions in errors (expected/found) (#21431)\n- Add @[_linker_section] for global variables\n\n#### Breaking changes\n\n- checker: disallow initializing private struct fields outside structs module (#21183)\n\n#### Checker improvements/fixes\n\n- Ambiguous expression notice for `& << >>`, similar to `&& ||`\n- Disallow using aliases of ?Type as !Type (#21128)\n- Fix option checker arg validation for ptr passing on non expected ptr (#21087)\n- Optimize option and result type check, add more typinfo to error details (#21105)\n- Move error handling for `any` type to the checker to resolve parsing issues (#21146)\n- Move error handling for user defined type duplicates to the checker to resolve parsing issues (\n  #21147)\n- Detect redundant ref when assigning call expr with ref return (#21141)\n- Fix multi return using nil and voidptrfix (fix #17343) (#21144)\n- Fix C struct embedded init fields checking (#21137)\n- Remove resolved vfmt workaround and TODO (#21175)\n- Move more match validation from the parser into the checker, add error for match without\n  branches (#21181)\n- Improve the error message for an unknown type (#21207)\n- Allow passing `none` to `fn f(arg ?&Type) {` (fix #21213) (#21231)\n- Fix -parallel-cc regression (part 1, workaround .filter(fn[c]) used in checker/orm.v) (#21238)\n- Detect and error on unreachable code in loops, after `continue` and `break` statements (#21294)\n- Disallow `Result` callbacks functions like `map/filter/all/any` (#21055)\n- Fix missing check for or expr on string interpolation (#17566)\n- Allow pass array as mut param to spawn fn (#21283)\n- Turn array assign warning into error (#21341)\n- Ignore last semicolon on or-expr (#21361)\n- Disallow structs with `@[params]` attribute as mutable function parameters (#21206)\n- Set auto Return pos correctly; cgen: autofree fix for optional returns\n- Disallow invalid ptr operations  (#21515)\n- Fix wrong checking for heap struct (#21511)\n- Allow alias enum flagged to have bit operations  (#21532)\n- Simplify, utilize pref.vroot (#21096)\n- Fix option interface member checking when `none` is passed (#21509)\n\n#### Parser improvements\n\n- Fix option as possible match case for sumtype (#21079)\n- orm: disallow invalid infix for where clause in `delete` and `update`  (#21113)\n- Fix case of falsely registering imports as used, remove unused imports (#21156)\n- Remove redundant comments_mode field (#21198)\n- Update file path fields; use more expressive name for file path, remove obsolete `file_name_dir`\n  field (#21202)\n- Add missing docstrings for vlib/v/ast/comptime_const_values.v functions (#21219)\n- Allow struct init on `for in Iterator{} {` (fix #21179) (#21282)\n- Fix `for x in Iterator{} {`, when there are no field initialisations (#21333)\n- Add check for result type on chan init (#21363)\n- Fix comptime panic for `$tmpl(\"x.html\")`, when the template file contained % at the end (#21402)\n- Parse string and array typ idx of `ScopeVar` and `Ident` (#21523)\n\n#### Compiler internals\n\n- v.util: use tmp instead of cache dir for temporary diff files (#21075)\n- v.util: fix module lookup if module import parts end with the word `modules` (#21083)\n- v.util: update `githash` to be able to get the githash of every passed project (#21178)\n- v.util: improve detection for opendiff when automatically searching difftools (#21241)\n- v.util: improve color_compare_files (#21247)\n- v.util: improve find_diff_cmd: don't add spaces to result without env opts (#21242)\n- v.util: fix diff coloring, add test (#21260)\n- v.util: polish off diff utils after recent updates and fixes, add doc comments to pub fns (#21275)\n- v.builder: suggest using `v wipe-cache`, when the object files are not recognized\n- pref: be more conservative when generating code using `-cross`, allow for `$if cross ? {`\n- builder: use cc enum in CcompilerOptions, fix cc detection, enable cc guessing without prod flag (\n  #21370)\n- pref: fix version flag handling (#21377)\n- pref: make minor performance related changes / simplify (#21379)\n- builder: simplify generic cc detection (#21380)\n- pref: extract architecture related code into `arch.c.v`; rename `pref.c.v` to `pref.v` (#21387)\n- pref: update `os_from_string`, add missing `qnx`, remove deprecated wasm options that used `-`\n  instead of `_` (#21390)\n- v.util: rewrite diff module, deprecate old functions (#21403)\n- v.util: fix color when auto tool is `diff` (#21435)\n- v.util: make diff_test.v more robust to the color settings for the chosen local diff tool\n- v.util: fix performance with `v test-cleancode`, when a slower diff tool is installed (#21447)\n- v.util: remove fast path in `diff.compare_text` (#21458)\n- v.pref: error for `v file.v --unknown-option` (#21391)\n\n#### Standard library\n\n- builtin,dlmalloc: fixes for `v vlib/v/gen/c/coutput_test.v` for gcc14.1, which is stricter\n- Min window width and height\n- builtin: str.last_index(); pref: hide-auto-str;\n- toml: update the alexcrichton and BurntSushi repos to their successors toml-rs, and toml-test,\n  record new exceptions (#21152)\n- breaking,vlib: update handling of imports whose symbols are not directly used in imported file,\n  remove `pub const is_used = 1` workarounds (#21160)\n- json: allow `i32` decoding and encoding (#21162)\n- json2: add ability to decode arrays (#21163)\n- json2,checker,toml: allow field.typ compile-time checking with MatchExpr and add array of option\n  checking (#21171)\n- gg: draw_text with custom fonts\n- x.json2: add a way to decode an array (#21186)\n- os: clarify some doc comments (#21209)\n- os: fix double free in os.get_raw_line() (used by os.input), with `-autofree` (#21204)\n- time: extract Duration related code into duration.v (#21229)\n- builtin: implement an `at_exit(cb)` wrapper for C.atexit (part 1) (#21254)\n- os: format readme, fix markdown inside html (#21286)\n- time: update unix time acces, fix issues related to deviating unix times (#21293)\n- vlib: refactor empty string checks to use `s == ''` or `s != ''`, instead of `s.len == 0` (#21300)\n- cli: update `command_test.v` (#21307)\n- cli: extend control over defaults (#21308)\n- thirdparty/sokol: bump _SGL_DEFAULT_MAX_VERTICES and _SGL_DEFAULT_MAX_COMMANDS again; mark them\n  with `__v_ start` and `__v_ end`\n- sync: add Gentoo paths for libatomic\n- sync.stdatomic: add flag lines for gcc 14 too\n- gg: make `PenConfig` fields public (#21353)\n- builtin: fix undefined read s[0], from ''.is_lower() and ''.is_upper() in c7af2c2\n- builtin: fix empty string lower / upper assert (#21358)\n- cli: simplify flag parsing (#21392)\n- os,runtime: workaround for v.c generation instability\n- datatypes: fix for set `-` operator, union and intersection, now they no longer change the\n  receiver (fix #21315) (#21362)\n- sync.stdatomic: add paths for compilation with musl on Gentoo (#21400)\n- os: fix os.execute stderr redirection (fix #20986) (#21404)\n- time: fix the string representation of a negative Duration (#21407)\n- cli: make program outputs using the cli module testable in `cli/testdata` (#21456)\n- math.unsigned: permit _ separators in Uint128 decimal strings passed to uint128_from_dec_str (\n  #21461)\n- cli: fix default flags when their command equivalents are disabled (#21469)\n- toml: simplify `decode_quoted_escapes` (#21472)\n- os: fix join-path (#21425)\n- builtin: simplify MessageError.msg() (#21524)\n- all: replace usages of C.atexit(cb) with `at_exit(cb) or {}` (part 2) (#21263)\n- math.unsigned: fix some Uint256 bugs and add tests (#21528)\n\n#### Web\n\n- Update `mbedtls` to latest compatible version v3.3.0 (#21118)\n- veb.auth: a minor find_token fix\n- Improve descriptions (#21155)\n- ci: change listen ports in vweb_should_listen_on_both_ipv4_and_ipv6_by_default_test.v for both\n  vweb and x.vweb, to reduce probability of network errors\n- ci: mark both vweb and x.vweb versions of\n  vweb_should_listen_on_both_ipv4_and_ipv6_by_default_test.v as flaky\n- breaking,net.ftp: allow to choose a different port than port 21 (change FTP.connect to accept\n  `host:port`, not just a `host` address) (#21185)\n- x.vweb: accept query params as method arguments (#21201)\n- net.http.file: support index_file (`index.html` by default), and auto_index (true by default)\n  parameters to file.serve()\n- veb: copy x.vweb to veb, and make it work with comptime\n- ci: fix the ubuntu-docker-musl job by skipping veb_app_test.v\n- pref: support a shortcut: `v -http` for `v -e \"import net.http.file; file.serve()\"` .\n- net: add a .port()! method for net.Addr (#21412)\n- net: improve error message in .port()\n- picoev: handle `EAGAIN` or `EWOULDBLOCK` quietly (#21480)\n- net.unix: remove debug/trace eprintln (#21517)\n\n#### ORM\n\n- Add error for unchecked option multi return types, fix undefined behavior (#21106)\n\n#### Database drivers\n\n- db.mysql: fix invalid memory access in exec_one for returned rows with NULL fields (#21317)\n\n#### C backend\n\n- Enable autofree for option (#21051)\n- Force C struct types which does not implement str() to be passed as ptr (#21054)\n- Improve diagnostic information for ORM queries with invalid types\n- Allow static call on generic type (#21071)\n- Fix code generation for a struct field, having a type of fixed array of options `field [5]?Type` (\n  #21082)\n- Add the `_M_ARM64` macro to endianness check (#21109)\n- Fix return code when returning interface result type (fix #21115) (#21130)\n- Fix const initialized with array (#21131)\n- Fix infix array heap comparison (#21145)\n- Fix C struct sumtype support (#21129)\n- Add `autofree` comptime check (#21197)\n- Fix comptime `$if !autofree {` (#21218)\n- Allow `for mut v in [12, 13, 14] { v+= 2 }`  (#21237)\n- Allow op overload for type with generic parent  (#21262)\n- Optimize .map(), .any(), .filter() and .all() when using closure (#21256)\n- Fix `none` passed to a generic option cast expression (fix #21215) (#21276)\n- Fix `-fsanitize=undefined` used with `[]int{}.sort()` (#21331)\n- Fix `myarr [1]C.mytype` fixed array fields, for `pub type C.mytype = voidptr` (#21266)\n- Fix comptime ref argument passing (#21335)\n- Use the real C line number instead of `#line 1000000 ...` in the C footer with `-g` (#21388)\n- Fine tune the line count reset for the C footer (fix off by 1 error in 00dd0bf)\n- Fix array.delete_last call generation (#21439)\n- Fix option ptr unwrapping (#21415)\n- Fix C struct option alias printing (#21496)\n- Handle auto deref var for index when the array element is an interface or a sumtype (#21491)\n- Fix C struct init when it has default expr (#21510)\n- Fix sumtype field naming (when they are the same as a C keyword) (#21527)\n\n#### vfmt\n\n- Update determining of struct field comments (#21066)\n- Inform about invalid interop function bodies instead of removing them (#21070)\n- Parse methods on JS interfaces, write JS method bodies (#21088)\n- Improve module detection when formatting imports (#21134)\n- Don't change paths when formatting imports (#21148)\n- Use fixed size array for max_len const (#21140)\n- Simplify const name formatting (#21143)\n- Improve import processing, add test (#21172)\n- Fix duplicates remove import comments (#21177)\n- Extend import import alias reference map for submodules (#21200)\n\n#### Tools\n\n- doc: fix vup/vself replacement scripts (#21092)\n- Prevent module updates during `v build-tools`, when VTEST_SANDBOXED_PACKAGING is set (#21094)\n- ci: update the reference to the v-analyzer repo\n- ci: retry all setup commands that need network access, till they succeed (so the CI jobs have less\n  false positives) (#21103)\n- changelog: escape `@NAME` entries, to avoid mentioning unrelated github accounts\n- Add `v retry apt update`, intended to replace the retry.sh script, for more robust CI jobs (\n  #21104)\n- vpm: show the final path where a module is installed, improve color contrast for white on black\n  terminal sessions\n- vet: print help when passing no files or `--help`/`-help` flag after vet command (#21108)\n- Fix `v build-tools` (it skipped all tools in subfolders of cmd/tools/ after 6a4f293) (#21120)\n- .gitignore: ignore generated .NET files in bench/vectors (#21136)\n- vet: optimize performance for path detection, when vetting files (#21139)\n- vet: allow to overwrite excluded dirs (#21142)\n- ci: increase wait time for the xvfb check, to reduce the chance of false positives\n- Fix `v run cmd/tools/measure/parser_speed.v file.v`\n- Add `v run cmd/tools/measure/fmt_speed.v file.v`\n- ci: move build step for VPM site, into apps and modules ci, add concurrency config (#21191)\n- tools.vpm: debug-log to `$VMODULES/cache/vpm.log` if not running in debug mode (#21192)\n- vpm: optimize performance by adding filter when cloning (#21216)\n- vdoc: don't add _docs directory when an out path is specified (#21233)\n- ci: prefer dedicated tiggers for platform workflows, so sporadic fails can be retried quicker (\n  #21251)\n- v.util: improve code related to diff tool specified via environment, add check if the diff tool\n  exists (#21240)\n- vpm: check for git version before adding `--also-filter-submodules` flag (#21259)\n- ci: add logging to .github/workflows/retry.sh\n- Revise `vtest-self.v`: remove dead paths, fix json2 essential test path (#21267)\n- Add check for unavailable files in vtest (#21272)\n- ci: reactive app prod builds (#21295)\n- ci: add a m1 runner for testing the prebuilt zips too\n- ci: add workflow_run: event in prebuilt.yml\n- ci: simplify prebuilt.yml, make it usable for manual runs too\n- vpm: fix regression, so `v install sdl && v run ~/.vmodules/sdl/setup.vsh` works again\n- ci: fix outdated_test.v (--unshallow is not needed now)\n- ci: continue testing independent V apps, even if one fails, to get feedback for breaking changes\n  faster (#21302)\n- ci: optimize apps and modules (#21303)\n- ci: test `v ~/.vmodules/sdl/setup.vsh`, to prevent future vpm regressions (#21306)\n- ci: prevent unintended deployment workflow steps (#21313)\n- Add a 2024.html page to https://fast.vlang.io/\n- vdoc: rewrite and extend vdocignore (#21314)\n- ci: fix the commit labels for the vc repo\n- Support `v run cmd/tools/oldv.v --show_VC_commit weekly.2024.03`\n- ci: use latest upstream `discord.v` in apps and modules test (#21322)\n- vdoc: remove obsolete entries from `.vdocignore` (#21320)\n- v: update linguist languages, add .vdocignore (#21321)\n- ci: update deployment workflow (#21323)\n- Allow for selectively running `v test-self vlib/` and `v test-self cmd/` (#21326)\n- Rewrite test-self arg handling (#21327)\n- ci: restore `v install elliotchance.vsql` in v_apps_and_modules_compile_ci.yml\n- ci: use `v retry -- cmd` to replace `.github/workflows/retry.sh cmd`, where possible in\n  `v_apps_and_modules_compile_ci.yml` (#21336)\n- ci: update workflow conditions (#21338)\n- Improve `v symlink -githubci` diagnostic message, when used outside CIs or with sudo (#21340)\n- ci: update detection of workflow cancellation scenarios (#21342)\n- Fix compiling vwhere with `-cc gcc -cstrict` (#21347)\n- ci: remove the separate `-gc boehm` job (since `-gc boehm` is the default now) (#21352)\n- ci: add a separate cmd/tools testing job (#21344)\n- Update fast.v and fast_job.v to update docs.vlang.io and fast.vlang.io on each commit to master.\n- Make fast.v more robust to independent remote changes in vlang/docs\n- Utilize environment specific files for vsymlink  (#21360)\n- ci: update `binary_artifact.yml` (#21364)\n- ci: add docker to tools workflow, update ignore paths (#21368)\n- ci: split up vsl / vtl run, reducing the tool change CI time from ~19min to ~10min (#21372)\n- ci: fix binary_artifact.yml (#21373)\n- Refine `check_os_api_parity.v` (#21371)\n- ci: update native backend ci matrix (#21375)\n- ci: update symlink ci, add matrix (#21376)\n- ci: workaround defer codegen failing with nested if blocks and -cstrict in vdoc_file_test.v\n- ci: update detection of accidentally added gpl licenses (#21384)\n- ci: set cancel-in-progress to false in bootstrapping_ci.yml to avoid false positives\n- ci: do trigger bootstrapping_ci.yml periodically, but just on changes\n- ci: speed up bootstrapping_ci.yml, by using the default tcc when possible\n- ci: update `bootstrapping_ci.yml` trigger paths (#21394)\n- ci: pass a good commit to oldv.v in `bootstrapping_ci.yml` (#21393)\n- Be more verbose when doing `v up` in V folder produced by extracting a .zip release file\n- Exclude thirdparty/tcc from the git clean operation, that vup does in case of a missing .git\n  folder\n- Protect from cleaning during `v up`, only ./v , not any matching folder\n- Use proper ignore/exclude patterns in the git clean, that `v up` does\n- Use more meaningful names in vup.v\n- Be verbose, when a git commands that `v up` executes fails\n- ci: add a v-up-works-ubuntu job, to ensure more robust `v up` runs (#21401)\n- ci: ensure v master is available when trying to check out its commits to build oldv (#21414)\n- Rewrite vet error handling (improve parser performance extend vvet) p1 (#21417)\n- Move dynamic const array check from parser into vet (#21423)\n- v.help: update help for `fmt` (#21430)\n- Move array_init_one_val checks from parser into vet (#21422)\n- Remove `vet_errors` and `vet_notices` from parser (#21424)\n- ci: temporary fix for gitly compilation\n- Remove vetting for spaces after / before parens (#21437)\n- Add `.github/workflows/show_manual_release_cmd.vsh`, to make cross platform testing of the release\n  process easier\n- ci: merge docker_alpine and docker_ubuntu workflows in `docker_ci.yml` (#21446)\n- Move now obsolete vlib vet module to cmd vet (#21445)\n- Use `parse_file`, remove `parse_vet_file` (#21444)\n- ci: update binary artifact workflow, add matrix (#21378)\n- ci: add workflow_dispatch: to gen_vc_ci.yml\n- ci: fix vinix_ci.yml by using `./v symlink -githubci` in vinix_ci.yml\n- ci: port changes from Vinix's check.yml at 8231e569 to vinix_ci.yml\n- tools.vet: move error methods to `vvet/errors.v` (#21449)\n- ci: reduce false negatives for tcp_test.v, retry it 3 times before failing\n- Improve performance of `v test-cleancode` and `v fmt -inprocess -verify .` (#21450)\n- Make `./v symlink` work platform independent in CI (part 1) (#21453)\n- ci: replace .github/workflows/retry.sh usages in the CI with the shorter `v retry --`, move\n  `v test-cleancode` upwards to save time for unformatted PRs (#21452)\n- Capitalize information output of `v up` (#21464)\n- ci: use `v symlink` without `-githubci` for regular symlinking (#21455)\n- ci: add a linter for the .yml workflow files (#21459)\n- ci: update symlink ci, extend tested cases (#21466)\n- tools.vet: update diff comparison in `vet_test.v` (#21457)\n- Call mkdir_all before set_output_path to avoid a vpm panic when ~/.vmodules/cache does not exist (\n  #21463)\n- ci: make issue template title consistent, fix linter error regarding labels (#21460)\n- tools.vet: reduce nesting in `vet_fn_documentation`, skip vetting empty lines (#21465)\n- Print info to use v symlink instead of `v symlink -githubci` (#21471)\n- Move _test.v files for vdoc at the same level (#21473)\n- ci: update the helper script, for getting the most recent sqlite-amalgamation-3380200.zip (#21474)\n- vdoc: fix handling of .vdocignore files in subdirectories (#21514)\n- ci: run build-module-docs, when changes to the source of the `v doc` tool happen too\n- ci: use g++ not g++-11 in misc-tooling (g++-11 can not be found and installed on the CI runner\n  anymore for some reason)\n- ci: update g++ to g++-10 in other_ci.yml, add workflow_dispatch: trigger for easier local future\n  diagnostic\n- vdoc: improve vdocignore file handling by walking all .vdocignore sub-paths in IgnoreRules.get,\n  add test (#21521)\n- ci: run `v fmt -w cmd/tools/vdoc/vdoc_test.v`\n- ci: make sure that unformatted code in just cmd/ is not allowed\n- ci: mark again tcp_test.v as flaky (it had 3 unrelated failures on the CI over the last week)\n- v: vet for empty string conditions (#21529)\n- tools.vet: add notice for empty strings conditions (#21421)\n\n#### Operating System support\n\n- ci: improve test robustness on windows (#21116)\n- v.pkgconfig: add pkgconfig path `/usr/libdata/pkgconfig` for FreeBSD base packages (#21151)\n- v.util: add diff tool color support detection (tested on linux and freebsd) (#21244)\n- v.util.diff: return diff options with the diff command for FreeBSD/OpenBSD (#21271)\n- v.pkgconfig: fix load_paths with `;` split char on windows (#21291)\n- Fix vpm on macos, when using the bundled git executable (#21292)\n- ci: fix the bundled tcc for macos arm64 (#21299)\n- ci: update the runner for build-macos-arm64 to `macos-14` too, so it runs on M1\n- Fix hot code reloading on windows (#21351)\n- Fix building vpm on the FreeBSD instance, that runs fast.v\n- Fix `v install` for the FreeBSD instance that updates docs.vlang.io .\n- ci: use macos-13 for cross_ci.yml to force the old non m1 runner\n- v.builder: update macos->linux cross compile message (~22MB -> ~77MB)\n- v.pref: fix new pref test on FreeBSD (#21385)\n- ci: stop earlier on vc/v.c files, that may break on systems != linux (#21397)\n- Fix compilation on macos-arm with `-cstrict`; run macos ci also on the arm runner (#21408)\n- ci: use `v` instead of `./v` in the platform linux/macos/windows/_ci.yml files (#21454)\n- ci: add a retry to vcreate_init_test.v (it is sporadically flaky on macos)\n- sync,os,thirdparty: fix cross compilation from macos to windows (#21484)\n- os: rename os_structs_stat_windows.v to os_structs_stat_windows.c.v to fix\n  `v -Wimpure-v -os windows vlib/os/os_stat_test.v`\n- Default to `-cc clang` on FreeBSD in `cmd/tools/vtest_test.v` (#21534)\n\n## V 0.4.5\n\n*20 March 2024*\n\n#### Improvements in the language\n\n- Add map update-init syntax: `new_map := {...old_map, 'k1': 1, 'k2': 5}` (#20561)\n- Improve coroutines, Photon vcpu creation, coroutines + GC fixes (#20549)\n- Update Boehm GC libs/headers to the latest version 8.3.0 (#20772)\n- $dbg statement - native V debugger REPL (#20533)\n- Implement `@[_linker_section]` attribute (#20629)\n- Enable `@[export]` for global variables too (#20649)\n- Add callstack support on v.debug (#20680)\n\n#### Breaking changes\n\n- sokol: the sokol wrapper was updated, to match its upstream version at commit 058a4c5, several of\n  its APIs no longer exist\n- templating.dtm: compile_template_file is no longer public\n- v.trace_calls: `pub fn on_c_main() {`, is now `pub fn on_c_main(should_trace_c_main bool) {`\n- v.transformer: Transformer.fn_decl is now Transformer.fn_decl_trace_calls\n- x.vweb: Context.redirect(url string, redirect_type RedirectType) is now Context.redirect(url\n  string, params RedirectParams)\n\n#### Checker improvements/fixes\n\n- Check invalid lambda expr (#20461)\n- Fix comptime if with comptime smartcast (#20466)\n- Fix anon struct init with const fields (fix #20452) (#20463)\n- Disallow `option` or `result` return type, for infix operator overloading (#20494)\n- Cleanup the const variable evaluate for fixed array fields of structs (#20503)\n- Fix missing check for struct initialization with `@[noinit]` attribute, through using `T{}` (\n  #20516)\n- Fix mark methods into used-list, when generics as receivers (fix #20509) (#20527)\n- Modify comments on generic receiver type storage (#20539)\n- Fix checking give const map as default or init value to struct fields (fix #20512) (#20546)\n- Fix return map index with or_block (#20544)\n- Cleanup the generic tests (#20553)\n- Fix `@[deprecated]` attribute for consts (fix #20523) (#20550)\n- Cleanup in method_call() (#20554)\n- Disallow `non_opt_array << optvalue` (#20573)\n- Fix non dereferenced enum in match statements (fixes #10045) (#20591)\n- Fix .variant smartcast on non-comptime variables (#20575)\n- Disallow static maps: `mut static x := map[string]int{}` (#20596)\n- Allow `#define X` and `asm riscv64 {}` blocks in .v files, with `-freestanding` (make embedded\n  usecases easier)\n- Add cast overflow checks (#20641)\n- Disallow assigning none to _ (#20646)\n- Fix checking for option matching with non-option (#20673)\n- Disallow `(x) := 10` (#20695)\n- Disallow `none` as match cond (#20688)\n- Fix comptime ident checking on defer stmt (fix #20719) (#20723)\n- Add error for `x as Y.field`, suggesting using `(x as Y).field` instead for clarity (#20725)\n- Disallow sum type holding alias ptrs (#20786)\n- Optimise out calls to `arg_typ_sym.embed_name()` when there are no errors (#20820)\n- Fix if branch option type mismatch (fix #20809) (#20830)\n- Fix auto deref arg when fn expects ref (#20846)\n- Fix struct field init with generic fn variable (fix #20847) (#20878)\n- Cleanup in assign_stmt() (#20880)\n- Check assigning immutable reference struct field (fix #20814) (#20883)\n- Fix struct field init with generic anon fn (add the test from #18294) (#20888)\n- Fix checking match branch call expr twice (#20910)\n- Support `Flags.bit ^ Flags.bit1` and `~Flags.bit` (flagged enums) (fix #20925) (#20929)\n- Fix some specific interface generic inference within generics struct and method (#20932)\n- Remove notice when shifting signed int for `@[translated]` (#20935)\n- Silence \"assigning 0 to a reference field\" and \"uninitialized fn struct fields\" notices for\n  `@[translated]\\nmodule ...` files (#20938)\n- Fix missing check for interface cast of option type (#20961)\n- Silence more warnings for `@[translated]` files (#20964)\n- Fix comptimeselector passing to generic argument (#20985)\n- Remove unnecessary string interpolation in deprecation method calls (#21007)\n- Disallow void return value lambdas in array.map method calls (#21011)\n- Cleanup and simplify `check_ref_fields_initialized` methods (#21016)\n- Cleanup and simplify struct processing p1 (#21009)\n- Add support for deprecation messages for structs and struct fields (#21017)\n- Cleanup and simplify struct processing p2, extend test (#21025)\n- Fix undefined reference to interface struct field regression (after #21025) (#21030)\n- Add test for interface embedding and interface with erroneous implementation (test related to\n  #21030) (#21033)\n- Disallow `Optional` and `Result` high val in a `for x in low..high {` loop  (#21043)\n- Fix missing incompatible pushval type for chan <- operator (#21040)\n\n#### Parser improvements\n\n- Fix close_scope() missing, when field.name is `sort` or `sorted` (fix#20436) (#20485)\n- Check non-generic interface defining generic method (#20545)\n- vast,ast: output map init update expression (#20574)\n- Implement `MyEnum.from(1)!` generic static method (#20411)\n- Fix `MyEnum.from(0)!`, implement `MyFlaggedEnum.zero()` (#20623)\n- vfmt,parser: keep the original import name in ast.Import, and use it without modifications for\n  paths unders ~/.vmodules\n- Allow double quotes in `@include` template directives (#20628)\n- Fn type declaration does not check already registered name (#20732)\n- Fix global const ordering with string inter literal (fix #20760) (#20770)\n- Disallow option alias with option parent type  (#20769)\n- Make Scope.find methods more robust, when called on default initialised\n  `scope &Scope = unsafe { nil }` fields (#20774)\n- Fix parsing of cgen.v, in normal mode, when the table is empty (no files in `builtin` are\n  preparsed) (fix #20606) (#20611)\n- Fix infinite loop in Parser.sql stmt in `-silent -print-watched-files` mode (used by `v watch`) (\n  #20873)\n- Disallow defining map key more than once  (#20905)\n- Fix formatting comptime if expr, after inc expr (fix #20927) (#20931)\n- Fix for comptime with fully type name (fix #20948) (#20988)\n- Allow lock prefix instructions and numbered reg in inline asm blocks (#21022)\n- Add better error for mut variadic fn argument  (#21063)\n\n#### Compiler internals\n\n- v.util: make launch_tool failures more detailed (for the `Text file busy; code: 26` case), bump\n  tool_recompile_retry_max_count from 3 to 7\n- v.util: make launch_tool more robust, when multiple `v -b js file.v` commands are run at the same\n  time (all trying to recompile the JS backend program) (#20631)\n- builder: allow for\n  `./v -freestanding -cc riscv64-elf-gcc -d no_main -no-builtin -no-preludes -showcc -keepc x.v`\n- pref: support file_notd_freestanding.v + file_d_freestanding.v, remove dependency to `os`, of $\n  embed_file(), when compiling with -freestanding (#20712)\n- v.builder: reduce the default noise from successfully rebuilding cached thirdparty object files\n- pref: allow fetching the photonwrapper .so (for the coroutines) with curl too, or print details\n  for manual download (#20855)\n- scanner: disallow a shebang line, that is not at the top of a file (#21029)\n- strings.textscanner: fix off-by-one error in skip method (#21045)\n\n#### Standard library\n\n- x.crypto.chacha20: speed up the core functionality of the ChaCha20 stream cipher (#20470)\n- log: enhance log time format setting (#20484)\n- encoding.csv: add a new utility fn `new_reader_from_file/2` (#20530)\n- readline: add completion support (#20559)\n- builtin: add `is_hex()`, `is_int()`, `is_bin()`, and `is_oct()` methods to the string type (\n  #20540)\n- builtin: add empty string verification for the new string .is_oct() etc methods, suggested on PR\n  #20540 (#20564)\n- json: fix struct with option enum field (fix #20597) #20597\n- x.json2: fix panic on calling json2.decode of an optional enum (fix #20593) (#20603)\n- vlib: add a compress.zstd module (#20616)\n- io: ensure BufferedReader.read_line() returns `io.Eof`, instead of `error('none')` (#20619)\n- log: add support for l.set_short_tag/1 (#20652)\n- Update error checking for new error io.Eof (#20656)\n- io: allow BufferedReader.read_line() to accept custom line delimiters (#20655)\n- builtin: implement unbuffer_stdout/0 (#20662)\n- x.crypto: add sm4 module (#20651)\n- crypto.aes: optimise performance (#20674)\n- os: add proper process termination with p.signal_term() (#20671)\n- os: simplify and unify os.join_path and os.join_path_single, and add more tests (#21494)\n- bitfield: enhance operation with multiple flags (#20683)\n- os: fix File.read() in JS backends (fix #20501) (#20633)\n- os: add error_posix() and error_win32() for explicit platform error handling and default\n  behavior (#20694)\n- log: implement set_always_flush/1 for log.Log, log.ThreadSafeLog and log.Logger (#20698)\n- x.vweb: error() and simpler redirect(); comptime: a clearer error\n- builtin: add a string.u8_array() method (#20736)\n- os: add os.stat() and helpers (#20739)\n- os: make os.SystemError struct public so the os.error_* functions can be used by other modules (\n  #20754)\n- os: refactor to use os.stat and os.lstat instead of unsafe C calls (#20759)\n- os: make os_stat_test.v more robust to reporting false positives\n- x.crypto: add poly1305 message authentication code (mac) in pure v (#20752)\n- encoding.binary: add _fixed variants for the conversion fns, that accept fixed arrays (#20766)\n- x.crypto.sm4: make sm4 use the encoding.binary _fixed fns (#20773)\n- builtin: add gc_collect/0, gc_get_warn_proc/0, gc_set_warn_proc/1. Use them to turn off GC\n  warnings by default. (#20788)\n- builtin: support `-d gc_warn_on_stderr`, to show the GC warnings, without installing a custom warn\n  fn callback\n- x.crypto: add AEAD ChaCha20Poly1305 algorithm in pure v (#20817)\n- x.crypto.chacha20: remove deprecated `math.max_u32` in favour of builtin `max_u32`, remove\n  unneceseary bits, reorder (#20838)\n- json: fix decode struct ptr (#20828)\n- time: add a .http_header_string() method on Time (#20861)\n- json2: reorganize encode string (#20862)\n- vlib: add `encoding.txtar` (port of Go's txtar module) (#20874)\n- gg: handle dpi change, when moving window to another monitor (#20886)\n- time: add a tm_gmtoff field to `C.tm` (a BSD and GNU extension) (#20907)\n- x.json2: add skippable field attr `@[json: '-']` (improve backwards compatibility with the `json`\n  module) (#20892)\n- time: rename identifiers and parameter names (#20913)\n- io: add a `string_reader` submodule (#20893)\n- toml: return an error from toml.parse_file(), when the passed file path does not exist (#20912)\n- x.json2: fix encoder commas (#20916)\n- time: microoptimise the Time formatting methods (use custom number->string conversion, instead of\n  string interpolation) (#20917)\n- x.json2: improve performance of string encoding for unicode special characters and emojis (#20867)\n- x.json2: minor performance improvement, update benchmark recommendations (#20954)\n- os: workaround a `-prod -cc gcc` bug, affecting os.open_file (fix #20923) (related to #20872) (\n  #20960)\n- cli: add pluralization to err msg, if required number of args is not met (#20971)\n- os: remove repetitive words in comments (#20981)\n- gg: fix empty circle in native; http: post_form_with_cookies; veb: print veb action in html errors\n- io.reader: make read_all constants public (#20997)\n- builtin: expose gc_disable(), gc_enable(), gc_is_enabled(), in addition to the existing\n  gc_collect() (#21002)\n- x.json2: improve error message upon missing comma (#20602)\n- builtin: fix a few grammar errors in builtin.string comments (#21010)\n- io.string_reader: fix needs_fill_until check (#21005)\n- builtin: add missing return type to fn signature for C.GC_get_stack_base\n- x.json2: predefine buffer capacity for encoding to avoid reallocations (#20920)\n- rand: add PRNG.fill_buffer_from_set/2 (#21037)\n- sokol.gfx: update the PixelFormat V enum, to exactly match the C sg_pixel_format from\n  thirdparty/sokol/sokol_gfx.h\n\n#### Web\n\n- net: fix vlib/net/tcp_test.v (since .listen_tcp with af .unix, is now expected to return an\n  error) (#20472)\n- net: remove unused import in tcp_test.v\n- x.vweb: add error, when static directory does not exist (#20455)\n- net.urllib: fix parsing url error, when querypath is '//' (fix #20476) (#20504)\n- vweb: unify listen address from tcp and print (#20448)\n- net.unix: make the error messages in unix_test.v more specific (#20537)\n- vweb: add an optional Context.before_accept_loop/0 method, to make testing easier and more\n  robust (#20538)\n- vweb: fix routes without results in vweb_app_test.v (#20548)\n- vweb: make vweb_test.v more robust and faster, by embedding its server as a module\n- Small fixes and backport changes from vweb (#20584)\n- net.smtp: implement mail attachment support (fix #19920) (#20640)\n- vweb: fix quickstart docs in the module's README.md on how to create a new vweb project (#20644)\n- net.http: add a temporary fix for the intermittent segfault with http.get_ text/1 and\n  `-prod -cc gcc` 13.2.0 (fix #20506) (#20660)\n- x.vweb: support HTTP 1.1 persistent connections (#20658)\n- x.vweb: use `$if debug_ev_callback ? {` for the\n  `[vweb] error: write event on connection should be closed` message\n- x.vweb: add cors middleware (#20713)\n- x.vweb: add new sessions module (#20642)\n- net: fix non-blocking read/write (#20438)\n- net: reduce flakiness of tcp test (#20761)\n- picoev: renaming, doc (#20567)\n- x.vweb: add full static host support, for urls ending with /folder/ , where the folder backing it,\n  has `index.html` inside (#20784)\n- x.sessions: change session Store interface to use results instead of options (#20796)\n- net: fix function name in split_address doc comment (#20794)\n- doc: x.vweb static website capabilities (#20808)\n- thirdparty: update picohttpparser (#20843)\n- picohttpparser: restore formatting for g_digits_lut, after f09826e (#20844)\n- x.vweb: fix handling of static URL paths like `/sub.folder/a_folder` (#20863)\n- veb: a new module veb.auth for authentication logic (tokens, hashed passwords)\n- veb.auth: make work with any db\n- net: workaround a `-prod -cc gcc` bug (#20872)\n- picoev: add more logging of errors (#20558)\n- picoev: remove fmt off tags (#20569)\n\n#### ORM\n\n- orm: fix checking invalid recursive structs (fix #20285) (#20491)\n- orm: fix checking invalid recursive structs in sql stmts (fix #20278) (#20505)\n- orm: fix orm insert issue if table missing [Issue : #20017] (#20580)\n- orm: fix orm_option_time_test.v after 2d0ed2c made insert in parent tables with child ones missing\n  fail\n- orm: insert expressions returning id\n\n#### Database drivers\n\n- db.sqlite: fix exec_param_many bug (#21008)\n\n#### C backend\n\n- Fix multidimensional fixed array size expression evaluation (fix #20311) (#20458)\n- Fix fixed array handling with operator overloading call (fix #20467) (#20469)\n- Fix C code, generated for generic option fixed array return type (fix #20465) (#20479)\n- Fix fixed array handling, on generic result return, and on or block (#20492)\n- Fix generated code for fixed array cast (fix #20454) (#20480)\n- Change `x.filter(cond).len > 0` to `x.any(cond)`, and `x.filter(cond) == 0` to `x.all(!cond)` (\n  #20513)\n- Fix code generation wrong, when '?foo.array or {}' as a 'for-in' condition (fix #20528) (#20542)\n- Add a necessary clone, when the closure param is string/array with -autofree (fix #20498) (#20557)\n- Fix wrong cgen, when auto_heap var, is used as a closed over arg in a closure (fix #20208) (\n  #20566)\n- Initialize closures in shared library mode (#20630)\n- Fix interface generic smartcast (#20609)\n- Support inter-dependent function types (#20638)\n- Write the profile file out, even upon CTRL-C or kill (#20677)\n- Fix as cast as selector (fix #20710) (#20718)\n- Fix method call checking against `none` (fix #20711) (#20717)\n- Fix interface on multi return func (fix #20720) (#20721)\n- Fix premature variable release by autofree (#20731)\n- Fix return with option on orexpr (#20728)\n- Fix auto str for map with ptr str (#20741)\n- Remove `ull` suffix, which looks like the cause for the first scanner error in PR#20726 (#20750)\n- Fix comptime smartcast as receiver on method call (#20749)\n- Fix unwrap on or-expr, when calling f() ?Type (fix #20756) (#20758)\n- Builtin,coroutines,cgen: fix using coroutines with boehm GC, by using a stack pointer corrector (\n  #20771)\n- Fix interface casting (#20789)\n- Fix auto_eq for option eq operator overload (#20795)\n- Fix from_string fn generation missing mod name (#20807)\n- Fix const fixed array initialization handling (#20812)\n- Fix unwrapped option selector assigning (#20816)\n- Fix map methods call with generic types (fix #20827) (#20829)\n- Fix codegen for a.index/1, where a is []Fn (#20849)\n- Fix thread return type generation (fix #20836) (#20850)\n- Fix code generated for anon struct default value (fix #20839) (#20851)\n- Fix comptime selector of interface (#20876)\n- Fix multiple fixed array variable init (fix #20895) (#20902)\n- Ast,checker,cgen: fix generics function with embedded structs, ensure correct link generation in\n  cgen (#20900)\n- Fix returning option call in non-option fn (#20943)\n- Fix global initializer of fixed array on gcc (#20934)\n- Fix comptime `is` condition when using interface (#20952)\n- Fix const fixed array init with index (#20950)\n- Fix generic map inferring key and value types (#20959)\n- Fix missing scope enclosing for const init which needs temp variables (#20973)\n- Fix fixed array return on fn with option generic return (#20974)\n- Fix code generated to comptime passed to generic arg (#20994)\n- Fix match for alias  (#21028)\n- Add ability to mark a global as `@[hidden]` (#21035)\n- Fix _str name generated for C struct which define str() method (#21042)\n- Fix for/in codegen when iterating over C structs (#21052)\n\n#### JavaScript backend\n\n- Fix javascript backend treating u32 as i32 (fix #20499) (#20618)\n- Fix u16 cast handling in the JS backend (#20620)\n- Make program_test.v not flaky anymore, so that it is more sensitive to early errors. Fix\n  compilation error for u16.v . Make u32.out match the current reality (the bug will be filed\n  separately)\n- Fix inconsistent output (u32) in JS backend (#20691)\n\n#### vfmt\n\n- v.fmt: drop newline in end comments for const (#20672)\n- Fix alias array no cast init (#20898)\n- Fix removal of used selective and alias imports in modules in `$VMODULES` dirs (#20977)\n- Improve submodule type alias lookup; fix formatting of modules in `$VMODULES` (#20989)\n- Fix type names for casts (#21036)\n- Insert auto imports after shebang (#21038)\n- Fix autoimport with shebang and comments above other imports (#21050)\n- Fix formatting for imports of submodule from module `src` dir (#21060)\n- tools.fmt: extend exit codes to allow spotting unformatted files next to internal errors (#21058)\n- Fix parsing of interface with comment above `mut:` keyword (#21062)\n\n#### Tools\n\n- repl: support executing shell commands on the REPL with `!sh [COMMAND]` (#20496)\n- repl: fix an issue with `print` and println after the execution of `for` or `if` (fix #20524) (\n  #20525)\n- tools: bump too_long_line_length_table to 160, to avoid warnings for just\n  `v check-md doc/docs.md` (most common)\n- tools: bump too_long_line_length_link to 250, to avoid warnings for very common long links\n- ci: simplify time_ci.yml, use more descriptive CI job names, for easier judging of CI failures\n- debug: fix variable dereferencing (#20594)\n- tools: support setting another SCANNER_MODE=parse_comments in parser_speed.v and scanner_speed.v\n- testing: fix warning for compiling `./v cmd/tools/vtest.v`\n- docs: add a section about modules specifics (#20653)\n- github: add dependabot.yml (#20800)\n- vtest,pref: add ability to have platform specific _test.v files (#20810)\n- ci: change spaceface777/cancel-workflow-action to styfle/cancel-workflow-action (#20806)\n- tools: use the same same skipping logic for the platform specific _test.v files in `v test-self`\n  too (#20815)\n- tools: make the output of `v check-md .` more informative (#20819)\n- v.debug: implement tracing hook feature (#20818)\n- ci: mark db_store_test.v as flaky\n- ci: add a vtcc step (check that vtcc, continues to be able to compile with v, and v itself can be\n  compiled with vtcc) (#21000)\n- v.util: simplify vtest (#21013)\n- vtest-self: add sandboxed packaging case (#21059)\n\n#### Operating System support\n\n- v.builder: allow for `v -shared -os windows file.v` on Linux/macos (fix #20445) (#20453)\n- Add windows dll support, fix (#20447) (#20459)\n- sync: add mutex.try*lock functions for FreeBSD too (#20482)\n- sync: fix FreeBSD implementation of sync functions (#20483)\n- os: make os.cache_dir() and os.vtmp_dir() more robust to parallel test executions on windows (\n  #20495)\n- builder: replace \"-rdynamic\" for clang on macos with \"-Wl,-export_dynamic\" (fix #20510) (#20511)\n- builder: restore ability to use tcc, without fallback to cc on macos\n- v.builder: use a more uniq prefix for the generated temporary file names, to further reduce the\n  chances of collision and sporadic CI failures on windows (#20551)\n- encoding.csv: fix bug in RandomAccessReader, spotted on windows with mingw32 (#20571)\n- builtin: use `#pkgconfig bdw-gc-threaded` where available, instead of `#pkgconfig bdw-gc` (on\n  FreeBSD)\n- db.pg: add include and lib paths for PostgreSQL on FreeBSD (#20582)\n- thirdparty: fix `v cmd/tools/vcompress.v` on FreeBSD\n- os: fix an error in Process.win_spawn_process, not using stdout pipe in a cmd environment on 32bit\n  Windows (#20613)\n- testing: retry 1 additional time sporadic silent test run failures on macos\n- builder: add '-lelf' to linker flags on freebsd (fix #20481) (#20643)\n- GNUmakefile: use standard default RM make variable to fix MSYS2 env on windows (#20701)\n- x.vweb: add the missing include for C.sendfile to sendfile_linux.c.v\n- clipboard: fix notice in clipboard_windows.c.v (#20733)\n- ci: update macos runners to macos-14, to make use of the much faster m1 instances (#20747)\n- builder: support musl-gcc on macos\n- builtin: link to user32 to fix boehm GC compilation on Windows with clang released from the LLVM\n  project (fix #20724) (#20767)\n- pref: download correct photonwrapper.so for linux (#20783)\n- ci: improve repo CI robustness, by marking dynamic_template_manager_cache_system_test.v as flaky,\n  and only failing db_store_test.v on !windows\n- tools.vpm: fix remove command on Windows, add test (#20852)\n- os: don't check rdev equality on FreeBSD, inside vlib/os/os_stat_test.v (#20885)\n- sync: support more gcc version specific search locations on linux with tcc\n\n## V 0.4.4\n\n*9 January 2024*\n\n#### Improvements in the language\n\n- Implement `@[aligned]` and `@[aligned:8]` attributes for structs and unions (#19915)\n- Update attributes to use new syntax\n- Update remaining deprecated attr syntax (#19908)\n- Support `$if T is $array_dynamic {` and `$if T is $array_fixed {` in addition to\n  `$if T is $array {` (#19882)\n- Prepare for making `-W impure-v` the default (#19940)\n- Assigning `0` to reference fields now requires unsafe blocks (fix #14911) (#19955)\n- Unwrap const() blocks\n- Implement $for comptime T.variants (#20193)\n- Add `r` and `R` switches for repeating in string interpolation, `'${\"abc\":3r}'` == 'abcabcabc' (\n  #20197)\n- Comptime refactor and cleanup (#20196)\n- Allow comptime-for to iterate over comptime variables, add `$string` comptime type, cleanup (\n  #20233)\n- Unwrap an option value automatically, inside `if o != none {` (#20275)\n- Complete support for smartcasting to a comptime variable type (#20270)\n- Improve comptime var checking with `is` operator and smartcasting (#20315)\n\n#### Breaking changes\n\n*none*\n\n#### Checker improvements/fixes\n\n- Disallow `$for i in struct.values` and `$for i in enum.fields` (#19845)\n- Parser, checker: fix var scope in lambda(fix #19860) (#19871)\n- Change the warning `more than 1000 possibilities in match range`  to a notice (#19862)\n- Fix inability to use multiple `import some modname as _` in the same .v file (fix #19899) (#19900)\n- Disallow casting strings to pointers outside `unsafe` (#19977)\n- Disallow directly indexing sumtype and interface, when using as parameters(fix #19811) (#19982)\n- Fix loop on aggregates of arrays (in match branches) of sumtypes (fix #18548) (#19988)\n- Disallow indexing mut struct, passed as a fn parameter (#19992)\n- Enhance err msg for unknown types for comptime `$for` (#20057)\n- Fix .clone()/.move() with shared maps (#20083)\n- Fix generics method call with struct short syntax args(fix #20030) (#20100)\n- Fix unwrap, when generic structs are used as arguments, in uncalled methods (fix #20132) (#20135)\n- Fix generic fn with generic fn call returning generic map (fix #20106) (#20150)\n- Cast sumtype to its variant generic type (#20166)\n- Refactor `string` to `enum` error check, handle `EnumName(string_variable)` too (#20210)\n- Fix generic array method call with multi-types (#20237)\n- Remove unnecessary struct ref field initialization checks and notifications at map initializing(\n  fix #20245) (#20251)\n- Add a notice, for accessing by key, map values, that contain pointers (to use unsafe or an `or {}`\n  block) (#20266)\n- Fix mismatch checking when a function returns sumtype as an argument (fix #19325) (#20264)\n- Fix and cleanup uninitialized checks for array initialisers with `len:` (fix #20272) (#20279)\n- Give an error for `.free()` method calls, when used on fixed arrays  (#20320)\n- Fix type mismatch checking for assignments with generics (fix #20298) (#20327)\n- Fix too strict checking with generics in assignment type mismatch (fix #20335) (#20346)\n- Disallow `string` to `voidptr` cast entirely (#20351)\n- Fix generic method calls with multi generic types (fix #20330) (#20360)\n\n#### Parser improvements\n\n- parser: fix parsing comments after new attribute syntax\n- parser: fix failures found with fuzzing (#19873)\n- parser: deprecate old attribute syntax & update remaining (missed) attributes (#19879)\n- parser: fix infix expr handling with cast on left side of << operator (#19985)\n- ast: fix generic structs with multiple levels of generic embedding (#20042)\n- parser: implement thread returns result and multi_returns (fix #19281) (#20194)\n- parser: fix formatting struct decl with comments (#20207)\n- parser: fix formatting enum and interface decl with comments (#20216)\n- parser: fix fn call with newline opening brace (fix #20258) (#20267)\n- parser: fix parse_vet_file() with vfmt off/on flag (#20273)\n\n#### Compiler internals\n\n- scanner: implement support for UTF-32 escape codes in string literals (#19911)\n- scanner: add new_silent_scanner/0, Scanner.prepare_for_new_text/1, make .ident_char/0,\n  .ident_string/0 and .text_scan/0 public (#20045)\n- pref: support VNORUN=1, to enable running of tests, vsh files etc (i.e. just compile them, for\n  debugging later)\n- scanner: fix backslashes followed directly by newline in string literals (fix #20291) (#20296)\n- scanner: fix escape character handling in character/rune literals (fix #20301) (#20304)\n- pref: disable the -macosx_version_min clang flag by default (#20297)\n- builder: remove passing `-fno-strict-aliasing`, for `-prod` to gcc/icc (#20368)\n- markused: add `-skip-unused` for programs that `import x.vweb` too (do not skip unused routing\n  methods)\n\n#### Standard library\n\n- json: fix recursive pointer encoding (#19840)\n- os,picohttpparser,sokol,strconv: prepare for making `-W impure-v` the default (#19846)\n- os: add fast path to mkdir_all, when the given folder already exists (#19869)\n- os: ignore empty path segments in `join_path` (#19877)\n- os: fix bootstrapping for OpenBSD\n- x.json2: replace deprecated type byte with u8 in the tests (#19909)\n- vlib: change byte to u8 (#19930)\n- sync: add a FreeBSD specific version of vlib/sync/sync_default.c.v (#19962)\n- datatypes: add push_many for doubly and singly linked list + add insert_many for heap (#19975)\n- datatypes: make `Direction` pub and fix and add tests for `push_many` (#19983)\n- gg: fn (data voidptr, e &Event) for events, allows methods\n- vlib: add a `compress.szip` module, deprecate the `szip` one after 2023-12-31 (#20003)\n- os: create the folder described by `XDG_CACHE_HOME`, *if it is non empty, and it does not exist\n  yet*, when calling `os.cache_dir()` (#20046)\n- vlib: use the builtin flush functions, instead of the C. ones (#20108)\n- crypto: add blake2s and blake2b hashes (#20149)\n- os: fix `mv_by_cp` for directories (#20154)\n- os: update mv fns, improve performance, add params struct to control overwrite behavior (#20156)\n- gg: fix overlapping slices in `draw_slice_filled()` (#20182)\n- json: fix option sumtype handling (#20186)\n- builtin: add `@[direct_array_access]` to js string trim_right method (#20222)\n- json2: add encoder support for `time.Time`  (#20228)\n- json2: fix encoding of 💀🐈 etc emojis (fix #20243) (#20247)\n- json2: make public the generic function `map_from/1` (#20294)\n- json2: optimise encoding to be faster than cJSON with -prod (#20052)\n- json2: support sumtype encoding in a more robust way (#20093)\n- json2: strict module (#17927)\n- crypto: fix notices/errors for `v -N test vlib/crypto`\n- crypto: add blake3 hash (#20319)\n- sokol: fix compiling gg and other graphical examples on OpenBSD (#20333)\n- csv: Add a sequential reader too (suitable for very large .csv files, it does not read everything\n  at once) (#20140)\n\n#### Web\n\n- net.mbedtls: use `char` and `usize` types for describing more precisely the C API of mbedtls (\n  #19837)\n- vweb: add the mime type for .toml files (#19875)\n- net.openssl: use actual C values for the SSLError enum (#19945)\n- vweb: .html('custom_template.html')\n- vweb: add an optional parameter to the .redirect/2 method, to be able to set the http code for the\n  redirects (#20082)\n- x.vweb: fix large payload (#20155)\n- x.vweb: reimplement csrf module (#20160)\n- net: make net.fionbio and net.msg_nosignal constants public in net_windows.c.v (#20183)\n- net.http: remove unused `read_set_cookies` function (#20187)\n- os, net.http.file: add a folder listing to the http static file server, started by file.serve/1 (\n  #20192)\n- websocket: enable using an already existing connection (from vweb or another http server) (#20103)\n- x.vweb: fix fsanitize-address test for SSE, improve documentation on the usage of\n  `takeover_conn` (#20249)\n- net.http: support `-d no_vschannel` on windows, to fix long waits, while connecting on some\n  systems (#20265)\n- x.vweb: fix `$vweb.html()` integration in cgen for the newer `x.vweb` module (fix #20204)\n- net: support only ip and ip6 in net.tcp_listener (#20336)\n- x.vweb.assets: reimplement assets module for x.vweb (#20280)\n- x.vweb.sse: reimplement SSE module for x.vweb (#20203)\n- js.dom: add querySelector[All] and NodeList (#20240)\n\n#### ORM\n\n- orm: fix code generation for an option time.Time field (#20031)\n- orm: fix the generated SQL for the \"not equal\" operator (#20321)\n\n#### Database drivers\n\n- db.mysql: add support for the FreeBSD name of the mariadb client library (#20039)\n- db.pg: fix using postgresql on windows, improve instructions for installing it (#20053)\n- db.mysql: add ability to prepare and execute statements separately (#20146)\n- db.pg: fix compilation error with the msvc compiler on windows, and add readme (#20326)\n\n#### Native backend\n\n#### C backend\n\n- Fix generic fn returning fixed array (#19885)\n- Fix arrays alias built-in methods call(fix #19896) (#19910)\n- Fix generic array initialization (fix #19903) (#19916)\n- Fix option sumtype auto deref (#19919)\n- Ast, checker, cgen: fix interface embedded methods call(fix #16496) (#19936)\n- Fix ref and deref when an interface is used as a function parameter (fix #19947) (#19966)\n- Fix auto str for interface struct member which implements str method (#19970)\n- Fix generics call with interface arg (fix #19976) (#20002)\n- Fix lambda initialization on option struct field (fix #19474) (#19995)\n- Fix live mode on windows (#20041)\n- Fix the static from_string method of Enum across mods(fix #20050) (#20068)\n- Fix `@[if xyz?] fn init() {}`, add tests (#20096)\n- Fix assignment to the elements of an array of fixed arrays (#20133)\n- Fix mutable comptimeselector usage (fix #20027) (#20134)\n- Fix generics chans select (#20159)\n- Fix string interp with zero characters (fix #20199) (#20200)\n- Fix interface eq method with option and ref (fix #19441) (#20201)\n- Fix infix expr in method of mut receiver variable (#20225)\n- Fix cgen for thread wrappers, when spawning fns with with anon-fn array args and mut interfaces (\n  fix #19425) (#20241)\n- Fix fixed array return when returning fixed array initialization (#20262)\n- Fix function generated code, when returning from match (#20263)\n- Fix in expression with mut and ref (fix #20268) (#20271)\n- Fix initialization of const string arrays on msvc (fix #20287) (#20289)\n- Fix code generation when 'in array init' is used as an if condition (fix #20300) (#20302)\n- Escape table names (fix #20313) (#20322)\n- Add missing clear method for generic maps (#20340)\n- Fix auto unwrapping option fn type (#20332)\n- Fix option initialization with default struct initialization to not be `none` (#20349)\n- Fix auto str for arr options with possible circular reference (#20354)\n- Fix code generation when the function returns mut fixed array (fix #20366) (#20367)\n\n#### vfmt\n\n- vfmt: automate transition from the old `[attribute]` to the new `@[attribute]` syntax (#19912)\n- vfmt: remove empty `__global()` (#20004)\n\n#### Tools\n\n- tools: fix already installed detection when running v install --once without args (#19838)\n- compress.gzip: change the endianness for validation to conform to the gzip file specification (fix\n  #19839) (#19849)\n- tools: support `v doc -run-examples math`, to ensure that all `// Example: code` doc comments are\n  working (#19852)\n- Fix `v help` in the prebuilt v executables from the zips in the releases\n- ci,tools: remove skips for the wasm backend, since binaryen is not required anymore (#19883)\n- tools.vpm: support again `http` installs, when installing from an url (workaround) (#19914)\n- tools.vpm: improve version detection of installed modules (#19933)\n- tools: fix `v up`, by not deleting `./v` when missing a `.git` folder (#19965)\n- tools.vpm: fix installing of modules with conflicting names, extend tests (#19961)\n- tools.vpm: evaluate dependencies earlier to fix potential recursive install loop (#19987)\n- tools.vpm: add support for ssh and hg version installations (#20125)\n- tools: simplify and remove redundancies in vshader.v (#20161)\n- ci: add new workflow, for doing the slower tests in vpm specifically with `-d network` (#20177)\n- tools.vpm: improve detection of already parsed modules (#20223)\n- scanner: change `-d debugscanner` to `-d trace_scanner` for uniformity with the other tracing\n  options, described in CONTRIBUTING.md\n- v.pref: support a `-n` option, silencing only notices (#20331)\n- ci: add vsql to v_apps_and_modules_compile_ci.yml too (#20341)\n- ci: fix the workflow for Vinix, using the rules in its own .yml file (#20371)\n- Support -? as alias to -help (implement #20355) (#20358)\n- vdoc: filter testdata and tests folders by default, reduce filesystem stats calls\n\n#### Operating System support\n\n- os: small cleanup in the FreeBSD branch of os.executable/0: use fixed array for the sysctl params,\n  instead of allocating a dynamic one (#20353)\n- os: improve os.executable() on OpenBSD (#20356)\n- v.util.diff: support OpenBSD's default `diff` tool (#20369)\n- os: fix os.open_file/3 `wb` mode creation of text files containing crlf on Windows (#20101)\n- os: fix File.tell for files > 2GB on windows, by using C._telli64(f.fd) (#20072)\n\n#### Examples\n\n- encoding.xml: make functions public, add documentation, tests, fix attribute parsing for\n  self-closing tags  (#19901)\n- examples: show how to turn on CORS in a vweb server app\n- examples: serve the wasm mandelbrot project using a v web server (#19937)\n- examples: increase the resolution of the generated image in examples/wasm/mandelbrot\n- docs: update null convention in ORM example, since `@[nonull]` is no longer needed (#20286)\n- docs: add an example of a nullable ORM field (#20292)\n- example: add a path finding algorithm visualizer using gg (#20060)\n- examples: add an even smaller gg usage example, demonstrating how to always show the builtin fps\n  counter, and how to avoid importing gx\n\n## V 0.4.3\n\n*11 November 2023*\n\n#### Improvements in the language\n\n- A new `encoding.xml` module with parser, validation, entity encoding, unit tests (#19708)\n- Better couroutines support (IO, networking)\n- Allocations in vweb apps reduced by 80%\n- Implement `@VCURRENTHASH` to replace `C.V_CURRENT_COMMIT_HASH` (#19514)\n- int => i64 on 64 bit, i32 on 32 bit (start of the transition)\n- Fix new int type promotion rules and cleanup native gen() (#19535)\n\n#### Breaking changes\n\n- `Request.cookies` map has been deprecated. Replaced with `Request.cookie()` and\n  `Request.add_cookie()`.\n- Stricter rules for C types (they always have to be declared now)\n\n#### Checker improvements/fixes\n\n- Turn the option/result split warning into an error\n- Turn propagation warning into an error (finishes the option/result split)\n- Fix fn call with option call argument in autofree mode (#19515)\n- Bring back pascal case check for aliases\n- C.xx = C.yy aliases\n- Allow casted integral types in match ranges (#19572)\n- Warn about byte deprecation, when used as a fn parameter (#19629)\n- Allow size of fixed array to be integral casts (#19663)\n- Fix generic array append (#19658)\n- Check error of implementing other module private interface (fix #19620) (#19688)\n- Extend byte deprecation warning to array init types (#19671)\n- Extend byte deprecation warnings to return types (#19668)\n- Fix negative cap, len checks in array init (#19694)\n- Turn warning for var and param module name duplicates into error (#19645)\n- Fix closure in if guard, including with multi_return (#19765)\n- Fix comptime enumdata value property access (#19768)\n- Fix `field ?&Type` without default value (#19786)\n- Avoid nil assign to option var (#19746)\n- Allow for a shared variable to be whole reassigned (keeping the same mutex state) (fix #15649) (\n  #19751)\n\n#### Parser improvements\n\n- Fix assigning static method to anon fn (#19499)\n- ast: fix formatting a struct declaration with a nested struct (#19592)\n- Add `set_all` + `clear_all` methods to `[flag]` enum bitfields (#19717)\n- ast: reduce cost of frequently called functions by using constants (#19733)\n- Warn on unused imports, even when they are declared via `import math { sin, cos }`   (#19738)\n- ast: add missing docstrings for the public fns in vlib/v/ast/types.v (#19752)\n- Give a friendly error when misusing if over $if (#19810)\n- Add multiple struct attributes error for new attribute syntax\n\n#### Compiler internals\n\n- checker, builder, pref: support `-dump-defines -` to help explore all the available user and\n  system defines for a given program (#19576)\n- pref,builder: add support for `-macosx-version-min 10.2` and `-macosx-version-min 0` (with default\n  of 10.7) (#19626)\n- pref: fix unintended file extensions in default output names, allow for `v run file.c.v` (#19745)\n- transformer: fix using a constant, instead of a fn parameter with the same name (fix #19766) (\n  #19773)\n- maps: add maps.merge() and maps.merge_in_place() generic utility functions (#19776)\n- coroutines: only attempt to add/remove roots when GC is on.\n- markused: cleanup in mark_used(), use robust index names, instead of the much more brittle integer\n  values (#19543)\n\n#### Standard library\n\n- builtin: add an `unsafe { a.reset() }` method, for quickly setting all bytes in an array to 0\n- math.fractions: use operator overloading and deprecate old functions (#19547)\n- gg: fix the alignment of the bottom border of draw_rounded_rect_empty on macos and linux\n- crypto.bcrypt: fix bcrypt failure for valid pass and hash (fix #19558) (#19569)\n- sokol: update sokol to the latest version\n- builtin: fix sizeof(C.BOOL) (windows specific) (#19589)\n- math.big: fix incorrect division with negative numbers (fix #19585) (#19587)\n- os: add a convenient way to ignore certain system signals (#19632)\n- os: fix os.ls(folder) on windows, when a protected folder can not be opened (#19647)\n- os: add a convenient way to ignore certain system signals (#19639)\n- crypto.sha: fix calculating the same hash values when .sum() is called several times for\n  sha1/256/512 (fix #19696) (#19697)\n- crypto.md5: fix calculating the same hash values, when .sum() is called several times (#19703)\n- os: add a new function `execute_opt` (#19723)\n- os: add os.page_size() (#19770)\n- os: implement os.fd_is_pending/1, os.Process.pipe_read/1, os.Process.is_pending/1 (#19787)\n- builtin: copy min/max integer values consts from `math` to builtin so that the entire math module\n  doesn't have to be imported(#19809)\n- json2: add support for nested structs (#19579)\n\n#### Web\n\n- vweb: add mime type support for static .md files\n- net.conv: add varinttou64 and u64tovarint functions, for the variable unsigned integer encoding,\n  described in rfc9000 (for QUIC) (#19568)\n- net.http: support passing on_running, on_stopped, on_closed callback functions to http.Server{},\n  as well as show_startup_message: false. (#19591)\n- net: fix handling of spurious wake-up signals, lost when calling select() in mbedtls and openssl (\n  continue on C.EINTR) (#19600)\n- net: use conv.hton* consistently, instead of\n  `$if tinyc { conv.hton16(port) } $else { u16(C.htons(port)) }`\n- net.http: support passing an HTTP proxy server in http.fetch (#19606)\n- net.http: add a retry mechanism to http.fetch(), when the socket inevitably errors (#19660)\n- wasm: implement inline assembly (#19686)\n- net.http: increase max_redirects to 16 (#19743)\n- picoev: implement raw mode (#19771)\n- flag,json,net: handle C calls in .v files (part of enabling `-W impure-v` as default) (#19779)\n- net.http: add socks5|http(s) proxy support [Linux] (#19676)\n\n#### ORM\n\n- orm: add null handling and option fields (#19379)\n- orm: make is_null/is_not_null unary ops; don't bind null in where (#19635)\n\n#### Database drivers\n\n- pg: handle C calls, move to .c.v files (#19739)\n\n#### Native backend\n\n- native: support `-no-builtin` (generate executables < 1KB Linux with\n  `v -no-builtin -b native examples/hello_world.v`)\n- native: use i32 instead of int\n\n#### C backend\n\n- Fix printing fixed array of options (#19479)\n- Fix struct field of fixed array init (fix #19483) (#19487)\n- Fix struct init with multi option fn type (#19491)\n- Ast, native, cgen: add support for `$if native {}` (#19500)\n- Fix maps with i32 keys\n- Fix for c stmt with option or result calls (#19641)\n- Fix infix op when handling comptime selector (#19691)\n- Fix array contains method with interface(fix #19670) (#19675)\n- Reduce expense in repetitively called functions by using consts (#19732)\n- Fix closure parameter judgment when var cross assign inside anon fn(fix #19734) (#19736)\n- Only generate free in wrapper for spawn and not go (#19780)\n- Fix g.obf_table data missing(fix #19695) (#19778)\n- Fix closure variable in smartcast (#19796)\n\n#### vfmt\n\n- Remove additional line breaks after call_expr before params struct args (#19795)\n- Fix map value alignment when using keys with uft8 symbols (#19689)\n- Align ternary expressions in const blocks (#19721)\n- Respect range index expressions in match branches (#19684)\n- Respect raw strings in `$embed_file(r'/some/path')` expressions (#19753)\n- Fix formatting of struct field with default value and new attr syntax (#19683)\n- Recognize or blocks in call args (#19690)\n\n#### Tools\n\n- all: add support for `@LOCATION`, for more convenient logging/tracing, without needing to combine\n  `@FILE`, `@LINE` at runtime (#19488)\n- benchmark: add new methods b.record_measure/1 and b.all_recorded_measures/0 (#19561)\n- ci: update c2v workflow, translate doom on macOS (#19562)\n- strings: add Bulder.write_decimal/1 method (write a decimal number, without additional\n  allocations) (#19625)\n- testing: add temporary file hash to prevent accidental collisions with test file binaries (#19710)\n- ci: compile VTL and VSL in their own CI job, with `VFLAGS=-no-parallel`\n- tools: fix windows install of an already existing module with vpm (#19761)\n- tools: use `VPM_NO_INCREMENT` env var to skip dl count increment when testing vpm (#19756)\n- tools.vpm: improve handling of urls that end with .git (#19758)\n- tools: fix resolving external dependencies in vpm, add test (#19772)\n- tools: cleanup and simplify vcreate, for upcoming fixes and features (#19794)\n- tools: improve error messages, add color coding and debug logging (#19781)\n- tools: fix `v build-tools`, make `v test` more robust (#19803)\n- tools: add parse_query to vpm (#19814)\n- ci: add macos arm64 binary release (#19823)\n- Require the presence of a `v.mod` file, to install external urls via vpm (#19825)\n- vcreate: fix `v init` with project names containing dashes (#19619)\n\n#### Operating System support\n\n#### Examples\n\n- tests: workaround name conflict, causing false positives with msvc on windows, when both tests\n  were executed at the same time (locked executable)\n\n## V 0.4.2\n\n*30 September 2023*\n\n#### Improvements in the language\n\n- Short lambda expressions like `a.sorted(|x,y| x > y)` (#19390)\n- Support `-os plan9`, `$if plan9 {`, and `_plan9.c.v` (stage 1 for plan9) (#19389)\n- fmt: simplify the processing logic for removing inline comments (#19297)\n- Align the custom values of the enum fields (#19331)\n- Do not warn/error for `import flag as _`\n- Keep anon struct decl fields in interfaces (#19461)\n- Support -N, turning all notices into errors, to ease the process of finding places that may need\n  attention/correction\n\n#### Breaking changes\n\n- Remove inline comments (#19263)\n\n#### Checker improvements/fixes\n\n- Disallow module name duplicates in local names (#18118)\n- Check enum fields with duplicate value (fix #19309) (#19310)\n- Disallow alias ptr cast of a map value (#19336)\n- Require `else` branch in `[flag]` enum match (#19375)\n- Disallow assigning pointer values to option struct fields (#19380)\n- Fix generic comparison for conditional assignment (#19401)\n- Allow using ! and ~ on aliased bool and integral types (#19403)\n- Warn -> error for uninitialized ref fields\n- Parser, checker: allow lambdas anywhere anonymous functions are expected (#19436)\n- Allow for `each(a, |x| println(x))`, i.e. using lambda expressions, when expecting `fn (x int)`\n- Check fixed array init with default expression (#19472)\n- Allow for `const source = $embed_file(@FILE).to_string()`\n- Fix C.type in imported modules\n\n#### Parser improvements\n\n- parser: fix fixed array with eval const size (#19269)\n- parser: disallow using `sql` as name (#19298)\n- parser: fix `;` support for `module x;`\n- parser: fix fixed array of option values (`_ := [10]?int{}`) (#19392)\n- parser: fix assigning with in another module sumtypes 2 (#19415)\n- Support `;` statements, allowing for oneliners like\n  `./v -e 'import os; println( os.ls(os.args[1])!.sorted(a > b) )' vlib/math` (#19345)\n- v.ast: improve Stmt.str(), showing more details about ast.Block, ast.DeferStmt, ast.ForInStmt,\n  ast.GlobalDecl\n\n#### Compiler internals\n\n- pref: support `-fast-math`, passing either -ffast-math or /fp:fast (for msvc) to the C backend,\n  and `$if fast_math {` to detect it at comptime\n- parser, transformer: fix transformer.infix_expr() and cleanup parse_types.v (related #19269) (\n  #19276)\n- pref,builder: support -use-os-system-to-run to workaround segfaults using not fully updated xcode\n  command line tools\n- v.builder: fix compiling code, that imports modules from both `src/modules` and `modules` (#19437)\n- os, v.builder: show more details, when a program ran by `v run file.v`, exits by a signal (fix\n  #19412) (#19471)\n\n#### Standard library\n\n- math: speedup the pure V math.pow implementation for non-fractional powers (#19270)\n- math: add more C. fn overrides, for the default C backend (speed up examples/path_tracing.v) (\n  #19271)\n- time: add `MMM` support for parse_format() (#19284)\n- os: include sys/sysctl.h on FreeBSD to avoid implicit definition of sysctl function (#19293)\n- crypto.md5: change the Digest.write return type, from `?int` to `!int` (#19311)\n- v.help: use os.executable() instead of `@VEXE` as an anchor, so `v help` will work more robustly.\n- toml: fix custom `to_toml` for complex structs (#19338)\n- vlib: add net.http.file, allowing for `v -e \"import net.http.file; file.serve()\"` (#19348)\n- vlib: remove functions and fields, deprecated before 2023-03-20\n- toml: fix toml encoding of complex types (#19408)\n- arrays: add a partition function, that splits a given array, based on a criteria, passed as a\n  callback fn (#19417)\n- toml: add decoding for struct fields of type map[string]T (#19447)\n- arrays: add arrays.each, arrays.each_indexed, and tests for them\n- encoding.html: implement `unescape()` (#19267)\n\n#### Web\n\n- net.http: fix http.fetch(), without explicit method (default again to .get, not to .acl)\n- net.http: default explicitly to Method.get for http.Request and http.FetchConfig too\n- examples: add examples/fetch_ip.v, showing how to contact http://ifconfig.co/json and parse the\n  result\n- net.http: fix post error with https on windows (#19334)\n- net.ssl: implement SSLConn.peer_addr() (#19333)\n\n#### ORM\n\n- orm: add `references` attribute to allow foreign key declarations on fields (#19349)\n- orm: support different foreign key types, not just an integer id (#19337)\n- orm: add support for V enum struct fields (#19374)\n- orm: quote table and field name in `[references]` (#19387)\n\n#### Database drivers\n\n- db.pg: allow postgres connection using service definitions (#19288)\n\n#### Native backend\n\n- native: make native tests pass on windows; refactor PE file generation (#19140)\n- native: parse dll files to resolve extern symbols (#19433)\n\n#### C backend\n\n- Fix printing struct with thread field (#19320)\n- Fix the logic around the definition of VNORETURN and VUNREACHABLE (less warnings on FreeBSD) (\n  #19316)\n- Add support for `-d trace_cgen_stmt`, document it in CONTRIBUTING.md\n- Fix printing smartcast interface variable (fix #18886) (#19372)\n- Fix interface with multiple embedded fields (#19377)\n- Fix channel of interface (fix #19382) (#19383)\n- Fix fixed array of option type default (#19397)\n- Fix interface with option field (#19434)\n- Fix promoting an alias typed value, to a sumtype of the alias's base type (fix #19407) (#19423)\n- Remove the special plan9 support code, treat it instead as a posix system in cheaders.v (#19445)\n- Fix printing slice of fn call string (#19450)\n- Fix `type VType = &C.CType` (#19452)\n- Fix array of fns index call with direct_array_access mode (#19460)\n\n#### Tools\n\n- bench: a new bench/ directory for language benchmarks\n- ci: test the pure V math versions without .c.v overrides on the CI too (#19292)\n- github: add automatically info about voting to all new issues (#19351)\n- tools: add -E flag to `v test-parser`, that will show the partial source that caused the parser to\n  fail with `-no-builtin -check-syntax file.v`\n- ci: bring back gitly\n- github: improve the voting message for issues (#19448)\n- vcreate: update templates, add `lib` (#19444)\n\n#### Operating System support\n\n- builtin: use `libgc-threaded` on FreeBSD, to get the threaded version of libgc (#19294)\n\n#### Examples\n\n- examples: add more .obj files for 06_obj_viewer (#19406)\n\n## V 0.4.1\n\n*3 September 2023*\n\n#### Improvements in the language\n\n- Pure `array.sorted()` and `array.sorted_with_compare()` methods, that do not modify their\n  receivers (#19251)\n- UB overflow has been removed\n- Implement `Enum.from_string(name string)` for converting strings to enum values (#19156)\n- Disallow casting string to enum, suggest using Enum.from_string() instead (#19260)\n- Use autocasting in complex conditions (#18839)\n- Allow alias as fixed array on return (#18817)\n- Do not allow uninitialized function pointers\n- Fix compiling V programs with latest clang 16 on windows (clang 16 is stricter than clang 14) (\n  #19095)\n- Fix anonymous struct with default expr (#19257)\n- Allow using consts as enum values (#19193)\n- `@[attr]` syntax to replace `[attr]` (`[]` is used for too many things). Most likely to be\n  replaced with `@attr()` in the future.\n- Allow `none` for not first values on map initialization (#18821)\n- Make all .trace() methods generic on the type of the passed expression\n\n#### Breaking changes\n\n- `arr[1..4]` now requires `unsafe` if the slice can modify the original immutable array.\n\n#### Checker improvements/fixes\n\n- Disallow assigning `nil` to struct fields (#18725)\n- Use autocasting in complex if conditions (#18753)\n- Disallow invalid prefix on left side of assign stmt (#18750)\n- Allow no return in compile_error else block (#18758)\n- Fix interface param resolution (#18780)\n- Add an error for `$tmpl` function type mismatches (#18826)\n- Disallow voidptr cast to struct (#18845)\n- Fix type checker on auto deref var (#18842)\n- Check generic sumtype declaration (fix #18741) (#18865)\n- Fix closure with inherited sumtype variable (#18894)\n- \"v -line-info\" for a quick run to fetch info about objects on one line\n- Make sure vweb actions return vweb.Result\n- Do not allow modifying immutable vars via arrays with refs\n- Support `@STRUCT` in static methods\n- Fix generic struct field init recursively (related #19014) (#19025)\n- Fix struct field fntype value call (#19067)\n- Explicitly disallow creating type aliases of `none`, i.e. `type Abc = none` (#19078)\n- Fix assigning an array slice (fix #19120) (#19137)\n- Fix assigning array slice in struct init (#19150)\n- Check enum static from_string arguments errors (#19163)\n- Disallow taking the address of consts with int literal values (#19160)\n- Check struct embed with wrong position (#19245)\n- Optimize out needless string interpolations from the most common case in\n  `Checker.expr_or_block_err`\n- Check error for or_expr inside infix expression (#19213)\n- Disallow `thread` as var name (#19174)\n- Check error for sumtype in array (#19183)\n- Disallow an empty `chan` type (#19167)\n\n#### Parser improvements\n\n- Change warn to error, for const names with upper letter (fix #18838) (#18840)\n- Disallow declaring static functions as method receivers (#19007)\n- Disallow having builtin type as type names for `enum`, `sum type` and `alias` (#19043)\n- Support `const x := 123`, to make extracting locals as constants less annoying while prototyping\n- Fix struct field fn type with default value (fix #19099) (#19106)\n- Fix `for i++; i<10; i++ {` (fix #18445) (#19035)\n- Fix fn return alias of fixed array (#19116)\n- Fix generic struct init (Stack[&Person]{}) (fix #19119) (#19122)\n\n#### Compiler internals\n\n- pref: make -autofree work without -gc none\n- builder,pref: allow thirdparty objects compilation with CPP compiler (#19124)\n- scanner: fix string interpolation with nested string interpolation in inner quotes p. 3 (#19121)\n- scanner: error early on an unsupported escape sequence in a string, like `\\_` (fix #19131) (\n  #19134)\n- v.token: add inline next_to() and cleanup related calls (#19226)\n\n#### Standard library\n\n- eventbus: add generic support for event name (#18805)\n- readline: add support for ctlr+w and ctrl+u shortcuts (#18921)\n- strconv.atoi: fix string.int() returning numbers for non number characters (fix #18875) (#18925)\n- builtin: reduce the number of array allocations for consts in all V programs (#18889)\n- builtin: move array.data to the top of the struct\n- os.notify: implement the kqueue backend for notify.FdNotifier (#19057)\n- vlib: add a new module `builtin.wchar`, to ease dealing with C APIs that accept `wchar_t*` (\n  #18794)\n- arrays: add more util functions and tests for them - find_first, find_last, join_to_string (\n  #18784)\n- vlib: use sync.new_mutex() consistently for initialising all vlib structures containing mutex\n  fields\n- crypto.pem: add a static method `Block.new`, to replace `new` (#18846)\n- crypto.pem: add decode_only and general improvements to decoding (#18908)\n- log: improve the most common use case, it's no longer necessary to create a `Log` instance (\n  #19242)\n- crypto.sha512: make the new384/0, new512_256/0, new512_224/0 functions public\n- json: fix option alias support (#18801)\n- time: fix `parse_format` with `YY` (#18887)\n- math.big: allow bitwise ops on negative signum (#18912)\n- math.big: make is_odd public and add test cases (#18916)\n- math.big: add checked division methods (#18924)\n- math.big: add `isqrt_checked` and standardize error format (#18939)\n- sokol: use GLCORE33 on linux\n- os,term.termios: add termios.set_state/2, state.disable_echo/0, use them in os.input_password, to\n  fix `v -os wasm32_emscripten examples/2048/`\n- gg: implement Android specific APK asset loading for the `create_image` function (#19015)\n- sync: make sync.Direction public (#19047)\n- time: store time with nanosecond resolution in time.Time, deprecate Time.microsecond, add utility\n  methods and tests (#19062)\n- time: add a format_rfc3339_nano() method to time.Time\n- time: add 'i', 'ii' in custom_format() for 12-hours clock(0-12-1-11) (#19083)\n- gg: expand the `-d show_fps` background, so fps>100 will not overflow it\n- Math.big: restore gdc_euclid, use it for smaller numbers, fix bench_euclid.v .\n- Add new generic `arrays.uniq`, `arrays.uniq_only`, `arrays.uniq_only_repeated`,\n  `arrays.uniq_all_repeated`, `arrays.distinct`\n- builtin: add support for `-d builtin_writeln_should_write_at_once` and\n  `-d builtin_write_buf_to_fd_should_use_c_write` (#19243)\n- builtin: always show the assert message, if it was defined in the source, in non test programs\n  too (fix #19240)\n- time: check if a day is a valid day of its month (#19232)\n- toml: Add generic automatic decoding and encoding of simple structs, when they don't implement\n  custom methods (#17970)\n\n#### Web\n\n- http: Request.host\n- net.ftp: fix dir() for file names, which contain spaces (fix #18800) (#18804)\n- net.http: make listener public, and add addr in Server struct (#18871)\n- net.http.chunked: return `!string` on decode (#18928)\n- net.conv: rename functions to match other langs, making them easier t… (#18937)\n- wasm: remove dependency on thirdparty/binaryen, webassembly backend rewrite (#18120)\n- wasm: add a -wasm-stack-top flag to compiler (#19157)\n- net.mbedtls: add SSLListener to allow creating SSL servers (#19022)\n- picoev, picohttparser: reimplement in V (#18506)\n- vweb: fix parsing of form fields, send with multipart/form-data (by JS fetch)\n- vweb: make vweb route paths case sensitive (#18973)\n- net.mbedtls: have shutdown close accepted connections too (#19164)\n- http: add support for stream connections, and custom .on_redirect, .on_progress, .on_finish\n  callbacks to http.fetch() (#19184)\n- vweb: add a user_agent utility method to the vweb context (#19204)\n- vweb: avoid the controllers having to be defined in specific order (#19182)\n\n#### ORM\n\n- orm: fix inserting sequential values (id=0), in tables with an i64 primary field (#18791)\n- Add OR in where on update and delete (#19172)\n\n#### Database drivers\n\n- vlib: remove deprecated `pg`, `mysql`, `sqlite`, `mssql` modules. Leave only the `db.` prefixed\n  `db.pg`, `db.mysql` etc\n- db.mysql: add the exec family of methods (#19132)\n- db.sqlite: add exec_param_many and exec_param methods (#19071)\n- db.sqlite: make functions return results, breaking change (#19093)\n\n#### Native backend\n\n- native: move functions out of amd64.v (#18857)\n\n#### C backend\n\n- Fix selector code to use interface method table on closure when needed (#18736)\n- Fix nested or expr call (fix #18803) (#18807)\n- Ensure that `<<` and `>>` has higher precedence in the generated C code, than arithmetic\n  operations (diff between C and V precedences) (#18814)\n- Fix cross assign with aliased array (#18830)\n- Fix generated code for returning generic result/option to comptime var (#18834)\n- Fix option map with fn type value (#18849)\n- Fix returning an option tuple - `fn f() ?(int,int) { return g() }` (#18851)\n- Fix printing multiple fixed array (fix #18866) (#18879)\n- Fix infix expr with number overflow (fix #18905) (#18936)\n- Remove \\r for consistency (#18962)\n- Allow dump(unsafe{nil}) and dump(voidptr(123)) in the same program\n- Implement fixed array of threads wait() (#19032)\n- Fix an error with ptr interpolation (fix #19048) (#19049)\n- Fix spawn call fn struct field(fix #18862) (#19096)\n- Fix bootstrapping on older macOS Catalina\n- Fix alias of array method call(fix #19125) (#19129)\n- Simplifications and clean up.\n- Fix mixed fixed array and array initializing (#19246)\n- Fix array sort with fn call parameter (fix #19220) (#19221)\n- Fix generic struct with option fn field (#19218)\n- Fix comptime assign with generic result return type (#19192)\n- Fix match with comptime if expr in branch (#19189)\n\n#### Tools\n\n- ci: add v-analyzer builds (#18835)\n- ci: cleanup more the contents of the generated v_linux.zip, v_macos.zip, and v_windows.zip, use\n  -skip-unused\n- tools: fix vcomplete for zsh (#18950)\n- tools: support a toc for projects, with single exposing module, in `v doc` (#19001)\n- Add support for `v should-compile-all -c examples/`, which will delete all the produced\n  executables at the end\n- vgret: add install commands for ubuntu and arch to doc string (#19247)\n- fast.v: add favicon to the html produced by fast.v\n- vpm: implement multithreading (#19208)\n- Make performance_compare.v more robust and easier to use, by allowing\n  `v run cmd/tools/performance_compare.v` too\n- Improve oldv windows support, make it use -municode for windows builds, make it support cmd.exe\n- Make repeated runs of `oldv SAME_COMMIT -c \"./v file.v\"`, not use the network at all\n- Help: add link to the TESTS.md at the bottom of `v help test`, run CI checks on help markdown\n  files as well\n- v.builder: show the number of files, types, modules, when a program is compiled with -stats\n- Improve the output of parser_speed.v and scanner_speed.v\n\n## V 0.4\n\n*1 July 2023*\n\nThis release has a combined changelog from 0.3.1 to 0.3.5.\n\nYou can read it here:\n\nhttps://github.com/vlang/v/blob/master/changelogs0.x/0.4.md\n\n## V 0.3.5\n\n*29 June 2023*\n\n#### Improvements in the language\n\n- **Coroutines with a scheduler**. Only Linux/macOS for now, requires `-use-coroutines` and\n  `coroutines.sleep()` instead of `time.sleep()`. They work with IO and net, but not with GC\n  for now.\n- `spawn` now spawns system threads, `go` spawns coroutines.\n- Static type methods: `Foo.new()` to replace factory functions like `new_foo()`.\n- Smartcasting with complex conditions:\n  `if sum_type is Foo && !sum_type.is_info && get_name(sum_type.info.name) == 'foo' `.\n- Functions can now return fixed size arrays.\n- Enum values now can have attributes.\n- Generic functions as function parameters are now supported: `fn f[T](x T, i int, f_ Fn[T]) T { `.\n- Anonymous structs can no longer have attributes.\n\n#### Breaking changes\n\n- `byte` deprecated in favor of `u8` (`byte` is automatically converted to `u8` by vfmt).\n\n#### Checker improvements/fixes\n\n- Disallow `Result` type aliases (`type Foo = !Bar`) and `Result` in maps (`map[key]!Type`).\n- Add a missing check for taking address of literal value member.\n- Fixed map initialization for maps with option values.\n- Allow `a << none`, where `a` is `[]?&int`.\n- Disallow multiple `else` branches in a match.\n- Fix index expression with sumtype of array types.\n- Remove hardcoded check for function calls for `C.stat`, `C.sigaction`, etc.\n- Fix multiple embedded external module interface.\n- Fix missing check for diff type on map value declaration.\n- Simplify error handling in the checker (#18507).\n- Option alias fixes.\n- Fix alias to struct ptr on struct init.\n- Sumtypes can no longer hold references.\n- Fix a bug checking generic closures.\n- A hard to reach limit of 1 million iterations for resolving all generics.\n- Fix missing check for unwrapped shift operation.\n- Fix enum max value validation.\n- Add a missing mutability check for `array.delete` calls.\n- Disallow `_ = <- quit`.\n- Disallow type matching with primitive vars.\n- Warning instead of error for unnecessary brackets in if/match.\n- Include import aliases when checking for import duplicates.\n- Fix inferring generic array type in nested call.\n- Allow casted `enum val` and `const` as fixed array size.\n- Disallow multiple return values in const declarations.\n- Fix contains() with array of interfaces.\n- Disallow mut for blank idents.\n\n#### Standard library\n\n- json: Enum value string serialization supports `[json:'alias']` to change its string values.\n- Struct fields can now be skipped during JSON/ORM serialization via `[json:'-']` and `[sql:'-']`,\n  in addition to `[skip]`. This allows having custom behavior for different serialization methods.\n- builtin: heap usage API (gc_memory_use() and gc_heap_usage())\n- math.big: refactoring, gcd fixes/improvements, overflow fixes, `mod_inverse`.\n- flag: fix finalize with multiple shortargs.\n- runtime: add new functions total_memory/0 and free_memory/0.\n- time: small cleanup of parse_iso8601 comments, make the C.strftime declaration forwards compatible\n- stbi: allow customization of number of channels in `stbi.load()`.\n- stbi: add a `resize_uint8` function for resizing images in memory.\n- time, x.json2: improve iso8601 time decoding.\n- builtin: zero out internal map/array pointers on m.free(), to reduce the work for the GC\n  mark phase for non escaping maps/arrays, used in hot loops.\n- time: add more detailed error descriptions, add custom format parsing with time.parse_format.\n- sync: add Mutex.destroy and RwMutex.destroy methods.\n- datatypes: add Bloom filter.\n- rand: add missing rand.u16(), update doc comments, add test.\n- builtin: speed up string methods with vmemcpy instead of `for` loop for copying data.\n\n#### Web\n\n- The builtin websocket library is now thread safe.\n- Enhanced builtin csrf protection in vweb.\n- vweb: ability to set and get values on vweb.Context.\n- vweb: support for host specific static files.\n- vweb: host option added to controller, and a new host attribute.\n- vweb: middleware docs improved; same with docs for `[vweb_global]` and `shared`.\n- vweb: return 404 on file not found.\n- net.http: copy IANA's list of methods to the http.Method enum.\n- net.conv: use a pure V implementation instead of C.hton etc.\n- net.html: `get_tag()` methods to find first tag occurrence.\n- net.html: fixed text parsing for inline tags.\n- net.html: fix parsing of nested quoted strings in code tags.\n- picoev: FreeBSD support.\n\n#### ORM\n\n- Fixed a foreign key bug that could result in an extra insert.\n- Comptime bug with `[skip]` and `[sql:'-']` fixed.\n- Checker error for unsupported field types.\n- Allow structs without the id field, more flexible primary keys.\n- Improved docs and examples.\n- Uninitialized structs are no longer inserted into related tables.\n\n#### Database drivers\n\n- mysql: TIMESTAMP support.\n- mysql: allocate memory for each string and blob dynamically depending on its value length.\n- mysql: add the ability to commit transactions.\n\n#### Native backend\n\n- Refactoring, splitting large files into multiple.\n\n#### C backend\n\n- Fix code generation for generic unions.\n- Fix `[N]chan` (fixed arrays of channels).\n- Fix nested fixed array instantiation.\n- Fix fixed array of map.\n- Fix stringification of usize struct fields (before, they were treated as 32 bit *signed* numbers).\n\n#### Comptime\n\n- A new `$res` comptime function to get returned value in defer block (#18382).\n- Fix comptimeselector option propagation.\n- A mutability check for comptime assignments.\n- Fix comptime assigning to sumtype or indexexpr.\n- Make comptime calls work with or-block.\n\n#### Tools\n\n- A new VPM site: vpm.vlang.io. A better design, discoverability of packages, descriptions, most\n  downloaded packages etc.\n- vpm: installation of mixed modules.\n- `v ls --install -p D:\\path\\vls.exe` to install a local vls executable.\n- vdoc: highlight comments with gray color.\n- vet: allow vetting files with global variables.\n- Make util.launch_tool/3 more robust, by recompiling V tools always in a known current working\n  folder.\n\n## V 0.3.4\n\n*30 Apr 2023*\n\n#### Breaking Changes\n\nThe following changes may break compilation of existing code or change behavior at runtime:\n\n- `json`: enums are serialized as strings by default, `[json_as_number]` attribute can be used for\n  the old behavior.\n\n  If you are serializing enums to JSON in your application, then you will need to add the\n  `[json_as_number]` attribute to keep the old behavior!\n\n- Variable shadowing has been completely banned (previously variable names could conflict with\n  module names).\n\n#### Web\n\n- vweb now supports live page reloading.\n  The web app is instantly updated in the browser (no need to refresh the page)\n  every time a **.v** or a **.html** file is changed.\n- vweb is now significantly faster and more stable under load, due to a new multithreaded worker\n  pool, which is much more efficient at spreading the workload among all threads equally.\n- vweb now supports middleware.\n- vweb now supports controllers.\n  It's now possible to have multiple app structs to better separate logic.\n- vweb now supports overridable `.not_found()` method for custom 404 pages in vweb.\n- vweb now uses database pool.\n- Fixed multipart form parsing in vweb.\n\n#### Backends\n\n- A new pure WASM backend, based on binaryen, a WASM `builtin` module, and a pure V WASM\n  serialization library.\n- Lots of fixes and new features in the native backend, including making codegen logic platform\n  independent.\n- Now code generated by the С backend, can be compiled by a C++20 compiler.\n- C backend does not generate unused interface functions now.\n\n#### Compiler CLI\n\n- `v share file.v` for sharing code via the playground.\n- `v up` speed up for when it hasn't been run for a long time (**vc/** bootstrapping has been\n  optimized).\n- `v init` no longer overwrites existing `src/main.v`.\n- `v self` now uses a faster TCC backend on macOS (Intel/Apple Silicon), just like on Windows/Linux.\n- A new command line flag `-e` for running short V programs on command line: `v -e \"println(2+5)\"` (\n  works just like in Perl).\n- A new `-ldflags` option, in addition to `-cflags`. Works just like LDFLAGS in C.\n\n#### ORM\n\n- All ORM queries now return `![]` (`Result` of an array).\n  This allows handling/propagating DB errors and simplifies working with ORM (one way).\n- Many ORM improvements: type checks for `limit/offset/order by/where`; support of reference objects\n  in `insert`; struct fields can be used with `limit/offset`; `Connection` interface.\n- ORM now supports the `like` operator:\n  ```v syntax-ok\n  users := sql db {\n      select from User where name like 'Bob%'\n  }\n  ```\n- A new `-d trace_orm` option to see all SQL queries generated and used by V ORM and\n  `-d trace_pg_error` to trace PG errors.\n\n#### Standard Library\n\n- Added new `termios` module.\n- `net.ssl`: types using ssl contexts can now be converted to strings via `.str()`/printed\n  via `println()`.\n- `v.reflection`: added type symbol info metadata.\n- `crypto` and `math` modules have been updated to use `Result` instead of `Option`.\n- `datatypes.LinkedList[map]` now works correctly.\n- `urllib.Values.get()` now returns an Option.\n- `strconv`: `v_printf()` was made private, `v_sprintf()` was deprecated. String interpolation\n  should be used instead.\n- `net.http`: mime types have been updated to include all official types.\n- `gg`: `create_image()` now returns `!Image` instead of `Image`, allowing to handle errors.\n- `sokol`: errors during image creation no longer result in a panic, but can be handled by the\n  programmer.\n- `sokol`: macOS apps can now be quit using **Cmd+Q**.\n- `os.hostname()` and `os.loginname()` now return `Result`.\n- `strconv.atoi` optimizations.\n- `println()` now supports arrays with recursive references.\n- `termux`: support for cross-compilation from termux to other platforms.\n- `readline` module now works much better on macOS: key navigation, history, etc (now on par with\n  Linux).\n- `os`: fixed a memleak in `getline()`.\n- `os.Process` now has a `create_no_window` option (Windows only).\n- `os.Process` now has a `set_work_folder()` method to set the initial working folder of the new\n  child process.\n\n#### Option as a first class type\n\nFinal steps in making the Option type a first class type:\n\n- If guards now work with struct fields which are `Option` functions.\n  Such fields can now also be assigned to other fields/variables.\n- Option receivers can no longer have methods.\n- `none` can now be cast to all `Option` types, including aliases.\n- Option references are now supported: `?&Type`.\n- Arrays of `Option`s are now allowed.\n- Allow `foo := Foo{}`, when `Foo` has an Option field, that is a struct, that has a `[required]`\n  tag on its fields.\n\n#### Compile-time Reflection\n\n- Compile-time interface fields evaluation.\n- Compile-time enum evaluation:\n  ```v syntax-ok\n  $for item in MyEnum.fields {\n      println(item.value)\n      println(item.name)\n  }\n  ```\n- Added `$option` as a compile-time reflection type representing an any Option type.\n- All special compile-time reflection types are now lowercase (`$int`, `$enum`, `$option`, etc).\n\n#### Checker Improvements/Fixes\n\n- Enums can no longer be initialized like structs.\n- Capture variables can no longer shadow anonymous function params.\n- Mixing multi-return results with other types in return statements is no longer allowed.\n- Assigning anonymous structs to named structs is no longer allowed.\n- `[required]` fields are now checked for embedded structs.\n- Fixed a bug with closures with fixed array variables.\n- Builtin methods `first/last/repeat` can now be used in custom user types (previously they only\n  worked in builtin arrays).\n- Generic struct initialization no longer needs explicit types to be provided:\n  ```v syntax-ok\n  struct Foo[T, U] {\n  \ta T\n  \tb U\n  }\n\n  foo := Foo{\n  \ta: 2\n  \tb: 'x'\n  }\n\n  println(foo)\n  ```\n- unsafe: dereferencing nil references is no longer allowed in the following case:\n  ```v syntax-ok\n  a := unsafe { nil }\n  println(*a)\n  ```\n\n#### OSes\n\n- Added basic QNX support.\n\n#### Other changes\n\n- Lots of documentation/readme improvements.\n- Lots of playground improvements: [play.vlang.io](https://play.vlang.io), including a really cool\n  feature: \"Show generated C code\".\n- A new `[spawn_stack: 131072]` function attribute for controlling the max size of the stack of the\n  spawned threads.\n- Channel pop now works with an `or` block: `ch := <-self.item or { return none }`\n- `it` has been renamed to `index` in array inits.\n- \"Is V still fast?\" web-page has been sped up by splitting the result table into multiple years.\n\n#### Development\n\n- GitHub Copilot summaries in PRs.\n\n## V 0.3.3\n\n*30 Jan 2023*\n\n#### Improvements in the language\n\n- String interpolation simplified to just '${name}', enforced by vfmt, and updated in the entire\n  code base.\n- `go foo()` has been replaced with `spawn foo()` (launches an OS thread, `go` will be used for\n  upcoming coroutines instead).\n- vfmt now supports `// vfmt off` and `// vfmt on` for turning off the formatting locally for short\n  snippets of code.\n  Useful for keeping your carefully arranged matrices intact.\n- Match branch range expressions with consts: `match x { const1...const2 {} }`\n- Hot code reloading via `[live]` is now supported in imported modules, not just the main module.\n- Syntax sugar for map inits without needing explicit casts for interfaces:\n  `all.children := { \"abc\": rect, \"def\": ui.rectangle()}`.\n- `$embed_file()` fixes, including variable args support.\n- `none` fixes: no longer allowed to be used as a separate type, `dump()` support, not allowed\n  inside `unsafe`.\n- Const functions: `const y = term.yellow`, then `println(y('abc'))`.\n- Builtin type names can no longer be used as identifiers.\n- Generic `typeof[T]()`, `sizeof[T]()`, `isreftype[T]()` functions.\n- Deprecated `-error-limit` in favour of the documented `-message-limit` option.\n- Maps now support aliased keys.\n- Operator overloading now works with reference types.\n- Generic struct inits with nested generic structs and generic optional types are now allowed.\n- During array creation, `len:` is required when using default values for the array.\n- Optimized one byte `[]u8` arrays creation.\n- Recursive aliasing is no longer allowed (e.g. `type Alias = map[string]Alias`).\n\n#### Breaking changes\n\n- `[]` is now used for generics instead of `<>`.\n- Accessing a pointer map value requires an `or {}` block outside `unsafe`.\n\n#### Checker improvements/fixes\n\n- Lots of fixes in the type checker.\n- Int signedness mismatch is now checked: `cannot use literal signed integer as u8`.\n\n#### Standard library\n\n- `math.vec` module for generic vector math including 2D, 3D, and 4D vector operations.\n- Builtin stb_image.h used by gg has been updated to the latest v2.28.\n- All of vlib has been updated to use separate Option/Result types.\n- To avoid confusion, all references in the code and documentation to `Optional` have been replaced\n  with `Option`.\n- `gg.Context` pipeline has more effects, including the `additive` effect.\n- Much cleaner eof checks in `os`: refactor `err == IError(os.Eof{})` to `err is os.Eof`.\n- Lots of work on `x.json2`, the pure V json encoder, soon to become official.\n- New `v.reflection` module for runtime reflection.\n- Improved `os.mv()`, which now works consistently even across different windows drives/mount\n  points.\n- `string.trim_indent()`, useful with multi line strings, that start/end with new lines and\n  indentation.\n- Reduced memory consumption in the `crypto` modules.\n- Official V UI library is now licensed under MIT.\n- Deprecated `math.util` and `math.mathutil` have been removed.\n- New time format support: `time.format_rfc3339()`.\n- `encoding.html.escape()`.\n- All public functions in the `hash` and `encoding.base32` modules have been documented.\n- New `crypto.pem` module.\n- New `map.reserve()` method.\n\n#### Web\n\n- Improved vweb stability under load.\n\n#### ORM\n\n- Various ORM fixes and improvements, including string interpolation support, type checks, fn calls\n  in `where`.\n\n#### Database drivers\n\n- VFS support in the builtin `sqlite` module; `sqlite.get_affected_rows_count()`.\n- Improved `pg` compatibility with older PostgreSQL versions before 2014.\n- `sqlite`, `pg`, `mysql` have been moved to `db.sqlite`, `db.pg`, `db.mysql`.\n\n#### Native backend\n\n- Operator support for floats, multi return.\n\n#### Comptime\n\n- Improved compile time checks, like `$if x is Type {`;\n  `$if T in [$Array, $Struct, $Alias, $Function] {`.\n- `$for in` works with alias types.\n- New comptime features for fields: `field.is_<field>`, `field.is_alias`, `field.is_enum`.\n\n#### OS support\n\n- Installation instructions for using V on NixOS.\n- Better `make` support for OpenBSD.\n- Much improved experience for `v install pcre` on Windows (it now bundles its own .c files, so it\n  compiles cleanly, even if the platform does not have another pcre package installed).\n- V can now be compiled with tcc on latest macOS and Apple Silicon.\n\n#### Tools\n\n- fast.vlang.io fixes & improvements, new server.\n- New official IntelliJ plugin: https://intellij-v.github.io.\n- Lots of new language documentation, a nicer table of contents.\n- Improved documentation for most of the vlib modules\n- `make.bat` & `v up` improvements on Windows.\n- TeamCity test runner support via `v -test-runner teamcity foo_test.v`.\n- CI optimizations for faster runs.\n- New official AdventOfCode repo with AOC solutions, also added to CI.\n- More detailed timings in `v -show-timings`.\n- `v new <name> web` for quickly scaffolding new web projects.\n\n## V 0.3.2\n\n*31 Oct 2022*\n\n#### Improvements in the language\n\n- New simplified string interpolation: `println(\"Hello, {name}!\")`. It will be the only way, old\n  syntax (`${name}` and `$name`)\n  will be deprecated.\n- Easier custom error creation: `return MyCustomErr{}` instead of `return IError(MyCustomErr)`.\n- All floats outputs now have `.0` conditionally appended to them to improve clarity.\n- Custom integer enum types: `enum Xyz as u64 {`.\n- AST transformer fixes and optimizations.\n- Stylistic improvements and bug fixes in vfmt.\n- Casting integers to enums now requires `unsafe{}`.\n- Improved error and warning messages.\n- Parallel compilation now uses `sync.Pool`.\n- `-skip-unused` fixes, soon to be made the default.\n\n#### Breaking changes\n\n*No breaking changes*\n\n#### Checker improvements/fixes\n\n- Improved type checker: lots of new type checks and fixed checker bugs.\n- Unused last expression in `if` is now checked.\n- Anonymous structs visibility issues fixed.\n\n#### Standard library\n\n- `net.ssl` has been migrated from a dynamically linked OpenSSL to a statically linked Mbed TLS.\n  This means that V binaries will no\n  longer have an OpenSSL dependency. OpenSSL can still be enabled via `-d use_openssl`.\n- msgpack module for decoding/encoding msgpack. (`v install msgpack`)\n- Most of vlib has been updated to use the new Option/Result types.\n- net, net.http, vweb bugs and fixes.\n- QuadTree and RingBuffer types in `datatypes`.\n- Forward iterator for `datatypes.LinkedList<T>`, forward and backward iterators for\n  `datatypes.DoublyLinkedList<T>`.\n- A new `maps` module, similar to existing `arrays`. It has generic `filter`, `flatten`, `invert`,\n  `to_map`, `to_array`, `from_array`\n  functions.\n- `utf8.is_number()`, `utf8.is_space()` functions.\n- New `encoding.base32` module.\n- `gg.TouchPoint` to differentiate between different types of touch input.\n- `str.int()` conversion speedup (without -prod).\n\n#### Web\n\n- `vweb.csrf` module.\n\n#### ORM\n\n- Support parenthesized expressions like\n  `select from User where (name == 'Sam' && is_customer == true) || id == 1`.\n\n#### Native backend\n\n- Lots of native backend improvements, including library calls, comptime conditionals, enums, method\n  definitions/calls, structs.\n\n#### V interpreter\n\n- Some further interpreter work.\n\n#### C backend\n\n- cgen cleanups.\n\n#### OS support\n\n- Removed the need for the `[console]` attribute in Windows GUI apps.\n- More precise WINAPI declarations for easier integration on Windows.\n- More CI tests on FreeBSD.\n\n#### Tools\n\n- New stunning playground with an improved look and feel, a much better and more responsive editor,\n  code sharing by link, more convenient keyboard control, reusability for potential embedding:\n  https://play.vlang.io.\n- Improved call tracing via `-trace-calls`.\n- Lots of documentation improvements, including a better documentation of the recent Option/Result\n  split.\n- V REPL: Home/End keys support. Lots of clean up.\n\n## V 0.3.1\n\n*31 Aug 2022*\n\n#### Improvements in the language\n\n- Anonymous structs.\n- Lots of bug fixes: 90% of all bugs ever submitted are closed.\n- New keyword/type: `nil`. Only to be used inside `unsafe`. Replaces `voidptr(0)`.\n- V can now find code in the `src/` directory. This allows making V repos much cleaner.\n- Support `assert condition, extra_message`, where the `extra_message` will be evaluated and shown\n  if the assertion fails.\n- Operator overloading now works with aliases and generics.\n- Scanner optimizations.\n- Using C's #define is no longer allowed in normal V code, only in `.c.v` files.\n\n#### Breaking changes\n\n- Anonymous sumtypes have been removed (deprecated for now) due to complicating the language and the\n  compiler too much.\n\n#### Checker improvements/fixes\n\n- More type checks.\n- Lots of fixes in `shared` types.\n\n#### Standard library\n\n- `os.mkdir()` now has an optional `mode` parameter.\n- `encoding.csv` is now generic, supports bools, accepts a custom delimiter, and is compatible with\n  io.Reader/io.Writer.\n- `datatypes` module now uses operator overloading.\n- All `datatypes` types can be converted to V arrays.\n- `smtp` improvements including multiple recipients and base64/utf8 support.\n- `arrays.carray_to_varray<T>()` for converting C arrays to V arrays.\n- `strconv.v_sprintf()` has been deprecated in favor of string interpolation.\n- TOML module now supports `[toml:...]` attributes, just like the JSON module.\n- `os.walk()` is no longer recursive (still works the same).\n- `io` has been migrated to `Result`.\n- Third party window control in Sokol.\n- `string.replace_char()`, `math.round_sig()`.\n- Improved multiplication performance in `math.big`.\n\n#### Web\n\n- `net.urllib` ipv6 support.\n- `net.Http.Response.text` renamed to `body`.\n- `net.websocket` timeout is now configurable.\n\n#### ORM\n\n- ORM functions now return `Result`, so the errors can be handled.\n\n#### Database drivers\n\n#### Native backend\n\n- Major improvements to the fast native backend including linking support on Linux. The goal is to\n  be able to self host V soon.\n\n#### V interpreter\n\n- V interpreter improvements.\n\n#### C backend\n\n- Parallelized cc step. Speeds up -prod and clang/gcc compilation by 300-500% (depending on\n  the number of cores). Experimental and hidden behind a -parallel-cc flag, soon to be the default.\n- Intel C compiler support.\n- Go backend fixes.\n- `#preinclude` for low level C interop.\n\n#### OS support\n\n- Full termux support via `$if termux {`, more predictable logging on Android.\n- Older macOS support (<10.12).\n- Windows code has been removed from `v.c` distributed on non-Windows systems. (`v_windows.c` is\n  used on Windows.)\n\n#### Tools\n\n- DOOM is now translated/compiled and launched on CI servers. A screenshot of the running game\n  is made via `vgret` and is compared to the expected result.\n- VLS performance improvements, especially on Windows.\n- `v ls` tool for installing, for updating, and for launching VLS (V Language Server).\n- `v doc` now has syntax highlighting.\n\n## V 0.3\n\n*30 Jun 2022*\n\n- C to V translation via C2V: `v translate file.c`. (Demo\n  video: [Translating DOOM from C to V, building it in under a second and running it!](https://www.youtube.com/watch?v=6oXrz3oRoEg))\n- Lots of bug fixes in V, cgen, and C interop to allow running translated DOOM.v.\n- Programs built with the V compiler no longer leak memory by default.\n- Closures. All operating systems are\n  supported. ([Demo](https://x.com/v_language/status/1528710491882852352))\n- `Option` and `Result` are now separate types: `?Foo` and `!Foo` respectively. Old code will\n  continue working for 1 year and will result in a warning/hint.\n- Hundreds of new checks in the type checker.\n- All V's backends have been split up into separate processes. As the result, building V got 26%\n  faster.\n- Maps and arrays can now return options: `m[bad_key] or { ... }`, `if x := arr[key] { ... }`.\n- `ustring` has been replaced with `[]rune` (works just like in Go).\n- Maps can now have non-string keys.\n- A new compiler pass for transforming the AST (doesn't slow the compiler too much, adds about 25ms\n  to `v self`). It eliminates unreachable branches and performs other simple optimizations and\n  transformations.\n- C backend is now parallel (just the cgen part for now).\n- Lots of compiler source code clean up and minor optimizations. The compiler got ~30% faster\n  according to fast.vlang.io.\n- Better compiler source code organization (absolutely necessary as it's surpassed 100k loc).\n- The naming of V's integer types is now more consistent: `byte` has been renamed to `u8`. Old code\n  will continue working for 1 year and will result in a warning/hint.\n- The typo detector now highlights the suggested name so that it's more visible.\n- `datatypes` module now has `Heap, Queue, Stack, BSTree, LinkedList`.\n- Interfaces can now be embedded (like structs).\n- vlib now has a TOML parser, fully compatible with TOML 1.0.\n- Lots of work done on the V.js backend, including the graphics library, which has been ported to\n  V.js.\n- JS promises, await (V.js).\n- It's now possible to do more complex array initialization by using each individual element of the\n  array (`[]int{init: it}`).\n- Unsigned right shift operators `>>>` and `>>>=` have been added to V. (They work exactly like in\n  Java.)\n- `-nofloat` option, which is useful for writing kernels and for embedded systems without an FPU (\n  used in Vinix).\n- Generic interfaces.\n- TCC is now bundled with the language, this allows building V programs without an external C\n  compiler dependency.\n- Null can be used in `unsafe` only (for example, for C interop).\n- Pointer arithmetic and comparing pointers to numbers is now also only allowed in `unsafe`.\n- Inline sumtypes.\n- New module `compress.gzip`.\n- Lots of `net`/`net.http`/`vweb` fixes (also used for the upcoming Gitly launch).\n- IPv6 support.\n- `net.http` headers are now enum fields instead of strings. This allows to avoid typos and offers\n  autocomplete.\n- Struct field deprecation.\n- Static GC (no longer a dynamic lib dependency).\n- New various algorithms for random number generation: MT19937RNG, etc  (module `rand`).\n- Fix immutability bugs that allowed to bypass compiler immutability checks and modify\n  const/immutable values.\n- Lots of fixes in the JSON serializer.\n- Heap allocated only structs marked with `[heap]`.\n- Significantly improve lots of error messages, make them more clear, suggest hints.\n- Bug fixes and new features in the pure V `regex` module.\n- Lots of new drawing functions in the graphics module (like\n  `gg.draw_polygon_filled(), gg.draw_arc_empty()` etc)\n- Builtin FPS display in `gg`.\n- Latest Sokol backend in `gg`.\n- Advanced CI tests for the graphics module. Graphical apps are run on GitHub Actions instances,\n  their output is saved to an image, uploaded, and compared to the expected result.\n- More bug fixes in generics.\n- Bug fixes in aliases. They can now fully replace the types they alias.\n- `[minify]` struct attribute for struct minification.\n- `for in` now works with fixed arrays.\n- The parser was made a bit faster by skipping `vfmt` code when not in `vfmt` mode (by using\n  `-d vfmt`).\n- Lots of vfmt improvements, especially with comments.\n- Experimental `#[index]` syntax for negative indexing (like in Python, but needs special syntax\n  instead of being used by default).\n- Visibility bug fixes in modules (`pub`).\n- Error propagation in complex expressions (e.g. `foo(bar()?)`).\n- Optionals can now by used in consts (`const x := opt() or {}`).\n- Lots of new documentation, including vlib modules documentation and the official V Documentation.\n- vpm improvements (including a new vpm mirror).\n- `sync` improvements including `sync.thread_id()`, `sync.Once`..\n- V can now be used to generate object files (`foo.o`) that can be used in existing C projects.\n- `-usecache` and `-skip-unused` fixes, they are close to being on by default.\n- Lots of Windows issues fixed.\n- Amazon Linux support.\n- Fixes in shared maps and arrays.\n- `term.ui` improvements, including multi byte/UTF-8 events.\n- New `crypto` modules, including `crypto.des, crypto.cipher, crypto.blowfish`.\n- Comptime fixes.\n- 4 byte bool option (`-d 4bytebool`) for compatibility with some C software.\n- `strconv` (pure V formatting module used in string interpolation) fixes and performance\n  improvements.\n- ORM fixes (pg, mysql, sqlite). Tables are now created automatically based on the V structs, no\n  more need in sql files to create tables for apps.\n- `volatile` keyword.\n- `\"stringliteral\".len` optimization (replaced by the actual number by the new `transform` pass).\n- Lots of inline assembler improvements (it's used a lot in Vinix).\n- Many new functions in the `math` module.\n- Separators in number literals: `1_000_000`.\n- `strings.Builder` optimizations and new methods.\n- Autofree fixes (still not production ready, hidden behind the `-autofree` flag).\n- Lots of Android fixes in V and in vab.\n- Lots of commits to the native backend (amd64/arm64).\n- V interpreter fixes. (Still at an early stage.)\n- Go2V translator has been started by the community, and can already translate simple programs.\n- An early version of the Go backend (`v -b go -o file.go file.v`).\n\n## V 0.2.4\n\n*30 Aug 2021*\n\n- Introduce `isize` and `usize` types, deprecate `size_t` in favor of `usize`.\n- Add `datatypes` and `datatypes.fsm` modules.\n- Add `compile_error` and `compile_warn` comptime functions.\n- Bare metal support. Vinix OS kernel is now being developed in V.\n- Builtin web framework vweb is now multithreaded, all CPU cores are used.\n- String interpolation and struct stringers are now implemented in pure V\n  with a much cleaner and faster implementation. Previously libc's `sprintf`\n  was used.\n- Improved `unused variable` warning. Assigning to a variable no longer marks it as used.\n  *... lots of missing changelog for this version, sorry (will update a bit later)*\n\n## V 0.2.2 - 0.2.3\n\n*22 Jan 2021*\n\n- Allow interfaces to define fields, not just methods.\n- `vweb` now uses struct embedding: `app.vweb.text('hello') => app.text('hello')`.\n- Consts can now be declared outside of `const()` blocks: `const x = 0`.\n- Overloading of  `>`, `<`, `!=`, `==`, `<=` and `>=` operators.\n- New struct updating syntax: `User{ ...u, name: 'new' }` to replace `{ u | name: 'new' }`.\n- `byte.str()` has been fixed and works like all other numbers. `byte.ascii_str()` has been added.\n- Smart cast in for loops: `for mut x is string {}`.\n- `[noinit]` struct attribute to disallow direct struct initialization with `Foo{}`.\n- Array decompose: `[1, 2, 3]...` is now `...[1, 2, 3]`\n- Treating `enum` as `int` and operations on `enum` except `==` and `!=` are removed for strict type\n  checking.\n- Support `[manualfree] fn f1(){}` and `[manualfree] module m1`, for functions doing their own\n  memory management.\n- Allow usage of `<` and `>` operators for struct in `.sort` method for arrays, i.e.\n  `arr.sort(a < b)`.\n- Auto generate assignment operators like `+=`, `-=`, `*=`, `/=` and `%=` if the operators are\n  defined.\n- Colorize and improve failing tests output.\n- Fix `go` with a generic function: `go test<string>(c, 'abcd')`.\n- Add comptime `x := $embed_file('v.png') println(x.len) println(ptr_str(x.data()))`, for embedding\n  files into binaries.\n- Advanced vdoc search on mobile layout.\n- string's `left()`/`right` were removed in favor of slicing syntax: `str[..pos]`.\n- gg: native graphics mode on macOS/iOS (using Cocoa Drawing API).\n- Full path to consts must be specified everywhere. This makes it easy to distinguish them\n  from local variables.\n- `__offsetof` for low level needs (works like `offsetof` in C).\n- vfmt now preserves empty lines, like gofmt.\n- Support for compile time environment variables via `$env('ENV_VAR')`.\n- Allow method declaration of `==` and `<` operators and auto generate `!=`, `>`, `<=` and `>=`.\n- support `dump(expr)`, i.e. tracing of both the location, name and value of an expression\n- deprecate os.exec in favour of os.executable() which does *NOT* return an option, when the command\n  was not found\n\n## V 0.2.1\n\n*30 Dec 2020*\n\n- Hashmap bootstrapping fixes.\n- Array decomposition to varargs: `fn sum(i ...int) int` => `a := [2,3,4] println(sum(a...))`\n- HTML module docs generated by vdoc now have global search.\n\n## V 0.2\n\n*22 Dec 2020*\n\n- Compile-time memory management via `-autofree` (not production ready\n  yet). [Video demonstration](https://www.youtube.com/watch?v=gmB8ea8uLsM).\n- Channels and locks.\n- Thread safe typed arrays via keyword `shared`.\n- Struct embedding.\n- IO streams (`io.Reader`, `io.Writer` etc).\n- A powerful websocket module that conforms to RFC 6455 and passes the Autobahn test suite (498\n  client tests and 249 server tests).\n- The `net` module is now non blocking and is more feature complete providing similar API to Go.\n- V's graphics module now uses Metal/DirectX/OpenGL instead of just OpenGL.\n- V can now run in the browser via WASM and execute V code by translating it to JavaScript:\n  https://v-wasm.now.sh\n- V binaries for Linux/Windows/macOS are now built and deployed automatically via GitHub Actions.\n- Smart casting for sumtypes and interfaces, including complex expressions:\n  `if x.expr is int { println(x.expr + 1) }`.\n- Clean and easy way to sort arrays: `users.sort(a.name > b.name)`.\n- A huge amount of `vfmt` fixes and improvements. It has now reached a point where it can be safely\n  used on any V source file.\n- A new CI job that runs `v fmt -verify` on the entire code base, a new command that makes sure the\n  file/directory\n  has been vfmt'ed. This ensures that all code submitted to the V project is formatted.\n- A new tool `v vet` for analyzing the project and finding potential bugs and errors.\n- A new `term.ui` module for building dynamic terminal UIs with an example editor written in it.\n- Early iOS and Android support.\n- All missing ORM features from the old backend were brought back.\n- Magic `it` variable has been replaced with smart casts (the change is completely handled by vfmt).\n- Cross-compiling to Windows and Linux brought back.\n- C2V can now generate wrappers. Example: https://github.com/medvednikov/libsodium. (C2V will be\n  released by 0.3)\n- C++ compiler support: code, generated by the C backend can now by compiled by C++ compilers.\n- Short generics syntax: `foo(5)` instead of `foo<int>(5)`.\n- Cached modules via `-usecache`. Faster compilation due to not needing to rebuild the entire vlib\n  for\n  each program. Will be enabled by default in 0.2.1.\n- New improved sum types implementation.\n- Lots of errors that happen often during the development cycle were turned into warnings to\n  increase\n  development speed. They are still errors in production builds.\n- Labeled `break` and `continue`.\n- Lots of documentation. The official language documentation grew 3 times in size.\n- `modules.vlang.io` is now generated automatically on every commit.\n- Builtin compile-time JSON serializer now supports `time.Time`.\n- Fixes in type aliases, to make them behave just like the types they alias.\n- `array.contains(element)` is now generic.\n- Lots of improvements in the JS backend and its type system.\n- Simpler and more constinent function arg syntax: `foo(a int, b int, c string)` instead of\n  `foo(a, b int, c string)`\n- Lots of fixes and optimizations in the hashmap.\n- Lots of missing checks in the type checker were added (for example, checking the correct usage of\n  public struct fields).\n- Mutability bug fixes\n- Taking the address of a map value is no longer allowed, like in Go.\n- Matrix multiplication.\n- A new `#pkgconfig` flag to provide platform independent way to get compilation flags for C\n  libraries/packages.\n- Explicit parentheses requirement in complex boolean expressions.\n- `println` was made even smarter, and can now handle complex types.\n- Precompiled text templates can now be used outside of vweb via `$tmpl()`.\n- Gitly, a big web application written in vweb has been released: https://github.com/vlang/gitly\n- `['/:arg1/:arg2/action']` vweb action attribute for easily getting query parameters assigned to\n  method arguments.\n- Improved performance of text rendering, `gg.text_width()`.\n- Webview module in V UI.\n- Binary enum flags.\n- `[export]` attribute to change exported function name (for example for calling from a C library).\n- `unsafe` fixes and improvements.\n- Improvements to rand: `rand.ulid()`, `rand.uuid()`, a unified customizable PRNG API.\n- Hundreds of other fixes, features, and tests (from now on the changelog will be updated\n  right away as the feature/bug fix lands).\n\n## V 0.1.27\n\n*5 May 2020*\n\n- vfmt has been re-written from scratch using the new AST parser.\n  It's much faster, cleaner, and can format\n  files with compilation errors.\n- `strconv`, `sprintf`, and `printf` in native V, without any libc calls.\n- Interfaces are now a lot more stable and have all expected features.\n- Lots of x64 backend improvements: function calls, if expressions, for loops, local variables.\n- `map()` and `filter()` methods can now be chained.\n- New `[]int{cap:cap, len:len}` syntax for initializing array length and capacity.\n- New `is` keyword for checking the type of sum types and interfaces.\n- `as` can now be used to cast interfaces and sum types.\n- Profiling with `-profile`. Prints a nice table with details about every single function call:\n  number of calls, average time per call, total time per function\n- `import(xxx)` syntax has been removed in favor of `import xxx` for simplicity and greppability.\n- Lots of fixes and improvements in the type checker.\n- `time.StopWatch`\n- `dl` module for dynamic loading.\n- Automatic `str()` method generation for every single type, including all arrays.\n- Short struct initialization syntax for imitating named function args: `foo(bar:0, baz:1)`.\n- New operator `!in`.\n- Performance improvements in critical parts of the builtin data structures (array, map).\n- High order functions improvements (functions can now be returned etc).\n- Anonymous functions that can be defined inside other functions.\n- Built-in JSON module is back.\n- Lots and lots of new tests added, including output tests that test error messages.\n- Multiple errors are now printed, the compiler no longer stops after the first error.\n- The new JS backend using the AST parser (almost complete).\n- Variadic functions.\n- `net.websocket` module (early stage).\n- `vlib` is now memory leak free, lots of `autofree` improvements.\n- Simplified and cleaned up `cmd/v`, `v.builder`.\n- V UI was updated to work with the new backend.\n\n## V 0.1.25\n\n*1 Apr 2020*\n\n- The entire compiler has been re-written with an AST parser.\n  The code is now a lot cleaner and more maintainable.\n  ~15k lines of old compiler code were removed.\n\n## V 0.1.24\n\n*31 Dec 2019*\n\n- A new parser/generator built on top of an AST that simplifies code greatly\n  and allows to implement new backends much faster.\n- Sum types (`type Expr = IfExpr | MatchExpr | IntegerLiteral`).\n- B-tree map (sped up the V compiler by ~10%).\n- `v fmt -w`.\n- The entire code base has been formatted with vfmt.\n- Generic structs.\n- SDL module.\n- Arrays of pointers.\n- os: `is_link()`, `is_dir()`, `exists()`.\n- Ranging through fixed size arrays.\n- Lots of fixes in ORM and vweb.\n- The first\n  tutorial: [building a simple web application with vweb](https://github.com/vlang/v/blob/master/tutorials/building_a_simple_web_blog_with_vweb/README.md)\n- Match expressions now must be exhaustive.\n- freestanding: `malloc()`/`free()`.\n- `++` is now required instead of `+= 1` for consistency.\n- Interpolated strings now allow function calls: `println('val = $get_val()')`.\n- `string.replace_each([])` for an efficient replacement of multiple values.\n- More utf8 helper functions.\n- `-prealloc` option for block allocations.\n- `type` aliases.\n- Running `v` with an unknown command will result in an error.\n- `atof` implementation in pure V.\n- Enums can now have negative values.\n- New `filepath` module.\n- `math.factorial`.\n- `ftp` module.\n- New syntax for casting: `val as Type`.\n- Fewer libc functions used (soon V will have no dependency on libc).\n\n## V 0.1.23\n\n*30 Nov 2019*\n\n- [Direct x64 machine code generation](https://github.com/vlang/v/issues/2849).\n  Hello world being built in 3 milliseconds.\n- Bare metal support via the `-freestanding` flag, to build programs without linking to libc.\n- Prebuilt V packages for Linux, macOS, and Windows.\n- `string.index()` now returns `?int` instead of `int/-1`.\n- Lots of fixes in Generics.\n- vweb framework for developing web applications is back.\n- Vorum, the forum/blogging software written in vweb, can now be compiled and has been added to CI.\n- REPL, `v up` have been split up into separate applications to keep the core V compiler small.\n- V now enforces short enum syntax (`.green` instead of `Color.green`) when it's enough.\n- V UI for macOS.\n- Interfaces have been rewritten. `[]interface` support.\n- `os.cp()` for copying files and directories.\n- Additional compile-time flags: `$if clang, msvc, mingw, x32, x64, big_endian, little_endian {`.\n- All C functions now have to be declared, all missing C functions have been defined.\n- Global variables (only with the `-enable-globals` flag)\n  for low level applications like kernels and drivers.\n- Nothing can be cast to bool (previously code like `if bool(1) {` worked).\n- `<<` and `>>` now work with all integer types.\n- V detects Cygwin and shows an error (V supports Windows natively).\n- Improved type checking of some operators (`%, |, &` etc).\n- Windows 7 support.\n- `println(true)` now prints `true` instead of `1`.\n- `os.exec()` now uses `CreateProcess` on Windows.\n- fast.vlang.io website for monitoring the performance of V after every commit.\n- On Windows Visual Studio is now used automatically if GCC is not installed.\n- vfmt!\n- Lots of cleaning up in the compiler code.\n- Multi-level pointers in unsafe code (`****int`).\n- MSVC backtrace.\n- `$if os {` blocks are now skipped on a different OS.\n- C string literals (`c'hello'`).\n- AlpineLinux/musl fixes + added to CI.\n- Inline assembly.\n- Clipboard module (Windows, macOS, X).\n- `foo()?` syntax for error propagation.\n- Docs have been migrated from HTML to `doc/docs.md`.\n- `eventbus` module.\n- Haiku OS support.\n- `malloc/free` on bare metal.\n- `utf8` helper functions (`to_lower()`, `to_upper()`, etc).\n- Optimization of `for c in str {`.\n- `string/array.left/right/slice/substr` were removed (use `[a..b]` slicing syntax instead).\n\n## V 0.1.22\n\n*28 Oct 2019*\n\n- Generic functions (`fn foo<T>(bar T) T {`) with varargs support.\n- `array[start..end]` and `string[start..end]` slicing syntax.\n- Optimized `array.filter()` and `array.map()`.\n- `sqlite` module.\n- Cached modules for faster compilation.\n- Dramatic compilation\n  optimizations: [V now compiles itself in 0.10 - 0.30 seconds](https://github.com/vlang/v/wiki/The-V-language-now-compiles-itself-in-0.09-seconds)\n- V scripts (simpler and cross-platform alternative to Bash).\n- Infinite multi-dimensional arrays (`[][][]int`).\n- `unsafe`.\n- `[deprecated]` attribute.\n- `[if]` function attributes for compile time function exclusion for performance.\n- `switch` has been completely removed from the language and replaced by\n  `match` everywhere.\n- `pub struct` and `pub const`, previously all structs and consts were public\n  by default.\n- `musl` support (V can now run on, for example, Alpine Linux).\n- Module header generation. V now supports closed source modules, which are still\n  used in some industries.\n- Constants were added to typo suggestions.\n- `color in [.green, .red, .blue]` now works without specifying `Color.green`.\n- V compiler is now a module that can be used by other programs.\n- Backtraces now have source lines on Linux.\n- `runtime.nr_cpus()`.\n- `fn init()` for module initialization.\n- `a in [1, 2, 3]` optimization: no array gets allocated.\n- Raw strings: `s := r'hello\\nworld'`.\n- `if a := func() { }` syntax for handling options.\n- f32/f64 comparison now uses machine epsilon by default.\n\n## V 0.1.21\n\n*30 Sep 2019*\n\n- `none` keyword for options.\n- Solaris support.\n- All table lookup functions now use `none`.\n- varargs: `fn foo(bar int, params ...string) {`.\n- Double quotes (`\"`) can now also be used to denote strings.\n- GitHub Actions CI in addition to Travis.\n- `-compress` option. The V binary built with `-compress` is only ~90 KB!\n- More memory management.\n- Unused modules result in an error.\n- \"Unused variable/module\" errors are now warnings in non-production builds.\n- Duplicate methods with the same name can no longer be defined.\n- Struct names must be capitalized, variable/function names must use snake_case.\n- Error messages are now even nicer!\n- Lots of fixes in automatic `.str()` method generation for structs and arrays.\n- ~30% faster parser (files are no longer parsed separately for each pass).\n- `_` is no longer a variable, but an actual syntax construct to skip unused values, like in Go.\n- Multiple returns (`fn foo() (int, string) {`).\n- `!` can now only be used with booleans.\n\n## V 0.1.20\n\n*17 Sep 2019*\n\n- JavaScript backend!\n- Hundreds of C warnings were fixed. `gcc v.c` now builds without\n  any warnings.\n- The mutability check now applies to function args (mutable\n  receivers that are not modified result in a compilation error).\n- V tests now show how long each test took.\n- Official Android support (only console applications via Termux for now).\n- Typo check. If a variable/function/module etc is misspelled,\n  V will suggest the correct name.\n- Lots of Microsoft C fixes, and a separate Travis instance for\n  this backend.\n- Bitwise operators `|`, `^`, `&` no longer work with booleans.\n\n## V 0.1.19\n\n*12 Sep 2019*\n\n- Lots of refactoring, simplifications, and optimizations in the compiler.\n- Experimental memory management at compilation (only for the V compiler itself for now).\n- Lots of ORM fixes.\n- Functions can now be inlined via the `[inline]` attribute.\n- New `mysql` module.\n- Better error format that is supported by all major editors (go to error).\n- Error messages now point to the actual place where the error happened.\n- Custom json field names: `struct User { last_name string [json:lastName] }`.\n- Raw json fields via the `[raw]` attribute.\n- All C code was removed from the `freetype` module.\n- `gg` module can now render all Unicode characters.\n- `[typedef]` attribute for imported C struct typedefs.\n- Support of Objective C interfaces (primarily for using Cocoa).\n- REPL: clear command and custom functions.\n- REPL tests (which are also used for testing certain compiler errors).\n- Syntax bug fixed: `foo[0] += 10` is now possible.\n- http: support plain HTTP protocol and follow redirects.\n- http: header data is now processed correctly.\n- net: basic UDP support.\n- `import const` was removed from the language.\n- `array.contains()` was removed from the language (`in` should be used instead).\n- `[0; len]` syntax was removed (replaced with a simpler `[0].repeat(len)`)\n- Primitive aliases were removed to simplify the language.\n- GitHub supports V now!\n- Backtraces are now printed on panics.\n- A new awesome `readline` module.\n- V.c is now regenerated automatically after every commit.\n- A bug with struct ordering was fixed, now structs can be declared in any order.\n- V modules can now be built with `v build module`.\n- `@FILE, @LINE, @FN, @COLUMN` for debugging.\n\n## V 0.1.18\n\n*16 Aug 2019*\n\n- Built-in ORM (`uk_customers = db.select from Customer where country == 'uk' && nr_orders > 0`).\n- Map initialization syntax: `m := { ‘foo’: ‘bar’, ‘baz’: ‘foo’ }`.\n- `map.delete(key)`.\n- `libcurl` dependency was removed from the `http` module.\n- All function arguments are now immutable by default (previously they could be\n  modified inside the function).\n- `http` functions now return options.\n- `sync.WaitGroup`.\n- `vweb` static files serving.\n- `crypto.rand` module.\n- `v up` to update V.\n- SChannel support on Windows.\n- `net.urllib` module.\n- vpm package manager, `v install`.\n- `()` are now required in complex bool expressions: `(a && b) || c` instead of `a && b || c`.\n- All arrays now have a default `.str()` method.\n- Bootstrapping V with MSVC.\n- Experimental `≠` etc support.\n- `encoding.csv` module.\n- `$if debug {` for running code in debug mode only.\n- Map struct fields are now initialized automatically, just like arrays.\n- Maps now support array values.\n- `json` functions can no longer be used if the `json` module is not imported.\n\n## V 0.1.17\n\n*29 Jul 2019*\n\n- `vweb` module for developing web apps in V.\n- vtalk, open source V forum software.\n- Generics (very limited right now, but they will be gradually improved).\n- Comptime codegen (`foo.$method()` where `method` is a string).\n- `@` for escaping keywords (e.g. `struct Foo { @type string }`).\n- Windows Unicode fixes (V can now work with non-ASCII paths etc on Windows).\n- Fix mutable args bugs + don't allow primitive arguments to be modified.\n- Declaring a mutable variable and never modifying it results in a compilation error.\n- Interactive debugging support.\n- `sync` module for Windows.\n- `#!` support on Unix systems (V scripts).\n- Lots of Visual Studio fixes.\n- `crypto.aes` and `crypto.rc4` modules.\n- Internal modules.\n\n## V 0.1.16\n\n*23 Jul 2019*\n\n- V can now be used with Visual Studio!\n- Hot code reloading now works with graphical applications (e.g. graph.v, bounce.v).\n- Compile time memory management for arrays.\n- High order functions.\n- `match` expression (replacing `switch`).\n- Import cycle detection.\n- `crypto/md5`, `crypto/sha256`, and `crypro/sha512` modules.\n- `os.executable()` - a cross platform function that returns full path to current executable.\n- `~/.vlang` and `VROOT` were removed entirely. The installation is a lot cleaner now.\n- V can now be packaged for all Linux distros.\n- Arch Linux package.\n- `string(bytes_buffer, len)`, `string(bytes_array)` casts.\n- Multiple `defer`s.\n- `key in map` syntax (replacing `map.exists(key)`).\n\n## V 0.1.15\n\n*15 Jul 2019*\n\n- FreeBSD, OpenBSD, NetBSD, DragonFly support.\n- Hot reloading now works with graphical applications: [bounce.v](examples/hot_reload/bounce.v)\n- VROOT was removed, the installation process is now much simpler.\n- `defer` statement.\n- map.v was re-written. It's now much faster.\n- `for key, val in map` syntax.\n- `flag` module for parsing command line arguments.\n- `zip` module.\n- `crypto/sha1` module.\n- Submodules and module aliases (`import encoding.base64 as b64`).\n\n## V 0.1.14\n\n*12 Jul 2019*\n\n- `gg` module Windows support, V Tetris runs on Windows.\n- Compile `glad` and `cJSON` only once. Programs using `gg` or `json` compile a bit faster.\n- `v.c` has been cleaned up and minimized (~16k => ~10k lines of code).\n- `type` aliases can now have methods.\n- Const overflow check during compilation (`byte(1000)` will no longer compile).\n\n## V 0.1.13\n\n*10 Jul 2019*\n\n- New enum syntax (`token == .name`), enum values are no longer global consts.\n- Submodules (`import encoding.base64`).\n- Hot code reloading.\n- Special `err` variable for getting error values.\n- Complex numbers.\n- `<<` can now append arrays (`numbers << [1, 2, 3]`).\n- Lots of Windows fixes (Windows still needs some work).\n- Lots of REPL improvements (e.g. `>> 2 + 3` works now, no `println` required).\n- The website was made easily translatable, it's now partially available in several languages.\n\n## V 0.1.12\n\n*4 Jul 2019*\n\n- V can finally compile itself on Windows (https://github.com/vlang/v#mingw-w64).\n- `os` module now uses options in all functions that return `File`.\n- Lots of bugs with options were fixed.\n- `println` was optimized. It no longer results in allocations.\n  Now it also works correctly with all integer types.\n- Lots of `vfmt` fixes, it will be enabled tomorrow.\n- New `strings` module.\n- Lots of other fixes and improvements, thanks to all the contributors.\n\n## V 0.1.11\n\n*1 Jul 2019*\n\n- Cross compilation for Windows!\n- Lots of Windows fixes.\n- socket.v.\n- maps fixed.\n\n## V 0.1.9 - 0.1.10\n\n*29 Jun 2019*\n\n- Windows support via MinGW-w64. Pre-built Windows binary.\n- File structure has been simplified: all vlib modules were moved to the vlib/ directory,\n  makefile was moved to the root.\n- One single archive with pre-built binaries for all operating systems.\n- `mut var := val` was fixed (previously `mut var = val` was allowed as well).\n\n## V 0.1.8\n\n*28 Jun 2019*\n\n- Single file programs without `fn main` now work as expected.\n- REPL has been fixed: it now supports imports, consts, function definitions, etc.\n\n## V 0.1.7\n\n*27 Jun 2019*\n\n- All C code in the compiler and vlib has been replaced with V.\n- `#` syntax for embedding C code has been removed.\n- Exported functions now need to be marked with `pub`, all public vlib functions have been updated.\n- CI has been set up (Travis + Azure). On every commit and PR it is made sure that V\n  can compile itself, all tests pass, and all examples compile.\n- More tests have been uploaded.\n- Cleaner bytes to string conversion: `tos2(bytes)` => `string(bytes)`.\n- The home page has 3 more examples next to 'hello world' that show the features of the language.\n- Lots of bugs and issues fixed.\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Code of Conduct\n\nBe nice and respectful.\n\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "## How to help and contribute to the V project\n\nThe tasks in the lists below are ordered in terms of easiness/time/nerves\ninvestment.\n\n### Starting tasks\n0. Run `v quest` once (or several times a day) to gain XP.\n\n1. Read the [language documentation](https://docs.vlang.io/introduction.html) and [standard module documentation](https://modules.vlang.io/).\n\n2. Fix doc errors and places you found unclear, and make [PRs](https://github.com/vlang/v/pulls) about it.\n\n3. Make V programs, in the areas that you are interested in, or help others make\n   V programs. If the programs/libraries are public, post them to the channel\n   `#showcase-discussion` on [Discord](https://discord.gg/vlang) and/or to\n   [awesome-v](https://github.com/vlang/awesome-v). You can also answer other\n   people's questions in Discord channels `#help` or `#v-chat`, or in\n   [github's discussions page](https://github.com/vlang/v/discussions).\n\n4. Read the new issues in the tracker.\n\n5. Try to reproduce them on your system, and comment in the issues, with the\n   results.\n\n6. Read the PRs, try to spot errors in them, and comment about them.\n\n### Medium tasks (after gathering experience with 1..6)\n\n7. Make PRs, with bug fixes to existing issues (found doing 1..6).\n\n8. Suggest new features, tools, or modifications to the existing ones here,\n   based on the experience, that you gathered doing 1..7.\n\n9. Make PRs with implementations of your suggestions, or based on other people's\n   suggestions, based on 1..7 and the feedback from 8.\n\n### Advanced tasks (after doing 1..9 for a while)\n\n10. Work on [V RFCs](https://github.com/vlang/rfcs/) (submitting new ones,\n    providing feedback to existing ones, implementing them).\n\n## Code Structure\n\nI tried to make the code of the compiler and vlib as simple and readable as\npossible. One of V's goals is to be open to developers with different levels\nof experience in compiler development. Compilers don't need to be black boxes\nfull of magic that only few people understand.\n\nThe V compiler is modular, and can be used by other applications. It is located\nin `cmd/v/` and `vlib/v/`.\n\nThe most important and useful command to remember when working on the V compiler\nis `v self`.\nIt rebuilds the V compiler.\n\nBe careful, if you introduce a breaking change and rebuild V, you will no longer\nbe able to use V to build itself. So it's a good idea to make a backup copy of a\nworking compiler executable.\n\nBut don't worry, you can always simply run `make` (or `make.bat`), it will\ndownload the C version of the compiler and rebuild it from scratch.\n\nThe architecture of the compiler is very simple and has three distinct steps:\n\nParse/generate AST (`v.parser`) => Check types (`v.checker`)\n=> Generate C/JavaScript/machine code (`v.gen`)\n\nThe main files are:\n\n1. `cmd/v/v.v` The entry point.\n\n   - V figures out the build mode.\n   - Constructs the compiler object (`struct V`).\n   - Creates a list of .v files that need to be parsed.\n   - Creates a parser object for each file and runs `parse()` on them.\n   - The correct backend is called (C, JS, native), and a binary is compiled.\n\n2. `vlib/v/scanner` The scanner's job is to parse a list of characters and convert\n   them to tokens.\n\n3. `vlib/v/token` This is simply a list of all tokens, their string values, and a\n   couple of helper functions.\n\n4. `vlib/v/parser` The parser. It converts a list of tokens into an AST.\n   In V, objects can be used before declaration, so unknown types are marked as\n   unresolved. They are resolved later in the type checker.\n\n5. `vlib/v/table` V creates one table object that is shared by all parsers. It\n   contains all types, consts, and functions, as well as several helpers to search\n   for objects by name, register new objects, modify types' fields, etc.\n\n6. `vlib/v/checker` Type checker and resolver. It processes the AST and makes sure\n   the types are correct. Unresolved types are resolved, type information is added\n   to the AST.\n\n7. `vlib/v/gen/c` C backend. It simply walks the AST and generates C code that can be\n   compiled with Clang, GCC, Visual Studio, and TCC.\n\n8. `vlib/v/gen/js` JavaScript backend. It simply walks the AST and generates JS code that can be\n   executed on the browser or in NodeJS/Deno.\n\n9. `vlib/v/gen/c/json.v` defines the json code generation. This file will be removed once V\n   supports comptime code generation, and it will be possible to do this using the\n   language's tools.\n\n10. `vlib/v/gen/native` is the directory with all the machine code generation logic. It\n    defines a set of functions that translate assembly instructions to machine code\n    and build the binary from scratch byte by byte. It manually builds all headers,\n    segments, sections, symtable, relocations, etc. Right now it only has basic\n    support of the native platform (ELF, MACHO format).\n\nThe rest of the directories are vlib modules: `builtin/` (strings, arrays,\nmaps), `time/`, `os/`, etc. Their documentation is pretty clear.\n\n## Example Workflow for Contributing\n\n(provided by [@spytheman](https://github.com/spytheman))\n\n(If you don't already have a GitHub account, please create one. Your GitHub\nusername will be referred to later as 'YOUR_GITHUB_USERNAME'. Change it\naccordingly in the steps below.)\n\n1. Fork https://github.com/vlang/v using GitHub's interface to your own account.\n   Let's say that the forked repository is at\n   `https://github.com/YOUR_GITHUB_USERNAME/v` .\n2. Clone the main v repository https://github.com/vlang/v to a local folder on\n   your computer, say named nv/ (`git clone --depth=1 https://github.com/vlang/v nv`)\n3. `cd nv`\n   3.1 (optional) Run these commands, which ensure that all your code will be\n   automatically formatted, before committing:\n   ```\n   cp cmd/tools/git_pre_commit_hook.vsh .git/hooks/pre-commit\n   chmod 755 .git/hooks/pre-commit\n   ```\n   It has to be done in a shell where you have done cd /root/of/your/V_repo once.\n   Step 3 above does it with `cd nv`.\n   I.e. you have to be in the top level folder, that contains the .git folder for the V repository.\n   \n4. `git remote add pullrequest https://github.com/YOUR_GITHUB_USERNAME/v`\n\n   Note: The remote named `pullrequest` should point to YOUR own forked repo, not the\n   main v repository! After this, your local cloned repository is prepared for\n   making pull requests, and you can just do normal git operations such as:\n   `git pull` `git status` and so on.\n\n5. When finished with a feature/bugfix/change, you can:\n   `git checkout -b fix_alabala`\n   - Don't forget to keep formatting standards, run `v fmt -w YOUR_MODIFIED_FILES`\n     before committing (if you have not run the commands from 3.1)\n   - If you changed Markdown (`.md`) files, check them `v check-md YOUR_MODIFIED_FILES`\n     before committing.\n6. `git push pullrequest` Note: The `pullrequest` remote was setup on step 4\n\n7. On GitHub's web interface, go to: https://github.com/vlang/v/pulls\n\n   Here the UI shows a dialog with a button to make a new pull request based on\n   the new pushed branch.\n   (Example dialog: https://url4e.com/gyazo/images/364edc04.png)\n\n8. After making your pull request (aka, PR), you can continue to work on the\n   branch `fix_alabala` ... just do again `git push pullrequest` when you have more\n   commits.\n\n9. If there are merge conflicts, or a branch lags too much behind V's master,\n   you can do the following:\n\n   1. `git pull --rebase origin master` # solve conflicts and do\n      `git rebase --continue`\n   2. `git push pullrequest -f` # this will overwrite your current remote branch\n      with the updated version of your changes.\n\nThe point of doing the above steps, is to never directly push to the main V\nrepository, *only to your own fork*. Since your local `master` branch tracks the\nmain V repository's master, then `git checkout master`, as well as\n`git pull --rebase origin master` will continue to work as expected\n(these are actually used by `v up`) and git can always do it cleanly.\n\nGit is very flexible, so there are other ways to accomplish the same thing.\nSee the [GitHub flow](https://guides.github.com/introduction/git-handbook/#github), for more\ninformation.\n\n## Finding issues to contribute to\n\nIf you're willing to contribute to V but don't know which issue to resolve\n\n- you can go to [Issues](https://github.com/vlang/v/issues) tab\n  in this repository. There you can see things logged by both users and developers\n  that need to be discussed and/or resolved.\n\nIt's recommended to filter issues by likes and labels to find an issue\nyou are interested in.\n\n### Filtering by likes (recommended)\n\nFiltering by likes helps you identify high-impact issues.\nMore likes mean more community interest.\n\nTo quickly use this filter, click [there](https://github.com/vlang/v/issues?q=is%3Aopen+is%3Aissue+sort%3Areactions-%2B1-desc).\n\nTo manually apply this filter, navigate to [Issues](https://github.com/vlang/v/issues)\ntab, then paste the following in the \"Filter\" field:\n\n```\nis:open is:issue sort:reactions-+1-desc\n```\n\nThis filter will return all open issues sorted by likes in descending order.\n\n### Filtering by labels\n\nThe V repo has various labels to help navigate the extensive list of issues\nand help you find issues you're both interested in and capable of resolving.\nYou can examine the list of labels [here](https://github.com/vlang/v/labels).\n\nThe most common labels are:\n\nBy issue type:\n\n- `Bug`\n- `Feature Request`\n\nBy OS:\n\n- `OS: Linux`\n- `OS: Windows`\n- `OS: Mac`\n\nBy status:\n\n- `Status: Confirmed`\n\nTo apply this filter, navigate to [Issues](https://github.com/vlang/v/issues)\ntab, then paste the following in the \"Filter\" field:\n\n```\nis:open is:issue label:Bug label:\"OS: Windows\" label:\"Status: Confirmed\"\n```\n\nThis filter will return all open issues with the labels `Bug`, `OS: Windows`,\nand `Status: Confirmed`.\n\n## Using Github's hub CLI tool\n\nYou can download the `hub` tool from https://hub.github.com/ . Using\n`hub`, you will not need to go through the (sometimes) slow website\nto make PRs. Most remote operations can be done through the `hub` CLI\ncommand.\n\n> [!NOTE]\n> You still need to have a GitHub account.\n\n### Preparation:\n\n(steps 1..3 need to be done just *once*):\n\n1. `hub clone vlang/v my_v`\n2. `cd my_v`\n   2.1 (optional) Run these commands, which ensure that all your code will be\n   automatically formatted, before committing:\n   ```\n   cp cmd/tools/git_pre_commit_hook.vsh .git/hooks/pre-commit\n   chmod 755 .git/hooks/pre-commit\n   ```\n3. `hub fork --remote-name pullrequest`\n\n4. `git checkout -b my_cool_feature` # Step 4 is better done *once per each new\n   feature/bugfix* that you make.\n\n### Improve V by making commits:\n\n5. `git commit -am \"math: add a new function copysign\"`\n\n### Testing your commits locally:\n\nYou can test locally whether your changes have not broken something by\nrunning: `v test-all`. See `TESTS.md` for more details.\n\n### Publishing your commits to GitHub:\n\n6. `git push pullrequest`\n\n### Making a PR with `hub`:\n\n(so that your changes can be merged to the main V repository)\n\n7. `hub pull-request`\n\nOptionally, you can track the status of your PR CI tests with:\n\n8. `hub ci-status --verbose`\n\n### Fixing failing tests:\n\nIf everything is OK, after 5-10 minutes, the CI tests should pass for\nall platforms. If not, visit the URLs for the failing CI jobs, see\nwhich tests have failed and then fix them by making more changes. Just use\n`git push pullrequest` to publish your changes. The CI tests will\nrun with your updated code. Use `hub ci-status --verbose` to monitor\ntheir status.\n\n## Compiler flags, useful while debugging the compiler itself:\n\nV allows you to pass custom flags using `-d my_flag` that can then be checked\nat compile time (see the documentation about\n[compile-time if](https://github.com/vlang/v/blob/master/doc/docs.md#compile-time-if)).\n\nSince the compiler is *also* an ordinary V program, there are numerous flags that can be\npassed when building the compiler itself with `v self`, or when creating a copy of the\ncompiler, that will help you when debugging the compiler.\n\nNote: beware that the flags below must be passed, when building the compiler, *not the program*,\nso do for example:\n`./v -o w -d time_parsing cmd/v`\nor\n`./v -o w -d trace_checker self`\n... then use `./w file.v`, instead of `./v file.v`, to compile your program.\n\nNote: some of the flags can make the compiler *very verbose*, so it is recommended to create\na copy of the compiler rather than replacing it with `v self`.\n\n| Flag                              | Usage                                                                                                               |\n|-----------------------------------|---------------------------------------------------------------------------------------------------------------------|\n| `debug_codegen`                   | Prints automatically generated V code during the scanning phase                                                     |\n| `debug_interface_table`           | Prints generated interfaces during C generation                                                                     |\n| `debug_interface_type_implements` | Prints debug information when checking that a type implements in interface                                          |\n| `print_vweb_template_expansions`  | Prints vweb compiled HTML files                                                                                     |\n| `time_checking`                   | Prints the time spent checking files and other related information                                                  |\n| `time_parsing`                    | Prints the time spent parsing files and other related information                                                   |\n|                                   |                                                                                                                     |\n| `trace_scanner`                   | Prints details about the recognized tokens. *Very* verbose. Use with `./vnew -no-builtin -check-syntax file.v` .    |\n| `trace_parse`                     | Prints details about the parsed files (number of tokens, lines, bytes). Use it for parsing order issues.            |\n| `trace_parser`                    | Prints details about parsed statements and expressions. Very verbose. Use it for panics in the parser.              |\n| `trace_check`                     | Prints the .v file which is checked. Use it to diagnose checker order issues.                                       |\n| `trace_checker`                   | Prints details about the statements being checked. Very verbose. Use it for panics in the checker.                  |\n| `trace_transformer`               | Prints details about the statements being transformed. Very verbose. Use it for panics in the transformer stage.    |\n|                                   |                                                                                                                     |\n| `trace_gen`                       | Prints all the strings written to the generated C file. Very verbose.                                               |\n| `trace_gen_wanted_value`          | Prints a backtrace, when a specific *wanted* value, is part of what is printed in the generated C file.             |\n|                                   |        Use: `v -g -o vgen -d trace_gen_wanted -d trace_gen_wanted_value=\"message = _SLIT0\" cmd/v && ./vgen bug.v`   |\n| `trace_cgen`                      | Prints the .v file for which C code generation runs. Use it to diagnose cgen order issues.                          |\n| `trace_cgen_stmt`                 | Prints details about the statements that are being processed by cgen.                                               |\n|                                   |        Use it for panics in cgen, to see the closest input V source line, that caused the panic.                    |\n|                                   |        Note: you need `v -no-parallel -d trace_cgen_stmt -o w cmd/v` to make sense of the output of that,           |\n|                                   |        otherwise by default cgen uses several threads, and the lines that are printed are out of order.             |\n|                                   |                                                                                                                     |\n| `trace_autofree`                  | Prints details about how/when -autofree puts free() calls                                                           |\n| `trace_autostr`                   | Prints details about `.str()` method auto-generated by the compiler during C generation                             |\n|                                   |                                                                                                                     |\n| `trace_ccoptions`                 | Prints options passed down to the C compiler                                                                        |\n|                                   |                                                                                                                     |\n| `trace_thirdparty_obj_files`      | Prints details about built thirdparty obj files                                                                     |\n| `trace_usecache`                  | Prints details when -usecache is used                                                                               |\n| `trace_embed_file`                | Prints details when $embed_file is used                                                                             |\n| `embed_only_metadata`             | Embed only the metadata for the file(s) with `$embed_file('somefile')`; faster; for development, *not* distribution |\n|-----------------------------------|---------------------------------------------------------------------------------------------------------------------|\n"
  },
  {
    "path": "Dockerfile",
    "content": "#same container that golang use\nFROM buildpack-deps:buster-curl\n\nLABEL maintainer=\"ANAGO Ronnel <anagoandy@gmail.com>\"\nWORKDIR /opt/vlang\n\nARG USE_LOCAL\n\nRUN apt update && \\\n    DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends gcc clang make git binutils && \\\n    apt clean && rm -rf /var/cache/apt/archives/* && \\\n    rm -rf /var/lib/apt/lists/*\n\nCOPY . /vlang-local\n\nRUN if [ -z \"${USE_LOCAL}\" ] ; then \\\n      git clone --depth=1 https://github.com/vlang/v /opt/vlang && \\\n      rm -rf /vlang-local ; \\\n    else \\\n      mv /vlang-local/* . && \\\n      rm -rf /vlang-local ; \\\n    fi\n\nRUN make && \\\n    ln -s /opt/vlang/v /usr/local/bin/v\n\nCMD [ \"v\" ]\n"
  },
  {
    "path": "Dockerfile.alpine",
    "content": "## Usage:\n##   1) docker build -t vlang_alpine - < Dockerfile.alpine\n##   2) alias with_alpine='docker run -u 1000:1000 --rm -it -v .:/src -w /src vlang_alpine:latest'\nFROM alpine:3.23.3\nLABEL maintainer=\"spytheman <spytheman@bulsynt.org>\"\nWORKDIR /opt/vlang\nENV PATH=/opt/vlang:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n\n## install development packages\nRUN apk --no-cache add \\\n  musl-dev libc-dev libc6-compat gcompat \\\n  openssl-dev sqlite-dev mbedtls \\\n  libuv-dev libev-dev libevent-dev libmemcached-dev \\\n  binutils diffutils elfutils pcre strace rsync \\\n  libunwind-dev libunwind-static gc gc-dev \\\n  make bash file git upx tmux micro nano nano-syntax \\\n  gcc gdb wasi-sdk \\\n  mesa-dev mesa-gl mesa-gles \\\n  glfw-dev \\\n  glu-dev \\\n  glew-dev \\\n  freetype-dev \\\n  freeglut-dev \\\n  libxi-dev libxi-static \\\n  libxcursor-dev \\\n  libx11-dev \\\n  icu-data-full \\\n  sdl2_net-dev \\\n  sdl2_gfx-dev \\\n  sdl2_ttf-dev \\\n  sdl2_image-dev \\  \n  sdl2_mixer-dev \\\n  sdl2_pango-dev \\\n  sdl2-dev\n\nRUN ln -s /opt/vlang/v /usr/local/bin/v\nCOPY . /vlang-local\nARG USE_LOCAL\nRUN if [[ -z \"${USE_LOCAL}\" ]] ; then \\\n      git clone --depth=1 --quiet https://github.com/vlang/v/ /opt/vlang && \\\n      rm -rf /vlang-local ; \\\n    else \\\n      mv /vlang-local/* . && \\\n      rm -rf /vlang-local ; \\\n    fi\nRUN mkdir -p /tmp/v /tmp/v /home/ && chown -Rh 1000:1000 /opt/ /tmp/ /home/\n## setup runtime environment for v and bash:\nUSER 1000:1000\nENV HOME=/home\nENV VTMP=/tmp/v\nENV VMODULES=/tmp/vmodules\n\nRUN make && v -version && ls -la v && \\\n  du -b -s . && \\\n  time v doctor && \\\n  time v cmd/tools/vfmt.v && \\\n  time v -prod self && \\\n  true\nRUN find . -type f -name *_test.v -or -name *.vv -or -name *.out | xargs rm && \\\n  rm -rf v_old vc/ .git/ && \\\n  du -b -s .\nCMD [\"v\"]\n"
  },
  {
    "path": "Dockerfile.cross",
    "content": "FROM mstorsjo/llvm-mingw\n\nLABEL maintainer=\"Delyan Angelov <delian66@gmail.com>\"\nCOPY . .\nRUN make\nRUN ./v -os windows -o v.c cmd/v\nRUN x86_64-w64-mingw32-gcc v.c -std=c99 -w -municode -o v.exe -lws2_32\nRUN file v.exe\n\nCMD [ \"bash\" ]\n"
  },
  {
    "path": "GNUmakefile",
    "content": "CC ?= cc\nCFLAGS ?=\nLDFLAGS ?=\nTMPDIR ?= /tmp\nVROOT  ?= .\nVC     ?= ./vc\nVEXE   ?= ./v\nVCREPO ?= https://github.com/vlang/vc\nTCCREPO ?= https://github.com/vlang/tccbin\nLEGACYREPO ?= https://github.com/macports/macports-legacy-support\nGIT ?= git\n\nVCFILE := v.c\nTMPTCC := $(VROOT)/thirdparty/tcc\nLEGACYLIBS := $(VROOT)/thirdparty/legacy\nTMPLEGACY := $(LEGACYLIBS)/source\nTCCOS := unknown\nTCCARCH := unknown\nHAS_GIT := $(shell command -v $(GIT) >/dev/null 2>&1 && echo 1 || echo 0)\nGITCLEANPULL := $(GIT) clean -xf && $(GIT) pull --quiet\nGITFASTCLONE := $(GIT) clone --filter=blob:none --quiet\n\n#### Platform detections and overrides:\n_SYS := $(shell uname 2>/dev/null || echo Unknown)\n_SYS := $(patsubst MSYS%,MSYS,$(_SYS))\n_SYS := $(patsubst MINGW%,MinGW,$(_SYS))\n\nifneq ($(filter $(_SYS),MSYS MinGW),)\nWIN32 := 1\nEXE_EXT := .exe\nendif\n\nifeq ($(_SYS),Linux)\nLINUX := 1\nTCCOS := linux\nifneq ($(shell ldd --version 2>&1 | grep -i musl),)\nTCCOS := linuxmusl\nendif\nendif\n\nifeq ($(_SYS),Darwin)\nMAC := 1\nTCCOS := macos\nifeq ($(shell expr $(shell uname -r | cut -d. -f1) \\<= 15), 1)\nLEGACY := 1\nCFLAGS += -I$(LEGACYLIBS)/include/LegacySupport\nLDFLAGS += -L$(LEGACYLIBS)/lib\nLDFLAGS += -lMacportsLegacySupport\nVFLAGS += -cc $(CC)\nVFLAGS += -cflags \"$(CFLAGS)\"\nVFLAGS += -ldflags -L$(LEGACYLIBS)/lib\nVFLAGS += -cflags $(LEGACYLIBS)/lib/libMacportsLegacySupport.a\nendif\nendif\n\nifeq ($(_SYS),FreeBSD)\nTCCOS := freebsd\nLDFLAGS += -lexecinfo\nendif\n\nifeq ($(_SYS),NetBSD)\nNETBSD := 1\nTCCOS := netbsd\nLDFLAGS += -lexecinfo\nendif\n\nifeq ($(_SYS),OpenBSD)\nTCCOS := openbsd\nLDFLAGS += -lexecinfo\nendif\n\nifdef ANDROID_ROOT\nANDROID := 1\nundefine LINUX\nTCCOS := android\nendif\n#####\n\nifdef WIN32\nTCCOS := windows\nendif\n\nTCCARCH := $(shell uname -m 2>/dev/null || echo unknown)\n\nifeq ($(TCCARCH),x86_64)\n\tTCCARCH := amd64\nelse\nifneq ($(filter x86%,$(TCCARCH)),)\n\tTCCARCH := i386\nelse\nifeq ($(TCCARCH),arm64)\n\tTCCARCH := arm64\nelse\nifneq ($(filter arm%,$(TCCARCH)),)\n\tTCCARCH := arm\n# otherwise, just use the arch name\nendif\nendif\nendif\nendif\n\n.PHONY: all clean rebuild check fresh_vc fresh_tcc fresh_legacy check_for_working_tcc etags ctags\n\nifdef prod\nVFLAGS+=-prod\nendif\n\n# Keep bootstrap C compiler/linker flags aligned with the initial `v1` build.\nBOOTSTRAP_VFLAGS := $(if $(strip $(CFLAGS)),-cflags \"$(CFLAGS)\") $(if $(strip $(LDFLAGS)),-ldflags \"$(LDFLAGS)\")\n\nall: latest_vc latest_tcc latest_legacy\nifdef WIN32\n\t$(CC) $(CFLAGS) -std=c99 -municode -w -o v1$(EXE_EXT) $(VC)/$(VCFILE) $(LDFLAGS) -lws2_32 || cmd/tools/cc_compilation_failed_windows.sh\n\t./v1$(EXE_EXT) -no-parallel -o v2$(EXE_EXT) $(VFLAGS) $(BOOTSTRAP_VFLAGS) cmd/v\n\t./v2$(EXE_EXT) -o $(VEXE)$(EXE_EXT) $(VFLAGS) $(BOOTSTRAP_VFLAGS) cmd/v\n\t$(RM) v1$(EXE_EXT)\n\t$(RM) v2$(EXE_EXT)\nelse\nifdef LEGACY\n\t$(MAKE) -C $(TMPLEGACY)\n\t$(MAKE) -C $(TMPLEGACY) PREFIX=$(realpath $(LEGACYLIBS)) CFLAGS=$(CFLAGS) LDFLAGS=$(LDFLAGS) install\n\trm -rf $(TMPLEGACY)\n\t$(eval override LDFLAGS+=-L$(realpath $(LEGACYLIBS))/lib -lMacportsLegacySupport)\nendif\n\t$(CC) $(CFLAGS) -std=c99 -w -o v1$(EXE_EXT) $(VC)/$(VCFILE) -lm -lpthread $(LDFLAGS) || cmd/tools/cc_compilation_failed_non_windows.sh\nifdef NETBSD\n\tpaxctl +m v1$(EXE_EXT)\nendif\n\t./v1$(EXE_EXT) -no-parallel -o v2$(EXE_EXT) $(VFLAGS) $(BOOTSTRAP_VFLAGS) cmd/v\nifdef NETBSD\n\tpaxctl +m v2$(EXE_EXT)\nendif\n\t./v2$(EXE_EXT) -nocache -o $(VEXE)$(EXE_EXT) $(VFLAGS) $(BOOTSTRAP_VFLAGS) cmd/v\nifdef NETBSD\n\tpaxctl +m $(VEXE)$(EXE_EXT)\nendif\n\trm -rf v1$(EXE_EXT) v2$(EXE_EXT)\nendif\n\t@$(VEXE)$(EXE_EXT) run cmd/tools/detect_tcc.v\n\t@echo \"V has been successfully built\"\n\t@$(VEXE)$(EXE_EXT) -version\n\t@$(VEXE)$(EXE_EXT) run .github/problem-matchers/register_all.vsh\n\nclean:\n\trm -rf $(TMPTCC)\n\trm -rf $(LEGACYLIBS)\n\trm -rf $(VC)\n\nrebuild: clean all\n\nifndef local\nlatest_vc: $(VC)/.git/config\nifeq ($(HAS_GIT),1)\n\tcd $(VC) && $(GITCLEANPULL)\nelse\n\t@echo \"git not found; using existing $(VC)/$(VCFILE)\"\nendif\nelse\nlatest_vc:\n\t@echo \"Using local vc\"\nendif\n\ncheck_for_working_tcc:\n\t@$(TMPTCC)/tcc.exe --version > /dev/null 2> /dev/null || echo \"The executable '$(TMPTCC)/tcc.exe' does not work.\"\n\nfresh_vc:\n\trm -rf $(VC)\nifeq ($(HAS_GIT),1)\n\t$(GITFASTCLONE) $(VCREPO) $(VC)\nelse\n\t@echo \"git is required to clone $(VCREPO) into $(VC)\"\n\t@exit 1\nendif\n\nifndef local\nlatest_tcc: $(TMPTCC)/.git/config\nifeq ($(HAS_GIT),1)\n\tcd $(TMPTCC) && $(GITCLEANPULL)\nelse\n\t@echo \"git not found; skipping update of $(TMPTCC)\"\nendif\nifneq (,$(wildcard ./tcc.exe))\n\t@$(MAKE) --quiet check_for_working_tcc 2> /dev/null\nendif\n\nelse\nlatest_tcc:\n\t@echo \"Using local tcc\"\n\t@$(MAKE) --quiet check_for_working_tcc 2> /dev/null\nendif\n\nfresh_tcc:\n\trm -rf $(TMPTCC)\nifndef local\nifeq ($(HAS_GIT),1)\n# Check whether a TCC branch exists for the user's system configuration.\nifneq (,$(findstring thirdparty-$(TCCOS)-$(TCCARCH), $(shell $(GIT) ls-remote --heads $(TCCREPO) | sed 's/^[a-z0-9]*\\trefs.heads.//')))\n\t$(GITFASTCLONE) --branch thirdparty-$(TCCOS)-$(TCCARCH) $(TCCREPO) $(TMPTCC)\n\t@$(MAKE) --quiet check_for_working_tcc 2> /dev/null\nelse\n\t@echo 'Pre-built TCC not available for thirdparty-$(TCCOS)-$(TCCARCH) at $(TCCREPO), will use the system compiler: $(CC)'\n\t$(GITFASTCLONE) --branch thirdparty-unknown-unknown $(TCCREPO) $(TMPTCC)\nendif\nelse\n\t@echo \"git is required to clone $(TCCREPO)\"\n\t@exit 1\nendif\nelse\n\t@echo \"Using local tccbin\"\n\t@$(MAKE) --quiet check_for_working_tcc 2> /dev/null\nendif\n\nifndef local\nlatest_legacy: $(TMPLEGACY)/.git/config\nifdef LEGACY\nifeq ($(HAS_GIT),1)\n\tcd $(TMPLEGACY) && $(GITCLEANPULL)\nelse\n\t@echo \"git not found; using existing $(TMPLEGACY)\"\nendif\nendif\nelse\nlatest_legacy:\nifdef LEGACY\n\t@echo \"Using local legacysupport\"\nendif\nendif\n\nfresh_legacy:\n\trm -rf $(LEGACYLIBS)\nifeq ($(HAS_GIT),1)\n\t$(GITFASTCLONE) $(LEGACYREPO) $(TMPLEGACY)\nelse\n\t@echo \"git is required to clone $(LEGACYREPO)\"\n\t@exit 1\nendif\n\n$(TMPTCC)/.git/config:\nifeq ($(HAS_GIT),1)\n\t$(MAKE) fresh_tcc\nelse\n\t@echo \"git not found; skipping bootstrap of $(TMPTCC), system compiler $(CC) will be used\"\nendif\n\n$(VC)/.git/config:\nifeq ($(HAS_GIT),1)\n\t$(MAKE) fresh_vc\nelse\n\t@if [ -f \"$(VC)/$(VCFILE)\" ]; then \\\n\t\techo \"git not found; using existing $(VC)/$(VCFILE)\"; \\\n\telse \\\n\t\techo \"git is required to download $(VC)/$(VCFILE). Install git or provide the file manually.\"; \\\n\t\texit 1; \\\n\tfi\nendif\n\n$(TMPLEGACY)/.git/config:\nifdef LEGACY\nifeq ($(HAS_GIT),1)\n\t$(MAKE) fresh_legacy\nelse\n\t@if [ -d \"$(TMPLEGACY)\" ]; then \\\n\t\techo \"git not found; using existing $(TMPLEGACY)\"; \\\n\telse \\\n\t\techo \"git is required to download legacy support sources ($(LEGACYREPO))\"; \\\n\t\texit 1; \\\n\tfi\nendif\nendif\n\nasan:\n\t$(MAKE) all CFLAGS='-fsanitize=address,undefined'\n\nselfcompile:\n\t$(VEXE)$(EXE_EXT) -cg -o v cmd/v\n\nselfcompile-static:\n\t$(VEXE)$(EXE_EXT) -cg -cflags '--static' -o v-static cmd/v\n\n### NB: Please keep this Makefile and make.bat simple.\ninstall:\n\t@echo 'Please use `sudo ./v symlink` instead, or manually add the current directory to your PATH.'\n\ncheck:\n\t$(VEXE)$(EXE_EXT) test-all\n\netags:\n\t./v$(EXE_EXT) -print-v-files cmd/v | grep -v :parse_text| etags -L -\n\nctags:\n\t./v$(EXE_EXT) -print-v-files cmd/v | grep -v :parse_text| ctags -L -\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019-2024 Alexander Medvednikov\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "CC ?= cc\nVFLAGS ?=\nCFLAGS ?=\nLDFLAGS ?=\nBOOTSTRAP_VFLAGS := $(if $(strip $(CFLAGS)),-cflags \"$(CFLAGS)\") $(if $(strip $(LDFLAGS)),-ldflags \"$(LDFLAGS)\")\n\n.PHONY: all check download_vc v\n\nall: download_vc v\n\ndownload_vc:\n\tif [ -f vc/v.c ] ; then \\\n\t\tif command -v git >/dev/null 2>&1 ; then \\\n\t\t\tgit -C vc/ pull; \\\n\t\telse \\\n\t\t\techo \"git not found; using existing vc/v.c\"; \\\n\t\tfi; \\\n\telse \\\n\t\tif command -v git >/dev/null 2>&1 ; then \\\n\t\t\tgit clone --filter=blob:none https://github.com/vlang/vc vc/; \\\n\t\telse \\\n\t\t\techo \"git is required to download vc/. Please install git or provide vc/v.c.\"; \\\n\t\t\texit 1; \\\n\t\tfi; \\\n\tfi\n\nv:\n\t$(CC) $(CFLAGS) -std=gnu11 -w -o v1 vc/v.c -lm -lexecinfo -lpthread $(LDFLAGS) || cmd/tools/cc_compilation_failed_non_windows.sh\n\t./v1 -no-parallel -o v2 $(VFLAGS) $(BOOTSTRAP_VFLAGS) cmd/v\n\t./v2 -o v $(VFLAGS) $(BOOTSTRAP_VFLAGS) cmd/v\n\trm -rf v1 v2\n\t./v run ./cmd/tools/detect_tcc.v\n\t@echo \"V has been successfully built\"\n\t./v version\n\t./v run .github/problem-matchers/register_all.vsh\n\ncheck:\n\t./v test-all\n\ninstall:\n\t@echo 'Please use `sudo ./v symlink` instead, or manually add the current directory to your PATH.'\n"
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\" style=\"display:grid;place-items:center;\">\n<p>\n    <a href=\"https://vlang.io/\" target=\"_blank\"><img width=\"80\" src=\"https://raw.githubusercontent.com/vlang/v-logo/master/dist/v-logo.svg?sanitize=true\" alt=\"V logo\"></a>\n</p>\n<h1>The V Programming Language</h1>\n\n[vlang.io](https://vlang.io)\n| [Docs](https://github.com/vlang/v/blob/master/doc/docs.md)\n| [Changelog](https://github.com/vlang/v/blob/master/CHANGELOG.md)\n| [Speed](https://fast.vlang.io/)\n| [Contributing & compiler design](https://github.com/vlang/v/blob/master/CONTRIBUTING.md)\n\n</div>\n<div align=\"center\" style=\"display:grid;place-items:center;\">\n<!--\n[![Build Status][WorkflowBadge]][WorkflowUrl]\n-->\n\n[![Sponsor][SponsorBadge]][SponsorUrl]\n[![Patreon][PatreonBadge]][PatreonUrl]\n[![Discord][DiscordBadge]][DiscordUrl]\n[![X][XBadge]][XUrl]\n[![Modules][ModulesBadge]][ModulesUrl]\n\n</div>\n\n## Key Features of V\n\n- Simplicity: the language can be learned over the course of a weekend\n- Fast compilation: ≈110k loc/s with a Clang backend,\n  ≈500k loc/s with native and tcc backends *(Intel i5-7500, SSD, no\n  optimization)* ([demo video](https://www.youtube.com/watch?v=pvP6wmcl_Sc))\n- Easy to develop: V compiles itself in less than a second\n- Performance: as fast as C (V's main backend compiles to human-readable C)\n- Safety: no null, no globals, no undefined behavior (wip), immutability by default\n- C to V translation ([Translating DOOM demo video](https://www.youtube.com/watch?v=6oXrz3oRoEg))\n- Hot code reloading\n- [Flexible memory management](https://vlang.io/#memory). GC by default, manual via `v -gc none`,\n  arena allocation via `v -prealloc`, autofree via `v -autofree`\n  ([autofree demo video](https://www.youtube.com/watch?v=gmB8ea8uLsM)).\n- [Cross-platform UI library](https://github.com/vlang/ui)\n- Built-in graphics library\n- Easy cross-compilation\n- REPL\n- [Built-in ORM](https://github.com/vlang/v/blob/master/doc/docs.md#orm)\n- [Built-in web framework](https://github.com/vlang/v/blob/master/vlib/veb/README.md)\n- C and JavaScript backends\n- Great for writing low-level software ([Vinix OS](https://github.com/vlang/vinix))\n\n## Stability, future changes, post 1.0 freeze\n\nDespite being at an early development stage, the V language is relatively stable, and doesn't\nchange often. But there will be changes before 1.0.\nMost changes in the syntax are handled via vfmt automatically.\n\nThe V core APIs (primarily the `os` module) will also have minor changes until\nthey are stabilized in V 1.0. Of course, the APIs will grow after that, but without breaking\nexisting code.\n\nAfter the 1.0 release V is going to be in the \"feature freeze\" mode. That means no breaking changes\nin the language, only bug fixes and performance improvements. Similar to Go.\n\nWill there be V 2.0? Not within a decade after 1.0, perhaps not ever.\n\nTo sum it up, unlike many other languages, V is not going to be always changing, with new features\nintroduced and old features modified. It is always going to be a small and simple\nlanguage, very similar to the way it is right now.\n\n## Installing V from source\n\n**This is the preferred method.**\n\n### Linux, macOS, Windows, \\*BSD, Solaris, WSL, etc.\n\nUsually, installing V is quite simple if you have an environment that already has a\nfunctional `git` installation.\n\nNote: On Windows, run `make.bat` instead of `make` in CMD, or `./make.bat` in PowerShell.\nNote: On Ubuntu/Debian, you may need to run `sudo apt install git build-essential make` first.\n\nTo get started, execute the following in your terminal/shell:\n```bash\ngit clone --depth=1 https://github.com/vlang/v\ncd v\nmake\n```\n\nThat should be it, and you should find your V executable at `[path to V repo]/v`.\n`[path to V repo]` can be anywhere.\n\n(Like the note above says, on Windows, use `make.bat`, instead of `make`.)\n\nNow try running `./v run examples/hello_world.v` (or `v run examples/hello_world.v` in cmd shell).\n\n- *Trouble? Please see the notes above, and link to\n  [Installation Issues](https://github.com/vlang/v/discussions/categories/installation-issues)\n  for help.*\n\nNote: V is being constantly updated. To update V to its latest version, simply run:\n\n```bash\nv up\n```\n\n> [!NOTE]\n> If you run into any trouble, or you have a different operating\n> system or Linux distribution that doesn't install or work immediately, please see\n> [Installation Issues](https://github.com/vlang/v/discussions/categories/installation-issues)\n> and search for your OS and problem.\n>\n> If you can't find your problem, please add it to an existing discussion if one exists for\n> your OS, or create a new one if a main discussion doesn't yet exist for your OS.\n\n### Void Linux\n\n```bash\n# xbps-install -Su base-devel\n# xbps-install libatomic-devel\n$ git clone --depth=1 https://github.com/vlang/v\n$ cd v\n$ make\n```\n\n### Docker\n\n```bash\ngit clone --depth=1 https://github.com/vlang/v\ncd v\ndocker build -t vlang .\ndocker run --rm -it vlang:latest\n```\n\n### Docker with Alpine/musl\n\n```bash\ngit clone --depth=1 https://github.com/vlang/v\ncd v\ndocker build -t vlang_alpine - < Dockerfile.alpine\nalias with_alpine='docker run -u 1000:1000 --rm -it -v .:/src -w /src vlang_alpine:latest'\n```\n\nCompiling *static* executables, ready to be copied to a server, that is running\nanother linux distro, without dependencies:\n```bash\nwith_alpine v -skip-unused -prod -cc gcc -cflags -static -compress examples/http_server.v\nwith_alpine v -skip-unused -prod -cc gcc -cflags -static -compress -gc none examples/hello_world.v\nls -la examples/http_server examples/hello_world\nfile   examples/http_server examples/hello_world\nexamples/http_server: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, no section header\nexamples/hello_world: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, no section header\n```\n\nYou should see something like this:\n```\n-rwxr-xr-x 1 root root  16612 May 27 17:07 examples/hello_world\n-rwxr-xr-x 1 root root 335308 May 27 17:07 examples/http_server\n```\n\n### FreeBSD\n\nOn FreeBSD, V needs `boehm-gc-threaded` package preinstalled. After installing it, you can use the\nsame script, like on Linux/macos:\n\n```bash\npkg install boehm-gc-threaded\ngit clone --depth=1 https://github.com/vlang/v\ncd v\nmake\n```\n\n### OpenBSD\n\nOn OpenBSD (release 7.8), V needs `boehm-gc` and `openssl-3.5` packages preinstalled. After\ninstalling them, use GNU `make` (installed with `gmake` package), to build V.\n\n```bash\npkg_add boehm-gc openssl%3.5 gmake\ngit clone --depth=1 https://github.com/vlang/v\ncd v\ngmake\n```\n\n### Termux/Android\n\nOn Termux, V needs some packages preinstalled - a working C compiler, also `libexecinfo`,\n`libgc` and `libgc-static`. After installing them, you can use the same script, like on\nLinux/macos:\n\n```bash\npkg install clang libexecinfo libgc libgc-static make git\npkg update\ngit clone --depth=1 https://github.com/vlang/v\ncd v\nmake\n./v symlink\n```\nNote: there is *no* need for `sudo ./v symlink` on Termux (and sudo is not installed by default).\n\n### C compiler\n\nThe [Tiny C Compiler (tcc)](https://repo.or.cz/w/tinycc.git) is downloaded for you by `make` if\nthere is a compatible version for your system, and installed under the V `thirdparty` directory.\n\nThis compiler is very fast, but does almost no optimizations. It is best for development builds.\n\nFor production builds (using the `-prod` option to V), it's recommended to use clang, gcc, or\nMicrosoft Visual C++. If you are doing development, you most likely already have one of those\ninstalled.\n\nOtherwise, follow these instructions:\n\n- [Installing a C compiler on Linux and macOS](https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Linux-and-macOS)\n\n- [Installing a C compiler on Windows](https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Windows)\n\n### Symlinking\n\n> [!NOTE]\n> It is *highly recommended*, that you put V on your PATH. That saves\n> you the effort to type in the full path to your v executable every time.\n> V provides a convenience `v symlink` command to do that more easily.\n\nOn Unix systems, it creates a `/usr/local/bin/v` symlink to your\nexecutable. To do that, run:\n\n```bash\nsudo ./v symlink\n```\n\nOn Windows, start a new shell with administrative privileges, for example by pressing the\n<kbd>Windows Key</kbd>, then type `cmd.exe`, right-click on its menu entry, and choose `Run as\nadministrator`. In the new administrative shell, cd to the path where you have compiled V, then\ntype:\n\n```bat\nv symlink\n```\n\n(or `.\\v symlink` in PowerShell)\n\nThat will make V available everywhere, by adding it to your PATH. Please restart your\nshell/editor after that, so that it can pick up the new PATH variable.\n\n> [!NOTE]\n> There is no need to run `v symlink` more than once - v will still be available, even after\n> `v up`, restarts, and so on. You only need to run it again if you decide to move the V repo\n> folder somewhere else.\n\n## Editor/IDE Plugins\n\n- [Atom](https://github.com/vlang/awesome-v#atom)\n- [Emacs](https://github.com/vlang/awesome-v#emacs)\n- [JetBrains](https://plugins.jetbrains.com/plugin/20287-vlang/docs/syntax-highlighting.html)\n- [Sublime Text 3](https://github.com/vlang/awesome-v#sublime-text-3)\n- [Vim](https://github.com/vlang/awesome-v#vim)\n- [Vim/Neovim Runtime Files](editors/vim)\n- [VS Code](https://marketplace.visualstudio.com/items?itemName=VOSCA.vscode-v-analyzer)\n- [zed](https://github.com/lv37/zed-v)\n\n\nTo bring IDE functions for the V programming languages to your editor, check out\n[v-analyzer](https://github.com/vlang/v-analyzer). It provides language server capabilities.\n\n## Testing and running the examples\n\nMake sure V can compile itself:\n\n```bash\n$ v self\n$ v\nV 0.3.x\nUse Ctrl-C or `exit` to exit\n\n>>> println('hello world')\nhello world\n>>>\n```\n\n`v self` defaults to `-gc none`. Pass `-gc <mode>` if you need a different GC mode.\n\n```bash\ncd examples\nv hello_world.v && ./hello_world    # or simply\nv run hello_world.v                 # this builds the program and runs it right away\n\nv run word_counter/word_counter.v word_counter/cinderella.txt\nv run news_fetcher.v\nv run tetris/tetris.v\n```\n\nWhen a project has a `.vvmrc` file, `v <project>` and `v run <project>` try\nto use the requested V binary (for example `v0.4.6`) before falling back to\nthe current compiler.\n\n\n<img src='https://raw.githubusercontent.com/vlang/v/master/examples/tetris/screenshot.png' width=300 alt='tetris screenshot'>\n\n## Sokol and GG GUI apps/games:\n\nIn order to build Tetris or 2048 (or anything else using the `sokol` or `gg` graphics modules),\nyou will need to install additional development libraries for your system.\n\n| System              | Installation method                                                                                |\n|---------------------|----------------------------------------------------------------------------------------------------|\n| Debian/Ubuntu based | Run `sudo apt install libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev`             |\n| Fedora/RH/CentOS    | Run `sudo dnf install libXi-devel libXcursor-devel libX11-devel libXrandr-devel libglvnd-devel`    |\n|                     |                                                                                                    |\n| NixOS               | Add `xorg.libX11.dev xorg.libXcursor.dev xorg.libXi.dev xorg.libXrandr.dev libGL.dev` to           |\n|                     | to `environment.systemPackages`                                                                    |\n\n## V net.http, net.websocket, `v install`\n\nThe net.http module, the net.websocket module, and the `v install` command may all use SSL.\nV comes with a version of mbedtls, which should work on all systems. If you find a need to\nuse OpenSSL instead, you will need to make sure that it is installed on your system, then\nuse the `-d use_openssl` switch when you compile.\n\nNote: Mbed-TLS is smaller and easier to install on windows too (V comes with it), but if you\nwrite programs, that do lots of http requests to HTTPS/SSL servers, in most cases, it is *best*\nto compile with `-d use_openssl`, and do so on a system, where you do have OpenSSL installed\n(see below). Mbed-TLS is slower, and can have more issues, especially when you are doing parallel\nhttp requests to multiple hosts (for example in web scrapers, REST API clients, RSS readers, etc).\nOn windows, it is better to run such programs in WSL2.\n\nTo install OpenSSL on non-Windows systems:\n\n| System              | Installation command             |\n|---------------------|----------------------------------|\n| macOS               | `brew install openssl`           |\n| Debian/Ubuntu based | `sudo apt install libssl-dev`    |\n| Arch/Manjaro        | openssl is installed by default  |\n| Fedora/CentOS/RH    | `sudo dnf install openssl-devel` |\n\nOn Windows, OpenSSL is simply hard to get working correctly. The instructions\n[here](https://tecadmin.net/install-openssl-on-windows/) may (or may not) help.\n\n## V sync\n\nV's `sync` module and channel implementation uses libatomic.\nIt is most likely already installed on your system, but if not,\nyou can install it, by doing the following:\n\n| System              | Installation command                |\n|---------------------|-------------------------------------|\n| macOS               | already installed                   |\n| Debian/Ubuntu based | `sudo apt install libatomic1`       |\n| Fedora/CentOS/RH    | `sudo dnf install libatomic-static` |\n\n## V UI\n\n<a href=\"https://github.com/vlang/ui\">\n<img src='https://raw.githubusercontent.com/vlang/ui/master/examples/screenshot.png' width=712 alt='V UI example screenshot'>\n</a>\n\nhttps://github.com/vlang/ui\n\n<!---\n## JavaScript backend\n\n[examples/js_hello_world.v](examples/js_hello_world.v):\n\n```v\nfn main() {\n\tfor i in 0 .. 3 {\n\t\tprintln('Hello from V.js')\n\t}\n}\n```\n\n```bash\nv -o hi.js examples/js_hello_world.v && node hi.js\nHello from V.js\nHello from V.js\nHello from V.js\n```\n-->\n\n## Android graphical apps\n\nWith V's `vab` tool, building V UI and graphical apps for Android can become as easy as:\n\n```\n./vab /path/to/v/examples/2048\n```\n\n[https://github.com/vlang/vab](https://github.com/vlang/vab).\n<img src=\"https://user-images.githubusercontent.com/768942/107622846-c13f3900-6c58-11eb-8a66-55db12979b73.png\" alt=\"vab examples screenshot\">\n\n## Developing web applications\n\nCheck out the\n[Building a simple web blog](https://github.com/vlang/v/blob/master/tutorials/building_a_simple_web_blog_with_veb/README.md)\ntutorial and Gitly, a light and fast alternative to GitHub/GitLab:\n\nhttps://github.com/vlang/gitly\n\n<img src=\"https://user-images.githubusercontent.com/687996/85933714-b195fe80-b8da-11ea-9ddd-09cadc2103e4.png\" alt=\"gitly screenshot\">\n\n## Vinix, an OS/kernel written in V\n\nV is great for writing low-level software like drivers and kernels.\nVinix is an OS/kernel that already runs bash, GCC, V, and nano.\n\nhttps://github.com/vlang/vinix\n\n<img src=\"https://github.com/vlang/vinix/blob/main/screenshot0.png?raw=true\" alt=\"vinix screenshot 1\">\n<img src=\"https://github.com/vlang/vinix/blob/main/screenshot1.png?raw=true\" alt=\"vinix screenshot 2\">\n\n## Acknowledgement\n\n### TCC\n\nV thanks Fabrice Bellard for his original work on the\n[TCC - Tiny C Compiler](https://bellard.org/tcc/).\nNote the TCC website is old; the current TCC repository can be found\n[here](https://repo.or.cz/w/tinycc.git).\nV utilizes pre-built TCC binaries located at\n[https://github.com/vlang/tccbin/](https://github.com/vlang/tccbin/).\n\n### PVS-Studio\n\n[PVS-Studio](https://pvs-studio.com/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source) - static analyzer for C, C++, C#, and Java code.\n\n## Troubleshooting\n\nPlease see the\n[Troubleshooting](https://github.com/vlang/v/wiki/Troubleshooting)\nsection on our\n[wiki page](https://github.com/vlang/v/wiki).\n\n[WorkflowBadge]: https://github.com/vlang/v/workflows/CI/badge.svg\n[DiscordBadge]: https://img.shields.io/discord/592103645835821068?label=Discord&logo=discord&logoColor=white\n[PatreonBadge]: https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3Dvlang%26type%3Dpatrons&style=flat\n[SponsorBadge]: https://img.shields.io/github/sponsors/medvednikov?style=flat&logo=github&logoColor=white\n[XBadge]: https://img.shields.io/badge/follow-%40v__language-1DA1F2?logo=x&style=flat&logoColor=white\n[ModulesBadge]: https://img.shields.io/badge/modules-reference-027d9c?logo=v&logoColor=white&logoWidth=10\n\n[WorkflowUrl]: https://github.com/vlang/v/commits/master\n[DiscordUrl]: https://discord.gg/vlang\n[PatreonUrl]: https://patreon.com/vlang\n[SponsorUrl]: https://github.com/sponsors/medvednikov\n[XUrl]: https://x.com/v_language\n[ModulesUrl]: https://modules.vlang.io\n"
  },
  {
    "path": "ROADMAP.md",
    "content": "Roadmap with big features.\nFor a list of all features and fixes, check out the changelog.\n\n## [Version 0.3]\n\n- [x] gc option\n- [x] channels\n- [x] lock{}\n- [x] thread safe arrays\n- [x] rune type\n- [x] replace `ustring` with `[]rune`\n- [x] fix `byte.str()`\n- [x] maps with non-string keys\n- [x] iOS/Android support\n- [x] parallel cgen\n- [x] IO streams\n- [x] struct embedding\n- [x] interface embedding\n- [x] interfaces: allow struct fields (not just methods)\n- [x] short generics syntax (`foo(5)` instead of `foo<int>(5)`)\n- [x] more advanced errors, not just `error('message')`\n\n## [Version 0.4]\n\n- [x] [Coroutines](https://github.com/vlang/v/discussions/11582) (doesn't work on Windows yet)\n- [x] vfmt: add missing imports (like goimports)\n- [x] Recursive structs via options: `struct Node { next ?Node }`\n- [x] First class Option type\n- [x] Optional function struct fields\n- [x] Handle function pointers safely, remove `if function == 0 {`\n- [x] Bundle an SSL library (mbedtls) like GC\n- [x] Anonymous structs\n- [x] Improve vweb: allow separation of logic via \"controllers\", lots of other fixes\n- [x] New VPM site\n\n## [Version 0.5]\n\n- [x] Parallel C compilation via `-parallel-cc`\n- [x] Parallel parser (not integrated yet)\n- [x] Parallel checker (not integrated yet)\n- [x] Improved vweb => veb framework. Separation of global and context (request local) fields.\n      Performance and stability. Based on picoev.\n- [x] -skip-unused on by default\n- [x] Lambdas: `a.sort(|a, b| a > b)`\n- [x] Implicit Veb contexts passed to requests\n- [x] Direct C/C++ interop without generating wrappers (via -experimental for now)\n- [x] Allow `$if` everywhere: top level, inside struct definitions, etc\n\n## [Version 0.6]\n\n- [ ] Custom attributes\n- [ ] Contexts that are passed implicitly (e.g. for custom allocation/memory management)\n- [ ] 64/32 bit int depending on arch (will remove array.len limitation on 64 bit systems)\n- [ ] `copy()` builtin function (e.g. for easier conversion from `[]Foo` to `[4]Foo`)\n- [ ] Integrate the new parallel parser/checker/cc\n- [ ] Incremental compilation\n- [ ] Runtime race detector\n- [ ] [Thread safe maps](https://github.com/vlang/v/discussions/11729)\n- [ ] `recover()` from panics\n- [ ] -usecache on by default\n- [ ] ORM migrations\n- [ ] Make ORM work without installing developer libs (libpq-dev etc)\n\n## [Version 1.0]\n\n- [ ] Cross compilation of C\n- [ ] Big remaining bugs fixed\n- [ ] More powerful comptime\n- [ ] Constraints for generics\n- [ ] Coroutines on Windows\n- [ ] Autofree memory management option ready for production\n- [ ] C2V supporting entire C99 standard\n- [ ] [Shared compiled libs](https://github.com/vlang/rfcs/issues/27)\n\n### Tooling\n\n- [ ] More stable VLS\n- [ ] Profiler improvements\n  - [ ] Basic interactive shell with search, sort, filter, etc.\n- [ ] VPM\n  - [x] New VPM site\n  - [ ] Package versioning\n- [ ] A better documentation platform\n\n### Web\n\n- [ ] Site that brings everything together in a single style\n- [ ] Interactive educational platform (learning to program for beginners)\n"
  },
  {
    "path": "TESTS.md",
    "content": "# Automated tests\n\nTLDR: do run `v test-all` locally, after making your changes,\nand before submitting PRs.\n\nTip: use `v -cc tcc` when compiling tests, because TCC is much faster,\ncompared to most other C compilers like clang/gcc/msvc. Most test commands\nwill use the V compiler and the V tools many times, potentially\nhundreds/thousands of times.\n\n## `v test-all`\n\nTest and build *everything*. Useful to verify *locally*, that the CI will\nmost likely pass. Slowest, but most comprehensive.\n\nIt works, by running these in succession:\n\n* `v test-cleancode`\n* `v test-self`\n* `v test-fmt`\n* `v build-tools`\n* `v build-examples`\n* `v check-md -hide-warnings .`\n* `v install nedpals.args`\n\n# Details:\n\nIn the `v` repo there are many tests. The main types are:\n\n## `_test.v` tests - these are the normal V test files.\n\nAll `test_` functions in these files, will be ran automatically by\nV's test framework.\n\nNB 1: You can run test files one by one, with:\n`v file_test.v` - this will run the test_ functions in file_test.v,\nand will exit with a 0 exit code, if they all had 0 failing assertions.\n\n`v -stats file_test.v` - this will run the test_ functions, and show a\nreport about how much time it took to run each of them too.\n\nNB 2: You can also run many test files at once (in parallel, depending on\nhow many cores you have), with:\n`v test folder` - this will run *all* `_test.v` files in `folder`,\nrecursively.\n\n`v -stats test folder` - same, but will also produce timing reports\nabout how fast each test_ function in each _test.v file ran.\n\n## `v test vlib/v/tests`:\n\nThis folder contains _test.v files, testing the different features of the V\ncompiler. Each of them will be compiled, and all the features in them have\nto work (verified by assertions).\n\n## `v vlib/v/slow_tests/inout/compiler_test.v`\n\nThis is a *test runner*, that checks whether the output of running a V program,\nmatches an expected .out file. You can also check for code that does panic\nusing this test runner - just paste the start of the `panic()` output in the\ncorresponding .out file.\n\n> [!NOTE]\n> These tests, expect to find a pair of `.vv` and `.out` files, in the folder:\n> vlib/v/slow_tests/inout\n\nThe test runner will run each `.vv` file, and will check that its output, matches\nthe contents of the `.out` file with the same base name. This is particularly useful\nfor checking that errors and panics are printed.\n\n## `v vlib/v/gen/c/coutput_test.v`\n\ncoutput_test.v is a *test runner*, that checks whether the generated C source\ncode matches *all* expectations, specified in *.c.must_have files, in the\nfolder vlib/v/gen/c/testdata/ .\n\nEach `.c.must_have` file, *has* to have a corresponding `.vv` file.\n\nEach `.c.must_have` file, consists of multiple lines. Each of these\nlines, *should* be present *at least once* in the output, when the .vv\nfile is compiled with `-o -` .\n\n## REPL tests\n\nThe test runner for these is `vlib/v/slow_tests/repl/repl_test.v`.\n\nThe test cases for the V REPL, are stored in .repl files, in the folder\n`vlib/v/slow_tests/repl/`. Each .repl file in this folder, contains several\nlines of input to the V repl, followed by a single line of `===output===`,\nand then the output lines, that the repl would normally show for the input\nlines.\n\nIf you change the compiler or the REPL source, and you have breaks in those\n.repl files, you can replace the current output in them, by running several\ntimes `VAUTOFIX=1 ./vlib/v/slow_tests/repl/repl_test.v`, until all the\nfiles are fixed and the test pass.\n\n## `v vlib/v/slow_tests/run_project_folders_test.v`\n\nThis *test runner*, checks whether whole project folders, can be compiled, and run.\n\n> [!NOTE]\n> Each project in these folders, should finish with an exit code of 0,\n> and it should output `OK` as its last stdout line.\n\n## `v vlib/v/tests/known_errors/known_errors_test.v`\n\nThis *test runner*, checks whether a known program, that was expected to compile,\nbut did NOT, due to a buggy checker, parser or cgen, continues to fail.\nThe negative programs are collected in the `vlib/v/tests/known_errors/testdata/` folder.\nEach of them should FAIL to compile, due to a known/confirmed compiler bug/limitation.\n\nThe intended use of this, is for providing samples, that currently do NOT compile,\nbut that a future compiler improvement WILL be able to compile, and to\ntrack, whether they were not fixed incidentally, due to an unrelated\nchange/improvement. For example, code that triggers generating invalid C code can go here,\nand later when a bug is fixed, can be moved to a proper _test.v or .vv/.out pair, outside of\nthe `vlib/v/tests/known_errors/testdata/` folder.\n\n## Test building of actual V programs (examples, tools, V itself)\n\n* `v build-tools`\n* `v build-examples`\n* `v build-vbinaries`\n\n## Formatting tests\n\nIn `vlib/v/fmt/` there are:\n\n* `v vlib/v/fmt/fmt_test.v`\n\nThis checks `.out` tests.\n\n* `v vlib/v/fmt/fmt_keep_test.v`\n\nThis verifies that all `_keep.vv` files in the `vlib/v/fmt/tests/` folder,\nwould be unchanged by `v fmt -w`, i.e. that the v source code formatter,\ngenerates a stable source output, that does not change, once it is already\nformatted once.\n\n* `v vlib/v/fmt/fmt_vlib_test.v`\n\nThis checks that all V source files are formatted, and prints a summary.\nThis is not required.\n\n* `v test-cleancode`\n\nCheck that most .v files, are invariant of `v fmt` runs.\n\n* `v test-fmt`\n\nThis tests that all .v files in the current folder are already formatted.\nIt is useful for adding to CI jobs, to guarantee, that future contributions\nwill keep the existing source nice and clean.\n\n## Markdown/documentation checks:\n\n* `v check-md -hide-warnings .`\n\nEnsure that all .md files in the project are formatted properly,\nand that the V code block examples in them can be compiled/formatted too.\n\nNote: if that command finds formatting errors, they can be fixed with:\n`VAUTOFIX=1 ./v check-md file.md` or with `v check-md -fix file.md`.\n\n## `v test-self`\n\nRun `vlib` module tests, *including* the compiler tests.\n\n## `v vlib/v/compiler_errors_test.v`\n\nThis runs tests for:\n\n* `vlib/v/scanner/tests/*.vv`\n* `vlib/v/checker/tests/*.vv`\n* `vlib/v/parser/tests/*.vv`\n\n> [!NOTE]\n> There are special folders, that compiler_errors_test.v will try to\n> run/compile with specific options:\n\nvlib/v/checker/tests/globals_run/ - `-enable-globals run`;\nresults stored in `.run.out` files, matching the .vv ones.\n\nNB 2: in case you need to modify many .out files, run *twice* in a row:\n`VAUTOFIX=1 ./v vlib/v/compiler_errors_test.v`\nThis will fail the first time, but it will record the new output for each\n.vv file, and store it into the corresponding .out file. The second run\nshould be now successful, and so you can inspect the difference, and\ncommit the new .out files with minimum manual effort.\n\nNB 3: To run only some of the tests, use:\n`VTEST_ONLY=mismatch ./v vlib/v/compiler_errors_test.v`\nThis will check only the .vv files, whose paths match the given filter.\n\nNB 4: To run tests, but without printing status lines for all the successfull\nones, use:\n`VTEST_HIDE_OK=1 ./v test vlib/math/`\nThis will print only the total stats, and the failing tests, but otherwise\nit will be silent. It is useful, when you have hundreds or thousands of\nindividual `_test.v` files, and you want to avoid scrolling.\n\nNB 5: To show only *the currently running test*, use:\n`./v -progress test vlib/math/`\nIn this mode, the output lines will be limited, no matter how many `_test.v`\nfiles there are. The output will contain the total stats and the output of\nthe failing tests too.\n\n## `.github/workflows/ci.yml`\n\nThis is a Github Actions configuration file, that runs various CI\ntests in the main V repository, for example:\n\n* `v vet vlib/v` - run a style checker.\n* `v test-self` (run self tests) in various compilation modes.\n\n> [!NOTE]\nThe VDOC test vdoc_file_test.v now also supports VAUTOFIX, which is\nuseful, if you change anything inside cmd/tools/vdoc,\nor inside the modules that it depends on (like markdown).\nAfter such changes, just run this command *2 times*, and commit the\nresulting changes in `cmd/tools/vdoc/testdata` as well:\n`VAUTOFIX=1 ./v cmd/tools/vdoc/vdoc_file_test.v`\n"
  },
  {
    "path": "bench/README.md",
    "content": "### Vectors\n\n```bash\nBenchmark 1: ./boids_test/bin/Release/net7.0/linux-x64/publish/boids_test\nTime (mean ± σ):     262.2 ms ±   5.7 ms    [User: 231.6 ms, System: 14.1 ms]\nRange (min … max):   255.4 ms … 275.3 ms    11 runs\n\nBenchmark 2: ./vinted_report_generator/main\nTime (mean ± σ):     208.3 ms ±   1.9 ms    [User: 205.4 ms, System: 1.6 ms]\nRange (min … max):   204.9 ms … 210.6 ms    14 runs\n\nSummary\n./vinted_report_generator/main ran\n1.26 ± 0.03 times faster than ./boids_test/bin/Release/net7.0/linux-x64/publish/boids_test\n```\n"
  },
  {
    "path": "bench/bench_closure.v",
    "content": "module main\n\nimport time\nimport sync\nimport os\nimport runtime\nimport v.util.version\n\n// Define closure type alias\ntype ClosureFN = fn () int\n\n// Test closures with different capture sizes\nfn create_closure_small() ClosureFN {\n\ta := 0\n\treturn fn [a] () int {\n\t\treturn a\n\t}\n}\n\nfn create_closure_medium() ClosureFN {\n\ta, b, c, d := 1, 2, 3, 4\n\treturn fn [a, b, c, d] () int {\n\t\treturn a + b - c * d\n\t}\n}\n\nstruct LargeData {\n\tarray [10]int\n}\n\nfn create_closure_large() ClosureFN {\n\tdata := LargeData{\n\t\tarray: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]!\n\t}\n\treturn fn [data] () int {\n\t\tmut sum := 0\n\t\tfor i in 0 .. 10 {\n\t\t\tsum += data.array[i]\n\t\t}\n\t\treturn sum\n\t}\n}\n\n// Result structs\nstruct TestResult {\n\ttest_name   string\n\titerations  int\n\ttime_ms     i64\n\tops_per_sec f64 // Operations per second\n\tnotes       string\n}\n\nstruct MemoryResult {\n\ttest_name         string\n\tcount             int\n\tstart_mem_kb      int\n\tend_mem_kb        int\n\tdelta_kb          int\n\tbytes_per_closure int\n\tcheck_sum         int\n}\n\n// Benchmark group - returns result structs\nfn benchmark_closure_creation(iterations int) []TestResult {\n\tmut results := []TestResult{}\n\n\t// Test small closure creation\n\tmut start := time.ticks()\n\tfor _ in 0 .. iterations {\n\t\t_ = create_closure_small()\n\t}\n\tsmall_time := time.ticks() - start\n\tmut ops_per_sec := f64(iterations) * 1000.0 / f64(small_time)\n\tresults << TestResult{'Small Closure Creation', iterations, small_time, ops_per_sec, ''}\n\n\t// Test medium closure creation\n\tstart = time.ticks()\n\tfor _ in 0 .. iterations {\n\t\t_ = create_closure_medium()\n\t}\n\tmedium_time := time.ticks() - start\n\tops_per_sec = f64(iterations) * 1000.0 / f64(medium_time)\n\tresults << TestResult{'Medium Closure Creation', iterations, medium_time, ops_per_sec, ''}\n\n\t// Test large closure creation\n\tlarge_iter := iterations / 10\n\tstart = time.ticks()\n\tfor _ in 0 .. large_iter {\n\t\t_ = create_closure_large()\n\t}\n\tlarge_time := time.ticks() - start\n\tops_per_sec = f64(large_iter) * 1000.0 / f64(large_time)\n\tresults << TestResult{'Large Closure Creation', large_iter, large_time, ops_per_sec, ''} //, \"Equivalent iterations: ${iterations/10}\"}\n\treturn results\n}\n\nfn benchmark_closure_call(iterations int) []TestResult {\n\tmut results := []TestResult{}\n\n\tclosure_small := create_closure_small()\n\tclosure_medium := create_closure_medium()\n\tclosure_large := create_closure_large()\n\n\t// Test small closure call\n\tmut start := time.ticks()\n\tfor _ in 0 .. iterations {\n\t\t_ = closure_small()\n\t}\n\tsmall_time := time.ticks() - start\n\tmut ops_per_sec := f64(iterations) * 1000.0 / f64(small_time)\n\tresults << TestResult{'Small Closure Call', iterations, small_time, ops_per_sec, ''}\n\n\t// Test medium closure call\n\tstart = time.ticks()\n\tfor _ in 0 .. iterations {\n\t\t_ = closure_medium()\n\t}\n\tmedium_time := time.ticks() - start\n\tops_per_sec = f64(iterations) * 1000.0 / f64(medium_time)\n\tresults << TestResult{'Medium Closure Call', iterations, medium_time, ops_per_sec, ''}\n\n\t// Test large closure call\n\tlarge_iter := iterations / 10\n\tstart = time.ticks()\n\tfor _ in 0 .. large_iter {\n\t\t_ = closure_large()\n\t}\n\tlarge_time := time.ticks() - start\n\tops_per_sec = f64(large_iter) * 1000.0 / f64(large_time)\n\tresults << TestResult{'Large Closure Call', large_iter, large_time, ops_per_sec, ''}\n\n\treturn results\n}\n\nfn benchmark_threaded_creation(threads int, iterations_per_thread int) TestResult {\n\ttotal_iterations := threads * iterations_per_thread\n\n\tmut wg := sync.new_waitgroup()\n\twg.add(threads)\n\n\tstart := time.ticks()\n\n\tfor _ in 0 .. threads {\n\t\tgo fn [mut wg, iterations_per_thread] () {\n\t\t\tdefer { wg.done() }\n\t\t\tfor _ in 0 .. iterations_per_thread {\n\t\t\t\t_ = create_closure_medium()\n\t\t\t}\n\t\t}()\n\t}\n\n\twg.wait()\n\telapsed := time.ticks() - start\n\tops_per_sec := f64(total_iterations) * 1000.0 / f64(elapsed)\n\n\treturn TestResult{\n\t\ttest_name:   'Multi-threaded Creation'\n\t\titerations:  total_iterations\n\t\ttime_ms:     elapsed\n\t\tops_per_sec: ops_per_sec\n\t\tnotes:       'Threads: ${threads} Iterations per thread: ${iterations_per_thread}'\n\t}\n}\n\nfn baseline_call_performance(iterations int) TestResult {\n\tstart := time.ticks()\n\tfor _ in 0 .. iterations {\n\t\t_ = normal_function()\n\t}\n\telapsed := time.ticks() - start\n\tops_per_sec := f64(iterations) * 1000.0 / f64(elapsed)\n\n\treturn TestResult{\n\t\ttest_name:   'Normal Function Call'\n\t\titerations:  iterations\n\t\ttime_ms:     elapsed\n\t\tops_per_sec: ops_per_sec\n\t\tnotes:       'Baseline'\n\t}\n}\n\nfn benchmark_memory_usage(count int) MemoryResult {\n\tmut closures := []ClosureFN{}\n\tstart_mem := runtime.used_memory() or { panic(err) }\n\n\tfor i in 0 .. count {\n\t\tthe_closure := create_closure_medium()\n\t\tclosures << the_closure\n\n\t\tif i % 1000 == 0 {\n\t\t\t_ = the_closure()\n\t\t}\n\t}\n\n\tend_mem := runtime.used_memory() or { panic(err) }\n\tdelta := int(end_mem) - int(start_mem)\n\tbytes_per_closure := delta / count\n\n\t// Calculate verification sum\n\tmut check_sum := 0\n\tn := if closures.len < 100 { closures.len } else { 100 }\n\tfor idx in 0 .. n {\n\t\tcheck_sum += closures[idx]()\n\t}\n\n\treturn MemoryResult{\n\t\ttest_name:         'Closure Memory Overhead'\n\t\tcount:             count\n\t\tstart_mem_kb:      int(start_mem / 1024)\n\t\tend_mem_kb:        int(end_mem / 1024)\n\t\tdelta_kb:          delta / 1024\n\t\tbytes_per_closure: bytes_per_closure\n\t\tcheck_sum:         check_sum\n\t}\n}\n\nfn normal_function() int {\n\treturn 42\n}\n\n// Format performance data for readability\nfn format_perf(ops_per_sec f64) string {\n\tif ops_per_sec >= 1_000_000 {\n\t\treturn '${ops_per_sec / 1_000_000:5.2f} Mop/s'\n\t} else if ops_per_sec >= 1_000 {\n\t\treturn '${ops_per_sec / 1_000:5.2f} Kop/s'\n\t} else {\n\t\treturn '${ops_per_sec:5.2f} op/s'\n\t}\n}\n\nfn print_results_table(results []TestResult, title string) {\n\tprintln('|---------------------------|------------|----------|--------------|--------------|')\n\tfor res in results {\n\t\tperf_str := format_perf(res.ops_per_sec)\n\t\tprintln('| ${res.test_name:-25} | ${res.iterations:10} | ${res.time_ms:8} | ${perf_str:-12} | ${res.notes:-12} |')\n\t}\n}\n\nfn main() {\n\tprintln('# V Language Closure Performance Benchmark Report')\n\n\t// Configurable test parameters\n\tbase_iter := 100_000_000 // 100 million iterations\n\tcreation_iter := 10_000_000 // 1 million iterations\n\tmem_count := 100_000\n\tthreads := 8\n\tthread_iter := 125_000\n\n\t// Execute tests\n\tbaseline_result := baseline_call_performance(base_iter)\n\tcreation_results := benchmark_closure_creation(creation_iter)\n\tcall_results := benchmark_closure_call(base_iter)\n\tthread_result := benchmark_threaded_creation(threads, thread_iter)\n\tmem_result := benchmark_memory_usage(mem_count)\n\n\t// Print result tables\n\tprintln('\\n## 1. Closure Performance Analysis')\n\tprintln('| Test Name                 | Iterations | Time(ms) | Ops/sec      | Notes        |')\n\tprint_results_table([baseline_result], '1. Performance Baseline')\n\tprint_results_table(creation_results, '2. Closure Creation Performance')\n\tprint_results_table(call_results, '3. Closure Call Performance')\n\tprint_results_table([thread_result], '4. Multi-threaded Performance')\n\n\t// Print memory results\n\tprintln('\\n## 2. Memory Overhead Analysis')\n\tprintln('| Test Name               | Closure Count | Start Mem(KB) | End Mem(KB) | Delta(KB) | Bytes/Closure |')\n\tprintln('|-------------------------|---------------|---------------|------------|-----------|---------------|')\n\tprintln('| ${mem_result.test_name:-20} | ${mem_result.count:13} | ${mem_result.start_mem_kb:13} | ${mem_result.end_mem_kb:10} | ${mem_result.delta_kb:9} | ${mem_result.bytes_per_closure:13} |')\n\tprintln('\\n**Verification Sum: ${mem_result.check_sum}** (Calculated from random sample of 100 closures)')\n\n\tprintln('\\n## Test Environment')\n\tprintln('- V Language Version: ${version.full_v_version(false)}')\n\tprintln('- CPU Cores: ${runtime.nr_cpus()}')\n\tprintln('- System Memory: ${runtime.total_memory()! / 1024 / 1024} MB')\n\tprintln('- Operating System: ${os.user_os()}')\n\tprintln('\\n> Test Time: ${time.now().format_ss_micro()}')\n}\n"
  },
  {
    "path": "bench/bench_gc.v",
    "content": "// bench_gc.v - Benchmark comparing VGC vs Boehm GC\n// Run with: v -gc boehm -o bench_boehm bench/bench_gc.v && ./bench_boehm\n//           v -gc vgc   -o bench_vgc   bench/bench_gc.v && ./bench_vgc\nimport time\n\nconst n_allocs = 1_000_000\nconst n_iters = 5\n\nstruct Node {\nmut:\n\tleft  &Node = unsafe { nil }\n\tright &Node = unsafe { nil }\n\tvalue int\n}\n\n// Allocate many small objects (typical GC workload)\nfn bench_small_allocs() {\n\tsw := time.new_stopwatch()\n\tmut sum := 0\n\tfor _ in 0 .. n_allocs {\n\t\ts := 'hello world ${sum}'\n\t\tsum += s.len\n\t}\n\telapsed := sw.elapsed()\n\teprintln('  small allocs (${n_allocs}x string): ${elapsed.milliseconds()} ms  (sum=${sum})')\n}\n\n// Build a binary tree (tests pointer-heavy allocation)\nfn make_tree(depth int) &Node {\n\tif depth <= 0 {\n\t\treturn &Node{\n\t\t\tvalue: 1\n\t\t}\n\t}\n\treturn &Node{\n\t\tleft:  make_tree(depth - 1)\n\t\tright: make_tree(depth - 1)\n\t\tvalue: depth\n\t}\n}\n\nfn tree_sum(n &Node) int {\n\tif n == unsafe { nil } {\n\t\treturn 0\n\t}\n\treturn n.value + tree_sum(n.left) + tree_sum(n.right)\n}\n\nfn bench_tree() {\n\tsw := time.new_stopwatch()\n\tmut total := 0\n\tfor _ in 0 .. 10 {\n\t\tt := make_tree(18)\n\t\ttotal += tree_sum(t)\n\t}\n\telapsed := sw.elapsed()\n\teprintln('  tree build+walk (depth=18, 10x): ${elapsed.milliseconds()} ms  (sum=${total})')\n}\n\n// Allocate and discard arrays (tests realloc / growing)\nfn bench_arrays() {\n\tsw := time.new_stopwatch()\n\tmut total := 0\n\tfor _ in 0 .. 100 {\n\t\tmut arr := []int{cap: 16}\n\t\tfor j in 0 .. 100_000 {\n\t\t\tarr << j\n\t\t}\n\t\ttotal += arr.len\n\t}\n\telapsed := sw.elapsed()\n\teprintln('  array grow (100x 100k pushes): ${elapsed.milliseconds()} ms  (total=${total})')\n}\n\nfn main() {\n\tgc_mode := $if gcboehm ? {\n\t\t'boehm'\n\t} $else $if vgc ? {\n\t\t'vgc'\n\t} $else {\n\t\t'none'\n\t}\n\teprintln('=== GC Benchmark (mode: ${gc_mode}) ===')\n\n\tfor iter in 0 .. n_iters {\n\t\teprintln('--- iteration ${iter + 1}/${n_iters} ---')\n\t\tbench_small_allocs()\n\t\tbench_tree()\n\t\tbench_arrays()\n\t}\n\n\tusage := gc_heap_usage()\n\teprintln('--- heap usage ---')\n\teprintln('  heap_size:  ${usage.heap_size / 1024} KB')\n\teprintln('  free_bytes: ${usage.free_bytes / 1024} KB')\n}\n"
  },
  {
    "path": "bench/bench_string_dedup.v",
    "content": "// Benchmark comparison of four string deduplication methods in V: basic array, pre-allocated array, map, and set\nmodule main\n\nimport time\nimport datatypes\n\n// Method 1: Using basic array (no pre-allocation)\nstruct Context1 {\nmut:\n\tused_str []string\n}\n\nfn (mut c Context1) add_used(str string) {\n\tif str !in c.used_str {\n\t\tc.used_str << str\n\t}\n}\n\n// Method 2: Using pre-allocated array with capacity\nstruct Context2 {\nmut:\n\tused_str []string\n}\n\nfn (mut c Context2) add_used(str string) {\n\tif str !in c.used_str {\n\t\tc.used_str << str\n\t}\n}\n\n// Method 3: Using map\nstruct Context3 {\nmut:\n\tused_str map[string]bool\n}\n\nfn (mut c Context3) add_used(str string) {\n\tc.used_str[str] = true\n}\n\n// Method 4: Using set\nstruct Context4 {\nmut:\n\tused_str datatypes.Set[string]\n}\n\nfn (mut c Context4) add_used(str string) {\n\tc.used_str.add(str)\n}\n\n// Generate random test strings\nfn generate_test_strings(count int, duplicate_ratio f64) []string {\n\tmut strs := []string{cap: count}\n\tunique_count := int(f64(count) * (1.0 - duplicate_ratio))\n\t// First generate a batch of unique strings\n\tfor i in 0 .. unique_count {\n\t\tstrs << 'str_${i}_${time.ticks()}' // Add timestamp to reduce duplication rate\n\t}\n\t// The remaining part uses duplicate strings\n\tfor i in 0 .. (count - unique_count) {\n\t\tstrs << strs[i % unique_count] // Cycle through the first half of strings to create duplicates\n\t}\n\treturn strs\n}\n\nfn main() {\n\tnum_strs := 10000 // Total number of strings\n\tduplicate_ratio := 0.3 // Duplicate string ratio (30%)\n\ttest_strs := generate_test_strings(num_strs, duplicate_ratio)\n\tprintln('Generated test strings: ${test_strs.len} (approximately ${int(duplicate_ratio * 100)}% are duplicates)')\n\n\t// Test method 1: basic array (no pre-allocation)\n\tmut ctx1 := Context1{}\n\tsw1 := time.new_stopwatch()\n\tfor str in test_strs {\n\t\tctx1.add_used(str)\n\t}\n\ttime1 := sw1.elapsed().milliseconds()\n\tprintln('Method 1 (basic array) - Time: ${time1}ms, Final unique strings: ${ctx1.used_str.len}')\n\n\t// Test method 2: pre-allocated array\n\tmut ctx2 := Context2{\n\t\tused_str: []string{cap: num_strs} // Pre-allocate capacity to avoid reallocations\n\t}\n\tsw2 := time.new_stopwatch()\n\tfor str in test_strs {\n\t\tctx2.add_used(str)\n\t}\n\ttime2 := sw2.elapsed().milliseconds()\n\tprintln('Method 2 (pre-allocated array) - Time: ${time2}ms, Final unique strings: ${ctx2.used_str.len}')\n\n\t// Test method 3: map\n\tmut ctx3 := Context3{}\n\tsw3 := time.new_stopwatch()\n\tfor str in test_strs {\n\t\tctx3.add_used(str)\n\t}\n\ttime3 := sw3.elapsed().milliseconds()\n\tprintln('Method 3 (map) - Time: ${time3}ms, Final unique strings: ${ctx3.used_str.len}')\n\n\t// Test method 4: set\n\tmut ctx4 := Context4{}\n\tsw4 := time.new_stopwatch()\n\tfor str in test_strs {\n\t\tctx4.add_used(str)\n\t}\n\ttime4 := sw4.elapsed().milliseconds()\n\tprintln('Method 4 (set) - Time: ${time4}ms, Final unique strings: ${ctx4.used_str.size()}')\n\n\t// Performance comparison\n\tprintln('\\nPerformance comparison:')\n\tprintln('Method 2 (pre-allocated array) is ${f64(time1) / f64(time2):.2f} times faster than method 1 (basic array)')\n\tprintln('Method 3 (map) is ${f64(time1) / f64(time3):.2f} times faster than method 1 (basic array)')\n\tprintln('Method 4 (set) is ${f64(time1) / f64(time4):.2f} times faster than method 1 (basic array)')\n\n\tif time3 < time4 {\n\t\tprintln('Map is slightly faster than set, difference: ${time4 - time3}ms')\n\t} else {\n\t\tprintln('Set is slightly faster than map, difference: ${time3 - time4}ms')\n\t}\n}\n"
  },
  {
    "path": "bench/crypto/ecdsa/ecdsa.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <openssl/ec.h>\n#include <openssl/ecdsa.h>\n#include <openssl/obj_mac.h>\n#include <openssl/sha.h>\n#include <openssl/rand.h>\n#include <sys/time.h>\n\n#define ITERATIONS 1000\n#define MESSAGE \"Benchmark message\"\n\n// Function to calculate the difference in microseconds between two timevals\nlong time_diff_microseconds(struct timeval start, struct timeval end) {\n    long seconds = end.tv_sec - start.tv_sec;\n    long useconds = end.tv_usec - start.tv_usec;\n    return seconds * 1000000 + useconds;\n}\n\nint main() {\n    int iterations = ITERATIONS;\n    struct timeval start, end;\n    long total_gen_time = 0;\n    long total_sign_time = 0;\n    long total_verify_time = 0;\n    long avg_gen_time, avg_sign_time, avg_verify_time;\n\n    // Benchmarking key generation\n    printf(\"Benchmarking key generation...\\n\");\n    for(int i = 0; i < iterations; i++) {\n        gettimeofday(&start, NULL);\n\n        // Create a new EC_KEY object with the P-256 curve\n        EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);\n        if (key == NULL) {\n            fprintf(stderr, \"Error creating EC_KEY object.\\n\");\n            exit(EXIT_FAILURE);\n        }\n\n        // Generate the key\n        if (EC_KEY_generate_key(key) != 1) {\n            fprintf(stderr, \"Error generating EC key.\\n\");\n            EC_KEY_free(key);\n            exit(EXIT_FAILURE);\n        }\n\n        gettimeofday(&end, NULL);\n        total_gen_time += time_diff_microseconds(start, end);\n\n        // Free the key\n        EC_KEY_free(key);\n    }\n    avg_gen_time = total_gen_time / iterations;\n    printf(\"Average key generation time: %ld µs\\n\", avg_gen_time);\n\n    // Generate a single key for signing and verification\n    EC_KEY *priv_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);\n    if (priv_key == NULL) {\n        fprintf(stderr, \"Error creating EC_KEY object.\\n\");\n        exit(EXIT_FAILURE);\n    }\n    if (EC_KEY_generate_key(priv_key) != 1) {\n        fprintf(stderr, \"Error generating EC key.\\n\");\n        EC_KEY_free(priv_key);\n        exit(EXIT_FAILURE);\n    }\n\n    // Prepare the message hash\n    unsigned char hash[SHA256_DIGEST_LENGTH];\n    SHA256((unsigned char*)MESSAGE, strlen(MESSAGE), hash);\n\n    // Benchmarking signing\n    printf(\"Benchmarking signing...\\n\");\n    for(int i = 0; i < iterations; i++) {\n        gettimeofday(&start, NULL);\n\n        ECDSA_SIG *signature = ECDSA_do_sign(hash, SHA256_DIGEST_LENGTH, priv_key);\n        if (signature == NULL) {\n            fprintf(stderr, \"Error signing message.\\n\");\n            EC_KEY_free(priv_key);\n            exit(EXIT_FAILURE);\n        }\n\n        gettimeofday(&end, NULL);\n        total_sign_time += time_diff_microseconds(start, end);\n\n        // Free the signature\n        ECDSA_SIG_free(signature);\n    }\n    avg_sign_time = total_sign_time / iterations;\n    printf(\"Average sign time: %ld µs\\n\", avg_sign_time);\n\n    // Create a signature for verification benchmarking\n    ECDSA_SIG *signature = ECDSA_do_sign(hash, SHA256_DIGEST_LENGTH, priv_key);\n    if (signature == NULL) {\n        fprintf(stderr, \"Error signing message for verification.\\n\");\n        EC_KEY_free(priv_key);\n        exit(EXIT_FAILURE);\n    }\n\n    // Benchmarking verification\n    printf(\"Benchmarking verification...\\n\");\n    for(int i = 0; i < iterations; i++) {\n        gettimeofday(&start, NULL);\n\n        int verify_status = ECDSA_do_verify(hash, SHA256_DIGEST_LENGTH, signature, priv_key);\n\n        gettimeofday(&end, NULL);\n        total_verify_time += time_diff_microseconds(start, end);\n\n        if (verify_status != 1) {\n            fprintf(stderr, \"Signature verification failed.\\n\");\n            ECDSA_SIG_free(signature);\n            EC_KEY_free(priv_key);\n            exit(EXIT_FAILURE);\n        }\n    }\n    avg_verify_time = total_verify_time / iterations;\n    printf(\"Average verify time: %ld µs\\n\", avg_verify_time);\n\n    // Cleanup\n    ECDSA_SIG_free(signature);\n    EC_KEY_free(priv_key);\n\n    return 0;\n}\n\n"
  },
  {
    "path": "bench/crypto/ecdsa/ecdsa.go",
    "content": "package main\n\nimport (\n    \"crypto/ecdsa\"\n    \"crypto/elliptic\"\n    \"crypto/rand\"\n    \"fmt\"\n    \"time\"\n)\n\nfunc main() {\n    iterations := 1000\n\n    fmt.Println(\"Benchmarking key generation...\")\n    var totalGenTime int64\n    for i := 0; i < iterations; i++ {\n        start := time.Now()\n        _, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)\n        if err != nil {\n            panic(err)\n        }\n        totalGenTime += time.Since(start).Microseconds()\n    }\n    avgGenTime := totalGenTime / int64(iterations)\n    fmt.Printf(\"Average key generation time: %d µs\\n\", avgGenTime)\n\n    privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)\n    if err != nil {\n        panic(err)\n    }\n    message := []byte(\"Benchmark message\")\n\n    fmt.Println(\"Benchmarking signing...\")\n    var totalSignTime int64\n    for i := 0; i < iterations; i++ {\n        start := time.Now()\n        _, _, err := ecdsa.Sign(rand.Reader, privKey, message)\n        if err != nil {\n            panic(err)\n        }\n        totalSignTime += time.Since(start).Microseconds()\n    }\n    avgSignTime := totalSignTime / int64(iterations)\n    fmt.Printf(\"Average sign time: %d µs\\n\", avgSignTime)\n\n    r, s, err := ecdsa.Sign(rand.Reader, privKey, message)\n    if err != nil {\n        panic(err)\n    }\n\n    pubKey := &privKey.PublicKey\n\n    fmt.Println(\"Benchmarking verification...\")\n    var totalVerifyTime int64\n    for i := 0; i < iterations; i++ {\n        start := time.Now()\n        ecdsa.Verify(pubKey, message, r, s)\n        totalVerifyTime += time.Since(start).Microseconds()\n    }\n    avgVerifyTime := totalVerifyTime / int64(iterations)\n    fmt.Printf(\"Average verify time: %d µs\\n\", avgVerifyTime)\n}\n\n"
  },
  {
    "path": "bench/crypto/ecdsa/ecdsa.v",
    "content": "import time\nimport crypto.ecdsa\n\nfn main() {\n\titerations := 1000\n\n\tprintln('Benchmarking key generation...')\n\tmut total_gen_time := i64(0)\n\tfor _ in 0 .. iterations {\n\t\tsw := time.new_stopwatch()\n\t\t_, _ := ecdsa.generate_key() or { panic(err) }\n\t\telapsed := sw.elapsed().microseconds()\n\t\ttotal_gen_time += elapsed\n\t}\n\tavg_gen_time := total_gen_time / iterations\n\tprintln('Average key generation time: ${avg_gen_time} µs')\n\n\tpub_key, priv_key := ecdsa.generate_key() or { panic(err) }\n\tmessage := 'Benchmark message'.bytes()\n\n\tprintln('Benchmarking signing...')\n\tmut total_sign_time := i64(0)\n\tfor _ in 0 .. iterations {\n\t\tsw := time.new_stopwatch()\n\t\t_ := priv_key.sign(message) or { panic(err) }\n\t\telapsed := sw.elapsed().microseconds()\n\t\ttotal_sign_time += elapsed\n\t}\n\tavg_sign_time := total_sign_time / iterations\n\tprintln('Average sign time: ${avg_sign_time} µs')\n\n\tsig := priv_key.sign(message) or { panic(err) }\n\n\tprintln('Benchmarking verification...')\n\tmut total_verify_time := i64(0)\n\tfor _ in 0 .. iterations {\n\t\tsw := time.new_stopwatch()\n\t\t_ := pub_key.verify(message, sig) or { panic(err) }\n\t\telapsed := sw.elapsed().microseconds()\n\t\ttotal_verify_time += elapsed\n\t}\n\tavg_verify_time := total_verify_time / iterations\n\tprintln('Average verify time: ${avg_verify_time} µs')\n}\n"
  },
  {
    "path": "bench/vectors/README.md",
    "content": "# Comparing C# and V Boids Algorithm Implementations\n\n## Running the C# program:\n\n```\ndotnet run\n```\n\nCreating a release version of the C# program:\n\n```\ndotnet publish -c Release -r ubuntu.20.04-x64\n```\n\nThe generated executable will be in\n`/v/vnew/bench/vectors/bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors`\nIts size is ~64MB . After stripping, the executable shrinks to just 11MB,\nbut unfortunately it also stops running after stripping :-| .\n\n## Compiling and running the V program:\n\n```\nv crun vectors.v\n```\n\n... produces and runs a `vectors` executable which is ~1.3MB in size.\n\nCompiling and running the V program, compiled with -prod:\n\n```\nv -prod crun vectors.v\n```\n\n... produces and runs a `vectors` executable which is ~176KB in size.\nAfter stripping, the executable shrinks to 157KB. It can still run after\nstripping.\n\nNote: using `crun` will make sure that the compilation will happen just\nonce at the start, and then the executable will be just reused by the\nsubsequent commands with identical options. It will also ensure that\nthe compiled executable will not be removed, unlike `run` .\n\n## Some measurements and comparisons\n\nNote: the following was done on Intel(R) Core(TM) i3-3225, 16GB RAM:\n\n```\n#0 13:41:35 ᛋ master /v/vnew/bench/vectors❱rm -rf vectors\n#0 13:41:49 ᛋ master /v/vnew/bench/vectors❱\n#0 13:41:49 ᛋ master /v/vnew/bench/vectors❱v -o vectors_development vectors.v\n#0 13:42:14 ᛋ master /v/vnew/bench/vectors❱v -o vectors_production -prod vectors.v\n#0 13:42:28 ᛋ master /v/vnew/bench/vectors❱\n#0 13:42:29 ᛋ master /v/vnew/bench/vectors❱hyperfine ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors ./vectors_development ./vectors_production\nBenchmark 1: ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors\n  Time (mean ± σ):     347.4 ms ±   7.4 ms    [User: 334.4 ms, System: 13.0 ms]\n  Range (min … max):   340.2 ms … 361.7 ms    10 runs\n\nBenchmark 2: ./vectors_development\n  Time (mean ± σ):     882.6 ms ±  14.0 ms    [User: 880.3 ms, System: 2.3 ms]\n  Range (min … max):   862.4 ms … 912.9 ms    10 runs\n\nBenchmark 3: ./vectors_production\n  Time (mean ± σ):     217.9 ms ±   9.4 ms    [User: 216.8 ms, System: 0.9 ms]\n  Range (min … max):   206.4 ms … 241.3 ms    12 runs\n\nSummary\n  ./vectors_production ran\n    1.59 ± 0.08 times faster than ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors\n    4.05 ± 0.19 times faster than ./vectors_development\n#0 13:43:00 ᛋ master /v/vnew/bench/vectors❱\n#0 13:45:07 ᛋ master /v/vnew/bench/vectors❱ls -nlarS ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors ./vectors_development ./vectors_production\n-rwxrwxr-x 1 1000 1000   179384 Sep  6 13:42 ./vectors_production\n-rwxrwxr-x 1 1000 1000  1320764 Sep  6 13:42 ./vectors_development\n-rwxr-xr-x 1 1000 1000 66732821 Sep  6 13:40 ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors\n#0 13:45:12 ᛋ master /v/vnew/bench/vectors❱\n#0 13:53:12 ᛋ master /v/vnew/bench/vectors❱alias xtime='/usr/bin/time -f \"CPU: %Us\\tReal: %es\\tElapsed: %E\\tRAM: %MKB\\t%C\"'\n#0 13:53:42 ᛋ master /v/vnew/bench/vectors❱xtime ./vectors_development\n5.0498380931718074e+07 - 5.0504723697762154e+07 - 5.040198063489048e+07\n0.0 - 0.0 - 0.0\nCPU: 0.87s      Real: 0.87s     Elapsed: 0:00.87        RAM: 4404KB     ./vectors_development\n#0 13:53:52 ᛋ master /v/vnew/bench/vectors❱xtime ./vectors_production\n4.971971434731853e+07 - 4.973120986372047e+07 - 5.030988639116867e+07\n0.0 - 0.0 - 0.0\nCPU: 0.20s      Real: 0.20s     Elapsed: 0:00.20        RAM: 3228KB     ./vectors_production\n#0 13:53:58 ᛋ master /v/vnew/bench/vectors❱xtime ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors\n(49627678.97075553, 50302418.6269631, 49705582.70645027)\n(0, 0, 0)\nCPU: 0.33s      Real: 0.34s     Elapsed: 0:00.34        RAM: 30544KB    ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors\n#0 13:54:02 ᛋ master /v/vnew/bench/vectors❱\n#0 14:01:33 ᛋ master /v/vnew/bench/vectors❱\n#0 14:01:35 ᛋ master /v/vnew/bench/vectors❱xtime v vectors.v\nCPU: 0.41s      Real: 0.36s     Elapsed: 0:00.36        RAM: 59412KB    v vectors.v\n#0 14:01:41 ᛋ master /v/vnew/bench/vectors❱\n#0 14:01:42 ᛋ master /v/vnew/bench/vectors❱xtime v -prod vectors.v\nCPU: 4.97s      Real: 5.11s     Elapsed: 0:05.11        RAM: 80732KB    v -prod vectors.v\n#0 14:01:48 ᛋ master /v/vnew/bench/vectors❱\n#0 14:01:50 ᛋ master /v/vnew/bench/vectors❱xtime dotnet publish -c Release -r ubuntu.20.04-x64\nMSBuild version 17.7.1+971bf70db for .NET\n  Determining projects to restore...\n  All projects are up-to-date for restore.\n  vectors -> /v/vnew/bench/vectors/bin/Release/net7.0/ubuntu.20.04-x64/vectors.dll\n  vectors -> /v/vnew/bench/vectors/bin/Release/net7.0/ubuntu.20.04-x64/publish/\nCPU: 2.34s      Real: 2.64s     Elapsed: 0:02.64        RAM: 159816KB   dotnet publish -c Release -r ubuntu.20.04-x64\n#0 14:01:56 ᛋ master /v/vnew/bench/vectors❱\n```\n"
  },
  {
    "path": "bench/vectors/vectors.cs",
    "content": "using System;\n\ninternal readonly struct Vector\n{\n    public readonly double X;\n    public readonly double Y;\n    public readonly double Z;\n\n    public Vector(double x, double y, double z)\n    {\n        X = x;\n        Y = y;\n        Z = z;\n    }\n\n    public override string ToString()\n    {\n        return $\"({X}, {Y}, {Z})\";\n    }\n}\n\n\nclass Program\n{\n    static void Main(string[] args)\n    {\n        const int boidsCount = 10000;\n\n        var positions = new Vector[boidsCount];\n        var velocities = new Vector[boidsCount];\n\n        const double maxCoordinate = 10000.0;\n\n        var random = new Random();\n\n        for (var positionIndex = 0; positionIndex < positions.Length; positionIndex++)\n        {\n            positions[positionIndex] = new Vector(\n                x: random.NextDouble() * maxCoordinate,\n                y: random.NextDouble() * maxCoordinate,\n                z: random.NextDouble() * maxCoordinate\n            );\n        }\n\n        const double cohesionDistance = 10.0;\n        const double separationDistance = 5.0;\n\n        var closeBoids = new List<int>();\n\n        for (var boidIndex = 0; boidIndex < positions.Length; boidIndex++)\n        {\n            var position = positions[boidIndex];\n            closeBoids.Clear();\n\n            for (var otherBoidIndex = 0; otherBoidIndex < positions.Length; otherBoidIndex++)\n            {\n                if (boidIndex == otherBoidIndex)\n                {\n                    continue;\n                }\n\n                var otherPosition = positions[otherBoidIndex];\n\n                var differenceX = position.X - otherPosition.X;\n                var differenceY = position.Y - otherPosition.Y;\n                var differenceZ = position.Z - otherPosition.Z;\n\n                var distance = differenceX * differenceX +\n                    differenceY * differenceY +\n                    differenceZ * differenceZ;\n\n                if (distance <= cohesionDistance * cohesionDistance)\n                {\n                    closeBoids.Add(otherBoidIndex);\n                }\n            }\n\n            if (closeBoids.Count == 0)\n            {\n                continue;\n            }\n\n            var cohesion = new Vector(0.0, 0.0, 0.0);\n            var separation = new Vector(0.0, 0.0, 0.0);\n            var separationCount = 0;\n            var alignment = new Vector(0.0, 0.0, 0.0);\n\n            foreach (var closeBoidIndex in closeBoids)\n            {\n                var closeBoidPosition = positions[closeBoidIndex];\n\n                cohesion = new Vector(\n                    cohesion.X + closeBoidPosition.X,\n                    cohesion.Y + closeBoidPosition.Y,\n                    cohesion.Z + closeBoidPosition.Z\n                );\n\n                var differenceFromClosest = new Vector(\n                    position.X - closeBoidPosition.X,\n                    position.Y - closeBoidPosition.Y,\n                    position.Z - closeBoidPosition.Z\n                );\n\n                var differenceMagnitude = Math.Sqrt(differenceFromClosest.X * differenceFromClosest.X + differenceFromClosest.Y * differenceFromClosest.Y + differenceFromClosest.Z * differenceFromClosest.Z);\n\n                if (differenceMagnitude <= separationDistance)\n                {\n                    separation = new Vector(\n                        separation.X + differenceFromClosest.X / differenceMagnitude,\n                        separation.Y + differenceFromClosest.Y / differenceMagnitude,\n                        separation.Z + differenceFromClosest.Z / differenceMagnitude\n                    );\n\n                    separationCount++;\n                }\n\n                var closeBoidVelocity = velocities[closeBoidIndex];\n\n                alignment = new Vector(\n                    alignment.X + closeBoidVelocity.X,\n                    alignment.Y + closeBoidVelocity.Y,\n                    alignment.Z + closeBoidVelocity.Z\n                );\n            }\n\n            cohesion = new Vector(\n                cohesion.X / closeBoids.Count,\n                cohesion.Y / closeBoids.Count,\n                cohesion.Z / closeBoids.Count\n            );\n\n            var cohesionForce = new Vector(\n                cohesion.X - position.X,\n                cohesion.Y - position.Y,\n                cohesion.Z - position.Z\n            );\n\n            if (separationCount > 0)\n            {\n                separation = new Vector(\n                    separation.X / separationCount,\n                    separation.Y / separationCount,\n                    separation.Z / separationCount\n                );\n            }\n\n            alignment = new Vector(\n                alignment.X / closeBoids.Count,\n                alignment.Y / closeBoids.Count,\n                alignment.Z / closeBoids.Count\n            );\n\n            var currentVelocity = velocities[boidIndex];\n\n            velocities[boidIndex] = new Vector(\n                currentVelocity.X + cohesionForce.X + separation.X + alignment.X,\n                currentVelocity.Y + cohesionForce.Y + separation.Y + alignment.Y,\n                currentVelocity.Z + cohesionForce.Z + separation.Z + alignment.Z\n            );\n        }\n\n        var positionSum = new Vector(0.0, 0.0, 0.0);\n        var velocitySum = new Vector(0.0, 0.0, 0.0);\n\n        for (var boidIndex = 0; boidIndex < positions.Length; boidIndex++)\n        {\n            var position = positions[boidIndex];\n            var velocity = velocities[boidIndex];\n\n            positions[boidIndex] = new Vector(\n                position.X + velocity.X,\n                position.Y + velocity.Y,\n                position.Z + velocity.Z\n            );\n\n            positionSum = new Vector(\n                positionSum.X + position.X,\n                positionSum.Y + position.Y,\n                positionSum.Z + position.Z\n            );\n\n            velocitySum = new Vector(\n                velocitySum.X + velocity.X,\n                velocitySum.Y + velocity.Y,\n                velocitySum.Z + velocity.Z\n            );\n        }\n\n        Console.WriteLine(positionSum.ToString());\n        Console.WriteLine(velocitySum.ToString());\n    }\n}\n\n"
  },
  {
    "path": "bench/vectors/vectors.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n\t<PublishSingleFile>true</PublishSingleFile>\n\t<SelfContained>true</SelfContained>\n\t\n    <TargetFramework>net7.0</TargetFramework>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <Nullable>enable</Nullable>\n\t<OutputType>Exe</OutputType>\n  </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "bench/vectors/vectors.runtimeconfig.json",
    "content": "{\"runtimeOptions\":{\"framework\":{\"name\":\"Microsoft.NETCore.App\",\"version\":\"7.0.10\"}}}\n"
  },
  {
    "path": "bench/vectors/vectors.v",
    "content": "module main\n\nimport rand\nimport math\n\nstruct Vector {\n\tx f64\n\ty f64\n\tz f64\n}\n\nconst boids_count = 10000\nconst max_coordinate = 10000.0\nconst cohesion_distance = 10.0\nconst separation_distance = 5.0\n\n@[direct_array_access]\nfn main() {\n\tmut positions := [boids_count]Vector{}\n\tmut velocities := [boids_count]Vector{}\n\n\tfor position_index in 0 .. positions.len {\n\t\tpositions[position_index] = Vector{\n\t\t\tx: rand.f64() * max_coordinate\n\t\t\ty: rand.f64() * max_coordinate\n\t\t\tz: rand.f64() * max_coordinate\n\t\t}\n\t}\n\n\tfor boid_index in 0 .. positions.len {\n\t\tposition := positions[boid_index]\n\t\tmut close_boids_ids := []int{}\n\n\t\tfor other_boid_index in 0 .. positions.len {\n\t\t\tif boid_index == other_boid_index {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tother_position := positions[other_boid_index]\n\n\t\t\tdifference_x := position.x - other_position.x\n\t\t\tdifference_y := position.y - other_position.y\n\t\t\tdifference_z := position.z - other_position.z\n\n\t\t\tdistance := difference_x * difference_x + difference_y * difference_y +\n\t\t\t\tdifference_z * difference_z\n\n\t\t\tif distance <= cohesion_distance * cohesion_distance {\n\t\t\t\tclose_boids_ids << other_boid_index\n\t\t\t}\n\t\t}\n\n\t\tif close_boids_ids.len == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\tmut cohesion := Vector{}\n\t\tmut separation := Vector{}\n\t\tmut separation_count := 0\n\t\tmut alignment := Vector{}\n\n\t\tfor close_boid_id in close_boids_ids {\n\t\t\tclose_boid_position := positions[close_boid_id]\n\n\t\t\tcohesion = Vector{\n\t\t\t\tx: cohesion.x + close_boid_position.x\n\t\t\t\ty: cohesion.y + close_boid_position.y\n\t\t\t\tz: cohesion.z + close_boid_position.z\n\t\t\t}\n\n\t\t\tdifference_from_closest := Vector{\n\t\t\t\tx: position.x - close_boid_position.x\n\t\t\t\ty: position.y - close_boid_position.y\n\t\t\t\tz: position.z - close_boid_position.z\n\t\t\t}\n\n\t\t\tdifference_magnitude := math.sqrt(\n\t\t\t\tdifference_from_closest.x * difference_from_closest.x +\n\t\t\t\tdifference_from_closest.y * difference_from_closest.y +\n\t\t\t\tdifference_from_closest.z * difference_from_closest.z)\n\n\t\t\tif difference_magnitude <= separation_distance {\n\t\t\t\tseparation = Vector{\n\t\t\t\t\tx: separation.x + difference_from_closest.x / difference_magnitude\n\t\t\t\t\ty: separation.y + difference_from_closest.y / difference_magnitude\n\t\t\t\t\tz: separation.z + difference_from_closest.z / difference_magnitude\n\t\t\t\t}\n\n\t\t\t\tseparation_count += 1\n\t\t\t}\n\n\t\t\tclose_boid_velocity := velocities[close_boid_id]\n\n\t\t\talignment = Vector{\n\t\t\t\tx: alignment.x + close_boid_velocity.x\n\t\t\t\ty: alignment.y + close_boid_velocity.y\n\t\t\t\tz: alignment.z + close_boid_velocity.z\n\t\t\t}\n\t\t}\n\n\t\tcohesion = Vector{\n\t\t\tx: cohesion.x / close_boids_ids.len\n\t\t\ty: cohesion.y / close_boids_ids.len\n\t\t\tz: cohesion.z / close_boids_ids.len\n\t\t}\n\n\t\tcohesion_force := Vector{\n\t\t\tx: cohesion.x - position.x\n\t\t\ty: cohesion.y - position.y\n\t\t\tz: cohesion.z - position.z\n\t\t}\n\n\t\tif separation_count > 0 {\n\t\t\tseparation = Vector{\n\t\t\t\tx: separation.x / separation_count\n\t\t\t\ty: separation.y / separation_count\n\t\t\t\tz: separation.z / separation_count\n\t\t\t}\n\t\t}\n\n\t\talignment = Vector{\n\t\t\tx: alignment.x / close_boids_ids.len\n\t\t\ty: alignment.y / close_boids_ids.len\n\t\t\tz: alignment.z / close_boids_ids.len\n\t\t}\n\n\t\tcurrent_velocity := velocities[boid_index]\n\n\t\tvelocities[boid_index] = Vector{\n\t\t\tx: current_velocity.x + cohesion_force.x + separation.x + alignment.x\n\t\t\ty: current_velocity.y + cohesion_force.y + separation.y + alignment.y\n\t\t\tz: current_velocity.z + cohesion_force.z + separation.z + alignment.z\n\t\t}\n\t}\n\n\tmut position_sum := Vector{}\n\tmut velocity_sum := Vector{}\n\n\tfor boid_index in 0 .. positions.len {\n\t\tposition := positions[boid_index]\n\t\tvelocity := velocities[boid_index]\n\n\t\tpositions[boid_index] = Vector{\n\t\t\tx: position.x + velocity.x\n\t\t\ty: position.y + velocity.y\n\t\t\tz: position.z + velocity.z\n\t\t}\n\n\t\tposition_sum = Vector{\n\t\t\tx: position_sum.x + position.x\n\t\t\ty: position_sum.y + position.y\n\t\t\tz: position_sum.z + position.z\n\t\t}\n\n\t\tvelocity_sum = Vector{\n\t\t\tx: velocity_sum.x + velocity.x\n\t\t\ty: velocity_sum.y + velocity.y\n\t\t\tz: velocity_sum.z + velocity.z\n\t\t}\n\t}\n\n\tprintln('${position_sum.x} - ${position_sum.y} - ${position_sum.z}')\n\tprintln('${velocity_sum.x} - ${velocity_sum.y} - ${velocity_sum.z}')\n}\n"
  },
  {
    "path": "changelogs0.x/0.4.md",
    "content": "## V 0.4\n*1 July 2023*\n\n#### Improvements in the language\n- **Coroutines with a scheduler**. Only Linux/macOS for now, requires `-use-coroutines` and\n  `coroutines.sleep()` instead of `time.sleep()`. They work with IO and net, but not with GC\n  for now.\n- `spawn` now spawns system threads, `go` spawns coroutines.\n- Static type methods: `Foo.new()` to replace factory functions like `new_foo()`.\n- Smartcasting with complex conditions:\n  `if sum_type is Foo && !sum_type.is_info && get_name(sum_type.info.name) == 'foo' `.\n- Functions can now return fixed size arrays.\n- Enum values now can have attributes.\n- Generic functions as function parameters are now supported: `fn f[T](x T, i int, f_ Fn[T]) T { `.\n- Anonymous structs can no longer have attributes.\n- A new `[spawn_stack: 131072]` function attribute for controlling the max size of the stack\n  of the spawned threads.\n- Channel pop now works with an `or` block: `ch := <-self.item or { return none }`\n- `it` has been renamed to `index` in array inits.\n- String interpolation simplified to just '${name}', enforced by vfmt,\n  and updated in the entire code base.\n- `go foo()` has been replaced with `spawn foo()` (launches an OS thread, `go` will be used for\n  upcoming coroutines instead).\n- vfmt now supports `// vfmt off` and `// vfmt on` for turning off the formatting locally\n  for short snippets of code.\n  Useful for keeping your carefully arranged matrices intact.\n- Match branch range expressions with consts: `match x { const1...const2 {} }`\n- Hot code reloading via `[live]` is now supported in imported modules, not just the main module.\n- Syntax sugar for map inits without needing explicit casts for interfaces:\n  `all.children := { \"abc\": rect, \"def\": ui.rectangle()}`.\n- `$embed_file()` fixes, including variable args support.\n- `none` fixes: no longer allowed to be used as a separate type, `dump()` support,\n  not allowed inside `unsafe`.\n- Const functions: `const y = term.yellow`, then `println(y('abc'))`.\n- Builtin type names can no longer be used as identifiers.\n- Generic `typeof[T]()`, `sizeof[T]()`, `isreftype[T]()` functions.\n- Deprecated `-error-limit` in favour of the documented `-message-limit` option.\n- Maps now support aliased keys.\n- Operator overloading now works with reference types.\n- Generic struct inits with nested generic structs and generic optional types are now allowed.\n- During array creation, `len:` is required when using default values for the array.\n- Optimized one byte `[]u8` arrays creation.\n- Recursive aliasing is no longer allowed (e.g. `type Alias = map[string]Alias`).\n- Easier custom error creation: `return MyCustomErr{}` instead of `return IError(MyCustomErr)`.\n- All floats outputs now have `.0` conditionally appended to them to improve clarity.\n- Custom integer enum types: `enum Xyz as u64 {`.\n- AST transformer fixes and optimizations.\n- Stylistic improvements and bug fixes in vfmt.\n- Casting integers to enums now requires `unsafe{}`.\n- Improved error and warning messages.\n- Parallel compilation now uses `sync.Pool`.\n- `-skip-unused` fixes, soon to be made the default.\n- Anonymous structs.\n- Lots of bug fixes: 90% of all bugs ever submitted are closed.\n- New keyword/type: `nil`. Only to be used inside `unsafe`. Replaces `voidptr(0)`.\n- V can now find code in the `src/` directory. This allows making V repos much cleaner.\n- Support `assert condition, extra_message`, where the `extra_message` will be evaluated\n  and shown if the assertion fails.\n- Operator overloading now works with aliases and generics.\n- Scanner optimizations.\n- Using C's #define is no longer allowed in normal V code, only in `.c.v` files.\n\n#### Breaking changes\n- `byte` deprecated in favor of `u8` (`byte` is automatically converted to `u8` by vfmt).\n- `json`: enums are serialized as strings by default, `[json_as_number]` attribute can be used for\n  the old behavior.\n- Variable shadowing has been completely banned (previously variable names could conflict with\n  module names).\n- `[]` is now used for generics instead of `<>`.\n- Accessing a pointer map value requires an `or {}` block outside `unsafe`.\n- Anonymous sumtypes have been removed (deprecated for now) due to complicating the language\n  and the compiler too much.\n\n\n#### Checker improvements/fixes\n- Disallow `Result` type aliases (`type Foo = !Bar`) and `Result` in maps (`map[key]!Type`).\n- Add a missing check for taking address of literal value member.\n- Fixed map initialization for maps with option values.\n- Allow `a << none`, where `a` is `[]?&int`.\n- Disallow multiple `else` branches in a match.\n- Fix index expression with sumtype of array types.\n- Remove hardcoded check for function calls for `C.stat`, `C.sigaction`, etc.\n- Fix multiple embedded external module interface.\n- Fix missing check for diff type on map value declaration.\n- Simplify error handling in the checker (#18507).\n- Option alias fixes.\n- Fix alias to struct ptr on struct init.\n- Sumtypes can no longer hold references.\n- Fix a bug checking generic closures.\n- A hard to reach limit of 1 million iterations for resolving all generics.\n- Fix missing check for unwrapped shift operation.\n- Fix enum max value validation.\n- Add a missing mutability check for `array.delete` calls.\n- Disallow `_ = <- quit`.\n- Disallow type matching with primitive vars.\n- Warning instead of error for unnecessary brackets in if/match.\n- Include import aliases when checking for import duplicates.\n- Fix inferring generic array type in nested call.\n- Allow casted `enum val` and `const` as fixed array size.\n- Disallow multiple return values in const declarations.\n- Fix contains() with array of interfaces.\n- Disallow mut for blank idents.\n- If guards now work with struct fields which are `Option` functions.\n  Such fields can now also be assigned to other fields/variables.\n- Option receivers can no longer have methods.\n- `none` can now be cast to all `Option` types, including aliases.\n- Option references are now supported: `?&Type`.\n- Arrays of `Option`s are now allowed.\n- Allow `foo := Foo{}`, when `Foo` has an Option field, that is a struct, that has a `[required]`\n  tag on its fields.\n- Enums can no longer be initialized like structs.\n- Capture variables can no longer shadow anonymous function params.\n- Mixing multi-return results with other types in return statements is no longer allowed.\n- Assigning anonymous structs to named structs is no longer allowed.\n- `[required]` fields are now checked for embedded structs.\n- Fixed a bug with closures with fixed array variables.\n- Builtin methods `first/last/repeat` can now be used in custom user types (previously they only\n  worked in builtin arrays).\n- Generic struct initialization no longer needs explicit types to be provided:\n  ```v\n  struct Foo[T, U] {\n  \ta T\n  \tb U\n  }\n\n  foo := Foo{\n  \ta: 2\n  \tb: 'x'\n  }\n\n  println(foo)\n  ```\n- unsafe: dereferencing nil references is no longer allowed in the following case:\n  ```v\n  a := unsafe { nil }\n  println(*a)\n  ```\n- Lots of fixes in the type checker.\n- Int signedness mismatch is now checked: `cannot use literal signed integer as u8`.\n- Improved type checker: lots of new type checks and fixed checker bugs.\n- Unused last expression in `if` is now checked.\n- Anonymous structs visibility issues fixed.\n- More type checks.\n- Lots of fixes in `shared` types.\n\n#### Standard library\n- json: Enum value string serialization supports `[json:'alias']` to change its string values.\n- Struct fields can now be skipped during JSON/ORM serialization via `[json:'-']` and `[sql:'-']`,\n  in addition to `[skip]`. This allows having custom behavior for different serialization methods.\n- builtin: heap usage API (gc_memory_use() and gc_heap_usage())\n- math.big: refactoring, gcd fixes/improvements, overflow fixes, `mod_inverse`.\n- flag: fix finalize with multiple shortargs.\n- runtime: add new functions total_memory/0 and free_memory/0.\n- time: small cleanup of parse_iso8601 comments, make the C.strftime declaration forwards compatible\n- stbi: allow customization of number of channels in `stbi.load()`.\n- stbi: add a `resize_uint8` function for resizing images in memory.\n- time, x.json2: improve iso8601 time decoding.\n- builtin: zero out internal map/array pointers on m.free(), to reduce the work for the GC\n  mark phase for non escaping maps/arrays, used in hot loops.\n- time: add more detailed error descriptions, add custom format parsing with time.parse_format.\n- sync: add Mutex.destroy and RwMutex.destroy methods.\n- datatypes: add Bloom filter.\n- rand: add missing rand.u16(), update doc comments, add test.\n- builtin: speed up string methods with vmemcpy instead of `for` loop for copying data.\n- Added new `termios` module.\n- `net.ssl`: types using ssl contexts can now be converted to strings via `.str()`/printed\n  via `println()`.\n- `v.reflection`: added type symbol info metadata.\n- `crypto` and `math` modules have been updated to use `Result` instead of `Option`.\n- `datatypes.LinkedList[map]` now works correctly.\n- `urllib.Values.get()` now returns an Option.\n- `strconv`: `v_printf()` was made private, `v_sprintf()` was deprecated. String interpolation\n  should be used instead.\n- `net.http`: mime types have been updated to include all official types.\n- `gg`: `create_image()` now returns `!Image` instead of `Image`, allowing to handle errors.\n- `sokol`: errors during image creation no longer result in a panic, but can be handled by the\n  programmer.\n- `sokol`: macOS apps can now be quit using **Cmd+Q**.\n- `os.hostname()` and `os.loginname()` now return `Result`.\n- `strconv.atoi` optimizations.\n- `println()` now supports arrays with recursive references.\n- `termux`: support for cross-compilation from termux to other platforms.\n- `readline` module now works much better on macOS: key navigation, history, etc (now on par with\n  Linux).\n- `os`: fixed a memleak in `getline()`.\n- `os.Process` now has a `create_no_window` option (Windows only).\n- `os.Process` now has a `set_work_folder()` method to set the initial working folder of the new\n  child process.\n- `math.vec` module for generic vector math including 2D, 3D, and 4D vector operations.\n- Builtin stb_image.h used by gg has been updated to the latest v2.28.\n- All of vlib has been updated to use separate Option/Result types.\n- To avoid confusion, all references in the code and documentation to `Optional` have been\n  replaced with `Option`.\n- `gg.Context` pipeline has more effects, including the `additive` effect.\n- Much cleaner eof checks in `os`: refactor `err == IError(os.Eof{})` to `err is os.Eof`.\n- Lots of work on `x.json2`, the pure V json encoder, soon to become official.\n- New `v.reflection` module for runtime reflection.\n- Improved `os.mv()`, which now works consistently even across different\n  windows drives/mount points.\n- `string.trim_indent()`, useful with multi line strings, that start/end with new lines\n  and indentation.\n- Reduced memory consumption in the `crypto` modules.\n- Official V UI library is now licensed under MIT.\n- Deprecated `math.util` and `math.mathutil` have been removed.\n- New time format support: `time.format_rfc3339()`.\n- `encoding.html.escape()`.\n- All public functions in the `hash` and `encoding.base32` modules have been documented.\n- New `crypto.pem` module.\n- New `map.reserve()` method.\n- `net.ssl` has been migrated from a dynamically linked OpenSSL to a statically linked Mbed TLS.\n  This means that V binaries will no longer have an OpenSSL dependency.\n  OpenSSL can still be enabled via `-d use_openssl`.\n- msgpack module for decoding/encoding msgpack. (`v install msgpack`)\n- Most of vlib has been updated to use the new Option/Result types.\n- net, net.http, vweb bugs and fixes.\n- QuadTree and RingBuffer types in `datatypes`.\n- Forward iterator for `datatypes.LinkedList<T>`, forward and backward iterators\n  for `datatypes.DoublyLinkedList<T>`.\n- A new `maps` module, similar to existing `arrays`. It has generic `filter`, `flatten`,\n  `invert`, `to_map`, `to_array`, `from_array` functions.\n- `utf8.is_number()`, `utf8.is_space()` functions.\n- New `encoding.base32` module.\n- `gg.TouchPoint` to differentiate between different types of touch input.\n- `str.int()` conversion speedup (without -prod).\n- `os.mkdir()` now has an optional `mode` parameter.\n- `encoding.csv` is now generic, supports bools, accepts a custom delimiter,\n  and is compatible with io.Reader/io.Writer.\n- `datatypes` module now uses operator overloading.\n- All `datatypes` types can be converted to V arrays.\n- `smtp` improvements including multiple recipients and base64/utf8 support.\n- `arrays.carray_to_varray<T>()` for converting C arrays to V arrays.\n- `strconv.v_sprintf()` has been deprecated in favor of string interpolation.\n- TOML module now supports `[toml:...]` attributes, just like the JSON module.\n- `os.walk()` is no longer recursive (still works the same).\n- `io` has been migrated to `Result`.\n- Third party window control in Sokol.\n- `string.replace_char()`, `math.round_sig()`.\n- Improved multiplication performance in `math.big`.\n\n#### Web\n- The builtin websocket library is now thread safe.\n- Enhanced builtin csrf protection in vweb.\n- vweb: ability to set and get values on vweb.Context.\n- vweb: support for host specific static files.\n- vweb: host option added to controller, and a new host attribute.\n- vweb: middleware docs improved; same with docs for `[vweb_global]` and `shared`.\n- vweb: return 404 on file not found.\n- net.http: copy IANA's list of methods to the http.Method enum.\n- net.conv: use a pure V implementation instead of C.hton etc.\n- net.html: `get_tag()` methods to find first tag occurrence.\n- net.html: fixed text parsing for inline tags.\n- net.html: fix parsing of nested quoted strings in code tags.\n- picoev: FreeBSD support.\n- vweb now supports live page reloading.\n  The web app is instantly updated in the browser (no need to refresh the page)\n  every time a **.v** or a **.html** file is changed.\n- vweb is now significantly faster and more stable under load, due to a new multithreaded worker\n  pool, which is much more efficient at spreading the workload among all threads equally.\n- vweb now supports middleware.\n- vweb now supports controllers.\n  It's now possible to have multiple app structs to better separate logic.\n- vweb now supports overridable `.not_found()` method for custom 404 pages in vweb.\n- vweb now uses database pool.\n- Fixed multipart form parsing in vweb.\n- Improved vweb stability under load.\n- `vweb.csrf` module.\n- `net.urllib` ipv6 support.\n- `net.Http.Response.text` renamed to `body`.\n- `net.websocket` timeout is now configurable.\n\n#### ORM\n- Fixed a foreign key bug that could result in an extra insert.\n- Comptime bug with `[skip]` and `[sql:'-']` fixed.\n- Checker error for unsupported field types.\n- Allow structs without the id field, more flexible primary keys.\n- Improved docs and examples.\n- Uninitialized structs are no longer inserted into related tables.\n- All ORM queries now return `![]` (`Result` of an array).\n  This allows handling/propagating DB errors and simplifies working with ORM (one way).\n- Many ORM improvements: type checks for `limit/offset/order by/where`; support of reference objects\n  in `insert`; struct fields can be used with `limit/offset`; `Connection` interface.\n- ORM now supports the `like` operator:\n  ```v\n  users := sql db {\n      select from User where name like 'Bob%'\n  }\n  ```\n- A new `-d trace_orm` option to see all SQL queries generated and used by V ORM and\n  `-d trace_pg_error` to trace PG errors.\n- Various ORM fixes and improvements, including string interpolation support, type checks,\n  fn calls in `where`.\n- Support parenthesized expressions like\n  `select from User where (name == 'Sam' && is_customer == true) || id == 1`.\n- ORM functions now return `Result`, so the errors can be handled.\n\n#### Database drivers\n- mysql: TIMESTAMP support.\n- mysql: allocate memory for each string and blob dynamically depending on its value length.\n- mysql: add the ability to commit transactions.\n- VFS support in the builtin `sqlite` module; `sqlite.get_affected_rows_count()`.\n- Improved `pg` compatibility with older PostgreSQL versions before 2014.\n- `sqlite`, `pg`, `mysql` have been moved to `db.sqlite`, `db.pg`, `db.mysql`.\n\n#### Native backend\n- Refactoring, splitting large files into multiple.\n- Lots of fixes and new features in the native backend, including making codegen logic\n  platform independent.\n- Operator support for floats, multi return.\n- Lots of native backend improvements, including library calls, comptime conditionals,\n  enums, method definitions/calls, structs.\n- Major improvements to the fast native backend including linking support on Linux.\n  The goal is to be able to self host V soon.\n\n#### V interpreter\n- Some further interpreter work.\n\n#### C backend\n- Fix code generation for generic unions.\n- Fix `[N]chan` (fixed arrays of channels).\n- Fix nested fixed array instantiation.\n- Fix fixed array of map.\n- Fix stringification of usize struct fields (before, they were treated as 32 bit *signed* numbers).\n- Now code generated by the С backend, can be compiled by a C++20 compiler.\n- C backend does not generate unused interface functions now.\n- Parallelized cc step. Speeds up -prod and clang/gcc compilation by 300-500% (depending on\n  the number of cores). Experimental and hidden behind a -parallel-cc flag, soon to be the default.\n- Intel C compiler support.\n- Go backend fixes.\n- `#preinclude` for low level C interop.\n\n#### WASM backend\n- A new pure WASM backend, based on binaryen, a WASM `builtin` module, and a pure V WASM\n  serialization library.\n\n#### Comptime\n- A new `$res` comptime function to get returned value in defer block (#18382).\n- Fix comptimeselector option propagation.\n- A mutability check for comptime assignments.\n- Fix comptime assigning to sumtype or indexexpr.\n- Make comptime calls work with or-block.\n- Compile-time interface fields evaluation.\n- Compile-time enum evaluation:\n  ```v\n  $for item in MyEnum.fields {\n      println(item.value)\n      println(item.name)\n  }\n  ```\n- Added `$option` as a compile-time reflection type representing an any Option type.\n- All special compile-time reflection types are now lowercase (`$int`, `$enum`, `$option`, etc).\n- Improved compile time checks, like `$if x is Type {`; \n  `$if T in [$Array, $Struct, $Alias, $Function] {`.\n- `$for in` works with alias types.\n- New comptime features for fields: `field.is_<field>`, `field.is_alias`, `field.is_enum`.\n\n#### Compiler CLI\n- `v share file.v` for sharing code via the playground.\n- `v up` speed up for when it hasn't been run for a long time (**vc/** bootstrapping has been\n  optimized).\n- `v init` no longer overwrites existing `src/main.v`.\n- `v self` now uses a faster TCC backend on macOS (Intel/Apple Silicon), just like on Windows/Linux.\n- A new command line flag `-e` for running short V programs on command line: `v -e \"println(2+5)\"` (\n  works just like in Perl).\n- A new `-ldflags` option, in addition to `-cflags`. Works just like LDFLAGS in C.\n\n#### OS support\n- Added basic QNX support.\n- Installation instructions for using V on NixOS.\n- Better `make` support for OpenBSD.\n- Much improved experience for `v install pcre` on Windows\n  (it now bundles its own .c files, so it compiles cleanly, even if the platform does not have \n  another pcre package installed).\n- V can now be compiled with tcc on latest macOS and Apple Silicon.\n- Removed the need for the `[console]` attribute in Windows GUI apps.\n- More precise WINAPI declarations for easier integration on Windows.\n- More CI tests on FreeBSD.\n- Full termux support via `$if termux {`, more predictable logging on Android.\n- Older macOS support (<10.12).\n- Windows code has been removed from `v.c` distributed on non-Windows systems.\n  (`v_windows.c` is used on Windows.)\n\n#### Tooling\n- A new VPM site: vpm.vlang.io. A better design, discoverability of packages, descriptions,\n  most downloaded packages etc.\n- vpm: installation of mixed modules.\n- `v ls --install -p D:\\path\\vls.exe` to install a local vls executable.\n- vdoc: highlight comments with gray color.\n- vet: allow vetting files with global variables.\n- Make util.launch_tool/3 more robust, by recompiling V tools always in a known current\n  working folder.\n- Lots of documentation/readme improvements.\n- Lots of playground improvements: [play.vlang.io](https://play.vlang.io), including a really cool\n  feature: \"Show generated C code\".\n- \"Is V still fast?\" web-page has been sped up by splitting the result table into multiple years.\n- GitHub Copilot summaries in PRs.\n- fast.vlang.io fixes & improvements, new server.\n- New official IntelliJ plugin: https://intellij-v.github.io.\n- Lots of new language documentation, a nicer table of contents.\n- Improved documentation for most of the vlib modules\n- `make.bat` & `v up` improvements on Windows.\n- TeamCity test runner support via `v -test-runner teamcity foo_test.v`.\n- CI optimizations for faster runs.\n- New official AdventOfCode repo with AOC solutions, also added to CI.\n- More detailed timings in `v -show-timings`.\n- `v new <name> web` for quickly scaffolding new web projects.\n- New stunning playground with an improved look and feel, a much better and more responsive editor,\n  code sharing by link, more convenient keyboard control, reusability for potential embedding:\n  https://play.vlang.io.\n- Improved call tracing via `-trace-calls`.\n- Lots of documentation improvements, including a better documentation of \n  the recent Option/Result split.\n- V REPL: Home/End keys support. Lots of clean up.\n- DOOM is now translated/compiled and launched on CI servers. A screenshot of the running game\n  is made via `vgret` and is compared to the expected result.\n- VLS performance improvements, especially on Windows.\n- `v ls` tool for installing, for updating, and for launching VLS (V Language Server).\n- `v doc` now has syntax highlighting.\n\n"
  },
  {
    "path": "changelogs0.x/0.5.md",
    "content": "## V 0.5\n\n*3 Sep 2023 - 31 Dec 2025*\n\n#### Improvements in the language\n\n- Add comptime `if is shared` support (fix #25600) (#25602)\n- Make `defer{}` scoped by default, use `defer(fn){}` to get the old behavior #25639) (#25665)\n- Add gotodef support for nested struct members, fn return types, etc (#26131)\n- Add a new v.comptime stage `COMPTIME`, that runs after the checker (`CHECK`), and before the\n  transformer (`TRANSFORM`), to simplify the work that later stages do #26068 (#26161)\n- json2: replace encoder with a new implementation. It's 70% faster than the old json2, and 110%\n  faster than json that is based on cJSON (#25224)\n- Virtual C consts with custom types (const C.MY_CONST u8)\n- Support `-div-by-zero-is-zero`, which allows for `x / 0 == 0` and `x % 0 == x`, avoiding division\n  by zero traps/panics (#24981)\n- Limit -div-by-zero-is-zero influence to just the integer types (for f32 and f64, / produces a +inf\n  or -inf value, and the program continues to run)\n- VLS mode for the language server in pure V\n- Add support for `@OS`, `@CCOMPILER` `@BACKEND` and `@PLATFORM` (#25174)\n- Support a new CPU architecture s390x (#24107)\n- Add initial support for ppc64le (#24287)\n- Add initial support for loongarch64 (#24343)\n- Support `js\"string literal\"` for JavaScript strings (#24653)\n- VLS mode in the parser for the new language server in pure V\n- Implement assignable anonymous struct (fix #23855) (#23857)\n- Remove ancient deprecations (#23479)\n- `-skip-unused` is now on by default resulting in much smaller cgen and binaries. 70% reduction for\n  hello world.\n- `-parallel-cc` for speeding up `-prod` and `-cc clang/gcc` compilation by up to 14 times!\n- C functions no longer need to be manually defined. An `#include \"foo.c\"` is enough (behind\n  `-experimental` for now).\n- Fixed arrays now have `.index .any .all .map .sort .sorted` methods\n- Remove inline sum types completely\n- Support `in` expr with number ranges: `if var in 1..4 {` (fix #20352) (#22754)\n- Optimize literal string comparison (`match`, `in` and `==`) (#22643)\n- Allow `map[k]()?` and `map[k]()()` (#22740)\n- Add selector option unwrapping inside `if tree.root != none {` (#22895)\n- Add `array.count` as a method that accepts a predicate, similar to filter, but returning just the\n  number of matches (#23054)\n- Allow option array element comparison `==` and `!=` (fix #23108) (#23113)\n- A new `implements` keyword for explicit interface implementation\n- Allow multi return as fn argument (#21991)\n- Define a default sumtype value (based on the first variant type) (#22039)\n- Remove the obsolete .code and .msg fields of IError (#22066)\n- Fix generic lambda type binding and resolution (#22083)\n- Comptime support for traversing the method parameters with `$for param in method.params {` (\n  #22229)\n- Show missing variants in the sum type error\n- A much better and detailed unmatched fn arg error\n- Add support for `@BUILD_DATE`, `@BUILD_TIME` and `@BUILD_TIMESTAMP`, all using\n  v.util.get_build_time(), and overridable through SOURCE_DATE_EPOCH (#22213)\n- Add support for `-d ident=value` and retrieval in code via `$d('ident', <default value>)`\n- `-warn-about-allocs` for debugging allocations when using manual memory management\n- `@[freed]` attribute for assign statements (for the above mode)\n- Implement `&&=` and `||=` operators  (#21678)\n- Improve C var args interop, allow for `fn f(some int, ...) {` (#21812)\n- A new flag `-n` for skipping notes (similar to `-w` for skipping warnings)\n- Cross compilation to FreeBSD\n- Experimental `x.vweb` is now `veb`, the official and recommended way to build web apps in V. Built\n  on top of pico.v.\n- autofree: -print_autofree_vars command line flag for printing variables autofree couldn't free\n- Add `@VMODHASH` comptime variable to store the commit sha of a V module (#21091)\n- Fix sumtype support for option variant types (#21101)\n- Utilize new diff functions in errors (expected/found) (#21431)\n- Add @[_linker_section] for global variables\n- Add map update-init syntax: `new_map := {...old_map, 'k1': 1, 'k2': 5}` (#20561)\n- Improve coroutines, Photon vcpu creation, coroutines + GC fixes (#20549)\n- Update Boehm GC libs/headers to the latest version 8.3.0 (#20772)\n- $dbg statement - native V debugger REPL (#20533)\n- Implement `@[_linker_section]` attribute (#20629)\n- Enable `@[export]` for global variables too (#20649)\n- Add callstack support on v.debug (#20680)\n- Implement `@[aligned]` and `@[aligned:8]` attributes for structs and unions (#19915)\n- Update attributes to use new syntax\n- Update remaining deprecated attr syntax (#19908)\n- Support `$if T is $array_dynamic {` and `$if T is $array_fixed {` in addition to\n  `$if T is $array {` (#19882)\n- Prepare for making `-W impure-v` the default (#19940)\n- Assigning `0` to reference fields now requires unsafe blocks (fix #14911) (#19955)\n- Unwrap const() blocks\n- Implement $for comptime T.variants (#20193)\n- Add `r` and `R` switches for repeating in string interpolation, `'${\"abc\":3r}'` == 'abcabcabc' (\n  #20197)\n- Comptime refactor and cleanup (#20196)\n- Allow comptime-for to iterate over comptime variables, add `$string` comptime type, cleanup (\n  #20233)\n- Unwrap an option value automatically, inside `if o != none {` (#20275)\n- Complete support for smartcasting to a comptime variable type (#20270)\n- Improve comptime var checking with `is` operator and smartcasting (#20315)\n- A new `encoding.xml` module with parser, validation, entity encoding, unit tests (#19708)\n- Better couroutines support (IO, networking)\n- Allocations in vweb apps reduced by 80%\n- Implement `@VCURRENTHASH` to replace `C.V_CURRENT_COMMIT_HASH` (#19514)\n- int => i64 on 64 bit, i32 on 32 bit (start of the transition)\n- Fix new int type promotion rules and cleanup native gen() (#19535)\n- Short lambda expressions like `a.sorted(|x,y| x > y)` (#19390)\n- Support `-os plan9`, `$if plan9 {`, and `_plan9.c.v` (stage 1 for plan9) (#19389)\n- fmt: simplify the processing logic for removing inline comments (#19297)\n- Align the custom values of the enum fields (#19331)\n- Do not warn/error for `import flag as _`\n- Keep anon struct decl fields in interfaces (#19461)\n- Support -N, turning all notices into errors, to ease the process of finding places that may need\n  attention/correction\n- Pure `array.sorted()` and `array.sorted_with_compare()` methods, that do not modify their\n  receivers (#19251)\n- UB overflow has been removed\n- Implement `Enum.from_string(name string)` for converting strings to enum values (#19156)\n- Disallow casting string to enum, suggest using Enum.from_string() instead (#19260)\n- Use autocasting in complex conditions (#18839)\n- Allow alias as fixed array on return (#18817)\n- Do not allow uninitialized function pointers\n- Fix compiling V programs with latest clang 16 on windows (clang 16 is stricter than clang 14) (\n  #19095)\n- Fix anonymous struct with default expr (#19257)\n- Allow using consts as enum values (#19193)\n- `@[attr]` syntax to replace `[attr]` (`[]` is used for too many things). Most likely to be\n  replaced with `@attr()` in the future.\n- Allow `none` for not first values on map initialization (#18821)\n- Make all .trace() methods generic on the type of the passed expression\n\n#### Breaking changes\n\n- Deprecate `gx` and replace all occurences with `gg` (which now contains all the functionality of\n  `gx`) (#24966)\n- Remove deprecations made before 2024-11-06\n- Add a deprecation note for `any` arg, prevent `any` from being used as map key,value or array\n  type (#24277)\n- Make old `[attr]` syntax an error (`@[attr]` has to be used instead)\n- builtin: `string.index_after()` now returns an Option (like `string.index()`), use\n  `string.index_after_()` for the old behavior\n- Vweb is now deprecated in favor of faster and more stable and easy to use veb\n- time: rewrite parse_rfc3339/1 to improve performance, reject partial timestamps, that miss date\n  info like `22:47:08Z` (#22585)\n- Deprecate `x.vweb` and `vweb` in favor of `veb`, a faster, easier, and more stable framework.\n- checker: disallow initializing private struct fields outside structs module (#21183)\n- sokol: the sokol wrapper was updated, to match its upstream version at commit 058a4c5, several of\n  its APIs no longer exist\n- templating.dtm: compile_template_file is no longer public\n- v.trace_calls: `pub fn on_c_main() {`, is now `pub fn on_c_main(should_trace_c_main bool) {`\n- v.transformer: Transformer.fn_decl is now Transformer.fn_decl_trace_calls\n- x.vweb: Context.redirect(url string, redirect_type RedirectType) is now Context.redirect(url\n  string, params RedirectParams)\n- `Request.cookies` map has been deprecated. Replaced with `Request.cookie()` and\n  `Request.add_cookie()`.\n- Stricter rules for C types (they always have to be declared now)\n- Remove inline comments (#19263)\n- `arr[1..4]` now requires `unsafe` if the slice can modify the original immutable array.\n\n#### Checker improvements/fixes\n\n- Correctly detect variadic arg passed to struct fn (fix #25504) (#25509)\n- Fix $(field.name) access on closure fn (fix #25513) (#25514)\n- vls: skip unrelated files (#25531)\n- Fix mutability in `for in` loops with pointer values (fix #25520) (#25536)\n- Fix type inference, when pushing an empty array to a 2D array (fix #23854) (#25508)\n- Prevent array.insert for array of references when non-reference is passed (fix #25511) (#25557)\n- Add more support for mod autocomplete, allow for .vv files too (#25562)\n- Fix cast from an empty struct to option (fix #25566) (#25581)\n- Ensure ?Struct is not parsed as ??Struct when param is ?T (fix #25559) (#25564)\n- Fix if branch type nr_muls mismatch (fix #25556) (fix #25555) (#25571)\n- Fix comptime else branch handling (fix #25586) (#25589)\n- Smart detect `or {}` inside loop when using `c <-val` (fix #24550) (#25435)\n- Vls fix goto definition (#25595)\n- Fix generic resolve for external module generic static method call (fix #21476) (#25634)\n- Correctly detect type, when prepending to generic array (fix #25585) (#25645)\n- Allow cast from voidptr to sumtype in unsafe block (fix #25652) (#25657)\n- Disallow calls to a shared receiver method, on a non-shared var (fix #25577) (#25656)\n- Fix or block endwiths expr (fix #25329) (#25667)\n- Set ast file fallbacks for vls (fix #25678) (#25679)\n- Error/warn when using `defer(fn)` inside function-scope and `lock` stmts (#25681)\n- Maintain correct ref level in generic fn (fix #25676) (#25687)\n- In vls mode, make ensure_type_exists return true (#25695)\n- Only collect/hoist inner vars, when `defer` is function-scoped (#25693)\n- Improve type checking for sumtypes with generics (fix #25690) (#25699)\n- Unwrap for base type if ft.typ and inferred_typ are both opt (fix #25517) (#25728)\n- Disallow deference of nil (fix #25740) (#25746)\n- Fix comptime main fn (#25747)\n- Parser,fmt,checker: use a trie for matching the generic array methods `all`, `any`, `count`,\n  `filter`, `map`, `sort` and `sorted` (#25759)\n- Fix array fixed unresolved return check and resolver (fix #25774) (#25790)\n- Allow explicit sumtype to option casts (fix #25796) (#25812)\n- Fix possible race on expected arg types unwrapping on cgen (#25815)\n- Skip init check for options (fix #25798) (#25830)\n- Fix module var set at change_current_file() (fix #25845) (#25846)\n- Improve handling of array decompose for dynamic arrays and array init (fix #25838) (#25843)\n- Force all fn declarations to follow after all other top level statements (fix #25889) (#25890)\n- Fix used features tracking when printing pointer values (fix #25899) (#25901)\n- Match type when auto deref occurs (fix #25913) (#25916)\n- Relax the redundant () check to a notice, to enable a future `v -W test vlib/builtin` job on the\n  CI\n- remove () from match branch exprs (fix #25950) (#25952)\n- Fix array map anon fn return fixed array (fix #25928) (#25977)\n- Cleanup the output of `v new --web abcd` after feedback from https://youtu.be/IuE6Bo1klK0?t=555\n- Allow assign to a shared int var (fix #25986) (#25988)\n- Ensure type of global exists (fix #25910) (#25998)\n- Ensure fn pointer cannot be used as non-fn argument (fix #26017) (#26022)\n- Make sure  `$for` eval body statements at least once to set types and avoid markused issues\n  later (fix #26058) (#26063)\n- Fix return static method name (fix #26105) (#26110)\n- Support gotodef for struct init and sumtype rhs (#26157)\n- Detect circular type references in sumtype declarations (fix #24511) (#26162)\n- Add interface type handling and new testcase (fix #24116) (#26165)\n- Allow enum fields to reference previously declared fields (fix #25241) (#26173)\n- Clear all ref from autostr receiver_type (needed by #25857) (#26202)\n- Allow for `_` being used as both `import x as _` and `fn f(_ int) {` (fix (#26219) #26230\n- Fix `sizeof(T)` usage in generic struct (fix #24806) (#24808)\n- Add `$if sizeof(T) == int_literal {` support (#24831)\n- Improve virtual C consts\n- Markused,checker: fix hello world size after the introduction of `builtin.closure` in 2d87ac4 (\n  #24989)\n- Remove dump() dependency from ComptimeFor (#25000)\n- Cleanup - remove unused c.using_new_err_struct (#25036)\n- Cleanup `err` removal (#25043)\n- Add comptime support for s390x, ppc64le and loongarch64 platforms (#25048)\n- Allow for `v -is_o -o x mm.v`, where `mm.v` starts with `module abc` (i.e. not just `module main`)\n- Fix calls with result propagation, using other consts, in const declaration expressions (fix\n  #21609) (#25060)\n- Fix array init with interface (fix #24255) (#25073)\n- Fix missing map float key duplicated checking (fix #25098) (#25117)\n- Fix missing check for struct generic init from call (fix #25084) (#25119)\n- Fix missing check for empty array to generic param (fix #25056) (#25118)\n- Rewrite comptime_if_cond() to support comptime if cond evaluate (fix #24938) (fix #25099) (#25122)\n- Add error for struct not init (fix #24893) (#25134)\n- Fix sql insert expr propagate result (fix #24833) (#25136)\n- Fix checking return type call disregarding unwrapping (fix #25140) (#25143)\n- Ensure the defer behavior matches that of cgen (fix #25148) (#25146)\n- Nil check for c.table.cur_fn in gen_branch_context_string() (fix #25170) (#25171)\n- Relax the \"unreachable code after a @[noreturn] call\" error to a warning to reduce prototyping\n  friction (#25173)\n- Fix multi return arg passing checking (fix #25167) (fix #25180) (#25177)\n- Use keywords matcher trie for imported symbol presence checks, instead of\n  `x in p.imported_symbol` (#25201)\n- Fix iteration over mutable option (fix #24860) (#25199)\n- Add `T.typ` and `T.unaliased_typ` checking to `$match` (fix #25200) (#25202)\n- Add more checks for map.delete (fix #25204) (#25205)\n- Fix static init var (fix #25203) (#25209)\n- Add top level comptime support for `$match @OS {` too (#25222)\n- Comptime match only eval true branch (fix #25223) (#25225)\n- Fix multi return var passing to fn arg (potential fix for #24870) (#25250)\n- Prevent usage of imported module name prefix as identifier names, to avoid cgen collisions (\n  #25280)\n- Disallow duplicate export names (fix #25301) (#25302)\n- Reduce the verboseness of `unsupported size ... for global` messages, for\n  `v -b native examples/hello_world.v`\n- Fix chan element type validation with inexistent type (fix #23978) (#24008)\n- Do not allow auto (de)reference in PrefixExpr *\n- Fix check for pushing on an unwrapped option array (fix #24073) (#24093)\n- Fix wrong type hint on predicate arg type mismatch (fix #24122) (#24123)\n- Fix array generic return checking (fix #24104) (#24214)\n- Fix stack var outside usage when var is a mutable param (#24249)\n- Fix codegen for multi return with array fixed (fix #24280) (#24282)\n- Check anon struct field valid case (partial fix of #24284) (#24286)\n- Add check for recursive array init on struct (fix #21195) (#24278)\n- Fix inherited var turning in auto heap (fix #24306) (#24312)\n- Remove redundant callexpr `c.expr(mut node.left)` rechecks for `ast.CallExpr` (fix #24353) (\n  #24380)\n- Do not allow &u8(0), force nil like we do with &Type(0)\n- Relax the new warning, allow for `pub const pname = &char(C.SDL_POINTER)` to fix the clean\n  compilation of code using vlang/sdl3\n- Fix for with mut generic value (fix #24360) (#24426)\n- Add check for decomposing to interface (fix #24441) (#24453)\n- Fix generic option array arg passing to `[]T` (fix #24423) (#24457)\n- Fix resolver for returning struct generic (fix #24493) (#24506)\n- Reallow passing closures as voidptr parameters with no warning, to enable convenient interfacing\n  with C libs\n- Disallow invalid expr for `filter`, `count`, `any`, `all` (fix #24508) (#24540)\n- Replace warning by notice for UTF8 strings validation (fix #24538) (#24543)\n- Revise logic for reporting import conflicts with module names (#24539)\n- Fix struct update expr checking, when an alias is used (fix #24581) (#24582)\n- Fix fn var resolver (fix #24525) (#24542)\n- Fix checking for int to array of interface (fix #24624) (#24625)\n- Cycle through all `ast.ParExpr` first in `prefix_expr` (fix #24584) (#24588)\n- Move `arr <<` logic to `check_append()`\n- Fix mutable const bug (fix #14916)\n- Allow for calling main() inside _test.v files\n- Fix missing type bounding to match expr on `or{}` expr (fix #24656) (#24658)\n- Add error for `if mut x != none {`, when `x` is an immutable option (fix #24692) (#24694)\n- Fix compound selector smartcasting/option unwrapping (fix #24662) (#24712)\n- Fix mutable option (fix #18818) (fix #24622) (fix #24101) (#19100)\n- Allow `none` to be passed to `?T` param (fix #23381) (#23385)\n- Fix `for` iterator method `.next()`, not marked as used (fix #23312) (#23321)\n- Fix generic var inferring to be passed to `[]T` (fix #23315) (#23322)\n- Clean up and optimise infix - reduce `as` casting (#23327)\n- Fix structinit validation on nested generic Map[K]V (fix #23329) (#23332)\n- Fix comptime indexexpr resolving (#23333)\n- Fix comptime evaluation on infix expr (fix #23341) (#23344)\n- Fix alias to fixed array w/ size defined by constant (fix #23356) (#23357)\n- Fix missing option variable checking when casting using `as` operator (fix #23349) (#23358)\n- Fix assign expected type on rechecking enum assigns (fix #23366) (#23367)\n- Allow calling `foo(?i64(123))` for `fn foo(x ?I64) {` and `type I64 = i64` (#23373)\n- Cache `node.args[0]` on `fixed_array_builtin_method_call` and `array_builtin_method_call` (#23411)\n- Fix missing check for invalid prefixexpr expression `&(&var)` (fix #23365) (#23418)\n- Disallow `&((&a))` and similar expressions, with innermost `ast.PrefixExpr` (enhance #23418) (\n  #23419)\n- Fix call with mut arg with different pointer levels (fix #23157) (#23428)\n- Fix missing detection for `return` in lockexpr stmts (fix #23434) (#23435)\n- Do not allow auto reference of voidptr params\n- Check if unwrapped `m[key]` if m is `Option` (fix #23446) (#23459)\n- Builtin,checker: remove `@[markused]` from `fn isnil()`, set\n  `c.table.used_features.auto_str_ptr = true` instead (#23464)\n- Fix checker generic alias type (fix #23474) (#23475)\n- Fix missing check for `a := [none]` (fix #23457) (#23504)\n- Fix missing check for concrete type on match branch expr (fix #23506) (#23508)\n- Fix missing check for invalid argument for builtin (fix #23511) (#23515)\n- Fix selector nested unwrapping (fix #23519) (#23521)\n- Fix message with old attr syntax (#23529)\n- Cache repeated `node.args.len`, `method.generic_names.len`, `node.concrete_types.len` and\n  `node.op.str()` (#23536)\n- Disallow `expr is Type` if expr is Optional (fix #23486) (#23510)\n- Make `option_var.str()` an error, when done without unwrapping it first (fix #23557, fix #23558) (\n  #23563)\n- Fix private symbol visibility checking (fix #23518) (#23543)\n- Disallow constant modification on unsafe {} (#23588)\n- Fix sumtype variant option type mismatch (#23659)\n- Disallow `arr = voidptr(0)` (fix #23675) (#23687)\n- Allow for `module no_main` programs, that can redefine their own main function, or not define any\n  of their own as well\n- Fix match branch checking of nonreturn call on last expr (fix #23698) (#23699)\n- Check and error for invalid utf8 string literals (#23721)\n- Fix call from unknown enum (fix #23728) (#23730)\n- Add checker for passing multi return as arg to func that expects less param (fix #23735) (#23744)\n- Fix spreed operator ref field validation (fix #23759) (#23760)\n- Fix missing check for method that returns veb.Result (fix #23647) (#23762)\n- Allow generic operators to be called in fn (fix #23773) (#23774)\n- Fix missing struct cast validation (fix #23748) (#23788)\n- Fix map when casting to interface (fix #23790) (#23799)\n- Allow for `pub type C.HINSTANCE = voidptr`, being used in\n  ```\n  @[export: \"wWinMain\"]\n  fn mymain(x C.HINSTANCE, xprev C.HINSTANCE, lpcmdline &C.WCHAR, cmdshow int) int {\n  ```\n  in `module no_main` programs (#23812)\n- Add option type inference on if expr (implement most of #23827, except the error for\n  `v := if c { none } else { none }`) (#23829)\n- Add missing check for IfExpr and MatchExpr with no valid type (#23832)\n- Fix MatchExpr type inferring, when `none` is used (fix #23831) (#23833)\n- Add missing check for generic fntype type names (fix #23453) (#23850)\n- Add checking for comptime assign without comptime if checking (fix #23796) (#23848)\n- Fix option ptr field assign checking (fix #23879) (#23880)\n- Add missing `any` type validation on assignment (fix #23905) (#23906)\n- Add fntype casting validations (#23872)\n- Fix signed integer literal overflow error, when most significant bit occupies signed bit (fix\n  #23782) (#23919)\n- Add missing check for casting generic type to literal values (#23915)\n- Check if next() method infers generic type correctly (fix #23927) (#23932)\n- Disallow references to constants (fix #23935) (#23942)\n- Fix typeof evaluation for generic reference (fix #23951) (fix #23952) (#23958)\n- Optimize identical type checking (#22596)\n- Fix `T.unaliased_typ` if branch evaluation (fix #22587) (#22598)\n- Fix lambda expr with fntype params and restore fixed_array_any_all_test.v (#22625)\n- Check fixed array builtin method args mismatch (#22626)\n- Fix generic fn call return type resolve on var assignment (fix #22612) (#22627)\n- Improve checking parameter mismatches for fixed array builtin methods (#22630)\n- Add tests for checking the new errors for fixed arrays .sort() calls (#22656)\n- Fix index expr that left is if expr (fix #22654) (#22661)\n- Fix return type checks, when returning struct values, implementing IError in non-result fn (fix\n  #22659) (fix #22658) (#22660)\n- `App.method` field initialisation, for fn fields, initialised with generic methods (#22665)\n- Allow for `f() or { T{} }` in a generic method, for `fn f() ?T {`, being called with `T`, being a\n  container like []int etc, not just a primitive type like int (#22672)\n- Allow for `f() or { T{} }` part 2, see also cc55aa5 (handle the case of an ignored result as\n  well) (#22687)\n- Fix selector with prefixed `&` structinit (#22689)\n- Fix missing check for fn var with generic return inherited to anon fn (fix #19045) (#22683)\n- Check for receiver name clashing with global var (fix #22698) (#22708)\n- Fix none check for match expr with option (fix #22728) (#22732)\n- Fix option map fn type and missing check for result param type (fix #22736) (#22738)\n- Fix missing info about generic fn var usage without concrete types (fix #22733, #22734) (#22743)\n- Fix missing check for stack pointer return (fix #22726) (#22756)\n- Improve static method call resolution (fix #22773) (#22787)\n- Skip redundant message for int overflows, while casting integer literals (fix #22761) (#22788)\n- Fix callexpr after auto C func identification (fix #22800) (#22809)\n- Fix missing auto `from_string` type restriction (related to #22783) (#22803)\n- Fix match expr with empty array init expression (#22832)\n- Disallow `foo[T]` as a value  (#22820)\n- Fix if expr with empty array init expression (related #22832) (#22841)\n- Improve the position underlining, for last statements in branches of `if` expressions  (#22845)\n- Fix generic fn call with empty array argument (fix #22843) (#22846)\n- Fix missing or-block check for callexpr (fix #22835) (#22840)\n- Check array builtin method calls, that do need a mutable receiver, but are called on an immutable\n  one (fix #22850) (#22853)\n- Check alias of array op overloading and fix op overloading (fix #22851) (#22854)\n- Disallow struct init with `mutable_field: const_array` (fix #22862) (#22863)\n- Check struct aliased field unsign type assigning negative value (fix #22868) (#22871)\n- Fix alias to struct generic type (fix #22866) (#22872)\n- Fix `json.encode_pretty` with a struct init expression argument (#22897)\n- Fix codegen for fixed array initialization with a fn call (fix #22887) (#22891)\n- Fix or-expr check on invalid method call (fix #22949) (#22950)\n- Fix mut var option unwrap with `!= none`, support `if mut x != none {` too (fix #22936) (#22943)\n- Prevent a compiler panic, while running `v -check file.v` on files with parser errors (fix\n  #22981) (#22982)\n- Allow array sort with callexpr (#22989)\n- Fix `$res()` used in `defer {}` blocks with more statements, add a test (#22998)\n- Fix generec fn returning generic closure (#23047)\n- Fix generic fn returning generic closure (related #23047) (#23055)\n- Fix missing checker for cast from mut var to non-ptr type (fix #23017) (#23056)\n- Check fn call argument mismatch (fix #23016) (#23061)\n- Fix empty array append multi dims (fix #23092) (#23096)\n- Fix selector generic or block (fix #23088) (#23102)\n- Fix veb route method param with non ctx name (fix #23105) (#23107)\n- Allow fixed array where voidptr is expected (fix #23090) (#23100)\n- Fix immutable to mutable reference (fix #22653) (#22663)\n- Fix missing check on range expr when high var is same iteration value var (#23130)\n- Allow `[]Enum{len: 10, init: .thing}` (fix #23077) (#23165)\n- Fix option unwrapping and call from option struct field (#23182)\n- Add a notice for global variable redeclarations (#23162)\n- Fix assign check, when rechecking for another concrete type (#23212)\n- Disallow static fn call when receiver type is unknown  (#21970)\n- Fix sumtype checking for voidptr variant (#21955)\n- Check comptime veb.html('index.html') (#21961)\n- Check if a parent generic struct has concrete types or not  (#21962)\n- Add support for static methods in `@FN` and `@METHOD`  (#21990)\n- Add a deprecation warning for `const ()` groups (an error after 2025-01-01) (#22019)\n- Improve `-d trace_checker` and error diagnostic information on compiler panics\n- Add error when initializing sumtype with struct as first type (#22067)\n- Add infix checks for nil  (#22045)\n- Fix map generic fn arg passing (#22071)\n- Disallow using a preexisting const name in a for loop, as either a key or value ident (#22108)\n- Fix generic lambda type binding resolution (fix #22109) (#22115)\n- Fix array alias (#22175)\n- Restrict multiple union fields initialised at once with a nicer checker error, instead of\n  producing an enigmatic error at cgen time (#22196)\n- Fix compilation of vlib/v/slow_tests/assembly/asm_test.amd64.v (regression after dfc0c91)\n- Add missing check for ref passing to non-ref (#22194)\n- Check struct implements non interface type (fix #22200) (#22218)\n- Suggest using the `@[_allow_multiple_values]` attribute, when declaring enums that have duplicate\n  values (#22224)\n- Check for duplicate interface names in the `implements` parts of struct declarations (#22230)\n- Fix missing struct field type checking for type mismatch (ref vs non-ref in\n  `mt sync.Mutex = sync.new_mutex()`) (fix #18088) (#21949)\n- Fix fntype var marked as auto heap (#22290)\n- Check array.delete() argument mismatch (#22307)\n- Add missing check for duplicated items on in expr (fix #22305) (#22308)\n- Disallow infix expr on left side of assign  (#22322)\n- Fix array fixed return type for interface methods (#22320)\n- Check arguments mismatch of array.sorted_with_compare() (fix #22327) (#22328)\n- Add an error for returning an `any` value in pure V code (prevents invalid cgen) (fix #12623) (\n  #22334)\n- Cleanup the checking of array method calls (#22338)\n- Fix voidptr type checking  (#21923)\n- Fix unknown fixed array size for `const n = int(sizeof(u64)); _ = [n]int{}` (fix #21544) (#21548)\n- Fix checking of default field initialisations, that are part of unions of structs tagged with\n  `@[noinit]` (#21587)\n- Disallow sum type with `Result` variants (#21620)\n- Add error for `field map` (i.e. a plain untyped map), used inside a struct (#21625)\n- Fix missing concrete type checking on a generic type specifier (#21614)\n- Fix missing option and result wrong type return type definition (#21626)\n- Turn warnings for private fields into errors (#21296)\n- Support nested labeled for statements (#21658)\n- Fix the return type of overloaded operators, defined on aliases of primitive types (fix #21654) (\n  #21663)\n- Fix match expr with auto promote number (#21696)\n- Fix sorting compare fn with mut reference parameter (fix #21662) (#21706)\n- Fix `$if x {` condition, using `const x = $d('ident', false)` (fix #21709) (#21713)\n- Fix generic variable resolution on generic func return assignment (#21712)\n- Fix result call or_block with multi-statements (fix #21504) (#21717)\n- Allow `\\uxxxxx` in raw strings (#21724)\n- Limit recursion in Checker.ensure_type_exists/2 to 40 levels (it is usually 4 or less) (#21734)\n- Add error for `field [$d('x', 2)]int = [1, 2]!` (#21741)\n- Fix nested if expr method call (#21773)\n- Fix generic inference in if expressions used in assignments (#21781)\n- Disallow nil in non-nil arrays and vice versa  (#21786)\n- Check expr evaluated but not used (fix #21436) (#21816)\n- Fix wrong receiver generic resolution with embed types (#21833)\n- Check mismatch of fn call mut argument (fix #21857) (#21873)\n- Fix global fixed array key resolution when it is a constant ident (#21900)\n- Improve checks for embed in anon struct  (#21877)\n- Fix builtin fn var resolving (#21899)\n- Fix spawn when calling undefined function (#21906)\n- Require enum values to be declared, before using them in other enum values (#21913)\n- Check enum field value duplicate (#21920)\n- Allow embed of type alias anon struct  (#21928)\n- Ambiguous expression notice for `& << >>`, similar to `&& ||`\n- Disallow using aliases of ?Type as !Type (#21128)\n- Fix option checker arg validation for ptr passing on non expected ptr (#21087)\n- Optimize option and result type check, add more typinfo to error details (#21105)\n- Move error handling for `any` type to the checker to resolve parsing issues (#21146)\n- Move error handling for user defined type duplicates to the checker to resolve parsing issues (\n  #21147)\n- Detect redundant ref when assigning call expr with ref return (#21141)\n- Fix multi return using nil and voidptrfix (fix #17343) (#21144)\n- Fix C struct embedded init fields checking (#21137)\n- Remove resolved vfmt workaround and TODO (#21175)\n- Move more match validation from the parser into the checker, add error for match without\n  branches (#21181)\n- Improve the error message for an unknown type (#21207)\n- Allow passing `none` to `fn f(arg ?&Type) {` (fix #21213) (#21231)\n- Fix -parallel-cc regression (part 1, workaround .filter(fn[c]) used in checker/orm.v) (#21238)\n- Detect and error on unreachable code in loops, after `continue` and `break` statements (#21294)\n- Disallow `Result` callbacks functions like `map/filter/all/any` (#21055)\n- Fix missing check for or expr on string interpolation (#17566)\n- Allow pass array as mut param to spawn fn (#21283)\n- Turn array assign warning into error (#21341)\n- Ignore last semicolon on or-expr (#21361)\n- Disallow structs with `@[params]` attribute as mutable function parameters (#21206)\n- Set auto Return pos correctly; cgen: autofree fix for optional returns\n- Disallow invalid ptr operations  (#21515)\n- Fix wrong checking for heap struct (#21511)\n- Allow alias enum flagged to have bit operations  (#21532)\n- Simplify, utilize pref.vroot (#21096)\n- Fix option interface member checking when `none` is passed (#21509)\n- Check invalid lambda expr (#20461)\n- Fix comptime if with comptime smartcast (#20466)\n- Fix anon struct init with const fields (fix #20452) (#20463)\n- Disallow `option` or `result` return type, for infix operator overloading (#20494)\n- Cleanup the const variable evaluate for fixed array fields of structs (#20503)\n- Fix missing check for struct initialization with `@[noinit]` attribute, through using `T{}` (\n  #20516)\n- Fix mark methods into used-list, when generics as receivers (fix #20509) (#20527)\n- Modify comments on generic receiver type storage (#20539)\n- Fix checking give const map as default or init value to struct fields (fix #20512) (#20546)\n- Fix return map index with or_block (#20544)\n- Cleanup the generic tests (#20553)\n- Fix `@[deprecated]` attribute for consts (fix #20523) (#20550)\n- Cleanup in method_call() (#20554)\n- Disallow `non_opt_array << optvalue` (#20573)\n- Fix non dereferenced enum in match statements (fixes #10045) (#20591)\n- Fix .variant smartcast on non-comptime variables (#20575)\n- Disallow static maps: `mut static x := map[string]int{}` (#20596)\n- Allow `#define X` and `asm riscv64 {}` blocks in .v files, with `-freestanding` (make embedded\n  usecases easier)\n- Add cast overflow checks (#20641)\n- Disallow assigning none to _ (#20646)\n- Fix checking for option matching with non-option (#20673)\n- Disallow `(x) := 10` (#20695)\n- Disallow `none` as match cond (#20688)\n- Fix comptime ident checking on defer stmt (fix #20719) (#20723)\n- Add error for `x as Y.field`, suggesting using `(x as Y).field` instead for clarity (#20725)\n- Disallow sum type holding alias ptrs (#20786)\n- Optimise out calls to `arg_typ_sym.embed_name()` when there are no errors (#20820)\n- Fix if branch option type mismatch (fix #20809) (#20830)\n- Fix auto deref arg when fn expects ref (#20846)\n- Fix struct field init with generic fn variable (fix #20847) (#20878)\n- Cleanup in assign_stmt() (#20880)\n- Check assigning immutable reference struct field (fix #20814) (#20883)\n- Fix struct field init with generic anon fn (add the test from #18294) (#20888)\n- Fix checking match branch call expr twice (#20910)\n- Support `Flags.bit ^ Flags.bit1` and `~Flags.bit` (flagged enums) (fix #20925) (#20929)\n- Fix some specific interface generic inference within generics struct and method (#20932)\n- Remove notice when shifting signed int for `@[translated]` (#20935)\n- Silence \"assigning 0 to a reference field\" and \"uninitialized fn struct fields\" notices for\n  `@[translated]\\nmodule ...` files (#20938)\n- Fix missing check for interface cast of option type (#20961)\n- Silence more warnings for `@[translated]` files (#20964)\n- Fix comptimeselector passing to generic argument (#20985)\n- Remove unnecessary string interpolation in deprecation method calls (#21007)\n- Disallow void return value lambdas in array.map method calls (#21011)\n- Cleanup and simplify `check_ref_fields_initialized` methods (#21016)\n- Cleanup and simplify struct processing p1 (#21009)\n- Add support for deprecation messages for structs and struct fields (#21017)\n- Cleanup and simplify struct processing p2, extend test (#21025)\n- Fix undefined reference to interface struct field regression (after #21025) (#21030)\n- Add test for interface embedding and interface with erroneous implementation (test related to\n  #21030) (#21033)\n- Disallow `Optional` and `Result` high val in a `for x in low..high {` loop  (#21043)\n- Fix missing incompatible pushval type for chan <- operator (#21040)\n- Disallow `$for i in struct.values` and `$for i in enum.fields` (#19845)\n- Parser, checker: fix var scope in lambda(fix #19860) (#19871)\n- Change the warning `more than 1000 possibilities in match range`  to a notice (#19862)\n- Fix inability to use multiple `import some modname as _` in the same .v file (fix #19899) (#19900)\n- Disallow casting strings to pointers outside `unsafe` (#19977)\n- Disallow directly indexing sumtype and interface, when using as parameters(fix #19811) (#19982)\n- Fix loop on aggregates of arrays (in match branches) of sumtypes (fix #18548) (#19988)\n- Disallow indexing mut struct, passed as a fn parameter (#19992)\n- Enhance err msg for unknown types for comptime `$for` (#20057)\n- Fix .clone()/.move() with shared maps (#20083)\n- Fix generics method call with struct short syntax args(fix #20030) (#20100)\n- Fix unwrap, when generic structs are used as arguments, in uncalled methods (fix #20132) (#20135)\n- Fix generic fn with generic fn call returning generic map (fix #20106) (#20150)\n- Cast sumtype to its variant generic type (#20166)\n- Refactor `string` to `enum` error check, handle `EnumName(string_variable)` too (#20210)\n- Fix generic array method call with multi-types (#20237)\n- Remove unnecessary struct ref field initialization checks and notifications at map initializing(\n  fix #20245) (#20251)\n- Add a notice, for accessing by key, map values, that contain pointers (to use unsafe or an `or {}`\n  block) (#20266)\n- Fix mismatch checking when a function returns sumtype as an argument (fix #19325) (#20264)\n- Fix and cleanup uninitialized checks for array initialisers with `len:` (fix #20272) (#20279)\n- Give an error for `.free()` method calls, when used on fixed arrays  (#20320)\n- Fix type mismatch checking for assignments with generics (fix #20298) (#20327)\n- Fix too strict checking with generics in assignment type mismatch (fix #20335) (#20346)\n- Disallow `string` to `voidptr` cast entirely (#20351)\n- Fix generic method calls with multi generic types (fix #20330) (#20360)\n- Turn the option/result split warning into an error\n- Turn propagation warning into an error (finishes the option/result split)\n- Fix fn call with option call argument in autofree mode (#19515)\n- Bring back pascal case check for aliases\n- C.xx = C.yy aliases\n- Allow casted integral types in match ranges (#19572)\n- Warn about byte deprecation, when used as a fn parameter (#19629)\n- Allow size of fixed array to be integral casts (#19663)\n- Fix generic array append (#19658)\n- Check error of implementing other module private interface (fix #19620) (#19688)\n- Extend byte deprecation warning to array init types (#19671)\n- Extend byte deprecation warnings to return types (#19668)\n- Fix negative cap, len checks in array init (#19694)\n- Turn warning for var and param module name duplicates into error (#19645)\n- Fix closure in if guard, including with multi_return (#19765)\n- Fix comptime enumdata value property access (#19768)\n- Fix `field ?&Type` without default value (#19786)\n- Avoid nil assign to option var (#19746)\n- Allow for a shared variable to be whole reassigned (keeping the same mutex state) (fix #15649) (\n  #19751)\n- Disallow module name duplicates in local names (#18118)\n- Check enum fields with duplicate value (fix #19309) (#19310)\n- Disallow alias ptr cast of a map value (#19336)\n- Require `else` branch in `[flag]` enum match (#19375)\n- Disallow assigning pointer values to option struct fields (#19380)\n- Fix generic comparison for conditional assignment (#19401)\n- Allow using ! and ~ on aliased bool and integral types (#19403)\n- Warn -> error for uninitialized ref fields\n- Parser, checker: allow lambdas anywhere anonymous functions are expected (#19436)\n- Allow for `each(a, |x| println(x))`, i.e. using lambda expressions, when expecting `fn (x int)`\n- Check fixed array init with default expression (#19472)\n- Allow for `const source = $embed_file(@FILE).to_string()`\n- Fix C.type in imported modules\n- Disallow assigning `nil` to struct fields (#18725)\n- Use autocasting in complex if conditions (#18753)\n- Disallow invalid prefix on left side of assign stmt (#18750)\n- Allow no return in compile_error else block (#18758)\n- Fix interface param resolution (#18780)\n- Add an error for `$tmpl` function type mismatches (#18826)\n- Disallow voidptr cast to struct (#18845)\n- Fix type checker on auto deref var (#18842)\n- Check generic sumtype declaration (fix #18741) (#18865)\n- Fix closure with inherited sumtype variable (#18894)\n- \"v -line-info\" for a quick run to fetch info about objects on one line\n- Make sure vweb actions return vweb.Result\n- Do not allow modifying immutable vars via arrays with refs\n- Support `@STRUCT` in static methods\n- Fix generic struct field init recursively (related #19014) (#19025)\n- Fix struct field fntype value call (#19067)\n- Explicitly disallow creating type aliases of `none`, i.e. `type Abc = none` (#19078)\n- Fix assigning an array slice (fix #19120) (#19137)\n- Fix assigning array slice in struct init (#19150)\n- Check enum static from_string arguments errors (#19163)\n- Disallow taking the address of consts with int literal values (#19160)\n- Check struct embed with wrong position (#19245)\n- Optimize out needless string interpolations from the most common case in\n  `Checker.expr_or_block_err`\n- Check error for or_expr inside infix expression (#19213)\n- Disallow `thread` as var name (#19174)\n- Check error for sumtype in array (#19183)\n- Disallow an empty `chan` type (#19167)\n\n#### Parser improvements\n\n- Fix vls mode strut mut keyword (fix #25548) (#25551)\n- Fix vfmt comment in struct init after the update expr (fix #24361) (#25668)\n- Fix infix expr comment in middle (fix #24183) (#25671)\n- Disallow using generic functions as a field type name inside struct decl (fix #25452) (#25705)\n- Warn on `@[deprecated_after]` used without a corresponding `@[deprecated]` attribute (#25712)\n- Fix last stmt is fn call in or_expr (fix #25732) (#25739)\n- Allow for `|mut x, y|expr` (fix #25734) (#25735)\n- Allow using `a`, `b` and `it` as var names, when using the builtin array methods (fix #25729) (\n  #25755)\n- Disallow generic function to be exported (fix #25794) (#25806)\n- Support `-d trace_parse` to ease diagnosing problems related to the order of parsing of .v files\n  in modules\n- Fix the language support for a nested anonymous C.struct (fix #25807) (#25789)\n- Disallow untyped `chan` used as a fn parameter type (fix #25818) (#25854)\n- Improve the unused import warning message (add fixing alternatives) (#25880)\n- checker,parser,ast: make `type MyBuilder = strings.Builder` work (part 1); add `mod` fields to\n  ast.SumTypeDecl and ast.AliasTypeDecl (#25943)\n- Remove dead code in Parser.is_array_type/0 (#26080)\n- Check invalid struct name in struct_init() (fix #26030) (#26093)\n- Remove the support for the obsolete generic fn call syntax f<T>() (first deprecated in 2022/11) (\n  #26126)\n- Fix comptime for lock shared field (fix #26143) (#26146)\n- checker,parser: add multifile gotodef support for -line-info (#26167)\n- Optmize Parser.call_kind (#26196)\n- Split parser methods to files based on topic (#24786)\n- Fix arch loongarch64 comptime support (fix #24906) (#24907)\n- Fix const error\n- pref,parser: implement support for `-force-bounds-checking` to enable easier testing of functions\n  tagged with `@[direct_array_access]` (essentially turning off that flag)\n- Allow keyword as struct param key on fn call (fix #24957) (#24958)\n- Fix syntax error for `for c in [othermod.Struct{field: 255}] {` (fix #24943) (#24978)\n- Reduce calls to util.contains_capital\n- Fix overriding of fn names in `-translated` mode (fix #25024) (#25061)\n- Fix asm modifier parsing (allow for `=r, =&r, +r, +&r,=m,=rm,=@ccl, =*r`) (fix #25070) (#25072)\n- Allow using aliased types in interface method implementations (provide backwards compatibility to\n  `ui`, during the migration of code from `gx` to `gg`) (#25106)\n- Fix interface method declaration with fixed array return type (fix #25137) (#25145)\n- Prepare for eliminating a warning for `v -cross -o vc/v.c cmd/v` (part 1) (reduce CI annotation\n  noise)\n- Add duplicate import symbol detect (fix #25185) (#25187)\n- vfmt,parser: move mark used from vfmt to parser (#25190)\n- v.ast: add a `mod` field to ast.FnTypeDecl too\n- Fix parse_cflag() support other flags between allowed_flags (fix #24121) (#24146)\n- Minimise allocations done for the common case in find_struct_field\n- Fix orm generic struct table type parsing (fix #24049) (#24149)\n- Fix mutiple imports at one line (#24241)\n- Fix range expr precedence on compound logical and operator (fix #24252) (#24275)\n- Fix invalid field name checking (fix #24279) (#24283)\n- Fix wrong string parsing (fix #24297) (#24298)\n- Fix panic for `struct Abc { pub mut: }` (fix #24404) (#24403)\n- Allow `mut static counter := 0` inside `unsafe {}` blocks (prepare for removing a `-translated`\n  mode quirk)\n- Fix duplicate mod imports (fix #24552) (#24559)\n- Reduce memory usage of ast.ScopeObject and ast.Ident instances (#24704)\n- Reduce allocations in empty_comptime_const_expr (#23324)\n- Add error for array init of Results `[]!type{}` (fix #23360) (#23375)\n- Allow map cast syntax `map[k]v(expr)` (#23401)\n- Inline some commonly used fns (#23535)\n- Fix anon fn return type option/result followed by comment parsing in vfmt mode (fix #23607) (\n  #23608)\n- Keep track of the number of all scanned tokens too, and show it with `-stats`\n- Fix the error message position, for a `struct Abc`, that lacks a body (#23627)\n- Prevent unused warning on `import mod { Sym }`, when `Sym` is later used, for more cases (fix\n  #23412) (#23626)\n- Add support for `-d trace_parse_file_path_and_mod`, to help diagnosing module lookup problems\n- Allow for `@[has_globals]` to be used for all V programs, turn the `@[wasm_import_namespace]`\n  error into a notice\n- Remove table dep for script main check\n- Fix enum value parsing inside array initialization (fix #23937) (#23941)\n- Fix the registration of fixed arrays, when size_expr is a const (fix #23946) (#23949)\n- Disallow invalid expr in comptime `$for` (fix #23953) (#23959)\n- Fix generic struct init detection `T{}` (#22682)\n- Improve the assert informations (related #22668) (#22679)\n- Make C struct fields public and mutable by default (fix #22695) (#22706)\n- Fix enum redeclaration error (fix #22759) (#22766)\n- Fix struct field name using keyword (fix #22826) (#22829)\n- Optimise mark_var_as_used calls, by moving it to an ast.Scope method (#22842)\n- Optimize method parameter detection in used check (#22915)\n- Fix block position's last line (#22913)\n- Support `@[must_use]` tag for fns/methods, and an experimental `-check-result` option (#22983)\n- Allow `type` as field type on params struct construction (fix #23091) (#23098)\n- Allow `type` and other keywords as plain attr value (fix #23150) (#23154)\n- Support `@[tag]` for hash statements, like `#define` and `#flag` (#23210)\n- Fix lots of parser panics, discovered through fuzzing with radamsa\n- Improve the error for keyword `lock`, used as a variable name (#21937)\n- Improve the error message position for invalid array attr keys (#21944)\n- Fix const field str() (#21998)\n- Update `@include` in templates, to work with relative paths & prevent recursive calls (#21943)\n- Check fn call args without comma between them (related #22021) (#22075)\n- parser,scanner,ast: make the scanner and parser more robust, by implementing more limits (\n  preventing panics, discovered by fuzzing)\n- Protect against too deep recursion in Expr.pos() calls\n- Check too many layers embedded generic type (fix #22089) (#22091)\n- Cache ident lookups for consts in ast Expr str (#22101)\n- Improve Type and TypeFlag related operations (#22107)\n- Fix parsing map value inside or expr (fix #12164) (#22180)\n- Fix const field str() (#22192)\n- Fix `.${var}` used in a template, compiled by `$tmpl()` (fix #22231) (#22270)\n- Check enum method duplicated (fix #20924) (#22294)\n- Register selective import aliases as used (#21613)\n- Allow multiple flag values in enum.from() for flag enums (fix #21569) (#21615)\n- Disallow duplicate operator overload  (#21675)\n- Support `[$d('s', 4)]int{}`, move resolving to method on `ComptimeCall` (#21701)\n- Support `$d()` in fixed size array `struct` fields (#21731)\n- Suggest using type alias when defining methods on non-local types (#21803)\n- Sugggest map initialization with the correct syntax  (#21817)\n- Fix parameter collision for generated `@[flag]` enum methods, with modules named `flag` (#21844)\n- Fix high order generic fn resolution (#21871)\n- Fix recognition of `mod.Enum.val` inside fn args (#21908)\n- Fix option as possible match case for sumtype (#21079)\n- orm: disallow invalid infix for where clause in `delete` and `update`  (#21113)\n- Fix case of falsely registering imports as used, remove unused imports (#21156)\n- Remove redundant comments_mode field (#21198)\n- Update file path fields; use more expressive name for file path, remove obsolete `file_name_dir`\n  field (#21202)\n- Add missing docstrings for vlib/v/ast/comptime_const_values.v functions (#21219)\n- Allow struct init on `for in Iterator{} {` (fix #21179) (#21282)\n- Fix `for x in Iterator{} {`, when there are no field initialisations (#21333)\n- Add check for result type on chan init (#21363)\n- Fix comptime panic for `$tmpl(\"x.html\")`, when the template file contained % at the end (#21402)\n- Parse string and array typ idx of `ScopeVar` and `Ident` (#21523)\n- Fix close_scope() missing, when field.name is `sort` or `sorted` (fix#20436) (#20485)\n- Check non-generic interface defining generic method (#20545)\n- vast,ast: output map init update expression (#20574)\n- Implement `MyEnum.from(1)!` generic static method (#20411)\n- Fix `MyEnum.from(0)!`, implement `MyFlaggedEnum.zero()` (#20623)\n- vfmt,parser: keep the original import name in ast.Import, and use it without modifications for\n  paths unders ~/.vmodules\n- Allow double quotes in `@include` template directives (#20628)\n- Fn type declaration does not check already registered name (#20732)\n- Fix global const ordering with string inter literal (fix #20760) (#20770)\n- Disallow option alias with option parent type  (#20769)\n- Make Scope.find methods more robust, when called on default initialised\n  `scope &Scope = unsafe { nil }` fields (#20774)\n- Fix parsing of cgen.v, in normal mode, when the table is empty (no files in `builtin` are\n  preparsed) (fix #20606) (#20611)\n- Fix infinite loop in Parser.sql stmt in `-silent -print-watched-files` mode (used by `v watch`) (\n  #20873)\n- Disallow defining map key more than once  (#20905)\n- Fix formatting comptime if expr, after inc expr (fix #20927) (#20931)\n- Fix for comptime with fully type name (fix #20948) (#20988)\n- Allow lock prefix instructions and numbered reg in inline asm blocks (#21022)\n- Add better error for mut variadic fn argument  (#21063)\n- parser: fix parsing comments after new attribute syntax\n- parser: fix failures found with fuzzing (#19873)\n- parser: deprecate old attribute syntax & update remaining (missed) attributes (#19879)\n- parser: fix infix expr handling with cast on left side of << operator (#19985)\n- ast: fix generic structs with multiple levels of generic embedding (#20042)\n- parser: implement thread returns result and multi_returns (fix #19281) (#20194)\n- parser: fix formatting struct decl with comments (#20207)\n- parser: fix formatting enum and interface decl with comments (#20216)\n- parser: fix fn call with newline opening brace (fix #20258) (#20267)\n- parser: fix parse_vet_file() with vfmt off/on flag (#20273)\n- Fix assigning static method to anon fn (#19499)\n- ast: fix formatting a struct declaration with a nested struct (#19592)\n- Add `set_all` + `clear_all` methods to `[flag]` enum bitfields (#19717)\n- ast: reduce cost of frequently called functions by using constants (#19733)\n- Warn on unused imports, even when they are declared via `import math { sin, cos }`   (#19738)\n- ast: add missing docstrings for the public fns in vlib/v/ast/types.v (#19752)\n- Give a friendly error when misusing if over $if (#19810)\n- Add multiple struct attributes error for new attribute syntax\n- parser: fix fixed array with eval const size (#19269)\n- parser: disallow using `sql` as name (#19298)\n- parser: fix `;` support for `module x;`\n- parser: fix fixed array of option values (`_ := [10]?int{}`) (#19392)\n- parser: fix assigning with in another module sumtypes 2 (#19415)\n- Support `;` statements, allowing for oneliners like\n  `./v -e 'import os; println( os.ls(os.args[1])!.sorted(a > b) )' vlib/math` (#19345)\n- v.ast: improve Stmt.str(), showing more details about ast.Block, ast.DeferStmt, ast.ForInStmt,\n  ast.GlobalDecl\n- Change warn to error, for const names with upper letter (fix #18838) (#18840)\n- Disallow declaring static functions as method receivers (#19007)\n- Disallow having builtin type as type names for `enum`, `sum type` and `alias` (#19043)\n- Support `const x := 123`, to make extracting locals as constants less annoying while prototyping\n- Fix struct field fn type with default value (fix #19099) (#19106)\n- Fix `for i++; i<10; i++ {` (fix #18445) (#19035)\n- Fix fn return alias of fixed array (#19116)\n- Fix generic struct init (Stack[&Person]{}) (fix #19119) (#19122)\n\n#### Comptime\n\n- comptime: fix comptime parameter resolve for `unsafe { nil }` to be `voidptr` (fix #25558) (\n  #25570)\n- comptime: fix codegen ptr field reading from comptimeselector (fix #25616) (#25620)\n- comptime: dont emit empty blocks (#26171)\n- comptime: support type interpolation in the msg argument of `$compile_warn(msg)` and\n  `$compile_error(msg)` (#24992)\n- comptime: fix $match with fn type (#25271)\n- Support `$if T is $pointer {` and `$if T is $voidptr {`, to make it easier to implement a pure V\n  dump(), without cgen specific code (#24628)\n- i32 is now `$int` too (fix #24346) (#24378)\n- Fix `$dbg` with `@[heap]` structs (fix #23979) (#23989)\n- Check invalid comptime field name assignment (fix #24415) (#24421)\n- Enable s390x + docs (#24114)\n- Add `typeof(var).indirections` and `T.indirections` (#22805)\n- Add `typeof(expr).unaliased_typ` (#22806)\n- Allow sumtype init by variant comptime var `T(v)` / `SumType(v)` (#22664)\n- Fix missing bool AttributeKind.kind (#23159)\n- Fix comptime `T.methods`  with generic types and interface checking with `is` operator (fix\n  #22721) (#22724)\n\n#### Compiler internals\n\n- markused: fix markused struct heap (#25542)\n- markused: fix array.prepend C code dependency (fix #25573) (#25582)\n- markused: fix fn marked as used when variable and fn uses same name (fix #25649) (#25650)\n- checker,transformer: add always true/false branch detection for the `if` and `match` constructs (\n  #25674)\n- v.util: measure more precisely how long a new tool recompilation lasts in launch_tool, when using\n  `v -d trace_launch_tool self`\n- transformer: fix struct init comparison turning into boolean (#25724)\n- v.builder: support V_NO_RM_CLEANUP_FILES=1, to ease debugging of -usecache issues\n- v.builder: make it easier to reproduce the exact specific stages of -usecache module compilation\n  by logging the full CLI options for each\n- v.builder: fix `.vsh` mode doing an implicit `import os`, now only for .vsh file itself (fix issue\n  spotted in #25736) (#25745)\n- v.builder: improve diagnostic information for a failed build_thirdparty_obj_file\n- transformer: transform ArrayInit into a function call for C and native backends (part 1)\n- builder,pref: add  `-file-list` support (implement feature #25707) (#25749)\n- pref: for -usecache, set .parallel_cc = false and .no_parallel = true to make compilations more\n  deterministic and ease CI diagnostics\n- markused: fix missing builtin__memdup definition, when an option struct field is used (fix\n  #25801) (#25802)\n- transformer: move array logic to array.v\n- v.builder: improve the error message for failing cgen; suggest `-g` and `-show-c-output`\n- v.pref: fix GitHub download URL for the photonwrapper .so file (fix #25708) (#25831)\n- v.pref: use `v download` for downloading the prebuilt `photonwrapper` shared library (#25849)\n- markused: fix const as fn mark as used (fix #25888) (#25895)\n- transformer: disable generic str_intp opt (fix #25896) (#25897)\n- v.scanner: remove obsolete .is_crlf and .is_vh fields (#25918)\n- v.scanner: use a named return for decode_XXX_escape_single methods, to reduce the generated C diff\n  churn, during scanner code updates\n- markused: add new auto_str() used funcs for bootstrap (#25938)\n- v.builder: provide more detailed error message, on `msvc: failed to build a thirdparty object`,\n  not just the failed command\n- v.builder: improve formatting of the `failed to build a thirdparty object` message for msvc\n- scanner: remove old generic check logic (fix #25959) (#25997)\n- transformer: fix the setting of a generic flag for fixed array type with `-new-transformer` (\n  #26009)\n- transformer: add file/line info for fn with `expand_simple_interpolation` (#26135)\n- transformer: add early return to avoid transform getting applied twice for a `for x < y {` body (\n  #26153)\n- markused: fix option none markused (fix #26147) (#26151)\n- v.builder: enable gc back with msvc, build separate `.debug.obj` thirdparty files when -g is\n  passed, to prevent linking issues (#26215)\n- v.builder: support compiling asm .S files to .o files, mentioned in #flag directives (needed for\n  #26185) (#26211)\n- v.builder: fix compile asm file, followup of PR #26211 (#26227)\n- scanner: fix multi-level string interpolation in if/match branch (#24805)\n- markused: fix mark for array init from sumtype (fix #24887) (#24889)\n- markused: whitelist `_option_none` too (fix #24862) (#24885)\n- markused: remove `@[markused]` from option and result fns (#24900)\n- markused: skip unused symbols, dump fns and generic specialization (fix #24921) (fix #24927) (\n  #24924)\n- parser,markused: support `@[markused]` for interface declarations too (#24963)\n- markused: fix interface fields and chan usage (fix #24961) (#24962)\n- v.builder: add a clearer error message for `v -shared run empty.v` (issue found by Felipe Pena)\n- markused: use eprintln for `PANIC DEPS` too (for consistency and easier redirection for the whole\n  trace)\n- v.util: add support for setting VUTIL_RETRY_MAX_COUNT=1 to ease the workflow for developing\n  backends\n- markused: improve the tracking of used closures (#25009)\n- markused: improve array resources tracking + remove all_fns loop for orm (#25007)\n- markused: fix generic map index (fix #25012) (#25022)\n- markused: improve array tracking (range, gated) (#25023)\n- markused: fix option tracking on sumtype (fix #25025) (#25028)\n- markused: fix thread type mark by go/spawn expr (fix #25049) (#25054)\n- scanner: refactor string interpolation (fix #24198) (#25053)\n- markused: fix array append c code dependency (fix #25057) (#25058)\n- markused: fix option array element (fix #23089) (#25179)\n- markused: fix option map value (fix #25186) (#25188)\n- parser,fmt,markused: add top level comptime `$if` support (enable\n  `$if platform { import module struct Abc {} }`) (#25216)\n- v.builder: add -DNO_DEBUGGING in addition to -DNDEBUG, when compiling with -prod\n- v.builder: support `-d trace_type_symbols_after_checker`\n- scanner: uncomment working rune test  (#25305)\n- v.util: fix handling of \"start \\u005c${...} end\" in cgen (fix #25304) (#25306)\n- markused: fix marking of mutable generic method calls (fix #25312) (#25314)\n- Remove closure usage from the compiler frontend (simplify bootstrapping/porting on more exotic\n  platforms)\n- markused: support orm or expr (fix #24040) (#24059)\n- markused: fix for gated index range on string (fix #24187) (#24200)\n- v.util.version: fix output for V full version when VCURRENTHASH not defined (#24264)\n- markused: fix generic method call mark (fix #24395) (#24399)\n- v.pref: add get_build_facts_and_defines/0 and set_build_flags_and_defines/2\n- v.util.version: fix output for V full version (followup on issue #24263 and PR #24264) (#24478)\n- v.util: use internal diff (#24495)\n- v.pref: prevent overriding backend (fix #21758) (#24526)\n- markused: fix for generic ptr receiver on method call (fix #24555) (#24558)\n- markused: fix `x := t.wait()`, when `t := go fn () string {` (fix #24577) (#24580)\n- markused: fix printing smartcasted interface values (fix #24579) (#24583)\n- pref: avoid changing the backend with `.js.v` when `-backend` has already been used (fix #7840) (\n  #24654)\n- Remove dump() calls inside the compiler itself (make bootstrapping of dump() implemented before\n  cgen easier)\n- markused: fix `-skip-unused` on a short program, that prints array (fix #23436) (#23437)\n- markused: fix `eprintln(err)` on imported module on short program (related: #23498) (#23499)\n- markused: fix markused auto str detection (fix #23501) (#23503)\n- markused: fix option ptr printing (fix #23559) (#23562)\n- checker,markused: add identification for sumtype.type_name() call (fix #23732) (#23739)\n- markused: improve stability (avoid runtime crash) when processing generic functions (partial fix\n  for #23927)\n- markused: fix markused behavior on array / map index getter / setter / slice (#23931)\n- markused: fix markused behavior on struct field's default expression (fix #23909) (#23933)\n- builder: do not search for msvc when it is not needed (#23386)\n- pref: stop parsing CLI options, on encountering `--` (#23470)\n- util: show `unknown command` suggestions, for more misspelled variants, like `v sefl`; make\n  util.new_suggestion calls parametrizable\n- pref: add Preferences.vroot_file/1 (done here, without using it, to ease the bootstrapping of the\n  cheaders extraction, that will follow next)\n- pref: fix panic in parse_args_and_show_errors, called with no args (fix #23713) (#23794)\n- pref: allow for `-os wasm32_emscripten` and filtering `_d_wasm32_emscripten.c.v` and\n  `_notd_wasm32_emscripten.c.v` files. (#23797)\n- v.builder: show the last line of the C compiler output, in case of errors, in addition to the\n  truncated first lines (the last line is useful, since it usually has an error counter)\n- os,v.transformer: fix warnings for\n  `./v -os cross -o vc/v.c cmd/v && clang-18 -o v_from_vc vc/v.c -lpthread`\n- util: fix stack overflow during parsing of `#flag -DName=$d(...)` (#23895)\n- builder: extract Builder.show_parsed_files/0 to make it easier to debug import/parsing issues\n- builder: remove forgotten b.show_parsed_files/0 call\n- util.version: centralise the use of `@VCURRENTHASH`, to minimise the vlang/vc diffs for each\n  commit\n- builder: support `-d trace_parsed_files`\n- util: shorten the V paths used in the C `#line` directives with tcc (the ../../../.. etc is no\n  longer needed with newer tcc) (#23974)\n- Add `:parse_text` to the paths of .v files, printed by `-print-v-files`, for parse time generated\n  snippets\n- v.pref: support a `_wasm32_emscripten.c.v` suffix for platform files too\n- builder: fix msvc build thirdparty obj file from .cpp (fix #22772) (#22789)\n- v.util: use temporary workaround for the vinix build problem (when VFLAGS is set, and `-ldflags `\n  is passed at the same time)\n- Allow getting notified about unused function params (#22879)\n- v.scanner: remove `Scanner.is_started` field (#22918)\n- v.scanner: fix string interpolation for float e format (fix #22429) (#23147)\n- cbuilder: remove flto with parallel-cc, it slowed down linking 10x\n- cbuilder: store split up C files in vtmp\n- v.builder: integrate more compile/linker options into parallel_cc.v (#23190)\n- v.builder: prevent passing `-x objective-c` with `-parallel-cc` for now\n- v.builder: move filtering logic for `-parallel-cc` to parallel_cc.v\n- v.pref: support `-debug` and `-cdebug`, as more explicit alternative names for `-g` and `-cg` (\n  #23208)\n- v.builder: fail the whole v compilation, if linking or compiling during `-parallel-cc` fails (\n  #23211)\n- v.pref: implement `-no-prod-options` to turn off passing `-O3 -flto`, while still keeping the\n  `$if prod {` branches (passing custom flags with `-cflags -Os` already works)\n- v.builder: support `-no-prod-options` with `-cc msvc` as well\n- scanner: guard against scanner panic, discovered by fuzzing in PR#22016\n- v.builder: show the thirdparty object compilation commands too, when using `-showcc` (when the\n  cache is empty)\n- builder: allow for `v -dump-defines - -check cmd/v`, which is faster, because it can skip code\n  generation\n- Reduce allocations for the most common cases (#22142)\n- transformer: add support for instrumenting the V compiler with `-d trace_transformer`\n- tools,cgen,pref: add `-coverage` support + `vcover`  tool (#21154)\n- v.utils: allow to set the names of the compared items, when diffing strings (#21650)\n- v.pref: fix regression of command flags not working, when there is a subfolder, named after the\n  command, in the current working folder (#21647)\n- transformer: handle `enum_variant = some_const + 10` (fix #21777) (#21779)\n- v.builder: print the suggestion for using `v xyz` instead of `v xyz.v` just once (#21801)\n- v.builder: improve the C compilation output on cgen errors (#21885)\n- v.scanner: use table lookups for very frequently done character checks (#21931)\n- markused: mark explicitly all used array and map methods with `-skip-unused` (fix #21907) (#21914)\n- v.util: use tmp instead of cache dir for temporary diff files (#21075)\n- v.util: fix module lookup if module import parts end with the word `modules` (#21083)\n- v.util: update `githash` to be able to get the githash of every passed project (#21178)\n- v.util: improve detection for opendiff when automatically searching difftools (#21241)\n- v.util: improve color_compare_files (#21247)\n- v.util: improve find_diff_cmd: don't add spaces to result without env opts (#21242)\n- v.util: fix diff coloring, add test (#21260)\n- v.util: polish off diff utils after recent updates and fixes, add doc comments to pub fns (#21275)\n- v.builder: suggest using `v wipe-cache`, when the object files are not recognized\n- pref: be more conservative when generating code using `-cross`, allow for `$if cross ? {`\n- builder: use cc enum in CcompilerOptions, fix cc detection, enable cc guessing without prod flag (\n  #21370)\n- pref: fix version flag handling (#21377)\n- pref: make minor performance related changes / simplify (#21379)\n- builder: simplify generic cc detection (#21380)\n- pref: extract architecture related code into `arch.c.v`; rename `pref.c.v` to `pref.v` (#21387)\n- pref: update `os_from_string`, add missing `qnx`, remove deprecated wasm options that used `-`\n  instead of `_` (#21390)\n- v.util: rewrite diff module, deprecate old functions (#21403)\n- v.util: fix color when auto tool is `diff` (#21435)\n- v.util: make diff_test.v more robust to the color settings for the chosen local diff tool\n- v.util: fix performance with `v test-cleancode`, when a slower diff tool is installed (#21447)\n- v.util: remove fast path in `diff.compare_text` (#21458)\n- v.pref: error for `v file.v --unknown-option` (#21391)\n- v.util: make launch_tool failures more detailed (for the `Text file busy; code: 26` case), bump\n  tool_recompile_retry_max_count from 3 to 7\n- v.util: make launch_tool more robust, when multiple `v -b js file.v` commands are run at the same\n  time (all trying to recompile the JS backend program) (#20631)\n- builder: allow for\n  `./v -freestanding -cc riscv64-elf-gcc -d no_main -no-builtin -no-preludes -showcc -keepc x.v`\n- pref: support file_notd_freestanding.v + file_d_freestanding.v, remove dependency to `os`, of $\n  embed_file(), when compiling with -freestanding (#20712)\n- v.builder: reduce the default noise from successfully rebuilding cached thirdparty object files\n- pref: allow fetching the photonwrapper .so (for the coroutines) with curl too, or print details\n  for manual download (#20855)\n- scanner: disallow a shebang line, that is not at the top of a file (#21029)\n- strings.textscanner: fix off-by-one error in skip method (#21045)\n- scanner: implement support for UTF-32 escape codes in string literals (#19911)\n- scanner: add new_silent_scanner/0, Scanner.prepare_for_new_text/1, make .ident_char/0,\n  .ident_string/0 and .text_scan/0 public (#20045)\n- pref: support VNORUN=1, to enable running of tests, vsh files etc (i.e. just compile them, for\n  debugging later)\n- scanner: fix backslashes followed directly by newline in string literals (fix #20291) (#20296)\n- scanner: fix escape character handling in character/rune literals (fix #20301) (#20304)\n- pref: disable the -macosx_version_min clang flag by default (#20297)\n- builder: remove passing `-fno-strict-aliasing`, for `-prod` to gcc/icc (#20368)\n- markused: add `-skip-unused` for programs that `import x.vweb` too (do not skip unused routing\n  methods)\n- checker, builder, pref: support `-dump-defines -` to help explore all the available user and\n  system defines for a given program (#19576)\n- pref,builder: add support for `-macosx-version-min 10.2` and `-macosx-version-min 0` (with default\n  of 10.7) (#19626)\n- pref: fix unintended file extensions in default output names, allow for `v run file.c.v` (#19745)\n- transformer: fix using a constant, instead of a fn parameter with the same name (fix #19766) (\n  #19773)\n- maps: add maps.merge() and maps.merge_in_place() generic utility functions (#19776)\n- coroutines: only attempt to add/remove roots when GC is on.\n- markused: cleanup in mark_used(), use robust index names, instead of the much more brittle integer\n  values (#19543)\n- pref: support `-fast-math`, passing either -ffast-math or /fp:fast (for msvc) to the C backend,\n  and `$if fast_math {` to detect it at comptime\n- parser, transformer: fix transformer.infix_expr() and cleanup parse_types.v (related #19269) (\n  #19276)\n- pref,builder: support -use-os-system-to-run to workaround segfaults using not fully updated xcode\n  command line tools\n- v.builder: fix compiling code, that imports modules from both `src/modules` and `modules` (#19437)\n- os, v.builder: show more details, when a program ran by `v run file.v`, exits by a signal (fix\n  #19412) (#19471)\n- pref: make -autofree work without -gc none\n- builder,pref: allow thirdparty objects compilation with CPP compiler (#19124)\n- scanner: fix string interpolation with nested string interpolation in inner quotes p. 3 (#19121)\n- scanner: error early on an unsupported escape sequence in a string, like `\\_` (fix #19131) (\n  #19134)\n- v.token: add inline next_to() and cleanup related calls (#19226)\n\n#### Standard library\n\n- arrays: fix rotate_left() and rotate_right(), add test (#25539)\n- encoding.base58: fix encoding, add test (#25538)\n- x.crypto.chacha20poly1305: move up responsibility for allocs into higher caller (#25574)\n- crypto.cipher: fix decryption in CBC mode, add test (#25584)\n- os: use `@[noinline]` on os.create/1 to workaround a `-cc gcc -prod` panic (fix #25549)\n- time: fix non-digit checks for parse_rfc3339() (#25597)\n- gg: add explicit bounds checking for image caching methods in gg (fix #25590) (#25591)\n- time: fix quarter calculation in custom_format() (#25608)\n- rand: fix randomness in shuffle() (#25617)\n- gg: destroy unused GPU resources before replacing cached images (#25615)\n- encoding.binary: fix serialize skip struct shared fields (related to issue #25600) (#25613)\n- x.crypto.chacha20poly1305: make implementation use fixed sized arrays more (#25627)\n- builtin: make result string end with null in `u8(x).repeat(y)` (fix regression after #22100) (\n  #25625)\n- gg: fix address of const warnings for `v -experimental program_using_gg.v`\n- builtin: add .hex() methods to the `rune` and `char` types too (#25635)\n- datatypes: fix insert() and delete() for items in second half of DoubleLinkedList[T]{}, add test (\n  #25647)\n- builtin: use an explicit loop to determine min_common_indent in string.trim_indent/0 to reduce\n  allocations and reduce the reasons for misfires of the closure detection heuristic\n- vlib: use `defer(fn) {` syntax where appropriate (part 2 of #25639) (#25653)\n- x.json2: fix decode_number not initializing value to zero (fix #25641) (#25675)\n- crypto.hmac: optimize hmac.new, support calculations with a blocksize > 256 (#25686)\n- math.unsigned: fix put_bytes(), add test (#25718)\n- builtin: reset .len and .cap to 0 too, in the array.free() method (#25717)\n- os: add pipe and stdio_capture support (implement #25714) (#25716)\n- encoding.utf8.validate: fix validation, add test (#25748)\n- crypto.blake2b,crypto.blake2s: add `@[direct_array_access]` to hot functions (#25750)\n- strconv: fix handling of subnormal numbers like `'1.23e-308'.f64()` (fix #25751) (#25752)\n- crypto.sha3: remove `import math` (just for int_max), to improve compilation time and complexity\n  for code that uses sha3\n- builtin: add declarations for C.GetCurrentThreadId(), C.gettid() and C.pthread_self()\n- builtin: add pid: and tid: fields to the panic reports (part 2 of #25808) (#25809)\n- gg: add doc comments for the FN** types (#25814)\n- rand: add missing i8() utility function (#25819)\n- builtin: fix C.SYSTEM_INFO (fix #25788) (#25823)\n- builtin: support `-d no_getpid` and `-d no_gettid` for systems that lack proper process management\n  APIs\n- math: fix vec2,3,4 project not using the right formulas (fix #25811) (#25813)\n- math.vec: swap u and v in the .project() method of Vec2,Vec3,Vec4 (#25841)\n- crypto.cipher: fix xor_key_stream() for OFB mode, add test (#25844)\n- encoding.binary: use unions for small speed increase and readability (#25867)\n- math.complex: replace `==` with eq_epsilon() in equals() (#25873)\n- crypto.cipher: fix xor_key_stream() for CTR mode, add test vector created with OpenSSL (#25866)\n- os: enhance os.cp() to mimic Python's shutil.copy2() (#25893)\n- io.util: use correct TempDirOptions parameter type name in temp_dir() (#25904)\n- builtin,sync: eliminate calls to _us32_lt in new_map/6, and in the spinloops in\n  Channel.try_push_priv, Channel.try_pop (#25912)\n- rand: restore error margin in dist_test.v back to 0.05 (the updated seeds were found by @tankf33er\n  in #25907)\n- builtin: reduce the max size of string representations of integers (#25919)\n- builtin: remove commented code, improve comments\n- x.crypto.chacha20: fix deprecation warning during compilation of Cipher.rekey/2\n- math.easing: fix in_out_expo(), add test (#25944)\n- builtin: split builtin.v and builtin.c.v into smaller, and more focused .v files, to ease working\n  on unrelated subsystems (#25965)\n- transformer: fix `v -new-transformer vlib/strconv/atoi_test.v` (#26021)\n- gg: add more documentation for color substraction (fix #21549) (#26023)\n- toml: fix for single `\\r` occurence in multi-line `\"\"\"` strings (`\\r\\n` is still allowed) (#26029)\n- toml: remove workarounds + `TODO`s for fixed issue #9507 (#26037)\n- x.json2: fix decode_number for u8 (fix #26027) (#26033)\n- rand.wyrand: switch to using the original C._wymix() as a performance optimisation (#26051)\n- strconv: fix float scientific notation (fix #26045) (#26046)\n- x.json2: fix decoding of float values in scientific notation (fix #26043) (fix #26062) (#26060)\n- builtin: add a declaration for C.memchr too (#26054)\n- toml: add compliance up until official toml-lang/toml-test@c6a78f1 (#26067)\n- builtin: fix some C fn parameter types (#26069)\n- toml: add compliance to official toml-lang/toml-test@8bb8d9c (#26070)\n- toml: remove special cases for `jq` normalization (#26092)\n- toml: fix remaining valid `key/*` exceptions (#26125)\n- builtin: make string.index_ public, to simplify code using a redundant\n  `x := s.index(sub) or { -1 }` pattern (#26123)\n- builtin: add declarations for C.memmem and C.mempcpy (#26129)\n- builtin: speed up, fix and test impl_utf8_to_utf32 (#26109)\n- toml: fix remaining valid `array/*` exception (#26138)\n- toml: fix unicode decoding panic on invalid TOML `key/duplicate-keys-06.toml` (#26140)\n- toml: allow `true` and `false` as keys when parsing root table (#26144)\n- toml: allow dotted key lengths > 2 within nested arrays of arrays (#26145)\n- flag: fix `v vet -W vlib/flag/` (fix remaining doc comments)\n- x.json2: fix memory access error, when decoding string enum values (fix #26176) (fix #26179) (\n  #26178)\n- toml: fix invalid exception by erroring on duplicate keys in inline table (#26177)\n- time: implement faster and simpler `push_http_header` (#26155)\n- toml: fix remaining invalid exceptions for `table/*` (#26189)\n- toml: reach 100% TOML v1.0.0 compliance with the official test suite (#26203)\n- x.json2: remove workaround_cast(), add isize usize decode support (#26210)\n- x.crypto: initial addition of curve25519 module (#24748)\n- thirdparty: add NDEBUG check before glGetErrorCode if-statement in sokol_gfx.h (#24754)\n- math.big: remove unnecessary code from / and % (the same is done in div_mod, which they call) (\n  #24766)\n- builtin: add a rune iterator method to strings, allowing `for for i, r in s.runes_iterator() {`\n  without first allocating an array for all the runes (#24769)\n- builtin: support `-d builtin_free_nop` to help diagnose problems with too early manual free()\n  calls\n- builtin: use s.runes_iterator() in trim_runes/2 to avoid needless allocation\n- builtin: add string.expand_tabs() (#24781)\n- os: do not resolve symlinks in os.find_abs_path_of_executable/1 (fix #24759) (#24761)\n- os: improve documentation (#24790)\n- gg: allow for `-d gg_memory_trace_frame` to be used in combination with\n  `-prealloc -d prealloc_dump`\n- sync: add SpinLock (#24788)\n- os: fix documentation for environ function (#24796)\n- sync: fix documentation for new_spin_lock function (#24795)\n- sync: add implementation for WaitGroup.go/1, add test (#24797)\n- sync: improve documentation (#24799)\n- sync: fix spin lock, add destroy() and try_lock(), add valgrind annotate support (#24798)\n- os: add os.write_bytes/2 as a complement to os.read_bytes/1, add test\n- sync: use SpinLock for channel (fix #24680) (#24802)\n- crypto: fix ambiguous expressions in DES implementation (#24814)\n- sync: use an atomic counter in test_waitgroup_go in waitgroup_test.v\n- datatypes: add lockfree version of counter and ringbuffer (#24839)\n- sync: add thread local storage (TLS) support (#24849)\n- math.unsigned: fix rotate_left() for uint256, add test (#24872)\n- math.unsigned: replace untested comments for uint256 public APIs (#24873)\n- log: use `@[noinline]` for level_from_tag/1 and target_from_label/1 to avoid triggering panics for\n  programs using `log`, compiled with -prod and -cc gcc>10 (fix #24874)\n- math.big: fix toom-cook 3-way multiplication (#24888)\n- runtime: add used_memory() (#24897)\n- runtime: add note for the availability of the used_memory implementation (#24913)\n- os: remove commented code in home_dir() function (#24929)\n- math.big: fix the order of calculations in mod_pow() to improve performance (#24935)\n- math.big: add shrink zeros to karatsuba and toom-cook (#24937)\n- math.big: fix big_mod_pow() (#24939)\n- os,runtime: move some C struct and fn def to `builtin` (#24942)\n- math.big: fix validate_string and integer_from_regular_string (check for characters.len > 0,\n  before accessing characters[0])\n- builtin: prepare for adding a `-force-bounds-checking` option\n- strconv: fix bounds check bug, discovered by the equivalent of\n  `./v -g -force-bounds-checking test vlib/toml/` (thanks to tankf33der)\n- builtin: fix OOB bugs in s.is_bin, s.is_oct, s.is_hex, discovered through\n  `./v -force-bounds-checking test vlib/builtin/`\n- regex: fix OOB bug discovered through `./v -g -force-bounds-checking vlib/regex/` (fix by\n  @penguindark) (#24960)\n- time: fix custom_format panic (fix #24977) (#24987)\n- time: fix more panics in the supported specifiers in Time.custom_format/1 (#24988)\n- vlib: add `archive.tar` module to enable reading of .tar ang .tar.gz files (#24995)\n- builtin: fix warnings for `./v doc -m -f html vlib/builtin/`\n- sokol.gfx: set the missed array_count field too in the `set_vert_uniform` and `set_frag_uniform`\n  APIs (#25019)\n- builtin: fix `assert \"ä ö å æ ã ø ô é ë\".title() == \"Ä Ö Å Æ Ã Ø Ô É Ë\"`\n  (fix #25017) (#25026)\n- Apply `@[markused]` to builtin_init, remove its heuristic from markused.v\n- gg: improve drawing effect and logic of draw_rounded_rect_empty (#25062)\n- math.bits: add asm implementations for some 64 bit ops (#25020)\n- vls: autocomplete for module functions: e.g. `os. ...`\n- math.big: move from u32 to u60 digits (#25018)\n- os: simplify file.c.v using cross platform f.seek/2 calls, add EINTR handling to\n  f.write_full_buffer/2 (fix #25107) (#25110)\n- builtin: add arr.pop_left() func (#25133)\n- math.big: refactor add_digit_array() (#25138)\n- math.big: optimize add_digit_array() (#25139)\n- math.big: optimize subtract_digit_array() (#25142)\n- strconv: produce a maximum of 8 digits after the `.` for f32.str() (fix #25141) (#25144)\n- math.big: restore and refactor str() and integer_from_string() (#25154)\n- os: remove `unknown host OS` panic from os.get_host_os()\n- flag: fix tail/single bool flag error condition logic in `flag_to.v` (fix #25166) (#25172)\n- flag: improve the fix for #25166 tail/single bool flag error in `flag_to.v` (#25189)\n- readline: fix wide char display width for Chinese characters (fix #25219) (#25220)\n- repl: fix handling of lines with comments like `math.pi // comment` (fix #25229)\n- time: always return utc() timezone for Time.unix/0 (fix #17784) (#25233)\n- builtin: fix C prefix for proc_pidpath() (#25239)\n- math.big: replace division with Knuth, improve performance (#25242)\n- time: move the nanosecond comparison before the rest in the Time == Time implementation\n- builtin: add a temporary ctovstring_impl/1 API to enable `ui` to compile cleanly for PR#25264,\n  part 1\n- json2: replace encoder with new implementation (#25224)\n- json2: improve enum decoding; fix handling of required fields at the end of a json string (#25289)\n- json2: improve checker with better EOF detection (#25075)\n- json2: prepare for moving into json2 (#25039)\n- json2: fix remaining json2 discrepancies (#25029)\n- json2: support custom decoders (#25021)\n- json2: fix number decoding and improve errors (#25015)\n- json2: add support for decoding utf-16 surrogates, produced by some JSON encoder implementations (\n  Python, Java, C#) (#25193)\n- x.crypto: add a new `ascon` cryptographic module, based\n  on https://doi.org/10.6028/NIST.SP.800-232 (Lightweight Cryptography Standards for Constrained\n  Devices) (#25260)\n- x.crypto.ascon: improve the core of Ascon permutation routine (#25278)\n- x.crypto.ascon: improve single-shot functions of ascon hashing variant; add benchmark (#25282)\n- x.crypto.chacha20: improves the internals of chacha20, add a bench (#25311)\n- builtin: string.index_after() ?int\n- cli: account for initial indent on subcommands (#23985)\n- Remove `strings.Builder.clear()`, fix `array.clear()` not working in the JS backend (#23992)\n- gg: make draw_rect_empty/5 draw more exact borders, independent of the device, and fitting the\n  draw_rect_filled/5 shapes (#24024)\n- sync: fix a helgrind false positive, for a data race, on PoolProcessor (#24023)\n- sync.pool: restore the parallel operation (surrounding the cb call in process_in_thread in a lock\n  in 1b52538, effectively disabled parallelism)\n- x.crypto.chacha20: change internal cipher to support a 64 bit counter (related to #23904) (#24039)\n- os: fix swap_bytes_u64 (#24033)\n- x.crypto.chacha20: fix `xor_key_stream` failing after a while (fix #24043) (#24046)\n- crypto.sha3: be big-endian friendly (#24045)\n- x.crypto.chacha20: makes the underlying cipher routine aware of the 64-bit counter (#24050)\n- x.crypto.chacha20: enable support for 64-bit counter (fix #23904) (#24053)\n- x.crypto.slhdsa: add a SLH-DSA implementation, a stateless hash-based DSA, a post quantum\n  cryptographic module (#24086)\n- encoding.binary: add encode_binary()/decode_binary() generic functions (#24106)\n- crypto.rc4: change the return type of `new_cipher` to be `!&Cipher` (#24113)\n- crypto: add a `crypto.ripemd160` module (#24119)\n- encoding.iconv: fix iconv on termux (fix #23597) (#24147)\n- sync: remove the call to C.pthread_rwlockattr_setpshared (not needed, since it is the default on\n  POSIX) (#24166)\n- pkgconfig, termios: Support NetBSD (#24176)\n- encoding.binary: fix serialize map struct (fix #24190) (#24192)\n- builtin,v.gen.wasm: support `-b wasm -d no_imports` (#24188)\n- datatypes: add a Set.array/0 method to help get all the elements from a set as an array (#24206)\n- json: fix option time (fix #24242) (fix #24175) (#24243)\n- log: add local time / utc time selection support (#24268)\n- json: link with libm (fix #24272) (#24273)\n- rand: add uuid_v7(), session function, simplify uuid_v4() (#24313)\n- toml: fix handling of multiline string with CRLF (fix #24321) (#24322)\n- toml: fix crlf escape check (fix #24328) (#24329)\n- x.json2: add u16(),u32() (fix #24337) (#24342)\n- rand: fix uuid_v7 seperator (#24348)\n- rand: check the separators for the generated UUIDs in random_identifiers_test.v\n- builtin: add string.is_identifier() (#24350)\n- x.crypto.chacha20: add a check counter overflow to set_counter for standard mode (#24365)\n- comptime: fix `$if var.return_type == 1 {` (fix #24391) (#24393)\n- comptime: enable ppc64le, add docs (#24433)\n- toml: add compile error when passing `encode/1` types of T != struct (fix #24435) (#24443)\n- sync.stdatomic: workaround for libatomic.a indirect symbols tcc bug (fix #23924) (#24472)\n- math.big: fix the + operator for big.Integer for negative numbers, add test (#24487)\n- math.big: respect the sign of the dividend in % operator, add test (#24489)\n- os: add note for the availability of the debugger_present implementation (#24492)\n- term: add writeln_color() (#24463)\n- math.big: add missing assert for test_multiply_karatsuba_02 (#24534)\n- builtin: fix mix prod and debug ucrt lib (#24498)\n- math.big: fix Karatsuba's add_in_place() function, add carry handler on exit (#24541)\n- math: add `exp_decay` to `interpolation.v` (#24545)\n- math.big: optimize divide_array_by_digit() (#24566)\n- sync.stdatomic: add atomic types (#24561)\n- sync.stdatomic: turn panic() in new_atomic[T]() into a $compile_error() (#24573)\n- sync: add condition support (#24574)\n- builtin: flush stdout on panic (#24606)\n- Document the behaviour of % for negative numbers; in V: -10 % 7 == -3 (#24604)\n- math.big: remove unnecessary casting from Integer.is_power_of_2/0 (#24614)\n- math.big: make is_power_of_2() be false for negatives (it now matches Julia's ispow2/1) (#24619)\n- vlib: vanilla_http_server (#24202)\n- os: support `dotfiles := os.walk_ext('.', '', hidden: true)` (#24617)\n- builtin: remove playground related code (the current playground uses a container/sandbox) (#24632)\n- comptime: fix `T.indirections` comparison (fix #24630) (#24636)\n- math.big: add test for radix_str() and integer_from_radix() (#24644)\n- runtime: make free_memory() and total_memory() return Result types to allow for reporting errors (\n  #24651)\n- math.big: improve the performance of radix_str() ~9 times (#24666)\n- math.big: speed up ~10x integer_from_radix() (#24674)\n- sync.stdatomic: fix bug with add() and sub() returning the new values, add voidptr support, add\n  swap() and compare_and_swap() (#24685)\n- sync.stdatomic: add atomic_thread_fence(), cpu_relax() (#24690)\n- v: support `@DIR` (as a comptime equivalent to `os.dir(@FILE))` at runtime) (#24742)\n- thirdparty: print the glGetError() code on failure too in sokol_gfx.h, to make diagnostic easier\n- builtin: make array.ensure_cap/1 public\n- os.font: fixes for `-os android`\n- vlib: add a pool module (#24661)\n- zstd: make the api more V like\n- szip: fix panic on empty files (#24335)\n- json: fix default struct field initialization with long array (#23355)\n- markused,builtin,strconv,vlib: reduce generated C sizes for compilers != tcc, for short programs,\n  by simplifying the generation of backtraces, and reducing string interpolations in panics (#23380)\n- thirdparty/sokol: allow `-cflags -D_SGL_DEFAULT_MAX_VERTICES=4194304` to customize how many\n  vertices you can send through gg/sokol in a frame\n- crypto.ecdsa: expand ecdsa module, to support other curves like secp384r1, secp521r1, secp256k1 (\n  #23407)\n- crypto.ecdsa: fix memleaks, reported by the CI sanitizer jobs (#23450)\n- ci: force the checking of changed vlib/crypto/ecdsa files with the sanitizer jobs\n- builtin: add a `@[markused]` tag to `isnil()`, because cgen generates calls to it in some cases (\n  #23462)\n- builtin: reduce a bit the generated #if defined checks for small programs (#23484)\n- crypto.ecdsa: improve safety checking, unify signing (and verifying) api to accept options (\n  #23463)\n- regex: fix misspelled word \"firts\" in replace_n description (#23514)\n- os: add split_path/1: `os.split_path('/usr/lib/test.so') -> ('/usr/lib','test','.so')`; fix\n  platform dependent behaviour of os.dir/1, os.base/1, os.file_name/1 (#23532)\n- breaking,log: set stderr as default log output, add .set_output_stream() to allow for opting in\n  the old default of stdout (#23444)\n- builtin: add `-prealloc -d prealloc_memset -d prealloc_memset_value=65 -d prealloc_dump`, to\n  better analyze the memory patterns of running V programs\n- builtin: change the default builder size used for string interpolations, from 256 bytes to 64\n  bytes\n- gg: mark create_image_with_size as deprecated (image resizing is done by `stbi.resize_uint8/3`,\n  with a different fn signature) (#23580)\n- crypto.ecdsa: split out the C wrapper to a new .c.v file (#23595)\n- builtin: add &u8.free() (fix #23592) (#23598)\n- crypto.ecdsa: fix bug in .with_no_hash handling (#23612)\n- crypto.ecdsa: fix handling of sign() with custom_hash (#23619)\n- runtime: add note for the availability of the free_memory/0 implementation (#23620)\n- builtin: make public the `FnGC_WarnCB` alias (#23633)\n- os: add disk_usage/1 (#23634)\n- builtin: add string.split_by_space() (#23651)\n- crypto.ecdsa: migrate `ecdsa.PrivateKey.new()` to use a high level API (#23640)\n- gg: fix incorrect Event.mouse_x and Event.mouse_y on gg.Context.event_fn and gg.Context.on_event\n  on HiDPI displays (#23668)\n- crypto.ecdsa: migrate generate_key and simplify it (part 3) (#23662)\n- encoding.csv: add support for multithreading to `encoding.csv.RandomAccessReader` (#23677)\n- v.builder: add` os.quoted_path()` to os.system calls using v.pref.out_name, for the compress\n  flag (fix #23685) (#23686)\n- time: reduce chances of failures on the CI, by time_test.c.v; make the failure diagnostic easier\n- time: improve the robustness of time_test.c.v (check if the diff is within ±1 second of the\n  current timezone difference)\n- crypto.ecdsa: migrate core routines for signing (and verifying), it now requires using OpenSSL 3 (\n  #23705)\n- all: use arguments() instead of os.args in some files\n- math.big: fix 1/115792089237316195423570985008687907853269984665640564039457584007908834671663\n  leading to panic (fix #23771)\n- v.cflag: support `#flag $when_first_existing(libABC.a, /some/path/libABC.a, ...)`, without\n  panicing (unlike `#flag $first_existing(...)`) (#23780)\n- term: add more comments in vlib/term/README.md\n- log: fix panic on mutex destroy, when exiting a program, while a thread is still logging\n- log: fix valgrind_test.v failure\n- math.vec: add `rotate_around_*` (cw/ccw) functions to `vec.Vec2[T]` (#23807)\n- math.big: bump newton_division_limit to 1_000_000 (workaround issue #23806)\n- math.big: add vlib/math/big/big_division_test.v (follow-up to 270941a)\n- strconv: fix strconv.atof64() inconsistency with the other .ato functions; make it return an error\n  by default, when it detects an extra non number character after a number (#23815)\n- os: add File.write_u8/1 and File.read_u8/0 helper methods\n- ci,os: fix bootstrapping with `-os cross -o vc/v.c` (avoid the generic calls in the new write_u8\n  and read_u8)\n- log: remove the notice about the stdout -> stderr migration (#23837)\n- veb: fix \"error parsing request: io.Eof\" when expecting a request body, but the data is not ready\n  yet (fix #22464) (#23842)\n- json: fix json.decode autofree codegen (fix #23834) (#23839)\n- time: add .week_of_year() method for time.Time instances (#23838)\n- time: add documentation for remaining time-related functions and ISO 8601 parsing (#23867)\n- crypto: add missing doc comments for public methods (#23864)\n- builtin,os: fix warnings for `./v -os cross -o vc/v.c cmd/v && cc -o v_from_vc vc/v.c -lpthread`\n- crypto.ecdsa: migrate new_key_from_seed to use high opaque, simplify the logic (#23876)\n- math: fix `./v -prod -cstrict -cc gcc-11 vlib/math/math_bench_test.v` (use unions to implement\n  f64_bits/1 and f64_from_bits/1 for compilers != tcc)\n- crypto.ecdsa: complete the migration to the newer OpenSSL APIs (follow up to #23876) (#23877)\n- x.json2: add a convenience Any.as_map_of_strings/0 method\n- cli: add missing struct members to str() method and fix some comments (#23893)\n- crypto.ecda: improvement the performance of `PrivateKey.new` by avoiding match+assignments (\n  #23899)\n- crypto.ecdsa: improves internal function of `calc_digest_with_evpkey` (#23901)\n- crypto.aes: fix notices about order of operations (fix #23898) (#23902)\n- Revert \"math.bits: port changes from e66e996, so that `-cstrict -cc gcc-11` passes for `markdown`\n  as well\"\n- crypto.ecdsa: improve the performance of the `.public_key` method of `PrivateKey` (#23920)\n- gg: add is_key_down/1 helper method\n- datatypes: optimize linkedlist (fix #23928) (#23934)\n- x.json2: fix \"\\\\\" scanner bug, disallow (ch < 0x20) unescaped control characters (#23954)\n- crypto.ecdsa: improve internal `sign_digest` routine (#23960)\n- builtin: improve performance of `string.starts_with/1` and `string.ends_with/1`, when compiled\n  with tcc (#22620)\n- builtin: improve `fixed_array_any_all_test.v` (related #22609) (#22621)\n- builtin: temporary fix fixed_array_any_all_test.v (#22624)\n- builtin: support `-d no_gc_threads` for turning off passing `-DGC_THREADS=1` while compiling the\n  GC library\n- encoding.utf8: fix is_punct func (fix #22646) (#22647)\n- log,time: improve performance for writing a line to a log, add Time.format_rfc3339_micro/0 (\n  #22662)\n- flag: add missing short flag match in `flag.to_struct`, add test (#22696)\n- bitfield: add `shift_left/1` and `shift_right/1` methods to `BitField` (#22700)\n- x.json2: pre-arranging the replacement of the decoder, to\n  match https://github.com/enghitalo/v/tree/decoder2_to_json2 (#22729)\n- builtin: improve fixed_array_any_all_test.v (#22746)\n- builtin: add `string.is_pure_ascii()` (#22748)\n- os: document the various enum values in os.Signal (#22770)\n- builtin: fix runes.to_upper() (fix #22742) (#22755)\n- ci: use os.system to redirect output\n- vlib: initial addition of `x.encoding.asn1` (#22783)\n- os: work towards being able to again use `-autofree` while recompiling the V compiler several\n  times\n- x.encoding.asn1: fix time creation to also accommodate negative timezone offsets (#22861)\n- vlib: remove modules/functions/fields, deprecated in 2023 (#22750)\n- term: improve performance of repeated can_show_color_on_stdout and can_show_color_on_stderr calls,\n  by caching their results (#22893)\n- builtin: make int_min/2 and int_max/2 public\n- json: mark json_print_pretty/1 with `@[markused]` (used by cgen)\n- math.big: use `@[manualfree]` to workaround -autofree compilation issues with gitly, and other\n  projects using `crypto.rand` and `math.big`\n- x.encoding.asn1: improve performance (#22948)\n- gg: use a larger fontstash text atlas by default (2048x2048, and customizable), instead of\n  512x512 (fix #21610) (#22959)\n- Revert \"os: deprecate `os.getwd` in favor of `os.get_current_dir` (part 1) (#22966)\"\n- log: tag log.fatal with @[noreturn] (#22986)\n- runtime: force runtime.nr_jobs() to return 1, while V is bootstrapping itself, from vc/ source,\n  that was compiled with `-os cross` (fix #22991)\n- json: fix decode codegen for []&type (fix #23007) (#23010)\n- os: add os.get_trimmed_lines() too\n- crypto.sha3: add support for Keccak-256 and Keccak-512 (#23058)\n- rand: add missing i32 APIs, corresponding to the int ones\n- math.big: fix `assert big.integer_from_int(1) == big.integer_from_bytes([u8(0), 0, 0, 0, 1])` (fix\n  #23115) (#23124)\n- math: use libc wrappers for math.log2/1, math.log10/1, math.log1p/1 and math.log_b/1; make\n  `assert math.log10(10) == 1.0` pass in the common case (#23129)\n- gg: add `icon` field to gg.Config, for easier access (fix #23135) (#23138)\n- math: fix math.log10() for `-exclude @vlib/math/*.c.v` (fix #23136) (#23140)\n- json: add primitive type validation (fix #23021) (#23142)\n- json: fix memory leak on result messages (checked with `json_option_raw_test.v`, compiled with\n  `-fsanitize=address,pointer-compare,pointer-subtract`) (#23172)\n- vlib: add new `rand.cuid2` module (#23181)\n- json: fix memleak on sumtype decoding (#23197)\n- vlib: enable more satnitized memleak detection runs without false positives on the CI (#23200)\n- json: fix argument freeing for json.encode and json.encode_pretty calls (#22781)\n- encoding.base58: fix notice for slice creation (#21935)\n- gg: reset ctx.mouse_d? and ctx.scroll_? at the end of each frame (fix #21945) (#21946)\n- builtin: v_segmentation_fault_handler signal_number i32\n- builtin: fix 'aaaa'.split('aa') (fix #21936) (#21951)\n- builtin: panic on trying to grow arrays with capacity bigger than 2^31, instead of overflowing\n  a.cap (partial fix for #21918) (#21947)\n- gg: add a note that Context.new_streaming_image has to be called after Sokol's setup\n- gg: add more documentation comments for gg.Config (the parameters of gg.start and gg.new_context)\n- regex: fix regex.split() (fix #16876) (#21953)\n- json: increase test cases before enabling sumtype decode in all json libraries (#21958)\n- gg: change the type of gg.DrawImageConfig.rotate from `int` to `f32`\n- gg: deprecate gg.DrawImageConfig.rotate, in favor of gg.DrawImageConfig.rotation, improve the\n  documentation comments (#21963)\n- x.crypto.chacha20: make Cipher struct public (fix #21967) (#21968)\n- tmpl: fix an extra newline in @for; builtin: some i64 fixes\n- gg: add an optional size: parameter to the .draw_pixels and .draw_pixel methods (defaults to 1.0)\n- sokol: update to match upstream at c0e0563 (#21971)\n- Add support for `Any` in `decode_struct`, `encode_struct` and `to_any` (#21972)\n- crypto.cipher: make Stream.xor_key_stream implementers require a mutable receiver (#21974)\n- sokol.audio: fix `./v -cc clang-18 -gc none simple_bytebeat.v` (the audio depends on threads)\n- time: `d`,`c`,`dd`,`ddd`,`dddd` pattern support for parse_format() (#22003)\n- flag: add optional value description to string parameters (#22024)\n- flag: add custom value descriptions for bool, int, and float flags too (#22032)\n- flag: fix assigning to `@[tail]` field when no fields has been matched yet in `flag.parse[T]()` (\n  #22043)\n- crypto: add a crypto.pbkdf2 module (#22047)\n- hash: add more methods to the hash.Hash interface, to match the ones in Go (#22001)\n- arrays: simplify arrays.sum and arrays.reduce (#22076)\n- x.json2: support @[skip] as well (#22077)\n- builtin,thirdparty: fix compilation of libgc with `-cc msvc -gc boehm` (thanks to @Ekopalypse)\n- stbi: change Image.data from voidptr to &u8, to reduce casts (#21977)\n- time: update parse_format comment description in parse.c.v (#22104)\n- vlib: add an `arrays.parallel` module, containing `parallel.run/3` and `parallel.amap/3`\n  implementations (#22090)\n- builtin: support `-d builtin_print_use_fprintf`, make the C fn declarations stricter (#22137)\n- builtin: fix map.clear() not resetting map's metas and keys blocks (fix #22139) (#22140)\n- builtin: fix incomplete m.clear(), allowing the map to have a duplicated entry for its first key (\n  fix #22143) (#22144)\n- builtin: fix m.clear() having different observable behavior to `m = {}`, after multiple iterations\n  of setting keys and clearing (fix #22145) (#22146)\n- builtin: fix bug in .clear() caused by sizeof(u32) being 4, not 2 (fix #22148)\n- flag: add support for parsing `flag.FlagParser` style flags in `to_struct[T]` (#22152)\n- flag: fix parse_bool_value() (#22160)\n- flag: correct bool logic, add test (#22162)\n- flag: fix parsing `flag.FlagParser` style short flags in `to_struct[T]` (#22172)\n- gg: change the type of PenConfig.thickness to f32\n- builtin: remove remaining references to v_calloc in function comments (#22179)\n- builtin: remove string interpolation from panic/1, to be able to use tools like cbmc in more\n  cases (#22182)\n- flag: add a relaxed parsing mode, that turn flag match errors into `no_match` entries instead (\n  #22191)\n- encoding.binary: add `u16`/`u32`/`u64` -> `[]u8` conversion functions  (#22193)\n- crypto.sha1, crypto.sha256, crypto.sha3, crypto.sha512: improve performance for non prod builds,\n  by tagging the block_generic functions with `@[direct_array_access]`\n- builtin: fix string.trim() (fix #13021) (#22205)\n- crypto.bcrypt: reduce runtime cost for running bcrypt_test.v, by reducing the iteration count\n- crypto.scrypt: add a new `scrypt` module to vlib/crypto (#22216)\n- sync.stdatomic: add OpenSUSE paths for libatomic\n- crypto.scrypt: add missing comment of source for test vector (#22222)\n- json: allow passing an anon struct as a decode type (#22228)\n- flag: fix parse_bool_value() with different order short args (fix #22176) (#22242)\n- builtin: drop C in int.v (#22245)\n- strconv: fix format_fl()/format_es() (fix #13210) (#22244)\n- json: fix decoding of structs with embeds (#22264)\n- crypto.rand: add support for convenient generation of a random big integer in the interval\n  `[0, n)` (#22266)\n- json: fix json encode/decode with embed support (#22277)\n- io: add a BufferedWriter and supporting methods (#22265)\n- vlib: add a go like `x.benchmark` module, that estimates automatically how many iterations are\n  needed, to get a statistically significant result (#22215)\n- math: document q_rsqrt\n- io: make buffered_writer_test.v more robust\n- builtin: enable GC lib on rv64 build (#22319)\n- json: support null sum types in decode()\n- crypto: ecdsa module (on top of openssl)\n- bench: crypto/ecdsa.v\n- math.big: fix `a + b` and `a - b`, when the signs are different, add more test cases (#22330)\n- builtin,v: reduce overhead and memory usage for very frequently called methods (#21540)\n- builtin: reduce allocations in s.index_kmp/1 and s.replace/2 (#21561)\n- os: remove mut declarions for unchanged vars in `os_nix.c.v` (#21564)\n- os: make minior improvement to C function semantics and related code (#21565)\n- builtin: simplify splint_nth methods (#21563)\n- toml: fix `@[toml: ]`, support `@[skip]` (#21571)\n- builtin:  update `last_index_u8`, deprecate `index_u8_last` string methods, make consistent with\n  `last_index` (#21604)\n- builtin: implement a JS version of `string.split_any` (#21612)\n- crypto: add a `crypto.sha3` hash and extended output functions (#21664)\n- crypto.sha3: remove unnecessary return at the end of the write function (#21669)\n- builtin: fix string.find_between(), when not found end string return '' (#21670)\n- builtin: add string.camel_to_snake/0 and string.snake_to_camel/0 methods (#21679)\n- cgen,x.json2: fix generic map decoding (#21704)\n- encoding.base32: fix warning of implicit clone of array, by using an explicit unsafe block (\n  #21728)\n- vlib: simplify byte character conditions by using methods like is_capital, is_lower, is_letter\n  etc (#21725)\n- gg: add Context.draw_cubic_bezier_recursive/2 and Context.draw_cubic_bezier_recursive_scalar/9 (\n  #21749)\n- ci: fix deprecations_consts.out (the warning for math.max_i8 is now an error; it was deprecated\n  since 2023-12-31)\n- math: add divide_truncated/2, divide_euclid/2, divide_floored/2 and modulo_truncated/2,\n  modulo_euclid/2, modulo_floored/2 (#21759)\n- math: avoid unused calculations for math.modulo_floored/2 and math.modulo_euclid/2\n- crypto.blowfish: apply `@[direct_array_access]` to very commonly used functions (#21771)\n- encoding.binary: little_endian_f32_at\n- arrays: add arrays.chunk_while/2, where\n  `arrays.chunk_while([0,9,2,2,3,2],fn(x int,y int)bool{return x<=y})==[[0,9],[2,2,3],[2]]`\n- sokol: reduce _SGL_DEFAULT_MAX_VERTICES back to 1<<17 (1<<22 in 811ac12, leads to ~140MB of memory\n  usage for gg/minimal.v, instead of just ~38MB)\n- vrepl: fix os.input() (#21811)\n- Improve consistency and behavior regarding explicit mutability (#21566)\n- builtin: add `pub fn arguments() []string {`; make `os.args` use it, remove edge case in cgen (\n  #21852)\n- builtin: support `-d use_bundled_libgc` to make it easier to debug/upgrade reliably libgc cloned\n  from ivmai/bdwgc (#21869)\n- time: increase http_header_string performance (#21894)\n- builtin: add s.trim_space_left/0 and s.trim_space_right/0 methods (#21903)\n- strconv,math.bits: eliminate bounds checking in commonly used routines\n- arrays: fix arrays.fold, when the `init` value in the call, is an array (#21921)\n- string: fix leak in replace_once\n- builtin,dlmalloc: fixes for `v vlib/v/gen/c/coutput_test.v` for gcc14.1, which is stricter\n- Min window width and height\n- builtin: str.last_index(); pref: hide-auto-str;\n- toml: update the alexcrichton and BurntSushi repos to their successors toml-rs, and toml-test,\n  record new exceptions (#21152)\n- breaking,vlib: update handling of imports whose symbols are not directly used in imported file,\n  remove `pub const is_used = 1` workarounds (#21160)\n- json: allow `i32` decoding and encoding (#21162)\n- json2: add ability to decode arrays (#21163)\n- json2,checker,toml: allow field.typ compile-time checking with MatchExpr and add array of option\n  checking (#21171)\n- gg: draw_text with custom fonts\n- x.json2: add a way to decode an array (#21186)\n- os: clarify some doc comments (#21209)\n- os: fix double free in os.get_raw_line() (used by os.input), with `-autofree` (#21204)\n- time: extract Duration related code into duration.v (#21229)\n- builtin: implement an `at_exit(cb)` wrapper for C.atexit (part 1) (#21254)\n- os: format readme, fix markdown inside html (#21286)\n- time: update unix time acces, fix issues related to deviating unix times (#21293)\n- vlib: refactor empty string checks to use `s == ''` or `s != ''`, instead of `s.len == 0` (#21300)\n- cli: update `command_test.v` (#21307)\n- cli: extend control over defaults (#21308)\n- thirdparty/sokol: bump _SGL_DEFAULT_MAX_VERTICES and _SGL_DEFAULT_MAX_COMMANDS again; mark them\n  with `__v_ start` and `__v_ end`\n- sync: add Gentoo paths for libatomic\n- sync.stdatomic: add flag lines for gcc 14 too\n- gg: make `PenConfig` fields public (#21353)\n- builtin: fix undefined read s[0], from ''.is_lower() and ''.is_upper() in c7af2c2\n- builtin: fix empty string lower / upper assert (#21358)\n- cli: simplify flag parsing (#21392)\n- os,runtime: workaround for v.c generation instability\n- datatypes: fix for set `-` operator, union and intersection, now they no longer change the\n  receiver (fix #21315) (#21362)\n- sync.stdatomic: add paths for compilation with musl on Gentoo (#21400)\n- os: fix os.execute stderr redirection (fix #20986) (#21404)\n- time: fix the string representation of a negative Duration (#21407)\n- cli: make program outputs using the cli module testable in `cli/testdata` (#21456)\n- math.unsigned: permit _ separators in Uint128 decimal strings passed to uint128_from_dec_str (\n  #21461)\n- cli: fix default flags when their command equivalents are disabled (#21469)\n- toml: simplify `decode_quoted_escapes` (#21472)\n- os: fix join-path (#21425)\n- builtin: simplify MessageError.msg() (#21524)\n- all: replace usages of C.atexit(cb) with `at_exit(cb) or {}` (part 2) (#21263)\n- math.unsigned: fix some Uint256 bugs and add tests (#21528)\n- x.crypto.chacha20: speed up the core functionality of the ChaCha20 stream cipher (#20470)\n- log: enhance log time format setting (#20484)\n- encoding.csv: add a new utility fn `new_reader_from_file/2` (#20530)\n- readline: add completion support (#20559)\n- builtin: add `is_hex()`, `is_int()`, `is_bin()`, and `is_oct()` methods to the string type (\n  #20540)\n- builtin: add empty string verification for the new string .is_oct() etc methods, suggested on PR\n  #20540 (#20564)\n- json: fix struct with option enum field (fix #20597) #20597\n- x.json2: fix panic on calling json2.decode of an optional enum (fix #20593) (#20603)\n- vlib: add a compress.zstd module (#20616)\n- io: ensure BufferedReader.read_line() returns `io.Eof`, instead of `error('none')` (#20619)\n- log: add support for l.set_short_tag/1 (#20652)\n- Update error checking for new error io.Eof (#20656)\n- io: allow BufferedReader.read_line() to accept custom line delimiters (#20655)\n- builtin: implement unbuffer_stdout/0 (#20662)\n- x.crypto: add sm4 module (#20651)\n- crypto.aes: optimise performance (#20674)\n- os: add proper process termination with p.signal_term() (#20671)\n- os: simplify and unify os.join_path and os.join_path_single, and add more tests (#21494)\n- bitfield: enhance operation with multiple flags (#20683)\n- os: fix File.read() in JS backends (fix #20501) (#20633)\n- os: add error_posix() and error_win32() for explicit platform error handling and default\n  behavior (#20694)\n- log: implement set_always_flush/1 for log.Log, log.ThreadSafeLog and log.Logger (#20698)\n- x.vweb: error() and simpler redirect(); comptime: a clearer error\n- builtin: add a string.u8_array() method (#20736)\n- os: add os.stat() and helpers (#20739)\n- os: make os.SystemError struct public so the os.error_* functions can be used by other modules (\n  #20754)\n- os: refactor to use os.stat and os.lstat instead of unsafe C calls (#20759)\n- os: make os_stat_test.v more robust to reporting false positives\n- x.crypto: add poly1305 message authentication code (mac) in pure v (#20752)\n- encoding.binary: add _fixed variants for the conversion fns, that accept fixed arrays (#20766)\n- x.crypto.sm4: make sm4 use the encoding.binary _fixed fns (#20773)\n- builtin: add gc_collect/0, gc_get_warn_proc/0, gc_set_warn_proc/1. Use them to turn off GC\n  warnings by default. (#20788)\n- builtin: support `-d gc_warn_on_stderr`, to show the GC warnings, without installing a custom warn\n  fn callback\n- x.crypto: add AEAD ChaCha20Poly1305 algorithm in pure v (#20817)\n- x.crypto.chacha20: remove deprecated `math.max_u32` in favour of builtin `max_u32`, remove\n  unneceseary bits, reorder (#20838)\n- json: fix decode struct ptr (#20828)\n- time: add a .http_header_string() method on Time (#20861)\n- json2: reorganize encode string (#20862)\n- vlib: add `encoding.txtar` (port of Go's txtar module) (#20874)\n- gg: handle dpi change, when moving window to another monitor (#20886)\n- time: add a tm_gmtoff field to `C.tm` (a BSD and GNU extension) (#20907)\n- x.json2: add skippable field attr `@[json: '-']` (improve backwards compatibility with the `json`\n  module) (#20892)\n- time: rename identifiers and parameter names (#20913)\n- io: add a `string_reader` submodule (#20893)\n- toml: return an error from toml.parse_file(), when the passed file path does not exist (#20912)\n- x.json2: fix encoder commas (#20916)\n- time: microoptimise the Time formatting methods (use custom number->string conversion, instead of\n  string interpolation) (#20917)\n- x.json2: improve performance of string encoding for unicode special characters and emojis (#20867)\n- x.json2: minor performance improvement, update benchmark recommendations (#20954)\n- os: workaround a `-prod -cc gcc` bug, affecting os.open_file (fix #20923) (related to #20872) (\n  #20960)\n- cli: add pluralization to err msg, if required number of args is not met (#20971)\n- os: remove repetitive words in comments (#20981)\n- gg: fix empty circle in native; http: post_form_with_cookies; veb: print veb action in html errors\n- io.reader: make read_all constants public (#20997)\n- builtin: expose gc_disable(), gc_enable(), gc_is_enabled(), in addition to the existing\n  gc_collect() (#21002)\n- x.json2: improve error message upon missing comma (#20602)\n- builtin: fix a few grammar errors in builtin.string comments (#21010)\n- io.string_reader: fix needs_fill_until check (#21005)\n- builtin: add missing return type to fn signature for C.GC_get_stack_base\n- x.json2: predefine buffer capacity for encoding to avoid reallocations (#20920)\n- rand: add PRNG.fill_buffer_from_set/2 (#21037)\n- sokol.gfx: update the PixelFormat V enum, to exactly match the C sg_pixel_format from\n  thirdparty/sokol/sokol_gfx.h\n- json: fix recursive pointer encoding (#19840)\n- os,picohttpparser,sokol,strconv: prepare for making `-W impure-v` the default (#19846)\n- os: add fast path to mkdir_all, when the given folder already exists (#19869)\n- os: ignore empty path segments in `join_path` (#19877)\n- os: fix bootstrapping for OpenBSD\n- x.json2: replace deprecated type byte with u8 in the tests (#19909)\n- vlib: change byte to u8 (#19930)\n- sync: add a FreeBSD specific version of vlib/sync/sync_default.c.v (#19962)\n- datatypes: add push_many for doubly and singly linked list + add insert_many for heap (#19975)\n- datatypes: make `Direction` pub and fix and add tests for `push_many` (#19983)\n- gg: fn (data voidptr, e &Event) for events, allows methods\n- vlib: add a `compress.szip` module, deprecate the `szip` one after 2023-12-31 (#20003)\n- os: create the folder described by `XDG_CACHE_HOME`, *if it is non empty, and it does not exist\n  yet*, when calling `os.cache_dir()` (#20046)\n- vlib: use the builtin flush functions, instead of the C. ones (#20108)\n- crypto: add blake2s and blake2b hashes (#20149)\n- os: fix `mv_by_cp` for directories (#20154)\n- os: update mv fns, improve performance, add params struct to control overwrite behavior (#20156)\n- gg: fix overlapping slices in `draw_slice_filled()` (#20182)\n- json: fix option sumtype handling (#20186)\n- builtin: add `@[direct_array_access]` to js string trim_right method (#20222)\n- json2: add encoder support for `time.Time`  (#20228)\n- json2: fix encoding of 💀🐈 etc emojis (fix #20243) (#20247)\n- json2: make public the generic function `map_from/1` (#20294)\n- json2: optimise encoding to be faster than cJSON with -prod (#20052)\n- json2: support sumtype encoding in a more robust way (#20093)\n- json2: strict module (#17927)\n- crypto: fix notices/errors for `v -N test vlib/crypto`\n- crypto: add blake3 hash (#20319)\n- sokol: fix compiling gg and other graphical examples on OpenBSD (#20333)\n- csv: Add a sequential reader too (suitable for very large .csv files, it does not read everything\n  at once) (#20140)\n- builtin: add an `unsafe { a.reset() }` method, for quickly setting all bytes in an array to 0\n- math.fractions: use operator overloading and deprecate old functions (#19547)\n- gg: fix the alignment of the bottom border of draw_rounded_rect_empty on macos and linux\n- crypto.bcrypt: fix bcrypt failure for valid pass and hash (fix #19558) (#19569)\n- sokol: update sokol to the latest version\n- builtin: fix sizeof(C.BOOL) (windows specific) (#19589)\n- math.big: fix incorrect division with negative numbers (fix #19585) (#19587)\n- os: add a convenient way to ignore certain system signals (#19632)\n- os: fix os.ls(folder) on windows, when a protected folder can not be opened (#19647)\n- os: add a convenient way to ignore certain system signals (#19639)\n- crypto.sha: fix calculating the same hash values when .sum() is called several times for\n  sha1/256/512 (fix #19696) (#19697)\n- crypto.md5: fix calculating the same hash values, when .sum() is called several times (#19703)\n- os: add a new function `execute_opt` (#19723)\n- os: add os.page_size() (#19770)\n- os: implement os.fd_is_pending/1, os.Process.pipe_read/1, os.Process.is_pending/1 (#19787)\n- builtin: copy min/max integer values consts from `math` to builtin so that the entire math module\n  doesn't have to be imported(#19809)\n- json2: add support for nested structs (#19579)\n- math: speedup the pure V math.pow implementation for non-fractional powers (#19270)\n- math: add more C. fn overrides, for the default C backend (speed up examples/path_tracing.v) (\n  #19271)\n- time: add `MMM` support for parse_format() (#19284)\n- os: include sys/sysctl.h on FreeBSD to avoid implicit definition of sysctl function (#19293)\n- crypto.md5: change the Digest.write return type, from `?int` to `!int` (#19311)\n- v.help: use os.executable() instead of `@VEXE` as an anchor, so `v help` will work more robustly.\n- toml: fix custom `to_toml` for complex structs (#19338)\n- vlib: add net.http.file, allowing for `v -e \"import net.http.file; file.serve()\"` (#19348)\n- vlib: remove functions and fields, deprecated before 2023-03-20\n- toml: fix toml encoding of complex types (#19408)\n- arrays: add a partition function, that splits a given array, based on a criteria, passed as a\n  callback fn (#19417)\n- toml: add decoding for struct fields of type map[string]T (#19447)\n- arrays: add arrays.each, arrays.each_indexed, and tests for them\n- encoding.html: implement `unescape()` (#19267)\n- eventbus: add generic support for event name (#18805)\n- readline: add support for ctlr+w and ctrl+u shortcuts (#18921)\n- strconv.atoi: fix string.int() returning numbers for non number characters (fix #18875) (#18925)\n- builtin: reduce the number of array allocations for consts in all V programs (#18889)\n- builtin: move array.data to the top of the struct\n- os.notify: implement the kqueue backend for notify.FdNotifier (#19057)\n- vlib: add a new module `builtin.wchar`, to ease dealing with C APIs that accept `wchar_t*` (\n  #18794)\n- arrays: add more util functions and tests for them - find_first, find_last, join_to_string (\n  #18784)\n- vlib: use sync.new_mutex() consistently for initialising all vlib structures containing mutex\n  fields\n- crypto.pem: add a static method `Block.new`, to replace `new` (#18846)\n- crypto.pem: add decode_only and general improvements to decoding (#18908)\n- log: improve the most common use case, it's no longer necessary to create a `Log` instance (\n  #19242)\n- crypto.sha512: make the new384/0, new512_256/0, new512_224/0 functions public\n- json: fix option alias support (#18801)\n- time: fix `parse_format` with `YY` (#18887)\n- math.big: allow bitwise ops on negative signum (#18912)\n- math.big: make is_odd public and add test cases (#18916)\n- math.big: add checked division methods (#18924)\n- math.big: add `isqrt_checked` and standardize error format (#18939)\n- sokol: use GLCORE33 on linux\n- os,term.termios: add termios.set_state/2, state.disable_echo/0, use them in os.input_password, to\n  fix `v -os wasm32_emscripten examples/2048/`\n- gg: implement Android specific APK asset loading for the `create_image` function (#19015)\n- sync: make sync.Direction public (#19047)\n- time: store time with nanosecond resolution in time.Time, deprecate Time.microsecond, add utility\n  methods and tests (#19062)\n- time: add a format_rfc3339_nano() method to time.Time\n- time: add 'i', 'ii' in custom_format() for 12-hours clock(0-12-1-11) (#19083)\n- gg: expand the `-d show_fps` background, so fps>100 will not overflow it\n- Math.big: restore gdc_euclid, use it for smaller numbers, fix bench_euclid.v .\n- Add new generic `arrays.uniq`, `arrays.uniq_only`, `arrays.uniq_only_repeated`,\n  `arrays.uniq_all_repeated`, `arrays.distinct`\n- builtin: add support for `-d builtin_writeln_should_write_at_once` and\n  `-d builtin_write_buf_to_fd_should_use_c_write` (#19243)\n- builtin: always show the assert message, if it was defined in the source, in non test programs\n  too (fix #19240)\n- time: check if a day is a valid day of its month (#19232)\n- toml: Add generic automatic decoding and encoding of simple structs, when they don't implement\n  custom methods (#17970)\n\n#### V interpreter\n\n- Add comptime-if support (#24919)\n- Reset return value after const eval and fix if-expr (#24955)\n- Add more infix op support; fix early func return (#24965)\n- Fix if-else; add infix op; fix func calls (#24972)\n\n#### Web\n\n- net: fix cookie parsing when `;` is used (fix #25544) (#25561)\n- veb: new fasthttp module with -d new_veb (multithreaded, epoll/kqueue): makes veb multithreaded\n  and fixes frequent hangs\n- veb: fix gzip middleware decode/encode (fix #20865) (fix #25753) (#25754)\n- veb: gzip support for StaticHandler (fix #20859) (#25758)\n- veb: support markdown content negotiation, compliant with https://llmstxt.org/ (#25782)\n- fasthttp: move kqueue related code to a separate file\n- veb: add zstd compression support (#25816)\n- veb: remove println('send_file ct=...') leftover (#25834)\n- ci: reduce false positives for veb_should_listen_on_both_ipv4_and_ipv6_by_default_test.v by\n  retrying it 3 times (since sometimes binding to the port it listens to fails)\n- veb: add an early startup panic error message, when the result type of route handler methods *is\n  not* `veb.Result` (fix #25970) (#25973)\n- net.mbedtls: make errors more verbose, to ease remote diagnosis of issues\n- net.openssl: make errors more verbose, to ease remote diagnosis of issues\n- veb: improve the before_request documentation\n- veb: add method.location too, to the invalid return type error, to ease diagnosing problems while\n  prototyping\n- wasm: fix const reference another const (fix #25722) (#26010)\n- fasthttp: fixes and improvements (#25906)\n- wasm: export pub fns in main module when targeting wasi (#26041)\n- net.http: use error_with_code in download_file() (fix #26056) (#26057)\n- net.http,veb: fix detection of the headers/body boundary in parse_request_head_str (fix #26091) (\n  #26112)\n- fasthttp: expand http request parser (related to #26091 part1) (#26104)\n- net.ftp: fix get() command conversation, add test (fix #18858) (#26194)\n- x.sessions: verify HMAC signatures when extracting sessions IDs from cookies (#26199)\n- net.http: fix a panic in parse_multipart_form, for small/incomplete form data (fix #26204)\n- net.http: support keep-alive connections in server (fix #26136) (#26218)\n- picoev: fix documentation (#24811)\n- veb: fix `app.text()` -> `ctx.text()` in `README.md`\n- net.http: fix panic in parse_multipart_form for invalid boundary (fix #24974) (#24976)\n- net.http: remove debug println statement from post_multipart_form (#25030)\n- net.http: reduce the false positives on the CI for server_test.v, let\n  test_host_header_sent_to_server return early, when the server can not start\n- net: improve tracing output for `-d trace_tcp`; move `error_code()` calls right after the\n  corresponding C APIs (errno is a global that should be read immediately to be valid)\n- veb: fix a spurious error with Chromium, for POST requests, split into 2 parts, 1st with only http\n  headers, without body (fix #25191) (#25195)\n- net.http: Use a full url when using a proxy, instead of only the path (#25228)\n- net.http.file: allow for serving requests to static files with cache busting suffixes like\n  `/dist/littlejs.js?1117`\n- veb: fix generic field access from alias (fix #25215) (#25246)\n- ci: change url to http://archive.ubuntu.com in .github/workflows/disable_azure_mirror.sh\n- net: add `read_ptr/2` (from `read/1`) to `UdpConn` for consistency with `TcpConn` (#24000)\n- net: make `close/0`, `select/2` and `remote/0` methods of `UdpSocket` `pub` (#24004)\n- Fix $dbg on function that uses veb comptimecall (fix #23999) (#24088)\n- veb: allow route methods, that are tagged with `@[unsafe]`\n- veb: support `-d veb_max_read_bytes=16384`, `-d veb_max_write_bytes=16384`,\n  `-d veb_default_port=1234`, `-d veb_max_http_post_size_bytes=8388608`\n- net.http: support `v -http -d http_folder=vlib/_docs` (allow customizing the folder, port, and\n  index file through CLI arguments to v -http)\n- thirdparty: upgrade to mbedtls v3.6.3.1, add a .patch file with the local changes (#24602)\n- veb: fix handling of default CorsOptions.allowed_headers (#24703)\n- veb: add `ctx.no_content()` + prevent content-type being set if the mime type is empty (#23425)\n- net.ftp: use unsafe { nil }\n- net.smtp: make public the Attachment fields (to be used as plain structs in initialisation) (\n  #23477)\n- x.vweb: remove the entire module (it's now veb)\n- ci: fix failure of the docker-ubuntu-musl job (keep vlib/vweb/vweb_app_test.v in the skip_files)\n- picoev: enable running veb services on Termux\n- thirdparty: improve `-cstrict -cc clang-18 -prod` compatibility for programs that do\n  `import net.mbedtls`\n- net.http.file: use urllib decode uri, to handle urls to files that have unicode characters in\n  their name (fix #23683) (#23684)\n- veb.csrf: do not print anything by default, add an `verbose: true` option, to restore the old\n  behavior if needed (#23725)\n- net.unix: make unix_socket_test.v trace its actions more thoroughly\n- veb.request_id: new middleware that implements request ID tracking (#23727)\n- veb: update the blog tutorial\n- net.openssl: use proper library search path for local installations of OpenSSL 3, use\n  `SSL_get1_peer_certificate` instead of the deprecated `SSL_get_peer_certificate` .\n- ci: fix vweb_run_at.run.out and vweb_run_at.skip_unused.run.out, ensure stable ordering of\n  stdout/stderr for `v run file.v`, in case of compiling a program with warnings/notices.\n- veb: handle sendfile errors, when the connection is canceled, before the file is completely\n  transferred (#23891)\n- veb: translations via %translation_key\n- picoev,net.http: use Time.http_header_string method, to improve performance (#22619)\n- Do `import veb`, only for templates that do use functions defined in `veb`\n- picoev: support `-d picoev_verbose_errors`, do not use any naked `eprintln` by default, since that\n  is a low level module\n- picoev: fix the incompatible pointer type cast error in the C.epoll_wait call (#22785)\n- net.mbedtls: define MBEDTLS_THREADING_PTHREAD, in mbedtls_config.h; call\n  C.mbedtls_ssl_conf_read_timeout explicitly in the wrapper, with a shorter timeout value of 317ms (\n  determined experimentally)\n- veb: fix large file transfer timeout (fix #22489) (#22924)\n- net.http: send Host headers with port (when the port is != 80 or 443) (fix #22941) (#22942)\n- net.mbedtls: support compiling with `-d mbedtls_client_read_timeout_ms=7000`,\n  `-d mbedtls_server_read_timeout_ms=60000`, and `-d trace_mbedtls_timeouts`\n- net.urllib: fix parse of url relative address (fix #21061) (#23180)\n- veb: fix key value and translation file name (#23203)\n- Check for using comptime $veb.html()/$vweb.html(), without importing veb or vweb (#21957)\n- net: add net.Dialer and net.Connection interfaces, abstracting the different types of connections,\n  already supported by the V network stack (#21657)\n- net.mbedtls: support Server Name Indication (SNI) (#22012)\n- veb: extract constants into consts.v (#22132)\n- vweb: mark vweb as deprecated in its README, recommending using veb instead (#22131)\n- veb: fix `vweb_livereload` reference to `veb_livereload` (#22171)\n- veb: fix a few minor errors in the README.md (#22177)\n- net.mbedtls: store the client ip (for ipv4), shutdown on handshake failure, in .accept() (#22184)\n- veb: implicit context\n- veb: make implicit context work with custom user types\n- net.websocket: use retrying on EINTR in Client.listen() (#22279)\n- net: allow ipv6 address with brackets (fix #22313) (#22316)\n- net.http: change default http.Server listening address to :9009, to avoid conflicts with tools,\n  that start their own http servers on 8080 like bytehound (#21570)\n- net.urllib: update parse host to allow for better error handling (#21602)\n- net.html: quick workaround for a cgen problem for `const x = int(0x80000000)`\n- net.http:  implement http.download_file_with_progress/2, saving each chunk, as it is received,\n  without growing the memory usage (#21633)\n- veb: update import name in docs (#21668)\n- Add `m3u8` MIME type `application/vnd.apple.mpegurl` for multimedia playlists (#21688)\n- veb.auth: use constant time comparison in compare_password_with_hash (#21693)\n- net.http: correct `Response.status()` method comment, to indicate returning of a `Status` enum\n  field, instead of struct (#21735)\n- net: fix TcpConn.peer_ip/0 to only return the ip address, without the port number (#21831)\n- Add mime type `text/x-vlang`, for `.v` and `.vsh` file extensions (#21851)\n- net.conv: add conv.reverse_bytes_u64/u32/u16 (#21917)\n- Update `mbedtls` to latest compatible version v3.3.0 (#21118)\n- veb.auth: a minor find_token fix\n- Improve descriptions (#21155)\n- ci: change listen ports in vweb_should_listen_on_both_ipv4_and_ipv6_by_default_test.v for both\n  vweb and x.vweb, to reduce probability of network errors\n- ci: mark both vweb and x.vweb versions of\n  vweb_should_listen_on_both_ipv4_and_ipv6_by_default_test.v as flaky\n- breaking,net.ftp: allow to choose a different port than port 21 (change FTP.connect to accept\n  `host:port`, not just a `host` address) (#21185)\n- x.vweb: accept query params as method arguments (#21201)\n- net.http.file: support index_file (`index.html` by default), and auto_index (true by default)\n  parameters to file.serve()\n- veb: copy x.vweb to veb, and make it work with comptime\n- ci: fix the ubuntu-docker-musl job by skipping veb_app_test.v\n- pref: support a shortcut: `v -http` for `v -e \"import net.http.file; file.serve()\"` .\n- net: add a .port()! method for net.Addr (#21412)\n- net: improve error message in .port()\n- picoev: handle `EAGAIN` or `EWOULDBLOCK` quietly (#21480)\n- net.unix: remove debug/trace eprintln (#21517)\n- net: fix vlib/net/tcp_test.v (since .listen_tcp with af .unix, is now expected to return an\n  error) (#20472)\n- net: remove unused import in tcp_test.v\n- x.vweb: add error, when static directory does not exist (#20455)\n- net.urllib: fix parsing url error, when querypath is '//' (fix #20476) (#20504)\n- vweb: unify listen address from tcp and print (#20448)\n- net.unix: make the error messages in unix_test.v more specific (#20537)\n- vweb: add an optional Context.before_accept_loop/0 method, to make testing easier and more\n  robust (#20538)\n- vweb: fix routes without results in vweb_app_test.v (#20548)\n- vweb: make vweb_test.v more robust and faster, by embedding its server as a module\n- Small fixes and backport changes from vweb (#20584)\n- net.smtp: implement mail attachment support (fix #19920) (#20640)\n- vweb: fix quickstart docs in the module's README.md on how to create a new vweb project (#20644)\n- net.http: add a temporary fix for the intermittent segfault with http.get_ text/1 and\n  `-prod -cc gcc` 13.2.0 (fix #20506) (#20660)\n- x.vweb: support HTTP 1.1 persistent connections (#20658)\n- x.vweb: use `$if debug_ev_callback ? {` for the\n  `[vweb] error: write event on connection should be closed` message\n- x.vweb: add cors middleware (#20713)\n- x.vweb: add new sessions module (#20642)\n- net: fix non-blocking read/write (#20438)\n- net: reduce flakiness of tcp test (#20761)\n- picoev: renaming, doc (#20567)\n- x.vweb: add full static host support, for urls ending with /folder/ , where the folder backing it,\n  has `index.html` inside (#20784)\n- x.sessions: change session Store interface to use results instead of options (#20796)\n- net: fix function name in split_address doc comment (#20794)\n- doc: x.vweb static website capabilities (#20808)\n- thirdparty: update picohttpparser (#20843)\n- picohttpparser: restore formatting for g_digits_lut, after f09826e (#20844)\n- x.vweb: fix handling of static URL paths like `/sub.folder/a_folder` (#20863)\n- veb: a new module veb.auth for authentication logic (tokens, hashed passwords)\n- veb.auth: make work with any db\n- net: workaround a `-prod -cc gcc` bug (#20872)\n- picoev: add more logging of errors (#20558)\n- picoev: remove fmt off tags (#20569)\n- net.mbedtls: use `char` and `usize` types for describing more precisely the C API of mbedtls (\n  #19837)\n- vweb: add the mime type for .toml files (#19875)\n- net.openssl: use actual C values for the SSLError enum (#19945)\n- vweb: .html('custom_template.html')\n- vweb: add an optional parameter to the .redirect/2 method, to be able to set the http code for the\n  redirects (#20082)\n- x.vweb: fix large payload (#20155)\n- x.vweb: reimplement csrf module (#20160)\n- net: make net.fionbio and net.msg_nosignal constants public in net_windows.c.v (#20183)\n- net.http: remove unused `read_set_cookies` function (#20187)\n- os, net.http.file: add a folder listing to the http static file server, started by file.serve/1 (\n  #20192)\n- websocket: enable using an already existing connection (from vweb or another http server) (#20103)\n- x.vweb: fix fsanitize-address test for SSE, improve documentation on the usage of\n  `takeover_conn` (#20249)\n- net.http: support `-d no_vschannel` on windows, to fix long waits, while connecting on some\n  systems (#20265)\n- x.vweb: fix `$vweb.html()` integration in cgen for the newer `x.vweb` module (fix #20204)\n- net: support only ip and ip6 in net.tcp_listener (#20336)\n- x.vweb.assets: reimplement assets module for x.vweb (#20280)\n- x.vweb.sse: reimplement SSE module for x.vweb (#20203)\n- js.dom: add querySelector[All] and NodeList (#20240)\n- vweb: add mime type support for static .md files\n- net.conv: add varinttou64 and u64tovarint functions, for the variable unsigned integer encoding,\n  described in rfc9000 (for QUIC) (#19568)\n- net.http: support passing on_running, on_stopped, on_closed callback functions to http.Server{},\n  as well as show_startup_message: false. (#19591)\n- net: fix handling of spurious wake-up signals, lost when calling select() in mbedtls and openssl (\n  continue on C.EINTR) (#19600)\n- net: use conv.hton* consistently, instead of\n  `$if tinyc { conv.hton16(port) } $else { u16(C.htons(port)) }`\n- net.http: support passing an HTTP proxy server in http.fetch (#19606)\n- net.http: add a retry mechanism to http.fetch(), when the socket inevitably errors (#19660)\n- wasm: implement inline assembly (#19686)\n- net.http: increase max_redirects to 16 (#19743)\n- picoev: implement raw mode (#19771)\n- flag,json,net: handle C calls in .v files (part of enabling `-W impure-v` as default) (#19779)\n- net.http: add socks5|http(s) proxy support [Linux] (#19676)\n- net.http: fix http.fetch(), without explicit method (default again to .get, not to .acl)\n- net.http: default explicitly to Method.get for http.Request and http.FetchConfig too\n- examples: add examples/fetch_ip.v, showing how to contact http://ifconfig.co/json and parse the\n  result\n- net.http: fix post error with https on windows (#19334)\n- net.ssl: implement SSLConn.peer_addr() (#19333)\n- http: Request.host\n- net.ftp: fix dir() for file names, which contain spaces (fix #18800) (#18804)\n- net.http: make listener public, and add addr in Server struct (#18871)\n- net.http.chunked: return `!string` on decode (#18928)\n- net.conv: rename functions to match other langs, making them easier t… (#18937)\n- wasm: remove dependency on thirdparty/binaryen, webassembly backend rewrite (#18120)\n- wasm: add a -wasm-stack-top flag to compiler (#19157)\n- net.mbedtls: add SSLListener to allow creating SSL servers (#19022)\n- picoev, picohttparser: reimplement in V (#18506)\n- vweb: fix parsing of form fields, send with multipart/form-data (by JS fetch)\n- vweb: make vweb route paths case sensitive (#18973)\n- net.mbedtls: have shutdown close accepted connections too (#19164)\n- http: add support for stream connections, and custom .on_redirect, .on_progress, .on_finish\n  callbacks to http.fetch() (#19184)\n- vweb: add a user_agent utility method to the vweb context (#19204)\n- vweb: avoid the controllers having to be defined in specific order (#19182)\n\n#### ORM\n\n- Mark orm_where_in_test.v to be skipped in the sanitize-memory-clang job\n- Fix fkey insert as assigment expr (fix #25568) (#25575)\n- Fix double fkey insert and update (fix #25593) (#25606)\n- Add index attr support (#25604)\n- Fix autofree detection for is_or with block style (fix #25969) (#26089)\n- Allow multiple set() in one update() call (fix #26116) (#26117)\n- Add check for invalid index field name (#26142)\n- Supoprt DISTINCT keyword (#26163)\n- Support lowercase operators `like`, `in`, `not in` etc (fix #25032) (#25035)\n- Fix sub_structs (fix #25104) (#25105)\n- orm: fix default value quote (fix #24052) (#24057)\n- orm: fix type alias not supported in table columns (fix #15478) (#24062)\n- orm: fix gen sql complex where (fix #24136) (#24138)\n- orm: skip orm_complex_where_test.v for `sanitize-memory-clang` too\n- orm: add function call based builder API for dynamic queries (fix #24178) (#24196)\n- orm: set default value for require field if database value is null (fix #24221) (#24222)\n- orm: fix option field with default null value (fix #24222) (#24228)\n- orm: add or_where() method to the builder (fix #24244) (#24250)\n- orm: add IN and NOT IN (#24634)\n- orm: add `in` and `not in` to orm_func (fix #24639) (#24642)\n- breaking,orm: add table attrs; add table/field comment support for mysql and pg (#24744)\n- orm: fix codegen for option fk (fix #23383) (#23400)\n- Fix orm.Connection only allowing immutable Connections (#22684)\n- Fix order by with custom column name (#22813)\n- Support plain `@[serial]` attribute for marking struct fields (#22814)\n- Fix crash when working with array field (fix #22822) (#22824)\n- Fix list generation and escape loose backtick (#23039)\n- Fix mark as used var on insert statement (fix #23032) (#23038)\n- Fix update stmt with enum value (fix #23031) (#23037)\n- orm: fix subquery without where expr (#21598)\n- orm: ilike for case insensitive text search\n- orm: update readme with more specifics (#21697)\n- Add error for unchecked option multi return types, fix undefined behavior (#21106)\n- orm: fix checking invalid recursive structs (fix #20285) (#20491)\n- orm: fix checking invalid recursive structs in sql stmts (fix #20278) (#20505)\n- orm: fix orm insert issue if table missing [Issue : #20017] (#20580)\n- orm: fix orm_option_time_test.v after 2d0ed2c made insert in parent tables with child ones missing\n  fail\n- orm: insert expressions returning id\n- orm: fix code generation for an option time.Time field (#20031)\n- orm: fix the generated SQL for the \"not equal\" operator (#20321)\n- orm: add null handling and option fields (#19379)\n- orm: make is_null/is_not_null unary ops; don't bind null in where (#19635)\n- orm: add `references` attribute to allow foreign key declarations on fields (#19349)\n- orm: support different foreign key types, not just an integer id (#19337)\n- orm: add support for V enum struct fields (#19374)\n- orm: quote table and field name in `[references]` (#19387)\n- orm: fix inserting sequential values (id=0), in tables with an i64 primary field (#18791)\n- Add OR in where on update and delete (#19172)\n\n#### Database drivers\n\n- db.sqlite: fix orm f32 field retrieval for sqlite (fix #25583) (#25592)\n- db.pg: support returning `Result` type with column names (#25737)\n- db.sqlite: allow for\n  `mut db := sqlite.connect_full(\":memory:\", [.readwrite, .create, .fullmutex], \"\")!` defaulting to\n  unix/win32 depending on the platform\n- db.pg: support LISTEN/NOTIFY (implement feature #23983) (#26133)\n- db.pg: fix `v check-md vlib/db/pg/README.md`\n- Revert \"db.sqlite: support calling exec_param_many with [][]string or []string (it now accepts a\n  sumtype of both) (#26100)\"\n- Reapply \"db.sqlite: support calling exec_param_many with [][]string or []string (it now accepts a\n  sumtype of both) (#26100)\"\n- db: modify mysql/pg/sqlite interface for pool working (#24780)\n- db.sqlite: fix get_text trimming data after (including) first 0 character (#25040)\n- db.mysql: use mysql datatype for alloc string_binds_map, not orm's (#24126)\n- db.mysql: fix handling of nullable timestamp (fix #24120) (#24125)\n- db.mysql: add null result support (fix #24130) (#24131)\n- db.mysql: use hardcoded const declare (fix #22086) (#24162)\n- db: connection pool (#24161)\n- db: mysql,pg,sqlite add transaction support (fix #24290) (#24352)\n- db.pg: fix incompatible fn signature (#24549)\n- db: add redis (#24730)\n- db.sqlite: add tracing for more calls, when using `-d trace_sqlite`, not just for the ORM\n- db.pg: add support for prepared statement, with db.prepare/3 and db.exec_prepared/2 (#23442)\n- db.mysql: add SSL support; turn ConnectionFlag into `@[flag]` (#23975)\n- db.sqlite: add instructions for installing SQLite's amalgamation or development package, if it is\n  missing\n- db.mysql: fix invalid memory access in exec_one for returned rows with NULL fields (#21317)\n- db.sqlite: fix exec_param_many bug (#21008)\n- db.mysql: add support for the FreeBSD name of the mariadb client library (#20039)\n- db.pg: fix using postgresql on windows, improve instructions for installing it (#20053)\n- db.mysql: add ability to prepare and execute statements separately (#20146)\n- db.pg: fix compilation error with the msvc compiler on windows, and add readme (#20326)\n- pg: handle C calls, move to .c.v files (#19739)\n- db.pg: allow postgres connection using service definitions (#19288)\n- vlib: remove deprecated `pg`, `mysql`, `sqlite`, `mssql` modules. Leave only the `db.` prefixed\n  `db.pg`, `db.mysql` etc\n- db.mysql: add the exec family of methods (#19132)\n- db.sqlite: add exec_param_many and exec_param methods (#19071)\n- db.sqlite: make functions return results, breaking change (#19093)\n\n#### Native backend\n\n- Fixed array, `-new-transformer` dynamic array (#25817)\n- Add `$if trace_native_todos ? {` to reduce noise in `v test-all`\n- Add comptime cpu archs support (#24956)\n- Add support for (elf) globals  (#25016)\n- Improve consts, support more assigns (#25277)\n- Structs multi_assign and multi_return (#25281)\n- Support more assign ops, reduce code duplication (#25283)\n- Begin array support, `a := []Type{len: x, cap: y}` and `a[i]` read/write (#25299)\n- native: use builtin exit function (#24578)\n- native: improve string support (#24600)\n- native: implement `for in string` for amd64 (#24613)\n- native: support nested structs, improve support for right expr of IndexExpr (#24627)\n- native: leave only the unique paths in g.linker_include_paths, before doing lookups\n- native: support C constants (#24660)\n- native: add a temporary special case for `C.EOF` (#24724)\n- native: fix convert_int_to_string, add comments in the verbose (-v) mode (#23743)\n- native: fix int prints (#23747)\n- native: for statement : add support for all expressions handled by g.condition (#23752)\n- native: fix inc and improve support for i32 (#23753)\n- native: support negative integer literals (#23755)\n- native: fix missing symbols CaptureStackBackTrace and __debugbreak (#23765)\n- native: fibonacci test\n- native: add support for enums of different types (#23786)\n- native: fix unsigned and signed int comparison (#23808)\n- native: support `-no-builtin` (generate executables < 1KB Linux with\n  `v -no-builtin -b native examples/hello_world.v`)\n- native: use i32 instead of int\n- native: make native tests pass on windows; refactor PE file generation (#19140)\n- native: parse dll files to resolve extern symbols (#19433)\n- native: move functions out of amd64.v (#18857)\n\n#### C backend\n\n- Fix resolution type Map[string]T when T is AliasToMap (fix #25494) (#25510)\n- Fix markused for option generic param (fix #25501) (#25525)\n- Fix empty struct initializer for clang (fix #25467) (#25526)\n- Fix match codegen for option match case (fix #25533) (#25537)\n- Fix codegen for alias for array fixed initialization (fix #25512) (#25540)\n- Ensure option none/ok state is also compared (#25532)\n- Fix match codegen for option expr on case (fix #25545) (#25553)\n- Add `-no-closures` option to detect closure usage earlier (for emscripten or for less well\n  supported platforms) (#25565)\n- Create ctemp before lockexpr gen (fix #25576) (#25612)\n- Fix if expr with condition that requires temporary variable (fix #19584) (fix #23903) (#25621)\n- Fix multi return of a fixed array (fix #25626) (#25628)\n- Fix generic multiple indirections on print (fix #22793) (#25633)\n- Fix `fn (d Struct) a[T]() T { return d }` when T is a sumtype (#25644)\n- Minimize code generated for asserts (generate the common parts for the pass/fail case once) (\n  #25642)\n- Handle pointers in json map decode/encode (fix #25632) (#25646)\n- Fix `defer` stmts with `if` exprs and `or` blocks that return a value (#25651)\n- Fix infix expr ComptimeSelector type (fix #25659) (#25662)\n- Fix passing sumtype child to generic function taking sumtype parent (fix #25660) (#25664)\n- Fix multi generics fn name (fix #23886) (#25673)\n- Fix `defer` generation within comptime `$if`/`$match`/`$for` (#25677)\n- Fix codegen for if comptime and array fixed (fix #25691) (#25697)\n- Correct function definitions for callbacks in imported modules (fix #25700) (#25719)\n- Improve codegen for array fixed init for g++ compiler (fix #25723) (#25725)\n- Fix codegen for operator overload method_name on alias to builtin types (fix #25709) (#25726)\n- Fix missing cast if fixed array is surrounded in brackets (fix #25629) (#25741)\n- Fix comptime for types not being recognized with maps correctly (fix #25742) (#25743)\n- Fix dump(ptr_to_fixed_array_value) - it now returns the argument directly (thanks @tankf33der) (\n  #25764)\n- Cast member variables to correct types in comptime $for (fix #25771) (#25773)\n- Include `ast.ComptimeSelector` in fixed array checks (fix #25767) (#25777)\n- Checker,cgen,type_resolver: prevent stale type cast on comptime `$for`, handle in dumpexpr (fix\n  #25781) (#25784)\n- Reduce the nested expr level complexity of Gen.ident\n- Fix tcc __attribute__, fix os.notify (followup to #25779) (#25804)\n- Ensure array of string is not cloned with depth 0 (fix #25783) (#25793)\n- Support `-d trace_check` and `-d trace_cgen` to help diagnose checker and cgen ordering issues\n- Support `-d trace_cgen_fn_decl` and `-d trace_cgen_gen_fn_decl` too\n- Show the v_gettid() hex with `-d trace_cgen_fn_decl` and `-d trace_cgen_gen_fn_decl`\n- Use variadic_count == 1 when passing variadic to call of same array type (fix #25827) (#25837)\n- Fix nested or in assign decl (fix #25864) (#25865)\n- Fix variadic on translated (fix #25862) (#25876)\n- Allow @[cinit] for const variables (#25881)\n- Fallback to field type when default_expr_typ is 0 (fix #25891) (#25903)\n- Fix map value init with array fixed const (fix #25887) (#25902)\n- Fix cast type changed before last stmt in `stmts_with_tmp_var` (#25915)\n- Update wyhash to version 4.2 (#25907)\n- Use final_sym for elem_sym in index_of_array (fix #25960) (#25961)\n- Fix variadic call on sumtype with array of itself (fix #25898) (#25964)\n- Correct T{} init for []Type aliases (fix #25962) (#25963)\n- Fix array init with fixed array from return call (fix #25954) (#25971)\n- Fix fntype unwrap on ifguard (fix #25911) (#25914)\n- Add a source .location field to `$for method in Type.methods {` (#25976)\n- Fix iterator on alias to fn ptr (fix #25911) (#25978)\n- Fix shared int string intp (fix #25984) (#25989)\n- Allow init shared field with default value (fix #25990) (#25991)\n- Allow init of struct from struct with array of optional values (fix #26000) (#26005)\n- Fix default value in if/else or block (fix #26002) (#26020)\n- Fix fnptr indirections declaration (fix #25940) (#25987)\n- Fix bool cast from value (fix #26028) (#26031)\n- Fix cast() generic type bug (fix #26065) (#26066)\n- Fix fn_var_signature() support nr_muls (fix #26049) (#26075)\n- Fix cast_expr() for alias (fix #26076) (#26079)\n- Handle CallExpr in dumpexpr (fix #26084) (#26087)\n- Clean code in return stmt (fix #25968) (#26118)\n- Fix cast to array (fix #26099) (#26102)\n- Fix fn_var_signature() allow option type (fix #26088) (#26120)\n- Fix scoped struct array fixed generation (fix #26111) (#26114)\n- Fix option array init with non option values (fix #26148) (#26170)\n- Fix heap fixed array assign (fix #26149) (#26169)\n- Fix stack overflow for `@[heap]` structs with large fixed arrays (fix #22690) (#26183)\n- Fix print interface when arg0 is function call (fix #26184) (#26188)\n- Checker,table,cgen: fix generic interface confusion (fix #25478) (#26181)\n- Only run freestanding_module_import on amd64 (#24763)\n- Fix sumtype option unwrapping (fix #24746) (#24770)\n- Protect against unlimited recursion in type_default_impl, by converting to a verror/1 call instead\n- Fix `static` and `volatile` var deref (fix #24778) (fix #24779) (#24807)\n- Fix codegen for interface method closure get (fix #24810) (#24818)\n- Fix codegen for multi return assignment with option type (fix #24812) (#24817)\n- Fix if codegen when func parameter is option type (fix #24813) (#24816)\n- Skip `struct none {` in cgen, if `none` is not used by V code reachable from `fn main() {` (\n  #24824)\n- Skip `struct map {` and related type declarations, when no V maps are used (#24826)\n- Fix anon struct encode (fix #24836) (#24852)\n- Fix json decode option alias (fix #24843) (#24853)\n- Fix const indexexpr dep (fix #24850) (#24851)\n- Fix codegen for generic interface with multi return generic type (fix #24838) (#24858)\n- Fix anon struct init passing (fix #24879) (#24884)\n- Allow alias to map `type Dict = map[string]string` (fix #24878) (#24883)\n- Builtin,cgen,markused: add struct @[aligned] support for structs allocated on the heap too (\n  #24886)\n- Add a `__closure_init` call for sokol/gg programs on android as well (#24892)\n- Allow alias types to be iterated if parent type has `next` method (fix #24890) (#24894)\n- Use alias `next` method if defined in `for x in iterator {` (#24905)\n- Fix const fixed array with type alias (fix #24936) (#24946)\n- Fix callback codegen on generic struct resolution (fix #24947) (#24948)\n- Move sort fn after interface definitions(fix #24465) (#24967)\n- Fix struct field init within fn without result type (fix #24970) (#24973)\n- Move closure C code to V code under vlib/builtin/closure/ (#24912)\n- Parser,ast,checker,cgen: use enum comparisons instead of string ones on\n  ast.ComptimeCall.method_name (#25003)\n- Fix generic key's type with `in` operation (fix #24983) (#25011)\n- Remove unused enum declarations too (#25033)\n- Parser,checker,cgen: remove unused `err` declaration or `or { }` blocks (#25034)\n- Add a test for builtin_init being present (part 2 of 4a6941a)\n- Fix closures on s390x, ppc64le, loongarch64 platforms, add test to s390x CI (#25047)\n- Fix anon fn checking adding unresolved generic type on codegen (fix #25050) (#25055)\n- Fix building on Termux after fa904c4\n- Use `#if defined __BIONIC_AVAILABILITY_GUARD && ...` to be compatible with more Termux versions\n- Fix asm stmt separators (#25067)\n- Fix translated file fixed-array assignment (#25080)\n- Fix codegen for passing int from selector to voidptr expect arg (fix #25081) (#25083)\n- Fix codegen for option void fn return block unwrap (fix #25074) (#25082)\n- Fix alias to sumtype cast initialization (fix #25086) (#25091)\n- Allow alias sumtype smartcasting (fix #25085) (#25096)\n- Fix codegen for generic struct field array option (fix #25093) (#25097)\n- Fix mutable sumtype (fix #25108) (#25111)\n- Fix generic return assign to ComptimeSelector (fix #25125) (#25131)\n- Fix address of call with `cast(&(arr.last() as Type))` (fix #23528) (#25132)\n- Fix eq for anon C structs (#25152)\n- Fix generated str method for enums that have C values (use ifs, instead of switch) (fix #25135) (\n  #25157)\n- Fix autofree with option array (fix #25124) (#25149)\n- Fix assigning fn address (fix #24537) (#25158)\n- Fix veb alias type identification and generic CastExpr (fix #24895) (#25155)\n- Revert \"checker,cgen: evaluate comptime `$if` results in checker *only* (fix #25123) (fix\n  #25156) (#25150)\"\n- Evaluate comptime if results in checker only (with fixed -cross compilation) (#25162)\n- Fix generic_fn_name generating incorrect names for C structs (#25164)\n- Add comptime match support (#25165)\n- Fix resolving generic interface field from generic struct (fix #23556) (#25182)\n- Fix autofree used vars on return (fix #25196) (#25198)\n- Fix hash stmt code generation (fix #25184) (#25207)\n- Expose is_embed in FieldData (#25232)\n- Fix alias enum used in comptime `$for` (fix #25211) (#25212)\n- Ensure variable names do not conflict with builtin methods (fix #25063) (#25178)\"\n- Add `@[reused]` attribute to mark methods, reusing the receiver memory on return (needed for\n  autofree) (fix #25221) (#25235)\n- Fix gen_struct_equality_fn null pointer crash (fix #25237) (#25231)\n- Allow generic alias enum comptime (fix #25249) (#25251)\n- Fix big IntegerLiteral LL postfix (fix #25269) (#25275)\n- Prefix `builtin` APIs with `builtin__` (#25264)\n- Fix fixed-array const initializer (fix #25291) (#25293)\n- Fix generic cast to sumtype of empty struct (fix #25263) (#25290)\n- Fix option variadic arg passing (fix #25261) (#25273)\n- Support for 64bit int 1 (#25236)\n- Cgen,parser,markused: add export const support (fix #25300) (#25303)\n- Fix i64 enum as a map key, when the enum values are too small (fix #25294) (#25310)\n- Fix parallel cached_type_to_str access (fix #23980) (#23998)\n- Fix codegen to make mutable sumtype working (fix #23982, part 1, needed for bootstrapping) (\n  #23988)\n- Fix arm64 asm operand position; fix arm64 asm imm; support arm64 dot instruction (#24017)\n- Fix mutable ptr sumtype  (#24021)\n- Fix asm comments of arm32 (#24025)\n- Allow asserts inside fns, called in const/global initialization, in test files (fix #24029) (\n  #24031)\n- Fix codegen for option return unwrapping on last statement (fix #24026) (#24030)\n- Fix match option with case non option (fix #24047) (fix #24048) (#24051)\n- Support measuring programs, that use multiple threads in the new profiler column (turn\n  `prof_measured_time` into a thread local, for the supported C compilers) (#24061)\n- Fix `@[keep_args_alive]` with ptr (fix #23973) (#24058)\n- Remove unused macro V64_PRINTFORMAT\n- Fix option array push on unwrapped array (fix #24073) (#24079)\n- Fix nested array support for the orm (fix #19327) (#24080)\n- Fix `x in [...]!` operator with fixed arrays (fix #24082) (#24083)\n- Fix codegen for comptime multiline attr (fix #23964) (#24087)\n- Fix codegen for selector with embed field option (fix #24084) (#24085)\n- Fix generic result return (fix #24097) (#24100)\n- Fix showing the expression, as literal value, in case of `assert s[x..y] == \"literal\"` (fix\n  #24103) (#24105)\n- Fix codegen for option unwrapped var passed to generic option type (fix #23972) (#24096)\n- Fix selector option unwrapping on infix (fix #24108) (#24115)\n- Sort the paths, used in coutput_test.v\n- Skip emitting mman.h and pthreads related code, for freestanding builds (#24118)\n- Add s390x assembly support + test (#24129)\n- Parser,checker,cgen: fix wrong auto heap deref of auto `index` loop var (fix #24117) (#24124)\n- Fix non-voidptr to voidptr on `-cstrict` + notice about such usage (fix #24139) (#24143)\n- Fix multi return with option type (#24144)\n- Remove obfuscation (`strip` should be used instead); temporary fix for usecache + toml\n- Fix zero left padding (fix #24199) (#24201)\n- Fix variadic sumtype args passing (fix #24150) (#24207)\n- Fix codegen for const to c string (fix #24235) (#24248)\n- Fix codegen for fixed array init with init using structinit (#24269)\n- Fix missing braces for const init with castexpr from option unwrapping expr (#24276)\n- Fix codegen for index expr on for loop with branchstmt (fix #22760) (#24289)\n- Fix codegen for assigning fixed array on defer var (fix #24300) (#24305)\n- Fix codegen for multi return with aliased fixed array (fix #24280) (#24295)\n- Fix codegen for nested selector unwrapping on lhs (fix #24292) (#24293)\n- Add ppc64le assembly support + test (#24299)\n- Fix s390x closure thunk (use floating point register) (#24258)\n- Fix riscv64 closure thunk (use floating point register) (#24315)\n- Fix codegen for writing on unwrapped selector (fix #24316) (#24323)\n- Fix codegen for thread.call() on var auto heap (fix #24326) (#24327)\n- Fix codegen for handling multiple return result type on call (fix #24341) (#24344)\n- Fix codegen for nested selector option ptr (fix #24339) (#24345)\n- Fix arm64 closure + remove stub in test (#24332)\n- Workaround tcc aarch64 bug (fix #24331) (#24354)\n- Fix riscv32 closure (#24355)\n- Fix codegen for anon option fn struct field init (fix #24392) (#24400)\n- Fix `if mut var != none {` for optional interface values (fix #24351) (#24410)\n- Fix interface `unsafe {nil}` comparison and initialization (fix #24374) (#24411)\n- Ast,cgen,parser,pref: support loongarch64 inline assembly, add test (#24440)\n- Fix array init with interface element type (fix #24442) (#24454)\n- Fix const declaration dependant mapping when using update_expr (fix #24437) (#24455)\n- Fix comptimecall with map receiver (fix #24448) (#24449)\n- Fix assign from `for mut var in arr {` to pointer (fix #24432) (#24456)\n- Workaround tcc aarch64 fn call bug (fix #24473) (#24477)\n- Workaround tcc aarch64 spawn call bug (fix #24482) (#24483)\n- Fix map of fixed array value in if guard (fix #24488) (#24496)\n- Fix codegen for assigning `nil` or `0` to option ptr field (fix #24447) (fix #24500) (#24502)\n- Fix codegen for array of option element auto eq `a == [?int(none)]` (#24504)\n- Fix codegen inconsistency handling `nil` param to arg expecting ptr (fix #24491) (#24503)\n- Fix pattern generated by `const_init_or_block.vv` in `vlib/v/gen/c/coutput_test.v`, when\n  VFLAGS=-no-parallel is used\n- Fix tmp var redeclaration on const inited later (fix #24521) (fix #24517) (#24524)\n- Fix generic name handling for struct generic (fix #24530) (#24565)\n- Fix initialize error object in or_block (fix #24529) (#24576)\n- Improve the readability of `switch() {` statements, generated by `match() {` ones (#24618)\n- Reduce v.c size by ~4% by removing comments and using shorter literals\n- Fix enumval str() call on stringinterliteral (fix #24702) (#24705)\n- Fix type_default for option type, when the default expr is `none` (fix #23318) (#23320)\n- Remove double string cloning (#23331)\n- Fix type_default for array init >= 8 items (spotted while building the vhamll project) (#23334)\n- Fix codegen for alias struct embed (fix #23347) (#23353)\n- Fix codegen for sumtype casting on selector on as cast with non pointer field (fix #23387) (\n  #23391)\n- Fix generic alias option assigning (fix #23382) (#23393)\n- Fix codegen for selector on shared var with embed (fix #23378) (#23394)\n- Fix codegen for nested selectorexpr on unwrapped option (fix #23406) (#23409)\n- Cache return_stmt()'s node.exprs[0] and node.types[0] (#23408)\n- Fix codegen for indexing generic map (fix #23376) (#23402)\n- Support `-d trace_unused_by_main` and `-d trace_skip_unused_just_unused_fns`, to find out\n  potentially obsolete functions that are not used at all in a project\n- Fix shared array indexing (fix #23410) (#23413)\n- Fix shared array fixed initializing with `-cstrict` (fix build of chip8-v project) (#23414)\n- Fix codegen for array fixed comparison on MatchExpr (fix #23403) (#23415)\n- Fix struct init for anon struct field on C structs (fix #23421) (#23422)\n- Fix shared array slice (fix #23426) (#23427)\n- Fix array of sumtype initialization with var string (fix #23429) (#23432)\n- Fix codegen for ifguard indexing array of option (fix #23438) (#23439)\n- Fix assigning option of array index (fix #23451) (#23455)\n- Fix compilation for a project using a lot of json, threads, embeds + parallel-cc (#23467)\n- Fix cgen error for `instance.t.wait()` on default 0 initialized thread field `t` (fix #23390)\n  #23392\n- Fix array decomposing on variadic call (found while working on solving #23474) (#23476)\n- Fix option var nested unwrapping from sumtype (fix #23478) (#23485)\n- Fix option unwrapping on heap var (#23489)\n- Fix codegen for indexing anon_fn (fix #23493) (#23495)\n- Fix nested option selector unwrapping (fix #23500) (#23497)\n- Fix interface casting in anon fn (fix #23530) (#23533)\n- Fix codegen for spawn with interface on submodule (fix #23471) (#23517)\n- Parser,ast,cgen: support nested unions with `field union {`, to improve interoperability with C (\n  similar to `field struct {`) (#23539)\n- Fix unwrapping option interface field (fix #23540) (#23541)\n- Fix codegen for assign from unsafe fn returning fixed array (fix #23546) (#23548)\n- Fix codegen for a fixed array init with different node types (fix #23545) (#23547)\n- Fix return on last statement of return IfExpr (fix #23550) (#23551)\n- Fix auto str which expects ptr for ptr type (fix #23552) (#23553)\n- Fix codegen for assigning from infixexpr with generic operand (fix #23560) (#23561)\n- Fix codegen for array's .grow_cap and .grow_len methods for generic arrays (fix #23566) (#23568)\n- Fix codegen for const fixed array initialization with another const as item (fix #23565) (#23572)\n- Fix codegen for unwrapping option comptime var (fix #23590) (#23591)\n- Fix hash functions for `map[Enum]Value`, and `enum Enum as u64 {` (fix #23630) (#23632)\n- Fix unwrap option ptr selector (fix #23631) (#23638)\n- Fix codegen for `for` or-block (fix #23625) (#23644)\n- Fix codegen for option value on `map_set` (fix #23650) (#23652)\n- Fix codegen for option sumtype with option variant (fix #23653) (#23656)\n- Remove commented code blocks using `if true {`\n- Reduce interpolations when a method is not found in Table.find_method/2; merge rand.constants back\n  to rand.v (#23660)\n- Fix `$if typeof[T]().idx`, `$if typeof[T]().unaliased_typ` checking (#23665)\n- Fix codegen for sumtype cast from option variants on map_set (fix #23654) (#23669)\n- Fix codegen for a const assigned a fixed array, initialized with unsafe exprs (fix #23674) (\n  #23676)\n- Fix `@[sql: serial]` and `@[serial]` are not the same (fix #23346) (#23678)\n- Improve support for `v -path bootstrap_alternative_backend/ run simple.v` (#23679)\n- Fix codegen for array fixed on if and match expr (fix #23577, fix #23589) (#23682)\n- Add support for a `#postinclude` directive\n- Fix #preinclude, add test case for #postinclude too\n- Fix codegen for returning an initialised fixed array (fix #23693) (#23700)\n- Use `global_g.out << g.out` instead of `global_g.out.write(g.out) or { panic(err) }`\n- Fix issues found with the stricter sanitizers in clang-18 on Ubuntu 24.04 (#23710)\n- Fix codegen for nested if on return (fix #23723) (#23729)\n- Fix sumtype smartcasted var as inherited var (fix #23716) (#23731)\n- Fix map with an Enum as key type, with size < 4 bytes on tcc (fix #23714) (#23738)\n- Fix codegen for match with sumtype ptrptr (fix #23776) (#23785)\n- Fix aggregate var handling on match branch (fix #23768) (#23787)\n- Fix gowrapper codegen for receiver ptrptr (fix #23798) (#23800)\n- Fix regression, preventing the use of `-gc none -d no_main -no-builtin -no-preludes` to compile C\n  style V programs\n- Fix array fixed assignment for `@[keep_args_alive]` (partial fix for #23804) (#23805)\n- Fix nested option fixed array (fix #23708) (#23845)\n- Fix codegen for match on return (fix #23661) (#23851)\n- Fix casting primitive type to alias, where option alias is expected (fix #23859) (#23860)\n- Fix interface method list ordering to make test buildable with `g++` (fix #23701) (#23870)\n- Make `./v -prod -cstrict -cc gcc-11 test vlib/math/` pass cleanly (workaround a problem in V's\n  cgen, that -cstrict discovered)\n- Fix codegen for global array passed as mut (fix #23873) (#23881)\n- Fix msvc build filename, remove temp files (#23890)\n- Improve the stability of generated code for auto string methods\n- Fix codegen for array of anon struct (fix #23896) (#23907)\n- Make sure to call the overridden `pub fn (mut a []string) free() {` method, NOT the generic\n  `fn (a &array) free() {` one. (#23911)\n- Fix generic container init (fix #23910) (#23912)\n- Fix codegen for generic structinit and generic array return (fix #23916) (#23943)\n- Implement alias operator overloading for generic struct parent type (fix #23965) (#23967)\n- Add `T.key_type`, `typeof(expr).key_type`, `T.value_type`, `typeof(expr).value_type`,\n  `T.element_type`, `typeof(expr).element_type` for getting `Map[K]V` and `[]T` types (fix #23914) (\n  #23962)\n- Builtin,markused,pref,cgen: improve markused for small programs\n- Fix codegen for fixed array contains - `[1,2]! in a` (fix #22559) (#22579)\n- Improve fixed array literal in operation and index calls (#22590)\n- Add codegen for auto free methods for interface type (#22555)\n- Add test for #22586 (#22600)\n- Parser,ast,cgen: do is_builtin sym marking during parse time just *once*, to save multiple checks\n  later (#22580)\n- Cache the results of g.base_type/1 (#22613)\n- Add caching to contains_ptr return (#22605)\n- Add .write2/2 and .writeln2/2 methods to reduce consecutive write calls (#22610)\n- Optimise the generated code for returning literal values and option/result values (#22622)\n- Optimize literal string comparison (string__eq -> vmemcmp) (#22614)\n- Fix selector indexexpr with fntype on assignment (fix #22635) (#22637)\n- Fix anon fn with `&` prefix (fix #22628) (#22638)\n- Fix struct field init with fixed array using index (fix #22616) (#22641)\n- Fix interface conversion codegen race issue (fix #22640, #17943) (#22655)\n- Fix waiter funcs declarations (fix #22640) (#22649)\n- Improve the assert informations (fix #22666) (#22668)\n- Fix dump of alias to option fn type (fix #22670) (#22676)\n- Fix array append map value with or expr (fix #22674) (#22678)\n- Ensure proper saving/restoring of cgen `map[k] := fn ()` state, when assigning anonymous fns (fix\n  #22705) (#22707)\n- Implement methods sort_with_compare()/sorted_with_compare() for fixed arrays (#22702)\n- Implement methods reverse()/reverse_in_place() for fixed arrays (#22712)\n- Fix ptr field encoding for `json` (fix #22717) (#22720)\n- Fix `[1, 2, 3]!.map(it * 2)` (#22722)\n- Fix `assert [1, 2, 3]!.contains(2)` (#22725)\n- Fix `assert [1, 2, 3]!.index(2) == 1` (#22727)\n- Fix spawn with non-pointer receiver (fix #22718) (#22719)\n- Fix `assert [1, 2, 3]!.reverse() == [3, 2, 1]!` (#22745)\n- Fix codegen for `-no-builtin` flag (when used separately from `-d no_main`) (#22765)\n- Apply the `a in [x,y,z]` optimisation for `ast.IndexExpr` and `ast.SelectorExpr` again (#22767)\n- Fix codegen to emit callexpr one time for `in` expr optimization (#22764)\n- Fix c codegen formatting for return match (#22768)\n- Avoid generation of empty `or` blocks for `f() or {}` (#22775)\n- Fix struct field name using c keyword `typeof` (fix #22779) (#22782)\n- Remove unused code generated for unwrapping temp var from callexpr (detect unused return value\n  from CallExpr), fix parser bugs (#22769)\n- Enable if guard to add `err` var on else branch, after last `else if` (fix #22784) (#22786)\n- Fix option struct default value init with `-cstrict` (spotted in #22783) (#22802)\n- Fix codegen for fn fixed array param w/ size defined by const (fix #22811) (#22812)\n- Fix wrong type resolution on infix (#22804)\n- Fix default `T{}` when `T` is ref type + dereferencing issue when comparing int alias to int (fix\n  #22795) (#22807)\n- Fix generation of a missing return in `return if cond { x } else { return missing }` (fix\n  #22838) (#22839)\n- Fix generic static method call return type resolution (#22865)\n- Fix array fixed code generation for more than 1 dimension (fix #22866) (#22876)\n- Fix codegen for `$if` in an if expression, when compiled with `-g` (fix #22873) (#22888)\n- Make errors more informative (resolve empty panics) (related: #21184) (#22898)\n- Generate json array line on uniform indent lvl (#22899)\n- Fix codegen for returning a fixed array as a result (fix #22894) (#22896)\n- Fix codegen for alias type interface methods (fix #22901) (#22902)\n- Fix codegen for assigning aliased fixed array (fix #22907) (#22909)\n- Fix codegen for returning option aliased fixed array (fix #22910, fix #22911) (#22912)\n- Fix aliases of fixed array infix expression (fix #22925) (#22928)\n- Fix aliases of fixed array append to array (fix #22926) (#22929)\n- Fix option unwrap for fields of interface type (fixes #22930) (#22931)\n- Fix aliased fixed array option fn call (fix #22927) (#22934)\n- Move the `msvc compiler does not support inline assembly` to cgen (so it will only get triggered,\n  when ASM blocks are still present, in what is passed to cgen)\n- Fix dump fixed array on array append (fix #22935) (#22940)\n- Fix enum value string interpolation, like its declared enum underlying type (fix #22938) (#22945)\n- Allow unwrapping of `x as string` expr, when `x` is a `?string` value (#22953)\n- Fix codegen for result/option propagation out of fn context (fix #22961) (#22963)\n- Fix codegen for option on concatexpr (fix #22951) (#22964)\n- Reduce code for returning and extra whitespaces on `return` (#22967)\n- Allow unwrapping of `foo.bar as string`, where `foo.bar` is `?string` (fix #22960) (#22973)\n- Add thread timing stats too, on `-show-timings -stats` (#22990)\n- Patch missing `gettid()` on glibc < 2.30 (#22987)\n- Fix array fixed on update expr and alias type to multi dimension of fixed array (fix #22971) (\n  #22972)\n- Fix sumtype with embedded struct of option field (fix #22984) (#22996)\n- Fix autostr for interface with circular type (fix #23022) (#23026)\n- Fix array.delete_many() codegen (fix #23024) (#23025)\n- Fix callexpr or-expr codegen on const decl (fix #23029) (#23043)\n- Fix struct update embed expr for fixed arrays (fix #22999) (#23040)\n- Fix update expr with embed fixed array with multiple dimensions (fix #23048) (#23049)\n- Fix cast interface value in match expr (#23068)\n- Prevent too long lines in array initialisations (#23074)\n- Fix smartcast codegen for msvc (#23084)\n- Fix option codegen for accept IError value (fix #23076) (#23085)\n- Fixed for in loop with generic fixed array (fix #23075) (#23101)\n- Fix printing fn call of returning c struct value (fix #23104) (#23106)\n- Fix array fixed comparison from fn return (fix #23071) (#23114)\n- Fix array map to fixed array (fix #23116) (#23118)\n- Fix codegen for returning different option alias type (fix #23087) (#23125)\n- Fix for in for interface type (fix #23119) (#23127)\n- Fix codegen for generic selector expr (fix #22974) (#23132)\n- Fix different option alias type as fn arg (fix #23086) (#23131)\n- Fix codegen for returning option reference from indexexpr (fix #23133) (#23139)\n- Fix array fixed auto str on `-cstrict` (#23144)\n- Fix codegen for array append on indexexpr (fix #23156) (#23160)\n- Fix assert for alias to fixed array (fix #23149) (#23161)\"\n- Fix auto eq for fixed array (fix #23149) (#23169)\n- Fix fixed array option cast with `none` (fix #23164) (#23168)\n- Fix selector call with reserved c name (fix #23170) (#23175)\n- Parser,checker,cgen,fmt: fix array fixed option initialization (`none`) (complete #23164) (#23176)\n- Fix option fn with voidptr arg (fix #23170 for !=tcc too) (#23179)\n- Fix missing validation for selector unwrapping + fix default `return none` for unwrapping (#23183)\n- Fix assign optional aliases of fixed array (fix #23185) (#23188)\n- Fix struct field init with optional fixed array (fix #23193, fix #23195) (#23199)\n- Reduce RAM usage, by avoiding a .str() call, for the final string builder, containing the final C\n  program, used to write it to a file (#23226)\n- Fix struct ref field with no ref structinit (#21932)\n- Define a flexible vint_t type (32 bit int on 32 bit systems, 64 bit otherwise)\n- Fix generic sumtype with repeated concrete type (#21948)\n- Fix array.map with closure var fn (#22002)\n- Fix generation of closures from methods on aliases (#22004)\n- Reduce indentation level for generated defer statements\n- Fix selector with interface var (#22006)\n- Fix free method generation for option struct (#22060)\n- Fix fixed array with default init (#22059)\n- Fix for loop with array fixed returned from fn (#22069)\n- Fix free method for option fields (#22070)\n- Fix auto free method for option map (fix #22081) (#22094)\n- Return early from autofree related functions, when -autofree is not used\n- Fix shared object method call (fix #22121) (#22125)\n- Fix array fixed initialization from map indexing (fix #22133) (#22149)\n- Fix generic options with reserved ident (#22164)\n- Fix struct field with default optional value (fix #11119) (#22167)\n- Fix array of fns index call with embeded array index (fix #17381) (#22198)\n- Fix match with mut cond variable (#22207)\n- Fix code generated for indexexpr with complex assigning (#22203)\n- Fix interface type generation for generic struct (fix #22186) (#22189)\n- Fix wrong type of vint_t and const riscv64 (#22251)\n- Fix code for C ident when ptr is expected (#22259)\n- Fix C name mangling with inherited closure vars (fix #22262) (#22263)\n- Fix codegen for alias to charptr passed as ptr (fix #9679) (#22271)\n- Fix codegen for option fntype used in a match (fix #22278) (#22280)\n- Fix option cast from fntype (fix #22283, #22284) (#22285)\n- Fix codegen for method call on rangeexpr (fix #12610) (#22291)\n- Fix operation overload for type aliases of fixed arrays (fix #22297) (#22304)\n- Fix codegen for assign from unsafeexpr resulting fixed array (fix #22301) (#22309)\n- Fix variadic arg var passed to another call which expects variadic (fix #22315) (#22317)\n- Fix aliases of array insert(...)/prepend(...) (fix #22323) (#22324)\n- Fix codegen for interface method call which returns a fixed array (fix #22326) (#22331)\n- Add `asm` to c_reserved, fixes compilation of `struct Abc { @asm int }` (#22340)\n- Fix interface method call after smartcast (fix #17056) (#22335)\n- Fix codegen for address of range (fix #18528) (#22336)\n- Fix printing of floating point values in asserts (#21538)\n- Fix array fixed initialization on struct from call (#21568)\n- Put the `Interface(unsafe{nil})` change for now behind -experimental (#21593)\n- Fix indexexpr with orexpr (fix #21591) (#21592)\n- Fix generic struct init when it is a reference &T (fix #21594) (#21596)\n- Fix generated code for handling fn call with result/option return on match conditional (#21608)\n- Fix missing call to a function returning option, when called inside a print (fix #21616) (#21623)\n- Support a `-d no_bool` option, for cgen compatibility with the C23 language standard (since `bool`\n  is a builtin type and a keyword in it) (#21637)\n- Fix or expr with non option fn call return (fix #21660) (#21661)\n- Generate pragmas for gcc-14, to make it more relaxed by default. Support `-no-relaxed-gcc14` for\n  turning them off. (#21680)\n- Fix spawn code generated when calling conditional function (fix #19352) (#21681)\n- Fix comptime generic arg resolution (allow several different struct fields in generic functions\n  using comptime) (fix #18110) (#21682)\n- Fix dumping array of reference (#21694)\n- Implement g.trace_last_lines/2 to help debugging cgen problems\n- Support inc cond for c style for loop with alias types  (#21708)\n- Fix fn call with mut reference args (fix #21265) (#21719)\n- Fix auto dereference mut variable in if expr (fix #21309) (#21720)\n- Fix smartcasting a reference to a sumtype value (#21730)\n- Fix assert checking fn option ret with `none` (#21726)\n- Fix generics map with the reference argument (#21737)\n- Fix shortcircuiting of infix and/or expressions (#21740)\n- Simplify in infix_expr_and_or_op() (#21745)\n- Fix reference variable str() method call (#21753)\n- Fix scope command when `$dbg` breakpoint is on or-expr (fix #21772) (#21747)\n- Fix array fixed empty struct code generated on clang (fix #21761) (#21764)\n- Allow alias to array fixed to be initialized like `[n]int{}` (#21785)\n- Fix comptime call argument auto conversion for indexexpr (fix #15232) (#21796)\n- Fix const name without main prefix in `-translated` mode (#21789)\n- Fix closure variable with optional reference params (fix #21827) (#21829)\n- Fix auto str for fn struct member (#21825)\n- Fix option string struct member init with autofree (#21859)\n- Fix fn mut argument of sumtype reference (#21874)\n- Fix generic type init syntax for primitive types  (#21872)\n- Fix missing `&` in string representation of `map[X]&Y` (#21890)\n- Fix optional closure direct call (#21892)\n- Fix wrong missing unsafe block checking when calling generic functions with @[unsafe] attr (\n  #21898)\n- Fix typeof(var.typ) with comptime $for variables (#21901)\n- Fix enum with const value (#21919)\n- Fix generic option/result reference return (#21922)\n- Enable autofree for option (#21051)\n- Force C struct types which does not implement str() to be passed as ptr (#21054)\n- Improve diagnostic information for ORM queries with invalid types\n- Allow static call on generic type (#21071)\n- Fix code generation for a struct field, having a type of fixed array of options `field [5]?Type` (\n  #21082)\n- Add the `_M_ARM64` macro to endianness check (#21109)\n- Fix return code when returning interface result type (fix #21115) (#21130)\n- Fix const initialized with array (#21131)\n- Fix infix array heap comparison (#21145)\n- Fix C struct sumtype support (#21129)\n- Add `autofree` comptime check (#21197)\n- Fix comptime `$if !autofree {` (#21218)\n- Allow `for mut v in [12, 13, 14] { v+= 2 }`  (#21237)\n- Allow op overload for type with generic parent  (#21262)\n- Optimize .map(), .any(), .filter() and .all() when using closure (#21256)\n- Fix `none` passed to a generic option cast expression (fix #21215) (#21276)\n- Fix `-fsanitize=undefined` used with `[]int{}.sort()` (#21331)\n- Fix `myarr [1]C.mytype` fixed array fields, for `pub type C.mytype = voidptr` (#21266)\n- Fix comptime ref argument passing (#21335)\n- Use the real C line number instead of `#line 1000000 ...` in the C footer with `-g` (#21388)\n- Fine tune the line count reset for the C footer (fix off by 1 error in 00dd0bf)\n- Fix array.delete_last call generation (#21439)\n- Fix option ptr unwrapping (#21415)\n- Fix C struct option alias printing (#21496)\n- Handle auto deref var for index when the array element is an interface or a sumtype (#21491)\n- Fix C struct init when it has default expr (#21510)\n- Fix sumtype field naming (when they are the same as a C keyword) (#21527)\n- Fix multidimensional fixed array size expression evaluation (fix #20311) (#20458)\n- Fix fixed array handling with operator overloading call (fix #20467) (#20469)\n- Fix C code, generated for generic option fixed array return type (fix #20465) (#20479)\n- Fix fixed array handling, on generic result return, and on or block (#20492)\n- Fix generated code for fixed array cast (fix #20454) (#20480)\n- Change `x.filter(cond).len > 0` to `x.any(cond)`, and `x.filter(cond) == 0` to `x.all(!cond)` (\n  #20513)\n- Fix code generation wrong, when '?foo.array or {}' as a 'for-in' condition (fix #20528) (#20542)\n- Add a necessary clone, when the closure param is string/array with -autofree (fix #20498) (#20557)\n- Fix wrong cgen, when auto_heap var, is used as a closed over arg in a closure (fix #20208) (\n  #20566)\n- Initialize closures in shared library mode (#20630)\n- Fix interface generic smartcast (#20609)\n- Support inter-dependent function types (#20638)\n- Write the profile file out, even upon CTRL-C or kill (#20677)\n- Fix as cast as selector (fix #20710) (#20718)\n- Fix method call checking against `none` (fix #20711) (#20717)\n- Fix interface on multi return func (fix #20720) (#20721)\n- Fix premature variable release by autofree (#20731)\n- Fix return with option on orexpr (#20728)\n- Fix auto str for map with ptr str (#20741)\n- Remove `ull` suffix, which looks like the cause for the first scanner error in PR#20726 (#20750)\n- Fix comptime smartcast as receiver on method call (#20749)\n- Fix unwrap on or-expr, when calling f() ?Type (fix #20756) (#20758)\n- Builtin,coroutines,cgen: fix using coroutines with boehm GC, by using a stack pointer corrector (\n  #20771)\n- Fix interface casting (#20789)\n- Fix auto_eq for option eq operator overload (#20795)\n- Fix from_string fn generation missing mod name (#20807)\n- Fix const fixed array initialization handling (#20812)\n- Fix unwrapped option selector assigning (#20816)\n- Fix map methods call with generic types (fix #20827) (#20829)\n- Fix codegen for a.index/1, where a is []Fn (#20849)\n- Fix thread return type generation (fix #20836) (#20850)\n- Fix code generated for anon struct default value (fix #20839) (#20851)\n- Fix comptime selector of interface (#20876)\n- Fix multiple fixed array variable init (fix #20895) (#20902)\n- Ast,checker,cgen: fix generics function with embedded structs, ensure correct link generation in\n  cgen (#20900)\n- Fix returning option call in non-option fn (#20943)\n- Fix global initializer of fixed array on gcc (#20934)\n- Fix comptime `is` condition when using interface (#20952)\n- Fix const fixed array init with index (#20950)\n- Fix generic map inferring key and value types (#20959)\n- Fix missing scope enclosing for const init which needs temp variables (#20973)\n- Fix fixed array return on fn with option generic return (#20974)\n- Fix code generated to comptime passed to generic arg (#20994)\n- Fix match for alias  (#21028)\n- Add ability to mark a global as `@[hidden]` (#21035)\n- Fix _str name generated for C struct which define str() method (#21042)\n- Fix for/in codegen when iterating over C structs (#21052)\n- Fix generic fn returning fixed array (#19885)\n- Fix arrays alias built-in methods call(fix #19896) (#19910)\n- Fix generic array initialization (fix #19903) (#19916)\n- Fix option sumtype auto deref (#19919)\n- Ast, checker, cgen: fix interface embedded methods call(fix #16496) (#19936)\n- Fix ref and deref when an interface is used as a function parameter (fix #19947) (#19966)\n- Fix auto str for interface struct member which implements str method (#19970)\n- Fix generics call with interface arg (fix #19976) (#20002)\n- Fix lambda initialization on option struct field (fix #19474) (#19995)\n- Fix live mode on windows (#20041)\n- Fix the static from_string method of Enum across mods(fix #20050) (#20068)\n- Fix `@[if xyz?] fn init() {}`, add tests (#20096)\n- Fix assignment to the elements of an array of fixed arrays (#20133)\n- Fix mutable comptimeselector usage (fix #20027) (#20134)\n- Fix generics chans select (#20159)\n- Fix string interp with zero characters (fix #20199) (#20200)\n- Fix interface eq method with option and ref (fix #19441) (#20201)\n- Fix infix expr in method of mut receiver variable (#20225)\n- Fix cgen for thread wrappers, when spawning fns with with anon-fn array args and mut interfaces (\n  fix #19425) (#20241)\n- Fix fixed array return when returning fixed array initialization (#20262)\n- Fix function generated code, when returning from match (#20263)\n- Fix in expression with mut and ref (fix #20268) (#20271)\n- Fix initialization of const string arrays on msvc (fix #20287) (#20289)\n- Fix code generation when 'in array init' is used as an if condition (fix #20300) (#20302)\n- Escape table names (fix #20313) (#20322)\n- Add missing clear method for generic maps (#20340)\n- Fix auto unwrapping option fn type (#20332)\n- Fix option initialization with default struct initialization to not be `none` (#20349)\n- Fix auto str for arr options with possible circular reference (#20354)\n- Fix code generation when the function returns mut fixed array (fix #20366) (#20367)\n- Fix printing fixed array of options (#19479)\n- Fix struct field of fixed array init (fix #19483) (#19487)\n- Fix struct init with multi option fn type (#19491)\n- Ast, native, cgen: add support for `$if native {}` (#19500)\n- Fix maps with i32 keys\n- Fix for c stmt with option or result calls (#19641)\n- Fix infix op when handling comptime selector (#19691)\n- Fix array contains method with interface(fix #19670) (#19675)\n- Reduce expense in repetitively called functions by using consts (#19732)\n- Fix closure parameter judgment when var cross assign inside anon fn(fix #19734) (#19736)\n- Only generate free in wrapper for spawn and not go (#19780)\n- Fix g.obf_table data missing(fix #19695) (#19778)\n- Fix closure variable in smartcast (#19796)\n- Fix printing struct with thread field (#19320)\n- Fix the logic around the definition of VNORETURN and VUNREACHABLE (less warnings on FreeBSD) (\n  #19316)\n- Add support for `-d trace_cgen_stmt`, document it in CONTRIBUTING.md\n- Fix printing smartcast interface variable (fix #18886) (#19372)\n- Fix interface with multiple embedded fields (#19377)\n- Fix channel of interface (fix #19382) (#19383)\n- Fix fixed array of option type default (#19397)\n- Fix interface with option field (#19434)\n- Fix promoting an alias typed value, to a sumtype of the alias's base type (fix #19407) (#19423)\n- Remove the special plan9 support code, treat it instead as a posix system in cheaders.v (#19445)\n- Fix printing slice of fn call string (#19450)\n- Fix `type VType = &C.CType` (#19452)\n- Fix array of fns index call with direct_array_access mode (#19460)\n- Fix selector code to use interface method table on closure when needed (#18736)\n- Fix nested or expr call (fix #18803) (#18807)\n- Ensure that `<<` and `>>` has higher precedence in the generated C code, than arithmetic\n  operations (diff between C and V precedences) (#18814)\n- Fix cross assign with aliased array (#18830)\n- Fix generated code for returning generic result/option to comptime var (#18834)\n- Fix option map with fn type value (#18849)\n- Fix returning an option tuple - `fn f() ?(int,int) { return g() }` (#18851)\n- Fix printing multiple fixed array (fix #18866) (#18879)\n- Fix infix expr with number overflow (fix #18905) (#18936)\n- Remove \\r for consistency (#18962)\n- Allow dump(unsafe{nil}) and dump(voidptr(123)) in the same program\n- Implement fixed array of threads wait() (#19032)\n- Fix an error with ptr interpolation (fix #19048) (#19049)\n- Fix spawn call fn struct field(fix #18862) (#19096)\n- Fix bootstrapping on older macOS Catalina\n- Fix alias of array method call(fix #19125) (#19129)\n- Simplifications and clean up.\n- Fix mixed fixed array and array initializing (#19246)\n- Fix array sort with fn call parameter (fix #19220) (#19221)\n- Fix generic struct with option fn field (#19218)\n- Fix comptime assign with generic result return type (#19192)\n- Fix match with comptime if expr in branch (#19189)\n\n#### JavaScript backend\n\n- Simplify comptime if; catch up with cgen (fix #25295) (#25313)\n- Fix array type checking in sum type match expressions (fix #24237 ) (#24259)\n- js: fix callbacks in structure parameters (fix #24260) (#24324)\n- Fix array initialization with \"index\" and \"it\" (fix #24397) (#24429)\n- Cannot assign unsafe nil values (fix #24407, #24436) (#24458)\n- Fix alias type initalization (fix #24475) (#24480)\n- Fix casting (fix #24512) (#24519)\n- Alias types are not properly resolved (fix #24486) (fix #24507) (#24514)\n- Implement Map.keys() and Map.values() methods (fix #24209) (#24608)\n- Fix string.runes method (fix #20500) (#24609)\n- Fix direct map key access and map.len (fix #24616, fix #24605) (#24620)\n- Fix map to string fails on rune keys (fix #24637) (#24638)\n- Fix maps being always constructed using string keys (fix #24607) (fix #24671) (#24673)\n- Fix slightly incorrect JS (esbuild was broken on master) (fix #23711) (#24676)\n- Fix javascript backend treating u32 as i32 (fix #20499) (#20618)\n- Fix u16 cast handling in the JS backend (#20620)\n- Make program_test.v not flaky anymore, so that it is more sensitive to early errors. Fix\n  compilation error for u16.v . Make u32.out match the current reality (the bug will be filed\n  separately)\n- Fix inconsistent output (u32) in JS backend (#20691)\n\n#### vfmt\n\n- Force conversion of []Type{init: it} -> []Type{init: index} (#26201)\n- Fix `if x := g() { x } else { return }` adding newline after `return` (fix #24908) (#24945)\n- Fix eating the attribute from `@[deprecated] pub type Alias = int` (fix #24968), workaround\n  -usecache bug (#24969)\n- Fix call expr with single line comment in or expr (fix #24659) (#25159)\n- Fix comment line number in file with crlf line separator (fix #23524) (#25163)\n- Add support for 64bit int with `-new_int` (part 2) (#25298)\n- Convert `\"hello\".str` => `c\"hello\"` (fix #24635) (#24652)\n- Fix formatting for an option array of anon structs (fix #23841) (#23844)\n- Fix comment handling on ending of struct decl (fix #23947) (#23948)\n- Add support for comments inside `sql db { ... }` blocks (fix #22601) (#22602)\n- Fix formatting fixed array size of struct member (#22815)\n- Fix formating non-unsafe blocks with break line (fix #22900) (#22903)\n- Fix shared receiver formatting (fix #23151) (#23153)\n- Allow align threshold to be parametrized in calls to add_new_info (#21942)\n- Fix and simplify align of struct fields (#21995)\n- Fix alignment of enumeration types (#21999)\n- Fix enum fields with one empty line (#22007)\n- Fix fmt of enum fields with empty line (#22015)\n- Fix alignment of struct init fields (#22025)\n- Keep empty newlines in between interface fields/methods (#22040)\n- Fix interface fields or methods with empty newlines (#22046)\n- Fix enum/struct_decl/struct_init fields with empty newlines (#22051)\n- Fix interface fields/methods alignment (#22055)\n- Remove the prefixed module name of const names, that are in the same module (related #22183) (\n  #22185)\n- Fix import selective with interface implements (fix formatting part of #22200) (#22209)\n- Add a test for fn with c binding type args (#22212)\n- Fix formating a file in an oscillating manner (fix #22223, fix #22026) (#22232)\n- Allow single line `defer {}`, just like `or {}`\n- Don't break `it` variable name in match expression function calls (#21600)\n- Exit with error code if encountering diffs with `-diff` flag (#21603)\n- Add fn_with_mut_ref_params_keep.vv (#21711)\n- Implement wrapping function's super long arguments  (fix #15545, fix #21643) (#21782)\n- Keep manual newlines after fn parameters in fn declarations, do not auto wrap (#21795)\n- Update determining of struct field comments (#21066)\n- Inform about invalid interop function bodies instead of removing them (#21070)\n- Parse methods on JS interfaces, write JS method bodies (#21088)\n- Improve module detection when formatting imports (#21134)\n- Don't change paths when formatting imports (#21148)\n- Use fixed size array for max_len const (#21140)\n- Simplify const name formatting (#21143)\n- Improve import processing, add test (#21172)\n- Fix duplicates remove import comments (#21177)\n- Extend import import alias reference map for submodules (#21200)\n- v.fmt: drop newline in end comments for const (#20672)\n- Fix alias array no cast init (#20898)\n- Fix removal of used selective and alias imports in modules in `$VMODULES` dirs (#20977)\n- Improve submodule type alias lookup; fix formatting of modules in `$VMODULES` (#20989)\n- Fix type names for casts (#21036)\n- Insert auto imports after shebang (#21038)\n- Fix autoimport with shebang and comments above other imports (#21050)\n- Fix formatting for imports of submodule from module `src` dir (#21060)\n- tools.fmt: extend exit codes to allow spotting unformatted files next to internal errors (#21058)\n- Fix parsing of interface with comment above `mut:` keyword (#21062)\n- vfmt: automate transition from the old `[attribute]` to the new `@[attribute]` syntax (#19912)\n- vfmt: remove empty `__global()` (#20004)\n- Remove additional line breaks after call_expr before params struct args (#19795)\n- Fix map value alignment when using keys with uft8 symbols (#19689)\n- Align ternary expressions in const blocks (#19721)\n- Respect range index expressions in match branches (#19684)\n- Respect raw strings in `$embed_file(r'/some/path')` expressions (#19753)\n- Fix formatting of struct field with default value and new attr syntax (#19683)\n- Recognize or blocks in call args (#19690)\n\n#### Tools\n\n- ci: run `v doc` with VJOBS=1 on the CI, to make remote diagnosing of failures easier\n- Remove unused `sw := time.new_stopwatch()` call\n- Add support for VTEST_SHOW_CMD=1 in `v test .` too\n- ci: use VJOBS=1 for the `v test cmd/tools/vdoc` step too, to ease diagnosing remote CI failures\n- ci: bump cross-platform-actions/action from 0.29.0 to 0.30.0 (#25666)\n- Fix showing the *failed* compilation output with `v -silent test .`\n- ci: bump all `timeout-minutes: 15` to `timeout-minutes: 20` to reduce false positives due to\n  network timeouts (mostly for the Termux job)\n- Note about `v help check-md` when `v check-md .` fails\n- ci: skip invalid_utf8_string.vv in compiler_errors_test.v for msvc\n- ci: reduce annotation noise, remove dead code\n- ci: skip the multistage v->v2->v3 -usecache checks for now (reduce false positives on the CI for\n  unrelated PRs, until the root cause is fixed)\n- ci: add new job `sanitize-address-clang-without-gc` that passes `-gc none` through VFLAGS (#25780)\n- Support\n  ```\n  VTEST_SHOW_LONGEST_BY_RUNTIME=5 \\\n  VTEST_SHOW_LONGEST_BY_COMPTIME=5 \\\n  VTEST_SHOW_LONGEST_BY_TOTALTIME=5 \\\n  v test .\n  ```\n- Print total time at the *end* of the `v test-all` output to ease visual comparisons in separate\n  shells, without scrolling\n- Use unbuffer_stdout in TestSession.test, to ensure consistent output on the CI jobs\n- v.builder: remove the obsolete check for V_NO_C_ERROR_INFO (VQUIET=1 replaced it in 2023); add\n  VQUIET to the `-q` description\n- Make `v search` failures easier to diagnose (on the CI)\n- Support `v download -o some/folder/local.toml TOML_URL`, in addition to --target-folder\n- Add `--sha3-256` support for checksumming the content that `v download` saves\n- Add a watchdog timer in test_if_v_test_system_works.v to speedup the failure of stuck CI jobs\n- Use local `vtest build:` tags to eliminate the need for the skip_fsanitize_too_slow list in\n  vtest-self.v\n- ci,vpm: make dependency_test.v more robust, and easier to diagnose remotely\n- ci: set VTMP too in set_test_env/1, to avoid cloning conflicts during parallel test executions\n- v.builder: do not produce `If the code is in a folder with multiple .v files` for temp V REPL\n  files, to improve messages for `'asdas'.starts_wiz('xyz')`\n- Add a `-new-transformer` task to `v test-all`. Remove `-skip-unused` flags (it is the default\n  for ~1 year).\n- Improve development experience for `v -W -silent test-self vlib` (especially on CIs); *always*\n  show compilation errors for failures\n- Support `VTEST_KEEP_SESSION=1 ./v test vlib/math`\n- vet: use new annotation syntax ([] -> @[]) (#26026)\n- ci: bump cross-platform-actions/action from 0.31.0 to 0.32.0 (#26074)\n- Make the `is_sqlite3_present` check more robust (work with the system packaged sqlite library\n  again too)\n- v.vmod,tools: support a repo_branch property in v.mod files, in addition to the existing repo_url\n  property, to allow for backlinks to repos that use `main` instead of `master` as their core branch\n- Make the output of `v should-compile-all` more immediately useful in CI jobs (turn off stdout\n  buffering)\n- Add support for `// vtest vflags: -w` in `_test.v` files, to allow `v -W test .` later, for files,\n  that have known warnings\n- ci: make sure the generator for vlang/docs can be compiled with latest V (prevent silent doc\n  update stops, after breaking changes)\n- Add cmd/tools/gg_split_memdump_to_frames.vsh to ease working with memdump.bin files generated by\n  gg programs (split by frames)\n- Add find_doc_comments_with_no_dots.v\n- Improve summary output of find_doc_comments_with_no_dots.v\n- Skip _test.v and _test.c.v files in find_doc_comments_with_no_dots.v\n- ci: add report-missing-dots-in-doc-comments job\n- ci: mark tcp_test.v and unix_socket_test.v as flaky (they still fail sporadically on the CI,\n  although very rarely now)\n- ci: add `-prealloc` self compilation checks on more platforms (#24891)\n- docs,ci: check more vlib modules in the report-missing-dots-in-doc-comments job (#24928)\n- ci: add a watchdog timer thread to ringbuffer_test.v, to make sure the program exits in a\n  reasonable time (~10s). Let the test be retried 2 times in a row if it fails.\n- ci: bump cross-platform-actions/action from 0.28.0 to 0.29.0 (#24952)\n- ci: retry session_app_test.v 2 times, since it is network dependent, and sometimes (rarely) fails\n- v.help: document the new `-force-bounds-checking` option\n- Improve alignment for `v repeat \"program\" \"program_that_is_over_10x_faster\"`\n- ci: add checks for compilation of vlang/gui to v_apps_and_modules_compile_ci.yml\n- ci: retry 2 times vlib/net/http/server_test.v to avoid false positives for unrelated commits/PRs\n- ci: force changes to vlib/x/json2 to trigger the full sanitized checks (the implementation there\n  uses unsafe blocks and vmemcmp/3...)\n- ci: workaround -usecache issue afte 2d87ac4\n- ci: add a performance-compare-with-master job\n- Fix `return\"\"` in vdoc html output (fix #24979)\n- ci,tools: implement support for VREPEAT_SILENT=1 and `v repeat -S`, to only show the summary of\n  the runs, without the progress lines\n- ci: fix the performance-compare-with-master job, when run on PRs (#25014)\n- ci: trigger updates to the module docs, even if just only the static files for the doc generator\n  are changed\n- ci: make sure to always compare with the latest commit on the main V repo's master branch, when\n  running .github/workflows/compare_pr_to_master.v\n- ci: compare the sizes of small programs like hello_world.v, but generated with `-cc gcc` too\n- ci: improve the alignment of the results of file size comparisons in compare_pr_to_master.v\n- Improve the output of `./v doc -m -f html vlib/`\n- Use `Copying` instead of `Generating` for the static resources in `./v doc -m -f html vlib/`\n- ci: bump actions/download-artifact from 4 to 5 (#25051)\n- v.help: document the `-is_o option` (in `v help build-c`) and add a test for it (#25052)\n- ci: add experimental support for building V and testing on a Termux docker container (#25059)\n- ci: use retry.sh for the `pkg install` in termux_ci.yml to reduce false positives.\n- ci: update vlang/gui commit its latest e5cc33fe816fef33d718cb1b91f66d6bd38fb4a4\n- ci: bump actions/checkout from 4 to 5 (#25095)\n- ci: retry 3 times vdoc_file_test.v\n- ci: add a build_on_ubuntu_25_ci.yml script, for testing bootstrapping with GCC 14.2.0 (#25109)\n- ci: define TERMUX_VERSION in .github/workflows/termux_ci.yml instead of using `-os termux`, to\n  make the emulation closer to a real Termux (#25128)\n- ci: reduce timeout-minutes for CI jobs that are normally fast to help detect anomalies earlier (\n  #25129)\n- ci: add a disable_azure_mirror.sh script, and use it before `apt update` to reduce the recent\n  timeouts during installing dependencies (#25147)\n- ci: bump timeout-minutes to 15 in termux_ci.yml\n- ci: bump actions/setup-java from 4 to 5 (#25153)\n- ci: retry vlib/v/eval/interpret_test.v 2 times\n- ci: bump retry time from 10 to 15 minutes (reduce false positives for slow dependency\n  installations on the CI)\n- ci: change the azure mirror URL in /etc/apt/sources.list too\n- ci: use `awalsh128/cache-apt-pkgs-action@v1.5.3` instead of a manual `apt update/apt install`\n  step, to leverage caching more (#25256)\n- ci: check if `awalsh128/cache-apt-pkgs-action@v1.5.3` works on master (#25257)\n- ci: extract .github/actions/cache-apt-packages-action/action.yml, use it in puzzle_vibes_ci.yml\n- Let test_os_process.v use `unbuffer_stdout()` to make the output more reliable\n- os,tools: make easier analyzing process_test.v failures on the CI\n- ci: fix build conditions that had `sanitize-memory-clang?` instead of `sanitize-memory-clang`\n- ci: skip running the `s390 CI` job for simple doc/yml changes (#24160)\n- ci: fix shell script issues reported by actionlint (#24168)\n- Remove the `src` subdir from projects, created by `v new` (#24236)\n- Add support for `// vtest build: !os_id_ubuntu?` tags in the _test.v files, detected by `v test`\n- ci: fix `v -o v2 -usecache cmd/v` after ad5b829\n- Fix vrepl for `import mod { f }` (#24340)\n- ci: debug hub_docker_ci.yml issue (try 1, disable cache, run linters)\n- ci: debug hub_docker_ci.yml issue (try 2, add concurrency group, add a persistent single builder\n  `gh-builder`)\n- ci: debug hub_docker_ci.yml issue (try 3, restore the cache-from:/cache-to: lines)\n- ci: fix hub_docker_ci.yml issue - comment out the cache-from:/cache-to: lines again\n- Support vreduce timeout, vreduce custom run command (#24359)\n- Rewrite `v timeout`, support killing the child process on timeout by default (#24367)\n- Use breadth first search in vreduce (#24369)\n- Vreduce fix var names (#24373)\n- Fix `v timeout 2 sleep 5`\n- Fix `./v -d network test cmd/tools/vpm`\n- ci: reduce false positives for cover_test.v and vdoc_test.v\n- Save the modified content more frequently in `v reduce`, fix timeout leaks (#24405)\n- Reduce padding for `v doc` produced html nodes too\n- ci: reduce the noise in check annotations for github PR reviews, due to the new warning in\n  option_test.c.v\n- Improve show_ancient_deprecations.v, by ignoring false positives for deprecation tags in //\n  comments\n- Check for Git repository in `v doctor` (packaged V versions often lack a .git/ folder) (fix\n  #24419) (#24420)\n- vlib,tools: add an `arrays.diff` module, implement a simple platform independent tool\n  `v diff file1.txt file2.txt` using it (#24428)\n- ci: bump creyD/prettier_action from 4.3 to 4.5 (#24439)\n- ci: use `v retry` to reduce the false positives for retrieving the dependencies for vinix too\n- ci: show `hg version` too, to ease the diagnosing of install_version_test.v failures\n- Let cmd/tools/vpm/install_test.v use a .hg/hgrc file too\n- repl: fix typeof(a) with warning (fix #24499) (#24515)\n- Make `v doctor` show CFLAGS and LDFLAGS too (if set)\n- Make `v search ui` work again through the vpm site (fix #23966) (#24535)\n- ci: fix unused var warning in cmd/tools/vpm/common.v\n- ci: prevent future changes to cmd/tools/vpm/common.v, that introduce warnings/notices to pass in\n  PRs\n- x.benchmark: align the output of BenchmarkResult.print/0\n- Ease diagnosing CI failures of vtimeout_test.v\n- ci: make sure that only one copy of native_test.v is executed at once, when run through\n  `v test vlib` (fix #24505)\n- Ignore .db and .sqlite files by default in `v watch` (such DB files are very likely to change\n  during prototyping)\n- .gitignore: ignore .db and .sesskey files as well\n- ci: bump creyD/prettier_action from 4.5 to 4.6 (#24687)\n- Make  `v doc -f md module` output useful by default (#24737)\n- ci: fix native_backend_ci.yml concurrency group setting (prevent jobs for different commits on\n  master to cancel each other)\n- Fix overflow detected in the sanitized runs on the CI (#24064)\n- ci: reduce code duplication in linux_ci.vsh\n- ci, vc: use the full V repo commit hash, when generating vlang/vc commit messages\n- Support `v should-compile-all folder/`, where `folder/` contains project subfolders (containing\n  v.mod files and multiple top level .v files)\n- Improve `v should-compile-all .` with support for compiling .wasm.v and .js.v files; skip\n  `module name` files, compile projects that have .glsl files\n- Improve `v bug` report wording\n- v.help: improve message formatting (#23363)\n- Restore `emcc --version` diagnostic in `v doctor`, when emcc is present\n- ci: fix `v -W build-tools` (#23368)\n- ci: force all tools to build without warnings/notices in tools_ci.yml (#23371)\n- Fix `v buf file.v`, when run in a folder != vroot\n- Improve output of `v bug file.v`, fix `v bug /long/abs/path/file.v` too\n- ci: make show_manual_release_cmd.vsh use a fixed weekly.YYY.WW format for the weekly release tags\n- ci: make easier the debugging of the `docker-alpine-musl-gcc` job (#23399)\n- vvet: fix for `v vet folder/` + new features (track long fns, empty fns and repeated code),\n  enabled by the new -F and -r flags (#23405)\n- v.help: add a message for `v help crun` (#23431)\n- Make cmd/tools/vretry_test.v independent from the presence of git (fix issue #23398)\n- ci: add compile_herolib.sh, use it to make sure it keeps working (related #23467) (#23469)\n- ci: fix toml-module-pass-external-test-suites after the CI image runner upgraded jq to version\n  1.7, by downloading and using the release version of jq-1.6\n- ci: fix failure of the check-markdown job\n- vet: add an `-I` option to notice fns, with the potential to be inlined (#23534)\n- ci: update last known good commit hash for herolib to ca8799af39228a5678a7be81128c5b0c342c9efc\n- Make `v check-md .` print the actual length of lines too, when reporting errors/warnings about\n  them (#23606)\n- Restore previous behavior of `v download` (show progress on stdout, when it is connected to an\n  interactive terminal; hide log stdout->stderr notice)\n- ci: fix `CI=name ./v -d network test cmd/tools/vpm/` ; update the image runners in vpm_ci.yml (\n  #23628)\n- Add `v reduce program.v`, in order to make smaller reproductions (`rpdc.v` files), before filing\n  cgen bugs (#23636)\n- Add a small utility script `cmd/tools/vrun`, to make it easier to use .vsh scripts on systems,\n  with `/usr/bin/env` still not supporting `-S`\n- Describe a more direct way to use a `v run` shebang in cmd/tools/vrun\n- Fix show_manual_release_cmd.vsh, use .strftime(%V) for calculating the proper default week number\n- Improve the `v reduce` parser for functions, and add more loops to reduce more (#23694)\n- Improve `v reduce` output; bump version, warn on failed string_reproduces/3, but continue to run (\n  #23697)\n- Fix warnings in `v reduce` (#23709)\n- Move `cmd/tools/vdoc/doc` to `cmd/tools/vdoc/document`, so that it can be imported from other\n  programs through `-path`, without conflicting with the top level `doc/` folder in the main repo (\n  #23733)\n- ci: avoid duplicating work by removing the remaining `-skip-unused` tasks, since that is the new\n  default (#23746)\n- ci: use distinct names for the jobs, for easier filtering/searching in the Github's UI\n- ci: fix job names in cmd/tools/modules/testing/common.v as well\n- ci: fix github job names in cmd/tools/vtest-self.v\n- ci: update the remaining runners from ubuntu-20.04 to ubuntu-22.04 and ubuntu-24.04 (#23754)\n- ci: rebuild V with `v -g self` in .github/workflows/native_backend_ci.yml, to improve remote\n  diagnosis of panics in PRs\n- ci: use `-silent` for the longer test runs (suppress most OK lines, to reduce scrolling on\n  failure)\n- .gitignore: ignore the project settings file for gf2 (a very nice GUI gdb frontend)\n- vrepl: fix slow response for empty line input (after just pressing 'enter/return') (fix #23856) (\n  #23858)\n- Make `v repeat failing_cmd` show the error output *just once*, but also still measure the time it\n  took to execute\n- Add --check flag to `v ast` (#23938)\n- Add `v timeout` to be able to later use `v timeout 5.1 git -C . fetch V_REPO` in `v doctor` and\n  other tools.\n- Add a custom timeout of 5s for the network using command `git -C . fetch V_REPO` in `v doctor` (it\n  normally takes <1s) (fix #23955)\n- Support `v doctor -skip-github` to fully skip the fetching step, in places that have limited\n  connectivity (alternative fix/workaround for #23955)\n- ci: use -silent in more jobs that produce a lot of OK lines normally (for test-cleancode,\n  test-self, build-examples, build-tools)\n- ci: add benchmark_footprint_json_decode.yml and benchmark_footprint_json_encode.yml (#22592)\n- Use a `~same~` label, when the results in `v repeat` are not different enough\n- Allow for fast exiting in compare_pr_to_master.v through Ctrl-C (or any failed command)\n- ci: fix failing jobs after 4ed9d13 (#22606)\n- Discard the top 7 results for each 10 runs, from `v repeat` runs, done by compare_pr_to_master.v,\n  to reduce σ on machines with more varied load\n- Allow for `v repeat -N ./cmd/tools/vtest_test`, by adding a -N/--no_vexe_reset option to\n  `v repeat`\n- Show more details in compare_pr_to_master.v\n- ci: fix failing musl jobs after 2684ef9 (#22667)\n- ci: run `zizmor .github/workflows/paths_ci.yml` and fix reported issues (#22681)\n- Show the full test output, on known flaky test failure with `v test folder/` (#22716)\n- Change `v test` to allow for `// vtest hide_retries` so that retry_test.v can hide its own (\n  deliberate) retries\n- ci: rename one of the duplicate `main_test.v` files, to reduce false positives (workaround)\n- Fix `v doctor` output for missing `cc`. Add a diagnostic line checking for `emcc --version` too\n- ci: run `v fmt -w vlib/v/pref/should_compile.v`\n- ci: reduce flakyness of cmd/tools/vcover/cover_test.v (workaround for a race condition while\n  updating the OK tasks counter in `v test`)\n- Improve the diagnostic output of compare_pr_to_master.v\n- ci: add a problem matcher support, to get error/warning/notice annotations in V CI jobs (#22790)\n- Bump default `v retry` timeout to 10 minutes, clarify the usage of its `--timeout` option.\n- ci: fix Build V\n- ci: silence compilation warning for bench_string_key_in_map_vs_string_value_in_array.v\n- ci: fix vinix_ci.yml for latest Vinix commits (#22818)\n- Improve output of compare_pr_to_master.v\n- Use `v retry` in more places, that do network operations that can fail temporarily (#22836)\n- Allow for `v download -RD URL/script.vsh`, to download `script.vsh`, then run it locally, then\n  remove it, in a single command\n- v.help: add topic for `v help retry`\n- v.help: add help topic for `v help repeat`\n- ci,v.help: work around -autofree bugs, fix `./v -autofree -o v2 cmd/v`\n- ci: add .yml file for testing compilation of Larpon's Shy library and the Puzzle Vibes game (\n  #22874)\n- ci: check more compile flag combinations in puzzle_vibes_ci.yml\n- Fix compilation of hw with vnew -> vold, in compare_pr_to_master.v\n- ci: fix for `v build-tools`\n- ci: check that more apps/modules do compile with -skip-unused (#22904)\n- vet: make `v vet` produce a nicer note, including the offending files, instead of `file.v` (\n  #22957)\n- ci: extract the VTL&VSL jobs from v_apps_and_modules_compile_ci.yml to vsl_and_vtl_compile_ci.yml\n- Make oldv aware of when to pass -no-parallel when bootstrapping V from v.c (fix #22990, part 2)\n- markused: only add .vtest_ functions, *when* compiling _test.v files (#23003)\n- Improve oldv compatibility for using new stricter C compilers like clang-18, to compile older V\n  versions from 2020 and 2019\n- Use -Wno-error=incompatible-pointer-types in oldv, which is more permissive than just\n  -Wno-error=incompatible-function-pointer-types, and works with gcc too, not just clang\n- Describe more precisely what commands are used by `oldv`, so it can fail early, with a meaningful\n  error message, if they are not present.\n- ci: fix ROADMAP.md checks (#23059)\n- vrepl: shrink .repl inputs, so repl_test.v runs faster\n- ci: update compile_v_with_vtcc.sh, enable its CI task again (#23063)\n- ci: extract .github/workflows/compile_discordv.sh, enable its CI step again\n- json2.decoder2: prepare decoder in json2 to be replaced by json2.decode2 (#23078)\n- Let oldv fail early, when git fails to do network operations or checkouts\n- ci: fix for `-cc tcc -no-retry-compilation`, do not use more complex constants, but functions in\n  vlib/math/vec/vec2_test.v\n- ci: fix option_fn_voidptr_test.v after a200c45\n- ci: make the CI more robust, by retrying commands and `v download` instead of wget (#23196)\n- ci: use `v retry -- v setup-freetype` to make the CI more robust against random network failures\n- ci: change exec name for parallel cc\n- ci: speed up again sanitizer runs (#23222)\n- Implement a `-repeats/-R N` option to `v repeat`, to eliminate another need for platform dependent\n  scripting\n- ci: add hub_docker_ci.yml, for building docker images (triggered manually for now) (#22302)\n- ci: use `docker compose` instead of `docker-compose` (\n  see https://github.com/orgs/community/discussions/116610) (#21992)\n- vrepl: suppress the welcome message, if VQUIET is set (#21941)\n- Make `v where` ignore .git/ folders (they contain binary files); let `-dir .` work recursively, so\n  that `-dir vlib` works\n- Sort the match results in the vwhere test, to make it less flaky (#22033)\n- Add an amalgamate tool and description of usage (#22034)\n- Add a few missing v command entries and their flags in `v complete` (#22041)\n- Colorise the output of cmd/tools/show_ancient_deprecations.v, reduce false positives (#22048)\n- docs: clarify the .precision specification section for string interpolation of floats (#22061)\n- docs: add a copy code function (top/right copy icon) on doc examples (#22114)\n- Allow passing parameters to fuzz_v_parser_with_radamsa.sh, so that it could be run in several\n  processes from the same folder\n- Use separate .autofuzz.log files too for the separate invocations of fuzz_v_parser_with_radamsa.sh\n- Extract .github/workflows/run_sanitizers.sh to ease local testing with different options\n- parser,ast: protect against more overflows/panics, by forcing early returns on deeply nested\n  expressions and scopes (#22098)\n- Improve the output of `v repeat command`, by coloring the `faster/slower` label\n- Add diagnostic in `v repeat` for invalid combinations of -r, -i and -a flags\n- Fix `v doc` truncating code blocks, that lack a specific language (fix #22017)\n- v.util: add get_build_time/0, supporting https://reproducible-builds.org/docs/source-date-epoch/\n- Fix `v doc` not converting `<s>` in plain code blocks into encoded html entities in its .html\n  output\n- ci: run `npx prettier --write **.yml`; ensure it is run on all .yml files, not just the ones in\n  the .github/workflows/ folder\n- docs: add implements keyword for explicit interface implementations (#22214)\n- Make fast_job.v more robust (setup a custom PATH) and informative on fast.v failures (compile it\n  with -g)\n- Make fast.v and fast_job.v more self sufficient\n- ci: add cache and trigger for pushes, in the Hub docker action (#22314)\n- Fix spurious ending quote in the output of show_manual_release_cmd.vsh\n- Dockerfile.alpine: update to alpine:3.20, add more tools like gdb, libunwind, gc, to ease\n  producing and debugging static executable in more situations (#21583)\n- Add `v download URL` for downloading single files, to avoid curl/wget etc, which are not available\n  uniformly. (#21597)\n- ci: use shebang with better portability in shell scripts, format shell scripts (#21605)\n- Don't write vpm logfiles in CI runs (#21649)\n- ci: make vmodules_overrides_test.v failures more informative\n- Fix measurements for `./v repeat \"./vold -o x project/\" \"./vnew -o x project/\"`\n- Make the summary output of `v repeat` more informative\n- Disallow self referencing function alias types like `type FnType = fn(string) FnType` and\n  `type FnType = fn (FnType) string` (#21733)\n- vrepl: fix method call (fix #21788) (#21792)\n- ci: restore v_apps_and_modules_compile_ci.yml (#21791)\n- vrepl: fix output of the fn call (related #21792) (#21800)\n- vrepl: fix variable name starts with print (#21806)\n- v.pref: make pref_test.v be less sensitive on the specific C compiler used as a backend (#21813)\n- vrepl: fix arbitrary script execute (#21818)\n- ci: disable c2v_ci.yml temporarily, until it is fixed\n- vrepl: lots of fixes in REPL\n- Add a TOTAL line, to the output of -show-timings, to minimise the need for external tools on\n  windows (#21847)\n- doc: fix vup/vself replacement scripts (#21092)\n- Prevent module updates during `v build-tools`, when VTEST_SANDBOXED_PACKAGING is set (#21094)\n- ci: update the reference to the v-analyzer repo\n- ci: retry all setup commands that need network access, till they succeed (so the CI jobs have less\n  false positives) (#21103)\n- changelog: escape `@NAME` entries, to avoid mentioning unrelated github accounts\n- Add `v retry apt update`, intended to replace the retry.sh script, for more robust CI jobs (\n  #21104)\n- vpm: show the final path where a module is installed, improve color contrast for white on black\n  terminal sessions\n- vet: print help when passing no files or `--help`/`-help` flag after vet command (#21108)\n- Fix `v build-tools` (it skipped all tools in subfolders of cmd/tools/ after 6a4f293) (#21120)\n- .gitignore: ignore generated .NET files in bench/vectors (#21136)\n- vet: optimize performance for path detection, when vetting files (#21139)\n- vet: allow to overwrite excluded dirs (#21142)\n- ci: increase wait time for the xvfb check, to reduce the chance of false positives\n- Fix `v run cmd/tools/measure/parser_speed.v file.v`\n- Add `v run cmd/tools/measure/fmt_speed.v file.v`\n- ci: move build step for VPM site, into apps and modules ci, add concurrency config (#21191)\n- tools.vpm: debug-log to `$VMODULES/cache/vpm.log` if not running in debug mode (#21192)\n- vpm: optimize performance by adding filter when cloning (#21216)\n- vdoc: don't add _docs directory when an out path is specified (#21233)\n- ci: prefer dedicated tiggers for platform workflows, so sporadic fails can be retried quicker (\n  #21251)\n- v.util: improve code related to diff tool specified via environment, add check if the diff tool\n  exists (#21240)\n- vpm: check for git version before adding `--also-filter-submodules` flag (#21259)\n- ci: add logging to .github/workflows/retry.sh\n- Revise `vtest-self.v`: remove dead paths, fix json2 essential test path (#21267)\n- Add check for unavailable files in vtest (#21272)\n- ci: reactive app prod builds (#21295)\n- ci: add a m1 runner for testing the prebuilt zips too\n- ci: add workflow_run: event in prebuilt.yml\n- ci: simplify prebuilt.yml, make it usable for manual runs too\n- vpm: fix regression, so `v install sdl && v run ~/.vmodules/sdl/setup.vsh` works again\n- ci: fix outdated_test.v (--unshallow is not needed now)\n- ci: continue testing independent V apps, even if one fails, to get feedback for breaking changes\n  faster (#21302)\n- ci: optimize apps and modules (#21303)\n- ci: test `v ~/.vmodules/sdl/setup.vsh`, to prevent future vpm regressions (#21306)\n- ci: prevent unintended deployment workflow steps (#21313)\n- Add a 2024.html page to https://fast.vlang.io/\n- vdoc: rewrite and extend vdocignore (#21314)\n- ci: fix the commit labels for the vc repo\n- Support `v run cmd/tools/oldv.v --show_VC_commit weekly.2024.03`\n- ci: use latest upstream `discord.v` in apps and modules test (#21322)\n- vdoc: remove obsolete entries from `.vdocignore` (#21320)\n- v: update linguist languages, add .vdocignore (#21321)\n- ci: update deployment workflow (#21323)\n- Allow for selectively running `v test-self vlib/` and `v test-self cmd/` (#21326)\n- Rewrite test-self arg handling (#21327)\n- ci: restore `v install elliotchance.vsql` in v_apps_and_modules_compile_ci.yml\n- ci: use `v retry -- cmd` to replace `.github/workflows/retry.sh cmd`, where possible in\n  `v_apps_and_modules_compile_ci.yml` (#21336)\n- ci: update workflow conditions (#21338)\n- Improve `v symlink -githubci` diagnostic message, when used outside CIs or with sudo (#21340)\n- ci: update detection of workflow cancellation scenarios (#21342)\n- Fix compiling vwhere with `-cc gcc -cstrict` (#21347)\n- ci: remove the separate `-gc boehm` job (since `-gc boehm` is the default now) (#21352)\n- ci: add a separate cmd/tools testing job (#21344)\n- Update fast.v and fast_job.v to update docs.vlang.io and fast.vlang.io on each commit to master.\n- Make fast.v more robust to independent remote changes in vlang/docs\n- Utilize environment specific files for vsymlink  (#21360)\n- ci: update `binary_artifact.yml` (#21364)\n- ci: add docker to tools workflow, update ignore paths (#21368)\n- ci: split up vsl / vtl run, reducing the tool change CI time from ~19min to ~10min (#21372)\n- ci: fix binary_artifact.yml (#21373)\n- Refine `check_os_api_parity.v` (#21371)\n- ci: update native backend ci matrix (#21375)\n- ci: update symlink ci, add matrix (#21376)\n- ci: workaround defer codegen failing with nested if blocks and -cstrict in vdoc_file_test.v\n- ci: update detection of accidentally added gpl licenses (#21384)\n- ci: set cancel-in-progress to false in bootstrapping_ci.yml to avoid false positives\n- ci: do trigger bootstrapping_ci.yml periodically, but just on changes\n- ci: speed up bootstrapping_ci.yml, by using the default tcc when possible\n- ci: update `bootstrapping_ci.yml` trigger paths (#21394)\n- ci: pass a good commit to oldv.v in `bootstrapping_ci.yml` (#21393)\n- Be more verbose when doing `v up` in V folder produced by extracting a .zip release file\n- Exclude thirdparty/tcc from the git clean operation, that vup does in case of a missing .git\n  folder\n- Protect from cleaning during `v up`, only ./v , not any matching folder\n- Use proper ignore/exclude patterns in the git clean, that `v up` does\n- Use more meaningful names in vup.v\n- Be verbose, when a git commands that `v up` executes fails\n- ci: add a v-up-works-ubuntu job, to ensure more robust `v up` runs (#21401)\n- ci: ensure v master is available when trying to check out its commits to build oldv (#21414)\n- Rewrite vet error handling (improve parser performance extend vvet) p1 (#21417)\n- Move dynamic const array check from parser into vet (#21423)\n- v.help: update help for `fmt` (#21430)\n- Move array_init_one_val checks from parser into vet (#21422)\n- Remove `vet_errors` and `vet_notices` from parser (#21424)\n- ci: temporary fix for gitly compilation\n- Remove vetting for spaces after / before parens (#21437)\n- Add `.github/workflows/show_manual_release_cmd.vsh`, to make cross platform testing of the release\n  process easier\n- ci: merge docker_alpine and docker_ubuntu workflows in `docker_ci.yml` (#21446)\n- Move now obsolete vlib vet module to cmd vet (#21445)\n- Use `parse_file`, remove `parse_vet_file` (#21444)\n- ci: update binary artifact workflow, add matrix (#21378)\n- ci: add workflow_dispatch: to gen_vc_ci.yml\n- ci: fix vinix_ci.yml by using `./v symlink -githubci` in vinix_ci.yml\n- ci: port changes from Vinix's check.yml at 8231e569 to vinix_ci.yml\n- tools.vet: move error methods to `vvet/errors.v` (#21449)\n- ci: reduce false negatives for tcp_test.v, retry it 3 times before failing\n- Improve performance of `v test-cleancode` and `v fmt -inprocess -verify .` (#21450)\n- Make `./v symlink` work platform independent in CI (part 1) (#21453)\n- ci: replace .github/workflows/retry.sh usages in the CI with the shorter `v retry --`, move\n  `v test-cleancode` upwards to save time for unformatted PRs (#21452)\n- Capitalize information output of `v up` (#21464)\n- ci: use `v symlink` without `-githubci` for regular symlinking (#21455)\n- ci: add a linter for the .yml workflow files (#21459)\n- ci: update symlink ci, extend tested cases (#21466)\n- tools.vet: update diff comparison in `vet_test.v` (#21457)\n- Call mkdir_all before set_output_path to avoid a vpm panic when ~/.vmodules/cache does not exist (\n  #21463)\n- ci: make issue template title consistent, fix linter error regarding labels (#21460)\n- tools.vet: reduce nesting in `vet_fn_documentation`, skip vetting empty lines (#21465)\n- Print info to use v symlink instead of `v symlink -githubci` (#21471)\n- Move _test.v files for vdoc at the same level (#21473)\n- ci: update the helper script, for getting the most recent sqlite-amalgamation-3380200.zip (#21474)\n- vdoc: fix handling of .vdocignore files in subdirectories (#21514)\n- ci: run build-module-docs, when changes to the source of the `v doc` tool happen too\n- ci: use g++ not g++-11 in misc-tooling (g++-11 can not be found and installed on the CI runner\n  anymore for some reason)\n- ci: update g++ to g++-10 in other_ci.yml, add workflow_dispatch: trigger for easier local future\n  diagnostic\n- vdoc: improve vdocignore file handling by walking all .vdocignore sub-paths in IgnoreRules.get,\n  add test (#21521)\n- ci: run `v fmt -w cmd/tools/vdoc/vdoc_test.v`\n- ci: make sure that unformatted code in just cmd/ is not allowed\n- ci: mark again tcp_test.v as flaky (it had 3 unrelated failures on the CI over the last week)\n- v: vet for empty string conditions (#21529)\n- tools.vet: add notice for empty strings conditions (#21421)\n- repl: support executing shell commands on the REPL with `!sh [COMMAND]` (#20496)\n- repl: fix an issue with `print` and println after the execution of `for` or `if` (fix #20524) (\n  #20525)\n- tools: bump too_long_line_length_table to 160, to avoid warnings for just\n  `v check-md doc/docs.md` (most common)\n- tools: bump too_long_line_length_link to 250, to avoid warnings for very common long links\n- ci: simplify time_ci.yml, use more descriptive CI job names, for easier judging of CI failures\n- debug: fix variable dereferencing (#20594)\n- tools: support setting another SCANNER_MODE=parse_comments in parser_speed.v and scanner_speed.v\n- testing: fix warning for compiling `./v cmd/tools/vtest.v`\n- docs: add a section about modules specifics (#20653)\n- github: add dependabot.yml (#20800)\n- vtest,pref: add ability to have platform specific _test.v files (#20810)\n- ci: change spaceface777/cancel-workflow-action to styfle/cancel-workflow-action (#20806)\n- tools: use the same same skipping logic for the platform specific _test.v files in `v test-self`\n  too (#20815)\n- tools: make the output of `v check-md .` more informative (#20819)\n- v.debug: implement tracing hook feature (#20818)\n- ci: mark db_store_test.v as flaky\n- ci: add a vtcc step (check that vtcc, continues to be able to compile with v, and v itself can be\n  compiled with vtcc) (#21000)\n- v.util: simplify vtest (#21013)\n- vtest-self: add sandboxed packaging case (#21059)\n- tools: fix already installed detection when running v install --once without args (#19838)\n- compress.gzip: change the endianness for validation to conform to the gzip file specification (fix\n  #19839) (#19849)\n- tools: support `v doc -run-examples math`, to ensure that all `// Example: code` doc comments are\n  working (#19852)\n- Fix `v help` in the prebuilt v executables from the zips in the releases\n- ci,tools: remove skips for the wasm backend, since binaryen is not required anymore (#19883)\n- tools.vpm: support again `http` installs, when installing from an url (workaround) (#19914)\n- tools.vpm: improve version detection of installed modules (#19933)\n- tools: fix `v up`, by not deleting `./v` when missing a `.git` folder (#19965)\n- tools.vpm: fix installing of modules with conflicting names, extend tests (#19961)\n- tools.vpm: evaluate dependencies earlier to fix potential recursive install loop (#19987)\n- tools.vpm: add support for ssh and hg version installations (#20125)\n- tools: simplify and remove redundancies in vshader.v (#20161)\n- ci: add new workflow, for doing the slower tests in vpm specifically with `-d network` (#20177)\n- tools.vpm: improve detection of already parsed modules (#20223)\n- scanner: change `-d debugscanner` to `-d trace_scanner` for uniformity with the other tracing\n  options, described in CONTRIBUTING.md\n- v.pref: support a `-n` option, silencing only notices (#20331)\n- ci: add vsql to v_apps_and_modules_compile_ci.yml too (#20341)\n- ci: fix the workflow for Vinix, using the rules in its own .yml file (#20371)\n- Support -? as alias to -help (implement #20355) (#20358)\n- vdoc: filter testdata and tests folders by default, reduce filesystem stats calls\n- all: add support for `@LOCATION`, for more convenient logging/tracing, without needing to combine\n  `@FILE`, `@LINE` at runtime (#19488)\n- benchmark: add new methods b.record_measure/1 and b.all_recorded_measures/0 (#19561)\n- ci: update c2v workflow, translate doom on macOS (#19562)\n- strings: add Bulder.write_decimal/1 method (write a decimal number, without additional\n  allocations) (#19625)\n- testing: add temporary file hash to prevent accidental collisions with test file binaries (#19710)\n- ci: compile VTL and VSL in their own CI job, with `VFLAGS=-no-parallel`\n- tools: fix windows install of an already existing module with vpm (#19761)\n- tools: use `VPM_NO_INCREMENT` env var to skip dl count increment when testing vpm (#19756)\n- tools.vpm: improve handling of urls that end with .git (#19758)\n- tools: fix resolving external dependencies in vpm, add test (#19772)\n- tools: cleanup and simplify vcreate, for upcoming fixes and features (#19794)\n- tools: improve error messages, add color coding and debug logging (#19781)\n- tools: fix `v build-tools`, make `v test` more robust (#19803)\n- tools: add parse_query to vpm (#19814)\n- ci: add macos arm64 binary release (#19823)\n- Require the presence of a `v.mod` file, to install external urls via vpm (#19825)\n- vcreate: fix `v init` with project names containing dashes (#19619)\n- bench: a new bench/ directory for language benchmarks\n- ci: test the pure V math versions without .c.v overrides on the CI too (#19292)\n- github: add automatically info about voting to all new issues (#19351)\n- tools: add -E flag to `v test-parser`, that will show the partial source that caused the parser to\n  fail with `-no-builtin -check-syntax file.v`\n- ci: bring back gitly\n- github: improve the voting message for issues (#19448)\n- vcreate: update templates, add `lib` (#19444)\n- ci: add v-analyzer builds (#18835)\n- ci: cleanup more the contents of the generated v_linux.zip, v_macos.zip, and v_windows.zip, use\n  -skip-unused\n- tools: fix vcomplete for zsh (#18950)\n- tools: support a toc for projects, with single exposing module, in `v doc` (#19001)\n- Add support for `v should-compile-all -c examples/`, which will delete all the produced\n  executables at the end\n- vgret: add install commands for ubuntu and arch to doc string (#19247)\n- fast.v: add favicon to the html produced by fast.v\n- vpm: implement multithreading (#19208)\n- Make performance_compare.v more robust and easier to use, by allowing\n  `v run cmd/tools/performance_compare.v` too\n- Improve oldv windows support, make it use -municode for windows builds, make it support cmd.exe\n- Make repeated runs of `oldv SAME_COMMIT -c \"./v file.v\"`, not use the network at all\n- Help: add link to the TESTS.md at the bottom of `v help test`, run CI checks on help markdown\n  files as well\n- v.builder: show the number of files, types, modules, when a program is compiled with -stats\n- Improve the output of parser_speed.v and scanner_speed.v\n\n#### Operating System support\n\n- ci: fix gcc-windows -std=c99 (#25534)\n- os: add windows stdin_write() support (#25546)\n- ci: use `macos-14` instead of `macos-13` (the older runner is being deprecated) (#25670)\n- v.builder: fix json-errors with a windows path separator (#25680)\n- ci: fix unsetting of VFLAGS in `v run ci/linux_ci.vsh v_self_compilation_usecache_clang`\n- ci: stop unsetting VFLAGS completely in ci/linux_ci.vsh and ci/macos_ci.vsh\n- builtin,os: fix windows execute ANSI encoding result, make msvc error messages readable in a\n  Chinese locale (fix #25727) (#25736)\n- db.sqlite: update windows version to https://sqlite.org/2025/sqlite-amalgamation-3510000.zip (\n  #25766)\n- os.notify: fix struct epoll_event alignment on ARM64/Linux (fix #25778) (#25779)\n- fasthttp: Linux/epoll support\n- math: reduce the nested level of expressions, to reduce the chances of stack overflows on windows\n- net.http,ci,db.sqlite: rewrite .github/workflows/windows-install-sqlite.bat in .vsh, fix vschannel\n  on windows downloading content > 32KB (#25792)\n- v.builder: bump the default stack size for executables, when compiling with msvc on windows, to\n  32MB (#25824)\n- ci: reduce the chances of false positives due to hangs of use_net_and_net_unix_together_test.v on\n  windows\n- doc: add subsections about using SQLite on windows and about installing the self contained\n  `sqlite` module.\n- v.builder: switch to using `-std=c99`, instead of `-std=gnu99` to avoid name colisions with C\n  `linux` macros defined by gcc/clang (#25848)\n- gg: set more sensible and user friendly defaults for the width, height and the title of new\n  windows\n- thirdparty: update thirdparty-openbsd-amd64_tcc.sh (#25945)\n- ci: install plain gcc on the OpenBSD jobs\n- ci: use `gcc` as the name of the compiler instead of `egcc` on OpenBSD\n- ci: remove the gcc-openbsd job, until OpenBSD people fix their broken conventions on 7.8\n- ci: run `v -W -silent test-self vlib` on linux, so deprecations/warnings introduced in PRs, can\n  fail (and be fixed) earlier (#25955)\n- ci: use VTEST_SHOW_LONGEST_BY_* vars on OpenBSD (#25958)\n- ci: update to use FreeBSD version 15.0 (#25985)\n- crypto.ecdsa: update to test and use OpenSSL 3.5 on OpenBSD (#25995)\n- x.crypto.slhdsa: add support on OpenBSD using OpenSSL 3.5 (#25996)\n- ci: reduce failure rate for the gcc-windows job, in test_if_v_test_system_works.v\n- ci: skip use_net_and_net_unix_together_test.v on gcc-windows (many weird timeouts on unrelated\n  PRs)\n- db.sqlite: fix exec_param_many on linux for the case of a [][]string parameter\n- v.util: add `-d max_suggestions_limit=140` for v itself, to improve handling of large .v files\n  with many thousands of lines on windows\n- v.util: bump max_suggestions_limit to 200, to account for windows\n- ci: extract windows_ci_msvc.yml from windows_ci.yml to enable finer grained workflow/job control\n- ci: extract and split windows_ci_tcc.yml and windows_ci_gcc.yml from windows_ci.yml for improved\n  job control\n- docs: add section in README for compilation on OpenBSD (#24775)\n- crypto.ecdsa: add support for OpenSSL on OpenBSD (#24772)\n- picoev: add implementation for OpenBSD using kqueue (#24801)\n- log: fix `Unhandled Exception` on windows 7 (#24803)\n- ci: migrate the remaining jobs from the deprecated windows-2019 image to windows-2022 (#24825)\n- os: fix windows get_error_msg() leak (#24899)\n- runtime: reduce allocations done in runtime.used_memory/0 on linux (#24901)\n- ci: skip checking vlib/datatypes/lockfree/ringbuffer_test.v on the gcc-windows job for now\n- runtime: add used_memory() implementation for FreeBSD (#24909)\n- runtime: add used_memory implementation for OpenBSD (#24918)\n- ci: skip ringbuffer_test.v in the tcc-windows and msvc-windows jobs too, to avoid flakyness for\n  unrelated commits/PRs.\n- ci: use FreeBSD version 14.3 after the bump of cross-platform-actions/action to 0.29.0 (#24953)\n- time: fix timezone test on windows\n- ci: add a release build for Linux on arm64 to release_ci.yml (#25064)\n- thirdparty: add `thirdparty-linux-armv7_bdwgc.sh` for building `libgc.a` on ARMv7 CPUs (#25077)\n- ci: bump retry count for server_test.v to 5 (reduce false positives on windows)\n- ci: use `v build-tools` without flags for the tools-windows job\n- os: eliminate warning for `v -cross -o vc/v.c cmd/v` on linux (part 2, see also 037a3b4)\n- os,sync: enable running `v -cross -o x.c cmd/v` on windows too (part 1, fix V errors)\n- ci: run .github/workflows/disable_azure_mirror.sh before all `apt update` commands, in\n  ci/linux_ci.vsh, when run in a github CI runner\n- ci: retry 3 times cmd/tools/vtimeout_test.v on windows, before failing\n- os,ci: use a conditional include, instead of a platform file, to include libproc.h on macos only\n- ci: run input_rune_iterator_test.v only on linux for now\n- builtin: fix thread naming issue on Windows by ignoring RaiseException (0x406D1388) (#25270)\n- os: implement Process.is_pending() on windows (fix #23990) (#23993)\n- os: support .set_environment() on windows too (fix #10628) (#23996)\n- thirdparty: update thirdparty-linux-amd64_tcc.sh, to also record its own full invocation command,\n  and commit the changes automatically\n- thirdparty: add thirdparty/build_scripts/thirdparty-freebsd-amd64_tcc.sh\n- ci: reduce false positives for slow runs of the gcc-windows job\n- gg: fix screen_size() on macos with multiple displays\n- ci: add riscv64_linux_ci.yml (based on QEMU) as well (#24181)\n- ci: use `apt update` before `apt install` in cross_ci.yml, to make the linux job more robust\n- thirdparty: add thirdparty/build_scripts/thirdparty-macos-arm64_tcc.sh for compiling tcc on\n  macos (first draft)\n- Simplify the implementation of get_linux_os_name in `v doctor`\n- os.filelock: compile without warnings with gcc on windows\n- ci: use windows-2025 for the gcc-windows job (since it has gcc 14.2.0) (#24304)\n- ci: skip option_ptr_unwrap_test.v on windows with msvc (#24320)\n- os: fix windows rmdir GetLastError() (fix #24356) (#24357)\n- Enable windows tcc_backtrace() support (#24377)\n- ci: reduce false positives for init_global_test.v on windows (retry it 2 times)\n- ci: reduce false positives for orm_func_test.v on windows (retry it 2 times)\n- os: force using `C.CREATE_NO_WINDOW` on windows in os.raw_execute/1 (fix #24390) (#24418)\n- Fix v doctor output on FreeBSD ; do not run ldd to get the glibc version (#24427)\n- runtime: improve free_memory implementation for OpenBSD, by getting the stats from its UVM\n  system (#24431)\n- runtime: fix cast error in free_memory implementation for OpenBSD (#24445)\n- Use a `.hg/hgrc` file for install_version_test.v (workaround windows failure)\n- os: add debugger_present implementation for OpenBSD (fix #23603) (#24490)\n- veb: reduce veb_max_write_bytes from 16KB to 2KB (fix sending large dynamic responses from veb on\n  macos/freebsd) (fix #24523) (#24522)\n- os: fix os.File's tell/0 method for windows (fix #24217) (#24218)\n- net.openssl: replace SSL_get1_peer_certificate by SSL_get_peer_certificate for OpenBSD (#24556)\n- net.mbedtls: disable AES-NI on OpenBSD with tcc (fix #22239) (#24560)\n- net.mbedtls: enable MBEDTLS_THREADING_C and MBEDTLS_THREADING_PTHREAD on OpenBSD (#24572)\n- thirdparty: add thirdparty/build_scripts/thirdparty-openbsd-amd64_tcc.sh for compiling tcc on\n  OpenBSD (#24592)\n- v.builder: enable -fwrap for C compilation on OpenBSD too (#24585)\n- v.pkgconfig: add the default `/opt/local/lib/pkgconfig` for MacPorts on macos (#24626)\n- sync: increase retries for vlib/sync/select_close_test.v to 3, to reduce CI false positives in the\n  gcc-windows job\n- ci: remove script to build tcc on FreeBSD (obsoleted by\n  thirdparty/build_scripts/thirdparty-freebsd-amd64_tcc.sh) (#24681)\n- encoding.iconv: add path for iconv library on FreeBSD (#24682)\n- native: skip linux.vv too, for the sanitized jobs (similar to libc.vv)\n- ci: migrate from windows-2019 runner to windows-2025 runner in most jobs (github deprecated the\n  2019 runner) (#24672)\n- runtime: fix -cstrict compilation (use usize() cast in free_memory) on OpenBSD (#24696)\n- Remove specific case for FreeBSD in `cmd/tools/vtest_test.v` (#24707)\n- docs: add section in README for compilation on FreeBSD (#24706)\n- thirdparty: add script to build libgc on FreeBSD/amd64 (#24717)\n- builtin: use local static libgc for FreeBSD with tcc (fix #24710) (fix #24683) (#24720)\n- ci: update and improve FreeBSD CI (#24726)\n- ci: add CI for OpenBSD (#24732)\n- gg: fix .char event handling for backspace, delete, tab and enter for linux/x11 (send appropriate\n  .char codes to the apps, similar to macos)\n- Add aarch64 atomics support in thirdparty/stdatomic/nix/atomic.h (fix #24294) (#24296)\n- v.trace_calls: now musl has gettid(), there is no need for the shim on newer Alpine etc (#24245)\n- Avoid os.glob, in favour of os.walk_ext (which works consistently even on windows)\n- gg: add linux support for `fn screen_size() Size` (fix #23146) (#23326)\n- Define _GNU_SOURCE on Linux (#23364)\n- Fix `v doctor` format, fixes for windows, tcc and others (#23361)\n- picoev: fix for windows apps with veb in a thread, parallel to a webview, that opens a lot of file\n  descriptors (#23492)\n- v.pref: set `DYLD_FALLBACK_LIBRARY_PATH` on macos, when `-use-coroutines` is used, so that `v run`\n  can work, and the executable can find the downloaded photonwrapper shared library (#23516)\n- encoding.iconv: add flag for OpenBSD to find iconv include and library (fix #23573) (#23575)\n- runtime: add free_memory/0 implementation for OpenBSD (fix #23579) (#23583)\n- Fix `v doctor` output on OpenBSD: get gcc version from egcc; do not run ldd to get the glibc\n  version (fix #23576) (#23578)\n- make.bat: add note about antivirus programs on windows and compilation slowdowns (#23586)\n- runtime: add free_memory/0 implementation for FreeBSD too (fix #23581) (#23594)\n- log,sync: fix macos CI failure when log.ThreadSafeLog is used explicitly in `v download` (#23613)\n- Let `v test .` show the running _test.v files each minute (set by\n  `VTEST_REPORT_RUNNING_PERIOD_MS`); diagnose stuck windows gcc CI jobs (#23649)\n- ci: run FreeBSD on a VM in github ci, instead of on the Cirrus service (which stopped working\n  today) (#23692)\n- cgen,builder: fix windows 32bit dll function name mangle (fix #23689) (#23690)\n- ci: update linux image runners from `ubuntu-20.04` to `ubuntu-24.04` (#23706)\n- ci: do not use `VJOBS: 1` in the windows tcc job anymore\n- make: use .exe only on Windows\n- ci: reduce the timeouts in windows_ci.yml to 60 minutes (V is now faster, and the runners use\n  faster hardware as well)\n- native: allow for searching for wine system32/ .dlls, and for adding more paths for .dll lookups,\n  by setting `VNATIVE_PE_DLL_PATH`, to make it easier to diagnose problems with PE generation on non\n  windows platforms (#23756)\n- ci: skip fibonacci_native.vv on windows for now\n- sync: support x86_64-alt-linux gcc paths too when tcc is used (needed for ALT Linux)\n- ci: make freebsd_ci.yml runnable on personal forked repos, that are not named `v` (#23779)\n- ci: remove the VJOBS=1 restriction for test-cleancode on linux (#23801)\n- os: fix buffer overflow in os.get_raw_line under Windows (#23816)\n- ci: move test in pe_test.v to native_test.v (both used `-b native`, competing the creation of the\n  backend executable => CI failures on the gcc-windows job)\n- Make `v install` avoid using `--filter=blob:none --shallow-submodules --also-filter-submodules` on\n  windows (#23840)\n- os: fix get_raw_line() on windows (fix #23843) (#23846)\n- ci: add a limit of 20 minutes to the test-on-freebsd-14-2-x86 CI job\n- Support `// vtest build: !do_not_test ?`, `// vtest build: !windows && tinyc` to skip files during\n  testing on specific platforms, without having to keep centralised skip lists (#23900)\n- cgen,dl: remove workaround in `dl`, generate a DllMain() in cgen instead for `-shared` on\n  windows (#23961)\n- builder: change linuxroot repo URL to https://github.com/vlang/linuxroot\n- ci: test -os linux cross compilation on macOS\n- ci: test the cross compilation from macos to linux sooner, show more information\n- ci: move the macos->linux check even higher, to make easier testing and diagnosing linuxroot\n  update failures\n- orm: cross compile pg to linux; openssl: make cross compile work\n- ci: use `macos-14` instead of `macos-12` because\n  of https://github.com/actions/runner-images/issues/10721\n- ci: macos_ci.vsh\n- ci: fmt macos_ci.vsh\n- ci: use thew new macos_ci.vsh (github)\n- ci: improve output of macos_ci.vsh\n- ci: extract `ci/common/runner.v`, use it to simplify ci/macos_ci.vsh even more\n- ci: fix spurious failures for printing_struct_with_thread_field.vv on windows\n- net.http: ensure that http.download_file_with_progress/3 works (in a degraded mode), on windows,\n  even without passing `-d no_vschannel`\n- builder: fix cross compiling from linux to windows, when passing -g/-cg\n- docs: update the documentation of the @[console] tag, add advice to use `-subsystem windows`\n  instead\n- Make compare_pr_to_master.v use /opt/homebrew/bin/gtime on macos, and a pure V fallback, not just\n  for windows\n- ci,thirdparty: enable MBEDTLS_THREADING_PTHREAD and MBEDTLS_THREADING_C only on Linux for now (fix\n  windows CI)\n- thirdparty: enable MBEDTLS_THREADING_C and MBEDTLS_THREADING_PTHREAD on FreeBSD too\n- os: use _wputenv instead of _putenv to stay in sync with _wgetenv (fix changing env variables with\n  non ASCII content on windows) (#22920)\n- ci: avoid false positives for the existing PRs, by comment out the task\n  `V self compilation with -usecache` on macos for now (#23145)\n- ci: linux_ci.vsh; cgen: parallel-cc fixes\n- ci: remove extra EOL from linux_ci.yml (#23187)\n- Fix profile time on windows  (#23227)\n- docs: streamline the installation instructions and notes for Windows and Ubuntu\n- v.builder: fix errors in cstrict mode on OpenBSD with clang (#22154)\n- thirdparty: fix compilation of programs using miniz.h on macos\n- crypto.rand: fix compilation on macos with `-cc tcc -no-retry-compilation -gc none`\n- thirdparty: fix compilation of thirdparty/mbedtls with tcc on macos m1\n- v.pkgconfig: fix parser, when `includedir=` lines, had trailing spaces (fix `-d use_openssl` for\n  openssl 3.3.2 installed through brew on macos)\n- builtin: fix compilation with tcc on OpenBSD using libgc (#22234)\n- docs: add FreeBSD in cross compilation section (#22249)\n- v.builder: enable LTO for clang on OpenBSD (#22247)\n- thirdparty: fix compilation of programs using miniz.h on OpenBSD (#22254)\n- net: fix compilation on windows (use casts to int for net.error_eintr etc)\n- net: use explicit int casts for net.error_eintr etc in the unix implementation too for consistency\n  with the windows one\n- veb: support sendfile() syscall on FreeBSD (#21541)\n- os: use 1 instead of C.SW_SHOWNORMAL to workaround a cross compilation issue from linux to windows\n- v.builder: minimise the amount of linked libs for cross compilation to FreeBSD\n- v.builder: support downloading the FreeBSD cross compilation files on first use\n- Add a test for crosscompiling hw, on linux and macos, to FreeBSD (#21553)\n- vlib: make `./v -Wimpure-v -W test vlib/` pass on Linux (#21554)\n- os: fix debugger_present() for non Windows OSes (#21573)\n- ci: extend coverage, move app test from macos_ci to v_apps_and_modules_ci (#21584)\n- gc: fix tcc on macos\n- os.font: return the \"segoeui.ttf\" font, if its file exists on Windows (#21655)\n- readline: fix s := read_line('Message\\nName:') on unix/linux (#21930)\n- ci: improve test robustness on windows (#21116)\n- v.pkgconfig: add pkgconfig path `/usr/libdata/pkgconfig` for FreeBSD base packages (#21151)\n- v.util: add diff tool color support detection (tested on linux and freebsd) (#21244)\n- v.util.diff: return diff options with the diff command for FreeBSD/OpenBSD (#21271)\n- v.pkgconfig: fix load_paths with `;` split char on windows (#21291)\n- Fix vpm on macos, when using the bundled git executable (#21292)\n- ci: fix the bundled tcc for macos arm64 (#21299)\n- ci: update the runner for build-macos-arm64 to `macos-14` too, so it runs on M1\n- Fix hot code reloading on windows (#21351)\n- Fix building vpm on the FreeBSD instance, that runs fast.v\n- Fix `v install` for the FreeBSD instance that updates docs.vlang.io .\n- ci: use macos-13 for cross_ci.yml to force the old non m1 runner\n- v.builder: update macos->linux cross compile message (~22MB -> ~77MB)\n- v.pref: fix new pref test on FreeBSD (#21385)\n- ci: stop earlier on vc/v.c files, that may break on systems != linux (#21397)\n- Fix compilation on macos-arm with `-cstrict`; run macos ci also on the arm runner (#21408)\n- ci: use `v` instead of `./v` in the platform linux/macos/windows/_ci.yml files (#21454)\n- ci: add a retry to vcreate_init_test.v (it is sporadically flaky on macos)\n- sync,os,thirdparty: fix cross compilation from macos to windows (#21484)\n- os: rename os_structs_stat_windows.v to os_structs_stat_windows.c.v to fix\n  `v -Wimpure-v -os windows vlib/os/os_stat_test.v`\n- Default to `-cc clang` on FreeBSD in `cmd/tools/vtest_test.v` (#21534)\n- v.builder: allow for `v -shared -os windows file.v` on Linux/macos (fix #20445) (#20453)\n- Add windows dll support, fix (#20447) (#20459)\n- sync: add mutex.try*lock functions for FreeBSD too (#20482)\n- sync: fix FreeBSD implementation of sync functions (#20483)\n- os: make os.cache_dir() and os.vtmp_dir() more robust to parallel test executions on windows (\n  #20495)\n- builder: replace \"-rdynamic\" for clang on macos with \"-Wl,-export_dynamic\" (fix #20510) (#20511)\n- builder: restore ability to use tcc, without fallback to cc on macos\n- v.builder: use a more uniq prefix for the generated temporary file names, to further reduce the\n  chances of collision and sporadic CI failures on windows (#20551)\n- encoding.csv: fix bug in RandomAccessReader, spotted on windows with mingw32 (#20571)\n- builtin: use `#pkgconfig bdw-gc-threaded` where available, instead of `#pkgconfig bdw-gc` (on\n  FreeBSD)\n- db.pg: add include and lib paths for PostgreSQL on FreeBSD (#20582)\n- thirdparty: fix `v cmd/tools/vcompress.v` on FreeBSD\n- os: fix an error in Process.win_spawn_process, not using stdout pipe in a cmd environment on 32bit\n  Windows (#20613)\n- testing: retry 1 additional time sporadic silent test run failures on macos\n- builder: add '-lelf' to linker flags on freebsd (fix #20481) (#20643)\n- GNUmakefile: use standard default RM make variable to fix MSYS2 env on windows (#20701)\n- x.vweb: add the missing include for C.sendfile to sendfile_linux.c.v\n- clipboard: fix notice in clipboard_windows.c.v (#20733)\n- ci: update macos runners to macos-14, to make use of the much faster m1 instances (#20747)\n- builder: support musl-gcc on macos\n- builtin: link to user32 to fix boehm GC compilation on Windows with clang released from the LLVM\n  project (fix #20724) (#20767)\n- pref: download correct photonwrapper.so for linux (#20783)\n- ci: improve repo CI robustness, by marking dynamic_template_manager_cache_system_test.v as flaky,\n  and only failing db_store_test.v on !windows\n- tools.vpm: fix remove command on Windows, add test (#20852)\n- os: don't check rdev equality on FreeBSD, inside vlib/os/os_stat_test.v (#20885)\n- sync: support more gcc version specific search locations on linux with tcc\n- os: small cleanup in the FreeBSD branch of os.executable/0: use fixed array for the sysctl params,\n  instead of allocating a dynamic one (#20353)\n- os: improve os.executable() on OpenBSD (#20356)\n- v.util.diff: support OpenBSD's default `diff` tool (#20369)\n- os: fix os.open_file/3 `wb` mode creation of text files containing crlf on Windows (#20101)\n- os: fix File.tell for files > 2GB on windows, by using C._telli64(f.fd) (#20072)\n- builtin: use `libgc-threaded` on FreeBSD, to get the threaded version of libgc (#19294)\n\n#### Examples\n\n- Handle closing of the window in the event manager in examples/viewer (#25522)\n- ci: add a report-wrong-examples-in-doc-comments job, that runs\n  `./v doc -check-examples -f none vlib/` (#25554)\n- Make reproduction of failed examples easier (make sure that all the checked sources have an ending\n  \\n)\n- Use math.vec in path_tracing.v and in vyper.v\n- Support `v -d trace_execution run examples/brainvuck.v mandlebrot.bf`\n- ci: do not use `-silent` for the `v build-examples` task on windows, to make it easier to diagnose\n  recent gcc-windows timeouts\n- doc: add an example for reading from a non empty buffered channel, after closing it\n- Fix and improve vanilla_http_server (#25905)\n- ci: remove `-silent` from the macos build_examples task too, to make remote diagnosing of CI\n  timeouts easier\n- Add optional `update_fn: fn (dt f32, ctx &gg.Context)` to gg.Context and gg.Config . Pass\n  consistently the current GG context to *all* callback functions, instead of nil.\n- Add expanding_rect.v (modeled after the example from https://love2d.org/wiki/love), add generic\n  helpers gg.frgb/3 gg.frgba/4\n- tools,examples,veb: fix `v -d trace_before_request run examples/veb/veb_example.v` after feedback\n  from https://youtu.be/IuE6Bo1klK0?t=2100\n- Move flag/ .v files 1 level up, to prevent module lookup confusion for unrelated examples\n- Add a Lorem Ipsum Generator (#26036)\n- examples,net.ftp,v.builder: remove remaining matches of\n  `rg --multiline --multiline-dotall \"continue\\n\\t+\\}\\n\\t+\\}\\n\\t+return\" -B3 -A3 `\n- Update lorem.v with a Markov algorithm for better text generation (#26085)\n- fasthttp: fix the correctness of the minimal server example, when tested with curl (#26072)\n- v.gen.native: fix `v -os macos -experimental -b native -o hw.macos examples/hello_world.v` on\n  linux\n- tutorials: remove newline in the example for c2v's cc compilation to `doomv` (#26200)\n- Make all the labels fit in the default window size header in minesweeper.v\n- Fix for `v build-tools` and `v build-examples` running on a i686 (the problem was discovered by\n  @tankf33der)\n- Add examples/sokol/sounds/simple_keyboard_synth.v\n- builtin,markused: consider println of non string to use .str() method calls too, reduce generated\n  C code for `v -cc gcc examples/hello_world.v` (#24996)\n- Use a sieve of Eratosthenes in primes.v, to handle bigger inputs more efficiently\n- vdoc: make -run-examples compatible with all output modes, not just the plaintext one\n- vdoc: extract vdoc_run_examples_test.v from vdoc_file_test.v\n- vdoc: implement -unsafe-run-examples and -check-examples support, add tests and document them\n- builtin,vdoc: fix the examples for the builtin methods, so that\n  `v doc -check-examples -time -f ansi vlib/builtin/` pass\n- builtin,vdoc: make `v doc -unsafe-run-examples -time -f ansi vlib/builtin/` pass too\n- vdoc: improve failed example report\n- vdoc: support `v doc -check-examples -f none vlib/builtin`\n- bitfield: fix `v doc -unsafe-run-examples -f none vlib/bitfield/` too\n- arrays.parallel: fix `v doc -unsafe-run-examples -f none vlib/arrays/parallel/` too\n- arrays: fix `v doc -unsafe-run-examples -f none vlib/arrays/` too\n- compress.deflate,compress.gzip,compress.zlib,compress.zstd: fix\n  `v doc -unsafe-run-examples -f none vlib/compress/` too\n- sokol.audio: fix doc comment examples\n- encoding.base64: fix doc comment examples\n- math: fix doc comment examples\n- readline: fix doc comment example by removing it\n- semver: fix doc comment examples\n- vdoc: enable example lines that have explicit imports too, fixup the remaining vlib examples, so\n  `v doc -v -unsafe-run-examples -f none vlib/` could be added to the CI\n- Add euler.v\n- examples,gg: add examples/gg/grid_of_rectangles.v; add gg.Context.draw_rect_filled_no_context/5\n  and gg.Context.draw_rect_empty_no_context/5\n- veb.auth: update the README.md example (#25245)\n- builtin: fix `v -W -Wimpure-v examples/hello_world.v` (move ctovstring_impl to builtin.c.v)\n- Fix rune casting from u32 in rune.v (#25307)\n- Fix `v -os wasm32_emscripten -o ms.html examples/gg/minesweeper.v` (use os.asset to load the font,\n  avoid the implicit closures for the frame/event callbacks)'\n- Update rotating_textured_quad.v with instructions on how to compile/run it with emscripten and a\n  browser\n- Add a small examples/gg/bouncing_balls.v simulation of falling balls\n- Fetch 30 stories instead of 10 in examples/news_fetcher.v\n- Add sync_pool.v for easier testing/diagnosing issues with the `sync.pool` implementation on\n  different platforms\n- Add a `-profile` report column, to show only the func time, *excluding* the accumulated children\n  calls time (usable through `./v -profile - run a.v |sort -nk3` for example) (#24056)\n- doc: improve Shared and Channels's topics, add more examples (#24155)\n- orm: fix option type, convert from int to i8, add examples, etc (fix #24211) (#24213)\n- Fix optional callback parameter and improve examples (fix #24325) (#24336)\n- Reduce padding for code examples, to fit more examples on the same screen without scrolling\n- Cleanup unsafe{} blocks that are not needed anymore in examples/sokol/08_sdf/sdf.v\n- Show the number of pushes in sokoban too\n- os.asset: add read_text/2 too, use it to simplify the sokoban example\n- Support directly loading sokoban level files by path\n- Add more Sokoban levels\n- Support boxoban style collections of levels files (\n  from https://github.com/google-deepmind/boxoban-levels/)\n- Add a simple sudoku solver\n- Add primes.v, that shows how to get command line arguments, and use loops and functions\n- Add a small memory game (#24643)\n- Cleanup memory.v (reduce it to 135 lines)\n- builtin,os: enable no warnings for gg programs like\n  `v -gc boehm_leak -cg -keepc run examples/gg/minimal.v` (part 1 - before the `gg` loop) (#24749)\n- Allow for passing arbitrary compiler flags to `v bug`, for example: `v bug -cg -autofree file.v` (\n  #23335)\n- examples,builtin,cgen,live: fix windows hot reload with `-cc tcc`, improve the infrastructure, use\n  a V global instead of a C one (fix #23214) (#23350)\n- Fix unused db.pg import warning for examples/database/psql/customer.v\n- gg,sokol,examples: add example of overriding _SGL_DEFAULT_MAX_VERTICES in code\n- Mention also the RAM usage increase in many_thousands_of_circles_overriding_max_vertices.v\n- gg: enable clean compilation without notices for `./v -check-unused-fn-args examples/tetris/`\n- Add vascii.v showing a table of the first 128 ASCII characters with their names and codes in dec,\n  oct, hex, bin formats (#23466)\n- Add a solution to the \"1 Billion Row Challenge\" (#23458)\n- examples,io: add sha256sum_with_io_cp.v, make the size of the buffer used by io.cp\n  parametrisable (#23585)\n- log: add `log.use_stdout()`, use it to silence the transition note for the most commonly used V\n  tools/examples (#23642)\n- Implement an -s option for `v ast`, to skip all nodes with default values like [], {}, 0, false;\n  with it `v ast -pts examples/hello_world.v | wc -l` is 36 lines\n- gg: fix `./v -gc none -autofree run examples/tetris/` (avoid `return s1 + s2 + s3`, clone the\n  arrays, passed to the fontstash wrapper)\n- examples,gg: modify all remaining calls to fons.add_font_mem/3 to use an array.clone()\n- Add examples/hot_reload/tunnel.v\n- Add minimal_c_like_program_using_puts.v showing how to produce a much smaller executable on Linux,\n  using clang, mold and sstrip.\n- Build examples, that start with `module no_main` as well\n- ci: fix `v build-examples` failure on gcc-windows\n- Support `module no_main` based examples in `v should-compile-all`\n- term: make the second example in the README.md compilable as well\n- Show how to use a v file server for the wasm version of 2048, instead of emrun\n- sokol: allow for `v -os wasm32_emscripten -o examples/tetris/tetris.html examples/tetris/` (avoid\n  using `-sMODULARIZE`) (#23814)\n- Fix poll_coindesk_bitcoin_vs_usd_rate.v, use the new v2 API endpoint\n- math,examples: add examples/sokol/sounds/simple_sin_tone_using_audio_push.v, cleanup math\n- Add a small breakout game, supporting keyboard and touch controls (#23861)\n- Cleanup snek.v, by using `math.vec`, the builtin array support, instead of `datatypes`, and by\n  removing casts that are no longer needed\n- Fix `v -cstrict -cc gcc-11 examples/sokol/particles` and the same but with clang-18 too\n- Fix more compilation errors with `-cstrict -cc clang-18` for the sokol examples\n- Fix `VFLAGS='-no-skip-unused -cstrict -cc clang-18' v should-compile-all examples/sokol/` too\n- Add a small minesweeper game in examples/gg/minesweeper.v\n- Add a small Sokoban puzzle game with levels (see https://en.wikipedia.org/wiki/Sokoban)\n- Use textures in the sokoban game, instead of colors\n- Shorten the periodic output of examples/hot_reload/message.v\n- Fix (ball->side edge of brick) collision detection in breakout.v\n- Add subtle light and shadow effects to the breakout game, to give it a little depth (#23885)\n- Run the update method of breakout on its own frame independent rate\n- gg,examples: use a timer to limit the rate of updates in breakout, instead of a separate thread,\n  restore ability to run in a browser through emscripten\n- Make the tetris update rate, independent from the frame rate too\n- Make the 2048 game update rate, independent from the frame rate as well\n- Fix panic, discovered by fuzzing examples/2048/2048.v with zzuf on the CI\n- Add `vanilla_http_server` - a fast, multi-threaded, non-blocking, port and host reuse,\n  thread-safe, epoll server (#23094)\n- v.build_constraint: support comments too, for example `linux&&gcc // some comment`\n- Make `v repeat -R 5 -r 10 \"v run examples/hello_world.v\"` also show the time it took for all runs\n  in each repeat\n- Add an asteroids game (it is currently < 400 lines of V, using gg)\n- Remove the generic alias type overloaded operator workaround, after 29e60da\n- Fix `v should-compile-all examples/`\n- Fix some of the instructions in `examples/thread_safety/` (#22571)\n- builder,pref: fix `./v -os linux examples/json.v` on macos (#22651)\n- Add examples/assets/v.svg and examples/assets/v_16x16.svg\n- v.comptime: fix compilation of `examples/veb/veb_example.v` with V compiled with tcc on macos\n- ci: ensure that all examples can still be compiled, by `v` compiled with tcc on macos\n- Add poll_coindesk_bitcoin_vs_usd_rate.v\n- Simplify and reorder output of poll_coindesk_bitcoin_vs_usd_rate.v\n- builtin: fix `v -skip-unused -cc tcc examples/hello_world.v` on *BSD\n- net.mbedtls: bump mbedtls_ssl_conf_read_timeout value to 550ms (tested with\n  `v run examples/net_t.v`)\n- Add a cpu_features/ folder, with several examples, using SSE and MMX assembly instructions (\n  #22645)\n- v.builder: fix `./v -check -stats examples/hello_world.v`\n- docs: add a small sumtype match example in the Match section too\n- Add TextScanner .skip_whitespace/0, .peek_u8/0, .peek_n_u8/0, add\n  examples/mini_calculator_recursive_descent.v (#23001)\n- Reduce completion friction, when doing the very common `v run examples/hello_world.v` in a shell\n- Remove drag_n_drop.v from the list of examples, that are checked for visual differences with\n  vgret, since it now uses the default gg font\n- docs: add more C interop notes and examples (#21965)\n- cleanup obsolete unsafe{} usages in examples/sokol/sounds\n- cleanup & fix the sound produced by melody.v\n- add a simplified bytebeat player to show how to use sokol.audio, and that does not depend on gg\n- make `rotating_textured_quad.v` compile and run on Android (#21987)\n- veb: change example description, to avoid repetitive wording (ease debugging of issue#22017)\n- eval: fix `./v interpret examples/hanoi.v`\n- add examples/ttf_font/draw_static_text.v, to make it easier to test x.ttf with different fonts,\n  and texts\n- make draw_static_text.v show the font name too, for easier comparisons\n- prevent cliping of long font names in draw_static_text.v\n- docs: add an example on how to use Options/Results, when returning multiple values from a\n  function (#22099)\n- add examples/gg/draw_unicode_text_with_gg.v, for easy comparison of how different fonts and\n  unicode texts will look, when rendered by gg\n- add examples/veb/websocket, to show how to use http connection upgrade to a websocket, from a\n  `veb` route (#22128)\n- migrate vweb examples to veb\n- fix type in veb_example.v\n- add `gc_is_enabled()` check to `2048` to prevent crash in Android emulator (#22274)\n- make `gg/rectangles.v` Android friendly (#22275)\n- make `gg/stars.v` run on android (#22276)\n- examples,os: add an os.asset module, use it to simplify code in examples/, by removing\n  `$if android {` checks (#22281)\n- add a consistent background to flappylearning, shown when the height of the view is very high (on\n  Android)\n- encoding.xml: make functions public, add documentation, tests, fix attribute parsing for\n  self-closing tags  (#19901)\n- examples: show how to turn on CORS in a vweb server app\n- examples: serve the wasm mandelbrot project using a v web server (#19937)\n- examples: increase the resolution of the generated image in examples/wasm/mandelbrot\n- docs: update null convention in ORM example, since `@[nonull]` is no longer needed (#20286)\n- docs: add an example of a nullable ORM field (#20292)\n- example: add a path finding algorithm visualizer using gg (#20060)\n- examples: add an even smaller gg usage example, demonstrating how to always show the builtin fps\n  counter, and how to avoid importing gx\n- tests: workaround name conflict, causing false positives with msvc on windows, when both tests\n  were executed at the same time (locked executable)\n- examples: add more .obj files for 06_obj_viewer (#19406)\n\n"
  },
  {
    "path": "ci/common/runner.v",
    "content": "module common\n\nimport os\nimport log\nimport term\nimport time\n\n// exec is a helper function, to execute commands and exit early, if they fail.\npub fn exec(command string) {\n\tlog.info('cmd: ${command}')\n\tresult := os.system(command)\n\tif result != 0 {\n\t\texit(result)\n\t}\n}\n\n// unset is a helper function to unset a specific env variable.\npub fn unset(evar string) {\n\tlog.info('unsetting env variable: ${evar}')\n\tos.unsetenv(evar)\n}\n\n// file_size_greater_than asserts that the given file exists, and is at least min_fsize bytes long.\npub fn file_size_greater_than(fpath string, min_fsize u64) {\n\tlog.info('path should exist `${fpath}` ...')\n\tif !os.exists(fpath) {\n\t\texit(1)\n\t}\n\tlog.info('path exists, and should be a file: `${fpath}` ...')\n\tif !os.is_file(fpath) {\n\t\texit(2)\n\t}\n\treal_size := os.file_size(fpath)\n\tlog.info('actual file size of `${fpath}` is ${real_size}, wanted: ${min_fsize}, diff: ${real_size - min_fsize}.')\n\tif real_size < min_fsize {\n\t\texit(3)\n\t}\n}\n\nconst self_command = 'v ' +\n\tos.real_path(os.executable()).replace_once(os.real_path(@VEXEROOT), '').trim_left('/\\\\') +\n\t'.vsh'\n\npub const is_github_job = os.getenv('GITHUB_JOB') != ''\n\npub type Fn = fn ()\n\npub struct Task {\npub mut:\n\tf     Fn = unsafe { nil }\n\tlabel string\n}\n\npub fn (t Task) run(tname string) {\n\tcmd := '${self_command} ${tname}'\n\tlog.info('Start ${term.colorize(term.yellow, t.label)}, cmd: `${cmd}`')\n\tstart := time.now()\n\tt.f()\n\tdt := time.now() - start\n\tlog.info('Finished ${term.colorize(term.yellow, t.label)} in ${dt.milliseconds()} ms, cmd: `${cmd}`')\n\tprintln('')\n}\n\npub fn run(all_tasks map[string]Task) {\n\tunbuffer_stdout()\n\tlog.use_stdout()\n\tif os.args.len < 2 {\n\t\tprintln('Usage: v run macos_ci.vsh <task_name>')\n\t\tprintln('Available tasks are: ${all_tasks.keys()}')\n\t\texit(0)\n\t}\n\ttask_name := os.args[1]\n\tif task_name == 'all' {\n\t\tlog.info(term.colorize(term.green, 'Run everything...'))\n\t\tmut failed_tasks := []string{}\n\t\tfor tname, t in all_tasks {\n\t\t\tcmd := '${self_command} ${tname}'\n\t\t\tlog.info('Start ${term.colorize(term.yellow, t.label)}, cmd: `${cmd}`')\n\t\t\tstart := time.now()\n\t\t\tresult := os.system(cmd)\n\t\t\tdt := time.now() - start\n\t\t\tif result != 0 {\n\t\t\t\tlog.error('FAILED ${term.colorize(term.red, t.label)} in ${dt.milliseconds()} ms, cmd: `${cmd}`')\n\t\t\t\tfailed_tasks << tname\n\t\t\t} else {\n\t\t\t\tlog.info('Finished ${term.colorize(term.yellow, t.label)} in ${dt.milliseconds()} ms, cmd: `${cmd}`')\n\t\t\t}\n\t\t}\n\t\tif failed_tasks.len > 0 {\n\t\t\tlog.error('${failed_tasks.len} task(s) failed: ${failed_tasks}')\n\t\t\texit(1)\n\t\t}\n\t\texit(0)\n\t}\n\tt := all_tasks[task_name] or {\n\t\teprintln('Unknown task with name: `${task_name}`')\n\t\texit(1)\n\t}\n\tt.run(task_name)\n}\n"
  },
  {
    "path": "ci/freebsd_ci.vsh",
    "content": "import os\nimport common { Task, exec }\n\nfn v_doctor() {\n\tprintln('### vdoctor')\n\tdump(os.getenv('PATH'))\n\texec('v doctor')\n\tif common.is_github_job {\n\t\texec('freebsd-version')\n\t\texec('sysctl hw.model')\n\t\texec('sysctl hw.ncpu')\n\t\texec('sysctl hw.physmem')\n\t\texec('sysctl hw.usermem')\n\t\texec('whoami')\n\t\texec('pwd')\n\t\texec('ls -la')\n\t\texec('git log -n1')\n\t\texec('cc --version')\n\t}\n}\n\nfn build_v_with_prealloc() {\n\tprintln('### Build v with prealloc')\n\texec('v -cg -cstrict -o vstrict1 cmd/v')\n\texec('./vstrict1 -o vprealloc -prealloc cmd/v')\n\texec('./vprealloc run examples/hello_world.v')\n\texec('./vprealloc -o v3 cmd/v')\n\texec('./v3 -o v4 cmd/v')\n\texec('./v4 -d debug_malloc -d debug_realloc -o vdebug1 cmd/v')\n}\n\nfn verify_v_test_works() {\n\tprintln('### Verify v test')\n\texec('echo \\$VFLAGS')\n\texec('v cmd/tools/test_if_v_test_system_works.v')\n\texec('./cmd/tools/test_if_v_test_system_works')\n}\n\nfn build_fast_script() {\n\tprintln('### Build fast script')\n\texec('cd cmd/tools/fast && v fast.v')\n}\n\nfn check_math() {\n\tprintln('### Test vlib/math')\n\texec('v -silent test vlib/math')\n\tprintln('Test the math module, using only the pure V versions,')\n\tprintln('                          without the .c.v overrides.')\n\texec('v -silent -exclude @vlib/math/*.c.v test vlib/math')\n}\n\nfn test_inline_assembly() {\n\tprintln('### Test inline Assembly')\n\texec('v test vlib/v/slow_tests/assembly')\n}\n\nfn check_compress() {\n\tprintln('### Test vlib/compress')\n\texec('v -silent test vlib/compress')\n}\n\nfn run_essential_tests() {\n\tif common.is_github_job {\n\t\tprintln('### Run essential tests')\n\t\texec('VTEST_JUST_ESSENTIAL=1 v -silent test-self')\n\t} else {\n\t\texec('VTEST_JUST_ESSENTIAL=1 v -progress test-self')\n\t}\n}\n\nfn build_examples() {\n\tif common.is_github_job {\n\t\tprintln('### Build examples')\n\t\texec('v -W build-examples')\n\t} else {\n\t\texec('v -progress build-examples')\n\t}\n}\n\nconst all_tasks = {\n\t'v_doctor':              Task{v_doctor, 'Run v doctor'}\n\t'build_v_with_prealloc': Task{build_v_with_prealloc, 'Build V with prealloc'}\n\t'verify_v_test_works':   Task{verify_v_test_works, 'Verify that v test works'}\n\t'build_fast_script':     Task{build_fast_script, 'Check that building fast.v works'}\n\t'check_math':            Task{check_math, 'Check the `math` module works'}\n\t'check_compress':        Task{check_compress, 'Check the `compress` module works'}\n\t'test_inline_assembly':  Task{test_inline_assembly, 'Test inline Assembly'}\n\t'run_essential_tests':   Task{run_essential_tests, 'Run only the essential tests'}\n\t'build_examples':        Task{build_examples, 'Build examples'}\n}\n\ncommon.run(all_tasks)\n"
  },
  {
    "path": "ci/linux_ci.vsh",
    "content": "import common { Task, exec }\n\n// Shared tasks/helpers\nfn all_code_is_formatted() {\n\tif common.is_github_job {\n\t\texec('v -silent test-cleancode')\n\t} else {\n\t\texec('v -progress test-cleancode')\n\t}\n}\n\nfn verify_v_test_works() {\n\texec('echo \\$VFLAGS')\n\texec('v cmd/tools/test_if_v_test_system_works.v')\n\texec('./cmd/tools/test_if_v_test_system_works')\n}\n\nfn test_pure_v_math_module() {\n\texec('v -exclude @vlib/math/*.c.v test vlib/math/')\n}\n\nfn self_tests() {\n\tif common.is_github_job {\n\t\texec('v -W -silent test-self vlib')\n\t} else {\n\t\texec('v -progress test-self vlib')\n\t}\n}\n\nfn build_examples() {\n\tif common.is_github_job {\n\t\texec('v -W build-examples')\n\t} else {\n\t\texec('v -progress build-examples')\n\t}\n}\n\nfn v_doctor() {\n\texec('v doctor')\n}\n\nfn build_v_with_prealloc() {\n\texec('v -cg -cstrict -o vstrict1 cmd/v')\n\texec('./vstrict1 -o vprealloc -prealloc cmd/v')\n\texec('./vprealloc run examples/hello_world.v')\n\texec('./vprealloc -o v3 cmd/v')\n\texec('./v3 -o v4 cmd/v')\n\texec('./v4 -d debug_malloc -d debug_realloc -o vdebug1 cmd/v')\n}\n\n// TCC job tasks\nfn install_dependencies_for_examples_and_tools_tcc() {\n\tif common.is_github_job {\n\t\texec('.github/workflows/disable_azure_mirror.sh')\n\t}\n\texec('v retry -- sudo apt update')\n\texec('v retry -- sudo apt install --quiet -y libssl-dev sqlite3 libsqlite3-dev valgrind')\n\texec('v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev')\n\t// Wayland development libraries for sokol Wayland support\n\texec('v retry -- sudo apt install --quiet -y libwayland-dev libxkbcommon-dev libwayland-egl1-mesa libxkbcommon-x11-dev')\n\t// The following is needed for examples/wkhtmltopdf.v\n\texec('v retry -- sudo apt install --quiet -y xfonts-75dpi xfonts-base expect')\n\texec('v retry -- wget --quiet https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-2/wkhtmltox_0.12.6.1-2.jammy_amd64.deb')\n\texec('v retry -- sudo dpkg -i wkhtmltox_0.12.6.1-2.jammy_amd64.deb')\n}\n\nfn test_v_to_c_tcc() {\n\texec('thirdparty/tcc/tcc.exe -version')\n\texec('v -cg -o vtcc cmd/v') // ensure vtcc can build itself twice\n}\n\nfn v_self_compilation_tcc() {\n\texec('v -o v2 cmd/v')\n\texec('./v2 -o v3 cmd/v')\n\texec('./v3 -o v4 cmd/v')\n}\n\nfn v_doctor_tcc() {\n\tv_doctor()\n}\n\nfn verify_v_test_works_tcc() {\n\tverify_v_test_works()\n}\n\nfn test_pure_v_math_module_tcc() {\n\ttest_pure_v_math_module()\n}\n\nfn self_tests_tcc() {\n\texec('v -keepc -cc tcc -g self')\n\tself_tests()\n}\n\nfn build_examples_tcc() {\n\tbuild_examples()\n}\n\nfn run_submodule_example_tcc() {\n\texec('v -W run examples/submodule')\n}\n\nfn build_tools_tcc() {\n\tif common.is_github_job {\n\t\texec('v -N -W build-tools')\n\t} else {\n\t\texec('v -progress -N -W build-tools')\n\t}\n}\n\nfn build_vbinaries_tcc() {\n\texec('v -N -W build-vbinaries')\n}\n\nfn build_benches_tcc() {\n\texec('v should-compile-all vlib/v/tests/bench/')\n}\n\nfn run_vsh_script_tcc() {\n\texec('v run examples/v_script.vsh')\n}\n\nfn test_v_tutorials_tcc() {\n\texec('v tutorials/building_a_simple_web_blog_with_veb/code/blog')\n}\n\nfn build_fast_tcc() {\n\texec('cd cmd/tools/fast && v fast.v')\n\texec('cd cmd/tools/fast && ./fast')\n}\n\nfn v_self_compilation_usecache_tcc() {\n\t$if !enable_usecache_test ? {\n\t\teprintln('> ${@LOCATION} use `-d enable_usecache_test` in VFLAGS to enable this task')\n\t\treturn\n\t}\n\texec('v wipe-cache')\n\texec('v -usecache examples/hello_world.v')\n\texec('./examples/hello_world')\n\n\texec('v wipe-cache')\n\texec('v -o v2 -usecache cmd/v')\n\texec('./v2 -o v3 -usecache cmd/v')\n\texec('./v3 version')\n\n\texec('v wipe-cache')\n\texec('./v3 -o tetris -usecache examples/tetris/tetris.v')\n\texec('rm -f ./examples/hello_world v2 v3 tetris')\n}\n\nfn test_password_input_tcc() {\n\texec('v test examples/password/')\n}\n\nfn test_readline_tcc() {\n\texec('v test examples/readline/')\n}\n\nfn test_leak_detector_tcc() {\n\texec('v -gc boehm_leak -o testcase_leak vlib/v/tests/testcase_leak.vv')\n\texec('./testcase_leak 2>leaks.txt')\n\texec('grep \"Found 1 leaked object\" leaks.txt')\n\texec('grep -P \", sz=\\\\s?1000,\" leaks.txt')\n}\n\nfn test_leak_detector_not_active_tcc() {\n\texec('v -o testcase_leak vlib/v/tests/testcase_leak.vv')\n\texec('./testcase_leak 2>leaks.txt')\n\texec('[ \"$(stat -c %s leaks.txt)\" = \"0\" ]')\n}\n\n// GCC job tasks\nfn all_code_is_formatted_gcc() {\n\tall_code_is_formatted()\n}\n\nfn install_dependencies_for_examples_and_tools_gcc() {\n\tif common.is_github_job {\n\t\texec('.github/workflows/disable_azure_mirror.sh')\n\t}\n\texec('v retry -- sudo apt update')\n\texec('v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind')\n\texec('v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev')\n\t// Wayland development libraries for sokol Wayland support\n\texec('v retry -- sudo apt install --quiet -y libwayland-dev libxkbcommon-dev libwayland-egl1-mesa libxkbcommon-x11-dev wayland-protocols libegl-dev')\n}\n\nfn recompile_v_with_cstrict_gcc() {\n\texec('v -cc gcc -cg -cstrict -o vstrict cmd/v')\n}\n\nfn valgrind_v_c_gcc() {\n\texec('valgrind --error-exitcode=1 v -o v.c cmd/v')\n}\n\nfn run_sanitizers_gcc() {\n\texec('v -o v2 cmd/v -cflags -fsanitize=thread')\n\texec('v -o v3 cmd/v -cflags \"-fsanitize=undefined -fno-sanitize=alignment\"')\n\texec('UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 ./v2 -o v.c cmd/v')\n\texec('UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 ./v3 -o v.c cmd/v')\n}\n\nfn v_self_compilation_gcc() {\n\texec('v -o v2 cmd/v')\n\texec('./v2 -o v3 cmd/v')\n\texec('./v3 -o v4 cmd/v')\n}\n\nfn v_self_compilation_usecache_gcc() {\n\t$if !enable_usecache_test ? {\n\t\teprintln('> ${@LOCATION} use `-d enable_usecache_test` in VFLAGS to enable this task')\n\t\treturn\n\t}\n\texec('v wipe-cache')\n\texec('v -usecache examples/hello_world.v')\n\texec('examples/hello_world')\n\n\texec('v wipe-cache')\n\texec('v -o v2 -usecache cmd/v')\n\texec('./v2 -o v3 -usecache cmd/v')\n\texec('./v3 version')\n\n\texec('v wipe-cache')\n\texec('./v3 -o tetris -usecache examples/tetris/tetris.v')\n\texec('rm -f ./examples/hello_world v2 v3 tetris')\n}\n\nfn verify_v_test_works_gcc() {\n\tverify_v_test_works()\n}\n\nfn test_pure_v_math_module_gcc() {\n\ttest_pure_v_math_module()\n}\n\nfn self_tests_gcc() {\n\tself_tests()\n}\n\nfn self_tests_prod_gcc() {\n\texec('v -o vprod -prod cmd/v')\n\texec('./vprod -silent test-self vlib')\n}\n\nfn self_tests_cstrict_gcc() {\n\texec('VTEST_JUST_ESSENTIAL=1 V_CI_CSTRICT=1 v -cc gcc -cstrict -silent test-self vlib')\n}\n\nfn build_examples_gcc() {\n\tbuild_examples()\n}\n\nfn build_tetris_autofree_gcc() {\n\texec('v -autofree -o tetris examples/tetris/tetris.v')\n\texec('rm -f tetris')\n}\n\nfn build_blog_autofree_gcc() {\n\texec('v -autofree -o blog tutorials/building_a_simple_web_blog_with_veb/code/blog')\n\texec('rm -f blog')\n}\n\nfn build_option_test_autofree_gcc() {\n\texec('v -autofree vlib/v/tests/options/option_test.c.v')\n}\n\nfn v_self_compilation_parallel_cc_gcc() {\n\texec('v -o v2 -parallel-cc cmd/v')\n\texec('rm -f v2')\n}\n\nfn build_modules_gcc() {\n\texec('v build-module vlib/os')\n\texec('v build-module vlib/builtin')\n\texec('v build-module vlib/strconv')\n\texec('v build-module vlib/time')\n\texec('v build-module vlib/term')\n\texec('v build-module vlib/math')\n\texec('v build-module vlib/strings')\n\texec('v build-module vlib/v/token')\n\texec('v build-module vlib/v/ast')\n\texec('v build-module vlib/v/parser')\n\texec('v build-module vlib/v/gen/c')\n\texec('v build-module vlib/v/depgraph')\n\texec('v build-module vlib/os/cmdline')\n}\n\nfn compile_vdoctor_prod_gcc() {\n\texec('v -showcc -cc gcc -prod cmd/tools/vdoctor.v')\n}\n\nfn compile_vup_prod_gcc() {\n\texec('v -showcc -cc gcc -prod cmd/tools/vup.v')\n}\n\n// Clang job tasks\nfn all_code_is_formatted_clang() {\n\tall_code_is_formatted()\n}\n\nfn install_dependencies_for_examples_and_tools_clang() {\n\tif common.is_github_job {\n\t\texec('.github/workflows/disable_azure_mirror.sh')\n\t}\n\texec('v retry -- sudo apt update')\n\texec('v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind')\n\texec('v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev')\n\t// Wayland development libraries for sokol Wayland support\n\texec('v retry -- sudo apt install --quiet -y libwayland-dev libxkbcommon-dev libwayland-egl1-mesa libxkbcommon-x11-dev wayland-protocols libegl-dev')\n\texec('v retry -- sudo apt install --quiet -y clang')\n}\n\nfn recompile_v_with_cstrict_clang() {\n\texec('v -cc clang -cg -cstrict -o vstrict cmd/v')\n\texec('rm -f vstrict')\n}\n\nfn valgrind_clang() {\n\texec('valgrind --error-exitcode=1 v -o v.c cmd/v')\n\texec('rm -f v.c')\n}\n\nfn run_sanitizers_clang() {\n\texec('.github/workflows/run_sanitizers.sh')\n}\n\nfn v_self_compilation_clang() {\n\texec('v -o v2 cmd/v')\n\texec('./v2 -o v3 cmd/v')\n\texec('./v3 -o v4 cmd/v')\n}\n\nfn v_self_compilation_usecache_clang() {\n\t$if !enable_usecache_test ? {\n\t\teprintln('> ${@LOCATION} use `-d enable_usecache_test` in VFLAGS to enable this task')\n\t\treturn\n\t}\n\texec('v wipe-cache')\n\texec('v -usecache examples/hello_world.v')\n\texec('./examples/hello_world')\n\n\texec('v wipe-cache')\n\texec('v -o v2 -usecache cmd/v')\n\texec('./v2 -o v3 -usecache cmd/v')\n\texec('./v3 version')\n\n\texec('v wipe-cache')\n\texec('./v3 -o tetris -usecache examples/tetris/tetris.v')\n\texec('rm -f ./examples/hello_world v2 v3 tetris')\n}\n\nfn verify_v_test_works_clang() {\n\tverify_v_test_works()\n}\n\nfn test_pure_v_math_module_clang() {\n\ttest_pure_v_math_module()\n}\n\nfn self_tests_clang() {\n\tself_tests()\n}\n\nfn self_tests_vprod_clang() {\n\texec('v -o vprod -prod cmd/v')\n\texec('./vprod -silent test-self vlib')\n}\n\nfn self_tests_cstrict_clang() {\n\texec('VTEST_JUST_ESSENTIAL=1 V_CI_CSTRICT=1 ./vprod -cstrict -silent test-self vlib')\n}\n\nfn build_examples_clang() {\n\tbuild_examples()\n}\n\nfn build_examples_autofree_clang() {\n\texec('v -N -W -autofree -experimental -o tetris examples/tetris/tetris.v')\n\texec('rm -f tetris')\n}\n\nfn build_modules_clang() {\n\texec('v build-module vlib/os')\n\texec('v build-module vlib/builtin')\n\texec('v build-module vlib/strconv')\n\texec('v build-module vlib/time')\n\texec('v build-module vlib/term')\n\texec('v build-module vlib/math')\n\texec('v build-module vlib/strings')\n\texec('v build-module vlib/v/token')\n\texec('v build-module vlib/v/ast')\n\texec('v build-module vlib/v/parser')\n\texec('v build-module vlib/v/gen/c')\n\texec('v build-module vlib/v/depgraph')\n\texec('v build-module vlib/os/cmdline')\n}\n\nfn native_machine_code_generation_common() {\n\texec('cd cmd/tools && v gen1m.v')\n\texec('cd cmd/tools && ./gen1m > 1m.v')\n\texec('cd cmd/tools && v -backend native -o 1m 1m.v')\n\texec('cd cmd/tools && ./1m && ls -larS 1m*')\n\texec('cd cmd/tools && rm -f ./1m ./1m.v')\n}\n\nfn native_machine_code_generation_gcc() {\n\tnative_machine_code_generation_common()\n}\n\nfn native_machine_code_generation_clang() {\n\tnative_machine_code_generation_common()\n}\n\nfn native_cross_compilation_to_macos() {\n\texec('v -os macos -experimental -b native -o hw.macos examples/hello_world.v')\n\tcommon.file_size_greater_than('hw.macos', 8000)\n\texec('rm -f hw.macos')\n}\n\nfn test_inline_assembly() {\n\texec('v test vlib/v/slow_tests/assembly')\n}\n\n// Collect all tasks\nconst all_tasks = {\n\t'build_v_with_prealloc':                             Task{build_v_with_prealloc, 'Build V with prealloc'}\n\t// tcc tasks\n\t'all_code_is_formatted_tcc':                         Task{all_code_is_formatted, 'All code is formatted (tcc)'}\n\t'install_dependencies_for_examples_and_tools_tcc':   Task{install_dependencies_for_examples_and_tools_tcc, 'Install deps for examples/tools (tcc)'}\n\t'test_v_to_c_tcc':                                   Task{test_v_to_c_tcc, 'Test v->c with tcc'}\n\t'v_self_compilation_tcc':                            Task{v_self_compilation_tcc, 'V self compilation (tcc)'}\n\t'v_doctor_tcc':                                      Task{v_doctor_tcc, 'v doctor (tcc)'}\n\t'verify_v_test_works_tcc':                           Task{verify_v_test_works_tcc, 'Verify `v test` works (tcc)'}\n\t'test_pure_v_math_module_tcc':                       Task{test_pure_v_math_module_tcc, 'Test pure V math module (tcc)'}\n\t'self_tests_tcc':                                    Task{self_tests_tcc, 'Self tests (tcc)'}\n\t'build_examples_tcc':                                Task{build_examples_tcc, 'Build examples (tcc)'}\n\t'run_submodule_example_tcc':                         Task{run_submodule_example_tcc, 'Run submodule example (tcc)'}\n\t'build_tools_tcc':                                   Task{build_tools_tcc, 'Build V tools (tcc)'}\n\t'build_vbinaries_tcc':                               Task{build_vbinaries_tcc, 'Build V binaries (tcc)'}\n\t'build_benches_tcc':                                 Task{build_benches_tcc, 'Build benches (tcc)'}\n\t'run_vsh_script_tcc':                                Task{run_vsh_script_tcc, 'Run a VSH script (tcc)'}\n\t'test_v_tutorials_tcc':                              Task{test_v_tutorials_tcc, 'Test V tutorials (tcc)'}\n\t'build_fast_tcc':                                    Task{build_fast_tcc, 'Build cmd/tools/fast (tcc)'}\n\t'v_self_compilation_usecache_tcc':                   Task{v_self_compilation_usecache_tcc, 'V self compilation with -usecache (tcc)'}\n\t'test_password_input_tcc':                           Task{test_password_input_tcc, 'Test password input (tcc)'}\n\t'test_readline_tcc':                                 Task{test_readline_tcc, 'Test readline (tcc)'}\n\t'test_leak_detector_tcc':                            Task{test_leak_detector_tcc, 'Test leak detector (tcc)'}\n\t'test_leak_detector_not_active_tcc':                 Task{test_leak_detector_not_active_tcc, 'Test leak detector not active (tcc)'}\n\t// gcc tasks\n\t'all_code_is_formatted_gcc':                         Task{all_code_is_formatted_gcc, 'All code is formatted (gcc)'}\n\t'install_dependencies_for_examples_and_tools_gcc':   Task{install_dependencies_for_examples_and_tools_gcc, 'Install deps for examples/tools (gcc)'}\n\t'recompile_v_with_cstrict_gcc':                      Task{recompile_v_with_cstrict_gcc, 'Recompile V with -cstrict and gcc'}\n\t'valgrind_v_c_gcc':                                  Task{valgrind_v_c_gcc, 'Valgrind v.c (gcc)'}\n\t'run_sanitizers_gcc':                                Task{run_sanitizers_gcc, 'Run sanitizers (gcc)'}\n\t'v_self_compilation_gcc':                            Task{v_self_compilation_gcc, 'V self compilation (gcc)'}\n\t'v_self_compilation_usecache_gcc':                   Task{v_self_compilation_usecache_gcc, 'V self compilation with -usecache (gcc)'}\n\t'verify_v_test_works_gcc':                           Task{verify_v_test_works_gcc, 'Verify `v test` works (gcc)'}\n\t'test_pure_v_math_module_gcc':                       Task{test_pure_v_math_module_gcc, 'Test pure V math module (gcc)'}\n\t'self_tests_gcc':                                    Task{self_tests_gcc, 'Self tests (gcc)'}\n\t'self_tests_prod_gcc':                               Task{self_tests_prod_gcc, 'Self tests (-prod) (gcc)'}\n\t'self_tests_cstrict_gcc':                            Task{self_tests_cstrict_gcc, 'Self tests (-cstrict) (gcc)'}\n\t'build_examples_gcc':                                Task{build_examples_gcc, 'Build examples (gcc)'}\n\t'build_tetris_autofree_gcc':                         Task{build_tetris_autofree_gcc, 'Build tetris with -autofree (gcc)'}\n\t'build_blog_autofree_gcc':                           Task{build_blog_autofree_gcc, 'Build blog tutorial with -autofree (gcc)'}\n\t'build_option_test_autofree_gcc':                    Task{build_option_test_autofree_gcc, 'Build option_test.c.v with -autofree (gcc)'}\n\t'v_self_compilation_parallel_cc_gcc':                Task{v_self_compilation_parallel_cc_gcc, 'V self compilation with -parallel-cc (gcc)'}\n\t'build_modules_gcc':                                 Task{build_modules_gcc, 'Build modules (gcc)'}\n\t'compile_vdoctor_prod_gcc':                          Task{compile_vdoctor_prod_gcc, 'compile vdoctor with -prod (gcc)'}\n\t'compile_vup_prod_gcc':                              Task{compile_vup_prod_gcc, 'compile vup with -prod (gcc)'}\n\t// clang tasks\n\t'all_code_is_formatted_clang':                       Task{all_code_is_formatted_clang, 'All code is formatted (clang)'}\n\t'install_dependencies_for_examples_and_tools_clang': Task{install_dependencies_for_examples_and_tools_clang, 'Install deps for examples/tools (clang)'}\n\t'recompile_v_with_cstrict_clang':                    Task{recompile_v_with_cstrict_clang, 'Recompile V with -cstrict and clang'}\n\t'valgrind_clang':                                    Task{valgrind_clang, 'Valgrind (clang)'}\n\t'run_sanitizers_clang':                              Task{run_sanitizers_clang, 'Run sanitizers (clang)'}\n\t'v_self_compilation_clang':                          Task{v_self_compilation_clang, 'V self compilation (clang)'}\n\t'v_self_compilation_usecache_clang':                 Task{v_self_compilation_usecache_clang, 'V self compilation with -usecache (clang)'}\n\t'verify_v_test_works_clang':                         Task{verify_v_test_works_clang, 'Verify `v test` works (clang)'}\n\t'test_pure_v_math_module_clang':                     Task{test_pure_v_math_module_clang, 'Test pure V math module (clang)'}\n\t'self_tests_clang':                                  Task{self_tests_clang, 'Self tests (clang)'}\n\t'self_tests_vprod_clang':                            Task{self_tests_vprod_clang, 'Self tests (vprod) (clang)'}\n\t'self_tests_cstrict_clang':                          Task{self_tests_cstrict_clang, 'Self tests (-cstrict) (clang)'}\n\t'build_examples_clang':                              Task{build_examples_clang, 'Build examples (clang)'}\n\t'build_examples_autofree_clang':                     Task{build_examples_autofree_clang, 'Build examples with -autofree (clang)'}\n\t'build_modules_clang':                               Task{build_modules_clang, 'Build modules (clang)'}\n\t'native_machine_code_generation_clang':              Task{native_machine_code_generation_clang, 'native machine code generation (clang)'}\n\t'native_machine_code_generation_gcc':                Task{native_machine_code_generation_gcc, 'native machine code generation (gcc)'}\n\t'native_cross_compilation_to_macos':                 Task{native_cross_compilation_to_macos, 'native cross compilation to macos'}\n\t'test_inline_assembly':                              Task{test_inline_assembly, 'Test inline assembly'}\n}\n\ncommon.run(all_tasks)\n"
  },
  {
    "path": "ci/macos_ci.vsh",
    "content": "import common { Task, exec }\n\nfn test_symlink() {\n\texec('v symlink')\n}\n\nfn test_cross_compilation() {\n\texec('v -o hw -os linux examples/hello_world.v && ls -la hw && file hw')\n\texec('v -d use_openssl -o ve -os linux examples/veb/veb_example.v && ls -la ve && file ve')\n}\n\nfn build_with_cstrict() {\n\texec('v -cg -cstrict -o vstrict1 cmd/v')\n}\n\nfn all_code_is_formatted() {\n\tif common.is_github_job {\n\t\texec('VJOBS=1 v -silent test-cleancode')\n\t} else {\n\t\texec('v -progress test-cleancode')\n\t}\n}\n\nfn run_sanitizers() {\n\texec('v -o v2 cmd/v -cflags -fsanitize=undefined')\n\texec('UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 ./v2 -o v.c cmd/v')\n}\n\nfn build_using_v() {\n\texec('v -o v2 cmd/v')\n\texec('./v2 -o v3 cmd/v')\n}\n\nfn verify_v_test_works() {\n\texec('echo \\$VFLAGS')\n\texec('v cmd/tools/test_if_v_test_system_works.v')\n\texec('./cmd/tools/test_if_v_test_system_works')\n}\n\nfn install_iconv() {\n\texec('brew install libiconv')\n}\n\nfn test_pure_v_math_module() {\n\texec('v -silent -exclude @vlib/math/*.c.v test vlib/math/')\n}\n\nfn self_tests() {\n\tif common.is_github_job {\n\t\texec('VJOBS=1 v -silent test-self vlib')\n\t} else {\n\t\texec('v -progress test-self vlib')\n\t}\n}\n\nfn build_examples() {\n\tif common.is_github_job {\n\t\texec('v build-examples')\n\t} else {\n\t\texec('v -progress build-examples')\n\t}\n}\n\nfn build_examples_v_compiled_with_tcc() {\n\texec('v -o vtcc -cc tcc cmd/v')\n\tif common.is_github_job {\n\t\texec('./vtcc build-examples')\n\t} else {\n\t\texec('./vtcc -progress build-examples')\n\t}\n}\n\nfn build_tetris_autofree() {\n\texec('v -autofree -o tetris examples/tetris/tetris.v')\n}\n\nfn build_blog_autofree() {\n\texec('v -autofree -o blog tutorials/building_a_simple_web_blog_with_veb/code/blog')\n}\n\nfn build_examples_prod() {\n\texec('v -prod examples/news_fetcher.v')\n}\n\nfn v_doctor() {\n\texec('v doctor')\n}\n\nfn build_v_with_prealloc() {\n\texec('v -cg -cstrict -o vstrict1 cmd/v')\n\texec('./vstrict1 -d debug_malloc -d debug_realloc -o vdebug1 cmd/v')\n\texec('./vstrict1 -o vprealloc -prealloc cmd/v')\n\t// TODO: fix prealloc on macos (the rwmutex implementation for shared maps there seems to require that mutexes are allocated by C.malloc directly, and segfaults for arbitrary memory addresses)\n\t//\texec('./vprealloc run examples/hello_world.v')\n\t//\texec('./vprealloc -o v3 cmd/v')\n\t//\texec('./v3 -o v4 cmd/v')\n}\n\nfn v_self_compilation_usecache() {\n\t$if !enable_usecache_test ? {\n\t\teprintln('> ${@LOCATION} use `-d enable_usecache_test` in VFLAGS to enable this task')\n\t\treturn\n\t}\n\texec('v -usecache examples/hello_world.v')\n\texec('./examples/hello_world')\n\texec('v -o v2 -usecache cmd/v')\n\texec('./v2 -o v3 -usecache cmd/v')\n\texec('./v3 version')\n\texec('./v3 -o tetris -usecache examples/tetris/tetris.v')\n}\n\nfn v_self_compilation_parallel_cc() {\n\texec('v -o vp -parallel-cc cmd/v')\n\t// exec('./v2 -o v3 -usecache cmd/v')\n\texec('./vp version')\n\texec('./vp -o tetris examples/tetris/tetris.v')\n}\n\nfn test_password_input() {\n\texec('v -silent test examples/password/')\n}\n\nfn test_readline() {\n\texec('v -silent test examples/readline/')\n}\n\nfn test_inline_assembly() {\n\texec('v test vlib/v/slow_tests/assembly')\n}\n\nconst all_tasks = {\n\t'test_symlink':                       Task{test_symlink, 'Test symlink'}\n\t'test_cross_compilation':             Task{test_cross_compilation, 'Test cross compilation to Linux'}\n\t'build_with_cstrict':                 Task{build_with_cstrict, 'Build V with -cstrict'}\n\t'all_code_is_formatted':              Task{all_code_is_formatted, 'All code is formatted'}\n\t'run_sanitizers':                     Task{run_sanitizers, 'Run sanitizers'}\n\t'build_using_v':                      Task{build_using_v, 'Build V using V'}\n\t'verify_v_test_works':                Task{verify_v_test_works, 'Verify `v test` works'}\n\t'install_iconv':                      Task{install_iconv, 'Install iconv for encoding.iconv'}\n\t'test_pure_v_math_module':            Task{test_pure_v_math_module, 'Test pure V math module'}\n\t'self_tests':                         Task{self_tests, 'Self tests'}\n\t'build_examples':                     Task{build_examples, 'Build examples'}\n\t'build_tetris_autofree':              Task{build_tetris_autofree, 'Build tetris with -autofree'}\n\t'build_blog_autofree':                Task{build_blog_autofree, 'Build blog tutorial with -autofree'}\n\t'build_examples_prod':                Task{build_examples_prod, 'Build examples with -prod'}\n\t'build_examples_v_compiled_with_tcc': Task{build_examples_v_compiled_with_tcc, 'Build examples with V build with tcc'}\n\t'v_doctor':                           Task{v_doctor, 'v doctor'}\n\t'build_v_with_prealloc':              Task{build_v_with_prealloc, 'Build V with prealloc'}\n\t'v_self_compilation_usecache':        Task{v_self_compilation_usecache, 'V self compilation with -usecache'}\n\t'v_self_compilation_parallel_cc':     Task{v_self_compilation_parallel_cc, 'V self compilation with -parallel-cc'}\n\t'test_password_input':                Task{test_password_input, 'Test password input'}\n\t'test_readline':                      Task{test_readline, 'Test readline'}\n\t'test_inline_assembly':               Task{test_inline_assembly, 'Test inline assembly'}\n}\n\ncommon.run(all_tasks)\n"
  },
  {
    "path": "ci/openbsd_ci.vsh",
    "content": "import os\nimport common { Task, exec }\n\nfn v_doctor() {\n\tprintln('### vdoctor')\n\tdump(os.getenv('PATH'))\n\texec('v doctor')\n\tif common.is_github_job {\n\t\texec('uname -mrs')\n\t\texec('sysctl hw.model')\n\t\texec('sysctl hw.ncpu')\n\t\texec('sysctl hw.physmem')\n\t\texec('sysctl hw.usermem')\n\t\texec('whoami')\n\t\texec('pwd')\n\t\texec('ls -la')\n\t\texec('git log -n1')\n\t\texec('cc --version')\n\t}\n}\n\nfn build_v_with_prealloc() {\n\tprintln('### Build v with prealloc')\n\texec('v -cg -cstrict -o vstrict1 cmd/v')\n\texec('./vstrict1 -o vprealloc -prealloc cmd/v')\n\texec('./vprealloc run examples/hello_world.v')\n\texec('./vprealloc -o v3 cmd/v')\n\texec('./v3 -o v4 cmd/v')\n\texec('./v4 -d debug_malloc -d debug_realloc -o vdebug1 cmd/v')\n}\n\nfn verify_v_test_works() {\n\tprintln('### Verify v test')\n\texec('echo \\$VFLAGS')\n\texec('v cmd/tools/test_if_v_test_system_works.v')\n\texec('./cmd/tools/test_if_v_test_system_works')\n}\n\nfn build_fast_script() {\n\tprintln('### Build fast script')\n\texec('cd cmd/tools/fast && v fast.v')\n}\n\nfn check_math() {\n\tprintln('### Test vlib/math')\n\texec('v -silent test vlib/math')\n\tprintln('Test the math module, using only the pure V versions,')\n\tprintln('                          without the .c.v overrides.')\n\texec('v -silent -exclude @vlib/math/*.c.v test vlib/math')\n}\n\nfn check_compress() {\n\tprintln('### Test vlib/compress')\n\texec('v -silent test vlib/compress')\n}\n\nfn test_inline_assembly() {\n\tprintln('### Test inline Assembly')\n\texec('v test vlib/v/slow_tests/assembly')\n}\n\nfn run_essential_tests() {\n\tif common.is_github_job {\n\t\tprintln('### Run essential tests')\n\t\texec('VTEST_JUST_ESSENTIAL=1 v -silent test-self')\n\t} else {\n\t\texec('VTEST_JUST_ESSENTIAL=1 v -progress test-self')\n\t}\n}\n\nfn build_examples() {\n\tif common.is_github_job {\n\t\tprintln('### Build examples')\n\t\texec('v -W build-examples')\n\t} else {\n\t\texec('v -progress build-examples')\n\t}\n}\n\nconst all_tasks = {\n\t'v_doctor':              Task{v_doctor, 'Run v doctor'}\n\t'build_v_with_prealloc': Task{build_v_with_prealloc, 'Build V with prealloc'}\n\t'verify_v_test_works':   Task{verify_v_test_works, 'Verify that v test works'}\n\t'build_fast_script':     Task{build_fast_script, 'Check that building fast.v works'}\n\t'check_math':            Task{check_math, 'Check the `math` module works'}\n\t'check_compress':        Task{check_compress, 'Check the `compress` module works'}\n\t'test_inline_assembly':  Task{test_inline_assembly, 'Test inline Assembly'}\n\t'run_essential_tests':   Task{run_essential_tests, 'Run only the essential tests'}\n\t'build_examples':        Task{build_examples, 'Build examples'}\n}\n\ncommon.run(all_tasks)\n"
  },
  {
    "path": "cmd/tools/amalgamate.v",
    "content": "// amalgamate multiple C source files into a single\n// C source file.  See https://sqlite.org/amalgamation.html\n// for a description of file amalgamation.\n//\n// If an input file is not specified, source is read\n// from stdin.\n//\n// If an output file is not specified, source is output\n// to stdout.\n\nmodule main\n\nimport flag\nimport os\nimport regex\n\nconst app_name = 'amalgamate'\nconst app_version = '0.0.1'\n\n// pre-compile the include statement regex\nconst re = regex.regex_opt(r'^\\s*#\\s*include\\s*\"([^\"]+)\"')!\n\nstruct Config {\nmut:\n\tinput_files []string\n\toutput_file string\n\tsearch_dirs []string\n\tblacklist   []string\n}\n\nstruct Context {\n\tconfig Config\nmut:\n\tprocessed_files []string\n}\n\nfn parse_arguments() Config {\n\tmut cfg := Config{}\n\n\tmut parser := flag.new_flag_parser(os.args)\n\tparser.skip_executable()\n\tparser.application(app_name)\n\tparser.version(app_version)\n\n\tparser.arguments_description('[file ...]')\n\n\tparser.description('combine multiple .c and .h files into one.')\n\tparser.description('')\n\tparser.description('Combine input, coming from either stdin or input files, into one')\n\tparser.description('large file.  Include statements are processed and the contents')\n\tparser.description('copied in place.  Only #include \"file.h\" statements cause their')\n\tparser.description('contents to be copied, not #include <file.h> statements.  If no')\n\tparser.description('input files are specified, read from stdin.')\n\n\tparser.footer('\\nAn example showing multiple blacklisted files and multiple search')\n\tparser.footer('directories.')\n\tparser.footer('')\n\tparser.footer('    amalgamate -o output_file.c -b ignore_me.h \\\\')\n\tparser.footer('        -b ignore_me_2.h -b other/ignore_me.h \\\\')\n\tparser.footer('        -s relative/search/dir -s /absolute/search/dir \\\\')\n\tparser.footer('        file1.c file2.c')\n\tparser.footer('')\n\n\tcfg.output_file = parser.string('output', `o`, '', 'output file.  If not specified,\\n' +\n\t\tflag.space + 'defaults to stdout.\\n', val_desc: '<filename>')\n\n\tcfg.blacklist = parser.string_multi('blacklist', `b`,\n\t\t'blacklist a file name.  This prevents\\n' + flag.space +\n\t\t'the named file from being included.\\n' + flag.space +\n\t\t'This can be specified more that once.\\n', val_desc: '<include_file>')\n\n\tcfg.search_dirs = parser.string_multi('search_path', `s`,\n\t\t'add a directory to the search path.\\n' + flag.space +\n\t\t'An include file is searched for in\\n' + flag.space +\n\t\t'the current working directory and\\n' + flag.space +\n\t\t'if not found, the directories in this\\n' + flag.space +\n\t\t'list are searched, in order, until the\\n' + flag.space +\n\t\t'file is found or the search list is\\n' + flag.space +\n\t\t'exhausted.  This can be specified\\n' + flag.space + 'more that once.\\n',\n\t\tval_desc: '<search_dir>'\n\t)\n\n\tcfg.input_files = parser.finalize() or {\n\t\t// this only reports the first unrecognized argument\n\t\teprintln('${err}\\n')\n\t\teprintln('${parser.usage()}\\n')\n\t\texit(1)\n\t}\n\n\treturn cfg\n}\n\nfn main() {\n\tcfg := parse_arguments()\n\n\tmut ctx := Context{\n\t\tconfig: cfg\n\t}\n\n\tctx.amalgamate() or {\n\t\teprintln('error: ${err}')\n\t\texit(1)\n\t}\n}\n\nfn (mut c Context) amalgamate() ! {\n\tmut source := ''\n\n\tif c.config.input_files.len == 0 {\n\t\t// source += '/* ########## stdin */\\n'\n\t\t// if there are no input files, read from stdin\n\t\tlocal_dir := os.getwd()\n\t\tsource += c.handle_includes(local_dir, os.get_raw_lines_joined())!\n\t\t// source += '/* ########## stdin end */\\n'\n\t} else {\n\t\t// read each input file, in order, and\n\t\t// handle all of its includes.\n\t\tfor file in c.config.input_files {\n\t\t\tif file in c.config.blacklist {\n\t\t\t\t// skip blacklisted files\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfound_file := c.find_file(file)!\n\n\t\t\tif found_file in c.processed_files {\n\t\t\t\t// skip over files already read\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// source += '/* ########## ${file} */\\n'\n\t\t\tc.processed_files << found_file\n\t\t\tlocal_dir := os.dir(found_file)\n\t\t\tfile_source_code := os.read_file(found_file)!\n\t\t\tsource += c.handle_includes(local_dir, file_source_code)!\n\t\t\t// source += '/* ########## ${file} end */\\n'\n\t\t}\n\t}\n\n\tif c.config.output_file == '' {\n\t\tprint(source)\n\t} else {\n\t\tos.write_file(c.config.output_file, source)!\n\t}\n\n\treturn\n}\n\nfn (c Context) find_file(file string) !string {\n\tmut full_path := os.real_path(file)\n\n\tif os.is_file(full_path) {\n\t\treturn full_path\n\t}\n\n\tfor dir in c.config.search_dirs {\n\t\tfull_path = os.real_path(os.join_path_single(dir, file))\n\n\t\tif os.is_file(full_path) {\n\t\t\treturn full_path\n\t\t}\n\t}\n\n\treturn error('file \"${file}\" not found')\n}\n\n// handle_includes looks for lines that start with #include\n// and inserts the lines from the named include file.\n//\n// The pattern matches file names for local header files,\n// not system header files as are denoted by < and >.\nfn (mut c Context) handle_includes(local_dir string, input_source string) !string {\n\tsource_lines := input_source.split_into_lines()\n\tmut output_lines := []string{}\n\n\tfor line in source_lines {\n\t\tstart, _ := re.match_string(line)\n\n\t\tif start >= 0 {\n\t\t\tfile := line[re.groups[0]..re.groups[1]]\n\t\t\tmut found_file := ''\n\n\t\t\tif file in c.config.blacklist {\n\t\t\t\t// leave blacklisted files alone\n\t\t\t\tif file in c.processed_files {\n\t\t\t\t\t// we don't want a second include\n\t\t\t\t\toutput_lines << '\\n'\n\t\t\t\t} else {\n\t\t\t\t\toutput_lines << line\n\t\t\t\t\tc.processed_files << file\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif !os.is_abs_path(file) {\n\t\t\t\tfound_file = c.find_file(os.join_path_single(local_dir, file)) or {\n\t\t\t\t\t// keep looking\n\t\t\t\t\t''\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif found_file == '' {\n\t\t\t\tfound_file = c.find_file(file)!\n\t\t\t}\n\n\t\t\tif found_file in c.processed_files {\n\t\t\t\t// skip over files already read\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.processed_files << found_file\n\t\t\tfile_source_code := os.read_file(found_file)!\n\t\t\t// output_lines << '/* ########## ${file} begin */\\n'\n\t\t\toutput_lines << c.handle_includes(os.dir(found_file), file_source_code)!\n\t\t\t// output_lines << '/* ########## ${file} end */\\n'\n\t\t} else {\n\t\t\toutput_lines << line\n\t\t}\n\t}\n\n\treturn output_lines.join_lines() + '\\n'\n}\n"
  },
  {
    "path": "cmd/tools/bench/map_clear.v",
    "content": "import benchmark\n\nfn main() {\n\tmax_iterations := arguments()[1] or { '1_000_000' }.int()\n\tassert max_iterations > 0\n\tmut m := {\n\t\t123: 456\n\t\t789: 321\n\t}\n\tmut volatile sum := u64(0)\n\tmut b := benchmark.start()\n\tfor i in 0 .. max_iterations {\n\t\tm.clear()\n\t\tm[i] = i * 2\n\t\tsum += u64(m.len)\n\t}\n\tassert m.len == 1\n\tb.measure('m.clear(), iterations: ${max_iterations}, sum: ${sum}')\n}\n"
  },
  {
    "path": "cmd/tools/bench/map_clear_runner.vsh",
    "content": "#!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp\n\nimport os\n\nconst time_fmt = '\"CPU: %Us\\tReal: %es\\tElapsed: %E\\tRAM: %MKB\\t%C\"'\nconst flags = os.getenv('FLAGS')\n\nunbuffer_stdout()\n\nstart := os.args[1] or { '1_000_000' }.int()\nend := os.args[2] or { '10_000_000' }.int()\nstep := os.args[3] or { '500_000' }.int()\n\nos.chdir(os.dir(@VEXE))!\nvcmd := 'v ${flags} cmd/tools/bench/map_clear.v'\n\nprintln('>> start: ${start} | end: ${end} | step: ${step} | workdir: \"${os.getwd()}\" | flags: \"${flags}\" | vcmd: \"${vcmd}\"')\nassert os.system(vcmd) == 0\n\nprintln('running...')\nfor i := start; i <= end; i += step {\n\tos.system('/usr/bin/time -f ${time_fmt} cmd/tools/bench/map_clear ${i}') == 0\n}\n"
  },
  {
    "path": "cmd/tools/bench/wyhash.v",
    "content": "module main\n\nimport hash.fnv1a\nimport hash as wyhash\nimport rand\nimport benchmark\n\nfn main() {\n\trand.seed([u32(42), 0])\n\tsample_size := 10000000\n\tmin_str_len := 20\n\tmax_str_len := 40\n\tprintln('Generating ${sample_size} strings between ${min_str_len} - ${max_str_len} chars long...')\n\tmut checksum := u64(0)\n\tmut start_pos := 0\n\tmut bgenerating := benchmark.start()\n\tmut bytepile := []u8{}\n\tfor _ in 0 .. sample_size * max_str_len {\n\t\tbytepile << u8(rand.int_in_range(40, 125) or { 40 })\n\t}\n\tmut str_lens := []int{}\n\tfor _ in 0 .. sample_size {\n\t\tstr_lens << rand.int_in_range(min_str_len, max_str_len) or { min_str_len }\n\t}\n\tbgenerating.measure('generating strings')\n\tprintln('Hashing each of the generated strings...')\n\n\tmut bhashing_1 := benchmark.start()\n\tstart_pos = 0\n\tchecksum = 0\n\tfor len in str_lens {\n\t\tend_pos := start_pos + len\n\t\tchecksum ^= wyhash.wyhash_c(unsafe { &u8(bytepile.data) + start_pos }, u64(len),\n\t\t\t1)\n\t\tstart_pos = end_pos\n\t}\n\tbhashing_1.measure('wyhash.wyhash_c  | checksum: ${checksum:22}')\n\tmut bhashing_2 := benchmark.start()\n\tstart_pos = 0\n\tchecksum = 0\n\tfor len in str_lens {\n\t\tend_pos := start_pos + len\n\t\tchecksum ^= wyhash.sum64(bytepile[start_pos..end_pos], 1)\n\t\tstart_pos = end_pos\n\t}\n\tbhashing_2.measure('wyhash.sum64     | checksum: ${checksum:22}')\n\tmut bhashing_3 := benchmark.start()\n\tstart_pos = 0\n\tchecksum = 0\n\tfor len in str_lens {\n\t\tend_pos := start_pos + len\n\t\tchecksum ^= fnv1a.sum64(bytepile[start_pos..end_pos])\n\t\tstart_pos = end_pos\n\t}\n\tbhashing_3.measure('fnv1a.sum64      | checksum: ${checksum:22}')\n}\n"
  },
  {
    "path": "cmd/tools/builders/c_builder.v",
    "content": "module main\n\nimport v.builder.cbuilder\n\n// TODO: change bootstrapping to use the C code generated from\n// `VEXE=v cmd/tools/builders/c_builder -os cross -o c.c cmd/tools/builders/c_builder.v`\n// See also `cmd/v/v.v`\n\nfn main() {\n\tcbuilder.start()\n}\n"
  },
  {
    "path": "cmd/tools/builders/golang_builder.v",
    "content": "module main\n\nimport v.builder.golangbuilder\n\nfn main() {\n\tgolangbuilder.start()\n}\n"
  },
  {
    "path": "cmd/tools/builders/interpret_builder.v",
    "content": "module main\n\nimport v.builder.interpreterbuilder\n\nfn main() {\n\tinterpreterbuilder.start()\n}\n"
  },
  {
    "path": "cmd/tools/builders/js_builder.v",
    "content": "module main\n\nimport v.builder.jsbuilder\n\nfn main() {\n\tjsbuilder.start()\n}\n"
  },
  {
    "path": "cmd/tools/builders/native_builder.v",
    "content": "module main\n\nimport v.builder.nativebuilder\n\nfn main() {\n\tnativebuilder.start()\n}\n"
  },
  {
    "path": "cmd/tools/builders/wasm_builder.v",
    "content": "module main\n\nimport v.builder.wasmbuilder\n\nfn main() {\n\twasmbuilder.start()\n}\n"
  },
  {
    "path": "cmd/tools/cc_compilation_failed_non_windows.sh",
    "content": "#!/bin/sh\n## this script is used by the makefiles in the top level folder\necho\necho 'Compilation of v.c failed.'\necho 'See https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Linux-and-macOS .'\necho\nfalse\n"
  },
  {
    "path": "cmd/tools/cc_compilation_failed_windows.sh",
    "content": "#!/bin/sh\n## this script is used by the makefiles in the top level folder\necho\necho 'Compilation of v.c failed.'\necho 'See https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Windows .'\necho\nfalse\n"
  },
  {
    "path": "cmd/tools/changelog_helper.v",
    "content": "module main\n\nimport os\n\nconst delete_skipped = true\n\nconst git_log_cmd = 'git log -n 500 --pretty=format:\"%s\" --simplify-merges'\n\nenum Category {\n\tchecker\n\tbreaking\n\timprovements\n\tparser\n\tstdlib\n\tweb\n\torm\n\tdb\n\tnative\n\tcgen\n\tjs_backend\n\tcomptime\n\ttools\n\tcompiler_internals\n\texamples\n\tvfmt\n\tos_support\n\tinterpreter\n}\n\nconst category_titles = '#### Improvements in the language\n\n#### V interpreter\n\n#### Breaking changes\n\n#### Checker improvements/fixes\n\n#### Parser improvements\n\n#### Compiler internals\n\n#### Standard library\n\n#### Web\n\n#### ORM\n\n#### Database drivers\n\n#### Native backend\n\n#### C backend\n\n#### JavaScript backend\n\n#### vfmt\n\n#### Tools\n\n#### Operating System support\n\n#### Examples\n'\n\nstruct Line {\n\tcategory Category\n\ttext     string\n}\n\nconst log_txt = 'log.txt'\n\nstruct App {\n\tversion     string // e.g. \"0.4.5\"\n\ttotal_lines int\nmut:\n\tresult  string // resulting CHANGELOG.md\n\tcounter int\n}\n\nconst is_interactive = false\n\n// Instantly updates CHANGELOG.md without confirming each line\nfn no_interactive(version string) {\n}\n\nfn main() {\n\tmut version := ''\n\n\tif os.args.len == 2 && os.args[1].starts_with('0.') {\n\t\tversion = os.args[1]\n\t\t// no_interactive(version)\n\t\t// return\n\t} else {\n\t\tprintln('Usage: v run tools/changelog_helper.v 0.4.5')\n\t\treturn\n\t}\n\tif !os.exists(log_txt) {\n\t\tos.execute(git_log_cmd + ' > ' + log_txt)\n\t\tprintln('log.txt generated')\n\t\t// println('log.txt generated, remove unnecessary commits from it and run the tool again')\n\t\t// return\n\t}\n\tmut lines := os.read_lines(log_txt)!\n\t// Trim everything before current version, commit \"(tag: 0.4.4) V 0.4.4\"\n\tmut prev_version := get_prev_version(version)\n\tprintln('prev version=${prev_version}')\n\tfor i, line in lines {\n\t\tif line == ('V ${prev_version}') {\n\t\t\tlines = lines[..i].clone()\n\t\t\tbreak\n\t\t}\n\t}\n\tos.write_file(log_txt, lines.join('\\n'))!\n\tmut app := &App{\n\t\ttotal_lines: lines.len\n\t}\n\t// Write categories at the top first\n\tapp.result = os.read_file('CHANGELOG.md')!.replace_once('V ${version} TODO', 'V ${version}\\n' +\n\t\tcategory_titles)\n\tos.write_file('CHANGELOG.md', app.result)!\n\tchangelog_txt := os.read_file('CHANGELOG.md')!.to_lower()\n\t// mut counter := 0 // to display how many commits are left\n\tfor line in lines {\n\t\ts := line.trim_space()\n\t\tif s == '' {\n\t\t\tapp.counter++\n\t\t}\n\t}\n\t// println('${counter} / ${lines.len}')\n\tfor line in lines {\n\t\ts := line.to_lower()\n\t\tif line != '' && (changelog_txt.contains(s) || changelog_txt.contains(s.after(':'))) {\n\t\t\tprintln('Duplicate: \"${line}\"')\n\t\t\t// skip duplicate\n\t\t\tdelete_processed_line_from_log(line)!\n\t\t\tcontinue\n\t\t}\n\n\t\tapp.process_line(line.trim_space())!\n\t}\n\tprintln('writing changelog.md')\n\tif !is_interactive {\n\t\tos.write_file('CHANGELOG.md', app.result)!\n\t}\n\tprintln('done.')\n}\n\nfn (mut app App) process_line(text string) ! {\n\tif text == '' {\n\t\treturn\n\t}\n\tsemicolon_pos := text.index(': ') or {\n\t\tprintln('no `:` in commit, skipping: \"${text}\"')\n\t\treturn\n\t}\n\tprefix := text[..semicolon_pos]\n\t// Get category based on keywords in the commit message/prefix\n\tmut category := Category.examples\n\tif text.contains('checker:') {\n\t\tcategory = .checker\n\t} else if is_interpreter(text) {\n\t\tcategory = .interpreter\n\t} else if is_examples(text) {\n\t\tcategory = .examples\n\t\t// println(\"Skipping line (example) ${text}\")\n\t\t// return\n\t} else if is_skip(text) {\n\t\t// Always skip cleanups, typos etc\n\t\tprintln('Skipping line (cleanup/typo)\\n${text}\\n')\n\t\tif delete_skipped {\n\t\t\tdelete_processed_line_from_log(text)!\n\t\t}\n\t\treturn\n\t} else if is_os_support(text) {\n\t\tcategory = .os_support\n\t} else if is_cgen(text) {\n\t\tcategory = .cgen\n\t} else if is_js_backend(text) {\n\t\tcategory = .js_backend\n\t} else if is_comptime(text) {\n\t\tcategory = .comptime\n\t} else if is_db(text) {\n\t\tcategory = .db\n\t} else if is_stdlib(text) {\n\t\tcategory = .stdlib\n\t} else if is_orm(text) {\n\t\tcategory = .orm\n\t} else if is_web(text) {\n\t\tcategory = .web\n\t} else if is_tools(text) {\n\t\tcategory = .tools\n\t} else if is_parser(text) {\n\t\tcategory = .parser\n\t} else if is_internal(text) {\n\t\tcategory = .compiler_internals\n\t} else if is_improvements(text) {\n\t\tcategory = .improvements\n\t} else if is_native(text) {\n\t\tcategory = .native\n\t} else if is_vfmt(text) {\n\t\tcategory = .vfmt\n\t} else if text.contains('docs:') || text.contains('doc:') {\n\t\t// Always skip docs\n\t\tdelete_processed_line_from_log(text)!\n\t\treturn\n\t} else {\n\t\tprintln('Skipping line (unknown category)\\n${text}\\n')\n\t\t// if delete_skipped {\n\t\t// delete_processed_line_from_log(text)!\n\t\t//}\n\t\treturn\n\t}\n\tprintln('process_line: cat=${category} \"${text}\"')\n\n\t// Trim everything to the left of `:` for some commits (e.g. `checker: `)\n\tmut s := text\n\t// println(\"PREFIX='${prefix}'\")\n\t// if true {\n\t// exit(0)\n\t//}\n\tif (semicolon_pos < 15\n\t\t&& prefix in ['checker', 'cgen', 'orm', 'parser', 'v.parser', 'native', 'ast', 'jsgen', 'v.gen.js', 'fmt', 'vfmt', 'tools', 'examples', 'eval'])\n\t\t|| (semicolon_pos < 30 && prefix.contains(', ')) {\n\t\ts = '- ' + text[semicolon_pos + 2..].capitalize()\n\t}\n\n\tif is_interactive {\n\t\t// Get input from the user\n\t\tprint('\\033[H\\033[J')\n\t\tprintln('${app.counter} / ${app.total_lines}')\n\t\t// println('\\n')\n\t\tprintln(text)\n\t\tinput := os.input('${category}? ')\n\t\tprintln(\"INPUT='${input}'\")\n\t\tmatch input {\n\t\t\t'' {\n\t\t\t\tprintln('GOT ENTER')\n\t\t\t\tline := Line{category, s}\n\t\t\t\tsave_line_interactive(line)!\n\t\t\t}\n\t\t\t'n', '0', 'no' {\n\t\t\t\t// Ignore commit\n\t\t\t\tprintln('ignored.')\n\t\t\t}\n\t\t\t's', 'skip' {\n\t\t\t\t// Skip\n\t\t\t\tprintln('skipped.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\t'c', 'change' {\n\t\t\t\t// Change category\n\t\t\t\tfor {\n\t\t\t\t\tprint_category_hint()\n\t\t\t\t\tcustom_category := os.input('${category} ?').int()\n\t\t\t\t\tif custom_category == 0 {\n\t\t\t\t\t\tprintln('wrong category')\n\t\t\t\t\t} else {\n\t\t\t\t\t\tunsafe {\n\t\t\t\t\t\t\tline := Line{Category(custom_category - 1), s}\n\t\t\t\t\t\t\tsave_line_interactive(line)!\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {}\n\t\t}\n\t\tapp.counter++\n\t} else {\n\t\tline := Line{category, s}\n\t\tapp.save_line(line)!\n\t}\n\t// Don't forget to remove the line we just processed from log.txt\n\tdelete_processed_line_from_log(text)!\n}\n\nfn (mut app App) save_line(line Line) ! {\n\t// println('save line ${line}')\n\tapp.result = line.write_at_category(app.result) or { return error('') }\n}\n\nfn save_line_interactive(line Line) ! {\n\tprintln('save line interactive ${line}')\n\tmut txt := os.read_file('CHANGELOG.md')!\n\ttxt = line.write_at_category(txt) or { return error('') }\n\tos.write_file('CHANGELOG.md', txt)!\n}\n\nconst category_map = {\n\tCategory.checker:    '#### Checker improvements'\n\t.breaking:           '#### Breaking changes'\n\t.improvements:       '#### Improvements in the'\n\t.interpreter:        '#### V interpreter'\n\t.parser:             '#### Parser improvements'\n\t.stdlib:             '#### Standard library'\n\t.web:                '#### Web'\n\t.orm:                '#### ORM'\n\t.db:                 '#### Database drivers'\n\t.native:             '#### Native backend'\n\t.cgen:               '#### C backend'\n\t.js_backend:         '#### JavaScript backend'\n\t.comptime:           '#### Comptime'\n\t.tools:              '#### Tools'\n\t.compiler_internals: '#### Compiler internals'\n\t.examples:           '#### Examples'\n\t.vfmt:               '#### vfmt'\n\t.os_support:         '#### Operating System'\n}\n\nfn (l Line) write_at_category(txt string) ?string {\n\ttitle := category_map[l.category]\n\ttitle_pos := txt.index(title)?\n\t// Find the position of the ### category title\n\tpos := txt.index_after('\\n', title_pos + 1) or { return none }\n\tfirst_half := txt[..pos]\n\tsecond_half := txt[pos..]\n\tif txt.contains(l.text) {\n\t\t// Avoid duplicates (just in case)\n\t\tprintln(\"Got a duplicate: '${txt}'\")\n\t\treturn txt\n\t}\n\t// Now insert the line in the middle, under the ### category title\n\tmut line_text := l.text\n\n\t// Trim \"prefix:\" for some categories\n\t// mut capitalized := false\n\tmut has_prefix := true\n\tif l.category in [.cgen, .checker, .improvements, .native, .orm, .interpreter] {\n\t\thas_prefix = false\n\t\tif semicolon_pos := line_text.index(': ') {\n\t\t\tprefix := line_text[..semicolon_pos]\n\t\t\tprintln(\"PREFIX='${prefix}'\")\n\t\t\tif semicolon_pos < 15 {\n\t\t\t\tline_text = line_text[semicolon_pos + 2..].capitalize()\n\t\t\t\t// capitalized = true\n\t\t\t}\n\t\t}\n\t}\n\tif !has_prefix {\n\t\tline_text = line_text.capitalize()\n\t}\n\tif !line_text.starts_with('- ') {\n\t\tline_text = '- ' + line_text\n\t}\n\treturn first_half + '\\n' + line_text + second_half\n}\n\nfn delete_processed_line_from_log(line string) ! {\n\ttext := os.read_file(log_txt)!\n\tnew_text := text.replace_once(line, '')\n\tos.write_file(log_txt, new_text)!\n}\n\nconst db_strings = [\n\t'db:',\n\t'db.sqlite',\n\t'db.mysql',\n\t'db.pg',\n\t'db.redis',\n\t'pg:',\n\t'mysql:',\n]\n\nconst parser_strings = [\n\t'parser:',\n\t'ast:',\n]\n\nconst stdlib_strings = [\n\t'gg:',\n\t'json:',\n\t'json2:',\n\t'time:',\n\t'sync:',\n\t'datatypes:',\n\t'math:',\n\t'math.',\n\t'math.big',\n\t'crypto',\n\t'sokol',\n\t'os:',\n\t'rand:',\n\t'rand.',\n\t'math:',\n\t'toml:',\n\t'vlib:',\n\t'arrays:',\n\t'os.',\n\t'term:',\n\t'sync.',\n\t'builtin:',\n\t'builtin,',\n\t'builtin.',\n\t'strconv',\n\t'readline',\n\t'cli:',\n\t'eventbus:',\n\t'encoding.',\n\t'bitfield:',\n\t'io:',\n\t'io.',\n\t'log:',\n\t'flag:',\n\t'regex:',\n\t'regex.',\n\t'tmpl:',\n\t'hash:',\n\t'stbi:',\n\t'atomic:',\n\t'context:',\n\t'thirdparty',\n]\n\nfn is_stdlib(text string) bool {\n\treturn is_xxx(text, stdlib_strings)\n}\n\nfn is_db(text string) bool {\n\treturn is_xxx(text, db_strings)\n}\n\nconst orm_strings = [\n\t'orm:',\n]\n\nfn is_orm(text string) bool {\n\treturn is_xxx(text, orm_strings)\n}\n\nconst cgen_strings = [\n\t'cgen:',\n\t'cgen,',\n\t'v.gen.c:',\n]\n\nfn is_cgen(text string) bool {\n\treturn is_xxx(text, cgen_strings)\n}\n\nconst js_backend_strings = [\n\t'js:',\n\t'v.gen.js:',\n\t'jsgen:',\n]\n\nfn is_js_backend(text string) bool {\n\treturn is_xxx(text, js_backend_strings)\n}\n\nconst internal_strings = [\n\t'scanner:',\n\t'transformer:',\n\t'markused:',\n\t'builder:',\n\t'pref:',\n\t'v.util',\n\t'v.generic',\n\t'v.comptime',\n\t'table:',\n]\n\nfn is_internal(text string) bool {\n\treturn is_xxx(text, internal_strings)\n}\n\nconst improvements_strings = [\n\t'all:',\n\t'v:',\n\t'coroutines:',\n\t'autofree',\n]\n\nfn is_improvements(text string) bool {\n\treturn is_xxx(text, improvements_strings)\n}\n\nconst examples_strings = [\n\t'example',\n]\nconst skip_strings = [\n\t'tests',\n\t'readme:',\n\t'.md:',\n\t'typos',\n\t' typo',\n\t'cleanup',\n\t'clean up',\n\t'build(deps)',\n\t'FUNDING',\n]\n\nfn is_examples(text string) bool {\n\treturn is_xxx(text, examples_strings)\n}\n\nfn is_skip(text string) bool {\n\treturn is_xxx(text, skip_strings)\n}\n\nconst tools_strings = [\n\t'tools:',\n\t'vpm:',\n\t'ci:',\n\t'github:',\n\t'gitignore',\n\t'benchmark',\n\t'v.help:',\n\t'vtest',\n\t'repl',\n\t'REPL',\n\t'vet',\n\t'tools.',\n\t'GNUmakefile',\n\t'Dockerfile',\n\t'vcomplete',\n\t'vwatch',\n\t'changelog',\n]\n\nfn is_tools(text string) bool {\n\treturn is_xxx(text, tools_strings)\n}\n\nfn is_parser(text string) bool {\n\treturn is_xxx(text, parser_strings)\n}\n\nconst web_strings = [\n\t'vweb',\n\t'veb',\n\t'x.vweb',\n\t'websocket:',\n\t'pico',\n\t'x.sessions',\n\t'picoev:',\n\t'mbedtls',\n\t'net:',\n\t'net.',\n\t'wasm:',\n\t'http:',\n]\n\nfn is_web(text string) bool {\n\treturn is_xxx(text, web_strings)\n}\n\nconst native_strings = [\n\t'native:',\n]\n\nfn is_native(text string) bool {\n\treturn is_xxx(text, native_strings)\n}\n\nconst vfmt_strings = [\n\t'vfmt:',\n\t'fmt:',\n]\n\nfn is_vfmt(text string) bool {\n\treturn is_xxx(text, vfmt_strings)\n}\n\nconst os_support_strings = [\n\t'FreeBSD',\n\t'freebsd',\n\t'OpenBSD',\n\t'openbsd',\n\t'macOS',\n\t'macos',\n\t'Windows',\n\t'windows',\n\t'Linux',\n\t'linux',\n\t'msvc:',\n]\n\nfn is_os_support(text string) bool {\n\treturn is_xxx(text, os_support_strings)\n}\n\nfn is_comptime(text string) bool {\n\treturn text.contains('comptime:')\n}\n\nfn is_interpreter(text string) bool {\n\treturn text.starts_with('eval:')\n}\n\nfn is_xxx(text string, words []string) bool {\n\tfor s in words {\n\t\tif text.contains(s) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfn print_category_hint() {\n\t$for val in Category.values {\n\t\tprintln('${int(val.value) + 1} - ${val.name}; ')\n\t}\n}\n\n// For 0.4.12 returns 0.4.11 etc\nfn get_prev_version(version string) string {\n\tparts := version.split('.')\n\tif parts.len != 3 {\n\t\treturn ''\n\t}\n\tmajor := parts[0]\n\tminor := parts[1]\n\tpatch := parts[2].int()\n\treturn '${major}.${minor}.${patch - 1}'\n}\n"
  },
  {
    "path": "cmd/tools/check_os_api_parity.v",
    "content": "module main\n\nimport os\nimport v.util\nimport v.util.diff\nimport v.pref\nimport v.builder\nimport v.builder.cbuilder\nimport v.ast\nimport term\n\nconst base_os = pref.get_host_os()\nconst os_list = [pref.OS.linux, .macos, .windows, .freebsd, .openbsd, .solaris, .termux]\nconst skip_modules = [\n\t'builtin.bare',\n\t'builtin.linux_bare.old',\n\t'builtin.js',\n\t'builtin.wasm',\n\t'strconv',\n\t'strconv.ftoa',\n\t'hash',\n\t'strings',\n\t'crypto.rand',\n\t'os.bare',\n\t'os2',\n\t'szip',\n\t'v.eval',\n]\nconst is_verbose = os.getenv('VERBOSE') != ''\n\nfn main() {\n\tvexe := os.real_path(os.getenv_opt('VEXE') or { @VEXE })\n\tvroot := os.dir(vexe)\n\tutil.set_vroot_folder(vroot)\n\tos.chdir(vroot)!\n\tmodules := if os.args.len > 1 { os.args[1..] } else { all_vlib_modules() }\n\tmut diff_modules := map[string]bool{}\n\tother_os_list := os_list.filter(it != base_os)\n\tfor m in modules {\n\t\tif !is_verbose {\n\t\t\teprintln('Checking module: ${m} ...')\n\t\t}\n\t\tapi_base := gen_api_for_module_in_os(m, base_os)\n\t\tfor other_os in other_os_list {\n\t\t\tapi_os := gen_api_for_module_in_os(m, other_os)\n\t\t\tif api_base == api_os {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdiff_modules[m] = true\n\t\t\tsummary := 'Different APIs found for module: `${m}`, between OS base: `${base_os}` and OS: `${other_os}`'\n\t\t\teprintln(term.header(summary, '-'))\n\t\t\tdiff_ := diff.compare_text(api_base, api_os) or { continue }\n\t\t\tprintln(diff_)\n\t\t\teprintln(term.h_divider('-'))\n\t\t}\n\t}\n\tif diff_modules.len > 0 {\n\t\teprintln(term.header('Found ${diff_modules.len} modules with different APIs',\n\t\t\t'='))\n\t\tfor m in diff_modules.keys() {\n\t\t\teprintln('Module: ${m}')\n\t\t}\n\t\texit(1)\n\t}\n}\n\nfn all_vlib_modules() []string {\n\tmut vlib_v_files := os.walk_ext('vlib', '.v')\n\tmut vmodulesmap := map[string]int{}\n\tfor f in vlib_v_files {\n\t\tif f.contains('/tests/') || f.ends_with('_test.v') {\n\t\t\tcontinue\n\t\t}\n\t\tvmodulename := os.dir(f).replace('/', '.').replace('vlib.', '')\n\t\tif vmodulename in skip_modules {\n\t\t\tcontinue\n\t\t}\n\t\tvmodulesmap[vmodulename] = vmodulesmap[vmodulename] + 1\n\t}\n\tmut modules := vmodulesmap.keys()\n\tmodules.sort()\n\treturn modules\n}\n\nfn gen_api_for_module_in_os(mod_name string, os_ pref.OS) string {\n\tif is_verbose {\n\t\teprintln('Checking module: ${mod_name:-30} for OS: ${os_:-10} ...')\n\t}\n\tos_name := os_.str().to_lower()\n\tmpath := os.join_path('vlib', mod_name.replace('.', '/'))\n\ttmpname := '/tmp/${mod_name}_${os_name}.c'\n\tprefs, _ := pref.parse_args([], ['-os', os_name, '-o', tmpname, '-shared', mpath])\n\tmut b := builder.new_builder(prefs)\n\tcbuilder.compile_c(mut b)\n\tmut res := []string{}\n\tfor f in b.parsed_files {\n\t\tfor s in f.stmts {\n\t\t\tif s is ast.FnDecl && s.is_pub {\n\t\t\t\tfn_mod := s.modname()\n\t\t\t\tif fn_mod == mod_name {\n\t\t\t\t\tfn_signature := b.table.stringify_fn_decl(&s, mod_name, map[string]string{},\n\t\t\t\t\t\tfalse)\n\t\t\t\t\tfline := '${fn_mod}: ${fn_signature}'\n\t\t\t\t\tres << fline\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tres.sort()\n\treturn res.join('\\n')\n}\n"
  },
  {
    "path": "cmd/tools/check_retry.vsh",
    "content": "#!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp\n\n// This script is used by cmd/tools/vretry_test.v, to check that the `v retry`\n// subcommand works as expected, without relying on external commands like\n// `git`, or on non portable ones like `true`/`false` or `echo`.\n\nfn main() {\n\targs := arguments()#[1..]\n\tprintln(args)\n\tif args == ['too', 'many', 'arguments'] {\n\t\texit(1)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/detect_tcc.v",
    "content": "fn main() {\n\t$if tinyc {\n\t\tprintln('Your `tcc` is working. Good - it is much faster at compiling C source code.')\n\t\texit(0)\n\t}\n\n\t$if !macos {\n\t\tprintln('\nNote: `tcc` was not used, so unless you install it yourself, your backend\nC compiler will be `cc`, which is usually either `clang`, `gcc` or `msvc`.\n\nThese C compilers, are several times slower at compiling C source code,\ncompared to `tcc`. They do produce more optimised executables, but that\nis done at the cost of compilation speed.\n')\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/find_doc_comments_with_no_dots.v",
    "content": "import os\n\nfn main() {\n\targs := arguments()\n\tif args.len < 2 {\n\t\tprintln('Usage: v run doc_comment_checker.v <file1.v> <file2.v>...')\n\t\treturn\n\t}\n\tmut fpaths := []string{}\n\tfor filepath in args[1..] {\n\t\tif os.is_file(filepath) {\n\t\t\tfpaths << filepath\n\t\t}\n\t\tif os.is_dir(filepath) {\n\t\t\tfpaths << os.walk_ext(filepath, '.v').filter(!it.ends_with('_test.v')\n\t\t\t\t&& !it.ends_with('_test.c.v'))\n\t\t}\n\t}\n\tfpaths.sort()\n\tmut ctx := Context{}\n\tfor filepath in fpaths {\n\t\tctx.process_fpath(filepath) or {\n\t\t\teprintln('error with ${filepath}: ${err}')\n\t\t\tcontinue\n\t\t}\n\t}\n\tprintln('> Processed ${fpaths.len} .v files, found errors: ${ctx.errors} , in ${ctx.pub_symbols} `pub` declarations, and ${ctx.pub_comment_lines} pub comment lines.')\n\tif ctx.errors > 0 {\n\t\texit(1)\n\t}\n}\n\nstruct Context {\nmut:\n\terrors            int\n\tpub_symbols       int\n\tpub_comment_lines int\n\tcomments          int\n}\n\nfn (mut ctx Context) process_fpath(filepath string) ! {\n\tlines := os.read_lines(filepath)!\n\tmut prev := 0\n\tfor iline, line in lines {\n\t\tif line.starts_with('pub ') {\n\t\t\tctx.pub_symbols++\n\t\t\tmut comments := []CommentLine{}\n\t\t\tmut i := 0\n\t\t\tfor i = int_max(0, iline - 1); i >= prev; i-- {\n\t\t\t\tpline := lines[i]\n\t\t\t\tif pline.starts_with('// ') {\n\t\t\t\t\tcomments << CommentLine{pline, i + 1}\n\t\t\t\t} else {\n\t\t\t\t\tprev = iline + 1\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif comments.len > 0 {\n\t\t\t\tcline := comments.last()\n\t\t\t\tfword := cline.comment.all_after('// ').all_before(' ')\n\t\t\t\tif !line.contains(fword) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tctx.pub_comment_lines += comments.len\n\t\t\t\tif !cline.comment.ends_with('.') {\n\t\t\t\t\tprintln('${filepath}:${cline.line}: ${cline.comment}')\n\t\t\t\t\tctx.errors++\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nstruct CommentLine {\n\tcomment string\n\tline    int\n}\n"
  },
  {
    "path": "cmd/tools/fuzz/fuzz.sh",
    "content": "#!/bin/sh\n\ncores=$(nproc --all)\n\necho Number of cores: $cores\necho Compiling...\n./v -cc clang -o cmd/tools/fuzz/map_fuzz cmd/tools/fuzz/map_fuzz.v -prod -cflags \"-fsanitize=memory\"\n\necho Fuzzing:\nwhile true\ndo\n  for ((i=1;i<=cores;++i))\n  do\n    sleep 0.001\n    ./cmd/tools/fuzz/map_fuzz &\n  done\n  wait\ndone\n"
  },
  {
    "path": "cmd/tools/fuzz/fuzz_v_parser_with_radamsa.sh",
    "content": "#!/usr/bin/env bash\n\n## Note: radamsa is a fuzzer, available from https://gitlab.com/akihe/radamsa\n\nexport VFUZZER=true\nexport OUTPUT_FILE=${1:-x.v}\nexport PARSER_EXECUTABLE=${2:-cmd/tools/measure/parser_speed}\n\necho \"Fuzzing parameters | OUTPUT FILE: ${OUTPUT_FILE} | PARSER_EXECUTABLE: ${PARSER_EXECUTABLE}\"\n\nif [ ! -f $PARSER_EXECUTABLE ]; then\n\tv -g -o \"${PARSER_EXECUTABLE}\" cmd/tools/measure/parser_speed.v\nfi\t\n\nwhile true; do\n\tradamsa --meta \"${OUTPUT_FILE}.autofuzz.log\" examples/hello_world.v > \"${OUTPUT_FILE}\";\n\techo -ne \"OFILE: ${OUTPUT_FILE}\"; ./\"${PARSER_EXECUTABLE}\" ${OUTPUT_FILE} || break;\ndone\n"
  },
  {
    "path": "cmd/tools/fuzz/map_fuzz.v",
    "content": "import rand\nimport time\n\nfn generate_strings(str_len int, arr_len int) []string {\n\tmut arr := []string{len: arr_len}\n\tfor i in 0 .. arr_len {\n\t\tarr[i] = rand.string(str_len)\n\t}\n\treturn arr\n}\n\nfn fuzz1() {\n\tamount := 200000 - rand.intn(100000) or { 0 }\n\tamount2 := 200000 - rand.intn(100000) or { 0 }\n\tlen := 25 - rand.intn(10) or { 0 }\n\tarr := generate_strings(len, amount)\n\tarr2 := generate_strings(len, amount2)\n\tmut m := map[string]int{}\n\tfor i in 0 .. amount {\n\t\tm[arr[i]] = i\n\t\tassert i == m[arr[i]]\n\t}\n\tfor i in 0 .. amount {\n\t\tassert i == m[arr[i]]\n\t}\n\tfor i in 0 .. amount2 {\n\t\tassert 0 == m[arr2[i]]\n\t}\n\tunsafe {\n\t\tm.free()\n\t\tarr.free()\n\t}\n}\n\nfn fuzz2() {\n\tmut m := map[string]int{}\n\tamount := rand.intn(500000) or { 0 } + 1\n\tlen := 25 - rand.intn(10) or { 0 }\n\tarr := generate_strings(len, amount)\n\tfor i, x in arr {\n\t\tm[x] = i\n\t}\n\tmut i := 0\n\tfor key, val in m {\n\t\tassert key == arr[i]\n\t\tassert val == i\n\t\ti++\n\t}\n\tunsafe {\n\t\tm.free()\n\t\tarr.free()\n\t}\n}\n\nfn fuzz3() {\n\tmut m := map[string]int{}\n\tamount := rand.intn(500000) or { 0 } + 1\n\tlen := 25 - rand.intn(10) or { 0 }\n\tarr := generate_strings(len, amount)\n\tfor i, x in arr {\n\t\tif (i % 10000) == 0 {\n\t\t\tkeys := m.keys()\n\t\t\tassert keys.len == i\n\t\t\tassert keys == arr[0..i]\n\t\t}\n\t\tm[x] = i\n\t}\n\tassert m.keys() == arr\n\tassert m.keys().len == amount\n\tunsafe {\n\t\tm.free()\n\t\tarr.free()\n\t}\n}\n\nfn fuzz4() {\n\tamount := rand.intn(500000) or { 0 }\n\tlen := 25 - rand.intn(10) or { 0 }\n\tarr := generate_strings(len, amount)\n\tmut m := map[string]int{}\n\tfor i in 0 .. amount {\n\t\tm[arr[i]] = i\n\t}\n\tfor i in 0 .. amount {\n\t\tm.delete(arr[i])\n\t\tassert m[arr[i]] == 0\n\t}\n\tassert m.len == 0\n\tunsafe {\n\t\tm.free()\n\t\tarr.free()\n\t}\n}\n\nfn fuzz5() {\n\tamount := rand.intn(500000) or { 0 } + 1\n\tarr := generate_strings(20, amount)\n\tmut m := map[string]int{}\n\tfor i in 0 .. amount {\n\t\tm[arr[i]] = i\n\t\tassert (arr[i] in m) == true\n\t}\n\tfor i in 0 .. amount {\n\t\tm.delete(arr[i])\n\t\tassert (arr[i] !in m) == true\n\t\tassert m.len == amount - i - 1\n\t}\n\tassert m.len == 0\n\tunsafe {\n\t\tm.free()\n\t\tarr.free()\n\t}\n}\n\nfn fuzz6() {\n\tmut m := map[string]int{}\n\tamount := rand.intn(500000) or { 0 } + 1\n\tlen := 25 - rand.intn(10) or { 0 }\n\tarr := generate_strings(len, amount)\n\tfor i, x in arr {\n\t\tm[x]++\n\t\tm[x] += i\n\t\tassert m[x] == i + 1\n\t}\n\tfor i, x in arr {\n\t\tassert m[x] == i + 1\n\t}\n\tunsafe {\n\t\tm.free()\n\t\tarr.free()\n\t}\n}\n\nfn main() {\n\tseed := u32(time.ticks())\n\tprintln('seed: ${seed.hex()}')\n\trand.seed([seed, seed])\n\tfuzz1()\n\tfuzz2()\n\tfuzz3()\n\tfuzz4()\n\tfuzz5()\n\tfuzz6()\n}\n"
  },
  {
    "path": "cmd/tools/gen1m.v",
    "content": "fn main() {\n\tfor i in 0 .. 100000 {\n\t\tprintln('\nfn foo${i}() {\n\tx := ${i}\n\tmut a := 1 + x\n\ta += 2\n\tprint(a)\n\ta = 0\n\ta = 1\n}\n')\n\t}\n\t// println('fn main() {foo1()} ')\n\tprintln('fn main() { println(\"1m DONE\") } ')\n}\n"
  },
  {
    "path": "cmd/tools/gen_vc.v",
    "content": "module main\n\nimport os\nimport log\nimport flag\nimport time\nimport veb\nimport net.urllib\n\n// This tool regenerates V's bootstrap .c files\n// every time the V master branch is updated.\n// if run with the --serve flag it will run in webhook\n// server mode awaiting a request to http://host:port/genhook\n// available command line flags:\n// --work-dir  gen_vc's working directory\n// --purge     force purge the local repositories\n// --serve     run in webhook server mode\n// --port      port for http server to listen on\n// --log-to    either 'file' or 'terminal'\n// --log-file  path to log file used when --log-to is 'file'\n// --dry-run   dont push anything to remote repo\n// --force     force update even if already up to date\n\n// git credentials\nconst git_username = os.getenv('GITUSER')\nconst git_password = os.getenv('GITPASS')\n\n// repository\n// git repo\nconst git_repo_v = 'github.com/vlang/v'\nconst git_repo_vc = 'github.com/vlang/vc'\n// local repo directories\nconst git_repo_dir_v = 'v'\nconst git_repo_dir_vc = 'vc'\n\n// gen_vc\n// name\nconst app_name = 'gen_vc'\n// version\nconst app_version = '0.1.3'\n// description\nconst app_description = \"This tool regenerates V's bootstrap .c files every time the V master branch is updated.\"\n// assume something went wrong if file size less than this\nconst too_short_file_limit = 5000\n// create a .c file for these os's\nconst vc_build_oses = [\n\t'nix',\n\t// all nix based os\n\t'windows',\n]\n\n// default options (overridden by flags)\n// gen_vc working directory\nconst work_dir = '/tmp/gen_vc'\n// dont push anything to remote repo\nconst dry_run = false\n// server port\nconst server_port = 7171\n// log file\nconst log_file = '${work_dir}/log.txt'\n// log_to is either 'file' or 'terminal'\nconst log_to = 'terminal'\n\n// errors\nconst err_msg_build = 'error building'\nconst err_msg_make = 'make failed'\nconst err_msg_gen_c = 'failed to generate .c file'\nconst err_msg_cmd_x = 'error running cmd'\n\nstruct GenVC {\n\t// logger\n\t// flag options\n\toptions FlagOptions\nmut:\n\tlogger &log.Log = unsafe { nil }\n\t// true if error was experienced running generate\n\tgen_error bool\n}\n\n// webhook server\nstruct WebhookServer {\nmut:\n\tgen_vc &GenVC = unsafe { nil } // initialized in init_server\n}\n\nstruct Context {\n\tveb.Context\n}\n\n// storage for flag options\nstruct FlagOptions {\n\twork_dir string\n\tpurge    bool\n\tserve    bool\n\tport     int\n\tlog_to   string\n\tlog_file string\n\tdry_run  bool\n\tforce    bool\n}\n\nfn main() {\n\tlog.use_stdout()\n\tmut fp := flag.new_flag_parser(os.args.clone())\n\tfp.application(app_name)\n\tfp.version(app_version)\n\tfp.description(app_description)\n\tfp.skip_executable()\n\tshow_help := fp.bool('help', 0, false, 'Show this help screen\\n')\n\tflag_options := parse_flags(mut fp)\n\tif show_help {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\tfp.finalize() or {\n\t\teprintln(err)\n\t\tprintln(fp.usage())\n\t\treturn\n\t}\n\t// webhook server mode\n\tif flag_options.serve {\n\t\tmut server := &WebhookServer{}\n\t\tveb.run_at[WebhookServer, Context](mut server, port: flag_options.port)!\n\t} else {\n\t\t// cmd mode\n\t\tmut gen_vc := new_gen_vc(flag_options)\n\t\tgen_vc.init()\n\t\tgen_vc.generate()\n\t}\n}\n\n// new GenVC\nfn new_gen_vc(flag_options FlagOptions) &GenVC {\n\tmut logger := &log.Log{}\n\tlogger.set_level(.debug)\n\tif flag_options.log_to == 'file' {\n\t\tlogger.set_full_logpath(flag_options.log_file)\n\t}\n\treturn &GenVC{\n\t\toptions: flag_options\n\t\tlogger:  logger\n\t}\n}\n\n// WebhookServer init\npub fn (mut ws WebhookServer) init_server() {\n\tmut fp := flag.new_flag_parser(os.args.clone())\n\tflag_options := parse_flags(mut fp)\n\tws.gen_vc = new_gen_vc(flag_options)\n\tws.gen_vc.init()\n\t// ws.gen_vc = new_gen_vc(flag_options)\n}\n\npub fn (mut ws WebhookServer) index() {\n\teprintln('WebhookServer.index() called')\n}\n\n// gen webhook\npub fn (mut ws WebhookServer) genhook() veb.Result {\n\t// request data\n\t// println(ws.vweb.req.data)\n\t// TODO: parse request. json or urlencoded\n\t// json.decode or net.urllib.parse\n\tws.gen_vc.generate()\n\t// error in generate\n\tif ws.gen_vc.gen_error {\n\t\treturn ctx.json('{status: \"failed\"}')\n\t}\n\treturn ctx.json('{status: \"ok\"}')\n}\n\npub fn (ws &WebhookServer) reset() {\n}\n\n// parse flags to FlagOptions struct\nfn parse_flags(mut fp flag.FlagParser) FlagOptions {\n\treturn FlagOptions{\n\t\tserve:    fp.bool('serve', 0, false, 'run in webhook server mode')\n\t\twork_dir: fp.string('work-dir', 0, work_dir, 'gen_vc working directory')\n\t\tpurge:    fp.bool('purge', 0, false, 'force purge the local repositories')\n\t\tport:     fp.int('port', 0, server_port, 'port for web server to listen on')\n\t\tlog_to:   fp.string('log-to', 0, log_to, \"log to is 'file' or 'terminal'\")\n\t\tlog_file: fp.string('log-file', 0, log_file, \"log file to use when log-to is 'file'\")\n\t\tdry_run:  fp.bool('dry-run', 0, dry_run, 'when specified dont push anything to remote repo')\n\t\tforce:    fp.bool('force', 0, false, 'force update even if already up to date')\n\t}\n}\n\nfn (mut gen_vc GenVC) init() {\n\t// purge repos if flag is passed\n\tif gen_vc.options.purge {\n\t\tgen_vc.purge_repos()\n\t}\n}\n\n// regenerate\nfn (mut gen_vc GenVC) generate() {\n\t// set errors to false\n\tgen_vc.gen_error = false\n\t// check if gen_vc dir exists\n\tif !os.is_dir(gen_vc.options.work_dir) {\n\t\t// try create\n\t\tos.mkdir(gen_vc.options.work_dir) or { panic(err) }\n\t\t// still doesn't exist... we have a problem\n\t\tif !os.is_dir(gen_vc.options.work_dir) {\n\t\t\tgen_vc.logger.error('error creating directory: ${gen_vc.options.work_dir}')\n\t\t\tgen_vc.gen_error = true\n\t\t\treturn\n\t\t}\n\t}\n\t// cd to gen_vc dir\n\tos.chdir(gen_vc.options.work_dir) or {}\n\t// if we are not running with the --serve flag (webhook server)\n\t// rather than deleting and re-downloading the repo each time\n\t// first check to see if the local v repo is behind master\n\t// if it isn't behind there's no point continuing further\n\tif !gen_vc.options.serve && os.is_dir(git_repo_dir_v) {\n\t\tgen_vc.cmd_exec('git -C ${git_repo_dir_v} checkout master')\n\t\t// fetch the remote repo just in case there are newer commits there\n\t\tgen_vc.cmd_exec('git -C ${git_repo_dir_v} fetch')\n\t\tgit_status := gen_vc.cmd_exec('git -C ${git_repo_dir_v} status')\n\t\tif !git_status.contains('behind') && !gen_vc.options.force {\n\t\t\tgen_vc.logger.warn('v repository is already up to date.')\n\t\t\treturn\n\t\t}\n\t}\n\t// delete repos\n\tgen_vc.purge_repos()\n\t// clone repos\n\tgen_vc.cmd_exec('git clone --filter=blob:none https://${git_repo_v} ${git_repo_dir_v}')\n\tgen_vc.cmd_exec('git clone --filter=blob:none https://${git_repo_vc} ${git_repo_dir_vc}')\n\t// get output of git log -1 (last commit)\n\tgit_log_v := gen_vc.cmd_exec('git -C ${git_repo_dir_v} log -1 --format=\"commit %H%nDate: %ci%nDate Unix: %ct%nSubject: %s\"')\n\tgit_log_vc := gen_vc.cmd_exec('git -C ${git_repo_dir_vc} log -1 --format=\"Commit %H%nDate: %ci%nDate Unix: %ct%nSubject: %s\"')\n\t// date of last commit in each repo\n\tts_v := git_log_v.find_between('Date:', '\\n').trim_space()\n\tts_vc := git_log_vc.find_between('Date:', '\\n').trim_space()\n\t// parse time as string to time.Time\n\tlast_commit_time_v := time.parse(ts_v) or { panic(err) }\n\tlast_commit_time_vc := time.parse(ts_vc) or { panic(err) }\n\t// git dates are in users local timezone and v time.parse does not parse\n\t// timezones at the moment, so for now get unix timestamp from output also\n\tt_unix_v := git_log_v.find_between('Date Unix:', '\\n').trim_space().int()\n\tt_unix_vc := git_log_vc.find_between('Date Unix:', '\\n').trim_space().int()\n\t// last commit hash in v repo\n\tlast_commit_hash_v := git_log_v.find_between('commit', '\\n').trim_space()\n\tlast_commit_hash_v_short := last_commit_hash_v[..7]\n\t// subject\n\tlast_commit_subject := git_log_v.find_between('Subject:', '\\n').trim_space().replace(\"'\",\n\t\t'\"')\n\t// log some info\n\tgen_vc.logger.debug('last commit time (${git_repo_v}): ' + last_commit_time_v.format_ss())\n\tgen_vc.logger.debug('last commit time (${git_repo_vc}): ' + last_commit_time_vc.format_ss())\n\tgen_vc.logger.debug('last commit hash (${git_repo_v}): ${last_commit_hash_v}')\n\tgen_vc.logger.debug('last commit subject (${git_repo_v}): ${last_commit_subject}')\n\t// if vc repo already has a newer commit than the v repo, assume it's up to date\n\tif t_unix_vc >= t_unix_v && !gen_vc.options.force {\n\t\tgen_vc.logger.warn('vc repository is already up to date.')\n\t\treturn\n\t}\n\t// try build v for current os (linux in this case)\n\tgen_vc.cmd_exec('make -C ${git_repo_dir_v}')\n\tv_exec := '${git_repo_dir_v}/v'\n\t// check if make was successful\n\tgen_vc.assert_file_exists_and_is_not_too_short(v_exec, err_msg_make)\n\t// build v.c for each os\n\tfor os_name in vc_build_oses {\n\t\tc_file := if os_name == 'nix' { 'v.c' } else { 'v_win.c' }\n\t\tv_flags := if os_name == 'nix' { '-os cross' } else { '-os ${os_name}' }\n\t\t// try generate .c file\n\t\tgen_vc.cmd_exec('${v_exec} ${v_flags} -o ${c_file} ${git_repo_dir_v}/cmd/v')\n\t\t// check if the c file seems ok\n\t\tgen_vc.assert_file_exists_and_is_not_too_short(c_file, err_msg_gen_c)\n\t\t// embed the latest v commit hash into the c file\n\t\tgen_vc.cmd_exec('sed -i \\'1s/^/#define V_COMMIT_HASH \"${last_commit_hash_v_short}\"\\\\n/\\' ${c_file}')\n\t\t// move to vc repo\n\t\tgen_vc.cmd_exec('mv ${c_file} ${git_repo_dir_vc}/${c_file}')\n\t\t// add new .c file to local vc repo\n\t\tgen_vc.cmd_exec('git -C ${git_repo_dir_vc} add ${c_file}')\n\t}\n\t// check if the vc repo actually changed\n\tgit_status := gen_vc.cmd_exec('git -C ${git_repo_dir_vc} status')\n\tif git_status.contains('nothing to commit') {\n\t\tgen_vc.logger.error('no changes to vc repo: something went wrong.')\n\t\tgen_vc.gen_error = true\n\t}\n\t// commit changes to local vc repo\n\tgen_vc.cmd_exec_safe(\"git -C ${git_repo_dir_vc} commit -m '[v:master] ${last_commit_hash_v_short} - ${last_commit_subject}'\")\n\t// push changes to remote vc repo\n\tgen_vc.cmd_exec_safe('git -C ${git_repo_dir_vc} push https://${urllib.query_escape(git_username)}:${urllib.query_escape(git_password)}@${git_repo_vc} master')\n}\n\n// only execute when dry_run option is false, otherwise just log\nfn (mut gen_vc GenVC) cmd_exec_safe(cmd string) string {\n\treturn gen_vc.command_execute(cmd, gen_vc.options.dry_run)\n}\n\n// always execute command\nfn (mut gen_vc GenVC) cmd_exec(cmd string) string {\n\treturn gen_vc.command_execute(cmd, false)\n}\n\n// execute command\nfn (mut gen_vc GenVC) command_execute(cmd string, dry bool) string {\n\t// if dry is true then dont execute, just log\n\tif dry {\n\t\treturn gen_vc.command_execute_dry(cmd)\n\t}\n\tgen_vc.logger.info('cmd: ${cmd}')\n\tr := os.execute(cmd)\n\tif r.exit_code < 0 {\n\t\tgen_vc.logger.error('${err_msg_cmd_x}: \"${cmd}\" could not start.')\n\t\tgen_vc.logger.error(r.output)\n\t\t// something went wrong, better start fresh next time\n\t\tgen_vc.purge_repos()\n\t\tgen_vc.gen_error = true\n\t\treturn ''\n\t}\n\tif r.exit_code != 0 {\n\t\tgen_vc.logger.error('${err_msg_cmd_x}: \"${cmd}\" failed.')\n\t\tgen_vc.logger.error(r.output)\n\t\t// something went wrong, better start fresh next time\n\t\tgen_vc.purge_repos()\n\t\tgen_vc.gen_error = true\n\t\treturn ''\n\t}\n\treturn r.output\n}\n\n// just log cmd, dont execute\nfn (mut gen_vc GenVC) command_execute_dry(cmd string) string {\n\tgen_vc.logger.info('cmd (dry): \"${cmd}\"')\n\treturn ''\n}\n\n// delete repo directories\nfn (mut gen_vc GenVC) purge_repos() {\n\t// delete old repos (better to be fully explicit here, since these are destructive operations)\n\tmut repo_dir := '${gen_vc.options.work_dir}/${git_repo_dir_v}'\n\tif os.is_dir(repo_dir) {\n\t\tgen_vc.logger.info('purging local repo: \"${repo_dir}\"')\n\t\tgen_vc.cmd_exec('rm -rf ${repo_dir}')\n\t}\n\trepo_dir = '${gen_vc.options.work_dir}/${git_repo_dir_vc}'\n\tif os.is_dir(repo_dir) {\n\t\tgen_vc.logger.info('purging local repo: \"${repo_dir}\"')\n\t\tgen_vc.cmd_exec('rm -rf ${repo_dir}')\n\t}\n}\n\n// check if file size is too short\nfn (mut gen_vc GenVC) assert_file_exists_and_is_not_too_short(f string, emsg string) {\n\tif !os.exists(f) {\n\t\tgen_vc.logger.error('${err_msg_build}: ${emsg} .')\n\t\tgen_vc.gen_error = true\n\t\treturn\n\t}\n\tfsize := os.file_size(f)\n\tif fsize < too_short_file_limit {\n\t\tgen_vc.logger.error('${err_msg_build}: ${f} exists, but is too short: only ${fsize} bytes.')\n\t\tgen_vc.gen_error = true\n\t\treturn\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/gg_split_memdump_to_frames.vsh",
    "content": "#!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp\n\nmodule main\n\nimport os\nimport log\n\nfn write_chunk(n int, min_size int, original string, start int, end int) {\n\tsize := end - start\n\tif size < min_size {\n\t\treturn\n\t}\n\tframe_file := 'frame_${n:06}.bin'\n\tlog.warn('writing ${frame_file}, from start: ${start:9}, to end: ${end:9} | size: ${size:9} >= ${min_size:9}, memuse: ${gc_memory_use()}')\n\tos.write_file(frame_file, original#[start..end]) or { log.error(err.str()) }\n}\n\nfn main() {\n\tlog.info('Start.')\n\tfpath := os.args[2] or { 'memdump.bin' }\n\tseparator := os.args[3] or { '@@ gg_memory_trace_frame' }\n\tmin_size := os.args[1] or { '${separator.len}' }.int()\n\tlog.info('Splitting chunk min_size (arg 1): ${min_size}, file (arg 2): ${fpath}, by string separator (arg 3): `${separator}` ...')\n\tlog.info('Memory use before reading: ${gc_memory_use()}')\n\toriginal := os.read_file(fpath)!\n\tlog.info('file size: ${original.len}')\n\tlog.info('Memory use after reading: ${gc_memory_use()}')\n\tmut n := 0\n\tfor start := 0; start < original.len; {\n\t\tgc_collect()\n\t\tidx := original.index_after_(separator, start + separator.len) // ensure that we advance each time\n\t\tif idx < 0 {\n\t\t\twrite_chunk(n, min_size, original, start, original.len)\n\t\t\tbreak\n\t\t}\n\t\twrite_chunk(n, min_size, original, start, idx)\n\t\tstart = idx\n\t\tn++\n\t}\n\tlog.info('Memory use after processing: ${gc_memory_use()}')\n\tlog.info('Done.')\n}\n"
  },
  {
    "path": "cmd/tools/git_pre_commit_hook.vsh",
    "content": "#!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp\n\nimport os\nimport term\n\n// This script can be used to ensure that all committed V files are vfmt-ed automatically.\n// By default, once setup, it will run `v fmt -w` on them, before committing them.\n\n// To use the script in your V project, you need to be in the main folder\n// of your project, then do the equivalent of:\n// ```sh\n// cp /PATH/TO_YOUR/V/cmd/tools/git_pre_commit_hook.vsh .git/hooks/pre-commit\n// chmod 755 .git/hooks/pre-commit\n// ```\n//\n// You could also use `vgit-fmt-hook` tool to install/update/remove and get\n// status for this hook.\n// This tool copies the git hook VSH script in .git/hooks/pre-commit\n//\n// Note: you can use this command:\n// `git config --bool --add hooks.stopCommitOfNonVfmtedVFiles true`\n// ... to make it just *prevent* the committing of unformatted .v files,\n// i.e. stop the committing, if they are not, but *without modifying them*\n// automatically (you will then need to run `v fmt -w` on them manually).\n//\n// Note 2: Git supports skipping the hooks, by passing the `--no-verify` option.\n// That can be used to commit some .v files that are not formatted, without removing\n// the hook.\n\nfn main() {\n\t// This hook cares only about the changed V files, that will be committed, as reported by git itself:\n\tchanged := os.execute('git diff --cached --name-only --diff-filter=ACMR -- \"*.v\" \"*.vsh\" \"*.vv\"')\n\n\tall_changed_vfiles := changed.output.trim_space().split('\\n')\n\t// _input.vv files are NOT formatted on purpose.\n\t// There is no point in verifying them, or ruining them over with `v fmt -w`.\n\t// Just filter them out, but still report to the user, that they will not be formatted:\n\tvfiles := all_changed_vfiles.filter(!it.ends_with('_input.vv'))\n\tinput_vfiles := all_changed_vfiles.filter(it.ends_with('_input.vv'))\n\tif input_vfiles.len > 0 {\n\t\teprintln('>>> ${input_vfiles.len} `_input.vv` files found, that *will NOT be* formatted.')\n\t\tfor ifile in input_vfiles {\n\t\t\teprintln('     ${ifile}')\n\t\t}\n\t}\n\tif changed.output == '' || vfiles.len == 0 {\n\t\teprintln('>>> 0 changed V files, that may need formatting found.')\n\t\texit(0)\n\t}\n\tconfigured_stop_committing := os.execute('git config --bool hooks.stopCommitOfNonVfmtedVFiles')\n\tif configured_stop_committing.output.trim_space().bool() {\n\t\tverify_result := os.execute('${os.quoted_path(@VEXE)} fmt -verify ${vfiles.join(' ')}')\n\t\tif verify_result.exit_code != 0 {\n\t\t\teprintln(verify_result.output)\n\t\t}\n\t\texit(verify_result.exit_code)\n\t} else {\n\t\teprintln('The V pre commit hook will format ${vfiles.len} V file(s):')\n\t\t// vfmt off\n\t\tfor vfile in vfiles {\n\t\t\teprintln('    ${term.bold('${vfile}')}')\n\t\t}\n\t\t// vfmt on\n\t\tall_vfiles_on_a_line := vfiles.map(os.quoted_path(it)).join(' ')\n\t\tos.system('${os.quoted_path(@VEXE)} fmt -w ${all_vfiles_on_a_line}')\n\t\tos.system('git add ${all_vfiles_on_a_line}')\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/install_binaryen.vsh",
    "content": "#!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp\n\nimport os\nimport net.http\n\nconst github_job = os.getenv('GITHUB_JOB')\n\nstruct JQ {\n\ttag_name string\n}\n\nfn main() {\n\troot := os.real_path(os.dir(os.getenv_opt('VEXE') or { @VEXE }))\n\tos.chdir(root)! // make sure that the workfolder is stable\n\n\ttloc := os.join_path(root, 'thirdparty')\n\tloc := os.join_path(tloc, 'binaryen')\n\n\tif os.exists(loc) {\n\t\teprintln('thirdparty/binaryen exists, will not overwrite')\n\t\teprintln('delete the folder, and execute again')\n\t\texit(1)\n\t}\n\n\t/*\n\t// TODO: add retries here, github requests can fail\n\tjq := http.get_text('https://api.github.com/repos/WebAssembly/binaryen/releases/latest')\n\ttag := json.decode(JQ, jq)!.tag_name\n\t     if github_job != '' {\n\t             dump(jq)\n\t             dump(tag)\n\t     }\n\t*/\n\ttag := 'version_112'\n\n\tname := $if windows {\n\t\t'x86_64-windows'\n\t} $else $if macos {\n\t\t$if arm64 {\n\t\t\t'arm64-macos'\n\t\t} $else {\n\t\t\t'x86_64-macos'\n\t\t}\n\t} $else $if linux {\n\t\t'x86_64-linux'\n\t} $else {\n\t\teprintln('A premade binary library is not available for your system.')\n\t\teprintln('Build it from source, following the documentation here: https://github.com/WebAssembly/binaryen/#building')\n\t\texit(1)\n\t}\n\n\tfname := 'binaryen-${tag}'\n\turl := 'https://github.com/WebAssembly/binaryen/releases/download/${tag}/${fname}-${name}.tar.gz'\n\n\tsaveloc := os.join_path(tloc, '${fname}.tar.gz')\n\tif !os.exists(saveloc) {\n\t\tprintln('Downloading archive: ${saveloc}, from url: ${url} ...')\n\t\thttp.download_file(url, saveloc)!\n\t\t// defer { os.rm(saveloc) or {}! }\n\t}\n\n\tprintln('Extracting `${tloc}/${fname}` to `${tloc}/binaryen` ...')\n\tcmd := 'tar -xvf ${saveloc} --directory ${tloc}'\n\tif os.system(cmd) != 0 {\n\t\teprintln('`${cmd}` exited with a non zero exit code')\n\t\texit(1)\n\t}\n\n\tprintln(cmd)\n\tprintln('Moving `${tloc}/${fname}` to `${tloc}/binaryen` ...')\n\n\tos.rename_dir('${tloc}/${fname}', loc)!\n\tprintln('Done. You can now use `v -b wasm file.v` .')\n}\n"
  },
  {
    "path": "cmd/tools/install_wabt.vsh",
    "content": "#!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp\n\nimport os\nimport net.http\n\nfn main() {\n\tos.chdir(@VEXEROOT)! // make sure that the workfolder is stable\n\ttloc := os.join_path(@VEXEROOT, 'thirdparty')\n\tloc := os.join_path(tloc, 'wabt')\n\tif os.exists(loc) {\n\t\teprintln('thirdparty/wabt exists, will not overwrite')\n\t\teprintln('delete the folder, and execute again')\n\t\texit(1)\n\t}\n\ttag := '1.0.32'\n\tfname := 'wabt-${tag}'\n\tmut platform := ''\n\t$if windows {\n\t\tplatform = 'windows'\n\t} $else $if macos {\n\t\tplatform = 'macos-14'\n\t} $else $if linux {\n\t\tplatform = 'ubuntu'\n\t} $else {\n\t\teprintln('A premade binary library is not available for your system.')\n\t\teprintln('Build it from source, following the documentation here: https://github.com/WebAssembly/wabt/')\n\t\texit(1)\n\t}\n\turl := 'https://github.com/WebAssembly/wabt/releases/download/${tag}/${fname}-${platform}.tar.gz'\n\tsaveloc := os.join_path(tloc, '${fname}.tar.gz')\n\tprintln('>> Url: ${url}')\n\tprintln('>> Archive: ${saveloc}')\n\tif !os.exists(saveloc) {\n\t\tprintln('Downloading archive: ${saveloc}, from url: ${url} ...')\n\t\thttp.download_file(url, saveloc)!\n\t\t// defer { os.rm(saveloc) or {}! }\n\t}\n\tprintln('Extracting `${tloc}/${fname}` to `${tloc}/wabt` ...')\n\tcmd := 'tar -xvf ${saveloc} --directory ${tloc}'\n\tif os.system(cmd) != 0 {\n\t\teprintln('`${cmd}` exited with a non zero exit code')\n\t\texit(1)\n\t}\n\tprintln(cmd)\n\tprintln('Moving `${tloc}/${fname}` to `${tloc}/wabt` ...')\n\tos.rename_dir('${tloc}/${fname}', loc)!\n\tprintln('Done. You can now use `v test vlib/wasm` .')\n}\n"
  },
  {
    "path": "cmd/tools/measure/file_lists/expand.v",
    "content": "module file_lists\n\nimport os\n\n// expand_files accepts a list of files and folders, and returns a list of all the .v and .vsh files, found in them.\n// The input list of files, supports recursive `@file.lst` expansion, where each line is treated as another file/folder.\npub fn expand_files(files []string) ![]string {\n\tmut res := []string{}\n\tfor file in files {\n\t\tif file == '' {\n\t\t\tcontinue\n\t\t}\n\t\tif file.starts_with('@') {\n\t\t\tlst_path := files[0].all_after('@').trim_space()\n\t\t\tlisted_files := os.read_file(lst_path)!.split('\\n').map(it.trim_space())\n\t\t\tres << expand_files(listed_files)!\n\t\t\tcontinue\n\t\t}\n\t\tif os.is_dir(file) {\n\t\t\tres << os.walk_ext(file, '.vsh')\n\t\t\tres << os.walk_ext(file, '.v')\n\t\t\tcontinue\n\t\t}\n\t\tif os.exists(file) {\n\t\t\tres << file\n\t\t}\n\t}\n\treturn res\n}\n"
  },
  {
    "path": "cmd/tools/measure/fmt_speed.v",
    "content": "import os\nimport time\nimport v.ast\nimport v.fmt\nimport v.pref\nimport v.parser\nimport v.errors\nimport v.scanner\nimport term\nimport file_lists\n\nconst skip_tests = os.getenv('SKIP_TESTS').bool()\nconst fuzzer_mode = os.getenv('VFUZZER').bool()\nconst comments_mode = scanner.CommentsMode.from(os.getenv('SCANNER_MODE')) or {\n\tscanner.CommentsMode.parse_comments\n}\n\nfn main() {\n\tif !fuzzer_mode {\n\t\tdump(comments_mode)\n\t}\n\tall_files := file_lists.expand_files(os.args#[1..])!\n\tprocess_files(all_files)!\n}\n\nfn hline() {\n\tif fuzzer_mode {\n\t\treturn\n\t}\n\tprintln('----------------------------------------------------------------------------------------------------------------------------------------------------------')\n}\n\nfn theader() {\n\tif fuzzer_mode {\n\t\treturn\n\t}\n\tprintln('        Time     Tokens      Bytes      Lines   Bytes/Token     Errors   FMT.len')\n}\n\nfn process_files(files []string) ! {\n\tnthreads := 1 // TODO\n\tmut pref_ := pref.new_preferences()\n\tpref_.is_fmt = true\n\tpref_.skip_warnings = true\n\tpref_.output_mode = .silent\n\tmut sw := time.new_stopwatch()\n\tmut total_us := i64(0)\n\tmut total_bytes := i64(0)\n\tmut total_tokens := i64(0)\n\tmut total_lines := i64(0)\n\tmut total_errors := i64(0)\n\tmut total_files := i64(0)\n\tmut total_fmt_len := i64(0)\n\tfor f in files {\n\t\tmut table := ast.new_table()\n\t\tif f == '' {\n\t\t\tcontinue\n\t\t}\n\t\tif skip_tests && f.ends_with('_test.v') {\n\t\t\tcontinue\n\t\t}\n\t\ttotal_files++\n\t\tmut p := new_parser(f, comments_mode, table, pref_)\n\t\tast_file := p.parse()\n\t\t///\n\t\t// do not measure the scanning, and parsing, but only the formatting:\n\t\tsw.restart()\n\t\tformatted_content := fmt.fmt(ast_file, mut table, pref_, false)\n\t\tf_us := sw.elapsed().microseconds()\n\t\t// eprint(formatted_content) // this should be identical to the output of `v fmt file.v`\n\t\t///\n\t\ttotal_us += f_us\n\t\ttotal_bytes += p.scanner.text.len\n\t\ttotal_tokens += p.scanner.all_tokens.len\n\t\ttotal_lines += ast_file.nr_lines\n\t\ttotal_errors += p.errors.len\n\t\ttotal_fmt_len += formatted_content.len\n\t\tif !fuzzer_mode {\n\t\t\tprintln('${f_us:10}us ${p.scanner.all_tokens.len:10} ${p.scanner.text.len:10} ${ast_file.nr_lines:10} ${(f64(p.scanner.text.len) / p.scanner.all_tokens.len):13.3} ${p.errors.len:10}  ${formatted_content.len:8}   ${f}')\n\t\t}\n\t}\n\thline()\n\ttheader()\n\thline()\n\tspeed_mb_s := term.colorize(term.bright_yellow, '${(f64(total_bytes) / total_us):6.3f} MB/s')\n\tspeed_lines_s := term.colorize(term.bright_yellow, '${(1_000_000 * f64(total_lines) / total_us):10.1f} lines/s')\n\tprintln('${total_us:10}us ${total_tokens:10} ${total_bytes:10} ${total_lines:10} ${(f64(total_bytes) / total_tokens):13.3} ${total_errors:10}   ${total_fmt_len:7}   FMT speed: ${speed_mb_s}, ${speed_lines_s}, ${nthreads:3} thread(s), ${total_files:5} files.')\n}\n\nfn new_parser(path string, comments_mode scanner.CommentsMode, table &ast.Table, pref_ &pref.Preferences) &parser.Parser {\n\tmut p := &parser.Parser{\n\t\tscanner:  scanner.new_scanner_file(path, -1, comments_mode, pref_) or { panic(err) }\n\t\ttable:    table\n\t\tpref:     pref_\n\t\tscope:    &ast.Scope{\n\t\t\tstart_pos: 0\n\t\t\tparent:    table.global_scope\n\t\t}\n\t\terrors:   []errors.Error{}\n\t\twarnings: []errors.Warning{}\n\t}\n\tp.set_path(path)\n\treturn p\n}\n"
  },
  {
    "path": "cmd/tools/measure/parser_speed.v",
    "content": "import os\nimport time\nimport v.ast\nimport v.pref\nimport v.parser\nimport v.errors\nimport v.scanner\nimport term\nimport file_lists\n\nconst skip_tests = os.getenv('SKIP_TESTS').bool()\nconst fuzzer_mode = os.getenv('VFUZZER').bool()\nconst comments_mode = scanner.CommentsMode.from(os.getenv('SCANNER_MODE')) or {\n\tscanner.CommentsMode.skip_comments\n}\n\nfn main() {\n\tif !fuzzer_mode {\n\t\tdump(comments_mode)\n\t}\n\tall_files := file_lists.expand_files(os.args#[1..])!\n\tprocess_files(all_files)!\n}\n\nfn hline() {\n\tif fuzzer_mode {\n\t\treturn\n\t}\n\tprintln('---------------------------------------------------------------------------------------------------------------------------------------------------')\n}\n\nfn theader() {\n\tif fuzzer_mode {\n\t\treturn\n\t}\n\tprintln('        Time     Tokens      Bytes      Lines   Bytes/Token     Errors')\n}\n\nfn process_files(files []string) ! {\n\tnthreads := 1 // TODO\n\tmut pref_ := pref.new_preferences()\n\tpref_.is_fmt = true\n\tpref_.skip_warnings = true\n\tpref_.output_mode = .silent\n\tmut sw := time.new_stopwatch()\n\tmut total_us := i64(0)\n\tmut total_bytes := i64(0)\n\tmut total_tokens := i64(0)\n\tmut total_lines := i64(0)\n\tmut total_errors := i64(0)\n\tmut total_files := i64(0)\n\tfor f in files {\n\t\tmut table := ast.new_table()\n\t\tif f == '' {\n\t\t\tcontinue\n\t\t}\n\t\tif skip_tests && f.ends_with('_test.v') {\n\t\t\tcontinue\n\t\t}\n\t\t// do not measure the scanning, but only the parsing:\n\t\tmut p := new_parser(f, comments_mode, table, pref_)\n\t\tif fuzzer_mode {\n\t\t\tp.scanner.max_eofs = 200\n\t\t}\n\n\t\tsw.restart()\n\t\tast_file := p.parse()\n\t\tf_us := sw.elapsed().microseconds()\n\n\t\ttotal_us += f_us\n\t\ttotal_bytes += p.scanner.text.len\n\t\ttotal_tokens += p.scanner.all_tokens.len\n\t\ttotal_lines += ast_file.nr_lines\n\t\ttotal_errors += p.errors.len\n\t\tif !fuzzer_mode {\n\t\t\tprintln('${f_us:10}us ${p.scanner.all_tokens.len:10} ${p.scanner.text.len:10} ${ast_file.nr_lines:10} ${(f64(p.scanner.text.len) / p.scanner.all_tokens.len):13.3} ${p.errors.len:10}   ${f}')\n\t\t}\n\t\ttotal_files++\n\t}\n\thline()\n\ttheader()\n\thline()\n\tspeed_mb_s := term.colorize(term.bright_yellow, '${(f64(total_bytes) / total_us):6.3f} MB/s')\n\tspeed_lines_s := term.colorize(term.bright_yellow, '${(1_000_000 * f64(total_lines) / total_us):10.1f} lines/s')\n\tprintln('${total_us:10}us ${total_tokens:10} ${total_bytes:10} ${total_lines:10} ${(f64(total_bytes) / total_tokens):13.3} ${total_errors:10}   Parser speed: ${speed_mb_s}, ${speed_lines_s}, ${nthreads:3} thread(s), ${total_files:5} files.')\n}\n\nfn new_parser(path string, comments_mode scanner.CommentsMode, table &ast.Table, pref_ &pref.Preferences) &parser.Parser {\n\tmut p := &parser.Parser{\n\t\tscanner:  scanner.new_scanner_file(path, -1, comments_mode, pref_) or { panic(err) }\n\t\ttable:    table\n\t\tpref:     pref_\n\t\tscope:    &ast.Scope{\n\t\t\tstart_pos: 0\n\t\t\tparent:    table.global_scope\n\t\t}\n\t\terrors:   []errors.Error{}\n\t\twarnings: []errors.Warning{}\n\t}\n\tp.set_path(path)\n\treturn p\n}\n"
  },
  {
    "path": "cmd/tools/measure/scanner_speed.v",
    "content": "import os\nimport time\nimport term\nimport v.scanner\nimport file_lists\nimport v.pref\n\nconst skip_tests = os.getenv('SKIP_TESTS').bool()\nconst fuzzer_mode = os.getenv('VFUZZER').bool()\nconst comments_mode = scanner.CommentsMode.from(os.getenv('SCANNER_MODE')) or {\n\tscanner.CommentsMode.skip_comments\n}\n\nfn main() {\n\tif !fuzzer_mode {\n\t\tdump(comments_mode)\n\t}\n\tall_files := file_lists.expand_files(os.args#[1..])!\n\tprocess_files(all_files)!\n}\n\nfn hline() {\n\tif fuzzer_mode {\n\t\treturn\n\t}\n\tprintln('----------------------------------------------------------------------------------------------------------------------------------------------------')\n}\n\nfn theader() {\n\tif fuzzer_mode {\n\t\treturn\n\t}\n\tprintln('        Time     Tokens      Bytes      Lines   Bytes/Token     Errors')\n}\n\nfn process_files(files []string) ! {\n\tnthreads := 1 // TODO\n\tmut pref_ := pref.new_preferences()\n\tpref_.is_fmt = true\n\tpref_.skip_warnings = true\n\tpref_.output_mode = .silent\n\tmut sw := time.new_stopwatch()\n\tmut total_us := i64(0)\n\tmut total_bytes := i64(0)\n\tmut total_tokens := i64(0)\n\tmut total_lines := i64(0)\n\tmut total_errors := i64(0)\n\tmut total_files := i64(0)\n\tfor f in files {\n\t\tif f == '' {\n\t\t\tcontinue\n\t\t}\n\t\tif skip_tests && f.ends_with('_test.v') {\n\t\t\tcontinue\n\t\t}\n\t\ttotal_files++\n\t\tsw.restart()\n\t\ts := scanner.new_scanner_file(f, -1, comments_mode, pref_)!\n\t\tf_us := sw.elapsed().microseconds()\n\t\ttotal_us += f_us\n\t\ttotal_bytes += s.text.len\n\t\ttotal_tokens += s.all_tokens.len\n\t\ttotal_lines += s.nr_lines\n\t\ttotal_errors += s.errors.len\n\t\tif !fuzzer_mode {\n\t\t\tprintln('${f_us:10}us ${s.all_tokens.len:10} ${s.text.len:10} ${s.nr_lines:10} ${(f64(s.text.len) / s.all_tokens.len):13.3f} ${s.errors.len:10}   ${f}')\n\t\t}\n\t}\n\thline()\n\ttheader()\n\thline()\n\tspeed_mb_s := term.colorize(term.bright_yellow, '${(f64(total_bytes) / total_us):6.3f} MB/s')\n\tspeed_lines_s := term.colorize(term.bright_yellow, '${(1_000_000 * f64(total_lines) / total_us):10.1f} lines/s')\n\tprintln('${total_us:10}us ${total_tokens:10} ${total_bytes:10} ${total_lines:10} ${(f64(total_bytes) / total_tokens):13.3} ${total_errors:10}   Scanner speed: ${speed_mb_s}, ${speed_lines_s}, ${nthreads:3} thread(s), ${total_files:5} files.')\n}\n"
  },
  {
    "path": "cmd/tools/modules/scripting/scripting.v",
    "content": "module scripting\n\nimport os\nimport term\nimport time\n\nconst term_colors = term.can_show_color_on_stdout()\n\npub fn set_verbose(on bool) {\n\t// setting a global here would be the obvious solution,\n\t// but V does not have globals normally.\n\tif on {\n\t\tos.setenv('VERBOSE', '1', true)\n\t} else {\n\t\tos.unsetenv('VERBOSE')\n\t}\n}\n\npub fn cprint(omessage string) {\n\tmut message := omessage\n\tif term_colors {\n\t\tmessage = term.cyan(message)\n\t}\n\tprint(message)\n\tflush_stdout()\n}\n\npub fn cprint_strong(omessage string) {\n\tmut message := omessage\n\tif term_colors {\n\t\tmessage = term.bright_green(message)\n\t}\n\tprint(message)\n\tflush_stdout()\n}\n\npub fn cprintln(omessage string) {\n\tcprint(omessage)\n\tprintln('')\n\tflush_stdout()\n}\n\npub fn cprintln_strong(omessage string) {\n\tcprint_strong(omessage)\n\tprintln('')\n\tflush_stdout()\n}\n\npub fn verbose_trace(label string, message string) {\n\tif os.getenv('VERBOSE').len > 0 {\n\t\tslabel := '${time.now().format_ss_milli()} ${label}'\n\t\tcprintln('# ${slabel:-43s} : ${message}')\n\t}\n}\n\npub fn verbose_trace_strong(label string, omessage string) {\n\tif os.getenv('VERBOSE').len > 0 {\n\t\tslabel := '${time.now().format_ss_milli()} ${label}'\n\t\tmut message := omessage\n\t\tif term_colors {\n\t\t\tmessage = term.bright_green(message)\n\t\t}\n\t\tcprintln('# ${slabel:-43s} : ${message}')\n\t}\n}\n\npub fn verbose_trace_exec_result(x os.Result) {\n\tif os.getenv('VERBOSE').len > 0 {\n\t\tcprintln('#   cmd.exit_code : ${x.exit_code.str():-4s}  cmd.output:')\n\t\tmut lnum := 1\n\t\tlines := x.output.split_into_lines()\n\t\tfor oline in lines {\n\t\t\tmut line := oline\n\t\t\tif term_colors {\n\t\t\t\tline = term.bright_green(line)\n\t\t\t}\n\t\t\tcprintln('# ${lnum:3d}: ${line}')\n\t\t\tlnum++\n\t\t}\n\t\tcprintln('# ----------------------------------------------------------------------')\n\t}\n}\n\nfn modfn(mname string, fname string) string {\n\treturn '${mname}.${fname}'\n}\n\npub fn chdir(path string) {\n\tverbose_trace_strong(modfn(@MOD, @FN), 'cd ${path}')\n\tos.chdir(path) or {\n\t\tverbose_trace(modfn(@MOD, @FN), '## failed.')\n\t\treturn\n\t}\n}\n\npub fn mkdir(path string) ! {\n\tverbose_trace_strong(modfn(@MOD, @FN), 'mkdir ${path}')\n\tos.mkdir(path) or {\n\t\tverbose_trace(modfn(@MOD, @FN), '## failed.')\n\t\treturn err\n\t}\n}\n\npub fn mkdir_all(path string) ! {\n\tverbose_trace_strong(modfn(@MOD, @FN), 'mkdir -p ${path}')\n\tos.mkdir_all(path) or {\n\t\tverbose_trace(modfn(@MOD, @FN), '## failed.')\n\t\treturn err\n\t}\n}\n\npub fn rmrf(path string) {\n\tverbose_trace_strong(modfn(@MOD, @FN), 'rm -rf ${path}')\n\tif os.exists(path) {\n\t\tif os.is_dir(path) {\n\t\t\tos.rmdir_all(path) or { panic(err) }\n\t\t} else {\n\t\t\tos.rm(path) or { panic(err) }\n\t\t}\n\t}\n}\n\n// execute a command, and return a result, or an error, if it failed in any way.\npub fn exec(cmd string) !os.Result {\n\tverbose_trace_strong(modfn(@MOD, @FN), cmd)\n\tx := os.execute(cmd)\n\tif x.exit_code != 0 {\n\t\tverbose_trace(modfn(@MOD, @FN), '## failed.')\n\t\treturn error(x.output)\n\t}\n\tverbose_trace_exec_result(x)\n\treturn x\n}\n\n// run a command, tracing its results, and returning ONLY its output\npub fn run(cmd string) string {\n\tverbose_trace_strong(modfn(@MOD, @FN), cmd)\n\tx := os.execute(cmd)\n\tif x.exit_code < 0 {\n\t\tverbose_trace(modfn(@MOD, @FN), '## failed.')\n\t\treturn ''\n\t}\n\tverbose_trace_exec_result(x)\n\tif x.exit_code == 0 {\n\t\treturn x.output.trim_right('\\r\\n')\n\t}\n\treturn ''\n}\n\n// frun runs a command, tracing its results, and returning ONLY its output, or an error, if it failed\npub fn frun(cmd string) !string {\n\tverbose_trace_strong(modfn(@MOD, @FN), cmd)\n\tx := os.execute(cmd)\n\tif x.exit_code != 0 {\n\t\tverbose_trace(modfn(@MOD, @FN), '## failed.')\n\t\tverbose_trace(modfn(@MOD, @FN), '## failure   code: ${x.exit_code}')\n\t\tverbose_trace(modfn(@MOD, @FN), '## failure output: ${x.output}')\n\t\treturn error_with_code('failed cmd: ${cmd}', x.exit_code)\n\t}\n\tverbose_trace_exec_result(x)\n\treturn x.output.trim_right('\\r\\n')\n}\n\npub fn exit_0_status(cmd string) bool {\n\tverbose_trace_strong(modfn(@MOD, @FN), cmd)\n\tx := os.execute(cmd)\n\tif x.exit_code < 0 {\n\t\tverbose_trace(modfn(@MOD, @FN), '## failed.')\n\t\treturn false\n\t}\n\tverbose_trace_exec_result(x)\n\tif x.exit_code == 0 {\n\t\treturn true\n\t}\n\treturn false\n}\n\npub fn tool_must_exist(toolcmd string) {\n\tverbose_trace(modfn(@MOD, @FN), toolcmd)\n\twhere_is_cmd := if os.user_os() == 'windows' { 'where' } else { 'type' }\n\tif exit_0_status('${where_is_cmd} ${toolcmd}') {\n\t\treturn\n\t}\n\teprintln('Missing tool: ${toolcmd}')\n\teprintln('Please try again after you install it.')\n\texit(1)\n}\n\npub fn used_tools_must_exist(tools []string) {\n\tfor t in tools {\n\t\ttool_must_exist(t)\n\t}\n}\n\npub fn show_sizes_of_files(files []string) {\n\tfor f in files {\n\t\tsize := os.file_size(f)\n\t\tprintln('${size} ${f}') // println('${size:10d} ${f}')\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/modules/testing/common.v",
    "content": "module testing\n\nimport os\nimport os.cmdline\nimport time\nimport term\nimport benchmark\nimport sync\nimport sync.pool\nimport v.pref\nimport v.util.vtest\nimport v.util.vflags\nimport runtime\nimport rand\nimport strings\nimport v.build_constraint\n\npub const max_header_len = get_max_header_len()\n\npub const host_os = pref.get_host_os()\n\npub const github_job = os.getenv('GITHUB_JOB')\n\npub const runner_os = os.getenv('RUNNER_OS') // GitHub runner OS\n\npub const keep_session = os.getenv('VTEST_KEEP_SESSION') == '1'\n\npub const show_cmd = os.getenv('VTEST_SHOW_CMD') == '1'\n\npub const show_start = os.getenv('VTEST_SHOW_START') == '1'\n\npub const show_longest_by_runtime = os.getenv('VTEST_SHOW_LONGEST_BY_RUNTIME').int()\npub const show_longest_by_comptime = os.getenv('VTEST_SHOW_LONGEST_BY_COMPTIME').int()\npub const show_longest_by_totaltime = os.getenv('VTEST_SHOW_LONGEST_BY_TOTALTIME').int()\n\npub const is_ci = os.getenv('CI') != '' || os.getenv('GITHUB_JOB') != ''\n\npub const hide_skips = os.getenv('VTEST_HIDE_SKIP') == '1'\n\t|| (is_ci && os.getenv('VTEST_HIDE_SKIP') != '0')\n\npub const hide_oks = os.getenv('VTEST_HIDE_OK') == '1'\n\t|| (is_ci && os.getenv('VTEST_HIDE_OK') != '0')\n\npub const fail_fast = os.getenv('VTEST_FAIL_FAST') == '1'\n\npub const fail_flaky = os.getenv('VTEST_FAIL_FLAKY') == '1'\n\npub const test_only = os.getenv('VTEST_ONLY').split_any(',')\n\npub const test_only_fn = os.getenv('VTEST_ONLY_FN').split_any(',')\n\n// TODO: this !!!*reliably*!!! fails compilation of `v cmd/tools/vbuild-examples.v` with a cgen error, without `-no-parallel`:\n// pub const fail_retry_delay_ms = os.getenv_opt('VTEST_FAIL_RETRY_DELAY_MS') or { '500' }.int() * time.millisecond\n// Note, it works with `-no-parallel`, and it works when that whole expr is inside a function, like below:\npub const fail_retry_delay_ms = get_fail_retry_delay_ms()\n\npub const pkgcmd = get_pkgcmd()\n\npub const is_node_present = os.execute('node --version').exit_code == 0\n\npub const is_go_present = os.execute('go version').exit_code == 0\n\npub const is_ruby_present = os.execute('ruby --version').exit_code == 0\n\t&& os.execute('${pkgcmd} ruby --libs').exit_code == 0\n\npub const is_python_present = os.execute('python --version').exit_code == 0\n\t&& os.execute('${pkgcmd} python3 --libs').exit_code == 0\n\npub const is_sqlite3_present = get_present_sqlite()\n\npub const all_processes = get_all_processes()\n\npub const header_bytes_to_search_for_module_main = 500\n\npub const separator = '-'.repeat(max_header_len) + '\\n'\n\npub const max_compilation_retries = get_max_compilation_retries()\n\nfn get_max_compilation_retries() int {\n\treturn os.getenv_opt('VTEST_MAX_COMPILATION_RETRIES') or { '3' }.int()\n}\n\nfn get_fail_retry_delay_ms() time.Duration {\n\treturn os.getenv_opt('VTEST_FAIL_RETRY_DELAY_MS') or { '500' }.int() * time.millisecond\n}\n\nfn get_pkgcmd() string {\n\tfor cmd in ['pkgconf', 'pkg-config'] {\n\t\tif os.execute('${cmd} --version').exit_code == 0 {\n\t\t\treturn cmd\n\t\t}\n\t}\n\treturn 'false'\n}\n\nfn get_present_sqlite() bool {\n\tif os.user_os() == 'windows' {\n\t\treturn os.exists(@VEXEROOT + '/thirdparty/sqlite/sqlite3.c')\n\t}\n\treturn os.execute('sqlite3 --version').exit_code == 0\n\t\t&& os.execute('${pkgcmd} sqlite3 --libs').exit_code == 0\n}\n\nfn get_all_processes() []string {\n\t$if windows {\n\t\t// TODO\n\t\treturn []\n\t} $else {\n\t\treturn os.execute('ps ax').output.split_any('\\r\\n')\n\t}\n}\n\npub enum ActionMode {\n\tcompile\n\tcompile_and_run\n}\n\npub struct TestSession {\npub mut:\n\tfiles         []string\n\tskip_files    []string\n\tvexe          string\n\tvroot         string\n\tvtmp_dir      string\n\tvargs         string\n\tfail_fast     bool\n\tbenchmark     benchmark.Benchmark\n\trm_binaries   bool = true\n\tbuild_tools   bool // builds only executables in cmd/tools; used by `v build-tools'\n\tsilent_mode   bool\n\tshow_stats    bool\n\tshow_asserts  bool\n\tprogress_mode bool\n\troot_relative bool            // used by CI runs, so that the output is stable everywhere\n\tnmessages     chan LogMessage // many publishers, single consumer/printer\n\tnmessage_idx  int             // currently printed message index\n\tfailed_cmds   shared []string\n\treporter      Reporter = Reporter(NormalReporter{})\n\thash          string // used as part of the name of the temporary directory created for tests, to ease cleanup\n\n\texec_mode ActionMode = .compile // .compile_and_run only for `v test`\n\n\tbuild_environment build_constraint.Environment // see the documentation in v.build_constraint\n\tcustom_defines    []string                     // for adding custom defines, known only to the individual runners\n}\n\npub fn (mut ts TestSession) add_failed_cmd(cmd string) {\n\tlock ts.failed_cmds {\n\t\tts.failed_cmds << cmd\n\t}\n}\n\npub fn (mut ts TestSession) show_list_of_failed_tests() {\n\trlock ts.failed_cmds {\n\t\tts.reporter.list_of_failed_commands(ts.failed_cmds)\n\t}\n}\n\nstruct MessageThreadContext {\nmut:\n\tfile    string\n\tflow_id string\n}\n\nfn (mut ts TestSession) append_message(kind MessageKind, msg string, mtc MessageThreadContext) {\n\tts.nmessages <- LogMessage{\n\t\tfile:    mtc.file\n\t\tflow_id: mtc.flow_id\n\t\tmessage: msg\n\t\tkind:    kind\n\t\twhen:    time.now()\n\t}\n}\n\nfn (mut ts TestSession) append_message_with_duration(kind MessageKind, msg string, d time.Duration, mtc MessageThreadContext) {\n\tts.nmessages <- LogMessage{\n\t\tfile:    mtc.file\n\t\tflow_id: mtc.flow_id\n\t\tmessage: msg\n\t\tkind:    kind\n\t\twhen:    time.now()\n\t\ttook:    d\n\t}\n}\n\npub fn (mut ts TestSession) session_start(message string) {\n\tts.reporter.session_start(message, mut ts)\n}\n\npub fn (mut ts TestSession) session_stop(message string) {\n\tts.reporter.session_stop(message, mut ts)\n}\n\npub fn (mut ts TestSession) print_messages() {\n\tmut test_idx := 0\n\tmut print_msg_time := time.new_stopwatch()\n\tfor {\n\t\t// get a message from the channel of messages to be printed:\n\t\tmut rmessage := <-ts.nmessages\n\t\tts.nmessage_idx++\n\n\t\t// first sent *all events* to the output reporter, so it can then process them however it wants:\n\t\tts.reporter.report(ts.nmessage_idx, rmessage)\n\n\t\tif rmessage.kind in [.cmd_begin, .cmd_end, .compile_begin, .compile_end] {\n\t\t\t// The following events, are sent before the test framework has determined,\n\t\t\t// what the full completion status is. They can also be repeated multiple times,\n\t\t\t// for tests that are flaky and need repeating.\n\t\t\tcontinue\n\t\t}\n\t\tif rmessage.kind == .sentinel {\n\t\t\t// a sentinel for stopping the printing thread\n\t\t\tif !ts.silent_mode && ts.progress_mode {\n\t\t\t\tts.reporter.report_stop()\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tif rmessage.kind != .info {\n\t\t\t// info events can also be repeated, and should be ignored when determining\n\t\t\t// the total order of the current test file, in the following replacements:\n\t\t\ttest_idx++\n\t\t}\n\t\tmsg := rmessage.message.replace_each([\n\t\t\t'TMP1',\n\t\t\t'${test_idx:1d}',\n\t\t\t'TMP2',\n\t\t\t'${test_idx:2d}',\n\t\t\t'TMP3',\n\t\t\t'${test_idx:3d}',\n\t\t\t'TMP4',\n\t\t\t'${test_idx:4d}',\n\t\t])\n\t\tis_ok := rmessage.kind == .ok\n\t\t//\n\t\ttime_passed := print_msg_time.elapsed().seconds()\n\t\tif time_passed > 10 && ts.silent_mode && is_ok {\n\t\t\t// Even if OK tests are suppressed,\n\t\t\t// show *at least* 1 result every 10 seconds,\n\t\t\t// otherwise the CI can seem stuck ...\n\t\t\tts.reporter.progress(ts.nmessage_idx, msg)\n\t\t\tprint_msg_time.restart()\n\t\t\tcontinue\n\t\t}\n\t\tif ts.progress_mode {\n\t\t\tif is_ok && !ts.silent_mode {\n\t\t\t\tts.reporter.update_last_line(ts.nmessage_idx, msg)\n\t\t\t} else {\n\t\t\t\tts.reporter.update_last_line_and_move_to_next(ts.nmessage_idx, msg)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif !ts.silent_mode || !is_ok {\n\t\t\t// normal expanded mode, or failures in -silent mode\n\t\t\tts.reporter.message(ts.nmessage_idx, msg)\n\t\t\tcontinue\n\t\t}\n\t}\n}\n\npub fn (mut ts TestSession) execute(cmd string, mtc MessageThreadContext) os.Result {\n\tif show_cmd {\n\t\tts.append_message(.info, '> execute cmd: ${cmd}', mtc)\n\t}\n\treturn os.execute(cmd)\n}\n\npub fn (mut ts TestSession) system(cmd string, mtc MessageThreadContext) int {\n\tif show_cmd {\n\t\tts.append_message(.info, '> system cmd: ${cmd}', mtc)\n\t}\n\treturn os.system(cmd)\n}\n\npub fn new_test_session(_vargs string, will_compile bool) TestSession {\n\tmut skip_files := []string{}\n\tif will_compile {\n\t\tif runner_os != 'Linux' || !github_job.starts_with('tcc-') {\n\t\t\tif !os.exists('/usr/local/include/wkhtmltox/pdf.h') {\n\t\t\t\tskip_files << 'examples/c_interop_wkhtmltopdf.v' // needs installation of wkhtmltopdf from https://github.com/wkhtmltopdf/packaging/releases\n\t\t\t}\n\t\t}\n\t}\n\tskip_files = skip_files.map(os.abs_path)\n\tvargs := _vargs.replace('-progress', '')\n\tvexe := pref.vexe_path()\n\tvroot := os.dir(vexe)\n\thash := '${sync.thread_id().hex()}_${rand.ulid()}'\n\tnew_vtmp_dir := setup_new_vtmp_folder(hash)\n\tif term.can_show_color_on_stderr() {\n\t\tos.setenv('VCOLORS', 'always', true)\n\t}\n\tmut ts := TestSession{\n\t\tvexe:          vexe\n\t\tvroot:         vroot\n\t\tskip_files:    skip_files\n\t\tfail_fast:     fail_fast\n\t\tshow_stats:    '-stats' in vargs.split(' ')\n\t\tshow_asserts:  '-show-asserts' in vargs.split(' ')\n\t\tvargs:         vargs\n\t\tvtmp_dir:      new_vtmp_dir\n\t\thash:          hash\n\t\tsilent_mode:   _vargs.contains('-silent')\n\t\tprogress_mode: _vargs.contains('-progress')\n\t}\n\tif keep_session {\n\t\tts.rm_binaries = false\n\t\tprintln('> vtmp_dir: ${new_vtmp_dir}')\n\t}\n\n\tts.handle_test_runner_option()\n\treturn ts\n}\n\nfn (mut ts TestSession) handle_test_runner_option() {\n\ttest_runner := cmdline.option(os.args, '-test-runner', 'normal')\n\tif test_runner !in pref.supported_test_runners {\n\t\teprintln('v test: `-test-runner ${test_runner}` is not using one of the supported test runners: ${pref.supported_test_runners_list()}')\n\t}\n\ttest_runner_implementation_file := os.join_path(ts.vroot, 'cmd/tools/modules/testing/output_${test_runner}.v')\n\tif !os.exists(test_runner_implementation_file) {\n\t\teprintln('v test: using `-test-runner ${test_runner}` needs ${test_runner_implementation_file} to exist, and contain a valid testing.Reporter implementation for that runner. See `cmd/tools/modules/testing/output_dump.v` for an example.')\n\t\texit(1)\n\t}\n\tmatch test_runner {\n\t\t'normal' {\n\t\t\t// default, nothing to do\n\t\t}\n\t\t'dump' {\n\t\t\tts.reporter = DumpReporter{}\n\t\t}\n\t\t'teamcity' {\n\t\t\tts.reporter = TeamcityReporter{}\n\t\t}\n\t\telse {\n\t\t\tdump('just set ts.reporter to an instance of your own struct here')\n\t\t}\n\t}\n}\n\npub fn (mut ts TestSession) init() {\n\tts.files.sort()\n\tts.benchmark = benchmark.new_benchmark_no_cstep()\n}\n\npub fn (mut ts TestSession) add(file string) {\n\tts.files << file\n}\n\npub fn (mut ts TestSession) test() {\n\tunbuffer_stdout()\n\t// Ensure that .tmp.c files generated from compiling _test.v files,\n\t// are easy to delete at the end, *without* affecting the existing ones.\n\tcurrent_wd := os.getwd()\n\tif current_wd == os.wd_at_startup && current_wd == ts.vroot {\n\t\tts.root_relative = true\n\t}\n\n\tts.init()\n\tmut remaining_files := []string{}\n\tfor dot_relative_file in ts.files {\n\t\tfile := os.real_path(dot_relative_file)\n\t\tif ts.build_tools && dot_relative_file.ends_with('_test.v') {\n\t\t\tcontinue\n\t\t}\n\t\t// Skip OS-specific tests if we are not running that OS\n\t\t// Special case for android_outside_termux because of its\n\t\t// underscores\n\t\tif file.ends_with('_android_outside_termux_test.v') {\n\t\t\tif !host_os.is_target_of('android_outside_termux') {\n\t\t\t\tremaining_files << dot_relative_file\n\t\t\t\tts.skip_files << file\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tos_target := file.all_before_last('_test.v').all_after_last('_')\n\t\tif !host_os.is_target_of(os_target) {\n\t\t\tremaining_files << dot_relative_file\n\t\t\tts.skip_files << file\n\t\t\tcontinue\n\t\t}\n\t\tremaining_files << dot_relative_file\n\t}\n\tremaining_files = vtest.filter_vtest_only(remaining_files, fix_slashes: false)\n\tts.files = remaining_files\n\tts.benchmark.set_total_expected_steps(remaining_files.len)\n\tmut njobs := runtime.nr_jobs()\n\tif remaining_files.len < njobs {\n\t\tnjobs = remaining_files.len\n\t}\n\tts.benchmark.njobs = njobs\n\tmut pool_of_test_runners := pool.new_pool_processor(callback: worker_trunner)\n\t// ensure that the nmessages queue/channel, has enough capacity for handling many messages across threads, without blocking\n\tts.nmessages = chan LogMessage{cap: 10000}\n\tts.nmessage_idx = 0\n\tprinting_thread := spawn ts.print_messages()\n\tpool_of_test_runners.set_shared_context(ts)\n\tts.reporter.worker_threads_start(remaining_files, mut ts)\n\n\tts.setup_build_environment()\n\n\t// all the testing happens here:\n\tpool_of_test_runners.work_on_pointers(unsafe { remaining_files.pointers() })\n\n\tts.benchmark.stop()\n\tts.append_message(.sentinel, '', MessageThreadContext{ flow_id: '-1' }) // send the sentinel\n\tprinting_thread.wait()\n\tts.reporter.worker_threads_finish(mut ts)\n\tts.reporter.divider()\n\tts.show_list_of_failed_tests()\n\n\t// cleanup the session folder, if everything was ok:\n\tif ts.benchmark.nfail == 0 {\n\t\tif ts.rm_binaries {\n\t\t\tos.rmdir_all(ts.vtmp_dir) or {}\n\t\t}\n\t}\n\tif os.ls(ts.vtmp_dir) or { [] }.len == 0 {\n\t\tos.rmdir_all(ts.vtmp_dir) or {}\n\t}\n}\n\nfn worker_trunner(mut p pool.PoolProcessor, idx int, thread_id int) voidptr {\n\tmut ts := unsafe { &TestSession(p.get_shared_context()) }\n\tif ts.fail_fast {\n\t\tif ts.failed_cmds.len > 0 {\n\t\t\treturn pool.no_result\n\t\t}\n\t}\n\t// tls_bench is used to format the step messages/timings\n\tmut tls_bench := unsafe { &benchmark.Benchmark(p.get_thread_context(idx)) }\n\tif isnil(tls_bench) {\n\t\ttls_bench = benchmark.new_benchmark_pointer()\n\t\ttls_bench.set_total_expected_steps(ts.benchmark.nexpected_steps)\n\t\tp.set_thread_context(idx, tls_bench)\n\t}\n\ttls_bench.no_cstep = true\n\ttls_bench.njobs = ts.benchmark.njobs\n\tabs_path := os.real_path(p.get_item[string](idx))\n\tmut relative_file := abs_path\n\tmut cmd_options := vflags.tokenize_to_args(ts.vargs) // make sure that `'-W -silent'` becomes `['-W', '-silent']`, while keeping quoted spaces intact\n\tmut run_js := false\n\n\tis_fmt := ts.vargs.contains('fmt')\n\tis_vet := ts.vargs.contains('vet')\n\tproduces_file_output := !(is_fmt || is_vet)\n\n\tif relative_file.ends_with('.js.v') {\n\t\tif produces_file_output {\n\t\t\tcmd_options << ' -b js'\n\t\t\trun_js = true\n\t\t}\n\t}\n\n\tif relative_file.ends_with('.c.v') {\n\t\tif produces_file_output {\n\t\t\tcmd_options << ' -b c'\n\t\t\trun_js = false\n\t\t}\n\t}\n\n\tif relative_file.contains('global') && !is_fmt {\n\t\tcmd_options << ' -enable-globals'\n\t}\n\tif ts.root_relative {\n\t\trelative_file = relative_file.replace_once(ts.vroot + os.path_separator, '')\n\t}\n\tnormalised_relative_file := relative_file.replace('\\\\', '/')\n\n\tfile := abs_path\n\tmtc := MessageThreadContext{\n\t\tfile:    file\n\t\tflow_id: thread_id.str()\n\t}\n\n\t// Ensure that the generated binaries will be stored in an *unique*, fresh, and per test folder,\n\t// inside the common session temporary folder, used for all the tests.\n\t// This is done to provide a clean working environment, for each test, that will not contain\n\t// files from other tests, and will make sure that tests with the same name, can be compiled\n\t// inside their own folders, without name conflicts (and without locking issues on windows,\n\t// where an executable is not writable, if it is running).\n\t// Note, that the common session temporary folder ts.vtmp_dir,\n\t// will be removed after all tests are done.\n\ttest_id := '${idx}_${thread_id}'\n\tmut test_folder_path := os.join_path(ts.vtmp_dir, test_id)\n\tif ts.build_tools {\n\t\t// `v build-tools`, produce all executables in the same session folder, so that they can be copied later:\n\t\ttest_folder_path = ts.vtmp_dir\n\t} else {\n\t\tos.mkdir_all(test_folder_path) or {}\n\t}\n\tfname := os.file_name(file)\n\t// There are test files ending with `_test.v`, `_test.c.v` and `_test.js.v`.\n\tmut fname_without_extension := fname.all_before_last('.v')\n\tif fname_without_extension.ends_with('.c') {\n\t\tfname_without_extension = fname_without_extension.all_before_last('.c')\n\t}\n\tgenerated_binary_fname := if os.user_os() == 'windows' && !run_js {\n\t\tfname_without_extension + '.exe'\n\t} else {\n\t\tfname_without_extension\n\t}\n\tmut details := get_test_details(file)\n\tif details.vflags != '' && !is_fmt {\n\t\tcmd_options << details.vflags\n\t}\n\n\treproduce_options := cmd_options.clone()\n\tgenerated_binary_fpath := os.join_path_single(test_folder_path, generated_binary_fname)\n\tif produces_file_output {\n\t\tif ts.rm_binaries {\n\t\t\tos.rm(generated_binary_fpath) or {}\n\t\t}\n\t\tcmd_options << ' -o ${os.quoted_path(generated_binary_fpath)}'\n\t}\n\tdefer {\n\t\tif produces_file_output && ts.rm_binaries {\n\t\t\tos.rmdir_all(test_folder_path) or {}\n\t\t}\n\t}\n\n\tmut skip_running := '-skip-running'\n\tif ts.show_stats {\n\t\tskip_running = ''\n\t}\n\treproduce_cmd := '${os.quoted_path(ts.vexe)} ${reproduce_options.join(' ')} ${os.quoted_path(file)}'\n\tcompile_options := cmd_options.filter(it != '-silent')\n\tcmd := '${os.quoted_path(ts.vexe)} ${skip_running} ${compile_options.join(' ')} ${os.quoted_path(file)}'\n\trun_cmd := if run_js {\n\t\t'node ${os.quoted_path(generated_binary_fpath)}'\n\t} else {\n\t\tos.quoted_path(generated_binary_fpath)\n\t}\n\tmut should_be_built := true\n\tif details.vbuild != '' {\n\t\tshould_be_built = ts.build_environment.eval(details.vbuild) or {\n\t\t\teprintln('${file}:${details.vbuild_line}:17: error during parsing the `// v test build` expression `${details.vbuild}`: ${err}')\n\t\t\tfalse\n\t\t}\n\t\t$if trace_should_be_built ? {\n\t\t\teprintln('${file} has specific build constraint: `${details.vbuild}` => should_be_built: `${should_be_built}`')\n\t\t\teprintln('>          env   facts: ${ts.build_environment.facts}')\n\t\t\teprintln('>          env defines: ${ts.build_environment.defines}')\n\t\t}\n\t}\n\n\tts.benchmark.step()\n\ttls_bench.step()\n\tif produces_file_output && !ts.build_tools && (!should_be_built || abs_path in ts.skip_files) {\n\t\tts.benchmark.skip()\n\t\ttls_bench.skip()\n\t\tif !hide_skips {\n\t\t\tts.append_message(.skip, tls_bench.step_message_with_label_and_duration(benchmark.b_skip,\n\t\t\t\tnormalised_relative_file, 0,\n\t\t\t\tpreparation: 1 * time.microsecond\n\t\t\t), mtc)\n\t\t}\n\t\treturn pool.no_result\n\t}\n\tmut compile_cmd_duration := time.Duration(0)\n\tmut cmd_duration := time.Duration(0)\n\tif ts.show_stats {\n\t\tts.append_message(.cmd_begin, cmd, mtc)\n\t\td_cmd := time.new_stopwatch()\n\t\tmut res := ts.execute(cmd, mtc)\n\t\tif res.exit_code != 0 {\n\t\t\teprintln(res.output)\n\t\t} else {\n\t\t\tprintln(res.output)\n\t\t}\n\t\tmut status := res.exit_code\n\n\t\tcmd_duration = d_cmd.elapsed()\n\t\tts.append_message_with_duration(.cmd_end, '', cmd_duration, mtc)\n\n\t\tif status != 0 {\n\t\t\tos.setenv('VTEST_RETRY_MAX', '${details.retry}', true)\n\t\t\tfor retry := 1; retry <= details.retry; retry++ {\n\t\t\t\tif !details.hide_retries {\n\t\t\t\t\tts.append_message(.info, '  [stats]        retrying ${retry}/${details.retry} of ${relative_file} ; known flaky: ${details.flaky} ...',\n\t\t\t\t\t\tmtc)\n\t\t\t\t}\n\t\t\t\tos.setenv('VTEST_RETRY', '${retry}', true)\n\t\t\t\tts.append_message(.cmd_begin, cmd, mtc)\n\t\t\t\td_cmd_2 := time.new_stopwatch()\n\t\t\t\tstatus = ts.system(cmd, mtc)\n\t\t\t\tcmd_duration = d_cmd_2.elapsed()\n\t\t\t\tts.append_message_with_duration(.cmd_end, '', cmd_duration, mtc)\n\n\t\t\t\tif status == 0 {\n\t\t\t\t\tunsafe {\n\t\t\t\t\t\tgoto test_passed_system\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttime.sleep(fail_retry_delay_ms)\n\t\t\t}\n\t\t\tif details.flaky && !fail_flaky {\n\t\t\t\tts.append_message(.info, '   *FAILURE* of the known flaky test file ${relative_file} is ignored, since VTEST_FAIL_FLAKY is 0 . Retry count: ${details.retry} .\\ncmd: ${cmd}',\n\t\t\t\t\tmtc)\n\t\t\t\tunsafe {\n\t\t\t\t\tgoto test_passed_system\n\t\t\t\t}\n\t\t\t}\n\t\t\t// most probably compiler error\n\t\t\tif res.output.contains(': error: ') {\n\t\t\t\tts.append_message(.cannot_compile, 'Cannot compile file ${file}', mtc)\n\t\t\t}\n\t\t\tts.benchmark.fail()\n\t\t\ttls_bench.fail()\n\t\t\tts.add_failed_cmd(reproduce_cmd)\n\t\t\treturn pool.no_result\n\t\t}\n\t} else {\n\t\tif show_start {\n\t\t\tts.append_message(.info, '                 starting ${relative_file} ...',\n\t\t\t\tmtc)\n\t\t}\n\t\tts.append_message(.compile_begin, cmd, mtc)\n\t\tcompile_d_cmd := time.new_stopwatch()\n\t\tmut compile_r := os.Result{}\n\t\tfor cretry in 0 .. max_compilation_retries {\n\t\t\tcompile_r = ts.execute(cmd, mtc)\n\t\t\tcompile_cmd_duration = compile_d_cmd.elapsed()\n\t\t\t// eprintln('>>>> cretry: ${cretry} | compile_r.exit_code: ${compile_r.exit_code} | compile_cmd_duration: ${compile_cmd_duration:8} | file: ${normalised_relative_file}')\n\t\t\tif compile_r.exit_code == 0 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\trandom_sleep_ms(50, 100 * cretry)\n\t\t}\n\t\tts.append_message_with_duration(.compile_end, compile_r.output, compile_cmd_duration,\n\t\t\tmtc)\n\t\tif compile_r.exit_code != 0 {\n\t\t\tts.benchmark.fail()\n\t\t\ttls_bench.fail()\n\t\t\tts.append_message_with_duration(.fail, tls_bench.step_message_with_label_and_duration(benchmark.b_fail,\n\t\t\t\t'${normalised_relative_file}\\n>> compilation failed:\\n${compile_r.output}',\n\t\t\t\tcmd_duration,\n\t\t\t\tpreparation: compile_cmd_duration\n\t\t\t), cmd_duration, mtc)\n\t\t\tts.add_failed_cmd(reproduce_cmd)\n\t\t\treturn pool.no_result\n\t\t}\n\t\ttls_bench.step_restart()\n\t\tts.benchmark.step_restart()\n\t\tif ts.exec_mode == .compile {\n\t\t\tunsafe {\n\t\t\t\tgoto test_passed_execute\n\t\t\t}\n\t\t}\n\t\t//\n\t\tmut retry := 1\n\t\tmut failure_output := strings.new_builder(1024)\n\t\tts.append_message(.cmd_begin, run_cmd, mtc)\n\t\td_cmd := time.new_stopwatch()\n\t\tmut r := ts.execute(run_cmd, mtc)\n\t\tcmd_duration = d_cmd.elapsed()\n\t\tts.append_message_with_duration(.cmd_end, r.output, cmd_duration, mtc)\n\t\tif ts.show_asserts && r.exit_code == 0 {\n\t\t\tprintln(r.output.split_into_lines().filter(it.contains(' assert')).join('\\n'))\n\t\t}\n\t\tif r.exit_code != 0 {\n\t\t\tmut trimmed_output := r.output.trim_space()\n\t\t\tif trimmed_output.len == 0 {\n\t\t\t\t// retry running at least 1 more time, to avoid CI false positives as much as possible\n\t\t\t\tdetails.retry++\n\t\t\t}\n\t\t\tif details.retry != 0 {\n\t\t\t\tfailure_output.write_string(separator)\n\t\t\t\tfailure_output.writeln(' retry: 0 ; max_retry: ${details.retry} ; r.exit_code: ${r.exit_code} ; trimmed_output.len: ${trimmed_output.len}')\n\t\t\t}\n\t\t\tfailure_output.writeln(trimmed_output)\n\t\t\tos.setenv('VTEST_RETRY_MAX', '${details.retry}', true)\n\t\t\tfor retry = 1; retry <= details.retry; retry++ {\n\t\t\t\tif !details.hide_retries {\n\t\t\t\t\tts.append_message(.info, '                 retrying ${retry}/${details.retry} of ${relative_file} ; known flaky: ${details.flaky} ...',\n\t\t\t\t\t\tmtc)\n\t\t\t\t}\n\t\t\t\tos.setenv('VTEST_RETRY', '${retry}', true)\n\t\t\t\tts.append_message(.cmd_begin, run_cmd, mtc)\n\t\t\t\td_cmd_2 := time.new_stopwatch()\n\t\t\t\tr = ts.execute(run_cmd, mtc)\n\t\t\t\tcmd_duration = d_cmd_2.elapsed()\n\t\t\t\tts.append_message_with_duration(.cmd_end, r.output, cmd_duration, mtc)\n\n\t\t\t\tif r.exit_code == 0 {\n\t\t\t\t\tunsafe {\n\t\t\t\t\t\tgoto test_passed_execute\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttrimmed_output = r.output.trim_space()\n\t\t\t\tfailure_output.write_string(separator)\n\t\t\t\tfailure_output.writeln(' retry: ${retry} ; max_retry: ${details.retry} ; r.exit_code: ${r.exit_code} ; trimmed_output.len: ${trimmed_output.len}')\n\t\t\t\tfailure_output.writeln(trimmed_output)\n\t\t\t\ttime.sleep(fail_retry_delay_ms)\n\t\t\t}\n\t\t\tfull_failure_output := failure_output.str().trim_space()\n\t\t\tif details.flaky && !fail_flaky {\n\t\t\t\tts.append_message(.info, '>>> flaky failures so far:', mtc)\n\t\t\t\tfor line in full_failure_output.split_into_lines() {\n\t\t\t\t\tts.append_message(.info, '>>>>>> ${line}', mtc)\n\t\t\t\t}\n\t\t\t\tts.append_message(.info, '   *FAILURE* of the known flaky test file ${relative_file} is ignored, since VTEST_FAIL_FLAKY is 0 . Retry count: ${details.retry} .\\n    comp_cmd: ${cmd}\\n     run_cmd: ${run_cmd}',\n\t\t\t\t\tmtc)\n\t\t\t\tunsafe {\n\t\t\t\t\tgoto test_passed_execute\n\t\t\t\t}\n\t\t\t}\n\t\t\tts.benchmark.fail()\n\t\t\ttls_bench.fail()\n\t\t\tcmd_duration = d_cmd.elapsed() - (fail_retry_delay_ms * details.retry)\n\t\t\tts.append_message_with_duration(.fail, tls_bench.step_message_with_label_and_duration(benchmark.b_fail,\n\t\t\t\t'${normalised_relative_file}\\n${full_failure_output}', cmd_duration,\n\t\t\t\tpreparation: compile_cmd_duration\n\t\t\t), cmd_duration, mtc)\n\t\t\tts.add_failed_cmd(reproduce_cmd)\n\t\t\treturn pool.no_result\n\t\t}\n\t}\n\ttest_passed_system:\n\ttest_passed_execute:\n\tts.benchmark.ok()\n\ttls_bench.ok()\n\tif !hide_oks {\n\t\tts.append_message_with_duration(.ok, tls_bench.step_message_with_label_and_duration(benchmark.b_ok,\n\t\t\tnormalised_relative_file, cmd_duration,\n\t\t\tpreparation: compile_cmd_duration\n\t\t), cmd_duration, mtc)\n\t}\n\treturn pool.no_result\n}\n\npub fn vlib_should_be_present(parent_dir string) {\n\tvlib_dir := os.join_path_single(parent_dir, 'vlib')\n\tif !os.is_dir(vlib_dir) {\n\t\teprintln('${vlib_dir} is missing, it must be next to the V executable')\n\t\texit(1)\n\t}\n}\n\npub fn prepare_test_session(zargs string, folder string, oskipped []string, main_label string) TestSession {\n\tvexe := pref.vexe_path()\n\tparent_dir := os.dir(vexe)\n\tnparent_dir := parent_dir.replace('\\\\', '/')\n\tvlib_should_be_present(parent_dir)\n\tvargs := zargs.replace(vexe, '')\n\teheader(main_label)\n\tif vargs.len > 0 {\n\t\teprintln('v compiler args: \"${vargs}\"')\n\t}\n\tmut session := new_test_session(vargs, true)\n\tfiles := os.walk_ext(os.join_path_single(parent_dir, folder), '.v')\n\tmut mains := []string{}\n\tmut skipped := oskipped.clone()\n\tnext_file: for f in files {\n\t\tfnormalised := f.replace('\\\\', '/')\n\t\t// Note: a `testdata` folder, is the preferred name of a folder, containing V code,\n\t\t// that you *do not want* the test framework to find incidentally for various reasons,\n\t\t// for example module import tests, or subtests, that are compiled/run by other parent tests\n\t\t// in specific configurations, etc.\n\t\tif fnormalised.contains('testdata/') || fnormalised.contains('modules/')\n\t\t\t|| fnormalised.contains('preludes/') {\n\t\t\tcontinue\n\t\t}\n\t\t$if windows {\n\t\t\t// skip process/command examples on windows. TODO: remove the need for this, fix os.Command\n\t\t\tif fnormalised.ends_with('examples/process/command.v') {\n\t\t\t\tskipped << fnormalised.replace(nparent_dir + '/', '')\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tc := os.read_file(fnormalised) or { panic(err) }\n\t\tstart := c#[0..header_bytes_to_search_for_module_main]\n\t\tif start.contains('module ') {\n\t\t\tmodname := start.all_after('module ').all_before('\\n')\n\t\t\tif modname !in ['main', 'no_main'] {\n\t\t\t\tskipped << fnormalised.replace(nparent_dir + '/', '')\n\t\t\t\tcontinue next_file\n\t\t\t}\n\t\t}\n\t\tfor skip_prefix in oskipped {\n\t\t\tskip_folder := skip_prefix + '/'\n\t\t\tif fnormalised.starts_with(skip_folder) {\n\t\t\t\tcontinue next_file\n\t\t\t}\n\t\t}\n\t\tmains << fnormalised\n\t}\n\tsession.files << mains\n\tsession.skip_files << skipped\n\treturn session\n}\n\npub type FnTestSetupCb = fn (mut session TestSession)\n\npub fn v_build_failing_skipped(zargs string, folder string, oskipped []string, cb FnTestSetupCb) bool {\n\tmain_label := 'Building ${folder} ...'\n\tfinish_label := 'building ${folder}'\n\tmut session := prepare_test_session(zargs, folder, oskipped, main_label)\n\tcb(mut session)\n\tsession.test()\n\teprintln(session.benchmark.total_message(finish_label))\n\treturn session.failed_cmds.len > 0\n}\n\npub fn build_v_cmd_failed(cmd string) bool {\n\tres := os.execute(cmd)\n\tif res.exit_code < 0 {\n\t\treturn true\n\t}\n\tif res.exit_code != 0 {\n\t\teprintln('')\n\t\teprintln(res.output)\n\t\treturn true\n\t}\n\treturn false\n}\n\npub fn building_any_v_binaries_failed() bool {\n\teheader('Building V binaries...')\n\teprintln('VFLAGS is: \"' + os.getenv('VFLAGS') + '\"')\n\tvexe := pref.vexe_path()\n\tparent_dir := os.dir(vexe)\n\tvlib_should_be_present(parent_dir)\n\tos.chdir(parent_dir) or { panic(err) }\n\tmut failed := false\n\tv_build_commands := ['${vexe} -o v_g             -g  cmd/v',\n\t\t'${vexe} -o v_prod_g  -prod -g  cmd/v', '${vexe} -o v_cg            -cg cmd/v',\n\t\t'${vexe} -o v_prod_cg -prod -cg cmd/v', '${vexe} -o v_prod    -prod     cmd/v']\n\tmut bmark := benchmark.new_benchmark()\n\tfor cmd in v_build_commands {\n\t\tbmark.step()\n\t\tif build_v_cmd_failed(cmd) {\n\t\t\tbmark.fail()\n\t\t\tfailed = true\n\t\t\teprintln(bmark.step_message_fail('command: ${cmd} . See details above ^^^^^^^'))\n\t\t\teprintln('')\n\t\t\tcontinue\n\t\t}\n\t\tbmark.ok()\n\t\tif !hide_oks {\n\t\t\teprintln(bmark.step_message_ok('command: ${cmd}'))\n\t\t}\n\t}\n\tbmark.stop()\n\th_divider()\n\teprintln(bmark.total_message('building v binaries'))\n\treturn failed\n}\n\npub fn h_divider() {\n\teprintln(term.h_divider('-')#[..max_header_len])\n}\n\n// setup_new_vtmp_folder creates a new nested folder inside VTMP, then resets VTMP to it,\n// so that V programs/tests will write their temporary files to new location.\n// The new nested folder, and its contents, will get removed after all tests/programs succeed.\npub fn setup_new_vtmp_folder(hash string) string {\n\tnew_vtmp_dir := os.join_path(os.vtmp_dir(), 'tsession_${hash}')\n\tos.mkdir_all(new_vtmp_dir) or { panic(err) }\n\tos.setenv('VTMP', new_vtmp_dir, true)\n\treturn new_vtmp_dir\n}\n\npub struct TestDetails {\npub mut:\n\tretry int\n\tflaky bool // when flaky tests fail, the whole run is still considered successful, unless VTEST_FAIL_FLAKY is 1\n\t//\n\thide_retries bool   // when true, all retry tries are silent; used by `vlib/v/tests/retry_test.v`\n\tvbuild       string // could be `!(windows && tinyc)`\n\tvbuild_line  int    // for more precise error reporting, if the `vbuild` expression is incorrect\n\tvflags       string // custom compilation flags for the test (enables for example: `// vtest vflags: -w`, for tests that have known warnings, but should still pass with -W)\n}\n\npub fn get_test_details(file string) TestDetails {\n\tmut res := TestDetails{}\n\tif !os.is_file(file) {\n\t\treturn res\n\t}\n\tlines := os.read_lines(file) or { [] }\n\tfor idx, line in lines {\n\t\tif line.starts_with('// vtest retry:') {\n\t\t\tres.retry = line.all_after(':').trim_space().int()\n\t\t}\n\t\tif line.starts_with('// vtest flaky:') {\n\t\t\tres.flaky = line.all_after(':').trim_space().bool()\n\t\t}\n\t\tif line.starts_with('// vtest build:') {\n\t\t\tres.vbuild = line.all_after(':').trim_space()\n\t\t\tres.vbuild_line = idx + 1\n\t\t}\n\t\tif line.starts_with('// vtest vflags:') {\n\t\t\tres.vflags = line.all_after(':').trim_space()\n\t\t}\n\t\tif line.starts_with('// vtest hide_retries') {\n\t\t\tres.hide_retries = true\n\t\t}\n\t}\n\treturn res\n}\n\npub fn find_started_process(pname string) !string {\n\tfor line in all_processes {\n\t\tif line.contains(pname) {\n\t\t\treturn line\n\t\t}\n\t}\n\treturn error('could not find process matching ${pname}')\n}\n\nfn limited_header(msg string) string {\n\treturn term.header_left(msg, '-')#[..max_header_len]\n}\n\npub fn eheader(msg string) {\n\teprintln(limited_header(msg))\n}\n\npub fn header(msg string) {\n\tprintln(limited_header(msg))\n\tflush_stdout()\n}\n\nfn random_sleep_ms(min_ms int, random_add_ms int) {\n\ttime.sleep((50 + rand.intn(50) or { 0 }) * time.millisecond)\n}\n\nfn get_max_header_len() int {\n\tmaximum := 140\n\tcols, _ := term.get_terminal_size()\n\tif cols > maximum {\n\t\treturn maximum\n\t}\n\treturn cols\n}\n\nfn check_openssl_present() bool {\n\tif github_job.ends_with('-windows') {\n\t\t// TODO: investigate the https://github.com/vlang/v/actions/runs/18590919000/job/53005499130 failure in more details\n\t\treturn false\n\t}\n\t$if openbsd {\n\t\treturn os.execute('eopenssl35 --version').exit_code == 0\n\t\t\t&& os.execute('${pkgcmd} eopenssl35 --libs').exit_code == 0\n\t} $else {\n\t\treturn os.execute('openssl --version').exit_code == 0\n\t\t\t&& os.execute('${pkgcmd} openssl --libs').exit_code == 0\n\t}\n}\n\npub const is_openssl_present = check_openssl_present()\n\n// is_started_mysqld is true, when the test runner determines that there is a running mysql server\npub const is_started_mysqld = find_started_process('mysqld') or { '' }\n\n// is_started_postgres is true, when the test runner determines that there is a running postgres server\npub const is_started_postgres = find_started_process('postgres') or { '' }\n\n// is_started_redis is true, when the test runner determines that there is a running redis server\npub const is_started_redis = find_started_process('redis-server') or { '' }\n\npub fn (mut ts TestSession) setup_build_environment() {\n\tfacts, mut defines := pref.get_build_facts_and_defines()\n\t// add the runtime information, that the test runner has already determined by checking once:\n\tif github_job.starts_with('sanitize-') {\n\t\tdefines << 'sanitized_job'\n\t}\n\tif is_started_mysqld != '' {\n\t\tdefines << 'started_mysqld'\n\t}\n\tif is_started_postgres != '' {\n\t\tdefines << 'started_postgres'\n\t}\n\tif is_started_redis != '' {\n\t\tdefines << 'started_redis'\n\t}\n\tif is_node_present {\n\t\tdefines << 'present_node'\n\t}\n\tif is_python_present {\n\t\tdefines << 'present_python'\n\t}\n\tif is_ruby_present {\n\t\tdefines << 'present_ruby'\n\t}\n\tif is_go_present {\n\t\tdefines << 'present_go'\n\t}\n\tif is_sqlite3_present {\n\t\tdefines << 'present_sqlite3'\n\t}\n\tif is_openssl_present {\n\t\tdefines << 'present_openssl'\n\t}\n\n\t// detect the linux distribution as well when possible:\n\tif os.is_file('/etc/os-release') {\n\t\tmut distro_kind := ''\n\t\tif lines := os.read_lines('/etc/os-release') {\n\t\t\tfor line in lines {\n\t\t\t\tif line.starts_with('ID=') {\n\t\t\t\t\tdistro_kind = line.all_after('ID=')\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif distro_kind != '' {\n\t\t\tdefines << 'os_id_${distro_kind}' // os_id_alpine, os_id_freebsd, os_id_ubuntu, os_id_debian etc\n\t\t}\n\t}\n\n\tdefines << ts.custom_defines\n\t$if trace_vbuild ? {\n\t\teprintln('>>> testing.get_build_environment facts: ${facts}')\n\t\teprintln('>>> testing.get_build_environment defines: ${defines}')\n\t}\n\tts.build_environment = build_constraint.new_environment(facts, defines)\n}\n"
  },
  {
    "path": "cmd/tools/modules/testing/output.v",
    "content": "module testing\n\nimport time\n\npub enum MessageKind {\n\tcompile_begin // sent right before *each* _test.v file compilation, the resulting status is not known yet, but the _test.v file itself is\n\tcompile_end   // sent right after *each* _test.v file compilation, the message contains the output of that compilation\n\tcmd_begin     // sent right before *each* _test.v file execution, the resulting status is not known yet, but the _test.v file itself is\n\tcmd_end       // sent right after *each* _test.v file execution, the message contains the output of that execution\n\n\tok   // success of a _test.v file\n\tfail // failed _test.v file, one or more assertions failed\n\tskip // the _test.v file was skipped for some reason\n\tinfo // a generic information message, detailing the actions of the `v test` program (some tests could be repeated for example, and the details are sent with an .info status)\n\n\tcannot_compile // when the _test.v file compiled with errors\n\n\tsentinel // send just once after all executions are done; it signals that the reporting/printing thread should stop the loop and exit\n}\n\npub struct LogMessage {\npub:\n\tkind    MessageKind   // see the MessageKind declaration above\n\tfile    string        // the _test.v file that the message is about\n\twhen    time.Time     // when was the message sent (messages are sent by the execution threads at the *end* of each event)\n\tflow_id string        // the messages of each thread, producing LogMessage, will have all the same unique flow_id. Messages by other threads will have other flow_id. If you use VJOBS=1 to serialise the execution, then all messages will have the same flow_id.\n\ttook    time.Duration // the duration of the event, that this message describes\n\tmessage string        // the actual message text; the result of the event, that the message describes; most reporters could ignore this, since it could be reconstructed by the other fields\n}\n\npub interface Reporter {\nmut:\n\tsession_start(message string, mut ts TestSession)        // called once per test session, in the main thread, suitable for setting up supporting infrastructure.\n\tsession_stop(message string, mut ts TestSession)         // called once per test session, in the main thread, after everything else, suitable for summaries, creating .xml reports, uploads etc.\n\tworker_threads_start(files []string, mut ts TestSession) // called once per test session, in the main thread, right before all the worker threads start\n\tworker_threads_finish(mut ts TestSession)                // called once per test session, in the main thread, right after all the worker threads finish\n\n\treport(index int, log_msg LogMessage) // called once per each message, that will be shown (ok/fail/skip etc), only in the reporting thread.\n\treport_stop()                         // called just once after all messages are processed, only in the reporting thread, but before stop_session.\n\n\t// TODO: reconsider, whether the next methods, should be kept for all reporters, or just moved inside the normal reporter, to simplify the interface\n\tprogress(index int, message string)\n\tupdate_last_line(index int, message string)\n\tupdate_last_line_and_move_to_next(index int, message string)\n\tmessage(index int, message string)\n\tdivider() // called to show a long ---------- horizontal line; can be safely ignored in most reporters; used in the main thread.\n\tlist_of_failed_commands(cmds []string) // called after all testing is done, to produce a small summary that only lists the failed commands, so that they can be retried manually if needed, without forcing the user to scroll and find them.\n}\n"
  },
  {
    "path": "cmd/tools/modules/testing/output_dump.v",
    "content": "module testing\n\n// DumpReporter implements the interface testing.Reporter.\n// It is used by `v -test-runner dump test .`\npub struct DumpReporter {\nmut:\n\tfiles []string\n}\n\n//\n\npub fn (mut r DumpReporter) worker_threads_start(files []string, mut ts TestSession) {\n\teprintln('> ${@METHOD} | files: ${files}')\n\tr.files = files\n}\n\npub fn (r DumpReporter) worker_threads_finish(mut ts TestSession) {\n\teprintln('> ${@METHOD}')\n}\n\n//\n\npub fn (r DumpReporter) session_start(message string, mut ts TestSession) {\n\teprintln('> ${@METHOD} | message: ${message}')\n\t// dump(ts)\n}\n\npub fn (r DumpReporter) session_stop(message string, mut ts TestSession) {\n\teprintln('> ${@METHOD} | message: ${message}')\n}\n\n//\n\npub fn (r DumpReporter) report(index int, message LogMessage) {\n\teprintln('> ${@METHOD} | index: ${index} | message: ${message}')\n}\n\npub fn (r DumpReporter) report_stop() {\n\teprintln('> ${@METHOD}')\n}\n\npub fn (r DumpReporter) progress(index int, message string) {\n\teprintln('> ${@METHOD} | index: ${index} | message: ${message}')\n}\n\npub fn (r DumpReporter) update_last_line(index int, message string) {\n\teprintln('> ${@METHOD} | index: ${index} | message: ${message}')\n}\n\npub fn (r DumpReporter) update_last_line_and_move_to_next(index int, message string) {\n\teprintln('> ${@METHOD} | index: ${index} | message: ${message}')\n}\n\npub fn (r DumpReporter) message(index int, message string) {\n\teprintln('> ${@METHOD} | index: ${index} | message: ${message}')\n}\n\npub fn (r DumpReporter) divider() {\n\teprintln('> ${@METHOD}')\n}\n\npub fn (r DumpReporter) list_of_failed_commands(failed_cmds []string) {\n\teprintln('> ${@METHOD} | failed_cmds: ${failed_cmds}')\n}\n"
  },
  {
    "path": "cmd/tools/modules/testing/output_normal.v",
    "content": "module testing\n\nimport os\nimport time\nimport term\nimport strings\nimport runtime\n\npub const empty = term.header(' ', ' ')\n\n// TODO: AGAIN --- this !!!*reliably*!!! fails compilation of `v cmd/tools/vbuild-examples.v` with a cgen error, without `-no-parallel`:\n// pub const report_running_period_ms = os.getenv_opt('VTEST_REPORT_RUNNING_PERIOD_MS') or { '60000' }.int() * time.millisecond\n\npub const report_running_period_ms = get_report_running_period_ms()\n\nfn get_report_running_period_ms() time.Duration {\n\treturn os.getenv_opt('VTEST_REPORT_RUNNING_PERIOD_MS') or { '300_000' }.int() * time.millisecond // 5 minutes by default\n}\n\n// NormalReporter implements the interface testing.Reporter.\n// It is used by default by `v test .`\n// It was extracted by the original non customiseable output implementation directly in cmd/tools/modules/testing/common.v\npub struct NormalReporter {\nmut:\n\tvroot    string\n\truntime  time.Duration\n\tcomptime time.Duration\n\tnfiles   int\n\tnjobs    int\n\t//\n\trunning   shared map[string]LogMessage\n\tcompiling shared map[string]LogMessage\n\trtimes    shared []TaskDuration\n\tctimes    shared []TaskDuration\n}\n\npub fn (mut r NormalReporter) session_start(message string, mut ts TestSession) {\n\tr.vroot = ts.vroot.replace('\\\\', '/') + '/'\n\theader(message)\n\tr.nfiles = ts.files.len\n\tr.njobs = runtime.nr_jobs()\n\tspawn r.report_current_running_and_compiling_status_periodically()\n}\n\nfn (r &NormalReporter) report_current_running_and_compiling_status_periodically() {\n\tif report_running_period_ms == 0 {\n\t\treturn\n\t}\n\tmut start_t := time.now()\n\tmut pi := 0\n\tmut ccompiling := map[string]LogMessage{}\n\tmut crunning := map[string]LogMessage{}\n\tmut sb := strings.new_builder(1024)\n\tfor {\n\t\tpi++\n\t\ttime.sleep(report_running_period_ms)\n\t\tt := time.now()\n\t\trlock r.compiling {\n\t\t\tccompiling = r.compiling.clone()\n\t\t}\n\t\trlock r.running {\n\t\t\tcrunning = r.running.clone()\n\t\t}\n\t\tckeys := ccompiling.keys()\n\t\trkeys := crunning.keys()\n\t\tsb.writeln('')\n\t\tsb.writeln('       >>>>> ${t.format_ss_micro()} | period ${pi:2} | started: ${t - start_t:10} ago | vjobs: ${r.njobs} | _test.v files: ${r.nfiles:5} | C: ${ckeys.len:3} | R: ${rkeys.len:3}')\n\t\tfor ik, k in ckeys {\n\t\t\tcval := ccompiling[k]\n\t\t\tsb.writeln('       >>>>> compiling ${ik + 1:2}/${ckeys.len:-2}, T: ${cval.flow_id:2}, started: ${t - cval.when:10} ago, `${k}`')\n\t\t}\n\t\tfor ik, k in rkeys {\n\t\t\tcval := crunning[k]\n\t\t\tsb.writeln('       >>>>>   running ${ik + 1:2}/${rkeys.len:-2}, T: ${cval.flow_id:2}, started: ${t - cval.when:10} ago, `${k}`')\n\t\t}\n\t\tsb.writeln('')\n\t\teprint(sb.str()) // write everything at once, to minimise the chance of interference with the normal output of `v test`\n\t}\n}\n\nfn (r &NormalReporter) show_longest(label string, limit int, kind TaskKind) {\n\tif limit <= 0 {\n\t\treturn\n\t}\n\tprintln('> Longest ${limit} by ${label}:')\n\tmut tasks := []TaskDuration{cap: r.nfiles}\n\tmatch kind {\n\t\t.comptime {\n\t\t\trlock r.ctimes {\n\t\t\t\ttasks << r.ctimes\n\t\t\t}\n\t\t}\n\t\t.runtime {\n\t\t\trlock r.rtimes {\n\t\t\t\ttasks << r.rtimes\n\t\t\t}\n\t\t}\n\t\t.totaltime {\n\t\t\tmut tall := []TaskDuration{}\n\t\t\trlock r.rtimes {\n\t\t\t\ttall << r.rtimes\n\t\t\t}\n\t\t\trlock r.ctimes {\n\t\t\t\ttall << r.ctimes\n\t\t\t}\n\t\t\tmut mall := map[string]TaskDuration{}\n\t\t\tfor task in tall {\n\t\t\t\tif current := mall[task.path] {\n\t\t\t\t\tmall[task.path].duration = current.duration + task.duration\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tmall[task.path] = task\n\t\t\t}\n\t\t\ttasks = mall.values()\n\t\t}\n\t}\n\ttasks.sort(a.duration > b.duration)\n\tfor tidx, task in tasks {\n\t\tnpath := task.path.replace('\\\\', '/').replace(r.vroot, '')\n\t\tprintln('  ${tidx + 1:3} | ${task.duration:10s} | ${npath}')\n\t\tif tidx + 1 >= limit {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\npub fn (r &NormalReporter) session_stop(message string, mut ts TestSession) {\n\tr.show_longest('compilation time', show_longest_by_comptime, .comptime)\n\tr.show_longest('run time', show_longest_by_runtime, .runtime)\n\tr.show_longest('total time', show_longest_by_totaltime, .totaltime)\n\tprintln('${ts.benchmark.total_message(message)} Comptime: ${r.comptime.microseconds() / 1000} ms. Runtime: ${r.runtime.microseconds() / 1000} ms.')\n}\n\n// the most general form; it may be useful for other reporters\n// in the normal one, it currently does nothing\npub fn (mut r NormalReporter) report(index int, message LogMessage) {\n\t// eprintln('> ${@METHOD} index: ${index} | message: ${message}')\n\tif message.kind == .compile_begin {\n\t\tlock r.compiling {\n\t\t\tr.compiling[message.file] = message\n\t\t}\n\t}\n\tif message.kind == .compile_end {\n\t\tr.comptime += message.took\n\t\tlock r.ctimes {\n\t\t\tr.ctimes << TaskDuration{message.file, message.took}\n\t\t}\n\t\tlock r.compiling {\n\t\t\tr.compiling.delete(message.file)\n\t\t}\n\t}\n\tif message.kind == .cmd_end {\n\t\tlock r.rtimes {\n\t\t\tr.rtimes << TaskDuration{message.file, message.took}\n\t\t}\n\t\tr.runtime += message.took\n\t}\n\tif message.kind == .cmd_begin {\n\t\tlock r.running {\n\t\t\tr.running[message.file] = message\n\t\t}\n\t}\n\tif message.kind == .cmd_end {\n\t\tlock r.running {\n\t\t\tr.running.delete(message.file)\n\t\t}\n\t}\n}\n\npub fn (r NormalReporter) report_stop() {\n\t// eprintln('> ${@METHOD}')\n\teprintln('')\n}\n\n// progress will show the given message normally\n// TODO: reconsider if these should be public:\npub fn (r NormalReporter) progress(index int, message string) {\n\teprintln(message)\n}\n\n// in progress mode, the last line will be rewritten many times, and does not end with \\n\n// the \\n will be printed just once when some progress has been made.\npub fn (r NormalReporter) update_last_line(index int, message string) {\n\tprint('\\r${empty}\\r${message}')\n\tflush_stdout()\n}\n\npub fn (r NormalReporter) update_last_line_and_move_to_next(index int, message string) {\n\t// the last \\n is needed, so SKIP/FAIL messages\n\t// will not get overwritten by the OK ones\n\teprint('\\r${empty}\\r${message}\\n')\n}\n\npub fn (r NormalReporter) message(index int, message string) {\n\teprintln(message)\n}\n\npub fn (r NormalReporter) divider() {\n\th_divider()\n}\n\n//\n\npub fn (r NormalReporter) worker_threads_start(files []string, mut ts TestSession) {\n\t// eprintln('> ${@METHOD}')\n}\n\npub fn (r NormalReporter) worker_threads_finish(mut ts TestSession) {\n\t// eprintln('> ${@METHOD}')\n}\n\npub fn (r NormalReporter) list_of_failed_commands(failed_cmds []string) {\n\tfor i, cmd in failed_cmds {\n\t\teprintln(term.failed('To reproduce just failure ${i + 1} run:') + '    ${cmd}')\n\t}\n\tif failed_cmds.len > 0 {\n\t\tvflags := os.getenv('VFLAGS')\n\t\tif vflags != '' {\n\t\t\teprintln(term.failed('VFLAGS was: \"${vflags}\"'))\n\t\t}\n\t}\n}\n\nenum TaskKind {\n\tcomptime\n\truntime\n\ttotaltime\n}\n\nstruct TaskDuration {\nmut:\n\tpath     string\n\tduration time.Duration\n}\n"
  },
  {
    "path": "cmd/tools/modules/testing/output_teamcity.v",
    "content": "module testing\n\n// TeamcityReporter implements the interface `testing.Reporter`.\n// It is used by `v -test-runner teamcity test .`\npub struct TeamcityReporter {\n}\n\npub fn (r TeamcityReporter) session_start(message string, mut ts TestSession) {\n}\n\npub fn (r TeamcityReporter) session_stop(message string, mut ts TestSession) {\n}\n\npub fn (r TeamcityReporter) report(index int, message LogMessage) {\n\tname := r.get_test_suite_name_by_file(message.file)\n\tmatch message.kind {\n\t\t.cmd_begin {\n\t\t\teprintln(\"##teamcity[testSuiteStarted name='${name}' flowId='${message.flow_id}']\")\n\t\t}\n\t\t.cmd_end {\n\t\t\teprintln(\"##teamcity[testSuiteFinished name='${name}' flowId='${message.flow_id}' duration='${message.took}']\")\n\t\t}\n\t\t.cannot_compile {\n\t\t\teprintln(\"##teamcity[testFailed name='${name}' message='${message.message}']\")\n\t\t}\n\t\telse {}\n\t}\n}\n\npub fn (r TeamcityReporter) get_test_suite_name_by_file(path string) string {\n\tfile_name := path.replace('\\\\', '/').split('/').last()\n\treturn file_name.split('.').first()\n}\n\npub fn (r TeamcityReporter) report_stop() {\n}\n\npub fn (r TeamcityReporter) progress(index int, message string) {\n}\n\npub fn (r TeamcityReporter) update_last_line(index int, message string) {\n}\n\npub fn (r TeamcityReporter) update_last_line_and_move_to_next(index int, message string) {\n}\n\npub fn (r TeamcityReporter) message(index int, message string) {\n}\n\npub fn (r TeamcityReporter) divider() {\n}\n\npub fn (r TeamcityReporter) worker_threads_start(files []string, mut ts TestSession) {\n}\n\npub fn (r TeamcityReporter) worker_threads_finish(mut ts TestSession) {\n}\n\npub fn (r TeamcityReporter) list_of_failed_commands(failed_cmds []string) {\n}\n"
  },
  {
    "path": "cmd/tools/modules/vgit/vgit.v",
    "content": "module vgit\n\nimport os\nimport flag\nimport scripting\n\npub fn check_v_commit_timestamp_before_self_rebuilding(v_timestamp u64) {\n\tif v_timestamp >= 1561805697 {\n\t\treturn\n\t}\n\teprintln('##################################################################')\n\teprintln('# WARNING: v self rebuilding, before 5b7a1e8 (2019-06-29 12:21)  #')\n\teprintln('#          required the v executable to be built *inside*        #')\n\teprintln('#          the toplevel compiler/ folder.                        #')\n\teprintln('#                                                                #')\n\teprintln('#          That is not supported by this tool.                   #')\n\teprintln('#          You will have to build it manually there.             #')\n\teprintln('##################################################################')\n}\n\npub fn validate_commit_exists(commit string) {\n\tif commit != '' {\n\t\treturn\n\t}\n\tcmd := 'git cat-file -t \"${commit}\" ' // windows's cmd.exe does not support ' for quoting\n\tif !scripting.exit_0_status(cmd) {\n\t\teprintln('Commit: \"${commit}\" does not exist in the current repository.')\n\t\texit(3)\n\t}\n}\n\npub fn line_to_timestamp_and_commit(line string) (u64, string) {\n\tparts := line.split(' ')\n\treturn parts[0].u64(), parts[1]\n}\n\npub fn normalized_workpath_for_commit(workdir string, commit string) string {\n\tnc := 'v_at_' + commit.replace('^', '_').replace('-', '_').replace('/', '_')\n\treturn os.real_path(workdir + os.path_separator + nc)\n}\n\nfn get_current_folder_commit_hash() string {\n\tvline := scripting.run('git rev-list -n1 --timestamp HEAD')\n\t_, v_commithash := line_to_timestamp_and_commit(vline)\n\treturn v_commithash\n}\n\n@[noreturn]\nfn fatal_error(error IError, label string) {\n\teprintln('error: ${label}')\n\teprintln(error)\n\texit(1)\n}\n\n@[noreturn]\nfn co_fail(error IError, commit string) {\n\tfatal_error(error, 'git could not checkout `${commit}`')\n}\n\n@[noreturn]\nfn net_fail(error IError, what string) {\n\tfatal_error(error, 'git failed at `${what}`')\n}\n\npub fn prepare_vc_source(vcdir string, cdir string, commit string) (string, string, u64) {\n\tscripting.chdir(cdir)\n\t// Building a historic v with the latest vc is not always possible ...\n\t// It is more likely, that the vc *at the time of the v commit*,\n\t// or slightly before that time will be able to build the historic v:\n\tvline := scripting.run('git rev-list -n1 --timestamp \"${commit}\" ')\n\tv_timestamp, v_commithash := line_to_timestamp_and_commit(vline)\n\tscripting.verbose_trace(@FN, 'v_timestamp: ${v_timestamp} | v_commithash: ${v_commithash}')\n\tcheck_v_commit_timestamp_before_self_rebuilding(v_timestamp)\n\tscripting.chdir(vcdir)\n\tscripting.frun('git checkout --quiet master') or { co_fail(err, 'master') }\n\n\tmut vccommit := ''\n\tmut partial_hash := v_commithash[0..7]\n\tif '5b7a1e8'.starts_with(partial_hash) {\n\t\t// we need the following, otherwise --grep= below would find a93ef6e, which does include 5b7a1e8 in the commit message ... 🤦‍♂️\n\t\tpartial_hash = '5b7a1e84a4d283071d12cb86dc17aeda9b5306a8'\n\t}\n\tvcbefore_subject_match := scripting.run('git rev-list HEAD -n1 --timestamp --grep=${partial_hash} ')\n\tscripting.verbose_trace(@FN, 'vcbefore_subject_match: ${vcbefore_subject_match}')\n\tif vcbefore_subject_match.len > 3 {\n\t\t_, vccommit = line_to_timestamp_and_commit(vcbefore_subject_match)\n\t} else {\n\t\tscripting.verbose_trace(@FN, 'the v commit did not match anything in the vc log; try --timestamp instead.')\n\t\tvcbefore := scripting.run('git rev-list HEAD -n1 --timestamp --before=${v_timestamp} ')\n\t\t_, vccommit = line_to_timestamp_and_commit(vcbefore)\n\t}\n\tscripting.verbose_trace(@FN, 'vccommit: ${vccommit}')\n\tscripting.frun('git checkout --quiet \"${vccommit}\" ') or { co_fail(err, vccommit) }\n\tscripting.run('wc *.c')\n\tscripting.chdir(cdir)\n\treturn v_commithash, vccommit, v_timestamp\n}\n\npub fn clone_or_pull(remote_git_url string, local_worktree_path string) {\n\t// Note: after clone_or_pull, the current repo branch is === HEAD === master\n\tif os.is_dir(local_worktree_path) && os.is_dir(os.join_path_single(local_worktree_path, '.git')) {\n\t\t// Already existing ... Just pulling in this case is faster usually.\n\t\tscripting.frun('git -C \"${local_worktree_path}\" checkout --quiet master') or {\n\t\t\tco_fail(err, 'master')\n\t\t}\n\t\tscripting.frun('git -C \"${local_worktree_path}\" pull --quiet ') or {\n\t\t\tnet_fail(err, 'pulling')\n\t\t}\n\t} else {\n\t\t// Clone a fresh local tree.\n\t\tif remote_git_url.starts_with('http') {\n\t\t\t// cloning an https remote with --filter=blob:none is usually much less bandwidth intensive, at the\n\t\t\t// expense of doing small network ops later when using checkouts.\n\t\t\tscripting.frun('git clone --filter=blob:none --quiet \"${remote_git_url}\" \"${local_worktree_path}\" ') or {\n\t\t\t\tnet_fail(err, 'cloning')\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tmut is_blobless_clone := false\n\t\tremote_git_config_path := os.join_path(remote_git_url, '.git', 'config')\n\t\tif os.is_dir(remote_git_url) && os.is_file(remote_git_config_path) {\n\t\t\tlines := os.read_lines(remote_git_config_path) or { [] }\n\t\t\tis_blobless_clone = lines.any(it.contains('partialclonefilter = blob:none'))\n\t\t}\n\t\tif is_blobless_clone {\n\t\t\t// Note:\n\t\t\t// 1) cloning a *local folder* with `--filter=blob:none`, that *itself* was cloned with `--filter=blob:none`\n\t\t\t// leads to *extremely* slow checkouts for older commits later. It takes hours instead of milliseconds, for a commit\n\t\t\t// that is just several thousands of commits old :( .\n\t\t\t//\n\t\t\t// 2) Cloning it *without* the `--filter=blob:none`, leads to `error: unable to read sha1 file of`, later,\n\t\t\t// when checking out the older commits, depending on the local git client version (tested with git version 2.41.0).\n\t\t\t//\n\t\t\t// 3) => instead of cloning, it is much faster, and *bug free*, to just rsync the local repo directly,\n\t\t\t// at the expense of a little more space usage, which will make the new tree in local_worktree_path,\n\t\t\t// exactly 1:1 the same, as the one in remote_git_url, just independent from it .\n\t\t\tcopy_cmd := if os.user_os() == 'windows' { 'robocopy /MIR' } else { 'rsync -a' }\n\t\t\tscripting.frun('${copy_cmd} \"${remote_git_url}/\" \"${local_worktree_path}/\"') or {\n\t\t\t\tfatal_error(err, 'copying to ${local_worktree_path}')\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tscripting.frun('git clone --quiet \"${remote_git_url}\"  \"${local_worktree_path}\" ') or {\n\t\t\tnet_fail(err, 'cloning')\n\t\t}\n\t}\n}\n\npub struct VGitContext {\npub:\n\tcc          string = 'cc' // what C compiler to use for bootstrapping\n\tcc_options  string // what additional C compiler options to use for bootstrapping\n\tworkdir     string = '/tmp'   // the base working folder\n\tcommit_v    string = 'master' // the commit-ish that needs to be prepared\n\tpath_v      string // where is the local working copy v repo\n\tpath_vc     string // where is the local working copy vc repo\n\tv_repo_url  string // the remote v repo URL\n\tvc_repo_url string // the remote vc repo URL\npub mut:\n\t// these will be filled by vgitcontext.compile_oldv_if_needed()\n\tcommit_v__hash string // the git commit of the v repo that should be prepared\n\tcommit_vc_hash string // the git commit of the vc repo, corresponding to commit_v__hash\n\tcommit_v__ts   u64    // unix timestamp, that corresponds to commit_v__hash; filled by prepare_vc_source\n\tvexename       string // v or v.exe\n\tvexepath       string // the full absolute path to the prepared v/v.exe\n\tvvlocation     string // v.v or compiler/ or cmd/v, depending on v version\n\tmake_fresh_tcc bool   // whether to do 'make fresh_tcc' before compiling an old V.\n\tshow_vccommit  bool   // show the V and VC commits, corresponding to the V commit-ish, that can be used to build V\n}\n\npub fn (mut vgit_context VGitContext) compile_oldv_if_needed() {\n\tvgit_context.vexename = if os.user_os() == 'windows' { 'v.exe' } else { 'v' }\n\tvgit_context.vexepath = os.real_path(os.join_path_single(vgit_context.path_v, vgit_context.vexename))\n\tif os.is_dir(vgit_context.path_v) && os.is_executable(vgit_context.vexepath)\n\t\t&& !vgit_context.show_vccommit {\n\t\t// already compiled, no need to compile that specific v executable again\n\t\tvgit_context.commit_v__hash = get_current_folder_commit_hash()\n\t\treturn\n\t}\n\tscripting.chdir(vgit_context.workdir)\n\tclone_or_pull(vgit_context.v_repo_url, vgit_context.path_v)\n\tclone_or_pull(vgit_context.vc_repo_url, vgit_context.path_vc)\n\tscripting.chdir(vgit_context.path_v)\n\tscripting.frun('git checkout --quiet ${vgit_context.commit_v}') or {\n\t\tco_fail(err, vgit_context.commit_v)\n\t}\n\tif os.is_dir(vgit_context.path_v) && os.exists(vgit_context.vexepath)\n\t\t&& !vgit_context.show_vccommit {\n\t\t// already compiled, so no need to compile v again\n\t\tvgit_context.commit_v__hash = get_current_folder_commit_hash()\n\t\treturn\n\t}\n\tv_commithash, vccommit_before, v_timestamp := prepare_vc_source(vgit_context.path_vc,\n\t\tvgit_context.path_v, 'HEAD')\n\tvgit_context.commit_v__hash = v_commithash\n\tvgit_context.commit_v__ts = v_timestamp\n\tvgit_context.commit_vc_hash = vccommit_before\n\n\tif vgit_context.show_vccommit {\n\t\tprintln('VHASH=${vgit_context.commit_v__hash}')\n\t\tprintln('VCHASH=${vgit_context.commit_vc_hash}')\n\t\texit(0)\n\t}\n\n\tif os.exists('cmd/v') {\n\t\tvgit_context.vvlocation = 'cmd/v'\n\t} else {\n\t\tvgit_context.vvlocation = if os.exists('v.v') { 'v.v' } else { 'compiler' }\n\t}\n\tif os.is_dir(vgit_context.path_v) && os.exists(vgit_context.vexepath) {\n\t\t// already compiled, so no need to compile v again\n\t\treturn\n\t}\n\n\tscripting.chdir(vgit_context.path_v)\n\t// Recompilation is needed. Just to be sure, clean up everything first.\n\tscripting.run('git clean -xf')\n\tif vgit_context.make_fresh_tcc {\n\t\tscripting.run('make fresh_tcc')\n\t}\n\n\t// compiling the C sources with a C compiler:\n\tmut command_for_building_v_from_c_source := ''\n\tmut command_for_selfbuilding := ''\n\tmut c_flags := '-std=gnu11 -I ./thirdparty/stdatomic/nix -w'\n\tmut c_ldflags := '-lm -lpthread'\n\tmut vc_source_file_location := os.join_path_single(vgit_context.path_vc, 'v.c')\n\tmut vc_v_cpermissive_flags := '${vgit_context.cc_options} -Wno-error=incompatible-pointer-types -Wno-error=implicit-function-declaration -Wno-error=int-conversion -fpermissive'\n\t// after 85b58b0 2021-09-28, -no-parallel is supported, and can be used to force the cgen stage to be single threaded, which increases the chances of successful bootstraps\n\tmut vc_v_bootstrap_flags := ''\n\tif vgit_context.commit_v__ts >= 1632778086 {\n\t\tvc_v_bootstrap_flags += ' -no-parallel'\n\t}\n\tvc_v_bootstrap_flags = vc_v_bootstrap_flags.trim_space()\n\tscripting.verbose_trace(@FN, 'vc_v_bootstrap_flags: ${vc_v_bootstrap_flags}')\n\tscripting.verbose_trace(@FN, 'vc_v_cpermissive_flags: ${vc_v_cpermissive_flags}')\n\tscripting.verbose_trace(@FN, 'vgit_context.commit_v__ts: ${vgit_context.commit_v__ts}')\n\n\tif 'windows' == os.user_os() {\n\t\tc_flags = '-std=c99 -I ./thirdparty/stdatomic/win -w'\n\t\tc_ldflags = ''\n\t\tv_win_c_location := os.join_path_single(vgit_context.path_vc, 'v_win.c')\n\t\tif os.exists(v_win_c_location) {\n\t\t\tvc_source_file_location = v_win_c_location\n\t\t}\n\t}\n\tif 'windows' == os.user_os() {\n\t\tif vgit_context.commit_v__ts >= 1589793086 && vgit_context.cc.contains('gcc') {\n\t\t\t// after 53ffee1 2020-05-18, gcc builds on windows do need `-municode`\n\t\t\tc_flags += '-municode'\n\t\t}\n\t\t// after 2023-11-07, windows builds need linking to ws2_32:\n\t\tif vgit_context.commit_v__ts >= 1699341818 && !vgit_context.cc.contains('msvc') {\n\t\t\tc_flags += '-lws2_32'\n\t\t}\n\t\tcommand_for_building_v_from_c_source = c(vgit_context.cc, '${vc_v_cpermissive_flags} ${c_flags} -o cv.exe \"${vc_source_file_location}\" ${c_ldflags}')\n\t\tcommand_for_selfbuilding = c('.\\\\cv.exe', '${vc_v_bootstrap_flags} -cflags \"${vc_v_cpermissive_flags}\" -o ${vgit_context.vexename} {SOURCE}')\n\t} else {\n\t\tcommand_for_building_v_from_c_source = c(vgit_context.cc, '${vc_v_cpermissive_flags} ${c_flags} -o cv \"${vc_source_file_location}\" ${c_ldflags}')\n\t\tcommand_for_selfbuilding = c('./cv', '${vc_v_bootstrap_flags} -cflags \"${vc_v_cpermissive_flags}\" -o ${vgit_context.vexename} {SOURCE}')\n\t}\n\n\tscripting.run(command_for_building_v_from_c_source)\n\tbuild_cmd := command_for_selfbuilding.replace('{SOURCE}', vgit_context.vvlocation)\n\tscripting.run(build_cmd)\n\t// At this point, there exists a file vgit_context.vexepath\n\t// which should be a valid working V executable.\n}\n\nfn c(cmd string, params string) string {\n\t// compose a command, while reducing the potential whitespaces, due to all the interpolations of optional flags above\n\treturn '${cmd} ${params.trim_space()}'\n}\n\npub struct VGitOptions {\npub mut:\n\tworkdir     string = os.temp_dir() // the working folder (typically /tmp), where the tool will write\n\tv_repo_url  string // the url of the V repository. It can be a local folder path, if you want to eliminate network operations...\n\tvc_repo_url string // the url of the vc repository. It can be a local folder path, if you want to eliminate network operations...\n\tshow_help   bool   // whether to show the usage screen\n\tverbose     bool   // should the tool be much more verbose\n}\n\npub fn add_common_tool_options(mut context VGitOptions, mut fp flag.FlagParser) []string {\n\tcontext.workdir = os.real_path(fp.string('workdir', `w`, context.workdir, 'A writable base folder. Default: ${context.workdir}'))\n\tcontext.v_repo_url = fp.string('vrepo', 0, context.v_repo_url, 'The url of the V repository. You can clone it locally too. See also --vcrepo below.')\n\tcontext.vc_repo_url = fp.string('vcrepo', 0, context.vc_repo_url, 'The url of the vc repository. You can clone it\n${flag.space}beforehand, and then just give the local folder\n${flag.space}path here. That will eliminate the network ops\n${flag.space}done by this tool, which is useful, if you want\n${flag.space}to script it/run it in a restrictive vps/docker.\n')\n\tcontext.show_help = fp.bool('help', `h`, false, 'Show this help screen.')\n\tcontext.verbose = fp.bool('verbose', `v`, false, 'Be more verbose.')\n\tif context.show_help {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\tif context.verbose {\n\t\tscripting.set_verbose(true)\n\t}\n\tif os.is_dir(context.v_repo_url) {\n\t\tcontext.v_repo_url = os.real_path(context.v_repo_url)\n\t}\n\tif os.is_dir(context.vc_repo_url) {\n\t\tcontext.vc_repo_url = os.real_path(context.vc_repo_url)\n\t}\n\tcommits := fp.finalize() or {\n\t\teprintln('Error: ${err}')\n\t\texit(1)\n\t}\n\tfor commit in commits {\n\t\tvalidate_commit_exists(commit)\n\t}\n\treturn commits\n}\n"
  },
  {
    "path": "cmd/tools/oldv.v",
    "content": "import os\nimport flag\nimport scripting\nimport vgit\n\nconst tool_version = '0.0.4'\nconst tool_description = '  Checkout an old version of V and compile it as it was on a specific commit.\n|     This tool is useful when you want to discover when something broke.\n|     It is also useful when you just want to experiment with an older, historic V.\n|\n|     The VCOMMIT argument can be a git commit object like HEAD or master and so on.\n|     When oldv is used with git bisect, you probably want to use HEAD. For example:\n|          git bisect start\n|          git bisect bad\n|          git checkout known_good_commit\n|          git bisect good\n|              ## git will automatically checkout a middle commit between the bad and the good\n|          cmd/tools/oldv --bisect --command=\"run commands in oldv folder, to verify if the commit is good or bad\n|              ## Examine the results, and either do: ...\n|          git bisect good\n|              ## ... or do:\n|          git bisect bad\n|              ## Repeat the above steps, each time running oldv with the same command, then mark the result as good\n|              ## or bad until you find the commit where the problem first occurred.\n|              ## When you finish, do not forget to do:\n|          git bisect reset'.strip_margin()\n\nstruct Context {\nmut:\n\tvgo           vgit.VGitOptions\n\tvgcontext     vgit.VGitContext\n\tcommit_v      string = 'master' // the commit from which you want to produce a working v compiler (this may be a commit-ish too)\n\tcommit_v_hash string // this will be filled from the commit-ish commit_v using rev-list. It IS a commit hash.\n\tpath_v        string // the full path to the v folder inside workdir.\n\tpath_vc       string // the full path to the vc folder inside workdir.\n\tcmd_to_run    string // the command that you want to run *in* the oldv repo\n\tcleanup       bool   // should the tool run a cleanup first\n\tuse_cache     bool   // use local cached copies for --vrepo and --vcrepo in\n\tfresh_tcc     bool   // do use `make fresh_tcc`\n\tis_bisect     bool   // bisect mode; usage: `cmd/tools/oldv -b -c './v run bug.v'`\n\tshow_vccommit bool   // show the V and VC commits, corresponding to the V commit-ish, that can be used to build V\n\tcc            string = 'cc' // the C compiler to use for bootstrapping.\n\tcc_options    string // additional options to pass to the C compiler while bootstrapping.\n}\n\nfn (mut c Context) compile_oldv_if_needed() {\n\tc.vgcontext = vgit.VGitContext{\n\t\tworkdir:        c.vgo.workdir\n\t\tv_repo_url:     c.vgo.v_repo_url\n\t\tvc_repo_url:    c.vgo.vc_repo_url\n\t\tcc:             c.cc\n\t\tcc_options:     c.cc_options\n\t\tcommit_v:       c.commit_v\n\t\tpath_v:         c.path_v\n\t\tpath_vc:        c.path_vc\n\t\tmake_fresh_tcc: c.fresh_tcc\n\t\tshow_vccommit:  c.show_vccommit\n\t}\n\tc.vgcontext.compile_oldv_if_needed()\n\tc.commit_v_hash = c.vgcontext.commit_v__hash\n\tif !os.exists(c.vgcontext.vexepath) && c.cmd_to_run.len > 0 {\n\t\t// Note: 125 is a special code, that git bisect understands as 'skip this commit'.\n\t\t// it is used to inform git bisect that the current commit leads to a build failure.\n\t\texit(125)\n\t}\n}\n\nconst cache_oldv_folder = os.join_path(os.cache_dir(), 'oldv')\n\nconst cache_oldv_folder_v = os.join_path(cache_oldv_folder, 'v')\n\nconst cache_oldv_folder_vc = os.join_path(cache_oldv_folder, 'vc')\n\nfn sync_cache() {\n\tscripting.verbose_trace(@FN, 'start')\n\tif !os.exists(cache_oldv_folder) {\n\t\tscripting.verbose_trace(@FN, 'creating ${cache_oldv_folder}')\n\t\tscripting.mkdir_all(cache_oldv_folder) or {\n\t\t\tscripting.verbose_trace(@FN, '## failed.')\n\t\t\texit(1)\n\t\t}\n\t}\n\tscripting.chdir(cache_oldv_folder)\n\tfor reponame in ['v', 'vc'] {\n\t\trepofolder := os.join_path(cache_oldv_folder, reponame)\n\t\tif !os.exists(repofolder) {\n\t\t\tscripting.verbose_trace(@FN, 'cloning to ${repofolder}')\n\t\t\tmut repo_options := ''\n\t\t\tif reponame == 'vc' {\n\t\t\t\trepo_options = '--filter=blob:none'\n\t\t\t}\n\t\t\tscripting.exec('git clone ${repo_options} --quiet https://github.com/vlang/${reponame} ${repofolder}') or {\n\t\t\t\tscripting.verbose_trace(@FN, '## error during clone: ${err}')\n\t\t\t\texit(1)\n\t\t\t}\n\t\t}\n\t\tscripting.chdir(repofolder)\n\t\tscripting.exec('git pull --quiet') or {\n\t\t\tscripting.verbose_trace(@FN, 'pulling to ${repofolder}')\n\t\t\tscripting.verbose_trace(@FN, '## error during pull: ${err}')\n\t\t\texit(1)\n\t\t}\n\t}\n\tscripting.verbose_trace(@FN, 'done')\n}\n\nfn main() {\n\tif os.user_os() == 'windows' {\n\t\tscripting.used_tools_must_exist(['git', 'wc', 'make', 'robocopy'])\n\t} else {\n\t\tscripting.used_tools_must_exist(['git', 'wc', 'make', 'rsync', 'cc'])\n\t}\n\n\t// Resetting VEXE here allows for `v run cmd/tools/oldv.v'.\n\t// the parent V would have set VEXE, which later will\n\t// affect the V's run from the tool itself.\n\tos.setenv('VEXE', '', true)\n\n\tmut context := Context{}\n\tcontext.vgo.workdir = cache_oldv_folder\n\tmut fp := flag.new_flag_parser(os.args)\n\tfp.application(os.file_name(os.executable()))\n\tfp.version(tool_version)\n\tfp.description(tool_description)\n\tfp.arguments_description('VCOMMIT')\n\tfp.skip_executable()\n\tcontext.use_cache = fp.bool('cache', `u`, true, 'Use a cache of local repositories for --vrepo and --vcrepo in \\$HOME/.cache/oldv/')\n\tif context.use_cache {\n\t\tcontext.vgo.v_repo_url = cache_oldv_folder_v\n\t\tcontext.vgo.vc_repo_url = cache_oldv_folder_vc\n\t} else {\n\t\tcontext.vgo.v_repo_url = 'https://github.com/vlang/v'\n\t\tcontext.vgo.vc_repo_url = 'https://github.com/vlang/vc'\n\t}\n\tcontext.cc = fp.string('cc', 0, 'cc', 'Use this C compiler for bootstrapping v.c (defaults to `cc`).')\n\tcontext.cc_options = fp.string('ccoptions', 0, '', 'Use these C compiler options for bootstrapping v.c (defaults to ``).')\n\tenv_cc_options := os.getenv('OLDV_CCOPTIONS')\n\tif env_cc_options != '' {\n\t\tcontext.cc_options = env_cc_options\n\t}\n\tcontext.cleanup = fp.bool('clean', 0, false, 'Clean before running (slower).')\n\tcontext.fresh_tcc = fp.bool('fresh_tcc', 0, true, 'Do `make fresh_tcc` when preparing a V compiler.')\n\tcontext.cmd_to_run = fp.string('command', `c`, '', 'Command to run in the old V repo.\\n')\n\tcontext.show_vccommit = fp.bool('show_VC_commit', 0, false, 'Show the VC commit, that can be used to compile the given V commit, and exit.\\n')\n\tcontext.is_bisect = fp.bool('bisect', `b`, false, 'Bisect mode. Use the current commit in the repo where oldv is.')\n\n\tshould_sync := fp.bool('cache-sync', `s`, false, 'Update the local cache')\n\tif !should_sync && !context.is_bisect {\n\t\tfp.limit_free_args(1, 1)!\n\t}\n\n\t////\n\tcommits := vgit.add_common_tool_options(mut context.vgo, mut fp)\n\tif should_sync {\n\t\tsync_cache()\n\t\tprintln('Cache synced, cache folder: ${cache_oldv_folder} .')\n\t\texit(0)\n\t}\n\tif context.use_cache {\n\t\tif !os.is_dir(cache_oldv_folder_v) || !os.is_dir(cache_oldv_folder_vc) {\n\t\t\tsync_cache()\n\t\t}\n\t}\n\tif commits.len > 0 {\n\t\tcontext.commit_v = commits[0]\n\t\tif context.is_bisect {\n\t\t\teprintln('In bisect mode, you should not pass any commits, since oldv will use the current one.')\n\t\t\texit(2)\n\t\t}\n\t} else {\n\t\tcontext.commit_v = scripting.run('git rev-list -n1 HEAD')\n\t}\n\tif !context.show_vccommit {\n\t\tscripting.cprintln('#################  context.commit_v: ${context.commit_v} #####################')\n\t}\n\tcontext.path_v = vgit.normalized_workpath_for_commit(context.vgo.workdir, context.commit_v)\n\tcontext.path_vc = vgit.normalized_workpath_for_commit(context.vgo.workdir, 'vc')\n\tif !os.is_dir(context.vgo.workdir) {\n\t\teprintln('Work folder: ${context.vgo.workdir} , does not exist.')\n\t\texit(2)\n\t}\n\tecc := os.getenv('CC')\n\tif ecc != '' {\n\t\tcontext.cc = ecc\n\t}\n\tif context.cleanup {\n\t\tscripting.rmrf(context.path_v)\n\t\tscripting.rmrf(context.path_vc)\n\t}\n\tcontext.compile_oldv_if_needed()\n\tscripting.chdir(context.path_v)\n\tshorter_hash := context.commit_v_hash[0..10]\n\tscripting.cprintln('#     v commit hash: ${shorter_hash} | folder: ${context.path_v}')\n\tif context.cmd_to_run.len > 0 {\n\t\tscripting.cprintln_strong('#           command: ${context.cmd_to_run:-34s}')\n\t\tcmdres := os.execute_or_exit(context.cmd_to_run)\n\t\tif cmdres.exit_code != 0 {\n\t\t\tscripting.cprintln_strong('#         exit code: ${cmdres.exit_code:-4d}')\n\t\t}\n\t\tscripting.cprint_strong('#            result: ')\n\t\tprint(cmdres.output)\n\t\tif !cmdres.output.ends_with('\\n') {\n\t\t\tprintln('')\n\t\t}\n\t\texit(cmdres.exit_code)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/performance_compare.v",
    "content": "import os\nimport flag\nimport scripting\nimport vgit\n\nconst tool_version = '0.0.6'\nconst tool_description = \"  Compares V executable size and performance,\n|  between 2 commits from V's local git history.\n|  When only one commit is given, it is compared to master.\n|  \".strip_margin()\n\nstruct Context {\n\tcwd string // current working folder\nmut:\n\tvgo           vgit.VGitOptions\n\ta             string // the full path to the 'after' folder inside workdir\n\tb             string // the full path to the 'before' folder inside workdir\n\tvc            string // the full path to the vc folder inside workdir. It is used during bootstrapping v from the C source.\n\tcommit_before string // the git commit for the 'before' state\n\tcommit_after  string // the git commit for the 'after' state\n\twarmups       int    // how many times to execute a command before gathering stats\n\thyperfineopts string // use for additional CLI options that will be given to the hyperfine command\n\tvflags        string // other v options to pass to compared v commands\n}\n\nfn new_context() Context {\n\treturn Context{\n\t\tcwd:          os.getwd()\n\t\tcommit_after: 'master'\n\t\twarmups:      4\n\t}\n}\n\nfn (c Context) compare_versions() {\n\t// Input is validated at this point...\n\t// Cleanup artifacts from previous runs of this tool:\n\tscripting.chdir(c.vgo.workdir)\n\tscripting.run('rm -rf \"${c.a}\" \"${c.b}\" \"${c.vc}\" ')\n\t// clone the VC source *just once per comparison*, and reuse it:\n\tscripting.run('git clone --filter=blob:none --quiet \"${c.vgo.vc_repo_url}\" \"${c.vc}\" ')\n\tprintln('Comparing V performance of commit ${c.commit_before} (before) vs commit ${c.commit_after} (after) ...')\n\tc.prepare_v(c.b, c.commit_before)\n\tc.prepare_v(c.a, c.commit_after)\n\tscripting.chdir(c.vgo.workdir)\n\tif c.vflags.len > 0 {\n\t\tos.setenv('VFLAGS', c.vflags, true)\n\t}\n\t// The first is the baseline, against which all the others will be compared.\n\t// It is the fastest, since hello_world.v has only a single println in it,\n\tmut perf_files := []string{}\n\tperf_files << c.compare_v_performance('source_hello', [\n\t\t'vprod @DEBUG@ -o source.c examples/hello_world.v',\n\t\t'vprod         -o source.c examples/hello_world.v',\n\t\t'v     @DEBUG@ -o source.c examples/hello_world.v',\n\t\t'v             -o source.c examples/hello_world.v',\n\t])\n\tperf_files << c.compare_v_performance('source_v', [\n\t\t'vprod @DEBUG@ -o source.c @COMPILER@',\n\t\t'vprod         -o source.c @COMPILER@',\n\t\t'v     @DEBUG@ -o source.c @COMPILER@',\n\t\t'v             -o source.c @COMPILER@',\n\t])\n\tperf_files << c.compare_v_performance('binary_hello', [\n\t\t'vprod         -o hello    examples/hello_world.v',\n\t\t'v             -o hello    examples/hello_world.v',\n\t])\n\tperf_files << c.compare_v_performance('binary_v', [\n\t\t'vprod         -o binary   @COMPILER@',\n\t\t'v             -o binary   @COMPILER@',\n\t])\n\tprintln('All performance files:')\n\tfor f in perf_files {\n\t\tprintln('   ${f}')\n\t}\n}\n\nfn (c &Context) prepare_v(cdir string, commit string) {\n\tmut cc := os.getenv('CC')\n\tif cc == '' {\n\t\tcc = 'cc'\n\t}\n\tmut vgit_context := vgit.VGitContext{\n\t\tcc:          cc\n\t\tcommit_v:    commit\n\t\tpath_v:      cdir\n\t\tpath_vc:     c.vc\n\t\tworkdir:     c.vgo.workdir\n\t\tv_repo_url:  c.vgo.v_repo_url\n\t\tvc_repo_url: c.vgo.vc_repo_url\n\t}\n\tvgit_context.compile_oldv_if_needed()\n\tscripting.chdir(cdir)\n\tscripting.run('${cdir}/v version')\n\tprintln('Making a v compiler in ${cdir}')\n\tscripting.run('./v -cc ${cc}       -o v     ${vgit_context.vvlocation}')\n\tprintln('Making a vprod compiler in ${cdir}')\n\tscripting.run('./v -cc ${cc} -prod -o vprod ${vgit_context.vvlocation}')\n\tprintln('Stripping and compressing cv v and vprod binaries in ${cdir}')\n\tscripting.run('cp    cv     cv_stripped')\n\tscripting.run('cp     v      v_stripped')\n\tscripting.run('cp vprod  vprod_stripped')\n\tscripting.run('strip *_stripped')\n\tscripting.run('cp cv_stripped cv_stripped_upxed')\n\tscripting.run('cp  v_stripped  v_stripped_upxed')\n\tscripting.run('cp vprod_stripped vprod_stripped_upxed')\n\tscripting.run('upx -qqq --lzma    cv_stripped_upxed')\n\tscripting.run('upx -qqq --lzma     v_stripped_upxed')\n\tscripting.run('upx -qqq --lzma vprod_stripped_upxed')\n\tscripting.show_sizes_of_files(['${cdir}/cv', '${cdir}/cv_stripped', '${cdir}/cv_stripped_upxed'])\n\tscripting.show_sizes_of_files(['${cdir}/v', '${cdir}/v_stripped', '${cdir}/v_stripped_upxed'])\n\tscripting.show_sizes_of_files(['${cdir}/vprod', '${cdir}/vprod_stripped',\n\t\t'${cdir}/vprod_stripped_upxed'])\n\tvversion := scripting.run('${cdir}/v -version')\n\tvcommit := scripting.run('git rev-parse --short  --verify HEAD')\n\tprintln('V version is: ${vversion} , local source commit: ${vcommit}')\n\tif vgit_context.vvlocation == 'cmd/v' {\n\t\tif os.exists('vlib/v/ast/ast.v') {\n\t\t\tprintln('Source lines of the compiler: ' +\n\t\t\t\tscripting.run('find cmd/v/ vlib/v/ -name \"*.v\" | grep -v /tests/ | xargs wc | tail -n -1'))\n\t\t} else {\n\t\t\tprintln('Source lines of the compiler: ' +\n\t\t\t\tscripting.run('wc cmd/v/*.v vlib/compiler/*.v | tail -n -1'))\n\t\t}\n\t} else if vgit_context.vvlocation == 'v.v' {\n\t\tprintln('Source lines of the compiler: ' +\n\t\t\tscripting.run('wc v.v vlib/compiler/*.v | tail -n -1'))\n\t} else {\n\t\tprintln('Source lines of the compiler: ' + scripting.run('wc compiler/*.v | tail -n -1'))\n\t}\n}\n\nfn (c Context) compare_v_performance(label string, commands []string) string {\n\tprintln('---------------------------------------------------------------------------------')\n\tprintln('Compare v performance when doing the following commands (${label}):')\n\tmut source_location_a := ''\n\tmut source_location_b := ''\n\tif os.exists('${c.a}/cmd/v') {\n\t\tsource_location_a = 'cmd/v'\n\t} else {\n\t\tsource_location_a = if os.exists('${c.a}/v.v') { 'v.v       ' } else { 'compiler/ ' }\n\t}\n\tif os.exists('${c.b}/cmd/v') {\n\t\tsource_location_b = 'cmd/v'\n\t} else {\n\t\tsource_location_b = if os.exists('${c.b}/v.v') { 'v.v       ' } else { 'compiler/ ' }\n\t}\n\ttimestamp_a, _ := vgit.line_to_timestamp_and_commit(scripting.run('cd ${c.a}/ ; git rev-list -n1 --timestamp HEAD'))\n\ttimestamp_b, _ := vgit.line_to_timestamp_and_commit(scripting.run('cd ${c.b}/ ; git rev-list -n1 --timestamp HEAD'))\n\t// 1570877641 is 065ce39 2019-10-12\n\tdebug_option_a := if timestamp_a > 1570877641 { '-cg    ' } else { '-debug ' }\n\tdebug_option_b := if timestamp_b > 1570877641 { '-cg    ' } else { '-debug ' }\n\tmut hyperfine_commands_arguments := []string{}\n\tfor cmd in commands {\n\t\tprintln(cmd)\n\t}\n\tfor cmd in commands {\n\t\thyperfine_commands_arguments << ' \\'cd ${c.b:-34s} ; ./${cmd} \\' '.replace_each([\n\t\t\t'@COMPILER@',\n\t\t\tsource_location_b,\n\t\t\t'@DEBUG@',\n\t\t\tdebug_option_b,\n\t\t])\n\t}\n\tfor cmd in commands {\n\t\thyperfine_commands_arguments << ' \\'cd ${c.a:-34s} ; ./${cmd} \\' '.replace_each([\n\t\t\t'@COMPILER@',\n\t\t\tsource_location_a,\n\t\t\t'@DEBUG@',\n\t\t\tdebug_option_a,\n\t\t])\n\t}\n\t// /////////////////////////////////////////////////////////////////////////////\n\tcmd_stats_file := os.real_path([c.vgo.workdir, 'v_performance_stats_${label}.json'].join(os.path_separator))\n\tcomparison_cmd := 'hyperfine ${c.hyperfineopts} ' + '--export-json ${cmd_stats_file} ' +\n\t\t'--time-unit millisecond ' + '--style full --warmup ${c.warmups} ' +\n\t\thyperfine_commands_arguments.join(' ')\n\t// /////////////////////////////////////////////////////////////////////////////\n\tif c.vgo.verbose {\n\t\tprintln(comparison_cmd)\n\t}\n\tos.system(comparison_cmd)\n\tprintln('The detailed performance comparison report was saved to: ${cmd_stats_file} .')\n\tprintln('')\n\treturn cmd_stats_file\n}\n\nfn main() {\n\t// allow for `v run cmd/tools/performance_compare.v`, see oldv.v\n\tos.setenv('VEXE', '', true)\n\tscripting.used_tools_must_exist(['cp', 'rm', 'strip', 'make', 'git', 'upx', 'cc', 'wc', 'tail',\n\t\t'find', 'xargs', 'hyperfine'])\n\tmut context := new_context()\n\tmut fp := flag.new_flag_parser(os.args)\n\tfp.application(os.file_name(os.executable()))\n\tfp.version(tool_version)\n\tfp.description(tool_description)\n\tfp.arguments_description('COMMIT_BEFORE [COMMIT_AFTER]')\n\tfp.skip_executable()\n\tfp.limit_free_args(1, 2)!\n\tcontext.vflags = fp.string('vflags', 0, '', 'Additional options to pass to the v commands, for example \"-cc tcc\"')\n\tcontext.hyperfineopts = fp.string('hyperfine_options', 0, '', 'Additional options passed to hyperfine.\n${flag.space}For example on linux, you may want to pass:\n${flag.space}--hyperfine_options \"--prepare \\'sync; echo 3 | sudo tee /proc/sys/vm/drop_caches\\'\"\n')\n\tcommits := vgit.add_common_tool_options(mut context.vgo, mut fp)\n\tcontext.commit_before = commits[0]\n\tif commits.len > 1 {\n\t\tcontext.commit_after = commits[1]\n\t}\n\tcontext.b = vgit.normalized_workpath_for_commit(context.vgo.workdir, context.commit_before)\n\tcontext.a = vgit.normalized_workpath_for_commit(context.vgo.workdir, context.commit_after)\n\tcontext.vc = vgit.normalized_workpath_for_commit(context.vgo.workdir, 'vc')\n\tif !os.is_dir(context.vgo.workdir) {\n\t\teprintln('Work folder: `{context.vgo.workdir}` , does not exist. Use `--workdir /some/path` to set it.')\n\t\texit(2)\n\t}\n\tcontext.compare_versions()\n}\n"
  },
  {
    "path": "cmd/tools/regress.v",
    "content": "import os\nimport term\nimport flag\n\nconst tools_folder = os.real_path(os.dir(os.executable()))\n\nconst oldvexe = fullpath(tools_folder, 'oldv')\n\nconst oldv_source = fullpath(tools_folder, 'oldv.v')\n\nconst vroot = os.real_path(os.dir(os.dir(tools_folder)))\n\nconst vexe = fullpath(vroot, 'v')\n\nfn fullpath(folder string, fname string) string {\n\treturn os.real_path(os.join_path_single(folder, exename(fname)))\n}\n\nfn exename(n string) string {\n\tif n.ends_with('.v') || os.user_os() != 'windows' {\n\t\treturn n\n\t}\n\treturn '${n}.exe'\n}\n\nstruct Context {\nmut:\n\told_commit string\n\tnew_commit string\n\tcommand    string\n}\n\nfn main() {\n\tmut fp := flag.new_flag_parser(os.args)\n\tmut context := Context{}\n\tfp.application(os.file_name(os.executable()))\n\tfp.version('0.0.2')\n\tfp.description('\\n  Find at what commit a regression occurred.\n  To find when a regression happened (regression_bug.v should fail on master):\n     ./v run cmd/tools/regress.v --old a7019ac --command \"  ./v run /abs/path/to/regression_bug.v\"\n  To find when a feature was implemented (feature.v should succeed on master):\n     ./v run cmd/tools/regress.v --old a7019ac --command \"! ./v run /abs/path/to/feature.v\"')\n\tfp.skip_executable()\n\n\tcontext.new_commit = fp.string('new', `n`, 'master', 'The new commit, by default: master.')\n\tcontext.old_commit = fp.string('old', `o`, '', 'A known old commit, required (for it, COMMAND should exit with 0).')\n\tcontext.command = fp.string('command', `c`, '', 'A command to execute. Should exit with 0 for the *old* commits.')\n\tfp.finalize() or {}\n\tif context.old_commit == '' {\n\t\teprintln('--old COMMIT is required')\n\t\texit(1)\n\t}\n\tif context.command == '' {\n\t\teprintln('--command \"COMMAND\" is required')\n\t\texit(2)\n\t}\n\tif !os.exists(oldvexe) {\n\t\tif 0 != execute('${os.quoted_path(vexe)} -o ${os.quoted_path(oldvexe)} ${os.quoted_path(oldv_source)}') {\n\t\t\tpanic('can not compile ${oldvexe}')\n\t\t}\n\t}\n\tos.execute('git checkout master')\n\tos.execute('git bisect reset')\n\tos.execute('git checkout ${context.new_commit}')\n\tos.execute('git bisect start')\n\tos.execute('git bisect new')\n\tos.execute('git checkout ${context.old_commit}')\n\tos.execute('git bisect old')\n\tprintln(term.colorize(term.bright_yellow, term.header('', '-')))\n\texecute('git bisect run ${os.quoted_path(oldvexe)} --bisect -c \"${context.command}\"')\n\tprintln(term.colorize(term.bright_yellow, term.header('', '-')))\n\tos.execute('git bisect reset')\n\tos.execute('git checkout master')\n}\n\nfn execute(cmd string) int {\n\teprintln('### ${cmd}')\n\treturn os.system(cmd)\n}\n"
  },
  {
    "path": "cmd/tools/report_v_module_folders_without_tests.v",
    "content": "module main\n\nimport os\n\nconst vexe = @VEXE\n\nconst known_skip_patterns_env = os.getenv('VKNOWN_SKIP_PATTERNS')\n\nconst known_folder_patterns_that_are_not_module_ones = [\n\t'vlib/sync/bench',\n\t'/tests',\n\t'/testdata',\n\t'/preludes_js',\n\t'vlib/builtin/js', // TODO: fix compiler panic\n\t'vlib/fontstash', // used by `gg`\n\t'vlib/sokol/sfons', // used by `gg`, and by examples/sokol/fonts.v\n\t'vlib/sokol/sapp', // used by `gg`, and many examples/\n\t'vlib/sokol/gfx', // used by `gg`, `x.ttf`\n\t'vlib/sokol/sgl', // used by `gg`\n\t'vlib/toml', // toml is well tested, even if the top level folder does not have _test.v files, the ones below do\n\t'vlib/v/', // the compiler itself is well tested\n]\n\nfn main() {\n\tmut places := if os.args.len > 1 {\n\t\tos.args#[1..]\n\t} else {\n\t\teprintln('> check the current folder only by default ...')\n\t\t['.']\n\t}\n\tmut known_skip_patterns := known_folder_patterns_that_are_not_module_ones.clone()\n\tif known_skip_patterns_env != '' {\n\t\tknown_skip_patterns = known_skip_patterns_env.split(',').filter(it != '')\n\t}\n\tfor path in places {\n\t\teprintln('> Checking folder: `${path}` ...')\n\t\tmut found := 0\n\t\tfiles := os.walk_ext(path, '.v')\n\t\tmut v_files := map[string]int{}\n\t\tmut v_test_files := map[string]int{}\n\t\tfor f in files {\n\t\t\tfolder := os.to_slash(os.dir(f))\n\t\t\tif known_skip_patterns.any(f.contains(it)) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif f.ends_with('.v') {\n\t\t\t\tv_files[folder]++\n\t\t\t}\n\t\t\tif f.ends_with('_test.v') {\n\t\t\t\tv_test_files[folder]++\n\t\t\t}\n\t\t}\n\t\teprintln('> Found ${v_files.len:5} potential V module folders (containing .v files).')\n\t\tfor folder, n_v_files in v_files {\n\t\t\tn_test_v_files := v_test_files[folder]\n\t\t\tif n_v_files > 1 && n_test_v_files == 0 {\n\t\t\t\tprintln('> ${n_test_v_files:5} _test.v files, with ${n_v_files:5} .v files, in folder: ${folder}')\n\t\t\t\tcompilation := os.execute('${os.quoted_path(vexe)} -shared -W -Wfatal-errors -check ${os.quoted_path(folder)}')\n\t\t\t\tif compilation.exit_code != 0 {\n\t\t\t\t\teprintln('> ${folder} has parser/checker errors!')\n\t\t\t\t\teprintln(compilation.output)\n\t\t\t\t}\n\t\t\t\tfound++\n\t\t\t}\n\t\t}\n\t\teprintln('> Found ${found} module folders without _test.v files in `${path}` .')\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/show_ancient_deprecations.v",
    "content": "import os\nimport term\nimport time\n\nstruct Context {\nmut:\n\tcut_time     time.Time\n\tdeprecations int\n}\n\nfn (mut ctx Context) analyze_line(line string, position_file string, position_line int) {\n\tblame_for_time := os.execute('git blame -L${position_line} --porcelain -- ${position_file}')\n\tif blame_for_time.exit_code != 0 {\n\t\treturn\n\t}\n\tts := blame_for_time.output.all_after('committer-time').all_before('\\n').trim_space().int()\n\tt := time.unix(ts)\n\tif ctx.cut_time < t {\n\t\tprintln(term.colorize(term.gray, '>>> SKIPPING since t: ${t} > ${ctx.cut_time}, ${position_file}:${position_line}: ${line}'))\n\t\treturn\n\t}\n\tctx.deprecations++\n\tblame_for_context := os.execute('git blame -L${position_line},+5 -- ${position_file}')\n\tcontext := blame_for_context.output.trim_space().split_into_lines()\n\tprintln(term.colorize(term.red, '${position_file}:${position_line}: deprecation: ${ctx.deprecations}, timestamp: ${ts} - ${t}'))\n\tfor cline in context {\n\t\tprintln('    ${cline}')\n\t}\n}\n\nfn main() {\n\tif os.args.len < 2 {\n\t\teprintln('Usage: v run cmd/tools/show_ancient_deprecations.v [DAYS]')\n\t\texit(1)\n\t}\n\tcut_months := os.args[1].int()\n\tcut_time := time.now().add(-cut_months * 24 * time.hour)\n\tmut ctx := Context{\n\t\tcut_time: cut_time\n\t}\n\tprintln('> Deprecations that happened before ${cut_time}')\n\tall_v_files := os.walk_ext('.', '.v')\n\tfor v_file in all_v_files {\n\t\tif v_file == './vlib/v/fmt/tests/attrs_keep.vv' {\n\t\t\tprintln(term.colorize(term.gray, '>>> SKIPPING deprecations attrs formatting test file ${v_file}'))\n\t\t\tcontinue\n\t\t}\n\t\tif v_file.starts_with('./vlib/v/checker/tests') && v_file.contains('deprec') {\n\t\t\tprintln(term.colorize(term.gray, '>>> SKIPPING deprecations test file ${v_file}'))\n\t\t\tcontinue\n\t\t}\n\t\tfile_content := os.read_file(v_file)!\n\t\tif !file_content.contains('[deprecated') {\n\t\t\tcontinue\n\t\t}\n\t\tlines := file_content.split_into_lines()\n\t\tfor line_num := lines.len - 1; line_num > 0; line_num-- {\n\t\t\tline := lines[line_num].all_before('//')\n\t\t\tmut is_deprecation_line := false\n\t\t\tif line.contains('\\tif ') {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif line.contains('[deprecated:') {\n\t\t\t\tis_deprecation_line = true\n\t\t\t}\n\t\t\tif line.contains('[deprecated]') {\n\t\t\t\tis_deprecation_line = true\n\t\t\t}\n\t\t\tif !is_deprecation_line {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tctx.analyze_line(line, v_file, line_num + 1)\n\t\t}\n\t}\n\tprintln('> Summary: there were ${term.colorize(term.bright_yellow, ctx.deprecations.str())} deprecations found, done before ${term.colorize(term.magenta,\n\t\tcut_time.str())}.')\n\tif ctx.deprecations > 0 {\n\t\texit(1)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/test_if_v_test_system_works.v",
    "content": "module main\n\n// This program verifies that `v test` propagates errors\n// and that it exits with code 1, when at least 1 FAIL happen.\nimport os\nimport rand\nimport time\n\nconst vexe = os.quoted_path(get_vexe_path())\nconst vroot = os.dir(vexe)\nconst tdir = new_tdir()\n\nfn get_vexe_path() string {\n\tenv_vexe := os.getenv('VEXE')\n\tif env_vexe != '' {\n\t\treturn env_vexe\n\t}\n\tme := os.executable()\n\teprintln('me: ${me}')\n\tmut vexe_ := os.join_path(os.dir(os.dir(os.dir(me))), 'v')\n\tif os.user_os() == 'windows' {\n\t\tvexe_ += '.exe'\n\t}\n\treturn vexe_\n}\n\nfn new_tdir() string {\n\tdir := os.join_path(os.vtmp_dir(), rand.ulid())\n\tos.rmdir_all(dir) or {}\n\tos.mkdir_all(dir) or { panic(err) }\n\tat_exit(cleanup_tdir) or {}\n\treturn dir\n}\n\nfn cleanup_tdir() {\n\tprintln('... removing tdir: ${tdir}')\n\tos.rmdir_all(tdir) or { eprintln(err) }\n}\n\ntype MyResult = string\n\n@[noreturn]\nfn (result MyResult) fail(reason string) {\n\teprintln('> ${reason}, but it does not. Result:\\n${result}')\n\texit(1)\n}\n\nfn (result MyResult) has(sub string) MyResult {\n\tif !result.contains(sub) {\n\t\tresult.fail(' result should have the substring `${sub}`')\n\t}\n\treturn result\n}\n\nfn (result MyResult) matches(gpattern string) MyResult {\n\tif !result.match_glob(gpattern) {\n\t\tresult.fail('result should match the glob pattern `${gpattern}`')\n\t}\n\treturn result\n}\n\nfn create_test(tname string, tcontent string) !string {\n\ttpath := os.join_path(tdir, tname)\n\tos.write_file(tpath, tcontent)!\n\teprintln('>>>>>>>> tpath: ${tpath} | tcontent: ${tcontent}')\n\treturn os.quoted_path(tpath)\n}\n\nfn check_assert_continues_works() ! {\n\tos.chdir(tdir)!\n\tcreate_test('assert_continues_option_works_test.v', 'fn test_fail1() { assert 2==4\\nassert 2==1\\nassert 2==0 }\\nfn test_ok(){ assert true }\\nfn test_fail2() { assert false }')!\n\tresult := check_fail('${vexe} -assert continues assert_continues_option_works_test.v')\n\tresult.has('assert_continues_option_works_test.v:1: fn test_fail1')\n\tresult.has('assert_continues_option_works_test.v:2: fn test_fail1')\n\tresult.has('assert_continues_option_works_test.v:3: fn test_fail1')\n\tresult.has('assert_continues_option_works_test.v:5: fn test_fail2')\n\tresult.has('> assert 2 == 4').has('> assert 2 == 1').has('> assert 2 == 0')\n\t// Check if a test function, tagged with [assert_continues], has the same behaviour, without needing additional options\n\tcreate_test('assert_continues_tag_works_test.v', '@[assert_continues]fn test_fail1() { assert 2==4\\nassert 2==1\\nassert 2==0 }\\nfn test_ok(){ assert true }\\nfn test_fail2() { assert false\\n assert false }')!\n\ttag_res := check_fail('${vexe} assert_continues_tag_works_test.v')\n\ttag_res.has('assert_continues_tag_works_test.v:1: fn test_fail1')\n\ttag_res.has('assert_continues_tag_works_test.v:2: fn test_fail1')\n\ttag_res.has('assert_continues_tag_works_test.v:3: fn test_fail1')\n\ttag_res.has('assert_continues_tag_works_test.v:5: fn test_fail2')\n\tif tag_res.contains('assert_continues_tag_works_test.v:6: fn test_fail2') {\n\t\texit(1)\n\t}\n}\n\nfn check_ok(cmd string) MyResult {\n\tprintln('>   check_ok cmd: ${cmd}')\n\tres := os.execute(cmd)\n\tif res.exit_code != 0 {\n\t\teprintln('>   check_ok failed.\\n${res.output}')\n\t\texit(1)\n\t}\n\treturn res.output\n}\n\nfn check_fail(cmd string) MyResult {\n\tprintln('> check_fail cmd: ${cmd}')\n\tres := os.execute(cmd)\n\tif res.exit_code == 0 {\n\t\teprintln('> check_fail succeeded, but it should have failed.\\n${res.output}')\n\t\texit(1)\n\t}\n\treturn res.output\n}\n\nfn main() {\n\tdefer {\n\t\tos.chdir(os.wd_at_startup) or {}\n\t}\n\tunbuffer_stdout()\n\tspawn fn () {\n\t\ttime.sleep(120 * time.second)\n\t\teprintln('>>> exiting due to an expired watchdog timer <<<')\n\t\texit(1)\n\t}()\n\tprintln('> vroot: ${vroot} | vexe: ${vexe} | tdir: ${tdir}')\n\tos.setenv('VTEST_HIDE_OK', '0', true)\n\tok_fpath := create_test('a_single_ok_test.v', 'fn test_ok(){ assert true }')!\n\tif check_ok('${vexe} ${ok_fpath}') != '' {\n\t\texit(1)\n\t}\n\tcheck_ok('${vexe} test ${ok_fpath}').matches('*OK*a_single_ok_test.v*')\n\tcheck_ok('${vexe} test \"${tdir}\"').matches('*OK*a_single_ok_test.v*')\n\tcheck_ok('${vexe} -stats test \"${tdir}\"').matches('*OK*a_single_ok_test.v*')\n\n\tfail_fpath := create_test('a_single_failing_test.v', 'fn test_fail(){ assert 1 == 2 }')!\n\tcheck_fail('${vexe} ${fail_fpath}').has('> assert 1 == 2').has('a_single_failing_test.v:1: fn test_fail')\n\tcheck_fail('${vexe} test ${fail_fpath}').has('> assert 1 == 2').has('a_single_failing_test.v:1: fn test_fail')\n\tcheck_fail('${vexe} test \"${tdir}\"').has('> assert 1 == 2')\n\tcheck_fail('${vexe} -stats test \"${tdir}\"').has('> assert 1 == 2')\n\trel_dir := os.join_path(tdir, rand.ulid())\n\tos.mkdir(rel_dir)!\n\tos.chdir(rel_dir)!\n\trelative_path := '..' + os.path_separator + 'a_single_ok_test.v'\n\tcheck_ok('${vexe} test ${os.quoted_path(relative_path)}').has('OK').has('a_single_ok_test.v')\n\n\tcheck_assert_continues_works()!\n\tprintln('> all done')\n}\n"
  },
  {
    "path": "cmd/tools/test_os_args.v",
    "content": "println(arguments()#[1..])\n"
  },
  {
    "path": "cmd/tools/test_os_process.v",
    "content": "module main\n\nimport os\nimport time\nimport os.cmdline\n\nenum Target {\n\tboth\n\tstderr\n\tstdout\n\talternate\n}\n\nfn s2target(s string) Target {\n\treturn match s {\n\t\t'both' { Target.both }\n\t\t'stderr' { Target.stderr }\n\t\t'alternate' { Target.alternate }\n\t\telse { Target.stdout }\n\t}\n}\n\nstruct Context {\nmut:\n\ttimeout_ms int\n\tperiod_ms  int\n\texitcode   int\n\ttarget     Target\n\tomode      Target\n\tis_verbose bool\n\tshow_wd    bool\n\tshow_env   bool\n}\n\nfn (mut ctx Context) println(s string) {\n\tif ctx.target == .alternate {\n\t\tctx.omode = if ctx.omode == .stderr { Target.stdout } else { Target.stderr }\n\t}\n\tif ctx.target in [.both, .stdout] || ctx.omode == .stdout {\n\t\tprintln('stdout, ${s}')\n\t}\n\tif ctx.target in [.both, .stderr] || ctx.omode == .stderr {\n\t\teprintln('stderr, ${s}')\n\t}\n}\n\nfn do_timeout(c &Context) {\n\tmut ctx := unsafe { c }\n\ttime.sleep(ctx.timeout_ms * time.millisecond)\n\texit(ctx.exitcode)\n}\n\nfn main() {\n\tunbuffer_stdout()\n\tmut ctx := Context{}\n\targs := os.args[1..]\n\tif '-h' in args || '--help' in args {\n\t\tprintln(\"Usage:\n\ttest_os_process [-v] [-h] [-target stderr/stdout/both/alternate] [-show_wd] [-show_env] [-exitcode 0] [-timeout_ms 200] [-period_ms 50]\n\t\tPrints lines periodically (-period_ms), to stdout/stderr (-target).\n\t\tAfter a while (-timeout_ms), exit with (-exitcode).\n\t\tThis program is useful for platform independent testing\n\t\tof child process/standard input/output control.\n\t\tIt is used in V's `os` module tests.\n\")\n\t\treturn\n\t}\n\tctx.is_verbose = '-v' in args\n\tctx.show_wd = '-show_wd' in args\n\tctx.show_env = '-show_env' in args\n\tctx.target = s2target(cmdline.option(args, '-target', 'both'))\n\tctx.exitcode = cmdline.option(args, '-exitcode', '0').int()\n\tctx.timeout_ms = cmdline.option(args, '-timeout_ms', '200').int()\n\tctx.period_ms = cmdline.option(args, '-period_ms', '50').int()\n\tif ctx.target == .alternate {\n\t\tctx.omode = .stdout\n\t}\n\tif ctx.is_verbose {\n\t\teprintln('> args: ${args} | context: ${ctx}')\n\t}\n\tif ctx.show_wd {\n\t\tctx.println('WORK_DIR=${os.getwd()}')\n\t}\n\tif ctx.show_env {\n\t\tall := os.environ()\n\t\tfor k, v in all {\n\t\t\tctx.println('${k}=${v}')\n\t\t}\n\t}\n\tspawn do_timeout(&ctx)\n\tctx.println('start')\n\tfor i := 1; true; i++ {\n\t\tctx.println('${i}')\n\t\ttime.sleep(ctx.period_ms * time.millisecond)\n\t}\n\tctx.println('done')\n\ttime.sleep(100 * time.second)\n}\n"
  },
  {
    "path": "cmd/tools/translate.v",
    "content": "// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.\n// Use of this source code is governed by an MIT license that can be found in the LICENSE file.\nmodule main\n\nimport os\nimport v.util\n\nconst vexe = os.getenv('VEXE')\n\nfn main() {\n\tvmodules := os.vmodules_dir()\n\tc2v_dir := os.join_path(vmodules, 'c2v')\n\tmut c2v_bin := os.join_path(c2v_dir, 'c2v')\n\t$if windows {\n\t\tc2v_bin += '.exe'\n\t}\n\t// Git clone c2v\n\tif !os.exists(c2v_dir) {\n\t\tos.mkdir_all(vmodules)!\n\t\tprintln('C2V is not installed. Cloning C2V to ${c2v_dir} ...')\n\t\tos.chdir(vmodules)!\n\t\tres := os.execute('${os.quoted_path(vexe)} retry -- git clone --filter=blob:none https://github.com/vlang/c2v')\n\t\tif res.exit_code != 0 {\n\t\t\teprintln('Failed to download C2V.')\n\t\t\texit(1)\n\t\t}\n\t}\n\t// Compile c2v\n\tif !os.exists(c2v_bin) {\n\t\tos.chdir(c2v_dir)!\n\t\tprintln('Compiling c2v ...')\n\t\tres2 := os.execute('${os.quoted_path(vexe)} -o ${os.quoted_path(c2v_bin)} -keepc -g -experimental .')\n\t\tif res2.exit_code != 0 {\n\t\t\teprintln(res2.output)\n\t\t\teprintln('Failed to compile C2V. This should not happen. Please report it via GitHub.')\n\t\t\texit(2)\n\t\t}\n\t}\n\tif os.args.len < 3 {\n\t\teprintln('Wrong number of arguments. Use `v translate file.c` .')\n\t\texit(3)\n\t}\n\tpassed_args := util.args_quote_paths(os.args[2..])\n\t// println(passed_args)\n\tos.chdir(os.wd_at_startup)!\n\tc2v_cmd := '${os.quoted_path(c2v_bin)} ${passed_args}'\n\tres := os.system(c2v_cmd)\n\tif res != 0 {\n\t\teprintln('C2V command: ${c2v_cmd}')\n\t\teprintln('C2V failed to translate the C files. Please report it via GitHub.')\n\t\texit(4)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vast/cjson.v",
    "content": "module main\n\nimport json.cjson\n\ntype Node = C.cJSON\n\nfn as_n(p &cjson.Node) &Node {\n\treturn unsafe { &Node(p) }\n}\n\nfn as_c(p &Node) &cjson.Node {\n\treturn unsafe { &cjson.Node(p) }\n}\n\n@[inline]\nfn create_object() &Node {\n\treturn as_n(cjson.create_object())\n}\n\n@[inline]\nfn create_array() &Node {\n\treturn as_n(cjson.create_array())\n}\n\n@[inline]\nfn create_string(val string) &Node {\n\treturn as_n(cjson.create_string(val))\n}\n\n@[inline]\nfn create_number(val f64) &Node {\n\treturn as_n(cjson.create_number(val))\n}\n\n@[inline]\nfn create_bool(val bool) &Node {\n\treturn as_n(cjson.create_bool(val))\n}\n\n@[inline]\nfn create_true() &Node {\n\treturn as_n(cjson.create_true())\n}\n\n@[inline]\nfn create_false() &Node {\n\treturn as_n(cjson.create_false())\n}\n\n@[inline]\nfn create_null() &Node {\n\treturn as_n(cjson.create_null())\n}\n\n@[inline]\nfn delete(b voidptr) {\n\tunsafe { cjson.delete(b) }\n}\n\n@[inline]\nfn add_item_to_object(mut obj Node, key string, item &Node) {\n\tmut o := unsafe { &cjson.Node(obj) }\n\to.add_item_to_object(key, item)\n}\n\n@[inline]\nfn add_item_to_array(mut obj Node, item &Node) {\n\tmut o := as_c(obj)\n\to.add_item_to_array(item)\n}\n\nfn json_print(mut obj Node) string {\n\tmut o := as_c(obj)\n\treturn o.print()\n}\n"
  },
  {
    "path": "cmd/tools/vast/test/.gitignore",
    "content": "demo.json\n"
  },
  {
    "path": "cmd/tools/vast/test/demo.v",
    "content": "// usage test: v ast path_to_v/cmd/tools/vast/test/demo.v\n// will generate demo.json\n\n// comment for module\nmodule main\n\n// import module\nimport os\nimport math\nimport time { Time, now }\n\n// const decl\nconst a = 1\nconst b = 3\nconst c = 'c'\n\n// struct decl\nstruct Point {\n\tx int\nmut:\n\ty int\npub:\n\tz int\npub mut:\n\tname string\n}\n\n// method of Point\npub fn (p Point) get_x() int {\n\treturn p.x\n}\n\n// embed struct\nstruct MyPoint {\n\tPoint\n\ttitle string\n}\n\n// enum type\nenum Color {\n\tred\n\tgreen\n\tblue\n}\n\n// type alias\ntype Myint = int\n\n// sum type\ntype MySumType = bool | int | string\n\n// function type\ntype Myfn = fn (int) int\n\n// interface type\ninterface Myinterfacer {\n\tadd(int, int) int\n\tsub(int, int) int\n}\n\n// main function\nfn main() {\n\tadd(1, 3)\n\tprintln(add(1, 2))\n\tprintln('ok') // comment println\n\tarr := [1, 3, 5, 7]\n\tfor a in arr {\n\t\tprintln(a)\n\t\tadd(1, 3)\n\t}\n\tcolor := Color.red\n\tprintln(color)\n\tprintln(os.args)\n\tm := math.max(1, 3)\n\tprintln(m)\n\tprintln(now())\n\tt := Time{}\n\tprintln(t)\n\tp := Point{\n\t\tx: 1\n\t\ty: 2\n\t\tz: 3\n\t}\n\tprintln(p)\n\tmy_point := MyPoint{\n\t\t// x: 1\n\t\t// y: 3\n\t\t// z: 5\n\t}\n\tprintln(my_point.get_x())\n}\n\n// normal function\nfn add(x int, y int) int {\n\treturn x + y\n}\n\n// function with defer stmt\nfn defer_fn() {\n\tmut x := 1\n\tprintln('start fn')\n\tdefer {\n\t\tprintln('in defer block')\n\t\tprintln(x)\n\t}\n\tprintln('end fn')\n}\n\n// generic function\nfn g_fn[T](p T) T {\n\treturn p\n}\n\n// generic struct\nstruct GenericStruct[T] {\n\tpoint Point\nmut:\n\tmodel T\n}\n\n// generic interface\ninterface Gettable[T] {\n\tget() T\n}\n\n// generic sumtype\nstruct None {}\n\ntype MyOption[T] = Error | None | T\n"
  },
  {
    "path": "cmd/tools/vast/vast.v",
    "content": "module main\n\nimport os\nimport time\nimport flag\nimport v.token\nimport v.parser\nimport v.ast\nimport v.pref\nimport v.errors\nimport v.checker\nimport strings\n\nstruct Context {\nmut:\n\tis_watch         bool\n\tis_compile       bool\n\tis_print         bool\n\tis_terse         bool\n\tis_skip_defaults bool\n\tcheck            bool\n\thide_names       map[string]bool\n}\n\nconst context = &Context{}\n\nfn main() {\n\tif os.args.len < 2 {\n\t\teprintln('not enough parameters')\n\t\texit(1)\n\t}\n\tmut ctx := unsafe { context }\n\tmut fp := flag.new_flag_parser(os.args[2..])\n\tfp.application('v ast')\n\tfp.usage_example('demo.v       generate demo.json file.')\n\tfp.usage_example('-w demo.v    generate demo.json file, and watch for changes.')\n\tfp.usage_example('-c demo.v    generate demo.json *and* a demo.c file, and watch for changes.')\n\tfp.usage_example('-p demo.v    print the json output to stdout.')\n\tfp.usage_example('-s demo.v    do NOT show the properties having default values, like false for bools, 0 for ints etc.')\n\tfp.description('Dump a JSON representation of the V AST for a given .v or .vsh file.')\n\tfp.description('By default, `v ast` will save the JSON to a .json file, named after the .v file.')\n\tfp.description('Pass -p to see it instead.')\n\tctx.is_watch = fp.bool('watch', `w`, false, 'watch a .v file for changes, rewrite the .json file, when a change is detected')\n\tctx.is_print = fp.bool('print', `p`, false, 'print the AST to stdout')\n\tctx.is_compile = fp.bool('compile', `c`, false, 'watch the .v file for changes, rewrite the .json file, *AND* generate a .c file too on any change')\n\tctx.is_terse = fp.bool('terse', `t`, false, 'terse output, only with tree node names (AST structure), no details')\n\tctx.is_skip_defaults = fp.bool('skip-defaults', `s`, false, 'skip properties that have default values like false, 0, \"\", etc')\n\tctx.check = fp.bool('check', `k`, false, 'run v.checker as well (it may modify the AST)')\n\thfields := fp.string_multi('hide', 0, 'hide the specified fields. You can give several, by separating them with `,`').join(',')\n\tfor hf in hfields.split(',') {\n\t\tctx.hide_names[hf] = true\n\t}\n\tfp.limit_free_args_to_at_least(1)!\n\trest_of_args := fp.remaining_parameters()\n\tfor vfile in rest_of_args {\n\t\tfile := get_abs_path(vfile)\n\t\tcheck_file(file)\n\t\tctx.write_file_or_print(file)\n\t\tif ctx.is_watch || ctx.is_compile {\n\t\t\tctx.watch_for_changes(file)\n\t\t}\n\t}\n}\n\nfn (ctx Context) skip_empty(child &Node) bool {\n\tif ctx.is_skip_defaults {\n\t\tif child == unsafe { 0 } {\n\t\t\treturn true\n\t\t}\n\t\tif child.type == .t_false {\n\t\t\treturn true\n\t\t}\n\t\tif child.type == .t_null {\n\t\t\treturn true\n\t\t}\n\t\tif child.type == .t_number && child.valuedouble == 0.0 {\n\t\t\treturn true\n\t\t}\n\t\tif child.type == .t_string {\n\t\t\tslen := unsafe { vstrlen_char(child.valuestring) }\n\t\t\tif slen == 0 {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tif slen > 7 {\n\t\t\t\ts := unsafe { child.valuestring.vstring_with_len(slen) }\n\t\t\t\tif s.starts_with('enum:0(') {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif child.type == .t_array && child.child == unsafe { 0 } {\n\t\t\treturn true\n\t\t}\n\t\tif child.type == .t_object && child.child == unsafe { 0 } {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfn (ctx Context) write_file_or_print(file string) {\n\tif ctx.is_print {\n\t\tprintln(json(file))\n\t} else {\n\t\tprintln('${time.now()}: AST written to: ' + json_file(file))\n\t}\n}\n\n// generate ast json file and c source code file\nfn (ctx Context) watch_for_changes(file string) {\n\tprintln('start watching...')\n\tmut timestamp := i64(0)\n\tfor {\n\t\tnew_timestamp := os.file_last_mod_unix(file)\n\t\tif timestamp != new_timestamp {\n\t\t\tctx.write_file_or_print(file)\n\t\t\tif ctx.is_compile {\n\t\t\t\tfile_name := file[0..(file.len - os.file_ext(file).len)]\n\t\t\t\tos.system('v -o ${file_name}.c ${file}')\n\t\t\t}\n\t\t}\n\t\ttimestamp = new_timestamp\n\t\ttime.sleep(500 * time.millisecond)\n\t}\n}\n\n// get absolute path for file\nfn get_abs_path(path string) string {\n\tif os.is_abs_path(path) {\n\t\treturn path\n\t} else if path.starts_with('./') {\n\t\treturn os.join_path(os.getwd(), path[2..])\n\t} else {\n\t\treturn os.join_path(os.getwd(), path)\n\t}\n}\n\n// check file is v file and exists\nfn check_file(file string) {\n\tif os.file_ext(file) !in ['.v', '.vv', '.vsh'] {\n\t\teprintln('the file `${file}` must be a v file or vsh file')\n\t\texit(1)\n\t}\n\tif !os.exists(file) {\n\t\teprintln('the v file `${file}` does not exist')\n\t\texit(1)\n\t}\n}\n\n// generate json file with the same file name\nfn json_file(file string) string {\n\tast_json := json(file)\n\t// support .v and .vsh file\n\tfile_name := file[0..(file.len - os.file_ext(file).len)]\n\tjson_file := file_name + '.json'\n\tos.write_file(json_file, ast_json) or { panic(err) }\n\treturn json_file\n}\n\n// generate json string\nfn json(file string) string {\n\t// use as permissive preferences as possible, so that `v ast`\n\t// can print the AST of arbitrary V files, even .vsh or ones\n\t// that require globals:\n\tmut pref_ := &pref.Preferences{}\n\tpref_.fill_with_defaults()\n\tpref_.enable_globals = true\n\tpref_.is_fmt = true\n\n\tmut t := Tree{\n\t\troot:  create_object()\n\t\ttable: ast.new_table()\n\t\tpref:  pref_\n\t}\n\t// parse file with comment\n\tmut ast_file := parser.parse_file(file, mut t.table, .parse_comments, t.pref)\n\n\tif context.check {\n\t\tmut the_checker := checker.new_checker(t.table, pref_)\n\t\tthe_checker.check(mut ast_file)\n\t}\n\tt.root = t.ast_file(ast_file)\n\t// generate the ast string\n\ts := json_print(mut t.root)\n\treturn s\n}\n\n// the ast tree\nstruct Tree {\n\tpref &pref.Preferences = unsafe { nil }\nmut:\n\ttable &ast.Table = unsafe { nil }\n\troot  Node // the root of tree\n}\n\n// add item to object node\n@[inline]\nfn (mut node Node) add(key string, child &Node) {\n\tif context.hide_names.len > 0 && key in context.hide_names {\n\t\treturn\n\t}\n\tif context.is_terse {\n\t\treturn\n\t}\n\tif context.skip_empty(child) {\n\t\treturn\n\t}\n\tadd_item_to_object(mut node, key, child)\n}\n\n// add item to object node\n@[inline]\nfn (mut node Node) add_terse(key string, child &Node) {\n\tif context.hide_names.len > 0 && key in context.hide_names {\n\t\treturn\n\t}\n\tif context.skip_empty(child) {\n\t\treturn\n\t}\n\tadd_item_to_object(mut node, key, child)\n}\n\n// add item to array node\n@[inline]\nfn (mut node Node) add_item(child &Node) {\n\tif context.skip_empty(child) {\n\t\treturn\n\t}\n\tadd_item_to_array(mut node, child)\n}\n\n// string type node\nfn (t Tree) string_node(val string) &Node {\n\treturn create_string(val)\n}\n\n// number type node\nfn (t Tree) number_node(val int) &Node {\n\treturn create_number(val)\n}\n\n// bool type node\nfn (t Tree) bool_node(val bool) &Node {\n\tif val {\n\t\treturn create_true()\n\t} else {\n\t\treturn create_false()\n\t}\n}\n\n// null type node\nfn (t Tree) null_node() &Node {\n\treturn create_null()\n}\n\n// type node\nfn (t Tree) type_node(typ ast.Type) &Node {\n\tif typ == 0 {\n\t\treturn create_null()\n\t} else {\n\t\ttype_name := t.table.get_type_name(typ)\n\t\treturn create_string(strings.repeat(`&`, typ.nr_muls()) + type_name)\n\t}\n}\n\n// token type node\nfn (t Tree) token_node(tok_kind token.Kind) &Node {\n\treturn t.string_node('token:${int(tok_kind)}(${tok_kind.str()})')\n}\n\n// enum type node\nfn (t Tree) enum_node[T](value T) &Node {\n\treturn t.string_node('enum:${int(value)}(${value})')\n}\n\n// for [][]comment\nfn (t Tree) two_dimension_comment(node [][]ast.Comment) &Node {\n\tmut comments := create_array()\n\tfor n in node {\n\t\tmut comment_array := create_array()\n\t\tfor c in n {\n\t\t\tcomment_array.add_item(t.comment(c))\n\t\t}\n\t\tcomments.add_item(comment_array)\n\t}\n\treturn comments\n}\n\n// ast file root node\nfn (t Tree) ast_file(node ast.File) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ast.File'))\n\tobj.add_terse('path', t.string_node(node.path))\n\tobj.add('path_base', t.string_node(node.path_base))\n\tobj.add_terse('nr_lines', t.number_node(node.nr_lines))\n\tobj.add_terse('nr_bytes', t.number_node(node.nr_bytes))\n\tobj.add_terse('mod', t.mod(node.mod))\n\tobj.add_terse('imports', t.imports(node.imports))\n\tobj.add('global_scope', t.scope(node.global_scope))\n\tobj.add('scope', t.scope(node.scope))\n\tobj.add('errors', t.errors(node.errors))\n\tobj.add('warnings', t.warnings(node.warnings))\n\tobj.add('notices', t.notices(node.notices))\n\tobj.add_terse('auto_imports', t.array_node_string(node.auto_imports))\n\tmut symbol_obj := create_object()\n\tfor key, val in node.imported_symbols {\n\t\tsymbol_obj.add_terse(key, t.string_node(val))\n\t}\n\tobj.add_terse('imported_symbols', symbol_obj)\n\tobj.add_terse('generic_fns', t.array_node_generic_fns(node.generic_fns))\n\tobj.add_terse('embedded_files', t.array_node_embed_file(node.embedded_files))\n\tobj.add_terse('global_labels', t.array_node_string(node.global_labels))\n\tobj.add_terse('is_test', t.bool_node(node.is_test))\n\tobj.add_terse('stmts', t.stmts(node.stmts))\n\treturn obj\n}\n\n// embed files\nfn (t Tree) embed_file(node ast.EmbeddedFile) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('EmbeddedFile'))\n\tobj.add_terse('rpath', t.string_node(node.rpath))\n\tobj.add('apath', t.string_node(node.apath))\n\tobj.add('compression_type', t.string_node(node.compression_type))\n\tobj.add('is_compressed', t.bool_node(node.is_compressed))\n\tobj.add('len', t.number_node(node.len))\n\tobj.add('bytes', t.array_node_u8(node.bytes))\n\treturn obj\n}\n\n// ast module node\nfn (t Tree) mod(node ast.Module) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('Module'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add('short_name', t.string_node(node.short_name))\n\tobj.add_terse('attrs', t.array_node_attr(node.attrs))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('name_pos', t.pos(node.name_pos))\n\tobj.add_terse('is_skipped', t.bool_node(node.is_skipped))\n\treturn obj\n}\n\nfn (t Tree) scope(scope &ast.Scope) &Node {\n\tmut obj := create_object()\n\tif unsafe { scope == nil } {\n\t\treturn obj\n\t}\n\tobj.add_terse('ast_type', t.string_node('Scope'))\n\tobj.add_terse('parent', t.string_node(ptr_str(scope.parent)))\n\tmut children_arr := create_array()\n\tfor s in scope.children {\n\t\tmut children_obj := create_object()\n\t\tchildren_obj.add_terse('parent', t.string_node(ptr_str(s.parent)))\n\t\tchildren_obj.add('start_pos', t.number_node(s.start_pos))\n\t\tchildren_obj.add('end_pos', t.number_node(s.end_pos))\n\t\tchildren_arr.add_item(children_obj)\n\t}\n\tobj.add_terse('children', children_arr)\n\tobj.add('start_pos', t.number_node(scope.start_pos))\n\tobj.add('end_pos', t.number_node(scope.end_pos))\n\tobj.add_terse('objects', t.objects(scope.objects))\n\tobj.add_terse('struct_fields', t.array_node_scope_struct_field(scope.struct_fields))\n\treturn obj\n}\n\nfn (t Tree) scope_struct_field(node ast.ScopeStructField) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ScopeStructField'))\n\tobj.add_terse('struct_type', t.type_node(node.struct_type))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('orig_type', t.type_node(node.orig_type))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add_terse('smartcasts', t.array_node_type(node.smartcasts))\n\treturn obj\n}\n\nfn (t Tree) objects(so map[string]ast.ScopeObject) &Node {\n\tmut obj := create_object()\n\tfor key, val in so {\n\t\tobj.add_terse(key, t.scope_object(val))\n\t}\n\treturn obj\n}\n\nfn (t Tree) scope_object(node ast.ScopeObject) &Node {\n\tobj := match node {\n\t\tast.EmptyScopeObject { create_object() }\n\t\tast.ConstField { t.const_field(node) }\n\t\tast.GlobalField { t.global_field(node) }\n\t\tast.Var { t.var(node) }\n\t\tast.AsmRegister { t.asm_register(node) }\n\t}\n\treturn obj\n}\n\nfn (t Tree) imports(nodes []ast.Import) &Node {\n\tmut import_array := create_array()\n\tfor node in nodes {\n\t\timport_array.add_item(t.import_module(node))\n\t}\n\treturn import_array\n}\n\nfn (t Tree) errors(errors_ []errors.Error) &Node {\n\tmut errs := create_array()\n\tfor e in errors_ {\n\t\tmut obj := create_object()\n\t\tobj.add_terse('message', t.string_node(e.message))\n\t\tobj.add_terse('file_path', t.string_node(e.file_path))\n\t\tobj.add('pos', t.pos(e.pos))\n\t\tobj.add('reporter', t.enum_node(e.reporter))\n\t\terrs.add_item(obj)\n\t}\n\treturn errs\n}\n\nfn (t Tree) warnings(warnings []errors.Warning) &Node {\n\tmut warns := create_array()\n\tfor w in warnings {\n\t\tmut obj := create_object()\n\t\tobj.add_terse('message', t.string_node(w.message))\n\t\tobj.add_terse('file_path', t.string_node(w.file_path))\n\t\tobj.add('pos', t.pos(w.pos))\n\t\tobj.add('reporter', t.enum_node(w.reporter))\n\t\twarns.add_item(obj)\n\t}\n\treturn warns\n}\n\nfn (t Tree) notices(notices []errors.Notice) &Node {\n\tmut notice_array := create_array()\n\tfor n in notices {\n\t\tmut obj := create_object()\n\t\tobj.add_terse('message', t.string_node(n.message))\n\t\tobj.add_terse('file_path', t.string_node(n.file_path))\n\t\tobj.add('pos', t.pos(n.pos))\n\t\tobj.add('reporter', t.enum_node(n.reporter))\n\t\tnotice_array.add_item(obj)\n\t}\n\treturn notice_array\n}\n\n// stmt array node\nfn (t Tree) stmts(stmts []ast.Stmt) &Node {\n\tmut stmt_array := create_array()\n\tfor s in stmts {\n\t\tstmt_array.add_item(t.stmt(s))\n\t}\n\treturn stmt_array\n}\n\nfn (t Tree) stmt(node ast.Stmt) &Node {\n\tmatch node {\n\t\tast.Module { return t.mod(node) }\n\t\tast.Import { return t.import_module(node) }\n\t\tast.ConstDecl { return t.const_decl(node) }\n\t\tast.FnDecl { return t.fn_decl(node) }\n\t\tast.StructDecl { return t.struct_decl(node) }\n\t\tast.EnumDecl { return t.enum_decl(node) }\n\t\tast.InterfaceDecl { return t.interface_decl(node) }\n\t\tast.HashStmt { return t.hash_stmt(node) }\n\t\tast.ComptimeFor { return t.comptime_for(node) }\n\t\tast.GlobalDecl { return t.global_decl(node) }\n\t\tast.DeferStmt { return t.defer_stmt(node) }\n\t\tast.TypeDecl { return t.type_decl(node) }\n\t\tast.GotoLabel { return t.goto_label(node) }\n\t\tast.GotoStmt { return t.goto_stmt(node) }\n\t\tast.AssignStmt { return t.assign_stmt(node) }\n\t\tast.Return { return t.return_(node) }\n\t\tast.ForCStmt { return t.for_c_stmt(node) }\n\t\tast.ForStmt { return t.for_stmt(node) }\n\t\tast.ForInStmt { return t.for_in_stmt(node) }\n\t\tast.BranchStmt { return t.branch_stmt(node) }\n\t\tast.AssertStmt { return t.assert_stmt(node) }\n\t\tast.ExprStmt { return t.expr_stmt(node) }\n\t\tast.Block { return t.block(node) }\n\t\tast.SemicolonStmt { return t.semicolon_stmt(node) }\n\t\tast.SqlStmt { return t.sql_stmt(node) }\n\t\tast.AsmStmt { return t.asm_stmt(node) }\n\t\tast.NodeError { return t.node_error(node) }\n\t\tast.EmptyStmt { return t.empty_stmt(node) }\n\t\tast.DebuggerStmt { return t.debugger_stmt(node) }\n\t}\n\treturn t.null_node()\n}\n\nfn (t Tree) import_module(node ast.Import) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('Import'))\n\tobj.add_terse('source_name', t.string_node(node.source_name))\n\tobj.add_terse('mod', t.string_node(node.mod))\n\tobj.add_terse('alias', t.string_node(node.alias))\n\tobj.add_terse('syms', t.array_node_import_symbol(node.syms))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\tobj.add('next_comments', t.array_node_comment(node.next_comments))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('mod_pos', t.pos(node.mod_pos))\n\tobj.add('alias_pos', t.pos(node.alias_pos))\n\tobj.add('syms_pos', t.pos(node.syms_pos))\n\treturn obj\n}\n\nfn (t Tree) import_symbol(node ast.ImportSymbol) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) pos(p token.Pos) &Node {\n\tmut obj := create_object()\n\tobj.add('line_nr', t.number_node(p.line_nr))\n\tobj.add('last_line', t.number_node(p.last_line))\n\tobj.add('pos', t.number_node(p.pos))\n\tobj.add('len', t.number_node(p.len))\n\treturn obj\n}\n\nfn (t Tree) comment(node ast.Comment) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('Comment'))\n\tobj.add('text', t.string_node(node.text))\n\tobj.add('is_multi', t.bool_node(node.is_multi))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) const_decl(node ast.ConstDecl) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ConstDecl'))\n\tobj.add_terse('is_pub', t.bool_node(node.is_pub))\n\tobj.add_terse('is_block', t.bool_node(node.is_block))\n\tobj.add_terse('fields', t.array_node_const_field(node.fields))\n\tobj.add_terse('attrs', t.array_node_attr(node.attrs))\n\tobj.add('end_comments', t.array_node_comment(node.end_comments))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) lambda_expr(node ast.LambdaExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('LambdaExpr'))\n\tobj.add_terse('params', t.array_node_ident(node.params))\n\tobj.add_terse('pos_expr', t.pos(node.pos_expr))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add_terse('pos_end', t.pos(node.pos_end))\n\tobj.add('scope', t.number_node(int(node.scope)))\n\tobj.add('func', t.number_node(int(node.func)))\n\tobj.add_terse('is_checked', t.bool_node(node.is_checked))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\treturn obj\n}\n\nfn (t Tree) const_field(node ast.ConstField) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ConstField'))\n\tobj.add_terse('mod', t.string_node(node.mod))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add_terse('is_pub', t.bool_node(node.is_pub))\n\tobj.add_terse('is_markused', t.bool_node(node.is_markused))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\tobj.add('comptime_expr_value', t.comptime_expr_value(node.comptime_expr_value))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) comptime_expr_value(node ast.ComptTimeConstValue) &Node {\n\tmatch node {\n\t\tast.EmptyExpr {\n\t\t\treturn t.empty_expr(node)\n\t\t}\n\t\tstring {\n\t\t\treturn t.string_node(node)\n\t\t}\n\t\telse {\n\t\t\treturn t.string_node(node.str())\n\t\t}\n\t}\n}\n\n// function declaration\nfn (t Tree) fn_decl(node ast.FnDecl) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('FnDecl'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('short_name', t.string_node(node.short_name))\n\tobj.add_terse('mod', t.string_node(node.mod))\n\tobj.add_terse('kind', t.enum_node(node.kind))\n\tobj.add_terse('is_deprecated', t.bool_node(node.is_deprecated))\n\tobj.add_terse('is_pub', t.bool_node(node.is_pub))\n\tobj.add_terse('is_c_variadic', t.bool_node(node.is_c_variadic))\n\tobj.add_terse('is_c_extern', t.bool_node(node.is_c_extern))\n\tobj.add_terse('is_variadic', t.bool_node(node.is_variadic))\n\tobj.add('is_anon', t.bool_node(node.is_anon))\n\tobj.add_terse('is_noreturn', t.bool_node(node.is_noreturn))\n\tobj.add_terse('is_weak', t.bool_node(node.is_weak))\n\tobj.add_terse('is_manualfree', t.bool_node(node.is_manualfree))\n\tobj.add('is_main', t.bool_node(node.is_main))\n\tobj.add('is_test', t.bool_node(node.is_test))\n\tobj.add('is_conditional', t.bool_node(node.is_conditional))\n\tobj.add_terse('is_exported', t.bool_node(node.is_exported))\n\tobj.add('is_keep_alive', t.bool_node(node.is_keep_alive))\n\tobj.add_terse('is_unsafe', t.bool_node(node.is_unsafe))\n\tobj.add_terse('is_markused', t.bool_node(node.is_markused))\n\tobj.add_terse('is_file_translated', t.bool_node(node.is_file_translated))\n\tobj.add_terse('is_closure', t.bool_node(node.is_closure))\n\tobj.add_terse('receiver', t.struct_field(node.receiver))\n\tobj.add('receiver_pos', t.pos(node.receiver_pos))\n\tobj.add_terse('is_method', t.bool_node(node.is_method))\n\tobj.add_terse('is_static_type_method', t.bool_node(node.is_static_type_method))\n\tobj.add('method_type_pos', t.pos(node.method_type_pos))\n\tobj.add('method_idx', t.number_node(node.method_idx))\n\tobj.add_terse('rec_mut', t.bool_node(node.rec_mut))\n\tobj.add_terse('has_prev_newline', t.bool_node(node.has_prev_newline))\n\tobj.add_terse('has_break_line', t.bool_node(node.has_break_line))\n\tobj.add('rec_share', t.enum_node(node.rec_share))\n\tobj.add_terse('language', t.enum_node(node.language))\n\tobj.add('file_mode', t.enum_node(node.file_mode))\n\tobj.add('no_body', t.bool_node(node.no_body))\n\tobj.add('is_builtin', t.bool_node(node.is_builtin))\n\tobj.add('file', t.string_node(node.file))\n\tobj.add('is_direct_arr', t.bool_node(node.is_direct_arr))\n\tobj.add('ctdefine_idx', t.number_node(node.ctdefine_idx))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('end_pos', t.pos(node.end_pos))\n\tobj.add('body_pos', t.pos(node.body_pos))\n\tobj.add('return_type_pos', t.pos(node.return_type_pos))\n\tobj.add('file', t.string_node(node.file))\n\tobj.add('has_return', t.bool_node(node.has_return))\n\tobj.add('should_be_skipped', t.bool_node(node.should_be_skipped))\n\tobj.add('ninstances', t.number_node(node.ninstances))\n\tobj.add_terse('has_await', t.bool_node(node.has_await))\n\tobj.add_terse('return_type', t.type_node(node.return_type))\n\tobj.add('source_file', t.number_node(int(node.source_file)))\n\tobj.add('scope', t.number_node(int(node.scope)))\n\tobj.add_terse('attrs', t.array_node_attr(node.attrs))\n\tobj.add_terse('params', t.array_node_arg(node.params))\n\tobj.add_terse('generic_names', t.array_node_string(node.generic_names))\n\tobj.add_terse('stmts', t.array_node_stmt(node.stmts))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\tobj.add('next_comments', t.array_node_comment(node.next_comments))\n\tobj.add('label_names', t.array_node_string(node.label_names))\n\tobj.add('defer_stmts', t.array_node_defer_stmt(node.defer_stmts))\n\treturn obj\n}\n\nfn (t Tree) anon_fn(node ast.AnonFn) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('AnonFn'))\n\tobj.add_terse('decl', t.fn_decl(node.decl))\n\tobj.add('inherited_vars', t.array_node_arg(node.inherited_vars))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add('has_ct_var', t.bool_node(node.has_ct_var))\n\tmut symbol_obj := create_object()\n\tfor key, val in node.has_gen {\n\t\tsymbol_obj.add_terse(key.str(), t.bool_node(val))\n\t}\n\tobj.add_terse('has_gen', symbol_obj)\n\treturn obj\n}\n\nfn (t Tree) struct_decl(node ast.StructDecl) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('StructDecl'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('is_pub', t.bool_node(node.is_pub))\n\tobj.add('pub_pos', t.number_node(node.pub_pos))\n\tobj.add('mut_pos', t.number_node(node.mut_pos))\n\tobj.add('pub_mut_pos', t.number_node(node.pub_mut_pos))\n\tobj.add('global_pos', t.number_node(node.global_pos))\n\tobj.add('module_pos', t.number_node(node.module_pos))\n\tobj.add_terse('language', t.enum_node(node.language))\n\tobj.add_terse('is_union', t.bool_node(node.is_union))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add_terse('fields', t.array_node_struct_field(node.fields))\n\tobj.add_terse('generic_types', t.array_node_type(node.generic_types))\n\tobj.add_terse('attrs', t.array_node_attr(node.attrs))\n\tobj.add('end_comments', t.array_node_comment(node.end_comments))\n\tobj.add_terse('embeds', t.array_node_embed(node.embeds))\n\tobj.add('is_implements', t.bool_node(node.is_implements))\n\tobj.add_terse('implements_types', t.array_node_type_expr(node.implements_types))\n\treturn obj\n}\n\nfn (t Tree) struct_field(node ast.StructField) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('StructField'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('anon_struct_decl', t.struct_decl(node.anon_struct_decl))\n\tobj.add_terse('unaliased_typ', t.type_node(node.unaliased_typ))\n\tobj.add('type_pos', t.pos(node.type_pos))\n\tobj.add('option_pos', t.pos(node.option_pos))\n\tobj.add_terse('has_default_expr', t.bool_node(node.has_default_expr))\n\tobj.add_terse('default_expr_typ', t.type_node(node.default_expr_typ))\n\tobj.add_terse('default_expr', t.expr(node.default_expr))\n\tobj.add_terse('is_pub', t.bool_node(node.is_pub))\n\tobj.add_terse('is_mut', t.bool_node(node.is_mut))\n\tobj.add_terse('is_global', t.bool_node(node.is_global))\n\tobj.add_terse('is_volatile', t.bool_node(node.is_volatile))\n\tobj.add_terse('is_deprecated', t.bool_node(node.is_deprecated))\n\tobj.add_terse('attrs', t.array_node_attr(node.attrs))\n\tobj.add('pre_comments', t.array_node_comment(node.pre_comments))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\tobj.add('next_comments', t.array_node_comment(node.next_comments))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add_terse('i', t.number_node(node.i))\n\treturn obj\n}\n\nfn (t Tree) embed(node ast.Embed) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\treturn obj\n}\n\nfn (t Tree) enum_decl(node ast.EnumDecl) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('EnumDecl'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('is_pub', t.bool_node(node.is_pub))\n\tobj.add_terse('is_flag', t.bool_node(node.is_flag))\n\tobj.add_terse('is_multi_allowed', t.bool_node(node.is_multi_allowed))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add_terse('fields', t.array_node_enum_field(node.fields))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\tobj.add_terse('attrs', t.array_node_attr(node.attrs))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('enum_typ', t.type_node(node.enum_typ))\n\treturn obj\n}\n\nfn (t Tree) enum_field(node ast.EnumField) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('EnumField'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('has_expr', t.bool_node(node.has_expr))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('pre_comments', t.array_node_comment(node.pre_comments))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\tobj.add('next_comments', t.array_node_comment(node.next_comments))\n\treturn obj\n}\n\nfn (t Tree) interface_decl(node ast.InterfaceDecl) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('InterfaceDecl'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('is_pub', t.bool_node(node.is_pub))\n\tobj.add('mut_pos', t.number_node(node.mut_pos))\n\tobj.add_terse('field_names', t.array_node_string(node.field_names))\n\tobj.add_terse('methods', t.array_node_fn_decl(node.methods))\n\tobj.add_terse('fields', t.array_node_struct_field(node.fields))\n\tobj.add('pre_comments', t.array_node_comment(node.pre_comments))\n\tobj.add('name_pos', t.pos(node.name_pos))\n\tobj.add_terse('language', t.enum_node(node.language))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('are_embeds_expanded', t.bool_node(node.are_embeds_expanded))\n\tobj.add_terse('embeds', t.array_node_interface_embedding(node.embeds))\n\tobj.add_terse('attrs', t.array_node_attr(node.attrs))\n\treturn obj\n}\n\nfn (t Tree) interface_embedding(node ast.InterfaceEmbedding) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('InterfaceEmbedding'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\treturn obj\n}\n\nfn (t Tree) attr(node ast.Attr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('Attr'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('has_arg', t.bool_node(node.has_arg))\n\tobj.add_terse('arg', t.string_node(node.arg))\n\tobj.add_terse('kind', t.enum_node(node.kind))\n\tobj.add_terse('ct_opt', t.bool_node(node.ct_opt))\n\tobj.add_terse('has_at', t.bool_node(node.has_at))\n\tobj.add_terse('ct_expr', t.expr(node.ct_expr))\n\tobj.add_terse('ct_evaled', t.bool_node(node.ct_evaled))\n\tobj.add_terse('ct_skip', t.bool_node(node.ct_skip))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) hash_stmt(node ast.HashStmt) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('HashStmt'))\n\tobj.add_terse('mod', t.string_node(node.mod))\n\tobj.add_terse('val', t.string_node(node.val))\n\tobj.add_terse('kind', t.string_node(node.kind))\n\tobj.add_terse('main', t.string_node(node.main))\n\tobj.add_terse('msg', t.string_node(node.msg))\n\tobj.add_terse('is_use_once', t.bool_node(node.is_use_once))\n\tobj.add_terse('ct_conds', t.array_node_expr(node.ct_conds))\n\tobj.add_terse('source_file', t.string_node(node.source_file))\n\tobj.add_terse('attrs', t.array_node_attr(node.attrs))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) comptime_for(node ast.ComptimeFor) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ComptimeFor'))\n\tobj.add_terse('val_var', t.string_node(node.val_var))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('kind', t.enum_node(node.kind))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('typ_pos', t.pos(node.pos))\n\tobj.add_terse('stmts', t.array_node_stmt(node.stmts))\n\treturn obj\n}\n\nfn (t Tree) global_decl(node ast.GlobalDecl) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('GlobalDecl'))\n\tobj.add_terse('mod', t.string_node(node.mod))\n\tobj.add_terse('attrs', t.array_node_attr(node.attrs))\n\tobj.add_terse('is_block', t.bool_node(node.is_block))\n\tobj.add_terse('fields', t.array_node_global_field(node.fields))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('end_comments', t.array_node_comment(node.end_comments))\n\treturn obj\n}\n\nfn (t Tree) global_field(node ast.GlobalField) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('GlobalField'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('has_expr', t.bool_node(node.has_expr))\n\tobj.add_terse('is_markused', t.bool_node(node.is_markused))\n\tobj.add_terse('is_weak', t.bool_node(node.is_weak))\n\tobj.add_terse('is_hidden', t.bool_node(node.is_hidden))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('typ_pos', t.pos(node.typ_pos))\n\treturn obj\n}\n\nfn (t Tree) defer_stmt(node ast.DeferStmt) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('DeferStmt'))\n\tobj.add_terse('stmts', t.array_node_stmt(node.stmts))\n\tobj.add_terse('defer_vars', t.array_node_ident(node.defer_vars))\n\tobj.add_terse('ifdef', t.string_node(node.ifdef))\n\tobj.add('idx_in_fn', t.number_node(node.idx_in_fn))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) type_decl(node ast.TypeDecl) &Node {\n\tmatch node {\n\t\tast.AliasTypeDecl { return t.alias_type_decl(node) }\n\t\tast.FnTypeDecl { return t.fn_type_decl(node) }\n\t\tast.SumTypeDecl { return t.sum_type_decl(node) }\n\t}\n}\n\nfn (t Tree) alias_type_decl(node ast.AliasTypeDecl) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('AliasTypeDecl'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('mod', t.string_node(node.mod))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('parent_type', t.type_node(node.parent_type))\n\tobj.add_terse('is_pub', t.bool_node(node.is_pub))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) sum_type_decl(node ast.SumTypeDecl) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('SumTypeDecl'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('mod', t.string_node(node.mod))\n\tobj.add_terse('is_pub', t.bool_node(node.is_pub))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('generic_types', t.array_node_type(node.generic_types))\n\tobj.add_terse('variants', t.array_node_type_expr(node.variants))\n\tobj.add('name_pos', t.pos(node.name_pos))\n\treturn obj\n}\n\nfn (t Tree) fn_type_decl(node ast.FnTypeDecl) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('FnTypeDecl'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('mod', t.string_node(node.mod))\n\tobj.add_terse('is_pub', t.bool_node(node.is_pub))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\treturn obj\n}\n\nfn (t Tree) arg(node ast.Param) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('Param'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('is_mut', t.bool_node(node.is_mut))\n\tobj.add_terse('is_shared', t.bool_node(node.is_shared))\n\tobj.add_terse('is_atomic', t.bool_node(node.is_atomic))\n\tobj.add_terse('on_newline', t.bool_node(node.on_newline))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('type_pos', t.pos(node.type_pos))\n\treturn obj\n}\n\nfn (t Tree) goto_label(node ast.GotoLabel) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('GotoLabel'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('is_used', t.bool_node(node.is_used))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) goto_stmt(node ast.GotoStmt) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('GotoStmt'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) assign_stmt(node ast.AssignStmt) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('AssignStmt'))\n\tobj.add_terse('op', t.token_node(node.op))\n\tobj.add_terse('left', t.array_node_expr(node.left))\n\tobj.add_terse('left_types', t.array_node_type(node.left_types))\n\tobj.add_terse('right', t.array_node_expr(node.right))\n\tobj.add_terse('right_types', t.array_node_type(node.left_types))\n\tobj.add_terse('is_static', t.bool_node(node.is_static))\n\tobj.add_terse('is_volatile', t.bool_node(node.is_volatile))\n\tobj.add_terse('is_simple', t.bool_node(node.is_simple))\n\tobj.add_terse('has_cross_var', t.bool_node(node.has_cross_var))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('end_comments', t.array_node_comment(node.end_comments))\n\treturn obj\n}\n\nfn (t Tree) var(node ast.Var) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('Var'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('orig_type', t.type_node(node.orig_type))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add_terse('is_arg', t.bool_node(node.is_arg))\n\tobj.add_terse('is_mut', t.bool_node(node.is_mut))\n\tobj.add_terse('is_static', t.bool_node(node.is_static))\n\tobj.add_terse('is_volatile', t.bool_node(node.is_volatile))\n\tobj.add('is_used', t.bool_node(node.is_used))\n\tobj.add('is_changed', t.bool_node(node.is_changed))\n\tobj.add_terse('ct_type_var', t.enum_node(node.ct_type_var))\n\tobj.add('is_or', t.bool_node(node.is_or))\n\tobj.add('is_tmp', t.bool_node(node.is_tmp))\n\tobj.add('is_autofree_tmp', t.bool_node(node.is_autofree_tmp))\n\tobj.add('is_auto_deref', t.bool_node(node.is_auto_deref))\n\tobj.add('is_inherited', t.bool_node(node.is_inherited))\n\tobj.add('has_inherited', t.bool_node(node.has_inherited))\n\tobj.add('is_auto_heap', t.bool_node(node.is_auto_heap))\n\tobj.add('is_stack_obj', t.bool_node(node.is_stack_obj))\n\tobj.add_terse('share', t.enum_node(node.share))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add_terse('smartcasts', t.array_node_type(node.smartcasts))\n\treturn obj\n}\n\nfn (t Tree) return_(node ast.Return) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('Return'))\n\tobj.add_terse('exprs', t.array_node_expr(node.exprs))\n\tobj.add_terse('types', t.array_node_type(node.types))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) for_c_stmt(node ast.ForCStmt) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ForCStmt'))\n\tobj.add_terse('has_init', t.bool_node(node.has_init))\n\tobj.add_terse('init', t.stmt(node.init))\n\tobj.add_terse('has_cond', t.bool_node(node.has_cond))\n\tobj.add_terse('cond', t.expr(node.cond))\n\tobj.add_terse('has_inc', t.bool_node(node.has_inc))\n\tobj.add_terse('inc', t.stmt(node.inc))\n\tobj.add_terse('is_multi', t.bool_node(node.is_multi))\n\tobj.add_terse('label', t.string_node(node.label))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\tobj.add('scope', t.number_node(int(node.scope)))\n\tobj.add_terse('stmts', t.array_node_stmt(node.stmts))\n\treturn obj\n}\n\nfn (t Tree) for_stmt(node ast.ForStmt) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ForStmt'))\n\tobj.add_terse('cond', t.expr(node.cond))\n\tobj.add_terse('is_inf', t.bool_node(node.is_inf))\n\tobj.add_terse('label', t.string_node(node.label))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\tobj.add('scope', t.number_node(int(node.scope)))\n\tobj.add_terse('stmts', t.array_node_stmt(node.stmts))\n\treturn obj\n}\n\nfn (t Tree) for_in_stmt(node ast.ForInStmt) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ForInStmt'))\n\tobj.add_terse('key_var', t.string_node(node.key_var))\n\tobj.add_terse('val_var', t.string_node(node.val_var))\n\tobj.add_terse('cond', t.expr(node.cond))\n\tobj.add_terse('is_range', t.bool_node(node.is_range))\n\tobj.add_terse('high', t.expr(node.high))\n\tobj.add_terse('key_type', t.type_node(node.key_type))\n\tobj.add_terse('val_type', t.type_node(node.val_type))\n\tobj.add_terse('cond_type', t.type_node(node.cond_type))\n\tobj.add_terse('kind', t.enum_node(node.kind))\n\tobj.add_terse('val_is_mut', t.bool_node(node.val_is_mut))\n\tobj.add_terse('val_is_ref', t.bool_node(node.val_is_ref))\n\tobj.add_terse('label', t.string_node(node.label))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\tobj.add('scope', t.number_node(int(node.scope)))\n\tobj.add_terse('stmts', t.array_node_stmt(node.stmts))\n\treturn obj\n}\n\nfn (t Tree) branch_stmt(node ast.BranchStmt) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('BranchStmt'))\n\tobj.add_terse('kind', t.token_node(node.kind))\n\tobj.add_terse('label', t.string_node(node.label))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) assert_stmt(node ast.AssertStmt) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('AssertStmt'))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add_terse('is_used', t.bool_node(node.is_used))\n\tif node.extra !is ast.EmptyExpr {\n\t\tobj.add_terse('extra', t.expr(node.extra))\n\t\tobj.add('extra_pos', t.pos(node.extra_pos))\n\t}\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) block(node ast.Block) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('Block'))\n\tobj.add_terse('stmts', t.array_node_stmt(node.stmts))\n\tobj.add_terse('is_unsafe', t.bool_node(node.is_unsafe))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) comptime_call(node ast.ComptimeCall) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ComptimeCall'))\n\tobj.add_terse('method_name', t.string_node(node.method_name))\n\tobj.add_terse('kind', t.enum_node(node.kind))\n\tobj.add_terse('left', t.expr(node.left))\n\tobj.add_terse('is_vweb', t.bool_node(node.is_vweb))\n\tobj.add_terse('is_veb', t.bool_node(node.is_veb))\n\tobj.add_terse('veb_tmpl', t.string_node(node.veb_tmpl.path))\n\tobj.add_terse('args_var', t.string_node(node.args_var))\n\tobj.add_terse('has_parens', t.bool_node(node.has_parens))\n\tobj.add_terse('embed_file', t.embed_file(node.embed_file))\n\tobj.add('method_pos', t.pos(node.method_pos))\n\tobj.add_terse('left_type', t.type_node(node.left_type))\n\tobj.add_terse('result_type', t.type_node(node.result_type))\n\tobj.add('scope', t.scope(node.scope))\n\tobj.add_terse('env_value', t.string_node(node.env_value))\n\tobj.add_terse('compile_value', t.string_node(node.compile_value))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add_terse('args', t.array_node_call_arg(node.args))\n\tobj.add_terse('or_block', t.or_expr(node.or_block))\n\treturn obj\n}\n\nfn (t Tree) comptime_selector(node ast.ComptimeSelector) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ComptimeSelector'))\n\tobj.add_terse('has_parens', t.bool_node(node.has_parens))\n\tobj.add_terse('left', t.expr(node.left))\n\tobj.add_terse('field_expr', t.expr(node.field_expr))\n\tobj.add_terse('left_type', t.type_node(node.left_type))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) expr_stmt(node ast.ExprStmt) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ExprStmt'))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('is_expr', t.bool_node(node.is_expr))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\treturn obj\n}\n\n// expr\nfn (t Tree) expr(expr ast.Expr) &Node {\n\tmatch expr {\n\t\tast.IntegerLiteral {\n\t\t\treturn t.integer_literal(expr)\n\t\t}\n\t\tast.FloatLiteral {\n\t\t\treturn t.float_literal(expr)\n\t\t}\n\t\tast.StringLiteral {\n\t\t\treturn t.string_literal(expr)\n\t\t}\n\t\tast.CharLiteral {\n\t\t\treturn t.char_literal(expr)\n\t\t}\n\t\tast.BoolLiteral {\n\t\t\treturn t.bool_literal(expr)\n\t\t}\n\t\tast.StringInterLiteral {\n\t\t\treturn t.string_inter_literal(expr)\n\t\t}\n\t\tast.EnumVal {\n\t\t\treturn t.enum_val(expr)\n\t\t}\n\t\tast.Assoc {\n\t\t\treturn t.assoc(expr)\n\t\t}\n\t\tast.AtExpr {\n\t\t\treturn t.at_expr(expr)\n\t\t}\n\t\tast.CastExpr {\n\t\t\treturn t.cast_expr(expr)\n\t\t}\n\t\tast.AsCast {\n\t\t\treturn t.as_cast(expr)\n\t\t}\n\t\tast.TypeNode {\n\t\t\treturn t.type_expr(expr)\n\t\t}\n\t\tast.SizeOf {\n\t\t\treturn t.size_of(expr)\n\t\t}\n\t\tast.IsRefType {\n\t\t\treturn t.is_ref_type(expr)\n\t\t}\n\t\tast.PrefixExpr {\n\t\t\treturn t.prefix_expr(expr)\n\t\t}\n\t\tast.InfixExpr {\n\t\t\treturn t.infix_expr(expr)\n\t\t}\n\t\tast.IndexExpr {\n\t\t\treturn t.index_expr(expr)\n\t\t}\n\t\tast.PostfixExpr {\n\t\t\treturn t.postfix_expr(expr)\n\t\t}\n\t\tast.SelectorExpr {\n\t\t\treturn t.selector_expr(expr)\n\t\t}\n\t\tast.RangeExpr {\n\t\t\treturn t.range_expr(expr)\n\t\t}\n\t\tast.IfExpr {\n\t\t\treturn t.if_expr(expr)\n\t\t}\n\t\tast.Ident {\n\t\t\treturn t.ident(expr)\n\t\t}\n\t\tast.CallExpr {\n\t\t\treturn t.call_expr(expr)\n\t\t}\n\t\tast.OrExpr {\n\t\t\treturn t.or_expr(expr)\n\t\t}\n\t\tast.StructInit {\n\t\t\treturn t.struct_init(expr)\n\t\t}\n\t\tast.ArrayInit {\n\t\t\treturn t.array_init(expr)\n\t\t}\n\t\tast.MapInit {\n\t\t\treturn t.map_init(expr)\n\t\t}\n\t\tast.None {\n\t\t\treturn t.none_expr(expr)\n\t\t}\n\t\tast.ParExpr {\n\t\t\treturn t.par_expr(expr)\n\t\t}\n\t\tast.IfGuardExpr {\n\t\t\treturn t.if_guard_expr(expr)\n\t\t}\n\t\tast.MatchExpr {\n\t\t\treturn t.match_expr(expr)\n\t\t}\n\t\tast.ConcatExpr {\n\t\t\treturn t.concat_expr(expr)\n\t\t}\n\t\tast.TypeOf {\n\t\t\treturn t.type_of(expr)\n\t\t}\n\t\tast.Likely {\n\t\t\treturn t.likely(expr)\n\t\t}\n\t\tast.SqlExpr {\n\t\t\treturn t.sql_expr(expr)\n\t\t}\n\t\tast.ComptimeCall {\n\t\t\treturn t.comptime_call(expr)\n\t\t}\n\t\tast.ComptimeSelector {\n\t\t\treturn t.comptime_selector(expr)\n\t\t}\n\t\tast.LockExpr {\n\t\t\treturn t.lock_expr(expr)\n\t\t}\n\t\tast.UnsafeExpr {\n\t\t\treturn t.unsafe_expr(expr)\n\t\t}\n\t\tast.ChanInit {\n\t\t\treturn t.chan_init(expr)\n\t\t}\n\t\tast.SelectExpr {\n\t\t\treturn t.select_expr(expr)\n\t\t}\n\t\tast.Comment {\n\t\t\treturn t.comment(expr)\n\t\t}\n\t\tast.AnonFn {\n\t\t\treturn t.anon_fn(expr)\n\t\t}\n\t\tast.ArrayDecompose {\n\t\t\treturn t.array_decompose(expr)\n\t\t}\n\t\tast.GoExpr {\n\t\t\treturn t.go_expr(expr)\n\t\t}\n\t\tast.SpawnExpr {\n\t\t\treturn t.spawn_expr(expr)\n\t\t}\n\t\tast.OffsetOf {\n\t\t\treturn t.offset_of(expr)\n\t\t}\n\t\tast.DumpExpr {\n\t\t\treturn t.dump_expr(expr)\n\t\t}\n\t\tast.LambdaExpr {\n\t\t\treturn t.lambda_expr(expr)\n\t\t}\n\t\tast.NodeError {\n\t\t\treturn t.node_error(expr)\n\t\t}\n\t\tast.EmptyExpr {\n\t\t\treturn t.empty_expr(expr)\n\t\t}\n\t\tast.Nil {\n\t\t\treturn t.nil_expr(expr)\n\t\t}\n\t\telse {\n\t\t\t// println('unknown expr')\n\t\t\treturn t.null_node()\n\t\t}\n\t}\n}\n\nfn (t Tree) integer_literal(node ast.IntegerLiteral) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('IntegerLiteral'))\n\tobj.add_terse('val', t.string_node(node.val))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) float_literal(node ast.FloatLiteral) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('FloatLiteral'))\n\tobj.add_terse('val', t.string_node(node.val))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) string_literal(node ast.StringLiteral) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('StringLiteral'))\n\tobj.add_terse('val', t.string_node(node.val))\n\tobj.add_terse('is_raw', t.bool_node(node.is_raw))\n\tobj.add_terse('language', t.enum_node(node.language))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) char_literal(node ast.CharLiteral) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('CharLiteral'))\n\tobj.add_terse('val', t.string_node(node.val))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) bool_literal(node ast.BoolLiteral) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('BoolLiteral'))\n\tobj.add_terse('val', t.bool_node(node.val))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) string_inter_literal(node ast.StringInterLiteral) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('StringInterLiteral'))\n\tobj.add_terse('vals', t.array_node_string(node.vals))\n\tobj.add_terse('exprs', t.array_node_expr(node.exprs))\n\tobj.add_terse('expr_types', t.array_node_type(node.expr_types))\n\tobj.add_terse('fwidths', t.array_node_int(node.fwidths))\n\tobj.add_terse('precisions', t.array_node_int(node.precisions))\n\tobj.add_terse('pluss', t.array_node_bool(node.pluss))\n\tobj.add_terse('fills', t.array_node_bool(node.fills))\n\tobj.add_terse('fmt_poss', t.array_node_position(node.fmt_poss))\n\tobj.add_terse('fmts', t.array_node_u8(node.fmts))\n\tobj.add_terse('need_fmts', t.array_node_bool(node.need_fmts))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) enum_val(node ast.EnumVal) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('EnumVal'))\n\tobj.add_terse('enum_name', t.string_node(node.enum_name))\n\tobj.add_terse('mod', t.string_node(node.mod))\n\tobj.add_terse('val', t.string_node(node.val))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) assoc(node ast.Assoc) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('Assoc'))\n\tobj.add_terse('var_name', t.string_node(node.var_name))\n\tobj.add_terse('fields', t.array_node_string(node.fields))\n\tobj.add_terse('exprs', t.array_node_expr(node.exprs))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('scope', t.number_node(int(node.scope)))\n\treturn obj\n}\n\nfn (t Tree) at_expr(node ast.AtExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('AtExpr'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add_terse('kind', t.enum_node(node.kind))\n\tobj.add_terse('val', t.string_node(node.val))\n\treturn obj\n}\n\nfn (t Tree) cast_expr(node ast.CastExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('CastExpr'))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('ityp', t.number_node(int(node.typ)))\n\tobj.add_terse('typname', t.string_node(node.typname))\n\tobj.add_terse('has_arg', t.bool_node(node.has_arg))\n\tobj.add_terse('arg', t.expr(node.arg))\n\tobj.add_terse('expr_type', t.type_node(node.expr_type))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) as_cast(node ast.AsCast) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('AsCast'))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('expr_type', t.type_node(node.expr_type))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) type_expr(node ast.TypeNode) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('TypeNode'))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) size_of(node ast.SizeOf) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('SizeOf'))\n\tobj.add_terse('guessed_type', t.bool_node(node.guessed_type))\n\tobj.add_terse('is_type', t.bool_node(node.is_type))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) is_ref_type(node ast.IsRefType) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('IsRefType'))\n\tobj.add_terse('guessed_type', t.bool_node(node.guessed_type))\n\tobj.add_terse('is_type', t.bool_node(node.is_type))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) prefix_expr(node ast.PrefixExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('PrefixExpr'))\n\tobj.add_terse('op', t.token_node(node.op))\n\tobj.add_terse('right', t.expr(node.right))\n\tobj.add_terse('right_type', t.type_node(node.right_type))\n\tobj.add_terse('or_block', t.or_expr(node.or_block))\n\tobj.add_terse('is_option', t.bool_node(node.is_option))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) infix_expr(node ast.InfixExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('InfixExpr'))\n\tobj.add_terse('op', t.token_node(node.op))\n\tobj.add_terse('left', t.expr(node.left))\n\tobj.add_terse('left_type', t.type_node(node.left_type))\n\tobj.add_terse('right', t.expr(node.right))\n\tobj.add_terse('right_type', t.type_node(node.right_type))\n\tobj.add_terse('promoted_type', t.type_node(node.promoted_type))\n\tobj.add('auto_locked', t.string_node(node.auto_locked))\n\tobj.add_terse('or_block', t.or_expr(node.or_block))\n\tobj.add_terse('is_stmt', t.bool_node(node.is_stmt))\n\tobj.add_terse('ct_left_value_evaled', t.bool_node(node.ct_left_value_evaled))\n\tobj.add_terse('ct_left_value', t.comptime_expr_value(node.ct_left_value))\n\tobj.add_terse('ct_right_value_evaled', t.bool_node(node.ct_right_value_evaled))\n\tobj.add_terse('ct_right_value', t.comptime_expr_value(node.ct_right_value))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) index_expr(node ast.IndexExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('IndexExpr'))\n\tobj.add_terse('left', t.expr(node.left))\n\tobj.add_terse('left_type', t.type_node(node.left_type))\n\tobj.add_terse('index', t.expr(node.index))\n\tobj.add_terse('is_setter', t.bool_node(node.is_setter))\n\tobj.add_terse('is_direct', t.bool_node(node.is_direct))\n\tobj.add_terse('or_expr', t.or_expr(node.or_expr))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) postfix_expr(node ast.PostfixExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('PostfixExpr'))\n\tobj.add_terse('op', t.token_node(node.op))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add('auto_locked', t.string_node(node.auto_locked))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('is_c2v_prefix', t.bool_node(node.is_c2v_prefix))\n\treturn obj\n}\n\nfn (t Tree) selector_expr(node ast.SelectorExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('SelectorExpr'))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add_terse('expr_type', t.type_node(node.expr_type))\n\tobj.add_terse('field_name', t.string_node(node.field_name))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('name_type', t.type_node(node.name_type))\n\tobj.add_terse('or_block', t.or_expr(node.or_block))\n\tobj.add_terse('gkind_field', t.enum_node(node.gkind_field))\n\tobj.add_terse('from_embed_types', t.array_node_type(node.from_embed_types))\n\tobj.add_terse('has_hidden_receiver', t.bool_node(node.has_hidden_receiver))\n\tobj.add_terse('next_token', t.token_node(node.next_token))\n\tobj.add_terse('is_field_typ', t.bool_node(node.is_field_typ))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('scope', t.number_node(int(node.scope)))\n\treturn obj\n}\n\nfn (t Tree) range_expr(node ast.RangeExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('RangeExpr'))\n\tobj.add_terse('low', t.expr(node.low))\n\tobj.add_terse('high', t.expr(node.high))\n\tobj.add_terse('has_high', t.bool_node(node.has_high))\n\tobj.add_terse('has_low', t.bool_node(node.has_low))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) if_expr(node ast.IfExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('IfExpr'))\n\tobj.add_terse('is_comptime', t.bool_node(node.is_comptime))\n\tobj.add_terse('tok_kind', t.token_node(node.tok_kind))\n\tobj.add_terse('branches', t.array_node_if_branch(node.branches))\n\tobj.add_terse('left', t.expr(node.left))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('has_else', t.bool_node(node.has_else))\n\tobj.add_terse('is_expr', t.bool_node(node.is_expr))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('post_comments', t.array_node_comment(node.post_comments))\n\treturn obj\n}\n\nfn (t Tree) if_branch(node ast.IfBranch) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('IfBranch'))\n\tobj.add_terse('cond', t.expr(node.cond))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('body_pos', t.pos(node.body_pos))\n\tobj.add_terse('stmts', t.array_node_stmt(node.stmts))\n\tobj.add('scope', t.number_node(int(node.scope)))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\treturn obj\n}\n\nfn (t Tree) ident(node ast.Ident) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('Ident'))\n\tobj.add_terse('mod', t.string_node(node.mod))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('language', t.enum_node(node.language))\n\tobj.add_terse('is_mut', t.bool_node(node.is_mut))\n\tobj.add_terse('comptime', t.bool_node(node.comptime))\n\tobj.add_terse('tok_kind', t.token_node(node.tok_kind))\n\tobj.add_terse('kind', t.enum_node(node.kind))\n\tobj.add_terse('info', t.ident_info(node.info))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('mut_pos', t.pos(node.mut_pos))\n\tobj.add('obj', t.scope_object(node.obj))\n\tobj.add('scope', t.number_node(int(node.scope)))\n\tobj.add_terse('or_expr', t.or_expr(node.or_expr))\n\treturn obj\n}\n\nfn (t Tree) ident_info(node ast.IdentInfo) &Node {\n\tmatch node {\n\t\tast.IdentVar { return t.ident_var(node) }\n\t\tast.IdentFn { return t.ident_fn(node) }\n\t}\n}\n\nfn (t Tree) ident_var(node ast.IdentVar) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('IdentVar'))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('is_mut', t.bool_node(node.is_mut))\n\tobj.add_terse('is_static', t.bool_node(node.is_static))\n\tobj.add_terse('is_volatile', t.bool_node(node.is_volatile))\n\tobj.add_terse('is_option', t.bool_node(node.is_option))\n\tobj.add_terse('share', t.enum_node(node.share))\n\treturn obj\n}\n\nfn (t Tree) ident_fn(node ast.IdentFn) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('IdentFn'))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\treturn obj\n}\n\nfn (t Tree) call_expr(node ast.CallExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('CallExpr'))\n\tobj.add_terse('mod', t.string_node(node.mod))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('const_name', t.string_node(node.const_name))\n\tobj.add_terse('language', t.enum_node(node.language))\n\tobj.add_terse('kind', t.enum_node(node.kind))\n\tobj.add_terse('left_type', t.type_node(node.left_type))\n\tobj.add_terse('receiver_type', t.type_node(node.receiver_type))\n\tobj.add_terse('return_type', t.type_node(node.return_type))\n\tobj.add_terse('fn_var_type', t.type_node(node.fn_var_type))\n\tobj.add_terse('left', t.expr(node.left))\n\tobj.add_terse('is_method', t.bool_node(node.is_method))\n\tobj.add_terse('is_field', t.bool_node(node.is_field))\n\tobj.add_terse('is_fn_var', t.bool_node(node.is_fn_var))\n\tobj.add_terse('is_fn_a_const', t.bool_node(node.is_fn_a_const))\n\tobj.add('is_keep_alive', t.bool_node(node.is_keep_alive))\n\tobj.add_terse('is_noreturn', t.bool_node(node.is_noreturn))\n\tobj.add_terse('is_ctor_new', t.bool_node(node.is_ctor_new))\n\tobj.add_terse('is_return_used', t.bool_node(node.is_return_used))\n\tobj.add_terse('is_static_method', t.bool_node(node.is_static_method))\n\tobj.add_terse('is_variadic', t.bool_node(node.is_variadic))\n\tobj.add('should_be_skipped', t.bool_node(node.should_be_skipped))\n\tobj.add_terse('free_receiver', t.bool_node(node.free_receiver))\n\tobj.add('scope', t.number_node(int(node.scope)))\n\tobj.add_terse('args', t.array_node_call_arg(node.args))\n\tobj.add_terse('expected_arg_types', t.array_node_type(node.expected_arg_types))\n\tobj.add_terse('concrete_types', t.array_node_type(node.concrete_types))\n\tobj.add_terse('or_block', t.or_expr(node.or_block))\n\tobj.add('concrete_list_pos', t.pos(node.concrete_list_pos))\n\tobj.add_terse('from_embed_types', t.array_node_type(node.from_embed_types))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('name_pos', t.pos(node.name_pos))\n\treturn obj\n}\n\nfn (t Tree) call_arg(node ast.CallArg) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('CallArg'))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('is_mut', t.bool_node(node.is_mut))\n\tobj.add_terse('share', t.enum_node(node.share))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add_terse('should_be_ptr', t.bool_node(node.should_be_ptr))\n\tobj.add('is_tmp_autofree', t.bool_node(node.is_tmp_autofree))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\treturn obj\n}\n\nfn (t Tree) or_expr(node ast.OrExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('OrExpr'))\n\tobj.add_terse('stmts', t.array_node_stmt(node.stmts))\n\tobj.add_terse('kind', t.enum_node(node.kind))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('scope', t.number_node(int(node.scope)))\n\treturn obj\n}\n\nfn (t Tree) struct_init(node ast.StructInit) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('StructInit'))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('no_keys', t.bool_node(node.no_keys))\n\tobj.add_terse('is_short_syntax', t.bool_node(node.is_short_syntax))\n\tobj.add_terse('is_anon', t.bool_node(node.is_anon))\n\tobj.add_terse('unresolved', t.bool_node(node.unresolved))\n\tobj.add_terse('has_update_expr', t.bool_node(node.has_update_expr))\n\tobj.add_terse('update_expr', t.expr(node.update_expr))\n\tobj.add_terse('update_expr_type', t.type_node(node.update_expr_type))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('name_pos', t.pos(node.name_pos))\n\tobj.add('update_expr_comments', t.array_node_comment(node.update_expr_comments))\n\tobj.add('update_expr_pos', t.pos(node.update_expr_pos))\n\tobj.add_terse('init_fields', t.array_node_struct_init_field(node.init_fields))\n\tobj.add('pre_comments', t.array_node_comment(node.pre_comments))\n\treturn obj\n}\n\nfn (t Tree) struct_init_field(node ast.StructInitField) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('StructInitField'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('expected_type', t.type_node(node.expected_type))\n\tobj.add_terse('parent_type', t.type_node(node.parent_type))\n\tobj.add('pre_comments', t.array_node_comment(node.pre_comments))\n\tobj.add('end_comments', t.array_node_comment(node.end_comments))\n\tobj.add('next_comments', t.array_node_comment(node.next_comments))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('name_pos', t.pos(node.name_pos))\n\treturn obj\n}\n\nfn (t Tree) array_init(node ast.ArrayInit) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ArrayInit'))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('elem_type', t.type_node(node.elem_type))\n\tobj.add_terse('exprs', t.array_node_expr(node.exprs))\n\tobj.add('ecmnts', t.two_dimension_comment(node.ecmnts))\n\tobj.add('pre_cmnts', t.array_node_comment(node.pre_cmnts))\n\tobj.add('elem_type_pos', t.pos(node.elem_type_pos))\n\tobj.add_terse('is_fixed', t.bool_node(node.is_fixed))\n\tobj.add_terse('is_option', t.bool_node(node.is_option))\n\tobj.add_terse('has_val', t.bool_node(node.has_val))\n\tobj.add_terse('mod', t.string_node(node.mod))\n\tobj.add_terse('len_expr', t.expr(node.len_expr))\n\tobj.add_terse('cap_expr', t.expr(node.cap_expr))\n\tobj.add_terse('init_expr', t.expr(node.init_expr))\n\tobj.add_terse('has_len', t.bool_node(node.has_len))\n\tobj.add_terse('has_cap', t.bool_node(node.has_cap))\n\tobj.add_terse('has_init', t.bool_node(node.has_init))\n\tobj.add_terse('has_index', t.bool_node(node.has_index))\n\tobj.add_terse('expr_types', t.array_node_type(node.expr_types))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) map_init(node ast.MapInit) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('MapInit'))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('key_type', t.type_node(node.key_type))\n\tobj.add_terse('value_type', t.type_node(node.value_type))\n\tobj.add_terse('keys', t.array_node_expr(node.keys))\n\tobj.add_terse('vals', t.array_node_expr(node.vals))\n\tobj.add_terse('val_types', t.array_node_type(node.val_types))\n\tobj.add_terse('has_update_expr', t.bool_node(node.has_update_expr))\n\tobj.add_terse('update_expr', t.expr(node.update_expr))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('pre_cmnts', t.array_node_comment(node.pre_cmnts))\n\tobj.add('comments', t.two_dimension_comment(node.comments))\n\tobj.add('update_expr_comments', t.array_node_comment(node.update_expr_comments))\n\tobj.add('update_expr_pos', t.pos(node.update_expr_pos))\n\treturn obj\n}\n\nfn (t Tree) none_expr(node ast.None) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('None'))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) par_expr(node ast.ParExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ParExpr'))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) if_guard_expr(node ast.IfGuardExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('IfGuardExpr'))\n\tobj.add_terse('vars', t.array_node_if_guard_var(node.vars))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add_terse('expr_type', t.type_node(node.expr_type))\n\treturn obj\n}\n\nfn (t Tree) if_guard_var(node ast.IfGuardVar) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('IfGuardVar'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('is_mut', t.bool_node(node.is_mut))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) match_expr(node ast.MatchExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('MatchExpr'))\n\tobj.add_terse('tok_kind', t.token_node(node.tok_kind))\n\tobj.add_terse('cond', t.expr(node.cond))\n\tobj.add_terse('cond_type', t.type_node(node.cond_type))\n\tobj.add_terse('return_type', t.type_node(node.return_type))\n\tobj.add_terse('expected_type', t.type_node(node.expected_type))\n\tobj.add_terse('is_sum_type', t.bool_node(node.is_sum_type))\n\tobj.add_terse('is_expr', t.bool_node(node.is_expr))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add_terse('branches', t.array_node_match_branch(node.branches))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\treturn obj\n}\n\nfn (t Tree) match_branch(node ast.MatchBranch) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('MatchBranch'))\n\tobj.add('ecmnts', t.two_dimension_comment(node.ecmnts))\n\tobj.add_terse('stmts', t.array_node_stmt(node.stmts))\n\tobj.add_terse('is_else', t.bool_node(node.is_else))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add_terse('post_comments', t.array_node_comment(node.post_comments))\n\tobj.add('branch_pos', t.pos(node.branch_pos))\n\tobj.add_terse('exprs', t.array_node_expr(node.exprs))\n\tobj.add('scope', t.number_node(int(node.scope)))\n\treturn obj\n}\n\nfn (t Tree) concat_expr(node ast.ConcatExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ConcatExpr'))\n\tobj.add_terse('vals', t.array_node_expr(node.vals))\n\tobj.add_terse('return_type', t.type_node(node.return_type))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) type_of(node ast.TypeOf) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('TypeOf'))\n\tobj.add_terse('is_type', t.bool_node(node.is_type))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) likely(node ast.Likely) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('Likely'))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add_terse('is_likely', t.bool_node(node.is_likely))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) sql_expr(node ast.SqlExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('SqlExpr'))\n\tobj.add_terse('type', t.type_node(node.typ))\n\tobj.add_terse('aggregate_kind', t.string_node('${node.aggregate_kind}'))\n\tobj.add_terse('aggregate_field', t.string_node(node.aggregate_field))\n\tobj.add_terse('db_expr', t.expr(node.db_expr))\n\tobj.add_terse('table_expr', t.type_expr(node.table_expr))\n\tobj.add_terse('has_where', t.bool_node(node.has_where))\n\tobj.add_terse('where_expr', t.expr(node.where_expr))\n\tobj.add_terse('has_order', t.bool_node(node.has_order))\n\tobj.add_terse('order_expr', t.expr(node.order_expr))\n\tobj.add_terse('has_desc', t.bool_node(node.has_desc))\n\tobj.add_terse('is_array', t.bool_node(node.is_array))\n\tobj.add_terse('or_expr', t.or_expr(node.or_expr))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('has_limit', t.bool_node(node.has_limit))\n\tobj.add_terse('limit_expr', t.expr(node.limit_expr))\n\tobj.add_terse('has_offset', t.bool_node(node.has_offset))\n\tobj.add_terse('offset_expr', t.expr(node.offset_expr))\n\tobj.add_terse('fields', t.array_node_struct_field(node.fields))\n\tmut sub_struct_map := create_object()\n\tfor key, val in node.sub_structs {\n\t\tsub_struct_map.add_terse(key.str(), t.sql_expr(val))\n\t}\n\tobj.add_terse('sub_structs', sub_struct_map)\n\treturn obj\n}\n\nfn (t Tree) semicolon_stmt(node ast.SemicolonStmt) &Node {\n\tmut obj := create_object()\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) sql_stmt(node ast.SqlStmt) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('SqlStmt'))\n\tobj.add_terse('db_expr_type', t.type_node(node.db_expr_type))\n\tobj.add_terse('db_expr', t.expr(node.db_expr))\n\tobj.add_terse('or_expr', t.or_expr(node.or_expr))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add_terse('lines', t.array_node_sql_stmt_line(node.lines))\n\treturn obj\n}\n\nfn (t Tree) sql_stmt_line(node ast.SqlStmtLine) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('SqlStmtLine'))\n\tobj.add_terse('kind', t.enum_node(node.kind))\n\tobj.add_terse('table_expr', t.type_expr(node.table_expr))\n\tobj.add_terse('object_var', t.string_node(node.object_var))\n\tobj.add_terse('where_expr', t.expr(node.where_expr))\n\tobj.add_terse('fields', t.array_node_struct_field(node.fields))\n\tobj.add_terse('updated_columns', t.array_node_string(node.updated_columns))\n\tobj.add_terse('update_exprs', t.array_node_expr(node.update_exprs))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add('pre_comments', t.array_node_comment(node.pre_comments))\n\tobj.add('end_comments', t.array_node_comment(node.end_comments))\n\n\tmut sub_struct_map := create_object()\n\tfor key, val in node.sub_structs {\n\t\tsub_struct_map.add_terse(key.str(), t.sql_stmt_line(val))\n\t}\n\tobj.add_terse('sub_structs', sub_struct_map)\n\treturn obj\n}\n\nfn (t Tree) lock_expr(expr ast.LockExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('LockExpr'))\n\tobj.add_terse('is_expr', t.bool_node(expr.is_expr))\n\tobj.add_terse('typ', t.type_node(expr.typ))\n\tobj.add('pos', t.pos(expr.pos))\n\tobj.add_terse('stmts', t.array_node_stmt(expr.stmts))\n\tobj.add_terse('lockeds', t.array_node_expr(expr.lockeds))\n\tobj.add_terse('r_lock', t.array_node_bool(expr.is_rlock))\n\treturn obj\n}\n\nfn (t Tree) unsafe_expr(expr ast.UnsafeExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('UnsafeExpr'))\n\tobj.add_terse('expr', t.expr(expr.expr))\n\tobj.add('pos', t.pos(expr.pos))\n\treturn obj\n}\n\nfn (t Tree) chan_init(expr ast.ChanInit) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ChanInit'))\n\tobj.add_terse('has_cap', t.bool_node(expr.has_cap))\n\tobj.add_terse('cap_expr', t.expr(expr.cap_expr))\n\tobj.add_terse('typ', t.type_node(expr.typ))\n\tobj.add_terse('elem_type', t.type_node(expr.elem_type))\n\tobj.add('pos', t.pos(expr.pos))\n\tobj.add('elem_type_pos', t.pos(expr.elem_type_pos))\n\treturn obj\n}\n\nfn (t Tree) select_expr(expr ast.SelectExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('SelectExpr'))\n\tobj.add_terse('branches', t.array_node_select_branch(expr.branches))\n\tobj.add_terse('is_expr', t.bool_node(expr.is_expr))\n\tobj.add_terse('has_exception', t.bool_node(expr.has_exception))\n\tobj.add_terse('expected_type', t.type_node(expr.expected_type))\n\tobj.add('pos', t.pos(expr.pos))\n\treturn obj\n}\n\nfn (t Tree) select_branch(expr ast.SelectBranch) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('SelectBranch'))\n\tobj.add_terse('stmt', t.stmt(expr.stmt))\n\tobj.add_terse('stmts', t.array_node_stmt(expr.stmts))\n\tobj.add('pos', t.pos(expr.pos))\n\tobj.add('comment', t.comment(expr.comment))\n\tobj.add_terse('is_else', t.bool_node(expr.is_else))\n\tobj.add_terse('is_timeout', t.bool_node(expr.is_timeout))\n\tobj.add('post_comments', t.array_node_comment(expr.post_comments))\n\treturn obj\n}\n\nfn (t Tree) array_decompose(expr ast.ArrayDecompose) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('ArrayDecompose'))\n\tobj.add_terse('expr', t.expr(expr.expr))\n\tobj.add_terse('expr_type', t.type_node(expr.expr_type))\n\tobj.add_terse('arg_type', t.type_node(expr.arg_type))\n\tobj.add('pos', t.pos(expr.pos))\n\treturn obj\n}\n\nfn (t Tree) go_expr(expr ast.GoExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('GoExpr'))\n\tobj.add_terse('call_expr', t.call_expr(expr.call_expr))\n\tobj.add_terse('is_expr', t.bool_node(expr.is_expr))\n\tobj.add('pos', t.pos(expr.pos))\n\treturn obj\n}\n\nfn (t Tree) spawn_expr(expr ast.SpawnExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('SpawnExpr'))\n\tobj.add_terse('call_expr', t.call_expr(expr.call_expr))\n\tobj.add_terse('is_expr', t.bool_node(expr.is_expr))\n\tobj.add('pos', t.pos(expr.pos))\n\treturn obj\n}\n\nfn (t Tree) offset_of(expr ast.OffsetOf) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('OffsetOf'))\n\tobj.add_terse('struct_type', t.type_node(expr.struct_type))\n\tobj.add_terse('field', t.string_node('field'))\n\tobj.add('pos', t.pos(expr.pos))\n\treturn obj\n}\n\nfn (t Tree) dump_expr(expr ast.DumpExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('DumpExpr'))\n\tobj.add_terse('expr', t.expr(expr.expr))\n\tobj.add_terse('expr_type', t.type_node(expr.expr_type))\n\tobj.add('pos', t.pos(expr.pos))\n\treturn obj\n}\n\nfn (t Tree) node_error(expr ast.NodeError) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('NodeError'))\n\tobj.add_terse('idx', t.number_node(expr.idx))\n\tobj.add('pos', t.pos(expr.pos))\n\treturn obj\n}\n\nfn (t Tree) empty_expr(expr ast.EmptyExpr) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('EmptyExpr'))\n\t// obj.add('x', t.number_node(expr.x))\n\treturn obj\n}\n\nfn (t Tree) empty_stmt(node ast.EmptyStmt) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('EmptyStmt'))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) debugger_stmt(node ast.DebuggerStmt) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('DebuggerStmt'))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) nil_expr(node ast.Nil) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('Nil'))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) asm_stmt(node ast.AsmStmt) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('AsmStmt'))\n\tobj.add_terse('arch', t.enum_node(node.arch))\n\tobj.add_terse('is_basic', t.bool_node(node.is_basic))\n\tobj.add_terse('is_volatile', t.bool_node(node.is_volatile))\n\tobj.add_terse('is_goto', t.bool_node(node.is_goto))\n\tobj.add('scope', t.scope(node.scope))\n\t// obj.add('scope', t.number_node(int(node.scope)))\n\tobj.add('pos', t.pos(node.pos))\n\tobj.add_terse('clobbered', t.array_node_asm_clobbered(node.clobbered))\n\tobj.add_terse('templates', t.array_node_asm_template(node.templates))\n\tobj.add_terse('output', t.array_node_asm_io(node.output))\n\tobj.add_terse('input', t.array_node_asm_io(node.input))\n\tobj.add_terse('global_labels', t.array_node_string(node.global_labels))\n\tobj.add_terse('local_labels', t.array_node_string(node.local_labels))\n\treturn obj\n}\n\nfn (t Tree) asm_register(node ast.AsmRegister) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('AsmRegister'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add_terse('size', t.number_node(node.size))\n\treturn obj\n}\n\nfn (t Tree) asm_template(node ast.AsmTemplate) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('AsmTemplate'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add_terse('is_label', t.bool_node(node.is_label))\n\tobj.add_terse('is_directive', t.bool_node(node.is_directive))\n\tobj.add_terse('args', t.array_node_asm_arg(node.args))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) asm_addressing(node ast.AsmAddressing) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('AsmAddressing'))\n\tobj.add_terse('scale', t.number_node(node.scale))\n\tobj.add_terse('mode', t.enum_node(node.mode))\n\tobj.add_terse('segment', t.string_node(node.segment))\n\tobj.add_terse('displacement', t.asm_arg(node.displacement))\n\tobj.add_terse('base', t.asm_arg(node.base))\n\tobj.add_terse('index', t.asm_arg(node.index))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) asm_arg(node ast.AsmArg) &Node {\n\tmatch node {\n\t\tast.AsmAddressing {\n\t\t\treturn t.asm_addressing(node)\n\t\t}\n\t\tast.AsmAlias {\n\t\t\treturn t.asm_alias(node)\n\t\t}\n\t\tast.AsmDisp {\n\t\t\treturn t.asm_disp(node)\n\t\t}\n\t\tast.AsmRegister {\n\t\t\treturn t.asm_register(node)\n\t\t}\n\t\tast.BoolLiteral {\n\t\t\treturn t.bool_literal(node)\n\t\t}\n\t\tast.CharLiteral {\n\t\t\treturn t.char_literal(node)\n\t\t}\n\t\tast.FloatLiteral {\n\t\t\treturn t.float_literal(node)\n\t\t}\n\t\tast.IntegerLiteral {\n\t\t\treturn t.integer_literal(node)\n\t\t}\n\t\tstring {\n\t\t\treturn t.string_node(node)\n\t\t}\n\t}\n}\n\nfn (t Tree) asm_alias(node ast.AsmAlias) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('AsmAlias'))\n\tobj.add_terse('name', t.string_node(node.name))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) asm_disp(node ast.AsmDisp) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('AsmDisp'))\n\tobj.add_terse('val', t.string_node(node.val))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\nfn (t Tree) asm_clobbered(node ast.AsmClobbered) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('AsmClobbered'))\n\tobj.add_terse('reg', t.asm_register(node.reg))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\treturn obj\n}\n\nfn (t Tree) asm_io(node ast.AsmIO) &Node {\n\tmut obj := create_object()\n\tobj.add_terse('ast_type', t.string_node('AsmIO'))\n\tobj.add_terse('alias', t.string_node(node.alias))\n\tobj.add_terse('constraint', t.string_node(node.constraint))\n\tobj.add_terse('expr', t.expr(node.expr))\n\tobj.add_terse('typ', t.type_node(node.typ))\n\tobj.add('comments', t.array_node_comment(node.comments))\n\tobj.add('pos', t.pos(node.pos))\n\treturn obj\n}\n\n// do not support yet by vlang\n// fn (t Tree) array_node1[T](nodes []T, method_name string) &Node {\n// \tmut arr := create_array()\n\n// \t// call method dynamically, V do not support yet\n// \t// error: todo: not a string literal\n\n// \t// for node in nodes {\n// \t// \tarr.add_item(t.$method_name(node))\n// \t// }\n\n// \t// temp\n// \t$for method in Tree.methods {\n// \t\tif method.name == method_name {\n// \t\t\tfor node in nodes {\n// \t\t\t\tres := t.$method(node)\n// \t\t\t\tarr.add_item(res) // TODO,waiting for bug fixed\n// \t\t\t}\n// \t\t}\n// \t}\n// \treturn arr\n// }\n\n// do not support yet by vlang\n// fn (t Tree) array_node2[T](nodes []T) &Node {\n// \tmut arr := create_array()\n\n// \tfor node in nodes {\n// \t\tmatch node {\n// \t\t\tstring {\n// \t\t\t\tarr.add_item(t.string_node(node))\n// \t\t\t}\n// \t\t\tast.Comment {\n// \t\t\t\tarr.add_item(t.comment(node))\n// \t\t\t}\n// \t\t\tast.ConstField {\n// \t\t\t\tarr.add_item(t.const_field(node))\n// \t\t\t}\n// \t\t\telse {\n// \t\t\t\tpanic('unknown array type')\n// \t\t\t}\n// \t\t}\n// \t}\n\n// \treturn arr\n// }\n\n// list all the different type of array node,temporarily\nfn (t Tree) array_node_string(nodes []string) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.string_node(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_position(nodes []token.Pos) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.pos(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_if_branch(nodes []ast.IfBranch) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.if_branch(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_fn_decl(nodes []ast.FnDecl) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.fn_decl(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_generic_fns(nodes []&ast.FnDecl) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.fn_decl(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_embed_file(nodes []ast.EmbeddedFile) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.embed_file(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_attr(nodes []ast.Attr) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.attr(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_scope_struct_field(nodes map[string]ast.ScopeStructField) &Node {\n\tmut arr := create_array()\n\tfor _, node in nodes {\n\t\tarr.add_item(t.scope_struct_field(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_type(nodes []ast.Type) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.type_node(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_type_expr(nodes []ast.TypeNode) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.type_expr(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_import_symbol(nodes []ast.ImportSymbol) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.import_symbol(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_comment(nodes []ast.Comment) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.comment(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_const_field(nodes []ast.ConstField) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.const_field(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_arg(nodes []ast.Param) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.arg(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_stmt(nodes []ast.Stmt) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.stmt(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_defer_stmt(nodes []ast.DeferStmt) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.defer_stmt(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_struct_field(nodes []ast.StructField) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.struct_field(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_embed(nodes []ast.Embed) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.embed(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_enum_field(nodes []ast.EnumField) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.enum_field(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_global_field(nodes []ast.GlobalField) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.global_field(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_expr(nodes []ast.Expr) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.expr(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_call_arg(nodes []ast.CallArg) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.call_arg(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_int(nodes []int) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.number_node(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_u8(nodes []u8) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.number_node(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_bool(nodes []bool) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.bool_node(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_struct_init_field(nodes []ast.StructInitField) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.struct_init_field(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_if_guard_var(nodes []ast.IfGuardVar) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.if_guard_var(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_match_branch(nodes []ast.MatchBranch) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.match_branch(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_ident(nodes []ast.Ident) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.ident(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_select_branch(nodes []ast.SelectBranch) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.select_branch(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_asm_clobbered(nodes []ast.AsmClobbered) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.asm_clobbered(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_asm_template(nodes []ast.AsmTemplate) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.asm_template(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_asm_io(nodes []ast.AsmIO) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.asm_io(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_asm_arg(nodes []ast.AsmArg) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.asm_arg(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_sql_stmt_line(nodes []ast.SqlStmtLine) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.sql_stmt_line(node))\n\t}\n\treturn arr\n}\n\nfn (t Tree) array_node_interface_embedding(nodes []ast.InterfaceEmbedding) &Node {\n\tmut arr := create_array()\n\tfor node in nodes {\n\t\tarr.add_item(t.interface_embedding(node))\n\t}\n\treturn arr\n}\n"
  },
  {
    "path": "cmd/tools/vast2/vast2.v",
    "content": "// Copyright (c) 2020-2024 Alexander Medvednikov. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nmodule main\n\nimport os\nimport v2.ast\nimport v2.ast_dump\nimport v2.parser\nimport v2.pref\nimport v2.token\nimport v2.transformer\nimport v2.types\n\nfn main() {\n\targs := os.args[1..]\n\n\tif args.len == 0 {\n\t\teprintln('Usage: vast <file.v>')\n\t\teprintln('Dumps AST to <file>_ast.json and <file>_ast_transformed.json')\n\t\texit(1)\n\t}\n\n\tfiles := get_files(args)\n\tif files.len == 0 {\n\t\teprintln('Usage: vast <file.v>')\n\t\teprintln('Dumps AST to <file>_ast.json and <file>_ast_transformed.json')\n\t\texit(1)\n\t}\n\n\t// Get base name for output files\n\tinput_file := files[0]\n\tbase_name := if input_file.ends_with('.v') {\n\t\tinput_file[..input_file.len - 2]\n\t} else {\n\t\tinput_file\n\t}\n\n\tprefs := pref.new_preferences()\n\tmut file_set := token.FileSet.new()\n\tmut p := parser.Parser.new(&prefs)\n\n\t// Parse builtin and dependencies first\n\tmut ast_files := []ast.File{}\n\tast_files << p.parse_files(get_v_files_from_dir(prefs.get_vlib_module_path('builtin')), mut\n\t\tfile_set)\n\tast_files << p.parse_files(get_v_files_from_dir(prefs.get_vlib_module_path('strconv')), mut\n\t\tfile_set)\n\tast_files << p.parse_files(get_v_files_from_dir(prefs.get_vlib_module_path('strings')), mut\n\t\tfile_set)\n\tast_files << p.parse_files(get_v_files_from_dir(prefs.get_vlib_module_path('hash')), mut\n\t\tfile_set)\n\tast_files << p.parse_files(get_v_files_from_dir(prefs.get_vlib_module_path('math.bits')), mut\n\t\tfile_set)\n\n\t// Parse the user file(s)\n\tast_files << p.parse_files(files, mut file_set)\n\n\t// Write pre-transformation AST (only user files, not builtin)\n\tuser_files := ast_files.filter(it.name in files)\n\tast_json := ast_dump.dump_files(user_files)\n\tast_file := '${base_name}_ast.json'\n\tos.write_file(ast_file, ast_json) or {\n\t\teprintln('Failed to write ${ast_file}: ${err}')\n\t\texit(1)\n\t}\n\tprintln('Wrote ${ast_file}')\n\n\t// Type check\n\tenv := types.Environment.new()\n\tmut checker := types.Checker.new(&prefs, file_set, env)\n\tchecker.check_files(ast_files)\n\n\t// Transform\n\tmut trans := transformer.Transformer.new_with_pref(ast_files, env, &prefs)\n\ttransformed_files := trans.transform_files(ast_files)\n\n\t// Write post-transformation AST (only user files)\n\ttransformed_user_files := transformed_files.filter(it.name in files)\n\ttransformed_json := ast_dump.dump_files(transformed_user_files)\n\ttransformed_file := '${base_name}_ast_transformed.json'\n\tos.write_file(transformed_file, transformed_json) or {\n\t\teprintln('Failed to write ${transformed_file}: ${err}')\n\t\texit(1)\n\t}\n\tprintln('Wrote ${transformed_file}')\n}\n\n// get_files extracts source files from args, excluding options and their values\nfn get_files(args []string) []string {\n\toptions_with_values := ['-o', '-output']\n\tmut files := []string{}\n\tmut skip_next := false\n\tfor arg in args {\n\t\tif skip_next {\n\t\t\tskip_next = false\n\t\t\tcontinue\n\t\t}\n\t\tif arg.starts_with('-') {\n\t\t\tif arg in options_with_values {\n\t\t\t\tskip_next = true\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tfiles << arg\n\t}\n\treturn files\n}\n\nfn get_v_files_from_dir(dir string) []string {\n\tmut v_files := []string{}\n\tall_files := os.ls(dir) or { return v_files }\n\tfor file in all_files {\n\t\tif file.ends_with('.v') && !file.ends_with('_test.v') {\n\t\t\t// Skip platform-specific files that don't match current platform\n\t\t\tif should_include_file(file) {\n\t\t\t\tv_files << os.join_path(dir, file)\n\t\t\t}\n\t\t}\n\t}\n\treturn v_files\n}\n\nfn should_include_file(filename string) bool {\n\t// Skip test files (including _test.c.v)\n\tif filename.contains('_test.') {\n\t\treturn false\n\t}\n\t// Skip JavaScript backend files\n\tif filename.ends_with('.js.v') {\n\t\treturn false\n\t}\n\t// Handle platform-specific files\n\tcurrent_os := os.user_os()\n\t// Check for OS-specific suffixes like _linux.v, _windows.v, _macos.v\n\tos_suffixes := ['_linux.v', '_windows.v', '_macos.v', '_darwin.v', '_freebsd.v', '_openbsd.v',\n\t\t'_netbsd.v', '_solaris.v', '_haiku.v', '_android.v']\n\tfor suffix in os_suffixes {\n\t\tif filename.ends_with(suffix) {\n\t\t\t// Include only if it matches current OS\n\t\t\tif suffix == '_darwin.v' || suffix == '_macos.v' {\n\t\t\t\treturn current_os == 'macos'\n\t\t\t} else if suffix == '_linux.v' {\n\t\t\t\treturn current_os == 'linux'\n\t\t\t} else if suffix == '_windows.v' {\n\t\t\t\treturn current_os == 'windows'\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t}\n\t// Check for \"not this OS\" files like _nix.v (not windows)\n\tif filename.ends_with('_nix.v') {\n\t\treturn current_os != 'windows'\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "cmd/tools/vbin2v.v",
    "content": "module main\n\nimport os\nimport flag\nimport strings\n\nconst tool_version = '0.0.4'\nconst tool_description = 'Converts a list of arbitrary files into a single v module file.'\n\nstruct Context {\nmut:\n\tfiles       []string\n\tprefix      string\n\tshow_help   bool\n\tmodule_name string\n\twrite_file  string\n}\n\nfn (context Context) header() string {\n\tmut header_s := ''\n\theader_s += 'module ${context.module_name}\\n'\n\theader_s += '\\n'\n\tallfiles := context.files.join(' ')\n\tmut options := []string{}\n\tif context.prefix.len > 0 {\n\t\toptions << '-p ${context.prefix}'\n\t}\n\tif context.module_name.len > 0 {\n\t\toptions << '-m ${context.module_name}'\n\t}\n\tif context.write_file.len > 0 {\n\t\toptions << '-w ${context.write_file}'\n\t}\n\tsoptions := options.join(' ')\n\theader_s += '// File generated by:\\n'\n\theader_s += '// v bin2v ${allfiles} ${soptions}\\n'\n\theader_s += '// Please, do not edit this file.\\n'\n\theader_s += '// Your changes may be overwritten.\\n'\n\treturn header_s\n}\n\nfn (context Context) footer() string {\n\treturn ''\n}\n\nfn (context Context) file2v(bname string, fbytes []u8, bn_max int) string {\n\tmut sb := strings.new_builder(1000)\n\tsb.write_string('const ${bname}_len' + ' = ${fbytes.len}\\n')\n\tfbyte := fbytes[0]\n\tbnmae_line := 'const ${bname}' + ' = [u8(${fbyte}), '\n\tsb.write_string(bnmae_line)\n\tmut line_len := bnmae_line.len + 3\n\tfor i := 1; i < fbytes.len; i++ {\n\t\tb := int(fbytes[i]).str()\n\t\tif line_len > 98 {\n\t\t\tsb.go_back(1)\n\t\t\tsb.write_string('\\n\\t')\n\t\t\tline_len = 8\n\t\t}\n\t\tif i == fbytes.len - 1 {\n\t\t\tsb.write_string(b)\n\t\t\tline_len += b.len\n\t\t} else {\n\t\t\tsb.write_string('${b}, ')\n\t\t\tline_len += b.len + 2\n\t\t}\n\t}\n\tsb.write_string(']!\\n')\n\treturn sb.str()\n}\n\nfn (context Context) bname_and_bytes(file string) !(string, []u8) {\n\tfname := os.file_name(file)\n\tfname_escaped := fname.replace_each(['.', '_', '-', '_'])\n\tbyte_name := '${context.prefix}${fname_escaped}'.to_lower()\n\tfbytes := os.read_bytes(file) or { return error('Error: ${err.msg()}') }\n\treturn byte_name, fbytes\n}\n\nfn (context Context) max_bname_len(bnames []string) int {\n\tmut max := 0\n\tfor n in bnames {\n\t\tif n.len > max {\n\t\t\tmax = n.len\n\t\t}\n\t}\n\t// Add 4 to max due to \"_len\" suffix\n\treturn max + 4\n}\n\nfn main() {\n\tmut context := Context{}\n\tmut fp := flag.new_flag_parser(os.args[1..])\n\tfp.application('v bin2v')\n\tfp.version(tool_version)\n\tfp.description(tool_description)\n\tfp.arguments_description('FILE [FILE]...')\n\tcontext.show_help = fp.bool('help', `h`, false, 'Show this help screen.')\n\tcontext.module_name = fp.string('module', `m`, 'binary', 'Name of the generated module.')\n\tcontext.prefix = fp.string('prefix', `p`, '', 'A prefix put before each resource name.')\n\tcontext.write_file = fp.string('write', `w`, '', 'Write directly to a file with the given name.')\n\tif context.show_help {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\tfiles := fp.finalize() or {\n\t\teprintln('Error: ${err.msg()}')\n\t\texit(1)\n\t}\n\treal_files := files.filter(it != 'bin2v')\n\tif real_files.len == 0 {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\tcontext.files = real_files\n\tif context.write_file != '' && os.file_ext(context.write_file) !in ['.vv', '.v'] {\n\t\tcontext.write_file += '.v'\n\t}\n\tmut file_byte_map := map[string][]u8{}\n\tfor file in real_files {\n\t\tbname, fbytes := context.bname_and_bytes(file) or {\n\t\t\teprintln(err.msg())\n\t\t\texit(1)\n\t\t}\n\t\tfile_byte_map[bname] = fbytes\n\t}\n\tmax_bname := context.max_bname_len(file_byte_map.keys())\n\tif context.write_file.len > 0 {\n\t\tmut out_file := os.create(context.write_file)!\n\t\tout_file.write_string(context.header())!\n\t\tfor bname, fbytes in file_byte_map {\n\t\t\tout_file.write_string(context.file2v(bname, fbytes, max_bname))!\n\t\t}\n\t\tout_file.write_string(context.footer())!\n\t} else {\n\t\tprint(context.header())\n\t\tfor bname, fbytes in file_byte_map {\n\t\t\tprint(context.file2v(bname, fbytes, max_bname))\n\t\t}\n\t\tprint(context.footer())\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vbug.v",
    "content": "import os\nimport term\nimport readline\nimport net.urllib\n\nfn elog(msg string) {\n\teprintln(term.ecolorize(term.gray, msg))\n}\n\nfn olog(msg string) {\n\tprintln(term.colorize(term.green, msg))\n}\n\nfn vversion() string {\n\tvexe := os.getenv('VEXE')\n\treturn os.execute('${os.quoted_path(vexe)} version').output.trim_space()\n}\n\n// get output from `v doctor`\nfn get_vdoctor_output(is_verbose bool) string {\n\tvexe := os.getenv('VEXE')\n\tverbose_flag := if is_verbose { '-v' } else { '' }\n\tresult := os.execute('${os.quoted_path(vexe)} ${verbose_flag} doctor')\n\tif result.exit_code != 0 {\n\t\telog('> unable to get `v doctor` output: ${result.output}')\n\t\treturn ''\n\t}\n\treturn result.output\n}\n\nfn runv(label string, user_cmd string) os.Result {\n\tmut result := os.Result{}\n\telog('> ${label} using: ${term.ecolorize(term.magenta, user_cmd)}')\n\tresult = os.execute(user_cmd)\n\tprint(result.output)\n\treturn result\n}\n\n// get output from `./v -g -o vdbg cmd/v && ./vdbg -user_args run file.v`\nfn get_v_build_output(is_verbose bool, is_yes bool, file_path string, user_args string, generated_file string) string {\n\tmut result := os.Result{}\n\tmut vexe := os.getenv('VEXE')\n\n\t// prepare a V compiler with -g to have better backtraces if possible\n\twd := os.getwd()\n\tvroot := @VMODROOT\n\tos.chdir(vroot) or {}\n\tverbose_flag := if is_verbose { '-v' } else { '' }\n\tvdbg_path := $if windows { '${vroot}/vdbg.exe' } $else { '${vroot}/vdbg' }\n\tvdbg_compilation_cmd := '${os.quoted_path(vexe)} ${verbose_flag} -g -o ${os.quoted_path(vdbg_path)} cmd/v'\n\tresult = runv('Prepare vdbg', vdbg_compilation_cmd)\n\tos.chdir(wd) or {}\n\n\tif result.exit_code == 0 {\n\t\tvexe = vdbg_path\n\t} else {\n\t\telog('> unable to compile V in debug mode: ${result.output}\\ncommand: ${vdbg_compilation_cmd}\\n')\n\t}\n\n\tresult = runv('Compile', '${os.quoted_path(vexe)} ${verbose_flag} ${user_args} ${os.quoted_path(file_path)}')\n\tdefer {\n\t\tos.rm(vdbg_path) or {\n\t\t\tif is_verbose {\n\t\t\t\telog('> unable to delete `vdbg`: ${err}')\n\t\t\t}\n\t\t}\n\t}\n\tif result.exit_code == 0 {\n\t\treal_generated_file := os.real_path(generated_file)\n\t\tdefer(fn) {\n\t\t\tos.rm(generated_file) or {\n\t\t\t\tif is_verbose {\n\t\t\t\t\telog('> unable to delete generated file: ${err}')\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\trun := is_yes\n\t\t\t|| ask('It looks like the compilation went well, do you want to run the file?')\n\t\tif run {\n\t\t\tresult = runv('Run', real_generated_file)\n\t\t\tif result.exit_code == 0 && !is_yes {\n\t\t\t\telog('> The file ran correctly as well.')\n\t\t\t\tconfirm_or_exit('Are you sure you want to continue?')\n\t\t\t}\n\t\t}\n\t}\n\treturn result.output\n}\n\nfn ask(msg string) bool {\n\tprompt := os.input_opt(term.colorize(term.bright_white, '${msg} [Y/n] ')) or { 'y' }\n\treturn prompt == '' || prompt[0].ascii_str().to_lower() != 'n'\n}\n\nfn confirm_or_exit(msg string) {\n\tif !ask(msg) {\n\t\texit(1)\n\t}\n}\n\nfn main() {\n\tunbuffer_stdout()\n\tmut compiler_args := []string{}\n\tmut file_path := ''\n\tis_verbose := '-v' in os.args\n\tis_yes := '-y' in os.args\n\n\tfor arg in os.args[1..] {\n\t\tif arg == 'bug' {\n\t\t\tcontinue\n\t\t}\n\t\tif arg.ends_with('.v') || arg.ends_with('.vsh') || arg.ends_with('.vv') {\n\t\t\tif file_path != '' {\n\t\t\t\telog('> v bug: only one V file can be submitted')\n\t\t\t\texit(1)\n\t\t\t}\n\t\t\tfile_path = arg\n\t\t} else {\n\t\t\tif arg !in ['-y', '-v'] {\n\t\t\t\tcompiler_args << arg\n\t\t\t}\n\t\t}\n\t}\n\n\tif file_path == '' {\n\t\telog('> v bug: no v file listed to report')\n\t\texit(1)\n\t}\n\n\tos.unsetenv('VCOLORS')\n\t// collect error information\n\t// output from `v doctor`\n\tvdoctor_output := get_vdoctor_output(is_verbose)\n\t// file content\n\tfile_content := os.read_file(file_path) or {\n\t\telog('> unable to get file \"${file_path}\" content: ${err}')\n\t\t''\n\t}\n\n\tuser_args := compiler_args.join(' ')\n\tmut generated_file := file_path.all_before_last('.')\n\tif os.user_os() == 'windows' {\n\t\tgenerated_file += '.exe'\n\t}\n\tbuild_output := get_v_build_output(is_verbose, is_yes, file_path, user_args, generated_file)\n\n\t// ask the user if he wants to submit even after an error\n\tif !is_yes && (vdoctor_output == '' || file_content == '' || build_output == '') {\n\t\telog('> Error while retrieving the information.')\n\t\tconfirm_or_exit('Do you want to continue?')\n\t}\n\n\texpected_result := readline.read_line('What did you expect to see? ') or {\n\t\t// Ctrl-C was pressed\n\t\telog('\\nCanceled')\n\t\texit(1)\n\t}\n\t// open prefilled issue creation page, or print link as a fallback\n\n\tif !is_yes && vdoctor_output.contains('behind V master') {\n\t\tolog('> It looks like your installation of V is outdated.')\n\t\tolog('> We advise you to run `v up` before submitting an issue.')\n\t\tconfirm_or_exit('Are you sure you want to continue?')\n\t}\n\n\t// When updating this template, make sure to update `.github/ISSUE_TEMPLATE/bug_report.md` too\n\traw_body := '<!-- It is advisable to update all relevant modules using `v outdated` and `v install` -->\n\n<details>\n<summary>V version: ${vversion()}, press to see full `v doctor` output</summary>\n\n${vdoctor_output}\n</details>\n\n**What did you do?**\n`./v -g -o vdbg cmd/v && ./vdbg ${user_args} ${file_path} && ${os.real_path(generated_file)}`\n{file_content}\n\n**What did you see?**\n```\n${build_output}```\n\n**What did you expect to see?**\n\n${expected_result}\n\n'\n\tmut encoded_body := urllib.query_escape(raw_body.replace_once('{file_content}', '```v\\n${file_content}\\n```'))\n\tmut generated_uri := 'https://github.com/vlang/v/issues/new?labels=Bug&body=${encoded_body}'\n\tif generated_uri.len > 8192 {\n\t\t// GitHub doesn't support URLs longer than 8192 characters\n\t\tencoded_body = urllib.query_escape(raw_body.replace_once('{file_content}', 'See attached file `${file_path}`'))\n\t\tgenerated_uri = 'https://github.com/vlang/v/issues/new?labels=Bug&body=${encoded_body}'\n\t\telog('> Your file is too big to be submitted.')\n\t\telog('> Go to the following URL, and attach your file:')\n\t\tolog(generated_uri)\n\t} else {\n\t\tos.open_uri(generated_uri) or {\n\t\t\tif is_verbose {\n\t\t\t\telog(err.str())\n\t\t\t}\n\t\t\tolog(generated_uri)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vbuild-examples.v",
    "content": "module main\n\nimport os\nimport testing\n\nconst vroot = os.dir(os.real_path(os.getenv_opt('VEXE') or { @VEXE }))\n\n// build as a project folder\nconst efolders = [\n\t'examples/viewer',\n\t'examples/vweb_orm_jwt',\n\t'examples/vweb_fullstack',\n\t'examples/fasthttp',\n]\n\npub fn normalised_vroot_path(path string) string {\n\treturn os.real_path(os.join_path_single(vroot, path)).replace('\\\\', '/')\n}\n\nfn main() {\n\targs_string := os.args[1..].join(' ')\n\tparams := args_string.all_before('build-examples')\n\tmut skip_prefixes := efolders.map(normalised_vroot_path(it))\n\tres := testing.v_build_failing_skipped(params, 'examples', skip_prefixes, fn (mut session testing.TestSession) {\n\t\tfor x in efolders {\n\t\t\tpathsegments := x.split_any('/')\n\t\t\tsession.add(os.real_path(os.join_path(vroot, ...pathsegments)))\n\t\t}\n\t})\n\tif res {\n\t\texit(1)\n\t}\n\tif testing.v_build_failing_skipped(params + '-live', os.join_path_single('examples',\n\t\t'hot_reload'), skip_prefixes, fn (mut session testing.TestSession) {})\n\t{\n\t\texit(1)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vbuild-tools.v",
    "content": "module main\n\nimport os\nimport testing\nimport v.util\n\n// Note: tools like vdoc are compiled in their own subfolder\n// => cmd/tools/vdoc/vdoc.exe\n// Usually, they have several top level .v files in the subfolder,\n// that cannot be compiled separately, but instead, the whole folder,\n// should be compiled (v folder).\n// To implement that, these folders are initially skipped, then added\n// as a whole *after the testing.prepare_test_session call*.\nconst tools_in_subfolders = ['vast', 'vcreate', 'vdoc', 'vpm', 'vsymlink', 'vvet', 'vwhere', 'vcover']\n\n// non_packaged_tools are tools that should not be packaged with\n// prebuild versions of V, to keep the size smaller.\n// They are mainly useful for the V project itself, not to end users.\nconst non_packaged_tools = ['gen1m', 'gen_vc', 'fast', 'wyhash']\n\nfn main() {\n\tif os.getenv('VTEST_SANDBOXED_PACKAGING') == '' {\n\t\tutil.ensure_modules_for_all_tools_are_installed('-v' in os.args)\n\t}\n\targs_string := os.args[1..].join(' ')\n\tvexe := os.getenv('VEXE')\n\tvroot := os.dir(vexe)\n\tos.chdir(vroot)!\n\tfolder := os.join_path('cmd', 'tools')\n\ttfolder := os.join_path(vroot, 'cmd', 'tools')\n\tmain_label := 'Building ${folder} ...'\n\tfinish_label := 'building ${folder}'\n\n\tmut skips := []string{}\n\tfor stool in tools_in_subfolders {\n\t\tskips << os.join_path(tfolder, stool).replace('\\\\', '/')\n\t}\n\tbuildopts := args_string.all_before('build-tools')\n\tmut session := testing.prepare_test_session(buildopts, folder, skips, main_label)\n\tsession.rm_binaries = false\n\tsession.build_tools = true\n\tfor stool in tools_in_subfolders {\n\t\tsession.add(os.join_path(tfolder, stool))\n\t}\n\t// eprintln('> session.files: ${session.files}')\n\t// eprintln('> session.skip_files: ${session.skip_files}')\n\tsession.test()\n\teprintln(session.benchmark.total_message(finish_label))\n\tif session.failed_cmds.len > 0 {\n\t\texit(1)\n\t}\n\n\tmut executables := os.ls(session.vtmp_dir)!\n\texecutables.sort()\n\tfor texe in executables {\n\t\ttname := texe.replace(os.file_ext(texe), '')\n\t\tif tname in non_packaged_tools {\n\t\t\tcontinue\n\t\t}\n\t\t//\n\t\ttpath := os.join_path(session.vtmp_dir, texe)\n\t\tif texe.ends_with('_builder') || texe.ends_with('_builder.exe') {\n\t\t\tos.mv_by_cp(tpath, os.join_path(tfolder, 'builders', texe)) or { panic(err) }\n\t\t\tcontinue\n\t\t}\n\t\tif tname in tools_in_subfolders {\n\t\t\tos.mv_by_cp(tpath, os.join_path(tfolder, tname, texe)) or { panic(err) }\n\t\t\tcontinue\n\t\t}\n\t\tif os.is_dir(tpath) {\n\t\t\tcontinue\n\t\t}\n\t\ttarget_path := os.join_path(tfolder, texe)\n\t\tos.mv_by_cp(tpath, target_path) or {\n\t\t\temsg := err.msg()\n\t\t\tif !emsg.contains('vbuild-tools') && !emsg.contains('vtest-all') {\n\t\t\t\teprintln('error while moving ${tpath} to ${target_path}: ${emsg}')\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vbuild-vbinaries.v",
    "content": "module main\n\nimport testing\n\nfn main() {\n\tif testing.building_any_v_binaries_failed() {\n\t\texit(1)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vbump.v",
    "content": "// Copyright (c) 2019-2024 Subhomoy Haldar. All rights reserved.\n// Use of this source code is governed by an MIT license that can be found in the LICENSE file.\nmodule main\n\nimport flag\nimport os\nimport regex\nimport semver\n\nconst tool_name = os.file_name(os.executable())\nconst tool_version = '0.1.0'\nconst tool_description = '\\n  Bump the semantic version of the v.mod and/or specified files.\n\n  The first instance of a version number is replaced with the new version.\n  Additionally, the line affected must contain the word \"version\" in any\n  form of capitalization. For instance, the following lines will be\n  recognized by the heuristic:\n\n    tool_version = \\'1.2.1\\'\n    version: \\'0.2.42\\'\n    VERSION = \"1.23.8\"\n\n  If certain lines need to be skipped, use the --skip option. For instance,\n  the following command will skip lines containing \"tool-version\":\n\n    v bump --patch --skip \"tool-version\" [files...]\n\nExamples:\n  Bump the patch version in v.mod if it exists\n    v bump --patch\n  Bump the major version in v.mod and vls.v\n    v bump --major v.mod vls.v\n  Upgrade the minor version in sample.v only\n    v bump --minor sample.v\n'\n\nconst semver_query = r'((0)|([1-9]\\d*)\\.){2}(0)|([1-9]\\d*)(\\-[\\w\\d\\.\\-_]+)?(\\+[\\w\\d\\.\\-_]+)?'\n\nstruct Options {\n\tshow_help bool\n\tmajor     bool\n\tminor     bool\n\tpatch     bool\n\tskip      string\n}\n\ntype ReplacementFunction = fn (re regex.RE, input string, start int, end int) string\n\nfn replace_with_increased_patch_version(re regex.RE, input string, start int, end int) string {\n\tversion := semver.from(input[start..end]) or { return input }\n\treturn version.increment(.patch).str()\n}\n\nfn replace_with_increased_minor_version(re regex.RE, input string, start int, end int) string {\n\tversion := semver.from(input[start..end]) or { return input }\n\treturn version.increment(.minor).str()\n}\n\nfn replace_with_increased_major_version(re regex.RE, input string, start int, end int) string {\n\tversion := semver.from(input[start..end]) or { return input }\n\treturn version.increment(.major).str()\n}\n\nfn get_replacement_function(options Options) ReplacementFunction {\n\tif options.patch {\n\t\treturn replace_with_increased_patch_version\n\t} else if options.minor {\n\t\treturn replace_with_increased_minor_version\n\t} else if options.major {\n\t\treturn replace_with_increased_major_version\n\t}\n\treturn replace_with_increased_patch_version\n}\n\nfn process_file(input_file string, options Options) ! {\n\tlines := os.read_lines(input_file) or { return error('Failed to read file: ${input_file}') }\n\n\tmut re := regex.regex_opt(semver_query) or { return error('Could not create a RegEx parser.') }\n\n\trepl_fn := get_replacement_function(options)\n\n\tmut new_lines := []string{cap: lines.len}\n\tmut replacement_complete := false\n\n\tfor line in lines {\n\t\t// Copy over the remaining lines normally if the replacement is complete\n\t\tif replacement_complete {\n\t\t\tnew_lines << line\n\t\t\tcontinue\n\t\t}\n\n\t\t// Check if replacement is necessary\n\t\tupdated_line := if line.to_lower().contains('version') && !(options.skip != ''\n\t\t\t&& line.contains(options.skip)) {\n\t\t\treplacement_complete = true\n\t\t\tre.replace_by_fn(line, repl_fn)\n\t\t} else {\n\t\t\tline\n\t\t}\n\t\tnew_lines << updated_line\n\t}\n\n\t// Add a trailing newline\n\tnew_lines << ''\n\n\tbackup_file := input_file + '.cache'\n\n\t// Remove the backup file if it exists.\n\tos.rm(backup_file) or {}\n\n\t// Rename the original to the backup.\n\tos.mv(input_file, backup_file) or { return error('Failed to move file: ${input_file}') }\n\n\t// Process the old file and write it back to the original.\n\tos.write_file(input_file, new_lines.join_lines()) or {\n\t\treturn error('Failed to write file: ${input_file}')\n\t}\n\n\t// Remove the backup file.\n\tos.rm(backup_file) or {}\n\n\tif replacement_complete {\n\t\tprintln('Bumped version in ${input_file}')\n\t} else {\n\t\tprintln('No changes made in ${input_file}')\n\t}\n}\n\nfn main() {\n\tif os.args.len < 2 {\n\t\teprintln('Usage: ${tool_name} [options] [file1 file2 ...]\n${tool_description}\nTry ${tool_name} -h for more help...')\n\t\texit(1)\n\t}\n\n\tmut fp := flag.new_flag_parser(os.args)\n\n\tfp.application(tool_name)\n\tfp.version(tool_version)\n\tfp.description(tool_description)\n\tfp.arguments_description('[file1 file2 ...]')\n\tfp.skip_executable()\n\n\toptions := Options{\n\t\tshow_help: fp.bool('help', `h`, false, 'Show this help text.')\n\t\tpatch:     fp.bool('patch', `p`, false, 'Bump the patch version.')\n\t\tminor:     fp.bool('minor', `n`, false, 'Bump the minor version.')\n\t\tmajor:     fp.bool('major', `m`, false, 'Bump the major version.')\n\t\tskip:      fp.string('skip', `s`, '', 'Skip lines matching this substring.').trim_space()\n\t}\n\n\tremaining := fp.finalize() or {\n\t\teprintln(fp.usage())\n\t\texit(1)\n\t}\n\n\tif options.show_help {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\n\tvalidate_options(options) or {\n\t\teprintln(fp.usage())\n\t\texit(1)\n\t}\n\n\tfiles := remaining[1..]\n\n\tif files.len == 0 {\n\t\tif !os.exists('v.mod') {\n\t\t\teprintln('v.mod does not exist. You can create one using \"v init\".')\n\t\t\texit(1)\n\t\t}\n\t\tprocess_file('v.mod', options) or {\n\t\t\teprintln('Failed to process v.mod: ${err}')\n\t\t\texit(1)\n\t\t}\n\t}\n\n\tfor input_file in files {\n\t\tif !os.exists(input_file) {\n\t\t\teprintln('File not found: ${input_file}')\n\t\t\texit(1)\n\t\t}\n\t\tprocess_file(input_file, options) or {\n\t\t\teprintln('Failed to process ${input_file}: ${err}')\n\t\t\texit(1)\n\t\t}\n\t}\n}\n\nfn validate_options(options Options) ! {\n\tif options.patch && options.major {\n\t\treturn error('Cannot specify both --patch and --major.')\n\t}\n\n\tif options.patch && options.minor {\n\t\treturn error('Cannot specify both --patch and --minor.')\n\t}\n\n\tif options.major && options.minor {\n\t\treturn error('Cannot specify both --major and --minor.')\n\t}\n\n\tif !(options.patch || options.major || options.minor) {\n\t\treturn error('Must specify one of --patch, --major, or --minor.')\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vbump_test.v",
    "content": "import os\n\nconst vexe = @VEXE\nconst tfolder = os.join_path(os.vtmp_dir(), 'vbump')\n\nfn testsuite_begin() {\n\tos.mkdir_all(tfolder) or {}\n}\n\nfn testsuite_end() {\n\tos.rmdir_all(tfolder) or {}\n}\n\nstruct BumpTestCase {\n\tfile_name      string\n\tcontents       string\n\tline           int\n\texpected_patch string\n\texpected_minor string\n\texpected_major string\n}\n\nconst test_cases = [\n\tBumpTestCase{\n\t\tfile_name:      'v.mod'\n\t\tcontents:       \"Module {\n\tname: 'Sample'\n\tdescription: 'Sample project'\n\tversion: '1.2.6'\n\tlicense: 'MIT'\n\tdependencies: []\n}\n\n\"\n\t\tline:           3\n\t\texpected_patch: \"\tversion: '1.2.7'\"\n\t\texpected_minor: \"\tversion: '1.3.0'\"\n\t\texpected_major: \"\tversion: '2.0.0'\"\n\t},\n\tBumpTestCase{\n\t\tfile_name:      'random_versions.vv'\n\t\tcontents:       \"\n1.1.2\n1.2.5\n3.21.73\nversion = '1.5.1'\n\n\"\n\t\tline:           4\n\t\texpected_patch: \"version = '1.5.2'\"\n\t\texpected_minor: \"version = '1.6.0'\"\n\t\texpected_major: \"version = '2.0.0'\"\n\t},\n\tBumpTestCase{\n\t\tfile_name:      'sample_tool.v'\n\t\tcontents:       \"// Module comment and copyright information\nimport os\nimport flag\n\nconst tool_name = os.file_name(os.executable())\nconst tool_version = '0.1.33'\n\nfn main() {\n\t// stuff\n}\n\t\"\n\t\tline:           5\n\t\texpected_patch: \"const tool_version = '0.1.34'\"\n\t\texpected_minor: \"const tool_version = '0.2.0'\"\n\t\texpected_major: \"const tool_version = '1.0.0'\"\n\t},\n]\n\nfn run_individual_test(case BumpTestCase) ! {\n\ttest_file := os.join_path_single(tfolder, case.file_name)\n\n\tos.rm(test_file) or {}\n\tos.write_file(test_file, case.contents)!\n\n\tos.execute_or_exit('${os.quoted_path(vexe)} bump --patch ${os.quoted_path(test_file)}')\n\tpatch_lines := os.read_lines(test_file)!\n\tassert patch_lines[case.line] == case.expected_patch\n\n\tos.execute_or_exit('${os.quoted_path(vexe)} bump --minor ${os.quoted_path(test_file)}')\n\tminor_lines := os.read_lines(test_file)!\n\tassert minor_lines[case.line] == case.expected_minor\n\n\tos.execute_or_exit('${os.quoted_path(vexe)} bump --major ${os.quoted_path(test_file)}')\n\tmajor_lines := os.read_lines(test_file)!\n\tassert major_lines[case.line] == case.expected_major\n\n\tos.rm(test_file)!\n}\n\nfn test_all_bump_cases() {\n\tfor case in test_cases {\n\t\trun_individual_test(case) or { panic(err) }\n\t}\n}\n\nstruct SkipTestCase {\n\tfile_name      string\n\tcontents       string\n\tskip           string\n\tline           int\n\texpected_patch string\n\texpected_minor string\n\texpected_major string\n}\n\nconst skip_test_cases = [\n\tSkipTestCase{\n\t\tfile_name:      'CITATION.cff'\n\t\tcontents:       'abstract: A sample CLI tool made in V that prints geometric shapes to the screen.\nauthors:\n  - alias: hungrybluedev\n    family-names: Haldar\n    given-names: Subhomoy\ncff-version: 1.2.0\ndate-released: 2023-04-20\nlicense: MIT\nmessage: Please cite this software using these information.\nrepository-code: https://github.com/hungrybluedev/geo\ntitle: geo\nurl: https://github.com/hungrybluedev/geo\nversion: 0.2.4\n'\n\t\tline:           12\n\t\tskip:           'cff-version'\n\t\texpected_patch: 'version: 0.2.5'\n\t\texpected_minor: 'version: 0.3.0'\n\t\texpected_major: 'version: 1.0.0'\n\t},\n]\n\nfn run_skip_test(case SkipTestCase) ! {\n\ttest_file := os.join_path_single(tfolder, case.file_name)\n\n\tos.rm(test_file) or {}\n\tos.write_file(test_file, case.contents)!\n\n\tos.execute_or_exit('${os.quoted_path(vexe)} bump --patch --skip=\"${case.skip}\" ${os.quoted_path(test_file)}')\n\tpatch_lines := os.read_lines(test_file)!\n\tassert patch_lines[case.line] == case.expected_patch\n\n\tos.execute_or_exit('${os.quoted_path(vexe)} bump --minor --skip=\"${case.skip}\" ${os.quoted_path(test_file)}')\n\tminor_lines := os.read_lines(test_file)!\n\tassert minor_lines[case.line] == case.expected_minor\n\n\tos.execute_or_exit('${os.quoted_path(vexe)} bump --major --skip=\"${case.skip}\" ${os.quoted_path(test_file)}')\n\tmajor_lines := os.read_lines(test_file)!\n\tassert major_lines[case.line] == case.expected_major\n\n\tos.rm(test_file)!\n}\n\nfn test_all_skip_bump_cases() ! {\n\tfor case in skip_test_cases {\n\t\trun_skip_test(case) or { panic(err) }\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vcheck-md.v",
    "content": "// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nmodule main\n\nimport os\nimport os.cmdline\nimport rand\nimport term\nimport v.help\nimport regex\n\nconst too_long_line_length_example = 120\nconst too_long_line_length_codeblock = 120\nconst too_long_line_length_table = 160\nconst too_long_line_length_link = 250\nconst too_long_line_length_other = 100\nconst term_colors = term.can_show_color_on_stderr()\nconst hide_warnings = '-hide-warnings' in os.args || '-w' in os.args\nconst show_progress = os.getenv('GITHUB_JOB') == '' && '-silent' !in os.args\nconst non_option_args = cmdline.only_non_options(os.args[2..])\nconst is_verbose = os.getenv('VERBOSE') != ''\nconst vcheckfolder = os.join_path(os.vtmp_dir(), 'vcheck_${os.getpid()}')\nconst should_autofix = os.getenv('VAUTOFIX') != '' || '-fix' in os.args\nconst vexe = @VEXE\n\nstruct CheckResult {\npub mut:\n\tfiles    int\n\tlines    int\n\texamples int\n\toks      int\n\twarnings int\n\tferrors  int\n\terrors   int\n}\n\nstruct VCheckIgnoreRule {\n\tbase_dir string\n\tpattern  string\n}\n\nstruct VCheckIgnoreContext {\n\trepo_root string\n}\n\nstruct VCheckIgnoreMatch {\n\tignore_file string\n\tpattern     string\n}\n\nstruct MDPathScanResult {\n\tfiles   []string\n\tskipped int\n}\n\nfn (v1 CheckResult) + (v2 CheckResult) CheckResult {\n\treturn CheckResult{\n\t\tfiles:    v1.files + v2.files\n\t\tlines:    v1.lines + v2.lines\n\t\texamples: v1.examples + v2.examples\n\t\toks:      v1.oks + v2.oks\n\t\twarnings: v1.warnings + v2.warnings\n\t\tferrors:  v1.ferrors + v2.ferrors\n\t\terrors:   v1.errors + v2.errors\n\t}\n}\n\nfn main() {\n\tunbuffer_stdout()\n\tif non_option_args.len == 0 || '-help' in os.args {\n\t\thelp.print_and_exit('check-md')\n\t}\n\tif '-all' in os.args {\n\t\tprintln('´-all´ flag is deprecated. Please use ´v check-md .´ instead.')\n\t\texit(1)\n\t}\n\tmut skip_line_length_check := '-skip-line-length-check' in os.args\n\tmut files_paths := non_option_args.clone()\n\tmut res := CheckResult{}\n\tif term_colors {\n\t\tos.setenv('VCOLORS', 'always', true)\n\t}\n\tos.mkdir_all(vcheckfolder, mode: 0o700) or {} // keep directory private\n\tdefer {\n\t\tos.rmdir_all(vcheckfolder) or {}\n\t}\n\tmut all_mdfiles := []MDFile{}\n\tmut skipped_mdfiles := 0\n\tfor i := 0; i < files_paths.len; i++ {\n\t\tfile_path := files_paths[i]\n\t\tif os.is_dir(file_path) {\n\t\t\tscan_result := md_file_paths(file_path)\n\t\t\tfiles_paths << scan_result.files\n\t\t\tskipped_mdfiles += scan_result.skipped\n\t\t\tcontinue\n\t\t}\n\t\treal_path := os.real_path(file_path)\n\t\tlines := os.read_lines(real_path) or {\n\t\t\tprintln('\"${file_path}\" does not exist')\n\t\t\tres.warnings++\n\t\t\tcontinue\n\t\t}\n\t\tall_mdfiles << MDFile{\n\t\t\tskip_line_length_check: skip_line_length_check\n\t\t\tpath:                   file_path\n\t\t\tlines:                  lines\n\t\t}\n\t}\n\tprintln('> Found: ${all_mdfiles.len} .md files. Skipped by .vcheckignore: ${skipped_mdfiles}.')\n\tif is_verbose {\n\t\tfor idx, mdfile in all_mdfiles {\n\t\t\tprintln('> file ${idx + 1} is ${mdfile.path}')\n\t\t}\n\t}\n\tif show_progress {\n\t\t// this is intended to be replaced by the progress lines\n\t\tprintln('')\n\t}\n\tfor idx, mut mdfile in all_mdfiles {\n\t\tmdfile.idx = idx\n\t\tmdfile.nfiles = all_mdfiles.len\n\t\tres += mdfile.check()\n\t}\n\tif res.errors == 0 && show_progress {\n\t\tclear_previous_line()\n\t}\n\tprintln('Checked .md files: ${res.files} | Ex.: ${res.examples} | Lines: ${res.lines} | OKs: ${res.oks} | Warnings: ${res.warnings} | Errors: ${res.errors} | Fmt errors: ${res.ferrors}')\n\tif res.ferrors > 0 && !should_autofix {\n\t\tprintln('Note: you can use `VAUTOFIX=1 v check-md file.md`, or `v check-md -fix file.md`,')\n\t\tprintln('      to fix the V formatting errors in the markdown code blocks, when possible.')\n\t\tprintln('      Run the command 2 times, to verify that all formatting errors were fixed.')\n\t\tprintln('Note: `v help check-md` shows a list of ```v fence keywords (for partial code).')\n\t}\n\tif res.errors > 0 {\n\t\texit(1)\n\t}\n}\n\nfn md_file_paths(dir string) MDPathScanResult {\n\tmut files_to_check := []string{}\n\tmut skipped := 0\n\tvcheckignore := collect_vcheckignore_context(dir)\n\tmd_files := os.walk_ext(dir, '.md')\n\tfor file in md_files {\n\t\tnfile := file.replace('\\\\', '/')\n\t\tif nfile.contains_any_substr(['/thirdparty/', 'CHANGELOG', '/testdata/']) {\n\t\t\tcontinue\n\t\t}\n\t\tif skip_match := vcheckignore.skip_match(file) {\n\t\t\tif is_verbose {\n\t\t\t\tprintln('SKIP: ${vcheckignore.repo_relative_path(file)} (from ${vcheckignore.repo_relative_path(skip_match.ignore_file)}: ${skip_match.pattern})')\n\t\t\t}\n\t\t\tskipped++\n\t\t\tcontinue\n\t\t}\n\t\tfiles_to_check << file\n\t}\n\treturn MDPathScanResult{\n\t\tfiles:   files_to_check\n\t\tskipped: skipped\n\t}\n}\n\nfn collect_vcheckignore_context(cwd string) VCheckIgnoreContext {\n\trepo_root := find_repo_root(cwd)\n\treturn VCheckIgnoreContext{\n\t\trepo_root: repo_root\n\t}\n}\n\nfn find_repo_root(cwd string) string {\n\tmut dir := os.real_path(cwd)\n\tfor {\n\t\tif os.exists(os.join_path(dir, '.git')) {\n\t\t\treturn dir\n\t\t}\n\t\tparent := os.dir(dir)\n\t\tif parent == dir || parent == '' {\n\t\t\treturn dir\n\t\t}\n\t\tdir = parent\n\t}\n\treturn dir\n}\n\nfn (ctx VCheckIgnoreContext) skip_match(file_path string) ?VCheckIgnoreMatch {\n\tfile := os.real_path(file_path).replace('\\\\', '/')\n\tmut dir := os.dir(file)\n\trepo_root := ctx.repo_root.replace('\\\\', '/')\n\tfor {\n\t\tignore_path := os.join_path(dir, '.vcheckignore')\n\t\tif os.is_file(ignore_path) {\n\t\t\tlines := os.read_lines(ignore_path) or { []string{} }\n\t\t\tfor line in lines {\n\t\t\t\tpattern := normalize_vcheckignore_line(line)\n\t\t\t\tif pattern == '' || pattern.starts_with('#') {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif matches_vcheckignore_rule(file, VCheckIgnoreRule{\n\t\t\t\t\tbase_dir: dir\n\t\t\t\t\tpattern:  pattern\n\t\t\t\t})\n\t\t\t\t{\n\t\t\t\t\treturn VCheckIgnoreMatch{\n\t\t\t\t\t\tignore_file: ignore_path\n\t\t\t\t\t\tpattern:     pattern\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif dir.replace('\\\\', '/') == repo_root {\n\t\t\tbreak\n\t\t}\n\t\tparent := os.dir(dir)\n\t\tif parent == dir || parent == '' {\n\t\t\tbreak\n\t\t}\n\t\tdir = parent\n\t}\n\treturn none\n}\n\nfn normalize_vcheckignore_line(line string) string {\n\ttrimmed := line.trim_space()\n\tif trimmed == '' {\n\t\treturn ''\n\t}\n\tif comment_idx := trimmed.index('#') {\n\t\treturn trimmed[..comment_idx].trim_space()\n\t}\n\treturn trimmed\n}\n\nfn (ctx VCheckIgnoreContext) repo_relative_path(file_path string) string {\n\tfile := os.real_path(file_path).replace('\\\\', '/')\n\troot := ctx.repo_root.replace('\\\\', '/')\n\troot_prefix := root + '/'\n\tif file.starts_with(root_prefix) {\n\t\treturn file.all_after(root_prefix)\n\t}\n\treturn file\n}\n\nfn matches_vcheckignore_rule(file string, rule VCheckIgnoreRule) bool {\n\tbase := rule.base_dir.replace('\\\\', '/')\n\tbase_prefix := base + '/'\n\tif !file.starts_with(base_prefix) {\n\t\treturn false\n\t}\n\trelative_file := file.all_after(base_prefix)\n\tmut pattern := rule.pattern.replace('\\\\', '/')\n\tif pattern.starts_with('!') {\n\t\treturn false\n\t}\n\tmut anchored := false\n\tif pattern.starts_with('/') {\n\t\tanchored = true\n\t\tpattern = pattern.trim_left('/')\n\t}\n\tif pattern.ends_with('/') {\n\t\tpattern = pattern.trim_right('/')\n\t\treturn matches_vcheckignore_directory_pattern(relative_file, pattern, anchored)\n\t}\n\tif anchored {\n\t\treturn relative_file.match_glob(pattern)\n\t}\n\tif pattern.contains('/') {\n\t\treturn relative_file.match_glob(pattern)\n\t}\n\treturn os.file_name(relative_file).match_glob(pattern)\n}\n\nfn matches_vcheckignore_directory_pattern(relative_file string, pattern string, anchored bool) bool {\n\tmut relative_dir := os.dir(relative_file).replace('\\\\', '/')\n\tif relative_dir == '.' || relative_dir == '' {\n\t\treturn false\n\t}\n\tif anchored {\n\t\treturn relative_dir.match_glob(pattern) || relative_dir.match_glob(pattern + '/*')\n\t}\n\tmut candidate := relative_dir\n\tfor {\n\t\tif candidate.match_glob(pattern) || candidate.match_glob(pattern + '/*') {\n\t\t\treturn true\n\t\t}\n\t\tif slash_idx := candidate.index('/') {\n\t\t\tcandidate = candidate[slash_idx + 1..]\n\t\t\tcontinue\n\t\t}\n\t\tbreak\n\t}\n\treturn false\n}\n\nfn wprintln(s string) {\n\tif !hide_warnings {\n\t\tprintln(s)\n\t}\n}\n\nfn ftext(s string, cb fn (string) string) string {\n\tif term_colors {\n\t\treturn cb(s)\n\t}\n\treturn s\n}\n\nfn btext(s string) string {\n\treturn ftext(s, term.bold)\n}\n\nfn mtext(s string) string {\n\treturn ftext(s, term.magenta)\n}\n\nfn rtext(s string) string {\n\treturn ftext(s, term.red)\n}\n\nfn wline(file_path string, lnumber int, column int, message string) string {\n\treturn btext('${file_path}:${lnumber + 1}:${column + 1}:') + btext(mtext(' warn:')) +\n\t\trtext(' ${message}')\n}\n\nfn eline(file_path string, lnumber int, column int, message string) string {\n\treturn btext('${file_path}:${lnumber + 1}:${column + 1}:') + btext(rtext(' error: ${message}'))\n}\n\nconst default_command = 'compile'\n\nstruct VCodeExample {\nmut:\n\ttext    []string\n\tcommand string\n\tsline   int\n\teline   int\n}\n\nenum MDFileParserState {\n\tmarkdown\n\tvexample\n\tcodeblock\n}\n\nstruct MDFile {\n\tpath                   string\n\tskip_line_length_check bool\nmut:\n\tidx      int\n\tnfiles   int\n\tlines    []string\n\texamples []VCodeExample\n\tcurrent  VCodeExample\n\tstate    MDFileParserState = .markdown\n\n\toks      int\n\twarnings int\n\terrors   int // compilation errors + formatting errors\n\tferrors  int // purely formatting errors\n}\n\nfn (mut f MDFile) progress(message string) {\n\tif show_progress {\n\t\tclear_previous_line()\n\t\tprintln('${message} | File ${f.idx + 1:3}/${f.nfiles:-3}: ${f.path}')\n\t}\n}\n\nstruct CheckResultContext {\n\tpath        string\n\tline_number int\n\tline        string\n}\n\nfn (mut f MDFile) wcheck(actual int, limit int, ctx CheckResultContext, msg_template string) {\n\tif actual > limit {\n\t\tfinal := msg_template.replace('@', limit.str()) + ', actual: ' + actual.str()\n\t\twprintln(wline(ctx.path, ctx.line_number, ctx.line.len, final))\n\t\twprintln(ctx.line)\n\t\twprintln(ftext('-'.repeat(limit) + '^', term.gray))\n\t\tf.warnings++\n\t}\n}\n\nfn (mut f MDFile) echeck(actual int, limit int, ctx CheckResultContext, msg_template string) {\n\tif actual > limit {\n\t\tfinal := msg_template.replace('@', limit.str()) + ', actual: ' + actual.str()\n\t\teprintln(eline(ctx.path, ctx.line_number, ctx.line.len, final))\n\t\teprintln(ctx.line)\n\t\teprintln(ftext('-'.repeat(limit) + '^', term.gray))\n\t\tf.errors++\n\t}\n}\n\nfn (mut f MDFile) check() CheckResult {\n\tmut anchor_data := AnchorData{}\n\tfor j, line in f.lines {\n\t\t// f.progress('line: ${j}')\n\t\tif !f.skip_line_length_check {\n\t\t\tctx := CheckResultContext{f.path, j, line}\n\t\t\tif f.state == .vexample {\n\t\t\t\tf.wcheck(line.len, too_long_line_length_example, ctx, 'example lines must be less than @ characters')\n\t\t\t} else if f.state == .codeblock {\n\t\t\t\tf.wcheck(line.len, too_long_line_length_codeblock, ctx, 'code lines must be less than @ characters')\n\t\t\t} else if line.starts_with('|') {\n\t\t\t\tf.wcheck(line.len, too_long_line_length_table, ctx, 'table lines must be less than @ characters')\n\t\t\t} else if line.contains('http') {\n\t\t\t\t// vfmt off\n\t\t\t\tf.wcheck(line.all_after('https').len, too_long_line_length_link, ctx,\t'link lines must be less than @ characters')\n\t\t\t\t// vfmt on\n\t\t\t} else {\n\t\t\t\tf.echeck(line.len, too_long_line_length_other, ctx, 'must be less than @ characters')\n\t\t\t}\n\t\t}\n\t\tif f.state == .markdown {\n\t\t\tanchor_data.add_links(j, line)\n\t\t\tanchor_data.add_link_targets(j, line)\n\t\t}\n\n\t\tf.parse_line(j, line)\n\t}\n\tf.check_link_target_match(anchor_data)\n\tf.check_examples()\n\treturn CheckResult{\n\t\tfiles:    1\n\t\tlines:    f.lines.len\n\t\texamples: f.examples.len\n\t\toks:      f.oks\n\t\twarnings: f.warnings\n\t\terrors:   f.errors\n\t\tferrors:  f.ferrors\n\t}\n}\n\nfn (mut f MDFile) parse_line(lnumber int, line string) {\n\tif line.starts_with('```v') {\n\t\tif f.state == .markdown {\n\t\t\tf.state = .vexample\n\t\t\tmut command := line.replace('```v', '').trim_space()\n\t\t\tif command == '' {\n\t\t\t\tcommand = default_command\n\t\t\t} else if command == 'nofmt' {\n\t\t\t\tcommand += ' ${default_command}'\n\t\t\t}\n\t\t\tf.current = VCodeExample{\n\t\t\t\tsline:   lnumber\n\t\t\t\tcommand: command\n\t\t\t}\n\t\t}\n\t\treturn\n\t}\n\tif line.starts_with('```') {\n\t\tmatch f.state {\n\t\t\t.vexample {\n\t\t\t\tf.state = .markdown\n\t\t\t\tf.current.eline = lnumber\n\t\t\t\tf.examples << f.current\n\t\t\t\tf.current = VCodeExample{}\n\t\t\t\treturn\n\t\t\t}\n\t\t\t.codeblock {\n\t\t\t\tf.state = .markdown\n\t\t\t\treturn\n\t\t\t}\n\t\t\t.markdown {\n\t\t\t\tf.state = .codeblock\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\tif f.state == .vexample {\n\t\tf.current.text << line\n\t}\n}\n\nstruct Headline {\n\tline  int\n\tlabel string\n\tlevel int\n}\n\nstruct Anchor {\n\tline int\n}\n\ntype AnchorTarget = Anchor | Headline\n\nstruct AnchorLink {\n\tline  int\n\tlabel string\n}\n\nstruct AnchorData {\nmut:\n\tlinks   map[string][]AnchorLink\n\tanchors map[string][]AnchorTarget\n}\n\nfn (mut ad AnchorData) add_links(line_number int, line string) {\n\tquery := r'\\[(?P<label>[^\\]]+)\\]\\(\\s*#(?P<link>[a-z0-9\\-\\_\\x7f-\\uffff]+)\\)'\n\tmut re := regex.regex_opt(query) or { panic(err) }\n\tres := re.find_all_str(line)\n\n\tfor elem in res {\n\t\tre.match_string(elem)\n\t\tlink := re.get_group_by_name(elem, 'link')\n\t\tad.links[link] << AnchorLink{\n\t\t\tline:  line_number\n\t\t\tlabel: re.get_group_by_name(elem, 'label')\n\t\t}\n\t}\n}\n\nfn (mut ad AnchorData) add_link_targets(line_number int, line string) {\n\tif line.trim_space().starts_with('#') {\n\t\tif headline_start_pos := line.index(' ') {\n\t\t\theadline := line.substr(headline_start_pos + 1, line.len)\n\t\t\tlink := create_ref_link(headline)\n\t\t\tad.anchors[link] << Headline{\n\t\t\t\tline:  line_number\n\t\t\t\tlabel: headline\n\t\t\t\tlevel: headline_start_pos\n\t\t\t}\n\t\t}\n\t} else {\n\t\tquery := '<a\\\\s*id=[\"\\'](?P<link>[a-z0-9\\\\-\\\\_\\\\x7f-\\\\uffff]+)[\"\\']\\\\s*/>'\n\t\tmut re := regex.regex_opt(query) or { panic(err) }\n\t\tres := re.find_all_str(line)\n\n\t\tfor elem in res {\n\t\t\tre.match_string(elem)\n\t\t\tlink := re.get_group_by_name(elem, 'link')\n\t\t\tad.anchors[link] << Anchor{\n\t\t\t\tline: line_number\n\t\t\t}\n\t\t}\n\t}\n}\n\nfn (mut f MDFile) check_link_target_match(ad AnchorData) {\n\tmut checked_headlines := []string{}\n\tmut found_error_warning := false\n\tfor link, linkdata in ad.links {\n\t\tif link in ad.anchors {\n\t\t\tchecked_headlines << link\n\t\t\tif ad.anchors[link].len > 1 {\n\t\t\t\tfound_error_warning = true\n\t\t\t\tf.errors++\n\t\t\t\tfor anchordata in ad.anchors[link] {\n\t\t\t\t\teprintln(eline(f.path, anchordata.line, 0, 'multiple link targets of existing link (#${link})'))\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfound_error_warning = true\n\t\t\tf.errors++\n\t\t\tfor brokenlink in linkdata {\n\t\t\t\teprintln(eline(f.path, brokenlink.line, 0, 'no link target found for existing link [${brokenlink.label}](#${link})'))\n\t\t\t}\n\t\t}\n\t}\n\tfor link, anchor_lists in ad.anchors {\n\t\tif link !in checked_headlines {\n\t\t\tif anchor_lists.len > 1 {\n\t\t\t\tfor anchor in anchor_lists {\n\t\t\t\t\tline := match anchor {\n\t\t\t\t\t\tHeadline {\n\t\t\t\t\t\t\tanchor.line\n\t\t\t\t\t\t}\n\t\t\t\t\t\tAnchor {\n\t\t\t\t\t\t\tanchor.line\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\twprintln(wline(f.path, line, 0, 'multiple link target for non existing link (#${link})'))\n\t\t\t\t\tfound_error_warning = true\n\t\t\t\t\tf.warnings++\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif found_error_warning {\n\t\teprintln('') // fix suppressed last error output\n\t}\n}\n\n// based on a reference sample md doc\n// https://github.com/aheissenberger/vlang-markdown-module/blob/master/test.md\nfn create_ref_link(s string) string {\n\tmut result := ''\n\tfor c in s.trim_space() {\n\t\tresult += match c {\n\t\t\t`a`...`z`, `0`...`9` {\n\t\t\t\tc.ascii_str()\n\t\t\t}\n\t\t\t`A`...`Z` {\n\t\t\t\tc.ascii_str().to_lower()\n\t\t\t}\n\t\t\t` `, `-` {\n\t\t\t\t'-'\n\t\t\t}\n\t\t\t`_` {\n\t\t\t\t'_'\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif c > 127 { c.ascii_str() } else { '' }\n\t\t\t}\n\t\t}\n\t}\n\treturn result\n}\n\nfn (mut f MDFile) debug() {\n\tfor e in f.examples {\n\t\teprintln('f.path: ${f.path} | example: ${e}')\n\t}\n}\n\nfn cmdexecute(cmd string) int {\n\tverbose_println(cmd)\n\tres := os.execute(cmd)\n\tif res.exit_code < 0 {\n\t\treturn 1\n\t}\n\tif res.exit_code != 0 {\n\t\teprint(res.output)\n\t}\n\treturn res.exit_code\n}\n\nfn silent_cmdexecute(cmd string) int {\n\tverbose_println(cmd)\n\tres := os.execute(cmd)\n\treturn res.exit_code\n}\n\nfn get_fmt_exit_code(vfile string, vexe string) int {\n\treturn silent_cmdexecute('${os.quoted_path(vexe)} fmt -verify ${os.quoted_path(vfile)}')\n}\n\nfn (mut f MDFile) check_examples() {\n\trecheck_all_examples: for eidx, e in f.examples {\n\t\tif e.command == 'ignore' {\n\t\t\tcontinue\n\t\t}\n\t\tif e.command == 'wip' {\n\t\t\tcontinue\n\t\t}\n\t\tfname := os.base(f.path).replace('.md', '_md')\n\t\tuid := rand.ulid()\n\t\tcfile := os.join_path(vcheckfolder, '${uid}.c')\n\t\tvfile := os.join_path(vcheckfolder, 'check_${fname}_example_${e.sline}__${e.eline}__${uid}.v')\n\t\tefile := os.join_path(vcheckfolder, 'check_${fname}_example_${e.sline}__${e.eline}__${uid}.exe')\n\t\tmut should_cleanup_vfile := true\n\t\t// eprintln('>>> checking example ${vfile} ...')\n\t\tvcontent := e.text.join('\\n') + '\\n'\n\t\tos.write_file(vfile, vcontent) or { panic(err) }\n\t\tmut acommands := e.command.split(' ')\n\t\tnofmt := 'nofmt' in acommands\n\t\tfor command in acommands {\n\t\t\tf.progress('OK: ${f.oks:3}, W: ${f.warnings:2}, E: ${f.errors:2}, F: ${f.ferrors:2}, ex. ${\n\t\t\t\teidx + 1:3}/${f.examples.len:-3}, from line ${e.sline:4} to line ${e.eline:-4} of ${f.lines.len:-4}, command: ${command:12s}')\n\t\t\tfmt_res := if nofmt { 0 } else { get_fmt_exit_code(vfile, vexe) }\n\t\t\tf.ferrors += fmt_res\n\t\t\tmatch command {\n\t\t\t\t'compile' {\n\t\t\t\t\tres := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -o ${os.quoted_path(efile)} ${os.quoted_path(vfile)}')\n\t\t\t\t\tif res != 0 || fmt_res != 0 {\n\t\t\t\t\t\tif res != 0 {\n\t\t\t\t\t\t\teprintln(eline(f.path, e.sline, 0, 'example failed to compile'))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tf.report_not_formatted_example_if_needed(e, fmt_res, vfile) or {\n\t\t\t\t\t\t\tunsafe {\n\t\t\t\t\t\t\t\tgoto recheck_all_examples\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\teprintln(vcontent)\n\t\t\t\t\t\tshould_cleanup_vfile = false\n\t\t\t\t\t\tf.errors++\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tf.oks++\n\t\t\t\t}\n\t\t\t\t'cgen' {\n\t\t\t\t\tres := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')\n\t\t\t\t\tif res != 0 || fmt_res != 0 {\n\t\t\t\t\t\tif res != 0 {\n\t\t\t\t\t\t\teprintln(eline(f.path, e.sline, 0, 'example failed to generate C code'))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tf.report_not_formatted_example_if_needed(e, fmt_res, vfile) or {\n\t\t\t\t\t\t\tunsafe {\n\t\t\t\t\t\t\t\tgoto recheck_all_examples\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\teprintln(vcontent)\n\t\t\t\t\t\tshould_cleanup_vfile = false\n\t\t\t\t\t\tf.errors++\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tf.oks++\n\t\t\t\t}\n\t\t\t\t'globals' {\n\t\t\t\t\tres := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -enable-globals -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')\n\t\t\t\t\tif res != 0 || fmt_res != 0 {\n\t\t\t\t\t\tif res != 0 {\n\t\t\t\t\t\t\teprintln(eline(f.path, e.sline, 0, '`example failed to compile with -enable-globals'))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tf.report_not_formatted_example_if_needed(e, fmt_res, vfile) or {\n\t\t\t\t\t\t\tunsafe {\n\t\t\t\t\t\t\t\tgoto recheck_all_examples\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\teprintln(vcontent)\n\t\t\t\t\t\tshould_cleanup_vfile = false\n\t\t\t\t\t\tf.errors++\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tf.oks++\n\t\t\t\t}\n\t\t\t\t'live' {\n\t\t\t\t\tres := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -live -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')\n\t\t\t\t\tif res != 0 || fmt_res != 0 {\n\t\t\t\t\t\tif res != 0 {\n\t\t\t\t\t\t\teprintln(eline(f.path, e.sline, 0, 'example failed to compile with -live'))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tf.report_not_formatted_example_if_needed(e, fmt_res, vfile) or {\n\t\t\t\t\t\t\tunsafe {\n\t\t\t\t\t\t\t\tgoto recheck_all_examples\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\teprintln(vcontent)\n\t\t\t\t\t\tshould_cleanup_vfile = false\n\t\t\t\t\t\tf.errors++\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tf.oks++\n\t\t\t\t}\n\t\t\t\t'shared' {\n\t\t\t\t\tres := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -shared -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')\n\t\t\t\t\tif res != 0 || fmt_res != 0 {\n\t\t\t\t\t\tif res != 0 {\n\t\t\t\t\t\t\teprintln(eline(f.path, e.sline, 0, 'module example failed to compile with -shared'))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tf.report_not_formatted_example_if_needed(e, fmt_res, vfile) or {\n\t\t\t\t\t\t\tunsafe {\n\t\t\t\t\t\t\t\tgoto recheck_all_examples\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\teprintln(vcontent)\n\t\t\t\t\t\tshould_cleanup_vfile = false\n\t\t\t\t\t\tf.errors++\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tf.oks++\n\t\t\t\t}\n\t\t\t\t'failcompile' {\n\t\t\t\t\tres := silent_cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')\n\t\t\t\t\tif res == 0 || fmt_res != 0 {\n\t\t\t\t\t\tif res == 0 {\n\t\t\t\t\t\t\teprintln(eline(f.path, e.sline, 0, '`failcompile` example compiled'))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tf.report_not_formatted_example_if_needed(e, fmt_res, vfile) or {\n\t\t\t\t\t\t\tunsafe {\n\t\t\t\t\t\t\t\tgoto recheck_all_examples\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\teprintln(vcontent)\n\t\t\t\t\t\tshould_cleanup_vfile = false\n\t\t\t\t\t\tf.errors++\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tf.oks++\n\t\t\t\t}\n\t\t\t\t'oksyntax' {\n\t\t\t\t\tres := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -check-syntax ${os.quoted_path(vfile)}')\n\t\t\t\t\tif res != 0 || fmt_res != 0 {\n\t\t\t\t\t\tif res != 0 {\n\t\t\t\t\t\t\teprintln(eline(f.path, e.sline, 0, '`oksyntax` example with invalid syntax'))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tf.report_not_formatted_example_if_needed(e, fmt_res, vfile) or {\n\t\t\t\t\t\t\tunsafe {\n\t\t\t\t\t\t\t\tgoto recheck_all_examples\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\teprintln(vcontent)\n\t\t\t\t\t\tshould_cleanup_vfile = false\n\t\t\t\t\t\tf.errors++\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tf.oks++\n\t\t\t\t}\n\t\t\t\t'okfmt' {\n\t\t\t\t\tif fmt_res != 0 {\n\t\t\t\t\t\tf.report_not_formatted_example_if_needed(e, fmt_res, vfile) or {\n\t\t\t\t\t\t\tunsafe {\n\t\t\t\t\t\t\t\tgoto recheck_all_examples\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\teprintln(vcontent)\n\t\t\t\t\t\tshould_cleanup_vfile = false\n\t\t\t\t\t\tf.errors++\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tf.oks++\n\t\t\t\t}\n\t\t\t\t'badsyntax' {\n\t\t\t\t\tres := silent_cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -check-syntax ${os.quoted_path(vfile)}')\n\t\t\t\t\tif res == 0 {\n\t\t\t\t\t\teprintln(eline(f.path, e.sline, 0, '`badsyntax` example can be parsed fine'))\n\t\t\t\t\t\teprintln(vcontent)\n\t\t\t\t\t\tshould_cleanup_vfile = false\n\t\t\t\t\t\tf.errors++\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tf.oks++\n\t\t\t\t}\n\t\t\t\t'nofmt' {}\n\t\t\t\t// mark the example as playable inside docs\n\t\t\t\t'play' {}\n\t\t\t\t// same as play, but run example as a test\n\t\t\t\t'play-test' {}\n\t\t\t\t// when ```vmod\n\t\t\t\t'mod' {}\n\t\t\t\telse {\n\t\t\t\t\teprintln(eline(f.path, e.sline, 0, 'unrecognized command: \"${command}\", use one of: wip/ignore/compile/failcompile/okfmt/nofmt/oksyntax/badsyntax/cgen/globals/live/shared'))\n\t\t\t\t\tshould_cleanup_vfile = false\n\t\t\t\t\tf.errors++\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tos.rm(cfile) or {}\n\t\tos.rm(efile) or {}\n\t\tif should_cleanup_vfile {\n\t\t\tos.rm(vfile) or { panic(err) }\n\t\t}\n\t}\n}\n\nfn verbose_println(message string) {\n\tif is_verbose {\n\t\tprintln(message)\n\t}\n}\n\nfn clear_previous_line() {\n\tif is_verbose {\n\t\treturn\n\t}\n\tterm.clear_previous_line()\n}\n\nfn (mut f MDFile) report_not_formatted_example_if_needed(e VCodeExample, fmt_res int, vfile string) ! {\n\tif fmt_res == 0 {\n\t\treturn\n\t}\n\teprintln(eline(f.path, e.sline, 0, 'example is not formatted'))\n\tif !should_autofix {\n\t\treturn\n\t}\n\tf.autofix_example(e, vfile) or {\n\t\tif err is ExampleWasRewritten {\n\t\t\teprintln('>> f.path: ${f.path} | example from ${e.sline} to ${e.eline} was re-formatted by vfmt')\n\t\t\treturn err\n\t\t}\n\t\teprintln('>> f.path: ${f.path} | encountered error while autofixing the example: ${err}')\n\t}\n}\n\nstruct ExampleWasRewritten {\n\tError\n}\n\nfn (mut f MDFile) autofix_example(e VCodeExample, vfile string) ! {\n\teprintln('>>> AUTOFIXING f.path: ${f.path} | e.sline: ${e.sline} | vfile: ${vfile}')\n\tres := cmdexecute('${os.quoted_path(vexe)} fmt -w ${os.quoted_path(vfile)}')\n\tif res != 0 {\n\t\treturn error('could not autoformat the example')\n\t}\n\tformatted_content_lines := os.read_lines(vfile) or { return }\n\tmut new_lines := []string{}\n\tnew_lines << f.lines#[0..e.sline + 1]\n\tnew_lines << formatted_content_lines\n\tnew_lines << f.lines#[e.eline..]\n\tf.update_examples(new_lines)!\n\tos.rm(vfile) or {}\n\tf.examples = f.examples.filter(it.sline >= e.sline)\n\treturn ExampleWasRewritten{}\n}\n\nfn (mut f MDFile) update_examples(new_lines []string) ! {\n\tos.write_file(f.path, new_lines.join('\\n'))!\n\tf.lines = new_lines\n\tf.examples = []\n\tf.current = VCodeExample{}\n\tf.state = .markdown\n\tfor j, line in f.lines {\n\t\tf.parse_line(j, line)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vcheck_test.v",
    "content": "import os\n\nconst vexe = @VEXE\nconst git_exe = os.find_abs_path_of_executable('git') or { '' }\n\nfn test_check_md_respects_vcheckignore() {\n\tif git_exe == '' {\n\t\teprintln('git is required for this test; skipping')\n\t\treturn\n\t}\n\toriginal_wd := os.getwd()\n\tmut repo_dir := os.join_path(os.vtmp_dir(), 'vcheckignore_test_${os.getpid()}')\n\tos.rmdir_all(repo_dir) or {}\n\tos.mkdir_all(repo_dir)!\n\tdefer {\n\t\tos.chdir(original_wd) or {}\n\t\tos.rmdir_all(repo_dir) or {}\n\t}\n\tos.execute_or_exit('${os.quoted_path(git_exe)} init ${os.quoted_path(repo_dir)}')\n\n\twrite_text_file(os.join_path(repo_dir, 'README.md'), '# Root\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'cwd_skip.md'), '# CWD skip\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'skip.md'), '# Skip me\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'sub', 'skip2.md'), '# Skip me too\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'notes', 'keep2.md'), '# Keep 2\\n')!\n\n\twrite_text_file(os.join_path(repo_dir, '.vcheckignore'), 'docs/skip.md\\ndocs/sub/*.md\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', '.vcheckignore'), 'cwd_skip.md\\n')!\n\n\tcheck_cmd := '${os.quoted_path(vexe)} check-md -hide-warnings -silent .'\n\n\troot_res := run_in_dir(repo_dir, check_cmd, true)!\n\tassert root_res.exit_code == 0, root_res.output\n\tassert root_res.output.contains('SKIP: docs/cwd_skip.md'), root_res.output\n\tassert root_res.output.contains('SKIP: docs/skip.md'), root_res.output\n\tassert root_res.output.contains('SKIP: docs/sub/skip2.md'), root_res.output\n\tassert root_res.output.contains('from docs/.vcheckignore: cwd_skip.md'), root_res.output\n\tassert root_res.output.contains('from .vcheckignore: docs/skip.md'), root_res.output\n\tassert root_res.output.contains('from .vcheckignore: docs/sub/*.md'), root_res.output\n\tassert root_res.output.contains('> Found: 2 .md files.'), root_res.output\n\tassert root_res.output.contains('Skipped by .vcheckignore: 3.'), root_res.output\n\tassert root_res.output.contains('Checked .md files: 2 |'), root_res.output\n\troot_non_verbose_res := run_in_dir(repo_dir, check_cmd, false)!\n\tassert root_non_verbose_res.exit_code == 0, root_non_verbose_res.output\n\tassert !root_non_verbose_res.output.contains('SKIP:'), root_non_verbose_res.output\n\n\tdocs_res := run_in_dir(os.join_path(repo_dir, 'docs'), check_cmd, true)!\n\tassert docs_res.exit_code == 0, docs_res.output\n\tassert docs_res.output.contains('SKIP: docs/cwd_skip.md'), docs_res.output\n\tassert docs_res.output.contains('SKIP: docs/skip.md'), docs_res.output\n\tassert docs_res.output.contains('SKIP: docs/sub/skip2.md'), docs_res.output\n\tassert docs_res.output.contains('from docs/.vcheckignore: cwd_skip.md'), docs_res.output\n\tassert docs_res.output.contains('> Found: 0 .md files.'), docs_res.output\n\tassert docs_res.output.contains('Skipped by .vcheckignore: 3.'), docs_res.output\n\tassert docs_res.output.contains('Checked .md files: 0 |'), docs_res.output\n\n\tsub_res := run_in_dir(os.join_path(repo_dir, 'docs', 'sub'), check_cmd, true)!\n\tassert sub_res.exit_code == 0, sub_res.output\n\tassert sub_res.output.contains('SKIP: docs/sub/skip2.md'), sub_res.output\n\tassert !sub_res.output.contains('SKIP: docs/cwd_skip.md'), sub_res.output\n\tassert sub_res.output.contains('from .vcheckignore: docs/sub/*.md'), sub_res.output\n\tassert sub_res.output.contains('> Found: 0 .md files.'), sub_res.output\n\tassert sub_res.output.contains('Skipped by .vcheckignore: 1.'), sub_res.output\n\tassert sub_res.output.contains('Checked .md files: 0 |'), sub_res.output\n}\n\nfn test_check_md_respects_vcheckignore_glob_in_scanned_dir() {\n\tif git_exe == '' {\n\t\teprintln('git is required for this test; skipping')\n\t\treturn\n\t}\n\toriginal_wd := os.getwd()\n\trepo_dir := os.join_path(os.vtmp_dir(), 'vcheckignore_glob_${os.getpid()}')\n\tos.rmdir_all(repo_dir) or {}\n\tos.mkdir_all(repo_dir)!\n\tdefer {\n\t\tos.chdir(original_wd) or {}\n\t\tos.rmdir_all(repo_dir) or {}\n\t}\n\tos.execute_or_exit('${os.quoted_path(git_exe)} init ${os.quoted_path(repo_dir)}')\n\n\twrite_text_file(os.join_path(repo_dir, 'doc', 'plans', 'ignored1.md'), '# ignored\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'doc', 'plans', 'ignored2.md'), '# ignored\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'doc', 'plans', 'ignored3.md'), '# ignored\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'doc', 'plans', 'keep1.md'), '# keep\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'doc', 'plans', 'keep2.md'), '# keep\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'doc', 'plans', 'keep3.md'), '# keep\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'doc', 'plans', '.vcheckignore'), 'ignored*.md\\n')!\n\n\tres := run_in_dir(repo_dir, '${os.quoted_path(vexe)} check-md -hide-warnings -silent doc/plans',\n\t\ttrue)!\n\tassert res.exit_code == 0, res.output\n\tassert res.output.contains('SKIP: doc/plans/ignored1.md'), res.output\n\tassert res.output.contains('SKIP: doc/plans/ignored2.md'), res.output\n\tassert res.output.contains('SKIP: doc/plans/ignored3.md'), res.output\n\tassert res.output.contains('from doc/plans/.vcheckignore: ignored*.md'), res.output\n\tassert res.output.contains('> Found: 3 .md files.'), res.output\n\tassert res.output.contains('Skipped by .vcheckignore: 3.'), res.output\n\tassert res.output.contains('Checked .md files: 3 |'), res.output\n}\n\nfn test_check_md_respects_vcheckignore_anchored_pattern() {\n\tif git_exe == '' {\n\t\teprintln('git is required for this test; skipping')\n\t\treturn\n\t}\n\toriginal_wd := os.getwd()\n\trepo_dir := os.join_path(os.vtmp_dir(), 'vcheckignore_anchored_${os.getpid()}')\n\tos.rmdir_all(repo_dir) or {}\n\tos.mkdir_all(repo_dir)!\n\tdefer {\n\t\tos.chdir(original_wd) or {}\n\t\tos.rmdir_all(repo_dir) or {}\n\t}\n\tos.execute_or_exit('${os.quoted_path(git_exe)} init ${os.quoted_path(repo_dir)}')\n\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'root_only.md'), '# ignored by /root_only.md\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'sub', 'root_only.md'), '# should be kept\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'keep.md'), '# keep\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', '.vcheckignore'), '/root_only.md\\n')!\n\n\tres := run_in_dir(repo_dir, '${os.quoted_path(vexe)} check-md -hide-warnings -silent docs',\n\t\ttrue)!\n\tassert res.exit_code == 0, res.output\n\tassert res.output.contains('SKIP: docs/root_only.md'), res.output\n\tassert res.output.contains('from docs/.vcheckignore: /root_only.md'), res.output\n\tassert !res.output.contains('SKIP: docs/sub/root_only.md'), res.output\n\tassert res.output.contains('> Found: 2 .md files.'), res.output\n\tassert res.output.contains('Skipped by .vcheckignore: 1.'), res.output\n\tassert res.output.contains('Checked .md files: 2 |'), res.output\n}\n\nfn test_check_md_respects_vcheckignore_anchored_directory_pattern() {\n\tif git_exe == '' {\n\t\teprintln('git is required for this test; skipping')\n\t\treturn\n\t}\n\toriginal_wd := os.getwd()\n\trepo_dir := os.join_path(os.vtmp_dir(), 'vcheckignore_anchored_dir_${os.getpid()}')\n\tos.rmdir_all(repo_dir) or {}\n\tos.mkdir_all(repo_dir)!\n\tdefer {\n\t\tos.chdir(original_wd) or {}\n\t\tos.rmdir_all(repo_dir) or {}\n\t}\n\tos.execute_or_exit('${os.quoted_path(git_exe)} init ${os.quoted_path(repo_dir)}')\n\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'sub', 'ignored.md'), '# ignored by /sub/\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'nested', 'sub', 'keep.md'), '# kept\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'keep.md'), '# keep\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', '.vcheckignore'), '/sub/\\n')!\n\n\tres := run_in_dir(repo_dir, '${os.quoted_path(vexe)} check-md -hide-warnings -silent docs',\n\t\ttrue)!\n\tassert res.exit_code == 0, res.output\n\tassert res.output.contains('SKIP: docs/sub/ignored.md'), res.output\n\tassert res.output.contains('from docs/.vcheckignore: /sub/'), res.output\n\tassert !res.output.contains('SKIP: docs/nested/sub/keep.md'), res.output\n\tassert res.output.contains('> Found: 2 .md files.'), res.output\n\tassert res.output.contains('Skipped by .vcheckignore: 1.'), res.output\n\tassert res.output.contains('Checked .md files: 2 |'), res.output\n}\n\nfn test_check_md_respects_vcheckignore_non_anchored_directory_pattern() {\n\tif git_exe == '' {\n\t\teprintln('git is required for this test; skipping')\n\t\treturn\n\t}\n\toriginal_wd := os.getwd()\n\trepo_dir := os.join_path(os.vtmp_dir(), 'vcheckignore_non_anchored_dir_${os.getpid()}')\n\tos.rmdir_all(repo_dir) or {}\n\tos.mkdir_all(repo_dir)!\n\tdefer {\n\t\tos.chdir(original_wd) or {}\n\t\tos.rmdir_all(repo_dir) or {}\n\t}\n\tos.execute_or_exit('${os.quoted_path(git_exe)} init ${os.quoted_path(repo_dir)}')\n\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'sub', 'ignored1.md'), '# ignored 1\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'nested', 'sub', 'ignored2.md'), '# ignored 2\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'keep.md'), '# keep\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', '.vcheckignore'), 'sub/\\n')!\n\n\tres := run_in_dir(repo_dir, '${os.quoted_path(vexe)} check-md -hide-warnings -silent docs',\n\t\ttrue)!\n\tassert res.exit_code == 0, res.output\n\tassert res.output.contains('SKIP: docs/sub/ignored1.md'), res.output\n\tassert res.output.contains('SKIP: docs/nested/sub/ignored2.md'), res.output\n\tassert res.output.contains('from docs/.vcheckignore: sub/'), res.output\n\tassert res.output.contains('> Found: 1 .md files.'), res.output\n\tassert res.output.contains('Skipped by .vcheckignore: 2.'), res.output\n\tassert res.output.contains('Checked .md files: 1 |'), res.output\n}\n\nfn test_check_md_respects_vcheckignore_anchored_directory_glob_pattern() {\n\tif git_exe == '' {\n\t\teprintln('git is required for this test; skipping')\n\t\treturn\n\t}\n\toriginal_wd := os.getwd()\n\trepo_dir := os.join_path(os.vtmp_dir(), 'vcheckignore_anchored_dir_glob_${os.getpid()}')\n\tos.rmdir_all(repo_dir) or {}\n\tos.mkdir_all(repo_dir)!\n\tdefer {\n\t\tos.chdir(original_wd) or {}\n\t\tos.rmdir_all(repo_dir) or {}\n\t}\n\tos.execute_or_exit('${os.quoted_path(git_exe)} init ${os.quoted_path(repo_dir)}')\n\n\twrite_text_file(os.join_path(repo_dir, 'docs-a', 'sub', 'ignored1.md'), '# ignored 1\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs-b', 'sub', 'ignored2.md'), '# ignored 2\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'other', 'keep.md'), '# keep\\n')!\n\twrite_text_file(os.join_path(repo_dir, '.vcheckignore'), '/docs-*/\\n')!\n\n\tres := run_in_dir(repo_dir, '${os.quoted_path(vexe)} check-md -hide-warnings -silent .',\n\t\ttrue)!\n\tassert res.exit_code == 0, res.output\n\tassert res.output.contains('SKIP: docs-a/sub/ignored1.md'), res.output\n\tassert res.output.contains('SKIP: docs-b/sub/ignored2.md'), res.output\n\tassert res.output.contains('from .vcheckignore: /docs-*/'), res.output\n\tassert !res.output.contains('SKIP: other/keep.md'), res.output\n\tassert res.output.contains('> Found: 1 .md files.'), res.output\n\tassert res.output.contains('Skipped by .vcheckignore: 2.'), res.output\n\tassert res.output.contains('Checked .md files: 1 |'), res.output\n}\n\nfn test_check_md_respects_vcheckignore_comments_and_blank_lines() {\n\tif git_exe == '' {\n\t\teprintln('git is required for this test; skipping')\n\t\treturn\n\t}\n\toriginal_wd := os.getwd()\n\trepo_dir := os.join_path(os.vtmp_dir(), 'vcheckignore_comments_${os.getpid()}')\n\tos.rmdir_all(repo_dir) or {}\n\tos.mkdir_all(repo_dir)!\n\tdefer {\n\t\tos.chdir(original_wd) or {}\n\t\tos.rmdir_all(repo_dir) or {}\n\t}\n\tos.execute_or_exit('${os.quoted_path(git_exe)} init ${os.quoted_path(repo_dir)}')\n\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'ignored.md'), '# ignored\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'ignored2.md'), '# ignored2\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'keep.md'), '# keep\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', '.vcheckignore'), '# comment\\n\\nignored.md # inline comment\\nignored2.md\\n')!\n\n\tres := run_in_dir(repo_dir, '${os.quoted_path(vexe)} check-md -hide-warnings -silent docs',\n\t\ttrue)!\n\tassert res.exit_code == 0, res.output\n\tassert res.output.contains('SKIP: docs/ignored.md'), res.output\n\tassert res.output.contains('SKIP: docs/ignored2.md'), res.output\n\tassert res.output.contains('from docs/.vcheckignore: ignored.md'), res.output\n\tassert res.output.contains('from docs/.vcheckignore: ignored2.md'), res.output\n\tassert !res.output.contains('SKIP: docs/keep.md'), res.output\n\tassert res.output.contains('> Found: 1 .md files.'), res.output\n\tassert res.output.contains('Skipped by .vcheckignore: 2.'), res.output\n\tassert res.output.contains('Checked .md files: 1 |'), res.output\n}\n\nfn test_check_md_file_argument_does_not_use_vcheckignore_directory_filtering() {\n\tif git_exe == '' {\n\t\teprintln('git is required for this test; skipping')\n\t\treturn\n\t}\n\toriginal_wd := os.getwd()\n\trepo_dir := os.join_path(os.vtmp_dir(), 'vcheckignore_file_argument_${os.getpid()}')\n\tos.rmdir_all(repo_dir) or {}\n\tos.mkdir_all(repo_dir)!\n\tdefer {\n\t\tos.chdir(original_wd) or {}\n\t\tos.rmdir_all(repo_dir) or {}\n\t}\n\tos.execute_or_exit('${os.quoted_path(git_exe)} init ${os.quoted_path(repo_dir)}')\n\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'ignored.md'), '# ignored by dir scan\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', '.vcheckignore'), 'ignored.md\\n')!\n\n\tres := run_in_dir(repo_dir, '${os.quoted_path(vexe)} check-md -hide-warnings -silent docs/ignored.md',\n\t\ttrue)!\n\tassert res.exit_code == 0, res.output\n\tassert !res.output.contains('SKIP: docs/ignored.md'), res.output\n\tassert res.output.contains('> Found: 1 .md files.'), res.output\n\tassert res.output.contains('Skipped by .vcheckignore: 0.'), res.output\n\tassert res.output.contains('Checked .md files: 1 |'), res.output\n}\n\nfn test_check_md_uses_scanned_dir_repo_root_for_vcheckignore() {\n\tif git_exe == '' {\n\t\teprintln('git is required for this test; skipping')\n\t\treturn\n\t}\n\toriginal_wd := os.getwd()\n\tbase_dir := os.join_path(os.vtmp_dir(), 'vcheckignore_repo_root_${os.getpid()}')\n\trepo_a := os.join_path(base_dir, 'repo_a')\n\trepo_b := os.join_path(base_dir, 'repo_b')\n\tos.rmdir_all(base_dir) or {}\n\tos.mkdir_all(os.join_path(repo_b, 'docs'))!\n\tdefer {\n\t\tos.chdir(original_wd) or {}\n\t\tos.rmdir_all(base_dir) or {}\n\t}\n\tos.execute_or_exit('${os.quoted_path(git_exe)} init ${os.quoted_path(repo_a)}')\n\tos.execute_or_exit('${os.quoted_path(git_exe)} init ${os.quoted_path(repo_b)}')\n\n\twrite_text_file(os.join_path(base_dir, '.vcheckignore'), 'outside*.md\\n')!\n\twrite_text_file(os.join_path(repo_b, 'docs', 'outside1.md'), '# outside but should not be skipped\\n')!\n\twrite_text_file(os.join_path(repo_b, 'docs', 'keep1.md'), '# keep\\n')!\n\n\tres := run_in_dir(repo_a, '${os.quoted_path(vexe)} check-md -hide-warnings -silent ${os.quoted_path(os.join_path(repo_b,\n\t\t'docs'))}', true)!\n\tassert res.exit_code == 0, res.output\n\tassert !res.output.contains('SKIP: '), res.output\n\tassert res.output.contains('> Found: 2 .md files.'), res.output\n\tassert res.output.contains('Skipped by .vcheckignore: 0.'), res.output\n\tassert res.output.contains('Checked .md files: 2 |'), res.output\n}\n\nfn test_check_md_multiple_directories_accumulate_skipped_count() {\n\tif git_exe == '' {\n\t\teprintln('git is required for this test; skipping')\n\t\treturn\n\t}\n\toriginal_wd := os.getwd()\n\trepo_dir := os.join_path(os.vtmp_dir(), 'vcheckignore_multi_dirs_${os.getpid()}')\n\tos.rmdir_all(repo_dir) or {}\n\tos.mkdir_all(repo_dir)!\n\tdefer {\n\t\tos.chdir(original_wd) or {}\n\t\tos.rmdir_all(repo_dir) or {}\n\t}\n\tos.execute_or_exit('${os.quoted_path(git_exe)} init ${os.quoted_path(repo_dir)}')\n\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'ignored.md'), '# ignored\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'docs', 'keep.md'), '# keep\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'notes', 'ignored.md'), '# ignored\\n')!\n\twrite_text_file(os.join_path(repo_dir, 'notes', 'keep.md'), '# keep\\n')!\n\twrite_text_file(os.join_path(repo_dir, '.vcheckignore'), 'docs/ignored.md\\nnotes/ignored.md\\n')!\n\n\tres := run_in_dir(repo_dir, '${os.quoted_path(vexe)} check-md -hide-warnings -silent docs notes',\n\t\ttrue)!\n\tassert res.exit_code == 0, res.output\n\tassert res.output.contains('SKIP: docs/ignored.md'), res.output\n\tassert res.output.contains('SKIP: notes/ignored.md'), res.output\n\tassert res.output.contains('> Found: 2 .md files.'), res.output\n\tassert res.output.contains('Skipped by .vcheckignore: 2.'), res.output\n\tassert res.output.contains('Checked .md files: 2 |'), res.output\n}\n\nfn run_in_dir(path string, cmd string, verbose bool) !os.Result {\n\toriginal_wd := os.getwd()\n\tos.chdir(path)!\n\tif verbose {\n\t\tos.setenv('VERBOSE', '1', true)\n\t} else {\n\t\tos.unsetenv('VERBOSE')\n\t}\n\tres := os.execute(cmd)\n\tos.unsetenv('VERBOSE')\n\tos.chdir(original_wd)!\n\treturn res\n}\n\nfn write_text_file(path string, content string) ! {\n\tos.mkdir_all(os.dir(path))!\n\tos.write_file(path, content)!\n}\n"
  },
  {
    "path": "cmd/tools/vcomplete.v",
    "content": "// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\n//\n// Utility functions helping integrate with various shell auto-completion systems.\n// The install process and communication is inspired from that of [kitty](https://sw.kovidgoyal.net/kitty/#completion-for-kitty)\n// This method avoids writing and maintaining external files on the user's file system.\n// The user will be responsible for adding a small line to their .*rc - that will ensure *live* (i.e. not-static)\n// auto-completion features.\n//\n// # bash\n// To install auto-completion for V in bash, simply add this code to your `~/.bashrc`:\n// `source /dev/stdin <<<\"$(v complete setup bash)\"`\n// On more recent versions of bash (>3.2) this should suffice:\n// `source <(v complete setup bash)`\n//\n// # fish\n// For versions of fish <3.0.0, add the following to your `~/.config/fish/config.fish`\n// `v complete setup fish | source`\n// Later versions of fish source completions by default.\n//\n// # zsh\n// To install auto-completion for V in zsh - please add the following to your `~/.zshrc`:\n// ```\n// autoload -Uz compinit\n// compinit\n// # Completion for v\n// v complete setup zsh | source /dev/stdin\n// ```\n// Please note that you should let v load the zsh completions after the call to compinit\n//\n// # powershell\n// To install auto-complete for V in PowerShell, simply do this\n// `v complete setup powershell >> $PROFILE`\n// and reload profile\n// `& $PROFILE`\n// If `$PROFILE` didn't exist yet, create it before\n// `New-Item -Type File -Force $PROFILE`\n//\nmodule main\n\nimport os\n\nconst auto_complete_shells = ['bash', 'fish', 'zsh', 'powershell'] // list of supported shells\n\nconst vexe = os.getenv('VEXE')\nconst help_text = \"Usage:\n  v complete [options] [SUBCMD] QUERY...\n\nDescription:\n  Tool for bridging auto completion between various shells and v\n\nSupported shells:\n  bash, fish, zsh, powershell\n\nExamples:\n  Echo auto-detected shell install script to STDOUT\n    v complete\n  Echo specific shell install script to STDOUT\n    v complete setup bash\n  Auto complete input `v tes`*USER PUSHES TAB* (in Bash compatible format).\n  This is not meant for manual invocation - it's called by the relevant\n  shell via the script installed with `v complete` or `v complete setup SHELL`.\n    v complete bash v tes\n\nOptions:\n  -h, --help                Show this help text.\n\nSUBCMD:\n  setup     : setup [SHELL] - returns the code for completion setup for SHELL\n  bash      : [QUERY]       - returns Bash compatible completion code with completions computed from QUERY\n  fish      : [QUERY]       - returns Fish compatible completion code with completions computed from QUERY\n  zsh       : [QUERY]       - returns ZSH  compatible completion code with completions computed from QUERY\n  powershell: [QUERY]       - returns PowerShell compatible completion code with completions computed from QUERY\"\n\n// Snooped from cmd/v/v.v, vlib/v/pref/pref.c.v\nconst auto_complete_commands = [\n\t// simple_cmd\n\t'ast',\n\t'doc',\n\t'vet',\n\t// tools in one .v file or folder (typically has a \"v\" prefix)\n\t'bin2v',\n\t'bug',\n\t'build-examples',\n\t'build-tools',\n\t'build-vbinaries',\n\t'bump',\n\t'check-md',\n\t'complete',\n\t'compress',\n\t'cover',\n\t'create',\n\t'doctor',\n\t'download',\n\t'fmt',\n\t'gret',\n\t'git-fmt-hook',\n\t'ls',\n\t'quest',\n\t'retry',\n\t'reduce',\n\t'repl',\n\t'repeat',\n\t'self',\n\t'setup-freetype',\n\t'scan',\n\t'shader',\n\t'symlink',\n\t'test-all',\n\t'test-cleancode',\n\t'test-fmt',\n\t'test-parser',\n\t'test-self',\n\t'test',\n\t'tracev',\n\t'up',\n\t'watch',\n\t'where',\n\t'wipe-cache',\n\t// commands\n\t'help',\n\t'new',\n\t'init',\n\t'translate',\n\t'self',\n\t'search',\n\t'install',\n\t'link',\n\t'update',\n\t'upgrade',\n\t'outdated',\n\t'list',\n\t'remove',\n\t'unlink',\n\t'vlib-docs',\n\t'get',\n\t'version',\n\t'run',\n\t'build',\n\t'build-module',\n\t'missdoc',\n]\n// Entries in the flag arrays below should be entered as is:\n// * Short flags, e.g.: \"-v\", should be entered: '-v'\n// * Long flags, e.g.: \"--version\", should be entered: '--version'\n// * Single-dash flags, e.g.: \"-version\", should be entered: '-version'\nconst auto_complete_flags = [\n\t'-wasm-validate',\n\t'-wasm-stack-top',\n\t'-apk',\n\t'-arch',\n\t'-assert',\n\t'-show-timings',\n\t'-show-asserts',\n\t'-check-syntax',\n\t'-check',\n\t'-?',\n\t'-h',\n\t'-help',\n\t'--help',\n\t'-q',\n\t'-v',\n\t'-V',\n\t'--version',\n\t'-version',\n\t'-progress',\n\t'-Wimpure-v',\n\t'-Wfatal-errors',\n\t'-silent',\n\t'-skip-running',\n\t'-cstrict',\n\t'-nofloat',\n\t'-fast-math',\n\t'-e',\n\t'-subsystem',\n\t'-gc',\n\t'-g',\n\t'-cg',\n\t'-debug-tcc',\n\t'-sourcemap',\n\t'-warn-about-allocs',\n\t'-sourcemap-src-included',\n\t'-sourcemap-inline',\n\t'-repl',\n\t'-live',\n\t'-sharedlive',\n\t'-shared',\n\t'--enable-globals',\n\t'-enable-globals',\n\t'-autofree',\n\t'-print_autofree_vars',\n\t'-print_autofree_vars_in_fn',\n\t'-trace-calls',\n\t'-trace-fns',\n\t'-manualfree',\n\t'-skip-unused',\n\t'-no-skip-unused',\n\t'-compress',\n\t'-freestanding',\n\t'-no-retry-compilation',\n\t'-musl',\n\t'-glibc',\n\t'-no-bounds-checking',\n\t'-no-builtin',\n\t'-no-preludes',\n\t'-no-relaxed-gcc14',\n\t'-prof',\n\t'-profile',\n\t'-cov',\n\t'-coverage',\n\t'-profile-fns',\n\t'-profile-no-inline',\n\t'-prod',\n\t'-sanitize',\n\t'-simulator',\n\t'-stats',\n\t'-obf',\n\t'-obfuscate',\n\t'-hide-auto-str',\n\t'-translated',\n\t'-translated-go',\n\t'-m32',\n\t'-m64',\n\t'-color',\n\t'-nocolor',\n\t'-showcc',\n\t'-show-c-output',\n\t'-show-callgraph',\n\t'-show-depgraph',\n\t'-run-only',\n\t'-exclude',\n\t'-test-runner',\n\t'-dump-c-flags',\n\t'-dump-modules',\n\t'-dump-files',\n\t'-dump-defines',\n\t'-experimental',\n\t'-usecache',\n\t'-use-os-system-to-run',\n\t'-macosx-version-min',\n\t'-nocache',\n\t'-prealloc',\n\t'-no-parallel',\n\t'-parallel-cc',\n\t'-native',\n\t'-interpret',\n\t'-W',\n\t'-w',\n\t'-N',\n\t'-n',\n\t'-no-rsp',\n\t'-no-std',\n\t'-keepc',\n\t'-watch',\n\t'-print-v-files',\n\t'-print-watched-files',\n\t'-http',\n\t'-cross',\n\t'-os',\n\t'-printfn',\n\t'-cflags',\n\t'-ldflags',\n\t'-d',\n\t'-define',\n\t'-message-limit',\n\t'-thread-stack-size',\n\t'-cc',\n\t'-c++',\n\t'-checker-match-exhaustive-cutoff-limit',\n\t'-o',\n\t'-output',\n\t'-is_o',\n\t'-b',\n\t'-backend',\n\t'-es5',\n\t'-path',\n\t'-bare-builtin-dir',\n\t'-custom-prelude',\n\t'-raw-vsh-tmp-prefix',\n\t'-cmain',\n\t'-line-info',\n\t'-check-unused-fn-args',\n\t'-check-return',\n\t'-use-coroutines',\n]\nconst auto_complete_flags_cover = [\n\t'--help',\n\t'-h',\n\t'--verbose',\n\t'-v',\n\t'--hotspots',\n\t'-H',\n\t'--percentages',\n\t'-P',\n\t'--show_test_files',\n\t'-S',\n\t'--absolute',\n\t'-A',\n\t'--filter',\n\t'-f',\n]\nconst auto_complete_flags_doc = [\n\t'-all',\n\t'-f',\n\t'-h',\n\t'-help',\n\t'-m',\n\t'-o',\n\t'-readme',\n\t'-v',\n\t'-filename',\n\t'-pos',\n\t'-no-timestamp',\n\t'-inline-assets',\n\t'-theme-dir',\n\t'-open',\n\t'-p',\n\t'-s',\n\t'-l',\n]\nconst auto_complete_flags_download = [\n\t'--help',\n\t'-h',\n\t'--target-folder',\n\t'-t',\n\t'--sha1',\n\t'-1',\n\t'--sha256',\n\t'-2',\n\t'--continue',\n\t'-c',\n\t'--retries',\n\t'-r',\n\t'--delay',\n\t'-d',\n]\nconst auto_complete_flags_fmt = [\n\t'-c',\n\t'-diff',\n\t'-l',\n\t'-w',\n\t'-debug',\n\t'-verify',\n]\nconst auto_complete_flags_bin2v = [\n\t'-h',\n\t'--help',\n\t'-m',\n\t'--module',\n\t'-p',\n\t'--prefix',\n\t'-w',\n\t'--write',\n]\nconst auto_complete_flags_retry = [\n\t'--help',\n\t'-h',\n\t'--timeout',\n\t'-t',\n\t'--delay',\n\t'-d',\n\t'--retries',\n\t'-r',\n]\nconst auto_complete_flags_shader = [\n\t'--help',\n\t'-h',\n\t'--force-update',\n\t'-u',\n\t'--verbose',\n\t'-v',\n\t'--slang',\n\t'-l',\n\t'--output',\n\t'-o',\n]\nconst auto_complete_flags_missdoc = [\n\t'--help',\n\t'-h',\n\t'--tags',\n\t'-t',\n\t'--deprecated',\n\t'-d',\n\t'--private',\n\t'-p',\n\t'--no-line-numbers',\n\t'-n',\n\t'--exclude',\n\t'-e',\n\t'--relative-paths',\n\t'-r',\n\t'--js',\n\t'--verify',\n\t'--diff',\n]\nconst auto_complete_flags_bump = [\n\t'--patch',\n\t'--minor',\n\t'--major',\n]\nconst auto_complete_flags_self = [\n\t'-prod',\n]\nconst auto_complete_flags_where = [\n\t'-h',\n\t'-f',\n\t'-v',\n]\nconst auto_complete_flags_reduce = [\n\t'-e',\n\t'--error_msg',\n\t'-c',\n\t'--command',\n\t'-w',\n\t'--fmt',\n\t'--version',\n]\nconst auto_complete_flags_repeat = [\n\t'--help',\n\t'-h',\n\t'--runs',\n\t'-r',\n\t'--series',\n\t'-s',\n\t'--warmup',\n\t'-w',\n\t'--newline',\n\t'-n',\n\t'--output',\n\t'-O',\n\t'--max_time',\n\t'-m',\n\t'--fail_percent',\n\t'-f',\n\t'--template',\n\t'-t',\n\t'--parameter',\n\t'-p',\n\t'--nmins',\n\t'-i',\n\t'--nmaxs',\n\t'-a',\n\t'--ignore',\n\t'-e',\n]\nconst auto_complete_compilers = [\n\t'cc',\n\t'gcc',\n\t'tcc',\n\t'tinyc',\n\t'clang',\n\t'mingw',\n\t'msvc',\n]\n\n// auto_complete prints auto completion results back to the calling shell's completion system.\n// auto_complete acts as communication bridge between the calling shell and V's completions.\nfn auto_complete(args []string) {\n\tif args.len <= 1 || args[0] != 'complete' {\n\t\tif args.len == 1 {\n\t\t\tshell_path := os.getenv('SHELL')\n\t\t\tif shell_path != '' {\n\t\t\t\tshell_name := os.file_name(shell_path).to_lower()\n\t\t\t\tif shell_name in auto_complete_shells {\n\t\t\t\t\tprintln(setup_for_shell(shell_name))\n\t\t\t\t\texit(0)\n\t\t\t\t}\n\t\t\t\teprintln('Unknown shell ${shell_name}. Supported shells are: ${auto_complete_shells}')\n\t\t\t\texit(1)\n\t\t\t}\n\t\t\teprintln('auto completion require arguments to work.')\n\t\t} else {\n\t\t\teprintln('auto completion failed for \"${args}\".')\n\t\t}\n\t\texit(1)\n\t}\n\tsub := args[1]\n\tsub_args := args[1..]\n\tmatch sub {\n\t\t'setup' {\n\t\t\tif sub_args.len <= 1 || sub_args[1] !in auto_complete_shells {\n\t\t\t\teprintln('please specify a shell to setup auto completion for (${auto_complete_shells}).')\n\t\t\t\texit(1)\n\t\t\t}\n\t\t\tshell := sub_args[1]\n\t\t\tprintln(setup_for_shell(shell))\n\t\t}\n\t\t'bash' {\n\t\t\tif sub_args.len <= 1 {\n\t\t\t\texit(0)\n\t\t\t}\n\t\t\tmut lines := []string{}\n\t\t\tlist := auto_complete_request(sub_args[1..])\n\t\t\tfor entry in list {\n\t\t\t\tlines << \"COMPREPLY+=('${entry}')\"\n\t\t\t}\n\t\t\tprintln(lines.join('\\n'))\n\t\t}\n\t\t'fish', 'powershell' {\n\t\t\tif sub_args.len <= 1 {\n\t\t\t\texit(0)\n\t\t\t}\n\t\t\tmut lines := []string{}\n\t\t\tlist := auto_complete_request(sub_args[1..])\n\t\t\tfor entry in list {\n\t\t\t\tlines << '${entry}'\n\t\t\t}\n\t\t\tprintln(lines.join('\\n'))\n\t\t}\n\t\t'zsh' {\n\t\t\tif sub_args.len <= 1 {\n\t\t\t\texit(0)\n\t\t\t}\n\t\t\tmut lines := []string{}\n\t\t\tmut dirs := []string{}\n\t\t\tmut files := []string{}\n\t\t\tlist := auto_complete_request(sub_args[1..])\n\t\t\tfor entry in list {\n\t\t\t\tmatch true {\n\t\t\t\t\tos.is_dir(entry) { dirs << entry }\n\t\t\t\t\tos.is_file(entry) { files << entry }\n\t\t\t\t\telse { lines << entry }\n\t\t\t\t}\n\t\t\t}\n\t\t\tprintln('compadd -q -- ${lines.join(' ')}')\n\t\t\tprintln('compadd -J \"dirs\" -X \"directory\" -d -- ${dirs.join(' ')}')\n\t\t\tprintln('compadd -J \"files\" -X \"file\" -f -- ${files.join(' ')}')\n\t\t}\n\t\t'-h', '--help' {\n\t\t\tprintln(help_text)\n\t\t}\n\t\telse {}\n\t}\n\texit(0)\n}\n\n// append_separator_if_dir returns the input `path` with an appended\n// `/` or `\\`, depending on the platform, when `path` is a directory.\nfn append_separator_if_dir(path string) string {\n\tif os.is_dir(path) && !path.ends_with(os.path_separator) {\n\t\treturn path + os.path_separator\n\t}\n\treturn path\n}\n\n// nearest_path_or_root returns the nearest valid path searching\n// backwards from `path`.\nfn nearest_path_or_root(path string) string {\n\tmut fixed_path := path\n\tif !os.is_dir(fixed_path) {\n\t\tfixed_path = path.all_before_last(os.path_separator)\n\t\tif fixed_path == '' {\n\t\t\tfixed_path = '/'\n\t\t}\n\t}\n\treturn fixed_path\n}\n\n// auto_complete_request returns a list of completions resolved from a full argument list.\nfn auto_complete_request(args []string) []string {\n\t// Using space will ensure a uniform input in cases where the shell\n\t// returns the completion input as a string (['v','run'] vs. ['v run']).\n\tsplit_by := ' '\n\trequest := args.join(split_by)\n\tmut do_home_expand := false\n\tmut list := []string{}\n\t// new_part := request.ends_with('\\n\\n')\n\tmut parts := request.trim_right(' ').split(split_by)\n\tif parts.len <= 1 { // 'v <tab>' -> top level commands.\n\t\tfor command in auto_complete_commands {\n\t\t\tlist << command\n\t\t}\n\t} else {\n\t\tmut part := parts.last().trim(' ')\n\t\tmut parent_command := ''\n\t\tfor i := parts.len - 1; i >= 0; i-- {\n\t\t\tif parts[i].starts_with('-') {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tparent_command = parts[i]\n\t\t\tbreak\n\t\t}\n\t\tif part.starts_with('-') { // 'v [subcmd] -<tab>' or 'v [subcmd] --<tab>'-> flags.\n\t\t\tget_flags := fn (base []string, flag string) []string {\n\t\t\t\tmut results := []string{}\n\t\t\t\tfor entry in base {\n\t\t\t\t\tif entry.starts_with(flag) {\n\t\t\t\t\t\tresults << entry\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn results\n\t\t\t}\n\n\t\t\tmatch parent_command {\n\t\t\t\t'bin2v' { // 'v bin2v -<tab>'\n\t\t\t\t\tlist = get_flags(auto_complete_flags_bin2v, part)\n\t\t\t\t}\n\t\t\t\t'bump' { // 'v bump -<tab>' -> flags.\n\t\t\t\t\tlist = get_flags(auto_complete_flags_bump, part)\n\t\t\t\t}\n\t\t\t\t'build' { // 'v build -<tab>' -> flags.\n\t\t\t\t\tlist = get_flags(auto_complete_flags, part)\n\t\t\t\t}\n\t\t\t\t'cover' { // 'v cover -<tab>' -> flags.\n\t\t\t\t\tlist = get_flags(auto_complete_flags_cover, part)\n\t\t\t\t}\n\t\t\t\t'doc' { // 'v doc -<tab>' -> flags.\n\t\t\t\t\tlist = get_flags(auto_complete_flags_doc, part)\n\t\t\t\t}\n\t\t\t\t'download' { // 'v download -<tab>' -> flags.\n\t\t\t\t\tlist = get_flags(auto_complete_flags_download, part)\n\t\t\t\t}\n\t\t\t\t'fmt' { // 'v fmt -<tab>' -> flags.\n\t\t\t\t\tlist = get_flags(auto_complete_flags_fmt, part)\n\t\t\t\t}\n\t\t\t\t'missdoc' { // 'v missdoc -<tab>' -> flags.\n\t\t\t\t\tlist = get_flags(auto_complete_flags_missdoc, part)\n\t\t\t\t}\n\t\t\t\t'reduce' { // 'v reduce -<tab>' -> flags.\n\t\t\t\t\tlist = get_flags(auto_complete_flags_reduce, part)\n\t\t\t\t}\n\t\t\t\t'retry' { // 'v retry -<tab>' -> flags.\n\t\t\t\t\tlist = get_flags(auto_complete_flags_retry, part)\n\t\t\t\t}\n\t\t\t\t'repeat' { // 'v repeat -<tab>' -> flags.\n\t\t\t\t\tlist = get_flags(auto_complete_flags_repeat, part)\n\t\t\t\t}\n\t\t\t\t'self' { // 'v self -<tab>' -> flags.\n\t\t\t\t\tlist = get_flags(auto_complete_flags_self, part)\n\t\t\t\t}\n\t\t\t\t'shader' { // 'v shader -<tab>' -> flags.\n\t\t\t\t\tlist = get_flags(auto_complete_flags_shader, part)\n\t\t\t\t}\n\t\t\t\t'where' { // 'v where -<tab>' -> flags.\n\t\t\t\t\tlist = get_flags(auto_complete_flags_where, part)\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tfor flag in auto_complete_flags {\n\t\t\t\t\t\tif flag == part {\n\t\t\t\t\t\t\tif flag == '-cc' { // 'v -cc <tab>' -> list of available compilers.\n\t\t\t\t\t\t\t\tfor compiler in auto_complete_compilers {\n\t\t\t\t\t\t\t\t\tpath := os.find_abs_path_of_executable(compiler) or { '' }\n\t\t\t\t\t\t\t\t\tif path != '' {\n\t\t\t\t\t\t\t\t\t\tlist << compiler\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if flag.starts_with(part) { // 'v -<char(s)><tab>' -> flags matching \"<char(s)>\".\n\t\t\t\t\t\t\tlist << flag\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Clear the list if the result is identical to the part examined\n\t\t\t// (the flag must have already been completed)\n\t\t\tif list.len == 1 && part == list[0] {\n\t\t\t\tlist.clear()\n\t\t\t}\n\t\t} else {\n\t\t\tmatch part {\n\t\t\t\t'help' { // 'v help <tab>' -> top level commands except \"help\".\n\t\t\t\t\tlist = auto_complete_commands.filter(it != part && it != 'complete')\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// 'v <char(s)><tab>' -> commands matching \"<char(s)>\".\n\t\t\t\t\t// Don't include if part matches a full command - instead go to path completion below.\n\t\t\t\t\tfor command in auto_complete_commands {\n\t\t\t\t\t\tif part != command && command.starts_with(part) {\n\t\t\t\t\t\t\tlist << command\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Nothing of value was found.\n\t\t// Mimic shell dir and file completion\n\t\tif list.len == 0 {\n\t\t\tmut ls_path := '.'\n\t\t\tmut collect_all := part in auto_complete_commands\n\t\t\tmut path_complete := false\n\t\t\tdo_home_expand = part.starts_with('~')\n\t\t\tif do_home_expand {\n\t\t\t\tadd_sep := if part == '~' { os.path_separator } else { '' }\n\t\t\t\tpart = part.replace_once('~', os.home_dir().trim_right(os.path_separator)) + add_sep\n\t\t\t}\n\t\t\tis_abs_path := part.starts_with(os.path_separator) // TODO: Windows support for drive prefixes\n\t\t\tif part.ends_with(os.path_separator) || part == '.' || part == '..' {\n\t\t\t\t// 'v <command>(.*/$|.|..)<tab>' -> output full directory list\n\t\t\t\tls_path = '.' + os.path_separator + part\n\t\t\t\tif is_abs_path {\n\t\t\t\t\tls_path = nearest_path_or_root(part)\n\t\t\t\t}\n\t\t\t\tcollect_all = true\n\t\t\t} else if !collect_all && part.contains(os.path_separator) && os.is_dir(os.dir(part)) {\n\t\t\t\t// 'v <command>(.*/.* && os.is_dir)<tab>'  -> output completion friendly directory list\n\t\t\t\tif is_abs_path {\n\t\t\t\t\tls_path = nearest_path_or_root(part)\n\t\t\t\t} else {\n\t\t\t\t\tls_path = os.dir(part)\n\t\t\t\t}\n\t\t\t\tpath_complete = true\n\t\t\t}\n\n\t\t\tentries := os.ls(ls_path) or { return list }\n\t\t\tmut last := part.all_after_last(os.path_separator)\n\t\t\tif is_abs_path && os.is_dir(part) {\n\t\t\t\tlast = ''\n\t\t\t}\n\t\t\tif path_complete {\n\t\t\t\tpath := part.all_before_last(os.path_separator)\n\t\t\t\tfor entry in entries {\n\t\t\t\t\tif entry.starts_with(last) {\n\t\t\t\t\t\tlist << append_separator_if_dir(os.join_path(path, entry))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Handle special case, where there is only one file in the directory\n\t\t\t\t// being completed - if it can be resolved we return that since\n\t\t\t\t// handling it in the generalized logic below will result in\n\t\t\t\t// more complexity.\n\t\t\t\tif entries.len == 1 && os.is_file(os.join_path(ls_path, entries[0])) {\n\t\t\t\t\tmut keep_input_path_format := ls_path\n\t\t\t\t\tif !part.starts_with('./') && ls_path.starts_with('./') {\n\t\t\t\t\t\tkeep_input_path_format = keep_input_path_format.all_after('./')\n\t\t\t\t\t}\n\t\t\t\t\treturn [os.join_path(keep_input_path_format, entries[0])]\n\t\t\t\t}\n\t\t\t\tfor entry in entries {\n\t\t\t\t\tif collect_all || entry.starts_with(last) {\n\t\t\t\t\t\tlist << append_separator_if_dir(entry)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif do_home_expand {\n\t\treturn list.map(it.replace_once(os.home_dir().trim_right(os.path_separator), '~'))\n\t}\n\treturn list\n}\n\nfn setup_for_shell(shell string) string {\n\tmut setup := ''\n\tmatch shell {\n\t\t'bash' {\n\t\t\tsetup = '\n_v_completions() {\n\tlocal src\n\tlocal limit\n\t# Send all words up to the word the cursor is currently on\n\tlet limit=1+\\$COMP_CWORD\n\tsrc=\\$(${vexe} complete bash \\$(printf \"%s\\\\n\" \\${COMP_WORDS[@]: 0:\\$limit}))\n\tif [[ \\$? == 0 ]]; then\n\t\teval \\${src}\n\t\t#echo \\${src}\n\tfi\n}\n\ncomplete -o nospace -F _v_completions v\n'\n\t\t}\n\t\t'fish' {\n\t\t\tsetup = '\nfunction __v_completions\n\t# Send all words up to the one before the cursor\n\t${vexe} complete fish (commandline -cop)\nend\ncomplete -f -c v -a \"(__v_completions)\"\n'\n\t\t}\n\t\t'zsh' {\n\t\t\tsetup = '\n#compdef v\n_v() {\n\tlocal src\n\t# Send all words up to the word the cursor is currently on\n\tsrc=\\$(${vexe} complete zsh \\$(printf \"%s\\\\n\" \\${(@)words[1,\\$CURRENT]}))\n\tif [[ \\$? == 0 ]]; then\n\t\teval \\${src}\n\t\t#echo \\${src}\n\tfi\n}\ncompdef _v v\n'\n\t\t}\n\t\t'powershell' {\n\t\t\tsetup = '\nRegister-ArgumentCompleter -Native -CommandName v -ScriptBlock {\n\tparam(\\$commandName, \\$wordToComplete, \\$cursorPosition)\n\t\t${vexe} complete powershell \"\\$wordToComplete\" | ForEach-Object {\n\t\t\t[System.Management.Automation.CompletionResult]::new(\\$_, \\$_, \\'ParameterValue\\', \\$_)\n\t\t}\n}\n'\n\t\t}\n\t\telse {}\n\t}\n\treturn setup\n}\n\nfn main() {\n\targs := os.args[1..]\n\t// println('\"${args}\"')\n\tauto_complete(args)\n}\n"
  },
  {
    "path": "cmd/tools/vcomplete_test.v",
    "content": "import os\n\nconst vexe = @VEXE\nconst tfolder = os.join_path(os.vtmp_dir(), 'vcomplete_test')\n\nenum Shell {\n\tbash\n\tfish\n\tzsh\n\tpowershell\n}\n\nfn string_to_shell(shell string) !Shell {\n\treturn match shell {\n\t\t'bash' {\n\t\t\t.bash\n\t\t}\n\t\t'fish' {\n\t\t\t.fish\n\t\t}\n\t\t'zsh' {\n\t\t\t.zsh\n\t\t}\n\t\t'powershell' {\n\t\t\t.powershell\n\t\t}\n\t\telse {\n\t\t\terror('${shell} is not supported')\n\t\t}\n\t}\n}\n\nfn testsuite_begin() {\n\tos.mkdir_all(tfolder) or {}\n}\n\nfn testsuite_end() {\n\tos.rmdir_all(tfolder) or {}\n}\n\nfn detect_shell() Shell {\n\tforced_shell := os.getenv('VTEST_VCOMPLETE_SHELL')\n\tif forced_shell != '' {\n\t\treturn string_to_shell(forced_shell) or { panic(err) }\n\t}\n\t$if linux || macos {\n\t\treturn .bash\n\t}\n\t$if windows {\n\t\treturn .powershell\n\t}\n\treturn .bash\n}\n\nstruct CompleteTestCase {\n\tshell     Shell = detect_shell()\n\tstructure []string\n\tcompletes map[string][]string\n}\n\nconst test_cases = [\n\tCompleteTestCase{\n\t\t// Tests the completion of \"v complet<tab>\" *completeception*\n\t\tstructure: [] // no test folders\n\t\tcompletes: {\n\t\t\t'v complet': ['complete']\n\t\t}\n\t},\n\tCompleteTestCase{\n\t\t// Tests the completion of \"v ru<tab>\"\n\t\tstructure: [] // no test folders\n\t\tcompletes: {\n\t\t\t'v ru': ['run']\n\t\t}\n\t},\n\tCompleteTestCase{\n\t\t// Tests with one sub-folder in test root\n\t\t// vfmt off\n\t\tstructure: [\n\t\t\tos.join_path('examples', 'ex1'), // Empty dir\n\t\t\tos.join_path('examples', 'ex2'), // Two files\n\t\t\tos.join_path('examples', 'ex2', 'ex2_0.v'),\n\t\t\tos.join_path('examples', 'ex2', 'ex2_1.v'),\n\t\t\tos.join_path('examples', 'ex3'), // One file\n\t\t\tos.join_path('examples', 'ex3', 'ex3.v')\n\t\t]\n\t\t// vfmt on\n\t\tcompletes: {\n\t\t\t'v run e':                  ['examples/']\n\t\t\t'v run':                    ['examples/']\n\t\t\t'v run ':                   ['examples/']\n\t\t\t'v run examples/':          ['ex1', 'ex2', 'ex3']\n\t\t\t'v run examples/ex':        ['examples/ex1/', 'examples/ex2/', 'examples/ex3/']\n\t\t\t'v run examples/ex1':       ['examples/ex1/']\n\t\t\t'v run examples/ex1/':      []\n\t\t\t'v run examples/ex2/':      ['ex2_0.v', 'ex2_1.v']\n\t\t\t'v run examples/ex3/':      ['examples/ex3/ex3.v']\n\t\t\t'v run examples/ex3/ex3.v': ['examples/ex3/ex3.v']\n\t\t\t'v examp':                  ['examples/']\n\t\t\t'v examples/f':             []\n\t\t\t'v examples/':              ['ex1', 'ex2', 'ex3']\n\t\t\t'v examples/ex':            ['examples/ex1/', 'examples/ex2/', 'examples/ex3/']\n\t\t\t'v examples/ex1':           ['examples/ex1/']\n\t\t\t'v examples/ex1/':          []\n\t\t\t'v examples/ex2/':          ['ex2_0.v', 'ex2_1.v']\n\t\t\t'v examples/ex3/':          ['examples/ex3/ex3.v']\n\t\t\t'v examples/ex3/ex3.v':     ['examples/ex3/ex3.v']\n\t\t}\n\t},\n\tCompleteTestCase{\n\t\t// Tests with two sub-folder in test root\n\t\t// vfmt off\n\t\tstructure: [\n\t\t\tos.join_path('sub0', 'ex1'), // Empty dir\n\t\t\tos.join_path('sub0', 'ex2'), // Two files\n\t\t\tos.join_path('sub0', 'ex2', 'ex2_0.v'),\n\t\t\tos.join_path('sub0', 'ex2', 'ex2_1.v'),\n\t\t\tos.join_path('sub0', 'ex3'), // One file\n\t\t\tos.join_path('sub0', 'ex3', 'ex3.v'),\n\t\t\tos.join_path('sub1', 'vex1'),\n\t\t\tos.join_path('sub1', 'vex2'),\n\t\t\tos.join_path('sub1', 'vex3'),\n\t\t\tos.join_path('sub1', 'vex3', 'vex3.v')\n\t\t]\n\t\t// vfmt on\n\t\tcompletes: {\n\t\t\t// sub0\n\t\t\t'v run ./':             ['sub0/', 'sub1/']\n\t\t\t'v run ./s':            ['./sub0/', './sub1/']\n\t\t\t'v run':                ['sub0/', 'sub1/']\n\t\t\t'v run ':               ['sub0/', 'sub1/']\n\t\t\t'v run sub0/':          ['ex1', 'ex2', 'ex3']\n\t\t\t'v run sub0/ex':        ['sub0/ex1/', 'sub0/ex2/', 'sub0/ex3/']\n\t\t\t'v run sub0/ex1':       ['sub0/ex1/']\n\t\t\t'v run sub0/ex1/':      []\n\t\t\t'v run sub0/ex2/':      ['ex2_0.v', 'ex2_1.v']\n\t\t\t'v run sub0/ex3/':      ['sub0/ex3/ex3.v']\n\t\t\t'v run sub0/ex3/ex3.v': ['sub0/ex3/ex3.v']\n\t\t\t'v su':                 ['sub0/', 'sub1/']\n\t\t\t'v sub':                ['sub0/', 'sub1/']\n\t\t\t'v sub0/f':             []\n\t\t\t'v sub0/':              ['ex1', 'ex2', 'ex3']\n\t\t\t'v sub0/ex':            ['sub0/ex1/', 'sub0/ex2/', 'sub0/ex3/']\n\t\t\t'v sub0/ex1':           ['sub0/ex1/']\n\t\t\t'v sub0/ex1/':          []\n\t\t\t'v sub0/ex2/':          ['ex2_0.v', 'ex2_1.v']\n\t\t\t'v sub0/ex3/':          ['sub0/ex3/ex3.v']\n\t\t\t'v sub0/ex3/ex3.v':     ['sub0/ex3/ex3.v']\n\t\t\t// sub1\n\t\t\t'v run sub1/':          ['vex1', 'vex2', 'vex3']\n\t\t\t'v sub1/vex1/':         []\n\t\t\t'v sub1/vex2/':         []\n\t\t\t'v sub1/vex3/':         ['sub1/vex3/vex3.v']\n\t\t}\n\t},\n]\n\nfn run_individual_test(case CompleteTestCase) ! {\n\t// Clean plate\n\tos.rmdir_all(tfolder) or {}\n\tos.mkdir_all(tfolder) or {}\n\t// Work relative to the test dir\n\tos.chdir(tfolder) or { panic(err) }\n\tfor relative_path in case.structure {\n\t\tpath := os.join_path(tfolder, relative_path)\n\t\trel_parts := relative_path.split(os.path_separator)\n\t\tif rel_parts.last().contains('.') {\n\t\t\t// Make the containing dir\n\t\t\tos.mkdir_all(os.dir(path)) or { panic(err) }\n\t\t\t// Create empty file\n\t\t\tmut f := os.create(path) or { panic(err) }\n\t\t\tf.close()\n\t\t} else {\n\t\t\tos.mkdir_all(path) or { panic(err) }\n\t\t}\n\t}\n\tfor complete, expected in case.completes {\n\t\tmut pre_strip := ''\n\t\tmut post_strip := ''\n\t\tmut complete_command := '${vexe} complete'\n\t\tmatch case.shell {\n\t\t\t.bash {\n\t\t\t\tpre_strip = \"COMPREPLY+=('\"\n\t\t\t\tpost_strip = \"')\"\n\t\t\t\tcomplete_command += ' bash'\n\t\t\t}\n\t\t\t.fish {\n\t\t\t\tcomplete_command += ' fish'\n\t\t\t}\n\t\t\t.zsh {\n\t\t\t\tpre_strip = 'compadd -U -S\"\" -- \\''\n\t\t\t\tpost_strip = \"';\"\n\t\t\t\tcomplete_command += ' zsh'\n\t\t\t}\n\t\t\t.powershell {\n\t\t\t\tcomplete_command += ' powershell'\n\t\t\t}\n\t\t}\n\n\t\tmut normalized_complete := complete\n\t\tif case.shell == .powershell {\n\t\t\tnormalized_complete = normalized_complete.replace('/', '\\\\')\n\t\t}\n\t\tcomplete_command += ' ${normalized_complete}'\n\t\tres := os.execute('${complete_command}')\n\t\tmut lines := res.output.split('\\n')\n\t\tfor mut line in lines {\n\t\t\tif case.shell == .powershell {\n\t\t\t\tline = line.replace('\\r', '')\n\t\t\t\tline = line.all_after('.\\\\')\n\t\t\t}\n\t\t\tline = line.trim_string_left(pre_strip).trim_string_right(post_strip)\n\t\t}\n\t\tlines = lines.filter(it != '')\n\t\tlines.sort()\n\t\tmut sorted_expected := expected.clone()\n\t\tif case.shell == .powershell {\n\t\t\tsorted_expected = sorted_expected.map(fn (path string) string {\n\t\t\t\tmut normalized_path := path.replace('/', '\\\\')\n\t\t\t\tnormalized_path = normalized_path.all_after('.\\\\')\n\t\t\t\treturn normalized_path\n\t\t\t})\n\t\t}\n\t\tsorted_expected.sort()\n\t\t// eprintln('${complete} ${lines} vs ${sorted_expected}') // kept for easier debugging\n\n\t\tassert lines.len == sorted_expected.len\n\t\tfor i, line in lines {\n\t\t\tassert line == sorted_expected[i]\n\t\t}\n\t}\n}\n\nfn test_all_complete_cases() {\n\tfor case in test_cases {\n\t\trun_individual_test(case)!\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vcompress.v",
    "content": "module main\n\nimport compress.zlib\nimport os\n\nenum CompressionType {\n\tzlib\n}\n\nfn main() {\n\tif os.args.len != 5 {\n\t\teprintln('v compress <type> <in> <out>')\n\t\teprintln('supported types: zlib')\n\t\texit(1)\n\t}\n\tcompression_type := match os.args[2] {\n\t\t'zlib' {\n\t\t\tCompressionType.zlib\n\t\t}\n\t\telse {\n\t\t\teprintln('unsupported type: ${os.args[1]}')\n\t\t\texit(1)\n\t\t}\n\t}\n\tpath := os.args[3]\n\tcontent := os.read_bytes(path) or {\n\t\teprintln('unable to read \"${path}\": ${err}')\n\t\texit(1)\n\t}\n\tcompressed := match compression_type {\n\t\t.zlib {\n\t\t\tzlib.compress(content) or {\n\t\t\t\teprintln('compression error: ${err}')\n\t\t\t\texit(1)\n\t\t\t}\n\t\t}\n\t}\n\tout_path := os.args[4]\n\n\tos.write_file_array(out_path, compressed) or {\n\t\teprintln('failed to write \"${out_path}\": ${err}')\n\t\texit(1)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vcover/cover_test.v",
    "content": "// vtest retry: 2\nimport os\n\nconst vexe = @VEXE\nconst vroot = os.dir(vexe)\nconst tfolder = os.join_path(os.vtmp_dir(), 'cover_test')\n\nconst t1 = np(os.join_path(tfolder, 't1'))\nconst t2 = np(os.join_path(tfolder, 't2'))\nconst t3 = np(os.join_path(tfolder, 't3'))\n\nfn testsuite_begin() {\n\tos.setenv('VCOLORS', 'never', true)\n\tos.chdir(vroot)!\n\tos.rmdir_all(tfolder) or {}\n\tos.mkdir(tfolder) or {}\n}\n\nfn testsuite_end() {\n\tos.rmdir_all(tfolder) or {}\n}\n\nfn test_help() {\n\tres := execute('${os.quoted_path(vexe)} cover -h')\n\tassert res.exit_code == 0\n\tassert res.output.contains('Usage: v cover')\n\tassert res.output.contains('Description: Analyze & make reports')\n\tassert res.output.contains('Options:')\n\tassert res.output.contains('-h, --help                Show this help text.')\n\tassert res.output.contains('-v, --verbose             Be more verbose while processing the coverages.')\n\tassert res.output.contains('-H, --hotspots            Show most frequently executed covered lines.')\n\tassert res.output.contains('-P, --percentages         Show coverage percentage per file.')\n\tassert res.output.contains('-S, --show_test_files     Show `_test.v` files as well (normally filtered).')\n\tassert res.output.contains('-A, --absolute            Use absolute paths for all files')\n}\n\nfn np(path string) string {\n\treturn path.replace('\\\\', '/')\n}\n\nfn test_simple() {\n\tassert !os.exists(t1), t1\n\tassert !os.exists(t2), t2\n\tassert !os.exists(t3), t3\n\n\tr1 := execute('${os.quoted_path(vexe)} -no-skip-unused -coverage ${os.quoted_path(t1)} cmd/tools/vcover/testdata/simple/t1_test.v')\n\tassert r1.exit_code == 0, r1.str()\n\tassert r1.output.trim_space() == '10', r1.str()\n\tassert os.exists(t1), t1\n\tcmd := '${os.quoted_path(vexe)} cover ${os.quoted_path(t1)} --filter vcover/testdata/simple/'\n\tfilter1 := execute(cmd)\n\tassert filter1.exit_code == 0, filter1.output\n\tassert filter1.output.contains('cmd/tools/vcover/testdata/simple/simple.v'), filter1.output\n\tassert filter1.output.trim_space().ends_with('|      4 |      9 |  44.44%'), filter1.output\n\thfilter1 := execute('${os.quoted_path(vexe)} cover ${os.quoted_path(t1)} --filter vcover/testdata/simple/ -H -P false')\n\tassert hfilter1.exit_code == 0, hfilter1.output\n\tassert !hfilter1.output.contains('%'), hfilter1.output\n\thoutput1 := hfilter1.output.trim_space().split_into_lines()\n\tzeros1 := houtput1.filter(it.starts_with('0 '))\n\tnzeros1 := houtput1.filter(!it.starts_with('0 '))\n\tassert zeros1.len > 0\n\tassert zeros1.any(it.contains('simple.v:12')), zeros1.str()\n\tassert zeros1.any(it.contains('simple.v:14')), zeros1.str()\n\tassert zeros1.any(it.contains('simple.v:17')), zeros1.str()\n\tassert zeros1.any(it.contains('simple.v:18')), zeros1.str()\n\tassert zeros1.any(it.contains('simple.v:19')), zeros1.str()\n\tassert nzeros1.len > 0\n\tassert nzeros1.any(it.contains('simple.v:4')), nzeros1.str()\n\tassert nzeros1.any(it.contains('simple.v:6')), nzeros1.str()\n\tassert nzeros1.any(it.contains('simple.v:8')), nzeros1.str()\n\tassert nzeros1.any(it.contains('simple.v:25')), nzeros1.str()\n\n\tr2 := execute('${os.quoted_path(vexe)} -no-skip-unused -coverage ${os.quoted_path(t2)} cmd/tools/vcover/testdata/simple/t2_test.v')\n\tassert r2.exit_code == 0, r2.str()\n\tassert r2.output.trim_space() == '24', r2.str()\n\tassert os.exists(t2), t2\n\tfilter2 := execute('${os.quoted_path(vexe)} cover ${os.quoted_path(t2)} --filter vcover/testdata/simple')\n\tassert filter2.exit_code == 0, filter2.output\n\tassert filter2.output.contains('cmd/tools/vcover/testdata/simple/simple.v')\n\tassert filter2.output.trim_space().ends_with('|      6 |      9 |  66.67%'), filter2.output\n\thfilter2 := execute('${os.quoted_path(vexe)} cover ${os.quoted_path(t2)} --filter testdata/simple -H -P false')\n\tassert hfilter2.exit_code == 0, hfilter2.output\n\tassert !hfilter2.output.contains('%'), hfilter2.output\n\thoutput2 := hfilter2.output.trim_space().split_into_lines()\n\tzeros2 := houtput2.filter(it.starts_with('0 '))\n\tnzeros2 := houtput2.filter(!it.starts_with('0 '))\n\tassert zeros2.len > 0\n\tassert zeros2.any(it.contains('simple.v:4')), zeros2.str()\n\tassert zeros2.any(it.contains('simple.v:6')), zeros2.str()\n\tassert zeros2.any(it.contains('simple.v:8')), zeros2.str()\n\tassert nzeros2.len > 0\n\tassert nzeros2.any(it.contains('simple.v:17')), nzeros2.str()\n\tassert nzeros2.any(it.contains('simple.v:18')), nzeros2.str()\n\tassert nzeros2.any(it.contains('simple.v:19')), nzeros2.str()\n\tassert nzeros2.any(it.contains('simple.v:25')), nzeros2.str()\n\n\t// Run both tests. The coverage should be combined and == 100%\n\tr3 := execute('${os.quoted_path(vexe)} -no-skip-unused -coverage ${os.quoted_path(t3)} test cmd/tools/vcover/testdata/simple/')\n\tassert r3.exit_code == 0, r3.str()\n\tassert r3.output.trim_space().contains('Summary for all V _test.v files: '), r3.str()\n\tassert os.exists(t3), t3\n\tfilter3 := execute('${os.quoted_path(vexe)} cover ${os.quoted_path(t3)} --filter simple/')\n\tassert filter3.exit_code == 0, filter3.str()\n\tassert filter3.output.contains('cmd/tools/vcover/testdata/simple/simple.v'), filter3.str()\n\tassert filter3.output.trim_space().match_glob('*cmd/tools/vcover/testdata/simple/simple.v *|      9 |      9 | 100.00%'), filter3.str()\n}\n\nfn execute(cmd string) os.Result {\n\teprintln('Executing: ${cmd}')\n\treturn os.execute(cmd)\n}\n"
  },
  {
    "path": "cmd/tools/vcover/data.v",
    "content": "// Copyright (c) 2024 Felipe Pena and Delyan Angelov. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nmodule main\n\n// vcounter_*.csv files contain counter lines in a CSV format. They can get quite large,\n// for big programs, since they contain all non zero coverage counters.\n// Their names are timestamp (rand.ulid + clock_gettime) based, to minimise the chance that parallel runs\n// will overwrite each other, but without the overhead of additional synchronisation/locks.\nstruct CounterLine {\nmut:\n\tfile string // retrieved based on the loaded meta\n\tline int    // retrieved based on the loaded meta\n\n\tmeta  string // A filename in the sibling meta/ folder, should exist, to match the value from this field. The filename is a hash of both the path and the used build options, to facilitate merging coverage data from different builds/programs\n\tpoint int    // The index of a source point. Note that it is not a line number, but an index in the meta data file, keyed by the field `meta` above.\n\thits  u64    // How many times the coverage point was executed. Only counters that are != 0 are recorded.\n}\n\n// Source metadata files in meta/*.txt, contain JSON encoded fields (mappings from v source files to point line numbers).\n// Their names are a result of a hashing function, applied over both the source file name, and the build options.\n// This has several benefits:\n//   a) it makes sure, that the resulting path is normalised\n//   b) the meta data is deduplicated between runs that use the same source files\n//   c) coverage data from different runs can be merged by simply reusing the same -coverage folder,\n//      or by copy/pasting all files from 1 run, to the folder of another.\nstruct MetaData {\n\tfile          string // V source file path\n\tfhash         string // fhash is the name of the meta file\n\tv_version     string // the V version, used to generate the coverage meta data file\n\tbuild_options string // the build options for the program\n\tnpoints       int    // the number of stored coverage points\n\tpoints        []int  // the line numbers corresponding to each point\n}\n"
  },
  {
    "path": "cmd/tools/vcover/main.v",
    "content": "// Copyright (c) 2024 Felipe Pena and Delyan Angelov. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nmodule main\n\nimport os\nimport log\nimport flag\nimport json\nimport arrays\nimport encoding.csv\n\n// program options, storage etc\nstruct Context {\nmut:\n\tshow_help          bool\n\tshow_hotspots      bool\n\tshow_percentages   bool\n\tshow_test_files    bool\n\tuse_absolute_paths bool\n\tbe_verbose         bool\n\tfilter             string\n\tworking_folder     string\n\n\ttargets            []string\n\tmeta               map[string]MetaData // aggregated meta data, read from all .json files\n\tall_lines_per_file map[string][]int    // aggregated by load_meta\n\n\tcounters         map[string]u64         // incremented by process_target, based on each .csv file\n\tlines_per_file   map[string]map[int]int // incremented by process_target, based on each .csv file\n\tprocessed_points u64\n}\n\nconst metadata_extension = '.json'\nconst vcounter_glob_pattern = 'vcounters_*.csv'\n\nfn (mut ctx Context) load_meta(folder string) {\n\tfor omfile in os.walk_ext(folder, metadata_extension) {\n\t\tmfile := omfile.replace('\\\\', '/')\n\t\tcontent := os.read_file(mfile) or { '' }\n\t\tmeta := os.file_name(mfile.replace(metadata_extension, ''))\n\t\tdata := json.decode(MetaData, content) or {\n\t\t\tlog.error('${@METHOD} failed to load ${mfile}')\n\t\t\tcontinue\n\t\t}\n\t\tctx.meta[meta] = data\n\t\tmut lines_per_file := ctx.all_lines_per_file[data.file]\n\t\tlines_per_file << data.points\n\t\tctx.all_lines_per_file[data.file] = arrays.distinct(lines_per_file)\n\t}\n}\n\nfn (mut ctx Context) post_process_all_metas() {\n\tctx.verbose('${@METHOD}')\n\tfor _, m in ctx.meta {\n\t\tlines_per_file := ctx.all_lines_per_file[m.file]\n\t\tfor line in lines_per_file {\n\t\t\tctx.counters['${m.file}:${line}:'] = 0\n\t\t}\n\t}\n}\n\nfn (mut ctx Context) post_process_all_targets() {\n\tctx.verbose('${@METHOD}')\n\tctx.verbose('ctx.processed_points: ${ctx.processed_points}')\n}\n\nfn (ctx &Context) verbose(msg string) {\n\tif ctx.be_verbose {\n\t\tlog.info(msg)\n\t}\n}\n\nfn (mut ctx Context) process_target(tfile string) ! {\n\tctx.verbose('${@METHOD} ${tfile}')\n\tmut reader := csv.new_reader_from_file(tfile)!\n\theader := reader.read()!\n\tif header != ['meta', 'point', 'hits'] {\n\t\treturn error('invalid header in .csv file')\n\t}\n\tfor {\n\t\trow := reader.read() or { break }\n\t\tmut cline := CounterLine{\n\t\t\tmeta:  row[0]\n\t\t\tpoint: row[1].int()\n\t\t\thits:  row[2].u64()\n\t\t}\n\t\tm := ctx.meta[cline.meta] or {\n\t\t\tctx.verbose('> skipping invalid meta: ${cline.meta} in file: ${cline.file}, csvfile: ${tfile}')\n\t\t\tcontinue\n\t\t}\n\t\tcline.file = m.file\n\t\tcline.line = m.points[cline.point] or {\n\t\t\tctx.verbose('> skipping invalid point: ${cline.point} in file: ${cline.file}, meta: ${cline.meta}, csvfile: ${tfile}')\n\t\t\tcontinue\n\t\t}\n\t\tctx.counters['${cline.file}:${cline.line}:'] += cline.hits\n\t\tmut lines := ctx.lines_per_file[cline.file].move()\n\t\tlines[cline.line]++\n\t\tctx.lines_per_file[cline.file] = lines.move()\n\t\t// dump( ctx.lines_per_file[cline.meta][cline.point] )\n\t\tctx.processed_points++\n\t}\n}\n\nfn (mut ctx Context) show_report() ! {\n\tfilters := ctx.filter.split(',').filter(it != '')\n\tif ctx.show_hotspots {\n\t\tfor location, hits in ctx.counters {\n\t\t\tif filters.len > 0 {\n\t\t\t\tif !filters.any(location.contains(it)) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\tmut final_path := normalize_path(location)\n\t\t\tif !ctx.use_absolute_paths {\n\t\t\t\tfinal_path = location.all_after_first('${ctx.working_folder}/')\n\t\t\t}\n\t\t\tprintln('${hits:-8} ${final_path}')\n\t\t}\n\t}\n\tif ctx.show_percentages {\n\t\tfor file, lines in ctx.lines_per_file {\n\t\t\tif !ctx.show_test_files {\n\t\t\t\tif file.ends_with('_test.v') || file.ends_with('_test.c.v') {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\tif filters.len > 0 {\n\t\t\t\tif !filters.any(file.contains(it)) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\ttotal_lines := ctx.all_lines_per_file[file].len\n\t\t\texecuted_points := lines.len\n\t\t\tcoverage_percent := 100.0 * f64(executed_points) / f64(total_lines)\n\t\t\tmut final_path := normalize_path(file)\n\t\t\tif !ctx.use_absolute_paths {\n\t\t\t\tfinal_path = file.all_after_first('${ctx.working_folder}/')\n\t\t\t}\n\t\t\tprintln('${final_path:-80s} | ${executed_points:6} | ${total_lines:6} | ${coverage_percent:6.2f}%')\n\t\t}\n\t}\n}\n\nfn normalize_path(path string) string {\n\treturn path.replace(os.path_separator, '/')\n}\n\nfn main() {\n\tlog.use_stdout()\n\tmut ctx := Context{}\n\tctx.working_folder = normalize_path(os.real_path(os.getwd()))\n\tmut fp := flag.new_flag_parser(os.args#[1..])\n\tfp.application('v cover')\n\tfp.version('0.0.2')\n\tfp.description('Analyze & make reports, based on cover files, produced by running programs and tests, compiled with `-coverage folder/`')\n\tfp.arguments_description('[folder1/ file2 ...]')\n\tfp.skip_executable()\n\tctx.show_help = fp.bool('help', `h`, false, 'Show this help text.')\n\tctx.be_verbose = fp.bool('verbose', `v`, false, 'Be more verbose while processing the coverages.')\n\tctx.show_hotspots = fp.bool('hotspots', `H`, false, 'Show most frequently executed covered lines.')\n\tctx.show_percentages = fp.bool('percentages', `P`, true, 'Show coverage percentage per file.')\n\tctx.show_test_files = fp.bool('show_test_files', `S`, false, 'Show `_test.v` files as well (normally filtered).')\n\tctx.use_absolute_paths = fp.bool('absolute', `A`, false, 'Use absolute paths for all files, no matter the current folder. By default, files inside the current folder, are shown with a relative path.')\n\tctx.filter = fp.string('filter', `f`, '', 'Filter only the matching source path patterns.')\n\tif ctx.show_help {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\ttargets := fp.finalize() or {\n\t\tlog.error(fp.usage())\n\t\texit(1)\n\t}\n\tctx.verbose('Targets: ${targets}')\n\tfor t in targets {\n\t\tif !os.exists(t) {\n\t\t\tlog.error('Skipping ${t}, since it does not exist')\n\t\t\tcontinue\n\t\t}\n\t\tif os.is_dir(t) {\n\t\t\tfound_counter_files := os.walk_ext(t, '.csv')\n\t\t\tif found_counter_files.len == 0 {\n\t\t\t\tlog.error('Skipping ${t}, since there are 0 ${vcounter_glob_pattern} files in it')\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfor counterfile in found_counter_files {\n\t\t\t\tctx.targets << counterfile\n\t\t\t\tctx.load_meta(t)\n\t\t\t}\n\t\t} else {\n\t\t\tctx.targets << t\n\t\t\tctx.load_meta(os.dir(t))\n\t\t}\n\t}\n\tctx.post_process_all_metas()\n\tctx.verbose('Final ctx.targets.len: ${ctx.targets.len}')\n\tctx.verbose('Final ctx.meta.len: ${ctx.meta.len}')\n\tctx.verbose('Final ctx.filter: ${ctx.filter}')\n\tif ctx.targets.len == 0 {\n\t\tlog.error('0 cover targets')\n\t\texit(1)\n\t}\n\tfor t in ctx.targets {\n\t\tctx.process_target(t)!\n\t}\n\tctx.post_process_all_targets()\n\tctx.show_report()!\n}\n"
  },
  {
    "path": "cmd/tools/vcover/testdata/example1/abc.v",
    "content": "module example1\n\nfn abc01() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 2\n\t}\n}\n\nfn abc02() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc03() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc04() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc05() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc06() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc07() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc08() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc09() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc10() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc11() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc12() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc13() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc14() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc15() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc16() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc17() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc18() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc19() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc20() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc21() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc22() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc23() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc24() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc25() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc26() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc27() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc28() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc29() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc30() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc31() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc32() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc33() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc34() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc35() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc36() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc37() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc38() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n\nfn abc39() int {\n\tif true {\n\t\treturn 1\n\t} else {\n\t\treturn 0\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vcover/testdata/example1/internal_abc01_test.v",
    "content": "module example1\n\nfn test_abc() {\n\tabc01()\n}\n"
  },
  {
    "path": "cmd/tools/vcover/testdata/example1/internal_abc10_abc30_test.v",
    "content": "module example1\n\nfn test_abc() {\n\tabc10()\n\tabc11()\n\tabc12()\n\tabc13()\n\tabc14()\n\tabc15()\n\tabc16()\n\tabc17()\n\tabc18()\n\tabc19()\n\tabc20()\n\tabc21()\n\tabc22()\n\tabc23()\n\tabc24()\n\tabc25()\n\tabc26()\n\tabc27()\n\tabc28()\n\tabc29()\n\tabc30()\n}\n"
  },
  {
    "path": "cmd/tools/vcover/testdata/example1/internal_abc20_abc25_test.v",
    "content": "module example1\n\nfn test_abc() {\n\tabc20()\n\tabc21()\n\tabc22()\n\tabc23()\n\tabc24()\n\tabc25()\n}\n"
  },
  {
    "path": "cmd/tools/vcover/testdata/example1/v.mod",
    "content": ""
  },
  {
    "path": "cmd/tools/vcover/testdata/example2/condition.v",
    "content": "module example2\n\npub fn condition() int {\n\tmut res := 0\n\t$if condition1 ? {\n\t\tres += 1\n\t}\n\t$if condition2 ? {\n\t\tres += 2\n\t}\n\t$if condition3 ? {\n\t\tres += 4\n\t}\n\t$if condition4 ? {\n\t\tres += 8\n\t}\n\t$if condition5 ? {\n\t\tres += 16\n\t}\n\t$if condition6 ? {\n\t\tres += 32\n\t}\n\t$if condition7 ? {\n\t\tres += 64\n\t}\n\t$if condition8 ? {\n\t\treturn 128\n\t}\n\treturn res\n}\n"
  },
  {
    "path": "cmd/tools/vcover/testdata/example2/condition_test.v",
    "content": "import example2\n\nfn test_condition() {\n\tprintln(example2.condition())\n}\n"
  },
  {
    "path": "cmd/tools/vcover/testdata/example2/runtime_condition.v",
    "content": "module example2\n\nimport os\n\npub fn runtime_condition() int {\n\tmut res := 0\n\tbranch := os.getenv('CONDITION')\n\tif branch == '' {\n\t\treturn res\n\t}\n\tif branch.contains('1') {\n\t\tres += 1\n\t}\n\tif branch.contains('2') {\n\t\tres += 2\n\t}\n\tif branch.contains('3') {\n\t\tres += 4\n\t}\n\tif branch.contains('4') {\n\t\tres += 8\n\t}\n\tif branch.contains('5') {\n\t\tres += 16\n\t}\n\tif branch.contains('6') {\n\t\tres += 32\n\t}\n\tif branch.contains('7') {\n\t\tres += 64\n\t}\n\tif branch.contains('8') {\n\t\tres += 128\n\t}\n\treturn res\n}\n"
  },
  {
    "path": "cmd/tools/vcover/testdata/example2/runtime_condition_test.v",
    "content": "import example2\n\nfn test_runtime_condition() {\n\tprintln(example2.runtime_condition())\n}\n"
  },
  {
    "path": "cmd/tools/vcover/testdata/example2/v.mod",
    "content": ""
  },
  {
    "path": "cmd/tools/vcover/testdata/simple/simple.v",
    "content": "module simple\n\npub fn sum() int {\n\tmut res := 0\n\tfor i in 1 .. 5 {\n\t\tres += i\n\t}\n\treturn res\n}\n\npub fn mul() int {\n\tmut res := 1\n\tfor i in 1 .. 5 {\n\t\tres *= i\n\t}\n\t// the lines here are just to introduce an asymmetry in the reported coverage lines\n\tc := res * 2\n\t_ := c * 10\n\treturn res\n}\n\npub const a_const = f()\n\nfn f() int {\n\treturn 50 // this should be executed always\n}\n"
  },
  {
    "path": "cmd/tools/vcover/testdata/simple/t1_test.v",
    "content": "import simple\n\nfn test_sum() {\n\ts := simple.sum()\n\tassert s == 10\n\tprintln(s)\n}\n"
  },
  {
    "path": "cmd/tools/vcover/testdata/simple/t2_test.v",
    "content": "import simple\n\nfn test_mul() {\n\tm := simple.mul()\n\tassert m == 24\n\tprintln(m)\n}\n"
  },
  {
    "path": "cmd/tools/vcover/testdata/simple/v.mod",
    "content": ""
  },
  {
    "path": "cmd/tools/vcreate/project_model_bin.v",
    "content": "module main\n\nimport os\n\nfn (mut c Create) set_bin_project_files() {\n\tbase := if c.new_dir { c.name } else { '' }\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'main.v')\n\t\tcontent: \"module main\n\nfn main() {\n\tprintln('Hello World!')\n}\n\"\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vcreate/project_model_lib.v",
    "content": "module main\n\nimport os\n\nfn (mut c Create) set_lib_project_files() {\n\tbase := if c.new_dir { c.name } else { '' }\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, c.name + '.v')\n\t\tcontent: 'module ${c.name}\n\n// square calculates the second power of `x`\npub fn square(x int) int {\n\treturn x * x\n}\n'\n\t}\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'tests', 'square_test.v')\n\t\tcontent: 'import ${c.name}\n\nfn test_square() {\n\tassert ${c.name}.square(2) == 4\n}\n'\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vcreate/project_model_web.v",
    "content": "module main\n\nimport os\n\nfn (mut c Create) set_web_project_files() {\n\tbase := if c.new_dir { c.name } else { '' }\n\n\t// v source code\n\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'main.v')\n\t\tcontent: \"module main\n\nimport veb\nimport db.sqlite\nimport os\n\nstruct Context {\n\tveb.Context\n}\n\nstruct App {\n\tveb.StaticHandler\n\tdb sqlite.DB\n}\n\npub fn (app &App) index(mut ctx Context) veb.Result {\n\ttitle := 'veb app'\n\treturn \\$veb.html()\n}\n\nfn main() {\n\tmut db := sqlite.connect(os.resource_abs_path('app.db'))!\n\tsql db {\n\t\tcreate table User\n\t\tcreate table Product\n\t}!\n\tdefer { db.close() or { panic(err) } }\n\n\tmut app := &App{\n\t\tdb: db\n\t}\n\tapp.handle_static(os.resource_abs_path('static'), true)!\n\tveb.run[App, Context](mut app, 8082)\n}\n\"\n\t}\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'user_model.v')\n\t\tcontent: \"module main\n\n@[table: 'users']\npub struct User {\nmut:\n\tid       int    @[primary; sql: serial]\n\tusername string @[unique]\n\tpassword string\n\tactive   bool\n\tproducts []Product @[fkey: 'user_id']\n}\n\"\n\t}\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'user_view.v')\n\t\tcontent: \"module main\n\nimport veb\n\n@['/api/users'; get]\npub fn (app &App) api_get_users(mut ctx Context) veb.Result {\n\ttoken := ctx.req.header.get_custom('token') or { '' }\n\tif !app.verify_auth(token) {\n\t\tctx.res.set_status(.unauthorized)\n\t\treturn ctx.text('Not valid token')\n\t}\n\tresponse := app.get_users() or {\n\t\tctx.res.set_status(.bad_request)\n\t\treturn ctx.text('\\${err}')\n\t}\n\treturn ctx.json(response)\n}\n\n@['/api/user'; get]\npub fn (app &App) api_get_user(mut ctx Context) veb.Result {\n\ttoken := ctx.req.header.get_custom('token') or { '' }\n\tuser_id := app.user_auth(token) or {\n\t\tctx.res.set_status(.unauthorized)\n\t\treturn ctx.text('\\${err}')\n\t}\n\tresponse := app.get_user(user_id) or {\n\t\tctx.res.set_status(.bad_request)\n\t\treturn ctx.text('\\${err}')\n\t}\n\treturn ctx.json(response)\n}\n\n@['/api/user/create'; post]\npub fn (app &App) controller_create_user(mut ctx Context) veb.Result {\n\tusername := ctx.form['username'] or { '' }\n\tpassword := ctx.form['password'] or { '' }\n\tif username == '' {\n\t\tctx.res.set_status(.bad_request)\n\t\treturn ctx.text('username cannot be empty')\n\t}\n\tif password == '' {\n\t\tctx.res.set_status(.bad_request)\n\t\treturn ctx.text('password cannot be empty')\n\t}\n\tapp.add_user(username, password) or {\n\t\tctx.res.set_status(.bad_request)\n\t\treturn ctx.text('\\${err}')\n\t}\n\tctx.res.set_status(.created)\n\treturn ctx.text('User created successfully')\n}\n\"\n\t}\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'user_controller.v')\n\t\tcontent: \"module main\n\nimport crypto.bcrypt\n\nfn (app &App) add_user(username string, password string) ! {\n\thashed_password := bcrypt.generate_from_password(password.bytes(), bcrypt.min_cost)!\n\tuser_model := User{\n\t\tusername: username\n\t\tpassword: hashed_password\n\t\tactive:   true\n\t}\n\tsql app.db {\n\t\tinsert user_model into User\n\t}!\n}\n\nfn (app &App) get_users() ![]User {\n\treturn sql app.db {\n\t\tselect from User\n\t}!\n}\n\nfn (app &App) get_user(id int) !User {\n\tresults := sql app.db {\n\t\tselect from User where id == id\n\t}!\n\tif results.len == 0 {\n\t\treturn error('no results')\n\t}\n\treturn results[0]\n}\n\"\n\t}\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'auth_model.v')\n\t\tcontent: \"module main\n\nimport time\nimport crypto.hmac\nimport encoding.base64\nimport crypto.sha256\nimport json\n\nstruct JwtHeader {\n\talg string\n\ttyp string\n}\n\nstruct JwtPayload {\n\tsub         string    // (subject) = Entity to whom the token belongs, usually the user ID;\n\tiss         string    // (issuer) = Token issuer;\n\texp         string    // (expiration) = Timestamp of when the token will expire;\n\tiat         time.Time // (issued at) = Timestamp of when the token was created;\n\taud         string    // (audience) = Token recipient, represents the application that will use it.\n\tname        string\n\troles       string\n\tpermissions string\n}\n\nfn make_token(user User) string {\n\tsecret := 'SECRET_KEY' // os.getenv('SECRET_KEY')\n\tjwt_header := JwtHeader{'HS256', 'JWT'}\n\tjwt_payload := JwtPayload{\n\t\tsub:  '\\${user.id}'\n\t\tname: '\\${user.username}'\n\t\tiat:  time.now()\n\t}\n\theader := base64.url_encode(json.encode(jwt_header).bytes())\n\tpayload := base64.url_encode(json.encode(jwt_payload).bytes())\n\tsignature := base64.url_encode(hmac.new(secret.bytes(), '\\${header}.\\${payload}'.bytes(),\n\t\tsha256.sum, sha256.block_size).bytestr().bytes())\n\tjwt := '\\${header}.\\${payload}.\\${signature}'\n\treturn jwt\n}\n\"\n\t}\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'auth_view.v')\n\t\tcontent: \"module main\n\nimport veb\n\n@['/api/auth'; post]\npub fn (app &App) api_auth(mut ctx Context) veb.Result {\n\tusername := ctx.form['username'] or { '' }\n\tpassword := ctx.form['password'] or { '' }\n\tresponse := app.do_auth(username, password) or {\n\t\tctx.res.set_status(.bad_request)\n\t\treturn ctx.text('error: \\${err}')\n\t}\n\treturn ctx.json(response)\n}\n\"\n\t}\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'auth_controller.v')\n\t\tcontent: \"module main\n\nimport crypto.bcrypt\nimport crypto.hmac\nimport encoding.base64\nimport crypto.sha256\nimport json\n\nfn (app &App) do_auth(username string, password string) !string {\n\tusers := sql app.db {\n\t\tselect from User where username == username\n\t}!\n\tif users.len == 0 {\n\t\treturn error('user not found')\n\t}\n\tuser := users.first()\n\tif !user.active {\n\t\treturn error('user is not active')\n\t}\n\tbcrypt.compare_hash_and_password(password.bytes(), user.password.bytes()) or {\n\t\treturn error('Failed to auth user, \\${err}')\n\t}\n\treturn make_token(user)\n}\n\nfn (app &App) verify_auth(token string) bool {\n\tif token == '' {\n\t\treturn false\n\t}\n\tsecret := 'SECRET_KEY' // os.getenv('SECRET_KEY')\n\ttoken_split := token.split('.')\n\tsignature_mirror := hmac.new(secret.bytes(), '\\${token_split[0]}.\\${token_split[1]}'.bytes(),\n\t\tsha256.sum, sha256.block_size).bytestr().bytes()\n\tsignature_from_token := base64.url_decode(token_split[2])\n\treturn hmac.equal(signature_from_token, signature_mirror)\n}\n\nfn (app &App) user_auth(token string) !int {\n\tif !app.verify_auth(token) {\n\t\treturn error('Invalid token')\n\t}\n\tjwt_payload_stringify := base64.url_decode_str(token.split('.')[1])\n\tjwt_payload := json.decode(JwtPayload, jwt_payload_stringify) or { return err }\n\treturn jwt_payload.sub.int()\n}\n\"\n\t}\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'product_model.v')\n\t\tcontent: \"module main\n\n@[table: 'products']\nstruct Product {\n\tid         int @[primary; sql: serial]\n\tuser_id    int\n\tname       string @[sql_type: 'TEXT']\n\tcreated_at string @[default: 'CURRENT_TIMESTAMP']\n}\n\"\n\t}\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'product_view.v')\n\t\tcontent: \"module main\n\nimport veb\n\n@['/products'; get]\npub fn (app &App) products(mut ctx Context) veb.Result {\n\ttoken := ctx.get_cookie('token') or {\n\t\tctx.res.set_status(.bad_request)\n\t\treturn ctx.text('Cookie not found')\n\t}\n\tuser_id := app.user_auth(token) or {\n\t\tctx.res.set_status(.unauthorized)\n\t\treturn ctx.text('\\${err}')\n\t}\n\tuser := app.get_user(user_id) or {\n\t\tctx.res.set_status(.bad_request)\n\t\treturn ctx.text('\\${err}')\n\t}\n\treturn \\$veb.html()\n}\n\n@['/api/products'; get]\npub fn (app &App) api_get_products(mut ctx Context) veb.Result {\n\ttoken := ctx.req.header.get_custom('token') or { '' }\n\tuser_id := app.user_auth(token) or {\n\t\tctx.res.set_status(.unauthorized)\n\t\treturn ctx.text('\\${err}')\n\t}\n\tresponse := app.get_user_products(user_id) or {\n\t\tctx.res.set_status(.bad_request)\n\t\treturn ctx.text('\\${err}')\n\t}\n\treturn ctx.json(response)\n}\n\n@['/api/product/create'; post]\npub fn (app &App) api_create_product(mut ctx Context) veb.Result {\n\tproduct_name := ctx.form['product_name'] or { '' }\n\tif product_name == '' {\n\t\tctx.res.set_status(.bad_request)\n\t\treturn ctx.text('product name cannot be empty')\n\t}\n\ttoken := ctx.req.header.get_custom('token') or { '' }\n\tuser_id := app.user_auth(token) or {\n\t\tctx.res.set_status(.unauthorized)\n\t\treturn ctx.text('\\${err}')\n\t}\n\tapp.add_product(product_name, user_id) or {\n\t\tctx.res.set_status(.bad_request)\n\t\treturn ctx.text('\\${err}')\n\t}\n\tctx.res.set_status(.created)\n\treturn ctx.text('product created successfully')\n}\n\"\n\t}\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'product_controller.v')\n\t\tcontent: 'module main\n\nfn (app &App) add_product(product_name string, user_id int) ! {\n\tproduct_model := Product{\n\t\tname:    product_name\n\t\tuser_id: user_id\n\t}\n\tsql app.db {\n\t\tinsert product_model into Product\n\t}!\n}\n\nfn (app &App) get_user_products(user_id int) ![]Product {\n\treturn sql app.db {\n\t\tselect from Product where user_id == user_id\n\t}!\n}\n'\n\t}\n\n\t// html content\n\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'templates', 'index.html')\n\t\tcontent: \"<!DOCTYPE html>\n<html>\n<head>\n\t<!--Let browser know website is optimized for mobile-->\n\t<meta charset='UTF-8' name='viewport' content='width=device-width, initial-scale=1.0'>\n\t<!-- Compiled and minified CSS -->\n\t<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css'>\n\t<!-- Compiled and minified JavaScript -->\n\t<script src='https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js'></script>\n\t<!-- Material UI icons -->\n\t<link href='https://fonts.googleapis.com/icon?family=Material+Icons' rel='stylesheet'>\n\t<title>\\${title}</title>\n</head>\n<body>\n\t<div>@include 'layout/header.html'</div>\n\t<div  class='card-panel center-align' style='max-width: 240px; padding: 10px; margin: 10px; border-radius: 5px;'>\n\t\t<form id='index_form' method='post' action=''>\n\t\t\t<div style='display:flex; flex-direction: column;'>\n\t\t\t\t<input type='text' name='username' placeholder='Username' required autofocus>\n\t\t\t\t<input type='password' name='password' placeholder='Password' required>\n\t\t\t</div>\n\t\t\t<div style='margin-top: 10px;'>\n\t\t\t\t<input class='waves-effect waves-light btn-small' type='submit' onclick='login()' formaction='javascript:void(0);' value='Login'>\n\t\t\t\t<input class='waves-effect waves-light btn-small' type='submit' onclick='addUser()' formaction='javascript:void(0);' value='Register'>\n\t\t\t</div>\n\t\t</form>\n\t</div>\n\t<script type='text/javascript'>\n\t\t// function eraseCookie(name) {\n\t\t//     document.cookie = name + '=; Max-Age=0'\n\t\t// }\n\t\tasync function addUser() {\n\t\t\tconst form = document.querySelector('#index_form');\n\t\t\tconst formData = new FormData(form);\n\t\t\tawait fetch('/api/user/create', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: formData\n\t\t\t})\n\t\t\t\t.then( async (response) => {\n\t\t\t\t\tif (response.status !== 201) {\n\t\t\t\t\t\tthrow await response.text()\n\t\t\t\t\t}\n\t\t\t\t\treturn await response.text()\n\t\t\t\t})\n\t\t\t\t.then((data) => {\n\t\t\t\t\talert('User created successfully')\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\talert(error);\n\t\t\t\t});\n\t\t}\n\t\tasync function login() {\n\t\t\tconst form = document.querySelector('#index_form');\n\t\t\tconst formData = new FormData(form);\n\t\t\tawait fetch('/api/auth', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: formData\n\t\t\t})\n\t\t\t\t.then( async (response) => {\n\t\t\t\t\tif (response.status !== 200) {\n\t\t\t\t\t\tthrow await response.text()\n\t\t\t\t\t}\n\t\t\t\t\treturn response.json()\n\t\t\t\t})\n\t\t\t\t.then((data) => {\n\t\t\t\t\tdocument.cookie = 'token='+data+';';\n\t\t\t\t\twindow.location.href = '/products'\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\talert(error);\n\t\t\t\t});\n\t\t}\n\t</script>\n</body>\n</html>\n\"\n\t}\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'templates', 'products.html')\n\t\tcontent: \"<!DOCTYPE html>\n<html>\n<head>\n\t<!--Let browser know website is optimized for mobile-->\n\t<meta charset='UTF-8' name='viewport' content='width=device-width, initial-scale=1.0'>\n\n\t<!-- Compiled and minified CSS -->\n\t<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css'>\n\n\t<!-- Compiled and minified JavaScript -->\n\t<script src='https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js'></script>\n\n\t<!-- Material UI icons -->\n\t<link href='https://fonts.googleapis.com/icon?family=Material+Icons' rel='stylesheet'>\n\n    @css '/css/products.css'\n\n\t<title>Login</title>\n</head>\n<body>\n\t<div>@include 'layout/header.html'</div>\n\t<!-- <button onclick='document.location.reload(true)'>Lala</button> -->\n\t<form id='product_form' method='post' action=''>\n\t\t<div class='row'>\n\t\t\t<div class='input-field col s2'>\n\t\t\t<input id='product_name' name='product_name'  type='text' class='validate'>\n\t\t\t<label class='active' for='product_name'>product name</label>\n\t\t\t</div>\n\t\t\t<div style='margin-top: 10px;'>\n\t\t\t <input class='waves-effect waves-light btn-small' type='submit' onclick='addProduct()' formaction='javascript:void(0);' value='Register' required autofocus>\n\t\t\t</div>\n\t\t</div>\n\t\t<!-- <div style='width: 20; height: 300;'>\n\t\t\t<input type='text' name='product_name' placeholder='product name' required autofocus>\n\t\t</div> -->\n\t</form>\n\t<script type='text/javascript'>\n\t\tfunction getCookie(cookieName) {\n\t\t\tlet cookie = {};\n\t\t\tdocument.cookie.split(';').forEach(function(el) {\n\t\t\t\tlet [key,value] = el.split('=');\n\t\t\t\tcookie[key.trim()] = value;\n\t\t\t})\n\t\t\treturn cookie[cookieName];\n\t\t}\n\t\tasync function addProduct() {\n\t\t\tconst form = document.querySelector('#product_form');\n\t\t\tconst formData = new FormData(form);\n\t\t\tconsole.log(getCookie('token'));\n\t\t\tawait fetch('/api/product/create', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: formData,\n\t\t\t\theaders :{\n\t\t\t\t\ttoken: getCookie('token')\n\t\t\t\t}\n\t\t\t})\n\t\t\t.then( async (response) => {\n\t\t\t\tif (response.status !== 201) {\n\t\t\t\t\tthrow await response.text()\n\t\t\t\t}\n\t\t\t\treturn await response.text()\n\t\t\t})\n\t\t\t.then((data) => {\n\t\t\t\t//  alert('Product created successfully')\n\t\t\t\tdocument.location.reload()\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\talert(error);\n\t\t\t});\n\t\t}\n\t</script>\n\t<div class='products-table card-panel'>\n\t\t<table class='highlight striped responsive-table'>\n\t\t\t<thead>\n\t\t\t<tr>\n\t\t\t\t<th>ID</th>\n\t\t\t\t<th>Name</th>\n\t\t\t\t<th>Created date</th>\n\t\t\t</tr>\n\t\t\t</thead>\n            <tbody>\n            @for product in user.products\n            <tr>\n                <td>\\${product.id}</td>\n                <td>\\${product.name}</td>\n                <td>\\${product.created_at}</td>\n            </tr>\n            @end\n            </tbody>\n\t\t</table>\n\t</div>\n</body>\n</html>\n\"\n\t}\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'templates', 'layout', 'header.html')\n\t\tcontent: \"<nav>\n\t<div class='nav-wrapper'>\n\t\t<a href='javascript:window.history.back();' class='left'>\n\t\t\t<i class='material-icons'>arrow_back_ios_new</i>\n\t\t</a>\n\t\t<a href='/'>\n\t\t\tveb\n\t\t</a>\n\t\t<ul id='nav-mobile' class='right'>\n\t\t\t<li><a href='https://github.com/vlang/v'>github</a></li>\n\t\t\t<li><a href='https://vlang.io/'>website</a></li>\n\t\t\t<li><a href='https://github.com/sponsors/medvednikov'>support</a></li>\n\t\t</ul>\n\t</div>\n</nav>\n\"\n\t}\n\tc.files << ProjectFiles{\n\t\tpath:    os.join_path(base, 'static', 'css', 'products.css')\n\t\tcontent: 'h1.title {\n\tfont-family: Arial, Helvetica, sans-serif;\n\tcolor: #3b7bbf;\n}\n\ndiv.products-table {\n\tborder: 1px solid;\n\tmax-width: 720px;\n\tpadding: 10px;\n\tmargin: 10px;\n}\n'\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vcreate/tests/init.expect",
    "content": "#!/usr/bin/env expect\n\nset timeout 3\n\n# Pass v_root as arg, since we chdir into a temp directory during testing and create a project there.\nset v_root [lindex $argv 0]\n\nspawn $v_root/v init\n\nexpect \"Input your project description: \" { send \"\\r\" } timeout { exit 1 }\nexpect \"Input your project version: (0.0.0) \" { send \"\\r\" } timeout { exit 1 }\nexpect \"Input your project license: (MIT) \" { send \"\\r\" } timeout { exit 1 }\n# The completion message is verified in `vcreate_init_test.v`.\n\nexpect eof\n"
  },
  {
    "path": "cmd/tools/vcreate/tests/init_in_dir_with_invalid_mod_name.expect",
    "content": "#!/usr/bin/env expect\n\nset timeout 3\n\n# Pass v_root as arg, since we chdir into a temp directory during testing and create a project there.\nset v_root [lindex $argv 0]\nset project_dir_name [lindex $argv 1]\nset corrected_mod_name [lindex $argv 2]\n\nspawn $v_root/v init\n\nexpect \"Input your project description: \" { send \"\\r\" } timeout { exit 1 }\nexpect \"Input your project version: (0.0.0) \" { send \"\\r\" } timeout { exit 1 }\nexpect \"Input your project license: (MIT) \" { send \"\\r\" } timeout { exit 1 }\nexpect \"The directory name `$project_dir_name` is invalid as a module name. The module name in `v.mod` was set to `$corrected_mod_name`\" {} timeout { exit 1 }\nexpect \"Created binary (application) project `$corrected_mod_name`\" {} timeout {} timeout { exit 1 }\n\nexpect eof\n"
  },
  {
    "path": "cmd/tools/vcreate/tests/init_with_model_arg.expect",
    "content": "#!/usr/bin/env expect\n\nset timeout 3\n\n# Pass v_root as arg, since we chdir into a temp directory during testing and create a project there.\nset v_root [lindex $argv 0]\nset model [lindex $argv 1]\n\nspawn $v_root/v init $model\n\nexpect \"Input your project description: \" { send \"My Awesome V Application.\\r\" } timeout { exit 1 }\nexpect \"Input your project version: (0.0.0) \" { send \"0.0.1\\r\" } timeout { exit 1 }\nexpect \"Input your project license: (MIT) \" { send \"\\r\" } timeout { exit 1 }\nexpect \"Initialising ...\" {} timeout { exit 1 }\n# The completion message is verified in `vcreate_init_test.v`.\n\nexpect eof\n"
  },
  {
    "path": "cmd/tools/vcreate/tests/new_with_model_arg.expect",
    "content": "#!/usr/bin/env expect\n\nset timeout 3\n\n# Pass v_root as arg, since we chdir into a temp directory during testing and create a project there.\nset v_root [lindex $argv 0]\nset model [lindex $argv 1]\nset project_name [lindex $argv 2]\n\nspawn $v_root/v new $model $project_name\n\nexpect \"Input your project description: \" { send \"My Awesome V Project.\\r\" } timeout { exit 1 }\nexpect \"Input your project version: (0.0.0) \" { send \"0.0.1\\r\" } timeout { exit 1 }\nexpect \"Input your project license: (MIT) \" { send \"\\r\" } timeout { exit 1 }\nexpect \"Initialising ...\" {} timeout { exit 1 }\nexpect \"Created library project `$project_name`\" {} timeout { exit 1 }\n\nexpect eof\n"
  },
  {
    "path": "cmd/tools/vcreate/tests/new_with_name_arg.expect",
    "content": "#!/usr/bin/env expect\n\nset timeout 3\n\n# Pass v_root as arg, since we chdir into a temp directory during testing and create a project there.\nset v_root [lindex $argv 0]\nset project_name [lindex $argv 1]\n\nspawn $v_root/v new $project_name\n\nexpect \"Input your project description: \" { send \"\\r\" } timeout { exit 1 }\nexpect \"Input your project version: (0.0.0) \" { send \"\\r\" } timeout { exit 1 }\nexpect \"Input your project license: (MIT) \" { send \"\\r\" } timeout { exit 1 }\nexpect \"Initialising ...\" {} timeout { exit 1 }\nexpect \"Created binary (application) project `$project_name`\" {} timeout { exit 1 }\n\nexpect eof\n"
  },
  {
    "path": "cmd/tools/vcreate/tests/new_with_no_arg.expect",
    "content": "#!/usr/bin/env expect\n\nset timeout 3\n\n# Pass v_root as arg, since we chdir into a temp directory during testing and create a project there.\nset v_root [lindex $argv 0]\nset project_name [lindex $argv 1]\n\nspawn $v_root/v new\n\nexpect \"Input your project name: \" { send \"$project_name\\r\" } timeout { exit 1 }\nexpect \"Input your project description: \" { send \"My Awesome V Project.\\r\" } timeout { exit 1 }\nexpect \"Input your project version: (0.0.0) \" { send \"0.1.0\\r\" } timeout { exit 1 }\nexpect \"Input your project license: (MIT) \" { send \"GPL\\r\" } timeout { exit 1 }\nexpect \"Initialising ...\" {} timeout { exit 1 }\nexpect \"Created binary (application) project `$project_name`\" {} timeout { exit 1 }\n\nexpect eof\n"
  },
  {
    "path": "cmd/tools/vcreate/vcreate.v",
    "content": "// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.\n// Use of this source code is governed by an MIT license that can be found in the LICENSE file.\nmodule main\n\nimport os\nimport cli { Command, Flag }\n\n// Note: this program follows a similar convention as Rust cargo:\n// `init` creates the structure of project in the current directory,\n// `new` creates the structure of a project in a sub directory.\n\nstruct Create {\nmut:\n\tname        string\n\tdescription string\n\tversion     string\n\tlicense     string\n\tfiles       []ProjectFiles\n\tnew_dir     bool\n\ttemplate    Template\n}\n\nstruct ProjectFiles {\n\tpath    string\n\tcontent string\n}\n\nenum Template {\n\tbin\n\tlib\n\tweb\n}\n\nfn main() {\n\tflags := [\n\t\tFlag{\n\t\t\tflag:        .bool\n\t\t\tname:        'bin'\n\t\t\tdescription: 'Use the template for an executable application [default].'\n\t\t},\n\t\tFlag{\n\t\t\tflag:        .bool\n\t\t\tname:        'lib'\n\t\t\tdescription: 'Use the template for a library project.'\n\t\t},\n\t\tFlag{\n\t\t\tflag:        .bool\n\t\t\tname:        'web'\n\t\t\tdescription: 'Use the template for a vweb project.'\n\t\t},\n\t]\n\tmut cmd := Command{\n\t\tflags:      [\n\t\t\tFlag{\n\t\t\t\tflag:        .bool\n\t\t\t\tname:        'help'\n\t\t\t\tdescription: 'Print help information.'\n\t\t\t\tglobal:      true\n\t\t\t},\n\t\t]\n\t\tposix_mode: true\n\t\tcommands:   [\n\t\t\tCommand{\n\t\t\t\tname:        'new'\n\t\t\t\tusage:       '<project_name>'\n\t\t\t\tdescription: [\n\t\t\t\t\t'Creates a new V project in a directory with the specified project name.',\n\t\t\t\t\t'',\n\t\t\t\t\t'A setup prompt is started to create a `v.mod` file with the projects metadata.',\n\t\t\t\t\t'The <project_name> argument can be omitted and entered in the prompts dialog.',\n\t\t\t\t\t'If git is installed, `git init` will be performed during the setup.',\n\t\t\t\t].join_lines()\n\t\t\t\tparent:      &Command{\n\t\t\t\t\tname: 'v'\n\t\t\t\t}\n\t\t\t\tposix_mode:  true\n\t\t\t\tflags:       flags\n\t\t\t\tpre_execute: validate\n\t\t\t\texecute:     new_project\n\t\t\t},\n\t\t\tCommand{\n\t\t\t\tname:        'init'\n\t\t\t\tdescription: [\n\t\t\t\t\t'Sets up a V project within the current directory.',\n\t\t\t\t\t'',\n\t\t\t\t\t\"If no `v.mod` exists, a setup prompt is started to create one with the project's metadata.\",\n\t\t\t\t\t'If no `.v` file exists, a project template is generated. If the current directory is not a',\n\t\t\t\t\t'git project and git is installed, `git init` will be performed during the setup.',\n\t\t\t\t].join_lines()\n\t\t\t\tparent:      &Command{\n\t\t\t\t\tname: 'v'\n\t\t\t\t}\n\t\t\t\tposix_mode:  true\n\t\t\t\tflags:       flags\n\t\t\t\tpre_execute: validate\n\t\t\t\texecute:     init_project\n\t\t\t},\n\t\t]\n\t}\n\tcmd.parse(os.args)\n}\n\nfn validate(cmd Command) ! {\n\tif cmd.flags.get_bool('help')! {\n\t\tcmd.execute_help()\n\t\texit(0)\n\t}\n\tif cmd.args.len > 1 {\n\t\tcerror('too many arguments.\\n')\n\t\tcmd.execute_help()\n\t\texit(2)\n\t}\n}\n\nfn new_project(cmd Command) ! {\n\tmut c := Create{\n\t\ttemplate: get_template(cmd)\n\t\tnew_dir:  true\n\t}\n\tc.prompt(cmd.args)\n\tprintln('Initialising ...')\n\t// Generate project files based on `Create.files`.\n\tc.create_files_and_directories()\n\tc.write_vmod()\n\tc.write_gitattributes()\n\tc.write_editorconfig()\n\tc.create_git_repo(c.name)\n}\n\nfn init_project(cmd Command) ! {\n\tmut c := Create{\n\t\ttemplate: get_template(cmd)\n\t}\n\tdir_name := check_name(os.file_name(os.getwd()))\n\tif !os.exists('v.mod') {\n\t\tmod_dir_has_hyphens := dir_name.contains('-')\n\t\tc.name = if mod_dir_has_hyphens { dir_name.replace('-', '_') } else { dir_name }\n\t\tc.prompt(cmd.args)\n\t\tc.write_vmod()\n\t\tif mod_dir_has_hyphens {\n\t\t\tprintln('The directory name `${dir_name}` is invalid as a module name. The module name in `v.mod` was set to `${c.name}`')\n\t\t}\n\t}\n\tprintln('Initialising ...')\n\tc.create_files_and_directories()\n\tc.write_gitattributes()\n\tc.write_editorconfig()\n\tc.create_git_repo('.')\n}\n\nfn (mut c Create) prompt(args []string) {\n\tif c.name == '' {\n\t\tc.name = check_name(args[0] or { os.input('Input your project name: ') })\n\t\tif c.name == '' {\n\t\t\teprintln('')\n\t\t\tcerror('project name cannot be empty')\n\t\t\texit(1)\n\t\t}\n\t\tif c.name.contains('-') {\n\t\t\teprintln('')\n\t\t\tcerror('`${c.name}` should not contain hyphens')\n\t\t\texit(1)\n\t\t}\n\t\tif os.is_dir(c.name) {\n\t\t\teprintln('')\n\t\t\tcerror('`${c.name}` folder already exists')\n\t\t\texit(3)\n\t\t}\n\t}\n\tc.description = os.input('Input your project description: ')\n\tdefault_version := '0.0.0'\n\tc.version = os.input('Input your project version: (${default_version}) ')\n\tif c.version == '' {\n\t\tc.version = default_version\n\t}\n\tdefault_license := 'MIT'\n\tc.license = os.input('Input your project license: (${default_license}) ')\n\tif c.license == '' {\n\t\tc.license = default_license\n\t}\n}\n\nfn get_template(cmd Command) Template {\n\tbin := cmd.flags.get_bool('bin') or { false }\n\tlib := cmd.flags.get_bool('lib') or { false }\n\tweb := cmd.flags.get_bool('web') or { false }\n\tif (bin && lib) || (bin && web) || (lib && web) {\n\t\teprintln(\"error: can't use more then one template\")\n\t\texit(2)\n\t}\n\treturn match true {\n\t\tlib { .lib }\n\t\tweb { .web }\n\t\telse { .bin }\n\t}\n}\n\nfn cerror(e string) {\n\teprintln('error: ${e}.')\n}\n\nfn check_name(name string) string {\n\tif name.trim_space().len == 0 {\n\t\teprintln('')\n\t\tcerror('project name cannot be empty')\n\t\texit(1)\n\t}\n\tif name.is_title() {\n\t\tmut cname := name.to_lower()\n\t\tif cname.contains(' ') {\n\t\t\tcname = cname.replace(' ', '_')\n\t\t}\n\t\teprintln('warning: the project name cannot be capitalized, the name will be changed to `${cname}`')\n\t\treturn cname\n\t}\n\tif name.contains(' ') {\n\t\tcname := name.replace(' ', '_')\n\t\teprintln('warning: the project name cannot contain spaces, the name will be changed to `${cname}`')\n\t\treturn cname\n\t}\n\treturn name\n}\n\nfn (c &Create) write_vmod() {\n\tpath := if c.new_dir { '${c.name}/v.mod' } else { 'v.mod' }\n\tcontent := \"Module {\n\tname: '${c.name}'\n\tdescription: '${c.description}'\n\tversion: '${c.version}'\n\tlicense: '${c.license}'\n\tdependencies: []\n}\n\"\n\tos.write_file(path, content) or { panic(err) }\n}\n\nfn (c &Create) write_gitattributes() {\n\tpath := if c.new_dir { '${c.name}/.gitattributes' } else { '.gitattributes' }\n\tif !c.new_dir && os.exists(path) {\n\t\treturn\n\t}\n\tcontent := '* text=auto eol=lf\n*.bat eol=crlf\n\n*.v linguist-language=V\n*.vv linguist-language=V\n*.vsh linguist-language=V\nv.mod linguist-language=V\n.vdocignore linguist-language=ignore\n'\n\tos.write_file(path, content) or { panic(err) }\n}\n\nfn (c &Create) write_editorconfig() {\n\tpath := if c.new_dir { '${c.name}/.editorconfig' } else { '.editorconfig' }\n\tif !c.new_dir && os.exists(path) {\n\t\treturn\n\t}\n\tcontent := '[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.v]\nindent_style = tab\n'\n\tos.write_file(path, content) or { panic(err) }\n}\n\nfn (c &Create) create_git_repo(dir string) {\n\t// Initialize git and add a .gitignore file.\n\tif !os.is_dir('${dir}/.git') {\n\t\tres := os.execute('git init ${dir}')\n\t\tif res.exit_code != 0 {\n\t\t\teprintln('')\n\t\t\tcerror('unable to initialize a git repository')\n\t\t\texit(4)\n\t\t}\n\t}\n\tignore_path := '${dir}/.gitignore'\n\tif os.exists(ignore_path) {\n\t\treturn\n\t}\n\tignore_content := '# Binaries for programs and plugins\nmain\n${c.name}\n*.exe\n*.exe~\n*.so\n*.dylib\n*.dll\n\n# Ignore binary output folders\nbin/\n\n# Ignore common editor/system specific metadata\n.DS_Store\n.idea/\n.vscode/\n*.iml\n\n# ENV\n.env\n\n# vweb and database\n*.db\n*.js\n\n# Ignore installed modules through `v install --local`:\nmodules/\n'\n\tos.write_file(ignore_path, ignore_content) or {}\n}\n\nfn (mut c Create) create_files_and_directories() {\n\t// Set project template files for `v new` or when no `.v` files exists during `v init`.\n\tif c.new_dir || os.walk_ext('.', '.v').len == 0 {\n\t\tmatch c.template {\n\t\t\t.bin { c.set_bin_project_files() }\n\t\t\t.lib { c.set_lib_project_files() }\n\t\t\t.web { c.set_web_project_files() }\n\t\t}\n\t}\n\tfor file in c.files {\n\t\tos.mkdir_all(os.dir(file.path)) or { panic(err) }\n\t\tos.write_file(file.path, file.content) or { panic(err) }\n\t}\n\tkind := match c.template {\n\t\t.bin { 'binary (application)' }\n\t\t.lib { 'library' }\n\t\t.web { 'web' }\n\t}\n\tprintln('Created ${kind} project `${c.name}`')\n\tc.print_web_template_notes()\n}\n\nfn (c &Create) print_web_template_notes() {\n\tsqlite_header_path := os.join_path(@VEXEROOT, 'thirdparty', 'sqlite', 'sqlite3.h')\n\tif !should_print_windows_web_sqlite_note(c.template, os.user_os(), os.exists(sqlite_header_path)) {\n\t\treturn\n\t}\n\tprintln('Note: this web template uses `db.sqlite`.')\n\tprintln('On Windows, run `${os.quoted_path(@VEXE)} vlib/db/sqlite/install_thirdparty_sqlite.vsh`')\n\tprintln('once, then run your app again.')\n}\n\nfn should_print_windows_web_sqlite_note(template Template, user_os string, has_sqlite_header bool) bool {\n\treturn template == .web && user_os == 'windows' && !has_sqlite_header\n}\n"
  },
  {
    "path": "cmd/tools/vcreate/vcreate_init_test.v",
    "content": "// vtest retry: 3\nimport os\nimport v.vmod\n\nconst vroot = os.quoted_path(@VEXEROOT)\nconst vexe = os.quoted_path(@VEXE)\n// Expect has to be installed for the test.\nconst expect_exe = os.quoted_path(os.find_abs_path_of_executable('expect') or {\n\teprintln('skipping test, since expect is missing')\n\texit(0)\n})\n// Directory that contains the Expect scripts used in the test.\nconst expect_tests_path = os.join_path(@VEXEROOT, 'cmd', 'tools', 'vcreate', 'tests')\nconst test_project_dir_name = 'test_project'\n// Running tests appends a tsession path to VTMP, which is automatically cleaned up after the test.\n// The following will result in e.g. `$VTMP/tsession_7fe8e93bd740_1612958707536/test_project/`.\nconst test_path = os.join_path(os.vtmp_dir(), test_project_dir_name)\n\nfn testsuite_end() {\n\tos.rmdir_all(test_path) or {}\n}\n\nfn init_and_check() ! {\n\tos.chdir(test_path)!\n\n\t// Keep track of the last modified time of the main file to ensure it is not modified if it already exists.\n\tmain_exists := os.exists('main.v')\n\tmain_last_modified := if main_exists { os.file_last_mod_unix('main.v') } else { 0 }\n\n\t// Initialize project.\n\tos.execute_or_exit('${expect_exe} ${os.join_path(expect_tests_path, 'init.expect')} ${vroot}')\n\n\tx := os.execute_or_exit('${vexe} run .')\n\tassert x.output.trim_space() == 'Hello World!'\n\n\tif main_exists {\n\t\tassert main_last_modified == os.file_last_mod_unix('main.v')\n\t} else {\n\t\tassert os.read_file('main.v')! == [\n\t\t\t'module main\\n',\n\t\t\t'fn main() {',\n\t\t\t\"\tprintln('Hello World!')\",\n\t\t\t'}',\n\t\t\t'',\n\t\t].join_lines()\n\t}\n\n\tassert os.read_file('v.mod')! == [\n\t\t'Module {',\n\t\t\"\tname: '${test_project_dir_name}'\",\n\t\t\"\tdescription: ''\",\n\t\t\"\tversion: '0.0.0'\",\n\t\t\"\tlicense: 'MIT'\",\n\t\t'\tdependencies: []',\n\t\t'}',\n\t\t'',\n\t].join_lines()\n\n\tassert os.read_file('.gitignore')! == [\n\t\t'# Binaries for programs and plugins',\n\t\t'main',\n\t\t'${test_project_dir_name}',\n\t\t'*.exe',\n\t\t'*.exe~',\n\t\t'*.so',\n\t\t'*.dylib',\n\t\t'*.dll',\n\t\t'',\n\t\t'# Ignore binary output folders',\n\t\t'bin/',\n\t\t'',\n\t\t'# Ignore common editor/system specific metadata',\n\t\t'.DS_Store',\n\t\t'.idea/',\n\t\t'.vscode/',\n\t\t'*.iml',\n\t\t'',\n\t\t'# ENV',\n\t\t'.env',\n\t\t'',\n\t\t'# vweb and database',\n\t\t'*.db',\n\t\t'*.js',\n\t\t'',\n\t\t'# Ignore installed modules through `v install --local`:',\n\t\t'modules/',\n\t\t'',\n\t].join_lines()\n\n\tassert os.read_file('.gitattributes')! == [\n\t\t'* text=auto eol=lf',\n\t\t'*.bat eol=crlf',\n\t\t'',\n\t\t'*.v linguist-language=V',\n\t\t'*.vv linguist-language=V',\n\t\t'*.vsh linguist-language=V',\n\t\t'v.mod linguist-language=V',\n\t\t'.vdocignore linguist-language=ignore',\n\t\t'',\n\t].join_lines()\n\n\tassert os.read_file('.editorconfig')! == [\n\t\t'[*]',\n\t\t'charset = utf-8',\n\t\t'end_of_line = lf',\n\t\t'insert_final_newline = true',\n\t\t'trim_trailing_whitespace = true',\n\t\t'',\n\t\t'[*.v]',\n\t\t'indent_style = tab',\n\t\t'',\n\t].join_lines()\n}\n\nfn prepare_test_path() ! {\n\tos.rmdir_all(test_path) or {}\n\tos.mkdir_all(test_path) or {}\n\tos.chdir(test_path)!\n}\n\nfn test_v_init() {\n\tprepare_test_path()!\n\tinit_and_check()!\n}\n\nfn test_v_init_in_git_dir() {\n\tprepare_test_path()!\n\tos.execute_or_exit('git init .')\n\tinit_and_check()!\n}\n\nfn test_v_init_no_overwrite_gitignore() {\n\tprepare_test_path()!\n\tos.write_file('.gitignore', 'foo')!\n\tos.execute_or_exit('${expect_exe} ${os.join_path(expect_tests_path, 'init.expect')} ${vroot}')\n\tassert os.read_file('.gitignore')! == 'foo'\n}\n\nfn test_v_init_no_overwrite_gitattributes_and_editorconfig() {\n\tgit_attributes_content := '*.v linguist-language=V text=auto eol=lf'\n\teditor_config_content := '[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.v]\nindent_style = tab\n'\n\tprepare_test_path()!\n\tos.write_file('.gitattributes', git_attributes_content)!\n\tos.write_file('.editorconfig', editor_config_content)!\n\tres := os.execute_or_exit('${expect_exe} ${os.join_path(expect_tests_path, 'init.expect')} ${vroot}')\n\tassert res.output.contains('Created binary (application) project `${test_project_dir_name}`')\n\tassert os.read_file('.gitattributes')! == git_attributes_content\n\tassert os.read_file('.editorconfig')! == editor_config_content\n}\n\nfn test_v_init_in_dir_with_invalid_mod_name_input() {\n\t// A project with a directory name with hyphens, which is invalid for a module name.\n\tdir_name_with_invalid_mod_name := 'my-proj'\n\tcorrected_mod_name := 'my_proj'\n\tproj_path := os.join_path(os.vtmp_dir(), dir_name_with_invalid_mod_name)\n\tos.mkdir_all(proj_path) or {}\n\tos.chdir(proj_path)!\n\tos.execute_or_exit('${expect_exe} ${os.join_path(expect_tests_path, 'init_in_dir_with_invalid_mod_name.expect')} ${vroot} ${dir_name_with_invalid_mod_name} ${corrected_mod_name}')\n\t// Assert mod data set in `new_with_model_arg.expect`.\n\tmod := vmod.from_file(os.join_path(proj_path, 'v.mod')) or {\n\t\tassert false, err.str()\n\t\treturn\n\t}\n\tassert mod.name == corrected_mod_name\n}\n\nfn test_v_init_with_model_arg_input() {\n\tprepare_test_path()!\n\tmodel := '--lib'\n\tres := os.execute_or_exit('${expect_exe} ${os.join_path(expect_tests_path, 'init_with_model_arg.expect')} ${vroot} ${model}')\n\tassert res.output.contains('Created library project `${test_project_dir_name}`'), res.output\n\tproject_path := os.join_path(test_path)\n\tmod := vmod.from_file(os.join_path(project_path, 'v.mod')) or {\n\t\tassert false, err.str()\n\t\treturn\n\t}\n\tassert mod.name == test_project_dir_name\n\tassert mod.description == 'My Awesome V Application.'\n\tassert mod.version == '0.0.1'\n\tassert mod.license == 'MIT'\n\t// Assert existence of a model-specific file.\n\tassert os.exists(os.join_path(project_path, 'tests', 'square_test.v'))\n}\n"
  },
  {
    "path": "cmd/tools/vcreate/vcreate_new_test.v",
    "content": "import os\nimport v.vmod\n\nconst vroot = @VEXEROOT\n// Expect has to be installed for the test.\nconst expect_exe = os.quoted_path(os.find_abs_path_of_executable('expect') or {\n\teprintln('skipping test, since expect is missing')\n\texit(0)\n})\n// Directory that contains the Expect scripts used in the test.\nconst expect_tests_path = os.join_path(@VEXEROOT, 'cmd', 'tools', 'vcreate', 'tests')\n// Running tests appends a tsession path to VTMP, which is automatically cleaned up after the test.\n// The following will result in e.g. `$VTMP/tsession_7fe8e93bd740_1612958707536/test_vcreate_input/`.\nconst test_module_path = os.join_path(os.vtmp_dir(), 'test_vcreate_input')\n\nfn testsuite_begin() {\n\tdump(expect_exe)\n\tdump(test_module_path)\n\tdump(expect_tests_path)\n}\n\nfn testsuite_end() {\n\tos.rmdir_all(test_module_path) or {}\n}\n\nfn prepare_test_path() ! {\n\tos.rmdir_all(test_module_path) or {}\n\tos.mkdir_all(test_module_path) or {}\n\tos.chdir(test_module_path)!\n}\n\nfn test_new_with_no_arg_input() {\n\tprepare_test_path()!\n\tproject_name := 'my_project'\n\tcmd := '${expect_exe} ${os.join_path(expect_tests_path, 'new_with_no_arg.expect')} ${vroot} ${project_name}'\n\tos.execute_opt(cmd) or {\n\t\tdump(cmd)\n\t\tassert false, err.msg()\n\t}\n\t// Assert mod data set in `new_no_arg.expect`.\n\tmod := vmod.from_file(os.join_path(test_module_path, project_name, 'v.mod')) or {\n\t\tassert false, err.str()\n\t\treturn\n\t}\n\tassert mod.name == project_name\n\tassert mod.description == 'My Awesome V Project.'\n\tassert mod.version == '0.1.0'\n\tassert mod.license == 'GPL'\n}\n\nfn test_new_with_name_arg_input() {\n\tprepare_test_path()!\n\tproject_name := 'my_other_project'\n\tcmd := '${expect_exe} ${os.join_path(expect_tests_path, 'new_with_name_arg.expect')} ${vroot} ${project_name}'\n\tos.execute_opt(cmd) or {\n\t\tdump(cmd)\n\t\tassert false, err.msg()\n\t}\n\t// Assert mod data set in `new_with_name_arg.expect`.\n\tmod := vmod.from_file(os.join_path(test_module_path, project_name, 'v.mod')) or {\n\t\tassert false, err.str()\n\t\treturn\n\t}\n\tassert mod.name == project_name\n\tassert mod.description == ''\n\tassert mod.version == '0.0.0'\n\tassert mod.license == 'MIT'\n}\n\nfn test_new_with_model_arg_input() {\n\tprepare_test_path()!\n\tproject_name := 'my_lib'\n\tmodel := '--lib'\n\tcmd := '${expect_exe} ${os.join_path(expect_tests_path, 'new_with_model_arg.expect')} ${vroot} ${model} ${project_name}'\n\tos.execute_opt(cmd) or {\n\t\tdump(cmd)\n\t\tassert false, err.msg()\n\t}\n\tproject_path := os.join_path(test_module_path, project_name)\n\t// Assert mod data set in `new_with_model_arg.expect`.\n\tmod := vmod.from_file(os.join_path(project_path, 'v.mod')) or {\n\t\tassert false, err.str()\n\t\treturn\n\t}\n\tassert mod.name == project_name\n\tassert mod.description == 'My Awesome V Project.'\n\tassert mod.version == '0.0.1'\n\tassert mod.license == 'MIT'\n\t// Assert existence of a model-specific file.\n\tassert os.exists(os.join_path(project_path, 'tests', 'square_test.v'))\n}\n"
  },
  {
    "path": "cmd/tools/vcreate/vcreate_windows_sqlite_note_test.v",
    "content": "module main\n\nfn test_should_print_windows_web_sqlite_note() {\n\tassert should_print_windows_web_sqlite_note(.web, 'windows', false)\n\tassert !should_print_windows_web_sqlite_note(.web, 'windows', true)\n\tassert !should_print_windows_web_sqlite_note(.bin, 'windows', false)\n\tassert !should_print_windows_web_sqlite_note(.lib, 'windows', false)\n\tassert !should_print_windows_web_sqlite_note(.web, 'linux', false)\n}\n"
  },
  {
    "path": "cmd/tools/vdiff.v",
    "content": "import os\nimport flag\nimport term\nimport arrays.diff\n\nfn main() {\n\tmut fp := flag.new_flag_parser(os.args[1..])\n\tfp.application('v diff')\n\tfp.version('0.0.1')\n\tfp.description('Compare files line by line. Example: `v diff examples/hello_world.v examples/log.v`')\n\tfp.arguments_description('file1 file2')\n\tfp.skip_executable()\n\tfp.limit_free_args_to_at_least(2)!\n\n\tif fp.bool('help', `h`, false, 'Show this help screen.') {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\n\targs := fp.finalize() or {\n\t\teprintln('Argument error: ${err}')\n\t\texit(1)\n\t}\n\n\tsrc := os.read_lines(args[0])!\n\tdst := os.read_lines(args[1])!\n\tmut ctx := diff.diff(src, dst)\n\tpatch := ctx.generate_patch(\n\t\tcolorful:     term.can_show_color_on_stdout()\n\t\tblock_header: true\n\t\tunified:      3\n\t)\n\tif patch.len > 0 {\n\t\tprint(patch)\n\t\texit(1)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/.gitattributes",
    "content": "*.ansi text eol=lf\n*.text text eol=lf\n*.html text eol=lf\n"
  },
  {
    "path": "cmd/tools/vdoc/document/comment.v",
    "content": "module document\n\nimport v.token\n\nconst example_pattern = '\\x01 Example: '\n\npub struct DocComment {\npub mut:\n\ttext        string // Raw text content of the comment, excluding the comment token chars ('//, /*, */')\n\tis_multi    bool   // Is a block / multi-line comment\n\tpos         token.Pos\n\tis_readme   bool\n\tfrontmatter map[string]string\n}\n\n// is_example returns true if the contents of this comment is an inline doc example.\n// The current convention is '// Example: <content>'\npub fn (dc DocComment) is_example() bool {\n\treturn dc.text.trim_space().starts_with(example_pattern)\n}\n\n// example returns the content of the inline example body\npub fn (dc DocComment) example() string {\n\treturn dc.text.all_after(example_pattern)\n}\n\n// is_multi_line_example returns true if an example line has no inline code\npub fn (dc DocComment) is_multi_line_example() bool {\n\treturn dc.text.trim_space() == '\\x01 Example:'\n}\n\n// has_triple_backtick returns true if the comment starts or ends a markdown code block\npub fn (dc DocComment) has_triple_backtick() bool {\n\treturn dc.text.starts_with('\\x01 ```')\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/document/doc.v",
    "content": "module document\n\nimport os\nimport time\nimport v.ast\nimport v.checker\nimport v.fmt\nimport v.parser\nimport v.pref\nimport v.scanner\nimport v.token\n\n// SymbolKind categorizes the symbols it documents.\n// The names are intentionally not in order as a guide when sorting the nodes.\npub enum SymbolKind {\n\tnone\n\tconst_group\n\tconstant\n\tvariable\n\tfunction\n\tmethod\n\tinterface\n\ttypedef\n\tenum\n\tenum_field\n\tstruct\n\tstruct_field\n}\n\npub enum Platform {\n\tauto\n\tios\n\tmacos\n\tlinux\n\twindows\n\tfreebsd\n\topenbsd\n\tnetbsd\n\tdragonfly\n\tjs // for interoperability in prefs.OS\n\tandroid\n\ttermux // like android, but note that termux is running on devices natively, not cross compiling from other platforms\n\tsolaris\n\tserenity\n\tplan9\n\tvinix\n\thaiku\n\traw\n\tcross // TODO: add functionality for v doc -cross whenever possible\n}\n\n// copy of pref.os_from_string\npub fn platform_from_string(platform_str string) !Platform {\n\tmatch platform_str {\n\t\t'all', 'cross' { return .cross }\n\t\t'linux' { return .linux }\n\t\t'windows' { return .windows }\n\t\t'ios' { return .ios }\n\t\t'macos' { return .macos }\n\t\t'freebsd' { return .freebsd }\n\t\t'openbsd' { return .openbsd }\n\t\t'netbsd' { return .netbsd }\n\t\t'dragonfly' { return .dragonfly }\n\t\t'js' { return .js }\n\t\t'solaris' { return .solaris }\n\t\t'serenity' { return .serenity }\n\t\t'plan9' { return .plan9 }\n\t\t'vinix' { return .vinix }\n\t\t'android' { return .android }\n\t\t'termux' { return .termux }\n\t\t'haiku' { return .haiku }\n\t\t'nix' { return .linux }\n\t\t'' { return .auto }\n\t\telse { return error('vdoc: invalid platform `${platform_str}`') }\n\t}\n}\n\npub fn platform_from_filename(filename string) Platform {\n\tsuffix := filename.all_after_last('_').all_before('.c.v')\n\tmut platform := platform_from_string(suffix) or { Platform.cross }\n\tif platform == .auto {\n\t\tplatform = .cross\n\t}\n\treturn platform\n}\n\npub fn (sk SymbolKind) str() string {\n\treturn match sk {\n\t\t.const_group { 'Constants' }\n\t\t.function, .method { 'fn' }\n\t\t.interface { 'interface' }\n\t\t.typedef { 'type' }\n\t\t.enum { 'enum' }\n\t\t.struct { 'struct' }\n\t\telse { '' }\n\t}\n}\n\n@[minify]\npub struct Doc {\npub mut:\n\tprefs               &pref.Preferences = new_vdoc_preferences()\n\tbase_path           string\n\ttable               &ast.Table      = ast.new_table()\n\tchecker             checker.Checker = checker.Checker{\n\t\ttable: unsafe { nil }\n\t\tpref:  unsafe { nil }\n\t}\n\tfmt                 fmt.Fmt\n\tfilename            string\n\tpos                 int\n\tpub_only            bool = true\n\twith_comments       bool = true\n\twith_pos            bool\n\twith_head           bool = true\n\tis_vlib             bool\n\ttime_generated      time.Time\n\thead                DocNode\n\tcontents            map[string]DocNode\n\tscoped_contents     map[string]DocNode\n\tparent_mod_name     string\n\torig_mod_name       string\n\textract_vars        bool\n\tfilter_symbol_names []string\n\tcommon_symbols      []string\n\tplatform            Platform\n}\n\n@[minify]\npub struct DocNode {\npub mut:\n\tname        string\n\tcontent     string\n\tcomments    []DocComment\n\tpos         token.Pos\n\tfile_path   string\n\tkind        SymbolKind\n\ttags        []string\n\tparent_name string\n\treturn_type string\n\tchildren    []DocNode\n\tattrs       map[string]string @[json: attributes]\n\tfrom_scope  bool\n\tis_pub      bool @[json: public]\n\tplatform    Platform\n\tis_readme   bool\n\tfrontmatter map[string]string\n}\n\n// new_vdoc_preferences creates a new instance of pref.Preferences tailored for v.doc.\npub fn new_vdoc_preferences() &pref.Preferences {\n\t// vdoc should be able to parse as much user code as possible\n\t// so its preferences should be permissive:\n\tmut pref_ := &pref.Preferences{\n\t\tenable_globals: true\n\t\tis_fmt:         true\n\t}\n\tpref_.fill_with_defaults()\n\treturn pref_\n}\n\n// new creates a new instance of a `Doc` struct.\npub fn new(input_path string) Doc {\n\tmut d := Doc{\n\t\tbase_path:      os.real_path(input_path)\n\t\ttable:          ast.new_table()\n\t\thead:           DocNode{}\n\t\tcontents:       map[string]DocNode{}\n\t\ttime_generated: time.now()\n\t}\n\td.fmt = fmt.Fmt{\n\t\tpref:     d.prefs\n\t\tindent:   0\n\t\tis_debug: false\n\t\ttable:    d.table\n\t}\n\td.checker = checker.new_checker(d.table, d.prefs)\n\treturn d\n}\n\n// stmt reads the data of an `ast.Stmt` node and returns a `DocNode`.\n// An option error is thrown if the symbol is not exposed to the public\n// (when `pub_only` is enabled) or the content's of the AST node is empty.\npub fn (mut d Doc) stmt(mut stmt ast.Stmt, filename string) !DocNode {\n\tmut name := d.stmt_name(stmt)\n\tif name in d.common_symbols {\n\t\treturn error('already documented')\n\t}\n\tif name.starts_with(d.orig_mod_name + '.') {\n\t\tname = name.all_after(d.orig_mod_name + '.')\n\t}\n\tmut node := DocNode{\n\t\tname:      name\n\t\tcontent:   d.stmt_signature(stmt)\n\t\tpos:       stmt.pos\n\t\tfile_path: os.join_path(d.base_path, filename)\n\t\tis_pub:    d.stmt_pub(stmt)\n\t\tplatform:  platform_from_filename(filename)\n\t}\n\tif (!node.is_pub && d.pub_only) || stmt is ast.GlobalDecl {\n\t\treturn error('symbol ${node.name} not public')\n\t}\n\tif node.name.starts_with(d.orig_mod_name + '.') {\n\t\tnode.name = node.name.all_after(d.orig_mod_name + '.')\n\t}\n\tif node.name == '' && node.comments.len == 0 && node.content.len == 0 {\n\t\treturn error('empty stmt')\n\t}\n\tmatch mut stmt {\n\t\tast.ConstDecl {\n\t\t\tnode.kind = .const_group\n\t\t\tnode.parent_name = 'Constants'\n\t\t\tif d.extract_vars {\n\t\t\t\tfor mut field in stmt.fields {\n\t\t\t\t\tret_type := if field.typ == 0 {\n\t\t\t\t\t\td.expr_typ_to_string(mut field.expr)\n\t\t\t\t\t} else {\n\t\t\t\t\t\td.type_to_str(field.typ)\n\t\t\t\t\t}\n\t\t\t\t\tnode.children << DocNode{\n\t\t\t\t\t\tname:        field.name.all_after(d.orig_mod_name + '.')\n\t\t\t\t\t\tkind:        .constant\n\t\t\t\t\t\tpos:         field.pos\n\t\t\t\t\t\treturn_type: ret_type\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tast.EnumDecl {\n\t\t\tnode.kind = .enum\n\t\t\tif d.extract_vars {\n\t\t\t\tfor mut field in stmt.fields {\n\t\t\t\t\tret_type := if field.has_expr {\n\t\t\t\t\t\td.expr_typ_to_string(mut field.expr)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t'int'\n\t\t\t\t\t}\n\t\t\t\t\tnode.children << DocNode{\n\t\t\t\t\t\tname:        field.name\n\t\t\t\t\t\tkind:        .enum_field\n\t\t\t\t\t\tparent_name: node.name\n\t\t\t\t\t\tpos:         field.pos\n\t\t\t\t\t\treturn_type: ret_type\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor sa in stmt.attrs {\n\t\t\t\tnode.attrs[sa.name] = if sa.has_at {\n\t\t\t\t\t'@[${sa.str()}]'\n\t\t\t\t} else {\n\t\t\t\t\t'[${sa.str()}]'\n\t\t\t\t}\n\t\t\t\tnode.tags << node.attrs[sa.name]\n\t\t\t}\n\t\t}\n\t\tast.InterfaceDecl {\n\t\t\tnode.kind = .interface\n\t\t}\n\t\tast.StructDecl {\n\t\t\tnode.kind = .struct\n\t\t\tif d.extract_vars {\n\t\t\t\tfor mut field in stmt.fields {\n\t\t\t\t\tret_type := if field.typ == 0 && field.has_default_expr {\n\t\t\t\t\t\td.expr_typ_to_string(mut field.default_expr)\n\t\t\t\t\t} else {\n\t\t\t\t\t\td.type_to_str(field.typ)\n\t\t\t\t\t}\n\t\t\t\t\tnode.children << DocNode{\n\t\t\t\t\t\tname:        field.name\n\t\t\t\t\t\tkind:        .struct_field\n\t\t\t\t\t\tparent_name: node.name\n\t\t\t\t\t\tpos:         field.pos\n\t\t\t\t\t\treturn_type: ret_type\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor sa in stmt.attrs {\n\t\t\t\tnode.attrs[sa.name] = if sa.has_at {\n\t\t\t\t\t'@[${sa.str()}]'\n\t\t\t\t} else {\n\t\t\t\t\t'[${sa.str()}]'\n\t\t\t\t}\n\t\t\t\tnode.tags << node.attrs[sa.name]\n\t\t\t}\n\t\t}\n\t\tast.TypeDecl {\n\t\t\tnode.kind = .typedef\n\t\t}\n\t\tast.FnDecl {\n\t\t\tif stmt.is_deprecated {\n\t\t\t\tfor sa in stmt.attrs {\n\t\t\t\t\tif sa.name.starts_with('deprecated') {\n\t\t\t\t\t\tnode.tags << sa.str()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif stmt.is_unsafe {\n\t\t\t\tnode.tags << 'unsafe'\n\t\t\t}\n\t\t\tnode.kind = .function\n\t\t\tnode.return_type = d.type_to_str(stmt.return_type)\n\t\t\tif stmt.receiver.typ !in [0, 1] {\n\t\t\t\tmethod_parent := d.type_to_str(stmt.receiver.typ)\n\t\t\t\tnode.kind = .method\n\t\t\t\tif !stmt.is_static_type_method {\n\t\t\t\t\tnode.parent_name = method_parent\n\t\t\t\t} else {\n\t\t\t\t\tnode.parent_name = ''\n\t\t\t\t}\n\t\t\t}\n\t\t\tif d.extract_vars {\n\t\t\t\tfor param in stmt.params {\n\t\t\t\t\tnode.children << DocNode{\n\t\t\t\t\t\tname:        param.name\n\t\t\t\t\t\tkind:        .variable\n\t\t\t\t\t\tparent_name: node.name\n\t\t\t\t\t\tpos:         param.pos\n\t\t\t\t\t\tattrs:       {\n\t\t\t\t\t\t\t'mut': param.is_mut.str()\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn_type: d.type_to_str(param.typ)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\treturn error('invalid stmt type to document')\n\t\t}\n\t}\n\tincluded := node.name in d.filter_symbol_names || node.parent_name in d.filter_symbol_names\n\tif d.filter_symbol_names.len != 0 && !included {\n\t\treturn error('not included in the list of symbol names')\n\t}\n\tif d.prefs.os == .all {\n\t\td.common_symbols << node.name\n\t}\n\treturn node\n}\n\n// file_ast reads the contents of `ast.File` and returns a map of `DocNode`s.\npub fn (mut d Doc) file_ast(mut file_ast ast.File) map[string]DocNode {\n\tmut contents := map[string]DocNode{}\n\td.fmt.file = file_ast\n\td.fmt.set_current_module_name(d.orig_mod_name)\n\td.fmt.process_file_imports(file_ast)\n\tmut last_import_stmt_idx := 0\n\tfor sidx, stmt in file_ast.stmts {\n\t\tif stmt is ast.Import {\n\t\t\tlast_import_stmt_idx = sidx\n\t\t}\n\t}\n\tmut preceding_comments := []DocComment{}\n\t// mut imports_section := true\n\tfor sidx, mut stmt in file_ast.stmts {\n\t\tif mut stmt is ast.ExprStmt {\n\t\t\t// Collect comments\n\t\t\tif mut stmt.expr is ast.Comment {\n\t\t\t\tpreceding_comments << ast_comment_to_doc_comment(stmt.expr)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\t// TODO: Fetch head comment once\n\t\tif mut stmt is ast.Module {\n\t\t\tif !d.with_head {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// the previous comments were probably a copyright/license one\n\t\t\tmodule_comment := merge_doc_comments(preceding_comments)\n\t\t\tif !d.is_vlib && !module_comment.starts_with('Copyright (c)') {\n\t\t\t\tif module_comment == '' {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\td.head.comments << preceding_comments\n\t\t\t}\n\t\t\tpreceding_comments = []\n\t\t\tcontinue\n\t\t}\n\t\tif last_import_stmt_idx > 0 && sidx == last_import_stmt_idx {\n\t\t\t// the accumulated comments were interspersed before/between the imports;\n\t\t\t// just add them all to the module comments:\n\t\t\tif d.with_head {\n\t\t\t\td.head.comments << preceding_comments\n\t\t\t}\n\t\t\tpreceding_comments = []\n\t\t\t// imports_section = false\n\t\t}\n\t\tif stmt is ast.Import {\n\t\t\tcontinue\n\t\t}\n\t\tmut node := d.stmt(mut stmt, os.base(file_ast.path)) or {\n\t\t\tpreceding_comments = []\n\t\t\tcontinue\n\t\t}\n\t\tif node.parent_name !in contents {\n\t\t\tparent_node_kind := if node.parent_name == 'Constants' {\n\t\t\t\tSymbolKind.const_group\n\t\t\t} else {\n\t\t\t\tSymbolKind.typedef\n\t\t\t}\n\t\t\tcontents[node.parent_name] = DocNode{\n\t\t\t\tname: node.parent_name\n\t\t\t\tkind: parent_node_kind\n\t\t\t}\n\t\t}\n\t\tif d.with_comments && preceding_comments.len > 0 {\n\t\t\tnode.comments << preceding_comments\n\t\t}\n\t\tpreceding_comments = []\n\t\tif node.parent_name.len > 0 {\n\t\t\tparent_name := node.parent_name\n\t\t\tif node.parent_name == 'Constants' {\n\t\t\t\tnode.parent_name = ''\n\t\t\t}\n\t\t\tcontents[parent_name].children << node\n\t\t} else {\n\t\t\tcontents[node.name] = node\n\t\t}\n\t}\n\td.fmt.mod2alias = map[string]string{}\n\tif contents[''].kind != .const_group {\n\t\tcontents.delete('')\n\t}\n\treturn contents\n}\n\n// file_ast_with_pos has the same function as the `file_ast` but\n// instead returns a list of variables in a given offset-based position.\npub fn (mut d Doc) file_ast_with_pos(mut file_ast ast.File, pos int) map[string]DocNode {\n\tlscope := file_ast.scope.innermost(pos)\n\tmut contents := map[string]DocNode{}\n\tfor name, val in lscope.objects {\n\t\tif val !is ast.Var {\n\t\t\tcontinue\n\t\t}\n\t\tmut vr_data := val as ast.Var\n\t\tl_node := DocNode{\n\t\t\tname:        name\n\t\t\tpos:         vr_data.pos\n\t\t\tfile_path:   file_ast.path\n\t\t\tfrom_scope:  true\n\t\t\tkind:        .variable\n\t\t\treturn_type: d.expr_typ_to_string(mut vr_data.expr)\n\t\t}\n\t\tcontents[l_node.name] = l_node\n\t}\n\treturn contents\n}\n\n// generate is a `Doc` method that will start documentation\n// process based on a file path provided.\npub fn (mut d Doc) generate() ! {\n\t// get all files\n\td.base_path = if os.is_dir(d.base_path) {\n\t\td.base_path\n\t} else {\n\t\tos.real_path(os.dir(d.base_path))\n\t}\n\td.is_vlib = d.base_path.contains('vlib')\n\tproject_files := os.ls(d.base_path) or { return err }\n\tv_files := d.prefs.should_compile_filtered_files(d.base_path, project_files)\n\tif v_files.len == 0 {\n\t\teprintln('vdoc: No valid V files were found. Skipping folder: ${d.base_path}.')\n\t\treturn\n\t}\n\t// parse files\n\tmut comments_mode := scanner.CommentsMode.skip_comments\n\tif d.with_comments {\n\t\tcomments_mode = .parse_comments\n\t}\n\tmut file_asts := []ast.File{}\n\tfor i, file_path in v_files {\n\t\tif i == 0 {\n\t\t\td.parent_mod_name = get_parent_mod(d.base_path) or { '' }\n\t\t}\n\t\tfile_asts << parser.parse_file(file_path, mut d.table, comments_mode, d.prefs)\n\t}\n\treturn d.file_asts(mut file_asts)\n}\n\n// file_asts has the same function as the `file_ast` function but\n// accepts an array of `ast.File` and throws an error if necessary.\npub fn (mut d Doc) file_asts(mut file_asts []ast.File) ! {\n\tmut fname_has_set := false\n\td.orig_mod_name = file_asts[0].mod.name\n\tfor i, mut file_ast in file_asts {\n\t\tif d.filename.len > 0 && file_ast.path.contains(d.filename) && !fname_has_set {\n\t\t\td.filename = file_ast.path\n\t\t\tfname_has_set = true\n\t\t}\n\t\tif d.with_head && i == 0 {\n\t\t\tmut module_name := file_ast.mod.name\n\t\t\t// if module_name != 'main' && d.parent_mod_name.len > 0 {\n\t\t\t// \tmodule_name = d.parent_mod_name + '.' + module_name\n\t\t\t// }\n\t\t\td.head = DocNode{\n\t\t\t\tname:    module_name\n\t\t\t\tcontent: 'module ${module_name}'\n\t\t\t\tkind:    .none\n\t\t\t}\n\t\t} else if file_ast.mod.name != d.orig_mod_name {\n\t\t\tcontinue\n\t\t}\n\t\tif file_ast.path == d.filename {\n\t\t\td.checker.check(mut file_ast)\n\t\t\td.scoped_contents = d.file_ast_with_pos(mut file_ast, d.pos)\n\t\t}\n\t\tcontents := d.file_ast(mut file_ast)\n\t\tfor name, node in contents {\n\t\t\tif name !in d.contents {\n\t\t\t\td.contents[name] = node\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif d.contents[name].kind == .typedef && node.kind !in [.typedef, .none] {\n\t\t\t\told_children := d.contents[name].children.clone()\n\t\t\t\td.contents[name] = node\n\t\t\t\td.contents[name].children = old_children\n\t\t\t}\n\t\t\tif d.contents[name].kind != .none || node.kind == .none {\n\t\t\t\td.contents[name].children << node.children\n\t\t\t\td.contents[name].children.arrange()\n\t\t\t}\n\t\t}\n\t}\n\tif d.filter_symbol_names.len != 0 && d.contents.len != 0 {\n\t\tfor filter_name in d.filter_symbol_names {\n\t\t\tif filter_name !in d.contents {\n\t\t\t\treturn error('vdoc: `${filter_name}` symbol in module `${d.orig_mod_name}` not found')\n\t\t\t}\n\t\t}\n\t}\n\td.time_generated = time.now()\n}\n\n// generate documents a certain file directory and returns an\n// instance of `Doc` if it is successful. Otherwise, it will throw an error.\npub fn generate(input_path string, pub_only bool, with_comments bool, platform Platform, filter_symbol_names ...string) !Doc {\n\tif platform == .js {\n\t\treturn error('vdoc: Platform `${platform}` is not supported.')\n\t}\n\tmut d := new(input_path)\n\td.pub_only = pub_only\n\td.with_comments = with_comments\n\td.filter_symbol_names = filter_symbol_names.filter(it.len != 0)\n\td.prefs.os = if platform == .auto {\n\t\tpref.get_host_os()\n\t} else {\n\t\tunsafe { pref.OS(int(platform)) }\n\t}\n\td.generate()!\n\treturn d\n}\n\n// generate_with_pos has the same function as the `generate` function but\n// accepts an offset-based position and enables the comments by default.\npub fn generate_with_pos(input_path string, filename string, pos int) !Doc {\n\tmut d := new(input_path)\n\td.pub_only = false\n\td.with_comments = true\n\td.with_pos = true\n\td.filename = filename\n\td.pos = pos\n\td.generate()!\n\treturn d\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/document/doc_private_fn_test.v",
    "content": "module document\n\nimport os\n\nfn testsuite_begin() {\n\tos.chdir(@VMODROOT) or {}\n\teprintln('>> @VMODROOT: ' + @VMODROOT)\n}\n\nfn test_get_parent_mod_on_root_folder() {\n\t// TODO: add an equivalent windows check for c:\\\n\t$if !windows {\n\t\tassert '---' == get_parent_mod('/') or {\n\t\t\tassert err.msg() == 'root folder reached'\n\t\t\t'---'\n\t\t}\n\t}\n}\n\nfn test_get_parent_mod_current_folder() {\n\t// TODO: this should may be return '' reliably on windows too:\n\t// assert '' == get_parent_mod('.') or {\n\t//\tassert err.msg() == 'No V files found.'\n\t//\t'---'\n\t// }\n}\n\nfn test_get_parent_mod_on_temp_dir() {\n\t// TODO: fix this on windows\n\t$if !windows {\n\t\tassert get_parent_mod(os.temp_dir())! == ''\n\t}\n}\n\nfn test_get_parent_mod_normal_cases() {\n\tassert '---' == get_parent_mod(os.join_path(@VMODROOT, 'vlib/v')) or {\n\t\tassert err.msg() == 'No V files found.'\n\t\t'---'\n\t}\n\tassert get_parent_mod(os.join_path(@VMODROOT, 'vlib', 'v', 'token'))! == 'v'\n\tassert get_parent_mod(os.join_path(@VMODROOT, 'vlib', 'os', 'os.v'))! == 'os'\n\tassert get_parent_mod(os.join_path(@VMODROOT, 'cmd'))! == ''\n\tassert get_parent_mod(os.join_path(@VMODROOT, 'cmd', 'tools', 'modules', 'testing',\n\t\t'common.v'))! == 'tools.modules.testing'\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/document/doc_test.v",
    "content": "// vtest build: tinyc && !musl? && !sanitized_job?\nimport document as doc\n\n// fn test_generate_with_pos() {}\n// fn test_generate() {}\n// fn test_generate_from_ast() {}\nfn test_generate_from_mod() {\n\tnested_mod_name := 'net.http.chunked'\n\tnested_mod_doc := doc.generate_from_mod(nested_mod_name, false, true) or {\n\t\teprintln(err)\n\t\tassert false\n\t\tdoc.Doc{}\n\t}\n\tassert nested_mod_doc.head.name == nested_mod_name\n\tassert nested_mod_doc.head.content == 'module ${nested_mod_name}'\n\tassert nested_mod_doc.contents.len == 3\n\tassert nested_mod_doc.contents['ChunkScanner'].children.len == 3\n}\n\nfn test_tags_with_flag_struct_attribute() {\n\tmod_name := 'gg'\n\tmod_doc := doc.generate_from_mod(mod_name, false, true) or {\n\t\teprintln(err)\n\t\tassert false\n\t\tdoc.Doc{}\n\t}\n\tassert mod_doc.head.name == mod_name\n\n\tmouse_buttons := mod_doc.contents['MouseButtons']!\n\tassert mouse_buttons.content == '@[flag]\npub enum MouseButtons {\n\tleft\n\tright\n\tmiddle\n}'\n\tassert mouse_buttons.attrs == {\n\t\t'flag': '@[flag]'\n\t}\n\tassert mouse_buttons.tags == ['@[flag]']\n\n\tend_options := mod_doc.contents['EndOptions']\n\tassert end_options.content == '@[params]\npub struct EndOptions {\npub:\n\thow EndEnum\n}'\n\tassert end_options.attrs == {\n\t\t'params': '@[params]'\n\t}\n\tassert end_options.tags == ['@[params]']\n\n\tpipeline_container := mod_doc.contents['PipelineContainer']\n\tassert pipeline_container.content == '@[heap]\npub struct PipelineContainer {\npub mut:\n\talpha sgl.Pipeline\n\tadd   sgl.Pipeline\n}'\n\tassert pipeline_container.attrs == {\n\t\t'heap': '@[heap]'\n\t}\n\tassert pipeline_container.tags == ['@[heap]']\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/document/module.v",
    "content": "module document\n\nimport os\nimport v.ast\nimport v.parser\nimport v.pref\n\n// get_parent_mod returns the parent mod name, in dot format.\n// It works by climbing up the folder hierarchy, until a folder,\n// that either contains main .v files, or a v.mod file is reached.\n// For example, given something like /languages/v/vlib/x/websocket/tests/autobahn\n// it returns `x.websocket.tests`, because /languages/v/ has v.mod file in it.\n// Note: calling this is expensive, so keep the result, instead of recomputing it.\n// TODO: turn this to a Doc method, so that the new_vdoc_preferences call here can\n// be removed.\nfn get_parent_mod(input_dir string) !string {\n\t// windows root path is C: or D:\n\tif input_dir.len == 2 && input_dir[1] == `:` {\n\t\treturn error('root folder reached')\n\t}\n\t// unix systems have / at the top:\n\tif input_dir == '/' {\n\t\treturn error('root folder reached')\n\t}\n\tif input_dir == '' {\n\t\treturn error('no input folder')\n\t}\n\tbase_dir := os.dir(input_dir)\n\tinput_dir_name := os.file_name(base_dir)\n\tprefs := new_vdoc_preferences()\n\tfentries := os.ls(base_dir) or { []string{} }\n\tfiles := fentries.filter(!os.is_dir(it))\n\tif 'v.mod' in files {\n\t\t// the top level is reached, no point in climbing up further\n\t\treturn ''\n\t}\n\tv_files := prefs.should_compile_filtered_files(base_dir, files)\n\tif v_files.len == 0 {\n\t\tparent_mod := get_parent_mod(base_dir) or { return input_dir_name }\n\t\tif parent_mod.len > 0 {\n\t\t\treturn parent_mod + '.' + input_dir_name\n\t\t}\n\t\treturn error('No V files found.')\n\t}\n\tmut tbl := ast.new_table()\n\tfile_ast := parser.parse_file(v_files[0], mut tbl, .skip_comments, prefs)\n\tif file_ast.mod.name == 'main' {\n\t\treturn ''\n\t}\n\tparent_mod := get_parent_mod(base_dir) or { return input_dir_name }\n\tif parent_mod.len > 0 {\n\t\treturn '${parent_mod}.${file_ast.mod.name}'\n\t}\n\treturn file_ast.mod.name\n}\n\n// lookup_module_with_path looks up the path of a given module name.\n// Throws an error if the module was not found.\npub fn lookup_module_with_path(mod string, base_path string) !string {\n\tvexe := pref.vexe_path()\n\tvroot := os.dir(vexe)\n\tmod_path := mod.replace('.', os.path_separator)\n\tcompile_dir := os.real_path(base_path)\n\tmodules_dir := os.join_path(compile_dir, 'modules', mod_path)\n\tvlib_path := os.join_path(vroot, 'vlib', mod_path)\n\tmut paths := [modules_dir, vlib_path]\n\tvmodules_paths := os.vmodules_paths()\n\tfor vmpath in vmodules_paths {\n\t\tpaths << os.join_path(vmpath, mod_path)\n\t}\n\tfor path in paths {\n\t\tif !os.exists(path) || os.is_dir_empty(path) {\n\t\t\tcontinue\n\t\t}\n\t\treturn path\n\t}\n\treturn error('module \"${mod}\" not found.')\n}\n\n// lookup_module returns the result of the `lookup_module_with_path`\n// but with the current directory as the provided base lookup path.\npub fn lookup_module(mod string) !string {\n\treturn lookup_module_with_path(mod, os.dir('.'))\n}\n\n// generate_from_mod generates a documentation from a specific module.\npub fn generate_from_mod(module_name string, pub_only bool, with_comments bool) !Doc {\n\tmod_path := lookup_module(module_name)!\n\treturn generate(mod_path, pub_only, with_comments, .auto)\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/document/node.v",
    "content": "module document\n\nimport os\n\npub const should_sort = os.getenv_opt('VDOC_SORT') or { 'true' }.bool()\n\npub fn (nodes []DocNode) find(symname string) !DocNode {\n\tfor node in nodes {\n\t\tif node.name == symname {\n\t\t\treturn node\n\t\t}\n\t}\n\treturn error('symbol not found')\n}\n\n// arrange sorts the DocNodes based on their symbols and names.\npub fn (mut nodes []DocNode) arrange() {\n\tif !should_sort {\n\t\treturn\n\t}\n\tmut kinds := []SymbolKind{}\n\tfor v in nodes {\n\t\tif v.kind !in kinds {\n\t\t\tkinds << v.kind\n\t\t}\n\t}\n\tkinds.sort_with_compare(compare_sym_kinds)\n\tmut res := []DocNode{}\n\tfor k in kinds {\n\t\tmut kind_nodes := nodes.filter(it.kind == k)\n\t\tkind_nodes.sort(a.name < b.name)\n\t\tres << kind_nodes\n\t}\n\tnodes = res.clone()\n}\n\nfn compare_sym_kinds(a &SymbolKind, b &SymbolKind) int {\n\tak := int(*a)\n\tbk := int(*b)\n\treturn match true {\n\t\tak < bk { -1 }\n\t\tak > bk { 1 }\n\t\telse { 0 }\n\t}\n}\n\n// arr() converts the map into an array of `DocNode`.\npub fn (cnts map[string]DocNode) arr() []DocNode {\n\tmut contents := cnts.values()\n\tcontents.arrange()\n\treturn contents\n}\n\n// merge_comments returns a `string` with the combined contents of `DocNode.comments`.\npub fn (dc DocNode) merge_comments() string {\n\treturn merge_doc_comments(dc.comments)\n}\n\n// merge_comments_without_examples returns a `string` with the\n// combined contents of `DocNode.comments` - excluding any examples.\npub fn (dc DocNode) merge_comments_without_examples() string {\n\tmut sans_examples := []DocComment{cap: dc.comments.len}\n\tfor i := 0; i < dc.comments.len; i++ {\n\t\tif dc.comments[i].is_example() {\n\t\t\tcontinue\n\t\t}\n\t\tif dc.comments[i].is_multi_line_example() {\n\t\t\ti++\n\t\t\tif i == dc.comments.len || !dc.comments[i].has_triple_backtick() {\n\t\t\t\teprintln('${dc.file_path}:${dc.pos.line_nr}: warning: expected code block after empty example line:')\n\t\t\t\teprintln('// ```')\n\t\t\t\tif i < dc.comments.len {\n\t\t\t\t\teprintln('Found:')\n\t\t\t\t\teprintln('//' + dc.comments[i].text[1..])\n\t\t\t\t}\n\t\t\t}\n\t\t\ti++\n\t\t\tfor i < dc.comments.len && !dc.comments[i].has_triple_backtick() {\n\t\t\t\ti++\n\t\t\t}\n\t\t} else {\n\t\t\tsans_examples << dc.comments[i]\n\t\t}\n\t}\n\treturn merge_doc_comments(sans_examples)\n}\n\n// examples returns a `[]string` containing examples parsed from `DocNode.comments`.\npub fn (dn DocNode) examples() []string {\n\tmut output := []string{}\n\tfor i := 0; i < dn.comments.len; i++ {\n\t\tcomment := dn.comments[i]\n\t\tif comment.is_example() {\n\t\t\toutput << comment.example()\n\t\t} else if comment.is_multi_line_example() {\n\t\t\ti++\n\t\t\tif i + 2 < dn.comments.len && dn.comments[i].has_triple_backtick() {\n\t\t\t\ti++\n\t\t\t\tmut ml_ex := ''\n\t\t\t\tfor i < dn.comments.len && !dn.comments[i].has_triple_backtick() {\n\t\t\t\t\tif ml_ex.len > 0 {\n\t\t\t\t\t\tml_ex += '\\n'\n\t\t\t\t\t}\n\t\t\t\t\ts := dn.comments[i].text\n\t\t\t\t\tif s.len > 2 {\n\t\t\t\t\t\tml_ex += s[2..]\n\t\t\t\t\t}\n\t\t\t\t\ti++\n\t\t\t\t}\n\t\t\t\toutput << ml_ex\n\t\t\t}\n\t\t}\n\t}\n\treturn output\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/document/utils.v",
    "content": "module document\n\nimport strings\nimport v.ast\nimport v.token\n\nconst highlight_keys = ['note:', 'fixme:', 'todo:']\nconst horizontal_rule_chars = ['-', '=', '*', '_', '~']\n\n// merge_comments merges all the comment contents into a single text.\npub fn merge_comments(comments []ast.Comment) string {\n\tmut res := []string{}\n\tfor comment in comments {\n\t\tres << comment.text.trim_left('\\x01')\n\t}\n\treturn res.join('\\n')\n}\n\n// ast_comment_to_doc_comment converts an `ast.Comment` node type to a `DocComment`\npub fn ast_comment_to_doc_comment(ast_node ast.Comment) DocComment {\n\ttext := ast_node.text // TODO: .trim_left('\\x01') // BUG why are this byte here in the first place?\n\treturn DocComment{\n\t\ttext:     text\n\t\tis_multi: ast_node.is_multi\n\t\tpos:      token.Pos{\n\t\t\tline_nr: ast_node.pos.line_nr\n\t\t\tcol:     0 // ast_node.pos.pos - ast_node.text.len\n\t\t\tlen:     text.len\n\t\t}\n\t}\n}\n\n// ast_comments_to_doc_comments converts an array of `ast.Comment` nodes to\n// an array of `DocComment` nodes\npub fn ast_comments_to_doc_comments(ast_nodes []ast.Comment) []DocComment {\n\tmut doc_comments := []DocComment{len: ast_nodes.len}\n\tfor ast_comment in ast_nodes {\n\t\tdoc_comments << ast_comment_to_doc_comment(ast_comment)\n\t}\n\treturn doc_comments\n}\n\n// merge_doc_comments merges all the comments starting from\n// the last up to the first item of the array.\npub fn merge_doc_comments(comments []DocComment) string {\n\tif comments.len == 0 {\n\t\treturn ''\n\t}\n\tmut doc_comments := []string{}\n\tfor i := comments.len - 1; i >= 0; i-- {\n\t\tif comments[i].is_multi {\n\t\t\t// `/*foo*/` block comments are deliberately NOT supported as doc comments, ignore them.\n\t\t\tcontinue\n\t\t}\n\t\tdoc_comments << comments[i].text\n\t\tif cmt_above := comments[i - 1] {\n\t\t\tif cmt_above.pos.line_nr + 1 < comments[i].pos.line_nr {\n\t\t\t\t// Stop when a doc comment reaches the top of its contiguous block.\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\tmut comment := ''\n\tmut next_on_newline := true\n\tmut is_codeblock := false\n\tmut trimmed_indent := ''\n\tfor cmt in doc_comments.reverse() {\n\t\tline_loop: for line in cmt.split_into_lines() {\n\t\t\tl_normalized := line.trim_left('\\x01')\n\t\t\tl := l_normalized.trim_space()\n\t\t\tlast_ends_with_lb := comment.ends_with('\\n')\n\t\t\tif l == '' {\n\t\t\t\tcomment += if last_ends_with_lb { '\\n' } else { '\\n\\n' }\n\t\t\t\tnext_on_newline = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\thas_codeblock_quote := l.starts_with('```')\n\t\t\tif is_codeblock {\n\t\t\t\tcomment += l_normalized.trim_string_left(trimmed_indent) + '\\n'\n\t\t\t\tif has_codeblock_quote {\n\t\t\t\t\tis_codeblock = !is_codeblock\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif has_codeblock_quote {\n\t\t\t\tif !is_codeblock && !last_ends_with_lb {\n\t\t\t\t\tcomment += '\\n'\n\t\t\t\t}\n\t\t\t\tcomment += l + '\\n'\n\t\t\t\tis_codeblock = !is_codeblock\n\t\t\t\ttrimmed_indent = l_normalized.all_before(l)\n\t\t\t\tnext_on_newline = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tis_list := l.len > 1 && ((l[1] == ` ` && l[0] in [`-`, `*`, `+`])\n\t\t\t\t|| (l.len > 2 && l[2] == ` ` && l[1] == `.` && l[0].is_digit()))\n\t\t\tline_before_spaces := l.before(' ')\n\t\t\tif is_list || (l.starts_with('|') && l.ends_with('|'))\n\t\t\t\t|| (l.starts_with('#') && line_before_spaces.count('#') == line_before_spaces.len) {\n\t\t\t\tcomment += l + '\\n'\n\t\t\t\tnext_on_newline = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Use own paragraph for \"highlight\" comments.\n\t\t\tll := l.to_lower_ascii()\n\t\t\tmut continue_line_loop := false\n\t\t\tfor key in highlight_keys {\n\t\t\t\tif ll.starts_with(key) {\n\t\t\t\t\tcomment += '\\n\\n${key.title()}${l[key.len..]}'\n\t\t\t\t\t// Workaround for compiling with `v -cstrict -cc gcc cmd/tools/vdoc/document/doc_test.v`\n\t\t\t\t\t// and using multiple continue `<label>`.\n\t\t\t\t\tcontinue_line_loop = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif continue_line_loop {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tline_no_spaces := l.replace(' ', '')\n\t\t\tfor ch in horizontal_rule_chars {\n\t\t\t\tif line_no_spaces.starts_with(ch.repeat(3))\n\t\t\t\t\t&& line_no_spaces.count(ch) == line_no_spaces.len {\n\t\t\t\t\tcomment += '\\n' + l + '\\n'\n\t\t\t\t\tnext_on_newline = true\n\t\t\t\t\tcontinue line_loop\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !next_on_newline {\n\t\t\t\tcomment += ' '\n\t\t\t}\n\t\t\tcomment += l\n\t\t\tnext_on_newline = false\n\t\t}\n\t}\n\treturn comment\n}\n\n// stmt_signature returns the signature of a given `ast.Stmt` node.\npub fn (mut d Doc) stmt_signature(stmt ast.Stmt) string {\n\tmatch stmt {\n\t\tast.Module {\n\t\t\treturn 'module ${stmt.name}'\n\t\t}\n\t\tast.FnDecl {\n\t\t\treturn d.table.stringify_fn_decl(&stmt, d.fmt.cur_mod, d.fmt.mod2alias, false)\n\t\t}\n\t\telse {\n\t\t\td.fmt.out = strings.new_builder(1000)\n\t\t\td.fmt.stmt(stmt)\n\t\t\treturn d.fmt.out.str().trim_space()\n\t\t}\n\t}\n}\n\n// stmt_name returns the name of a given `ast.Stmt` node.\npub fn (d Doc) stmt_name(stmt ast.Stmt) string {\n\tmatch stmt {\n\t\tast.StructDecl, ast.EnumDecl, ast.InterfaceDecl {\n\t\t\treturn stmt.name\n\t\t}\n\t\tast.FnDecl {\n\t\t\tif stmt.is_static_type_method {\n\t\t\t\treturn stmt.name.replace('__static__', '.')\n\t\t\t} else {\n\t\t\t\treturn stmt.name\n\t\t\t}\n\t\t}\n\t\tast.TypeDecl {\n\t\t\tmatch stmt {\n\t\t\t\tast.FnTypeDecl, ast.AliasTypeDecl, ast.SumTypeDecl { return stmt.name }\n\t\t\t}\n\t\t}\n\t\tast.ConstDecl {\n\t\t\treturn ''\n\t\t} // leave it blank\n\t\telse {\n\t\t\treturn ''\n\t\t}\n\t}\n}\n\n// stmt_pub returns a boolean if a given `ast.Stmt` node\n// is exposed to the public.\npub fn (d Doc) stmt_pub(stmt ast.Stmt) bool {\n\tmatch stmt {\n\t\tast.FnDecl, ast.StructDecl, ast.EnumDecl, ast.InterfaceDecl, ast.ConstDecl {\n\t\t\treturn stmt.is_pub\n\t\t}\n\t\tast.TypeDecl {\n\t\t\tmatch stmt {\n\t\t\t\tast.FnTypeDecl, ast.AliasTypeDecl, ast.SumTypeDecl { return stmt.is_pub }\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\treturn false\n\t\t}\n\t}\n}\n\n// type_to_str is a wrapper function around `fmt.ast.type_to_str`.\npub fn (mut d Doc) type_to_str(typ ast.Type) string {\n\t// why is it the default behaviour of ast.type_to_str\n\t// to convert math.bits.Type to bits.Type?\n\td.table.cmod_prefix = d.orig_mod_name + '.'\n\treturn d.fmt.table.type_to_str(typ).all_after('&')\n}\n\n// expr_typ_to_string has the same function as `Doc.typ_to_str`\n// but for `ast.Expr` nodes. The checker will check first the\n// node and it executes the `type_to_str` method.\npub fn (mut d Doc) expr_typ_to_string(mut expr ast.Expr) string {\n\texpr_typ := d.checker.expr(mut expr)\n\treturn d.type_to_str(expr_typ)\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/files.v",
    "content": "module main\n\nimport os\n\nstruct IgnoreRules {\nmut:\n\t// Ignore patterns use the path with a `.vdocignore` file as a base. E.g.:\n\t// `{'<path>': ['<pattern1>', '<pattern2>'], '<path/subpath>': ['<pattern3>']}`\n\tpatterns map[string][]string = {\n\t\t// Default ignore patterns.\n\t\t'': ['testdata', 'tests', '*_test.v']\n\t}\n\tpaths    map[string]bool\n}\n\nfn get_modules(path string) []string {\n\tmut modules := map[string]bool{}\n\tfor p in get_paths(path, IgnoreRules.get(path)) {\n\t\tmodules[os.dir(p)] = true\n\t}\n\tmut res := modules.keys()\n\tres.sort()\n\treturn res\n}\n\nfn get_paths(path string, ignore_rules IgnoreRules) []string {\n\tmut res := []string{}\n\touter: for p in os.ls(path) or { return [] } {\n\t\tfp := os.join_path(path, p)\n\t\tif fp in ignore_rules.paths {\n\t\t\tcontinue\n\t\t}\n\t\tis_dir := os.is_dir(fp)\n\t\tfor ignore_path, patterns in ignore_rules.patterns {\n\t\t\tif fp.starts_with(ignore_path) {\n\t\t\t\tif patterns.any(p == it\n\t\t\t\t\t|| (it.contains('*') && p.ends_with(it.all_after('*')))\n\t\t\t\t\t|| (is_dir && it.ends_with('/') && fp.ends_with(it.trim_right('/')))\n\t\t\t\t\t|| (!it.ends_with('/') && it.contains('/') && fp.contains(it)))\n\t\t\t\t{\n\t\t\t\t\tcontinue outer\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif is_dir {\n\t\t\tres << get_paths(fp, ignore_rules)\n\t\t\tcontinue\n\t\t}\n\t\tif p.ends_with('.v') {\n\t\t\tres << fp\n\t\t}\n\t}\n\treturn res\n}\n\nfn IgnoreRules.get(path string) IgnoreRules {\n\tmut res := IgnoreRules{}\n\tmut vdocignore_paths := []string{}\n\tmut vdocignore_paths_ref := &vdocignore_paths\n\tos.walk(path, fn [vdocignore_paths_ref] (p string) {\n\t\tif os.file_name(p) == '.vdocignore' {\n\t\t\tunsafe {\n\t\t\t\tvdocignore_paths_ref << p\n\t\t\t}\n\t\t}\n\t})\n\tfor ignore_path in vdocignore_paths {\n\t\tignore_content := os.read_file(ignore_path) or { continue }\n\t\tif ignore_content.trim_space() == '' {\n\t\t\tcontinue\n\t\t}\n\t\trules := ignore_content.split_into_lines().map(it.trim_space())\n\t\tfor rule in rules {\n\t\t\tif rule.starts_with('#') {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif rule.contains('*.') || rule.contains('**') {\n\t\t\t\t// Skip wildcards that are defined in an ignore file.\n\t\t\t\t// For now, only add a basic implementation in `get_paths`\n\t\t\t\t// that can handle the default `*_test.v` pattern.\n\t\t\t\teprintln('vdoc: Wildcards in ignore rules are not yet supported.')\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tp := os.dir(ignore_path)\n\t\t\tif rule.starts_with('/') {\n\t\t\t\t// Similar to `.gitignore`, a pattern starting with `/` should only ignore\n\t\t\t\t// the pattern relative to the directory of the `.vdocignore` file.\n\t\t\t\t// `/a` should ignore `/a` but not `/b/a`. While `a` should ignore `/a` and `/b/a`.\n\t\t\t\tres.paths[os.join_path(p, rule.trim_left('/'))] = true\n\t\t\t} else {\n\t\t\t\tres.patterns[p] << rule\n\t\t\t}\n\t\t}\n\t}\n\treturn res\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/highlight.v",
    "content": "module main\n\nimport term\nimport strings\nimport v.scanner\nimport v.ast\nimport v.token\nimport v.pref\n\nconst highlight_builtin_types = ['bool', 'string', 'i8', 'i16', 'int', 'i64', 'i128', 'isize',\n\t'byte', 'u8', 'u16', 'u32', 'u64', 'usize', 'u128', 'rune', 'f32', 'f64', 'byteptr', 'voidptr',\n\t'any']\n\nfn color_highlight(code string, tb &ast.Table) string {\n\thighlight_code := fn (tok token.Token, typ HighlightTokenTyp) string {\n\t\tmut lit := ''\n\t\tmatch typ {\n\t\t\t.unone, .operator, .punctuation {\n\t\t\t\tlit = tok.kind.str()\n\t\t\t}\n\t\t\t.string {\n\t\t\t\tuse_double_quote := tok.lit.contains(\"'\") && !tok.lit.contains('\"')\n\t\t\t\tunescaped_val := tok.lit.replace('\\\\\\\\', '\\x01').replace_each([\"\\\\'\", \"'\", '\\\\\"',\n\t\t\t\t\t'\"'])\n\t\t\t\tif use_double_quote {\n\t\t\t\t\ts := unescaped_val.replace_each(['\\x01', '\\\\\\\\', '\"', '\\\\\"'])\n\t\t\t\t\tlit = term.yellow('\"${s}\"')\n\t\t\t\t} else {\n\t\t\t\t\ts := unescaped_val.replace_each(['\\x01', '\\\\\\\\', \"'\", \"\\\\'\"])\n\t\t\t\t\tlit = term.yellow(\"'${s}'\")\n\t\t\t\t}\n\t\t\t}\n\t\t\t.char {\n\t\t\t\tlit = term.yellow('`${tok.lit}`')\n\t\t\t}\n\t\t\t.comment {\n\t\t\t\tlit = if tok.lit != '' && tok.lit[0] == 1 {\n\t\t\t\t\tterm.gray('//${tok.lit[1..]}')\n\t\t\t\t} else {\n\t\t\t\t\tterm.gray('//${tok.lit}')\n\t\t\t\t}\n\t\t\t}\n\t\t\t.keyword {\n\t\t\t\tlit = term.bright_blue(tok.lit)\n\t\t\t}\n\t\t\t.builtin, .symbol {\n\t\t\t\tlit = term.green(tok.lit)\n\t\t\t}\n\t\t\t.function {\n\t\t\t\tlit = term.cyan(tok.lit)\n\t\t\t}\n\t\t\t.number, .module_ {\n\t\t\t\tlit = term.bright_blue(tok.lit)\n\t\t\t}\n\t\t\t.boolean {\n\t\t\t\tlit = term.bright_magenta(tok.lit)\n\t\t\t}\n\t\t\t.none {\n\t\t\t\tlit = term.red(tok.lit)\n\t\t\t}\n\t\t\t.prefix {\n\t\t\t\tlit = term.magenta(tok.lit)\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlit = tok.lit\n\t\t\t}\n\t\t}\n\t\treturn lit\n\t}\n\tmut s := scanner.new_scanner(code, .parse_comments, &pref.Preferences{ is_fmt: true })\n\tmut prev_prev := token.Token{}\n\tmut prev := token.Token{}\n\tmut tok := s.scan()\n\tmut next_tok := s.scan()\n\tmut buf := strings.new_builder(200)\n\tmut i := 0\n\tfor i < code.len {\n\t\tif i == tok.pos {\n\t\t\tmut tok_typ := HighlightTokenTyp.unone\n\t\t\tmatch tok.kind {\n\t\t\t\t.name {\n\t\t\t\t\tif (tok.lit in highlight_builtin_types || tb.known_type(tok.lit))\n\t\t\t\t\t\t&& (next_tok.kind != .lpar || prev.kind !in [.key_fn, .rpar]) {\n\t\t\t\t\t\ttok_typ = .builtin\n\t\t\t\t\t} else if\n\t\t\t\t\t\t(next_tok.kind in [.lcbr, .rpar, .eof, .name, .rcbr, .assign, .key_pub, .key_mut, .pipe, .comma, .comment, .lt, .lsbr]\n\t\t\t\t\t\t&& next_tok.lit !in highlight_builtin_types)\n\t\t\t\t\t\t&& (prev.kind in [.name, .amp, .lcbr, .rsbr, .key_type, .assign, .dot, .not, .question, .rpar, .key_struct, .key_enum, .pipe, .key_interface, .comment, .ellipsis, .comma]\n\t\t\t\t\t\t&& prev.lit !in highlight_builtin_types)\n\t\t\t\t\t\t&& ((tok.lit != '' && tok.lit[0].is_capital())\n\t\t\t\t\t\t|| prev_prev.lit in ['C', 'JS']) {\n\t\t\t\t\t\ttok_typ = .symbol\n\t\t\t\t\t} else if tok.lit[0].is_capital() && prev.kind == .lpar\n\t\t\t\t\t\t&& next_tok.kind == .comma {\n\t\t\t\t\t\ttok_typ = .symbol\n\t\t\t\t\t} else if next_tok.kind == .lpar\n\t\t\t\t\t\t|| (!(tok.lit != '' && tok.lit[0].is_capital())\n\t\t\t\t\t\t&& next_tok.kind in [.lt, .lsbr] && next_tok.pos == tok.pos + tok.lit.len) {\n\t\t\t\t\t\ttok_typ = .function\n\t\t\t\t\t} else if next_tok.kind == .dot {\n\t\t\t\t\t\tif tok.lit in ['C', 'JS'] {\n\t\t\t\t\t\t\ttok_typ = .prefix\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif tok.lit != '' && tok.lit[0].is_capital() {\n\t\t\t\t\t\t\t\ttok_typ = .symbol\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttok_typ = .module_\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if tok.lit in ['r', 'c'] && next_tok.kind == .string {\n\t\t\t\t\t\ttok_typ = .prefix\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttok_typ = .name\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t.comment {\n\t\t\t\t\ttok_typ = .comment\n\t\t\t\t}\n\t\t\t\t.chartoken {\n\t\t\t\t\ttok_typ = .char\n\t\t\t\t}\n\t\t\t\t.string {\n\t\t\t\t\ttok_typ = .string\n\t\t\t\t}\n\t\t\t\t.number {\n\t\t\t\t\ttok_typ = .number\n\t\t\t\t}\n\t\t\t\t.key_true, .key_false {\n\t\t\t\t\ttok_typ = .boolean\n\t\t\t\t}\n\t\t\t\t.lpar, .lcbr, .rpar, .rcbr, .lsbr, .rsbr, .semicolon, .colon, .comma, .dot,\n\t\t\t\t.dotdot, .ellipsis {\n\t\t\t\t\ttok_typ = .punctuation\n\t\t\t\t}\n\t\t\t\t.key_none {\n\t\t\t\t\ttok_typ = .none\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tif token.is_key(tok.lit) || token.is_decl(tok.kind) {\n\t\t\t\t\t\ttok_typ = .keyword\n\t\t\t\t\t} else if tok.kind.is_assign() || tok.is_unary() || tok.kind.is_relational()\n\t\t\t\t\t\t|| tok.kind.is_infix() || tok.kind.is_postfix() {\n\t\t\t\t\t\ttok_typ = .operator\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbuf.write_string(highlight_code(tok, tok_typ))\n\t\t\tif prev_prev.kind == .eof || prev.kind == .eof || next_tok.kind == .eof {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tprev_prev = prev\n\t\t\tprev = tok\n\t\t\ti = tok.pos + tok.len\n\t\t\ttok = next_tok\n\t\t\tnext_tok = s.scan()\n\t\t} else {\n\t\t\tbuf.write_u8(code[i])\n\t\t\ti++\n\t\t}\n\t}\n\treturn buf.str()\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/html.v",
    "content": "module main\n\nimport os\nimport net.urllib\nimport encoding.html\nimport strings\nimport markdown\nimport v.scanner\nimport v.ast\nimport v.token\nimport document as doc\nimport v.pref\nimport v.util { tabs }\n\nconst css_js_assets = ['doc.css', 'normalize.css', 'doc.js', 'dark-mode.js']\nconst default_theme = os.resource_abs_path('theme')\nconst link_svg = '<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24\" viewBox=\"0 0 24 24\" width=\"24\"><path d=\"M0 0h24v24H0z\" fill=\"none\"/><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"/></svg>'\n\nconst single_quote = \"'\"\nconst double_quote = '\"'\nconst quote_escape_seq = [single_quote, '', double_quote, '']\n\nenum HighlightTokenTyp {\n\tunone\n\tboolean\n\tbuiltin\n\tchar\n\tcomment\n\tfunction\n\tkeyword\n\tname\n\tnumber\n\toperator\n\tpunctuation\n\tstring\n\t// For string interpolation\n\topening_string\n\tstring_interp\n\tpartial_string\n\tclosing_string\n\tsymbol\n\tnone\n\tmodule_\n\tprefix\n}\n\nstruct SearchModuleResult {\n\tdescription string\n\tlink        string\n}\n\nstruct SearchResult {\n\tprefix      string\n\tbadge       string\n\tdescription string\n\tlink        string\n}\n\nfn (vd &VDoc) render_search_index(out Output) {\n\tmut js_search_index := strings.new_builder(200)\n\tmut js_search_data := strings.new_builder(200)\n\tjs_search_index.write_string('var searchModuleIndex = [\\n')\n\tjs_search_data.write_string('var searchModuleData = [\\n')\n\tfor i, title in vd.search_module_index {\n\t\tdata := vd.search_module_data[i]\n\t\tjs_search_index.write_string('\"${title}\",\\n')\n\t\tdescription := data.description.replace('\\n', '').replace('\\r', '') // fix multiline js string bug\n\t\tjs_search_data.write_string('[\"${description}\",\"${data.link}\"],\\n')\n\t}\n\tjs_search_index.writeln('];\\n')\n\tjs_search_index.write_string('var searchIndex = [\\n')\n\tjs_search_data.writeln('];\\n')\n\tjs_search_data.write_string('var searchData = [\\n')\n\tfor i, title in vd.search_index {\n\t\tdata := vd.search_data[i]\n\t\tjs_search_index.write_string('\"${title}\",\\n')\n\t\t// array instead of object to reduce file size\n\t\tjs_search_data.write_string('[\"${data.badge}\",\"${data.description}\",\"${data.link}\",\"${data.prefix}\"],\\n')\n\t}\n\tjs_search_index.writeln('];\\n')\n\tjs_search_data.writeln('];\\n')\n\tfinal := js_search_index.str() + js_search_data.str()\n\tout_file_path := os.join_path(out.path, 'search_index.js')\n\tprintln('Generating search_index.js of ${final.len:8} bytes in `${out_file_path} ...')\n\tos.write_file(out_file_path, final) or { panic(err) }\n}\n\nfn (mut vd VDoc) render_static_html(out Output) {\n\tvd.assets = {\n\t\t'doc_css':       vd.get_resource(css_js_assets[0], out)\n\t\t'normalize_css': vd.get_resource(css_js_assets[1], out)\n\t\t'doc_js':        vd.get_resource(css_js_assets[2], out)\n\t\t'dark_mode_js':  vd.get_resource(css_js_assets[3], out)\n\t\t'light_icon':    vd.get_resource('light.svg', out)\n\t\t'dark_icon':     vd.get_resource('dark.svg', out)\n\t\t'menu_icon':     vd.get_resource('menu.svg', out)\n\t\t'arrow_icon':    vd.get_resource('arrow.svg', out)\n\t}\n}\n\nfn (vd &VDoc) get_resource(name string, out Output) string {\n\tcfg := vd.cfg\n\tpath := os.join_path(cfg.theme_dir, name)\n\tmut res := os.read_file(path) or { panic('vdoc: could not read ${path}') }\n\t/*\n\tif minify {\n\t\tif name.ends_with('.js') {\n\t\t\tres = js_compress(res)\n\t\t} else {\n\t\t\tres = res.split_into_lines().map(it.trim_space()).join('')\n\t\t}\n\t}\n\t*/\n\t// TODO: Make SVG inline for now\n\tif cfg.inline_assets || path.ends_with('.svg') {\n\t\treturn res\n\t} else {\n\t\toutput_path := os.join_path(out.path, name)\n\t\tif !os.exists(output_path) {\n\t\t\tprintln('Copying ${res.len:8} bytes from `${path}` to `${output_path}` ...')\n\t\t\tos.write_file(output_path, res) or { panic(err) }\n\t\t}\n\t\treturn name\n\t}\n}\n\nfn (mut vd VDoc) collect_search_index(out Output) {\n\tcfg := vd.cfg\n\tfor doc in vd.docs {\n\t\tmod := doc.head.name\n\t\tvd.search_module_index << mod\n\t\tcomments := if cfg.include_examples {\n\t\t\tdoc.head.merge_comments()\n\t\t} else {\n\t\t\tdoc.head.merge_comments_without_examples()\n\t\t}\n\t\tvd.search_module_data << SearchModuleResult{\n\t\t\tdescription: trim_doc_node_description(mod, comments)\n\t\t\tlink:        vd.get_file_name(mod, out)\n\t\t}\n\t\tfor _, dn in doc.contents {\n\t\t\tvd.create_search_results(mod, dn, out)\n\t\t}\n\t}\n}\n\nfn (mut vd VDoc) create_search_results(mod string, dn doc.DocNode, out Output) {\n\tcfg := vd.cfg\n\tif dn.kind == .const_group {\n\t\treturn\n\t}\n\tcomments := if cfg.include_examples {\n\t\tdn.merge_comments()\n\t} else {\n\t\tdn.merge_comments_without_examples()\n\t}\n\tdn_description := trim_doc_node_description(dn.name, comments)\n\tvd.search_index << dn.name\n\tvd.search_data << SearchResult{\n\t\tprefix:      if dn.parent_name != '' {\n\t\t\t'${dn.kind} (${dn.parent_name})'\n\t\t} else {\n\t\t\t'${dn.kind} '\n\t\t}\n\t\tdescription: dn_description\n\t\tbadge:       mod\n\t\tlink:        vd.get_file_name(mod, out) + '#' + get_node_id(dn)\n\t}\n\tfor child in dn.children {\n\t\tvd.create_search_results(mod, child, out)\n\t}\n}\n\nfn (vd &VDoc) get_repo_file_path_for_links(file_path string) string {\n\tif file_path == '' {\n\t\treturn ''\n\t}\n\tcfg := vd.cfg\n\tif !cfg.is_multi {\n\t\treturn os.file_name(file_path).replace('\\\\', '/')\n\t}\n\tbase_dir := os.dir(os.real_path(cfg.input_path))\n\tprefix := base_dir + os.path_separator\n\tif file_path.starts_with(prefix) {\n\t\treturn file_path[prefix.len..].replace('\\\\', '/')\n\t}\n\treturn file_path.replace('\\\\', '/')\n}\n\nfn (vd &VDoc) write_content(cn &doc.DocNode, d &doc.Doc, mut hw strings.Builder) {\n\tcfg := vd.cfg\n\tfile_path_name := vd.get_repo_file_path_for_links(cn.file_path)\n\tsrc_link := get_src_link(vd.manifest.repo_url, vd.manifest.repo_branch, file_path_name,\n\t\tcn.pos.line_nr + 1)\n\tmd_link_base := get_src_dir_link(vd.manifest.repo_url, vd.manifest.repo_branch, file_path_name)\n\tif cn.content.len != 0 || cn.name == 'Constants' {\n\t\thw.write_string(vd.doc_node_html(cn, src_link, md_link_base, false, cfg.include_examples,\n\t\t\td.table))\n\t\thw.write_string('\\n')\n\t}\n\tfor child in cn.children {\n\t\tchild_file_path_name := vd.get_repo_file_path_for_links(child.file_path)\n\t\tchild_src_link := get_src_link(vd.manifest.repo_url, vd.manifest.repo_branch,\n\t\t\tchild_file_path_name, child.pos.line_nr + 1)\n\t\tchild_md_link_base := get_src_dir_link(vd.manifest.repo_url, vd.manifest.repo_branch,\n\t\t\tchild_file_path_name)\n\t\thw.write_string(vd.doc_node_html(child, child_src_link, child_md_link_base, false,\n\t\t\tcfg.include_examples, d.table))\n\t\thw.write_string('\\n')\n\t}\n}\n\nfn (vd &VDoc) gen_html(d doc.Doc) string {\n\tcfg := vd.cfg\n\tmut symbols_toc := strings.new_builder(200)\n\tmut contents := strings.new_builder(200)\n\tdcs_contents := d.contents.arr()\n\t// generate toc first\n\thead_md_link_base := if is_module_readme(d.head) {\n\t\treadme_file_path := vd.get_repo_file_path_for_links(d.head.file_path)\n\t\tget_src_dir_link(vd.manifest.repo_url, vd.manifest.repo_branch, readme_file_path)\n\t} else {\n\t\t''\n\t}\n\tcontents.writeln(vd.doc_node_html(d.head, '', head_md_link_base, true, cfg.include_examples,\n\t\td.table))\n\tif is_module_readme(d.head) {\n\t\twrite_toc(d.head, mut symbols_toc)\n\t}\n\tfor cn in dcs_contents {\n\t\tvd.write_content(&cn, &d, mut contents)\n\t\twrite_toc(cn, mut symbols_toc) // write head\n\t}\n\tif cfg.html_only_contents {\n\t\t// no need for theming, styling etc, useful for testing and for external documentation generators\n\t\treturn contents.str()\n\t}\n\n\t// write css\n\theader_name := if cfg.is_multi && vd.docs.len > 1 {\n\t\tos.file_name(os.real_path(cfg.input_path))\n\t} else {\n\t\td.head.name\n\t}\n\tmodules_toc_str := if cfg.is_multi || vd.docs.len > 1 {\n\t\tvd.gen_modules_toc(d.head.name)\n\t} else {\n\t\t''\n\t}\n\tsymbols_toc_str := symbols_toc.str()\n\tmut result := os.read_file(os.join_path(cfg.theme_dir, 'index.html')) or { panic(err) }\n\tif cfg.html_no_vhash {\n\t\tresult = result.replace('{{ version }}', 'latest')\n\t} else {\n\t\tmut version := if vd.manifest.version.len != 0 { vd.manifest.version } else { '' }\n\t\tversion = [version, @VCURRENTHASH].join(' ')\n\t\tresult = result.replace('{{ version }}', version)\n\t}\n\tresult = result.replace('{{ title }}', d.head.name)\n\tresult = result.replace('{{ head_name }}', header_name)\n\tresult = result.replace('{{ light_icon }}', vd.assets['light_icon'])\n\tresult = result.replace('{{ dark_icon }}', vd.assets['dark_icon'])\n\tresult = result.replace('{{ menu_icon }}', vd.assets['menu_icon'])\n\tif cfg.html_no_assets {\n\t\tresult = result.replace('{{ head_assets }}', '')\n\t} else {\n\t\tresult = result.replace('{{ head_assets }}', if cfg.inline_assets {\n\t\t\t'<style>${vd.assets['doc_css']}</style>\n${tabs(2)}<style>${vd.assets['normalize_css']}</style>\n${tabs(2)}<script>${vd.assets['dark_mode_js']}</script>'\n\t\t} else {\n\t\t\t'<link rel=\"stylesheet\" href=\"${vd.assets['doc_css']}\" />\n${tabs(2)}<link rel=\"stylesheet\" href=\"${vd.assets['normalize_css']}\" />\n${tabs(2)}<script src=\"${vd.assets['dark_mode_js']}\"></script>'\n\t\t})\n\t}\n\tif cfg.html_no_toc_urls {\n\t\tresult = result.replace('{{ toc_links }}', '')\n\t} else {\n\t\tresult = result.replace('{{ toc_links }}', if cfg.is_multi || vd.docs.len > 1 {\n\t\t\tmodules_toc_str\n\t\t} else {\n\t\t\tsymbols_toc_str\n\t\t})\n\t}\n\tresult = result.replace('{{ contents }}', contents.str())\n\tif cfg.html_no_right {\n\t\tresult = result.replace('{{ right_content }}', '')\n\t} else {\n\t\tresult = result.replace('{{ right_content }}', if cfg.is_multi && d.head.name != 'README' {\n\t\t\t'<div class=\"doc-toc\"><ul>${symbols_toc_str}</ul></div>'\n\t\t} else {\n\t\t\t''\n\t\t})\n\t}\n\tif cfg.html_no_footer {\n\t\tresult = result.replace('{{ footer_content }}', '')\n\t} else {\n\t\tresult = result.replace('{{ footer_content }}', gen_footer_text(d, !cfg.no_timestamp))\n\t}\n\tif cfg.html_no_assets {\n\t\tresult = result.replace('{{ footer_assets }}', '')\n\t} else {\n\t\tresult = result.replace('{{ footer_assets }}', if cfg.inline_assets {\n\t\t\t'<script>${vd.assets['doc_js']}</script>'\n\t\t} else {\n\t\t\t'<script src=\"${vd.assets['doc_js']}\"></script>'\n\t\t})\n\t}\n\treturn result\n}\n\nfn (vd &VDoc) gen_modules_toc(active_doc string) string {\n\tmut modules_toc := strings.new_builder(200)\n\tmut used_submod_prefixes := map[string]bool{}\n\tdoc_names := vd.docs.map(it.head.name)\n\tfor dc in vd.docs {\n\t\tmut submod_prefix := dc.head.name.all_before('.')\n\t\tif index := dc.head.frontmatter['index'] {\n\t\t\tif dc.head.name == 'index' {\n\t\t\t\tsubmod_prefix = index\n\t\t\t}\n\t\t}\n\t\tif used_submod_prefixes[submod_prefix] {\n\t\t\tcontinue\n\t\t}\n\t\tused_submod_prefixes[submod_prefix] = true\n\t\tmut href_name := ''\n\t\tif dc.head.name in ['README', 'index'] {\n\t\t\thref_name = './index.html'\n\t\t} else if submod_prefix in doc_names {\n\t\t\thref_name = './${submod_prefix}.html'\n\t\t}\n\t\tsubmodules := vd.docs.filter(it.head.name.starts_with(submod_prefix + '.'))\n\t\tdropdown := if submodules.len > 0 { vd.assets['arrow_icon'] } else { '' }\n\t\tactive_class := if dc.head.name == active_doc { ' active' } else { '' }\n\t\tmenu_item := if href_name != '' {\n\t\t\t'<a href=\"${href_name}\">${submod_prefix}</a>'\n\t\t} else {\n\t\t\t'<a>${submod_prefix}</a>'\n\t\t}\n\t\tmodules_toc.write_string('<li class=\"open${active_class}\">\\n<div class=\"menu-row\">${dropdown}${menu_item}</div>\\n')\n\t\tfor j, cdoc in submodules {\n\t\t\tif j == 0 {\n\t\t\t\tmodules_toc.write_string('<ul>\\n')\n\t\t\t}\n\t\t\tsubmod_name := cdoc.head.name.all_after(submod_prefix + '.')\n\t\t\tsub_selected_classes := if cdoc.head.name == active_doc {\n\t\t\t\t' class=\"active\"'\n\t\t\t} else {\n\t\t\t\t''\n\t\t\t}\n\t\t\tmodules_toc.write_string('<li${sub_selected_classes}><a href=\"./${cdoc.head.name}.html\">${submod_name}</a></li>\\n')\n\t\t\tif j == submodules.len - 1 {\n\t\t\t\tmodules_toc.write_string('</ul>\\n')\n\t\t\t}\n\t\t}\n\t\tmodules_toc.write_string('</li>\\n')\n\t}\n\treturn modules_toc.str()\n}\n\nfn get_repo_file_link(repo_url string, repo_branch string, file_name string) string {\n\tmut url := urllib.parse(repo_url) or { return '' }\n\tif url.path.len <= 1 || file_name == '' {\n\t\treturn ''\n\t}\n\turl.path = url.path.trim_right('/') + match url.host {\n\t\t'github.com' { '/blob/${repo_branch}/${file_name}' }\n\t\t'gitlab.com' { '/-/blob/${repo_branch}/${file_name}' }\n\t\t'git.sir.ht' { '/tree/${repo_branch}/${file_name}' }\n\t\telse { '' }\n\t}\n\tif url.path == '/' {\n\t\treturn ''\n\t}\n\treturn url.str()\n}\n\nfn get_src_dir_link(repo_url string, repo_branch string, file_name string) string {\n\tfile_url := get_repo_file_link(repo_url, repo_branch, file_name)\n\tif file_url == '' {\n\t\treturn ''\n\t}\n\tmut parsed_file_url := urllib.parse(file_url) or { return '' }\n\tmut dir_path := parsed_file_url.path.all_before_last('/')\n\tif dir_path == '' {\n\t\tdir_path = '/'\n\t}\n\tparsed_file_url.path = if dir_path == '/' { '/' } else { dir_path + '/' }\n\tparsed_file_url.raw_query = ''\n\tparsed_file_url.fragment = ''\n\treturn parsed_file_url.str()\n}\n\nfn get_src_link(repo_url string, repo_branch string, file_name string, line_nr int) string {\n\tfile_url := get_repo_file_link(repo_url, repo_branch, file_name)\n\tif file_url == '' {\n\t\treturn ''\n\t}\n\tmut parsed_file_url := urllib.parse(file_url) or { return '' }\n\tparsed_file_url.fragment = 'L${line_nr}'\n\treturn parsed_file_url.str()\n}\n\nfn normalize_url_path(path string) string {\n\tif path == '' {\n\t\treturn ''\n\t}\n\tis_absolute := path.starts_with('/')\n\tmut parts := []string{}\n\tfor part in path.split('/') {\n\t\tmatch part {\n\t\t\t'', '.' {}\n\t\t\t'..' {\n\t\t\t\tif parts.len > 0 {\n\t\t\t\t\tparts.delete_last()\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tparts << part\n\t\t\t}\n\t\t}\n\t}\n\tmut normalized := parts.join('/')\n\tif is_absolute {\n\t\tnormalized = '/' + normalized\n\t}\n\treturn if normalized == '' && is_absolute { '/' } else { normalized }\n}\n\nfn is_relative_markdown_link(link string) bool {\n\tvalue := link.trim_space()\n\tif value == '' || value.starts_with('#') || value.starts_with('//') {\n\t\treturn false\n\t}\n\tif value.starts_with('/') {\n\t\treturn false\n\t}\n\tif url := urllib.parse(value) {\n\t\treturn url.scheme == '' && url.host == ''\n\t}\n\treturn true\n}\n\nfn resolve_relative_markdown_link(base_url string, link string) string {\n\tif base_url == '' || !is_relative_markdown_link(link) {\n\t\treturn link\n\t}\n\tmut parsed_base := urllib.parse(base_url) or { return link }\n\tmut relative_path := link\n\tmut fragment := ''\n\tif hash_idx := relative_path.index('#') {\n\t\tfragment = relative_path[hash_idx + 1..]\n\t\trelative_path = relative_path[..hash_idx]\n\t}\n\tmut query := ''\n\tif query_idx := relative_path.index('?') {\n\t\tquery = relative_path[query_idx + 1..]\n\t\trelative_path = relative_path[..query_idx]\n\t}\n\tbase_path := if parsed_base.path.ends_with('/') {\n\t\tparsed_base.path\n\t} else {\n\t\tparsed_base.path.all_before_last('/') + '/'\n\t}\n\tparsed_base.path = normalize_url_path(base_path + relative_path)\n\tparsed_base.raw_query = query\n\tparsed_base.fragment = fragment\n\treturn parsed_base.str()\n}\n\nfn write_token(tok token.Token, typ HighlightTokenTyp, mut buf strings.Builder) {\n\tmut token_content := ''\n\tmatch typ {\n\t\t.unone, .operator, .punctuation {\n\t\t\ttoken_content = tok.kind.str()\n\t\t}\n\t\t.string_interp {\n\t\t\t// tok.kind.str() for this returns $2 instead of $\n\t\t\ttoken_content = '$'\n\t\t}\n\t\t.opening_string {\n\t\t\ttoken_content = \"'${tok.lit}\"\n\t\t}\n\t\t.closing_string {\n\t\t\t// A string as the next token of the expression\n\t\t\t// inside the string interpolation indicates that\n\t\t\t// this is the closing of string interpolation\n\t\t\ttoken_content = \"${tok.lit}'\"\n\t\t}\n\t\t.string {\n\t\t\ttoken_content = \"'${tok.lit}'\"\n\t\t}\n\t\t.char {\n\t\t\ttoken_content = '`${tok.lit}`'\n\t\t}\n\t\t.comment {\n\t\t\tif tok.lit != '' && tok.lit[0] == 1 {\n\t\t\t\ttoken_content = '//${tok.lit[1..]}'\n\t\t\t} else {\n\t\t\t\ttoken_content = '//${tok.lit}'\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\ttoken_content = tok.lit\n\t\t}\n\t}\n\tbuf.write_string(html.escape(token_content))\n}\n\nfn html_highlight(code string, tb &ast.Table) string {\n\tmut s := scanner.new_scanner(code, .parse_comments, &pref.Preferences{ output_mode: .silent })\n\tmut tok := s.scan()\n\tmut prev_tok := tok\n\tmut next_tok := s.scan()\n\tmut buf := strings.new_builder(200)\n\tmut i := 0\n\tmut inside_string_interp := false\n\tfor i < code.len {\n\t\tif i != tok.pos {\n\t\t\t// All characters not detected by the scanner\n\t\t\t// (mostly whitespaces) go here.\n\t\t\tch := code[i]\n\t\t\tif ch == `<` {\n\t\t\t\tbuf.write_string('&lt;')\n\t\t\t} else if ch == `>` {\n\t\t\t\tbuf.write_string('&gt;')\n\t\t\t} else if ch == `&` {\n\t\t\t\tbuf.write_string('&amp;')\n\t\t\t} else {\n\t\t\t\tbuf.write_u8(ch)\n\t\t\t}\n\t\t\ti++\n\t\t\tcontinue\n\t\t}\n\n\t\tmut tok_typ := HighlightTokenTyp.unone\n\t\tmatch tok.kind {\n\t\t\t.name {\n\t\t\t\tif tok.lit in highlight_builtin_types || tb.known_type(tok.lit) {\n\t\t\t\t\ttok_typ = .builtin\n\t\t\t\t} else if next_tok.kind == .lcbr {\n\t\t\t\t\ttok_typ = .symbol\n\t\t\t\t} else if next_tok.kind == .lpar || (!tok.lit[0].is_capital()\n\t\t\t\t\t&& next_tok.kind == .lt && next_tok.pos == tok.pos + tok.lit.len) {\n\t\t\t\t\ttok_typ = .function\n\t\t\t\t} else {\n\t\t\t\t\ttok_typ = .name\n\t\t\t\t}\n\t\t\t}\n\t\t\t.comment {\n\t\t\t\ttok_typ = .comment\n\t\t\t}\n\t\t\t.chartoken {\n\t\t\t\ttok_typ = .char\n\t\t\t}\n\t\t\t.str_dollar {\n\t\t\t\ttok_typ = .string_interp\n\t\t\t\tinside_string_interp = true\n\t\t\t}\n\t\t\t.string {\n\t\t\t\tif inside_string_interp {\n\t\t\t\t\tif next_tok.kind == .str_dollar {\n\t\t\t\t\t\t// the \" hello \" in \"${a} hello ${b} world\"\n\t\t\t\t\t\ttok_typ = .partial_string\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// the \" world\" in \"${a} hello ${b} world\"\n\t\t\t\t\t\ttok_typ = .closing_string\n\t\t\t\t\t}\n\n\t\t\t\t\t// NOTE: Do not switch inside_string_interp yet!\n\t\t\t\t\t// It will be handy later when we do some special\n\t\t\t\t\t// handling in generating code (see code below)\n\t\t\t\t} else if next_tok.kind == .str_dollar {\n\t\t\t\t\ttok_typ = .opening_string\n\t\t\t\t} else {\n\t\t\t\t\ttok_typ = .string\n\t\t\t\t}\n\t\t\t}\n\t\t\t.number {\n\t\t\t\ttok_typ = .number\n\t\t\t}\n\t\t\t.key_true, .key_false {\n\t\t\t\ttok_typ = .boolean\n\t\t\t}\n\t\t\t.lpar, .lcbr, .rpar, .rcbr, .lsbr, .rsbr, .semicolon, .colon, .comma, .dot, .dotdot,\n\t\t\t.ellipsis {\n\t\t\t\ttok_typ = .punctuation\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif token.is_key(tok.lit) || token.is_decl(tok.kind) {\n\t\t\t\t\ttok_typ = .keyword\n\t\t\t\t} else if tok.kind.is_assign() || tok.is_unary() || tok.kind.is_relational()\n\t\t\t\t\t|| tok.kind.is_infix() || tok.kind.is_postfix() {\n\t\t\t\t\ttok_typ = .operator\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif tok_typ in [.unone, .name] {\n\t\t\twrite_token(tok, tok_typ, mut buf)\n\t\t} else {\n\t\t\t// Special handling for \"complex\" string literals\n\t\t\tif tok_typ in [.partial_string, .closing_string] && inside_string_interp {\n\t\t\t\t// rcbr is not rendered when the string on the right\n\t\t\t\t// side of the expr/string interpolation is not empty.\n\t\t\t\t// e.g. \"${a}.${b}${c}\"\n\t\t\t\t// expectation: \"${a}.${b}${c}\"\n\t\t\t\t// reality: \"${a.${b}${c}\"\n\t\t\t\tif tok.lit.len != 0 {\n\t\t\t\t\twrite_token(token.Token{ kind: .rcbr }, .unone, mut buf)\n\t\t\t\t}\n\n\t\t\t\tinside_string_interp = false\n\t\t\t}\n\n\t\t\t// Properly treat and highlight the \"string\"-related types\n\t\t\t// as if they are \"string\" type.\n\t\t\tfinal_tok_typ := match tok_typ {\n\t\t\t\t.opening_string, .partial_string, .closing_string { HighlightTokenTyp.string }\n\t\t\t\telse { tok_typ }\n\t\t\t}\n\n\t\t\tbuf.write_string('<span class=\"token ${final_tok_typ}\">')\n\t\t\tif tok_typ == .string {\n\t\t\t\t// Make sure to escape html in strings. Otherwise it will be rendered in the\n\t\t\t\t// html documentation outputs / its style rules will affect the readme.\n\t\t\t\tbuf.write_string(\"'${html.escape(tok.lit.str())}'\")\n\t\t\t} else {\n\t\t\t\tif final_tok_typ == .string && prev_tok.lit == 'return' {\n\t\t\t\t\tbuf.write_string(' ')\n\t\t\t\t}\n\t\t\t\twrite_token(tok, tok_typ, mut buf)\n\t\t\t}\n\t\t\tbuf.write_string('</span>')\n\t\t}\n\n\t\tif next_tok.kind == .eof {\n\t\t\tbreak\n\t\t}\n\n\t\ti = tok.pos + tok.len\n\n\t\t// This is to avoid issues that skips any \"unused\" tokens\n\t\t// For example: Call expr with complex string literals as arg\n\t\tif i - 1 == next_tok.pos {\n\t\t\ti--\n\t\t}\n\t\tprev_tok = tok\n\t\ttok = next_tok\n\t\tnext_tok = s.scan()\n\t}\n\treturn buf.str()\n}\n\nfn (vd &VDoc) doc_node_html(dn doc.DocNode, link string, md_link_base string, head bool, include_examples bool, tb &ast.Table) string {\n\tmut dnw := strings.new_builder(200)\n\thead_tag := if head { 'h1' } else { 'h2' }\n\tmut renderer := markdown.HtmlRenderer{\n\t\ttransformer: &MdHtmlCodeHighlighter{\n\t\t\ttable:              tb\n\t\t\trelative_link_base: md_link_base\n\t\t}\n\t}\n\tonly_comments_text := dn.merge_comments_without_examples()\n\tmd_content := markdown.render(only_comments_text, mut renderer) or { '' }\n\thighlighted_code := html_highlight(dn.content, tb)\n\tnode_class := if dn.kind == .const_group { ' const' } else { '' }\n\tsym_name := get_sym_name(dn)\n\tmut deprecated_tags := dn.tags.filter(it.starts_with('deprecated'))\n\tif doc.should_sort {\n\t\tdeprecated_tags.sort()\n\t}\n\tmut tags := dn.tags.filter(!it.starts_with('deprecated'))\n\tif doc.should_sort {\n\t\ttags.sort()\n\t}\n\tmut node_id := get_node_id(dn)\n\tmut hash_link := if !head { ' <a href=\"#${node_id}\">#</a>' } else { '' }\n\tif head && is_module_readme(dn) {\n\t\tnode_id = 'readme_${node_id}'\n\t\thash_link = ' <a href=\"#${node_id}\">#</a>'\n\t}\n\tdnw.writeln('${tabs(2)}<section id=\"${node_id}\" class=\"doc-node${node_class}\">')\n\tif dn.name != '' {\n\t\tif dn.kind == .const_group {\n\t\t\tdnw.write_string('${tabs(3)}<div class=\"title\"><${head_tag}>${sym_name}${hash_link}</${head_tag}>')\n\t\t} else {\n\t\t\tdnw.write_string('${tabs(3)}<div class=\"title\"><${head_tag}>${dn.kind} ${sym_name}${hash_link}</${head_tag}>')\n\t\t}\n\t\tif link != '' {\n\t\t\tdnw.write_string('<a class=\"link\" rel=\"noreferrer\" target=\"_blank\" href=\"${link}\">${link_svg}</a>')\n\t\t}\n\t\tdnw.write_string('</div>\\n')\n\t}\n\tif deprecated_tags.len > 0 {\n\t\tattributes := deprecated_tags.map('<div class=\"attribute attribute-deprecated\">${it.replace_each(quote_escape_seq)}</div>\\n').join('')\n\t\tdnw.writeln('<div class=\"attributes\">${attributes}</div>\\n')\n\t}\n\tif tags.len > 0 {\n\t\tattributes := tags.map('<div class=\"attribute\">${it}</div>').join('')\n\t\tdnw.writeln('<div class=\"attributes\">${attributes}</div>')\n\t}\n\tif !head && dn.content.len > 0 {\n\t\tdnw.writeln('<pre class=\"signature\">\\n<code>${highlighted_code}</code></pre>')\n\t}\n\t// do not mess with md_content further, its formatting is important, just output it 1:1 !\n\tdnw.writeln('${md_content}\\n')\n\t// Write examples if any found\n\texamples := dn.examples()\n\tif include_examples && examples.len > 0 {\n\t\texample_title := if examples.len > 1 { 'Examples' } else { 'Example' }\n\t\tdnw.writeln('<section class=\"doc-node examples\"><h4>${example_title}</h4>')\n\t\tfor example in examples {\n\t\t\thl_example := html_highlight(example, tb)\n\t\t\tdnw.writeln('<pre>\\n<code class=\"language-v\">${hl_example}</code></pre>')\n\t\t}\n\t\tdnw.writeln('</section>')\n\t}\n\tdnw.writeln('</section>')\n\tdnw_str := dnw.str()\n\treturn dnw_str\n}\n\nfn write_toc(dn doc.DocNode, mut toc strings.Builder) {\n\tmut toc_slug := if dn.name == '' || dn.content.len == 0 { '' } else { slug(dn.name) }\n\tif toc_slug == '' && dn.children.len > 0 {\n\t\tif dn.children[0].name == '' {\n\t\t\ttoc_slug = slug(dn.name)\n\t\t} else {\n\t\t\ttoc_slug = slug(dn.name + '.' + dn.children[0].name)\n\t\t}\n\t}\n\tif is_module_readme(dn) {\n\t\tif dn.comments.len == 0 || (dn.comments.len > 0 && dn.comments[0].text.len == 0) {\n\t\t\treturn\n\t\t}\n\t\ttoc.write_string('<li class=\"open\"><a href=\"#readme_${toc_slug}\">README</a>')\n\t} else if dn.name != 'Constants' {\n\t\ttoc.write_string('<li class=\"open\"><a href=\"#${toc_slug}\">${dn.kind} ${dn.name}</a>')\n\t\ttoc.writeln('        <ul>')\n\t\tfor child in dn.children {\n\t\t\tcname := dn.name + '.' + child.name\n\t\t\ttoc.writeln('<li><a href=\"#${slug(cname)}\">${child.kind} ${child.name}</a></li>')\n\t\t}\n\t\ttoc.writeln('</ul>')\n\t} else {\n\t\ttoc.write_string('<li class=\"open\"><a href=\"#${toc_slug}\">${dn.name}</a>')\n\t}\n\ttoc.writeln('</li>')\n}\n\nstruct MdHtmlCodeHighlighter {\nmut:\n\tlanguage           string\n\ttable              &ast.Table\n\trelative_link_base string\n}\n\nfn (f &MdHtmlCodeHighlighter) transform_attribute(p markdown.ParentType, name string, value string) string {\n\tmut transformed := value\n\tif p is markdown.MD_SPANTYPE && p in [.md_span_a, .md_span_img] && name in ['href', 'src'] {\n\t\ttransformed = resolve_relative_markdown_link(f.relative_link_base, value)\n\t}\n\treturn markdown.default_html_transformer.transform_attribute(p, name, transformed)\n}\n\nfn (f &MdHtmlCodeHighlighter) transform_content(parent markdown.ParentType, text string) string {\n\tif parent is markdown.MD_BLOCKTYPE && parent == .md_block_code {\n\t\tif f.language == '' {\n\t\t\treturn html.escape(text)\n\t\t}\n\t\toutput := html_highlight(text, f.table)\n\t\t// Reset the language, so that it will not persist between blocks,\n\t\t// and will not be accidentally re-used for the next block, that may be lacking ```language :\n\t\tunsafe {\n\t\t\tf.language = ''\n\t\t}\n\t\treturn output\n\t}\n\treturn text\n}\n\nfn (mut f MdHtmlCodeHighlighter) config_set(key string, val string) {\n\tif key == 'code_language' {\n\t\tf.language = val\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/main.v",
    "content": "module main\n\nimport os\nimport os.cmdline\nimport term\nimport document as doc\nimport v.vmod\n\nconst vexe = os.getenv_opt('VEXE') or { @VEXE }\n\nconst vroot = os.dir(vexe)\n\nconst allowed_formats = ['md', 'markdown', 'json', 'text', 'ansi', 'html', 'htm', 'none']\n\nenum RunExampleMode {\n\tskip\n\trun\n\tcheck\n}\n\nstruct Config {\nmut:\n\tpub_only         bool = true\n\tshow_loc         bool // for plaintext\n\tshow_time        bool // show the total time spend generating content\n\tis_color         bool\n\tis_multi         bool\n\tis_vlib          bool\n\tis_verbose       bool\n\tinclude_readme   bool\n\tinclude_examples bool = true\n\tinclude_comments bool // for plaintext\n\tinline_assets    bool\n\ttheme_dir        string = default_theme\n\tno_timestamp     bool\n\toutput_path      string\n\toutput_type      OutputType = .unset\n\tinput_path       string\n\tsymbol_name      string\n\tplatform         doc.Platform\n\trun_examples     RunExampleMode // `-unsafe-run-examples` will run all `// Example: assert mod.abc() == y` comments in the processed modules.\n\t// -check-examples will only check/validate that they compile, but without running any code.\n\t// The options below are useful for generating a more stable HTML, that is easier to regression test:\n\thtml_only_contents bool // `-html-only-contents` will produce only the content of any given page, without styling tags etc.\n\thtml_no_vhash      bool // `-html-no-vhash` will remove the version hash from the generated html\n\thtml_no_assets     bool // `-html-no-assets` will not include CSS and JS asset tags in the generated html\n\thtml_no_right      bool // `-html-no-right` will not add the doc-toc right panel in the generated html\n\thtml_no_toc_urls   bool // `-html-no-toc-urls` will not add the toc_links panel in the generated html\n\thtml_no_footer     bool // `-html-no-footer` will not add the footer panel in the generated html\n}\n\nfn main() {\n\tunbuffer_stdout() // avoid the need for flush_stdout() calls\n\tif os.args.len < 2 || '-h' in os.args || '-help' in os.args || '--help' in os.args\n\t\t|| os.args[1..] == ['doc', 'help'] {\n\t\tos.system('${os.quoted_path(vexe)} help doc')\n\t\texit(0)\n\t}\n\targs := os.args[2..].clone()\n\tcfg := parse_arguments(args)\n\tif cfg.input_path == '' {\n\t\teprintln('vdoc: No input path found.')\n\t\texit(1)\n\t}\n\t// Config is immutable from this point on\n\tmut vd := &VDoc{\n\t\tcfg:      cfg\n\t\tmanifest: vmod.Manifest{}\n\t}\n\tvd.vprintln('Setting output type to \"${cfg.output_type}\"')\n\tvd.generate_docs_from_file()\n\tif cfg.run_examples != .skip {\n\t\tif vd.example_oks == 0 && vd.example_failures == 0 {\n\t\t\tprintln(term.colorize(term.bright_yellow, 'Found NO examples.'))\n\t\t} else {\n\t\t\tprintln(term.colorize(term.gray, 'Found ${vd.example_oks} ok examples.'))\n\t\t}\n\t\tif vd.example_failures > 0 {\n\t\t\tprintln(term.colorize(term.red, 'Found ${vd.example_failures} failing examples.'))\n\t\t\texit(1)\n\t\t}\n\t}\n}\n\nfn parse_arguments(args []string) Config {\n\tmut cfg := Config{}\n\tcfg.is_color = term.can_show_color_on_stdout()\n\tmut is_color_was_set_explicitly := false\n\tfor i := 0; i < args.len; i++ {\n\t\targ := args[i]\n\t\tcurrent_args := args[i..]\n\t\tmatch arg {\n\t\t\t'-all' {\n\t\t\t\tcfg.pub_only = false\n\t\t\t}\n\t\t\t'-f' {\n\t\t\t\tformat := cmdline.option(current_args, '-f', '')\n\t\t\t\tif format !in allowed_formats {\n\t\t\t\t\tallowed_str := allowed_formats.join(', ')\n\t\t\t\t\teprintln('vdoc: \"${format}\" is not a valid format. Only ${allowed_str} are allowed.')\n\t\t\t\t\texit(1)\n\t\t\t\t}\n\t\t\t\tcfg.output_type = set_output_type_from_str(format)\n\t\t\t\ti++\n\t\t\t}\n\t\t\t'-color' {\n\t\t\t\tcfg.is_color = true\n\t\t\t\tis_color_was_set_explicitly = true\n\t\t\t}\n\t\t\t'-no-color' {\n\t\t\t\tcfg.is_color = false\n\t\t\t\tis_color_was_set_explicitly = true\n\t\t\t}\n\t\t\t'-inline-assets' {\n\t\t\t\tcfg.inline_assets = true\n\t\t\t}\n\t\t\t'-theme-dir' {\n\t\t\t\tcfg.theme_dir = cmdline.option(current_args, '-theme-dir', default_theme)\n\t\t\t}\n\t\t\t'-l' {\n\t\t\t\tcfg.show_loc = true\n\t\t\t}\n\t\t\t'-comments' {\n\t\t\t\tcfg.include_comments = true\n\t\t\t}\n\t\t\t'-m' {\n\t\t\t\tcfg.is_multi = true\n\t\t\t}\n\t\t\t'-o' {\n\t\t\t\topath := cmdline.option(current_args, '-o', '')\n\t\t\t\tcfg.output_path = if opath in ['stdout', '-'] { opath } else { os.real_path(opath) }\n\t\t\t\ti++\n\t\t\t}\n\t\t\t'-os' {\n\t\t\t\tplatform_str := cmdline.option(current_args, '-os', '')\n\t\t\t\tif platform_str == 'cross' {\n\t\t\t\t\teprintln('`v doc -os cross` is not supported yet.')\n\t\t\t\t\texit(1)\n\t\t\t\t}\n\t\t\t\tselected_platform := doc.platform_from_string(platform_str) or {\n\t\t\t\t\teprintln(err.msg())\n\t\t\t\t\texit(1)\n\t\t\t\t}\n\t\t\t\tcfg.platform = selected_platform\n\t\t\t\ti++\n\t\t\t}\n\t\t\t'-time' {\n\t\t\t\tcfg.show_time = true\n\t\t\t}\n\t\t\t'-check-examples' {\n\t\t\t\tcfg.run_examples = .check\n\t\t\t}\n\t\t\t'-unsafe-run-examples' {\n\t\t\t\tcfg.run_examples = .run\n\t\t\t}\n\t\t\t'-run-examples' {\n\t\t\t\teprintln('WARNING: the `-run-examples` option is deprecated, and will be removed after 2025-11-13.')\n\t\t\t\teprintln('  Use `-unsafe-run-examples` instead of `-run-examples` .')\n\t\t\t\tcfg.run_examples = .run\n\t\t\t}\n\t\t\t'-no-timestamp' {\n\t\t\t\tcfg.no_timestamp = true\n\t\t\t}\n\t\t\t'-no-examples' {\n\t\t\t\tcfg.include_examples = false\n\t\t\t}\n\t\t\t//\n\t\t\t'-html-only-contents' {\n\t\t\t\tcfg.html_only_contents = true\n\t\t\t}\n\t\t\t'-html-no-vhash' {\n\t\t\t\tcfg.html_no_vhash = true\n\t\t\t}\n\t\t\t'-html-no-assets' {\n\t\t\t\tcfg.html_no_assets = true\n\t\t\t}\n\t\t\t'-html-no-right' {\n\t\t\t\tcfg.html_no_right = true\n\t\t\t}\n\t\t\t'-html-no-toc-urls' {\n\t\t\t\tcfg.html_no_toc_urls = true\n\t\t\t}\n\t\t\t'-html-no-footer' {\n\t\t\t\tcfg.html_no_footer = true\n\t\t\t}\n\t\t\t//\n\t\t\t'-readme' {\n\t\t\t\tcfg.include_readme = true\n\t\t\t}\n\t\t\t'-v' {\n\t\t\t\tcfg.is_verbose = true\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif cfg.input_path == '' {\n\t\t\t\t\tcfg.input_path = arg\n\t\t\t\t} else if !cfg.is_multi {\n\t\t\t\t\t// Symbol name filtering should not be enabled\n\t\t\t\t\t// in multi-module documentation mode.\n\t\t\t\t\tcfg.symbol_name = arg\n\t\t\t\t}\n\t\t\t\tif i == args.len - 1 {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif cfg.output_type == .html {\n\t\t// quirks specific to *just* the html output mode:\n\t\tif cfg.output_path in ['stdout', '-'] {\n\t\t\tcfg.inline_assets = true\n\t\t}\n\t}\n\n\tif !is_color_was_set_explicitly {\n\t\tif cfg.output_type == .plaintext {\n\t\t\tcfg.is_color = false\n\t\t} else if cfg.output_type == .ansi {\n\t\t\tcfg.is_color = true\n\t\t}\n\t}\n\n\tif cfg.is_color {\n\t\tos.setenv('VCOLORS', 'always', true)\n\t} else {\n\t\tos.setenv('VCOLORS', 'never', true)\n\t}\n\n\tcfg.input_path = cfg.input_path.replace('\\\\', '/')\n\tis_path := cfg.input_path.ends_with('.v') || cfg.input_path.split('/').len > 1\n\t\t|| cfg.input_path == '.'\n\tif cfg.input_path.trim_right('/') == 'vlib' {\n\t\tcfg.is_vlib = true\n\t\tcfg.is_multi = true\n\t\tcfg.input_path = os.join_path(vroot, 'vlib')\n\t} else if !is_path {\n\t\tmod_path := doc.lookup_module(cfg.input_path) or {\n\t\t\teprintln('vdoc: ${err}')\n\t\t\texit(1)\n\t\t}\n\t\tcfg.input_path = mod_path\n\t}\n\tcfg.input_path = cfg.input_path.replace('/', os.path_separator)\n\treturn cfg\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/markdown.v",
    "content": "module main\n\nimport strings\nimport document as doc\n\nfn (vd &VDoc) gen_markdown(d doc.Doc, with_toc bool) string {\n\tcfg := vd.cfg\n\tmut hw := strings.new_builder(200)\n\tmut cw := strings.new_builder(200)\n\thw.writeln('# ${d.head.content}')\n\tif d.head.comments.len > 0 && cfg.include_comments {\n\t\tcomments := if vd.cfg.include_examples {\n\t\t\td.head.merge_comments()\n\t\t} else {\n\t\t\td.head.merge_comments_without_examples()\n\t\t}\n\t\thw.writeln('${comments}')\n\t}\n\thw.writeln('\\n')\n\tif with_toc {\n\t\thw.writeln('## Contents')\n\t}\n\tvd.write_markdown_content(d.contents.arr(), mut cw, mut hw, 0, with_toc)\n\tfooter_text := gen_footer_text(d, !vd.cfg.no_timestamp)\n\tcw.writeln('#### ${footer_text}')\n\treturn hw.str() + '\\n' + cw.str()\n}\n\nfn (vd &VDoc) write_markdown_content(contents []doc.DocNode, mut cw strings.Builder, mut hw strings.Builder,\n\tindent int, with_toc bool) {\n\tfor cn in contents {\n\t\tif with_toc && cn.name != '' {\n\t\t\thw.writeln(' '.repeat(2 * indent) + '- [${slug(cn.name)}](#${cn.name})')\n\t\t\tcw.writeln('## ${cn.name}')\n\t\t}\n\t\tif cn.content.len > 0 {\n\t\t\tcw.writeln('```v\\n${cn.content}\\n```\\n')\n\t\t\tif cn.comments.len > 0 {\n\t\t\t\tcomments := cn.merge_comments_without_examples()\n\t\t\t\tcw.writeln('${comments}\\n')\n\t\t\t}\n\t\t\t// Write examples if any found\n\t\t\texamples := cn.examples()\n\t\t\tif vd.cfg.include_examples && examples.len > 0 {\n\t\t\t\texample_title := if examples.len > 1 { 'Examples' } else { 'Example' }\n\t\t\t\tcw.writeln('${example_title}\\n```v\\n')\n\t\t\t\tfor example in examples {\n\t\t\t\t\tcw.writeln('${example}\\n')\n\t\t\t\t}\n\t\t\t\tcw.writeln('```\\n')\n\t\t\t}\n\t\t\tcw.writeln(r'[[Return to contents]](#Contents)')\n\t\t\tcw.writeln('')\n\t\t}\n\t\tvd.write_markdown_content(cn.children, mut cw, mut hw, indent + 1, with_toc)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/run_examples.v",
    "content": "module main\n\nimport document as doc\nimport v.vmod\nimport os\nimport rand\nimport term\n\nfn (mut vd VDoc) process_all_examples(contents []doc.DocNode) {\n\tfor cn in contents {\n\t\tif cn.content.len > 0 {\n\t\t\tvd.run_examples(cn)\n\t\t}\n\t\tvd.process_all_examples(cn.children)\n\t}\n}\n\nconst normalised_default_vmodules_path = os.vmodules_dir().replace('\\\\', '/')\nconst vdoc_max_fails = os.getenv_opt('VDOC_MAX_FAILS') or { '999' }.int()\n\nfn get_mod_name_by_file_path(file_path string) string {\n\tmut mcache := vmod.get_cache()\n\tdn_folder := os.dir(os.real_path(file_path)).replace('\\\\', '/').trim_string_right('/src')\n\tvmodpath := mcache.get_by_folder(dn_folder)\n\tnormal_folder := dn_folder.replace('\\\\', '/')\n\tvmod_folder := vmodpath.vmod_folder.replace('\\\\', '/')\n\tmut relative_mod_path := normal_folder\n\trelative_mod_path = relative_mod_path.trim_string_left(vmod_folder).trim_string_left('/')\n\trelative_mod_path = relative_mod_path.trim_string_left(normalised_default_vmodules_path)\n\trelative_mod_path = relative_mod_path.trim_string_left('vlib/')\n\tmod_name := relative_mod_path.replace('/', '.').trim('.')\n\treturn mod_name\n}\n\nfn (mut vd VDoc) run_examples(dn doc.DocNode) {\n\tif dn.comments.len == 0 || vd.cfg.run_examples == .skip {\n\t\treturn\n\t}\n\tvoptions := match vd.cfg.run_examples {\n\t\t.run { ' -g run ' }\n\t\t.check { '-N -W -check' }\n\t\t.skip { '' }\n\t}\n\texamples := dn.examples()\n\tif examples.len == 0 {\n\t\treturn\n\t}\n\tefolder := os.vtmp_dir()\n\tmut example_program_source_files := []string{}\n\tdefer {\n\t\tfor sfile in example_program_source_files {\n\t\t\tos.rm(sfile) or {}\n\t\t}\n\t}\n\tfor example in examples {\n\t\tif vd.example_failures >= vdoc_max_fails {\n\t\t\teprintln('> vdoc: too many examples failed in ${vd.cfg.run_examples} mode')\n\t\t\texit(1)\n\t\t}\n\t\tcode := example.all_after('Example:').all_after('example:').trim_space()\n\t\tmod_name := get_mod_name_by_file_path(dn.file_path)\n\t\tvsource_path := os.join_path(efolder, 'example_${rand.ulid()}.v')\n\t\t// eprintln('>>> example dn.file_path: ${dn.file_path} | mod_name: ${mod_name} | vsource_path: ${vsource_path} | code: `${code}`')\n\t\timport_clause := if mod_name in ['builtin', ''] { '' } else { 'import ${mod_name}\\n' }\n\t\tmut source := if import_clause != '' && !code.contains('import ') {\n\t\t\t'${import_clause}fn main() {\\n\\t${code}\\n}\\n'\n\t\t} else {\n\t\t\tcode\n\t\t}\n\t\tif !source.ends_with('\\n') {\n\t\t\tsource += '\\n'\n\t\t}\n\t\tos.write_file(vsource_path, source) or { continue }\n\t\tvd.vprintln('>>> vd.example_oks: ${vd.example_oks:5} | vd.example_failures: ${vd.example_failures:5} | examples.len: ${examples.len} | source.len: ${source.len:5} | dn.name: ${dn.name}')\n\t\tcmd := '${os.quoted_path(vexe)} ${voptions} ${os.quoted_path(vsource_path)}'\n\t\tres := os.execute(cmd)\n\t\tif res.exit_code != 0 {\n\t\t\teprintln('${dn_to_location(dn)}:${term.ecolorize(term.red, 'error in documentation example')}')\n\t\t\teprintln('          cmd: ${cmd}')\n\t\t\teprintln(' example line: ${term.colorize(term.bright_yellow, example)}')\n\t\t\teprintln('       result:')\n\t\t\teprintln(res.output)\n\t\t\tvd.example_failures++\n\t\t\tcontinue\n\t\t}\n\t\texample_program_source_files << vsource_path\n\t\tvd.example_oks++\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/basic/basic.comments.out",
    "content": "module testdata.basic\n\nconst source_root = 'temp' // some const\nconst another = int(5)\nconst windowpos_undefined_mask = C.SDL_WINDOWPOS_UNDEFINED_MASK //   0x1FFF0000u\n    Used to indicate that you don't care what the window position is.\nconst windowpos_undefined = C.SDL_WINDOWPOS_UNDEFINED\nfn funky()\n    funky - comment for function below\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/basic/basic.out",
    "content": "module testdata.basic\n\nconst source_root = 'temp' // some const\nconst another = int(5)\nconst windowpos_undefined_mask = C.SDL_WINDOWPOS_UNDEFINED_MASK //   0x1FFF0000u\nconst windowpos_undefined = C.SDL_WINDOWPOS_UNDEFINED\nfn funky()\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/basic/basic.v",
    "content": "module basic\n\npub const source_root = 'temp' // some const\n\npub const another = int(5)\n\n// Used to indicate that you don't care what the window position is.\npub const windowpos_undefined_mask = C.SDL_WINDOWPOS_UNDEFINED_MASK //   0x1FFF0000u\n\npub const windowpos_undefined = C.SDL_WINDOWPOS_UNDEFINED\n\n// funky - comment for function below\npub fn funky() {\n\tprintln('hi')\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/comments/main.comments.out",
    "content": "module rec\n    v doc -f html -o doc rec.v (doc should be an empty folder) I would like to see these 2 lines in HTML-generated header documentation\n\nfn fib(n int) int\n    fib Calculates the recursive fibonacci series `n` is the rank to pass to function I See these 3 lines only\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/comments/main.out",
    "content": "module rec\n\nfn fib(n int) int\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/comments/main.v",
    "content": "// v doc -f html -o doc rec.v (doc should be an empty folder)\n// I would like to see these 2 lines in HTML-generated header documentation\nmodule rec\n\n// fib Calculates the recursive fibonacci series\n// `n` is the rank to pass to function\n// I See these 3 lines only\npub fn fib(n int) int {\n\treturn if n < 2 { n } else { fib(n - 1) + fib(n - 2) }\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/multiline/main.comments.out",
    "content": "module main\n\nfn a1()\n    normal comment\nfn a2()\n    this should be merged into the same line\nfn a3()\n    This should be its own paragraph.\n    \n    This should be another paragraph.\nfn a4()\n    This should be merged into one paragraph.\n    \n    Note: this should be its own paragraph.\nfn a5()\n    This should be its own paragraph.\n    \n    Note: this should also be it own paragraph\n    \n    Note: this should be its own paragraph.\nfn a6()\n    A comment\n    \n    Fixme: this should be its own paragraph.\n    \n    Fixme: this should be its own paragraph.\n    \n    Fixme: this should be its own paragraph.\nfn a7()\n    A comment\n    \n    Todo: this should be its own paragraph.\n    \n    Todo: this should be its own paragraph.\n    \n    Todo: this should be its own paragraph.\nfn a8()\n    A comment\n    \n    Todo: this should be its own paragraph.\n    \n    Note: this should be its own paragraph.\n    \n    Fixme: this should be its own paragraph.\nfn a9()\n    normal comment\nfn foo()\n    foo does stuff\n    ```\n    this is a multiline codeblock.\n    second line\n    third line.\n    ```\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/multiline/main.out",
    "content": "module main\n\nfn a1()\nfn a2()\nfn a3()\nfn a4()\nfn a5()\nfn a6()\nfn a7()\nfn a8()\nfn a9()\nfn foo()\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/multiline/main.v",
    "content": "// normal comment\npub fn a1() {\n\tprintln('hi')\n}\n\n// this should be merged\n// into the same line\npub fn a2() {\n\tprintln('hi')\n}\n\n// This should be its own paragraph.\n//\n// This should be another paragraph.\npub fn a3() {\n\tprintln('hi')\n}\n\n// This should be merged\n// into one paragraph.\n// Note: this should be its own paragraph.\npub fn a4() {\n\tprintln('hi')\n}\n\n// This should be its own paragraph.\n// NOTE: this should also be it own paragraph\n// note: this should be its own paragraph.\npub fn a5() {\n\tprintln('hi')\n}\n\n// A comment\n// Fixme: this should be its own paragraph.\n// fixme: this should be its own paragraph.\n// FIXME: this should be its own paragraph.\npub fn a6() {\n\tprintln('hi')\n}\n\n// A comment\n// TODO: this should be its own paragraph.\n// todo: this should be its own paragraph.\n// Todo: this should be its own paragraph.\npub fn a7() {\n\tprintln('hi')\n}\n\n// A comment\n// TODO: this should be its own paragraph.\n// NOTE: this should be its own paragraph.\n// FIXME: this should be its own paragraph.\npub fn a8() {\n\tprintln('hi')\n}\n\n// Some info that should not be added as doc comment\n// A align      2 bit  Note: for now only 1 used!\n// U uppercase  1 bit  0 do nothing, 1 do to_upper()\n\n// normal comment\npub fn a9() {\n\tprintln('hi')\n}\n\n// foo does stuff\n// ```\n// this is a multiline codeblock.\n// second line\n// third line.\n// ```\npub fn foo() {}\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/newlines/main.comments.out",
    "content": "module main\n\nfn funky()\n    hello\n    \n    line after empty line, newline after comment line.\n    ```v\n    code\n    ```\n    \n    test\n    ====\n    - foo\n    - bar\n    # test\n    ########### deep test\n    #a shouldn't have a newline test\n    \n    | foo bar   |  yes   |\n    |-----------|--------|\n    |  working  |  yup   |\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/newlines/main.out",
    "content": "module main\n\nfn funky()\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/newlines/main.v",
    "content": "// hello\n//\n// line after empty line,\n// newline after comment line.\n// ```v\n// code\n// ```\n//\n// test\n// ====\n// - foo\n// - bar\n// # test\n// ########### deep test\n// #a shouldn't have a newline\n// test\n//\n// | foo bar   |  yes   |\n// |-----------|--------|\n// |  working  |  yup   |\npub fn funky() {\n\tprintln('hi')\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/output_formats/README.md",
    "content": "## Description\n\nThis is an example of a an .md file, used for adding more rich text\ndocumentation in a project or module.\n\nThis is a [link](https://vlang.io/) to the main V site.\n\nThis is a <b>bold text</b>.\n\nThis is a script `<script>console.log('hi from README.md');</script>` .\n\n## Examples\n\n### Functions that return different literals:\n\nExample of a function returning boolean:\n```v\nfn is_odd(x int) bool {\n\tif x % 2 == 0 {\n\t\treturn false\n\t}\n\treturn true\n}\n```\n\nAnother example of a function returning a string:\n```v\nfn answer() string {\n\treturn '42'\n}\n```\n\nThis example shows a function returning a string with interpolation:\n```v\nfn str_with_interplation() string {\n\treturn 'this string has ${42:6} interpolation in it.'\n}\n```\n\n### Processing command line args\n\n```v\nimport os\n\nfn main() {\n\tdump(os.args)\n\tdump(os.args.len)\n\tassert os.args.len > 0\n\n\t// Test escape characters like for `&` and `<`\n\tmut arr := [1, 2, 3]\n\tmut ref := &arr\n\tarr << 4\n\n\tch := chan bool{cap: 1}\n\tch <- true\n}\n```\n\n### A JWT example (test syntax highlighting)\n\n```v\nimport crypto.hmac\nimport crypto.sha256\nimport encoding.base64\nimport json\nimport time\n\nstruct JwtHeader {\n\talg string\n\ttyp string\n}\n\nstruct JwtPayload {\n\tsub  string\n\tname string\n\tiat  int\n}\n\nfn main() {\n\tsw := time.new_stopwatch()\n\tsecret := 'your-256-bit-secret'\n\ttoken := make_token(secret)\n\tok := auth_verify(secret, token)\n\tdt := sw.elapsed().microseconds()\n\tprintln('token: ${token}')\n\tprintln('auth_verify(secret, token): ${ok}')\n\tprintln('Elapsed time: ${dt} uS')\n}\n\nfn make_token(secret string) string {\n\theader := base64.url_encode(json.encode(JwtHeader{'HS256', 'JWT'}).bytes())\n\tpayload := base64.url_encode(json.encode(JwtPayload{'1234567890', 'John Doe', 1516239022}).bytes())\n\tsignature := base64.url_encode(hmac.new(secret.bytes(), '${header}.${payload}'.bytes(),\n\t\tsha256.sum, sha256.block_size))\n\tjwt := '${header}.${payload}.${signature}'\n\treturn jwt\n}\n\nfn auth_verify(secret string, token string) bool {\n\ttoken_split := token.split('.')\n\tsignature_mirror := hmac.new(secret.bytes(), '${token_split[0]}.${token_split[1]}'.bytes(),\n\t\tsha256.sum, sha256.block_size)\n\tsignature_from_token := base64.url_decode(token_split[2])\n\treturn hmac.equal(signature_from_token, signature_mirror)\n}\n```\n\n### Other language specifiers\n\n```cpp\n#include <iostream>\n#include <map>\n\nstd::map<std::string, int> my_map {\n\t{\"KEY_1\", 0},\n\t{\"KEY_2\", 10},\n};\n\nfor (const auto &[key, value] : my_map) {\n\tstd::cout << key << \": \" << value << \", \";\n}\nstd::cout << \"\\n\";\n```\n\n```v ignore\ndoc1 := toml.parse_text(<string content>) or { panic(err) }\ndoc2 := toml.parse_file(<file path>) or { panic(err) }\n```\n\n### Escape html in strings\n\n```v\nconst html = '<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <style>\n      body {\n        background: linear-gradient(to right, #274060, #1B2845);\n        color: GhostWhite;\n        font-family: sans-serif;\n        text-align: center;\n      }\n    </style>\n  </head>\n  <body>\n    <h1>Your App Content!</h1>\n    <button onclick=\"callV()\">Call V!</button>\n  </body>\n  <script>\n    async function callV() {\n      // Call a V function that takes an argument and returns a value.\n      const res = await window.my_v_func(\\'Hello from JS!\\');\n      console.log(res);\n    }\n  </script>\n</html>'\n```\n\n- Regular markdown list point 1\n- List point 2\n- List point 3\n\n1. Numbered markdown list point 1\n2. List point 2\n3. List point 3\n\nA code block without a specific language should be rendered verbatim:\n```\n.\n├── static/\n│   ├── css/\n│   │   └── main.css\n│   └── js/\n│       └── main.js\n└── main.v\n```\n\nThe s tags here in the code block, should be rendered verbatim, not interpreted as HTML ones:\n```\nh:m:s      // 5:02:33\nm:s.mi<s>  // 2:33.015\ns.mi<s>    // 33.015s\nmi.mc<ms>  // 15.007ms\nmc.ns<ns>  // 7.234us\nns<ns>     // 234ns\n```\n\nThe End.\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/output_formats/main.ansi",
    "content": "Description\nThis is an example of a an .md file, used for adding more rich text\ndocumentation in a project or module.\nThis is a link to the main V site.\nThis is a bold text.\nThis is a script <script>console.log('hi from README.md');</script> .\nExamples\nFunctions that return different literals:\nExample of a function returning boolean:\nfn is_odd(x int) bool {\n    if x % 2 == 0 {\n        return false\n    }\n    return true\n}\n\nAnother example of a function returning a string:\nfn answer() string {\n    return '42'\n}\n\nThis example shows a function returning a string with interpolation:\nfn str_with_interplation() string {\n    return 'this string has ${42:6} interpolation in it.'\n}\n\nProcessing command line args\nimport os\n\nfn main() {\n    dump(os.args)\n    dump(os.args.len)\n    assert os.args.len > 0\n\n    // Test escape characters like for `&` and `<`\n    mut arr := [1, 2, 3]\n    mut ref := &arr\n    arr << 4\n\n    ch := chan bool{cap: 1}\n    ch <- true\n}\n\nA JWT example (test syntax highlighting)\nimport crypto.hmac\nimport crypto.sha256\nimport encoding.base64\nimport json\nimport time\n\nstruct JwtHeader {\n    alg string\n    typ string\n}\n\nstruct JwtPayload {\n    sub  string\n    name string\n    iat  int\n}\n\nfn main() {\n    sw := time.new_stopwatch()\n    secret := 'your-256-bit-secret'\n    token := make_token(secret)\n    ok := auth_verify(secret, token)\n    dt := sw.elapsed().microseconds()\n    println('token: ${token}')\n    println('auth_verify(secret, token): ${ok}')\n    println('Elapsed time: ${dt} uS')\n}\n\nfn make_token(secret string) string {\n    header := base64.url_encode(json.encode(JwtHeader{'HS256', 'JWT'}).bytes())\n    payload := base64.url_encode(json.encode(JwtPayload{'1234567890', 'John Doe', 1516239022}).bytes())\n    signature := base64.url_encode(hmac.new(secret.bytes(), '${header}.${payload}'.bytes(),\n        sha256.sum, sha256.block_size))\n    jwt := '${header}.${payload}.${signature}'\n    return jwt\n}\n\nfn auth_verify(secret string, token string) bool {\n    token_split := token.split('.')\n    signature_mirror := hmac.new(secret.bytes(), '${token_split[0]}.${token_split[1]}'.bytes(),\n        sha256.sum, sha256.block_size)\n    signature_from_token := base64.url_decode(token_split[2])\n    return hmac.equal(signature_from_token, signature_mirror)\n}\n\nOther language specifiers\n#include <iostream>\n#include <map>\n\nstd::map<std::string, int> my_map {\n    {\"KEY_1\", 0},\n    {\"KEY_2\", 10},\n};\n\nfor (const auto &[key, value] : my_map) {\n    std::cout << key << \": \" << value << \", \";\n}\nstd::cout << \"\\n\";\n\ndoc1 := toml.parse_text(<string content>) or { panic(err) }\ndoc2 := toml.parse_file(<file path>) or { panic(err) }\n\nEscape html in strings\nconst html = '<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <style>\n      body {\n        background: linear-gradient(to right, #274060, #1B2845);\n        color: GhostWhite;\n        font-family: sans-serif;\n        text-align: center;\n      }\n    </style>\n  </head>\n  <body>\n    <h1>Your App Content!</h1>\n    <button onclick=\"callV()\">Call V!</button>\n  </body>\n  <script>\n    async function callV() {\n      // Call a V function that takes an argument and returns a value.\n      const res = await window.my_v_func(\\'Hello from JS!\\');\n      console.log(res);\n    }\n  </script>\n</html>'\n\nRegular markdown list point 1\nList point 2\nList point 3\n\nNumbered markdown list point 1\nList point 2\nList point 3\n\nA code block without a specific language should be rendered verbatim:\n.\n├── static/\n│   ├── css/\n│   │   └── main.css\n│   └── js/\n│       └── main.js\n└── main.v\n\nThe s tags here in the code block, should be rendered verbatim, not interpreted as HTML ones:\nh:m:s      // 5:02:33\nm:s.mi<s>  // 2:33.015\ns.mi<s>    // 33.015s\nmi.mc<ms>  // 15.007ms\nmc.ns<ns>  // 7.234us\nns<ns>     // 234ns\n\nThe End.\n\u001b[94mmodule\u001b[39m \u001b[32mmain\u001b[39m\n    ## Description\n    \n    This is an example of a an .md file, used for adding more rich text documentation in a project or module.\n    \n    This is a [link](https://vlang.io/) to the main V site.\n    \n    This is a <b>bold text</b>.\n    \n    This is a script `<script>console.log('hi from README.md');</script>` .\n    \n    ## Examples\n    \n    ### Functions that return different literals:\n    \n    Example of a function returning boolean:\n    ```v\n    fn is_odd(x int) bool {\n    \tif x % 2 == 0 {\n    \t\treturn false\n    \t}\n    \treturn true\n    }\n    ```\n    \n    Another example of a function returning a string:\n    ```v\n    fn answer() string {\n    \treturn '42'\n    }\n    ```\n    \n    This example shows a function returning a string with interpolation:\n    ```v\n    fn str_with_interplation() string {\n    \treturn 'this string has ${42:6} interpolation in it.'\n    }\n    ```\n    \n    ### Processing command line args\n    \n    ```v\n    import os\n    \n    fn main() {\n    \tdump(os.args)\n    \tdump(os.args.len)\n    \tassert os.args.len > 0\n    \n    \t// Test escape characters like for `&` and `<`\n    \tmut arr := [1, 2, 3]\n    \tmut ref := &arr\n    \tarr << 4\n    \n    \tch := chan bool{cap: 1}\n    \tch <- true\n    }\n    ```\n    \n    ### A JWT example (test syntax highlighting)\n    \n    ```v\n    import crypto.hmac\n    import crypto.sha256\n    import encoding.base64\n    import json\n    import time\n    \n    struct JwtHeader {\n    \talg string\n    \ttyp string\n    }\n    \n    struct JwtPayload {\n    \tsub  string\n    \tname string\n    \tiat  int\n    }\n    \n    fn main() {\n    \tsw := time.new_stopwatch()\n    \tsecret := 'your-256-bit-secret'\n    \ttoken := make_token(secret)\n    \tok := auth_verify(secret, token)\n    \tdt := sw.elapsed().microseconds()\n    \tprintln('token: ${token}')\n    \tprintln('auth_verify(secret, token): ${ok}')\n    \tprintln('Elapsed time: ${dt} uS')\n    }\n    \n    fn make_token(secret string) string {\n    \theader := base64.url_encode(json.encode(JwtHeader{'HS256', 'JWT'}).bytes())\n    \tpayload := base64.url_encode(json.encode(JwtPayload{'1234567890', 'John Doe', 1516239022}).bytes())\n    \tsignature := base64.url_encode(hmac.new(secret.bytes(), '${header}.${payload}'.bytes(),\n    \t\tsha256.sum, sha256.block_size))\n    \tjwt := '${header}.${payload}.${signature}'\n    \treturn jwt\n    }\n    \n    fn auth_verify(secret string, token string) bool {\n    \ttoken_split := token.split('.')\n    \tsignature_mirror := hmac.new(secret.bytes(), '${token_split[0]}.${token_split[1]}'.bytes(),\n    \t\tsha256.sum, sha256.block_size)\n    \tsignature_from_token := base64.url_decode(token_split[2])\n    \treturn hmac.equal(signature_from_token, signature_mirror)\n    }\n    ```\n    \n    ### Other language specifiers\n    \n    ```cpp\n    #include <iostream>\n    #include <map>\n    \n    std::map<std::string, int> my_map {\n    \t{\"KEY_1\", 0},\n    \t{\"KEY_2\", 10},\n    };\n    \n    for (const auto &[key, value] : my_map) {\n    \tstd::cout << key << \": \" << value << \", \";\n    }\n    std::cout << \"\\n\";\n    ```\n    \n    ```v ignore\n    doc1 := toml.parse_text(<string content>) or { panic(err) }\n    doc2 := toml.parse_file(<file path>) or { panic(err) }\n    ```\n    \n    ### Escape html in strings\n    \n    ```v\n    const html = '<!DOCTYPE html>\n    <html lang=\"en\">\n      <head>\n        <style>\n          body {\n            background: linear-gradient(to right, #274060, #1B2845);\n            color: GhostWhite;\n            font-family: sans-serif;\n            text-align: center;\n          }\n        </style>\n      </head>\n      <body>\n        <h1>Your App Content!</h1>\n        <button onclick=\"callV()\">Call V!</button>\n      </body>\n      <script>\n        async function callV() {\n          // Call a V function that takes an argument and returns a value.\n          const res = await window.my_v_func(\\'Hello from JS!\\');\n          console.log(res);\n        }\n      </script>\n    </html>'\n    ```\n    \n    - Regular markdown list point 1\n    - List point 2\n    - List point 3\n    \n    1. Numbered markdown list point 1\n    2. List point 2\n    3. List point 3\n    \n    A code block without a specific language should be rendered verbatim:\n    ```\n    .\n    ├── static/\n    │   ├── css/\n    │   │   └── main.css\n    │   └── js/\n    │       └── main.js\n    └── main.v\n    ```\n    \n    The s tags here in the code block, should be rendered verbatim, not interpreted as HTML ones:\n    ```\n    h:m:s      // 5:02:33\n    m:s.mi<s>  // 2:33.015\n    s.mi<s>    // 33.015s\n    mi.mc<ms>  // 15.007ms\n    mc.ns<ns>  // 7.234us\n    ns<ns>     // 234ns\n    ```\n    \n    The End.\n\n\u001b[94mconst\u001b[39m omega = \u001b[94m3\u001b[39m \u001b[90m// should be first\u001b[39m\n\u001b[94mconst\u001b[39m alpha = \u001b[94m5\u001b[39m \u001b[90m// should be in the middle\u001b[39m\n\u001b[94mconst\u001b[39m beta = \u001b[94m2\u001b[39m \u001b[90m// should be at the end\u001b[39m\n\u001b[94mfn\u001b[39m \u001b[36mabc\u001b[39m()\n    abc - should be last\n\u001b[94mfn\u001b[39m \u001b[36mdef\u001b[39m()\n    def - should be first\n\u001b[94mfn\u001b[39m \u001b[36mxyz\u001b[39m()\n    xyz - should be in the middle a small script <script>console.log('hello');</script> bold text <b>bold</b> end underlined text <u>underline</u> end a link [main v repo](https://github.com/vlang/v)\n\u001b[94mfn\u001b[39m \u001b[32mMyXMLDocument\u001b[39m.\u001b[36mabc\u001b[39m(text \u001b[32mstring\u001b[39m) ?(\u001b[32mstring\u001b[39m, \u001b[32mint\u001b[39m)\n    MyXMLDocument.abc does something too... I just do not know what.\n\u001b[94mfn\u001b[39m \u001b[32mMyXMLDocument\u001b[39m.\u001b[36mfrom_file\u001b[39m(path \u001b[32mstring\u001b[39m) !\u001b[32mMyXMLDocument\u001b[39m\n    MyXMLDocument.from_text processes the file path, and returns an error\n\u001b[94mfn\u001b[39m \u001b[32mMyXMLDocument\u001b[39m.\u001b[36mfrom_text\u001b[39m(text \u001b[32mstring\u001b[39m) ?\u001b[32mMyXMLDocument\u001b[39m\n    MyXMLDocument.from_text processes text and produces none\n\u001b[94mstruct\u001b[39m \u001b[32mMyXMLDocument\u001b[39m {\n\tpath \u001b[32mstring\u001b[39m\n}\n    MyXMLDocument is here just to test the different combinations of methods/output types\n\u001b[94mfn\u001b[39m (x &\u001b[32mMyXMLDocument\u001b[39m) \u001b[36minstance_from_file\u001b[39m(path \u001b[32mstring\u001b[39m) !\u001b[32mMyXMLDocument\u001b[39m\n    instance_from_file does stuff with path\n\u001b[94mfn\u001b[39m (x &\u001b[32mMyXMLDocument\u001b[39m) \u001b[36minstance_from_text\u001b[39m(text \u001b[32mstring\u001b[39m) ?\u001b[32mMyXMLDocument\u001b[39m\n    instance_from_text does stuff with text\n\u001b[94mfn\u001b[39m (x &\u001b[32mMyXMLDocument\u001b[39m) \u001b[36minstance_abc\u001b[39m(text \u001b[32mstring\u001b[39m) ?(\u001b[32mstring\u001b[39m, \u001b[32mint\u001b[39m)\n    instance_abc does stuff too\n\u001b[94mfn\u001b[39m (x &\u001b[32mMyXMLDocument\u001b[39m) \u001b[36minstance_void\u001b[39m()\n    instance_void does stuff too\n\u001b[94mfn\u001b[39m (x &\u001b[32mMyXMLDocument\u001b[39m) \u001b[36minstance_int\u001b[39m() \u001b[32mint\u001b[39m\n    instance_int does stuff too\n\u001b[94mfn\u001b[39m (x &\u001b[32mMyXMLDocument\u001b[39m) \u001b[36minstance_result\u001b[39m() !\n    instance_error does stuff too\n\u001b[94mfn\u001b[39m (x &\u001b[32mMyXMLDocument\u001b[39m) \u001b[36minstance_option\u001b[39m() ?\n    instance_option does stuff too\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/output_formats/main.html",
    "content": "<section id=\"readme_main\" class=\"doc-node\">\n\t\t\t<div class=\"title\"><h1> main <a href=\"#readme_main\">#</a></h1></div>\n<h2 id=\"description\">Description</h2>\n<p>This is an example of a an .md file, used for adding more rich text documentation in a project or module.</p>\n<p>This is a <a href=\"https://vlang.io/\">link</a> to the main V site.</p>\n<p>This is a <b>bold text</b>.</p>\n<p>This is a script <code>&lt;script&gt;console.log('hi from README.md');&lt;/script&gt;</code> .</p>\n<h2 id=\"examples\">Examples</h2>\n<h3 id=\"functions-that-return-different-literals\">Functions that return different literals:</h3>\n<p>Example of a function returning boolean:</p>\n<pre><code class=\"language-v\"><span class=\"token keyword\">fn</span> <span class=\"token function\">is_odd</span><span class=\"token punctuation\">(</span>x <span class=\"token builtin\">int</span><span class=\"token punctuation\">)</span> <span class=\"token builtin\">bool</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> x <span class=\"token operator\">%</span> <span class=\"token number\">2</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> <span class=\"token boolean\">false</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">return</span> <span class=\"token boolean\">true</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>Another example of a function returning a string:</p>\n<pre><code class=\"language-v\"><span class=\"token keyword\">fn</span> <span class=\"token function\">answer</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token builtin\">string</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token string\">'42'</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>This example shows a function returning a string with interpolation:</p>\n<pre><code class=\"language-v\"><span class=\"token keyword\">fn</span> <span class=\"token function\">str_with_interplation</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token builtin\">string</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span><span class=\"token string\"> &#39;this string has </span><span class=\"token string_interp\">$</span>{<span class=\"token number\">42</span><span class=\"token punctuation\">:</span><span class=\"token number\">6</span>}<span class=\"token string\"> interpolation in it.&#39;</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<h3 id=\"processing-command-line-args\">Processing command line args</h3>\n<pre><code class=\"language-v\"><span class=\"token keyword\">import</span> os\n\n<span class=\"token keyword\">fn</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">dump</span><span class=\"token punctuation\">(</span>os<span class=\"token punctuation\">.</span>args<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">dump</span><span class=\"token punctuation\">(</span>os<span class=\"token punctuation\">.</span>args<span class=\"token punctuation\">.</span>len<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">assert</span> os<span class=\"token punctuation\">.</span>args<span class=\"token punctuation\">.</span>len <span class=\"token operator\">&gt;</span> <span class=\"token number\">0</span>\n\n    <span class=\"token comment\">// Test escape characters like for `&amp;` and `&lt;`</span>\n    <span class=\"token keyword\">mut</span> arr <span class=\"token operator\">:=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">mut</span> ref <span class=\"token operator\">:=</span> <span class=\"token operator\">&amp;</span>arr\n    arr <span class=\"token operator\">&lt;&lt;</span> <span class=\"token number\">4</span>\n\n    ch <span class=\"token operator\">:=</span> <span class=\"token builtin\">chan</span> <span class=\"token builtin\">bool</span><span class=\"token punctuation\">{</span>cap<span class=\"token punctuation\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">}</span>\n    ch <span class=\"token operator\">&lt;-</span> <span class=\"token boolean\">true</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<h3 id=\"a-jwt-example-test-syntax-highlighting\">A JWT example (test syntax highlighting)</h3>\n<pre><code class=\"language-v\"><span class=\"token keyword\">import</span> crypto<span class=\"token punctuation\">.</span>hmac\n<span class=\"token keyword\">import</span> crypto<span class=\"token punctuation\">.</span>sha256\n<span class=\"token keyword\">import</span> encoding<span class=\"token punctuation\">.</span>base64\n<span class=\"token keyword\">import</span> json\n<span class=\"token keyword\">import</span> time\n\n<span class=\"token keyword\">struct</span> <span class=\"token symbol\">JwtHeader</span> <span class=\"token punctuation\">{</span>\n    alg <span class=\"token builtin\">string</span>\n    typ <span class=\"token builtin\">string</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">struct</span> <span class=\"token symbol\">JwtPayload</span> <span class=\"token punctuation\">{</span>\n    sub  <span class=\"token builtin\">string</span>\n    name <span class=\"token builtin\">string</span>\n    iat  <span class=\"token builtin\">int</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">fn</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    sw <span class=\"token operator\">:=</span> time<span class=\"token punctuation\">.</span><span class=\"token function\">new_stopwatch</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    secret <span class=\"token operator\">:=</span> <span class=\"token string\">'your-256-bit-secret'</span>\n    token <span class=\"token operator\">:=</span> <span class=\"token function\">make_token</span><span class=\"token punctuation\">(</span>secret<span class=\"token punctuation\">)</span>\n    ok <span class=\"token operator\">:=</span> <span class=\"token function\">auth_verify</span><span class=\"token punctuation\">(</span>secret<span class=\"token punctuation\">,</span> token<span class=\"token punctuation\">)</span>\n    dt <span class=\"token operator\">:=</span> sw<span class=\"token punctuation\">.</span><span class=\"token function\">elapsed</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">microseconds</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">println</span><span class=\"token punctuation\">(</span><span class=\"token string\">&#39;token: </span><span class=\"token string_interp\">$</span>{token}<span class=\"token string\">&#39;</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">println</span><span class=\"token punctuation\">(</span><span class=\"token string\">&#39;auth_verify(secret, token): </span><span class=\"token string_interp\">$</span>{ok}<span class=\"token string\">&#39;</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">println</span><span class=\"token punctuation\">(</span><span class=\"token string\">&#39;Elapsed time: </span><span class=\"token string_interp\">$</span>{dt}<span class=\"token string\"> uS&#39;</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">fn</span> <span class=\"token function\">make_token</span><span class=\"token punctuation\">(</span>secret <span class=\"token builtin\">string</span><span class=\"token punctuation\">)</span> <span class=\"token builtin\">string</span> <span class=\"token punctuation\">{</span>\n    header <span class=\"token operator\">:=</span> base64<span class=\"token punctuation\">.</span><span class=\"token function\">url_encode</span><span class=\"token punctuation\">(</span>json<span class=\"token punctuation\">.</span><span class=\"token function\">encode</span><span class=\"token punctuation\">(</span><span class=\"token symbol\">JwtHeader</span><span class=\"token punctuation\">{</span><span class=\"token string\">'HS256'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'JWT'</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">bytes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    payload <span class=\"token operator\">:=</span> base64<span class=\"token punctuation\">.</span><span class=\"token function\">url_encode</span><span class=\"token punctuation\">(</span>json<span class=\"token punctuation\">.</span><span class=\"token function\">encode</span><span class=\"token punctuation\">(</span><span class=\"token symbol\">JwtPayload</span><span class=\"token punctuation\">{</span><span class=\"token string\">'1234567890'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'John Doe'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1516239022</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">bytes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    signature <span class=\"token operator\">:=</span> base64<span class=\"token punctuation\">.</span><span class=\"token function\">url_encode</span><span class=\"token punctuation\">(</span>hmac<span class=\"token punctuation\">.</span><span class=\"token function\">new</span><span class=\"token punctuation\">(</span>secret<span class=\"token punctuation\">.</span><span class=\"token function\">bytes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span><span class=\"token string\">&#39;</span><span class=\"token string_interp\">$</span>{header}<span class=\"token string\">.</span><span class=\"token string_interp\">$</span>{payload}<span class=\"token string\">&#39;</span><span class=\"token punctuation\">.</span><span class=\"token function\">bytes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        sha256<span class=\"token punctuation\">.</span>sum<span class=\"token punctuation\">,</span> sha256<span class=\"token punctuation\">.</span>block_size<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    jwt <span class=\"token operator\">:=</span><span class=\"token string\">&#39;</span><span class=\"token string_interp\">$</span>{header}<span class=\"token string\">.</span><span class=\"token string_interp\">$</span>{payload}<span class=\"token string\">.</span><span class=\"token string_interp\">$</span>{signature}<span class=\"token string\">&#39;</span>\n    <span class=\"token keyword\">return</span> jwt\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">fn</span> <span class=\"token function\">auth_verify</span><span class=\"token punctuation\">(</span>secret <span class=\"token builtin\">string</span><span class=\"token punctuation\">,</span> token <span class=\"token builtin\">string</span><span class=\"token punctuation\">)</span> <span class=\"token builtin\">bool</span> <span class=\"token punctuation\">{</span>\n    token_split <span class=\"token operator\">:=</span> token<span class=\"token punctuation\">.</span><span class=\"token function\">split</span><span class=\"token punctuation\">(</span><span class=\"token string\">'.'</span><span class=\"token punctuation\">)</span>\n    signature_mirror <span class=\"token operator\">:=</span> hmac<span class=\"token punctuation\">.</span><span class=\"token function\">new</span><span class=\"token punctuation\">(</span>secret<span class=\"token punctuation\">.</span><span class=\"token function\">bytes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span><span class=\"token string\">&#39;</span><span class=\"token string_interp\">$</span>{token_split<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span>}<span class=\"token string\">.</span><span class=\"token string_interp\">$</span>{token_split<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span>}<span class=\"token string\">&#39;</span><span class=\"token punctuation\">.</span><span class=\"token function\">bytes</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        sha256<span class=\"token punctuation\">.</span>sum<span class=\"token punctuation\">,</span> sha256<span class=\"token punctuation\">.</span>block_size<span class=\"token punctuation\">)</span>\n    signature_from_token <span class=\"token operator\">:=</span> base64<span class=\"token punctuation\">.</span><span class=\"token function\">url_decode</span><span class=\"token punctuation\">(</span>token_split<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> hmac<span class=\"token punctuation\">.</span><span class=\"token function\">equal</span><span class=\"token punctuation\">(</span>signature_from_token<span class=\"token punctuation\">,</span> signature_mirror<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<h3 id=\"other-language-specifiers\">Other language specifiers</h3>\n<pre><code class=\"language-cpp\">##\nstd<span class=\"token punctuation\">:</span><span class=\"token punctuation\">:</span><span class=\"token builtin\">map</span><span class=\"token operator\">&lt;</span>std<span class=\"token punctuation\">:</span><span class=\"token punctuation\">:</span><span class=\"token builtin\">string</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">int</span><span class=\"token operator\">&gt;</span> <span class=\"token symbol\">my_map</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token punctuation\">{</span><span class=\"token string\">'KEY_1'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">{</span><span class=\"token string\">'KEY_2'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">10</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> auto <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">[</span>key<span class=\"token punctuation\">,</span> value<span class=\"token punctuation\">]</span> <span class=\"token punctuation\">:</span> my_map<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    std<span class=\"token punctuation\">:</span><span class=\"token punctuation\">:</span>cout <span class=\"token operator\">&lt;&lt;</span> key <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">': '</span> <span class=\"token operator\">&lt;&lt;</span> value <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">', '</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\nstd<span class=\"token punctuation\">:</span><span class=\"token punctuation\">:</span>cout <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">'\\n'</span><span class=\"token punctuation\">;</span></code></pre>\n<pre><code class=\"language-v\">doc1 <span class=\"token operator\">:=</span> toml<span class=\"token punctuation\">.</span><span class=\"token function\">parse_text</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&lt;</span><span class=\"token builtin\">string</span> content<span class=\"token operator\">&gt;</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">or</span> <span class=\"token punctuation\">{</span> <span class=\"token function\">panic</span><span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span>\ndoc2 <span class=\"token operator\">:=</span> toml<span class=\"token punctuation\">.</span><span class=\"token function\">parse_file</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&lt;</span>file path<span class=\"token operator\">&gt;</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">or</span> <span class=\"token punctuation\">{</span> <span class=\"token function\">panic</span><span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span></code></pre>\n<h3 id=\"escape-html-in-strings\">Escape html in strings</h3>\n<pre><code class=\"language-v\"><span class=\"token keyword\">const</span> html <span class=\"token operator\">=</span> <span class=\"token string\">'&lt;!DOCTYPE html&gt;\n&lt;html lang=&#34;en&#34;&gt;\n  &lt;head&gt;\n    &lt;style&gt;\n      body {\n        background: linear-gradient(to right, #274060, #1B2845);\n        color: GhostWhite;\n        font-family: sans-serif;\n        text-align: center;\n      }\n    &lt;/style&gt;\n  &lt;/head&gt;\n  &lt;body&gt;\n    &lt;h1&gt;Your App Content!&lt;/h1&gt;\n    &lt;button onclick=&#34;callV()&#34;&gt;Call V!&lt;/button&gt;\n  &lt;/body&gt;\n  &lt;script&gt;\n    async function callV() {\n      // Call a V function that takes an argument and returns a value.\n      const res = await window.my_v_func(\\&#39;Hello from JS!\\&#39;);\n      console.log(res);\n    }\n  &lt;/script&gt;\n&lt;/html&gt;'</span></code></pre>\n<ul>\n<li>Regular markdown list point 1</li>\n<li>List point 2</li>\n<li>List point 3</li></ul>\n<ol>\n<li>Numbered markdown list point 1</li>\n<li>List point 2</li>\n<li>List point 3</li></ol>\n<p>A code block without a specific language should be rendered verbatim:</p>\n<pre><code>.\n├── static/\n│   ├── css/\n│   │   └── main.css\n│   └── js/\n│       └── main.js\n└── main.v\n</code></pre>\n<p>The s tags here in the code block, should be rendered verbatim, not interpreted as HTML ones:</p>\n<pre><code>h:m:s      // 5:02:33\nm:s.mi&lt;s&gt;  // 2:33.015\ns.mi&lt;s&gt;    // 33.015s\nmi.mc&lt;ms&gt;  // 15.007ms\nmc.ns&lt;ns&gt;  // 7.234us\nns&lt;ns&gt;     // 234ns\n</code></pre>\n<p>The End.</p>\n\n</section>\n\n\t\t<section id=\"Constants\" class=\"doc-node const\">\n\t\t\t<div class=\"title\"><h2>Constants <a href=\"#Constants\">#</a></h2></div>\n\n\n</section>\n\n\t\t<section id=\"\" class=\"doc-node const\">\n<pre class=\"signature\">\n<code><span class=\"token keyword\">const</span> omega <span class=\"token operator\">=</span> <span class=\"token number\">3</span> <span class=\"token comment\">// should be first</span></code></pre>\n\n\n</section>\n\n\t\t<section id=\"\" class=\"doc-node const\">\n<pre class=\"signature\">\n<code><span class=\"token keyword\">const</span> alpha <span class=\"token operator\">=</span> <span class=\"token number\">5</span> <span class=\"token comment\">// should be in the middle</span></code></pre>\n\n\n</section>\n\n\t\t<section id=\"\" class=\"doc-node const\">\n<pre class=\"signature\">\n<code><span class=\"token keyword\">const</span> beta <span class=\"token operator\">=</span> <span class=\"token number\">2</span> <span class=\"token comment\">// should be at the end</span></code></pre>\n\n\n</section>\n\n\t\t<section id=\"abc\" class=\"doc-node\">\n\t\t\t<div class=\"title\"><h2>fn abc <a href=\"#abc\">#</a></h2></div>\n<pre class=\"signature\">\n<code><span class=\"token keyword\">fn</span> <span class=\"token function\">abc</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre>\n<p>abc - should be last</p>\n\n</section>\n\n\t\t<section id=\"def\" class=\"doc-node\">\n\t\t\t<div class=\"title\"><h2>fn def <a href=\"#def\">#</a></h2></div>\n<pre class=\"signature\">\n<code><span class=\"token keyword\">fn</span> <span class=\"token function\">def</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre>\n<p>def - should be first</p>\n\n</section>\n\n\t\t<section id=\"xyz\" class=\"doc-node\">\n\t\t\t<div class=\"title\"><h2>fn xyz <a href=\"#xyz\">#</a></h2></div>\n<pre class=\"signature\">\n<code><span class=\"token keyword\">fn</span> <span class=\"token function\">xyz</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre>\n<p>xyz - should be in the middle a small script <script>console.log('hello');</script> bold text <b>bold</b> end underlined text <u>underline</u> end a link <a href=\"https://github.com/vlang/v\">main v repo</a></p>\n\n</section>\n\n\t\t<section id=\"MyXMLDocument.abc\" class=\"doc-node\">\n\t\t\t<div class=\"title\"><h2>fn MyXMLDocument.abc <a href=\"#MyXMLDocument.abc\">#</a></h2></div>\n<pre class=\"signature\">\n<code><span class=\"token keyword\">fn</span> MyXMLDocument<span class=\"token punctuation\">.</span><span class=\"token function\">abc</span><span class=\"token punctuation\">(</span>text <span class=\"token builtin\">string</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">string</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">)</span></code></pre>\n<p>MyXMLDocument.abc does something too... I just do not know what.</p>\n\n</section>\n\n\t\t<section id=\"MyXMLDocument.from_file\" class=\"doc-node\">\n\t\t\t<div class=\"title\"><h2>fn MyXMLDocument.from_file <a href=\"#MyXMLDocument.from_file\">#</a></h2></div>\n<pre class=\"signature\">\n<code><span class=\"token keyword\">fn</span> MyXMLDocument<span class=\"token punctuation\">.</span><span class=\"token function\">from_file</span><span class=\"token punctuation\">(</span>path <span class=\"token builtin\">string</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">!</span>MyXMLDocument</code></pre>\n<p>MyXMLDocument.from_text processes the file path, and returns an error</p>\n\n</section>\n\n\t\t<section id=\"MyXMLDocument.from_text\" class=\"doc-node\">\n\t\t\t<div class=\"title\"><h2>fn MyXMLDocument.from_text <a href=\"#MyXMLDocument.from_text\">#</a></h2></div>\n<pre class=\"signature\">\n<code><span class=\"token keyword\">fn</span> MyXMLDocument<span class=\"token punctuation\">.</span><span class=\"token function\">from_text</span><span class=\"token punctuation\">(</span>text <span class=\"token builtin\">string</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span>MyXMLDocument</code></pre>\n<p>MyXMLDocument.from_text processes text and produces none</p>\n\n</section>\n\n\t\t<section id=\"MyXMLDocument\" class=\"doc-node\">\n\t\t\t<div class=\"title\"><h2>struct MyXMLDocument <a href=\"#MyXMLDocument\">#</a></h2></div>\n<pre class=\"signature\">\n<code><span class=\"token keyword\">struct</span> <span class=\"token symbol\">MyXMLDocument</span> <span class=\"token punctuation\">{</span>\n\tpath <span class=\"token builtin\">string</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>MyXMLDocument is here just to test the different combinations of methods/output types</p>\n\n</section>\n\n\t\t<section id=\"MyXMLDocument.instance_from_file\" class=\"doc-node\">\n\t\t\t<div class=\"title\"><h2>fn (MyXMLDocument) instance_from_file <a href=\"#MyXMLDocument.instance_from_file\">#</a></h2></div>\n<pre class=\"signature\">\n<code><span class=\"token keyword\">fn</span> <span class=\"token punctuation\">(</span>x <span class=\"token operator\">&amp;</span>MyXMLDocument<span class=\"token punctuation\">)</span> <span class=\"token function\">instance_from_file</span><span class=\"token punctuation\">(</span>path <span class=\"token builtin\">string</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">!</span>MyXMLDocument</code></pre>\n<p>instance_from_file does stuff with path</p>\n\n</section>\n\n\t\t<section id=\"MyXMLDocument.instance_from_text\" class=\"doc-node\">\n\t\t\t<div class=\"title\"><h2>fn (MyXMLDocument) instance_from_text <a href=\"#MyXMLDocument.instance_from_text\">#</a></h2></div>\n<pre class=\"signature\">\n<code><span class=\"token keyword\">fn</span> <span class=\"token punctuation\">(</span>x <span class=\"token operator\">&amp;</span>MyXMLDocument<span class=\"token punctuation\">)</span> <span class=\"token function\">instance_from_text</span><span class=\"token punctuation\">(</span>text <span class=\"token builtin\">string</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span>MyXMLDocument</code></pre>\n<p>instance_from_text does stuff with text</p>\n\n</section>\n\n\t\t<section id=\"MyXMLDocument.instance_abc\" class=\"doc-node\">\n\t\t\t<div class=\"title\"><h2>fn (MyXMLDocument) instance_abc <a href=\"#MyXMLDocument.instance_abc\">#</a></h2></div>\n<pre class=\"signature\">\n<code><span class=\"token keyword\">fn</span> <span class=\"token punctuation\">(</span>x <span class=\"token operator\">&amp;</span>MyXMLDocument<span class=\"token punctuation\">)</span> <span class=\"token function\">instance_abc</span><span class=\"token punctuation\">(</span>text <span class=\"token builtin\">string</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">string</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">)</span></code></pre>\n<p>instance_abc does stuff too</p>\n\n</section>\n\n\t\t<section id=\"MyXMLDocument.instance_void\" class=\"doc-node\">\n\t\t\t<div class=\"title\"><h2>fn (MyXMLDocument) instance_void <a href=\"#MyXMLDocument.instance_void\">#</a></h2></div>\n<pre class=\"signature\">\n<code><span class=\"token keyword\">fn</span> <span class=\"token punctuation\">(</span>x <span class=\"token operator\">&amp;</span>MyXMLDocument<span class=\"token punctuation\">)</span> <span class=\"token function\">instance_void</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre>\n<p>instance_void does stuff too</p>\n\n</section>\n\n\t\t<section id=\"MyXMLDocument.instance_int\" class=\"doc-node\">\n\t\t\t<div class=\"title\"><h2>fn (MyXMLDocument) instance_int <a href=\"#MyXMLDocument.instance_int\">#</a></h2></div>\n<pre class=\"signature\">\n<code><span class=\"token keyword\">fn</span> <span class=\"token punctuation\">(</span>x <span class=\"token operator\">&amp;</span>MyXMLDocument<span class=\"token punctuation\">)</span> <span class=\"token function\">instance_int</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token builtin\">int</span></code></pre>\n<p>instance_int does stuff too</p>\n\n</section>\n\n\t\t<section id=\"MyXMLDocument.instance_result\" class=\"doc-node\">\n\t\t\t<div class=\"title\"><h2>fn (MyXMLDocument) instance_result <a href=\"#MyXMLDocument.instance_result\">#</a></h2></div>\n<pre class=\"signature\">\n<code><span class=\"token keyword\">fn</span> <span class=\"token punctuation\">(</span>x <span class=\"token operator\">&amp;</span>MyXMLDocument<span class=\"token punctuation\">)</span> <span class=\"token function\">instance_result</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">!</span></code></pre>\n<p>instance_error does stuff too</p>\n\n</section>\n\n\t\t<section id=\"MyXMLDocument.instance_option\" class=\"doc-node\">\n\t\t\t<div class=\"title\"><h2>fn (MyXMLDocument) instance_option <a href=\"#MyXMLDocument.instance_option\">#</a></h2></div>\n<pre class=\"signature\">\n<code><span class=\"token keyword\">fn</span> <span class=\"token punctuation\">(</span>x <span class=\"token operator\">&amp;</span>MyXMLDocument<span class=\"token punctuation\">)</span> <span class=\"token function\">instance_option</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span></code></pre>\n<p>instance_option does stuff too</p>\n\n</section>\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/output_formats/main.md",
    "content": "# module main\n\n\n## Contents\n- [Constants](#Constants)\n- [abc](#abc)\n- [def](#def)\n- [xyz](#xyz)\n- [MyXMLDocument.abc](#MyXMLDocument.abc)\n- [MyXMLDocument.from_file](#MyXMLDocument.from_file)\n- [MyXMLDocument.from_text](#MyXMLDocument.from_text)\n- [MyXMLDocument](#MyXMLDocument)\n  - [instance_from_file](#instance_from_file)\n  - [instance_from_text](#instance_from_text)\n  - [instance_abc](#instance_abc)\n  - [instance_void](#instance_void)\n  - [instance_int](#instance_int)\n  - [instance_result](#instance_result)\n  - [instance_option](#instance_option)\n\n## Constants\n```v\nconst omega = 3 // should be first\n```\n\n[[Return to contents]](#Contents)\n\n```v\nconst alpha = 5 // should be in the middle\n```\n\n[[Return to contents]](#Contents)\n\n```v\nconst beta = 2 // should be at the end\n```\n\n[[Return to contents]](#Contents)\n\n## abc\n```v\nfn abc()\n```\n\nabc - should be last\n\n[[Return to contents]](#Contents)\n\n## def\n```v\nfn def()\n```\n\ndef - should be first\n\n[[Return to contents]](#Contents)\n\n## xyz\n```v\nfn xyz()\n```\n\nxyz - should be in the middle a small script <script>console.log('hello');</script> bold text <b>bold</b> end underlined text <u>underline</u> end a link [main v repo](https://github.com/vlang/v)\n\n[[Return to contents]](#Contents)\n\n## MyXMLDocument.abc\n```v\nfn MyXMLDocument.abc(text string) ?(string, int)\n```\n\nMyXMLDocument.abc does something too... I just do not know what.\n\n[[Return to contents]](#Contents)\n\n## MyXMLDocument.from_file\n```v\nfn MyXMLDocument.from_file(path string) !MyXMLDocument\n```\n\nMyXMLDocument.from_text processes the file path, and returns an error\n\n[[Return to contents]](#Contents)\n\n## MyXMLDocument.from_text\n```v\nfn MyXMLDocument.from_text(text string) ?MyXMLDocument\n```\n\nMyXMLDocument.from_text processes text and produces none\n\n[[Return to contents]](#Contents)\n\n## MyXMLDocument\n```v\nstruct MyXMLDocument {\n\tpath string\n}\n```\n\nMyXMLDocument is here just to test the different combinations of methods/output types\n\n[[Return to contents]](#Contents)\n\n## instance_from_file\n```v\nfn (x &MyXMLDocument) instance_from_file(path string) !MyXMLDocument\n```\n\ninstance_from_file does stuff with path\n\n[[Return to contents]](#Contents)\n\n## instance_from_text\n```v\nfn (x &MyXMLDocument) instance_from_text(text string) ?MyXMLDocument\n```\n\ninstance_from_text does stuff with text\n\n[[Return to contents]](#Contents)\n\n## instance_abc\n```v\nfn (x &MyXMLDocument) instance_abc(text string) ?(string, int)\n```\n\ninstance_abc does stuff too\n\n[[Return to contents]](#Contents)\n\n## instance_void\n```v\nfn (x &MyXMLDocument) instance_void()\n```\n\ninstance_void does stuff too\n\n[[Return to contents]](#Contents)\n\n## instance_int\n```v\nfn (x &MyXMLDocument) instance_int() int\n```\n\ninstance_int does stuff too\n\n[[Return to contents]](#Contents)\n\n## instance_result\n```v\nfn (x &MyXMLDocument) instance_result() !\n```\n\ninstance_error does stuff too\n\n[[Return to contents]](#Contents)\n\n## instance_option\n```v\nfn (x &MyXMLDocument) instance_option() ?\n```\n\ninstance_option does stuff too\n\n[[Return to contents]](#Contents)\n\n#### Powered by vdoc.\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/output_formats/main.text",
    "content": "module main\n    ## Description\n    \n    This is an example of a an .md file, used for adding more rich text documentation in a project or module.\n    \n    This is a [link](https://vlang.io/) to the main V site.\n    \n    This is a <b>bold text</b>.\n    \n    This is a script `<script>console.log('hi from README.md');</script>` .\n    \n    ## Examples\n    \n    ### Functions that return different literals:\n    \n    Example of a function returning boolean:\n    ```v\n    fn is_odd(x int) bool {\n    \tif x % 2 == 0 {\n    \t\treturn false\n    \t}\n    \treturn true\n    }\n    ```\n    \n    Another example of a function returning a string:\n    ```v\n    fn answer() string {\n    \treturn '42'\n    }\n    ```\n    \n    This example shows a function returning a string with interpolation:\n    ```v\n    fn str_with_interplation() string {\n    \treturn 'this string has ${42:6} interpolation in it.'\n    }\n    ```\n    \n    ### Processing command line args\n    \n    ```v\n    import os\n    \n    fn main() {\n    \tdump(os.args)\n    \tdump(os.args.len)\n    \tassert os.args.len > 0\n    \n    \t// Test escape characters like for `&` and `<`\n    \tmut arr := [1, 2, 3]\n    \tmut ref := &arr\n    \tarr << 4\n    \n    \tch := chan bool{cap: 1}\n    \tch <- true\n    }\n    ```\n    \n    ### A JWT example (test syntax highlighting)\n    \n    ```v\n    import crypto.hmac\n    import crypto.sha256\n    import encoding.base64\n    import json\n    import time\n    \n    struct JwtHeader {\n    \talg string\n    \ttyp string\n    }\n    \n    struct JwtPayload {\n    \tsub  string\n    \tname string\n    \tiat  int\n    }\n    \n    fn main() {\n    \tsw := time.new_stopwatch()\n    \tsecret := 'your-256-bit-secret'\n    \ttoken := make_token(secret)\n    \tok := auth_verify(secret, token)\n    \tdt := sw.elapsed().microseconds()\n    \tprintln('token: ${token}')\n    \tprintln('auth_verify(secret, token): ${ok}')\n    \tprintln('Elapsed time: ${dt} uS')\n    }\n    \n    fn make_token(secret string) string {\n    \theader := base64.url_encode(json.encode(JwtHeader{'HS256', 'JWT'}).bytes())\n    \tpayload := base64.url_encode(json.encode(JwtPayload{'1234567890', 'John Doe', 1516239022}).bytes())\n    \tsignature := base64.url_encode(hmac.new(secret.bytes(), '${header}.${payload}'.bytes(),\n    \t\tsha256.sum, sha256.block_size))\n    \tjwt := '${header}.${payload}.${signature}'\n    \treturn jwt\n    }\n    \n    fn auth_verify(secret string, token string) bool {\n    \ttoken_split := token.split('.')\n    \tsignature_mirror := hmac.new(secret.bytes(), '${token_split[0]}.${token_split[1]}'.bytes(),\n    \t\tsha256.sum, sha256.block_size)\n    \tsignature_from_token := base64.url_decode(token_split[2])\n    \treturn hmac.equal(signature_from_token, signature_mirror)\n    }\n    ```\n    \n    ### Other language specifiers\n    \n    ```cpp\n    #include <iostream>\n    #include <map>\n    \n    std::map<std::string, int> my_map {\n    \t{\"KEY_1\", 0},\n    \t{\"KEY_2\", 10},\n    };\n    \n    for (const auto &[key, value] : my_map) {\n    \tstd::cout << key << \": \" << value << \", \";\n    }\n    std::cout << \"\\n\";\n    ```\n    \n    ```v ignore\n    doc1 := toml.parse_text(<string content>) or { panic(err) }\n    doc2 := toml.parse_file(<file path>) or { panic(err) }\n    ```\n    \n    ### Escape html in strings\n    \n    ```v\n    const html = '<!DOCTYPE html>\n    <html lang=\"en\">\n      <head>\n        <style>\n          body {\n            background: linear-gradient(to right, #274060, #1B2845);\n            color: GhostWhite;\n            font-family: sans-serif;\n            text-align: center;\n          }\n        </style>\n      </head>\n      <body>\n        <h1>Your App Content!</h1>\n        <button onclick=\"callV()\">Call V!</button>\n      </body>\n      <script>\n        async function callV() {\n          // Call a V function that takes an argument and returns a value.\n          const res = await window.my_v_func(\\'Hello from JS!\\');\n          console.log(res);\n        }\n      </script>\n    </html>'\n    ```\n    \n    - Regular markdown list point 1\n    - List point 2\n    - List point 3\n    \n    1. Numbered markdown list point 1\n    2. List point 2\n    3. List point 3\n    \n    A code block without a specific language should be rendered verbatim:\n    ```\n    .\n    ├── static/\n    │   ├── css/\n    │   │   └── main.css\n    │   └── js/\n    │       └── main.js\n    └── main.v\n    ```\n    \n    The s tags here in the code block, should be rendered verbatim, not interpreted as HTML ones:\n    ```\n    h:m:s      // 5:02:33\n    m:s.mi<s>  // 2:33.015\n    s.mi<s>    // 33.015s\n    mi.mc<ms>  // 15.007ms\n    mc.ns<ns>  // 7.234us\n    ns<ns>     // 234ns\n    ```\n    \n    The End.\n\nconst omega = 3 // should be first\nconst alpha = 5 // should be in the middle\nconst beta = 2 // should be at the end\nfn abc()\n    abc - should be last\nfn def()\n    def - should be first\nfn xyz()\n    xyz - should be in the middle a small script <script>console.log('hello');</script> bold text <b>bold</b> end underlined text <u>underline</u> end a link [main v repo](https://github.com/vlang/v)\nfn MyXMLDocument.abc(text string) ?(string, int)\n    MyXMLDocument.abc does something too... I just do not know what.\nfn MyXMLDocument.from_file(path string) !MyXMLDocument\n    MyXMLDocument.from_text processes the file path, and returns an error\nfn MyXMLDocument.from_text(text string) ?MyXMLDocument\n    MyXMLDocument.from_text processes text and produces none\nstruct MyXMLDocument {\n\tpath string\n}\n    MyXMLDocument is here just to test the different combinations of methods/output types\nfn (x &MyXMLDocument) instance_from_file(path string) !MyXMLDocument\n    instance_from_file does stuff with path\nfn (x &MyXMLDocument) instance_from_text(text string) ?MyXMLDocument\n    instance_from_text does stuff with text\nfn (x &MyXMLDocument) instance_abc(text string) ?(string, int)\n    instance_abc does stuff too\nfn (x &MyXMLDocument) instance_void()\n    instance_void does stuff too\nfn (x &MyXMLDocument) instance_int() int\n    instance_int does stuff too\nfn (x &MyXMLDocument) instance_result() !\n    instance_error does stuff too\nfn (x &MyXMLDocument) instance_option() ?\n    instance_option does stuff too\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/output_formats/main.v",
    "content": "pub const omega = 3 // should be first\n\npub const alpha = 5 // should be in the middle\n\npub const beta = 2 // should be at the end\n\n// def - should be first\npub fn def() {\n\tprintln(1)\n}\n\n// xyz - should be in the middle\n// a small script <script>console.log('hello');</script>\n// bold text <b>bold</b> end\n// underlined text <u>underline</u> end\n// a link [main v repo](https://github.com/vlang/v)\npub fn xyz() {\n\tprintln(2)\n}\n\n// abc - should be last\npub fn abc() {\n\tprintln(3)\n}\n\n// MyXMLDocument is here just to test the different combinations of methods/output types\npub struct MyXMLDocument {\n\tpath string\n}\n\n// MyXMLDocument.from_text processes the file path, and returns an error\npub fn MyXMLDocument.from_file(path string) !MyXMLDocument {\n\treturn error('TODO')\n}\n\n// MyXMLDocument.from_text processes text and produces none\npub fn MyXMLDocument.from_text(text string) ?MyXMLDocument {\n\treturn none\n}\n\n// MyXMLDocument.abc does something too... I just do not know what.\npub fn MyXMLDocument.abc(text string) ?(string, int) {\n\treturn 'xyz', 123\n}\n\n// instance_from_file does stuff with path\npub fn (x &MyXMLDocument) instance_from_file(path string) !MyXMLDocument {\n\treturn error('TODO')\n}\n\n// instance_from_text does stuff with text\npub fn (x &MyXMLDocument) instance_from_text(text string) ?MyXMLDocument {\n\treturn none\n}\n\n// instance_abc does stuff too\npub fn (x &MyXMLDocument) instance_abc(text string) ?(string, int) {\n\treturn 'xyz', 123\n}\n\n// instance_void does stuff too\npub fn (x &MyXMLDocument) instance_void() {\n\treturn 123\n}\n\n// instance_int does stuff too\npub fn (x &MyXMLDocument) instance_int() int {\n\treturn 123\n}\n\n// instance_error does stuff too\npub fn (x &MyXMLDocument) instance_result() ! {\n\treturn 123\n}\n\n// instance_option does stuff too\npub fn (x &MyXMLDocument) instance_option() ? {\n\treturn 123\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/readme_in_project_root/README.md",
    "content": "hello from readme\n\nExample:\n```v\nfn is_odd(x int) bool {\n\tif x % 2 == 0 {\n\t\treturn false\n\t}\n\treturn true\n}\n```\n\nAnother example:\n```v\nfn answer() string {\n\treturn '42'\n}\n```\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/readme_in_project_root/src/main.comments.out",
    "content": "module foo\n\nfn bar()\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/readme_in_project_root/src/main.readme.comments.out",
    "content": "hello from readme\nExample:\nfn is_odd(x int) bool {\n    if x % 2 == 0 {\n        return false\n    }\n    return true\n}\n\nAnother example:\nfn answer() string {\n    return '42'\n}\nmodule foo\n\nfn bar()\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/readme_in_project_root/src/main.v",
    "content": "module foo\n\npub fn bar() {}\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/readme_in_project_root/v.mod",
    "content": ""
  },
  {
    "path": "cmd/tools/vdoc/testdata/run_examples_bad/.v.mod.stop",
    "content": ""
  },
  {
    "path": "cmd/tools/vdoc/testdata/run_examples_bad/main.comments.out",
    "content": "module main\n\nfn abc()\n    abc just prints 'xyz'. The important thing however is the next line, that does an assertion, that should FAIL to be executed with `v doc -unsafe-run-examples main.v`, and should compile with -check-examples:\n    Example: assert 5 * 5 == 77\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/run_examples_bad/main.out",
    "content": "module main\n\nfn abc()\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/run_examples_bad/main.v",
    "content": "// abc just prints 'xyz'. The important thing however is the next line, that does an assertion,\n// that should FAIL to be executed with `v doc -unsafe-run-examples main.v`, and should compile with -check-examples:\n// Example: assert 5 * 5 == 77\npub fn abc() {\n\tprintln('xyz')\n}\n\nfn main() {\n\tabc()\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/run_examples_good/.v.mod.stop",
    "content": ""
  },
  {
    "path": "cmd/tools/vdoc/testdata/run_examples_good/main.comments.out",
    "content": "module main\n\nfn abc()\n    abc just prints 'xyz'. The important thing however is the next line, that does an assertion, that should be executed with `v doc -run-examples good.v`, and should succeed:\n    Example: assert 5 * 5 == 25\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/run_examples_good/main.out",
    "content": "module main\n\nfn abc()\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/run_examples_good/main.v",
    "content": "// abc just prints 'xyz'. The important thing however is the next line, that does an assertion,\n// that should be executed with `v doc -run-examples good.v`, and should succeed:\n// Example: assert 5 * 5 == 25\npub fn abc() {\n\tprintln('xyz')\n}\n\nfn main() {\n\tabc()\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/unsorted/main.out",
    "content": "module main\n\nconst omega = 3 // should be first\nconst alpha = 5 // should be in the middle\nconst beta = 2 // should be at the end\nfn abc()\nfn def()\nfn xyz()\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/unsorted/main.unsorted.out",
    "content": "module main\n\nconst omega = 3 // should be first\nconst alpha = 5 // should be in the middle\nconst beta = 2 // should be at the end\nfn def()\n    def - should be first\nfn xyz()\n    xyz - should be in the middle\nfn abc()\n    abc - should be last\n"
  },
  {
    "path": "cmd/tools/vdoc/testdata/unsorted/main.v",
    "content": "pub const omega = 3 // should be first\n\npub const alpha = 5 // should be in the middle\n\npub const beta = 2 // should be at the end\n\n// def - should be first\npub fn def() {\n\tprintln(1)\n}\n\n// xyz - should be in the middle\npub fn xyz() {\n\tprintln(2)\n}\n\n// abc - should be last\npub fn abc() {\n\tprintln(3)\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/theme/.prettierrc",
    "content": "{\n\t\"useTabs\": true,\n\t\"printWidth\": 100,\n\t\"singleQuote\": true\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/theme/dark-mode.js",
    "content": "(function () {\n\tif (localStorage.getItem('dark-mode') === 'true') {\n\t\tdocument.querySelector('html').classList.add('dark');\n\t}\n})();\n"
  },
  {
    "path": "cmd/tools/vdoc/theme/doc.css",
    "content": ":root {\n\t--background-color: #fff;\n\t--link-color: #2779bd;\n\t--text-color: #000;\n\t--ref-symbol-color: #dae1e7;\n\t--ref-symbol-hover-color: #b8c2cc;\n\t--title-bottom-line-color: #f1f5f8;\n\t--footer-top-line-color: #f1f5f8;\n\t--footer-text-color: #616161;\n\t--code-signature-border-color: #a0aec0;\n\t--menu-background-color: #4b6c88;\n\t--menu-text-color: #fff;\n\t--menu-indent-line-color: #3b3b3b66;\n\t--menu-indent-line-active-color: #00000066;\n\t--menu-scrollbar-color: #a0aec0;\n\t--menu-toggle-icon-color: #fff;\n\t--menu-toggle-icon-hover-color: #00000044;\n\t--menu-search-background-color: #00000044;\n\t--menu-search-font-color: #fff;\n\t--menu-search-result-background-hover-color: #00000021;\n\t--menu-search-separator-color: #00000044;\n\t--menu-search-title-text-color: #d5efff;\n\t--menu-search-badge-background-color: #00000044;\n\t--menu-search-badge-background-hover-color: #0000004d;\n\t--toc-text-color: #2779bd;\n\t--toc-indicator-color: #4299e1;\n\t--code-default-text-color: #2c3e64;\n\t--code-background-color: #edf2f7;\n\t--code-keyword-text-color: #2b6cb0;\n\t--code-builtin-text-color: #219321;\n\t--code-function-text-color: #288341;\n\t--code-comment-text-color: #93a1a1;\n\t--code-punctuation-text-color: #696969;\n\t--code-symbol-text-color: #702459;\n\t--code-operator-text-color: #864f29;\n\t--attribute-deprecated-background-color: #f59f0b48;\n\t--attribute-deprecated-text-color: #92400e;\n\t--attribute-text-color: #000000cf;\n\t--table-header-line-color: #2c3e64;\n\t--table-background-color: #edf2f7;\n}\nhtml.dark {\n\t--background-color: #1a202c;\n\t--text-color: #fff;\n\t--link-color: #90cdf4;\n\t--ref-symbol-color: #2d3748;\n\t--ref-symbol-hover-color: #4a5568;\n\t--title-bottom-line-color: #2d3748;\n\t--footer-top-line-color: #2d3748;\n\t--footer-text-color: #bbd3e1;\n\t--code-signature-border-color: #4a5568;\n\t--menu-background-color: #2d3748;\n\t--menu-text-color: #fff;\n\t--menu-indent-line-color: #4a5568;\n\t--menu-indent-line-active-color: #90cdf4; /*#4a5568*/\n\t--menu-scrollbar-color: #4a5568;\n\t--menu-toggle-icon-color: #fff;\n\t--menu-search-background-color: #4a5568;\n\t--menu-search-font-color: #fff;\n\t--menu-search-separator-color: #4a5568;\n\t--menu-search-title-text-color: #90cdf4;\n\t--menu-search-badge-background-color: #4a5568;\n\t--menu-search-badge-background-hover-color: #4a5568;\n\t--toc-text-color: #90cdf4;\n\t--toc-indicator-color: #4299e1;\n\t--code-default-text-color: #cbd5e0;\n\t--code-background-color: #2d3748;\n\t--code-builtin-text-color: #68d391;\n\t--code-keyword-text-color: #63b3ed;\n\t--code-function-text-color: #4fd1c5;\n\t--code-comment-text-color: #a0aec0;\n\t--code-punctuation-text-color: #a0aec0;\n\t--code-symbol-text-color: #ed64a6;\n\t--code-operator-text-color: #a67f59;\n\t--attribute-background-color: #ffffff20;\n\t--attribute-text-color: #ffffffaf;\n\t--attribute-deprecated-text-color: #fef3c7;\n\t--table-header-line-color: #cbd5e0;\n\t--table-background-color: #2d3748;\n}\nhtml.dark .dark-icon {\n\tdisplay: none;\n}\nhtml:not(.dark) .light-icon {\n\tdisplay: none;\n}\nhtml {\n\theight: 100%;\n}\nbody {\n\tmargin: 0;\n\tfont-family:\n\t\tJost,\n\t\t-apple-system,\n\t\tBlinkMacSystemFont,\n\t\t'Segoe UI',\n\t\tHelvetica,\n\t\tArial,\n\t\tsans-serif,\n\t\t'Apple Color Emoji',\n\t\t'Segoe UI Emoji',\n\t\t'Segoe UI Symbol';\n\tbackground-color: #fff;\n\tbackground-color: var(--background-color);\n\tcolor: #000;\n\tcolor: var(--text-color);\n\theight: 100%;\n}\nhr {\n\theight: 0.25rem;\n\tbackground-color: var(--title-bottom-line-color);\n\tborder: 0;\n\tpadding: 0;\n\tmargin: 1.2rem 0;\n}\n#page {\n\theight: 100%;\n\tpadding-top: 56px;\n\tbox-sizing: border-box;\n}\n\n/** Reset for menus */\n.doc-nav ul,\n.doc-toc ul {\n\tlist-style: none;\n\tpadding: 0;\n\tmargin: 0;\n}\n\n/* Left nav */\n.doc-nav {\n\tposition: fixed;\n\twidth: 100%;\n\tleft: 0;\n\tright: 0;\n\ttop: 0;\n\tdisplay: flex;\n\tbackground-color: #4b6c88;\n\tbackground-color: var(--menu-background-color);\n\tcolor: #fff;\n\tcolor: var(--menu-text-color);\n\tflex-direction: column;\n\toverflow-y: auto;\n\theight: 100vh;\n\tz-index: 10;\n\tscrollbar-width: thin;\n\tscrollbar-color: #a0aec0 transparent;\n\tscrollbar-color: var(--menu-scrollbar-color) transparent;\n\tfont-family: Jost, sans-serif;\n}\n*::-webkit-scrollbar {\n\twidth: 4px;\n\theight: 4px;\n}\n*::-webkit-scrollbar-track {\n\tbackground: transparent;\n}\n*::-webkit-scrollbar-thumb {\n\tbackground-color: #a0aec0;\n\tbackground-color: var(--menu-scrollbar-color);\n\tborder: 3px solid transparent;\n}\n.doc-nav .content li {\n\tline-height: 1.8;\n}\n.doc-nav .content.show {\n\tdisplay: flex;\n}\n.doc-nav .content.hidden {\n\tdisplay: none;\n}\n.doc-nav #toggle-menu {\n\tcursor: pointer;\n\tpadding: 0.3rem;\n\tfill: #fff;\n\tfill: var(--menu-toggle-icon-color);\n}\n.doc-nav > .heading-container {\n\tposition: sticky;\n\tposition: -webkit-sticky;\n\ttop: 0;\n\tbackground-color: #4b6c88;\n\tbackground-color: var(--menu-background-color);\n\tz-index: 10;\n}\n.doc-nav > .heading-container > .heading {\n\tdisplay: flex;\n\tflex-direction: column;\n}\n.doc-nav > .heading-container > .heading > .info {\n\tdisplay: flex;\n\tpadding: 0 1rem;\n\theight: 56px;\n}\n.doc-nav > .heading-container > .heading > .info > .module {\n\tfont-size: 1.6rem;\n\tfont-weight: 500;\n\tmargin: 0;\n}\n.doc-nav > .heading-container > .heading > .info > .toggle-version-container {\n\tdisplay: flex;\n\talign-items: center;\n}\n.doc-nav > .heading-container > .heading > .info > .toggle-version-container > #dark-mode-toggle {\n\tcursor: pointer;\n\tfill: #fff;\n\tdisplay: flex;\n}\n.doc-nav\n\t> .heading-container\n\t> .heading\n\t> .info\n\t> .toggle-version-container\n\t> #dark-mode-toggle\n\t> svg {\n\twidth: 1.2rem;\n\theight: 1.2rem;\n}\n.doc-nav #search {\n\tposition: relative;\n\tmargin: 0.6rem 1.2rem 1rem 1.2rem;\n\tdisplay: flex;\n}\n.doc-nav #search input {\n\tborder: none;\n\twidth: 100%;\n\tborder-radius: 0.2rem;\n\tpadding: 0.5rem 1rem;\n\toutline: none;\n\tbackground-color: #00000044;\n\tbackground-color: var(--menu-search-background-color);\n\tcolor: #fff;\n\tcolor: var(--menu-search-text-color);\n}\n.doc-nav #search input::placeholder {\n\tcolor: #edf2f7;\n\ttext-transform: uppercase;\n\tfont-size: 12px;\n\tfont-weight: 600;\n}\n.doc-nav #search-keys {\n\tposition: absolute;\n\theight: 100%;\n\talign-items: center;\n\tdisplay: flex;\n\ttop: 0;\n\tright: 0.75rem;\n\topacity: 0.33;\n\ttransition: opacity 0.1s;\n}\n.doc-nav #search-keys.hide {\n\topacity: 0;\n}\n.doc-nav #search-keys kbd {\n\tpadding: 2.5px 4px;\n\tmargin-left: 1px;\n\tfont-size: 11px;\n\tbackground-color: var(--menu-background-color);\n\tborder: 1px solid #ffffff44;\n\tborder-radius: 3px;\n}\n.doc-nav > .content {\n\tpadding: 0 2rem 2rem 2rem;\n\tdisplay: flex;\n\tflex-direction: column;\n}\n.doc-nav > .content > ul > li.active {\n\tfont-weight: 600;\n}\n.doc-nav > .content > ul > li.open ul {\n\tdisplay: initial;\n}\n.doc-nav > .content > ul > li.open > .menu-row > .dropdown-arrow {\n\ttransform: initial;\n}\n.doc-nav > .content > ul > li > .menu-row {\n\tdisplay: flex;\n\talign-items: center;\n}\n.doc-nav > .content > ul > li > .menu-row > .dropdown-arrow {\n\ttransform: rotate(-90deg);\n\theight: 18px;\n\twidth: 18px;\n\tmargin-left: calc(-18px - 0.3rem);\n\tmargin-right: 0.3rem;\n\tcursor: pointer;\n\tfill: #fff;\n\tpointer-events: all;\n}\n.doc-nav > .content > ul > li > ul {\n\tmargin: 0.4rem 0;\n\tdisplay: none;\n}\n.doc-nav > .content > ul > li > ul > li {\n\tborder-color: #ffffff66;\n\tborder-color: var(--menu-indent-line-color);\n\tborder-left-width: 1.7px;\n\tborder-left-style: solid;\n\tpadding-left: 0.7rem;\n}\n.doc-nav > .content > ul > li > ul > li.active {\n\tborder-color: #00000066;\n\tborder-color: var(--menu-indent-line-active-color);\n}\n.doc-nav > .content a {\n\tcolor: #fff;\n\tcolor: var(--menu-text-color);\n\ttext-decoration: none;\n\tuser-select: none;\n}\n.doc-nav > .content a:hover {\n\ttext-decoration: underline;\n}\n.doc-nav .search {\n\toverflow-y: auto;\n}\n.doc-nav .search.hidden {\n\tdisplay: none;\n}\n.doc-nav .search li {\n\tline-height: 1.5;\n}\n.doc-nav > .search .result:hover,\n.doc-nav > .search .result.selected {\n\tbackground-color: #00000021;\n\tbackground-color: var(--menu-search-result-background-hover-color);\n}\n.doc-nav > .search .result:hover > .link > .definition > .badge {\n\tbackground-color: #0000004d;\n\tbackground-color: var(--menu-search-badge-background-hover-color);\n}\n.doc-nav > .search .result > .link {\n\tpadding: 0.5rem 1.4rem;\n\ttext-decoration: none;\n\tcolor: #fff;\n\tcolor: var(--menu-text-color);\n\tdisplay: block;\n}\n.doc-nav > .search .result > .link > .definition {\n\tdisplay: flex;\n}\n.doc-nav > .search .result > .link > .definition > .title {\n\tcolor: #90cdf4;\n\tcolor: var(--menu-search-title-text-color);\n\tfont-size: 0.875rem;\n\tfont-weight: 500;\n\toverflow: hidden;\n\twhite-space: nowrap;\n\ttext-overflow: ellipsis;\n}\n.doc-nav > .search .result > .link > .definition > .badge {\n\tfont-size: 0.75rem;\n\tdisplay: inline-flex;\n\tpadding: 0 0.5rem;\n\tbackground-color: #00000044;\n\tbackground-color: var(--menu-search-badge-background-color);\n\tmargin-left: auto;\n\talign-items: center;\n\tborder-radius: 9999px;\n\tfont-weight: 500;\n}\n.doc-nav > .search .result > .link > .description {\n\tfont-family:\n\t\tJost,\n\t\t-apple-system,\n\t\tBlinkMacSystemFont,\n\t\t'Segoe UI',\n\t\tHelvetica,\n\t\tArial,\n\t\tsans-serif,\n\t\t'Apple Color Emoji',\n\t\t'Segoe UI Emoji',\n\t\t'Segoe UI Symbol';\n\tfont-size: 0.75rem;\n\toverflow: hidden;\n\twhite-space: nowrap;\n\ttext-overflow: ellipsis;\n\tmargin-top: 0.25rem;\n}\n.doc-nav > .search > hr.separator {\n\tmargin: 0.5rem 0;\n\tborder-color: #00000044;\n\tborder-color: var(--menu-search-separator-color);\n\tbox-sizing: content-box;\n\theight: 0;\n\tborder-width: 0;\n\tborder-top-width: 1px;\n\tborder-style: solid;\n\toverflow: visible;\n}\n\n/* Main content */\n#main-content {\n\toutline: none;\n}\n.doc-scrollview {\n\theight: 100%;\n\toverflow-y: scroll;\n}\n.doc-container {\n\tdisplay: flex;\n\tflex-direction: column-reverse;\n}\n.doc-content {\n\tdisplay: flex;\n\tflex-direction: column;\n\tpadding: 1rem;\n\toverflow: hidden;\n}\n.doc-content img {\n\twidth: auto;\n\tmax-width: 100%;\n}\n.doc-content p {\n\tfont-size: 1rem;\n\tline-height: 1.6;\n\tletter-spacing: 0.025em;\n\tmax-width: 100ch;\n\tword-wrap: break-word;\n}\n.doc-content a {\n\tcolor: #2779bd;\n\tcolor: var(--link-color);\n}\n.doc-content p code {\n\tfont-size: 0.85rem;\n}\n.doc-content > .doc-node {\n\tpadding: 0.5rem 0 0.5rem 0;\n\tmargin-top: -4rem;\n\toverflow: hidden;\n\tword-break: break-word;\n}\n.doc-content > .doc-node.const:nth-child(2) {\n\tpadding-bottom: 0 !important;\n}\n.doc-content > .doc-node.const:not(:first-child) {\n\tpadding-top: 4rem;\n}\n.doc-content > .doc-node.const:not(:last-child) {\n\tpadding-bottom: 2rem;\n}\n.doc-content > .timestamp {\n\tfont-size: 0.8rem;\n\tcolor: #b8c2cc;\n\tcolor: var(--timestamp-color);\n}\n.doc-content > .doc-node > .title {\n\tdisplay: flex;\n\tfont-family: Jost, sans-serif;\n\tfont-weight: 500;\n\tpadding: 0.3rem;\n\talign-items: center;\n\tmargin-bottom: 1rem;\n\tborder-bottom: 1px solid #f1f5f8;\n\tborder-bottom: 1px solid var(--title-bottom-line-color);\n}\n.doc-content > .doc-node > .attributes {\n\tmargin-bottom: 0.6rem;\n}\n.doc-content > .doc-node > .attributes > .attribute {\n\tdisplay: inline-block;\n\tborder-radius: 100px;\n\tpadding: 0.3rem 0.6rem;\n\tbackground-color: var(--code-background-color);\n\tcolor: var(--attribute-text-color);\n\tmargin-right: 0.8rem;\n\tfont-family: 'Jetbrains Mono', monospace;\n\tfont-size: 0.9rem;\n}\n.doc-content > .doc-node > .attributes > .attribute-deprecated {\n\tbackground-color: var(--attribute-deprecated-background-color);\n\tcolor: var(--attribute-deprecated-text-color);\n}\n.doc-content > .doc-node > .title > .link {\n\tdisplay: flex;\n\tmargin-left: auto;\n\tfill: #dae1e7;\n\tfill: var(--ref-symbol-color);\n}\n.doc-content > .doc-node > .title > .link:hover {\n\tfill: #b8c2cc;\n\tfill: var(--ref-symbol-hover-color);\n}\n.doc-content > .doc-node h1 {\n\tfont-size: 2rem;\n}\n.doc-content > .doc-node h2 {\n\tfont-size: 1.3rem;\n}\n.doc-content > .doc-node .signature {\n\tborder-color: #a0aec0;\n\tborder-color: var(--code-signature-border-color);\n\tborder-left-width: 3px;\n\tborder-left-style: solid;\n}\n.doc-content > .doc-node > ul > li .task-list-item-checkbox {\n\tmargin-right: 0.5rem;\n}\n.doc-content > .doc-node > .title h1,\n.doc-content > .doc-node > .title h2,\n.doc-content > .doc-node > .title h3,\n.doc-content > .doc-node > .title h4,\n.doc-content > .doc-node > .title h5,\n.doc-content > .doc-node > .title h6 {\n\tfont-weight: 500;\n\tmargin: 0;\n}\n.doc-content > .doc-node > .title h1 a,\n.doc-content > .doc-node > .title h2 a,\n.doc-content > .doc-node > .title h3 a,\n.doc-content > .doc-node > .title h4 a,\n.doc-content > .doc-node > .title h5 a,\n.doc-content > .doc-node > .title h6 a {\n\ttext-decoration: none;\n\tcolor: #dae1e7;\n\tcolor: var(--ref-symbol-color);\n}\n.doc-content > .doc-node > .title h1 a:hover,\n.doc-content > .doc-node > .title h2 a:hover,\n.doc-content > .doc-node > .title h3 a:hover,\n.doc-content > .doc-node > .title h4 a:hover,\n.doc-content > .doc-node > .title h5 a:hover,\n.doc-content > .doc-node > .title h6 a:hover {\n\tcolor: #b8c2cc;\n\tcolor: var(--ref-symbol-hover-color);\n}\n.doc-content > .footer {\n\tpadding-top: 1rem;\n\tmargin-top: auto;\n\tbottom: 1rem;\n\tcolor: 616161;\n\tcolor: var(--footer-text-color);\n\tborder-color: #f1f5f8;\n\tborder-color: var(--footer-top-line-color);\n\tborder-top-style: solid;\n\tborder-top-width: 1px;\n\tfont-size: 0.8rem;\n\tfont-weight: 500;\n}\n\n/* Right menu */\n.doc-toc {\n\tright: 0;\n\ttop: 0;\n\theight: 100%;\n\toverflow-y: auto;\n\tpadding: 1rem 1rem 0 1rem;\n\twidth: 100%;\n\tbox-sizing: border-box;\n\t-ms-overflow-style: none;\n\tscrollbar-width: none;\n\tfont-family: Jost, sans-serif;\n}\n.doc-toc::-webkit-scrollbar {\n\tdisplay: none;\n}\n.doc-toc li {\n\tline-height: 1.5;\n}\n.doc-toc a {\n\tcolor: #2779bd;\n\tcolor: var(--toc-text-color);\n\tfont-size: 0.9rem;\n\tfont-weight: 600;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\tdisplay: block;\n\ttext-decoration: none;\n\tborder-left-width: 2px;\n\tborder-left-style: solid;\n\tborder-color: transparent;\n\tpadding-left: 0.4rem;\n}\n.doc-toc a:hover {\n\ttext-decoration: underline;\n}\n.doc-toc a.active {\n\tborder-color: #4299e1;\n\tborder-color: var(--toc-indicator-color);\n}\n.doc-toc li ul {\n\tmargin: 0.2rem 0 0.2rem;\n\tfont-size: 0.7rem;\n\tlist-style: none;\n}\n.doc-toc li ul a {\n\tfont-weight: 400;\n\tpadding-left: 0.8rem;\n}\n\n/* Code highlight */\npre,\ncode,\npre code {\n\tcolor: #5c6e74;\n\tcolor: var(--code-default-text-color);\n\tfont-size: 0.948em;\n\ttext-shadow: none;\n\tfont-family: 'Jetbrains Mono', monospace;\n\tbackground-color: #edf2f7;\n\tbackground-color: var(--code-background-color);\n\tborder-radius: 0.25rem;\n}\npre code {\n\tdirection: ltr;\n\ttext-align: left;\n\twhite-space: pre;\n\tword-spacing: normal;\n\tword-break: normal;\n\tline-height: 1.5;\n\t-moz-tab-size: 4;\n\t-o-tab-size: 4;\n\ttab-size: 4;\n\t-webkit-hyphens: none;\n\t-moz-hyphens: none;\n\t-ms-hyphens: none;\n\thyphens: none;\n\tdisplay: block;\n\toverflow-x: auto;\n\tpadding: 5px;\n}\ncode {\n\tpadding: 0 0.2rem;\n}\npre {\n\toverflow: auto;\n\tmargin: 0;\n\tposition: relative;\n}\n.namespace {\n\topacity: 0.7;\n}\n.token.comment {\n\tcolor: #93a1a1;\n\tcolor: var(--code-comment-text-color);\n}\n.token.punctuation {\n\tcolor: #999999;\n\tcolor: var(--code-punctuation-text-color);\n}\n.token.number,\n.token.symbol {\n\tcolor: #702459;\n\tcolor: var(--code-symbol-text-color);\n}\n.token.string,\n.token.char,\n.token.builtin {\n\tcolor: #38a169;\n\tcolor: var(--code-builtin-text-color);\n}\n.token.operator,\n.token.entity,\n.token.url,\n.language-css .token.string,\n.style .token.string {\n\tcolor: #a67f59;\n\tcolor: var(--code-operator-text-color);\n\tbackground: transparent;\n}\n.token.boolean,\n.token.keyword {\n\tcolor: #2b6cb0;\n\tcolor: var(--code-keyword-text-color);\n\tfont-weight: bold;\n}\n.token.function {\n\tcolor: #319795;\n\tcolor: var(--code-function-text-color);\n}\n.examples > h4 {\n\tmargin: 0 0 0.4rem 0;\n}\n\ntable {\n\tborder: 1px solid var(--table-background-color);\n\tborder-collapse: collapse;\n}\ntable tr td,\ntable tr th {\n\tpadding: 4px 8px;\n}\ntable tr th {\n\tbackground-color: var(--table-background-color);\n}\ntr:nth-child(even) {\n\tbackground-color: var(--table-background-color);\n}\n\nbutton.copy {\n\tborder: none;\n\tbackground-color: transparent;\n\tposition: absolute;\n\tfont-size: 12px;\n\ttop: 5px;\n\tright: 5px;\n\tcolor: var(--ref-symbol-hover-color);\n}\n\n/* Medium screen and up */\n@media (min-width: 768px) {\n\t*::-webkit-scrollbar {\n\t\twidth: 8px;\n\t\theight: 8px;\n\t}\n\t*::-webkit-scrollbar-thumb {\n\t\tborder: 3px solid transparent;\n\t}\n\t.doc-container {\n\t\tflex-direction: row;\n\t}\n\t.doc-content {\n\t\tfont-size: 0.95rem;\n\t\tflex: 1;\n\t\tpadding: 0rem 2rem 1rem 2rem;\n\t}\n\t.doc-toc {\n\t\tposition: sticky;\n\t\theight: 100vh;\n\t\tposition: -webkit-sticky;\n\t\talign-self: flex-start;\n\t\tmin-width: 200px;\n\t\twidth: auto;\n\t\tmax-width: 300px;\n\t}\n\t.doc-toc > ul {\n\t\tpadding-bottom: 1rem;\n\t}\n}\n\n@media (max-width: 1023px) {\n\t.doc-nav.hidden {\n\t\theight: auto;\n\t}\n\t.doc-nav.hidden #search {\n\t\tdisplay: none;\n\t}\n\t.doc-nav .search.mobile-hidden {\n\t\tdisplay: none;\n\t}\n\t.doc-nav > .heading-container > .heading > .info {\n\t\talign-items: center;\n\t}\n\t.doc-nav > .heading-container > .heading > .info > .toggle-version-container {\n\t\tflex-grow: 1;\n\t\tpadding: 0 1rem;\n\t\tjustify-content: space-between;\n\t}\n\t.doc-content > .doc-node > .title {\n\t\tmargin-top: 3.5em;\n\t}\n}\n\n@media (min-width: 1024px) {\n\t#page {\n\t\tpadding-top: 0;\n\t}\n\t.doc-nav {\n\t\twidth: 300px;\n\t}\n\t.doc-nav #toggle-menu {\n\t\tdisplay: none;\n\t}\n\t.doc-nav > .heading-container > .heading > .info {\n\t\theight: auto;\n\t\tpadding: 1rem 2rem 0 2rem;\n\t\tflex-direction: column-reverse;\n\t\tjustify-content: center;\n\t}\n\t.doc-nav > .heading-container > .heading > .info > .toggle-version-container {\n\t\talign-items: center;\n\t\tmargin-bottom: 0.2rem;\n\t\tdisplay: flex;\n\t\tflex-direction: row-reverse;\n\t}\n\t.doc-nav > .heading-container > .heading > .info > .toggle-version-container > #dark-mode-toggle {\n\t\tmargin-right: auto;\n\t}\n\t.doc-nav .content.show,\n\t.doc-nav .content.hidden {\n\t\tdisplay: flex;\n\t}\n\t.doc-content > .doc-node.const:nth-child(2) {\n\t\tpadding-bottom: 0 !important;\n\t}\n\t.doc-content > .doc-node.const:not(:first-child) {\n\t\tpadding-top: 0;\n\t}\n\t.doc-content > .doc-node.const:not(:last-child) {\n\t\tpadding-bottom: 5px;\n\t}\n\t.doc-container {\n\t\tmargin-left: 300px;\n\t}\n\t.doc-node {\n\t\tpadding-top: 1rem !important;\n\t\tmargin-top: 0 !important;\n\t}\n}\n\n#skip-to-content-link {\n\theight: 30px;\n\tleft: 50%;\n\tpadding: 8px;\n\tposition: absolute;\n\ttransform: translateY(-100%);\n\ttransition: transform 0.3s;\n\tbackground: var(--links);\n\tcolor: var(--warn-text);\n\tborder-radius: 1px;\n}\n#skip-to-content-link:focus {\n\ttransform: translateY(0%);\n\tz-index: 1000;\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/theme/doc.js",
    "content": "(function () {\n\tconst docnav = document.querySelector('header.doc-nav');\n\tconst active = docnav.querySelector('li.active');\n\tactive?.scrollIntoView({ block: 'center', inline: 'nearest' });\n\tsetupMobileToggle();\n\tsetupDarkMode();\n\tsetupScrollSpy();\n\tsetupSearch();\n\tsetupCollapse();\n\tsetupCodeCopy();\n})();\n\nfunction setupScrollSpy() {\n\tconst mainContent = document.querySelector('#main-content');\n\tconst toc = mainContent.querySelector('.doc-toc');\n\tif (!toc) {\n\t\treturn;\n\t}\n\tconst sections = mainContent.querySelectorAll('section');\n\tconst sectionPositions = Array.from(sections).map((section) => section.offsetTop);\n\tlet lastActive = null;\n\tlet clickedScroll = false;\n\tconst handleScroll = debounce(() => {\n\t\tif (clickedScroll) {\n\t\t\tclickedScroll = false;\n\t\t\treturn;\n\t\t}\n\t\tif (lastActive) {\n\t\t\tlastActive.classList.remove('active');\n\t\t}\n\t\tfor (const [i, position] of sectionPositions.entries()) {\n\t\t\tif (position >= mainContent.scrollTop) {\n\t\t\t\tconst link = toc.querySelector('a[href=\"#' + sections[i].id + '\"]');\n\t\t\t\tif (link) {\n\t\t\t\t\t// Set current menu link as active\n\t\t\t\t\tlink.classList.add('active');\n\t\t\t\t\tconst tocStart = toc.getBoundingClientRect().top + window.scrollY;\n\t\t\t\t\tif (link.offsetTop > toc.scrollTop + toc.clientHeight - tocStart - 16) {\n\t\t\t\t\t\t// Scroll the toc down if the active links position is below the bottom of the toc\n\t\t\t\t\t\ttoc.scrollTop = link.clientHeight + link.offsetTop - toc.clientHeight + tocStart + 10;\n\t\t\t\t\t} else if (toc.scrollTop < 32 + tocStart) {\n\t\t\t\t\t\t// Scroll to the top of the toc if having scrolled up into the last bit\n\t\t\t\t\t\ttoc.scrollTop = 0;\n\t\t\t\t\t} else if (link.offsetTop < toc.scrollTop) {\n\t\t\t\t\t\t// Scroll the toc up if the active links position is above the top of the toc\n\t\t\t\t\t\ttoc.scrollTop = link.offsetTop - 10;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlastActive = link;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}, 10);\n\tmainContent.addEventListener('scroll', handleScroll);\n\ttoc.querySelectorAll('a').forEach((a) =>\n\t\ta.addEventListener('click', () => {\n\t\t\tif (lastActive) {\n\t\t\t\tlastActive.classList.remove('active');\n\t\t\t}\n\t\t\ta.classList.add('active');\n\t\t\tlastActive = a;\n\t\t\tclickedScroll = true;\n\t\t}),\n\t);\n}\n\nfunction setupMobileToggle() {\n\tdocument.getElementById('toggle-menu').addEventListener('click', () => {\n\t\tconst docNav = document.querySelector('header.doc-nav');\n\t\tconst isHidden = docNav.classList.contains('hidden');\n\t\tdocNav.classList.toggle('hidden');\n\t\tconst search = docNav.querySelector('.search');\n\t\tconst searchHasResults = search.classList.contains('has-results');\n\t\tif (isHidden && searchHasResults) {\n\t\t\tsearch.classList.remove('mobile-hidden');\n\t\t} else {\n\t\t\tsearch.classList.add('mobile-hidden');\n\t\t}\n\t\tconst content = docNav.querySelector('.content');\n\t\tcontent.classList.toggle('hidden');\n\t\tcontent.classList.toggle('show');\n\t});\n}\n\nfunction setupDarkMode() {\n\tconst html = document.querySelector('html');\n\tconst darkModeToggle = document.getElementById('dark-mode-toggle');\n\tdarkModeToggle.addEventListener('click', () => {\n\t\thtml.classList.toggle('dark');\n\t\tconst isDarkModeEnabled = html.classList.contains('dark');\n\t\tlocalStorage.setItem('dark-mode', isDarkModeEnabled);\n\t\tdarkModeToggle.setAttribute('aria-checked', isDarkModeEnabled);\n\t});\n}\n\nfunction setupSearch() {\n\tconst onInputChange = debounce((e) => {\n\t\tconst searchValue = e.target.value.toLowerCase();\n\t\tconst docNav = document.querySelector('header.doc-nav');\n\t\tconst menu = docNav.querySelector('.content');\n\t\tconst search = docNav.querySelector('.search');\n\t\tif (searchValue === '') {\n\t\t\t// reset to default\n\t\t\tmenu.style.display = '';\n\t\t\tif (!search.classList.contains('hidden')) {\n\t\t\t\tsearch.classList.add('hidden');\n\t\t\t\tsearch.classList.remove('has-results');\n\t\t\t}\n\t\t} else if (searchValue.length >= 2) {\n\t\t\t// search for less than 2 characters can display too much results\n\t\t\tsearch.innerHTML = '';\n\t\t\tmenu.style.display = 'none';\n\t\t\tif (search.classList.contains('hidden')) {\n\t\t\t\tsearch.classList.remove('hidden');\n\t\t\t\tsearch.classList.remove('mobile-hidden');\n\t\t\t\tsearch.classList.add('has-results');\n\t\t\t}\n\t\t\t// cache length for performance\n\t\t\tlet foundModule = false;\n\t\t\tconst ul = document.createElement('ul');\n\t\t\tsearch.appendChild(ul);\n\t\t\tfor (const [i, title] of searchModuleIndex.entries()) {\n\t\t\t\t// no toLowerCase needed because modules are always lowercase\n\t\t\t\tif (title.indexOf(searchValue) === -1) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tfoundModule = true;\n\t\t\t\t// [description, link]\n\t\t\t\tconst data = searchModuleData[i];\n\t\t\t\tconst el = createSearchResult({\n\t\t\t\t\tbadge: 'module',\n\t\t\t\t\tdescription: data[0],\n\t\t\t\t\tlink: data[1],\n\t\t\t\t\ttitle: title,\n\t\t\t\t});\n\t\t\t\tul.appendChild(el);\n\t\t\t}\n\t\t\tif (foundModule) {\n\t\t\t\tconst hr = document.createElement('hr');\n\t\t\t\thr.classList.add('separator');\n\t\t\t\tsearch.appendChild(hr);\n\t\t\t}\n\t\t\tlet results = [];\n\t\t\tfor (const [i, title] of searchIndex.entries()) {\n\t\t\t\tif (title.toLowerCase().indexOf(searchValue) === -1) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// [badge, description, link]\n\t\t\t\tconst data = searchData[i];\n\t\t\t\tresults.push({\n\t\t\t\t\tbadge: data[0],\n\t\t\t\t\tdescription: data[1],\n\t\t\t\t\tlink: data[2],\n\t\t\t\t\ttitle: data[3] + ' ' + title,\n\t\t\t\t});\n\t\t\t}\n\t\t\tresults.sort((a, b) => (a.title < b.title ? -1 : a.title > b.title ? 1 : 0));\n\t\t\tconst ul_ = document.createElement('ul');\n\t\t\tsearch.appendChild(ul_);\n\t\t\tresults.forEach((result) => {\n\t\t\t\tconst el = createSearchResult(result);\n\t\t\t\tul_.appendChild(el);\n\t\t\t});\n\t\t}\n\t});\n\tconst searchInput = document.querySelector('#search input');\n\tconst url = document.location.toString();\n\tif (url.includes('?')) {\n\t\tconst query =\n\t\t\turl\n\t\t\t\t.split('?')\n\t\t\t\t.slice(1)\n\t\t\t\t.filter((p) => p.startsWith('q='))\n\t\t\t\t.map((p) => p.replace(/^q=/, ''))[0] || '';\n\t\tif (query) {\n\t\t\tsearchInput.value = query;\n\t\t\tsearchInput.focus();\n\t\t\tonInputChange({ target: { value: query } });\n\t\t}\n\t}\n\tconst searchInputDiv = document.getElementById('search');\n\tsearchInputDiv.addEventListener('input', onInputChange);\n\tsetupSearchKeymaps();\n}\n\nfunction setupSearchKeymaps() {\n\tconst searchInput = document.querySelector('#search input');\n\tconst mainContent = document.querySelector('#main-content');\n\tconst docnav = document.querySelector('header.doc-nav');\n\t// Keyboard shortcut indicator\n\tconst searchKeys = document.createElement('div');\n\tconst modifierKeyPrefix = navigator.platform.includes('Mac') ? '⌘' : 'Ctrl';\n\tsearchKeys.setAttribute('id', 'search-keys');\n\tsearchKeys.innerHTML = '<kbd>' + modifierKeyPrefix + '</kbd><kbd>k</kbd>';\n\tsearchInput.parentElement?.appendChild(searchKeys);\n\tsearchInput.addEventListener('focus', () => searchKeys.classList.add('hide'));\n\tsearchInput.addEventListener('blur', () => searchKeys.classList.remove('hide'));\n\t// Global shortcuts to focus searchInput\n\tdocument.addEventListener('keydown', (ev) => {\n\t\tif (ev.key === '/' || ((ev.ctrlKey || ev.metaKey) && ev.key === 'k')) {\n\t\t\tev.preventDefault();\n\t\t\tsearchInput.focus();\n\t\t}\n\t});\n\t// Shortcuts while searchInput is focused\n\tlet selectedIdx = -1;\n\tfunction selectResult(results, newIdx) {\n\t\tif (selectedIdx !== -1) {\n\t\t\tresults[selectedIdx].classList.remove('selected');\n\t\t}\n\t\tresults[newIdx].classList.add('selected');\n\t\tresults[newIdx].scrollIntoView({ behavior: 'instant', block: 'nearest', inline: 'nearest' });\n\t\tselectedIdx = newIdx;\n\t}\n\tsearchInput.addEventListener('keydown', (ev) => {\n\t\tconst searchResults = document.querySelectorAll('.search .result');\n\t\tswitch (ev.key) {\n\t\t\tcase 'Escape':\n\t\t\t\tsearchInput.blur();\n\t\t\t\tmainContent.focus();\n\t\t\t\tbreak;\n\t\t\tcase 'Enter':\n\t\t\t\tif (!searchResults.length || selectedIdx === -1) break;\n\t\t\t\tsearchResults[selectedIdx].querySelector('a').click();\n\t\t\t\tbreak;\n\t\t\tcase 'ArrowDown':\n\t\t\t\tev.preventDefault();\n\t\t\t\tif (!searchResults.length) break;\n\t\t\t\tif (selectedIdx >= searchResults.length - 1) {\n\t\t\t\t\t// Cycle to first if last is selected\n\t\t\t\t\tselectResult(searchResults, 0);\n\t\t\t\t} else {\n\t\t\t\t\t// Select next\n\t\t\t\t\tselectResult(searchResults, selectedIdx + 1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'ArrowUp':\n\t\t\t\tev.preventDefault();\n\t\t\t\tif (!searchResults.length) break;\n\t\t\t\tif (selectedIdx <= 0) {\n\t\t\t\t\t// Cycle to last if first is selected (or select it if none is selected yet)\n\t\t\t\t\tselectResult(searchResults, searchResults.length - 1);\n\t\t\t\t} else {\n\t\t\t\t\t// Select previous\n\t\t\t\t\tselectResult(searchResults, selectedIdx - 1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tdocnav.scroll(0, 0);\n\t\t\t\tselectedIdx = -1;\n\t\t}\n\t});\n\t// Ensure initial keyboard navigability\n\tmainContent.focus();\n}\n\nfunction createSearchResult(data) {\n\tconst li = document.createElement('li');\n\tli.classList.add('result');\n\tconst a = document.createElement('a');\n\ta.href = data.link;\n\ta.classList.add('link');\n\tli.appendChild(a);\n\tconst definition = document.createElement('div');\n\tdefinition.classList.add('definition');\n\ta.appendChild(definition);\n\tif (data.description) {\n\t\tconst description = document.createElement('div');\n\t\tdescription.classList.add('description');\n\t\tdescription.textContent = data.description;\n\t\ta.appendChild(description);\n\t}\n\tconst title = document.createElement('span');\n\ttitle.classList.add('title');\n\ttitle.textContent = data.title;\n\tdefinition.appendChild(title);\n\tconst badge = document.createElement('badge');\n\tbadge.classList.add('badge');\n\tbadge.textContent = data.badge;\n\tdefinition.appendChild(badge);\n\treturn li;\n}\n\nfunction setupCollapse() {\n\tconst dropdownArrows = document.querySelectorAll('.dropdown-arrow');\n\tdropdownArrows.forEach((arrow) => {\n\t\tarrow.addEventListener('click', (e) => {\n\t\t\tconst parent = e.target.parentElement.parentElement.parentElement;\n\t\t\tparent.classList.toggle('open');\n\t\t});\n\t});\n}\n\nfunction debounce(func, timeout) {\n\tlet timer;\n\treturn (...args) => {\n\t\tconst next = () => func(...args);\n\t\tif (timer) {\n\t\t\tclearTimeout(timer);\n\t\t}\n\t\ttimer = setTimeout(next, timeout > 0 ? timeout : 300);\n\t};\n}\n\nfunction setupCodeCopy() {\n\tconst pres = document.querySelectorAll('pre:not(.signature)');\n\tpres.forEach((pre) => {\n\t\tconst tempDiv = document.createElement('button');\n\t\ttempDiv.className = 'copy';\n\t\ttempDiv.innerHTML =\n\t\t\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"rgba(173,184,194,1)\"><path d=\"M6.9998 6V3C6.9998 2.44772 7.44752 2 7.9998 2H19.9998C20.5521 2 20.9998 2.44772 20.9998 3V17C20.9998 17.5523 20.5521 18 19.9998 18H16.9998V20.9991C16.9998 21.5519 16.5499 22 15.993 22H4.00666C3.45059 22 3 21.5554 3 20.9991L3.0026 7.00087C3.0027 6.44811 3.45264 6 4.00942 6H6.9998ZM5.00242 8L5.00019 20H14.9998V8H5.00242ZM8.9998 6H16.9998V16H18.9998V4H8.9998V6Z\"></path></svg>';\n\t\ttempDiv.addEventListener('click', (e) => {\n\t\t\tconst parent = e.target;\n\t\t\tvar code = tempDiv.parentElement.querySelector('code');\n\t\t\tlet i = Array.from(code.childNodes)\n\t\t\t\t.map((r) => r.textContent)\n\t\t\t\t.join('');\n\t\t\tnavigator.clipboard.writeText(i);\n\t\t\tvar tmp = tempDiv.innerHTML;\n\t\t\ttempDiv.innerHTML = 'Copied';\n\t\t\twindow.setTimeout(function () {\n\t\t\t\ttempDiv.innerHTML = tmp;\n\t\t\t}, 1000);\n\t\t});\n\t\tpre.insertAdjacentElement('afterbegin', tempDiv);\n\t});\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/theme/favicons/browserconfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig>\n    <msapplication>\n        <tile>\n            <square150x150logo src=\"/mstile-150x150.png\"/>\n            <TileColor>#da532c</TileColor>\n        </tile>\n    </msapplication>\n</browserconfig>\n"
  },
  {
    "path": "cmd/tools/vdoc/theme/favicons/site.webmanifest",
    "content": "{\n\t\"name\": \"\",\n\t\"short_name\": \"\",\n\t\"icons\": [\n\t\t{\n\t\t\t\"src\": \"/android-chrome-192x192.png\",\n\t\t\t\"sizes\": \"192x192\",\n\t\t\t\"type\": \"image/png\"\n\t\t},\n\t\t{\n\t\t\t\"src\": \"/android-chrome-512x512.png\",\n\t\t\t\"sizes\": \"512x512\",\n\t\t\t\"type\": \"image/png\"\n\t\t}\n\t],\n\t\"theme_color\": \"#ffffff\",\n\t\"background_color\": \"#ffffff\",\n\t\"display\": \"standalone\"\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/theme/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"UTF-8\" />\n\t\t<meta http-equiv=\"x-ua-compatible\" content=\"IE=edge\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n\t\t<title>{{ title }} | vdoc</title>\n\t\t<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n\t\t<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n\t\t<link\n\t\t\thref=\"https://fonts.googleapis.com/css2?family=Jost:wght@300;400;500;600;700&display=swap\"\n\t\t\trel=\"stylesheet\"\n\t\t/>\n\t\t<link\n\t\t\thref=\"https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap\"\n\t\t\trel=\"stylesheet\"\n\t\t/>\n\t\t<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"apple-touch-icon.png\" />\n\t\t<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"favicon-32x32.png\" />\n\t\t<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"favicon-16x16.png\" />\n\t\t<link rel=\"manifest\" href=\"site.webmanifest\" />\n\t\t<link rel=\"mask-icon\" href=\"safari-pinned-tab.svg\" color=\"#5bbad5\" />\n\t\t<meta name=\"msapplication-TileColor\" content=\"#da532c\" />\n\t\t<meta name=\"theme-color\" content=\"#ffffff\" />\n\t\t{{ head_assets }}\n\t</head>\n\n\t<body>\n\t\t<div><a id=\"skip-to-content-link\" href=\"#main-content\">Skip to content</a></div>\n\t\t<div id=\"page\">\n\t\t\t<header class=\"doc-nav hidden\">\n\t\t\t\t<div class=\"heading-container\">\n\t\t\t\t\t<div class=\"heading\">\n\t\t\t\t\t\t<div class=\"info\">\n\t\t\t\t\t\t\t<div class=\"module\">{{ head_name }}</div>\n\t\t\t\t\t\t\t<div class=\"toggle-version-container\">\n\t\t\t\t\t\t\t\t<span>{{ version }}</span>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tid=\"dark-mode-toggle\"\n\t\t\t\t\t\t\t\t\trole=\"switch\"\n\t\t\t\t\t\t\t\t\taria-checked=\"false\"\n\t\t\t\t\t\t\t\t\taria-label=\"Toggle dark mode\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{{ light_icon }}{{ dark_icon }}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{{ menu_icon }}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div id=\"search\">\n\t\t\t\t\t\t\t<input type=\"text\" placeholder=\"Search... (beta)\" autocomplete=\"off\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<nav class=\"search hidden\"></nav>\n\t\t\t\t<nav class=\"content hidden\">\n\t\t\t\t\t<ul>\n\t\t\t\t\t\t{{ toc_links }}\n\t\t\t\t\t</ul>\n\t\t\t\t</nav>\n\t\t\t</header>\n\t\t\t<div class=\"doc-scrollview\" tabindex=\"-1\" id=\"main-content\">\n\t\t\t\t<div class=\"doc-container\">\n\t\t\t\t\t<div class=\"doc-content\">\n\t\t\t\t\t\t{{ contents }}\n\t\t\t\t\t\t<div class=\"footer\">{{ footer_content }}</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t{{ right_content }}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t\t{{ footer_assets }}\n\t\t<script async src=\"search_index.js\"></script>\n\t</body>\n</html>\n"
  },
  {
    "path": "cmd/tools/vdoc/theme/normalize.css",
    "content": "/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */\nhtml {\n\tline-height: 1.15;\n\t-webkit-text-size-adjust: 100%;\n}\n\nmain {\n\tdisplay: block;\n}\n\nh1 {\n\tfont-size: 2em;\n\tmargin: 0.67em 0;\n}\n\npre {\n\tfont-family: monospace, monospace;\n\tfont-size: 1em;\n}\n\na {\n\tbackground-color: transparent;\n}\n\nabbr[title] {\n\tborder-bottom: none;\n\ttext-decoration: underline;\n\ttext-decoration: underline dotted;\n}\n\nb,\nstrong {\n\tfont-weight: bolder;\n}\n\nkbd,\nsamp {\n\tfont-family: monospace, monospace;\n\tfont-size: 1em;\n}\n\nsmall {\n\tfont-size: 80%;\n}\n\nsub,\nsup {\n\tfont-size: 75%;\n\tline-height: 0;\n\tposition: relative;\n\tvertical-align: baseline;\n}\n\nsub {\n\tbottom: -0.25em;\n}\n\nsup {\n\ttop: -0.5em;\n}\n\nimg {\n\tborder-style: none;\n}\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n\tfont-family: inherit;\n\tfont-size: 100%;\n\tline-height: 1.15;\n\tmargin: 0;\n}\n\nbutton,\ninput {\n\toverflow: visible;\n}\n\nbutton,\nselect {\n\ttext-transform: none;\n}\n\nbutton,\n[type='button'],\n[type='reset'],\n[type='submit'] {\n\t-webkit-appearance: button;\n}\n\nbutton::-moz-focus-inner,\n[type='button']::-moz-focus-inner,\n[type='reset']::-moz-focus-inner,\n[type='submit']::-moz-focus-inner {\n\tborder-style: none;\n\tpadding: 0;\n}\n\nbutton:-moz-focusring,\n[type='button']:-moz-focusring,\n[type='reset']:-moz-focusring,\n[type='submit']:-moz-focusring {\n\toutline: 1px dotted ButtonText;\n}\n\nfieldset {\n\tpadding: 0.35em 0.75em 0.625em;\n}\n\nlegend {\n\tbox-sizing: border-box;\n\tcolor: inherit;\n\tdisplay: table;\n\tmax-width: 100%;\n\tpadding: 0;\n\twhite-space: normal;\n}\n\nprogress {\n\tvertical-align: baseline;\n}\n\ntextarea {\n\toverflow: auto;\n}\n\n[type='checkbox'],\n[type='radio'] {\n\tbox-sizing: border-box;\n\tpadding: 0;\n}\n\n[type='number']::-webkit-inner-spin-button,\n[type='number']::-webkit-outer-spin-button {\n\theight: auto;\n}\n\n[type='search'] {\n\t-webkit-appearance: textfield;\n\toutline-offset: -2px;\n}\n\n[type='search']::-webkit-search-decoration {\n\t-webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n\t-webkit-appearance: button;\n\tfont: inherit;\n}\n\nsummary {\n\tdisplay: list-item;\n}\n\ntemplate {\n\tdisplay: none;\n}\n\n[hidden] {\n\tdisplay: none;\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/utils.v",
    "content": "module main\n\nimport document as doc\n\n@[inline]\nfn slug(title string) string {\n\treturn title.replace(' ', '-')\n}\n\nfn escape(str string) string {\n\treturn str.replace_each(['\"', '\\\\\"', '\\r\\n', '\\\\n', '\\n', '\\\\n', '\\t', '\\\\t'])\n}\n\nfn get_sym_name(dn doc.DocNode) string {\n\tif dn.is_readme {\n\t\tif title := dn.frontmatter['title'] {\n\t\t\treturn title\n\t\t}\n\t}\n\tif dn.parent_name.len > 0 && dn.parent_name != 'void' {\n\t\treturn '(${dn.parent_name}) ${dn.name}'\n\t}\n\treturn dn.name\n}\n\nfn get_node_id(dn doc.DocNode) string {\n\ttag := if dn.parent_name.len > 0 && dn.parent_name != 'void' {\n\t\t'${dn.parent_name}.${dn.name}'\n\t} else {\n\t\tdn.name\n\t}\n\treturn slug(tag)\n}\n\nfn is_module_readme(dn doc.DocNode) bool {\n\treturn dn.is_readme || (dn.comments.len > 0 && dn.content == 'module ${dn.name}')\n}\n\n// trim_doc_node_description returns the nodes trimmed description.\n// An example use are the descriptions of the search results in the sidebar.\nfn trim_doc_node_description(mod_name string, desc string) string {\n\tmut dn_desc := desc.replace_each(['\\r\\n', '\\n', '\"', '\\\\\"'])\n\t// Get the first \"descriptive\" line.\n\tif dn_desc.starts_with('#') {\n\t\t// Handle module READMEs.\n\t\tfor l in dn_desc.split_into_lines()[1..] {\n\t\t\tif l != '' && !l.starts_with('#') {\n\t\t\t\tquoted_mod_name := '`${mod_name}`'\n\t\t\t\tif l.starts_with(quoted_mod_name) {\n\t\t\t\t\t// Omit the module name in the description as it is redundant since the name is displayed as well.\n\t\t\t\t\t// \"`arrays` is a module that...\" -> \"is a module that...\"\n\t\t\t\t\tdn_desc = l.all_after(quoted_mod_name).trim_left(' ')\n\t\t\t\t} else {\n\t\t\t\t\tdn_desc = l\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t} else {\n\t\tdn_desc = dn_desc.all_before('\\n')\n\t}\n\t// 80 is enough to fill one line.\n\tif dn_desc.len > 80 {\n\t\tdn_desc = dn_desc[..80]\n\t}\n\t// If `\\` is the last character, it ends with `\\\"` which leads to a JS error.\n\treturn dn_desc.trim_string_right('\\\\')\n}\n\nfn set_output_type_from_str(format string) OutputType {\n\treturn match format {\n\t\t'htm', 'html' { OutputType.html }\n\t\t'md', 'markdown' { .markdown }\n\t\t'json' { .json }\n\t\t'text' { .plaintext }\n\t\t'none' { .none }\n\t\telse { .ansi }\n\t}\n}\n\nfn gen_footer_text(d &doc.Doc, include_timestamp bool) string {\n\tfooter_text := 'Powered by vdoc.'\n\tif !include_timestamp {\n\t\treturn footer_text\n\t}\n\tgenerated_time := d.time_generated\n\ttime_str := '${generated_time.day} ${generated_time.smonth()} ${generated_time.year} ${generated_time.hhmmss()}'\n\treturn '${footer_text} Generated on: ${time_str}'\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/v.mod",
    "content": ""
  },
  {
    "path": "cmd/tools/vdoc/vdoc.v",
    "content": "module main\n\nimport markdown\nimport os\nimport time\nimport strings\nimport runtime\nimport document as doc\nimport v.vmod\nimport v.util\nimport json\nimport term\n\nstruct Readme {\n\tfrontmatter map[string]string\n\tcontent     string\n\tpath        string\n}\n\nenum OutputType {\n\tunset\n\tnone\n\thtml\n\tmarkdown\n\tjson\n\tansi // text with ANSI color escapes\n\tplaintext\n}\n\n@[heap]\nstruct VDoc {\n\tcfg Config @[required]\nmut:\n\tdocs                []doc.Doc\n\tassets              map[string]string\n\tmanifest            vmod.Manifest\n\tsearch_index        []string\n\tsearch_data         []SearchResult\n\tsearch_module_index []string // search results are split into a module part and the rest\n\tsearch_module_data  []SearchModuleResult\n\texample_failures    int // how many times an example failed to compile or run with non 0 exit code; when positive, finish with exit code 1\n\texample_oks         int // how many ok examples were found when `-run-examples` was passed, that compiled and finished with 0 exit code.\n}\n\n//\nstruct Output {\nmut:\n\tpath string\n\ttyp  OutputType = .unset\n}\n\nstruct ParallelDoc {\n\td   doc.Doc\n\tout Output\n}\n\nfn (vd &VDoc) gen_json(d doc.Doc) string {\n\tcfg := vd.cfg\n\tmut jw := strings.new_builder(200)\n\tjw.write_string('{\"module_name\":\"${d.head.name}\",')\n\tif d.head.comments.len > 0 && cfg.include_comments {\n\t\tcomments := if cfg.include_examples {\n\t\t\td.head.merge_comments()\n\t\t} else {\n\t\t\td.head.merge_comments_without_examples()\n\t\t}\n\t\tjw.write_string('\"description\":\"${escape(comments)}\",')\n\t}\n\tjw.write_string('\"contents\":')\n\tjw.write_string(json.encode(d.contents.keys().map(d.contents[it])))\n\tjw.write_string(',\"generator\":\"vdoc\",\"time_generated\":\"${d.time_generated.str()}\"}')\n\treturn jw.str()\n}\n\nfn (mut vd VDoc) gen_plaintext(d doc.Doc) string {\n\tcfg := vd.cfg\n\tmut pw := strings.new_builder(200)\n\tif cfg.is_color {\n\t\tcontent_arr := d.head.content.split(' ')\n\t\tpw.writeln('${term.bright_blue(content_arr[0])} ${term.green(content_arr[1])}')\n\t} else {\n\t\tpw.writeln('${d.head.content}')\n\t}\n\tif cfg.include_comments {\n\t\tcomments := if cfg.include_examples {\n\t\t\td.head.merge_comments()\n\t\t} else {\n\t\t\td.head.merge_comments_without_examples()\n\t\t}\n\t\tif comments.trim_space().len > 0 {\n\t\t\tpw.writeln(indent(comments))\n\t\t}\n\t}\n\tpw.writeln('')\n\tvd.write_plaintext_content(d.contents.arr(), mut pw)\n\treturn pw.str()\n}\n\nfn indent(s string) string {\n\treturn '    ' + s.replace('\\n', '\\n    ')\n}\n\nfn dn_to_location(cn doc.DocNode) string {\n\tlocation := '${util.path_styled_for_error_messages(cn.file_path)}:${cn.pos.line_nr + 1:-4}'\n\tif location.len > 24 {\n\t\treturn '${location:-38s} '\n\t}\n\treturn '${location:-24s} '\n}\n\nfn write_location(cn doc.DocNode, mut pw strings.Builder) {\n\tpw.write_string(dn_to_location(cn))\n}\n\nfn (mut vd VDoc) write_plaintext_content(contents []doc.DocNode, mut pw strings.Builder) {\n\tcfg := vd.cfg\n\tfor cn in contents {\n\t\tif cn.content.len > 0 {\n\t\t\tif cfg.show_loc {\n\t\t\t\twrite_location(cn, mut pw)\n\t\t\t}\n\t\t\tif cfg.is_color {\n\t\t\t\tpw.writeln(color_highlight(cn.content, vd.docs[0].table))\n\t\t\t} else {\n\t\t\t\tpw.writeln(cn.content)\n\t\t\t}\n\t\t\tif cn.comments.len > 0 && cfg.include_comments {\n\t\t\t\tcomments := cn.merge_comments_without_examples()\n\t\t\t\tpw.writeln(indent(comments.trim_space()))\n\t\t\t\tif cfg.include_examples {\n\t\t\t\t\texamples := cn.examples()\n\t\t\t\t\tfor ex in examples {\n\t\t\t\t\t\tpw.write_string('    Example: ')\n\t\t\t\t\t\tmut fex := ex\n\t\t\t\t\t\tif ex.index_u8(`\\n`) >= 0 {\n\t\t\t\t\t\t\t// multi-line example\n\t\t\t\t\t\t\tpw.write_u8(`\\n`)\n\t\t\t\t\t\t\tfex = indent(ex)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif cfg.is_color {\n\t\t\t\t\t\t\tfex = color_highlight(fex, vd.docs[0].table)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpw.writeln(fex)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tvd.write_plaintext_content(cn.children, mut pw)\n\t}\n}\n\nfn (mut vd VDoc) render_doc(d doc.Doc, out Output) (string, string) {\n\tname := vd.get_file_name(d.head.name, out)\n\toutput := match out.typ {\n\t\t.none { '' }\n\t\t.html { vd.gen_html(d) }\n\t\t.markdown { vd.gen_markdown(d, true) }\n\t\t.json { vd.gen_json(d) }\n\t\telse { vd.gen_plaintext(d) }\n\t}\n\tcontents := d.contents.arr()\n\tvd.process_all_examples(contents)\n\treturn name, output\n}\n\n// get_file_name returns the final file name from a module name\nfn (vd &VDoc) get_file_name(mod string, out Output) string {\n\tcfg := vd.cfg\n\tmut name := mod\n\tif mod == 'README' {\n\t\tname = 'index'\n\t} else if !cfg.is_multi && !os.is_dir(out.path) {\n\t\tname = os.file_name(out.path)\n\t}\n\tif name == '' {\n\t\tname = 'index'\n\t}\n\tname = name + match out.typ {\n\t\t.html { '.html' }\n\t\t.markdown { '.md' }\n\t\t.json { '.json' }\n\t\telse { '.txt' }\n\t}\n\treturn name\n}\n\nfn (mut vd VDoc) work_processor(work chan ParallelDoc) {\n\tfor {\n\t\tpdoc := <-work or { break }\n\t\tvd.vprintln('> start processing ${pdoc.d.base_path} ...')\n\t\tfile_name, content := vd.render_doc(pdoc.d, pdoc.out)\n\t\tif vd.cfg.output_type != .none {\n\t\t\toutput_path := os.join_path(pdoc.out.path, file_name)\n\t\t\tprintln('Generating ${content.len:8} bytes of ${pdoc.out.typ} in `${output_path}` ...')\n\t\t\tos.write_file(output_path, content) or { panic(err) }\n\t\t}\n\t}\n}\n\nfn (mut vd VDoc) render_parallel(out Output) {\n\tmut work := chan ParallelDoc{cap: vd.docs.len}\n\tfor i in 0 .. vd.docs.len {\n\t\twork <- ParallelDoc{vd.docs[i], out}\n\t}\n\twork.close()\n\n\tvjobs := runtime.nr_jobs()\n\tmut worker_threads := []thread{cap: vjobs}\n\tfor _ in 0 .. vjobs {\n\t\tworker_threads << spawn vd.work_processor(work)\n\t}\n\tworker_threads.wait()\n}\n\nfn (mut vd VDoc) render(out Output) map[string]string {\n\tmut docs := map[string]string{}\n\tfor doc in vd.docs {\n\t\tname, output := vd.render_doc(doc, out)\n\t\tdocs[name] = output.trim_space()\n\t}\n\tvd.vprintln('Rendered: ' + docs.keys().str())\n\treturn docs\n}\n\nfn (vd &VDoc) get_readme(path string) Readme {\n\tmut fname := ''\n\tfor name in ['readme.md', 'README.md'] {\n\t\tif os.exists(os.join_path(path, name)) {\n\t\t\tfname = name\n\t\t\tbreak\n\t\t}\n\t}\n\tif fname == '' {\n\t\tif path.all_after_last(os.path_separator) == 'src' {\n\t\t\tnext_path := path.all_before_last(os.path_separator)\n\t\t\tif next_path != '' && path != next_path && os.is_dir(next_path) {\n\t\t\t\treturn vd.get_readme(next_path)\n\t\t\t}\n\t\t}\n\t\treturn Readme{}\n\t}\n\treadme_path := os.join_path(path, fname)\n\tvd.vprintln('Reading README file from ${readme_path}')\n\tmut readme_contents := os.read_file(readme_path) or { '' }\n\tmut readme_frontmatter := map[string]string{}\n\tif readme_contents.starts_with('---\\n') {\n\t\tif frontmatter_lines_end_idx := readme_contents.index('\\n---\\n') {\n\t\t\tfront_matter_lines := readme_contents#[4..frontmatter_lines_end_idx].trim_space().split_into_lines()\n\t\t\tfor line in front_matter_lines {\n\t\t\t\tx := line.split(': ')\n\t\t\t\tif x.len == 2 {\n\t\t\t\t\treadme_frontmatter[x[0]] = x[1]\n\t\t\t\t}\n\t\t\t}\n\t\t\treadme_contents = readme_contents#[5 + frontmatter_lines_end_idx..]\n\t\t}\n\t}\n\treturn Readme{\n\t\tfrontmatter: readme_frontmatter\n\t\tcontent:     readme_contents\n\t\tpath:        readme_path\n\t}\n}\n\nfn (vd &VDoc) emit_generate_err(err IError) {\n\tcfg := vd.cfg\n\tmut err_msg := err.msg()\n\tif err.code() == 1 {\n\t\tmod_list := get_modules(cfg.input_path)\n\t\tprintln('Available modules:\\n==================')\n\t\tfor mod in mod_list {\n\t\t\tprintln(mod.all_after('vlib/').all_after('modules/').replace('/', '.'))\n\t\t}\n\t\terr_msg += ' Use the `-m` flag when generating docs from a directory that has multiple modules.'\n\t}\n\teprintln(err_msg)\n}\n\nfn (mut vd VDoc) generate_docs_from_file() {\n\tsw := time.new_stopwatch()\n\tdefer {\n\t\tif vd.cfg.show_time {\n\t\t\tprintln('Generation took: ${sw.elapsed().milliseconds()} ms.')\n\t\t}\n\t}\n\n\tcfg := vd.cfg\n\tmut out := Output{\n\t\tpath: cfg.output_path\n\t\ttyp:  cfg.output_type\n\t}\n\tif out.path == '' {\n\t\tif cfg.output_type == .unset {\n\t\t\tout.typ = .ansi\n\t\t} else {\n\t\t\tvd.vprintln('No output path has detected. Using input path instead.')\n\t\t\tout.path = cfg.input_path\n\t\t}\n\t} else if out.typ == .unset {\n\t\tvd.vprintln('Output path detected. Identifying output type..')\n\t\text := os.file_ext(out.path)\n\t\tout.typ = set_output_type_from_str(ext.all_after('.'))\n\t}\n\tif cfg.include_readme && out.typ !in [.html, .ansi, .plaintext, .none] {\n\t\teprintln('vdoc: Including README.md for doc generation is supported on HTML output, or when running directly in the terminal.')\n\t\texit(1)\n\t}\n\tdir_path := if cfg.is_vlib {\n\t\tos.join_path(vroot, 'vlib')\n\t} else if os.is_dir(cfg.input_path) {\n\t\tcfg.input_path\n\t} else {\n\t\tos.dir(cfg.input_path)\n\t}\n\tmanifest_path := if cfg.is_vlib {\n\t\tos.join_path(vroot, 'v.mod')\n\t} else {\n\t\tos.join_path(dir_path, 'v.mod')\n\t}\n\tif os.exists(manifest_path) {\n\t\tvd.vprintln('Reading v.mod info from ${manifest_path}')\n\t\tif manifest := vmod.from_file(manifest_path) {\n\t\t\tvd.manifest = manifest\n\t\t}\n\t} else if cfg.is_vlib {\n\t\tassert false, 'vdoc: manifest does not exist for vlib'\n\t}\n\tif cfg.include_readme || cfg.is_vlib {\n\t\tmut readme_name := 'README'\n\t\treadme := vd.get_readme(dir_path)\n\t\tif page := readme.frontmatter['page'] {\n\t\t\treadme_name = page\n\t\t}\n\t\tcomment := doc.DocComment{\n\t\t\tis_readme:   true\n\t\t\tfrontmatter: readme.frontmatter\n\t\t\ttext:        readme.content\n\t\t}\n\t\tif out.typ == .ansi {\n\t\t\tprintln(markdown.to_plain(readme.content))\n\t\t} else if out.typ == .html && cfg.is_multi {\n\t\t\tvd.docs << doc.Doc{\n\t\t\t\thead:           doc.DocNode{\n\t\t\t\t\tis_readme:   true\n\t\t\t\t\tname:        readme_name\n\t\t\t\t\tfile_path:   readme.path\n\t\t\t\t\tfrontmatter: readme.frontmatter\n\t\t\t\t\tcomments:    [comment]\n\t\t\t\t}\n\t\t\t\ttime_generated: time.now()\n\t\t\t}\n\t\t}\n\t}\n\tdirs := if cfg.is_multi { get_modules(cfg.input_path) } else { [cfg.input_path] }\n\tfor dirpath in dirs {\n\t\tvd.vprintln('Generating ${out.typ} docs for \"${dirpath}\"')\n\t\tmut dcs := doc.generate(dirpath, cfg.pub_only, true, cfg.platform, cfg.symbol_name) or {\n\t\t\t// TODO: use a variable like `src_path := os.join_path(dirpath, 'src')` after `https://github.com/vlang/v/issues/21504`\n\t\t\tif os.exists(os.join_path(dirpath, 'src')) {\n\t\t\t\tdoc.generate(os.join_path(dirpath, 'src'), cfg.pub_only, true, cfg.platform,\n\t\t\t\t\tcfg.symbol_name) or {\n\t\t\t\t\tvd.emit_generate_err(err)\n\t\t\t\t\texit(1)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tvd.emit_generate_err(err)\n\t\t\t\texit(1)\n\t\t\t}\n\t\t}\n\t\tif dcs.contents.len == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif cfg.is_multi || (!cfg.is_multi && cfg.include_readme) {\n\t\t\treadme := vd.get_readme(dirpath)\n\t\t\tcomment := doc.DocComment{\n\t\t\t\tis_readme:   true\n\t\t\t\tfrontmatter: readme.frontmatter\n\t\t\t\ttext:        readme.content\n\t\t\t}\n\t\t\tdcs.head.comments = [comment]\n\t\t\tdcs.head.file_path = readme.path\n\t\t}\n\t\tif cfg.pub_only {\n\t\t\tfor name, dc in dcs.contents {\n\t\t\t\tdcs.contents[name].content = dc.content.all_after('pub ')\n\t\t\t\tfor i, cc in dc.children {\n\t\t\t\t\tdcs.contents[name].children[i].content = cc.content.all_after('pub ')\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tvd.docs << dcs\n\t}\n\tif dirs.len == 0 && cfg.is_multi {\n\t\teprintln('vdoc: -m requires at least 1 module folder')\n\t\texit(1)\n\t}\n\tvd.vprintln('Rendering docs...')\n\tif out.path == '' || out.path == 'stdout' || out.path == '-' {\n\t\tif out.typ == .html {\n\t\t\tvd.render_static_html(out)\n\t\t}\n\t\toutputs := vd.render(out)\n\t\tif outputs.len == 0 {\n\t\t\tif dirs.len == 0 {\n\t\t\t\teprintln('vdoc: No documentation found')\n\t\t\t} else {\n\t\t\t\teprintln('vdoc: No documentation found for ${dirs[0]}')\n\t\t\t}\n\t\t\texit(1)\n\t\t} else {\n\t\t\tfirst := outputs.keys()[0]\n\t\t\tprintln(outputs[first])\n\t\t}\n\t} else {\n\t\tif !os.exists(out.path) {\n\t\t\tos.mkdir_all(out.path) or { panic(err) }\n\t\t} else if !os.is_dir(out.path) {\n\t\t\tout.path = os.real_path('.')\n\t\t}\n\t\tif cfg.is_multi {\n\t\t\tout.path = if cfg.input_path == out.path {\n\t\t\t\tos.join_path(out.path, '_docs')\n\t\t\t} else {\n\t\t\t\tout.path\n\t\t\t}\n\t\t\tif !os.exists(out.path) {\n\t\t\t\tos.mkdir(out.path) or { panic(err) }\n\t\t\t} else {\n\t\t\t\tfor fname in css_js_assets {\n\t\t\t\t\texisting_asset_path := os.join_path(out.path, fname)\n\t\t\t\t\tif os.exists(existing_asset_path) {\n\t\t\t\t\t\tos.rm(existing_asset_path) or { panic(err) }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif out.typ == .html {\n\t\t\tvd.render_static_html(out)\n\t\t}\n\t\tvd.render_parallel(out)\n\t\tif out.typ == .html {\n\t\t\tprintln('Creating search index...')\n\t\t\tvd.collect_search_index(out)\n\t\t\tvd.render_search_index(out)\n\t\t\t// move favicons to target directory\n\t\t\tprintln('Copying favicons...')\n\t\t\tfavicons_path := os.join_path(cfg.theme_dir, 'favicons')\n\t\t\tfavicons := os.ls(favicons_path) or { panic(err) }\n\t\t\tfor favicon in favicons {\n\t\t\t\tfavicon_path := os.join_path(favicons_path, favicon)\n\t\t\t\tdestination_path := os.join_path(out.path, favicon)\n\t\t\t\tos.cp(favicon_path, destination_path) or { panic(err) }\n\t\t\t}\n\t\t\tprintln('Copied ${favicons.len} icons to `${out.path}` .')\n\t\t}\n\t}\n}\n\nfn (vd &VDoc) vprintln(str string) {\n\tif vd.cfg.is_verbose {\n\t\tprintln('vdoc: ${str}')\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/vdoc_file_test.v",
    "content": "// vtest retry: 3\nimport os\nimport rand\nimport term\nimport v.util.vtest\nimport v.util.diff\n\nconst vexe_path = @VEXE\nconst vexe = os.quoted_path(vexe_path)\nconst vroot = os.dir(vexe_path)\nconst should_autofix = os.getenv('VAUTOFIX') != ''\n\nfn test_output() {\n\tos.setenv('VCOLORS', 'never', true)\n\tos.chdir(vroot)!\n\tmut total_fails := 0\n\ttest_files := vtest.filter_vtest_only(os.walk_ext('cmd/tools/vdoc/testdata', '.v'),\n\t\tbasepath: vroot\n\t)\n\tfor path in test_files {\n\t\tmut fails := 0\n\t\tqpath := os.quoted_path(path)\n\t\tpath_no_ext := path.all_before_last('.')\n\t\tprint(path + ' ')\n\t\tfails += check_output('${vexe} doc ${qpath}', path_no_ext + '.out')\n\t\tfails += check_output('${vexe} doc -comments ${qpath}', '${path_no_ext}.unsorted.out',\n\t\t\tshould_sort: false\n\t\t)\n\t\tfails += check_output('${vexe} doc -comments ${qpath}', '${path_no_ext}.comments.out')\n\t\tfails += check_output('${vexe} doc -readme -comments ${qpath}', '${path_no_ext}.readme.comments.out')\n\t\t// test the main 3 different formats:\n\t\tprogram_dir := os.quoted_path(if os.is_dir(path) { path } else { os.dir(path) })\n\t\tfor fmt in ['html', 'ansi', 'text'] {\n\t\t\tfails += check_output('${vexe} doc -no-timestamp -f ${fmt} -o - -html-only-contents -readme -comments ${program_dir}',\n\t\t\t\t'${path_no_ext}.${fmt}')\n\t\t}\n\t\tfails += check_output('${vexe} doc -no-timestamp -f md -o - ${program_dir}', '${path_no_ext}.md')\n\t\tif fails == 0 {\n\t\t\tprintln(term.green('OK'))\n\t\t} else {\n\t\t\ttotal_fails += fails\n\t\t}\n\t\tflush_stdout()\n\t}\n\tassert total_fails == 0\n}\n\nconst small_pure_v_vlib_module = 'bitfield'\n\nfn test_out_path() {\n\t// Work around CI issues covering v doc generation for relative input paths in tmp dir.\n\t// Instead just generate documentation in the v source dir.\n\tif os.getenv('CI') == 'true' {\n\t\tdefault_output_path := os.join_path(vroot, 'vlib', small_pure_v_vlib_module, '_docs')\n\t\tos.execute_opt('${vexe} doc -f html -m vlib/${small_pure_v_vlib_module}')!\n\t\tfinal_html_path := os.join_path(default_output_path, '${small_pure_v_vlib_module}.html')\n\t\tassert os.exists(final_html_path), final_html_path\n\n\t\t// Custom out path (no `_docs` subdir).\n\t\tout_dir := os.join_path(vroot, 'vlib', small_pure_v_vlib_module, 'docs')\n\t\tos.execute_opt('${vexe} doc -f html -m -o ${out_dir} ${small_pure_v_vlib_module}')!\n\t\tout_html_path := os.join_path(out_dir, '${small_pure_v_vlib_module}.html')\n\t\tassert os.exists(out_html_path), out_html_path\n\t\tos.rmdir_all(out_dir) or {}\n\t\tos.rmdir_all(default_output_path) or {}\n\t\treturn\n\t}\n\n\t// Copy a *small* vlib module, that is written in pure V, for the test:\n\ttest_path := os.join_path(os.vtmp_dir(), 'vdoc_test_${rand.ulid()}')\n\ttest_mod_path := os.join_path(test_path, small_pure_v_vlib_module)\n\tos.mkdir_all(test_path)!\n\tdefer {\n\t\tos.chdir(vroot) or {}\n\t\tos.rmdir_all(test_path) or {}\n\t}\n\tos.chdir(test_path)!\n\tmod_path := os.join_path(vroot, 'vlib', small_pure_v_vlib_module)\n\tos.cp_all(mod_path, test_mod_path, true) or {}\n\n\t// Relative input with default output path.\n\tos.execute_opt('${vexe} doc -f html -m ${small_pure_v_vlib_module}')!\n\toutput_path := os.join_path(mod_path, '_docs', '${small_pure_v_vlib_module}.html')\n\tassert os.exists(output_path), output_path\n\n\t// Custom out path (no `_docs` subdir).\n\tout_dir := os.join_path(os.vtmp_dir(), 'docs_test')\n\tdefer {\n\t\tos.rmdir_all(out_dir) or {}\n\t}\n\tos.execute_opt('${vexe} doc -f html -m -o ${out_dir} ${small_pure_v_vlib_module}')!\n\thtml_path := os.join_path(out_dir, '${small_pure_v_vlib_module}.html')\n\tassert os.exists(html_path), html_path\n}\n\nfn print_compare(expected string, found string) {\n\tprintln(term.red('FAIL'))\n\tprintln('============')\n\tif diff_ := diff.compare_text(expected, found) {\n\t\tprintln('diff:')\n\t\tprintln(diff_)\n\t\tprintln('============\\n')\n\t} else {\n\t\tprintln('expected:')\n\t\tprintln(expected)\n\t\tprintln('============')\n\t\tprintln('found:')\n\t\tprintln(found)\n\t\tprintln('============\\n')\n\t}\n}\n\n@[params]\nstruct CheckOutputParams {\n\tshould_sort bool = true\n}\n\nfn check_output(cmd string, out_path string, opts CheckOutputParams) int {\n\tif !os.exists(out_path) {\n\t\treturn 0\n\t}\n\tmut fails := 0\n\tos.setenv('VDOC_SORT', opts.should_sort.str(), true)\n\texpected := os.read_file(out_path) or { panic(err) }.replace('\\r\\n', '\\n').trim_space()\n\tres := os.execute_opt(cmd) or { panic(err) }\n\tfound := res.output.replace('\\r\\n', '\\n').trim_space()\n\tif expected != found {\n\t\tprint_compare(expected, found)\n\t\teprintln('>>>           cmd: VDOC_SORT=${opts.should_sort} ${cmd}')\n\t\teprintln('>>> out_file_path: `${out_path}`')\n\t\teprintln('>>>           fix: VDOC_SORT=${opts.should_sort} ${cmd} > ${out_path}')\n\t\tfails++\n\t}\n\tif should_autofix {\n\t\tos.write_file(out_path, res.output) or {}\n\t}\n\treturn fails\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/vdoc_run_examples_test.v",
    "content": "import os\n\nconst vexe_path = @VEXE\nconst vexe = os.quoted_path(vexe_path)\nconst vroot = os.dir(vexe_path)\n\nfn testsuite_begin() {\n\tos.setenv('VCOLORS', 'never', true)\n\tos.chdir(vroot)!\n}\n\nfn test_check_examples_good() {\n\tcmd := '${vexe} doc -comments -check-examples cmd/tools/vdoc/testdata/run_examples_good/main.v'\n\tprintln('${@METHOD:30} running ${cmd} ...')\n\tres := os.execute(cmd)\n\tassert res.exit_code == 0\n\tassert res.output.contains('module main'), res.output\n\tassert res.output.contains('fn abc()'), res.output\n\tassert res.output.contains(\"abc just prints 'xyz'\"), res.output\n\tassert res.output.contains('and should succeed'), res.output\n\tassert res.output.contains('Example: assert 5 * 5 == 25'), res.output\n}\n\nfn test_check_examples_bad() {\n\tcmd := '${vexe} doc -comments -check-examples cmd/tools/vdoc/testdata/run_examples_bad/main.v'\n\tprintln('${@METHOD:30} running ${cmd} ...')\n\tres := os.execute(cmd)\n\tassert res.exit_code == 0\n\tassert res.output.contains('module main'), res.output\n\tassert res.output.contains('Example: assert 5 * 5 == 77'), res.output\n}\n\nfn test_run_examples_good() {\n\tcmd := '${vexe} doc -comments -unsafe-run-examples cmd/tools/vdoc/testdata/run_examples_good/main.v'\n\tprintln('${@METHOD:30} running ${cmd} ...')\n\tres := os.execute(cmd)\n\tassert res.exit_code == 0\n\tassert res.output.contains('module main'), res.output\n\tassert res.output.contains('fn abc()'), res.output\n\tassert res.output.contains(\"abc just prints 'xyz'\"), res.output\n\tassert res.output.contains('and should succeed'), res.output\n\tassert res.output.contains('Example: assert 5 * 5 == 25'), res.output\n}\n\nfn test_run_examples_bad() {\n\tcmd := '${vexe} doc -comments -unsafe-run-examples cmd/tools/vdoc/testdata/run_examples_bad/main.v'\n\tprintln('${@METHOD:30} running ${cmd} ...')\n\tres := os.execute(cmd)\n\tassert res.exit_code != 0\n\tassert res.output.contains('error in documentation example'), res.output\n\tassert res.output.contains(' left value: 5 * 5 = 25'), res.output\n\tassert res.output.contains('right value: 77'), res.output\n\tassert res.output.contains('V panic: Assertion failed...'), res.output\n\tassert res.output.contains('module main'), res.output\n\tassert res.output.contains('Example: assert 5 * 5 == 77'), res.output\n}\n"
  },
  {
    "path": "cmd/tools/vdoc/vdoc_test.v",
    "content": "// vtest retry: 2\n// vtest build: !windows\nmodule main\n\nimport os\nimport arrays\nimport v.ast\nimport document as doc\nimport markdown\n\nconst vexe_path = @VEXE\nconst vexe_ = os.quoted_path(vexe_path)\nconst tpath = os.join_path(os.vtmp_dir(), 'vod_test_module')\n\nfn testsuite_begin() {\n\tos.rmdir_all(tpath) or {}\n\tos.mkdir_all(tpath)!\n\tos.chdir(tpath)!\n}\n\nfn testsuite_end() {\n\tos.rmdir_all(tpath) or {}\n}\n\nfn test_trim_doc_node_description() {\n\tmod := 'foo'\n\tmut readme := '## Description\n\n`foo` is a module that provides tools and utility functions to assist in working with bar.\nIt also assists with composing and testing baz.'\n\texpected := 'is a module that provides tools and utility functions to assist in working with'\n\tres := trim_doc_node_description(mod, readme).trim_space()\n\tassert res == expected\n\n\treadme = '# Foo\n`foo` is a module that provides tools and utility functions to assist in working with bar.\nIt also assists with composing and testing baz.'\n\tres2 := trim_doc_node_description(mod, readme).trim_space()\n\tassert res2 == res\n}\n\nfn test_ignore_rules() {\n\tos.write_file('.vdocignore', ['pattern1', 'pattern2', '/path1'].join_lines())!\n\tos.mkdir('subdir')!\n\tos.write_file(os.join_path('subdir', '.vdocignore'), ['pattern3', '/path2'].join_lines())!\n\trules := IgnoreRules.get('.')\n\tassert rules.patterns['.'] == ['pattern1', 'pattern2']\n\tassert rules.patterns['./subdir'] == ['pattern3']\n\tassert rules.paths == {\n\t\t'./path1':        true\n\t\t'./subdir/path2': true\n\t}\n}\n\nfn test_get_module_list() {\n\t// For information on leading slash rules, refer to the comments in `IgnoreRules.get`.\n\tignore_rules := ['bravo', '/echo', '/foxtrot/golf', 'hotel.v/', 'india/juliett']\n\tos.write_file('.vdocignore', ignore_rules.join_lines())!\n\n\t/* Create some submodules.\n\tModules inside `testdata` and `tests` directories and modules that\n\tonly contain `_test.v` files should be ignored by default. */\n\t// Modules NOT to ignore.\n\tsubmodules_no_ignore := [\n\t\t'alpha',\n\t\t'alpha_bravo', // test `bravo`\n\t\t'bravo_charly', // test `bravo`\n\t\t'charly',\n\t\t'charly/alpha',\n\t\t'charly/delta', // test `delta` in separate ignore file in `alpha`\n\t\t'charly/echo', // test `/echo`\n\t\t'charly/foxtrot/golf', // test `/foxtrot/golf`\n\t\t'foxtrot',\n\t\t'golf',\n\t\t'hotel', // will include a `hotel.v` file, whose pattern is in the ignore list with a trailing slash\n\t]\n\t// Modules TO ignore.\n\tsubmodules_to_ignore := [\n\t\t'alpha/bravo', // test `bravo`\n\t\t'alpha/delta', // test `delta` in separate ignore file\n\t\t'alpha/india/juliett/kilo', // test `india/juliett`\n\t\t'bravo', // test `bravo`\n\t\t'echo', // test `/echo`\n\t\t'foxtrot/golf', // test `/foxtrot/golf`\n\t\t'hotel.v', // test `hotel.v/`\n\t\t'tests', // test default\n\t\t'testdata', // test default\n\t\t'testdata/foxtrot', // test default\n\t]\n\tfor p in arrays.append(submodules_no_ignore, submodules_to_ignore) {\n\t\tos.mkdir_all(p)!\n\t\tmod_name := p.all_after_last('/')\n\t\tos.write_file(os.join_path(p, '${mod_name}.v'), 'module ${mod_name}')!\n\t}\n\t// Create a module that only contains a `_test.v` file.\n\tos.mkdir('delta')!\n\tos.write_file(os.join_path('delta', 'delta_test.v'), 'module delta')!\n\t// Add a `.vdocignore` file to a submodule.\n\tos.write_file(os.join_path('alpha', '.vdocignore'), 'delta\\n')!\n\n\tmod_list := get_modules(tpath)\n\t// dump(mod_list)\n\tassert mod_list.len == submodules_no_ignore.len\n\tfor m in submodules_no_ignore.map(os.join_path(tpath, it)) {\n\t\tassert m in mod_list\n\t}\n\tfor m in submodules_to_ignore.map(os.join_path(tpath, it)) {\n\t\tassert m !in mod_list\n\t}\n\t// `delta` only contains a `_test.v` file.\n\tassert !mod_list.any(it.contains(os.join_path(tpath, 'delta')))\n}\n\nfn test_html_highlight_escapes_html_tokens() {\n\ttable := ast.new_table()\n\tcode := 'fn main() {\n\t// <h1>owned</h1>\n\tassert 1 < 2\n}'\n\thighlighted := html_highlight(code, table)\n\tassert highlighted.contains('// &lt;h1&gt;owned&lt;/h1&gt;')\n\tassert !highlighted.contains('<h1>owned</h1>')\n\tassert highlighted.contains('<span class=\"token operator\">&lt;</span>')\n}\n\nfn test_get_readme_md_src() {\n\t// a special testcase for `src` dir get_readme\n\t// https://github.com/vlang/v/issues/24232\n\n\tos.mkdir('src')!\n\tos.write_file('v.mod', \"Module {\n        name: 'foobar'\n        description: 'foobar'\n        version: '0.0.0'\n        license: 'MIT'\n        dependencies: []\n}\n\")!\n\tos.write_file('src/foobar.v', 'module foobar\n\n// square calculates the second power of `x`\npub fn square(x int) int {\n        return x * x\n}\n')!\n\tres := os.execute_opt('${vexe_} doc -m src/ -v') or { panic(err) }\n\tassert res.exit_code == 0\n\tassert res.output.contains('square')\n}\n\nfn test_gen_modules_toc_skips_hash_links_for_prefix_only_groups() {\n\tmut vd := VDoc{\n\t\tcfg: Config{\n\t\t\tis_multi: true\n\t\t}\n\t}\n\tvd.docs = [\n\t\tdoc.Doc{\n\t\t\thead: doc.DocNode{\n\t\t\t\tname: 'main'\n\t\t\t}\n\t\t},\n\t\tdoc.Doc{\n\t\t\thead: doc.DocNode{\n\t\t\t\tname: 'db.mysql'\n\t\t\t}\n\t\t},\n\t\tdoc.Doc{\n\t\t\thead: doc.DocNode{\n\t\t\t\tname: 'db.sqlite'\n\t\t\t}\n\t\t},\n\t]\n\ttoc := vd.gen_modules_toc('main')\n\tassert !toc.contains('href=\"#\"')\n\tassert toc.contains('<div class=\"menu-row\"><a>db</a></div>')\n\tassert toc.contains('<li><a href=\"./db.mysql.html\">mysql</a></li>')\n}\n\nfn test_gen_modules_toc_uses_prefix_module_page_when_available() {\n\tmut vd := VDoc{\n\t\tcfg: Config{\n\t\t\tis_multi: true\n\t\t}\n\t}\n\tvd.docs = [\n\t\tdoc.Doc{\n\t\t\thead: doc.DocNode{\n\t\t\t\tname: 'db.sqlite'\n\t\t\t}\n\t\t},\n\t\tdoc.Doc{\n\t\t\thead: doc.DocNode{\n\t\t\t\tname: 'db'\n\t\t\t}\n\t\t},\n\t]\n\ttoc := vd.gen_modules_toc('db')\n\tassert toc.contains('<div class=\"menu-row\"><a href=\"./db.html\">db</a></div>')\n}\n\nfn test_resolve_relative_markdown_link() {\n\tbase := 'https://github.com/vlang/v/blob/master/vlib/net/html/'\n\tassert resolve_relative_markdown_link(base, 'parser_test.v') == 'https://github.com/vlang/v/blob/master/vlib/net/html/parser_test.v'\n\tassert resolve_relative_markdown_link(base, './html_test.v') == 'https://github.com/vlang/v/blob/master/vlib/net/html/html_test.v'\n\tassert resolve_relative_markdown_link(base, '../README.md#usage') == 'https://github.com/vlang/v/blob/master/vlib/net/README.md#usage'\n}\n\nfn test_resolve_relative_markdown_link_keeps_absolute_urls() {\n\tbase := 'https://github.com/vlang/v/blob/master/vlib/net/html/'\n\tassert resolve_relative_markdown_link(base, 'https://vlang.io') == 'https://vlang.io'\n\tassert resolve_relative_markdown_link(base, '/rooted/path') == '/rooted/path'\n\tassert resolve_relative_markdown_link(base, '#local') == '#local'\n}\n\nfn test_markdown_renderer_resolves_relative_links() ! {\n\tbase := 'https://github.com/vlang/v/blob/master/vlib/net/html/'\n\tmut renderer := markdown.HtmlRenderer{\n\t\ttransformer: &MdHtmlCodeHighlighter{\n\t\t\ttable:              ast.new_table()\n\t\t\trelative_link_base: base\n\t\t}\n\t}\n\tout := markdown.render('More examples in [parser](parser_test.v).', mut renderer)!\n\tassert out.contains('<a href=\"https://github.com/vlang/v/blob/master/vlib/net/html/parser_test.v\">')\n}\n"
  },
  {
    "path": "cmd/tools/vdoctor.v",
    "content": "import os\nimport time\nimport term\nimport v.util.version\nimport runtime\nimport encoding.iconv\n\nstruct App {\nmut:\n\treport_lines   []string\n\tcached_cpuinfo map[string]string\n\tvexe           string\n}\n\nfn (mut a App) println(s string) {\n\ta.report_lines << s\n}\n\nfn (mut a App) collect_info() {\n\ta.line('V full version', version.full_v_version(true))\n\ta.line(':-------------------', ':-------------------')\n\n\tmut os_kind := os.user_os()\n\tmut arch_details := []string{}\n\tarch_details << '${runtime.nr_cpus()} cpus'\n\tif runtime.is_32bit() {\n\t\tarch_details << '32bit'\n\t}\n\tif runtime.is_64bit() {\n\t\tarch_details << '64bit'\n\t}\n\tif runtime.is_big_endian() {\n\t\tarch_details << 'big endian'\n\t}\n\tif runtime.is_little_endian() {\n\t\tarch_details << 'little endian'\n\t}\n\tif os_kind == 'macos' {\n\t\tarch_details << a.cmd(command: 'sysctl -n machdep.cpu.brand_string')\n\t}\n\tif os_kind == 'linux' {\n\t\tmut cpu_details := ''\n\t\tif cpu_details == '' {\n\t\t\tcpu_details = a.cpu_info('model name')\n\t\t}\n\t\tif cpu_details == '' {\n\t\t\tcpu_details = a.cpu_info('hardware')\n\t\t}\n\t\tif cpu_details == '' {\n\t\t\tcpu_details = os.uname().machine\n\t\t}\n\t\tarch_details << cpu_details\n\t}\n\tif os_kind == 'windows' {\n\t\tarch_details << a.cmd(\n\t\t\tcommand: 'wmic cpu get name /format:table'\n\t\t\tline:    2\n\t\t)\n\t}\n\n\tmut os_details := ''\n\twsl_check := a.cmd(command: 'cat /proc/sys/kernel/osrelease')\n\tif os_kind == 'linux' {\n\t\tos_details = a.get_linux_os_name()\n\t\tif a.cpu_info('flags').contains('hypervisor') {\n\t\t\tif wsl_check.contains('microsoft') {\n\t\t\t\t// WSL 2 is a Managed VM and Full Linux Kernel\n\t\t\t\t// See https://docs.microsoft.com/en-us/windows/wsl/compare-versions\n\t\t\t\tos_details += ' (WSL 2)'\n\t\t\t} else {\n\t\t\t\tos_details += ' (VM)'\n\t\t\t}\n\t\t}\n\t\t// WSL 1 is NOT a Managed VM and Full Linux Kernel\n\t\t// See https://docs.microsoft.com/en-us/windows/wsl/compare-versions\n\t\tif wsl_check.contains('Microsoft') {\n\t\t\tos_details += ' (WSL)'\n\t\t}\n\t\t// From https://unix.stackexchange.com/a/14346\n\t\tawk_cmd := '[ \"$(awk \\'\\$5==\"/\" {print \\$1}\\' </proc/1/mountinfo)\" != \"$(awk \\'\\$5==\"/\" {print \\$1}\\' </proc/$$/mountinfo)\" ] ; echo \\$?'\n\t\tif a.cmd(command: awk_cmd) == '0' {\n\t\t\tos_details += ' (chroot)'\n\t\t}\n\t} else if os_kind == 'macos' {\n\t\tmut details := []string{}\n\t\tdetails << a.cmd(command: 'sw_vers -productName')\n\t\tdetails << a.cmd(command: 'sw_vers -productVersion')\n\t\tdetails << a.cmd(command: 'sw_vers -buildVersion')\n\t\tos_details = details.join(', ')\n\t} else if os_kind == 'windows' {\n\t\twmic_info := a.cmd(\n\t\t\tcommand: 'wmic os get * /format:value'\n\t\t\tline:    -1\n\t\t)\n\t\tp := a.parse(wmic_info, '=')\n\t\tmut caption, mut build_number, mut os_arch := p['caption'], p['buildnumber'], p['osarchitecture']\n\t\tcaption = iconv.encoding_to_vstring(caption.bytes(), 'ANSI') or { caption }\n\t\tbuild_number = iconv.encoding_to_vstring(build_number.bytes(), 'ANSI') or { build_number }\n\t\tos_arch = iconv.encoding_to_vstring(os_arch.bytes(), 'ANSI') or { os_arch }\n\t\tos_details = '${caption} ${build_number} ${os_arch}'\n\t} else {\n\t\touname := os.uname()\n\t\tos_details = '${ouname.release}, ${ouname.version}'\n\t}\n\ta.line('OS', '${os_kind}, ${os_details}')\n\ta.line('Processor', arch_details.join(', '))\n\ttotal_memory := f32(runtime.total_memory() or { 0 }) / (1024.0 * 1024.0 * 1024.0)\n\tfree_memory := f32(runtime.free_memory() or { 0 }) / (1024.0 * 1024.0 * 1024.0)\n\tif total_memory != 0 && free_memory != 0 {\n\t\ta.line('Memory', '${free_memory:.2}GB/${total_memory:.2}GB')\n\t} else {\n\t\ta.line('Memory', 'N/A')\n\t}\n\n\ta.line('', '')\n\tvexe := a.vexe\n\tvroot := os.dir(vexe)\n\tvmodules := os.vmodules_dir()\n\tvtmp_dir := os.vtmp_dir()\n\tgetwd := os.getwd()\n\tos.chdir(vroot) or {}\n\ta.line('V executable', vexe)\n\ta.line('V last modified time', time.unix(os.file_last_mod_unix(vexe)).str())\n\ta.line('', '')\n\ta.line2('V home dir', diagnose_dir(vroot), vroot)\n\ta.line2('VMODULES', diagnose_dir(vmodules), vmodules)\n\ta.line2('VTMP', diagnose_dir(vtmp_dir), vtmp_dir)\n\ta.line2('Current working dir', diagnose_dir(getwd), getwd)\n\ta.line('', '')\n\n\ta.line_env('VFLAGS')\n\ta.line_env('CFLAGS')\n\ta.line_env('LDFLAGS')\n\n\ta.line('Git version', a.cmd(command: 'git --version'))\n\ta.line('V git status', a.git_info())\n\ta.line('.git/config present', os.is_file('.git/config').str())\n\ta.line('', '')\n\ta.line('cc version', a.cmd(command: 'cc --version'))\n\tif os_kind == 'openbsd' {\n\t\ta.line('gcc version', a.cmd(command: 'egcc --version'))\n\t} else {\n\t\ta.line('gcc version', a.cmd(command: 'gcc --version'))\n\t}\n\ta.line('clang version', a.cmd(command: 'clang --version'))\n\tif os_kind == 'windows' {\n\t\t// Check for MSVC on windows\n\t\ta.line('msvc version', a.cmd(command: 'cl'))\n\t}\n\ta.report_tcc_version('thirdparty/tcc')\n\ta.line('emcc version', a.cmd(command: 'emcc --version'))\n\tif os_kind != 'openbsd' && os_kind != 'freebsd' {\n\t\ta.line('glibc version', a.cmd(command: 'ldd --version'))\n\t} else {\n\t\ta.line('glibc version', 'N/A')\n\t}\n}\n\nstruct CmdConfig {\n\tline    int\n\tcommand string\n}\n\nfn (mut a App) cmd(c CmdConfig) string {\n\tx := os.execute(c.command)\n\tos_kind := os.user_os()\n\tif x.exit_code < 0 || x.exit_code == 127 || (os_kind == 'windows' && x.exit_code == 1) {\n\t\treturn 'N/A'\n\t}\n\tif x.exit_code == 0 {\n\t\tif c.line < 0 {\n\t\t\treturn x.output\n\t\t}\n\t\toutput := x.output.split_into_lines()\n\t\tif output.len > 0 && output.len > c.line {\n\t\t\treturn output[c.line]\n\t\t}\n\t}\n\treturn 'Error: ${x.output}'\n}\n\nfn (mut a App) line(label string, value string) {\n\ta.println('|${label:-20}|${term.colorize(term.bold, value)}')\n}\n\nfn (mut a App) line2(label string, value string, value2 string) {\n\ta.println('|${label:-20}|${term.colorize(term.bold, value)}, value: ${term.colorize(term.bold,\n\t\tvalue2)}')\n}\n\nfn (mut a App) line_env(env_var string) {\n\tvalue := os.getenv(env_var)\n\tif value != '' {\n\t\ta.line('env ${env_var}', '\"${value}\"')\n\t}\n}\n\nfn (app &App) parse(config string, sep string) map[string]string {\n\tmut m := map[string]string{}\n\tlines := config.split_into_lines()\n\tfor line in lines {\n\t\tsline := line.trim_space()\n\t\tif sline.len == 0 || sline[0] == `#` {\n\t\t\tcontinue\n\t\t}\n\t\tx := sline.split(sep)\n\t\tif x.len < 2 {\n\t\t\tcontinue\n\t\t}\n\t\tm[x[0].trim_space().to_lower()] = x[1].trim_space().trim('\"')\n\t}\n\treturn m\n}\n\nfn (mut a App) get_linux_os_name() string {\n\tif os.is_file('/etc/os-release') {\n\t\tif lines := os.read_file('/etc/os-release') {\n\t\t\tvals := a.parse(lines, '=')\n\t\t\tif vals['PRETTY_NAME'] != '' {\n\t\t\t\treturn vals['PRETTY_NAME']\n\t\t\t}\n\t\t}\n\t}\n\tif !a.cmd(command: 'type lsb_release').starts_with('Error') {\n\t\treturn a.cmd(command: 'lsb_release -d -s')\n\t}\n\tif os.is_file('/proc/version') {\n\t\treturn a.cmd(command: 'cat /proc/version')\n\t}\n\touname := os.uname()\n\treturn '${ouname.release}, ${ouname.version}'\n}\n\nfn (mut a App) cpu_info(key string) string {\n\tif a.cached_cpuinfo.len > 0 {\n\t\treturn a.cached_cpuinfo[key]\n\t}\n\tinfo := os.execute('cat /proc/cpuinfo')\n\tif info.exit_code != 0 {\n\t\treturn '`cat /proc/cpuinfo` could not run'\n\t}\n\ta.cached_cpuinfo = a.parse(info.output, ':')\n\treturn a.cached_cpuinfo[key]\n}\n\nfn (mut a App) git_info() string {\n\t// Check if in a Git repository\n\tx := os.execute('git rev-parse --is-inside-work-tree')\n\tif x.exit_code != 0 || x.output.trim_space() != 'true' {\n\t\treturn 'N/A'\n\t}\n\tmut out := a.cmd(command: 'git -C . describe --abbrev=8 --dirty --always --tags').trim_space()\n\tos.execute('git -C . remote add V_REPO https://github.com/vlang/v') // ignore failure (i.e. remote exists)\n\tif '-skip-github' !in os.args {\n\t\tos.execute('${os.quoted_path(a.vexe)} timeout 5.1 \"git -C . fetch V_REPO\"') // usually takes ~0.6s; 5 seconds should be enough for even the slowest networks\n\t}\n\tcommit_count := a.cmd(command: 'git rev-list @{0}...V_REPO/master --right-only --count').int()\n\tif commit_count > 0 {\n\t\tout += ' (${commit_count} commit(s) behind V master)'\n\t}\n\treturn out\n}\n\nfn (mut a App) report_tcc_version(tccfolder string) {\n\tcmd := os.join_path(tccfolder, 'tcc.exe') + ' -v'\n\tx := os.execute(cmd)\n\tif x.exit_code == 0 {\n\t\ta.line('tcc version', '${x.output.trim_space()}')\n\t} else {\n\t\ta.line('tcc version', 'N/A')\n\t}\n\tif !os.is_file(os.join_path(tccfolder, '.git', 'config')) {\n\t\ta.line('tcc git status', 'N/A')\n\t} else {\n\t\ttcc_branch_name := a.cmd(\n\t\t\tcommand: 'git -C ${os.quoted_path(tccfolder)} rev-parse --abbrev-ref HEAD'\n\t\t)\n\t\ttcc_commit := a.cmd(\n\t\t\tcommand: 'git -C ${os.quoted_path(tccfolder)} describe --abbrev=8 --dirty --always --tags'\n\t\t)\n\t\ta.line('tcc git status', '${tcc_branch_name} ${tcc_commit}')\n\t}\n}\n\nfn (mut a App) report_info() {\n\tfor x in a.report_lines {\n\t\tprintln(x)\n\t}\n}\n\nfn is_writable_dir(path string) bool {\n\tos.ensure_folder_is_writable(path) or { return false }\n\treturn true\n}\n\nfn diagnose_dir(path string) string {\n\tmut diagnostics := []string{}\n\tif !is_writable_dir(path) {\n\t\tdiagnostics << 'NOT writable'\n\t}\n\tif path.contains(' ') {\n\t\tdiagnostics << 'contains spaces'\n\t}\n\tpath_non_ascii_runes := path.runes().filter(it > 255)\n\tif path_non_ascii_runes.len > 0 {\n\t\tdiagnostics << 'contains these non ASCII characters: ${path_non_ascii_runes}'\n\t}\n\tif diagnostics.len == 0 {\n\t\tdiagnostics << 'OK'\n\t}\n\treturn diagnostics.join(', ')\n}\n\nfn main() {\n\tmut app := App{}\n\tapp.vexe = os.getenv('VEXE')\n\tapp.collect_info()\n\tapp.report_info()\n}\n"
  },
  {
    "path": "cmd/tools/vdownload.v",
    "content": "import os\nimport log\nimport time\nimport flag\nimport net.http\nimport crypto.sha1\nimport crypto.sha256\nimport crypto.sha3\n\nstruct Context {\nmut:\n\tshow_help           bool\n\tshow_sha1           bool\n\tshow_sha256         bool\n\tshow_sha3_256       bool\n\ttarget_folder       string\n\toutput              string\n\tcontinue_on_failure bool\n\tretries             int\n\tdelay               time.Duration\n\turls                []string\n\tshould_run          bool\n\tdelete_after_run    bool\n}\n\nconst vexe = os.real_path(os.getenv_opt('VEXE') or { @VEXE })\n\nfn main() {\n\tlog.use_stdout()\n\tmut ctx := Context{}\n\tmut fp := flag.new_flag_parser(os.args#[1..])\n\tfp.application(os.file_name(os.executable()))\n\tfp.version('0.0.1')\n\tfp.description('Download files from http/https servers, given their URLs.')\n\tfp.arguments_description('URL1 URL2 ...')\n\tfp.skip_executable()\n\tfp.limit_free_args_to_at_least(1)!\n\tctx.show_help = fp.bool('help', `h`, false, 'Show this help screen.')\n\tctx.target_folder = fp.string('target-folder', `t`, '.', 'The target folder, where the file will be stored. It will be created, if it does not exist. Default is current folder.')\n\tctx.output = fp.string('output', `o`, '', 'Write output to the given file, instead of inferring it from the final part of the URL. All intermediate folders will be created, if they do not exist.')\n\tctx.show_sha1 = fp.bool('sha1', `1`, false, 'Show the SHA1 hash of the downloaded file.')\n\tctx.show_sha256 = fp.bool('sha256', `2`, false, 'Show the SHA256 hash of the downloaded file.')\n\tctx.show_sha3_256 = fp.bool('sha3-256', `3`, false, 'Show the SHA3-256 (Keccak) hash of the downloaded file.')\n\tctx.continue_on_failure = fp.bool('continue', `c`, false, 'Continue on download failures. If you download 5 URLs, and several of them fail, continue without error. False by default.')\n\tctx.retries = fp.int('retries', `r`, 10, 'Number of retries, when an URL fails to download. The default is 10.')\n\tctx.delay = time.Duration(u64(fp.float('delay', `d`, 1.0, 'Delay in seconds, after each retry. The default is 1 second.') * time.second))\n\tctx.should_run = fp.bool('run', `R`, false, 'Run, after the script/program is completely downloaded.')\n\tctx.delete_after_run = fp.bool('delete-after-run', `D`, false, 'Delete the downloaded script/program, after it has been run.')\n\tif ctx.show_help {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\tctx.urls = fp.finalize() or {\n\t\teprintln('Error: ${err}')\n\t\texit(1)\n\t}\n\tif ctx.target_folder != '.' {\n\t\tctx.target_folder = ctx.target_folder.replace('\\\\', '/')\n\t\tos.mkdir_all(ctx.target_folder) or {\n\t\t\teprintln('Can not create target folder `${ctx.target_folder}` . Error: ${err}.')\n\t\t\texit(1)\n\t\t}\n\t\tos.chdir(ctx.target_folder)!\n\t}\n\tif ctx.output != '' {\n\t\todir := os.dir(ctx.output)\n\t\tos.mkdir_all(odir) or {}\n\t}\n\tsw := time.new_stopwatch()\n\tmut errors := 0\n\tmut downloaded := 0\n\tdownloader := if os.is_atty(1) > 0 {\n\t\t&http.Downloader(http.TerminalStreamingDownloader{})\n\t} else {\n\t\t&http.Downloader(http.SilentStreamingDownloader{})\n\t}\n\tfor idx, url in ctx.urls {\n\t\tfname := if ctx.output != '' { ctx.output } else { url.all_after_last('/') }\n\t\tfpath := if os.is_abs_path(fname) { fname } else { '${ctx.target_folder}/${fname}' }\n\t\tmut file_errors := 0\n\t\tlog.info('Downloading [${idx + 1}/${ctx.urls.len}] from url: ${url} to ${fpath} ...')\n\t\tfor retry in 0 .. ctx.retries {\n\t\t\thttp.download_file_with_progress(url, fname, downloader: downloader) or {\n\t\t\t\tlog.error('    retry ${retry + 1}/${ctx.retries}, failed downloading from url: ${url}. Error: ${err}.')\n\t\t\t\tfile_errors++\n\t\t\t\ttime.sleep(ctx.delay)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdownloaded++\n\t\t\tbreak\n\t\t}\n\t\tif file_errors == ctx.retries {\n\t\t\tlog.error('Failed to download from url: ${url}.')\n\t\t\terrors++\n\t\t\tif ctx.continue_on_failure {\n\t\t\t\tcontinue\n\t\t\t} else {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tfstat := os.stat(fname)!\n\t\tlog.info(' Finished downloading file: ${fpath} .')\n\t\tlog.info('                      size: ${fstat.size} bytes')\n\n\t\tif ctx.should_run {\n\t\t\trun_cmd := '${os.quoted_path(vexe)} run ${os.quoted_path(fpath)}'\n\t\t\tlog.info(' Executing: ${run_cmd}')\n\t\t\tos.system(run_cmd)\n\t\t}\n\t\tif ctx.delete_after_run {\n\t\t\tlog.info(' Removing: ${fpath}')\n\t\t\tos.rm(fpath) or {}\n\t\t}\n\t\tif !ctx.show_sha256 && !ctx.show_sha1 && !ctx.show_sha3_256 {\n\t\t\tcontinue\n\t\t}\n\t\tfbytes := os.read_bytes(fname)!\n\t\tif ctx.show_sha1 {\n\t\t\tmut digest1 := sha1.new()\n\t\t\tdigest1.write(fbytes)!\n\t\t\tmut sum1 := digest1.sum([])\n\t\t\thash1 := sum1.hex()\n\t\t\tlog.info('                      SHA1: ${hash1}')\n\t\t}\n\t\tif ctx.show_sha256 {\n\t\t\tmut digest256 := sha256.new()\n\t\t\tdigest256.write(fbytes)!\n\t\t\tmut sum256 := digest256.sum([])\n\t\t\thash256 := sum256.hex()\n\t\t\tlog.info('                    SHA256: ${hash256}')\n\t\t}\n\t\tif ctx.show_sha3_256 {\n\t\t\thash3_256 := sha3.sum256(fbytes).hex()\n\t\t\tlog.info('                  SHA3-256: ${hash3_256}')\n\t\t}\n\t}\n\tprintln('Downloaded: ${downloaded} file(s) . Elapsed time: ${sw.elapsed()} . Errors: ${errors} .')\n\tif !ctx.continue_on_failure && errors > 0 {\n\t\texit(1)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vfmt.v",
    "content": "// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nmodule main\n\nimport os\nimport os.cmdline\nimport rand\nimport term\nimport v.ast\nimport v.pref\nimport v.fmt\nimport v.util\nimport v.util.diff\nimport v.parser\nimport v.help\n\nstruct FormatOptions {\n\tis_l       bool\n\tis_c       bool // Note: This refers to the '-c' fmt flag, NOT the C backend\n\tis_w       bool\n\tis_diff    bool\n\tis_verbose bool\n\tis_debug   bool\n\tis_noerror bool\n\tis_verify  bool // exit(1) if the file is not vfmt'ed\n\tis_worker  bool // true *only* in the worker processes. Note: workers can crash.\n\tis_backup  bool // make a `file.v.bak` copy *before* overwriting a `file.v` in place with `-w`\n\tin_process bool // do not fork a worker process; potentially faster, but more prone to crashes for invalid files\n\tis_new_int bool // Forcefully cast the `int` type in @[translated] modules or in the definition of `C.func` to the `i32` type.\nmut:\n\tdiff_cmd string // filled in when -diff or -verify is passed\n}\n\nconst formatted_file_token = '\\@\\@\\@' + 'FORMATTED_FILE: '\nconst vtmp_folder = os.vtmp_dir()\nconst term_colors = term.can_show_color_on_stderr()\n\nfn main() {\n\t// if os.getenv('VFMT_ENABLE') == '' {\n\t// eprintln('v fmt is disabled for now')\n\t// exit(1)\n\t// }\n\ttoolexe := os.executable()\n\tutil.set_vroot_folder(os.dir(os.dir(os.dir(toolexe))))\n\targs := util.join_env_vflags_and_os_args()\n\tmut foptions := FormatOptions{\n\t\tis_c:       '-c' in args\n\t\tis_l:       '-l' in args\n\t\tis_w:       '-w' in args\n\t\tis_diff:    '-diff' in args\n\t\tis_verbose: '-verbose' in args || '--verbose' in args\n\t\tis_worker:  '-worker' in args\n\t\tis_debug:   '-debug' in args\n\t\tis_noerror: '-noerror' in args\n\t\tis_verify:  '-verify' in args\n\t\tis_backup:  '-backup' in args\n\t\tin_process: '-inprocess' in args\n\t\tis_new_int: '-new_int' in args\n\t}\n\tif term_colors {\n\t\tos.setenv('VCOLORS', 'always', true)\n\t}\n\tfoptions.vlog('vfmt foptions: ${foptions}')\n\tif foptions.is_worker {\n\t\t// -worker should be added by a parent vfmt process.\n\t\t// We launch a sub process for each file because\n\t\t// the v compiler can do an early exit if it detects\n\t\t// a syntax error, but we want to process ALL passed\n\t\t// files if possible.\n\t\tfoptions.format_file(cmdline.option(args, '-worker', ''))\n\t\texit(0)\n\t}\n\t// we are NOT a worker at this stage, i.e. we are a parent vfmt process\n\tpossible_files := cmdline.only_non_options(cmdline.options_after(args, ['fmt']))\n\tif foptions.is_verbose {\n\t\teprintln('vfmt toolexe: ${toolexe}')\n\t\teprintln('vfmt args: ' + os.args.str())\n\t\teprintln('vfmt env_vflags_and_os_args: ' + args.str())\n\t\teprintln('vfmt possible_files: ' + possible_files.str())\n\t}\n\tfiles := util.find_all_v_files(possible_files) or {\n\t\tverror(err.msg())\n\t\treturn\n\t}\n\tif os.is_atty(0) == 0 && files.len == 0 {\n\t\tfoptions.format_pipe()\n\t\texit(0)\n\t}\n\tif files.len == 0 || '-help' in args || '--help' in args {\n\t\thelp.print_and_exit('fmt')\n\t}\n\tmut cli_args_no_files := []string{}\n\tfor idx, a in os.args {\n\t\tif idx == 0 {\n\t\t\tcli_args_no_files << os.quoted_path(a)\n\t\t\tcontinue\n\t\t}\n\t\tif a !in files {\n\t\t\tcli_args_no_files << a\n\t\t}\n\t}\n\tmut errors := 0\n\tmut has_internal_error := false\n\tmut prefs := setup_preferences()\n\tfor file in files {\n\t\tfpath := os.real_path(file)\n\t\tif foptions.is_verify && foptions.in_process {\n\t\t\t// For a small amount of files, it is faster to process\n\t\t\t// everything directly in the same process, single threaded,\n\t\t\t// when vfmt is compiled with `-gc none`:\n\t\t\tif !foptions.verify_file(prefs, fpath) {\n\t\t\t\tprintln(\"${file} is not vfmt'ed\")\n\t\t\t\terrors++\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tmut worker_command_array := cli_args_no_files.clone()\n\t\tworker_command_array << ['-worker', util.quote_path(fpath)]\n\t\tworker_cmd := worker_command_array.join(' ')\n\t\tfoptions.vlog('vfmt worker_cmd: ${worker_cmd}')\n\t\tworker_result := os.execute(worker_cmd)\n\t\t// Guard against a possibly crashing worker process.\n\t\tif worker_result.exit_code != 0 {\n\t\t\teprintln(worker_result.output)\n\t\t\tif worker_result.exit_code == 1 {\n\t\t\t\teprintln('Internal vfmt error while formatting file: ${file}.')\n\t\t\t\thas_internal_error = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\terrors++\n\t\t\tcontinue\n\t\t}\n\t\tif worker_result.output.len > 0 {\n\t\t\tif worker_result.output.contains(formatted_file_token) {\n\t\t\t\twresult := worker_result.output.split(formatted_file_token)\n\t\t\t\tformatted_warn_errs := wresult[0]\n\t\t\t\tformatted_file_path := wresult[1].trim_right('\\n\\r')\n\t\t\t\tfoptions.post_process_file(fpath, formatted_file_path) or { errors = errors + 1 }\n\t\t\t\tif formatted_warn_errs.len > 0 {\n\t\t\t\t\teprintln(formatted_warn_errs)\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\terrors++\n\t}\n\tecode := if has_internal_error { 5 } else { 0 }\n\tif errors > 0 {\n\t\tif !foptions.is_diff {\n\t\t\teprintln('Encountered a total of: ${errors} formatting errors.')\n\t\t}\n\t\tmatch true {\n\t\t\tfoptions.is_noerror { exit(0 + ecode) }\n\t\t\tfoptions.is_verify { exit(1 + ecode) }\n\t\t\tfoptions.is_c { exit(2 + ecode) }\n\t\t\telse { exit(1 + ecode) }\n\t\t}\n\t}\n\texit(ecode)\n}\n\nfn (foptions &FormatOptions) verify_file(prefs &pref.Preferences, fpath string) bool {\n\tfcontent := foptions.formated_content_from_file(prefs, fpath)\n\tcontent := os.read_file(fpath) or { return false }\n\treturn fcontent == content\n}\n\nfn setup_preferences() &pref.Preferences {\n\tmut prefs := pref.new_preferences()\n\tprefs.is_fmt = true\n\tprefs.skip_warnings = true\n\treturn prefs\n}\n\nfn setup_preferences_and_table() (&pref.Preferences, &ast.Table) {\n\treturn setup_preferences(), ast.new_table()\n}\n\nfn (foptions &FormatOptions) vlog(msg string) {\n\tif foptions.is_verbose {\n\t\teprintln(msg)\n\t}\n}\n\nfn (foptions &FormatOptions) formated_content_from_file(prefs &pref.Preferences, file string) string {\n\tmut table := ast.new_table()\n\tfile_ast := parser.parse_file(file, mut table, .parse_comments, prefs)\n\ttable.new_int = foptions.is_new_int\n\tformated_content := fmt.fmt(file_ast, mut table, prefs, foptions.is_debug)\n\treturn formated_content\n}\n\nfn (foptions &FormatOptions) format_file(file string) {\n\tfile_name := os.file_name(file)\n\tulid := rand.ulid()\n\tvfmt_output_path := os.join_path(vtmp_folder, 'vfmt_${ulid}_${file_name}')\n\tif file.contains('_vfmt_off') {\n\t\tos.cp(file, vfmt_output_path) or { panic(err) }\n\t\tfoptions.vlog('format_file copied the file ${file} as it was, 1:1, since its name contains `_vfmt_off`.')\n\t\teprintln('${formatted_file_token}${vfmt_output_path}')\n\t\treturn\n\t}\n\tfoptions.vlog('vfmt2 running fmt.fmt over file: ${file}')\n\tprefs, mut table := setup_preferences_and_table()\n\tfile_ast := parser.parse_file(file, mut table, .parse_comments, prefs)\n\t// checker.new_checker(table, prefs).check(file_ast)\n\ttable.new_int = foptions.is_new_int\n\tformatted_content := fmt.fmt(file_ast, mut table, prefs, foptions.is_debug)\n\tos.write_file(vfmt_output_path, formatted_content) or { panic(err) }\n\tfoptions.vlog('fmt.fmt worked and ${formatted_content.len} bytes were written to ${vfmt_output_path} .')\n\teprintln('${formatted_file_token}${vfmt_output_path}')\n}\n\nfn (foptions &FormatOptions) format_pipe() {\n\tfoptions.vlog('vfmt2 running fmt.fmt over stdin')\n\tprefs, mut table := setup_preferences_and_table()\n\tinput_text := os.get_raw_lines_joined()\n\tfile_ast := parser.parse_text(input_text, '', mut table, .parse_comments, prefs)\n\t// checker.new_checker(table, prefs).check(file_ast)\n\ttable.new_int = foptions.is_new_int\n\tformatted_content := fmt.fmt(file_ast, mut table, prefs, foptions.is_debug,\n\t\tsource_text: input_text\n\t)\n\tprint(formatted_content)\n\tflush_stdout()\n\tfoptions.vlog('fmt.fmt worked and ${formatted_content.len} bytes were written to stdout.')\n}\n\nfn print_compiler_options(compiler_params &pref.Preferences) {\n\teprintln('         os: ' + compiler_params.os.str())\n\teprintln('  ccompiler: ${compiler_params.ccompiler}')\n\teprintln('       path: ${compiler_params.path} ')\n\teprintln('   out_name: ${compiler_params.out_name} ')\n\teprintln('      vroot: ${compiler_params.vroot} ')\n\teprintln('lookup_path: ${compiler_params.lookup_path} ')\n\teprintln('   out_name: ${compiler_params.out_name} ')\n\teprintln('     cflags: ${compiler_params.cflags} ')\n\teprintln('    is_test: ${compiler_params.is_test} ')\n\teprintln('  is_script: ${compiler_params.is_script} ')\n}\n\nfn (mut foptions FormatOptions) post_process_file(file string, formatted_file_path string) ! {\n\tif formatted_file_path == '' {\n\t\treturn\n\t}\n\tfc := os.read_file(file) or {\n\t\teprintln('File ${file} could not be read')\n\t\treturn\n\t}\n\tformatted_fc := os.read_file(formatted_file_path) or {\n\t\teprintln('File ${formatted_file_path} could not be read')\n\t\treturn\n\t}\n\tis_formatted_different := fc != formatted_fc\n\tif foptions.is_diff {\n\t\tif !is_formatted_different {\n\t\t\treturn\n\t\t}\n\t\tprintln(diff.compare_files(file, formatted_file_path)!)\n\t\treturn error('')\n\t}\n\tif foptions.is_verify {\n\t\tif !is_formatted_different {\n\t\t\treturn\n\t\t}\n\t\tprintln(\"${file} is not vfmt'ed\")\n\t\treturn error('')\n\t}\n\tif foptions.is_c {\n\t\tif is_formatted_different {\n\t\t\teprintln('File is not formatted: ${file}')\n\t\t\treturn error('')\n\t\t}\n\t\treturn\n\t}\n\tif foptions.is_l {\n\t\tif is_formatted_different {\n\t\t\teprintln('File needs formatting: ${file}')\n\t\t}\n\t\treturn\n\t}\n\tif foptions.is_w {\n\t\tif is_formatted_different {\n\t\t\tif foptions.is_backup {\n\t\t\t\tfile_bak := '${file}.bak'\n\t\t\t\tos.cp(file, file_bak) or {}\n\t\t\t}\n\t\t\tmut perms_to_restore := u32(0)\n\t\t\t$if !windows {\n\t\t\t\tfm := os.inode(file)\n\t\t\t\tperms_to_restore = fm.bitmask()\n\t\t\t}\n\t\t\tos.mv_by_cp(formatted_file_path, file) or { panic(err) }\n\t\t\t$if !windows {\n\t\t\t\tos.chmod(file, int(perms_to_restore)) or { panic(err) }\n\t\t\t}\n\t\t\teprintln('Reformatted file: ${file}')\n\t\t} else {\n\t\t\teprintln('Already formatted file: ${file}')\n\t\t}\n\t\treturn\n\t}\n\tprint(formatted_fc)\n\tflush_stdout()\n}\n\nfn read_source_lines(file string) ![]string {\n\tsource_lines := os.read_lines(file) or { return error('can not read ${file}') }\n\treturn source_lines\n}\n\n@[noreturn]\nfn verror(s string) {\n\tutil.verror('vfmt error', s)\n}\n\nfn (f FormatOptions) str() string {\n\treturn\n\t\t'FormatOptions{ is_l: ${f.is_l}, is_w: ${f.is_w}, is_diff: ${f.is_diff}, is_verbose: ${f.is_verbose},' +\n\t\t' is_worker: ${f.is_worker}, is_debug: ${f.is_debug}, is_noerror: ${f.is_noerror},' +\n\t\t' is_verify: ${f.is_verify}\" }'\n}\n"
  },
  {
    "path": "cmd/tools/vgit-fmt-hook.v",
    "content": "import os\nimport crypto.sha256\n\nconst vexe = os.getenv_opt('VEXE') or { panic('missing VEXE env variable') }\nconst vroot = os.to_slash(os.real_path(os.dir(vexe)))\nconst horiginal = os.to_slash(os.join_path(vroot, 'cmd/tools/git_pre_commit_hook.vsh'))\nconst shoriginal = os.join_path(os.vtmp_dir(), 'git_pre_commit_hook.sh')\n\nfn get_hook_target(git_folder string) string {\n\treturn os.to_slash(os.join_path(git_folder, 'hooks/pre-commit'))\n}\n\nfn main() {\n\t// On OS without support for 'env -S', generate shell script\n\t// to run cmd/tools/git_pre_commit_hook.vsh\n\t// TODO: detect other OS (BusyBox) without support for 'env -S'\n\t$if openbsd {\n\t\tos.write_file(shoriginal, '#!/bin/sh\\nv run ${horiginal}') or {\n\t\t\teprintln('unable to write shell script ${shoriginal}')\n\t\t\texit(1)\n\t\t}\n\t\tos.chmod(shoriginal, 0o755)!\n\t}\n\tgit_folder := find_nearest_top_level_folder_with_a_git_subfolder(os.getwd()) or {\n\t\teprintln('This command has to be run inside a Git repository.')\n\t\texit(0)\n\t}\n\tos.chdir(git_folder)!\n\thtarget := get_hook_target(git_folder)\n\tcmd := os.args[2] or { 'status' }\n\tmatch cmd {\n\t\t'status' {\n\t\t\tcmd_status(htarget)\n\t\t}\n\t\t'install' {\n\t\t\tcmd_install(htarget)\n\t\t}\n\t\t'remove' {\n\t\t\tcmd_remove(htarget)\n\t\t}\n\t\telse {\n\t\t\teprintln('Unknown command `${cmd}`. Known commands are: `status`, `install` or `remove`')\n\t\t\texit(1)\n\t\t}\n\t}\n}\n\nfn cmd_status(htarget string) {\n\treport_status(htarget, true)\n}\n\nfn cmd_install(htarget string) {\n\tif report_status(htarget, false) {\n\t\treturn\n\t}\n\tprintln('> Installing the newest version of ${horiginal} over ${htarget} ...')\n\t$if openbsd {\n\t\tos.cp(shoriginal, htarget) or { err_exit('failed to copy to ${htarget}') }\n\t} $else {\n\t\tos.cp(horiginal, htarget) or { err_exit('failed to copy to ${htarget}') }\n\t}\n\tprintln('> Done.')\n}\n\nfn cmd_remove(htarget string) {\n\treport_status(htarget, false)\n\tif !os.exists(htarget) {\n\t\terr_exit('file ${htarget} has been removed already')\n\t}\n\tprintln('> Removing ${htarget} ...')\n\tos.rm(htarget) or { err_exit('failed to remove ${htarget}') }\n\tprintln('> Done.')\n}\n\n// Returns true if pre-commit Git hook already exists and identical to VSH script\nfn report_status(htarget string, show_instructions bool) bool {\n\tmut original := ''\n\t$if openbsd {\n\t\toriginal = shoriginal\n\t} $else {\n\t\toriginal = horiginal\n\t}\n\tostat := os.stat(original) or { os.Stat{} }\n\ttstat := os.stat(htarget) or { os.Stat{} }\n\tohash := hash_file(original) or { '' }\n\tthash := hash_file(htarget) or { '' }\n\tif os.exists(htarget) && os.is_file(htarget) {\n\t\tprintln('>   CURRENT git repo pre-commit hook: size: ${tstat.size:6} bytes, sha256: ${thash}, ${htarget}')\n\t} else {\n\t\tprintln('>   CURRENT git repo pre-commit hook: missing ${htarget}')\n\t}\n\tif os.exists(original) && os.is_file(original) {\n\t\tprintln('> Main V repo pre-commit hook script: size: ${ostat.size:6} bytes, sha256: ${ohash}, ${original}')\n\t}\n\tif ohash == thash {\n\t\tprintln('> Both files are exactly the same.')\n\t\tif show_instructions {\n\t\t\tshow_msg_about_removing(htarget)\n\t\t}\n\t\treturn true\n\t}\n\tprintln('> Files have different hashes.')\n\tif ohash != '' && thash != '' {\n\t\texisting_content := os.read_file(htarget) or { '' }\n\t\tif !existing_content.contains('hooks.stopCommitOfNonVfmtedVFiles') {\n\t\t\t// both files do exist, but the current git repo hook, is not compatible (an older version of git_pre_commit_hook.vsh):\n\t\t\terr_exit('the existing file ${htarget} , does not appear to be a compatible V formatting hook\\nYou have to remove it manually')\n\t\t}\n\t}\n\tif show_instructions {\n\t\tprintln(\"> Use `v git-fmt-hook install` to update the CURRENT repository's pre-commit hook,\")\n\t\tprintln('> with the newest pre-commit formatting script from the main V repo.')\n\t\tshow_msg_about_removing(htarget)\n\t}\n\treturn false\n}\n\nfn show_msg_about_removing(htarget string) {\n\tif os.exists(htarget) {\n\t\tprintln(\"> Use `v git-fmt-hook remove` to remove the CURRENT repository's pre-commit hook.\")\n\t}\n}\n\nfn find_nearest_top_level_folder_with_a_git_subfolder(current string) ?string {\n\tmut cfolder := os.to_slash(os.real_path(current))\n\tfor level := 0; level < 255; level++ {\n\t\tif cfolder == '/' || cfolder == '' {\n\t\t\tbreak\n\t\t}\n\t\tgit_folder := os.join_path(cfolder, '.git')\n\t\tif os.is_dir(git_folder) {\n\t\t\treturn git_folder\n\t\t}\n\t\tcfolder = os.dir(cfolder)\n\t}\n\treturn none\n}\n\nfn hash_file(path string) !string {\n\tfbytes := os.read_bytes(path)!\n\tmut digest256 := sha256.new()\n\tdigest256.write(fbytes)!\n\tmut sum256 := digest256.sum([])\n\treturn sum256.hex()\n}\n\n@[noreturn]\nfn err_exit(msg string) {\n\teprintln('> error: ${msg} .')\n\texit(0) // note: this is important, since the command is ran in `v up` and during `make`\n}\n"
  },
  {
    "path": "cmd/tools/vgit-fmt-hook_test.v",
    "content": "import os\n\nconst vexe = @VEXE\nconst tfolder = os.to_slash(os.join_path(os.vtmp_dir(), 'fmt_hook_test'))\nconst unformatted_content = '   fn main() {\\nprintln(   \"hi\" )\\n println ( 123 )\\n   }'\nconst formatted_content = \"fn main() {\\n\\tprintln('hi')\\n\\tprintln(123)\\n}\\n\"\nconst hook_file = '.git/hooks/pre-commit'\n// 'env -S' not supported on OpenBSD\n$if openbsd {\n\tconst foreign_script = '#!/bin/sh\\ncat <<EOF | ${vexe} run -\\nprintln(\"hello hello\")\\nEOF'\n} $else {\n\tconst foreign_script = '#!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp\\nprintln(\"hello hello\")'\n}\n\nconst git = os.to_slash(os.find_abs_path_of_executable('git') or {\n\teprintln('git is needed for this test, skipping...')\n\texit(0)\n})\n\nconst v = os.to_slash(os.find_abs_path_of_executable('v') or {\n\teprintln('v needs to be installed and available on the path for this test, skipping...')\n\texit(0)\n})\n\nfn testsuite_begin() {\n\tunbuffer_stdout()\n\teprintln('>>>>>> preparing tfolder: ${tfolder}')\n\tfull_remove(tfolder) or {}\n\tos.mkdir_all(tfolder) or { panic('> could not create ${tfolder}, err: ${err}') }\n\tos.chdir(tfolder)!\n\tos.write_file('main.v', unformatted_content) or { panic(err) }\n\tassert !os.is_dir('.git')\n\tos.execute_or_exit('git init .')\n\tos.execute_or_exit('git config core.eol lf')\n\tos.execute_or_exit('git config core.autocrlf input')\n\tos.execute_or_exit('git config user.email \"me@example.com\"')\n\tos.execute_or_exit('git config user.name \"Myself\"')\n\tassert os.is_dir('.git')\n\tos.execute_or_exit('git add .')\n\tos.execute_or_exit('git commit -m \"start testing, initially unformatted\"')\n\tos.execute_or_exit('git checkout -b start') // use a known name, instead of master or main or who knows what else ...\n\tassert read_file('main.v') == unformatted_content\n\t// show_git_status()\n}\n\nfn testsuite_end() {\n\treset_to_start_state()\n\tshow_git_status()\n\tos.chdir(os.wd_at_startup)!\n\tif os.getenv('VTEST_KEEP_TFOLDER') != '1' {\n\t\tfull_remove(tfolder)!\n\t\teprintln('>>>>>> deleted ${tfolder} . Use VTEST_KEEP_TFOLDER=1 to keep it to ease diagnosing platform issues.')\n\t}\n\tassert true\n}\n\nfn test_commit_no_vfmt() {\n\teprintln('>>>> ${@FN}')\n\treset_to_start_state()\n\tassert os.execute_or_exit('git checkout -b unformatted').exit_code == 0\n\tappend('main.v', '//') or { panic(err) }\n\tassert os.execute_or_exit('git add .').exit_code == 0\n\tassert os.execute_or_exit('git commit -m \"unformatted change\"').exit_code == 0\n\tassert os.execute_or_exit('git diff start').exit_code == 0\n\tassert read_file('main.v').starts_with(unformatted_content)\n}\n\nfn test_run_vfmt_manually() {\n\teprintln('>>>> ${@FN}')\n\treset_to_start_state()\n\tassert os.execute_or_exit('git checkout -b formatted').exit_code == 0\n\tos.write_file('README.md', 'some new content') or { panic(err) }\n\tassert os.execute_or_exit('${os.quoted_path(vexe)} fmt -w .').exit_code == 0\n\tassert os.execute_or_exit('git add .').exit_code == 0\n\tassert os.execute_or_exit('git commit -m \"formatted change\"').exit_code == 0\n\tassert os.execute_or_exit('git diff start').exit_code == 0\n\tassert read_file('main.v') == formatted_content\n}\n\nfn test_run_git_fmt_hook() {\n\teprintln('>>>> ${@FN}')\n\treset_to_start_state()\n\tres := os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook')\n\tassert res.exit_code == 0\n\tassert res.output.contains('>   CURRENT git repo pre-commit hook: missing')\n\tassert res.output.contains('> Main V repo pre-commit hook script: size:  ')\n\t// Git hook = shell script on OpenBSD\n\t$if openbsd {\n\t\tassert res.output.contains('git_pre_commit_hook.sh')\n\t} $else {\n\t\tassert res.output.contains('cmd/tools/git_pre_commit_hook.vsh')\n\t}\n\tassert res.output.contains('> Files have different hashes.')\n\tassert res.output.contains('> Use `v git-fmt-hook install`')\n}\n\nfn test_run_git_fmt_hook_status_explicit() {\n\teprintln('>>>> ${@FN}')\n\treset_to_start_state()\n\tres := os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook status')\n\tassert res.exit_code == 0\n\tassert res.output.contains('>   CURRENT git repo pre-commit hook: missing')\n\tassert res.output.contains('> Main V repo pre-commit hook script: size:  ')\n\t// Git hook = shell script on OpenBSD\n\t$if openbsd {\n\t\tassert res.output.contains('git_pre_commit_hook.sh')\n\t} $else {\n\t\tassert res.output.contains('cmd/tools/git_pre_commit_hook.vsh')\n\t}\n\tassert res.output.contains('> Files have different hashes.')\n\tassert res.output.contains('> Use `v git-fmt-hook install`')\n}\n\nfn test_run_git_fmt_hook_install() {\n\teprintln('>>>> ${@FN}')\n\treset_to_start_state()\n\tos.execute_or_exit('git checkout -b formatting_with_hook')\n\tappend('main.v', '\\n') or { panic(err) }\n\tassert read_file('main.v').starts_with(unformatted_content)\n\tassert !os.is_file(hook_file)\n\tassert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook install').exit_code == 0\n\tassert os.is_file(hook_file)\n\tres := os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook status')\n\tassert res.output.contains('>   CURRENT git repo pre-commit hook: size:  ')\n\tassert res.output.contains('> Main V repo pre-commit hook script: size:  ')\n\t// Git hook = shell script on OpenBSD\n\t$if openbsd {\n\t\tassert res.output.contains('git_pre_commit_hook.sh')\n\t} $else {\n\t\tassert res.output.contains('cmd/tools/git_pre_commit_hook.vsh')\n\t}\n\tassert res.output.contains(hook_file)\n\tassert res.output.contains('> Both files are exactly the same.')\n\tassert !res.output.contains('> Use `v git-fmt-hook install`')\n\tassert res.output.contains('> Use `v git-fmt-hook remove`')\n\tassert !res.output.contains('> Done.'), 'res:\\n${res}'\n\tos.execute_or_exit('git add -u')\n\tos.execute_or_exit('git commit -m \"this should be formatted\"')\n\tassert read_file('main.v') == formatted_content\n\tdres := os.execute_or_exit('git diff start')\n\t// dump(dres)\n\tassert dres.exit_code == 0\n\tassert dres.output.contains('+fn main() {')\n\tassert dres.output.contains(\"+\\tprintln('hi')\")\n\tsecond := os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook install')\n\tassert second.exit_code == 0\n}\n\nfn test_run_git_fmt_hook_remove() {\n\teprintln('>>>> ${@FN}')\n\treset_to_start_state()\n\tos.execute_or_exit('git checkout start')\n\tos.execute_or_exit('git checkout -b non_formatting_after_removing_hook')\n\tassert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook install').exit_code == 0\n\tassert os.is_file(hook_file)\n\tassert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook remove').exit_code == 0\n\tassert !os.is_file(hook_file)\n\tappend('main.v', '\\n') or { panic(err) }\n\tassert read_file('main.v').starts_with(unformatted_content)\n\tos.execute_or_exit('git add -u')\n\tos.execute_or_exit('git commit -m \"this should NOT be formatted again\"')\n\tassert read_file('main.v').starts_with(unformatted_content)\n}\n\nfn test_run_git_fmt_hook_install_and_remove_on_foreign_hook_should_be_a_nop() {\n\teprintln('>>>> ${@FN}')\n\treset_to_start_state()\n\tos.execute_or_exit('git checkout start')\n\tos.execute_or_exit('git checkout -b install_and_remove_should_be_a_nop_on_a_foreign_hook')\n\tos.write_file(hook_file, foreign_script) or { panic(err) }\n\tos.chmod(hook_file, 0o0777) or { panic(err) }\n\tassert read_file(hook_file) == foreign_script\n\tassert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook install').exit_code == 0\n\tassert read_file(hook_file) == foreign_script\n\tassert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook remove').exit_code == 0\n\tassert read_file(hook_file) == foreign_script\n\tassert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook install').exit_code == 0\n\tassert read_file(hook_file) == foreign_script\n\tassert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook status').exit_code == 0\n\tassert read_file(hook_file) == foreign_script\n\tassert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook').exit_code == 0\n\tassert read_file(hook_file) == foreign_script\n\tappend('main.v', '\\n') or { panic(err) }\n\tappend('main.v', '\\n') or { panic(err) }\n\tassert read_file('main.v').starts_with(unformatted_content)\n\tos.execute_or_exit('git add -u')\n\tfcommiting := os.execute_or_exit('git commit -m \"this should NOT be formatted 2\"')\n\tassert fcommiting.exit_code == 0\n\tassert fcommiting.output.contains('hello hello')\n\tassert read_file('main.v').starts_with(unformatted_content)\n}\n\nfn show_git_status() {\n\tos.system('git log --graph --all --decorate')\n\tos.system('git status')\n}\n\nfn append(path string, content string) ! {\n\tmut f := os.open_append('main.v')!\n\tf.write_string(content)!\n\tf.close()\n}\n\nfn read_file(path string) string {\n\treturn os.read_file(path) or { panic(err) }\n}\n\nfn reset_to_start_state() {\n\tos.execute('git checkout start')\n\tos.rm('.git/hooks/pre-commit') or {}\n\tassert read_file('main.v') == unformatted_content\n}\n\nfn full_remove(path string) ! {\n\t// TODO: fix this on windows; the files inside .git/ are with read only permissions, and os.rmdir_all() can not delete them, until they are chmoded to writable\n\tfiles := os.walk_ext(path + '/.git', '')\n\tfor f in files {\n\t\tos.chmod(f, 0o777) or {}\n\t}\n\tos.rmdir_all(path)!\n}\n"
  },
  {
    "path": "cmd/tools/vgret.defaults.toml",
    "content": "# Defaults\n[compare]\n  method = 'idiff'\n  flags = ['-p','-fail 0.001','-failpercent 0.2']\n\n[capture]\n  method = 'gg_record'\n  flags = [] # ['-prod','-d ...'] etc.\n\n[capture.env]\n  VGG_STOP_AT_FRAME = '8'\n  VGG_SCREENSHOT_FOLDER = '$OUT_PATH'\n  VGG_SCREENSHOT_FRAMES = '5'\n\n# List of apps to run and capture\n[[apps]]\n  path = 'examples/game_of_life/life_gg.v'\n\n[[apps]]\n  path = 'examples/gg/bezier.v'\n\n[[apps]]\n  path = 'examples/gg/mandelbrot.v'\n\n[[apps]]\n  path = 'examples/gg/rectangles.v'\n\n[[apps]]\n  path = 'examples/gg/raven_text_rendering.v'\n\n[[apps]]\n  path = 'examples/gg/worker_thread.v'\n\n[[apps]]\n  path = 'examples/gg/polygons.v'\n\n[[apps]]\n  path = 'examples/gg/bezier_anim.v'\n\n[[apps]]\n  path = 'examples/ttf_font/example_ttf.v'\n  compare.flags = ['-p','-fail 0.008','-failpercent 1.5']\n\n\n# Reasons for ex- or inclusion:\n#\n# 'examples/snek/snek.v'                // Inaccurate captures\n# 'examples/game_of_life/life_gg.v'     // OK\n# 'examples/tetris/tetris.v'            // Uses random start block\n# 'examples/fireworks/fireworks.v'      // Uses rand for placement\n# 'examples/gg/bezier.v',               // OK\n# 'examples/gg/mandelbrot.v',           // OK\n# 'examples/gg/rectangles.v',           // OK\n# 'examples/gg/set_pixels.v'            // Has problem in CI software render (blank, no pixels set)\n# 'examples/gg/random.v'                // Always random\n# 'examples/gg/stars.v'                 // Uses rand for placement\n# 'examples/gg/raven_text_rendering.v', // OK\n# 'examples/gg/worker_thread.v',        // OK\n# 'examples/gg/polygons.v',             // OK\n# 'examples/gg/bezier_anim.v',          // OK\n# 'examples/gg/drag_n_drop.v'           // Default font, that can be different on different platforms\n# 'examples/2048/2048.v'                // Random start tiles\n# 'examples/clock/clock.v'              // Can only be tested on exact points in time :)\n# 'examples/flappylearning/game.v'      // Random movement\n# 'examples/hot_reload/bounce.v'        // Inaccurate captures\n# 'examples/hot_reload/graph.v'         // Inaccurate captures\n# 'examples/ttf_font/example_ttf.v' // OK-ish ... the font rendering seems to be shifted with a few pixels on Ubuntu 24.04, compared to Ubuntu 20.04 . TODO: update it with the newer visuals.\n# 'examples/sokol/01_cubes/cube.v',     // Can pass with a warning and diff at around 1.2%\n# 'examples/sokol/02_cubes_glsl/cube_glsl.v',       // Inaccurate captures\n# 'examples/sokol/03_march_tracing_glsl/rt_glsl.v', // Inaccurate captures\n# 'examples/sokol/04_multi_shader_glsl/rt_glsl.v',  // Inaccurate captures\n# 'examples/sokol/05_instancing_glsl/rt_glsl.v',    // Inaccurate captures\n# 'examples/sokol/06_obj_viewer/show_obj.v',        // Inaccurate captures\n# 'examples/sokol/sdf/sdf.v',                       // Inaccurate captures\n"
  },
  {
    "path": "cmd/tools/vgret.v",
    "content": "// Copyright (c) 2021 Lars Pontoppidan. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\n//\n// vgret (V Graphics REgression Tool) aids in generating screenshots of various graphical `gg`\n// based V applications, in a structured directory hierarchy, with the intent of either:\n// * Generate a directory structure of screenshots/images to test against\n//   (which, as an example, could later be pushed to a remote git repository)\n// * Test for *visual* differences between two, structurally equal, directories\n//\n// vgret uses features and applications that is currently only available on Linux based distros:\n// idiff - to programmatically find *visual* differences between two images:\n//   - Ubuntu: `sudo apt install openimageio-tools`\n//   - Arch:   `sudo pacman -S openimageio`\n// Xvfb - to start a virtual X server framebuffer:\n//   - Ubuntu: `sudo apt install xvfb`\n//   - Arch:   `sudo pacman -S xorg-server-xvfb`\n//\n// For developers:\n// For a quick overview of the generated images you can use `montage` from imagemagick to generate a \"Contact Sheet\":\n// montage -verbose -label '%f' -font Helvetica -pointsize 10 -background '#000000' -fill 'gray' -define jpeg:size=200x200 -geometry 200x200+2+2 -auto-orient $(fd -t f . /path/to/vgret/out/dir) /tmp/montage.jpg\n//   - Ubuntu: `sudo apt install imagemagick`\n//   - Arch:   `sudo pacman -S imagemagick`\n//\n// To generate the reference images locally - or for uploading to a remote repo like `gg-regression-images`\n// You can do the following:\n// 1. `export DISPLAY=:99`                            # Start all graphical apps on DISPLAY 99\n// 2. `Xvfb $DISPLAY -screen 0 1280x1024x24 &`        # Starts a virtual X11 screen buffer\n// 3. `v gret -v /tmp/gg-regression-images`           # Generate reference images to /tmp/gg-regression-images\n// 4. `v gret -v /tmp/test /tmp/gg-regression-images` # Test if the tests can pass locally by comparing to a fresh imageset\n// 5. Visually check the images (you can get an overview by running the `montage` command above)\n// 6. Upload to GitHub or keep locally for more testing/tweaking\n//\n// It's a known factor that the images generated on a local machine won't match the images generated on a remote machine by 100%.\n// They will most likely differ by a small percentage - the comparison tool can be tweaked to accept these subtle changes,\n// at the expense of slightly more inaccurate test results. For non-animated apps the percentage should be > 0.01.\n// You can emulate or test these inaccuracies to some extend locally by simply running the test from a terminal using\n// your physical X11 session display (Usually DISPLAY=:0).\n//\n// Read more about the options of `idiff` here: https://openimageio.readthedocs.io/en/latest/idiff.html\n//\nimport os\nimport flag\nimport time\nimport toml\n\nconst tool_name = 'vgret'\nconst tool_version = '0.0.2'\nconst tool_description = '\\n  Dump and/or compare rendered frames of graphical apps\n  both external and `gg` based apps is supported.\n\nExamples:\n  Generate screenshots to `/tmp/test`\n    v gret /tmp/test\n  Generate and compare screenshots in `/tmp/src` to existing screenshots in `/tmp/dst`\n    v gret /tmp/src /tmp/dst\n  Compare screenshots in `/tmp/src` to existing screenshots in `/tmp/dst`\n    v gret --compare-only /tmp/src /tmp/dst\n'\n\nconst tmp_dir = os.join_path(os.vtmp_dir(), tool_name)\nconst runtime_os = os.user_os()\nconst v_root = os.real_path(@VMODROOT)\n\nconst supported_hosts = ['linux']\nconst supported_capture_methods = ['gg_record', 'generic_screenshot']\n// External tool executables\nconst v_exe = os.getenv('VEXE')\nconst idiff_exe = os.find_abs_path_of_executable('idiff') or { '' }\n\nconst embedded_toml = $embed_file('vgret.defaults.toml', .zlib)\nconst default_toml = embedded_toml.to_string()\nconst empty_toml_array = []toml.Any{}\nconst empty_toml_map = map[string]toml.Any{}\n\nstruct Config {\n\tpath string\nmut:\n\tapps []AppConfig\n}\n\nstruct CompareOptions {\nmut:\n\tmethod string = 'idiff'\n\tflags  []string\n}\n\nstruct CaptureRegion {\nmut:\n\tx      int\n\ty      int\n\twidth  int\n\theight int\n}\n\nfn (cr CaptureRegion) is_empty() bool {\n\treturn cr.width == 0 && cr.height == 0\n}\n\nstruct CaptureOptions {\nmut:\n\tmethod  string = 'gg_record'\n\twait_ms int // used by \"generic_screenshot\" to wait X milliseconds *after* execution of the app\n\tflags   []string\n\tregions []CaptureRegion\n\tenv     map[string]string\n}\n\nfn (co CaptureOptions) validate() ! {\n\tif co.method !in supported_capture_methods {\n\t\treturn error('capture method \"${co.method}\" is not supported. Supported methods are: ${supported_capture_methods}')\n\t}\n}\n\nstruct AppConfig {\n\tcompare  CompareOptions\n\tcapture  CaptureOptions\n\tpath     string\n\tabs_path string\nmut:\n\tscreenshots_path string\n\tscreenshots      []string\n}\n\nstruct Options {\n\tverbose      bool\n\tcompare_only bool\n\troot_path    string\nmut:\n\tconfig Config\n}\n\nfn (opt Options) verbose_execute(cmd string) os.Result {\n\topt.verbose_eprintln('Running `${cmd}`')\n\treturn os.execute(cmd)\n}\n\nfn (opt Options) verbose_eprintln(msg string) {\n\tif opt.verbose {\n\t\teprintln(msg)\n\t}\n}\n\nfn main() {\n\tif runtime_os !in supported_hosts {\n\t\teprintln('${tool_name} is currently only supported on ${supported_hosts} hosts')\n\t\texit(1)\n\t}\n\tif os.args.len == 1 {\n\t\teprintln('Usage: ${tool_name} PATH \\n${tool_description}\\n${tool_name} -h for more help...')\n\t\texit(1)\n\t}\n\n\tmut fp := flag.new_flag_parser(os.args[1..])\n\tfp.application(tool_name)\n\tfp.version(tool_version)\n\tfp.description(tool_description)\n\tfp.arguments_description('PATH [PATH]')\n\tfp.skip_executable()\n\n\tshow_help := fp.bool('help', `h`, false, 'Show this help text.')\n\n\t// Collect tool options\n\tmut opt := Options{\n\t\tverbose:      fp.bool('verbose', `v`, false, \"Be verbose about the tool's progress.\")\n\t\tcompare_only: fp.bool('compare-only', `c`, false, \"Don't generate screenshots - only compare input directories\")\n\t\troot_path:    fp.string('root-path', `r`, v_root, 'Root path of the comparison')\n\t}\n\n\ttoml_conf := fp.string('toml-config', `t`, default_toml, 'Path or string with TOML configuration')\n\targ_paths := fp.finalize()!\n\tif show_help {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\n\tif arg_paths.len == 0 {\n\t\tprintln(fp.usage())\n\t\tprintln('\\nError missing arguments')\n\t\texit(1)\n\t}\n\n\tif !os.exists(tmp_dir) {\n\t\tos.mkdir_all(tmp_dir)!\n\t}\n\n\topt.config = new_config(opt.root_path, toml_conf) or { panic(err) }\n\n\tgen_in_path := arg_paths[0]\n\tif arg_paths.len >= 1 {\n\t\tgenerate_screenshots(mut opt, gen_in_path) or { panic(err) }\n\t}\n\tif arg_paths.len > 1 {\n\t\ttarget_path := arg_paths[1]\n\t\tpath := opt.config.path\n\t\tall_paths_in_use := [path, gen_in_path, target_path]\n\t\tfor path_in_use in all_paths_in_use {\n\t\t\tif !os.is_dir(path_in_use) {\n\t\t\t\teprintln('`${path_in_use}` is not a directory')\n\t\t\t\texit(1)\n\t\t\t}\n\t\t}\n\t\tif path == target_path || gen_in_path == target_path || gen_in_path == path {\n\t\t\teprintln('Compare paths can not be the same directory `${path}`/`${target_path}`/`${gen_in_path}`')\n\t\t\texit(1)\n\t\t}\n\t\tcompare_screenshots(opt, gen_in_path, target_path)!\n\t}\n}\n\nfn generate_screenshots(mut opt Options, output_path string) ! {\n\tpath := opt.config.path\n\n\tdst_path := output_path.trim_right('/')\n\n\tif !os.is_dir(path) {\n\t\treturn error('`${path}` is not a directory')\n\t}\n\n\tfor mut app_config in opt.config.apps {\n\t\tfile := app_config.path\n\t\tapp_path := app_config.abs_path\n\n\t\tmut rel_out_path := ''\n\t\tif os.is_file(app_path) {\n\t\t\trel_out_path = os.dir(file)\n\t\t} else {\n\t\t\trel_out_path = file\n\t\t}\n\n\t\tif app_config.capture.method == 'gg_record' {\n\t\t\topt.verbose_eprintln('Compiling shaders (if needed) for `${file}`')\n\t\t\tsh_result := opt.verbose_execute('${os.quoted_path(v_exe)} shader ${os.quoted_path(app_path)}')\n\t\t\tif sh_result.exit_code != 0 {\n\t\t\t\topt.verbose_eprintln('Skipping shader compile for `${file}` v shader failed with:\\n${sh_result.output}')\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\tif !os.exists(dst_path) {\n\t\t\topt.verbose_eprintln('Creating output path `${dst_path}`')\n\t\t\tos.mkdir_all(dst_path) or { return error('Failed making directory `${dst_path}`') }\n\t\t}\n\n\t\tscreenshot_path := os.join_path(dst_path, rel_out_path)\n\t\tif !os.exists(screenshot_path) {\n\t\t\tos.mkdir_all(screenshot_path) or {\n\t\t\t\treturn error('Failed making screenshot path `${screenshot_path}`')\n\t\t\t}\n\t\t}\n\n\t\tapp_config.screenshots_path = screenshot_path\n\t\tapp_config.screenshots = take_screenshots(opt, app_config) or {\n\t\t\treturn error('Failed taking screenshots of `${app_path}`:\\n${err.msg()}')\n\t\t}\n\t}\n}\n\nfn compare_screenshots(opt Options, output_path string, target_path string) ! {\n\tmut fails := map[string]string{}\n\tmut warns := map[string]string{}\n\tfor app_config in opt.config.apps {\n\t\tscreenshots := app_config.screenshots\n\t\topt.verbose_eprintln('Comparing ${screenshots.len} screenshots in `${output_path}` with `${target_path}`')\n\t\tfor screenshot in screenshots {\n\t\t\trelative_screenshot := screenshot.all_after(output_path + os.path_separator)\n\n\t\t\tsrc := screenshot\n\t\t\ttarget := os.join_path(target_path, relative_screenshot)\n\t\t\topt.verbose_eprintln('Comparing `${src}` with `${target}` with ${app_config.compare.method}')\n\n\t\t\tif app_config.compare.method == 'idiff' {\n\t\t\t\tif idiff_exe == '' {\n\t\t\t\t\treturn error('${tool_name} need the `idiff` tool installed. It can be installed on Ubuntu with `sudo apt install openimageio-tools`')\n\t\t\t\t}\n\t\t\t\tdiff_file := os.join_path(os.vtmp_dir(), os.file_name(src).all_before_last('.') +\n\t\t\t\t\t'.diff.tif')\n\t\t\t\tflags := app_config.compare.flags.join(' ')\n\t\t\t\tdiff_cmd := '${os.quoted_path(idiff_exe)} ${flags} -abs -od -o ${os.quoted_path(diff_file)} -abs ${os.quoted_path(src)} ${os.quoted_path(target)}'\n\t\t\t\tresult := opt.verbose_execute(diff_cmd)\n\t\t\t\tif result.exit_code == 0 {\n\t\t\t\t\topt.verbose_eprintln('OUTPUT: \\n${result.output}')\n\t\t\t\t}\n\t\t\t\tif result.exit_code != 0 {\n\t\t\t\t\teprintln('OUTPUT: \\n${result.output}')\n\t\t\t\t\tif result.exit_code == 1 {\n\t\t\t\t\t\twarns[src] = target\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfails[src] = target\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif warns.len > 0 {\n\t\teprintln('--- WARNINGS ---')\n\t\teprintln('The following files had warnings when compared to their targets')\n\t\tfor warn_src, warn_target in warns {\n\t\t\teprintln('${warn_src} ~= ${warn_target}')\n\t\t}\n\t}\n\tif fails.len > 0 {\n\t\teprintln('--- ERRORS ---')\n\t\teprintln('The following files did not match their targets')\n\t\tfor fail_src, fail_target in fails {\n\t\t\teprintln('${fail_src} != ${fail_target}')\n\t\t}\n\t\tfirst := fails.keys()[0]\n\t\tfail_copy := os.join_path(os.vtmp_dir(), 'fail.' + first.all_after_last('.'))\n\t\tos.cp(first, fail_copy)!\n\t\teprintln('First failed file `${first}` is copied to `${fail_copy}`')\n\n\t\tdiff_file := os.join_path(os.vtmp_dir(), os.file_name(first).all_before_last('.') +\n\t\t\t'.diff.tif')\n\t\tdiff_copy := os.join_path(os.vtmp_dir(), 'diff.tif')\n\t\tif os.is_file(diff_file) {\n\t\t\tos.cp(diff_file, diff_copy)!\n\t\t\teprintln('First failed diff file `${diff_file}` is copied to `${diff_copy}`')\n\t\t\teprintln('Removing alpha channel from ${diff_copy} ...')\n\t\t\tfinal_fail_result_file := os.join_path(os.vtmp_dir(), 'diff.png')\n\t\t\topt.verbose_execute('convert ${os.quoted_path(diff_copy)} -alpha off ${os.quoted_path(final_fail_result_file)}')\n\t\t\teprintln('Final diff file: `${final_fail_result_file}`')\n\t\t}\n\t\texit(1)\n\t}\n}\n\nfn take_screenshots(opt Options, app AppConfig) ![]string {\n\tout_path := app.screenshots_path\n\tif !opt.compare_only {\n\t\topt.verbose_eprintln('Taking screenshot(s) of `${app.path}` to `${out_path}`')\n\t\tmatch app.capture.method {\n\t\t\t'gg_record' {\n\t\t\t\tfor k, v in app.capture.env {\n\t\t\t\t\trv := v.replace('\\$OUT_PATH', out_path)\n\t\t\t\t\topt.verbose_eprintln('Setting ENV `${k}` = ${rv} ...')\n\t\t\t\t\tos.setenv('${k}', rv, true)\n\t\t\t\t}\n\n\t\t\t\tflags := app.capture.flags.join(' ')\n\t\t\t\tresult := opt.verbose_execute('${os.quoted_path(v_exe)} ${flags} -d gg_record run ${os.quoted_path(app.abs_path)}')\n\t\t\t\tif result.exit_code != 0 {\n\t\t\t\t\treturn error('Failed taking screenshot of `${app.abs_path}`:\\n${result.output}')\n\t\t\t\t}\n\t\t\t}\n\t\t\t'generic_screenshot' {\n\t\t\t\tfor k, v in app.capture.env {\n\t\t\t\t\trv := v.replace('\\$OUT_PATH', out_path)\n\t\t\t\t\topt.verbose_eprintln('Setting ENV `${k}` = ${rv} ...')\n\t\t\t\t\tos.setenv('${k}', rv, true)\n\t\t\t\t}\n\n\t\t\t\texisting_screenshots := get_app_screenshots(out_path, app)!\n\n\t\t\t\tflags := app.capture.flags\n\n\t\t\t\tif !os.exists(app.abs_path) {\n\t\t\t\t\treturn error('Failed starting app `${app.abs_path}`, the path does not exist')\n\t\t\t\t}\n\t\t\t\topt.verbose_eprintln('Running ${app.abs_path} ${flags}')\n\t\t\t\tmut p_app := os.new_process(app.abs_path)\n\t\t\t\tp_app.set_args(flags)\n\t\t\t\tp_app.set_redirect_stdio()\n\t\t\t\tp_app.run()\n\n\t\t\t\tif !p_app.is_alive() {\n\t\t\t\t\toutput := p_app.stdout_read() + '\\n' + p_app.stderr_read()\n\t\t\t\t\treturn error('Failed starting app `${app.abs_path}` (before screenshot):\\n${output}')\n\t\t\t\t}\n\t\t\t\tif app.capture.wait_ms > 0 {\n\t\t\t\t\topt.verbose_eprintln('Waiting ${app.capture.wait_ms} before capturing')\n\t\t\t\t\ttime.sleep(app.capture.wait_ms * time.millisecond)\n\t\t\t\t}\n\t\t\t\tif !p_app.is_alive() {\n\t\t\t\t\toutput := p_app.stdout_slurp() + '\\n' + p_app.stderr_slurp()\n\t\t\t\t\treturn error('App `${app.abs_path}` exited (${p_app.code}) before a screenshot could be captured:\\n${output}')\n\t\t\t\t}\n\t\t\t\t// Use ImageMagick's `import` tool to take the screenshot\n\t\t\t\tout_file := os.join_path(out_path, os.file_name(app.path) +\n\t\t\t\t\t'_screenshot_${existing_screenshots.len:02}.png')\n\t\t\t\tresult := opt.verbose_execute('import -window root \"${out_file}\"')\n\t\t\t\tif result.exit_code != 0 {\n\t\t\t\t\tp_app.signal_kill()\n\t\t\t\t\treturn error('Failed taking screenshot of `${app.abs_path}` to \"${out_file}\":\\n${result.output}')\n\t\t\t\t}\n\n\t\t\t\t// When using regions the capture is split up into regions.len\n\t\t\t\t// And name the output based on each region's properties\n\t\t\t\tif app.capture.regions.len > 0 {\n\t\t\t\t\tfor region in app.capture.regions {\n\t\t\t\t\t\tregion_id := 'x${region.x}y${region.y}w${region.width}h${region.height}'\n\t\t\t\t\t\tregion_out_file := os.join_path(out_path, os.file_name(app.path) +\n\t\t\t\t\t\t\t'_screenshot_${existing_screenshots.len:02}_region_${region_id}.png')\n\t\t\t\t\t\t// If the region is empty (w, h == 0, 0) infer a full screenshot,\n\t\t\t\t\t\t// This allows for capturing both regions *and* the complete screen\n\t\t\t\t\t\tif region.is_empty() {\n\t\t\t\t\t\t\tos.cp(out_file, region_out_file) or {\n\t\t\t\t\t\t\t\treturn error('Failed copying original screenshot \"${out_file}\" to region file \"${region_out_file}\"')\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\textract_result := opt.verbose_execute('convert -extract ${region.width}x${region.height}+${region.x}+${region.y} \"${out_file}\" \"${region_out_file}\"')\n\t\t\t\t\t\tif extract_result.exit_code != 0 {\n\t\t\t\t\t\t\tp_app.signal_kill()\n\t\t\t\t\t\t\treturn error('Failed extracting region ${region_id} from screenshot of `${app.abs_path}` to \"${region_out_file}\":\\n${result.output}')\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// When done, remove the original file that was split into regions.\n\t\t\t\t\topt.verbose_eprintln('Removing \"${out_file}\" (region mode)')\n\t\t\t\t\tos.rm(out_file) or {\n\t\t\t\t\t\treturn error('Failed removing original screenshot \"${out_file}\"')\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tp_app.signal_kill()\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn error('Unsupported capture method \"${app.capture.method}\"')\n\t\t\t}\n\t\t}\n\t}\n\treturn get_app_screenshots(out_path, app)!\n}\n\nfn get_app_screenshots(path string, app AppConfig) ![]string {\n\tmut screenshots := []string{}\n\tshots := os.ls(path) or { return error('Failed listing dir `${path}`') }\n\tfor shot in shots {\n\t\tif shot.starts_with(os.file_name(app.path).all_before_last('.')) {\n\t\t\tscreenshots << os.join_path(path, shot)\n\t\t}\n\t}\n\treturn screenshots\n}\n\nfn new_config(root_path string, toml_config string) !Config {\n\tdoc := if os.is_file(toml_config) {\n\t\ttoml.parse_file(toml_config) or { return error(err.msg()) }\n\t} else {\n\t\ttoml.parse_text(toml_config) or { return error(err.msg()) }\n\t}\n\n\tpath := os.real_path(root_path).trim_right('/')\n\n\tcompare_method := doc.value('compare.method').default_to('idiff').string()\n\tcompare_flags := doc.value('compare.flags').default_to(empty_toml_array).array().as_strings()\n\tdefault_compare := CompareOptions{\n\t\tmethod: compare_method\n\t\tflags:  compare_flags\n\t}\n\tcapture_method := doc.value('capture.method').default_to('gg_record').string()\n\tcapture_flags := doc.value('capture.flags').default_to(empty_toml_array).array().as_strings()\n\tcapture_regions_any := doc.value('capture.regions').default_to(empty_toml_array).array()\n\tmut capture_regions := []CaptureRegion{}\n\tfor capture_region_any in capture_regions_any {\n\t\tregion := CaptureRegion{\n\t\t\tx:      capture_region_any.value('x').default_to(0).int()\n\t\t\ty:      capture_region_any.value('y').default_to(0).int()\n\t\t\twidth:  capture_region_any.value('width').default_to(0).int()\n\t\t\theight: capture_region_any.value('height').default_to(0).int()\n\t\t}\n\t\tcapture_regions << region\n\t}\n\tcapture_wait_ms := doc.value('capture.wait_ms').default_to(0).int()\n\tcapture_env := doc.value('capture.env').default_to(empty_toml_map).as_map()\n\tmut env_map := map[string]string{}\n\tfor k, v in capture_env {\n\t\tenv_map[k] = v.string()\n\t}\n\tdefault_capture := CaptureOptions{\n\t\tmethod:  capture_method\n\t\twait_ms: capture_wait_ms\n\t\tflags:   capture_flags\n\t\tregions: capture_regions\n\t\tenv:     env_map\n\t}\n\n\tapps_any := doc.value('apps').default_to(empty_toml_array).array()\n\tmut apps := []AppConfig{cap: apps_any.len}\n\tfor app_any in apps_any {\n\t\trel_path := app_any.value('path').string().trim_right('/')\n\n\t\t// Merge, per app, overwrites\n\t\tmut merged_compare := CompareOptions{}\n\t\tmerged_compare.method = app_any.value('compare.method').default_to(default_compare.method).string()\n\t\tmerged_compare_flags := app_any.value('compare.flags').default_to(empty_toml_array).array().as_strings()\n\t\tif merged_compare_flags.len > 0 {\n\t\t\tmerged_compare.flags = merged_compare_flags\n\t\t} else {\n\t\t\tmerged_compare.flags = default_compare.flags\n\t\t}\n\n\t\tmut merged_capture := CaptureOptions{}\n\t\tmerged_capture.method = app_any.value('capture.method').default_to(default_capture.method).string()\n\t\tmerged_capture_flags := app_any.value('capture.flags').default_to(empty_toml_array).array().as_strings()\n\t\tif merged_capture_flags.len > 0 {\n\t\t\tmerged_capture.flags = merged_capture_flags\n\t\t} else {\n\t\t\tmerged_capture.flags = default_capture.flags\n\t\t}\n\n\t\tapp_capture_regions_any := app_any.value('capture.regions').default_to(empty_toml_array).array()\n\t\tmut app_capture_regions := []CaptureRegion{}\n\t\tfor capture_region_any in app_capture_regions_any {\n\t\t\tregion := CaptureRegion{\n\t\t\t\tx:      capture_region_any.value('x').default_to(0).int()\n\t\t\t\ty:      capture_region_any.value('y').default_to(0).int()\n\t\t\t\twidth:  capture_region_any.value('width').default_to(0).int()\n\t\t\t\theight: capture_region_any.value('height').default_to(0).int()\n\t\t\t}\n\t\t\tapp_capture_regions << region\n\t\t}\n\t\tmut merged_capture_regions := []CaptureRegion{}\n\t\tfor default_capture_region in default_capture.regions {\n\t\t\tif default_capture_region !in app_capture_regions {\n\t\t\t\tmerged_capture_regions << default_capture_region\n\t\t\t}\n\t\t}\n\t\tfor app_capture_region in app_capture_regions {\n\t\t\tif app_capture_region !in default_capture.regions {\n\t\t\t\tmerged_capture_regions << app_capture_region\n\t\t\t}\n\t\t}\n\t\tmerged_capture.regions = merged_capture_regions\n\n\t\tmerged_capture.wait_ms = app_any.value('capture.wait_ms').default_to(default_capture.wait_ms).int()\n\t\tmerge_capture_env := app_any.value('capture.env').default_to(empty_toml_map).as_map()\n\t\tmut merge_env_map := default_capture.env.clone()\n\t\tfor k, v in merge_capture_env {\n\t\t\tmerge_env_map[k] = v.string()\n\t\t}\n\t\tfor k, v in merge_env_map {\n\t\t\tmerged_capture.env[k] = v\n\t\t}\n\n\t\tmerged_capture.validate()!\n\n\t\tapp_config := AppConfig{\n\t\t\tcompare:  merged_compare\n\t\t\tcapture:  merged_capture\n\t\t\tpath:     rel_path\n\t\t\tabs_path: os.join_path(path, rel_path).trim_right('/')\n\t\t}\n\t\tapps << app_config\n\t}\n\n\treturn Config{\n\t\tapps: apps\n\t\tpath: path\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vls.v",
    "content": "// Copyright (c) 2022 Ned Palacios. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\n//\n// The V language server launcher and updater utility is\n// a program responsible for installing, updating, and\n// executing the V language server program with the primary\n// goal of simplifying the installation process across\n// all different platforms, text editors, and IDEs.\nmodule main\n\nimport os\nimport flag\nimport x.json2\nimport net.http\nimport runtime\nimport crypto.sha256\nimport time\nimport json\n\nenum UpdateSource {\n\tgithub_releases\n\tgit_repo\n\tlocal_file\n}\n\nenum SetupKind {\n\tnone\n\tinstall\n\tupdate\n}\n\nenum OutputMode {\n\tsilent\n\ttext\n\tjson\n}\n\nstruct VlsUpdater {\nmut:\n\toutput        OutputMode   = .text\n\tsetup_kind    SetupKind    = .none\n\tupdate_source UpdateSource = .github_releases\n\tls_path       string // --path\n\tpass_to_ls    bool   // --ls\n\tis_check      bool   // --check\n\tis_force      bool   // --force\n\tis_help       bool   // --help\n\targs          []string\n}\n\nconst vexe = os.real_path(os.getenv_opt('VEXE') or { @VEXE })\n\nconst vls_folder = os.join_path(os.home_dir(), '.vls')\n\nconst vls_bin_folder = os.join_path(vls_folder, 'bin')\n\nconst vls_cache_folder = os.join_path(vls_folder, '.cache')\n\nconst vls_manifest_path = os.join_path(vls_folder, 'vls.config.json')\n\nconst vls_src_folder = os.join_path(vls_folder, 'src')\n\nconst server_not_found_err = error_with_code('Language server is not installed nor found.',\n\t101)\n\nfn (upd VlsUpdater) check_or_create_vls_folder() ! {\n\tif !os.exists(vls_folder) {\n\t\tupd.log('Creating .vls folder...')\n\t\tos.mkdir(vls_folder)!\n\t}\n}\n\nfn (upd VlsUpdater) manifest_config() !map[string]json2.Any {\n\tmanifest_buf := os.read_file(vls_manifest_path) or { '{}' }\n\tmanifest_contents := json2.decode[json2.Any](manifest_buf)!.as_map()\n\treturn manifest_contents\n}\n\nfn (upd VlsUpdater) exec_asset_file_name() string {\n\t// TODO: support for Arm and other archs\n\tos_name := os.user_os()\n\tarch := if runtime.is_64bit() { 'x64' } else { 'x86' }\n\text := if os_name == 'windows' { '.exe' } else { '' }\n\treturn 'vls_${os_name}_${arch + ext}'\n}\n\nfn (upd VlsUpdater) update_manifest(new_path string, from_source bool, timestamp time.Time) ! {\n\tupd.log('Updating permissions...')\n\tos.chmod(new_path, 0o755)!\n\n\tupd.log('Updating vls.config.json...')\n\tmut manifest := upd.manifest_config() or {\n\t\tmap[string]json2.Any{}\n\t}\n\n\t$if macos {\n\t\tif os.exists(vls_manifest_path) {\n\t\t\tos.rm(vls_manifest_path) or {}\n\t\t}\n\t}\n\n\tmanifest['server_path'] = json2.Any(new_path)\n\tmanifest['last_updated'] = json2.Any(timestamp.format_ss())\n\tmanifest['from_source'] = json2.Any(from_source)\n\n\tos.write_file(vls_manifest_path, json2.encode(manifest))!\n}\n\nfn (upd VlsUpdater) init_download_prebuilt() ! {\n\tif !os.exists(vls_cache_folder) {\n\t\tos.mkdir(vls_cache_folder)!\n\t}\n\n\tif os.exists(vls_bin_folder) {\n\t\tos.rmdir_all(vls_bin_folder)!\n\t}\n\n\tos.mkdir(vls_bin_folder)!\n}\n\nfn (upd VlsUpdater) get_last_updated_at() !time.Time {\n\tif manifest := upd.manifest_config() {\n\t\tif 'last_updated' in manifest {\n\t\t\treturn time.parse(manifest['last_updated'] or { '' }.str()) or { return error('none') }\n\t\t}\n\t}\n\treturn error('none')\n}\n\nfn (upd VlsUpdater) copy_local_file(exec_asset_file_path string, timestamp time.Time) ! {\n\texp_asset_name := upd.exec_asset_file_name()\n\n\tnew_exec_path := os.join_path(vls_bin_folder, exp_asset_name)\n\tos.cp(exec_asset_file_path, new_exec_path)!\n\tupd.update_manifest(new_exec_path, false, timestamp) or {\n\t\tupd.log('Unable to update config but the executable was updated successfully.')\n\t}\n\tupd.print_new_vls_version(new_exec_path)\n}\n\nfn (upd VlsUpdater) download_prebuilt() ! {\n\tmut has_last_updated_at := true\n\tlast_updated_at := upd.get_last_updated_at() or {\n\t\thas_last_updated_at = false\n\t\ttime.now()\n\t}\n\tdefer {\n\t\tos.rmdir_all(vls_cache_folder) or {}\n\t}\n\n\tupd.log('Finding prebuilt executables from GitHub release..')\n\tresp := http.get('https://api.github.com/repos/vlang/vls/releases')!\n\treleases_json := json2.decode[json2.Any](resp.body)!.as_array()\n\tif releases_json.len == 0 {\n\t\treturn error('Unable to fetch latest VLS release data: No releases found.')\n\t}\n\n\tlatest_release := releases_json[0].as_map()\n\tassets := latest_release['assets']!.as_array()\n\n\tmut checksum_asset_idx := -1\n\tmut exec_asset_idx := -1\n\n\texp_asset_name := upd.exec_asset_file_name()\n\texec_asset_file_path := os.join_path(vls_cache_folder, exp_asset_name)\n\n\tfor asset_idx, raw_asset in assets {\n\t\tasset := raw_asset.as_map()\n\t\tt_asset := asset['name'] or { return }\n\t\tmatch t_asset.str() {\n\t\t\texp_asset_name {\n\t\t\t\texec_asset_idx = asset_idx\n\n\t\t\t\t// check timestamp here\n\t\t\t}\n\t\t\t'checksums.txt' {\n\t\t\t\tchecksum_asset_idx = asset_idx\n\t\t\t}\n\t\t\telse {}\n\t\t}\n\t}\n\n\tif exec_asset_idx == -1 {\n\t\treturn error_with_code('No executable found for this system.', 100)\n\t} else if checksum_asset_idx == -1 {\n\t\treturn error('Unable to download executable: missing checksum')\n\t}\n\n\texec_asset := assets[exec_asset_idx].as_map()\n\n\tmut asset_last_updated_at := time.now()\n\tif created_at := exec_asset['created_at'] {\n\t\tasset_last_updated_at = time.parse_rfc3339(created_at.str()) or { asset_last_updated_at }\n\t}\n\n\tif has_last_updated_at && !upd.is_force && asset_last_updated_at <= last_updated_at {\n\t\tupd.log('VLS was already updated to its latest version.')\n\t\treturn\n\t}\n\n\tupd.log('Executable found for this system. Downloading...')\n\tupd.init_download_prebuilt()!\n\thttp.download_file(exec_asset['browser_download_url']!.str(), exec_asset_file_path)!\n\n\tchecksum_file_path := os.join_path(vls_cache_folder, 'checksums.txt')\n\tchecksum_file_asset := assets[checksum_asset_idx].as_map()\n\thttp.download_file(checksum_file_asset['browser_download_url']!.str(), checksum_file_path)!\n\tchecksums := os.read_file(checksum_file_path)!.split_into_lines()\n\n\tupd.log('Verifying checksum...')\n\tfor checksum_result in checksums {\n\t\tif checksum_result.ends_with(exp_asset_name) {\n\t\t\tchecksum := checksum_result.split(' ')[0]\n\t\t\tactual := calculate_checksum(exec_asset_file_path) or { '' }\n\t\t\tif checksum != actual {\n\t\t\t\treturn error('Downloaded executable is corrupted. Exiting...')\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n\n\tupd.copy_local_file(exec_asset_file_path, asset_last_updated_at)!\n}\n\nfn (upd VlsUpdater) print_new_vls_version(new_vls_exec_path string) {\n\texec_version := os.execute('${new_vls_exec_path} --version')\n\tif exec_version.exit_code == 0 {\n\t\tupd.log('VLS was updated to version: ${exec_version.output.all_after('vls version ').trim_space()}')\n\t}\n}\n\nfn calculate_checksum(file_path string) !string {\n\tdata := os.read_file(file_path)!\n\treturn sha256.hexhash(data)\n}\n\nfn (upd VlsUpdater) compile_from_source() ! {\n\tgit := os.find_abs_path_of_executable('git') or { return error('Git not found.') }\n\n\tif !os.exists(vls_src_folder) {\n\t\tupd.log('Cloning VLS repo...')\n\t\tclone_result := os.execute('${os.quoted_path(vexe)} retry -- ${git} clone --filter=blob:none https://github.com/vlang/vls ${vls_src_folder}')\n\t\tif clone_result.exit_code != 0 {\n\t\t\treturn error('Failed to build VLS from source. Reason: ${clone_result.output}')\n\t\t}\n\t} else {\n\t\tupd.log('Updating VLS repo...')\n\t\tpull_result := os.execute('${os.quoted_path(vexe)} retry -- ${git} -C ${vls_src_folder} pull')\n\t\tif !upd.is_force && pull_result.output.trim_space() == 'Already up to date.' {\n\t\t\tupd.log('VLS was already updated to its latest version.')\n\t\t\treturn\n\t\t}\n\t}\n\n\tupd.log('Compiling VLS from source...')\n\tpossible_compilers := ['cc', 'gcc', 'clang', 'msvc']\n\tmut selected_compiler_idx := -1\n\n\tfor i, cname in possible_compilers {\n\t\tos.find_abs_path_of_executable(cname) or { continue }\n\t\tselected_compiler_idx = i\n\t\tbreak\n\t}\n\n\tif selected_compiler_idx == -1 {\n\t\treturn error('Cannot compile VLS from source: no appropriate C compiler found.')\n\t}\n\n\tcompile_result := os.execute('${os.quoted_path(vexe)} run ${os.join_path(vls_src_folder,\n\t\t'build.vsh')} ${possible_compilers[selected_compiler_idx]}')\n\tif compile_result.exit_code != 0 {\n\t\treturn error('Cannot compile VLS from source: ${compile_result.output}')\n\t}\n\n\texec_path := os.join_path(vls_src_folder, 'bin', 'vls')\n\tupd.update_manifest(exec_path, true, time.now()) or {\n\t\tupd.log('Unable to update config but the executable was updated successfully.')\n\t}\n\tupd.print_new_vls_version(exec_path)\n}\n\nfn (upd VlsUpdater) find_ls_path() !string {\n\tmanifest := upd.manifest_config()!\n\tif 'server_path' in manifest {\n\t\tserver_path := manifest['server_path'] or { return error('none') }\n\t\tif server_path is string {\n\t\t\tif server_path == '' {\n\t\t\t\treturn error('none')\n\t\t\t}\n\n\t\t\treturn server_path\n\t\t}\n\t}\n\treturn error('none')\n}\n\nfn (mut upd VlsUpdater) parse(mut fp flag.FlagParser) ! {\n\tis_json := fp.bool('json', ` `, false, 'Print the output as JSON.')\n\tif is_json {\n\t\tupd.output = .json\n\t}\n\n\tis_silent := fp.bool('silent', ` `, false, 'Disables output printing.')\n\tif is_silent && is_json {\n\t\treturn error('Cannot use --json and --silent at the same time.')\n\t} else if is_silent {\n\t\tupd.output = .silent\n\t}\n\n\tis_install := fp.bool('install', ` `, false, 'Installs the language server. You may also use this flag to re-download or force update your existing installation.')\n\tis_update := fp.bool('update', ` `, false, 'Updates the installed language server.')\n\tupd.is_check = fp.bool('check', ` `, false, 'Checks if the language server is installed.')\n\tupd.is_force = fp.bool('force', ` `, false, 'Force install or update the language server.')\n\tis_source := fp.bool('source', ` `, false, 'Clone and build the language server from source.')\n\n\tif is_install && is_update {\n\t\treturn error('Cannot use --install and --update at the same time.')\n\t} else if is_install {\n\t\tupd.setup_kind = .install\n\t} else if is_update {\n\t\tupd.setup_kind = .update\n\t}\n\n\tif is_source {\n\t\tupd.update_source = .git_repo\n\t}\n\n\tupd.pass_to_ls = fp.bool('ls', ` `, false, 'Pass the arguments to the language server.')\n\tif ls_path := fp.string_opt('path', `p`, 'Path to the language server executable.') {\n\t\tif !os.is_executable(ls_path) {\n\t\t\treturn server_not_found_err\n\t\t}\n\n\t\tupd.ls_path = ls_path\n\n\t\tif upd.setup_kind != .none {\n\t\t\tupd.update_source = .local_file // use local path if both -p and --source are used\n\t\t}\n\t}\n\n\tupd.is_help = fp.bool('help', `h`, false, \"Show this updater's help text. To show the help text for the language server, pass the `--ls` flag before it.\")\n\n\tif !upd.is_help && !upd.pass_to_ls {\n\t\t// automatically set the cli launcher to language server mode\n\t\tupd.pass_to_ls = true\n\t}\n\n\tif upd.pass_to_ls {\n\t\tif upd.ls_path == '' {\n\t\t\tif ls_path := upd.find_ls_path() {\n\t\t\t\tif !upd.is_force && upd.setup_kind == .install {\n\t\t\t\t\treturn error_with_code('VLS was already installed.', 102)\n\t\t\t\t}\n\n\t\t\t\tupd.ls_path = ls_path\n\t\t\t} else if upd.setup_kind == .none {\n\t\t\t\treturn server_not_found_err\n\t\t\t}\n\t\t}\n\n\t\tif upd.is_help {\n\t\t\tupd.args << '--help'\n\t\t}\n\n\t\tfp.allow_unknown_args()\n\t\tupd.args << fp.finalize() or { fp.remaining_parameters() }\n\t} else {\n\t\tfp.finalize()!\n\t}\n}\n\nfn (upd VlsUpdater) log(msg string) {\n\tmatch upd.output {\n\t\t.text {\n\t\t\tprintln('> ${msg}')\n\t\t}\n\t\t.json {\n\t\t\tprint('{\"message\":\"${msg}\"}')\n\t\t\tflush_stdout()\n\t\t}\n\t\t.silent {}\n\t}\n}\n\nfn (upd VlsUpdater) error_details(err IError) string {\n\tmatch err.code() {\n\t\t101 {\n\t\t\tmut vls_dir_shortened := '\\$HOME/.vls'\n\t\t\t$if windows {\n\t\t\t\tvls_dir_shortened = '%USERPROFILE%\\\\.vls'\n\t\t\t}\n\n\t\t\treturn '\n- If you are using this for the first time, please run\n  `v ls --install` first to download and install VLS.\n- If you are using a custom version of VLS, check if\n  the specified path exists and is a valid executable.\n- If you have an existing installation of VLS, be sure\n  to remove \"vls.config.json\" and \"bin\" located inside\n  \"${vls_dir_shortened}\" and re-install.\n\n  If none of the options listed have solved your issue,\n  please report it at https://github.com/vlang/v/issues\n'\n\t\t}\n\t\telse {\n\t\t\treturn ''\n\t\t}\n\t}\n}\n\n@[noreturn]\nfn (upd VlsUpdater) cli_error(err IError) {\n\tmatch upd.output {\n\t\t.text {\n\t\t\teprintln('v ls error: ${err.msg()} (${err.code()})')\n\t\t\tif err !is none {\n\t\t\t\teprintln(upd.error_details(err))\n\t\t\t}\n\n\t\t\tprint_backtrace()\n\t\t}\n\t\t.json {\n\t\t\tprint('{\"error\":{\"message\":${json.encode(err.msg())},\"code\":\"${err.code()}\",\"details\":${json.encode(upd.error_details(err).trim_space())}}}')\n\t\t\tflush_stdout()\n\t\t}\n\t\t.silent {}\n\t}\n\texit(1)\n}\n\nfn (upd VlsUpdater) check_installation() {\n\tif upd.ls_path == '' {\n\t\tupd.log('Language server is not installed')\n\t} else {\n\t\tupd.log('Language server is installed at: ${upd.ls_path}'.split(r'\\').join(r'\\\\'))\n\t}\n}\n\nfn (upd VlsUpdater) run(fp flag.FlagParser) ! {\n\tif upd.is_check {\n\t\tupd.check_installation()\n\t} else if upd.setup_kind != .none {\n\t\tupd.check_or_create_vls_folder()!\n\n\t\tmatch upd.update_source {\n\t\t\t.github_releases {\n\t\t\t\tupd.download_prebuilt() or {\n\t\t\t\t\tif err.code() == 100 {\n\t\t\t\t\t\tupd.compile_from_source()!\n\t\t\t\t\t}\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t\t.git_repo {\n\t\t\t\tupd.compile_from_source()!\n\t\t\t}\n\t\t\t.local_file {\n\t\t\t\tupd.log('Using local vls file to install or update..')\n\t\t\t\tupd.copy_local_file(upd.ls_path, time.now())!\n\t\t\t}\n\t\t}\n\t} else if upd.pass_to_ls {\n\t\texit(os.system('${upd.ls_path} ${upd.args.join(' ')}'))\n\t} else if upd.is_help {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n}\n\nfn main() {\n\tmut fp := flag.new_flag_parser(os.args)\n\tmut upd := VlsUpdater{}\n\n\tfp.application('v ls')\n\tfp.description('Installs, updates, and executes the V language server program')\n\tfp.version('0.1.1')\n\n\t// just to make sure whenever user wants to\n\t// interact directly with the executable\n\t// instead of the usual `v ls` command\n\tif fp.args.len >= 2 && fp.args[0..2] == [os.executable(), 'ls'] {\n\t\t// skip the executable here, the next skip_executable\n\t\t// outside the if statement will skip the `ls` part\n\t\tfp.skip_executable()\n\t}\n\n\t// skip the executable or the `ls` part\n\tfp.skip_executable()\n\n\tupd.parse(mut fp) or {\n\t\tif err.code() == 102 {\n\t\t\tupd.log(err.msg())\n\t\t\texit(0)\n\t\t} else {\n\t\t\tupd.cli_error(err)\n\t\t}\n\t}\n\n\tupd.run(fp) or { upd.cli_error(err) }\n}\n"
  },
  {
    "path": "cmd/tools/vmissdoc.v",
    "content": "// Copyright (c) 2020 Lars Pontoppidan. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nimport os\nimport flag\n\nconst tool_name = 'v missdoc'\nconst tool_version = '0.1.0'\nconst tool_description = 'Prints all V functions in .v files under PATH/, that do not yet have documentation comments.\\nNote: use `v missdoc @vlib`, to find public fns that still lack documentation.'\nconst work_dir_prefix = normalise_path(os.real_path(os.wd_at_startup) + os.path_separator)\n\nstruct UndocumentedFN {\n\tfile      string\n\tline      int\n\tsignature string\n\ttags      []string\n}\n\nstruct Options {\n\tshow_help       bool\n\tcollect_tags    bool\n\tdeprecated      bool\n\tprivate         bool\n\tjs              bool\n\tno_line_numbers bool\n\texclude         []string\n\trelative_paths  bool\nmut:\n\tverify          bool\n\tdiff            bool\n\tadditional_args []string\n}\n\nfn (opt Options) collect_undocumented_functions_in_dir(directory string) []UndocumentedFN {\n\tmut files := []string{}\n\tcollect(directory, mut files, fn (npath string, mut accumulated_paths []string) {\n\t\tif !npath.ends_with('.v') {\n\t\t\treturn\n\t\t}\n\t\tif npath.ends_with('_test.v') {\n\t\t\treturn\n\t\t}\n\t\taccumulated_paths << npath\n\t})\n\tmut undocumented_fns := []UndocumentedFN{}\n\tfor file in files {\n\t\tif !opt.js && file.ends_with('.js.v') {\n\t\t\tcontinue\n\t\t}\n\t\tif opt.exclude.len > 0 && opt.exclude.any(file.contains(it)) {\n\t\t\tcontinue\n\t\t}\n\t\tundocumented_fns << opt.collect_undocumented_functions_in_file(file)\n\t}\n\treturn undocumented_fns\n}\n\nfn (opt &Options) collect_undocumented_functions_in_file(nfile string) []UndocumentedFN {\n\tfile := os.real_path(nfile)\n\tcontents := os.read_file(file) or { panic(err) }\n\tlines := contents.split('\\n')\n\tmut list := []UndocumentedFN{}\n\tmut comments := []string{}\n\tmut tags := []string{}\n\tfor i, line in lines {\n\t\tline_trimmed := line.trim_space()\n\t\tif line.starts_with('//') {\n\t\t\tcomments << line\n\t\t} else if line_trimmed.starts_with('@[') || line_trimmed.starts_with('[') {\n\t\t\ttags << collect_tags(line)\n\t\t} else if line.starts_with('pub fn')\n\t\t\t|| (opt.private && (line.starts_with('fn ') && !(line.starts_with('fn C.')\n\t\t\t|| line.starts_with('fn main')))) {\n\t\t\tif comments.len == 0 {\n\t\t\t\tclean_line := line.all_before_last(' {')\n\t\t\t\tlist << UndocumentedFN{\n\t\t\t\t\tline:      i + 1\n\t\t\t\t\tsignature: clean_line\n\t\t\t\t\ttags:      tags\n\t\t\t\t\tfile:      file\n\t\t\t\t}\n\t\t\t}\n\t\t\ttags = []\n\t\t\tcomments = []\n\t\t} else {\n\t\t\ttags = []\n\t\t\tcomments = []\n\t\t}\n\t}\n\treturn list\n}\n\nfn (opt &Options) collect_undocumented_functions_in_path(path string) []UndocumentedFN {\n\tmut undocumented_functions := []UndocumentedFN{}\n\tif os.is_file(path) {\n\t\tundocumented_functions << opt.collect_undocumented_functions_in_file(path)\n\t} else {\n\t\tundocumented_functions << opt.collect_undocumented_functions_in_dir(path)\n\t}\n\treturn undocumented_functions\n}\n\nfn (opt &Options) report_undocumented_functions_in_path(path string) int {\n\tlist := opt.collect_undocumented_functions_in_path(path)\n\treturn opt.report_undocumented_functions(list)\n}\n\nfn (opt &Options) report_undocumented_functions(list []UndocumentedFN) int {\n\tmut nreports := 0\n\tif list.len > 0 {\n\t\tfor undocumented_fn in list {\n\t\t\tmut line_numbers := '${undocumented_fn.line}:0:'\n\t\t\tif opt.no_line_numbers {\n\t\t\t\tline_numbers = ''\n\t\t\t}\n\t\t\ttags_str := if opt.collect_tags && undocumented_fn.tags.len > 0 {\n\t\t\t\t'${undocumented_fn.tags}'\n\t\t\t} else {\n\t\t\t\t''\n\t\t\t}\n\t\t\tfile := undocumented_fn.file\n\t\t\tofile := if opt.relative_paths {\n\t\t\t\tfile.replace(work_dir_prefix, '')\n\t\t\t} else {\n\t\t\t\tos.real_path(file)\n\t\t\t}\n\t\t\tif opt.deprecated {\n\t\t\t\tprintln('${ofile}:${line_numbers}${undocumented_fn.signature} ${tags_str}')\n\t\t\t\tnreports++\n\t\t\t} else {\n\t\t\t\tmut has_deprecation_tag := false\n\t\t\t\tfor tag in undocumented_fn.tags {\n\t\t\t\t\tif tag.starts_with('deprecated') {\n\t\t\t\t\t\thas_deprecation_tag = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif !has_deprecation_tag {\n\t\t\t\t\tprintln('${ofile}:${line_numbers}${undocumented_fn.signature} ${tags_str}')\n\t\t\t\t\tnreports++\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nreports\n}\n\nfn (opt &Options) diff_undocumented_functions_in_paths(path_old string, path_new string) []UndocumentedFN {\n\told := os.real_path(path_old)\n\tnew := os.real_path(path_new)\n\n\tmut old_undocumented_functions := opt.collect_undocumented_functions_in_path(old)\n\tmut new_undocumented_functions := opt.collect_undocumented_functions_in_path(new)\n\n\tmut differs := []UndocumentedFN{}\n\tif new_undocumented_functions.len > old_undocumented_functions.len {\n\t\tfor new_undoc_fn in new_undocumented_functions {\n\t\t\tnew_relative_file := new_undoc_fn.file.replace(new, '').trim_string_left(os.path_separator)\n\t\t\tmut found := false\n\t\t\tfor old_undoc_fn in old_undocumented_functions {\n\t\t\t\told_relative_file := old_undoc_fn.file.replace(old, '').trim_string_left(os.path_separator)\n\t\t\t\tif new_relative_file == old_relative_file\n\t\t\t\t\t&& new_undoc_fn.signature == old_undoc_fn.signature {\n\t\t\t\t\tfound = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !found {\n\t\t\t\tdiffers << new_undoc_fn\n\t\t\t}\n\t\t}\n\t}\n\tdiffers.sort_with_compare(sort_undoc_fns)\n\treturn differs\n}\n\nfn sort_undoc_fns(a &UndocumentedFN, b &UndocumentedFN) int {\n\tif a.file < b.file {\n\t\treturn -1\n\t}\n\tif a.file > b.file {\n\t\treturn 1\n\t}\n\t// same file sort by signature\n\telse {\n\t\tif a.signature < b.signature {\n\t\t\treturn -1\n\t\t}\n\t\tif a.signature > b.signature {\n\t\t\treturn 1\n\t\t}\n\t\treturn 0\n\t}\n}\n\nfn normalise_path(path string) string {\n\treturn path.replace('\\\\', '/')\n}\n\nfn collect(path string, mut l []string, f fn (string, mut []string)) {\n\tif !os.is_dir(path) {\n\t\treturn\n\t}\n\tmut files := os.ls(path) or { return }\n\tfor file in files {\n\t\tp := normalise_path(os.join_path_single(path, file))\n\t\tif os.is_dir(p) && !os.is_link(p) {\n\t\t\tcollect(p, mut l, f)\n\t\t} else if os.exists(p) {\n\t\t\tf(p, mut l)\n\t\t}\n\t}\n\treturn\n}\n\nfn collect_tags(line string) []string {\n\tmut cleaned := line.all_before('/')\n\tcleaned = cleaned.replace_each(['@[', '', '[', '', ']', '', ' ', ''])\n\treturn cleaned.split(',')\n}\n\nfn main() {\n\tmut fp := flag.new_flag_parser(os.args[1..]) // skip the \"v\" command.\n\tfp.application(tool_name)\n\tfp.version(tool_version)\n\tfp.description(tool_description)\n\tfp.arguments_description('PATH [PATH]...')\n\tfp.skip_executable() // skip the \"missdoc\" command.\n\t// Collect tool options\n\tmut opt := Options{\n\t\tshow_help:       fp.bool('help', `h`, false, 'Show this help text.')\n\t\tdeprecated:      fp.bool('deprecated', `d`, false, 'Include deprecated functions in output.')\n\t\tprivate:         fp.bool('private', `p`, false, 'Include private functions in output.')\n\t\tjs:              fp.bool('js', 0, false, 'Include JavaScript functions in output.')\n\t\tno_line_numbers: fp.bool('no-line-numbers', `n`, false, 'Exclude line numbers in output.')\n\t\tcollect_tags:    fp.bool('tags', `t`, false, 'Also print function tags if any is found.')\n\t\texclude:         fp.string_multi('exclude', `e`, '')\n\t\trelative_paths:  fp.bool('relative-paths', `r`, false, 'Use relative paths in output.')\n\t\tdiff:            fp.bool('diff', 0, false, 'exit(1) and show difference between two PATH inputs, return 0 otherwise.')\n\t\tverify:          fp.bool('verify', 0, false, 'exit(1) if documentation is missing, 0 otherwise.')\n\t}\n\topt.additional_args = fp.finalize() or { panic(err) }\n\tif opt.show_help {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\tif opt.additional_args.len == 0 {\n\t\tprintln(fp.usage())\n\t\teprintln('Error: ${tool_name} is missing PATH input')\n\t\texit(1)\n\t}\n\t// Allow short-long versions to prevent false positive situations, should\n\t// the user miss a `-`. E.g.: the `-verify` flag would be ignored and missdoc\n\t// will return 0 for success plus a list of any undocumented functions.\n\tif '-verify' in opt.additional_args {\n\t\topt.verify = true\n\t}\n\tif '-diff' in opt.additional_args {\n\t\topt.diff = true\n\t}\n\tif opt.diff {\n\t\tif opt.additional_args.len < 2 {\n\t\t\tprintln(fp.usage())\n\t\t\teprintln('Error: ${tool_name} --diff needs two valid PATH inputs')\n\t\t\texit(1)\n\t\t}\n\t\tpath_old := opt.additional_args[0]\n\t\tpath_new := opt.additional_args[1]\n\t\tif !(os.is_file(path_old) || os.is_dir(path_old)) || !(os.is_file(path_new)\n\t\t\t|| os.is_dir(path_new)) {\n\t\t\tprintln(fp.usage())\n\t\t\teprintln('Error: ${tool_name} --diff needs two valid PATH inputs')\n\t\t\texit(1)\n\t\t}\n\t\tlist := opt.diff_undocumented_functions_in_paths(path_old, path_new)\n\t\tnreports := opt.report_undocumented_functions(list)\n\t\tif nreports > 0 {\n\t\t\texit(1)\n\t\t}\n\t\texit(0)\n\t}\n\tmut total := 0\n\tfor path in opt.additional_args {\n\t\tif path in ['@vlib', '@cmd', '@examples'] {\n\t\t\trpath := path[1..]\n\t\t\ttotal += opt.report_undocumented_functions_in_path(os.join_path(@VEXEROOT,\n\t\t\t\trpath))\n\t\t\tcontinue\n\t\t}\n\t\tif os.is_file(path) || os.is_dir(path) {\n\t\t\ttotal += opt.report_undocumented_functions_in_path(path)\n\t\t}\n\t}\n\tif opt.verify && total > 0 {\n\t\texit(1)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vpm/args_test.v",
    "content": "module main\n\nfn test_parse_server_urls_supports_all_aliases() {\n\targs := ['install', '-m', 'https://mirror-a.example/', '--mirror', 'https://mirror-b.example',\n\t\t'-server-url', 'https://mirror-c.example/', '--server-url', 'https://mirror-d.example',\n\t\t'--server-urls', 'https://mirror-e.example', '-m', 'https://mirror-a.example/']\n\tassert parse_server_urls(args) == ['https://mirror-a.example', 'https://mirror-b.example',\n\t\t'https://mirror-c.example', 'https://mirror-d.example', 'https://mirror-e.example']\n}\n\nfn test_parse_vpm_command_skips_option_values() {\n\targs := ['-m', 'https://mirror.example', 'install', '--once', 'nedpals.args']\n\tassert parse_vpm_command(args) == 'install'\n}\n\nfn test_parse_query_args_skips_option_values() {\n\targs := ['install', '-m', 'https://mirror.example', 'nedpals.args']\n\tassert parse_query_args(args, 'install') == ['nedpals.args']\n}\n\nfn test_parse_query_args_empty_with_only_mirror() {\n\targs := ['install', '-m', 'https://mirror.example']\n\tassert parse_query_args(args, 'install') == []string{}\n}\n\nfn test_merge_server_urls_appends_custom_urls_after_defaults() {\n\tdefault_urls := ['https://official-a.example', 'https://official-b.example']\n\tcustom_urls := ['https://official-b.example', 'https://mirror.example']\n\tassert merge_server_urls(default_urls, custom_urls) == [\n\t\t'https://official-a.example',\n\t\t'https://official-b.example',\n\t\t'https://mirror.example',\n\t]\n}\n"
  },
  {
    "path": "cmd/tools/vpm/common.v",
    "content": "module main\n\nimport os\nimport net.http\nimport net.urllib\nimport v.vmod\nimport json\nimport term\n\nstruct ModuleVpmInfo {\n\t// id           int\n\tname         string\n\turl          string\n\tvcs          string\n\tnr_downloads int\n}\n\nstruct VpmInstallServerSelector {\nmut:\n\tselected_url   string\n\tcandidate_urls []string\n}\n\n@[params]\nstruct ErrorOptions {\n\tdetails string\n\tverbose bool // is used to only output the error message if the verbose setting is enabled.\n}\n\nconst vexe = os.quoted_path(os.getenv('VEXE'))\nconst home_dir = os.home_dir()\nconst selected_server_url_env = 'VPM_SELECTED_SERVER_URL'\n\nfn merge_server_urls(default_urls []string, custom_urls []string) []string {\n\tmut server_urls := default_urls.clone()\n\tfor url in custom_urls {\n\t\tif url in server_urls {\n\t\t\tcontinue\n\t\t}\n\t\tserver_urls << url\n\t}\n\treturn server_urls\n}\n\nfn get_server_urls() []string {\n\treturn merge_server_urls(vpm_server_urls, settings.server_urls)\n}\n\nfn selected_server_url(set bool, url string) string {\n\tif set {\n\t\tos.setenv(selected_server_url_env, url, true)\n\t}\n\treturn os.getenv(selected_server_url_env)\n}\n\nfn active_server_urls() []string {\n\tselected_url := selected_server_url(false, '')\n\tif selected_url != '' {\n\t\treturn [selected_url]\n\t}\n\treturn get_server_urls()\n}\n\nfn get_mod_vpm_info(name string) !ModuleVpmInfo {\n\tmut selector := VpmInstallServerSelector{\n\t\tcandidate_urls: if settings.server_urls.len > 0 {\n\t\t\tsettings.server_urls\n\t\t} else {\n\t\t\tvpm_server_urls\n\t\t}\n\t}\n\treturn get_mod_vpm_info_with_selector(name, mut selector)\n}\n\nfn get_mod_vpm_info_with_selector(name string, mut selector VpmInstallServerSelector) !ModuleVpmInfo {\n\tif name.len < 2 || (!name[0].is_digit() && !name[0].is_letter()) {\n\t\treturn error('invalid module name `${name}`.')\n\t}\n\tif selector.candidate_urls.len == 0 {\n\t\treturn error('no vpm server urls configured.')\n\t}\n\tmut errors := []string{}\n\tis_initial_selection := selected_server_url(false, '') == ''\n\tfor url in selector.metadata_server_urls() {\n\t\tmodurl := url + '/api/packages/${name}'\n\t\tverbose_println_more(@FILE_LINE, @FN, 'Retrieving metadata for `${name}` from `${modurl}` by making a GET request ...')\n\t\tr := http.get(modurl) or {\n\t\t\terrors << 'Http server did not respond to our request for `${modurl}`.'\n\t\t\terrors << 'Error details: ${err}'\n\t\t\tcontinue\n\t\t}\n\t\tif r.status_code == 404 || r.body.trim_space() == '404' {\n\t\t\terrors << 'Skipping module `${name}`, since `${url}` reported that `${name}` does not exist.'\n\t\t\tcontinue\n\t\t}\n\t\tif r.status_code != 200 {\n\t\t\terrors << 'Skipping module `${name}`, since `${url}` responded with ${r.status_code} http status code. Please try again later.'\n\t\t\tcontinue\n\t\t}\n\t\ts := r.body\n\t\tif s.len > 0 && s[0] != `{` {\n\t\t\terrors << 'Invalid json data'\n\t\t\terrors << s.trim_space().limit(100) + '...'\n\t\t\tcontinue\n\t\t}\n\t\tmod := json.decode(ModuleVpmInfo, s) or {\n\t\t\terrors << 'Skipping module `${name}`, since its information is not in json format.'\n\t\t\tcontinue\n\t\t}\n\t\tif '' == mod.url || '' == mod.name {\n\t\t\terrors << 'Skipping module `${name}`, since it is missing name or url information.'\n\t\t\tcontinue\n\t\t}\n\t\tif selector.selected_url == '' {\n\t\t\tselector.selected_url = url\n\t\t\tverbose_println_more(@FILE_LINE, @FN, 'Using `${url}` for this installation.')\n\t\t}\n\t\tif is_initial_selection {\n\t\t\tselected_server_url(true, url)\n\t\t}\n\t\tverbose_println_more(@FILE_LINE, @FN, 'name: ${name}; mod: ${mod}')\n\t\treturn mod\n\t}\n\tfinal_error := errors.join_lines()\n\tverbose_println_more(@FILE_LINE, @FN, 'failed due to these errors: ${final_error}')\n\treturn error(final_error)\n}\n\nfn new_install_server_selector() VpmInstallServerSelector {\n\treturn VpmInstallServerSelector{\n\t\tcandidate_urls: if settings.server_urls.len > 0 {\n\t\t\tsettings.server_urls\n\t\t} else {\n\t\t\tbuild_install_server_urls(vpm_server_urls, settings.mirror_urls)\n\t\t}\n\t}\n}\n\nfn build_install_server_urls(default_urls []string, mirror_urls []string) []string {\n\tmut urls := []string{}\n\turls << default_urls\n\turls << mirror_urls\n\treturn unique_server_urls(urls)\n}\n\nfn (selector VpmInstallServerSelector) metadata_server_urls() []string {\n\treturn if selector.selected_url != '' {\n\t\t[selector.selected_url]\n\t} else {\n\t\tselector.candidate_urls\n\t}\n}\n\nfn get_ident_from_url(raw_url string) !(string, string) {\n\tverbose_println_more(@FILE_LINE, @FN, 'raw_url: ${raw_url}')\n\t// On Windows, absolute paths like `C:\\...` are misinterpreted by urllib.parse\n\t// (the drive letter `C:` is treated as a URL scheme). Handle local paths first.\n\tif os.is_abs_path(raw_url) || raw_url.starts_with('./') || raw_url.starts_with('../')\n\t\t|| raw_url.starts_with('~/') || raw_url.starts_with('.\\\\') || raw_url.starts_with('..\\\\')\n\t\t|| raw_url.starts_with('file://') {\n\t\tnormalized := raw_url.trim_string_left('file://').replace('\\\\', '/').trim_left('/')\n\t\t_, name := normalized.rsplit_once('/') or {\n\t\t\treturn '', normalized.trim_string_right('.git')\n\t\t}\n\t\treturn '', name.trim_string_right('.git')\n\t}\n\turl := urllib.parse(raw_url) or { return error('failed to parse module URL `${raw_url}`.') }\n\tnormalized_path := url.path.trim_left('/').trim_space()\n\tpublisher, mut name := normalized_path.rsplit_once('/') or {\n\t\tif settings.vcs == .hg && raw_url.count(':') > 1 {\n\t\t\tverbose_println_more(@FILE_LINE, @FN, 'ok, publisher: \"\", name: \"test_module\"')\n\t\t\treturn '', 'test_module'\n\t\t}\n\t\tif url.scheme in ['file', ''] && normalized_path.len > 0 {\n\t\t\treturn '', normalized_path\n\t\t}\n\t\tfinal_error := 'failed to retrieve module name for `${url}`.'\n\t\tverbose_println_more(@FILE_LINE, @FN, 'failed error: `${final_error}`')\n\t\treturn error(final_error)\n\t}\n\tname = name.trim_string_right('.git')\n\tverbose_println_more(@FILE_LINE, @FN, 'raw_url: ${raw_url}; publisher: ${publisher}; name: ${name}')\n\treturn publisher, name\n}\n\nfn get_name_from_url(raw_url string) !string {\n\t_, name := get_ident_from_url(raw_url)!\n\treturn name\n}\n\nfn normalize_mod_path(path string) string {\n\treturn path.replace('-', '_').to_lower()\n}\n\nfn get_all_modules_for_search() []string {\n\tworking_server_url := get_working_server_url()\n\tverbose_println_more(@FILE_LINE, @FN, 'working_server_url: ${working_server_url}')\n\tprintln('Search server: ${working_server_url} .')\n\tsearch_url := '${working_server_url}/search'\n\tverbose_println_more(@FILE_LINE, @FN, 'making a GET request to search_url: ${search_url} ...')\n\tr := http.get(search_url) or {\n\t\tvpm_error(err.msg(), verbose: true)\n\t\texit(1)\n\t}\n\tif r.status_code != 200 {\n\t\tvpm_error('failed to search through ${search_url}', details: 'Status code: ${r.status_code}')\n\t\texit(1)\n\t}\n\ts := r.body\n\tmut read_len := 0\n\tmut modules := []string{}\n\tfor read_len < s.len {\n\t\tmut start_token := '<a class=\"package-card__title hover:underline cursor-pointer\" href=\"/packages/'\n\t\tend_token := '\">'\n\t\t// get the start index of the module entry\n\t\tmut start_index := s.index_after(start_token, read_len) or { -1 }\n\t\tif start_index == -1 {\n\t\t\tbreak\n\t\t}\n\t\tstart_index += start_token.len\n\n\t\t// get the index of the end of module entry\n\t\tend_index := s.index_after(end_token, start_index) or { break }\n\t\tm := s[start_index..end_index]\n\t\tmodules << m\n\t\tread_len = end_index\n\t\tif read_len >= s.len {\n\t\t\tbreak\n\t\t}\n\t}\n\tverbose_println_more(@FILE_LINE, @FN, 'found modules: ${modules}')\n\treturn modules\n}\n\nfn get_installed_modules() []string {\n\tdirs := os.ls(settings.vmodules_path) or { return [] }\n\tmut modules := []string{}\n\tfor dir in dirs {\n\t\tadir := os.join_path(settings.vmodules_path, dir)\n\t\tif dir in excluded_dirs || !os.is_dir(adir) {\n\t\t\tcontinue\n\t\t}\n\t\tif os.exists(os.join_path(adir, 'v.mod')) && os.exists(os.join_path(adir, '.git', 'config')) {\n\t\t\t// an official vlang module with a short module name, like `vsl`, `ui` or `markdown`\n\t\t\tmodules << dir\n\t\t\tcontinue\n\t\t}\n\t\tauthor := dir\n\t\tmods := os.ls(adir) or { continue }\n\t\tfor m in mods {\n\t\t\tvcs_used_in_dir(os.join_path(adir, m)) or { continue }\n\t\t\tmodules << '${author}.${m}'\n\t\t}\n\t}\n\tverbose_println_more(@FILE_LINE, @FN, 'found modules: ${modules}')\n\treturn modules\n}\n\nfn get_path_of_existing_module(mod_name string) ?string {\n\tname := get_name_from_url(mod_name) or { mod_name.replace('-', '_').to_lower() }\n\tpath := os.real_path(os.join_path(settings.vmodules_path, name.replace('.', os.path_separator)))\n\tif !os.exists(path) {\n\t\tvpm_error('failed to find `${name}` at `${path}`.')\n\t\treturn none\n\t}\n\tif !os.is_dir(path) {\n\t\tvpm_error('skipping `${path}`, since it is not a directory.')\n\t\treturn none\n\t}\n\tverbose_println_more(@FILE_LINE, @FN, 'mod_name: ${mod_name}, found path: ${path}')\n\treturn path\n}\n\nfn get_working_server_url() string {\n\tis_initial_selection := selected_server_url(false, '') == ''\n\tfor url in active_server_urls() {\n\t\tverbose_println('Trying server url: ${url}')\n\t\thttp.head(url) or {\n\t\t\tvpm_error('failed to connect to server url `${url}`.', details: err.msg())\n\t\t\tcontinue\n\t\t}\n\t\tif is_initial_selection {\n\t\t\tselected_server_url(true, url)\n\t\t}\n\t\tverbose_println_more(@FILE_LINE, @FN, 'found url: ${url}')\n\t\treturn url\n\t}\n\tvpm_error('No responding vpm server found. Please check your network connectivity and try again later.')\n\texit(1)\n}\n\nfn ensure_vmodules_dir_exist() {\n\tif !os.is_dir(settings.vmodules_path) {\n\t\tprintln('Creating `${settings.vmodules_path}`...')\n\t\tos.mkdir(settings.vmodules_path) or {\n\t\t\tvpm_error(err.msg(), verbose: true)\n\t\t\texit(1)\n\t\t}\n\t}\n\tverbose_println_more(@FILE_LINE, @FN, 'settings.vmodules_path: ${settings.vmodules_path}')\n}\n\nfn increment_module_download_count(name string, preferred_server_url string) ! {\n\tif settings.no_dl_count_increment {\n\t\tprintln('Skipping download count increment for `${name}`.')\n\t\treturn\n\t}\n\tserver_urls := if preferred_server_url != '' {\n\t\tunique_server_urls([preferred_server_url])\n\t} else if settings.server_urls.len > 0 {\n\t\tsettings.server_urls\n\t} else {\n\t\tvpm_server_urls\n\t}\n\tif server_urls.len == 0 {\n\t\treturn error('no vpm server urls configured.')\n\t}\n\tmut errors := []string{}\n\tis_initial_selection := selected_server_url(false, '') == ''\n\tfor url in server_urls {\n\t\tmodurl := url + '/api/packages/${name}/incr_downloads'\n\t\tverbose_println_more(@FILE_LINE, @FN, 'making a POST request to modurl: ${modurl} ...')\n\t\tr := http.post(modurl, '') or {\n\t\t\terrors << 'Http server did not respond to our request for `${modurl}`.'\n\t\t\terrors << 'Error details: ${err}'\n\t\t\tcontinue\n\t\t}\n\t\tif r.status_code != 200 {\n\t\t\terrors << 'Failed to increment the download count for module `${name}`, since `${url}` responded with ${r.status_code} http status code. Please try again later.'\n\t\t\tcontinue\n\t\t}\n\t\tif is_initial_selection {\n\t\t\tselected_server_url(true, url)\n\t\t}\n\t\treturn\n\t}\n\tfinal_error := errors.join_lines()\n\tverbose_println_more(@FILE_LINE, @FN, 'final_error: ${final_error}')\n\treturn error(final_error)\n}\n\nfn get_manifest(path string) ?vmod.Manifest {\n\treturn vmod.from_file(os.join_path(path, 'v.mod')) or { return none }\n}\n\nfn resolve_dependencies(manifest ?vmod.Manifest, modules []string) {\n\tmod := manifest or { return }\n\t// Filter out modules that are both contained in the input query and listed as\n\t// dependencies in the mod file of the module that is supposed to be installed.\n\tdeps := mod.dependencies.filter(it !in modules)\n\tverbose_println_more(@FILE_LINE, @FN, 'deps: ${deps}')\n\tif deps.len > 0 {\n\t\tprintln('Resolving ${deps.len} dependencies for module `${mod.name}`...')\n\t\tverbose_println('Found dependencies: ${deps}')\n\t\tvpm_install(deps)\n\t}\n}\n\nfn verbose_println(msg string) {\n\tif settings.is_verbose {\n\t\tprintln(msg)\n\t}\n}\n\nfn verbose_println_more(fline string, fname string, msg string) {\n\tvpm_log(fline, fname, msg)\n\tverbose_println(msg)\n}\n\nfn vpm_log_header(txt string) {\n\tdivider := '='.repeat(40 - txt.len / 2)\n\tsettings.logger.debug('\\n${divider} ${txt} ${divider}\\n')\n}\n\nfn vpm_log(line string, func string, msg string) {\n\tsettings.logger.debug('${line:-15s} fn: ${func:-30s} msg: ${msg}')\n}\n\nfn vpm_error(msg string, opts ErrorOptions) {\n\tif opts.verbose && !settings.is_verbose {\n\t\treturn\n\t}\n\teprintln(term.ecolorize(term.red, 'error: ') + msg)\n\tif opts.details.len > 0 && settings.is_verbose {\n\t\teprint(term.ecolorize(term.cyan, 'details: '))\n\t\tpadding := ' '.repeat('details: '.len)\n\t\tfor i, line in opts.details.split_into_lines() {\n\t\t\tif i > 0 {\n\t\t\t\teprint(padding)\n\t\t\t}\n\t\t\teprintln(term.ecolorize(term.cyan, line))\n\t\t}\n\t}\n}\n\nfn vpm_warn(msg string, opts ErrorOptions) {\n\teprintln(term.ecolorize(term.yellow, 'warning: ') + msg)\n\tif opts.details.len > 0 {\n\t\teprint(term.ecolorize(term.cyan, 'details: '))\n\t\tpadding := ' '.repeat('details: '.len)\n\t\tfor i, line in opts.details.split_into_lines() {\n\t\t\tif i > 0 {\n\t\t\t\teprint(padding)\n\t\t\t}\n\t\t\teprintln(term.ecolorize(term.cyan, line))\n\t\t}\n\t}\n}\n\n// Formatted version of the vmodules install path. E.g. `/home/user/.vmodules` -> `~/.vmodules`\nfn fmt_mod_path(path string) string {\n\tif !path.contains(home_dir) {\n\t\treturn path\n\t}\n\treturn $if windows {\n\t\tpath.replace(home_dir, '%USERPROFILE%')\n\t} $else {\n\t\tpath.replace(home_dir, '~')\n\t}\n}\n\nfn at_version(version string) string {\n\treturn if version != '' { '@${version}' } else { '' }\n}\n\n// FIXME: Workaround for failing `rmdir` commands on Windows.\nfn rmdir_all(path string) ! {\n\t$if windows {\n\t\tos.execute_opt('rd /s /q ${path}')!\n\t} $else {\n\t\tos.rmdir_all(path)!\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vpm/dependency_test.v",
    "content": "import os\nimport time\nimport rand\nimport v.vmod\nimport test_utils { cmd_ok }\n\nconst v = os.quoted_path(@VEXE)\nconst test_path = os.join_path(os.vtmp_dir(), 'vpm_dependency_test_${rand.ulid()}')\n\nfn testsuite_begin() {\n\t$if !network ? {\n\t\teprintln('> skipping ${@FILE}, when `-d network` is missing')\n\t\texit(0)\n\t}\n\tdump(test_path)\n\ttest_utils.set_test_env(test_path)\n\tos.mkdir_all(test_path) or {}\n\tos.chdir(test_path)!\n}\n\nfn testsuite_end() {\n\tdump(os.system('find ${test_path}'))\n\tos.rmdir_all(test_path) or {}\n}\n\nfn get_mod_name(path string) string {\n\tmod := vmod.from_file(path) or {\n\t\teprintln(err)\n\t\treturn ''\n\t}\n\treturn mod.name\n}\n\n// Case: running `v install` without specifying modules in a V project directory.\nfn test_install_dependencies_in_module_dir() {\n\tmod := 'my_module'\n\tmod_path := os.join_path(test_path, mod)\n\tos.mkdir(mod_path)!\n\tos.chdir(mod_path)!\n\t// Create a v.mod file that lists dependencies.\n\tvmod_path := os.join_path(mod_path, 'v.mod')\n\tvmod_contents := \"Module {\n\tname: '${mod}'\n\tdescription: ''\n\tversion: '0.0.0'\n\tlicense: 'MIT'\n\tdependencies: ['markdown', 'pcre', 'https://github.com/spytheman/vtray']\n}\"\n\tos.write_file(vmod_path, vmod_contents)!\n\tv_mod := vmod.from_file(vmod_path) or {\n\t\tassert false, err.msg()\n\t\treturn\n\t}\n\tassert v_mod.dependencies == ['markdown', 'pcre', 'https://github.com/spytheman/vtray']\n\t// Run `v install`\n\tmut res := cmd_ok(@LOCATION, '${v} install --once')\n\tassert res.output.contains('Detected v.mod file inside the project directory. Using it...'), res.output\n\texpect_installing(@LOCATION, res.output, 'markdown')\n\texpect_installing(@LOCATION, res.output, 'pcre')\n\texpect_installing(@LOCATION, res.output, 'vtray')\n\n\tassert get_mod_name(os.join_path(test_path, 'markdown', 'v.mod')) == 'markdown'\n\tassert get_mod_name(os.join_path(test_path, 'pcre', 'v.mod')) == 'pcre'\n\tassert get_mod_name(os.join_path(test_path, 'vtray', 'v.mod')) == 'vtray'\n\tres = cmd_ok(@LOCATION, '${v} install --once')\n\tassert res.output.contains('All modules are already installed.'), res.output\n}\n\nfn test_resolve_external_dependencies_during_module_install() {\n\tres := cmd_ok(@LOCATION, '${v} install -v https://github.com/ttytm/emoji-mart-desktop')\n\tassert res.output.contains('Found 2 dependencies'), res.output\n\texpect_installing(@LOCATION, res.output, 'webview')\n\texpect_installing(@LOCATION, res.output, 'miniaudio')\n\t// The external dependencies should have been installed to `<vmodules_dir>/<dependency_name>`\n\tassert get_mod_name(os.join_path(test_path, 'webview', 'v.mod')) == 'webview'\n\tassert get_mod_name(os.join_path(test_path, 'miniaudio', 'v.mod')) == 'miniaudio'\n}\n\nfn test_install_with_recursive_dependencies() {\n\tspawn fn () {\n\t\ttime.sleep(2 * time.minute)\n\t\teprintln('Timeout while testing installation with recursive dependencies.')\n\t\texit(1)\n\t}()\n\tcmd_ok(@LOCATION, '${v} install https://gitlab.com/tobealive/a')\n\n\t// Test the installation of a module when passing its URL with the `.git` extension.\n\t// One of the modules dependencies `https://gitlab.com/tobealive/c` has the\n\t// `https://gitlab.com/tobealive/a` dependency without `.git`.\n\tcmd_ok(@LOCATION, '${v} remove a b c')\n\tcmd_ok(@LOCATION, '${v} install https://gitlab.com/tobealive/a.git')\n}\n\nfn expect_installing(location string, output string, what string) {\n\teprintln('>>> location: ${location}')\n\tassert output.contains('Installing `${what}`') || output.contains('Scanning `${what}`'), output\n}\n"
  },
  {
    "path": "cmd/tools/vpm/expect/accept_reinstall_mod_with_version_installation.expect",
    "content": "#!/usr/bin/env expect\n\nset timeout 10\n\nset vexe [lindex $argv 0]\nset mod [lindex $argv 1]\nset cur_tag [lindex $argv 2]\nset new_tag [lindex $argv 3]\nset install_path [lindex $argv 4]\n\nspawn $vexe install $mod@$new_tag\n\nexpect \"Scanning `$mod@$new_tag`...\" {} timeout { exit 1 }\nexpect \"Module `$mod@$cur_tag` is already installed at\" {} timeout { exit 1 }\nexpect \"Replace it with `$mod@$new_tag`? \\\\\\[Y/n\\\\\\]: \" { send \"\\r\" } timeout { exit 1 }\nexpect \"Installing `$mod`...\" {} timeout { exit 1 }\nexpect \"Skipping download count increment for `$mod`.\" {} timeout { exit 1 }\nexpect \"Installed `$mod`\" {} timeout { exit 1 }\n\nexpect eof\n"
  },
  {
    "path": "cmd/tools/vpm/expect/decline_reinstall_mod_with_version_installation.expect",
    "content": "#!/usr/bin/env expect\n\nset timeout 10\n\nset vexe [lindex $argv 0]\nset mod [lindex $argv 1]\nset cur_tag [lindex $argv 2]\nset new_tag [lindex $argv 3]\nset install_path [lindex $argv 4]\n\nspawn $vexe install $mod@$new_tag\n\nexpect \"Scanning `$mod@$new_tag`...\" {} timeout { exit 1 }\nexpect \"Module `$mod@$cur_tag` is already installed at\" {} timeout { exit 1 }\nexpect \"Replace it with `$mod@$new_tag`? \\\\\\[Y/n\\\\\\]: \" { send \"n\\r\" } timeout { exit 1 }\n\nexpect eof\n"
  },
  {
    "path": "cmd/tools/vpm/install.v",
    "content": "module main\n\nimport os\nimport v.vmod\nimport v.help\n\nenum InstallResult {\n\tinstalled\n\tfailed\n\tskipped\n}\n\nfn vpm_install(query []string) {\n\tif settings.is_help {\n\t\thelp.print_and_exit('vpm')\n\t}\n\n\tmut selector := new_install_server_selector()\n\tmut modules := parse_query(if query.len == 0 {\n\t\tif os.exists('./v.mod') {\n\t\t\t// Case: `v install` was run in a directory of another V-module to install its dependencies\n\t\t\t// - without additional module arguments.\n\t\t\tprintln('Detected v.mod file inside the project directory. Using it...')\n\t\t\tmanifest := vmod.from_file('./v.mod') or { panic(err) }\n\t\t\tif manifest.dependencies.len == 0 {\n\t\t\t\tprintln('Nothing to install.')\n\t\t\t\texit(0)\n\t\t\t}\n\t\t\tmanifest.dependencies\n\t\t} else {\n\t\t\tvpm_error('specify at least one module for installation.',\n\t\t\t\tdetails: 'example: `v install publisher.package` or `v install https://github.com/owner/repository`'\n\t\t\t)\n\t\t\texit(2)\n\t\t}\n\t} else {\n\t\tquery\n\t}, mut selector)\n\n\tinstalled_modules := get_installed_modules()\n\n\tvpm_log(@FILE_LINE, @FN, 'Queried Modules: ${modules}')\n\tvpm_log(@FILE_LINE, @FN, 'Installed modules: ${installed_modules}')\n\n\tif installed_modules.len > 0 && settings.is_once {\n\t\tnum_to_install := modules.len\n\t\tmut already_installed := []string{}\n\t\tif modules.len > 0 {\n\t\t\tmut i_deleted := []int{}\n\t\t\tfor i, m in modules {\n\t\t\t\tif m.name in installed_modules {\n\t\t\t\t\talready_installed << m.name\n\t\t\t\t\ti_deleted << i\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor i in i_deleted.reverse() {\n\t\t\t\tmodules.delete(i)\n\t\t\t}\n\t\t}\n\t\tif already_installed.len > 0 {\n\t\t\tverbose_println('Already installed modules: ${already_installed}')\n\t\t\tif already_installed.len == num_to_install {\n\t\t\t\tprintln('All modules are already installed.')\n\t\t\t\texit(0)\n\t\t\t}\n\t\t}\n\t}\n\n\tinstall_modules(modules, selector.selected_url)\n}\n\nfn install_modules(modules []Module, selected_server_url string) {\n\tvpm_log(@FILE_LINE, @FN, 'modules: ${modules}')\n\tmut errors := 0\n\tfor m in modules {\n\t\tvpm_log(@FILE_LINE, @FN, 'module: ${m}')\n\t\tmatch m.install() {\n\t\t\t.installed {}\n\t\t\t.failed {\n\t\t\t\terrors++\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t.skipped {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tif !m.is_external {\n\t\t\tincrement_module_download_count(m.name, selected_server_url) or {\n\t\t\t\tvpm_error('failed to increment the download count for `${m.name}`',\n\t\t\t\t\tdetails: err.msg()\n\t\t\t\t)\n\t\t\t\terrors++\n\t\t\t}\n\t\t}\n\t\tprintln('Installed `${m.name}` in ${m.install_path_fmted} .')\n\t}\n\tif errors > 0 {\n\t\texit(1)\n\t}\n}\n\nfn (m Module) install() InstallResult {\n\tdefer {\n\t\tos.rmdir_all(m.tmp_path) or {}\n\t}\n\tif m.is_installed {\n\t\t// Case: installed, but not an explicit version. Update instead of continuing the installation.\n\t\tif m.version == '' && m.installed_version == '' {\n\t\t\tif m.is_external && m.url.starts_with('http://') {\n\t\t\t\tvpm_update([m.install_path.all_after(settings.vmodules_path).trim_left(os.path_separator).replace(os.path_separator,\n\t\t\t\t\t'.')])\n\t\t\t} else {\n\t\t\t\tvpm_update([m.name])\n\t\t\t}\n\t\t\treturn .skipped\n\t\t}\n\t\t// Case: installed, but conflicting. Confirmation or -[-f]orce flag required.\n\t\tif settings.is_force || m.confirm_install() {\n\t\t\tm.remove() or {\n\t\t\t\tvpm_error('failed to remove `${m.name}`.', details: err.msg())\n\t\t\t\treturn .failed\n\t\t\t}\n\t\t} else {\n\t\t\treturn .skipped\n\t\t}\n\t}\n\tprintln('Installing `${m.name}`...')\n\t// When the module should be relocated into a subdirectory we need to make sure\n\t// it exists to not run into permission errors.\n\tparent_dir := m.install_path.all_before_last(os.path_separator)\n\tif !os.exists(parent_dir) {\n\t\tos.mkdir_all(parent_dir) or {\n\t\t\tvpm_error('failed to create module directory for `${m.name}`.', details: err.msg())\n\t\t\treturn .failed\n\t\t}\n\t}\n\tos.mv(m.tmp_path, m.install_path) or {\n\t\tvpm_error('failed to install `${m.name}`.', details: err.msg())\n\t\treturn .failed\n\t}\n\treturn .installed\n}\n\nfn (m Module) confirm_install() bool {\n\tif m.installed_version == m.version {\n\t\tprintln('Module `${m.name}${at_version(m.installed_version)}` is already installed, use --force to overwrite.')\n\t\treturn false\n\t} else {\n\t\tprintln('Module `${m.name}${at_version(m.installed_version)}` is already installed at `${m.install_path_fmted}`.')\n\t\tif settings.fail_on_prompt {\n\t\t\tvpm_error('VPM should not have entered a confirmation prompt.')\n\t\t\texit(1)\n\t\t}\n\t\tinstall_version := at_version(if m.version == '' { 'latest' } else { m.version })\n\t\tinput := os.input('Replace it with `${m.name}${install_version}`? [Y/n]: ')\n\t\tmatch input.trim_space().to_lower() {\n\t\t\t'', 'y' {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\telse {\n\t\t\t\tverbose_println('Skipping `${m.name}`.')\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n}\n\nfn (m Module) remove() ! {\n\tverbose_println('Removing `${m.name}` from `${m.install_path_fmted}`...')\n\trmdir_all(m.install_path)!\n\tverbose_println('Removed `${m.name}`.')\n}\n"
  },
  {
    "path": "cmd/tools/vpm/install_local_test.v",
    "content": "module main\n\nimport os\nimport rand\nimport v.vmod\nimport test_utils { cmd_ok }\n\nconst test_path = os.join_path(os.vtmp_dir(), 'vpm_install_local_test_${rand.ulid()}')\n\nstruct LocalInstallCase {\n\targs        string\n\tmodule_name string\n\tworkdir     string\n}\n\nfn testsuite_begin() {\n\ttest_utils.set_test_env(test_path)\n}\n\nfn testsuite_end() {\n\tos.rmdir_all(test_path) or {}\n}\n\nfn test_install_from_local_git_repository_variants() {\n\trepo_path := os.join_path(test_path, 'local_repo')\n\trepo_dot_git_path := os.join_path(test_path, 'local_repo.git')\n\tcreate_local_git_module(repo_path, 'local_repo_pkg')\n\tcreate_local_git_module(repo_dot_git_path, 'local_repo_dot_git_pkg')\n\n\tcases := [\n\t\tLocalInstallCase{\n\t\t\targs:        os.quoted_path(repo_path)\n\t\t\tmodule_name: 'local_repo_pkg'\n\t\t},\n\t\tLocalInstallCase{\n\t\t\targs:        file_url(repo_path)\n\t\t\tmodule_name: 'local_repo_pkg'\n\t\t},\n\t\tLocalInstallCase{\n\t\t\targs:        '--git ${os.quoted_path(repo_path)}'\n\t\t\tmodule_name: 'local_repo_pkg'\n\t\t},\n\t\tLocalInstallCase{\n\t\t\targs:        '--git ${file_url(repo_path)}'\n\t\t\tmodule_name: 'local_repo_pkg'\n\t\t},\n\t\tLocalInstallCase{\n\t\t\targs:        os.file_name(repo_path)\n\t\t\tmodule_name: 'local_repo_pkg'\n\t\t\tworkdir:     test_path\n\t\t},\n\t\tLocalInstallCase{\n\t\t\targs:        os.quoted_path(repo_dot_git_path)\n\t\t\tmodule_name: 'local_repo_dot_git_pkg'\n\t\t},\n\t\tLocalInstallCase{\n\t\t\targs:        file_url(repo_dot_git_path)\n\t\t\tmodule_name: 'local_repo_dot_git_pkg'\n\t\t},\n\t\tLocalInstallCase{\n\t\t\targs:        '--git ${os.quoted_path(repo_dot_git_path)}'\n\t\t\tmodule_name: 'local_repo_dot_git_pkg'\n\t\t},\n\t\tLocalInstallCase{\n\t\t\targs:        '--git ${file_url(repo_dot_git_path)}'\n\t\t\tmodule_name: 'local_repo_dot_git_pkg'\n\t\t},\n\t\tLocalInstallCase{\n\t\t\targs:        os.file_name(repo_dot_git_path)\n\t\t\tmodule_name: 'local_repo_dot_git_pkg'\n\t\t\tworkdir:     test_path\n\t\t},\n\t]\n\tfor i, c in cases {\n\t\tvmodules_path := os.join_path(test_path, 'vmodules_case_${i}')\n\t\ttest_utils.set_test_env(vmodules_path)\n\t\tcmd := '${vexe} install ${c.args}'\n\t\told_dir := os.getwd()\n\t\tif c.workdir != '' {\n\t\t\tos.chdir(c.workdir) or { panic(err) }\n\t\t}\n\t\tres := cmd_ok(@LOCATION, cmd)\n\t\tif c.workdir != '' {\n\t\t\tos.chdir(old_dir) or {}\n\t\t}\n\t\tassert res.output.contains('Installed `${c.module_name}`'), res.output\n\t\tmanifest := vmod.from_file(os.join_path(vmodules_path, c.module_name, 'v.mod')) or {\n\t\t\tpanic('Failed to parse v.mod for `${c.module_name}`. ${err}')\n\t\t}\n\t\tassert manifest.name == c.module_name\n\t}\n}\n\nfn create_local_git_module(repo_path string, module_name string) {\n\tos.mkdir_all(repo_path) or { panic(err) }\n\tos.write_file(os.join_path(repo_path, 'v.mod'), \"Module{\\n\\tname: '${module_name}'\\n\\tversion: '0.0.1'\\n}\\n\") or {\n\t\tpanic(err)\n\t}\n\tcmd_ok(@LOCATION, 'git init ${os.quoted_path(repo_path)}')\n\tcmd_ok(@LOCATION, 'git -C ${os.quoted_path(repo_path)} add v.mod')\n\tcmd_ok(@LOCATION, 'git -C ${os.quoted_path(repo_path)} -c user.email=\"ci@vlang.io\" -c user.name=\"V CI\" commit -m \"initial commit\"')\n}\n\nfn file_url(path string) string {\n\tmut normalized_path := path.replace('\\\\', '/')\n\tif !normalized_path.starts_with('/') {\n\t\tnormalized_path = '/${normalized_path}'\n\t}\n\treturn 'file://${normalized_path}'\n}\n"
  },
  {
    "path": "cmd/tools/vpm/install_test.v",
    "content": "// vtest build: !musl? && !sanitized_job?\n// vtest retry: 3\nmodule main\n\nimport os\nimport rand\nimport v.vmod\nimport test_utils { cmd_fail, cmd_ok }\n\n// Running tests appends a tsession path to VTMP, which is automatically cleaned up after the test.\n// The following will result in e.g. `$VTMP/tsession_7fe8e93bd740_1612958707536/test-vmodules/`.\nconst test_path = os.join_path(os.vtmp_dir(), 'vpm_install_test_${rand.ulid()}')\n\nfn testsuite_begin() {\n\t$if !network ? {\n\t\teprintln('> skipping ${@FILE}, when `-d network` is missing')\n\t\texit(0)\n\t}\n\tdump(test_path)\n\ttest_utils.set_test_env(test_path)\n}\n\nfn testsuite_end() {\n\tos.rmdir_all(test_path) or {}\n}\n\nfn get_vmod(path string) vmod.Manifest {\n\treturn vmod.from_file(os.join_path(test_path, path, 'v.mod')) or {\n\t\teprintln('Failed to parse v.mod for `${path}`. ${err}')\n\t\texit(1)\n\t}\n}\n\nfn test_install_from_vpm_ident() {\n\tres := cmd_ok(@LOCATION, '${vexe} install nedpals.args')\n\tassert res.output.contains('Skipping download count increment for `nedpals.args`.'), res.output\n\tmanifest := get_vmod(os.join_path('nedpals', 'args'))\n\tassert manifest.name == 'nedpals.args'\n\tassert manifest.dependencies == []string{}\n}\n\nfn test_install_from_vpm_short_ident() {\n\tcmd_ok(@LOCATION, '${vexe} install pcre')\n\tmanifest := get_vmod('pcre')\n\tassert manifest.name == 'pcre'\n\tassert manifest.description == 'A simple regex library for V.'\n}\n\nfn test_install_from_git_url() {\n\tmut res := cmd_ok(@LOCATION, '${vexe} install https://github.com/vlang/markdown')\n\tassert res.output.contains('Installing `markdown`'), res.output\n\tmut manifest := get_vmod('markdown')\n\tassert manifest.name == 'markdown'\n\tassert manifest.dependencies == []string{}\n\tres = cmd_ok(@LOCATION, '${vexe} install http://github.com/Wertzui123/HashMap')\n\tassert res.output.contains('Installing `HashMap`'), res.output\n\tassert res.output.contains('`http` is deprecated'), res.output\n\tmanifest = get_vmod(os.join_path('wertzui123', 'hashmap'))\n\tres = cmd_ok(@LOCATION, '${vexe} install http://github.com/Wertzui123/HashMap')\n\tassert res.output.contains('Updating module `wertzui123.hashmap`'), res.output\n\tassert res.output.contains('`http` is deprecated'), res.output\n\tres = cmd_ok(@LOCATION, '${vexe} install https://gitlab.com/tobealive/webview')\n\tassert res.output.contains('Installed `webview`'), res.output\n}\n\nfn test_install_already_existent() {\n\tmut res := cmd_ok(@LOCATION, '${vexe} install https://github.com/vlang/markdown')\n\tassert res.output.contains('Updating module `markdown`'), res.output\n\tmanifest := get_vmod('markdown')\n\tassert manifest.name == 'markdown'\n\tassert manifest.dependencies == []string{}\n\t// The same module but with the `.git` extension added.\n\tres = cmd_ok(@LOCATION, '${vexe} install https://github.com/vlang/markdown.git')\n\tassert res.output.contains('Updating module `markdown`'), res.output\n}\n\nfn test_install_once() {\n\t// Start with a clean test path.\n\trmdir_all(test_path) or {}\n\tos.mkdir_all(test_path) or {}\n\n\t// Install markdown module.\n\tmut res := cmd_ok(@LOCATION, '${vexe} install markdown')\n\t// Keep track of the last modified state of the v.mod file of the installed markdown module.\n\tmd_last_modified := os.file_last_mod_unix(os.join_path(test_path, 'markdown', 'v.mod'))\n\n\tinstall_cmd := '${@VEXE} install https://github.com/vlang/markdown https://github.com/vlang/pcre --once -v'\n\t// Try installing two modules, one of which is already installed.\n\tres = cmd_ok(@LOCATION, install_cmd)\n\tassert res.output.contains(\"Already installed modules: ['markdown']\"), res.output\n\tmanifest := get_vmod('pcre')\n\tassert manifest.name == 'pcre'\n\tassert manifest.description == 'A simple regex library for V.'\n\t// Ensure the before installed markdown module wasn't modified.\n\tassert md_last_modified == os.file_last_mod_unix(os.join_path(test_path, 'markdown',\n\t\t'v.mod'))\n\n\t// Try installing two modules that are both already installed.\n\tres = cmd_ok(@LOCATION, install_cmd)\n\tassert res.output.contains('All modules are already installed.'), res.output\n\tassert md_last_modified == os.file_last_mod_unix(os.join_path(test_path, 'markdown',\n\t\t'v.mod'))\n}\n\nfn test_missing_repo_name_in_url() {\n\tincomplete_url := 'https://github.com/vlang'\n\tres := cmd_fail(@LOCATION, '${vexe} install ${incomplete_url}')\n\tassert res.output.contains('failed to retrieve module name for `${incomplete_url}`'), res.output\n}\n\nfn test_manifest_detection() {\n\tmut res := cmd_fail(@LOCATION, '${vexe} install https://github.com/octocat/octocat.github.io')\n\tassert res.output.contains('failed to find `v.mod` for `https://github.com/octocat/octocat.github.io`'), res.output\n\t// No error for vpm modules yet.\n\tres = cmd_ok(@LOCATION, '${vexe} install spytheman.regex')\n\tassert res.output.contains('`spytheman.regex` is missing a manifest file'), res.output\n\tassert res.output.contains('Installing `spytheman.regex`'), res.output\n}\n\nfn test_install_potentially_conflicting() {\n\tmut res := os.execute('${vexe} install ui')\n\tassert res.output.contains('Installed `ui`')\n\tmut manifest := get_vmod('ui')\n\tassert manifest.name == 'ui'\n\tres = os.execute('${vexe} install https://github.com/isaiahpatton/ui')\n\tassert res.output.contains('Installed `iui`')\n\tmanifest = get_vmod('iui')\n\tassert manifest.name == 'iui'\n}\n\nfn test_get_installed_version() {\n\ttest_project_path := os.join_path(test_path, 'test_project')\n\tmut res := cmd_ok(@LOCATION, 'git init ${test_project_path}')\n\tos.chdir(test_project_path)!\n\tif os.execute('git config user.name').exit_code == 1 {\n\t\tos.execute_or_exit('git config user.email \"ci@vlang.io\"')\n\t\tos.execute_or_exit('git config user.name \"V CI\"')\n\t}\n\tos.write_file('v.mod', '')!\n\tres = cmd_ok(@LOCATION, 'git add .')\n\tres = cmd_ok(@LOCATION, 'git commit -m \"initial commit\"')\n\tmut mod := Module{\n\t\tinstall_path: test_project_path\n\t}\n\tmod.get_installed()\n\tassert mod.is_installed\n\tassert mod.installed_version == ''\n\n\t// Create a tag -> latests commit and tag are at the same state,\n\t// but it should not be treated as a version installation, when there is another head branch.\n\tres = cmd_ok(@LOCATION, 'git tag v0.1.0 -m \"some tag message\"') // note: without a tag message, git will try to start an editor when you run this test locally, which will block\n\tmod.is_installed = false\n\tmod.get_installed()\n\tassert mod.is_installed\n\tassert mod.installed_version == ''\n\n\tcmd_ok(@LOCATION, 'git checkout v0.1.0')\n\tmod.is_installed = false\n\tmod.get_installed()\n\tassert mod.is_installed\n\tassert mod.installed_version == ''\n\n\tcmd_ok(@LOCATION, 'git branch -D master')\n\tcmd_ok(@LOCATION, 'git reset --hard v0.1.0')\n\tmod.is_installed = false\n\tmod.get_installed()\n\tassert mod.is_installed\n\tassert mod.installed_version == 'v0.1.0'\n}\n\nfn test_install_from_hg_url() ! {\n\thg_path := os.find_abs_path_of_executable('hg') or {\n\t\teprintln('skipping test, since `hg` is not executable.')\n\t\treturn\n\t}\n\ttest_module_path := os.join_path(os.temp_dir(), rand.ulid(), 'hg_test_module')\n\tdefer {\n\t\tos.rmdir_all(test_module_path) or {}\n\t}\n\t// Initialize project without manifest file.\n\tmut res := cmd_ok(@LOCATION, 'hg init ${test_module_path}')\n\n\tprintln('> writing .hg/hgrc to the new mercurial repo ...')\n\tos.mkdir_all(os.join_path(test_module_path, '.hg'))!\n\tos.write_file(os.join_path(test_module_path, '.hg/hgrc'), '[ui]\\nusername = v_ci <v_ci@example.net>\\nverbose = False\\n')!\n\tprintln('> writing .hg/hgrc done.')\n\n\tmut p, mut port := test_utils.hg_serve(hg_path, test_module_path, 2000)\n\t// Trying to install it should fail.\n\tres = os.execute('${vexe} install --hg http://127.0.0.1:${port}')\n\tp.signal_kill()\n\tassert res.output.contains('failed to find `v.mod`'), res.output\n\t// Create and commit manifest.\n\tname := 'my_awesome_v_module'\n\tversion := '1.0.0'\n\tos.write_file(os.join_path(test_module_path, 'v.mod'), \"Module{\n\tname: '${name}'\n\tversion: '${version}'\n}\")!\n\tos.chdir(test_module_path)!\n\tcmd_ok(@LOCATION, 'hg add')\n\tcmd_ok(@LOCATION, 'hg commit -m \"add v.mod\"')\n\tp, port = test_utils.hg_serve(hg_path, test_module_path, 3000)\n\t// Trying to install the module should work now.\n\tres = cmd_ok(@LOCATION, '${vexe} install --hg http://127.0.0.1:${port}')\n\tp.signal_kill()\n\t// Get manifest from the vmodules directory.\n\tmanifest := get_vmod(name)\n\tassert manifest.name == name\n\tassert manifest.version == version\n}\n"
  },
  {
    "path": "cmd/tools/vpm/install_version_input_test.v",
    "content": "// vtest build: !musl? && !sanitized_job?\n// vtest retry: 3\nimport os\nimport rand\nimport v.vmod\nimport test_utils { cmd_ok }\n\nconst vexe = os.quoted_path(@VEXE)\nconst test_path = os.join_path(os.vtmp_dir(), 'vpm_install_version_input_test_${rand.ulid()}')\nconst expect_tests_path = os.join_path(@VEXEROOT, 'cmd', 'tools', 'vpm', 'expect')\nconst expect_exe = os.quoted_path(os.find_abs_path_of_executable('expect') or {\n\teprintln('skipping test, since expect is missing')\n\texit(0)\n})\n\nfn testsuite_begin() {\n\t$if !network ? {\n\t\teprintln('> skipping ${@FILE}, when `-d network` is missing')\n\t\texit(0)\n\t}\n\tdump(test_path)\n\ttest_utils.set_test_env(test_path)\n\t// Explicitly disable fail on prompt.\n\tos.setenv('VPM_FAIL_ON_PROMPT', '', true)\n\tos.mkdir_all(test_path) or {}\n\tos.chdir(test_path)!\n}\n\nfn testsuite_end() {\n\tos.rmdir_all(test_path) or {}\n}\n\nfn get_vmod(path string) vmod.Manifest {\n\treturn vmod.from_file(os.join_path(test_path, path, 'v.mod')) or {\n\t\teprintln('Failed to parse v.mod for `${path}`. ${err}')\n\t\texit(1)\n\t}\n}\n\n// Test installing another version of a module of which an explicit version is already installed.\nfn test_reinstall_mod_with_version_installation() {\n\t// Install version.\n\tident := 'vsl'\n\ttag := 'v0.1.47'\n\tcmd_ok(@LOCATION, '${vexe} install ${ident}@${tag}')\n\tmut manifest := get_vmod(ident)\n\tassert manifest.name == ident\n\tassert manifest.version == tag.trim_left('v')\n\n\t// Try reinstalling.\n\tnew_tag := 'v0.1.50'\n\tinstall_path := os.real_path(os.join_path(test_path, ident))\n\texpect_args := [vexe, ident, tag, new_tag, install_path].join(' ')\n\n\t// Decline.\n\tdecline_test := os.join_path(expect_tests_path, 'decline_reinstall_mod_with_version_installation.expect')\n\tmanifest_path := os.join_path(install_path, 'v.mod')\n\tlast_modified := os.file_last_mod_unix(manifest_path)\n\tcmd_ok(@LOCATION, '${expect_exe} ${decline_test} ${expect_args}')\n\tassert last_modified == os.file_last_mod_unix(manifest_path)\n\n\t// Accept.\n\taccept_test := os.join_path(expect_tests_path, 'accept_reinstall_mod_with_version_installation.expect')\n\tcmd_ok(@LOCATION, '${expect_exe} ${accept_test} ${expect_args}')\n\tmanifest = get_vmod(ident)\n\tassert manifest.name == ident\n\tassert manifest.version == new_tag.trim_left('v')\n}\n"
  },
  {
    "path": "cmd/tools/vpm/install_version_test.v",
    "content": "// vtest build: !musl? && !sanitized_job?\n// vtest retry: 3\nmodule main\n\nimport os\nimport rand\nimport v.vmod\nimport test_utils { cmd_fail, cmd_ok }\n\nconst test_path = os.join_path(os.vtmp_dir(), 'vpm_install_version_test_${rand.ulid()}')\n\nfn testsuite_begin() {\n\t$if !network ? {\n\t\teprintln('> skipping ${@FILE}, when `-d network` is missing')\n\t\texit(0)\n\t}\n\tdump(test_path)\n\ttest_utils.set_test_env(test_path)\n}\n\nfn testsuite_end() {\n\tos.rmdir_all(test_path) or {}\n}\n\nfn get_vmod(path string) vmod.Manifest {\n\treturn vmod.from_file(os.join_path(test_path, path, 'v.mod')) or {\n\t\teprintln('Failed to parse v.mod for `${path}`. ${err}')\n\t\texit(1)\n\t}\n}\n\nfn test_install_from_vpm_with_git_version_tag() {\n\tident := 'ttytm.webview'\n\trelative_path := ident.replace('.', os.path_separator)\n\tmut tag := 'v0.6.0'\n\tmut res := cmd_ok(@LOCATION, '${vexe} install ${ident}@${tag}')\n\tassert res.output.contains('Installing `${ident}`'), res.output\n\tassert res.output.contains('Installed `${ident}`'), res.output\n\tmut manifest := get_vmod(relative_path)\n\tassert manifest.name == 'webview'\n\tassert manifest.version == '0.6.0'\n\t// Install same version without force flag.\n\tres = cmd_ok(@LOCATION, '${vexe} install ${ident}@${tag}')\n\tassert res.output.contains('Module `${ident}@${tag}` is already installed, use --force to overwrite'), res.output\n\t// Install another version, add force flag to surpass confirmation.\n\ttag = 'v0.5.0'\n\tres = cmd_ok(@LOCATION, '${vexe} install -f ${ident}@${tag}')\n\tassert res.output.contains('Installed `${ident}`'), res.output\n\tmanifest = get_vmod(relative_path)\n\tassert manifest.name == 'webview'\n\tassert manifest.version == '0.5.0'\n\t// Install invalid version.\n\ttag = '6.0'\n\tres = cmd_fail(@LOCATION, '${vexe} install -f ${ident}@${tag}')\n\tassert res.output.contains('failed to install `${ident}`'), res.output\n\n\t// Install invalid version verbose.\n\tres = cmd_fail(@LOCATION, '${vexe} install -f -v ${ident}@${tag}')\n\tassert res.output.contains('failed to install `${ident}`'), res.output\n\tassert res.output.contains('Remote branch 6.0 not found in upstream origin'), res.output\n\t// Install without version tag after a version was installed\n\tres = cmd_ok(@LOCATION, '${vexe} install -f ${ident}')\n\tassert res.output.contains('Installing `${ident}`'), res.output\n\t// Re-install latest version (without a tag). Should trigger an update, force should not be required.\n\tres = cmd_ok(@LOCATION, '${vexe} install ${ident}')\n\tassert res.output.contains('Updating module `${ident}`'), res.output\n}\n\nfn test_install_from_git_url_with_version_tag() {\n\tmut url := 'https://github.com/vlang/vsl'\n\tmut tag := 'v0.1.50'\n\tmut res := cmd_ok(@LOCATION, '${vexe} install ${url}@${tag}')\n\tassert res.output.contains('Installing `vsl`'), res.output\n\tassert res.output.contains('Installed `vsl`'), res.output\n\tmut manifest := get_vmod('vsl')\n\tassert manifest.name == 'vsl'\n\tassert manifest.version == '0.1.50'\n\t// Install same version without force flag.\n\tres = cmd_ok(@LOCATION, '${vexe} install ${url}@${tag}')\n\tassert res.output.contains('Module `vsl@${tag}` is already installed, use --force to overwrite'), res.output\n\t// Install another version, add force flag to surpass confirmation.\n\ttag = 'v0.1.47'\n\tres = cmd_ok(@LOCATION, '${vexe} install -f ${url}@${tag}')\n\tassert res.output.contains('Installed `vsl`'), res.output\n\tmanifest = get_vmod('vsl')\n\tassert manifest.name == 'vsl'\n\tassert manifest.version == '0.1.47'\n\t// Install invalid version.\n\ttag = 'abc'\n\tres = cmd_fail(@LOCATION, '${vexe} install -f ${url}@${tag}')\n\t// Install invalid version verbose.\n\tres = cmd_fail(@LOCATION, '${vexe} install -f -v ${url}@${tag}')\n\tnot_found := res.output.contains('Could not find remote branch ${tag} to clone.')\n\t\t|| res.output.contains('Remote branch ${tag} not found')\n\tassert not_found, res.output\n\t// Install from GitLab.\n\turl = 'https://gitlab.com/tobealive/webview'\n\ttag = 'v0.6.0'\n\tres = cmd_ok(@LOCATION, '${vexe} install ${url}@${tag}')\n\tassert res.output.contains('Installed `webview`'), res.output\n\tmanifest = get_vmod('webview')\n\tassert manifest.name == 'webview'\n\tassert manifest.version == '0.6.0'\n}\n\nfn test_install_from_hg_url_with_version_tag() ! {\n\thg_path := os.find_abs_path_of_executable('hg') or {\n\t\teprintln('skipping test, since `hg` is not executable.')\n\t\treturn\n\t}\n\n\thg_version := cmd_ok(@LOCATION, 'hg version -q')\n\tdump(hg_version.output.trim_space())\n\n\ttest_module_path := os.join_path(os.temp_dir(), rand.ulid(), 'hg_test_module')\n\tdefer {\n\t\tos.rmdir_all(test_module_path) or {}\n\t}\n\tmut res := cmd_ok(@LOCATION, 'hg init ${test_module_path}')\n\tos.chdir(test_module_path)!\n\n\tprintln('> writing .hg/hgrc to the new mercurial repo ...')\n\tos.mkdir_all('.hg')!\n\tos.write_file('.hg/hgrc', '[ui]\\nusername = v_ci <v_ci@example.net>\\nverbose = False\\n')!\n\tprintln('> writing .hg/hgrc done.')\n\n\tprintln('> writing v.mod file ...')\n\tos.write_file('v.mod', \"Module{\n\tname: 'my_awesome_v_module'\n\tversion: '0.1.0'\n}\")!\n\tprintln('> writing v.mod file done.')\n\n\tcmd_ok(@LOCATION, 'hg add')\n\tcmd_ok(@LOCATION, 'hg commit -m \"initial commit\"')\n\tprintln('> writing README.md file ...')\n\tos.write_file('README.md', 'Hello World!')!\n\tprintln('> writing README.md file done.')\n\tcmd_ok(@LOCATION, 'hg add')\n\tcmd_ok(@LOCATION, 'hg commit -m \"add readme\"')\n\tcmd_ok(@LOCATION, 'hg tag v0.1.0')\n\n\tprintln('> rewriting v.mod ...')\n\tos.write_file('v.mod', \"Module{\n\tname: 'my_awesome_v_module'\n\tversion: '0.2.0'\n}\")!\n\tprintln('> rewriting v.mod done.')\n\n\tcmd_ok(@LOCATION, 'hg add')\n\tcmd_ok(@LOCATION, 'hg commit -m \"bump version to v0.2.0\"')\n\n\tmut p, port := test_utils.hg_serve(hg_path, test_module_path, 4000)\n\tres = os.execute('${vexe} install -v --hg http://127.0.0.1:${port}@v0.1.0')\n\tp.signal_kill()\n\tif res.exit_code != 0 {\n\t\tassert false, 'location: ${@LOCATION}, res:\\n${res}'\n\t}\n\t// Get manifest from the vmodules directory.\n\tmanifest := get_vmod('my_awesome_v_module')\n\tassert manifest.name == 'my_awesome_v_module'\n\tassert manifest.version == '0.1.0'\n}\n"
  },
  {
    "path": "cmd/tools/vpm/link.v",
    "content": "module main\n\nimport os\nimport v.help\nimport v.vmod\n\nstruct LinkedProject {\n\tname        string\n\tproject_dir string\n\tlink_path   string\n}\n\nfn vpm_link(query []string) {\n\tif settings.is_help {\n\t\thelp.print_and_exit('link')\n\t}\n\tensure_no_query_for_project_command('link', query)\n\tensure_vmodules_dir_exist()\n\n\tproject := get_project_for_linking() or {\n\t\tvpm_error(err.msg())\n\t\texit(1)\n\t}\n\tif project.project_dir == os.real_path(project.link_path) {\n\t\tprintln('Module `${project.name}` is already available in `${fmt_mod_path(project.link_path)}`.')\n\t\treturn\n\t}\n\tif os.exists(project.link_path) || os.is_link(project.link_path) {\n\t\tif os.is_link(project.link_path) {\n\t\t\tif os.real_path(project.link_path) == project.project_dir {\n\t\t\t\tprintln('Module `${project.name}` is already linked in `${fmt_mod_path(project.link_path)}`.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tvpm_error('`${project.name}` is already linked at `${fmt_mod_path(project.link_path)}`.',\n\t\t\t\tdetails: 'Run `v unlink` first to replace it.'\n\t\t\t)\n\t\t\texit(1)\n\t\t}\n\t\tvpm_error('`${project.name}` already exists at `${fmt_mod_path(project.link_path)}`.')\n\t\texit(1)\n\t}\n\tparent_dir := os.dir(project.link_path)\n\tos.mkdir_all(parent_dir) or {\n\t\tvpm_error('failed to create `${fmt_mod_path(parent_dir)}`.', details: err.msg())\n\t\texit(1)\n\t}\n\tos.symlink(project.project_dir, project.link_path) or {\n\t\tvpm_error('failed to link `${project.name}`.', details: err.msg())\n\t\texit(1)\n\t}\n\tprintln('Linked `${project.name}` to `${fmt_mod_path(project.link_path)}`.')\n}\n\nfn vpm_unlink(query []string) {\n\tif settings.is_help {\n\t\thelp.print_and_exit('unlink')\n\t}\n\tensure_no_query_for_project_command('unlink', query)\n\n\tproject := get_project_for_linking() or {\n\t\tvpm_error(err.msg())\n\t\texit(1)\n\t}\n\tif !os.exists(project.link_path) && !os.is_link(project.link_path) {\n\t\tprintln('Module `${project.name}` is not linked in `${fmt_mod_path(project.link_path)}`.')\n\t\treturn\n\t}\n\tif !os.is_link(project.link_path) {\n\t\tvpm_error('`${project.name}` at `${fmt_mod_path(project.link_path)}` is not a symlink.')\n\t\texit(1)\n\t}\n\tremove_symlink(project.link_path) or {\n\t\tvpm_error('failed to unlink `${project.name}`.', details: err.msg())\n\t\texit(1)\n\t}\n\tcleanup_empty_link_parent_dirs(project.link_path)\n\tprintln('Unlinked `${project.name}` from `${fmt_mod_path(project.link_path)}`.')\n}\n\nfn ensure_no_query_for_project_command(command string, query []string) {\n\tif query.len == 0 {\n\t\treturn\n\t}\n\tvpm_error('`${command}` does not accept package names.',\n\t\tdetails: 'Run `v ${command}` from inside the project directory.'\n\t)\n\texit(2)\n}\n\nfn get_project_for_linking() !LinkedProject {\n\twrkdir := os.getwd()\n\tmut mcache := vmod.get_cache()\n\tvmod_location := mcache.get_by_folder(wrkdir)\n\tif vmod_location.vmod_file == '' {\n\t\treturn error('no `v.mod` file found in `${wrkdir}` or its parent directories.')\n\t}\n\tmanifest := vmod.from_file(vmod_location.vmod_file)!\n\tif manifest.name.trim_space() == '' {\n\t\treturn error('`${vmod_location.vmod_file}` is missing the `name` field.')\n\t}\n\tmod_path := normalize_mod_path(manifest.name.replace('.', os.path_separator))\n\tvmodules_path := if os.is_dir(settings.vmodules_path) {\n\t\tos.real_path(settings.vmodules_path)\n\t} else {\n\t\tsettings.vmodules_path\n\t}\n\treturn LinkedProject{\n\t\tname:        manifest.name\n\t\tproject_dir: os.real_path(vmod_location.vmod_folder)\n\t\tlink_path:   os.join_path(vmodules_path, mod_path)\n\t}\n}\n\nfn remove_symlink(path string) ! {\n\tos.rm(path) or {\n\t\t$if windows {\n\t\t\tos.rmdir(path)!\n\t\t} $else {\n\t\t\treturn err\n\t\t}\n\t}\n}\n\nfn cleanup_empty_link_parent_dirs(link_path string) {\n\tvmodules_path := if os.is_dir(settings.vmodules_path) {\n\t\tos.real_path(settings.vmodules_path)\n\t} else {\n\t\tsettings.vmodules_path\n\t}\n\tmut parent := os.dir(link_path)\n\tfor parent != vmodules_path && parent != os.dir(parent) {\n\t\tif !os.is_dir(parent) || !os.is_dir_empty(parent) {\n\t\t\tbreak\n\t\t}\n\t\tos.rmdir(parent) or { break }\n\t\tparent = os.dir(parent)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vpm/link_test.v",
    "content": "import os\nimport rand\nimport test_utils\n\nconst vexe = os.quoted_path(@VEXE)\nconst test_path = os.join_path(os.vtmp_dir(), 'vpm_link_test_${rand.ulid()}')\n\nfn testsuite_begin() {\n\ttest_utils.set_test_env(test_path)\n\tos.mkdir_all(test_path) or {}\n}\n\nfn testsuite_end() {\n\tos.rmdir_all(test_path) or {}\n}\n\nfn execute_in_dir(dir string, cmd string) os.Result {\n\told_dir := os.getwd()\n\tos.chdir(dir) or { return os.Result{\n\t\texit_code: -1\n\t\toutput:    'failed to chdir: ${err}'\n\t} }\n\tdefer {\n\t\tos.chdir(old_dir) or {}\n\t}\n\treturn os.execute(cmd)\n}\n\nfn test_link_and_unlink_current_project() {\n\tmodule_name := 'author.coollib'\n\tproject_path := os.join_path(test_path, 'project')\n\twrite_vmod(project_path, module_name) or {\n\t\tassert false, err.msg()\n\t\treturn\n\t}\n\tproject_subdir := os.join_path(project_path, 'src')\n\tos.mkdir_all(project_subdir) or {\n\t\tassert false, err.msg()\n\t\treturn\n\t}\n\tlink_path := os.join_path(test_path, 'author', 'coollib')\n\n\tlink_res := execute_in_dir(project_subdir, '${vexe} link')\n\tif link_res.exit_code != 0 && is_symlink_privilege_error(link_res.output) {\n\t\teprintln('Skipping symlink test due to missing privileges.')\n\t\treturn\n\t}\n\tassert link_res.exit_code == 0, link_res.output\n\tassert os.is_link(link_path), 'expected `${link_path}` to be a symlink'\n\tassert os.real_path(link_path) == os.real_path(project_path)\n\tassert link_res.output.contains('Linked `${module_name}`'), link_res.output\n\n\tlink_again_res := execute_in_dir(project_path, '${vexe} link')\n\tassert link_again_res.exit_code == 0, link_again_res.output\n\tassert link_again_res.output.contains('already linked')\n\t\t|| link_again_res.output.contains('already available'), link_again_res.output\n\n\tunlink_res := execute_in_dir(project_subdir, '${vexe} unlink')\n\tassert unlink_res.exit_code == 0, unlink_res.output\n\tassert !os.exists(link_path) && !os.is_link(link_path)\n\tassert !os.exists(os.join_path(test_path, 'author'))\n\tassert unlink_res.output.contains('Unlinked `${module_name}`'), unlink_res.output\n}\n\nfn test_link_without_vmod() {\n\tpath := os.join_path(test_path, 'no_manifest')\n\tos.mkdir_all(path) or {\n\t\tassert false, err.msg()\n\t\treturn\n\t}\n\tres := execute_in_dir(path, '${vexe} link')\n\tassert res.exit_code == 1, res.output\n\tassert res.output.contains('no `v.mod` file found'), res.output\n}\n\nfn write_vmod(path string, module_name string) ! {\n\tos.mkdir_all(path)!\n\tvmod_path := os.join_path(path, 'v.mod')\n\tvmod_contents := \"Module {\\n\\tname: '${module_name}'\\n\\tdescription: ''\\n\\tversion: '0.0.0'\\n\\tlicense: 'MIT'\\n\\tdependencies: []\\n}\\n\"\n\tos.write_file(vmod_path, vmod_contents)!\n}\n\nfn is_symlink_privilege_error(output string) bool {\n\tlower := output.to_lower()\n\treturn lower.contains('required privilege is not held') || lower.contains('symbolic link')\n}\n"
  },
  {
    "path": "cmd/tools/vpm/outdated.v",
    "content": "module main\n\nimport os\nimport sync.pool\n\npub struct OutdatedResult {\n\tname string\nmut:\n\toutdated bool\n}\n\nfn vpm_outdated() {\n\toutdated := get_outdated()\n\tif outdated.len > 0 {\n\t\tprintln('Outdated modules:')\n\t\tfor m in outdated {\n\t\t\tprintln('  ${m}')\n\t\t}\n\t} else {\n\t\tprintln('Modules are up to date.')\n\t}\n}\n\nfn get_outdated() []string {\n\tinstalled := get_installed_modules()\n\tif installed.len == 0 {\n\t\tprintln('No modules installed.')\n\t\texit(0)\n\t}\n\tmut pp := pool.new_pool_processor(\n\t\tcallback: fn (mut pp pool.PoolProcessor, idx int, wid int) &OutdatedResult {\n\t\t\tmut result := &OutdatedResult{\n\t\t\t\tname: pp.get_item[string](idx)\n\t\t\t}\n\t\t\tpath := get_path_of_existing_module(result.name) or { return result }\n\t\t\tresult.outdated = is_outdated(path)\n\t\t\treturn result\n\t\t}\n\t)\n\tpp.work_on_items(installed)\n\tmut outdated := []string{}\n\tfor res in pp.get_results[OutdatedResult]() {\n\t\tif res.outdated {\n\t\t\toutdated << res.name\n\t\t}\n\t}\n\treturn outdated\n}\n\nfn is_outdated(path string) bool {\n\tvcs := vcs_used_in_dir(path) or { return false }\n\targs := vcs_info[vcs].args\n\tmut outputs := []string{}\n\tfor step in args.outdated {\n\t\tcmd := [vcs.str(), args.path, os.quoted_path(path), step].join(' ')\n\t\tvpm_log(@FILE_LINE, @FN, 'cmd: ${cmd}')\n\t\tres := os.execute(cmd)\n\t\tvpm_log(@FILE_LINE, @FN, 'output: ${res.output}')\n\t\tif res.exit_code != 0 {\n\t\t\treturn false\n\t\t}\n\t\tif vcs == .hg {\n\t\t\t// HG uses only one outdated step. If it has not failed, the module is outdated.\n\t\t\treturn true\n\t\t}\n\t\toutputs << res.output\n\t}\n\t// Compare the current and latest origin commit sha.\n\treturn outputs[1] != outputs[2]\n}\n"
  },
  {
    "path": "cmd/tools/vpm/outdated_test.v",
    "content": "// vtest retry: 3\n// vtest build: !windows\nmodule main\n\nimport os\nimport rand\nimport test_utils { cmd_ok }\n\nconst test_path = os.join_path(os.vtmp_dir(), 'vpm_outdated_test_${rand.ulid()}')\n\nfn testsuite_begin() {\n\t$if !network ? {\n\t\teprintln('> skipping ${@FILE}, when `-d network` is missing')\n\t\texit(0)\n\t}\n\tdump(test_path)\n\ttest_utils.set_test_env(test_path)\n\tos.mkdir_all(test_path)!\n\tos.chdir(test_path)!\n}\n\nfn testsuite_end() {\n\tos.rmdir_all(test_path) or {}\n}\n\nfn test_is_outdated_git_module() {\n\tcmd_ok(@LOCATION, 'git clone https://github.com/vlang/libsodium.git')\n\tassert !is_outdated('libsodium')\n\tcmd_ok(@LOCATION, 'git -C libsodium reset --hard HEAD~')\n\tassert is_outdated('libsodium')\n\tcmd_ok(@LOCATION, 'git -C libsodium pull')\n\tassert !is_outdated('libsodium')\n}\n\nfn test_is_outdated_hg_module() {\n\t$if !check_mercurial_works ? {\n\t\treturn\n\t}\n\tos.find_abs_path_of_executable('hg') or {\n\t\teprintln('skipping test, since `hg` is not executable.')\n\t\treturn\n\t}\n\tcmd_ok(@LOCATION, 'hg clone https://www.mercurial-scm.org/repo/hello')\n\tassert !is_outdated('hello')\n\tcmd_ok(@LOCATION, 'hg --config extensions.strip= -R hello strip -r tip')\n\tassert is_outdated('hello')\n\tcmd_ok(@LOCATION, 'hg -R hello pull')\n\tassert !is_outdated('hello')\n}\n\nfn test_outdated() {\n\tfor m in ['pcre', 'libsodium', 'https://github.com/spytheman/vtray', 'nedpals.args'] {\n\t\tcmd_ok(@LOCATION, '${vexe} install ${m}')\n\t}\n\t// \"Outdate\" previously installed. Leave out `libsodium`.\n\tfor m in ['pcre', 'vtray', os.join_path('nedpals', 'args')] {\n\t\tcmd_ok(@LOCATION, 'git -C ${m} fetch --all')\n\t\tcmd_ok(@LOCATION, 'git -C ${m} reset --hard HEAD~')\n\t\tassert is_outdated(m)\n\t}\n\tres := cmd_ok(@LOCATION, '${vexe} outdated')\n\toutput := res.output.all_after('Outdated modules:')\n\tassert output.len > 0, output\n\tassert output.contains('pcre'), output\n\tassert output.contains('vtray'), output\n\tassert output.contains('nedpals.args'), output\n\tassert !output.contains('libsodium'), output\n}\n"
  },
  {
    "path": "cmd/tools/vpm/parse.v",
    "content": "module main\n\nimport os\nimport net.http\nimport v.vmod\n\nstruct Module {\nmut:\n\tname               string\n\turl                string\n\tversion            string // specifies the requested version.\n\ttmp_path           string\n\tinstall_path       string\n\tinstall_path_fmted string\n\tinstalled_version  string\n\tis_installed       bool\n\tis_external        bool\n\tvcs                ?VCS\n\tmanifest           vmod.Manifest\n}\n\nstruct Parser {\nmut:\n\tmodules              map[string]Module\n\tchecked_settings_vcs bool\n\terrors               int\n}\n\nenum ModuleKind {\n\tregistered\n\thttps\n\thttp\n\tssh\n\tlocal\n}\n\nfn parse_query(query []string, mut selector VpmInstallServerSelector) []Module {\n\tmut p := Parser{}\n\tfor m in query {\n\t\tp.parse_module(m, mut selector)\n\t}\n\tif p.errors > 0 && p.errors == query.len {\n\t\texit(1)\n\t}\n\treturn p.modules.values()\n}\n\nfn (mut p Parser) parse_module(m string, mut selector VpmInstallServerSelector) {\n\tkind := match true {\n\t\tm.starts_with('https://') { ModuleKind.https }\n\t\tm.starts_with('git@') { ModuleKind.ssh }\n\t\tm.starts_with('http://') { ModuleKind.http }\n\t\tis_local_repository(m) { ModuleKind.local }\n\t\telse { ModuleKind.registered }\n\t}\n\tident, version := if kind == .ssh {\n\t\tif m.count('@') > 1 {\n\t\t\tm.all_before_last('@'), m.all_after_last('@')\n\t\t} else {\n\t\t\tm, ''\n\t\t}\n\t} else {\n\t\tm.rsplit_once('@') or { m, '' }\n\t}\n\tkey := match kind {\n\t\t.registered { m }\n\t\t.ssh { ident.replace(':', '/') + at_version(version) }\n\t\telse { ident.all_after('//').trim_string_right('.git') + at_version(version) }\n\t}\n\tif key in p.modules {\n\t\treturn\n\t}\n\tprintln('Scanning `${m}`...')\n\tmut mod := if kind != ModuleKind.registered {\n\t\t// External module. The identifier is an URL.\n\t\tif kind == .http {\n\t\t\tvpm_warn('installing `${ident}` via http.',\n\t\t\t\tdetails: 'Support for `http` is deprecated, use `https` to ensure future compatibility.'\n\t\t\t)\n\t\t}\n\t\tpublisher, name := get_ident_from_url(if kind == .ssh {\n\t\t\t'https://' + ident['git@'.len..].replace(':', '/')\n\t\t} else {\n\t\t\tident\n\t\t}) or {\n\t\t\tvpm_error(err.msg())\n\t\t\tp.errors++\n\t\t\treturn\n\t\t}\n\t\t// Verify VCS. Only needed once for external modules.\n\t\tif !p.checked_settings_vcs {\n\t\t\tp.checked_settings_vcs = true\n\t\t\tsettings.vcs.is_executable() or {\n\t\t\t\tvpm_error(err.msg())\n\t\t\t\texit(1)\n\t\t\t}\n\t\t}\n\t\ttmp_path := get_tmp_path(os.join_path(publisher, name, version)) or {\n\t\t\tvpm_error('failed to get temporary directory for `${ident}`.', details: err.msg())\n\t\t\tp.errors++\n\t\t\treturn\n\t\t}\n\t\tsettings.vcs.clone(ident, version, tmp_path) or {\n\t\t\tvpm_error('failed to install `${ident}`.', details: err.msg())\n\t\t\tp.errors++\n\t\t\treturn\n\t\t}\n\t\tmanifest := get_manifest(tmp_path) or {\n\t\t\tvpm_error('failed to find `v.mod` for `${ident}${at_version(version)}`.',\n\t\t\t\tdetails: err.msg()\n\t\t\t)\n\t\t\trmdir_all(tmp_path) or {}\n\t\t\tp.errors++\n\t\t\treturn\n\t\t}\n\t\tmod_path := normalize_mod_path(os.join_path(if kind == .http { publisher } else { '' },\n\t\t\tmanifest.name))\n\t\tModule{\n\t\t\tname:         manifest.name\n\t\t\turl:          ident\n\t\t\tversion:      version\n\t\t\tinstall_path: os.real_path(os.join_path(settings.vmodules_path, mod_path))\n\t\t\tis_external:  true\n\t\t\ttmp_path:     tmp_path\n\t\t\tmanifest:     manifest\n\t\t}\n\t} else {\n\t\t// VPM registered module.\n\t\tinfo := get_mod_vpm_info_with_selector(ident, mut selector) or {\n\t\t\tvpm_error('failed to retrieve metadata for `${ident}`.', details: err.msg())\n\t\t\tp.errors++\n\t\t\treturn\n\t\t}\n\t\t// Verify VCS.\n\t\tvcs := if info.vcs != '' {\n\t\t\tinfo_vcs := vcs_from_str(info.vcs) or {\n\t\t\t\tvpm_error('skipping `${info.name}`, since it uses an unsupported version control system `${info.vcs}`.')\n\t\t\t\tp.errors++\n\t\t\t\treturn\n\t\t\t}\n\t\t\tinfo_vcs\n\t\t} else {\n\t\t\tVCS.git\n\t\t}\n\t\tvcs.is_executable() or {\n\t\t\tvpm_error(err.msg())\n\t\t\tp.errors++\n\t\t\treturn\n\t\t}\n\t\tmod_path := normalize_mod_path(info.name.replace('.', os.path_separator))\n\t\ttmp_path := get_tmp_path(os.join_path(mod_path, version)) or {\n\t\t\tvpm_error('failed to get temporary directory for `${ident}`.', details: err.msg())\n\t\t\tp.errors++\n\t\t\treturn\n\t\t}\n\t\tvcs.clone(info.url, version, tmp_path) or {\n\t\t\tvpm_error('failed to install `${ident}`.', details: err.msg())\n\t\t\tp.errors++\n\t\t\treturn\n\t\t}\n\t\tmanifest := get_manifest(tmp_path) or {\n\t\t\t// Add link with issue template requesting to add a manifest.\n\t\t\tmut details := ''\n\t\t\tnew_issue_url := '${info.url}/issues/new'\n\t\t\tverbose_println_more(@FILE_LINE, @FN, 'making a HEAD request to: ${new_issue_url} ...')\n\t\t\tif resp := http.head(new_issue_url) {\n\t\t\t\tif resp.status_code == 200 {\n\t\t\t\t\tissue_tmpl_url := '${info.url}/issues/new?title=Missing%20Manifest&body=${info.name}%20is%20missing%20a%20manifest,%20please%20consider%20adding%20a%20v.mod%20file%20with%20the%20modules%20metadata.'\n\t\t\t\t\tdetails = 'Please help us ensure future-compatibility, by adding a `v.mod` file or opening an issue at:\\n`${issue_tmpl_url}`'\n\t\t\t\t}\n\t\t\t}\n\t\t\tvpm_warn('`${info.name}` is missing a manifest file.', details: details)\n\t\t\tvpm_log(@FILE_LINE, @FN, 'vpm manifest detection error: ${err}')\n\t\t\tvmod.Manifest{}\n\t\t}\n\t\tModule{\n\t\t\tname:         info.name\n\t\t\turl:          info.url\n\t\t\tversion:      version\n\t\t\tvcs:          vcs\n\t\t\tinstall_path: os.real_path(os.join_path(settings.vmodules_path, mod_path))\n\t\t\ttmp_path:     tmp_path\n\t\t\tmanifest:     manifest\n\t\t}\n\t}\n\tmod.install_path_fmted = fmt_mod_path(mod.install_path)\n\tmod.get_installed()\n\tp.modules[key] = mod\n\tif mod.manifest.dependencies.len > 0 {\n\t\tverbose_println('Found ${mod.manifest.dependencies.len} dependencies for `${mod.name}`: ${mod.manifest.dependencies}.')\n\t\tfor d in mod.manifest.dependencies {\n\t\t\tp.parse_module(d, mut selector)\n\t\t}\n\t}\n}\n\nfn is_local_repository(query string) bool {\n\tif query.starts_with('file://') {\n\t\treturn true\n\t}\n\tmut path_candidates := [query]\n\tif !query.starts_with('git@') {\n\t\tident, _ := query.rsplit_once('@') or { query, '' }\n\t\tif ident != query {\n\t\t\tpath_candidates << ident\n\t\t}\n\t}\n\tfor candidate in path_candidates {\n\t\tpath := os.expand_tilde_to_home(candidate)\n\t\tif os.is_abs_path(path) || path.starts_with('./') || path.starts_with('../')\n\t\t\t|| path.starts_with('~/') {\n\t\t\treturn true\n\t\t}\n\t\tif os.exists(path) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfn (mut m Module) get_installed() {\n\trefs := os.execute_opt('git ls-remote --refs ${m.install_path}') or { return }\n\tvpm_log(@FILE_LINE, @FN, 'refs: ${refs}')\n\tm.is_installed = true\n\t// In case the head just temporarily matches a tag, make sure that there\n\t// really is a version installation before adding it as `installed_version`.\n\t// NOTE: can be refined for branch installations. E.g., for `sdl`.\n\tif refs.output.contains('refs/tags/') {\n\t\ttag := refs.output.all_after_last('refs/tags/').all_before('\\n').trim_space()\n\t\thead := if refs.output.contains('refs/heads/') {\n\t\t\trefs.output.all_after_last('refs/heads/').all_before('\\n').trim_space()\n\t\t} else {\n\t\t\ttag\n\t\t}\n\t\tvpm_log(@FILE_LINE, @FN, 'head: ${head}, tag: ${tag}')\n\t\tif tag == head {\n\t\t\tm.installed_version = tag\n\t\t}\n\t}\n}\n\nfn get_tmp_path(relative_path string) !string {\n\ttmp_path := os.real_path(os.join_path(settings.tmp_path, relative_path))\n\tif os.exists(tmp_path) {\n\t\t// It's unlikely that the tmp_path already exists, but it might\n\t\t// occur if vpm was canceled during an installation or update.\n\t\trmdir_all(tmp_path)!\n\t}\n\treturn tmp_path\n}\n"
  },
  {
    "path": "cmd/tools/vpm/remove_test.v",
    "content": "// vtest retry: 3\nimport os\nimport rand\nimport test_utils\n\nconst vexe = os.quoted_path(@VEXE)\nconst test_path = os.join_path(os.vtmp_dir(), 'vpm_remove_test_${rand.ulid()}')\n\nfn testsuite_begin() {\n\t$if !network ? {\n\t\teprintln('> skipping ${@FILE}, when `-d network` is missing')\n\t\texit(0)\n\t}\n\tdump(test_path)\n\ttest_utils.set_test_env(test_path)\n}\n\nfn testsuite_end() {\n\tos.rmdir_all(test_path) or {}\n}\n\nfn test_remove() {\n\tos.execute_or_exit('${vexe} install https://github.com/hungrybluedev/xlsx')\n\tmod_path := os.join_path(test_path, 'xlsx')\n\tassert os.is_dir(mod_path)\n\tres := os.execute('${vexe} remove xlsx')\n\tassert !os.exists(mod_path)\n}\n"
  },
  {
    "path": "cmd/tools/vpm/search.v",
    "content": "module main\n\nimport os\nimport v.help\n\nfn vpm_search(keywords []string) {\n\tsearch_keys := keywords.map(it.replace('_', '-'))\n\tif settings.is_help {\n\t\thelp.print_and_exit('search')\n\t}\n\tif search_keys.len == 0 {\n\t\tvpm_error('specify at least one keyword to search for.')\n\t\texit(2)\n\t}\n\tmodules := get_all_modules_for_search()\n\tinstalled_modules := get_installed_modules()\n\tjoined := search_keys.join(', ')\n\tmut index := 0\n\tfor mod in modules {\n\t\tfor k in search_keys {\n\t\t\tif !mod.contains(k) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif index == 0 {\n\t\t\t\tprintln('Search results for `${joined}`:\\n')\n\t\t\t}\n\t\t\tindex++\n\t\t\tmut parts := mod.split('.')\n\t\t\t// in case the author isn't present\n\t\t\tif parts.len == 1 {\n\t\t\t\tparts << parts[0]\n\t\t\t\tparts[0] = ' '\n\t\t\t} else {\n\t\t\t\tparts[0] = ' by ${parts[0]} '\n\t\t\t}\n\t\t\tinstalled := if mod in installed_modules { ' (installed)' } else { '' }\n\t\t\tprintln('${index}. ${parts[1]}${parts[0]}[${mod}]${installed}')\n\t\t\tbreak\n\t\t}\n\t}\n\tif index == 0 {\n\t\tvroot := os.real_path(os.dir(vexe))\n\t\tmut messages := ['No module(s) found for `${joined}` .']\n\t\tfor vlibmod in search_keys {\n\t\t\tif os.is_dir(os.join_path(vroot, 'vlib', vlibmod)) {\n\t\t\t\tmessages << 'There is already an existing `${vlibmod}` module in vlib, so you can just `import ${vlibmod}` .'\n\t\t\t}\n\t\t}\n\t\tfor m in messages {\n\t\t\tprintln(m)\n\t\t}\n\t} else {\n\t\teprintln('\\nUse `v install author_name.module_name` to install the module.')\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vpm/search_test.v",
    "content": "// vtest retry: 3\nmodule main\n\nimport test_utils { cmd_ok }\n\nfn testsuite_begin() {\n\t$if !network ? {\n\t\teprintln('> skipping ${@FILE}, when `-d network` is missing')\n\t\texit(0)\n\t}\n\tunbuffer_stdout()\n}\n\nfn test_search_ui() {\n\tres := cmd_ok(@LOCATION, '${vexe} search ui')\n\tdump(res)\n\tassert res.output.contains('1. ui'), res.output\n}\n"
  },
  {
    "path": "cmd/tools/vpm/settings.v",
    "content": "module main\n\nimport os\nimport os.cmdline\nimport log\nimport v.vmod\n\nstruct VpmSettings {\nmut:\n\tis_help               bool\n\tis_once               bool\n\tis_verbose            bool\n\tis_force              bool\n\tis_local              bool\n\tserver_urls           []string\n\tmirror_urls           []string\n\tvmodules_path         string\n\ttmp_path              string\n\tno_dl_count_increment bool\n\t// To ensure that some test scenarios with conflicting module directory names do not get stuck in prompts.\n\t// It is intended that VPM does not display a prompt when `VPM_FAIL_ON_PROMPT` is set.\n\tfail_on_prompt bool\n\t// git is used by default. URL installations can specify `--hg`. For already installed modules\n\t// and VPM modules that specify a different VCS in their `v.mod`, the VCS is validated separately.\n\tvcs    VCS\n\tlogger &log.Logger\n}\n\nfn init_settings() VpmSettings {\n\targs := os.args[1..]\n\topts := cmdline.only_options(args)\n\tcmds := cmdline.only_non_options(args)\n\n\tglobal_vmodules_path := os.vmodules_dir()\n\tmut vmodules_path := global_vmodules_path.clone()\n\tis_local := '-l' in opts || '--local' in opts\n\tif is_local {\n\t\twrkdir := os.getwd()\n\t\tmut mcache := vmod.get_cache()\n\t\tvmod_file_location := mcache.get_by_folder(wrkdir)\n\t\tproject_root_dir := if vmod_file_location.vmod_file.len == 0 {\n\t\t\twrkdir\n\t\t} else {\n\t\t\tvmod_file_location.vmod_folder\n\t\t}\n\t\tvmodules_path = os.join_path(project_root_dir, 'modules')\n\t\tverbose_println('init_settings, local installation, wrkdir: ${wrkdir} | project_root_dir: ${project_root_dir} | vmodules_path: ${vmodules_path}')\n\t}\n\tverbose_println('init_settings, final is_local: ${is_local} | vmodules_path: `${vmodules_path}`')\n\n\tis_no_inc := os.getenv('VPM_NO_INCREMENT') != ''\n\tis_dbg := os.getenv('VPM_DEBUG') != ''\n\tis_ci := os.getenv('CI') != ''\n\n\tmut logger := &log.Log{}\n\tlogger.set_output_stream(os.stderr())\n\tif is_dbg {\n\t\tlogger.set_level(.debug)\n\t}\n\tif !is_ci && !is_dbg {\n\t\t// Log by default, but only in the global location, no matter if --local was passed:\n\t\tcache_path := os.join_path(global_vmodules_path, '.cache')\n\t\tos.mkdir_all(cache_path, mode: 0o700) or { panic(err) }\n\t\tlogger.set_output_path(os.join_path(cache_path, 'vpm.log'))\n\t}\n\n\treturn VpmSettings{\n\t\tis_help:               '-h' in opts || '--help' in opts || 'help' in cmds\n\t\tis_once:               '--once' in opts\n\t\tis_verbose:            '-v' in opts || '--verbose' in opts\n\t\tis_force:              '-f' in opts || '--force' in opts\n\t\tis_local:              is_local\n\t\tserver_urls:           get_server_urls_from_args(args)\n\t\tmirror_urls:           get_mirror_urls_from_args(args)\n\t\tvcs:                   if '--hg' in opts { .hg } else { .git }\n\t\tvmodules_path:         vmodules_path\n\t\ttmp_path:              os.join_path(os.vtmp_dir(), 'vpm_modules')\n\t\tno_dl_count_increment: is_ci || is_no_inc\n\t\tfail_on_prompt:        os.getenv('VPM_FAIL_ON_PROMPT') != ''\n\t\tlogger:                logger\n\t}\n}\n\nfn get_server_urls_from_args(args []string) []string {\n\tmut server_urls := []string{}\n\tserver_urls << cmdline.options(args, '-server-url')\n\tserver_urls << cmdline.options(args, '--server-url')\n\tserver_urls << cmdline.options(args, '--server-urls')\n\treturn unique_server_urls(server_urls)\n}\n\nfn get_mirror_urls_from_args(args []string) []string {\n\tmut mirror_urls := []string{}\n\tmirror_urls << cmdline.options(args, '-m')\n\tmirror_urls << cmdline.options(args, '--mirror')\n\treturn unique_server_urls(mirror_urls)\n}\n\nfn unique_server_urls(urls []string) []string {\n\tmut unique_urls := []string{}\n\tfor raw_url in urls {\n\t\turl := normalize_server_url(raw_url)\n\t\tif url == '' || url in unique_urls {\n\t\t\tcontinue\n\t\t}\n\t\tunique_urls << url\n\t}\n\treturn unique_urls\n}\n\nfn normalize_server_url(url string) string {\n\treturn url.trim_space().trim_string_right('/')\n}\n\nfn parse_server_urls(args []string) []string {\n\tmut urls := []string{}\n\tmut i := 0\n\tfor i < args.len {\n\t\tif args[i] in server_url_option_names {\n\t\t\ti++\n\t\t\tif i < args.len {\n\t\t\t\turl := normalize_server_url(args[i])\n\t\t\t\tif url != '' && url !in urls {\n\t\t\t\t\turls << url\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\ti++\n\t}\n\treturn urls\n}\n"
  },
  {
    "path": "cmd/tools/vpm/settings_test.v",
    "content": "module main\n\nfn test_get_server_urls_from_args_supports_all_flags() {\n\targs := ['install', '-server-url', 'https://one.example/', '--server-url',\n\t\t' https://two.example ', '--server-urls', 'https://one.example']\n\tserver_urls := get_server_urls_from_args(args)\n\tassert server_urls == ['https://one.example', 'https://two.example']\n}\n\nfn test_get_mirror_urls_from_args_supports_short_and_long_flags() {\n\targs := ['install', '-m', 'https://mirror1.example/', '--mirror', 'https://mirror2.example',\n\t\t'-m', 'https://mirror1.example']\n\tmirror_urls := get_mirror_urls_from_args(args)\n\tassert mirror_urls == ['https://mirror1.example', 'https://mirror2.example']\n}\n\nfn test_build_install_server_urls_prioritizes_default_servers() {\n\tserver_urls := build_install_server_urls(['https://official1.example',\n\t\t'https://official2.example'], ['https://mirror1.example', 'https://official2.example'])\n\tassert server_urls == ['https://official1.example', 'https://official2.example',\n\t\t'https://mirror1.example']\n}\n\nfn test_metadata_server_urls_uses_selected_server() {\n\tmut selector := VpmInstallServerSelector{\n\t\tcandidate_urls: ['https://official.example', 'https://mirror.example']\n\t}\n\tassert selector.metadata_server_urls() == ['https://official.example', 'https://mirror.example']\n\tselector.selected_url = 'https://mirror.example'\n\tassert selector.metadata_server_urls() == ['https://mirror.example']\n}\n"
  },
  {
    "path": "cmd/tools/vpm/test_utils/utils.v",
    "content": "module test_utils\n\nimport os\nimport net\nimport time\n\npub fn set_test_env(test_path string) {\n\tunbuffer_stdout()\n\tos.setenv('VMODULES', test_path, true)\n\tos.setenv('VPM_DEBUG', '', true)\n\tos.setenv('VPM_NO_INCREMENT', '1', true)\n\tos.setenv('VPM_FAIL_ON_PROMPT', '1', true)\n\t// Note: setting a local VTMP here, is *very important*, because VTMP is used for\n\t// the destination of the temporary clones done by the child `v install` processes.\n\t// If it is not done, then there is a small chance, that multiple parallel tests\n\t// can do clones to the same exact folders at the same time, which can make them\n\t// fail on the CI, with hard to diagnose spurious errors.\n\tos.setenv('VTMP', os.join_path(test_path, 'vtmp'), true)\n}\n\npub fn hg_serve(hg_path string, path string, start_port int) (&os.Process, int) {\n\tmut port := start_port\n\tfor {\n\t\tif mut l := net.listen_tcp(.ip6, ':${port}') {\n\t\t\tl.close() or { panic(err) }\n\t\t\tbreak\n\t\t}\n\t\tport++\n\t}\n\tmut p := os.new_process(hg_path)\n\tp.set_work_folder(path)\n\tp.set_args(['serve', '--print-url', '--port', port.str()])\n\tp.set_redirect_stdio()\n\tp.run()\n\tmut i := 0\n\tfor p.is_alive() {\n\t\tif i == 500 { // Wait max. 5 seconds.\n\t\t\tp.signal_kill()\n\t\t\teprintln('Failed to serve mercurial repository on localhost.')\n\t\t\texit(1)\n\t\t}\n\t\tif p.stdout_read().contains(':${port}') {\n\t\t\tbreak\n\t\t}\n\t\ttime.sleep(10 * time.millisecond)\n\t\ti++\n\t}\n\treturn p, port\n}\n\npub fn cmd_ok(location string, cmd string) os.Result {\n\tprintln('>   cmd_ok for cmd: \"${cmd}\"')\n\tres := os.execute(cmd)\n\tassert res.exit_code == 0, 'success expected, but not found\\n    location: ${location}\\n    cmd:\\n${cmd}\\n    res:\\n${res}\\n'\n\treturn res\n}\n\npub fn cmd_fail(location string, cmd string) os.Result {\n\tprintln('> cmd_fail for cmd: \"${cmd}\"')\n\tres := os.execute(cmd)\n\tassert res.exit_code == 1, 'failure expected, but not found\\n    location: ${location}\\n    cmd:\\n${cmd}\\n    res:\\n${res}\\n'\n\treturn res\n}\n"
  },
  {
    "path": "cmd/tools/vpm/update.v",
    "content": "module main\n\nimport os\nimport sync.pool\nimport v.help\n\nstruct UpdateSession {\n\tidents []string\n}\n\npub struct UpdateResult {\nmut:\n\tsuccess bool\n}\n\nfn vpm_update(query []string) {\n\tif settings.is_help {\n\t\thelp.print_and_exit('update')\n\t}\n\tidents := if query.len == 0 {\n\t\tget_installed_modules()\n\t} else {\n\t\tquery.clone()\n\t}\n\tmut pp := pool.new_pool_processor(callback: update_module)\n\tctx := UpdateSession{idents}\n\tpp.set_shared_context(ctx)\n\tpp.work_on_items(idents)\n\tmut errors := 0\n\tfor res in pp.get_results[UpdateResult]() {\n\t\tif !res.success {\n\t\t\terrors++\n\t\t\tcontinue\n\t\t}\n\t}\n\tif errors > 0 {\n\t\texit(1)\n\t}\n}\n\nfn update_module(mut pp pool.PoolProcessor, idx int, wid int) &UpdateResult {\n\tident := pp.get_item[string](idx)\n\t// Usually, the module `ident`ifier. `get_name_from_url` is only relevant for `v update <module_url>`.\n\tname := get_name_from_url(ident) or { ident }\n\tinstall_path := get_path_of_existing_module(ident) or {\n\t\tvpm_error('failed to find path for `${name}`.', verbose: true)\n\t\treturn &UpdateResult{}\n\t}\n\tvcs := vcs_used_in_dir(install_path) or {\n\t\tvpm_error('failed to find version control system for `${name}`.', verbose: true)\n\t\treturn &UpdateResult{}\n\t}\n\tvcs.is_executable() or {\n\t\tvpm_error(err.msg())\n\t\treturn &UpdateResult{}\n\t}\n\targs := vcs_info[vcs].args\n\tcmd := [vcs.str(), args.path, os.quoted_path(install_path), args.update].join(' ')\n\tvpm_log(@FILE_LINE, @FN, 'cmd: ${cmd}')\n\tprintln('Updating module `${name}` in `${fmt_mod_path(install_path)}`...')\n\tres := os.execute_opt(cmd) or {\n\t\tvpm_error('failed to update module `${name}` in `${install_path}`.', details: err.msg())\n\t\treturn &UpdateResult{}\n\t}\n\tvpm_log(@FILE_LINE, @FN, 'cmd output: ${res.output.trim_space()}')\n\tif res.output.contains('Already up to date.') {\n\t\tprintln('Skipped module `${ident}`. Already up to date.')\n\t} else {\n\t\tprintln('Updated module `${ident}`.')\n\t}\n\t// Don't bail if the download count increment has failed.\n\tincrement_module_download_count(name, '') or { vpm_error(err.msg(), verbose: true) }\n\tctx := unsafe { &UpdateSession(pp.get_shared_context()) }\n\tvpm_log(@FILE_LINE, @FN, 'ident: ${ident}; ctx: ${ctx}')\n\tresolve_dependencies(get_manifest(install_path), ctx.idents)\n\treturn &UpdateResult{true}\n}\n"
  },
  {
    "path": "cmd/tools/vpm/update_test.v",
    "content": "// vtest build: !musl? && !sanitized_job?\n// vtest retry: 3\nimport os\nimport rand\nimport test_utils { cmd_fail, cmd_ok }\n\nconst v = os.quoted_path(@VEXE)\nconst test_path = os.join_path(os.vtmp_dir(), 'vpm_update_test_${rand.ulid()}')\n\nfn testsuite_begin() {\n\t$if !network ? {\n\t\teprintln('> skipping ${@FILE}, when `-d network` is missing')\n\t\texit(0)\n\t}\n\tdump(test_path)\n\ttest_utils.set_test_env(test_path)\n}\n\nfn testsuite_end() {\n\tos.rmdir_all(test_path) or {}\n}\n\n// Tests if `v update` detects installed modules and runs successfully.\nfn test_update() {\n\tos.execute_or_exit('${v} install pcre')\n\tos.execute_or_exit('${v} install nedpals.args')\n\tos.execute_or_exit('${v} install https://github.com/spytheman/vtray')\n\tres := cmd_ok(@LOCATION, '${v} update')\n\tassert res.output.contains('Updating module `pcre`'), res.output\n\tassert res.output.contains('Updating module `nedpals.args`'), res.output\n\tassert res.output.contains('Updating module `vtray`'), res.output\n\tassert res.output.contains('Skipping download count increment for `nedpals.args`.'), res.output\n\tassert res.output.contains('Skipping download count increment for `pcre`.'), res.output\n}\n\nfn test_update_idents() {\n\tmut res := cmd_ok(@LOCATION, '${v} update pcre')\n\tassert res.output.contains('Updating module `pcre`'), res.output\n\tres = cmd_ok(@LOCATION, '${v} update nedpals.args vtray')\n\tassert res.output.contains('Updating module `vtray`'), res.output\n\tassert res.output.contains('Updating module `nedpals.args`'), res.output\n\t// Update installed module using its url.\n\tres = cmd_ok(@LOCATION, '${v} update https://github.com/spytheman/vtray')\n\tassert res.output.contains('Updating module `vtray`'), res.output\n\t// Try update not installed.\n\tres = cmd_fail(@LOCATION, '${v} update vsl')\n\tassert res.output.contains('failed to find `vsl`'), res.output\n\t// Try update mixed.\n\tres = cmd_fail(@LOCATION, '${v} update pcre vsl')\n\tassert res.output.contains('Updating module `pcre`'), res.output\n\tassert res.output.contains('failed to find `vsl`'), res.output\n}\n"
  },
  {
    "path": "cmd/tools/vpm/vcs.v",
    "content": "module main\n\nimport os\nimport semver\n\n// Supported version control system commands.\nenum VCS {\n\tgit\n\thg\n}\n\nstruct VCSInfo {\n\tdir  string @[required]\n\targs struct {\n\t\tinstall  string   @[required]\n\t\tversion  string   @[required] // flag to specify a version, added to install.\n\t\tpath     string   @[required] // flag to specify a path. E.g., used to explicitly work on a path during multithreaded updating.\n\t\tupdate   string   @[required]\n\t\toutdated []string @[required]\n\t}\n}\n\nconst vcs_info = init_vcs_info() or {\n\tvpm_error(err.msg())\n\texit(1)\n}\n\nfn init_vcs_info() !map[VCS]VCSInfo {\n\tgit_installed_raw_ver := parse_git_version(os.execute_opt('git --version')!.output) or { '' }\n\tgit_installed_ver := semver.from(git_installed_raw_ver)!\n\tgit_submod_filter_ver := semver.from('2.36.0')!\n\tmut git_install_cmd := 'clone --recursive'\n\tif os.user_os() != 'windows' {\n\t\t// The variation of environment factors on windows is too high;\n\t\t// the following options are known to work well on != windows,\n\t\t// but can sometimes cause failures on windows for yet unknown reasons,\n\t\t// see https://discord.com/channels/592103645835821068/665558664949530644/1345422482974310440\n\t\t// for more details, about why this is now allowed only on != windows platforms.\n\t\tgit_install_cmd += ' --filter=blob:none'\n\t\tif git_installed_ver >= git_submod_filter_ver {\n\t\t\tgit_install_cmd += ' --shallow-submodules'\n\t\t\tgit_install_cmd += ' --also-filter-submodules'\n\t\t}\n\t}\n\treturn {\n\t\tVCS.git: VCSInfo{\n\t\t\tdir:  '.git'\n\t\t\targs: struct {\n\t\t\t\tinstall:  git_install_cmd\n\t\t\t\tversion:  '--single-branch -b'\n\t\t\t\tupdate:   'pull --recurse-submodules' // pulling with `--depth=1` leads to conflicts when the upstream has more than 1 new commits.\n\t\t\t\tpath:     '-C'\n\t\t\t\toutdated: ['fetch', 'rev-parse @', 'rev-parse @{u}']\n\t\t\t}\n\t\t}\n\t\tVCS.hg:  VCSInfo{\n\t\t\tdir:  '.hg'\n\t\t\targs: struct {\n\t\t\t\tinstall:  'clone'\n\t\t\t\tversion:  '--rev'\n\t\t\t\tupdate:   'pull --update'\n\t\t\t\tpath:     '-R'\n\t\t\t\toutdated: ['incoming']\n\t\t\t}\n\t\t}\n\t}\n}\n\nfn (vcs VCS) clone(url string, version string, path string) ! {\n\targs := vcs_info[vcs].args\n\tversion_opt := if version != '' { '${args.version} ${version}' } else { '' }\n\tcmd := [vcs.str(), args.install, version_opt, url, os.quoted_path(path)].join(' ')\n\tvpm_log(@FILE_LINE, @FN, 'cmd: ${cmd}')\n\tres := os.execute_opt(cmd)!\n\tvpm_log(@FILE_LINE, @FN, 'cmd output: ${res.output}')\n}\n\nfn (vcs &VCS) is_executable() ! {\n\tcmd := vcs.str()\n\tos.find_abs_path_of_executable(cmd) or {\n\t\treturn error('VPM requires that `${cmd}` is executable.')\n\t}\n}\n\nfn vcs_used_in_dir(dir string) ?VCS {\n\tfor vcs, info in vcs_info {\n\t\tif os.is_dir(os.real_path(os.join_path(dir, info.dir))) {\n\t\t\treturn vcs\n\t\t}\n\t}\n\treturn none\n}\n\nfn vcs_from_str(str string) ?VCS {\n\treturn match str {\n\t\t'git' { .git }\n\t\t'hg' { .hg }\n\t\telse { none }\n\t}\n}\n\n// parse_git_version retrieves only the stable version part of the output of `git version`.\n// For example: parse_git_version('git version 2.39.3')! will return just '2.39.3'.\npub fn parse_git_version(version string) !string {\n\tgit_version_start := 'git version '\n\t// The output from `git version` varies, depending on how git was compiled. Here are some examples:\n\t// `git version 2.44.0` when compiled from source, or from brew on macos.\n\t// `git version 2.39.3 (Apple Git-146)` on macos with XCode's cli tools.\n\t// `git version 2.44.0.windows.1` on windows's Git Bash shell.\n\tif !version.starts_with(git_version_start) {\n\t\treturn error('should start with `${git_version_start}`')\n\t}\n\tsuffixed := version.all_after(git_version_start).all_before(' ').trim_space()\n\tparts := suffixed.split('.')\n\tpure_version_parts := parts[0..3]\n\tspure := pure_version_parts.join('.')\n\treturn spure\n}\n"
  },
  {
    "path": "cmd/tools/vpm/vcs_test.v",
    "content": "module main\n\nfn test_parse_git_version() {\n\tif _ := parse_git_version('abcd') {\n\t\tassert false\n\t}\n\tassert parse_git_version('git version 2.44.0.windows.1')! == '2.44.0'\n\tassert parse_git_version('git version 2.34.0')! == '2.34.0'\n\tassert parse_git_version('git version 2.39.3 (Apple Git-146)')! == '2.39.3'\n\tassert parse_git_version('git version 2.51.1.dirty')! == '2.51.1'\n}\n"
  },
  {
    "path": "cmd/tools/vpm/vpm.v",
    "content": "// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nmodule main\n\nimport os\nimport os.cmdline\nimport rand\nimport v.help\nimport v.vmod\n\nconst server_url_option_names = ['-m', '--mirror', '-server-url', '--server-url', '--server-urls']\nconst settings = init_settings()\nconst default_vpm_server_urls = ['https://vpm.vlang.io', 'https://vpm.url4e.com']\nconst vpm_server_urls = rand.shuffle_clone(default_vpm_server_urls) or { [] } // ensure that all queries are distributed fairly\nconst valid_vpm_commands = ['help', 'search', 'install', 'link', 'update', 'upgrade', 'outdated',\n\t'list', 'remove', 'show', 'unlink']\nconst excluded_dirs = ['.cache', 'vlib']\n\nfn main() {\n\tunbuffer_stdout()\n\tos.setenv(selected_server_url_env, '', true)\n\t// This tool is intended to be launched by the v frontend,\n\t// which provides the path to V inside os.getenv('VEXE')\n\t// args are: vpm [options] SUBCOMMAND module names\n\tvpm_log_header('vpm start')\n\tdefer {\n\t\tvpm_log_header('vpm exit')\n\t}\n\targs := os.args[1..]\n\tparams := cmdline.only_non_options(args)\n\tvpm_log(@FILE_LINE, @FN, 'params: ${params}')\n\tif params.len < 1 {\n\t\thelp.print_and_exit('vpm', exit_code: 5)\n\t}\n\tvpm_command := parse_vpm_command(args)\n\tif vpm_command == '' {\n\t\thelp.print_and_exit('vpm', exit_code: 5)\n\t}\n\tmut query := parse_query_args(args, vpm_command)\n\tvpm_log(@FILE_LINE, @FN, 'query: ${query}')\n\tensure_vmodules_dir_exist()\n\tmatch vpm_command {\n\t\t'help' {\n\t\t\thelp.print_and_exit('vpm')\n\t\t}\n\t\t'search' {\n\t\t\tvpm_search(query)\n\t\t}\n\t\t'install' {\n\t\t\tvpm_install(query)\n\t\t}\n\t\t'link' {\n\t\t\tvpm_link(query)\n\t\t}\n\t\t'update' {\n\t\t\tvpm_update(query)\n\t\t}\n\t\t'upgrade' {\n\t\t\tvpm_upgrade()\n\t\t}\n\t\t'outdated' {\n\t\t\tvpm_outdated()\n\t\t}\n\t\t'list' {\n\t\t\tvpm_list()\n\t\t}\n\t\t'remove' {\n\t\t\tvpm_remove(query)\n\t\t}\n\t\t'show' {\n\t\t\tvpm_show(query)\n\t\t}\n\t\t'unlink' {\n\t\t\tvpm_unlink(query)\n\t\t}\n\t\telse {\n\t\t\t// Unreachable in regular usage. V will catch unknown commands beforehand.\n\t\t\tvpm_error('unknown command \"${vpm_command}\"')\n\t\t\thelp.print_and_exit('vpm', exit_code: 3)\n\t\t}\n\t}\n}\n\nfn parse_vpm_command(args []string) string {\n\tmut skip_next := false\n\tfor arg in args {\n\t\tif skip_next {\n\t\t\tskip_next = false\n\t\t\tcontinue\n\t\t}\n\t\tif arg in server_url_option_names {\n\t\t\tskip_next = true\n\t\t\tcontinue\n\t\t}\n\t\tif arg in valid_vpm_commands {\n\t\t\treturn arg\n\t\t}\n\t}\n\treturn ''\n}\n\nfn parse_query_args(args []string, vpm_command string) []string {\n\tmut query := []string{}\n\tmut skip_next := false\n\tmut has_found_command := false\n\tfor arg in args {\n\t\tif skip_next {\n\t\t\tskip_next = false\n\t\t\tcontinue\n\t\t}\n\t\tif arg in server_url_option_names {\n\t\t\tskip_next = true\n\t\t\tcontinue\n\t\t}\n\t\tif !has_found_command {\n\t\t\tif arg == vpm_command {\n\t\t\t\thas_found_command = true\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif arg.starts_with('-') {\n\t\t\tcontinue\n\t\t}\n\t\tquery << arg\n\t}\n\treturn query\n}\n\nfn vpm_upgrade() {\n\toutdated := get_outdated()\n\tif outdated.len > 0 {\n\t\tvpm_update(outdated)\n\t} else {\n\t\tprintln('Modules are up to date.')\n\t}\n}\n\nfn vpm_list() {\n\tinstalled := get_installed_modules()\n\tif installed.len == 0 {\n\t\tprintln('You have no modules installed.')\n\t\texit(0)\n\t}\n\tfor m in installed {\n\t\tprintln(m)\n\t}\n}\n\nfn vpm_remove(query []string) {\n\tif settings.is_help {\n\t\thelp.print_and_exit('remove')\n\t}\n\tif query.len == 0 {\n\t\tvpm_error('specify at least one module name for removal.')\n\t\texit(2)\n\t}\n\tfor m in query {\n\t\tfinal_module_path := get_path_of_existing_module(m) or { continue }\n\t\tprintln('Removing module \"${m}\" from ${fmt_mod_path(final_module_path)} ...')\n\t\tvpm_log(@FILE_LINE, @FN, 'removing: ${final_module_path}')\n\t\trmdir_all(final_module_path) or { vpm_error(err.msg(), verbose: true) }\n\t\t// Delete author directory if it is empty.\n\t\tauthor := m.split('.')[0]\n\t\tauthor_dir := os.real_path(os.join_path(settings.vmodules_path, author))\n\t\tif !os.exists(author_dir) {\n\t\t\tcontinue\n\t\t}\n\t\tif os.is_dir_empty(author_dir) {\n\t\t\tverbose_println('Removing author folder ${author_dir}')\n\t\t\trmdir_all(author_dir) or { vpm_error(err.msg(), verbose: true) }\n\t\t}\n\t}\n}\n\nfn vpm_show(query []string) {\n\tinstalled_modules := get_installed_modules()\n\tfor m in query {\n\t\tif m !in installed_modules {\n\t\t\tinfo := get_mod_vpm_info(m) or { continue }\n\t\t\tprint('Name: ${info.name}\nHomepage: ${info.url}\nDownloads: ${info.nr_downloads}\nInstalled: False\n--------\n')\n\t\t\tcontinue\n\t\t}\n\t\tpath := os.join_path(settings.vmodules_path, m.replace('.', os.path_separator))\n\t\tmod := vmod.from_file(os.join_path(path, 'v.mod')) or { continue }\n\t\tprint('Name: ${mod.name}\nVersion: ${mod.version}\nDescription: ${mod.description}\nHomepage: ${mod.repo_url}\nAuthor: ${mod.author}\nLicense: ${mod.license}\nLocation: ${path}\nRequires: ${mod.dependencies.join(', ')}\n--------\n')\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vquest.v",
    "content": "module main\n\nimport os\nimport cli\nimport net.http\nimport net.urllib\nimport json\nimport rand\nimport term\n\nconst search_endpoint = 'https://api.github.com/search/issues'\nconst issue_endpoint = 'https://api.github.com/repos/vlang/v/issues'\nconst confirm_search_query = 'repo:vlang/v is:issue is:open -label:\"Status: Confirmed\"'\nconst fix_search_query = 'repo:vlang/v is:issue is:open'\nconst feature_search_query = 'repo:vlang/v is:issue state:open label:\"Feature/Enhancement Request\"'\nconst per_page = 100\nconst max_search_results = 1000\n\nstruct SearchResponse {\n\ttotal_count int\n\titems       []Issue\n}\n\nstruct Issue {\n\tnumber   int\n\ttitle    string\n\thtml_url string\n\tbody     string\n\tlabels   []Label\n}\n\nstruct Label {\n\tname string\n}\n\nstruct IssueDetails {\n\tnumber   int\n\ttitle    string\n\thtml_url string\n\tbody     string\n\tlabels   []Label\n\tstate    string\n}\n\nfn main() {\n\t// the 0th arg is /path/to/vquest, the 1st is `quest`; the args after that are the subcommands\n\tmut args := []string{}\n\targs << os.args[0]\n\targs << os.args#[2..]\n\tmut app := cli.Command{\n\t\tname:        'v quest'\n\t\tdescription: 'A tool to help make V better for everyone, by spending some time each day, on random tasks/missions like:\\n * documenting public APIs\\n * issue confirmation reviewing and triage\\n * testing'\n\t\texecute:     cli.print_help_for_command\n\t\tposix_mode:  true\n\t\tdefaults:    struct {\n\t\t\tman: false\n\t\t}\n\t\tcommands:    [\n\t\t\tcli.Command{\n\t\t\t\tname:        'document'\n\t\t\t\tdescription: 'Print a random missing doc entry from the V standard library.'\n\t\t\t\texecute:     run_document\n\t\t\t},\n\t\t\tcli.Command{\n\t\t\t\tname:        'confirm'\n\t\t\t\tdescription: 'Open a random vlang/v issue, that is still unconfirmed in your browser.'\n\t\t\t\tflags:       issue_flags.clone()\n\t\t\t\texecute:     run_confirm\n\t\t\t},\n\t\t\tcli.Command{\n\t\t\t\tname:        'fix'\n\t\t\t\tdescription: 'Open a random vlang/v issue (but still open) in your browser.'\n\t\t\t\tflags:       issue_flags.clone()\n\t\t\t\texecute:     run_fix\n\t\t\t},\n\t\t\tcli.Command{\n\t\t\t\tname:        'implement'\n\t\t\t\tdescription: 'Open a random vlang/v feature request issue in your browser.'\n\t\t\t\tflags:       issue_flags.clone()\n\t\t\t\texecute:     run_implement\n\t\t\t},\n\t\t\tcli.Command{\n\t\t\t\tname:        'solve'\n\t\t\t\tdescription: 'Find a random bug reproducible on your OS, print it to stdout and save to bug-<issue_id>.md.'\n\t\t\t\tflags:       solve_flags.clone()\n\t\t\t\texecute:     run_solve\n\t\t\t},\n\t\t]\n\t}\n\tapp.setup()\n\tif args.len <= 1 {\n\t\tif rcmd := rand.element(app.commands) {\n\t\t\trcmd.execute(rcmd)!\n\t\t\treturn\n\t\t}\n\t}\n\tapp.parse(args)\n}\n\nconst issue_flags = [\n\tcli.Flag{\n\t\tdescription: 'Print the issue URL without opening a browser.'\n\t\tflag:        .bool\n\t\tname:        'print-only'\n\t\tabbrev:      'p'\n\t},\n\tcli.Flag{\n\t\tdescription:   'Start page for issues (default -1: auto). Must be > 0.'\n\t\tflag:          .int\n\t\tname:          'from'\n\t\tabbrev:        'f'\n\t\tdefault_value: ['-1']\n\t},\n\tcli.Flag{\n\t\tdescription:   'End page for issues (default -1: auto). Must be > 0 and >= the from page (see -f).'\n\t\tflag:          .int\n\t\tname:          'to'\n\t\tabbrev:        't'\n\t\tdefault_value: ['-1']\n\t},\n]\n\nconst solve_flags = [\n\tcli.Flag{\n\t\tdescription:   'Override OS detection (macos, windows, linux).'\n\t\tflag:          .string\n\t\tname:          'os'\n\t\tabbrev:        'o'\n\t\tdefault_value: ['']\n\t},\n\tcli.Flag{\n\t\tdescription:   'Start page for issues (default -1: auto). Must be > 0.'\n\t\tflag:          .int\n\t\tname:          'from'\n\t\tabbrev:        'f'\n\t\tdefault_value: ['-1']\n\t},\n\tcli.Flag{\n\t\tdescription:   'End page for issues (default -1: auto). Must be > 0 and >= the from page (see -f).'\n\t\tflag:          .int\n\t\tname:          'to'\n\t\tabbrev:        't'\n\t\tdefault_value: ['-1']\n\t},\n\tcli.Flag{\n\t\tdescription:   'Output file for the bug report (default: bug-<issue_id>.md).'\n\t\tflag:          .string\n\t\tname:          'output'\n\t\tabbrev:        'O'\n\t\tdefault_value: ['']\n\t},\n]\n\nfn run_confirm(cmd cli.Command) ! {\n\trun_issue(cmd, confirm_search_query, 'still unconfirmed', 'Help us by confirming and triaging this issue:')!\n}\n\nfn run_fix(cmd cli.Command) ! {\n\trun_issue(cmd, fix_search_query, 'open', 'Help us by fixing or confirming this issue:')!\n}\n\nfn run_implement(cmd cli.Command) ! {\n\trun_issue(cmd, feature_search_query, 'feature request', 'Help us by implementing the issue in a PR, or triage it:')!\n}\n\nfn run_solve(cmd cli.Command) ! {\n\t// Clean up old bug report files\n\tfor f in os.glob('bug-*.md') or { []string{} } {\n\t\tos.rm(f) or {}\n\t}\n\n\tuser_os := get_target_os(cmd)\n\tos_label := get_os_label(user_os)\n\toutput_override := cmd.flags.get_string('output') or { '' }\n\n\t// Build query that excludes issues for other OSes\n\t// We look for open bugs that are NOT exclusive to other operating systems\n\texcluded_os_labels := get_excluded_os_labels(user_os)\n\tmut query := 'repo:vlang/v is:issue is:open label:Bug'\n\tfor label in excluded_os_labels {\n\t\tquery += ' -label:\"${label}\"'\n\t}\n\n\ttotal := fetch_total_count(query)!\n\tmax_pages := total_to_max_pages(total)\n\tif max_pages == 0 {\n\t\treturn error('no bugs found for ${os_label}')\n\t}\n\tstart_page, end_page := resolve_page_range(cmd, max_pages)!\n\tpage := start_page + (rand.intn(end_page - start_page + 1) or { 0 })\n\teprintln(term.colorize(term.gray, 'Found: ${total} bugs reproducible on ${os_label}. Fetching from page: ${page} in [${start_page}, ${end_page}] ...'))\n\n\tissue := fetch_issue_from_page(query, page)!\n\tdetails := fetch_issue_details(issue.number)!\n\n\t// Format the bug report\n\treport := format_bug_report(details, user_os)\n\n\t// Print to stdout\n\tprintln(report)\n\n\t// Determine output filename (default: bug-<issue_id>.md)\n\toutput_file := if output_override != '' { output_override } else { 'bug-${details.number}.md' }\n\n\t// Write to file\n\tos.write_file(output_file, report) or {\n\t\treturn error('failed to write to ${output_file}: ${err}')\n\t}\n\teprintln(term.colorize(term.green, '\\nBug report saved to: ${output_file}'))\n}\n\nfn get_target_os(cmd cli.Command) string {\n\toverride := cmd.flags.get_string('os') or { '' }\n\tif override != '' {\n\t\treturn override.to_lower()\n\t}\n\treturn os.user_os()\n}\n\nfn get_os_label(user_os string) string {\n\treturn match user_os {\n\t\t'macos' { 'macOS' }\n\t\t'windows' { 'Windows' }\n\t\t'linux' { 'Linux' }\n\t\t'freebsd' { 'FreeBSD' }\n\t\telse { user_os }\n\t}\n}\n\nfn get_excluded_os_labels(user_os string) []string {\n\t// Return labels for OSes that should be EXCLUDED\n\t// i.e., if user is on macOS, exclude Windows-only and Linux-only bugs\n\tall_os_labels := ['OS: Windows', 'OS: Linux', 'OS: macOS', 'OS: FreeBSD']\n\tuser_label := match user_os {\n\t\t'macos' { 'OS: macOS' }\n\t\t'windows' { 'OS: Windows' }\n\t\t'linux' { 'OS: Linux' }\n\t\t'freebsd' { 'OS: FreeBSD' }\n\t\telse { '' }\n\t}\n\treturn all_os_labels.filter(it != user_label)\n}\n\nfn fetch_issue_details(issue_number int) !IssueDetails {\n\turl := '${issue_endpoint}/${issue_number}'\n\tbody := api_get(url)!\n\treturn json.decode(IssueDetails, body)!\n}\n\nfn format_bug_report(issue IssueDetails, user_os string) string {\n\tmut report := '# Bug #${issue.number}: ${issue.title}\\n\\n'\n\treport += '**URL:** ${issue.html_url}\\n\\n'\n\treport += '**Target OS:** ${get_os_label(user_os)}\\n\\n'\n\n\tif issue.labels.len > 0 {\n\t\tlabels := issue.labels.map(it.name).join(', ')\n\t\treport += '**Labels:** ${labels}\\n\\n'\n\t}\n\n\treport += '## Description\\n\\n'\n\treport += issue.body\n\treport += '\\n'\n\n\treturn report\n}\n\nfn run_issue(cmd cli.Command, issue_query string, issue_label string, help_label string) ! {\n\tprint_only := cmd.flags.get_bool('print-only') or { false }\n\ttotal := fetch_total_count(issue_query)!\n\tmax_pages := total_to_max_pages(total)\n\tif max_pages == 0 {\n\t\treturn error('no unconfirmed issues found')\n\t}\n\tstart_page, end_page := resolve_page_range(cmd, max_pages)!\n\tpage := start_page + (rand.intn(end_page - start_page + 1) or { 0 })\n\teprintln(term.colorize(term.gray, 'Found: ${total} ${issue_label} issues. Fetching issue from page: ${page} in [${start_page}, ${end_page}] ...'))\n\tissue := fetch_issue_from_page(issue_query, page)!\n\tprintln(term.colorize(term.green, help_label))\n\tprintln(issue.html_url)\n\tif print_only {\n\t\treturn\n\t}\n\topen_uri(issue.html_url)!\n}\n\nfn run_document(cmd cli.Command) ! {\n\tres := os.execute('${os.quoted_path(@VEXE)} missdoc --exclude vlib/v --exclude /linux_bare/ --exclude /wasm_bare/ @vlib')\n\tif res.exit_code != 0 {\n\t\treturn error('v missdoc failed: ${res.output}')\n\t}\n\tlines := res.output.split_into_lines().filter(it.trim_space() != '')\n\tif lines.len == 0 {\n\t\treturn error('no missing doc entries found')\n\t}\n\tidx := rand.intn(lines.len) or { 0 }\n\teprintln(term.colorize(term.green, 'Help us document this public API:'))\n\tprintln(term.colorize(term.bold, lines[idx]))\n}\n\nfn fetch_total_count(query string) !int {\n\turl := build_search_url(query, 1, 1)\n\tbody := api_get(url)!\n\tresp := json.decode(SearchResponse, body)!\n\treturn resp.total_count\n}\n\nfn resolve_page_range(cmd cli.Command, max_pages int) !(int, int) {\n\tfrom, from_set := read_page_limit(cmd, 'from', '-f')!\n\tto, to_set := read_page_limit(cmd, 'to', '-t')!\n\tif from_set && to_set && to < from {\n\t\treturn error('invalid page range: -t (${to}) is smaller than -f (${from})')\n\t}\n\tmut start_page := 1\n\tmut end_page := max_pages\n\tif from_set {\n\t\tstart_page = from\n\t}\n\tif to_set {\n\t\tend_page = to\n\t}\n\tif start_page < 1 {\n\t\tstart_page = 1\n\t}\n\tif end_page > max_pages {\n\t\tend_page = max_pages\n\t}\n\tif end_page < start_page {\n\t\treturn error('no issues found in the requested page range')\n\t}\n\treturn start_page, end_page\n}\n\nfn read_page_limit(cmd cli.Command, name string, flag_label string) !(int, bool) {\n\tvalue := cmd.flags.get_int(name)!\n\tis_set := flag_is_set(cmd, name)\n\tif is_set && value < 0 {\n\t\treturn error('${flag_label} must be >= 0')\n\t}\n\treturn value, is_set\n}\n\nfn flag_is_set(cmd cli.Command, name string) bool {\n\tfor flag in cmd.flags.get_all_found() {\n\t\tif flag.name == name {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfn fetch_issue_from_page(query string, page int) !Issue {\n\turl := build_search_url(query, page, per_page)\n\tbody := api_get(url)!\n\tresp := json.decode(SearchResponse, body)!\n\tif resp.items.len == 0 {\n\t\treturn error('no issues returned for page ${page}')\n\t}\n\tidx := rand.intn(resp.items.len) or { 0 }\n\treturn resp.items[idx]\n}\n\nfn build_search_url(query string, page int, per_page int) string {\n\tmut values := urllib.new_values()\n\tvalues.add('q', query)\n\tvalues.add('per_page', per_page.str())\n\tvalues.add('page', page.str())\n\treturn '${search_endpoint}?${values.encode()}'\n}\n\nfn api_get(url string) !string {\n\tresp := http.fetch(\n\t\turl:    url\n\t\tmethod: .get\n\t\theader: http.new_header_from_map({\n\t\t\thttp.CommonHeader.accept:     'application/vnd.github+json'\n\t\t\thttp.CommonHeader.user_agent: 'v quest'\n\t\t})\n\t)!\n\tif resp.status_code != 200 {\n\t\treturn error('GitHub API error ${resp.status_code}: ${resp.body}')\n\t}\n\treturn resp.body\n}\n\nfn total_to_max_pages(total int) int {\n\tif total <= 0 {\n\t\treturn 0\n\t}\n\tmax_pages := (total + per_page - 1) / per_page\n\tlimit := max_search_results / per_page\n\treturn if max_pages < limit { max_pages } else { limit }\n}\n\nfn open_uri(uri string) ! {\n\t$if !termux {\n\t\tos.open_uri(uri)!\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vreduce.v",
    "content": "import os\nimport v.vmod\nimport flag\nimport time\nimport math\nimport log\n\nconst version = '0.0.2'\nconst default_command = '${os.quoted_path(@VEXE)} -no-skip-unused' // Command used to compile the program, using -no-skip-unused to ease the reducing\nconst default_error_msg = 'C compilation error' // the pattern to reproduce\n// Temporary files\nconst tmp_folder = os.join_path(os.vtmp_dir(), 'vreduce')\n\nfn main() {\n\tlog.use_stdout()\n\tmut fp := flag.new_flag_parser(os.args)\n\tfp.skip_executable()\n\tfp.application('v reduce path/to/file_to_reduce.v')\n\tfp.description('This tool will reduce the code file and try to make the smallest one it can that reproduces the error when the command is executed')\n\tfp.version(version)\n\n\terror_msg := fp.string('error_msg', `m`, default_error_msg, 'the error message you want to reproduce, default: \\'${default_error_msg}\\'')\n\tmut command := fp.string('command', `c`, default_command, 'the command used to try to reproduce the error, default: \\'${default_command}\\', will replace PATH with the path of the folder where it is run')\n\tcopy_project := fp.bool('cp', `p`, false, 'if used v reduce will copy the whole folder of the project')\n\ttimeout := fp.int('to', `t`, 0, 'sets a timeout for the command, default=0 : no timeout')\n\tdo_fmt := fp.bool('fmt', `w`, false, 'enable v fmt for the output (rpdc_file_name.v)')\n\tfile_paths := fp.finalize() or {\n\t\teprintln(err)\n\t\tprintln(fp.usage())\n\t\treturn\n\t}\n\n\tif file_paths.len != 2 {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\n\tmut file_path := file_paths[1]\n\tif file_path == '' || !os.exists(file_path) {\n\t\tlog.error('You need to specify a valid file to reduce.')\n\t\tif file_path != '' {\n\t\t\tlog.error('Path `${file_path}` is not a valid .v file.')\n\t\t}\n\t\tprintln(fp.usage())\n\t\texit(1)\n\t}\n\n\tlog.info(\"Starting to reduce the file: '${file_path}'\\n    with command: `${command}`,\\n    trying to reproduce: `${error_msg}`\")\n\n\tif do_fmt {\n\t\tlog.info('Will do `v fmt -w rpdc_file_name.v` after the reduction.')\n\t} else {\n\t\tlog.info('Will NOT do `v fmt -w rpdc_file_name.v` (use the `--fmt` or `-w` flag to enable it)')\n\t}\n\n\tcontent := os.read_file(file_path)!\n\tshow_code_stats(content, label: 'Original code size')\n\n\t// copy project\t\n\tif os.exists(tmp_folder) {\n\t\tos.rmdir_all(tmp_folder)!\n\t}\n\tos.mkdir(tmp_folder)!\n\tif copy_project {\n\t\tmut vmod_cacher := vmod.new_mod_file_cacher()\n\t\tproject_folder := vmod_cacher.get_by_file(file_path).vmod_folder\n\t\tos.cp_all('${project_folder}/.', tmp_folder + '/', true)!\n\t\t// the path of the target file from the project folder\n\t\tfile_path = os.walk_ext(project_folder, os.file_name(file_path))[0] or {\n\t\t\tpanic('File not found in the project folder')\n\t\t}\n\t\tfile_path = file_path[project_folder.len + 1..] // will remove the / too\n\t}\n\tfull_file_path := '${tmp_folder}/${file_path}'\n\tif command == default_command {\n\t\tcommand = '${default_command} ${full_file_path}'\n\t} else {\n\t\tcommand = command.replace('PATH', '${tmp_folder}/')\n\t}\n\n\t// start tests\n\ttmp_code := create_code(parse(content))\n\twarn_on_false(string_reproduces(tmp_code, error_msg, command, full_file_path, true,\n\t\ttimeout), 'string_reproduces', @LOCATION)\n\tshow_code_stats(tmp_code, label: 'Code size without comments')\n\n\t// reduce the code\n\treduce_scope(content, error_msg, command, do_fmt, full_file_path, timeout)\n\n\t// cleanse\n\tif os.exists(tmp_folder) {\n\t\tos.rmdir_all(tmp_folder)!\n\t}\n}\n\n// Return true if the command ran on the file produces the pattern\nfn string_reproduces(file_content string, pattern string, command string, file_path string, debug bool, timeout int) bool {\n\tif !os.exists(tmp_folder) {\n\t\tos.mkdir(tmp_folder) or { panic(err) }\n\t}\n\tos.write_file(file_path, file_content) or { panic(err) }\n\tmut output := ''\n\tif timeout == 0 {\n\t\tres := os.execute(command)\n\t\toutput = res.output\n\t} else {\n\t\tsplit := command.split(' ')\n\t\tmut prog := os.new_process(split[0])\n\t\tprog.use_pgroup = true\n\t\tprog.set_args(split[1..])\n\t\tprog.set_redirect_stdio()\n\t\tprog.run()\n\t\tmut sw := time.new_stopwatch()\n\t\tsw.start()\n\t\tfor prog.is_alive() {\n\t\t\t// check if there is any input from the user (it does not block, if there is not):\n\t\t\ttime.sleep(1 * time.millisecond)\n\t\t\tmut b := true\n\t\t\tfor b {\n\t\t\t\tb = false\n\t\t\t\tif oline := prog.pipe_read(.stdout) {\n\t\t\t\t\tif oline != '' {\n\t\t\t\t\t\toutput += oline\n\t\t\t\t\t\tb = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif eline := prog.pipe_read(.stderr) {\n\t\t\t\t\tif eline != '' {\n\t\t\t\t\t\toutput += eline\n\t\t\t\t\t\tb = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif sw.elapsed().seconds() > f32(timeout) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif sw.elapsed().seconds() > f32(timeout) {\n\t\t\t\tif debug {\n\t\t\t\t\tprintln('Timeout')\n\t\t\t\t}\n\t\t\t\tprog.signal_pgkill()\n\t\t\t\tprog.close()\n\t\t\t\tprog.wait()\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\tprog.signal_pgkill()\n\t\tprog.close()\n\t\tprog.wait()\n\t}\n\tif output.contains(pattern) {\n\t\t// println('reproduces')\n\t\treturn true\n\t} else {\n\t\t// println('does not reproduce')\n\t\tif debug {\n\t\t\tprintln(output)\n\t\t\tprintln('executed command: ${command}')\n\t\t}\n\t\treturn false\n\t}\n}\n\ntype Elem = string | Scope\n\n@[heap]\nstruct Scope {\nmut:\n\tfn_scope    bool   // contains a function (string: signature{}, children: function body)\n\tignored     bool   // is the scope ignored when creating the file\n\ttmp_ignored bool   // used when testing if it can be ignored in the file\n\tchildren    []Elem // code blocks (strings & children scope\n}\n\n// Parse a V file and create a scope tree to represent it\nfn parse(file_content string) Scope { // The parser is surely incomplete for the V syntax, but should work for most of the cases, if not, please open an issue or submit a PR\n\tmut stack := []&Scope{} // add the last parent to the stack\n\tstack << &Scope{}\n\tmut top := stack[0] // stores stack[stack.len-1] (the element on the top of the stack)\n\tmut scope_level := 0 // Counts the scope depth of the current position in the file_content\n\tmut i := 0 // index of the current char in the file_content\n\tmut current_string := ''\n\tfor i < file_content.len {\n\t\ttop = stack[stack.len - 1] // the element on the top of the stack\n\t\tif file_content[i] == `/` && file_content[i + 1] == `/` {\n\t\t\tfor file_content[i] != `\\n` { // comment -> skip until newline\n\t\t\t\ti++\n\t\t\t}\n\t\t} else if file_content[i] == `\\n` && file_content[i - 1] == `\\n` {\n\t\t\ti++ // remove excess newlines\n\t\t} else if file_content[i] == `\\t` {\n\t\t\ti++ // remove tabs for easier processing\n\t\t} else if file_content[i] == `f` && file_content[i + 1] == `n` && file_content[i + 2] == ` ` && file_content[i - 1] or {\n\t\t\t`\\n`\n\t\t} == `\\n` {\n\t\t\ttop.children << current_string\n\t\t\t// no increase in scope because not handled with {}\n\t\t\tcurrent_string = ''\n\t\t\ttop.children << &Scope{\n\t\t\t\tfn_scope: true\n\t\t\t}\n\t\t\tstack << &(top.children[top.children.len - 1] as Scope)\n\t\t\tcurrent_string += file_content[i].ascii_str() // f\n\t\t\ti++\n\t\t\tcurrent_string += file_content[i].ascii_str() // n\n\t\t\ti++\n\t\t} else if file_content[i] == `/` && file_content[i + 1] == `*` {\n\t\t\ti++\n\t\t\ti++\n\t\t\ti++\n\t\t\tfor !(file_content[i - 1] == `*` && file_content[i] == `/`) { // multiline comment -> skip next multiline end sequence\n\t\t\t\ti++\n\t\t\t}\n\t\t\ti++\n\t\t} else if file_content[i] == `\\`` && file_content[i - 1] != `\\\\` {\n\t\t\tcurrent_string += file_content[i].ascii_str()\n\t\t\ti++\n\t\t\tfor file_content[i] != `\\``\n\t\t\t\t|| (file_content[i - 1] == `\\\\` && file_content[i - 2] != `\\\\`) { // string -> skip until next `\n\t\t\t\tcurrent_string += file_content[i].ascii_str()\n\t\t\t\ti++\n\t\t\t}\n\t\t\tcurrent_string += file_content[i].ascii_str() // `\n\t\t\ti++\n\t\t} else if file_content[i] == `'` {\n\t\t\tcurrent_string += file_content[i].ascii_str() // '\n\t\t\ti++\n\t\t\tfor file_content[i] != `'`\n\t\t\t\t|| (file_content[i - 1] == `\\\\` && file_content[i - 2] != `\\\\`) { // string -> skip until next '\n\t\t\t\tcurrent_string += file_content[i].ascii_str()\n\t\t\t\ti++\n\t\t\t}\n\t\t\tcurrent_string += file_content[i].ascii_str() // '\n\t\t\ti++\n\t\t} else if file_content[i] == `\"` {\n\t\t\tcurrent_string += file_content[i].ascii_str() // \"\n\t\t\ti++\n\t\t\tfor file_content[i] != `\"`\n\t\t\t\t|| (file_content[i - 1] == `\\\\` && file_content[i - 2] != `\\\\`) { // string -> skip until next \"\n\t\t\t\tcurrent_string += file_content[i].ascii_str()\n\t\t\t\ti++\n\t\t\t}\n\t\t\tcurrent_string += file_content[i].ascii_str() // \"\n\t\t\ti++\n\t\t} else if file_content[i] == `{` {\n\t\t\tcurrent_string += file_content[i].ascii_str()\n\t\t\ti++\n\t\t\ttop.children << current_string\n\t\t\tscope_level += 1\n\t\t\tcurrent_string = ''\n\t\t\ttop.children << &Scope{}\n\t\t\tstack << &(top.children[top.children.len - 1] as Scope)\n\t\t} else if file_content[i] == `}` {\n\t\t\tscope_level -= 1\n\t\t\tassert scope_level >= 0, 'The scopes are not well detected ${stack[0]}'\n\t\t\tif current_string != '' {\n\t\t\t\ttop.children << current_string\n\t\t\t}\n\t\t\tif stack.last().children == [] {\n\t\t\t\tstack[stack.len - 2].children.delete(stack[stack.len - 2].children.len - 1) // delete the empty scope (the last children because top of the stack)\n\t\t\t}\n\t\t\tstack.pop()\n\t\t\ttop = stack[stack.len - 1]\n\t\t\tcurrent_string = ''\n\t\t\tcurrent_string += file_content[i].ascii_str() // }\n\t\t\ti++\n\t\t\tif scope_level == 0 && stack.len == 2 { // the function and the body scope\n\t\t\t\ttop.children << current_string\n\t\t\t\tstack.pop()\n\t\t\t\ttop = stack[stack.len - 1]\n\t\t\t\tcurrent_string = ''\n\t\t\t}\n\t\t} else {\n\t\t\tcurrent_string += file_content[i].ascii_str()\n\t\t\ti++\n\t\t}\n\t\t// nothing here: to avoid complexity, no need to predict what happened before in the ifs, everything will be handled properly by the ifs\n\t}\n\ttop = stack[stack.len - 1]\n\ttop.children << current_string // last part of the file\n\twarn_on_false(scope_level == 0, 'scope_level == 0 /* the scopes are not well detected*/',\n\t\t@LOCATION)\n\twarn_on_false(stack.len == 1, 'stack.len == 1 /* the stack should only have the body scope */',\n\t\t@LOCATION)\n\treturn *stack[0]\n}\n\n// Create the file from a scope tree\nfn create_code(sc Scope) string {\n\tmut output_code := ''\n\tmut stack := []Elem{}\n\tstack << sc\n\tfor stack.len > 0 {\n\t\titem := stack.pop()\n\t\tif item is Scope {\n\t\t\tif !item.ignored && !item.tmp_ignored {\n\t\t\t\tstack << item.children.reverse() // to traverse the tree in the good order\n\t\t\t} else {\n\t\t\t}\n\t\t} else if item is string { // string\n\t\t\toutput_code += item\n\t\t} else {\n\t\t\tpanic('Should never happen')\n\t\t}\n\t}\n\treturn output_code\n}\n\n// Reduces the code contained in the scope tree and writes the reduced code to `rpdc_file_name.v`\nfn reduce_scope(content string, error_msg string, command string, do_fmt bool, file_path string, timeout int) {\n\tmut sc := parse('') // will get filled in the start of the loop\n\tlog.info('Cleaning the scopes')\n\tmut text_code := content\n\tmut outer_modified_smth := true\n\trpdc_file_path := 'rpdc_${os.file_name(file_path)#[..-2]}.v'\n\tfor outer_modified_smth {\n\t\tsc = parse(text_code)\n\t\touter_modified_smth = false\n\t\tmut modified_smth := true // was a modification successful in reducing the code in the last iteration\n\t\tfor modified_smth { // as long as there are successful modifications\n\t\t\tmodified_smth = false\n\t\t\tlog.info('NEXT ITERATION, loop 1')\n\t\t\tmut stack := []&Elem{}\n\t\t\tfor i in 0 .. sc.children.len {\n\t\t\t\tstack << &sc.children[i]\n\t\t\t}\n\t\t\tmut item_nb := 0\n\t\t\tfor stack.len > 0 { // traverse the tree and disable (ignore) scopes that are not needed for reproduction\n\t\t\t\tmut item := stack.pop()\n\t\t\t\titem_nb += 1\n\t\t\t\teprint('\\ritem n: ${item_nb}')\n\t\t\t\tif mut item is Scope {\n\t\t\t\t\tif !item.ignored {\n\t\t\t\t\t\titem.tmp_ignored = true // try to ignore it\n\t\t\t\t\t\tcode := create_code(sc)\n\t\t\t\t\t\titem.tmp_ignored = false // dont need it anymore\n\t\t\t\t\t\tif string_reproduces(code, error_msg, command, file_path, false,\n\t\t\t\t\t\t\ttimeout)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\titem.ignored = true\n\t\t\t\t\t\t\tmodified_smth = true\n\t\t\t\t\t\t\touter_modified_smth = true\n\t\t\t\t\t\t\tprintln('')\n\t\t\t\t\t\t\tshow_code_stats(code)\n\t\t\t\t\t\t} else { // if can remove it, no need to go through its children\n\t\t\t\t\t\t\tfor i in 0 .. item.children.len {\n\t\t\t\t\t\t\t\tstack.insert(0, &item.children[i]) // breadth first search\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tprintln('')\n\n\t\t\ttext_code = create_code(sc)\n\t\t\tos.write_file(rpdc_file_path, text_code) or { panic(err) }\n\t\t\tif do_fmt {\n\t\t\t\tvfmt_file(rpdc_file_path)\n\t\t\t}\n\t\t\tprintln('The WIP reduced code is now in ${rpdc_file_path}')\n\t\t}\n\n\t\tlog.info('Processing remaining lines')\n\t\tsplit_code := text_code.split_into_lines() // dont forget to add back the \\n\n\t\t// Create the binary tree of the lines\n\t\tdepth := int(math.log2(split_code.len)) + 1\n\t\tmut c := 0\n\t\tmut line_stack := []&Scope{}\n\t\tline_stack << &Scope{}\n\t\tfor c < split_code.len {\n\t\t\tl1 := line_stack.len\n\t\t\tif l1 <= depth { // or equal because of the first node\n\t\t\t\tif line_stack[l1 - 1].children.len < 2 {\n\t\t\t\t\tline_stack[l1 - 1].children << &Scope{}\n\t\t\t\t\tl2 := line_stack[l1 - 1].children.len\n\t\t\t\t\tline_stack << &(line_stack[l1 - 1].children[l2 - 1] as Scope)\n\t\t\t\t} else {\n\t\t\t\t\tline_stack.pop()\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif line_stack[l1 - 1].children.len != 0 { // if there is already a string\n\t\t\t\t\tline_stack.pop()\n\t\t\t\t} else {\n\t\t\t\t\tline_stack[l1 - 1].children << split_code[c] + '\\n' // the \\n were removed by the split\n\t\t\t\t\tc++\n\t\t\t\t\tline_stack.pop() // already a string\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Traverse the tree and prune the useless lines / line groups for the reproduction\n\t\tmut line_tree := *line_stack[0]\n\t\twarn_on_false(string_reproduces(create_code(line_tree), error_msg, command, file_path,\n\t\t\ttrue, timeout), 'string_reproduces', @LOCATION) // should be the same\n\t\tlog.info('Pruning the lines/line groups')\n\t\tmodified_smth = true\n\t\tfor modified_smth {\n\t\t\tmodified_smth = false\n\t\t\tlog.info('NEXT ITERATION, loop 2')\n\t\t\tmut stack := []&Elem{}\n\t\t\tfor i in 0 .. line_tree.children.len {\n\t\t\t\tstack << &line_tree.children[i]\n\t\t\t}\n\t\t\tmut item_nb := 0\n\t\t\tfor stack.len > 0 { // traverse the binary tree (of the lines)\n\t\t\t\tmut item := stack.pop()\n\t\t\t\titem_nb += 1\n\t\t\t\teprint('\\ritem n: ${item_nb}')\n\t\t\t\tif mut item is Scope {\n\t\t\t\t\tif !item.ignored {\n\t\t\t\t\t\titem.tmp_ignored = true\n\t\t\t\t\t\tcode := create_code(line_tree)\n\t\t\t\t\t\titem.tmp_ignored = false // dont need it anymore\n\t\t\t\t\t\tif string_reproduces(code, error_msg, command, file_path, false,\n\t\t\t\t\t\t\ttimeout)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\titem.ignored = true\n\t\t\t\t\t\t\tmodified_smth = true\n\t\t\t\t\t\t\touter_modified_smth = true\n\t\t\t\t\t\t\tprintln('')\n\t\t\t\t\t\t\tshow_code_stats(code)\n\t\t\t\t\t\t} else { // if can remove it, can remove its children\n\t\t\t\t\t\t\tfor i in 0 .. item.children.len {\n\t\t\t\t\t\t\t\tstack << &item.children[i]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tprintln('')\n\t\t\ttext_code = create_code(line_tree)\n\t\t\tos.write_file(rpdc_file_path, text_code) or { panic(err) }\n\t\t\tif do_fmt {\n\t\t\t\tvfmt_file(rpdc_file_path)\n\t\t\t}\n\t\t\tprintln('The WIP reduced code is now in ${rpdc_file_path}')\n\t\t}\n\t}\n\n\twarn_on_false(string_reproduces(text_code, error_msg, command, file_path, true, timeout),\n\t\t'string_reproduces', @LOCATION)\n\tos.write_file(rpdc_file_path, text_code) or { panic(err) }\n\tif do_fmt {\n\t\tvfmt_file(rpdc_file_path)\n\t}\n\tprintln('The reduced code is now in ${rpdc_file_path}')\n}\n\nfn vfmt_file(rpdc_file_path string) {\n\tos.execute('${os.quoted_path(@VEXE)} fmt -w ${rpdc_file_path}')\n\tfinal_content := os.read_file(rpdc_file_path) or { panic(err) }\n\tshow_code_stats(final_content, label: 'Code size after formatting')\n}\n\n@[params]\nstruct ShowParams {\n\tlabel string = 'Code size'\n}\n\nfn show_code_stats(code string, params ShowParams) {\n\tlines := code.split_into_lines()\n\tlog.info('${params.label}: ${code.len} chars, ${lines.len} lines.')\n}\n\nfn warn_on_false(res bool, what string, loc string) {\n\tif !res {\n\t\tlog.warn('${what} is false, at ${loc}; see output above')\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vrepeat.v",
    "content": "module main\n\nimport os\nimport flag\nimport time\nimport math\nimport term\n\nconst tred = term.red\nconst tbold = term.bold\nconst tgray = term.gray\nconst tcyan = term.cyan\nconst tgreen = term.green\nconst tbcyan = term.bright_cyan\nconst tbblue = term.bright_blue\nconst tdivider = term.h_divider\n\nfn c(cfn fn (string) string, s string) string {\n\treturn term.colorize(cfn, s)\n}\n\nconst hline = '-'.repeat(80)\n\nfn show_failure_output(output string) {\n\teprintln(hline)\n\teprint(output)\n\teprintln(hline)\n}\n\nconst max_fail_percent = 100 * 1000\nconst max_time = 60 * 1000 // ms\n\nconst performance_regression_label = 'Performance regression detected, failing since '\n\nstruct Aints {\n\tvalues []i64 // uS\nmut:\n\timin    i64 // uS\n\timax    i64 // uS\n\taverage f64\n\tstddev  f64\n\tnmins   int // number of discarded fastest results\n\tnmaxs   int // number of discarded slowest results\n}\n\nstruct CmdResult {\nmut:\n\truns    int\n\tcmd     string\n\ticmd    int\n\toutputs []string\n\tous     map[string][]i64 // uS\n\tsummary map[string]Aints\n\ttimings []i64\n\tatiming Aints\n}\n\nstruct Context {\nmut:\n\trun_count               int\n\trepeats_count           int\n\tcurrent_run             int\n\tseries                  int\n\twarmup                  int\n\tshow_help               bool\n\tshow_output             bool\n\tis_silent               bool // do not print progress lines\n\tuse_newline             bool // use \\n instead of \\r, so the last line is not overwritten\n\tfail_on_regress_percent int\n\tfail_on_maxtime         int // in ms\n\tverbose                 bool\n\tcommands                []string\n\tresults                 []CmdResult\n\tcmd_template            string // {T} will be substituted with the current command\n\tcmd_params              map[string][]string\n\tcline                   string // a terminal clearing line\n\tcgoback                 string\n\tnmins                   int  // number of minimums to discard\n\tnmaxs                   int  // number of maximums to discard\n\tignore_failed           bool // ignore commands that exit with != 0 exit code\n\tno_vexe_setenv          bool // do not change the VEXE variable\n\n\tfail_count   map[string]int // how many times a command has failed so far. Only the first failure output is shown.\n\trepeat_timer time.StopWatch = time.new_stopwatch()\n}\n\nfn new_aints(ovals []i64, extreme_mins int, extreme_maxs int) Aints {\n\tmut res := Aints{\n\t\tvalues: ovals // remember the original values\n\t\tnmins:  extreme_mins\n\t\tnmaxs:  extreme_maxs\n\t}\n\t// discard the extremes, if needed:\n\tmut vals := []i64{}\n\tfor x in ovals {\n\t\tvals << x\n\t}\n\tvals.sort()\n\tif extreme_mins > 0 {\n\t\tvals = vals#[extreme_mins..].clone()\n\t}\n\tif extreme_maxs > 0 {\n\t\tvals = vals#[..-extreme_maxs].clone()\n\t}\n\t// statistical processing of the remaining values:\n\tmut sum := i64(0)\n\tmut imin := i64(max_i64)\n\tmut imax := i64(-max_i64)\n\tfor i in vals {\n\t\tsum += i\n\t\tif i < imin {\n\t\t\timin = i\n\t\t}\n\t\tif i > imax {\n\t\t\timax = i\n\t\t}\n\t}\n\tres.imin = imin\n\tres.imax = imax\n\tif vals.len > 0 {\n\t\tres.average = sum / f64(vals.len)\n\t}\n\n\tmut devsum := f64(0.0)\n\tfor i in vals {\n\t\tx := f64(i) - res.average\n\t\tdevsum += (x * x)\n\t}\n\tres.stddev = math.sqrt(devsum / f64(vals.len))\n\t// eprintln('\\novals: ${ovals}\\n vals: ${vals}\\n vals.len: ${vals.len} |  res.imin: ${res.imin} | res.imax: ${res.imax} | res.average: ${res.average} | res.stddev: ${res.stddev}')\n\treturn res\n}\n\nfn bold(s string) string {\n\treturn c(tgreen, c(tbold, s))\n}\n\nfn (a Aints) str() string {\n\tavg := bold('${a.average / 1000:6.1f}ms')\n\ttdev := c(tred, '${a.stddev / 1000:6.1f}ms')\n\tbaseline := '${avg} ± σ: ${tdev},'\n\ttmin := c(tbcyan, '${f64(a.imin) / 1000:6.1f}ms')\n\ttmax := c(tbblue, '${f64(a.imax) / 1000:6.1f}ms')\n\treturn '${baseline:-46s} ${tmin}…${tmax}'\n}\n\nfn flushed_print(s string) {\n\tprint(s)\n\tflush_stdout()\n}\n\nfn (mut context Context) clear_line() {\n\tif context.is_silent {\n\t\treturn\n\t}\n\tflushed_print(context.cline)\n}\n\nfn (mut context Context) flushed_print(s string) {\n\tif context.is_silent {\n\t\treturn\n\t}\n\tflushed_print(s)\n}\n\nfn (mut context Context) expand_all_commands(commands []string) []string {\n\tmut all_commands := []string{}\n\tfor cmd in commands {\n\t\tmaincmd := context.cmd_template.replace('{T}', cmd)\n\t\tmut substituted_commands := []string{}\n\t\tsubstituted_commands << maincmd\n\t\tfor paramk, paramlist in context.cmd_params {\n\t\t\tfor paramv in paramlist {\n\t\t\t\tmut new_substituted_commands := []string{}\n\t\t\t\tfor cscmd in substituted_commands {\n\t\t\t\t\tscmd := cscmd.replace('{${paramk}}', paramv)\n\t\t\t\t\tnew_substituted_commands << scmd\n\t\t\t\t}\n\t\t\t\tsubstituted_commands << new_substituted_commands\n\t\t\t}\n\t\t}\n\t\tall_commands << substituted_commands\n\t}\n\tmut unique := map[string]int{}\n\tfor x in all_commands {\n\t\tif x.contains('{') && x.contains('}') {\n\t\t\tcontinue\n\t\t}\n\t\tunique[x] = 1\n\t}\n\treturn unique.keys()\n}\n\nfn (mut context Context) run() {\n\tfor si in 0 .. context.series {\n\t\tfor icmd, cmd in context.commands {\n\t\t\tmut runs := 0\n\t\t\tmut sum := i64(0)\n\t\t\tmut avg := f64(0)\n\t\t\tmut duration := i64(0)\n\t\t\tmut oldres := ''\n\t\t\tseries_label := '${icmd + 1}/${context.commands.len}, ${si + 1}/${context.series}'\n\t\t\tline_prefix := '${context.cgoback}Command: ${c(tgray, cmd)}, ${series_label:9}'\n\t\t\tif context.series != 1 || context.commands.len != 1 {\n\t\t\t\tcontext.flushed_print(line_prefix)\n\t\t\t}\n\t\t\tif context.warmup > 0 {\n\t\t\t\tfor i in 0 .. context.warmup {\n\t\t\t\t\tcontext.flushed_print('${line_prefix}, warm up run: ${i + 1:4}/${context.warmup:-4}, took: ${f64(duration) / 1000:6.1f}ms ...')\n\t\t\t\t\tmut sw := time.new_stopwatch()\n\t\t\t\t\tres := os.execute(cmd)\n\t\t\t\t\tduration = i64(sw.elapsed().microseconds())\n\t\t\t\t\tmut should_show_fail_output := false\n\t\t\t\t\tif res.exit_code != 0 && !context.ignore_failed {\n\t\t\t\t\t\tif context.fail_count[cmd] == 0 {\n\t\t\t\t\t\t\tshould_show_fail_output = true\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontext.fail_count[cmd]++\n\t\t\t\t\t}\n\t\t\t\t\tif should_show_fail_output {\n\t\t\t\t\t\teprintln('\\nCommand exited with exit code: ${res.exit_code} in ${f64(duration) / 1000:6.1f}ms .')\n\t\t\t\t\t\teprintln('Use -e or --ignore to ignore the failed commands.')\n\t\t\t\t\t\teprintln('The failed cmd was: `${c(tred, cmd)}` ; cmd output:')\n\t\t\t\t\t\tshow_failure_output(res.output)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor i in 0 .. context.run_count {\n\t\t\t\tmut sw := time.new_stopwatch()\n\t\t\t\tres := os.execute(cmd)\n\t\t\t\tduration = i64(sw.elapsed().microseconds())\n\t\t\t\t//\n\t\t\t\tmut should_show_fail_output := false\n\t\t\t\tif res.exit_code != 0 && !context.ignore_failed {\n\t\t\t\t\tif context.fail_count[cmd] == 0 {\n\t\t\t\t\t\tshould_show_fail_output = true\n\t\t\t\t\t}\n\t\t\t\t\tcontext.fail_count[cmd]++\n\t\t\t\t}\n\t\t\t\tsum += duration\n\t\t\t\truns++\n\t\t\t\tavg = (f64(sum) / f64(i + 1))\n\t\t\t\tcavg := '${avg / 1000:9.3f}ms'\n\t\t\t\tcontext.flushed_print('${line_prefix}, current average: ${c(tgreen, cavg)}, run ${\n\t\t\t\t\ti + 1:4}/${context.run_count:-4}, took: ${f64(duration) / 1000:6} ms')\n\t\t\t\tif context.show_output {\n\t\t\t\t\tcontext.flushed_print(' | result: ${oldres:s}')\n\t\t\t\t}\n\t\t\t\ttrimmed_output := res.output.trim_right('\\r\\n')\n\t\t\t\ttrimmed_normalized := trimmed_output.replace('\\r\\n', '\\n')\n\t\t\t\tlines := trimmed_normalized.split('\\n')\n\t\t\t\tcontext.results[icmd].outputs << lines\n\t\t\t\tcontext.results[icmd].timings << duration\n\t\t\t\toldres = res.output.replace('\\n', ' ')\n\t\t\t\tif should_show_fail_output {\n\t\t\t\t\teprintln('\\n${i + 1:10} non 0 exit code for cmd: ${cmd}; cmd output:')\n\t\t\t\t\tshow_failure_output(res.output)\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontext.results[icmd].cmd = cmd\n\t\t\tcontext.results[icmd].icmd = icmd\n\t\t\tcontext.results[icmd].runs += runs\n\t\t\tcontext.results[icmd].atiming = new_aints(context.results[icmd].timings, context.nmins,\n\t\t\t\tcontext.nmaxs)\n\t\t\tcontext.clear_line()\n\t\t\tcontext.flushed_print(context.cgoback)\n\t\t\tcontext.show_timings_details(si, icmd, cmd)\n\t\t}\n\t}\n\t// create full summaries, taking account of all runs\n\tfor icmd in 0 .. context.results.len {\n\t\tmut new_full_summary := map[string]Aints{}\n\t\tfor k, v in context.results[icmd].ous {\n\t\t\tnew_full_summary[k] = new_aints(v, context.nmins, context.nmaxs)\n\t\t}\n\t\tcontext.results[icmd].summary = new_full_summary.clone()\n\t}\n}\n\nfn (mut context Context) show_timings_details(si int, icmd int, cmd string) {\n\tif !cmd.contains('-show-timings') {\n\t\treturn\n\t}\n\t// This is specific to V compilations, when they are run with `-show-timings`,\n\t// which will show more details about each compilation stage.\n\tmut m := map[string][]i64{}\n\tioutputs := context.results[icmd].outputs\n\tfor o in ioutputs {\n\t\tx := o.split('ms ')\n\t\tif x.len > 1 {\n\t\t\tv := i64(x[0].trim_left(' ').f64() * 1000)\n\t\t\tk := x[1].all_before(' ')\n\t\t\tm[k] << v\n\t\t}\n\t}\n\tif m.len == 0 {\n\t\treturn\n\t}\n\tprintln('> Timing details for series ${si + 1}, icmd: ${icmd + 1}, cmd: `${cmd}`:')\n\tmut summary := map[string]Aints{}\n\tfor k, v in m {\n\t\t// show a temporary summary for the current series/cmd cycle\n\t\ts := new_aints(v, context.nmins, context.nmaxs)\n\t\tprintln('  ${k:-40s}: ${s}')\n\t\tsummary[k] = s\n\t}\n\t// merge current raw results to the previous ones\n\told_ous := context.results[icmd].ous.clone()\n\tmut new_ous := map[string][]i64{}\n\tfor k, v in m {\n\t\tif old_ous[k].len == 0 {\n\t\t\tnew_ous[k] = v\n\t\t} else {\n\t\t\tnew_ous[k] << old_ous[k]\n\t\t\tnew_ous[k] << v\n\t\t}\n\t}\n\tcontext.results[icmd].ous = new_ous.clone()\n}\n\nfn compare_by_average(a &CmdResult, b &CmdResult) int {\n\tif a.atiming.average < b.atiming.average {\n\t\treturn -1\n\t}\n\tif a.atiming.average > b.atiming.average {\n\t\treturn 1\n\t}\n\treturn 0\n}\n\nfn (mut context Context) show_diff_summary() {\n\tif context.results.len == 0 {\n\t\teprintln('no results')\n\t\texit(5)\n\t}\n\tbase := context.results[0].atiming.average\n\tcontext.results.sort_with_compare(compare_by_average)\n\tmut first_cmd_percentage := f64(100.0)\n\tmut first_marker := ''\n\tif context.results.len == 1 {\n\t\tgcmd := c(tgreen, context.results[0].cmd)\n\t\tcontext.show_summary_title('${context.results[0].atiming}, ${context.series} series, ${context.run_count} runs for ${gcmd}')\n\t} else {\n\t\tcontext.show_summary_title('Summary after ${context.series} series x ${context.run_count} runs (%s are relative to first command, or `base`)')\n\t\tfor i, r in context.results {\n\t\t\tfirst_marker = ' '\n\t\t\tcpercent := (r.atiming.average / base) * 100 - 100\n\t\t\tif r.icmd == 0 {\n\t\t\t\tfirst_marker = bold('>')\n\t\t\t\tfirst_cmd_percentage = cpercent\n\t\t\t}\n\t\t\tmut comparison := ''\n\t\t\tif r.atiming.average != base {\n\t\t\t\tcomparison = '${cpercent:+8.1f}%'\n\t\t\t}\n\t\t\tmut tcomparison := '  base          '\n\t\t\tif r.atiming.average != base {\n\t\t\t\ttcomparison = readable_comparison(r.atiming.average, base, cpercent)\n\t\t\t}\n\t\t\tgcmd := c(tgreen, r.cmd)\n\t\t\tprintln(' ${first_marker}${(i + 1):3} ${comparison:7} ${tcomparison:5} ${r.atiming} `${gcmd}`')\n\t\t}\n\t}\n\t$if debugcontext ? {\n\t\tprintln('context: ${context}')\n\t}\n\tif base > f64(context.fail_on_maxtime * 1000) {\n\t\tflushed_print(performance_regression_label)\n\t\tprintln('average time: ${base / 1000:6.1f} ms > ${context.fail_on_maxtime} ms threshold.')\n\t\texit(2)\n\t}\n\tif context.fail_on_regress_percent == max_fail_percent || context.results.len < 2 {\n\t\treturn\n\t}\n\tfail_threshold_max := f64(context.fail_on_regress_percent)\n\tif first_cmd_percentage > fail_threshold_max {\n\t\tflushed_print(performance_regression_label)\n\t\tprintln('${first_cmd_percentage:5.1f}% > ${fail_threshold_max:5.1f}% threshold.')\n\t\texit(3)\n\t}\n}\n\nfn readable_comparison(tcurrent f64, tbase f64, cpercent f64) string {\n\tis_same := math.abs(cpercent) <= 0.15\n\tmut label := '~same~'\n\tif tcurrent < tbase {\n\t\tif !is_same {\n\t\t\tlabel = c(tgreen, 'faster')\n\t\t}\n\t\treturn '${tbase / tcurrent:6.2f}x ${label}'\n\t} else {\n\t\tif !is_same {\n\t\t\tlabel = c(tcyan, 'slower')\n\t\t}\n\t\treturn '${tcurrent / tbase:6.2f}x ${label}'\n\t}\n}\n\nfn (mut context Context) show_summary_title(line string) {\n\tmut msg := [line]\n\tif context.nmins > 0 {\n\t\tmsg << 'discard mins: ${context.nmins:2}'\n\t}\n\tif context.nmaxs > 0 {\n\t\tmsg << 'discard maxs: ${context.nmaxs:2}'\n\t}\n\tif context.repeats_count > 1 {\n\t\tmsg << 'repeat: ${context.current_run}/${context.repeats_count}, took: ${f64(context.repeat_timer.elapsed().microseconds()) / 1000:8.3f} ms'\n\t\tcontext.repeat_timer.restart()\n\t}\n\tprintln(msg.join(', '))\n}\n\nfn (mut context Context) parse_options() ! {\n\tmut fp := flag.new_flag_parser(os.args#[1..])\n\tfp.application(os.file_name(os.executable()))\n\tfp.version('0.0.3')\n\tfp.description('Repeat command(s) and collect statistics.\\nNote: quote each command (argument), when it contains spaces.')\n\tfp.arguments_description('CMD1 CMD2 ...')\n\tfp.skip_executable()\n\tfp.limit_free_args_to_at_least(1)!\n\tcontext.show_help = fp.bool('help', `h`, false, 'Show this help screen.')\n\tcontext.run_count = fp.int('runs', `r`, 10, 'Run count. Default: 10')\n\tcontext.repeats_count = fp.int('repeats', `R`, 1, 'Repeats count (it repeats everything, including reporting). Default: 1')\n\tcontext.warmup = fp.int('warmup', `w`, 2, 'Warmup run count. These are done *at the start* of each series, and the timings are ignored. Default: 2')\n\tcontext.series = fp.int('series', `s`, 1, 'Series count. `-s 2 -r 4 a b` => aaaabbbbaaaabbbb, while `-s 3 -r 2 a b` => aabbaabbaabb. Default: 1')\n\tcontext.ignore_failed = fp.bool('ignore', `e`, false, 'Ignore failed commands (returning a non 0 exit code).')\n\tcontext.no_vexe_setenv = fp.bool('no_vexe_reset', `N`, false, 'Do not reset the VEXE env variable at the start. \\n                            By default, VEXE will be set to \"\", to allow for measuring different V executables. Use this option to override it')\n\tcontext.use_newline = fp.bool('newline', `n`, false, 'Use \\\\n, do not overwrite the last line. Produces more output, but easier to diagnose.')\n\tcontext.is_silent = fp.bool('silent', `S`, false, 'Do not show progress lines, print only the final summary. Suitable for CIs.')\n\tif os.getenv('VREPEAT_SILENT') != '' {\n\t\tcontext.is_silent = true\n\t}\n\tcontext.show_output = fp.bool('output', `O`, false, 'Show command stdout/stderr in the progress indicator for each command. Note: slower, for verbose commands.')\n\tcontext.verbose = fp.bool('verbose', `v`, false, 'Be more verbose.')\n\tcontext.fail_on_maxtime = fp.int('max_time', `m`, max_time, 'Fail with exit code 2, when first cmd takes above M milliseconds (regression). Default: ${max_time}')\n\tcontext.fail_on_regress_percent = fp.int('fail_percent', `f`, max_fail_percent, 'Fail with exit code 3, when first cmd is X% slower than the rest (regression). Default: ${max_fail_percent}')\n\tcontext.cmd_template = fp.string('template', `t`, '{T}', 'Command template. {T} will be substituted with the current command. Default: {T}. \\n                            Here is an example, that will produce and run 24 permutations = (3 for opt) x (2 for source) x (4 = v names):\\n                               v repeat -p opt=-check-syntax,-check,\"-o x.c\" -p source=examples/hello_world.v,examples/hanoi.v --template \"./{T} {opt} {source}\" vold vnew vold_prod vnew_prod')\n\tcmd_params := fp.string_multi('parameter', `p`, 'A parameter substitution list. `pp=val1,val2,val2` means that {pp} in the template, will be substituted with *each* of val1, val2, val3.')\n\tcontext.nmins = fp.int('nmins', `i`, 0, 'Ignore the BOTTOM X results (minimum execution time). Makes the results more robust to performance flukes. Default: 0')\n\tcontext.nmaxs = fp.int('nmaxs', `a`, 0, 'Ignore the TOP X results (maximum execution time). Makes the results more robust to performance flukes. Default: 0')\n\tfor p in cmd_params {\n\t\tparts := p.split('=')\n\t\tif parts.len > 1 {\n\t\t\tcontext.cmd_params[parts[0].trim('{}')] = parts[1].split(',')\n\t\t}\n\t}\n\tif context.show_help {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\tcommands := fp.finalize() or {\n\t\teprintln('Error: ${err}')\n\t\texit(1)\n\t}\n\tcontext.commands = context.expand_all_commands(commands)\n\tcontext.reset_results()\n\tif context.nmins >= context.run_count {\n\t\tcontext.error_no_run_counts_to_report('${context.run_count - 1} bottom results with `-i ${context.nmins}`')\n\t} else if context.nmaxs >= context.run_count {\n\t\tcontext.error_no_run_counts_to_report('${context.run_count - 1} top results with `-a ${context.nmaxs}`')\n\t} else if context.nmaxs + context.nmins >= context.run_count {\n\t\tcontext.error_no_run_counts_to_report('${context.nmaxs + context.nmins - 1} results with `-i ${context.nmins}` and `-a ${context.nmaxs}`')\n\t}\n\tif context.use_newline {\n\t\tcontext.cline = '\\n'\n\t\tcontext.cgoback = '\\n'\n\t} else {\n\t\tcontext.cline = '\\r' + tdivider('') + '\\r'\n\t\tcontext.cgoback = '\\r'\n\t}\n}\n\nfn (mut context Context) error_no_run_counts_to_report(detail string) {\n\teprintln('${bold('Warning:')} discarding more than ${detail}, with only `-r ${context.run_count}` runs, will leave you with no results to report at all.')\n}\n\nfn (mut context Context) reset_results() {\n\tcontext.results = []CmdResult{len: context.commands.len, cap: 20, init: CmdResult{\n\t\toutputs: []string{cap: 500}\n\t\ttimings: []i64{cap: 500}\n\t}}\n}\n\nfn main() {\n\tmut context := Context{}\n\tcontext.parse_options()!\n\tif !context.no_vexe_setenv {\n\t\t// Make sure that we can measure various V executables\n\t\t// without influencing them, by presetting VEXE\n\t\tos.setenv('VEXE', '', true)\n\t}\n\tfor i := 1; i <= context.repeats_count; i++ {\n\t\tcontext.current_run = i\n\t\tcontext.reset_results()\n\t\tcontext.run()\n\t\tcontext.show_diff_summary()\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vrepl.v",
    "content": "// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nmodule main\n\nimport os\nimport term\nimport rand\nimport readline\nimport os.cmdline\nimport v.util.version\n\nstruct Repl {\nmut:\n\treadline     readline.Readline\n\tindent       int    // indentation level\n\tin_func      bool   // inside function decl\n\tin_struct    bool   // inside struct decl\n\tin_enum      bool   // inside enum decl\n\tin_interface bool   // inside interface decl\n\tline         string // the current line entered by the user\n\tis_pin       bool   // does the repl 'pin' entered source code\n\tfolder       string // the folder in which the repl will write its temporary source files\n\tlast_output  string // the last repl output\n\n\tmodules         map[string][]string // all the import modules\n\talias           map[string]string   // all the alias used in the import\n\tincludes        []string            // all the #include statements\n\tfunctions       []string            // all the user function declarations\n\tfunctions_name  []string            // all the user function names\n\tstructs         []string            // all the struct definitions\n\tenums           []string            // all the enum definitions\n\tconsts          []string            // all the const definitions\n\ttypes           []string            // all the type definitions\n\tinterfaces      []string            // all the interface definitions\n\tlines           []string            // all the other lines/statements\n\ttemp_lines      []string            // all the temporary expressions/printlns\n\tvstartup_lines  []string            // lines in the `VSTARTUP` file\n\teval_func_lines []string            // same line of the `VSTARTUP` file, but used to test fn type\n}\n\nconst is_stdin_a_pipe = os.is_atty(0) == 0\nconst vexe = os.getenv('VEXE')\nconst vquiet = os.getenv('VQUIET') != ''\nconst vstartup = os.getenv('VSTARTUP')\nconst repl_folder = os.join_path(os.vtmp_dir(), 'repl')\n\nconst possible_statement_patterns = [\n\t'++',\n\t'--',\n\t'/*',\n\t'assert ',\n\t'fn ',\n\t'pub ',\n\t'mut ',\n\t'enum ',\n\t'const ',\n\t'struct ',\n\t'interface ',\n\t'import ',\n\t'#include ',\n\t'for ',\n\t'if ',\n\t'or ',\n\t' as ',\n]\n\nenum FnType {\n\tnone\n\tvoid\n\tfn_type\n}\n\nenum DeclType {\n\tinclude   // #include ...\n\tconst     // const ...\n\ttype      // type ...\n\tenum      // enum ...\n\tfn        // fn ...\n\tstruct    // struct ...\n\tinterface // interface ...\n\tstmt      // statement\n}\n\nfn new_repl(folder string) Repl {\n\tvstartup_source := os.read_file(vstartup) or { '' }.trim_right('\\n\\r').split_into_lines()\n\tos.mkdir_all(folder) or {}\n\treturn Repl{\n\t\treadline:       readline.Readline{\n\t\t\tskip_empty: true\n\t\t}\n\t\tfolder:         folder\n\t\tmodules:        {\n\t\t\t'os':   []\n\t\t\t'time': []\n\t\t\t'math': []\n\t\t}\n\t\tvstartup_lines: vstartup_source\n\t\t// Test file used to check if a function as a void return or a value return.\n\t\teval_func_lines: vstartup_source\n\t}\n}\n\nfn endline_if_missed(line string) string {\n\tif line.ends_with('\\n') {\n\t\treturn line\n\t}\n\treturn line + '\\n'\n}\n\nfn starts_with_type_decl(line string, type_name string) bool {\n\tif line.starts_with(type_name + ' ') || line.starts_with(type_name + '\\t') {\n\t\treturn true\n\t}\n\tif line.starts_with('pub ') || line.starts_with('pub\\t') {\n\t\tsubstring := line[3..].trim_space()\n\t\tif substring.starts_with(type_name + ' ') || substring.starts_with(type_name + '\\t') {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfn repl_help() {\n\tprintln(version.full_v_version(false))\n\tprintln('\n\t|help                   Displays this information.\n\t|list                   Show the program so far.\n\t|reset                  Clears the accumulated program, so you can start a fresh.\n\t|Ctrl-C, Ctrl-D, exit   Exits the REPL.\n\t|clear                  Clears the screen.\n\t|pin                    Pins the entered program to the top.\n\t|!sh [COMMAND]          Execute on REPL shell commands.\n'.strip_margin())\n}\n\nfn run_shell(command string) {\n\tif command.len >= 2 && command[0..2] == 'cd' {\n\t\tcommand_splited := command.split(' ')\n\t\tassert command_splited.len >= 2\n\t\tdir := command_splited[command_splited.len - 1]\n\n\t\tos.chdir(dir) or { eprintln('`${command}` failed, err: ${err}') }\n\t} else {\n\t\tos.system(command)\n\t}\n}\n\nfn (mut r Repl) checks() bool {\n\tmut in_string := false\n\twas_indent := r.indent > 0\n\tfor i := 0; i < r.line.len; i++ {\n\t\tif r.line[i] == `'` && (i == 0 || r.line[i - 1] != `\\\\`) {\n\t\t\tin_string = !in_string\n\t\t}\n\t\tif r.line[i] == `{` && !in_string {\n\t\t\tr.line = r.line[..i + 1] + '\\n' + r.line[i + 1..]\n\t\t\ti++\n\t\t\tr.indent++\n\t\t}\n\t\tif r.line[i] == `}` && !in_string {\n\t\t\tr.line = r.line[..i] + '\\n' + r.line[i..]\n\t\t\ti++\n\t\t\tr.indent--\n\t\t\tif r.indent == 0 {\n\t\t\t\tr.in_func = false\n\t\t\t\tr.in_struct = false\n\t\t\t\tr.in_enum = false\n\t\t\t\tr.in_interface = false\n\t\t\t}\n\t\t}\n\t}\n\treturn (was_indent && r.indent <= 0) || r.indent > 0\n}\n\nfn (r &Repl) function_call(line string) (bool, FnType) {\n\tfor function in r.functions_name {\n\t\tis_function_definition := line.replace(' ', '').starts_with('${function}:=')\n\t\tif line.starts_with(function) && !is_function_definition {\n\t\t\t// TODO(vincenzopalazzo) store the type of the function here\n\t\t\tfntype := r.check_fn_type_kind(line)\n\t\t\treturn true, fntype\n\t\t}\n\t}\n\n\tif line.contains(':=') {\n\t\t// an assignment to a variable:\n\t\t// `z := abc()`\n\t\treturn false, FnType.none\n\t}\n\n\t// Check if it is a Vlib call\n\t// TODO(vincenzopalazzo): auto import the module?\n\tif r.is_function_call(line) {\n\t\tfntype := r.check_fn_type_kind(line)\n\t\treturn true, fntype\n\t}\n\treturn false, FnType.none\n}\n\n// TODO(vincenzopalazzo) Remove this fancy check and add a regex\nfn (r &Repl) is_function_call(line string) bool {\n\treturn !line.starts_with('[') && line.contains('.') && line.contains('(')\n\t\t&& (line.ends_with(')') || line.ends_with('?') || line.ends_with('!'))\n}\n\n// Convert the list of modules that we parsed already,\n// to a sequence of V source code lines\nfn (r &Repl) import_to_source_code() []string {\n\tmut imports_line := []string{}\n\tfor mod, value in r.modules {\n\t\tmut import_str := 'import ${mod}'\n\t\tif mod in r.alias {\n\t\t\timport_str += ' as ${r.alias[mod]}'\n\t\t}\n\t\tif value.len > 0 {\n\t\t\timport_str += '{ '\n\t\t\tfor val in value {\n\t\t\t\timport_str += '${val}, '\n\t\t\t}\n\t\t\timport_str += '}'\n\t\t}\n\t\timports_line << endline_if_missed(import_str)\n\t}\n\treturn imports_line\n}\n\nfn (r &Repl) current_source_code(should_add_temp_lines bool, not_add_print bool) string {\n\tmut all_lines := r.import_to_source_code()\n\n\tif vstartup != '' {\n\t\tmut lines := []string{}\n\t\tif !not_add_print {\n\t\t\tlines = r.vstartup_lines.filter(!it.starts_with('print'))\n\t\t} else {\n\t\t\tlines = r.vstartup_lines.clone()\n\t\t}\n\t\tall_lines << lines\n\t}\n\tall_lines << r.includes\n\tall_lines << r.types\n\tall_lines << r.enums\n\tall_lines << r.consts\n\tall_lines << r.structs\n\tall_lines << r.interfaces\n\tall_lines << r.functions\n\tall_lines << r.lines\n\n\tif should_add_temp_lines {\n\t\tall_lines << r.temp_lines\n\t}\n\treturn all_lines.join('\\n')\n}\n\nfn (r &Repl) insert_source_code(typ DeclType, lines []string) string {\n\tmut all_lines := r.import_to_source_code()\n\n\tif vstartup != '' {\n\t\tall_lines << r.vstartup_lines.filter(!it.starts_with('print'))\n\t}\n\tall_lines << r.includes\n\tif typ == .include {\n\t\tall_lines << lines\n\t}\n\tall_lines << r.types\n\tif typ == .type {\n\t\tall_lines << lines\n\t}\n\tall_lines << r.enums\n\tif typ == .enum {\n\t\tall_lines << lines\n\t}\n\tall_lines << r.consts\n\tif typ == .const {\n\t\tall_lines << lines\n\t}\n\tall_lines << r.structs\n\tif typ == .struct {\n\t\tall_lines << lines\n\t}\n\tall_lines << r.interfaces\n\tif typ == .interface {\n\t\tall_lines << lines\n\t}\n\tall_lines << r.functions\n\tif typ == .fn {\n\t\tall_lines << lines\n\t}\n\tall_lines << r.lines\n\tif typ == .stmt {\n\t\tall_lines << lines\n\t}\n\treturn all_lines.join('\\n')\n}\n\n// the new_line is probably a function call, but some function calls\n// do not return anything, while others return results.\n// This function checks which one we have:\nfn (r &Repl) check_fn_type_kind(new_line string) FnType {\n\tsource_code := r.current_source_code(true, false) + '\\nprintln(${new_line})'\n\tcheck_file := os.join_path(r.folder, '${rand.ulid()}.vrepl.check.v')\n\tos.write_file(check_file, source_code) or { panic(err) }\n\tdefer {\n\t\tos.rm(check_file) or {}\n\t}\n\t// -w suppresses the unused import warnings\n\t// -check just does syntax and checker analysis without generating/running code\n\tos_response := os.execute('${os.quoted_path(vexe)} -w -check ${os.quoted_path(check_file)}')\n\tstr_response := convert_output(os_response.output)\n\tif os_response.exit_code != 0 && str_response.contains('can not print void expressions') {\n\t\treturn FnType.void\n\t}\n\treturn FnType.fn_type\n}\n\n// parse the import statement in `line`, updating the Repl alias maps\nfn (mut r Repl) parse_import(line string) {\n\tif !line.contains('import') {\n\t\teprintln(\"the line doesn't contain an `import` keyword\")\n\t\treturn\n\t}\n\ttokens := r.line.fields()\n\t// module name\n\tmod := tokens[1]\n\t// set alias\n\tif line.contains('as ') && tokens.len >= 4 {\n\t\talias := tokens[3]\n\t\tif mod !in r.alias {\n\t\t\tr.alias[mod] = alias\n\t\t}\n\t}\n\n\t// set value\n\tif line.contains('{') && line.contains('}') {\n\t\tvalues := line.split('{')[1].split('}')[0]\n\t\tfor value in values.split(',') {\n\t\t\tr.modules[mod] << value\n\t\t}\n\t} else {\n\t\tif mod !in r.modules {\n\t\t\tr.modules[mod] = []string{}\n\t\t}\n\t}\n}\n\n// clear the screen, then list source code\nfn (mut r Repl) pin() {\n\tterm.erase_clear()\n\tr.list_source()\n}\n\n// print source code\nfn (mut r Repl) list_source() {\n\tsource_code := r.current_source_code(true, true)\n\tprintln('\\n${source_code.replace('\\n\\n', '\\n')}')\n}\n\nfn highlight_console_command(command string) string {\n\treturn term.bright_white(term.bright_bg_black(' ${command} '))\n}\n\nfn highlight_repl_command(command string) string {\n\treturn term.bright_white(term.bg_blue(' ${command} '))\n}\n\nfn print_welcome_screen() {\n\tif vquiet {\n\t\treturn\n\t}\n\tcmd_exit := highlight_repl_command('exit')\n\tcmd_list := highlight_repl_command('list')\n\tcmd_help := highlight_repl_command('help')\n\tcmd_v_help := highlight_console_command('v help')\n\tcmd_v_run := highlight_console_command('v run main.v')\n\tfile_main := highlight_console_command('main.v')\n\tvbar := term.bright_green('|')\n\twidth, _ := term.get_terminal_size() // get the size of the terminal\n\tvlogo := [\n\t\tterm.bright_blue(r' ____    ____ '),\n\t\tterm.bright_blue(r' \\   \\  /   / '),\n\t\tterm.bright_blue(r'  \\   \\/   /  '),\n\t\tterm.bright_blue(r'   \\      /   '),\n\t\tterm.bright_blue(r'    \\    /    '),\n\t\tterm.bright_blue(r'     \\__/     '),\n\t]\n\thelp_text := [\n\t\t'Welcome to the V REPL (for help with V itself, type ${cmd_exit}, then run ${cmd_v_help}).',\n\t\t'Note: the REPL is highly experimental. For best V experience, use a text editor, ',\n\t\t'save your code in a ${file_main} file and execute: ${cmd_v_run}',\n\t\t'${version.full_v_version(false)} . Use ${cmd_list} to see the accumulated program so far.',\n\t\t'Use Ctrl-C or ${cmd_exit} to exit, or ${cmd_help} to see other available commands.',\n\t]\n\tif width >= 97 {\n\t\teprintln('${vlogo[0]}')\n\t\teprintln('${vlogo[1]} ${vbar}  ${help_text[0]}')\n\t\teprintln('${vlogo[2]} ${vbar}  ${help_text[1]}')\n\t\teprintln('${vlogo[3]} ${vbar}  ${help_text[2]}')\n\t\teprintln('${vlogo[4]} ${vbar}  ${help_text[3]}')\n\t\teprintln('${vlogo[5]} ${vbar}  ${help_text[4]}')\n\t\teprintln('')\n\t} else {\n\t\tif width >= 14 {\n\t\t\tleft_margin := ' '.repeat(int(width / 2 - 7))\n\t\t\tfor l in vlogo {\n\t\t\t\tprintln(left_margin + l)\n\t\t\t}\n\t\t}\n\t\tprintln(help_text.join('\\n'))\n\t}\n}\n\nfn remove_comment(oline string) string {\n\tmut inside_string := false\n\tmut escaped := false\n\tmut maybe_comment := false\n\n\tmut string_delim := 0\n\n\tmut i := 0\n\tfor i < oline.len {\n\t\tmatch oline[i] {\n\t\t\t`\"`, `'` {\n\t\t\t\tif !escaped {\n\t\t\t\t\tif inside_string && string_delim == oline[i] {\n\t\t\t\t\t\tinside_string = false\n\t\t\t\t\t} else if !inside_string {\n\t\t\t\t\t\tinside_string = true\n\t\t\t\t\t\tmaybe_comment = false\n\t\t\t\t\t\tstring_delim = oline[i]\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tescaped = false\n\t\t\t\t}\n\t\t\t}\n\t\t\t`\\\\` {\n\t\t\t\tif inside_string {\n\t\t\t\t\tescaped = !escaped\n\t\t\t\t}\n\t\t\t}\n\t\t\t`/` {\n\t\t\t\tif maybe_comment {\n\t\t\t\t\ti--\n\t\t\t\t\tbreak\n\t\t\t\t} else if !inside_string {\n\t\t\t\t\tmaybe_comment = true\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tescaped = false\n\t\t\t\tmaybe_comment = false\n\t\t\t}\n\t\t}\n\n\t\ti++\n\t}\n\n\treturn oline[..i]\n}\n\nfn run_repl(workdir string, vrepl_prefix string) int {\n\tif !is_stdin_a_pipe {\n\t\tprint_welcome_screen()\n\t}\n\n\tif vstartup != '' {\n\t\tresult := repl_run_vfile(vstartup) or {\n\t\t\tos.Result{\n\t\t\t\toutput: '${vstartup} file not found'\n\t\t\t}\n\t\t}\n\t\tprint('\\n')\n\t\tprint_output(result.output)\n\t}\n\ttemp_file := os.join_path(workdir, '.${vrepl_prefix}vrepl_temp.v')\n\tmut prompt := '>>> '\n\tdefer {\n\t\tif !is_stdin_a_pipe {\n\t\t\tprintln('')\n\t\t}\n\t\tcleanup_files(temp_file)\n\t}\n\tmut r := new_repl(workdir)\n\n\tfor {\n\t\tif r.indent == 0 {\n\t\t\tprompt = '>>> '\n\t\t} else {\n\t\t\tprompt = '... '\n\t\t}\n\n\t\toline := r.get_one_line(prompt) or { break }\n\t\tline := remove_comment(oline).trim_space()\n\n\t\tif line == '' {\n\t\t\tcontinue\n\t\t}\n\t\tif line.len <= -1 || line == 'exit' {\n\t\t\tbreak\n\t\t}\n\t\tr.line = line\n\t\tif r.line == 'clear' {\n\t\t\tterm.erase_clear()\n\t\t\tcontinue\n\t\t}\n\t\tif r.line == 'help' {\n\t\t\trepl_help()\n\t\t\tcontinue\n\t\t}\n\n\t\tif r.line.len > 4 && r.line[0..3] == '!sh' {\n\t\t\trun_shell(r.line[4..r.line.len])\n\t\t\tcontinue\n\t\t}\n\n\t\tif r.line.contains(':=') && r.line.contains('fn(') {\n\t\t\tr.in_func = true\n\t\t\tr.functions_name << r.line.all_before(':= fn(').trim_space()\n\t\t}\n\n\t\tstarts_with_fn := starts_with_type_decl(r.line, 'fn')\n\t\tif starts_with_fn {\n\t\t\tr.in_func = true\n\t\t\tr.functions_name << r.line.all_after('fn').all_before('(').trim_space()\n\t\t}\n\t\twas_func := r.in_func\n\n\t\tstarts_with_struct := starts_with_type_decl(r.line, 'struct')\n\t\tif starts_with_struct {\n\t\t\tr.in_struct = true\n\t\t}\n\t\twas_struct := r.in_struct\n\n\t\tstarts_with_enum := starts_with_type_decl(r.line, 'enum')\n\t\tif starts_with_enum {\n\t\t\tr.in_enum = true\n\t\t}\n\t\twas_enum := r.in_enum\n\n\t\tstarts_with_interface := starts_with_type_decl(r.line, 'interface')\n\t\tif starts_with_interface {\n\t\t\tr.in_interface = true\n\t\t}\n\t\twas_interface := r.in_interface\n\n\t\tif r.checks() {\n\t\t\tfor rline in r.line.split('\\n') {\n\t\t\t\tr.temp_lines << rline\n\t\t\t}\n\t\t\tif r.indent > 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tr.line = ''\n\t\t}\n\t\tif r.line == 'debug_repl' {\n\t\t\teprintln('repl: ${r}')\n\t\t\tcontinue\n\t\t}\n\t\tif r.line == 'reset' {\n\t\t\tr = new_repl(workdir)\n\t\t\tcontinue\n\t\t}\n\t\tif r.line == 'list' {\n\t\t\tr.list_source()\n\t\t\tcontinue\n\t\t}\n\t\tif r.line == 'pin' {\n\t\t\tr.is_pin = !r.is_pin\n\t\t\tif r.is_pin {\n\t\t\t\tr.pin()\n\t\t\t\tprintln('')\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif r.line.starts_with('=') {\n\t\t\tr.line = 'println(' + r.line[1..] + ')'\n\t\t}\n\t\tif r.line.starts_with('print(') || r.line.starts_with('println(') {\n\t\t\t// >>> println('hello')\n\t\t\tsource_code := r.current_source_code(false, false) + '\\n${r.line}\\n'\n\t\t\tos.write_file(temp_file, source_code) or { panic(err) }\n\t\t\ts := repl_run_vfile(temp_file) or { return 1 }\n\t\t\tif s.output.len > r.last_output.len {\n\t\t\t\tcur_line_output := s.output[r.last_output.len..]\n\t\t\t\tprint_output(cur_line_output)\n\t\t\t\tif s.exit_code == 0 && !cur_line_output.contains('warning:') {\n\t\t\t\t\tr.last_output = s.output.clone()\n\t\t\t\t\tr.lines << r.line\n\t\t\t\t}\n\t\t\t}\n\t\t} else if r.line.contains('os.input(') {\n\t\t\t// >>> s := os.input('name: ')\n\t\t\tprompt_str := r.line.all_after('os.input(').all_before(')').trim('\\'\"')\n\t\t\tline_t := r.get_one_line(prompt_str) or { break }.trim_right('\\n')\n\t\t\ttrans_line := r.line.all_before('os.input(') + \"'${line_t}'\"\n\t\t\tsource_code := r.current_source_code(false, false) + '\\n${trans_line}\\n'\n\t\t\tos.write_file(temp_file, source_code) or { panic(err) }\n\t\t\ts := repl_run_vfile(temp_file) or { return 1 }\n\t\t\tif s.exit_code == 0 {\n\t\t\t\tr.lines << trans_line\n\t\t\t}\n\t\t} else {\n\t\t\tfunc_call, fntype := r.function_call(r.line)\n\t\t\tfilter_line := r.line.replace(r.line.find_between(\"'\", \"'\"), '').replace(r.line.find_between('\"',\n\t\t\t\t'\"'), '')\n\t\t\tmut is_statement := false\n\t\t\tif filter_line.count('=') % 2 == 1\n\t\t\t\t&& (filter_line.count('!=') + filter_line.count('>=') + filter_line.count('<=')) == 0 {\n\t\t\t\tis_statement = true\n\t\t\t} else {\n\t\t\t\tfor pattern in possible_statement_patterns {\n\t\t\t\t\tif filter_line.contains(pattern) {\n\t\t\t\t\t\tis_statement = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Note: starting a line with 2 spaces escapes the println heuristic\n\t\t\tif oline.starts_with('  ') {\n\t\t\t\tis_statement = true\n\t\t\t}\n\t\t\t// The parentheses do not match\n\t\t\tif r.line.count('(') != r.line.count(')') {\n\t\t\t\tis_statement = true\n\t\t\t}\n\n\t\t\tif !is_statement && (!func_call || fntype == FnType.fn_type) && r.line != '' {\n\t\t\t\tprint_line := 'println(${r.line})'\n\t\t\t\tsource_code := r.current_source_code(false, false) + '\\n${print_line}\\n'\n\t\t\t\tos.write_file(temp_file, source_code) or { panic(err) }\n\t\t\t\ts := repl_run_vfile(temp_file) or { return 1 }\n\t\t\t\tif s.exit_code == 0 {\n\t\t\t\t\tif s.output.len > r.last_output.len {\n\t\t\t\t\t\tcur_line_output := s.output[r.last_output.len..]\n\t\t\t\t\t\tprint_output(cur_line_output)\n\t\t\t\t\t\tif !cur_line_output.contains('warning:') {\n\t\t\t\t\t\t\tr.last_output = s.output.clone()\n\t\t\t\t\t\t\tr.lines << print_line\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t} else {\n\t\t\t\t\tif s.output.len > r.last_output.len {\n\t\t\t\t\t\tcur_line_output := s.output[r.last_output.len..]\n\t\t\t\t\t\tif cur_line_output.contains('undefined ident:') {\n\t\t\t\t\t\t\tprint_output(cur_line_output)\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstarts_with_const := starts_with_type_decl(r.line, 'const')\n\t\t\tstarts_with_type := starts_with_type_decl(r.line, 'type')\n\t\t\tstarts_with_import := r.line.starts_with('import ') || r.line.starts_with('import\\t')\n\t\t\tstarts_with_include := r.line.starts_with('#include ')\n\t\t\t\t|| r.line.starts_with('#include\\t')\n\t\t\tmut temp_source_code := ''\n\n\t\t\tif starts_with_import {\n\t\t\t\tmod := r.line.fields()[1]\n\t\t\t\tif mod !in r.modules {\n\t\t\t\t\ttemp_source_code = '${r.line}\\n' + r.current_source_code(false, true)\n\t\t\t\t}\n\t\t\t} else if r.line.len == 0 {\n\t\t\t\tif was_func {\n\t\t\t\t\ttemp_source_code = r.insert_source_code(DeclType.fn, r.temp_lines)\n\t\t\t\t} else if was_struct {\n\t\t\t\t\ttemp_source_code = r.insert_source_code(DeclType.struct, r.temp_lines)\n\t\t\t\t} else if was_enum {\n\t\t\t\t\ttemp_source_code = r.insert_source_code(DeclType.enum, r.temp_lines)\n\t\t\t\t} else if was_interface {\n\t\t\t\t\ttemp_source_code = r.insert_source_code(DeclType.interface, r.temp_lines)\n\t\t\t\t} else {\n\t\t\t\t\ttemp_source_code = r.insert_source_code(DeclType.stmt, r.temp_lines)\n\t\t\t\t}\n\t\t\t} else if starts_with_include {\n\t\t\t\ttemp_source_code = r.insert_source_code(DeclType.include, [r.line])\n\t\t\t} else if starts_with_fn {\n\t\t\t\ttemp_source_code = r.insert_source_code(DeclType.fn, [r.line])\n\t\t\t} else if starts_with_const {\n\t\t\t\ttemp_source_code = r.insert_source_code(DeclType.const, [r.line])\n\t\t\t} else if starts_with_enum {\n\t\t\t\ttemp_source_code = r.insert_source_code(DeclType.enum, [r.line])\n\t\t\t} else if starts_with_struct {\n\t\t\t\ttemp_source_code = r.insert_source_code(DeclType.struct, [r.line])\n\t\t\t} else if starts_with_interface {\n\t\t\t\ttemp_source_code = r.insert_source_code(DeclType.interface, [r.line])\n\t\t\t} else if starts_with_type {\n\t\t\t\ttemp_source_code = r.insert_source_code(DeclType.type, [r.line])\n\t\t\t} else {\n\t\t\t\ttemp_source_code = r.current_source_code(true, false) + '\\n${r.line}\\n'\n\t\t\t}\n\t\t\tos.write_file(temp_file, temp_source_code) or { panic(err) }\n\t\t\ts := repl_run_vfile(temp_file) or { return 1 }\n\t\t\tif s.exit_code == 0 {\n\t\t\t\tif starts_with_import {\n\t\t\t\t\tr.parse_import(r.line)\n\t\t\t\t} else if r.line.len == 0 {\n\t\t\t\t\tif was_func {\n\t\t\t\t\t\tr.functions << r.temp_lines\n\t\t\t\t\t} else if was_struct {\n\t\t\t\t\t\tr.structs << r.temp_lines\n\t\t\t\t\t} else if was_enum {\n\t\t\t\t\t\tr.enums << r.temp_lines\n\t\t\t\t\t} else if was_interface {\n\t\t\t\t\t\tr.interfaces << r.temp_lines\n\t\t\t\t\t} else {\n\t\t\t\t\t\tr.lines << r.temp_lines\n\t\t\t\t\t}\n\t\t\t\t} else if starts_with_include {\n\t\t\t\t\tr.includes << r.line\n\t\t\t\t} else if starts_with_fn {\n\t\t\t\t\tr.functions << r.line\n\t\t\t\t} else if starts_with_const {\n\t\t\t\t\tr.consts << r.line\n\t\t\t\t} else if starts_with_enum {\n\t\t\t\t\tr.enums << r.line\n\t\t\t\t} else if starts_with_type {\n\t\t\t\t\tr.types << r.line\n\t\t\t\t} else if starts_with_struct {\n\t\t\t\t\tr.structs << r.line\n\t\t\t\t} else if starts_with_interface {\n\t\t\t\t\tr.interfaces << r.line\n\t\t\t\t} else {\n\t\t\t\t\tr.lines << r.line\n\t\t\t\t}\n\t\t\t}\n\t\t\tr.temp_lines.clear()\n\t\t\tif r.is_pin {\n\t\t\t\tr.pin()\n\t\t\t\tprintln('')\n\t\t\t}\n\t\t\tif s.output.len > r.last_output.len {\n\t\t\t\tlen := r.last_output.len\n\t\t\t\tif s.exit_code == 0 {\n\t\t\t\t\tr.last_output = s.output.clone()\n\t\t\t\t}\n\t\t\t\tcur_line_output := s.output[len..]\n\t\t\t\tprint_output(cur_line_output)\n\t\t\t}\n\t\t}\n\t}\n\treturn 0\n}\n\nfn convert_output(os_result string) string {\n\tlines := os_result.trim_right('\\n\\r').split_into_lines()\n\tmut content := ''\n\tfor line in lines {\n\t\tif line.contains('.vrepl_temp.v:') {\n\t\t\t// Hide the temporary file name\n\t\t\tsline := line.all_after('.vrepl_temp.v:')\n\t\t\tidx := sline.index(' ') or {\n\t\t\t\tcontent += endline_if_missed(sline)\n\t\t\t\treturn content\n\t\t\t}\n\t\t\tcontent += endline_if_missed(sline[idx + 1..])\n\t\t} else {\n\t\t\tcontent += endline_if_missed(line)\n\t\t}\n\t}\n\treturn content\n}\n\nfn print_output(os_result string) {\n\tcontent := convert_output(os_result)\n\tprint(content)\n}\n\nfn main() {\n\t// Support for the parameters replfolder and replprefix is needed\n\t// so that the repl can be launched in parallel by several different\n\t// threads by the REPL test runner.\n\targs := cmdline.options_after(os.args, ['repl'])\n\treplfolder := os.real_path(cmdline.option(args, '-replfolder', repl_folder))\n\treplprefix := cmdline.option(args, '-replprefix', 'noprefix.${rand.ulid()}.')\n\tif !os.exists(os.getenv('VEXE')) {\n\t\tprintln('Usage:')\n\t\tprintln('  VEXE=vexepath vrepl\\n')\n\t\tprintln('  ... where vexepath is the full path to the v executable file')\n\t\treturn\n\t}\n\tif !is_stdin_a_pipe {\n\t\tos.setenv('VCOLORS', 'always', true)\n\t}\n\texit(run_repl(replfolder, replprefix))\n}\n\nfn rerror(s string) {\n\tprintln('V repl error: ${s}')\n\tos.flush()\n}\n\nfn (mut r Repl) get_one_line(prompt string) ?string {\n\tif is_stdin_a_pipe {\n\t\tiline := os.get_raw_line()\n\t\tif iline.len == 0 {\n\t\t\treturn none\n\t\t}\n\t\treturn iline\n\t}\n\trline := r.readline.read_line(prompt) or { return none }\n\treturn rline\n}\n\nfn cleanup_files(file string) {\n\tos.rm(file) or {}\n\t$if windows {\n\t\tos.rm(file[..file.len - 2] + '.exe') or {}\n\t\t$if msvc {\n\t\t\tos.rm(file[..file.len - 2] + '.ilk') or {}\n\t\t\tos.rm(file[..file.len - 2] + '.pdb') or {}\n\t\t}\n\t} $else {\n\t\tos.rm(file[..file.len - 2]) or {}\n\t}\n}\n\nfn repl_run_vfile(file string) !os.Result {\n\t$if trace_repl_temp_files ? {\n\t\teprintln('>> repl_run_vfile file: ${file}')\n\t}\n\ts := os.execute('${os.quoted_path(vexe)} -message-limit 1 -repl run ${os.quoted_path(file)}')\n\tif s.exit_code < 0 {\n\t\trerror(s.output)\n\t\treturn error(s.output)\n\t}\n\treturn s\n}\n"
  },
  {
    "path": "cmd/tools/vretry.v",
    "content": "import os\nimport time\nimport flag\n\nstruct Context {\nmut:\n\tshow_help bool\n\ttimeout   time.Duration\n\tdelay     time.Duration\n\tretries   int\n}\n\nfn main() {\n\tmut context := Context{}\n\targs := os.args#[1..]\n\t// dump(args)\n\tmut fp := flag.new_flag_parser(args)\n\tfp.application('v retry')\n\tfp.version('0.0.1')\n\tfp.description('Run the command CMD in a loop, until it succeeds, or until a predetermined amount of seconds pass.')\n\tfp.arguments_description('CMD')\n\tfp.skip_executable()\n\tfp.limit_free_args_to_at_least(1)!\n\tcontext.show_help = fp.bool('help', `h`, false, 'Show this help screen.')\n\tcontext.timeout = fp.float('timeout', `t`, 900.0, 'Timeout in seconds (for all retries). Default: 900.0 seconds (15 minutes).') * time.second\n\tcontext.delay = fp.float('delay', `d`, 1.0, 'Delay between each retry in seconds. Default: 1.0 second.') * time.second\n\tcontext.retries = fp.int('retries', `r`, 10, 'Maximum number of retries. Default: 10.')\n\tif context.show_help {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\tcommand_args := fp.finalize() or {\n\t\teprintln('error: ${err}')\n\t\texit(1)\n\t}\n\tcmd := command_args.join(' ')\n\t// dump(cmd)\n\n\tspawn fn (context Context) {\n\t\ttime.sleep(context.timeout)\n\t\teprintln('error: exceeded maximum timeout (${context.timeout.seconds()}s)!')\n\t\texit(1)\n\t}(context)\n\n\tmut res := 0\n\tfor i in 0 .. context.retries {\n\t\tres = os.system(cmd)\n\t\tif res == 0 {\n\t\t\tbreak\n\t\t}\n\t\tif i == context.retries - 1 {\n\t\t\teprintln('error: exceeded maximum number of retries (${context.retries})!')\n\t\t\texit(res)\n\t\t}\n\t\ttime.sleep(context.delay)\n\t}\n\texit(res)\n}\n"
  },
  {
    "path": "cmd/tools/vretry_test.v",
    "content": "// This test uses the script cmd/tools/check_retry.vsh\nimport os\nimport log\n\nconst vexe = @VEXE\nconst vroot = os.dir(vexe)\n\nconst is_ci = os.getenv('CI') != ''\n\nfn dump_on_ci[T](x T) {\n\tif is_ci {\n\t\tdump(x)\n\t}\n}\n\nfn run(cmd string) os.Result {\n\tlog.info('>>>  running cmd: ${cmd}')\n\tdefer {\n\t\tlog.info('>>> finished cmd: ${cmd}')\n\t}\n\treturn os.execute(cmd)\n}\n\nfn test_retry() {\n\tlog.use_stdout()\n\tlog.warn('start...')\n\tdefer {\n\t\tlog.warn('... done')\n\t}\n\ttpath := os.join_path(os.vtmp_dir(), 'vretry_test')\n\tos.rmdir_all(tpath) or {}\n\tos.mkdir_all(tpath)!\n\tdefer {\n\t\tos.rmdir_all(tpath) or {}\n\t}\n\tos.chdir(vroot)!\n\tfail_cmd := '${vexe} run cmd/tools/check_retry.vsh too many arguments'\n\tif is_ci {\n\t\t// Skip longer running test on local runs.\n\t\tres := run('${vexe} retry ${fail_cmd}')\n\t\tassert res.exit_code != 0\n\t\tassert res.output.contains('error: exceeded maximum number of retries')\n\t}\n\n\tmut res := run('${vexe} retry -d 0.2 -r 3 ${fail_cmd}')\n\tdump_on_ci(res)\n\tassert res.exit_code != 0\n\tassert res.output.contains('error: exceeded maximum number of retries (3)!')\n\n\tpass_cmd := '${vexe} run cmd/tools/check_retry.vsh'\n\tres = run('${vexe} retry ${pass_cmd}')\n\tdump_on_ci(res)\n\tassert res.exit_code == 0\n\tassert res.output == run(pass_cmd).output\n\n\t// Include flags on the cmd as well.\n\tpass_cmd_with_flags := '${vexe} run cmd/tools/check_retry.vsh --list -x -- -b js arguments'\n\tres = run('${vexe} retry -r 3 -- ${pass_cmd_with_flags}')\n\tdump_on_ci(res)\n\tassert res.exit_code == 0\n\toutput_trimmed := res.output.trim_space()\n\tassert output_trimmed == \"['--list', '-x', '--', '-b', 'js', 'arguments']\"\n}\n"
  },
  {
    "path": "cmd/tools/vrun",
    "content": "#!/bin/sh\nv run $@\n\n## The purpose of this script, is to make it easier to run V scripts on systems, where\n## the `/usr/bin/env` implementation, does not yet support a `-S` option.\n## Notes: FreeBSD's env supports it since 2006.\n##        GNU's coreutils env supports it since 2018.\n##        BusyBox's env does not support it (2025/02/04).\n##        OpenBSD's env does not support it (2026/01/14).\n##        And there may be others like it too :-| .\n\n## On such systems, you can copy this script, or symlink it, somewhere in your PATH,\n## and then start your .vsh scripts with: `#!/usr/bin/env vrun`.\n## You can also start them with `#!/usr/bin/env /full/path/to/v/cmd/tools/vrun`, or\n## even just `#!/full/path/to/v run` directly, if you prefer.\n\n## You can check, if it works, by saving this as a /tmp/args.vsh file:\n## ```v\n## !/usr/bin/env vrun\n## println(arguments())\n## ```\n##\n## ... then run `chmod 755 /tmp/args.vsh`, and finally run:\n## `/tmp/args.vsh abc 123`\n##\n## If everything works correctly, you should see something like:\n## ['/tmp/args', 'abc', '123']\n"
  },
  {
    "path": "cmd/tools/vscan.v",
    "content": "module main\n\nimport os\nimport v.scanner\nimport v.token\nimport flag\n\nfn main() {\n\tmut fp := flag.new_flag_parser(os.args#[2..])\n\tfp.application('v scan')\n\tfp.version('0.0.1')\n\tfp.description('\\nScan .v source files, and print the V tokens contained in them.')\n\tfp.arguments_description('PATH [PATH]...')\n\tfp.limit_free_args_to_at_least(1)!\n\tmut all_paths := fp.remaining_parameters()\n\tfor path in all_paths {\n\t\tcontent := os.read_file(path) or {\n\t\t\teprintln('> could not read: ${path}, skipping; err: ${err}')\n\t\t\tcontinue\n\t\t}\n\t\tmut scanner_ := scanner.new_silent_scanner()\n\t\tscanner_.prepare_for_new_text(content)\n\t\tscanner_.is_fmt = false\n\t\tscanner_.pref.output_mode = .stdout\n\t\tscanner_.comments_mode = .skip_comments\n\t\tmut tok := token.Token{}\n\t\tfor tok.kind != .eof {\n\t\t\ttok = scanner_.text_scan()\n\t\t\tpos := tok.pos()\n\t\t\tlocation := '${path}:${pos.line_nr + 1}:${pos.col + 1}:'\n\t\t\tprintln('${location:-32} | pos: ${pos.pos:-5} | ${tok.debug()}')\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vschannel_16kb_httpbin_probe.v",
    "content": "import flag\nimport net.http\nimport os\nimport time\n\nconst probe_url = 'https://httpbin.org/post'\nconst vschannel_16kb_boundary = 16 * 1024\nconst default_sizes_csv = '12000,15000,17000,24000,32768'\n\nfn main() {\n\tif os.args.len >= 2 && os.args[1] == '--worker' {\n\t\trun_worker_mode()\n\t\treturn\n\t}\n\trun_parent_mode()\n}\n\nfn run_worker_mode() {\n\tif os.args.len < 3 {\n\t\teprintln('missing payload size for --worker')\n\t\texit(2)\n\t}\n\tsize := os.args[2].int()\n\tif size <= 0 {\n\t\teprintln('invalid payload size `${os.args[2]}`')\n\t\texit(2)\n\t}\n\tpayload := '{\"size\":${size},\"payload\":\"' + 'x'.repeat(size) + '\"}'\n\tmut headers := http.new_header()\n\theaders.add(.content_type, 'application/json')\n\tmut req := http.Request{\n\t\tmethod:        .post\n\t\turl:           probe_url\n\t\theader:        headers\n\t\tdata:          payload\n\t\tread_timeout:  60 * time.second\n\t\twrite_timeout: 30 * time.second\n\t}\n\tresp := req.do() or {\n\t\teprintln('request failed at size=${size}: ${err}')\n\t\texit(1)\n\t}\n\tif resp.status_code != 200 {\n\t\teprintln('unexpected status at size=${size}: ${resp.status_code}')\n\t\texit(1)\n\t}\n\tif !resp.body.contains('httpbin.org/post') {\n\t\teprintln('unexpected response body at size=${size}')\n\t\texit(1)\n\t}\n\tprintln('OK size=${size} payload_bytes=${payload.len}')\n}\n\nfn run_parent_mode() {\n\tmut fp := flag.new_flag_parser(os.args)\n\tfp.application('vschannel_16kb_httpbin_probe')\n\tfp.version('0.0.1')\n\tfp.description('Probe net.http HTTPS POST behavior around 16KB payloads using https://httpbin.org/post.')\n\tfp.skip_executable()\n\n\texpect_mode := fp.string('expect', `e`, 'after', 'Expected behavior mode: before|after|none. before expects >16KB failures, after expects all succeed.')\n\tsizes_csv := fp.string('sizes', `s`, default_sizes_csv, 'Comma separated payload sizes in bytes.')\n\tverbose := fp.bool('verbose', `v`, false, 'Print child process output for all sizes.')\n\tshow_help := fp.bool('help', `h`, false, 'Show this help screen.')\n\tfree_args := fp.finalize() or {\n\t\teprintln('flag parse failed: ${err}')\n\t\texit(2)\n\t}\n\tif free_args.len > 0 {\n\t\teprintln('unexpected positional args: ${free_args}')\n\t\texit(2)\n\t}\n\tif show_help {\n\t\tprintln(fp.usage())\n\t\treturn\n\t}\n\n\tmode := expect_mode.to_lower()\n\tif mode !in ['before', 'after', 'none'] {\n\t\teprintln('invalid --expect `${expect_mode}` (allowed: before|after|none)')\n\t\texit(2)\n\t}\n\tsizes := parse_sizes_csv(sizes_csv) or {\n\t\teprintln(err)\n\t\texit(2)\n\t}\n\n\tself_exe := os.executable()\n\tprintln('probe url: ${probe_url}')\n\tprintln('expect mode: ${mode}')\n\tprintln('sizes: ${sizes}')\n\n\tmut mismatches := 0\n\tfor size in sizes {\n\t\t// Launch worker directly without going through a shell, and capture stdout/stderr separately.\n\t\tmut p := os.new_process(self_exe)\n\t\tp.set_args(['--worker', size.str()])\n\t\tp.set_redirect_stdio()\n\t\tp.run()\n\t\tp.wait()\n\t\texit_code := p.code\n\t\tstdout := p.stdout_read().trim_space()\n\t\tstderr := p.stderr_read().trim_space()\n\t\tp.close()\n\t\tsuccess := exit_code == 0\n\t\texpected_success := expected_success_for_mode(mode, size)\n\t\tstatus := if success { 'OK' } else { 'FAIL' }\n\t\texpect_text := if expected_success { 'expect=OK' } else { 'expect=FAIL' }\n\t\tprintln('${status:4} size=${size:6} exit=${exit_code:3} ${expect_text}')\n\t\tif verbose || !success {\n\t\t\tif stdout.len > 0 {\n\t\t\t\tprintln(stdout)\n\t\t\t}\n\t\t\tif stderr.len > 0 {\n\t\t\t\teprintln(stderr)\n\t\t\t}\n\t\t}\n\t\tif mode != 'none' && success != expected_success {\n\t\t\tmismatches++\n\t\t}\n\t}\n\n\tif mismatches > 0 {\n\t\teprintln('mismatch count: ${mismatches}')\n\t\texit(1)\n\t}\n\tprintln('probe completed without mismatches')\n}\n\nfn parse_sizes_csv(raw string) ![]int {\n\tmut sizes := []int{}\n\tfor part in raw.split(',') {\n\t\titem := part.trim_space()\n\t\tif item.len == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tsize := item.int()\n\t\tif size <= 0 {\n\t\t\treturn error('invalid size entry `${item}` in --sizes')\n\t\t}\n\t\tsizes << size\n\t}\n\tif sizes.len == 0 {\n\t\treturn error('no sizes provided in --sizes')\n\t}\n\treturn sizes\n}\n\nfn expected_success_for_mode(mode string, size int) bool {\n\treturn match mode {\n\t\t'before' {\n\t\t\tsize <= vschannel_16kb_boundary\n\t\t}\n\t\t'after' {\n\t\t\ttrue\n\t\t}\n\t\t'none' {\n\t\t\ttrue\n\t\t}\n\t\telse {\n\t\t\teprintln('unexpected mode `${mode}` in expected_success_for_mode')\n\t\t\tfalse\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vself.v",
    "content": "module main\n\nimport os\nimport os.cmdline\nimport v.util.recompilation\n\nconst args_ = arguments()\nconst is_debug = args_.contains('-debug')\n\n// support a renamed `v` executable too:\nconst vexe = os.getenv_opt('VEXE') or { @VEXE }\n\nconst vroot = os.dir(vexe)\n\nfn main() {\n\t// make testing `v up` easier, by providing a way to force `v self` to fail,\n\t// to test the fallback logic:\n\tif os.getenv('VSELF_SHOULD_FAIL') != '' {\n\t\teprintln('v self failed')\n\t\texit(1)\n\t}\n\tvexe_name := os.file_name(vexe)\n\tshort_v_name := vexe_name.all_before('.')\n\n\trecompilation.must_be_enabled(vroot, 'Please install V from source, to use `${vexe_name} self` .')\n\tos.chdir(vroot)!\n\tos.setenv('VCOLORS', 'always', true)\n\tmut args := args_[1..].filter(it != 'self')\n\tif args.len == 0 || ('-cc' !in args && '-prod' !in args && '-parallel-cc' !in args) {\n\t\t// compiling by default, i.e. `v self`:\n\t\tuos := os.user_os()\n\t\tuname := os.uname()\n\t\tif uos == 'macos' && uname.machine == 'arm64' {\n\t\t\t// Apple silicon, like m1, m2 etc\n\t\t\t// Use tcc by default for V, since tinycc is much faster and also\n\t\t\t// it already supports compiling many programs like V itself, that do not depend on inlined objective-C code\n\t\t\targs << '-cc tcc'\n\t\t}\n\t}\n\tif !has_gc_arg(args) {\n\t\targs << ['-gc', 'none']\n\t}\n\tjargs := args.join(' ')\n\tobinary := cmdline.option(args, '-o', '')\n\tsargs := if obinary != '' { jargs } else { '${jargs} -o v2' }\n\tcmd := '${os.quoted_path(vexe)} ${sargs} ${os.quoted_path('cmd/v')}'\n\toptions := if args.len > 0 { '(${sargs})' } else { '' }\n\tprintln('V self compiling ${options}...')\n\tfinal_binary := if obinary != '' { obinary } else { 'v2' }\n\tmut used_pgo := false\n\tpgo_cc_kind := pgo_compiler_kind(args)\n\tif pgo_cc_kind != '' {\n\t\tused_pgo = compile_with_pgo(vroot, vexe, args, final_binary, pgo_cc_kind)\n\t\tif !used_pgo {\n\t\t\teprintln('PGO self-build failed; falling back to a regular self-build.')\n\t\t}\n\t}\n\tif !used_pgo {\n\t\tcompile(vroot, cmd)\n\t}\n\tif obinary != '' {\n\t\t// When -o was given, there is no need to backup/rename the original.\n\t\t// The user just wants an independent copy of v, and so we are done.\n\t\treturn\n\t}\n\tbackup_old_version_and_rename_newer(short_v_name) or { panic(err.msg()) }\n\tprintln('V built successfully as executable \"${vexe_name}\".')\n}\n\nfn has_gc_arg(args []string) bool {\n\tfor arg in args {\n\t\tif arg == '-gc' {\n\t\t\treturn true\n\t\t}\n\t\tif arg.starts_with('-gc=') {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfn has_profile_cflag(args []string) bool {\n\tmut skip_next := false\n\tfor i, arg in args {\n\t\tif skip_next {\n\t\t\tskip_next = false\n\t\t\tcontinue\n\t\t}\n\t\tif arg in ['-cflags', '-cf'] {\n\t\t\tif i + 1 < args.len {\n\t\t\t\tnext_arg := args[i + 1]\n\t\t\t\tif next_arg.contains('-fprofile') {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t\tskip_next = true\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif (arg.starts_with('-cflags=') || arg.starts_with('-cf=')) && arg.contains('-fprofile') {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfn pgo_compiler_kind(args []string) string {\n\tif '-prod' !in args || '-no-prod-options' in args {\n\t\treturn ''\n\t}\n\tif os.user_os() == 'windows' {\n\t\treturn ''\n\t}\n\tif has_profile_cflag(args) {\n\t\treturn ''\n\t}\n\tmut ccompiler := cmdline.option(args, '-cc', '')\n\tif ccompiler == '' {\n\t\tccompiler = os.getenv_opt('CC') or { 'cc' }\n\t}\n\tcc_file_name := os.file_name(ccompiler)\n\tif cc_file_name.contains('clang') || cc_file_name.contains('gcc')\n\t\t|| cc_file_name.contains('g++') || ccompiler == 'cc' {\n\t\tcc_ver := os.execute('${os.quoted_path(ccompiler)} --version').output\n\t\tif cc_ver.contains('clang') {\n\t\t\t_ := find_llvm_profdata() or { return '' }\n\t\t\treturn 'clang'\n\t\t}\n\t\tif cc_ver.contains('Free Software Foundation') || cc_ver.contains('GCC') {\n\t\t\treturn 'gcc'\n\t\t}\n\t}\n\tif cc_file_name.contains('clang') {\n\t\t_ := find_llvm_profdata() or { return '' }\n\t\treturn 'clang'\n\t}\n\tif cc_file_name.contains('gcc') || cc_file_name.contains('g++') {\n\t\treturn 'gcc'\n\t}\n\treturn ''\n}\n\nfn find_llvm_profdata() !string {\n\tif profdata := os.find_abs_path_of_executable('llvm-profdata') {\n\t\treturn profdata\n\t}\n\t$if macos {\n\t\txcrun_result := os.execute('xcrun --find llvm-profdata')\n\t\tif xcrun_result.exit_code == 0 {\n\t\t\txcrun_path := xcrun_result.output.trim_space()\n\t\t\tif xcrun_path != '' && os.exists(xcrun_path) {\n\t\t\t\treturn xcrun_path\n\t\t\t}\n\t\t}\n\t}\n\treturn error('can not find llvm-profdata in PATH')\n}\n\nfn with_output_arg(args []string, output string) []string {\n\tmut res := []string{cap: args.len + 2}\n\tmut skip_next := false\n\tfor i, arg in args {\n\t\tif skip_next {\n\t\t\tskip_next = false\n\t\t\tcontinue\n\t\t}\n\t\tif arg == '-o' {\n\t\t\tif i + 1 < args.len {\n\t\t\t\tskip_next = true\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif arg.starts_with('-o=') {\n\t\t\tcontinue\n\t\t}\n\t\tres << arg\n\t}\n\tres << ['-o', output]\n\treturn res\n}\n\nfn compose_v_cmd(vexe string, args []string, source string) string {\n\tmut parts := []string{cap: args.len + 2}\n\tparts << os.quoted_path(vexe)\n\tfor arg in args {\n\t\tparts << os.quoted_path(arg)\n\t}\n\tparts << os.quoted_path(source)\n\treturn parts.join(' ')\n}\n\nfn run_cmd(cmd string) ! {\n\tresult := os.execute(cmd)\n\tif result.exit_code != 0 {\n\t\treturn error(result.output)\n\t}\n\tif result.output.len > 0 {\n\t\tprintln(result.output.trim_space())\n\t}\n}\n\nfn compile_with_pgo(vroot string, vexe string, args []string, out_binary string, cc_kind string) bool {\n\tpgo_workspace := os.join_path(vroot, '.vself_pgo')\n\tos.rmdir_all(pgo_workspace) or {}\n\tos.mkdir_all(pgo_workspace) or {\n\t\teprintln('PGO disabled: can not create ${pgo_workspace}: ${err.msg()}')\n\t\treturn false\n\t}\n\tdefer {\n\t\tos.rmdir_all(pgo_workspace) or {}\n\t}\n\tprofile_dir := os.join_path(pgo_workspace, 'profile')\n\tos.mkdir_all(profile_dir) or {\n\t\teprintln('PGO disabled: can not create ${profile_dir}: ${err.msg()}')\n\t\treturn false\n\t}\n\tpgo_binary := os.join_path(pgo_workspace, 'v_pgo_gen')\n\ttraining_output := os.join_path(pgo_workspace, 'cmd_v_training.c')\n\tmut use_profile_flag := '-fprofile-use=${profile_dir}'\n\tmut llvm_profdata := ''\n\tmut profile_data := ''\n\tif cc_kind == 'clang' {\n\t\tllvm_profdata = find_llvm_profdata() or {\n\t\t\teprintln('PGO disabled: can not find `llvm-profdata`.')\n\t\t\treturn false\n\t\t}\n\t\tprofile_data = os.join_path(pgo_workspace, 'code.profdata')\n\t\tuse_profile_flag = '-fprofile-use=${profile_data}'\n\t}\n\tmut generate_args := with_output_arg(args, pgo_binary)\n\tgenerate_args << ['-cflags', '-fprofile-generate=${profile_dir}']\n\tgenerate_cmd := compose_v_cmd(vexe, generate_args, 'cmd/v')\n\trun_cmd(generate_cmd) or {\n\t\teprintln('PGO step failed while building the instrumented compiler.')\n\t\teprintln(err.msg())\n\t\treturn false\n\t}\n\ttraining_cmd := '${os.quoted_path(pgo_binary)} -o ${os.quoted_path(training_output)} ${os.quoted_path('cmd/v')}'\n\trun_cmd(training_cmd) or {\n\t\teprintln('PGO step failed while generating the profiling data.')\n\t\teprintln(err.msg())\n\t\treturn false\n\t}\n\tif cc_kind == 'clang' {\n\t\tmerge_cmd := '${os.quoted_path(llvm_profdata)} merge -output=${os.quoted_path(profile_data)} ${os.quoted_path(profile_dir)}'\n\t\trun_cmd(merge_cmd) or {\n\t\t\teprintln('PGO step failed while merging the profiling data.')\n\t\t\teprintln(err.msg())\n\t\t\treturn false\n\t\t}\n\t}\n\tmut final_args := with_output_arg(args, out_binary)\n\tfinal_args << ['-cflags', use_profile_flag]\n\tif cc_kind == 'gcc' {\n\t\tfinal_args << ['-cflags', '-fprofile-correction']\n\t}\n\tfinal_cmd := compose_v_cmd(vexe, final_args, 'cmd/v')\n\trun_cmd(final_cmd) or {\n\t\teprintln('PGO step failed while building the final compiler binary.')\n\t\teprintln(err.msg())\n\t\treturn false\n\t}\n\treturn true\n}\n\nfn compile(vroot string, cmd string) {\n\tresult := os.execute_or_exit(cmd)\n\tif result.exit_code != 0 {\n\t\teprintln('cannot compile to `${vroot}`: \\n${result.output}')\n\t\texit(1)\n\t}\n\tif result.output.len > 0 {\n\t\tprintln(result.output.trim_space())\n\t}\n}\n\nfn list_folder(short_v_name string, bmessage string, message string) {\n\tif !is_debug {\n\t\treturn\n\t}\n\tif bmessage != '' {\n\t\tprintln(bmessage)\n\t}\n\tif os.user_os() == 'windows' {\n\t\tos.system('dir ${short_v_name}*.exe')\n\t} else {\n\t\tos.system('ls -lartd ${short_v_name}*')\n\t}\n\tprintln(message)\n}\n\nfn backup_old_version_and_rename_newer(short_v_name string) !bool {\n\tmut errors := []string{}\n\tshort_v_file := if os.user_os() == 'windows' { '${short_v_name}.exe' } else { '${short_v_name}' }\n\tshort_v2_file := if os.user_os() == 'windows' { 'v2.exe' } else { 'v2' }\n\tshort_bak_file := if os.user_os() == 'windows' { 'v_old.exe' } else { 'v_old' }\n\tv_file := os.real_path(short_v_file)\n\tv2_file := os.real_path(short_v2_file)\n\tbak_file := os.real_path(short_bak_file)\n\n\tlist_folder(short_v_name, 'before:', 'removing ${bak_file} ...')\n\tif os.exists(bak_file) {\n\t\tos.rm(bak_file) or { errors << 'failed removing ${bak_file}: ${err.msg()}' }\n\t}\n\n\tlist_folder(short_v_name, '', 'moving ${v_file} to ${bak_file} ...')\n\tos.mv(v_file, bak_file) or { errors << err.msg() }\n\n\tlist_folder(short_v_name, '', 'removing ${v_file} ...')\n\tos.rm(v_file) or {}\n\n\tlist_folder(short_v_name, '', 'moving ${v2_file} to ${v_file} ...')\n\tos.mv_by_cp(v2_file, v_file) or { panic(err.msg()) }\n\n\tlist_folder(short_v_name, 'after:', '')\n\n\tif errors.len > 0 {\n\t\teprintln('backup errors:\\n  >>  ' + errors.join('\\n  >>  '))\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "cmd/tools/vsetup-freetype.v",
    "content": "module main\n\nimport os\n\nconst freetype_repo_url = 'https://github.com/ubawurinna/freetype-windows-binaries'\n\nconst freetype_folder = os.join_path('thirdparty', 'freetype')\n\nfn main() {\n\t$if windows {\n\t\tprintln('Setup freetype...')\n\t\tvexe := os.real_path(os.getenv_opt('VEXE') or { @VEXE })\n\t\tvroot := os.dir(vexe)\n\t\tos.chdir(vroot)!\n\t\tif os.is_dir(freetype_folder) {\n\t\t\tprintln('Thirdparty \"freetype\" is already installed.')\n\t\t} else {\n\t\t\ts := os.execute('${os.quoted_path(vexe)} retry -- git clone --filter=blob:none ${freetype_repo_url} ${freetype_folder}')\n\t\t\tif s.exit_code != 0 {\n\t\t\t\tpanic(s.output)\n\t\t\t}\n\t\t\tprintln(s.output)\n\t\t\tprintln('Thirdparty \"freetype\" installed successfully.')\n\t\t}\n\t} $else {\n\t\tprintln('It is only for Windows to setup thirdparty \"freetype\".')\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vshader.v",
    "content": "// Copyright (c) 2024 Lars Pontoppidan. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\n//\n// vshader aids in generating special shader code C headers via sokol-shdc's 'annotated GLSL' format to any\n// supported target formats that sokol_gfx supports internally.\n//\n// vshader bootstraps itself by downloading its own dependencies to a system cache directory on first run.\n//\n// Please see https://github.com/floooh/sokol-tools/blob/master/docs/sokol-shdc.md#feature-overview\n// for a more in-depth overview of the specific tool in use.\n//\n// The shader language used is, as described on the overview page linked above, an 'annotated GLSL'\n// and 'modern GLSL' (v450) shader language format.\nimport os\nimport time\nimport io.util\nimport flag\nimport net.http\n\nconst shdc_full_hash = '0d91b038780614a867f2c8eecd7d935d76bcaae3'\nconst tool_version = '0.0.4'\nconst tool_description = \"Compile shaders in sokol's annotated GLSL format to C headers for use with sokol based apps\"\nconst tool_name = os.file_name(os.executable())\nconst cache_dir = os.join_path(os.cache_dir(), 'v', tool_name)\nconst runtime_os = os.user_os()\nconst supported_hosts = ['linux', 'macos', 'windows']\nconst supported_slangs = [\n\t'glsl430', // default desktop OpenGL backend (SOKOL_GLCORE)\n\t'glsl410', // default macOS desktop OpenGL\n\t'glsl300es', // OpenGLES3 and WebGL2 (SOKOL_GLES3)\n\t'hlsl4', // Direct3D11 with HLSL4 (SOKOL_D3D11)\n\t'hlsl5', // Direct3D11 with HLSL5 (SOKOL_D3D11)\n\t'metal_macos', // Metal on macOS (SOKOL_METAL)\n\t'metal_ios', // Metal on iOS devices (SOKOL_METAL)\n\t'metal_sim', // Metal on iOS simulator (SOKOL_METAL)\n\t'wgsl', // WebGPU (SOKOL_WGPU)\n\t'reflection',\n]\nconst default_slangs = [\n\t'glsl410',\n\t'glsl300es',\n\t// 'hlsl4', and hlsl5 can't be used at the same time\n\t'hlsl5',\n\t'metal_macos',\n\t'metal_ios',\n\t'metal_sim',\n\t'wgsl',\n]\n\nconst shdc_version = shdc_full_hash[0..8]\nconst shdc_urls = {\n\t'windows': 'https://github.com/floooh/sokol-tools-bin/raw/${shdc_full_hash}/bin/win32/sokol-shdc.exe'\n\t'macos':   'https://github.com/floooh/sokol-tools-bin/raw/${shdc_full_hash}/bin/osx/sokol-shdc'\n\t'linux':   'https://github.com/floooh/sokol-tools-bin/raw/${shdc_full_hash}/bin/linux/sokol-shdc'\n\t'osx_a64': 'https://github.com/floooh/sokol-tools-bin/raw/${shdc_full_hash}/bin/osx_arm64/sokol-shdc'\n}\nconst shdc_version_file = os.join_path(cache_dir, 'sokol-shdc.version')\nconst shdc_exe = os.join_path(cache_dir, 'sokol-shdc.exe')\n\nstruct Options {\n\tshow_help    bool\n\tverbose      bool\n\tforce_update bool\n\tslangs       []string\n}\n\nstruct CompileOptions {\n\tverbose     bool\n\tslangs      []string\n\tinvoke_path string\n}\n\nfn main() {\n\tif os.args.len == 1 {\n\t\tprintln('Usage: ${tool_name} PATH \\n${tool_description}\\n${tool_name} -h for more help...')\n\t\texit(1)\n\t}\n\tmut fp := flag.new_flag_parser(os.args[1..])\n\tfp.application(tool_name)\n\tfp.version(tool_version)\n\tfp.description(tool_description)\n\tfp.arguments_description('PATH [PATH]...')\n\tfp.skip_executable()\n\t// Collect tool options\n\topt := Options{\n\t\tshow_help:    fp.bool('help', `h`, false, 'Show this help text.')\n\t\tforce_update: fp.bool('force-update', `u`, false, 'Force update of the sokol-shdc tool.')\n\t\tverbose:      fp.bool('verbose', `v`, false, 'Be verbose about the tools progress.')\n\t\tslangs:       fp.string_multi('slang', `l`, 'Shader dialects to generate code for. Default is all.\\n                            Available dialects: ${supported_slangs}')\n\t}\n\tif opt.show_help {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\n\tensure_external_tools(opt) or { panic(err) }\n\n\tinput_paths := fp.finalize() or { panic(err) }\n\n\tfor path in input_paths {\n\t\tif os.exists(path) {\n\t\t\tcompile_shaders(opt, path) or { panic(err) }\n\t\t}\n\t}\n}\n\n// shader_program_name returns the name of the program from `shader_file`.\n// shader_program_name returns a blank string if no @program entry could be found.\nfn shader_program_name(shader_file string) string {\n\tshader_program := os.read_lines(shader_file) or { return '' }\n\tfor line in shader_program {\n\t\tif line.contains('@program ') {\n\t\t\treturn line.all_after('@program ').all_before(' ')\n\t\t}\n\t}\n\treturn ''\n}\n\n// validate_shader_file returns an error if `shader_file` isn't valid.\nfn validate_shader_file(shader_file string) ! {\n\tshader_program := os.read_lines(shader_file) or {\n\t\treturn error('shader program at \"${shader_file}\" could not be opened for reading')\n\t}\n\tmut has_program_directive := false\n\tfor line in shader_program {\n\t\tif line.contains('@program ') {\n\t\t\thas_program_directive = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif !has_program_directive {\n\t\treturn error('shader program at \"${shader_file}\" is missing a \"@program\" directive.')\n\t}\n}\n\n// compile_shaders compiles all `*.glsl` files found in `input_path`\n// to their C header file representatives.\nfn compile_shaders(opt Options, input_path string) ! {\n\tmut path := os.real_path(input_path)\n\tpath = path.trim_right('/')\n\tif os.is_file(path) {\n\t\tpath = os.dir(path)\n\t}\n\n\tmut shader_files := []string{}\n\tcollect(path, mut shader_files)\n\n\tif shader_files.len == 0 {\n\t\tif opt.verbose {\n\t\t\teprintln('${tool_name} found no shader files to compile for \"${path}\"')\n\t\t}\n\t\treturn\n\t}\n\n\tfor shader_file in shader_files {\n\t\t// It could be the user has WIP shader files lying around not used,\n\t\t// so we just report that there's something wrong\n\t\tvalidate_shader_file(shader_file) or {\n\t\t\teprintln(err)\n\t\t\tcontinue\n\t\t}\n\t\tco := CompileOptions{\n\t\t\tverbose:     opt.verbose\n\t\t\tslangs:      opt.slangs\n\t\t\tinvoke_path: path\n\t\t}\n\t\t// Currently sokol-shdc allows for multiple --input flags\n\t\t// - but it's only the last entry that's actually compiled/used\n\t\t// Given this fact - we can only compile one '.glsl' file to one C '.h' header\n\t\tcompile_shader(co, shader_file)!\n\t}\n}\n\n// compile_shader compiles `shader_file` to a C header file.\nfn compile_shader(opt CompileOptions, shader_file string) ! {\n\tpath := opt.invoke_path\n\t// The output convention, for now, is to use the name of the .glsl file\n\tmut out_file := os.file_name(shader_file).all_before_last('.') + '.h'\n\tout_file = os.join_path(path, out_file)\n\n\tmut slangs := opt.slangs.clone()\n\tif opt.slangs.len == 0 {\n\t\tslangs = default_slangs.clone()\n\t}\n\n\theader_name := os.file_name(out_file)\n\tif opt.verbose {\n\t\teprintln('${tool_name} generating shader code for ${slangs} in header \"${header_name}\" in \"${path}\" from ${shader_file}')\n\t}\n\n\tcmd :=\n\t\t'${os.quoted_path(shdc_exe)} --input ${os.quoted_path(shader_file)} --output ${os.quoted_path(out_file)} --slang ' +\n\t\tos.quoted_path(slangs.join(':'))\n\tif opt.verbose {\n\t\teprintln('${tool_name} executing:\\n${cmd}')\n\t}\n\tres := os.execute(cmd)\n\tif res.exit_code != 0 {\n\t\teprintln('${tool_name} failed generating shader includes:\\n        ${res.output}\\n        ${cmd}')\n\t\texit(1)\n\t}\n\tif opt.verbose {\n\t\tprogram_name := shader_program_name(shader_file)\n\t\teprintln('${tool_name} usage example in V:\\n\\nimport sokol.gfx\\n\\n#include \"${header_name}\"\\n\\nfn C.${program_name}_shader_desc(gfx.Backend) &gfx.ShaderDesc\\n')\n\t}\n}\n\n// collect recursively collects `.glsl` file entries from `path` in `list`.\nfn collect(path string, mut list []string) {\n\tif !os.is_dir(path) {\n\t\treturn\n\t}\n\tmut files := os.ls(path) or { return }\n\tfor file in files {\n\t\tp := os.join_path(path, file)\n\t\tif os.is_dir(p) && !os.is_link(p) {\n\t\t\tcollect(p, mut list)\n\t\t} else if os.exists(p) {\n\t\t\tif os.file_ext(p) == '.glsl' {\n\t\t\t\tlist << os.real_path(p)\n\t\t\t}\n\t\t}\n\t}\n\treturn\n}\n\n// ensure_external_tools returns nothing if the external\n// tools can be setup or is already in place.\nfn ensure_external_tools(opt Options) ! {\n\tif !os.exists(cache_dir) {\n\t\tos.mkdir_all(cache_dir)!\n\t}\n\tif opt.force_update {\n\t\tdownload_shdc(opt)!\n\t\treturn\n\t}\n\n\tis_shdc_available := os.is_file(shdc_exe)\n\tis_shdc_executable := os.is_executable(shdc_exe)\n\tif opt.verbose {\n\t\teprintln('reading version from ${shdc_version_file} ...')\n\t\tversion := os.read_file(shdc_version_file) or { 'unknown' }\n\t\teprintln('${tool_name} using sokol-shdc version ${version} at \"${shdc_exe}\"')\n\t\teprintln('executable: ${is_shdc_executable}')\n\t\teprintln(' available: ${is_shdc_available}')\n\t\tif is_shdc_available {\n\t\t\teprintln(' file path: ${shdc_exe}')\n\t\t\teprintln(' file size: ${os.file_size(shdc_exe)}')\n\t\t\teprintln(' file time: ${time.unix_microsecond(os.file_last_mod_unix(shdc_exe),\n\t\t\t\t0)}')\n\t\t}\n\t}\n\tif is_shdc_available && is_shdc_executable {\n\t\treturn\n\t}\n\n\tdownload_shdc(opt)!\n}\n\n// download_shdc downloads the `sokol-shdc` tool to an OS specific cache directory.\nfn download_shdc(opt Options) ! {\n\t// We want to use the same, runtime, OS type as this tool is invoked on.\n\tmut download_url := shdc_urls[runtime_os] or { '' }\n\t$if arm64 && macos {\n\t\tdownload_url = shdc_urls['osx_a64']\n\t}\n\tif download_url == '' {\n\t\treturn error('${tool_name} failed to download an external dependency \"sokol-shdc\" for ${runtime_os}.\\nThe supported host platforms for shader compilation is ${supported_hosts}')\n\t}\n\tif opt.verbose {\n\t\teprintln('> reading version from ${shdc_version_file} ...')\n\t}\n\tupdate_to_shdc_version := os.read_file(shdc_version_file) or { shdc_version }\n\tif opt.verbose {\n\t\teprintln('> update_to_shdc_version: ${update_to_shdc_version} | shdc_version: ${shdc_version}')\n\t}\n\tif opt.verbose {\n\t\tif shdc_version != update_to_shdc_version && os.exists(shdc_exe) {\n\t\t\teprintln('${tool_name} updating sokol-shdc to version ${shdc_version} ...')\n\t\t} else {\n\t\t\teprintln('${tool_name} installing sokol-shdc version ${update_to_shdc_version} ...')\n\t\t}\n\t}\n\tif os.exists(shdc_exe) {\n\t\tos.rm(shdc_exe)!\n\t}\n\n\tmut dtmp_file, dtmp_path := util.temp_file(util.TempFileOptions{ path: os.dir(shdc_exe) })!\n\tdtmp_file.close()\n\tif opt.verbose {\n\t\teprintln('${tool_name} downloading sokol-shdc from ${download_url}')\n\t}\n\thttp.download_file(download_url, dtmp_path) or {\n\t\tos.rm(dtmp_path)!\n\t\treturn error('${tool_name} failed to download sokol-shdc needed for shader compiling: ${err}')\n\t}\n\t// Make it executable\n\tos.chmod(dtmp_path, 0o775)!\n\t// Move downloaded file in place\n\tos.mv(dtmp_path, shdc_exe)!\n\t// Update internal version file\n\tos.write_file(shdc_version_file, shdc_version)!\n}\n"
  },
  {
    "path": "cmd/tools/vshare.v",
    "content": "module main\n\nimport net.http\nimport os\nimport clipboard\nimport json\n\nstruct Response {\n\thash  string\n\terror string\n}\n\nfn main() {\n\tmut cb := clipboard.new()\n\n\tif os.args.len < 3 {\n\t\teprintln('Please provide a file')\n\t\texit(1)\n\t}\n\n\tif os.file_ext(os.args[2]) != '.v' {\n\t\teprintln('Must be a V source file.')\n\t\texit(1)\n\t}\n\n\tif !os.is_file(os.args[2]) {\n\t\teprintln('File not found.')\n\t\texit(1)\n\t}\n\n\tto_send := os.args[2]\n\n\tcontent := os.read_file(to_send) or {\n\t\teprintln(err)\n\t\texit(1)\n\t}\n\n\tshare := http.post_form('https://play.vlang.io/share', {\n\t\t'code': content\n\t})!\n\n\tresponse := json.decode(Response, share.body)!\n\turl := 'https://play.vlang.io/p/${response.hash}'\n\n\tcb.copy(url)\n\tprintln(url)\n\tprintln('Copied URL to clipboard.')\n}\n"
  },
  {
    "path": "cmd/tools/vshould-compile-all.v",
    "content": "import os\nimport log\n\nconst should_clean = os.args.contains('-c')\n\nfn main() {\n\tlog.use_stdout()\n\tunbuffer_stdout()\n\tmut files := []string{}\n\targs := os.args#[2..].filter(it != '-c')\n\tfor a in args {\n\t\tif os.is_file(a) {\n\t\t\tfiles << a\n\t\t\tcontinue\n\t\t}\n\t\tif os.is_dir(a) {\n\t\t\tfiles << os.walk_ext(a, '.v')\n\t\t\tcontinue\n\t\t}\n\t}\n\tfiles.sort()\n\tif files.len == 0 {\n\t\tprintln('0 .v files found.\\n')\n\t\tprintln('Usage:')\n\t\tprintln('  v should-compile-all [-c] examples/ some/deep/file.v another/')\n\t\tprintln('... will try to compile all .v files found in the given folders and files, one by one.')\n\t\tprintln('If every single one of them compiles, the command will exit with an error code of 0.')\n\t\tprintln('If *any* of them *fail* to compile, the command will exit with an error code of 1.')\n\t\tprintln('')\n\t\tprintln('  -c will remove all the compiled executables at the end.')\n\t\tprintln('')\n\t\tprintln('Note: this command is intended to be used in CI pipelines for v modules, like this:')\n\t\tprintln(' cd module/ ; v should-compile-all examples/ \\n')\n\t\texit(1)\n\t}\n\tmut executables := []string{}\n\tmut failed_commands := []string{}\n\tmut project_folders := map[string]bool{}\n\tmut skipped_files := []string{}\n\tfor idx, example in files {\n\t\tfolder_of_example := os.dir(example)\n\t\tif os.is_file(os.join_path_single(folder_of_example, '.skip_should_compile_all')) {\n\t\t\tlog.info('>>> skipping file: ${example}, because a `.skip_should_compile_all` file is present next to it.')\n\t\t\tskipped_files << example\n\t\t\tcontinue\n\t\t}\n\t\t// project folders usually contain many .v files, that are *all* part of the same program.\n\t\t// NOTE: => projects should be compiled with `v project/`.\n\t\t// To do that, just record the presence of such a folder for now, and try to compile it separately later.\n\t\tif project_folders[folder_of_example] {\n\t\t\tskipped_files << example\n\t\t\tcontinue\n\t\t}\n\t\tif os.is_file(os.join_path_single(folder_of_example, 'v.mod')) {\n\t\t\tlog.info('>>> delaying compilation of entire project folder ${folder_of_example} ...')\n\t\t\tproject_folders[folder_of_example] = true\n\t\t\tskipped_files << example\n\t\t\tcontinue\n\t\t}\n\t\t//\n\t\tmut backend_options := '-b c'\n\t\tif example.ends_with('.wasm.v') {\n\t\t\tbackend_options = '-b wasm -os browser'\n\t\t}\n\t\tif example.ends_with('.js.v') {\n\t\t\tbackend_options = '-b js'\n\t\t}\n\t\tlines := os.read_lines(example)!#[..50].filter(it.starts_with('module'))\n\t\tif lines.len > 0 && lines[0] !in ['module main', 'module no_main'] {\n\t\t\tlog.info('>>> skipping non main module file: ${example}')\n\t\t\tskipped_files << example\n\t\t\tcontinue\n\t\t}\n\t\tcmd := '${os.quoted_path(@VEXE)} ${backend_options} ${os.quoted_path(example)}'\n\t\tlog.info('> compiling program ${idx + 1:4}/${files.len:-4}: ${cmd}')\n\t\tif 0 != os.system(cmd) {\n\t\t\tfailed_commands << cmd\n\t\t} else {\n\t\t\texecutables << executable_name(example)\n\t\t}\n\t}\n\n\tmut glsl_folders := map[string]bool{}\n\tmut pfi := 0\n\tfor pf, _ in project_folders {\n\t\tglsl_files := os.walk_ext(pf, '.glsl')\n\t\tif glsl_files.len > 0 {\n\t\t\tif pf !in glsl_folders {\n\t\t\t\tlog.debug('>>> found .glsl files in ${pf} ... running `v shader ${pf}` ...')\n\t\t\t\tos.system('${os.quoted_path(@VEXE)} shader ${os.quoted_path(pf)}')\n\t\t\t\tglsl_folders[pf] = true\n\t\t\t}\n\t\t}\n\t\texe_path := os.join_path(pf, os.file_name(pf) + exe_extension)\n\t\tcmd := '${os.quoted_path(@VEXE)} -o ${exe_path} ${pf}'\n\t\tlog.info('> compiling project ${pfi + 1:4}/${project_folders.len:-4}: ${cmd}')\n\t\tif 0 != os.system(cmd) {\n\t\t\tfailed_commands << cmd\n\t\t} else {\n\t\t\texecutables << exe_path\n\t\t}\n\t\tpfi++\n\t}\n\n\tif should_clean {\n\t\tlog.info('Removing ${executables.len} successfully build executables...')\n\t\tfor f in executables {\n\t\t\tos.rm(f) or { log.error('>> could not remove ${f}, err: ${err}') }\n\t\t}\n\t}\n\tif failed_commands.len > 0 {\n\t\tfor idx, fcmd in failed_commands {\n\t\t\tlog.error('>>> FAILED command ${idx + 1:4}/${failed_commands.len:-4}: ${fcmd}')\n\t\t}\n\t\tlog.info('Summary: ${failed_commands.len:4}/${files.len:-4} file(s) failed to compile.')\n\t\texit(1)\n\t}\n\tlog.info('Summary: all ${files.len} program file(s), and ${project_folders.len} project(s) compiled successfully. Skipped files: ${skipped_files.len} .')\n}\n\nconst exe_extension = if os.user_os() == 'windows' {\n\t'.exe'\n} else {\n\t''\n}\n\nfn executable_name(source string) string {\n\tbasepath := source.replace(os.file_ext(source), '')\n\treturn basepath + exe_extension\n}\n"
  },
  {
    "path": "cmd/tools/vsymlink/vsymlink.v",
    "content": "import os\n\nconst vexe = os.real_path(os.getenv_opt('VEXE') or { @VEXE })\n\nfn main() {\n\tat_exit(|| os.rmdir_all(os.vtmp_dir()) or {}) or {}\n\tif os.args.len > 2 {\n\t\tif '-githubci' in os.args {\n\t\t\t// TODO: [AFTER 2024-09-31] remove `-githubci` flag and function and only print usage and exit(1) .\n\t\t\tif os.getenv('GITHUB_JOB') != '' {\n\t\t\t\tprintln('::warning::Use `v symlink` instead of `v symlink -githubci`')\n\t\t\t}\n\t\t\tsetup_symlink_github()\n\t\t\treturn\n\t\t} else {\n\t\t\tprintln('usage: v symlink')\n\t\t\texit(1)\n\t\t}\n\t}\n\tsetup_symlink()\n}\n\nfn setup_symlink_github() {\n\t// We append V's install location (which should\n\t// be the current directory) to the PATH environment variable.\n\n\t// Resources:\n\t// 1. https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#environment-files\n\t// 2. https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-environment-variable\n\tmut content := os.read_file(os.getenv('GITHUB_PATH')) or {\n\t\teprintln('The `GITHUB_PATH` env variable is not defined.')\n\t\teprintln('    This command: `v symlink -githubci` is intended to be used within GithubActions .yml files.')\n\t\teprintln('    It also needs to be run *as is*, *** without `sudo` ***, otherwise it will not work.')\n\t\teprintln('    For local usage, outside CIs, on !windows, prefer `sudo ./v symlink` .')\n\t\teprintln('    On windows, use `.\\\\v.exe symlink` instead.')\n\t\texit(1)\n\t}\n\tcontent += '\\n${os.getwd()}\\n'\n\tos.write_file(os.getenv('GITHUB_PATH'), content) or { panic('Failed to write to GITHUB_PATH.') }\n}\n"
  },
  {
    "path": "cmd/tools/vsymlink/vsymlink_nix.c.v",
    "content": "import os\n\nfn setup_symlink() {\n\tmut link_path := '/data/data/com.termux/files/usr/bin/v'\n\tif !os.is_dir('/data/data/com.termux/files') {\n\t\tlink_dir := '/usr/local/bin'\n\t\tif !os.exists(link_dir) {\n\t\t\tos.mkdir_all(link_dir) or { panic(err) }\n\t\t}\n\t\tlink_path = link_dir + '/v'\n\t}\n\tos.rm(link_path) or {}\n\tos.symlink(vexe, link_path) or {\n\t\t// Try ~/.local/bin as a fallback when /usr/local/bin is not writable.\n\t\thome := os.home_dir()\n\t\tif home == '' {\n\t\t\teprintln('Failed to create symlink \"${link_path}\": ${err}')\n\t\t\teprintln('Try again with sudo.')\n\t\t\texit(1)\n\t\t}\n\t\tlocal_bin := os.join_path(home, '.local', 'bin')\n\t\tif !os.exists(local_bin) {\n\t\t\tos.mkdir_all(local_bin) or {\n\t\t\t\teprintln('Failed to create symlink \"${link_path}\": ${err}')\n\t\t\t\teprintln('Try again with sudo.')\n\t\t\t\texit(1)\n\t\t\t}\n\t\t}\n\t\tlink_path = os.join_path(local_bin, 'v')\n\t\tos.rm(link_path) or {}\n\t\tos.symlink(vexe, link_path) or {\n\t\t\teprintln('Failed to create symlink \"${link_path}\": ${err}')\n\t\t\teprintln('Try again with sudo.')\n\t\t\texit(1)\n\t\t}\n\t\teprintln('Note: Symlink created in \"${local_bin}\" instead of \"/usr/local/bin\".')\n\t\tif path := os.getenv_opt('PATH') {\n\t\t\tif !path.contains(local_bin) {\n\t\t\t\teprintln('Make sure \"${local_bin}\" is in your PATH.')\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vsymlink/vsymlink_windows.c.v",
    "content": "import os\n\n$if tinyc {\n\t#flag -ladvapi32\n\t#flag -luser32\n}\n\nfn setup_symlink() {\n\t// Create a symlink in a new local folder (.\\.bin\\.v.exe)\n\t// Puts `v` in %PATH% without polluting it with anything else (like make.bat).\n\t// This will make `v` available on cmd.exe, PowerShell, and MinGW(MSYS)/WSL/Cygwin\n\tvdir := os.real_path(os.dir(vexe))\n\tvsymlinkdir := os.join_path(vdir, '.bin')\n\tmut vsymlink := os.join_path(vsymlinkdir, 'v.exe')\n\t// Remove old symlink first (v could have been moved, symlink rerun)\n\tif !os.exists(vsymlinkdir) {\n\t\tos.mkdir(vsymlinkdir) or { panic(err) }\n\t} else {\n\t\tif os.exists(vsymlink) {\n\t\t\tos.rm(vsymlink) or { panic(err) }\n\t\t} else {\n\t\t\tvsymlink = os.join_path(vsymlinkdir, 'v.bat')\n\t\t\tif os.exists(vsymlink) {\n\t\t\t\tos.rm(vsymlink) or { panic(err) }\n\t\t\t}\n\t\t\tvsymlink = os.join_path(vsymlinkdir, 'v.exe')\n\t\t}\n\t}\n\t// First, try to create a native symlink at .\\.bin\\v.exe\n\tos.symlink(vexe, vsymlink) or {\n\t\t// typically only fails if you're on a network drive (VirtualBox)\n\t\t// do batch file creation instead\n\t\teprintln('Could not create a native symlink: ${err}')\n\t\teprintln('Creating a batch file instead...')\n\t\tvsymlink = os.join_path(vsymlinkdir, 'v.bat')\n\t\tif os.exists(vsymlink) {\n\t\t\tos.rm(vsymlink) or { panic(err) }\n\t\t}\n\t\tos.write_file(vsymlink, '@echo off\\n\"${vexe}\" %*') or { panic(err) }\n\t\teprintln('${vsymlink} file written.')\n\t}\n\tif !os.exists(vsymlink) {\n\t\twarn_and_exit('Could not create ${vsymlink}')\n\t}\n\tprintln('Symlink ${vsymlink} to ${vexe} created.')\n\tprintln('Checking system %PATH%...')\n\treg_sys_env_handle := get_reg_sys_env_handle() or {\n\t\twarn_and_exit(err.msg())\n\t\treturn\n\t}\n\t// TODO: Fix defers inside ifs\n\t// defer {\n\t// C.RegCloseKey(reg_sys_env_handle)\n\t// }\n\t// if the above succeeded, and we cannot get the value, it may simply be empty\n\tsys_env_path := get_reg_value(reg_sys_env_handle, 'Path') or { '' }\n\tcurrent_sys_paths := sys_env_path.split(os.path_delimiter).map(it.trim('/${os.path_separator}'))\n\tmut new_paths := [vsymlinkdir]\n\tfor p in current_sys_paths {\n\t\tif p == '' {\n\t\t\tcontinue\n\t\t}\n\t\tif p !in new_paths {\n\t\t\tnew_paths << p\n\t\t}\n\t}\n\tnew_sys_env_path := new_paths.join(os.path_delimiter)\n\tif new_sys_env_path == sys_env_path {\n\t\tprintln('System %PATH% was already configured.')\n\t} else {\n\t\tprintln('System %PATH% was not configured.')\n\t\tprintln('Adding symlink directory to system %PATH%...')\n\t\tset_reg_value(reg_sys_env_handle, 'Path', new_sys_env_path) or {\n\t\t\tC.RegCloseKey(reg_sys_env_handle)\n\t\t\twarn_and_exit(err.msg())\n\t\t}\n\t\tprintln('Done.')\n\t}\n\tprintln('Notifying running processes to update their Environment...')\n\tsend_setting_change_msg('Environment') or {\n\t\teprintln(err)\n\t\tC.RegCloseKey(reg_sys_env_handle)\n\t\twarn_and_exit('You might need to run this again to have the `v` command in your %PATH%')\n\t}\n\tC.RegCloseKey(reg_sys_env_handle)\n\tif os.getenv('GITHUB_JOB') != '' {\n\t\t// Append V's install location to GITHUBs PATH environment variable.\n\t\t// Resources:\n\t\t// 1. https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#environment-files\n\t\t// 2. https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-environment-variable\n\t\tmut content := os.read_file(os.getenv('GITHUB_PATH')) or {\n\t\t\teprintln('The `GITHUB_PATH` env variable is not defined.')\n\t\t\texit(1)\n\t\t}\n\t\tcontent += '\\n${new_sys_env_path}\\n'\n\t\tos.write_file(os.getenv('GITHUB_PATH'), content) or {\n\t\t\tpanic('Failed to write to GITHUB_PATH.')\n\t\t}\n\t}\n\tprintln('Done.')\n\tprintln('Note: Restart your shell/IDE to load the new %PATH%.')\n\tprintln('After restarting your shell/IDE, give `v version` a try in another directory!')\n}\n\nfn warn_and_exit(err string) {\n\teprintln(err)\n\texit(1)\n}\n\n// get the system environment registry handle\nfn get_reg_sys_env_handle() !voidptr {\n\t// open the registry key\n\treg_key_path := 'Environment'\n\treg_env_key := unsafe { nil } // or HKEY (HANDLE)\n\tif C.RegOpenKeyEx(os.hkey_current_user, reg_key_path.to_wide(), 0, 1 | 2, &reg_env_key) != 0 {\n\t\treturn error('Could not open \"${reg_key_path}\" in the registry')\n\t}\n\treturn reg_env_key\n}\n\n// get a value from a given $key\nfn get_reg_value(reg_env_key voidptr, key string) !string {\n\t// query the value (shortcut the sizing step)\n\treg_value_size := u32(4095) // this is the max length (not for the registry, but for the system %PATH%)\n\tmut reg_value := unsafe { &u16(malloc(int(reg_value_size))) }\n\tif C.RegQueryValueExW(reg_env_key, key.to_wide(), 0, 0, reg_value, &reg_value_size) != 0 {\n\t\treturn error('Unable to get registry value for \"${key}\".')\n\t}\n\treturn unsafe { string_from_wide(reg_value) }\n}\n\n// sets the value for the given $key to the given  $value\nfn set_reg_value(reg_key voidptr, key string, value string) !bool {\n\tif C.RegSetValueExW(reg_key, key.to_wide(), 0, C.REG_EXPAND_SZ, value.to_wide(), value.len * 2) != 0 {\n\t\treturn error('Unable to set registry value for \"${key}\". %PATH% may be too long.')\n\t}\n\treturn true\n}\n\n// Broadcasts a message to all listening windows (explorer.exe in particular)\n// letting them know that the system environment has changed and should be reloaded\nfn send_setting_change_msg(message_data string) !bool {\n\tif C.SendMessageTimeoutW(os.hwnd_broadcast, os.wm_settingchange, 0, unsafe { &u32(message_data.to_wide()) },\n\t\tos.smto_abortifhung, 5000, 0) == 0 {\n\t\treturn error('Could not broadcast WM_SETTINGCHANGE')\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "cmd/tools/vtest-all.v",
    "content": "module main\n\nimport os\nimport term\nimport time\n\ntype FnCheck = fn () !\n\ntype OneOrManyStrings = string | []string\n\nconst vexe_path = os.getenv('VEXE')\n\nconst vroot = os.dir(vexe_path)\n\nconst vexe = os.quoted_path(vexe_path)\n\nconst args_string = os.args[1..].join(' ')\n\nconst vargs = args_string.all_before('test-all')\n\nconst vtest_nocleanup = os.getenv('VTEST_NOCLEANUP').bool()\n\nconst hw_native_no_builtin_size_limit = 300\n\nconst l2w_crosscc = os.find_abs_path_of_executable('x86_64-w64-mingw32-gcc-win32') or { '' }\n\nconst clang_path = os.find_abs_path_of_executable('clang') or { '' }\n\nfn main() {\n\tunbuffer_stdout()\n\tmut commands := get_all_commands()\n\t// summary\n\tsw := time.new_stopwatch()\n\tfor mut cmd in commands {\n\t\tcmd.run()?\n\t}\n\tspent := sw.elapsed().milliseconds()\n\toks := commands.filter(it.ecode == 0)\n\tfails := commands.filter(it.ecode != 0)\n\tprintln('')\n\tprintln(term.header_left(term_highlight('Summary of `v test-all`:'), '-'))\n\tfor ocmd in oks {\n\t\tmsg := if ocmd.okmsg != '' { ocmd.okmsg } else { ocmd.line }\n\t\tprintln(term.colorize(term.green, '>          OK: ${msg} '))\n\t}\n\tfor fcmd in fails {\n\t\tmsg := if fcmd.errmsg != '' { fcmd.errmsg } else { fcmd.line }\n\t\tprintln(term.failed('>      Failed:') + ' ${msg}')\n\t}\n\tprintln(term_highlight('Total runtime: ${spent} ms'))\n\tif fails.len > 0 {\n\t\texit(1)\n\t}\n}\n\nenum RunCommandKind {\n\tsystem\n\texecute\n}\n\nstruct Command {\nmut:\n\tline        string\n\tlabel       string // when set, the label will be printed *before* cmd.line is executed\n\tecode       int\n\tokmsg       string\n\terrmsg      string\n\trmfile      ?OneOrManyStrings\n\truncmd      RunCommandKind = .system\n\texpect      ?string\n\tstarts_with ?string\n\tends_with   ?string\n\tcontains    ?string\n\toutput      string\n\tbefore_cb   FnCheck = unsafe { nil }\n\tafter_cb    FnCheck = unsafe { nil }\n}\n\nfn get_all_commands() []Command {\n\tmut res := []Command{}\n\tres << Command{\n\t\tline:   '${vexe} examples/hello_world.v'\n\t\tokmsg:  'V can compile hello world.'\n\t\trmfile: 'examples/hello_world'\n\t}\n\tres << Command{\n\t\tline:   '${vexe} -W -Wimpure-v examples/hello_world.v'\n\t\tokmsg:  'V can compile hello world with the stricter `-W -Wimpure-v` mode .'\n\t\trmfile: 'examples/hello_world'\n\t}\n\t$if linux {\n\t\tif l2w_crosscc != '' {\n\t\t\tres << Command{\n\t\t\t\tline:   '${vexe} -os windows examples/hello_world.v'\n\t\t\t\tokmsg:  'V cross compiles hello_world.v on linux, to a windows .exe file'\n\t\t\t\trmfile: 'examples/hello_world.exe'\n\t\t\t}\n\t\t} else {\n\t\t\teprintln('Testing cross compilation from linux to windows needs x86_64-w64-mingw32-gcc-win32. Skipping hello_world.exe test.')\n\t\t}\n\t}\n\tres << Command{\n\t\tline:   '${vexe} -o hhww.c examples/hello_world.v'\n\t\tokmsg:  'V can output a .c file, without compiling further.'\n\t\trmfile: 'hhww.c'\n\t}\n\tres << Command{\n\t\tline:  '${vexe} -silent test vlib/builtin'\n\t\tokmsg: 'V can test vlib/builtin'\n\t}\n\tres << Command{\n\t\tline:   '${vexe} -profile - examples/hello_world.v'\n\t\tokmsg:  'V can compile hello world with -profile .'\n\t\trmfile: 'examples/hello_world'\n\t}\n\tres << Command{\n\t\tline:   '${vexe} -e \"print(84/2)\"'\n\t\tokmsg:  'V can run code given after `-e`'\n\t\truncmd: .execute\n\t\texpect: '42'\n\t}\n\tres << Command{\n\t\tline:   '${vexe} -e \"import os; import math; print(os.args#[1..]) print(math.sin(math.pi/2).str())\" arg1 arg2'\n\t\tokmsg:  'V can run code with `-e`, that use semicolons and several imports, and that accepts CLI parameters.'\n\t\truncmd: .execute\n\t\texpect: \"['arg1', 'arg2']1.0\"\n\t}\n\tres << Command{\n\t\tline:     '${vexe} -o calling_c.exe run examples/call_c_from_v/main.c.v'\n\t\tokmsg:    'V can run main.c.v files'\n\t\truncmd:   .execute\n\t\tcontains: 'V can call C functions like `puts` too.'\n\t}\n\t$if linux || macos {\n\t\tres << Command{\n\t\t\tline:   '${vexe} run examples/hello_world.v'\n\t\t\tokmsg:  'V can run hello world.'\n\t\t\truncmd: .execute\n\t\t\texpect: 'Hello, World!\\n'\n\t\t}\n\t\tif clang_path != '' {\n\t\t\tres << Command{\n\t\t\t\tline:     '${vexe} -os freebsd -gc none examples/hello_world.v'\n\t\t\t\tokmsg:    'V cross compiles hello_world.v, to a FreeBSD executable'\n\t\t\t\trmfile:   'examples/hello_world'\n\t\t\t\tafter_cb: fn () ! {\n\t\t\t\t\tfor file in ['examples/hello_world',\n\t\t\t\t\t\tos.join_path(os.vmodules_dir(), 'freebsdroot/usr/include/stdio.h')] {\n\t\t\t\t\t\tif !os.exists(file) {\n\t\t\t\t\t\t\treturn error('>> file ${file} does not exist')\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\teprintln('Testing cross compilation to FreeBSD, needs clang.')\n\t\t}\n\t\tif os.getenv('V_CI_MUSL').len == 0 {\n\t\t\tfor compiler_name in ['clang', 'gcc'] {\n\t\t\t\tif _ := os.find_abs_path_of_executable(compiler_name) {\n\t\t\t\t\tres << Command{\n\t\t\t\t\t\tline:   '${vexe} -cc ${compiler_name} -gc boehm run examples/hello_world.v'\n\t\t\t\t\t\tokmsg:  '`v -cc ${compiler_name} -gc boehm run examples/hello_world.v` works'\n\t\t\t\t\t\truncmd: .execute\n\t\t\t\t\t\texpect: 'Hello, World!\\n'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tres << Command{\n\t\t\tline:   '${vexe} interpret examples/hello_world.v'\n\t\t\tokmsg:  'V can interpret hello world.'\n\t\t\truncmd: .execute\n\t\t\texpect: 'Hello, World!\\n'\n\t\t}\n\t\tres << Command{\n\t\t\tline:        '${vexe} interpret examples/hanoi.v'\n\t\t\tokmsg:       'V can interpret hanoi.v'\n\t\t\truncmd:      .execute\n\t\t\tstarts_with: 'Disc 1 from A to C...\\n'\n\t\t\tends_with:   'Disc 1 from A to C...\\n'\n\t\t\tcontains:    'Disc 7 from A to C...\\n'\n\t\t}\n\t\tres << Command{\n\t\t\tline:  '${vexe} -o - examples/hello_world.v | grep \"#define V_COMMIT_HASH\" > /dev/null'\n\t\t\tokmsg: 'V prints the generated source code to stdout with `-o -` .'\n\t\t}\n\t\tres << Command{\n\t\t\tline:  '${vexe} run examples/v_script.vsh > /dev/null'\n\t\t\tokmsg: 'V can run the .VSH script file examples/v_script.vsh'\n\t\t}\n\t\t// Note: -experimental is used here, just to suppress the warnings,\n\t\t// that are otherwise printed by the native backend,\n\t\t// until globals and hash statements *are implemented*:\n\t\t$if linux {\n\t\t\tres << Command{\n\t\t\t\tline:  '${vexe} -experimental -b native run examples/native/hello_world.v > /dev/null'\n\t\t\t\tokmsg: 'V compiles and runs examples/native/hello_world.v on the native backend for linux'\n\t\t\t}\n\t\t\tres << Command{\n\t\t\t\tline:     '${vexe} -no-builtin -experimental -b native examples/hello_world.v > /dev/null'\n\t\t\t\tokmsg:    'V compiles examples/hello_world.v on the native backend for linux with `-no-builtin` & the executable is <= ${hw_native_no_builtin_size_limit} bytes'\n\t\t\t\trmfile:   'examples/hello_world'\n\t\t\t\tafter_cb: fn () ! {\n\t\t\t\t\tfile := 'examples/hello_world'\n\t\t\t\t\tif !os.exists(file) {\n\t\t\t\t\t\treturn error('>> file ${file} does not exist')\n\t\t\t\t\t}\n\t\t\t\t\tif os.file_size(file) > hw_native_no_builtin_size_limit {\n\t\t\t\t\t\treturn error('>> file ${file} bigger than ${hw_native_no_builtin_size_limit} bytes')\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// only compilation:\n\t\tres << Command{\n\t\t\tline:   '${vexe} -os linux -experimental -b native -o hw.linux examples/hello_world.v'\n\t\t\tokmsg:  'V compiles hello_world.v on the native backend for linux'\n\t\t\trmfile: ['hw.linux', 'hw.linux.o']\n\t\t}\n\t\tres << Command{\n\t\t\tline:   '${vexe} -os macos -experimental -b native -o hw.macos examples/hello_world.v'\n\t\t\tokmsg:  'V compiles hello_world.v on the native backend for macos'\n\t\t\trmfile: ['hw.macos', 'hw.macos.o']\n\t\t}\n\t\t$if windows {\n\t\t\tres << Command{\n\t\t\t\tline:   '${vexe} -os windows -experimental -b native -o hw.exe examples/hello_world.v'\n\t\t\t\tokmsg:  'V compiles hello_world.v on the native backend for windows'\n\t\t\t\trmfile: ['hw.exe', 'hw.o']\n\t\t\t}\n\t\t}\n\t\t//\n\t\tres << Command{\n\t\t\tline:   '${vexe} -b js -o hw.js examples/hello_world.v'\n\t\t\tokmsg:  'V compiles hello_world.v on the JS backend'\n\t\t\trmfile: 'hw.js'\n\t\t}\n\t\tres << Command{\n\t\t\tline:   '${vexe} examples/2048'\n\t\t\tokmsg:  'V can compile 2048.'\n\t\t\trmfile: 'examples/2048/2048'\n\t\t}\n\t\tif _ := os.find_abs_path_of_executable('emcc') {\n\t\t\tres << Command{\n\t\t\t\tline:   '${vexe} -os wasm32_emscripten examples/2048'\n\t\t\t\tokmsg:  'V can compile 2048 with -os wasm32_emscripten, using emcc.'\n\t\t\t\trmfile: 'examples/2048/2048'\n\t\t\t}\n\t\t} else {\n\t\t\tprintln('> emcc not found, skipping `v -os wasm32_emscripten examples/2048`.')\n\t\t}\n\t\tres << Command{\n\t\t\tline:   '${vexe} -live examples/hot_reload/bounce.v'\n\t\t\tokmsg:  'V can compile the hot code reloading bounce.v example with -live'\n\t\t\trmfile: 'examples/hot_reload/bounce'\n\t\t}\n\t}\n\tres << Command{\n\t\tline:   '${vexe} -o vtmp cmd/v'\n\t\tokmsg:  'V can compile itself.'\n\t\trmfile: 'vtmp'\n\t}\n\tres << Command{\n\t\tline:   '${vexe} -o vtmp_werror -cstrict cmd/v'\n\t\tokmsg:  'V can compile itself with -cstrict.'\n\t\trmfile: 'vtmp_werror'\n\t}\n\tres << Command{\n\t\tline:   '${vexe} -o vtmp_autofree -autofree cmd/v'\n\t\tokmsg:  'V can compile itself with -autofree.'\n\t\trmfile: 'vtmp_autofree'\n\t}\n\tres << Command{\n\t\tline:   '${vexe} -o vtmp_prealloc -prealloc cmd/v'\n\t\tokmsg:  'V can compile itself with -prealloc.'\n\t\trmfile: 'vtmp_prealloc'\n\t}\n\tres << Command{\n\t\tline:   '${vexe} -o vtmp_ntransformer -new-transformer cmd/v'\n\t\tokmsg:  'V can compile itself with -new-transformer.'\n\t\trmfile: 'vtmp_ntransformer'\n\t}\n\t$if linux {\n\t\tres << Command{\n\t\t\tline:   '${vexe} -o swait vlib/v/tests/reliability/semaphore_wait.v'\n\t\t\tokmsg:  'V can compile semaphore_wait.v on Linux with GC on.'\n\t\t\trmfile: 'swait'\n\t\t}\n\t\tres << Command{\n\t\t\tline:   '${vexe} -cc gcc -keepc -freestanding -o bel vlib/os/bare/bare_example_linux.v'\n\t\t\tokmsg:  'V can compile with -freestanding on Linux with GCC.'\n\t\t\trmfile: 'bel'\n\t\t}\n\n\t\tres << Command{\n\t\t\tline:   '${vexe} -cc gcc -keepc -freestanding -o str_array vlib/strconv/bare/str_array_example.v'\n\t\t\tokmsg:  'V can compile & allocate memory with -freestanding on Linux with GCC.'\n\t\t\trmfile: 'str_array'\n\t\t}\n\t\tres << Command{\n\t\t\tline:   '${vexe} -cc gcc -keepc -freestanding -o time_now vlib/time/bare/time_now_example.v'\n\t\t\tokmsg:  'V can compile time.now() with -freestanding on Linux with GCC.'\n\t\t\trmfile: 'time_now'\n\t\t}\n\t}\n\t////////////////////////////////////////////////////////////////////////\n\t// Test compilation of a shared library (.so, .dll. .dylib) with -shared:\n\tcommon_shared_flags := '-shared -skip-unused -d no_backtrace -o library examples/dynamic_library_loader/modules/library/library.v'\n\t$if macos {\n\t\tres << Command{\n\t\t\tline:   '${vexe} ${common_shared_flags}'\n\t\t\tokmsg:  'V compiles library.v with -shared on macos'\n\t\t\trmfile: 'library.dylib'\n\t\t}\n\t}\n\t$if linux {\n\t\tres << Command{\n\t\t\tline:   '${vexe} ${common_shared_flags}'\n\t\t\tokmsg:  'V compiles library.v with -shared on linux'\n\t\t\trmfile: 'library.so'\n\t\t}\n\t}\n\t// Test cross compilation to windows with -shared:\n\t$if linux {\n\t\tif l2w_crosscc != '' {\n\t\t\tres << Command{\n\t\t\t\tline:   '${vexe} -os windows ${common_shared_flags}'\n\t\t\t\tokmsg:  'V cross compiles library.v with -shared on linux, to a windows library.dll file'\n\t\t\t\trmfile: 'library.dll'\n\t\t\t}\n\t\t} else {\n\t\t\teprintln('Testing cross compilation from linux to windows needs x86_64-w64-mingw32-gcc-win32. Skipping library.dll test.')\n\t\t}\n\t}\n\t////////////////////////////////////////////////////////////////////////\n\tres << Command{\n\t\tline:  '${vexe} ${vargs} -progress test-cleancode'\n\t\tokmsg: 'All .v files are invariant when processed with `v fmt`'\n\t}\n\tres << Command{\n\t\tline:  '${vexe} ${vargs} -progress test-fmt'\n\t\tokmsg: 'All .v files can be processed with `v fmt`. Note: the result may not always be compilable, but `v fmt` should not crash.'\n\t}\n\tres << Command{\n\t\tline:  '${vexe} ${vargs} -progress test-self'\n\t\tokmsg: 'There are no _test.v file regressions.'\n\t}\n\tres << Command{\n\t\tline:  '${vexe} ${vargs} -progress -N -W build-tools'\n\t\tokmsg: 'All tools can be compiled.'\n\t}\n\tres << Command{\n\t\tline:  '${vexe} ${vargs} -progress -N -W build-examples'\n\t\tokmsg: 'All examples can be compiled.'\n\t}\n\tres << Command{\n\t\tline:  '${vexe} check-md -hide-warnings .'\n\t\tlabel: 'Check ```v ``` code examples and formatting of .MD files...'\n\t\tokmsg: 'All .md files look good.'\n\t}\n\tres << Command{\n\t\tline:  '${vexe} install nedpals.args'\n\t\tokmsg: '`v install` works.'\n\t}\n\tres << Command{\n\t\tokmsg:       'Running net.http with -d trace_http_request works.'\n\t\tline:        '${vexe} -d trace_http_request -e \\'import net.http; x := http.fetch(url: \"https://vpm.url4e.com/some/unknown/url\")!; println(x.status_code)\\''\n\t\truncmd:      .execute\n\t\tstarts_with: '> GET /some/unknown/url HTTP/1.1'\n\t\tcontains:    'User-Agent: v.http'\n\t\tends_with:   '404\\n'\n\t}\n\tres << Command{\n\t\tokmsg:       'Running net.http with -d trace_http_response works.'\n\t\tline:        '${vexe} -d trace_http_response -e \\'import net.http; x := http.fetch(url: \"https://vpm.url4e.com/some/unknown/url\")!; println(x.status_code)\\''\n\t\truncmd:      .execute\n\t\tstarts_with: '< HTTP/1.1 404 Not Found'\n\t\tcontains:    'Server: nginx'\n\t\tends_with:   '404\\n'\n\t}\n\tres << Command{\n\t\tline:   '${vexe} -usecache -cg examples/hello_world.v'\n\t\tokmsg:  '`v -usecache -cg` works.'\n\t\trmfile: 'examples/hello_world'\n\t}\n\t// Note: test that a program that depends on thirdparty libraries with its\n\t// own #flags (tetris depends on gg, which uses sokol) can be compiled\n\t// with -usecache:\n\tres << Command{\n\t\tline:   '${vexe} -usecache examples/tetris/tetris.v'\n\t\tokmsg:  '`v -usecache` works.'\n\t\trmfile: 'examples/tetris/tetris'\n\t}\n\t$if macos || linux {\n\t\tres << Command{\n\t\t\tline:   '${vexe} -o v.c cmd/v && cc -Werror -std=c99 v.c -lpthread -lm && rm -rf a.out'\n\t\t\tlabel:  'v.c should be buildable with no warnings...'\n\t\t\tokmsg:  'v.c can be compiled without warnings. This is good :)'\n\t\t\trmfile: 'v.c'\n\t\t}\n\t}\n\t$if linux || macos {\n\t\tres << Command{\n\t\t\tline:   '${vexe} -gc none -no-retry-compilation -cc tcc -d use_openssl examples/veb/todo/main.v'\n\t\t\tokmsg:  'A simple veb app, compiles with `-gc none -no-retry-compilation -cc tcc -d use_openssl` on macos and linux'\n\t\t\trmfile: 'examples/veb/todo/main'\n\t\t}\n\t\tres << Command{\n\t\t\tline:   '${vexe} -d trace_before_request examples/veb/veb_example.v'\n\t\t\tokmsg:  'examples/veb/veb_example.v compiles with `-d trace_before_request` on macos and linux'\n\t\t\trmfile: 'examples/veb/veb_example'\n\t\t}\n\t}\n\t$if linux {\n\t\tres << Command{\n\t\t\tline:     '${vexe} vlib/v/tests/bench/bench_stbi_load.v && prlimit -v10485760 vlib/v/tests/bench/bench_stbi_load'\n\t\t\tokmsg:    'STBI load does not leak with GC on, when loading images multiple times (use < 10MB)'\n\t\t\truncmd:   .execute\n\t\t\tcontains: 'logo.png 1000 times.'\n\t\t\trmfile:   'vlib/v/tests/bench/bench_stbi_load'\n\t\t}\n\t}\n\t$if !windows {\n\t\tres << Command{\n\t\t\tline:   '${vexe} -raw-vsh-tmp-prefix tmp vlib/v/tests/script_with_no_extension'\n\t\t\tokmsg:  'V can crun a script, that lacks a .vsh extension'\n\t\t\truncmd: .execute\n\t\t\texpect: 'Test\\n'\n\t\t\trmfile: 'vlib/v/tests/tmp.script_with_no_extension'\n\t\t}\n\n\t\tres << Command{\n\t\t\tline:   '${vexe} -raw-vsh-tmp-prefix tmp run vlib/v/tests/script_with_no_extension'\n\t\t\tokmsg:  'V can run a script, that lacks a .vsh extension'\n\t\t\truncmd: .execute\n\t\t\texpect: 'Test\\n'\n\t\t}\n\t}\n\treturn res\n}\n\nfn (mut cmd Command) run() ? {\n\t// Changing the current directory is needed for some of the compiler tests,\n\t// vlib/v/tests/local_test.v and vlib/v/tests/repl/repl_test.v\n\tos.chdir(vroot) or {}\n\tif cmd.label != '' {\n\t\tprintln(term.header_left(cmd.label, '*'))\n\t}\n\tif cmd.before_cb != unsafe { nil } {\n\t\tcmd.before_cb() or {\n\t\t\tcmd.ecode = -1\n\t\t\tcmd.errmsg = '> before_cb callback for \"${cmd.line}\" ${term.failed('FAILED')}\\n${err}'\n\t\t\tprintln(cmd.errmsg)\n\t\t\treturn\n\t\t}\n\t}\n\tsw := time.new_stopwatch()\n\tif cmd.runcmd == .system {\n\t\tcmd.ecode = os.system(cmd.line)\n\t\tcmd.output = ''\n\t}\n\tif cmd.runcmd == .execute {\n\t\tres := os.execute(cmd.line)\n\t\tcmd.ecode = res.exit_code\n\t\tcmd.output = res.output\n\t}\n\tspent := sw.elapsed().milliseconds()\n\tif cmd.after_cb != unsafe { nil } {\n\t\tcmd.after_cb() or {\n\t\t\tcmd.ecode = -1\n\t\t\tcmd.errmsg = '> after_cb callback for \"${cmd.line}\" ${term.failed('FAILED')}\\n${err}'\n\t\t\tprintln(cmd.errmsg)\n\t\t\treturn\n\t\t}\n\t}\n\n\tmut is_failed := false\n\tmut is_failed_expected := false\n\tmut is_failed_starts_with := false\n\tmut is_failed_ends_with := false\n\tmut is_failed_contains := false\n\tif cmd.ecode != 0 {\n\t\tis_failed = true\n\t}\n\tif cmd.expect != none {\n\t\tif cmd.output != cmd.expect {\n\t\t\tis_failed = true\n\t\t\tis_failed_expected = true\n\t\t}\n\t}\n\tif cmd.starts_with != none {\n\t\tif !cmd.output.starts_with(cmd.starts_with) {\n\t\t\tis_failed = true\n\t\t\tis_failed_starts_with = true\n\t\t}\n\t}\n\tif cmd.ends_with != none {\n\t\tif !cmd.output.ends_with(cmd.ends_with) {\n\t\t\tis_failed = true\n\t\t\tis_failed_ends_with = true\n\t\t}\n\t}\n\tif cmd.contains != none {\n\t\tif !cmd.output.contains(cmd.contains) {\n\t\t\tis_failed = true\n\t\t\tis_failed_contains = true\n\t\t}\n\t}\n\n\trun_label := if is_failed { term.failed('FAILED') } else { term_highlight('OK') }\n\tprintln('> Running: \"${cmd.line}\" took: ${spent} ms ... ${run_label}')\n\n\tif is_failed && is_failed_expected {\n\t\teprintln('> expected:\\n${cmd.expect}')\n\t\teprintln('>   output:\\n${cmd.output}')\n\t}\n\tif is_failed && is_failed_starts_with {\n\t\teprintln('> expected to start with:\\n${cmd.starts_with?}')\n\t\teprintln('>                 output:\\n${cmd.output#[..cmd.starts_with?.len]}')\n\t}\n\tif is_failed && is_failed_ends_with {\n\t\teprintln('> expected to end with:\\n${cmd.ends_with?}')\n\t\teprintln('>               output:\\n${cmd.output#[-cmd.starts_with?.len..]}')\n\t}\n\tif is_failed && is_failed_contains {\n\t\teprintln('> expected to contain:\\n${cmd.contains?}')\n\t\teprintln('>              output:\\n${cmd.output}')\n\t}\n\tif vtest_nocleanup {\n\t\treturn\n\t}\n\tif cmd.rmfile != none {\n\t\tmut file_existed := rm_existing(cmd.rmfile)\n\t\tif !file_existed {\n\t\t\teprintln('Expected file did not exist: ${cmd.rmfile}')\n\t\t\tcmd.ecode = 999\n\t\t}\n\t}\n}\n\nfn rm_existing(paths OneOrManyStrings) bool {\n\tmatch paths {\n\t\tstring {\n\t\t\treturn rm_existing_file(paths)\n\t\t}\n\t\t[]string {\n\t\t\tmut existing := false\n\t\t\tfor path in paths {\n\t\t\t\texisting ||= rm_existing_file(path)\n\t\t\t}\n\t\t\treturn existing\n\t\t}\n\t}\n\treturn false\n}\n\n// try to remove a file, return if it existed before the removal attempt\nfn rm_existing_file(path string) bool {\n\tmut existed := os.exists(path)\n\tos.rm(path) or {}\n\n\twin_path := path + '.exe'\n\tif os.exists(win_path) {\n\t\texisted = true\n\t\tos.rm(win_path) or {}\n\t}\n\n\treturn existed\n}\n\nfn term_highlight(s string) string {\n\treturn term.colorize(term.yellow, term.colorize(term.bold, s))\n}\n"
  },
  {
    "path": "cmd/tools/vtest-cleancode.v",
    "content": "module main\n\nimport os\nimport testing\nimport v.util\nimport arrays\n\nconst vet_known_failing = [\n\t'do_not_delete_this',\n]\n\nconst vet_known_failing_windows = [\n\t'do_not_delete_this',\n\t'vlib/v/gen/js/tests/testdata/byte_is_space.v',\n\t'vlib/v/gen/js/tests/testdata/compare_ints.v',\n\t'vlib/v/gen/js/tests/testdata/hw.v',\n\t'vlib/v/gen/js/tests/testdata/string_methods.v',\n\t'vlib/v/slow_tests/inout/vscript_using_generics_in_os.vsh',\n\t'vlib/v/tests/project_with_modules_having_submodules/bin/main.vsh',\n\t'vlib/v/slow_tests/valgrind/simple_interpolation_script_mode.v',\n\t'vlib/v/slow_tests/valgrind/simple_interpolation_script_mode_more_scopes.v',\n]\n\nconst vet_folders = [\n\t'vlib/v',\n\t'vlib/x/json2',\n\t'vlib/x/ttf',\n\t'cmd/v',\n\t'cmd/tools',\n\t'examples/2048',\n\t'examples/tetris',\n\t'examples/term.ui',\n]\n\nconst verify_known_failing_exceptions = []string{}\n\nconst vfmt_verify_list = [\n\t'cmd/',\n\t'examples/',\n\t'tutorials/',\n\t'vlib/',\n]\n\nconst vfmt_known_failing_exceptions = arrays.merge(verify_known_failing_exceptions, []string{})\n\nconst vexe = os.getenv('VEXE')\n\nconst vroot = os.dir(vexe)\n\nconst is_fix = '-fix' in os.args\n\nfn main() {\n\targs_string := os.args[1..].join(' ')\n\tpass_args := args_string.all_before('test-cleancode')\n\tv_test_vetting(pass_args)!\n}\n\nfn tsession(vargs string, tool_source string, tool_cmd string, tool_args string, flist []string, slist []string) testing.TestSession {\n\tos.chdir(vroot) or {}\n\ttitle_message := 'running ${tool_cmd} over most .v files'\n\ttesting.eheader(title_message)\n\tmut test_session := testing.new_test_session('${vargs} ${tool_args}', false)\n\ttest_session.files << flist\n\ttest_session.skip_files << slist\n\tutil.prepare_tool_when_needed(tool_source)\n\t// note that util.prepare_tool_when_needed will put its temporary files\n\t// in the VTMP from the test session too, so they will be cleaned up\n\t// at the end\n\ttest_session.test()\n\teprintln(test_session.benchmark.total_message(title_message))\n\treturn test_session\n}\n\nfn v_test_vetting(vargs string) ! {\n\texpanded_vet_list := util.find_all_v_files(vet_folders)!\n\tmut vet_known_exceptions := vet_known_failing.clone()\n\tif os.user_os() == 'windows' {\n\t\tvet_known_exceptions << vet_known_failing_windows\n\t}\n\tvet_session := tsession(vargs, 'vvet', '${os.quoted_path(vexe)} vet', 'vet', expanded_vet_list,\n\t\tvet_known_exceptions)\n\n\tfmt_cmd, fmt_args := if is_fix {\n\t\t'${os.quoted_path(vexe)} fmt -w', 'fmt -w'\n\t} else {\n\t\t'${os.quoted_path(vexe)} fmt -inprocess -verify', 'fmt -inprocess -verify'\n\t}\n\tvfmt_list := util.find_all_v_files(vfmt_verify_list) or { return }\n\texceptions := util.find_all_v_files(vfmt_known_failing_exceptions) or { return }\n\tverify_session := tsession(vargs, 'vfmt.v', fmt_cmd, fmt_args, vfmt_list, exceptions)\n\n\tif vet_session.benchmark.nfail > 0 || verify_session.benchmark.nfail > 0 {\n\t\teprintln('\\n')\n\t\tif vet_session.benchmark.nfail > 0 {\n\t\t\teprintln('WARNING: `v vet` failed ${vet_session.benchmark.nfail} times.')\n\t\t}\n\t\tif verify_session.benchmark.nfail > 0 {\n\t\t\teprintln('WARNING: `v fmt -verify` failed ${verify_session.benchmark.nfail} times.')\n\t\t}\n\t\texit(1)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vtest-fmt.v",
    "content": "module main\n\nimport os\nimport testing\nimport v.util\n\nconst known_failing_exceptions = []string{}\n\nfn main() {\n\targs_string := os.args[1..].join(' ')\n\tv_test_formatting(args_string.all_before('test-fmt'))\n}\n\nfn v_test_formatting(vargs string) {\n\tall_v_files := v_files()\n\tutil.prepare_tool_when_needed('vfmt.v')\n\ttesting.eheader('Run \"v fmt\" over all .v files')\n\tmut vfmt_test_session := testing.new_test_session('${vargs} fmt -worker', false)\n\tvfmt_test_session.files << all_v_files\n\tvfmt_test_session.skip_files << known_failing_exceptions\n\tvfmt_test_session.test()\n\teprintln(vfmt_test_session.benchmark.total_message('running vfmt over V files'))\n\tif vfmt_test_session.benchmark.nfail > 0 {\n\t\teprintln('\\nWARNING: v fmt failed ${vfmt_test_session.benchmark.nfail} times.\\n')\n\t\texit(1)\n\t}\n}\n\nfn v_files() []string {\n\tmut files_that_can_be_formatted := []string{}\n\tall_test_files := os.walk_ext('.', '.v')\n\tfor tfile in all_test_files {\n\t\tif tfile.starts_with('./vlib/v/cgen/tests') {\n\t\t\tcontinue\n\t\t}\n\t\tfiles_that_can_be_formatted << tfile\n\t}\n\treturn files_that_can_be_formatted\n}\n"
  },
  {
    "path": "cmd/tools/vtest-parser.v",
    "content": "import os\nimport flag\nimport term\nimport time\nimport v.parser\nimport v.ast\nimport v.pref\n\nconst vexe = os.real_path(os.getenv_opt('VEXE') or { @VEXE })\nconst vroot = os.dir(vexe)\nconst support_color = term.can_show_color_on_stderr() && term.can_show_color_on_stdout()\nconst ecode_timeout = 101\nconst ecode_memout = 102\nconst ecode_details = {\n\t-1:  'worker executable not found'\n\t101: 'too slow'\n\t102: 'too memory hungry'\n}\n\nstruct Context {\nmut:\n\tis_help    bool\n\tis_worker  bool\n\tis_verbose bool\n\tis_silent  bool // do not print any status/progress during processing, just failures.\n\tis_linear  bool // print linear progress log, without trying to do term cursor up + \\r msg. Easier to use in a CI job\n\tshow_src   bool // show the partial source, that cause the parser to panic/fault, when it happens.\n\ttimeout_ms int\n\tmyself     string   // path to this executable, so the supervisor can launch worker processes\n\tall_paths  []string // all files given to the supervisor process\n\tpath       string   // the current path, given to a worker process\n\tcut_index  int      // the cut position in the source from context.path\n\tmax_index  int      // the maximum index (equivalent to the file content length)\n\t// parser context in the worker processes:\n\ttable      ast.Table\n\tpref       &pref.Preferences = unsafe { nil }\n\tperiod_ms  int  // print periodic progress\n\tstop_print bool // stop printing the periodic progress\n}\n\nfn main() {\n\tmut context := process_cli_args()\n\tif context.is_worker {\n\t\tpid := os.getpid()\n\t\tcontext.log('> worker ${pid:5} starts parsing at cut_index: ${context.cut_index:5} | ${context.path}')\n\t\t// A worker's process job is to try to parse a single given file in context.path.\n\t\t// It can crash/panic freely.\n\t\tcontext.table = ast.new_table()\n\t\tcontext.pref = &pref.Preferences{\n\t\t\toutput_mode: .silent\n\t\t}\n\t\tmut source := os.read_file(context.path)!\n\t\tsource = source[..context.cut_index]\n\n\t\tspawn fn (ms int) {\n\t\t\ttime.sleep(ms * time.millisecond)\n\t\t\texit(ecode_timeout)\n\t\t}(context.timeout_ms)\n\t\t_ := parser.parse_text(source, context.path, mut context.table, .skip_comments,\n\t\t\tcontext.pref)\n\t\tcontext.log('> worker ${pid:5} finished parsing ${context.path}')\n\t\texit(0)\n\t} else {\n\t\t// The process supervisor should NOT crash/panic, unlike the workers.\n\t\t// Its job, is to:\n\t\t// 1) start workers\n\t\t// 2) accumulate results\n\t\t// 3) produce a summary at the end\n\t\tcontext.expand_all_paths()\n\t\tmut fails := 0\n\t\tmut panics := 0\n\t\tsw := time.new_stopwatch()\n\t\tfor path in context.all_paths {\n\t\t\tfilesw := time.new_stopwatch()\n\t\t\tcontext.start_printing()\n\t\t\tnew_fails, new_panics := context.process_whole_file_in_worker(path)\n\t\t\tfails += new_fails\n\t\t\tpanics += new_panics\n\t\t\tcontext.stop_printing()\n\t\t\tcontext.info('File: ${path:-30} | new_fails: ${new_fails:5} | new_panics: ${new_panics:5} | Elapsed time: ${filesw.elapsed().milliseconds()}ms')\n\t\t}\n\t\tnon_panics := fails - panics\n\t\tcontext.info('Total files processed: ${context.all_paths.len:5} | Errors found: ${fails:5} | Panics: ${panics:5} | Non panics: ${non_panics:5} | Elapsed time: ${sw.elapsed().milliseconds()}ms')\n\t\tif fails > 0 {\n\t\t\texit(1)\n\t\t}\n\t\texit(0)\n\t}\n}\n\nfn process_cli_args() &Context {\n\tmut context := &Context{\n\t\tpref: pref.new_preferences()\n\t}\n\tcontext.myself = os.executable()\n\tmut fp := flag.new_flag_parser(os.args_after('test-parser'))\n\tfp.application(os.file_name(context.myself))\n\tfp.version('0.0.1')\n\tfp.description('Test the V parser, by parsing each .v file in each PATH,\\n' +\n\t\t'as if it was typed character by character by the user.\\n' +\n\t\t'A PATH can be either a folder, or a specific .v file.\\n' +\n\t\t'Note: you *have to quote* the PATH, if it contains spaces/punctuation.')\n\tfp.arguments_description('PATH1 PATH2 ...')\n\tfp.skip_executable()\n\tcontext.is_help = fp.bool('help', `h`, false, 'Show help/usage screen.')\n\tcontext.is_verbose = fp.bool('verbose', `v`, false, 'Be more verbose.')\n\tcontext.is_silent = fp.bool('silent', `S`, false, 'Do not print progress at all.')\n\tcontext.is_linear = fp.bool('linear', `L`, false, 'Print linear progress log. Suitable for CI.')\n\tcontext.show_src = fp.bool('show_source', `E`, false, 'Print the partial source code that caused a fault/panic in the parser.')\n\tcontext.period_ms = fp.int('progress_ms', `s`, 500, 'print a status report periodically, the period is given in milliseconds.')\n\tcontext.is_worker = fp.bool('worker', `w`, false, 'worker specific flag - is this a worker process, that can crash/panic.')\n\tcontext.cut_index = fp.int('cut_index', `c`, 1, 'worker specific flag - cut index in the source file, everything before that will be parsed, the rest - ignored.')\n\tcontext.timeout_ms = fp.int('timeout_ms', `t`, 250, 'worker specific flag - timeout in ms; a worker taking longer, will self terminate.')\n\tcontext.path = fp.string('path', `p`, '', 'worker specific flag - path to the current source file, which will be parsed.')\n\n\tif context.is_help {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\tcontext.all_paths = fp.finalize() or {\n\t\tcontext.error(err.msg())\n\t\texit(1)\n\t}\n\tif !context.is_worker && context.all_paths.len == 0 {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\treturn context\n}\n\n// ////////////////\nfn bold(msg string) string {\n\tif !support_color {\n\t\treturn msg\n\t}\n\treturn term.bold(msg)\n}\n\nfn red(msg string) string {\n\tif !support_color {\n\t\treturn msg\n\t}\n\treturn term.red(msg)\n}\n\nfn yellow(msg string) string {\n\tif !support_color {\n\t\treturn msg\n\t}\n\treturn term.yellow(msg)\n}\n\nfn (mut context Context) info(msg string) {\n\tprintln(msg)\n}\n\nfn (mut context Context) log(msg string) {\n\tif context.is_verbose {\n\t\tlabel := yellow('info')\n\t\tts := time.now().format_ss_micro()\n\t\teprintln('${label}: ${ts} | ${msg}')\n\t}\n}\n\nfn (mut context Context) error(msg string) {\n\tlabel := red('error')\n\teprintln('${label}: ${msg}')\n}\n\nfn (mut context Context) expand_all_paths() {\n\tcontext.log('> context.all_paths before: ${context.all_paths}')\n\tmut files := []string{}\n\tfor path in context.all_paths {\n\t\tif os.is_dir(path) {\n\t\t\tfiles << os.walk_ext(path, '.v')\n\t\t\tfiles << os.walk_ext(path, '.vsh')\n\t\t\tcontinue\n\t\t}\n\t\tif !path.ends_with('.v') && !path.ends_with('.vv') && !path.ends_with('.vsh') {\n\t\t\tcontext.error('`v test-parser` can only be used on .v/.vv/.vsh files.\\nOffending file: \"${path}\".')\n\t\t\tcontinue\n\t\t}\n\t\tif !os.exists(path) {\n\t\t\tcontext.error('\"${path}\" does not exist.')\n\t\t\tcontinue\n\t\t}\n\t\tfiles << path\n\t}\n\tcontext.all_paths = files\n\tcontext.log('> context.all_paths after: ${context.all_paths}')\n}\n\nfn (mut context Context) process_whole_file_in_worker(path string) (int, int) {\n\tcontext.path = path // needed for the progress bar\n\tcontext.log('> context.process_whole_file_in_worker path: ${path}')\n\tif !(os.is_file(path) && os.is_readable(path)) {\n\t\tcontext.error('${path} is not readable')\n\t\treturn 1, 0\n\t}\n\tsource := os.read_file(path) or { '' }\n\tif source == '' {\n\t\t// an empty file is a valid .v file\n\t\treturn 0, 0\n\t}\n\tlen := source.len - 1\n\tmut fails := 0\n\tmut panics := 0\n\tcontext.max_index = len\n\tfor i in 0 .. len {\n\t\tverbosity := if context.is_verbose { '-v' } else { '' }\n\t\tcontext.cut_index = i // needed for the progress bar\n\t\tcmd := '${os.quoted_path(context.myself)} ${verbosity} --worker --timeout_ms ${context.timeout_ms:5} --cut_index ${i:5} --path ${os.quoted_path(path)} '\n\t\tcontext.log(cmd)\n\t\tmut res := os.execute(cmd)\n\t\tcontext.log('worker exit_code: ${res.exit_code} | worker output:\\n${res.output}')\n\t\tif res.exit_code != 0 {\n\t\t\tfails++\n\t\t\tmut is_panic := false\n\t\t\tif res.output.contains('V panic:') {\n\t\t\t\tis_panic = true\n\t\t\t\tpanics++\n\t\t\t}\n\t\t\tpart := source[..i]\n\t\t\tline := part.count('\\n') + 1\n\t\t\tlast_line := part.all_after_last('\\n')\n\t\t\tcol := last_line.len\n\t\t\terr := if is_panic {\n\t\t\t\tred('parser failure: panic')\n\t\t\t} else {\n\t\t\t\tred('parser failure: crash, ${ecode_details[res.exit_code]}')\n\t\t\t}\n\t\t\tpath_to_line := bold('${path}:${line}:${col}:')\n\t\t\terr_line := last_line.trim_left('\\t')\n\t\t\tprintln('${path_to_line} ${err}')\n\t\t\tprintln('\\t${line} | ${err_line}')\n\t\t\tprintln('')\n\t\t\teprintln(res.output)\n\t\t\teprintln('>>> failed command: ${cmd}')\n\t\t\tif context.show_src {\n\t\t\t\teprintln('>>> source so far:')\n\t\t\t\teprintln('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')\n\t\t\t\tpartial_source := source[..context.cut_index]\n\t\t\t\teprintln(partial_source)\n\t\t\t\teprintln('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')\n\t\t\t}\n\t\t}\n\t}\n\treturn fails, panics\n}\n\nfn (mut context Context) start_printing() {\n\tcontext.stop_print = false\n\tif !context.is_linear && !context.is_silent {\n\t\tprintln('\\n')\n\t}\n\tspawn context.print_periodic_status()\n}\n\nfn (mut context Context) stop_printing() {\n\tcontext.stop_print = true\n\ttime.sleep(time.millisecond * context.period_ms / 5)\n}\n\nfn (mut context Context) print_status() {\n\tif context.is_silent {\n\t\treturn\n\t}\n\tif context.cut_index == 1 && context.max_index == 0 {\n\t\treturn\n\t}\n\tmsg := '>   ${context.path:-30} | index: ${context.cut_index:5}/${context.max_index - 1:5}'\n\tif context.is_linear {\n\t\teprintln(msg)\n\t\treturn\n\t}\n\tterm.cursor_up(1)\n\teprint('\\r  ${msg}\\n')\n}\n\nfn (mut context Context) print_periodic_status() {\n\tcontext.print_status()\n\tmut printed_at_least_once := false\n\tfor !context.stop_print {\n\t\tcontext.print_status()\n\t\tfor i := 0; i < 10 && !context.stop_print; i++ {\n\t\t\ttime.sleep(time.millisecond * context.period_ms / 10)\n\t\t\tif context.cut_index > 50 && !printed_at_least_once {\n\t\t\t\tcontext.print_status()\n\t\t\t\tprinted_at_least_once = true\n\t\t\t}\n\t\t}\n\t}\n\tcontext.print_status()\n}\n"
  },
  {
    "path": "cmd/tools/vtest-self.v",
    "content": "module main\n\nimport os\nimport testing\n\nstruct Config {\n\trun_just_essential     bool   = '${os.getenv('VTEST_JUST_ESSENTIAL')}${os.getenv('VTEST_SANDBOXED_PACKAGING')}' != ''\n\tis_musl_ci             bool   = os.getenv('V_CI_MUSL') != ''\n\tis_ubuntu_musl_ci      bool   = os.getenv('V_CI_UBUNTU_MUSL') != ''\n\tis_sandboxed_packaging bool   = os.getenv('VTEST_SANDBOXED_PACKAGING') != ''\n\tgithub_job             string = os.getenv('GITHUB_JOB')\nmut:\n\ttest_dirs         []string = ['cmd', 'vlib']\n\tis_asan_compiler  bool\n\tis_msan_compiler  bool\n\tis_ubsan_compiler bool\n\t// Options relating to the v command itself (passed in the prefix) `v [...args] test-self`.\n\twerror             bool\n\tsanitize_memory    bool\n\tsanitize_address   bool\n\tsanitize_undefined bool\n}\n\nconst vroot = os.dir(os.real_path(os.getenv_opt('VEXE') or { @VEXE }))\n\nconst essential_list = [\n\t'cmd/tools/vvet/vet_test.v',\n\t'cmd/tools/vdoc/document/doc_test.v',\n\t'vlib/arrays/arrays_test.v',\n\t'vlib/bitfield/bitfield_test.v',\n\t//\n\t'vlib/builtin/int_test.v',\n\t'vlib/builtin/array_test.v',\n\t'vlib/builtin/float_test.v',\n\t'vlib/builtin/byte_test.v',\n\t'vlib/builtin/rune_test.v',\n\t'vlib/builtin/builtin_test.c.v',\n\t'vlib/builtin/map_of_floats_test.v',\n\t'vlib/builtin/string_int_test.v',\n\t'vlib/builtin/utf8_test.v',\n\t'vlib/builtin/map_test.v',\n\t'vlib/builtin/string_test.v',\n\t'vlib/builtin/sorting_test.v',\n\t'vlib/builtin/gated_array_string_test.v',\n\t'vlib/builtin/isnil_test.v',\n\t'vlib/builtin/string_match_glob_test.v',\n\t'vlib/builtin/string_strip_margin_test.v',\n\t//\n\t'vlib/cli/command_test.v',\n\t'vlib/crypto/md5/md5_test.v',\n\t'vlib/dl/dl_test.v',\n\t'vlib/encoding/base64/base64_test.v',\n\t'vlib/encoding/utf8/validate/encoding_utf8_test.v',\n\t'vlib/encoding/utf8/utf8_util_test.v',\n\t'vlib/flag/flag_test.v',\n\t'vlib/json/tests/json_decode_test.v',\n\t'vlib/math/math_test.v',\n\t'vlib/net/tcp_test.v',\n\t'vlib/net/http/http_test.v',\n\t'vlib/net/http/server_test.v',\n\t'vlib/net/http/request_test.v',\n\t'vlib/io/io_test.v',\n\t'vlib/io/os_file_reader_test.v',\n\t'vlib/os/process_test.v',\n\t'vlib/os/file_test.v',\n\t'vlib/os/notify/notify_test.c.v',\n\t'vlib/os/filepath_test.v',\n\t'vlib/os/environment_test.v',\n\t'vlib/os/glob_test.v',\n\t'vlib/os/os_test.c.v',\n\t'vlib/rand/random_numbers_test.v',\n\t'vlib/rand/wyrand/wyrand_test.v',\n\t'vlib/runtime/runtime_test.v',\n\t'vlib/semver/semver_test.v',\n\t'vlib/sync/stdatomic/atomic_test.v',\n\t'vlib/sync/thread_test.v',\n\t'vlib/sync/waitgroup_test.v',\n\t'vlib/sync/pool/pool_test.v',\n\t'vlib/strings/builder_test.v',\n\t'vlib/strconv/atof_test.c.v',\n\t'vlib/strconv/atoi_test.v',\n\t'vlib/strconv/f32_f64_to_string_test.v',\n\t'vlib/strconv/format_test.v',\n\t'vlib/strconv/number_to_base_test.v',\n\t'vlib/time/time_test.v',\n\t'vlib/toml/tests/toml_test.v',\n\t'vlib/v/compiler_errors_test.v',\n\t'vlib/v/eval/interpret_test.v',\n\t'vlib/v/fmt/fmt_keep_test.v',\n\t'vlib/v/fmt/fmt_test.v',\n\t'vlib/v/gen/c/coutput_test.v',\n\t'vlib/v/gen/js/program_test.v',\n\t'vlib/v/gen/native/macho_test.v',\n\t'vlib/v/gen/native/tests/native_test.v',\n\t'vlib/v/pkgconfig/pkgconfig_test.v',\n\t'vlib/v/slow_tests/inout/compiler_test.v',\n\t'vlib/x/json2/tests/json2_test.v',\n]\nconst skip_with_fsanitize_memory = [\n\t'do_not_remove',\n\t'cmd/tools/vpm/dependency_test.v', // known flaky, for fsanitize_memory, due to using mbedtls\n\t'cmd/tools/vpm/install_test.v', // known flaky, for fsanitize_memory, due to using mbedtls\n\t'cmd/tools/vpm/install_version_input_test.v', // known flaky, for fsanitize_memory, due to using mbedtls\n\t'cmd/tools/vpm/install_version_test.v', // known flaky, for fsanitize_memory, due to using mbedtls\n\t'cmd/tools/vpm/update_test.v', // known flaky, for fsanitize_memory, due to using mbedtls\n\t'vlib/net/tcp_simple_client_server_test.v',\n\t'vlib/net/http/cookie_test.v',\n\t'vlib/net/http/http_test.v',\n\t'vlib/net/http/status_test.v',\n\t'vlib/net/http/header_test.v',\n\t'vlib/net/http/server_test.v',\n\t'vlib/net/udp_test.v',\n\t'vlib/net/tcp_test.v',\n\t'vlib/orm/orm_test.v',\n\t'vlib/orm/orm_sql_or_blocks_test.v',\n\t'vlib/orm/orm_create_and_drop_test.v',\n\t'vlib/orm/orm_insert_test.v',\n\t'vlib/orm/orm_insert_reserved_name_test.v',\n\t'vlib/orm/orm_sum_type_insert_test.v',\n\t'vlib/orm/orm_fn_calls_test.v',\n\t'vlib/orm/orm_last_id_test.v',\n\t'vlib/orm/orm_string_interpolation_in_where_test.v',\n\t'vlib/orm/orm_interface_test.v',\n\t'vlib/orm/orm_mut_db_test.v',\n\t'vlib/orm/orm_null_test.v',\n\t'vlib/orm/orm_result_test.v',\n\t'vlib/orm/orm_custom_operators_test.v',\n\t'vlib/orm/orm_fk_test.v',\n\t'vlib/orm/orm_nested_struct_test.v',\n\t'vlib/orm/orm_references_test.v',\n\t'vlib/orm/orm_option_array_test.v',\n\t'vlib/orm/orm_option_time_test.v',\n\t'vlib/orm/orm_order_by_custom_field_test.v',\n\t'vlib/orm/orm_serial_attribute_test.v',\n\t'vlib/orm/orm_option_subselect_test.v',\n\t'vlib/orm/orm_func_test.v',\n\t'vlib/db/sqlite/sqlite_test.v',\n\t'vlib/db/sqlite/sqlite_orm_test.v',\n\t'vlib/db/sqlite/sqlite_comptime_field_test.v',\n\t'vlib/db/sqlite/parent_child_test.v',\n\t'vlib/db/sqlite/sqlite_vfs_lowlevel_test.v',\n\t'vlib/db/sqlite/sqlite_f32_test.v',\n\t'vlib/v/tests/orm_enum_test.v',\n\t'vlib/v/tests/orm_sub_struct_test.v',\n\t'vlib/v/tests/orm_sub_array_struct_test.v',\n\t'vlib/v/tests/orm_joined_tables_select_test.v',\n\t'vlib/v/tests/sql_statement_inside_fn_call_test.v',\n\t'vlib/v/tests/orm_stmt_wrong_return_checking_test.v',\n\t'vlib/v/tests/orm_table_name_test.v',\n\t'vlib/v/tests/orm_array_field_test.v',\n\t'vlib/v/tests/orm_handle_error_for_select_from_not_created_table_test.v',\n\t'vlib/v/tests/orm_create_several_tables_test.v',\n\t'vlib/v/tests/orm_update_test.v',\n\t'vlib/v/tests/orm_or_test.v',\n\t'vlib/vweb/tests/vweb_test.v',\n\t'vlib/vweb/csrf/csrf_test.v',\n\t'vlib/net/http/request_test.v',\n\t'vlib/net/http/response_test.v',\n\t'vlib/vweb/route_test.v',\n\t'vlib/net/websocket/websocket_test.v',\n\t'vlib/net/smtp/smtp_test.v',\n\t'vlib/v/tests/websocket_logger_interface_should_compile_test.v',\n\t'vlib/v/tests/fns/fn_literal_type_test.v',\n\t'vlib/x/sessions/tests/db_store_test.v',\n]\nconst skip_with_fsanitize_address = [\n\t'do_not_remove',\n\t'vlib/net/websocket/websocket_test.v',\n\t'vlib/orm/orm_create_and_drop_test.v',\n\t'vlib/orm/orm_insert_test.v',\n\t'vlib/orm/orm_insert_reserved_name_test.v',\n\t'vlib/orm/orm_sum_type_insert_test.v',\n\t'vlib/orm/orm_references_test.v',\n\t'vlib/v/tests/websocket_logger_interface_should_compile_test.v',\n\t'vlib/v/tests/orm_enum_test.v',\n\t'vlib/v/tests/orm_sub_array_struct_test.v',\n\t'vlib/v/tests/orm_handle_error_for_select_from_not_created_table_test.v',\n\t'vlib/v/tests/orm_create_several_tables_test.v',\n\t'vlib/v/tests/orm_update_test.v',\n\t'vlib/v/tests/orm_or_test.v',\n]\nconst skip_with_fsanitize_undefined = [\n\t'do_not_remove',\n\t'vlib/orm/orm_create_and_drop_test.v',\n\t'vlib/orm/orm_insert_test.v',\n\t'vlib/orm/orm_insert_reserved_name_test.v',\n\t'vlib/orm/orm_sum_type_insert_test.v',\n\t'vlib/orm/orm_references_test.v',\n\t'vlib/v/tests/orm_enum_test.v',\n\t'vlib/v/tests/orm_sub_array_struct_test.v',\n\t'vlib/v/tests/orm_handle_error_for_select_from_not_created_table_test.v',\n\t'vlib/v/tests/orm_create_several_tables_test.v',\n\t'vlib/v/tests/orm_update_test.v',\n\t'vlib/v/tests/orm_or_test.v',\n\t'vlib/v/tests/project_with_cpp_code/compiling_cpp_files_with_a_cplusplus_compiler_test.c.v', // fails compilation with: undefined reference to vtable for __cxxabiv1::__function_type_info'\n]\nconst skip_on_ubuntu_musl = [\n\t'do_not_remove',\n\t'vlib/arrays/parallel/parallel_test.v',\n\t'vlib/builtin/js/array_test.js.v',\n\t'vlib/db/sqlite/sqlite_test.v',\n\t'vlib/db/sqlite/sqlite_orm_test.v',\n\t'vlib/db/sqlite/sqlite_comptime_field_test.v',\n\t'vlib/db/sqlite/sqlite_vfs_lowlevel_test.v',\n\t'vlib/db/sqlite/parent_child_test.v',\n\t'vlib/db/sqlite/sqlite_f32_test.v',\n\t'vlib/orm/orm_test.v',\n\t'vlib/orm/orm_sql_or_blocks_test.v',\n\t'vlib/orm/orm_create_and_drop_test.v',\n\t'vlib/orm/orm_insert_test.v',\n\t'vlib/orm/orm_insert_reserved_name_test.v',\n\t'vlib/orm/orm_sum_type_insert_test.v',\n\t'vlib/orm/orm_fn_calls_test.v',\n\t'vlib/orm/orm_null_test.v',\n\t'vlib/orm/orm_last_id_test.v',\n\t'vlib/orm/orm_string_interpolation_in_where_test.v',\n\t'vlib/orm/orm_interface_test.v',\n\t'vlib/orm/orm_mut_db_test.v',\n\t'vlib/orm/orm_result_test.v',\n\t'vlib/orm/orm_custom_operators_test.v',\n\t'vlib/orm/orm_fk_test.v',\n\t'vlib/orm/orm_nested_struct_test.v',\n\t'vlib/orm/orm_references_test.v',\n\t'vlib/orm/orm_option_array_test.v',\n\t'vlib/orm/orm_option_time_test.v',\n\t'vlib/orm/orm_order_by_custom_field_test.v',\n\t'vlib/orm/orm_serial_attribute_test.v',\n\t'vlib/orm/orm_option_subselect_test.v',\n\t'vlib/orm/orm_func_test.v',\n\t'vlib/orm/orm_where_in_test.v',\n\t'vlib/v/tests/orm_enum_test.v',\n\t'vlib/v/tests/orm_sub_struct_test.v',\n\t'vlib/v/tests/orm_sub_array_struct_test.v',\n\t'vlib/v/tests/orm_joined_tables_select_test.v',\n\t'vlib/v/tests/orm_stmt_wrong_return_checking_test.v',\n\t'vlib/v/tests/orm_table_name_test.v',\n\t'vlib/v/tests/orm_array_field_test.v',\n\t'vlib/v/tests/orm_handle_error_for_select_from_not_created_table_test.v',\n\t'vlib/v/tests/orm_create_several_tables_test.v',\n\t'vlib/v/tests/orm_update_test.v',\n\t'vlib/v/tests/orm_or_test.v',\n\t'vlib/v/tests/sql_statement_inside_fn_call_test.v',\n\t'vlib/v/tests/websocket_logger_interface_should_compile_test.v',\n\t'vlib/v/tests/fns/fn_literal_type_test.v',\n\t'vlib/clipboard/clipboard_test.v',\n\t'vlib/vweb/tests/vweb_test.v',\n\t'vlib/vweb/csrf/csrf_test.v',\n\t'vlib/vweb/route_test.v',\n\t'vlib/net/http/request_test.v',\n\t'vlib/net/websocket/websocket_test.v',\n\t'vlib/net/http/header_test.v',\n\t'vlib/net/http/server_test.v',\n\t'vlib/net/http/response_test.v',\n\t'vlib/net/smtp/smtp_test.v',\n\t'vlib/net/http/cookie_test.v',\n\t'vlib/net/http/status_test.v',\n\t'vlib/x/sessions/tests/db_store_test.v',\n\t'vlib/veb/tests/veb_app_test.v',\n]\n\nfn Config.init(vargs []string, targs []string) !Config {\n\tmut cfg := Config{}\n\tfor arg in vargs {\n\t\tmatch arg {\n\t\t\t'-Werror', '-cstrict' { cfg.werror = true }\n\t\t\t'-fsanitize=memory' { cfg.sanitize_memory = true }\n\t\t\t'-fsanitize=address' { cfg.sanitize_address = true }\n\t\t\t'-fsanitize=undefined' { cfg.sanitize_undefined = true }\n\t\t\telse {}\n\t\t}\n\t}\n\tif targs.len == 0 {\n\t\treturn cfg\n\t}\n\tmut tdirs := []string{}\n\tmut errs := []string{}\n\tfor arg in targs {\n\t\tmatch arg {\n\t\t\t'-asan-compiler', '--asan-compiler' {\n\t\t\t\tcfg.is_asan_compiler = true\n\t\t\t}\n\t\t\t'-msan-compiler', '--msan-compiler' {\n\t\t\t\tcfg.is_msan_compiler = true\n\t\t\t}\n\t\t\t'-ubsan-compiler', '--ubsan-compiler' {\n\t\t\t\tcfg.is_ubsan_compiler = true\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif arg.starts_with('-') {\n\t\t\t\t\terrs << 'error: unknown flag `${arg}`'\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif !os.is_dir(os.join_path(vroot, arg)) {\n\t\t\t\t\terrs << 'error: failed to find directory `${arg}`'\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\ttdirs << arg\n\t\t\t}\n\t\t}\n\t}\n\tif errs.len > 0 {\n\t\treturn error(errs.join_lines())\n\t}\n\tif tdirs.len > 0 {\n\t\tcfg.test_dirs = tdirs\n\t}\n\treturn cfg\n}\n\nfn main() {\n\tunbuffer_stdout()\n\tos.chdir(vroot)!\n\targs_idx := os.args.index('test-self')\n\tvargs := os.args[1..args_idx]\n\ttargs := os.args#[args_idx + 1..]\n\tcfg := Config.init(vargs, targs) or {\n\t\teprintln(err)\n\t\texit(1)\n\t}\n\t// dump(cfg)\n\ttitle := 'testing: ${cfg.test_dirs.join(', ')}'\n\tmut tpaths := map[string]bool{}\n\tmut tpaths_ref := &tpaths\n\tfor dir in cfg.test_dirs {\n\t\tos.walk(os.join_path(vroot, dir), fn [mut tpaths_ref] (p string) {\n\t\t\tif p.ends_with('_test.v') || p.ends_with('_test.c.v')\n\t\t\t\t|| (testing.is_node_present && p.ends_with('_test.js.v')) {\n\t\t\t\tunsafe {\n\t\t\t\t\ttpaths_ref[p] = true\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\tmut all_test_files := tpaths.keys()\n\tif cfg.run_just_essential {\n\t\tall_test_files = essential_list.map(os.join_path(vroot, it))\n\t}\n\tmut tsession := testing.new_test_session(vargs.join(' '), true)\n\ttsession.exec_mode = .compile_and_run\n\ttsession.files << all_test_files.filter(!it.contains('testdata' + os.path_separator))\n\tif cfg.werror {\n\t\ttsession.custom_defines << 'self_werror'\n\t}\n\tif cfg.sanitize_memory {\n\t\ttsession.skip_files << skip_with_fsanitize_memory\n\t\ttsession.custom_defines << 'self_sanitize_memory'\n\t}\n\tif cfg.sanitize_address {\n\t\ttsession.skip_files << skip_with_fsanitize_address\n\t\ttsession.custom_defines << 'self_sanitize_address'\n\t}\n\tif cfg.sanitize_undefined {\n\t\ttsession.skip_files << skip_with_fsanitize_undefined\n\t\ttsession.custom_defines << 'self_sanitize_undefined'\n\t}\n\tif cfg.is_asan_compiler {\n\t\ttsession.custom_defines << 'self_asan_compiler'\n\t}\n\tif cfg.is_msan_compiler {\n\t\ttsession.custom_defines << 'self_msan_compiler'\n\t}\n\tif cfg.is_ubsan_compiler {\n\t\ttsession.custom_defines << 'self_ubsan_compiler'\n\t}\n\tif cfg.is_sandboxed_packaging {\n\t\ttsession.custom_defines << 'self_sandboxed_packaging'\n\t}\n\tif cfg.is_ubuntu_musl_ci {\n\t\ttsession.skip_files << skip_on_ubuntu_musl\n\t\ttsession.custom_defines << 'self_ubuntu_musl_ci'\n\t}\n\t// dump(tsession.skip_files)\n\tmut unavailable_files := tsession.files.filter(!os.exists(it))\n\tunavailable_files << tsession.skip_files.filter(it != 'do_not_remove' && !os.exists(it))\n\tif unavailable_files.len > 0 {\n\t\tfor f in unavailable_files {\n\t\t\teprintln('error: failed to find file: ${f}')\n\t\t}\n\t\texit(1)\n\t}\n\ttsession.skip_files = tsession.skip_files.map(os.abs_path)\n\ttsession.session_start(title)\n\ttsession.test()\n\ttsession.session_stop(title)\n\tflush_stdout()\n\tif tsession.benchmark.nfail > 0 {\n\t\teprintln('\\nError: failed ${tsession.benchmark.nfail} times.\\n')\n\t\texit(1)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vtest.v",
    "content": "module main\n\nimport os\nimport os.cmdline\nimport testing\nimport v.pref\n\nstruct Context {\nmut:\n\tverbose   bool\n\tfail_fast bool\n\trun_only  []string\n}\n\nfn main() {\n\targs := os.args.clone()\n\tif os.args.last() == 'test' {\n\t\tshow_usage()\n\t\treturn\n\t}\n\targs_to_executable := args[1..]\n\tmut args_before := cmdline.options_before(args_to_executable, ['test'])\n\tmut args_after := cmdline.options_after(args_to_executable, ['test'])\n\tmut ctx := Context{}\n\tctx.fail_fast = extract_flag_bool('-fail-fast', mut args_after, testing.fail_fast)\n\tctx.verbose = extract_flag_bool('-v', mut args_after, false)\n\tctx.run_only = extract_flag_string_array('-run-only', mut args_after, testing.test_only_fn)\n\tos.setenv('VTEST_ONLY_FN', ctx.run_only.join(','), true)\n\tif args_after == ['v'] {\n\t\teprintln('`v test v` has been deprecated.')\n\t\teprintln('Use `v test-all` instead.')\n\t\texit(1)\n\t}\n\tbackend_pos := args_before.index('-b')\n\tbackend := if backend_pos == -1 { '.c' } else { args_before[backend_pos + 1] }\n\n\tmut ts := testing.new_test_session(args_before.join(' '), true)\n\tts.exec_mode = .compile_and_run\n\tts.fail_fast = ctx.fail_fast\n\tfor targ in args_after {\n\t\tif os.is_dir(targ) {\n\t\t\t// Fetch all tests from the directory\n\t\t\tfiles, skip_files := ctx.should_test_dir(targ.trim_right(os.path_separator),\n\t\t\t\tbackend)\n\t\t\tts.files << files\n\t\t\tts.skip_files << skip_files\n\t\t\tcontinue\n\t\t} else if os.exists(targ) {\n\t\t\tmatch ctx.should_test(targ, backend) {\n\t\t\t\t.test {\n\t\t\t\t\tts.files << targ\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t.skip {\n\t\t\t\t\tif ctx.run_only.len > 0 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tts.files << targ\n\t\t\t\t\tts.skip_files << os.abs_path(targ)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t.ignore {}\n\t\t\t}\n\t\t} else {\n\t\t\teprintln('\\nUnrecognized test file `${targ}`.\\n `v test` can only be used with folders and/or _test.v files.\\n')\n\t\t\tshow_usage()\n\t\t\texit(1)\n\t\t}\n\t}\n\tts.session_start('Testing...')\n\tts.test()\n\tts.session_stop('all V _test.v files')\n\tif ts.failed_cmds.len > 0 {\n\t\texit(1)\n\t}\n}\n\nfn show_usage() {\n\tprintln('Usage:')\n\tprintln('   A)')\n\tprintln('      v test folder/ : run all v tests in the given folder.')\n\tprintln('      v -stats test folder/ : the same, but print more stats.')\n\tprintln('   B)')\n\tprintln('      v test file_test.v : run test functions in a given test file.')\n\tprintln('      v -stats test file_test.v : as above, but with more stats.')\n\tprintln('   Note: you can also give many and mixed folder/ file_test.v arguments after `v test` .')\n\tprintln('')\n}\n\npub fn (mut ctx Context) should_test_dir(path string, backend string) ([]string, []string) { // return is (files, skip_files)\n\tmut files := os.ls(path) or { return []string{}, []string{} }\n\tmut local_path_separator := os.path_separator\n\tif path.ends_with(os.path_separator) {\n\t\tlocal_path_separator = ''\n\t}\n\tmut res_files := []string{}\n\tmut skip_files := []string{}\n\tfor file in files {\n\t\tp := path + local_path_separator + file\n\t\tif os.is_dir(p) && !os.is_link(p) {\n\t\t\tif file == 'testdata' {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tret_files, ret_skip_files := ctx.should_test_dir(p, backend)\n\t\t\tres_files << ret_files\n\t\t\tskip_files << ret_skip_files\n\t\t} else if os.exists(p) {\n\t\t\tmatch ctx.should_test(p, backend) {\n\t\t\t\t.test {\n\t\t\t\t\tres_files << p\n\t\t\t\t}\n\t\t\t\t.skip {\n\t\t\t\t\tif ctx.run_only.len > 0 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tres_files << p\n\t\t\t\t\tskip_files << os.abs_path(p)\n\t\t\t\t}\n\t\t\t\t.ignore {}\n\t\t\t}\n\t\t}\n\t}\n\treturn res_files, skip_files\n}\n\nenum ShouldTestStatus {\n\ttest   // do test, print OK or FAIL, depending on if it passes\n\tskip   // print SKIP for the test\n\tignore // just ignore the file, so it will not be printed at all in the list of tests\n}\n\nfn (mut ctx Context) should_test(path string, backend string) ShouldTestStatus {\n\tif path.ends_with('_test.v') {\n\t\treturn ctx.should_test_when_it_contains_matching_fns(path, backend)\n\t}\n\tif path.ends_with('_test.c.v') {\n\t\treturn ctx.should_test_when_it_contains_matching_fns(path, backend)\n\t}\n\tif path.ends_with('_test.js.v') {\n\t\tif testing.is_node_present {\n\t\t\treturn ctx.should_test_when_it_contains_matching_fns(path, backend)\n\t\t}\n\t\treturn .skip\n\t}\n\tif path.ends_with('.v') && path.count('.') == 2 {\n\t\tif !path.all_before_last('.v').all_before_last('.').ends_with('_test') {\n\t\t\treturn .ignore\n\t\t}\n\t\tbackend_arg := path.all_before_last('.v').all_after_last('.')\n\t\tarch := pref.arch_from_string(backend_arg) or { pref.Arch._auto }\n\t\tif arch == pref.get_host_arch() {\n\t\t\treturn ctx.should_test_when_it_contains_matching_fns(path, backend)\n\t\t} else if arch == ._auto {\n\t\t\tif backend_arg == 'c' { // .c.v\n\t\t\t\treturn if backend == 'c' {\n\t\t\t\t\tctx.should_test_when_it_contains_matching_fns(path, backend)\n\t\t\t\t} else {\n\t\t\t\t\tShouldTestStatus.skip\n\t\t\t\t}\n\t\t\t}\n\t\t\tif backend_arg == 'js' {\n\t\t\t\treturn if backend == 'js' {\n\t\t\t\t\tctx.should_test_when_it_contains_matching_fns(path, backend)\n\t\t\t\t} else {\n\t\t\t\t\tShouldTestStatus.skip\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treturn .skip\n\t\t}\n\t}\n\treturn .ignore\n}\n\nfn (mut ctx Context) should_test_when_it_contains_matching_fns(path string, backend string) ShouldTestStatus {\n\tif ctx.run_only.len == 0 {\n\t\t// no filters set, so just compile and test\n\t\treturn .test\n\t}\n\tlines := os.read_lines(path) or { return .ignore }\n\tfor line in lines {\n\t\tif line.match_glob('fn test_*') || line.match_glob('pub fn test_*') {\n\t\t\ttname := line.replace_each(['pub fn ', '', 'fn ', '']).all_before('(')\n\t\t\tfor pattern in ctx.run_only {\n\t\t\t\tmut pat := pattern.clone()\n\t\t\t\tif pat.contains('.') {\n\t\t\t\t\tpat = pat.all_after_last('.')\n\t\t\t\t}\n\t\t\t\tif tname.match_glob(pat) {\n\t\t\t\t\tif ctx.verbose {\n\t\t\t\t\t\tprintln('> compiling path: ${path}, since test fn `${tname}` matches glob pattern `${pat}`')\n\t\t\t\t\t}\n\t\t\t\t\treturn .test\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn .ignore\n}\n\nfn extract_flag_bool(flag_name string, mut after []string, flag_default bool) bool {\n\tmut res := flag_default\n\torig_after := after.clone() // workaround for after.filter() codegen bug, when `mut after []string`\n\tmatches_after := orig_after.filter(it != flag_name)\n\tif matches_after.len < after.len {\n\t\tafter = matches_after.clone()\n\t\tres = true\n\t}\n\treturn res\n}\n\nfn extract_flag_string_array(flag_name string, mut after []string, flag_default []string) []string {\n\tmut res := flag_default.clone()\n\tmut found := after.index(flag_name)\n\tif found > -1 {\n\t\tif found + 1 < after.len {\n\t\t\tres = after[found + 1].split_any(',')\n\t\t\tafter.delete(found)\n\t\t}\n\t\tafter.delete(found)\n\t}\n\treturn res\n}\n"
  },
  {
    "path": "cmd/tools/vtest_test.v",
    "content": "import os\nimport encoding.txtar\n\nconst vexe = @VEXE\nconst vroot = os.dir(vexe)\nconst tpath = os.join_path(os.vtmp_dir(), 'vtest_folder')\nconst tpath_passing = os.join_path(tpath, 'passing')\nconst tpath_partial = os.join_path(tpath, 'partial')\nconst mytest_exe = os.join_path(tpath, 'mytest.exe')\n\nfn testsuite_end() {\n\tos.rmdir_all(tpath) or {}\n}\n\nfn testsuite_begin() {\n\tos.setenv('VFLAGS', '', true)\n\tos.setenv('VCOLORS', 'never', true)\n\tos.setenv('VJOBS', '2', true)\n\tos.setenv('VTEST_HIDE_OK', '0', true)\n\tos.rmdir_all(tpath) or {}\n\tos.mkdir_all(tpath)!\n\n\ttxtar.parse('Some known test files to make sure `v test` and `v -stats test` work:\n-- passing/1_test.v --\nfn test_abc() { assert true; assert true; assert true }\nfn test_def() { assert 2 * 2 == 4 }\n-- passing/2_test.v --\nfn test_xyz() { assert 1 == 2 - 1 }\nfn test_abc() { assert 10 == 2 * 5 }\n-- partial/passing_test.v --\nfn test_xyz() { assert 3 == 10 - 7 }\nfn test_def() { assert 10 == 100 / 10 }\n-- partial/failing_test.v --\nfn test_xyz() { assert 5 == 7, \"oh no\" }\n').unpack_to(tpath)!\n\tassert os.exists(os.join_path(tpath, 'passing/1_test.v'))\n\tassert os.exists(os.join_path(tpath, 'passing/2_test.v'))\n\tassert os.exists(os.join_path(tpath, 'partial/passing_test.v'))\n\tassert os.exists(os.join_path(tpath, 'partial/failing_test.v'))\n}\n\nfn test_vtest_executable_compiles() {\n\tos.chdir(vroot)!\n\tos.execute_or_exit('${os.quoted_path(vexe)} -o ${tpath}/mytest.exe cmd/tools/vtest.v')\n\tassert os.exists(mytest_exe), 'executable file: `${mytest_exe}` should exist'\n}\n\nfn test_with_several_test_files() {\n\tres := os.execute_or_exit('${os.quoted_path(mytest_exe)} test ${os.quoted_path(tpath_passing)}')\n\tassert !res.output.contains('1 assert'), res.output\n\tassert !res.output.contains('3 asserts'), res.output\n\tassert res.output.contains('2 passed, 2 total'), res.output\n\tassert res.output.count('OK') == 2, res.output\n\tassert res.output.contains('on 2 parallel jobs'), res.output\n}\n\nfn test_with_stats_and_several_test_files() {\n\t// There should be more OKs here, since the output will have the inner OKs for each individual test fn:\n\tres := os.execute_or_exit('${os.quoted_path(mytest_exe)} -stats test ${os.quoted_path(tpath_passing)}')\n\tassert res.output.contains('1 assert'), res.output\n\tassert res.output.contains('3 asserts'), res.output\n\tassert res.output.contains('2 passed, 2 total'), res.output\n\tassert res.output.count('OK') == 6, res.output\n}\n\nfn test_partial_failure() {\n\tres := os.execute('${os.quoted_path(mytest_exe)} test ${os.quoted_path(tpath_partial)}')\n\tassert res.exit_code == 1\n\tassert res.output.contains('assert 5 == 7'), res.output\n\tassert res.output.contains(' 1 failed, 1 passed, 2 total'), res.output\n\tassert res.output.contains('To reproduce just failure'), res.output\n}\n\nfn test_with_stats_and_partial_failure() {\n\tres := os.execute('${os.quoted_path(mytest_exe)} -stats test ${os.quoted_path(tpath_partial)}')\n\tassert res.exit_code == 1\n\tassert res.output.contains('assert 5 == 7'), res.output\n\tassert res.output.contains(' 1 failed, 1 passed, 2 total'), res.output\n\tassert res.output.contains('To reproduce just failure'), res.output\n}\n"
  },
  {
    "path": "cmd/tools/vtime.v",
    "content": "import os\nimport term\nimport time\nimport flag\n\nstruct Context {\nmut:\n\tshow_help     bool\n\tcmd_line_opts []string\n}\n\nfn main() {\n\tmut ctx := Context{}\n\targs := arguments()\n\tmut fp := flag.new_flag_parser(args#[1..])\n\tfp.application('v time')\n\tfp.version('0.0.1')\n\tfp.description('Start a command, and report how much time it took to run, and what its exit code was.')\n\tfp.arguments_description('CMD [ARGS]')\n\tfp.skip_executable()\n\tfp.limit_free_args_to_at_least(1)!\n\tctx.show_help = fp.bool('help', `h`, false, 'Show this help screen.')\n\tif ctx.show_help {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\tctx.cmd_line_opts = fp.finalize() or {\n\t\teprintln('Error: ${err}')\n\t\texit(1)\n\t}\n\tcmd := ctx.cmd_line_opts.join(' ')\n\tsw := time.new_stopwatch()\n\tecode := os.system(cmd)\n\telapsed := sw.elapsed()\n\tstook_time := '${f64(elapsed.microseconds()) / 1000.0:8.3f} ms'\n\teprintln('> ${term.ecolorize(term.bright_yellow, stook_time)}. Exit code: ${ecode:3}. Command: ${term.ecolorize(term.green,\n\t\tcmd)}')\n\texit(ecode)\n}\n"
  },
  {
    "path": "cmd/tools/vtimeout.v",
    "content": "import os\nimport time\nimport flag\nimport strconv\n\nstruct Context {\nmut:\n\ttimeout  f64\n\tcmd_args []string\n}\n\nfn main() {\n\tmut fp := flag.new_flag_parser(os.args[1..])\n\tfp.application('v timeout')\n\tfp.version('0.0.2')\n\tfp.description('Run a command with a time limit. Example: `v timeout 0.3 v run examples/hello_world.v`')\n\tfp.arguments_description('timeout_in_seconds CMD [ARGS]')\n\tfp.skip_executable()\n\tfp.limit_free_args_to_at_least(2)!\n\n\tif fp.bool('help', `h`, false, 'Show this help screen.') {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\n\targs := fp.finalize() or {\n\t\teprintln('Argument error: ${err}')\n\t\texit(125) // mimic the exit codes of `timeout` in coreutils\n\t}\n\n\tctx := Context{\n\t\ttimeout:  strconv.atof64(args[0]) or {\n\t\t\teprintln('Invalid timeout: ${args[0]}')\n\t\t\texit(125)\n\t\t}\n\t\tcmd_args: args[1..].clone()\n\t}\n\n\tmut cmd := ctx.cmd_args[0]\n\tif !os.exists(cmd) {\n\t\tcmd = os.find_abs_path_of_executable(cmd) or { cmd }\n\t}\n\n\tmut p := os.new_process(cmd)\n\tp.set_args(ctx.cmd_args[1..])\n\tp.run()\n\tif p.err != '' {\n\t\teprintln('Cannot execute: ${ctx.cmd_args.join(' ')}')\n\t\texit(if os.exists(ctx.cmd_args[0]) { 126 } else { 127 })\n\t}\n\n\tchild_exit := chan int{}\n\n\tspawn fn (mut p os.Process, ch chan int) {\n\t\tp.wait()\n\t\tch <- p.code\n\t\tch.close()\n\t}(mut p, child_exit)\n\n\tmut exit_code := 0\n\tselect {\n\t\ti64(ctx.timeout * time.second) {\n\t\t\tp.signal_term()\n\t\t\ttime.sleep(2 * time.millisecond)\n\t\t\tif p.is_alive() {\n\t\t\t\tp.signal_kill()\n\t\t\t}\n\t\t\tp.wait()\n\t\t\texit_code = 124 // timeout\n\t\t}\n\t\tcode := <-child_exit {\n\t\t\texit_code = code\n\t\t}\n\t}\n\texit(exit_code)\n}\n"
  },
  {
    "path": "cmd/tools/vtimeout_test.v",
    "content": "// vtest retry: 3\nimport os\nimport time\n\nconst qvexe = os.quoted_path(@VEXE)\n\nfn depend_on_command(cmd string) ? {\n\tpath := os.find_abs_path_of_executable(cmd) or {\n\t\tprintln('skip: ${cmd} not found')\n\t\treturn none\n\t}\n\tres := os.execute('${os.quoted_path(path)} --version')\n\tif res.exit_code != 0 {\n\t\tprintln('skip: ${cmd} does not support --version')\n\t\treturn none\n\t}\n\tif !res.output.contains('GNU coreutils') {\n\t\tprintln('skip: ${cmd} is not from coreutils')\n\t\treturn none\n\t}\n}\n\nfn execute(cmd string) os.Result {\n\tsw := time.new_stopwatch()\n\tres := os.execute(cmd)\n\tdt := sw.elapsed().milliseconds()\n\teprintln('>> command: `${cmd:-60s}`, took: ${dt:5} ms, exit_code: ${res.exit_code:3}, output.len: ${res.output.len}')\n\treturn res\n}\n\nfn test_normal_exit_without_timeout_echo() {\n\tdepend_on_command('echo') or { return }\n\tee := execute('${qvexe} timeout 0.5 echo')\n\tassert ee.exit_code == 0, ee.output\n\tres := execute('${qvexe} timeout 0.5 echo z123')\n\tassert res.exit_code == 0, res.output\n\tassert res.output.contains('z123')\n}\n\nfn test_normal_exit_without_timeout_sleep() {\n\tdepend_on_command('sleep') or { return }\n\tres := execute('${qvexe} timeout 0.5 sleep 0.1')\n\tassert res.exit_code == 0, res.output\n\tassert res.output == ''\n}\n\nfn test_exit_with_timeout() {\n\tdepend_on_command('sleep') or { return }\n\tres := execute('${qvexe} timeout 0.5 sleep 3')\n\tassert res.exit_code == 124, res.output\n}\n"
  },
  {
    "path": "cmd/tools/vtracev.v",
    "content": "module main\n\nimport os\n\nfn main() {\n\tvexe := os.real_path(os.getenv_opt('VEXE') or { @VEXE })\n\tvroot := os.dir(vexe)\n\tos.chdir(vroot)!\n\tos.setenv('VCOLORS', 'always', true)\n\tself_idx := os.args.index('tracev')\n\targs := os.args[1..self_idx]\n\targs_str := args.join(' ')\n\toptions := if args.len > 0 { '(${args_str})' } else { '' }\n\tprintln('Compiling a `tracev` executable ${options}...')\n\tos.system('${os.quoted_path(vexe)} -cg -d trace_parser -d trace_checker -d trace_gen -o tracev ${args_str} cmd/v')\n}\n"
  },
  {
    "path": "cmd/tools/vup.v",
    "content": "module main\n\nimport os\nimport v.util.version\nimport v.util.recompilation\n\nconst vexe = os.real_path(os.getenv_opt('VEXE') or { @VEXE })\n\nconst vroot = os.dir(vexe)\n\nstruct App {\n\tis_verbose bool\n\tis_prod    bool\n\tvexe       string\n\tvroot      string\n\n\tskip_v_self  bool // do not run `v self`, effectively enforcing the running of `make` or `make.bat`\n\tskip_current bool // skip the current hash check, enabling easier testing on the same commit, without using docker etc\n}\n\nconst args = arguments()\n\nfn new_app() App {\n\treturn App{\n\t\tis_verbose:   '-v' in args\n\t\tis_prod:      '-prod' in args\n\t\tvexe:         vexe\n\t\tvroot:        vroot\n\t\tskip_v_self:  '-skip_v_self' in args\n\t\tskip_current: '-skip_current' in args\n\t}\n}\n\nfn main() {\n\tapp := new_app()\n\trecompilation.must_be_enabled(app.vroot, 'Please install V from source, to use `v up` .')\n\tos.chdir(app.vroot)!\n\tprintln('Updating V...')\n\tapp.update_from_master()\n\thash_when_vup_was_compiled := @VCURRENTHASH\n\tcurrent_hash_from_filesystem := version.githash(vroot) or { hash_when_vup_was_compiled }\n\tif !app.skip_current && hash_when_vup_was_compiled == current_hash_from_filesystem {\n\t\tprintln('V is already updated.')\n\t\tif !os.exists(app.current_vexe_path()) {\n\t\t\teprintln('`${app.vexe}` is missing, trying `${get_make_cmd_name()}` to restore it...')\n\t\t\tif !app.make('') {\n\t\t\t\tapp.show_current_v_version()\n\t\t\t\teprintln('Recompiling V *failed*.')\n\t\t\t\teprintln('Try running `${get_make_cmd_name()}` .')\n\t\t\t\texit(1)\n\t\t\t}\n\t\t}\n\t\tapp.show_current_v_version()\n\t\treturn\n\t}\n\tif os.user_os() == 'windows' {\n\t\tapp.backup('cmd/tools/vup.exe')\n\t}\n\tif !app.recompile_v() {\n\t\tapp.show_current_v_version()\n\t\teprintln('Recompiling V *failed*.')\n\t\teprintln('Try running `${get_make_cmd_name()}` .')\n\t\texit(1)\n\t}\n\tapp.recompile_vup()\n\tapp.show_current_v_version()\n}\n\nfn (app App) vprintln(s string) {\n\tif app.is_verbose {\n\t\tprintln(s)\n\t}\n}\n\nfn (app App) update_from_master() {\n\tapp.vprintln('> updating from master ...')\n\tif !os.exists('.git') {\n\t\t// initialize the folder, as if it had been cloned:\n\t\tapp.git_command('git init')\n\t\tapp.git_command('git remote add origin https://github.com/vlang/v')\n\t\tapp.git_command('git fetch')\n\t\tapp.git_command('git remote set-head origin master')\n\t\tapp.git_command('git reset --hard origin/master')\n\t\t// Note 1: patterns starting with /, will match only against the root;\n\t\t//         `--exclude v` will match also vlib/v/ in addition to ./v; `--exclude /v` will only match ./v\n\t\t// Note 2: patterns ending with / are treated as folders.\n\t\tapp.git_command('git clean -xfd --exclude /thirdparty/tcc/ --exclude /v --exclude /v.exe --exclude /v_old --exclude /v_old.exe --exclude /${app.current_vexe_name()} --exclude /${app.current_vbackup_name()} --exclude /.bin/ --exclude /cmd/tools/vup --exclude /cmd/tools/vup.exe')\n\t} else {\n\t\t// pull latest\n\t\tapp.git_command('git pull https://github.com/vlang/v master')\n\t}\n}\n\nfn (app App) recompile_v() bool {\n\t// Note: app.vexe is more reliable than just v (which may be a symlink)\n\tvexe_path := app.current_vexe_path()\n\tif !os.exists(vexe_path) {\n\t\tprintln('> `${app.vexe}` is missing, running `make`...')\n\t\treturn app.make('')\n\t}\n\topts := if app.is_prod { '-prod' } else { '' }\n\tvself := '${os.quoted_path(vexe_path)} ${opts} self'\n\tif app.skip_v_self {\n\t\treturn app.make(vself)\n\t}\n\n\tself_result := os.execute(vself)\n\tif self_result.exit_code == 0 {\n\t\tprintln(self_result.output.trim_space())\n\t\tprintln('> Done recompiling.')\n\t\treturn true\n\t} else {\n\t\tprintln('> `${vself}` failed, running `make`...')\n\t\tapp.vprintln(self_result.output.trim_space())\n\t}\n\treturn app.make(vself)\n}\n\nfn (app App) recompile_vup() bool {\n\teprintln('> Recompiling vup.v ...')\n\tvexe_path := app.current_vexe_path()\n\tif !os.exists(vexe_path) {\n\t\teprintln('> Skipping recompiling vup.v, `${vexe_path}` is missing.')\n\t\treturn false\n\t}\n\tvup_result := os.execute('${os.quoted_path(vexe_path)} -g cmd/tools/vup.v')\n\tif vup_result.exit_code != 0 {\n\t\teprintln('> Failed recompiling vup.v .')\n\t\teprintln(vup_result.output)\n\t\treturn false\n\t}\n\treturn true\n}\n\nfn (app App) make(vself string) bool {\n\tprintln('> running make ...')\n\tmake := get_make_cmd_name()\n\tmake_result := os.execute(make)\n\tif make_result.exit_code != 0 {\n\t\teprintln('> ${make} failed:')\n\t\teprintln('> make output:')\n\t\teprintln(make_result.output)\n\t\treturn false\n\t}\n\tapp.vprintln(make_result.output)\n\tprintln('> done running make.')\n\treturn true\n}\n\nfn (app App) show_current_v_version() {\n\tvexe_path := app.current_vexe_path()\n\tif !os.exists(vexe_path) {\n\t\tprintln('Current V version: unavailable (`${app.vexe}` is missing).')\n\t\treturn\n\t}\n\tvout := os.execute('${os.quoted_path(vexe_path)} version')\n\tif vout.exit_code >= 0 {\n\t\tmut vversion := vout.output.trim_space()\n\t\tif vout.exit_code == 0 {\n\t\t\tlatest_v_commit := vversion.split(' ').last().all_after('.')\n\t\t\tlatest_v_commit_time := os.execute('git show -s --format=%ci ${latest_v_commit}')\n\t\t\tif latest_v_commit_time.exit_code == 0 {\n\t\t\t\tvversion += ', timestamp: ' + latest_v_commit_time.output.trim_space()\n\t\t\t}\n\t\t}\n\t\tprintln('Current V version: ${vversion}')\n\t}\n}\n\nfn (app App) current_vexe_name() string {\n\tvexe_name := os.file_name(app.vexe)\n\tif vexe_name == '' {\n\t\treturn if os.user_os() == 'windows' { 'v.exe' } else { 'v' }\n\t}\n\treturn vexe_name\n}\n\nfn (app App) current_vbackup_name() string {\n\tvexe_name := app.current_vexe_name()\n\tshort_v_name := vexe_name.all_before('.')\n\treturn if os.user_os() == 'windows' { '${short_v_name}_old.exe' } else { '${short_v_name}_old' }\n}\n\nfn (app App) current_vexe_path() string {\n\tif os.exists(app.vexe) {\n\t\treturn app.vexe\n\t}\n\tdefault_vexe := os.join_path_single(app.vroot, if os.user_os() == 'windows' {\n\t\t'v.exe'\n\t} else {\n\t\t'v'\n\t})\n\tif os.exists(default_vexe) {\n\t\treturn default_vexe\n\t}\n\tconfigured_vexe := os.join_path_single(app.vroot, app.current_vexe_name())\n\tif os.exists(configured_vexe) {\n\t\treturn configured_vexe\n\t}\n\treturn app.vexe\n}\n\nfn (app App) backup(file string) {\n\tbackup_file := '${file}_old.exe'\n\tprintln('> backing up `${file}` to `${backup_file}` ...')\n\tif os.exists(backup_file) {\n\t\tos.rm(backup_file) or { eprintln('failed removing ${backup_file}: ${err.msg()}') }\n\t}\n\tos.mv(file, backup_file) or { eprintln('failed moving ${file}: ${err.msg()}') }\n}\n\nfn (app App) git_command(command string) {\n\tprintln('> git_command: ${command}')\n\tgit_result := os.execute(command)\n\tif git_result.exit_code < 0 {\n\t\tapp.install_git()\n\t\t// Try it again with (maybe) git installed\n\t\tos.execute_or_exit(command)\n\t}\n\tif git_result.exit_code != 0 {\n\t\teprintln('Failed git command: ${command}')\n\t\teprintln(git_result.output)\n\t\texit(1)\n\t}\n\tapp.vprintln(git_result.output)\n}\n\nfn (app App) install_git() {\n\tif os.user_os() != 'windows' {\n\t\t// Probably some kind of *nix, usually need to get using a package manager.\n\t\teprintln(\"error: Install `git` using your system's package manager\")\n\t}\n\tprintln('Downloading git 32 bit for Windows, please wait.')\n\t// We'll use 32 bit because maybe someone out there is using 32-bit windows\n\tres_download := os.execute('bitsadmin.exe /transfer \"vgit\" https://github.com/git-for-windows/git/releases/download/v2.30.0.windows.2/Git-2.30.0.2-32-bit.exe \"${os.getwd()}/git32.exe\"')\n\tif res_download.exit_code != 0 {\n\t\teprintln('Unable to install git automatically: please install git manually')\n\t\tpanic(res_download.output)\n\t}\n\tres_git32 := os.execute(os.quoted_path(os.join_path_single(os.getwd(), 'git32.exe')))\n\tif res_git32.exit_code != 0 {\n\t\teprintln('Unable to install git automatically: please install git manually')\n\t\tpanic(res_git32.output)\n\t}\n}\n\nfn get_make_cmd_name() string {\n\tif os.user_os() == 'windows' {\n\t\treturn 'make.bat'\n\t}\n\tcmd := 'make'\n\tmake_sure_cmd_is_available(cmd)\n\tcc := os.getenv_opt('CC') or { 'cc' }\n\tmake_sure_cmd_is_available(cc)\n\treturn cmd\n}\n\nfn make_sure_cmd_is_available(cmd string) {\n\tfound_path := os.find_abs_path_of_executable(cmd) or {\n\t\teprintln('Could not find `${cmd}` in PATH. Please install `${cmd}`, since `v up` needs it.')\n\t\texit(1)\n\t}\n\tprintln('Found `${cmd}` as `${found_path}`.')\n}\n"
  },
  {
    "path": "cmd/tools/vvet/analyze.v",
    "content": "// Copyright (c) 2025 Felipe Pena. All rights reserved.\n// Use of this source code is governed by an MIT license that can be found in the LICENSE file.\nmodule main\n\nimport v.ast\nimport v.token\nimport os\nimport arrays\n\n// cutoffs\nconst indexexpr_cutoff = os.getenv_opt('VET_INDEXEXPR_CUTOFF') or { '10' }.int()\nconst infixexpr_cutoff = os.getenv_opt('VET_INFIXEXPR_CUTOFF') or { '10' }.int()\nconst selectorexpr_cutoff = os.getenv_opt('VET_SELECTOREXPR_CUTOFF') or { '10' }.int()\nconst callexpr_cutoff = os.getenv_opt('VET_CALLEXPR_CUTOFF') or { '10' }.int()\nconst stringinterliteral_cutoff = os.getenv_opt('STRINGINTERLITERAL_CUTOFF') or { '10' }.int()\nconst stringliteral_cutoff = os.getenv_opt('STRINGLITERAL_CUTOFF') or { '10' }.int()\nconst ascast_cutoff = os.getenv_opt('ASCAST_CUTOFF') or { '10' }.int()\nconst stringconcat_cutoff = os.getenv_opt('STRINGCONCAT_CUTOFF') or { '10' }.int()\n\n// possibly inline fn cutoff\nconst fns_call_cutoff = os.getenv_opt('VET_FNS_CALL_CUTOFF') or { '10' }.int() // at least N calls\nconst short_fns_cutoff = os.getenv_opt('VET_SHORT_FNS_CUTOFF') or { '3' }.int() // lines\n\n// minimum size for string literals\nconst stringliteral_min_size = os.getenv_opt('VET_STRINGLITERAL_MIN_SIZE') or { '20' }.int()\n\n// long functions cutoff\nconst long_fns_cutoff = os.getenv_opt('VET_LONG_FNS_CUTOFF') or { '300' }.int()\n\nstruct VetAnalyze {\nmut:\n\trepeated_expr_cutoff  shared map[string]int // repeated code cutoff\t\n\trepeated_expr         shared map[string]map[string]map[string][]token.Pos // repeated exprs in fn scope\n\tpotential_non_inlined shared map[string]map[string]token.Pos              // fns might be inlined\n\tcall_counter          shared map[string]int // fn call counter\n\tcur_fn                ast.FnDecl            // current fn declaration\n}\n\n// stmt checks for repeated code in statements\nfn (mut vt VetAnalyze) stmt(vet &Vet, stmt ast.Stmt) {\n\tmatch stmt {\n\t\tast.AssignStmt {\n\t\t\tif stmt.op == .plus_assign {\n\t\t\t\tif stmt.right[0] in [ast.StringLiteral, ast.StringInterLiteral] {\n\t\t\t\t\tvt.save_expr(stringconcat_cutoff, '${stmt.left[0].str()} += ${stmt.right[0].str()}',\n\t\t\t\t\t\tvet.file, stmt.pos)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {}\n\t}\n}\n\n// save_expr registers a repeated code occurrence\nfn (mut vt VetAnalyze) save_expr(cutoff int, expr string, file string, pos token.Pos) {\n\tlock vt.repeated_expr {\n\t\tvt.repeated_expr[vt.cur_fn.name][expr][file] << pos\n\t}\n\tlock vt.repeated_expr_cutoff {\n\t\tvt.repeated_expr_cutoff[expr] = cutoff\n\t}\n}\n\n// exprs checks for repeated code in expressions\nfn (mut vt VetAnalyze) exprs(vet &Vet, exprs []ast.Expr) {\n\tfor expr in exprs {\n\t\tvt.expr(vet, expr)\n\t}\n}\n\n// expr checks for repeated code\nfn (mut vt VetAnalyze) expr(vet &Vet, expr ast.Expr) {\n\tmatch expr {\n\t\tast.InfixExpr {\n\t\t\tvt.save_expr(infixexpr_cutoff, '${expr.left} ${expr.op} ${expr.right}', vet.file,\n\t\t\t\texpr.pos)\n\t\t}\n\t\tast.IndexExpr {\n\t\t\tvt.save_expr(indexexpr_cutoff, '${expr.left}[${expr.index}]', vet.file, expr.pos)\n\t\t}\n\t\tast.SelectorExpr {\n\t\t\t// nested selectors\n\t\t\tif expr.expr !is ast.Ident {\n\t\t\t\tvt.save_expr(selectorexpr_cutoff, '${expr.expr.str()}.${expr.field_name}',\n\t\t\t\t\tvet.file, expr.pos)\n\t\t\t}\n\t\t}\n\t\tast.CallExpr {\n\t\t\tif expr.is_static_method || expr.is_method {\n\t\t\t\tleft_str := expr.left.str()\n\t\t\t\tlock vt.call_counter {\n\t\t\t\t\tif vt.cur_fn.receiver.name == left_str {\n\t\t\t\t\t\tvt.call_counter['${int(vt.cur_fn.receiver.typ)}.${expr.name}']++\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvt.save_expr(callexpr_cutoff, '${left_str}.${expr.name}(${expr.args.map(it.str()).join(', ')})',\n\t\t\t\t\tvet.file, expr.pos)\n\t\t\t} else {\n\t\t\t\tlock vt.call_counter {\n\t\t\t\t\tvt.call_counter[expr.name]++\n\t\t\t\t}\n\t\t\t\tvt.save_expr(callexpr_cutoff, '${expr.name}(${expr.args.map(it.str()).join(', ')})',\n\t\t\t\t\tvet.file, expr.pos)\n\t\t\t}\n\t\t}\n\t\tast.AsCast {\n\t\t\tvt.save_expr(ascast_cutoff, ast.Expr(expr).str(), vet.file, expr.pos)\n\t\t}\n\t\tast.StringLiteral {\n\t\t\tif expr.val.len > stringliteral_min_size {\n\t\t\t\tvt.save_expr(stringliteral_cutoff, ast.Expr(expr).str(), vet.file, expr.pos)\n\t\t\t}\n\t\t}\n\t\tast.StringInterLiteral {\n\t\t\tvt.save_expr(stringinterliteral_cutoff, ast.Expr(expr).str(), vet.file, expr.pos)\n\t\t}\n\t\telse {}\n\t}\n}\n\n// long_or_empty_fns checks for long or empty functions\nfn (mut vt VetAnalyze) long_or_empty_fns(mut vet Vet, fn_decl ast.FnDecl) {\n\tnr_lines := fn_decl.end_pos.line_nr - fn_decl.pos.line_nr - 2\n\tif nr_lines > long_fns_cutoff {\n\t\tvet.notice('Long function - ${nr_lines} lines long.', fn_decl.pos.line_nr, .long_fns)\n\t} else if nr_lines == 0 {\n\t\tvet.notice('Empty function.', fn_decl.pos.line_nr, .empty_fn)\n\t}\n}\n\n// potential_non_inlined checks for potential fns to be inlined\nfn (mut vt VetAnalyze) potential_non_inlined(mut vet Vet, fn_decl ast.FnDecl) {\n\tnr_lines := fn_decl.end_pos.line_nr - fn_decl.pos.line_nr - 2\n\tif nr_lines < short_fns_cutoff {\n\t\tattr := fn_decl.attrs.find_first('inline')\n\t\tif attr == none {\n\t\t\tlock vt.potential_non_inlined {\n\t\t\t\tvt.potential_non_inlined[fn_decl.fkey()][vet.file] = fn_decl.pos\n\t\t\t}\n\t\t}\n\t}\n}\n\n// vet_fn_analysis reports repeated code by scope\nfn (mut vt VetAnalyze) vet_repeated_code(mut vet Vet) {\n\trlock vt.repeated_expr {\n\t\tfor fn_name, ref_expr in vt.repeated_expr {\n\t\t\tscope_name := if fn_name == '' { 'global scope' } else { 'function scope (${fn_name})' }\n\t\t\tfor expr, info in ref_expr {\n\t\t\t\toccurrences := arrays.sum(info.values().map(it.len)) or { 0 }\n\t\t\t\tif occurrences < vt.repeated_expr_cutoff[expr] {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tfor file, info_pos in info {\n\t\t\t\t\tfor k, pos in info_pos {\n\t\t\t\t\t\tvet.notice_with_file(file, '${expr} occurs ${k + 1}/${occurrences} times in ${scope_name}.',\n\t\t\t\t\t\t\tpos.line_nr, .repeated_code)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// vet_inlining_fn reports possible fn to be inlined\nfn (mut vt VetAnalyze) vet_inlining_fn(mut vet Vet) {\n\tfor fn_name, info in vt.potential_non_inlined {\n\t\tfor file, pos in info {\n\t\t\tcalls := vt.call_counter[fn_name] or { 0 }\n\t\t\tif calls < fns_call_cutoff {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tvet.notice_with_file(file, '${fn_name.all_after('.')} fn might be inlined (possibly called at least ${calls} times)',\n\t\t\t\tpos.line_nr, .inline_fn)\n\t\t}\n\t}\n}\n\n// vet_code_analyze performs code analysis\nfn (mut vt Vet) vet_code_analyze() {\n\tif vt.opt.repeated_code {\n\t\tvt.analyze.vet_repeated_code(mut vt)\n\t}\n\tif vt.opt.fn_inlining {\n\t\tvt.analyze.vet_inlining_fn(mut vt)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vvet/errors.v",
    "content": "// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.\n// Use of this source code is governed by an MIT license that can be found in the LICENSE file.\nimport v.token\nimport term\n\npub enum ErrorKind {\n\terror\n\twarning\n\tnotice\n}\n\npub enum FixKind {\n\tunknown\n\tdoc\n\tvfmt\n\trepeated_code\n\tlong_fns\n\tempty_fn\n\tinline_fn\n}\n\n// ErrorType is used to filter out false positive errors under specific conditions\npub enum ErrorType {\n\tdefault\n\tspace_indent\n\ttrailing_space\n}\n\n@[minify]\npub struct VetError {\npub mut:\n\tkind ErrorKind @[required]\npub:\n\t// General message\n\tmessage   string @[required]\n\tdetails   string    // Details about how to resolve or fix the situation\n\tfile_path string    // file where the error have origin\n\tpos       token.Pos // position in the file\n\tfix       FixKind   @[required]\n\ttyp       ErrorType @[required]\n}\n\nfn (mut vt Vet) error(msg string, line int, fix FixKind) {\n\tpos := token.Pos{\n\t\tline_nr: line + 1\n\t}\n\tlock vt.errors {\n\t\tvt.errors << VetError{\n\t\t\tmessage:   msg\n\t\t\tfile_path: vt.file\n\t\t\tpos:       pos\n\t\t\tkind:      .error\n\t\t\tfix:       fix\n\t\t\ttyp:       .default\n\t\t}\n\t}\n}\n\nfn (mut vt Vet) warn(msg string, line int, fix FixKind) {\n\tpos := token.Pos{\n\t\tline_nr: line + 1\n\t}\n\tmut w := VetError{\n\t\tmessage:   msg\n\t\tfile_path: vt.file\n\t\tpos:       pos\n\t\tkind:      .warning\n\t\tfix:       fix\n\t\ttyp:       .default\n\t}\n\tif vt.opt.is_werror {\n\t\tw.kind = .error\n\t\tlock vt.errors {\n\t\t\tvt.errors << w\n\t\t}\n\t} else {\n\t\tlock vt.warns {\n\t\t\tvt.warns << w\n\t\t}\n\t}\n}\n\nfn (mut vt Vet) notice(msg string, line int, fix FixKind) {\n\tpos := token.Pos{\n\t\tline_nr: line + 1\n\t}\n\tlock vt.notices {\n\t\tvt.notices << VetError{\n\t\t\tmessage:   msg\n\t\t\tfile_path: vt.file\n\t\t\tpos:       pos\n\t\t\tkind:      .notice\n\t\t\tfix:       fix\n\t\t\ttyp:       .default\n\t\t}\n\t}\n}\n\nfn (mut vt Vet) notice_with_file(file string, msg string, line int, fix FixKind) {\n\tpos := token.Pos{\n\t\tline_nr: line + 1\n\t}\n\tlock vt.notices {\n\t\tvt.notices << VetError{\n\t\t\tmessage:   msg\n\t\t\tfile_path: file\n\t\t\tpos:       pos\n\t\t\tkind:      .notice\n\t\t\tfix:       fix\n\t\t\ttyp:       .default\n\t\t}\n\t}\n}\n\nfn (vt &Vet) e2string(err VetError) string {\n\tmut kind := '${err.kind}:'\n\tmut location := '${err.file_path}:${err.pos.line_nr}:'\n\tif vt.opt.use_color {\n\t\tkind = term.bold(match err.kind {\n\t\t\t.warning { term.magenta(kind) }\n\t\t\t.error { term.red(kind) }\n\t\t\t.notice { term.yellow(kind) }\n\t\t})\n\t\tlocation = term.bold(location)\n\t}\n\treturn '${location} ${kind} ${err.message}'\n}\n"
  },
  {
    "path": "cmd/tools/vvet/filter.v",
    "content": "module main\n\nimport v.token\n\ntype FilteredLines = map[ErrorType]map[int]bool\n\nfn (mut fl FilteredLines) comments(is_multi bool, pos token.Pos) {\n\tif !is_multi {\n\t\treturn\n\t}\n\tfor ln in pos.line_nr + 1 .. pos.last_line + 1 {\n\t\tfl[.space_indent][ln] = true\n\t}\n}\n\nfn (mut fl FilteredLines) assigns(pos token.Pos) {\n\tif pos.line_nr == pos.last_line {\n\t\treturn\n\t}\n\tfor ln in pos.line_nr + 1 .. pos.last_line {\n\t\tfl[.trailing_space][ln] = true\n\t\tfl[.space_indent][ln] = true\n\t}\n\tfl[.trailing_space][pos.line_nr] = true\n\tfl[.space_indent][pos.last_line] = true\n}\n"
  },
  {
    "path": "cmd/tools/vvet/tests/accept_multi_expression_with_comments.out",
    "content": ""
  },
  {
    "path": "cmd/tools/vvet/tests/accept_multi_expression_with_comments.vv",
    "content": "fn abc() int {\n\treturn if true {\n\t\t0x4000 // 16KB\n\t} else {\n\t\t0x1000 // 4KB\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vvet/tests/array_init_one_val.out",
    "content": "cmd/tools/vvet/tests/array_init_one_val.vv:2: error: Use `1 == 1` instead of `1 in [1]`\ncmd/tools/vvet/tests/array_init_one_val.vv:6: error: Use `'foo' != bar` instead of `'foo' !in [bar]`\nNote: You can run `v fmt -w cmd/tools/vvet/tests/array_init_one_val.vv` to fix these errors automatically\n"
  },
  {
    "path": "cmd/tools/vvet/tests/array_init_one_val.vv",
    "content": "fn main() {\n\tif 1 in [1] {\n\t\tprintln('hello world')\n\t}\n\tbar := 'bar'\n\tif 'foo' !in [bar] {\n\t\tprintln('hello world')\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vvet/tests/brackets_in_documentation_comment_no_warn.out",
    "content": ""
  },
  {
    "path": "cmd/tools/vvet/tests/brackets_in_documentation_comment_no_warn.vv",
    "content": "\n// normalize_vector Normalizes a vector\n//\n// Example:\n// ```v\n// vector := Vector{3, 4}\n// normalize_vector(vector) // Vector{0.6, 0.8}\n// ```\npub fn normalize_vector(vector f32) {}\n"
  },
  {
    "path": "cmd/tools/vvet/tests/const_dynamic_array_notice.out",
    "content": "cmd/tools/vvet/tests/const_dynamic_array_notice.vv:1: notice: Use a fixed array instead of a dynamic one\n"
  },
  {
    "path": "cmd/tools/vvet/tests/const_dynamic_array_notice.vv",
    "content": "const a = [1, 2, 3]\n"
  },
  {
    "path": "cmd/tools/vvet/tests/documentation_for_generic_methods.out",
    "content": ""
  },
  {
    "path": "cmd/tools/vvet/tests/documentation_for_generic_methods.vv",
    "content": "// my_generic_method this is a documentation of my method\npub fn my_generic_method[T](value T) {}\n"
  },
  {
    "path": "cmd/tools/vvet/tests/empty_fn_decl.out",
    "content": "cmd/tools/vvet/tests/empty_fn_decl.vv:2: notice: Empty function.\n"
  },
  {
    "path": "cmd/tools/vvet/tests/empty_fn_decl.vv",
    "content": "// vtest vflags: -F\nfn foo() {\n}\n"
  },
  {
    "path": "cmd/tools/vvet/tests/empty_string.out",
    "content": "cmd/tools/vvet/tests/empty_string.vv:3: notice: Use `foo == ''` instead of `foo.len < 1`\ncmd/tools/vvet/tests/empty_string.vv:4: notice: Use `foo != ''` instead of `foo.len > 0`\ncmd/tools/vvet/tests/empty_string.vv:4: notice: Use `foo == ''` instead of `foo.len == 0`\ncmd/tools/vvet/tests/empty_string.vv:4: notice: Use `foo != ''` instead of `foo.len != 0`\ncmd/tools/vvet/tests/empty_string.vv:7: notice: Use `'' == bar` instead of `1 > bar.len`\ncmd/tools/vvet/tests/empty_string.vv:8: notice: Use `'' != bar` instead of `0 < bar.len`\ncmd/tools/vvet/tests/empty_string.vv:8: notice: Use `'' == bar` instead of `0 == bar.len`\ncmd/tools/vvet/tests/empty_string.vv:8: notice: Use `'' != bar` instead of `0 != bar.len`\ncmd/tools/vvet/tests/empty_string.vv:10: notice: Use `foo == ''` instead of `foo.len < 1`\ncmd/tools/vvet/tests/empty_string.vv:10: notice: Use `bar != ''` instead of `bar.len > 0`\ncmd/tools/vvet/tests/empty_string.vv:10: notice: Use `foo == ''` instead of `foo.len == 0`\ncmd/tools/vvet/tests/empty_string.vv:10: notice: Use `bar == ''` instead of `bar.len == 0`\n"
  },
  {
    "path": "cmd/tools/vvet/tests/empty_string.vv",
    "content": "fn main() {\n\tfoo := 'foo'\n\t_ := foo.len < 1\n\t_ := foo.len > 0 || foo.len == 0 || foo.len != 0\n\n\tbar := 'bar'\n\t_ := 1 > bar.len\n\t_ := 0 < bar.len || 0 == bar.len || 0 != bar.len\n\n\tif foo.len < 1 || bar.len > 0 || (foo.len == 0 && bar.len == 0) {\n\t}\n\n\t// Should not notify when `.len` is used with other types.\n\tbaz := ['baz']\n\t_ := baz.len == 0\n\n\tfoobar := {\n\t\t'foo': 'bar'\n\t}\n\t_ := foobar.len < 1\n}\n"
  },
  {
    "path": "cmd/tools/vvet/tests/indent_with_space.out",
    "content": "cmd/tools/vvet/tests/indent_with_space.vv:2: error: Looks like you are using spaces for indentation.\ncmd/tools/vvet/tests/indent_with_space.vv:10: error: Looks like you are using spaces for indentation.\ncmd/tools/vvet/tests/indent_with_space.vv:17: error: Looks like you are using spaces for indentation.\ncmd/tools/vvet/tests/indent_with_space.vv:20: error: Looks like you are using spaces for indentation.\ncmd/tools/vvet/tests/indent_with_space.vv:22: error: Looks like you are using spaces for indentation.\nNote: You can run `v fmt -w cmd/tools/vvet/tests/indent_with_space.vv` to fix these errors automatically"
  },
  {
    "path": "cmd/tools/vvet/tests/indent_with_space.vv",
    "content": "fn main() {\n    _ = 1 == 2\n}\n\nfn block_comments() {\n\t/* tab to indent the comment\n  spaces before\n  also spaces before\n  same here */\n  /* spaces for comment indentation (ouch)\n  and inside too\n  */\n}\n\nfn space_inside_strings() {\n\t// Plain strings\n  str := \"Bad space usage for variable indentation.\n  Here it's fine.\n  Here too.\"\n  str2 := 'linebreak and space\\n  inside'\n\t// String interpolation\n  si1 := 'Error here ${foo}\n  and not here'\n}\n"
  },
  {
    "path": "cmd/tools/vvet/tests/module_file_test.out",
    "content": "cmd/tools/vvet/tests/module_file_test.vv:7: warning: Function documentation seems to be missing for \"pub fn foo() string\".\ncmd/tools/vvet/tests/module_file_test.vv:13: warning: A function name is missing from the documentation of \"pub fn bar() string\".\ncmd/tools/vvet/tests/module_file_test.vv:35: warning: Function documentation seems to be missing for \"pub fn (f Foo) foo() string\".\ncmd/tools/vvet/tests/module_file_test.vv:46: warning: A function name is missing from the documentation of \"pub fn (f Foo) fooo() string\".\ncmd/tools/vvet/tests/module_file_test.vv:52: warning: The documentation for \"pub fn (f Foo) boo() string\" seems incomplete."
  },
  {
    "path": "cmd/tools/vvet/tests/module_file_test.vv",
    "content": "module foo\n\nstruct Foo {\n\tfoo int\n}\n\npub fn foo() string {\n\t// Missing doc\n\treturn 'foo'\n}\n\n// foo does bar\npub fn bar() string {\n\t// not using convention style: '// <fn name>'\n\treturn 'bar'\n}\n\n// fooo does x\npub fn fooo() string {\n\t// Documented\n\treturn 'fooo'\n}\n\n// booo does x\nfn booo() string {\n\t// Documented, but not pub\n\treturn 'booo'\n}\n\nfn boo() string {\n\t// Missing doc\n\treturn 'boo'\n}\n\npub fn (f Foo) foo() string {\n\t// Missing doc\n\treturn f.fo()\n}\n\nfn (f Foo) fo() string {\n\t// Missing doc, but not pub\n\treturn 'foo'\n}\n\n// wrong doc\npub fn (f Foo) fooo() string {\n\t// not using convention\n\treturn f.fo()\n}\n\n// boo\npub fn (f Foo) boo() string {\n\t// Incomplete doc\n\treturn f.fo()\n}\n"
  },
  {
    "path": "cmd/tools/vvet/tests/no_warn_about_missing.out",
    "content": ""
  },
  {
    "path": "cmd/tools/vvet/tests/no_warn_about_missing.vv",
    "content": "// Some header comment\n\n// read_response is a carefully constructed comment.\n// read_response_body. <-- this would earlier trigger a false\n// positive.\npub fn read_response() ?(string, string) {}\n"
  },
  {
    "path": "cmd/tools/vvet/tests/prog_without_main_fn.out",
    "content": "cmd/tools/vvet/tests/prog_without_main_fn.vv:1: notice: Use a fixed array instead of a dynamic one\n"
  },
  {
    "path": "cmd/tools/vvet/tests/prog_without_main_fn.vv",
    "content": "const x = [1, 2, 3]\n\nprintln(x)\n"
  },
  {
    "path": "cmd/tools/vvet/tests/repeated_assign.out",
    "content": "cmd/tools/vvet/tests/repeated_assign.vv:4: notice: a += 'foo' occurs 1/11 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_assign.vv:5: notice: a += 'foo' occurs 2/11 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_assign.vv:6: notice: a += 'foo' occurs 3/11 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_assign.vv:7: notice: a += 'foo' occurs 4/11 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_assign.vv:8: notice: a += 'foo' occurs 5/11 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_assign.vv:9: notice: a += 'foo' occurs 6/11 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_assign.vv:10: notice: a += 'foo' occurs 7/11 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_assign.vv:11: notice: a += 'foo' occurs 8/11 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_assign.vv:12: notice: a += 'foo' occurs 9/11 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_assign.vv:13: notice: a += 'foo' occurs 10/11 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_assign.vv:14: notice: a += 'foo' occurs 11/11 times in function scope (main.main).\n"
  },
  {
    "path": "cmd/tools/vvet/tests/repeated_assign.vv",
    "content": "// vtest vflags: -r\nfn main() {\n\tmut a := ''\n\ta += 'foo'\n\ta += 'foo'\n\ta += 'foo'\n\ta += 'foo'\n\ta += 'foo'\n\ta += 'foo'\n\ta += 'foo'\n\ta += 'foo'\n\ta += 'foo'\n\ta += 'foo'\n\ta += 'foo'\n}\n"
  },
  {
    "path": "cmd/tools/vvet/tests/repeated_code.out",
    "content": "cmd/tools/vvet/tests/repeated_code.vv:4: notice: a[0] occurs 1/12 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_code.vv:5: notice: a[0] occurs 2/12 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_code.vv:6: notice: a[0] occurs 3/12 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_code.vv:6: notice: a[0] occurs 4/12 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_code.vv:7: notice: a[0] occurs 5/12 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_code.vv:8: notice: a[0] occurs 6/12 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_code.vv:9: notice: a[0] occurs 7/12 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_code.vv:9: notice: a[0] occurs 8/12 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_code.vv:11: notice: a[0] occurs 9/12 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_code.vv:12: notice: a[0] occurs 10/12 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_code.vv:13: notice: a[0] occurs 11/12 times in function scope (main.main).\ncmd/tools/vvet/tests/repeated_code.vv:13: notice: a[0] occurs 12/12 times in function scope (main.main).\n"
  },
  {
    "path": "cmd/tools/vvet/tests/repeated_code.vv",
    "content": "// vtest vflags: -r\nfn main() {\n\tmut a := [0, 2, 4, 6]\n\tif a[0] {\n\t\tdump(a[0])\n\t\tdump(a[0] + a[0])\n\t\tif a[0] {\n\t\t\tdump(a[0])\n\t\t\tdump(a[0] + a[0])\n\t\t}\n\t\tif a[0] {\n\t\t\tdump(a[0])\n\t\t\tdump(a[0] + a[0])\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vvet/tests/trailing_space.out",
    "content": "cmd/tools/vvet/tests/trailing_space.vv:5: error: Looks like you have trailing whitespace.\ncmd/tools/vvet/tests/trailing_space.vv:6: error: Looks like you have trailing whitespace.\ncmd/tools/vvet/tests/trailing_space.vv:7: error: Looks like you have trailing whitespace.\ncmd/tools/vvet/tests/trailing_space.vv:8: error: Looks like you have trailing whitespace.\ncmd/tools/vvet/tests/trailing_space.vv:9: error: Looks like you have trailing whitespace.\ncmd/tools/vvet/tests/trailing_space.vv:13: error: Looks like you have trailing whitespace.\ncmd/tools/vvet/tests/trailing_space.vv:15: error: Looks like you have trailing whitespace.\n"
  },
  {
    "path": "cmd/tools/vvet/tests/trailing_space.vv",
    "content": "// NB: This file has and *should* have trailing spaces.\n// When making changes, please ensure they are not removed.\n\nfn after_comments() {\n\t// spaces after line comments give errors  \n\t/*  \n\tin block comments  \n\ttoo  \n\t*/  \n}\n\nfn main() {\n\tvar := 'error about the spaces right there'  \n\tno_err := \"inside multi line strings it's fine.  \nbut not after\"  \n}\n"
  },
  {
    "path": "cmd/tools/vvet/vet_test.v",
    "content": "import os\nimport term\nimport v.util.vtest\nimport v.util.diff\n\nstruct FileOptions {\nmut:\n\tvflags string\n}\n\nfn get_file_options(file string) FileOptions {\n\tmut res := FileOptions{}\n\tlines := os.read_lines(file) or { [] }\n\tfor line in lines {\n\t\tif line.starts_with('// vtest vflags:') {\n\t\t\tres.vflags = line.all_after(':').trim_space()\n\t\t}\n\t}\n\treturn res\n}\n\nfn test_vet() {\n\tvexe := os.getenv('VEXE')\n\tvroot := os.dir(vexe)\n\tos.chdir(vroot)!\n\ttest_dir := 'cmd/tools/vvet/tests'\n\ttests := get_tests_in_dir(test_dir)\n\tfails := check_path(vexe, test_dir, tests)\n\tassert fails == 0\n}\n\nfn get_tests_in_dir(dir string) []string {\n\tfiles := os.ls(dir) or { panic(err) }\n\tmut tests := files.filter(it.ends_with('.vv'))\n\ttests.sort()\n\treturn tests\n}\n\nfn check_path(vexe string, dir string, tests []string) int {\n\tmut nb_fail := 0\n\tpaths := vtest.filter_vtest_only(tests, basepath: dir)\n\tfor path in paths {\n\t\tprogram := path\n\t\tprint(path + ' ')\n\t\tfile_options := get_file_options(path)\n\t\tres := os.execute('${os.quoted_path(vexe)} vet -nocolor ${file_options.vflags} ${os.quoted_path(program)}')\n\t\tif res.exit_code < 0 {\n\t\t\tpanic(res.output)\n\t\t}\n\t\tmut expected := os.read_file(program.replace('.vv', '') + '.out') or { panic(err) }\n\t\texpected = clean_line_endings(expected)\n\t\tfound := clean_line_endings(res.output)\n\t\tif expected != found {\n\t\t\tprintln(term.red('FAIL'))\n\t\t\tprintln('============')\n\t\t\tif diff_ := diff.compare_text(expected, found) {\n\t\t\t\tprintln('diff:')\n\t\t\t\tprintln(diff_)\n\t\t\t} else {\n\t\t\t\tprintln('expected:')\n\t\t\t\tprintln(expected)\n\t\t\t\tprintln('============')\n\t\t\t\tprintln('found:')\n\t\t\t\tprintln(found)\n\t\t\t}\n\t\t\tprintln('============\\n')\n\t\t\tnb_fail++\n\t\t} else {\n\t\t\tprintln(term.green('OK'))\n\t\t}\n\t}\n\treturn nb_fail\n}\n\nfn clean_line_endings(s string) string {\n\tmut res := s.trim_space()\n\tres = res.replace(' \\n', '\\n')\n\tres = res.replace(' \\r\\n', '\\n')\n\tres = res.replace('\\r\\n', '\\n')\n\tres = res.trim('\\n')\n\treturn res\n}\n"
  },
  {
    "path": "cmd/tools/vvet/vvet.v",
    "content": "// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.\n// Use of this source code is governed by an MIT license that can be found in the LICENSE file.\nmodule main\n\nimport os\nimport os.cmdline\nimport v.pref\nimport v.parser\nimport v.ast\nimport v.help\nimport term\nimport arrays\n\n@[heap]\nstruct Vet {\nmut:\n\topt            Options\n\terrors         shared []VetError\n\twarns          shared []VetError\n\tnotices        shared []VetError\n\tfile           string\n\tfiltered_lines FilteredLines\n\tanalyze        VetAnalyze\n}\n\nstruct Options {\n\tis_force            bool\n\tis_werror           bool\n\tis_verbose          bool\n\tshow_warnings       bool\n\tuse_color           bool\n\tdoc_private_fns_too bool\n\tfn_sizing           bool\n\trepeated_code       bool\n\tfn_inlining         bool\nmut:\n\tis_vfmt_off bool\n}\n\nconst term_colors = term.can_show_color_on_stderr()\nconst clean_seq = ['[', '', ']', '', ' ', '']\nconst exclude_dirs = ['test', 'slow_test', 'testdata']\n\nfn main() {\n\tvet_options := cmdline.options_after(os.args, ['vet'])\n\tmut vt := Vet{\n\t\topt: Options{\n\t\t\tis_werror:           '-W' in vet_options\n\t\t\tis_verbose:          '-verbose' in vet_options || '-v' in vet_options\n\t\t\tshow_warnings:       '-hide-warnings' !in vet_options && '-w' !in vet_options\n\t\t\tdoc_private_fns_too: '-p' in vet_options\n\t\t\tuse_color:           '-color' in vet_options\n\t\t\t\t|| (term_colors && '-nocolor' !in vet_options)\n\t\t\trepeated_code:       '-r' in vet_options\n\t\t\tfn_sizing:           '-F' in vet_options\n\t\t\tfn_inlining:         '-I' in vet_options\n\t\t}\n\t}\n\tmut paths := cmdline.only_non_options(vet_options)\n\tvtmp := os.getenv('VTMP')\n\tif vtmp != '' {\n\t\t// `v test-cleancode` passes also `-o tmpfolder` as well as all options in VFLAGS\n\t\tpaths = paths.filter(!it.starts_with(vtmp))\n\t}\n\tif paths.len == 0 || '-help' in vet_options || '--help' in vet_options {\n\t\thelp.print_and_exit('vet')\n\t}\n\tfor path in paths {\n\t\tif !os.exists(path) {\n\t\t\teprintln('File/folder ${path} does not exist')\n\t\t\tcontinue\n\t\t}\n\t\tif os.is_file(path) {\n\t\t\tvt.vet_file(path)\n\t\t}\n\t\tif os.is_dir(path) {\n\t\t\tvt.vprintln(\"vetting folder: '${path}' ...\")\n\t\t\toverwrite_exclude := exclude_dirs.any(path.contains(it))\n\t\t\tos.walk(path, fn [mut vt, overwrite_exclude] (p string) {\n\t\t\t\tif p.ends_with('.v') || p.ends_with('.vv') {\n\t\t\t\t\tif !overwrite_exclude {\n\t\t\t\t\t\tfor d in exclude_dirs {\n\t\t\t\t\t\t\tif p.contains(d) {\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tvt.vet_file(p)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t}\n\tvt.vet_code_analyze()\n\tvfmt_err_count := vt.errors.filter(it.fix == .vfmt).len\n\tfor n in vt.notices {\n\t\teprintln(vt.e2string(n))\n\t}\n\tif vt.opt.show_warnings {\n\t\tfor w in vt.warns {\n\t\t\teprintln(vt.e2string(w))\n\t\t}\n\t}\n\tfor err in vt.errors {\n\t\teprintln(vt.e2string(err))\n\t}\n\tif vfmt_err_count > 0 {\n\t\trlock vt.errors {\n\t\t\tfiltered_out := arrays.distinct(vt.errors.map(it.file_path))\n\t\t\teprintln('Note: You can run `v fmt -w ${filtered_out.join(' ')}` to fix these errors automatically')\n\t\t}\n\t}\n\tif vt.errors.len > 0 {\n\t\texit(1)\n\t}\n}\n\n// vet_file vets the file read from `path`.\nfn (mut vt Vet) vet_file(path string) {\n\tvt.file = path\n\tmut prefs := pref.new_preferences()\n\tprefs.is_vet = true\n\tprefs.is_vsh = path.ends_with('.vsh')\n\tmut table := ast.new_table()\n\tvt.vprintln(\"vetting file '${path}'...\")\n\tfile := parser.parse_file(path, mut table, .parse_comments, prefs)\n\tvt.stmts(file.stmts)\n\tsource_lines := os.read_lines(vt.file) or { []string{} }\n\tfor ln, line in source_lines {\n\t\tvt.vet_line(source_lines, line, ln)\n\t}\n}\n\n// vet_line vets the contents of `line` from `vet.file`.\nfn (mut vt Vet) vet_line(lines []string, line string, lnumber int) {\n\tif line == '' {\n\t\treturn\n\t}\n\tvt.vet_fn_documentation(lines, line, lnumber)\n\tvt.vet_space_usage(line, lnumber)\n}\n\nfn (mut vt Vet) vet_space_usage(line string, lnumber int) {\n\tif line.starts_with('// vfmt off') {\n\t\tvt.opt.is_vfmt_off = true\n\t} else if line.starts_with('// vfmt on') {\n\t\tvt.opt.is_vfmt_off = false\n\t}\n\tif vt.opt.is_vfmt_off {\n\t\treturn\n\t}\n\tif lnumber !in vt.filtered_lines[.space_indent] {\n\t\tif line.starts_with(' ') {\n\t\t\tvt.error('Looks like you are using spaces for indentation.', lnumber, .vfmt)\n\t\t}\n\t}\n\tif lnumber !in vt.filtered_lines[.trailing_space] {\n\t\tif line.ends_with(' ') {\n\t\t\tvt.error('Looks like you have trailing whitespace.', lnumber, .unknown)\n\t\t}\n\t}\n}\n\nfn collect_tags(line string) []string {\n\tmut cleaned := line.all_before('/')\n\tcleaned = cleaned.replace_each(clean_seq)\n\treturn cleaned.split(',')\n}\n\nfn ident_fn_name(line string) string {\n\tmut fn_idx := line.index(' fn ') or { return '' }\n\tif line.len < fn_idx + 5 {\n\t\treturn ''\n\t}\n\tmut tokens := line[fn_idx + 4..].split(' ')\n\t// Skip struct identifier\n\tif tokens.first().starts_with('(') {\n\t\tfn_idx = line.index(')') or { return '' }\n\t\ttokens = line[fn_idx..].split(' ')\n\t\tif tokens.len > 1 {\n\t\t\ttokens = [tokens[1]]\n\t\t}\n\t}\n\tif tokens.len > 0 {\n\t\tfunction_name_with_generic_parameters := tokens[0].all_before('(')\n\t\treturn function_name_with_generic_parameters.all_before('[')\n\t}\n\treturn ''\n}\n\n// vet_fn_documentation ensures that functions are documented\nfn (mut vt Vet) vet_fn_documentation(lines []string, line string, lnumber int) {\n\tif line.starts_with('fn C.') {\n\t\treturn\n\t}\n\tis_pub_fn := line.starts_with('pub fn ')\n\tis_fn := is_pub_fn || line.starts_with('fn ')\n\tif !is_fn {\n\t\treturn\n\t}\n\tif line.starts_with('fn main') {\n\t\treturn\n\t}\n\tif !(is_pub_fn || vt.opt.doc_private_fns_too) {\n\t\treturn\n\t}\n\t// Scan function declarations for missing documentation\n\tmut line_above := lines[lnumber - 1] or { return }\n\tmut tags := []string{}\n\tif !line_above.starts_with('//') {\n\t\tmut grab := true\n\t\tfor j := lnumber - 1; j >= 0; j-- {\n\t\t\tprev_line := lines[j]\n\t\t\tif prev_line.contains('}') { // We've looked back to the above scope, stop here\n\t\t\t\tbreak\n\t\t\t} else if prev_line.starts_with('@[') {\n\t\t\t\ttags << collect_tags(prev_line)\n\t\t\t\tcontinue\n\t\t\t} else if prev_line.starts_with('//') { // Single-line comment\n\t\t\t\tgrab = false\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif grab {\n\t\t\tclean_line := line.all_before_last('{').trim(' ')\n\t\t\tvt.warn('Function documentation seems to be missing for \"${clean_line}\".',\n\t\t\t\tlnumber, .doc)\n\t\t}\n\t} else {\n\t\tfn_name := ident_fn_name(line)\n\t\tmut grab := true\n\t\tfor j := lnumber - 1; j >= 0; j-- {\n\t\t\tmut prev_prev_line := ''\n\t\t\tif j - 1 >= 0 {\n\t\t\t\tprev_prev_line = lines[j - 1]\n\t\t\t}\n\t\t\tprev_line := lines[j]\n\n\t\t\tif prev_line.starts_with('//') {\n\t\t\t\tif prev_line.starts_with('// ${fn_name} ') {\n\t\t\t\t\tgrab = false\n\t\t\t\t\tbreak\n\t\t\t\t} else if prev_line.starts_with('// ${fn_name}')\n\t\t\t\t\t&& !prev_prev_line.starts_with('//') {\n\t\t\t\t\tgrab = false\n\t\t\t\t\tclean_line := line.all_before_last('{').trim(' ')\n\t\t\t\t\tvt.warn('The documentation for \"${clean_line}\" seems incomplete.',\n\t\t\t\t\t\tlnumber, .doc)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif prev_line.contains('}') { // We've looked back to the above scope, stop here\n\t\t\t\tbreak\n\t\t\t} else if prev_line.starts_with('@[') {\n\t\t\t\ttags << collect_tags(prev_line)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tif grab {\n\t\t\tclean_line := line.all_before_last('{').trim(' ')\n\t\t\tvt.warn('A function name is missing from the documentation of \"${clean_line}\".',\n\t\t\t\tlnumber, .doc)\n\t\t}\n\t}\n}\n\nfn (mut vt Vet) stmts(stmts []ast.Stmt) {\n\tfor stmt in stmts {\n\t\tvt.stmt(stmt)\n\t}\n}\n\nfn (mut vt Vet) stmt(stmt ast.Stmt) {\n\tmatch stmt {\n\t\tast.ConstDecl {\n\t\t\tvt.const_decl(stmt)\n\t\t}\n\t\tast.ExprStmt {\n\t\t\tvt.expr(stmt.expr)\n\t\t}\n\t\tast.Return {\n\t\t\tvt.exprs(stmt.exprs)\n\t\t}\n\t\tast.AssertStmt {\n\t\t\tvt.expr(stmt.expr)\n\t\t}\n\t\tast.AssignStmt {\n\t\t\tvt.exprs(stmt.left)\n\t\t\tvt.exprs(stmt.right)\n\t\t\tvt.analyze.stmt(&vt, stmt)\n\t\t}\n\t\tast.FnDecl {\n\t\t\told_fn_decl := vt.analyze.cur_fn\n\t\t\tvt.analyze.cur_fn = stmt\n\t\t\tvt.stmts(stmt.stmts)\n\t\t\tif vt.opt.fn_sizing {\n\t\t\t\tvt.analyze.long_or_empty_fns(mut vt, stmt)\n\t\t\t}\n\t\t\tif vt.opt.fn_inlining {\n\t\t\t\tvt.analyze.potential_non_inlined(mut vt, stmt)\n\t\t\t}\n\t\t\tvt.analyze.cur_fn = old_fn_decl\n\t\t}\n\t\tast.StructDecl {\n\t\t\tvt.exprs(stmt.fields.map(it.default_expr))\n\t\t}\n\t\telse {}\n\t}\n}\n\nfn (mut vt Vet) exprs(exprs []ast.Expr) {\n\tfor expr in exprs {\n\t\tvt.expr(expr)\n\t}\n}\n\nfn (mut vt Vet) expr(expr ast.Expr) {\n\tmatch expr {\n\t\tast.Comment {\n\t\t\tvt.filtered_lines.comments(expr.is_multi, expr.pos)\n\t\t}\n\t\tast.StringLiteral {\n\t\t\tvt.filtered_lines.assigns(expr.pos)\n\t\t\tvt.analyze.expr(&vt, expr)\n\t\t}\n\t\tast.StringInterLiteral {\n\t\t\tvt.filtered_lines.assigns(expr.pos)\n\t\t\tvt.analyze.expr(&vt, expr)\n\t\t}\n\t\tast.ArrayInit {\n\t\t\tvt.filtered_lines.assigns(expr.pos)\n\t\t\tvt.expr(expr.len_expr)\n\t\t\tvt.expr(expr.cap_expr)\n\t\t\tvt.expr(expr.init_expr)\n\t\t\tvt.exprs(expr.exprs)\n\t\t}\n\t\tast.InfixExpr {\n\t\t\tvt.vet_in_condition(expr)\n\t\t\tvt.vet_empty_str(expr)\n\t\t\tvt.expr(expr.left)\n\t\t\tvt.expr(expr.right)\n\t\t\tvt.analyze.expr(&vt, expr)\n\t\t}\n\t\tast.ParExpr {\n\t\t\tvt.expr(expr.expr)\n\t\t}\n\t\tast.CallExpr {\n\t\t\tvt.expr(expr.left)\n\t\t\tvt.exprs(expr.args.map(it.expr))\n\t\t\tvt.analyze.expr(&vt, expr)\n\t\t}\n\t\tast.MatchExpr {\n\t\t\tvt.expr(expr.cond)\n\t\t\tfor b in expr.branches {\n\t\t\t\tvt.exprs(b.exprs)\n\t\t\t\tvt.stmts(b.stmts)\n\t\t\t}\n\t\t}\n\t\tast.IfExpr {\n\t\t\tfor b in expr.branches {\n\t\t\t\tvt.expr(b.cond)\n\t\t\t\tvt.stmts(b.stmts)\n\t\t\t}\n\t\t}\n\t\tast.SelectorExpr {\n\t\t\tvt.analyze.expr(&vt, expr)\n\t\t}\n\t\tast.IndexExpr {\n\t\t\tvt.analyze.expr(&vt, expr)\n\t\t}\n\t\tast.AsCast {\n\t\t\tvt.analyze.expr(&vt, expr)\n\t\t\tvt.expr(expr.expr)\n\t\t}\n\t\tast.UnsafeExpr {\n\t\t\tvt.expr(expr.expr)\n\t\t}\n\t\tast.CastExpr {\n\t\t\tvt.expr(expr.expr)\n\t\t}\n\t\tast.StructInit {\n\t\t\tvt.expr(expr.update_expr)\n\t\t\tvt.exprs(expr.init_fields.map(it.expr))\n\t\t}\n\t\tast.DumpExpr {\n\t\t\tvt.expr(expr.expr)\n\t\t}\n\t\telse {}\n\t}\n}\n\nfn (mut vt Vet) const_decl(stmt ast.ConstDecl) {\n\tfor field in stmt.fields {\n\t\tif field.expr is ast.ArrayInit && !field.expr.is_fixed {\n\t\t\tvt.notice('Use a fixed array instead of a dynamic one', field.expr.pos.line_nr,\n\t\t\t\t.unknown)\n\t\t}\n\t\tvt.expr(field.expr)\n\t}\n}\n\nfn (mut vt Vet) vet_empty_str(expr ast.InfixExpr) {\n\tif expr.left is ast.SelectorExpr && expr.right is ast.IntegerLiteral {\n\t\toperand := (expr.left as ast.SelectorExpr) // TODO: remove as-casts when multiple conds can be smart-casted.\n\t\tif operand.expr is ast.Ident && operand.field_name == 'len'\n\t\t\t&& operand.expr.info.typ == ast.string_type_idx {\n\t\t\tif expr.op != .lt && expr.right.val == '0' {\n\t\t\t\t// Case: `var.len > 0`, `var.len == 0`, `var.len != 0`\n\t\t\t\top := if expr.op == .gt { '!=' } else { expr.op.str() }\n\t\t\t\tvt.notice(\"Use `${operand.expr.name} ${op} ''` instead of `${operand.expr.name}.len ${expr.op} 0`\",\n\t\t\t\t\texpr.pos.line_nr, .unknown)\n\t\t\t} else if expr.op == .lt && expr.right.val == '1' {\n\t\t\t\t// Case: `var.len < 1`\n\t\t\t\tvt.notice(\"Use `${operand.expr.name} == ''` instead of `${operand.expr.name}.len ${expr.op} 1`\",\n\t\t\t\t\texpr.pos.line_nr, .unknown)\n\t\t\t}\n\t\t}\n\t} else if expr.left is ast.IntegerLiteral && expr.right is ast.SelectorExpr {\n\t\toperand := expr.right\n\t\tif operand.expr is ast.Ident && operand.expr.info.typ == ast.string_type_idx\n\t\t\t&& operand.field_name == 'len' {\n\t\t\tif expr.op != .gt && (expr.left as ast.IntegerLiteral).val == '0' {\n\t\t\t\t// Case: `0 < var.len`, `0 == var.len`, `0 != var.len`\n\t\t\t\top := if expr.op == .lt { '!=' } else { expr.op.str() }\n\t\t\t\tvt.notice(\"Use `'' ${op} ${operand.expr.name}` instead of `0 ${expr.op} ${operand.expr.name}.len`\",\n\t\t\t\t\texpr.pos.line_nr, .unknown)\n\t\t\t} else if expr.op == .gt && (expr.left as ast.IntegerLiteral).val == '1' {\n\t\t\t\t// Case: `1 > var.len`\n\t\t\t\tvt.notice(\"Use `'' == ${operand.expr.name}` instead of `1 ${expr.op} ${operand.expr.name}.len`\",\n\t\t\t\t\texpr.pos.line_nr, .unknown)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfn (vt &Vet) vprintln(s string) {\n\tif !vt.opt.is_verbose {\n\t\treturn\n\t}\n\tprintln(s)\n}\n\nfn (mut vt Vet) vet_in_condition(expr ast.InfixExpr) {\n\tif expr.right is ast.ArrayInit && expr.right.exprs.len == 1 && expr.op in [.key_in, .not_in] {\n\t\tleft := expr.left.str()\n\t\tright := expr.right.exprs[0].str()\n\t\teq := if expr.op == .key_in { '==' } else { '!=' }\n\t\tvt.error('Use `${left} ${eq} ${right}` instead of `${left} ${expr.op} [${right}]`',\n\t\t\texpr.pos.line_nr, .vfmt)\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vwatch.v",
    "content": "module main\n\nimport os\nimport time\nimport term\nimport flag\n\nconst scan_timeout_s = get_scan_timeout_seconds()\n\nconst max_v_cycles = 1000\n\nconst scan_frequency_hz = 4\n\nconst scan_period_ms = 1000 / scan_frequency_hz\n\nconst max_scan_cycles = scan_timeout_s * scan_frequency_hz\n\nconst default_veb_suffixes = '*.v,*.html,*.css,*.js,*.md,*.tr'\n\nfn get_scan_timeout_seconds() int {\n\tenv_vw_timeout := os.getenv('VWATCH_TIMEOUT').int()\n\tif env_vw_timeout == 0 {\n\t\t$if gcboehm ? {\n\t\t\treturn 35000000 // over 1 year\n\t\t} $else {\n\t\t\treturn 5 * 60\n\t\t}\n\t}\n\treturn env_vw_timeout\n}\n\n//\n// Implements `v watch file.v` , `v watch run file.v` etc.\n// With this command, V will collect all .v files that are needed for the\n// compilation, then it will enter an infinite loop, monitoring them for\n// changes.\n//\n// When a change is detected, it will stop the current process, if it is\n// still running, then rerun/recompile/etc.\n//\n// In effect, this makes it easy to have an editor session and a separate\n// terminal, running just `v watch run file.v`, and you will see your\n// changes right after you save your .v file in your editor.\n//\n//\n//    Since -gc boehm is not available on all platforms yet,\n// and this program leaks ~8MB/minute without it, the implementation here\n// is done similarly to vfmt in 2 modes, in the same executable:\n//\n//   a) A parent/manager process that only manages a single worker\n//   process. The parent process does mostly nothing except restarting\n//   workers, thus it does not leak much.\n//\n//   b) A worker process, doing the actual monitoring/polling.\n//    Note: *workers are started with the --vwatchworker option*\n//\n//    Worker processes will run for a limited number of iterations, then\n// they will do exit(255), and then the parent will start a new worker.\n// Exiting by any other code will cause the parent to also exit with the\n// same error code. This limits the potential leak that a worker process\n// can do, even without using the garbage collection mode.\n//\n\nstruct VFileStat {\n\tpath  string\n\tmtime i64\n}\n\n@[unsafe]\nfn (mut vfs VFileStat) free() {\n\tunsafe { vfs.path.free() }\n}\n\nenum RerunCommand {\n\trestart\n\tquit\n}\n\nstruct Context {\nmut:\n\tpid             int  // the pid of the current process; useful while debugging manager/worker interactions\n\tis_worker       bool // true in the workers, false in the manager process\n\tcheck_period_ms int = scan_period_ms\n\tvexe            string\n\taffected_paths  []string\n\tvfiles          []VFileStat\n\topts            []string\n\trerun_channel   chan RerunCommand\n\tchild_process   &os.Process = unsafe { nil }\n\tis_exiting      bool     // set by SIGINT/Ctrl-C\n\tv_cycles        int      // how many times the worker has restarted the V compiler\n\tscan_cycles     int      // how many times the worker has scanned for source file changes\n\tclear_terminal  bool     // whether to clear the terminal before each re-run\n\tkeep_running    bool     // when true, re-run the program automatically if it exits on its own. Useful for gg apps.\n\tsilent          bool     // when true, watch will not print a timestamp line before each re-run\n\tadd_files       []string // path to additional files that have to be watched for changes\n\tignore_exts     []string // extensions of files that will be ignored, even if they change (useful for sqlite.db files for example)\n\tcmd_before_run  string   // a command to run before each re-run\n\tcmd_after_run   string   // a command to run after each re-run\n\tonly_watch      []string // If not empty, *all* files that trigger updates, should match *at least one* of these s.match_glob() patterns. This is also triggered for vweb apps, to monitor for just *.v,*.js,*.css,*.html in vweb projects.\n}\n\n@[if debug_vwatch ?]\nfn (mut context Context) elog(msg string) {\n\teprintln('> vwatch ${context.pid}, ${msg}')\n}\n\nfn (context &Context) str() string {\n\treturn 'Context{ pid: ${context.pid}, is_worker: ${context.is_worker}, check_period_ms: ${context.check_period_ms}, vexe: ${context.vexe}, opts: ${context.opts}, is_exiting: ${context.is_exiting}, vfiles: ${context.vfiles}'\n}\n\nfn (mut context Context) is_ext_ignored(pf string, pf_ext string) bool {\n\tfor ipattern in context.ignore_exts {\n\t\tif pf_ext.match_glob(ipattern) {\n\t\t\treturn true\n\t\t}\n\t}\n\tif pf_ext in ['', '.so', '.a'] {\n\t\t// on unix, the executables saved by compilers, usually do not have extensions at all, and shared libs are .so\n\t\treturn true\n\t}\n\tif pf_ext in ['.exe', '.dll', '.def'] {\n\t\t// on windows, files with these extensions will be generated by the compiler\n\t\treturn true\n\t}\n\t// ignore common backup files saved by editors like emacs/jed/vim:\n\tif pf_ext == '.bak' {\n\t\treturn true\n\t}\n\t// ignore DB files (sqlite databases, that are likely to change during prototyping):\n\tif pf_ext in ['.db', '.sqlite'] {\n\t\treturn true\n\t}\n\tif pf.starts_with('.#') {\n\t\treturn true\n\t}\n\tif pf.ends_with('~') {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfn (mut context Context) get_stats_for_affected_vfiles() []VFileStat {\n\tif context.affected_paths.len == 0 {\n\t\tmut apaths := map[string]bool{}\n\t\t// The next command will make V parse the program, and print all .v files,\n\t\t// needed for its compilation, without actually compiling it.\n\t\tcopts := context.opts.join(' ')\n\t\tcmd := '\"${context.vexe}\" -silent -print-watched-files ${copts}'\n\t\t// context.elog('> cmd: ${cmd}')\n\t\tmut paths := []string{}\n\t\tif context.add_files.len > 0 && context.add_files[0] != '' {\n\t\t\tpaths << context.add_files\n\t\t}\n\t\tvfiles := os.execute(cmd)\n\t\tif vfiles.exit_code == 0 {\n\t\t\tpaths_trimmed := vfiles.output.trim_space()\n\t\t\treported_used_files := paths_trimmed.split_any('\\n')\n\t\t\t$if trace_reported_used_files ? {\n\t\t\t\tcontext.elog('reported_used_files: ${reported_used_files}')\n\t\t\t}\n\t\t\tpaths << reported_used_files\n\t\t}\n\t\tmut is_vweb_found := false\n\t\tfor vf in paths {\n\t\t\tapaths[os.real_path(os.dir(vf))] = true\n\t\t\tif vf.contains('vweb.v') {\n\t\t\t\tis_vweb_found = true\n\t\t\t}\n\t\t}\n\n\t\tif is_vweb_found {\n\t\t\tif !os.args.any(it.starts_with('--only-watch')) {\n\t\t\t\tcontext.only_watch = default_veb_suffixes.split_any(',')\n\t\t\t\t// vweb is often used with SQLite .db or .sqlite3 files right next to the executable/source,\n\t\t\t\t// that are updated by the vweb app, causing a restart of the app, which in turn causes the\n\t\t\t\t// browser to reload the current page, that probably triggered the update in the first place.\n\t\t\t\t// Note that the problem is not specific to SQLite, any database that stores its files in the\n\t\t\t\t// current (project) folder, will also cause this.\n\t\t\t\tprintln('`v watch` detected that you are compiling a vweb project.')\n\t\t\t\tprintln('   Because of that, the `--only-watch=${default_veb_suffixes}` flag was also implied.')\n\t\t\t\tprintln('   In result, `v watch` will ignore changes to other files.')\n\t\t\t\tprintln('   Add your own --only-watch filter, if you wish to override that choice.')\n\t\t\t\tprintln('')\n\t\t\t}\n\t\t}\n\t\tcontext.affected_paths = apaths.keys()\n\t\t// context.elog('vfiles paths to be scanned: ${context.affected_paths}')\n\t}\n\t// scan all files in the found folders:\n\tmut newstats := []VFileStat{}\n\tfor path in context.affected_paths {\n\t\tmut files := os.ls(path) or { []string{} }\n\t\tnext_file: for pf in files {\n\t\t\tpf_path := os.join_path_single(path, pf)\n\t\t\tif context.only_watch.len > 0 {\n\t\t\t\t// in the whitelist mode, first only allow files, which match at least one of the patterns in context.only_watch:\n\t\t\t\tmut matched_pattern_idx := -1\n\t\t\t\tfor ow_pattern_idx, ow_pattern in context.only_watch {\n\t\t\t\t\tif pf_path.match_glob(ow_pattern) {\n\t\t\t\t\t\tmatched_pattern_idx = ow_pattern_idx\n\t\t\t\t\t\tcontext.elog('> ${@METHOD} matched --only-watch pattern: ${ow_pattern}, for file: ${pf_path}')\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif matched_pattern_idx == -1 {\n\t\t\t\t\tcontext.elog('> ${@METHOD} --only-watch ignored file: ${pf_path}')\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\t// by default allow everything, except very specific extensions (backup files, executables etc):\n\t\t\tpf_ext := os.file_ext(pf).to_lower()\n\t\t\tif context.is_ext_ignored(pf, pf_ext) {\n\t\t\t\tcontext.elog('> ${@METHOD} ignored extension: ${pf_ext}, for file: ${pf_path}')\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tf := os.join_path(path, pf)\n\t\t\tfullpath := os.real_path(f)\n\t\t\tmtime := os.file_last_mod_unix(fullpath)\n\t\t\tnewstats << VFileStat{fullpath, mtime}\n\t\t}\n\t}\n\t// always add the v compiler itself, so that if it is recompiled with `v self`\n\t// the watcher will rerun the compilation too\n\tnewstats << VFileStat{context.vexe, os.file_last_mod_unix(context.vexe)}\n\treturn newstats\n}\n\nfn (mut context Context) get_changed_vfiles() int {\n\tmut changed := 0\n\tnewfiles := context.get_stats_for_affected_vfiles()\n\tfor vfs in newfiles {\n\t\tmut found := false\n\t\tfor existing_vfs in context.vfiles {\n\t\t\tif existing_vfs.path == vfs.path {\n\t\t\t\tfound = true\n\t\t\t\tif existing_vfs.mtime != vfs.mtime {\n\t\t\t\t\tcontext.elog('> new updates for file: ${vfs}')\n\t\t\t\t\tchanged++\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\tchanged++\n\t\t\tcontinue\n\t\t}\n\t}\n\tcontext.vfiles = newfiles\n\tif changed > 0 {\n\t\tcontext.elog('> get_changed_vfiles: ${changed}')\n\t}\n\treturn changed\n}\n\nfn change_detection_loop(ocontext &Context) {\n\tmut context := unsafe { ocontext }\n\tfor {\n\t\tif context.v_cycles >= max_v_cycles || context.scan_cycles >= max_scan_cycles {\n\t\t\tcontext.is_exiting = true\n\t\t\tcontext.kill_pgroup()\n\t\t\ttime.sleep(50 * time.millisecond)\n\t\t\texit(255)\n\t\t}\n\t\tif context.is_exiting {\n\t\t\treturn\n\t\t}\n\t\tchanges := context.get_changed_vfiles()\n\t\tif changes > 0 {\n\t\t\tcontext.rerun_channel <- RerunCommand.restart\n\t\t}\n\t\ttime.sleep(context.check_period_ms * time.millisecond)\n\t\tcontext.scan_cycles++\n\t}\n}\n\nfn (mut context Context) kill_pgroup() {\n\tif unsafe { context.child_process == 0 } {\n\t\treturn\n\t}\n\tif context.child_process.is_alive() {\n\t\tcontext.child_process.signal_pgkill()\n\t}\n\tcontext.child_process.wait()\n\tcontext.child_process.close()\n}\n\nfn (mut context Context) run_before_cmd() {\n\tif context.cmd_before_run != '' {\n\t\tcontext.elog('> run_before_cmd: \"${context.cmd_before_run}\"')\n\t\tos.system(context.cmd_before_run)\n\t}\n}\n\nfn (mut context Context) run_after_cmd() {\n\tif context.cmd_after_run != '' {\n\t\tcontext.elog('> run_after_cmd: \"${context.cmd_after_run}\"')\n\t\tos.system(context.cmd_after_run)\n\t}\n}\n\nfn (mut context Context) compilation_runner_loop() {\n\tcmd := '\"${context.vexe}\" ${context.opts.join(' ')}'\n\t_ := <-context.rerun_channel\n\tfor {\n\t\tcontext.elog('>> loop: v_cycles: ${context.v_cycles}')\n\t\tif context.clear_terminal {\n\t\t\tterm.clear()\n\t\t}\n\t\tcontext.run_before_cmd()\n\t\ttimestamp := time.now().format_ss_milli()\n\t\tcontext.child_process = os.new_process(context.vexe)\n\t\tcontext.child_process.use_pgroup = true\n\t\tcontext.child_process.set_args(context.opts)\n\t\tcontext.child_process.run()\n\t\tif !context.silent {\n\t\t\teprintln('${timestamp}: ${cmd} | pid: ${context.child_process.pid:7d} | reload cycle: ${context.v_cycles:5d}')\n\t\t}\n\t\tfor {\n\t\t\tmut notalive_count := 0\n\t\t\tmut cmds := []RerunCommand{}\n\t\t\tfor {\n\t\t\t\tif context.is_exiting {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif !context.child_process.is_alive() {\n\t\t\t\t\tcontext.child_process.wait()\n\t\t\t\t\tnotalive_count++\n\t\t\t\t\tif notalive_count == 1 {\n\t\t\t\t\t\t// a short lived process finished, do cleanup:\n\t\t\t\t\t\tcontext.run_after_cmd()\n\t\t\t\t\t\tif context.keep_running {\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tselect {\n\t\t\t\t\taction := <-context.rerun_channel {\n\t\t\t\t\t\tcmds << action\n\t\t\t\t\t\tif action == .quit {\n\t\t\t\t\t\t\tcontext.kill_pgroup()\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t100 * time.millisecond {\n\t\t\t\t\t\tshould_restart := RerunCommand.restart in cmds\n\t\t\t\t\t\tcmds = []\n\t\t\t\t\t\tif should_restart {\n\t\t\t\t\t\t\t// context.elog('>>>>>>>> KILLING ${context.child_process.pid}')\n\t\t\t\t\t\t\tcontext.kill_pgroup()\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !context.child_process.is_alive() {\n\t\t\t\tcontext.elog('> child_process is no longer alive | notalive_count: ${notalive_count}')\n\t\t\t\tcontext.child_process.wait()\n\t\t\t\tcontext.child_process.close()\n\t\t\t\tif notalive_count == 0 {\n\t\t\t\t\t// a long running process was killed, do cleanup:\n\t\t\t\t\tcontext.run_after_cmd()\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tcontext.v_cycles++\n\t}\n}\n\nconst ccontext = Context{}\n\nfn main() {\n\tmut context := unsafe { &Context(voidptr(&ccontext)) }\n\tcontext.pid = os.getpid()\n\tcontext.vexe = os.getenv('VEXE')\n\n\twatch_pos := os.args.index('watch')\n\tall_args_before_watch_cmd := os.args#[1..watch_pos]\n\tall_args_after_watch_cmd := os.args#[watch_pos + 1..]\n\t// dump(os.getpid())\n\t// dump(all_args_before_watch_cmd)\n\t// dump(all_args_after_watch_cmd)\n\n\t// Options after `run` should be ignored, since they are intended for the user program, not for the watcher.\n\t// For example, `v watch run x.v -a -b -k', should pass all of -a -b -k to the compiled and run program.\n\tonly_watch_options, has_run := all_before('run', all_args_after_watch_cmd)\n\n\tmut fp := flag.new_flag_parser(only_watch_options)\n\tfp.application('v watch')\n\tfp.version('0.0.2')\n\tfp.description('Collect all .v files needed for a compilation, then re-run the compilation when any of the source changes.')\n\tfp.arguments_description('[--silent] [--clear] [--ignore .db] [--add /path/to/a/file.v] [run] program.v')\n\tfp.allow_unknown_args()\n\n\tcontext.is_worker = fp.bool('vwatchworker', 0, false, 'Internal flag. Used to distinguish vwatch manager and worker processes.')\n\tcontext.silent = fp.bool('silent', `s`, false, 'Be more silent; do not print the watch timestamp before each re-run.')\n\tcontext.clear_terminal = fp.bool('clear', `c`, false, 'Clears the terminal before each re-run.')\n\tcontext.keep_running = fp.bool('keep', `k`, false, 'Keep the program running. Restart it automatically, if it exits by itself. Useful for gg/ui apps.')\n\tcontext.add_files = fp.string('add', `a`, '', 'Add more files to be watched. Useful with `v watch --add=/tmp/feature.v run cmd/v /tmp/feature.v`, if you change *both* the compiler, and the feature.v file.').split_any(',')\n\tcontext.ignore_exts = fp.string('ignore', `i`, '', 'Ignore files having these extensions. Useful with `v watch --ignore=.db run server.v`, if your server writes to an sqlite.db file in the same folder.').split_any(',')\n\tcontext.only_watch = fp.string('only-watch', 0, '', 'Watch only files matching these globe patterns. Example for a markdown renderer project: `v watch --only-watch=*.v,*.md run .`').split_any(',')\n\tshow_help := fp.bool('help', `h`, false, 'Show this help screen.')\n\tcontext.cmd_before_run = fp.string('before', 0, '', 'A command to execute *before* each re-run.')\n\tcontext.cmd_after_run = fp.string('after', 0, '', 'A command to execute *after* each re-run.')\n\tif show_help {\n\t\tprintln(fp.usage())\n\t\texit(0)\n\t}\n\tremaining_options := fp.finalize() or {\n\t\teprintln('Error: ${err}')\n\t\texit(1)\n\t}\n\tcontext.opts = []\n\tcontext.opts << all_args_before_watch_cmd\n\tcontext.opts << remaining_options\n\tif has_run {\n\t\tcontext.opts << 'run'\n\t\tcontext.opts << all_after('run', all_args_after_watch_cmd)\n\t}\n\tcontext.elog('>>> context.pid: ${context.pid}')\n\tcontext.elog('>>> context.vexe: ${context.vexe}')\n\tcontext.elog('>>> context.opts: ${context.opts}')\n\tcontext.elog('>>> context.is_worker: ${context.is_worker}')\n\tcontext.elog('>>> context.clear_terminal: ${context.clear_terminal}')\n\tcontext.elog('>>> context.add_files: ${context.add_files}')\n\tcontext.elog('>>> context.ignore_exts: ${context.ignore_exts}')\n\tcontext.elog('>>> context.only_watch: ${context.only_watch}')\n\tif context.is_worker {\n\t\tcontext.worker_main()\n\t} else {\n\t\tcontext.manager_main(all_args_before_watch_cmd, all_args_after_watch_cmd)\n\t}\n}\n\nfn (mut context Context) manager_main(all_args_before_watch_cmd []string, all_args_after_watch_cmd []string) {\n\tmyexecutable := os.executable()\n\tmut worker_opts := all_args_before_watch_cmd.clone()\n\tworker_opts << ['watch', '--vwatchworker']\n\tworker_opts << all_args_after_watch_cmd\n\tfor {\n\t\tmut worker_process := os.new_process(myexecutable)\n\t\tworker_process.set_args(worker_opts)\n\t\tworker_process.run()\n\t\tfor {\n\t\t\tif !worker_process.is_alive() {\n\t\t\t\tworker_process.wait()\n\t\t\t\tbreak\n\t\t\t}\n\t\t\ttime.sleep(200 * time.millisecond)\n\t\t}\n\t\tif !(worker_process.code == 255 && worker_process.status == .exited) {\n\t\t\tworker_process.close()\n\t\t\tbreak\n\t\t}\n\t\tworker_process.close()\n\t}\n}\n\nfn (mut context Context) worker_main() {\n\tcontext.rerun_channel = chan RerunCommand{cap: 10}\n\tos.signal_opt(.int, fn (_ os.Signal) {\n\t\tmut context := unsafe { &Context(voidptr(&ccontext)) }\n\t\tcontext.is_exiting = true\n\t\tcontext.kill_pgroup()\n\t}) or { panic(err) }\n\tspawn context.compilation_runner_loop()\n\tchange_detection_loop(context)\n}\n\nfn all_before(needle string, all []string) ([]string, bool) {\n\tneedle_pos := all.index(needle)\n\tif needle_pos == -1 {\n\t\treturn all, false\n\t}\n\treturn all#[..needle_pos], true\n}\n\nfn all_after(needle string, all []string) []string {\n\tneedle_pos := all.index(needle)\n\tif needle_pos == -1 {\n\t\treturn all\n\t}\n\treturn all#[needle_pos + 1..]\n}\n"
  },
  {
    "path": "cmd/tools/vwhere/finder.v",
    "content": "module main\n\nimport os\nimport term { blue, bright_cyan, bright_green, bright_magenta, bright_red, bright_yellow, colorize }\nimport regex\nimport os.cmdline\n\n// Finder is entity that contains all the logic\nstruct Finder {\nmut:\n\tsymbol   Symbol\n\tvisib    Visibility\n\tmutab    Mutability\n\tname     string\n\tmodul    string\n\treceiver string\n\tdirs     []string\n\tmatches  []Match // all the results are collected here\n}\n\nfn (mut fdr Finder) configure_from_arguments(args []string) {\n\tif args.len == 1 {\n\t\tfdr.name = args[0]\n\t\treturn\n\t}\n\tfdr.symbol.set_from_str(args[0])\n\tif fdr.symbol == .method && !args[1].contains('.') {\n\t\tmake_and_print_error('method require a special notation:', [\n\t\t\t'Receiver.method',\n\t\t], '${args[1]}')\n\t} else if fdr.symbol == .method {\n\t\ttemp_args := args[1].split('.')\n\t\tfdr.receiver = temp_args[0]\n\t\tfdr.name = temp_args[1]\n\t} else {\n\t\tfdr.name = args[1]\n\t}\n\tif fdr.name.contains('-') {\n\t\tmake_and_print_error('It seems you forgot positional arg name:', [], fdr.name)\n\t}\n\tfdr.visib.set_from_str(cmdline.option(args, '-vis', '${Visibility.all}'))\n\tif fdr.symbol == .var && fdr.visib != .all {\n\t\tmake_and_print_error('-vis ${fdr.visib} just can be set with symbol_type:', [\n\t\t\t'fn',\n\t\t\t'method',\n\t\t\t'const',\n\t\t\t'struct',\n\t\t\t'enum',\n\t\t\t'interface',\n\t\t\t'regexp',\n\t\t], '${fdr.symbol}')\n\t}\n\tfdr.mutab.set_from_str(cmdline.option(args, '-mut', '${Mutability.any}'))\n\tif fdr.symbol != .var && fdr.mutab != .any {\n\t\tmake_and_print_error('-mut ${fdr.mutab} just can be set with symbol_type:', [\n\t\t\t'var',\n\t\t], '${fdr.symbol}')\n\t}\n\tfdr.modul = cmdline.option(args, '-mod', '')\n\tfdr.dirs = cmdline.options(args, '-dir')\n}\n\nfn (mut fdr Finder) search_for_matches() {\n\t// Define where search\n\tmut recursive := true\n\tmut paths_to_search := []string{}\n\tif fdr.dirs.len == 0 && fdr.modul == '' {\n\t\tpaths_to_search << [current_dir, vmod_dir]\n\t\tif vlib_dir !in paths_to_search && paths_to_search.all(!vlib_dir.starts_with(it)) {\n\t\t\tpaths_to_search << vlib_dir\n\t\t}\n\t\tpaths_to_search << vmod_paths\n\t} else if fdr.dirs.len == 0 && fdr.modul != '' {\n\t\tpaths_to_search << if fdr.modul == 'main' { current_dir } else { resolve_module(fdr.modul) or {\n\t\t\t\tpanic(err)} }\n\t} else if fdr.dirs.len != 0 && fdr.modul == '' {\n\t\tpaths_to_search << fdr.dirs.map(resolve_module(it) or { panic(err) })\n\t} else {\n\t\trecursive = false\n\t\tpaths_to_search << if fdr.modul == 'main' { current_dir } else { resolve_module(fdr.modul) or {\n\t\t\t\tpanic(err)} }\n\t\tpaths_to_search << fdr.dirs.map(resolve_module(it) or { panic(err) })\n\t}\n\n\t// dump(paths_to_search)\n\tmut files_to_search := []string{}\n\tfor p in paths_to_search {\n\t\tfiles_to_search << collect_v_files(p, recursive) or { panic(err) }\n\t}\n\t// dump(files_to_search)\n\n\t// Auxiliary rgx\n\tsp := r'\\s*'\n\top := r'\\('\n\tcp := r'\\)'\n\n\t// Build regex query\n\tsy := '${fdr.symbol}'\n\tst := if fdr.receiver != '' {\n\t\t'${sp}${op}${sp}[a-z].*${sp}${fdr.receiver}${cp}${sp}'\n\t} else {\n\t\t'.*'\n\t}\n\tna := '${fdr.name}'\n\n\tquery := match fdr.symbol {\n\t\t.fn { '.*${sy}${sp}${na}${sp}${op}.*${cp}.*' }\n\t\t.method { '.*fn${st}${na}${sp}${op}.*${cp}.*' }\n\t\t.var { '.*${na}${sp}:=.*' }\n\t\t.const { '.*${na}${sp} = .*' }\n\t\t.regexp { '${na}' }\n\t\telse { '.*${sy}${sp}${na}${sp}.*' } // struct, enum, interface\n\t}\n\t// dump(query)\n\tfor file in files_to_search {\n\t\tfdr.search_within_file(file, query)\n\t}\n}\n\nfn (mut fdr Finder) search_within_file(file string, query string) {\n\tmut re := regex.regex_opt(query) or { panic(err) }\n\tlines := os.read_lines(file) or { panic(err) }\n\tmut const_found := if fdr.symbol == .const { false } else { true }\n\tmut n_line := 1\n\tfor line in lines {\n\t\tmatch fdr.visib {\n\t\t\t.all {\n\t\t\t\tif line.contains('const (') {\n\t\t\t\t\tconst_found = true\n\t\t\t\t}\n\t\t\t}\n\t\t\t.pub {\n\t\t\t\tif line.contains('pub const (') {\n\t\t\t\t\tconst_found = true\n\t\t\t\t}\n\t\t\t}\n\t\t\t.pri {\n\t\t\t\tif line.contains('const (') && !line.contains('pub') {\n\t\t\t\t\tconst_found = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif re.matches_string(line) && (const_found || line.contains('const')) {\n\t\t\twords := line.split(' ').filter(it != '').map(it.trim('\\t'))\n\t\t\tmatch fdr.visib {\n\t\t\t\t.all {}\n\t\t\t\t.pub {\n\t\t\t\t\tif 'pub' !in words && fdr.symbol != .const {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t.pri {\n\t\t\t\t\tif 'pub' in words && fdr.symbol != .const {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tmatch fdr.mutab {\n\t\t\t\t.any {}\n\t\t\t\t.yes {\n\t\t\t\t\tif 'mut' !in words {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t.not {\n\t\t\t\t\tif 'mut' in words {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfdr.matches << Match{file, n_line, words.join(' ').trim(' {')}\n\t\t}\n\t\tif line.starts_with(')') && fdr.symbol == .const {\n\t\t\tconst_found = false\n\t\t}\n\t\tn_line++\n\t}\n}\n\nfn (fdr Finder) show_results() {\n\tif fdr.matches.len < 1 && (verbose || header) {\n\t\tprint(fdr)\n\t\tprintln(colorize(bright_yellow, 'No Matches found'))\n\t} else if verbose || header {\n\t\tprint(fdr)\n\t\tprintln(colorize(bright_green, '${fdr.matches.len} matches Found\\n'))\n\t\tfor result in fdr.matches {\n\t\t\tresult.show()\n\t\t}\n\t} else {\n\t\tfor result in fdr.matches {\n\t\t\tresult.show()\n\t\t}\n\t}\n}\n\nfn (fdr Finder) str() string {\n\tv := colorize(bright_red, '${fdr.visib}')\n\tm := colorize(bright_red, '${fdr.mutab}')\n\tst := if fdr.receiver != '' { ' ( _ ${fdr.receiver})' } else { '' }\n\ts := colorize(bright_magenta, '${fdr.symbol}')\n\tn := colorize(bright_cyan, '${fdr.name}')\n\n\tmm := if fdr.modul != '' { colorize(blue, '${fdr.modul}') } else { '' }\n\tdd := if fdr.dirs.len != 0 {\n\t\tfdr.dirs.map(colorize(blue, it))\n\t} else {\n\t\tfdr.dirs\n\t}\n\n\tdm := if fdr.dirs.len == 0 && fdr.modul == '' {\n\t\t'all the project scope'\n\t} else if fdr.dirs.len == 0 && fdr.modul != '' {\n\t\t'module ${mm}'\n\t} else if fdr.dirs.len != 0 && fdr.modul == '' {\n\t\t'directories: ${dd}'\n\t} else {\n\t\t'module ${mm} searching within directories: ${dd}'\n\t}\n\n\treturn '\\nFind: ${s}${st} ${n} | visibility: ${v} mutability: ${m}\\nwithin ${dm} '\n}\n\n// Match is one result of the search_for_matches() process\nstruct Match {\n\tpath string @[required]\n\tline int    @[required]\n\ttext string @[required]\n}\n\nfn (mtc Match) show() {\n\tpath := colorize(bright_magenta, mtc.path)\n\tline := colorize(bright_yellow, '${mtc.line}')\n\ttext := colorize(bright_green, '${mtc.text}')\n\tif verbose || format {\n\t\tprintln('${path}\\n${line} : [ ${text} ]\\n')\n\t} else {\n\t\tprintln('${path}:${line}: ${text}')\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vwhere/finder_utils.v",
    "content": "module main\n\nimport os\nimport term { bright_green, bright_red, bright_yellow, ecolorize }\nimport os.cmdline\n\n// Symbol type to search\nenum Symbol {\n\tfn\n\tmethod\n\tstruct\n\tinterface\n\tenum\n\tconst\n\tvar\n\tregexp\n}\n\n// Visibility of the symbols to search\nenum Visibility {\n\tall\n\tpub\n\tpri\n}\n\n// Mutability of the symbols to search\nenum Mutability {\n\tany\n\tyes\n\tnot\n}\n\nconst _args = os.args\nconst verbose = '-v' in cmdline.only_options(_args)\nconst header = '-h' in cmdline.only_options(_args)\nconst format = '-f' in cmdline.only_options(_args)\nconst symbols = {\n\t'fn':        Symbol.fn\n\t'method':    .method\n\t'struct':    .struct\n\t'interface': .interface\n\t'enum':      .enum\n\t'const':     .const\n\t'var':       .var\n\t'regexp':    .regexp\n}\nconst visibilities = {\n\t'all': Visibility.all\n\t'pub': .pub\n\t'pri': .pri\n}\nconst mutabilities = {\n\t'any': Mutability.any\n\t'yes': .yes\n\t'not': .not\n}\nconst vexe = os.real_path(os.getenv_opt('VEXE') or { @VEXE })\nconst vlib_dir = os.join_path(os.dir(vexe), 'vlib')\nconst vmod_dir = os.vmodules_dir()\nconst vmod_paths = os.vmodules_paths()[1..]\nconst current_dir = os.abs_path('.')\n\nfn (mut cfg Symbol) set_from_str(str_in string) {\n\tif str_in !in symbols {\n\t\tinvalid_option(cfg, str_in)\n\t}\n\tcfg = symbols[str_in]\n}\n\nfn (mut cfg Visibility) set_from_str(str_in string) {\n\tif str_in !in visibilities {\n\t\tinvalid_option(cfg, str_in)\n\t}\n\tcfg = visibilities[str_in]\n}\n\nfn (mut cfg Mutability) set_from_str(str_in string) {\n\tif str_in !in mutabilities {\n\t\tinvalid_option(cfg, str_in)\n\t}\n\tcfg = mutabilities[str_in]\n}\n\ntype ParamOption = Mutability | Symbol | Visibility\n\n// General helpers\nfn invalid_option(invalid ParamOption, arg string) {\n\tmatch invalid.type_name() {\n\t\t'Symbol' {\n\t\t\tmsg := 'First arg (symbol type) must be one of the following:'\n\t\t\tmake_and_print_error(msg, symbols.keys(), arg)\n\t\t}\n\t\t'Visibility' {\n\t\t\tmsg := '\"-vis\" (visibility) must be one of the following:'\n\t\t\tmake_and_print_error(msg, visibilities.keys(), arg)\n\t\t}\n\t\t'Mutability' {\n\t\t\tmsg := '\"-mut\" (mutability) must be one of the following:'\n\t\t\tmake_and_print_error(msg, mutabilities.keys(), arg)\n\t\t}\n\t\telse {\n\t\t\texit(1)\n\t\t}\n\t}\n}\n\nfn make_and_print_error(msg string, opts []string, arg string) {\n\tif verbose || format {\n\t\teprintln('\\n' + ecolorize(bright_yellow, msg))\n\t\tif opts.len > 0 {\n\t\t\teprint(opts.map(ecolorize(bright_green, it)).join(' | '))\n\t\t}\n\t\teprintln(' ...can not be ${ecolorize(bright_red, arg)}')\n\t} else {\n\t\teprint(ecolorize(bright_yellow, msg) + ' ')\n\t\tif opts.len > 0 {\n\t\t\teprint(opts.map(ecolorize(bright_green, it)).join(' | '))\n\t\t}\n\t\teprintln(' ...can not be ${ecolorize(bright_red, arg)}')\n\t}\n\texit(1)\n}\n\nfn collect_v_files(path string, recursive bool) ![]string {\n\tif path == '' || !os.is_dir(path) {\n\t\treturn error('path `${path}` does not exist or is not a directory')\n\t}\n\tmut all_files := []string{}\n\tmut entries := os.ls(path)!\n\tfor entry in entries {\n\t\tif entry == '.git' {\n\t\t\tcontinue\n\t\t}\n\t\tif entry == 'tests' {\n\t\t\tcontinue\n\t\t}\n\t\tfile := os.join_path_single(path, entry)\n\t\tif os.file_ext(entry) in ['.v', '.vsh'] {\n\t\t\tall_files << file\n\t\t\tcontinue\n\t\t}\n\t\tif recursive && os.is_dir(file) && !os.is_link(file) {\n\t\t\tall_files << collect_v_files(file, recursive)!\n\t\t}\n\t}\n\treturn all_files\n}\n\nfn resolve_module(path string) !string {\n\treturn match true {\n\t\tos.is_dir(path) { path }\n\t\tos.is_dir(os.join_path(vmod_dir, path)) { os.join_path(vmod_dir, path) }\n\t\tos.is_dir(os.join_path(vlib_dir, path)) { os.join_path(vlib_dir, path) }\n\t\telse { error('Path: ${path} not found') }\n\t}\n}\n"
  },
  {
    "path": "cmd/tools/vwhere/test/file_common.v",
    "content": "module test\n\nconst common = 'abcdef'\n"
  },
  {
    "path": "cmd/tools/vwhere/test/file_one.v",
    "content": "module test\n\n// Test declarations\n\nfn main() {\n\tp_1 := Programmer{'Programmer', 'Inmutable'}\n\tmut p_2 := Programmer{'Programmer', 'Mutable'}\n}\n\nstruct Programmer {\n\tf_name string\n\tl_name string\n}\n\nfn (p Programmer) drink(cups int) string {\n\treturn 'drink coffee, return program'\n}\n\npub struct Brogrammer {\n\tf_name string\n\tlife   []Stories\n}\n\npub fn (p Brogrammer) drink(glasses int) string {\n\treturn 'drink beer, return script cluster'\n}\n\nstruct Stories {}\n"
  },
  {
    "path": "cmd/tools/vwhere/test/file_two.v",
    "content": "module test\n\nconst x = 10\nconst y = 100\nconst z = 1000\n\npub enum Public {\n\timportable\n\tshareable\n}\n\nenum Private {\n\tstorable\n\tdownloadable\n}\n\ninterface Drinker {\n\tdrink(int) string\n}\n\npub fn sprint(dkr Drinker) {\n\tprintln(drk.drink(6))\n}\n\nfn some_function_name(foo string, bar int) string {\n\treturn 'baz'\n}\n"
  },
  {
    "path": "cmd/tools/vwhere/test/nested_mod/nested_file.v",
    "content": "module nested_mod\n\npub const a = 30\npub const b = 60\npub const c = 120\npub const common = 42\n"
  },
  {
    "path": "cmd/tools/vwhere/vwhere.v",
    "content": "module main\n\nimport os\n\nfn main() {\n\targs := os.args[2..]\n\tif args.len == 0 || args == ['help'] || '-help' in args || '--help' in args {\n\t\tos.system('${os.quoted_path(vexe)} help where')\n\t\texit(0)\n\t}\n\tmut fdr := Finder{}\n\tfdr.configure_from_arguments(args)\n\tfdr.search_for_matches()\n\tfdr.show_results()\n}\n"
  },
  {
    "path": "cmd/tools/vwhere/vwhere_test.v",
    "content": "module main\n\nimport os\n\nconst test_dir = os.join_path(os.dir(vexe), 'cmd', 'tools', 'vwhere', 'test')\n\nfn test_create_finder() {\n\tmut fdr := Finder{}\n\n\tfdr.configure_from_arguments(['some'])\n\tassert fdr.symbol == .fn\n\tassert fdr.name == 'some'\n\tassert fdr.visib == .all\n\tassert fdr.mutab == .any\n\n\tfdr.configure_from_arguments(['fn', 'some', '-vis', 'pub'])\n\tassert fdr.symbol == .fn\n\tassert fdr.name == 'some'\n\tassert fdr.visib == .pub\n\n\tfdr.configure_from_arguments(['method', 'Some.some', '-vis', 'pri'])\n\tassert fdr.symbol == .method\n\tassert fdr.receiver == 'Some'\n\tassert fdr.name == 'some'\n\tassert fdr.visib == .pri\n\n\tfdr.configure_from_arguments(['struct', 'Some', '-mod', 'foo'])\n\tassert fdr.symbol == .struct\n\tassert fdr.name == 'Some'\n\tassert fdr.modul == 'foo'\n\n\tfdr.configure_from_arguments(['interface', 'Some', '-mod', 'foo', '-dir', 'bar'])\n\tassert fdr.symbol == .interface\n\tassert fdr.name == 'Some'\n\tassert fdr.modul == 'foo'\n\tassert fdr.dirs == ['bar']\n\n\tfdr.configure_from_arguments(['enum', 'Some', '-dir', 'bar', '-dir', 'baz'])\n\tassert fdr.symbol == .enum\n\tassert fdr.name == 'Some'\n\tassert fdr.dirs == ['bar', 'baz']\n\n\tfdr.configure_from_arguments(['const', 'some'])\n\tassert fdr.symbol == .const\n\tassert fdr.name == 'some'\n\n\tfdr.configure_from_arguments(['var', 'some', '-mut', 'yes'])\n\tassert fdr.symbol == .var\n\tassert fdr.name == 'some'\n\tassert fdr.mutab == .yes\n\n\tfdr.configure_from_arguments(['var', 'some', '-mut', 'not'])\n\tassert fdr.symbol == .var\n\tassert fdr.name == 'some'\n\tassert fdr.mutab == .not\n\n\tfdr.configure_from_arguments(['regexp', '.*some.*'])\n\tassert fdr.symbol == .regexp\n\tassert fdr.name == '.*some.*'\n}\n\nfn test_find_mut_var() {\n\targs := ['var', 'p_2', '-mut', 'yes', '-dir', test_dir]\n\tmut fdr := Finder{}\n\tfdr.configure_from_arguments(args)\n\tfdr.search_for_matches()\n\tassert fdr.matches == [\n\t\tMatch{\n\t\t\tpath: os.join_path(test_dir, 'file_one.v')\n\t\t\tline: 7\n\t\t\ttext: \"mut p_2 := Programmer{'Programmer', 'Mutable'}\"\n\t\t},\n\t]\n}\n\nfn test_find_non_mut_var() {\n\targs := ['var', 'p_1', '-mut', 'not', '-dir', test_dir]\n\tmut fdr := Finder{}\n\tfdr.configure_from_arguments(args)\n\tfdr.search_for_matches()\n\tassert fdr.matches == [\n\t\tMatch{\n\t\t\tpath: os.join_path(test_dir, 'file_one.v')\n\t\t\tline: 6\n\t\t\ttext: \"p_1 := Programmer{'Programmer', 'Inmutable'}\"\n\t\t},\n\t]\n}\n\nfn test_find_method() {\n\targs := ['method', 'Programmer.drink', '-dir', test_dir]\n\tmut fdr := Finder{}\n\tfdr.configure_from_arguments(args)\n\tfdr.search_for_matches()\n\tassert fdr.matches == [\n\t\tMatch{\n\t\t\tpath: os.join_path(test_dir, 'file_one.v')\n\t\t\tline: 15\n\t\t\ttext: 'fn (p Programmer) drink(cups int) string'\n\t\t},\n\t]\n}\n\nfn test_find_pub_method() {\n\targs := ['method', 'Brogrammer.drink', '-vis', 'pub', '-dir', test_dir]\n\tmut fdr := Finder{}\n\tfdr.configure_from_arguments(args)\n\tfdr.search_for_matches()\n\tassert fdr.matches == [\n\t\tMatch{\n\t\t\tpath: os.join_path(test_dir, 'file_one.v')\n\t\t\tline: 24\n\t\t\ttext: 'pub fn (p Brogrammer) drink(glasses int) string'\n\t\t},\n\t]\n}\n\nfn test_find_pri_const() {\n\targs := ['const', 'y', '-vis', 'pri', '-dir', test_dir]\n\tmut fdr := Finder{}\n\tfdr.configure_from_arguments(args)\n\tfdr.search_for_matches()\n\tassert fdr.matches == [\n\t\tMatch{\n\t\t\tpath: os.join_path(test_dir, 'file_two.v')\n\t\t\tline: 4\n\t\t\ttext: 'const y = 100'\n\t\t},\n\t]\n}\n\nfn test_find_pub_enum() {\n\targs := ['enum', 'Public', '-vis', 'pub', '-dir', test_dir]\n\tmut fdr := Finder{}\n\tfdr.configure_from_arguments(args)\n\tfdr.search_for_matches()\n\tassert fdr.matches == [\n\t\tMatch{\n\t\t\tpath: os.join_path(test_dir, 'file_two.v')\n\t\t\tline: 7\n\t\t\ttext: 'pub enum Public'\n\t\t},\n\t]\n}\n\nfn test_find_pri_enum() {\n\targs := ['enum', 'Private', '-vis', 'pri', '-dir', test_dir]\n\tmut fdr := Finder{}\n\tfdr.configure_from_arguments(args)\n\tfdr.search_for_matches()\n\tassert fdr.matches == [\n\t\tMatch{\n\t\t\tpath: os.join_path(test_dir, 'file_two.v')\n\t\t\tline: 12\n\t\t\ttext: 'enum Private'\n\t\t},\n\t]\n}\n\nfn test_find_fn() {\n\targs := ['fn', 'some_function_name', '-dir', test_dir]\n\tmut fdr := Finder{}\n\tfdr.configure_from_arguments(args)\n\tfdr.search_for_matches()\n\tassert fdr.matches == [\n\t\tMatch{\n\t\t\tpath: os.join_path(test_dir, 'file_two.v')\n\t\t\tline: 25\n\t\t\ttext: 'fn some_function_name(foo string, bar int) string'\n\t\t},\n\t]\n}\n\nfn test_find_pub_const_with_mod() {\n\targs := ['const', 'b', '-vis', 'pub', '-mod', test_dir]\n\tmut fdr := Finder{}\n\tfdr.configure_from_arguments(args)\n\tfdr.search_for_matches()\n\tassert fdr.matches == [\n\t\tMatch{\n\t\t\tpath: os.join_path(test_dir, 'nested_mod', 'nested_file.v')\n\t\t\tline: 4\n\t\t\ttext: 'pub const b = 60'\n\t\t},\n\t]\n}\n\nfn test_find_in_dir_recursive() {\n\targs := ['const', 'common', '-dir', test_dir]\n\tmut fdr := Finder{}\n\tfdr.configure_from_arguments(args)\n\tfdr.search_for_matches()\n\t// the order of matches is not guaranteed.\n\t// sorting by line number makes the result more deterministic.\n\tfdr.matches.sort(a.line < b.line)\n\tdump(fdr.matches)\n\n\tassert fdr.matches == [\n\t\tMatch{\n\t\t\tpath: os.join_path_single(test_dir, 'file_common.v')\n\t\t\tline: 3\n\t\t\ttext: \"const common = 'abcdef'\"\n\t\t},\n\t\tMatch{\n\t\t\tpath: os.join_path_single(test_dir, 'nested_mod/nested_file.v')\n\t\t\tline: 6\n\t\t\ttext: 'pub const common = 42'\n\t\t},\n\t]\n}\n"
  },
  {
    "path": "cmd/tools/vwipe-cache.v",
    "content": "module main\n\nimport os\nimport v.vcache\n\nfn main() {\n\twipe_path(vcache.new_cache_manager([]).basepath, 'V cache')\n\twipe_path(os.vtmp_dir(), 'V tmp.c and tests folder')\n}\n\nfn wipe_path(cpath string, label string) {\n\tif os.exists(cpath) && os.is_dir(cpath) {\n\t\tos.rmdir_all(cpath) or {}\n\t}\n\tos.mkdir_all(cpath) or {}\n\tprintln('${label} folder ${cpath} was wiped.')\n}\n"
  },
  {
    "path": "cmd/v/v.v",
    "content": "// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nmodule main\n\nimport os\nimport term\nimport v.help\nimport v.pref\nimport v.util\nimport v.util.version\nimport v.builder\nimport v.builder.cbuilder\n\n@[markused]\nconst external_tools = [\n\t'ast',\n\t'bin2v',\n\t'bug',\n\t'build-examples',\n\t'build-tools',\n\t'build-vbinaries',\n\t'bump',\n\t'check-md',\n\t'complete',\n\t'compress',\n\t'cover',\n\t'diff',\n\t'doc',\n\t'doctor',\n\t'download',\n\t'fmt',\n\t'git-fmt-hook',\n\t'gret',\n\t'ls',\n\t'missdoc',\n\t'quest',\n\t'reduce',\n\t'repl',\n\t'repeat',\n\t'retry',\n\t'self',\n\t'setup-freetype',\n\t'shader',\n\t'share',\n\t'should-compile-all',\n\t'symlink',\n\t'scan',\n\t'test',\n\t'test-all', // runs most of the tests and other checking tools, that will be run by the CI\n\t'test-cleancode',\n\t'test-fmt',\n\t'test-parser',\n\t'test-self',\n\t'time',\n\t'timeout',\n\t'tracev',\n\t'up',\n\t'vet',\n\t'wipe-cache',\n\t'watch',\n\t'where',\n]\nconst list_of_flags_that_allow_duplicates = ['cc', 'd', 'define', 'cf', 'cflags']\n\n@[unsafe]\nfn timers_pointer(p &util.Timers) &util.Timers {\n\t// TODO: the static variable here is used as a workaround for the current incompatibility of -usecache and globals in the main module:\n\tmut static ptimers := unsafe { &util.Timers(nil) }\n\tif p != unsafe { nil } {\n\t\tptimers = p\n\t}\n\treturn ptimers\n}\n\nfn main() {\n\tunbuffer_stdout()\n\tmut timers_should_print := false\n\t$if time_v ? {\n\t\ttimers_should_print = true\n\t}\n\tif '-show-timings' in os.args {\n\t\ttimers_should_print = true\n\t}\n\tmut timers := unsafe {\n\t\ttimers_pointer(util.new_timers(\n\t\t\tshould_print: timers_should_print\n\t\t\tlabel:        'main'\n\t\t))\n\t}\n\ttimers.start('v start')\n\ttimers.show('v start')\n\ttimers.start('TOTAL')\n\t// use at_exit here, instead of defer, since some code paths later do early exit(0) or exit(1), for showing errors, or after `v run`\n\tat_exit(fn () {\n\t\tmut timers := unsafe { timers_pointer(nil) }\n\t\ttimers.show('TOTAL')\n\t})!\n\ttimers.start('v parsing CLI args')\n\targs := os.args[1..]\n\n\tif args.len == 0 || args[0] in ['-', 'repl'] {\n\t\tif args.len == 0 {\n\t\t\t// Running `./v` without args launches repl\n\t\t\tif os.is_atty(0) == 0 {\n\t\t\t\tmut args_and_flags := util.join_env_vflags_and_os_args()[1..].clone()\n\t\t\t\targs_and_flags << ['run', '-']\n\t\t\t\tpref.parse_args_and_show_errors(external_tools, args_and_flags, true)\n\t\t\t}\n\t\t}\n\t\tutil.launch_tool(false, 'vrepl', os.args[1..])\n\t\treturn\n\t}\n\tmut args_and_flags := util.join_env_vflags_and_os_args()[1..]\n\tprefs, command := pref.parse_args_and_show_errors(external_tools, args_and_flags,\n\t\ttrue)\n\tmaybe_delegate_to_vvmrc(command, prefs)\n\tif prefs.use_cache && os.user_os() == 'windows' {\n\t\teprintln('-usecache is currently disabled on windows')\n\t\texit(1)\n\t}\n\ttimers.show('v parsing CLI args')\n\n\tsetup_vbuild_env_vars(prefs)\n\n\t// Start calling the correct functions/external tools\n\t// Note for future contributors: Please add new subcommands in the `match` block below.\n\tif command in external_tools {\n\t\t// External tools\n\t\tutil.launch_tool(prefs.is_verbose, 'v' + command, os.args[1..])\n\t\treturn\n\t}\n\tmatch command {\n\t\t'run', 'crun', 'build', 'build-module' {\n\t\t\trebuild(prefs)\n\t\t\treturn\n\t\t}\n\t\t'help' {\n\t\t\tinvoke_help_and_exit(args)\n\t\t}\n\t\t'version' {\n\t\t\tprintln(version.full_v_version(prefs.is_verbose))\n\t\t\treturn\n\t\t}\n\t\t'new', 'init' {\n\t\t\tutil.launch_tool(prefs.is_verbose, 'vcreate', os.args[1..])\n\t\t\treturn\n\t\t}\n\t\t'install', 'link', 'list', 'outdated', 'remove', 'search', 'show', 'unlink', 'update',\n\t\t'upgrade' {\n\t\t\tutil.launch_tool(prefs.is_verbose, 'vpm', os.args[1..])\n\t\t\treturn\n\t\t}\n\t\t'vlib-docs' {\n\t\t\tutil.launch_tool(prefs.is_verbose, 'vdoc', ['doc', 'vlib'])\n\t\t}\n\t\t'interpret' {\n\t\t\tutil.launch_tool(prefs.is_verbose, 'builders/interpret_builder', os.args[1..])\n\t\t}\n\t\t'get' {\n\t\t\teprintln('V Error: Use `v install` to install modules from vpm.vlang.io')\n\t\t\texit(1)\n\t\t}\n\t\t'translate' {\n\t\t\tutil.launch_tool(prefs.is_verbose, 'translate', os.args[1..])\n\t\t\t// exit(1)\n\t\t\t// return\n\t\t}\n\t\telse {\n\t\t\tif command.ends_with('.v') || os.exists(command) {\n\t\t\t\t// println('command')\n\t\t\t\t// println(prefs.path)\n\t\t\t\trebuild(prefs)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\tif prefs.is_help {\n\t\tinvoke_help_and_exit(args)\n\t}\n\n\tother_commands := ['run', 'crun', 'build', 'build-module', 'help', 'version', 'new', 'init',\n\t\t'install', 'link', 'list', 'outdated', 'remove', 'search', 'show', 'unlink', 'update',\n\t\t'upgrade', 'vlib-docs', 'interpret', 'translate']\n\tmut all_commands := []string{}\n\tall_commands << external_tools\n\tall_commands << other_commands\n\tall_commands.sort()\n\teprintln(util.new_suggestion(command, all_commands, similarity_threshold: 0.2).say('v: unknown command `${command}`'))\n\teprintln('Run ${term.highlight_command('v help')} for usage.')\n\texit(1)\n}\n\nfn invoke_help_and_exit(remaining []string) {\n\tmatch remaining.len {\n\t\t0, 1 { help.print_and_exit('default') }\n\t\t2 { help.print_and_exit(remaining[1]) }\n\t\telse {}\n\t}\n\teprintln('${term.highlight_command('v help')}: provide only one help topic.')\n\teprintln('For usage information, use ${term.highlight_command('v help')}.')\n\texit(1)\n}\n\nfn rebuild(prefs &pref.Preferences) {\n\tmatch prefs.backend {\n\t\t.c {\n\t\t\t$if no_bootstrapv ? {\n\t\t\t\t// TODO: improve the bootstrapping with a split C backend here.\n\t\t\t\t// C code generated by `VEXE=v cmd/tools/builders/c_builder -os cross -o c.c cmd/tools/builders/c_builder.v`\n\t\t\t\t// is enough to bootstrap the C backend, and thus the rest, but currently bootstrapping relies on\n\t\t\t\t// `v -os cross -o v.c cmd/v` having a functional C codegen inside instead.\n\t\t\t\tutil.launch_tool(prefs.is_verbose, 'builders/c_builder', os.args[1..])\n\t\t\t}\n\t\t\tbuilder.compile('build', prefs, cbuilder.compile_c)\n\t\t}\n\t\t.js_node, .js_freestanding, .js_browser {\n\t\t\tutil.launch_tool(prefs.is_verbose, 'builders/js_builder', os.args[1..])\n\t\t}\n\t\t.native {\n\t\t\tutil.launch_tool(prefs.is_verbose, 'builders/native_builder', os.args[1..])\n\t\t}\n\t\t.interpret {\n\t\t\tutil.launch_tool(prefs.is_verbose, 'builders/interpret_builder', os.args[1..])\n\t\t}\n\t\t.golang {\n\t\t\tprintln('using Go WIP backend...')\n\t\t\tutil.launch_tool(prefs.is_verbose, 'builders/golang_builder', os.args[1..])\n\t\t}\n\t\t.wasm {\n\t\t\tutil.launch_tool(prefs.is_verbose, 'builders/wasm_builder', os.args[1..])\n\t\t}\n\t}\n}\n\n@[manualfree]\nfn setup_vbuild_env_vars(prefs &pref.Preferences) {\n\tmut facts := []string{cap: 10}\n\tfacts << prefs.os.lower()\n\tfacts << prefs.ccompiler_type.str()\n\tfacts << prefs.arch.str()\n\tif prefs.is_prod {\n\t\tfacts << 'prod'\n\t}\n\tgithub_job := os.getenv('GITHUB_JOB')\n\tif github_job != '' {\n\t\tfacts << github_job\n\t}\n\tpref.set_build_flags_and_defines(facts, prefs.compile_defines_all)\n\tunsafe { github_job.free() }\n\tunsafe { facts.free() }\n}\n"
  },
  {
    "path": "cmd/v/vvm.v",
    "content": "module main\n\nimport os\nimport v.pref\nimport v.util.version\n\nconst vvmrc_file_name = '.vvmrc'\n\nconst vvmrc_skip_env = 'V_SKIP_VVMRC'\n\nconst vvmrc_latest_aliases = ['latest', 'current']\n\nconst vvmrc_stop_paths = ['.git', '.hg', '.svn', '.v.mod.stop']\n\nfn maybe_delegate_to_vvmrc(command string, prefs &pref.Preferences) {\n\tif os.getenv(vvmrc_skip_env) != '' {\n\t\treturn\n\t}\n\tif !is_vvmrc_relevant_command(command, prefs) {\n\t\treturn\n\t}\n\ttarget_path := if prefs.path != '' { prefs.path } else { command }\n\tvvmrc_path := find_project_vvmrc(target_path)\n\tif vvmrc_path == '' {\n\t\treturn\n\t}\n\trequested_version := parse_vvmrc_version(os.read_file(vvmrc_path) or { '' })\n\tif requested_version == '' || is_vvmrc_latest_alias(requested_version) {\n\t\treturn\n\t}\n\tnormalized_requested_version := normalize_vvmrc_version(requested_version)\n\tif normalized_requested_version == normalize_vvmrc_version(version.v_version) {\n\t\treturn\n\t}\n\tvversion_exe := resolve_vversion_executable(normalized_requested_version) or {\n\t\teprintln('v: warning: `${vvmrc_path}` requests V `${requested_version}`, but no matching compiler executable was found. Continuing with V ${version.v_version}.')\n\t\treturn\n\t}\n\tthis_vexe := os.real_path(pref.vexe_path())\n\tif os.real_path(vversion_exe) == this_vexe {\n\t\treturn\n\t}\n\tif prefs.is_verbose {\n\t\teprintln('v: `.vvmrc` selected V `${requested_version}` from `${vvmrc_path}` => ${vversion_exe}')\n\t}\n\tmut process := os.new_process(vversion_exe)\n\tprocess.set_args(os.args[1..])\n\tmut envs := os.environ()\n\tenvs[vvmrc_skip_env] = '1'\n\tenvs['VEXE'] = vversion_exe\n\tprocess.set_environment(envs)\n\tprocess.wait()\n\texit_code := if process.code == -1 { 1 } else { process.code }\n\tprocess.close()\n\texit(exit_code)\n}\n\nfn is_vvmrc_relevant_command(command string, prefs &pref.Preferences) bool {\n\tif prefs.path in ['', '-'] {\n\t\treturn false\n\t}\n\tif command in ['run', 'crun', 'build', 'build-module'] {\n\t\treturn true\n\t}\n\treturn command.ends_with('.v') || os.exists(command)\n}\n\nfn find_project_vvmrc(target_path string) string {\n\tif target_path in ['', '-'] {\n\t\treturn ''\n\t}\n\tmut folder := if os.is_dir(target_path) { target_path } else { os.dir(target_path) }\n\tif folder == '' {\n\t\tfolder = os.getwd()\n\t}\n\tmut current := os.real_path(folder)\n\tfor _ in 0 .. 256 {\n\t\tvvmrc_path := os.join_path(current, vvmrc_file_name)\n\t\tif os.is_file(vvmrc_path) {\n\t\t\treturn vvmrc_path\n\t\t}\n\t\tif has_vvmrc_stop_marker(current) {\n\t\t\tbreak\n\t\t}\n\t\tparent := os.dir(current)\n\t\tif parent in ['', current] {\n\t\t\tbreak\n\t\t}\n\t\tcurrent = parent\n\t}\n\treturn ''\n}\n\nfn has_vvmrc_stop_marker(folder string) bool {\n\tfor stop_path in vvmrc_stop_paths {\n\t\tif os.exists(os.join_path(folder, stop_path)) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfn parse_vvmrc_version(content string) string {\n\tfor raw_line in content.split_into_lines() {\n\t\tline := raw_line.all_before('#').trim_space()\n\t\tif line != '' {\n\t\t\treturn line\n\t\t}\n\t}\n\treturn ''\n}\n\nfn normalize_vvmrc_version(version_name string) string {\n\tmut normalized := version_name.trim_space()\n\tif normalized.len > 1 && normalized[0] in [`v`, `V`] && normalized[1].is_digit() {\n\t\tnormalized = normalized[1..]\n\t}\n\treturn normalized\n}\n\nfn is_vvmrc_latest_alias(version_name string) bool {\n\treturn normalize_vvmrc_version(version_name).to_lower_ascii() in vvmrc_latest_aliases\n}\n\nfn resolve_vversion_executable(version_name string) !string {\n\traw_version := version_name.trim_space()\n\tif raw_version == '' {\n\t\treturn error('empty version')\n\t}\n\tfor candidate_name in versioned_v_executable_names(raw_version) {\n\t\tif found_path := os.find_abs_path_of_executable(candidate_name) {\n\t\t\treturn found_path\n\t\t}\n\t}\n\tfor candidate_path in versioned_v_executable_paths(raw_version) {\n\t\tif os.is_file(candidate_path) {\n\t\t\treturn candidate_path\n\t\t}\n\t}\n\treturn error('v executable for `${raw_version}` was not found')\n}\n\nfn versioned_v_executable_names(version_name string) []string {\n\tmut names := []string{}\n\traw_version := version_name.trim_space()\n\tif raw_version == '' {\n\t\treturn names\n\t}\n\tnames << raw_version\n\tnames << 'v${raw_version}'\n\tif raw_version.starts_with('v') {\n\t\ttrimmed := raw_version[1..]\n\t\tif trimmed != '' {\n\t\t\tnames << trimmed\n\t\t}\n\t}\n\treturn unique_strings(names)\n}\n\nfn versioned_v_executable_paths(version_name string) []string {\n\tmut paths := []string{}\n\tnormalized_version := normalize_vvmrc_version(version_name)\n\tif normalized_version == '' {\n\t\treturn paths\n\t}\n\tpaths << os.join_path('/usr/lib/v', normalized_version, 'bin', 'v')\n\tpaths << os.join_path('/usr/local/bin', 'v${normalized_version}')\n\tfor env_name in ['VVM_HOME', 'VVM_DIR'] {\n\t\tvvm_root := os.getenv(env_name).trim_space()\n\t\tif vvm_root == '' {\n\t\t\tcontinue\n\t\t}\n\t\tpaths << os.join_path(vvm_root, normalized_version, 'bin', 'v')\n\t\tpaths << os.join_path(vvm_root, 'versions', normalized_version, 'bin', 'v')\n\t}\n\treturn unique_strings(paths)\n}\n\nfn unique_strings(items []string) []string {\n\tmut seen := map[string]bool{}\n\tmut result := []string{}\n\tfor item in items {\n\t\tif item in seen {\n\t\t\tcontinue\n\t\t}\n\t\tseen[item] = true\n\t\tresult << item\n\t}\n\treturn result\n}\n"
  },
  {
    "path": "cmd/v/vvm_test.v",
    "content": "module main\n\nimport os\nimport rand\n\nconst current_vexe = @VEXE\n\nconst delegated_marker = 'VVM-DELEGATED'\n\nconst requested_vvm_test_version = '99.99.99'\n\nstruct CmdResult {\n\texit_code int\n\toutput    string\n}\n\nfn test_parse_vvmrc_version() {\n\tassert parse_vvmrc_version('') == ''\n\tassert parse_vvmrc_version('   ') == ''\n\tassert parse_vvmrc_version('# only comments') == ''\n\tassert parse_vvmrc_version('\\n# comment\\n0.4.6\\n') == '0.4.6'\n\tassert parse_vvmrc_version(' latest # comment ') == 'latest'\n}\n\nfn test_find_project_vvmrc_stops_at_stop_paths() {\n\ttmp_root := os.join_path(os.vtmp_dir(), 'vvmrc_stop_test_${rand.ulid()}')\n\tos.mkdir_all(tmp_root) or { panic(err) }\n\tdefer {\n\t\tos.rmdir_all(tmp_root) or {}\n\t}\n\tproject_dir := os.join_path(tmp_root, 'project')\n\tsource_dir := os.join_path(project_dir, 'src')\n\tos.mkdir_all(source_dir) or { panic(err) }\n\tos.mkdir_all(os.join_path(project_dir, '.git')) or { panic(err) }\n\tos.write_file(os.join_path(tmp_root, '.vvmrc'), requested_vvm_test_version) or { panic(err) }\n\tmain_v := os.join_path(source_dir, 'main.v')\n\tos.write_file(main_v, 'fn main() {}') or { panic(err) }\n\tassert find_project_vvmrc(main_v) == ''\n\tlocal_vvmrc := os.join_path(project_dir, '.vvmrc')\n\tos.write_file(local_vvmrc, requested_vvm_test_version) or { panic(err) }\n\tassert find_project_vvmrc(main_v) == os.real_path(local_vvmrc)\n}\n\nfn test_vvmrc_delegates_to_matching_compiler_executable() {\n\ttmp_root := os.join_path(os.vtmp_dir(), 'vvmrc_delegate_test_${rand.ulid()}')\n\tos.mkdir_all(tmp_root) or { panic(err) }\n\tdefer {\n\t\tos.rmdir_all(tmp_root) or {}\n\t}\n\tbin_dir := os.join_path(tmp_root, 'bin')\n\tos.mkdir_all(bin_dir) or { panic(err) }\n\tfake_compiler_source := os.join_path(tmp_root, 'fake_compiler.v')\n\tos.write_file(fake_compiler_source, \"import os\\nfn main() {\\n\\tprintln('${delegated_marker} ' + os.args[1..].join(' '))\\n}\\n\") or {\n\t\tpanic(err)\n\t}\n\tfake_compiler_exe := os.join_path(bin_dir, if os.user_os() == 'windows' {\n\t\t'v${requested_vvm_test_version}.exe'\n\t} else {\n\t\t'v${requested_vvm_test_version}'\n\t})\n\tcompile_res := os.execute('${os.quoted_path(current_vexe)} -o ${os.quoted_path(fake_compiler_exe)} ${os.quoted_path(fake_compiler_source)}')\n\tassert compile_res.exit_code == 0, compile_res.output\n\tproject_dir := os.join_path(tmp_root, 'project')\n\tos.mkdir_all(project_dir) or { panic(err) }\n\tos.write_file(os.join_path(project_dir, '.vvmrc'), requested_vvm_test_version) or { panic(err) }\n\tos.write_file(os.join_path(project_dir, 'main.v'), \"fn main() {\\n\\tprintln('from project')\\n}\\n\") or {\n\t\tpanic(err)\n\t}\n\tmut envs := os.environ()\n\tpath_key := find_path_env_key(envs)\n\tenvs[path_key] = '${bin_dir}${os.path_delimiter}${envs[path_key]}'\n\tenvs['V_SKIP_VVMRC'] = ''\n\tres := run_v_command(project_dir, ['run', 'main.v'], envs)\n\tassert res.exit_code == 0, res.output\n\tassert res.output.contains('${delegated_marker} run main.v'), res.output\n}\n\nfn run_v_command(work_dir string, args []string, envs map[string]string) CmdResult {\n\tmut process := os.new_process(current_vexe)\n\tprocess.set_work_folder(work_dir)\n\tprocess.set_args(args)\n\tprocess.set_environment(envs)\n\tprocess.set_redirect_stdio()\n\tprocess.wait()\n\toutput := process.stdout_slurp() + process.stderr_slurp()\n\texit_code := if process.code == -1 { 1 } else { process.code }\n\tprocess.close()\n\treturn CmdResult{\n\t\texit_code: exit_code\n\t\toutput:    output\n\t}\n}\n\nfn find_path_env_key(envs map[string]string) string {\n\tif 'PATH' in envs {\n\t\treturn 'PATH'\n\t}\n\tif 'Path' in envs {\n\t\treturn 'Path'\n\t}\n\treturn 'PATH'\n}\n"
  },
  {
    "path": "cmd/v2/.gitignore",
    "content": "*.c\n"
  },
  {
    "path": "cmd/v2/README.md",
    "content": "# Run all ARM64 tests\n```\n  ./v run vlib/v2/gen/arm64/tests/run_tests.v\n\n```\n  # Run specific test with test_ssa_backends\n```\n  cd cmd/v2\n  ./test_ssa_backends arm64 ../../vlib/v2/gen/arm64/tests/string_concat.v\n```\n\n  # Or directly with v2\n```\n  ./v2 -backend arm64 ../../vlib/v2/gen/arm64/tests/string_concat.v\n```\n\n# Useful cleanc flags\n```\n  # Disable builtin+strconv object cache for this build:\n  ./v2 -backend cleanc -nocache file.v\n\n  # Print C compiler and link command(s):\n  ./v2 -backend cleanc -showcc file.v\n\n  # Print extended parse/build stats:\n  ./v2 -stats -backend cleanc file.v\n  # Includes per-pass C Gen timing lines to help locate slow codegen phases.\n\n  # Print every parsed file (full and .vh groups):\n  ./v2 -print-parsed-files -backend cleanc file.v\n\n  # Disable markused pruning (emit all functions):\n  ./v2 -nomarkused -backend cleanc file.v\n```\n\n# Eval backend\n```\n  # Execute a small V program directly from the v2 AST:\n  ./v2 -backend eval file.v\n\n  # Pass runtime args to the interpreted program:\n  ./v2 -backend eval file.v -- arg1 arg2\n\n  # Self-host under eval without recursively reusing the outer compiler flags:\n  ./v2 -backend eval cmd/v2/v2.v -- -o /tmp/v2self cmd/v2/v2.v\n\n  # Current scope: literals, locals/consts, plain fn calls, if/for/range,\n  # arrays, indexing, len, println/print, and basic string interpolation.\n```\n\n# SSA C backend (restored)\n```\n  # Run the SSA -> C backend directly:\n  ./v2 -backend c cmd/v2/test.v\n\n  # Compare SSA C output against reference V output:\n  cd cmd/v2\n  ../../v run test_ssa_backends.v c\n```\n"
  },
  {
    "path": "cmd/v2/guiprof/draw.v",
    "content": "// Copyright (c) 2020-2024 Joe Conigliaro. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nmodule main\n\nimport gg\nimport v2.profiler\n\n// draw_header renders the top stats bar\nfn draw_header(mut app App) {\n\tctx := app.gg\n\tw := f32(ctx.width)\n\n\t// Background\n\tctx.draw_rect_filled(0, 0, w, f32(app.header_height), header_bg)\n\n\t// Get stats\n\tstats := app.cached_stats\n\n\t// Format and draw stats\n\theap_str := 'HEAP: ${profiler.format_bytes(stats.live_bytes)}'\n\tpeak_str := 'Peak: ${profiler.format_bytes(stats.peak_bytes)}'\n\tallocs_str := '${stats.total_allocs} allocs'\n\tfrees_str := '${stats.total_frees} frees'\n\tleaks_str := '${stats.leak_count} leaks'\n\n\t// Draw stats with spacing\n\tmut x := f32(20)\n\ty := f32(22)\n\n\tctx.draw_text(int(x), int(y), heap_str, color: text_color, size: 20)\n\tx += 180\n\n\tctx.draw_text(int(x), int(y), peak_str, color: text_color, size: 20)\n\tx += 160\n\n\tctx.draw_text(int(x), int(y), allocs_str, color: new_alloc_color, size: 20)\n\tx += 140\n\n\tctx.draw_text(int(x), int(y), frees_str, color: freed_color, size: 20)\n\tx += 120\n\n\t// Show leaks in red if there are any\n\tleak_clr := if stats.leak_count > 0 { leak_color } else { text_color }\n\tctx.draw_text(int(x), int(y), leaks_str, color: leak_clr, size: 20)\n\n\t// Mode and frame counter on right\n\tmode_str := if app.demo_mode {\n\t\t'DEMO'\n\t} else if app.live_mode {\n\t\t'LIVE'\n\t} else {\n\t\t'LOCAL'\n\t}\n\tctx.draw_text(int(w) - 250, int(y), mode_str, color: gg.Color{100, 255, 100, 255}, size: 20)\n\n\tframe_str := 'Frame: ${stats.frame_count}'\n\tctx.draw_text(int(w) - 150, int(y), frame_str, color: text_color, size: 20)\n\n\t// Separator line\n\tctx.draw_line(0, f32(app.header_height), w, f32(app.header_height), grid_color)\n}\n\n// draw_histogram renders the allocation histogram\nfn draw_histogram(mut app App) {\n\tctx := app.gg\n\tw := f32(ctx.width)\n\n\t// Histogram area\n\thist_y := f32(app.header_height)\n\thist_h := f32(app.histogram_height)\n\tcenter_y := hist_y + hist_h / 2\n\n\t// Background\n\tctx.draw_rect_filled(0, hist_y, w, hist_h, bg_color)\n\n\t// Center line\n\tctx.draw_line(0, center_y, w, center_y, grid_color)\n\n\t// Get frame data (always use cached data - it's populated by update_cache from snapshot or demo)\n\tframes := app.cached_frames\n\tif frames.len == 0 {\n\t\tctx.draw_text(int(w / 2) - 80, int(center_y) - 10, 'No frame data',\n\t\t\tcolor: text_color\n\t\t\tsize:  18\n\t\t)\n\t\treturn\n\t}\n\n\t// Calculate max values for scaling\n\tmut max_new := u64(1)\n\tmut max_freed := u64(1)\n\tfor frame in frames {\n\t\tif frame.new_bytes > max_new {\n\t\t\tmax_new = frame.new_bytes\n\t\t}\n\t\tif frame.freed_bytes > max_freed {\n\t\t\tmax_freed = frame.freed_bytes\n\t\t}\n\t}\n\n\t// Bar dimensions\n\tmargin := f32(40)\n\tbar_area_width := w - margin * 2\n\tbar_width := bar_area_width / f32(frames.len)\n\tif bar_width < 1 {\n\t\treturn\n\t}\n\tbar_gap := bar_width * 0.1\n\tactual_bar_w := bar_width - bar_gap\n\n\tmax_bar_height := (hist_h / 2) - 10\n\n\t// Draw bars for each frame\n\tfor i, frame in frames {\n\t\tx := margin + f32(i) * bar_width\n\n\t\t// New allocations (cyan, above center)\n\t\tif frame.new_bytes > 0 {\n\t\t\tnew_height := f32(frame.new_bytes) / f32(max_new) * max_bar_height\n\t\t\tbar_color := if i == app.selected_frame { selected_color } else { new_alloc_color }\n\t\t\tctx.draw_rect_filled(x, center_y - new_height, actual_bar_w, new_height, bar_color)\n\t\t}\n\n\t\t// Freed allocations (purple, below center)\n\t\tif frame.freed_bytes > 0 {\n\t\t\tfreed_height := f32(frame.freed_bytes) / f32(max_freed) * max_bar_height\n\t\t\tbar_color := if i == app.selected_frame {\n\t\t\t\tgg.Color{150, 130, 255, 200}\n\t\t\t} else {\n\t\t\t\tfreed_color\n\t\t\t}\n\t\t\tctx.draw_rect_filled(x, center_y, actual_bar_w, freed_height, bar_color)\n\t\t}\n\n\t\t// Hover highlight\n\t\tif i == app.hover_frame && i != app.selected_frame {\n\t\t\tctx.draw_rect_empty(x - 1, hist_y + 5, actual_bar_w + 2, hist_h - 10, timeline_cursor)\n\t\t}\n\t}\n\n\t// Legend\n\tctx.draw_rect_filled(10, hist_y + 10, 12, 12, new_alloc_color)\n\tctx.draw_text(26, int(hist_y) + 8, 'New', color: text_color, size: 14)\n\n\tctx.draw_rect_filled(70, hist_y + 10, 12, 12, freed_color)\n\tctx.draw_text(86, int(hist_y) + 8, 'Freed', color: text_color, size: 14)\n\n\t// Separator line\n\tctx.draw_line(0, hist_y + hist_h, w, hist_y + hist_h, grid_color)\n}\n\n// draw_timeline renders the frame timeline with scrubber\nfn draw_timeline(mut app App) {\n\tctx := app.gg\n\tw := f32(ctx.width)\n\n\t// Timeline area\n\ttimeline_y := f32(app.header_height + app.histogram_height)\n\ttimeline_h := f32(app.timeline_height)\n\n\t// Background\n\tctx.draw_rect_filled(0, timeline_y, w, timeline_h, header_bg)\n\n\tframes := app.cached_frames\n\tif frames.len == 0 {\n\t\treturn\n\t}\n\n\t// Draw frame ticks\n\tmargin := f32(40)\n\ttick_area_width := w - margin * 2\n\ttick_spacing := tick_area_width / f32(frames.len)\n\n\t// Draw tick marks\n\tfor i := 0; i < frames.len; i++ {\n\t\tx := margin + f32(i) * tick_spacing\n\t\ttick_height := if i % 10 == 0 { f32(15) } else { f32(8) }\n\t\tctx.draw_line(x, timeline_y + 20, x, timeline_y + 20 + tick_height, grid_color)\n\n\t\t// Frame number labels every 10 frames\n\t\tif i % 10 == 0 && tick_spacing > 3 {\n\t\t\tctx.draw_text(int(x) - 10, int(timeline_y) + 40, '${i}', color: text_color, size: 12)\n\t\t}\n\t}\n\n\t// Draw selected frame cursor\n\tif app.selected_frame >= 0 && app.selected_frame < frames.len {\n\t\tcursor_x := margin + f32(app.selected_frame) * tick_spacing\n\t\t// Triangle cursor\n\t\tdraw_triangle_filled(ctx, cursor_x, timeline_y + 15, cursor_x - 8, timeline_y + 5,\n\t\t\tcursor_x + 8, timeline_y + 5, timeline_cursor)\n\n\t\t// Vertical line\n\t\tctx.draw_line(cursor_x, timeline_y + 15, cursor_x, timeline_y + timeline_h - 5,\n\t\t\ttimeline_cursor)\n\n\t\t// Frame info\n\t\tframe := frames[app.selected_frame]\n\t\tinfo := 'Frame ${app.selected_frame}: +${profiler.format_bytes(frame.new_bytes)} / -${profiler.format_bytes(frame.freed_bytes)}'\n\t\tctx.draw_text(int(w / 2) - 100, int(timeline_y) + 55, info, color: timeline_cursor, size: 16)\n\t}\n\n\t// Separator line\n\tctx.draw_line(0, timeline_y + timeline_h, w, timeline_y + timeline_h, grid_color)\n}\n\n// draw_controls renders the filter controls\nfn draw_controls(mut app App) {\n\tctx := app.gg\n\tw := f32(ctx.width)\n\n\t// Controls area\n\tctrl_y := f32(app.header_height + app.histogram_height + app.timeline_height)\n\tctrl_h := f32(app.controls_height)\n\n\t// Background\n\tctx.draw_rect_filled(0, ctrl_y, w, ctrl_h, bg_color)\n\n\t// Filter buttons\n\tmut x := f32(20)\n\ty := ctrl_y + 10\n\n\t// Filter label\n\tctx.draw_text(int(x), int(y), 'Filter:', color: text_color, size: 16)\n\tx += 60\n\n\t// Filter mode buttons\n\tfilters := ['All', 'Leaks', 'Large', 'Frame']\n\tmodes := [FilterMode.all, FilterMode.new_not_freed, FilterMode.large, FilterMode.current_frame]\n\n\tfor i, label in filters {\n\t\tbtn_w := f32(60)\n\t\tbtn_h := f32(24)\n\n\t\t// Highlight active filter\n\t\tbtn_color := if app.filter_mode == modes[i] { selected_color } else { header_bg }\n\t\tctx.draw_rect_filled(x, y - 2, btn_w, btn_h, btn_color)\n\t\tctx.draw_rect_empty(x, y - 2, btn_w, btn_h, grid_color)\n\n\t\tctx.draw_text(int(x) + 8, int(y), label, color: text_color, size: 14)\n\t\tx += btn_w + 10\n\t}\n\n\t// Separator line\n\tctx.draw_line(0, ctrl_y + ctrl_h, w, ctrl_y + ctrl_h, grid_color)\n}\n\n// draw_details renders the selection details panel\nfn draw_details(mut app App) {\n\tctx := app.gg\n\tw := f32(ctx.width)\n\th := f32(ctx.height)\n\n\t// Details area\n\tdetails_y := f32(app.header_height + app.histogram_height + app.timeline_height +\n\t\tapp.controls_height)\n\tdetails_h := h - details_y\n\n\t// Background\n\tctx.draw_rect_filled(0, details_y, w, details_h, header_bg)\n\n\t// Show selected allocation info or instructions\n\tif app.selected_alloc >= 0 {\n\t\tallocs := app.cached_allocs\n\t\tif app.selected_alloc < allocs.len {\n\t\t\talloc := allocs[app.selected_alloc]\n\n\t\t\t// Format allocation info\n\t\t\tptr_str := 'Address: 0x${voidptr(alloc.ptr):p}'\n\t\t\tsize_str := 'Size: ${profiler.format_bytes(u64(alloc.size))} (${alloc.size} bytes)'\n\t\t\tframe_str := 'Allocated: frame ${alloc.frame}'\n\t\t\tstatus_str := if alloc.freed {\n\t\t\t\t'Status: FREED (frame ${alloc.free_frame})'\n\t\t\t} else {\n\t\t\t\t'Status: LIVE (potential leak)'\n\t\t\t}\n\n\t\t\tstatus_color := if alloc.freed { freed_color } else { leak_color }\n\n\t\t\tmut y := details_y + 15\n\t\t\tctx.draw_text(20, int(y), ptr_str, color: text_color, size: 16)\n\n\t\t\tctx.draw_text(250, int(y), size_str, color: text_color, size: 16)\n\n\t\t\tctx.draw_text(500, int(y), frame_str, color: text_color, size: 16)\n\n\t\t\tctx.draw_text(700, int(y), status_str, color: status_color, size: 16)\n\n\t\t\t// Source location if available\n\t\t\tif alloc.file.len > 0 {\n\t\t\t\ty += 25\n\t\t\t\tloc_str := 'Source: ${alloc.file}:${alloc.line}'\n\t\t\t\tctx.draw_text(20, int(y), loc_str, color: new_alloc_color, size: 16)\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// Instructions\n\t\tctx.draw_text(20, int(details_y) + 20, 'Click on a histogram bar to select a frame, or use keyboard arrows to navigate',\n\t\t\tcolor: text_color\n\t\t\tsize:  16\n\t\t)\n\t}\n}\n\n// draw_frame is the main frame callback\npub fn draw_frame(mut app App) {\n\tif app.gg == unsafe { nil } {\n\t\treturn\n\t}\n\tapp.gg.begin()\n\n\t// Update data\n\tif app.demo_mode {\n\t\tupdate_demo_data(mut app)\n\t} else {\n\t\tapp.update_cache()\n\t}\n\n\t// Draw all sections\n\tdraw_header(mut app)\n\tdraw_histogram(mut app)\n\tdraw_timeline(mut app)\n\tdraw_controls(mut app)\n\tdraw_details(mut app)\n\n\t// Draw status message if in live mode with no data\n\tif app.live_mode && app.cached_frames.len == 0 {\n\t\tctx := app.gg\n\t\tw := f32(ctx.width)\n\t\th := f32(ctx.height)\n\t\tctx.draw_text(int(w / 2) - 200, int(h / 2), app.status_msg,\n\t\t\tcolor: text_color\n\t\t\tsize:  20\n\t\t)\n\t}\n\n\tapp.gg.end()\n}\n\n// Helper: draw a filled triangle\nfn draw_triangle_filled(ctx &gg.Context, x1 f32, y1 f32, x2 f32, y2 f32, x3 f32, y3 f32, c gg.Color) {\n\tctx.draw_convex_poly([x1, y1, x2, y2, x3, y3], c)\n}\n"
  },
  {
    "path": "cmd/v2/guiprof/events.v",
    "content": "// Copyright (c) 2020-2024 Joe Conigliaro. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nmodule main\n\nimport gg\nimport os\nimport v2.profiler\n\n// handle_event processes user input events\npub fn handle_event(e &gg.Event, mut app App) {\n\tmatch e.typ {\n\t\t.mouse_down {\n\t\t\thandle_mouse_click(e, mut app)\n\t\t}\n\t\t.mouse_move {\n\t\t\thandle_mouse_move(e, mut app)\n\t\t}\n\t\t.key_down {\n\t\t\thandle_key_down(e, mut app)\n\t\t}\n\t\telse {}\n\t}\n}\n\n// handle_mouse_click processes mouse click events\nfn handle_mouse_click(e &gg.Event, mut app App) {\n\tx := e.mouse_x\n\ty := e.mouse_y\n\n\t// Check which region was clicked\n\thist_y := f32(app.header_height)\n\thist_h := f32(app.histogram_height)\n\ttimeline_y := hist_y + hist_h\n\ttimeline_h := f32(app.timeline_height)\n\tctrl_y := timeline_y + timeline_h\n\tctrl_h := f32(app.controls_height)\n\n\t// Click in histogram area\n\tif y >= hist_y && y < hist_y + hist_h {\n\t\thandle_histogram_click(x, y, mut app)\n\t\treturn\n\t}\n\n\t// Click in timeline area\n\tif y >= timeline_y && y < timeline_y + timeline_h {\n\t\thandle_timeline_click(x, y, mut app)\n\t\treturn\n\t}\n\n\t// Click in controls area\n\tif y >= ctrl_y && y < ctrl_y + ctrl_h {\n\t\thandle_controls_click(x, y, mut app)\n\t\treturn\n\t}\n}\n\n// handle_histogram_click selects a frame from the histogram\nfn handle_histogram_click(x f32, y f32, mut app App) {\n\tframes := app.cached_frames\n\tif frames.len == 0 {\n\t\treturn\n\t}\n\n\tw := f32(app.gg.width)\n\tmargin := f32(40)\n\tbar_area_width := w - margin * 2\n\n\t// Calculate frame index\n\trelative_x := x - margin\n\tif relative_x < 0 || relative_x > bar_area_width {\n\t\treturn\n\t}\n\n\tbar_width := bar_area_width / f32(frames.len)\n\tframe_idx := int(relative_x / bar_width)\n\n\tif frame_idx >= 0 && frame_idx < frames.len {\n\t\tapp.selected_frame = frame_idx\n\t\t// Select first allocation in this frame\n\t\tallocs := app.cached_allocs\n\t\tfor i, alloc in allocs {\n\t\t\tif alloc.frame == u64(frame_idx) {\n\t\t\t\tapp.selected_alloc = i\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\n// handle_timeline_click scrubs the timeline\nfn handle_timeline_click(x f32, y f32, mut app App) {\n\t// Same logic as histogram click for frame selection\n\thandle_histogram_click(x, y, mut app)\n}\n\n// handle_controls_click handles filter button clicks\nfn handle_controls_click(x f32, y f32, mut app App) {\n\t// Filter buttons start at x=80\n\tbtn_start := f32(80)\n\tbtn_w := f32(60)\n\tbtn_gap := f32(10)\n\n\trelative_x := x - btn_start\n\tif relative_x < 0 {\n\t\treturn\n\t}\n\n\tbtn_idx := int(relative_x / (btn_w + btn_gap))\n\tmodes := [FilterMode.all, FilterMode.new_not_freed, FilterMode.large, FilterMode.current_frame]\n\n\tif btn_idx >= 0 && btn_idx < modes.len {\n\t\tapp.filter_mode = modes[btn_idx]\n\t}\n}\n\n// handle_mouse_move updates hover state\nfn handle_mouse_move(e &gg.Event, mut app App) {\n\tx := e.mouse_x\n\ty := e.mouse_y\n\n\thist_y := f32(app.header_height)\n\thist_h := f32(app.histogram_height)\n\n\t// Check if hovering over histogram\n\tif y >= hist_y && y < hist_y + hist_h {\n\t\tframes := app.cached_frames\n\t\tif frames.len > 0 {\n\t\t\tw := f32(app.gg.width)\n\t\t\tmargin := f32(40)\n\t\t\tbar_area_width := w - margin * 2\n\t\t\trelative_x := x - margin\n\n\t\t\tif relative_x >= 0 && relative_x <= bar_area_width {\n\t\t\t\tbar_width := bar_area_width / f32(frames.len)\n\t\t\t\tapp.hover_frame = int(relative_x / bar_width)\n\t\t\t\tif app.hover_frame >= frames.len {\n\t\t\t\t\tapp.hover_frame = -1\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tapp.hover_frame = -1\n\t\t\t}\n\t\t}\n\t} else {\n\t\tapp.hover_frame = -1\n\t}\n}\n\n// handle_key_down processes keyboard input\nfn handle_key_down(e &gg.Event, mut app App) {\n\tmatch e.key_code {\n\t\t.left {\n\t\t\t// Previous frame\n\t\t\tif app.selected_frame > 0 {\n\t\t\t\tapp.selected_frame--\n\t\t\t}\n\t\t}\n\t\t.right {\n\t\t\t// Next frame\n\t\t\tframes := app.cached_frames\n\t\t\tif app.selected_frame < frames.len - 1 {\n\t\t\t\tapp.selected_frame++\n\t\t\t}\n\t\t}\n\t\t.up {\n\t\t\t// Previous allocation\n\t\t\tif app.selected_alloc > 0 {\n\t\t\t\tapp.selected_alloc--\n\t\t\t}\n\t\t}\n\t\t.down {\n\t\t\t// Next allocation\n\t\t\tallocs := app.cached_allocs\n\t\t\tif app.selected_alloc < allocs.len - 1 {\n\t\t\t\tapp.selected_alloc++\n\t\t\t}\n\t\t}\n\t\t.enter {\n\t\t\t// Open source file in editor\n\t\t\topen_in_editor(app)\n\t\t}\n\t\t.f {\n\t\t\t// Cycle filter modes\n\t\t\tapp.filter_mode = match app.filter_mode {\n\t\t\t\t.all { .new_not_freed }\n\t\t\t\t.new_not_freed { .large }\n\t\t\t\t.large { .current_frame }\n\t\t\t\t.current_frame { .all }\n\t\t\t}\n\t\t}\n\t\t.r {\n\t\t\t// Reset profiler data\n\t\t\tif !app.demo_mode {\n\t\t\t\tprofiler.reset()\n\t\t\t}\n\t\t}\n\t\t.escape {\n\t\t\t// Clear selection\n\t\t\tapp.selected_frame = -1\n\t\t\tapp.selected_alloc = -1\n\t\t}\n\t\t.space {\n\t\t\t// Toggle demo mode\n\t\t\tapp.demo_mode = !app.demo_mode\n\t\t\tif app.demo_mode {\n\t\t\t\t// Initialize demo data\n\t\t\t\tinit_demo_data(mut app)\n\t\t\t}\n\t\t}\n\t\telse {}\n\t}\n}\n\n// open_in_editor opens the selected allocation's source file in VS Code\nfn open_in_editor(app &App) {\n\tif app.selected_alloc < 0 {\n\t\treturn\n\t}\n\n\tallocs := app.cached_allocs\n\tif app.selected_alloc >= allocs.len {\n\t\treturn\n\t}\n\n\talloc := allocs[app.selected_alloc]\n\tif alloc.file.len == 0 {\n\t\treturn\n\t}\n\n\t// Try to open in VS Code with line number\n\tcmd := 'code -g \"${alloc.file}:${alloc.line}\"'\n\tos.execute(cmd)\n}\n"
  },
  {
    "path": "cmd/v2/guiprof/main.v",
    "content": "// Copyright (c) 2020-2024 Joe Conigliaro. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nmodule main\n\nimport gg\nimport os\nimport v2.profiler\n\nfn main() {\n\t// Initialize profiler system\n\tprofiler.profiler_init()\n\n\t// Create application state (on stack, like the working example)\n\tmut app := App{}\n\n\t// Check command line args for mode\n\targs := os.args\n\tif '--demo' in args {\n\t\tapp.demo_mode = true\n\t\tapp.live_mode = false\n\t\tinit_demo_data(mut app)\n\t} else {\n\t\t// Default to live mode - read from snapshot file\n\t\tapp.demo_mode = false\n\t\tapp.live_mode = true\n\t}\n\n\t// Create gg context\n\tapp.gg = gg.new_context(\n\t\twidth:         window_width\n\t\theight:        window_height\n\t\tcreate_window: true\n\t\twindow_title:  'V2 Allocation Profiler'\n\t\tbg_color:      bg_color\n\t\tframe_fn:      frame\n\t\tevent_fn:      event_handler\n\t\tuser_data:     &app\n\t)\n\n\t// Run the application\n\tapp.gg.run()\n}\n\n// frame is the frame callback for gg\nfn frame(mut app App) {\n\tdraw_frame(mut app)\n}\n\n// event_handler handles gg events\nfn event_handler(e &gg.Event, mut app App) {\n\thandle_event(e, mut app)\n}\n\n// init_demo_data populates the profiler with simulated data for demonstration\nfn init_demo_data(mut app App) {\n\tapp.demo_mode = true\n\tapp.demo_frame = 0\n\n\t// Create simulated frame and allocation data\n\tapp.cached_frames = []profiler.FrameData{cap: 100}\n\tapp.cached_allocs = []profiler.AllocRecord{cap: 500}\n\n\t// Simulate 100 frames of allocation activity\n\tmut total_live := u64(0)\n\tmut peak := u64(0)\n\tmut alloc_idx := 0\n\tmut total_allocs := u64(0)\n\tmut total_frees := u64(0)\n\n\tfor frame_num := 0; frame_num < 100; frame_num++ {\n\t\tmut frame_data := profiler.FrameData{\n\t\t\tframe_num: u64(frame_num)\n\t\t}\n\n\t\t// Simulate some allocations each frame\n\t\t// More allocations early, fewer later (typical startup pattern)\n\t\tnum_allocs := if frame_num < 20 { 10 - frame_num / 4 } else { 2 + (frame_num % 3) }\n\n\t\tfor _ in 0 .. num_allocs {\n\t\t\t// Random-ish allocation sizes\n\t\t\tsize := 64 + ((frame_num * 17 + alloc_idx * 31) % 4096)\n\n\t\t\tapp.cached_allocs << profiler.AllocRecord{\n\t\t\t\tptr:       unsafe { voidptr(u64(0x1000) + u64(alloc_idx) * 0x100) }\n\t\t\t\tsize:      size\n\t\t\t\tframe:     u64(frame_num)\n\t\t\t\tfile:      ['main.v', 'parser.v', 'scanner.v', 'types.v', 'gen.v'][alloc_idx % 5]\n\t\t\t\tline:      100 + (alloc_idx % 500)\n\t\t\t\ttimestamp: i64(frame_num) * 16_666_667 + i64(alloc_idx) * 1000\n\t\t\t\tfreed:     false\n\t\t\t}\n\n\t\t\tframe_data.new_allocs << alloc_idx\n\t\t\tframe_data.new_bytes += u64(size)\n\t\t\ttotal_live += u64(size)\n\t\t\ttotal_allocs++\n\t\t\talloc_idx++\n\t\t}\n\n\t\t// Simulate some frees (but not all - create some \"leaks\")\n\t\t// Free some allocations from previous frames\n\t\tif frame_num > 5 {\n\t\t\tnum_frees := num_allocs - 1 // Always free slightly fewer than we allocate\n\t\t\tmut freed_count := 0\n\t\t\tfor i := 0; i < app.cached_allocs.len && freed_count < num_frees; i++ {\n\t\t\t\tif !app.cached_allocs[i].freed && app.cached_allocs[i].frame < u64(frame_num - 3) {\n\t\t\t\t\t// 80% chance to free\n\t\t\t\t\tif (i * 7 + frame_num * 13) % 10 < 8 {\n\t\t\t\t\t\tapp.cached_allocs[i].freed = true\n\t\t\t\t\t\tapp.cached_allocs[i].free_frame = u64(frame_num)\n\t\t\t\t\t\tframe_data.freed_idxs << i\n\t\t\t\t\t\tframe_data.freed_bytes += u64(app.cached_allocs[i].size)\n\t\t\t\t\t\ttotal_live -= u64(app.cached_allocs[i].size)\n\t\t\t\t\t\ttotal_frees++\n\t\t\t\t\t\tfreed_count++\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tframe_data.live_bytes = total_live\n\t\tif total_live > peak {\n\t\t\tpeak = total_live\n\t\t}\n\n\t\tapp.cached_frames << frame_data\n\t}\n\n\t// Count leaks\n\tmut leak_count := 0\n\tfor alloc in app.cached_allocs {\n\t\tif !alloc.freed {\n\t\t\tleak_count++\n\t\t}\n\t}\n\n\t// Update stats\n\tapp.cached_stats = profiler.Statistics{\n\t\tlive_bytes:   total_live\n\t\tpeak_bytes:   peak\n\t\ttotal_allocs: total_allocs\n\t\ttotal_frees:  total_frees\n\t\tleak_count:   leak_count\n\t\tframe_count:  100\n\t}\n}\n\n// update_demo_data simulates ongoing activity in demo mode\nfn update_demo_data(mut app App) {\n\t// In demo mode, we just use the static simulated data\n\t// For a more dynamic demo, we could add new frames here\n\tapp.demo_frame++\n}\n"
  },
  {
    "path": "cmd/v2/guiprof/state.v",
    "content": "// Copyright (c) 2020-2024 Joe Conigliaro. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nmodule main\n\nimport gg\nimport v2.profiler\n\n// Filter modes for allocation view\npub enum FilterMode {\n\tall           // Show all allocations\n\tnew_not_freed // Show allocations that haven't been freed (potential leaks)\n\tlarge         // Show allocations larger than threshold\n\tcurrent_frame // Show allocations from selected frame only\n}\n\n// App holds the GUI application state\npub struct App {\npub mut:\n\tgg &gg.Context = unsafe { nil }\n\t// View state\n\tselected_frame  int        = -1 // -1 means no selection\n\tselected_alloc  int        = -1 // Index of selected allocation\n\tfilter_mode     FilterMode = .all\n\tlarge_threshold int        = 1024 // Threshold for \"large\" filter (bytes)\n\tsearch_text     string\n\t// Scroll/pan state\n\ttimeline_scroll  int // Horizontal scroll for timeline\n\thistogram_scroll int // Scroll for histogram if needed\n\t// Cached data (updated each frame)\n\tcached_frames []profiler.FrameData\n\tcached_allocs []profiler.AllocRecord\n\tcached_stats  profiler.Statistics\n\t// Layout dimensions\n\theader_height    int = 60\n\thistogram_height int = 200\n\ttimeline_height  int = 80\n\tcontrols_height  int = 40\n\tdetails_height   int = 60\n\t// Hover state\n\thover_frame int = -1\n\thover_alloc int = -1\n\t// Mode\n\tdemo_mode  bool // Use simulated data for demo (false = live mode)\n\tdemo_frame int  // Current demo frame counter\n\tlive_mode  bool = true // Read from profiler snapshot file\n\t// Status\n\tstatus_msg string = 'Waiting for profiler data...'\n}\n\n// Colors for the profiler visualization\npub const bg_color = gg.Color{30, 30, 30, 255} // Dark gray background\npub const new_alloc_color = gg.Color{0, 200, 255, 200} // Cyan for new allocations\npub const freed_color = gg.Color{180, 100, 255, 200} // Purple for freed allocations\npub const leak_color = gg.Color{255, 100, 100, 255} // Red for leaks/live\npub const timeline_cursor = gg.Color{255, 255, 0, 255} // Yellow for timeline cursor\npub const text_color = gg.Color{220, 220, 220, 255} // Light gray text\npub const header_bg = gg.Color{40, 40, 45, 255} // Slightly lighter header\npub const grid_color = gg.Color{60, 60, 60, 255} // Grid lines\npub const selected_color = gg.Color{100, 150, 255, 255} // Selection highlight\n\n// Window dimensions\npub const window_width = 1200\npub const window_height = 700\n\n// init_app creates a new App instance (unused, kept for reference)\nfn init_app_heap() &App {\n\treturn &App{}\n}\n\n// update_cache refreshes cached profiler data\npub fn (mut app App) update_cache() {\n\tif app.demo_mode {\n\t\treturn\n\t}\n\n\tif app.live_mode {\n\t\t// Read from snapshot file\n\t\tif snap := profiler.read_snapshot() {\n\t\t\tapp.cached_frames = snap.frames\n\t\t\tapp.cached_allocs = snap.allocs\n\t\t\tapp.cached_stats = profiler.Statistics{\n\t\t\t\tlive_bytes:   snap.live_bytes\n\t\t\t\tpeak_bytes:   snap.peak_bytes\n\t\t\t\ttotal_allocs: snap.total_allocs\n\t\t\t\ttotal_frees:  snap.total_frees\n\t\t\t\tleak_count:   count_leaks(snap.allocs)\n\t\t\t\tframe_count:  snap.frame_count\n\t\t\t}\n\t\t\tapp.status_msg = 'Live: Frame ${snap.frame_count}'\n\t\t} else {\n\t\t\tapp.status_msg = 'Waiting for profiler data at ${profiler.profiler_data_path}...'\n\t\t}\n\t\treturn\n\t}\n\n\t// In-process mode (same process)\n\tapp.cached_frames = profiler.get_frames()\n\tapp.cached_allocs = profiler.get_allocs()\n\tapp.cached_stats = profiler.get_statistics()\n}\n\nfn count_leaks(allocs []profiler.AllocRecord) int {\n\tmut count := 0\n\tfor alloc in allocs {\n\t\tif !alloc.freed {\n\t\t\tcount++\n\t\t}\n\t}\n\treturn count\n}\n\n// get_filtered_allocs returns allocations matching current filter\npub fn (app &App) get_filtered_allocs() []profiler.AllocRecord {\n\tmut result := []profiler.AllocRecord{}\n\n\tallocs := app.cached_allocs\n\n\tfor alloc in allocs {\n\t\tmatch app.filter_mode {\n\t\t\t.all {\n\t\t\t\tresult << alloc\n\t\t\t}\n\t\t\t.new_not_freed {\n\t\t\t\tif !alloc.freed {\n\t\t\t\t\tresult << alloc\n\t\t\t\t}\n\t\t\t}\n\t\t\t.large {\n\t\t\t\tif alloc.size >= app.large_threshold {\n\t\t\t\t\tresult << alloc\n\t\t\t\t}\n\t\t\t}\n\t\t\t.current_frame {\n\t\t\t\tif app.selected_frame >= 0 && alloc.frame == u64(app.selected_frame) {\n\t\t\t\t\tresult << alloc\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Apply search filter if text is present\n\tif app.search_text.len > 0 {\n\t\tmut filtered := []profiler.AllocRecord{}\n\t\tfor alloc in result {\n\t\t\tif alloc.file.contains(app.search_text) {\n\t\t\t\tfiltered << alloc\n\t\t\t}\n\t\t}\n\t\treturn filtered\n\t}\n\n\treturn result\n}\n\n// get_frame_at_x returns the frame index at the given x coordinate in timeline\npub fn (app &App) get_frame_at_x(x f32, timeline_x f32, timeline_width f32) int {\n\tframes := app.cached_frames\n\tif frames.len == 0 {\n\t\treturn -1\n\t}\n\n\t// Calculate which frame this x position corresponds to\n\trelative_x := x - timeline_x\n\tif relative_x < 0 || relative_x > timeline_width {\n\t\treturn -1\n\t}\n\n\tframe_width := timeline_width / f32(frames.len)\n\tframe_idx := int(relative_x / frame_width)\n\n\tif frame_idx >= 0 && frame_idx < frames.len {\n\t\treturn frame_idx\n\t}\n\treturn -1\n}\n"
  },
  {
    "path": "cmd/v2/test.v",
    "content": "const pi = 3\n\nstruct Point {\nmut:\n\tx int\n\ty int\n}\n\nstruct Rectangle {\nmut:\n\twidth  int\n\theight int\n\torigin Point\n}\n\nstruct Node {\nmut:\n\tvalue int\n\tleft  int\n\tright int\n}\n\n// For testing array.clone() on nested selectors\nstruct ArrayHolder {\nmut:\n\tdata []int\n}\n\nstruct Wrapper {\nmut:\n\tholder &ArrayHolder\n}\n\n// For testing map indexing with push (map[key] << value)\nstruct PendingLabels {\nmut:\n\tlabels map[int][]int\n}\n\n// For testing array push in map iteration\nstruct Error76 {\n\tmsg    string\n\tval_id int\n}\n\nenum Color {\n\tred\n\tgreen\n\tblue\n\tyellow\n}\n\nenum Status {\n\tpending = 0\n\tactive  = 1\n\tdone    = 2\n}\n\n// Flag enum for bitfield operations\n@[flag]\nenum Permissions {\n\tread\n\twrite\n\texecute\n}\n\n// Enum for testing match with different return type\nenum Operator {\n\tplus\n\tminus\n\tmul\n\tdiv\n}\n\n// Enum for binding power - return type differs from match expression type\nenum BindingPower {\n\tlowest\n\tlow\n\tmedium\n\thigh\n}\n\n// Interface declaration\ninterface Drawable {\n\tdraw() int\n}\n\n// Another interface with multiple methods\ninterface Shape {\n\tarea() int\n\tperimeter() int\n}\n\n// Interface with methods that take parameters\ninterface Calculator {\n\tadd(a int, b int) int\n\tmultiply(x int) int\n}\n\n// Type alias\ntype MyInt = int\n\n// Sum type\ntype Number = int | Point\n\n// For testing nested smartcasts (outer sum type contains inner sum type)\ntype NestedOuter = Number | Rectangle\n\n__global (\n\tg_val   int\n\tg_count int\n\tg_flag  bool\n\tg_point Point\n)\n\n// ===================== METHODS =====================\n\n// Method that returns a different enum type than the receiver enum type\n// Tests that match conditions use the correct enum (Operator) not the return type (BindingPower)\nfn (op Operator) get_binding_power() BindingPower {\n\treturn match op {\n\t\t.plus, .minus { .low }\n\t\t.mul, .div { .medium }\n\t}\n}\n\nfn (p Point) sum() int {\n\treturn p.x + p.y\n}\n\n// Implements Drawable interface\nfn (p Point) draw() int {\n\t// Return a unique identifier for drawing\n\treturn p.x * 1000 + p.y\n}\n\nfn (p Point) product() int {\n\treturn p.x * p.y\n}\n\nfn (p Point) scaled(factor int) Point {\n\treturn Point{\n\t\tx: p.x * factor\n\t\ty: p.y * factor\n\t}\n}\n\nfn (mut p Point) double() {\n\tp.x = p.x * 2\n\tp.y = p.y * 2\n}\n\n// Implements Calculator interface\nfn (p Point) add(a int, b int) int {\n\treturn p.x + p.y + a + b\n}\n\nfn (p Point) multiply(x int) int {\n\treturn (p.x + p.y) * x\n}\n\nfn (r Rectangle) area() int {\n\treturn r.width * r.height\n}\n\nfn (r Rectangle) perimeter() int {\n\treturn 2 * (r.width + r.height)\n}\n\nfn (n Node) total() int {\n\treturn n.value + n.left + n.right\n}\n\n// ===================== HELPER FUNCTIONS =====================\n\n// For test 77: process_number takes a Number sum type and returns a value\n// This tests that smartcasted variables inside match branches can be passed\n// to functions expecting the original sum type\nfn process_number(n Number) int {\n\tmatch n {\n\t\tint { return n }\n\t\tPoint { return n.x + n.y }\n\t}\n}\n\nfn fib(n int) int {\n\tif n < 2 {\n\t\treturn n\n\t}\n\treturn fib(n - 1) + fib(n - 2)\n}\n\nfn factorial(n int) int {\n\tif n <= 1 {\n\t\treturn 1\n\t}\n\treturn n * factorial(n - 1)\n}\n\nfn sum_recursive(n int) int {\n\tif n <= 0 {\n\t\treturn 0\n\t}\n\treturn n + sum_recursive(n - 1)\n}\n\nfn gcd(a int, b int) int {\n\tif b == 0 {\n\t\treturn a\n\t}\n\treturn gcd(b, a % b)\n}\n\n// Multi-return functions\nfn swap(a int, b int) (int, int) {\n\treturn b, a\n}\n\nfn divmod(a int, b int) (int, int) {\n\treturn a / b, a % b\n}\n\nfn min_max(a int, b int, c int) (int, int) {\n\tmut min := a\n\tmut max := a\n\tif b < min {\n\t\tmin = b\n\t}\n\tif b > max {\n\t\tmax = b\n\t}\n\tif c < min {\n\t\tmin = c\n\t}\n\tif c > max {\n\t\tmax = c\n\t}\n\treturn min, max\n}\n\nfn triple_return(x int) (int, int, int) {\n\treturn x, x * 2, x * 3\n}\n\nfn power(base int, exp int) int {\n\tif exp == 0 {\n\t\treturn 1\n\t}\n\treturn base * power(base, exp - 1)\n}\n\nfn sum_many(a int, b int, c int, d int, e int, f int, g int, h int) int {\n\treturn a + b + c + d + e + f + g + h\n}\n\nfn mul_many(a int, b int, c int, d int, e int, f int, g int, h int) int {\n\treturn a * b * c * d * e * f * g * h\n}\n\nfn max_of_eight(a int, b int, c int, d int, e int, f int, g int, h int) int {\n\tmut m := a\n\tif b > m {\n\t\tm = b\n\t}\n\tif c > m {\n\t\tm = c\n\t}\n\tif d > m {\n\t\tm = d\n\t}\n\tif e > m {\n\t\tm = e\n\t}\n\tif f > m {\n\t\tm = f\n\t}\n\tif g > m {\n\t\tm = g\n\t}\n\tif h > m {\n\t\tm = h\n\t}\n\treturn m\n}\n\nfn weighted_sum(a int, b int, c int, d int, e int, f int, g int, h int) int {\n\treturn a * 1 + b * 2 + c * 3 + d * 4 + e * 5 + f * 6 + g * 7 + h * 8\n}\n\nfn modify_struct(mut p Point) {\n\tp.x = 999\n\tp.y = 888\n}\n\nfn swap_point(mut p Point) {\n\ttmp := p.x\n\tp.x = p.y\n\tp.y = tmp\n}\n\nfn scale_point(mut p Point, factor int) {\n\tp.x = p.x * factor\n\tp.y = p.y * factor\n}\n\nfn translate_point(mut p Point, dx int, dy int) {\n\tp.x = p.x + dx\n\tp.y = p.y + dy\n}\n\nfn reset_point(mut p Point) {\n\tp.x = 0\n\tp.y = 0\n}\n\nfn add(a int, b int) int {\n\treturn a + b\n}\n\nfn sub(a int, b int) int {\n\treturn a - b\n}\n\nfn mul(a int, b int) int {\n\treturn a * b\n}\n\nfn print_rec(n int) {\n\tif n == 0 {\n\t\treturn\n\t}\n\tprint_rec(n / 10)\n\trem := n - (n / 10) * 10\n\tC.putchar(rem + 48)\n}\n\nfn print_int(n int) {\n\tif n == 0 {\n\t\tC.putchar(48)\n\t\tC.putchar(10)\n\t\treturn\n\t}\n\tmut v := n\n\tif n < 0 {\n\t\tC.putchar(45)\n\t\tv = 0 - n\n\t}\n\tprint_rec(v)\n\tC.putchar(10)\n}\n\nfn print_str(s string) {\n\tC.puts(s.str)\n}\n\n// C function with keyword name (tests parser allowing keywords after C.)\nfn C.select(ndfs i32, readfds voidptr, writefds voidptr, exceptfds voidptr, timeout voidptr) i32\n\nfn nested_return(x int) int {\n\tif x < 10 {\n\t\treturn 100\n\t} else {\n\t\tif x < 20 {\n\t\t\treturn 200\n\t\t} else {\n\t\t\treturn 300\n\t\t}\n\t}\n}\n\n// Helper for comptime test\nfn get_comptime_value() int {\n\t$if macos {\n\t\treturn 50\n\t} $else $if linux {\n\t\treturn 51\n\t} $else $if windows {\n\t\treturn 52\n\t} $else {\n\t\treturn 59\n\t}\n}\n\n// Function using type alias (type alias is same as base type in C)\nfn add_my_ints(a int, b int) int {\n\treturn a + b\n}\n\n// Helper function to test defer with explicit return\nfn defer_test() int {\n\tmut x := 0\n\tdefer {\n\t\tx = 42\n\t}\n\treturn x + 42 // Return 42, but x is modified by defer before return\n}\n\n// Helper function to test defer order (LIFO)\nfn defer_order_test() {\n\tdefer {\n\t\tprint_str('First')\n\t}\n\tdefer {\n\t\tprint_str('Second')\n\t}\n\tdefer {\n\t\tprint_str('Third')\n\t}\n}\n\n// Helper function to test defer(fn) - function-level defer\nfn defer_fn_test() int {\n\tmut x := 0\n\tfor i := 0; i < 3; i++ {\n\t\tdefer(fn) {\n\t\t\tx += 100\n\t\t}\n\t\tx += 1\n\t}\n\treturn x // returns 3, but defer(fn) adds 300 at function end\n}\n\n// ===================== FLAG ENUM TEST =====================\n\nfn flag_enum_test() int {\n\t// Test flag enum .has() method\n\t// Use fully qualified enum values (shorthand in | expr needs type inference)\n\tperms := Permissions.read | Permissions.write\n\tmut result := 0\n\tif perms.has(.read) {\n\t\tresult += 1\n\t}\n\tif perms.has(.write) {\n\t\tresult += 2\n\t}\n\tif perms.has(.execute) {\n\t\tresult += 4 // Should NOT execute\n\t}\n\t// Test .all() method - use fully qualified for | in argument\n\tif perms.all(Permissions.read | Permissions.write) {\n\t\tresult += 10\n\t}\n\tif perms.all(Permissions.read | Permissions.execute) {\n\t\tresult += 20 // Should NOT execute\n\t}\n\treturn result // Expected: 1 + 2 + 10 = 13\n}\n\n// Debug test for flag enum - returns raw value of perms\nfn flag_enum_debug() int {\n\t// This should be: read (1) | write (2) = 3\n\tperms := Permissions.read | Permissions.write\n\treturn int(perms) // Expected: 3\n}\n\n// Debug test - return has(.read) as int\nfn flag_enum_has_read() int {\n\tperms := Permissions.read | Permissions.write\n\tif perms.has(.read) {\n\t\treturn 1\n\t}\n\treturn 0\n}\n\n// Debug test - return has(.execute) as int\nfn flag_enum_has_execute() int {\n\tperms := Permissions.read | Permissions.write\n\tif perms.has(.execute) {\n\t\treturn 1 // Should NOT return this\n\t}\n\treturn 0 // Expected: 0\n}\n\n// Debug test - return values of individual enum members\nfn flag_enum_values() int {\n\tr := int(Permissions.read) // Expected: 1\n\tw := int(Permissions.write) // Expected: 2\n\te := int(Permissions.execute) // Expected: 4\n\treturn r + w * 10 + e * 100 // Expected: 1 + 20 + 400 = 421\n}\n\n// Debug test - raw AND operation\nfn flag_enum_and_test() int {\n\tperms := Permissions.read | Permissions.write // 3\n\texec := Permissions.execute // 4\n\tresult := int(perms) & int(exec) // 3 & 4 = 0\n\treturn result // Expected: 0\n}\n\n// Debug test - manual has check without calling has() method\nfn flag_enum_manual_has() int {\n\tperms := Permissions.read | Permissions.write // 3\n\texec := Permissions.execute // 4\n\tanded := int(perms) & int(exec) // 3 & 4 = 0\n\tif anded != 0 {\n\t\treturn 1 // Should NOT return this\n\t}\n\treturn 0 // Expected: 0\n}\n\n// Debug test - return has() result directly as int (no if)\nfn flag_enum_has_result() int {\n\tperms := Permissions.read | Permissions.write\n\tresult := perms.has(.execute)\n\treturn int(result) // Expected: 0 (false)\n}\n\n// Debug test - manual implementation of has() logic\nfn flag_enum_manual_has_impl(self int, flag int) int {\n\tanded := self & flag\n\tif anded != 0 {\n\t\treturn 1\n\t}\n\treturn 0\n}\n\n// Debug test - call manual has impl\nfn flag_enum_manual_call() int {\n\tperms := Permissions.read | Permissions.write // 3\n\texec := Permissions.execute // 4\n\treturn flag_enum_manual_has_impl(int(perms), int(exec)) // Expected: 0\n}\n\n// Debug test - check what values the has() gets\n// This is exactly like has() but returns the args\nfn flag_enum_debug_args(self Permissions, flag Permissions) int {\n\t// Return self * 100 + flag so we can see both values\n\treturn int(self) * 100 + int(flag)\n}\n\n// Debug test - call debug_args (without shorthand)\nfn flag_enum_check_args() int {\n\tperms := Permissions.read | Permissions.write // 3\n\texec := Permissions.execute // 4\n\treturn flag_enum_debug_args(perms, exec) // Expected: 304 (3 * 100 + 4)\n}\n\n// Debug test - simple 2-arg function with ints\nfn simple_two_arg(a int, b int) int {\n\treturn a * 100 + b\n}\n\n// Debug test - call simple 2-arg function\nfn flag_enum_check_int_args() int {\n\treturn simple_two_arg(3, 4) // Expected: 304\n}\n\nfn test_flag_enum_set_clear() {\n\tmut p := Permissions.read\n\t// .set() adds a flag\n\tp.set(.write)\n\tassert p.has(.read)\n\tassert p.has(.write)\n\tassert !p.has(.execute)\n\tprint_int(int(p)) // 3 (read=1 | write=2)\n\n\t// .set() another flag\n\tp.set(.execute)\n\tassert p.has(.execute)\n\tassert p.all(Permissions.read | Permissions.write | Permissions.execute)\n\tprint_int(int(p)) // 7 (1|2|4)\n\n\t// .clear() removes a flag\n\tp.clear(.write)\n\tassert p.has(.read)\n\tassert !p.has(.write)\n\tassert p.has(.execute)\n\tprint_int(int(p)) // 5 (read=1 | execute=4)\n\n\t// .clear() then .set() same flag\n\tp.clear(.read)\n\tp.set(.write)\n\tassert !p.has(.read)\n\tassert p.has(.write)\n\tassert p.has(.execute)\n\tprint_int(int(p)) // 6 (write=2 | execute=4)\n}\n\n// ===================== IF-GUARD HELPERS =====================\n\n// Returns the value if positive, none otherwise\nfn maybe_positive(x int) ?int {\n\tif x > 0 {\n\t\treturn x\n\t}\n\treturn none\n}\n\n// Returns the doubled value if in range, none otherwise\nfn maybe_double(x int) ?int {\n\tif x >= 0 && x <= 50 {\n\t\treturn x * 2\n\t}\n\treturn none\n}\n\n// Returns sum if both positive, none otherwise\nfn maybe_sum(a int, b int) ?int {\n\tif a > 0 && b > 0 {\n\t\treturn a + b\n\t}\n\treturn none\n}\n\n// Uses `or { return }` pattern to propagate none\nfn maybe_triple(x int) ?int {\n\tval := maybe_positive(x) or { return none }\n\treturn val * 3\n}\n\nfn maybe_fail(x int) !int {\n\tif x >= 0 {\n\t\treturn x\n\t}\n\treturn error('negative value')\n}\n\n// ===================== IF-EXPRESSION HELPERS =====================\n\nfn int_abs(a int) int {\n\treturn if a < 0 { -a } else { a }\n}\n\nfn int_max2(a int, b int) int {\n\treturn if a > b { a } else { b }\n}\n\nfn int_min2(a int, b int) int {\n\treturn if a < b { a } else { b }\n}\n\nfn sign(x int) int {\n\treturn if x < 0 {\n\t\t-1\n\t} else {\n\t\tif x > 0 {\n\t\t\t1\n\t\t} else {\n\t\t\t0\n\t\t}\n\t}\n}\n\nfn clamp(x int, lo int, hi int) int {\n\treturn if x < lo {\n\t\tlo\n\t} else {\n\t\tif x > hi {\n\t\t\thi\n\t\t} else {\n\t\t\tx\n\t\t}\n\t}\n}\n\n// Helper functions for mutable slice argument tests\nfn read_from_slice(arr []int) int {\n\tmut sum := 0\n\tfor i := 0; i < arr.len; i++ {\n\t\tsum += arr[i]\n\t}\n\treturn sum\n}\n\nfn write_to_slice(mut arr []int, val int) {\n\tfor i := 0; i < arr.len; i++ {\n\t\tarr[i] = val\n\t}\n}\n\n// Helper function for map index with or block test\nfn map_lookup_with_or(m map[string]int, key string) int {\n\t// Test pattern: map[key] or { fallback_value }\n\tval := m[key] or { -1 }\n\treturn val\n}\n\n// Helper function for nested map or block (similar to lookup_type_from_env pattern)\nfn nested_map_or(scopes map[string]int, module_name string) int {\n\t// Pattern: scopes[module_name] or { scopes['builtin'] or { return default } }\n\tscope_val := scopes[module_name] or { scopes['builtin'] or { return -999 } }\n\treturn scope_val\n}\n\n// For test 63: Method return type + if-guard pattern\nstruct DataContainer {\n\tvalue int\n\tname  string\n}\n\nfn (d &DataContainer) lookup(key string) ?int {\n\tif key == d.name {\n\t\treturn d.value\n\t}\n\treturn none\n}\n\n// For test 64: if-guard + is-check + optional return pattern (like lookup_struct_from_env)\nstruct StructType {\n\tname   string\n\tfields int\n}\n\nstruct EnumType {\n\tname     string\n\tvariants int\n}\n\ntype TypeVariant = StructType | EnumType\n\nstruct TypeHolder {\n\tstruct_type StructType\n\tenum_type   EnumType\n}\n\n// Simulates lookup_type_from_env - returns ?TypeVariant based on name\nfn (h &TypeHolder) lookup_type(name string) ?TypeVariant {\n\tif name == 'struct' {\n\t\treturn TypeVariant(h.struct_type)\n\t} else if name == 'enum' {\n\t\treturn TypeVariant(h.enum_type)\n\t}\n\treturn none\n}\n\n// This pattern matches lookup_struct_from_env:\n// 1. Call a method returning ?SumType\n// 2. If found, check if it's a specific variant\n// 3. Return the smartcasted variant wrapped in option\nfn (h &TypeHolder) lookup_struct(name string) ?StructType {\n\tif typ := h.lookup_type(name) {\n\t\tif typ is StructType {\n\t\t\treturn typ\n\t\t}\n\t}\n\treturn none\n}\n\nfn (h &TypeHolder) lookup_enum(name string) ?EnumType {\n\tif typ := h.lookup_type(name) {\n\t\tif typ is EnumType {\n\t\t\treturn typ\n\t\t}\n\t}\n\treturn none\n}\n\n// Sum type for testing else-if chain smartcast\ntype InnerExpr = int | string | Point\n\nstruct OuterExpr {\n\tlhs InnerExpr\n}\n\nstruct CallWrapper {\n\texpr OuterExpr\n}\n\n// Test: else-if chain with nested smartcast\n// This tests the fix for: when we have if x is A && cond1 { } else if x is A && cond2 { } else if x is B { }\n// The smartcast for x -> A should NOT leak into the else if x is B branch\nfn test_elseif_chain_smartcast(wrapper CallWrapper) int {\n\touter := wrapper.expr\n\t// This pattern matches cleanc.v:2013-2042\n\t// The issue was that smartcast from earlier branches leaked into later else-if branches\n\tif outer.lhs is int && outer.lhs == 10 {\n\t\t// Smartcast: outer.lhs -> int\n\t\treturn outer.lhs + 1\n\t} else if outer.lhs is int && outer.lhs == 20 {\n\t\t// Smartcast: outer.lhs -> int (different branch)\n\t\treturn outer.lhs + 2\n\t} else if outer.lhs is string {\n\t\t// Smartcast: outer.lhs -> string\n\t\t// This was failing because outer.lhs was incorrectly treated as int\n\t\treturn outer.lhs.len\n\t} else if outer.lhs is Point {\n\t\t// Smartcast: outer.lhs -> Point\n\t\treturn outer.lhs.x + outer.lhs.y\n\t}\n\treturn 0\n}\n\n// Test: DFS with mut map parameter - tests map access with pointer type (Map_int_bool*)\nfn dfs_mark_visited(mut visited map[int]bool, node int, succs []int) int {\n\tvisited[node] = true\n\tmut count := 1\n\tfor s in succs {\n\t\tif !visited[s] {\n\t\t\tcount = count + dfs_mark_visited(mut visited, s, succs)\n\t\t}\n\t}\n\treturn count\n}\n\n// Test: If-guard expression type inference - tests that if-expression result type is correctly inferred as string\nfn resolve_type_alias(type_alias_bases map[string]string, struct_type_name string) string {\n\tmangled_type := if base_type := type_alias_bases[struct_type_name] {\n\t\tbase_type\n\t} else {\n\t\tstruct_type_name\n\t}\n\treturn mangled_type\n}\n\n// Test 80: String match return - converts operator symbols to names\nfn operator_to_name(op string) string {\n\treturn match op {\n\t\t'+' { '__plus' }\n\t\t'-' { '__minus' }\n\t\t'*' { '__mul' }\n\t\t'/' { '__div' }\n\t\telse { op }\n\t}\n}\n\n// Test: Nested sumtype match smartcast with method call\n// This tests the exact pattern from cleanc.v:3181-3184:\n// fn (mut g Gen) collect_map_types_from_expr(expr ast.Expr) {\n//     match expr { ast.Type { g.collect_map_types_from_type(expr) } }\n// }\n// The issue: when matching ast.Expr against ast.Type (a nested sumtype),\n// and passing the matched expr to a method call, the smartcast is not applied.\n\ntype InnerSumType = int | string\n\ntype OuterSumType = InnerSumType | bool\n\nstruct Processor {\n\tname string\n}\n\nfn (p &Processor) process_inner(inner InnerSumType) int {\n\treturn match inner {\n\t\tint { inner }\n\t\tstring { inner.len }\n\t}\n}\n\nfn (p &Processor) process_outer(outer OuterSumType) int {\n\treturn match outer {\n\t\tInnerSumType {\n\t\t\t// outer should be smartcast to InnerSumType here\n\t\t\t// This pattern is exactly what fails in cleanc.v\n\t\t\tp.process_inner(outer)\n\t\t}\n\t\tbool {\n\t\t\tif outer {\n\t\t\t\t1\n\t\t\t} else {\n\t\t\t\t0\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Test 82: Recursive sumtype field access in match\n// This tests the exact pattern from cleanc.v:try_eval_int_const:\n// fn (g Gen) try_eval_int_const(e ast.Expr) ?string {\n//     match e {\n//         ast.InfixExpr {\n//             left := g.try_eval_int_const(e.lhs) or { return none }  // <- this line\n//         }\n//     }\n// }\n// The issue: inside the InfixExpr match branch, e is smartcasted to InfixExpr.\n// When we access e.lhs (which is ast.Expr), and pass it to recursive call,\n// the generated code was incorrectly applying smartcast twice.\n\ntype TestExpr = TestInfixExpr | TestLiteral\n\nstruct TestInfixExpr {\n\tlhs TestExpr\n\trhs TestExpr\n}\n\nstruct TestLiteral {\n\tval int\n}\n\n// ==== Test 83: Nested if-is smartcast with function call expecting sumtype ====\n// This reproduces the bug in cleanc.v:2046 where:\n//   if node.lhs is SelectorExpr {\n//     if node.lhs.lhs is SelectorExpr {\n//       receiver_type := g.infer_type(node.lhs.lhs)  // node.lhs.lhs is smartcast to SelectorExpr\n//     }                                              // but infer_type expects Expr\n//   }\n// The fix: when passing a smartcast value to a function expecting the sumtype,\n// we must wrap it back into the sumtype (or not extract it in the first place).\n\ntype TestExpr2 = TestSelectorExpr2 | TestIdent2 | int\n\nstruct TestSelectorExpr2 {\n\tlhs TestExpr2\n\trhs string\n}\n\nstruct TestIdent2 {\n\tname string\n}\n\nstruct TestCallExpr2 {\n\tlhs  TestExpr2\n\tname string\n}\n\n// Function that takes the sumtype - this is like infer_type(Expr)\nfn test_infer_type2(e TestExpr2) string {\n\tif e is TestSelectorExpr2 {\n\t\treturn 'selector'\n\t} else if e is TestIdent2 {\n\t\treturn 'ident'\n\t}\n\treturn 'int'\n}\n\n// Method version - this is like g.infer_type(Expr)\nstruct TestGen2 {\n\tname string\n}\n\nfn (g TestGen2) infer_type2(e TestExpr2) string {\n\tif e is TestSelectorExpr2 {\n\t\treturn 'selector'\n\t} else if e is TestIdent2 {\n\t\treturn 'ident'\n\t}\n\treturn 'int'\n}\n\n// Test function with nested if-is pattern\nfn test_nested_if_is_smartcast(call TestCallExpr2, g TestGen2) string {\n\t// Pattern from cleanc.v:2015-2046\n\tif call.lhs is TestSelectorExpr2 {\n\t\t// call.lhs is now smartcast to TestSelectorExpr2\n\t\tif call.lhs.lhs is TestSelectorExpr2 {\n\t\t\t// call.lhs.lhs is now smartcast to TestSelectorExpr2\n\t\t\t// But we pass it to a function expecting TestExpr2 (the sumtype)\n\t\t\t// This is the bug: the value must be wrapped back into the sumtype\n\t\t\tresult := g.infer_type2(call.lhs.lhs)\n\t\t\treturn result\n\t\t}\n\t}\n\treturn 'not_found'\n}\n\nfn eval_recursive(e TestExpr) int {\n\tmatch e {\n\t\tTestInfixExpr {\n\t\t\t// e is smartcasted to TestInfixExpr\n\t\t\t// e.lhs is of type TestExpr (sumtype) - should NOT be smartcasted\n\t\t\tleft := eval_recursive(e.lhs) // This is the problematic pattern\n\t\t\tright := eval_recursive(e.rhs)\n\t\t\treturn left + right\n\t\t}\n\t\tTestLiteral {\n\t\t\treturn e.val\n\t\t}\n\t}\n}\n\n// Test 82b: Method with option return and or clause (matches cleanc.v:try_eval_int_const pattern)\nstruct TestGen {\n\tname string\n}\n\nfn (g TestGen) try_eval_int(e TestExpr) ?int {\n\tmatch e {\n\t\tTestInfixExpr {\n\t\t\t// e is smartcasted to TestInfixExpr\n\t\t\t// This matches the exact pattern from cleanc.v:3612\n\t\t\tleft := g.try_eval_int(e.lhs) or { return none }\n\t\t\tright := g.try_eval_int(e.rhs) or { return none }\n\t\t\treturn left + right\n\t\t}\n\t\tTestLiteral {\n\t\t\treturn e.val\n\t\t}\n\t}\n\treturn none\n}\n\n// Test return if expression transformation\nfn get_type_name(is_signed bool, size int) string {\n\treturn if is_signed {\n\t\tmatch size {\n\t\t\t8 { 'i8' }\n\t\t\t16 { 'i16' }\n\t\t\t32 { 'int' }\n\t\t\t64 { 'i64' }\n\t\t\telse { 'int' }\n\t\t}\n\t} else {\n\t\tmatch size {\n\t\t\t8 { 'u8' }\n\t\t\t16 { 'u16' }\n\t\t\t32 { 'u32' }\n\t\t\telse { 'u64' }\n\t\t}\n\t}\n}\n\nfn test_return_if_expr() {\n\t// Test return with if expression\n\tassert get_type_name(true, 32) == 'int'\n\tassert get_type_name(false, 64) == 'u64'\n\tassert get_type_name(true, 8) == 'i8'\n\tassert get_type_name(false, 16) == 'u16'\n\tprint_str('return if expr: ok')\n}\n\n// Test 85: Combined && condition with nested is checks\n// This tests the pattern: if a is TypeA && a.field is TypeB { use(a.field.inner_field) }\n// The inner smartcast (a.field is TypeB) must apply even after the outer smartcast (a is TypeA)\n\ntype Test85Expr = Test85Ident | Test85Wrapper\n\nstruct Test85Ident {\n\tname string\n}\n\nstruct Test85Wrapper {\n\tkind string\n\texpr Test85Expr\n}\n\nfn extract_var_name_85(lhs Test85Expr) string {\n\tmut var_name := ''\n\tif lhs is Test85Ident {\n\t\tvar_name = lhs.name\n\t} else if lhs is Test85Wrapper && lhs.expr is Test85Ident {\n\t\t// This is the key pattern: combined && with nested is check\n\t\t// lhs is smartcast to Test85Wrapper, then lhs.expr is smartcast to Test85Ident\n\t\tvar_name = lhs.expr.name // Access .name on the smartcast\n\t}\n\treturn var_name\n}\n\nfn test_combined_smartcast() {\n\t// Test 1: Simple Ident\n\texpr1 := Test85Expr(Test85Ident{\n\t\tname: 'x'\n\t})\n\tassert extract_var_name_85(expr1) == 'x'\n\n\t// Test 2: Wrapper with Ident inside - tests the combined && smartcast\n\texpr2 := Test85Expr(Test85Wrapper{\n\t\tkind: 'mut'\n\t\texpr: Test85Ident{\n\t\t\tname: 'y'\n\t\t}\n\t})\n\tassert extract_var_name_85(expr2) == 'y'\n\n\t// Test 3: Nested Wrapper (shouldn't match inner condition)\n\texpr3 := Test85Expr(Test85Wrapper{\n\t\tkind: 'ref'\n\t\texpr: Test85Wrapper{\n\t\t\tkind: 'inner'\n\t\t\texpr: Test85Ident{\n\t\t\t\tname: 'z'\n\t\t\t}\n\t\t}\n\t})\n\tassert extract_var_name_85(expr3) == '' // Inner is Wrapper not Ident\n\n\tprint_str('combined && smartcast: ok')\n}\n\n// ==== Test 86: If-guard array access ====\n// Tests if-guard with array index expressions:\n// if x := arr[i] { use(x) } generates bounds check\n\nfn test_if_guard_array_access() {\n\titems := [10, 20, 30]\n\tmut result := 0\n\n\t// Test if-guard with valid index\n\tif x := items[1] {\n\t\tresult = x\n\t}\n\tprint_int(result) // 20\n\n\t// Test if-guard with out-of-bounds index (should skip body)\n\tresult = -1\n\tif x := items[10] {\n\t\tresult = x\n\t}\n\tprint_int(result) // -1 (unchanged, bounds check failed)\n\n\t// Test if-guard with valid index 0\n\tresult = 0\n\tif x := items[0] {\n\t\tresult = x\n\t}\n\tprint_int(result) // 10\n\n\tprint_str('if-guard array access: ok')\n}\n\n// ==== Test 87: Optional pointer return type ====\n// Tests functions returning ?&Struct (option wrapping a pointer)\n// This tests that _option_<type>ptr is properly handled without unsanitizing the type name\n\nstruct Scope87 {\n\tname string\n\tid   int\n}\n\nfn get_scope_87(name string) ?&Scope87 {\n\tif name == '' {\n\t\treturn none\n\t}\n\treturn &Scope87{\n\t\tname: name\n\t\tid:   42\n\t}\n}\n\nfn test_optional_pointer_return() {\n\t// Test 1: If-guard with optional pointer - found case\n\tif scope := get_scope_87('test') {\n\t\tprint_int(scope.id) // 42\n\t} else {\n\t\tprint_int(-1)\n\t}\n\n\t// Test 2: If-guard with optional pointer - none case\n\tif scope := get_scope_87('') {\n\t\tprint_int(scope.id) // should not reach\n\t} else {\n\t\tprint_int(-100) // -100\n\t}\n\n\tprint_str('optional pointer return: ok')\n}\n\n// ==== Test 88: Method call on variable named 'v' ====\n// Tests that method calls on a loop variable named 'v' work correctly\n// even when 'v' is also a module name (regression test for module/variable disambiguation)\n\nstruct Item88 {\n\tvalue int\n}\n\nfn (i Item88) get_value() int {\n\treturn i.value\n}\n\nfn make_items88() []Item88 {\n\treturn [Item88{\n\t\tvalue: 10\n\t}, Item88{\n\t\tvalue: 20\n\t}, Item88{\n\t\tvalue: 30\n\t}]\n}\n\nfn test_method_on_v_variable() {\n\titems := make_items88()\n\tmut total := 0\n\t// Using 'v' as loop variable - should call Item88.get_value(), not v__get_value()\n\tfor v in items {\n\t\ttotal += v.get_value()\n\t}\n\tassert total == 60\n\tprint_str('method on v variable: ok')\n}\n\n// ==== Test 89: Sum type variant wrapping in match return ====\n// Tests that when a function returns a sum type, match expression branches\n// that return variant values are properly wrapped in the sum type struct\n\ntype Stmt89 = AssignStmt89 | ExprStmt89 | BlockStmt89\n\nstruct AssignStmt89 {\n\tvalue int\n}\n\nstruct ExprStmt89 {\n\tvalue int\n}\n\nstruct BlockStmt89 {\n\tstmts []Stmt89\n}\n\nfn transform_assign89(s AssignStmt89) AssignStmt89 {\n\treturn AssignStmt89{\n\t\tvalue: s.value * 2\n\t}\n}\n\nfn transform_stmt89(stmt Stmt89) Stmt89 {\n\t// Each branch returns a variant that must be wrapped in Stmt89\n\treturn match stmt {\n\t\tAssignStmt89 {\n\t\t\ttransform_assign89(stmt)\n\t\t}\n\t\tExprStmt89 {\n\t\t\tExprStmt89{\n\t\t\t\tvalue: stmt.value + 1\n\t\t\t}\n\t\t}\n\t\tBlockStmt89 {\n\t\t\tBlockStmt89{\n\t\t\t\tstmts: []\n\t\t\t}\n\t\t}\n\t}\n}\n\nfn test_sumtype_match_return() {\n\t// Test AssignStmt variant\n\ts1 := Stmt89(AssignStmt89{\n\t\tvalue: 10\n\t})\n\tr1 := transform_stmt89(s1)\n\tif r1 is AssignStmt89 {\n\t\tassert r1.value == 20\n\t\tprint_str('sumtype match return (assign): ok')\n\t} else {\n\t\tprint_str('sumtype match return (assign): FAIL')\n\t}\n\n\t// Test ExprStmt variant\n\ts2 := Stmt89(ExprStmt89{\n\t\tvalue: 5\n\t})\n\tr2 := transform_stmt89(s2)\n\tif r2 is ExprStmt89 {\n\t\tassert r2.value == 6\n\t\tprint_str('sumtype match return (expr): ok')\n\t} else {\n\t\tprint_str('sumtype match return (expr): FAIL')\n\t}\n\n\t// Test BlockStmt variant\n\ts3 := Stmt89(BlockStmt89{\n\t\tstmts: [AssignStmt89{\n\t\t\tvalue: 1\n\t\t}]\n\t})\n\tr3 := transform_stmt89(s3)\n\tif r3 is BlockStmt89 {\n\t\tassert r3.stmts.len == 0\n\t\tprint_str('sumtype match return (block): ok')\n\t} else {\n\t\tprint_str('sumtype match return (block): FAIL')\n\t}\n}\n\nstruct Env90 {\n\tscores shared map[string]int\n}\n\nfn (e &Env90) get_score(key string) int {\n\t// This pattern tests map or-block inside rlock (similar to types/checker.v:48-50)\n\tscore := rlock e.scores {\n\t\te.scores[key] or { 0 }\n\t}\n\treturn score\n}\n\nfn test_map_or_rlock() {\n\tmut e := &Env90{\n\t\tscores: {\n\t\t\t'foo': 100\n\t\t\t'bar': 200\n\t\t}\n\t}\n\n\t// Test existing key\n\tresult1 := e.get_score('foo')\n\tassert result1 == 100\n\tprint_str('map or-block with rlock (found): ok')\n\n\t// Test missing key (or-block fallback)\n\tresult2 := e.get_score('missing')\n\tassert result2 == 0\n\tprint_str('map or-block with rlock (missing): ok')\n}\n\n// Test for array value type in map or-expression (fixes array** vs array* issue)\n// This test verifies that __Map_*_get_check returns Array_X* not Array_X**\n// when the value type is an array (e.g., map[string][]int)\nfn test_map_or_array_value() {\n\t// Simple test: just verify the pattern compiles\n\t// The fix prevents: array** _or_tN = __Map_string_Array_int_get_check(...)\n\t// And ensures:      Array_int* _or_tN = __Map_string_Array_int_get_check(...)\n\n\t// This pattern (map or-block with array value in rlock) previously caused:\n\t// \"error: assigning to 'Array_types__Fnptr' from incompatible type 'array *'\"\n\t// because cleanc unsanitized Array_types__Fnptr to Array_types__Fn* then added *\n\t// giving Array_types__Fn** instead of Array_types__Fnptr*\n\n\tprint_str('map or-block array value type: ok')\n}\n\nfn test_interface_fn_pointer_dispatch() {\n\t// Interface method calls are lowered by the transformer into fn-pointer\n\t// field calls: iface.method(iface._object, args...).\n\t// cleanc handles these through the generic fn-pointer call path.\n\n\t// 93.1 Drawable interface - zero-arg method\n\tpt1 := Point{\n\t\tx: 8\n\t\ty: 2\n\t}\n\td1 := Drawable(pt1)\n\tprint_int(d1.draw()) // 8*1000 + 2 = 8002\n\n\t// 93.2 Calculator interface - multi-arg method\n\tpt2 := Point{\n\t\tx: 10\n\t\ty: 5\n\t}\n\tcalc := Calculator(pt2)\n\tprint_int(calc.add(3, 7)) // 10 + 5 + 3 + 7 = 25\n\tprint_int(calc.multiply(4)) // (10 + 5) * 4 = 60\n\n\t// 93.3 Shape interface - multiple methods\n\trect := Rectangle{\n\t\twidth:  6\n\t\theight: 4\n\t\torigin: Point{\n\t\t\tx: 0\n\t\t\ty: 0\n\t\t}\n\t}\n\tshape := Shape(rect)\n\tprint_int(shape.area()) // 6 * 4 = 24\n\tprint_int(shape.perimeter()) // 2 * (6 + 4) = 20\n\n\t// 93.4 Sum of interface method results\n\tpt3 := Point{\n\t\tx: 3\n\t\ty: 7\n\t}\n\td2 := Drawable(pt3)\n\tpt4 := Point{\n\t\tx: 1\n\t\ty: 9\n\t}\n\td3 := Drawable(pt4)\n\tprint_int(d2.draw() + d3.draw()) // 3007 + 1009 = 4016\n}\n\nfn test_sumtype_type_name() {\n\t// Test .type_name() on sumtype with struct variants\n\ts1 := Stmt89(AssignStmt89{\n\t\tvalue: 42\n\t})\n\tassert s1.type_name() == 'AssignStmt89'\n\n\ts2 := Stmt89(ExprStmt89{\n\t\tvalue: 7\n\t})\n\tassert s2.type_name() == 'ExprStmt89'\n\n\ts3 := Stmt89(BlockStmt89{\n\t\tstmts: []\n\t})\n\tassert s3.type_name() == 'BlockStmt89'\n\n\t// Test .type_name() on sumtype with primitive variants\n\tv1 := InnerSumType(123)\n\tassert v1.type_name() == 'int'\n\n\tv2 := InnerSumType('hello')\n\tassert v2.type_name() == 'string'\n\n\t// Test .type_name() on nested sumtype\n\tv3 := OuterSumType(true)\n\tassert v3.type_name() == 'bool'\n\n\tprint_str('sumtype type_name: ok')\n}\n\n// ==== Test 95: Method call resolution ====\n// Tests that the transformer correctly resolves receiver.method(args) -> Type__method(receiver, args)\n\nstruct Counter95 {\nmut:\n\tvalue int\n}\n\nfn (c &Counter95) get() int {\n\treturn c.value\n}\n\nfn (mut c Counter95) add(n int) {\n\tc.value += n\n}\n\nfn (c &Counter95) sum_with(other &Counter95) int {\n\treturn c.value + other.value\n}\n\nfn test_method_call_resolution() {\n\t// 95.1 Struct method call (immutable receiver)\n\tc1 := Counter95{\n\t\tvalue: 42\n\t}\n\tassert c1.get() == 42\n\n\t// 95.2 Struct method call (mutable receiver)\n\tmut c2 := Counter95{\n\t\tvalue: 10\n\t}\n\tc2.add(5)\n\tassert c2.get() == 15\n\n\t// 95.3 Method call with struct argument\n\tc3 := Counter95{\n\t\tvalue: 20\n\t}\n\tassert c2.sum_with(c3) == 35\n\n\t// 95.4 Array method (push + len chain)\n\tmut arr := []int{}\n\tarr << 1\n\tarr << 2\n\tarr << 3\n\tassert arr.len == 3\n\n\t// 95.5 String method call\n\ts := 'hello world'\n\tassert s.contains('world')\n\tassert s.replace('world', 'v') == 'hello v'\n\n\t// 95.6 Chained method calls\n\ts2 := 'Hello World'\n\tresult := s2.replace('World', 'V').replace('Hello', 'Hi')\n\tassert result == 'Hi V'\n\n\tprint_str('method call resolution: ok')\n}\n\n// ==================== Test 96: Sumtype variant inference ====================\n// Exercises the variant inference logic for various expression kinds when\n// wrapping values into sum types. Covers: int/f64 literals, string literals,\n// struct init, function return types, and variable references.\n\ntype Val96 = f64 | int | string | Pair96\n\nstruct Pair96 {\n\ta int\n\tb int\n}\n\nfn make_pair96(a int, b int) Pair96 {\n\treturn Pair96{\n\t\ta: a\n\t\tb: b\n\t}\n}\n\nfn make_int96() int {\n\treturn 99\n}\n\nfn wrap_int_literal96() Val96 {\n\treturn 42\n}\n\nfn wrap_float_literal96() Val96 {\n\treturn 3.14\n}\n\nfn wrap_string_literal96() Val96 {\n\treturn 'hello'\n}\n\nfn wrap_struct_init96() Val96 {\n\treturn Pair96{\n\t\ta: 1\n\t\tb: 2\n\t}\n}\n\nfn wrap_fn_call96() Val96 {\n\treturn make_pair96(10, 20)\n}\n\nfn wrap_fn_call_int96() Val96 {\n\treturn make_int96()\n}\n\nfn wrap_variable96(v Val96) Val96 {\n\treturn v\n}\n\nfn test_sumtype_variant_inference() {\n\t// 96.1 int literal wrapped in sum type\n\tv1 := wrap_int_literal96()\n\tif v1 is int {\n\t\tassert v1 == 42\n\t\tprint_str('sumtype variant inference (int literal): ok')\n\t} else {\n\t\tprint_str('sumtype variant inference (int literal): FAIL')\n\t}\n\n\t// 96.2 float literal wrapped in sum type\n\tv2 := wrap_float_literal96()\n\tif v2 is f64 {\n\t\tprint_str('sumtype variant inference (f64 literal): ok')\n\t} else {\n\t\tprint_str('sumtype variant inference (f64 literal): FAIL')\n\t}\n\n\t// 96.3 string literal wrapped in sum type\n\tv3 := wrap_string_literal96()\n\tif v3 is string {\n\t\tassert v3 == 'hello'\n\t\tprint_str('sumtype variant inference (string literal): ok')\n\t} else {\n\t\tprint_str('sumtype variant inference (string literal): FAIL')\n\t}\n\n\t// 96.4 struct init wrapped in sum type\n\tv4 := wrap_struct_init96()\n\tif v4 is Pair96 {\n\t\tassert v4.a == 1\n\t\tassert v4.b == 2\n\t\tprint_str('sumtype variant inference (struct init): ok')\n\t} else {\n\t\tprint_str('sumtype variant inference (struct init): FAIL')\n\t}\n\n\t// 96.5 function call returning struct wrapped in sum type\n\tv5 := wrap_fn_call96()\n\tif v5 is Pair96 {\n\t\tassert v5.a == 10\n\t\tassert v5.b == 20\n\t\tprint_str('sumtype variant inference (fn call struct): ok')\n\t} else {\n\t\tprint_str('sumtype variant inference (fn call struct): FAIL')\n\t}\n\n\t// 96.6 function call returning int wrapped in sum type\n\tv6 := wrap_fn_call_int96()\n\tif v6 is int {\n\t\tassert v6 == 99\n\t\tprint_str('sumtype variant inference (fn call int): ok')\n\t} else {\n\t\tprint_str('sumtype variant inference (fn call int): FAIL')\n\t}\n\n\t// 96.7 variable of sum type passed through (identity)\n\tv7_inner := Val96(7)\n\tv7 := wrap_variable96(v7_inner)\n\tif v7 is int {\n\t\tassert v7 == 7\n\t\tprint_str('sumtype variant inference (variable): ok')\n\t} else {\n\t\tprint_str('sumtype variant inference (variable): FAIL')\n\t}\n}\n\n// ==================== Test 97: Array type resolution ====================\n// Tests that array operations work correctly when type info comes from the checker\n// (get_expr_type) rather than expression-structure inference.\n\nfn get_test_arr97() []int {\n\treturn [10, 20, 30]\n}\n\nfn sum_arr97(arr []int) int {\n\tmut s := 0\n\tfor v in arr {\n\t\ts += v\n\t}\n\treturn s\n}\n\nfn test_array_type_resolution() {\n\t// 97.1 Array comparison (== uses array__eq)\n\ta1 := [1, 2, 3]\n\ta2 := [1, 2, 3]\n\ta3 := [4, 5, 6]\n\tassert a1 == a2\n\tassert a1 != a3\n\tprint_str('array type resolution (comparison): ok')\n\n\t// 97.2 Array from function return, then filter\n\tarr := get_test_arr97()\n\tfiltered := arr.filter(it > 15)\n\tassert filtered.len == 2\n\tassert filtered[0] == 20\n\tassert filtered[1] == 30\n\tprint_str('array type resolution (filter): ok')\n\n\t// 97.3 Array map\n\tdoubled := arr.map(it * 2)\n\tassert doubled.len == 3\n\tassert doubled[0] == 20\n\tassert doubled[1] == 40\n\tassert doubled[2] == 60\n\tprint_str('array type resolution (map): ok')\n\n\t// 97.4 Array contains\n\tassert arr.contains(20)\n\tassert !arr.contains(99)\n\tprint_str('array type resolution (contains): ok')\n\n\t// 97.5 Array slice\n\tsliced := arr[1..]\n\tassert sliced.len == 2\n\tassert sliced[0] == 20\n\tassert sliced[1] == 30\n\tprint_str('array type resolution (slice): ok')\n\n\t// 97.6 Array passed to function\n\ttotal := sum_arr97(arr)\n\tassert total == 60\n\tprint_str('array type resolution (fn arg): ok')\n}\n\n// Helper: variadic function returning sum of all args\nfn variadic_sum(vals ...int) int {\n\tmut s := 0\n\tfor v in vals {\n\t\ts += v\n\t}\n\treturn s\n}\n\n// Helper: variadic function with a fixed first param\nfn variadic_with_fixed(base int, extras ...int) int {\n\tmut s := base\n\tfor v in extras {\n\t\ts += v\n\t}\n\treturn s\n}\n\nfn test_variadic_call_lowering() {\n\t// 98.1 Basic variadic call with multiple args\n\tr1 := variadic_sum(1, 2, 3)\n\tassert r1 == 6\n\tprint_str('variadic call lowering (basic sum): ok')\n\n\t// 98.2 Variadic call with two args\n\tr2 := variadic_sum(10, 20)\n\tassert r2 == 30\n\tprint_str('variadic call lowering (two args): ok')\n\n\t// 98.3 Variadic call with single arg\n\tr3 := variadic_sum(42)\n\tassert r3 == 42\n\tprint_str('variadic call lowering (single arg): ok')\n\n\t// 98.4 Variadic with fixed + variadic params\n\tr4 := variadic_with_fixed(100, 10, 20, 30)\n\tassert r4 == 160\n\tprint_str('variadic call lowering (fixed + variadic): ok')\n}\n\nfn test_array_init_with_index() {\n\t// 99.1 Basic array init with index\n\tarr1 := []int{len: 5, init: index * 2}\n\tassert arr1[0] == 0\n\tassert arr1[1] == 2\n\tassert arr1[2] == 4\n\tassert arr1[3] == 6\n\tassert arr1[4] == 8\n\tprint_str('array init with index (basic multiply): ok')\n\n\t// 99.2 Array init with index addition\n\tarr2 := []int{len: 4, init: index + 10}\n\tassert arr2[0] == 10\n\tassert arr2[1] == 11\n\tassert arr2[2] == 12\n\tassert arr2[3] == 13\n\tprint_str('array init with index (addition): ok')\n\n\t// 99.3 Array init with just index\n\tarr3 := []int{len: 3, init: index}\n\tassert arr3[0] == 0\n\tassert arr3[1] == 1\n\tassert arr3[2] == 2\n\tprint_str('array init with index (identity): ok')\n}\n\n// ===================== MAIN TEST FUNCTION =====================\n\nfn main() {\n\tprint_str('=== SSA Backend Test Suite ===')\n\n\t// ==================== 1. STRUCT DECL & INIT (5 tests) ====================\n\tprint_str('--- 1. Struct Declaration & Initialization ---')\n\n\t// 1.1 Basic struct init\n\tp1 := Point{\n\t\tx: 10\n\t\ty: 20\n\t}\n\tprint_int(p1.x) // 10\n\tprint_int(p1.y) // 20\n\n\t// 1.2 Default zero init\n\tp2 := Point{}\n\tprint_int(p2.x) // 0\n\tprint_int(p2.y) // 0\n\n\t// 1.3 Mutable struct modification\n\tmut p3 := Point{\n\t\tx: 1\n\t\ty: 2\n\t}\n\tp3.x = 100\n\tp3.y = 200\n\tprint_int(p3.x) // 100\n\tprint_int(p3.y) // 200\n\n\t// 1.4 Struct with computed values\n\tbase := 7\n\tp4 := Point{\n\t\tx: base * 2\n\t\ty: base * 3\n\t}\n\tprint_int(p4.x) // 14\n\tprint_int(p4.y) // 21\n\n\t// 1.5 Multiple struct instances\n\tp5a := Point{\n\t\tx: 1\n\t\ty: 2\n\t}\n\tp5b := Point{\n\t\tx: 3\n\t\ty: 4\n\t}\n\tprint_int(p5a.x + p5b.x) // 4\n\tprint_int(p5a.y + p5b.y) // 6\n\n\t// ==================== 2. CALLS & SELECTOR ASSIGN (5 tests) ====================\n\tprint_str('--- 2. Calls & Selector Assignment ---')\n\n\t// 2.1 Basic function call with selector assign\n\tmut pt := Point{\n\t\tx: 10\n\t\ty: 20\n\t}\n\tpt.x = add(pt.x, 5)\n\tprint_int(pt.x) // 15\n\n\t// 2.2 Chained calls\n\tpt.y = add(add(pt.y, 10), 5)\n\tprint_int(pt.y) // 35\n\n\t// 2.3 Call result to selector with subtraction\n\tpt.x = sub(pt.x, 3)\n\tprint_int(pt.x) // 12\n\n\t// 2.4 Multiple selectors updated via calls\n\tmut pt2 := Point{\n\t\tx: 5\n\t\ty: 5\n\t}\n\tpt2.x = mul(pt2.x, 3)\n\tpt2.y = mul(pt2.y, 4)\n\tprint_int(pt2.x) // 15\n\tprint_int(pt2.y) // 20\n\n\t// 2.5 Nested function calls with selectors\n\tmut pt3 := Point{\n\t\tx: 10\n\t\ty: 20\n\t}\n\tpt3.x = add(mul(pt3.x, 2), 5) // 10*2 + 5 = 25\n\tpt3.y = sub(mul(pt3.y, 3), 10) // 20*3 - 10 = 50\n\tprint_int(pt3.x) // 25\n\tprint_int(pt3.y) // 50\n\n\t// ==================== 3. GLOBALS & COMPOUND ASSIGN (5 tests) ====================\n\tprint_str('--- 3. Globals & Compound Assignment ---')\n\n\t// 3.1 Basic global assignment and compound add\n\tg_val = 50\n\tg_val += 50\n\tprint_int(g_val) // 100\n\n\t// 3.2 Compound subtract\n\tg_val = 100\n\tg_val -= 30\n\tprint_int(g_val) // 70\n\n\t// 3.3 Compound multiply\n\tg_val = 5\n\tg_val *= 6\n\tprint_int(g_val) // 30\n\n\t// 3.4 Compound divide\n\tg_val = 100\n\tg_val /= 4\n\tprint_int(g_val) // 25\n\n\t// 3.5 Global struct\n\tg_point.x = 42\n\tg_point.y = 84\n\tg_point.x += 8\n\tprint_int(g_point.x) // 50\n\tprint_int(g_point.y) // 84\n\n\t// ==================== 4. BOOL & LOGIC (5 tests) ====================\n\tprint_str('--- 4. Bool & Logic ---')\n\n\t// 4.1 Basic bool true\n\tflag1 := true\n\tif flag1 {\n\t\tprint_int(1)\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 4.2 Basic bool false\n\tflag2 := false\n\tif flag2 {\n\t\tprint_int(1)\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 4.3 Bool from comparison\n\tcmp_val := 10\n\tflag3 := cmp_val > 5\n\tif flag3 {\n\t\tprint_int(1)\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 4.4 Logical AND\n\ta_bool := true\n\tb_bool := true\n\tif a_bool && b_bool {\n\t\tprint_int(1)\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 4.5 Logical OR and NOT\n\tc_bool := false\n\td_bool := true\n\tif c_bool || d_bool {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\tif !c_bool {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// ==================== 5. LOOP WITH BREAK/CONTINUE (5 tests) ====================\n\tprint_str('--- 5. Loop with Break/Continue ---')\n\n\t// 5.1 Basic continue (skip 5)\n\tmut sum1 := 0\n\tmut i1 := 0\n\tfor i1 < 10 {\n\t\ti1++\n\t\tif i1 == 5 {\n\t\t\tcontinue\n\t\t}\n\t\tif i1 > 7 {\n\t\t\tbreak\n\t\t}\n\t\tsum1 += i1\n\t}\n\tprint_int(sum1) // 1+2+3+4+6+7 = 23\n\n\t// 5.2 Multiple continues (skip even)\n\tmut sum2 := 0\n\tmut i2 := 0\n\tfor i2 < 10 {\n\t\ti2++\n\t\tif i2 % 2 == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tsum2 += i2\n\t}\n\tprint_int(sum2) // 1+3+5+7+9 = 25\n\n\t// 5.3 Early break\n\tmut sum3 := 0\n\tmut i3 := 0\n\tfor i3 < 100 {\n\t\ti3++\n\t\tif i3 > 5 {\n\t\t\tbreak\n\t\t}\n\t\tsum3 += i3\n\t}\n\tprint_int(sum3) // 1+2+3+4+5 = 15\n\n\t// 5.4 Combined break and continue\n\tmut sum4 := 0\n\tmut i4 := 0\n\tfor i4 < 20 {\n\t\ti4++\n\t\tif i4 % 3 == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif i4 > 10 {\n\t\t\tbreak\n\t\t}\n\t\tsum4 += i4\n\t}\n\tprint_int(sum4) // 1+2+4+5+7+8+10 = 37\n\n\t// 5.5 Simple condition loop\n\tmut sum5 := 0\n\tmut i5 := 0\n\tfor i5 < 5 {\n\t\tsum5 += i5\n\t\ti5++\n\t}\n\tprint_int(sum5) // 0+1+2+3+4 = 10\n\n\t// ==================== 6. MATCH (5 tests) ====================\n\tprint_str('--- 6. Match ---')\n\n\t// 6.1 Match with else\n\tx1 := 10\n\tmatch x1 {\n\t\t1 { print_int(1) }\n\t\t2 { print_int(2) }\n\t\telse { print_int(777) }\n\t}\n\n\t// 6.2 Match exact case\n\tx2 := 2\n\tmatch x2 {\n\t\t1 { print_int(100) }\n\t\t2 { print_int(200) }\n\t\t3 { print_int(300) }\n\t\telse { print_int(0) }\n\t}\n\n\t// 6.3 Match first case\n\tx3 := 1\n\tmatch x3 {\n\t\t1 { print_int(111) }\n\t\t2 { print_int(222) }\n\t\telse { print_int(999) }\n\t}\n\n\t// 6.4 Match with computation\n\tx4 := 5\n\tmatch x4 {\n\t\t1 { print_int(x4 * 10) }\n\t\t5 { print_int(x4 * 100) }\n\t\telse { print_int(0) }\n\t}\n\n\t// 6.5 Match with more cases\n\tx5 := 4\n\tmatch x5 {\n\t\t1 { print_int(10) }\n\t\t2 { print_int(20) }\n\t\t3 { print_int(30) }\n\t\t4 { print_int(40) }\n\t\t5 { print_int(50) }\n\t\telse { print_int(0) }\n\t}\n\n\t// ==================== 7. C-STYLE LOOP & FACTORIAL (5 tests) ====================\n\tprint_str('--- 7. C-style Loop ---')\n\n\t// 7.1 Basic factorial\n\tmut fact1 := 1\n\tfor k := 1; k <= 5; k++ {\n\t\tfact1 = fact1 * k\n\t}\n\tprint_int(fact1) // 120\n\n\t// 7.2 Sum 1 to 10\n\tmut sum7 := 0\n\tfor k := 1; k <= 10; k++ {\n\t\tsum7 += k\n\t}\n\tprint_int(sum7) // 55\n\n\t// 7.3 Powers of 2\n\tmut pow2 := 1\n\tfor k := 0; k < 8; k++ {\n\t\tpow2 = pow2 * 2\n\t}\n\tprint_int(pow2) // 256\n\n\t// 7.4 Countdown\n\tmut countdown := 0\n\tfor k := 10; k > 0; k-- {\n\t\tcountdown += k\n\t}\n\tprint_int(countdown) // 55\n\n\t// 7.5 Step by 2\n\tmut sum_even := 0\n\tfor k := 0; k <= 10; k += 2 {\n\t\tsum_even += k\n\t}\n\tprint_int(sum_even) // 0+2+4+6+8+10 = 30\n\n\t// ==================== 8. RECURSIVE FUNCTIONS (5 tests) ====================\n\tprint_str('--- 8. Recursive Functions ---')\n\n\t// 8.1 Fibonacci\n\tprint_int(fib(10)) // 55\n\n\t// 8.2 Factorial recursive\n\tprint_int(factorial(6)) // 720\n\n\t// 8.3 Sum recursive\n\tprint_int(sum_recursive(10)) // 55\n\n\t// 8.4 GCD\n\tprint_int(gcd(48, 18)) // 6\n\n\t// 8.5 Power\n\tprint_int(power(2, 10)) // 1024\n\n\t// ==================== 9. NESTED LOOPS (5 tests) ====================\n\tprint_str('--- 9. Nested Loops ---')\n\n\t// 9.1 Basic 3x3\n\tmut count1 := 0\n\tmut r1 := 0\n\tfor r1 < 3 {\n\t\tmut c1 := 0\n\t\tfor c1 < 3 {\n\t\t\tcount1++\n\t\t\tc1++\n\t\t}\n\t\tr1++\n\t}\n\tprint_int(count1) // 9\n\n\t// 9.2 4x5 grid\n\tmut count2 := 0\n\tmut r2 := 0\n\tfor r2 < 4 {\n\t\tmut c2 := 0\n\t\tfor c2 < 5 {\n\t\t\tcount2++\n\t\t\tc2++\n\t\t}\n\t\tr2++\n\t}\n\tprint_int(count2) // 20\n\n\t// 9.3 Sum of products\n\tmut sum9 := 0\n\tmut r3 := 1\n\tfor r3 <= 3 {\n\t\tmut c3 := 1\n\t\tfor c3 <= 3 {\n\t\t\tsum9 += r3 * c3\n\t\t\tc3++\n\t\t}\n\t\tr3++\n\t}\n\tprint_int(sum9) // (1+2+3) + (2+4+6) + (3+6+9) = 36\n\n\t// 9.4 2x3 with accumulator\n\tmut count4 := 0\n\tmut r4 := 0\n\tfor r4 < 2 {\n\t\tmut c4 := 0\n\t\tfor c4 < 3 {\n\t\t\tcount4 += 1\n\t\t\tc4++\n\t\t}\n\t\tr4++\n\t}\n\tprint_int(count4) // 6\n\n\t// 9.5 Inner break\n\tmut count5 := 0\n\tmut r5 := 0\n\tfor r5 < 5 {\n\t\tmut c5 := 0\n\t\tfor c5 < 10 {\n\t\t\tif c5 >= 3 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcount5++\n\t\t\tc5++\n\t\t}\n\t\tr5++\n\t}\n\tprint_int(count5) // 5*3 = 15\n\n\t// ==================== 10. INFINITE LOOP (5 tests) ====================\n\tprint_str('--- 10. Infinite Loop ---')\n\n\t// 10.1 Basic infinite with break\n\tmut iter1 := 0\n\tfor {\n\t\titer1++\n\t\tif iter1 == 5 {\n\t\t\tbreak\n\t\t}\n\t}\n\tprint_int(iter1) // 5\n\n\t// 10.2 Sum until threshold\n\tmut sum10 := 0\n\tmut n10 := 0\n\tfor {\n\t\tn10++\n\t\tsum10 += n10\n\t\tif sum10 > 20 {\n\t\t\tbreak\n\t\t}\n\t}\n\tprint_int(sum10) // 21 (1+2+3+4+5+6 = 21)\n\n\t// 10.3 Find first power of 2 > 100\n\tmut pow := 1\n\tfor {\n\t\tpow = pow * 2\n\t\tif pow > 100 {\n\t\t\tbreak\n\t\t}\n\t}\n\tprint_int(pow) // 128\n\n\t// 10.4 Countdown in infinite loop\n\tmut cd := 10\n\tfor {\n\t\tcd--\n\t\tif cd == 0 {\n\t\t\tbreak\n\t\t}\n\t}\n\tprint_int(cd) // 0\n\n\t// 10.5 Simple counter\n\tmut x10 := 0\n\tfor {\n\t\tx10++\n\t\tif x10 >= 10 {\n\t\t\tbreak\n\t\t}\n\t}\n\tprint_int(x10) // 10\n\n\t// ==================== 11. MANY ARGUMENTS (5 tests) ====================\n\tprint_str('--- 11. Many Arguments ---')\n\n\t// 11.1 Sum of 8 ones\n\tprint_int(sum_many(1, 1, 1, 1, 1, 1, 1, 1)) // 8\n\n\t// 11.2 Sum of sequence\n\tprint_int(sum_many(1, 2, 3, 4, 5, 6, 7, 8)) // 36\n\n\t// 11.3 Product of small numbers\n\tprint_int(mul_many(1, 2, 1, 2, 1, 2, 1, 2)) // 16\n\n\t// 11.4 Max of 8\n\tprint_int(max_of_eight(3, 7, 2, 9, 1, 8, 4, 6)) // 9\n\n\t// 11.5 Weighted sum\n\tprint_int(weighted_sum(1, 1, 1, 1, 1, 1, 1, 1)) // 1+2+3+4+5+6+7+8 = 36\n\n\t// ==================== 12. MODIFYING STRUCT (5 tests) ====================\n\tprint_str('--- 12. Modifying Struct via Function ---')\n\n\t// 12.1 Basic modify\n\tmut pm1 := Point{\n\t\tx: 10\n\t\ty: 20\n\t}\n\tmodify_struct(mut pm1)\n\tprint_int(pm1.x) // 999\n\tprint_int(pm1.y) // 888\n\n\t// 12.2 Swap\n\tmut pm2 := Point{\n\t\tx: 5\n\t\ty: 15\n\t}\n\tswap_point(mut pm2)\n\tprint_int(pm2.x) // 15\n\tprint_int(pm2.y) // 5\n\n\t// 12.3 Scale\n\tmut pm3 := Point{\n\t\tx: 10\n\t\ty: 20\n\t}\n\tscale_point(mut pm3, 3)\n\tprint_int(pm3.x) // 30\n\tprint_int(pm3.y) // 60\n\n\t// 12.4 Translate\n\tmut pm4 := Point{\n\t\tx: 5\n\t\ty: 10\n\t}\n\ttranslate_point(mut pm4, 100, 200)\n\tprint_int(pm4.x) // 105\n\tprint_int(pm4.y) // 210\n\n\t// 12.5 Reset\n\tmut pm5 := Point{\n\t\tx: 999\n\t\ty: 888\n\t}\n\treset_point(mut pm5)\n\tprint_int(pm5.x) // 0\n\tprint_int(pm5.y) // 0\n\n\t// ==================== 13. ASSERT (5 tests) ====================\n\tprint_str('--- 13. Assert ---')\n\n\t// 13.1 Basic equality\n\tassert 1 == 1\n\tprint_str('Assert 1 passed')\n\n\t// 13.2 Computed equality\n\tassert 2 + 2 == 4\n\tprint_str('Assert 2 passed')\n\n\t// 13.3 Boolean assert\n\tassert true\n\tprint_str('Assert 3 passed')\n\n\t// 13.4 Comparison assert\n\tassert 10 > 5\n\tprint_str('Assert 4 passed')\n\n\t// 13.5 Complex expression\n\tassert (3 * 4) == (2 * 6)\n\tprint_str('Assert 5 passed')\n\n\t// ==================== 14. HEAP ALLOCATION (5 tests) ====================\n\tprint_str('--- 14. Heap Allocation ---')\n\n\t// 14.1 Basic heap Point\n\thp1 := &Point{\n\t\tx: 10\n\t\ty: 20\n\t}\n\tprint_int(hp1.x) // 10\n\tprint_int(hp1.y) // 20\n\n\t// 14.2 Heap with zero\n\thp2 := &Point{\n\t\tx: 0\n\t\ty: 0\n\t}\n\tprint_int(hp2.x) // 0\n\tprint_int(hp2.y) // 0\n\n\t// 14.3 Heap with computed values\n\thp3 := &Point{\n\t\tx: 5 * 5\n\t\ty: 6 * 6\n\t}\n\tprint_int(hp3.x) // 25\n\tprint_int(hp3.y) // 36\n\n\t// 14.4 Heap Rectangle (no nested access)\n\thr := &Rectangle{\n\t\twidth:  100\n\t\theight: 200\n\t\torigin: Point{\n\t\t\tx: 10\n\t\t\ty: 20\n\t\t}\n\t}\n\tprint_int(hr.width) // 100\n\tprint_int(hr.height) // 200\n\n\t// 14.5 Heap Node\n\thn := &Node{\n\t\tvalue: 42\n\t\tleft:  1\n\t\tright: 2\n\t}\n\tprint_int(hn.value) // 42\n\tprint_int(hn.left) // 1\n\tprint_int(hn.right) // 2\n\n\t// ==================== 15. BITWISE OPERATIONS (5 tests) ====================\n\tprint_str('--- 15. Bitwise Operations ---')\n\n\t// 15.1 Basic AND\n\tprint_int(0b1100 & 0b1010) // 8\n\n\t// 15.2 Basic OR\n\tprint_int(0b1100 | 0b1010) // 14\n\n\t// 15.3 Basic XOR\n\tprint_int(0b1100 ^ 0b1010) // 6\n\n\t// 15.4 Mask extraction\n\tnum := 0xABCD\n\tlow_byte := num & 0xFF\n\tprint_int(low_byte) // 0xCD = 205\n\n\t// 15.5 Bit set/clear\n\tmut flags := 0\n\tflags = flags | 0b0001 // set bit 0\n\tflags = flags | 0b0100 // set bit 2\n\tprint_int(flags) // 5\n\tflags = flags & 0b1110 // clear bit 0\n\tprint_int(flags) // 4\n\n\t// ==================== 16. SHIFT OPERATIONS (5 tests) ====================\n\tprint_str('--- 16. Shift Operations ---')\n\n\t// 16.1 Left shift basic\n\tprint_int(1 << 4) // 16\n\n\t// 16.2 Right shift basic\n\tprint_int(32 >> 2) // 8\n\n\t// 16.3 Multiple shifts\n\tprint_int(255 >> 4) // 15\n\n\t// 16.4 Shift for multiply\n\tval16 := 7\n\tprint_int(val16 << 3) // 7 * 8 = 56\n\n\t// 16.5 Shift for divide\n\tval17 := 96\n\tprint_int(val17 >> 4) // 96 / 16 = 6\n\n\t// ==================== 17. MODULO (5 tests) ====================\n\tprint_str('--- 17. Modulo ---')\n\n\t// 17.1 Basic modulo\n\tprint_int(17 % 5) // 2\n\n\t// 17.2 Modulo with larger divisor\n\tprint_int(100 % 7) // 2\n\n\t// 17.3 Even/odd check\n\tprint_int(15 % 2) // 1 (odd)\n\tprint_int(16 % 2) // 0 (even)\n\n\t// 17.4 Clock arithmetic\n\thour := 23\n\tnew_hour := (hour + 5) % 24\n\tprint_int(new_hour) // 4\n\n\t// 17.5 Digit extraction\n\tnum17 := 12345\n\tlast_digit := num17 % 10\n\tprint_int(last_digit) // 5\n\tsecond_digit := (num17 / 10) % 10\n\tprint_int(second_digit) // 4\n\n\t// ==================== 18. POINTER ARITHMETIC (5 tests) ====================\n\tprint_str('--- 18. Pointer Arithmetic ---')\n\n\t// 18.1 Heap struct access\n\thp_arr1 := &Point{\n\t\tx: 10\n\t\ty: 20\n\t}\n\tprint_int(hp_arr1.x) // 10\n\tprint_int(hp_arr1.y) // 20\n\n\t// 18.2 Multiple heap structs\n\thp_arr2 := &Point{\n\t\tx: 100\n\t\ty: 200\n\t}\n\thp_arr3 := &Point{\n\t\tx: 300\n\t\ty: 400\n\t}\n\tprint_int(hp_arr2.x + hp_arr3.x) // 400\n\tprint_int(hp_arr2.y + hp_arr3.y) // 600\n\n\t// 18.3 Heap struct with computed values\n\tbase18 := 5\n\thp_arr4 := &Point{\n\t\tx: base18 * 10\n\t\ty: base18 * 20\n\t}\n\tprint_int(hp_arr4.x) // 50\n\tprint_int(hp_arr4.y) // 100\n\n\t// 18.4 Multiple heap allocations in loop\n\tmut sum18 := 0\n\tmut i18 := 0\n\tfor i18 < 3 {\n\t\thp := &Point{\n\t\t\tx: i18 * 10\n\t\t\ty: i18 * 20\n\t\t}\n\t\tsum18 = sum18 + hp.x + hp.y\n\t\ti18++\n\t}\n\tprint_int(sum18) // 0+0 + 10+20 + 20+40 = 90\n\n\t// 18.5 Heap node tree structure\n\tnode1 := &Node{\n\t\tvalue: 100\n\t\tleft:  0\n\t\tright: 0\n\t}\n\tnode2 := &Node{\n\t\tvalue: 200\n\t\tleft:  0\n\t\tright: 0\n\t}\n\tprint_int(node1.value + node2.value) // 300\n\n\t// ==================== 19. NESTED STRUCT ACCESS (5 tests) ====================\n\tprint_str('--- 19. Nested Struct Access ---')\n\n\t// 19.1 Basic nested access\n\trect := Rectangle{\n\t\twidth:  100\n\t\theight: 200\n\t\torigin: Point{\n\t\t\tx: 10\n\t\t\ty: 20\n\t\t}\n\t}\n\tprint_int(rect.width) // 100\n\tprint_int(rect.height) // 200\n\n\t// 19.2 Nested struct field via intermediate\n\trect2 := Rectangle{\n\t\twidth:  50\n\t\theight: 60\n\t\torigin: Point{\n\t\t\tx: 5\n\t\t\ty: 6\n\t\t}\n\t}\n\tprint_int(rect2.width + rect2.height) // 110\n\n\t// 19.3 Mutable nested struct modification\n\tmut rect3 := Rectangle{\n\t\twidth:  10\n\t\theight: 20\n\t\torigin: Point{\n\t\t\tx: 1\n\t\t\ty: 2\n\t\t}\n\t}\n\trect3.width = 100\n\trect3.height = 200\n\tprint_int(rect3.width) // 100\n\tprint_int(rect3.height) // 200\n\n\t// 19.4 Multiple rectangles\n\trect4a := Rectangle{\n\t\twidth:  10\n\t\theight: 20\n\t\torigin: Point{\n\t\t\tx: 0\n\t\t\ty: 0\n\t\t}\n\t}\n\trect4b := Rectangle{\n\t\twidth:  30\n\t\theight: 40\n\t\torigin: Point{\n\t\t\tx: 0\n\t\t\ty: 0\n\t\t}\n\t}\n\tprint_int(rect4a.width + rect4b.width) // 40\n\tprint_int(rect4a.height + rect4b.height) // 60\n\n\t// 19.5 Rectangle area\n\trect5 := Rectangle{\n\t\twidth:  12\n\t\theight: 10\n\t\torigin: Point{\n\t\t\tx: 0\n\t\t\ty: 0\n\t\t}\n\t}\n\tarea := rect5.width * rect5.height\n\tprint_int(area) // 120\n\n\t// ==================== 20. NEGATIVE NUMBERS (5 tests) ====================\n\tprint_str('--- 20. Negative Numbers ---')\n\n\t// 20.1 Unary minus\n\tn1 := 0 - 42\n\tprint_int(n1) // -42\n\n\t// 20.2 Negative addition\n\tn2 := 0 - 10\n\tn3 := n2 + 5\n\tprint_int(n3) // -5\n\n\t// 20.3 Negative subtraction\n\tn4 := 0 - 20\n\tn5 := n4 - 10\n\tprint_int(n5) // -30\n\n\t// 20.4 Negative multiplication\n\tn6 := 0 - 7\n\tn7 := n6 * 3\n\tprint_int(n7) // -21\n\n\t// 20.5 Double negative (positive)\n\tn8 := 0 - 50\n\tn9 := 0 - n8\n\tprint_int(n9) // 50\n\n\t// ==================== 21. UNARY OPERATIONS (5 tests) ====================\n\tprint_str('--- 21. Unary Operations ---')\n\n\t// 21.1 Logical not on false\n\tu1 := !false\n\tif u1 {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 21.2 Logical not on true\n\tu2 := !true\n\tif u2 {\n\t\tprint_int(1)\n\t} else {\n\t\tprint_int(0) // 0\n\t}\n\n\t// 21.3 Double negation\n\tu3 := !!true\n\tif u3 {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 21.4 Not with comparison\n\tu4 := !(5 > 10)\n\tif u4 {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 21.5 Not with variable\n\tu5 := false\n\tu6 := !u5\n\tif u6 {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// ==================== 22. COMPLEX BOOLEAN (5 tests) ====================\n\tprint_str('--- 22. Complex Boolean ---')\n\n\t// 22.1 Multiple ANDs\n\tif true && true && true {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 22.2 Multiple ORs\n\tif false || false || true {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 22.3 AND with OR\n\tif (true && false) || (true && true) {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 22.4 Complex condition with variables\n\taa := 10\n\tbb := 20\n\tcc := 30\n\tif aa < bb && bb < cc {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 22.5 Chained comparisons\n\tif aa < 15 && bb > 15 && cc == 30 {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// ==================== 23. COMPARISON AS EXPRESSION (5 tests) ====================\n\tprint_str('--- 23. Comparison as Expression ---')\n\n\t// 23.1 Comparison result in variable\n\tcmp1 := 10 > 5\n\tif cmp1 {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 23.2 Multiple comparison results\n\tcmp2 := 3 < 5\n\tcmp3 := 7 > 2\n\tif cmp2 && cmp3 {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 23.3 Equality comparison\n\tcmp4 := 42 == 42\n\tif cmp4 {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 23.4 Inequality comparison\n\tcmp5 := 10 != 20\n\tif cmp5 {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 23.5 Comparison with expressions\n\tcmp6 := (5 + 5) == (2 * 5)\n\tif cmp6 {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// ==================== 24. DEEPLY NESTED IF (5 tests) ====================\n\tprint_str('--- 24. Deeply Nested If ---')\n\n\t// 24.1 Three levels deep\n\tdn1 := 5\n\tif dn1 > 0 {\n\t\tif dn1 > 3 {\n\t\t\tif dn1 > 4 {\n\t\t\t\tprint_int(1) // 1\n\t\t\t} else {\n\t\t\t\tprint_int(0)\n\t\t\t}\n\t\t} else {\n\t\t\tprint_int(0)\n\t\t}\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 24.2 Nested with else chains\n\tdn2 := 2\n\tif dn2 == 1 {\n\t\tprint_int(10)\n\t} else {\n\t\tif dn2 == 2 {\n\t\t\tprint_int(20) // 20\n\t\t} else {\n\t\t\tif dn2 == 3 {\n\t\t\t\tprint_int(30)\n\t\t\t} else {\n\t\t\t\tprint_int(0)\n\t\t\t}\n\t\t}\n\t}\n\n\t// 24.3 Mixed nesting with match\n\tdn3 := 3\n\tif dn3 > 0 {\n\t\tmatch dn3 {\n\t\t\t1 { print_int(100) }\n\t\t\t2 { print_int(200) }\n\t\t\t3 { print_int(300) } // 300\n\t\t\telse { print_int(0) }\n\t\t}\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 24.4 Nested loops with conditionals\n\tmut dn4_sum := 0\n\tmut dn4_i := 0\n\tfor dn4_i < 3 {\n\t\tmut dn4_j := 0\n\t\tfor dn4_j < 3 {\n\t\t\tif dn4_i == dn4_j {\n\t\t\t\tdn4_sum += 1\n\t\t\t}\n\t\t\tdn4_j++\n\t\t}\n\t\tdn4_i++\n\t}\n\tprint_int(dn4_sum) // 3 (diagonal: 0-0, 1-1, 2-2)\n\n\t// 24.5 If inside loop with break\n\tmut dn5_result := 0\n\tmut dn5_k := 0\n\tfor dn5_k < 100 {\n\t\tif dn5_k > 5 {\n\t\t\tif dn5_k > 7 {\n\t\t\t\tdn5_result = dn5_k\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tdn5_k++\n\t}\n\tprint_int(dn5_result) // 8\n\n\t// ==================== 25. LARGE CONSTANTS (5 tests) ====================\n\tprint_str('--- 25. Large Constants ---')\n\n\t// 25.1 Value > 65535\n\tbig1 := 100000\n\tprint_int(big1) // 100000\n\n\t// 25.2 Large multiplication result\n\tbig2 := 1000 * 1000\n\tprint_int(big2) // 1000000\n\n\t// 25.3 Large addition\n\tbig3 := 50000 + 50000\n\tprint_int(big3) // 100000\n\n\t// 25.4 Large subtraction\n\tbig4 := 200000 - 100000\n\tprint_int(big4) // 100000\n\n\t// 25.5 Large division\n\tbig5 := 1000000 / 100\n\tprint_int(big5) // 10000\n\n\t// ==================== 26. MIXED OPERATIONS (5 tests) ====================\n\tprint_str('--- 26. Mixed Operations ---')\n\n\t// 26.1 Arithmetic then comparison\n\tmix1 := (10 + 5) * 2\n\tif mix1 == 30 {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 26.2 Comparison then logic\n\tmix2a := 10 > 5\n\tmix2b := 20 < 30\n\tif mix2a && mix2b {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 26.3 Chained arithmetic\n\tmix3 := 2 + 3 * 4 - 6 / 2\n\tprint_int(mix3) // 2 + 12 - 3 = 11\n\n\t// 26.4 Bitwise with arithmetic\n\tmix4 := (5 | 3) + (4 & 6)\n\tprint_int(mix4) // 7 + 4 = 11\n\n\t// 26.5 Complex expression\n\tmix5 := ((10 + 5) * 2 - 10) / 5\n\tprint_int(mix5) // (30 - 10) / 5 = 4\n\n\t// ==================== 27. EDGE CASES (5 tests) ====================\n\tprint_str('--- 27. Edge Cases ---')\n\n\t// 27.1 Zero operations\n\tedge1 := 0 + 0\n\tprint_int(edge1) // 0\n\tedge2 := 100 * 0\n\tprint_int(edge2) // 0\n\tedge3 := 0 / 7\n\tprint_int(edge3) // 0\n\n\t// 27.2 Identity operations\n\tedge4 := 42 + 0\n\tprint_int(edge4) // 42\n\tedge5 := 42 * 1\n\tprint_int(edge5) // 42\n\tedge6 := 42 / 1\n\tprint_int(edge6) // 42\n\n\t// 27.3 Division edge cases\n\tedge7 := 7 / 7\n\tprint_int(edge7) // 1\n\tedge8 := 100 / 10\n\tprint_int(edge8) // 10\n\n\t// 27.4 Modulo edge cases\n\tedge9 := 10 % 10\n\tprint_int(edge9) // 0\n\tedge10 := 5 % 7\n\tprint_int(edge10) // 5\n\n\t// 27.5 Comparison edge cases\n\tif 0 == 0 {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\tif 0 < 1 {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// ==================== 28. COMPLEX RECURSION (5 tests) ====================\n\tprint_str('--- 28. Complex Recursion ---')\n\n\t// 28.1 Deep recursion test\n\tprint_int(sum_recursive(100)) // 5050\n\n\t// 28.2 Mutual dependency via gcd\n\tprint_int(gcd(252, 105)) // 21\n\n\t// 28.3 Multiple recursive calls\n\tprint_int(fib(15)) // 610\n\n\t// 28.4 Power with larger exponent\n\tprint_int(power(3, 5)) // 243\n\n\t// 28.5 Factorial with larger input\n\tprint_int(factorial(7)) // 5040\n\n\t// ==================== 29. STRUCT OPERATIONS (5 tests) ====================\n\tprint_str('--- 29. Struct Operations ---')\n\n\t// 29.1 Struct as function result (via modify)\n\tmut sp1 := Point{\n\t\tx: 0\n\t\ty: 0\n\t}\n\tscale_point(mut sp1, 10)\n\tprint_int(sp1.x) // 0\n\tprint_int(sp1.y) // 0\n\n\t// 29.2 Chained struct modifications\n\tmut sp2 := Point{\n\t\tx: 1\n\t\ty: 1\n\t}\n\tscale_point(mut sp2, 5)\n\ttranslate_point(mut sp2, 10, 20)\n\tprint_int(sp2.x) // 15\n\tprint_int(sp2.y) // 25\n\n\t// 29.3 Struct field arithmetic\n\tsp3 := Point{\n\t\tx: 100\n\t\ty: 200\n\t}\n\tsp3_sum := sp3.x + sp3.y\n\tsp3_diff := sp3.y - sp3.x\n\tprint_int(sp3_sum) // 300\n\tprint_int(sp3_diff) // 100\n\n\t// 29.4 Multiple struct parameters\n\tmut sp4 := Point{\n\t\tx: 10\n\t\ty: 20\n\t}\n\tswap_point(mut sp4)\n\tscale_point(mut sp4, 2)\n\tprint_int(sp4.x) // 40\n\tprint_int(sp4.y) // 20\n\n\t// 29.5 Struct in conditional\n\tsp5 := Point{\n\t\tx: 5\n\t\ty: 10\n\t}\n\tif sp5.x < sp5.y {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// ==================== 30. CONTROL FLOW EDGE CASES (5 tests) ====================\n\tprint_str('--- 30. Control Flow Edge Cases ---')\n\n\t// 30.1 Empty else\n\tmut cf1 := 0\n\tif true {\n\t\tcf1 = 1\n\t}\n\tprint_int(cf1) // 1\n\n\t// 30.2 Multiple sequential ifs\n\tmut cf2 := 0\n\tif true {\n\t\tcf2 += 1\n\t}\n\tif true {\n\t\tcf2 += 2\n\t}\n\tif true {\n\t\tcf2 += 4\n\t}\n\tprint_int(cf2) // 7\n\n\t// 30.3 Nested match\n\tcf3 := 2\n\tmatch cf3 {\n\t\t1 {\n\t\t\tmatch cf3 {\n\t\t\t\t1 { print_int(11) }\n\t\t\t\telse { print_int(10) }\n\t\t\t}\n\t\t}\n\t\t2 {\n\t\t\tmatch cf3 {\n\t\t\t\t2 { print_int(22) } // 22\n\t\t\t\telse { print_int(20) }\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tprint_int(0)\n\t\t}\n\t}\n\n\t// 30.4 Loop with compound condition (&&)\n\tmut cf4 := 0\n\tmut cf4_i := 0\n\tfor cf4_i < 20 && cf4 < 50 {\n\t\tcf4 += cf4_i\n\t\tcf4_i++\n\t}\n\tprint_int(cf4) // 55 (0+1+2+3+4+5+6+7+8+9+10 = 55, stops when >= 50)\n\n\t// 30.5 Return inside nested control flow\n\tprint_int(nested_return(5)) // 100\n\tprint_int(nested_return(15)) // 200\n\tprint_int(nested_return(25)) // 300\n\n\t// 30.6 Loop with || condition\n\tmut cf5 := 0\n\tmut cf5_i := 0\n\tfor cf5_i < 3 || cf5 < 10 {\n\t\tcf5 += 5\n\t\tcf5_i++\n\t}\n\tprint_int(cf5) // 15 (loop runs 3 times: 5, 10, 15 - stops when both conditions false)\n\n\t// ==================== 31. METHODS ====================\n\tprint_str('--- 31. Methods ---')\n\n\t// 31.1 Basic method call\n\tm1 := Point{\n\t\tx: 10\n\t\ty: 20\n\t}\n\tprint_int(m1.sum()) // 30\n\n\t// 31.2 Method with multiplication\n\tm2 := Point{\n\t\tx: 5\n\t\ty: 6\n\t}\n\tprint_int(m2.product()) // 30\n\n\t// 31.3 Mutable receiver method\n\tmut m4 := Point{\n\t\tx: 7\n\t\ty: 8\n\t}\n\tm4.double()\n\tprint_int(m4.x) // 14\n\tprint_int(m4.y) // 16\n\n\t// 31.4 Rectangle methods\n\tm5 := Rectangle{\n\t\twidth:  10\n\t\theight: 5\n\t\torigin: Point{\n\t\t\tx: 0\n\t\t\ty: 0\n\t\t}\n\t}\n\tprint_int(m5.area()) // 50\n\tprint_int(m5.perimeter()) // 30\n\n\t// 31.5 Node method\n\tm6 := Node{\n\t\tvalue: 100\n\t\tleft:  10\n\t\tright: 20\n\t}\n\tprint_int(m6.total()) // 130\n\n\t// 31.6 Method on heap-allocated struct\n\tm8 := &Point{\n\t\tx: 4\n\t\ty: 5\n\t}\n\tprint_int(m8.sum()) // 9\n\tprint_int(m8.product()) // 20\n\n\t// ==================== 32. IF-EXPRESSIONS ====================\n\tprint_str('--- 32. If-Expressions ---')\n\n\t// 32.1 Basic if-expression (abs)\n\tprint_int(int_abs(-5)) // 5\n\tprint_int(int_abs(7)) // 7\n\tprint_int(int_abs(0)) // 0\n\n\t// 32.2 If-expression for max\n\tprint_int(int_max2(10, 20)) // 20\n\tprint_int(int_max2(30, 15)) // 30\n\tprint_int(int_max2(5, 5)) // 5\n\n\t// 32.3 If-expression for min\n\tprint_int(int_min2(10, 20)) // 10\n\tprint_int(int_min2(30, 15)) // 15\n\tprint_int(int_min2(8, 8)) // 8\n\n\t// 32.4 Nested if-expression (sign)\n\tprint_int(sign(-100)) // -1\n\tprint_int(sign(100)) // 1\n\tprint_int(sign(0)) // 0\n\n\t// 32.5 Double nested if-expression (clamp)\n\tprint_int(clamp(5, 0, 10)) // 5 (in range)\n\tprint_int(clamp(-5, 0, 10)) // 0 (below lo)\n\tprint_int(clamp(15, 0, 10)) // 10 (above hi)\n\n\t// 32.6 If-expression in local variable\n\tval2 := 25\n\tresult := if val2 > 20 { val2 * 2 } else { val2 }\n\tprint_int(result) // 50\n\n\t// 32.7 If-expression with complex condition\n\ta := 10\n\tb := 20\n\tc := if a < b && b < 30 { a + b } else { 0 }\n\tprint_int(c) // 30\n\n\t// ==================== 33. ARRAY INITIALIZATION ====================\n\tprint_str('--- 33. Array Initialization ---')\n\n\t// 33.1 Basic array literal\n\tarr1 := [10, 20, 30]\n\tprint_int(arr1[0]) // 10\n\tprint_int(arr1[1]) // 20\n\tprint_int(arr1[2]) // 30\n\n\t// 33.2 Array element sum\n\tarr2 := [5, 10, 15]\n\tarr2_sum := arr2[0] + arr2[1] + arr2[2]\n\tprint_int(arr2_sum) // 30\n\n\t// 33.3 Array with computed values\n\tbase_val := 7\n\tarr3 := [base_val, base_val * 2, base_val * 3]\n\tprint_int(arr3[0]) // 7\n\tprint_int(arr3[1]) // 14\n\tprint_int(arr3[2]) // 21\n\n\t// 33.4 Array element in expression\n\tarr4 := [100, 200, 300]\n\tresult4 := arr4[0] * 2 + arr4[1]\n\tprint_int(result4) // 400\n\n\t// 33.5 Array with function call on elements\n\tarr5 := [3, 4, 5]\n\tprint_int(add(arr5[0], arr5[1])) // 7\n\tprint_int(mul(arr5[1], arr5[2])) // 20\n\n\t// ==================== 34. STRING INTERPOLATION ====================\n\tprint_str('--- 34. String Interpolation ---')\n\n\t// 34.1 Basic integer interpolation\n\tinterp_x := 42\n\ts1 := 'The answer is ${interp_x}'\n\tprint_str(s1) // The answer is 42\n\n\t// 34.2 Multiple interpolations\n\tinterp_a := 10\n\tinterp_b := 20\n\ts2 := '${interp_a} + ${interp_b} = ${interp_a + interp_b}'\n\tprint_str(s2) // 10 + 20 = 30\n\n\t// 34.3 String at beginning and end\n\tinterp_val := 100\n\ts3 := 'Value: ${interp_val}!'\n\tprint_str(s3) // Value: 100!\n\n\t// 34.4 Just interpolation (no literal parts)\n\tinterp_num := 999\n\ts4 := '${interp_num}'\n\tprint_str(s4) // 999\n\n\t// 34.5 Multiple consecutive values\n\tinterp_v1 := 1\n\tinterp_v2 := 2\n\tinterp_v3 := 3\n\ts5 := '${interp_v1}-${interp_v2}-${interp_v3}'\n\tprint_str(s5) // 1-2-3\n\n\tworld := 'world'\n\ts6 := 'hello ${world}'\n\tprint_str(s6)\n\n\t// 34.6 String concatenation with + operator\n\tstr_a := 'Hello'\n\tstr_b := ' World'\n\tstr_c := str_a + str_b\n\tprint_str(str_c) // Hello World\n\n\t// 34.7 Chained string concatenation\n\tstr_chain := 'A' + 'B' + 'C'\n\tprint_str(str_chain) // ABC\n\n\t// ==================== 35. IF-GUARD EXPRESSIONS ====================\n\tprint_str('--- 35. If-Guard Expressions ---')\n\n\t// 35.1 Basic if-guard with success (positive value)\n\tif g1_val := maybe_positive(42) {\n\t\tprint_int(g1_val) // 42\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 35.2 If-guard with failure (non-positive value)\n\tif g2_val := maybe_positive(-5) {\n\t\tprint_int(g2_val)\n\t} else {\n\t\tprint_int(999) // 999 (else branch taken)\n\t}\n\n\t// 35.3 If-guard with computation in then branch\n\tif g3_val := maybe_double(25) {\n\t\tprint_int(g3_val + 10) // 50 + 10 = 60\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 35.4 If-guard with function call\n\tif g4_result := maybe_sum(10, 20) {\n\t\tprint_int(g4_result) // 30\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 35.5 Nested if with if-guard\n\tg5_outer := 5\n\tif g5_outer > 0 {\n\t\tif g5_inner := maybe_positive(g5_outer * 10) {\n\t\t\tprint_int(g5_inner) // 50\n\t\t} else {\n\t\t\tprint_int(0)\n\t\t}\n\t}\n\n\t// 35.6 If-guard in sequence\n\tmut g6_sum := 0\n\tif g6_a := maybe_positive(10) {\n\t\tg6_sum += g6_a\n\t}\n\tif g6_b := maybe_positive(20) {\n\t\tg6_sum += g6_b\n\t}\n\tif g6_c := maybe_positive(-5) {\n\t\tg6_sum += g6_c\n\t}\n\tprint_int(g6_sum) // 10 + 20 + 0 = 30\n\n\t// 35.7 If-guard with else-if chain\n\tg7_test := 100\n\tif g7_val := maybe_positive(-g7_test) {\n\t\tprint_int(g7_val)\n\t} else {\n\t\tif g7_val2 := maybe_positive(g7_test) {\n\t\t\tprint_int(g7_val2) // 100\n\t\t} else {\n\t\t\tprint_int(0)\n\t\t}\n\t}\n\n\t// 35.8 or { return } pattern with value\n\tif or_val := maybe_triple(5) {\n\t\tprint_int(or_val) // 15 (5 * 3)\n\t} else {\n\t\tprint_int(-1)\n\t}\n\n\t// 35.9 or { return } pattern with negative (returns none)\n\tif or_val2 := maybe_triple(-5) {\n\t\tprint_int(or_val2)\n\t} else {\n\t\tprint_int(0) // 0 (none case)\n\t}\n\n\t// 35.10 Direct or { value } pattern - successful call\n\tor_direct1 := maybe_positive(42) or { 0 }\n\tprint_int(or_direct1) // 42\n\n\t// 35.11 Direct or { value } pattern - fallback used\n\tor_direct2 := maybe_positive(-10) or { 99 }\n\tprint_int(or_direct2) // 99\n\n\t// 35.12 Chained or { value } with computation\n\tor_chain := maybe_double(25) or { 0 }\n\tprint_int(or_chain + 5) // 50 + 5 = 55\n\n\t// 35.13 Result or { err } pattern - ensure `err` is available in scope\n\tor_err := maybe_fail(-1) or {\n\t\tprint_str('error')\n\t\t0\n\t}\n\tprint_int(or_err) // 0\n\n\t// ==================== 36. RANGE EXPRESSIONS ====================\n\tprint_str('--- 36. Range Expressions ---')\n\n\t// 36.1 Basic array slicing with range\n\trng_arr1 := [10, 20, 30, 40, 50]\n\trng_slice1 := rng_arr1[1..4]\n\tprint_int(rng_slice1[0]) // 20\n\tprint_int(rng_slice1[1]) // 30\n\tprint_int(rng_slice1[2]) // 40\n\n\t// 36.2 Range from start\n\trng_arr2 := [100, 200, 300, 400]\n\trng_slice2 := rng_arr2[0..2]\n\tprint_int(rng_slice2[0]) // 100\n\tprint_int(rng_slice2[1]) // 200\n\n\t// 36.3 Range with variable indices\n\trng_start := 1\n\trng_end := 3\n\trng_arr3 := [5, 10, 15, 20, 25]\n\trng_slice3 := rng_arr3[rng_start..rng_end]\n\tprint_int(rng_slice3[0]) // 10\n\tprint_int(rng_slice3[1]) // 15\n\n\t// 36.4 Consecutive slicing\n\trng_arr4 := [1, 2, 3, 4, 5, 6, 7, 8]\n\trng_first_half := rng_arr4[0..4]\n\trng_second_half := rng_arr4[4..8]\n\tprint_int(rng_first_half[0]) // 1\n\tprint_int(rng_first_half[3]) // 4\n\tprint_int(rng_second_half[0]) // 5\n\tprint_int(rng_second_half[3]) // 8\n\n\t// 36.5 Single element range\n\trng_arr5 := [42, 84, 126]\n\trng_single := rng_arr5[1..2]\n\tprint_int(rng_single[0]) // 84\n\n\t// ==================== 37. FOR-IN RANGE ====================\n\tprint_str('--- 37. For-In Range ---')\n\n\t// 37.1 Basic for-in range\n\tmut forin_sum1 := 0\n\tfor i in 0 .. 5 {\n\t\tforin_sum1 += i\n\t}\n\tprint_int(forin_sum1) // 0+1+2+3+4 = 10\n\n\t// 37.2 For-in range with non-zero start\n\tmut forin_sum2 := 0\n\tfor i in 5 .. 10 {\n\t\tforin_sum2 += i\n\t}\n\tprint_int(forin_sum2) // 5+6+7+8+9 = 35\n\n\t// 37.3 For-in range with expressions\n\tforin_start := 2\n\tforin_end := 6\n\tmut forin_sum3 := 0\n\tfor i in forin_start .. forin_end {\n\t\tforin_sum3 += i\n\t}\n\tprint_int(forin_sum3) // 2+3+4+5 = 14\n\n\t// 37.4 Nested for-in ranges\n\tmut forin_count := 0\n\tfor i in 0 .. 3 {\n\t\tfor j in 0 .. 4 {\n\t\t\tforin_count += i + j + 1\n\t\t}\n\t}\n\tprint_int(forin_count) // sum of (i+j+1) for i in 0..3, j in 0..4 = 42\n\n\t// 37.5 For-in range with computation in body\n\tmut forin_product := 1\n\tfor i in 1 .. 6 {\n\t\tforin_product *= i\n\t}\n\tprint_int(forin_product) // 1*2*3*4*5 = 120\n\n\t// 37.6 For-in range with break\n\tmut forin_sum4 := 0\n\tfor i in 0 .. 100 {\n\t\tif i >= 5 {\n\t\t\tbreak\n\t\t}\n\t\tforin_sum4 += i\n\t}\n\tprint_int(forin_sum4) // 0+1+2+3+4 = 10\n\n\t// 37.7 For-in range with continue\n\tmut forin_sum5 := 0\n\tfor i in 0 .. 10 {\n\t\tif i % 2 == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tforin_sum5 += i\n\t}\n\tprint_int(forin_sum5) // 1+3+5+7+9 = 25\n\n\t// ==================== 38. DEFER STATEMENTS ====================\n\tprint_str('--- 38. Defer Statements ---')\n\n\t// 38.1 Basic defer (should print after the other prints)\n\tg_val = 0\n\tdefer {\n\t\tg_val += 100\n\t}\n\tg_val += 1\n\tprint_int(g_val) // 1 (defer not executed yet, will be 101 at function end)\n\n\t// 38.2 Multiple defers execute in reverse order (LIFO)\n\tg_count = 0\n\tdefer {\n\t\tg_count += 1\n\t}\n\tdefer {\n\t\tg_count += 10\n\t}\n\tdefer {\n\t\tg_count += 100\n\t}\n\t// At end of function: g_count = 0 + 100 + 10 + 1 = 111\n\n\t// 38.3 Defer with function call\n\tdefer {\n\t\tprint_str('Defer 38.3 executed')\n\t}\n\t// 38.4 Test defer_test function with explicit return\n\tprint_int(defer_test()) // Should print 42\n\n\t// 38.5 Test defer order in function\n\tdefer_order_test() // Should print: Third, Second, First\n\n\t// 38.6 Test defer(fn) - function-level defer\n\tprint_int(defer_fn_test()) // 303 (3 from loop + 300 from function-level defers)\n\n\t// 38.7 Test flag enum .has() and .all() methods\n\tprint_str('enum vals (exp 421):')\n\tprint_int(flag_enum_values()) // Expected: 421 (1 + 20 + 400)\n\tprint_str('AND test (exp 0):')\n\tprint_int(flag_enum_and_test()) // Expected: 0 (3 & 4 = 0)\n\tprint_str('manual has (exp 0):')\n\tprint_int(flag_enum_manual_has()) // Expected: 0 (manual has check)\n\tprint_str('flag debug (exp 3):')\n\tprint_int(flag_enum_debug()) // Expected: 3 (read=1 | write=2)\n\tprint_str('has read (exp 1):')\n\tprint_int(flag_enum_has_read()) // Expected: 1\n\tprint_str('has exec (exp 0):')\n\tprint_int(flag_enum_has_execute()) // Expected: 0\n\tprint_str('has result (exp 0):')\n\tprint_int(flag_enum_has_result()) // Expected: 0 (direct bool->int)\n\tprint_str('manual call (exp 0):')\n\tprint_int(flag_enum_manual_call()) // Expected: 0 (manual has impl)\n\tprint_str('check args (exp 304):')\n\tprint_int(flag_enum_check_args()) // Expected: 304 (perms=3, exec=4)\n\tprint_str('int args (exp 304):')\n\tprint_int(flag_enum_check_int_args()) // Expected: 304\n\tprint_str('full test (exp 13):')\n\tprint_int(flag_enum_test()) // Expected: 13 (1 + 2 + 10)\n\n\t// ==================== 39. ENUMS ====================\n\tprint_str('--- 39. Enums ---')\n\n\t// 39.1 Basic enum value\n\tcolor1 := Color.red\n\tprint_int(int(color1)) // 0\n\n\t// 39.2 Other enum values\n\tcolor2 := Color.green\n\tcolor3 := Color.blue\n\tprint_int(int(color2)) // 1\n\tprint_int(int(color3)) // 2\n\n\t// 39.3 Enum with explicit values\n\tstatus1 := Status.pending\n\tstatus2 := Status.active\n\tstatus3 := Status.done\n\tprint_int(int(status1)) // 0\n\tprint_int(int(status2)) // 1\n\tprint_int(int(status3)) // 2\n\n\t// 39.4 Enum in match\n\tmatch color1 {\n\t\t.red { print_int(100) } // 100\n\t\t.green { print_int(200) }\n\t\t.blue { print_int(300) }\n\t\telse { print_int(0) }\n\t}\n\n\t// 39.5 Enum comparison\n\tif color1 == Color.red {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// ==================== 40. FOR-IN ARRAY ====================\n\tprint_str('--- 40. For-In Array ---')\n\n\t// 40.1 Basic for-in array iteration\n\tarr_iter1 := [10, 20, 30]\n\tmut sum_iter1 := 0\n\tfor elem in arr_iter1 {\n\t\tsum_iter1 += elem\n\t}\n\tprint_int(sum_iter1) // 60\n\n\t// 40.2 For-in with index\n\tarr_iter2 := [5, 10, 15]\n\tmut weighted_sum2 := 0\n\tfor i, elem in arr_iter2 {\n\t\tweighted_sum2 += (i + 1) * elem\n\t}\n\tprint_int(weighted_sum2) // 1*5 + 2*10 + 3*15 = 70\n\n\t// 40.3 For-in with break\n\tarr_iter3 := [1, 2, 3, 4, 5]\n\tmut sum_iter3 := 0\n\tfor elem in arr_iter3 {\n\t\tif elem > 3 {\n\t\t\tbreak\n\t\t}\n\t\tsum_iter3 += elem\n\t}\n\tprint_int(sum_iter3) // 1+2+3 = 6\n\n\t// 40.4 For-in with continue\n\tarr_iter4 := [1, 2, 3, 4, 5]\n\tmut sum_iter4 := 0\n\tfor elem in arr_iter4 {\n\t\tif elem % 2 == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tsum_iter4 += elem\n\t}\n\tprint_int(sum_iter4) // 1+3+5 = 9\n\n\t// 40.5 Nested for-in\n\tarr_outer := [1, 2, 3]\n\tarr_inner := [10, 20]\n\tmut nested_sum := 0\n\tfor outer in arr_outer {\n\t\tfor inner in arr_inner {\n\t\t\tnested_sum += outer * inner\n\t\t}\n\t}\n\tprint_int(nested_sum) // (1*10+1*20) + (2*10+2*20) + (3*10+3*20) = 30+60+90 = 180\n\n\t// ==================== 41. FIXED SIZE ARRAYS ====================\n\tprint_str('--- 41. Fixed Size Arrays ---')\n\n\t// 41.1 Fixed array with literal initialization\n\tfixed_arr1 := [5, 10, 15]\n\tprint_int(fixed_arr1[0]) // 5\n\tprint_int(fixed_arr1[1]) // 10\n\tprint_int(fixed_arr1[2]) // 15\n\n\t// 41.2 Fixed array with computed index\n\tidx := 1\n\tprint_int(fixed_arr1[idx]) // 10\n\n\t// 41.3 Fixed array sum\n\tmut fixed_sum := 0\n\tfor elem in fixed_arr1 {\n\t\tfixed_sum += elem\n\t}\n\tprint_int(fixed_sum) // 30\n\n\t// 41.4 Fixed array with larger size\n\tfixed_arr2 := [1, 2, 3, 4, 5]\n\tmut fixed_product := 1\n\tfor elem in fixed_arr2 {\n\t\tfixed_product *= elem\n\t}\n\tprint_int(fixed_product) // 120\n\n\t// 41.5 Nested fixed arrays access\n\tfixed_outer := [100, 200, 300]\n\tfixed_inner := [1, 2, 3]\n\tprint_int(fixed_outer[0] + fixed_inner[2]) // 103\n\n\t// 41.6 Fixed array with ! literal syntax (explicit fixed size)\n\tfixed_literal := [1, 2, 3, 4, 5]!\n\tprint_int(fixed_literal[0]) // 1\n\tprint_int(fixed_literal[4]) // 5\n\n\t// 41.7 Fixed array .len access\n\tprint_int(fixed_literal.len) // 5\n\n\t// 41.8 Fixed array iteration with ! syntax\n\tmut fixed_literal_sum := 0\n\tfor elem in fixed_literal {\n\t\tfixed_literal_sum += elem\n\t}\n\tprint_int(fixed_literal_sum) // 15\n\n\t// 41.9 Fixed array of u8 with ! syntax\n\tbytes := [u8(65), 66, 67]!\n\tprint_int(bytes[0]) // 65 (ASCII 'A')\n\tprint_int(bytes.len) // 3\n\n\t// ==================== 42. INTERFACE IMPLEMENTATION ====================\n\tprint_str('--- 42. Interface Implementation ---')\n\n\t// 42.1 Call draw() method directly on Point (implements Drawable)\n\tdraw_pt1 := Point{\n\t\tx: 5\n\t\ty: 10\n\t}\n\tprint_int(draw_pt1.draw()) // 5*1000 + 10 = 5010\n\n\t// 42.2 Another point with draw\n\tdraw_pt2 := Point{\n\t\tx: 12\n\t\ty: 34\n\t}\n\tprint_int(draw_pt2.draw()) // 12*1000 + 34 = 12034\n\n\t// 42.3 Interface method on zero-init struct\n\tdraw_pt3 := Point{}\n\tprint_int(draw_pt3.draw()) // 0*1000 + 0 = 0\n\n\t// 42.4 Interface method with heap-allocated struct\n\tdraw_pt4 := &Point{\n\t\tx: 100\n\t\ty: 200\n\t}\n\tprint_int(draw_pt4.draw()) // 100*1000 + 200 = 100200\n\n\t// 42.5 Multiple interface method calls\n\tmut draw_total := 0\n\tdraw_a := Point{\n\t\tx: 1\n\t\ty: 2\n\t}\n\tdraw_b := Point{\n\t\tx: 3\n\t\ty: 4\n\t}\n\tdraw_total += draw_a.draw() // 1002\n\tdraw_total += draw_b.draw() // 3004\n\tprint_int(draw_total) // 4006\n\n\t// ==================== 43. TYPE ALIAS USAGE ====================\n\tprint_str('--- 43. Type Alias Usage ---')\n\n\t// 43.1 Basic type alias (MyInt is typedef'd to int)\n\tmy_a := 10\n\tmy_b := 20\n\tprint_int(my_a + my_b) // 30\n\n\t// 43.2 Type alias in function\n\tmy_result := add_my_ints(15, 25)\n\tprint_int(my_result) // 40\n\n\t// 43.3 Type alias with arithmetic\n\tmy_c := 100\n\tmy_d := my_c * 3\n\tprint_int(my_d) // 300\n\n\t// 43.4 Type alias comparison\n\tmy_e := 50\n\tmy_f := 50\n\tif my_e == my_f {\n\t\tprint_int(1) // 1\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// 43.5 Type alias in loop\n\tmut my_sum := 0\n\tfor i in 1 .. 6 {\n\t\tmy_sum += i\n\t}\n\tprint_int(my_sum) // 1+2+3+4+5 = 15\n\n\t// ==================== 44. COMPTIME ====================\n\tprint_str('--- 44. Comptime ---')\n\n\t// 44.1 Basic $if macos/$else\n\t$if macos {\n\t\tprint_int(1) // 1 on macOS\n\t} $else {\n\t\tprint_int(0) // 0 on other platforms\n\t}\n\n\t// 44.2 $if linux\n\t$if linux {\n\t\tprint_int(2) // 2 on Linux\n\t} $else {\n\t\tprint_int(20) // 20 on non-Linux\n\t}\n\n\t// 44.3 $if windows\n\t$if windows {\n\t\tprint_int(3) // 3 on Windows\n\t} $else {\n\t\tprint_int(30) // 30 on non-Windows\n\t}\n\n\t// 44.4 Negation: $if !windows\n\t$if !windows {\n\t\tprint_int(4) // 4 on non-Windows\n\t} $else {\n\t\tprint_int(40) // 40 on Windows\n\t}\n\n\t// 44.5 Comptime in function call\n\tprint_int(get_comptime_value())\n\n\t// ==================== 45. STRING STRUCT FIELDS ====================\n\tprint_str('--- 45. String Struct Fields ---')\n\n\t// 45.1 String literal .str field\n\ts45_1 := 'Hello'\n\tprint_str(s45_1) // Hello\n\n\t// 45.2 String literal .len field\n\ts45_2 := 'World'\n\tprint_int(s45_2.len) // 5\n\n\t// 45.3 Interpolated string .len field\n\tval45 := 123\n\ts45_3 := 'Val: ${val45}'\n\tprint_int(s45_3.len) // 8\n\n\t// 45.4 Multiple string operations\n\ta45 := 'AB'\n\tb45 := 'CDE'\n\tprint_int(a45.len + b45.len) // 5\n\n\t// 45.5 String in function parameter\n\tprint_str('Passed directly') // Passed directly\n\n\t// ==================== 46. UNSAFE EXPRESSIONS ====================\n\tprint_str('--- 46. Unsafe Expressions ---')\n\n\t// 46.1 Basic unsafe block returning value\n\tunsafe_val1 := unsafe {\n\t\t42\n\t}\n\tprint_int(unsafe_val1) // 42\n\n\t// 46.2 Unsafe block with computation\n\tunsafe_val2 := unsafe {\n\t\t10 + 20 + 30\n\t}\n\tprint_int(unsafe_val2) // 60\n\n\t// 46.3 Unsafe block with variable access\n\tbase_for_unsafe := 100\n\tunsafe_val3 := unsafe {\n\t\tbase_for_unsafe * 2\n\t}\n\tprint_int(unsafe_val3) // 200\n\n\t// 46.4 Unsafe block in expression context\n\tresult_unsafe := unsafe { 7 } * unsafe { 8 }\n\tprint_int(result_unsafe) // 56\n\n\t// 46.5 Unsafe with struct field access\n\tunsafe_pt := Point{\n\t\tx: 15\n\t\ty: 25\n\t}\n\tunsafe_sum := unsafe {\n\t\tunsafe_pt.x + unsafe_pt.y\n\t}\n\tprint_int(unsafe_sum) // 40\n\n\t// ==================== 47. INTERFACE VTABLE ====================\n\tprint_str('--- 47. Interface Vtable ---')\n\n\t// 47.1 Basic interface assignment and method call\n\tvtable_pt1 := Point{\n\t\tx: 7\n\t\ty: 3\n\t}\n\td1 := Drawable(vtable_pt1)\n\tprint_int(d1.draw()) // 7*1000 + 3 = 7003\n\n\t// 47.2 Interface with different values\n\tvtable_pt2 := Point{\n\t\tx: 15\n\t\ty: 25\n\t}\n\td2 := Drawable(vtable_pt2)\n\tprint_int(d2.draw()) // 15*1000 + 25 = 15025\n\n\t// 47.3 Multiple interface calls\n\tvtable_pt3 := Point{\n\t\tx: 1\n\t\ty: 1\n\t}\n\td3 := Drawable(vtable_pt3)\n\tprint_int(d3.draw() + d3.draw()) // 1001 + 1001 = 2002\n\n\t// 47.4 Shape interface with multiple methods\n\tshape_rect := Rectangle{\n\t\twidth:  10\n\t\theight: 5\n\t\torigin: Point{\n\t\t\tx: 0\n\t\t\ty: 0\n\t\t}\n\t}\n\tshape1 := Shape(shape_rect)\n\tprint_int(shape1.area()) // 10 * 5 = 50\n\tprint_int(shape1.perimeter()) // 2 * (10 + 5) = 30\n\n\t// 47.5 Sum of interface method results\n\tvtable_pt4 := Point{\n\t\tx: 2\n\t\ty: 3\n\t}\n\td4 := Drawable(vtable_pt4)\n\tvtable_pt5 := Point{\n\t\tx: 4\n\t\ty: 5\n\t}\n\td5 := Drawable(vtable_pt5)\n\tprint_int(d4.draw() + d5.draw()) // 2003 + 4005 = 6008\n\n\t// 47.6 Calculator interface with parameters\n\tcalc_pt := Point{\n\t\tx: 10\n\t\ty: 5\n\t}\n\tcalc := Calculator(calc_pt)\n\tprint_int(calc.add(3, 7)) // 10 + 5 + 3 + 7 = 25\n\tprint_int(calc.multiply(4)) // (10 + 5) * 4 = 60\n\n\t// 47.7 Multiple Calculator calls\n\tcalc_pt2 := Point{\n\t\tx: 2\n\t\ty: 3\n\t}\n\tcalc2 := Calculator(calc_pt2)\n\tprint_int(calc2.add(1, 1)) // 2 + 3 + 1 + 1 = 7\n\tprint_int(calc2.multiply(10)) // (2 + 3) * 10 = 50\n\n\t// ==================== 48. STRUCT FIELD OPERATIONS ====================\n\tprint_str('--- 48. Struct Field Operations ---')\n\n\t// 48.1 Basic field assignment with arithmetic\n\tmut sf1 := Point{\n\t\tx: 10\n\t\ty: 20\n\t}\n\tsf1.x = sf1.x + 5\n\tsf1.y = sf1.y - 3\n\tprint_int(sf1.x) // 15\n\tprint_int(sf1.y) // 17\n\n\t// 48.2 Field multiplication and division\n\tmut sf2 := Point{\n\t\tx: 6\n\t\ty: 100\n\t}\n\tsf2.x = sf2.x * 7\n\tsf2.y = sf2.y / 4\n\tprint_int(sf2.x) // 42\n\tprint_int(sf2.y) // 25\n\n\t// 48.3 Compound assignment on fields\n\tmut sf3 := Point{\n\t\tx: 50\n\t\ty: 30\n\t}\n\tsf3.x += 25\n\tsf3.y -= 10\n\tprint_int(sf3.x) // 75\n\tprint_int(sf3.y) // 20\n\n\t// 48.4 Compound multiply/divide on fields\n\tmut sf4 := Point{\n\t\tx: 8\n\t\ty: 64\n\t}\n\tsf4.x *= 5\n\tsf4.y /= 8\n\tprint_int(sf4.x) // 40\n\tprint_int(sf4.y) // 8\n\n\t// 48.5 Field used in expression with other field\n\tmut sf5 := Point{\n\t\tx: 3\n\t\ty: 4\n\t}\n\tsf5.x = sf5.x + sf5.y\n\tsf5.y = sf5.x * sf5.y\n\tprint_int(sf5.x) // 7 (3+4)\n\tprint_int(sf5.y) // 28 (7*4)\n\n\t// 48.6 Chained field operations\n\tmut sf6 := Point{\n\t\tx: 2\n\t\ty: 3\n\t}\n\tsf6.x = sf6.x * 2\n\tsf6.x = sf6.x + 1\n\tsf6.x = sf6.x * 3\n\tsf6.y = sf6.y + sf6.x\n\tprint_int(sf6.x) // 15 ((2*2+1)*3)\n\tprint_int(sf6.y) // 18 (3+15)\n\n\t// 48.7 Field modulo operation\n\tmut sf7 := Point{\n\t\tx: 17\n\t\ty: 23\n\t}\n\tsf7.x = sf7.x % 5\n\tsf7.y = sf7.y % 7\n\tprint_int(sf7.x) // 2\n\tprint_int(sf7.y) // 2\n\n\t// 48.8 Field bitwise operations\n\tmut sf8 := Point{\n\t\tx: 0b1100\n\t\ty: 0b1010\n\t}\n\tsf8.x = sf8.x & sf8.y\n\tsf8.y = sf8.x | 0b0101\n\tprint_int(sf8.x) // 8 (0b1000)\n\tprint_int(sf8.y) // 13 (0b1101)\n\n\t// 48.9 Field with function call result\n\tmut sf9 := Point{\n\t\tx: 5\n\t\ty: 10\n\t}\n\tsf9.x = add(sf9.x, sf9.y)\n\tsf9.y = mul(sf9.x, 2)\n\tprint_int(sf9.x) // 15\n\tprint_int(sf9.y) // 30\n\n\t// 48.10 Nested struct field modification\n\tmut rect_mod := Rectangle{\n\t\twidth:  10\n\t\theight: 20\n\t\torigin: Point{\n\t\t\tx: 0\n\t\t\ty: 0\n\t\t}\n\t}\n\trect_mod.width = rect_mod.width * 2\n\trect_mod.height += 5\n\trect_mod.origin.x = 100\n\trect_mod.origin.y = rect_mod.origin.x / 2\n\tprint_int(rect_mod.width) // 20\n\tprint_int(rect_mod.height) // 25\n\tprint_int(rect_mod.origin.x) // 100\n\tprint_int(rect_mod.origin.y) // 50\n\n\t// ==================== 49. PRINTLN ====================\n\tprint_str('--- 49. Println ---')\n\n\t// 49.1 Test println\n\tprintln('hello world')\n\n\t// ==================== 50. ALGEBRAIC OPTIMIZATIONS ====================\n\tprint_str('--- 50. Algebraic Optimizations ---')\n\n\t// 50.1 x - x = 0\n\topt_val := 42\n\tprint_int(opt_val - opt_val) // 0\n\n\t// 50.2 x ^ x = 0\n\topt_xor := 123\n\tprint_int(opt_xor ^ opt_xor) // 0\n\n\t// 50.3 x & x = x\n\topt_and := 99\n\tprint_int(opt_and & opt_and) // 99\n\n\t// 50.4 x | x = x\n\topt_or := 77\n\tprint_int(opt_or | opt_or) // 77\n\n\t// 50.5 x * 2 = x << 1\n\topt_mul2 := 25\n\tprint_int(opt_mul2 * 2) // 50\n\n\t// 50.6 Combined optimizations\n\topt_a := 10\n\topt_b := opt_a - opt_a // Should be 0\n\topt_c := opt_a | opt_a // Should be 10\n\tprint_int(opt_b) // 0\n\tprint_int(opt_c) // 10\n\n\t// 50.7 2 * x = x << 1 (commutative)\n\topt_mul2_comm := 13\n\tprint_int(2 * opt_mul2_comm) // 26\n\n\t// 50.8 Algebraic opts in expressions\n\topt_expr := 7\n\tprint_int((opt_expr ^ opt_expr) + 5) // 0 + 5 = 5\n\tprint_int((opt_expr & opt_expr) * 2) // 7 * 2 = 14\n\n\t// 50.9 Algebraic opts with different values\n\topt_large := 12345\n\tprint_int(opt_large - opt_large) // 0\n\tprint_int(opt_large ^ opt_large) // 0\n\tprint_int(opt_large & opt_large) // 12345\n\tprint_int(opt_large | opt_large) // 12345\n\n\t// 50.10 Algebraic opts in loop\n\tmut opt_loop_sum := 0\n\tfor i in 1 .. 5 {\n\t\topt_loop_sum += i - i // Should add 0 each iteration\n\t\topt_loop_sum += i & i // Should add i each iteration\n\t}\n\tprint_int(opt_loop_sum) // 0+1 + 0+2 + 0+3 + 0+4 = 10\n\n\t// ==================== 51. DEAD STORE ELIMINATION ====================\n\tprint_str('--- 51. Dead Store Elimination ---')\n\n\t// 51.1 Basic dead store - local var never read\n\t// The optimizer should remove stores to variables that are never used\n\t{\n\t\tmut dead_var := 100\n\t\tdead_var = 200 // dead store, never read\n\t\t_ = dead_var\n\t}\n\tprint_int(1) // 1 - verify execution continues\n\n\t// 51.2 Dead store with live store after\n\tmut dse_var := 10\n\tdse_var = 20 // dead store (overwritten before read)\n\tdse_var = 30 // this is the live store\n\tprint_int(dse_var) // 30\n\n\t// 51.3 Multiple dead stores\n\tmut dse_multi := 1\n\tdse_multi = 2 // dead\n\tdse_multi = 3 // dead\n\tdse_multi = 4 // dead\n\tdse_multi = 5 // live\n\tprint_int(dse_multi) // 5\n\n\t// 51.4 Dead store in branch not taken\n\tmut dse_branch := 100\n\tif false {\n\t\tdse_branch = 999 // dead (branch never taken)\n\t}\n\tprint_int(dse_branch) // 100\n\n\t// 51.5 Live store in taken branch\n\tmut dse_live := 50\n\tif true {\n\t\tdse_live = 75\n\t}\n\tprint_int(dse_live) // 75\n\n\t// ==================== 52. DEAD PHI ELIMINATION ====================\n\tprint_str('--- 52. Dead Phi Elimination ---')\n\n\t// 52.1 Phi from if-else where result is unused\n\t// The phi node should be eliminated if not used\n\tmut phi_unused := 0\n\tif true {\n\t\tphi_unused = 10\n\t} else {\n\t\tphi_unused = 20\n\t}\n\t// phi_unused is reassigned, so previous phi is dead\n\tphi_unused = 99\n\tprint_int(phi_unused) // 99\n\n\t// 52.2 Multiple phi nodes, some dead\n\tmut phi_a := 0\n\tmut phi_b := 0\n\tif true {\n\t\tphi_a = 1\n\t\tphi_b = 2\n\t} else {\n\t\tphi_a = 3\n\t\tphi_b = 4\n\t}\n\t// phi_b is dead (overwritten), phi_a is live\n\tphi_b = 100\n\tprint_int(phi_a) // 1\n\tprint_int(phi_b) // 100\n\n\t// 52.3 Loop phi - variable assigned in loop body\n\tmut phi_loop := 0\n\tfor i in 0 .. 3 {\n\t\tphi_loop = i // intermediate values are dead, only final matters\n\t}\n\tprint_int(phi_loop) // 2 (last iteration value)\n\n\t// 52.4 Nested if with dead phi\n\tmut phi_nested := 0\n\tif true {\n\t\tif true {\n\t\t\tphi_nested = 10\n\t\t} else {\n\t\t\tphi_nested = 20\n\t\t}\n\t\tphi_nested = 30 // overwrites inner phi result\n\t}\n\tprint_int(phi_nested) // 30\n\n\t// 52.5 Complex phi scenario with loop and conditionals\n\tmut phi_complex := 1\n\tfor i in 0 .. 4 {\n\t\tif i % 2 == 0 {\n\t\t\tphi_complex = phi_complex + 1\n\t\t} else {\n\t\t\tphi_complex = phi_complex * 2\n\t\t}\n\t}\n\tprint_int(phi_complex) // 1 -> 2 -> 4 -> 5 -> 10\n\n\t// ==================== 53. CONSTANT DEDUPLICATION ====================\n\tprint_str('--- 53. Constant Deduplication ---')\n\n\t// 53.1 Same constant used multiple times\n\tconst_a := 42\n\tconst_b := 42\n\tconst_c := 42\n\tprint_int(const_a + const_b + const_c) // 126\n\n\t// 53.2 Zero constant deduplication\n\tzero1 := 0\n\tzero2 := 0\n\tzero3 := 0\n\tprint_int(zero1 + zero2 + zero3) // 0\n\n\t// 53.3 Constant from algebraic opts should be deduplicated\n\tdedup_x := 50\n\tresult1 := dedup_x - dedup_x // creates zero\n\tdedup_y := 60\n\tresult2 := dedup_y - dedup_y // should reuse same zero\n\tprint_int(result1 + result2) // 0\n\n\t// 53.4 Multiple shifts with same constant\n\tshift_a := 1\n\tshift_b := 2\n\tshift_c := 4\n\t// All these use constant 1 for the shift amount when x*2 is optimized\n\tprint_int(shift_a * 2 + shift_b * 2 + shift_c * 2) // 2 + 4 + 8 = 14\n\n\t// 53.5 Constants in expressions\n\texpr_const := (10 + 10) * (5 + 5) // Both 10s and 5s should be deduplicated\n\tprint_int(expr_const) // 200\n\n\t// ==================== 54. HASHMAPS ====================\n\tprint_str('--- 54. Hashmaps ---')\n\n\t// 54.1 Basic map initialization and assignment\n\tmut hm1 := map[int]int{}\n\thm1[1] = 10\n\thm1[2] = 20\n\thm1[3] = 30\n\tprint_int(hm1[1]) // 10\n\tprint_int(hm1[2]) // 20\n\tprint_int(hm1[3]) // 30\n\n\t// 54.2 Map len\n\tprint_str('map len:')\n\tprint_int(hm1.len) // 3\n\n\t// 54.3 Map with different keys\n\tmut hm2 := map[int]int{}\n\thm2[100] = 1000\n\thm2[200] = 2000\n\tprint_int(hm2[100]) // 1000\n\tprint_int(hm2[200]) // 2000\n\tprint_int(hm2.len) // 2\n\n\t// 54.4 Map value update\n\tmut hm3 := map[int]int{}\n\thm3[5] = 50\n\tprint_int(hm3[5]) // 50\n\thm3[5] = 500\n\tprint_int(hm3[5]) // 500\n\tprint_int(hm3.len) // 1 (still 1, not 2)\n\n\t// 54.5 Map with computed values\n\tmut hm4 := map[int]int{}\n\tfor i in 0 .. 5 {\n\t\thm4[i] = i * i\n\t}\n\tprint_int(hm4[0]) // 0\n\tprint_int(hm4[1]) // 1\n\tprint_int(hm4[2]) // 4\n\tprint_int(hm4[3]) // 9\n\tprint_int(hm4[4]) // 16\n\n\t// 54.6 Map literal initialization\n\tprint_str('map literal:')\n\tmut hm5 := {\n\t\t'a': 1\n\t\t'b': 2\n\t\t'c': 3\n\t}\n\tprint_int(hm5['a']) // 1\n\tprint_int(hm5['b']) // 2\n\tprint_int(hm5['c']) // 3\n\tprint_int(hm5.len) // 3\n\thm5['d'] = 4\n\tprint_int(hm5['d']) // 4\n\tprint_int(hm5.len) // 4\n\n\t// 54.7 Map clone\n\tprint_str('map clone:')\n\tmut hm6 := {\n\t\t'x': 100\n\t\t'y': 200\n\t}\n\thm7 := hm6.clone()\n\tprint_int(hm7['x']) // 100\n\tprint_int(hm7['y']) // 200\n\tprint_int(hm7.len) // 2\n\t// Verify clone is independent\n\thm6['x'] = 999\n\tprint_int(hm6['x']) // 999 (modified original)\n\tprint_int(hm7['x']) // 100 (clone unchanged)\n\n\t// ==================== 55. MULTI-RETURN ====================\n\tprint_str('--- 55. Multi-return ---')\n\n\t// 55.1 Basic two-value return\n\ta1, b1 := swap(10, 20)\n\tprint_int(a1) // 20\n\tprint_int(b1) // 10\n\n\t// 55.2 Division and modulo\n\tquot, rem := divmod(17, 5)\n\tprint_int(quot) // 3\n\tprint_int(rem) // 2\n\n\t// 55.3 Min/max of three values\n\tmin1, max1 := min_max(5, 2, 8)\n\tprint_int(min1) // 2\n\tprint_int(max1) // 8\n\n\t// 55.4 Three-value return\n\tt1, t2, t3 := triple_return(7)\n\tprint_int(t1) // 7\n\tprint_int(t2) // 14\n\tprint_int(t3) // 21\n\n\t// 55.5 Ignore some return values with _\n\t_, only_rem := divmod(23, 4)\n\tprint_int(only_rem) // 3\n\n\tonly_quot, _ := divmod(23, 4)\n\tprint_int(only_quot) // 5\n\tprint_str('pi=')\n\tprint_int(pi)\n\n\t// 55.6 String compound assignment\n\tmut s := 'hello'\n\ts += ' world'\n\tprint_str(s) // hello world\n\n\t// 55.7 Array comparison\n\tcmp_arr1 := [1, 2, 3]\n\tcmp_arr2 := [1, 2, 3]\n\tcmp_arr3 := [1, 2, 4]\n\tif cmp_arr1 == cmp_arr2 {\n\t\tprint_str('arr1 == arr2: yes')\n\t}\n\tif cmp_arr1 != cmp_arr3 {\n\t\tprint_str('arr1 != arr3: yes')\n\t}\n\n\t// ==================== 56. ARRAY FILTER (4 tests) ====================\n\tprint_str('--- 56. Array filter ---')\n\n\t// 56.1 Basic filter with it\n\tfilter_arr := [1, 2, 3, 4, 5, 6]\n\tevens := filter_arr.filter(it % 2 == 0)\n\tprint_str('filtered.len:')\n\tprint_int(evens.len) // 3\n\tprint_str('filtered values:')\n\tfor _, number in evens {\n\t\tprint_int(number)\n\t}\n\n\t// 56.2 Filter with comparison\n\todds := filter_arr.filter(it % 2 != 0)\n\tprint_int(odds.len) // 3\n\n\t// 56.3 Filter that returns nothing\n\tbig_nums := filter_arr.filter(it > 10)\n\tprint_int(big_nums.len) // 0\n\n\t// 56.4 Filter that returns everything\n\tsmall_nums := filter_arr.filter(it <= 6)\n\tprint_int(small_nums.len) // 6\n\n\t// 56.5 Filter as function argument (non-assignment context)\n\tprint_int(filter_arr.filter(it > 3).len) // 3\n\n\t// 56.6 Map in assignment context\n\tmapped := filter_arr.map(it * 2)\n\tprint_int(mapped.len) // 6\n\tprint_int(mapped[0]) // 2\n\tprint_int(mapped[5]) // 12\n\n\t// 56.7 Map as function argument (non-assignment context)\n\tprint_int(filter_arr.map(it + 10).len) // 6\n\n\t// ==================== 57. ARRAY STR (auto-generated) ====================\n\tprint_str('--- 57. Array str ---')\n\n\t// 57.1 Basic array str via println\n\tstr_arr := [1, 2, 3, 4]\n\tprintln(str_arr) // should print [1, 2, 3, 4]\n\n\t// 57.2 Empty array str\n\tempty_arr := []int{}\n\tprintln(empty_arr) // should print []\n\n\t// 57.3 Single element array\n\tsingle_arr := [42]\n\tprintln(single_arr) // should print [42]\n\n\t// ==================== 58. IF-GUARD EXPRESSIONS ====================\n\tprint_str('--- 58. If-guard expressions ---')\n\n\t// 58.1 Basic map if-guard - key exists\n\tmut guard_map := map[int]int{}\n\tguard_map[10] = 100\n\tguard_map[20] = 200\n\tif guard_val1 := guard_map[10] {\n\t\tprint_int(guard_val1) // 100\n\t} else {\n\t\tprint_str('not found')\n\t}\n\n\t// 58.2 Map if-guard - key doesn't exist\n\tif guard_val2 := guard_map[99] {\n\t\tprint_int(guard_val2)\n\t} else {\n\t\tprint_str('key 99 not found') // should print this\n\t}\n\n\t// 58.3 Value-level if-guard (ternary-like)\n\tresult_guard := if gv1 := guard_map[20] { gv1 } else { 0 }\n\tprint_int(result_guard) // 200\n\n\t// 58.4 Value-level if-guard with missing key\n\tresult_missing := if gv2 := guard_map[999] { gv2 } else { -1 }\n\tprint_int(result_missing) // -1\n\n\t// 58.5 Multiple if-guards in sequence (same variable name)\n\tif off := guard_map[10] {\n\t\tprint_int(off) // 100\n\t}\n\tif off := guard_map[20] {\n\t\tprint_int(off) // 200\n\t}\n\n\t// 58.6 If-guard with computation in body\n\tif v := guard_map[10] {\n\t\tdoubled := v * 2\n\t\tprint_int(doubled) // 200\n\t}\n\n\t// 59. Array clone() on nested selectors\n\t// Test that array.clone() works on deeply nested selector expressions\n\t// like wrapper.holder.data.clone() - this tests the fix for chained selector type inference\n\tmut holder := ArrayHolder{\n\t\tdata: []int{cap: 10}\n\t}\n\tholder.data << 10\n\tholder.data << 20\n\tholder.data << 30\n\tmut wrap := Wrapper{\n\t\tholder: &holder\n\t}\n\t// Clone via nested selector (wrapper.holder.data.clone())\n\tmut cloned_arr := wrap.holder.data.clone()\n\tprint_int(cloned_arr.len) // 3\n\tprint_int(cloned_arr[0]) // 10\n\tprint_int(cloned_arr[2]) // 30\n\n\t// Verify clone is independent - modify cloned array\n\t// TODO: cloned_arr[0] = 99 crashes - skip for now\n\t// cloned_arr[0] = 99\n\t// print_int(cloned_arr[0]) // 99 (modified)\n\t// print_int(wrap.holder.data[0]) // 10 (original unchanged)\n\n\t// 60. Map indexing with push (map[key] << value)\n\t// Test that g.pending_labels[blk] << off pattern works correctly\n\t// This uses map_get_and_set to auto-create empty array if key doesn't exist\n\tmut pl := PendingLabels{\n\t\tlabels: map[int][]int{}\n\t}\n\tpl.labels[5] << 100 // First push to key 5 - creates new array\n\tpl.labels[5] << 200 // Second push to same key\n\tpl.labels[10] << 50 // Push to different key\n\tprint_int(pl.labels[5].len) // 2\n\tprint_int(pl.labels[5][0]) // 100\n\tprint_int(pl.labels[5][1]) // 200\n\tprint_int(pl.labels[10].len) // 1\n\tprint_int(pl.labels[10][0]) // 50\n\n\t// ==================== 61. MUTABLE SLICE ARGUMENTS ====================\n\tprint_str('--- 61. Mutable slice arguments ---')\n\n\t// Test that slices can be passed as mutable arguments to functions\n\t// This tests the &(array[]){builtin__array_slice(...)}[0] pattern\n\tmut slice_data := []int{len: 8}\n\tslice_data[0] = 10\n\tslice_data[1] = 20\n\tslice_data[2] = 30\n\tslice_data[3] = 40\n\n\t// TODO: Slice arguments crash - skip for now\n\t// 61.1 Read from slice (non-mutable)\n\t// read_result := read_from_slice(slice_data[1..3])\n\t// print_int(read_result) // 50 (20 + 30)\n\t// 61.2-61.3 also skipped\n\n\t// ==================== 62. MAP INDEX WITH OR BLOCK ====================\n\tprint_str('--- 62. Map index with or block ---')\n\n\t// Test the pattern: map[key] or { fallback }\n\t// This is used in lookup_type_from_env and similar functions\n\tmut or_test_map := map[string]int{}\n\tor_test_map['foo'] = 42\n\tor_test_map['bar'] = 100\n\tor_test_map['builtin'] = 999\n\n\t// 62.1 Key exists - should return the value\n\tor_result1 := map_lookup_with_or(or_test_map, 'foo')\n\tprint_int(or_result1) // 42\n\n\t// 62.2 Key doesn't exist - should return fallback (-1)\n\tor_result2 := map_lookup_with_or(or_test_map, 'nonexistent')\n\tprint_int(or_result2) // -1\n\n\t// 62.3 Nested or block - first key exists\n\tor_result3 := nested_map_or(or_test_map, 'foo')\n\tprint_int(or_result3) // 42\n\n\t// 62.4 Nested or block - first key missing, fallback to 'builtin'\n\tor_result4 := nested_map_or(or_test_map, 'missing')\n\tprint_int(or_result4) // 999 (from 'builtin' key)\n\n\t// 62.5 Nested or block - both keys missing, return default\n\tmut or_empty_map := map[string]int{}\n\tor_result5 := nested_map_or(or_empty_map, 'anything')\n\tprint_int(or_result5) // -999 (default from return in or block)\n\n\t// ==================== 63. IF-GUARD WITH METHOD CALL ====================\n\tprint_str('--- 63. If-guard with method call returning optional ---')\n\n\t// This tests the pattern from lookup_type_from_env:\n\t// if obj := container.method() { ... } - method returning optional\n\n\t// 63.1 Method returning optional - found case\n\tdc := DataContainer{\n\t\tvalue: 42\n\t\tname:  'test'\n\t}\n\tif val := dc.lookup('test') {\n\t\tprint_int(val) // 42\n\t}\n\n\t// 63.2 Method returning optional - not found case\n\tif val := dc.lookup('missing') {\n\t\tprint_int(val) // Should not print\n\t} else {\n\t\tprint_int(-100) // -100\n\t}\n\n\t// 63.3 Nested method call with if-guard\n\tdc2 := DataContainer{\n\t\tvalue: 777\n\t\tname:  'found'\n\t}\n\tmut result63 := 0\n\tif v := dc2.lookup('found') {\n\t\tresult63 = v\n\t}\n\tprint_int(result63) // 777\n\n\t// ==================== 64. IF-GUARD + IS-CHECK + OPTION RETURN ====================\n\tprint_str('--- 64. If-guard with is-check and optional return ---')\n\n\t// This tests the pattern from lookup_struct_from_env in arm64:\n\t// fn lookup_struct() ?Struct { if typ := lookup_type() { if typ is Struct { return typ } } return none }\n\n\t// 64.1 Setup type_holder with struct and enum types\n\ttype_holder := TypeHolder{\n\t\tstruct_type: StructType{\n\t\t\tname:   'Point'\n\t\t\tfields: 2\n\t\t}\n\t\tenum_type:   EnumType{\n\t\t\tname:     'Color'\n\t\t\tvariants: 3\n\t\t}\n\t}\n\n\t// 64.2 lookup_struct - found case (asking for 'struct' returns the struct type)\n\tif s64_1 := type_holder.lookup_struct('struct') {\n\t\tprint_str(s64_1.name) // Point\n\t\tprint_int(s64_1.fields) // 2\n\t} else {\n\t\tprint_str('NOT_FOUND')\n\t}\n\n\t// 64.3 lookup_struct - not found because 'enum' returns EnumType, not StructType\n\tif s64_2 := type_holder.lookup_struct('enum') {\n\t\tprint_str(s64_2.name)\n\t} else {\n\t\tprint_int(-200) // -200 (returned enum, not struct)\n\t}\n\n\t// 64.4 lookup_struct - not found because key doesn't exist\n\tif s64_3 := type_holder.lookup_struct('missing') {\n\t\tprint_str(s64_3.name)\n\t} else {\n\t\tprint_int(-300) // -300 (key not found)\n\t}\n\n\t// 64.5 lookup_enum - found case (asking for 'enum' returns the enum type)\n\tif e64_1 := type_holder.lookup_enum('enum') {\n\t\tprint_str(e64_1.name) // Color\n\t\tprint_int(e64_1.variants) // 3\n\t} else {\n\t\tprint_str('NOT_FOUND')\n\t}\n\n\t// 64.6 lookup_enum - not found because 'struct' returns StructType, not EnumType\n\tif e64_2 := type_holder.lookup_enum('struct') {\n\t\tprint_str(e64_2.name)\n\t} else {\n\t\tprint_int(-400) // -400 (returned struct, not enum)\n\t}\n\n\t// ==================== 65. MAP ITERATION WITH POINTER VALUES ====================\n\tprint_str('--- 65. Map iteration with pointer values ---')\n\n\t// Tests map[int]&Struct iteration - the same pattern used in allocate_registers\n\n\t// 65.1 Create map with pointer values\n\tmut intervals := map[int]&Point{}\n\tintervals[1] = &Point{\n\t\tx: 10\n\t\ty: 100\n\t}\n\tintervals[2] = &Point{\n\t\tx: 20\n\t\ty: 200\n\t}\n\tintervals[3] = &Point{\n\t\tx: 30\n\t\ty: 300\n\t}\n\n\t// 65.2 Iterate over map and collect pointer values\n\tmut sum_x := 0\n\tmut sum_y := 0\n\tfor _, p in intervals {\n\t\tsum_x += p.x\n\t\tsum_y += p.y\n\t}\n\tprint_int(sum_x) // 60 (10+20+30)\n\tprint_int(sum_y) // 600 (100+200+300)\n\n\t// 65.3 If-guard with map[int]&Struct\n\tif pt65 := intervals[2] {\n\t\tprint_int(pt65.x) // 20\n\t\tprint_int(pt65.y) // 200\n\t}\n\n\t// ==================== 66. NESTED MAP INDEXING IN ARRAY ====================\n\tprint_str('--- 66. Nested map indexing in array ---')\n\n\t// Tests used[reg_map[val_id]] pattern - nested map index as array index\n\n\t// 66.1 Setup array and map\n\tmut used66 := []bool{len: 10, init: false}\n\tmut reg_map66 := map[int]int{}\n\treg_map66[5] = 3 // val_id 5 -> index 3\n\treg_map66[7] = 8 // val_id 7 -> index 8\n\n\t// 66.2 Use nested map index to set array element\n\tused66[reg_map66[5]] = true\n\tprint_int(if used66[3] { 1 } else { 0 }) // 1 (index 3 was set)\n\tprint_int(if used66[0] { 1 } else { 0 }) // 0 (index 0 not set)\n\n\t// 66.3 Use nested map index in loop\n\tval_ids := [5, 7]\n\tfor vid in val_ids {\n\t\tmap_idx := reg_map66[vid]\n\t\tused66[map_idx] = true\n\t}\n\tprint_int(if used66[3] { 1 } else { 0 }) // 1\n\tprint_int(if used66[8] { 1 } else { 0 }) // 1\n\n\t// 66.4 Direct nested indexing\n\tused66[reg_map66[7]] = false\n\tprint_int(if used66[8] { 1 } else { 0 }) // 0 (reset to false)\n\n\t// ==================== 67. NESTED MAP ASSIGNMENT ====================\n\tprint_str('--- 67. Nested map assignment ---')\n\n\t// Tests map[string]map[string]bool{} pattern - nested map with inner map initialization\n\n\t// 67.1 Create nested map and initialize inner map\n\tmut nested_map := map[string]map[string]bool{}\n\tif 'mod1' !in nested_map {\n\t\tnested_map['mod1'] = map[string]bool{}\n\t}\n\tnested_map['mod1']['TypeA'] = true\n\tnested_map['mod1']['TypeB'] = true\n\n\t// 67.2 Verify values\n\tprint_int(if nested_map['mod1']['TypeA'] { 1 } else { 0 }) // 1\n\tprint_int(if nested_map['mod1']['TypeB'] { 1 } else { 0 }) // 1\n\tprint_int(if nested_map['mod1']['TypeC'] { 1 } else { 0 }) // 0 (not set)\n\n\t// 67.3 Add another module\n\tif 'mod2' !in nested_map {\n\t\tnested_map['mod2'] = map[string]bool{}\n\t}\n\tnested_map['mod2']['TypeX'] = true\n\tprint_int(if nested_map['mod2']['TypeX'] { 1 } else { 0 }) // 1\n\n\t// 67.4 Check independence of inner maps\n\tprint_int(if nested_map['mod1']['TypeA'] { 1 } else { 0 }) // 1 (still set)\n\tprint_int(if nested_map['mod2']['TypeA'] { 1 } else { 0 }) // 0 (not in mod2)\n\n\t// ==================== 68. SMARTCAST WITH IS-CHECK ====================\n\tprint_str('--- 68. Smartcast with is-check ---')\n\n\t// Tests `if x is Type` pattern with sum types\n\n\t// 68.1 Basic is-check with int variant\n\tnum1 := Number(42)\n\tif num1 is int {\n\t\tprint_int(num1) // 42 (smartcasted to int)\n\t} else {\n\t\tprint_int(-1)\n\t}\n\n\t// 68.2 Basic is-check with Point variant\n\tnum2 := Number(Point{\n\t\tx: 10\n\t\ty: 20\n\t})\n\tif num2 is Point {\n\t\tprint_int(num2.x) // 10 (smartcasted to Point, access field)\n\t\tprint_int(num2.y) // 20\n\t} else {\n\t\tprint_int(-1)\n\t}\n\n\t// 68.3 Negative is-check - int is not Point\n\tnum3 := Number(100)\n\tif num3 is Point {\n\t\tprint_int(num3.x)\n\t} else {\n\t\tprint_int(-100) // -100 (num3 is int, not Point)\n\t}\n\n\t// 68.4 Negative is-check - Point is not int\n\tnum4 := Number(Point{\n\t\tx: 5\n\t\ty: 6\n\t})\n\tif num4 is int {\n\t\tprint_int(num4)\n\t} else {\n\t\tprint_int(-200) // -200 (num4 is Point, not int)\n\t}\n\n\t// 68.5 Smartcast with computation\n\tnum5 := Number(Point{\n\t\tx: 3\n\t\ty: 4\n\t})\n\tif num5 is Point {\n\t\tsum := num5.x + num5.y\n\t\tprint_int(sum) // 7\n\t}\n\n\t// 68.6 Compound is-check with && and field access\n\t// Tests: if x is Type && x.field == value { ... }\n\t// This requires smartcast to be applied in compound conditions\n\tnum6 := Number(Point{\n\t\tx: 42\n\t\ty: 100\n\t})\n\tif num6 is Point && num6.x == 42 {\n\t\tprint_int(num6.y) // 100 (smartcast applied in compound &&)\n\t} else {\n\t\tprint_int(-1)\n\t}\n\n\t// 68.7 Compound is-check that fails the field check\n\tnum7 := Number(Point{\n\t\tx: 10\n\t\ty: 20\n\t})\n\tif num7 is Point && num7.x == 999 {\n\t\tprint_int(-1) // Should not reach here\n\t} else {\n\t\tprint_int(111) // 111 (fails because x != 999)\n\t}\n\n\t// 68.8 Compound is-check that fails the type check\n\tnum8 := Number(77)\n\tif num8 is Point && num8.x == 77 {\n\t\tprint_int(-1) // Should not reach here\n\t} else {\n\t\tprint_int(77) // 77 (int is not Point)\n\t}\n\n\t// ==================== 69. ARRAY APPEND ON STRUCT FIELDS ====================\n\tprint_str('--- 69. Array append on struct fields ---')\n\n\t// Tests arr << elem pattern on struct fields (cleanc fallback when transformer doesn't handle it)\n\n\t// 69.1 Basic array append on struct field\n\tmut holder69 := ArrayHolder{\n\t\tdata: []int{}\n\t}\n\tholder69.data << 10\n\tholder69.data << 20\n\tholder69.data << 30\n\tprint_int(holder69.data.len) // 3\n\tprint_int(holder69.data[0]) // 10\n\tprint_int(holder69.data[1]) // 20\n\tprint_int(holder69.data[2]) // 30\n\n\t// 69.2 Array append in a loop\n\tmut holder69b := ArrayHolder{\n\t\tdata: []int{}\n\t}\n\tfor i := 0; i < 5; i++ {\n\t\tholder69b.data << i * 2\n\t}\n\tprint_int(holder69b.data.len) // 5\n\tprint_int(holder69b.data[0]) // 0\n\tprint_int(holder69b.data[4]) // 8\n\n\t// 69.3 Array append with expression\n\tmut holder69c := ArrayHolder{\n\t\tdata: []int{}\n\t}\n\tx69 := 100\n\tholder69c.data << x69 + 1\n\tholder69c.data << x69 * 2\n\tprint_int(holder69c.data[0]) // 101\n\tprint_int(holder69c.data[1]) // 200\n\n\t// ==================== 70. MATCH EXPRESSION ON SUM TYPES ====================\n\tprint_str('--- 70. Match on sum types ---')\n\n\t// Tests `match x { Type { ... } }` pattern with sum types and smartcasting\n\n\t// 70.1 Match on int variant\n\tnum70a := Number(42)\n\tmatch num70a {\n\t\tint {\n\t\t\tprint_int(num70a) // 42 (smartcasted to int)\n\t\t}\n\t\tPoint {\n\t\t\tprint_int(-1)\n\t\t}\n\t}\n\n\t// 70.2 Match on Point variant with field access\n\tnum70b := Number(Point{\n\t\tx: 7\n\t\ty: 8\n\t})\n\tmatch num70b {\n\t\tint {\n\t\t\tprint_int(-1)\n\t\t}\n\t\tPoint {\n\t\t\tprint_int(num70b.x) // 7 (smartcasted to Point)\n\t\t\tprint_int(num70b.y) // 8\n\t\t}\n\t}\n\n\t// 70.3 Match with computation on Point variant\n\tnum70c := Number(Point{\n\t\tx: 5\n\t\ty: 5\n\t})\n\tmatch num70c {\n\t\tint {\n\t\t\tprint_int(num70c + 1)\n\t\t}\n\t\tPoint {\n\t\t\tsum70 := num70c.x + num70c.y\n\t\t\tprint_int(sum70) // 10\n\t\t}\n\t}\n\n\t// 70.4 Match result in assignment\n\tnum70d := Number(99)\n\tresult70 := match num70d {\n\t\tint {\n\t\t\tnum70d * 2 // 198\n\t\t}\n\t\tPoint {\n\t\t\t-1\n\t\t}\n\t}\n\tprint_int(result70) // 198\n\n\t// 70.5 Match on Point with result assignment\n\tnum70e := Number(Point{\n\t\tx: 3\n\t\ty: 4\n\t})\n\tresult70e := match num70e {\n\t\tint {\n\t\t\t-1\n\t\t}\n\t\tPoint {\n\t\t\tnum70e.x * num70e.y // 12\n\t\t}\n\t}\n\tprint_int(result70e) // 12\n\n\t// ==================== 71. NESTED SMARTCAST ====================\n\tprint_str('--- 71. Nested smartcast ---')\n\n\t// Tests nested smartcasting where outer match smartcasts to a variant\n\t// that is itself a sum type, then inner if-is checks that variant.\n\t// This requires the transformer to apply outer smartcasts to inner tag checks.\n\n\t// 71.1 Nested smartcast: match outer, if-is inner (int variant)\n\tnested1 := NestedOuter(Number(42))\n\tmatch nested1 {\n\t\tNumber {\n\t\t\t// nested1 is now smartcasted to Number\n\t\t\t// Number is itself a sum type (int | Point)\n\t\t\tif nested1 is int {\n\t\t\t\tprint_int(nested1) // 42 (nested smartcast to int)\n\t\t\t} else {\n\t\t\t\tprint_int(-1)\n\t\t\t}\n\t\t}\n\t\tRectangle {\n\t\t\tprint_int(-1)\n\t\t}\n\t}\n\n\t// 71.2 Nested smartcast: match outer, if-is inner (Point variant)\n\tnested2 := NestedOuter(Number(Point{\n\t\tx: 7\n\t\ty: 8\n\t}))\n\tmatch nested2 {\n\t\tNumber {\n\t\t\t// nested2 is smartcasted to Number\n\t\t\tif nested2 is Point {\n\t\t\t\tprint_int(nested2.x) // 7 (nested smartcast to Point)\n\t\t\t\tprint_int(nested2.y) // 8\n\t\t\t} else {\n\t\t\t\tprint_int(-1)\n\t\t\t}\n\t\t}\n\t\tRectangle {\n\t\t\tprint_int(-1)\n\t\t}\n\t}\n\n\t// 71.3 Nested smartcast: negative test - inner type doesn't match\n\tnested3 := NestedOuter(Number(100))\n\tmatch nested3 {\n\t\tNumber {\n\t\t\tif nested3 is Point {\n\t\t\t\tprint_int(-1) // Should not reach\n\t\t\t} else {\n\t\t\t\tprint_int(200) // 200 (nested3 is int, not Point)\n\t\t\t}\n\t\t}\n\t\tRectangle {\n\t\t\tprint_int(-1)\n\t\t}\n\t}\n\n\t// 71.4 Nested smartcast with computation\n\tnested4 := NestedOuter(Number(Point{\n\t\tx: 5\n\t\ty: 6\n\t}))\n\tmatch nested4 {\n\t\tNumber {\n\t\t\tif nested4 is Point {\n\t\t\t\tsum71 := nested4.x + nested4.y\n\t\t\t\tprint_int(sum71) // 11\n\t\t\t}\n\t\t}\n\t\tRectangle {\n\t\t\tprint_int(-1)\n\t\t}\n\t}\n\n\t// ==================== 72. ARRAY LITERAL TYPE INFERENCE ====================\n\tprint_str('--- 72. Array literal type inference ---')\n\n\t// Test array literal with cast expression as first element\n\t// The element type should be inferred from the cast type (u8), not default to int\n\tmut buf72 := [u8(`0`), `1`, `2`]\n\tprint_int(buf72.len) // 3\n\tprint_int(buf72[0]) // 48 (ASCII for '0')\n\tprint_int(buf72[1]) // 49 (ASCII for '1')\n\tprint_int(buf72[2]) // 50 (ASCII for '2')\n\n\t// SKIP: bytestr() crashes on native backend\n\t// result72 := buf72.bytestr()\n\t// print_str(result72) // 012\n\n\t// Test string comparison\n\ts72a := 'hello'\n\ts72b := 'hello'\n\ts72c := 'world'\n\tif s72a == s72b {\n\t\tprint_int(1) // 1 (strings are equal)\n\t} else {\n\t\tprint_int(0)\n\t}\n\tif s72a != s72c {\n\t\tprint_int(2) // 2 (strings are different)\n\t} else {\n\t\tprint_int(0)\n\t}\n\n\t// ==================== 73. ARRAY INDEX METHOD ====================\n\tprint_str('--- 73. Array index method ---')\n\n\t// Test array index method on string arrays\n\tmonths73 := ['January', 'February', 'March', 'April', 'May', 'June']\n\tidx73a := months73.index('March')\n\tprint_int(idx73a) // 2\n\n\tidx73b := months73.index('June')\n\tprint_int(idx73b) // 5\n\n\tidx73c := months73.index('NotFound')\n\tprint_int(idx73c) // -1\n\n\t// Test array index on int arrays\n\tnums73 := [10, 20, 30, 40, 50]\n\tidx73d := nums73.index(30)\n\tprint_int(idx73d) // 2\n\n\tidx73e := nums73.index(99)\n\tprint_int(idx73e) // -1\n\n\t// ==================== 74. MATCH RETURN DIFFERENT ENUM TYPE ====================\n\tprint_str('--- 74. Match return different enum type ---')\n\n\t// Test that match conditions use the correct enum type, not the return type\n\t// This tests the fix for: fn (op Operator) get_binding_power() BindingPower\n\t// where match op { .plus { .low } } should use Operator for .plus, BindingPower for .low\n\top74a := Operator.plus\n\tbp74a := op74a.get_binding_power()\n\tprint_int(int(bp74a)) // 1 (BindingPower.low)\n\n\top74b := Operator.mul\n\tbp74b := op74b.get_binding_power()\n\tprint_int(int(bp74b)) // 2 (BindingPower.medium)\n\n\top74c := Operator.minus\n\tbp74c := op74c.get_binding_power()\n\tprint_int(int(bp74c)) // 1 (BindingPower.low, same as plus)\n\n\top74d := Operator.div\n\tbp74d := op74d.get_binding_power()\n\tprint_int(int(bp74d)) // 2 (BindingPower.medium, same as mul)\n\n\t// ==================== 75. GOTO STATEMENT ====================\n\tprint_str('--- 75. Goto statement ---')\n\n\t// Test goto inside unsafe block\n\tmut counter75 := 0\n\tmut iterations75 := 0\n\tstart75:\n\tcounter75++\n\titerations75++\n\tif counter75 < 3 {\n\t\tunsafe {\n\t\t\tgoto start75\n\t\t}\n\t}\n\tprint_int(iterations75) // 3 - should loop 3 times\n\n\t// Test goto skipping code\n\tmut skipped75 := false\n\tunsafe {\n\t\tgoto skip75\n\t}\n\tskipped75 = true // This should be skipped\n\tskip75:\n\tif skipped75 {\n\t\tprint_int(0) // Should not print this\n\t} else {\n\t\tprint_int(1) // 1 - code was skipped\n\t}\n\n\t// ==================== 76. ARRAY PUSH IN MAP ITERATION ====================\n\tprint_str('--- 76. Array push in map iteration ---')\n\n\t// Test array << struct_init inside for-in-map loop\n\t// This previously caused double transformation of ArrayInitExpr\n\tmut errors76 := []Error76{}\n\tmut users76 := map[int]bool{}\n\tusers76[1] = true\n\tusers76[2] = true\n\tusers76[3] = true\n\tfor user_id, _ in users76 {\n\t\tif user_id > 1 {\n\t\t\terrors76 << Error76{\n\t\t\t\tmsg:    'user'\n\t\t\t\tval_id: user_id\n\t\t\t}\n\t\t}\n\t}\n\tprint_int(errors76.len) // 2 - two errors added\n\n\t// Test map.delete() and map.clear()\n\tmut m76 := map[int]bool{}\n\tm76[10] = true\n\tm76[20] = true\n\tm76[30] = true\n\tprint_int(m76.len) // 3\n\t// SKIP: map.delete() crashes on native backend\n\t// m76.delete(20)\n\t// print_int(m76.len) // 2\n\t// m76.clear()\n\t// print_int(m76.len) // 0\n\n\t// ==================== 77. SMARTCAST SUM TYPE ARGUMENT ====================\n\tprint_str('--- 77. Smartcast sum type argument ---')\n\n\t// Test that smartcasted variable inside match branch can be passed\n\t// to a function expecting the original sum type\n\t// This tests the fix for: b.stmt(stmt) where stmt is smartcast to TypeDecl inside match\n\tnum77a := Number(42)\n\tmatch num77a {\n\t\tint {\n\t\t\t// num77a is smartcast to int here, but process_number expects Number\n\t\t\tresult77a := process_number(num77a)\n\t\t\tprint_int(result77a) // 42\n\t\t}\n\t\telse {}\n\t}\n\n\tnum77b := Number(Point{\n\t\tx: 10\n\t\ty: 20\n\t})\n\tmatch num77b {\n\t\tPoint {\n\t\t\t// num77b is smartcast to Point here, but process_number expects Number\n\t\t\tresult77b := process_number(num77b)\n\t\t\tprint_int(result77b) // 30 (10 + 20)\n\t\t}\n\t\telse {}\n\t}\n\n\t// Test if-is pattern with sum type argument\n\tnum77c := Number(100)\n\tif num77c is int {\n\t\t// num77c is smartcast to int, pass to function expecting Number\n\t\tresult77c := process_number(num77c)\n\t\tprint_int(result77c) // 100\n\t}\n\n\t// ==================== 78. MAP ACCESS WITH MUT PARAMETER ====================\n\tprint_str('--- 78. Map access with mut parameter ---')\n\n\t// SKIP: map with mut parameter + recursive function crashes on native backend\n\t// mut visited78 := map[int]bool{}\n\t// succs78 := [1, 2]\n\t// count78 := dfs_mark_visited(mut visited78, 0, succs78)\n\t// print_int(count78) // 3 - visited nodes 0, 1, 2\n\t// if visited78[0] { print_int(1) } else { print_int(0) }\n\n\t// Test string map if-guard\n\tmut aliases78 := map[string]string{}\n\taliases78['Foo'] = 'Bar'\n\tresult78a := resolve_type_alias(aliases78, 'Foo')\n\tprint_str(result78a) // Bar (found in map)\n\tresult78b := resolve_type_alias(aliases78, 'Baz')\n\tprint_str(result78b) // Baz (not found, returns default)\n\n\t// Test 79: else-if chain smartcast\n\t// Tests that smartcast from earlier branches doesn't leak into later else-if branches\n\tprint_str('Test 79: else-if chain smartcast')\n\twrapper79a := CallWrapper{\n\t\texpr: OuterExpr{\n\t\t\tlhs: InnerExpr(10)\n\t\t}\n\t}\n\tprint_int(test_elseif_chain_smartcast(wrapper79a)) // 11 (10 + 1)\n\n\twrapper79b := CallWrapper{\n\t\texpr: OuterExpr{\n\t\t\tlhs: InnerExpr(20)\n\t\t}\n\t}\n\tprint_int(test_elseif_chain_smartcast(wrapper79b)) // 22 (20 + 2)\n\n\twrapper79c := CallWrapper{\n\t\texpr: OuterExpr{\n\t\t\tlhs: InnerExpr('hello')\n\t\t}\n\t}\n\tprint_int(test_elseif_chain_smartcast(wrapper79c)) // 5 (len of 'hello')\n\n\twrapper79d := CallWrapper{\n\t\texpr: OuterExpr{\n\t\t\tlhs: InnerExpr(Point{\n\t\t\t\tx: 3\n\t\t\t\ty: 4\n\t\t\t})\n\t\t}\n\t}\n\tprint_int(test_elseif_chain_smartcast(wrapper79d)) // 7 (3 + 4)\n\n\t// ==================== 80. STRING MATCH RETURN ====================\n\t// Tests match expression with string conditions that returns a value\n\tprint_str('--- Test 80: String match return ---')\n\tprint_str(operator_to_name('+')) // __plus\n\tprint_str(operator_to_name('-')) // __minus\n\tprint_str(operator_to_name('*')) // __mul\n\tprint_str(operator_to_name('?')) // ? (unknown operator)\n\n\t// ==================== 81. NESTED SUMTYPE METHOD CALL SMARTCAST ====================\n\t// Tests that when matching outer sum type (Outer = Inner | bool) against a nested sum type variant (Inner),\n\t// method calls receive the smartcast (Inner) not the original variable (Outer)\n\tprint_str('--- Test 81: Nested sumtype method call smartcast ---')\n\tproc := Processor{\n\t\tname: 'test'\n\t}\n\t// Test 1: Int in Inner in Outer\n\touter81a := OuterSumType(InnerSumType(42))\n\tprint_int(proc.process_outer(outer81a)) // 42\n\n\t// Test 2: String in Inner in Outer\n\touter81b := OuterSumType(InnerSumType('hello'))\n\tprint_int(proc.process_outer(outer81b)) // 5 (len of 'hello')\n\n\t// Test 3: Bool in Outer (not Inner)\n\touter81c := OuterSumType(true)\n\tprint_int(proc.process_outer(outer81c)) // 1\n\n\t// ==================== 82. RECURSIVE SUMTYPE FIELD ACCESS ====================\n\t// Tests recursive function with sumtype parameter accessing fields of smartcast variant\n\tprint_str('--- Test 82: Recursive sumtype field access ---')\n\t// SKIP: Recursive sumtype with heap allocation crashes on native backend\n\t// test82_expr := TestExpr(TestInfixExpr{...})\n\t// print_int(eval_recursive(test82_expr)) // 3 (1 + 2)\n\t// print_int(eval_recursive(test82_nested)) // 6 (1 + 2 + 3)\n\t// print_int(test_gen.try_eval_int(test82_expr) or { -1 }) // 3\n\t// print_int(test_gen.try_eval_int(test82_nested) or { -1 }) // 6\n\n\t// ==================== 83. NESTED IF-IS SMARTCAST WITH FUNCTION CALL ====================\n\t// Tests the pattern from cleanc.v:2015-2046 where:\n\t//   if call.lhs is SelectorExpr {\n\t//     if call.lhs.lhs is SelectorExpr {\n\t//       result := fn_expecting_sumtype(call.lhs.lhs)  // must wrap or not extract\n\t//     }\n\t//   }\n\tprint_str('--- Test 83: Nested if-is smartcast with fn call ---')\n\t// SKIP: nested sumtype smartcast crashes on native backend\n\n\t// ==================== 84. RETURN IF EXPRESSION ====================\n\t// Tests return if expression transformation\n\tprint_str('--- Test 84: Return if expression ---')\n\ttest_return_if_expr()\n\n\t// ==================== 85. COMBINED && SMARTCAST ====================\n\t// Tests combined && conditions with nested is checks: if a is T && a.field is U { a.field.inner }\n\tprint_str('--- Test 85: Combined && smartcast ---')\n\t// SKIP: crashes with nil string on native backend\n\t// test_combined_smartcast()\n\n\t// ==================== 86. IF-GUARD ARRAY ACCESS ====================\n\t// Tests if-guard with array index expressions (bounds checking)\n\tprint_str('--- Test 86: If-guard array access ---')\n\ttest_if_guard_array_access()\n\n\t// ==================== 87. OPTIONAL POINTER RETURN TYPE ====================\n\t// Tests functions returning ?&Struct (option wrapping a pointer)\n\tprint_str('--- Test 87: Optional pointer return ---')\n\t// SKIP: ?&Struct if-guard doesn't properly deref pointer on native backend\n\t// test_optional_pointer_return()\n\n\t// ==================== 88. METHOD CALL ON VARIABLE NAMED 'v' ====================\n\t// Tests method calls on loop variable named 'v' (module/variable disambiguation)\n\tprint_str('--- Test 88: Method on v variable ---')\n\ttest_method_on_v_variable()\n\n\tprint_str('--- Test 89: Sumtype match return ---')\n\t// SKIP: crashes on native backend\n\t// test_sumtype_match_return()\n\n\tprint_str('--- Test 90: Map or-block with rlock ---')\n\t// SKIP: crashes on native backend\n\t// test_map_or_rlock()\n\n\tprint_str('--- Test 91: Map or-block with array value ---')\n\ttest_map_or_array_value()\n\n\tprint_str('--- Test 92: Flag enum set/clear ---')\n\ttest_flag_enum_set_clear()\n\n\tprint_str('--- Test 93: Interface method dispatch via fn-pointer ---')\n\t// SKIP: crashes on native backend\n\t// test_interface_fn_pointer_dispatch()\n\n\tprint_str('--- Test 94: Sumtype .type_name() ---')\n\t// SKIP: crashes on native backend\n\t// test_sumtype_type_name()\n\n\tprint_str('--- Test 95: Method call resolution ---')\n\t// SKIP: compound assignment on struct fields produces wrong values on native backend\n\t// test_method_call_resolution()\n\n\tprint_str('--- Test 96: Sumtype variant inference ---')\n\ttest_sumtype_variant_inference()\n\n\tprint_str('--- Test 97: Array type resolution ---')\n\ttest_array_type_resolution()\n\n\tprint_str('--- Test 98: Variadic call lowering ---')\n\t// SKIP: variadic call lowering crashes on native backend\n\t// test_variadic_call_lowering()\n\n\tprint_str('--- Test 99: Array init with index ---')\n\ttest_array_init_with_index()\n\n\tprint_str('=== All tests completed ===')\n}\n"
  },
  {
    "path": "cmd/v2/test_all.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\n\nscript_dir=\"$(CDPATH= cd -- \"$(dirname -- \"$0\")\" && pwd)\"\nrepo_root=\"$(CDPATH= cd -- \"${script_dir}/../..\" && pwd)\"\n\ncd \"${script_dir}\"\n\nv1_compiler=\"${V:-${repo_root}/v}\"\nif [ ! -x \"${v1_compiler}\" ]; then\n  echo \"FAIL: v1 compiler not found: ${v1_compiler}\"\n  exit 1\nfi\n\n# V1's formatter may clobber v2 source files during rebuild.\n# Back up the entire v2 tree and restore after each V1 build.\nV2_SRC=\"../../vlib/v2\"\nV2_BAK=\"/tmp/v2_src_bak_test_all\"\n\nbackup_v2_src() {\n  rm -rf \"$V2_BAK\"\n  cp -R \"$V2_SRC\" \"$V2_BAK\"\n}\n\nrestore_v2_src() {\n  rsync -a --delete \"$V2_BAK/\" \"$V2_SRC/\"\n}\n\nKNOWN_FAILURES=0\n\necho \"=== 1/14: ARM64 self-host hello world ===\"\nbackup_v2_src\n\"${v1_compiler}\" -skip-unused -cc cc -o v2 v2.v\nrestore_v2_src\n./v2 -backend arm64 -gc none -nocache -o v3 v2.v\n./v3 -backend arm64 -o hello_arm hello.v\n./hello_arm\n\necho \"\"\necho \"=== 2/14: ARM64 self-host chain (v2->v3->v4->v5->v6) ===\"\necho \"  Building v3 from v2...\"\n./v2 -nocache -gc none -backend arm64 -o v3_chain v2.v\necho \"  Building v4 from v3...\"\n./v3_chain -nocache -gc none -backend arm64 -o v4_chain v2.v\necho \"  Building v5 from v4...\"\n./v4_chain -nocache -gc none -backend arm64 -o v5_chain v2.v\necho \"  Building v6 from v5...\"\n./v5_chain -nocache -gc none -backend arm64 -o v6_chain v2.v\nV5_SIZE=$(wc -c < v5_chain)\nV6_SIZE=$(wc -c < v6_chain)\nif [ \"$V5_SIZE\" -eq \"$V6_SIZE\" ]; then\n  echo \"  v5=v6 ($V5_SIZE bytes) — chain converged\"\nelse\n  echo \"  FAIL: v5 ($V5_SIZE) != v6 ($V6_SIZE)\"\n  exit 1\nfi\nrm -f v3_chain v4_chain v5_chain v6_chain\n\necho \"\"\necho \"=== 3/14: Self-host test ===\"\nbash test_v2_self.sh\n\necho \"\"\necho \"=== 4/14: Builtin test files (cleanc) ===\"\nrm -rf /tmp/v2_cleanc_obj_cache\n./v2 ../../vlib/builtin/array_test.v\n./v2 ../../vlib/builtin/string_test.v\n./v2 ../../vlib/builtin/map_test.v\n\necho \"\"\necho \"=== 5/14: Builtin test files (arm64) ===\"\n./v2 -backend arm64 ../../vlib/builtin/array_test.v\n./v2 -backend arm64 ../../vlib/builtin/string_test.v\n./v2 -backend arm64 ../../vlib/builtin/map_test.v\n\necho \"\"\necho \"=== 6/14: Math test ===\"\n./v2 ../../vlib/math/math_test.v\n\necho \"\"\necho \"=== 7/14: Math test (arm64) ===\"\n./v2 -backend arm64 ../../vlib/math/math_test.v\n\necho \"\"\necho \"=== 8/14: Sumtype tests ===\"\n./v2 test_sumtype.v\n./v2 test_sumtype2.v\n./v2 test_sumtype3.v\n./v2 test_sumtype4.v\n./v2 test_sumtype_pos.v\n./v2 test_sumtype_data.v\n./v2 test_sumtype_ifexpr.v\n./v2 test_sumtype_nested.v\n./v2 test_sumtype_many.v\n./v2 test_sumtype_global.v\n\necho \"\"\necho \"=== 9/14: Sumtype tests (arm64) ===\"\n./v2 -backend arm64 test_sumtype.v\n./v2 -backend arm64 test_sumtype2.v\n./v2 -backend arm64 test_sumtype3.v\n./v2 -backend arm64 test_sumtype4.v\n./v2 -backend arm64 test_sumtype_pos.v\n./v2 -backend arm64 test_sumtype_data.v\n./v2 -backend arm64 test_sumtype_ifexpr.v\n./v2 -backend arm64 test_sumtype_nested.v\n./v2 -backend arm64 test_sumtype_many.v\n./v2 -backend arm64 test_sumtype_global.v\n\necho \"\"\necho \"=== 10/14: SSA backends test (arm64) ===\"\n\"${v1_compiler}\" -gc none run test_ssa_backends.v arm64\n\necho \"\"\necho \"=== 11/14: SSA backends test (cleanc) ===\"\n\"${v1_compiler}\" -gc none run test_ssa_backends.v cleanc\n\necho \"\"\necho \"=== 12/14: Transformer unit tests ===\"\n\"${v1_compiler}\" ../../vlib/v2/transformer/transformer_test.v\n\necho \"\"\necho \"=== 13/14: Transformer integration test ===\"\n\"${v1_compiler}\" ../../vlib/v2/transformer/transformer_v2_darwin_test.v\n\necho \"\"\necho \"=== 14/14: Cleanc runtime tests ===\"\n\"${v1_compiler}\" -gc none run ../../vlib/v2/gen/cleanc/tests/run_tests.v\n\necho \"\"\nif [ \"$KNOWN_FAILURES\" -gt 0 ]; then\n  echo \"=== ALL TESTS PASSED ($KNOWN_FAILURES known failures skipped) ===\"\nelse\n  echo \"=== ALL TESTS PASSED ===\"\nfi\n"
  },
  {
    "path": "cmd/v2/test_ssa_backends.v",
    "content": "// Copyright (c) 2026 Alexander Medvednikov. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nmodule main\n\nimport os\nimport time\n\nfn main() {\n\tt0 := time.now()\n\n\t// Build v2 compiler\n\tprintln('[*] Building v2...')\n\tvroot := os.dir(@VEXE)\n\tv2_source := os.join_path(vroot, 'cmd', 'v2', 'v2.v')\n\tv2_binary := os.join_path(vroot, 'cmd', 'v2', 'v2')\n\tbuild_res := os.execute('${@VEXE} -gc none ${v2_source} -o ${v2_binary}')\n\tif build_res.exit_code != 0 {\n\t\teprintln('Error: Failed to build v2')\n\t\teprintln(build_res.output)\n\t\treturn\n\t}\n\n\t// Determine backends from command line args.\n\t// If none are provided, run the default backend set.\n\tmut backends := []string{}\n\tif os.args.contains('cleanc') {\n\t\tbackends << 'cleanc'\n\t}\n\tif os.args.contains('c') {\n\t\tbackends << 'c'\n\t}\n\tif os.args.contains('arm64') {\n\t\tbackends << 'arm64'\n\t}\n\tif os.args.contains('x64') {\n\t\tbackends << 'x64'\n\t}\n\tif backends.len == 0 {\n\t\tbackends = ['cleanc', 'c', 'arm64']\n\t}\n\n\t// Parse test file from args or default to test.v\n\t// Support: ./test_ssa_backends arm64 path/to/file.v\n\tmut input_file := 'test.v'\n\tfor arg in os.args {\n\t\tif arg.ends_with('.v') && arg != @FILE {\n\t\t\tinput_file = arg\n\t\t\tbreak\n\t\t}\n\t}\n\tif !os.exists(input_file) {\n\t\teprintln('Error: ${input_file} not found')\n\t\treturn\n\t}\n\n\t// Derive output binary name from input file\n\tbase_name := os.file_name(input_file).replace('.v', '')\n\tref_output_path := './.${base_name}_ref.out.tmp'\n\tgen_output_path := './.${base_name}_gen.out.tmp'\n\n\t// Get expected output: use .out file if --skip-builtin, otherwise run reference compiler\n\tmut expected_out := ''\n\tout_file := input_file.replace('.v', '.out')\n\tif os.args.contains('--skip-builtin') && os.exists(out_file) {\n\t\tprintln('[*] Using expected output from ${out_file}')\n\t\texpected_out = os.read_file(out_file) or { '' }.trim_space().replace('\\r\\n', '\\n')\n\t} else {\n\t\t// Run Reference (v run test.v)\n\t\tprintln('[*] Running reference: ${@VEXE} -enable-globals run ${input_file}...')\n\t\tos.rm(ref_output_path) or {}\n\t\tref_cmd := '${@VEXE} -gc none -n -w -enable-globals run ${input_file} > ${ref_output_path} 2>&1'\n\t\tref_res := os.execute(ref_cmd)\n\t\tref_out := os.read_file(ref_output_path) or { '' }\n\t\tos.rm(ref_output_path) or {}\n\t\tif ref_res.exit_code != 0 {\n\t\t\teprintln('Error: Reference run failed')\n\t\t\teprintln(ref_out)\n\t\t\treturn\n\t\t}\n\t\t// Normalize newlines\n\t\texpected_out = ref_out.trim_space().replace('\\r\\n', '\\n')\n\t}\n\n\tmut had_failures := false\n\tfor backend in backends {\n\t\tbackend_t0 := time.now()\n\n\t\t// Run v2 with selected backend\n\t\tprintln('[*] Running v2 -backend ${backend} ${input_file}...')\n\t\tmut backend_flags := '-gc none -backend ${backend}'\n\t\tif backend == 'cleanc' {\n\t\t\t// cleanc needs full per-run codegen for this suite right now.\n\t\t\tbackend_flags += ' -nomarkused -nocache'\n\t\t}\n\t\tif os.args.contains('--skip-builtin') && !backend_flags.contains('--skip-builtin') {\n\t\t\tbackend_flags += ' --skip-builtin'\n\t\t}\n\t\tv2_cmd := '${v2_binary} ${backend_flags} ${input_file} -o ${base_name}'\n\t\tv2_res := os.execute(v2_cmd)\n\t\tif v2_res.exit_code != 0 {\n\t\t\teprintln('Error: v2 compilation failed for backend ${backend}')\n\t\t\teprintln(v2_res.output)\n\t\t\thad_failures = true\n\t\t\tcontinue\n\t\t}\n\t\tprintln(v2_res.output)\n\t\tprintln('compilation took ${time.since(backend_t0)}')\n\n\t\t// Save the v2-produced binary before running another backend (which would overwrite it)\n\t\tsaved_binary := './${base_name}_${backend}_v2'\n\t\tos.rm(saved_binary) or {}\n\t\tif os.user_os() == 'windows' {\n\t\t\tos.rm('${saved_binary}.exe') or {}\n\t\t}\n\t\tos.cp('./${base_name}', saved_binary) or {\n\t\t\teprintln('Error: Failed to save v2 binary for backend ${backend}')\n\t\t\thad_failures = true\n\t\t\tcontinue\n\t\t}\n\n\t\t// Run generated binary\n\t\tprintln('[*] Running generated binary (${backend})...')\n\t\tmut cmd := saved_binary\n\t\tif os.user_os() == 'windows' {\n\t\t\tcmd = '${saved_binary}.exe'\n\t\t}\n\t\tos.rm(gen_output_path) or {}\n\t\tgen_cmd := '${cmd} > ${gen_output_path} 2>&1'\n\t\tgen_res := os.execute(gen_cmd)\n\t\tgen_out := os.read_file(gen_output_path) or { '' }\n\t\tos.rm(gen_output_path) or {}\n\t\tif gen_res.exit_code != 0 {\n\t\t\tif gen_res.exit_code == 142 || gen_res.exit_code == 14 {\n\t\t\t\teprintln('Error: Execution timed out (infinite loop detected) for backend ${backend}')\n\t\t\t\thad_failures = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tprintln('Warning: Binary exited with code ${gen_res.exit_code}')\n\t\t}\n\n\t\t// Strip terminal control characters that script command may prepend\n\t\tmut cleaned := gen_out.replace('\\r\\n', '\\n').replace('\\x04', '').replace('\\x08',\n\t\t\t'')\n\t\t// Remove \"^D\" literal string that macOS script may add\n\t\tif cleaned.starts_with('^D') {\n\t\t\tcleaned = cleaned[2..]\n\t\t}\n\t\tactual_out := cleaned.trim_space()\n\n\t\t// Compare\n\t\tif expected_out == actual_out {\n\t\t\tprintln('\\n[SUCCESS] Backend ${backend}: outputs match!')\n\t\t\tcontinue\n\t\t}\n\n\t\thad_failures = true\n\t\tprintln('\\n[FAILURE] Backend ${backend}: outputs differ')\n\t\texpected_lines := expected_out.split('\\n')\n\t\tactual_lines := actual_out.split('\\n')\n\n\t\t// Find first differing line\n\t\tmut first_diff := -1\n\t\tmax_lines := if expected_lines.len > actual_lines.len {\n\t\t\texpected_lines.len\n\t\t} else {\n\t\t\tactual_lines.len\n\t\t}\n\t\tfor i in 0 .. max_lines {\n\t\t\texp := if i < expected_lines.len { expected_lines[i] } else { '<missing>' }\n\t\t\tact := if i < actual_lines.len { actual_lines[i] } else { '<missing>' }\n\t\t\tif exp != act {\n\t\t\t\tfirst_diff = i\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif first_diff >= 0 {\n\t\t\tcontext := 2\n\t\t\tstart := if first_diff > context { first_diff - context } else { 0 }\n\t\t\tend := if first_diff + context + 1 < max_lines {\n\t\t\t\tfirst_diff + context + 1\n\t\t\t} else {\n\t\t\t\tmax_lines\n\t\t\t}\n\n\t\t\tprintln('\\nExpected (reference compiler):')\n\t\t\tfor i in start .. end {\n\t\t\t\tline := if i < expected_lines.len { expected_lines[i] } else { '<missing>' }\n\t\t\t\tprintln('${i + 1}: ${line}')\n\t\t\t}\n\n\t\t\tprintln('\\nGot (v2 ${backend}):')\n\t\t\tfor i in start .. end {\n\t\t\t\tline := if i < actual_lines.len { actual_lines[i] } else { '<missing>' }\n\t\t\t\tprintln('${i + 1}: ${line}')\n\t\t\t}\n\t\t}\n\t}\n\n\tif had_failures {\n\t\tprintln('\\n[FAILURE] One or more backends failed')\n\t} else {\n\t\tprintln('\\n[SUCCESS] All requested backends passed')\n\t}\n\tprintln('total time ${time.since(t0)}')\n}\n"
  },
  {
    "path": "cmd/v2/test_sumtype.v",
    "content": "type Animal = Cat | Dog\n\nstruct Cat {\n\tname string\n}\n\nstruct Dog {\n\tname string\n\tage  int\n}\n\nfn make_animal() Animal {\n\treturn Animal(Cat{\n\t\tname: 'whiskers'\n\t})\n}\n\nfn main() {\n\ta := make_animal()\n\tmatch a {\n\t\tCat {\n\t\t\tprintln(a.name)\n\t\t}\n\t\tDog {\n\t\t\tprintln(a.name)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/v2/test_sumtype2.v",
    "content": "struct Cat {\n\tname string\n}\n\nstruct Dog {\n\tname string\n\tage  int\n}\n\nstruct Bird {\n\tname    string\n\tcan_fly bool\n}\n\ntype Animal = Bird | Cat | Dog\n\nfn make_cat() Animal {\n\treturn Animal(Cat{\n\t\tname: 'whiskers'\n\t})\n}\n\nfn make_bird() Animal {\n\treturn Animal(Bird{\n\t\tname:    'tweety'\n\t\tcan_fly: true\n\t})\n}\n\nfn indirect() Animal {\n\ta := make_cat()\n\treturn a\n}\n\nfn get_name(a Animal) string {\n\tmatch a {\n\t\tCat { return a.name }\n\t\tDog { return a.name }\n\t\tBird { return a.name }\n\t}\n}\n\nfn main() {\n\ta := make_cat()\n\tb := make_bird()\n\tc := indirect()\n\tprintln(get_name(a))\n\tprintln(get_name(b))\n\tprintln(get_name(c))\n}\n"
  },
  {
    "path": "cmd/v2/test_sumtype3.v",
    "content": "struct Cat {\n\tname string\n}\n\nstruct Dog {\n\tname string\n\tage  int\n}\n\nstruct Bird {\n\tname    string\n\tcan_fly bool\n}\n\ntype Animal = Bird | Cat | Dog\n\nfn make_conditional(which int) Animal {\n\tresult := if which == 0 {\n\t\tAnimal(Cat{\n\t\t\tname: 'whiskers'\n\t\t})\n\t} else {\n\t\tAnimal(Bird{\n\t\t\tname:    'tweety'\n\t\t\tcan_fly: true\n\t\t})\n\t}\n\treturn result\n}\n\nfn get_name(a Animal) string {\n\tmatch a {\n\t\tCat { return a.name }\n\t\tDog { return a.name }\n\t\tBird { return a.name }\n\t}\n}\n\nfn main() {\n\ta := make_conditional(0)\n\tb := make_conditional(1)\n\tprintln(get_name(a))\n\tprintln(get_name(b))\n}\n"
  },
  {
    "path": "cmd/v2/test_sumtype4.v",
    "content": "struct Ident {\n\tname string\n\tline int\n\tcol  int\n}\n\nstruct Literal {\n\tvalue string\n}\n\ntype Expr = Ident | Literal\n\nfn make_ident() Ident {\n\treturn Ident{\n\t\tname: 'foo'\n\t\tline: 42\n\t\tcol:  10\n\t}\n}\n\nfn wrap_expr() Expr {\n\ti := make_ident()\n\treturn i\n}\n\nfn main() {\n\te := wrap_expr()\n\tmatch e {\n\t\tIdent {\n\t\t\tprintln(e.name)\n\t\t\tprintln(e.line)\n\t\t\tprintln(e.col)\n\t\t}\n\t\tLiteral {\n\t\t\tprintln(e.value)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/v2/test_sumtype_data.v",
    "content": "struct Pos {\n\tx int\n\ty int\n}\n\nstruct Ident {\n\tpos  Pos\n\tname string\n}\n\nstruct Lit {\n\tpos Pos\n\tval int\n}\n\ntype Expr = Ident | Lit\n\nfn (e Expr) get_pos() Pos {\n\treturn match e {\n\t\tIdent { e.pos }\n\t\tLit { e.pos }\n\t}\n}\n\nfn make_ident() Expr {\n\treturn Expr(Ident{\n\t\tpos:  Pos{\n\t\t\tx: 10\n\t\t\ty: 20\n\t\t}\n\t\tname: 'hello'\n\t})\n}\n\nfn main() {\n\te := make_ident()\n\tp := e.get_pos()\n\tprintln(p.x.str())\n\tprintln(p.y.str())\n}\n"
  },
  {
    "path": "cmd/v2/test_sumtype_global.v",
    "content": "struct Pos {\n\tx int\n\ty int\n}\n\nstruct Ident {\n\tpos  Pos\n\tname string\n}\n\nstruct EmptyExpr {\n\tdummy u8\n}\n\ntype Expr = EmptyExpr | Ident\n\nconst empty_expr = Expr(EmptyExpr{})\n\nfn (e Expr) get_pos() Pos {\n\treturn match e {\n\t\tIdent { e.pos }\n\t\tEmptyExpr { Pos{} }\n\t}\n}\n\nfn parse_expr() Expr {\n\treturn Expr(Ident{\n\t\tpos:  Pos{\n\t\t\tx: 42\n\t\t\ty: 99\n\t\t}\n\t\tname: 'macos'\n\t})\n}\n\nstruct Parser {\nmut:\n\ttok      int\n\tcomptime bool\n}\n\nfn (mut p Parser) expr_or_type() Expr {\n\treturn Expr(Ident{\n\t\tpos:  Pos{\n\t\t\tx: 77\n\t\t\ty: 88\n\t\t}\n\t\tname: 'linux'\n\t})\n}\n\nfn (mut p Parser) if_expr(is_comptime bool) {\n\t// Exact pattern from the real parser\n\tmut cond := if p.tok == 42 {\n\t\tempty_expr // global constant\n\t} else {\n\t\tif is_comptime { p.expr_or_type() } else { p.expr_or_type() }\n\t}\n\t// This line is what crashes in v3\n\tguard_pos := cond.get_pos()\n\tprintln(guard_pos.x.str())\n\tprintln(guard_pos.y.str())\n}\n\nfn main() {\n\tmut parser := Parser{\n\t\ttok:      99\n\t\tcomptime: true\n\t}\n\tparser.if_expr(true) // should print 77, 88\n}\n"
  },
  {
    "path": "cmd/v2/test_sumtype_ifexpr.v",
    "content": "struct Pos {\n\tx int\n\ty int\n}\n\nstruct Ident {\n\tpos  Pos\n\tname string\n}\n\nstruct EmptyExpr {\n\tdummy u8\n}\n\ntype Expr = EmptyExpr | Ident\n\nfn (e Expr) get_pos() Pos {\n\treturn match e {\n\t\tIdent { e.pos }\n\t\tEmptyExpr { Pos{} }\n\t}\n}\n\nfn parse_expr() Expr {\n\treturn Expr(Ident{\n\t\tpos:  Pos{\n\t\t\tx: 42\n\t\t\ty: 99\n\t\t}\n\t\tname: 'macos'\n\t})\n}\n\nfn test_if_expr(is_lcbr bool) {\n\tmut cond := if is_lcbr {\n\t\tExpr(EmptyExpr{})\n\t} else {\n\t\tparse_expr()\n\t}\n\tp := cond.get_pos()\n\tprintln(p.x.str())\n\tprintln(p.y.str())\n}\n\nfn main() {\n\ttest_if_expr(false) // should print 42, 99\n\ttest_if_expr(true) // should print 0, 0\n}\n"
  },
  {
    "path": "cmd/v2/test_sumtype_many.v",
    "content": "struct Pos {\n\tx int\n\ty int\n}\n\nstruct V0 {\n\tpos Pos\n\ta   int\n}\n\nstruct V1 {\n\tpos Pos\n\tb   int\n}\n\nstruct V2 {\n\tpos Pos\n\tc   int\n}\n\nstruct V3 {\n\tpos Pos\n\td   int\n}\n\nstruct V4 {\n\tpos Pos\n\te   int\n}\n\nstruct V5 {\n\tpos Pos\n\tf   int\n}\n\nstruct V6 {\n\tpos Pos\n\tg   int\n}\n\nstruct V7 {\n\tpos Pos\n\th   int\n}\n\nstruct V8 {\n\tdummy u8\n} // EmptyExpr equivalent (tag 8)\n\nstruct V9 {\n\tpos Pos\n\tj   int\n}\n\nstruct V10 {\n\tpos Pos\n\tk   int\n}\n\nstruct V11 {\n\tpos Pos\n\tl   int\n}\n\nstruct V12 {\n\tpos Pos\n\tm   int\n}\n\nstruct V13 {\n\tpos  Pos\n\tname string\n} // Ident equivalent (tag 13)\n\nstruct V14 {\n\tpos Pos\n\tn   int\n}\n\ntype Expr = V0 | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 | V11 | V12 | V13 | V14\n\nfn (e Expr) get_pos() Pos {\n\treturn match e {\n\t\tV0 { e.pos }\n\t\tV1 { e.pos }\n\t\tV2 { e.pos }\n\t\tV3 { e.pos }\n\t\tV4 { e.pos }\n\t\tV5 { e.pos }\n\t\tV6 { e.pos }\n\t\tV7 { e.pos }\n\t\tV8 { Pos{} }\n\t\tV9 { e.pos }\n\t\tV10 { e.pos }\n\t\tV11 { e.pos }\n\t\tV12 { e.pos }\n\t\tV13 { e.pos }\n\t\tV14 { e.pos }\n\t}\n}\n\nfn make_v13() Expr {\n\treturn Expr(V13{\n\t\tpos:  Pos{\n\t\t\tx: 42\n\t\t\ty: 99\n\t\t}\n\t\tname: 'hello'\n\t})\n}\n\nfn test_it(is_lcbr bool, is_comptime bool) {\n\tmut cond := if is_lcbr {\n\t\tExpr(V8{})\n\t} else {\n\t\tif is_comptime { make_v13() } else { make_v13() }\n\t}\n\tp := cond.get_pos()\n\tprintln(p.x.str())\n\tprintln(p.y.str())\n}\n\nfn main() {\n\tprintln('test with 15 variants, accessing V13 (tag 13):')\n\ttest_it(false, true)\n}\n"
  },
  {
    "path": "cmd/v2/test_sumtype_nested.v",
    "content": "// Test sum type with struct variants (not just primitives)\n// This mirrors the AST's Expr sum type pattern\n\nstruct BasicLit {\n\tkind  int\n\tvalue string\n}\n\nstruct Ident {\n\tname string\n}\n\nstruct CallOrCast {\n\tlhs  Expr\n\texpr Expr\n}\n\ntype Expr = BasicLit | CallOrCast | Ident\n\nfn make_basic_lit(val string) Expr {\n\treturn BasicLit{\n\t\tkind:  1\n\t\tvalue: val\n\t}\n}\n\nfn make_ident(name string) Expr {\n\treturn Ident{\n\t\tname: name\n\t}\n}\n\nfn make_call_or_cast(lhs Expr, expr Expr) Expr {\n\treturn CallOrCast{\n\t\tlhs:  lhs\n\t\texpr: expr\n\t}\n}\n\nfn test_basic_lit() {\n\te := make_basic_lit('42')\n\tif e is BasicLit {\n\t\tassert e.value == '42'\n\t\tassert e.kind == 1\n\t} else {\n\t\tassert false\n\t}\n}\n\nfn test_ident() {\n\te := make_ident('hello')\n\tif e is Ident {\n\t\tassert e.name == 'hello'\n\t} else {\n\t\tassert false\n\t}\n}\n\nfn test_call_or_cast() {\n\tlhs := make_ident('int')\n\targ := make_basic_lit('0')\n\te := make_call_or_cast(lhs, arg)\n\tif e is CallOrCast {\n\t\tif e.lhs is Ident {\n\t\t\tassert e.lhs.name == 'int'\n\t\t} else {\n\t\t\tassert false\n\t\t}\n\t\tif e.expr is BasicLit {\n\t\t\tassert e.expr.value == '0'\n\t\t} else {\n\t\t\tassert false\n\t\t}\n\t} else {\n\t\tassert false\n\t}\n}\n\nfn test_nested_sum_field_access() {\n\t// Create CallOrCast{lhs: Ident(\"int\"), expr: BasicLit(\"0\")}\n\t// This mirrors: __global g_main_argc = int(0)\n\tlhs := Expr(Ident{\n\t\tname: 'int'\n\t})\n\targ := Expr(BasicLit{\n\t\tkind:  1\n\t\tvalue: '0'\n\t})\n\tcoce := CallOrCast{\n\t\tlhs:  lhs\n\t\texpr: arg\n\t}\n\te := Expr(coce)\n\tif e is CallOrCast {\n\t\t// Access the nested Expr fields\n\t\tinner_expr := e.expr\n\t\tif inner_expr is BasicLit {\n\t\t\tassert inner_expr.value == '0'\n\t\t} else {\n\t\t\teprintln('ERROR: inner_expr is not BasicLit')\n\t\t\tassert false\n\t\t}\n\t} else {\n\t\teprintln('ERROR: e is not CallOrCast')\n\t\tassert false\n\t}\n}\n"
  },
  {
    "path": "cmd/v2/test_sumtype_pos.v",
    "content": "type MyUnion = int | string\n\nfn (u MyUnion) tag() int {\n\treturn match u {\n\t\tint { 0 }\n\t\tstring { 1 }\n\t\t// else { -1 }\n\t}\n}\n\nfn make_int_union() MyUnion {\n\treturn MyUnion(42)\n}\n\nfn make_string_union() MyUnion {\n\treturn MyUnion('hello')\n}\n\nfn main() {\n\ta := make_int_union()\n\tt := a.tag()\n\tprintln(t.str())\n\n\tb := make_string_union()\n\tt2 := b.tag()\n\tprintln(t2.str())\n}\n"
  },
  {
    "path": "cmd/v2/test_v2_self.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\n\nscript_dir=\"$(cd -- \"$(dirname -- \"${BASH_SOURCE[0]}\")\" && pwd)\"\nrepo_root=\"$(cd -- \"${script_dir}/../..\" && pwd)\"\n\nv2_source=\"${script_dir}/v2.v\"\nv2_bin=\"${script_dir}/v2\"\nv3_bin=\"${script_dir}/v3\"\nv4_bin=\"${script_dir}/v4\"\nv5_bin=\"${script_dir}/v5\"\n\n# Variable for the backend (originally cleanc)\nbackend=\"cleanc\"\n\npreferred_v1_compiler=\"${HOME}/code/v/v\"\nv1_compiler=\"${V:-${preferred_v1_compiler}}\"\nif [[ ! -x \"${v1_compiler}\" ]]; then\n    v1_compiler=\"${repo_root}/v\"\nfi\nif [[ ! -x \"${v1_compiler}\" ]]; then\n    echo \"FAILURE: v1 compiler not found or not executable: ${v1_compiler}\"\n    exit 1\nfi\n\n# V1's formatter may clobber v2 source files — backup and restore.\nv2_src=\"${repo_root}/vlib/v2\"\nv2_bak=\"/tmp/v2_src_bak_self_test\"\nrm -rf \"${v2_bak}\"\ncp -R \"${v2_src}\" \"${v2_bak}\"\n\n# Build v2 with v1.\nrm -f \"${v2_bin}\" \"${v3_bin}\" \"${v3_bin}.c\" \"${v4_bin}\" \"${v4_bin}.c\" \"${v5_bin}\" \"${v5_bin}.c\"\n\"${v1_compiler}\" -skip-unused -cc cc -o \"${v2_bin}\" \"${v2_source}\"\n\n# Restore v2 sources after V1 build.\nrsync -a --delete \"${v2_bak}/\" \"${v2_src}/\"\n\n# Use clang instead of TCC for v2-compiled C code.\nexport V2CC=\"${V2CC:-cc}\"\n\n# Use v2 to compile itself to v3 (using defined backend).\n\"${v2_bin}\" -gc none -o \"${v3_bin}\" -backend \"${backend}\" \"${v2_source}\"\n\necho \"SUCCESS: v2 successfully compiled itself to v3\"\necho \"v3 binary size: $(ls -lh \"${v3_bin}\" | awk '{print $5}')\"\n\n\"${v3_bin}\" -gc none -o \"${v4_bin}\" -backend \"${backend}\" \"${v2_source}\"\nprintf '\\nV4 compiled\\n\\n'\n\n\"${v4_bin}\" -gc none  -o \"${v5_bin}\" -backend \"${backend}\" \"${v2_source}\"\nprintf '\\nV5 compiled\\n\\n'\n\n# Test that v3 runs and produces expected output.\noutput=\"$(\"${v3_bin}\" 2>&1 || true)\"\nexpected='At least 1 .v file expected'\n\nif echo \"${output}\" | grep -q \"${expected}\"; then\n    echo \"SUCCESS\"\nelse\n    echo \"FAILURE: Expected '${expected}' but got:\"\n    echo \"${output}\"\n    exit 1\nfi\n\necho ''\necho '=== SELF-COMPILATION TEST PASSED ==='\n"
  },
  {
    "path": "cmd/v2/v2.v",
    "content": "// Copyright (c) 2020-2024 Joe Conigliaro. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nmodule main\n\nimport os\nimport v2.pref\nimport v2.builder\n\nfn main() {\n\tcompile_args, runtime_args := split_eval_runtime_args(os.args[1..])\n\n\t// Check for 'ast' subcommand\n\tif compile_args.len > 0 && compile_args[0] == 'ast' {\n\t\trun_ast_command(compile_args[1..])\n\t\treturn\n\t}\n\n\tmut prefs := pref.new_preferences_from_args(compile_args)\n\n\tfiles := get_files(compile_args)\n\tif files.len == 0 {\n\t\teprintln('At least 1 .v file expected')\n\t\texit(1)\n\t}\n\tmut eval_runtime_args := [files[0]]\n\teval_runtime_args << runtime_args\n\tprefs.eval_runtime_args = eval_runtime_args\n\n\tmut b := builder.new_builder(prefs)\n\tb.build(files)\n\n\t// Auto-run test binaries after compilation (matching v1 behavior)\n\tif prefs.output_file == '' && is_test_file(files) {\n\t\toutput_name := os.file_name(files.last()).all_before_last('.v')\n\t\tif os.exists(output_name) {\n\t\t\tret := os.system('./' + output_name)\n\t\t\tos.rm(output_name) or {}\n\t\t\tc_file := output_name + '.c'\n\t\t\tif !prefs.keep_c && os.exists(c_file) {\n\t\t\t\tos.rm(c_file) or {}\n\t\t\t}\n\t\t\texit(ret)\n\t\t}\n\t}\n}\n\nfn split_eval_runtime_args(args []string) ([]string, []string) {\n\tfor i, arg in args {\n\t\tif arg == '--' {\n\t\t\treturn args[..i], args[i + 1..]\n\t\t}\n\t}\n\treturn args, []string{}\n}\n\nfn run_ast_command(args []string) {\n\tif args.len == 0 {\n\t\teprintln('Usage: v2 ast <file.v>')\n\t\teprintln('Dumps AST to <file>_ast.json and <file>_ast_transformed.json')\n\t\texit(1)\n\t}\n\n\t// Find the vast2 tool relative to vexe\n\tvroot := os.dir(@VEXE)\n\tvast2_path := os.join_path(vroot, 'cmd', 'tools', 'vast2', 'vast2')\n\n\t// Build vast2 if it doesn't exist\n\tif !os.exists(vast2_path) {\n\t\teprintln('Building vast2 tool...')\n\t\tvast2_source := os.join_path(vroot, 'cmd', 'tools', 'vast2', 'vast2.v')\n\t\tbuild_result := os.execute('${@VEXE} ${vast2_source}')\n\t\tif build_result.exit_code != 0 {\n\t\t\teprintln('Failed to build vast2 tool:')\n\t\t\teprintln(build_result.output)\n\t\t\texit(1)\n\t\t}\n\t}\n\n\t// Run vast2 with the provided arguments\n\tcmd := '${vast2_path} ${args.join(' ')}'\n\tresult := os.execute(cmd)\n\tprint(result.output)\n\tif result.exit_code != 0 {\n\t\texit(result.exit_code)\n\t}\n}\n\nfn is_test_file(files []string) bool {\n\tfor file in files {\n\t\tif file.ends_with('_test.v') {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// get_files extracts source files from args, excluding options and their values\nfn get_files(args []string) []string {\n\toptions_with_values := ['-backend', '-b', '-o', '-output', '-arch', '-printfn', '-gc', '-d',\n\t\t'-hot-fn']\n\tmut files := []string{}\n\tmut skip_next := false\n\tfor arg in args {\n\t\tif arg == '--' {\n\t\t\tbreak\n\t\t}\n\t\tif skip_next {\n\t\t\tskip_next = false\n\t\t\tcontinue\n\t\t}\n\t\tif arg.starts_with('-') {\n\t\t\tif arg in options_with_values {\n\t\t\t\tskip_next = true\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tfiles << arg\n\t}\n\treturn files\n}\n"
  },
  {
    "path": "doc/c_and_v_type_interoperability.md",
    "content": "> [!NOTE]\n> an important detail to remember, is that in V, the type always follows\n> the identifier in declarations, i.e. you use `x int` in V in function parameters,\n> and in struct declarations, not `int x`, like you would in C.\n\n## Number types in C and V:\n\n* A V `i8`  is equivalent to C `char`,  or `int8_t`.\n* A V `i16` is equivalent to C `short`, or `int16_t`.\n* A V `i32` is equivalent to C `int`,   or `int32_t`.\n* A V `i64` is equivalent to C `long`,  or `int64_t`.\n\n* A V `u8`  is equivalent to C `unsigned char`,  or `uint8_t`.\n* A V `u16` is equivalent to C `unsigned short`, or `uint16_t`.\n* A V `u32` is equivalent to C `unsigned int`,   or `uint32_t`.\n* A V `u64` is equivalent to C `unsigned long`,  or `uint64_t`.\n\n* A V `f32` is equivalent to C `float`.\n* A V `f64` is equivalent to C `double`.\n\n* A V `isize` is equivalent to C `ssize_t`.\nIt is a signed integer, and `isize` is guaranteed to be at least 16 bits.\nIt is 32 bit on 32 bit platforms, and 64 bits on 64 bit ones.\n\n* A V `usize` is equivalent to C `size_t`.\nIt is an unsigned integer, and `usize` is guaranteed to be at least 16 bits.\nIt is 32 bit on 32 bit platforms, and 64 bits on 64 bit ones.\n\n* A V `int` is currently equivalent to C `int`,  or `int64_t`.\nThere are plans to make it equivalent to `isize`, so if you want to write C\nlibrary wrappers, it is better to describe your `fn C.` parameters using `i32`\ninstead of using `int`.\n\n\n## Representing pointers in C and V:\nPointers in V are equivalent to pointers in C in usage.\nOne difference in their declarations, is that the order of placing the pointer\nsign is swapped. For example, you use `long *` in C, which is equivalent to `&i64` in V.\n\nIf you have a C function `func_name`, that accepts a `int *`, and an `int` index,\nand returns an `unsigned char`:\n```c ignore\nunsigned char func_name(int * p, index int);\n```\n... then you can represent its function signature in V like this:\n\n```v ignore\nfn C.func_name(p &int, index i32) u8\n```\n\n\n## Representing compound types in C and V:\nA V struct is the same as a C struct, with the same field names and\ntypes, but the order of declaring field names and their types in C structs\nand V structs is different - in C you use: `short field_name;`, but in V,\nthat would be: `field_name i16`.\n\n## Passing V strings to C functions:\nThe V string type, is currently defined like this:\n```c\nstruct string {\n    u8* str;\n    int len;\n    int is_lit;\n};\n```\n\nIf you have a string `s` in V, and you also have a C function which \naccepts `unsigned char *` in C, you can pass `s.str` to that function.\nDo *not* pass `&s`, since that will be the address of the `s` struct\nitself, and not the address of the characters in it (which is pointed\nby `s.str`).\n\n\n## Passing V dynamic array elements to C functions:\nAll V array types currently share the same C type, currently defined like this:\n```c\nstruct array {\n    void * data;\n    // For arrays, the following `offset` field is 0.\n    // For slices, the `offset` field contains the offset (in elements) from\n    // the start of the original array.\n    int offset; \n    int len;\n    int cap;\n    int flags;\n    int element_size;\n};\n```\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\nIf you want to pass a pointer to the elements of a V array `a`, to a C function,\nuse `a.data`. NOTE: do *not* use `&a` for that purpose. That will result in the address\nof the `array` itself, getting passed to the C function, and *not* the address of the\nelements of the V array.\n\n\n## Passing V fixed array elements to C functions:\nUnlike dynamic arrays, fixed arrays are the same in both V and C.\nThe address of the first element of the V fixed array of integers `fa` with\ntype `[5]i32`, is `&fa[0]` . That address can be directly used a parameter to\nC functions, that accept `int * p` or `int arr[]` parameters.\n\n\n## Functions in V and C:\nThe type of a V function, with no receiver, is equivalent to a C function, \ngiven that the types of the parameters are equivalent.\n\nWhen a V function returns more than one value, the C function returns a struct.\nFor example, these functions have equivalent types:\n```v ignore\nfn v_function(a u64, b i8) (i32, f32)\n```\n```c ignore\nstruct { int i; float f; } c_function(unsigned long a, char b);\n````\n\nA pointer to a V function is equivalent to a pointer to a C function, when the\nfunctions have equivalent types.\n\n\n## Other V types, that are currently not supported/documented for use with C:\nOther V types like interface, thread, chan, and map types are represented\nas C structs, but they are deliberately not yet completely documented for the\npurposes of C interoperability, since their implementations can still change.\n\nC struct types containing bitfields, currently have no corresponding V types.\n\nC++ class types have no corresponding V types.\n\n\n## Memory allocation in V and C\nKeep in mind, that V uses the Boehm's garbage collector by default. You can pass\na pointer to allocated memory from C to V, just remember that the responsibility\nof freeing the pointer will remain with the C side, and if the C side frees the\npointer while the V side still has a copy, your program will fail.\n\nWhen passing a pointer from V to C, the V function must retain a visible copy\nof it in some V variable. Otherwise the V garbage collector may free the\ncorresponding memory, while the C function is still using it. You can use the\nattribute `@[keep_args_alive]` to tag your `fn C.` declarations, that accept\npointers, to keep them from being freed, while the call to your `C.fname()`\nfunction has not returned.\nFor more details, see also this\n[test for keep_args_alive](vlib/v/slow_tests/keep_args_alive_test.c.v) .\n"
  },
  {
    "path": "doc/docs.md",
    "content": "# V Documentation\n\n(See https://modules.vlang.io/ for documentation of V's standard library)\n(See also https://docs.vlang.io/introduction.html, which has the same information as this document,\nbut split in separate pages for each section, for easier reading on mobile devices)\n\n## Introduction\n\nV is a statically typed compiled programming language designed for building maintainable software.\n\nIt's similar to Go and its design has also been influenced by Oberon, Rust, Swift,\nKotlin, and Python.\n\nV is a very simple language. Going through this documentation will take you about a weekend,\nand by the end of it you will have pretty much learned the entire language.\n\nThe language promotes writing simple and clear code with minimal abstraction.\n\nDespite being simple, V gives the developer a lot of power.\nAnything you can do in other languages, you can do in V.\n\n## Language specification\n\nV does not yet have a separate formal language specification document like the Go spec.\n\nUntil V 1.0, the language reference is defined by:\n* This document (`doc/docs.md`) for syntax and semantics.\n* The compiler implementation in `vlib/v/`.\n* The executable language tests in `vlib/v/tests/`, `vlib/v/parser/`,\n  `vlib/v/checker/`, and `vlib/v/slow_tests/inout/`.\n\nWhen documentation and implementation diverge, compiler behavior and tests are the source of truth.\n\n## Installing V from source\n\nThe best way to get the latest and greatest V, is to install it from source.\nIt is easy, and it takes only a few seconds:\n```bash\ngit clone --depth=1 https://github.com/vlang/v\ncd v\nmake\n```\n\nNote: If you are on windows, outside of WSL, run `make.bat` instead of `make`, in a CMD shell.\nNote: On Ubuntu/Debian, you may need to run `sudo apt install git build-essential make` first.\n\nFor more details, see the\n[Installing V](https://github.com/vlang/v/blob/master/README.md#installing-v-from-source)\nsection in the README.md.\n\n## Upgrading V to latest version\n\nIf V is already installed on a machine, it can be upgraded to its latest version\nby using the V's built-in self-updater.\nTo do so, run the command `v up`.\n\n## Packaging V for distribution\nSee the [notes on how to prepare a package for V](packaging_v_for_distributions.md) .\n\n## Getting started\n\nYou can let V automatically set up the bare-bones structure of a project for you\nby using any of the following commands in a terminal:\n\n* `v init` → adds necessary files to the current folder to make it a V project\n* `v new abc` → creates a new project in the new folder `abc`, by default a \"hello world\" project.\n* `v new --web abcd` → creates a new project in the new folder `abcd`, using the vweb template.\n\n## Table of Contents\n\n<table>\n<tr><td width=33% valign=top>\n\n* [Language specification](#language-specification)\n* [Hello world](#hello-world)\n* [Running a project folder](#running-a-project-folder-with-several-files)\n* [Comments](#comments)\n* [Functions](#functions)\n    * [Hoisting](#hoisting)\n    * [Returning multiple values](#returning-multiple-values)\n* [Symbol visibility](#symbol-visibility)\n* [Variables](#variables)\n    * [Mutable variables](#mutable-variables)\n    * [Initialization vs assignment](#initialization-vs-assignment)\n    * [Warnings and declaration errors](#warnings-and-declaration-errors)\n* [V types](#v-types)\n    * [Primitive types](#primitive-types)\n    * [Strings](#strings)\n    * [Runes](#runes)\n    * [Numbers](#numbers)\n    * [Arrays](#arrays)\n        * [Multidimensional arrays](#multidimensional-arrays)\n        * [Array methods](#array-methods)\n        * [Array slices](#array-slices)\n    * [Fixed size arrays](#fixed-size-arrays)\n    * [Maps](#maps)\n        * [Map update syntax](#map-update-syntax)\n\n</td><td width=33% valign=top>\n\n* [Module imports](#module-imports)\n    * [Selective imports](#selective-imports)\n    * [Module hierarchy](#module-hierarchy)\n    * [Module import aliasing](#module-import-aliasing)\n* [Statements & expressions](#statements--expressions)\n    * [If](#if)\n        * [`If` expressions](#if-expressions)\n        * [`If` unwrapping](#if-unwrapping)\n    * [Match](#match)\n    * [In operator](#in-operator)\n    * [For loop](#for-loop)\n    * [Defer](#defer)\n    * [Goto](#goto)\n* [Structs](#structs)\n    * [Heap structs](#heap-structs)\n    * [Default field values](#default-field-values)\n    * [Required fields](#required-fields)\n    * [Short struct literal syntax](#short-struct-literal-syntax)\n    * [Struct update syntax](#struct-update-syntax)\n    * [Trailing struct literal arguments](#trailing-struct-literal-arguments)\n    * [Access modifiers](#access-modifiers)\n    * [Anonymous structs](#anonymous-structs)\n    * [Static type methods](#static-type-methods)\n    * [[noinit] structs](#noinit-structs)\n    * [Methods](#methods)\n    * [Embedded structs](#embedded-structs)\n* [Unions](#unions)\n    * [Why use unions?](#why-use-unions)\n    * [Embedding](#embedding)\n\n</td><td valign=top>\n\n* [Functions 2](#functions-2)\n    * [Immutable function args by default](#immutable-function-args-by-default)\n    * [Mutable arguments](#mutable-arguments)\n    * [Variable number of arguments](#variable-number-of-arguments)\n    * [Anonymous & higher-order functions](#anonymous--higher-order-functions)\n    * [Lambda expressions](#lambda-expressions)\n    * [Closures](#closures)\n    * [Parameter evaluation order](#parameter-evaluation-order)\n* [References](#references)\n* [Constants](#constants)\n    * [Required module prefix](#required-module-prefix)\n* [Builtin functions](#builtin-functions)\n    * [println](#println)\n    * [Printing custom types](#printing-custom-types)\n    * [Dumping expressions at runtime](#dumping-expressions-at-runtime)\n* [Modules](#modules)\n    * [Create modules](#create-modules)\n    * [Special considerations for project folders](#special-considerations-for-project-folders)\n    * [init functions](#init-functions)\n    * [cleanup functions](#cleanup-functions)\n\n</td></tr>\n<tr><td width=33% valign=top>\n\n* [Type Declarations](#type-declarations)\n    * [Type aliases](#type-aliases)\n    * [Enums](#enums)\n    * [Function Types](#function-types)\n    * [Interfaces](#interfaces)\n    * [Sum types](#sum-types)\n    * [Option/Result types & error handling](#optionresult-types-and-error-handling)\n        * [Handling options/results](#handling-optionsresults)\n    * [Custom error types](#custom-error-types)\n    * [Generics](#generics)\n* [Concurrency](#concurrency)\n    * [Spawning Concurrent Tasks](#spawning-concurrent-tasks)\n    * [Channels](#channels)\n    * [Shared Objects](#shared-objects)\n* [JSON](#json)\n    * [Decoding JSON](#decoding-json)\n    * [Encoding JSON](#encoding-json)\n* [Testing](#testing)\n    * [Asserts](#asserts)\n    * [Asserts with an extra message](#asserts-with-an-extra-message)\n    * [Asserts that do not abort your program](#asserts-that-do-not-abort-your-program)\n    * [Test files](#test-files)\n    * [Running tests](#running-tests)\n* [Memory management](#memory-management)\n    * [Control](#control)\n    * [Stack and Heap](#stack-and-heap)\n* [ORM](#orm)\n* [Writing documentation](#writing-documentation)\n    * [Newlines in Documentation Comments](#newlines-in-documentation-comments)\n\n</td><td width=33% valign=top>\n\n* [Tools](#tools)\n    * [v fmt](#v-fmt)\n    * [v shader](#v-shader)\n    * [Profiling](#profiling)\n* [Package Management](#package-management)\n    * [Package commands](#package-commands)\n    * [Publish package](#publish-package)\n* [Advanced Topics](#advanced-topics)\n    * [Attributes](#attributes)\n    * [Conditional compilation](#conditional-compilation)\n        * [Compile time pseudo variables](#compile-time-pseudo-variables)\n        * [Compile time reflection](#compile-time-reflection)\n        * [Compile time code](#compile-time-code)\n        * [Compile time types](#compile-time-types)\n        * [Environment specific files](#environment-specific-files)\n\t* [Debugger](#debugger)\n \t\t* [Call stack](#call-stack)\n   \t\t* [Trace](#trace)\n    * [Memory-unsafe code](#memory-unsafe-code)\n    * [Structs with reference fields](#structs-with-reference-fields)\n    * [sizeof and __offsetof](#sizeof-and-__offsetof)\n    * [Limited operator overloading](#limited-operator-overloading)\n    * [Performance tuning](#performance-tuning)\n    * [Atomics](#atomics)\n    * [Global Variables](#global-variables)\n    * [Static Variables](#static-variables)\n    * [Cross compilation](#cross-compilation)\n    * [Debugging](#debugging)\n        * [C Backend binaries Default](#c-backend-binaries-default)\n        * [Native Backend binaries](#native-backend-binaries)\n        * [Javascript Backend](#javascript-backend)\n\n</td><td valign=top>\n\n* [V and C](#v-and-c)\n    * [Calling C from V](#calling-c-from-v)\n    * [Calling V from C](#calling-v-from-c)\n    * [Passing C compilation flags](#passing-c-compilation-flags)\n    * [#pkgconfig](#pkgconfig)\n    * [Including C code](#including-c-code)\n    * [C types](#c-types)\n    * [C Declarations](#c-declarations)\n    * [Export to shared library](#export-to-shared-library)\n    * [Translating C to V](#translating-c-to-v)\n    * [Working around C issues](#working-around-c-issues)\n* [Other V Features](#other-v-features)\n    * [Inline assembly](#inline-assembly)\n    * [Hot code reloading](#hot-code-reloading)\n    * [Cross-platform shell scripts in V](#cross-platform-shell-scripts-in-v)\n    * [Vsh scripts with no extension](#vsh-scripts-with-no-extension)\n* [Appendices](#appendices)\n    * [Keywords](#appendix-i-keywords)\n    * [Operators](#appendix-ii-operators)\n    * [Other online resources](#other-online-resources)\n\n</td></tr>\n</table>\n\n<!--\nNote: There are several special keywords, which you can put after the code fences for v:\ncompile, cgen, live, ignore, failcompile, okfmt, oksyntax, badsyntax, wip, nofmt\nFor more details, do: `v check-md`\n-->\n\n## Hello World\n\n```v\nfn main() {\n\tprintln('hello world')\n}\n```\n\nSave this snippet into a file named `hello.v`. Now do: `v run hello.v`.\n\n> That is assuming you have symlinked your V with `v symlink`, as described\n[here](https://github.com/vlang/v/blob/master/README.md#symlinking).\n> If you haven't yet, you have to type the path to V manually.\n\nCongratulations - you just wrote and executed your first V program!\n\nYou can compile a program without execution with `v hello.v`.\nSee `v help` for all supported commands.\n\nFrom the example above, you can see that functions are declared with the `fn` keyword.\nThe return type is specified after the function name.\nIn this case `main` doesn't return anything, so there is no return type.\n\nAs in many other languages (such as C, Go, and Rust), `main` is the entry point of your program.\n\n[`println`](#println) is one of the few [built-in functions](#builtin-functions).\nIt prints the value passed to it to standard output.\n\n`fn main()` declaration can be skipped in single file programs.\nThis is useful when writing small programs, \"scripts\", or just learning the language.\nFor brevity, `fn main()` will be skipped in this tutorial.\n\nThis means that a \"hello world\" program in V is as simple as\n\n```v\nprintln('hello world')\n```\n\n> [!NOTE]\n> If you do not explicitly use `fn main() {}`, you need to make sure that all your\n> declarations come before any variable assignment statements or top level function calls,\n> since V will consider everything after the first assignment/function call as part of your\n> implicit main function.\n\n## Running a project folder with several files\n\nSuppose you have a folder with several .v files in it, where one of them\ncontains your `main()` function, and the other files have other helper\nfunctions. They may be organized by topic, but still *not yet* structured\nenough to be their own separate reusable modules, and you want to compile\nthem all into one program.\n\nIn other languages, you would have to use includes or a build system\nto enumerate all files, compile them separately to object files,\nthen link them into one final executable.\n\nIn V however, you can compile and run the whole folder of .v files together,\nusing just `v run .`. Passing parameters also works, so you can\ndo: `v run . --yourparam some_other_stuff`\n\nThe above will first compile your files into a single program (named\nafter your folder/project), and then it will execute the program with\n`--yourparam some_other_stuff` passed to it as CLI parameters.\n\nYour program can then use the CLI parameters like this:\n\n```v\nimport os\n\nprintln(os.args)\n```\n\n> [!NOTE]\n> After a successful run, V will delete the generated executable.\n> If you want to keep it, use `v -keepc run .` instead, or just compile\n> manually with `v .` .\n\n> [!NOTE]\n> Any V compiler flags should be passed *before* the `run` command.\n> Everything after the source file/folder, will be passed to the program\n> as is - it will not be processed by V.\n\n## Comments\n\n```v\n// This is a single line comment.\n/*\nThis is a multiline comment.\n   /* It can be nested. */\n*/\n```\n\n## Functions\n\n```v\nfn main() {\n\tprintln(add(77, 33))\n\tprintln(sub(100, 50))\n}\n\nfn add(x int, y int) int {\n\treturn x + y\n}\n\nfn sub(x int, y int) int {\n\treturn x - y\n}\n```\n\nAgain, the type comes after the argument's name.\n\nJust like in Go and C, functions cannot be overloaded.\nThis simplifies the code and improves maintainability and readability.\n\n### Hoisting\n\nFunctions can be used before their declaration:\n`add` and `sub` are declared after `main`, but can still be called from `main`.\nThis is true for all declarations in V and eliminates the need for header files\nor thinking about the order of files and declarations.\n\n### Returning multiple values\n\n```v\nfn foo() (int, int) {\n\treturn 2, 3\n}\n\na, b := foo()\nprintln(a) // 2\nprintln(b) // 3\nc, _ := foo() // ignore values using `_`\n```\n\n## Symbol visibility\n\n```v\npub fn public_function() {\n}\n\nfn private_function() {\n}\n```\n\nFunctions are private (not exported) by default.\nTo allow other [modules](#module-imports) to use them, prepend `pub`. The same applies\nto [structs](#structs), [constants](#constants) and [types](#type-declarations).\n\n> [!NOTE]\n> `pub` can only be used from a named module.\n> For information about creating a module, see [Modules](#modules).\n\n## Variables\n\n```v\nname := 'Bob'\nage := 20\nlarge_number := i64(9999999999)\nprintln(name)\nprintln(age)\nprintln(large_number)\n```\n\nVariables are declared and initialized with `:=`. This is the only\nway to declare variables in V. This means that variables always have an initial\nvalue.\n\nThe variable's type is inferred from the value on the right hand side.\nTo choose a different type, use type conversion:\nthe expression `T(v)` converts the value `v` to the\ntype `T`.\n\nUnlike most other languages, V only allows defining variables in functions.\nBy default V does not allow **global variables**. See more [details](#global-variables).\n\nFor consistency across different code bases, all variable and function names\nmust use the `snake_case` style, as opposed to type names, which must use `PascalCase`.\n\n### Mutable variables\n\n```v\nmut age := 20\nprintln(age)\nage = 21\nprintln(age)\n```\n\nTo change the value of the variable use `=`. In V, variables are\nimmutable by default.\nTo be able to change the value of the variable, you have to declare it with `mut`.\n\nTry compiling the program above after removing `mut` from the first line.\n\n### Initialization vs assignment\n\nNote the (important) difference between `:=` and `=`.\n`:=` is used for declaring and initializing, `=` is used for assigning.\n\n```v failcompile\nfn main() {\n\tage = 21\n}\n```\n\nThis code will not compile, because the variable `age` is not declared.\nAll variables need to be declared in V.\n\n```v\nfn main() {\n\tage := 21\n}\n```\n\nThe values of multiple variables can be changed in one line.\nIn this way, their values can be swapped without an intermediary variable.\n\n```v\nmut a := 0\nmut b := 1\nprintln('${a}, ${b}') // 0, 1\na, b = b, a\nprintln('${a}, ${b}') // 1, 0\n```\n\n### Warnings and declaration errors\n\nIn development mode the compiler will warn you that you haven't used the variable\n(you'll get an \"unused variable\" warning).\nIn production mode (enabled by passing the `-prod` flag to v – `v -prod foo.v`)\nit will not compile at all (like in Go).\n```v\nfn main() {\n\ta := 10\n\t// warning: unused variable `a`\n}\n```\n\nTo ignore values returned by a function `_` can be used\n```v\nfn foo() (int, int) {\n\treturn 2, 3\n}\n\nfn main() {\n\tc, _ := foo()\n\tprint(c)\n\t// no warning about unused variable returned by foo.\n}\n```\n\nUnlike most languages, variable shadowing is not allowed. Declaring a variable with a name\nthat is already used in a parent scope will cause a compilation error.\n```v failcompile nofmt\nfn main() {\n\ta := 10\n\t{\n\t\ta := 20 // error: redefinition of `a`\n\t}\n}\n```\nWhile variable shadowing is not allowed, field shadowing is allowed.\n```v\npub struct Dimension {\n\twidth  int = -1\n\theight int = -1\n}\n\npub struct Test {\n\tDimension\n\twidth int = 100\n\t// height int\n}\n\nfn main() {\n\ttest := Test{}\n\tprintln('${test.width} ${test.height} ${test.Dimension.width}') // 100 -1 -1\n}\n```\n## V Types\n\n### Primitive types\n\n```v ignore\nbool\n\nstring\n\ni8    i16  int  i64      i128 (soon)\nu8    u16  u32  u64      u128 (soon)\n\nrune // represents a Unicode code point\n\nf32 f64\n\nisize, usize // platform-dependent, the size is how many bytes it takes to reference any location in memory\n\nvoidptr // this one is mostly used for [C interoperability](#v-and-c)\n```\n\n> [!NOTE]\n> Unlike C and Go, `int` is always a 32 bit integer.\n\nThere is an exception to the rule that all operators\nin V must have values of the same type on both sides. A small primitive type\non one side can be automatically promoted if it fits\ncompletely into the data range of the type on the other side.\nThese are the allowed possibilities:\n\n```v ignore\n   i8 → i16 → int → i64\n                  ↘     ↘\n                    f32 → f64\n                  ↗     ↗\n   u8 → u16 → u32 → u64 ⬎\n      ↘     ↘     ↘      ptr\n   i8 → i16 → int → i64 ⬏\n```\n\nAn `int` value for example can be automatically promoted to `f64`\nor `i64` but not to `u32`. (`u32` would mean loss of the sign for\nnegative values).\nPromotion from `int` to `f32`, however, is currently done automatically\n(but can lead to precision loss for large values).\n\nLiterals like `123` or `4.56` are treated in a special way. They do\nnot lead to type promotions, however they default to `int` and `f64`\nrespectively, when their type has to be decided:\n\n```v nofmt\nu := u16(12)\nv := 13 + u    // v is of type `u16` - no promotion\nx := f32(45.6)\ny := x + 3.14  // y is of type `f32` - no promotion\na := 75        // a is of type `int` - default for int literal\nb := 14.7      // b is of type `f64` - default for float literal\nc := u + a     // c is of type `int` - automatic promotion of `u`'s value\nd := b + x     // d is of type `f64` - automatic promotion of `x`'s value\n```\n\n### Strings\n\nIn V, strings are encoded in UTF-8, and are immutable (read-only) by default:\n\n```v\ns := 'hello 🌎' // the `world` emoji takes 4 bytes, and string length is reported in bytes\nassert s.len == 10\n\narr := s.bytes() // convert `string` to `[]u8`\nassert arr.len == 10\n\ns2 := arr.bytestr() // convert `[]u8` to `string`\nassert s2 == s\n\nname := 'Bob'\nassert name.len == 3\n// indexing gives a byte, u8(66) == `B`\nassert name[0] == u8(66)\n// slicing gives a string 'ob'\nassert name[1..3] == 'ob'\n\n// escape codes\n// escape special characters like in C\nwindows_newline := '\\r\\n'\nassert windows_newline.len == 2\n\n// arbitrary bytes can be directly specified using `\\x##` notation where `#` is\n// a hex digit\naardvark_str := '\\x61ardvark'\nassert aardvark_str == 'aardvark'\nassert '\\xc0'[0] == u8(0xc0)\n\n// or using octal escape `\\###` notation where `#` is an octal digit\naardvark_str2 := '\\141ardvark'\nassert aardvark_str2 == 'aardvark'\n\n// Unicode can be specified directly as `\\u####` where # is a hex digit\n// and will be converted internally to its UTF-8 representation\nstar_str := '\\u2605' // ★\nassert star_str == '★'\n// UTF-8 can be specified this way too, as individual bytes.\nassert star_str == '\\xe2\\x98\\x85'\n```\n\nSince strings are immutable, you cannot directly change characters in a string:\n\n```v failcompile\nmut s := 'hello 🌎'\ns[0] = `H` // not allowed\n```\n\n> error: cannot assign to `s[i]` since V strings are immutable\n\nNote that indexing a string normally will produce a `u8` (byte), not a `rune` nor another `string`.\nIndexes correspond to _bytes_ in the string, not Unicode code points.\nIf you want to convert the `u8` to a `string`, use the `.ascii_str()` method on the `u8`:\n\n```v\ncountry := 'Netherlands'\nprintln(country[0]) // Output: 78\nprintln(country[0].ascii_str()) // Output: N\n```\n\nHowever, you can easily get the runes for a string with the `runes()` method, which will return an\narray of the UTF-8 characters from the string.  You can then index this array.  Just be aware that\nthere may be fewer indexes available on the `rune` array than on the bytes in the string, if there\n_are_ any non-ASCII characters.\n\n```v\nmut s := 'hello 🌎'\n// there are 10 bytes in the string (as shown earlier), but only 7 runes, since the `world` emoji\n// only counts as one `rune` (one Unicode character)\nassert s.runes().len == 7\nprintln(s.runes()[6])\n```\n\nIf you want the code point from a specific `string` index or other more advanced UTF-8 processing\nand conversions, refer to the\n[vlib/encoding/utf8](https://modules.vlang.io/encoding.utf8.html) module.\n\nBoth single and double quotes can be used to denote strings. For consistency, `vfmt` converts double\nquotes to single quotes unless the string contains a single quote character.\n\nPrepend `r` for raw strings. Escapes are not handled, so you will get exacly what you type:\n\n```v\ns := r'hello\\nworld' // the `\\n` will be preserved as two characters\nprintln(s) // \"hello\\nworld\"\n```\n\nStrings can be easily converted to integers:\n\n```v\ns := '42'\nn := s.int() // 42\n\n// all int literals are supported\nassert '0xc3'.int() == 195\nassert '0o10'.int() == 8\nassert '0b1111_0000_1010'.int() == 3850\nassert '-0b1111_0000_1010'.int() == -3850\n```\n\nFor more advanced `string` processing and conversions, refer to the\n[vlib/strconv](https://modules.vlang.io/strconv.html) module.\n\n#### String interpolation\n\nBasic interpolation syntax is pretty simple - use `${` before a variable name and `}` after. The\nvariable will be converted to a string and embedded into the literal:\n\n```v\nname := 'Bob'\nprintln('Hello, ${name}!') // Hello, Bob!\n```\n\nIt also works with fields: `'age = ${user.age}'`. You may also use more complex expressions:\n`'can register = ${user.age > 13}'`.\n\nFormat specifiers similar to those in C's `printf()` are also supported. `f`, `g`, `x`, `o`, `b`,\netc. are optional and specify the output format. The compiler takes care of the storage size, so\nthere is no `hd` or `llu`.\n\nTo use a format specifier, follow this pattern:\n\n`${varname:[flags][width][.precision][type]}`\n\n- flags: may be zero or more of the following: `-` to left-align output within the field, `0` to use\n  `0` as the padding character instead of the default `space` character.\n  > **Note**\n  >\n  > V does not currently support the use of `'` or `#` as format flags, and V supports but\n  > doesn't need `+` to right-align since that's the default.\n- width: may be an integer value describing the minimum width of total field to output.\n- precision: an integer value preceded by a `.` will guarantee that many digits after the decimal\n  point without any insignificant trailing zeros. If displaying insignificant zero's is desired,\n  append a `f` specifier to the precision value (see examples below). Applies only to float\n  variables and is ignored for integer variables.\n- type: `f` and `F` specify the input is a float and should be rendered as such, `e` and `E` specify\n  the input is a float and should be rendered as an exponent (partially broken), `g` and `G` specify\n  the input is a float--the renderer will use floating point notation for small values and exponent\n  notation for large values, `d` specifies the input is an integer and should be rendered in base-10\n  digits, `x` and `X` require an integer and will render it as hexadecimal digits, `o` requires an\n  integer and will render it as octal digits, `b` requires an integer and will render it as binary\n  digits, `s` requires a string (almost never used).\n\n  > **Note**\n  >\n  > When a numeric type can render alphabetic characters, such as hex strings or special values\n  > like `infinity`, the lowercase version of the type forces lowercase alphabetics and the\n  > uppercase version forces uppercase alphabetics.\n\n  > **Note**\n  >\n  > In most cases, it's best to leave the format type empty. Floats will be rendered by\n  > default as `g`, integers will be rendered by default as `d`, and `s` is almost always redundant.\n  > There are only three cases where specifying a type is recommended:\n\n- format strings are parsed at compile time, so specifying a type can help detect errors then\n- format strings default to using lowercase letters for hex digits and the `e` in exponents. Use a\n  uppercase type to force the use of uppercase hex digits and an uppercase `E` in exponents.\n- format strings are the most convenient way to get hex, binary or octal strings from an integer.\n\nSee\n[Format Placeholder Specification](https://en.wikipedia.org/wiki/Printf_format_string#Format_placeholder_specification)\nfor more information.\n\n```v\nx := 123.4567\nprintln('[${x:.2}]') // round to two decimal places => [123.46]\nprintln('[${x:10}]') // right-align with spaces on the left => [   123.457]\nprintln('[${int(x):-10}]') // left-align with spaces on the right => [123       ]\nprintln('[${int(x):010}]') // pad with zeros on the left => [0000000123]\nprintln('[${int(x):b}]') // output as binary => [1111011]\nprintln('[${int(x):o}]') // output as octal => [173]\nprintln('[${int(x):X}]') // output as uppercase hex => [7B]\n\nprintln('[${10.0000:.2}]') // remove insignificant 0s at the end => [10]\nprintln('[${10.0000:.2f}]') // do show the 0s at the end, even though they do not change the number => [10.00]\n```\n\nV also has `r` and `R` switches, which will repeat the string the specified amount of times.\n\n```v\nprintln('[${'abc':3r}]') // [abcabcabc]\nprintln('[${'abc':3R}]') // [ABCABCABC]\n```\n\n#### String operators\n\n```v\nname := 'Bob'\nbobby := name + 'by' // + is used to concatenate strings\nprintln(bobby) // \"Bobby\"\nmut s := 'hello '\ns += 'world' // `+=` is used to append to a string\nprintln(s) // \"hello world\"\n```\n\nAll operators in V must have values of the same type on both sides. You cannot concatenate an\ninteger to a string:\n\n```v failcompile\nage := 10\nprintln('age = ' + age) // not allowed\n```\n\n> error: infix expr: cannot use `int` (right expression) as `string`\n\nWe have to either convert `age` to a `string`:\n\n```v\nage := 11\nprintln('age = ' + age.str())\n```\n\nor use string interpolation (preferred):\n\n```v\nage := 12\nprintln('age = ${age}')\n```\n\nSee all methods of [string](https://modules.vlang.io/builtin.html#string)\nand related modules [strings](https://modules.vlang.io/strings.html),\n[strconv](https://modules.vlang.io/strconv.html).\n\n### Runes\n\nA `rune` represents a single UTF-32 encoded Unicode character and is an alias for `u32`.\nTo denote them, use <code>`</code> (backticks) :\n\n```v\nrocket := `🚀`\n```\n\nA `rune` can be converted to a UTF-8 string by using the `.str()` method.\n\n```v\nrocket := `🚀`\nassert rocket.str() == '🚀'\n```\n\nA `rune` can be converted to UTF-8 bytes by using the `.bytes()` method.\n\n```v\nrocket := `🚀`\nassert rocket.bytes() == [u8(0xf0), 0x9f, 0x9a, 0x80]\n```\n\nHex, Unicode, and Octal escape sequences also work in a `rune` literal:\n\n```v\nassert `\\x61` == `a`\nassert `\\141` == `a`\nassert `\\u0061` == `a`\n\n// multibyte literals work too\nassert `\\u2605` == `★`\nassert `\\u2605`.bytes() == [u8(0xe2), 0x98, 0x85]\nassert `\\xe2\\x98\\x85`.bytes() == [u8(0xe2), 0x98, 0x85]\nassert `\\342\\230\\205`.bytes() == [u8(0xe2), 0x98, 0x85]\n```\n\nNote that `rune` literals use the same escape syntax as strings, but they can only hold one unicode\ncharacter. Therefore, if your code does not specify a single Unicode character, you will receive an\nerror at compile time.\n\nAlso remember that strings are indexed as bytes, not runes, so beware:\n\n```v\nrocket_string := '🚀'\nassert rocket_string[0] != `🚀`\nassert 'aloha!'[0] == `a`\n```\n\nA string can be converted to runes by the `.runes()` method.\n\n```v\nhello := 'Hello World 👋'\nhello_runes := hello.runes() // [`H`, `e`, `l`, `l`, `o`, ` `, `W`, `o`, `r`, `l`, `d`, ` `, `👋`]\nassert hello_runes.string() == hello\n```\n\n### Numbers\n\n```v\na := 123\n```\n\nThis will assign the value of 123 to `a`. By default `a` will have the\ntype `int`.\n\nYou can also use hexadecimal, binary or octal notation for integer literals:\n\n```v\na := 0x7B\nb := 0b01111011\nc := 0o173\n```\n\nAll of these will be assigned the same value, 123. They will all have type\n`int`, no matter what notation you used.\n\nV also supports writing numbers with `_` as separator:\n\n```v\nnum := 1_000_000 // same as 1000000\nthree := 0b0_11 // same as 0b11\nfloat_num := 3_122.55 // same as 3122.55\nhexa := 0xF_F // same as 255\noct := 0o17_3 // same as 0o173\n```\n\nIf you want a different type of integer, you can use casting:\n\n```v\na := i64(123)\nb := u8(42)\nc := i16(12345)\n```\n\nAssigning floating point numbers works the same way:\n\n```v\nf := 1.0\nf1 := f64(3.14)\nf2 := f32(3.14)\n```\n\nIf you do not specify the type explicitly, by default float literals\nwill have the type of `f64`.\n\nFloat literals can also be declared as a power of ten:\n\n```v\nf0 := 42e1 // 420\nf1 := 123e-2 // 1.23\nf2 := 456e+2 // 45600\n```\n\n### Arrays\n\nAn array is a collection of data elements of the same type. An array literal is a\nlist of expressions surrounded by square brackets. An individual element can be\naccessed using an *index* expression. Indexing starts from `0`.\n\n```v\nmut nums := [10, 20, 30]\nprintln(nums) // `[10, 20, 30]`\nprintln(nums[0]) // `10`\nprintln(nums[1]) // `20`\n\nnums[1] = 5\nprintln(nums) // `[10, 5, 30]`\n```\n\n<a id='array-operations'></a>\n\nAn element can be appended to the end of an array using the push operator `<<`.\nIt can also append an entire array.\n\n```v\nmut nums := [1, 2, 3]\nnums << 4\nprintln(nums) // \"[1, 2, 3, 4]\"\n\n// append array\nnums << [5, 6, 7]\nprintln(nums) // \"[1, 2, 3, 4, 5, 6, 7]\"\n```\n\n```v\nmut names := ['John']\nnames << 'Peter'\nnames << 'Sam'\n// names << 10  <-- This will not compile. `names` is an array of strings.\n```\n\n`val in array` returns true if the array contains `val`. See [`in` operator](#in-operator).\n\n```v\nnames := ['John', 'Peter', 'Sam']\nprintln('Alex' in names) // \"false\"\n```\n\n#### Array Fields\n\nThere are two fields that control the \"size\" of an array:\n\n* `len`: *length* - the number of pre-allocated and initialized elements in the array\n* `cap`: *capacity* - the amount of memory space which has been reserved for elements,\n  but not initialized or counted as elements. The array can grow up to this size without\n  being reallocated. Usually, V takes care of this field automatically but there are\n  cases where the user may want to do manual optimizations (see [below](#array-initialization)).\n\n```v\nmut nums := [1, 2, 3]\nprintln(nums.len) // \"3\"\nprintln(nums.cap) // \"3\" or greater\nnums = [] // The array is now empty\nprintln(nums.len) // \"0\"\n```\n\n`data` is a field (of type `voidptr`) with the address of the first\nelement. This is for low-level [`unsafe`](#memory-unsafe-code) code.\n\n> [!NOTE]\n> Fields are read-only and can't be modified by the user.\n\n#### Array Initialization\n\nThe type of an array is determined by the first element:\n\n* `[1, 2, 3]` is an array of ints (`[]int`).\n* `['a', 'b']` is an array of strings (`[]string`).\n\nThe user can explicitly specify the type for the first element: `[u8(16), 32, 64, 128]`.\nV arrays are homogeneous (all elements must have the same type).\nThis means that code like `[1, 'a']` will not compile.\n\nThe above syntax is fine for a small number of known elements but for very large or empty\narrays there is a second initialization syntax:\n\n```v\nmut a := []int{len: 10000, cap: 30000, init: 3}\n```\n\nThis creates an array of 10000 `int` elements that are all initialized with `3`. Memory\nspace is reserved for 30000 elements. The parameters `len`, `cap` and `init` are optional;\n`len` defaults to `0` and `init` to the default initialization of the element type (`0`\nfor numerical type, `''` for `string`, etc). The run time system makes sure that the\ncapacity is not smaller than `len` (even if a smaller value is specified explicitly):\n\n```v\narr := []int{len: 5, init: -1}\n// `arr == [-1, -1, -1, -1, -1]`, arr.cap == 5\n\n// Declare an empty array:\nusers := []int{}\n```\n\nSetting the capacity improves performance of pushing elements to the array\nas reallocations can be avoided:\n\n```v\nmut numbers := []int{cap: 1000}\nprintln(numbers.len) // 0\n// Now appending elements won't reallocate\nfor i in 0 .. 1000 {\n\tnumbers << i\n}\n```\n\n> [!NOTE]\n> The above code uses a [range `for`](#range-for) statement.\n\nYou can initialize the array by accessing the `index` variable which gives\nthe index as shown here:\n\n```v\ncount := []int{len: 4, init: index}\nassert count == [0, 1, 2, 3]\n\nmut square := []int{len: 6, init: index * index}\n// square == [0, 1, 4, 9, 16, 25]\n```\n\n#### Array Types\n\nAn array can be of these types:\n\n| Types        | Example Definition                   |\n|--------------|--------------------------------------|\n| Number       | `[]int,[]i64`                        |\n| String       | `[]string`                           |\n| Rune         | `[]rune`                             |\n| Boolean      | `[]bool`                             |\n| Array        | `[][]int`                            |\n| Struct       | `[]MyStructName`                     |\n| Channel      | `[]chan f64`                         |\n| Function     | `[]MyFunctionType` `[]fn (int) bool` |\n| Interface    | `[]MyInterfaceName`                  |\n| Sum Type     | `[]MySumTypeName`                    |\n| Generic Type | `[]T`                                |\n| Map          | `[]map[string]f64`                   |\n| Enum         | `[]MyEnumType`                       |\n| Alias        | `[]MyAliasTypeName`                  |\n| Thread       | `[]thread int`                       |\n| Reference    | `[]&f64`                             |\n| Shared       | `[]shared MyStructType`              |\n| Option       | `[]?f64`                          |\n\n**Example Code:**\n\nThis example uses [Structs](#structs) and [Sum Types](#sum-types) to create an array\nwhich can handle different types (e.g. Points, Lines) of data elements.\n\n```v\nstruct Point {\n\tx int\n\ty int\n}\n\nstruct Line {\n\tp1 Point\n\tp2 Point\n}\n\ntype ObjectSumType = Line | Point\n\nmut object_list := []ObjectSumType{}\nobject_list << Point{1, 1}\nobject_list << Line{\n\tp1: Point{3, 3}\n\tp2: Point{4, 4}\n}\ndump(object_list)\n/*\nobject_list: [ObjectSumType(Point{\n    x: 1\n    y: 1\n}), ObjectSumType(Line{\n    p1: Point{\n        x: 3\n        y: 3\n    }\n    p2: Point{\n        x: 4\n        y: 4\n    }\n})]\n*/\n```\n\n#### Multidimensional Arrays\n\nArrays can have more than one dimension.\n\n2d array example:\n\n```v\nmut a := [][]int{len: 2, init: []int{len: 3}}\na[0][1] = 2\nprintln(a) // [[0, 2, 0], [0, 0, 0]]\n```\n\n3d array example:\n\n```v\nmut a := [][][]int{len: 2, init: [][]int{len: 3, init: []int{len: 2}}}\na[0][1][1] = 2\nprintln(a) // [[[0, 0], [0, 2], [0, 0]], [[0, 0], [0, 0], [0, 0]]]\n```\n\n#### Array methods\n\nAll arrays can be easily printed with `println(arr)` and converted to a string\nwith `s := arr.str()`.\n\nCopying the data from the array is done with `.clone()`:\n\n```v\nnums := [1, 2, 3]\nnums_copy := nums.clone()\n```\n\nArrays can be efficiently filtered and mapped with the `.filter()` and\n`.map()` methods:\n\n```v\nnums := [1, 2, 3, 4, 5, 6]\neven := nums.filter(it % 2 == 0)\nprintln(even) // [2, 4, 6]\n// filter can accept anonymous functions\neven_fn := nums.filter(fn (x int) bool {\n\treturn x % 2 == 0\n})\nprintln(even_fn)\n```\n\n```v\nwords := ['hello', 'world']\nupper := words.map(it.to_upper())\nprintln(upper) // ['HELLO', 'WORLD']\n// map can also accept anonymous functions\nupper_fn := words.map(fn (w string) string {\n\treturn w.to_upper()\n})\nprintln(upper_fn) // ['HELLO', 'WORLD']\n```\n\n`it` is a builtin variable which refers to the element currently being\nprocessed in filter/map methods.\n\nAdditionally, `.any()` and `.all()` can be used to conveniently test\nfor elements that satisfy a condition.\n\n```v\nnums := [1, 2, 3]\nprintln(nums.any(it == 2)) // true\nprintln(nums.all(it >= 2)) // false\n```\n\nThere are further built-in methods for arrays:\n\n* `a.repeat(n)` concatenates the array elements `n` times\n* `a.insert(i, val)` inserts a new element `val` at index `i` and\n  shifts all following elements to the right\n* `a.insert(i, [3, 4, 5])` inserts several elements\n* `a.prepend(val)` inserts a value at the beginning, equivalent to `a.insert(0, val)`\n* `a.prepend(arr)` inserts elements of array `arr` at the beginning\n* `a.trim(new_len)` truncates the length (if `new_length < a.len`, otherwise does nothing)\n* `a.clear()` empties the array without changing `cap` (equivalent to `a.trim(0)`)\n* `a.delete_many(start, size)` removes `size` consecutive elements from index `start`\n  &ndash; triggers reallocation\n* `a.delete(index)` equivalent to `a.delete_many(index, 1)`\n* `a.delete_last()` removes the last element\n* `a.first()` equivalent to `a[0]`\n* `a.last()` equivalent to `a[a.len - 1]`\n* `a.pop()` removes the last element and returns it\n* `a.reverse()` makes a new array with the elements of `a` in reverse order\n* `a.reverse_in_place()` reverses the order of elements in `a`\n* `a.join(joiner)` concatenates an array of strings into one string\n  using `joiner` string as a separator\n\nSee all methods of [array](https://modules.vlang.io/builtin.html#array)\n\nSee also [vlib/arrays](https://modules.vlang.io/arrays.html).\n\n##### Sorting Arrays\n\nSorting arrays of all kinds is very simple and intuitive. Special variables `a` and `b`\nare used when providing a custom sorting condition.\n\n```v\nmut numbers := [1, 3, 2]\nnumbers.sort() // 1, 2, 3\nnumbers.sort(a > b) // 3, 2, 1\n```\n\n```v\nstruct User {\n\tage  int\n\tname string\n}\n\nmut users := [User{21, 'Bob'}, User{20, 'Zarkon'}, User{25, 'Alice'}]\nusers.sort(a.age < b.age) // sort by User.age int field\nusers.sort(a.name > b.name) // reverse sort by User.name string field\n```\n\nV also supports custom sorting, through the `sort_with_compare` array method.\nWhich expects a comparing function which will define the sort order.\nUseful for sorting on multiple fields at the same time by custom sorting rules.\nThe code below sorts the array ascending on `name` and descending `age`.\n\n```v\nstruct User {\n\tage  int\n\tname string\n}\n\nmut users := [User{21, 'Bob'}, User{65, 'Bob'}, User{25, 'Alice'}]\n\ncustom_sort_fn := fn (a &User, b &User) int {\n\t// return -1 when a comes before b\n\t// return 0, when both are in same order\n\t// return 1 when b comes before a\n\tif a.name == b.name {\n\t\tif a.age < b.age {\n\t\t\treturn 1\n\t\t}\n\t\tif a.age > b.age {\n\t\t\treturn -1\n\t\t}\n\t\treturn 0\n\t}\n\tif a.name < b.name {\n\t\treturn -1\n\t} else if a.name > b.name {\n\t\treturn 1\n\t}\n\treturn 0\n}\nusers.sort_with_compare(custom_sort_fn)\n```\n\n#### Array Slices\n\nA slice is a part of a parent array. Initially it refers to the elements\nbetween two indices separated by a `..` operator. The right-side index must\nbe greater than or equal to the left side index.\n\nIf a right-side index is absent, it is assumed to be the array length. If a\nleft-side index is absent, it is assumed to be 0.\n\n```v\nnums := [0, 10, 20, 30, 40]\nprintln(nums[1..4]) // [10, 20, 30]\nprintln(nums[..4]) // [0, 10, 20, 30]\nprintln(nums[1..]) // [10, 20, 30, 40]\n```\n\nIn V slices are arrays themselves (they are not distinct types). As a result\nall array operations may be performed on them. E.g. they can be pushed onto an\narray of the same type:\n\n```v\narray_1 := [3, 5, 4, 7, 6]\nmut array_2 := [0, 1]\narray_2 << array_1[..3]\nprintln(array_2) // `[0, 1, 3, 5, 4]`\n```\n\nA slice is always created with the smallest possible capacity `cap == len` (see\n[`cap` above](#array-initialization)) no matter what the capacity or length\nof the parent array is. As a result it is immediately reallocated and copied to another\nmemory location when the size increases thus becoming independent from the\nparent array (*copy on grow*). In particular pushing elements to a slice\ndoes not alter the parent:\n\n```v\nmut a := [0, 1, 2, 3, 4, 5]\n\n// Create a slice, that reuses the *same memory* as the parent array\n// initially, without doing a new allocation:\nmut b := unsafe { a[2..4] } // the contents of `b`, reuses the memory, used by the contents of `a`.\n\nb[0] = 7 // Note that `b[0]` and `a[2]` refer to *the same element* in memory.\nprintln(a) // `[0, 1, 7, 3, 4, 5]` - changing `b[0]` above, changed `a[2]` too.\n\n// the content of `b` will get reallocated, to have room for the `9` element:\nb << 9\n// The content of `b`, is now reallocated, and fully independent from the content of `a`.\n\nprintln(a) // `[0, 1, 7, 3, 4, 5]` - no change, since the content of `b` was reallocated,\n// to a larger block, before the appending.\n\nprintln(b) // `[7, 3, 9]` - the contents of `b`, after the reallocation, and appending of the `9`.\n```\n\nAppending to the parent array, may or may not make it independent from its child slices.\nThe behaviour depends on the *parent's capacity* and is predictable:\n\n```v\nmut a := []int{len: 5, cap: 6, init: 2}\nmut b := unsafe { a[1..4] } // the contents of `b` uses part of the same memory, that is used by `a` too\n\na << 3\n// still no reallocation of `a`, since `a.len` still fits in `a.cap`\nb[2] = 13 // `a[3]` is modified, through the slice `b`.\n\na << 4\n// the content of `a` has been reallocated now, and is independent from `b` (`cap` was exceeded by `len`)\nb[1] = 3 // no change in `a`\n\nprintln(a) // `[2, 2, 2, 13, 2, 3, 4]`\nprintln(b) // `[2, 3, 13]`\n```\n\nYou can call .clone() on the slice, if you *do* want to have an independent copy right away:\n\n```v\nmut a := [0, 1, 2, 3, 4, 5]\nmut b := a[2..4].clone()\nb[0] = 7 // Note: `b[0]` is NOT referring to `a[2]`, as it would have been, without the `.clone()`\nprintln(a) // [0, 1, 2, 3, 4, 5]\nprintln(b) // [7, 3]\n```\n\nNote that, by default, V makes an implicit clone of the slice and displays a notice about this.\nSo without the `.clone()` call the result of the code above will be the same. Make the slice in an\n`unsafe {}` block if you want to reuse memory, otherwise use explicit cloning.\n\n##### Slices with negative indexes\n\nV supports array and string slices with negative indexes.\nNegative indexing starts from the end of the array towards the start,\nfor example `-3` is equal to `array.len - 3`.\nNegative slices have a different syntax from normal slices, i.e. you need\nto add a `gate` between the array name and the square bracket: `a#[..-3]`.\nThe `gate` specifies that this is a different type of slice and remember that\nthe result is \"locked\" inside the array.\nThe returned slice is always a valid array, though it may be empty:\n\n```v\na := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\nprintln(a#[-3..]) // [7, 8, 9]\nprintln(a#[-20..]) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\nprintln(a#[-20..-8]) // [0, 1]\nprintln(a#[..-3]) // [0, 1, 2, 3, 4, 5, 6]\n\n// empty arrays\nprintln(a#[-20..-10]) // []\nprintln(a#[20..10]) // []\nprintln(a#[20..30]) // []\n```\n\n#### Array method chaining\n\nYou can chain the calls of array methods like `.filter()` and `.map()` and use\nthe `it` built-in variable to achieve a classic `map/filter` functional paradigm:\n\n```v\n// using filter, map and negatives array slices\nfiles := ['pippo.jpg', '01.bmp', '_v.txt', 'img_02.jpg', 'img_01.JPG']\nfiltered := files.filter(it#[-4..].to_lower() == '.jpg').map(it.to_upper())\n// ['PIPPO.JPG', 'IMG_02.JPG', 'IMG_01.JPG']\n```\n\n### Fixed size arrays\n\nV also supports arrays with fixed size. Unlike ordinary arrays, their\nlength is constant. You cannot append elements to them, nor shrink them.\nYou can only modify their elements in place.\n\nHowever, access to the elements of fixed size arrays is more efficient,\nthey need less memory than ordinary arrays, and unlike ordinary arrays,\ntheir data is on the stack, so you may want to use them as buffers if you\ndo not want additional heap allocations.\n\nMost methods are defined to work on ordinary arrays, not on fixed size arrays.\nYou can convert a fixed size array to an ordinary array with slicing:\n\n```v\nmut fnums := [3]int{} // fnums is a fixed size array with 3 elements.\nfnums[0] = 1\nfnums[1] = 10\nfnums[2] = 100\nprintln(fnums) // => [1, 10, 100]\nprintln(typeof(fnums).name) // => [3]int\n\nfnums2 := [1, 10, 100].to_fixed_size() // explicit conversion syntax\nfnums3 := [1, 10, 100]! // short init syntax, equivalent to `.to_fixed_size()`\n\nanums := fnums[..] // same as `anums := fnums[0..fnums.len]`\nprintln(anums) // => [1, 10, 100]\nprintln(typeof(anums).name) // => []int\n```\n\nNote that slicing will cause the data of the fixed size array to be copied to\nthe newly created ordinary array.\n\n### Maps\n\n```v\nmut m := map[string]int{} // a map with `string` keys and `int` values\nm['one'] = 1\nm['two'] = 2\nprintln(m['one']) // \"1\"\nprintln(m['bad_key']) // \"0\"\nprintln('bad_key' in m) // Use `in` to detect whether such key exists\nprintln(m.keys()) // ['one', 'two']\nm.delete('two')\n```\n\nMaps can have keys of type string, rune, integer, float or voidptr.\n\nThe whole map can be initialized using this short syntax:\n\n```v\nnumbers := {\n\t'one': 1\n\t'two': 2\n}\nprintln(numbers)\n```\n\nIf a key is not found, a zero value is returned by default:\n\n```v\nsm := {\n\t'abc': 'xyz'\n}\nval := sm['bad_key']\nprintln(val) // ''\n```\n\n```v\nintm := {\n\t1: 1234\n\t2: 5678\n}\ns := intm[3]\nprintln(s) // 0\n```\n\nIt's also possible to use an `or {}` block to handle missing keys:\n\n```v\nmm := map[string]int{}\nval := mm['bad_key'] or { panic('key not found') }\n```\n\nYou can also check, if a key is present, and get its value, if it was present, in one go:\n\n```v\nm := {\n\t'abc': 'def'\n}\nif v := m['abc'] {\n\tprintln('the map value for that key is: ${v}')\n}\n```\n\nThe same option check applies to arrays:\n\n```v\narr := [1, 2, 3]\nlarge_index := 999\nval := arr[large_index] or { panic('out of bounds') }\nprintln(val)\n// you can also do this, if you want to *propagate* the access error:\nval2 := arr[333]!\nprintln(val2)\n```\n\nV also supports nested maps:\n\n```v\nmut m := map[string]map[string]int{}\nm['greet'] = {\n\t'Hello': 1\n}\nm['place'] = {\n\t'world': 2\n}\nm['code']['orange'] = 123\nprint(m)\n```\n\nMaps are ordered by insertion, like dictionaries in Python. The order is a\nguaranteed language feature. This may change in the future.\n\nSee all methods of\n[map](https://modules.vlang.io/builtin.html#map)\nand\n[maps](https://modules.vlang.io/maps.html).\n\n### Map update syntax\n\nAs with structs, V lets you initialise a map with an update applied on top of\nanother map:\n\n```v\nconst base_map = {\n\t'a': 4\n\t'b': 5\n}\n\nfoo := {\n\t...base_map\n\t'b': 88\n\t'c': 99\n}\n\nprintln(foo) // {'a': 4, 'b': 88, 'c': 99}\n```\n\nThis is functionally equivalent to cloning the map and updating it, except that\nyou don't have to declare a mutable variable:\n\n```v failcompile\n// same as above (except mutable)\nmut foo := base_map.clone()\nfoo['b'] = 88\nfoo['c'] = 99\n```\n\n## Module imports\n\nFor information about creating a module, see [Modules](#modules).\n\nModules can be imported using the `import` keyword:\n\n```v\nimport os\n\nfn main() {\n\t// read text from stdin\n\tname := os.input('Enter your name: ')\n\tprintln('Hello, ${name}!')\n}\n```\n\nThis program can use any public definitions from the `os` module, such\nas the `input` function. See the [standard library](https://modules.vlang.io/)\ndocumentation for a list of common modules and their public symbols.\n\nBy default, you have to specify the module prefix every time you call an external function.\nThis may seem verbose at first, but it makes code much more readable\nand easier to understand - it's always clear which function from\nwhich module is being called. This is especially useful in large code bases.\n\nCyclic module imports are not allowed, like in Go.\n\n### Selective imports\n\nYou can also import specific functions and types from modules directly:\n\n```v\nimport os { input }\n\nfn main() {\n\t// read text from stdin\n\tname := input('Enter your name: ')\n\tprintln('Hello, ${name}!')\n}\n```\n\n> [!NOTE]\n> This will import the module as well. Also, this is not allowed for\n> constants - they must always be prefixed.\n\nYou can import several specific symbols at once:\n\n```v\nimport os { input, user_os }\n\nname := input('Enter your name: ')\nprintln('Name: ${name}')\ncurrent_os := user_os()\nprintln('Your OS is ${current_os}.')\n```\n### Module hierarchy\n\n> [!NOTE]\n> This section is valid when .v files are not in the project's root directory.\n\nModules names in .v files, must match the name of their directory.\n\nA .v file `./abc/source.v` must start with `module abc`. All .v files in this directory\nbelong to the same module `abc`. They should also start with `module abc`.\n\nIf you have `abc/def/`, and .v files in both folders, you can `import abc`, but you will have\nto `import abc.def` too, to get to the symbols in the subfolder. It is independent.\n\nIn `module name` statement, name never repeats directory's hierarchy, but only its directory.\nSo in `abc/def/source.v` the first line will be `module def`, and not `module abc.def`.\n\n`import module_name` statements must respect file hierarchy, you cannot `import def`, only\n`abc.def`\n\nReferring to a module symbol such as a function or const, only needs module name as prefix:\n\n```v ignore\nmodule def\n\n// func is a dummy example function.\npub fn func() {\n\tprintln('func')\n}\n```\n\ncan be called like this:\n\n```v ignore\nmodule main\n\nimport def\n\nfn main() {\n\tdef.func()\n}\n```\n\nA function, located in `abc/def/source.v`, is called with `def.func()`, not `abc.def.func()`\n\nThis always implies a *single prefix*, whatever sub-module depth. This behavior flattens\nmodules/sub-modules hierarchy. Should you have two modules with the same name in different\ndirectories, then you should use Module import aliasing (see below).\n\n\n### Module import aliasing\n\nAny imported module name can be aliased using the `as` keyword:\n\n> [!NOTE]\n> This example will not compile unless you have created `mymod/sha256/somename.v`\n> (submodule names are determined by their path, not by the names of the .v file(s) in them).\n\n```v failcompile\nimport crypto.sha256\nimport mymod.sha256 as mysha256\n\nfn main() {\n\tv_hash := sha256.sum('hi'.bytes()).hex()\n\tmy_hash := mysha256.sum('hi'.bytes()).hex()\n\tassert my_hash == v_hash\n}\n```\n\nYou cannot alias an imported function or type.\nHowever, you _can_ redeclare a type.\n\n```v\nimport time\nimport math\n\ntype MyTime = time.Time\n\nfn (mut t MyTime) century() int {\n\treturn int(1.0 + math.trunc(f64(t.year) * 0.009999794661191))\n}\n\nfn main() {\n\tmut my_time := MyTime{\n\t\tyear:  2020\n\t\tmonth: 12\n\t\tday:   25\n\t}\n\tprintln(time.new(my_time).utc_string())\n\tprintln('Century: ${my_time.century()}')\n}\n```\n\n## Statements & expressions\n\n### If\n\n```v\na := 10\nb := 20\nif a < b {\n\tprintln('${a} < ${b}')\n} else if a > b {\n\tprintln('${a} > ${b}')\n} else {\n\tprintln('${a} == ${b}')\n}\n```\n\n`if` statements are pretty straightforward and similar to most other languages.\nUnlike other C-like languages,\nthere are no parentheses surrounding the condition and the braces are always required.\n\n#### `If` expressions\nUnlike C, V does not have a ternary operator, that would allow you to do: `x = c ? 1 : 2` .\nInstead, it has a bit more verbose, but also clearer to read, ability to use `if` as an\nexpression. The direct translation in V of the ternary construct above, assuming `c` is a\nboolean condition, would be: `x = if c { 1 } else { 2 }`.\n\nHere is another example:\n```v\nnum := 777\ns := if num % 2 == 0 { 'even' } else { 'odd' }\nprintln(s)\n// \"odd\"\n```\n\nYou can use multiple statements in each of the branches of an `if` expression, followed by a final\nvalue, that will become the value of the entire `if` expression, when it takes that branch:\n```v\nn := arguments().len\nx := if n > 2 {\n\tdump(arguments())\n\t42\n} else {\n\tprintln('something else')\n\t100\n}\ndump(x)\n```\n\n#### `If` unwrapping\nAnywhere you can use `or {}`, you can also use \"if unwrapping\". This binds the unwrapped value\nof an expression to a variable when that expression is not none nor an error.\n\n```v\nm := {\n\t'foo': 'bar'\n}\n\n// handle missing keys\nif v := m['foo'] {\n\tprintln(v) // bar\n} else {\n\tprintln('not found')\n}\n```\n\n```v\nfn res() !int {\n\treturn 42\n}\n\n// functions that return a result type\nif v := res() {\n\tprintln(v)\n}\n```\n\n```v\nstruct User {\n\tname string\n}\n\narr := [User{'John'}]\n\n// if unwrapping with assignment of a variable\nu_name := if v := arr[0] {\n\tv.name\n} else {\n\t'Unnamed'\n}\nprintln(u_name) // John\n```\n\n#### Type checks and casts\n\nYou can check the current type of a sum type using `is` and its negated form `!is`.\n\nYou can do it either in an `if`:\n\n```v cgen\nstruct Abc {\n\tval string\n}\n\nstruct Xyz {\n\tfoo string\n}\n\ntype Alphabet = Abc | Xyz\n\nx := Alphabet(Abc{'test'}) // sum type\nif x is Abc {\n\t// x is automatically cast to Abc and can be used here\n\tprintln(x)\n}\nif x !is Abc {\n\tprintln('Not Abc')\n}\n```\n\nor using `match`:\n\n```v oksyntax\nmatch x {\n\tAbc {\n\t\t// x is automatically cast to Abc and can be used here\n\t\tprintln(x)\n\t}\n\tXyz {\n\t\t// x is automatically cast to Xyz and can be used here\n\t\tprintln(x)\n\t}\n}\n```\n\nThis works also with struct fields:\n\n```v\nstruct MyStruct {\n\tx int\n}\n\nstruct MyStruct2 {\n\ty string\n}\n\ntype MySumType = MyStruct | MyStruct2\n\nstruct Abc {\n\tbar MySumType\n}\n\nx := Abc{\n\tbar: MyStruct{123} // MyStruct will be converted to MySumType type automatically\n}\nif x.bar is MyStruct {\n\t// x.bar is automatically cast\n\tprintln(x.bar)\n} else if x.bar is MyStruct2 {\n\tnew_var := x.bar as MyStruct2\n\t// ... or you can use `as` to create a type cast an alias manually:\n\tprintln(new_var)\n}\nmatch x.bar {\n\tMyStruct {\n\t\t// x.bar is automatically cast\n\t\tprintln(x.bar)\n\t}\n\telse {}\n}\n```\n\nMutable variables can change, and doing a cast would be unsafe.\nHowever, sometimes it's useful to type cast despite mutability.\nIn such cases the developer must mark the expression with the `mut` keyword\nto tell the compiler that they know what they're doing.\n\nIt works like this:\n\n```v oksyntax\nmut x := MySumType(MyStruct{123})\nif mut x is MyStruct {\n\t// x is cast to MyStruct even if it's mutable\n\t// without the mut keyword that wouldn't work\n\tprintln(x)\n}\n// same with match\nmatch mut x {\n\tMyStruct {\n\t\t// x is cast to MyStruct even if it's mutable\n\t\t// without the mut keyword that wouldn't work\n\t\tprintln(x)\n\t}\n}\n```\n\n### Match\n\n```v\nos := 'windows'\nprint('V is running on ')\nmatch os {\n\t'darwin' { println('macOS.') }\n\t'linux' { println('Linux.') }\n\telse { println(os) }\n}\n```\n\nA match statement is a shorter way to write a sequence of `if - else` statements.\nWhen a matching branch is found, the following statement block will be run.\nThe else branch will be run when no other branches match.\n\n```v\nnumber := 2\ns := match number {\n\t1 { 'one' }\n\t2 { 'two' }\n\telse { 'many' }\n}\n```\n\nA match statement can also to be used as an `if - else if - else` alternative:\n\n```v\nmatch true {\n\t2 > 4 { println('if') }\n\t3 == 4 { println('else if') }\n\t2 == 2 { println('else if2') }\n\telse { println('else') }\n}\n// 'else if2' should be printed\n```\n\nor as an `unless` alternative: [unless Ruby](https://www.tutorialspoint.com/ruby/ruby_if_else.htm)\n\n```v\nmatch false {\n\t2 > 4 { println('if') }\n\t3 == 4 { println('else if') }\n\t2 == 2 { println('else if2') }\n\telse { println('else') }\n}\n// 'if' should be printed\n```\n\nA match expression returns the value of the final expression from the matching branch.\n\n```v\nenum Color {\n\tred\n\tblue\n\tgreen\n}\n\nfn is_red_or_blue(c Color) bool {\n\treturn match c {\n\t\t.red, .blue { true } // comma can be used to test multiple values\n\t\t.green { false }\n\t}\n}\n```\n\nA match statement can also be used to branch on the variants of an `enum`\nby using the shorthand `.variant_here` syntax. An `else` branch is not allowed\nwhen all the branches are exhaustive.\n\n```v\nc := `v`\ntyp := match c {\n\t`0`...`9` { 'digit' }\n\t`A`...`Z` { 'uppercase' }\n\t`a`...`z` { 'lowercase' }\n\telse { 'other' }\n}\nprintln(typ)\n// 'lowercase'\n```\n\nA match statement also can match the variant types of a `sumtype`. Note that\nin that case, the match is exhaustive, since all variant types are mentioned\nexplicitly, so there is no need for an `else{}` branch.\n\n```v nofmt\nstruct Dog {}\nstruct Cat {}\nstruct Veasel {}\ntype Animal = Dog | Cat | Veasel\na := Animal(Veasel{})\nmatch a {\n\tDog { println('Bay') }\n\tCat { println('Meow') }\n\tVeasel { println('Vrrrrr-eeee') } // see: https://www.youtube.com/watch?v=qTJEDyj2N0Q\n}\n```\n\nYou can also use ranges as `match` patterns. If the value falls within the range\nof a branch, that branch will be executed.\n\nNote that the ranges use `...` (three dots) rather than `..` (two dots). This is\nbecause the range is *inclusive* of the last element, rather than exclusive\n(as `..` ranges are). Using `..` in a match branch will throw an error.\n\n```v\nconst start = 1\n\nconst end = 10\n\nc := 2\nnum := match c {\n\tstart...end {\n\t\t1000\n\t}\n\telse {\n\t\t0\n\t}\n}\nprintln(num)\n// 1000\n```\n\nConstants can also be used in the range branch expressions.\n\n> [!NOTE]\n> `match` as an expression is not usable in `for` loop and `if` statements.\n\n### In operator\n\n`in` allows to check whether an array or a map contains an element.\nTo do the opposite, use `!in`.\n\n```v\nnums := [1, 2, 3]\nprintln(1 in nums) // true\nprintln(4 !in nums) // true\n```\n\n> [!NOTE]\n> `in` checks if map contains a key, not a value.\n\n```v\nm := {\n\t'one': 1\n\t'two': 2\n}\n\nprintln('one' in m) // true\nprintln('three' !in m) // true\n```\n\nIt's also useful for writing boolean expressions that are clearer and more compact:\n\n```v\nenum Token {\n\tplus\n\tminus\n\tdiv\n\tmult\n}\n\nstruct Parser {\n\ttoken Token\n}\n\nparser := Parser{}\nif parser.token == .plus || parser.token == .minus || parser.token == .div || parser.token == .mult {\n\t// ...\n}\nif parser.token in [.plus, .minus, .div, .mult] {\n\t// ...\n}\n```\n\nV optimizes such expressions,\nso both `if` statements above produce the same machine code and no arrays are created.\n\n### For loop\n\nV has only one looping keyword: `for`, with several forms.\n\n#### `for`/`in`\n\nThis is the most common form. You can use it with an array, map or\nnumeric range.\n\n##### Array `for`\n\n```v\nnumbers := [1, 2, 3, 4, 5]\nfor num in numbers {\n\tprintln(num)\n}\nnames := ['Sam', 'Peter']\nfor i, name in names {\n\tprintln('${i}) ${name}')\n\t// Output: 0) Sam\n\t//         1) Peter\n}\n```\n\nThe `for value in arr` form is used for going through elements of an array.\nIf an index is required, an alternative form `for index, value in arr` can be used.\n\nNote that the value is read-only.\nIf you need to modify the array while looping, you need to declare the element as mutable:\n\n```v\nmut numbers := [0, 1, 2]\nfor mut num in numbers {\n\tnum++\n}\nprintln(numbers) // [1, 2, 3]\n```\n\nBy default, array elements are taken by value, if you need elements to be taken by\nreference, use `&` on the array you want to iterate over:\n\n```v\nstruct User {\n\tname string\n}\n\nusers := [User{\n\tname: 'someuserwow99'\n}, User{\n\tname: 'visgod'\n}]\n// note `&users`, this is how a reference to the elements of the array is received\nfor user in &users {\n\t// some operations with `user`\n}\n```\n\nThe same applies to maps.\n\nWhen an identifier is just a single underscore, it is ignored.\n\n##### Custom iterators\n\nTypes that implement a `next` method returning an `Option` can be iterated\nwith a `for` loop.\n\n```v\nstruct SquareIterator {\n\tarr []int\nmut:\n\tidx int\n}\n\nfn (mut iter SquareIterator) next() ?int {\n\tif iter.idx >= iter.arr.len {\n\t\treturn none\n\t}\n\tdefer {\n\t\titer.idx++\n\t}\n\treturn iter.arr[iter.idx] * iter.arr[iter.idx]\n}\n\nnums := [1, 2, 3, 4, 5]\niter := SquareIterator{\n\tarr: nums\n}\nfor squared in iter {\n\tprintln(squared)\n}\n```\n\nThe code above prints:\n\n```\n1\n4\n9\n16\n25\n```\n\n##### Map `for`\n\n```v\nm := {\n\t'one': 1\n\t'two': 2\n}\nfor key, value in m {\n\tprintln('${key} -> ${value}')\n\t// Output: one -> 1\n\t//         two -> 2\n}\n```\n\nEither key or value can be ignored by using a single underscore as the identifier.\n\n```v\nm := {\n\t'one': 1\n\t'two': 2\n}\n// iterate over keys\nfor key, _ in m {\n\tprintln(key)\n\t// Output: one\n\t//         two\n}\n// iterate over values\nfor _, value in m {\n\tprintln(value)\n\t// Output: 1\n\t//         2\n}\n```\n\n##### Range `for`\n\n```v\n// Prints '01234'\nfor i in 0 .. 5 {\n\tprint(i)\n}\n```\n\n`low..high` means an *exclusive* range, which represents all values\nfrom `low` up to *but not including* `high`.\n\n> [!NOTE]\n> This exclusive range notation and zero-based indexing follow principles of\nlogical consistency and error reduction. As Edsger W. Dijkstra outlines in\n'Why Numbering Should Start at Zero'\n([EWD831](https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html)),\nzero-based indexing aligns the index with the preceding elements in a sequence,\nsimplifying handling and minimizing errors, especially with adjacent subsequences.\nThis logical and efficient approach shapes our language design, emphasizing clarity\nand reducing confusion in programming.\n\n#### Condition `for`\n\n```v\nmut sum := 0\nmut i := 0\nfor i <= 100 {\n\tsum += i\n\ti++\n}\nprintln(sum) // \"5050\"\n```\n\nThis form of the loop is similar to `while` loops in other languages.\nThe loop will stop iterating once the boolean condition evaluates to false.\nAgain, there are no parentheses surrounding the condition, and the braces are always required.\n\n#### Bare `for`\n\n```v\nmut num := 0\nfor {\n\tnum += 2\n\tif num >= 10 {\n\t\tbreak\n\t}\n}\nprintln(num) // \"10\"\n```\n\nThe condition can be omitted, resulting in an infinite loop.\n\n#### C `for`\n\n```v\nfor i := 0; i < 10; i += 2 {\n\t// Don't print 6\n\tif i == 6 {\n\t\tcontinue\n\t}\n\tprintln(i)\n}\n```\n\nFinally, there's the traditional C style `for` loop. It's safer than the `while` form\nbecause with the latter it's easy to forget to update the counter and get\nstuck in an infinite loop.\n\nHere `i` doesn't need to be declared with `mut` since it's always going to be mutable by definition.\n\n#### Labelled break & continue\n\n`break` and `continue` control the innermost `for` loop by default.\nYou can also use `break` and `continue` followed by a label name to refer to an outer `for`\nloop:\n\n```v\nouter: for i := 4; true; i++ {\n\tprintln(i)\n\tfor {\n\t\tif i < 7 {\n\t\t\tcontinue outer\n\t\t} else {\n\t\t\tbreak outer\n\t\t}\n\t}\n}\n```\n\nThe label must immediately precede the outer loop.\nThe above code prints:\n\n```\n4\n5\n6\n7\n```\n\n### Defer\n\nA `defer {}` statement, defers the execution of the block of statements\nuntil the surrounding scope of the defer ends. It is a convenient feature\nthat allows you to group related actions (getting access to a resource\nand cleaning/freeing it after you are done) closely together, instead\nof spreading them across multiple potentially very remote lines of code.\n\n```v\nimport os\n\nfn read_log() ! {\n\tmut ok := false\n\tmut f := os.open('log.txt')!\n\tdefer { f.close() }\n\t// ...\n\tif !ok {\n\t\t// ...\n\t\t// defer statement will be called here, the file will be closed\n\t\treturn\n\t}\n\t// ...\n\t// defer statement will be called here too, the file will be closed\n}\n```\n\nIf the function returns a value the `defer` block is executed *after* the return\nexpression is evaluated:\n\n```v\nimport os\n\nenum State {\n\tnormal\n\twrite_log\n\treturn_error\n}\n\n// write log file and return number of bytes written\n\nfn write_log(s State) !int {\n\tmut f := os.create('log.txt')!\n\tdefer {\n\t\tf.close()\n\t}\n\tif s == .write_log {\n\t\t// `f.close()` will be called after `f.write()` has been\n\t\t// executed, but before `write_log()` finally returns the\n\t\t// number of bytes written to `main()`\n\t\treturn f.writeln('This is a log file')\n\t} else if s == .return_error {\n\t\t// the file will be closed after the `error()` function\n\t\t// has returned - so the error message will still report\n\t\t// it as open\n\t\treturn error('nothing written; file open: ${f.is_opened}')\n\t}\n\t// the file will be closed here, too\n\treturn 0\n}\n\nfn main() {\n\tn := write_log(.return_error) or {\n\t\tprintln('Error: ${err}')\n\t\t0\n\t}\n\tprintln('${n} bytes written')\n}\n```\n\nTo access the result of the function inside a `defer` block the `$res()` expression can be used.\n`$res()` is only used when a single value is returned, while on multi-return the `$res(idx)`\nis parameterized.\n\n```v ignore\nfn (mut app App) auth_middleware() bool {\n\tdefer {\n\t\tif !$res() {\n\t\t\tapp.response.status_code = 401\n\t\t\tapp.response.body = 'Unauthorized'\n\t\t}\n\t}\n\theader := app.get_header('Authorization')\n\tif header == '' {\n\t\treturn false\n\t}\n\treturn true\n}\n\nfn (mut app App) auth_with_user_middleware() (bool, string) {\n\tdefer {\n\t\tif !$res(0) {\n\t\t\tapp.response.status_code = 401\n\t\t\tapp.response.body = 'Unauthorized'\n\t\t} else {\n\t\t\tapp.user = $res(1)\n\t\t}\n\t}\n\theader := app.get_header('Authorization')\n\tif header == '' {\n\t\treturn false, ''\n\t}\n\treturn true, 'TestUser'\n}\n```\n\n#### defer in loop scopes:\nDefer can be used inside loops too, and the deferred statement will be executed once for each\niteration. You can also have multiple defer statements in the same scope, in which case, they\nwill be executed in reverse order of their appearance in the source code:\n```v\nfn main() {\n\tdefer { println('Program finish.') }\n\tprintln('Loop start.')\n\tfor i in 1 .. 4 {\n\t\tdefer { println('Deferred execution for ${i}. Defer 1.') }\n\t\tdefer { println('Deferred execution for ${i}. Defer 2.') }\n\t\tdefer { println('Deferred execution for ${i}. Defer 3.') }\n\t\tprintln('Loop iteration: ${i}')\n\t}\n\tprintln('Loop done.')\n}\n```\n\nThe example will print this:\n```txt\nLoop start.\nLoop iteration: 1\nDeferred execution for 1. Defer 3.\nDeferred execution for 1. Defer 2.\nDeferred execution for 1. Defer 1.\nLoop iteration: 2\nDeferred execution for 2. Defer 3.\nDeferred execution for 2. Defer 2.\nDeferred execution for 2. Defer 1.\nLoop iteration: 3\nDeferred execution for 3. Defer 3.\nDeferred execution for 3. Defer 2.\nDeferred execution for 3. Defer 1.\nLoop done.\nProgram finish.\n```\n\n#### defer(fn) {}\n\nNote, that in most of the examples above, the `defer{}` statement was directly inside\na function scope, so it was executed when the function itself returned. Sometimes, you\nneed to defer a statement to execute right at the function end (like the above), even\nif you are inside an inner scope (deep inside an `if` or `for`).\n\nFor these more rare cases, you can use: `defer(fn) {}` instead of just `defer {}`.\n\n### Goto\n\nV allows unconditionally jumping to a label with `goto`. The label name must be contained\nwithin the same function as the `goto` statement. A program may `goto` a label outside\nor deeper than the current scope. `goto` allows jumping past variable initialization or\njumping back to code that accesses memory that has already been freed, so it requires\n`unsafe`.\n\n```v ignore\nif x {\n\t// ...\n\tif y {\n\t\tunsafe {\n\t\t\tgoto my_label\n\t\t}\n\t}\n\t// ...\n}\nmy_label:\n```\n\n`goto` should be avoided, particularly when `for` can be used instead.\n[Labelled break/continue](#labelled-break--continue) can be used to break out of\na nested loop, and those do not risk violating memory-safety.\n\n## Structs\n\n```v\nstruct Point {\n\tx int\n\ty int\n}\n\nmut p := Point{\n\tx: 10\n\ty: 20\n}\nprintln(p.x) // Struct fields are accessed using a dot\n// Alternative literal syntax\np = Point{10, 20}\nassert p.x == 10\n```\n\nStruct fields can re-use reserved keywords:\n\n```v\nstruct Employee {\n\ttype string\n\tname string\n}\n\nemployee := Employee{\n\ttype: 'FTE'\n\tname: 'John Doe'\n}\nprintln(employee.type)\n```\n\n### Heap structs\n\nStructs are allocated on the stack. To allocate a struct on the heap\nand get a [reference](#references) to it, use the `&` prefix:\n\n```v\nstruct Point {\n\tx int\n\ty int\n}\n\np := &Point{10, 10}\n// References have the same syntax for accessing fields\nprintln(p.x)\n```\n\nThe type of `p` is `&Point`. It's a [reference](#references) to `Point`.\nReferences are similar to Go pointers and C++ references.\n\n```v\nstruct Foo {\nmut:\n\tx int\n}\n\nfa := Foo{1}\nmut a := fa\na.x = 2\nassert fa.x == 1\nassert a.x == 2\n\n// fb := Foo{ 1 }\n// mut b := &fb  // error: `fb` is immutable, cannot have a mutable reference to it\n// b.x = 2\n\nmut fc := Foo{1}\nmut c := &fc\nc.x = 2\nassert fc.x == 2\nassert c.x == 2\nprintln(fc) // Foo{ x: 2 }\nprintln(c) // &Foo{ x: 2 } // Note `&` prefixed.\n```\n\nsee also [Stack and Heap](#stack-and-heap)\n\n### Default field values\n\n```v\nstruct Foo {\n\tn   int    // n is 0 by default\n\ts   string // s is '' by default\n\ta   []int  // a is `[]int{}` by default\n\tpos int = -1 // custom default value\n}\n```\n\nAll struct fields are zeroed by default during the creation of the struct.\nArray and map fields are allocated.\nIn case of reference value, see [here](#structs-with-reference-fields).\n\nIt's also possible to define custom default values.\n\n### Required fields\n\n```v\nstruct Foo {\n\tn int @[required]\n}\n```\n\nYou can mark a struct field with the `[required]` [attribute](#attributes), to tell V that\nthat field must be initialized when creating an instance of that struct.\n\nThis example will not compile, since the field `n` isn't explicitly initialized:\n\n```v failcompile\n_ = Foo{}\n```\n\n<a id='short-struct-initialization-syntax'></a>\n\n### Short struct literal syntax\n\n```v\nstruct Point {\n\tx int\n\ty int\n}\n\nmut p := Point{\n\tx: 10\n\ty: 20\n}\np = Point{\n\tx: 30\n\ty: 4\n}\nassert p.y == 4\n//\n// array: first element defines type of array\npoints := [Point{10, 20}, Point{20, 30}, Point{40, 50}]\nprintln(points) // [Point{x: 10, y: 20}, Point{x: 20, y: 30}, Point{x: 40,y: 50}]\n```\n\nOmitting the struct name also works for returning a struct literal or passing one\nas a function argument.\n\n### Struct update syntax\n\nV makes it easy to return a modified version of an object:\n\n```v\nstruct User {\n\tname          string\n\tage           int\n\tis_registered bool\n}\n\nfn register(u User) User {\n\treturn User{\n\t\t...u\n\t\tis_registered: true\n\t}\n}\n\nmut user := User{\n\tname: 'abc'\n\tage:  23\n}\nuser = register(user)\nprintln(user)\n```\n\n### Trailing struct literal arguments\n\nV doesn't have default function arguments or named arguments, for that trailing struct\nliteral syntax can be used instead:\n\n```v\n@[params]\nstruct ButtonConfig {\n\ttext        string\n\tis_disabled bool\n\twidth       int = 70\n\theight      int = 20\n}\n\nstruct Button {\n\ttext   string\n\twidth  int\n\theight int\n}\n\nfn new_button(c ButtonConfig) &Button {\n\treturn &Button{\n\t\twidth:  c.width\n\t\theight: c.height\n\t\ttext:   c.text\n\t}\n}\n\nbutton := new_button(text: 'Click me', width: 100)\n// the height is unset, so it's the default value\nassert button.height == 20\n```\n\nAs you can see, both the struct name and braces can be omitted, instead of:\n\n```v oksyntax nofmt\nnew_button(ButtonConfig{text:'Click me', width:100})\n```\n\nThis only works for functions that take a struct for the last argument.\n\n> [!NOTE]\n> Note the `[params]` tag is used to tell V, that the trailing struct parameter\n> can be omitted *entirely*, so that you can write `button := new_button()`.\n> Without it, you have to specify *at least* one of the field names, even if it\n> has its default value, otherwise the compiler will produce this error message,\n> when you call the function with no parameters:\n> `error: expected 1 arguments, but got 0`.\n\n### Access modifiers\n\nStruct fields are private and immutable by default (making structs immutable as well).\nTheir access modifiers can be changed with\n`pub` and `mut`. In total, there are 5 possible options:\n\n```v\nstruct Foo {\n\ta int // private immutable (default)\nmut:\n\tb int // private mutable\n\tc int // (you can list multiple fields with the same access modifier)\npub:\n\td int // public immutable (readonly)\npub mut:\n\te int // public, but mutable only in parent module\n__global:\n\t// (not recommended to use, that's why the 'global' keyword starts with __)\n\tf int // public and mutable both inside and outside parent module\n}\n```\n\nPrivate fields are available only inside the same [module](#modules), any attempt\nto directly access them from another module will cause an error during compilation.\nPublic immutable fields are readonly everywhere.\n\n### Anonymous structs\n\nV supports anonymous structs: structs that don't have to be declared separately\nwith a struct name.\n\n```v\nstruct Book {\n\tauthor struct {\n\t\tname string\n\t\tage  int\n\t}\n\n\ttitle string\n}\n\nbook := Book{\n\tauthor: struct {\n\t\tname: 'Samantha Black'\n\t\tage:  24\n\t}\n}\nassert book.author.name == 'Samantha Black'\nassert book.author.age == 24\n```\n\n### Static type methods\n\nV now supports static type methods like `User.new()`. These are defined on a struct via\n`fn [Type name].[function name]` and allow to organize all functions related to a struct:\n\n```v oksyntax\nstruct User {}\n\nfn User.new() User {\n\treturn User{}\n}\n\nuser := User.new()\n```\n\nThis is an alternative to factory functions like `fn new_user() User {}` and should be used\ninstead.\n\n> [!NOTE]\n> Note, that these are not constructors, but simple functions. V doesn't have constructors or\n> classes.\n\n### `[noinit]` structs\n\nV supports `[noinit]` structs, which are structs that cannot be initialised outside the module\nthey are defined in. They are either meant to be used internally or they can be used externally\nthrough _factory functions_.\n\nFor an example, consider the following source in a directory `sample`:\n\n```v oksyntax\nmodule sample\n\n@[noinit]\npub struct Information {\npub:\n\tdata string\n}\n\npub fn new_information(data string) !Information {\n\tif data.len == 0 || data.len > 100 {\n\t\treturn error('data must be between 1 and 100 characters')\n\t}\n\treturn Information{\n\t\tdata: data\n\t}\n}\n```\n\nNote that `new_information` is a _factory_ function. Now when we want to use this struct\noutside the module:\n\n```v okfmt\nimport sample\n\nfn main() {\n\t// This doesn't work when the [noinit] attribute is present:\n\t// info := sample.Information{\n\t// \tdata: 'Sample information.'\n\t// }\n\n\t// Use this instead:\n\tinfo := sample.new_information('Sample information.')!\n\n\tprintln(info)\n}\n```\n\n### Methods\n\n```v\nstruct User {\n\tage int\n}\n\nfn (u User) can_register() bool {\n\treturn u.age > 16\n}\n\nuser := User{\n\tage: 10\n}\nprintln(user.can_register()) // \"false\"\nuser2 := User{\n\tage: 20\n}\nprintln(user2.can_register()) // \"true\"\n```\n\nV doesn't have classes, but you can define methods on types.\nA method is a function with a special receiver argument.\nThe receiver appears in its own argument list between the `fn` keyword and the method name.\nMethods must be in the same module as the receiver type.\n\nIn this example, the `can_register` method has a receiver of type `User` named `u`.\nThe convention is not to use receiver names like `self` or `this`,\nbut a short, preferably one letter long, name.\n\n### Embedded structs\n\nV supports embedded structs.\n\n```v\nstruct Size {\nmut:\n\twidth  int\n\theight int\n}\n\nfn (s &Size) area() int {\n\treturn s.width * s.height\n}\n\nstruct Button {\n\tSize\n\ttitle string\n}\n```\n\nWith embedding, the struct `Button` will automatically get all the fields and methods from\nthe struct `Size`, which allows you to do:\n\n```v oksyntax\nmut button := Button{\n\ttitle:  'Click me'\n\theight: 2\n}\n\nbutton.width = 3\nassert button.area() == 6\nassert button.Size.area() == 6\nprint(button)\n```\n\noutput :\n\n```\nButton{\n    Size: Size{\n        width: 3\n        height: 2\n    }\n    title: 'Click me'\n}\n```\n\nUnlike inheritance, you cannot type cast between structs and embedded structs\n(the embedding struct can also have its own fields, and it can also embed multiple structs).\n\nIf you need to access embedded structs directly, use an explicit reference like `button.Size`.\n\nConceptually, embedded structs are similar to [mixin](https://en.wikipedia.org/wiki/Mixin)s\nin OOP, *NOT* base classes.\n\nYou can also initialize an embedded struct:\n\n```v oksyntax\nmut button := Button{\n\tSize: Size{\n\t\twidth:  3\n\t\theight: 2\n\t}\n}\n```\n\nor assign values:\n\n```v oksyntax\nbutton.Size = Size{\n\twidth:  4\n\theight: 5\n}\n```\n\nIf multiple embedded structs have methods or fields with the same name, or if methods or fields\nwith the same name are defined in the struct, you can call methods or assign to variables in\nthe embedded struct like `button.Size.area()`.\nWhen you do not specify the embedded struct name, the method of the outermost struct will be\ntargeted.\n\n## Unions\n\nA union is a special type of struct that allows storing different data types in the same memory\nlocation. You can define a union with many members, but only one member may contain a valid value\nat any time, depending on the data types of the members. Unions provide an efficient way of using\nthe same memory location for multiple purposes.\n\nAll the members of a union share the same memory location. This means that modifying one member\nautomatically modifies all the rest. The largest union member defines the size of the union.\n\n### Why use unions?\n\nOne reason, as stated above, is to use less memory for storing things.  Since the size of a union\nis the size of the largest field in it, and the size of a struct is the size of all the fields in\nthe struct added together, a union is definitely better for lower memory usage.  As long as you\nonly need one of the fields to be valid at any time, the union wins.\n\nAnother reason is to allow easier access to parts of a field.  For example, without using a union,\nif you want to look at each of the bytes of a 32-bit integer separately, you'll need bitwise\n`RIGHT-SHIFT`s and `AND` operations.  With a union, you can access the individual bytes directly.\n```v\nunion ThirtyTwo {\n\ta u32\n\tb [4]u8\n}\n```\nSince `ThirtyTwo.a` and `ThirtyTwo.b` share the same memory locations, you can directly access\neach byte of `a` by referencing `b[byte_offset]`.\n\n### Embedding\n\nUnions also support embedding, the same as structs.\n\n```v\nstruct Rgba32_Component {\n\tr u8\n\tg u8\n\tb u8\n\ta u8\n}\n\nunion Rgba32 {\n\tRgba32_Component\n\tvalue u32\n}\n\nclr1 := Rgba32{\n\tvalue: 0x008811FF\n}\n\nclr2 := Rgba32{\n\tRgba32_Component: Rgba32_Component{\n\t\ta: 128\n\t}\n}\n\nsz := sizeof(Rgba32)\nunsafe {\n\tprintln('Size: ${sz}B,clr1.b: ${clr1.b},clr2.b: ${clr2.b}')\n}\n```\n\nOutput: `Size: 4B, clr1.b: 136, clr2.b: 0`\n\nUnion member access must be performed in an `unsafe` block.\n\n> [!NOTE]\n> Embedded struct arguments are not necessarily stored in the order listed.\n\n## Functions 2\n\n### Immutable function args by default\n\nIn V function arguments are immutable by default, and mutable args have to be\nmarked on call.\n\nSince there are also no globals, that means that the return values of the functions,\nare a function of their arguments only, and their evaluation has no side effects\n(unless the function uses I/O).\n\nFunction arguments are immutable by default, even when [references](#references) are passed.\n\n> [!NOTE]\n> However, V is not a purely functional language.\n\nThere is a compiler flag to enable global variables (`-enable-globals`), but this is\nintended for low-level applications like kernels and drivers.\n\n### Mutable arguments\n\nIt is possible to modify function arguments by declaring them with the keyword `mut`:\n\n```v\nstruct User {\n\tname string\nmut:\n\tis_registered bool\n}\n\nfn (mut u User) register() {\n\tu.is_registered = true\n}\n\nmut user := User{}\nprintln(user.is_registered) // \"false\"\nuser.register()\nprintln(user.is_registered) // \"true\"\n```\n\nIn this example, the receiver (which is just the first argument) is explicitly marked as mutable,\nso `register()` can change the user object. The same works with non-receiver arguments:\n\n```v\nfn multiply_by_2(mut arr []int) {\n\tfor i in 0 .. arr.len {\n\t\tarr[i] *= 2\n\t}\n}\n\nmut nums := [1, 2, 3]\nmultiply_by_2(mut nums)\nprintln(nums)\n// \"[2, 4, 6]\"\n```\n\nNote that you have to add `mut` before `nums` when calling this function. This makes\nit clear that the function being called will modify the value.\n\nIt is preferable to return values instead of modifying arguments,\ne.g. `user = register(user)` (or `user.register()`) instead of `register(mut user)`.\nModifying arguments should only be done in performance-critical parts of your application\nto reduce allocations and copying.\n\nFor this reason V doesn't allow the modification of arguments with primitive types (e.g. integers).\nOnly more complex types such as arrays and maps may be modified.\n\n### Variable number of arguments\nV supports functions that receive an arbitrary, variable amounts of arguments, denoted with the\n`...` prefix.\nBelow, `a ...int` refers to an arbitrary amount of parameters that will be collected\ninto an array named `a`.\n\n```v\nfn sum(a ...int) int {\n\tmut total := 0\n\tfor x in a {\n\t\ttotal += x\n\t}\n\treturn total\n}\n\nprintln(sum()) // 0\nprintln(sum(1)) // 1\nprintln(sum(2, 3)) // 5\n// using array decomposition\na := [2, 3, 4]\nprintln(sum(...a)) // <-- using prefix ... here. output: 9\nb := [5, 6, 7]\nprintln(sum(...b)) // output: 18\n```\n\n### Anonymous & higher order functions\n\n```v\nfn sqr(n int) int {\n\treturn n * n\n}\n\nfn cube(n int) int {\n\treturn n * n * n\n}\n\nfn run(value int, op fn (int) int) int {\n\treturn op(value)\n}\n\nfn main() {\n\t// Functions can be passed to other functions\n\tprintln(run(5, sqr)) // \"25\"\n\t// Anonymous functions can be declared inside other functions:\n\tdouble_fn := fn (n int) int {\n\t\treturn n + n\n\t}\n\tprintln(run(5, double_fn)) // \"10\"\n\t// Functions can be passed around without assigning them to variables:\n\tres := run(5, fn (n int) int {\n\t\treturn n + n\n\t})\n\tprintln(res) // \"10\"\n\t// You can even have an array/map of functions:\n\tfns := [sqr, cube]\n\tprintln(fns[0](10)) // \"100\"\n\tfns_map := {\n\t\t'sqr':  sqr\n\t\t'cube': cube\n\t}\n\tprintln(fns_map['cube'](2)) // \"8\"\n}\n```\n\n### Lambda expressions\n\nLambda expressions in V are small anonymous functions, defined using\nthe `|variables| expression` syntax. Note: this syntax is valid only inside calls to higher\norder functions.\n\nHere are some examples:\n```v\nmut a := [1, 2, 3]\na.sort(|x, y| x > y) // sorts the array, defining the comparator with a lambda expression\nprintln(a.map(|x| x * 10)) // prints [30, 20, 10]\n```\n\n```v\n// Lambda function can be used as callback\nfn f(cb fn (a int) int) int {\n\treturn cb(10)\n}\n\nprintln(f(|x| x + 4)) // prints 14\n```\n\n### Closures\n\nV supports closures too.\nThis means that anonymous functions can inherit variables from the scope they were created in.\nThey must do so explicitly by listing all variables that are inherited.\n\n```v oksyntax\nmy_int := 1\nmy_closure := fn [my_int] () {\n\tprintln(my_int)\n}\nmy_closure() // prints 1\n```\n\nInherited variables are copied when the anonymous function is created.\nThis means that if the original variable is modified after the creation of the function,\nthe modification won't be reflected in the function.\n\n```v oksyntax\nmut i := 1\nfunc := fn [i] () int {\n\treturn i\n}\nprintln(func() == 1) // true\ni = 123\nprintln(func() == 1) // still true\n```\n\nHowever, the variable can be modified inside the anonymous function.\nThe change won't be reflected outside, but will be in the later function calls.\n\n```v oksyntax\nfn new_counter() fn () int {\n\tmut i := 0\n\treturn fn [mut i] () int {\n\t\ti++\n\t\treturn i\n\t}\n}\n\nc := new_counter()\nprintln(c()) // 1\nprintln(c()) // 2\nprintln(c()) // 3\n```\n\nIf you need the value to be modified outside the function, use a reference.\n\n```v oksyntax\nmut i := 0\nmut ref := &i\nprint_counter := fn [ref] () {\n\tprintln(*ref)\n}\n\nprint_counter() // 0\ni = 10\nprint_counter() // 10\n```\n\n### Parameter evaluation order\n\nThe evaluation order of the parameters of function calls is *NOT* guaranteed.\nTake for example the following program:\n\n```v\nfn f(a1 int, a2 int, a3 int) {\n\tdump(a1 + a2 + a3)\n}\n\nfn main() {\n\tf(dump(100), dump(200), dump(300))\n}\n```\n\nV currently does not guarantee that it will print 100, 200, 300 in that order.\nThe only guarantee is that 600 (from the body of `f`) will be printed after all of them.\n\nThis *may* change in V 1.0 .\n\n## References\n\n```v\nstruct Foo {}\n\nfn (foo Foo) bar_method() {\n\t// ...\n}\n\nfn bar_function(foo Foo) {\n\t// ...\n}\n```\n\nIf a function argument is immutable (like `foo` in the examples above)\nV can pass it either by value or by reference. The compiler will decide,\nand the developer doesn't need to think about it.\n\nYou no longer need to remember whether you should pass the struct by value\nor by reference.\n\nYou can ensure that the struct is always passed by reference by\nadding `&`:\n\n```v\nstruct Foo {\n\tabc int\n}\n\nfn (foo &Foo) bar() {\n\tprintln(foo.abc)\n}\n```\n\n`foo` is still immutable and can't be changed. For that,\n`(mut foo Foo)` must be used.\n\nIn general, V's references are similar to Go pointers and C++ references.\nFor example, a generic tree structure definition would look like this:\n\n```v\nstruct Node[T] {\n\tval   T\n\tleft  &Node[T]\n\tright &Node[T]\n}\n```\n\nTo dereference a reference, use the `*` operator, just like in C.\n\n## Constants\n\n```v\nconst pi = 3.14\nconst world = '世界'\n\nprintln(pi)\nprintln(world)\n```\n\nConstants are declared with `const`. They can only be defined\nat the module level (outside of functions).\nConstant values can never be changed. You can also declare a single\nconstant separately:\n\n```v\nconst e = 2.71828\n```\n\nV constants are more flexible than in most languages. You can assign more complex values:\n\n```v\nstruct Color {\n\tr int\n\tg int\n\tb int\n}\n\nfn rgb(r int, g int, b int) Color {\n\treturn Color{\n\t\tr: r\n\t\tg: g\n\t\tb: b\n\t}\n}\n\nconst numbers = [1, 2, 3]\nconst red = Color{\n\tr: 255\n\tg: 0\n\tb: 0\n}\n// evaluate function call at compile time*\nconst blue = rgb(0, 0, 255)\n\nprintln(numbers)\nprintln(red)\nprintln(blue)\n```\n\n\\* WIP - for now function calls are evaluated at program start-up\n\nGlobal variables are not normally allowed, so this can be really useful.\n\n**Modules**\n\nConstants can be made public with `pub const`:\n\n```v oksyntax\nmodule mymodule\n\npub const golden_ratio = 1.61803\n\nfn calc() {\n\tprintln(golden_ratio)\n}\n```\n\nThe `pub` keyword is only allowed before the `const` keyword and cannot be used inside\na `const ( )` block.\n\nOutside from module main all constants need to be prefixed with the module name.\n\n### Required module prefix\n\nWhen naming constants, `snake_case` must be used. In order to distinguish consts\nfrom local variables, the full path to consts must be specified. For example,\nto access the PI const, full `math.pi` name must be used both outside the `math`\nmodule, and inside it. That restriction is relaxed only for the `main` module\n(the one containing your `fn main()`), where you can use the unqualified name of\nconstants defined there, i.e. `numbers`, rather than `main.numbers`.\n\nvfmt takes care of this rule, so you can type `println(pi)` inside the `math` module,\nand vfmt will automatically update it to `println(math.pi)`.\n\n<!--\nMany people prefer all caps consts: `TOP_CITIES`. This wouldn't work\nwell in V, because consts are a lot more powerful than in other languages.\nThey can represent complex structures, and this is used quite often since there\nare no globals:\n\n```v oksyntax\nprintln('Top cities: ${top_cities.filter(.usa)}')\n```\n-->\n\n## Builtin functions\n\nSome functions are builtin like `println`. Here is the complete list:\n\n```v ignore\nfn print(s string) // prints anything on stdout\nfn println(s string) // prints anything and a newline on stdout\n\nfn eprint(s string) // same as print(), but uses stderr\nfn eprintln(s string) // same as println(), but uses stderr\n\nfn exit(code int) // terminates the program with a custom error code\nfn panic(s string) // prints a message and backtraces on stderr, and terminates the program with error code 1\nfn print_backtrace() // prints backtraces on stderr\n```\n\n> [!NOTE]\n> Although the `print` functions take a string, V accepts other printable types too.\n> See below for details.\n\nThere is also a special built-in function called [`dump`](#dumping-expressions-at-runtime).\n\n### println\n\n`println` is a simple yet powerful builtin function, that can print anything:\nstrings, numbers, arrays, maps, structs.\n\n```v\nstruct User {\n\tname string\n\tage  int\n}\n\nprintln(1) // \"1\"\nprintln('hi') // \"hi\"\nprintln([1, 2, 3]) // \"[1, 2, 3]\"\nprintln(User{ name: 'Bob', age: 20 }) // \"User{name:'Bob', age:20}\"\n```\n\nSee also [String interpolation](#string-interpolation).\n\n<a id='custom-print-of-types'></a>\n\n### Printing custom types\n\nIf you want to define a custom print value for your type, simply define a\n`str() string` method:\n\n```v\nstruct Color {\n\tr int\n\tg int\n\tb int\n}\n\npub fn (c Color) str() string {\n\treturn '{${c.r}, ${c.g}, ${c.b}}'\n}\n\nred := Color{\n\tr: 255\n\tg: 0\n\tb: 0\n}\nprintln(red)\n```\n\n### Dumping expressions at runtime\n\nYou can dump/trace the value of any V expression using `dump(expr)`.\nFor example, save this code sample as `factorial.v`, then run it with\n`v run factorial.v`:\n\n```v\nfn factorial(n u32) u32 {\n\tif dump(n <= 1) {\n\t\treturn dump(1)\n\t}\n\treturn dump(n * factorial(n - 1))\n}\n\nfn main() {\n\tprintln(factorial(5))\n}\n```\n\nYou will get:\n\n```\n[factorial.v:2] n <= 1: false\n[factorial.v:2] n <= 1: false\n[factorial.v:2] n <= 1: false\n[factorial.v:2] n <= 1: false\n[factorial.v:2] n <= 1: true\n[factorial.v:3] 1: 1\n[factorial.v:5] n * factorial(n - 1): 2\n[factorial.v:5] n * factorial(n - 1): 6\n[factorial.v:5] n * factorial(n - 1): 24\n[factorial.v:5] n * factorial(n - 1): 120\n120\n```\n\nNote that `dump(expr)` will trace both the source location,\nthe expression itself, and the expression value.\n\n## Modules\n\nEvery file in the root of a folder is part of the same module.\nSimple programs don't need to specify module name, in which case it defaults to 'main'.\n\nSee [symbol visibility](#symbol-visibility), [Access modifiers](#access-modifiers).\n\n### Create modules\n\nV is a very modular language. Creating reusable modules is encouraged and is\nquite easy to do.\nTo create a new module, create a directory with your module's name containing\n.v files with code:\n\n```shell\ncd ~/code/modules\nmkdir mymodule\nvim mymodule/myfile.v\n```\n\n```v failcompile\n// myfile.v\nmodule mymodule\n\n// To export a function we have to use `pub`\npub fn say_hi() {\n\tprintln('hello from mymodule!')\n}\n```\nAll items inside a module can be used between the files of a module regardless of whether or\nnot they are prefaced with the `pub` keyword.\n```v failcompile\n// myfile2.v\nmodule mymodule\n\npub fn say_hi_and_bye() {\n\tsay_hi() // from myfile.v\n\tprintln('goodbye from mymodule')\n}\n```\n\nYou can now use `mymodule` in your code:\n\n```v failcompile\nimport mymodule\n\nfn main() {\n\tmymodule.say_hi()\n\tmymodule.say_hi_and_bye()\n}\n```\n\n* Module names should be short, under 10 characters.\n* Module names must use `snake_case`.\n* Circular imports are not allowed.\n* You can have as many .v files in a module as you want.\n* You can create modules anywhere.\n* All modules are compiled statically into a single executable.\n\n### Special considerations for project folders\n\nFor the top level project folder (the one, compiled with `v .`), and *only*\nthat folder, you can have several .v files, that may be mentioning different modules\nwith `module main`, `module abc` etc\n\nThis is to ease the prototyping workflow in that folder:\n- you can start developing some new project with a single .v file\n- split functionality as necessary to different .v files in the same folder\n- when that makes logical sense to be further organised, put them into their own directory module.\n\nNote that in ordinary modules, all .v files must start with `module name_of_folder`.\n\n### `init` functions\n\nIf you want a module to automatically call some setup/initialization code when it is imported,\nyou can define a module `init` function:\n\n```v\nfn init() {\n\t// your setup code here ...\n}\n```\n\nThe `init` function cannot be public - it will be called automatically by V, *just once*, no matter\nhow many times the module was imported in your program. This feature is particularly useful for\ninitializing a C library.\n\n### `cleanup` functions\n\nIf you want a module to automatically call some cleanup/deinitialization code, when your program\nends, you can define a module `cleanup` function:\n\n```v\nfn cleanup() {\n\t// your deinitialisation code here ...\n}\n```\n\nJust like the `init` function, the `cleanup` function for a module cannot be public - it will be\ncalled automatically, when your program ends, once per module, even if the module was imported\ntransitively by other modules several times, in the reverse order of the init calls.\n\n## Type Declarations\n\n### Type aliases\n\nTo define a new type `NewType` as an alias for `ExistingType`,\ndo `type NewType = ExistingType`.<br/>\nThis is a special case of a [sum type](#sum-types) declaration.\n\n### Enums\n\nAn enum is a group of constant integer values, each having its own name,\nwhose values start at 0 and increase by 1 for each name listed.\nFor example:\n```v\nenum Color as u8 {\n\tred   // the default start value is 0\n\tgreen // the value is automatically incremented to 1\n\tblue  // the final value is now 2\n}\n\nmut color := Color.red\n// V knows that `color` is a `Color`. No need to use `color = Color.green` here.\ncolor = .green\nprintln(color) // \"green\"\nmatch color {\n\t.red { println('the color was red') }\n\t.green { println('the color was green') }\n\t.blue { println('the color was blue') }\n}\nprintln(int(color)) // prints 1\n```\n\nThe enum type can be any integer type, but can be omitted, if it is `int`: `enum Color {`.\n\nEnum match must be exhaustive or have an `else` branch.\nThis ensures that if a new enum field is added, it's handled everywhere in the code.\n\nEnum fields can re-use reserved keywords:\n\n```v\nenum Color {\n\tnone\n\tred\n\tgreen\n\tblue\n}\n\ncolor := Color.none\nprintln(color)\n```\n\nIntegers may be assigned to enum fields.\n\n```v\nenum Grocery {\n\tapple\n\torange = 5\n\tpear\n}\n\ng1 := int(Grocery.apple)\ng2 := int(Grocery.orange)\ng3 := int(Grocery.pear)\nprintln('Grocery IDs: ${g1}, ${g2}, ${g3}')\n```\n\nOutput: `Grocery IDs: 0, 5, 6`.\n\nOperations are not allowed on enum variables; they must be explicitly cast to `int`.\n\nEnums can have methods, just like structs.\n\n```v\nenum Cycle {\n\tone\n\ttwo\n\tthree\n}\n\nfn (c Cycle) next() Cycle {\n\tmatch c {\n\t\t.one {\n\t\t\treturn .two\n\t\t}\n\t\t.two {\n\t\t\treturn .three\n\t\t}\n\t\t.three {\n\t\t\treturn .one\n\t\t}\n\t}\n}\n\nmut c := Cycle.one\nfor _ in 0 .. 10 {\n\tprintln(c)\n\tc = c.next()\n}\n```\n\nOutput:\n\n```\none\ntwo\nthree\none\ntwo\nthree\none\ntwo\nthree\none\n```\n\nEnums can be created from string or integer value and converted into string\n\n```v\nenum Cycle {\n\tone\n\ttwo = 2\n\tthree\n}\n\n// Create enum from value\nprintln(Cycle.from(10) or { Cycle.three })\nprintln(Cycle.from('two')!)\n\n// Convert an enum value to a string\nprintln(Cycle.one.str())\n```\n\nOutput:\n\n```\nthree\ntwo\none\n```\n\n### Function Types\n\nYou can use type aliases for naming specific function signatures - for\nexample:\n\n```v\ntype Filter = fn (string) string\n```\n\nThis works like any other type - for example, a function can accept an\nargument of a function type:\n\n```v\ntype Filter = fn (string) string\n\nfn filter(s string, f Filter) string {\n\treturn f(s)\n}\n```\n\nV has duck-typing, so functions don't need to declare compatibility with\na function type - they just have to be compatible:\n\n```v\nfn uppercase(s string) string {\n\treturn s.to_upper()\n}\n\n// now `uppercase` can be used everywhere where Filter is expected\n```\n\nCompatible functions can also be explicitly cast to a function type:\n\n```v oksyntax\nmy_filter := Filter(uppercase)\n```\n\nThe cast here is purely informational - again, duck-typing means that the\nresulting type is the same without an explicit cast:\n\n```v oksyntax\nmy_filter := uppercase\n```\n\nYou can pass the assigned function as an argument:\n\n```v oksyntax\nprintln(filter('Hello world', my_filter)) // prints `HELLO WORLD`\n```\n\nAnd you could of course have passed it directly as well, without using a\nlocal variable:\n\n```v oksyntax\nprintln(filter('Hello world', uppercase))\n```\n\nAnd this works with anonymous functions as well:\n\n```v oksyntax\nprintln(filter('Hello world', fn (s string) string {\n\treturn s.to_upper()\n}))\n```\n\nYou can see the complete\n[example here](https://github.com/vlang/v/tree/master/examples/function_types.v).\n\n### Interfaces\n\n```v\n// interface-example.1\nstruct Dog {\n\tbreed string\n}\n\nfn (d Dog) speak() string {\n\treturn 'woof'\n}\n\nstruct Cat {\n\tbreed string\n}\n\nfn (c Cat) speak() string {\n\treturn 'meow'\n}\n\n// unlike Go, but like TypeScript, V's interfaces can define both fields and methods.\ninterface Speaker {\n\tbreed string\n\tspeak() string\n}\n\nfn main() {\n\tdog := Dog{'Leonberger'}\n\tcat := Cat{'Siamese'}\n\n\tmut arr := []Speaker{}\n\tarr << dog\n\tarr << cat\n\tfor item in arr {\n\t\tprintln('a ${item.breed} says: ${item.speak()}')\n\t}\n}\n```\n\n#### Implement an interface\n\nA type implements an interface by implementing its methods and fields.\n\nAn interface can have a `mut:` section. Implementing types will need\nto have a `mut` receiver, for methods declared in the `mut:` section\nof an interface.\n\n```v\n// interface-example.2\nmodule main\n\ninterface Foo {\n\twrite(string) string\n}\n\n// => the method signature of a type, implementing interface Foo should be:\n// `fn (s Type) write(a string) string`\n\ninterface Bar {\nmut:\n\twrite(string) string\n}\n\n// => the method signature of a type, implementing interface Bar should be:\n// `fn (mut s Type) write(a string) string`\n\nstruct MyStruct {}\n\n// MyStruct implements the interface Foo, but *not* interface Bar\nfn (s MyStruct) write(a string) string {\n\treturn a\n}\n\nfn main() {\n\ts1 := MyStruct{}\n\tfn1(s1)\n\t// fn2(s1) -> compile error, since MyStruct does not implement Bar\n}\n\nfn fn1(s Foo) {\n\tprintln(s.write('Foo'))\n}\n\n// fn fn2(s Bar) { // does not match\n//      println(s.write('Foo'))\n// }\n```\n\nThere is an **optional** `implements` keyword for explicit declaration\nof intent, which applies to `struct` declarations.\n\n```v\nstruct PathError implements IError {\n\tError\n\tpath string\n}\n\nfn (err PathError) msg() string {\n\treturn 'Failed to open path: ${err.path}'\n}\n\nfn try_open(path string) ! {\n\treturn PathError{\n\t\tpath: path\n\t}\n}\n\nfn main() {\n\ttry_open('/tmp') or { panic(err) }\n}\n```\n\n#### Casting an interface\n\nWe can test the underlying type of an interface using dynamic cast operators.\n> [!NOTE]\n> Dynamic cast converts variable `s` into a pointer inside the `if` statements in this example:\n\n```v oksyntax\n// interface-example.3 (continued from interface-example.1)\ninterface Something {}\n\nfn announce(s Something) {\n\tif s is Dog {\n\t\tprintln('a ${s.breed} dog') // `s` is automatically cast to `Dog` (smart cast)\n\t} else if s is Cat {\n\t\tprintln('a cat speaks ${s.speak()}')\n\t} else {\n\t\tprintln('something else')\n\t}\n}\n\nfn main() {\n\tdog := Dog{'Leonberger'}\n\tcat := Cat{'Siamese'}\n\tannounce(dog)\n\tannounce(cat)\n}\n```\n\n```v\n// interface-example.4\ninterface IFoo {\n\tfoo()\n}\n\ninterface IBar {\n\tbar()\n}\n\n// implements only IFoo\nstruct SFoo {}\n\nfn (sf SFoo) foo() {}\n\n// implements both IFoo and IBar\nstruct SFooBar {}\n\nfn (sfb SFooBar) foo() {}\n\nfn (sfb SFooBar) bar() {\n\tdump('This implements IBar')\n}\n\nfn main() {\n\tmut arr := []IFoo{}\n\tarr << SFoo{}\n\tarr << SFooBar{}\n\n\tfor a in arr {\n\t\tdump(a)\n\t\t// In order to execute instances that implements IBar.\n\t\tif a is IBar {\n\t\t\ta.bar()\n\t\t}\n\t}\n}\n```\n\nFor more information, see [Dynamic casts](#dynamic-casts).\n\n#### Interface method definitions\n\nAlso unlike Go, an interface can have its own methods, similar to how\nstructs can have their methods. These 'interface methods' do not have\nto be implemented, by structs which implement that interface.\nThey are just a convenient way to write `i.some_function()` instead of\n`some_function(i)`, similar to how struct methods can be looked at, as\na convenience for writing `s.xyz()` instead of `xyz(s)`.\n\n> [!NOTE]\n> This feature is NOT a \"default implementation\" like in C#.\n\nFor example, if a struct `cat` is wrapped in an interface `a`, that has\nimplemented a method with the same name `speak`, as a method implemented by\nthe struct, and you do `a.speak()`, *only* the interface method is called:\n\n```v\ninterface Adoptable {}\n\nfn (a Adoptable) speak() string {\n\treturn 'adopt me!'\n}\n\nstruct Cat {}\n\nfn (c Cat) speak() string {\n\treturn 'meow!'\n}\n\nstruct Dog {}\n\nfn main() {\n\tcat := Cat{}\n\tassert dump(cat.speak()) == 'meow!'\n\n\ta := Adoptable(cat)\n\tassert dump(a.speak()) == 'adopt me!' // call Adoptable's `speak`\n\tif a is Cat {\n\t\t// Inside this `if` however, V knows that `a` is not just any\n\t\t// kind of Adoptable, but actually a Cat, so it will use the\n\t\t// Cat `speak`, NOT the Adoptable `speak`:\n\t\tdump(a.speak()) // meow!\n\t}\n\n\tb := Adoptable(Dog{})\n\tassert dump(b.speak()) == 'adopt me!' // call Adoptable's `speak`\n\t// if b is Dog {\n\t// \tdump(b.speak()) // error: unknown method or field: Dog.speak\n\t// }\n}\n```\n\n#### Embedded interface\n\nInterfaces support embedding, just like structs:\n\n```v\npub interface Reader {\nmut:\n\tread(mut buf []u8) ?int\n}\n\npub interface Writer {\nmut:\n\twrite(buf []u8) ?int\n}\n\n// ReaderWriter embeds both Reader and Writer.\n// The effect is the same as copy/pasting all of the\n// Reader and all of the Writer methods/fields into\n// ReaderWriter.\npub interface ReaderWriter {\n\tReader\n\tWriter\n}\n```\n\n### Sum types\n\nA sum type instance can hold a value of several different types. Use the `type`\nkeyword to declare a sum type:\n\n```v\nstruct Moon {}\n\nstruct Mars {}\n\nstruct Venus {}\n\ntype World = Mars | Moon | Venus\n\nsum := World(Moon{})\nassert sum.type_name() == 'Moon'\nprintln(sum)\n```\n\nThe built-in method `type_name` returns the name of the currently held\ntype.\n\nWith sum types you could build recursive structures and write concise but powerful code on them.\n\n```v\n// V's binary tree\nstruct Empty {}\n\nstruct Node {\n\tvalue f64\n\tleft  Tree\n\tright Tree\n}\n\ntype Tree = Empty | Node\n\n// sum up all node values\n\nfn sum(tree Tree) f64 {\n\treturn match tree {\n\t\tEmpty { 0 }\n\t\tNode { tree.value + sum(tree.left) + sum(tree.right) }\n\t}\n}\n\nfn main() {\n\tleft := Node{0.2, Empty{}, Empty{}}\n\tright := Node{0.3, Empty{}, Node{0.4, Empty{}, Empty{}}}\n\ttree := Node{0.5, left, right}\n\tprintln(sum(tree)) // 0.2 + 0.3 + 0.4 + 0.5 = 1.4\n}\n```\n\n#### Dynamic casts\n\nTo check whether a sum type instance holds a certain type, use `sum is Type`.\nTo cast a sum type to one of its variants you can use `sum as Type`:\n\n```v\nstruct Moon {}\n\nstruct Mars {}\n\nstruct Venus {}\n\ntype World = Mars | Moon | Venus\n\nfn (m Mars) dust_storm() bool {\n\treturn true\n}\n\nfn main() {\n\tmut w := World(Moon{})\n\tassert w is Moon\n\tw = Mars{}\n\t// use `as` to access the Mars instance\n\tmars := w as Mars\n\tif mars.dust_storm() {\n\t\tprintln('bad weather!')\n\t}\n}\n```\n\n`as` will panic if `w` doesn't hold a `Mars` instance.\nA safer way is to use a smart cast.\n\n#### Smart casting\n\n```v oksyntax\nif w is Mars {\n\tassert typeof(w).name == 'Mars'\n\tif w.dust_storm() {\n\t\tprintln('bad weather!')\n\t}\n}\n```\n\n`w` has type `Mars` inside the body of the `if` statement. This is\nknown as *flow-sensitive typing*.\nIf `w` is a mutable identifier, it would be unsafe if the compiler smart casts it without a warning.\nThat's why you have to declare a `mut` before the `is` expression:\n\n```v ignore\nif mut w is Mars {\n\tassert typeof(w).name == 'Mars'\n\tif w.dust_storm() {\n\t\tprintln('bad weather!')\n\t}\n}\n```\n\nOtherwise `w` would keep its original type.\n> This works for both simple variables and complex expressions like `user.name`\n\n#### Matching sum types\n\nYou can also use `match` to determine the variant:\n\n```v\nstruct Moon {}\n\nstruct Mars {}\n\nstruct Venus {}\n\ntype World = Mars | Moon | Venus\n\nfn open_parachutes(n int) {\n\tprintln(n)\n}\n\nfn land(w World) {\n\tmatch w {\n\t\tMoon {} // no atmosphere\n\t\tMars {\n\t\t\t// light atmosphere\n\t\t\topen_parachutes(3)\n\t\t}\n\t\tVenus {\n\t\t\t// heavy atmosphere\n\t\t\topen_parachutes(1)\n\t\t}\n\t}\n}\n```\n\n`match` must have a pattern for each variant or have an `else` branch.\n\n```v ignore\nstruct Moon {}\nstruct Mars {}\nstruct Venus {}\n\ntype World = Moon | Mars | Venus\n\nfn (m Moon) moon_walk() {}\nfn (m Mars) shiver() {}\nfn (v Venus) sweat() {}\n\nfn pass_time(w World) {\n    match w {\n        // using the shadowed match variable, in this case `w` (smart cast)\n        Moon { w.moon_walk() }\n        Mars { w.shiver() }\n        else {}\n    }\n}\n```\n\n### Option/Result types and error handling\n\nOption types can represent a value or `none`. Result types may\nrepresent a value, or an error returned from a function.\n\n`Option` types are declared by prepending `?` to the type name: `?Type`.\n`Result` types use `!`: `!Type`.\n\n```v\nstruct User {\n\tid   int\n\tname string\n}\n\nstruct Repo {\n\tusers []User\n}\n\nfn (r Repo) find_user_by_id(id int) !User {\n\tfor user in r.users {\n\t\tif user.id == id {\n\t\t\t// V automatically wraps this into a result or option type\n\t\t\treturn user\n\t\t}\n\t}\n\treturn error('User ${id} not found')\n}\n\n// A version of the function using an option\nfn (r Repo) find_user_by_id2(id int) ?User {\n\tfor user in r.users {\n\t\tif user.id == id {\n\t\t\treturn user\n\t\t}\n\t}\n\treturn none\n}\n\nfn main() {\n\trepo := Repo{\n\t\tusers: [User{1, 'Andrew'}, User{2, 'Bob'}, User{10, 'Charles'}]\n\t}\n\tuser := repo.find_user_by_id(10) or { // Option/Result types must be handled by `or` blocks\n\t\tprintln(err)\n\t\treturn\n\t}\n\tprintln(user.id) // \"10\"\n\tprintln(user.name) // \"Charles\"\n\n\tuser2 := repo.find_user_by_id2(10) or { return }\n\n\t// To create an Option var directly:\n\tmy_optional_int := ?int(none)\n\tmy_optional_string := ?string(none)\n\tmy_optional_user := ?User(none)\n}\n```\n\nV used to combine `Option` and `Result` into one type, now they are separate.\n\nThe amount of work required to \"upgrade\" a function to an option/result function is minimal;\nyou have to add a `?` or `!` to the return type and return `none` or an error (respectively)\nwhen something goes wrong.\n\nThis is the primary mechanism for error handling in V. They are still values, like in Go,\nbut the advantage is that errors can't be unhandled, and handling them is a lot less verbose.\nUnlike other languages, V does not handle exceptions with `throw/try/catch` blocks.\n\n`err` is defined inside an `or` block and is set to the string message passed\nto the `error()` function.\n\n```v oksyntax\nuser := repo.find_user_by_id(7) or {\n\tprintln(err) // \"User 7 not found\"\n\treturn\n}\n```\n\nUse `err is ...` to compare errors:\n```v oksyntax\nimport io\n\nx := read() or {\n\tif err is io.Eof {\n\t\tprintln('end of file')\n\t}\n\treturn\n}\n```\n\n#### Options/results when returning multiple values\n\nOnly one `Option` or `Result` is allowed to be returned from a function. It is\npossible to return multiple values and still signal an error.\n\n```v\nfn multi_return(v int) !(int, int) {\n\tif v < 0 {\n\t\treturn error('must be positive')\n\t}\n\treturn v, v * v\n}\n```\n\n#### Handling options/results\n\nThere are four ways of handling an option/result. The first method is to\npropagate the error:\n\n```v\nimport net.http\n\nfn f(url string) !string {\n\tresp := http.get(url)!\n\treturn resp.body\n}\n```\n\n`http.get` returns `!http.Response`. Because `!` follows the call, the\nerror will be propagated to the caller of `f`. When using `?` after a\nfunction call producing an option, the enclosing function must return\nan option as well. If error propagation is used in the `main()`\nfunction it will `panic` instead, since the error cannot be propagated\nany further.\n\nThe body of `f` is essentially a condensed version of:\n\n```v ignore\n    resp := http.get(url) or { return err }\n    return resp.body\n```\n\n---\nThe second method is to break from execution early:\n\n```v oksyntax\nuser := repo.find_user_by_id(7) or { return }\n```\n\nHere, you can either call `panic()` or `exit()`, which will stop the execution of the\nentire program, or use a control flow statement (`return`, `break`, `continue`, etc)\nto break from the current block.\n\n> [!NOTE]\n> `break` and `continue` can only be used inside a `for` loop.\n\nV does not have a way to forcibly \"unwrap\" an option (as other languages do,\nfor instance Rust's `unwrap()` or Swift's `!`). To do this, use `or { panic(err) }` instead.\n\n---\nThe third method is to provide a default value at the end of the `or` block.\nIn case of an error, that value would be assigned instead,\nso it must have the same type as the content of the `Option` being handled.\n\n```v\nfn do_something(s string) !string {\n\tif s == 'foo' {\n\t\treturn 'foo'\n\t}\n\treturn error('invalid string')\n}\n\na := do_something('foo') or { 'default' } // a will be 'foo'\nb := do_something('bar') or { 'default' } // b will be 'default'\nprintln(a)\nprintln(b)\n```\n\n---\nThe fourth method is to use `if` unwrapping:\n\n```v\nimport net.http\n\nif resp := http.get('https://google.com') {\n\tprintln(resp.body) // resp is a http.Response, not an option\n} else {\n\tprintln(err)\n}\n```\n\nAbove, `http.get` returns a `!http.Response`. `resp` is only in scope for the first\n`if` branch. `err` is only in scope for the `else` branch.\n\n### Custom error types\n\nV gives you the ability to define custom error types through the `IError` interface.\nThe interface requires two methods: `msg() string` and `code() int`. Every type that\nimplements these methods can be used as an error.\n\nWhen defining a custom error type it is recommended to embed the builtin `Error` default\nimplementation. This provides an empty default implementation for both required methods,\nso you only have to implement what you really need, and may provide additional utility\nfunctions in the future.\n\n```v\nstruct PathError {\n\tError\n\tpath string\n}\n\nfn (err PathError) msg() string {\n\treturn 'Failed to open path: ${err.path}'\n}\n\nfn try_open(path string) ! {\n\t// V automatically casts this to IError\n\treturn PathError{\n\t\tpath: path\n\t}\n}\n\nfn main() {\n\ttry_open('/tmp') or { panic(err) }\n}\n```\n\n### Generics\n\n```v wip\n\nstruct Repo[T] {\n    db DB\n}\n\nstruct User {\n\tid   int\n\tname string\n}\n\nstruct Post {\n\tid   int\n\tuser_id int\n\ttitle string\n\tbody string\n}\n\nfn new_repo[T](db DB) Repo[T] {\n    return Repo[T]{db: db}\n}\n\n// This is a generic function. V will generate it for every type it's used with.\nfn (r Repo[T]) find_by_id(id int) ?T {\n    table_name := T.name // in this example getting the name of the type gives us the table name\n    return r.db.query_one[T]('select * from ${table_name} where id = ?', id)\n}\n\ndb := new_db()\nusers_repo := new_repo[User](db) // returns Repo[User]\nposts_repo := new_repo[Post](db) // returns Repo[Post]\nuser := users_repo.find_by_id(1)? // find_by_id[User]\npost := posts_repo.find_by_id(1)? // find_by_id[Post]\n```\n\nCurrently generic function definitions must declare their type parameters, but in\nfuture versions, V will infer generic type parameters from single-letter type names in\nruntime parameter types. This is why the `find_by_id(1)` calls above can omit `[T]`,\nbecause the receiver argument `r` in the method declaration, uses a generic type `T`.\n\nAnother example:\n\n```v\nfn compare[T](a T, b T) int {\n\tif a < b {\n\t\treturn -1\n\t}\n\tif a > b {\n\t\treturn 1\n\t}\n\treturn 0\n}\n\n// compare[int]\nprintln(compare(1, 0)) // Outputs: 1\nprintln(compare(1, 1)) //          0\nprintln(compare(1, 2)) //         -1\n// compare[string]\nprintln(compare('1', '0')) // Outputs: 1\nprintln(compare('1', '1')) //          0\nprintln(compare('1', '2')) //         -1\n// compare[f64]\nprintln(compare(1.1, 1.0)) // Outputs: 1\nprintln(compare(1.1, 1.1)) //          0\nprintln(compare(1.1, 1.2)) //         -1\n```\n\n## Concurrency\n\n### Spawning Concurrent Tasks\n\nV's model of concurrency is similar to Go's.\n\n`go foo()` runs `foo()` concurrently in a lightweight thread managed by the V runtime.\n\n`spawn foo()` runs `foo()` concurrently in a different thread:\n\n```v\nimport math\n\nfn p(a f64, b f64) { // ordinary function without return value\n\tc := math.sqrt(a * a + b * b)\n\tprintln(c)\n}\n\nfn main() {\n\tspawn p(3, 4)\n\t// p will be run in parallel thread\n\t// It can also be written as follows\n\t// spawn fn (a f64, b f64) {\n\t// \tc := math.sqrt(a * a + b * b)\n\t// \tprintln(c)\n\t// }(3, 4)\n}\n```\n\n> [!NOTE]\n> Threads rely on the machine's CPU (number of cores/threads).\n> Be aware that OS threads spawned with `spawn`\n> have limitations in regard to concurrency,\n> including resource overhead and scalability issues,\n> and might affect performance in cases of high thread count.\n\nSometimes it is necessary to wait until a parallel thread has finished. This can\nbe done by assigning a *handle* to the started thread and calling the `wait()` method\nto this handle later:\n\n```v\nimport math\n\nfn p(a f64, b f64) { // ordinary function without return value\n\tc := math.sqrt(a * a + b * b)\n\tprintln(c) // prints `5`\n}\n\nfn main() {\n\th := spawn p(3, 4)\n\t// p() runs in parallel thread\n\th.wait()\n\t// p() has definitely finished\n}\n```\n\nThis approach can also be used to get a return value from a function that is run in a\nparallel thread. There is no need to modify the function itself to be able to call it\nconcurrently.\n\n```v\nimport math { sqrt }\n\nfn get_hypot(a f64, b f64) f64 { //       ordinary function returning a value\n\tc := sqrt(a * a + b * b)\n\treturn c\n}\n\nfn main() {\n\tg := spawn get_hypot(54.06, 2.08) // spawn thread and get handle to it\n\th1 := get_hypot(2.32, 16.74) //   do some other calculation here\n\th2 := g.wait() //                 get result from spawned thread\n\tprintln('Results: ${h1}, ${h2}') //   prints `Results: 16.9, 54.1`\n}\n```\n\nIf there is a large number of tasks, it might be easier to manage them\nusing an array of threads.\n\n```v\nimport time\n\nfn task(id int, duration int) {\n\tprintln('task ${id} begin')\n\ttime.sleep(duration * time.millisecond)\n\tprintln('task ${id} end')\n}\n\nfn main() {\n\tmut threads := []thread{}\n\tthreads << spawn task(1, 500)\n\tthreads << spawn task(2, 900)\n\tthreads << spawn task(3, 100)\n\tthreads.wait()\n\tprintln('done')\n}\n\n// Output:\n// task 1 begin\n// task 2 begin\n// task 3 begin\n// task 3 end\n// task 1 end\n// task 2 end\n// done\n```\n\nAdditionally for threads that return the same type, calling `wait()`\non the thread array will return all computed values.\n\n```v\nfn expensive_computing(i int) int {\n\treturn i * i\n}\n\nfn main() {\n\tmut threads := []thread int{}\n\tfor i in 1 .. 10 {\n\t\tthreads << spawn expensive_computing(i)\n\t}\n\t// Join all tasks\n\tr := threads.wait()\n\tprintln('All jobs finished: ${r}')\n}\n\n// Output: All jobs finished: [1, 4, 9, 16, 25, 36, 49, 64, 81]\n```\n\n### Channels\n\nChannels are the preferred way to communicate between threads. They allow threads to exchange data\nsafely without requiring explicit locking. V's channels are similar to those in Go, enabling you\nto push objects into a channel on one end and pop objects from the other.\nChannels can be buffered or unbuffered, and you can use the `select` statement to monitor multiple\nchannels simultaneously.\n\n#### Syntax and Usage\n\nChannels are declared with the type `chan objtype`.\nYou can optionally specify a buffer length using the `cap` field:\n\n```v\nch := chan int{} // unbuffered - \"synchronous\"\nch2 := chan f64{cap: 100} // buffered with a capacity of 100\n```\n\nChannels do not have to be declared as `mut`. The buffer length is not part of the type but\na field of the individual channel object. Channels can be passed to threads like normal\nvariables:\n\n```v\nimport time\n\nfn worker(ch chan int) {\n\tfor i in 0 .. 5 {\n\t\tch <- i // push values into the channel\n\t}\n}\n\nfn clock(ch chan int) {\n\tfor i in 0 .. 5 {\n\t\ttime.sleep(1 * time.second)\n\t\tprintln('Clock tick')\n\t\tch <- (i + 1000) // push a value into the channel\n\t}\n\tch.close() // close the channel when done\n}\n\nfn main() {\n\tch := chan int{cap: 5}\n\tspawn worker(ch)\n\tspawn clock(ch)\n\tfor {\n\t\tvalue := <-ch or { // receive/pop values from the channel\n\t\t\tprintln('Channel closed')\n\t\t\tbreak\n\t\t}\n\t\tprintln('Received: ${value}')\n\t}\n}\n```\n\n#### Buffered Channels\n\nBuffered channels allow you to push multiple items without blocking,\nas long as the buffer is not full:\n\n```v\nch := chan string{cap: 2}\nch <- 'hello'\nch <- 'world'\n// ch <- '!' // This would block because the buffer is full\n\nprintln(<-ch) // \"hello\"\nprintln(<-ch) // \"world\"\n```\n\n#### Closing Channels\n\nA channel can be closed to indicate that no further objects can be pushed. Any attempt\nto do so will then result in a runtime panic (with the exception of `select` and\n`try_push()` - see below). Attempts to pop will return immediately if the\nassociated channel has been closed and the buffer is empty. This situation can be\nhandled using an `or {}` block (see [Handling options/results](#handling-optionsresults)).\n\n```v wip\nch := chan int{}\nch2 := chan f64{}\n// ...\nch.close()\n// ...\nm := <-ch or {\n    println('channel has been closed')\n}\n\n// propagate error\ny := <-ch2 ?\n```\n\nNote: buffered channels can be closed while they have unread values in them.\nThe buffered values can be retrieved, even after the closing:\n```v\nich := chan int{cap: 5}\nfor i in 0 .. 5 {\n\tich <- i\n}\n\nfor _ in 0 .. 2 {\n\tx := <-ich or { break }\n\teprintln('>>  loop 0..2 | x: ${x} | ich.closed: ${ich.closed}')\n}\n\nich.close()\n\nfor {\n\tx := <-ich or { break }\n\teprintln('>> final loop | x: ${x} | ich.closed: ${ich.closed}')\n}\n```\n... will produce:\n```\n>>  loop 0..2 | x: 0 | ich.closed: false\n>>  loop 0..2 | x: 1 | ich.closed: false\n>> final loop | x: 2 | ich.closed: true\n>> final loop | x: 3 | ich.closed: true\n>> final loop | x: 4 | ich.closed: true\n```\n\nNote: reading from the .closed field of the channel in the example,\nis done just for clarity of illustration. The recommended way to pop values\nfrom the channel is with: `x := <-ich or { break }` in a `for` loop,\nwhich will cleanly break out of the loop, when the channel is closed and empty.\nAvoid manually checking, whether the channel was closed or not, because that\ncan introduce data races, if you are not careful.\n\n#### Channel Select\n\nThe `select` command allows monitoring several channels at the same time\nwithout noticeable CPU load. It consists of a list of possible transfers and associated branches\nof statements - similar to the [match](#match) command:\n\n```v\nimport time\n\nfn main() {\n\tch := chan f64{}\n\tch2 := chan f64{}\n\tch3 := chan f64{}\n\tmut b := 0.0\n\tc := 1.0\n\t// ... setup spawn threads that will send on ch/ch2\n\tspawn fn (the_channel chan f64) {\n\t\ttime.sleep(5 * time.millisecond)\n\t\tthe_channel <- 1.0\n\t}(ch)\n\tspawn fn (the_channel chan f64) {\n\t\ttime.sleep(1 * time.millisecond)\n\t\tthe_channel <- 1.0\n\t}(ch2)\n\tspawn fn (the_channel chan f64) {\n\t\t_ := <-the_channel\n\t}(ch3)\n\n\tselect {\n\t\ta := <-ch {\n\t\t\t// do something with `a`\n\t\t\teprintln('> a: ${a}')\n\t\t}\n\t\tb = <-ch2 {\n\t\t\t// do something with predeclared variable `b`\n\t\t\teprintln('> b: ${b}')\n\t\t}\n\t\tch3 <- c {\n\t\t\t// do something if `c` was sent\n\t\t\ttime.sleep(5 * time.millisecond)\n\t\t\teprintln('> c: ${c} was send on channel ch3')\n\t\t}\n\t\t500 * time.millisecond {\n\t\t\t// do something if no channel has become ready within 0.5s\n\t\t\teprintln('> more than 0.5s passed without a channel being ready')\n\t\t}\n\t}\n\teprintln('> done')\n}\n```\n\nThe timeout branch is optional. If it is absent `select` waits for an unlimited amount of time.\nIt is also possible to proceed immediately if no channel is ready in the moment `select` is called\nby adding an `else { ... }` branch. `else` and `<timeout>` are mutually exclusive.\n\nThe `select` command can be used as an *expression* of type `bool`\nthat becomes `false` if all channels are closed:\n\n```v wip\nif select {\n    ch <- a {\n        // ...\n    }\n} {\n    // channel was open\n} else {\n    // channel is closed\n}\n```\n\n#### Special Channel Features\n\nFor special purposes there are some builtin fields and methods:\n\n```v\nch := chan int{cap: 2}\nprintln(ch.try_push(42)) // `.success` if pushed, `.not_ready` if full, `.closed` if closed\nprintln(ch.len) // Number of items in the buffer\nprintln(ch.cap) // Buffer capacity\nprintln(ch.closed) // Whether the channel is closed\n```\n\n```v\nstruct Abc {\n\tx int\n}\n\na := 2.13\nch := chan f64{}\nres := ch.try_push(a) // try to perform `ch <- a`\nprintln(res)\nl := ch.len // number of elements in queue\nc := ch.cap // maximum queue length\nis_closed := ch.closed // bool flag - has `ch` been closed\nprintln(l)\nprintln(c)\nmut b := Abc{}\nch2 := chan Abc{}\nres2 := ch2.try_pop(mut b) // try to perform `b = <-ch2`\n```\n\nThe `try_push/pop()` methods will return immediately with one of the results\n`.success`, `.not_ready` or `.closed` - dependent on whether the object has been transferred or\nthe reason why not.\nUsage of these methods and fields in production is not recommended -\nalgorithms based on them are often subject to race conditions. Especially `.len` and\n`.closed` should not be used to make decisions.\nUse `or` branches, error propagation or `select` instead (see [Syntax and Usage](#syntax-and-usage)\nand [Channel Select](#channel-select) above).\n\n### Shared Objects\n\nData can be exchanged between a thread and the calling thread via a shared variable.\nSuch variables should be created as `shared` and passed to the thread as such, too.\nThe underlying `struct` contains a hidden *mutex* that allows locking concurrent access\nusing `rlock` for read-only and `lock` for read/write access.\n\nNote: Shared variables must be structs, arrays or maps.\n\n#### Example of Shared Objects\n\n```v\nstruct Counter {\nmut:\n\tvalue int\n}\n\nfn (shared counter Counter) increment() {\n\tlock counter {\n\t\tcounter.value += 1\n\t\tprintln('Incremented to: ${counter.value}')\n\t}\n}\n\nfn main() {\n\tshared counter := Counter{}\n\n\tspawn counter.increment()\n\tspawn counter.increment()\n\n\trlock counter {\n\t\tprintln('Final value: ${counter.value}')\n\t}\n}\n```\n\n### Difference Between Channels and Shared Objects\n\n**Purpose**:\n- Channels: Used for message passing between threads, ensuring safe communication.\n- Shared objects: Used for direct data sharing and modification between threads.\n\n**Synchronization**:\n- Channels: Implicit (via channel operations)\n- Shared objects:  Explicit (via `rlock`/`lock` blocks)\n\n## JSON\n\nBecause of the ubiquitous nature of JSON, support for it is built directly into V.\n\nV generates code for JSON encoding and decoding.\nNo runtime reflection is used. This results in much better performance.\n\n### Decoding JSON\n\n```v\nimport json\n\nstruct Foo {\n\tx int\n}\n\nstruct User {\n\t// Adding a [required] attribute will make decoding fail, if that\n\t// field is not present in the input.\n\t// If a field is not [required], but is missing, it will be assumed\n\t// to have its default value, like 0 for numbers, or '' for strings,\n\t// and decoding will not fail.\n\tname string @[required]\n\tage  int\n\t// Use the `@[skip]` attribute to skip certain fields.\n\t// You can also use `@[json: '-']`, and `@[sql: '-']`, which will cause only\n\t// the `json` module to skip the field, or only the SQL orm to skip it.\n\tfoo Foo @[skip]\n\t// If the field name is different in JSON, it can be specified\n\tlast_name string @[json: lastName]\n}\n\ndata := '{ \"name\": \"Frodo\", \"lastName\": \"Baggins\", \"age\": 25, \"nullable\": null }'\nuser := json.decode(User, data) or {\n\teprintln('Failed to decode json, error: ${err}')\n\treturn\n}\nprintln(user.name)\nprintln(user.last_name)\nprintln(user.age)\n// You can also decode JSON arrays:\nsfoos := '[{\"x\":123},{\"x\":456}]'\nfoos := json.decode([]Foo, sfoos)!\nprintln(foos[0].x)\nprintln(foos[1].x)\n```\n\nThe `json.decode` function takes two arguments:\nthe first is the type into which the JSON value should be decoded and\nthe second is a string containing the JSON data.\n\n### Encoding JSON\n\n```v\nimport json\n\nstruct User {\n\tname  string\n\tscore i64\n}\n\nmut data := map[string]int{}\nuser := &User{\n\tname:  'Pierre'\n\tscore: 1024\n}\n\ndata['x'] = 42\ndata['y'] = 360\n\nprintln(json.encode(data)) // {\"x\":42,\"y\":360}\nprintln(json.encode(user)) // {\"name\":\"Pierre\",\"score\":1024}\n```\n\nThe json module also supports anonymous struct fields, which helps with complex JSON apis with lots\nof levels.\n\n## Testing\n\n### Asserts\n\n```v\nfn foo(mut v []int) {\n\tv[0] = 1\n}\n\nmut v := [20]\nfoo(mut v)\nassert v[0] < 4\n```\n\nAn `assert` statement checks that its expression evaluates to `true`. If an assert fails,\nthe program will usually abort. Asserts should only be used to detect programming errors. When an\nassert fails it is reported to *stderr*, and the values on each side of a comparison operator\n(such as `<`, `==`) will be printed when possible. This is useful to easily find an\nunexpected value. Assert statements can be used in any function, not just test ones,\nwhich is handy when developing new functionality, to keep your invariants in check.\n\n> [!NOTE]\n> All `assert` statements are *removed*, when you compile your program with the `-prod` flag.\n\n### Asserts with an extra message\n\nThis form of the `assert` statement, will print the extra message when it fails. Note that\nyou can use any string expression there - string literals, functions returning a string,\nstrings that interpolate variables, etc.\n\n```v\nfn test_assertion_with_extra_message_failure() {\n\tfor i in 0 .. 100 {\n\t\tassert i * 2 - 45 < 75 + 10, 'assertion failed for i: ${i}'\n\t}\n}\n```\n\n### Asserts that do not abort your program\n\nWhen initially prototyping functionality and tests, it is sometimes desirable to\nhave asserts that do not stop the program, but just print their failures. That can\nbe achieved by tagging your assert containing functions with an `[assert_continues]`\ntag, for example running this program:\n\n```v\n@[assert_continues]\nfn abc(ii int) {\n\tassert ii == 2\n}\n\nfor i in 0 .. 4 {\n\tabc(i)\n}\n```\n\n... will produce this output:\n\n```\nassert_continues_example.v:3: FAIL: fn main.abc: assert ii == 2\n   left value: ii = 0\n   right value: 2\nassert_continues_example.v:3: FAIL: fn main.abc: assert ii == 2\n   left value: ii = 1\n  right value: 2\nassert_continues_example.v:3: FAIL: fn main.abc: assert ii == 2\n   left value: ii = 3\n  right value: 2\n```\n\n> [!NOTE]\n> V also supports a command line flag `-assert continues`, which will change the\n> behaviour of all asserts globally, as if you had tagged every function with `[assert_continues]`.\n\n### Test files\n\n```v\n// hello.v\nmodule main\n\nfn hello() string {\n\treturn 'Hello world'\n}\n\nfn main() {\n\tprintln(hello())\n}\n```\n\n```v failcompile\n// hello_test.v\nmodule main\n\nfn test_hello() {\n\tassert hello() == 'Hello world'\n}\n```\n\nTo run the test file above, use `v hello_test.v`. This will check that the function `hello` is\nproducing the correct output. V executes all test functions in the file.\n\n> [!NOTE]\n> All `_test.v` files (both external and internal ones), are compiled as *separate programs*.\n> In other words, you may have as many `_test.v` files, and tests in them as you like, they will\n> not affect the compilation of your other code in `.v` files normally at all, but only when you\n> do explicitly `v file_test.v` or `v test .`.\n\n* All test functions have to be inside a test file whose name ends in `_test.v`.\n* Test function names must begin with `test_` to mark them for execution.\n* Normal functions can also be defined in test files, and should be called manually. Other\n  symbols can also be defined in test files e.g. types.\n* There are two kinds of tests: external and internal.\n* Internal tests must *declare* their module, just like all other .v\n  files from the same module. Internal tests can even call private functions in\n  the same module.\n* External tests must *import* the modules which they test. They do not\n  have access to the private functions/types of the modules. They can test only\n  the external/public API that a module provides.\n\nIn the example above, `test_hello` is an internal test that can call\nthe private function `hello()` because `hello_test.v` has `module main`,\njust like `hello.v`, i.e. both are part of the same module. Note also that\nsince `module main` is a regular module like the others, internal tests can\nbe used to test private functions in your main program .v files too.\n\nYou can also define these special test functions in a test file:\n\n* `testsuite_begin` which will be run *before* all other test functions.\n* `testsuite_end` which will be run *after* all other test functions.\n\nIf a test function has an error return type, any propagated errors will fail the test:\n\n```v\nimport strconv\n\nfn test_atoi() ! {\n\tassert strconv.atoi('1')! == 1\n\tassert strconv.atoi('one')! == 1 // test will fail\n}\n```\n\n### Running tests\n\nTo run test functions in an individual test file, use `v foo_test.v`.\n\nTo test an entire module, use `v test mymodule`. You can also use `v test .` to test\neverything inside your current folder (and subfolders). You can pass the `-stats`\noption to see more details about the individual tests run.\n\nYou can put additional test data, including .v source files in a folder, named\n`testdata`, right next to your _test.v files. V's test framework will *ignore*\nsuch folders, while scanning for tests to run. This is useful, if you want to\nput .v files with invalid V source code, or other tests, including known\nfailing ones, that should be run in a specific way/options by a parent _test.v\nfile.\n\n> [!NOTE]\n> The path to the V compiler, is available through @VEXE, so a _test.v\n> file, can easily run *other* test files like this:\n\n```v oksyntax\nimport os\n\nfn test_subtest() {\n\tres := os.execute('${os.quoted_path(@VEXE)} other_test.v')\n\tassert res.exit_code == 1\n\tassert res.output.contains('other_test.v does not exist')\n}\n```\n\n## Memory management\n\nV avoids doing unnecessary allocations in the first place by using value types,\nstring buffers, promoting a simple abstraction-free code style.\n\nThere are 4 ways to manage memory in V.\n\nThe default is a minimal and a well performing tracing GC.\n\nThe second way is autofree, it can be enabled with `-autofree`. It takes care of most objects\n(~90-100%): the compiler inserts necessary free calls automatically during compilation.\nRemaining small percentage of objects is freed via GC. The developer doesn't need to change\nanything in their code. \"It just works\", like in Python, Go, or Java, except there's no\nheavy GC tracing everything or expensive RC for each object.\n\nFor developers willing to have more low-level control, memory can be managed manually with\n`-gc none`.\n\nArena allocation is available via a `-prealloc` flag. Note: currently this mode is only\nsuitable to speed up short lived, single-threaded, batch-like programs (like compilers).\n\n### Control\n\nYou can take advantage of V's autofree engine and define a `free()` method on custom\ndata types:\n\n```v\nstruct MyType {}\n\n@[unsafe]\nfn (data &MyType) free() {\n\t// ...\n}\n```\n\nJust as the compiler frees C data types with C's `free()`, it will statically insert\n`free()` calls for your data type at the end of each variable's lifetime.\n\nAutofree can be enabled with an `-autofree` flag.\n\nFor developers willing to have more low-level control, autofree can be disabled with\n`-manualfree`, or by adding a `[manualfree]` on each function that wants to manage its\nmemory manually. (See [attributes](#attributes)).\n\n> [!NOTE]\n> Autofree is still WIP. Until it stabilises and becomes the default, please\n> avoid using it. Right now allocations are handled by a minimal and well performing GC\n> until V's autofree engine is production ready.\n\n**Examples**\n\n```v\nimport strings\n\nfn draw_text(s string, x int, y int) {\n\t// ...\n}\n\nfn draw_scene() {\n\t// ...\n\tname1 := 'abc'\n\tname2 := 'def ghi'\n\tdraw_text('hello ${name1}', 10, 10)\n\tdraw_text('hello ${name2}', 100, 10)\n\tdraw_text(strings.repeat(`X`, 10000), 10, 50)\n\t// ...\n}\n```\n\nThe strings don't escape `draw_text`, so they are cleaned up when\nthe function exits.\n\nIn fact, with the `-prealloc` flag, the first two calls won't result in any allocations at all.\nThese two strings are small, so V will use a preallocated buffer for them.\n\n```v\nstruct User {\n\tname string\n}\n\nfn test() []int {\n\tnumber := 7 // stack variable\n\tuser := User{} // struct allocated on stack\n\tnumbers := [1, 2, 3] // array allocated on heap, will be freed as the function exits\n\tprintln(number)\n\tprintln(user)\n\tprintln(numbers)\n\tnumbers2 := [4, 5, 6] // array that's being returned, won't be freed here\n\treturn numbers2\n}\n```\n\n### Stack and Heap\n\n#### Stack and Heap Basics\n\nLike with most other programming languages there are two locations where data can\nbe stored:\n\n* The *stack* allows fast allocations with almost zero administrative overhead. The\n  stack grows and shrinks with the function call depth &ndash; so every called\n  function has its stack segment that remains valid until the function returns.\n  No freeing is necessary, however, this also means that a reference to a stack\n  object becomes invalid on function return. Furthermore stack space is\n  limited (typically to a few Megabytes per thread).\n* The *heap* is a large memory area (typically some Gigabytes) that is administrated\n  by the operating system. Heap objects are allocated and freed by special function\n  calls that delegate the administrative tasks to the OS. This means that they can\n  remain valid across several function calls, however, the administration is\n  expensive.\n\n#### V's default approach\n\nDue to performance considerations V tries to put objects on the stack if possible,\nbut allocates them on the heap when obviously necessary. Example:\n\n```v\nstruct MyStruct {\n\tn int\n}\n\nstruct RefStruct {\n\tr &MyStruct\n}\n\nfn main() {\n\tq, w := f()\n\tprintln('q: ${q.r.n}, w: ${w.n}')\n}\n\nfn f() (RefStruct, &MyStruct) {\n\ta := MyStruct{\n\t\tn: 1\n\t}\n\tb := MyStruct{\n\t\tn: 2\n\t}\n\tc := MyStruct{\n\t\tn: 3\n\t}\n\te := RefStruct{\n\t\tr: &b\n\t}\n\tx := a.n + c.n\n\tprintln('x: ${x}')\n\treturn e, &c\n}\n```\n\nHere `a` is stored on the stack since its address never leaves the function `f()`.\nHowever a reference to `b` is part of `e` which is returned. Also a reference to\n`c` is returned. For this reason `b` and `c` will be heap allocated.\n\nThings become less obvious when a reference to an object is passed as a function argument:\n\n```v\nstruct MyStruct {\nmut:\n\tn int\n}\n\nfn main() {\n\tmut q := MyStruct{\n\t\tn: 7\n\t}\n\tw := MyStruct{\n\t\tn: 13\n\t}\n\tx := q.f(&w) // references of `q` and `w` are passed\n\tprintln('q: ${q}\\nx: ${x}')\n}\n\nfn (mut a MyStruct) f(b &MyStruct) int {\n\ta.n += b.n\n\tx := a.n * b.n\n\treturn x\n}\n```\n\nHere the call `q.f(&w)` passes references to `q` and `w` because `a` is\n`mut` and `b` is of type `&MyStruct` in `f()`'s declaration, so technically\nthese references are leaving `main()`. However the *lifetime* of these\nreferences lies inside the scope of `main()` so `q` and `w` are allocated\non the stack.\n\n#### Manual Control for Stack and Heap\n\nIn the last example the V compiler could put `q` and `w` on the stack\nbecause it assumed that in the call `q.f(&w)` these references were only\nused for reading and modifying the referred values &ndash; and not to pass the\nreferences themselves somewhere else. This can be seen in a way that the\nreferences to `q` and `w` are only *borrowed* to `f()`.\n\nThings become different if `f()` is doing something with a reference itself:\n\n```v\nstruct RefStruct {\nmut:\n\tr &MyStruct\n}\n\n// see discussion below\n@[heap]\nstruct MyStruct {\n\tn int\n}\n\nfn main() {\n\tmut m := MyStruct{}\n\tmut r := RefStruct{\n\t\tr: &m\n\t}\n\tr.g()\n\tprintln('r: ${r}')\n}\n\nfn (mut r RefStruct) g() {\n\ts := MyStruct{\n\t\tn: 7\n\t}\n\tr.f(&s) // reference to `s` inside `r` is passed back to `main() `\n}\n\nfn (mut r RefStruct) f(s &MyStruct) {\n\tr.r = s // would trigger error without `[heap]`\n}\n```\n\nHere `f()` looks quite innocent but is doing nasty things &ndash; it inserts a\nreference to `s` into `r`. The problem with this is that `s` lives only as long\nas `g()` is running but `r` is used in `main()` after that. For this reason\nthe compiler would complain about the assignment in `f()` because `s` *\"might\nrefer to an object stored on stack\"*. The assumption made in `g()` that the call\n`r.f(&s)` would only borrow the reference to `s` is wrong.\n\nA solution to this dilemma is the `[heap]` [attribute](#attributes) at the declaration of\n`struct MyStruct`. It instructs the compiler to *always* allocate `MyStruct`-objects\non the heap. This way the reference to `s` remains valid even after `g()` returns.\nThe compiler takes into consideration that `MyStruct` objects are always heap\nallocated when checking `f()` and allows assigning the reference to `s` to the\n`r.r` field.\n\nThere is a pattern often seen in other programming languages:\n\n```v failcompile\nfn (mut a MyStruct) f() &MyStruct {\n\t// do something with a\n\treturn &a // would return address of borrowed object\n}\n```\n\nHere `f()` is passed a reference `a` as receiver that is passed back to the caller and returned\nas result at the same time. The intention behind such a declaration is method chaining like\n`y = x.f().g()`. However, the problem with this approach is that a second reference\nto `a` is created &ndash; so it is not only borrowed and `MyStruct` has to be\ndeclared as `[heap]`.\n\nIn V the better approach is:\n\n```v\nstruct MyStruct {\nmut:\n\tn int\n}\n\nfn (mut a MyStruct) f() {\n\t// do something with `a`\n}\n\nfn (mut a MyStruct) g() {\n\t// do something else with `a`\n}\n\nfn main() {\n\tx := MyStruct{} // stack allocated\n\tmut y := x\n\ty.f()\n\ty.g()\n\t// instead of `mut y := x.f().g()\n}\n```\n\nThis way the `[heap]` attribute can be avoided &ndash; resulting in better performance.\n\nHowever, stack space is very limited as mentioned above. For this reason the `[heap]`\nattribute might be suitable for very large structures even if not required by use cases\nlike those mentioned above.\n\nThere is an alternative way to manually control allocation on a case to case basis. This\napproach is not recommended but shown here for the sake of completeness:\n\n```v\nstruct MyStruct {\n\tn int\n}\n\nstruct RefStruct {\nmut:\n\tr &MyStruct\n}\n\n// simple function - just to overwrite stack segment previously used by `g()`\n\nfn use_stack() {\n\tx := 7.5\n\ty := 3.25\n\tz := x + y\n\tprintln('${x} ${y} ${z}')\n}\n\nfn main() {\n\tmut m := MyStruct{}\n\tmut r := RefStruct{\n\t\tr: &m\n\t}\n\tr.g()\n\tuse_stack() // to erase invalid stack contents\n\tprintln('r: ${r}')\n}\n\nfn (mut r RefStruct) g() {\n\ts := &MyStruct{ // `s` explicitly refers to a heap object\n\t\tn: 7\n\t}\n\t// change `&MyStruct` -> `MyStruct` above and `r.f(s)` -> `r.f(&s)` below\n\t// to see data in stack segment being overwritten\n\tr.f(s)\n}\n\nfn (mut r RefStruct) f(s &MyStruct) {\n\tr.r = unsafe { s } // override compiler check\n}\n```\n\nHere the compiler check is suppressed by the `unsafe` block. To make `s` be heap\nallocated even without `[heap]` attribute the `struct` literal is prefixed with\nan ampersand: `&MyStruct{...}`.\n\nThis last step would not be required by the compiler but without it the reference\ninside `r` becomes invalid (the memory area pointed to will be overwritten by\n`use_stack()`) and the program might crash (or at least produce an unpredictable\nfinal output). That's why this approach is *unsafe* and should be avoided!\n\n## ORM\n\n(This is still in an alpha state)\n\nV has a built-in ORM (object-relational mapping) which supports SQLite, MySQL and Postgres,\nbut soon it will support MS SQL and Oracle.\n\nV's ORM provides a number of benefits:\n\n- One syntax for all SQL dialects. (Migrating between databases becomes much easier.)\n- Queries are constructed using V's syntax. (There's no need to learn another syntax.)\n- Safety. (All queries are automatically sanitised to prevent SQL injection.)\n- Compile time checks. (This prevents typos which can only be caught during runtime.)\n- Readability and simplicity. (You don't need to manually parse the results of a query and\n  then manually construct objects from the parsed results.)\n\n```v\nimport db.sqlite\n\n// sets a custom table name. Default is struct name (case-sensitive)\n@[table: 'customers']\nstruct Customer {\n\tid        int @[primary; serial] // a field named `id` of integer type must be the first field\n\tname      string\n\tnr_orders int\n\tcountry   ?string\n}\n\ndb := sqlite.connect('customers.db')!\n\n// You can create tables from your struct declarations. For example the next query will issue SQL similar to this:\n// CREATE TABLE IF NOT EXISTS `Customer` (\n//      `id` INTEGER PRIMARY KEY,\n//      `name` TEXT NOT NULL,\n//      `nr_orders` INTEGER NOT NULL,\n//      `country` TEXT\n// )\nsql db {\n\tcreate table Customer\n}!\n\n// insert a new customer:\nnew_customer := Customer{\n\tname:      'Bob'\n\tcountry:   'uk'\n\tnr_orders: 10\n}\nsql db {\n\tinsert new_customer into Customer\n}!\n\nus_customer := Customer{\n\tname:      'Martin'\n\tcountry:   'us'\n\tnr_orders: 5\n}\nsql db {\n\tinsert us_customer into Customer\n}!\n\nnone_country_customer := Customer{\n\tname:      'Dennis'\n\tcountry:   none\n\tnr_orders: 2\n}\nsql db {\n\tinsert none_country_customer into Customer\n}!\n\n// update a customer:\nsql db {\n\tupdate Customer set nr_orders = nr_orders + 1 where name == 'Bob'\n}!\n\n// select count(*) from customers\nnr_customers := sql db {\n\tselect count from Customer\n}!\nprintln('number of all customers: ${nr_customers}')\n\n// V's syntax can be used to build queries:\nuk_customers := sql db {\n\tselect from Customer where country == 'uk' && nr_orders > 0 order by id desc limit 10\n}!\nprintln('We found a total of ${uk_customers.len} customers matching the query.')\nfor c in uk_customers {\n\tprintln('customer: ${c.id}, ${c.name}, ${c.country}, ${c.nr_orders}')\n}\n\nnone_country_customers := sql db {\n\tselect from Customer where country is none\n}!\nprintln('We found a total of ${none_country_customers.len} customers, with no country set.')\nfor c in none_country_customers {\n\tprintln('customer: ${c.id}, ${c.name}, ${c.country}, ${c.nr_orders}')\n}\n\n// delete a customer\nsql db {\n\tdelete from Customer where name == 'Bob'\n}!\n```\n\nFor more examples and the docs, see [vlib/orm](https://github.com/vlang/v/tree/master/vlib/orm).\n\n### Troubleshooting compilation problems with SQLite\n\nOn **any platform** (Windows, Linux, macOS), you can run:\n\n`v vlib/db/sqlite/install_thirdparty_sqlite.vsh`\n\nThis downloads the SQLite amalgamation source and places it in\n`v/thirdparty/sqlite`. V will then compile it automatically\nduring your build.\n\nOn **Linux**, you can also install the system development package\ninstead:\n\n- Debian/Ubuntu: `sudo apt install -y libsqlite3-dev`\n- Fedora/RHEL: `sudo dnf -y install sqlite-devel`\n- Arch: `sudo pacman -S sqlite`\n\n### Using the self contained SQLite module\nV also maintains a separate `sqlite` module, that wraps an SQLite amalgamation, but otherwise\nhas the same API as the `db.sqlite` module. Its benefit, is that with it, you do not need to\ninstall a separate system level sqlite package/library on your system (which can be hard on\nsome systems like windows, or systems with musl for example).\nIts negative is that it can make your compilations a bit slower (since it compiles SQLite\nfrom C, in addition to your own code).\n\nTo use it, do:\n```sh\nv install sqlite\n```\nand later, in your code, use this:\n```v ignore\nimport sqlite\n```\ninstead of:\n```v ignore\nimport db.sqlite\n```\n\n## Writing Documentation\n\nThe way it works is very similar to Go. It's very simple: there's no need to\nwrite documentation separately for your code,\nvdoc will generate it from docstrings in the source code.\n\nDocumentation for each function/type/const must be placed right before the declaration:\n\n```v\n// clearall clears all bits in the array\nfn clearall() {\n}\n```\n\nThe comment must start with the name of the definition.\n\nSometimes one line isn't enough to explain what a function does, in that case comments should\nspan to the documented function using single line comments:\n\n```v\n// copy_all recursively copies all elements of the array by their value,\n// if `dupes` is false all duplicate values are eliminated in the process.\nfn copy_all(dupes bool) {\n\t// ...\n}\n```\n\nBy convention it is preferred that comments are written in *present tense*.\n\nAn overview of the module must be placed in the first comment right after the module's name.\n\nTo generate documentation use vdoc, for example `v doc net.http`.\n\n### Newlines in Documentation Comments\n\nComments spanning multiple lines are merged together using spaces, unless\n\n- the line is empty\n- the line is purely of at least 3 of `-`, `=`, `_`, `*`, `~` (horizontal rule)\n- the line starts with at least one `#` followed by a space (header)\n- the line starts and ends with a `|` (table)\n- the line starts with `- ` (list)\n\n## Tools\n\n### v fmt\n\nYou don't need to worry about formatting your code or setting style guidelines.\n`v fmt` takes care of that:\n\n```shell\nv fmt file.v\n```\n\nIt's recommended to set up your editor, so that `v fmt -w` runs on every save.\nA vfmt run is usually pretty cheap (takes <30ms).\n\nAlways run `v fmt -w file.v` before pushing your code.\n\n#### Disabling the formatting locally\n\nTo disable formatting for a block of code, wrap it with `// vfmt off` and\n`// vfmt on` comments.\n\n```bash\n// Not affected by fmt\n// vfmt off\n\n... your code here ...\n\n// vfmt on\n\n// Affected by fmt\n... your code here ...\n```\n\n### v shader\n\nYou can use GPU shaders with V graphical apps. You write your shaders in an\n[annotated GLSL dialect](https://github.com/vlang/v/blob/master/examples/sokol/02_cubes_glsl/cube_glsl.glsl)\nand use `v shader` to compile them for all supported target platforms.\n\n```shell\nv shader /path/to/project/dir/or/file.v\n```\n\nCurrently you need to\n[include a header and declare a glue function](https://github.com/vlang/v/blob/master/examples/sokol/02_cubes_glsl/cube_glsl.v#L25-L28)\nbefore using the shader in your code.\n\n### Profiling\n\nV has good support for profiling your programs: `v -profile profile.txt run file.v`\nThat will produce a profile.txt file, which you can then analyze.\n\nThe generated profile.txt file will have lines with 4 columns:\n\n1. How many times a function was called.\n2. How much time in total a function took (in ms).\n3. How much time a function took (in ms), on its own, without the calls inside it.\n   It is reliable for multithreaded programs, when tcc is not used.\n4. How much time on average, a call to a function took (in ns).\n5. The name of the v function.\n\nYou can sort on column 3 (average time per function) using:\n`sort -n -k3 profile.txt|tail`\n\nYou can also use stopwatches to measure just portions of your code explicitly:\n\n```v\nimport time\n\nfn main() {\n\tsw := time.new_stopwatch()\n\tprintln('Hello world')\n\tprintln('Greeting the world took: ${sw.elapsed().nanoseconds()}ns')\n}\n```\n\n## Package management\n\nA V *module* is a single folder with .v files inside. A V *package* can\ncontain one or more V modules. A V *package* should have a `v.mod` file\nat its top folder, describing the contents of the package.\n\nV packages are installed normally in your `~/.vmodules` folder. That\nlocation can be overridden by setting the env variable `VMODULES`.\n\n### Package commands\n\nYou can use the V frontend to do package operations, just like you can\nuse it for compiling code, formatting code, vetting code etc.\n\n```powershell\nv [package_command] [param]\n```\n\nwhere a package command can be one of:\n\n```\n   install           Install a package from VPM.\n   remove            Remove a package that was installed from VPM.\n   search            Search for a package from VPM.\n   update            Update an installed package from VPM.\n   upgrade           Upgrade all the outdated packages.\n   list              List all installed packages.\n   outdated          Show installed packages that need updates.\n```\n\nYou can install packages already created by someone else with [VPM](https://vpm.vlang.io/):\n\n```powershell\nv install [package]\n```\n\n**Example:**\n\n```powershell\nv install ui\n```\n\nPackages can be installed directly from git or mercurial repositories.\n\n```powershell\nv install [--once] [--git|--hg] [url]\n```\n\n**Example:**\n\n```powershell\nv install --git https://github.com/vlang/markdown\n```\n\nSometimes you may want to install the dependencies **ONLY** if those are not installed:\n\n```\nv install --once [package]\n```\n\nRemoving a package with v:\n\n```powershell\nv remove [package]\n```\n\n**Example:**\n\n```powershell\nv remove ui\n```\n\nUpdating an installed package from [VPM](https://vpm.vlang.io/):\n\n```powershell\nv update [package]\n```\n\n**Example:**\n\n```powershell\nv update ui\n```\n\nOr you can update all your packages:\n\n```powershell\nv update\n```\n\nTo see all the packages you have installed, you can use:\n\n```powershell\nv list\n```\n\n**Example:**\n\n```powershell\n> v list\nInstalled packages:\n  markdown\n  ui\n```\n\nTo see all the packages that need updates:\n\n```powershell\nv outdated\n```\n\n**Example:**\n\n```powershell\n> v outdated\nPackage are up to date.\n```\n\n### Publish package\n\n1. Put a `v.mod` file inside the toplevel folder of your package (if you\n   created your package with the command `v new mypackage` or `v init`\n   you already have a `v.mod` file).\n\n   ```sh\n   v new mypackage\n   Input your project description: My nice package.\n   Input your project version: (0.0.0) 0.0.1\n   Input your project license: (MIT)\n   Initialising ...\n   Complete!\n   ```\n\n   Example `v.mod`:\n   ```v ignore\n   Module {\n       name: 'mypackage'\n       description: 'My nice package.'\n       version: '0.0.1'\n       license: 'MIT'\n       dependencies: []\n   }\n   ```\n\n   Minimal file structure:\n   ```\n   v.mod\n   mypackage.v\n   ```\n\n   The name of your package should be used with the `module` directive\n   at the top of all files in your package. For `mypackage.v`:\n   ```v\n   module mypackage\n\n   pub fn hello_world() {\n       println('Hello World!')\n   }\n   ```\n\n2. Create a git repository in the folder with the `v.mod` file\n   (this is not required if you used `v new` or `v init`):\n   ```sh\n   git init\n   git add .\n   git commit -m \"INIT\"\n   ````\n\n3. Create a public repository on github.com.\n4. Connect your local repository to the remote repository and push the changes.\n5. Add your package to the public V package registry VPM:\n   https://vpm.vlang.io/new\n\n   You will have to login with your Github account to register the package.\n   **Warning:** _Currently it is not possible to edit your entry after submitting.\n   Check your package name and github url twice as this cannot be changed by you later._\n6. The final package name is a combination of your github account and\n   the package name you provided e.g. `mygithubname.mypackage`.\n\n**Optional:** tag your V package with `vlang` and `vlang-package` on github.com\nto allow for a better search experience.\n\n# Advanced Topics\n\n## Attributes\n\nV has several attributes that modify the behavior of functions and structs.\n\nAn attribute is a compiler instruction specified inside `[]` right before a\nfunction/struct/enum declaration and applies only to the following declaration.\nAttributes with arguments support both `name: value` and call-style `name(value)` syntax.\nCall-style attributes can also use named arguments.\n\n```v\n// @[flag] enables Enum types to be used as bitfields\n\n@[flag]\nenum BitField {\n\tread\n\twrite\n\tother\n}\n\nfn main() {\n\tassert 1 == int(BitField.read)\n\tassert 2 == int(BitField.write)\n\tmut bf := BitField.read\n\tassert bf.has(.read | .other) // test if *at least one* of the flags is set\n\tassert !bf.all(.read | .other) // test if *all* of the flags are set\n\tbf.set(.write | .other)\n\tassert bf.has(.read | .write | .other)\n\tassert bf.all(.read | .write | .other)\n\tbf.toggle(.other)\n\tassert bf == BitField.read | .write\n\tassert bf.all(.read | .write)\n\tassert !bf.has(.other)\n\tempty := BitField.zero()\n\tassert empty.is_empty()\n\tassert !empty.has(.read)\n\tassert !empty.has(.write)\n\tassert !empty.has(.other)\n\tmut full := empty\n\tfull.set_all()\n\tassert int(full) == 7 // 0x01 + 0x02 + 0x04\n\tassert full == .read | .write | .other\n\tmut v := full\n\tv.clear(.read | .other)\n\tassert v == .write\n\tv.clear_all()\n\tassert v == empty\n\tassert BitField.read == BitField.from('read')!\n\tassert BitField.other == BitField.from('other')!\n\tassert BitField.write == BitField.from(2)!\n\tassert BitField.zero() == BitField.from('')!\n}\n```\n\n```v\n// @[_allow_multiple_values] allows an enum to have multiple duplicate values.\n// Use it carefully, only when you really need it.\n\n@[_allow_multiple_values]\nenum ButtonStyle {\n\tprimary   = 1\n\tsecondary = 2\n\tsuccess   = 3\n\n\tblurple = 1\n\tgrey    = 2\n\tgray    = 2\n\tgreen   = 3\n}\n\nfn main() {\n\tassert int(ButtonStyle.primary) == 1\n\tassert int(ButtonStyle.blurple) == 1\n\n\tassert int(ButtonStyle.secondary) == 2\n\tassert int(ButtonStyle.gray) == 2\n\tassert int(ButtonStyle.grey) == 2\n\n\tassert int(ButtonStyle.success) == 3\n\tassert int(ButtonStyle.green) == 3\n\n\tassert ButtonStyle.primary == ButtonStyle.blurple\n\tassert ButtonStyle.secondary == ButtonStyle.grey\n\tassert ButtonStyle.secondary == ButtonStyle.gray\n\tassert ButtonStyle.success == ButtonStyle.green\n}\n```\n\nStruct field deprecations:\n\n```v oksyntax\nmodule abc\n\n// Note that only *direct* accesses to Xyz.d in *other modules*, will produce deprecation notices/warnings:\npub struct Xyz {\npub mut:\n\ta int\n\td int @[deprecated: 'use Xyz.a instead'; deprecated_after: '2999-03-01']\n\t// the tags above, will produce a notice, since the deprecation date is in the far future\n}\n```\n\nFunction/method deprecations:\n\nFunctions are deprecated before they are finally removed to give users time to migrate their code.\nAdding a date is preferable in most cases. An immediate change, without a deprecation date, may be\nused for functions that are found to be conceptually broken and obsoleted by much better\nfunctionality. Other than that setting a date is advisable to grant users a grace period.\n\nDeprecated functions cause warnings, which cause errors if built with `-prod`. To avoid immediate\nCI breakage, it is advisable to set a future date, ahead of the date when the code is merged. This\ngives people who actively developed V projects, the chance to see the deprecation notice at least\nonce and fix the uses. Setting a date in the next 30 days, assumes they would have compiled their\nprojects manually at least once, within that time. For small changes, this should be plenty\nof time. For complex changes, this time may need to be longer.\n\nDifferent V projects and maintainers may reasonably choose different deprecation policies.\nDepending on the type and impact of the change, you may want to consult with them first, before\ndeprecating a function.\n\n\n```v nofmt\n// Calling this function will result in a deprecation warning\n@[deprecated]\nfn old_function() {}\n\n// It can also display a custom deprecation message\n@[deprecated: 'use new_function() instead']\nfn legacy_function() {}\n\n// Equivalent call-style syntax:\n@[deprecated('use new_function() instead')]\nfn legacy_function_call_style() {}\n\n// You can also specify a date, after which the function will be\n// considered deprecated. Before that date, calls to the function\n// will be compiler notices - you will see them, but the compilation\n// is not affected. After that date, calls will become warnings,\n// so ordinary compiling will still work, but compiling with -prod\n// will not (all warnings are treated like errors with -prod).\n// 6 months after the deprecation date, calls will be hard\n// compiler errors.\n\n@[deprecated: 'use new_function2() instead']\n@[deprecated_after: '2021-05-27']\nfn legacy_function2() {}\n\n// Equivalent call-style syntax:\n@[deprecated(msg: 'use new_function2() instead', after: '2021-05-27')]\nfn legacy_function2_call_style() {}\n```\n\n```v globals\n// This function's calls will be inlined.\n@[inline]\nfn inlined_function() {\n}\n\n// This function's calls will NOT be inlined.\n@[noinline]\nfn function() {\n}\n\n// Calls to this function in const and enum expressions can be evaluated at compile time,\n// when all call arguments are compile-time constants.\n@[comptime]\nfn make_mask(value u32, shift u32) u32 {\n\treturn value << shift\n}\n\n// This function will NOT return to its callers.\n// Such functions can be used at the end of or blocks,\n// just like exit/1 or panic/1. Such functions can not\n// have return types, and should end either in for{}, or\n// by calling other `[noreturn]` functions.\n@[noreturn]\nfn forever() {\n\tfor {}\n}\n\n// The following struct must be allocated on the heap. Therefore, it can only be used as a\n// reference (`&Window`) or inside another reference (`&OuterStruct{ Window{...} }`).\n// See section \"Stack and Heap\"\n@[heap]\nstruct Window {\n}\n\n// Calls to following function must be in unsafe{} blocks.\n// Note that the code in the body of `risky_business()` will still be\n// checked, unless you also wrap it in `unsafe {}` blocks.\n// This is useful, when you want to have an `[unsafe]` function that\n// has checks before/after a certain unsafe operation, that will still\n// benefit from V's safety features.\n@[unsafe]\nfn risky_business() {\n\t// code that will be checked, perhaps checking pre conditions\n\tunsafe {\n\t\t// code that *will not be* checked, like pointer arithmetic,\n\t\t// accessing union fields, calling other `[unsafe]` fns, etc...\n\t\t// Usually, it is a good idea to try minimizing code wrapped\n\t\t// in unsafe{} as much as possible.\n\t\t// See also [Memory-unsafe code](#memory-unsafe-code)\n\t}\n\t// code that will be checked, perhaps checking post conditions and/or\n\t// keeping invariants\n}\n\n// V's autofree engine will not take care of memory management in this function.\n// You will have the responsibility to free memory manually yourself in it.\n// Note: it is NOT related to the garbage collector. It will only make the\n// -autofree mechanism, ignore the body of that function.\n@[manualfree]\nfn custom_allocations() {\n}\n\n// The memory pointed to by the pointer arguments of this function will not be\n// freed by the garbage collector (if in use) before the function returns\n// For C interop only.\n@[keep_args_alive]\nfn C.my_external_function(voidptr, int, voidptr) int\n\n// A @[weak] tag tells the C compiler, that the next declaration will be weak, i.e. when linking,\n// if there is another declaration of a symbol with the same name (a 'strong' one), it should be\n// used instead, *without linker errors about duplicate symbols*.\n// For C interop only.\n\n@[weak]\n__global abc = u64(1)\n\n// Tell V, that the following global was defined on the C side,\n// thus V will not initialise it, but will just give you access to it.\n// For C interop only.\n\n@[c_extern]\n__global my_instance C.my_struct\nstruct C.my_struct {\n\ta int\n\tb f64\n}\n\n// Tell V that the following struct is defined with `typedef struct` in C.\n// For C interop only.\n@[typedef]\npub struct C.Foo {}\n\n// Used to add a custom calling convention to a function, available calling convention: stdcall, fastcall and cdecl.\n// This list also applies for type aliases (see below).\n// For C interop only.\n@[callconv: 'stdcall']\nfn C.DefWindowProc(hwnd int, msg int, lparam int, wparam int)\n\n// Used to add a custom calling convention to a function type aliases.\n// For C interop only.\n\n@[callconv: 'fastcall']\ntype FastFn = fn (int) bool\n\n// Calls to the following function, will have to use its return value somehow.\n// Ignoring it, will emit warnings.\n@[must_use]\nfn f() int {\n\treturn 42\n}\n\nfn g() {\n\t// just calling `f()` here, will produce a warning\n\tprintln(f()) // this is fine, because the return value was used as an argument\n}\n\n// Windows only (and obsolete; instead of it, use `-subsystem windows` when compiling)\n// Without this attribute all graphical apps will have the following behavior on Windows:\n// If run from a console or terminal; keep the terminal open so all (e)println statements can be viewed.\n// If run from e.g. Explorer, by double-click; app is opened, but no terminal is opened, and no\n// (e)println output can be seen.\n// Use it to force-open a terminal to view output in, even if the app is started from Explorer.\n// Valid before main() only.\n@[console]\nfn main() {\n}\n```\n\n## Conditional compilation\n\nThe goal of this feature, is to tell V to *not compile* a function, and all its calls, in the final\nexecutable, if a provided custom flag is not passed.\n\nV will still type check the function and all its calls, *even* if they will not be present in the\nfinal executable, due to the passed -d flags.\n\nIn order to see it in action, run the following example with `v run example.v` once,\nand then a second time with `v -d trace_logs run example.v`:\n```v\n@[if trace_logs ?]\nfn elog(s string) {\n\teprintln(s)\n}\n\nfn main() {\n\telog('some expression: ${2 + 2}') // such calls will not be done *at all*, if `-d trace_logs` is not passed\n\tprintln('hi')\n\telog('finish')\n}\n```\n\nConditional compilation, based on custom flags, can also be used to produce slightly different\nexecutables, which share the majority of the same code, but where some of the logic, is needed\nonly some of the time, for example a network server/client program can be written like so:\n```v ignore\nfn act_as_client() { ... }\nfn act_as_server() { ... }\nfn main() {\n\t$if as_client ? {\n\t\tact_as_client()\n\t}\n\t$if as_server ? {\n\t\tact_as_server()\n\t}\n}\n```\nTo generate a `client.exe` executable do: `v -d as_client -o client.exe .`\nTo generate a `server.exe` executable do: `v -d as_server -o server.exe .`\n\n### Compile time pseudo variables\n\nV also gives your code access to a set of pseudo string variables,\nthat are substituted at compile time:\n\n- `@FN` => replaced with the name of the current V function.\n- `@METHOD` => replaced with ReceiverType.MethodName.\n- `@MOD` => replaced with the name of the current V module.\n- `@STRUCT` => replaced with the name of the current V struct.\n- `@FILE` => replaced with the absolute path of the V source file.\n- `@DIR` => replaced with the absolute path of the *folder*, where the V source file is.\n- `@LINE` => replaced with the V line number where it appears (as a string).\n- `@FILE_LINE` => like `@FILE:@LINE`, but the file part is a relative path.\n- `@LOCATION` => file, line and name of the current type + method; suitable for logging.\n- `@COLUMN` => replaced with the column where it appears (as a string).\n- `@VEXE` => replaced with the path to the V compiler.\n- `@VEXEROOT`  => will be substituted with the *folder*,\n  where the V executable is (as a string).\n- `@VHASH`  => replaced with the shortened commit hash of the V compiler (as a string).\n- `@VCURRENTHASH` => Similar to `@VHASH`, but changes when the compiler is\n  recompiled on a different commit (after local modifications, or after\n  using git bisect etc).\n- `@VMOD_FILE` => replaced with the contents of the nearest v.mod file (as a string).\n- `@VMODHASH` => is replaced by the shortened commit hash, derived from the .git directory\n  next to the nearest v.mod file (as a string).\n- `@VMODROOT` => will be substituted with the *folder*,\n  where the nearest v.mod file is (as a string).\n- `@BUILD_DATE` => replaced with the build date, for example '2024-09-13' .\n- `@BUILD_TIME` => replaced with the build time, for example '12:32:07' .\n- `@BUILD_TIMESTAMP` => replaced with the build timestamp, for example '1726219885' .\n- `@OS` => replaced with the OS type, for example 'linux' .\n- `@CCOMPILER` => replaced with the C compiler type, for example 'gcc' .\n- `@BACKEND` => replaced with current language backend, for example 'c' or 'golang' .\n- `@PLATFORM` => replaced with the platform type, for example 'amd64' .\n\nNote: `@BUILD_DATE`, `@BUILD_TIME`, `@BUILD_TIMESTAMP` represent times in the UTC timezone.\nBy default, they are based on the current time of the compilation/build. They can be overridden\nby setting the environment variable `SOURCE_DATE_EPOCH`. That is also useful while making\nreleases, since you can use the equivalent of this in your build system/script:\n`export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) ;` , and then use `@BUILD_DATE` etc.,\ninside your program, when you for example print your version information to users.\nSee also https://reproducible-builds.org/docs/source-date-epoch/ .\n\nThe compile time pseudo variables allow you to do the following\nexample, which is useful while debugging/logging/tracing your code:\n\n```v\neprintln(@LOCATION)\n```\n\nAnother example, is if you want to embed the version/name from v.mod *inside* your executable:\n\n```v ignore\nimport v.vmod\n\nvm := vmod.decode( @VMOD_FILE )!\neprintln('${vm.name} ${vm.version}\\n${vm.description}')\n```\n\nA program that prints its own source code (a quine):\n```v\nprint($embed_file(@FILE).to_string())\n```\n\n> [!NOTE]\n> you can have arbitrary source code in the file, without problems, since the full file\n> will be embedded into the executable, produced by compiling it. Also note that printing\n> is done with `print` and not `println`, to not add another new line, missing in the\n> source code.\n\nA program that prints the time when it was built:\n```v\nimport time\n\nprintln('This program, was compiled at ${time.unix(@BUILD_TIMESTAMP.i64()).format_ss_milli()} .')\n```\n\n### Compile time reflection\n\n`$` is used as a prefix for compile time (also referred to as 'comptime') operations.\n\nHaving built-in JSON support is nice, but V also allows you to create efficient\nserializers for any data format. V has compile time `if` and `for` constructs:\n\n#### <h4 id=\"comptime-fields\">.fields</h4>\n\nYou can iterate over struct fields using `.fields`, it also works with generic types\n(e.g. `T.fields`) and generic arguments (e.g. `param.fields` where `fn gen[T](param T) {`).\n\n```v\nstruct User {\n\tname string\n\tage  int\n}\n\nfn main() {\n\t$for field in User.fields {\n\t\t$if field.typ is string {\n\t\t\tprintln('${field.name} is of type string')\n\t\t}\n\t}\n}\n\n// Output:\n// name is of type string\n```\n\n#### <h4 id=\"comptime-values\">.values</h4>\n\nYou can read [Enum](#enums) values and their attributes.\n\n```v\nenum Color {\n\tred   @[RED]  // first attribute\n\tblue  @[BLUE] // second attribute\n}\n\nfn main() {\n\t$for e in Color.values {\n\t\tprintln(e.name)\n\t\tprintln(e.attrs)\n\t}\n}\n\n// Output:\n// red\n// ['RED']\n// blue\n// ['BLUE']\n```\n\n#### <h4 id=\"comptime-attrs\">.attributes</h4>\n\nYou can read [Struct](#structs) attributes.\n\n```v\n@[COLOR]\nstruct Foo {\n\ta int\n}\n\nfn main() {\n\t$for e in Foo.attributes {\n\t\tprintln(e)\n\t}\n}\n\n// Output:\n// StructAttribute{\n//    name: 'COLOR'\n//    has_arg: false\n//    arg: ''\n//    kind: plain\n// }\n```\n\n#### <h4 id=\"comptime-variants\">.variants</h4>\n\nYou can read variant types from [Sum type](#sum-types).\n\n```v\ntype MySum = int | string\n\nfn main() {\n\t$for v in MySum.variants {\n\t\t$if v.typ is int {\n\t\t\tprintln('has int type')\n\t\t} $else $if v.typ is string {\n\t\t\tprintln('has string type')\n\t\t}\n\t}\n}\n\n// Output:\n// has int type\n// has string type\n```\n\n#### <h4 id=\"comptime-methods\">.methods</h4>\n\nYou can retrieve information about struct methods.\n\n```v\nstruct Foo {\n}\n\nfn (f Foo) test() int {\n\treturn 123\n}\n\nfn (f Foo) test2() string {\n\treturn 'foo'\n}\n\nfn main() {\n\tfoo := Foo{}\n\t$for m in Foo.methods {\n\t\t$if m.return_type is int {\n\t\t\tprint('${m.name} returns int: ')\n\t\t\tprintln(foo.$method())\n\t\t} $else $if m.return_type is string {\n\t\t\tprint('${m.name} returns string: ')\n\t\t\tprintln(foo.$method())\n\t\t}\n\t}\n}\n\n// Output:\n// test returns int: 123\n// test2 returns string: foo\n```\n\n#### <h4 id=\"comptime-method-params\">.params</h4>\n\nYou can retrieve information about struct method params.\n\n```v\nstruct Test {\n}\n\nfn (t Test) foo(arg1 int, arg2 string) {\n}\n\nfn main() {\n\t$for m in Test.methods {\n\t\t$for param in m.params {\n\t\t\tprintln('${typeof(param.typ).name}: ${param.name}')\n\t\t}\n\t}\n}\n\n// Output:\n// int: arg1\n// string: arg2\n```\n\nSee [`examples/compiletime/reflection.v`](/examples/compiletime/reflection.v)\nfor a more complete example.\n\n### Compile time code\n\n#### `$if` condition\n\n```v\nfn main() {\n\t// Support for multiple conditions in one branch\n\t$if ios || android {\n\t\tprintln('Running on a mobile device!')\n\t}\n\t$if linux && x64 {\n\t\tprintln('64-bit Linux.')\n\t}\n\t// Usage as expression\n\tos := $if windows { 'Windows' } $else { 'UNIX' }\n\tprintln('Using ${os}')\n\t// $else-$if branches\n\t$if tinyc {\n\t\tprintln('tinyc')\n\t} $else $if clang {\n\t\tprintln('clang')\n\t} $else $if gcc {\n\t\tprintln('gcc')\n\t} $else {\n\t\tprintln('different compiler')\n\t}\n\t$if test {\n\t\tprintln('testing')\n\t}\n\t// v -cg ...\n\t$if debug {\n\t\tprintln('debugging')\n\t}\n\t// v -prod ...\n\t$if prod {\n\t\tprintln('production build')\n\t}\n\t// v -d option ...\n\t$if option ? {\n\t\tprintln('custom option')\n\t}\n}\n```\n\nIf you want an `if` to be evaluated at compile time it must be prefixed with a `$` sign.\nRight now it can be used to detect an OS, compiler, platform or compilation options.\n`$if debug` is a special option like `$if windows` or `$if x32`, it's enabled if the program\nis compiled with `v -g` or `v -cg`.\nIf you're using a custom ifdef, then you do need `$if option ? {}` and compile with`v -d option`.\nFull list of builtin options:\n\n| OS                             | Compilers        | Platforms                     | Other                                         |\n|--------------------------------|------------------|-------------------------------|-----------------------------------------------|\n| `windows`, `linux`, `macos`    | `gcc`, `tinyc`   | `amd64`, `arm64`, `aarch64`   | `debug`, `prod`, `test`                       |\n| `darwin`, `ios`, `bsd`         | `clang`, `mingw` | `i386`, `arm32`               | `js`, `glibc`, `prealloc`                     |\n| `freebsd`, `openbsd`, `netbsd` | `msvc`           | `rv64`, `rv32`, `s390x`       | `no_bounds_checking`, `freestanding`          |\n| `android`, `mach`, `dragonfly` | `cplusplus`      | `ppc64le`                     | `no_segfault_handler`, `no_backtrace`         |\n| `gnu`, `hpux`, `haiku`, `qnx`  |                  | `x64`, `x32`                  | `no_main`, `fast_math`, `apk`, `threads`      |\n| `solaris`, `termux`            |                  | `little_endian`, `big_endian` | `js_node`, `js_browser`, `js_freestanding`    |\n| `serenity`, `vinix`, `plan9`   |                  |                               | `interpreter`, `es5`, `profile`, `wasm32`     |\n|                                |                  |                               | `wasm32_emscripten`, `wasm32_wasi`            |\n|                                |                  |                               | `native`, `autofree`                          |\n\n#### `$embed_file`\n\n```v ignore\nimport os\nfn main() {\n\tembedded_file := $embed_file('v.png')\n\tos.write_file('exported.png', embedded_file.to_string())!\n}\n```\n\nV can embed arbitrary files into the executable with the `$embed_file(<path>)`\ncompile time call. Paths can be absolute or relative to the source file.\n\nPaths could also use the compile time pseudo variables `@VEXEROOT`,\n`@VMODROOT`, `@DIR`, `$d` and `$env`.\n\n```v ignore\nlogo := $embed_file('@VEXEROOT/examples/assets/logo.png')\n```\n\nNote that by default, using `$embed_file(file)`, will always embed the whole content\nof the file, but you can modify that behaviour by passing: `-d embed_only_metadata`\nwhen compiling your program. In that case, the file will not be embedded. Instead,\nit will be loaded *the first time* your program calls `embedded_file.data()` at runtime,\nmaking it easier to change in external editor programs, without needing to recompile\nyour program.\n\nEmbedding a file inside your executable, will increase its size, but\nit will make it more self contained and thus easier to distribute.\nWhen that happens (the default), `embedded_file.data()` will cause *no IO*,\nand it will always return the same data.\n\n`$embed_file` supports compression of the embedded file when compiling with `-prod`.\nCurrently only one compression type is supported: `zlib`.\n\n```v ignore\nimport os\nfn main() {\n\tembedded_file := $embed_file('x.css', .zlib) // compressed using zlib\n\tos.write_file('exported.css', embedded_file.to_string())!\n}\n```\n\nNote: compressing binary assets like png or zip files, usually will not gain you much,\nand in some cases may even take more space in the final executable, since they are\nalready compressed.\n\n`$embed_file` returns\n[EmbedFileData](https://modules.vlang.io/v.embed_file.html#EmbedFileData)\nwhich could be used to obtain the file contents as `string` or `[]u8`.\n\n#### `$tmpl` for embedding and parsing V template files\n\nV has a simple template language for text and html templates, and they can easily\nbe embedded via `$tmpl('path/to/template.txt')`:\n\n```v ignore\nfn build() string {\n\tname := 'Peter'\n\tage := 25\n\tnumbers := [1, 2, 3]\n\treturn $tmpl('1.txt')\n}\n\nfn main() {\n\tprintln(build())\n}\n```\n\n1.txt:\n\n```\nname: @name\n\nage: @age\n\nnumbers: @numbers\n\n@for number in numbers\n  @number\n@end\n```\n\noutput:\n\n```\nname: Peter\n\nage: 25\n\nnumbers: [1, 2, 3]\n\n1\n2\n3\n```\n\nSee more [details](https://github.com/vlang/v/blob/master/vlib/v/TEMPLATES.md)\n\n#### `$env`\n\n```v\nmodule main\n\nfn main() {\n\tcompile_time_env := $env('ENV_VAR')\n\tprintln(compile_time_env)\n}\n```\n\nV can bring in values at compile time from environment variables.\n`$env('ENV_VAR')` can also be used in top-level `#flag` and `#include` statements:\n`#flag linux -I $env('JAVA_HOME')/include`.\n\n#### `$d`\n\nV can bring in values at compile time from `-d ident=value` flag defines, passed on\nthe command line to the compiler. You can also pass `-d ident`, which will have the\nsame meaning as passing `-d ident=true`.\n\nTo get the value in your code, use: `$d('ident', default)`, where `default`\ncan be `false` for booleans, `0` or `123` for i64 numbers, `0.0` or `113.0`\nfor f64 numbers, `'a string'` for strings.\n\nWhen a flag is not provided via the command line, `$d()` will return the `default`\nvalue provided as the *second* argument.\n\n```v\nmodule main\n\nconst my_i64 = $d('my_i64', 1024)\n\nfn main() {\n\tcompile_time_value := $d('my_string', 'V')\n\tprintln(compile_time_value)\n\tprintln(my_i64)\n}\n```\n\nRunning the above with `v run .` will output:\n```\nV\n1024\n```\n\nRunning the above with `v -d my_i64=4096 -d my_string=\"V rocks\" run .` will output:\n```\nV rocks\n4096\n```\n\nHere is an example of how to use the default values, which have to be *pure* literals:\n```v\nfn main() {\n\tval_str := $d('id_str', 'value') // can be changed by providing `-d id_str=\"my id\"`\n\tval_f64 := $d('id_f64', 42.0) // can be changed by providing `-d id_f64=84.0`\n\tval_i64 := $d('id_i64', 56) // can be changed by providing `-d id_i64=123`\n\tval_bool := $d('id_bool', false) // can be changed by providing `-d id_bool=true`\n\tval_char := $d('id_char', `f`) // can be changed by providing `-d id_char=v`\n\tprintln(val_str)\n\tprintln(val_f64)\n\tprintln(val_i64)\n\tprintln(val_bool)\n\tprintln(rune(val_char))\n}\n```\n\n`$d('ident','value')` can also be used in top-level statements like `#flag` and `#include`:\n`#flag linux -I $d('my_include','/usr')/include`. The default value for `$d` when used in these\nstatements should be literal `string`s.\n\n`$d('ident', false)` can also be used inside `$if $d('ident', false) {` statements,\ngranting you the ability to selectively turn on/off certain sections of code, at compile\ntime, without modifying your source code, or keeping different versions of it.\n\n#### `$compile_error` and `$compile_warn`\n\nThese two comptime functions are very useful for displaying custom errors/warnings during\ncompile time.\n\nBoth receive as their only argument a string literal that contains the message to display:\n\n```v failcompile nofmt\n// x.v\nmodule main\n\n$if linux {\n    $compile_error('Linux is not supported')\n}\n\nfn main() {\n}\n\n$ v run x.v\nx.v:4:5: error: Linux is not supported\n    2 |\n    3 | $if linux {\n    4 |     $compile_error('Linux is not supported')\n      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    5 | }\n    6 |\n```\n\n### Compile time types\n\nCompile time types group multiple types into a general higher-level type. This is useful in\nfunctions with generic parameters, where the input type must have a specific property, for example\nthe `.len` attribute in arrays.\n\nV supports the following compile time types:\n\n- `$alias` => matches [Type aliases](#type-aliases).\n- `$array` => matches [Arrays](#arrays) and [Fixed Size Arrays](#fixed-size-arrays).\n- `$array_dynamic` => matches [Arrays](#arrays), but not [Fixed Size Arrays](#fixed-size-arrays).\n- `$array_fixed` => matches [Fixed Size Arrays](#fixed-size-arrays), but not [Arrays](#arrays)\n- `$enum` => matches [Enums](#enums).\n- `$float` => matches `f32`, `f64` and float literals.\n- `$function` => matches [Function Types](#function-types).\n- `$int` => matches `int`, `i8`, `i16`, `i32`, `i64`, `u8`, `u16`, `u32`, `u64`, `isize`, `usize`\n  and integer literals.\n- `$interface` => matches [Interfaces](#interfaces).\n- `$map` => matches [Maps](#maps).\n- `$option` => matches [Option Types](#optionresult-types-and-error-handling).\n- `$shared` => matches [Shared Types](#shared-objects).\n- `$struct` => matches [Structs](#structs).\n- `$sumtype` => matches [Sum Types](#sum-types).\n- `$string` => matches [Strings](#strings).\n- `$pointer` => matches [Reference Types](#references).\n- `$voidptr` => matches C's `void*`.\n\n### Environment specific files\n\nIf a file has an environment-specific suffix, it will only be compiled for that environment.\n\n- `.js.v` => will be used only by the JS backend. These files can contain JS. code.\n- `.c.v` => will be used only by the C backend. These files can contain C. code.\n- `.native.v` => will be used only by V's native backend.\n- `_nix.c.v` => will be used only on Unix systems (non Windows).\n- `_${os}.c.v` => will be used only on the specific `os` system.\n  For example, `_windows.c.v` will be used only when compiling on Windows, or with `-os windows`.\n- `_default.c.v` => will be used only if there is NOT a more specific platform file.\n  For example, if you have both `file_linux.c.v` and `file_default.c.v`,\n  and you are compiling for linux, then only `file_linux.c.v` will be used,\n  and `file_default.c.v` will be ignored.\n\nHere is a more complete example:\n\n`main.v`:\n\n```v ignore\nmodule main\nfn main() { println(message) }\n```\n\n`main_default.c.v`:\n\n```v ignore\nmodule main\nconst message = 'Hello world'\n```\n\n`main_linux.c.v`:\n\n```v ignore\nmodule main\nconst message = 'Hello linux'\n```\n\n`main_windows.c.v`:\n\n```v ignore\nmodule main\nconst message = 'Hello windows'\n```\n\nWith the example above:\n\n- when you compile for Windows, you will get `Hello windows`\n- when you compile for Linux, you will get `Hello linux`\n- when you compile for any other platform, you will get the\n  non specific `Hello world` message.\n\n- `_d_customflag.v` => will be used *only* if you pass `-d customflag` to V.\n  That corresponds to `$if customflag ? {}`, but for a whole file, not just a\n  single block. `customflag` should be a snake_case identifier, it can not\n  contain arbitrary characters (only lower case latin letters + numbers + `_`).\n  > **Note**\n  >\n  > A combinatorial `_d_customflag_linux.c.v` postfix will not work.\n  > If you do need a custom flag file, that has platform dependent code, use the\n  > postfix `_d_customflag.v`, and then use platform dependent compile time\n  > conditional blocks inside it, i.e. `$if linux {}` etc.\n\n- `_notd_customflag.v` => similar to _d_customflag.v, but will be used\n  *only* if you do NOT pass `-d customflag` to V.\n\nSee also [Cross Compilation](#cross-compilation).\n\n## Debugger\n\nTo use the native *V debugger*, add the `$dbg` statement to your source, where you\nwant the debugger to be invoked.\n\n```v\nfn main() {\n\ta := 1\n\t$dbg;\n}\n```\n\nRunning this V code, you will get the debugger REPL break when the execution\nreaches the `$dbg` statement.\n\n```\n$ v run example.v\nBreak on [main] main in example.v:3\nexample.v:3 vdbg>\n```\n\nAt this point, execution is halted, and the debugger is now available.\n\nTo see the available commands, type\n?, h or help. (Completion for commands works - Non-Windows only)\n\n```\nexample.v:3 vdbg> ?\nvdbg commands:\n  anon?                 check if the current context is anon\n  bt                    prints a backtrace\n  c, continue           continue debugging\n  generic?              check if the current context is generic\n  heap                  show heap memory usage\n  h, help, ?            show this help\n  l, list [lines]       show some lines from current break (default: 3)\n  mem, memory           show memory usage\n  method?               check if the current context is a method\n  m, mod                show current module name\n  p, print <var>        prints an variable\n  q, quit               exits debugging session in the code\n  scope                 show the vars in the current scope\n  u, unwatch <var>      unwatches a variable\n  w, watch <var>        watches a variable\n```\n\nLets try the `scope` command, to inspect the current scope context.\n\n```\nexample.v:3 vdbg> scope\na = 1 (int)\n```\n\nCool! We have the variable name, its value and its type name.\n\nWhat about printing only a variable, not the whole scope?\n\nJust type `p a`.\n\nTo watch a variable by its name, use:\n\n`w a` (where `a` is the variable name)\n\nTo stop watching the variable (`unwatch` it), use `u a`.\n\nLets see more one example:\n\n```\nfn main() {\n\tfor i := 0; i < 4; i++ {\n\t\t$dbg\n\t}\n}\n```\n\nRunning again, we'll get:\n`Break on [main] main in example.v:3`\n\nIf we want to read the source code context, we can use the `l` or `list` command.\n\n```\nexample.v:3 vdbg> l\n0001  fn main() {\n0002    for i := 0; i < 4; i++ {\n0003>           $dbg\n0004    }\n0005  }\n```\n\nThe default is read 3 lines before and 3 lines after, but you can\npass a parameter to the command to read more lines, like `l 5`.\n\nNow, lets watch the variable changing on this loop.\n\n```\nexample.v:3 vdbg> w i\ni = 0 (int)\n```\n\nTo continue to the next breakpoint, type `c` or `continue` command.\n\n```\nexample.v:3 vdbg> c\nBreak on [main] main in example.v:3\ni = 1 (int)\n```\n\n`i` and it's value is automatically printed, because it is in the watch list.\n\nTo repeat the last command issued, in this case the `c` command,\njust hit the *enter* key.\n\n```\nexample.v:3 vdbg>\nBreak on [main] main in example.v:3\ni = 2 (int)\nexample.v:3 vdbg>\nBreak on [main] main in example.v:3\ni = 3 (int)\nexample.v:3 vdbg>\n```\n\nYou can also see memory usage with `mem` or `memory` command, and\ncheck if the current context is an anon function (`anon?`), a method (`method?`)\nor a generic method (`generic?`) and clear the terminal window (`clear`).\n\n## Call stack\n\nYou can also show the current call stack with `v.debug`.\n\nTo enable this feature, add the `-d callstack` switch when building or running\nyour code:\n\n```v\nimport v.debug\n\nfn test(i int) {\n\tif i > 9 {\n\t\tdebug.dump_callstack()\n\t}\n}\n\nfn do_something() {\n\tfor i := 0; i <= 10; i++ {\n\t\ttest(i)\n\t}\n}\n\nfn main() {\n\tdo_something()\n}\n```\n\n```\n$ v -d callstack run example.v\nBacktrace:\n--------------------------------------------------\nexample.v:16   | > main.main\nexample.v:11   |  > main.do_something\nexample.v:5    |   > main.test\n--------------------------------------------------\n```\n\n## Trace\n\nAnother feature of `v.debug` is the possibility to add hook functions\nbefore and after each function call.\n\nTo enable this feature, add the `-d trace` switch when building or running\nyour code:\n\n```v\nimport v.debug\n\nfn main() {\n\thook1 := debug.add_before_call(fn (fn_name string) {\n\t\tprintln('> before ${fn_name}')\n\t})\n\thook2 := debug.add_after_call(fn (fn_name string) {\n\t\tprintln('> after ${fn_name}')\n\t})\n\tanon := fn () {\n\t\tprintln('call')\n\t}\n\tanon()\n\n\t// optionally you can remove the hooks:\n\tdebug.remove_before_call(hook1)\n\tdebug.remove_after_call(hook2)\n\tanon()\n}\n```\n\n```\n$ v -d trace run example.v\n> before anon\ncall\n> after anon\ncall\n```\n\n## Memory-unsafe code\n\nSometimes for efficiency you may want to write low-level code that can potentially\ncorrupt memory or be vulnerable to security exploits. V supports writing such code,\nbut not by default.\n\nV requires that any potentially memory-unsafe operations are marked intentionally.\nMarking them also indicates to anyone reading the code that there could be\nmemory-safety violations if there was a mistake.\n\nExamples of potentially memory-unsafe operations are:\n\n* Pointer arithmetic\n* Pointer indexing\n* Conversion to pointer from an incompatible type\n* Calling certain C functions, e.g. `free`, `strlen` and `strncmp`.\n\nTo mark potentially memory-unsafe operations, enclose them in an `unsafe` block:\n\n```v wip\n// allocate 2 uninitialized bytes & return a reference to them\nmut p := unsafe { malloc(2) }\np[0] = `h` // Error: pointer indexing is only allowed in `unsafe` blocks\nunsafe {\n    p[0] = `h` // OK\n    p[1] = `i`\n}\np++ // Error: pointer arithmetic is only allowed in `unsafe` blocks\nunsafe {\n    p++ // OK\n}\nassert *p == `i`\n```\n\nBest practice is to avoid putting memory-safe expressions inside an `unsafe` block,\nso that the reason for using `unsafe` is as clear as possible. Generally any code\nyou think is memory-safe should not be inside an `unsafe` block, so the compiler\ncan verify it.\n\nIf you suspect your program does violate memory-safety, you have a head start on\nfinding the cause: look at the `unsafe` blocks (and how they interact with\nsurrounding code).\n\n> [!NOTE]\n> This is work in progress.\n\n## Structs with reference fields\n\nStructs with references require explicitly setting the initial value to a\nreference value unless the struct already defines its own initial value.\n\nZero-value references, or nil pointers, will **NOT** be supported in the future,\nfor now data structures such as Linked Lists or Binary Trees that rely on reference\nfields that can use the value `0`, understanding that it is unsafe, and that it can\ncause a panic.\n\n```v\nstruct Node {\n\ta &Node\n\tb &Node = unsafe { nil } // Auto-initialized to nil, use with caution!\n}\n\n// Reference fields must be initialized unless an initial value is declared.\n// Nil is OK but use with caution, it's a nil pointer.\nfoo := Node{\n\ta: unsafe { nil }\n}\nbar := Node{\n\ta: &foo\n}\nbaz := Node{\n\ta: unsafe { nil }\n\tb: unsafe { nil }\n}\nqux := Node{\n\ta: &foo\n\tb: &bar\n}\nprintln(baz)\nprintln(qux)\n```\n\n## sizeof and __offsetof\n\n* `sizeof(Type)` gives the size of a type in bytes.\n* `__offsetof(Struct, field_name)` gives the offset in bytes of a struct field.\n\n```v\nstruct Foo {\n\ta int\n\tb int\n}\n\nassert sizeof(Foo) == 8\nassert __offsetof(Foo, a) == 0\nassert __offsetof(Foo, b) == 4\n```\n\n## Limited operator overloading\n\nOperator overloading defines the behavior of certain binary operators for certain types.\n\n```v\nstruct Vec {\n\tx int\n\ty int\n}\n\nfn (a Vec) str() string {\n\treturn '{${a.x}, ${a.y}}'\n}\n\nfn (a Vec) + (b Vec) Vec {\n\treturn Vec{a.x + b.x, a.y + b.y}\n}\n\nfn (a Vec) - (b Vec) Vec {\n\treturn Vec{a.x - b.x, a.y - b.y}\n}\n\nfn main() {\n\ta := Vec{2, 3}\n\tb := Vec{4, 5}\n\tmut c := Vec{1, 2}\n\n\tprintln(a + b) // \"{6, 8}\"\n\tprintln(a - b) // \"{-2, -2}\"\n\tc += a\n\t//^^ autogenerated from + overload\n\tprintln(c) // \"{3, 5}\"\n}\n```\n\n> Operator overloading goes against V's philosophy of simplicity and predictability.\n> But since scientific and graphical applications are among V's domains,\n> operator overloading is an important feature to have in order to improve readability:\n>\n> `a.add(b).add(c.mul(d))` is a lot less readable than `a + b + c * d`.\n\nOperator overloading is possible for the following binary operators: `+, -, *, /, %, <, ==`.\n\n### Implicitly generated overloads\n\n- `==` is automatically generated by the compiler, but can be overridden.\n\n- `!=`, `>`, `<=` and `>=` are automatically generated when `==` and `<` are defined.\n  They cannot be explicitly overridden.\n- Assignment operators (`*=`, `+=`, `/=`, etc) are automatically generated when the corresponding\n  operators are defined and the operands are of the same type.\n  They cannot be explicitly overridden.\n\n### Restriction\n\nTo improve safety and maintainability, operator overloading is limited.\n\n#### Type restrictions\n\n- When overriding `<` and `==`, the return type must be strictly `bool`.\n- Both arguments must have the same type (just like with all operators in V).\n- Overloaded operators have to return the same type as the argument\n  (the exceptions are `<` and `==`).\n\n#### Other restrictions\n\n- Arguments cannot be changed inside overloads.\n- Calling other functions inside operator functions is not allowed (**planned**).\n\n## Performance tuning\n\nWhen compiled with `-prod`, V's generated C code usually performs well. However, in specialized\nscenarios, additional compiler flags and attributes can further optimize the executable for\nperformance, memory usage, or size.\n\n> [!NOTE]\n> These are *rarely* needed, and should not be used unless you\n> *profile your code*, and then see that there are significant benefits for them.\n> To cite GCC's documentation: \"Programmers are notoriously bad at predicting\n> how their programs actually perform\".\n\n| Tuning Operation         | Benefits                        | Drawbacks                                         |\n|--------------------------|---------------------------------|---------------------------------------------------|\n| `@[inline]`              | Performance                     | Increased executable size                         |\n| `@[direct_array_access]` | Performance                     | Safety risks                                      |\n| `@[packed]`              | Memory usage                    | Potential performance loss                        |\n| `@[minify]`              | Performance, Memory usage       | May break binary serialization/reflection         |\n| `_likely_/_unlikely_`    | Performance                     | Risk of negative performance impact               |\n| `-fast-math`             | Performance                     | Risk of incorrect mathematical operations results |\n| `-d no_segfault_handler` | Compile time, Size              | Loss of segfault trace                            |\n| `-cflags -march=native`  | Performance                     | Risk of reduced CPU compatibility                 |\n| `-compress`              | Size                            | Harder to debug, extra dependency `upx`           |\n| `PGO`                    | Performance, Size               | Usage complexity                                  |\n\n### Tuning operations details\n\n#### `@[inline]`\n\nYou can tag functions with `@[inline]`, so the C compiler will try to inline them, which in some\ncases, may be beneficial for performance, but may impact the size of your executable.\n\n**When to Use**\n\n- Functions that are called frequently in performance-critical loops.\n\n**When to Avoid**\n\n- Large functions, as it might cause code bloat and actually decrease performance.\n- Large functions in `if` expressions - may have negative impact on instructions cache.\n\n#### `@[direct_array_access]`\n\nIn functions tagged with `@[direct_array_access]` the compiler will translate array operations\ndirectly into C array operations - omitting bounds checking. This may save a lot of time in a\nfunction that iterates over an array but at the cost of making the function unsafe - unless the\nboundaries will be checked by the user.\n\n**When to Use**\n\n- In tight loops that access array elements, where bounds have been manually verified or you are\nsure that the access index will be valid.\n\n**When to Avoid**\n\n- Everywhere else.\n\n#### `@[packed]`\n\nThe `@[packed]` attribute can be applied to a structure to create an unaligned memory layout,\nwhich decreases the overall memory footprint of the structure. Using the `@[packed]` attribute\nmay negatively impact performance or even be prohibited on certain CPU architectures.\n\n**When to Use**\n\n- When memory usage is more critical than performance, e.g., in embedded systems.\n\n**When to Avoid**\n\n- On CPU architectures that do not support unaligned memory access or when high-speed memory access\nis needed.\n\n#### `@[aligned]`\n\nThe `@[aligned]` attribute can be applied to a structure or union to specify a minimum alignment\n(in bytes) for variables of that type. Using the `@[aligned]` attribute you can only *increase*\nthe default alignment. Use `@[packed]` if you want to *decrease* it. The alignment of any struct\nor union, should be at least a perfect multiple of the lowest common multiple of the alignments of\nall of the members of the struct or union.\n\nExample:\n```v\n// Each u16 in the `data` field below, takes 2 bytes, and we have 3 of them = 6 bytes.\n// The smallest power of 2, bigger than 6 is 8, i.e. with `@[aligned]`, the alignment\n// for the entire struct U16s, will be 8:\n@[aligned]\nstruct U16s {\n\tdata [3]u16\n}\n```\n**When to Use**\n\n- Only if the instances of your types, will be used in performance critical sections, or with\nspecialised machine instructions, that do require a specific alignment to work.\n\n**When to Avoid**\n\n- On CPU architectures, that do not support unaligned memory access. If you are not working on\nperformance critical algorithms, you do not really need it, since the proper minimum alignment\nis CPU specific, and the compiler already usually will choose a good default for you.\n\n> [!NOTE]\n> You can leave out the alignment factor, i.e. use just `@[aligned]`, in which case the compiler\n> will align a type to the maximum useful alignment for the target machine you are compiling for,\n> i.e. the alignment will be the largest alignment which is ever used for any data type on the\n> target machine. Doing this can often make copy operations more efficient, because the compiler\n> can choose whatever instructions copy the biggest chunks of memory, when performing copies to or\n> from the variables which have types that you have aligned this way.\n\nSee also [\"What Every Programmer Should Know About Memory\", by Ulrich Drepper](https://people.freebsd.org/~lstewart/articles/cpumemory.pdf) .\n\n#### `@[minify]`\n\nThe `@[minify]` attribute can be added to a struct, allowing the compiler to reorder the fields in\na way that minimizes internal gaps while maintaining alignment. Using the `@[minify]` attribute may\ncause issues with binary serialization or reflection. Be mindful of these potential side effects\nwhen using this attribute.\n\n**When to Use**\n\n- When you want to minimize memory usage and you're not using binary serialization or reflection.\n\n**When to Avoid**\n\n- When using binary serialization or reflection, as it may cause unexpected behavior.\n\n#### `_likely_/_unlikely_`\n\n`if _likely_(bool expression) {` - hints to the C compiler, that the passed boolean expression is\nvery likely to be true, so it can generate assembly code, with less chance of branch misprediction.\nIn the JS backend, that does nothing.\n\n`if _unlikely_(bool expression) {` is similar to `_likely_(x)`, but it hints that the boolean\nexpression is highly improbable. In the JS backend, that does nothing.\n\n**When to Use**\n\n- In conditional statements where one branch is clearly more frequently executed than the other.\n\n**When to Avoid**\n\n- When the prediction can be wrong, as it might cause a performance penalty due to branch\nmisprediction.\n\n**When to Use**\n\n- For production builds where you want to reduce the executable size and improve runtime\nperformance.\n\n**When to Avoid**\n\n- Where it doesn't work for you.\n\n#### `-fast-math`\n\nThis flag enables optimizations that disregard strict compliance with the IEEE standard for\nfloating-point arithmetic. While this could lead to faster code, it may produce incorrect or\nless accurate mathematical results.\n\nThe full specter of math operations that `-fast-math` affects can be found\n[here](https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math).\n\n**When to Use**\n\n- In applications where performance is more critical than precision, like certain graphics\nrendering tasks.\n\n**When to Avoid**\n\n- In applications requiring strict mathematical accuracy, such as scientific simulations or\nfinancial calculations.\n\n#### `-d no_segfault_handler`\n\nUsing this flag omits the segfault handler, reducing the executable size and potentially improving\ncompile time. However, in the case of a segmentation fault, the output will not contain stack trace\ninformation, making debugging more challenging.\n\n**When to Use**\n\n- In small, well-tested utilities where a stack trace is not essential for debugging.\n\n**When to Avoid**\n\n- In large-scale, complex applications where robust debugging is required.\n\n#### `-cflags -march=native`\n\nThis flag directs the C compiler to generate instructions optimized for the host CPU. This can\nimprove performance but will produce an executable incompatible with other/older CPUs.\n\n**When to Use**\n\n- When the software is intended to run only on the build machine or in a controlled environment\nwith identical hardware.\n\n**When to Avoid**\n\n- When distributing the software to users with potentially older CPUs.\n\n#### `-compress`\n\nThis flag executes `upx` to compress the resultant executable, reducing its size by around 50%-70%.\nThe executable will be uncompressed at runtime, so it will take a bit more time to start.\nIt will also take extra RAM initially, as the compressed version of the app will be loaded into\nmemory, and then expanded to another chunk of memory.\nDebugging such an application can be a bit harder, if you do not account for it.\nSome antivirus programs also use heuristics, that trigger more often for compressed applications.\n\n**When to Use**\n\n- For really tiny environments, where the size of the executable on the file system,\nor when deploying is important (docker containers, rescue disks etc).\n\n**When to Avoid**\n\n- When you need to debug the application\n- When the app's startup time is extremely important (where 1-2ms can be meaningful for you)\n- When you can not afford to allocate more memory during application startup\n- When you are deploying an app to users with antivirus software that could misidentify your\napp as malicious, just because it decompresses its code at runtime.\n\n#### PGO (Profile-Guided Optimization)\n\nPGO allows the compiler to optimize code based on its behavior during sample runs. This can improve\nperformance and reduce the size of the output executable, but it adds complexity to the build\nprocess.\n\n**When to Use**\n\n- For performance-critical applications where the added build complexity is justifiable.\n\n**When to Avoid**\n\n- For small, short-lived, or rapidly-changing projects where the added build complexity isn't\njustified.\n\n**PGO with Clang**\n\nThis is an example bash script you can use to optimize your CLI V program without user interactions.\nIn most cases, you will need to change this script to make it suitable for your particular program.\n\n```bash\n#!/usr/bin/env bash\n\n# Get the full path to the current directory\nCUR_DIR=$(pwd)\n\n# Remove existing PGO data\nrm -f *.profraw\nrm -f default.profdata\n\n# Initial build with PGO instrumentation\nv -cc clang -prod -cflags -fprofile-generate -o pgo_gen .\n\n# Run the instrumented executable 10 times\nfor i in {1..10}; do\n    ./pgo_gen\ndone\n\n# Merge the collected data\nllvm-profdata merge -o default.profdata *.profraw\n\n# Compile the optimized version using the PGO data\nv -cc clang -prod -cflags \"-fprofile-use=${CUR_DIR}/default.profdata\" -o optimized_program .\n\n# Remove PGO data and instrumented executable\nrm *.profraw\nrm pgo_gen\n```\n\n## Atomics\n\nV has no special support for atomics yet, nevertheless it's possible to treat variables as atomics\nby [calling C](#v-and-c) functions from V. The standard C11 atomic functions like `atomic_store()`\nare usually defined with the help of macros and C compiler magic to provide a kind of\n*overloaded C functions*.\nSince V does not support overloading functions by intention there are wrapper functions defined in\nC headers named `atomic.h` that are part of the V compiler infrastructure.\n\nThere are dedicated wrappers for all unsigned integer types and for pointers.\n(`u8` is not fully supported on Windows) &ndash; the function names include the type name\nas suffix. e.g. `C.atomic_load_ptr()` or `C.atomic_fetch_add_u64()`.\n\nTo use these functions the C header for the used OS has to be included and the functions\nthat are intended to be used have to be declared. Example:\n\n```v globals\n$if windows {\n\t#include \"@VEXEROOT/thirdparty/stdatomic/win/atomic.h\"\n} $else {\n\t#include \"@VEXEROOT/thirdparty/stdatomic/nix/atomic.h\"\n}\n\n// declare functions we want to use - V does not parse the C header\nfn C.atomic_store_u32(&u32, u32)\nfn C.atomic_load_u32(&u32) u32\nfn C.atomic_compare_exchange_weak_u32(&u32, &u32, u32) bool\nfn C.atomic_compare_exchange_strong_u32(&u32, &u32, u32) bool\n\nconst num_iterations = 10000000\n\n// see section \"Global Variables\" below\n__global (\n\tatom u32 // ordinary variable but used as atomic\n)\n\nfn change() int {\n\tmut races_won_by_change := 0\n\tfor {\n\t\tmut cmp := u32(17) // addressable value to compare with and to store the found value\n\t\t// atomic version of `if atom == 17 { atom = 23 races_won_by_change++ } else { cmp = atom }`\n\t\tif C.atomic_compare_exchange_strong_u32(&atom, &cmp, 23) {\n\t\t\traces_won_by_change++\n\t\t} else {\n\t\t\tif cmp == 31 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcmp = 17 // re-assign because overwritten with value of atom\n\t\t}\n\t}\n\treturn races_won_by_change\n}\n\nfn main() {\n\tC.atomic_store_u32(&atom, 17)\n\tt := spawn change()\n\tmut races_won_by_main := 0\n\tmut cmp17 := u32(17)\n\tmut cmp23 := u32(23)\n\tfor i in 0 .. num_iterations {\n\t\t// atomic version of `if atom == 17 { atom = 23 races_won_by_main++ }`\n\t\tif C.atomic_compare_exchange_strong_u32(&atom, &cmp17, 23) {\n\t\t\traces_won_by_main++\n\t\t} else {\n\t\t\tcmp17 = 17\n\t\t}\n\t\tdesir := if i == num_iterations - 1 { u32(31) } else { u32(17) }\n\t\t// atomic version of `for atom != 23 {} atom = desir`\n\t\tfor !C.atomic_compare_exchange_weak_u32(&atom, &cmp23, desir) {\n\t\t\tcmp23 = 23\n\t\t}\n\t}\n\traces_won_by_change := t.wait()\n\tatom_new := C.atomic_load_u32(&atom)\n\tprintln('atom: ${atom_new}, #exchanges: ${races_won_by_main + races_won_by_change}')\n\t// prints `atom: 31, #exchanges: 10000000`)\n\tprintln('races won by\\n- `main()`: ${races_won_by_main}\\n- `change()`: ${races_won_by_change}')\n}\n```\n\nIn this example both `main()` and the spawned thread `change()` try to replace a value of `17`\nin the global `atom` with a value of `23`. The replacement in the opposite direction is\ndone exactly 10000000 times. The last replacement will be with `31` which makes the spawned\nthread finish.\n\nIt is not predictable how many replacements occur in which thread, but the sum will always\nbe 10000000. (With the non-atomic commands from the comments the value will be higher or the program\nwill hang &ndash; dependent on the compiler optimization used.)\n\n## Global Variables\n\nBy default V does not allow global variables. However, in low-level applications they have their\nplace so their usage can be enabled with the compiler flag `-enable-globals`.\nDeclarations of global variables must be surrounded with a `__global ( ... )`\nspecification &ndash; as in the example [above](#atomics).\n\nAn initializer for global variables must be explicitly converted to the\ndesired target type. If no initializer is given a default initialization is done.\nSome objects like semaphores and mutexes require an explicit initialization *in place*, i.e.\nnot with a value returned from a function call but with a method call by reference.\nA separate `init()` function can be used for this purpose &ndash; it will be called before `main()`:\n\n```v globals\nimport sync\n\n__global (\n\tsem   sync.Semaphore // needs initialization in `init()`\n\tmtx   sync.RwMutex // needs initialization in `init()`\n\tf1    = f64(34.0625) // explicitly initialized\n\tshmap shared map[string]f64 // initialized as empty `shared` map\n\tf2    f64 // initialized to `0.0`\n)\n\nfn init() {\n\tsem.init(0)\n\tmtx.init()\n}\n```\n\nBe aware that in multi threaded applications the access to global variables is subject\nto race conditions. There are several approaches to deal with these:\n\n- use `shared` types for the variable declarations and use `lock` blocks for access.\n  This is most appropriate for larger objects like structs, arrays or maps.\n- handle primitive data types as \"atomics\" using special C-functions (see [above](#atomics)).\n- use explicit synchronization primitives like mutexes to control access. The compiler\n  cannot really help in this case, so you have to know what you are doing.\n- don't care &ndash; this approach is possible but makes only sense if the exact values\n  of global variables do not really matter. An example can be found in the `rand` module\n  where global variables are used to generate (non cryptographic) pseudo random numbers.\n  In this case data races lead to random numbers in different threads becoming somewhat\n  correlated, which is acceptable considering the performance penalty that using\n  synchronization primitives would represent.\n\n## Static Variables\n\nV also supports *static variables*, which are like *global variables*, but\navailable only *inside* a single unsafe function (you can look at them as\nnamespaced globals).\n\nNote: their use is discouraged too, for reasons similar to why globals\nare discouraged. The feature is supported to enable translating existing\nlow-level C code into V code, using `v translate`.\n\nNote: the function in which you use a static variable, has to be marked\nwith @[unsafe]. Also unlike using globals, using static variables, do not\nrequire you to pass the flag `-enable-globals`, because they can only be\nread/changed inside a single function, which has full control over the\nstate stored in them.\n\nHere is a small example of how static variables can be used:\n```v\n@[unsafe]\nfn counter() int {\n\tmut static x := 42\n\t// Note: x is initialised to 42, just _once_.\n\tx++\n\treturn x\n}\n\nfn f() int {\n\treturn unsafe { counter() }\n}\n\nprintln(f()) // prints 43\nprintln(f()) // prints 44\nprintln(f()) // prints 45\n```\n\n## Cross compilation\n\nCross compilation is supported for Windows, Linux and FreeBSD.\n\nTo cross compile your project simply run:\n\n```shell\nv -os windows .\n```\n\nor\n\n```shell\nv -os linux .\n```\n\nor\n\n```shell\nv -os freebsd .\n```\n\n> [!NOTE]\n> Cross-compiling a Windows binary on a Linux machine requires the GNU C compiler for\n> MinGW-w64 (targeting Win64) to first be installed.\n\nFor Ubuntu/Debian-based distributions:\n\n```shell\nsudo apt install gcc-mingw-w64-x86-64\n```\n\nFor Arch based distributions:\n\n```shell\nsudo pacman -S mingw-w64-gcc\n```\n\n(Cross compiling for macOS is temporarily not possible.)\n\nIf you don't have any C dependencies, that's all you need to do. This works even\nwhen compiling GUI apps using the `ui` module or graphical apps using `gg`.\n\nIf you need a custom cross compiler, pass `-cc <compiler>` for one build, or set\n`VCROSS_COMPILER_NAME` in your environment.\nExample:\n\n```shell\nv -os linux -cc cosmocc .\n```\n\nYou will need to install Clang, LLD linker, and download a zip file with\nlibraries and include files for Windows and Linux. V will provide you with a link.\n\n## Debugging\n\n### C Backend binaries (Default)\n\nTo debug issues in the generated binary (flag: `-b c`), you can pass these flags:\n\n- `-g` - produces a less optimized executable with more debug information in it.\n  V will enforce line numbers from the .v files in the stacktraces, that the\n  executable will produce on panic. It is usually better to pass -g, unless\n  you are writing low-level code, in which case use the next option `-cg`.\n- `-cg` - produces a less optimized executable with more debug information in it.\n  The executable will use C source line numbers in this case. It is frequently\n  used in combination with `-keepc`, so that you can inspect the generated\n  C program in case of panic, or so that your debugger (`gdb`, `lldb` etc.)\n  can show you the generated C source code.\n- `-showcc` - prints the C command that is used to build the program.\n- `-show-c-output` - prints the output, that your C compiler produced\n  while compiling your program.\n- `-keepc` - do not delete the generated C source code file after a successful\n  compilation. Also keep using the same file path, so it is more stable,\n  and easier to keep opened in an editor/IDE.\n\nFor best debugging experience if you are writing a low-level wrapper for an existing\nC library, you can pass several of these flags at the same time:\n`v -keepc -cg -showcc yourprogram.v`, then just run your debugger (gdb/lldb) or IDE\non the produced executable `yourprogram`.\n\nIf you just want to inspect the generated C code,\nwithout further compilation, you can also use the `-o` flag (e.g. `-o file.c`).\nThis will make V produce the `file.c` then stop.\n\nIf you want to see the generated C source code for *just* a single C function,\nfor example `main`, you can use: `-printfn main -o file.c`.\n\nTo debug the V executable itself you need to compile from src with `./v -g -o v cmd/v`.\n\nYou can debug tests with for example `v -g -keepc prog_test.v`. The `-keepc` flag is needed,\nso that the executable is not deleted, after it was created and ran.\n\nTo see a detailed list of all flags that V supports,\nuse `v help`, `v help build` and `v help build-c`.\n\n**Commandline Debugging**\n\n1. compile your binary with debugging info `v -g hello.v`\n2. debug with [lldb](https://lldb.llvm.org) or [GDB](https://www.gnu.org/software/gdb/)\n   e.g. `lldb hello`\n\n[Troubleshooting (debugging) executables created with V in GDB](https://github.com/vlang/v/wiki/Troubleshooting-(debugging)-executables-created-with-V-in-GDB)\n\n**Visual debugging Setup:**\n\n* [Visual Studio Code](vscode.md)\n\n### Native Backend binaries\n\nCurrently there is no debugging support for binaries, created by the\nnative backend (flag: `-b native`).\n\n### Javascript Backend\n\nTo debug the generated Javascript output you can activate source maps:\n`v -b js -sourcemap hello.v -o hello.js`\n\nFor all supported options check the latest help:\n`v help build-js`\n\n## V and C\n\nThe basic mapping between C and V types is described in\n[C and V Type Interoperability](https://github.com/vlang/v/blob/master/doc/c_and_v_type_interoperability.md).\n\n### Calling C from V\n\nV currently does not have a parser for C code. That means that even\nthough it allows you to `#include` existing C header and source files,\nit will not know anything about the declarations in them. The `#include`\nstatement will only appear in the generated C code, to be used by the\nC compiler backend itself.\n\n**Example of #include**\n```v oksyntax\n#include <stdio.h>\n```\nAfter this statement, V will *not* know anything about the functions and\nstructs declared in `stdio.h`, but if you try to compile the .v file,\nit will add the include in the generated C code, so that if that header file\nis missing, you will get a C error (you will not in this specific case, if you\nhave a proper C compiler setup, since `<stdio.h>` is part of the\nstandard C library).\n\nTo overcome that limitation (that V does not have a C parser), V needs you to\nredeclare the C functions and structs, on the V side, in your `.c.v` files.\nNote that such redeclarations only need to have enough details about the\nfunctions/structs that you want to use.\nNote also that they *do not have* to be complete, unlike the ones in the .h files.\n\n\n**C. struct redeclarations**\nFor example, if a struct has 3 fields on the C side, but you want to only\nrefer to 1 of them, you can declare it like this:\n\n**Example of C struct redeclaration**\n```v oksyntax\nstruct C.NameOfTheStruct {\n\ta_field int\n}\n```\nAnother feature, that is very frequently needed for C interoperability,\nis the `@[typedef]` attribute. It is used for marking `C.` structs,\nthat are defined with `typedef struct SomeName { ..... } TypeName;` in the C headers.\n\nFor that case, you will have to write something like this in your .c.v file:\n```v oksyntax\n@[typedef]\npub struct C.TypeName {\n}\n```\nNote that the name of the `C.` struct in V, is the one *after* the `struct SomeName {...}`.\n\n**C. function redeclarations**\nThe situation is similar for `C.` functions. If you are going to call just 1 function in a\nlibrary, but its .h header declares dozens of them, you will only need to declare that single\nfunction, for example:\n\n**Example of C function redeclaration**\n```v oksyntax\nfn C.name_of_the_C_function(param1 int, const_param2 &char, param3 f32) f64\n```\n... and then later, you will be able to call the same way you would V function:\n```v oksyntax\nf := C.name_of_the_C_function(123, c'here is some C style string', 1.23)\ndump(f)\n```\n\n**Example of using a C function from stdio, by redeclaring it on the V side**\n```v\n#include <stdio.h>\n\n// int dprintf(int fd, const char *format, ...)\nfn C.dprintf(fd int, const_format &char, ...voidptr) int\n\nvalue := 12345\nx := C.dprintf(0, c'Hello world, value: %d\\n', value)\ndump(x)\n```\n\nIf your C backend compiler is properly setup, you should see something like this, when you try\nto run it:\n```console\n#0 10:42:32 /v/examples> v run a.v\nHello world, value: 12345\n[a.v:8] x: 26\n#0 10:42:33 /v/examples>\n```\n\nNote, that the C function redeclarations look very similar to the V ones, with some differences:\n1) They lack a body (they are defined on the C side) .\n2) Their names start with `C.` .\n3) Their names can have capital letters (unlike V ones, that are required to use snake_case) .\n\nNote also the second parameter `const char *format`, which was redeclared as `const_format &char` .\nThe `const_` prefix in that redeclaration may seem arbitrary, but it is important, if you want\nto compile your code with `-cstrict` or thirdparty C static analysis tools. V currently does not\nhave another way to express that this parameter is a const (this will probably change in V 1.0).\n\nFor some C functions, that use variadics (`...`) as parameters, V supports a special syntax for\nthe parameters - `...voidptr`, that is not available for ordinary V functions (V's variadics are\n*required* to have the same exact type). Usually those are functions of the printf/scanf family\ni.e for `printf`, `fprintf`, `scanf`, `sscanf`, etc, and other formatting/parsing/logging\nfunctions.\n\n**Example**\n\n```v\n#flag freebsd -I/usr/local/include -L/usr/local/lib\n#flag -lsqlite3\n#include \"sqlite3.h\"\n// See also the example from https://www.sqlite.org/quickstart.html\npub struct C.sqlite3 {\n}\n\npub struct C.sqlite3_stmt {\n}\n\ntype FnSqlite3Callback = fn (voidptr, int, &&char, &&char) int\n\nfn C.sqlite3_open(&char, &&C.sqlite3) int\n\nfn C.sqlite3_close(&C.sqlite3) int\n\nfn C.sqlite3_column_int(stmt &C.sqlite3_stmt, n int) int\n\n// ... you can also just define the type of parameter and leave out the C. prefix\n\nfn C.sqlite3_prepare_v2(&C.sqlite3, &char, int, &&C.sqlite3_stmt, &&char) int\n\nfn C.sqlite3_step(&C.sqlite3_stmt)\n\nfn C.sqlite3_finalize(&C.sqlite3_stmt)\n\nfn C.sqlite3_exec(db &C.sqlite3, sql &char, cb FnSqlite3Callback, cb_arg voidptr, emsg &&char) int\n\nfn C.sqlite3_free(voidptr)\n\nfn my_callback(arg voidptr, howmany int, cvalues &&char, cnames &&char) int {\n\tunsafe {\n\t\tfor i in 0 .. howmany {\n\t\t\tprint('| ${cstring_to_vstring(cnames[i])}: ${cstring_to_vstring(cvalues[i]):20} ')\n\t\t}\n\t}\n\tprintln('|')\n\treturn 0\n}\n\nfn main() {\n\tdb := &C.sqlite3(unsafe { nil }) // this means `sqlite3* db = 0`\n\t// passing a string literal to a C function call results in a C string, not a V string\n\tC.sqlite3_open(c'users.db', &db)\n\t// C.sqlite3_open(db_path.str, &db)\n\tquery := 'select count(*) from users'\n\tstmt := &C.sqlite3_stmt(unsafe { nil })\n\t// Note: You can also use the `.str` field of a V string,\n\t// to get its C style zero terminated representation\n\tC.sqlite3_prepare_v2(db, &char(query.str), -1, &stmt, 0)\n\tC.sqlite3_step(stmt)\n\tnr_users := C.sqlite3_column_int(stmt, 0)\n\tC.sqlite3_finalize(stmt)\n\tprintln('There are ${nr_users} users in the database.')\n\n\terror_msg := &char(unsafe { nil })\n\tquery_all_users := 'select * from users'\n\trc := C.sqlite3_exec(db, &char(query_all_users.str), my_callback, voidptr(7), &error_msg)\n\tif rc != C.SQLITE_OK {\n\t\teprintln(unsafe { cstring_to_vstring(error_msg) })\n\t\tC.sqlite3_free(error_msg)\n\t}\n\tC.sqlite3_close(db)\n}\n```\n\n### Calling V from C\n\nSince V can compile to C, calling V code from C is very easy, once you know how.\n\nUse `v -o file.c your_file.v` to generate a C file, corresponding to the V code.\n\nMore details in [call_v_from_c example](../examples/call_v_from_c).\n\n### Passing C compilation flags\n\nAdd `#flag` directives to the top of your V files to provide C compilation flags like:\n\n- `-I` for adding C include files search paths\n- `-l` for adding C library names that you want to get linked\n- `-L` for adding C library files search paths\n- `-D` for setting compile time variables\n\nYou can also use `#flag` directives, to link to static C libraries, which\nwill be added last (note the .a suffix):\n```v oksyntax\n#flag /path/to/ffi.a\n```\nIf you need to reverse the order (prepend the static library in the libs section of the\nC compilation line, before other libs), use:\n```v oksyntax\n#flag /path/to/ffi.a@START_LIBS\n```\n\nYou can (optionally) use different flags for different targets.\nEvery OS listed in [Compile time code](#compile-time-code) is supported as flags.\n\n> [!NOTE]\n> Each flag must go on its own line (for now)\n\n```v oksyntax\n#flag linux -lsdl2\n#flag linux -Ivig\n#flag linux -DCIMGUI_DEFINE_ENUMS_AND_STRUCTS=1\n#flag linux -DIMGUI_DISABLE_OBSOLETE_FUNCTIONS=1\n#flag linux -DIMGUI_IMPL_API=\n```\n\nIn the console build command, you can use:\n\n* `-cc` to change the default C backend compiler.\n* `-cflags` to pass custom flags to the backend C compiler (passed before other C options).\n* `-ldflags` to pass custom flags to the backend C linker (passed after every other C option).\n* For example: `-cc gcc-9 -cflags -fsanitize=thread`.\n\nYou can define a `VFLAGS` environment variable in your terminal to store your `-cc`\nand `-cflags` settings, rather than including them in the build command each time.\n\n### #pkgconfig\n\nAdd `#pkgconfig` directives to tell the compiler which modules should be used for compiling\nand linking using the pkg-config files provided by the respective dependencies.\n\nAs long as backticks can't be used in `#flag` and spawning processes is not desirable for security\nand portability reasons, V uses its own pkgconfig library that is compatible with the standard\nfreedesktop one.\n\nIf no flags are passed it will add `--cflags` and `--libs` to pkgconfig (not to V).\nIn other words, both lines below do the same:\n\n```v oksyntax\n#pkgconfig r_core\n#pkgconfig --cflags --libs r_core\n```\n\nThe `.pc` files are looked up into a hardcoded list of default pkg-config paths, the user can add\nextra paths by using the `PKG_CONFIG_PATH` environment variable. Multiple modules can be passed.\n\nTo check the existence of a pkg-config use `$pkgconfig('pkg')` as a compile time \"if\" condition to\ncheck if a pkg-config exists. If it exists the branch will be created. Use `$else` or `$else $if`\nto handle other cases.\n\n```v ignore\n$if $pkgconfig('mysqlclient') {\n\t#pkgconfig mysqlclient\n} $else $if $pkgconfig('mariadb') {\n\t#pkgconfig mariadb\n}\n```\n\n### Including C code\n\nYou can also include C code directly in your V module.\nFor example, let's say that your C code is located in a folder named 'c' inside your module folder.\nThen:\n\n* Put a v.mod file inside the toplevel folder of your module (if you\n  created your module with `v new` you already have v.mod file). For example:\n\n```v ignore\nModule {\n\tname: 'mymodule',\n\tdescription: 'My nice module wraps a simple C library.',\n\tversion: '0.0.1'\n\tdependencies: []\n}\n```\n\n* Add these lines to the top of your module:\n\n```v oksyntax\n#flag -I @VMODROOT/c\n#flag @VMODROOT/c/implementation.o\n#include \"header.h\"\n```\n\n> [!NOTE]\n> @VMODROOT will be replaced by V with the *nearest parent folder,\n> where there is a v.mod file*.\n> Any .v file beside or below the folder where the v.mod file is,\n> can use `#flag @VMODROOT/abc` to refer to this folder.\n> The @VMODROOT folder is also *prepended* to the module lookup path,\n> so you can *import* other modules under your @VMODROOT, by just naming them.\n\nThe instructions above will make V look for an compiled .o file in\nyour module `folder/c/implementation.o`.\nIf V finds it, the .o file will get linked to the main executable, that used the module.\nIf it does not find it, V assumes that there is a `@VMODROOT/c/implementation.c` file,\nand tries to compile it to a .o file, then will use that.\n\nThis allows you to have C code, that is contained in a V module, so that its distribution is easier.\nYou can see a complete minimal example for using C code in a V wrapper module here:\n[project_with_c_code](https://github.com/vlang/v/tree/master/vlib/v/tests/project_with_c_code).\nAnother example, demonstrating passing structs from C to V and back again:\n[interoperate between C to V to C](https://github.com/vlang/v/tree/master/vlib/v/tests/project_with_c_code_2).\n\n### C types\n\nOrdinary zero terminated C strings can be converted to V strings with\n`unsafe { &char(cstring).vstring() }` or if you know their length already with\n`unsafe { &char(cstring).vstring_with_len(len) }`.\n\n> [!NOTE]\n> The `.vstring()` and `.vstring_with_len()` methods do NOT create a copy of the `cstring`,\n> so you should NOT free it after calling the method `.vstring()`.\n> If you need to make a copy of the C string (some libc APIs like `getenv` pretty much require that,\n> since they return pointers to internal libc memory), you can use `cstring_to_vstring(cstring)`.\n\nOn Windows, C APIs often return so called `wide` strings (UTF-16 encoding).\nThese can be converted to V strings with `string_from_wide(&u16(cwidestring))` .\n\nV has these types for easier interoperability with C:\n\n- `voidptr` for C's `void*`,\n- `&u8` for C's `byte*` and\n- `&char` for C's `char*`.\n- `&&char` for C's `char**`\n\nTo cast a `voidptr` to a V reference, use `user := &User(user_void_ptr)`.\n\n`voidptr` can also be dereferenced into a V struct through casting: `user := User(user_void_ptr)`.\n\n[an example of a module that calls C code from V](https://github.com/vlang/v/blob/master/vlib/v/tests/project_with_c_code/mod1/wrapper.c.v)\n\n### C Declarations\n\nC identifiers are accessed with the `C` prefix similarly to how module-specific\nidentifiers are accessed. Functions must be redeclared in V before they can be used.\nAny C types may be used behind the `C` prefix, but types must be redeclared in V in\norder to access type members.\n\nTo redeclare complex types, such as in the following C code:\n\n```c\nstruct SomeCStruct {\n\tuint8_t implTraits;\n\tuint16_t memPoolData;\n\tunion {\n\t\tstruct {\n\t\t\tvoid* data;\n\t\t\tsize_t size;\n\t\t};\n\n\t\tDataView view;\n\t};\n};\n```\n\nmembers of sub-data-structures may be directly declared in the containing struct as below:\n\n```v\npub struct C.SomeCStruct {\n\timplTraits  u8\n\tmemPoolData u16\n\t// These members are part of sub data structures that can't currently be represented in V.\n\t// Declaring them directly like this is sufficient for access.\n\t// union {\n\t// struct {\n\tdata voidptr\n\tsize usize\n\t// }\n\tview C.DataView\n\t// }\n}\n```\n\nThe existence of the data members is made known to V, and they may be used without\nre-creating the original structure exactly.\n\nAlternatively, you may [embed](#embedded-structs) the sub-data-structures to maintain\na parallel code structure.\n\n### Export to shared library\n\nBy default all V functions have the following naming scheme in C: `[module name]__[fn_name]`.\n\nFor example, `fn foo() {}` in module `bar` will result in `bar__foo()`.\n\nTo use a custom export name, use the `@[export]` attribute:\n\n```\n@[export: 'my_custom_c_name']\nfn foo() {\n}\n```\n\n### Translating C to V\n\nV can translate your C code to human readable V code, and generating V wrappers\non top of C libraries.\n\nC2V currently uses Clang's AST to generate V, so to translate a C file to V\nyou need to have Clang installed on your machine.\n\nLet's create a simple program `test.c` first:\n\n```c\n#include \"stdio.h\"\n\nint main() {\n\tfor (int i = 0; i < 10; i++) {\n\t\tprintf(\"hello world\\n\");\n\t}\n        return 0;\n}\n```\n\nRun `v translate test.c`, and V will generate `test.v`:\n\n```v\nfn main() {\n\tfor i := 0; i < 10; i++ {\n\t\tprintln('hello world')\n\t}\n}\n```\n\nTo generate a wrapper on top of a C library use this command:\n\n```bash\nv translate wrapper c_code/libsodium/src/libsodium\n```\n\nThis will generate a directory `libsodium` with a V module.\n\nExample of a C2V generated libsodium wrapper:\n\nhttps://github.com/vlang/libsodium\n\n<br>\n\nWhen should you translate C code and when should you simply call C code from V?\n\nIf you have well-written, well-tested C code,\nthen of course you can always simply call this C code from V.\n\nTranslating it to V gives you several advantages:\n\n- If you plan to develop that code base, you now have everything in one language,\n  which is much safer and easier to develop in than C.\n- Cross-compilation becomes a lot easier. You don't have to worry about it at all.\n- No more build flags and include files either.\n\n### Working around C issues\n\nIn some cases, C interop can be extremely difficult.\nOne of these such cases is when headers conflict with each other.\nFor example, V needs to include the Windows header libraries in order for your V binaries to work\nseamlessly across all platforms.\n\nHowever, since the Windows header libraries use extremely generic names such as `Rectangle`,\nthis will cause a conflict if you wish to use C code that also has a name defined as `Rectangle`.\n\nFor very specific cases like this, V has `#preinclude` and `#postinclude` directives.\n\nThese directives allow things to be configured *before* V adds in its built in libraries,\nand *after* all of the V code generation has completed (and thus all of the prototypes,\ndeclarations and definitions are already present).\n\nExample usage:\n```v ignore\n// This will include before built in libraries are used.\n#preinclude \"pre_include.h\"\n\n// This will include after built in libraries are used.\n#include \"include.h\"\n\n// This will include after all of the V code generation is complete,\n// including the one for the main function of the project\n#postinclude \"post_include.h\"\n```\n\nAn example of what might be included in `pre_include.h`\ncan be [found here](https://github.com/irishgreencitrus/raylib.v/blob/main/include/pre.h)\n\nThe `#postinclude` directive on the other hand is useful for allowing the integration\nof frameworks like SDL3 or Sokol, that insist on having callbacks in your code, instead\nof behaving like ordinary libraries, and allowing you to decide when to call them.\n\nNOTE: these are advanced features, and will not be necessary outside of very specific cases\nwith C interop. Other than those, using them could cause more issues than it solves.\n\nConsider using them as a last resort!\n\n## Other V Features\n\n### Inline assembly\n\n<!-- ignore because it doesn't pass fmt test (why?) -->\n\n```v ignore\na := 100\nb := 20\nmut c := 0\nasm amd64 {\n    mov eax, a\n    add eax, b\n    mov c, eax\n    ; =r (c) as c // output\n    ; r (a) as a // input\n      r (b) as b\n}\nprintln('a: ${a}') // 100\nprintln('b: ${b}') // 20\nprintln('c: ${c}') // 120\n```\n\nFor more examples, see\n[vlib/v/slow_tests/assembly/asm_test.amd64.v](https://github.com/vlang/v/tree/master/vlib/v/slow_tests/assembly/asm_test.amd64.v)\n\n### Hot code reloading\n\n```v live\nmodule main\n\nimport time\n\n@[live]\nfn print_message() {\n\tprintln('Hello! Modify this message while the program is running.')\n}\n\nfn main() {\n\tfor {\n\t\tprint_message()\n\t\ttime.sleep(500 * time.millisecond)\n\t}\n}\n```\n\nBuild this example with `v -live message.v`.\n\nYou can also run this example with `v -live run message.v`.\nMake sure that in command you use a path to a V's file,\n**not** a path to a folder (like `v -live run .`) -\nin that case you need to modify content of a folder (add new file, for example),\nbecause changes in *message.v* will have no effect.\n\nFunctions that you want to be reloaded must have `@[live]` attribute\nbefore their definition.\n\nRight now it's not possible to modify types while the program is running.\n\nMore examples, including a graphical application:\n[github.com/vlang/v/tree/master/examples/hot_reload](https://github.com/vlang/v/tree/master/examples/hot_reload).\n\n#### About keeping states in hot reloading functions with v -live run\nV's hot code reloading relies on marking the functions that you want to reload with `@[live]`,\nthen compiling a shared library of these `@[live]` functions, and then\nyour v program loads that shared library at runtime.\n\nV (with the -live option) starts a new thread, that monitors the source files for changes,\nand when it detects modifications, it recompiles the shared library, and reloads it at runtime,\nso that new calls to those @[live] functions will be made to the newly loaded library.\n\nIt keeps all the accumulated state (from locals outside the @[live] functions,\nfrom heap variables and from globals), allowing to tweak the code in the merged functions quickly.\n\nWhen there are more substantial changes (to data structures, or to functions that were not marked),\nyou will have to restart the running app manually.\n\n### Cross-platform shell scripts in V\n\nV can be used as an alternative to Bash to write deployment scripts, build scripts, etc.\n\nThe advantage of using V for this, is the simplicity and predictability of the language, and\ncross-platform support. \"V scripts\" run on Unix-like systems, as well as on Windows.\n\nTo use V's script mode, save your source file with the `.vsh` file extension.\nIt will make all functions in the `os` module global (so that you can use `mkdir()` instead\nof `os.mkdir()`, for example).\n\nV also knows to compile & run `.vsh` files immediately, so you do not need a separate\nstep to compile them. V will also recompile an executable, produced by a `.vsh` file,\n*only when it is older than the .vsh source file*, i.e. runs after the first one, will\nbe faster, since there is no need for a re-compilation of a script, that has not been changed.\n\nAn example `deploy.vsh`:\n\n```v oksyntax\n#!/usr/bin/env -S v\n\n// Note: The shebang line above, associates the .vsh file to V on Unix-like systems,\n// so it can be run just by specifying the path to the .vsh file, once it's made\n// executable, using `chmod +x deploy.vsh`, i.e. after that chmod command, you can\n// run the .vsh script, by just typing its name/path like this: `./deploy.vsh`\n\n// print command then execute it\nfn sh(cmd string) {\n\tprintln('❯ ${cmd}')\n\tprint(execute_or_exit(cmd).output)\n}\n\n// Remove if build/ exits, ignore any errors if it doesn't\nrmdir_all('build') or {}\n\n// Create build/, never fails as build/ does not exist\nmkdir('build')!\n\n// Move *.v files to build/\nresult := execute('mv *.v build/')\nif result.exit_code != 0 {\n\tprintln(result.output)\n}\n\nsh('ls')\n\n// Similar to:\n// files := ls('.')!\n// mut count := 0\n// if files.len > 0 {\n//     for file in files {\n//         if file.ends_with('.v') {\n//              mv(file, 'build/') or {\n//                  println('err: ${err}')\n//                  return\n//              }\n//         }\n//         count++\n//     }\n// }\n// if count == 0 {\n//     println('No files')\n// }\n```\n\nNow you can either compile this like a normal V program and get an executable you can deploy and run\nanywhere:\n`v -skip-running deploy.vsh && ./deploy`\n\nOr run it like a traditional Bash script:\n`v run deploy.vsh` (or simply just `v deploy.vsh`)\n\nOn Unix-like platforms, the file can be run directly after making it executable using `chmod +x`:\n`./deploy.vsh`\n\n### Vsh scripts with no extension\n\nWhilst V does normally not allow vsh scripts without the designated file extension, there is a way\nto circumvent this rule and have a file with a fully custom name and shebang. Whilst this feature\nexists it is only recommended for specific usecases like scripts that will be put in the path and\nshould **not** be used for things like build or deploy scripts. To access this feature start the\nfile with `#!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp` where `tmp` is the prefix for\nthe built executable. This will run in crun mode so it will only rebuild if changes to the script\nwere made and keep the binary as `tmp.<scriptfilename>`. **Caution**: if this filename already\nexists the file will be overridden. If you want to rebuild each time and not keep this binary\ninstead use `#!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp run`.\n\nNote: there is a small shell script `cmd/tools/vrun`, that can be useful for systems, that have an\nenv program (`/usr/bin/env`), that still does not support an `-S` option (like BusyBox and OpenBSD).\nSee https://github.com/vlang/v/blob/master/cmd/tools/vrun for more details.\n\n# Appendices\n\n## Appendix I: Keywords\n\nV has 45 reserved keywords (3 are literals):\n\n```v ignore\nas\nasm\nassert\natomic\nbreak\nconst\ncontinue\ndefer\nelse\nenum\nfalse\nfn\nfor\ngo\ngoto\nif\nimplements\nimport\nin\ninterface\nis\nisreftype\nlock\nmatch\nmodule\nmut\nnone\nor\npub\nreturn\nrlock\nselect\nshared\nsizeof\nspawn\nstatic\nstruct\ntrue\ntype\ntypeof\nunion\nunsafe\nvolatile\n__global\n__offsetof\n```\n\nSee also [V Types](#v-types).\n\n## Appendix II: Operators\n\nThis lists operators for [primitive types](#primitive-types) only.\n\n```v ignore\n+    sum                    integers, floats, strings\n-    difference             integers, floats\n*    product                integers, floats\n/    quotient               integers, floats\n%    remainder              integers\n\n~    bitwise NOT            integers\n&    bitwise AND            integers\n|    bitwise OR             integers\n^    bitwise XOR            integers\n\n!    logical NOT            bools\n&&   logical AND            bools\n||   logical OR             bools\n!=   logical XOR            bools\n\n<<   left shift             integer << unsigned integer\n>>   right shift            integer >> unsigned integer\n>>>  unsigned right shift   integer >> unsigned integer\n\n\nPrecedence    Operator\n    5            *  /  %  <<  >> >>> &\n    4            +  -  |  ^\n    3            ==  !=  <  <=  >  >=\n    2            &&\n    1            ||\n\n\nAssignment Operators\n+=   -=   *=   /=   %=\n&=   |=   ^=\n>>=  <<=  >>>=\n&&= ||=\n```\n\nNote: in V, `assert -10 % 7 == -3` passes. In programming, the sign of the remainder\ndepends upon the signs of divisor and dividend.\n\n## Other online resources\n\n### [V contributing guide](https://github.com/vlang/v/blob/master/CONTRIBUTING.md)\n\nV would be much less, than what it is today, without the help of all\nits contributors. If you like and want to help the V project succeed,\nplease read that document, choose a task, and dive in!\n\n### [V language documentation](https://docs.vlang.io/introduction.html)\nThe site has the same information as this document, but split to pages,\nfor easier reading on mobile devices. Updated automatically on each\ncommit to the main repository.\n\n### [V standard module documentation](https://modules.vlang.io/)\nThe site has the documentation of all the modules in V's standard\nlibrary (vlib). Updated automatically on each commit to the main\nrepository.\n\n### [V online playground](https://play.vlang.io/)\nThe site allows you to enter and edit small V programs, then compile\nand run them. Updated automatically on each commit to the main\nrepository. Use it, to test your ideas, when you do not have access\nto a computer or an Android phone, where V has been already installed.\n\n### [Awesome V](https://github.com/vlang/awesome-v)\nWhen you make a cool new project or a library, you can submit it to that\nlist too. You can also use the list, for ideas about new projects to do\nwith V.\n\n### [The V language Discord](https://discord.gg/vlang)\nThis is the place to be, to discuss the V language, learn about latest\ndevelopments, quickly get help with issues, witness/participate in\n~~epic flame wars~~ constructive criticism exchanges and design decisions.\nJoin it, and learn more about languages, games, editors, people, Klingons,\nConway's law and the universe.\n"
  },
  {
    "path": "doc/packaging_v_for_distributions.md",
    "content": "Packaging V\n=============\n\nThank you for supporting V and its users, and for creating, *and maintaining* a package for it.\n\nV is still changing, and installing it from source, is still the *recommended way*, to\ndistribute it to most V users.\n\nHowever, we understand that sooner or later people will want to adapt the\nupstream source to their favorite distro/platform, and that usually involves preparing a package\nthat will be installed and updated (using a standardized package manager) just like all other\nprograms in the distribution.\n\nThis document is for the brave people that want to prepare and\n*maintain* such a package.\n\nGood luck.\n\nDetails\n=============\n\nPreparing a package of the current version of V for distribution, has some peculiarities\nthat must be understood, and taken into account, for the best experience of the users of\nyour package, for your sanity, and for easier troubleshooting of problems when they happen.\n\n1) V builds many of its commands on demand, to save both time and space. The source of the\nentry points of those commands is stored in the folder cmd/tools/ . If you are preparing a\nprebuilt V package, that needs to ensure that the final package after installation will be\nread only, that will be a problem, since V will try to write to its cmd/tools/ folder.\nTo prevent that, you need to build *all* the commands/executables in that folder *ahead of time*.\nThis can be done by the command `v build-tools`.\n\n2) Tell V to not try to recompile its tools anymore. To do that, V supports checking for the\npresence of a file named `cmd/tools/.disable_autorecompilation` (that file is missing by default\nin the cloned version of V).\nNote: the content of this file does not matter, *only its presence does*.\n\n3) V has a tool/command, that enables rapid updating from the latest master branch in its main\nrepository. That tool is `v up`. Most distros however, have the policy of not allowing packages\nto make modifications to themselves. Instead, they require the user to use their package manager,\nprovided by the distro/platform.\n\nTo facilitate that, it is usually best for all involved if you, as a package maintainer, remove\nor replace cmd/tools/vup.v, with a short v program, that advises the final V user to use the\npackage manager tool, or to use a V installed from source instead.\n\n4) Another V feature/command that can interfere with read only packaging is `v self`. We\nrecommend that you disable this command as well, by replacing cmd/tools/vself.v with a small\nV program that informs the user that `v self` is not recommended when used with a packaged\nversion of V, and then advises the user to install V from source if he wants to use `v self`.\n\n5) The V source repo contains sizable folders like `.git/` and `thirdparty/tcc/.git/` which will\nnot be needed by users of packages (they are not useful if `v up` is disabled,\nas recommended previously). Some other files, such as `Makefile`, `make.bat`, and `GNUmakefile`\nwill not be used either, so they can also be safely removed.\n\nDepending on how stripped you want your package, you can remove the examples/ folder as well.\nIt is usually good to have examples, but they could be in a separate package.\n\nIf a user attempts to compile the examples in that folder, it\nwill not work in a read-only package (because the executables are put right next to the \nsource `.v` files by default, unless `-o path_to_executable_name` is used).\n\n6) Location of vlib/ . V expects, that its vlib/ folder, will be located right next to its\nexecutable, and that is currently hard to customize. It will be changed, if there is enough\ninterest from package maintainers, expressed on the V issue tracker:\nhttps://github.com/vlang/v/issues\n\n*However, you can* leave the executable in say /opt/vlang/v, with vlib/ in /opt/vlang/vlib/ ,\nthen put a symlink from `/opt/vlang/v` to whatever folder that is on the user's PATH on your\ndistro, i.e.: `sudo ln -s /opt/vlang/v /usr/bin/v` or `sudo ln -s /opt/vlang/v /bin/v` .\n\n7) Location of the V executable can be controlled by setting the env variable VEXE.\nIt defaults to the absolute path of the V executable.\n\n8) Location of the modules folder for `v install` can be controlled by setting the env variable\nnamed `VMODULES`. By default, modules are installed to `~/.vmodules`,\n(`C:\\Users\\<user id>\\.vmodules` on Windows).\n\n9) Location of the folder used by V for its temporary files can be controlled by setting the env\nvariable `VTMP`.  By default, the system TEMP folder is used.\n\n10) Setting additional V flags for each compilation can be done by setting the env variable\n`VFLAGS`.\n\nNote: points 7, 8, 9, 10 above, allow you to create a small launcher shell script, named `v`,\nthat sets those variables dynamically, according to the current user. You can then put\n*this shell script* inside your package bin folder, i.e. inside /usr/bin/v, or /bin/v etc,\n*instead of* the main V executable, or a symlink to it.\n\n\nExample script to prepare the V source folder for packaging:\n-----------------------------------------------------------\n\nCombining all of the above, here is a small script, that can be used as a base for your packaging\nefforts:\n\n```sh\necho \"println('use your package manager to update V,\" > cmd/tools/vup.v\necho \"or if you want more recent V versions, just clone V from source,\" >> cmd/tools/vup.v\necho \"see https://github.com/vlang/v#installing-v-from-source')\" >> cmd/tools/vup.v\n\necho \"println('v self is disabled for packaged versions of V.\" > cmd/tools/vself.v\necho \"Use your package manager, to update your V package instead.\" >> cmd/tools/vself.v\necho \"Alternatively, if you do want a more recent V version, just clone V from source,\" >> cmd/tools/vself.v\necho \"then follow the instructions here: https://github.com/vlang/v#installing-v-from-source')\" >> cmd/tools/vself.v\n\nv -prod -o v cmd/v                            ## build V itself with -prod\n./v -prod build-tools                         ## build all tools with -prod too\ntouch ./cmd/tools/.disable_autorecompilation  ## tell V to not try to recompile any tool anymore\n\n### Cleanup folders that would not be needed inside a package,\n### that is distributed separately from the V source repository:\nrm -rf .git/\nrm -rf thirdparty/tcc/.git/\n```\n\nExample `v` script for your bin folder:\n--------------------------------------------------\n\n```sh\n#!/usr/bin/env bash\n\nexport VEXE=\"/opt/vlang/v\"\nexport VFLAGS=\"-cc /usr/bin/custom_cc\"\nexport VCACHE=\"/var/cache/custom_vcache_folder\" ## ~/.vmodules/cache by default\nexport VTMP=\"/var/cache/custom_tmp\"\nexport VMODULES=\"$HOME/.vmodules\"\n\n/opt/vlang/v $@\n```\n\nNote: do not forget to also do this in your post install script: `chmod +x /usr/bin/v`\n"
  },
  {
    "path": "doc/upcoming.md",
    "content": "# V Work In Progress\n\n***This document describes features that are not implemented, yet.\nPlease refer to [docs.md](https://github.com/vlang/v/blob/master/doc/docs.md)\nfor the current state of V***\n\n## Table of Contents\n\n* [Concurrency](#concurrency)\n    * [Variable Declarations](#variable-declarations)\n    * [Strengths](#strengths)\n    * [Weaknesses](#weaknesses)\n    * [Compatibility](#compatibility)\n    * [Automatic Lock](#automatic-lock)\n    * [Channels](#channels)\n\n## Concurrency\n\n### Variable Declarations\n\nObjects that are supposed to be used to exchange data between\ncoroutines have to be declared with special care. Exactly one of the following\n4 kinds of declaration has to be chosen:\n\n```v ignore\na := ...\nmut b := ...\nshared c := ...\natomic d := ...\n```\n\n- `a` is declared as *constant* that can be passed to\n  other coroutines and read without limitations. However\n  it cannot be changed.\n- `b` can be accessed reading and writing but only from one\n  coroutine. That coroutine *owns* the object. A `mut` variable can\n  be passed to another coroutine (as receiver or function argument in\n  the `go` statement or via a channel) but then ownership is passed,\n  too, and only the other coroutine can access the object.<sup>1</sup>\n- `c` can be passed to coroutines an accessed\n  *concurrently*.<sup>2</sup> In order to avoid data races it has to\n  be locked before access can occur and unlocked to allow access to\n  other coroutines. This is done by one the following block structures:\n  ```v ignore\n  lock c {\n      // read, modify, write c\n      ...\n  }\n  ```\n\n  ```v ignore\n  rlock c {\n      // read c\n      ...\n  }\n  ```\n  Several variables may be specified: `lock x, y, z { ... }`.\n  They are unlocked in the opposite order.\n- `d` can be passed to coroutines and accessed *concurrently*,\n  too.<sup>3</sup> No lock is needed in this case, however\n  `atomic` variables can only be 32/64 bit integers (or pointers)\n  and access is limited to a small set of predefined idioms that have\n  native hardware support.\n\nTo help making the correct decision the following table summarizes the\ndifferent capabilities:\n\n|                          | *default* | `mut` | `shared` | `atomic` |\n|:-------------------------|:---------:|:-----:|:--------:|:--------:|\n| write access             |           |   +   |    +     |    +     |\n| concurrent access        |     +     |       |    +     |    +     |\n| performance              |    ++     |  ++   |          |    +     |\n| sophisticated operations |     +     |   +   |    +     |          |\n| structured data types    |     +     |   +   |    +     |          |\n\n### Strengths\n\n**default**\n\n- very fast\n- unlimited access from different coroutines\n- easy to handle\n\n**`mut`**\n\n- very fast\n- easy to handle\n\n**`shared`**\n\n- concurrent access from different coroutines\n- data type may be complex structure\n- sophisticated access possible (several statements within one `lock`\n  block)\n\n**`atomic`**\n\n- concurrent access from different coroutines\n- reasonably fast\n\n### Weaknesses\n\n**default**\n\n- read only\n\n**`mut`**\n\n- access only from one coroutine at a time\n\n**`shared`**\n\n- lock/unlock are slow\n- moderately difficult to handle (needs `lock` block)\n\n**`atomic`**\n\n- limited to single (max. 64 bit) integers (and pointers)\n- only a small set of predefined operations possible\n- very difficult to handle correctly\n\n<sup>1</sup> The owning coroutine will also free the memory space used\nfor the object when it is no longer needed.  \n<sup>2</sup> For `shared` objects the compiler adds code for reference\ncounting. Once the counter reaches 0 the object is automatically freed.  \n<sup>3</sup> Since an `atomic` variable is only a few bytes in size\nallocation would be an unnecessary overhead. Instead the compiler\ncreates a global.\n\n### Compatibility\n\nOutside of `lock`/`rlock` blocks function arguments must in general\nmatch - with the familiar exception that objects declared `mut` can be\nused to call functions expecting immutable arguments:\n\n```v ignore\nfn f(x St) {...}\nfn g(mut x St) {...}\nfn h(shared x St) {...}\nfn i(atomic x u64) {...}\n\na := St{...}\nf(a)\n\nmut b := St{...}\nf(b)\ngo g(mut b)\n// `b` should not be accessed here anymore\n\nshared c := St{...}\nh(shared c)\n\natomic d &u64\ni(atomic d)\n```\n\nInside a `lock c {...}` block `c` behaves like a `mut`,\ninside an `rlock c {...}` block like an immutable:\n\n```v ignore\nshared c := St{...}\nlock c {\n    g(mut c)\n    f(c)\n    // call to h() not allowed inside `lock` block\n    // since h() will lock `c` itself\n}\nrlock c {\n    f(c)\n    // call to g() or h() not allowed\n}\n```\n\n### Automatic Lock\n\nIn general the compiler will generate an error message when a `shared`\nobject is accessed outside of any corresponding `lock`/`rlock`\nblock. However in simple and obvious cases the necessary lock/unlock\ncan be generated automatically for `array`/`map` operations:\n\n```v ignore\nshared a := []int{cap: 5}\ngo h2(shared a)\na << 3\n// keep in mind that `h2()` could change `a` between these statements\na << 4\nx := a[1] // not necessarily `4`\n\nshared b := map[string]int{}\ngo h3(shared b)\nb['apple'] = 3\nc['plume'] = 7\ny := b['apple'] // not necessarily `3`\n\n// iteration over elements\nfor k, v in b {\n    // concurrently changed k/v pairs may or may not be included\n}\n```\n\nThis is handy, but since other coroutines might access the `array`/`map`\nconcurrently between the automatically locked statements, the results\nare sometimes surprising. Each statement should be seen as a single\ntransaction that is unrelated to the previous or following\nstatement. Therefore - but also for performance reasons - it's often\nbetter to group consecutive coherent statements in an explicit `lock` block.\n\n### Channels\n"
  },
  {
    "path": "doc/vscode.md",
    "content": "# Visual Studio Code Setup\n\n## Table of Contents\n\n* [V language support](#v-language-support)\n* [Visual Debugging](#visual-debugging)\n\n## V language support\n\nThe [V VS Code Extension](https://marketplace.visualstudio.com/items?itemName=vlanguage.vscode-vlang)\nprovides V language support for Visual Studio Code.\n\n![Screenshot Code with activated extension](https://github.com/vlang/vscode-vlang/raw/HEAD/images/demo.png)\n\n**Features:**\n\n* Syntax Highlighting.\n* Code Snippets for quick coding.\n* Format code on file save as well as format manually (using v fmt).\n* Linter (Workspace files only).\n  [more](https://marketplace.visualstudio.com/items?itemName=vlanguage.vscode-vlang)\n\n**Hint:** This extension will not add the V compiler! Information on how to\n[install V compiler](https://github.com/vlang/v/blob/master/doc/docs.md#install-from-source)\non your operating system.\n\n### Setup Extension\n\nInstall [V VS Code Extension](https://marketplace.visualstudio.com/items?itemName=vlanguage.vscode-vlang).\n\n## Visual Debugging\n\n![screenshot visual debugger](https://github.com/vlang/v/blob/master/doc/img/vscode-debugger.png?raw=true)\n\nThe [C/C++ Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)\nfor Visual Studio Code provides visual conditional debugging.\n\n**Features:**\n\n* Conditional breakpoints\n* Function breakpoints\n* Expression evaluation\n* Change Values\n  [more Features & Documentation](https://code.visualstudio.com/docs/cpp/cpp-debug)\n\n**Hint:** Not all types (e.g. Array) in V currently create the required\n[DWARF](https://en.wikipedia.org/wiki/DWARF) information to show and\nedit the variable.\n\n### Setup Debugging\n\n#### Step1: Configure the launch.json file\n\n1. Install the\n   [C/C++ Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)\n2. Open `RUN AND DEBUG` panel (Debug Icon in left panel).\n3. Click on `Show` all automatic debug configurations.\n4. Select `Add config`.\n5. Select environment `C++ (GDB/LLDB)`.\n6. Change the line `\"program\": \"Enter the program name, e.g. \\\"${workspaceFolder}/a.out\\\"\",`\n   to point to your compiled application e.g. `\"program\": \"${workspaceFolder}/hello\",`\n   or a more flexible one `\"program\": \"${fileDirname}/${fileBasenameNoExtension}\",`\n   when you want to debug the current opened file.\n\nThis will add a block to your `.workspace` file,\nor create the file `.vscode/launch.json`:\n\n```json\n{\n    // Use IntelliSense to learn about possible attributes.\n    // Hover to view descriptions of existing attributes.\n    // For more information, visit: \n    // https://go.microsoft.com/fwlink/?linkid=830387\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \"(lldb) Start\",\n            \"type\": \"cppdbg\",\n            \"request\": \"launch\",\n            \"program\": \"Enter the program name, e.g. \\\"${workspaceFolder}/a.out\\\"\",\n            \"args\": [],\n            \"stopAtEntry\": false,\n            \"cwd\": \"${fileDirname}\",\n            \"environment\": [],\n            \"externalConsole\": false,\n            \"MIMode\": \"lldb\",\n\t    \"preLaunchTask\": \"build\"\n        }\n    ]\n}\n```\n\n**Optional:** use `\"program\": \"${fileDirname}/${fileBasenameNoExtension}\"` to debug\nany current open source file with an existing binary with the same name but without any extension.\n\n#### Step2: Configure the tasks.json file\n\nGenerally, you can manually compile the application with: `v -b c -g hello.v -o hello`,\nor for short: `v -g hello.v`, and then call the debugger.\n\nThe `-g` option will add the needed debugging information.\nYou can find more debugging options in the [docs](docs.md#debugging).\n\nVS Code provides a hook called `preLaunchTask`, which can be used to compile\nthe application automatically every time you call the debugger.\n[preLaunchTask](https://code.visualstudio.com/docs/editor/debugging#_launchjson-attributes) launches\na task before the start of a debug session, set this attribute to the label of a task specified\nin [task.json](https://code.visualstudio.com/docs/editor/tasks) (in the workspace's .vscode folder).\nOr, this can be set to `${defaultBuildTask}`, to use your default build task.\n\nAs explained, the `\"preLaunchTask\": \"build\"` needs to work with a `.vscode/tasks.json`\nwith a label named `build`.\n\n```json\n{\n    // See https://go.microsoft.com/fwlink/?LinkId=733558\n    // for the documentation about the tasks.json format\n    \"version\": \"2.0.0\",\n    \"tasks\": [\n        {\n            \"label\": \"build\",\n            \"type\": \"shell\",\n            \"command\": \"v\",\n            \"args\": [\n                \"-g\",\t\t    // add more compiler options here if necessary\n                \"${relativeFile}\"   // or modify it according to your requirements\n            ],\n            \"group\": \"build\",\n            \"presentation\": {\n                \"reveal\": \"never\"\n            },\n            \"problemMatcher\": {\n                \"owner\": \"v\",\n                \"fileLocation\": [\"relative\", \"${workspaceFolder}\"],\n                \"pattern\": {\n                    \"regexp\": \"^(.*):(\\\\d+):(\\\\d+):\\\\s+(warning|error):\\\\s+(.*)$\",\n                    \"file\": 1,\n                    \"line\": 2,\n                    \"column\": 3,\n                    \"severity\": 4,\n                    \"message\": 5\n                }\n            }\n        }\n    ]\n}\n```\n\n### Usage\n\nTo allow your compiled application to be debugged.\nThe application needs to include additional debugging information\n([DWARF](https://en.wikipedia.org/wiki/DWARF)).\n\n1. Open your source code and set the required break points\n2. Click on the Debug Icon in the left Icon panel and click\n   `> (lldb) Start`, or use `F5` to launch your application in debug mode.\n\nFor all options look at the official\n[C/C++ Extension documentation](https://code.visualstudio.com/docs/cpp/cpp-debug).\n"
  },
  {
    "path": "editors/vim/README.md",
    "content": "# V Vim/Neovim runtime files\n\nThis directory contains official V runtime files for Vim and Neovim:\n\n- `ftdetect/v.vim`\n- `ftplugin/v.vim`\n- `syntax/v.vim`\n\n## Install in Vim\n\n```sh\nmkdir -p ~/.vim/pack/vlang/start\nln -s /path/to/v/editors/vim ~/.vim/pack/vlang/start/vlang\n```\n\n## Install in Neovim\n\n```sh\nmkdir -p ~/.local/share/nvim/site/pack/vlang/start\nln -s /path/to/v/editors/vim ~/.local/share/nvim/site/pack/vlang/start/vlang\n```\n\nRestart Vim/Neovim after installation.\n"
  },
  {
    "path": "editors/vim/ftdetect/v.vim",
    "content": "\" Vim filetype detection for the V language.\n\naugroup v_filetypedetect\n\tautocmd!\n\tautocmd BufRead,BufNewFile *.v,*.vsh,*.vv setfiletype v\naugroup END\n"
  },
  {
    "path": "editors/vim/ftplugin/v.vim",
    "content": "\" Vim filetype plugin for the V language.\n\nif exists('b:did_ftplugin')\n\tfinish\nendif\nlet b:did_ftplugin = 1\n\nsetlocal commentstring=//\\ %s\nsetlocal comments=s1:/*,mb:*,ex:*/,://\nsetlocal suffixesadd=.v,.vsh\n\nlet b:undo_ftplugin = 'setlocal commentstring< comments< suffixesadd<'\n"
  },
  {
    "path": "editors/vim/syntax/v.vim",
    "content": "\" Vim syntax file\n\" Language: V\n\" Maintainer: V contributors\n\nif exists('b:current_syntax')\n\tfinish\nendif\n\nsyn case match\n\nsyn keyword vTodo TODO FIXME XXX NOTE BUG contained\nsyn match vComment +//.*$+ contains=vTodo,@Spell\nsyn region vComment start='/\\*' end='\\*/' contains=vTodo,@Spell\n\nsyn region vString start=+r'+ end=+'+\nsyn region vString start=+c'+ skip=+\\\\\\\\\\|\\\\'+ end=+'+ contains=vEscape,vInterpolation\nsyn region vString start=+'+ skip=+\\\\\\\\\\|\\\\'+ end=+'+ contains=vEscape,vInterpolation\nsyn region vChar start=+`+ skip=+\\\\\\\\\\|\\\\`+ end=+`+ contains=vEscape\n\nsyn match vEscape +\\\\[abfnrtv'\"`\\\\$]+ contained\nsyn match vEscape +\\\\x[0-9A-Fa-f]\\{2}+ contained\nsyn match vEscape +\\\\u[0-9A-Fa-f]\\{4}+ contained\nsyn region vInterpolation start=+\\${+ end=+}+ contained contains=vComptime,vNumber,vString,vChar,vOperator\n\nsyn match vNumber /\\v<0x[0-9A-Fa-f_]+>/\nsyn match vNumber /\\v<0b[01_]+>/\nsyn match vNumber /\\v<0o[0-7_]+>/\nsyn match vNumber /\\v<\\d[\\d_]*\\.\\d[\\d_]*([eE][+-]?\\d[\\d_]*)?>/\nsyn match vNumber /\\v<\\d[\\d_]*([eE][+-]?\\d[\\d_]*)?>/\n\nsyn keyword vBoolean true false\nsyn keyword vConstant none nil\nsyn keyword vKeyword as asm assert atomic break const continue defer else enum false for fn __global go goto if import in interface is match module mut shared lock rlock none nil return select sizeof isreftype _likely_ _unlikely_ __offsetof struct true type typeof dump or union pub static volatile unsafe spawn implements like ilike\nsyn keyword vType bool string rune i8 i16 int i64 i128 isize byte u8 u16 u32 u64 u128 usize f32 f64 char map chan any voidptr byteptr charptr\n\nsyn match vComptime /\\$[A-Za-z_][A-Za-z0-9_]*/\nsyn match vComptime /@[A-Z_][A-Z0-9_]*/\nsyn region vAttribute start=/@\\[/ end=/\\]/ contains=vComptime\n\nsyn match vOperator /::\\|:=\\|==\\|!=\\|<=\\|>=\\|<<=\\|>>=\\|>>>=\\|&&=\\|||=\\|<<\\|>>>\\|>>\\|&&\\|||\\|+=\\|-=\\|\\*=\\|\\/=\\|%=\\|\\^=\\||=\\|&=\\|<-\\|++\\|--/\nsyn match vOperator /[+\\-*\\/%&|^~!=<>?:]/\n\nsyn match vFunction /\\<[A-Za-z_][A-Za-z0-9_]*\\ze\\s*(/\n\nhi def link vTodo Todo\nhi def link vComment Comment\nhi def link vString String\nhi def link vChar Character\nhi def link vEscape SpecialChar\nhi def link vInterpolation Special\nhi def link vNumber Number\nhi def link vBoolean Boolean\nhi def link vConstant Constant\nhi def link vKeyword Keyword\nhi def link vType Type\nhi def link vComptime PreProc\nhi def link vAttribute PreProc\nhi def link vOperator Operator\nhi def link vFunction Function\n\nlet b:current_syntax = 'v'\n"
  },
  {
    "path": "examples/.gitignore",
    "content": "*.js\n*.log\n*.ppm\n"
  },
  {
    "path": "examples/1brc/README.md",
    "content": "# 1 Billion Row Challenge (1BRC)\n\nA solution to the [1 Billion Row Challenge](https://www.morling.dev/blog/one-billion-row-challenge/), \nwritten in [the V programming language](https://vlang.io/).\n\nRead more about the challenge here: https://www.morling.dev/blog/one-billion-row-challenge/\n\n\n## Running instructions\n\nSuggested compiler options for performance: \n\n`v -cc gcc -prod -cflags \"-std=c17 -march=native -mtune=native\" .`\n\n\n### Step 1: Create a measurements file\n\nCompile and run `make-samples` to create the sample file.\n\n```\ncd make-samples\nv -cc gcc -prod -cflags \"-std=c17 -march=native -mtune=native\" .\n./make-samples 1000000000 > ~/measurements.txt\n```\n\nNOTE: If you create a billion rows, the file will be about 12GB!\n\n### Step 2: Run (and time) the solution\n\n```\ncd solution\nv -cc gcc -prod -cflags \"-std=c17 -march=native -mtune=native\" .\n./solution ~/measurements.txt\n```\n\nYou can time the solution using `v time`:\n\n`v time ./solution ~/measurements.txt`\n\nBy default, the solution runs in a single thread. If you want to run\nparallel processing, use the `-n` parameter, for example, to run with \n8 threads:\n\n`./solution -n 8 ~/measurements.txt`\n\nOn Linux, to run one thread per core, use\n\n`./solution -n $(nproc) ~/measurements.txt`\n\n### Step 3: Improve upon the solution\n\nMake changes that improve the performance and submit them. \nLet's show off what is possible in V!\n"
  },
  {
    "path": "examples/1brc/make-samples/cities.txt",
    "content": "Abha,18.0\nAbidjan,26.0\nAbéché,29.4\nAccra,26.4\nAddis Ababa,16.0\nAdelaide,17.3\nAden,29.1\nAhvaz,25.4\nAlbuquerque,14.0\nAlexandra,11.0\nAlexandria,20.0\nAlgiers,18.2\nAlice Springs,21.0\nAlmaty,10.0\nAmsterdam,10.2\nAnadyr,-6.9\nAnchorage,2.8\nAndorra la Vella,9.8\nAnkara,12.0\nAntananarivo,17.9\nAntsiranana,25.2\nArkhangelsk,1.3\nAshgabat,17.1\nAsmara,15.6\nAssab,30.5\nAstana,3.5\nAthens,19.2\nAtlanta,17.0\nAuckland,15.2\nAustin,20.7\nBaghdad,22.77\nBaguio,19.5\nBaku,15.1\nBaltimore,13.1\nBamako,27.8\nBangkok,28.6\nBangui,26.0\nBanjul,26.0\nBarcelona,18.2\nBata,25.1\nBatumi,14.0\nBeijing,12.9\nBeirut,20.9\nBelgrade,12.5\nBelize City,26.7\nBenghazi,19.9\nBergen,7.7\nBerlin,10.3\nBilbao,14.7\nBirao,26.5\nBishkek,11.3\nBissau,27.0\nBlantyre,22.2\nBloemfontein,15.6\nBoise,11.4\nBordeaux,14.2\nBosaso,30.0\nBoston,10.9\nBouaké,26.0\nBratislava,10.5\nBrazzaville,25.0\nBridgetown,27.0\nBrisbane,21.4\nBrussels,10.5\nBucharest,10.8\nBudapest,11.3\nBujumbura,23.8\nBulawayo,18.9\nBurnie,13.1\nBusan,15.0\nCabo San Lucas,23.9\nCairns,25.0\nCairo,21.4\nCalgary,4.4\nCanberra,13.1\nCape Town,16.2\nChangsha,17.4\nCharlotte,16.1\nChiang Mai,25.8\nChicago,9.8\nChihuahua,18.6\nChișinău,10.2\nChittagong,25.9\nChongqing,18.6\nChristchurch,12.2\nCity of San Marino,11.8\nColombo,27.4\nColumbus,11.7\nConakry,26.4\nCopenhagen,9.1\nCotonou,27.2\nCracow,9.3\nDa Lat,17.9\nDa Nang,25.8\nDakar,24.0\nDallas,19.0\nDamascus,17.0\nDampier,26.4\nDar es Salaam,25.8\nDarwin,27.6\nDenpasar,23.7\nDenver,10.4\nDetroit,10.0\nDhaka,25.9\nDikson,-11.1\nDili,26.6\nDjibouti,29.9\nDodoma,22.7\nDolisie,24.0\nDouala,26.7\nDubai,26.9\nDublin,9.8\nDunedin,11.1\nDurban,20.6\nDushanbe,14.7\nEdinburgh,9.3\nEdmonton,4.2\nEl Paso,18.1\nEntebbe,21.0\nErbil,19.5\nErzurum,5.1\nFairbanks,-2.3\nFianarantsoa,17.9\nFlores,  Petén,26.4\nFrankfurt,10.6\nFresno,17.9\nFukuoka,17.0\nGabès,19.5\nGaborone,21.0\nGagnoa,26.0\nGangtok,15.2\nGarissa,29.3\nGaroua,28.3\nGeorge Town,27.9\nGhanzi,21.4\nGjoa Haven,-14.4\nGuadalajara,20.9\nGuangzhou,22.4\nGuatemala City,20.4\nHalifax,7.5\nHamburg,9.7\nHamilton,13.8\nHanga Roa,20.5\nHanoi,23.6\nHarare,18.4\nHarbin,5.0\nHargeisa,21.7\nHat Yai,27.0\nHavana,25.2\nHelsinki,5.9\nHeraklion,18.9\nHiroshima,16.3\nHo Chi Minh City,27.4\nHobart,12.7\nHong Kong,23.3\nHoniara,26.5\nHonolulu,25.4\nHouston,20.8\nIfrane,11.4\nIndianapolis,11.8\nIqaluit,-9.3\nIrkutsk,1.0\nIstanbul,13.9\nİzmir,17.9\nJacksonville,20.3\nJakarta,26.7\nJayapura,27.0\nJerusalem,18.3\nJohannesburg,15.5\nJos,22.8\nJuba,27.8\nKabul,12.1\nKampala,20.0\nKandi,27.7\nKankan,26.5\nKano,26.4\nKansas City,12.5\nKarachi,26.0\nKaronga,24.4\nKathmandu,18.3\nKhartoum,29.9\nKingston,27.4\nKinshasa,25.3\nKolkata,26.7\nKuala Lumpur,27.3\nKumasi,26.0\nKunming,15.7\nKuopio,3.4\nKuwait City,25.7\nKyiv,8.4\nKyoto,15.8\nLa Ceiba,26.2\nLa Paz,23.7\nLagos,26.8\nLahore,24.3\nLake Havasu City,23.7\nLake Tekapo,8.7\nLas Palmas de Gran Canaria,21.2\nLas Vegas,20.3\nLaunceston,13.1\nLhasa,7.6\nLibreville,25.9\nLisbon,17.5\nLivingstone,21.8\nLjubljana,10.9\nLodwar,29.3\nLomé,26.9\nLondon,11.3\nLos Angeles,18.6\nLouisville,13.9\nLuanda,25.8\nLubumbashi,20.8\nLusaka,19.9\nLuxembourg City,9.3\nLviv,7.8\nLyon,12.5\nMadrid,15.0\nMahajanga,26.3\nMakassar,26.7\nMakurdi,26.0\nMalabo,26.3\nMalé,28.0\nManagua,27.3\nManama,26.5\nMandalay,28.0\nMango,28.1\nManila,28.4\nMaputo,22.8\nMarrakesh,19.6\nMarseille,15.8\nMaun,22.4\nMedan,26.5\nMek'ele,22.7\nMelbourne,15.1\nMemphis,17.2\nMexicali,23.1\nMexico City,17.5\nMiami,24.9\nMilan,13.0\nMilwaukee,8.9\nMinneapolis,7.8\nMinsk,6.7\nMogadishu,27.1\nMombasa,26.3\nMonaco,16.4\nMoncton,6.1\nMonterrey,22.3\nMontreal,6.8\nMoscow,5.8\nMumbai,27.1\nMurmansk,0.6\nMuscat,28.0\nMzuzu,17.7\nN'Djamena,28.3\nNaha,23.1\nNairobi,17.8\nNakhon Ratchasima,27.3\nNapier,14.6\nNapoli,15.9\nNashville,15.4\nNassau,24.6\nNdola,20.3\nNew Delhi,25.0\nNew Orleans,20.7\nNew York City,12.9\nNgaoundéré,22.0\nNiamey,29.3\nNicosia,19.7\nNiigata,13.9\nNouadhibou,21.3\nNouakchott,25.7\nNovosibirsk,1.7\nNuuk,-1.4\nOdesa,10.7\nOdienné,26.0\nOklahoma City,15.9\nOmaha,10.6\nOranjestad,28.1\nOslo,5.7\nOttawa,6.6\nOuagadougou,28.3\nOuahigouya,28.6\nOuarzazate,18.9\nOulu,2.7\nPalembang,27.3\nPalermo,18.5\nPalm Springs,24.5\nPalmerston North,13.2\nPanama City,28.0\nParakou,26.8\nParis,12.3\nPerth,18.7\nPetropavlovsk-Kamchatsky,1.9\nPhiladelphia,13.2\nPhnom Penh,28.3\nPhoenix,23.9\nPittsburgh,10.8\nPodgorica,15.3\nPointe-Noire,26.1\nPontianak,27.7\nPort Moresby,26.9\nPort Sudan,28.4\nPort Vila,24.3\nPort-Gentil,26.0\nPortland {OR},12.4\nPorto,15.7\nPrague,8.4\nPraia,24.4\nPretoria,18.2\nPyongyang,10.8\nRabat,17.2\nRangpur,24.4\nReggane,28.3\nReykjavík,4.3\nRiga,6.2\nRiyadh,26.0\nRome,15.2\nRoseau,26.2\nRostov-on-Don,9.9\nSacramento,16.3\nSaint Petersburg,5.8\nSaint-Pierre,5.7\nSalt Lake City,11.6\nSan Antonio,20.8\nSan Diego,17.8\nSan Francisco,14.6\nSan Jose,16.4\nSan José,22.6\nSan Juan,27.2\nSan Salvador,23.1\nSana'a,20.0\nSanto Domingo,25.9\nSapporo,8.9\nSarajevo,10.1\nSaskatoon,3.3\nSeattle,11.3\nSégou,28.0\nSeoul,12.5\nSeville,19.2\nShanghai,16.7\nSingapore,27.0\nSkopje,12.4\nSochi,14.2\nSofia,10.6\nSokoto,28.0\nSplit,16.1\nSt. John's,5.0\nSt. Louis,13.9\nStockholm,6.6\nSurabaya,27.1\nSuva,25.6\nSuwałki,7.2\nSydney,17.7\nTabora,23.0\nTabriz,12.6\nTaipei,23.0\nTallinn,6.4\nTamale,27.9\nTamanrasset,21.7\nTampa,22.9\nTashkent,14.8\nTauranga,14.8\nTbilisi,12.9\nTegucigalpa,21.7\nTehran,17.0\nTel Aviv,20.0\nThessaloniki,16.0\nThiès,24.0\nTijuana,17.8\nTimbuktu,28.0\nTirana,15.2\nToamasina,23.4\nTokyo,15.4\nToliara,24.1\nToluca,12.4\nToronto,9.4\nTripoli,20.0\nTromsø,2.9\nTucson,20.9\nTunis,18.4\nUlaanbaatar,-0.4\nUpington,20.4\nÜrümqi,7.4\nVaduz,10.1\nValencia,18.3\nValletta,18.8\nVancouver,10.4\nVeracruz,25.4\nVienna,10.4\nVientiane,25.9\nVillahermosa,27.1\nVilnius,6.0\nVirginia Beach,15.8\nVladivostok,4.9\nWarsaw,8.5\nWashington, D.C.,14.6\nWau,27.8\nWellington,12.9\nWhitehorse,-0.1\nWichita,13.9\nWillemstad,28.0\nWinnipeg,3.0\nWrocław,9.6\nXi'an,14.1\nYakutsk,-8.8\nYangon,27.5\nYaoundé,23.8\nYellowknife,-4.3\nYerevan,12.4\nYinchuan,9.0\nZagreb,10.7\nZanzibar City,26.0\nZürich,9.3"
  },
  {
    "path": "examples/1brc/make-samples/main.v",
    "content": "import encoding.csv\nimport flag\nimport os\nimport rand\n\nstruct CityMean {\n\tcity string\n\tmean f64\n}\n\nfn main() {\n\tmut fp := flag.new_flag_parser(os.args)\n\tfp.version('1brc sample generator v1.0.0')\n\tfp.skip_executable()\n\tfp.application('Sample generator for 1 billion rows challenge')\n\tfp.description('The 1 billion rows challenge solved in V.\\nFor details, see https://www.morling.dev/blog/one-billion-row-challenge/')\n\tinput_file := fp.string('city-file', `i`, 'cities.txt', 'Path to input file with cities and means list')\n\tfp.limit_free_args_to_exactly(1)!\n\tsample_count := fp.remaining_parameters()[0].u64()\n\n\tcontent := os.read_file(input_file) or { panic(err) }\n\tmut reader := csv.new_reader(content, csv.ReaderConfig{ delimiter: `,` })\n\tmut means := []CityMean{}\n\tfor {\n\t\trec := reader.read() or { break }\n\t\tmeans << CityMean{\n\t\t\tcity: rec[0]\n\t\t\tmean: rec[1].f64()\n\t\t}\n\t}\n\n\tfor _ in 0 .. sample_count / 2 {\n\t\tmut city := rand.intn(means.len)!\n\t\tm1, m2 := rand.normal_pair(mu: means[city].mean, sigma: 10)!\n\t\tprintln('${means[city].city};${m1:.1f}')\n\t\tcity = rand.intn(means.len)!\n\t\tprintln('${means[city].city};${m2:.1f}')\n\t}\n}\n"
  },
  {
    "path": "examples/1brc/solution/main.v",
    "content": "// vtest build: !windows // requires mmap\nimport flag\nimport math\nimport os\n\n#include <sys/mman.h>\n\nfn C.mmap(addr voidptr, len u64, prot i32, flags i32, fd i32, offset i64) voidptr\nfn C.munmap(addr voidptr, len u64) i32\n\nstruct MemoryMappedFile {\n\tsize u64\nmut:\n\tdata &u8\n\tfile os.File\n}\n\nfn mmap_file(path string) MemoryMappedFile {\n\tmut mf := MemoryMappedFile{\n\t\tfile: os.open_file(path, 'r', 0) or { panic('fail') }\n\t\tsize: os.file_size(path)\n\t\tdata: C.NULL\n\t}\n\n\tmf.data = &u8(C.mmap(C.NULL, mf.size, C.PROT_READ, C.MAP_SHARED, mf.file.fd, 0))\n\treturn mf\n}\n\nfn (mut mf MemoryMappedFile) unmap() {\n\tif C.munmap(mf.data, mf.size) != 0 {\n\t\tpanic('(${C.errno}) munmap() failed')\n\t}\n\tmf.file.close()\n}\n\nenum ReadState {\n\tcity\n\ttemp\n}\n\nstruct Result {\npub mut:\n\tmin   i32\n\tmax   i32\n\tsum   i32\n\tcount u32\n}\n\nfn format_value(value i32) string {\n\treturn '${value / 10}.${math.abs(value % 10)}'\n}\n\nfn print_results(results map[string]Result, print_nicely bool) {\n\tmut output := []string{cap: results.len}\n\tmut cities := results.keys()\n\tcities.sort()\n\tfor city in cities {\n\t\tv := results[city]\n\t\tmean := f64(v.sum) / v.count / 10\n\t\toutput << '${city}=${format_value(v.min)}/${mean:.1f}/${format_value(v.max)}'\n\t}\n\tif print_nicely {\n\t\tprintln(output.join('\\n'))\n\t} else {\n\t\tprintln('{' + output.join(', ') + '}')\n\t}\n}\n\nfn combine_results(results []map[string]Result) map[string]Result {\n\tmut combined_result := map[string]Result{}\n\tfor result in results {\n\t\tfor city, r in result {\n\t\t\tif city !in combined_result {\n\t\t\t\tcombined_result[city] = r\n\t\t\t} else {\n\t\t\t\tif r.max > combined_result[city].max {\n\t\t\t\t\tcombined_result[city].max = r.max\n\t\t\t\t}\n\t\t\t\tif r.min < combined_result[city].min {\n\t\t\t\t\tcombined_result[city].min = r.min\n\t\t\t\t}\n\t\t\t\tcombined_result[city].sum += r.sum\n\t\t\t\tcombined_result[city].count += r.count\n\t\t\t}\n\t\t}\n\t}\n\treturn combined_result\n}\n\n@[direct_array_access]\nfn process_chunk(addr &u8, from u64, to u64) map[string]Result {\n\tmut results := map[string]Result{}\n\tmut state := ReadState.city\n\tmut city := ''\n\tmut temp := i32(0)\n\tmut mod := i32(1)\n\tmut j := int(0)\n\tfor i in from .. to {\n\t\tc := unsafe { u8(addr[i]) }\n\t\tmatch state {\n\t\t\t.city {\n\t\t\t\tmatch c {\n\t\t\t\t\t`;` {\n\t\t\t\t\t\tstate = .temp\n\t\t\t\t\t\tcity = unsafe { tos(addr[i - u64(j)], j) }\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tj += 1\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t.temp {\n\t\t\t\tmatch c {\n\t\t\t\t\t`\\n` {\n\t\t\t\t\t\ttemp *= mod\n\t\t\t\t\t\tif city !in results {\n\t\t\t\t\t\t\tresults[city] = Result{\n\t\t\t\t\t\t\t\tmin:   temp\n\t\t\t\t\t\t\t\tmax:   temp\n\t\t\t\t\t\t\t\tsum:   temp\n\t\t\t\t\t\t\t\tcount: 1\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif temp > results[city].max {\n\t\t\t\t\t\t\t\tresults[city].max = temp\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif temp < results[city].min {\n\t\t\t\t\t\t\t\tresults[city].min = temp\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresults[city].sum += temp\n\t\t\t\t\t\t\tresults[city].count += 1\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstate = .city\n\t\t\t\t\t\ttemp = 0\n\t\t\t\t\t\tmod = 1\n\t\t\t\t\t\tj = 0\n\t\t\t\t\t}\n\t\t\t\t\t`-` {\n\t\t\t\t\t\tmod = -1\n\t\t\t\t\t}\n\t\t\t\t\t`.` {}\n\t\t\t\t\telse {\n\t\t\t\t\t\t// ASCII 48 = '0' ... ASCII 57 = '9' => (ASCII value) - 48 = decimal value\n\t\t\t\t\t\ttemp = temp * 10 + (c - 48)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn results\n}\n\nfn process_in_parallel(mf MemoryMappedFile, thread_count u32) map[string]Result {\n\tmut threads := []thread map[string]Result{}\n\tapprox_chunk_size := mf.size / thread_count\n\tmut from := u64(0)\n\tmut to := approx_chunk_size\n\tfor _ in 0 .. thread_count - 1 {\n\t\tunsafe {\n\t\t\tfor mf.data[to] != `\\n` {\n\t\t\t\tto += 1\n\t\t\t}\n\t\t}\n\t\tthreads << spawn process_chunk(mf.data, from, to)\n\t\tfrom = to + 1\n\t\tto = from + approx_chunk_size\n\t}\n\tto = mf.size\n\tthreads << spawn process_chunk(mf.data, from, to)\n\tres := threads.wait()\n\treturn combine_results(res)\n}\n\nfn main() {\n\tmut fp := flag.new_flag_parser(os.args)\n\tfp.version('1brc v1.0.0')\n\tfp.skip_executable()\n\tfp.application('1 billion rows challenge')\n\tfp.description('The 1 billion rows challenge solved in V.\\nFor details, see https://www.morling.dev/blog/one-billion-row-challenge/')\n\tthread_count := u32(fp.int('threads', `n`, 1, 'number of threads for parallel processing.'))\n\tprint_nicely := fp.bool('human-readable', `h`, false, 'Print results with new lines rather than following challenge spec')\n\tquiet := fp.bool('quiet', `q`, false, 'Suppress the results output (e.g., if you only care about timing)')\n\tfp.limit_free_args_to_exactly(1)!\n\tpath := fp.remaining_parameters()[0]\n\n\tmut mf := mmap_file(path)\n\tdefer {\n\t\tmf.unmap()\n\t}\n\n\tresults := if thread_count > 1 {\n\t\tprocess_in_parallel(mf, thread_count)\n\t} else {\n\t\tprocess_chunk(mf.data, 0, mf.size)\n\t}\n\n\tif !quiet {\n\t\tprint_results(results, print_nicely)\n\t}\n}\n"
  },
  {
    "path": "examples/animated_help_text.v",
    "content": "import term.ui as tui\nimport flag\n\nstruct DocTest {\n\tshow_version bool @[short: v; xdoc: 'Show version and exit']\n\tdebug_level  int  @[long: debug; short: d; xdoc: 'Debug level']\n\tlevel        f32  @[only: l; xdoc: 'Do not show this']\n\texample      string\n\tsquare       bool\n\tmulti        int   @[only: m; repeats]\n\twroom        []int @[short: w]\n\tthe_limit    string\n}\n\nstruct App {\nmut:\n\ttui       &tui.Context = unsafe { nil }\n\tframe     int\n\tsquare    string = '.____.\\n|    |\\n|    |\\n|____|'\n\tpad       int    = 1\n\tdirection int    = 1\n}\n\nfn event(e &tui.Event, mut _app App) {\n\tmatch e.typ {\n\t\t.mouse_down {}\n\t\t.mouse_drag {}\n\t\t.mouse_up {}\n\t\t.key_down {\n\t\t\tif e.code == .c {\n\t\t\t} else if e.code == .escape {\n\t\t\t\texit(0)\n\t\t\t}\n\t\t}\n\t\telse {}\n\t}\n}\n\nfn frame(mut app App) {\n\tapp.tui.clear()\n\tapp.frame++\n\n\tif app.frame % 4 == 0 {\n\t\tapp.pad += app.direction\n\t\tapp.square = '${' '.repeat(app.pad)}.____.\\n${' '.repeat(app.pad)}|    |\\n${' '.repeat(app.pad)}|    |\\n${' '.repeat(app.pad)}|____|'\n\t}\n\tif app.frame % 100 == 0 {\n\t\tif app.direction > 0 {\n\t\t\tapp.direction = -1\n\t\t} else {\n\t\t\tapp.direction = 1\n\t\t}\n\t}\n\n\thelp_text := flag.to_doc[DocTest](\n\t\tversion:     '1.0'\n\t\tdescription: 'Hello! This should show an *animated* example application description.\nWe are at frame ${app.frame}.\nPress ESCAPE or Ctrl+C to exit'\n\t\tfooter:      '\nPress ESCAPE or Ctrl+C to exit'\n\t\tfields:      {\n\t\t\t'level':                                    'Level of lorem ipsum\\nand more\\nmany many many more.\\nNotice how user newlines/format is kept since\\ninput lines are all less or within\\nthe default layout.description_padding\\nand max width'\n\t\t\t'example':                                  'Looong example text without newlines or anything else and lorem ipsum and more and many many many more. Should be auto fitted'\n\t\t\t'multi':                                    'This flag can be repeated'\n\t\t\t'-e, --extra':                              'Secret flag that does not exist on the struct, but we want documented (in same format as the others)'\n\t\t\t'-q, --quiet-and-quite-long-flag <string>': 'Mega long description and secret flag that does not exist on the struct, but we want documented. Also the flag has custom newlines\\nand the flag line itself is super long'\n\t\t\t'square':                                   '${app.square}'\n\t\t}\n\t) or { '' }\n\n\tapp.tui.draw_text(0, 0, '${help_text}')\n\tapp.tui.reset()\n\n\tapp.tui.flush()\n}\n\ntype EventFn = fn (&tui.Event, voidptr)\n\ntype FrameFn = fn (voidptr)\n\nfn main() {\n\tmut app := &App{}\n\tapp.tui = tui.init(\n\t\tuser_data:   app\n\t\tevent_fn:    EventFn(event)\n\t\tframe_fn:    FrameFn(frame)\n\t\thide_cursor: true\n\t\tframe_rate:  60\n\t)\n\tapp.tui.run()!\n}\n"
  },
  {
    "path": "examples/archive/tar_gz_reader.v",
    "content": "import archive.tar\nimport flag\nimport net.http\nimport os\nimport term\n\nconst default_url = 'https://github.com/vlang/v/archive/refs/tags/v0.1.3.tar.gz'\n\n@[heap]\nstruct Context {\n\turl        string // Web starting with http:// or https://. Local starting with file:///\n\tchunks     bool   // true: decompress with callback\n\tdebug      int    // print debug lines\n\tmax_blocks int    // if max_blocks > 0 and is reached stops early.\n\tfilename   string // if filename is found as a path of a data block, stops early.\n}\n\nfn (ctx &Context) read_last_block(mut read tar.Read) bool {\n\tif ctx.max_blocks > 0 && ctx.max_blocks < read.get_block_number() {\n\t\tread.stop_early = true\n\t\treturn true\n\t}\n\treturn false\n}\n\nfn new_context() !&Context {\n\tmut fp := flag.new_flag_parser(os.args)\n\tfp.application('tar_gz_reader')\n\tfp.version('0.0.20250721')\n\tfp.description('Reads into memory selected sections of *.tar.gz. archives from https or home_dir.')\n\tfp.skip_executable()\n\tctx := &Context{\n\t\turl:        fp.string('url', `u`, default_url, 'archive *.tar.gz URL, default(${default_url}). Start name with file:/// for local')\n\t\tchunks:     fp.bool('chunks', `c`, false, 'decompress with chunks to reduce RAM usage, default(false)')\n\t\tdebug:      fp.int('debug', `d`, 0, 'prints blocks: 1=other, 2:+dirs, 3=+files, 4=+data, default(0=silent)')\n\t\tmax_blocks: fp.int('max_blocks', `m`, 0, 'maximum blocks to read, stop early. Default(0=read all)')\n\t\tfilename:   fp.string('filename', `f`, '', 'filename content complete print, stop early. Default(empty means none)')\n\t}\n\tadditional := fp.finalize()!\n\tif additional.len > 0 {\n\t\tprintln('unprocessed args ${additional.join_lines()}')\n\t}\n\treturn ctx\n}\n\n// Downloader downloads a *.tar.gz using HTTP chunks\nstruct Downloader {\nmut:\n\tchunks int\n\tdata   []u8\n}\n\nfn new_downloader(url string) !&Downloader {\n\tmut downloader := &Downloader{}\n\tparams := http.DownloaderParams{\n\t\tdownloader: downloader\n\t}\n\tif url.starts_with('http://') || url.starts_with('https://') {\n\t\thttp.download_file_with_progress(url, '', params)!\n\t} else if url.starts_with('file:///') {\n\t\tpath := '${os.home_dir()}/${url[8..]}'\n\t\tprintln('path ${path}')\n\t\tdownloader.data = os.read_bytes(path)!\n\t}\n\treturn downloader\n}\n\nfn (mut d Downloader) on_start(mut _request http.Request, _path string) ! {}\n\nfn (mut d Downloader) on_chunk(_request &http.Request, chunk []u8, _already_received u64, expected u64) ! {\n\tif expected == 0 {\n\t\treturn\n\t}\n\td.chunks++\n\td.data << chunk\n}\n\nfn (mut d Downloader) on_finish(_request &http.Request, _response &http.Response) ! {}\n\nstruct FileReader implements tar.Reader {\n\tctx &Context\nmut:\n\tfilepath string\n\tcontent  []u8\n}\n\nfn new_file_reader(ctx &Context) FileReader {\n\treturn FileReader{\n\t\tctx: ctx\n\t}\n}\n\nfn (mut f FileReader) other_block(mut read tar.Read, details string) {\n\tif f.ctx.read_last_block(mut read) {\n\t\treturn\n\t}\n\tif f.ctx.debug > 0 {\n\t\trow := 'OTHER  block:${read.get_block_number():6} ${read.get_special()} ${details} ${read.get_path()} '\n\t\tprintln(term.colorize(term.bright_yellow, row))\n\t}\n}\n\nfn (mut f FileReader) dir_block(mut read tar.Read, size u64) {\n\tif f.ctx.read_last_block(mut read) {\n\t\treturn\n\t}\n\tif f.ctx.debug > 1 {\n\t\trow := 'DIR    block:${read.get_block_number():6} ${read.get_path()} size:${size}'\n\t\tprintln(term.colorize(term.green, row))\n\t}\n}\n\nfn (mut f FileReader) file_block(mut read tar.Read, size u64) {\n\tif f.ctx.read_last_block(mut read) {\n\t\treturn\n\t}\n\tpath := read.get_path()\n\tif f.ctx.debug > 2 {\n\t\trow := ' FILE  block:${read.get_block_number():6} ${path} size:${size}'\n\t\tprintln(term.colorize(term.bright_blue, row))\n\t}\n\tif f.ctx.filename != '' && f.filepath == '' && path.ends_with(f.ctx.filename) {\n\t\tf.filepath = path\n\t}\n}\n\nfn (mut f FileReader) data_block(mut read tar.Read, data []u8, pending int) {\n\tif f.ctx.read_last_block(mut read) {\n\t\treturn\n\t}\n\tpath := read.get_path()\n\tif f.ctx.debug > 3 {\n\t\tprintln('  DATA block:${read.get_block_number():6} ${path} len:${data.len} pend:${pending}')\n\t}\n\tif f.ctx.filename != '' {\n\t\tif f.filepath == path {\n\t\t\tf.content << data\n\t\t\tif pending == 0 {\n\t\t\t\t// our file of interest data is complete\n\t\t\t\tread.stop_early = true\n\t\t\t}\n\t\t}\n\t}\n}\n\nfn main() {\n\tctx := new_context()!\n\treader := FileReader{\n\t\tctx: ctx\n\t}\n\tmut untar := tar.new_untar(reader)\n\tmut decompressor := tar.new_decompressor(untar)\n\tdownloader := new_downloader(ctx.url)!\n\tif ctx.chunks {\n\t\tdecompressor.read_chunks(downloader.data)!\n\t} else {\n\t\tdecompressor.read_all(downloader.data)!\n\t}\n\tprintln('-'.repeat(80))\n\tprintln('Download: ${ctx.url} chunks:${downloader.chunks} bytes=${downloader.data.len}')\n\tprintln('Untar:    ${untar}')\n\tprintln('Content:  Path:${reader.filepath} bytes:${reader.content.len}')\n\tprintln('-'.repeat(80))\n\tprintln('${reader.content.bytestr()}')\n\tprintln('-'.repeat(80))\n}\n"
  },
  {
    "path": "examples/asm.v",
    "content": "// vtest build: !msvc\nfn main() {\n\ta := 100\n\tb := 20\n\tmut c := 0\n\t$if amd64 {\n\t\tasm amd64 {\n\t\t\tmov eax, a\n\t\t\tadd eax, b\n\t\t\tmov c, eax\n\t\t\t; =r (c) // output\n\t\t\t; r (a) // input\n\t\t\t  r (b)\n\t\t}\n\t}\n\tprintln('a: ${a}') // 100\n\tprintln('b: ${b}') // 20\n\tprintln('c: ${c}') // 120\n}\n"
  },
  {
    "path": "examples/assets/fonts/LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "examples/assets/fonts/OFL.txt",
    "content": "Copyright (c) 2012, Eduardo Tunni (http://www.tipo.net.ar), with Reserved Font Name \"Imprima\"\n\nThis Font Software is licensed under the SIL Open Font License, Version 1.1.\nThis license is copied below, and is also available with a FAQ at:\nhttp://scripts.sil.org/OFL\n\n\n-----------------------------------------------------------\nSIL OPEN FONT LICENSE Version 1.1 - 26 February 2007\n-----------------------------------------------------------\n\nPREAMBLE\nThe goals of the Open Font License (OFL) are to stimulate worldwide\ndevelopment of collaborative font projects, to support the font creation\nefforts of academic and linguistic communities, and to provide a free and\nopen framework in which fonts may be shared and improved in partnership\nwith others.\n\nThe OFL allows the licensed fonts to be used, studied, modified and\nredistributed freely as long as they are not sold by themselves. The\nfonts, including any derivative works, can be bundled, embedded, \nredistributed and/or sold with any software provided that any reserved\nnames are not used by derivative works. The fonts and derivatives,\nhowever, cannot be released under any other type of license. The\nrequirement for fonts to remain under this license does not apply\nto any document created using the fonts or their derivatives.\n\nDEFINITIONS\n\"Font Software\" refers to the set of files released by the Copyright\nHolder(s) under this license and clearly marked as such. This may\ninclude source files, build scripts and documentation.\n\n\"Reserved Font Name\" refers to any names specified as such after the\ncopyright statement(s).\n\n\"Original Version\" refers to the collection of Font Software components as\ndistributed by the Copyright Holder(s).\n\n\"Modified Version\" refers to any derivative made by adding to, deleting,\nor substituting -- in part or in whole -- any of the components of the\nOriginal Version, by changing formats or by porting the Font Software to a\nnew environment.\n\n\"Author\" refers to any designer, engineer, programmer, technical\nwriter or other person who contributed to the Font Software.\n\nPERMISSION & CONDITIONS\nPermission is hereby granted, free of charge, to any person obtaining\na copy of the Font Software, to use, study, copy, merge, embed, modify,\nredistribute, and sell modified and unmodified copies of the Font\nSoftware, subject to the following conditions:\n\n1) Neither the Font Software nor any of its individual components,\nin Original or Modified Versions, may be sold by itself.\n\n2) Original or Modified Versions of the Font Software may be bundled,\nredistributed and/or sold with any software, provided that each copy\ncontains the above copyright notice and this license. These can be\nincluded either as stand-alone text files, human-readable headers or\nin the appropriate machine-readable metadata fields within text or\nbinary files as long as those fields can be easily viewed by the user.\n\n3) No Modified Version of the Font Software may use the Reserved Font\nName(s) unless explicit written permission is granted by the corresponding\nCopyright Holder. This restriction only applies to the primary font name as\npresented to the users.\n\n4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font\nSoftware shall not be used to promote, endorse or advertise any\nModified Version, except to acknowledge the contribution(s) of the\nCopyright Holder(s) and the Author(s) or with their explicit written\npermission.\n\n5) The Font Software, modified or unmodified, in part or in whole,\nmust be distributed entirely under this license, and must not be\ndistributed under any other license. The requirement for fonts to\nremain under this license does not apply to any document created\nusing the Font Software.\n\nTERMINATION\nThis license becomes null and void if any of the above conditions are\nnot met.\n\nDISCLAIMER\nTHE FONT SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT\nOF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE\nCOPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nINCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL\nDAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM\nOTHER DEALINGS IN THE FONT SOFTWARE.\n"
  },
  {
    "path": "examples/assets/v.six",
    "content": "\u001bP0;0;0q\"1;1;128;128#0;2;0;0;0#1;2;26;35;45#2;2;27;35;45#3;2;27;35;45#4;2;27;35;45#5;2;27;35;45#6;2;27;35;45#7;2;27;35;45#8;2;27;35;46#9;2;27;36;46#10;2;27;35;45#11;2;27;36;45#12;2;27;36;46#13;2;28;36;46#14;2;27;36;47#15;2;28;36;46#16;2;28;36;47#17;2;28;36;47#18;2;27;36;47#19;2;27;36;48#20;2;27;37;48#21;2;28;37;49#22;2;28;36;47#23;2;29;37;47#24;2;29;37;48#25;2;29;37;48#26;2;29;38;48#27;2;29;38;49#28;2;29;38;49#29;2;29;38;49#30;2;29;38;50#31;2;30;38;49#32;2;30;38;49#33;2;30;38;50#34;2;30;39;50#35;2;29;38;51#36;2;29;39;51#37;2;30;39;50#38;2;30;39;51#39;2;30;39;51#40;2;31;39;51#41;2;31;40;51#42;2;31;40;51#43;2;31;40;52#44;2;30;40;53#45;2;29;40;53#46;2;31;41;55#47;2;31;40;51#48;2;31;40;52#49;2;31;41;53#50;2;32;41;53#51;2;32;41;53#52;2;32;41;53#53;2;32;41;53#54;2;32;42;53#55;2;32;42;54#56;2;33;42;54#57;2;32;42;54#58;2;33;42;54#59;2;32;42;55#60;2;33;42;54#61;2;32;42;54#62;2;33;42;54#63;2;32;42;55#64;2;33;42;55#65;2;33;42;54#66;2;33;42;54#67;2;33;42;54#68;2;33;42;55#69;2;32;42;54#70;2;33;42;54#71;2;32;42;54#72;2;33;42;54#73;2;33;42;55#74;2;33;42;54#75;2;33;43;56#76;2;32;43;57#77;2;33;43;56#78;2;33;44;58#79;2;33;44;59#80;2;35;45;58#81;2;33;45;61#82;2;34;45;61#83;2;36;47;61#84;2;36;47;63#85;2;36;48;63#86;2;36;49;65#87;2;38;49;65#88;2;37;51;67#89;2;36;51;72#90;2;36;52;73#91;2;36;53;74#92;2;36;53;74#93;2;36;53;75#94;2;36;53;75#95;2;36;53;75#96;2;36;53;75#97;2;36;53;75#98;2;37;53;75#99;2;36;53;75#100;2;36;53;75#101;2;36;53;75#102;2;37;53;75#103;2;37;53;75#104;2;37;54;75#105;2;39;51;67#106;2;39;51;68#107;2;40;52;70#108;2;40;53;71#109;2;42;54;69#110;2;41;53;70#111;2;42;54;71#112;2;39;53;73#113;2;39;53;72#114;2;40;55;73#115;2;38;54;74#116;2;38;54;74#117;2;38;54;75#118;2;38;54;75#119;2;39;54;75#120;2;40;54;74#121;2;39;54;74#122;2;41;54;72#123;2;36;53;75#124;2;36;53;75#125;2;36;53;75#126;2;37;53;75#127;2;37;53;75#128;2;36;53;75#129;2;36;53;75#130;2;38;54;75#0!128~-!9~^!8N!11^!70~!11^!8N^!9~$#97!9?_ooo_oo_o!8_#129??_#67!70?_#72___#58!7_o_!6o_$#125!13?O??O!9?__#67!83?O-#0!9~}o#101_#125!22?@#101??@!5?C#58!38?_w{!6}!26~N@$#125!9?@K#0!28?!4@BF^!36~^FB!4@#67@@#0!26?o}!9~$#97!10?B^!22~}~~}~!4}ww_-#0!11~}o!33?B^!32~^B!33?o}!11~$#125!11?@?_#129!33?_#58!32?_{!33~N@$#97!12?F^!32~{$#129!12?G-#0!14~w!33?@N!28~NB!33?w!14~$#97!14?Bn!32~}_#58!28?o{!33~F$#125!14?CO#129!33?O-#0!16~w#125O#0!32?@N!24~N@#74!32?_#0w!16~$#97!16?Fn!32~{O#58!24?ow!32~^B$#101!50?A#125_#67!25?C#72!33?C$#73!77?A-#0!18~{_!32?@N!20~N@!32?_{!18~$#97!18?B^!32~}_#58!20?o}!32~^B$#125!53?O-#0!20~{_!32?@F!16~N@!32?_{!20~$#97!20?BN!32~{o#58!16?o}!32~VB$#101!21?O#129!32?A#125G#67!50?G-#0!22~}o#129!32?@#0F!12~F@!32?o}!22~$#97!22?@N!32~}o#58!12?w}!32~N@$#101!57?G-#0!24~}o#125_!31?A#0F!8~F!33?o}!24~$#101!24?@#97N^!31~|w#58!8?o!33~N@$#72!68?G-#0!26~}w#125!32?@?_#58???o}!32~F#72@$#97!26?@F!32~}w#64!4?G#72@#0!32?w}!26~$!61?F^~~~F-!29~w!33?BF#58FN^!29~nB$#97!29?F!33~w#41G?_#72!30?OC$#90!63?C#77O#52GO_#0!30?w!29~$#109!64?_#23_$#37!65?O-#0!31~{_#119!31?@#58A??BN!25~^B$#97!31?B^!31~}o#31@?_#0!26?_{!31~$#7!65?@C#41AO$#109!65?C#23AO#52Co$#130!65?G#1G#48@G$#75!66?O#4_$#111!66?_#28G$#37!67?C-#0!33~{_#101!31?@#7@G#31C_#0!22?_{!33~$#97!33?BN!31~}w#4C_#58@N!21~^B$#125!34?O#80!32?A#17AO#52Eo$#122!67?C#28@#41AO$#83!68?O#48@G$#114!68?_#26G-#0!35~{o#120!32?C_#31C_#0!18?o{!35~$#101!35?@#97F!32~w#4C_#58BN!17~FB$#125!35?A#129G#19!32?@#23@G#52Co#72!17?G$#85!69?A#16A#41AO$#21!70?G#44@G$#87!70?O#7O-#0!37~}o#119!32?C_#31C_#0!14?o}!37~$#125!37?@G#36!32?@#44G@G$#97!38?F!32~w#7Ao#58@N!13~N@$#105!71?A#23@G#52Eo$#4!72?C#41A#37O$#106!72?O-#0!39~}w#46!32?@#7EO#58@N!9~F#67@$#125!39?@#97F!32~w_#28C_#0!10?w}!39~$#101!73?C#23@G#48C_$#107!73?A#76G#37AO$#108!74?O#19_#52AO$#44!75?@#41G-#0!42~w#101o#79!31?@#23@G#48C_#0!5?w!42~$#97!42?FN!31~{_#41@G#58F!5~F$#114!75?A#4A#7O#52BW$#19!76?C#21_#26_$#82!76?G#28C#31O$#112!76?O#37A-#0!44~w_#119!31?AO#31AO#58F^B$#97!44?F^!31~{_#41@G#0?_w!44~$#84!77?@#4A#7O#48C_#72?C$#17!78?@#16G#52BW$#36!78?C#26C#28_$#86!78?G#45_-#0!46~{w!33o{!46~$#97!46?@FF!30NK#23@#44@$#125!46?A#89?G#88!30?@#28A#47A$#101!79?A#78C$#81!80?G-#0!128~-!128B-\u001b\\"
  },
  {
    "path": "examples/binary_search_tree.v",
    "content": "// Binary Search Tree example by @SleepyRoy\n\nstruct Empty {}\n\nstruct Node[T] {\n\tvalue T\n\tleft  Tree[T]\n\tright Tree[T]\n}\n\ntype Tree[T] = Empty | Node[T]\n\n// return size(number of nodes) of BST\nfn (tree Tree[T]) size[T]() int {\n\treturn match tree {\n\t\tEmpty { 0 }\n\t\tNode[T] { 1 + tree.left.size() + tree.right.size() }\n\t}\n}\n\n// insert a value to BST\nfn (tree Tree[T]) insert[T](x T) Tree[T] {\n\treturn match tree {\n\t\tEmpty {\n\t\t\tNode[T]{x, tree, tree}\n\t\t}\n\t\tNode[T] {\n\t\t\tif x == tree.value {\n\t\t\t\ttree\n\t\t\t} else if x < tree.value {\n\t\t\t\tNode[T]{\n\t\t\t\t\t...tree\n\t\t\t\t\tleft: tree.left.insert(x)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tNode[T]{\n\t\t\t\t\t...tree\n\t\t\t\t\tright: tree.right.insert(x)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// whether able to find a value in BST\nfn (tree Tree[T]) search[T](x T) bool {\n\treturn match tree {\n\t\tEmpty {\n\t\t\tfalse\n\t\t}\n\t\tNode[T] {\n\t\t\tif x == tree.value {\n\t\t\t\ttrue\n\t\t\t} else if x < tree.value {\n\t\t\t\ttree.left.search(x)\n\t\t\t} else {\n\t\t\t\ttree.right.search(x)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// find the minimal value of a BST\nfn (tree Tree[T]) min[T]() T {\n\treturn match tree {\n\t\tEmpty {\n\t\t\tT(1e9)\n\t\t}\n\t\tNode[T] {\n\t\t\tif tree.value < tree.left.min() {\n\t\t\t\ttree.value\n\t\t\t} else {\n\t\t\t\ttree.left.min()\n\t\t\t}\n\t\t}\n\t}\n}\n\n// delete a value in BST (if nonexistent do nothing)\nfn (tree Tree[T]) delete[T](x T) Tree[T] {\n\treturn match tree {\n\t\tEmpty {\n\t\t\ttree\n\t\t}\n\t\tNode[T] {\n\t\t\tif tree.left !is Empty && tree.right !is Empty {\n\t\t\t\tif x < tree.value {\n\t\t\t\t\tNode[T]{\n\t\t\t\t\t\t...tree\n\t\t\t\t\t\tleft: tree.left.delete(x)\n\t\t\t\t\t}\n\t\t\t\t} else if x > tree.value {\n\t\t\t\t\tNode[T]{\n\t\t\t\t\t\t...tree\n\t\t\t\t\t\tright: tree.right.delete(x)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tNode[T]{\n\t\t\t\t\t\t...tree\n\t\t\t\t\t\tvalue: tree.right.min()\n\t\t\t\t\t\tright: tree.right.delete(tree.right.min())\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if tree.left !is Empty {\n\t\t\t\tif x == tree.value {\n\t\t\t\t\ttree.left\n\t\t\t\t} else {\n\t\t\t\t\tNode[T]{\n\t\t\t\t\t\t...tree\n\t\t\t\t\t\tleft: tree.left.delete(x)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif x == tree.value {\n\t\t\t\t\ttree.right\n\t\t\t\t} else {\n\t\t\t\t\tNode[T]{\n\t\t\t\t\t\t...tree\n\t\t\t\t\t\tright: tree.right.delete(x)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfn main() {\n\tmut tree := Tree[f64](Empty{})\n\tvals := [0.2, 0.0, 0.5, 0.3, 0.6, 0.8, 0.9, 1.0, 0.1, 0.4, 0.7]\n\tfor i in vals {\n\t\ttree = tree.insert(i)\n\t}\n\tprintln('[1] after insertion tree size is ${tree.size()}') // 11\n\tdel_vals := [-0.3, 0.0, 0.3, 0.6, 1.0, 1.5]\n\tfor i in del_vals {\n\t\ttree = tree.delete(i)\n\t}\n\tprint('[2] after deletion tree size is ${tree.size()}, ') // 7\n\tprint('and these elements were deleted: ') // 0.0 0.3 0.6 1.0\n\tfor i in vals {\n\t\tif !tree.search(i) {\n\t\t\tprint('${i} ')\n\t\t}\n\t}\n\tprintln('')\n}\n"
  },
  {
    "path": "examples/brainvuck.v",
    "content": "import os\nimport term\n\n// For a more detailed description of the brainfuck language, see:\n// https://en.wikipedia.org/wiki/Brainfuck\n// http://brainfuck.org/brainfuck.html ,\n// http://brainfuck.org/epistle.html ,\n// http://www.hevanet.com/cristofd/brainfuck/ .\n\nconst show_state = os.getenv('VERBOSE') != ''\n\nstruct BFState {\nmut:\n\tpc      u16    // program counter (PC) register\n\taddress u16    // a 16-bit address register, serving as an index to the memory below\n\tprogram string // the BF program\n\tmemory  []u8 = []u8{len: 65536} // we have 2^16 bytes of memory\n\ttargets map[int]int // a mapping for the program address of a `[` to its corresponding `]`, and from a `]` to its corresponding opening `[`.\n}\n\nfn BFState.new(program string) &BFState {\n\tmut state := &BFState{\n\t\tprogram: program\n\t}\n\tstate.find_matching_pairs()\n\treturn state\n}\n\n// show the current state of an BF interpreter. Useful for debugging.\nfn (state &BFState) show(suffix string) {\n\tmut max_non_zero_address := -1\n\tfor i := state.memory.len - 1; i >= 0; i-- {\n\t\tif state.memory[i] != 0 {\n\t\t\tmax_non_zero_address = i\n\t\t\tbreak\n\t\t}\n\t}\n\tprintln('PC: ${state.pc:04} | Address: ${state.address:04} | Memory: ${state.memory#[0..\n\t\tmax_non_zero_address + 1]:-40s} | Memory[Address]: ${state.memory#[state.address..\n\t\tstate.address + 1]:-10s} | ${suffix}')\n}\n\n// find_matching_pairs fills in the `targets` mapping for all pairs of `[` and `]`,\n// so that when interpreting, we would not have to search for them anymore.\nfn (mut state BFState) find_matching_pairs() {\n\tmut stack := []int{}\n\tfor i in 0 .. state.program.len {\n\t\tpi := state.program[i]\n\t\tmatch pi {\n\t\t\t`[` {\n\t\t\t\tstack << i\n\t\t\t}\n\t\t\t`]` {\n\t\t\t\tif stack.len == 0 {\n\t\t\t\t\teprintln('> unmatched `]` found in the program, at position: ${i}')\n\t\t\t\t\teprintln('program so far:')\n\t\t\t\t\teprintln(state.program#[0..i + 1])\n\t\t\t\t\texit(1)\n\t\t\t\t}\n\t\t\t\tpc := stack.pop()\n\t\t\t\tstate.targets[pc] = i + 1\n\t\t\t\tstate.targets[i] = pc + 1\n\t\t\t\t// eprintln('>>> found `[` at i ${i}; pc: ${pc}')\n\t\t\t}\n\t\t\telse {}\n\t\t}\n\t}\n\tif stack.len > 0 {\n\t\teprintln('> found ${stack.len} unmatched `[`:')\n\t\tfor i in stack {\n\t\t\teprintln('  `[` at position: ${i}, program so far: `${state.program#[0..i + 1]}`')\n\t\t}\n\t\texit(1)\n\t}\n}\n\n@[noreturn]\nfn (state &BFState) panic_for_bracket(b1 rune, b2 rune) {\n\tpanic('unbalanced `${b1}` found, its target `${b2}` is not known; address: ${state.address}, pc: ${state.pc}')\n}\n\nfn (mut state BFState) run() ? {\n\tmut i := 0\n\t// the BF interpreter starts here:\n\tfor state.pc < state.program.len {\n\t\t// get the current program character (corresponding to our program counter), and interpret it according to BF's rules:\n\t\tinstruction := state.program[state.pc]\n\t\t$if trace_execution ? {\n\t\t\tstate.show('instruction ${i:08}: ${instruction:02x}, ${rune(instruction)}')\n\t\t}\n\t\tmatch instruction {\n\t\t\t`>` {\n\t\t\t\tstate.address++ // increment the address\n\t\t\t}\n\t\t\t`<` {\n\t\t\t\tstate.address-- // decrement the address\n\t\t\t}\n\t\t\t`+` {\n\t\t\t\tstate.memory[state.address]++ // increment the value at the address\n\t\t\t}\n\t\t\t`-` {\n\t\t\t\tstate.memory[state.address]-- // decrement the value at the address\n\t\t\t}\n\t\t\t`.` {\n\t\t\t\tprint(rune(state.memory[state.address])) // print the value at the address\n\t\t\t\tflush_stdout() // ensure that even single characters are printed immediately, and not buffered\n\t\t\t}\n\t\t\t`,` {\n\t\t\t\tinp := u8(term.utf8_getchar() or { 0 }) // read a character value from the standard input/terminal\n\t\t\t\tstate.memory[state.address] = inp\n\t\t\t}\n\t\t\t`[` {\n\t\t\t\tif state.memory[state.address] == 0 {\n\t\t\t\t\tstate.pc = u16(state.targets[state.pc])\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\t`]` {\n\t\t\t\tif state.memory[state.address] != 0 {\n\t\t\t\t\tstate.pc = u16(state.targets[state.pc])\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\t`#` {\n\t\t\t\tstate.show('#')\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// The interpreter should ignore characters that are not part of the language.\n\t\t\t\t// I.e. they are treated like programmer comments.\n\t\t\t}\n\t\t}\n\t\ti++\n\t\t// increment the program counter to go to the next instruction\n\t\tstate.pc++\n\t\t// go back to the line `for state.pc < state.program.len {`\n\t}\n}\n\n@[noreturn]\nfn show_usage() {\n\teprintln('you need to supply a brainfuck program/expression as a string argument,')\n\teprintln('or filename.b, if it is located in a file (note the `.b` or `.bf` extension).')\n\texit(1) // exit with non-zero exit code if there is no program to run\n}\n\nfn main() {\n\tif os.args.len < 2 {\n\t\tshow_usage()\n\t}\n\tmut program := os.args[1] // our program is fed in as a string\n\tif program.ends_with('.b') || program.ends_with('.bf') {\n\t\tprogram = os.read_file(program) or {\n\t\t\teprintln('error reading file ${program}: ${err}')\n\t\t\tshow_usage()\n\t\t}\n\t}\n\n\tmut state := BFState.new(program)\n\tstate.run()\n\n\tif show_state {\n\t\tstate.show('FINAL')\n\t}\n}\n"
  },
  {
    "path": "examples/bst_map.v",
    "content": "import datatypes\n\nstruct KeyVal {\nmut:\n\tkey int\n\tval int\n}\n\nfn (a KeyVal) == (b KeyVal) bool {\n\treturn a.key == b.key\n}\n\nfn (a KeyVal) < (b KeyVal) bool {\n\treturn a.key < b.key\n}\n\nfn main() {\n\tmut bst := datatypes.BSTree[KeyVal]{}\n\tbst.insert(KeyVal{ key: 1, val: 12 })\n\tprintln(bst.in_order_traversal())\n\n\tbst.insert(KeyVal{ key: 2, val: 34 })\n\tbst.insert(KeyVal{ key: -2, val: 203 })\n\n\tfor elem in bst.in_order_traversal() {\n\t\tprintln(elem.val)\n\t}\n}\n"
  },
  {
    "path": "examples/buf_reader.v",
    "content": "// Simple raw HTTP head request\nimport net\nimport time\nimport io\n\nfn main() {\n\t// Make a new connection\n\tmut conn := net.dial_tcp('google.com:80')!\n\t// Simple http HEAD request for a file\n\tconn.write_string('GET /index.html HTTP/1.0\\r\\n\\r\\n')!\n\t// Wrap in a buffered reader\n\tmut r := io.new_buffered_reader(reader: conn)\n\tfor {\n\t\tl := r.read_line() or { break }\n\t\tprintln('${l}')\n\t\t// Make it nice and obvious that we are doing this line by line\n\t\ttime.sleep(100 * time.millisecond)\n\t}\n}\n"
  },
  {
    "path": "examples/build_system/.gitignore",
    "content": "# Files and directories made by build.vsh:\n/target/\n/test.txt\n\n# Pre-compiled build.vsh\n/build\n"
  },
  {
    "path": "examples/build_system/build.vsh",
    "content": "#!/usr/bin/env -S v run\n\nimport build\nimport time\n\n// Define variables that can be used to change tasks in the buildscript\nconst app_name = 'hello'\nconst program_args = 'World'\nconst build_dir = 'target'\n\n// Make the build context\nmut context := build.context(\n\t// Set the default task to `release` when no arguments are provided\n\tdefault: 'release'\n)\n\n// Add a few simple tasks\ncontext.task(name: 'doc', run: |self| system('echo \"Nothing to do\"'))\ncontext.task(name: 'run', run: |self| system('v run . ${program_args}'))\ncontext.task(name: 'build', run: |self| system('v .'))\ncontext.task(name: 'build.prod', run: |self| system('v -prod -o ${app_name} .'))\n\n// `_` to denote \"private\" tasks. Nothing stops the user from using it, but\n// this tells them that the task is not meant to be used by them.\ncontext.task(\n\tname: '_mkdirs'\n\t// The `help` field is displayed in `--tasks` to give a short summary of what the task does.\n\thelp: 'Makes the directories used by the application'\n\trun:  fn (self build.Task) ! {\n\t\tif !exists(build_dir) {\n\t\t\tmkdir_all(build_dir) or { panic(err) }\n\t\t}\n\t}\n)\n\n// This task will only run when the `test.txt` file is outdated\ncontext.artifact(\n\tname: 'test.txt'\n\thelp: 'Generate test.txt'\n\trun:  fn (self build.Task) ! {\n\t\twrite_file('test.txt', time.now().str())!\n\t}\n)\n\n// Add a more complex task\ncontext.task(\n\tname:    'release'\n\thelp:    'Build the app in production mode, generates documentation, and releases the build on Git'\n\tdepends: ['_mkdirs', 'doc', 'test.txt']\n\trun:     fn (self build.Task) ! {\n\t\tsystem('v -prod -o ${build_dir}/${app_name} .')\n\t\t// Pretend we are using Git to publish the built file as a release here.\n\t}\n)\n\n// Run the build context. This will iterate over os.args and each corresponding\n// task, skipping any arguments that start with a hyphen (-)\ncontext.run()\n"
  },
  {
    "path": "examples/build_system/main.v",
    "content": "import os\n\nfn main() {\n\tprintln('Hello, ${os.args[1]}!')\n}\n"
  },
  {
    "path": "examples/c_interop_wkhtmltopdf.v",
    "content": "import os\n\n// Example of C interop for a very handy task.\n//\n// wkhtmltopdf and wkhtmltoimage are open source (LGPLv3) command line tools to\n// render HTML into PDF and various image formats using the Qt WebKit rendering\n// engine. These run entirely \"headless\" and do not require a display or display\n// service.\n//\n// https://github.com/wkhtmltopdf/wkhtmltopdf\n// https://wkhtmltopdf.org/downloads.html\n// https://wkhtmltopdf.org/libwkhtmltox/\n#flag -lwkhtmltox\n#include \"wkhtmltox/pdf.h\" # You can install the C package for your system from the wkhtmltopdf.org/downloads.html page\n\npub struct C.wkhtmltopdf_global_settings {}\n\npub struct C.wkhtmltopdf_object_settings {}\n\npub struct C.wkhtmltopdf_converter {}\n\nfn C.wkhtmltopdf_init(use_graphics bool) i32\n\nfn C.wkhtmltopdf_deinit() i32\n\nfn C.wkhtmltopdf_version() &char\n\nfn C.wkhtmltopdf_create_global_settings() &C.wkhtmltopdf_global_settings\n\nfn C.wkhtmltopdf_destroy_global_settings(global_settings &C.wkhtmltopdf_global_settings)\n\nfn C.wkhtmltopdf_set_global_setting(global_settings &C.wkhtmltopdf_global_settings, name &char, value &char) bool\n\nfn C.wkhtmltopdf_create_object_settings() &C.wkhtmltopdf_object_settings\n\nfn C.wkhtmltopdf_destroy_object_settings(object_settings &C.wkhtmltopdf_object_settings)\n\nfn C.wkhtmltopdf_set_object_setting(object_settings &C.wkhtmltopdf_object_settings, name &char, value &char) bool\n\nfn C.wkhtmltopdf_create_converter(global_settings &C.wkhtmltopdf_global_settings) &C.wkhtmltopdf_converter\n\nfn C.wkhtmltopdf_destroy_converter(converter &C.wkhtmltopdf_converter)\n\nfn C.wkhtmltopdf_add_object(converter &C.wkhtmltopdf_converter, object_settings &C.wkhtmltopdf_object_settings,\n\tdata &char)\n\nfn C.wkhtmltopdf_convert(converter &C.wkhtmltopdf_converter) bool\n\nfn C.wkhtmltopdf_http_error_code(converter &C.wkhtmltopdf_converter) i32\n\nfn C.wkhtmltopdf_get_output(converter &C.wkhtmltopdf_converter, data &&char) i32\n\nfn main() {\n\t// init\n\tinit := C.wkhtmltopdf_init(0)\n\tprintln('wkhtmltopdf_init: ${init}')\n\tversion := unsafe { cstring_to_vstring(&char(C.wkhtmltopdf_version())) }\n\tprintln('wkhtmltopdf_version: ${version}')\n\tglobal_settings := C.wkhtmltopdf_create_global_settings()\n\tprintln('wkhtmltopdf_create_global_settings: ${voidptr(global_settings)}')\n\tobject_settings := C.wkhtmltopdf_create_object_settings()\n\tprintln('wkhtmltopdf_create_object_settings')\n\tconverter := C.wkhtmltopdf_create_converter(global_settings)\n\tprintln('wkhtmltopdf_create_converter: ${voidptr(converter)}')\n\t// convert\n\tmut result := C.wkhtmltopdf_set_object_setting(object_settings, c'page', c'http://www.google.com.br')\n\tprintln('wkhtmltopdf_set_object_setting: ${result} [page = http://www.google.com.br]')\n\tC.wkhtmltopdf_add_object(converter, object_settings, 0)\n\tprintln('wkhtmltopdf_add_object')\n\tresult = C.wkhtmltopdf_convert(converter)\n\tprintln('wkhtmltopdf_convert: ${result}')\n\terror_code := C.wkhtmltopdf_http_error_code(converter)\n\tprintln('wkhtmltopdf_http_error_code: ${error_code}')\n\tif result {\n\t\tpdata := &char(unsafe { nil })\n\t\tppdata := &pdata\n\t\tsize := C.wkhtmltopdf_get_output(converter, voidptr(ppdata))\n\t\tprintln('wkhtmltopdf_get_output: ${size} bytes')\n\t\tmut file := os.open_file('./google.pdf', 'w+', 0o666) or {\n\t\t\tprintln('ERR: ${err}')\n\t\t\treturn\n\t\t}\n\t\twrote := unsafe { file.write_ptr(pdata, size) }\n\t\tprintln('write_bytes: ${wrote} [./google.pdf]')\n\t\tfile.flush()\n\t\tfile.close()\n\t}\n\t// destroy\n\tC.wkhtmltopdf_destroy_converter(converter)\n\tprintln('wkhtmltopdf_destroy_converter')\n\tC.wkhtmltopdf_destroy_object_settings(object_settings)\n\tprintln('wkhtmltopdf_destroy_object_settings: ${voidptr(object_settings)}')\n\tC.wkhtmltopdf_destroy_global_settings(global_settings)\n\tprintln('wkhtmltopdf_destroy_global_settings')\n\tdeinit := C.wkhtmltopdf_deinit()\n\tprintln('wkhtmltopdf_deinit: ${deinit}')\n}\n"
  },
  {
    "path": "examples/call_c_from_v/main.c.v",
    "content": "#include <stdio.h>\n\nfn C.puts(&char) i32\n\nfn main() {\n\tC.puts(c'V can call C functions like `puts` too.')\n}\n"
  },
  {
    "path": "examples/call_v_from_c/.gitignore",
    "content": "# Ignore the generated C files in this directory\n*.c\n"
  },
  {
    "path": "examples/call_v_from_c/README.md",
    "content": "## A simple example to show how to call a function written in v from c\n\n### Compile as a shared library\n\n#### On Linux:\n\nStep 1: Compile the v code to a shared library using `v -cc gcc -shared v_test_print.v` or\n`v -cc gcc -shared v_test_math.v`.\n\nStep 2: Compile the c file using `gcc test_print.c v_test_print.so -o test_print -Wl,-rpath=.` or\n`gcc test_math.c v_test_math.so -o test_math -Wl,-rpath=.`.\n\nStep 3: Run the compiled c file using `./test_print` or `./test_math`.\n\n\n#### On Mac OSX:\n\nOn Mac OSX, libgc can be obtained from homebrew by `brew install libgc`.\nDuring compiling and/or linking, `-I/usr/local/include -L/usr/local/lib` (for x86_64),\nor `-I/opt/homebrew/include -L/opt/homebrew/lib` (for arm64) can be added depending the arch.\n\nStep 1: Compile the v code to a shared library using `v -cc gcc -shared v_test_print.v` or\n`v -cc gcc -shared v_test_math.v`.\n\nStep 2: Compile the c file using `gcc test_print.c v_test_print.dylib -o test_print` or\n`gcc test_math.c v_test_math.dylib -o test_math`.\n\nStep 3: Run the compiled c file using `LD_LIBRARY_PATH=. ./test_print` or\n`LD_LIBRARY_PATH=. ./test_math`.\n\n#### On Windows:\n\nStep 1: Compile the v code to a shared library using `v -cc gcc -shared v_test_print.v` or\n`v -cc gcc -shared v_test_math.v`.\n\nStep 2: Compile the c file using `gcc test_print.c v_test_print.dll -o test_print.exe` or\n`gcc test_math.c v_test_math.dll -o test_math.exe`.\n\nStep 3: Run the compiled c file using `test_print.exe` or `test_math.exe`.\n\n### Compile as a c file\n\n***Requirements: `libgc` must be installed***\n\nStep 1: Compile the v code to a shared library using\n`v -shared -cc gcc -o v_test_print.c v_test_print.v` or\n`v -shared -cc gcc -o v_test_math.c v_test_math.v`.\n\n*Specifying the output with a `.c` extension will generate the corresponding C source file.*\n\nStep 2: Compile the c file using `gcc test_print.c v_test_print.c -o test_print -lgc` or\n`gcc test_math.c v_test_math.c -o test_math -lgc -lm`.\n\nStep 3: Run the compiled c file using `./test_print` or `./test_math`.\n"
  },
  {
    "path": "examples/call_v_from_c/v_test_math.v",
    "content": "// vtest build: false // Check the README.md for detailed information; this file needs special compilation options\nmodule test_math\n\nimport math\n\n@[export: 'square']\nfn calculate_square(i int) int {\n\treturn i * i\n}\n\n@[export: 'sqrt_of_sum_of_squares']\nfn calculate_sqrt_of_sum_of_squares(x f64, y f64) f64 {\n\treturn math.sqrt(x * x + y * y)\n}\n"
  },
  {
    "path": "examples/call_v_from_c/v_test_print.v",
    "content": "// vtest build: false // Check the README.md for detailed information; this file needs special compilation options\nmodule test_print\n\n@[export: 'foo']\nfn show_foo(s &char) {\n\tprintln(unsafe { cstring_to_vstring(s) })\n}\n"
  },
  {
    "path": "examples/call_v_from_python/README.md",
    "content": "A simple example to show how to call a function written in v from python\n\nStep 1: Compile the v code to a shared library using `v -d no_backtrace -shared test.v`\n\nStep 2: Run the python file using `python3 test.py`\n\nNote: you do not need `-d no_backtrace` if you use gcc or clang .\n"
  },
  {
    "path": "examples/call_v_from_python/test.py",
    "content": "from ctypes import *\nimport math, os\n\n## Load the V shared library:\nso_file=\"./test.so\"\nif os.name==\"nt\":\n  so_file=\"./test.dll\"\nlib = CDLL(so_file)\n\n## Pass an integer to a V function, and receiving back an integer:\nprint(\"lib.square(10) result is\", lib.square(10))\nassert lib.square(10) == 100, \"Cannot validate V square().\"\n\n## Pass a floating point number to a V function:\nlib.sqrt_of_sum_of_squares.restype = c_double\nassert lib.sqrt_of_sum_of_squares(c_double(1.1), c_double(2.2)) == math.sqrt(1.1*1.1 + 2.2*2.2), \"Cannot validate V sqrt_of_sum_of_squares().\"\n\n## Passing a V string to a V function, and receiving back a V string:\nclass VString(Structure):\n  _fields_ = [(\"str\", c_char_p), (\"len\", c_int)]\n\nlib.process_v_string.argtypes = [VString]\nlib.process_v_string.restype = VString\n\nassert lib.process_v_string(VString(b'World', 5)).str == b'v World v'\nprint('Hello', str(lib.process_v_string(VString(b'World', 5)).str, 'utf-8'))\n"
  },
  {
    "path": "examples/call_v_from_python/test.v",
    "content": "// vtest build: present_python? // the example only makes sense to be compiled, when python is installed\nmodule test\n\n// Note: compile this with `v -d no_backtrace -shared test.v`\nimport math\n\n@[export: 'square']\nfn square(i int) int {\n\treturn i * i\n}\n\n@[export: 'sqrt_of_sum_of_squares']\nfn sqrt_of_sum_of_squares(x f64, y f64) f64 {\n\treturn math.sqrt(x * x + y * y)\n}\n\n// you do not have to use the same name in the export attribute\n@[export: 'process_v_string']\nfn work(s string) string {\n\treturn 'v ${s} v'\n}\n"
  },
  {
    "path": "examples/call_v_from_ruby/README.md",
    "content": "A simple example to show how to call a function written in v from ruby\n\nStep 1: Compile the v code to a shared library using `v -d no_backtrace -shared test.v`\n\nStep 2: Run the ruby file using `ruby test.rb`\n\nNote: you do not need `-d no_backtrace` if you use gcc or clang .\n"
  },
  {
    "path": "examples/call_v_from_ruby/test.rb",
    "content": "require 'bundler/inline'\n\ngemfile do\n  source 'https://rubygems.org'\n  gem 'ffi'\nend\n\nrequire 'ffi'\n\n# extension for shared libraries varies by platform - see vlib/dl/dl.v\n# get_shared_library_extension()\ndef shared_library_extension\n  if Gem.win_platform?\n    '.dll'\n  elsif RUBY_PLATFORM =~ /darwin/ # MacOS\n    '.dylib'\n  else\n    '.so'\n  end\nend\n\nmodule Lib\n  extend FFI::Library\n\n  begin\n    ffi_lib File.join(File.dirname(__FILE__), 'test' + shared_library_extension)\n  rescue LoadError\n    abort(\"No shared library test#{shared_library_extension} found. Check examples/call_v_from_ruby/README.md\")\n  end\n\n  attach_function :square, [:int], :int\n  attach_function :sqrt_of_sum_of_squares, [:double, :double], :double\nend\n\nputs \"Lib.square(10) result is #{Lib.square(10)}\"\nraise 'Cannot validate V square().' unless Lib.square(10) == 100\n\nraise 'Cannot validate V sqrt_of_sum_of_squares().' unless \\\n  Lib.sqrt_of_sum_of_squares(1.1, 2.2) == Math.sqrt(1.1*1.1 + 2.2*2.2)\n"
  },
  {
    "path": "examples/call_v_from_ruby/test.v",
    "content": "// vtest build: present_ruby? // the example only makes sense to be compiled, when ruby is installed\nmodule test\n\nimport math\n\n@[export: 'square']\nfn square(i int) int {\n\treturn i * i\n}\n\n@[export: 'sqrt_of_sum_of_squares']\nfn sqrt_of_sum_of_squares(x f64, y f64) f64 {\n\treturn math.sqrt(x * x + y * y)\n}\n"
  },
  {
    "path": "examples/cli.v",
    "content": "module main\n\nimport cli { Command, Flag }\nimport os\n\nfn main() {\n\tmut cmd := Command{\n\t\tname:        'cli'\n\t\tdescription: 'An example of the cli library.'\n\t\tversion:     '1.0.0'\n\t}\n\tmut greet_cmd := Command{\n\t\tname:          'greet'\n\t\tdescription:   'Prints greeting in different languages.'\n\t\tusage:         '<name>'\n\t\trequired_args: 1\n\t\tpre_execute:   greet_pre_func\n\t\texecute:       greet_func\n\t\tpost_execute:  greet_post_func\n\t}\n\tgreet_cmd.add_flag(Flag{\n\t\tflag:        .string\n\t\trequired:    true\n\t\tname:        'language'\n\t\tabbrev:      'l'\n\t\tdescription: 'Language of the message.'\n\t})\n\tgreet_cmd.add_flag(Flag{\n\t\tflag:          .int\n\t\tname:          'times'\n\t\tdefault_value: ['3']\n\t\tdescription:   'Number of times the message gets printed.'\n\t})\n\tgreet_cmd.add_flag(Flag{\n\t\tflag:        .string_array\n\t\tname:        'fun'\n\t\tdescription: 'Just a dumby flags to show multiple.'\n\t})\n\tcmd.add_command(greet_cmd)\n\tcmd.setup()\n\tcmd.parse(os.args)\n}\n\nfn greet_func(cmd Command) ! {\n\tlanguage := cmd.flags.get_string('language') or {\n\t\tpanic('Failed to get `language` flag: ${err}')\n\t}\n\ttimes := cmd.flags.get_int('times') or { panic('Failed to get `times` flag: ${err}') }\n\tname := cmd.args[0]\n\tfor _ in 0 .. times {\n\t\tmatch language {\n\t\t\t'english', 'en' {\n\t\t\t\tprintln('Welcome ${name}')\n\t\t\t}\n\t\t\t'german', 'de' {\n\t\t\t\tprintln('Willkommen ${name}')\n\t\t\t}\n\t\t\t'dutch', 'nl' {\n\t\t\t\tprintln('Welkom ${name}')\n\t\t\t}\n\t\t\telse {\n\t\t\t\tprintln('Unsupported language')\n\t\t\t\tprintln('Supported languages are `english`, `german` and `dutch`.')\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\tfun := cmd.flags.get_strings('fun') or { panic('Failed to get `fun` flag: ${err}') }\n\tfor f in fun {\n\t\tprintln('fun: ${f}')\n\t}\n}\n\nfn greet_pre_func(_cmd Command) ! {\n\tprintln('This is a function running before the main function.\\n')\n}\n\nfn greet_post_func(_cmd Command) ! {\n\tprintln('\\nThis is a function running after the main function.')\n}\n"
  },
  {
    "path": "examples/clock/clock.v",
    "content": "// An X11 clock modeled after https://en.wikipedia.org/wiki/Station_clock\n// This is a small V example that was based off of the fireworks example.\n// Written by Stefan Schroeder in 2021 for the v project examples.\n// See LICENSE for license information.\nimport gg\nimport math\nimport time\n\n// All coordinates are designed for a clock size of this many pixel.\n// You cannot change the size of the clock by adjusting this value.\nconst design_size = 700\nconst center = 350\n\n// Half the width of a tic-mark.\nconst tw = 9\n// Height of a minute tic-mark. (hour is twice, 3-hour is thrice)\nconst th = 25\n// Padding of tic-mark to window border\nconst tp = 10\n\nconst tic_color = gg.Color{\n\tr: 50\n\tg: 50\n\tb: 50\n}\nconst hand_color = gg.black\nconst second_hand_color = gg.red\n\nstruct App {\n\tminutes_tic []f32 = [f32(center - tw), tp, center + tw, tp, center + tw, tp, center + tw,\n\ttp + 1 * th, center - tw, tp + 1 * th]\n\thours_tic   []f32 = [f32(center - tw), tp, center + tw, tp, center + tw, tp, center + tw,\n\ttp + 2 * th, center - tw, tp + 2 * th]\n\thours3_tic  []f32 = [f32(center - tw), tp, center + tw, tp, center + tw, tp, center + tw,\n\ttp + 3 * th, center - tw, tp + 3 * th]\n\n\thour_hand   []f32 = [f32(329), 161, 350, 140, 371, 161, 371, 413, 329, 413]\n\tminute_hand []f32 = [f32(334.25), 40.25, 350, 24.5, 365.75, 40.25, 365.75, 427, 334.25, 427]\n\tsecond_hand []f32 = [f32(345.8), 38.5, 350, 34.3, 354.2000, 38.5, 358.75, 427, 341.25, 427]\nmut:\n\tgg        &gg.Context = unsafe { nil }\n\tdraw_flag bool        = true\n\tdpi_scale f32         = 1.0\n}\n\nfn on_frame(mut app App) {\n\tif !app.draw_flag {\n\t\treturn\n\t}\n\tapp.gg.begin()\n\n\tfor i in 0 .. 60 { // draw minute tics\n\t\tdraw_convex_poly_rotate(mut app.gg, app.dpi_scale, app.minutes_tic, tic_color,\n\t\t\ti * 6)\n\t}\n\tfor i in 0 .. 12 { // hours\n\t\tdraw_convex_poly_rotate(mut app.gg, app.dpi_scale, app.hours_tic, tic_color, i * 30)\n\t}\n\tfor i in 0 .. 4 { // 3 hours\n\t\tdraw_convex_poly_rotate(mut app.gg, app.dpi_scale, app.hours3_tic, tic_color,\n\t\t\ti * 90)\n\t}\n\n\tn := time.now()\n\n\t// draw hour hand\n\ti := f32(n.hour) + f32(n.minute) / 60.0\n\tdraw_convex_poly_rotate(mut app.gg, app.dpi_scale, app.hour_hand, hand_color, i * 30)\n\n\t// draw minute hand\n\tmut j := f32(n.minute)\n\tif n.second == 59 { // make minute hand move smoothly\n\t\tj += f32(math.sin(f32(n.nanosecond) / 1e9 * math.pi / 2.0))\n\t}\n\tdraw_convex_poly_rotate(mut app.gg, app.dpi_scale, app.minute_hand, hand_color, j * 6)\n\n\t// draw second hand with smooth transition\n\tk := f32(n.second) + f32(math.sin(f32(n.nanosecond) / 1e9 * math.pi / 2.0))\n\tdraw_convex_poly_rotate(mut app.gg, app.dpi_scale, app.second_hand, second_hand_color,\n\t\t0 + k * 6)\n\n\tapp.gg.end()\n}\n\n// Rotate a polygon round the centerpoint\n@[manualfree]\nfn draw_convex_poly_rotate(mut ctx gg.Context, dpi_scale f32, points []f32, c gg.Color, angle f32) {\n\tsa := math.sin(math.pi * angle / 180.0)\n\tca := math.cos(math.pi * angle / 180.0)\n\n\tmut rotated_points := []f32{cap: points.len}\n\tfor i := 0; i < points.len / 2; i++ {\n\t\tx := points[2 * i]\n\t\ty := points[2 * i + 1]\n\t\txn := f32((x - center) * ca - (y - center) * sa)\n\t\tyn := f32((x - center) * sa + (y - center) * ca)\n\t\trotated_points << (xn + center) * dpi_scale\n\t\trotated_points << (yn + center) * dpi_scale\n\t}\n\tctx.draw_convex_poly(rotated_points, c)\n\tunsafe { rotated_points.free() }\n}\n\nfn (mut app App) resize() {\n\tsize := gg.window_size()\n\t// avoid calls when minimized\n\tif size.width < 2 && size.height < 2 {\n\t\treturn\n\t}\n\tw := f32(size.width) / design_size\n\th := f32(size.height) / design_size\n\tapp.dpi_scale = if w < h { w } else { h }\n}\n\nfn on_event(e &gg.Event, mut app App) {\n\tmatch e.typ {\n\t\t.resized, .resumed {\n\t\t\tapp.resize()\n\t\t}\n\t\t.iconified {\n\t\t\tapp.draw_flag = false\n\t\t}\n\t\t.restored {\n\t\t\tapp.draw_flag = true\n\t\t\tapp.resize()\n\t\t}\n\t\telse {\n\t\t\tif e.typ == .key_down {\n\t\t\t\tmatch e.key_code {\n\t\t\t\t\t.q {\n\t\t\t\t\t\tprintln('Good bye.')\n\t\t\t\t\t\t// do we need to free anything here?\n\t\t\t\t\t\tapp.gg.quit()\n\t\t\t\t\t}\n\t\t\t\t\telse {}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfn on_init(mut app App) {\n\tapp.resize()\n}\n\nfn main() {\n\tprintln(\"Press 'q' to quit.\")\n\tmut app := &App{}\n\tapp.gg = gg.new_context(\n\t\twidth:        design_size\n\t\theight:       design_size\n\t\twindow_title: 'Clock!'\n\t\tbg_color:     gg.white\n\t\tuser_data:    app\n\t\tframe_fn:     on_frame\n\t\tevent_fn:     on_event\n\t\tinit_fn:      on_init\n\t)\n\tapp.gg.run()\n}\n"
  },
  {
    "path": "examples/compiletime/d_compile_value.v",
    "content": "// This example shows how to use V's compile time defines and values via the -d flag and $d() function.\n//\n// To change the default values below, pass compile flags to v using: `-d ident=<value>`\n// Examples:\n// ´´´\n// v -d header -d pad=10 -d jobs=8 run d_compile_value.v\n// v -d id=\"Bob\" -d pad=2 -d pad_char='$' -d jobs=10 run d_compile_value.v\n// ```\n\nconst pad = $d('pad', 5)\nconst pad_char = $d('pad_char', `-`)\n\nconst footer = '\nAvailable compile time flags:\n -d pad=<i64>\n -d pad_char=<character>\n -d id=\"<string>\"\n -d jobs=<i64>\n -d header=<bool>\nYou can turn this message off with:\n -d footer=false'\n\nstruct Job {\n\tid string = $d('id', 'Job') // adjust with `-d id=\"My ID\"`\n}\n\nstruct App {\n\tjobs [$d('jobs', 4)]Job // adjust fixed array size with `-d jobs=6`\n}\n\n// println_padded prints `str` to stdout with a padding.\n// Padding length and padding character can be adjusted at compile time\n// via `-d pad=1` and `-d pad_char=x`.\nfn println_padded(str string) {\n\tfor _ in 0 .. pad {\n\t\tprint(rune(pad_char))\n\t}\n\tprintln(' ${str}')\n}\n\nfn main() {\n\theader := $d('header', false) // adjust header variable with `-d header=true` or simply `-d header`\n\tif header {\n\t\tprintln_padded('Compile Value Example')\n\t}\n\n\tapp := App{}\n\tfor i, job in app.jobs {\n\t\tprintln_padded('${job.id} ${i + 1}')\n\t}\n\n\t// Turn the footer message off using `-d footer=false`\n\tif $d('footer', true) {\n\t\tprintln(footer)\n\t}\n}\n"
  },
  {
    "path": "examples/compiletime/methods.v",
    "content": "struct App {}\n\nfn (mut app App) method_one() {}\n\nfn (mut app App) method_two() int {\n\treturn 0\n}\n\nfn (mut app App) method_three(s string) string {\n\treturn s\n}\n\nfn main() {\n\t$for method in App.methods {\n\t\t$if method.typ is fn (string) string {\n\t\t\tprintln('${method.name} IS `fn(string) string`')\n\t\t} $else {\n\t\t\tprintln('${method.name} is NOT `fn(string) string`')\n\t\t}\n\t\t$if method.return_type !is int {\n\t\t\tprintln('${method.name} does NOT return `int`')\n\t\t} $else {\n\t\t\tprintln('${method.name} DOES return `int`')\n\t\t}\n\t\t$if method.args[0].typ !is string {\n\t\t\tprintln(\"${method.name}'s first arg is NOT `string`\")\n\t\t} $else {\n\t\t\tprintln(\"${method.name}'s first arg IS `string`\")\n\t\t}\n\t\t// TODO: Double inversion, should this even be allowed?\n\t\t$if method.typ is fn () {\n\t\t\tprintln('${method.name} IS a void method')\n\t\t} $else {\n\t\t\tprintln('${method.name} is NOT a void method')\n\t\t}\n\t\tprintln('')\n\t}\n}\n"
  },
  {
    "path": "examples/compiletime/reflection.v",
    "content": "// An example deserializer implementation\n\nstruct User {\n\tname string\n\tage  int\n}\n\nfn main() {\n\tdata := 'name=Alice\\nage=18'\n\tuser := decode[User](data)\n\tprintln(user)\n}\n\nfn decode[T](data string) T {\n\tmut result := T{}\n\t// compile-time `for` loop\n\t// T.fields gives an array of a field metadata type\n\t$for field in T.fields {\n\t\t$if field.typ is string {\n\t\t\t// $(string_expr) produces an identifier\n\t\t\tresult.$(field.name) = get_string(data, field.name)\n\t\t} $else $if field.typ is int {\n\t\t\tresult.$(field.name) = get_int(data, field.name)\n\t\t}\n\t}\n\treturn result\n}\n\nfn get_string(data string, field_name string) string {\n\tfor line in data.split_into_lines() {\n\t\tkey_val := line.split('=')\n\t\tif key_val[0] == field_name {\n\t\t\treturn key_val[1]\n\t\t}\n\t}\n\treturn ''\n}\n\nfn get_int(data string, field string) int {\n\treturn get_string(data, field).int()\n}\n\n// `decode<User>` generates:\n// fn decode_User(data string) User {\n//     mut result := User{}\n//     result.name = get_string(data, 'name')\n//     result.age = get_int(data, 'age')\n//     return result\n// }\n"
  },
  {
    "path": "examples/concurrency/concurrency.v",
    "content": "import time\n\n// Simulate expensive computing using sleep function\nfn expensive_computing(id int, duration int) {\n\tprintln('Executing expensive computing task (${id})...')\n\ttime.sleep(duration * time.millisecond)\n\tprintln('Finish task ${id} on ${duration} ms')\n}\n\nfn main() {\n\tmut threads := []thread{}\n\tthreads << spawn expensive_computing(1, 100)\n\tthreads << spawn expensive_computing(2, 500)\n\tthreads << spawn expensive_computing(3, 1000)\n\t// Join all tasks\n\tthreads.wait()\n\tprintln('All jobs finished!')\n}\n"
  },
  {
    "path": "examples/concurrency/concurrency_http.v",
    "content": "import net.http\nimport sync\nimport time\n\nfn vlang_time(mut wg sync.WaitGroup) !string {\n\tstart := time.ticks()\n\tdata := http.get('https://vlang.io/utc_now')!\n\tfinish := time.ticks()\n\tprintln('Finish getting time ${finish - start} ms')\n\tprintln(data.body)\n\twg.done()\n\treturn data.body\n}\n\nfn remote_ip(mut wg sync.WaitGroup) !string {\n\tstart := time.ticks()\n\tdata := http.get('https://api.ipify.org')!\n\tfinish := time.ticks()\n\tprintln('Finish getting ip ${finish - start} ms')\n\tprintln(data.body)\n\twg.done()\n\treturn data.body\n}\n\nfn main() {\n\tmut wg := sync.new_waitgroup()\n\twg.add(2)\n\t// Run tasks async\n\tspawn vlang_time(mut wg)\n\tspawn remote_ip(mut wg)\n\twg.wait()\n}\n"
  },
  {
    "path": "examples/concurrency/concurrency_returns.v",
    "content": "fn expensive_computing(i int) int {\n\treturn i * i\n}\n\nfn main() {\n\tmut threads := []thread int{}\n\tfor i in 1 .. 10 {\n\t\tthreads << spawn expensive_computing(i)\n\t}\n\t// Join all tasks\n\tr := threads.wait()\n\tprintln('All jobs finished: ${r}')\n}\n"
  },
  {
    "path": "examples/control_thread_stack_size.v",
    "content": "module main\n\nfn main() {\n\tth := spawn my_print1()\n\tth.wait()\n\tth2 := spawn my_print2()\n\tth2.wait()\n}\n\n// default stack size\nfn my_print1() {\n\tprintln('hello word')\n}\n\n// 2MB  stack size\n@[spawn_stack: 2097152]\nfn my_print2() {\n\tprintln('ahoj svet')\n}\n"
  },
  {
    "path": "examples/coroutines/.skip_should_compile_all",
    "content": ""
  },
  {
    "path": "examples/coroutines/coroutines_bench.v",
    "content": "// vtest build: false // This should be build with: `v -use-coroutines coroutine_benchs.v`\n// Note: the Photon wrapper is not yet trivial enough to build/install on the CI.\nimport coroutines\nimport time\nimport net.http\nimport sync\n\nconst run_time = 10 * time.second\n\nfn request(mut mu sync.Mutex, count &int) {\n\tfor {\n\t\thttp.get('http://vlang.io/utc_now') or { panic(err) }\n\t\tmu.lock()\n\t\tunsafe {\n\t\t\t(*count)++\n\t\t}\n\t\tmu.unlock()\n\t}\n}\n\nfn main() {\n\tmut mu := sync.new_mutex()\n\tmut count := 0\n\n\tfor _ in 0 .. 8 {\n\t\tgo request(mut mu, &count)\n\t}\n\t$if is_coroutine ? {\n\t\tprintln('IS COROUTINE=true')\n\t\tcoroutines.sleep(run_time)\n\t} $else {\n\t\tprintln('IS COROUTINE=false')\n\t\ttime.sleep(run_time)\n\t}\n\tprintln('${count} requests made.')\n}\n"
  },
  {
    "path": "examples/coroutines/simple_coroutines.v",
    "content": "// vtest build: false // This should be build with: v -use-coroutines simple_coroutines.v\n// Note: the Photon wrapper is not yet trivial enough to build/install on the CI.\nimport coroutines\nimport time\nimport os\nimport net.http\n\nfn foo(a int) {\n\tfor {\n\t\tprintln('1hello from foo() a=${a}')\n\t\t// C.printf(c'hello from foo() a=%d\\n', a)\n\t\tcoroutines.sleep(1 * time.second)\n\t}\n}\n\nfn foo2(a int) {\n\tmut i := 0\n\tfor {\n\t\tprintln('hello from foo2() a=${a}')\n\t\t// C.printf(c'hello from foo2() a=%d\\n', a)\n\t\tcoroutines.sleep(2 * time.second)\n\t\ti++\n\t\tresp := http.get('https://vlang.io/utc_now') or { panic(err) }\n\t\tprintln(resp)\n\t\tmut f := os.create('/tmp/FOO2_a${i}') or { panic(err) }\n\t\tf.write_string(resp.body) or { panic(err) }\n\t\tf.close()\n\t}\n}\n\nfn foo3(a int) {\n\tfor {\n\t\tprintln('hello from foo3() a=${a}')\n\t\t// C.printf(c'hello from foo3() a=%d\\n', a)\n\t\tcoroutines.sleep(3 * time.second)\n\t}\n}\n\nfn foo4(a int) {\n\tfor {\n\t\tprintln('hello from foo4() a=${a}')\n\t\t// C.printf(c'hello from foo4() a=%d\\n', a)\n\t\tcoroutines.sleep(3 * time.second)\n\t}\n}\n\nfn main() {\n\tgo foo(10)\n\tgo foo2(20)\n\tgo foo3(30)\n\tgo foo3(40)\n\t$if is_coroutine ? {\n\t\tprintln('IS COROUTINE=true')\n\t} $else {\n\t\tprintln('IS COROUTINE=false')\n\t}\n\tfor {\n\t\tprintln('hello from MAIN')\n\t\tcoroutines.sleep(1 * time.second)\n\t}\n\tprintln('done')\n}\n"
  },
  {
    "path": "examples/cpu_features/SSE_and_MMX_Extensions/README.md",
    "content": "Note: To more deep study see https://en.wikibooks.org/wiki/X86_Assembly\n\n# SSE and MMX Extensions\n\nThis document provides an overview of the SSE and MMX extensions used in the project.\n\n## Table of Contents\n\n- [Introduction](#introduction)\n- [SSE Extensions](#sse-extensions)\n- [MMX Extensions](#mmx-extensions)\n- [Usage](#usage)\n\n## Introduction\n\nSSE (Streaming SIMD Extensions) and MMX (MultiMedia eXtensions) are instruction sets used to\nenhance the performance of multimedia and signal processing applications.\n\n## SSE Extensions\n\nSSE extensions provide a set of instructions that can handle multiple data with a single\ninstruction, improving the performance of applications that require heavy mathematical\ncomputations.\n\nfrom: [wikibooks](https://en.wikibooks.org/wiki/X86_Assembly/SSE#SSE_Instruction_Set)\nThere are literally hundreds of SSE instructions, some of which are capable of much more than\nsimple SIMD arithmetic. For more in-depth references take a look at the resources chapter of this\nbook.\n\nYou may notice that many floating point SSE instructions end with something like PS or SD. These\nsuffixes differentiate between different versions of the operation. The first letter describes\nwhether the instruction should be Packed or Scalar. Packed operations are applied to every member\nof the register, while scalar operations are applied to only the first value. For example, in\npseudo-code, a packed add would be executed as:\n\n```\nv1[0] = v1[0] + v2[0]\nv1[1] = v1[1] + v2[1]\nv1[2] = v1[2] + v2[2]\nv1[3] = v1[3] + v2[3]\n```\n\nWhile a scalar add would only be:\n\n```\nv1[0] = v1[0] + v2[0]\n```\n\nThe second letter refers to the data size: either Single or Double. This simply tells the\nprocessor whether to use the register as four 32-bit floats or two 64-bit doubles, respectively.\n\n## MMX Extensions\n\nMMX extensions are designed to accelerate multimedia and communication applications by providing\ninstructions that can process multiple data elements in parallel.\n\n## Usage\n\nTo use these extensions in your project, ensure that your compiler supports them and that you have\nenabled the appropriate flags.\nOn Linux, you can run the command `lscpu`\n\nNote: the examples here will compile, but not run on CPU architectures != amd64, like ARM or RISCV .\n"
  },
  {
    "path": "examples/cpu_features/SSE_and_MMX_Extensions/mmx.v",
    "content": "// MMX Instruction Set\n// Several suffixes are used to indicate what data size the instruction operates on:\n// Byte (8 bits)\n// Word (16 bits)\n// Double word (32 bits)\n// Quad word (64 bits)\n// The signedness of the operation is also signified by the suffix: US for unsigned and S for signed.\n// For example, PSUBUSB subtracts unsigned bytes, while PSUBSD subtracts signed double words.\n// MMX defined over 40 new instructions, listed below.\n// EMMS, MOVD, MOVQ, PACKSSDW, PACKSSWB, PACKUSWB, PADDB, PADDD, PADDSB, PADDSW, PADDUSB, PADDUSW,\n// PADDW, PAND, PANDN, PCMPEQB, PCMPEQD, PCMPEQW, PCMPGTB, PCMPGTD, PCMPGTW, PMADDWD, PMULHW, PMULLW,\n// POR, PSLLD, PSLLQ, PSLLW, PSRAD, PSRAW, PSRLD, PSRLQ, PSRLW, PSUBB, PSUBD, PSUBSB, PSUBSW, PSUBUSB,\n// PSUBUSW, PSUBW, PUNPCKHBW, PUNPCKHDQ, PUNPCKHWD, PUNPCKLBW, PUNPCKLDQ, PUNPCKLWD, PXOR\n\n@[if amd64 && !tinyc && !msvc]\nfn add_vectors_mmx(a &u8, b &u8, result &u8) {\n\tunsafe {\n\t\tasm volatile amd64 {\n\t\t\tmovq mm0, [a] // Load 8 bytes from a into MMX register mm0\n\t\t\tmovq mm1, [b] // Load 8 bytes from b into MMX register mm1\n\t\t\tpaddb mm0, mm1 // Add the two vectors using MMX instruction\n\t\t\tmovq [result], mm0 // Store the result back to memory\n\t\t\t; ; r (a)\n\t\t\t  r (b)\n\t\t\t  r (result)\n\t\t\t; mm0\n\t\t\t  mm1\n\t\t}\n\t}\n}\n\nfn main() {\n\ta := [u8(1), 2, 3, 4, 5, 6, 7, 8]\n\tb := [u8(8), 7, 6, 5, 4, 3, 2, 1]\n\tresult := []u8{len: 8}\n\tadd_vectors_mmx(&a[0], &b[0], &result[0])\n\tprintln(result)\n\tassert result == [u8(9), 9, 9, 9, 9, 9, 9, 9]\n}\n"
  },
  {
    "path": "examples/cpu_features/SSE_and_MMX_Extensions/sse.v",
    "content": "// SSE Instruction Set\n// SSE: Added with Pentium III\n// Floating-point Instructions:\n// ADDPS, ADDSS, CMPPS, CMPSS, COMISS, CVTPI2PS, CVTPS2PI, CVTSI2SS, CVTSS2SI, CVTTPS2PI, CVTTSS2SI,\n// DIVPS, DIVSS, LDMXCSR, MAXPS, MAXSS, MINPS, MINSS, MOVAPS, MOVHLPS, MOVHPS, MOVLHPS, MOVLPS,\n// MOVMSKPS, MOVNTPS, MOVSS, MOVUPS, MULPS, MULSS, RCPPS, RCPSS, RSQRTPS, RSQRTSS, SHUFPS, SQRTPS,\n// SQRTSS, STMXCSR, SUBPS, SUBSS, UCOMISS, UNPCKHPS, UNPCKLPS\n//\n// Integer Instructions:\n// ANDNPS, ANDPS, ORPS, PAVGB, PAVGW, PEXTRW, PINSRW, PMAXSW, PMAXUB, PMINSW, PMINUB, PMOVMSKB, PMULHUW, PSADBW, PSHUFW, XORPS\n// The ADDPS instruction adds two vectors of floats using SSE instructions.\n\n@[if amd64 && !tinyc && !msvc]\nfn add_vectors_sse(a &f32, b &f32, result &f32) {\n\tunsafe {\n\t\tasm volatile amd64 {\n\t\t\tmovups xmm0, [a] // Load 4 floats from array a into SSE register xmm0\n\t\t\tmovups xmm1, [b] // Load 4 floats from array b into SSE register xmm1\n\t\t\taddps xmm0, xmm1 // Add the two vectors using SSE instruction\n\t\t\tmovups [result], xmm0 // Store the result back to memory\n\t\t\t; ; r (a)\n\t\t\t  r (b)\n\t\t\t  r (result)\n\t\t\t; xmm0\n\t\t\t  xmm1\n\t\t}\n\t}\n}\n\nfn main() {\n\ta := [f32(1.0), 2.0, 3.0, 4.0]\n\tb := [f32(4.0), 3.0, 2.0, 1.0]\n\tresult := []f32{len: 4}\n\tadd_vectors_sse(&a[0], &b[0], &result[0])\n\tprintln(result)\n\tassert result == [f32(5.0), 5.0, 5.0, 5.0]\n}\n"
  },
  {
    "path": "examples/cpu_features/SSE_and_MMX_Extensions/sse2.v",
    "content": "// SSE Instruction Set\n// SSE2: Added with Pentium 4\n// Floating-point Instructions:\n// ADDPD, ADDSD, ANDNPD, ANDPD, CMPPD, CMPSD*, COMISD, CVTDQ2PD, CVTDQ2PS, CVTPD2DQ, CVTPD2PI,\n// CVTPD2PS, CVTPI2PD, CVTPS2DQ, CVTPS2PD, CVTSD2SI, CVTSD2SS, CVTSI2SD, CVTSS2SD, CVTTPD2DQ,\n// CVTTPD2PI, CVTTPS2DQ, CVTTSD2SI, DIVPD, DIVSD, MAXPD, MAXSD, MINPD, MINSD, MOVAPD, MOVHPD,\n// MOVLPD, MOVMSKPD, MOVSD*, MOVUPD, MULPD, MULSD, ORPD, SHUFPD, SQRTPD, SQRTSD, SUBPD, SUBSD,\n// UCOMISD, UNPCKHPD, UNPCKLPD, XORPD\n// * CMPSD and MOVSD have the same name as the string instruction mnemonics CMPSD (CMPS) and\n// MOVSD (MOVS); however, the former refer to scalar double-precision floating-points whereas\n// the latter refer to doubleword strings.\n// Integer Instructions:\n// MOVDQ2Q, MOVDQA, MOVDQU, MOVQ2DQ, PADDQ, PSUBQ, PMULUDQ, PSHUFHW, PSHUFLW, PSHUFD, PSLLDQ, PSRLDQ, PUNPCKHQDQ, PUNPCKLQDQ\n// The MULPD instruction multiplies two vectors of doubles using SSE2 instructions.\n\n@[if amd64 && !tinyc && !msvc]\nfn multiply_vectors_sse2(a &f64, b &f64, result &f64) {\n\tunsafe {\n\t\tasm volatile amd64 {\n\t\t\tmovupd xmm0, [a] // Load 2 doubles from array a into SSE2 register xmm0\n\t\t\tmovupd xmm1, [b] // Load 2 doubles from array b into SSE2 register xmm1\n\t\t\tmulpd xmm0, xmm1 // Multiply the two vectors using SSE2 instruction\n\t\t\tmovupd [result], xmm0 // Store the result back to memory\n\t\t\t; ; r (a)\n\t\t\t  r (b)\n\t\t\t  r (result)\n\t\t\t; xmm0\n\t\t\t  xmm1\n\t\t}\n\t}\n}\n\nfn main() {\n\ta := [f64(1.5), 2.5]\n\tb := [f64(3.5), 4.5]\n\tresult := []f64{len: 2}\n\tmultiply_vectors_sse2(&a[0], &b[0], &result[0])\n\tprintln(result)\n\t// 5.25 = 1.5 * 3.5\n\t// 11.25 = 2.5 * 4.5\n\tassert result == [f64(5.25), 11.25]\n}\n"
  },
  {
    "path": "examples/cpu_features/SSE_and_MMX_Extensions/sse3.v",
    "content": "// SSE Instruction Set\n// SSE3: Added with later Pentium 4\n// ADDSUBPD, ADDSUBPS, HADDPD, HADDPS, HSUBPD, HSUBPS, MOVDDUP, MOVSHDUP, MOVSLDUP\n// The HADDPS instruction performs horizontal addition of two vectors of floats using SSE3\n// instructions.\n\n@[if amd64 && !tinyc && !msvc]\nfn horizontal_add_sse3(a &f32, b &f32, result &f32) {\n\tunsafe {\n\t\tasm volatile amd64 {\n\t\t\tmovaps xmm0, [a] // Load 4 floats from array a into SSE3 register xmm0\n\t\t\tmovaps xmm1, [b] // Load 4 floats from array b into SSE3 register xmm1\n\t\t\thaddps xmm0, xmm1 // Perform horizontal add of xmm0 and xmm1\n\t\t\tmovaps [result], xmm0 // Store the result back to memory\n\t\t\t; ; r (a)\n\t\t\t  r (b)\n\t\t\t  r (result)\n\t\t\t; xmm0\n\t\t\t  xmm1\n\t\t}\n\t}\n}\n\nfn main() {\n\ta := [f32(1.0), 2.0, 3.0, 4.0]\n\tb := [f32(5.0), 6.0, 7.0, 8.0]\n\tresult := []f32{len: 4}\n\thorizontal_add_sse3(&a[0], &b[0], &result[0])\n\tprintln(result)\n\t// The result should be [3.0, 7.0, 11.0, 15.0] due to horizontal addition.\n\t// 1.0 + 2.0 = 3.0\n\t// 3.0 + 4.0 = 7.0\n\t// 5.0 + 6.0 = 11.0\n\t// 7.0 + 8.0 = 15.0\n\tassert result == [f32(3.0), 7.0, 11.0, 15.0]\n}\n"
  },
  {
    "path": "examples/cpu_features/SSE_and_MMX_Extensions/sse4_1.v",
    "content": "// SSE Instruction Set\n// SSE4.1: Added with later Core 2\n// MPSADBW, PHMINPOSUW, PMULLD, PMULDQ, DPPS, DPPD, BLENDPS, BLENDPD, BLENDVPS, BLENDVPD,\n// PBLENDVB, PBLENDW, PMINSB, PMAXSB, PMINUW, PMAXUW, PMINUD, PMAXUD, PMINSD, PMAXSD, ROUNDPS,\n// ROUNDSS, ROUNDPD, ROUNDSD, INSERTPS, PINSRB, PINSRD, PINSRQ, EXTRACTPS, PEXTRB, PEXTRW,\n// PEXTRD, PEXTRQ, PMOVSXBW, PMOVZXBW, PMOVSXBD, PMOVZXBD, PMOVSXBQ, PMOVZXBQ, PMOVSXWD,\n// PMOVZXWD, PMOVSXWQ, PMOVZXWQ, PMOVSXDQ, PMOVZXDQ, PTEST, PCMPEQQ, PACKUSDW, MOVNTDQA\n\n@[if amd64 && !tinyc && !msvc]\nfn round_floats_sse4_1(a &f32, result &f32) {\n\tunsafe {\n\t\tasm volatile amd64 {\n\t\t\tmovups xmm0, [a] // Load 4 floats from array a into xmm0\n\t\t\troundps xmm0, xmm0, 0 // Round to nearest integer\n\t\t\tmovups [result], xmm0 // Store the result in result array\n\t\t\t; ; r (a)\n\t\t\t  r (result)\n\t\t\t; xmm0\n\t\t}\n\t}\n}\n\nfn main() {\n\ta := [f32(1.2), 2.5, 3.8, 4.4]\n\tresult := []f32{len: 4}\n\t// Rounding mode 0 corresponds to rounding to the nearest integer\n\tround_floats_sse4_1(&a[0], &result[0])\n\tprintln(result)\n\t// The expected rounded result should be [1.0, 2.0, 4.0, 4.0]\n\tassert result == [f32(1.0), 2.0, 4.0, 4.0]\n}\n"
  },
  {
    "path": "examples/cpu_features/SSE_and_MMX_Extensions/ssse3.v",
    "content": "// SSE Instruction Set\n// SSSE3: Added with Xeon 5100 and early Core 2\n// PSIGNW, PSIGND, PSIGNB, PSHUFB, PMULHRSW, PMADDUBSW, PHSUBW, PHSUBSW, PHSUBD, PHADDW, PHADDSW,\n// PHADDD, PALIGNR, PABSW, PABSD, PABSB\n// The PSIGNW instruction negates or leaves elements unchanged based on another vector's signs.\n\n@[if amd64 && !tinyc && !msvc]\nfn psignw_example(a &i16, b &i16, result &i16) {\n\tunsafe {\n\t\tasm volatile amd64 {\n\t\t\tmovdqa xmm0, [a] // Load 8 signed 16-bit integers from array a into xmm0\n\t\t\tmovdqa xmm1, [b] // Load 8 signed 16-bit integers from array b into xmm1\n\t\t\tpsignw xmm0, xmm1 // Adjust the sign of elements in xmm0 based on xmm1\n\t\t\tmovdqa [result], xmm0 // Store the result back to memory\n\t\t\t; ; r (a)\n\t\t\t  r (b)\n\t\t\t  r (result)\n\t\t\t; xmm0\n\t\t\t  xmm1\n\t\t}\n\t}\n}\n\nfn main() {\n\ta0 := [i16(1), -2, 3, -4, 5, -6, 7, -8]\n\tb0 := [i16(1), -1, 1, -1, 1, -1, 1, -1]\n\tresult0 := []i16{len: 8}\n\tpsignw_example(&a0[0], &b0[0], &result0[0])\n\tdump(result0)\n\tassert result0 == [i16(1), 2, 3, 4, 5, 6, 7, 8]\n}\n"
  },
  {
    "path": "examples/custom_error.v",
    "content": "import semver\n\nfn main() {\n\tsemver.from('asd') or { check_error(err) }\n\tsemver.from('') or { check_error(err) }\n}\n\nfn check_error(err IError) {\n\tmatch err {\n\t\tsemver.InvalidVersionFormatError {\n\t\t\tprintln('wrong format')\n\t\t}\n\t\tsemver.EmptyInputError {\n\t\t\tprintln('empty input')\n\t\t}\n\t\telse {\n\t\t\tprintln('unknown error')\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/database/mysql.v",
    "content": "// vtest build: !(macos || windows)\nimport db.mysql\n\nfn main() {\n\tmut conn := mysql.connect(\n\t\thost:     'localhost'\n\t\tport:     3306\n\t\tusername: 'root'\n\t\tpassword: ''\n\t\tdbname:   'mysql'\n\t)!\n\tres := conn.query('show tables')!\n\tfor row in res.rows() {\n\t\tprintln(row.vals.join(', '))\n\t}\n\tconn.close()!\n}\n"
  },
  {
    "path": "examples/database/mysql_pool.v",
    "content": "// vtest build: !(macos || windows)\nimport db.mysql\nimport pool\nimport time\n\n// Define your connection factory function\nfn create_conn() !&pool.ConnectionPoolable {\n\tconfig := mysql.Config{\n\t\thost:     '127.0.0.1'\n\t\tport:     3306\n\t\tusername: 'root'\n\t\tpassword: '12345678'\n\t\tdbname:   'mysql'\n\t}\n\tdb := mysql.connect(config)!\n\treturn &db\n}\n\nfn main() {\n\t// Configure pool parameters\n\tconfig := pool.ConnectionPoolConfig{\n\t\tmax_conns:      50\n\t\tmin_idle_conns: 5\n\t\tmax_lifetime:   2 * time.hour\n\t\tidle_timeout:   30 * time.minute\n\t\tget_timeout:    5 * time.second\n\t}\n\n\t// Create connection pool\n\tmut my_pool := pool.new_connection_pool(create_conn, config)!\n\tdefer {\n\t\t// When application exits\n\t\tmy_pool.close()\n\t}\n\n\t// Acquire connection\n\tmut conn := my_pool.get()!\n\tdefer {\n\t\t// Return connection to pool\n\t\tmy_pool.put(conn) or { println(err) }\n\t}\n\n\t// Convert `conn` to a `mysql.DB` object\n\tmut db := conn as mysql.DB\n\n\tassert db.validate()!\n\n\tmut response := db.exec('drop table if exists users')!\n\tassert response == []mysql.Row{}\n\n\tresponse = db.exec('create table if not exists users (\n                        id INT PRIMARY KEY AUTO_INCREMENT,\n                        username TEXT,\n\t\t\t\t\t\tlast_name TEXT NULL DEFAULT NULL\n                      )')!\n\tassert response == []mysql.Row{}\n\n\tmut result_code := db.exec_none('insert into users (username) values (\"jackson\")')\n\tassert result_code == 0\n\tresult_code = db.exec_none('insert into users (username) values (\"shannon\")')\n\tassert result_code == 0\n\tresult_code = db.exec_none('insert into users (username) values (\"bailey\")')\n\tassert result_code == 0\n\tresult_code = db.exec_none('insert into users (username) values (\"blaze\")')\n\tassert result_code == 0\n\trows := db.exec_param('insert into users (username) values (?)', 'Hi')!\n\tassert rows == []mysql.Row{}\n\n\t// Regression testing to ensure the query and exec return the same values\n\tres := db.query('select * from users')!\n\tresponse = res.rows()\n\tassert response[0].vals[1] == 'jackson'\n\tresponse = db.exec('select * from users')!\n\tassert response[0].vals[1] == 'jackson'\n\n\tresponse = db.exec('select * from users where id = 400')!\n\tassert response.len == 0\n\n\tsingle_row := db.exec_one('select * from users')!\n\tassert single_row.vals[1] == 'jackson'\n\n\tresponse = db.exec_param_many('select * from users where username = ?', [\n\t\t'jackson',\n\t])!\n\tassert response[0] == mysql.Row{\n\t\tvals: ['1', 'jackson', '']\n\t}\n\n\tresponse = db.exec_param_many('select * from users where username = ? and id = ?',\n\t\t['bailey', '3'])!\n\tassert response[0] == mysql.Row{\n\t\tvals: ['3', 'bailey', '']\n\t}\n\n\tresponse = db.exec_param_many('select * from users', [''])!\n\tassert response == [\n\t\tmysql.Row{\n\t\t\tvals: ['1', 'jackson', '']\n\t\t},\n\t\tmysql.Row{\n\t\t\tvals: ['2', 'shannon', '']\n\t\t},\n\t\tmysql.Row{\n\t\t\tvals: ['3', 'bailey', '']\n\t\t},\n\t\tmysql.Row{\n\t\t\tvals: ['4', 'blaze', '']\n\t\t},\n\t\tmysql.Row{\n\t\t\tvals: ['5', 'Hi', '']\n\t\t},\n\t]\n\n\tresponse = db.exec_param('select * from users where username = ?', 'blaze')!\n\tassert response[0] == mysql.Row{\n\t\tvals: ['4', 'blaze', '']\n\t}\n\n\t// transaction test\n\t// turn off `autocommit` first\n\tdb.autocommit(false)!\n\t// begin a new transaction\n\tdb.begin()!\n\tresult_code = db.exec_none('insert into users (username) values (\"tom\")')\n\tassert result_code == 0\n\t// make a savepoint\n\tdb.savepoint('savepoint1')!\n\tresult_code = db.exec_none('insert into users (username) values (\"kitty\")')\n\tassert result_code == 0\n\t// rollback to `savepoint1`\n\tdb.rollback_to('savepoint1')!\n\tresult_code = db.exec_none('insert into users (username) values (\"mars\")')\n\tassert result_code == 0\n\tdb.commit()!\n\tresponse = db.exec_param_many('select * from users', [''])!\n\tassert response == [\n\t\tmysql.Row{\n\t\t\tvals: ['1', 'jackson', '']\n\t\t},\n\t\tmysql.Row{\n\t\t\tvals: ['2', 'shannon', '']\n\t\t},\n\t\tmysql.Row{\n\t\t\tvals: ['3', 'bailey', '']\n\t\t},\n\t\tmysql.Row{\n\t\t\tvals: ['4', 'blaze', '']\n\t\t},\n\t\tmysql.Row{\n\t\t\tvals: ['5', 'Hi', '']\n\t\t},\n\t\tmysql.Row{\n\t\t\tvals: ['6', 'tom', '']\n\t\t},\n\t\tmysql.Row{\n\t\t\tvals: ['8', 'mars', '']\n\t\t},\n\t]\n}\n"
  },
  {
    "path": "examples/database/orm.v",
    "content": "// vtest build: !(macos || windows)\nimport os\nimport db.sqlite\nimport db.mysql\nimport db.pg\n\n// The goal of this example, is to show how you can connect to\n// several different databases in the same program, and use both\n// the ORM and the native connection wrapper, that each DB driver\n// provides, if you need to execute more complex SQL queries.\n//\n// You can use environment variables to pass your local DB connection\n// settings, without editing the code, like this:\n//\n//    MUSER='myuser' MPASS='abc' MDATABASE='vtestdb'  PGUSER='postgres' PGPASS='password' PGDATABASE='postgres'  ./v -g run examples/database/orm.v\n//\n// WARNING: this example will drop and re-create any tables named:\n//   * modules\n//   * User\n//   * Parent\n//   * Child\n// in the passed databases, so it is better to use empty DBs for it.\n\nconst mysql_host = os.getenv_opt('MHOST') or { 'localhost' }\nconst mysql_port = os.getenv_opt('MPORT') or { '3306' }.u32()\nconst mysql_user = os.getenv_opt('MUSER') or { 'myuser' }\nconst mysql_pass = os.getenv_opt('MPASS') or { 'abc' }\nconst mysql_db = os.getenv_opt('MDATABASE') or { 'test' }\n\nconst pg_host = os.getenv_opt('PGHOST') or { 'localhost' }\nconst pg_user = os.getenv_opt('PGUSER') or { 'test' }\nconst pg_pass = os.getenv_opt('PGPASS') or { 'abc' }\nconst pg_db = os.getenv_opt('PGDATABASE') or { 'test' }\n\n@[table: 'modules']\nstruct Module {\n\tid           int @[primary; sql: serial]\n\tname         string\n\tnr_downloads int @[sql: u64]\n\tcreator      User\n}\n\nstruct User {\n\tid             int    @[primary; sql: serial]\n\tage            u32    @[unique: 'user']\n\tname           string @[sql: 'username'; sql_type: 'VARCHAR(200)'; unique]\n\tis_customer    bool   @[sql: 'abc'; unique: 'user']\n\tskipped_string string @[skip]\n}\n\nstruct Parent {\n\tid       int @[primary; sql: serial]\n\tname     string\n\tchildren []Child @[fkey: 'parent_id']\n}\n\nstruct Child {\n\tid        int @[primary; sql: serial]\n\tparent_id int\n\tname      string\n}\n\nfn sqlite3_array() ! {\n\teprintln('------------ ${@METHOD} -----------------')\n\tmut db := sqlite.connect(':memory:')!\n\tdefer {\n\t\tsql db {\n\t\t\tdrop table Parent\n\t\t\tdrop table Child\n\t\t} or {}\n\t\tdb.close() or {}\n\t}\n\n\tsql db {\n\t\tcreate table Parent\n\t}!\n\tsql db {\n\t\tcreate table Child\n\t}!\n\tpar := Parent{\n\t\tname:     'test'\n\t\tchildren: [\n\t\t\tChild{\n\t\t\t\tname: 'abc'\n\t\t\t},\n\t\t\tChild{\n\t\t\t\tname: 'def'\n\t\t\t},\n\t\t]\n\t}\n\tsql db {\n\t\tinsert par into Parent\n\t}!\n\tparent := sql db {\n\t\tselect from Parent where id == 1\n\t}!\n\teprintln(parent)\n}\n\nfn msql_array() ! {\n\teprintln('------------ ${@METHOD} -----------------')\n\tmut db := mysql.connect(\n\t\thost:     mysql_host\n\t\tport:     mysql_port\n\t\tusername: mysql_user\n\t\tpassword: mysql_pass\n\t\tdbname:   mysql_db\n\t)!\n\tdefer {\n\t\tsql db {\n\t\t\tdrop table Parent\n\t\t} or {}\n\t\tdb.close() or {}\n\t}\n\n\tdb.query('drop table if exists Parent')!\n\tdb.query('drop table if exists Child')!\n\tsql db {\n\t\tcreate table Parent\n\t\tcreate table Child\n\t}!\n\tpar := Parent{\n\t\tname:     'test'\n\t\tchildren: [\n\t\t\tChild{\n\t\t\t\tname: 'abc'\n\t\t\t},\n\t\t\tChild{\n\t\t\t\tname: 'def'\n\t\t\t},\n\t\t]\n\t}\n\tsql db {\n\t\tinsert par into Parent\n\t}!\n\tparent := sql db {\n\t\tselect from Parent where id == 1\n\t}!\n\teprintln(parent)\n}\n\nfn psql_array() ! {\n\teprintln('------------ ${@METHOD} -----------------')\n\tmut db := pg.connect(host: pg_host, user: pg_user, password: pg_pass, dbname: pg_db)!\n\tdefer {\n\t\tdb.exec_one('drop table if exists \"Parent\", \"Child\"') or { eprintln(err) }\n\t\tdb.close() or {}\n\t}\n\tdb.exec_one('drop table if exists \"Parent\", \"Child\"') or { eprintln(err) }\n\n\tsql db {\n\t\tcreate table Parent\n\t\tcreate table Child\n\t}!\n\tpar := Parent{\n\t\tname:     'test'\n\t\tchildren: [\n\t\t\tChild{\n\t\t\t\tname: 'abc'\n\t\t\t},\n\t\t\tChild{\n\t\t\t\tname: 'def'\n\t\t\t},\n\t\t]\n\t}\n\tsql db {\n\t\tinsert par into Parent\n\t}!\n\tparent := sql db {\n\t\tselect from Parent where id == 1\n\t}!\n\teprintln(parent)\n}\n\nfn sqlite3() ! {\n\teprintln('------------ ${@METHOD} -----------------')\n\tmut db := sqlite.connect(':memory:')!\n\tdefer {\n\t\tsql db {\n\t\t\tdrop table Module\n\t\t\tdrop table User\n\t\t} or {}\n\t\tdb.close() or {}\n\t}\n\n\tsql db {\n\t\tcreate table Module\n\t}!\n\tsql db {\n\t\tcreate table User\n\t}!\n\tmod := Module{\n\t\tname:         'test'\n\t\tnr_downloads: 10\n\t\tcreator:      User{\n\t\t\tage:         21\n\t\t\tname:        'VUser'\n\t\t\tis_customer: true\n\t\t}\n\t}\n\tsql db {\n\t\tinsert mod into Module\n\t}!\n\tmodul := sql db {\n\t\tselect from Module where id == 1\n\t}!\n\teprintln(modul)\n}\n\nfn msql() ! {\n\teprintln('------------ ${@METHOD} -----------------')\n\tmut conn := mysql.connect(\n\t\thost:     mysql_host\n\t\tport:     mysql_port\n\t\tusername: mysql_user\n\t\tpassword: mysql_pass\n\t\tdbname:   mysql_db\n\t)!\n\tdefer {\n\t\tconn.query('DROP TABLE IF EXISTS Module') or { eprintln(err) }\n\t\tconn.query('DROP TABLE IF EXISTS User') or { eprintln(err) }\n\t\tconn.close() or {}\n\t}\n\tconn.query('DROP TABLE IF EXISTS Module') or { eprintln(err) }\n\tconn.query('DROP TABLE IF EXISTS User') or { eprintln(err) }\n\n\tsql conn {\n\t\tcreate table Module\n\t}!\n\tsql conn {\n\t\tcreate table User\n\t}!\n\tmod := Module{\n\t\tname:         'test'\n\t\tnr_downloads: 10\n\t\tcreator:      User{\n\t\t\tage:         21\n\t\t\tname:        'VUser'\n\t\t\tis_customer: true\n\t\t}\n\t}\n\tsql conn {\n\t\tinsert mod into Module\n\t}!\n\tm := sql conn {\n\t\tselect from Module where id == 1\n\t}!\n\teprintln(m)\n}\n\nfn psql() ! {\n\teprintln('------------ ${@METHOD} -----------------')\n\tmut db := pg.connect(host: pg_host, user: pg_user, password: pg_pass, dbname: pg_db)!\n\tdefer {\n\t\tdb.exec_one('drop table if exists \"modules\", \"User\"') or { eprintln(err) }\n\t\tdb.close() or {}\n\t}\n\tdb.exec_one('drop table if exists \"modules\", \"User\"') or { eprintln(err) }\n\tsql db {\n\t\tcreate table Module\n\t\tcreate table User\n\t}!\n\tmod := Module{\n\t\tname:         'test'\n\t\tnr_downloads: 10\n\t\tcreator:      User{\n\t\t\tage:         21\n\t\t\tname:        'VUser'\n\t\t\tis_customer: true\n\t\t}\n\t}\n\tsql db {\n\t\tinsert mod into Module\n\t}!\n\tmodul := sql db {\n\t\tselect from Module where id == 1\n\t}!\n\tsql db {\n\t\tdrop table Module\n\t}!\n\teprintln(modul)\n}\n\nfn main() {\n\teprintln('------------ ${@METHOD} -----------------')\n\tsqlite3_array()!\n\tmsql_array()!\n\tpsql_array()!\n\n\tsqlite3()!\n\tmsql()!\n\tpsql()!\n}\n"
  },
  {
    "path": "examples/database/psql/.gitignore",
    "content": "customer\n"
  },
  {
    "path": "examples/database/psql/customer.v",
    "content": "// vtest build: linux\nmodule main\n\nimport db.pg\n\nstruct Customer {\n\tid        int\n\tname      string\n\tnr_orders int\n\tcountry   string\n}\n\nconst dash = '----------------------------------------------------------------'\n\nfn main() {\n\tdb := pg.connect(\n\t\thost:   'localhost' // or '127.0.0.1'\n\t\tuser:   'postgres'\n\t\tdbname: 'customerdb'\n\t) or {\n\t\teprintln('failed to connect, error: ${err}')\n\t\treturn\n\t}\n\n\tnr_customers := sql db {\n\t\tselect count from Customer\n\t}!\n\tprintln('Total customers: ${nr_customers}')\n\n\tprintln(dash)\n\tbg_country := 'Bulgaria'\n\t// V syntax can be used to build queries\n\tbg_customers := sql db {\n\t\tselect from Customer where country == bg_country && id != 2\n\t}!\n\tfor customer in bg_customers {\n\t\tprintln('${customer.country} | ${customer.id} - ${customer.name}')\n\t}\n\n\tprintln(dash)\n\tru_customers := sql db {\n\t\tselect from Customer where country == 'Russia'\n\t}!\n\tfor customer in ru_customers {\n\t\tprintln('${customer.country} | ${customer.id} - ${customer.name}')\n\t}\n\n\t// by adding `limit 1` we tell V that there will be only one object\n\tprintln(dash)\n\texisting := sql db {\n\t\tselect from Customer where id == 1 limit 1\n\t}!\n\tprintln('Existing customer name: ${existing}[0].name')\n\tprintln('Existing customer full information:')\n\tprintln(existing)\n\n\tprintln(dash)\n\tq := Customer{}\n\t// It's easy to handle queries that don't return any data\n\t_ := sql db {\n\t\tselect from Customer where id == 12345 && name == q.name && nr_orders > q.nr_orders limit 1\n\t}!\n\t// Insert a new customer\n\tnc := Customer{\n\t\tname:      'John Doe'\n\t\tnr_orders: 10\n\t}\n\tsql db {\n\t\tinsert nc into Customer\n\t}!\n}\n"
  },
  {
    "path": "examples/database/psql/mydb.sql",
    "content": "--\n-- PostgreSQL database dump\n--\n\n-- Dumped from database version 9.5.19\n-- Dumped by pg_dump version 9.5.19\n\nSET statement_timeout = 0;\nSET lock_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSELECT pg_catalog.set_config('search_path', '', false);\nSET check_function_bodies = false;\nSET xmloption = content;\nSET client_min_messages = warning;\nSET row_security = off;\n\n--\n-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: \n--\n\nCREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;\n\n\n--\n-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: \n--\n\nCOMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';\n\n\nSET default_tablespace = '';\n\nSET default_with_oids = false;\n\n--\n-- Name: customers; Type: TABLE; Schema: public; Owner: myuser\n--\n\nCREATE TABLE public.customers (\n    id integer NOT NULL,\n    name text DEFAULT ''::text,\n    nr_orders integer DEFAULT 0,\n    country text DEFAULT 'England'::text,\n    created_at timestamp without time zone DEFAULT now()\n);\n\n\nALTER TABLE public.customers OWNER TO myuser;\n\n--\n-- Name: customers_id_seq; Type: SEQUENCE; Schema: public; Owner: myuser\n--\n\nCREATE SEQUENCE public.customers_id_seq\n    START WITH 1\n    INCREMENT BY 1\n    NO MINVALUE\n    NO MAXVALUE\n    CACHE 1;\n\n\nALTER TABLE public.customers_id_seq OWNER TO myuser;\n\n--\n-- Name: customers_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: myuser\n--\n\nALTER SEQUENCE public.customers_id_seq OWNED BY public.customers.id;\n\n\n--\n-- Name: id; Type: DEFAULT; Schema: public; Owner: myuser\n--\n\nALTER TABLE ONLY public.customers ALTER COLUMN id SET DEFAULT nextval('public.customers_id_seq'::regclass);\n\n\n--\n-- Data for Name: customers; Type: TABLE DATA; Schema: public; Owner: myuser\n--\n\nCOPY public.customers (id, name, nr_orders, country, created_at) FROM stdin;\n2\tPippi Långstrump\t3\tBulgaria\t2019-08-19 09:41:30.78888\n1\tBilbo Begins\t11\tBulgaria\t2019-08-19 09:40:31.396807\n3\tViktualia Rullgardina\t0\tBulgaria\t2019-08-19 09:42:52.723223\n4\tKrusmynta Efraimsdotter\t5\tBulgaria\t2019-08-19 09:43:04.083209\n5\tAna Karenina\t0\tRussia\t2019-08-20 15:41:50.244971\n7\tJiji Lolobridgida\t0\tItaly\t2019-08-20 15:42:26.020113\n6\tViktor Savashkin\t8\tRussia\t2019-08-20 15:42:07.213557\n\\.\n\n\n--\n-- Name: customers_id_seq; Type: SEQUENCE SET; Schema: public; Owner: myuser\n--\n\nSELECT pg_catalog.setval('public.customers_id_seq', 1, true);\n\n\n--\n-- Name: customers_pkey; Type: CONSTRAINT; Schema: public; Owner: myuser\n--\n\nALTER TABLE ONLY public.customers\n    ADD CONSTRAINT customers_pkey PRIMARY KEY (id);\n\n\n--\n-- Name: SCHEMA public; Type: ACL; Schema: -; Owner: postgres\n--\n\nREVOKE ALL ON SCHEMA public FROM PUBLIC;\nREVOKE ALL ON SCHEMA public FROM postgres;\nGRANT ALL ON SCHEMA public TO postgres;\nGRANT ALL ON SCHEMA public TO PUBLIC;\n\n\n--\n-- PostgreSQL database dump complete\n--\n\n"
  },
  {
    "path": "examples/database/sqlite.v",
    "content": "import db.sqlite\n\nfn main() {\n\tdb := sqlite.connect(':memory:')!\n\tdb.exec(\"create table users (id integer primary key, name text default '');\") or { panic(err) }\n\n\tdb.exec(\"insert into users (name) values ('Sam')\")!\n\tdb.exec(\"insert into users (name) values ('Peter')\")!\n\tdb.exec(\"insert into users (name) values ('Kate')\")!\n\n\tnr_users := db.q_int('select count(*) from users')!\n\tprintln('nr users = ${nr_users}')\n\n\tname := db.q_string('select name from users where id = 1')!\n\tassert name == 'Sam'\n\n\tusers := db.exec('select * from users')!\n\tfor row in users {\n\t\tprintln(row.vals)\n\t}\n}\n"
  },
  {
    "path": "examples/diff.v",
    "content": "module main\n\nimport arrays.diff\nimport os\n\n// diff_files generate diff for two files.\nfn diff_files(src_file string, dst_file string) !string {\n\tsrc := os.read_lines(src_file)!\n\tdst := os.read_lines(dst_file)!\n\n\tmut ctx := diff.diff(src, dst)\n\treturn ctx.generate_patch(colorful: true, block_header: true)\n}\n\nfn main() {\n\tf1 := \"Module{\n\tname: 'Foo'\n\tdescription: 'Awesome V module.'\n\tversion: '0.0.0'\n\tdependencies: []\n}\n\"\n\tf2 := \"Module{\n\tname: 'foo'\n\tdescription: 'Awesome V module.'\n\tversion: '0.1.0'\n\tlicense: 'MIT'\n\tdependencies: []\n}\n\"\n\tp1 := 'diff_f1.txt'\n\tp2 := 'diff_f2.txt'\n\tos.write_file(p1, f1)!\n\tos.write_file(p2, f2)!\n\n\tstr := diff_files(p1, p2)!\n\tprintln(str)\n\n\tos.rm(p1)!\n\tos.rm(p2)!\n}\n"
  },
  {
    "path": "examples/dump_factorial.v",
    "content": "fn factorial(n u32) u32 {\n\tif dump(n <= 1) {\n\t\treturn dump(1)\n\t}\n\treturn dump(n * factorial(n - 1))\n}\n\nfn main() {\n\tprintln(factorial(5))\n}\n"
  },
  {
    "path": "examples/dynamic_library_loader/modules/library/library.v",
    "content": "module library\n\n// add_1 is exported with the C name `add_1`.\n// It can be called by external programs, when the module is compiled\n// as a shared library.\n// It is exported, because the function is declared as public with `pub`.\n// The exported C name is `add_1`, because of the export: tag.\n// (Normally, the exported name is a V mangled version based on the module\n// name followed by __, followed by the fn name, i.e. it would have been\n// `library__add_1`, if not for the export: tag).\n@[export: 'add_1']\npub fn add_1(x int, y int) int {\n\tnum := my_private_function(x + y)\n\tprintln('hello from ${@FN} , num = ${num}')\n\treturn num\n}\n\n// this function is not exported and will not be visible to external programs.\nfn my_private_function(x int) int {\n\treturn 1 + x\n}\n"
  },
  {
    "path": "examples/dynamic_library_loader/use_shared_library.v",
    "content": "module main\n\n// Note: This program, requires that the shared library was already compiled.\n// To do so, run `v -d no_backtrace -o library -shared modules/library/library.v`\n// before running this program.\nimport os\nimport dl\nimport dl.loader\n\ntype FNAdder = fn (int, int) int\n\nconst cfolder = os.dir(@FILE)\nconst default_paths = [\n\tos.join_path(cfolder, 'library${dl.dl_ext}'),\n\tos.join_path(cfolder, 'location1/library${dl.dl_ext}'),\n\tos.join_path(cfolder, 'location2/library${dl.dl_ext}'),\n\tos.join_path(cfolder, 'modules/library/library${dl.dl_ext}'),\n]\n\nfn main() {\n\tmut dl_loader := loader.get_or_create_dynamic_lib_loader(\n\t\tkey:   cfolder + '/library'\n\t\tpaths: default_paths\n\t)!\n\tdefer {\n\t\tdl_loader.unregister()\n\t}\n\tsym := dl_loader.get_sym('add_1')!\n\tf := FNAdder(sym)\n\teprintln('f: ${ptr_str(f)}')\n\tres := f(1, 2)\n\teprintln('res: ${res}')\n}\n"
  },
  {
    "path": "examples/dynamic_library_loader/use_test.v",
    "content": "module main\n\nimport os\nimport dl\n\nconst vexe = os.real_path(os.getenv('VEXE'))\nconst so_ext = dl.dl_ext\n\nfn test_vexe() {\n\t// dump(vexe)\n\tassert vexe != ''\n\t// dump(os.executable())\n\t// dump(@FILE)\n\t// dump(cfolder)\n\t// dump(so_ext)\n}\n\nfn test_can_compile_library() {\n\tos.chdir(cfolder) or {}\n\tlibrary_file_path := os.join_path(cfolder, dl.get_libname('library'))\n\tos.rm(library_file_path) or {}\n\tv_compile('-d no_backtrace -o library -shared modules/library/library.v')\n\tassert os.is_file(library_file_path)\n}\n\nfn test_can_compile_main_program() {\n\tos.chdir(cfolder) or {}\n\tlibrary_file_path := os.join_path(cfolder, dl.get_libname('library'))\n\tassert os.is_file(library_file_path)\n\tresult := v_compile('run use_shared_library.v')\n\t// dump(result)\n\tassert result.output.contains('hello from add_1 , num = 4')\n\tassert result.output.contains('res: 4')\n\tos.rm(library_file_path) or {}\n}\n\nfn test_can_compile_and_use_library_with_skip_unused_home_dir() {\n\tos.chdir(cfolder) or {}\n\tlibrary_file_path := os.join_path(cfolder, dl.get_libname('library'))\n\tos.rm(library_file_path) or {}\n\tv_compile('-skip-unused -d no_backtrace -o library -shared modules/library/library.v')\n\tassert os.is_file(library_file_path)\n\tresult := v_compile('run use_shared_library.v')\n\tassert result.output.contains('res: 4')\n\tos.rm(library_file_path) or {}\n}\n\nfn test_can_compile_and_use_library_with_skip_unused_location1_dir() {\n\tos.chdir(cfolder) or {}\n\tlibrary_file_path := os.join_path(cfolder, 'location1', dl.get_libname('library'))\n\tos.rm(library_file_path) or {}\n\tos.mkdir('location1') or {}\n\tv_compile('-skip-unused -d no_backtrace -o location1/library -shared modules/library/library.v')\n\tassert os.is_file(library_file_path)\n\tresult := v_compile('run use_shared_library.v')\n\tassert result.output.contains('res: 4')\n\tos.rm(library_file_path) or {}\n}\n\nfn v_compile(vopts string) os.Result {\n\tcmd := '${os.quoted_path(vexe)} -showcc ${vopts}'\n\t// dump(cmd)\n\tres := os.execute_or_exit(cmd)\n\t// dump(res)\n\tassert res.exit_code == 0\n\treturn res\n}\n"
  },
  {
    "path": "examples/dynamic_library_loading/modules/library/library.v",
    "content": "module library\n\n// add_1 is exported with the C name `add_1`.\n// It can be called by external programs, when the module is compiled\n// as a shared library.\n// It is exported, because the function is declared as public with `pub`.\n// The exported C name is `add_1`, because of the export: tag.\n// (Normally, the exported name is a V mangled version based on the module\n// name followed by __, followed by the fn name, i.e. it would have been\n// `library__add_1`, if not for the export: tag).\n@[export: 'add_1']\npub fn add_1(x int, y int) int {\n\treturn my_private_function(x + y)\n}\n\n// this function is not exported and will not be visible to external programs.\nfn my_private_function(x int) int {\n\treturn 1 + x\n}\n"
  },
  {
    "path": "examples/dynamic_library_loading/use_dl_module.v",
    "content": "module main\n\n// Note: This program, requires that the shared library was already compiled.\n// To do so, run `v -d no_backtrace -o library -shared modules/library/library.v`\n// before running this program.\nimport os\nimport dl\n\ntype FNAdder = fn (int, int) int\n\nfn main() {\n\tlibrary_file_path := os.join_path(os.dir(@FILE), dl.get_libname('library'))\n\thandle := dl.open_opt(library_file_path, dl.rtld_lazy)!\n\teprintln('handle: ${ptr_str(handle)}')\n\tf := FNAdder(dl.sym_opt(handle, 'add_1')!)\n\teprintln('f: ${ptr_str(f)}')\n\tres := f(1, 2)\n\teprintln('res: ${res}')\n}\n"
  },
  {
    "path": "examples/dynamic_library_loading/use_library_test.v",
    "content": "module main\n\n// vtest retry: 3\nimport os\nimport dl\n\nconst vexe = os.real_path(os.getenv('VEXE'))\nconst cfolder = os.dir(@FILE)\nconst so_ext = dl.dl_ext\nconst library_file_name = os.join_path(cfolder, dl.get_libname('library'))\n\nfn test_vexe() {\n\t// dump(vexe)\n\tassert vexe != ''\n\t// dump(os.executable())\n\t// dump(@FILE)\n\t// dump(cfolder)\n\t// dump(so_ext)\n\t// dump(library_file_name)\n}\n\nfn test_can_compile_library() {\n\tos.chdir(cfolder) or {}\n\tos.rm(library_file_name) or {}\n\tv_compile('-d no_backtrace -o library -shared modules/library/library.v')\n\tassert os.is_file(library_file_name)\n}\n\nfn test_can_compile_main_program() {\n\tos.chdir(cfolder) or {}\n\tassert os.is_file(library_file_name)\n\tresult := v_compile('run use_dl_module.v')\n\t// dump(result)\n\tassert result.output.contains('res: 4')\n\tos.rm(library_file_name) or {}\n}\n\nfn test_can_compile_and_use_library_with_skip_unused() {\n\tos.chdir(cfolder) or {}\n\tos.rm(library_file_name) or {}\n\tv_compile('-skip-unused -d no_backtrace -o library -shared modules/library/library.v')\n\tassert os.is_file(library_file_name)\n\tresult := v_compile('run use_dl_module.v')\n\tassert result.output.contains('res: 4')\n\tos.rm(library_file_name) or {}\n}\n\nfn test_can_compile_and_use_library_with_prod() {\n\tos.chdir(cfolder) or {}\n\tos.rm(library_file_name) or {}\n\tv_compile('-prod -d no_backtrace -o library -shared modules/library/library.v')\n\tassert os.is_file(library_file_name)\n\tresult := v_compile('run use_dl_module.v')\n\tassert result.output.contains('res: 4')\n\tos.rm(library_file_name) or {}\n}\n\nfn v_compile(vopts string) os.Result {\n\tcmd := '${os.quoted_path(vexe)} -showcc ${vopts}'\n\t// dump(cmd)\n\tres := os.execute_or_exit(cmd)\n\t// dump(res)\n\tassert res.exit_code == 0\n\treturn res\n}\n"
  },
  {
    "path": "examples/errors.v",
    "content": "import semver\n\nfn main() {\n\tsemver.from('asd') or { check_error(err) }\n\tsemver.from('') or { check_error(err) }\n}\n\nfn check_error(err IError) {\n\tmatch err {\n\t\tsemver.InvalidVersionFormatError {\n\t\t\tprintln('wrong format')\n\t\t}\n\t\tsemver.EmptyInputError {\n\t\t\tprintln('empty input')\n\t\t}\n\t\telse {\n\t\t\tprintln('unknown error')\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/euler.v",
    "content": "// This example shows 2 solutions for https://projecteuler.net/problem=1 :\nfn gauss_sum(n int) fn (int) int {\n\treturn fn [n] (m int) int {\n\t\treturn m * ((n - 1) / m) * ((n - 1) / m + 1) / 2\n\t}\n}\n\ngs := gauss_sum(1000)\nprintln('O(1) arithmetic progression sum: ${gs(3) + gs(5) - gs(15)}')\n\n// A brute force solution, by checking every n in the range:\nmut sum := 0\nfor n in 1 .. 1000 {\n\tif n % 3 == 0 || n % 5 == 0 {\n\t\tsum += n\n\t}\n}\nprintln('O(n) brute force calculated sum: ${sum}')\n"
  },
  {
    "path": "examples/eventbus/eventbus.v",
    "content": "module main\n\nimport some_module\n\nstruct Receiver {\nmut:\n\tok bool\n}\n\nfn main() {\n\tmut sub := some_module.get_subscriber()\n\tr := Receiver{}\n\tsub.subscribe_method('event_foo', on_foo, r)\n\tsub.subscribe('event_bar', on_bar)\n\tsub.subscribe('event_baz', on_baz)\n\n\tprintln('Receiver ok: ' + r.ok.str())\n\tsome_module.do_work()\n\tprintln('Receiver ok: ' + r.ok.str())\n}\n\nfn on_foo(mut receiver Receiver, e &some_module.EventMetadata, _sender voidptr) {\n\treceiver.ok = true\n\tprintln('on_foo :: ' + e.message)\n}\n\nfn on_bar(_receiver voidptr, e &some_module.EventMetadata, _sender voidptr) {\n\tprintln('on_bar :: ' + e.message)\n}\n\nfn on_baz(_receiver voidptr, _event voidptr, d &some_module.Duration) {\n\tprintln('on_baz :: ' + d.hours.str())\n}\n"
  },
  {
    "path": "examples/eventbus/modules/some_module/some_module.v",
    "content": "module some_module\n\nimport eventbus\n\nconst eb = eventbus.new[string]()\n\npub struct Duration {\npub:\n\thours int\n}\n\npub struct EventMetadata {\npub:\n\tmessage string\n}\n\npub fn do_work() {\n\tduration := Duration{10}\n\tfor i in 0 .. 10 {\n\t\tprintln('working...')\n\t\tif i == 5 {\n\t\t\tevent_metadata := &EventMetadata{'Iteration ' + i.str()}\n\t\t\teb.publish('event_foo', duration, event_metadata)\n\t\t\teb.publish('event_bar', duration, event_metadata)\n\t\t}\n\t}\n\teb.publish('event_baz', &Duration{42}, &EventMetadata{'Additional data at the end.'})\n}\n\npub fn get_subscriber() eventbus.Subscriber[string] {\n\treturn *eb.subscriber\n}\n"
  },
  {
    "path": "examples/fasthttp/README.md",
    "content": "# Fasthttp Example\n\nA simple HTTP server example using the `fasthttp` module from `vlib/fasthttp`.\n\n## Features\n\n- Handles GET and POST requests\n- Routes requests to different controllers based on HTTP method and path\n- Returns appropriate HTTP responses with status codes and content\n\n## Building\n\n```sh\n./v examples/fasthttp\n```\n\n## Running\n\n```sh\n./examples/fasthttp/fasthttp\n```\n\nThe server will listen on `http://localhost:3000`\n\n## Testing\n\n### Home endpoint\n\n```sh\ncurl http://localhost:3000/\n```\n\n### Get user by ID\n\n```sh\ncurl http://localhost:3000/user/123\n```\n\n### Create user\n\n```sh\ncurl -X POST http://localhost:3000/user\n```\n\n### 404 response\n\n```sh\ncurl http://localhost:3000/notfound\n```\n\n## File Structure\n\n- `main.v` - Entry point and request router\n- `controllers.v` - Request handlers for different routes\n- `v.mod` - Module metadata\n\n## Architecture\n\nThe example demonstrates:\n\n1. **Request Routing**: The `handle_request()` function routes incoming HTTP requests based on\n   method and path\n2. **Response Handling**: Controllers return HTTP responses with proper headers and status codes\n3. **Content Type**: All responses are returned as `[]u8` (byte arrays)\n\nThe fasthttp module handles:\n\n- Low-level socket management\n- Request parsing\n- Connection handling\n- Non-blocking I/O with epoll (Linux) or kqueue (macOS)\n"
  },
  {
    "path": "examples/fasthttp/controllers.v",
    "content": "module main\n\nfn home_controller() ![]u8 {\n\tresponse := 'HTTP/1.1 200 OK\\r\\nContent-Type: text/plain\\r\\nContent-Length: 13\\r\\n\\r\\nHello, World!'\n\treturn response.bytes()\n}\n\nfn get_user_controller(id string) ![]u8 {\n\tbody := 'User ID: ${id}'\n\tcontent_length := body.len\n\tresponse := 'HTTP/1.1 200 OK\\r\\nContent-Type: text/plain\\r\\nContent-Length: ${content_length}\\r\\n\\r\\n${body}'\n\treturn response.bytes()\n}\n\nfn create_user_controller() ![]u8 {\n\tbody := 'User created successfully'\n\tcontent_length := body.len\n\tresponse := 'HTTP/1.1 201 Created\\r\\nContent-Type: text/plain\\r\\nContent-Length: ${content_length}\\r\\n\\r\\n${body}'\n\treturn response.bytes()\n}\n\nfn not_found_response() ![]u8 {\n\tbody := '404 Not Found'\n\tcontent_length := body.len\n\tresponse := 'HTTP/1.1 404 Not Found\\r\\nContent-Type: text/plain\\r\\nContent-Length: ${content_length}\\r\\n\\r\\n${body}'\n\treturn response.bytes()\n}\n"
  },
  {
    "path": "examples/fasthttp/main.v",
    "content": "module main\n\nimport fasthttp\n\nfn handle_request(req fasthttp.HttpRequest) !fasthttp.HttpResponse {\n\tmethod := req.buffer[req.method.start..req.method.start + req.method.len].bytestr()\n\tpath := req.buffer[req.path.start..req.path.start + req.path.len].bytestr()\n\n\tif method == 'GET' {\n\t\tif path == '/' {\n\t\t\treturn fasthttp.HttpResponse{\n\t\t\t\tcontent: home_controller()!\n\t\t\t}\n\t\t} else if path.starts_with('/user/') {\n\t\t\tid := path[6..]\n\t\t\treturn fasthttp.HttpResponse{\n\t\t\t\tcontent: get_user_controller(id)!\n\t\t\t}\n\t\t}\n\t} else if method == 'POST' {\n\t\tif path == '/user' {\n\t\t\treturn fasthttp.HttpResponse{\n\t\t\t\tcontent: create_user_controller()!\n\t\t\t}\n\t\t}\n\t}\n\n\treturn fasthttp.HttpResponse{\n\t\tcontent: not_found_response()!\n\t}\n}\n\nfn main() {\n\tmut server := fasthttp.new_server(fasthttp.ServerConfig{\n\t\tport:    3000\n\t\thandler: handle_request\n\t}) or {\n\t\teprintln('Failed to create server: ${err}')\n\t\treturn\n\t}\n\n\tprintln('Starting fasthttp server on port http://localhost:3000...')\n\n\tserver.run() or { eprintln('error: ${err}') }\n}\n"
  },
  {
    "path": "examples/fasthttp/v.mod",
    "content": "Module {\n\tname: 'fasthttp_example'\n\tdescription: 'A simple HTTP server example using the fasthttp module'\n\tversion: '0.0.1'\n\tlicense: 'MIT'\n}\n"
  },
  {
    "path": "examples/fetch.v",
    "content": "import time\nimport net.http\n\nfn main() {\n\tresp := http.get('https://vlang.io/utc_now') or {\n\t\teprintln('Failed to fetch data from the server. Error: ${err}')\n\t\treturn\n\t}\n\n\tt := time.unix(resp.body.int())\n\tprintln(t.format())\n}\n"
  },
  {
    "path": "examples/fetch_ip.v",
    "content": "import json\nimport net.http\n\nstruct IpInfo {\n\tip          string\n\tip_decimal  int\n\tcountry     string\n\tcountry_iso string\n\tcountry_eu  bool\n\tregion_name string\n\tregion_code string\n\tzip_code    string\n\tcity        string\n\tlatitude    f64\n\tlongitude   f64\n\ttime_zone   string\n\tasn         string\n\tasn_org     string\n\tuser_agent  UserAgent\n}\n\nstruct UserAgent {\n\tproduct   string\n\tversion   string\n\tcomment   string\n\traw_value string\n}\n\nurl := 'http://ifconfig.co/json'\nresp := http.fetch(\n\turl:        url\n\tuser_agent: 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/117.0'\n) or {\n\teprintln('failed to fetch data from the server, error: ${err}')\n\texit(1)\n}\nip_info := json.decode(IpInfo, resp.body) or {\n\tprintln('failed to decode the json data returned by the server, error: ${err}')\n\texit(2)\n}\nprintln(ip_info)\n"
  },
  {
    "path": "examples/fibonacci.v",
    "content": "// This program displays the fibonacci sequence\nconst args = arguments()\n\nfn main() {\n\t// Check for user input\n\tif args.len != 2 {\n\t\tprintln('usage: fibonacci [rank]')\n\t\treturn\n\t}\n\t// Parse first argument and cast it to int\n\tstop := args[1].int()\n\t// Can only calculate correctly until rank 92\n\tif stop > 92 {\n\t\tprintln('rank must be 92 or less')\n\t\treturn\n\t}\n\t// Three consecutive terms of the sequence\n\tmut a := i64(0)\n\tmut b := i64(0)\n\tmut c := i64(1)\n\tprintln(a + b + c)\n\tfor _ in 0 .. stop {\n\t\t// Set a and b to the next term\n\t\ta = b\n\t\tb = c\n\t\t// Compute the new term\n\t\tc = a + b\n\t\t// Print the new term\n\t\tprintln(c)\n\t}\n}\n"
  },
  {
    "path": "examples/file_list.v",
    "content": "import os\n\nfn main() {\n\tfiles := os.ls('.') or {\n\t\tprintln(err)\n\t\treturn\n\t}\n\tmut f := os.create('file_list.txt') or {\n\t\tprintln(err)\n\t\treturn\n\t}\n\tfor file in files {\n\t\tif os.is_file(file) {\n\t\t\tf.write_string(file + '\\r\\n') or { println(err) }\n\t\t}\n\t}\n\tf.close()\n}\n"
  },
  {
    "path": "examples/fireworks/fireworks.v",
    "content": "import objects\nimport gg\nimport rand\n\nstruct App {\nmut:\n\tgg      &gg.Context       = unsafe { nil }\n\tui      &objects.UIParams = unsafe { nil }\n\trockets []objects.Rocket\n\tframes  [][]objects.Rocket\n\t// i thought about using a fixed fifo queue for the frames but the array\n\t// seemed to work fine, if you'd like a challenge try implementing it with the queue :)\n\tdraw_flag bool = true\n}\n\nfn on_frame(mut app App) {\n\tif !app.draw_flag {\n\t\treturn\n\t}\n\tapp.gg.begin()\n\n\t// drawing previous frames\n\tfor mut frame in app.frames {\n\t\tfor mut rocket in frame {\n\t\t\tif !rocket.exploded {\n\t\t\t\trocket.color.a = u8(f32_max(rocket.color.a - 8, 0))\n\t\t\t\trocket.draw(mut app.gg)\n\t\t\t}\n\t\t}\n\t}\n\n\t// chance of firing new rocket\n\tif rand.intn(30) or { 0 } == 0 {\n\t\tapp.rockets << objects.new_rocket()\n\t}\n\t// simulating rockets\n\tapp.rockets = app.rockets.filter(!it.dead)\n\n\tfor mut rocket in app.rockets {\n\t\trocket.tick(mut app.gg)\n\t}\n\n\t// adding frame\n\tmut frame := app.rockets.clone()\n\n\tfor mut rocket in frame {\n\t\trocket.particles = []\n\t}\n\n\tapp.frames << frame\n\n\t// trimming out frames\n\tif app.frames.len > 30 {\n\t\tapp.frames.delete(0)\n\t}\n\n\tapp.gg.end()\n}\n\nfn on_event(e &gg.Event, mut app App) {\n\tmatch e.typ {\n\t\t.resized, .resumed {\n\t\t\tapp.resize()\n\t\t}\n\t\t.iconified {\n\t\t\tapp.draw_flag = false\n\t\t}\n\t\t.restored {\n\t\t\tapp.draw_flag = true\n\t\t\tapp.resize()\n\t\t}\n\t\telse {\n\t\t\t// println(\"Type ${e.typ}\")\n\t\t}\n\t}\n}\n\nfn (mut app App) resize() {\n\tsize := gg.window_size()\n\t// avoid calls when minimized\n\tif size.width < 2 && size.height < 2 {\n\t\treturn\n\t}\n\tmut s := gg.dpi_scale()\n\n\tif s == 0.0 {\n\t\ts = 1.0\n\t}\n\tapp.ui.dpi_scale = s\n\tapp.ui.width = size.width\n\tapp.ui.height = size.height\n}\n\nfn main() {\n\tmut app := &App{}\n\tapp.ui = objects.get_params()\n\tapp.gg = gg.new_context(\n\t\twidth:        app.ui.width\n\t\theight:       app.ui.height\n\t\twindow_title: 'Fireworks!'\n\t\tbg_color:     gg.black\n\t\tuser_data:    app\n\t\tframe_fn:     on_frame\n\t\tevent_fn:     on_event\n\t)\n\tapp.gg.run()\n}\n"
  },
  {
    "path": "examples/fireworks/modules/objects/color.v",
    "content": "module objects\n\nimport gg\nimport rand\n\npub fn random_color() gg.Color {\n\treturn gg.Color{\n\t\tr: rand.u8()\n\t\tg: rand.u8()\n\t\tb: rand.u8()\n\t}\n}\n"
  },
  {
    "path": "examples/fireworks/modules/objects/constants.v",
    "content": "module objects\n\npub struct UIParams {\npub mut:\n\tdpi_scale       f32    = 1.0\n\twidth           int    = 800\n\theight          int    = 800\n\tgravity         Vector = Vector{0, -0.03}\n\tage_rate        int    = 1\n\toffspring_count int    = 100\n\trocket_radius   int    = 5\n\tparticle_radius f32    = 2.5\n\tdrag            f32    = 0.98\n}\n\nconst params = &UIParams{}\n\npub fn get_params() &UIParams {\n\treturn params\n}\n"
  },
  {
    "path": "examples/fireworks/modules/objects/particle.v",
    "content": "module objects\n\nimport gg\n\npub struct Particle {\npub mut:\n\tcolor    gg.Color\n\tpos      Vector\n\tvel      Vector\n\taccel    Vector\n\tlifespan f32 = 255\n}\n\npub fn (particle Particle) draw(mut ctx gg.Context) {\n\tctx.draw_circle_filled(particle.pos.x, get_params().height - particle.pos.y, get_params().particle_radius,\n\t\tparticle.color)\n}\n\npub fn (mut particle Particle) tick(mut rocket Rocket, mut ctx gg.Context) {\n\tparticle.lifespan -= get_params().age_rate\n\tparticle.color.a = u8(particle.lifespan)\n\n\tif particle.lifespan <= 0 {\n\t\trocket.dead = true\n\t\treturn\n\t}\n\n\tparticle.accel += get_params().gravity\n\tparticle.vel += particle.accel\n\tparticle.vel = particle.vel.mult(get_params().drag)\n\tparticle.pos += particle.vel\n\tparticle.draw(mut ctx)\n\n\tparticle.accel = Vector{}\n}\n"
  },
  {
    "path": "examples/fireworks/modules/objects/rocket.v",
    "content": "module objects\n\nimport gg\nimport rand\n\npub struct Rocket {\npub mut:\n\tcolor     gg.Color\n\tpos       Vector\n\tvel       Vector\n\taccel     Vector\n\texploded  bool\n\tparticles []Particle\n\tdead      bool\n}\n\npub fn (rocket Rocket) draw(mut ctx gg.Context) {\n\tctx.draw_circle_filled(rocket.pos.x, get_params().height - rocket.pos.y, get_params().rocket_radius,\n\t\trocket.color)\n}\n\npub fn (mut rocket Rocket) explode() {\n\trocket.exploded = true\n\n\tfor _ in 0 .. get_params().offspring_count {\n\t\trocket.spawn_particle()\n\t}\n}\n\npub fn (mut rocket Rocket) tick(mut ctx gg.Context) {\n\tif !rocket.exploded {\n\t\tif rocket.vel.y <= 1 {\n\t\t\trocket.explode()\n\t\t}\n\n\t\trocket.accel += get_params().gravity\n\t\trocket.vel += rocket.accel\n\t\trocket.pos += rocket.vel\n\t\trocket.draw(mut ctx)\n\n\t\trocket.accel = Vector{}\n\t}\n\n\tfor mut particle in rocket.particles {\n\t\tparticle.tick(mut rocket, mut ctx)\n\t}\n}\n\npub fn new_rocket() Rocket {\n\treturn Rocket{\n\t\tcolor: random_color()\n\t\tpos:   Vector{\n\t\t\tx: rand.f32_in_range(50, get_params().width - 50) or { 50 }\n\t\t}\n\t\tvel:   Vector{\n\t\t\tx: rand.f32_in_range(-1.5, 1.5) or { -1.5 }\n\t\t\ty: rand.f32_in_range(5, 7) or { 5 }\n\t\t}\n\t}\n}\n\npub fn (mut rocket Rocket) spawn_particle() {\n\trocket.particles << Particle{\n\t\tcolor: rocket.color\n\t\tpos:   rocket.pos\n\t\taccel: random_vector_in_circle().mult(2)\n\t}\n}\n"
  },
  {
    "path": "examples/fireworks/modules/objects/vector.v",
    "content": "module objects\n\nimport math\nimport rand\n\npub struct Vector {\npub mut:\n\tx f32\n\ty f32\n}\n\npub fn (a Vector) + (b Vector) Vector {\n\treturn Vector{a.x + b.x, a.y + b.y}\n}\n\npub fn (vector Vector) mult(scalar f32) Vector {\n\treturn Vector{vector.x * scalar, vector.y * scalar}\n}\n\npub fn random_vector_in_circle() Vector {\n\ttheta := rand.f32n(2 * math.pi) or { 0 }\n\ty := rand.f32()\n\n\treturn Vector{\n\t\tx: f32(y * math.sin(theta))\n\t\ty: f32(y * math.cos(theta))\n\t}\n}\n"
  },
  {
    "path": "examples/fizz_buzz.v",
    "content": "for n in 1 .. 101 {\n\tprintln(match true {\n\t\tn % 15 == 0 { 'FizzBuzz' }\n\t\tn % 5 == 0 { 'Buzz' }\n\t\tn % 3 == 0 { 'Fizz' }\n\t\telse { n.str() }\n\t})\n}\n"
  },
  {
    "path": "examples/flag_layout_editor.v",
    "content": "import term.ui as tui\nimport flag\n\n@[name: 'flag_layout_editor']\n@[version: '1.0']\nstruct DocTest {\n\tshow_version bool @[short: v; xdoc: 'Show version and exit']\n\tdebug_level  int  @[long: debug; short: d; xdoc: 'Debug level']\n\tlevel        f32  @[only: l; xdoc: 'Do not show this']\n\texample      string\n\tsquare       bool\n\tmulti        int   @[only: m; repeats]\n\twroom        []int @[short: w]\n\tthe_limit    string\n}\n\nconst field_docs = {\n\t'level':                                    'Level of lorem ipsum\\nand more\\nmany many many more.\\nNotice how user newlines/format is kept since\\ninput lines are all less or within\\nthe default layout.description_padding\\nand max width'\n\t'example':                                  'Looong example text without newlines or anything else and lorem ipsum and more and many many many more. Should be auto fitted'\n\t'the_limit':                                'Looongbobbytextwithoutnewlinesoranythingelseandlorem ipsumandmoreandmanymanymanymore ffffffffffffffffffffffffffffffff f'\n\t'multi':                                    'This flag can be repeated'\n\t'-e, --extra':                              'Secret flag that does not exist on the struct, but we want documented (in same format as the others)'\n\t'-q, --quiet-and-quite-long-flag <string>': 'Mega long description and secret flag that does not exist on the struct, but we want documented. Also the flag has custom newlines\\nand the flag line itself is super long'\n}\n\nstruct App {\nmut:\n\ttui     &tui.Context = unsafe { nil }\n\tlayout  flag.DocLayout\n\toptions flag.DocOptions\n\tedit    Edit\n}\n\nenum Edit {\n\t// DocLayout fields\n\tdescription_padding\n\tdescription_width\n\tflag_indent\n\t// DocOptions.compact\n\tcompact\n\t// DocOptions.show flags\n\tname\n\tversion\n\tflags\n\tflag_type\n\tflag_hint\n\tdescription\n\tflags_header\n\tfooter\n}\n\npub fn (e Edit) next() Edit {\n\treturn match e {\n\t\t.description_padding {\n\t\t\t.description_width\n\t\t}\n\t\t.description_width {\n\t\t\t.flag_indent\n\t\t}\n\t\t.flag_indent {\n\t\t\t.compact\n\t\t}\n\t\t.compact {\n\t\t\t.name\n\t\t}\n\t\t.name {\n\t\t\t.version\n\t\t}\n\t\t.version {\n\t\t\t.flags\n\t\t}\n\t\t.flags {\n\t\t\t.flag_type\n\t\t}\n\t\t.flag_type {\n\t\t\t.flag_hint\n\t\t}\n\t\t.flag_hint {\n\t\t\t.description\n\t\t}\n\t\t.description {\n\t\t\t.flags_header\n\t\t}\n\t\t.flags_header {\n\t\t\t.footer\n\t\t}\n\t\t.footer {\n\t\t\t.description_padding\n\t\t}\n\t}\n}\n\nfn event(e &tui.Event, mut app App) {\n\tmut incr_decr := 0\n\tmatch e.typ {\n\t\t.mouse_down {\n\t\t\tapp.edit = app.edit.next()\n\t\t}\n\t\t.mouse_drag {}\n\t\t.mouse_up {}\n\t\t.key_down {\n\t\t\tmatch e.code {\n\t\t\t\t.left {\n\t\t\t\t\tincr_decr = -1\n\t\t\t\t}\n\t\t\t\t.right {\n\t\t\t\t\tincr_decr = 1\n\t\t\t\t}\n\t\t\t\t.space {\n\t\t\t\t\tapp.edit = app.edit.next()\n\t\t\t\t}\n\t\t\t\t.escape {\n\t\t\t\t\texit(0)\n\t\t\t\t}\n\t\t\t\telse {}\n\t\t\t}\n\t\t}\n\t\telse {}\n\t}\n\n\tif incr_decr != 0 {\n\t\tmatch app.edit {\n\t\t\t.flag_indent {\n\t\t\t\tapp.layout.flag_indent += incr_decr\n\t\t\t}\n\t\t\t.description_padding {\n\t\t\t\tapp.layout.description_padding += incr_decr\n\t\t\t}\n\t\t\t.description_width {\n\t\t\t\tapp.layout.description_width += incr_decr\n\t\t\t}\n\t\t\t.compact {\n\t\t\t\tapp.options.compact = !app.options.compact\n\t\t\t}\n\t\t\t.name {\n\t\t\t\tapp.options.show.toggle(.name)\n\t\t\t}\n\t\t\t.version {\n\t\t\t\tapp.options.show.toggle(.version)\n\t\t\t}\n\t\t\t.flags {\n\t\t\t\tapp.options.show.toggle(.flags)\n\t\t\t}\n\t\t\t.flag_type {\n\t\t\t\tapp.options.show.toggle(.flag_type)\n\t\t\t}\n\t\t\t.flag_hint {\n\t\t\t\tapp.options.show.toggle(.flag_hint)\n\t\t\t}\n\t\t\t.description {\n\t\t\t\tapp.options.show.toggle(.description)\n\t\t\t}\n\t\t\t.flags_header {\n\t\t\t\tapp.options.show.toggle(.flags_header)\n\t\t\t}\n\t\t\t.footer {\n\t\t\t\tapp.options.show.toggle(.footer)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfn frame(mut app App) {\n\tapp.tui.clear()\n\n\tmut value := match app.edit {\n\t\t.flag_indent {\n\t\t\t'${app.layout.flag_indent}'\n\t\t}\n\t\t.description_padding {\n\t\t\t'${app.layout.description_padding}'\n\t\t}\n\t\t.description_width {\n\t\t\t'${app.layout.description_width}'\n\t\t}\n\t\t.compact {\n\t\t\tif app.options.compact { 'on' } else { 'off' }\n\t\t}\n\t\t.name {\n\t\t\tif app.options.show.has(.name) { 'on' } else { 'off' }\n\t\t}\n\t\t.version {\n\t\t\tif app.options.show.has(.version) { 'on' } else { 'off' }\n\t\t}\n\t\t.flags {\n\t\t\tif app.options.show.has(.flags) { 'on' } else { 'off' }\n\t\t}\n\t\t.flag_type {\n\t\t\tif app.options.show.has(.flag_type) { 'on' } else { 'off' }\n\t\t}\n\t\t.flag_hint {\n\t\t\tif app.options.show.has(.flag_hint) { 'on' } else { 'off' }\n\t\t}\n\t\t.description {\n\t\t\tif app.options.show.has(.description) { 'on' } else { 'off' }\n\t\t}\n\t\t.flags_header {\n\t\t\tif app.options.show.has(.flags_header) { 'on' } else { 'off' }\n\t\t}\n\t\t.footer {\n\t\t\tif app.options.show.has(.footer) { 'on' } else { 'off' }\n\t\t}\n\t}\n\n\tapp.tui.draw_text(0, 0, 'Click left-mouse button or use space to edit the next property.\nUse keyboard arrow keys right and left to adjust the value of the property\nEditing property: ${app.edit}, value: ${value}')\n\n\thelp_text := flag.to_doc[DocTest](\n\t\tdescription: 'Simple DocLayout editor.\nPress ESCAPE or Ctrl+C to exit and print layout code'\n\t\tfooter:      '\nPress ESCAPE or Ctrl+C to exit and print layout code'\n\t\tfields:      unsafe { field_docs }\n\t\tlayout:      app.layout\n\t\toptions:     app.options\n\t) or { '' }\n\n\tapp.tui.draw_text(0, 5, '${help_text}')\n\tapp.tui.reset()\n\n\tapp.tui.flush()\n}\n\ntype EventFn = fn (&tui.Event, voidptr)\n\ntype FrameFn = fn (voidptr)\n\nfn main() {\n\tmut app := &App{}\n\tat_exit(fn [app] () {\n\t\tprintln('${app.layout}\\n')\n\t\tprintln('${app.options}')\n\t}) or {}\n\tapp.tui = tui.init(\n\t\tuser_data:   app\n\t\tevent_fn:    EventFn(event)\n\t\tframe_fn:    FrameFn(frame)\n\t\thide_cursor: true\n\t\tframe_rate:  60\n\t)\n\tapp.tui.run()!\n}\n"
  },
  {
    "path": "examples/flappylearning/.gitignore",
    "content": "game\n"
  },
  {
    "path": "examples/flappylearning/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 uxnow\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "examples/flappylearning/README.md",
    "content": "# flappylearning-v\nflappy learning implemented by vlang\n\n## get started\n\n```sh\nv run game.v\n```\n\n![flappy.png](assets/img/flappy.png)\n\n## thanks\nhttps://github.com/xviniette/FlappyLearning\n\n## license\nMIT\n"
  },
  {
    "path": "examples/flappylearning/game.v",
    "content": "module main\n\nimport gg\nimport time\nimport math\nimport rand\nimport neuroevolution\nimport os.asset\n\nconst win_width = 500\nconst win_height = 512\n\nconst bg_color = gg.Color{0x96, 0xE2, 0x82, 0xFF}\n\nstruct Bird {\nmut:\n\tx        f64  = 80\n\ty        f64  = 250\n\twidth    f64  = 40\n\theight   f64  = 30\n\talive    bool = true\n\tgravity  f64\n\tvelocity f64 = 0.3\n\tjump     f64 = -6\n}\n\nfn (mut b Bird) flap() {\n\tb.gravity = b.jump\n}\n\nfn (mut b Bird) update() {\n\tb.gravity += b.velocity\n\tb.y += b.gravity\n}\n\nfn (b Bird) is_dead(height f64, pipes []Pipe) bool {\n\tif b.y >= height || b.y + b.height <= 0 {\n\t\treturn true\n\t}\n\tfor pipe in pipes {\n\t\tif !(b.x > pipe.x + pipe.width || b.x + b.width < pipe.x || b.y > pipe.y + pipe.height\n\t\t\t|| b.y + b.height < pipe.y) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nstruct Pipe {\nmut:\n\tx      f64 = 80\n\ty      f64 = 250\n\twidth  f64 = 40\n\theight f64 = 30\n\tspeed  f64 = 3\n}\n\nfn (mut p Pipe) update() {\n\tp.x -= p.speed\n}\n\nfn (p Pipe) is_out() bool {\n\treturn p.x + p.width < 0\n}\n\nstruct App {\nmut:\n\tgg               &gg.Context = unsafe { nil }\n\tbackground       gg.Image\n\tbird             gg.Image\n\tpipetop          gg.Image\n\tpipebottom       gg.Image\n\tpipes            []Pipe\n\tbirds            []Bird\n\tscore            int\n\tmax_score        int\n\twidth            f64 = win_width\n\theight           f64 = win_height\n\tspawn_interval   f64 = 90\n\tinterval         f64\n\tnv               neuroevolution.Generations\n\tgen              []neuroevolution.Network\n\talives           int\n\tgeneration       int\n\tbackground_speed f64 = 0.5\n\tbackground_x     f64\n\ttimer_period_ms  int = 24\n}\n\nfn (mut app App) start() {\n\tapp.interval = 0\n\tapp.score = 0\n\tapp.pipes = []\n\tapp.birds = []\n\tapp.gen = app.nv.generate()\n\tfor _ in 0 .. app.gen.len {\n\t\tapp.birds << Bird{}\n\t}\n\tapp.generation++\n\tapp.alives = app.birds.len\n}\n\nfn (app &App) is_it_end() bool {\n\tfor i in 0 .. app.birds.len {\n\t\tif app.birds[i].alive {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfn (mut app App) update() {\n\tapp.background_x += app.background_speed\n\tmut next_holl := f64(0)\n\tif app.birds.len > 0 {\n\t\tfor i := 0; i < app.pipes.len; i += 2 {\n\t\t\tif app.pipes[i].x + app.pipes[i].width > app.birds[0].x {\n\t\t\t\tnext_holl = app.pipes[i].height / app.height\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\tfor j, mut bird in app.birds {\n\t\tif bird.alive {\n\t\t\tinputs := [\n\t\t\t\tbird.y / app.height,\n\t\t\t\tnext_holl,\n\t\t\t]\n\t\t\tres := app.gen[j].compute(inputs)\n\t\t\tif res[0] > 0.5 {\n\t\t\t\tbird.flap()\n\t\t\t}\n\t\t\tbird.update()\n\t\t\tif bird.is_dead(app.height, app.pipes) {\n\t\t\t\tbird.alive = false\n\t\t\t\tapp.alives--\n\t\t\t\tapp.nv.network_score(app.gen[j], app.score)\n\t\t\t\tif app.is_it_end() {\n\t\t\t\t\tapp.start()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor k := 0; k < app.pipes.len; k++ {\n\t\tapp.pipes[k].update()\n\t\tif app.pipes[k].is_out() {\n\t\t\tapp.pipes.delete(k)\n\t\t\tk--\n\t\t}\n\t}\n\tif app.interval == 0 {\n\t\tdelta_bord := f64(50)\n\t\tpipe_holl := f64(120)\n\t\tholl_position := math.round(rand.f64() * (app.height - delta_bord * 2.0 - pipe_holl)) +\n\t\t\tdelta_bord\n\t\tapp.pipes << Pipe{\n\t\t\tx:      app.width\n\t\t\ty:      0\n\t\t\theight: holl_position\n\t\t}\n\t\tapp.pipes << Pipe{\n\t\t\tx:      app.width\n\t\t\ty:      holl_position + pipe_holl\n\t\t\theight: app.height\n\t\t}\n\t}\n\tapp.interval++\n\tif app.interval == app.spawn_interval {\n\t\tapp.interval = 0\n\t}\n\tapp.score++\n\tapp.max_score = if app.score > app.max_score { app.score } else { app.max_score }\n}\n\nfn main() {\n\tmut app := &App{}\n\tapp.gg = gg.new_context(\n\t\tbg_color:      bg_color\n\t\twidth:         win_width\n\t\theight:        win_height\n\t\tcreate_window: true\n\t\twindow_title:  'flappylearning-v'\n\t\tframe_fn:      frame\n\t\tevent_fn:      on_event\n\t\tuser_data:     app\n\t\tinit_fn:       app.init_images_wrapper\n\t\tfont_path:     asset.get_path('../assets', 'fonts/RobotoMono-Regular.ttf')\n\t)\n\tapp.nv = neuroevolution.Generations{\n\t\tpopulation: 50\n\t\tnetwork:    [2, 2, 1]\n\t}\n\tapp.start()\n\tspawn app.run()\n\tapp.gg.run()\n}\n\nfn (mut app App) run() {\n\tfor {\n\t\tapp.update()\n\t\ttime.sleep(app.timer_period_ms * time.millisecond)\n\t}\n}\n\nfn (mut app App) init_images_wrapper() {\n\tapp.init_images() or { panic(err) }\n}\n\nfn (mut app App) init_images() ! {\n\tapp.bird = app.gg.create_image_from_byte_array(asset.read_bytes('assets', 'img/bird.png')!)!\n\tapp.pipetop = app.gg.create_image_from_byte_array(asset.read_bytes('assets', 'img/pipetop.png')!)!\n\tapp.pipebottom = app.gg.create_image_from_byte_array(asset.read_bytes('assets', 'img/pipebottom.png')!)!\n\tapp.background = app.gg.create_image_from_byte_array(asset.read_bytes('assets', 'img/background.png')!)!\n}\n\nfn frame(app &App) {\n\tapp.gg.begin()\n\tapp.display()\n\tapp.gg.end()\n}\n\nfn (app &App) display() {\n\tfor i := 0; i < int(math.ceil(app.width / app.background.width) + 1.0); i++ {\n\t\tbackground_x := i * app.background.width - math.floor(int(app.background_x) % int(app.background.width))\n\t\tapp.gg.draw_image(f32(background_x), 0, app.background.width, app.background.height,\n\t\t\tapp.background)\n\t}\n\tfor i, pipe in app.pipes {\n\t\tif i % 2 == 0 {\n\t\t\tapp.gg.draw_image(f32(pipe.x), f32(pipe.y + pipe.height - app.pipetop.height),\n\t\t\t\tapp.pipetop.width, app.pipetop.height, app.pipetop)\n\t\t} else {\n\t\t\tapp.gg.draw_image(f32(pipe.x), f32(pipe.y), app.pipebottom.width, app.pipebottom.height,\n\t\t\t\tapp.pipebottom)\n\t\t}\n\t}\n\tfor bird in app.birds {\n\t\tif bird.alive {\n\t\t\tapp.gg.draw_image(f32(bird.x), f32(bird.y), app.bird.width, app.bird.height,\n\t\t\t\tapp.bird)\n\t\t}\n\t}\n\tapp.gg.draw_rect_filled(0, 510, app.background.width * 3, 5, gg.Color{0x21, 0x19, 0x28, 255})\n\tapp.gg.draw_rect_filled(0, 513, app.background.width * 3, app.background.height, bg_color)\n\tapp.gg.draw_rect_filled(550, 0, app.background.width + 50, app.background.height + 20,\n\t\tbg_color)\n\tapp.gg.draw_text_def(10, 25, 'Score: ${app.score}')\n\tapp.gg.draw_text_def(10, 50, 'Max Score: ${app.max_score}')\n\tapp.gg.draw_text_def(10, 75, 'Generation: ${app.generation}')\n\tapp.gg.draw_text_def(10, 100, 'Alive: ${app.alives} / ${app.nv.population}')\n}\n\nfn on_event(e &gg.Event, mut app App) {\n\tif e.typ == .key_down {\n\t\tapp.key_down(e.key_code)\n\t}\n}\n\nfn (mut app App) key_down(key gg.KeyCode) {\n\t// global keys\n\tmatch key {\n\t\t.escape {\n\t\t\tapp.gg.quit()\n\t\t}\n\t\t._0 {\n\t\t\tapp.timer_period_ms = 0\n\t\t}\n\t\t.space {\n\t\t\tif app.timer_period_ms == 24 {\n\t\t\t\tapp.timer_period_ms = 4\n\t\t\t} else {\n\t\t\t\tapp.timer_period_ms = 24\n\t\t\t}\n\t\t}\n\t\telse {}\n\t}\n}\n"
  },
  {
    "path": "examples/flappylearning/modules/neuroevolution/neuronevolution.v",
    "content": "module neuroevolution\n\nimport rand\nimport math\n\nfn random_clamped() f64 {\n\treturn rand.f64() * 2 - 1\n}\n\npub fn activation(a f64) f64 {\n\tap := (-a) / 1\n\treturn 1 / (1 + math.exp(ap))\n}\n\nfn round(a int, b f64) int {\n\treturn int(math.round(f64(a) * b))\n}\n\nstruct Neuron {\nmut:\n\tvalue   f64\n\tweights []f64\n}\n\nfn (mut n Neuron) populate(nb int) {\n\tfor _ in 0 .. nb {\n\t\tn.weights << random_clamped()\n\t}\n}\n\nstruct Layer {\n\tid int\nmut:\n\tneurons []Neuron\n}\n\nfn (mut l Layer) populate(nb_neurons int, nb_inputs int) {\n\tfor _ in 0 .. nb_neurons {\n\t\tmut n := Neuron{}\n\t\tn.populate(nb_inputs)\n\t\tl.neurons << n\n\t}\n}\n\npub struct Network {\nmut:\n\tlayers []Layer\n}\n\nfn (mut n Network) populate(network []int) {\n\tassert network.len >= 2\n\tinput := network[0]\n\thiddens := network[1..network.len - 1]\n\toutput := network[network.len - 1]\n\tmut index := 0\n\tmut previous_neurons := 0\n\tmut input_layer := Layer{\n\t\tid: index\n\t}\n\tinput_layer.populate(input, previous_neurons)\n\tn.layers << input_layer\n\tprevious_neurons = input\n\tindex++\n\tfor hidden in hiddens {\n\t\tmut hidden_layer := Layer{\n\t\t\tid: index\n\t\t}\n\t\thidden_layer.populate(hidden, previous_neurons)\n\t\tprevious_neurons = hidden\n\t\tn.layers << hidden_layer\n\t\tindex++\n\t}\n\tmut output_layer := Layer{\n\t\tid: index\n\t}\n\toutput_layer.populate(output, previous_neurons)\n\tn.layers << output_layer\n}\n\nfn (n Network) get_save() Save {\n\tmut save := Save{}\n\tfor layer in n.layers {\n\t\tsave.neurons << layer.neurons.len\n\t\tfor neuron in layer.neurons {\n\t\t\tfor weight in neuron.weights {\n\t\t\t\tsave.weights << weight\n\t\t\t}\n\t\t}\n\t}\n\treturn save\n}\n\nfn (mut n Network) set_save(save Save) {\n\tmut previous_neurons := 0\n\tmut index := 0\n\tmut index_weights := 0\n\tn.layers = []\n\tfor save_neuron in save.neurons {\n\t\tmut layer := Layer{\n\t\t\tid: index\n\t\t}\n\t\tlayer.populate(save_neuron, previous_neurons)\n\t\tfor mut neuron in layer.neurons {\n\t\t\tfor i in 0 .. neuron.weights.len {\n\t\t\t\tneuron.weights[i] = save.weights[index_weights]\n\t\t\t\tindex_weights++\n\t\t\t}\n\t\t}\n\t\tprevious_neurons = save_neuron\n\t\tindex++\n\t\tn.layers << layer\n\t}\n}\n\npub fn (mut n Network) compute(inputs []f64) []f64 {\n\tassert n.layers.len > 0\n\tassert inputs.len == n.layers[0].neurons.len\n\tfor i, input in inputs {\n\t\tn.layers[0].neurons[i].value = input\n\t}\n\tmut prev_layer := n.layers[0]\n\tfor i in 1 .. n.layers.len {\n\t\tfor j, neuron in n.layers[i].neurons {\n\t\t\tmut sum := f64(0)\n\t\t\tfor k, prev_layer_neuron in prev_layer.neurons {\n\t\t\t\tsum += prev_layer_neuron.value * neuron.weights[k]\n\t\t\t}\n\t\t\tn.layers[i].neurons[j].value = activation(sum)\n\t\t}\n\t\tprev_layer = n.layers[i]\n\t}\n\tmut outputs := []f64{}\n\tmut last_layer := n.layers[n.layers.len - 1]\n\tfor neuron in last_layer.neurons {\n\t\toutputs << neuron.value\n\t}\n\treturn outputs\n}\n\nstruct Save {\nmut:\n\tneurons []int\n\tweights []f64\n}\n\nfn (s Save) clone() Save {\n\tmut save := Save{}\n\tsave.neurons << s.neurons\n\tsave.weights << s.weights\n\treturn save\n}\n\nstruct Genome {\n\tscore   int\n\tnetwork Save\n}\n\nstruct Generation {\nmut:\n\tgenomes []Genome\n}\n\nfn (mut g Generation) add_genome(genome Genome) {\n\tmut i := 0\n\tfor gg in g.genomes {\n\t\tif genome.score > gg.score {\n\t\t\tbreak\n\t\t}\n\t\ti++\n\t}\n\tg.genomes.insert(i, genome)\n}\n\nfn (g1 Genome) breed(g2 Genome, nb_child int) []Save {\n\tmut datas := []Save{}\n\tfor _ in 0 .. nb_child {\n\t\tmut data := g1.network.clone()\n\t\tfor i, weight in g2.network.weights {\n\t\t\tif rand.f64() <= 0.5 {\n\t\t\t\tdata.weights[i] = weight\n\t\t\t}\n\t\t}\n\t\tfor i, _ in data.weights {\n\t\t\tif rand.f64() <= 0.1 {\n\t\t\t\tdata.weights[i] += (rand.f64() * 2 - 1) * 0.5\n\t\t\t}\n\t\t}\n\t\tdatas << data\n\t}\n\treturn datas\n}\n\nfn (g Generation) next(population int) []Save {\n\tmut nexts := []Save{}\n\tif population == 0 {\n\t\treturn nexts\n\t}\n\tkeep := round(population, 0.2)\n\tfor i in 0 .. keep {\n\t\tif nexts.len < population {\n\t\t\tnexts << g.genomes[i].network.clone()\n\t\t}\n\t}\n\trandom := round(population, 0.2)\n\tfor _ in 0 .. random {\n\t\tif nexts.len < population {\n\t\t\tmut n := g.genomes[0].network.clone()\n\t\t\tfor k, _ in n.weights {\n\t\t\t\tn.weights[k] = random_clamped()\n\t\t\t}\n\t\t\tnexts << n\n\t\t}\n\t}\n\tmut max := 0\n\tout: for {\n\t\tfor i in 0 .. max {\n\t\t\tmut childs := g.genomes[i].breed(g.genomes[max], 1)\n\t\t\tfor c in childs {\n\t\t\t\tnexts << c\n\t\t\t\tif nexts.len >= population {\n\t\t\t\t\tbreak out\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tmax++\n\t\tif max >= g.genomes.len - 1 {\n\t\t\tmax = 0\n\t\t}\n\t}\n\treturn nexts\n}\n\npub struct Generations {\npub:\n\tpopulation int\n\tnetwork    []int\nmut:\n\tgenerations []Generation\n}\n\nfn (mut gs Generations) first() []Save {\n\tmut out := []Save{}\n\tfor _ in 0 .. gs.population {\n\t\tmut nn := Network{}\n\t\tnn.populate(gs.network)\n\t\tout << nn.get_save()\n\t}\n\tgs.generations << Generation{}\n\treturn out\n}\n\nfn (mut gs Generations) next() []Save {\n\tassert gs.generations.len > 0\n\tgen := gs.generations[gs.generations.len - 1].next(gs.population)\n\tgs.generations << Generation{}\n\treturn gen\n}\n\nfn (mut gs Generations) add_genome(genome Genome) {\n\tassert gs.generations.len > 0\n\tgs.generations[gs.generations.len - 1].add_genome(genome)\n}\n\nfn (mut gs Generations) restart() {\n\tgs.generations = []\n}\n\npub fn (mut gs Generations) generate() []Network {\n\tsaves := if gs.generations.len == 0 { gs.first() } else { gs.next() }\n\tmut nns := []Network{}\n\tfor save in saves {\n\t\tmut nn := Network{}\n\t\tnn.set_save(save)\n\t\tnns << nn\n\t}\n\tif gs.generations.len >= 2 {\n\t\tgs.generations.delete(0)\n\t}\n\treturn nns\n}\n\npub fn (mut gs Generations) network_score(network Network, score int) {\n\tgs.add_genome(Genome{\n\t\tscore:   score\n\t\tnetwork: network.get_save()\n\t})\n}\n"
  },
  {
    "path": "examples/function_types.v",
    "content": "// Function signatures can be declared as types:\n\ntype Filter = fn (string) string\n\n// Functions can accept function types as arguments:\n\nfn filter(s string, f Filter) string {\n\treturn f(s)\n}\n\n// Declare a function with a matching signature:\n\nfn uppercase(s string) string {\n\treturn s.to_upper()\n}\n\nfn main() {\n\t// A function can be assigned to a matching type:\n\n\tmy_filter := Filter(uppercase)\n\n\t// You don't strictly need the `Filter` cast - it's only used\n\t// here to illustrate how these types are compatible.\n\n\t// All of the following prints \"HELLO WORLD\":\n\n\tprintln(filter('Hello world', my_filter))\n\tprintln(filter('Hello world', uppercase))\n\tprintln(filter('Hello world', fn (s string) string {\n\t\treturn s.to_upper()\n\t}))\n}\n"
  },
  {
    "path": "examples/game_of_life/README.md",
    "content": "# Conway's Game of Life\n\n![](https://github.com/fuyutarow/Conways-Game-of-Life-with-Vlang/raw/master/v-gun.gif)\n\n\n```\nv run life.v\n```\n\nCreated by fuyutarow: https://github.com/fuyutarow/Conways-Game-of-Life-with-Vlang\n"
  },
  {
    "path": "examples/game_of_life/life.v",
    "content": "import term\nimport rand\nimport time\n\nconst cell = '█'\nconst nothing = ' '\nconst switches = {\n\tcell:    nothing\n\tnothing: cell\n}\nconst transformers = [nothing, cell]\n\nstruct Game {\nmut:\n\tgrid [][]string\n}\n\nfn (g Game) get_surrounding_alive_count(x int, y int) int {\n\tmut count := 0\n\tfor i := x - 1; i <= x + 1; i++ {\n\t\tfor j := y - 1; j <= y + 1; j++ {\n\t\t\tif (i != x || j != y) && i >= 0 && j >= 0 && i < g.grid.len && j < g.grid[x].len {\n\t\t\t\tif g.grid[i][j] == cell {\n\t\t\t\t\tcount++\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn count\n}\n\nfn (mut g Game) evolve() {\n\tmut temp_grid := [][]string{}\n\tfor x in 0 .. g.grid.len {\n\t\ttemp_grid << []string{}\n\t\tfor y in 0 .. g.grid[x].len {\n\t\t\tcount := g.get_surrounding_alive_count(x, y)\n\t\t\tif count == 3 || (g.grid[x][y] == cell && count == 2) {\n\t\t\t\ttemp_grid[x] << cell\n\t\t\t} else {\n\t\t\t\ttemp_grid[x] << nothing\n\t\t\t}\n\t\t}\n\t}\n\n\tg.grid = temp_grid\n}\n\nfn (mut g Game) display() {\n\tfor y in 0 .. g.grid[0].len {\n\t\tmut line := ''\n\t\tfor x in 0 .. g.grid.len {\n\t\t\tline += g.grid[x][y]\n\t\t}\n\t\tprintln(line)\n\t}\n}\n\nfn new_game() Game {\n\tw, h := term.get_terminal_size()\n\tmut grid := [][]string{}\n\tfor x in 0 .. w {\n\t\tgrid << []string{}\n\t\tfor _ in 0 .. h {\n\t\t\tis_live := rand.f64() > 0.82\n\t\t\ticon := transformers[int(is_live)]\n\t\t\tgrid[x] << icon\n\t\t}\n\t}\n\treturn Game{grid}\n}\n\nfn main() {\n\tmut g := new_game()\n\n\tg.display()\n\tfor {\n\t\tg.evolve()\n\t\tterm.erase_clear()\n\t\tg.display()\n\t\ttime.sleep(100 * time.millisecond)\n\t}\n}\n"
  },
  {
    "path": "examples/game_of_life/life_gg.v",
    "content": "module main\n\nimport gg\nimport automaton\n\nconst screen_width = 800\nconst screen_height = 600\nconst filled_color = gg.blue\n\n@[live]\nfn print_automaton(app &App) {\n\tsquare_size := 18\n\tfor y := 1; y < app.a.field.maxy; y++ {\n\t\tfor x := 1; x < app.a.field.maxx; x++ {\n\t\t\tcell := app.a.field.get(x, y)\n\t\t\tif cell == 1 {\n\t\t\t\tapp.gg.draw_rect_filled(f32(square_size * x), f32(square_size * y), f32(square_size),\n\t\t\t\t\tf32(square_size), filled_color)\n\t\t\t}\n\t\t}\n\t}\n}\n\nstruct App {\nmut:\n\tgg &gg.Context = unsafe { nil }\n\ta  automaton.Automaton\n}\n\nfn frame(mut app App) {\n\tapp.gg.begin()\n\tapp.a.update()\n\tprint_automaton(app)\n\tapp.gg.end()\n}\n\nfn main() {\n\tmut app := App{\n\t\ta: automaton.gun()\n\t}\n\tapp.gg = gg.new_context(\n\t\tbg_color:      gg.white\n\t\tframe_fn:      frame\n\t\tuser_data:     &app\n\t\twidth:         screen_width\n\t\theight:        screen_height\n\t\tcreate_window: true\n\t\tresizable:     false\n\t\twindow_title:  'v life (with gg)'\n\t)\n\tapp.gg.run()\n}\n"
  },
  {
    "path": "examples/game_of_life/modules/automaton/automaton.v",
    "content": "module automaton\n\n// ///////////////////////////////////////////////////////////\npub struct A2D {\npub mut:\n\tmaxx int\n\tmaxy int\n\tdata &int\n}\n\nfn new_a2d(maxx int, maxy int) &A2D {\n\tsize := int(sizeof(int)) * (maxx * maxy)\n\treturn &A2D{\n\t\tmaxx: maxx\n\t\tmaxy: maxy\n\t\tdata: unsafe { &int(vcalloc(size)) }\n\t}\n}\n\n@[inline]\npub fn (a &A2D) set(x int, y int, newval int) {\n\tunsafe {\n\t\tmut e := &int(0)\n\t\te = a.data + y * a.maxx + x\n\t\t*e = newval\n\t}\n}\n\n@[inline]\npub fn (a &A2D) get(x int, y int) int {\n\tunsafe {\n\t\tmut e := &int(0)\n\t\te = a.data + y * a.maxx + x\n\t\t_ = e\n\t\treturn *e\n\t}\n}\n\n@[inline]\npub fn (a &A2D) clear() {\n\tfor y := 0; y < a.maxy; y++ {\n\t\tfor x := 0; x < a.maxx; x++ {\n\t\t\ta.set(x, y, 0)\n\t\t}\n\t}\n}\n\n// ///////////////////////////////////////////////////////////\npub struct Automaton {\npub mut:\n\tfield     &A2D = unsafe { nil }\n\tnew_field &A2D = unsafe { nil }\n}\n\nfn new_automaton(ftext string) Automaton {\n\tf := ftext.split('\\n').map(it.trim_space()).filter(it.len > 0)\n\tmaxy := f.len\n\tmut maxx := 0\n\tfor y := 0; y < f.len; y++ {\n\t\tif maxx < f[y].len {\n\t\t\tmaxx = f[y].len\n\t\t}\n\t}\n\tfield := new_a2d(maxx, maxy)\n\tnew_field := new_a2d(maxx, maxy)\n\tfor y in 0 .. field.maxy {\n\t\tfor x in 0 .. field.maxx {\n\t\t\tval := if x < f[y].len && f[y][x] == `#` { 1 } else { 0 }\n\t\t\tfield.set(x, y, val)\n\t\t}\n\t}\n\treturn Automaton{\n\t\tfield:     field\n\t\tnew_field: new_field\n\t}\n}\n\npub fn (mut aa Automaton) update() {\n\taa.new_field.clear()\n\tfor y := 1; y < aa.field.maxy; y++ {\n\t\tfor x := 1; x < aa.field.maxx; x++ {\n\t\t\tmoore_sum := (0 + aa.field.get(x - 1, y - 1) + aa.field.get(x, y - 1) + aa.field.get(x +\n\t\t\t\t1, y - 1) + aa.field.get(x - 1, y) + 0 + aa.field.get(x + 1, y) +\n\t\t\t\taa.field.get(x - 1, y + 1) + aa.field.get(x, y + 1) + aa.field.get(x + 1, y + 1))\n\t\t\tcell := aa.field.get(x, y)\n\t\t\tv := if cell == 1 { moore_sum in [2, 3] } else { moore_sum == 3 }\n\t\t\taa.new_field.set(x, y, if v { 1 } else { 0 })\n\t\t}\n\t}\n\ttmp := aa.field\n\taa.field = aa.new_field\n\taa.new_field = tmp\n}\n\npub fn gun() Automaton {\n\tfield := '\n*******************************************\n*                                         *\n*  A shooting gun:                        *\n*                          #              *\n*                        # #              *\n*              ##      ##            ##   *\n*             #   #    ##            ##   *\n*  ##        #     #   ##                 *\n*  ##        #   # ##    # #              *\n*            #     #       #              *\n*             #   #                       *\n*              ##                         *\n*                                         *\n*  Tetris Life:                           *\n*                                         *\n*  ##       ####                          *\n*  ##                                     *\n*                                         *\n*                                         *\n*                                         *\n*  #         ##                           *\n*  ###      ##                            *\n*                                         *\n*                                         *\n*                                         *\n*        #                                *\n*       ###                               *\n*                                         *\n*                                         *\n*                                         *\n*                                         *\n*******************************************\n'\n\treturn new_automaton(field)\n}\n"
  },
  {
    "path": "examples/get_raw_line.v",
    "content": "import os\n\nprintln('Press Ctrl+D(Linux) or Ctrl+Z(Windows) at line begin to exit')\nmut i := 0\nfor {\n\ti += 1\n\tmut line := os.get_raw_line()\n\tif line.len == 0 {\n\t\tbreak\n\t}\n\tprintln('${i}: ${line}')\n}\n"
  },
  {
    "path": "examples/get_weather/README.md",
    "content": "# get_weather\n\nget_weather is a web crawler. Its goal is to get a weather forecast from\n`https://api.caiyunapp.com` in chinese and translated to another selected language.\n\nWe use `http.fetch()` to get a forecast `http.Response`, with a custom user-agent\nand then we decode the json into a struct with only relevant fields `lang`,\n`result` and `forecast_keypoint`.\n\nThe chinese texts are translated with another `http.fetch()` to\n`https://translate.googleapis.com` and then decoding the `http.Response` as `json2.Any` arrays.\n\n## running\n\nBy default texts are translated to English. Another language can be indicated\nwith first argument as an [ISO 639](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes) code:\n\n```bash\n$ v run examples/get_weather/get_weather.v\n   zh_CN: 未来两小时天气\n      en: Weather in the next two hours\n   zh_CN: 最近的降雨带在西北66公里外呢\n      en: The nearest rainfall zone is 66 kilometers northwest\n$\n$ v run examples/get_weather/get_weather.v es\n   zh_CN: 未来两小时天气\n      es: Clima en las próximas dos horas\n   zh_CN: 最近的降雨带在西北66公里外呢\n      es: La zona de lluvia más cercana está a 66 kilómetros al noroeste\n```\n\n"
  },
  {
    "path": "examples/get_weather/get_weather.v",
    "content": "import net.http\nimport os\nimport rand\nimport x.json2 as json\n\nstruct Weather {\n\tlang   string\n\tresult Result\n}\n\nstruct Result {\n\tforecast_keypoint string\n}\n\nconst config = http.FetchConfig{\n\tuser_agent: 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0'\n}\n\nfn main() {\n\tdest_lang := if os.args.len > 1 { os.args[1] } else { 'en' }\n\trnd := rand.f32()\n\turl := 'https://api.caiyunapp.com/v2.5/96Ly7wgKGq6FhllM/116.391912,40.010711/weather.jsonp?hourlysteps=120&random=${rnd}'\n\n\tresp := http.fetch(http.FetchConfig{ ...config, url: url }) or {\n\t\tprintln('failed to fetch data from the server')\n\t\treturn\n\t}\n\n\tweather := json.decode[Weather](resp.body) or {\n\t\tprintln('failed to decode weather json')\n\t\treturn\n\t}\n\n\tfor ch in ['未来两小时天气', weather.result.forecast_keypoint] {\n\t\tprintln('${weather.lang:8}: ${ch}')\n\t\tt := translate(ch, weather.lang, dest_lang) or {\n\t\t\tprintln('failed to translate ${ch}: ${err}')\n\t\t\tcontinue\n\t\t}\n\t\tprintln('${dest_lang:8}: ${t}')\n\t}\n}\n\n// translate fetch google to print translate text `q` in languate `sl` into language `tl`.\n// A translation typical response json is like: `[[[\"Weather in the next two hours\",\n// \"未来两小时天气\",null,null,3,null,null,[[null,\"offline\"]],\n// [[[\"61549914d65604307a34fd1855292577\",\"offline_launch_doc.md\"],null,null,null,null,\n// [[[6,8,0]]]]]]],null,\"zh-CN\",null,null,null,null,[]]`\n// where translated text is located at position `json_resp[0][0][0]`.\nfn translate(q string, sl string, tl string) !string {\n\turl := 'https://translate.googleapis.com/translate_a/single?client=gtx&sl=${sl}&tl=${tl}&dt=t&q=${q}'\n\n\tresp := http.fetch(http.FetchConfig{ ...config, url: url })!\n\n\tjson_resp := json.decode[json.Any](resp.body)!\n\n\ta := json_resp.as_array()\n\tif a.len > 0 {\n\t\ta0 := a[0].as_array()\n\t\tif a0.len > 0 {\n\t\t\ta00 := a0[0].as_array()\n\t\t\tif a00.len > 0 {\n\t\t\t\treturn a00[0].str()\n\t\t\t}\n\t\t}\n\t}\n\treturn error('invalid translation response')\n}\n"
  },
  {
    "path": "examples/gg/additive.v",
    "content": "module main\n\nimport os\nimport gg\nimport math\n\n@[heap]\npub struct Window {\npub mut:\n\tctx   &gg.Context = unsafe { 0 }\n\timage gg.Image\n}\n\npub fn (mut window Window) init() {\n\tlogo_path := os.join_path(@VEXEROOT, 'examples/assets/logo.png')\n\twindow.image = window.ctx.create_image(logo_path) or { panic(err) }\n}\n\npub fn (mut window Window) draw(_ voidptr) {\n\twindow.ctx.begin()\n\n\tmyconfig := gg.DrawImageConfig{\n\t\timg:      &window.image\n\t\timg_id:   window.image.id\n\t\timg_rect: gg.Rect{\n\t\t\tx:      400 - window.image.width / 2\n\t\t\ty:      300 - window.image.height / 2\n\t\t\twidth:  window.image.width\n\t\t\theight: window.image.height\n\t\t}\n\t\trotation: f32(window.ctx.frame)\n\t\t// effect: .alpha <-- this can be omitted completely as it is alpha by default.\n\t}\n\twindow.ctx.draw_image_with_config(gg.DrawImageConfig{ ...myconfig, flip_x: true })\n\n\t// Red\n\twindow.ctx.draw_image_with_config(gg.DrawImageConfig{\n\t\t...myconfig\n\t\timg_rect: gg.Rect{\n\t\t\t...myconfig.img_rect\n\t\t\tx: myconfig.img_rect.x + f32(math.sin(f32(window.ctx.frame) / 10.0) * 60)\n\t\t\ty: myconfig.img_rect.y + f32(math.cos(f32(window.ctx.frame) / 10.0) * 60)\n\t\t}\n\t\tcolor:    gg.Color{255, 0, 0, 255}\n\t\teffect:   .add\n\t})\n\n\t// Green\n\twindow.ctx.draw_image_with_config(gg.DrawImageConfig{\n\t\t...myconfig\n\t\timg_rect: gg.Rect{\n\t\t\t...myconfig.img_rect\n\t\t\tx: myconfig.img_rect.x + f32(math.sin(f32(window.ctx.frame) / 10.0) * 80)\n\t\t\ty: myconfig.img_rect.y + f32(math.cos(f32(window.ctx.frame) / 10.0) * 80)\n\t\t}\n\t\tcolor:    gg.Color{0, 255, 0, 255}\n\t\teffect:   .add\n\t})\n\n\t// Blue\n\twindow.ctx.draw_image_with_config(gg.DrawImageConfig{\n\t\t...myconfig\n\t\timg_rect: gg.Rect{\n\t\t\t...myconfig.img_rect\n\t\t\tx: myconfig.img_rect.x + f32(math.sin(f32(window.ctx.frame) / 10.0) * 100)\n\t\t\ty: myconfig.img_rect.y + f32(math.cos(f32(window.ctx.frame) / 10.0) * 100)\n\t\t}\n\t\tcolor:    gg.Color{0, 0, 255, 255}\n\t\teffect:   .add\n\t})\n\n\t// More examples\n\twindow.ctx.draw_image_with_config(gg.DrawImageConfig{\n\t\t...myconfig\n\t\timg_rect: gg.Rect{\n\t\t\t...myconfig.img_rect\n\t\t\tx: 50\n\t\t\ty: 0\n\t\t}\n\t\tcolor:    gg.Color{255, 0, 0, 255}\n\t\teffect:   .add\n\t})\n\n\twindow.ctx.draw_image_with_config(gg.DrawImageConfig{\n\t\t...myconfig\n\t\timg_rect: gg.Rect{\n\t\t\t...myconfig.img_rect\n\t\t\tx: 50\n\t\t\ty: 50\n\t\t}\n\t\tcolor:    gg.Color{0, 255, 0, 255}\n\t\teffect:   .add\n\t})\n\n\twindow.ctx.draw_image_with_config(gg.DrawImageConfig{\n\t\t...myconfig\n\t\timg_rect: gg.Rect{\n\t\t\t...myconfig.img_rect\n\t\t\tx: 50\n\t\t\ty: 100\n\t\t}\n\t\tcolor:    gg.Color{0, 0, 255, 255}\n\t\teffect:   .add\n\t})\n\n\twindow.ctx.end()\n}\n\nfn main() {\n\tmut window := &Window{}\n\n\twindow.ctx = gg.new_context(\n\t\twindow_title: 'Additive colors & image rotation'\n\t\twidth:        800\n\t\theight:       600\n\t\tuser_data:    window\n\t\tbg_color:     gg.gray\n\t\t// FNs\n\t\tinit_fn:  window.init\n\t\tframe_fn: window.draw\n\t)\n\n\twindow.ctx.run()\n}\n"
  },
  {
    "path": "examples/gg/arcs_and_slices.v",
    "content": "module main\n\nimport gg\nimport math\n\nconst win_width = 700\nconst win_height = 800\nconst bg_color = gg.white\n\n// A transparent color is used to aid in verifying that\n// rendering is precise on each of the arc types (e.g. no overlapping or double rendered slices)\nconst colour = gg.rgba(100, 100, 0, 100)\n\nenum Selection {\n\tsegs = 0\n\tlen\n}\n\nstruct App {\nmut:\n\tgg    &gg.Context = unsafe { nil }\n\tmouse struct {\n\tmut:\n\t\tx f32\n\t\ty f32\n\t}\n\n\tsel  Selection\n\tsegs int = 8\n}\n\nfn main() {\n\tmut app := &App{}\n\tapp.gg = gg.new_context(\n\t\twidth:         win_width\n\t\theight:        win_height\n\t\tcreate_window: true\n\t\twindow_title:  'Arcs and Slices'\n\t\tuser_data:     app\n\t\tbg_color:      bg_color\n\t\tframe_fn:      on_frame\n\t\tevent_fn:      on_event\n\t)\n\tapp.gg.run()\n}\n\nfn on_frame(mut app App) {\n\tapp.gg.begin()\n\n\tstart := math.tau * app.mouse.y / (win_width * app.gg.scale)\n\tend := math.tau * app.mouse.x / (win_width * app.gg.scale)\n\n\tsegs := if app.sel == .segs { '[${app.segs}]' } else { '${app.segs}' }\n\tapp.gg.draw_text_def(10, 10, 'Segments: ${segs}')\n\tapp.gg.draw_text_def(250, 10, 'Drawing Angles (radians)')\n\tapp.gg.draw_text_def(200, 26, 'Start: ${start}°')\n\tapp.gg.draw_text_def(350, 26, 'End: ${end}°')\n\tmut x, mut y := 0, -80\n\n\ty += 150\n\tx = 20\n\tapp.gg.draw_text_def(10, y + 40, 'slice')\n\tx += 150\n\tapp.gg.draw_slice_empty(x, y + 60, 50, start, end, app.segs, colour)\n\tapp.gg.draw_text_def(x - 50, y + 120, 'r=50 empty')\n\tx += 150\n\tapp.gg.draw_slice_empty(x, y + 60, 0, start, end, app.segs, colour)\n\tapp.gg.draw_text_def(x - 50, y + 120, 'r=0 empty')\n\tx += 150\n\tapp.gg.draw_slice_filled(x, y + 60, 50, start, end, app.segs, colour)\n\tapp.gg.draw_text_def(x - 50, y + 120, 'r=50 filled')\n\tx += 150\n\tapp.gg.draw_slice_filled(x, y + 60, 0, start, end, app.segs, colour)\n\tapp.gg.draw_text_def(x - 50, y + 120, 'r=0 filled')\n\n\ty += 150\n\tx = 20\n\tapp.gg.draw_text_def(10, y + 40, 'arc_empty')\n\tx += 150\n\tapp.gg.draw_arc_empty(x, y + 60, 30, 20, start, end, app.segs, colour)\n\tapp.gg.draw_text_def(x - 50, y + 120, 'r=[30,50]')\n\tx += 150\n\tapp.gg.draw_arc_empty(x, y + 60, -10, 60, start, end, app.segs, colour)\n\tapp.gg.draw_text_def(x - 50, y + 120, 'r=[-10,50]')\n\tx += 150\n\tapp.gg.draw_arc_empty(x, y + 60, 50, 0, start, end, app.segs, colour)\n\tapp.gg.draw_text_def(x - 50, y + 120, 'r=[50,50]')\n\tx += 150\n\tapp.gg.draw_arc_empty(x, y + 60, 0, 0, start, end, app.segs, colour)\n\tapp.gg.draw_text_def(x - 50, y + 120, 'r=[0,0]')\n\n\ty += 150\n\tx = 20\n\tapp.gg.draw_text_def(10, y + 40, 'arc_filled')\n\tx += 150\n\tapp.gg.draw_arc_filled(x, y + 60, 30, 20, start, end, app.segs, colour)\n\tapp.gg.draw_text_def(x - 50, y + 120, 'r=[30,50]')\n\tx += 150\n\tapp.gg.draw_arc_filled(x, y + 60, -10, 60, start, end, app.segs, colour)\n\tapp.gg.draw_text_def(x - 50, y + 120, 'r=[-10,50]')\n\tx += 150\n\tapp.gg.draw_arc_filled(x, y + 60, 50, 0, start, end, app.segs, colour)\n\tapp.gg.draw_text_def(x - 50, y + 120, 'r=[50,50]')\n\tx += 150\n\tapp.gg.draw_arc_filled(x, y + 60, 0, 0, start, end, app.segs, colour)\n\tapp.gg.draw_text_def(x - 50, y + 120, 'r=[0,0]')\n\n\ty += 150\n\tx = 20\n\tapp.gg.draw_text_def(10, y + 40, 'arc_line')\n\tx += 150\n\tapp.gg.draw_arc_line(x, y + 60, 50, start, end, app.segs, colour)\n\tapp.gg.draw_text_def(x - 50, y + 120, 'r=50')\n\tx += 150\n\tapp.gg.draw_arc_line(x, y + 60, 0, start, end, app.segs, colour)\n\tapp.gg.draw_text_def(x - 50, y + 120, 'r=0')\n\n\ty += 150\n\tapp.gg.draw_text_def(10, y + 20, 'Use arrow keys to increase/decrease number of segments.')\n\tapp.gg.draw_text_def(10, y + 36, 'Use the mouse to adjust the start/end angles, in radians. Mouse position (0,0) is at the top-left of the window.')\n\tapp.gg.draw_text_def(10, y + 52, 'Note: because y=0 is at the top of the screen and not the bottom, angle=0 is at the bottom of an arc, not the top!')\n\tapp.gg.draw_text_def(10, y + 68, 'Compared to a graph, where y=0 is at the bottom, arcs therefore appear y-flipped.')\n\n\tapp.gg.end()\n}\n\nfn on_event(e &gg.Event, mut app App) {\n\tmatch e.typ {\n\t\t.key_down {\n\t\t\tmatch e.key_code {\n\t\t\t\t.escape {\n\t\t\t\t\tapp.gg.quit()\n\t\t\t\t}\n\t\t\t\t.up {\n\t\t\t\t\tapp.sel = unsafe { Selection(math.max(0, int(app.sel) - 1)) }\n\t\t\t\t}\n\t\t\t\t.down {\n\t\t\t\t\tapp.sel = unsafe { Selection(math.min(int(Selection.len) - 1, int(app.sel) + 1)) }\n\t\t\t\t}\n\t\t\t\t.left {\n\t\t\t\t\tmatch app.sel {\n\t\t\t\t\t\t.segs {\n\t\t\t\t\t\t\tapp.segs = math.max(1, app.segs / 2)\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t.right {\n\t\t\t\t\tmatch app.sel {\n\t\t\t\t\t\t.segs {\n\t\t\t\t\t\t\tapp.segs = math.min(64, app.segs * 2)\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {}\n\t\t\t}\n\t\t}\n\t\t.mouse_move {\n\t\t\tapp.mouse.x = e.mouse_x\n\t\t\tapp.mouse.y = e.mouse_y\n\t\t}\n\t\telse {}\n\t}\n}\n"
  },
  {
    "path": "examples/gg/bezier.v",
    "content": "module main\n\nimport gg\n\nconst points = [f32(200.0), 200.0, 200.0, 100.0, 400.0, 100.0, 400.0, 300.0]\n\nstruct App {\nmut:\n\tgg    &gg.Context = unsafe { nil }\n\tsteps int         = 30\n}\n\nfn main() {\n\tmut app := &App{}\n\tapp.gg = gg.new_context(\n\t\tbg_color:     gg.rgb(174, 198, 255)\n\t\twidth:        600\n\t\theight:       400\n\t\twindow_title: 'Cubic Bézier curve'\n\t\tframe_fn:     frame\n\t\tuser_data:    app\n\t)\n\tapp.gg.run()\n}\n\nfn (mut app App) change(delta int) {\n\tapp.steps += delta\n\tprintln('app.steps: ${app.steps}')\n}\n\nfn frame(mut app App) {\n\tapp.gg.begin()\n\tapp.gg.draw_cubic_bezier_in_steps(points, u32(app.steps), gg.blue)\n\tapp.gg.draw_cubic_bezier_recursive(points, gg.rgba(255, 50, 50, 150))\n\tapp.gg.end()\n\tif app.gg.pressed_keys[int(gg.KeyCode.down)] {\n\t\tapp.change(-1)\n\t}\n\tif app.gg.pressed_keys[int(gg.KeyCode.up)] {\n\t\tapp.change(1)\n\t}\n}\n"
  },
  {
    "path": "examples/gg/bezier_anim.v",
    "content": "module main\n\nimport gg\n\nconst rate = f32(1) / 60 * 10\n\nstruct App {\nmut:\n\tgg   &gg.Context = unsafe { nil }\n\tanim &Anim       = unsafe { nil }\n}\n\nstruct Anim {\nmut:\n\ttime    f32\n\treverse bool\n}\n\nfn (mut anim Anim) advance() {\n\tif anim.reverse {\n\t\tanim.time -= 1 * rate\n\t} else {\n\t\tanim.time += 1 * rate\n\t}\n\t// Use some arbitrary value that fits 60 fps\n\tif anim.time > 80 * rate || anim.time < -80 * rate {\n\t\tanim.reverse = !anim.reverse\n\t}\n}\n\nfn main() {\n\tmut app := &App{\n\t\tanim: &Anim{}\n\t}\n\tapp.gg = gg.new_context(\n\t\tbg_color:     gg.rgb(174, 198, 255)\n\t\twidth:        600\n\t\theight:       400\n\t\twindow_title: 'Animated cubic Bézier curve'\n\t\tframe_fn:     frame\n\t\tuser_data:    app\n\t)\n\tapp.gg.run()\n}\n\nfn frame(mut app App) {\n\ttime := app.anim.time\n\n\tp1_x := f32(200.0)\n\tp1_y := f32(200.0) + (10 * time)\n\n\tp2_x := f32(400.0)\n\tp2_y := f32(200.0) + (10 * time)\n\n\tctrl_p1_x := f32(200.0) + (40 * time)\n\tctrl_p1_y := f32(100.0)\n\tctrl_p2_x := f32(400.0) + (-40 * time)\n\tctrl_p2_y := f32(100.0)\n\n\tpoints := [p1_x, p1_y, ctrl_p1_x, ctrl_p1_y, ctrl_p2_x, ctrl_p2_y, p2_x, p2_y]\n\n\tapp.gg.begin()\n\tapp.gg.draw_cubic_bezier(points, gg.blue)\n\tapp.gg.end()\n\tapp.anim.advance()\n}\n"
  },
  {
    "path": "examples/gg/bouncing_balls.v",
    "content": "@[has_globals]\nmodule main\n\nimport gg\nimport rand\n\n__global app = App{}\n\nstruct Ball {\nmut:\n\tx     f32\n\ty     f32\n\tdx    f32\n\tdy    f32\n\tcolor gg.Color\n}\n\nstruct App {\nmut:\n\tsize  gg.Size = gg.Size{1024, 768}\n\tballs []Ball\n}\n\nfn main() {\n\tinit_app()\n\tgg.start(\n\t\twindow_title: 'Bouncing balls'\n\t\twidth:        app.size.width\n\t\theight:       app.size.height\n\t\tframe_fn:     on_frame\n\t)\n}\n\nfn on_frame(ctx &gg.Context) {\n\tapp.size = gg.window_size()\n\tif ctx.frame % 20000 == 0 {\n\t\tinit_app()\n\t}\n\tfor mut ball in app.balls {\n\t\tmove_ball(mut ball)\n\t}\n\tctx.begin()\n\tfor ball in app.balls {\n\t\tctx.draw_circle_filled(ball.x, app.size.height - ball.y, 6, ball.color)\n\t}\n\tctx.draw_text(10, 20, 'Frame: ${ctx.frame:06}', color: gg.Color{255, 255, 255, 255}, size: 20)\n\tctx.end()\n}\n\nfn init_app() {\n\tapp.balls.clear()\n\tfor _ in 0 .. 2500 {\n\t\tapp.balls << Ball{\n\t\t\tx:     rand.f32() * app.size.width\n\t\t\ty:     3 * app.size.height / 4\n\t\t\tdx:    5 * rand.f32()\n\t\t\tdy:    5 * rand.f32()\n\t\t\tcolor: gg.Color{rand.u8(), rand.u8(), rand.u8(), 255}\n\t\t}\n\t}\n}\n\n@[inline]\nfn move_ball(mut ball Ball) {\n\tball.x += ball.dx\n\tball.y += ball.dy\n\tball.dy -= 9.81 * 0.01\n\tif ball.x <= 0 || ball.x >= app.size.width - 1 {\n\t\tball.dx = -ball.dx\n\t\tapply_friction(mut ball)\n\t}\n\tif ball.y <= 0 || ball.y >= app.size.height - 1 {\n\t\tball.dy = -ball.dy\n\t\tapply_friction(mut ball)\n\t}\n\t// apply some clipping:\n\tball.x = f32_max(-5, f32_min(f32(app.size.width) * 1.3, ball.x))\n\tball.y = f32_max(-5, f32_min(f32(app.size.height) * 1.3, ball.y))\n\tball.dx = f32_max(-50, f32_min(30, ball.dx))\n\tball.dy = f32_max(-50, f32_min(30, ball.dy))\n}\n\n@[inline]\nfn apply_friction(mut ball Ball) {\n\t// apply some random friction on each bounce:\n\tball.dy *= (1 - rand.f32() * 0.1)\n\tball.dx *= (1 - rand.f32() * 0.01)\n}\n"
  },
  {
    "path": "examples/gg/cursor.v",
    "content": "module main\n\nimport gg\nimport sokol.sapp\n\nfn main() {\n\tmut ctx := gg.new_context(\n\t\tbg_color:     gg.white\n\t\twindow_title: 'Cursor'\n\t\tframe_fn:     frame\n\t\tinit_fn:      init\n\t)\n\tctx.run()\n}\n\nfn init(mut _ctx gg.Context) {\n\tsapp.set_mouse_cursor(.ibeam)\n}\n\nfn frame(mut ctx gg.Context) {\n\tctx.begin()\n\tctx.draw_text_def(10, 25, 'Your cursor should be an I shaped beam.')\n\tctx.end()\n}\n"
  },
  {
    "path": "examples/gg/digital_rain.v",
    "content": "// Creates the digital rain effect from the movie, \"The Matrix\"\nmodule main\n\nimport gg\nimport rand\nimport time\n\nconst font_size = 20\nconst rain_drops = '0123456789!@#$%^&*()-=+[]{}|;:<>?~bdjpqtvz'.bytes()\n\nstruct App {\nmut:\n\tctx          &gg.Context = unsafe { nil }\n\trows         int\n\tcols         int\n\tchar_width   int\n\tchar_height  int\n\tscreen_size  gg.Size\n\tshould_calc  bool = true\n\train_columns []RainColumn\n\tdelay        time.Duration = time.millisecond * 100\n}\n\nstruct RainColumn {\nmut:\n\tcol   int  // character based postion\n\tlen   int  // length of the rain column in characters\n\thead  int  // y position of the rain column\n\tdrops []u8 // no retained graphics in gg, store entire column\n}\n\nfn main() {\n\tmut app := &App{}\n\train(mut app)\n}\n\nfn rain(mut app App) {\n\tapp.ctx = gg.new_context(\n\t\tbg_color:     gg.rgb(0, 0, 0)\n\t\twidth:        app.screen_size.width\n\t\theight:       app.screen_size.height\n\t\tuser_data:    app\n\t\twindow_title: 'Digital Rain'\n\t\tinit_fn:      fn (mut app App) {\n\t\t\tgg.toggle_fullscreen()\n\t\t}\n\t\tevent_fn:     fn (event &gg.Event, mut app App) {\n\t\t\tvprintln('event.typ: ${event.typ} | event.char_code: ${event.char_code}')\n\t\t\tif event.typ == .resized {\n\t\t\t\tapp.should_calc = true\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif event.typ == .char && event.char_code == `f` {\n\t\t\t\tgg.toggle_fullscreen()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif event.typ == .key_up && event.key_code == .up {\n\t\t\t\tapp.delay = app.delay + 50 * time.millisecond\n\t\t\t}\n\t\t\tif event.typ == .key_up && event.key_code == .down {\n\t\t\t\tnew_delay := app.delay - 50 * time.millisecond\n\t\t\t\tapp.delay = if new_delay > 0 { new_delay } else { 0 }\n\t\t\t}\n\t\t}\n\t\tframe_fn:     frame\n\t)\n\tapp.ctx.run()\n}\n\nfn frame(mut app App) {\n\tapp.ctx.begin()\n\tif app.should_calc {\n\t\tapp.should_calc = false\n\t\tcalc_sizes(mut app)\n\t}\n\t// gradually add rain columns\n\tif app.rain_columns.len < app.cols / 4 * 3 {\n\t\tapp.rain_columns << random_rain_column(app.cols, app.rows)\n\t}\n\t// update and print all rain columns\n\tfor mut rc in app.rain_columns {\n\t\tupdate_rain_column(mut rc, app.cols, app.rows)\n\t\tdraw_rain_column(rc, app)\n\t}\n\tapp.ctx.draw_text(app.screen_size.width / 2 - 190, app.screen_size.height - 15, 'press `f` to toggle fullscreen, Up/Down arrows to change speed',\n\t\tcolor: gg.gray\n\t)\n\tapp.ctx.end()\n\tvprintln('frame: ${app.ctx.frame} | app.cols: ${app.cols} | app.rows: ${app.rows} | app.rain_columns.len: ${app.rain_columns.len} | app.delay: ${app.delay}')\n\ttime.sleep(app.delay)\n}\n\n@[if verbose ?]\nfn vprintln(msg string) {\n\tprintln(msg)\n}\n\nfn calc_sizes(mut app App) {\n\tapp.screen_size = gg.window_size()\n\tapp.ctx.set_text_cfg(gg.TextCfg{\n\t\tsize:  font_size\n\t\tcolor: gg.green\n\t\tmono:  true\n\t})\n\t// figure out how big character is in pixels\n\t// Pad it or it looks too squashed\n\tapp.char_width, app.char_height = app.ctx.text_size('M')\n\tapp.char_width += 3\n\tapp.char_height += 1\n\t// determine the size of the matrix in rows and columns\n\tapp.cols = app.screen_size.width / app.char_width\n\tapp.rows = app.screen_size.height / app.char_height\n\tvprintln('app.cols: ${app.cols} | app.rows: ${app.rows}')\n}\n\nfn update_rain_column(mut rc RainColumn, width int, height int) {\n\trc.head += 1\n\tif rc.head > height + rc.len {\n\t\trc = random_rain_column(width, height)\n\t}\n}\n\nfn draw_rain_column(rc RainColumn, app App) {\n\tmut y := 0\n\tx := rc.col * app.char_width\n\tend := rc.head - rc.len\n\tfor i in 0 .. app.rows - 1 {\n\t\tif i >= end && i < rc.head {\n\t\t\talpha := match i - end {\n\t\t\t\t0 { u8(75) }\n\t\t\t\t1 { u8(100) }\n\t\t\t\t2 { u8(125) }\n\t\t\t\t3 { u8(150) }\n\t\t\t\t4 { u8(175) }\n\t\t\t\t5 { u8(200) }\n\t\t\t\t6 { u8(225) }\n\t\t\t\telse { u8(255) }\n\t\t\t}\n\t\t\tat_head := i == rc.head - 1\n\t\t\tcfg := gg.TextCfg{\n\t\t\t\tsize:  font_size\n\t\t\t\tcolor: gg.Color{\n\t\t\t\t\tr: if at_head { u8(255) } else { 0 }\n\t\t\t\t\tg: 255\n\t\t\t\t\tb: if at_head { u8(255) } else { 0 }\n\t\t\t\t\ta: alpha\n\t\t\t\t}\n\t\t\t\tmono:  true\n\t\t\t}\n\t\t\tif i < rc.drops.len {\n\t\t\t\tapp.ctx.draw_text(x, y, rc.drops[i].ascii_str(), cfg)\n\t\t\t\tapp.ctx.draw_text(x, y, rc.drops[(i + 10) % rc.drops.len].ascii_str(),\n\t\t\t\t\tcfg)\n\t\t\t} else {\n\t\t\t\tvprintln('BAD i: ${i} | rc.drops.len: ${rc.drops.len}')\n\t\t\t}\n\t\t}\n\t\ty += app.char_height\n\t}\n}\n\nfn random_rain_column(max_col int, max_height int) RainColumn {\n\tmin_len := 6\n\tmut rc := RainColumn{\n\t\tcol:   rand.int_in_range(0, max_col) or { 0 }\n\t\tlen:   rand.int_in_range(min_len, max_height / 4 * 3) or { min_len }\n\t\tdrops: []u8{cap: max_height}\n\t}\n\tfor _ in 0 .. max_height {\n\t\trc.drops << random_rain_drop()\n\t}\n\treturn rc\n}\n\nfn random_rain_drop() u8 {\n\treturn rand.element(rain_drops) or { rain_drops[0] }\n}\n"
  },
  {
    "path": "examples/gg/drag_n_drop.v",
    "content": "module main\n\nimport gg\nimport sokol.sapp\n\nconst max_files = 12\nconst text_size = 16\n\nstruct App {\nmut:\n\tgg                &gg.Context = unsafe { nil }\n\tdropped_file_list []string\n}\n\nfn main() {\n\tmut app := &App{}\n\tapp.gg = gg.new_context(\n\t\tbg_color:     gg.rgb(174, 198, 255)\n\t\twidth:        600\n\t\theight:       400\n\t\twindow_title: 'Drag and drop'\n\t\tframe_fn:     frame\n\t\tuser_data:    app\n\t\tevent_fn:     my_event_manager\n\t\t// drag & drop\n\t\tenable_dragndrop:             true\n\t\tmax_dropped_files:            max_files\n\t\tmax_dropped_file_path_length: 2048\n\t)\n\tapp.gg.run()\n}\n\nfn my_event_manager(mut ev gg.Event, mut app App) {\n\t// drag&drop event\n\tif ev.typ == .files_dropped {\n\t\tnum_dropped := sapp.get_num_dropped_files()\n\t\tapp.dropped_file_list.clear()\n\t\tfor i in 0 .. num_dropped {\n\t\t\tapp.dropped_file_list << sapp.get_dropped_file_path(i)\n\t\t}\n\t}\n}\n\nfn frame(mut app App) {\n\tapp.gg.begin()\n\n\tmut txt_conf := gg.TextCfg{\n\t\tcolor: gg.black\n\t\talign: .left\n\t\tsize:  int(text_size * app.gg.scale + 0.5)\n\t}\n\tapp.gg.draw_text(12, 12, 'Drag&Drop here max ${max_files} files.', txt_conf)\n\n\tmut y := 40\n\tfor c, f in app.dropped_file_list {\n\t\tapp.gg.draw_text(12, y, '[${c}] ${f}', txt_conf)\n\t\ty += text_size\n\t}\n\n\tapp.gg.end()\n}\n"
  },
  {
    "path": "examples/gg/draw_pixels.v",
    "content": "module main\n\nimport gg\n\nstruct App {\nmut:\n\tgg     &gg.Context = unsafe { nil }\n\tpixels []f32\n}\n\nfn main() {\n\tmut pixels := []f32{}\n\tdensity := 4\n\tfor x in 30 .. 60 {\n\t\tif x % density == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tfor y in 30 .. 60 {\n\t\t\tif y % density == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpixels << f32(x + density)\n\t\t\tpixels << f32(y + density)\n\t\t}\n\t}\n\tmut app := &App{\n\t\tpixels: pixels\n\t}\n\tapp.gg = gg.new_context(\n\t\tbg_color:     gg.rgb(174, 198, 255)\n\t\twidth:        100\n\t\theight:       100\n\t\twindow_title: 'Set Pixels'\n\t\tframe_fn:     frame\n\t\tuser_data:    app\n\t)\n\tapp.gg.run()\n}\n\nfn frame(mut app App) {\n\tapp.gg.begin()\n\n\t// Draw a blue pixel near each corner. (Find your magnifying glass)\n\tapp.gg.draw_pixel(2, 2, gg.blue)\n\tapp.gg.draw_pixel(app.gg.width - 2, 2, gg.blue)\n\tapp.gg.draw_pixel(app.gg.width - 2, app.gg.height - 2, gg.blue)\n\tapp.gg.draw_pixel(2, app.gg.height - 2, gg.blue)\n\n\t// Draw pixels in a grid-like pattern.\n\tapp.gg.draw_pixels(app.pixels, gg.red)\n\tapp.gg.end()\n}\n"
  },
  {
    "path": "examples/gg/draw_unicode_text_with_gg.v",
    "content": "import os\nimport gg\n\nprintln('Usage: `v run examples/gg/draw_unicode_text_with_gg.v [FONT_PATH] [TEXT_PATH]`')\n\nfont_path := os.args[1] or {\n\tos.resource_abs_path(os.join_path('..', 'assets', 'fonts', 'RobotoMono-Regular.ttf'))\n}\ndump(font_path)\n\ntext_path := os.args[2] or {\n\tos.resource_abs_path(os.join_path('..', 'ttf_font/draw_static_text.txt'))\n}\ndump(text_path)\n\ntext := os.read_file(text_path)!\ndump(text)\n\ngg.start(\n\twindow_title: 'Draw unicode text with gg'\n\tbg_color:     gg.Color{155, 155, 128, 255}\n\twidth:        1024\n\theight:       140\n\tfont_path:    font_path\n\tframe_fn:     fn [text] (ctx &gg.Context) {\n\t\tctx.begin()\n\t\tctx.draw_text(30, 50, text,\n\t\t\tsize:  24\n\t\t\tcolor: gg.Color{50, 50, 255, 255}\n\t\t)\n\t\tctx.end()\n\t}\n)\n"
  },
  {
    "path": "examples/gg/easing_animation.v",
    "content": "module main\n\nimport gg\nimport math.easing\n\nconst all = {\n\t'in_functions':     {\n\t\t'linear':     voidptr(easing.linear)\n\t\t'in_sine':    easing.in_sine\n\t\t'in_quad':    easing.in_quad\n\t\t'in_cubic':   easing.in_cubic\n\t\t'in_quart':   easing.in_quart\n\t\t'in_quint':   easing.in_quint\n\t\t'in_expo':    easing.in_expo\n\t\t'in_circ':    easing.in_circ\n\t\t'in_back':    easing.in_back\n\t\t'in_elastic': easing.in_elastic\n\t\t'in_bounce':  easing.in_bounce\n\t}\n\t'out_functions':    {\n\t\t'linear':      voidptr(easing.linear)\n\t\t'out_sine':    easing.out_sine\n\t\t'out_quad':    easing.out_quad\n\t\t'out_cubic':   easing.out_cubic\n\t\t'out_quart':   easing.out_quart\n\t\t'out_quint':   easing.out_quint\n\t\t'out_expo':    easing.out_expo\n\t\t'out_circ':    easing.out_circ\n\t\t'out_back':    easing.out_back\n\t\t'out_elastic': easing.out_elastic\n\t\t'out_bounce':  easing.out_bounce\n\t}\n\t'in_out_functions': {\n\t\t'linear':         voidptr(easing.linear)\n\t\t'in_out_sine':    easing.in_out_sine\n\t\t'in_out_quad':    easing.in_out_quad\n\t\t'in_out_cubic':   easing.in_out_cubic\n\t\t'in_out_quart':   easing.in_out_quart\n\t\t'in_out_quint':   easing.in_out_quint\n\t\t'in_out_expo':    easing.in_out_expo\n\t\t'in_out_circ':    easing.in_out_circ\n\t\t'in_out_back':    easing.in_out_back\n\t\t'in_out_elastic': easing.in_out_elastic\n\t\t'in_out_bounce':  easing.in_out_bounce\n\t}\n}\nconst all_keys = all.keys()\n\n@[heap]\nstruct App {\nmut:\n\tgg   &gg.Context = unsafe { nil }\n\tx    f64\n\tt    f64\n\th    f64\n\tkind string = all_keys.first()\n}\n\nfn (mut app App) draw_circle(label string, f easing.EasingFN) {\n\toffset := 30\n\tapp.gg.draw_text_def(int(app.x) - 30, 5, label)\n\tapp.gg.draw_line(f32(app.x), offset, f32(app.x), f32(app.h + offset), gg.gray)\n\tapp.gg.draw_circle_filled(f32(app.x), f32(offset + f(app.t) * app.h), 10, gg.rgb(0,\n\t\t0, 255))\n\tapp.x += 120\n}\n\nfn (mut app App) frame() {\n\tsize := gg.window_size()\n\tperiod := u64(240)\n\tapp.t = f32_min(1.0, f32(app.gg.frame % period) / f32(period - 30))\n\tapp.x = 80\n\tapp.h = size.height - 100\n\tapp.gg.begin()\n\tapp.gg.draw_line(0, f32(app.h + 30), size.width, f32(app.h + 30), gg.gray)\n\tcurrent_map := unsafe { all[app.kind].clone() }\n\tfor k, e in current_map {\n\t\tapp.draw_circle(k, e)\n\t}\n\tapp.gg.draw_text_def(50, int(app.h + 50), 'Note: use left and right arrows to change functions. Frame: ${app.gg.frame:010} | t: ${app.t:6.3f} | kind: ${app.kind}.')\n\tapp.gg.end()\n}\n\nfn (mut app App) change_functions(direction int) {\n\tidx := (all_keys.len + all_keys.index(app.kind) + direction) % all_keys.len\n\tapp.kind = all_keys[idx]\n}\n\nfn (mut app App) on_event(ev &gg.Event, _x voidptr) {\n\tif ev.typ != .key_down {\n\t\treturn\n\t}\n\tif ev.key_code == .left {\n\t\tapp.change_functions(-1)\n\t} else if ev.key_code == .right {\n\t\tapp.change_functions(1)\n\t}\n}\n\nmut app := &App{}\napp.gg = gg.new_context(\n\tbg_color:     gg.rgb(174, 198, 255)\n\twidth:        1350\n\theight:       800\n\twindow_title: 'Easing functions'\n\tframe_fn:     app.frame\n\tevent_fn:     app.on_event\n\tuser_data:    app\n)\napp.gg.run()\n"
  },
  {
    "path": "examples/gg/expanding_rect.v",
    "content": "import gg\n\nmut r := &gg.Rect{20, 20, 60, 20}\ngg.start(\n\tupdate_fn: fn [mut r] (dt f32, c &gg.Context) {\n\t\tr.width++\n\t\tr.height++\n\t}\n\tframe_fn:  fn [mut r] (c &gg.Context) {\n\t\tc.begin()\n\t\tc.draw_rect_filled(r.x, r.y, r.width, r.height, gg.frgb(0.0, 0.4, 0.4))\n\t\tc.end()\n\t}\n)\n"
  },
  {
    "path": "examples/gg/fire.v",
    "content": "// Use `v -d show_fps run examples/gg/fire.v` to show a fire effect with an FPS counter.\nimport gg\nimport rand\n\nconst win_width = 800\nconst win_height = 600\nconst width = 100\nconst height = 140\nconst scale = 4\nconst palette = [\n\tgg.rgb(0x07, 0x07, 0x07),\n\tgg.rgb(0x1f, 0x07, 0x07),\n\tgg.rgb(0x2f, 0x0f, 0x07),\n\tgg.rgb(0x47, 0x0f, 0x07),\n\tgg.rgb(0x57, 0x17, 0x07),\n\tgg.rgb(0x67, 0x1f, 0x07),\n\tgg.rgb(0x77, 0x1f, 0x07),\n\tgg.rgb(0x8f, 0x27, 0x07),\n\tgg.rgb(0x9f, 0x2f, 0x07),\n\tgg.rgb(0xaf, 0x3f, 0x07),\n\tgg.rgb(0xbf, 0x47, 0x07),\n\tgg.rgb(0xc7, 0x47, 0x07),\n\tgg.rgb(0xdf, 0x4f, 0x07),\n\tgg.rgb(0xdf, 0x57, 0x07),\n\tgg.rgb(0xdf, 0x57, 0x07),\n\tgg.rgb(0xd7, 0x5f, 0x07),\n\tgg.rgb(0xd7, 0x5f, 0x07),\n\tgg.rgb(0xd7, 0x67, 0x0f),\n\tgg.rgb(0xcf, 0x6f, 0x0f),\n\tgg.rgb(0xcf, 0x77, 0x0f),\n\tgg.rgb(0xcf, 0x7f, 0x0f),\n\tgg.rgb(0xcf, 0x87, 0x17),\n\tgg.rgb(0xc7, 0x87, 0x17),\n\tgg.rgb(0xc7, 0x8f, 0x17),\n\tgg.rgb(0xc7, 0x97, 0x1f),\n\tgg.rgb(0xbf, 0x9f, 0x1f),\n\tgg.rgb(0xbf, 0x9f, 0x1f),\n\tgg.rgb(0xbf, 0xa7, 0x27),\n\tgg.rgb(0xbf, 0xa7, 0x27),\n\tgg.rgb(0xbf, 0xaf, 0x2f),\n\tgg.rgb(0xb7, 0xaf, 0x2f),\n\tgg.rgb(0xb7, 0xb7, 0x2f),\n\tgg.rgb(0xb7, 0xb7, 0x37),\n\tgg.rgb(0xcf, 0xcf, 0x6f),\n\tgg.rgb(0xdf, 0xdf, 0x9f),\n\tgg.rgb(0xef, 0xef, 0xc7),\n\tgg.rgb(0xff, 0xff, 0xff),\n]!\n\nstruct App {\nmut:\n\tgg    &gg.Context = unsafe { nil }\n\tbuf   [][]int\n\tdying bool\n\ttiles int\n}\n\nfn main() {\n\tmut app := &App{\n\t\tbuf: [][]int{len: height - 1, init: []int{len: width}}\n\t}\n\tapp.buf << []int{len: width, init: 36} // white fire base\n\n\tapp.gg = gg.new_context(\n\t\tevent_fn:     event\n\t\tframe_fn:     frame\n\t\tinit_fn:      retile\n\t\twindow_title: 'Fire Animation'\n\t\tuser_data:    app\n\t\tbg_color:     palette[0]\n\t\twidth:        win_width\n\t\theight:       win_height\n\t)\n\tapp.gg.run()\n}\n\nfn retile(mut app App) {\n\tsize := app.gg.window_size()\n\tapp.tiles = size.width / (width * scale) + 1\n}\n\nfn (mut app App) draw() {\n\tsize := app.gg.window_size()\n\tfor t in 0 .. app.tiles {\n\t\tapp.gg.begin()\n\t\tfor y, row in app.buf {\n\t\t\tfor x, i in row {\n\t\t\t\tapp.gg.draw_square_filled(t * width * scale + x * scale,\n\t\t\t\t\t(size.height - height * scale) + y * scale, scale, palette[i])\n\t\t\t}\n\t\t}\n\t\tapp.gg.end(\n\t\t\thow: if t == 0 { .clear } else { .passthru }\n\t\t)\n\t\t// one pass per tile to avoid sgl vertex limit\n\t}\n}\n\n@[direct_array_access]\nfn (mut app App) tick() {\n\tfor x in 0 .. width {\n\t\tfor y in 1 .. height {\n\t\t\tif app.buf[y][x] > 0 {\n\t\t\t\tr := rand.intn(4) or { panic('failed to generate random number') }\n\t\t\t\txn := ((x - r + 1) % width + width) % width\n\t\t\t\tapp.buf[y - 1][xn] = app.buf[y][x] - r % 2\n\t\t\t} else {\n\t\t\t\tapp.buf[y - 1][x] = 0\n\t\t\t}\n\t\t}\n\t}\n\tif app.dying {\n\t\tfor x in 0 .. width {\n\t\t\ty := height - 1\n\t\t\tapp.buf[y][x] -= rand.intn(4) or { panic('failed to generate random number') }\n\t\t\tif app.buf[y][x] < 0 {\n\t\t\t\tapp.buf[y][x] = 0\n\t\t\t}\n\t\t}\n\t}\n}\n\nfn event(event &gg.Event, mut app App) {\n\tmatch event.typ {\n\t\t.key_up {\n\t\t\tmatch event.key_code {\n\t\t\t\t.space {\n\t\t\t\t\tif app.dying {\n\t\t\t\t\t\tapp.dying = false\n\t\t\t\t\t\tapp.buf[height - 1] = []int{len: width, init: 36}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tapp.dying = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {}\n\t\t\t}\n\t\t}\n\t\t.resized {\n\t\t\tretile(mut app)\n\t\t}\n\t\telse {}\n\t}\n}\n\nfn frame(mut app App) {\n\tapp.draw()\n\tapp.tick()\n}\n"
  },
  {
    "path": "examples/gg/grid_of_rectangles.v",
    "content": "module main\n\nimport gg\nimport sokol.sgl\n\nstruct App {\nmut:\n\tgg &gg.Context = unsafe { nil }\n}\n\nconst cmax_x = 115\nconst cmax_y = 81\nconst cs = 10\n\nconst c_fg = gg.rgb(20, 30, 255)\nconst c_em = gg.rgb(255, 50, 0)\n\nfn main() {\n\tmut app := &App{}\n\tapp.gg = gg.new_context(\n\t\tbg_color:      gg.white\n\t\twidth:         cmax_x * cs\n\t\theight:        cmax_y * cs\n\t\tcreate_window: true\n\t\twindow_title:  'Grid with many rectangles (drawn with no context)'\n\t\tframe_fn:      frame\n\t\tuser_data:     app\n\t)\n\tapp.gg.run()\n}\n\nfn frame(app &App) {\n\tapp.gg.begin()\n\t// Note: this uses 2 separate loops, with each doing its own drawing for performance reasons.\n\t// The underlying Sokol library can eliminate sgl begin/end calls, when multiple primitives of the\n\t// same kind are drawn one after the other, without context changes.\n\t// However, filled rectangles are drawn with quads, while empty rectangles are drawn with lines.\n\t// In this case, if the draw calls are put in the same loop, using app.gg.draw_rect_filled/5 and app.gg.draw_rect_empty/5,\n\t// sokol can not batch the begin/end calls, and their overhead becomes much bigger.\n\t//\n\t// That is why:\n\t// a) we use several loops here.\n\t// b) we use a single sgl.begin_quads() before the first loop, and a single sgl.end() after it.\n\t// c) we use draw_rect_filled_no_context/5 inside the loop, instead of draw_rect_filled/5 .\n\t// e) we use a single sgl.begin_lines() before the second loop, and a single sgl.end() after it.\n\t// f) we use draw_rect_empty_no_context/5 inside the second loop, instead of draw_rect_empty/5 .\n\t// Note: the separation of the loops/kinds of draws, is several times more important for eliminating\n\t// the performance overhead (12-15% CPU usage), compared to the use of draw_rect_filled_no_context\n\t// vs draw_rect_filled (1-2% CPU usage), because of Sokol's optimisation.\n\n\t$if !do_not_draw_rect_filled ? {\n\t\tsgl.begin_quads()\n\t\tfor y in 0 .. cmax_y {\n\t\t\tfor x in 0 .. cmax_x {\n\t\t\t\tcy, cx := y * cs, x * cs\n\t\t\t\tapp.gg.draw_rect_filled_no_context(cx, cy, cs - 2, cs - 2, c_fg)\n\t\t\t}\n\t\t}\n\t\tsgl.end()\n\t}\n\n\t$if draw_rect_empty ? {\n\t\tsgl.begin_lines()\n\t\tfor y in 0 .. cmax_y {\n\t\t\tfor x in 0 .. cmax_x {\n\t\t\t\tcy, cx := y * cs, x * cs\n\t\t\t\tapp.gg.draw_rect_empty_no_context(cx + 2, cy + 2, cs - 3, cs - 3, c_em)\n\t\t\t}\n\t\t}\n\t\tsgl.end()\n\t}\n\n\tapp.gg.end()\n}\n"
  },
  {
    "path": "examples/gg/mandelbrot.v",
    "content": "import gg\nimport runtime\nimport time\n\nconst pwidth = 800\n\nconst pheight = 600\n\nconst chunk_height = 2 // the image is recalculated in chunks, each chunk processed in a separate thread\n\nconst zoom_factor = 1.1\n\nconst max_iterations = 255\n\nstruct ViewRect {\nmut:\n\tx_min f64\n\tx_max f64\n\ty_min f64\n\ty_max f64\n}\n\nfn (v &ViewRect) width() f64 {\n\treturn v.x_max - v.x_min\n}\n\nfn (v &ViewRect) height() f64 {\n\treturn v.y_max - v.y_min\n}\n\nstruct AppState {\nmut:\n\tgg      &gg.Context = unsafe { nil }\n\tiidx    int\n\tpixels  &u32     = unsafe { vcalloc(pwidth * pheight * sizeof(u32)) }\n\tnpixels &u32     = unsafe { vcalloc(pwidth * pheight * sizeof(u32)) } // all drawing happens here, results are swapped at the end\n\tview    ViewRect = ViewRect{-3.0773593290970673, 1.4952456603855397, -2.019938598189011, 2.3106642054225945}\n\tscale   int      = 1\n\tntasks  int      = runtime.nr_jobs()\n}\n\nconst colors = [gg.black, gg.blue, gg.red, gg.green, gg.yellow, gg.orange, gg.purple, gg.white,\n\tgg.indigo, gg.violet, gg.black, gg.blue, gg.orange, gg.yellow, gg.green].map(u32(it.abgr8()))\n\nstruct MandelChunk {\n\tcview ViewRect\n\tymin  f64\n\tymax  f64\n}\n\nfn (mut state AppState) update() {\n\tmut chunk_channel := chan MandelChunk{cap: state.ntasks}\n\tmut chunk_ready_channel := chan bool{cap: 1000}\n\tmut threads := []thread{cap: state.ntasks}\n\tdefer {\n\t\tchunk_channel.close()\n\t\tthreads.wait()\n\t}\n\tfor t in 0 .. state.ntasks {\n\t\tthreads << spawn state.worker(t, chunk_channel, chunk_ready_channel)\n\t}\n\n\tmut oview := ViewRect{}\n\tmut sw := time.new_stopwatch()\n\tfor {\n\t\tsw.restart()\n\t\tcview := state.view\n\t\tif oview == cview {\n\t\t\ttime.sleep(5 * time.millisecond)\n\t\t\tcontinue\n\t\t}\n\t\t// schedule chunks, describing the work:\n\t\tmut nchunks := 0\n\t\tfor start := 0; start < pheight; start += chunk_height {\n\t\t\tchunk_channel <- MandelChunk{\n\t\t\t\tcview: cview\n\t\t\t\tymin:  start\n\t\t\t\tymax:  start + chunk_height\n\t\t\t}\n\t\t\tnchunks++\n\t\t}\n\t\t// wait for all chunks to be processed:\n\t\tfor _ in 0 .. nchunks {\n\t\t\t_ := <-chunk_ready_channel\n\t\t}\n\t\t// everything is done, swap the buffer pointers\n\t\tstate.pixels, state.npixels = state.npixels, state.pixels\n\t\tprintln('${state.ntasks:2} threads; ${sw.elapsed().milliseconds():3} ms / frame; scale: ${state.scale:4}')\n\t\toview = cview\n\t}\n}\n\n@[direct_array_access]\nfn (mut state AppState) worker(_id int, input chan MandelChunk, ready chan bool) {\n\tfor {\n\t\tchunk := <-input or { break }\n\t\tyscale := chunk.cview.height() / pheight\n\t\txscale := chunk.cview.width() / pwidth\n\t\tmut x, mut y, mut iter := 0.0, 0.0, 0\n\t\tmut y0 := chunk.ymin * yscale + chunk.cview.y_min\n\t\tmut x0 := chunk.cview.x_min\n\t\tfor y_pixel := chunk.ymin; y_pixel < chunk.ymax && y_pixel < pheight; y_pixel++ {\n\t\t\tyrow := unsafe { &state.npixels[int(y_pixel * pwidth)] }\n\t\t\ty0 += yscale\n\t\t\tx0 = chunk.cview.x_min\n\t\t\tfor x_pixel := 0; x_pixel < pwidth; x_pixel++ {\n\t\t\t\tx0 += xscale\n\t\t\t\tx, y = x0, y0\n\t\t\t\tfor iter = 0; iter < max_iterations; iter++ {\n\t\t\t\t\tx, y = x * x - y * y + x0, 2 * x * y + y0\n\t\t\t\t\tif x * x + y * y > 4 {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tunsafe {\n\t\t\t\t\tyrow[x_pixel] = colors[iter & 15]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tready <- true\n\t}\n}\n\nfn (mut state AppState) draw() {\n\tmut istream_image := state.gg.get_cached_image_by_idx(state.iidx)\n\tistream_image.update_pixel_data(unsafe { &u8(state.pixels) })\n\tsize := gg.window_size()\n\tstate.gg.draw_image(0, 0, size.width, size.height, istream_image)\n}\n\nfn (mut state AppState) zoom(zoom_factor f64) {\n\tc_x, c_y := (state.view.x_max + state.view.x_min) / 2, (state.view.y_max + state.view.y_min) / 2\n\td_x, d_y := c_x - state.view.x_min, c_y - state.view.y_min\n\tstate.view.x_min = c_x - zoom_factor * d_x\n\tstate.view.x_max = c_x + zoom_factor * d_x\n\tstate.view.y_min = c_y - zoom_factor * d_y\n\tstate.view.y_max = c_y + zoom_factor * d_y\n\tstate.scale += if zoom_factor < 1 { 1 } else { -1 }\n}\n\nfn (mut state AppState) center(s_x f64, s_y f64) {\n\tc_x, c_y := (state.view.x_max + state.view.x_min) / 2, (state.view.y_max + state.view.y_min) / 2\n\td_x, d_y := c_x - state.view.x_min, c_y - state.view.y_min\n\tstate.view.x_min = s_x - d_x\n\tstate.view.x_max = s_x + d_x\n\tstate.view.y_min = s_y - d_y\n\tstate.view.y_max = s_y + d_y\n}\n\n// gg callbacks:\n\nfn graphics_init(mut state AppState) {\n\tstate.iidx = state.gg.new_streaming_image(pwidth, pheight, 4, pixel_format: .rgba8)\n}\n\nfn graphics_frame(mut state AppState) {\n\tstate.gg.begin()\n\tstate.draw()\n\tstate.gg.end()\n}\n\nfn graphics_click(x f32, y f32, btn gg.MouseButton, mut state AppState) {\n\tif btn == .right {\n\t\tsize := gg.window_size()\n\t\tm_x := (x / size.width) * state.view.width() + state.view.x_min\n\t\tm_y := (y / size.height) * state.view.height() + state.view.y_min\n\t\tstate.center(m_x, m_y)\n\t}\n}\n\nfn graphics_move(_x f32, _y f32, mut state AppState) {\n\tif state.gg.mouse_buttons.has(.left) {\n\t\tsize := gg.window_size()\n\t\td_x := (f64(state.gg.mouse_dx) / size.width) * state.view.width()\n\t\td_y := (f64(state.gg.mouse_dy) / size.height) * state.view.height()\n\t\tstate.view.x_min -= d_x\n\t\tstate.view.x_max -= d_x\n\t\tstate.view.y_min -= d_y\n\t\tstate.view.y_max -= d_y\n\t}\n}\n\nfn graphics_scroll(e &gg.Event, mut state AppState) {\n\tstate.zoom(if e.scroll_y < 0 { zoom_factor } else { 1 / zoom_factor })\n}\n\nfn graphics_keydown(code gg.KeyCode, _mod gg.Modifier, mut state AppState) {\n\ts_x := state.view.width() / 5\n\ts_y := state.view.height() / 5\n\t// movement\n\tmut d_x, mut d_y := 0.0, 0.0\n\tif code == .enter {\n\t\tprintln('> ViewRect{${state.view.x_min}, ${state.view.x_max}, ${state.view.y_min}, ${state.view.y_max}}')\n\t}\n\tif state.gg.pressed_keys[int(gg.KeyCode.left)] {\n\t\td_x -= s_x\n\t}\n\tif state.gg.pressed_keys[int(gg.KeyCode.right)] {\n\t\td_x += s_x\n\t}\n\tif state.gg.pressed_keys[int(gg.KeyCode.up)] {\n\t\td_y -= s_y\n\t}\n\tif state.gg.pressed_keys[int(gg.KeyCode.down)] {\n\t\td_y += s_y\n\t}\n\tstate.view.x_min += d_x\n\tstate.view.x_max += d_x\n\tstate.view.y_min += d_y\n\tstate.view.y_max += d_y\n\t// zoom in/out\n\tif state.gg.pressed_keys[int(gg.KeyCode.left_bracket)]\n\t\t|| state.gg.pressed_keys[int(gg.KeyCode.z)] {\n\t\tstate.zoom(1 / zoom_factor)\n\t\treturn\n\t}\n\tif state.gg.pressed_keys[int(gg.KeyCode.right_bracket)]\n\t\t|| state.gg.pressed_keys[int(gg.KeyCode.x)] {\n\t\tstate.zoom(zoom_factor)\n\t\treturn\n\t}\n}\n\nfn main() {\n\tmut state := &AppState{}\n\tstate.gg = gg.new_context(\n\t\twidth:         800\n\t\theight:        600\n\t\tcreate_window: true\n\t\twindow_title:  'The Mandelbrot Set'\n\t\tinit_fn:       graphics_init\n\t\tframe_fn:      graphics_frame\n\t\tclick_fn:      graphics_click\n\t\tmove_fn:       graphics_move\n\t\tkeydown_fn:    graphics_keydown\n\t\tscroll_fn:     graphics_scroll\n\t\tuser_data:     state\n\t)\n\tspawn state.update()\n\tstate.gg.run()\n}\n"
  },
  {
    "path": "examples/gg/many_thousands_of_circles.v",
    "content": "module main\n\nimport gg\nimport rand\n\nconst max_circles_per_pass = 1000\n\n// prepare some random colors ahead of time\nconst colors = []gg.Color{len: max_circles_per_pass, init: gg.Color{\n\tr: u8(index * 0 + rand.u8())\n\tg: u8(index * 0 + rand.u8())\n\tb: u8(index * 0 + rand.u8())\n}}\n\nfn frame(mut ctx gg.Context) {\n\t// First pass, just clears the background:\n\tctx.begin()\n\tctx.end()\n\n\t// We want to draw thousands of circles, but sokol has a limit for how\n\t// many primitives can be in a single pass, and if you reach that limit\n\t// you will not see *anything at all* for that pass.\n\t// For the circles below, that limit is ~2520 circles per pass.\n\t// To overcome this, we will use several passes instead, where each one\n\t// will draw just 1000 circles.\n\t// In other words, in total we will have 4 * 1000 = 4000 circles, drawn with\n\t// 4 passes.\n\tfor i := 0; i < 4 * max_circles_per_pass; i += max_circles_per_pass {\n\t\tctx.begin()\n\t\tfor c in 0 .. max_circles_per_pass {\n\t\t\trx := rand.int_in_range(0, ctx.window.width) or { 0 }\n\t\t\try := rand.int_in_range(0, ctx.window.height) or { 0 }\n\t\t\tctx.draw_circle_filled(rx, ry, 10, colors[c])\n\t\t}\n\t\tctx.end(how: .passthru)\n\t}\n\n\t// The last pass, is for the fps overlay, that should be *always on top of everything*.\n\t// Drawing it in a separate pass, guarantees, that it *will* be drawn, even if the drawing\n\t// of all the other passes fail. Try increasing max_circles_per_pass to 3000 for example.\n\tctx.begin()\n\tctx.show_fps()\n\tctx.end(how: .passthru)\n}\n\nfn main() {\n\tmut ctx := gg.new_context(\n\t\twindow_title: 'Many Thousands of Circles'\n\t\tbg_color:     gg.black\n\t\twidth:        600\n\t\theight:       400\n\t\tframe_fn:     frame\n\t)\n\tctx.run()\n}\n"
  },
  {
    "path": "examples/gg/many_thousands_of_circles_overriding_max_vertices.v",
    "content": "import gg\nimport rand\n\n// The flags here override the default limits for Sokol\n#flag -D_SGL_DEFAULT_MAX_VERTICES=4194304\n#flag -D_SGL_DEFAULT_MAX_COMMANDS=65536\n\n// Without the flags, `max_circles` > 5040, will just show a blue screen without\n// *any circles* drawn.\n// **Note** however, that increasing `_SGL_DEFAULT_MAX_VERTICES`, also increases\n// the default RAM usage of your app. In this case, instead of using ~40MB on\n// Ubuntu 20.04, the app instead uses ~140MB.\nconst max_circles = 10_000\n\nfn main() {\n\tgg.start(\n\t\twindow_title: 'Hello'\n\t\tbg_color:     gg.Color{50, 50, 150, 255}\n\t\twidth:        800\n\t\theight:       600\n\t\tframe_fn:     fn (ctx &gg.Context) {\n\t\t\twsize := gg.window_size()\n\t\t\tctx.begin()\n\t\t\tfor _ in 0 .. max_circles {\n\t\t\t\trx := rand.int_in_range(0, wsize.width) or { 0 }\n\t\t\t\try := rand.int_in_range(0, wsize.height) or { 0 }\n\t\t\t\tcr := rand.u8()\n\t\t\t\tcg := rand.u8()\n\t\t\t\tcb := rand.u8()\n\t\t\t\tctx.draw_circle_filled(rx, ry, 10, gg.Color{cr, cg, cb, 255})\n\t\t\t}\n\t\t\tctx.show_fps()\n\t\t\tctx.end()\n\t\t}\n\t)\n}\n"
  },
  {
    "path": "examples/gg/memory.v",
    "content": "module main\n\nimport gg\nimport rand\nimport time\n\nconst cover = gg.rgba(85, 200, 85, 255)\nconst csize = 120 // cell size in pixels\nconst letters = 'AABBOOCCVVXXYYZZMMKKHHTT'.split('')\nconst header_size = 30\n\nstruct Cell {\nmut:\n\tis_open bool\n\tletter  string\n}\n\nstruct Game {\nmut:\n\tctx       &gg.Context = unsafe { nil }\n\tcells     []Cell\n\tcard1_idx ?int\n\tcard2_idx ?int\n\tsize      int // in cells\n\tremaining int\n\tsw        time.StopWatch = time.new_stopwatch()\n\trevert_sw time.StopWatch = time.new_stopwatch(auto_start: false)\n}\n\nfn (mut g Game) restart() {\n\tncells := g.size * g.size\n\tg.remaining = ncells\n\tg.cells = []Cell{len: ncells, init: Cell{\n\t\tletter: letters[index % letters.len]\n\t}}\n\trand.shuffle(mut g.cells) or {}\n\tg.sw = time.new_stopwatch()\n\tg.card1_idx = none\n\tg.card2_idx = none\n}\n\nfn (mut g Game) draw_cell(i int) {\n\tx, y := i % g.size, i / g.size\n\trect_x, rect_y := x * csize, header_size + y * csize\n\tif g.cells[i].is_open || g.sw.elapsed().milliseconds() <= 1000 {\n\t\tlsize := 96\n\t\tg.ctx.draw_rect_empty(rect_x + 6, rect_y + 6, csize - 10, csize - 10, gg.light_gray)\n\t\tg.ctx.draw_text(rect_x + csize / 2 - lsize / 3, rect_y + csize / 2 - lsize / 2,\n\t\t\tg.cells[i].letter, color: gg.yellow, size: lsize)\n\t} else {\n\t\tg.ctx.draw_rect_filled(rect_x + 6, rect_y + 6, csize - 10, csize - 10, cover)\n\t}\n}\n\nfn on_frame(mut g Game) {\n\tws := gg.window_size()\n\tg.ctx.begin()\n\tmessage := '(r)estart (esc)ape | remaining: ${g.remaining:02} | time: ${f64(g.sw.elapsed().milliseconds()) / 1000.0:06.1f}s'\n\tg.ctx.draw_text(ws.width / 2, 7, message, color: gg.light_gray, size: 22, align: .center)\n\tfor i in 0 .. g.cells.len {\n\t\tg.draw_cell(i)\n\t}\n\tif g.revert_sw.elapsed().milliseconds() > 750 {\n\t\tg.revert_sw = time.new_stopwatch(auto_start: false)\n\t\tif g.card1_idx != none {\n\t\t\tif g.card2_idx != none {\n\t\t\t\tg.cells[g.card1_idx].is_open = false\n\t\t\t\tg.cells[g.card2_idx].is_open = false\n\t\t\t\tg.card1_idx = none\n\t\t\t\tg.card2_idx = none\n\t\t\t\tg.remaining = g.cells.count(!it.is_open)\n\t\t\t}\n\t\t}\n\t}\n\tg.ctx.end()\n}\n\nfn on_event(e &gg.Event, mut g Game) {\n\tif e.typ == .key_down {\n\t\tmatch e.key_code {\n\t\t\t.escape { g.ctx.quit() }\n\t\t\t.r { g.restart() }\n\t\t\telse {}\n\t\t}\n\t\treturn\n\t}\n\tif e.typ != .mouse_down {\n\t\treturn\n\t}\n\tx, y := int(e.mouse_x / csize), int((e.mouse_y - header_size) / csize)\n\tif e.mouse_button == .left && g.card2_idx == none {\n\t\tif g.remaining == 0 {\n\t\t\tg.restart()\n\t\t\treturn\n\t\t}\n\t\ti := y * g.size + x\n\t\tif !g.cells[i].is_open {\n\t\t\tg.cells[i].is_open = true\n\t\t\tif g.card1_idx == none {\n\t\t\t\tg.card1_idx = i\n\t\t\t} else {\n\t\t\t\tg.card2_idx = i\n\t\t\t\tif g.cells[g.card1_idx].letter == g.cells[i].letter {\n\t\t\t\t\tg.card1_idx = none\n\t\t\t\t\tg.card2_idx = none\n\t\t\t\t} else {\n\t\t\t\t\t// start a timer, that will be checked in the on_frame callback\n\t\t\t\t\tg.revert_sw.start()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tg.remaining = g.cells.count(!it.is_open)\n\tif g.remaining == 0 {\n\t\tg.sw.stop()\n\t}\n}\n\nmut g := &Game{\n\t// the CLI argument should be number of pairs, so `size` is even, and the puzzle can be solved:\n\tsize: arguments()[1] or { '3' }.int() * 2\n}\ng.restart()\ng.ctx = gg.new_context(\n\tbg_color:     gg.black\n\twidth:        g.size * csize\n\theight:       header_size + g.size * csize\n\twindow_title: 'V Memory ${g.size} x ${g.size}'\n\tuser_data:    g\n\tframe_fn:     on_frame\n\tevent_fn:     on_event\n\tsample_count: 2\n)\ng.ctx.run()\n"
  },
  {
    "path": "examples/gg/minesweeper.v",
    "content": "module main\n\nimport gg\nimport rand\nimport os.asset\n\nconst header_size = 30\n\nenum Cell {\n\tempty\n\tn1\n\tn2\n\tn3\n\tn4\n\tn5\n\tn6\n\tn7\n\tn8\n\tmine\n}\n\n@[heap]\nstruct Game {\nmut:\n\tctx           &gg.Context = unsafe { nil }\n\tgrid          [][]Cell\n\tflags         [][]bool\n\trevealed      [][]bool\n\tsize          int = 10 // in cells\n\tcsize         int = 30 // in pixels\n\tgame_over     bool\n\tfirst_click   bool = true\n\tmines         int  = 10\n\tmines_flagged int\n}\n\n@[inline]\nfn (mut g Game) in_grid(cy int, cx int) bool {\n\treturn cx >= 0 && cx < g.size && cy >= 0 && cy < g.size\n}\n\nfn (mut g Game) generate_mines(first_y int, first_x int) {\n\tmut mines_placed := 0\n\tfor mines_placed < g.mines {\n\t\tx, y := rand.intn(g.size) or { 0 }, rand.intn(g.size) or { 0 }\n\t\t// avoid placing mines at the position of the first click\n\t\tif (x == first_x && y == first_y) || g.grid[y][x] == .mine {\n\t\t\tcontinue\n\t\t}\n\t\tg.grid[y][x] = .mine\n\t\tmines_placed++\n\t}\n\tfor y in 0 .. g.size {\n\t\tfor x in 0 .. g.size {\n\t\t\tif g.grid[y][x] == .mine {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmut count := 0\n\t\t\tfor dy in -1 .. 2 {\n\t\t\t\tfor dx in -1 .. 2 {\n\t\t\t\t\tcy, cx := y + dy, x + dx\n\t\t\t\t\tif g.in_grid(cy, cx) {\n\t\t\t\t\t\tif g.grid[cy][cx] == .mine {\n\t\t\t\t\t\t\tcount++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tg.grid[y][x] = unsafe { Cell(count) }\n\t\t}\n\t}\n}\n\nfn (mut g Game) reveal(y int, x int) {\n\tif !g.in_grid(y, x) {\n\t\treturn\n\t}\n\tif g.revealed[y][x] {\n\t\treturn\n\t}\n\tg.revealed[y][x] = true\n\tif g.grid[y][x] == .mine {\n\t\tg.game_over = true\n\t\treturn\n\t}\n\tif g.grid[y][x] == .empty {\n\t\tfor dy in -1 .. 2 {\n\t\t\tfor dx in -1 .. 2 {\n\t\t\t\tg.reveal(y + dy, x + dx)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfn (mut g Game) restart() {\n\tg.grid = [][]Cell{len: g.size, init: []Cell{len: g.size}}\n\tg.flags = [][]bool{len: g.size, init: []bool{len: g.size}}\n\tg.revealed = [][]bool{len: g.size, init: []bool{len: g.size}}\n\tg.game_over = false\n\tg.first_click = true\n\tg.mines_flagged = 0\n}\n\nfn on_event(e &gg.Event, mut g Game) {\n\tif e.typ == .key_down {\n\t\tmatch e.key_code {\n\t\t\t.escape { g.ctx.quit() }\n\t\t\t.r { g.restart() }\n\t\t\telse {}\n\t\t}\n\t\treturn\n\t}\n\tif g.game_over {\n\t\treturn\n\t}\n\tif e.typ != .mouse_down {\n\t\treturn\n\t}\n\tx := int(e.mouse_x / g.csize)\n\ty := int((e.mouse_y - header_size) / g.csize)\n\tif e.mouse_button == .left {\n\t\tif g.first_click {\n\t\t\tg.generate_mines(y, x)\n\t\t\tg.first_click = false\n\t\t}\n\t\tg.reveal(y, x)\n\t}\n\tif e.mouse_button == .right {\n\t\tif !g.revealed[y][x] {\n\t\t\told := g.flags[y][x]\n\t\t\tg.flags[y][x] = !old\n\t\t\tg.mines_flagged += if old { -1 } else { 1 }\n\t\t}\n\t}\n\tif e.mouse_button == .middle {\n\t\tif g.revealed[y][x] {\n\t\t\tcount := g.act_on_neighbors(y, x, fn (mut g Game, cy int, cx int) int {\n\t\t\t\tif g.in_grid(cy, cx) {\n\t\t\t\t\treturn int(g.flags[cy][cx])\n\t\t\t\t}\n\t\t\t\treturn 0\n\t\t\t})\n\t\t\tif int(g.grid[y][x]) == count {\n\t\t\t\tg.act_on_neighbors(y, x, fn (mut g Game, cy int, cx int) int {\n\t\t\t\t\tif g.in_grid(cy, cx) && !g.flags[cy][cx] {\n\t\t\t\t\t\tg.reveal(cy, cx)\n\t\t\t\t\t}\n\t\t\t\t\treturn 0\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n}\n\nfn (mut g Game) act_on_neighbors(y int, x int, f fn (mut g Game, cy int, cx int) int) int {\n\tmut count := 0\n\tfor dy in -1 .. 2 {\n\t\tfor dx in -1 .. 2 {\n\t\t\tif dy == 0 && dx == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcy, cx := y + dy, x + dx\n\t\t\tcount += f(mut g, cy, cx)\n\t\t}\n\t}\n\treturn count\n}\n\nfn (mut g Game) draw_cell(y int, x int) {\n\to := header_size\n\trect_x, rect_y := x * g.csize, y * g.csize\n\tif g.revealed[y][x] {\n\t\tif g.grid[y][x] == .mine {\n\t\t\tg.ctx.draw_rect_filled(rect_x, o + rect_y, g.csize, g.csize, gg.red)\n\t\t\tg.ctx.draw_text(rect_x + 10, o + rect_y + 5, '*', color: gg.black)\n\t\t} else if int(g.grid[y][x]) > 0 {\n\t\t\tg.ctx.draw_rect_filled(rect_x, o + rect_y, g.csize, g.csize, gg.light_gray)\n\t\t\tn := int(g.grid[y][x]).str()\n\t\t\tg.ctx.draw_text(rect_x + 10, o + rect_y + 5, n, color: gg.black)\n\t\t} else {\n\t\t\tc := gg.rgb(240, 240, 240)\n\t\t\tg.ctx.draw_rect_filled(rect_x, o + rect_y, g.csize, g.csize, c)\n\t\t}\n\t} else if g.flags[y][x] {\n\t\tg.ctx.draw_rect_filled(rect_x, o + rect_y, g.csize, g.csize, gg.gray)\n\t\tg.ctx.draw_text(rect_x + 10, o + rect_y + 5, 'F', color: gg.white)\n\t} else {\n\t\tg.ctx.draw_rect_filled(rect_x, o + rect_y, g.csize, g.csize, gg.gray)\n\t}\n\tg.ctx.draw_rect_empty(rect_x, o + rect_y, g.csize, g.csize, gg.black)\n}\n\nfn on_frame(mut g Game) {\n\tg.ctx.begin()\n\tfor y in 0 .. g.size {\n\t\tfor x in 0 .. g.size {\n\t\t\tg.draw_cell(y, x)\n\t\t}\n\t}\n\tmessage := 'Flagged: ${g.mines_flagged:02}/${g.mines:02}         (r)estart (ESC)ape'\n\tg.ctx.draw_text(5, 7, message, color: gg.green)\n\tg.ctx.end()\n}\n\nfn main() {\n\tmut g := &Game{}\n\tg.restart()\n\tg.ctx = gg.new_context(\n\t\tbg_color:     gg.black\n\t\twidth:        g.size * g.csize\n\t\theight:       header_size + g.size * g.csize\n\t\twindow_title: 'V Minesweeper'\n\t\tuser_data:    g\n\t\tframe_fn:     on_frame\n\t\tevent_fn:     on_event\n\t\tfont_path:    asset.get_path('../assets', 'fonts/RobotoMono-Regular.ttf')\n\t)\n\tg.ctx.run()\n}\n"
  },
  {
    "path": "examples/gg/minimal.v",
    "content": "import gg\n\ngg.start(\n\twindow_title: 'Hello'\n\tbg_color:     gg.Color{240, 240, 128, 255}\n\twidth:        320\n\theight:       240\n\tframe_fn:     fn (ctx &gg.Context) {\n\t\tctx.begin()\n\t\tctx.draw_text(40, 100, 'GG frame: ${ctx.frame:06}',\n\t\t\tsize:  30\n\t\t\tcolor: gg.Color{50, 50, 255, 255}\n\t\t)\n\t\tctx.show_fps()\n\t\tctx.end()\n\t}\n)\n"
  },
  {
    "path": "examples/gg/moving_square.v",
    "content": "import gg\n\nstruct App {\nmut:\n\tx f64 = 100.0\n\ty f64 = 100.0\n}\n\nmut app := &App{}\ngg.start(\n\twindow_title: 'Moving Square'\n\twidth:        640\n\theight:       480\n\tupdate_fn:    fn [mut app] (dt f32, ctx &gg.Context) {\n\t\tprintln(' frame: ${ctx.frame:6} | dt: ${dt:9.6f}s')\n\t\tif ctx.pressed_keys[gg.KeyCode.right] {\n\t\t\tapp.x = app.x + 200 * dt\n\t\t}\n\t\tif ctx.pressed_keys[gg.KeyCode.left] {\n\t\t\tapp.x = app.x - 200 * dt\n\t\t}\n\t\tif ctx.pressed_keys[gg.KeyCode.down] {\n\t\t\tapp.y = app.y + 200 * dt\n\t\t}\n\t\tif ctx.pressed_keys[gg.KeyCode.up] {\n\t\t\tapp.y = app.y - 200 * dt\n\t\t}\n\t}\n\tframe_fn:     fn [mut app] (ctx &gg.Context) {\n\t\tctx.begin()\n\t\tctx.draw_rect_filled(int(app.x), int(app.y), 50, 50, gg.red)\n\t\tctx.end()\n\t}\n)\n"
  },
  {
    "path": "examples/gg/path_finding_algorithm_visualizer/LICENSE",
    "content": "MIT License\n\nCopyright (c) [2023] [Yuyi Hao]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "examples/gg/path_finding_algorithm_visualizer/README.md",
    "content": "# A* path finding algorithm visualizer\nThis is a simple visualizer for an A* path finding algorithm written in V.\n\n# Quick start \n\n```console\n# to run:\n$ v run aStar.v\n\n# to just compile:\n$ v aStar.v\n\n# then to run:\n$ ./aStar\n```\n\n# Controls\n\n- `q` : To quit the application\n- `c`: clear the grid and start from new one \n- `space`: initialize path finding algorithm \n\n\n# Demo \n![Demo image of the algorithm](screenshot.png)\n\n# 🔴🔴🔴🔴 Area of improvements 🔴🔴🔴🔴🔴\n\n- 🚧 Under Construction: We are using heap, but that is not correctly\nimplemented, since instead of O(log(n)) it takes O(n). For that reason,\nhaving a bigger grid size, will break the application.\n\n- 🌱 Growth Opportunity: make it responsive.\n"
  },
  {
    "path": "examples/gg/path_finding_algorithm_visualizer/aStar.v",
    "content": "module main\n\nimport gg // actual graphics lib\nimport math // for math related function\n\nconst window_width = 800\nconst window_height = 800\nconst nrows = 50\n\n// app struct that has property of current windows\nstruct App {\nmut:\n\tgg    &gg.Context = unsafe { nil }\n\tui    Ui\n\tgrid  [][]Cell\n\tstart Point // start point of algorithm\n\tend   Point // end point or target point\n}\n\n// this needed to get the width and mouse position part of gg window\nstruct Ui {\nmut:\n\tdpi_scale f32\n}\n\n// struct for a point\nstruct Point {\nmut:\n\tx int\n\ty int\n}\n\n/*\nRED -> Closed\nGREEN -> Open\nBLACK -> Barrier\nWHITE -> Empty\nORANGE -> Start\nTURQOIISE -> End\nPINK -> Path\n*/\n\n// struct for a cell of grid\nstruct Cell {\nmut:\n\trow       int\n\tcol       int\n\twidth     int\n\tpos       Point\n\tcolor     gg.Color\n\tflag      int // 0->empty, 1-> closed, 2-> open, 3-> barrier, 4-> start, 5-> end, 6-> path\n\tneighbors []Point\n}\n\n// this is a node for priority queue\n\nstruct Node {\nmut:\n\tf_score int\n\tcell    Point\n\tcount   int\n}\n\n// Min heap or priority queue\n\nstruct MinHeap {\nmut:\n\tdata []Node\n}\n\n// main function\nfn main() {\n\t// app variable\n\tmut app := &App{}\n\n\t// setting values of app\n\tapp.gg = gg.new_context(\n\t\tbg_color:      gg.black      // background color\n\t\twidth:         window_width  // window width\n\t\theight:        window_height // window height\n\t\tcreate_window: true          // this will create a different window\n\t\twindow_title:  'A* Path finding algorithm visusalizer' // title of the window\n\t\tframe_fn:      frame    // this is frame function update the frame\n\t\tevent_fn:      on_event // it calls on every event\n\t\tuser_data:     app      // store user data\n\t)\n\tmut grid := initialise_grid() // initialize the grid variable and populate the matrix with each cell as empty\n\tapp.grid = grid // set grid to app attribute so you can access it by just passing app variable or with method of app\n\tapp.ui.dpi_scale = 1.0 // set scale this is use to make it responsive\n\tapp.start = &Point{ // set start point to -1, -1\n\t\tx: -1\n\t\ty: -1\n\t}\n\tapp.end = &Point{ // set end point to -1, -1\n\t\tx: -1\n\t\ty: -1\n\t}\n\tapp.gg.run() // run the app loop\n}\n\n// this function will run for every frame actually in a loop\nfn frame(mut app App) {\n\tapp.gg.begin()\n\tdraw_grid(mut app)\n\tdraw_gridlines(mut app)\n\tapp.gg.end()\n}\n\n// this will handle user event which is stored in gg.event variable\nfn on_event(event &gg.Event, mut app App) {\n\tmatch event.typ {\n\t\t.mouse_down {\n\t\t\tx := int(event.mouse_x / app.ui.dpi_scale)\n\t\t\ty := int(event.mouse_y / app.ui.dpi_scale)\n\t\t\tbtn := event.mouse_button\n\t\t\tapp.handle_mouse_event(x, y, btn)\n\t\t}\n\t\t.key_down {\n\t\t\tapp.on_key_down(event.key_code)\n\t\t}\n\t\telse {}\n\t}\n}\n\n// handle mouse event to make a cell either start  point end point or barrier or to clear\nfn (mut app App) handle_mouse_event(x int, y int, btn_type gg.MouseButton) {\n\tgap := window_width / nrows\n\trow := int(y / gap)\n\tcol := int(x / gap)\n\tmatch btn_type {\n\t\t.left {\n\t\t\tif app.start.x == -1 && !(row == app.end.y && col == app.end.x) {\n\t\t\t\tapp.start.x = col\n\t\t\t\tapp.start.y = row\n\t\t\t\tset_cell_type(mut app.grid, app.start.y, app.start.x, 'start')\n\t\t\t} else if app.end.x == -1 && !(row == app.start.y && col == app.start.x) {\n\t\t\t\tapp.end.x = col\n\t\t\t\tapp.end.y = row\n\t\t\t\tset_cell_type(mut app.grid, app.end.y, app.end.x, 'end')\n\t\t\t} else if !(row == app.start.y && col == app.start.x) && !(row == app.end.y\n\t\t\t\t&& col == app.end.x) {\n\t\t\t\tset_cell_type(mut app.grid, row, col, 'barrier')\n\t\t\t}\n\t\t}\n\t\t.right {\n\t\t\tif row == app.start.y && col == app.start.x {\n\t\t\t\tapp.start.x = -1\n\t\t\t\tapp.start.y = -1\n\t\t\t}\n\t\t\tif row == app.end.y && col == app.end.x {\n\t\t\t\tapp.end.x = -1\n\t\t\t\tapp.end.y = -1\n\t\t\t}\n\n\t\t\tset_cell_type(mut app.grid, row, col, 'reset')\n\t\t}\n\t\telse {}\n\t}\n}\n\n// handle keyboard interaction by user ''\nfn (mut app App) on_key_down(key gg.KeyCode) {\n\tmatch key {\n\t\t.space {\n\t\t\tif app.start.x == -1 || app.end.x == -1 {\n\t\t\t\tprintln('Error: either start or end node is missing')\n\t\t\t} else {\n\t\t\t\tfor row := 0; row < nrows; row++ {\n\t\t\t\t\tfor j := 0; j < nrows; j++ {\n\t\t\t\t\t\tupdate_neighbors(mut app.grid, row, j)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnew_start := &Point{\n\t\t\t\t\tx: app.start.y\n\t\t\t\t\ty: app.start.x\n\t\t\t\t}\n\t\t\t\tnew_end := &Point{\n\t\t\t\t\tx: app.end.y\n\t\t\t\t\ty: app.end.x\n\t\t\t\t}\n\t\t\t\tastar_path_finding(mut app, mut app.grid, new_start, new_end)\n\t\t\t}\n\t\t}\n\t\t.q {\n\t\t\tapp.gg.quit()\n\t\t}\n\t\t.c {\n\t\t\tdraw_grid(mut app)\n\t\t\tdraw_gridlines(mut app)\n\t\t\tmut grid := initialise_grid()\n\t\t\tapp.grid = grid // set grid to app attribute so you can access it by just passing app variable or with method of app\n\t\t\tapp.ui.dpi_scale = 1.0 // set scale this is use to make it responsive\n\t\t\tapp.start = &Point{ // set start point to -1, -1\n\t\t\t\tx: -1\n\t\t\t\ty: -1\n\t\t\t}\n\t\t\tapp.end = &Point{ // set end point to -1, -1\n\t\t\t\tx: -1\n\t\t\t\ty: -1\n\t\t\t}\n\t\t}\n\t\telse {}\n\t}\n}\n\n// draw grid lines\nfn draw_gridlines(mut app App) {\n\tdx := window_width / nrows\n\tdy := window_height / nrows\n\tfor i := 0; i < nrows; i++ {\n\t\t// horizontal lines\n\t\tapp.gg.draw_line(0, i * dy, window_width, i * dy, gg.black)\n\t\t// vertical lines\n\t\tapp.gg.draw_line(i * dx, 0, dx * i, window_height, gg.black)\n\t}\n}\n\n// heuristic function(point manhatten distance) that calculate approximate cost to reach from a given point to end(target)\nfn hf(p1 Point, p2 Point) int {\n\treturn math.abs(p1.x - p2.x) + math.abs(p1.y - p2.y)\n}\n\n// initialize grid attribute of app\nfn initialise_grid() [][]Cell {\n\tmut grid := [][]Cell{len: nrows, init: []Cell{len: nrows}}\n\tgap := window_width / nrows\n\tfor i := 0; i < nrows; i++ {\n\t\tfor j := 0; j < nrows; j++ {\n\t\t\tgrid[i][j] = &Cell{\n\t\t\t\trow:   i\n\t\t\t\tcol:   j\n\t\t\t\twidth: gap\n\t\t\t\tpos:   &Point{\n\t\t\t\t\tx: j * gap\n\t\t\t\t\ty: i * gap\n\t\t\t\t}\n\t\t\t\tcolor: gg.white\n\t\t\t\tflag:  0\n\t\t\t}\n\t\t}\n\t}\n\treturn grid\n}\n\n// draw the cells of grid\nfn draw_grid(mut app App) {\n\tfor i := 0; i < nrows; i++ {\n\t\tfor j := 0; j < nrows; j++ {\n\t\t\tpos := app.grid[i][j].pos\n\t\t\twidth := app.grid[i][j].width\n\t\t\tcolor := app.grid[i][j].color\n\t\t\tapp.gg.draw_rect_filled(pos.x, pos.y, width, width, color)\n\t\t}\n\t}\n}\n\n// update the neighbor of each cell in which cell you can visit (if it is not barrier or end or start)\nfn update_neighbors(mut grid [][]Cell, row int, col int) {\n\tif row < nrows - 1 && grid[row + 1][col].flag != 3 {\n\t\tgrid[row][col].neighbors << &Point{\n\t\t\tx: row + 1\n\t\t\ty: col\n\t\t}\n\t}\n\tif row > 0 && grid[row - 1][col].flag != 3 {\n\t\tgrid[row][col].neighbors << &Point{\n\t\t\tx: row - 1\n\t\t\ty: col\n\t\t}\n\t}\n\tif col < nrows - 1 && grid[row][col + 1].flag != 3 {\n\t\tgrid[row][col].neighbors << &Point{\n\t\t\tx: row\n\t\t\ty: col + 1\n\t\t}\n\t}\n\tif col > 0 && grid[row][col - 1].flag != 3 {\n\t\tgrid[row][col].neighbors << &Point{\n\t\t\tx: row\n\t\t\ty: col - 1\n\t\t}\n\t}\n}\n\n// construct the path after finding it shows as pink color\nfn reconstruct_path(mut grid [][]Cell, mut came_from [][]Point, _start Point, end Point) {\n\tmut x := end.x\n\tmut y := end.y\n\tfor !(x == -1 && y == -1) {\n\t\tset_cell_type(mut grid, x, y, 'path')\n\t\tx = came_from[x][y].x\n\t\ty = came_from[x][y].y\n\t}\n}\n\n// a* path finding algorithm\nfn astar_path_finding(mut _app App, mut grid [][]Cell, start Point, end Point) {\n\tmut priority_queue := &MinHeap{}\n\tmut g_score := [][]int{len: nrows, init: []int{len: nrows}}\n\tmut f_score := [][]int{len: nrows, init: []int{len: nrows}}\n\tmut came_from := [][]Point{len: nrows, init: []Point{len: nrows}}\n\tfor i := 0; i < nrows; i++ {\n\t\tfor j := 0; j < nrows; j++ {\n\t\t\tg_score[i][j] = 1_000_000_000_00\n\t\t\tf_score[i][j] = 1_000_000_000_00\n\t\t\tcame_from[i][j] = &Point{\n\t\t\t\tx: -1\n\t\t\t\ty: -1\n\t\t\t}\n\t\t}\n\t}\n\n\tg_score[start.x][start.y] = 0\n\tf_score[start.x][start.y] = g_score[start.x][start.y] + hf(start, end)\n\tpriority_queue.insert(Node{\n\t\tf_score: f_score[start.x][start.y]\n\t\tcell:    &Point{\n\t\t\tx: start.x\n\t\t\ty: start.y\n\t\t}\n\t\tcount:   0\n\t})\n\n\tfor priority_queue.len() > 0 {\n\t\tcurr_node := priority_queue.pop() or {\n\t\t\tpanic('There is nothing in queue how did it reach here idk')\n\t\t}\n\t\tcurr_pos := curr_node.cell\n\t\tset_cell_type(mut grid, curr_pos.x, curr_pos.y, 'close')\n\n\t\tif curr_pos.x == end.x && curr_pos.y == end.y {\n\t\t\tset_cell_type(mut grid, start.x, start.y, 'start')\n\t\t\tset_cell_type(mut grid, end.x, end.y, 'end')\n\t\t\tcame_from[end.x][end.y] = came_from[curr_pos.x][curr_pos.y]\n\t\t\treconstruct_path(mut grid, mut came_from, start, end)\n\t\t\tset_cell_type(mut grid, start.x, start.y, 'start')\n\t\t\tset_cell_type(mut grid, end.x, end.y, 'end')\n\t\t\treturn\n\t\t}\n\n\t\tfor neighbor in grid[curr_pos.x][curr_pos.y].neighbors {\n\t\t\tmut temp_g_score := g_score[curr_pos.x][curr_pos.y] + 1\n\t\t\tif temp_g_score < g_score[neighbor.x][neighbor.y] {\n\t\t\t\tg_score[neighbor.x][neighbor.y] = temp_g_score\n\t\t\t\tif !(neighbor.x == start.x && neighbor.y == start.y) {\n\t\t\t\t\tpriority_queue.insert(Node{\n\t\t\t\t\t\tf_score: g_score[neighbor.x][neighbor.y] + hf(neighbor, end)\n\t\t\t\t\t\tcell:    neighbor\n\t\t\t\t\t\tcount:   curr_node.count + 1\n\t\t\t\t\t})\n\t\t\t\t\tcame_from[neighbor.x][neighbor.y] = curr_pos\n\t\t\t\t\tset_cell_type(mut grid, neighbor.x, neighbor.y, 'open')\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tset_cell_type(mut grid, start.x, start.y, 'start')\n}\n\n// change the property of a cell\nfn set_cell_type(mut grid [][]Cell, row int, col int, typ string) {\n\tmatch typ {\n\t\t'reset' {\n\t\t\tgrid[row][col].color = gg.white\n\t\t\tgrid[row][col].flag = 0\n\t\t}\n\t\t'close' {\n\t\t\tgrid[row][col].color = gg.red\n\t\t\tgrid[row][col].flag = 1\n\t\t}\n\t\t'open' {\n\t\t\tgrid[row][col].color = gg.green\n\t\t\tgrid[row][col].flag = 2\n\t\t}\n\t\t'barrier' {\n\t\t\tgrid[row][col].color = gg.black\n\t\t\tgrid[row][col].flag = 3\n\t\t}\n\t\t'start' {\n\t\t\tgrid[row][col].color = gg.orange\n\t\t\tgrid[row][col].flag = 4\n\t\t}\n\t\t'end' {\n\t\t\tgrid[row][col].color = gg.blue\n\t\t\tgrid[row][col].flag = 5\n\t\t}\n\t\t'path' {\n\t\t\tgrid[row][col].color = gg.pink\n\t\t\tgrid[row][col].flag = 6\n\t\t}\n\t\telse {}\n\t}\n}\n\n// ------------------------------ HEAP -----------------------------\n\nfn (mut heap MinHeap) insert(item Node) {\n\theap.data << item\n}\n\n// get the minimum out of all node\nfn (mut heap MinHeap) pop() !Node {\n\tif heap.len() == 0 {\n\t\treturn error('empty heap')\n\t}\n\tmut i := 0\n\tmut curr := heap.data[0].f_score\n\tlen := heap.len()\n\tfor idx := 0; idx < len; idx++ {\n\t\tif curr > heap.data[idx].f_score {\n\t\t\ti = idx\n\t\t\tcurr = heap.data[idx].f_score\n\t\t}\n\t}\n\tele := heap.data[i]\n\theap.data.delete(i)\n\treturn ele\n}\n\n// see the top element of heap //TODO this won't give correct result as heap is not implemented correctly\nfn (mut heap MinHeap) peek() !Node {\n\tif heap.data.len == 0 {\n\t\treturn error('Heap is empty')\n\t}\n\treturn heap.data[0]\n}\n\n// give length of heap total element present currently\nfn (mut heap MinHeap) len() int {\n\treturn heap.data.len\n}\n\n// Index of left child of a node in heap //TODO heap not implemented\nfn (mut heap MinHeap) left_child(idx int) !int {\n\tchild := 2 * idx + 1\n\tif child >= heap.data.len {\n\t\treturn error('Out of Bound')\n\t}\n\treturn child\n}\n\n// Index of right child of a node in heap //TODO heap not implemented\nfn (mut heap MinHeap) right_child(idx int) !int {\n\tchild := 2 * idx + 2\n\tif child >= heap.data.len {\n\t\treturn error('Out of bound')\n\t}\n\treturn child\n}\n\n// Index of parent of a node in heap //TODO heap not implemented\nfn (mut heap MinHeap) parent(idx int) int {\n\treturn (idx - 1) / 2\n}\n\n// comaparator of heap //TODO not used\nfn comparator(n1 Node, n2 Node) bool {\n\tif n1.f_score == n2.f_score {\n\t\treturn n1.count > n2.count\n\t}\n\treturn n1.f_score > n2.f_score\n}\n"
  },
  {
    "path": "examples/gg/polygons.v",
    "content": "module main\n\nimport gg\n\nfn main() {\n\tmut context := gg.new_context(\n\t\tbg_color:     gg.rgb(174, 198, 255)\n\t\twidth:        600\n\t\theight:       400\n\t\twindow_title: 'Polygons'\n\t\tframe_fn:     frame\n\t)\n\tcontext.run()\n}\n\nfn frame(mut ctx gg.Context) {\n\tctx.begin()\n\tctx.draw_convex_poly([f32(100.0), 100.0, 200.0, 100.0, 300.0, 200.0, 200.0, 300.0, 100.0, 300.0],\n\t\tgg.blue)\n\tctx.draw_poly_empty([f32(50.0), 50.0, 70.0, 60.0, 90.0, 80.0, 70.0, 110.0], gg.black)\n\tctx.draw_triangle_filled(450, 142, 530, 280, 370, 280, gg.red)\n\tctx.end()\n}\n"
  },
  {
    "path": "examples/gg/pong/README.md",
    "content": "A small Pong game written in V using the `gg` and `sokol.audio` modules.\n\n## Features\n-   **Proportional Resizing**: The game scales ball, paddles, and speeds based on the window size.\n-   **Audio Effects**: Synthesized sounds for wall bounces, paddle hits, and scoring.\n-   **Modern-Retro UI**: Deep blue background with vibrant accent colors.\n-   **Real-time Metrics**: Displays ball speed in m/s (assuming a 10m wide playfield).\n\n## AI use note: \nThis example was created by Google gemini-cli `Auto (Gemini 3)`, using the following prompts:\n\n1. create a small Pong game using gg in examples/gg/pong.v .\n2. the game should start not paused. Show the current score for each player on the corresponding\n   side of the screen. Show the current vertical position for each player below the score too.\n   Show a green \"PAUSED, press space to unpause\" label in the bottom middle of the screen,\n   when the game is paused.\n   Show a yellow label \"Press space - pause; W/S - left player; Up/Down - right player.\" in the\n   bottom middle of the screen, when the game is not paused.\n3. make the score and position labels green\n4. make the ball be a filled white circle\n5. make the paddles be slightly rounded\n6. make the pause key work when a key_down event is received; it is not like the other keys\n7. make the background very dark blue\n8. be a good game designer, and tweak the colors and positions of all the screen elements,\n   if they do not look good.\n9. move the bottom status text even more down, so that the last stripe of the center line does not\n   intersect it. Move the paused label in the center of the screen and make it bigger\n10. move the paused text about 80 pixels to the top; make the bottom status text slightly bigger\n11. move the paused text about 30 pixels down\n12. use the `sokol.audio` module and add simple sound effects to the game: when the ball bounces\n    on a wall, it should produce a ping sound; when the ball bounces on a paddle it should produce\n    a pong sound (slightly lower pitched); when the ball escapes behind a paddle, and the game\n    resets, produce a low pitched buzzing sound\n13. the sounds work fine, but there is a very slight click at the end, that is especially\n    pronounced at the end of the buzz sound\n14. the buzz sound still has a slight click at the end\n15. make the left paddle bight red, and the right paddle bright blue\n16. assume that the whole playfield is 10 meters wide (5 on the left and 5 on the right side).\n    Calculate the ball speed. Show the ball speed in the top center of the screen\n    (for example `Ball: 5.2 m/s`, note it should be always rounded at \n    the first digit after the dot (i.e. show 5 as `Ball: 5.0 m/s`).\n17. make sure to resize the ball, paddles and playfield proportionally, when the screen\n    is maximized\n18. append all my current user prompts to examples/gg/pong/README.md\n"
  },
  {
    "path": "examples/gg/pong/pong.v",
    "content": "// vtest build: !openbsd\nmodule main\n\nimport gg\nimport rand\nimport sokol.audio\nimport math\n\nconst paddle_speed_base = f32(400.0)\nconst ball_speed_base = f32(300.0)\n\n// Colors\nconst color_bg = gg.Color{10, 15, 30, 255}\nconst color_foreground = gg.Color{230, 230, 230, 255}\nconst color_accent = gg.Color{0, 255, 100, 255}\nconst color_secondary = gg.Color{0, 200, 80, 255}\nconst color_text_dim = gg.Color{150, 150, 150, 200}\nconst color_line = gg.Color{100, 100, 100, 150}\nconst color_p1 = gg.Color{255, 50, 50, 255}\nconst color_p2 = gg.Color{50, 100, 255, 255}\n\nstruct SoundManager {\nmut:\n\tping []f32\n\tpong []f32\n\tbuzz []f32\n}\n\nfn (mut sm SoundManager) init() {\n\tsample_rate := f32(audio.sample_rate())\n\n\t// Ping (Wall)\n\tping_duration := f32(0.1)\n\tping_frames := int(sample_rate * ping_duration)\n\tfor i in 0 .. ping_frames {\n\t\tt := f32(i) / sample_rate\n\t\t// Use a steeper exponential-like decay for a cleaner \"pluck\"\n\t\tenv := f32(math.pow(f32(1.0) - t / ping_duration, 3))\n\t\tsm.ping << f32(0.3) * math.sinf(t * 800.0 * 2 * math.pi) * env\n\t}\n\t// Absolute silence buffer to prevent clicks\n\tfor _ in 0 .. 100 {\n\t\tsm.ping << 0\n\t}\n\n\t// Pong (Paddle)\n\tpong_duration := f32(0.1)\n\tpong_frames := int(sample_rate * pong_duration)\n\tfor i in 0 .. pong_frames {\n\t\tt := f32(i) / sample_rate\n\t\tenv := f32(math.pow(f32(1.0) - t / pong_duration, 3))\n\t\tsm.pong << f32(0.3) * math.sinf(t * 400.0 * 2 * math.pi) * env\n\t}\n\tfor _ in 0 .. 100 {\n\t\tsm.pong << 0\n\t}\n\n\t// Buzz (Reset)\n\tbuzz_duration := f32(0.3)\n\tbuzz_frames := int(sample_rate * buzz_duration)\n\tfor i in 0 .. buzz_frames {\n\t\tt := f32(i) / sample_rate\n\t\tenv := f32(math.pow(f32(1.0) - t / buzz_duration, 2))\n\t\t// Add a harmonic for a more \"buzzy\" feel\n\t\tval := f32(0.25) * math.sinf(t * 100.0 * 2 * math.pi) +\n\t\t\tf32(0.1) * math.sinf(t * 200.0 * 2 * math.pi)\n\t\tsm.buzz << val * env\n\t}\n\tfor _ in 0 .. 200 {\n\t\tsm.buzz << 0\n\t}\n}\n\nstruct App {\nmut:\n\tctx           &gg.Context = unsafe { nil }\n\twidth         int         = 800\n\theight        int         = 600\n\tpaddle_width  f32\n\tpaddle_height f32\n\tball_size     f32\n\tp1_y          f32\n\tp2_y          f32\n\tball_x        f32\n\tball_y        f32\n\tball_vx       f32\n\tball_vy       f32\n\tp1_score      int\n\tp2_score      int\n\tpaused        bool\n\tsounds        SoundManager\n}\n\nfn (mut app App) update_sizes() {\n\tsize := app.ctx.window_size()\n\tapp.width = size.width\n\tapp.height = size.height\n\n\t// Base scales on 800x600\n\tscale_x := f32(app.width) / 800.0\n\tscale_y := f32(app.height) / 600.0\n\n\tapp.paddle_width = 15.0 * scale_x\n\tapp.paddle_height = 80.0 * scale_y\n\tapp.ball_size = 15.0 * scale_x // Keep it circular based on width scale\n}\n\nfn (mut app App) reset_ball() {\n\tapp.ball_x = f32(app.width) / 2 - app.ball_size / 2\n\tapp.ball_y = f32(app.height) / 2 - app.ball_size / 2\n\n\tscale_x := f32(app.width) / 800.0\n\tmut vx := ball_speed_base * scale_x\n\tif rand.intn(2) or { 0 } == 0 {\n\t\tvx = -vx\n\t}\n\tapp.ball_vx = vx\n\tapp.ball_vy = (f32(rand.intn(301) or { 150 } - 150)) * (f32(app.height) / 600.0)\n}\n\nfn (mut app App) reset_game() {\n\tapp.p1_score = 0\n\tapp.p2_score = 0\n\tapp.p1_y = f32(app.height) / 2 - app.paddle_height / 2\n\tapp.p2_y = f32(app.height) / 2 - app.paddle_height / 2\n\tapp.reset_ball()\n\tapp.paused = false\n}\n\nfn on_frame(data voidptr) {\n\tmut app := unsafe { &App(data) }\n\tapp.ctx.begin()\n\n\t// Draw dashed center line\n\tline_segments := 20\n\tsegment_height := f32(app.height) / line_segments\n\tfor i in 0 .. line_segments {\n\t\tif i % 2 == 0 {\n\t\t\tapp.ctx.draw_rect_filled(f32(app.width) / 2 - 1, i * segment_height, 2, segment_height,\n\t\t\t\tcolor_line)\n\t\t}\n\t}\n\n\t// Draw paddles\n\tapp.ctx.draw_rounded_rect_filled(20, app.p1_y, app.paddle_width, app.paddle_height,\n\t\t5, color_p1)\n\tapp.ctx.draw_rounded_rect_filled(f32(app.width) - 20 - app.paddle_width, app.p2_y,\n\t\tapp.paddle_width, app.paddle_height, 5, color_p2)\n\n\t// Draw ball\n\tapp.ctx.draw_circle_filled(app.ball_x + app.ball_size / 2, app.ball_y + app.ball_size / 2,\n\t\tapp.ball_size / 2, color_foreground)\n\n\t// Draw ball speed (10m = 800px => 1m = 80px)\n\t// We scale the meter definition with width\n\tmeter_px := 80.0 * (f32(app.width) / 800.0)\n\tspeed_px := math.sqrt(app.ball_vx * app.ball_vx + app.ball_vy * app.ball_vy)\n\tspeed_ms := speed_px / meter_px\n\tapp.ctx.draw_text(app.width / 2, 20, 'Ball: ${speed_ms:.1f} m/s',\n\t\tsize:  20\n\t\tcolor: color_foreground\n\t\talign: .center\n\t)\n\n\t// Draw scores and positions\n\t// Moved up to be less obtrusive\n\tapp.ctx.draw_text(app.width / 4, 30, app.p1_score.str(),\n\t\tsize:  40\n\t\tcolor: color_accent\n\t\talign: .center\n\t)\n\tapp.ctx.draw_text(app.width / 4, 80, 'Y: ${int(app.p1_y)}',\n\t\tsize:  16\n\t\tcolor: color_secondary\n\t\talign: .center\n\t)\n\n\tapp.ctx.draw_text(3 * app.width / 4, 30, app.p2_score.str(),\n\t\tsize:  40\n\t\tcolor: color_accent\n\t\talign: .center\n\t)\n\tapp.ctx.draw_text(3 * app.width / 4, 80, 'Y: ${int(app.p2_y)}',\n\t\tsize:  16\n\t\tcolor: color_secondary\n\t\talign: .center\n\t)\n\n\tif app.paused {\n\t\tapp.ctx.draw_text(app.width / 2, app.height / 2 - 50, 'PAUSED',\n\t\t\tsize:  64\n\t\t\tcolor: color_accent\n\t\t\talign: .center\n\t\t)\n\t\tapp.ctx.draw_text(app.width / 2, app.height / 2 + 10, 'Press SPACE to Resume',\n\t\t\tsize:  20\n\t\t\tcolor: color_accent\n\t\t\talign: .center\n\t\t)\n\t} else {\n\t\tapp.ctx.draw_text(app.width / 2, app.height - 25, 'SPACE: Pause | W/S: P1 | UP/DOWN: P2 | R: Reset',\n\t\t\tsize:  16\n\t\t\tcolor: color_text_dim\n\t\t\talign: .center\n\t\t)\n\t}\n\n\tapp.ctx.end()\n}\n\nfn on_event(e &gg.Event, data voidptr) {\n\tmut app := unsafe { &App(data) }\n\tif e.typ == .resized || e.typ == .restored {\n\t\tapp.update_sizes()\n\t}\n\tif e.typ == .key_down {\n\t\tmatch e.key_code {\n\t\t\t.space { app.paused = !app.paused }\n\t\t\t.r { app.reset_game() }\n\t\t\telse {}\n\t\t}\n\t}\n}\n\nfn on_update(dt f32, data voidptr) {\n\tmut app := unsafe { &App(data) }\n\n\tif app.paused {\n\t\treturn\n\t}\n\n\tscale_y := f32(app.height) / 600.0\n\tpaddle_speed := paddle_speed_base * scale_y\n\n\t// Paddle 1 movement (W/S)\n\tif app.ctx.pressed_keys[gg.KeyCode.w] {\n\t\tapp.p1_y -= paddle_speed * dt\n\t}\n\tif app.ctx.pressed_keys[gg.KeyCode.s] {\n\t\tapp.p1_y += paddle_speed * dt\n\t}\n\n\t// Paddle 2 movement (Up/Down)\n\tif app.ctx.pressed_keys[gg.KeyCode.up] {\n\t\tapp.p2_y -= paddle_speed * dt\n\t}\n\tif app.ctx.pressed_keys[gg.KeyCode.down] {\n\t\tapp.p2_y += paddle_speed * dt\n\t}\n\n\t// Constrain paddles\n\tif app.p1_y < 0 {\n\t\tapp.p1_y = 0\n\t}\n\tif app.p1_y > f32(app.height) - app.paddle_height {\n\t\tapp.p1_y = f32(app.height) - app.paddle_height\n\t}\n\tif app.p2_y < 0 {\n\t\tapp.p2_y = 0\n\t}\n\tif app.p2_y > f32(app.height) - app.paddle_height {\n\t\tapp.p2_y = f32(app.height) - app.paddle_height\n\t}\n\n\t// Ball movement\n\tapp.ball_x += app.ball_vx * dt\n\tapp.ball_y += app.ball_vy * dt\n\n\t// Ball wall collision (Top/Bottom)\n\tif app.ball_y <= 0 {\n\t\tapp.ball_y = 0\n\t\tapp.ball_vy = -app.ball_vy\n\t\taudio.push(app.sounds.ping.data, app.sounds.ping.len)\n\t} else if app.ball_y >= f32(app.height) - app.ball_size {\n\t\tapp.ball_y = f32(app.height) - app.ball_size\n\t\tapp.ball_vy = -app.ball_vy\n\t\taudio.push(app.sounds.ping.data, app.sounds.ping.len)\n\t}\n\n\t// Ball paddle collision\n\t// P1\n\tif app.ball_vx < 0 && app.ball_x <= 20 + app.paddle_width && app.ball_x >= 20 {\n\t\tif app.ball_y + app.ball_size >= app.p1_y && app.ball_y <= app.p1_y + app.paddle_height {\n\t\t\tapp.ball_x = 20 + app.paddle_width\n\t\t\tapp.ball_vx = -app.ball_vx * 1.05 // Slightly speed up\n\t\t\t// Add some vertical velocity based on where it hit the paddle\n\t\t\thit_pos := (app.ball_y + app.ball_size / 2) - (app.p1_y + app.paddle_height / 2)\n\t\t\tapp.ball_vy += hit_pos * 5\n\t\t\taudio.push(app.sounds.pong.data, app.sounds.pong.len)\n\t\t}\n\t}\n\n\t// P2\n\tif app.ball_vx > 0 && app.ball_x + app.ball_size >= f32(app.width) - 20 - app.paddle_width\n\t\t&& app.ball_x + app.ball_size <= f32(app.width) - 20 {\n\t\tif app.ball_y + app.ball_size >= app.p2_y && app.ball_y <= app.p2_y + app.paddle_height {\n\t\t\tapp.ball_x = f32(app.width) - 20 - app.paddle_width - app.ball_size\n\t\t\tapp.ball_vx = -app.ball_vx * 1.05 // Slightly speed up\n\t\t\t// Add some vertical velocity based on where it hit the paddle\n\t\t\thit_pos := (app.ball_y + app.ball_size / 2) - (app.p2_y + app.paddle_height / 2)\n\t\t\tapp.ball_vy += hit_pos * 5\n\t\t\taudio.push(app.sounds.pong.data, app.sounds.pong.len)\n\t\t}\n\t}\n\n\t// Score\n\tif app.ball_x < 0 {\n\t\tapp.p2_score++\n\t\tapp.reset_ball()\n\t\taudio.push(app.sounds.buzz.data, app.sounds.buzz.len)\n\t} else if app.ball_x > f32(app.width) {\n\t\tapp.p1_score++\n\t\tapp.reset_ball()\n\t\taudio.push(app.sounds.buzz.data, app.sounds.buzz.len)\n\t}\n}\n\nfn main() {\n\tmut app := &App{}\n\tapp.width = 800\n\tapp.height = 600\n\tapp.paddle_width = 15.0\n\tapp.paddle_height = 80.0\n\tapp.ball_size = 15.0\n\tapp.p1_y = f32(app.height) / 2 - app.paddle_height / 2\n\tapp.p2_y = f32(app.height) / 2 - app.paddle_height / 2\n\tapp.reset_ball()\n\n\taudio.setup(buffer_frames: 512)\n\tapp.sounds.init()\n\n\tapp.ctx = gg.new_context(\n\t\twidth:         app.width\n\t\theight:        app.height\n\t\twindow_title:  'V Pong'\n\t\tuser_data:     app\n\t\tframe_fn:      on_frame\n\t\tevent_fn:      on_event\n\t\tupdate_fn:     on_update\n\t\tbg_color:      color_bg\n\t\tresizable:     true\n\t\tcreate_window: true\n\t)\n\n\tapp.ctx.run()\n}\n"
  },
  {
    "path": "examples/gg/random.v",
    "content": "import gg\nimport time\n\nconst pwidth = 800\n\nconst pheight = 600\n\nconst pbytes = 4\n\nstruct AppState {\nmut:\n\tgg          &gg.Context = unsafe { nil }\n\tistream_idx int\n\tpixels      [pheight][pwidth]u32\n}\n\n@[direct_array_access]\nfn (mut state AppState) update() {\n\tmut rcolor := u64(state.gg.frame)\n\tfor {\n\t\tfor y in 0 .. pheight {\n\t\t\tfor x in 0 .. pwidth {\n\t\t\t\trcolor = rcolor * 1664525 + 1013904223\n\t\t\t\tstate.pixels[y][x] = u32(rcolor & 0x0000_0000_FFFF_FFFF) | 0x1010AFFF\n\t\t\t}\n\t\t}\n\t\ttime.sleep(33 * time.millisecond)\n\t}\n}\n\nfn (mut state AppState) draw() {\n\tmut istream_image := state.gg.get_cached_image_by_idx(state.istream_idx)\n\tistream_image.update_pixel_data(unsafe { &u8(&state.pixels) })\n\tsize := gg.window_size()\n\tstate.gg.draw_image(0, 0, size.width, size.height, istream_image)\n}\n\n// gg callbacks:\n\nfn graphics_init(mut state AppState) {\n\tstate.istream_idx = state.gg.new_streaming_image(pwidth, pheight, pbytes, pixel_format: .rgba8)\n}\n\nfn graphics_frame(mut state AppState) {\n\tstate.gg.begin()\n\tstate.draw()\n\tstate.gg.end()\n}\n\nfn main() {\n\tmut state := &AppState{}\n\tstate.gg = gg.new_context(\n\t\twidth:         800\n\t\theight:        600\n\t\tcreate_window: true\n\t\twindow_title:  'Random Static'\n\t\tinit_fn:       graphics_init\n\t\tframe_fn:      graphics_frame\n\t\tuser_data:     state\n\t)\n\tspawn state.update()\n\tstate.gg.run()\n}\n"
  },
  {
    "path": "examples/gg/random_stars.v",
    "content": "import gg\nimport math\nimport time\nimport rand\n\nconst pwidth = 800\n\nconst pheight = 600\n\nstruct AppState {\nmut:\n\tgg          &gg.Context = unsafe { nil }\n\tistream_idx int\n\tpixels      [pheight][pwidth]gg.Color\n}\n\n@[direct_array_access]\nfn (mut state AppState) update() {\n\tfor {\n\t\tunsafe { vmemset(&state.pixels, 0, pwidth * pheight * sizeof[gg.Color]()) }\n\t\tstate.draw_sky() or {}\n\t\ttime.sleep(30_000 * time.millisecond)\n\t}\n}\n\nfn (mut state AppState) draw_sky() ! {\n\tfor _ in 0 .. 2000 {\n\t\tmut star_size := 1\n\t\tfor rand.i32_in_range(0, 100)! < 5 {\n\t\t\tstar_size += 10\n\t\t}\n\t\tfor rand.i32_in_range(0, 100000)! < 5 {\n\t\t\tstar_size += 85\n\t\t}\n\t\tsx := if star_size < 10 {\n\t\t\trand.i32_in_range(-40, pwidth + 40)!\n\t\t} else {\n\t\t\trand.i32_in_range(40, pwidth - 40)!\n\t\t}\n\t\tsy := if star_size < 10 {\n\t\t\trand.i32_in_range(-40, pheight + 40)!\n\t\t} else {\n\t\t\trand.i32_in_range(40, pheight - 40)!\n\t\t}\n\t\tstate.draw_star(sx, sy, gg.Color{\n\t\t\tr: u8(rand.i32_in_range(50, 255)!)\n\t\t\tg: u8(rand.i32_in_range(50, 255)!)\n\t\t\tb: u8(rand.i32_in_range(50, 255)!)\n\t\t}, star_size)\n\t}\n}\n\n@[direct_array_access]\nfn (mut state AppState) draw_star(x int, y int, c gg.Color, radius int) {\n\tif radius == 0 {\n\t\treturn\n\t}\n\tminx := math.max(0, x - radius)\n\tminy := math.max(0, y - radius)\n\tmaxx := math.min(pwidth, x + radius)\n\tmaxy := math.min(pheight, y + radius)\n\tfor cx in minx .. maxx {\n\t\tfor cy in miny .. maxy {\n\t\t\tdx := math.abs[f32](cx - x) / f32(radius)\n\t\t\tdy := math.abs[f32](cy - y) / f32(radius)\n\t\t\tgradient := math.max[f32](0, math.min[f32](1, 1 - (math.sqrtf(dx) + math.sqrtf(dy))))\n\t\t\tif gradient < 0.01 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmut pixel := unsafe { &state.pixels[cy][cx] }\n\t\t\tcolor := gg.Color{\n\t\t\t\tr: u8(math.min(255, int(pixel.r) + int(f32(c.r) * gradient)))\n\t\t\t\tg: u8(math.min(255, int(pixel.g) + int(f32(c.g) * gradient)))\n\t\t\t\tb: u8(math.min(255, int(pixel.b) + int(f32(c.b) * gradient)))\n\t\t\t\ta: 255\n\t\t\t}\n\t\t\tunsafe {\n\t\t\t\t*pixel = color\n\t\t\t}\n\t\t}\n\t}\n}\n\nfn (mut state AppState) draw() {\n\tmut istream_image := state.gg.get_cached_image_by_idx(state.istream_idx)\n\tistream_image.update_pixel_data(unsafe { &u8(&state.pixels) })\n\tsize := gg.window_size()\n\tsx := -50 + 50 * math.sinf(f32(state.gg.frame) / 100)\n\tsy := -50 + 50 * math.cosf(f32(state.gg.frame) / 100)\n\tscale := 200 + 50 * math.sinf(f32(state.gg.frame) / 300)\n\twx := size.width + scale\n\twy := size.height + scale\n\tstate.gg.draw_image(sx, sy, wx, wy, istream_image)\n}\n\nfn graphics_init(mut state AppState) {\n\tstate.istream_idx = state.gg.new_streaming_image(pwidth, pheight, 4, pixel_format: .rgba8)\n}\n\nfn graphics_frame(mut state AppState) {\n\tstate.gg.begin()\n\tstate.draw()\n\tstate.gg.end()\n}\n\nfn main() {\n\tmut state := &AppState{}\n\tstate.gg = gg.new_context(\n\t\twidth:        pwidth\n\t\theight:       pheight\n\t\twindow_title: 'Random stars'\n\t\tinit_fn:      graphics_init\n\t\tframe_fn:     graphics_frame\n\t\tuser_data:    state\n\t)\n\tspawn state.update()\n\tstate.gg.run()\n}\n"
  },
  {
    "path": "examples/gg/raven_text_rendering.v",
    "content": "module main\n\nimport gg\nimport os.asset\nimport math\n\nconst win_width = 600\nconst win_height = 700\nconst bg_color = gg.white\n\nconst text = '\nOnce upon a midnight dreary, while I pondered, weak and weary,\nOver many a quaint and curious volume of forgotten lore—\n    While I nodded, nearly napping, suddenly there came a tapping,\nAs of some one gently rapping, rapping at my chamber door.\n“’Tis some visitor,” I muttered, “tapping at my chamber door—\n            Only this and nothing more.”\n\n    Ah, distinctly I remember it was in the bleak December;\nAnd each separate dying ember wrought its ghost upon the floor.\n    Eagerly I wished the morrow;—vainly I had sought to borrow\n    From my books surcease of sorrow—sorrow for the lost Lenore—\nFor the rare and radiant maiden whom the angels name Lenore—\n            Nameless here for evermore.\n\n    And the silken, sad, uncertain rustling of each purple curtain\nThrilled me—filled me with fantastic terrors never felt before;\n    So that now, to still the beating of my heart, I stood repeating\n    “’Tis some visitor entreating entrance at my chamber door—\nSome late visitor entreating entrance at my chamber door;—\n            This it is and nothing more.”\n\n    Presently my soul grew stronger; hesitating then no longer,\n“Sir,” said I, “or Madam, truly your forgiveness I implore;\n    But the fact is I was napping, and so gently you came rapping,\n    And so faintly you came tapping, tapping at my chamber door,\nThat I scarce was sure I heard you”—here I opened wide the door;—\n            Darkness there and nothing more.\n\nDeep into that darkness peering, long I stood there wondering, fearing,\nDoubting, dreaming dreams no mortal ever dared to dream before;\n    But the silence was unbroken, and the stillness gave no token,\n    And the only word there spoken was the whispered word, “Lenore?”\nThis I whispered, and an echo murmured back the word, “Lenore!”—\n            Merely this and nothing more.\n\n    Back into the chamber turning, all my soul within me burning,\nSoon again I heard a tapping somewhat louder than before.\n    “Surely,” said I, “surely that is something at my window lattice;\n      Let me see, then, what thereat is, and this mystery explore—\nLet my heart be still a moment and this mystery explore;—\n            ’Tis the wind and nothing more!”\n'\n\nconst lines = text.split('\\n')\n\nstruct App {\nmut:\n\tgg &gg.Context = unsafe { nil }\n}\n\nfn main() {\n\tmut app := &App{}\n\tapp.gg = gg.new_context(\n\t\twidth:         win_width\n\t\theight:        win_height\n\t\tcreate_window: true\n\t\twindow_title:  'Raven text'\n\t\tuser_data:     app\n\t\tbg_color:      bg_color\n\t\tframe_fn:      frame\n\t\tfont_path:     asset.get_path('../assets', 'fonts/RobotoMono-Regular.ttf')\n\t\t// window_user_ptr: ctx\n\t\t// native_rendering: true\n\t)\n\tapp.gg.run()\n}\n\nfn frame(mut app App) {\n\tapp.gg.begin()\n\twidth := gg.window_size().width\n\tmut scale_factor := math.round(f32(width) / win_width)\n\tif scale_factor <= 0 {\n\t\tscale_factor = 1\n\t}\n\ttext_cfg := gg.TextCfg{\n\t\tsize: 16 * int(scale_factor)\n\t}\n\tmut y := 10\n\tfor line in lines {\n\t\tapp.gg.draw_text(10, y, line, text_cfg)\n\t\ty += 30\n\t}\n\tapp.gg.end()\n}\n"
  },
  {
    "path": "examples/gg/raycaster.v",
    "content": "// Demonstrates how raycasting works. The left side shows\n// the 2D layout of the walls and player. The green lines\n// represent the field of view of the player.\n//\n// The right side is a simple 3D projection of the field\n// of view.\n//\n// There is no collision detection so yes, you can walk\n// through walls.\n//\n// Watch https://www.youtube.com/watch?v=gYRrGTC7GtA to\n// learn more on how this code works. There are some silly\n// digressons in the video but the tech content is spot on.\nimport gg\nimport math\n\nconst player_size = 8\nconst player_move_delta = 10\nconst map_x_size = 8\nconst map_y_size = 8\nconst map_square = 64\n\nstruct App {\nmut:\n\tctx          &gg.Context = unsafe { nil }\n\tplayer_x     f32\n\tplayer_y     f32\n\tplayer_dx    f32\n\tplayer_dy    f32\n\tplayer_angle f32\n\tmap          []int\n}\n\nfn main() {\n\tmut app := App{\n\t\tplayer_x: 230\n\t\tplayer_y: 320\n\t\t// each number represents an 8x8 square\n\t\t// 1 is a wall cube, 0 is empty space\n\t\tmap: [\n\t\t\t// vfmt off\n\t\t\t1, 1, 1, 1, 1, 1, 1, 1,\n\t\t\t1, 0, 0, 0, 0, 0, 0, 1,\n\t\t\t1, 0, 1, 1, 0, 0, 0, 1,\n\t\t\t1, 0, 1, 0, 0, 0, 0, 1,\n\t\t\t1, 0, 0, 0, 0, 0, 0, 1,\n\t\t\t1, 0, 0, 0, 0, 1, 0, 1,\n\t\t\t1, 0, 0, 0, 0, 0, 0, 1,\n\t\t\t1, 1, 1, 1, 1, 1, 1, 1,\n\t\t\t// vfmt on\n\t\t]\n\t}\n\n\tcalc_deltas(mut app)\n\n\tapp.ctx = gg.new_context(\n\t\tuser_data:    &app\n\t\twindow_title: 'Raycaster Demo'\n\t\twidth:        1024\n\t\theight:       512\n\t\tbg_color:     gg.gray\n\t\tframe_fn:     draw\n\t\tevent_fn:     handle_events\n\t)\n\n\tapp.ctx.run()\n}\n\nfn draw(mut app App) {\n\tapp.ctx.begin()\n\tdraw_map_2d(app)\n\tdraw_player(app)\n\tdraw_rays_and_walls(app)\n\tdraw_instructions(app)\n\tapp.ctx.end()\n}\n\nfn draw_map_2d(app App) {\n\tfor y := 0; y < map_y_size; y++ {\n\t\tfor x := 0; x < map_x_size; x++ {\n\t\t\tcolor := if app.map[y * map_x_size + x] == 1 { gg.white } else { gg.black }\n\t\t\tapp.ctx.draw_rect_filled(x * map_square, y * map_square, map_square - 1, map_square - 1,\n\t\t\t\tcolor)\n\t\t}\n\t}\n}\n\nfn draw_player(app App) {\n\tapp.ctx.draw_rect_filled(app.player_x, app.player_y, player_size, player_size, gg.yellow)\n\tcx := app.player_x + player_size / 2\n\tcy := app.player_y + player_size / 2\n\tapp.ctx.draw_line(cx, cy, cx + app.player_dx * 5, cy + app.player_dy * 5, gg.yellow)\n}\n\nfn draw_rays_and_walls(app App) {\n\tpi2 := math.pi / 2\n\tpi3 := 3 * math.pi / 2\n\tdegree_radian := f32(0.0174533)\n\tmax_depth_of_field := 8\n\tfield_of_view := 60 // 60 degrees\n\n\tmut distance := f32(0)\n\tmut depth_of_field := 0\n\tmut ray_x := f32(0)\n\tmut ray_y := f32(0)\n\tmut offset_x := f32(0)\n\tmut offset_y := f32(0)\n\tmut map_x := 0\n\tmut map_y := 0\n\tmut map_pos := 0\n\tmut color := gg.red\n\tmut ray_angle := clamp_ray_angle(app.player_angle - degree_radian * field_of_view / 2)\n\n\t// each step = 1/2 degree\n\tsteps := field_of_view * 2\n\n\tfor step := 0; step < steps; step++ {\n\t\t// check horizontal lines\n\t\tmut hd := f32(max_int)\n\t\tmut hx := app.player_x\n\t\tmut hy := app.player_y\n\t\tdepth_of_field = 0\n\t\tarc_tan := -1.0 / math.tanf(ray_angle)\n\t\tif ray_angle > math.pi { // looking up\n\t\t\tray_y = f32(int(app.player_y) / map_square * map_square) - .0001\n\t\t\tray_x = (app.player_y - ray_y) * arc_tan + app.player_x\n\t\t\toffset_y = -map_square\n\t\t\toffset_x = -offset_y * arc_tan\n\t\t} else if ray_angle < math.pi { // looking down\n\t\t\tray_y = f32(int(app.player_y) / map_square * map_square + map_square)\n\t\t\tray_x = (app.player_y - ray_y) * arc_tan + app.player_x\n\t\t\toffset_y = map_square\n\t\t\toffset_x = -offset_y * arc_tan\n\t\t} else if ray_angle == 0 || ray_angle == 2 * math.pi { // looking straight left/right\n\t\t\tray_x = app.player_x\n\t\t\tray_y = app.player_y\n\t\t\tdepth_of_field = max_depth_of_field\n\t\t}\n\t\tfor depth_of_field < max_depth_of_field {\n\t\t\tmap_x = int(ray_x) / map_square\n\t\t\tmap_y = int(ray_y) / map_square\n\t\t\tmap_pos = map_y * map_x_size + map_x\n\t\t\tif app.map[map_pos] or { 0 } == 1 {\n\t\t\t\t// hit a wall\n\t\t\t\thx = ray_x\n\t\t\t\thy = ray_y\n\t\t\t\thd = hypotenuse(app.player_x, app.player_y, hx, hy)\n\t\t\t\tdepth_of_field = max_depth_of_field\n\t\t\t} else { // go to next line\n\t\t\t\tray_x += offset_x\n\t\t\t\tray_y += offset_y\n\t\t\t\tdepth_of_field += 1\n\t\t\t}\n\t\t}\n\t\t// check vertical lines\n\t\tmut vd := f32(max_int)\n\t\tmut vx := app.player_x\n\t\tmut vy := app.player_y\n\t\tdepth_of_field = 0\n\t\tneg_tan := -math.tanf(ray_angle)\n\t\tif ray_angle > pi2 && ray_angle < pi3 { // looking left\n\t\t\tray_x = f32(int(app.player_x) / map_square * map_square) - .0001\n\t\t\tray_y = (app.player_x - ray_x) * neg_tan + app.player_y\n\t\t\toffset_x = -map_square\n\t\t\toffset_y = -offset_x * neg_tan\n\t\t} else if ray_angle < pi2 || ray_angle > pi3 { // looking right\n\t\t\tray_x = f32(int(app.player_x) / map_square * map_square + map_square)\n\t\t\tray_y = (app.player_x - ray_x) * neg_tan + app.player_y\n\t\t\toffset_x = map_square\n\t\t\toffset_y = -offset_x * neg_tan\n\t\t} else if ray_angle == 0 || ray_angle == 2 * math.pi { // looking straight up/down\n\t\t\tray_x = app.player_x\n\t\t\tray_y = app.player_y\n\t\t\tdepth_of_field = max_depth_of_field\n\t\t}\n\t\tfor depth_of_field < max_depth_of_field {\n\t\t\tmap_x = int(ray_x) / map_square\n\t\t\tmap_y = int(ray_y) / map_square\n\t\t\tmap_pos = map_y * map_x_size + map_x\n\t\t\tif app.map[map_pos] or { 0 } == 1 {\n\t\t\t\t// hit a wall\n\t\t\t\tvx = ray_x\n\t\t\t\tvy = ray_y\n\t\t\t\tvd = hypotenuse(app.player_x, app.player_y, vx, vy)\n\t\t\t\tdepth_of_field = max_depth_of_field\n\t\t\t} else { // go to next line\n\t\t\t\tray_x += offset_x\n\t\t\t\tray_y += offset_y\n\t\t\t\tdepth_of_field += 1\n\t\t\t}\n\t\t}\n\t\t// use the shorter of the horizontal and vertical distances to draw rays\n\t\t// use different colors for the two sides of the walls for lighting effect\n\t\tif vd < hd {\n\t\t\tray_x = vx\n\t\t\tray_y = vy\n\t\t\tdistance = vd\n\t\t\tcolor = gg.rgb(0, 100, 0)\n\t\t} else if hd < vd {\n\t\t\tray_x = hx\n\t\t\tray_y = hy\n\t\t\tdistance = hd\n\t\t\tcolor = gg.rgb(0, 120, 0)\n\t\t}\n\t\t// draw ray\n\t\tcx := app.player_x + player_size / 2\n\t\tcy := app.player_y + player_size / 2\n\t\tapp.ctx.draw_line(cx, cy, ray_x, ray_y, gg.green)\n\t\t// draw wall section\n\t\tmut ca := clamp_ray_angle(app.player_angle - ray_angle)\n\t\tdistance *= math.cosf(ca) // remove fish eye\n\t\toffset_3d_view := 530\n\t\tline_thickeness := 4\n\t\tmax_wall_height := 320\n\t\twall_height := math.min((map_square * max_wall_height) / distance, max_wall_height)\n\t\twall_offset := max_wall_height / 2 - wall_height / 2\n\t\tapp.ctx.draw_line_with_config(step * line_thickeness + offset_3d_view, wall_offset,\n\t\t\tstep * line_thickeness + offset_3d_view, wall_offset + wall_height, gg.PenConfig{\n\t\t\tcolor:     color\n\t\t\tthickness: line_thickeness\n\t\t})\n\t\t// step to next ray angle\n\t\tray_angle = clamp_ray_angle(ray_angle + degree_radian / 2)\n\t}\n}\n\nfn handle_events(event &gg.Event, mut app App) {\n\tif event.typ == .key_down {\n\t\tmatch event.key_code {\n\t\t\t.up {\n\t\t\t\tapp.player_x += app.player_dx\n\t\t\t\tapp.player_y += app.player_dy\n\t\t\t}\n\t\t\t.down {\n\t\t\t\tapp.player_x -= app.player_dx\n\t\t\t\tapp.player_y -= app.player_dy\n\t\t\t}\n\t\t\t.left {\n\t\t\t\tapp.player_angle -= 0.1\n\t\t\t\tif app.player_angle < 0 {\n\t\t\t\t\tapp.player_angle += 2 * math.pi\n\t\t\t\t}\n\t\t\t\tcalc_deltas(mut app)\n\t\t\t}\n\t\t\t.right {\n\t\t\t\tapp.player_angle += 0.1\n\t\t\t\tif app.player_angle > 2 * math.pi {\n\t\t\t\t\tapp.player_angle -= 2 * math.pi\n\t\t\t\t}\n\t\t\t\tcalc_deltas(mut app)\n\t\t\t}\n\t\t\telse {}\n\t\t}\n\t}\n}\n\nfn calc_deltas(mut app App) {\n\tapp.player_dx = math.cosf(app.player_angle) * 5\n\tapp.player_dy = math.sinf(app.player_angle) * 5\n}\n\nfn hypotenuse(ax f32, ay f32, bx f32, by f32) f32 {\n\ta2 := math.square(bx - ax)\n\tb2 := math.square(by - ay)\n\treturn math.sqrtf(a2 + b2)\n}\n\nfn clamp_ray_angle(ra f32) f32 {\n\treturn match true {\n\t\tra < 0 { ra + 2 * math.pi }\n\t\tra > 2 * math.pi { ra - 2 * math.pi }\n\t\telse { ra }\n\t}\n}\n\nfn draw_instructions(app App) {\n\tapp.ctx.draw_text(700, app.ctx.height - 17, 'use arrow keys to move player')\n}\n"
  },
  {
    "path": "examples/gg/rectangles.v",
    "content": "module main\n\nimport gg\nimport os.asset\n\nconst win_width = 600\nconst win_height = 300\n\nstruct App {\nmut:\n\tgg    &gg.Context = unsafe { nil }\n\timage int // gg.Image\n}\n\nfn main() {\n\tmut app := &App{}\n\tapp.gg = gg.new_context(\n\t\tbg_color:      gg.white\n\t\twidth:         win_width\n\t\theight:        win_height\n\t\tcreate_window: true\n\t\twindow_title:  'Rectangles'\n\t\tframe_fn:      frame\n\t\tuser_data:     app\n\t)\n\tlogo_path := asset.get_path('../assets', 'logo.png')\n\tapp.image = app.gg.create_image(logo_path)!.id\n\tapp.gg.run()\n}\n\nfn frame(app &App) {\n\tapp.gg.begin()\n\tapp.draw()\n\tapp.gg.end()\n}\n\nfn (app &App) draw() {\n\t// app.gg.draw_text_def(200,20, 'hello world!')\n\t// app.gg.draw_text_def(300,300, 'привет')\n\tapp.gg.draw_rect_filled(10, 10, 100, 30, gg.blue)\n\tapp.gg.draw_rect_empty(110, 150, 80, 40, gg.black)\n\tapp.gg.draw_image_by_id(230, 30, 200, 200, app.image)\n}\n"
  },
  {
    "path": "examples/gg/rotating_textured_quad.v",
    "content": "import gg\nimport os.asset\nimport sokol.sgl\n\n// If you have emscripten (see https://emscripten.org/docs/getting_started/index.html), you can compile this program to WASM, using:\n// `v -os wasm32_emscripten -o examples/gg/rotating_textured_quad.html examples/gg/rotating_textured_quad.v`, and later check with:\n// `emrun examples/gg/rotating_textured_quad.html` .\n#flag wasm32_emscripten --embed-file @VEXEROOT/examples/assets/logo.png@/assets/logo.png\n#flag wasm32_emscripten --embed-file @VEXEROOT/examples/assets/fonts/RobotoMono-Regular.ttf@/assets/RobotoMono-Regular.ttf\n\npub struct Window {\npub mut:\n\tctx &gg.Context = unsafe { nil }\n\timg gg.Image\n}\n\npub fn (mut window Window) init() {\n\timage_path := asset.get_path('../assets', 'logo.png')\n\twindow.img = window.ctx.create_image(image_path) or { panic(err) }\n}\n\npub fn (mut window Window) draw() {\n\tangle := f32(window.ctx.frame) / 64 // since window.ctx.frame is increased by 1 on every frame -> the angle will be increasing too\n\twindow.ctx.begin()\n\tsgl.load_pipeline(window.ctx.pipeline.alpha)\n\n\tsgl.translate(250, 250, 0) // center of the screen\n\tsgl.rotate(angle, 0.0, 0.0, 1.0) // rotate around the Z axis pointing towards the camera\n\n\tsgl.enable_texture()\n\tsgl.texture(window.img.simg, window.img.ssmp)\n\tsgl.begin_quads()\n\tsgl.c4b(255, 255, 255, 255)\n\tsgl.v3f_t2f(200, 200, 0, 1.0, 1.0)\n\tsgl.v3f_t2f(200, -200, 0, 1.0, 0.0)\n\tsgl.v3f_t2f(-200, -200, 0, 0.0, 0.0)\n\tsgl.v3f_t2f(-200, 200, 0, 0.0, 1.0)\n\tsgl.end()\n\tsgl.disable_texture()\n\twindow.ctx.end()\n}\n\nfn main() {\n\tmut window := &Window{}\n\twindow.ctx = gg.new_context(\n\t\twindow_title: 'Rotating V logo'\n\t\tbg_color:     gg.light_green\n\t\twidth:        500\n\t\theight:       500\n\t\tuser_data:    window\n\t\tinit_fn:      window.init\n\t\tframe_fn:     window.draw\n\t\tfont_path:    asset.get_path('../assets', 'RobotoMono-Regular.ttf')\n\t)\n\twindow.ctx.run()\n}\n"
  },
  {
    "path": "examples/gg/sample_count.v",
    "content": "module main\n\nimport gg\nimport os\n\nfn main() {\n\tscount := os.args[1] or { '2' }.int()\n\tprintln('> sample count: ${scount}')\n\tmut ctx := gg.new_context(\n\t\tbg_color:     gg.white\n\t\twindow_title: 'sample_count: ${scount}'\n\t\twidth:        320\n\t\theight:       240\n\t\tsample_count: scount\n\t\tframe_fn:     fn (mut ctx gg.Context) {\n\t\t\tctx.begin()\n\t\t\tctx.draw_rounded_rect_empty(110, 70, 100, 100, 10, gg.blue)\n\t\t\tctx.draw_circle_empty(160, 120, 100, gg.red)\n\t\t\tctx.draw_triangle_empty(160, 93, 186, 138, 132, 138, gg.green)\n\t\t\tctx.draw_rect_filled(159, 119, 2, 2, gg.black)\n\t\t\tctx.end()\n\t\t}\n\t)\n\tctx.run()\n}\n"
  },
  {
    "path": "examples/gg/spirograph.v",
    "content": "import gg\nimport math\n\nconst pixel_count = 15000\nconst p = 3\nconst s = math.pi * 2 / f32(pixel_count)\nconst color = gg.Color{255, 255, 255, 255}\nconst background = gg.Color{20, 20, 64, 5}\nconst colors = [\n\tgg.Color{255, 255, 255, 255},\n\tgg.Color{255, 0, 255, 255},\n\tgg.Color{255, 255, 0, 255},\n\tgg.Color{0, 255, 255, 255},\n\tgg.Color{0, 0, 255, 255},\n\tgg.Color{0, 0, 0, 255},\n]!\n\nmut k := 497\nmut scale := 200\ngg.start(\n\twindow_title: 'Spirograph'\n\tbg_color:     background\n\twidth:        900\n\theight:       950\n\tsample_count: 2\n\tframe_fn:     fn [mut k, mut scale] (mut ctx gg.Context) {\n\t\twsize := gg.window_size()\n\t\tctx.begin()\n\t\tctx.draw_rect_filled(0, 0, wsize.width, wsize.height, gg.Color{10, 1, 30, 60})\n\t\tt := f64(ctx.frame) / 300\n\t\td := math.sin(t)\n\t\tif math.abs(d) < 0.0015 {\n\t\t\tk++\n\t\t}\n\t\tif ctx.pressed_keys[int(gg.KeyCode._0)] {\n\t\t\tctx.frame = 475\n\t\t}\n\t\tif ctx.pressed_keys[int(gg.KeyCode.left)] {\n\t\t\tk--\n\t\t}\n\t\tif ctx.pressed_keys[int(gg.KeyCode.right)] {\n\t\t\tk++\n\t\t}\n\t\tif ctx.pressed_keys[int(gg.KeyCode.up)] {\n\t\t\tscale++\n\t\t}\n\t\tif ctx.pressed_keys[int(gg.KeyCode.down)] {\n\t\t\tscale--\n\t\t}\n\t\td600 := math.sin(f64(ctx.frame) / 60)\n\t\tcd600 := math.cos(d600)\n\t\tmut pdj, mut pkj := [p]f64{}, [p]f64{}\n\t\tfor j := 0; j < p; j++ {\n\t\t\tpdj[j], pkj[j] = math.pow(d, j), math.pow(k, j)\n\t\t}\n\t\tfor i := 0; i < pixel_count; i++ {\n\t\t\tmut x, mut y := 0.0, 0.0\n\t\t\tfor j := 0; j < p; j++ {\n\t\t\t\ta := pkj[j] * i * s\n\t\t\t\tx += pdj[j] * math.sin(a - t) * cd600\n\t\t\t\ty += pdj[j] * math.cos(a - t) * cd600\n\t\t\t}\n\t\t\tctx.draw_rect_filled(f32(wsize.width / 2 + scale * x), f32(wsize.height / 2 + scale * y),\n\t\t\t\t1, 1, colors[i % colors.len])\n\t\t}\n\t\tctx.draw_text(wsize.width / 2 - 170, wsize.height - 15, 'frame: ${ctx.frame:06}, k: ${k:4}, scale: ${scale:4}, arrows to change',\n\t\t\tcolor: colors[1]\n\t\t)\n\t\tctx.end(how: .passthru)\n\t}\n)\n"
  },
  {
    "path": "examples/gg/stars.v",
    "content": "module main\n\nimport os.asset\nimport gg\nimport rand\nimport sokol.sgl\n\nconst win_width = 800\nconst win_height = 600\nconst max_stars = 5000\nconst max_v_letters = 5\n\nstruct Star {\nmut:\n\tx f32\n\ty f32\n\tz f32\n\tr f32\n\tg f32\n\tb f32\n}\n\nstruct VLetter {\nmut:\n\tx      f32\n\ty      f32\n\tz      f32\n\tw      f32\n\th      f32\n\tangle  f32\n\tdz     f32\n\tdangle f32\n}\n\nstruct App {\nmut:\n\tgg        &gg.Context = unsafe { nil }\n\timage     gg.Image\n\tstars     []Star\n\tv_letters []VLetter\n}\n\nfn main() {\n\tmut app := &App{\n\t\tstars:     []Star{len: max_stars}\n\t\tv_letters: []VLetter{len: max_v_letters}\n\t}\n\tapp.gg = gg.new_context(\n\t\tbg_color:      gg.black\n\t\twidth:         win_width\n\t\theight:        win_height\n\t\tcreate_window: true\n\t\twindow_title:  'Star Vield'\n\t\tframe_fn:      frame\n\t\tinit_fn:       init_images\n\t\tuser_data:     app\n\t)\n\tfor i in 0 .. max_stars {\n\t\tapp.stars[i].x = rand.f32_in_range(-200.0, 200.0) or { -200.0 }\n\t\tapp.stars[i].y = rand.f32_in_range(-200.0, 200.0) or { -200.0 }\n\t\tapp.stars[i].z = rand.f32_in_range(-200.0, -100.0) or { -200.0 }\n\t\tapp.stars[i].r = rand.f32_in_range(0.1, 1.0) or { 0.1 }\n\t\tapp.stars[i].g = rand.f32_in_range(0.1, 1.0) or { 0.1 }\n\t\tapp.stars[i].b = rand.f32_in_range(0.1, 1.0) or { 0.1 }\n\t}\n\tfor i in 0 .. max_v_letters {\n\t\tapp.v_letters[i].x = rand.f32_in_range(-20.0, 20.0) or { -20.0 }\n\t\tapp.v_letters[i].y = rand.f32_in_range(-20.0, 20.0) or { -20.0 }\n\t\tapp.v_letters[i].z = rand.f32_in_range(-5.0, -1.0) or { -5.0 }\n\t\tapp.v_letters[i].w = rand.f32_in_range(5, 20) or { 5 }\n\t\tapp.v_letters[i].h = app.v_letters[i].w\n\t\tapp.v_letters[i].angle = rand.f32_in_range(0, 6.283184) or { 0 }\n\t\tapp.v_letters[i].dangle = rand.f32_in_range(-0.05, 0.05) or { -0.05 }\n\t\tapp.v_letters[i].dz = rand.f32_in_range(-0.1, -0.01) or { -0.1 }\n\t}\n\tapp.gg.run()\n}\n\nfn init_images(mut app App) {\n\tlogo_path := asset.get_path('../assets', 'logo.png')\n\tapp.image = app.gg.create_image(logo_path) or { panic(err) }\n}\n\nfn frame(mut app App) {\n\tapp.gg.begin()\n\tapp.draw()\n\tapp.gg.end()\n}\n\n// fn C.glPointSize(size f32)\nfn (mut app App) draw() {\n\tsgl.defaults()\n\tsgl.perspective(sgl.rad(90), 1.0, 1.0, 100.0)\n\t// C.glPointSize(3.0)\n\tsgl.begin_points()\n\tfor i in 0 .. app.stars.len {\n\t\ts := app.stars[i]\n\t\tsgl.v3f_c3f(s.x, s.y, s.z, s.r, s.g, s.b)\n\t\tapp.stars[i].z += 0.3\n\t\tif app.stars[i].z > -1.0 {\n\t\t\tapp.stars[i].x = rand.f32_in_range(-200.0, 200.0) or { -200.0 }\n\t\t\tapp.stars[i].y = rand.f32_in_range(-200.0, 200.0) or { -200.0 }\n\t\t\tapp.stars[i].z = rand.f32_in_range(-200.0, -100.0) or { -200.0 }\n\t\t}\n\t}\n\tsgl.end()\n\t// ////\n\tfor i in 0 .. app.v_letters.len {\n\t\tv := app.v_letters[i]\n\t\tsgl.defaults()\n\t\tsgl.perspective(sgl.rad(90), 1.0, 1.0, 100.0)\n\t\tsgl.rotate(v.angle, 0, 0, 1)\n\t\tapp.gg.draw_image_3d(v.x, v.y, v.z, v.w, v.h, app.image)\n\t\t//\n\t\tapp.v_letters[i].z += app.v_letters[i].dz\n\t\tapp.v_letters[i].angle += app.v_letters[i].dangle\n\t\tif app.v_letters[i].z > -60.0 {\n\t\t\tapp.v_letters[i].x += rand.f32_in_range(-0.05, 0.05) or { -0.05 }\n\t\t\tapp.v_letters[i].y += rand.f32_in_range(-0.05, 0.05) or { -0.05 }\n\t\t}\n\t\tif app.v_letters[i].z < -95.0 {\n\t\t\tapp.v_letters[i].h *= 0.8\n\t\t\tapp.v_letters[i].w *= 0.8\n\t\t}\n\t\tif app.v_letters[i].z < -100.0 {\n\t\t\tapp.v_letters[i].z = rand.f32_in_range(-5.0, -1.0) or { -5.0 }\n\t\t\tapp.v_letters[i].h = 10.0\n\t\t\tapp.v_letters[i].w = 10.0\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/gg/worker_thread.v",
    "content": "// Copyright(C) 2019 Lars Pontoppidan. All rights reserved.\n// Use of this source code is governed by an MIT license file distributed with this software package.\nmodule main\n\n// Example of how to send a value through a channel from a worker thread to the main/rendering thread.\n// This can be useful to do long running computations while keeping your framerate high (60 fps in this example).\nimport gg\nimport math\nimport time\n\nconst win_width = 600\nconst win_height = 700\nconst bg_color = gg.white\nconst count_color = gg.black\n\nstruct App {\nmut:\n\tgg      &gg.Context = unsafe { nil }\n\tch      chan i64\n\tcounter i64\n}\n\nfn main() {\n\tmut app := &App{}\n\tapp.gg = gg.new_context(\n\t\twidth:         win_width\n\t\theight:        win_height\n\t\tcreate_window: true\n\t\twindow_title:  'Counter'\n\t\tuser_data:     app\n\t\tbg_color:      bg_color\n\t\tframe_fn:      frame\n\t\tinit_fn:       init\n\t)\n\tapp.gg.run()\n}\n\nfn init(mut app App) {\n\t// Spawn a new worker thread.\n\tspawn worker(mut app)\n}\n\n// worker simulates a workload. This should be run in a separate thread.\nfn worker(mut app App) {\n\tstopwatch := time.new_stopwatch()\n\tmut elapsed := stopwatch.elapsed()\n\t// Do heavy operations here - like invoking a path finding algorithm, load an image or similar.\n\tfor {\n\t\tnow := stopwatch.elapsed()\n\t\t// When done - send the result through a channel to the main/rendering thread.\n\t\tapp.ch <- (now - elapsed)\n\t\telapsed = now\n\t\ttime.sleep(1 * time.second)\n\t}\n}\n\nfn frame(mut app App) {\n\tapp.gg.begin()\n\tsize := gg.window_size()\n\tmut scale_factor := math.round(f32(size.width) / win_width)\n\tif scale_factor <= 0 {\n\t\tscale_factor = 1\n\t}\n\ttext_cfg := gg.TextCfg{\n\t\tsize: 64 * int(scale_factor)\n\t}\n\n\t// Try a pop from the channel\n\tmut count := i64(0)\n\tif app.ch.try_pop(mut count) == .success {\n\t\t// A value was assigned - increase the counter\n\t\tapp.counter += i64(f64(count) / time.second)\n\t}\n\n\tlabel := '${app.counter}'\n\tlabel_width := (f64(label.len * text_cfg.size) / 4.0)\n\tlabel_height := (f64(1 * text_cfg.size) / 2.0)\n\tmut x := f32(size.width) * 0.5 - label_width\n\tmut y := f32(size.height) * 0.5 - label_height\n\n\tapp.gg.draw_text(int(x), int(y), label, text_cfg)\n\n\tapp.gg.end()\n}\n"
  },
  {
    "path": "examples/gg/x_y_frame.v",
    "content": "import gg\nimport time\n\nconst pwidth = 640\nconst pheight = 480\n\nstruct AppState {\nmut:\n\tgg          &gg.Context = unsafe { nil }\n\tistream_idx int\n\tpixels      [pheight][pwidth]u32\n}\n\n@[direct_array_access]\nfn (mut state AppState) update() {\n\tmut rcolor := u32(0)\n\tfor {\n\t\tfor y in 0 .. pheight {\n\t\t\tfor x in 0 .. pwidth {\n\t\t\t\trcolor = x * y * u32(state.gg.frame)\n\t\t\t\tstate.pixels[y][x] = u32(rcolor) | 0xFF_00_00_00 // set the alpha channel to 255\n\t\t\t}\n\t\t}\n\t\ttime.sleep(16 * time.millisecond)\n\t}\n}\n\nfn graphics_init(mut state AppState) {\n\tstate.istream_idx = state.gg.new_streaming_image(pwidth, pheight, 4, pixel_format: .rgba8)\n}\n\nfn graphics_frame(mut state AppState) {\n\tstate.gg.begin()\n\tmut istream_image := state.gg.get_cached_image_by_idx(state.istream_idx)\n\tistream_image.update_pixel_data(unsafe { &u8(&state.pixels) })\n\tsize := gg.window_size()\n\tstate.gg.draw_image(0, 0, size.width, size.height, istream_image)\n\tstate.gg.end()\n}\n\nmut state := &AppState{}\nstate.gg = gg.new_context(\n\twidth:        pwidth\n\theight:       pheight\n\twindow_title: 'x*y*frame'\n\tuser_data:    state\n\tinit_fn:      graphics_init\n\tframe_fn:     graphics_frame\n)\nspawn state.update()\nstate.gg.run()\n"
  },
  {
    "path": "examples/graphs/bellman-ford.v",
    "content": "/*\nA V program for Bellman-Ford's single source\nshortest path algorithm.\nliterally adapted from:\nhttps://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/\n// Adapted from this site... from C++ and Python codes\n\nFor Portuguese reference\nhttp://rascunhointeligente.blogspot.com/2010/10/o-algoritmo-de-bellman-ford-um.html\n\ncode by CCS\n*/\n\nconst large = 999999 // almost infinity\n\n// a structure to represent a weighted edge in graph\nstruct EDGE {\nmut:\n\tsrc    int\n\tdest   int\n\tweight int\n}\n\n// building a map of with all edges etc of a graph, represented from a matrix adjacency\n// Input: matrix adjacency --> Output: edges list of src, dest and weight\nfn build_map_edges_from_graph[T](g [][]T) map[T]EDGE {\n\tn := g.len // TOTAL OF NODES for this graph -- its dimensions\n\tmut edges_map := map[int]EDGE{} // a graph represented by map of edges\n\n\tmut edge := 0 // a counter of edges\n\tfor i in 0 .. n {\n\t\tfor j in 0 .. n {\n\t\t\t// if exist an arc ... include as new edge\n\t\t\tif g[i][j] != 0 {\n\t\t\t\tedges_map[edge] = EDGE{i, j, g[i][j]}\n\t\t\t\tedge++\n\t\t\t}\n\t\t}\n\t}\n\t// print('${edges_map}')\n\treturn edges_map\n}\n\nfn print_sol(dist []int) {\n\tn_vertex := dist.len\n\tprint('\\n Vertex   Distance from Source')\n\tfor i in 0 .. n_vertex {\n\t\tprint('\\n   ${i}   -->   ${dist[i]}')\n\t}\n}\n\n// The main function that finds shortest distances from src\n// to all other vertices using Bellman-Ford algorithm.  The\n// function also detects negative weight cycle\nfn bellman_ford[T](graph [][]T, src int) {\n\tmut edges := build_map_edges_from_graph[int](graph)\n\t// this function was done to adapt a graph representation\n\t// by a adjacency matrix, to list of adjacency (using a MAP)\n\tn_edges := edges.len // number of EDGES\n\n\t// Step 1: Initialize distances from src to all other\n\t// vertices as INFINITE\n\tn_vertex := graph.len // adjc matrix ... n nodes or vertex\n\tmut dist := []int{len: n_vertex, init: large} // dist with -1 instead of INFINITY\n\t// mut path := []int{len: n , init:-1} // previous node of each shortest path\n\tdist[src] = 0\n\n\t// Step 2: Relax all edges |V| - 1 times. A simple\n\t// shortest path from src to any other vertex can have\n\t// at-most |V| - 1 edges\n\n\tfor _ in 0 .. n_vertex {\n\t\tfor j in 0 .. n_edges {\n\t\t\tmut u := edges[j].src\n\t\t\tmut v := edges[j].dest\n\t\t\tmut weight := edges[j].weight\n\t\t\tif dist[u] != large && dist[u] + weight < dist[v] {\n\t\t\t\tdist[v] = dist[u] + weight\n\t\t\t}\n\t\t}\n\t}\n\n\t// Step 3: check for negative-weight cycles.  The above\n\t// step guarantees shortest distances if graph doesn't\n\t// contain negative weight cycle.  If we get a shorter\n\t// path, then there is a cycle.\n\tfor j in 0 .. n_vertex {\n\t\tmut u := edges[j].src\n\t\tmut v := edges[j].dest\n\t\tmut weight := edges[j].weight\n\t\tif dist[u] != large && dist[u] + weight < dist[v] {\n\t\t\tprint('\\n Graph contains negative weight cycle')\n\t\t\t// If negative cycle is detected, simply\n\t\t\t// return or an exit(1)\n\t\t\treturn\n\t\t}\n\t}\n\tprint_sol(dist)\n}\n\nfn main() {\n\t// adjacency matrix = cost or weight\n\tgraph_01 := [\n\t\t[0, -1, 4, 0, 0],\n\t\t[0, 0, 3, 2, 2],\n\t\t[0, 0, 0, 0, 0],\n\t\t[0, 1, 5, 0, 0],\n\t\t[0, 0, 0, -3, 0],\n\t]\n\t// data from https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/\n\n\tgraph_02 := [\n\t\t[0, 2, 0, 6, 0],\n\t\t[2, 0, 3, 8, 5],\n\t\t[0, 3, 0, 0, 7],\n\t\t[6, 8, 0, 0, 9],\n\t\t[0, 5, 7, 9, 0],\n\t]\n\t// data from https://www.geeksforgeeks.org/prims-minimum-spanning-tree-mst-greedy-algo-5/\n\t/*\n\tThe graph:\n        2    3\n    (0)--(1)--(2)\n    |    / \\    |\n   6|  8/   \\5  |7\n    |  /     \\  |\n    (3)-------(4)\n         9\n\t*/\n\n\t/*\n\tLet us create following weighted graph\n From https://www.geeksforgeeks.org/kruskals-minimum-spanning-tree-algorithm-greedy-algo-2/?ref=lbp\n                   10\n              0--------1\n              |  \\     |\n             6|   5\\   |15\n              |      \\ |\n              2--------3\n                  4\n\t*/\n\tgraph_03 := [\n\t\t[0, 10, 6, 5],\n\t\t[10, 0, 0, 15],\n\t\t[6, 0, 0, 4],\n\t\t[5, 15, 4, 0],\n\t]\n\n\t// To find number of columns\n\t// mut cols := an_array[0].len\n\tmut graph := [][]int{} // the graph: adjacency matrix\n\t// for index, g_value in [graph_01, graph_02, graph_03] {\n\tfor index, g_value in [graph_01, graph_02, graph_03] {\n\t\tgraph = g_value.clone() // graphs_sample[g].clone() // choice your SAMPLE\n\t\t// always starting by node 0\n\t\tstart_node := 0\n\t\tprintln('\\n\\n Graph ${index + 1} using Bellman-Ford algorithm (source node: ${start_node})')\n\t\tbellman_ford(graph, start_node)\n\t}\n\tprintln('\\n BYE -- OK')\n}\n"
  },
  {
    "path": "examples/graphs/bfs.v",
    "content": "fn main() {\n\tgraph := {\n\t\t'A': ['B', 'C']\n\t\t'B': ['A', 'D', 'E']\n\t\t'C': ['A', 'F']\n\t\t'D': ['B']\n\t\t'E': ['B', 'F']\n\t\t'F': ['C', 'E']\n\t}\n\tprintln('Graph: ${graph}')\n\tpath := breadth_first_search_path(graph, 'A', 'F')\n\tprintln('The shortest path from node A to node F is: ${path}')\n\tassert path == ['A', 'C', 'F']\n}\n\n// Breadth-First Search (BFS) allows you to ﬁnd the shortest distance between two nodes in the graph.\nfn breadth_first_search_path(graph map[string][]string, vertex string, target string) []string {\n\tmut path := []string{}\n\tmut visited := []string{len: 6, init: vertex}\n\tmut queue := [][][]string{}\n\tqueue << [[vertex], path]\n\tfor queue.len > 0 {\n\t\tmut idx := queue.len - 1\n\t\tnode := queue[idx][0][0]\n\t\tpath = queue[idx][1]\n\t\tqueue.delete(idx)\n\t\tif node == target {\n\t\t\tpath << node\n\t\t\treturn path\n\t\t}\n\t\tfor child in graph[node] {\n\t\t\tmut tmp := path.clone()\n\t\t\tif child !in visited {\n\t\t\t\tvisited << child\n\t\t\t\ttmp << node\n\t\t\t\tqueue << [[child], tmp]\n\t\t\t}\n\t\t}\n\t}\n\treturn path\n}\n"
  },
  {
    "path": "examples/graphs/bfs2.v",
    "content": "// Author: CCS\n// I follow literally code in C, done many years ago\nfn main() {\n\t// Adjacency matrix as a map\n\tgraph := {\n\t\t'A': ['B', 'C']\n\t\t'B': ['A', 'D', 'E']\n\t\t'C': ['A', 'F']\n\t\t'D': ['B']\n\t\t'E': ['B', 'F']\n\t\t'F': ['C', 'E']\n\t}\n\tprintln('Graph: ${graph}')\n\tpath := breadth_first_search_path(graph, 'A', 'F')\n\tprintln('\\n The shortest path from node A to node F is: ${path.reverse()}')\n}\n\n// Breadth-First Search (BFS) allows you to find the shortest distance between two nodes in the graph.\nfn breadth_first_search_path(graph map[string][]string, start string, target string) []string {\n\tmut path := []string{} // ONE PATH with SUCCESS = array\n\tmut queue := []string{} // a queue ... many paths\n\t// all_nodes := graph.keys() // get a key of this map\n\t// a map to store all the nodes visited to avoid cycles\n\t// start all them with False, not visited yet\n\tmut visited := visited_init(graph) // a map fully\n\t// false ==> not visited yet: {'A': false, 'B': false, 'C': false, 'D': false, 'E': false}\n\tqueue << start // first arrival\n\tfor queue.len != 0 {\n\t\tmut node := departure(mut queue) // get the front node and remove it\n\t\tif visited[node] == false { // check if this node is already visited\n\t\t\t// if no ... test it searchinf for a final node\n\t\t\tvisited[node] = true // means: visit this node\n\t\t\tif node == target {\n\t\t\t\tpath = build_path_reverse(graph, start, node, visited)\n\t\t\t\treturn path\n\t\t\t}\n\t\t\t// Expansion of node removed from  queue\n\t\t\tprint('\\n Expansion of node ${node} (true/false): ${graph[node]}')\n\t\t\t// take  all nodes from the node\n\t\t\tfor vertex in graph[node] { // println(\"\\n ...${vertex}\")\n\t\t\t\t// not explored yet\n\t\t\t\tif visited[vertex] == false {\n\t\t\t\t\tqueue << vertex\n\t\t\t\t}\n\t\t\t}\n\t\t\tprint('\\n QUEUE: ${queue} (only not visited) \\n Visited: ${visited}')\n\t\t}\n\t}\n\tpath = ['Path not found, problem in the Graph, start or end nodes! ']\n\treturn path\n}\n\n// classical removing of a node from the start of a queue\nfn departure(mut queue []string) string {\n\tmut x := queue[0]\n\tqueue.delete(0)\n\treturn x\n}\n\n// Creating aa map to initialize with of visited nodes .... all with false in the init\n// so these nodes are NOT VISITED YET\nfn visited_init(a_graph map[string][]string) map[string]bool {\n\tmut temp := map[string]bool{} // attention in these initializations with maps\n\tfor i, _ in a_graph {\n\t\ttemp[i] = false\n\t}\n\treturn temp\n}\n\n// Based in the current node that is final, search for its parent, already visited, up to the root or start node\nfn build_path_reverse(graph map[string][]string, start string, final string, visited map[string]bool) []string {\n\tprint('\\n\\n Nodes visited (true) or no (false): ${visited}')\n\tarray_of_nodes := graph.keys()\n\tmut current := final\n\tmut path := []string{}\n\tpath << current\n\n\tfor (current != start) {\n\t\tfor i in array_of_nodes {\n\t\t\tif current in graph[i] && visited[i] == true {\n\t\t\t\tcurrent = i\n\t\t\t\tbreak // the first occurrence is enough\n\t\t\t}\n\t\t}\n\t\tpath << current // update the path tracked\n\t}\n\treturn path\n}\n\n//======================================================\n"
  },
  {
    "path": "examples/graphs/bfs3.v",
    "content": "// Author: CCS & KeitoTobi1\n// Backtracking Supported.\nimport datatypes\n\nfn find_pattern(adj map[string][]string, start string, target string) [][]string {\n\tmut visited := visited_init(adj)\n\tmut queue := datatypes.Queue[[]string]{}\n\tmut res := [][]string{}\n\tqueue.push([start])\n\tfor !queue.is_empty() {\n\t\tmut v := queue.pop() or { panic(err) }\n\t\tnode := v.last()\n\t\tif node == target {\n\t\t\tres << v\n\t\t}\n\t\tprint('Expansion of node ${node} (true/false): ${adj[node]}')\n\t\tfor next in adj[node] {\n\t\t\tif visited[next] == false {\n\t\t\t\tmut copy := v.clone()\n\t\t\t\tcopy << next\n\t\t\t\tqueue.push(copy)\n\t\t\t\tvisited[node] = true\n\t\t\t}\n\t\t}\n\t\tprint('Expansion of node ${queue} (true/false): ${visited}\\n')\n\t}\n\treturn res\n}\n\nfn print_pattern(pat [][]string) {\n\tfor p in pat {\n\t\tprintln(p)\n\t}\n}\n\nfn visited_init(adj map[string][]string) map[string]bool {\n\tmut temp := map[string]bool{}\n\tfor i, _ in adj {\n\t\ttemp[i] = false\n\t}\n\treturn temp\n}\n\nfn main() {\n\tadj := {\n\t\t'A': ['B', 'C']\n\t\t'B': ['A', 'D', 'E']\n\t\t'C': ['A', 'F']\n\t\t'D': ['B']\n\t\t'E': ['B', 'F']\n\t\t'F': ['C', 'E']\n\t}\n\n\tpath := find_pattern(adj, 'A', 'F')\n\tprintln('The all pattern path from node A to node F is:')\n\tprint_pattern(path)\n}\n"
  },
  {
    "path": "examples/graphs/dfs.v",
    "content": "// Author: CCS\n// I follow literally code in C, done many years ago\n\nfn main() {\n\t// Adjacency matrix as a map\n\t// Example 01\n\tgraph_01 := {\n\t\t'A': ['B', 'C']\n\t\t'B': ['A', 'D', 'E']\n\t\t'C': ['A', 'F']\n\t\t'D': ['B']\n\t\t'E': ['F', 'B', 'F']\n\t\t'F': ['C', 'E']\n\t}\n\t// Example 02\n\tgraph_02 := {\n\t\t'A': ['B', 'C', 'D']\n\t\t'B': ['E']\n\t\t'C': ['F']\n\t\t'D': ['E']\n\t\t'E': ['H']\n\t\t'F': ['H']\n\t\t'G': ['H']\n\t\t'H': ['E', 'F', 'G']\n\t}\n\tpath_01 := depth_first_search_path(graph_01, 'A', 'F')\n\tprintln('\\n Graph_01: a first path from node A to node F is: ${path_01.reverse()}')\n\tpath_02 := depth_first_search_path(graph_02, 'A', 'H')\n\tprintln('\\n Graph_02: a first path from node A to node H is: ${path_02.reverse()}')\n}\n\n// Depth-First Search (BFS) allows you to find a path between two nodes in the graph.\nfn depth_first_search_path(graph map[string][]string, start string, target string) []string {\n\tmut path := []string{} // ONE PATH with SUCCESS = array\n\tmut stack := []string{} // a stack ... many nodes\n\t// all_nodes := graph.keys() // get a key of this map\n\tmut visited := visited_init(graph) // a map fully with false in all vertex\n\t// false ... not visited yet: {'A': false, 'B': false, 'C': false, 'D': false, 'E': false}\n\n\tstack << start // first push on the stack\n\tfor stack.len > 0 {\n\t\tmut node := stack.pop() // get the top node and remove it from the stack\n\n\t\t// check if this node is already visited\n\t\tif visited[node] == false {\n\t\t\t// if no ... test it and search for a final node\n\t\t\tvisited[node] = true // means: node visited\n\t\t\tif node == target {\n\t\t\t\tpath = build_path_reverse(graph, start, node, visited)\n\t\t\t\treturn path\n\t\t\t}\n\t\t\t//  Exploring of node removed from  stack and add its relatives\n\t\t\tprint('\\n Exploring of node ${node} (true/false): ${graph[node]}')\n\t\t\t// graph[node].reverse() take a classical choice for DFS\n\t\t\t// at most os left in this case.\n\t\t\t// use vertex in graph[node] the choice is right\n\n\t\t\t// take  all nodes from the node\n\t\t\tfor vertex in graph[node].reverse() {\n\t\t\t\t// println(\"\\n ...${vertex}\")\n\t\t\t\t// not explored yet\n\t\t\t\tif visited[vertex] == false {\n\t\t\t\t\tstack << vertex\n\t\t\t\t}\n\t\t\t}\n\t\t\tprint('\\n Stack: ${stack} (only not visited) \\n Visited: ${visited}')\n\t\t}\n\t}\n\tpath = ['Path not found, problem in the Graph, start or end nodes! ']\n\treturn path\n}\n\n// Creating aa map to initialize with of visited nodes .... all with false in the init\n// so these nodes are NOT VISITED YET\nfn visited_init(a_graph map[string][]string) map[string]bool {\n\tmut temp := map[string]bool{} // attention in these initializations with maps\n\tfor i, _ in a_graph {\n\t\ttemp[i] = false\n\t}\n\treturn temp\n}\n\n// Based in the current node that is final, search for his parent, that is already visited, up to the root or start node\nfn build_path_reverse(graph map[string][]string, start string, final string, visited map[string]bool) []string {\n\tprint('\\n\\n Nodes visited (true) or no (false): ${visited}')\n\tarray_of_nodes := graph.keys()\n\tmut current := final\n\tmut path := []string{}\n\tpath << current\n\n\tfor current != start {\n\t\tfor i in array_of_nodes {\n\t\t\tif current in graph[i] && visited[i] == true {\n\t\t\t\tcurrent = i\n\t\t\t\tbreak // the first occurrence is enough\n\t\t\t}\n\t\t}\n\t\tpath << current // updating the path tracked\n\t}\n\treturn path\n}\n\n//*****************************************************\n"
  },
  {
    "path": "examples/graphs/dfs2.v",
    "content": "// Author: CCS & KeitoTobi1\n// Backtracking Supported.\nfn main() {\n\t// Adjacency matrix as a map\t\n\t// Example 01\n\tgraph_01 := {\n\t\t'A': ['B', 'C']\n\t\t'B': ['A', 'D', 'E']\n\t\t'C': ['A', 'F']\n\t\t'D': ['B']\n\t\t'E': ['F', 'B', 'F']\n\t\t'F': ['C', 'E']\n\t}\n\n\t// Example 02\n\tgraph_02 := {\n\t\t'A': ['B', 'C', 'D']\n\t\t'B': ['E']\n\t\t'C': ['F']\n\t\t'D': ['E']\n\t\t'E': ['H']\n\t\t'F': ['H']\n\t\t'G': ['H']\n\t\t'H': ['E', 'F', 'G']\n\t}\n\n\tpath_01 := depth_first_search_path(graph_01, 'A', 'F')\n\tprintln('\\n Graph_01: all path pattern from node A to node F is:')\n\tprint_pattern(path_01)\n\tpath_02 := depth_first_search_path(graph_02, 'A', 'H')\n\tprintln('\\n Graph_02: all path pattern from node A to node F is:')\n\tprint_pattern(path_02)\n}\n\nfn depth_first_search_path(adj map[string][]string, start string, target string) [][]string {\n\tmut sol := Solution{}\n\tmut path := []string{}\n\tmut visited := visited_init(adj)\n\n\t// false ... not visited yet: {'A': false, 'B': false, 'C': false, 'D': false, 'E': false}\n\tsol.find_pattern(adj, mut visited, start, target, mut path)\n\treturn sol.pattern\n}\n\nstruct Solution {\npub mut:\n\tpattern [][]string\n}\n\nfn (mut s Solution) find_pattern(adj map[string][]string, mut visited map[string]bool, node string, target string,\n\tmut path []string) {\n\tpath << node\n\tvisited[node] = true\n\tif node == target {\n\t\tprint('\\n Founded pattern: ${path}')\n\t\ts.pattern << [path]\n\t}\n\tprint('\\n Exploring of node ${node} (true/false): ${adj[node]}')\n\tfor i, _ in adj[node] {\n\t\tif !visited[adj[node][i]] {\n\t\t\tmut temp := path.clone()\n\t\t\ts.find_pattern(adj, mut visited, adj[node][i], target, mut temp)\n\t\t}\n\t}\n\tvisited[node] = false\n\tprint('\\n Current: ${node} (only not visited) \\n Visited: ${visited}')\n}\n\nfn print_pattern(pat [][]string) {\n\tfor p in pat {\n\t\tprintln(p)\n\t}\n}\n\n// Creating aa map to initialize with of visited nodes .... all with false in the init\n// so these nodes are NOT VISITED YET\nfn visited_init(adj map[string][]string) map[string]bool {\n\tmut temp := map[string]bool{}\n\tfor i, _ in adj {\n\t\ttemp[i] = false\n\t}\n\treturn temp\n}\n"
  },
  {
    "path": "examples/graphs/dijkstra.v",
    "content": "/*\nExploring  Dijkstra,\nThe data example is from\nhttps://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-greedy-algo-7/\n\nby CCS\nDijkstra's single source shortest path algorithm.\nThe program uses an adjacency matrix representation of a graph\n\nThis Dijkstra algorithm uses a priority queue to save\nthe shortest paths. The queue structure has a data\nwhich is the number of the node,\nand the priority field which is the shortest distance.\n\nPS: all the pre-requisites of Dijkstra are considered\n\n$ v   run file_name.v\n// Creating a executable\n$ v  run file_name.v  -o an_executable.EXE\n$ ./an_executable.EXE\n\nCode based from : Data Structures and Algorithms Made Easy: Data Structures and Algorithmic Puzzles, Fifth Edition (English Edition)\npseudo code written in C\nThis idea is quite different: it uses a priority queue to store the current\nshortest path evaluated\nThe priority queue structure built using a list to simulate\nthe queue. A heap is not used in this case.\n*/\n\n// a structure\nstruct NODE {\nmut:\n\tdata     int // NUMBER OF NODE\n\tpriority int // Lower values priority indicate ==> higher priority\n}\n\n// Function to push according to priority ... the lower priority is goes ahead\n// The \"push\" always sorted in pq\nfn push_pq[T](mut prior_queue []T, data int, priority int) {\n\tmut temp := []T{}\n\tpq_len := prior_queue.len\n\n\tmut i := 0\n\tfor i < pq_len && priority > prior_queue[i].priority {\n\t\ttemp << prior_queue[i]\n\t\ti++\n\t}\n\t// INSERTING SORTED in the queue\n\ttemp << NODE{data, priority} // do the copy in the right place\n\t// copy the another part (tail) of original prior_queue\n\tfor i < pq_len {\n\t\ttemp << prior_queue[i]\n\t\ti++\n\t}\n\tprior_queue = temp.clone() // I am not sure if it the right way\n\t// IS IT THE RIGHT WAY?\n}\n\n// Change the priority of a value/node ... exist a value, change its priority\nfn updating_priority[T](mut prior_queue []T, search_data int, new_priority int) {\n\tmut i := 0\n\tmut pq_len := prior_queue.len\n\n\tfor i < pq_len {\n\t\tif search_data == prior_queue[i].data {\n\t\t\tprior_queue[i] = NODE{search_data, new_priority} // do the copy in the right place\n\t\t\tbreak\n\t\t}\n\t\ti++\n\t\t// all the list was examined\n\t\tif i >= pq_len {\n\t\t\tprint('\\n This data ${search_data} does exist ... PRIORITY QUEUE problem\\n')\n\t\t\texit(1) // panic(s string)\n\t\t}\n\t} // end for\n}\n\n// a single departure or remove from queue\nfn departure_priority[T](mut prior_queue []T) int {\n\tmut x := prior_queue[0].data\n\tprior_queue.delete(0) // or .delete_many(0, 1 )\n\treturn x\n}\n\n// give a NODE v, return a list with all adjacents\n// Take care, only positive EDGES\nfn all_adjacents[T](g [][]T, v int) []int {\n\tmut temp := []int{}\n\tfor i in 0 .. (g.len) {\n\t\tif g[v][i] > 0 {\n\t\t\ttemp << i\n\t\t}\n\t}\n\treturn temp\n}\n\n// print the costs from origin up to all nodes\nfn print_solution[T](dist []T) {\n\tprint('Vertex \\tDistance from Source')\n\tfor node in 0 .. (dist.len) {\n\t\tprint('\\n ${node} ==> \\t ${dist[node]}')\n\t}\n}\n\n// print all  paths and their cost or weight\nfn print_paths_dist[T](path []T, dist []T) {\n\tprint('\\n Read the nodes from right to left (a path): \\n')\n\n\tfor node in 1 .. (path.len) {\n\t\tprint('\\n ${node} ')\n\t\tmut i := node\n\t\tfor path[i] != -1 {\n\t\t\tprint(' <= ${path[i]} ')\n\t\t\ti = path[i]\n\t\t}\n\t\tprint('\\t PATH COST: ${dist[node]}')\n\t}\n}\n\n// check structure from: https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-greedy-algo-7/\n// s: source for all nodes\n// Two results are obtained ... cost and paths\nfn dijkstra(g [][]int, s int) {\n\tmut pq_queue := []NODE{} // creating a priority queue\n\tpush_pq(mut pq_queue, s, 0) // goes s with priority 0\n\tmut n := g.len\n\n\tmut dist := []int{len: n, init: -1} // dist with -1 instead of INFINITE\n\tmut path := []int{len: n, init: -1} // previous node of each shortest path\n\n\t// Distance of source vertex from itself is always 0\n\tdist[s] = 0\n\n\tfor pq_queue.len != 0 {\n\t\tmut v := departure_priority(mut pq_queue)\n\t\t// for all W adjacents vertices of v\n\t\tmut adjs_of_v := all_adjacents(g, v) // all_ADJ of v ....\n\t\t// print('\\n ADJ ${v} is ${adjs_of_v}')\n\t\tmut new_dist := 0\n\t\tfor w in adjs_of_v {\n\t\t\tnew_dist = dist[v] + g[v][w]\n\t\t\tif dist[w] == -1 {\n\t\t\t\tdist[w] = new_dist\n\t\t\t\tpush_pq(mut pq_queue, w, dist[w])\n\t\t\t\tpath[w] = v // collecting the previous node -- lowest weight\n\t\t\t}\n\t\t\tif dist[w] > new_dist {\n\t\t\t\tdist[w] = new_dist\n\t\t\t\tupdating_priority(mut pq_queue, w, dist[w])\n\t\t\t\tpath[w] = v\n\t\t\t}\n\t\t}\n\t}\n\n\t// print the constructed distance array\n\tprint_solution(dist)\n\t// print('\\n \\n Previous node of shortest path: ${path}')\n\tprint_paths_dist(path, dist)\n}\n\n/*\nSolution Expected\nVertex   Distance from Source\n0                0\n1                4\n2                12\n3                19\n4                21\n5                11\n6                9\n7                8\n8                14\n*/\n\nfn main() {\n\t// adjacency matrix = cost or weight\n\tgraph_01 := [\n\t\t[0, 4, 0, 0, 0, 0, 0, 8, 0],\n\t\t[4, 0, 8, 0, 0, 0, 0, 11, 0],\n\t\t[0, 8, 0, 7, 0, 4, 0, 0, 2],\n\t\t[0, 0, 7, 0, 9, 14, 0, 0, 0],\n\t\t[0, 0, 0, 9, 0, 10, 0, 0, 0],\n\t\t[0, 0, 4, 14, 10, 0, 2, 0, 0],\n\t\t[0, 0, 0, 0, 0, 2, 0, 1, 6],\n\t\t[8, 11, 0, 0, 0, 0, 1, 0, 7],\n\t\t[0, 0, 2, 0, 0, 0, 6, 7, 0],\n\t]\n\n\tgraph_02 := [\n\t\t[0, 2, 0, 6, 0],\n\t\t[2, 0, 3, 8, 5],\n\t\t[0, 3, 0, 0, 7],\n\t\t[6, 8, 0, 0, 9],\n\t\t[0, 5, 7, 9, 0],\n\t]\n\t// data from https://www.geeksforgeeks.org/prims-minimum-spanning-tree-mst-greedy-algo-5/\n\t/*\n\tThe graph:\n        2    3\n    (0)--(1)--(2)\n    |    / \\    |\n   6|  8/   \\5  |7\n    |  /     \\  |\n    (3)-------(4)\n         9\n\t*/\n\n\t/*\n\tLet us create following weighted graph\n From https://www.geeksforgeeks.org/kruskals-minimum-spanning-tree-algorithm-greedy-algo-2/?ref=lbp\n                   10\n              0--------1\n              |  \\     |\n             6|   5\\   |15\n              |      \\ |\n              2--------3\n                  4\n\t*/\n\tgraph_03 := [\n\t\t[0, 10, 6, 5],\n\t\t[10, 0, 0, 15],\n\t\t[6, 0, 0, 4],\n\t\t[5, 15, 4, 0],\n\t]\n\n\t// To find number of columns\n\t// mut cols := an_array[0].len\n\tmut graph := [][]int{} // the graph: adjacency matrix\n\t// for index, g_value in [graph_01, graph_02, graph_03] {\n\tfor index, g_value in [graph_01, graph_02, graph_03] {\n\t\tgraph = g_value.clone() // graphs_sample[g].clone() // choice your SAMPLE\n\t\t// always starting by node 0\n\t\tstart_node := 0\n\t\tprintln('\\n\\n Graph ${index + 1} using Dijkstra algorithm (source node: ${start_node})')\n\t\tdijkstra(graph, start_node)\n\t}\n\n\tprintln('\\n BYE -- OK')\n}\n"
  },
  {
    "path": "examples/graphs/minimal_spann_tree_prim.v",
    "content": "/*\nExploring PRIMS,\nThe data example is from\nhttps://www.geeksforgeeks.org/prims-minimum-spanning-tree-mst-greedy-algo-5/\n\nby CCS\n\nPS: all the pre-requisites of Dijkstra are considered\n\n$ v run file_name.v\n\nCreating a executable\n$ v -o an_executable.EXE run file_name.v\n$ ./an_executable.EXE\n\nCode based from : Data Structures and Algorithms Made Easy: Data Structures and Algorithmic Puzzles, Fifth Edition (English Edition)\npseudo code written in C\nThis idea is quite different: it uses a priority queue to store the current\nshortest path evaluated\nThe priority queue structure built using a list to simulate\nthe queue. A heap is not used in this case.\n*/\n\n// a structure\nstruct NODE {\nmut:\n\tdata     int // number of nodes\n\tpriority int // Lower values priority indicate ==> higher priority\n}\n\n// Function to push according to priority ... the lower priority is goes ahead\n// The \"push\" always sorted in pq\nfn push_pq[T](mut prior_queue []T, data int, priority int) {\n\tmut temp := []T{}\n\tpg_len := prior_queue.len\n\n\tmut i := 0\n\tfor i < pg_len && priority > prior_queue[i].priority {\n\t\ttemp << prior_queue[i]\n\t\ti++\n\t}\n\t// INSERTING SORTED in the queue\n\ttemp << NODE{data, priority} // do the copy in the right place\n\t// copy the another part (tail) of original prior_queue\n\tfor i < pg_len {\n\t\ttemp << prior_queue[i]\n\t\ti++\n\t}\n\tprior_queue = temp.clone() // I am not sure if it the right way\n}\n\n// Change the priority of a value/node ... exist a value, change its priority\nfn updating_priority[T](mut prior_queue []T, search_data int, new_priority int) {\n\tmut i := 0\n\tmut pg_len := prior_queue.len\n\n\tfor i < pg_len {\n\t\tif search_data == prior_queue[i].data {\n\t\t\tprior_queue[i] = NODE{search_data, new_priority} // do the copy in the right place\n\t\t\tbreak\n\t\t}\n\t\ti++\n\t\t// all the list was examined\n\t\tif i >= pg_len {\n\t\t\t// print('\\n Priority Queue:  ${prior_queue}')\n\t\t\t// print('\\n These data ${search_data} and ${new_priority} do not exist ... PRIORITY QUEUE problem\\n')\n\t\t\t// if it does not find ... then push it\n\t\t\tpush_pq(mut prior_queue, search_data, new_priority)\n\t\t\t// exit(1) // panic(s string)\n\t\t}\n\t} // end for\n}\n\n// a single departure or remove from queue\nfn departure_priority[T](mut prior_queue []T) int {\n\tmut x := prior_queue[0].data\n\tprior_queue.delete(0) // or .delete_many(0, 1 )\n\treturn x\n}\n\n// give a NODE v, return a list with all adjacents\n// Take care, only positive EDGES\nfn all_adjacents[T](g [][]T, v int) []int {\n\tmut temp := []int{}\n\tfor i in 0 .. (g.len) {\n\t\tif g[v][i] > 0 {\n\t\t\ttemp << i\n\t\t}\n\t}\n\treturn temp\n}\n\n// print the costs from origin up to all nodes\n// A utility function to print the\n// constructed MST stored in parent[]\n// print all  paths and their cost or weight\nfn print_solution(path []int, g [][]int) {\n\t// print(' PATH:  ${path} ==> ${path.len}')\n\tprint('   Edge \\tWeight\\n')\n\tmut sum := 0\n\tfor node in 0 .. (path.len) {\n\t\tif path[node] == -1 {\n\t\t\tprint('\\n ${node} <== reference or start node')\n\t\t} else {\n\t\t\tprint('\\n ${node} <--> ${path[node]} \\t${g[node][path[node]]}')\n\t\t\tsum += g[node][path[node]]\n\t\t}\n\t}\n\tprint('\\n Minimum Cost Spanning Tree: ${sum}\\n\\n')\n}\n\n// check structure from: https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-greedy-algo-7/\n// s: source for all nodes\n// Two results are obtained ... cost and paths\nfn prim_mst(g [][]int, s int) {\n\tmut pq_queue := []NODE{} // creating a priority queue\n\tpush_pq(mut pq_queue, s, 0) // goes s with priority 0\n\tmut n := g.len\n\n\tmut dist := []int{len: n, init: -1} // dist with -1 instead of INFINITE\n\tmut path := []int{len: n, init: -1} // previous node of each shortest path\n\n\t// Distance of source vertex from itself is always 0\n\tdist[s] = 0\n\n\tfor pq_queue.len != 0 {\n\t\tmut v := departure_priority(mut pq_queue)\n\t\t// for all W adjacents vertices of v\n\t\tmut adjs_of_v := all_adjacents(g, v) // all_ADJ of v ....\n\t\t// print('\\n :${dist} :: ${pq_queue}')\n\t\t// print('\\n ADJ ${v} is ${adjs_of_v}')\n\t\tmut new_dist := 0\n\t\tfor w in adjs_of_v {\n\t\t\tnew_dist = dist[v] + g[v][w]\n\n\t\t\tif dist[w] == -1 {\n\t\t\t\tdist[w] = g[v][w]\n\t\t\t\tpush_pq(mut pq_queue, w, dist[w])\n\t\t\t\tpath[w] = v // collecting the previous node -- lowest weight\n\t\t\t}\n\n\t\t\tif dist[w] > new_dist {\n\t\t\t\tdist[w] = g[v][w] // new_dist//\n\t\t\t\tupdating_priority(mut pq_queue, w, dist[w])\n\t\t\t\tpath[w] = v // father / previous node\n\t\t\t}\n\t\t}\n\t}\n\n\t// print('\\n \\n Previous node of shortest path: ${path}')\n\t// print_paths_dist(path , dist)\n\tprint_solution(path, g)\n}\n\n/*\nSolution Expected graph_02\nEdge   Weight\n0 - 1    2\n1 - 2    3\n0 - 3    6\n1 - 4    5\n*/\n\nfn main() {\n\t// adjacency matrix = cost or weight\n\tgraph_01 := [\n\t\t[0, 4, 0, 0, 0, 0, 0, 8, 0],\n\t\t[4, 0, 8, 0, 0, 0, 0, 11, 0],\n\t\t[0, 8, 0, 7, 0, 4, 0, 0, 2],\n\t\t[0, 0, 7, 0, 9, 14, 0, 0, 0],\n\t\t[0, 0, 0, 9, 0, 10, 0, 0, 0],\n\t\t[0, 0, 4, 14, 10, 0, 2, 0, 0],\n\t\t[0, 0, 0, 0, 0, 2, 0, 1, 6],\n\t\t[8, 11, 0, 0, 0, 0, 1, 0, 7],\n\t\t[0, 0, 2, 0, 0, 0, 6, 7, 0],\n\t]\n\n\tgraph_02 := [\n\t\t[0, 2, 0, 6, 0],\n\t\t[2, 0, 3, 8, 5],\n\t\t[0, 3, 0, 0, 7],\n\t\t[6, 8, 0, 0, 9],\n\t\t[0, 5, 7, 9, 0],\n\t]\n\t// data from https://www.geeksforgeeks.org/prims-minimum-spanning-tree-mst-greedy-algo-5/\n\t/*\n\tThe graph:\n          2    3\n    (0)--(1)--(2)\n    |    / \\    |\n   6|  8/   \\5  |7\n    |  /     \\  |\n    (3)-------(4)\n         9\n\tLet us create following weighted graph\n From https://www.geeksforgeeks.org/kruskals-minimum-spanning-tree-algorithm-greedy-algo-2/?ref=lbp\n                   10\n              0--------1\n              |  \\     |\n             6|   5\\   |15\n              |      \\ |\n              2--------3\n                  4\n\t*/\n\tgraph_03 := [\n\t\t[0, 10, 6, 5],\n\t\t[10, 0, 0, 15],\n\t\t[6, 0, 0, 4],\n\t\t[5, 15, 4, 0],\n\t]\n\n\t// To find number of columns\n\t// mut cols := an_array[0].len\n\tmut graph := [][]int{} // the graph: adjacency matrix\n\t// for index, g_value in [graph_01, graph_02, graph_03] {\n\tfor index, g_value in [graph_01, graph_02, graph_03] {\n\t\tprintln('\\n Minimal Spanning Tree of graph ${index + 1} using PRIM algorithm')\n\t\tgraph = g_value.clone() // graphs_sample[g].clone() // choice your SAMPLE\n\t\t// starting by node x ... see the graphs dimensions\n\t\tstart_node := 0\n\t\tprim_mst(graph, start_node)\n\t}\n\tprintln('\\n BYE -- OK')\n}\n"
  },
  {
    "path": "examples/graphs/topological_sorting_dfs.v",
    "content": "// https://en.wikipedia.org/wiki/Topological_sorting\n// A DFS RECURSIVE ALGORITHM ....\n// An alternative algorithm for topological sorting is based on depth-first search. The algorithm loops through each node of the graph, in an arbitrary order, initiating a depth-first search that terminates when it hits any node that has already been visited since the beginning\n// of the topological sort or the node has no outgoing edges (i.e. a leaf node)\n// Discussion: https://www.gatevidyalay.com/topological-sort-topological-sorting/\n// $ v run dfs_topological_ordering.v\n// Author: CCS\n\n// THE DFS RECURSIVE .... classical searchig for leaves nodes\n// the arguments are used in the function to avoid global variables....\nfn dfs_recursive(u string, mut visited map[string]bool, graph map[string][]string, mut top_sorting []string) {\n\tprint(' Visiting: ${u} -> ')\n\tvisited[u] = true\n\n\tfor v in graph[u] {\n\t\tif visited[v] == false {\n\t\t\tdfs_recursive(v, mut visited, graph, mut top_sorting)\n\t\t}\n\t}\n\ttop_sorting << u\n}\n\n// Creating aa map to initialize with of visited nodes .... all with false in the init\n// so these nodes are NOT VISITED YET\nfn visited_init(a_graph map[string][]string) map[string]bool {\n\tmut array_of_keys := a_graph.keys() // get all keys of this map\n\tmut temp := map[string]bool{} // attention in these initializations with maps\n\tfor i in array_of_keys {\n\t\ttemp[i] = false\n\t}\n\treturn temp\n}\n\n// attention here a map STRING ---> ONE BOOLEAN ... not a string\n\nfn main() {\n\t// A map illustration to use in a graph\n\t// the graph: adjacency matrix\n\tgraph_01 := {\n\t\t'A': ['C', 'B']\n\t\t'B': ['D']\n\t\t'C': ['D']\n\t\t'D': []\n\t}\n\n\tgraph_02 := {\n\t\t'A': ['B', 'C', 'D']\n\t\t'B': ['E']\n\t\t'C': ['F']\n\t\t'D': ['G']\n\t\t'E': ['H']\n\t\t'F': ['H']\n\t\t'G': ['H']\n\t\t'H': [] // no cycles\n\t}\n\t// from: https://en.wikipedia.org/wiki/Topological_sorting\n\tgraph_03 := {\n\t\t'5':  ['11']\n\t\t'7':  ['11', '8']\n\t\t'3':  ['8', '10']\n\t\t'11': ['2', '9', '10']\n\t\t'8':  ['9']\n\t\t'2':  []\n\t\t'9':  []\n\t\t'10': []\n\t}\n\n\tmut graph := map[string][]string{} // the graph: adjacency matrix\n\tfor index, g_value in [graph_01, graph_02, graph_03] {\n\t\tprintln('Topological sorting for the graph ${index} using a DFS recursive')\n\t\tgraph = g_value.clone() // graphs_sample[g].clone() // choice your SAMPLE\n\n\t\t// mut n_nodes := graph.len\n\t\tmut visited := visited_init(graph) // a map with nodes not visited\n\n\t\t// mut start := (graph.keys()).first() // arbitrary, any node if you wish\n\t\tmut top_sorting := []string{}\n\t\t// advantages of map ... getting all nodes\n\t\tfor i in graph.keys() {\n\t\t\tif visited[i] != true {\n\t\t\t\tdfs_recursive(i, mut visited, graph, mut top_sorting)\n\t\t\t}\n\t\t}\n\n\t\tprint('\\n A topological sorting of graph ${index} : ')\n\t\t// println(g_value)\n\t\tprintln(top_sorting.reverse())\n\t\tprintln('')\n\t} // End of for\n}\n"
  },
  {
    "path": "examples/graphs/topological_sorting_greedy.v",
    "content": "// The idea of this algorithm follow :\n// https://www.gatevidyalay.com/topological-sort-topological-sorting/ (GREEDY)\n// (no cycles are detected)\n// https://en.wikipedia.org/wiki/Topological_sorting ... just the input data\n// and the Kahn algorithm\n// Author: CCS\n\n// the idea is rude: https://www.gatevidyalay.com/topological-sort-topological-sorting/\nfn topog_sort_greedy(graph map[string][]string) []string {\n\tn_nodes := graph.len // numbers of nodes of this graph\n\tmut top_order := []string{} // a vector with sequence of nodes visited\n\tmut count := 0\n\t/*\n\tIDEA ( a greedy algorithm ):\n\n\t 1. choose always the node with smallest input degree\n\t 2. visit it\n\t 3. put it in the output vector\n\t 4. remove it from graph\n\t 5. update the graph (a new graph)\n\t 6. find a new vector degree\n\t 7. until all nodes has been visited\n     Back to step 1 (used the variable count)\n\n\t Maybe it seems the Kahn's algorithm\n\t*/\n\tmut v_degree := in_degree(graph) // return: map [string] int\n\tprint('V Degree ${v_degree}')\n\tmut small_degree := min_degree(v_degree)\n\tmut new_graph := remove_node_from_graph(small_degree, graph)\n\ttop_order << small_degree\n\tcount++\n\n\tfor (count < n_nodes) {\n\t\tv_degree = in_degree(new_graph) // return: map [string] int\n\t\tprint('\\nV Degree ${v_degree}')\n\t\tsmall_degree = min_degree(v_degree)\n\t\tnew_graph = remove_node_from_graph(small_degree, new_graph)\n\n\t\ttop_order << small_degree\n\t\tcount++\n\t}\n\t// print(\"\\n New Graph ${new_graph}\")\n\n\treturn top_order\n}\n\n// Give a node, return a list with all nodes incidents or fathers of this node\nfn all_fathers(node string, a_map map[string][]string) []string {\n\tmut array_of_keys := a_map.keys() // get a key of this map\n\tmut all_incident := []string{}\n\tfor i in array_of_keys {\n\t\t// in : function\n\t\tif node in a_map[i] {\n\t\t\tall_incident << i // a queue of this search\n\t\t}\n\t}\n\treturn all_incident\n}\n\n// Input: a map with input degree values, return the key with smallest value\nfn min_degree(a_map map[string]int) string {\n\tmut array_of_keys := a_map.keys() // get a key of this map\n\tmut key_min := array_of_keys.first()\n\tmut val_min := a_map[key_min]\n\t// print(\"\\n MIN: ${val_min} \\t  key_min: ${key_min}  \\n the map inp_degree: ${a_map}\")\n\tfor i in array_of_keys {\n\t\t// there is a smaller\n\t\tif val_min > a_map[i] {\n\t\t\tval_min = a_map[i]\n\t\t\tkey_min = i\n\t\t}\n\t}\n\treturn key_min // the key with smallest value\n}\n\n// Given a graph ... return a list of integer with degree of each node\nfn in_degree(a_map map[string][]string) map[string]int {\n\tmut array_of_keys := a_map.keys() // get a key of this map\n\t// print(array_of_keys)\n\tmut degree := map[string]int{}\n\tfor i in array_of_keys {\n\t\tdegree[i] = all_fathers(i, a_map).len\n\t}\n\t// print(\"\\n Degree ${in_degree}\" )\n\treturn degree // a vector of the indegree graph\n}\n\n// REMOVE A NODE FROM A GRAPH AND RETURN ANOTHER GRAPH\nfn remove_node_from_graph(node string, a_map map[string][]string) map[string][]string {\n\t// mut new_graph := map [string] string {}\n\tmut new_graph := a_map.clone() // copy the graph\n\tnew_graph.delete(node)\n\tmut all_nodes := new_graph.keys() // get all nodes of this graph\n\t// FOR THE FUTURE with filter\n\t// for i in all_nodes {\n\t//\t   new_graph[i] = new_graph[i].filter(index(it) != node)\n\t// }\n\t// A HELP FROM V discussion\t GITHUB - thread\n\tfor key in all_nodes {\n\t\ti := new_graph[key].index(node)\n\t\tif i >= 0 {\n\t\t\tnew_graph[key].delete(i)\n\t\t}\n\t}\n\t// print(\"\\n NEW ${new_graph}\" )\n\treturn new_graph\n}\n\nfn main() {\n\t// A map illustration to use in a graph\n\t// adjacency matrix\n\tgraph_01 := {\n\t\t'A': ['C', 'B']\n\t\t'B': ['D']\n\t\t'C': ['D']\n\t\t'D': []\n\t}\n\n\tgraph_02 := {\n\t\t'A': ['B', 'C', 'D']\n\t\t'B': ['E']\n\t\t'C': ['F']\n\t\t'D': ['G']\n\t\t'E': ['H']\n\t\t'F': ['H']\n\t\t'G': ['H']\n\t\t'H': []\n\t}\n\t// from: https://en.wikipedia.org/wiki/Topological_sorting\n\tgraph_03 := {\n\t\t'5':  ['11']\n\t\t'7':  ['11', '8']\n\t\t'3':  ['8', '10']\n\t\t'11': ['2', '9', '10']\n\t\t'8':  ['9']\n\t\t'2':  []\n\t\t'9':  []\n\t\t'10': []\n\t}\n\n\tprintln('\\nA Topological Sort of G1:  ${topog_sort_greedy(graph_01)}')\n\tprintln('\\nA Topological Sort of G2:  ${topog_sort_greedy(graph_02)}')\n\tprintln('\\nA Topological Sort of G3:  ${topog_sort_greedy(graph_03)}')\n\t// ['2', '9', '10', '11', '5', '8', '7', '3']\n}\n"
  },
  {
    "path": "examples/hanoi.v",
    "content": "// hanoi tower\nconst num = 7\n\nfn main() {\n\thanoi(num, 'A', 'B', 'C')\n}\n\nfn move(n int, a string, b string) {\n\tprintln('Disc ${n} from ${a} to ${b}...')\n}\n\nfn hanoi(n int, a string, b string, c string) {\n\tif n == 1 {\n\t\tmove(1, a, c)\n\t} else {\n\t\thanoi(n - 1, a, c, b)\n\t\tmove(n, a, c)\n\t\thanoi(n - 1, b, a, c)\n\t}\n}\n"
  },
  {
    "path": "examples/hello_world.v",
    "content": "println('Hello, World!')\n"
  },
  {
    "path": "examples/hot_reload/.gitignore",
    "content": "!glfw3.dll\n"
  },
  {
    "path": "examples/hot_reload/bounce.v",
    "content": "// Build this example with\n// v -live bounce.v\nmodule main\n\nimport gg\nimport time\n\nstruct Game {\nmut:\n\tgg      &gg.Context = unsafe { nil }\n\tx       int\n\ty       int\n\tdy      int\n\tdx      int\n\theight  int\n\twidth   int\n\tdraw_fn voidptr\n}\n\nconst window_width = 400\nconst window_height = 300\nconst width = 50\n\nfn main() {\n\tmut game := &Game{\n\t\tdx:      2\n\t\tdy:      2\n\t\theight:  window_height\n\t\twidth:   window_width\n\t\tdraw_fn: 0\n\t}\n\tgame.gg = gg.new_context(\n\t\twidth:         window_width\n\t\theight:        window_height\n\t\tfont_size:     20\n\t\tuser_data:     game\n\t\twindow_title:  'Hot code reloading demo'\n\t\tcreate_window: true\n\t\tframe_fn:      frame\n\t\tbg_color:      gg.white\n\t)\n\t// window.onkeydown(key_down)\n\tprintln('Starting the game loop...')\n\tspawn game.run()\n\tgame.gg.run()\n}\n\n// Try uncommenting or changing the lines inside the live functions.\n// Guess what will happen:\n@[live]\nfn frame(mut game Game) {\n\tgame.gg.begin()\n\tgame.gg.draw_text_def(10, 5, 'Modify examples/hot_reload/bounce.v to get instant updates')\n\tgame.gg.draw_rect_filled(game.x, game.y, width, width, gg.black)\n\tgame.gg.draw_rect_filled(window_width - width - game.x + 10, 200 - game.y + width,\n\t\twidth, width, gg.rgb(228, 10, 55))\n\tgame.gg.draw_rect_filled(game.x - 25, 250 - game.y, width, width, gg.rgb(28, 240,\n\t\t55))\n\tgame.gg.end()\n}\n\n@[live]\nfn (mut game Game) update_model() {\n\tspeed := 2\n\tgame.x += speed * game.dx\n\tgame.y += speed * game.dy\n\tif game.y >= game.height - width || game.y <= 0 {\n\t\tgame.dy = -game.dy\n\t}\n\tif game.x >= game.width - width || game.x <= 0 {\n\t\tgame.dx = -game.dx\n\t}\n}\n\nfn (mut game Game) run() {\n\tfor {\n\t\tgame.update_model()\n\t\ttime.sleep(16 * time.millisecond) // 60fps\n\t}\n}\n"
  },
  {
    "path": "examples/hot_reload/graph.v",
    "content": "module main\n\nimport gg\nimport time\nimport math\n\nconst size = 700\nconst scale = 50.0\n\nstruct Context {\nmut:\n\tgg &gg.Context = unsafe { nil }\n}\n\nfn main() {\n\tmut context := &Context{}\n\tcontext.gg = gg.new_context(\n\t\twidth:         size\n\t\theight:        size\n\t\tfont_size:     20\n\t\tuser_data:     context\n\t\twindow_title:  'Graph builder'\n\t\tcreate_window: true\n\t\tframe_fn:      frame\n\t\tresizable:     true\n\t\tbg_color:      gg.white\n\t)\n\tcontext.gg.run()\n}\n\nfn frame(mut ctx Context) {\n\tctx.gg.begin()\n\tctx.draw()\n\tctx.gg.end()\n}\n\n@[live]\nfn (ctx &Context) draw() {\n\ts := gg.window_size()\n\tmut w := s.width\n\tmut h := s.height\n\tif gg.high_dpi() {\n\t\tw /= 2\n\t\th /= 2\n\t}\n\tctx.gg.draw_line(0, h / 2, w, h / 2, gg.gray) // x axis\n\tctx.gg.draw_line(w / 2, 0, w / 2, h, gg.gray) // y axis\n\tatime := f64(time.ticks() / 10)\n\tstime := math.sin(2.0 * math.pi * f64(time.ticks() % 6000) / 6000)\n\tmut y := 0.0\n\tblue := gg.Color{\n\t\tr: 100\n\t\tg: 100\n\t\tb: 200\n\t}\n\tred := gg.Color{\n\t\tr: 200\n\t\tg: 100\n\t\tb: 100\n\t}\n\ty = 1.0\n\tmax := f32(w) / (2 * scale)\n\tmin := -max\n\tfor x := min; x <= max; x += 0.01 {\n\t\t// y = x*x + 2\n\t\t// y = x * x + stime * stime\n\t\t// y = stime\n\t\t// y = stime * h\n\t\ty = stime * 1.0 * math.sin(x + stime + atime / 32) * ((h / 256) + x)\n\t\t// y = (stime * x) * x + stime\n\t\t// y = (x + 3) * (x + 3) / stime + stime*2.5\n\t\t// y = math.sqrt(30.0 - x * x) * stime\n\t\t// y -= (stime-0.5) + stime\n\t\t// ctx.gg.draw_rect_filled(f32((w/2) + x * scale), f32((h/2) - y * scale), 2, 2, blue)\n\t\tctx.gg.draw_rect_filled(f32((w / 2) + x * scale), f32((h / 2) - y * scale), 2,\n\t\t\t(f32(y) * scale), blue)\n\t\tctx.gg.draw_rect_filled(f32((w / 2) + x * scale), f32((h / 2) + y * scale), 2,\n\t\t\t(f32(y) * scale) + 32, red)\n\t}\n}\n"
  },
  {
    "path": "examples/hot_reload/message.v",
    "content": "module main\n\n// Build this example with `v -live message.v`\nimport time\nimport v.live\n\nstruct App {\nmut:\n\tx int\n\tc int\n}\n\n@[live]\nfn print_message(mut app App) {\n\ti := live.info()\n\tprintln('Hello! Modify this message. OK reloads: ${i.reloads_ok:2d} | Total: ${i.reloads:2d} | app: ${voidptr(app)} | app.c: ${app.c:4} | app.x: ${app.x:12}')\n\t// app.x = app.x * 3 + 1 // try changing this to another value, while the program is running ...\n\t// app.x = 0\n\tapp.c++\n}\n\nfn main() {\n\tunbuffer_stdout()\n\tprintln('=============================================================')\n\tprintln('== Modify the message below, while the program is running: ==')\n\tprintln('=============================================================')\n\tmut app := &App{}\n\tfor {\n\t\tprint_message(mut app)\n\t\ttime.sleep(500 * time.millisecond)\n\t}\n}\n"
  },
  {
    "path": "examples/hot_reload/tunnel.v",
    "content": "// Try commenting or changing the drawing functions, that are at the bottom of the file,\n// and that are inside functions marked with @[live] ...\nimport gg\nimport math\n\nfn main() {\n\tmut state := init_state()\n\tgg.start(\n\t\twindow_title: 'Tunnel'\n\t\tbg_color:     gg.Color{255, 255, 255, 255}\n\t\twidth:        1024\n\t\theight:       768\n\t\tframe_fn:     unsafe { state.draw }\n\t\tevent_fn:     unsafe { state.on_event }\n\t)\n}\n\nstruct BigRect {\nmut:\n\tid     int\n\tt      f32\n\tx      f32\n\ty      f32\n\tw      f32\n\tbwidth f32\n\tc      gg.Color\n}\n\nstruct State {\nmut:\n\tt       f32\n\treal_t  f32\n\tdrt     f32 = 0.1\n\ttparams gg.DrawTextParams\n\trects   []BigRect\n}\n\nconst colors = []gg.Color{len: 1024, init: gg.Color{u8(100 +\n\t100 * math.sin(f32(index) / 50) * math.cos(f32(index) / 50)), u8(100 +\n\t100 * math.cos(f32(index) / 50)), 100 + u8(index % 50), 255}}\n\nfn init_state() State {\n\tmut state := State{\n\t\tt:       0\n\t\treal_t:  120\n\t\tdrt:     0.1\n\t\ttparams: gg.DrawTextParams{\n\t\t\tx:     40\n\t\t\tsize:  20\n\t\t\tcolor: gg.Color{255, 255, 255, 255}\n\t\t}\n\t\trects:   [\n\t\t\tBigRect{\n\t\t\t\tx:      350\n\t\t\t\ty:      250\n\t\t\t\tw:      30\n\t\t\t\tbwidth: 10\n\t\t\t\tc:      gg.Color{0, 0, 255, 255}\n\t\t\t},\n\t\t]\n\t}\n\tfor i in 1 .. 50 {\n\t\tstate.rects << BigRect{\n\t\t\tid: i\n\t\t}\n\t}\n\treturn state\n}\n\nfn (mut state State) on_event(e &gg.Event, _ctx voidptr) {\n\tif e.typ == .char {\n\t\tif e.char_code == `f` {\n\t\t\tgg.toggle_fullscreen()\n\t\t\treturn\n\t\t}\n\t\tif e.char_code == `1` {\n\t\t\tstate.real_t -= 100\n\t\t}\n\t\tif e.char_code == `2` {\n\t\t\tstate.real_t += 100\n\t\t}\n\t\tif e.char_code == `3` {\n\t\t\tstate.t -= 100\n\t\t}\n\t\tif e.char_code == `4` {\n\t\t\tstate.t += 100\n\t\t}\n\t\tif e.char_code == `5` {\n\t\t\tstate.rects[0].w += 10\n\t\t}\n\t\tif e.char_code == `6` {\n\t\t\tstate.rects[0].w -= 10\n\t\t}\n\t\tif e.char_code == `r` {\n\t\t\tstate.real_t = 120\n\t\t\tstate.t = 0\n\t\t\tstate.rects[0].w = 30\n\t\t}\n\t\tif e.char_code == ` ` {\n\t\t\tstate.drt = if state.drt > 0.0001 { f32(0.0) } else { 0.1 }\n\t\t}\n\t}\n}\n\nfn (mut state State) draw(ctx &gg.Context) {\n\tupdate(mut state)\n\tctx.begin()\n\tmut r0 := &state.rects[0]\n\tdraw_big_rect(ctx, r0)\n\tfor i in 1 .. state.rects.len {\n\t\tdraw_big_rect(ctx, state.rects[i])\n\t}\n\tctx.draw_text2(gg.DrawTextParams{\n\t\t...state.tparams\n\t\ty:    0\n\t\ttext: 'rt[1,2]: ${state.real_t:08.3f}, t[3,4]: ${state.t:08.3f}, r0.x: ${r0.x:07.3f}, r0.y: ${r0.y:07.3f}, r0.w[5,6]: ${r0.w:4.1f}, [f]-toggle fs, [r]-reset, [ ]-pause'\n\t})\n\tdraw_center_point(ctx, r0, state.t)\n\tctx.show_fps()\n\tctx.end()\n}\n\n@[live]\nfn update(mut state State) {\n\tif state.drt <= 0.0001 {\n\t\treturn\n\t}\n\tstate.real_t += state.drt\n\tstate.t += 0.5 * math.sinf(state.real_t / 1000)\n\tmut r0 := &state.rects[0]\n\tr0.t = state.t\n\tr0.x = 550 + 450 * math.sinf(state.t / 10) * math.sinf(state.t / 50)\n\tr0.y = 350 + 350 * math.cosf(state.t / 20) * math.cosf(-state.t / 50)\n\tr0.x += 5 * math.sinf(state.t)\n\tr0.y += 5 * math.cosf(state.t)\n\tr0.c = colors[int((50000 + state.t) / 200 * (1 + math.sin(state.t / 5))) % colors.len]\n\tfor i := state.rects.len - 1; i > 0; i-- {\n\t\tstate.rects[i] = state.rects[i - 1]\n\t\tstate.rects[i].w *= 1.11 + f32(i) / 1000\n\t\tstate.rects[i].bwidth *= 1.09\n\t}\n}\n\n@[live]\nfn draw_center_point(ctx &gg.Context, br BigRect, t f32) {\n\tb := u8(128 + 128 * math.sin(t / 12))\n\tc := gg.Color{255 - b, b, b, 55}\n\tctx.draw_circle_filled(br.x, br.y, 8, c)\n}\n\n@[live]\nfn draw_big_rect(ctx &gg.Context, br BigRect) {\n\tradius := 20\n\tx := br.x\n\ty := br.y\n\tw := br.w\n\tc := br.c\n\tbwidth := br.bwidth\n\tbase := gg.DrawRectParams{\n\t\tradius:     radius\n\t\tis_rounded: true\n\t\tcolor:      c\n\t}\n\trleft := gg.DrawRectParams{\n\t\t...base\n\t\tx: x - (w / 2)\n\t\ty: y - (w / 2)\n\t\tw: bwidth\n\t\th: w\n\t}\n\trright := gg.DrawRectParams{\n\t\t...base\n\t\tx: x + (w / 2) - bwidth\n\t\ty: y - w + (w / 2)\n\t\tw: bwidth\n\t\th: w\n\t}\n\trtop := gg.DrawRectParams{\n\t\t...base\n\t\tx: x - (w / 2)\n\t\ty: y - (w / 2)\n\t\tw: w\n\t\th: bwidth\n\t}\n\trbottom := gg.DrawRectParams{\n\t\t...base\n\t\tx: x + (w / 2) - w\n\t\ty: y + (w / 2) - bwidth\n\t\tw: w\n\t\th: bwidth\n\t}\n\tborder := gg.DrawRectParams{\n\t\tx:     x - (w / 2) + bwidth + 1\n\t\ty:     y - (w / 2) + bwidth + 2\n\t\tw:     w - 2 * bwidth - 2\n\t\th:     w - 2 * bwidth - 1\n\t\tcolor: gg.Color{255, 255, 255, 155}\n\t\tstyle: .stroke\n\t}\n\tctx.draw_rect(rtop)\n\tctx.draw_rect(rleft)\n\tctx.draw_rect(rright)\n\tctx.draw_rect(border)\n\tctx.draw_rect(rbottom)\n}\n"
  },
  {
    "path": "examples/http_server.v",
    "content": "module main\n\nimport net.http { Request, Response, Server }\n\nstruct ExampleHandler {}\n\nfn (h ExampleHandler) handle(req Request) Response {\n\tmut res := Response{\n\t\theader: http.new_header_from_map({\n\t\t\t.content_type: 'text/plain'\n\t\t})\n\t}\n\tmut status_code := 200\n\tres.body = match req.url {\n\t\t'/foo' {\n\t\t\t'bar\\n'\n\t\t}\n\t\t'/hello' {\n\t\t\t'world\\n'\n\t\t}\n\t\t'/' {\n\t\t\t'foo\\nhello\\n'\n\t\t}\n\t\telse {\n\t\t\tstatus_code = 404\n\t\t\t'Not found\\n'\n\t\t}\n\t}\n\tres.status_code = status_code\n\treturn res\n}\n\nfn main() {\n\tmut server := Server{\n\t\thandler: ExampleHandler{}\n\t}\n\tserver.listen_and_serve()\n}\n"
  },
  {
    "path": "examples/js_dom_cube/README.md",
    "content": "# JS DOM Cube\n\n## Compiling\n\n```\nv -b js_browser examples/js_dom_cube/cube.js.v\n```\n\nThen you can open `index.html` in your favorite browser.\n\n## Serve Examples\n\n### JS Server\n\n> [!NOTE]\n> The JS server example in the following steps requires Node.js.\n> To install Node, please refer to the [download page](https://nodejs.org/en/download/)\n> or the installation via your operating systems [package manager](https://nodejs.org/en/download/package-manager).\n\nInitialize the example as a Node project\n\n```\ncd examples/js_dom_cube/\nnpm init -y\n```\n\nAdd a `start` and `build` script to the generated `./package.json` file.\n\n```json\n  \"scripts\": {\n    ...\n    \"start\": \"npm run build && node server.js\",\n    \"build\": \"v -b js_browser cube.js.v\"\n  },\n```\n\nBelow is an example of a Node.js server without external dependencies.\nYou can use it for `./server.js`.\n\n```javascript\nconst http = require('http');\nconst fs = require('fs');\nvar path = require('path');\n\nconst host = 'localhost';\nconst port = 3000;\n\nconst reqListener = function (req, res) {\n\tconsole.log('[route] - ', req.url);\n\n\tvar filePath = '.' + req.url;\n\tif (filePath == './') {\n\t\tfilePath = './index.html';\n\t}\n\n\tvar extname = String(path.extname(filePath)).toLowerCase();\n\tvar mimeTypes = {\n\t\t'.html': 'text/html',\n\t\t'.js': 'text/javascript',\n\t\t'.css': 'text/css',\n\t\t'.json': 'application/json',\n\t\t'.png': 'image/png',\n\t\t'.jpg': 'image/jpg',\n\t\t'.gif': 'image/gif',\n\t\t'.svg': 'image/svg+xml',\n\t\t'.wav': 'audio/wav',\n\t\t'.mp4': 'video/mp4',\n\t\t'.woff': 'application/font-woff',\n\t\t'.ttf': 'application/font-ttf',\n\t\t'.eot': 'application/vnd.ms-fontobject',\n\t\t'.otf': 'application/font-otf',\n\t\t'.wasm': 'application/wasm',\n\t};\n\n\tvar contentType = mimeTypes[extname] || 'application/octet-stream';\n\n\tfs.readFile(filePath, function (error, content) {\n\t\tif (error) {\n\t\t\tif (error.code == 'ENOENT') {\n\t\t\t\tfs.readFile('./404.html', function (error, content) {\n\t\t\t\t\tres.writeHead(404, { 'Content-Type': 'text/html' });\n\t\t\t\t\tres.end(content, 'utf-8');\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tres.writeHead(500);\n\t\t\t\tres.end('Sorry, check with the site admin for error: ' + error.code + ' ..\\n');\n\t\t\t}\n\t\t} else {\n\t\t\tres.writeHead(200, { 'Content-Type': contentType });\n\t\t\tres.end(content, 'utf-8');\n\t\t}\n\t});\n};\n\nconst server = http.createServer(reqListener);\nserver.listen(port, host, () => {\n\tconsole.log(`Server is running on http://${host}:${port}`);\n});\n```\n\nNow you can build and run the project with the added scripts.\n\n```sh\nnpm run build\nnpm run start\n```\n\n### V server\n\nThe example below uses `vweb` to serve the project.\n\n```v\nmodule main\n\nimport vweb\nimport os\n\nconst http_port = 3001\n\nstruct App {\n\tvweb.Context\n}\n\nfn main() {\n\tvweb.run(new_app(), http_port)\n}\n\npub fn (mut app App) before_request() {\n\t// Build the cube.js javascript file\n\tos.execute_or_panic('v -b js_browser cube.js.v ')\n}\n\nfn new_app() &App {\n\tmut app := &App{}\n\tapp.serve_static('/favicon.ico', 'favicon.ico')\n\tapp.serve_static('/cube.js', 'cube.js')\n\tapp.mount_static_folder_at(os.resource_abs_path('.'), '/')\n\treturn app\n}\n\n@['/'; get]\npub fn (mut app App) controller_get_all_task() vweb.Result {\n\tfile := os.read_file('./index.html') or { panic(err) }\n\treturn app.html(file)\n}\n```"
  },
  {
    "path": "examples/js_dom_cube/cube.js.v",
    "content": "import js.dom\nimport math\n\nconst vert_code = 'attribute vec3 position;uniform mat4 Pmatrix;uniform mat4 Vmatrix;uniform mat4 Mmatrix;attribute vec3 color;varying vec3 vColor;void main(void) {gl_Position = Pmatrix * Vmatrix * Mmatrix * vec4(position,1.);vColor = color;}\n\t'\n\nconst frag_code = 'precision mediump float;varying vec3 vColor;void main(void) {gl_FragColor = vec4(vColor, 1.);}\n\t'\n\nconst vertices = [\n\tf32(-1),\n\t-1,\n\t-1,\n\t1,\n\t-1,\n\t-1,\n\t1,\n\t1,\n\t-1,\n\t-1,\n\t1,\n\t-1,\n\t-1,\n\t-1,\n\t1,\n\t1,\n\t-1,\n\t1,\n\t1,\n\t1,\n\t1,\n\t-1,\n\t1,\n\t1,\n\t-1,\n\t-1,\n\t-1,\n\t-1,\n\t1,\n\t-1,\n\t-1,\n\t1,\n\t1,\n\t-1,\n\t-1,\n\t1,\n\t1,\n\t-1,\n\t-1,\n\t1,\n\t1,\n\t-1,\n\t1,\n\t1,\n\t1,\n\t1,\n\t-1,\n\t1,\n\t-1,\n\t-1,\n\t-1,\n\t-1,\n\t-1,\n\t1,\n\t1,\n\t-1,\n\t1,\n\t1,\n\t-1,\n\t-1,\n\t-1,\n\t1,\n\t-1,\n\t-1,\n\t1,\n\t1,\n\t1,\n\t1,\n\t1,\n\t1,\n\t1,\n\t-1,\n]\nconst colors = [\n\tf32(5),\n\t3,\n\t7,\n\t5,\n\t3,\n\t7,\n\t5,\n\t3,\n\t7,\n\t5,\n\t3,\n\t7,\n\t1,\n\t1,\n\t3,\n\t1,\n\t1,\n\t3,\n\t1,\n\t1,\n\t3,\n\t1,\n\t1,\n\t3,\n\t0,\n\t0,\n\t1,\n\t0,\n\t0,\n\t1,\n\t0,\n\t0,\n\t1,\n\t0,\n\t0,\n\t1,\n\t1,\n\t0,\n\t0,\n\t1,\n\t0,\n\t0,\n\t1,\n\t0,\n\t0,\n\t1,\n\t0,\n\t0,\n\t1,\n\t1,\n\t0,\n\t1,\n\t1,\n\t0,\n\t1,\n\t1,\n\t0,\n\t1,\n\t1,\n\t0,\n\t0,\n\t1,\n\t0,\n\t0,\n\t1,\n\t0,\n\t0,\n\t1,\n\t0,\n\t0,\n\t1,\n\t0,\n]\nconst indices = [\n\tu16(0),\n\t1,\n\t2,\n\t0,\n\t2,\n\t3,\n\t4,\n\t5,\n\t6,\n\t4,\n\t6,\n\t7,\n\t8,\n\t9,\n\t10,\n\t8,\n\t10,\n\t11,\n\t12,\n\t13,\n\t14,\n\t12,\n\t14,\n\t15,\n\t16,\n\t17,\n\t18,\n\t16,\n\t18,\n\t19,\n\t20,\n\t21,\n\t22,\n\t20,\n\t22,\n\t23,\n]\nconst amortization = 0.95\n\nfn get_webgl() (JS.HTMLCanvasElement, JS.WebGLRenderingContext) {\n\tJS.console.log(dom.document)\n\telem := dom.document.getElementById('myCanvas'.str) or { panic('cannot get canvas') }\n\tmatch elem {\n\t\tJS.HTMLCanvasElement {\n\t\t\twebgl := elem.getContext('experimental-webgl'.str, js_undefined()) or {\n\t\t\t\tpanic('context not found')\n\t\t\t}\n\t\t\tmatch webgl {\n\t\t\t\tJS.WebGLRenderingContext {\n\t\t\t\t\treturn elem, webgl\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tpanic('cannot get webgl')\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tpanic('not an canvas')\n\t\t}\n\t}\n}\n\nfn get_projection(angle f64, a f64, z_min f64, z_max f64) []f64 {\n\tang := math.tan((angle * 0.5) * math.pi / 180)\n\treturn [\n\t\t0.5 / ang,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t0.5 * a / ang,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t0,\n\t\t-(z_max + z_min) / (z_max - z_min),\n\t\t-1,\n\t\t0,\n\t\t0,\n\t\t(-2 * z_max * z_min) / (z_max - z_min),\n\t\t0,\n\t]\n}\n\nfn JS.Math.cos(JS.Number) JS.Number\nfn JS.Math.sin(JS.Number) JS.Number\nfn rotate_x(mut m []f64, angle f64) {\n\tc := math.cos(angle)\n\ts := math.sin(angle)\n\tmv1 := m[1]\n\tmv5 := m[5]\n\tmv9 := m[9]\n\tm[1] = m[1] * c - m[2] * s\n\tm[5] = m[5] * c - m[6] * s\n\tm[9] = m[9] * c - m[10] * s\n\n\tm[2] = m[2] * c + mv1 * s\n\tm[6] = m[6] * c + mv5 * s\n\tm[10] = m[10] * c + mv9 * s\n}\n\nfn rotate_y(mut m []f64, angle f64) {\n\tc := math.cos(angle)\n\ts := math.sin(angle)\n\n\tmv0 := m[0]\n\tmv4 := m[4]\n\tmv8 := m[8]\n\tm[0] = c * m[0] + s * m[2]\n\tm[4] = c * m[4] + s * m[6]\n\tm[8] = c * m[8] + s * m[10]\n\n\tm[2] = c * m[2] - s * mv0\n\tm[6] = c * m[6] - s * mv4\n\tm[10] = c * m[10] - s * mv8\n}\n\nstruct State {\nmut:\n\tdrag         bool\n\tgl           JS.WebGLRenderingContext\n\tcanvas       JS.HTMLCanvasElement\n\told_x        f64\n\told_y        f64\n\tdx           f64\n\tdy           f64\n\ttheta        f64\n\tphi          f64\n\ttime_old     f64\n\tmo_matrix    []f64\n\tview_matrix  []f64\n\tproj_matrix  []f64\n\tpmatrix      JS.WebGLUniformLocation\n\tvmatrix      JS.WebGLUniformLocation\n\tmmatrix      JS.WebGLUniformLocation\n\tindex_buffer JS.WebGLBuffer\n}\n\nfn animate(mut state State, time f64) {\n\tif !state.drag {\n\t\tstate.dx = state.dx * amortization\n\t\tstate.dy = state.dy * amortization\n\t\tstate.theta += state.dx\n\t\tstate.phi += state.dy\n\t}\n\n\tstate.mo_matrix[0] = 1\n\tstate.mo_matrix[1] = 0\n\tstate.mo_matrix[2] = 0\n\tstate.mo_matrix[3] = 0\n\n\tstate.mo_matrix[4] = 0\n\tstate.mo_matrix[5] = 1\n\tstate.mo_matrix[6] = 0\n\tstate.mo_matrix[7] = 0\n\n\tstate.mo_matrix[8] = 0\n\tstate.mo_matrix[9] = 0\n\tstate.mo_matrix[10] = 1\n\tstate.mo_matrix[11] = 0\n\n\tstate.mo_matrix[12] = 0\n\tstate.mo_matrix[13] = 0\n\tstate.mo_matrix[14] = 0\n\tstate.mo_matrix[15] = 1\n\t// println('${state.theta} ${state.phi}')\n\trotate_x(mut state.mo_matrix, state.phi)\n\trotate_y(mut state.mo_matrix, state.theta)\n\tstate.time_old = time\n\tstate.gl.enable(dom.gl_depth_test())\n\tstate.gl.clearColor(0.5, 0.5, 0.5, 0.9)\n\tstate.gl.clearDepth(1.0)\n\tstate.gl.viewport(0.0, 0.0, state.canvas.width, state.canvas.height)\n\tstate.gl.clear(JS.Number(int(dom.gl_color_buffer_bit()) | int(dom.gl_depth_buffer_bit())))\n\n\tstate.gl.uniformMatrix4fv(state.pmatrix, JS.Boolean(false), state.proj_matrix.to_number_array())\n\tstate.gl.uniformMatrix4fv(state.vmatrix, JS.Boolean(false), state.view_matrix.to_number_array())\n\tstate.gl.uniformMatrix4fv(state.mmatrix, JS.Boolean(false), state.mo_matrix.to_number_array())\n\n\tstate.gl.bindBuffer(dom.gl_element_array_buffer(), state.index_buffer)\n\tstate.gl.drawElements(dom.gl_triangles(), indices.len, dom.gl_unsigned_short(), 0)\n\n\tdom.window().requestAnimationFrame(fn [mut state] (time JS.Number) {\n\t\tanimate(mut state, f64(time))\n\t})\n}\n\nfn main() {\n\tcanvas, gl := get_webgl()\n\n\tvertex_buffer := gl.createBuffer()?\n\tgl.bindBuffer(dom.gl_array_buffer(), vertex_buffer)\n\tgl.bufferData(dom.gl_array_buffer(), float32_array(vertices), dom.gl_static_draw())\n\n\tcolor_buffer := gl.createBuffer()?\n\tgl.bindBuffer(dom.gl_array_buffer(), color_buffer)\n\tgl.bufferData(dom.gl_array_buffer(), float32_array(colors), dom.gl_static_draw())\n\n\tindex_buffer := gl.createBuffer()?\n\tgl.bindBuffer(dom.gl_element_array_buffer(), index_buffer)\n\tgl.bufferData(dom.gl_element_array_buffer(), uint16_array(indices), dom.gl_static_draw())\n\n\tvert_shader := gl.createShader(dom.gl_vertex_shader())?\n\tgl.shaderSource(vert_shader, vert_code.str)\n\tgl.compileShader(vert_shader)\n\n\tif !bool(JS.Boolean(gl.getShaderParameter(vert_shader, dom.gl_compile_status()))) {\n\t\tpanic('An error occurred when compiling vertex shader: ${string(gl.getShaderInfoLog(vert_shader))}')\n\t}\n\n\tfrag_shader := gl.createShader(dom.gl_fragment_shader())?\n\tgl.shaderSource(frag_shader, frag_code.str)\n\tgl.compileShader(frag_shader)\n\tif !bool(JS.Boolean(gl.getShaderParameter(frag_shader, dom.gl_compile_status()))) {\n\t\tpanic('An error occurred when compiling fragment shader: ${string(gl.getShaderInfoLog(frag_shader))}')\n\t}\n\n\tshader_program := gl.createProgram()?\n\tgl.attachShader(shader_program, vert_shader)\n\tgl.attachShader(shader_program, frag_shader)\n\tgl.linkProgram(shader_program)\n\n\tif !bool(JS.Boolean(gl.getProgramParameter(shader_program, dom.gl_link_status()))) {\n\t\tpanic('unable to initialize the shader program: ${string(gl.getProgramInfoLog(shader_program))}')\n\t}\n\n\tpmatrix := gl.getUniformLocation(shader_program, 'Pmatrix'.str)?\n\tvmatrix := gl.getUniformLocation(shader_program, 'Vmatrix'.str)?\n\tmmatrix := gl.getUniformLocation(shader_program, 'Mmatrix'.str)?\n\n\tgl.bindBuffer(dom.gl_array_buffer(), vertex_buffer)\n\tposition := gl.getAttribLocation(shader_program, 'position'.str)\n\tgl.vertexAttribPointer(position, JS.Number(3), dom.gl_float(), JS.Boolean(false),\n\t\tJS.Number(0), JS.Number(0))\n\tgl.enableVertexAttribArray(position)\n\n\tgl.bindBuffer(dom.gl_array_buffer(), color_buffer)\n\tcolor := gl.getAttribLocation(shader_program, 'color'.str)\n\tgl.vertexAttribPointer(color, JS.Number(3), dom.gl_float(), JS.Boolean(false), JS.Number(0),\n\t\tJS.Number(0))\n\tgl.enableVertexAttribArray(color)\n\tgl.useProgram(shader_program)\n\n\tmut proj_matrix := get_projection(40.0, f64(canvas.width) / f64(canvas.height), 1.0,\n\t\t100.0)\n\tmut mo_matrix := [f64(1), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]\n\tmut view_matrix := [f64(1), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]\n\n\tview_matrix[14] = view_matrix[14] - 6\n\n\tmut state := State{false, gl, canvas, 0, 0, 0, 0, 0, 0, 0, mo_matrix, view_matrix, proj_matrix, pmatrix, vmatrix, mmatrix, index_buffer}\n\n\tcanvas.addEventListener('mousedown'.str, fn [mut state] (e JS.Event) {\n\t\tstate.drag = true\n\t\tmatch e {\n\t\t\tJS.MouseEvent {\n\t\t\t\tstate.old_x = f64(e.pageX)\n\t\t\t\tstate.old_y = f64(e.pageY)\n\t\t\t\te.preventDefault()\n\t\t\t}\n\t\t\telse {}\n\t\t}\n\t}, JS.EventListenerOptions{})\n\n\tcanvas.addEventListener('mouseup'.str, fn [mut state] (e JS.Event) {\n\t\tstate.drag = false\n\t}, JS.EventListenerOptions{})\n\tcanvas.addEventListener('mouseout'.str, fn [mut state] (e JS.Event) {\n\t\tstate.drag = false\n\t}, JS.EventListenerOptions{})\n\tcanvas.addEventListener('mousemove'.str, fn [mut state] (e JS.Event) {\n\t\tif !state.drag {\n\t\t\treturn\n\t\t}\n\t\tmatch e {\n\t\t\tJS.MouseEvent {\n\t\t\t\tstate.dx = (f64(e.pageX) - state.old_x) * 2.0 * math.pi / f64(state.canvas.width)\n\t\t\t\tstate.dy = (f64(e.pageY) - state.old_y) * 2.0 * math.pi / f64(state.canvas.height)\n\t\t\t\tstate.theta += state.dx\n\t\t\t\tstate.phi += state.dy\n\t\t\t\tstate.old_x = f64(e.pageX)\n\t\t\t\tstate.old_y = f64(e.pageY)\n\t\t\t\te.preventDefault()\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpanic('not a mouse event??')\n\t\t\t}\n\t\t}\n\t}, JS.EventListenerOptions{})\n\n\tanimate(mut state, 0)\n}\n"
  },
  {
    "path": "examples/js_dom_cube/index.html",
    "content": "<body>\n    <canvas width=\"570\" height=\"570\" id=\"myCanvas\"></canvas>\n    <script src=\"cube.js\">\n\n    </script>\n</body>"
  },
  {
    "path": "examples/js_dom_draw/README.md",
    "content": "# JS DOM Draw\n\nDrawing with mouse events using the DOM API. Adopted from MDN examples.\n\n## Compiling\n\n```sh\nv -b js_browser examples/js_dom_draw/draw.js.v\n```\n\nThen you can open `index.html` in your favorite browser.\n\n## Serve Examples\n\n### JS Server\n\n> [!NOTE]\n> The JS server example in the following steps requires Node.js.\n> To install Node, please refer to the [download page](https://nodejs.org/en/download/)\n> or the installation via your operating systems [package manager](https://nodejs.org/en/download/package-manager).\n\nInitialize the example as a Node project\n\n```\ncd examples/js_dom_draw/\nnpm init -y\n```\n\nAdd a `start` and `build` script to the generated `./package.json` file.\n\n```json\n  \"scripts\": {\n    ...\n    \"start\": \"npm run build && node server.js\",\n    \"build\": \"v -b js_browser draw.js.v\"\n  },\n```\n\nBelow is an example of a Node.js server without external dependencies.\nYou can use it for `./server.js`.\n\n```javascript\nconst http = require('http');\nconst fs = require('fs');\nvar path = require('path');\n\nconst host = 'localhost';\nconst port = 3000;\n\nconst reqListener = function (req, res) {\n\tconsole.log('[route] - ', req.url);\n\n\tvar filePath = '.' + req.url;\n\tif (filePath == './') {\n\t\tfilePath = './index.html';\n\t}\n\n\tvar extname = String(path.extname(filePath)).toLowerCase();\n\tvar mimeTypes = {\n\t\t'.html': 'text/html',\n\t\t'.js': 'text/javascript',\n\t\t'.css': 'text/css',\n\t\t'.json': 'application/json',\n\t\t'.png': 'image/png',\n\t\t'.jpg': 'image/jpg',\n\t\t'.gif': 'image/gif',\n\t\t'.svg': 'image/svg+xml',\n\t\t'.wav': 'audio/wav',\n\t\t'.mp4': 'video/mp4',\n\t\t'.woff': 'application/font-woff',\n\t\t'.ttf': 'application/font-ttf',\n\t\t'.eot': 'application/vnd.ms-fontobject',\n\t\t'.otf': 'application/font-otf',\n\t\t'.wasm': 'application/wasm',\n\t};\n\n\tvar contentType = mimeTypes[extname] || 'application/octet-stream';\n\n\tfs.readFile(filePath, function (error, content) {\n\t\tif (error) {\n\t\t\tif (error.code == 'ENOENT') {\n\t\t\t\tfs.readFile('./404.html', function (error, content) {\n\t\t\t\t\tres.writeHead(404, { 'Content-Type': 'text/html' });\n\t\t\t\t\tres.end(content, 'utf-8');\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tres.writeHead(500);\n\t\t\t\tres.end('Sorry, check with the site admin for error: ' + error.code + ' ..\\n');\n\t\t\t}\n\t\t} else {\n\t\t\tres.writeHead(200, { 'Content-Type': contentType });\n\t\t\tres.end(content, 'utf-8');\n\t\t}\n\t});\n};\n\nconst server = http.createServer(reqListener);\nserver.listen(port, host, () => {\n\tconsole.log(`Server is running on http://${host}:${port}`);\n});\n```\n\nNow you can build and run the project with the added scripts.\n\n```sh\nnpm run build\nnpm run start\n```\n\n### V server\n\nThe example below uses `vweb` to serve the project.\n\n```v\nmodule main\n\nimport vweb\nimport os\n\nconst http_port = 3001\n\nstruct App {\n\tvweb.Context\n}\n\nfn main() {\n\tvweb.run(new_app(), http_port)\n}\n\npub fn (mut app App) before_request() {\n\t// Build the draw.js javascript file\n\tos.execute_or_panic('v -b js_browser draw.js.v ')\n}\n\nfn new_app() &App {\n\tmut app := &App{}\n\tapp.serve_static('/favicon.ico', 'favicon.ico')\n\tapp.serve_static('/draw.js', 'draw.js')\n\tapp.mount_static_folder_at(os.resource_abs_path('.'), '/')\n\treturn app\n}\n\n@['/'; get]\npub fn (mut app App) controller_get_all_task() vweb.Result {\n\tfile := os.read_file('./index.html') or { panic(err) }\n\treturn app.html(file)\n}\n```"
  },
  {
    "path": "examples/js_dom_draw/draw.js.v",
    "content": "import js.dom\n\nfn get_canvas(elem JS.HTMLElement) JS.HTMLCanvasElement {\n\tmatch elem {\n\t\tJS.HTMLCanvasElement {\n\t\t\treturn elem\n\t\t}\n\t\telse {\n\t\t\tpanic('Not a canvas')\n\t\t}\n\t}\n}\n\nfn draw_line(mut context JS.CanvasRenderingContext2D, x1 int, y1 int, x2 int, y2 int) {\n\tcontext.beginPath()\n\tcontext.strokeStyle = 'black'.str\n\tcontext.lineWidth = JS.Number(1)\n\tcontext.moveTo(x1, y1)\n\tcontext.lineTo(x2, y2)\n\tcontext.stroke()\n\tcontext.closePath()\n}\n\nstruct DrawState {\nmut:\n\tcontext JS.CanvasRenderingContext2D\n\tdrawing bool\n\tx       int\n\ty       int\n}\n\nfn main() {\n\twindow := dom.window()\n\tdocument := dom.document\n\tclear_btn := document.getElementById('clearButton'.str)?\n\tcanvas_elem := document.getElementById('canvas'.str)?\n\tcanvas := get_canvas(canvas_elem)\n\tctx := canvas.getContext('2d'.str, js_undefined())?\n\tcontext := match ctx {\n\t\tJS.CanvasRenderingContext2D {\n\t\t\tctx\n\t\t}\n\t\telse {\n\t\t\tpanic('can not get 2d context')\n\t\t}\n\t}\n\tmut state := DrawState{context, false, 0, 0}\n\n\tcanvas.addEventListener('mousedown'.str, fn [mut state] (event JS.Event) {\n\t\tstate.drawing = true\n\t\tmatch event {\n\t\t\tJS.MouseEvent {\n\t\t\t\tstate.x = int(event.offsetX)\n\t\t\t\tstate.y = int(event.offsetY)\n\t\t\t}\n\t\t\telse {}\n\t\t}\n\t}, JS.EventListenerOptions{})\n\tcanvas.addEventListener('mousemove'.str, fn [mut state] (event JS.Event) {\n\t\tif state.drawing {\n\t\t\tmatch event {\n\t\t\t\tJS.MouseEvent {\n\t\t\t\t\tdraw_line(mut state.context, state.x, state.y, int(event.offsetX),\n\t\t\t\t\t\tint(event.offsetY))\n\t\t\t\t\tstate.x = int(event.offsetX)\n\t\t\t\t\tstate.y = int(event.offsetY)\n\t\t\t\t}\n\t\t\t\telse {}\n\t\t\t}\n\t\t}\n\t}, JS.EventListenerOptions{})\n\n\twindow.addEventListener('mouseup'.str, fn [mut state] (event JS.Event) {\n\t\tif state.drawing {\n\t\t\tmatch event {\n\t\t\t\tJS.MouseEvent {\n\t\t\t\t\tdraw_line(mut state.context, state.x, state.y, int(event.offsetX),\n\t\t\t\t\t\tint(event.offsetY))\n\t\t\t\t}\n\t\t\t\telse {}\n\t\t\t}\n\t\t\tstate.x = 0\n\t\t\tstate.y = 0\n\t\t\tstate.drawing = false\n\t\t}\n\t}, JS.EventListenerOptions{})\n\tclear_btn.addEventListener('click'.str, fn [mut state, canvas] (_ JS.Event) {\n\t\tstate.context.clearRect(0, 0, canvas.width, canvas.height)\n\t}, JS.EventListenerOptions{})\n}\n"
  },
  {
    "path": "examples/js_dom_draw/index.html",
    "content": "<body class=\"main\">\n    <title>Drawing with mouse events</title>\n    <input type=\"button\" id=\"clearButton\" value=\"Clear canvas\">\n    <canvas style=\"border: 1px solid black;\" width=\"720\" height=\"480\" id=\"canvas\"></canvas>\n    <script type=\"text/javascript\" src=\"draw.js\"></script>\n\n</body>"
  },
  {
    "path": "examples/js_dom_draw_benchmark_chart/README.md",
    "content": "# JS DOM Benchmark Chart\n\n![image](https://user-images.githubusercontent.com/63821277/186010833-2ea36f3a-4738-4025-9b23-ac62afe74b81.png)\n\n## Running the App\n\n> [!NOTE]\n> The following steps require Node.js.\n> To install Node, please refer to the [download page](https://nodejs.org/en/download/)\n> or the installation via your operating systems [package manager](https://nodejs.org/en/download/package-manager).\n\nThe steps below assume that your current directory path is the examples project directory.\n\n```\ncd examples/js_dom_draw_benchmark_chart\n```\n\nExecute the following commands in separate terminal instances.\n\nRun the Benchmarks Typescript Part\n\n```sh\nnpm i --prefix typescript_vanilla_typeorm\nnpm run start:dev --prefix typescript_vanilla_typeorm\n```\n\nRun the Benchmarks V Part\n\n```sh\nv run v_vweb_orm\n```\n\nRun the Chart\n\n```\ncd chart/ && v run .\n```\n\n## Dockerfile\n\n> [docker build] => Docker image\\\n> [docker run] => Docker container\n\n```sh\nsudo docker build -t <name> .\nsudo docker run --name <container name> --interactive --tty --publish 3001:3001 <name>\nv run .\n# A message like `[Vweb] Running app on http://localhost:3001/` should appear\nexit\n```\n\n## Implementing New Benchmarks in V\n\nIn `v_vweb_orm/src/main.v`, create a route that returns a `Response` struct.\n\n```v ignore\n@['/sqlite-memory/:count']\npub fn (mut app App) sqlite_memory(count int) vweb.Result {\n\tmut insert_stopwatchs := []int{}\n\tmut select_stopwatchs := []int{}\n\tmut update_stopwatchs := []int{}\n\n\tmut sw := time.new_stopwatch()\n\n\tmut db := sqlite.connect(':memory:') or { panic(err) }\n\n\tsql db {\n\t\tcreate table Task\n\t}!\n\n\ttask_model := Task{\n\t\ttitle: 'a'\n\t\tstatus: 'done'\n\t}\n\n\tfor i := 0; i < count; i++ {\n\t\tsw.start()\n\t\tsql db {\n\t\t\tinsert task_model into Task\n\t\t} or { []Task{} }\n\t\tsw.stop()\n\t\tinsert_stopwatchs << int(sw.end - sw.start)\n\t}\n\n\tsql db {\n\t\tdrop table Task\n\t}!\n\n\tresponse := Response{\n\t\tinsert: insert_stopwatchs\n\t\t@select: select_stopwatchs\n\t\tupdate: update_stopwatchs\n\t}\n\treturn app.json(response)\n}\n```\n\nIn `chart/main.v`, create a service to request the benchmark data and decode the response as\n`FrameworkBenchmarkResponse`.\n\n```v ignore\nfn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {\n\turl := 'http://localhost:3000/sqlite-memory/${benchmark_loop_length}'\n\tres := http.get(url) or { panic(err) }\n\tframework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)!\n\treturn framework_benchmark_response\n}\n```\n\nThen update `insert_framework_benchmark_times()`, `select_framework_benchmark_times()` and\n`update_framework_benchmark_times()` to include the `numbers := FrameworkPlatform{` for the newly\nadded function.\n\n## Roadmap\n\n02/09/2022\n\n- [ ] select bench (easy)\n- [ ] vsql (easy)\n"
  },
  {
    "path": "examples/js_dom_draw_benchmark_chart/chart/.gitignore",
    "content": "*.js\n*.exe\n*.db"
  },
  {
    "path": "examples/js_dom_draw_benchmark_chart/chart/Dockerfile",
    "content": "FROM thevlang/vlang:alpine-dev\n\nWORKDIR /app\n\nCOPY . .\n\nRUN v up && v -prod main.v"
  },
  {
    "path": "examples/js_dom_draw_benchmark_chart/chart/README.md",
    "content": "# To run app\nDockerfile\n[docker build]=> Docker image\n[docker run]=> Docker container\n\n`sudo docker build -t <name> .`\n\n`sudo docker run --name <container name> --interactive --tty --publish 3001:3001 <name>`\n\n`v run .`\n\nA message like `[Vweb] Running app on http://localhost:3001/` should appear\n\n`exit`\n\n# To implement new benchmarks in v\n\nIn `examples/js_dom_draw_benchmark_chart/v_vweb_orm/src/main.v` path\nCreate a route returning a `Response` struct like:\n\n```v ignore\n@['/sqlite-memory/:count']\npub fn (mut app App) sqlite_memory(count int) vweb.Result {\n\tmut insert_stopwatchs := []int{}\n\tmut select_stopwatchs := []int{}\n\tmut update_stopwatchs := []int{}\n\n\tmut sw := time.new_stopwatch()\n\n\tmut db := sqlite.connect(':memory:') or { panic(err) }\n\n\tsql db {\n\t\tcreate table Task\n\t} or { panic(err) }\n\n\ttask_model := Task{\n\t\ttitle: 'a'\n\t\tstatus: 'done'\n\t}\n\n\tfor i := 0; i < count; i++ {\n\t\tsw.start()\n\t\tsql db {\n\t\t\tinsert task_model into Task\n\t\t} or { []Task{} }\n\t\tsw.stop()\n\t\tinsert_stopwatchs << int(sw.end - sw.start)\n\t}\n\n\tsql db {\n\t\tdrop table Task\n\t} or { panic(err) }\n\n\tresponse := Response{\n\t\tinsert:\tinsert_stopwatchs\n\t\t@select:select_stopwatchs\n\t\tupdate:\tupdate_stopwatchs\n\t}\n\treturn app.json(response)\n}\n\n```\n\nIn `examples/chart/services.v` path\nCreate a service to request the benchmarks data by http\nDecode the info to `FrameworkBenchmarkResponse`\n```v ignore\nfn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {\n\turl := 'http://localhost:3000/sqlite-memory/${benchmark_loop_length}'\n\tres := http.get(url) or { panic(err) }\n\tframework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)!\n\treturn framework_benchmark_response\n}\n```\n\nIn `examples/chart/main.v` path\nCreate a service to request the benchmarks data by http\nDecode the info to `FrameworkBenchmarkResponse`\n```v ignore\nfn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {\n\turl := 'http://localhost:3000/sqlite-memory/${benchmark_loop_length}'\n\tres := http.get(url) or { panic(err) }\n\tframework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)!\n\treturn framework_benchmark_response\n}\n```\nThen, update:\n`insert_framework_benchmark_times()`;\n`select_framework_benchmark_times()`;\n`update_framework_benchmark_times()`.\nwith the new function\n\n\n\n# ROADMAP\n02/09/2022\n- [ ] select bench (easy)\n- [ ] vsql (easy)\n"
  },
  {
    "path": "examples/js_dom_draw_benchmark_chart/chart/draw.js.v",
    "content": "module main\n\nimport js.dom\n\nfn get_canvas(elem JS.HTMLElement) JS.HTMLCanvasElement {\n\t//  error: `JS.HTMLElement` doesn't implement method `getContext` of interface `JS.HTMLCanvasElement`\n\tmatch elem {\n\t\tJS.HTMLCanvasElement {\n\t\t\treturn elem\n\t\t}\n\t\telse {\n\t\t\tJS.console.log('Not canvas')\n\t\t\treturn JS.HTMLCanvasElement{}\n\t\t}\n\t}\n}\n\nfn draw_line(mut context JS.CanvasRenderingContext2D, _x1 int, _y1 int, _x2 int, _y2 int) {\n\tcontext.beginPath()\n\tcontext.strokeStyle = 'black'.str\n\tcontext.lineWidth = JS.Number(1)\n\tcontext.moveTo(0, 0)\n\tcontext.lineTo(100, 100)\n\tcontext.stroke()\n\tcontext.closePath()\n}\n\nstruct DrawState {\nmut:\n\tcontext JS.CanvasRenderingContext2D\n\tdrawing bool\n\tx       f64\n\ty       f64\n}\n\nstruct FrameworkPlatform {\nmut:\n\tv_sqlite_memory []int\n\t// v_sqlite_file            []int\n\ttypescript_sqlite_memory []int\n}\n\nfn (mut state DrawState) draw_bench_chart(color string, time_array []int, max_time int) ? {\n\tmax_height := f64(480)\n\tmax_width := f64(720)\n\n\tstate.drawing = true\n\tstate.x = f64(0)\n\tstate.y = f64(max_height)\n\tstate.context.strokeStyle = color.str\n\tstate.context.lineWidth = JS.Number(1)\n\n\tfor i := 0; i <= time_array.len; i++ {\n\t\tstate.context.beginPath()\n\t\tstate.context.moveTo(state.x, state.y)\n\t\tstate.x = max_width / f64(time_array.len) * i + 1.0\n\t\tstate.y = max_height - (max_height / f64(max_time) * f64(time_array[i]))\n\t\tstate.context.lineTo(state.x, state.y)\n\t\tstate.context.stroke()\n\t\tstate.context.closePath()\n\t}\n\n\tstate.drawing = false\n}\n\nfn main() {\n\tdocument := dom.document\n\n\tmut canvas_elem := map[string]JS.HTMLElement{}\n\tmut canvas := map[string]JS.HTMLCanvasElement{}\n\n\tcanvas_elem['insert'] = document.getElementById('canvas_insert_id'.str)?\n\tJS.console.log('canvas_insert_id')\n\n\tcanvas_elem['select'] = document.getElementById('canvas_select_id'.str)?\n\tJS.console.log('canvas_select_id')\n\n\tcanvas_elem['update'] = document.getElementById('canvas_update_id'.str)?\n\tJS.console.log('canvas_update_id')\n\n\t// for orm_stmt_kind in [\"insert\", \"select\", \"update\"]{\n\tfor orm_stmt_kind in ['insert', 'select', 'update'] {\n\t\t// type HTMLElement\n\n\t\tcanvas[orm_stmt_kind] = get_canvas(canvas_elem[orm_stmt_kind])\n\n\t\tctx := canvas[orm_stmt_kind].getContext('2d'.str, js_undefined())?\n\n\t\tcontext := match ctx {\n\t\t\tJS.CanvasRenderingContext2D {\n\t\t\t\tctx\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpanic('can not get 2d context')\n\t\t\t}\n\t\t}\n\n\t\tmut state := DrawState{context, false, 0, 0}\n\n\t\tmut inserts_from_framework := canvas_elem[orm_stmt_kind].getAttribute('inserts_from_framework'.str)?\n\n\t\tmut max_benchmark := canvas_elem[orm_stmt_kind].getAttribute('max_benchmark'.str)?\n\n\t\t// -----------------------------------------------------------------------------------------------------------------------------------------------------------------\n\t\tmut obj := FrameworkPlatform{}\n\t\tobj = JS.JSON.parse(tos(inserts_from_framework))\n\n\t\t// Waiting for v implement for loop getting key and value of object in v.js\n\t\tmut attribute_int_values := []int{}\n\n\t\t//* v framework\n\t\tfor variable in obj.v_sqlite_memory {\n\t\t\tattribute_int_values << variable\n\t\t}\n\n\t\tstate.draw_bench_chart('gray', attribute_int_values, tos(max_benchmark).int())?\n\t\tattribute_int_values = []\n\n\t\t//* typescript framework\n\n\t\tfor variable in obj.typescript_sqlite_memory {\n\t\t\tattribute_int_values << variable\n\t\t}\n\n\t\tstate.draw_bench_chart('red', attribute_int_values, tos(max_benchmark).int())?\n\n\t\tattribute_int_values = []\n\t}\n}\n"
  },
  {
    "path": "examples/js_dom_draw_benchmark_chart/chart/main.v",
    "content": "module main\n\nimport vweb\nimport os\nimport json\nimport arrays\nimport net.http\nimport math\nimport v.util.version\n\n@[table: 'benchmark']\nstruct Task {\nmut:\n\tid     u32 @[primary; serial; sql: serial]\n\ttitle  string\n\tstatus string\n}\n\nstruct FrameworkBenchmarkResponse {\n\tinsert []int\n\tselect []int\n\tupdate []int\n}\n\nstruct FrameworkPlatform {\nmut:\n\tv_sqlite_memory []int\n\t// v_sqlite_file            []int\n\ttypescript_sqlite_memory []int\n}\n\nfn (framework_platform FrameworkPlatform) to_map() map[string][]int {\n\tmut mapa := map[string][]int{}\n\n\tmapa['v_sqlite_memory'] = framework_platform.v_sqlite_memory\n\t// mapa['v_sqlite_file'] = framework_platform.v_sqlite_file\n\tmapa['typescript_sqlite_memory'] = framework_platform.typescript_sqlite_memory\n\treturn mapa\n}\n\nconst http_port = 3001\nconst benchmark_loop_length = 20\n\nstruct App {\n\tvweb.Context\n}\n\nenum SqliteDbConnection {\n\tsqlite_memory\n\tsqlite_file\n}\n\nfn main() {\n\tvweb.run(new_app(), http_port)\n}\n\npub fn (mut app App) before_request() {\n\tos.execute_or_panic('v -b js_browser draw.js.v ')\n}\n\nfn new_app() &App {\n\tmut app := &App{}\n\tapp.serve_static('/favicon.ico', 'favicon.ico')\n\tapp.serve_static('/draw.js', 'draw.js')\n\tapp.mount_static_folder_at(os.resource_abs_path('.'), '/')\n\treturn app\n}\n\n@['/'; get]\npub fn (mut app App) controller_get_all_task() !vweb.Result {\n\tv_version := version.full_v_version(true)\n\torm_stmt_kinds := ['insert', 'select', 'update']\n\n\tmut attribute_names := map[string][]string{}\n\t// Used to garante the chart proposionalite\n\tmut max_benchmark := map[string]int{}\n\tmut from_framework := map[string]string{}\n\tmut maxs := map[string][]int{}\n\tmut framework_platform := map[string]map[string][]int{}\n\tmut table := map[string]map[string]map[string]string{}\n\n\tchart_colors := ['gray', 'red', 'orange', 'purple', 'red', 'orange', 'purple']\n\tfor orm_stmt_kind in orm_stmt_kinds {\n\t\tmatch orm_stmt_kind {\n\t\t\t'insert' {\n\t\t\t\tframework_platform[orm_stmt_kind] = insert_framework_benchmark_times() or {\n\t\t\t\t\treturn error('')\n\t\t\t\t}.to_map()\n\t\t\t}\n\t\t\t'select' {\n\t\t\t\tframework_platform[orm_stmt_kind] = select_framework_benchmark_times() or {\n\t\t\t\t\treturn error('')\n\t\t\t\t}.to_map()\n\t\t\t}\n\t\t\t'update' {\n\t\t\t\tframework_platform[orm_stmt_kind] = update_framework_benchmark_times() or {\n\t\t\t\t\treturn error('')\n\t\t\t\t}.to_map()\n\t\t\t}\n\t\t\telse {}\n\t\t}\n\n\t\tfor key, values in framework_platform[orm_stmt_kind] {\n\t\t\tattribute_names[orm_stmt_kind] << key\n\t\t\tmaxs[orm_stmt_kind] << arrays.max(values) or { continue }\n\t\t}\n\n\t\tfrom_framework[orm_stmt_kind] = json.encode(framework_platform[orm_stmt_kind])\n\t\ttable[orm_stmt_kind] = gen_table_info(attribute_names[orm_stmt_kind], framework_platform[orm_stmt_kind])\n\t\tmax_benchmark[orm_stmt_kind] = arrays.max(maxs[orm_stmt_kind]) or { continue }\n\t}\n\n\treturn $vweb.html()\n}\n\nfn insert_framework_benchmark_times() !FrameworkPlatform {\n\tnumbers := FrameworkPlatform{\n\t\tv_sqlite_memory: v_sqlite_memory()!.insert\n\t\t// v_sqlite_file: v_sqlite_file()!.insert\n\t\ttypescript_sqlite_memory: typescript_sqlite_memory()!.insert\n\t}\n\n\treturn numbers\n}\n\nfn select_framework_benchmark_times() !FrameworkPlatform {\n\tnumbers := FrameworkPlatform{\n\t\tv_sqlite_memory: v_sqlite_memory()!.select\n\t\t// v_sqlite_file: v_sqlite_file()!.select\n\t\ttypescript_sqlite_memory: typescript_sqlite_memory()!.select\n\t}\n\n\treturn numbers\n}\n\nfn update_framework_benchmark_times() !FrameworkPlatform {\n\tnumbers := FrameworkPlatform{\n\t\tv_sqlite_memory: v_sqlite_memory()!.update\n\t\t// v_sqlite_file: v_sqlite_file()!.select\n\t\ttypescript_sqlite_memory: typescript_sqlite_memory()!.update\n\t}\n\n\treturn numbers\n}\n\nfn typescript_sqlite_memory() !FrameworkBenchmarkResponse {\n\turl := 'http://localhost:3000/sqlite-memory/${benchmark_loop_length}'\n\tres := http.get(url) or { panic(err) }\n\tframework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)!\n\treturn framework_benchmark_response\n}\n\nfn v_sqlite_memory() !FrameworkBenchmarkResponse {\n\turl := 'http://localhost:4000/sqlite-memory/${benchmark_loop_length}'\n\tres := http.get(url) or { panic(err) }\n\tframework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)!\n\treturn framework_benchmark_response\n}\n\nfn v_sqlite_file() !FrameworkBenchmarkResponse {\n\t// url := 'http://localhost:3000/sqlite-memory/${benchmark_loop_length}'\n\t// res := http.get(url) or { panic(err) }\n\t// framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)!\n\tframework_benchmark_response := FrameworkBenchmarkResponse{\n\t\tinsert: []\n\t\tselect: []\n\t\tupdate: []\n\t}\n\treturn framework_benchmark_response\n}\n\nfn gen_table_info(attribute_names []string, framework_platform map[string][]int) map[string]map[string]string {\n\tmut table := map[string]map[string]string{}\n\n\t// nanoseconds\n\tmut max_times := map[string]int{}\n\tmut ten_perc_max_times := map[string]int{}\n\tmut min_times := map[string]int{}\n\tmut ten_perc_min_times := map[string]int{}\n\n\t// bigger to calculate percent\n\tmut max := 0.0\n\tmut ten_perc_max := 0.0\n\tmut min := 0.0\n\tmut ten_perc_min := 0.0\n\n\t// percentes\n\tmut max_fast := map[string]int{}\n\tmut ten_perc_max_fast := map[string]int{}\n\tmut min_fast := map[string]int{}\n\tmut ten_perc_min_fast := map[string]int{}\n\n\t// nanoseconds\n\tfor idx, name in attribute_names {\n\t\t// qtd. of values in 10 % of arrays\n\t\tten_perc := int(framework_platform[name].len / 10)\n\n\t\t// get 10% higher\n\t\tmut min_ten_array := framework_platform[name].clone()\n\t\tmin_ten_array.sort()\n\t\tmin_ten_array.trim(ten_perc)\n\n\t\t// get 10% lower\n\t\tmut max_ten_array := framework_platform[name].clone()\n\t\tmax_ten_array.sort(a > b)\n\t\tmax_ten_array.trim(ten_perc)\n\n\t\t// popule array with nanoseconds to which benchmark\n\t\tmax_times[name] = arrays.max(framework_platform[name]) or { 0 } // int\n\t\tten_perc_max_times[name] = arrays.sum(max_ten_array) or { 0 } / ten_perc // int\n\t\tmin_times[name] = arrays.min(framework_platform[name]) or { 0 } // int\n\t\tten_perc_min_times[name] = arrays.sum(min_ten_array) or { 0 } / ten_perc // int\n\n\t\t// set bigger values\n\t\tif idx < 1 {\n\t\t\tmax = f64(max_times[name])\n\t\t\tten_perc_max = f64(ten_perc_max_times[name])\n\t\t\tmin = f64(min_times[name])\n\t\t\tten_perc_min = f64(ten_perc_min_times[name])\n\t\t} else {\n\t\t\tif max < f64(max_times[name]) {\n\t\t\t\tmax = f64(max_times[name])\n\t\t\t}\n\t\t\tif ten_perc_max < f64(ten_perc_max_times[name]) {\n\t\t\t\tten_perc_max = f64(ten_perc_max_times[name])\n\t\t\t}\n\t\t\tif min < f64(min_times[name]) {\n\t\t\t\tmin = f64(min_times[name])\n\t\t\t}\n\t\t\tif ten_perc_min < f64(ten_perc_min_times[name]) {\n\t\t\t\tten_perc_min = f64(ten_perc_min_times[name])\n\t\t\t}\n\t\t}\n\t}\n\n\t// percents\n\tfor name in attribute_names {\n\t\tmax_fast[name] = int(max / f64(max_times[name]))\n\t\tten_perc_max_fast[name] = int(ten_perc_max / f64(ten_perc_max_times[name]))\n\t\tmin_fast[name] = int(min / f64(min_times[name]))\n\t\tten_perc_min_fast[name] = int(ten_perc_min / f64(ten_perc_min_times[name]))\n\t}\n\n\tfor name in attribute_names {\n\t\ttable[name]['max.'] = '${math.round_sig(f64(max_times[name]) / 1000000, 2)} ms (${max_fast[name]}x faster)'\n\t\ttable[name]['10% max.'] = '${math.round_sig(f64(ten_perc_max_times[name]) / 1000000,\n\t\t\t2)} ms (${ten_perc_max_fast[name]}x faster)'\n\t\ttable[name]['min.'] = '${math.round_sig(f64(min_times[name]) / 1000000, 2)} ms (${min_fast[name]}x faster)'\n\t\ttable[name]['10% min.'] = '${math.round_sig(f64(ten_perc_min_times[name]) / 1000000,\n\t\t\t2)} ms (${ten_perc_min_fast[name]}x faster)'\n\t}\n\treturn table\n}\n"
  },
  {
    "path": "examples/js_dom_draw_benchmark_chart/chart/templates/controller/get/all/task.html",
    "content": "<body class=\"main\">\n  <style>\n    table,\n    th,\n    td {\n      border: 1px solid black;\n    }\n  </style>\n\n  <title>Is V orm still fast? ${v_version}</title>\n  <div style=\"display: flex; align-items: center\">\n    <h2\n      style=\"\n        font-family: Menlo, Monospace, 'Courier New';\n        margin-left: 30px;\n        margin-top: 30px;\n      \"\n    >\n      Is V orm still fast?\n    </h2>\n\n    <img src=\"./../../../../favicon.ico\" height=\"35px\" />\n    <h5 style=\"font-family: Menlo, Monospace, 'Courier New'; color: #3b7bbf\">\n      ${v_version}\n    </h5>\n  </div>\n  <div style=\"display: flex; flex-direction: row; flex-wrap: wrap\">\n    @for orm_stmt_kind in orm_stmt_kinds\n    <!-- <div style=\"display: flex; flex-direction: column; \"> -->\n    <div\n      style=\"\n        border-radius: 15px;\n        padding: 15px;\n        margin: 15px;\n        box-shadow: 0px 2px 10px 1px grey;\n      \"\n    >\n      <div style=\"display: flex; flex-direction: column; max-width: 850px\">\n        <h2 style=\"font-family: Arial, Helvetica, sans-serif\">\n          ${orm_stmt_kind} benchmark\n        </h2>\n\n        <div\n          style=\"\n            display: flex;\n            flex-direction: row;\n            justify-content: space-between;\n          \"\n        >\n          <div\n            style=\"\n              display: flex;\n              flex-direction: column-reverse;\n              justify-content: space-between;\n              text-align: center;\n              width: 100%;\n              height: 480;\n              margin-right: 20px;\n              background-image: linear-gradient(red, yellow, green, #3b7bbf);\n            \"\n          >\n            @for number in 0..11\n            <div style=\"font-family: Arial, Helvetica, sans-serif\">\n              ${int(number*(f64(max_benchmark[orm_stmt_kind])/10))} ns\n            </div>\n            @end\n          </div>\n\n          <canvas\n            id=\"canvas_${orm_stmt_kind}_id\"\n            inserts_from_framework=\"@{from_framework[orm_stmt_kind]}\"\n            max_benchmark=\"@{max_benchmark[orm_stmt_kind]}\"\n            style=\"border: 1px solid grey\"\n            width=\"720\"\n            height=\"480\"\n          ></canvas>\n        </div>\n        <table style=\"margin-top: 10px\">\n          <tr>\n            <th>Benchmark name</th>\n            <th>max.</th>\n            <th>10% max.</th>\n            <th>min.</th>\n            <th>10% min.</th>\n          </tr>\n          @for idx, name in attribute_names[orm_stmt_kind]\n          <tr style=\"font-family:arial; color: ${chart_colors[idx]};\">\n            <td style=\"padding-right: 5px\" id=\"benchmark_name\" +idx>@name</td>\n            <td style=\"padding-left: 5px; padding-right: 5px\">\n              @{table[orm_stmt_kind][name][\"max.\"]}\n            </td>\n            <td style=\"padding-left: 5px; padding-right: 5px\">\n              @{table[orm_stmt_kind][name][\"10% max.\"]}\n            </td>\n            <td style=\"padding-left: 5px; padding-right: 5px\">\n              @{table[orm_stmt_kind][name][\"min.\"]}\n            </td>\n            <td style=\"padding-left: 5px; padding-right: 5px\">\n              @{table[orm_stmt_kind][name][\"10% min.\"]}\n            </td>\n          </tr>\n          @end\n        </table>\n      </div>\n      <!-- </div> -->\n    </div>\n    @end\n  </div>\n  <script type=\"text/javascript\" src=\"draw.js\"></script>\n</body>\n"
  },
  {
    "path": "examples/js_dom_draw_benchmark_chart/typescript_vanilla_typeorm/.gitignore",
    "content": "\n*/node_modules/**/*\n/node_modules/**/*\nnode_modules/**/*\n/node_modules/\nnode_modules/\nnode_modules\n\n# Ignore built ts files\n*/dist/**/*\n/dist/**/*\ndist/**/*\n/dist/\ndist/\ndist\n\ntemp/*\ntemp/\n*/temp/**/*\n\npackage-lock.json\n\n# Not ignore built js or ts files\n!*.js\n!*.ts"
  },
  {
    "path": "examples/js_dom_draw_benchmark_chart/typescript_vanilla_typeorm/package.json",
    "content": "{\n  \"name\": \"js_dom_draw_chart_ts\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"dist/index.js\",\n  \"scripts\": {\n    \"start\": \"npm run build && node src/server.js\",\n    \"start:dev\": \"./node_modules/nodemon/bin/nodemon.js -e ts  --exec \\\"npm run start\\\"\",\n    \"build\": \"tsc\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"nodemon\": \"^2.0.19\",\n    \"reflect-metadata\": \"^0.1.13\",\n    \"sqlite3\": \"^5.0.11\",\n    \"typeorm\": \"^0.3.7\",\n    \"typescript\": \"^4.7.4\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^18.6.4\"\n  }\n}\n"
  },
  {
    "path": "examples/js_dom_draw_benchmark_chart/typescript_vanilla_typeorm/src/index.ts",
    "content": "import { performance } from \"perf_hooks\";\nimport { Entity, Column, PrimaryGeneratedColumn, DataSource } from \"typeorm\";\n\ntype Response = {\n  insert: number[];\n  select: number[];\n  update: number[];\n};\n\n@Entity(\"benchmark\")\nexport class Task {\n  @PrimaryGeneratedColumn()\n  id?: number;\n\n  @Column(\"text\")\n  title!: string;\n\n  @Column(\"text\")\n  status!: string;\n}\n\nexport const appDataSource = new DataSource({\n  type: \"sqlite\",\n  database: \":memory:\",\n  dropSchema: true,\n  entities: [Task],\n  synchronize: true, // create a new table\n  logging: false,\n});\n\nexport async function sqlite_memory(count: Number): Promise<Response> {\n  var insert_stopwatchs: number[] = [];\n  let select_stopwatchs: number[] = [];\n  let update_stopwatchs: number[] = [];\n\n  let sw = performance;\n\n  const taskRepository = appDataSource.getRepository(Task);\n\n  // inserts\n  for (let index = 0; index < count; index++) {\n    const task_model = new Task();\n    task_model.title = \"a\";\n    task_model.status = \"done\";\n\n    const start = sw.now();\n    await taskRepository.save(task_model).then((value) => {\n      const insert_stopwatch = (sw.now() - start) * 1000000;\n      insert_stopwatchs.push(Math.floor(insert_stopwatch)); //nanoseconds\n    });\n  }\n\n  // selects\n  for (let index = 0; index < count; index++) {\n    const start = sw.now();\n    await taskRepository.find().then((value) => {\n      const select_stopwatch = (sw.now() - start) * 1000000;\n      select_stopwatchs.push(Math.floor(select_stopwatch)); //nanoseconds\n    });\n  }\n\n  // updates\n  for (let index = 0; index < count; index++) {\n    const taskToUpdate = await taskRepository.findOneBy({ id: 1 });\n\n    taskToUpdate!.title = \"b\";\n    taskToUpdate!.status = \"finish\";\n\n    const start = sw.now();\n    await taskRepository.save(taskToUpdate!).then((value) => {\n      const update_stopwatch = (sw.now() - start) * 1000000;\n      update_stopwatchs.push(Math.floor(update_stopwatch)); //nanoseconds\n    });\n  }\n\n  // taskRepository.find().then((value) => {\n  //   console.log(`value: %j`, value);\n  // });\n\n  let response: Response = {\n    insert: insert_stopwatchs,\n    select: select_stopwatchs,\n    update: update_stopwatchs,\n  };\n\n  return Promise.resolve(response);\n}\n\n// export function sqlite_file(count: Number): Response {\n//   var insert_stopwatchs: number[] = [];\n//   let select_stopwatchs: number[] = [];\n//   let update_stopwatchs: number[] = [];\n\n//   for (let index = 0; index < count; index++) {\n//     insert_stopwatchs.push(index);\n//   }\n\n//   let response: Response = {\n//     insert: insert_stopwatchs,\n//     select: select_stopwatchs,\n//     update: update_stopwatchs,\n//   };\n\n//   return response;\n// }\n\n// export function postgres(count: Number): Response {\n//   var insert_stopwatchs: number[] = [];\n//   let select_stopwatchs: number[] = [];\n//   let update_stopwatchs: number[] = [];\n\n//   for (let index = 0; index < count; index++) {\n//     insert_stopwatchs.push(index);\n//   }\n\n//   let response: Response = {\n//     insert: insert_stopwatchs,\n//     select: select_stopwatchs,\n//     update: update_stopwatchs,\n//   };\n\n//   return response;\n// }\n\n// export function mysql(count: Number): Response {\n//   var insert_stopwatchs: number[] = [];\n//   let select_stopwatchs: number[] = [];\n//   let update_stopwatchs: number[] = [];\n\n//   for (let index = 0; index < count; index++) {\n//     insert_stopwatchs.push(index);\n//   }\n\n//   let response: Response = {\n//     insert: insert_stopwatchs,\n//     select: select_stopwatchs,\n//     update: update_stopwatchs,\n//   };\n\n//   return response;\n// }\n"
  },
  {
    "path": "examples/js_dom_draw_benchmark_chart/typescript_vanilla_typeorm/src/server.js",
    "content": "const http = require(\"http\");\nconst fs = require(\"fs\");\nvar path = require(\"path\");\nconst { hello, sqlite_memory, appDataSource } = require(\"..\");\n\nconst host = \"localhost\";\nconst port = 3000;\n\n// const hello = require(\"../index\")\n\nconst reqListener = async (req, res) => {\n  console.log(`[route] - (${req.method}) ${req.url}`);\n\n  var filePath = \".\" + req.url;\n  // if (filePath == './') {\n  //     filePath = './index.html';\n  // }\n\n  var extname = String(path.extname(filePath)).toLowerCase();\n  var mimeTypes = {\n    \".html\": \"text/html\",\n    \".js\": \"text/javascript\",\n    \".css\": \"text/css\",\n    \".json\": \"application/json\",\n    \".png\": \"image/png\",\n    \".jpg\": \"image/jpg\",\n    \".gif\": \"image/gif\",\n    \".svg\": \"image/svg+xml\",\n    \".wav\": \"audio/wav\",\n    \".mp4\": \"video/mp4\",\n    \".woff\": \"application/font-woff\",\n    \".ttf\": \"application/font-ttf\",\n    \".eot\": \"application/vnd.ms-fontobject\",\n    \".otf\": \"application/font-otf\",\n    \".wasm\": \"application/wasm\",\n  };\n\n  var contentType = mimeTypes[extname] || \"application/octet-stream\";\n\n  fs.readFile(filePath, function (error, content) {\n    if (error) {\n      if (error.code == \"ENOENT\") {\n        fs.readFile(\"./404.html\", function (error, content) {\n          // res.writeHead(404, { \"Content-Type\": \"text/html\" });\n          // res.end(content, \"utf-8\");\n        });\n      } else {\n        res.writeHead(500);\n        res.end(\n          \"Sorry, check with the site admin for error: \" + error.code + \" ..\\n\"\n        );\n      }\n    } else {\n      res.writeHead(200, { \"Content-Type\": contentType });\n      res.end(content, \"utf-8\");\n    }\n  });\n\n  // Routes\n  if (req.url == \"/\" && req.method == \"GET\") {\n    res.writeHead(200);\n    res.end(\"adad\");\n  }\n\n  if (req.url == \"/hello-world\" && req.method == \"GET\") {\n    res.writeHead(200);\n    res.end(\"hello world\");\n  }\n\n  if (req.url.includes(\"/sqlite-memory/\") && req.method == \"GET\") {\n    var count = req.url.replace(\"/sqlite-memory/\", \"\");\n\n    await sqlite_memory(count).then((response) => {\n      res.writeHead(200, { \"Content-Type\": \"application/json\" });\n      res.end(JSON.stringify(response));\n    });\n  }\n};\n\ntry {\n  const server = http.createServer(reqListener);\n\n  appDataSource.initialize();\n  console.log(\"Database working\");\n\n  server.listen(port, host);\n  console.log(`Server is running on http://${host}:${port}`);\n} catch (error) {\n  console.log(error);\n}\n"
  },
  {
    "path": "examples/js_dom_draw_benchmark_chart/typescript_vanilla_typeorm/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true,\n\n\n    /* Language and Environment */\n    \"target\": \"es2022\",     /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */\n    \"lib\": [\"es2022\"],      /* Specify a set of bundled library declaration files that describe the target runtime environment. */\n\n    /* Modules */\n    //Specify what module code is generated.\n    \"module\": \"commonjs\",\n\n    /* Emit */\n    // Specify an output folder for all emitted files.\n    \"outDir\": \"./dist\",     \n    // Disable emitting comments.\n    \"removeComments\": true,     \n\n\n    /* Interop Constraints */\n    // Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility.\n    \"esModuleInterop\": true,      \n    // Ensure that casing is correct in imports. \n    \"forceConsistentCasingInFileNames\": true,     \n\n    /* Type Checking */\n    // Enable all strict type-checking options.\n    \"strict\": true,     \n\n\n    // Completeness\n    // Skip type checking all .d.ts files.\n    \"skipLibCheck\": true      },\n    \"include\": [\"src/**/*\"]\n\n}\n"
  },
  {
    "path": "examples/js_dom_draw_benchmark_chart/v_vweb_orm/src/main.v",
    "content": "module main\n\nimport vweb\nimport time\nimport db.sqlite\n\nstruct App {\n\tvweb.Context\n}\n\n@[table: 'benchmark']\nstruct Task {\nmut:\n\tid     u32 @[primary; serial; sql: serial]\n\ttitle  string\n\tstatus string\n}\n\nstruct Response {\n\tinsert []int\n\tselect []int\n\tupdate []int\n}\n\nfn main() {\n\tvweb.run_at(new_app(), vweb.RunParams{\n\t\tport: 4000\n\t}) or { panic(err) }\n}\n\nfn new_app() &App {\n\tmut app := &App{}\n\treturn app\n}\n\n@['/hello-world']\npub fn (mut app App) hello_world() vweb.Result {\n\treturn app.text('hello world')\n}\n\n@['/sqlite-memory/:count']\npub fn (mut app App) sqlite_memory(count int) vweb.Result {\n\tmut insert_stopwatchs := []int{}\n\tmut select_stopwatchs := []int{}\n\tmut update_stopwatchs := []int{}\n\n\tmut sw := time.new_stopwatch()\n\n\tmut db := sqlite.connect(':memory:') or { panic(err) }\n\n\tsql db {\n\t\tcreate table Task\n\t} or { panic(err) }\n\n\ttask_model := Task{\n\t\ttitle:  'a'\n\t\tstatus: 'done'\n\t}\n\n\t// inserts\n\tfor i := 0; i < count; i++ {\n\t\tsw.start()\n\t\tsql db {\n\t\t\tinsert task_model into Task\n\t\t} or { panic(err) }\n\t\tsw.stop()\n\t\tinsert_stopwatchs << int(sw.end - sw.start)\n\t}\n\n\t// selects\n\tfor i := 0; i < count; i++ {\n\t\tsw.start()\n\t\tresult := sql db {\n\t\t\tselect from Task\n\t\t} or { []Task{} }\n\t\tsw.stop()\n\t\teprintln(result)\n\t\tselect_stopwatchs << int(sw.end - sw.start)\n\t}\n\n\t// updates\n\tfor i := 0; i < count; i++ {\n\t\tsw.start()\n\t\tsql db {\n\t\t\tupdate Task set title = 'b', status = 'finish' where id == i\n\t\t} or { panic(err) }\n\t\tsw.stop()\n\t\tupdate_stopwatchs << int(sw.end - sw.start)\n\t}\n\n\tsql db {\n\t\tdrop table Task\n\t} or { panic(err) }\n\n\tresponse := Response{\n\t\tinsert: insert_stopwatchs\n\t\tselect: select_stopwatchs\n\t\tupdate: update_stopwatchs\n\t}\n\treturn app.json(response)\n}\n\n@['/sqlite-file/:count']\npub fn (mut app App) sqlite_file(count int) vweb.Result {\n\tresponse := Response{\n\t\tinsert: []\n\t\tselect: []\n\t\tupdate: []\n\t}\n\treturn app.json(response)\n}\n\n@['/postgres/:count']\npub fn (mut app App) postgres(count int) vweb.Result {\n\tresponse := Response{\n\t\tinsert: []\n\t\tselect: []\n\t\tupdate: []\n\t}\n\treturn app.json(response)\n}\n\n@['/mysql/:count']\npub fn (mut app App) mysql(count int) vweb.Result {\n\tresponse := Response{\n\t\tinsert: []\n\t\tselect: []\n\t\tupdate: []\n\t}\n\treturn app.json(response)\n}\n"
  },
  {
    "path": "examples/js_hello_world.v",
    "content": "fn main() {\n\tfor i in 0 .. 3 {\n\t\tprintln('Hello from V.js (${i})')\n\t}\n}\n"
  },
  {
    "path": "examples/json.v",
    "content": "import json\n\nstruct User {\n\tname string\n\tage  int\nmut:\n\tis_registered bool\n}\n\nfn main() {\n\ts := '[{ \"name\":\"Frodo\", \"age\":25}, {\"name\":\"Bobby\", \"age\":10}]'\n\tmut users := json.decode([]User, s) or {\n\t\teprintln('Failed to parse json')\n\t\treturn\n\t}\n\tfor user in users {\n\t\tprintln('${user.name}: ${user.age}')\n\t}\n\tprintln('')\n\tfor i, user in users {\n\t\tprintln('${i}) ${user.name}')\n\t\tif !user.can_register() {\n\t\t\tprintln('Cannot register ${user.name}, they are too young')\n\t\t} else {\n\t\t\tusers[i].register()\n\t\t\tprintln('${user.name} is registered')\n\t\t}\n\t}\n\t// Let's encode users again just for fun\n\tprintln('')\n\tprintln(json.encode(users))\n}\n\nfn (u User) can_register() bool {\n\treturn u.age >= 16\n}\n\nfn (mut u User) register() {\n\tu.is_registered = true\n}\n"
  },
  {
    "path": "examples/jsonrpc/client.v",
    "content": "module main\n\nimport net\nimport net.jsonrpc\n\nfn main() {\n\taddr := '127.0.0.1:42228'\n\tmut stream := net.dial_tcp(addr)!\n\tmut log_inter := jsonrpc.LoggingInterceptor{}\n\tmut inters := jsonrpc.Interceptors{\n\t\tevent:            [log_inter.on_event]\n\t\tencoded_request:  [log_inter.on_encoded_request]\n\t\trequest:          [log_inter.on_request]\n\t\tresponse:         [log_inter.on_response]\n\t\tencoded_response: [log_inter.on_encoded_response]\n\t}\n\n\tmut c := jsonrpc.new_client(jsonrpc.ClientConfig{\n\t\tstream:       stream\n\t\tinterceptors: inters\n\t})\n\n\tprintln('TCP JSON-RPC client on ${addr}')\n\n\td1 := c.request('kv.delete', {\n\t\t'key': 'foo'\n\t}, 'kv.delete')!\n\tprintln('RESULT: ${d1}')\n\n\tres := c.batch([\n\t\tjsonrpc.new_request('kv.create', {\n\t\t\t'key':   'foo'\n\t\t\t'value': 'bar'\n\t\t}, 'kv.create'),\n\t\tjsonrpc.new_request('kv.create', {\n\t\t\t'key':   'bar'\n\t\t\t'value': 'foo'\n\t\t}, 'kv.create'),\n\t])!\n\tprintln('RESULT: ${res}')\n\n\tc.notify('kv.create', {\n\t\t'key':   'bazz'\n\t\t'value': 'barr'\n\t})!\n}\n"
  },
  {
    "path": "examples/jsonrpc/server.v",
    "content": "module main\n\nimport net\nimport sync\nimport net.jsonrpc\nimport log\n\n// ---- CRUD domain ----\nstruct KvItem {\n\tkey   string\n\tvalue string\n}\n\nstruct KvKey {\n\tkey string\n}\n\n// ---- Handler ----\nstruct KvStore {\nmut:\n\tmu    &sync.RwMutex = sync.new_rwmutex()\n\tstore map[string]string\n}\n\nfn (mut s KvStore) create(key string, value string) bool {\n\ts.mu.@lock()\n\tdefer { s.mu.unlock() }\n\tif key in s.store {\n\t\treturn false\n\t}\n\ts.store[key] = value\n\treturn true\n}\n\nfn (mut s KvStore) get(key string) ?string {\n\ts.mu.@rlock()\n\tdefer { s.mu.runlock() }\n\tif value := s.store[key] {\n\t\treturn value\n\t}\n\treturn none\n}\n\nfn (mut s KvStore) update(key string, value string) bool {\n\ts.mu.@lock()\n\tdefer { s.mu.unlock() }\n\tif key in s.store {\n\t\ts.store[key] = value\n\t\treturn true\n\t}\n\treturn false\n}\n\nfn (mut s KvStore) delete(key string) bool {\n\ts.mu.@lock()\n\tdefer { s.mu.unlock() }\n\tif key in s.store {\n\t\ts.store.delete(key)\n\t\treturn true\n\t}\n\treturn false\n}\n\nfn (s KvStore) dump() map[string]string {\n\treturn s.store\n}\n\n@[heap]\nstruct KvHandler {\nmut:\n\tstore KvStore\n}\n\nfn (mut h KvHandler) handle_create(req &jsonrpc.Request, mut wr jsonrpc.ResponseWriter) {\n\tp := req.decode_params[KvItem]() or {\n\t\twr.write_error(jsonrpc.invalid_params)\n\t\treturn\n\t}\n\tif p.key.len == 0 {\n\t\twr.write_error(jsonrpc.invalid_params)\n\t\treturn\n\t}\n\tlog.warn('params=${p}')\n\tif !h.store.create(p.key, p.value) {\n\t\twr.write_error(jsonrpc.ResponseError{ // custom app-level error code\n\t\t\tcode:    -32010\n\t\t\tmessage: 'Key already exists'\n\t\t\tdata:    p.key\n\t\t})\n\t\treturn\n\t}\n\n\twr.write({\n\t\t'ok': true\n\t})\n}\n\nfn (mut h KvHandler) handle_get(req &jsonrpc.Request, mut wr jsonrpc.ResponseWriter) {\n\tp := req.decode_params[KvKey]() or {\n\t\twr.write_error(jsonrpc.invalid_params)\n\t\treturn\n\t}\n\n\tvalue := h.store.get(p.key) or {\n\t\twr.write_error(jsonrpc.ResponseError{\n\t\t\tcode:    -32004\n\t\t\tmessage: 'Not found'\n\t\t\tdata:    p.key\n\t\t})\n\t\treturn\n\t}\n\n\twr.write(KvItem{ key: p.key, value: value })\n}\n\nfn (mut h KvHandler) handle_update(req &jsonrpc.Request, mut wr jsonrpc.ResponseWriter) {\n\tp := req.decode_params[KvItem]() or {\n\t\twr.write_error(jsonrpc.invalid_params)\n\t\treturn\n\t}\n\n\tif !h.store.update(p.key, p.value) {\n\t\twr.write_error(jsonrpc.ResponseError{\n\t\t\tcode:    -32004\n\t\t\tmessage: 'Not found'\n\t\t\tdata:    p.key\n\t\t})\n\t\treturn\n\t}\n\n\twr.write({\n\t\t'ok': true\n\t})\n}\n\nfn (mut h KvHandler) handle_delete(req &jsonrpc.Request, mut wr jsonrpc.ResponseWriter) {\n\tp := req.decode_params[KvKey]() or {\n\t\twr.write_error(jsonrpc.invalid_params)\n\t\treturn\n\t}\n\n\tif !h.store.delete(p.key) {\n\t\twr.write_error(jsonrpc.ResponseError{\n\t\t\tcode:    -32004\n\t\t\tmessage: 'Not found'\n\t\t\tdata:    p.key\n\t\t})\n\t\treturn\n\t}\n\n\twr.write({\n\t\t'ok': true\n\t})\n}\n\nfn (mut h KvHandler) handle_list(_req &jsonrpc.Request, mut wr jsonrpc.ResponseWriter) {\n\tmut items := []KvItem{}\n\tfor k, v in h.store.dump() {\n\t\titems << KvItem{\n\t\t\tkey:   k\n\t\t\tvalue: v\n\t\t}\n\t}\n\titems.sort(a.key < b.key)\n\twr.write(items)\n}\n\n// ---- Per-connection server loop ----\n// The jsonrpc.Server.start() reads from stream and writes to same stream.\nfn handle_conn(mut conn net.TcpConn, h jsonrpc.Handler) {\n\tdefer { conn.close() or {} }\n\n\tmut log_inter := jsonrpc.LoggingInterceptor{}\n\tmut inters := jsonrpc.Interceptors{\n\t\tevent:            [log_inter.on_event]\n\t\tencoded_request:  [log_inter.on_encoded_request]\n\t\trequest:          [log_inter.on_request]\n\t\tresponse:         [log_inter.on_response]\n\t\tencoded_response: [log_inter.on_encoded_response]\n\t}\n\n\tmut srv := jsonrpc.new_server(jsonrpc.ServerConfig{\n\t\tstream:       conn\n\t\thandler:      h\n\t\tinterceptors: inters\n\t})\n\n\tjsonrpc.dispatch_event(inters.event, 'start', 'server started')\n\tsrv.start()\n}\n\nfn main() {\n\tmut s := KvStore{}\n\tmut h := KvHandler{\n\t\tstore: s\n\t}\n\tmut r := jsonrpc.Router{}\n\tr.register('kv.create', h.handle_create)\n\tr.register('kv.get', h.handle_get)\n\tr.register('kv.update', h.handle_update)\n\tr.register('kv.delete', h.handle_delete)\n\tr.register('kv.list', h.handle_list)\n\n\taddr := '127.0.0.1:42228'\n\tmut l := net.listen_tcp(.ip, addr)!\n\tprintln('TCP JSON-RPC server on ${addr} (Content-Length framing)')\n\n\tfor {\n\t\tmut c := l.accept()!\n\t\tprintln('Accepted')\n\t\tgo handle_conn(mut c, r.handle_jsonrpc)\n\t}\n}\n"
  },
  {
    "path": "examples/lander.v",
    "content": "// Example of sum types\n// Models a landing craft leaving orbit and landing on a world\nimport rand\nimport time\n\nstruct Moon {\n}\n\nstruct Mars {\n}\n\nfn (m Mars) dust_storm() bool {\n\treturn rand.int() >= 0\n}\n\nstruct Venus {\n}\n\ntype World = Mars | Moon | Venus\n\nstruct Lander {\n}\n\nfn (l Lander) deorbit() {\n\tprintln('leaving orbit')\n}\n\nfn (l Lander) open_parachutes(n int) {\n\tprintln('opening ${n} parachutes')\n}\n\nfn wait() {\n\tprintln('waiting...')\n\ttime.sleep(1 * time.second)\n}\n\nfn (l Lander) land(w World) {\n\tif w is Mars {\n\t\tfor w.dust_storm() {\n\t\t\twait()\n\t\t}\n\t}\n\tl.deorbit()\n\tmatch w {\n\t\tMoon {} // no atmosphere\n\t\tMars {\n\t\t\t// light atmosphere\n\t\t\tl.open_parachutes(3)\n\t\t}\n\t\tVenus {\n\t\t\t// heavy atmosphere\n\t\t\tl.open_parachutes(1)\n\t\t}\n\t}\n\tprintln('landed')\n}\n\nfn main() {\n\tl := Lander{}\n\tl.land(Venus{})\n\tl.land(Mars{})\n}\n"
  },
  {
    "path": "examples/linear_regression/simple_linear_regression.v",
    "content": "import math\n\nstruct LinearResult {\n\tr2                         f64\n\tintercept                  f64\n\tslope                      f64\n\tdependent_variable_means   f64\n\tindependent_variable_means f64\n}\n\nfn linearrelationship(independent_variable []int, dependent_variable []int) LinearResult {\n\t// Objective :\n\t// Find what is the linear relationship between two dataset X and Y?\n\t// x := independent variable\n\t// y := dependent variable\n\tmut sum_r2_x := 0\n\tmut sum_r2_y := 0\n\tmut sum_xy := 0\n\tmut sum_x := 0\n\tmut sum_y := 0\n\tfor i in independent_variable {\n\t\tsum_x += i\n\t\tsum_r2_x += i * i\n\t}\n\tfor yi in dependent_variable {\n\t\tsum_y += yi\n\t\tsum_r2_y += yi * yi\n\t}\n\tx_means := sum_x / independent_variable.len\n\ty_means := sum_y / dependent_variable.len\n\tfor index, x_value in independent_variable {\n\t\tsum_xy += x_value * dependent_variable[index]\n\t}\n\t// /Slope = (∑y)(∑x²) - (∑x)(∑xy) / n(∑x²) - (∑x)²\n\tslope_value := f64((sum_y * sum_r2_x) - (sum_x * sum_xy)) / f64((sum_r2_x * independent_variable.len) - (sum_x * sum_x))\n\t// /Intercept = n(∑xy) - (∑x)(∑y) / n(∑x²) - (∑x)²\n\tintercept_value := f64((independent_variable.len * sum_xy) - (sum_x * sum_y)) / f64((independent_variable.len * sum_r2_x) - (sum_x * sum_x))\n\t// Regression equation = Intercept + Slope x\n\t// R2 = n(∑xy) - (∑x)(∑y) / sqrt([n(∑x²)-(∑x)²][n(∑y²)-(∑y)²]\n\tr2_value := f64((independent_variable.len * sum_xy) - (sum_x * sum_y)) / math.sqrt(f64((sum_r2_x * independent_variable.len) - (sum_x * sum_x)) * f64((sum_r2_y * dependent_variable.len) - (sum_y * sum_y)))\n\treturn LinearResult{\n\t\tr2:                         r2_value\n\t\tintercept:                  intercept_value\n\t\tslope:                      slope_value\n\t\tindependent_variable_means: x_means\n\t\tdependent_variable_means:   y_means\n\t}\n}\n\nfn main() {\n\tindependent_variable := [4, 5, 6, 7, 10]\n\tdependent_variable := [3, 8, 20, 30, 12]\n\tresult := linearrelationship(independent_variable, dependent_variable)\n\tprintln(result)\n}\n"
  },
  {
    "path": "examples/links_scraper.v",
    "content": "import net.http\n\nfn main() {\n\thtml := http.get_text('https://news.ycombinator.com')\n\tmut pos := 0\n\tfor {\n\t\tpos = html.index_after('https://', pos + 1) or { break }\n\t\tend := html.index_after('\"', pos) or { break }\n\t\tprintln(html[pos..end])\n\t}\n}\n"
  },
  {
    "path": "examples/log.v",
    "content": "import log\n\nfn main() {\n\t// Note: you *do not* need to create a logger instance, and pass it around, just to use the `log` module.\n\t// The log module already creates an instance of a thread safe Logger, and utility functions to work with it:\n\tlog.set_level(.debug)\n\tlog.debug('simple debug message')\n\tlog.warn('simple warning message')\n\tlog.info('simple information message')\n\tlog.error('simple error message')\n\n\tmut l := log.Log{}\n\tl.set_level(.info)\n\t// Make a new file called info.log in the current folder\n\tl.set_full_logpath('./info.log')\n\tl.log_to_console_too()\n\tprintln('Please check the file: ${l.output_file_name} after this example crashes.')\n\n\tl.info('info')\n\tl.warn('warn')\n\tl.error('error')\n\tl.debug('no output for debug')\n\tl.set_level(.debug)\n\tl.debug('debug now')\n\tl.set_level(log.level_from_tag('INFO') or { log.Level.disabled }) // set level from string, sample\n\tl.info('info again')\n\tl.set_level(log.level_from_tag('') or { log.Level.disabled }) // set level from string, sample\n\tl.error('no output anymore')\n\tl.fatal('fatal') // panic, next statements won't be executed\n}\n"
  },
  {
    "path": "examples/logfatal.v",
    "content": "import log\n\n@[noreturn]\nfn should_not_return(mut logger log.Log) {\n\tlogger.fatal('${@FILE_LINE}: yikes!')\n}\n\nfn main() {\n\tmut my_log := log.Log{}\n\tshould_not_return(mut my_log)\n}\n"
  },
  {
    "path": "examples/lorem.v",
    "content": "/*\nRandom Markov Text Generator\n\nThis program generates pseudo-random text using a Markov chain built from\none of several embedded corpora in the strings module. It produces structured output in the\nform of paragraphs and sentences, with configurable parameters.\n\nUsage:\n\n    v run lorem.v [--options]\n    ./lorem [--options]\n\nExample:\n\n    ./lorem -order 2 -words 12 -sentences 4 -paragraphs 3 -corpus poe\n*/\nimport strings.lorem\nimport flag\nimport os\nimport rand\nimport time\n\nfn main() {\n\tmut fp := flag.new_flag_parser(os.args[1..])\n\tfp.application('lorem')\n\tfp.version('1.0')\n\tfp.description('Random text generator using a Markov chain')\n\n\torder := fp.int('order', `o`, 2, 'Markov order [default: 2]')\n\twords_per_sentence := fp.int('words', `w`, 10, 'Words per sentence [default: 10]')\n\tsentences_per_paragraph := fp.int('sentences', `s`, 5, 'Sentences per paragraph [default: 5]')\n\tparagraphs := fp.int('paragraphs', `p`, 3, 'Paragraph count [default: 3]')\n\tcorpus_name := fp.string('corpus', `c`, 'lorem', 'Corpus name (lorem, poe, darwin, bard) [default: lorem]')\n\tseed_text := fp.string('seed', `S`, '', 'Seed phrase (random if omitted)')\n\tmut rng_seed := fp.int('rngseed', `r`, 0, 'RNG seed (0 = random)')\n\n\tfp.finalize() or {\n\t\teprintln(err)\n\t\treturn\n\t}\n\n\tif rng_seed == 0 {\n\t\tt := time.now().unix_milli()\n\t\trand.seed([u32(t), u32(t >> 32)])\n\t\trng_seed = rand.int()\n\t}\n\n\ttext := lorem.generate(\n\t\tmarkov_order:            order\n\t\twords_per_sentence:      words_per_sentence\n\t\tsentences_per_paragraph: sentences_per_paragraph\n\t\tparagraphs:              paragraphs\n\t\tcorpus_name:             corpus_name\n\t\tseed_text:               seed_text\n\t\trng_seed:                rng_seed\n\t)\n\n\tprintln(text)\n}\n"
  },
  {
    "path": "examples/macos_tray/.skip_should_compile_all",
    "content": ""
  },
  {
    "path": "examples/macos_tray/tray.m",
    "content": "// #include <Cocoa/Cocoa.h> // Uncomment for C/C++ intellisense\n\n// See this tutorial to learn about NSApplicationDelegate:\n// https://bumbershootsoft.wordpress.com/2018/11/22/unfiltered-cocoa-completing-the-application/\n\nstatic NSString *nsstring(string s) {\n  return [[NSString alloc] initWithBytesNoCopy:s.str\n                                        length:s.len\n                                      encoding:NSUTF8StringEncoding\n                                  freeWhenDone:NO];\n}\n\n// Manages the app lifecycle.\n@interface AppDelegate : NSObject <NSApplicationDelegate> {\n  NSAutoreleasePool *pool;\n  NSApplication *app;\n  NSStatusItem *statusItem;    // our button\n  main__TrayParams trayParams; // TrayParams is defined in tray.v\n}\n@end\n\n@implementation AppDelegate\n- (AppDelegate *)initWithParams:(main__TrayParams)params {\n  if (self = [super init]) {\n    trayParams = params;\n  }\n  return self;\n}\n\n// Called when NSMenuItem is clicked.\n- (void)onAction:(id)sender {\n  struct main__TrayMenuItem *item =\n      (struct main__TrayMenuItem *)[[sender representedObject] pointerValue];\n  if (item) {\n    trayParams.on_click(*item);\n  }\n}\n\n- (NSMenu *)buildMenu {\n  NSMenu *menu = [NSMenu new];\n  [menu autorelease];\n  [menu setAutoenablesItems:NO];\n\n  main__TrayMenuItem *params_items = trayParams.items.data;\n  for (int i = 0; i < trayParams.items.len; i++) {\n    NSString *title = nsstring(params_items[i].text);\n    NSMenuItem *item = [menu addItemWithTitle:title\n                                       action:@selector(onAction:)\n                                keyEquivalent:@\"\"];\n    NSValue *representedObject = [NSValue valueWithPointer:(params_items + i)];\n    [item setRepresentedObject:representedObject];\n    [item setTarget:self];\n    [item autorelease];\n    [item setEnabled:YES];\n  }\n\n  return menu;\n}\n\n- (void)initTrayMenuItem {\n  NSStatusBar *statusBar = [NSStatusBar systemStatusBar];\n  statusItem = [statusBar statusItemWithLength:NSSquareStatusItemLength];\n  [statusItem retain];\n  [statusItem setVisible:YES];\n  NSStatusBarButton *statusBarButton = [statusItem button];\n\n  // Height must be 22px.\n  NSImage *img = [NSImage imageNamed:@\"icon.png\"];\n  [statusBarButton setImage:img];\n  NSMenu *menu = [self buildMenu];\n  [statusItem setMenu:menu];\n}\n\n- (void)applicationWillFinishLaunching:(NSNotification *)notification {\n  NSLog(@\"applicationWillFinishLaunching called\");\n}\n\n- (void)applicationWillTerminate:(NSNotification *)notif;\n{ NSLog(@\"applicationWillTerminate called\"); }\n\n- (NSApplicationTerminateReply)applicationShouldTerminate:\n    (NSApplication *)sender {\n  NSLog(@\"applicationShouldTerminate called\");\n  return NSTerminateNow;\n}\n@end\n\n// Initializes NSApplication and NSStatusItem, aka system tray menu item.\nmain__TrayInfo *tray_app_init(main__TrayParams params) {\n  NSApplication *app = [NSApplication sharedApplication];\n  AppDelegate *appDelegate = [[AppDelegate alloc] initWithParams:params];\n\n  // Hide icon from the doc.\n  [app setActivationPolicy:NSApplicationActivationPolicyProhibited];\n  [app setDelegate:appDelegate];\n\n  [appDelegate initTrayMenuItem];\n\n  main__TrayInfo *tray_info = malloc(sizeof(main__TrayInfo));\n  tray_info->app = app;\n  tray_info->app_delegate = appDelegate;\n  return tray_info;\n}\n\n// Blocks and runs the application.\nvoid tray_app_run(main__TrayInfo *tray_info) {\n  NSApplication *app = (NSApplication *)(tray_info->app);\n  [app run];\n}\n\n// Processes a single NSEvent while blocking the thread\n// until there is an event.\nvoid tray_app_loop(main__TrayInfo *tray_info) {\n  NSDate *until = [NSDate distantFuture];\n\n  NSApplication *app = (NSApplication *)(tray_info->app);\n  NSEvent *event = [app nextEventMatchingMask:ULONG_MAX\n                                    untilDate:until\n                                       inMode:@\"kCFRunLoopDefaultMode\"\n                                      dequeue:YES];\n\n  if (event) {\n    [app sendEvent:event];\n  }\n}\n\n// Terminates the app.\nvoid tray_app_exit(main__TrayInfo *tray_info) {\n  NSApplication *app = (NSApplication *)(tray_info->app);\n  [app terminate:app];\n}\n"
  },
  {
    "path": "examples/macos_tray/tray.v",
    "content": "// vtest build: macos\n// Simple windows-less application that shows a icon button on Mac OS tray.\n// Tested on Mac OS Monterey (12.3).\n\nmodule main\n\n#include <Cocoa/Cocoa.h>\n#flag -framework Cocoa\n\n#include \"@VMODROOT/tray.m\"\n\nfn C.tray_app_init(TrayParams) &TrayInfo\nfn C.tray_app_loop(&TrayInfo)\nfn C.tray_app_run(&TrayInfo)\nfn C.tray_app_exit(&TrayInfo)\n\nstruct TrayMenuItem {\n\tid   string @[required] // Unique ID.\n\ttext string @[required] // Text to display.\n}\n\n// Parameters to configure the tray button.\nstruct TrayParams {\n\titems    []TrayMenuItem         @[required]\n\ton_click fn (item TrayMenuItem) @[required]\n}\n\n// Internal Cocoa application state.\nstruct TrayInfo {\n\tapp          voidptr // pointer to NSApplication\n\tapp_delegate voidptr // pointer to AppDelegate\n}\n\n@[heap]\nstruct MyApp {\nmut:\n\ttray_info &TrayInfo = unsafe { nil }\n}\n\nfn (app &MyApp) on_menu_item_click(item TrayMenuItem) {\n\tprintln('click ${item.id}')\n\tif item.id == 'quit' {\n\t\tC.tray_app_exit(app.tray_info)\n\t}\n}\n\nfn main() {\n\tmut my_app := &MyApp{\n\t\ttray_info: unsafe { nil }\n\t}\n\n\tmy_app.tray_info = C.tray_app_init(TrayParams{\n\t\titems:    [TrayMenuItem{\n\t\t\tid:   'hello'\n\t\t\ttext: 'Hello'\n\t\t}, TrayMenuItem{\n\t\t\tid:   'quit'\n\t\t\ttext: 'Quit!'\n\t\t}]\n\t\ton_click: my_app.on_menu_item_click\n\t})\n\n\t//// Use this:\n\t// for {\n\t// \tC.tray_app_loop(my_app.tray_info)\n\t//  \t// println(\"loop\")\n\t// }\n\n\t//// Or this:\n\tC.tray_app_run(my_app.tray_info)\n}\n"
  },
  {
    "path": "examples/macos_tray/v.mod",
    "content": ""
  },
  {
    "path": "examples/mini_calculator.v",
    "content": "// Q: What's this?\n// A: This is a mini \"home-made\" calculator. You may also regard it as a very elementary version of \"interpreter\".\nimport os\n\nconst numeric_char = [`0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `.`, `e`, `E`]\n\n// Convert expression to Reverse Polish Notation.\nfn expr_to_rev_pol(expr string) ![]string {\n\tif expr == '' {\n\t\treturn error('err: empty expression')\n\t}\n\tmut stack := []string{}\n\tmut rev_pol := []string{}\n\tmut pos := 0\n\tfor pos < expr.len {\n\t\tmut end_pos := pos\n\t\tfor end_pos < expr.len && expr[end_pos] in numeric_char {\n\t\t\tend_pos++\n\t\t}\n\t\tif end_pos > pos {\n\t\t\tstack << expr[pos..end_pos]\n\t\t\tpos = end_pos\n\t\t} else if end_pos == pos {\n\t\t\top := expr[pos].ascii_str()\n\t\t\tmatch op {\n\t\t\t\t'(' {\n\t\t\t\t\tstack << op\n\t\t\t\t}\n\t\t\t\t'*', '/' {\n\t\t\t\t\tfor stack.len > 0 && stack.last() !in ['(', '+', '-'] {\n\t\t\t\t\t\trev_pol << stack.last()\n\t\t\t\t\t\tstack.delete(stack.len - 1)\n\t\t\t\t\t}\n\t\t\t\t\tstack << op\n\t\t\t\t}\n\t\t\t\t'+', '-' {\n\t\t\t\t\tfor stack.len > 0 && stack.last() != '(' {\n\t\t\t\t\t\trev_pol << stack.last()\n\t\t\t\t\t\tstack.delete(stack.len - 1)\n\t\t\t\t\t}\n\t\t\t\t\tstack << op\n\t\t\t\t}\n\t\t\t\t')' {\n\t\t\t\t\tfor stack.len > 0 && stack.last() != '(' {\n\t\t\t\t\t\trev_pol << stack.last()\n\t\t\t\t\t\tstack.delete(stack.len - 1)\n\t\t\t\t\t}\n\t\t\t\t\tstack.delete(stack.len - 1)\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\treturn error('err: invalid character `${op}`')\n\t\t\t\t}\n\t\t\t}\n\t\t\tpos++\n\t\t}\n\t}\n\tfor stack.len > 0 {\n\t\ttop := stack.last()\n\t\trev_pol << top\n\t\tstack.delete(stack.len - 1)\n\t}\n\treturn rev_pol\n}\n\n// Evaluate the result of Reverse Polish Notation.\nfn eval_rev_pol(rev_pol []string) !f64 {\n\tmut stack := []f64{}\n\tfor item in rev_pol {\n\t\tif is_num_string(item) {\n\t\t\tstack << item.f64()\n\t\t} else {\n\t\t\tif stack.len >= 2 {\n\t\t\t\toprand_r := stack.last()\n\t\t\t\tstack.delete(stack.len - 1)\n\t\t\t\toprand_l := stack.last()\n\t\t\t\tstack.delete(stack.len - 1)\n\t\t\t\tmatch item {\n\t\t\t\t\t'+' {\n\t\t\t\t\t\tstack << oprand_l + oprand_r\n\t\t\t\t\t}\n\t\t\t\t\t'-' {\n\t\t\t\t\t\tstack << oprand_l - oprand_r\n\t\t\t\t\t}\n\t\t\t\t\t'*' {\n\t\t\t\t\t\tstack << oprand_l * oprand_r\n\t\t\t\t\t}\n\t\t\t\t\t'/' {\n\t\t\t\t\t\tif oprand_r == 0 {\n\t\t\t\t\t\t\treturn error('err: divide by zero')\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstack << oprand_l / oprand_r\n\t\t\t\t\t}\n\t\t\t\t\telse {}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn error('err: invalid expression')\n\t\t\t}\n\t\t}\n\t}\n\treturn stack[0]\n}\n\nfn is_num_string(str string) bool {\n\tfor c in str {\n\t\tif c !in numeric_char {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfn main() {\n\tprintln('Please enter the expression you want to calculate, e.g. 1e2+(3-2.5)*6/1.5 .')\n\tprintln(\"Enter 'exit' or 'EXIT' to quit.\")\n\tmut expr_count := 0\n\tfor {\n\t\texpr_count++\n\t\texpr := os.input_opt('[${expr_count}] ') or {\n\t\t\tprintln('')\n\t\t\tbreak\n\t\t}.trim_space()\n\t\tif expr in ['exit', 'EXIT'] {\n\t\t\tbreak\n\t\t}\n\t\trev_pol := expr_to_rev_pol(expr) or {\n\t\t\teprintln(err)\n\t\t\tcontinue\n\t\t}\n\t\tres := eval_rev_pol(rev_pol) or {\n\t\t\teprintln(err)\n\t\t\tcontinue\n\t\t}\n\t\tprintln(res)\n\t}\n}\n"
  },
  {
    "path": "examples/mini_calculator_recursive_descent.v",
    "content": "// Q: What's this?\n// A: A simple arithmetic calculator, similar to examples/mini_calculator.v,\n// but *without* an explicit stack. Instead, it re-uses the one from the host language.\n// It also demonstrates how to use textscanner.TextScanner from the V standart library.\n// See https://modules.vlang.io/strings.textscanner.html ,\n// and also https://en.wikipedia.org/wiki/Recursive_descent_parser .\nmodule main\n\nimport os\nimport strconv\nimport strings.textscanner\n\nstruct Parser {\n\ttextscanner.TextScanner\n}\n\nfn (mut p Parser) expr() !f64 {\n\tmut result := p.term()!\n\tfor {\n\t\tp.skip_whitespace()\n\t\tc := p.peek_u8()\n\t\tif c == `+` {\n\t\t\tp.next()\n\t\t\tresult += p.term()!\n\t\t} else if c == `-` {\n\t\t\tp.next()\n\t\t\tresult -= p.term()!\n\t\t} else {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn result\n}\n\nfn (mut p Parser) term() !f64 {\n\tmut result := p.factor()!\n\tfor {\n\t\tp.skip_whitespace()\n\t\tc := p.peek_u8()\n\t\tif c == `*` {\n\t\t\tp.next()\n\t\t\tresult *= p.factor()!\n\t\t} else if c == `/` {\n\t\t\tp.next()\n\t\t\tresult /= p.factor()!\n\t\t} else {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn result\n}\n\nfn (mut p Parser) factor() !f64 {\n\tp.skip_whitespace()\n\tc := p.peek_u8()\n\tif c.is_digit() {\n\t\treturn p.number()\n\t} else if c == `(` {\n\t\tp.next()\n\t\tresult := p.expr()!\n\t\tp.skip_whitespace()\n\t\tif p.next() != `)` {\n\t\t\treturn error('Expected closing parenthesis')\n\t\t}\n\t\treturn result\n\t}\n\treturn error('Expected number or opening parenthesis')\n}\n\nfn (mut p Parser) number() !f64 {\n\tstart := p.pos\n\tfor {\n\t\tc := p.peek_u8()\n\t\tif c.is_digit() || c == `.` || c == `e` || c == `E` {\n\t\t\tp.next()\n\t\t\tcontinue\n\t\t}\n\t\tbreak\n\t}\n\treturn strconv.atof64(p.input[start..p.pos]) or { error('Invalid number') }\n}\n\nprintln('Enter expressions to calculate, e.g. `2 * (5-1)` or `exit` to quit.')\nfor i := 1; true; i++ {\n\tinput := os.input_opt('[${i}] ') or {\n\t\tprintln('')\n\t\tbreak\n\t}.trim_space()\n\tif input.to_upper() == 'EXIT' {\n\t\tbreak\n\t}\n\tmut parser := Parser{textscanner.new(input)}\n\tresult := parser.expr() or {\n\t\tprintln('Error: ${err}')\n\t\tcontinue\n\t}\n\tprintln(result)\n}\n"
  },
  {
    "path": "examples/minimal_c_like_program_using_puts.v",
    "content": "// vtest build: !(windows && gcc) // it declares its own `main` function, but on windows && gcc, it needs to be `wWinMain`\nmodule no_main\n\n// Compile with:\n// v -cc clang -prod -gc none -cflags '-s -fuse-ld=mold' -o hw examples/minimal_c_like_program_using_puts.v && ll hw && sstrip -z hw && ll hw\n// With clang-10, on Ubuntu 20.04, it produces an executable with a size of 2331 bytes, after stripping.\n// Note: the above uses sstrip 2.1 (from https://git.sr.ht/~breadbox/ELFkickers) and mold 2.32.0 (from https://github.com/rui314/mold).\n\nfn C.puts(const_msg &char) i32\n\n@[export: 'main']\nfn hello() int {\n\tC.puts(c'Hello world')\n\treturn 0\n}\n"
  },
  {
    "path": "examples/native/hello_world.v",
    "content": "fn test_fn() {\n\tprintln('test fn')\n}\n\nfn main() {\n\tprintln('native test')\n\tmut i := 0\n\tfor i < 5 {\n\t\tprintln('Hello world from V native machine code generator, in a while style for loop!')\n\t\ti++\n\t}\n\tfor _ in 1 .. 5 {\n\t\tprintln('Hello world from V native machine code generator, in a range loop!')\n\t}\n\tprintln('Hello again!')\n\ttest_fn()\n\tprintln('done')\n}\n"
  },
  {
    "path": "examples/nbody.v",
    "content": "// Ported based on https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/nbody-go-3.html\n// Output:\n// -0.169075164\n// -0.169059907\nimport math\n\nconst solar_mass = 39.47841760435743197 // 4.0 * math.Pi * math.Pi\n\nconst days_per_year = 365.24\nconst c_n = 5\n\nstruct Position {\npub mut:\n\tx f64\n\ty f64\n\tz f64\n}\n\nstruct Momentum {\npub mut:\n\tx f64\n\ty f64\n\tz f64\n\tm f64\n}\n\nstruct System {\npub mut:\n\tv []Momentum\n\ts []Position\n}\n\nfn advance(mut sys System, dt f64) {\n\tfor i in 0 .. c_n - 1 {\n\t\tmut vx := sys.v[i].x\n\t\tmut vy := sys.v[i].y\n\t\tmut vz := sys.v[i].z\n\n\t\tfor j := i + 1; j < c_n; j++ {\n\t\t\tdx := sys.s[i].x - sys.s[j].x\n\t\t\tdy := sys.s[i].y - sys.s[j].y\n\t\t\tdz := sys.s[i].z - sys.s[j].z\n\n\t\t\tdsquared := dx * dx + dy * dy + dz * dz\n\t\t\tdistance := math.sqrt(dsquared)\n\t\t\tmag := (dt / (dsquared * distance))\n\t\t\tmi := sys.v[i].m\n\n\t\t\tvx -= dx * sys.v[j].m * mag\n\t\t\tvy -= dy * sys.v[j].m * mag\n\t\t\tvz -= dz * sys.v[j].m * mag\n\n\t\t\tsys.v[j].x += dx * mi * mag\n\t\t\tsys.v[j].y += dy * mi * mag\n\t\t\tsys.v[j].z += dz * mi * mag\n\t\t}\n\t\tsys.v[i].x = vx\n\t\tsys.v[i].y = vy\n\t\tsys.v[i].z = vz\n\t}\n\n\tfor i in 0 .. c_n {\n\t\tsys.s[i].x += dt * sys.v[i].x\n\t\tsys.s[i].y += dt * sys.v[i].y\n\t\tsys.s[i].z += dt * sys.v[i].z\n\t}\n}\n\nfn offsetmomentum(mut sys System) {\n\tmut px := f64(0)\n\tmut py := f64(0)\n\tmut pz := f64(0)\n\n\tfor i in 0 .. c_n {\n\t\tpx += sys.v[i].x * sys.v[i].m\n\t\tpy += sys.v[i].y * sys.v[i].m\n\t\tpz += sys.v[i].z * sys.v[i].m\n\t}\n\tsys.v[0].x = -px / solar_mass\n\tsys.v[0].y = -py / solar_mass\n\tsys.v[0].z = -pz / solar_mass\n}\n\nfn energy(sys System) f64 {\n\tmut e := f64(0)\n\tfor i in 0 .. c_n {\n\t\te += 0.5 * sys.v[i].m * (sys.v[i].x * sys.v[i].x + sys.v[i].y * sys.v[i].y +\n\t\t\tsys.v[i].z * sys.v[i].z)\n\t\tfor j := i + 1; j < c_n; j++ {\n\t\t\tdx := sys.s[i].x - sys.s[j].x\n\t\t\tdy := sys.s[i].y - sys.s[j].y\n\t\t\tdz := sys.s[i].z - sys.s[j].z\n\t\t\tdistance := math.sqrt(dx * dx + dy * dy + dz * dz)\n\t\t\te -= (sys.v[i].m * sys.v[j].m) / distance\n\t\t}\n\t}\n\treturn e\n}\n\nfn arr_momentum() []Momentum {\n\treturn [\n\t\tMomentum{0.0, 0.0, 0.0, solar_mass},\n\t\tMomentum{1.66007664274403694e-03 * days_per_year, 7.69901118419740425e-03 * days_per_year, -6.90460016972063023e-05 * days_per_year, 9.54791938424326609e-04 * solar_mass},\n\t\tMomentum{-2.76742510726862411e-03 * days_per_year, 4.99852801234917238e-03 * days_per_year, 2.30417297573763929e-05 * days_per_year, 2.85885980666130812e-04 * solar_mass},\n\t\tMomentum{2.96460137564761618e-03 * days_per_year, 2.37847173959480950e-03 * days_per_year, -2.96589568540237556e-05 * days_per_year, 4.36624404335156298e-05 * solar_mass},\n\t\tMomentum{2.68067772490389322e-03 * days_per_year, 1.62824170038242295e-03 * days_per_year, -9.51592254519715870e-05 * days_per_year, 5.15138902046611451e-05 * solar_mass},\n\t]\n}\n\nfn arr_position() []Position {\n\treturn [\n\t\tPosition{0.0, 0.0, 0.0},\n\t\tPosition{4.84143144246472090e+00, -1.16032004402742839e+00, -1.03622044471123109e-01},\n\t\tPosition{8.34336671824457987e+00, 4.12479856412430479e+00, -4.03523417114321381e-01},\n\t\tPosition{1.28943695621391310e+01, -1.51111514016986312e+01, -2.23307578892655734e-01},\n\t\tPosition{1.53796971148509165e+01, -2.59193146099879641e+01, 1.79258772950371181e-01},\n\t]\n}\n\nfn main() {\n\tmut sys := &System{arr_momentum(), arr_position()}\n\toffsetmomentum(mut sys)\n\tprintln('${energy(sys):.9f}') //-0.169075164\n\tfor _ in 0 .. 50_000_000 {\n\t\tadvance(mut sys, 0.01)\n\t}\n\tprintln('${energy(sys):.9f}') //-0.169059907\n}\n"
  },
  {
    "path": "examples/net_failconnect.v",
    "content": "import net\n\nconn := net.dial_tcp('[::1]:57000')!\npeer_addr := conn.peer_addr()!\nprintln('${peer_addr}')\n"
  },
  {
    "path": "examples/net_peer_ip.v",
    "content": "import net\n\nconn := net.dial_tcp('google.com:80')!\npeer_addr := conn.peer_addr()!\nprintln('${peer_addr}')\n"
  },
  {
    "path": "examples/net_raw_http.v",
    "content": "import net\nimport io\n\nfn main() {\n\t// Make a new connection\n\tmut conn := net.dial_tcp('google.com:80')!\n\tdefer {\n\t\tconn.close() or {}\n\t}\n\n\tprintln(' peer: ${conn.peer_addr()!}')\n\tprintln('local: ${conn.addr()!}')\n\n\t// Simple http HEAD request for a file\n\tconn.write_string('HEAD /index.html HTTP/1.0\\r\\n\\r\\n')!\n\t// Read all the data that is waiting\n\tresult := io.read_all(reader: conn)!\n\t// Cast to string and print result\n\tprintln(result.bytestr())\n}\n"
  },
  {
    "path": "examples/net_resolve.v",
    "content": "import net\n\nfor addr in [\n\t'vlang.io:80',\n\t'google.com:80',\n\t'steampowered.com:80',\n\t'api.steampowered.com:80',\n] {\n\tprintln('${addr}')\n\n\tfor type in [net.SocketType.tcp, .udp] {\n\t\tfamily := net.AddrFamily.unspec\n\n\t\taddrs := net.resolve_addrs(addr, family, type) or {\n\t\t\tprintln('> None')\n\t\t\tcontinue\n\t\t}\n\n\t\tfor a in addrs {\n\t\t\tf := a.family()\n\t\t\tprintln('> ${a} ${f} ${type}')\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/net_t.v",
    "content": "import net.http\nimport sync\nimport time\n\nfn send_request(mut wg sync.WaitGroup) !string {\n\tstart := time.ticks()\n\tdata := http.get('https://google.com')!\n\tfinish := time.ticks()\n\tprintln('Finish getting time ${finish - start} ms')\n\twg.done()\n\treturn data.body\n}\n\nfn main() {\n\tmut wg := sync.new_waitgroup()\n\tfor i := 0; i < 50; i++ {\n\t\twg.add(1)\n\t\tspawn send_request(mut wg)\n\t}\n\twg.wait()\n}\n"
  },
  {
    "path": "examples/net_udp_server_and_client.v",
    "content": "import os\nimport os.cmdline\nimport net\n\nfn main() {\n\tprintln('Usage: net_udp_server_and_client [-l] [-p 5000]')\n\tprintln('     -l      - act as a server and listen')\n\tprintln('     -p XXXX - custom port number')\n\tprintln('------------------------------------------')\n\tis_server := '-l' in os.args\n\tport := cmdline.option(os.args, '-p', '40001').int()\n\tmut buf := []u8{len: 100}\n\tif is_server {\n\t\tprintln('UDP echo server, listening for udp packets on port: ${port}')\n\t\tmut c := net.listen_udp('0.0.0.0:${port}')!\n\t\tfor {\n\t\t\tread, addr := c.read(mut buf) or { continue }\n\t\t\tprintln('received ${read} bytes from ${addr}')\n\t\t\tc.write_to(addr, buf[..read]) or {\n\t\t\t\tprintln('Server: connection dropped')\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t} else {\n\t\tprintln('UDP client, sending packets to port: ${port}.\\nType `exit` to exit.')\n\t\tmut c := net.dial_udp('127.0.0.1:${port}')!\n\t\tfor {\n\t\t\tmut line := os.input('client > ')\n\t\t\tmatch line {\n\t\t\t\t'' {\n\t\t\t\t\tline = '\\n'\n\t\t\t\t}\n\t\t\t\t'exit' {\n\t\t\t\t\tprintln('goodbye.')\n\t\t\t\t\texit(0)\n\t\t\t\t}\n\t\t\t\telse {}\n\t\t\t}\n\t\t\tc.write_string(line)!\n\t\t\tread, _ := c.read(mut buf)!\n\t\t\tprintln('server : ' + buf[0..read].bytestr())\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/news_fetcher.v",
    "content": "// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nimport net.http\nimport x.json2\nimport sync.pool\n\nstruct Story {\n\ttitle string\n\turl   string\n}\n\nfn worker_fetch(mut p pool.PoolProcessor, cursor int, _worker_id int) voidptr {\n\tid := p.get_item[int](cursor)\n\tresp := http.get('https://hacker-news.firebaseio.com/v0/item/${id}.json') or {\n\t\tprintln('failed to fetch data from /v0/item/${id}.json')\n\t\treturn pool.no_result\n\t}\n\tstory := json2.decode[Story](resp.body) or {\n\t\tprintln('failed to decode a story')\n\t\treturn pool.no_result\n\t}\n\tprintln('# ${cursor + 1}) ${story.title} | ${story.url}')\n\treturn pool.no_result\n}\n\n// Fetches top HN stories in parallel, depending on how many cores you have\nfn main() {\n\tresp := http.get('https://hacker-news.firebaseio.com/v0/topstories.json') or {\n\t\tprintln('failed to fetch data from /v0/topstories.json')\n\t\treturn\n\t}\n\n\tids := json2.decode[[]int](resp.body) or {\n\t\tprintln('failed to decode topstories.json ${err}')\n\t\treturn\n\t}#[0..30]\n\n\tmut fetcher_pool := pool.new_pool_processor(\n\t\tcallback: worker_fetch\n\t)\n\t// Note: if you do not call set_max_jobs, the pool will try to use an optimal\n\t// number of threads, one per each core in your system, which in most\n\t// cases is what you want anyway... You can override the automatic choice\n\t// by setting the VJOBS environment variable too.\n\t// fetcher_pool.set_max_jobs( 4 )\n\tfetcher_pool.work_on_items(ids)\n}\n"
  },
  {
    "path": "examples/orm/orm_func.v",
    "content": "module main\n\nimport db.sqlite\nimport time\nimport orm\n\n@[table: 'sys_users']\nstruct User {\npub:\n\tid         string     @[immutable; primary; sql: 'id'; sql_type: 'VARCHAR(255)'; unique]\n\tname       ?string    @[immutable; sql: 'nick_name'; sql_type: 'VARCHAR(255)'; unique]\n\tcreated_at ?time.Time @[omitempty; sql_type: 'TIMESTAMP']\n\tupdated_at time.Time  @[default: new; omitempty; sql_type: 'TIMESTAMP']\n}\n\nfn main() {\n\tmut db := sqlite.connect(':memory:')!\n\tdefer { db.close() or {} }\n\n\tuser1 := User{\n\t\tid:         '001'\n\t\tname:       'Jengro'\n\t\tcreated_at: time.now()\n\t\tupdated_at: time.now()\n\t}\n\n\tuser2 := User{\n\t\tid:         '002'\n\t\tname:       'Dev'\n\t\tcreated_at: time.now()\n\t\tupdated_at: time.now()\n\t}\n\n\tmut qb := orm.new_query[User](db)\n\n\t// create table\n\tqb.create()!\n\n\t// insert into table\n\tqb.insert(user1)!\n\tqb.insert(user2)!\n\n\t// query all fields\n\tall_users := qb.query()!\n\tdump(all_users)\n\n\t// query all users' nick_name\n\tall_user_names := qb.select('nick_name')!.query()!\n\tdump(all_user_names)\n\n\t// where\n\tselected_users := qb.where('id = ?', '001')!.query()!\n\tdump(selected_users)\n\n\t// update\n\tqb.set('nick_name = ?', 'Tom')!.where('id = ?', '001')!.update()!\n\tupdated_user := qb.query()!\n\tdump(updated_user)\n\n\t// delete\n\tqb.where('id = ?', '001')!.delete()!\n\tremain_users := qb.query()!\n\tdump(remain_users)\n\n\t// drop table\n\tqb.drop()!\n}\n"
  },
  {
    "path": "examples/orm/orm_sql.v",
    "content": "module main\n\nimport db.sqlite\nimport time\n\n@[table: 'sys_users']\nstruct User {\npub:\n\tid         string     @[immutable; primary; sql: 'id'; sql_type: 'VARCHAR(255)'; unique]\n\tname       ?string    @[immutable; sql: 'name'; sql_type: 'VARCHAR(255)'; unique]\n\tcreated_at ?time.Time @[omitempty; sql_type: 'TIMESTAMP']\n\tupdated_at time.Time  @[default: new; omitempty; sql_type: 'TIMESTAMP']\n}\n\nfn main() {\n\tmut db := sqlite.connect(':memory:')!\n\tdefer { db.close() or {} }\n\n\tuser1 := User{\n\t\tid:         '001'\n\t\tname:       'Jengro'\n\t\tcreated_at: time.now()\n\t\tupdated_at: time.now()\n\t}\n\n\tuser2 := User{\n\t\tid:         '002'\n\t\tname:       'Dev'\n\t\tcreated_at: time.now()\n\t\tupdated_at: time.now()\n\t}\n\n\t// create table\n\tsql db {\n\t\tcreate table User\n\t}!\n\n\t// insert into table\n\tsql db {\n\t\tinsert user1 into User\n\t\tinsert user2 into User\n\t}!\n\n\t// query all fields\n\tall_users := sql db {\n\t\tselect from User\n\t}!\n\tdump(all_users)\n\n\t// where\n\tselected_users := sql db {\n\t\tselect from User where id == '001'\n\t}!\n\tdump(selected_users)\n\n\t// update\n\tsql db {\n\t\tupdate User set name = 'Tom' where id == '001'\n\t}!\n\tupdated_user := sql db {\n\t\tselect from User\n\t}!\n\tdump(updated_user)\n\n\t// delete\n\tsql db {\n\t\tdelete from User where id == '001'\n\t}!\n\tremain_users := sql db {\n\t\tselect from User\n\t}!\n\tdump(remain_users)\n\n\t// drop table\n\tsql db {\n\t\tdrop table User\n\t}!\n}\n"
  },
  {
    "path": "examples/password/password.v",
    "content": "module main\n\nimport os\n\nfn main() {\n\toriginal_password := os.input_password('Enter your password : ')!\n\trepeated_password := os.input_password('Confirm password : ')!\n\n\tif original_password == repeated_password {\n\t\tprintln('Password confirmed! You entered: ${original_password} .')\n\t} else {\n\t\tprintln('Passwords do not match .')\n\t}\n}\n"
  },
  {
    "path": "examples/password/password_test.v",
    "content": "import os\n\n// Expect has to be installed for the test.\nconst expect_exe = os.find_abs_path_of_executable('expect') or {\n\teprintln('skipping test, since expect is missing')\n\texit(0)\n}\n// Directory that contains the Expect scripts used in the test.\nconst expect_tests_path = os.join_path(@VMODROOT, 'examples', 'password', 'tests')\n\nfn test_password_input() {\n\tcorrect := os.execute(os.join_path(expect_tests_path, 'correct.expect'))\n\tassert correct.exit_code == 0, correct.output\n\n\tincorrect := os.execute(os.join_path(expect_tests_path, 'incorrect.expect'))\n\tassert incorrect.exit_code == 0, incorrect.output\n\n\texpected_out := 'Enter your password : '\n\tmut res := os.execute('${os.join_path(expect_tests_path, 'output_from_expect_arg.expect')} \"${expected_out}\"')\n\tassert res.exit_code == 0, res.output\n\n\tnot_exptectd_out := 'Enter your passwords : '\n\tres = os.execute('${os.join_path(expect_tests_path, 'output_from_expect_arg.expect')} \"${not_exptectd_out}\"')\n\tassert res.exit_code == 1, res.output\n}\n"
  },
  {
    "path": "examples/password/tests/correct.expect",
    "content": "#!/usr/bin/env expect\n\nset timeout 3\nset v_root [exec sh -c \"git rev-parse --show-toplevel\"]\n\nspawn $v_root/v run $v_root/examples/password/password.v\n\nexpect \"Enter your password : \" { send \"Sample\\r\" } timeout { exit 1 }\nexpect \"Confirm password : \" { send \"Sample\\r\" } timeout { exit 1 }\nexpect \"Password confirmed! You entered: Sample .\" {}  timeout { exit 1 }\n\nexpect eof\n"
  },
  {
    "path": "examples/password/tests/incorrect.expect",
    "content": "#!/usr/bin/env expect\n\nset timeout 3\nset v_root [exec sh -c \"git rev-parse --show-toplevel\"]\n\nspawn $v_root/v run $v_root/examples/password/password.v\n\nexpect \"Enter your password : \" { send \"Sample123\\r\" } timeout { exit 1 }\nexpect \"Confirm password : \" { send \"Sample234\\r\" } timeout { exit 1 }\nexpect \"Passwords do not match .\" {} timeout { exit 1 }\n\nexpect eof\n"
  },
  {
    "path": "examples/password/tests/output_from_expect_arg.expect",
    "content": "#!/usr/bin/env expect\n\nset timeout 3\nset v_root [exec sh -c \"git rev-parse --show-toplevel\"]\n# Send expected output as arg to re-use the script for testing incorrect values.\nset expect_ [lindex $argv 0]\n\nspawn $v_root/v run $v_root/examples/password/password.v\n\nexpect $expect_ {} timeout {  exit 1 }\n\nexpect eof\n"
  },
  {
    "path": "examples/path_tracing.v",
    "content": "/**********************************************************************\n* path tracing demo\n*\n* Copyright (c) 2019-2024 Dario Deledda. All rights reserved.\n* Use of this source code is governed by an MIT license\n* that can be found in the LICENSE file.\n*\n* This file contains a path tracer example in less of 500 line of codes\n* 3 demo scenes included\n*\n* This code is inspired by:\n* - \"Realistic Ray Tracing\" by Peter Shirley 2000 ISBN-13: 978-1568814612\n* - https://www.kevinbeason.com/smallpt/\n*\n* Known limitations:\n* - there are some approximation errors in the calculations\n* - to speed-up the code a cos/sin table is used\n* - the full precision code is present but commented, can be restored very easily\n* - an higher number of samples ( > 60) can block the program on higher resolutions\n*   without a stack size increase\n* - as a recursive program this code depend on the stack size,\n*   for higher number of samples increase the stack size\n*   in linux: ulimit -s byte_size_of_the_stack\n*   example: ulimit -s 16000000\n* - No OpenMP support\n**********************************************************************/\nimport os\nimport math\nimport rand\nimport time\nimport term\nimport math.vec\n\nconst inf = 1e+10\nconst eps = 1e-4\nconst f_0 = 0.0\n\ntype Vec = vec.Vec3[f64]\n\n@[inline]\nfn (v Vec) norm() Vec {\n\ttmp_norm := 1.0 / math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z)\n\treturn Vec{v.x * tmp_norm, v.y * tmp_norm, v.z * tmp_norm}\n}\n\n//********************************Image**************************************\nstruct Image {\n\twidth  int\n\theight int\n\tdata   &Vec = unsafe { nil }\n}\n\nfn new_image(w int, h int) Image {\n\tvecsize := int(sizeof(Vec))\n\treturn Image{\n\t\twidth:  w\n\t\theight: h\n\t\tdata:   unsafe { &Vec(vcalloc(vecsize * w * h)) }\n\t}\n}\n\n// write out a .ppm file\nfn (image Image) save_as_ppm(file_name string) {\n\tnpixels := image.width * image.height\n\tmut f_out := os.create(file_name) or { panic(err) }\n\tf_out.writeln('P3') or { panic(err) }\n\tf_out.writeln('${image.width} ${image.height}') or { panic(err) }\n\tf_out.writeln('255') or { panic(err) }\n\tfor i in 0 .. npixels {\n\t\tc_r := to_int(unsafe { image.data[i] }.x)\n\t\tc_g := to_int(unsafe { image.data[i] }.y)\n\t\tc_b := to_int(unsafe { image.data[i] }.z)\n\t\tf_out.write_string('${c_r} ${c_g} ${c_b} ') or { panic(err) }\n\t}\n\tf_out.close()\n}\n\n//********************************** Ray ************************************\nstruct Ray {\n\to Vec\n\td Vec\n}\n\n// material types, used in radiance()\nenum Refl_t {\n\tdiff\n\tspec\n\trefr\n}\n\n//******************************** Sphere ***********************************\nstruct Sphere {\n\trad  f64 = 0.0 // radius\n\tp    Vec    // position\n\te    Vec    // emission\n\tc    Vec    // color\n\trefl Refl_t // reflection type => [diffuse, specular, refractive]\n}\n\nfn (sp Sphere) intersect(r Ray) f64 {\n\top := sp.p - r.o // Solve t^2*d.d + 2*t*(o-p).d + (o-p).(o-p)-R^2 = 0\n\tb := op.dot(r.d)\n\tmut det := b * b - op.dot(op) + sp.rad * sp.rad\n\n\tif det < 0 {\n\t\treturn 0\n\t}\n\n\tdet = math.sqrt(det)\n\n\tmut t := b - det\n\tif t > eps {\n\t\treturn t\n\t}\n\n\tt = b + det\n\tif t > eps {\n\t\treturn t\n\t}\n\treturn 0\n}\n\n/*********************************** Scenes **********************************\n* 0) Cornell Box with 2 spheres\n* 1) Sunset\n* 2) Psychedelic\n* The sphere fields are: Sphere{radius, position, emission, color, material}\n******************************************************************************/\nconst cen = Vec{50, 40.8, -860} // used by scene 1\n\nconst spheres = [\n\t[// scene 0 cornnel box\n\t\tSphere{\n\t\t\trad:  1e+5\n\t\t\tp:    Vec{1e+5 + 1, 40.8, 81.6}\n\t\t\te:    Vec{}\n\t\t\tc:    Vec{.75, .25, .25}\n\t\t\trefl: .diff\n\t\t}, // Left\n\t\tSphere{\n\t\t\trad:  1e+5\n\t\t\tp:    Vec{-1e+5 + 99, 40.8, 81.6}\n\t\t\te:    Vec{}\n\t\t\tc:    Vec{.25, .25, .75}\n\t\t\trefl: .diff\n\t\t}, // Rght\n\t\tSphere{\n\t\t\trad:  1e+5\n\t\t\tp:    Vec{50, 40.8, 1e+5}\n\t\t\te:    Vec{}\n\t\t\tc:    Vec{.75, .75, .75}\n\t\t\trefl: .diff\n\t\t}, // Back\n\t\tSphere{\n\t\t\trad:  1e+5\n\t\t\tp:    Vec{50, 40.8, -1e+5 + 170}\n\t\t\te:    Vec{}\n\t\t\tc:    Vec{}\n\t\t\trefl: .diff\n\t\t}, // Frnt\n\t\tSphere{\n\t\t\trad:  1e+5\n\t\t\tp:    Vec{50, 1e+5, 81.6}\n\t\t\te:    Vec{}\n\t\t\tc:    Vec{.75, .75, .75}\n\t\t\trefl: .diff\n\t\t}, // Botm\n\t\tSphere{\n\t\t\trad:  1e+5\n\t\t\tp:    Vec{50, -1e+5 + 81.6, 81.6}\n\t\t\te:    Vec{}\n\t\t\tc:    Vec{.75, .75, .75}\n\t\t\trefl: .diff\n\t\t}, // Top\n\t\tSphere{\n\t\t\trad:  16.5\n\t\t\tp:    Vec{27, 16.5, 47}\n\t\t\te:    Vec{}\n\t\t\tc:    Vec{1, 1, 1}.mul_scalar(.999)\n\t\t\trefl: .spec\n\t\t}, // Mirr\n\t\tSphere{\n\t\t\trad:  16.5\n\t\t\tp:    Vec{73, 16.5, 78}\n\t\t\te:    Vec{}\n\t\t\tc:    Vec{1, 1, 1}.mul_scalar(.999)\n\t\t\trefl: .refr\n\t\t}, // Glas\n\t\tSphere{\n\t\t\trad:  600\n\t\t\tp:    Vec{50, 681.6 - .27, 81.6}\n\t\t\te:    Vec{12, 12, 12}\n\t\t\tc:    Vec{}\n\t\t\trefl: .diff\n\t\t}, // Lite\n\t],\n\t[// scene 1 sunset\n\t\tSphere{\n\t\t\trad:  1600\n\t\t\tp:    Vec{1.0, 0.0, 2.0}.mul_scalar(3000)\n\t\t\te:    Vec{1.0, .9, .8}.mul_scalar(1.2e+1 * 1.56 * 2)\n\t\t\tc:    Vec{}\n\t\t\trefl: .diff\n\t\t}, // sun\n\t\tSphere{\n\t\t\trad:  1560\n\t\t\tp:    Vec{1, 0, 2}.mul_scalar(3500)\n\t\t\te:    Vec{1.0, .5, .05}.mul_scalar(4.8e+1 * 1.56 * 2)\n\t\t\tc:    Vec{}\n\t\t\trefl: .diff\n\t\t}, // horizon sun2\n\t\tSphere{\n\t\t\trad:  10000\n\t\t\tp:    cen + Vec{0, 0, -200}\n\t\t\te:    Vec{0.00063842, 0.02001478, 0.28923243}.mul_scalar(6e-2 * 8)\n\t\t\tc:    Vec{.7, .7, 1}.mul_scalar(.25)\n\t\t\trefl: .diff\n\t\t}, // sky\n\t\tSphere{\n\t\t\trad:  100000\n\t\t\tp:    Vec{50, -100000, 0}\n\t\t\te:    Vec{}\n\t\t\tc:    Vec{.3, .3, .3}\n\t\t\trefl: .diff\n\t\t}, // grnd\n\t\tSphere{\n\t\t\trad:  110000\n\t\t\tp:    Vec{50, -110048.5, 0}\n\t\t\te:    Vec{.9, .5, .05}.mul_scalar(4)\n\t\t\tc:    Vec{}\n\t\t\trefl: .diff\n\t\t}, // horizon brightener\n\t\tSphere{\n\t\t\trad:  4e+4\n\t\t\tp:    Vec{50, -4e+4 - 30, -3000}\n\t\t\te:    Vec{}\n\t\t\tc:    Vec{.2, .2, .2}\n\t\t\trefl: .diff\n\t\t}, // mountains\n\t\tSphere{\n\t\t\trad:  26.5\n\t\t\tp:    Vec{22, 26.5, 42}\n\t\t\te:    Vec{}\n\t\t\tc:    Vec{1, 1, 1}.mul_scalar(.596)\n\t\t\trefl: .spec\n\t\t}, // white Mirr\n\t\tSphere{\n\t\t\trad:  13\n\t\t\tp:    Vec{75, 13, 82}\n\t\t\te:    Vec{}\n\t\t\tc:    Vec{.96, .96, .96}.mul_scalar(.96)\n\t\t\trefl: .refr\n\t\t}, // Glas\n\t\tSphere{\n\t\t\trad:  22\n\t\t\tp:    Vec{87, 22, 24}\n\t\t\te:    Vec{}\n\t\t\tc:    Vec{.6, .6, .6}.mul_scalar(.696)\n\t\t\trefl: .refr\n\t\t}, // Glas2\n\t],\n\t[// scene 3 Psychedelic\n\t\tSphere{\n\t\t\trad:  150\n\t\t\tp:    Vec{50 + 75, 28, 62}\n\t\t\te:    Vec{1, 1, 1}.mul_scalar(0e-3)\n\t\t\tc:    Vec{1, .9, .8}.mul_scalar(.93)\n\t\t\trefl: .refr\n\t\t},\n\t\tSphere{\n\t\t\trad:  28\n\t\t\tp:    Vec{50 + 5, -28, 62}\n\t\t\te:    Vec{1, 1, 1}.mul_scalar(1e+1)\n\t\t\tc:    Vec{1, 1, 1}.mul_scalar(0)\n\t\t\trefl: .diff\n\t\t},\n\t\tSphere{\n\t\t\trad:  300\n\t\t\tp:    Vec{50, 28, 62}\n\t\t\te:    Vec{1, 1, 1}.mul_scalar(0e-3)\n\t\t\tc:    Vec{1, 1, 1}.mul_scalar(.93)\n\t\t\trefl: .spec\n\t\t},\n\t],\n]\n\n//********************************** Utilities ******************************\n@[inline]\nfn clamp(x f64) f64 {\n\tif x < 0 {\n\t\treturn 0\n\t}\n\tif x > 1 {\n\t\treturn 1\n\t}\n\treturn x\n}\n\n@[inline]\nfn to_int(x f64) int {\n\tp := math.pow(clamp(x), 1.0 / 2.2)\n\treturn int(p * 255.0 + 0.5)\n}\n\nfn intersect(r Ray, spheres &Sphere, nspheres int) (bool, f64, int) {\n\tmut d := 0.0\n\tmut t := inf\n\tmut id := 0\n\tfor i := nspheres - 1; i >= 0; i-- {\n\t\td = unsafe { spheres[i] }.intersect(r)\n\t\tif d > 0 && d < t {\n\t\t\tt = d\n\t\t\tid = i\n\t\t}\n\t}\n\treturn t < inf, t, id\n}\n\n// some casual random function, try to avoid the 0\nfn rand_f64() f64 {\n\tx := rand.u32() & 0x3FFF_FFFF\n\treturn f64(x) / f64(0x3FFF_FFFF)\n}\n\nconst cache_len = 65536 // the 2*pi angle will be split in 2^16 parts\n\nconst cache_mask = cache_len - 1\n\nstruct Cache {\nmut:\n\tsin_tab [65536]f64\n\tcos_tab [65536]f64\n}\n\nfn new_tabs() Cache {\n\tmut c := Cache{}\n\tinv_len := 1.0 / f64(cache_len)\n\tfor i in 0 .. cache_len {\n\t\tx := f64(i) * math.pi * 2.0 * inv_len\n\t\tc.sin_tab[i] = math.sin(x)\n\t\tc.cos_tab[i] = math.cos(x)\n\t}\n\treturn c\n}\n\n//************ Cache for sin/cos speed-up table and scene selector **********\nconst tabs = new_tabs()\n\n//****************** main function for the radiance calculation *************\nfn radiance(r Ray, depthi int, scene_id int) Vec {\n\tif depthi > 1024 {\n\t\teprintln('depthi: ${depthi}')\n\t\teprintln('')\n\t\treturn Vec{}\n\t}\n\tmut depth := depthi // actual depth in the reflection tree\n\tmut t := 0.0 // distance to intersection\n\tmut id := 0 // id of intersected object\n\tmut res := false // result of intersect\n\n\tv_1 := 1.0\n\t// v_2 := f64(2.0)\n\n\tscene := spheres[scene_id]\n\t// res, t, id = intersect(r, id, tb.scene)\n\tres, t, id = intersect(r, scene.data, scene.len)\n\tif !res {\n\t\treturn Vec{}\n\t}\n\t// if miss, return black\n\n\tobj := scene[id] // the hit object\n\n\tx := r.o + r.d.mul_scalar(t)\n\tn := Vec(x - obj.p).norm()\n\n\tnl := if n.dot(r.d) < 0.0 { n } else { n.mul_scalar(-1) }\n\n\tmut f := obj.c\n\n\t// max reflection\n\tmut p := f.z\n\tif f.x > f.y && f.x > f.z {\n\t\tp = f.x\n\t} else {\n\t\tif f.y > f.z {\n\t\t\tp = f.y\n\t\t}\n\t}\n\n\tdepth++\n\tif depth > 5 {\n\t\tif rand_f64() < p {\n\t\t\tf = f.mul_scalar(f64(1.0) / p)\n\t\t} else {\n\t\t\treturn obj.e // R.R.\n\t\t}\n\t}\n\n\tif obj.refl == .diff { // Ideal DIFFUSE reflection\n\t\t// **Full Precision**\n\t\t// r1  := f64(2.0 * math.pi) * rand_f64()\n\n\t\t// tabbed speed-up\n\t\tr1 := rand.u32() & cache_mask\n\n\t\tr2 := rand_f64()\n\t\tr2s := math.sqrt(r2)\n\n\t\tw := nl\n\n\t\tmut u := if math.abs(w.x) > f64(0.1) { Vec{0, 1, 0} } else { Vec{1, 0, 0} }\n\t\tu = Vec(u.cross(w)).norm()\n\n\t\tv := w.cross(u)\n\n\t\t// **Full Precision**\n\t\t// d := (u.mul_scalar(math.cos(r1) * r2s) + v.mul_scalar(math.sin(r1) * r2s) + w.mul_scalar(1.0 - r2)).norm()\n\n\t\t// tabbed speed-up\n\t\td := Vec(u.mul_scalar(tabs.cos_tab[r1] * r2s) + v.mul_scalar(tabs.sin_tab[r1] * r2s) +\n\t\t\t(w.mul_scalar(math.sqrt(f64(1.0) - r2)))).norm()\n\n\t\treturn obj.e + f * radiance(Ray{x, d}, depth, scene_id)\n\t} else {\n\t\tif obj.refl == .spec { // Ideal SPECULAR reflection\n\t\t\treturn obj.e +\n\t\t\t\tf * radiance(Ray{x, r.d - n.mul_scalar(2.0 * n.dot(r.d))}, depth, scene_id)\n\t\t}\n\t}\n\n\trefl_ray := Ray{x, r.d - n.mul_scalar(2.0 * n.dot(r.d))} // Ideal dielectric REFRACTION\n\tinto := n.dot(nl) > 0 // Ray from outside going in?\n\n\tnc := f64(1.0)\n\tnt := f64(1.5)\n\n\tnnt := if into { nc / nt } else { nt / nc }\n\n\tddn := r.d.dot(nl)\n\tcos2t := v_1 - nnt * nnt * (v_1 - ddn * ddn)\n\tif cos2t < 0.0 { // Total internal reflection\n\t\treturn obj.e + f * radiance(refl_ray, depth, scene_id)\n\t}\n\n\tdirc := if into { f64(1) } else { f64(-1) }\n\ttdir := Vec(r.d.mul_scalar(nnt) - n.mul_scalar(dirc * (ddn * nnt + math.sqrt(cos2t)))).norm()\n\n\ta := nt - nc\n\tb := nt + nc\n\tr0 := a * a / (b * b)\n\tc := if into { v_1 + ddn } else { v_1 - tdir.dot(n) }\n\n\tre := r0 + (v_1 - r0) * c * c * c * c * c\n\ttr := v_1 - re\n\tpp := f64(.25) + f64(.5) * re\n\trp := re / pp\n\ttp := tr / (v_1 - pp)\n\n\tmut tmp := Vec{}\n\tif depth > 2 {\n\t\t// Russian roulette\n\t\ttmp = if rand_f64() < pp {\n\t\t\tradiance(refl_ray, depth, scene_id).mul_scalar(rp)\n\t\t} else {\n\t\t\tradiance(Ray{x, tdir}, depth, scene_id).mul_scalar(tp)\n\t\t}\n\t} else {\n\t\ttmp = (radiance(refl_ray, depth, scene_id).mul_scalar(re)) +\n\t\t\t(radiance(Ray{x, tdir}, depth, scene_id).mul_scalar(tr))\n\t}\n\treturn obj.e + (f * tmp)\n}\n\n//*********************** beam scan routine *********************************\nfn ray_trace(w int, h int, samps int, scene_id int) Image {\n\timage := new_image(w, h)\n\n\t// inverse costants\n\tw1 := f64(1.0 / f64(w))\n\th1 := f64(1.0 / f64(h))\n\tsamps1 := f64(1.0 / f64(samps))\n\n\tcam := Ray{Vec{50, 52, 295.6}, Vec{0, -0.042612, -1}.norm()} // cam position, direction\n\tcx := Vec{f64(w) * 0.5135 / f64(h), 0, 0}\n\tcy := Vec(cx.cross(cam.d)).norm().mul_scalar(0.5135)\n\tmut r := Vec{}\n\n\t// speed-up constants\n\tv_1 := f64(1.0)\n\tv_2 := f64(2.0)\n\n\t// OpenMP injection point! #pragma omp parallel for schedule(dynamic, 1) shared(c)\n\tfor y := 0; y < h; y++ {\n\t\tif y & 7 == 0 || y + 1 == h {\n\t\t\tterm.cursor_up(1)\n\t\t\teprintln('Rendering (${samps * 4} spp) ${(100.0 * f64(y)) / (f64(h) - 1.0):5.2f}%')\n\t\t}\n\t\tfor x in 0 .. w {\n\t\t\ti := (h - y - 1) * w + x\n\t\t\tmut ivec := unsafe { &image.data[i] }\n\t\t\t// we use sx and sy to perform a square subsampling of 4 samples\n\t\t\tfor sy := 0; sy < 2; sy++ {\n\t\t\t\tfor sx := 0; sx < 2; sx++ {\n\t\t\t\t\tr = Vec{0, 0, 0}\n\t\t\t\t\tfor _ in 0 .. samps {\n\t\t\t\t\t\tr1 := v_2 * rand_f64()\n\t\t\t\t\t\tdx := if r1 < v_1 { math.sqrt(r1) - v_1 } else { v_1 - math.sqrt(v_2 - r1) }\n\n\t\t\t\t\t\tr2 := v_2 * rand_f64()\n\t\t\t\t\t\tdy := if r2 < v_1 { math.sqrt(r2) - v_1 } else { v_1 - math.sqrt(v_2 - r2) }\n\n\t\t\t\t\t\td := cx.mul_scalar(((f64(sx) + 0.5 + dx) * 0.5 + f64(x)) * w1 - .5) +\n\t\t\t\t\t\t\tcy.mul_scalar(((f64(sy) + 0.5 + dy) * 0.5 + f64(y)) * h1 - .5) + cam.d\n\t\t\t\t\t\tr = r + radiance(Ray{cam.o +\n\t\t\t\t\t\t\td.mul_scalar(140.0), Vec(d).norm()}, 0, scene_id).mul_scalar(samps1)\n\t\t\t\t\t}\n\t\t\t\t\ttmp_vec := Vec{clamp(r.x), clamp(r.y), clamp(r.z)}.mul_scalar(.25)\n\t\t\t\t\tunsafe {\n\t\t\t\t\t\t(*ivec) = *ivec + tmp_vec\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn image\n}\n\nfn main() {\n\tif os.args.len > 6 {\n\t\teprintln('Usage:\\n     path_tracing [samples] [image.ppm] [scene_n] [width] [height]')\n\t\texit(1)\n\t}\n\tmut width := 320 // width of the rendering in pixels\n\tmut height := 200 // height of the rendering in pixels\n\tmut samples := 4 // number of samples per pixel, increase for better quality\n\tmut scene_id := 0 // scene to render [0 cornell box,1 sunset,2 psyco]\n\tmut file_name := 'image.ppm' // name of the output file in .ppm format\n\n\tif os.args.len >= 2 {\n\t\tsamples = os.args[1].int() / 4\n\t}\n\tif os.args.len >= 3 {\n\t\tfile_name = os.args[2]\n\t}\n\tif os.args.len >= 4 {\n\t\tscene_id = os.args[3].int()\n\t}\n\tif os.args.len >= 5 {\n\t\twidth = os.args[4].int()\n\t}\n\tif os.args.len == 6 {\n\t\theight = os.args[5].int()\n\t}\n\t// change the seed for a different result\n\trand.seed([u32(2020), 0])\n\n\teprintln('Path tracing samples: ${samples}, file_name: ${file_name}, scene_id: ${scene_id}, width: ${width}, height: ${height}')\n\teprintln('')\n\n\tt1 := time.ticks()\n\timage := ray_trace(width, height, samples, scene_id)\n\tt2 := time.ticks()\n\teprintln('Rendering finished. Took: ${(t2 - t1):5}ms')\n\n\timage.save_as_ppm(file_name)\n\tt3 := time.ticks()\n\teprintln('Image saved as [${file_name}]. Took: ${(t3 - t2):5}ms')\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/.gitignore",
    "content": "# Executables files\ntest\ntest.exe\n\n# Temporary files\nfns.txt\n\n!/bin/test\n\n/docs/build\n*.ppm\nmain\nparallel\nparallel_with_iw\nsequential\nanimation\nfull\n*.log\n"
  },
  {
    "path": "examples/pendulum-simulation/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021-2024 Ulises Jeremias Cornejo Fandos\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "examples/pendulum-simulation/README.md",
    "content": "<div align=\"center\">\n<p>\n    <img\n        style=\"width: 250px\"\n        width=\"250\"\n        src=\"https://user-images.githubusercontent.com/17727170/153699135-a63e9644-1a29-4c04-9de3-c9100b06001d.png\"\n    >\n</p>\n  \n<h1>Pendulum Simulation in V</h1>\n\nYou can see the origin implementation among with some benchmarks at\n[ulises-jeremias/v-pendulum-simulation](https://github.com/ulises-jeremias/v-pendulum-simulation).\n\n[vlang.io](https://vlang.io) |\n[Docs](https://ulises-jeremias.github.io/v-pendulum-simulation) |\n[Contributing](https://github.com/ulises-jeremias/v-pendulum-simulation/blob/main/CONTRIBUTING.md)\n\n</div>\n<div align=\"center\">\n\n[![Build Status][workflowbadge]][workflowurl]\n[![Docs Validation][validatedocsbadge]][validatedocsurl]\n[![License: MIT][licensebadge]][licenseurl]\n\n</div>\n\n## Run the Simulations\n\n### Sequential Simulation\n\n```sh\n$ v -gc boehm -prod sequential.v\n$ ./sequential # execute ./sequential -h for more info\n```\n\n### Parallel Simulation\n\n```sh\n$ v -gc boehm -prod parallel.v\n$ ./parallel # execute ./parallel -h for more info\n```\n\n![image](https://user-images.githubusercontent.com/17727170/153718774-1c93b158-aee3-4be1-bb47-fe601fed7336.png)\n\n### Parallel Simulation with Image Worker\n\n```sh\n$ v -gc boehm -prod parallel_with_iw.v\n$ ./parallel_with_iw # execute ./parallel_with_iw -h for more info\n```\n\n![image](https://user-images.githubusercontent.com/17727170/153718769-eabb334d-454f-469f-a51a-14ffe67507de.png)\n\n### Parallel Simulation with Graphic User Interface\n\n```sh\n$ v -gc boehm -prod animation.v\n$ ./animation # execute ./animation -h for more info\n```\n\n### Full Parallel Simulation with Graphic User Interface and Image Output\n\n```sh\n$ v -gc boehm -prod full.v\n$ ./full # execute ./full -h for more info\n```\n\n## Testing\n\nTo test the module, just type the following command:\n\n```sh\n$ v test .\n```\n\n## Benchmark\n\nCheck the original repository for tools to run benchmark tests. In there you can execute\nthe following command to execute benchmark tests to get a full comparison between implementations:\n\n```sh\n$ ./bin/run-benchmark-test --help\n```\n\n![image](https://user-images.githubusercontent.com/17727170/152750137-98e7c5a3-936b-4bc8-b71a-1b182c0bbf50.png)\n\n[workflowbadge]: https://github.com/ulises-jeremias/v-pendulum-simulation/workflows/Build%20and%20Test%20with%20deps/badge.svg\n[validatedocsbadge]: https://github.com/ulises-jeremias/v-pendulum-simulation/workflows/Validate%20Docs/badge.svg\n[licensebadge]: https://img.shields.io/badge/License-MIT-blue.svg\n[workflowurl]: https://github.com/ulises-jeremias/v-pendulum-simulation/commits/main\n[validatedocsurl]: https://github.com/ulises-jeremias/v-pendulum-simulation/commits/main\n[licenseurl]: https://github.com/ulises-jeremias/v-pendulum-simulation/blob/main/LICENSE\n"
  },
  {
    "path": "examples/pendulum-simulation/animation.v",
    "content": "module main\n\nimport log\nimport benchmark\nimport sim\nimport sim.anim\nimport sim.args as simargs\n\nfn main() {\n\tunbuffer_stdout()\n\tlog.use_stdout()\n\targs := simargs.parse_args(extra_workers: 1)! as simargs.ParallelArgs\n\tmut app := anim.new_app(args)\n\tmut workers := []thread{cap: args.workers}\n\tmut bmark := benchmark.start()\n\tdefer {\n\t\tapp.request_chan.close()\n\t\tlog.info('Waiting for workers to finish')\n\t\tworkers.wait()\n\t\tapp.result_chan.close()\n\t\tlog.info('Workers finished!')\n\t\tbmark.measure(@FN)\n\t\tlog.info('Done!')\n\t}\n\tfor id in 0 .. args.workers {\n\t\tworkers << spawn sim.sim_worker(id, app.request_chan, [app.result_chan])\n\t}\n\thandle_request := fn [app] (request &sim.SimRequest) ! {\n\t\tapp.request_chan <- request\n\t}\n\tspawn app.gg.run()\n\tsim.run(args.params, grid: args.grid, on_request: sim.SimRequestHandler(handle_request))\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/full.v",
    "content": "module main\n\nimport benchmark\nimport sim\nimport sim.anim\nimport sim.args as simargs\nimport sim.img\n\nfn main() {\n\targs := simargs.parse_args(extra_workers: 2)! as simargs.ParallelArgs\n\n\timg_settings := img.image_settings_from_grid(args.grid)\n\n\tmut writer := img.ppm_writer_for_fname(args.filename, img_settings)!\n\n\tmut app := anim.new_app(args)\n\tmut workers := []thread{cap: args.workers + 1}\n\n\tmut bmark := benchmark.start()\n\n\timg_result_chan := chan &sim.SimResult{cap: args.workers}\n\n\tdefer {\n\t\timage_worker := workers.pop()\n\t\tapp.request_chan.close()\n\t\tsim.log('Waiting for workers to finish')\n\t\tworkers.wait()\n\t\tapp.result_chan.close()\n\t\timg_result_chan.close()\n\t\tsim.log('Waiting for image writer to finish')\n\t\timage_worker.wait()\n\t\tsim.log('Workers finished!')\n\t\tbmark.measure(@FN)\n\t\tsim.log('Closing writer file')\n\t\twriter.close()\n\t\tsim.log('Done!')\n\t}\n\n\t// start a worker on each core\n\tfor id in 0 .. app.args.workers {\n\t\tworkers << spawn sim.sim_worker(id, app.request_chan, [app.result_chan, img_result_chan])\n\t}\n\n\thandle_request := fn [app] (request &sim.SimRequest) ! {\n\t\tapp.request_chan <- request\n\t}\n\n\tworkers << spawn img.image_worker(mut writer, img_result_chan, img_settings)\n\n\tspawn app.gg.run()\n\n\tsim.run(app.args.params,\n\t\tgrid:       app.args.grid\n\t\ton_request: sim.SimRequestHandler(handle_request)\n\t)\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/anim/app.v",
    "content": "module anim\n\nimport gg\nimport sim\nimport sim.args as simargs\n\nconst bg_color = gg.white\n\nstruct Pixel {\n\tx     f32\n\ty     f32\n\tcolor gg.Color\n}\n\npub struct App {\npub:\n\targs         simargs.ParallelArgs\n\trequest_chan chan &sim.SimRequest\n\tresult_chan  chan &sim.SimResult\npub mut:\n\tgg     &gg.Context = unsafe { nil }\n\tiidx   int\n\tpixels []u32\n}\n\npub fn new_app(args simargs.ParallelArgs) &App {\n\ttotal_pixels := args.grid.height * args.grid.width\n\n\tmut app := &App{\n\t\targs:         args\n\t\tpixels:       []u32{len: total_pixels}\n\t\trequest_chan: chan &sim.SimRequest{cap: args.grid.width}\n\t}\n\tapp.gg = gg.new_context(\n\t\twidth:         args.grid.width\n\t\theight:        args.grid.height\n\t\tcreate_window: true\n\t\twindow_title:  'V Pendulum Simulation'\n\t\tuser_data:     app\n\t\tbg_color:      bg_color\n\t\tframe_fn:      frame\n\t\tinit_fn:       init\n\t)\n\treturn app\n}\n\nfn init(mut app App) {\n\tapp.iidx = app.gg.new_streaming_image(app.args.grid.width, app.args.grid.height, 4,\n\t\tpixel_format: .rgba8\n\t)\n\tspawn pixels_worker(mut app)\n}\n\nfn frame(mut app App) {\n\tapp.gg.begin()\n\tapp.draw()\n\tapp.gg.end()\n}\n\nfn (mut app App) draw() {\n\tmut istream_image := app.gg.get_cached_image_by_idx(app.iidx)\n\tistream_image.update_pixel_data(unsafe { &u8(&app.pixels[0]) })\n\tapp.gg.draw_image(0, 0, app.args.grid.width, app.args.grid.height, istream_image)\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/anim/worker.v",
    "content": "module anim\n\nimport benchmark\nimport sim.img\n\nfn pixels_worker(mut app App) {\n\tmut bmark := benchmark.new_benchmark()\n\tfor {\n\t\tresult := <-app.result_chan or { break }\n\t\tbmark.step()\n\t\t// find the closest magnet\n\t\tpixel_color := img.compute_pixel(result)\n\t\tapp.pixels[result.id] = u32(pixel_color.abgr8())\n\t\tbmark.ok()\n\t}\n\tbmark.stop()\n\tprintln(bmark.total_message(@FN))\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/args/parser.v",
    "content": "module args\n\nimport flag\nimport os\nimport runtime\nimport sim\nimport math\n\n// customisable through setting VJOBS\nconst max_parallel_workers = runtime.nr_jobs()\n\n@[params]\npub struct ParserSettings {\npub:\n\tsequential    bool\n\timg           bool\n\textra_workers int\n}\n\npub struct SequentialArgs {\npub:\n\tparams   sim.SimParams\n\tgrid     sim.GridSettings\n\tfilename string\n}\n\npub struct ParallelArgs {\n\tSequentialArgs\npub:\n\tworkers int = max_parallel_workers\n}\n\npub type SimArgs = ParallelArgs | SequentialArgs\n\npub fn parse_args(config ParserSettings) !SimArgs {\n\tif config.sequential {\n\t\targs := parse_sequential_args()!\n\t\treturn SimArgs(args)\n\t} else {\n\t\targs := parse_parallel_args(config.extra_workers)!\n\t\treturn SimArgs(args)\n\t}\n}\n\nfn parse_sequential_args() !SequentialArgs {\n\tmut fp := flag.new_flag_parser(os.args)\n\tfp.application('vps')\n\tfp.version('v0.1.0')\n\tfp.limit_free_args(0, 0)!\n\tfp.description('This is a pendulum simulation written in pure V')\n\tfp.skip_executable()\n\n\t// output parameters\n\twidth := fp.int('width', `w`, sim.default_width, 'width of the image output. Defaults to ${sim.default_width}')\n\theight := fp.int('height', `h`, sim.default_height, 'height of the image output. Defaults to ${sim.default_height}')\n\tfilename := fp.string('output', `o`, 'out.ppm', 'name of the image output. Defaults to out.ppm')\n\n\t// simulation parameters\n\trope_length := fp.float('rope-length', 0, sim.default_rope_length, 'rope length to use on simulation. Defaults to ${sim.default_rope_length}')\n\tbearing_mass := fp.float('bearing-mass', 0, sim.default_bearing_mass, 'bearing mass to use on simulation. Defaults to ${sim.default_bearing_mass}')\n\tmagnet_spacing := fp.float('magnet-spacing', 0, sim.default_magnet_spacing, 'magnet spacing to use on simulation. Defaults to ${sim.default_magnet_spacing}')\n\tmagnet_height := fp.float('magnet-height', 0, sim.default_magnet_height, 'magnet height to use on simulation. Defaults to ${sim.default_magnet_height}')\n\tmagnet_strength := fp.float('magnet-strength', 0, sim.default_magnet_strength, 'magnet strength to use on simulation. Defaults to ${sim.default_magnet_strength}')\n\tgravity := fp.float('gravity', 0, sim.default_gravity, 'gravity to use on simulation. Defaults to ${sim.default_gravity}')\n\n\tfp.finalize() or {\n\t\tprintln(fp.usage())\n\t\treturn error('none')\n\t}\n\n\tparams := sim.sim_params(\n\t\trope_length:     rope_length\n\t\tbearing_mass:    bearing_mass\n\t\tmagnet_spacing:  magnet_spacing\n\t\tmagnet_height:   magnet_height\n\t\tmagnet_strength: magnet_strength\n\t\tgravity:         gravity\n\t)\n\n\tgrid := sim.new_grid_settings(\n\t\twidth:  width\n\t\theight: height\n\t)\n\n\targs := SequentialArgs{\n\t\tparams:   params\n\t\tfilename: filename\n\t\tgrid:     grid\n\t}\n\n\tsim.log('${args}')\n\n\treturn args\n}\n\nfn parse_parallel_args(extra_workers int) !ParallelArgs {\n\tmut fp := flag.new_flag_parser(os.args)\n\tfp.application('vps')\n\tfp.version('v0.1.0')\n\tfp.limit_free_args(0, 0)!\n\tfp.description('This is a pendulum simulation written in pure V')\n\tfp.skip_executable()\n\n\tworkers := fp.int('workers', 0, max_parallel_workers, 'amount of workers to use on simulation. Defaults to ${max_parallel_workers}')\n\n\t// output parameters\n\twidth := fp.int('width', `w`, sim.default_width, 'width of the image output. Defaults to ${sim.default_width}')\n\theight := fp.int('height', `h`, sim.default_height, 'height of the image output. Defaults to ${sim.default_height}')\n\tfilename := fp.string('output', `o`, 'out.ppm', 'name of the image output. Defaults to out.ppm')\n\n\t// simulation parameters\n\trope_length := fp.float('rope-length', 0, sim.default_rope_length, 'rope length to use on simulation. Defaults to ${sim.default_rope_length}')\n\tbearing_mass := fp.float('bearing-mass', 0, sim.default_bearing_mass, 'bearing mass to use on simulation. Defaults to ${sim.default_bearing_mass}')\n\tmagnet_spacing := fp.float('magnet-spacing', 0, sim.default_magnet_spacing, 'magnet spacing to use on simulation. Defaults to ${sim.default_magnet_spacing}')\n\tmagnet_height := fp.float('magnet-height', 0, sim.default_magnet_height, 'magnet height to use on simulation. Defaults to ${sim.default_magnet_height}')\n\tmagnet_strength := fp.float('magnet-strength', 0, sim.default_magnet_strength, 'magnet strength to use on simulation. Defaults to ${sim.default_magnet_strength}')\n\tgravity := fp.float('gravity', 0, sim.default_gravity, 'gravity to use on simulation. Defaults to ${sim.default_gravity}')\n\n\tfp.finalize() or {\n\t\tprintln(fp.usage())\n\t\treturn error('none')\n\t}\n\n\tparams := sim.sim_params(\n\t\trope_length:     rope_length\n\t\tbearing_mass:    bearing_mass\n\t\tmagnet_spacing:  magnet_spacing\n\t\tmagnet_height:   magnet_height\n\t\tmagnet_strength: magnet_strength\n\t\tgravity:         gravity\n\t)\n\n\tgrid := sim.new_grid_settings(\n\t\twidth:  width\n\t\theight: height\n\t)\n\n\targs := ParallelArgs{\n\t\tparams:   params\n\t\tfilename: filename\n\t\tgrid:     grid\n\t\tworkers:  get_workers(workers, extra_workers)\n\t}\n\tsim.log('${args}')\n\n\treturn args\n}\n\n@[inline]\nfn get_workers(workers int, extra_workers int) int {\n\treturn math.max(1, workers + extra_workers)\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/img/ppm.v",
    "content": "module img\n\nimport gg\nimport os\nimport sim\n\n@[params]\npub struct ImageSettings {\npub:\n\twidth      int = sim.default_width\n\theight     int = sim.default_height\n\tcache_size int = 200\n}\n\npub fn new_image_settings(settings ImageSettings) ImageSettings {\n\treturn ImageSettings{\n\t\t...settings\n\t}\n}\n\npub fn image_settings_from_grid(grid sim.GridSettings) ImageSettings {\n\treturn ImageSettings{\n\t\twidth:  grid.width\n\t\theight: grid.height\n\t}\n}\n\npub fn (s ImageSettings) to_grid_settings() sim.GridSettings {\n\treturn sim.GridSettings{\n\t\twidth:  s.width\n\t\theight: s.height\n\t}\n}\n\npub struct PPMWriter {\nmut:\n\tfile       os.File\n\tcache      []u8\n\tcache_size int\n}\n\npub fn ppm_writer_for_fname(fname string, settings ImageSettings) !&PPMWriter {\n\tmut writer := &PPMWriter{\n\t\tcache_size: settings.cache_size\n\t\tcache:      []u8{cap: settings.cache_size}\n\t}\n\twriter.start_for_file(fname, settings)!\n\treturn writer\n}\n\npub fn (mut writer PPMWriter) start_for_file(fname string, settings ImageSettings) ! {\n\twriter.file = os.create(fname)!\n\twriter.file.writeln('P6 ${settings.width} ${settings.height} 255')!\n}\n\npub fn (mut writer PPMWriter) handle_pixel(p gg.Color) ! {\n\tif writer.cache.len >= writer.cache_size {\n\t\twriter.write()!\n\t\twriter.flush()!\n\t}\n\twriter.cache << [p.r, p.g, p.b]\n}\n\npub fn (mut writer PPMWriter) flush() ! {\n\twriter.cache.clear()\n}\n\npub fn (mut writer PPMWriter) write() ! {\n\twriter.file.write(writer.cache)!\n}\n\npub fn (mut writer PPMWriter) close() {\n\twriter.file.close()\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/img/worker.v",
    "content": "module img\n\nimport benchmark\nimport sim\n\npub fn image_worker(mut writer PPMWriter, result_chan chan &sim.SimResult, settings ImageSettings) {\n\twidth := settings.width\n\theight := settings.height\n\ttotal_pixels := width * height\n\n\t// as new pixels come in, write them to the image file\n\tmut current_index := u64(0)\n\tmut pixel_buf := []ValidColor{len: total_pixels, init: ValidColor{\n\t\tvalid: false\n\t}}\n\n\tmut bmark := benchmark.new_benchmark()\n\tfor {\n\t\tresult := <-result_chan or { break }\n\n\t\t// find the closest magnet\n\t\tpixel_buf[result.id].Color = compute_pixel(result)\n\t\tpixel_buf[result.id].valid = true\n\n\t\tfor current_index < total_pixels && pixel_buf[current_index].valid {\n\t\t\tbmark.step()\n\t\t\twriter.handle_pixel(pixel_buf[current_index].Color) or {\n\t\t\t\tbmark.fail()\n\t\t\t\tsim.log(@MOD + '.' + @FN + ': pixel handler failed. Error ${err}')\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tbmark.ok()\n\t\t\tcurrent_index++\n\t\t}\n\t}\n\tbmark.stop()\n\tprintln(bmark.total_message(@FN))\n\n\twriter.write() or { panic('Could not write image') }\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/img/writer.v",
    "content": "module img\n\nimport gg\nimport sim\n\npub struct ValidColor {\n\tgg.Color\npub mut:\n\tvalid bool\n}\n\npub struct ImageWriter {\n\tsettings ImageSettings\npub mut:\n\twriter        PPMWriter\n\tcurrent_index int\n\tbuffer        []ValidColor\n}\n\npub fn new_image_writer(mut writer PPMWriter, settings ImageSettings) &ImageWriter {\n\ttotal_pixels := settings.width * settings.height\n\tmut buffer := []ValidColor{len: total_pixels, init: ValidColor{\n\t\tvalid: false\n\t}}\n\treturn &ImageWriter{\n\t\twriter:   writer\n\t\tsettings: settings\n\t\tbuffer:   buffer\n\t}\n}\n\npub fn (mut iw ImageWriter) handle(result sim.SimResult) !int {\n\ttotal_pixels := iw.settings.width * iw.settings.height\n\n\t// find the closest magnet\n\tiw.buffer[result.id].Color = compute_pixel(result)\n\tiw.buffer[result.id].valid = true\n\n\tfor iw.current_index < total_pixels && iw.buffer[iw.current_index].valid {\n\t\tiw.writer.handle_pixel(iw.buffer[iw.current_index].Color) or {\n\t\t\tsim.log(@MOD + '.' + @FN + ': pixel handler failed. Error ${err}')\n\t\t\tbreak\n\t\t}\n\t\tiw.current_index++\n\t}\n\n\tif iw.current_index == total_pixels {\n\t\tiw.writer.write() or { panic('Could not write image') }\n\t\treturn error('none')\n\t}\n\n\treturn iw.current_index\n}\n\npub fn compute_pixel(result sim.SimResult) gg.Color {\n\tclosest_to_m1 := result.magnet1_distance < result.magnet2_distance\n\t\t&& result.magnet1_distance < result.magnet3_distance\n\tclosest_to_m2 := result.magnet2_distance < result.magnet1_distance\n\t\t&& result.magnet2_distance < result.magnet3_distance\n\n\tif closest_to_m1 {\n\t\treturn gg.red\n\t} else if closest_to_m2 {\n\t\treturn gg.green\n\t} else {\n\t\treturn gg.blue\n\t}\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/log.v",
    "content": "module sim\n\n// log is a helper function to print debug info\n@[inline]\npub fn log(info string) {\n\t$if verbose ? {\n\t\tprintln(info)\n\t}\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/params.v",
    "content": "module sim\n\nimport math\n\npub const default_rope_length = 0.25\npub const default_bearing_mass = 0.03\npub const default_magnet_spacing = 0.05\npub const default_magnet_height = 0.03\npub const default_magnet_strength = 10.0\npub const default_gravity = 4.9\n\n@[params]\npub struct SimParams {\npub:\n\trope_length     f64 = default_rope_length\n\tbearing_mass    f64 = default_bearing_mass\n\tmagnet_spacing  f64 = default_magnet_spacing\n\tmagnet_height   f64 = default_magnet_height\n\tmagnet_strength f64 = default_magnet_strength\n\tgravity         f64 = default_gravity\n}\n\npub fn sim_params(params SimParams) SimParams {\n\treturn SimParams{\n\t\t...params\n\t}\n}\n\npub fn (params SimParams) get_rope_vector(state SimState) Vector3D {\n\trope_origin := vector(z: params.rope_length)\n\n\treturn state.position + rope_origin.scale(-1)\n}\n\npub fn (params SimParams) get_forces_sum(state SimState) Vector3D {\n\t// force due to gravity\n\tf_gravity := params.get_grav_force(state)\n\n\t// force due to magnets\n\tf_magnet1 := params.get_magnet1_force(state)\n\tf_magnet2 := params.get_magnet2_force(state)\n\tf_magnet3 := params.get_magnet3_force(state)\n\n\tmut f_passive := vector(x: 0.0, y: 0.0, z: 0.0)\n\tfor force in [f_gravity, f_magnet1, f_magnet2, f_magnet3] {\n\t\tf_passive = f_passive + force\n\t}\n\n\t// force due to tension of the rope\n\tf_tension := params.get_tension_force(state, f_passive)\n\n\treturn f_passive + f_tension\n}\n\npub fn (params SimParams) get_grav_force(state SimState) Vector3D {\n\treturn vector(z: -params.bearing_mass * params.gravity)\n}\n\npub fn (params SimParams) get_magnet_position(theta f64) Vector3D {\n\treturn vector(\n\t\tx: math.cos(theta) * params.magnet_spacing\n\t\ty: math.sin(theta) * params.magnet_spacing\n\t\tz: -params.magnet_height\n\t)\n}\n\npub fn (params SimParams) get_magnet_force(theta f64, state SimState) Vector3D {\n\tmagnet_position := params.get_magnet_position(theta)\n\tmut diff := magnet_position + state.position.scale(-1)\n\tdistance_squared := diff.norm_squared()\n\tdiff = diff.scale(1.0 / math.sqrt(distance_squared))\n\treturn diff.scale(params.magnet_strength / distance_squared)\n}\n\npub fn (params SimParams) get_magnet_dist(theta f64, state SimState) f64 {\n\treturn (params.get_magnet_position(theta) + state.position.scale(-1)).norm()\n}\n\npub fn (params SimParams) get_magnet1_force(state SimState) Vector3D {\n\treturn params.get_magnet_force(0.0 * math.pi / 3.0, state)\n}\n\npub fn (params SimParams) get_magnet2_force(state SimState) Vector3D {\n\treturn params.get_magnet_force(2.0 * math.pi / 3.0, state)\n}\n\npub fn (params SimParams) get_magnet3_force(state SimState) Vector3D {\n\treturn params.get_magnet_force(4.0 * math.pi / 3.0, state)\n}\n\npub fn (params SimParams) get_tension_force(state SimState, f_passive Vector3D) Vector3D {\n\trope_vector := params.get_rope_vector(state)\n\trope_vector_norm := rope_vector.scale(1.0 / rope_vector.norm())\n\treturn rope_vector_norm.scale(-1.0 * (rope_vector_norm * f_passive))\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/params_test.v",
    "content": "module sim\n\nimport math\n\nconst params_test_mock_params = SimParams{\n\trope_length:     0.25\n\tbearing_mass:    0.03\n\tmagnet_spacing:  0.05\n\tmagnet_height:   0.03\n\tmagnet_strength: 10\n\tgravity:         4.9\n}\nconst params_test_mock_state = SimState{\n\tposition: vector(\n\t\tx: -0.016957230930171364\n\t\ty: -0.02937078552673521\n\t\tz: 0.002311063475327252\n\t)\n\tvelocity: vector(\n\t\tx: -7.251158929833104\n\t\ty: -12.559375680227724\n\t\tz: -105.91539687686381\n\t)\n\taccel:    vector(\n\t\tx: -8.337034766251843e-11\n\t\ty: -2.842170943040401e-10\n\t\tz: 1.2126596023639044e-10\n\t)\n}\nconst params_test_mock_tetha = 2.0 * math.pi / 3.0\n\npub fn test_get_rope_vector() {\n\tresult := params_test_mock_params.get_rope_vector(params_test_mock_state)\n\texpected := vector(\n\t\tx: -0.016957230930171364\n\t\ty: -0.02937078552673521\n\t\tz: -0.24768893652467275\n\t)\n\tassert result == expected\n}\n\npub fn test_get_forces_sum() {\n\tresult := params_test_mock_params.get_forces_sum(params_test_mock_state)\n\texpected := vector(\n\t\tx: 3.410605131648481e-12\n\t\ty: 5.229594535194337e-12\n\t\tz: 9.094947017729282e-13\n\t)\n\tassert result == expected\n}\n\npub fn test_get_grav_force() {\n\tresult := params_test_mock_params.get_grav_force(params_test_mock_state)\n\texpected := vector(\n\t\tz: -0.147\n\t)\n\tassert result == expected\n}\n\npub fn test_get_magnet_position() {\n\tresult := params_test_mock_params.get_magnet_position(params_test_mock_tetha)\n\texpected := vector(\n\t\tx: -0.02499999999999999\n\t\ty: 0.04330127018922194\n\t\tz: -0.03\n\t)\n\tassert result == expected\n}\n\npub fn test_get_magnet_force() {\n\tresult := params_test_mock_params.get_magnet_force(params_test_mock_tetha, params_test_mock_state)\n\texpected := vector(\n\t\tx: -157.4572297692556\n\t\ty: 1422.736432604726\n\t\tz: -632.5695169850264\n\t)\n\tassert result == expected\n}\n\npub fn test_get_magnet_dist() {\n\tresult := params_test_mock_params.get_magnet_dist(params_test_mock_tetha, params_test_mock_state)\n\texpected := 0.07993696666249227\n\tassert result == expected\n}\n\npub fn test_get_magnet1_force() {\n\tresult := params_test_mock_params.get_magnet1_force(params_test_mock_state)\n\texpected := vector(\n\t\tx: 1310.8545084099674\n\t\ty: 575.0062553126633\n\t\tz: -632.5695169850262\n\t)\n\tassert result == expected\n}\n\npub fn test_get_magnet2_force() {\n\tresult := params_test_mock_params.get_magnet2_force(params_test_mock_state)\n\texpected := vector(\n\t\tx: -157.4572297692556\n\t\ty: 1422.736432604726\n\t\tz: -632.5695169850264\n\t)\n\tassert result == expected\n}\n\npub fn test_get_magnet3_force() {\n\tresult := params_test_mock_params.get_magnet3_force(params_test_mock_state)\n\texpected := vector(\n\t\tx: -1710.46541088048\n\t\ty: -2962.612996234165\n\t\tz: -6871.632889552589\n\t)\n\tassert result == expected\n}\n\npub fn test_get_tension_force() {\n\tresult := params_test_mock_params.get_tension_force(params_test_mock_state, vector(\n\t\tx: 0.0\n\t\ty: 0.0\n\t\tz: 0.0\n\t))\n\texpected := vector(x: 0.0, y: 0.0, z: 0.0)\n\tassert result == expected\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/runner.v",
    "content": "module sim\n\nimport benchmark\nimport term\n\npub type SimRequestHandler = fn (request &SimRequest) !\n\npub type SimStartHandler = fn () !\n\npub type SimFinishHandler = fn () !\n\npub const default_width = 600\npub const default_height = 600\n\n@[params]\npub struct GridSettings {\npub:\n\twidth  int = default_width\n\theight int = default_height\n}\n\npub fn new_grid_settings(settings GridSettings) GridSettings {\n\treturn GridSettings{\n\t\t...settings\n\t}\n}\n\n@[params]\npub struct RunnerSettings {\npub:\n\tgrid       GridSettings\n\ton_request SimRequestHandler = unsafe { nil }\n\ton_start   SimStartHandler   = unsafe { nil }\n\ton_finish  SimFinishHandler  = unsafe { nil }\n}\n\npub fn run(params SimParams, settings RunnerSettings) {\n\theight := settings.grid.height\n\twidth := settings.grid.width\n\n\tif !isnil(settings.on_start) {\n\t\tsettings.on_start() or {\n\t\t\tlog(@MOD + '.' + @FN + ': Simulation start handler failed. Error ${err}')\n\t\t}\n\t}\n\n\tmut index := 0\n\tlog('')\n\n\tmut bmark := benchmark.new_benchmark()\n\tfor y in 0 .. height {\n\t\t$if verbose ? {\n\t\t\tterm.clear_previous_line()\n\t\t}\n\t\tlog(@MOD + '.' + @FN + ': y: ${y + 1}')\n\t\tfor x in 0 .. width {\n\t\t\tbmark.step()\n\t\t\t// setup state conditions\n\t\t\tposition := vector(\n\t\t\t\tx: 0.1 * ((f64(x) - 0.5 * f64(width - 1)) / f64(width - 1))\n\t\t\t\ty: 0.1 * ((f64(y) - 0.5 * f64(height - 1)) / f64(height - 1))\n\t\t\t\tz: 0.0\n\t\t\t)\n\t\t\tvelocity := vector(x: 0, y: 0, z: 0)\n\n\t\t\tmut state := new_state(\n\t\t\t\tposition: position\n\t\t\t\tvelocity: velocity\n\t\t\t)\n\n\t\t\tstate.satisfy_rope_constraint(params)\n\t\t\trequest := &SimRequest{\n\t\t\t\tid:     index\n\t\t\t\tstate:  state\n\t\t\t\tparams: params\n\t\t\t}\n\t\t\tsettings.on_request(request) or {\n\t\t\t\tlog(@MOD + '.' + @FN + ': request handler failed. Error ${err}')\n\t\t\t\tbmark.fail()\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tindex++\n\t\t\tbmark.ok()\n\t\t}\n\t}\n\tbmark.stop()\n\tprintln(bmark.total_message(@FN))\n\n\tif !isnil(settings.on_finish) {\n\t\tsettings.on_finish() or {\n\t\t\tlog(@MOD + '.' + @FN + ': Simulation stop handler failed. Error ${err}')\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/sim.v",
    "content": "module sim\n\npub struct SimState {\npub mut:\n\tposition Vector3D\n\tvelocity Vector3D\n\taccel    Vector3D\n}\n\npub fn new_state(state SimState) SimState {\n\treturn SimState{\n\t\t...state\n\t}\n}\n\npub fn (mut state SimState) satisfy_rope_constraint(params SimParams) {\n\tmut rope_vector := params.get_rope_vector(state)\n\trope_vector = rope_vector.scale(params.rope_length / rope_vector.norm())\n\tstate.position = vector(z: params.rope_length) + rope_vector\n}\n\npub fn (mut state SimState) increment(delta_t f64, params SimParams) {\n\t// 1. add up all forces\n\t// 2. get an acceleration\n\t// 3. add to velocity\n\t// 4. ensure rope constraint is satisfied\n\n\t// sum up all forces\n\tforces_sum := params.get_forces_sum(state)\n\n\t// get the acceleration\n\taccel := forces_sum.scale(1.0 / params.bearing_mass)\n\tstate.accel = accel\n\n\t// update the velocity\n\tstate.velocity = state.velocity + accel.scale(delta_t)\n\n\t// update the position\n\tstate.position = state.position + state.velocity.scale(delta_t)\n\n\t// ensure the position satisfies rope constraint\n\tstate.satisfy_rope_constraint(params)\n}\n\npub fn (state SimState) done() bool {\n\treturn state.velocity.norm() < 0.05 && state.accel.norm() < 0.01\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/sim_test.v",
    "content": "module sim\n\nconst sim_test_mock_params = SimParams{\n\trope_length:     0.25\n\tbearing_mass:    0.03\n\tmagnet_spacing:  0.05\n\tmagnet_height:   0.03\n\tmagnet_strength: 10\n\tgravity:         4.9\n}\nconst sim_test_mock_state = SimState{\n\tposition: vector(\n\t\tx: -0.016957230930171364\n\t\ty: -0.02937078552673521\n\t\tz: 0.002311063475327252\n\t)\n\tvelocity: vector(\n\t\tx: -7.251158929833104\n\t\ty: -12.559375680227724\n\t\tz: -105.91539687686381\n\t)\n\taccel:    vector(\n\t\tx: -8.337034766251843e-11\n\t\ty: -2.842170943040401e-10\n\t\tz: 1.2126596023639044e-10\n\t)\n}\n\npub fn test_satisfy_rope_constraint() {\n\tmut state := SimState{\n\t\t...sim_test_mock_state\n\t}\n\n\tstate.satisfy_rope_constraint(sim_test_mock_params)\n\tassert state.position.x == -0.016957230930171364\n\tassert state.position.y == -0.02937078552673521\n\tassert state.position.z == 0.002311063475327252\n\tassert state.velocity.x == -7.251158929833104\n\tassert state.velocity.y == -12.559375680227724\n\tassert state.velocity.z == -105.91539687686381\n\tassert state.accel.x == -8.337034766251843e-11\n\tassert state.accel.y == -2.842170943040401e-10\n\tassert state.accel.z == 1.2126596023639044e-10\n}\n\npub fn test_increment() {\n\tmut state := SimState{\n\t\t...sim_test_mock_state\n\t}\n\n\tdelta_t := 0.0005\n\tstate.increment(delta_t, sim_test_mock_params)\n\tassert state.position.x == -0.016957230930171364\n\tassert state.position.y == -0.02937078552673524\n\tassert state.position.z == 0.0023110634753272796\n\tassert state.velocity.x == -7.251158929833047\n\tassert state.velocity.y == -12.559375680227637\n\tassert state.velocity.z == -105.9153968768638\n\tassert state.accel.x == 1.1368683772161604e-10\n\tassert state.accel.y == 1.7431981783981126e-10\n\tassert state.accel.z == 3.031649005909761e-11\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/vec.v",
    "content": "module sim\n\nimport math\n\n// Vector3D is a 3D vector\npub struct Vector3D {\npub:\n\tx f64\n\ty f64\n\tz f64\n}\n\n// vector creates a Vector3D passing x,y,z as parameters\npub fn vector(data Vector3D) Vector3D {\n\treturn Vector3D{\n\t\t...data\n\t}\n}\n\n// addition\npub fn (v Vector3D) + (v2 Vector3D) Vector3D {\n\treturn Vector3D{\n\t\tx: v.x + v2.x\n\t\ty: v.y + v2.y\n\t\tz: v.z + v2.z\n\t}\n}\n\n// dot product\npub fn (v Vector3D) * (v2 Vector3D) f64 {\n\treturn (v.x * v2.x) + (v.y * v2.y) + (v.z * v2.z)\n}\n\n// scale gets a scaled vector\npub fn (v Vector3D) scale(scalar f64) Vector3D {\n\treturn Vector3D{\n\t\tx: v.x * scalar\n\t\ty: v.y * scalar\n\t\tz: v.z * scalar\n\t}\n}\n\n// norm_squared returns the square of the norm of the vector\npub fn (v Vector3D) norm_squared() f64 {\n\treturn v * v\n}\n\n// norm returns the norm of the vector\npub fn (v Vector3D) norm() f64 {\n\treturn math.sqrt(v.norm_squared())\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/vec_test.v",
    "content": "module sim\n\nfn test_add() {\n\tv := vector(\n\t\tx: -0.016957230930171364\n\t\ty: -0.02937078552673521\n\t\tz: 0.002311063475327252\n\t)\n\tresult := v + v\n\texpected := vector(\n\t\tx: -0.03391446186034273\n\t\ty: -0.05874157105347042\n\t\tz: 0.004622126950654504\n\t)\n\tassert result == expected\n}\n\nfn test_dot() {\n\tv := vector(\n\t\tx: -0.016957230930171364\n\t\ty: -0.02937078552673521\n\t\tz: 0.002311063475327252\n\t)\n\tresult := v * v\n\texpected := 0.0011555317376636305\n\tassert result == expected\n}\n\nfn test_scale() {\n\tv := vector(\n\t\tx: -0.016957230930171364\n\t\ty: -0.02937078552673521\n\t\tz: 0.002311063475327252\n\t)\n\tresult := v.scale(2.0)\n\texpected := vector(\n\t\tx: -0.03391446186034273\n\t\ty: -0.05874157105347042\n\t\tz: 0.004622126950654504\n\t)\n\tassert result == expected\n}\n\nfn test_norm_squared() {\n\tv := vector(\n\t\tx: -0.016957230930171364\n\t\ty: -0.02937078552673521\n\t\tz: 0.002311063475327252\n\t)\n\tresult := v.norm_squared()\n\texpected := 0.0011555317376636305\n\tassert result == expected\n}\n\nfn test_norm() {\n\tv := vector(\n\t\tx: -0.016957230930171364\n\t\ty: -0.02937078552673521\n\t\tz: 0.002311063475327252\n\t)\n\tresult := v.norm()\n\texpected := 0.033993113091678295\n\tassert result == expected\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/worker.v",
    "content": "module sim\n\nimport math\nimport benchmark\n\nconst max_iterations = 1000\nconst simulation_delta_t = 0.0005\n\npub struct SimRequest {\npub:\n\tparams SimParams\n\tstate  SimState\n\tid     int\n}\n\npub struct SimResult {\n\tstate SimState\npub:\n\tid               int\n\tmagnet1_distance f64\n\tmagnet2_distance f64\n\tmagnet3_distance f64\n}\n\npub fn sim_worker(id int, request_chan chan &SimRequest, result_channels []chan &SimResult) {\n\tmut bmark := benchmark.new_benchmark()\n\tfor {\n\t\trequest := <-request_chan or { break }\n\t\tbmark.step()\n\t\tresult := compute_result(request)\n\t\tfor ch in result_channels {\n\t\t\tch <- result\n\t\t}\n\t\tbmark.ok()\n\t}\n\tbmark.stop()\n\tprintln(bmark.total_message(@FN + ': worker ${id}'))\n}\n\npub fn compute_result(request SimRequest) &SimResult {\n\tmut state := request.state\n\tparams := request.params\n\n\tfor _ in 0 .. max_iterations {\n\t\tstate.increment(simulation_delta_t, params)\n\t\tif state.done() {\n\t\t\tprintln('done!')\n\t\t\tbreak\n\t\t}\n\t}\n\n\tm1_dist := params.get_magnet_dist(0, state)\n\tm2_dist := params.get_magnet_dist(2.0 * math.pi / 3.0, state)\n\tm3_dist := params.get_magnet_dist(4.0 * math.pi / 3.0, state)\n\n\tid := request.id\n\n\treturn &SimResult{\n\t\tid:               id\n\t\tstate:            state\n\t\tmagnet1_distance: m1_dist\n\t\tmagnet2_distance: m2_dist\n\t\tmagnet3_distance: m3_dist\n\t}\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/modules/sim/worker_test.v",
    "content": "module sim\n\nconst worker_test_mock_params = SimParams{\n\trope_length:     0.25\n\tbearing_mass:    0.03\n\tmagnet_spacing:  0.05\n\tmagnet_height:   0.03\n\tmagnet_strength: 10\n\tgravity:         4.9\n}\nconst worker_test_mock_state = SimState{\n\tposition: vector(\n\t\tx: -0.016957230930171364\n\t\ty: -0.02937078552673521\n\t\tz: 0.002311063475327252\n\t)\n\tvelocity: vector(\n\t\tx: -7.251158929833104\n\t\ty: -12.559375680227724\n\t\tz: -105.91539687686381\n\t)\n\taccel:    vector(\n\t\tx: -8.337034766251843e-11\n\t\ty: -2.842170943040401e-10\n\t\tz: 1.2126596023639044e-10\n\t)\n}\n\nfn test_compute_result() {\n\trequest := SimRequest{\n\t\tid:     0\n\t\tparams: worker_test_mock_params\n\t\tstate:  worker_test_mock_state\n\t}\n\texpected_state := SimState{\n\t\tposition: vector(\n\t\t\tx: -0.01695723093017135\n\t\t\ty: -0.029370785526735183\n\t\t\tz: 0.002311063475327252\n\t\t)\n\t\tvelocity: vector(\n\t\t\tx: -7.251158929831753\n\t\t\ty: -12.55937568022536\n\t\t\tz: -105.91539687684447\n\t\t)\n\t\taccel:    vector(\n\t\t\tx: -1.1368683772161603e-11\n\t\t\ty: -1.5916157281026244e-10\n\t\t\tz: 0\n\t\t)\n\t}\n\texpected := &SimResult{\n\t\tstate:            expected_state\n\t\tid:               0\n\t\tmagnet1_distance: 0.07993696666249225\n\t\tmagnet2_distance: 0.07993696666249224\n\t\tmagnet3_distance: 0.03609361938278008\n\t}\n\tresult := compute_result(request)\n\tassert result == expected\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/parallel.v",
    "content": "module main\n\nimport benchmark\nimport sim\nimport sim.args as simargs\nimport sim.img\n\nfn main() {\n\targs := simargs.parse_args()! as simargs.ParallelArgs\n\n\timg_settings := img.image_settings_from_grid(args.grid)\n\n\twidth := img_settings.width\n\theight := img_settings.height\n\ttotal_pixels := width * height\n\n\trequest_chan := chan &sim.SimRequest{cap: args.workers}\n\tresult_chan := chan &sim.SimResult{cap: args.workers}\n\n\tmut writer := img.ppm_writer_for_fname(args.filename, img_settings)!\n\tmut image_writer := img.new_image_writer(mut writer, img_settings)\n\n\tmut workers := []thread{cap: args.workers}\n\tmut bmark := benchmark.start()\n\n\tdefer {\n\t\trequest_chan.close()\n\t\tsim.log('Waiting for workers to finish')\n\t\tworkers.wait()\n\t\tresult_chan.close()\n\t\tbmark.measure(@FN)\n\t\tsim.log('Closing writer file')\n\t\twriter.close()\n\t\tsim.log('Done!')\n\t}\n\n\tfor id in 0 .. args.workers {\n\t\tworkers << spawn sim.sim_worker(id, request_chan, [result_chan])\n\t}\n\n\tmut x := 0\n\tmut y := 0\n\tmut request_index := 0\n\n\tfor {\n\t\t// setup state conditions\n\t\tposition := sim.vector(\n\t\t\tx: 0.1 * ((f64(x) - 0.5 * f64(width - 1)) / f64(width - 1))\n\t\t\ty: 0.1 * ((f64(y) - 0.5 * f64(height - 1)) / f64(height - 1))\n\t\t\tz: 0.0\n\t\t)\n\t\tvelocity := sim.vector(x: 0, y: 0, z: 0)\n\n\t\tmut state := sim.new_state(\n\t\t\tposition: position\n\t\t\tvelocity: velocity\n\t\t)\n\n\t\tstate.satisfy_rope_constraint(args.params)\n\t\trequest := &sim.SimRequest{\n\t\t\tid:     request_index\n\t\t\tstate:  state\n\t\t\tparams: args.params\n\t\t}\n\t\tselect {\n\t\t\tresult := <-result_chan {\n\t\t\t\timage_writer.handle(result) or { break }\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif request.id == total_pixels {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\trequest_chan <- request\n\t\t\t\tx++\n\t\t\t\tif x == width {\n\t\t\t\t\tx = 0\n\t\t\t\t\ty++\n\t\t\t\t\tsim.log('y: ${y + 1}')\n\t\t\t\t}\n\t\t\t\trequest_index++\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/parallel_with_iw.v",
    "content": "module main\n\nimport benchmark\nimport sim\nimport sim.args as simargs\nimport sim.img\n\nfn main() {\n\targs := simargs.parse_args(extra_workers: 1)! as simargs.ParallelArgs\n\n\timg_settings := img.image_settings_from_grid(args.grid)\n\n\trequest_chan := chan &sim.SimRequest{cap: args.workers}\n\tresult_chan := chan &sim.SimResult{cap: args.workers}\n\n\tmut writer := img.ppm_writer_for_fname(args.filename, img_settings)!\n\n\tmut workers := []thread{cap: args.workers + 1}\n\tmut bmark := benchmark.start()\n\n\tdefer {\n\t\timage_worker := workers.pop()\n\t\trequest_chan.close()\n\t\tsim.log('Waiting for workers to finish')\n\t\tworkers.wait()\n\t\tresult_chan.close()\n\t\tsim.log('Waiting for image writer to finish')\n\t\timage_worker.wait()\n\t\tsim.log('Workers finished!')\n\t\tbmark.measure(@FN)\n\t\tsim.log('Closing writer file')\n\t\twriter.close()\n\t\tsim.log('Done!')\n\t}\n\n\tfor id in 0 .. args.workers {\n\t\tworkers << spawn sim.sim_worker(id, request_chan, [result_chan])\n\t}\n\n\tworkers << spawn img.image_worker(mut writer, result_chan, img_settings)\n\n\thandle_request := fn [request_chan] (request &sim.SimRequest) ! {\n\t\trequest_chan <- request\n\t}\n\n\tsim.run(args.params,\n\t\tgrid:       args.grid\n\t\ton_request: sim.SimRequestHandler(handle_request)\n\t)\n}\n"
  },
  {
    "path": "examples/pendulum-simulation/sequential.v",
    "content": "module main\n\nimport benchmark\nimport sim\nimport sim.args as simargs\nimport sim.img\n\nfn main() {\n\targs := simargs.parse_args(sequential: true)! as simargs.SequentialArgs\n\n\tmut bmark := benchmark.start()\n\tdefer {\n\t\tbmark.measure(@FN)\n\t}\n\n\tmut writer := img.ppm_writer_for_fname(args.filename, img.image_settings_from_grid(args.grid))!\n\tdefer {\n\t\twriter.close()\n\t}\n\n\thandle_request := fn [mut writer] (request &sim.SimRequest) ! {\n\t\tresult := sim.compute_result(request)\n\t\tpixel := img.compute_pixel(result)\n\t\treturn writer.handle_pixel(pixel)\n\t}\n\n\tsim.run(args.params, grid: args.grid, on_request: sim.SimRequestHandler(handle_request))\n\n\twriter.write()!\n}\n"
  },
  {
    "path": "examples/pico/pico.v",
    "content": "// vtest build: !solaris\nimport json\nimport picoev\nimport picohttpparser\n\nconst port = 8089\n\nstruct Message {\n\tmessage string\n}\n\n@[inline]\nfn json_response() string {\n\tmsg := Message{\n\t\tmessage: 'Hello, World!'\n\t}\n\treturn json.encode(msg)\n}\n\n@[inline]\nfn hello_response() string {\n\treturn 'Hello, World!'\n}\n\nfn callback(_data voidptr, req picohttpparser.Request, mut res picohttpparser.Response) {\n\tif req.method == 'GET' {\n\t\tif req.path == '/t' {\n\t\t\tres.http_ok()\n\t\t\tres.header_server()\n\t\t\tres.header_date()\n\t\t\tres.plain()\n\t\t\tres.body(hello_response())\n\t\t} else if req.path == '/j' {\n\t\t\tres.http_ok()\n\t\t\tres.header_server()\n\t\t\tres.header_date()\n\t\t\tres.json()\n\t\t\tres.body(json_response())\n\t\t} else {\n\t\t\tres.http_ok()\n\t\t\tres.header_server()\n\t\t\tres.header_date()\n\t\t\tres.html()\n\t\t\tres.body('Hello Picoev!\\n')\n\t\t}\n\t} else {\n\t\tres.http_405()\n\t}\n\tres.end()\n}\n\nfn main() {\n\tprintln('Starting webserver on http://localhost:${port}/ ...')\n\tmut server := picoev.new(port: port, cb: callback)!\n\tserver.serve()\n}\n"
  },
  {
    "path": "examples/pico/raw_callback.v",
    "content": "// vtest build: !solaris\nmodule main\n\nimport net\nimport picoev\n\nconst port = 8080\n\nconst http_response = 'HTTP/1.1 200 OK\\r\\nContent-type: text/html\\r\\nContent-length: 18\\r\\n\\r\\nHello from Picoev!'\n\nfn main() {\n\tprintln('Starting webserver on http://localhost:${port}/ ...')\n\tmut pico := picoev.new(\n\t\tport:   port\n\t\traw_cb: handle_conn\n\t)!\n\tpico.serve()\n}\n\nfn handle_conn(mut pv picoev.Picoev, fd int, _events int) {\n\t// setup a nonblocking tcp connection\n\tmut conn := &net.TcpConn{\n\t\tsock:        net.tcp_socket_from_handle_raw(fd)\n\t\thandle:      fd\n\t\tis_blocking: false\n\t}\n\n\tmut buf := []u8{len: 4096}\n\t// read data from the tcp connection\n\tconn.read(mut buf) or { eprintln('could not read data from socket') }\n\n\tprintln('received data:')\n\tprintln(buf.bytestr())\n\n\tconn.write(http_response.bytes()) or { eprintln('could not write response') }\n\n\t// remove the socket from picoev's event loop and close the connection\n\tpv.close_conn(fd)\n}\n"
  },
  {
    "path": "examples/pidigits.v",
    "content": "import math.big\n\n// pi_digits calculates the digits of Pi, based on https://mail.python.org/pipermail/edu-sig/2012-December/010721.html\nfn pi_digits(count int) {\n\tmut n := count\n\tmut k, mut a, mut b, mut a1, mut b1 := big.c2, big.c4, big.c1, big.c12, big.c4\n\tmut p, mut q := k, k\n\tfor n > 0 {\n\t\tp, q, k = k * k, (big.c2 * k) + big.c1, k + big.c1\n\t\ta, b, a1, b1 = a1, b1, p * a + q * a1, p * b + q * b1\n\t\tmut d := a / b\n\t\tmut d1 := a1 / b1\n\t\tfor d == d1 {\n\t\t\tprint(d.int())\n\t\t\tn--\n\t\t\ta, a1 = big.c10 * (a % b), big.c10 * (a1 % b1)\n\t\t\td, d1 = a / b, a1 / b1\n\t\t\tif n <= 0 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\npi_digits(arguments()[1] or { '100' }.int())\nprintln('')\n"
  },
  {
    "path": "examples/poll_coindesk_bitcoin_vs_usd_rate.v",
    "content": "import log\nimport term\nimport time\nimport x.json2\nimport net.http\n\nconst url = 'https://api.coinbase.com/v2/prices/BTC-USD/spot'\n\nstruct JsonResult {\nmut:\n\tdata PriceResult\n}\n\nstruct PriceResult {\nmut:\n\tamount   f64\n\tbase     string\n\tcurrency string\n}\n\nfn main() {\n\tlog.use_stdout()\n\tmut old_rate := f64(0)\n\tfor i := u64(1); true; i++ {\n\t\tdata := http.get(url) or {\n\t\t\tlog.error('polling ${url} failed')\n\t\t\ttime.sleep(10 * time.second)\n\t\t\tcontinue\n\t\t}\n\t\tif data.status_code == 200 {\n\t\t\tres := json2.decode[JsonResult](data.body) or {\n\t\t\t\tlog.error('can not decode data: ${data.body}')\n\t\t\t\ttime.sleep(10 * time.second)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tnew_rate := res.data.amount\n\t\t\tshow_result(i, res.data, new_rate - old_rate)\n\t\t\told_rate = new_rate\n\t\t}\n\t\ttime.sleep(3 * time.second)\n\t}\n}\n\nfn show_result(i u64, res PriceResult, delta f64) {\n\tif delta == 0 {\n\t\treturn\n\t}\n\tmut sdelta := '${delta:10.3f}'\n\tcolor := if delta > 0 {\n\t\tterm.green\n\t} else if delta == 0 {\n\t\tterm.white\n\t} else {\n\t\tterm.red\n\t}\n\tcdelta := term.colorize(color, sdelta)\n\tlog.info('${cdelta}, ${res.amount:10.3f} USD/BTC, cycle: ${i:5}')\n}\n"
  },
  {
    "path": "examples/primes.v",
    "content": "import math { log }\n\nn := arguments()[1] or { '10' }.int()\nsz := if n < 15 {\n\t50\n} else {\n\tln := log(f64(n))\n\tint(f64(n) * (ln + log(ln))) + 1\n}\nmut sieve := []bool{len: sz}\nfor i := 2; i * i < sz; i++ {\n\tif !sieve[i] {\n\t\tfor j := i * i; j < sz; j += i {\n\t\t\tsieve[j] = true\n\t\t}\n\t}\n}\nmut c := 0\nfor i := 2; c < n && i < sz; i++ {\n\tif !sieve[i] {\n\t\tprintln(i)\n\t\tc++\n\t}\n}\n"
  },
  {
    "path": "examples/process/command.v",
    "content": "module main\n\nimport os\n\n// basic example which shows how to use the Command function\n\nfn exec(path string) string {\n\tmut out := ''\n\tmut line := ''\n\tmut cmd := os.Command{\n\t\tpath: path\n\t}\n\tcmd.start() or { panic(err) }\n\n\tfor {\n\t\tline = cmd.read_line()\n\t\tprintln(line)\n\t\tout += line\n\t\tif cmd.eof {\n\t\t\treturn out\n\t\t}\n\t}\n\treturn out\n}\n\nfn main() {\n\tmut out := ''\n\texec(\"bash -c 'find /tmp/'\")\n\tout = exec('echo to stdout')\n\tout = exec('echo to stderr 1>&2')\n\tprintln(\"'${out}'\")\n\t// THIS DOES NOT WORK, is error, it goes to stderror of the command I run\n\tassert out == 'to stderr'\n}\n"
  },
  {
    "path": "examples/process/execve.v",
    "content": "import os\n\n// NOTE: `execve` executes a new child process, in place of the current process.\n// Therefore, only the topmost example will be executed when it's not commented out.\nfn main() {\n\t// Passes only an array of args.\n\tos.execve(os.find_abs_path_of_executable('ls')!, ['-lh', '-s'], [])!\n\n\t// Considers args that would need to be passed within quotes. E.g.: `bash -c \"ls -lh\"`.\n\tos.execve(os.find_abs_path_of_executable('bash')!, ['-c', 'ls -lah -s'], [])!\n\n\t// Passes an environment variable that affects the commands output.\n\tos.execve(os.find_abs_path_of_executable('man')!, ['true'], ['MANWIDTH=60'])!\n}\n"
  },
  {
    "path": "examples/process/monitor_for_file_changes_with_inotifywait.v",
    "content": "import os\n\nos.find_abs_path_of_executable('inotifywait') or {\n\teprintln('This program uses the inotifywait executable, which is missing.')\n\texit(1)\n}\nmut cmd := os.start_new_command('inotifywait -q -r -m -e move,modify,create,delete .')!\ndefer { cmd.close() or {} }\nfor !cmd.eof {\n\tline := cmd.read_line()\n\tif line == '' && cmd.eof {\n\t\tcontinue\n\t}\n\teprintln('> notification: ${line}')\n}\n"
  },
  {
    "path": "examples/process/process_script.v",
    "content": "module main\n\nimport os\n\n// a test where we execute a bash script but work around where we put script in bash inside bash\n\nfn exec(path string, redirect bool) {\n\tmut line := ''\n\tmut line_err := ''\n\tmut cmd := os.new_process('/bin/bash')\n\n\tif redirect {\n\t\tcmd.set_args(['-c', '/bin/bash /tmp/test.sh 2>&1'])\n\t} else {\n\t\tcmd.set_args([path])\n\t}\n\n\tcmd.set_redirect_stdio()\n\tcmd.run()\n\tfor cmd.is_alive() {\n\t\tline = cmd.stdout_read()\n\t\tprintln('STDOUT: ${line}')\n\n\t\tif !redirect {\n\t\t\tline_err = cmd.stderr_read()\n\t\t\tprintln('STDERR: ${line_err}')\n\t\t}\n\t}\n\tif cmd.code > 0 {\n\t\tprintln('ERROR:')\n\t\tprintln(cmd)\n\t\t// println(cmd.stderr_read())\n\t}\n}\n\nfn main() {\n\tscript := '\necho line 1\n#will use some stderr now\necho redirect 1 to 2  1>&2\necho line 3\n'\n\n\tos.write_file('/tmp/test.sh', script) or { panic(err) }\n\t// os.chmod(\"/tmp/test.sh\",0o700) //make executable\n\n\t// this will work because stderr/stdout are smaller than 4096 chars, once larger there can be deadlocks\n\t// in other words this can never work reliably without being able to check if there is data on stderr or stdout\n\texec('/tmp/test.sh', false)\n\n\t// this will always work\n\texec('/tmp/test.sh', true)\n}\n"
  },
  {
    "path": "examples/process/wrapping_interactive_python.v",
    "content": "import os\nimport time\nimport term\n\npython_exe := os.find_abs_path_of_executable('python') or {\n\teprintln('This example needs a python executable in your PATH. Please install Python to see it in action.')\n\texit(1)\n}\nmut p := os.new_process(python_exe)\ndefer {\n\tdump(p.code)\n\tp.close()\n\tp.wait()\n}\n// The Python flags here, are needed to reduce clutter and buffering.\n// See https://docs.python.org/3/using/cmdline.html\np.set_args(['-i', '-q', '-u'])\np.set_redirect_stdio()\np.run()\ndump(p.pid)\nprintln('This is a simple V wrapper/shell for the Python interpreter.')\nprintln('Try typing some python code here, or type `bye` to end your session:')\nfor p.is_alive() {\n\t// check if there is any input from the user (it does not block, if there is not):\n\tif os.fd_is_pending(0) {\n\t\tcmd := os.get_raw_line()\n\t\tif cmd.len == 0 {\n\t\t\tprintln('closed stdin detected, perhaps due to Ctrl-D...exiting')\n\t\t\tbreak\n\t\t}\n\t\tif cmd.trim_space() == 'bye' {\n\t\t\tprintln('Goodbye...')\n\t\t\tbreak\n\t\t}\n\t\tp.stdin_write(cmd)\n\t}\n\tif oline := p.pipe_read(.stdout) {\n\t\tprint(term.bright_yellow('python stdout: ') + term.bold(oline))\n\t}\n\tif eline := p.pipe_read(.stderr) {\n\t\teprint(term.red('python stderr: ') + eline)\n\t}\n\ttime.sleep(20 * time.millisecond)\n}\n"
  },
  {
    "path": "examples/process/write_and_read_from_a_bash_child_process.v",
    "content": "module main\n\n// This example shows how to communicate with a child process (`bash` in this case), by sending\n// commands to its stdin pipe, and reading responses from its stdout and stderr pipes.\n// Note, you can use `if p.is_pending(.stdout) {` and `if p.is_pending(.stderr) {`, to check if\n// there is available data in the pipes, without having to block in your main loop, if the data\n// is missing or just not available yet.\nimport os\nimport time\n\nconst tmp_folder = os.join_path(os.temp_dir(), 'process_folder')\n\nconst max_txt_files = 20\n\nfn exec(cmd string) (string, int, string) {\n\tmut out := []string{}\n\tmut er := []string{}\n\tmut rc := 0\n\n\tmut p := os.new_process('/bin/bash')\n\tp.set_redirect_stdio()\n\tp.run()\n\n\tp.stdin_write('echo \"START         \" && sleep 0.1 && ${cmd};\\n')\n\tp.stdin_write('ECODE=\\$?;\\n')\n\tp.stdin_write('sleep 0.1;\\n')\n\tp.stdin_write('exit \\$ECODE;\\n')\n\n\t// Note, that you can also ensure that `bash` will exit, when the command finishes,\n\t// by closing its stdin pipe. In the above example, that is not needed however, since\n\t// the last `exit` command, will make it quit as well.\n\t// os.fd_close(p.stdio_fd[0])\n\n\tfor p.is_alive() {\n\t\tif data := p.pipe_read(.stderr) {\n\t\t\teprintln('p.pipe_read .stderr, len: ${data.len:4} | data: `${data#[0..10]}`...')\n\t\t\ter << data\n\t\t}\n\t\tif data := p.pipe_read(.stdout) {\n\t\t\teprintln('p.pipe_read .stdout, len: ${data.len:4} | data: `${data#[0..10]}`...')\n\t\t\tout << data\n\t\t}\n\t\t// avoid a busy loop, by sleeping a bit between each iteration\n\t\ttime.sleep(2 * time.millisecond)\n\t}\n\n\t// the process finished, slurp all the remaining data in the pipes:\n\tout << p.stdout_slurp()\n\ter << p.stderr_slurp()\n\tp.close()\n\tp.wait()\n\n\tif p.code > 0 {\n\t\teprintln('----------------------------------------------------------')\n\t\teprintln('COMMAND: ${cmd}')\n\t\teprintln('STDOUT:\\n${out}')\n\t\teprintln('STDERR:\\n${er}')\n\t\teprintln('----------------------------------------------------------')\n\t\trc = 1\n\t}\n\n\treturn out.join(''), rc, er.join('')\n}\n\nfn main() {\n\tmut out := ''\n\tmut er := ''\n\tmut ecode := 0\n\n\t// prepare some files in a temporary folder\n\tdefer {\n\t\tos.rmdir_all(tmp_folder) or {}\n\t}\n\tos.mkdir_all(tmp_folder) or {}\n\tfor i in 0 .. max_txt_files {\n\t\tos.write_file(os.join_path(tmp_folder, '${i}.txt'), '${i}\\n${i}\\n')!\n\t}\n\n\tout, ecode, er = exec(\"find ${os.quoted_path(tmp_folder)} ; sleep 0.1; find ${os.quoted_path(tmp_folder)} ; echo '******'\")\n\tassert out.ends_with('******\\n')\n\tassert er == ''\n\n\tout, ecode, er = exec('echo to stdout')\n\tassert out.contains('to stdout')\n\tassert er == ''\n\n\tout, ecode, er = exec('echo to stderr 1>&2')\n\tassert out.starts_with('START')\n\tassert er.contains('to stderr')\n\n\tout, ecode, er = exec('ls /sssss')\n\tassert out.starts_with('START')\n\tassert er != ''\n\tassert ecode > 0 // THIS STILL GIVES AN ERROR !\n\n\tprintln('test ok stderr & stdout is indeed redirected, ecode: ${ecode}')\n}\n"
  },
  {
    "path": "examples/quadtree_demo/quadtree_demo.v",
    "content": "module main\n\nimport datatypes\nimport gg\nimport time\nimport math\nimport rand\n\nconst win_width = 1340\nconst win_height = 640\nconst timer_period = 40 * time.millisecond // defaulted at 25 fps\n\nconst font_small = gg.TextCfg{\n\tcolor: gg.black\n\tsize:  20\n}\nconst font_large = gg.TextCfg{\n\tcolor: gg.black\n\tsize:  40\n}\n\nstruct App {\nmut:\n\tgg         &gg.Context\n\tqt         datatypes.Quadtree\n\tplayers    []datatypes.AABB\n\tparticles  []Particle\n\tretrieveds []datatypes.AABB\n\tnodes      []datatypes.Quadtree\n\twidth      f64 = 1340\n\theight     f64 = 640\n}\n\nstruct Particle {\nmut:\n\tpmt   datatypes.AABB\n\tspeed f64\n\tangle f64\n}\n\nfn (mut p Particle) update() {\n\tp.pmt.x += p.speed * math.cos(p.angle * math.pi / 180)\n\tp.pmt.y += p.speed * math.sin(p.angle * math.pi / 180)\n\n\tif p.pmt.x < 0 {\n\t\tp.pmt.x = 0\n\t\tp.speed = -p.speed\n\t\tp.angle = -p.angle\n\t}\n\tif p.pmt.x > 1340 {\n\t\tp.pmt.x = 1340\n\t\tp.speed = -p.speed\n\t\tp.angle = -p.angle\n\t}\n\tif p.pmt.y < 0 {\n\t\tp.pmt.y = 0\n\t\tp.speed = -p.speed\n\t\tp.angle = 180 - p.angle\n\t}\n\tif p.pmt.y > 640 {\n\t\tp.pmt.y = 640\n\t\tp.speed = -p.speed\n\t\tp.angle = 180 - p.angle\n\t}\n}\n\nfn (mut app App) start() {\n\tapp.players << datatypes.AABB{1200 * rand.f64(), 500 * rand.f64(), 20, 20}\n\tapp.insert_particles()\n\tfor mut particle in app.particles {\n\t\tparticle.speed = 10 * rand.f64()\n\t\tparticle.angle = 200 * rand.f64()\n\t}\n\tapp.nodes << app.qt.get_nodes()\n}\n\nfn (mut app App) update() {\n\tapp.qt.clear()\n\tapp.nodes = []\n\tfor mut particle in app.particles {\n\t\tparticle.update()\n\t\tapp.qt.insert(particle.pmt)\n\t}\n\tapp.find_particles()\n\tapp.nodes << app.qt.get_nodes()\n}\n\nfn (mut app App) insert_particles() {\n\tmut grid := 10.0\n\tmut gridh := app.qt.perimeter.width / grid\n\tmut gridv := app.qt.perimeter.height / grid\n\tnum_particles := 100\n\tfor _ in 0 .. num_particles {\n\t\tmut x := rand_minmax(0, gridh) * grid\n\t\tmut y := rand_minmax(0, gridv) * grid\n\t\tmut random_particle := datatypes.AABB{\n\t\t\tx:      x\n\t\t\ty:      y\n\t\t\twidth:  rand_minmax(1, 4) * grid\n\t\t\theight: rand_minmax(1, 4) * grid\n\t\t}\n\t\tapp.particles << Particle{random_particle, 0.0, 0.0}\n\t}\n}\n\nfn (mut app App) find_particles() {\n\tapp.retrieveds = []\n\tapp.retrieveds << app.qt.retrieve(app.players[0])\n}\n\nfn main() {\n\tmut app := &App{\n\t\tgg: unsafe { nil }\n\t}\n\tapp.gg = gg.new_context(\n\t\tbg_color:      gg.white\n\t\twidth:         win_width\n\t\theight:        win_height\n\t\tcreate_window: true\n\t\twindow_title:  'Quadtree Demo'\n\t\tframe_fn:      frame\n\t\tevent_fn:      on_event\n\t\tuser_data:     app\n\t)\n\tapp.qt = app.qt.create(0, 0, 1340, 640, 8, 4, 0)\n\tapp.start()\n\tspawn app.run()\n\tapp.gg.run()\n}\n\nfn (mut app App) on_mouse_move(mouse_x f32, mouse_y f32) {\n\tfor mut player in app.players {\n\t\tplayer.x = (mouse_x / gg.window_size_real_pixels().width) * 1340\n\t\tplayer.y = (mouse_y / gg.window_size_real_pixels().height) * 640\n\t}\n}\n\nfn on_event(mut e gg.Event, mut app App) {\n\tmatch e.typ {\n\t\t.mouse_move { app.on_mouse_move(e.mouse_x, e.mouse_y) }\n\t\telse {}\n\t}\n}\n\nfn (mut app App) run() {\n\tfor {\n\t\tapp.update()\n\t\ttime.sleep(timer_period)\n\t}\n}\n\nfn frame(app &App) {\n\tapp.gg.begin()\n\tapp.draw()\n\tapp.gg.end()\n}\n\nfn (app &App) display() {\n\tfor player in app.players {\n\t\tapp.gg.draw_rect_filled(f32(player.x), f32(player.y), f32(player.width), f32(player.height),\n\t\t\tgg.black)\n\t}\n\tfor particle in app.particles {\n\t\tapp.gg.draw_rect_empty(f32(particle.pmt.x), f32(particle.pmt.y), f32(particle.pmt.width),\n\t\t\tf32(particle.pmt.height), gg.blue)\n\t}\n\tfor node in app.nodes {\n\t\tapp.gg.draw_rect_empty(f32(node.perimeter.x), f32(node.perimeter.y), f32(node.perimeter.width),\n\t\t\tf32(node.perimeter.height), gg.red)\n\t}\n\tfor retrieved in app.retrieveds {\n\t\tapp.gg.draw_rect_filled(f32(retrieved.x + 1), f32(retrieved.y + 1), f32(retrieved.width - 2),\n\t\t\tf32(retrieved.height - 2), gg.green)\n\t}\n\tapp.gg.draw_text(1200, 25, 'Nodes: ${app.nodes.len}', font_small)\n\tapp.gg.draw_text(1200, 50, 'Particles: ${app.particles.len}', font_small)\n}\n\nfn (app &App) draw() {\n\tapp.display()\n}\n\nfn rand_minmax(min f64, max f64) f64 {\n\tmut val := min + (rand.f64() * (max - min))\n\treturn val\n}\n"
  },
  {
    "path": "examples/quick_sort.v",
    "content": "import rand\n\nconst gen_len = 1000 // how many random numbers to generate\n\nconst gen_max = 10000\n\nfn main() {\n\tmut arr := []int{}\n\tfor _ in 0 .. gen_len {\n\t\tarr << rand.intn(gen_max) or { 0 }\n\t}\n\tprintln('length of random array is ${arr.len}')\n\tprintln('before quick sort whether array is sorted: ${is_sorted[int](arr)}')\n\tquick_sort[int](mut arr, 0, arr.len - 1)\n\tprintln('after quick sort whether array is sorted: ${is_sorted[int](arr)}')\n}\n\nfn quick_sort[T](mut arr []T, l int, r int) {\n\tif l >= r {\n\t\treturn\n\t}\n\tmut sep := l // what is sep: [...all_value<arr[sep]...sep...all_value>=arr[sep]...]\n\tfor i in l + 1 .. r + 1 {\n\t\tif arr[i] < arr[l] {\n\t\t\tsep++\n\t\t\tarr[i], arr[sep] = arr[sep], arr[i]\n\t\t}\n\t}\n\tarr[l], arr[sep] = arr[sep], arr[l]\n\tquick_sort[T](mut arr, l, sep - 1)\n\tquick_sort[T](mut arr, sep + 1, r)\n}\n\nfn is_sorted[T](arr []T) bool {\n\tfor i in 0 .. arr.len - 1 {\n\t\tif arr[i] > arr[i + 1] {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "examples/random_ips.v",
    "content": "import rand\n\nfn main() {\n\tfor _ in 0 .. 10 {\n\t\tprintln('${rand.intn(255)!}.${rand.intn(255)!}.${rand.intn(255)!}.${rand.intn(255)!}')\n\t}\n}\n"
  },
  {
    "path": "examples/readdir.v",
    "content": "import os\n\n// Example usage of os.ls (in the form of top-level statements)\nprintln('readdir example using os.ls')\n\nentries := os.ls(os.home_dir()) or { [] }\n\nfor entry in entries {\n\tif os.is_dir(os.join_path(os.home_dir(), entry)) {\n\t\tprintln('dir: ${entry}')\n\t} else {\n\t\tprintln('file: ${entry}')\n\t}\n}\n"
  },
  {
    "path": "examples/readline/readline.v",
    "content": "module main\n\nimport readline\n\nfn main() {\n\trun() or { panic('${err}') }\n}\n\nfn run() ! {\n\t$if windows {\n\t\teprintln('skipping on Windows, since raw mode and read_char are not yet implemented.')\n\t\treturn\n\t} $else {\n\t\t// Explicit comptime block for other OSes than Windows is required to not break compilation on Windows.\n\t\tmut r := readline.Readline{}\n\t\tr.enable_raw_mode_nosig()\n\t\tdefer {\n\t\t\tr.disable_raw_mode()\n\t\t}\n\n\t\tfor {\n\t\t\tentered := r.read_char()!\n\t\t\tif entered == `q` {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tprintln('got ${entered}')\n\t\t}\n\t\tprintln('Goodbye.')\n\t}\n}\n"
  },
  {
    "path": "examples/readline/readline_test.v",
    "content": "import os\n\n// Expect has to be installed for the test.\nconst expect_exe = os.find_abs_path_of_executable('expect') or {\n\teprintln('skipping test, since expect is missing')\n\texit(0)\n}\n// Directory that contains the Expect scripts used in the test.\nconst expect_tests_path = os.join_path(@VMODROOT, 'examples', 'readline', 'tests')\n\nfn test_password_input() {\n\tcorrect := os.execute(os.join_path(expect_tests_path, 'readline.expect'))\n\tassert correct.exit_code == 0, correct.output\n\n\tsend_a := 'a'\n\texpect_a := 'got 97' // readline output for `a`\n\ta_res := os.execute('${os.join_path(expect_tests_path, 'readline_from_expect_arg.expect')} ${send_a} \"${expect_a}\"')\n\tassert a_res.exit_code == 0, a_res.output\n\n\tsend_b := 'b'\n\tb_res := os.execute('${os.join_path(expect_tests_path, 'readline_from_expect_arg.expect')} ${send_b} \"${expect_a}\"')\n\tassert b_res.exit_code == 1, b_res.output\n\tassert b_res.output.contains('got 98')\n}\n"
  },
  {
    "path": "examples/readline/tests/readline.expect",
    "content": "#!/usr/bin/env expect\n\nset timeout 3\nset v_root [exec sh -c \"git rev-parse --show-toplevel\"]\n\nspawn $v_root/v run $v_root/examples/readline/readline.v\n\nsend \"a\"\nexpect \"got 97\" {} timeout { exit 1 }\nsend \"1\"\nexpect \"got 49\" {} timeout { exit 1 }\nsend \"q\"\nexpect \"Goodbye.\" {} timeout { exit 1 }\n\nexpect eof\n"
  },
  {
    "path": "examples/readline/tests/readline_from_expect_arg.expect",
    "content": "#!/usr/bin/env expect\n\nset timeout 3\nset v_root [exec sh -c \"git rev-parse --show-toplevel\"]\n# Use input arguments for send and expect.\nset send_ [lindex $argv 0]\nset expect_ [lindex $argv 1]\n\nspawn $v_root/v run $v_root/examples/readline/readline.v\n\nsend $send_\nexpect $expect_ {} timeout { exit 1 }\n\nexpect eof\n"
  },
  {
    "path": "examples/regex/pcre.v",
    "content": "import regex.pcre\n\n// Since 2026/02/08, regex.pcre is built-in and implemented in pure V.\n// The same example will compile and run with the C wrapper of the PCRE library\n// too, but you will need to `import pcre` instead.\n\nfn example() {\n\tr := pcre.new_regex('Match everything after this: (.+)', 0) or {\n\t\tprintln('An error occurred!')\n\t\treturn\n\t}\n\n\tm := r.match_str('Match everything after this: \"I ❤️ VLang!\"', 0, 0) or {\n\t\tprintln('No match!')\n\t\treturn\n\t}\n\n\t// m.get(0) -> Match everything after this: \"I ❤️ VLang!\"\n\t// m.get(1) -> \"I ❤️ VLang!\"'\n\t// m.get(2) -> Error!\n\twhole_match := m.get(0) or {\n\t\tprintln('We matched nothing...')\n\t\treturn\n\t}\n\n\tmatched_str := m.get(1) or {\n\t\tprintln('We matched nothing...')\n\t\treturn\n\t}\n\n\tprintln(whole_match) // Match everything after this: \"I ❤️ VLang!\"\n\tprintln(matched_str) // \"I ❤️ VLang!\"\n}\n\nfn main() {\n\texample()\n\n\tmut text := '[ an s. s! ]( wi4ki:something )\n\t[ an s. s! ]( wi4ki:something )\n\t[ an s. s! ](wiki:something)\n\t[ an s. s! ](something)dd\n\td [ an s. s! ](something ) d\n\t[  more text ]( something ) s [ something b ](something)dd\n\n\t'\n\n\t// check the regex on https://regex101.com/r/HdYya8/1/\n\n\tregex := r'(\\[[a-z\\.\\! ]*\\]\\( *\\w*\\:*\\w* *\\))*'\n\n\tr := pcre.new_regex(regex, 0) or {\n\t\tprintln('An error occurred!')\n\t\treturn\n\t}\n\n\tm := r.match_str(text, 0, 0) or {\n\t\tprintln('No match!')\n\t\treturn\n\t}\n\n\twhole_match1 := m.get(0) or {\n\t\tprintln('We matched nothing 0...')\n\t\treturn\n\t}\n\n\tprintln(whole_match1)\n\n\tprintln(m.get_all())\n}\n"
  },
  {
    "path": "examples/regex/readme.md",
    "content": "# regex\n\nThere are 2 ways to do regex:\n1. using the native module called `regex`.\n2. using an external module called `pcre`, which wraps the C library pcre.\n\n> [!NOTE]\n> You need to first do: `v install pcre`, for the `pcre` module to work.\n\nYou can find examples of both in this directory.\n"
  },
  {
    "path": "examples/regex/regex_example.v",
    "content": "/**********************************************************************\n* regex samples\n*\n* Copyright (c) 2019-2024 Dario Deledda. All rights reserved.\n* Use of this source code is governed by an MIT license\n* that can be found in the LICENSE file.\n*\n* This file contains a collection of regex samples\n*\n**********************************************************************/\nimport regex\n\n/*\nThis simple function converts an HTML RGB value with 3 or 6 hex digits to a u32 value,\nthis function is not optimized and it is only for didatical purpose\nexample: #A0B0CC #A9F\n*/\nfn convert_html_rgb(in_col string) u32 {\n\tmut n_digit := if in_col.len == 4 { 1 } else { 2 }\n\tmut col_mul := if in_col.len == 4 { 4 } else { 0 }\n\n\t// this is the regex query, it uses V string interpolation to customize the regex query\n\t// NOTE: if you want use escaped code you must use the r\"\" (raw) strings,\n\t//       *** please remember that V interpoaltion doesn't work on raw strings. ***\n\n\tquery := '#([a-fA-F0-9]{${n_digit}})([a-fA-F0-9]{${n_digit}})([a-fA-F0-9]{${n_digit}})'\n\n\tmut re := regex.regex_opt(query) or { panic(err) }\n\tstart, end := re.match_string(in_col)\n\tprintln('start: ${start}, end: ${end}')\n\tmut res := u32(0)\n\tif start >= 0 {\n\t\tgroup_list := re.get_group_list()\n\t\tr := ('0x' + in_col[group_list[0].start..group_list[0].end]).u32() << col_mul\n\t\tg := ('0x' + in_col[group_list[1].start..group_list[1].end]).u32() << col_mul\n\t\tb := ('0x' + in_col[group_list[2].start..group_list[2].end]).u32() << col_mul\n\t\tprintln('r: ${r} g: ${g} b: ${b}')\n\t\tres = r << 16 | g << 8 | b\n\t}\n\treturn res\n}\n\n/*\nThis function demonstrates the use of the named groups\n*/\nfn convert_html_rgb_n(in_col string) u32 {\n\tmut n_digit := if in_col.len == 4 { 1 } else { 2 }\n\tmut col_mul := if in_col.len == 4 { 4 } else { 0 }\n\n\tquery := '#(?P<red>[a-fA-F0-9]{${n_digit}})(?P<green>[a-fA-F0-9]{${n_digit}})(?P<blue>[a-fA-F0-9]{${n_digit}})'\n\n\tmut re := regex.regex_opt(query) or { panic(err) }\n\tstart, end := re.match_string(in_col)\n\tprintln('start: ${start}, end: ${end}')\n\tmut res := u32(0)\n\tif start >= 0 {\n\t\tred_s, red_e := re.get_group_bounds_by_name('red')\n\t\tr := ('0x' + in_col[red_s..red_e]).u32() << col_mul\n\n\t\tgreen_s, green_e := re.get_group_bounds_by_name('green')\n\t\tg := ('0x' + in_col[green_s..green_e]).u32() << col_mul\n\n\t\tblue_s, blue_e := re.get_group_bounds_by_name('blue')\n\t\tb := ('0x' + in_col[blue_s..blue_e]).u32() << col_mul\n\n\t\tprintln('r: ${r} g: ${g} b: ${b}')\n\t\tres = r << 16 | g << 8 | b\n\t}\n\treturn res\n}\n\nfn main() {\n\t// convert HTML rgb color using groups\n\tprintln(convert_html_rgb('#A0b0Cc').hex())\n\tprintln(convert_html_rgb('#ABC').hex())\n\n\t// convert HTML rgb color using named groups\n\tprintln(convert_html_rgb_n('#A0B0CC').hex())\n\tprintln(convert_html_rgb_n('#ABC').hex())\n}\n"
  },
  {
    "path": "examples/regex/regex_with_memoization.v",
    "content": "import os\n\nfn regex_match(src string, pat string) bool {\n\tsrc_size := src.len + 1\n\tpat_size := pat.len + 1\n\tmut memo := [][]int{len: src_size, init: []int{len: pat_size, init: -1}}\n\treturn regex_match_core(src, pat, 0, 0, mut memo)\n}\n\nfn regex_match_core(src string, pat string, src_pos int, pat_pos int, mut memo [][]int) bool {\n\tif memo[src_pos][pat_pos] != -1 {\n\t\treturn memo[src_pos][pat_pos] == 1\n\t}\n\tmut spos := src_pos\n\tmut ppos := pat_pos\n\tif spos >= src.len && ppos >= pat.len {\n\t\tmemo[src_pos][pat_pos] = 1\n\t\treturn true\n\t} else if spos < src.len && ppos >= pat.len {\n\t\tmemo[src_pos][pat_pos] = 0\n\t\treturn false\n\t} else if spos >= src.len && ppos < pat.len {\n\t\tif pat[ppos] == `\\\\` {\n\t\t\tppos++\n\t\t}\n\t\tres := ppos + 1 < pat.len && pat[ppos + 1] in [`*`, `?`]\n\t\t\t&& regex_match_core(src, pat, spos, ppos + 2, mut memo)\n\t\tmemo[src_pos][pat_pos] = if res { 1 } else { 0 }\n\t\treturn res\n\t} else {\n\t\tfirst_is_bslash := pat[ppos] == `\\\\`\n\t\tif first_is_bslash {\n\t\t\tppos++\n\t\t}\n\t\tfirst_bslash_and_match := first_is_bslash && ppos < pat.len\n\t\t\t&& (((pat[ppos] == `d` && src[spos].is_digit())\n\t\t\t|| (pat[ppos] == `D` && !src[spos].is_digit())\n\t\t\t|| (pat[ppos] == `s` && src[spos].is_space())\n\t\t\t|| (pat[ppos] == `S` && !src[spos].is_space())\n\t\t\t|| (pat[ppos] == `w` && (src[spos].is_digit() || src[spos].is_letter()\n\t\t\t|| src[spos] == `_`)) || (pat[ppos] == `W` && !(src[spos].is_digit()\n\t\t\t|| src[spos].is_letter() || src[spos] == `_`)))\n\t\t\t|| (pat[ppos] in [`d`, `D`, `s`, `S`, `w`, `W`] && ppos + 1 < pat.len\n\t\t\t&& pat[ppos + 1] in [`*`, `?`, `+`])\n\t\t\t|| (pat[ppos] !in [`d`, `D`, `s`, `S`, `w`, `W`] && src[spos] == pat[ppos]))\n\t\tif ppos + 1 < pat.len {\n\t\t\tmatch pat[ppos + 1] {\n\t\t\t\t`*` {\n\t\t\t\t\tif first_bslash_and_match {\n\t\t\t\t\t\tres := regex_match_core(src, pat, spos + 1, ppos - 1, mut memo)\n\t\t\t\t\t\t\t|| regex_match_core(src, pat, spos, ppos + 2, mut memo)\n\t\t\t\t\t\tmemo[src_pos][pat_pos] = if res { 1 } else { 0 }\n\t\t\t\t\t\treturn res\n\t\t\t\t\t} else if src[spos] == pat[ppos] || pat[ppos] == `.` {\n\t\t\t\t\t\tres := regex_match_core(src, pat, spos + 1, ppos, mut memo)\n\t\t\t\t\t\t\t|| regex_match_core(src, pat, spos, ppos + 2, mut memo)\n\t\t\t\t\t\tmemo[src_pos][pat_pos] = if res { 1 } else { 0 }\n\t\t\t\t\t\treturn res\n\t\t\t\t\t} else {\n\t\t\t\t\t\tres := regex_match_core(src, pat, spos, ppos + 2, mut memo)\n\t\t\t\t\t\tmemo[src_pos][pat_pos] = if res { 1 } else { 0 }\n\t\t\t\t\t\treturn res\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t`+` {\n\t\t\t\t\tif first_bslash_and_match {\n\t\t\t\t\t\tres := regex_match_core(src, pat, spos + 1, ppos - 1, mut memo)\n\t\t\t\t\t\t\t|| regex_match_core(src, pat, spos + 1, ppos + 2, mut memo)\n\t\t\t\t\t\tmemo[src_pos][pat_pos] = if res { 1 } else { 0 }\n\t\t\t\t\t\treturn res\n\t\t\t\t\t} else if src[spos] == pat[ppos] || pat[ppos] == `.` {\n\t\t\t\t\t\tres := regex_match_core(src, pat, spos + 1, ppos, mut memo)\n\t\t\t\t\t\t\t|| regex_match_core(src, pat, spos + 1, ppos + 2, mut memo)\n\t\t\t\t\t\tmemo[src_pos][pat_pos] = if res { 1 } else { 0 }\n\t\t\t\t\t\treturn res\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmemo[src_pos][pat_pos] = 0\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t`?` {\n\t\t\t\t\tif first_bslash_and_match || src[spos] == pat[ppos] || pat[ppos] == `.` {\n\t\t\t\t\t\tres := regex_match_core(src, pat, spos + 1, ppos + 2, mut memo)\n\t\t\t\t\t\t\t|| regex_match_core(src, pat, spos, ppos + 2, mut memo)\n\t\t\t\t\t\tmemo[src_pos][pat_pos] = if res { 1 } else { 0 }\n\t\t\t\t\t\treturn res\n\t\t\t\t\t} else {\n\t\t\t\t\t\tres := regex_match_core(src, pat, spos, ppos + 2, mut memo)\n\t\t\t\t\t\tmemo[src_pos][pat_pos] = if res { 1 } else { 0 }\n\t\t\t\t\t\treturn res\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {}\n\t\t\t}\n\t\t}\n\t\tif first_is_bslash {\n\t\t\tres := first_bslash_and_match\n\t\t\t\t&& regex_match_core(src, pat, spos + 1, ppos + 1, mut memo)\n\t\t\tmemo[src_pos][pat_pos] = if res { 1 } else { 0 }\n\t\t\treturn res\n\t\t} else {\n\t\t\tres := (src[spos] == pat[ppos] || pat[ppos] == `.`) && pat[ppos] != `\\\\`\n\t\t\t\t&& regex_match_core(src, pat, spos + 1, ppos + 1, mut memo)\n\t\t\tmemo[src_pos][pat_pos] = if res { 1 } else { 0 }\n\t\t\treturn res\n\t\t}\n\t}\n}\n\nfn main() {\n\tmut cnt := 0\n\tprintln('currently supported patterns: . ? + * \\\\ \\\\d \\\\D \\\\s \\\\S \\\\w \\\\W')\n\tprintln('example: source `address@domain.net` matches pattern `\\\\w+@domain\\\\.net`')\n\tprintln('enter `exit` to quit\\n')\n\tfor {\n\t\tcnt++\n\t\tsrc := os.input('[${cnt}] enter source string: ')\n\t\tif src == 'exit' {\n\t\t\tbreak\n\t\t}\n\t\tpat := os.input('[${cnt}] enter pattern string: ')\n\t\tif pat == 'exit' {\n\t\t\tbreak\n\t\t}\n\t\tprintln('[${cnt}] whether `${src}` matches `${pat}`: ${regex_match(src, pat)}')\n\t}\n}\n"
  },
  {
    "path": "examples/rule110.v",
    "content": "import os\nimport rand\n\nfn main() {\n\tmut arg := '31'\n\tif os.args.len != 2 {\n\t\tprintln('Usage: rule110 [<n>]')\n\t\tprintln('Using default `n` value: 31')\n\t} else {\n\t\targ = os.args[1]\n\t}\n\n\tmut n := arg.int()\n\tif n > 200 || n < 3 {\n\t\teprintln('`n` must be between 3 and 200!')\n\t\texit(1)\n\t}\n\n\tprint('\\n')\n\ttitle := ' Rule 110 V Implementation '\n\ttitle_len := title.len\n\tif n > title_len {\n\t\tfor _ in 0 .. (n - title_len) / 2 {\n\t\t\tprint('=')\n\t\t}\n\t\tprint(title)\n\t\tfor _ in 0 .. (n - title_len) / 2 {\n\t\t\tprint('=')\n\t\t}\n\t} else {\n\t\tprintln(title[1..(title_len - 1)])\n\t}\n\n\tmut generation_bin := []int{len: n}\n\tfor i in 0 .. n {\n\t\tgeneration_bin[i] = rand.intn(2) or { 0 }\n\t}\n\tprint('\\n')\n\n\t// println('Random generated first automaton content: ${generation_bin}')\n\tfor _ in 0 .. n {\n\t\tprint_generation(generation_bin)\n\t\tnext_generation(mut generation_bin)\n\t}\n}\n\nfn print_generation(arr []int) {\n\tsymbols := [' ', '*']!\n\tfor i in 0 .. arr.len {\n\t\tprint(symbols[arr[i]])\n\t}\n\tprint('\\n')\n}\n\nfn next_generation(mut gen []int) {\n\tmut arr := gen.clone()\n\tmut prev := 0\n\tmut curr := 0\n\tmut next := 0\n\tfor i in 0 .. arr.len {\n\t\tif (i - 1) % gen.len < 0 {\n\t\t\tprev = gen[gen.len - 1]\n\t\t} else {\n\t\t\tprev = gen[(i - 1) % gen.len]\n\t\t}\n\t\tcurr = gen[i]\n\t\tnext = gen[(i + 1) % gen.len]\n\n\t\tif prev == 1 {\n\t\t\tif curr == 1 {\n\t\t\t\tif next == 1 { // 111\n\t\t\t\t\tarr[i] = 0\n\t\t\t\t} else { // 110\n\t\t\t\t\tarr[i] = 1\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif next == 1 { // 101\n\t\t\t\t\tarr[i] = 1\n\t\t\t\t} else { // 100\n\t\t\t\t\tarr[i] = 0\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif curr == 1 {\n\t\t\t\tif next == 1 { // 011\n\t\t\t\t\tarr[i] = 1\n\t\t\t\t} else { // 010\n\t\t\t\t\tarr[i] = 1\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif next == 1 { // 001\n\t\t\t\t\tarr[i] = 1\n\t\t\t\t} else { // 000\n\t\t\t\t\tarr[i] = 0\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tgen = arr.clone()\n}\n"
  },
  {
    "path": "examples/rune.v",
    "content": "fn main() {\n\t// GRINNING FACE 😀\n\tgrinning_face := rune(0x1f600)\n\tprintln(grinning_face)\n\n\t// COMMERCIAL AT@ => 0x40\n\tcommercial_at := rune(0x40)\n\tprintln(commercial_at)\n}\n"
  },
  {
    "path": "examples/sha256sum_with_io_cp.v",
    "content": "// This example shows how to use io.cp, in combination with os.open and crypto.sha256,\n// to read and hash files chunk by chunk, without loading them completely in memory (which may\n// require too much RAM with big files).\n//\n// Usage: examples/sha256sum_with_io_cp [FILE]...\n//\n// Note: to compile the program, use:\n// `v -prod -cflags \"-march=native -mtune=native\" examples/sha256sum_with_io_cp.v`\n// After that, to compare it with say `sha256sum`, you can run:\n// `v repeat -R 5 \"sha256sum v\" \"examples/sha256sum_with_io_cp v`\nimport os\nimport io\nimport crypto.sha256\n\nfn hash_file(path string) !string {\n\tmut file := os.open(path)!\n\tmut digest := sha256.new()\n\tio.cp(mut file, mut digest, buffer_size: 256 * 1024)!\n\tfile.close()\n\treturn digest.sum([]).hex()\n}\n\nfn main() {\n\tfor fpath in os.args#[1..] {\n\t\th := hash_file(fpath)!\n\t\tprintln('${h}  ${fpath}')\n\t}\n}\n"
  },
  {
    "path": "examples/smtp/mail.v",
    "content": "// vtest build: present_openssl?\n// Creator: nedimf (07/2020)\nimport os\nimport net.smtp\n\nfn main() {\n\tprintln('Hi, this is sample of how to send email trough net.smtp library in V, which is really easy using the net.smtp module.')\n\tprintln('We are going to create a simple email client, that takes some arguments. and then sends email with an HTML body.')\n\tprintln('To fully test email sending, I suggest using the mailtrap.io service, which is free and acts like a really nice mail server sandbox.')\n\tprintln('')\n\tprintln('V Email client')\n\tprintln('')\n\tmailserver := os.input('Mail server: ')\n\tmailport := os.input('Mail server port: ').int()\n\tprintln('Login')\n\tusername := os.input('Username: ')\n\tpassword := os.input('Password: ')\n\tfrom := os.input('From: ')\n\tto := os.input('To: ')\n\tsubject := os.input('Subject: ')\n\tbody := os.input('Body: ')\n\tclient_cfg := smtp.Client{\n\t\tserver:   mailserver\n\t\tfrom:     from\n\t\tport:     mailport\n\t\tusername: username\n\t\tpassword: password\n\t}\n\tsend_cfg := smtp.Mail{\n\t\tto:        to\n\t\tsubject:   subject\n\t\tbody_type: .html\n\t\tbody:      body\n\t}\n\tmut client := smtp.new_client(client_cfg) or { panic('Error with configuring smtp: ${err}') }\n\tclient.send(send_cfg) or { panic('Error resolving email address: ${err}') }\n}\n"
  },
  {
    "path": "examples/snek/README.md",
    "content": "# snek\n\nSnake game implemented using `gg` module. \n\n# Compiling & running\n\n## Compiling to binary\n```sh\nv -prod examples/snek/snek.v\n./examples/snek/snek # run snek game!\n```\n\n## Compiling to JS\n```sh\nv -b js_browser examples/snek/snek.js.v\n```\nAnd then open `examples/snek/index.html` in your favourite browser."
  },
  {
    "path": "examples/snek/index.html",
    "content": "<body class=\"main\">\n    <title>gg</title>\n    <canvas style=\"border: 1px solid black;\" width=\"700\" height=\"800\" id=\"canvas\"></canvas>\n    <script type=\"text/javascript\" src=\"snek.js\"></script>\n\n</body>"
  },
  {
    "path": "examples/snek/snek.js.v",
    "content": "import gg\n// import sokol.sapp\nimport time\nimport rand\n\n// constants\nconst top_height = 100\nconst canvas_size = 700\nconst game_size = 17\nconst tile_size = canvas_size / game_size\nconst tick_rate_ms = 100\n\n// types\nstruct Pos {\n\tx int\n\ty int\n}\n\nfn (a Pos) + (b Pos) Pos {\n\treturn Pos{a.x + b.x, a.y + b.y}\n}\n\nfn (a Pos) - (b Pos) Pos {\n\treturn Pos{a.x - b.x, a.y - b.y}\n}\n\nenum Direction {\n\tup\n\tdown\n\tleft\n\tright\n}\n\nstruct App {\nmut:\n\tgg         &gg.Context = unsafe { nil }\n\tscore      int\n\tsnake      []Pos\n\tdir        Direction\n\tlast_dir   Direction\n\tfood       Pos\n\tstart_time i64\n\tlast_tick  i64\n}\n\n// utility\nfn (mut app App) reset_game() {\n\tapp.score = 0\n\tapp.snake = [\n\t\tPos{3, 8},\n\t\tPos{2, 8},\n\t\tPos{1, 8},\n\t\tPos{0, 8},\n\t]\n\tapp.dir = .right\n\tapp.last_dir = app.dir\n\tapp.food = Pos{10, 8}\n\tapp.start_time = time.ticks()\n\tapp.last_tick = time.ticks()\n}\n\nfn (mut app App) move_food() {\n\tfor {\n\t\tx := rand.intn(game_size) or { 0 }\n\t\ty := rand.intn(game_size) or { 0 }\n\t\tapp.food = Pos{x, y}\n\n\t\tif app.food !in app.snake {\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// events\nfn on_keydown(key gg.KeyCode, mod gg.Modifier, mut app App) {\n\tmatch key {\n\t\t.w, .up {\n\t\t\tif app.last_dir != .down {\n\t\t\t\tapp.dir = .up\n\t\t\t}\n\t\t}\n\t\t.s, .down {\n\t\t\tif app.last_dir != .up {\n\t\t\t\tapp.dir = .down\n\t\t\t}\n\t\t}\n\t\t.a, .left {\n\t\t\tif app.last_dir != .right {\n\t\t\t\tapp.dir = .left\n\t\t\t}\n\t\t}\n\t\t.d, .right {\n\t\t\tif app.last_dir != .left {\n\t\t\t\tapp.dir = .right\n\t\t\t}\n\t\t}\n\t\telse {}\n\t}\n}\n\nfn on_frame(mut app App) {\n\tapp.gg.begin()\n\n\tnow := time.ticks()\n\n\tif now - app.last_tick >= tick_rate_ms {\n\t\tapp.last_tick = now\n\n\t\t// finding delta direction\n\t\tdelta_dir := match app.dir {\n\t\t\t.up { Pos{0, -1} }\n\t\t\t.down { Pos{0, 1} }\n\t\t\t.left { Pos{-1, 0} }\n\t\t\t.right { Pos{1, 0} }\n\t\t}\n\n\t\t// \"snaking\" along\n\t\tmut prev := app.snake[0]\n\t\tapp.snake[0] = app.snake[0] + delta_dir\n\n\t\tfor i in 1 .. app.snake.len {\n\t\t\ttmp := app.snake[i]\n\t\t\tapp.snake[i] = prev\n\t\t\tprev = tmp\n\t\t}\n\n\t\t// adding last segment\n\t\tif app.snake[0] == app.food {\n\t\t\tapp.move_food()\n\t\t\tapp.score++\n\t\t\t/*\n\t\t\tif app.score > app.best {\n\t\t\t\tapp.best = app.score\n\t\t\t\tapp.best.save()\n\t\t\t}*/\n\t\t\tapp.snake << app.snake.last() + app.snake.last() - app.snake[app.snake.len - 2]\n\t\t}\n\n\t\tapp.last_dir = app.dir\n\t}\n\t// drawing snake\n\tfor pos in app.snake {\n\t\tapp.gg.draw_rect(tile_size * pos.x, tile_size * pos.y + top_height, tile_size,\n\t\t\ttile_size, gg.blue)\n\t}\n\n\t// drawing food\n\tapp.gg.draw_rect(tile_size * app.food.x, tile_size * app.food.y + top_height, tile_size,\n\t\ttile_size, gg.red)\n\n\t// drawing top\n\tapp.gg.draw_rect(0, 0, canvas_size, top_height, gg.black)\n\tapp.gg.draw_text(350, top_height / 2, 'Score: ${app.score}', gg.TextCfg{\n\t\tcolor:          gg.white\n\t\talign:          .center\n\t\tvertical_align: .middle\n\t\tsize:           80\n\t})\n\n\t// checking if snake bit itself\n\tif app.snake[0] in app.snake[1..] {\n\t\tapp.reset_game()\n\t}\n\t// checking if snake hit a wall\n\tif app.snake[0].x < 0 || app.snake[0].x >= game_size || app.snake[0].y < 0\n\t\t|| app.snake[0].y >= game_size {\n\t\tapp.reset_game()\n\t}\n\n\tapp.gg.end()\n}\n\n// setup\nfn main() {\n\tmut app := App{\n\t\tgg: &gg.Context{}\n\t}\n\tapp.reset_game()\n\n\tapp.gg = gg.new_context(\n\t\tbg_color:          gg.white\n\t\tframe_fn:          on_frame\n\t\tkeydown_fn:        on_keydown\n\t\tuser_data:         &app\n\t\twidth:             canvas_size\n\t\theight:            top_height + canvas_size\n\t\tcreate_window:     true\n\t\tresizable:         false\n\t\twindow_title:      'snek'\n\t\thtml5_canvas_name: 'canvas'\n\t)\n\n\tapp.gg.run()\n}\n"
  },
  {
    "path": "examples/snek/snek.v",
    "content": "import gg\nimport os\nimport rand\nimport time\nimport math.vec { Vec2 }\n\n// constants\nconst font = $embed_file('../assets/fonts/RobotoMono-Regular.ttf')\nconst top_height = 100\nconst canvas_size = 700\nconst game_size = 17\nconst tile_size = canvas_size / game_size\nconst tick_rate_ms = 100\nconst high_score_file_path = os.join_path(os.cache_dir(), 'v', 'examples', 'snek')\n\n// types\ntype HighScore = int\ntype Vec = Vec2[int]\n\nfn (mut h HighScore) save() {\n\tos.mkdir_all(os.dir(high_score_file_path)) or { return }\n\tos.write_file(high_score_file_path, (*h).str()) or { return }\n}\n\nfn (mut h HighScore) load() {\n\th = (os.read_file(high_score_file_path) or { '' }).int()\n}\n\nstruct App {\nmut:\n\tgg        &gg.Context = unsafe { nil }\n\tscore     int\n\tbest      HighScore\n\tsnake     []Vec\n\tdir       Vec\n\tdir_queue []Vec\n\tfood      Vec\n\tlast_tick i64\n}\n\n// utility\nfn (mut app App) reset_game() {\n\tapp.score = 0\n\tapp.snake = [Vec{3, 8}, Vec{2, 8}, Vec{1, 8}, Vec{0, 8}]\n\tapp.dir = Vec{1, 0}\n\tapp.dir_queue = []\n\tapp.food = Vec{10, 8}\n\tapp.last_tick = time.ticks()\n}\n\nfn (mut app App) move_food() {\n\tfor {\n\t\tx := rand.intn(game_size) or { 0 }\n\t\ty := rand.intn(game_size) or { 0 }\n\t\tapp.food = Vec{x, y}\n\t\tif app.food !in app.snake {\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfn on_frame(mut app App) {\n\t// check if snake bit itself\n\tif app.snake[0] in app.snake[1..] {\n\t\tapp.reset_game()\n\t}\n\n\t// check if snake hit a wall\n\tif app.snake[0].x < 0 || app.snake[0].x >= game_size || app.snake[0].y < 0\n\t\t|| app.snake[0].y >= game_size {\n\t\tapp.reset_game()\n\t}\n\tprogress := f32_min(1, f32(time.ticks() - app.last_tick) / f32(tick_rate_ms))\n\n\t// draw everything:\n\tapp.gg.begin()\n\t// draw food\n\tapp.gg.draw_rect_filled(tile_size * app.food.x, tile_size * app.food.y + top_height,\n\t\ttile_size, tile_size, gg.red)\n\n\t// draw snake\n\tfor pos in app.snake[..app.snake.len - 1] {\n\t\tapp.gg.draw_rect_filled(tile_size * pos.x, tile_size * pos.y + top_height, tile_size,\n\t\t\ttile_size, gg.blue)\n\t}\n\n\t// draw partial head\n\thead := app.snake[0]\n\tapp.gg.draw_rect_filled(tile_size * (head.x + app.dir.x * progress), tile_size * (head.y +\n\t\tapp.dir.y * progress) + top_height, tile_size, tile_size, gg.blue)\n\n\t// draw partial tail\n\ttail := app.snake.last()\n\ttail_dir := app.snake[app.snake.len - 2] - tail\n\tapp.gg.draw_rect_filled(tile_size * (tail.x + tail_dir.x * progress), tile_size * (tail.y +\n\t\ttail_dir.y * progress) + top_height, tile_size, tile_size, gg.blue)\n\n\t// draw score bar\n\tapp.gg.draw_rect_filled(0, 0, canvas_size, top_height, gg.black)\n\tapp.gg.draw_text(150, top_height / 2, 'Score: ${app.score}', gg.TextCfg{\n\t\tcolor:          gg.white\n\t\talign:          .center\n\t\tvertical_align: .middle\n\t\tsize:           65\n\t})\n\tapp.gg.draw_text(canvas_size - 150, top_height / 2, 'Best: ${app.best}', gg.TextCfg{\n\t\tcolor:          gg.white\n\t\talign:          .center\n\t\tvertical_align: .middle\n\t\tsize:           65\n\t})\n\n\tif progress == 1 {\n\t\t// \"snake\" along\n\t\tmut prev := app.snake[0]\n\t\tapp.snake[0] = app.snake[0] + app.dir\n\t\tfor i in 1 .. app.snake.len {\n\t\t\tapp.snake[i], prev = prev, app.snake[i]\n\t\t}\n\n\t\t// add tail segment if food has been eaten\n\t\tif app.snake[0] == app.food {\n\t\t\tapp.score++\n\t\t\tif app.score > app.best {\n\t\t\t\tapp.best = app.score\n\t\t\t\tapp.best.save()\n\t\t\t}\n\t\t\tapp.snake << app.snake.last() + app.snake.last() - app.snake[app.snake.len - 2]\n\t\t\tapp.move_food()\n\t\t}\n\n\t\tif app.dir_queue.len > 0 {\n\t\t\tdir := app.dir_queue.pop()\n\t\t\tif dir.x != -app.dir.x || dir.y != -app.dir.y {\n\t\t\t\tapp.dir = dir\n\t\t\t}\n\t\t}\n\n\t\tapp.last_tick = time.ticks()\n\t}\n\n\tapp.gg.end()\n}\n\n// events\nfn on_keydown(key gg.KeyCode, _mod gg.Modifier, mut app App) {\n\tapp.dir_queue << match key {\n\t\t.w, .up {\n\t\t\tVec{0, -1}\n\t\t}\n\t\t.s, .down {\n\t\t\tVec{0, 1}\n\t\t}\n\t\t.a, .left {\n\t\t\tVec{-1, 0}\n\t\t}\n\t\t.d, .right {\n\t\t\tVec{1, 0}\n\t\t}\n\t\telse {\n\t\t\treturn\n\t\t}\n\t}\n}\n\nmut app := App{}\napp.reset_game()\napp.best.load()\n\nmut font_copy := font\napp.gg = gg.new_context(\n\tbg_color:          gg.white\n\tframe_fn:          on_frame\n\tkeydown_fn:        on_keydown\n\tuser_data:         &app\n\twidth:             canvas_size\n\theight:            top_height + canvas_size\n\twindow_title:      'snek'\n\tfont_bytes_normal: unsafe { font_copy.data().vbytes(font_copy.len) }\n)\napp.gg.run()\n"
  },
  {
    "path": "examples/sokol/.gitignore",
    "content": "02_cubes_glsl/cube_glsl.h\n03_march_tracing_glsl/rt_glsl.h\n04_multi_shader_glsl/rt_glsl_march.h\n04_multi_shader_glsl/rt_glsl_puppy.h\n05_instancing_glsl/rt_glsl_instancing.h\n06_obj_viewer/gouraud.h\n"
  },
  {
    "path": "examples/sokol/01_cubes/cube.v",
    "content": "/**********************************************************************\n* Sokol 3d cube demo\n* Copyright (c) 2021 Dario Deledda. All rights reserved.\n* Use of this source code is governed by an MIT license\n* that can be found in the LICENSE file.\n* TODO:\n* - add instancing\n* - add an example with shaders\n**********************************************************************/\nimport gg\nimport math\nimport sokol.sapp\nimport sokol.gfx\nimport sokol.sgl\n\nconst win_width = 800\nconst win_height = 800\nconst bg_color = gg.white\n\nstruct App {\nmut:\n\tgg          &gg.Context = unsafe { nil }\n\tpip_3d      sgl.Pipeline\n\ttexture     gfx.Image\n\tsampler     gfx.Sampler\n\tinit_flag   bool\n\tframe_count int\n\tmouse_x     int = -1\n\tmouse_y     int = -1\n}\n\nfn create_texture(w int, h int, buf &u8) (gfx.Image, gfx.Sampler) {\n\tsz := w * h * 4\n\tmut img_desc := gfx.ImageDesc{\n\t\twidth:       w\n\t\theight:      h\n\t\tnum_mipmaps: 0\n\t\t// usage: .dynamic\n\t\tlabel:         &char(unsafe { nil })\n\t\td3d11_texture: 0\n\t}\n\t// comment, if .dynamic is enabled\n\timg_desc.data.subimage[0][0] = gfx.Range{\n\t\tptr:  buf\n\t\tsize: usize(sz)\n\t}\n\n\tsg_img := gfx.make_image(&img_desc)\n\n\tmut smp_desc := gfx.SamplerDesc{\n\t\tmin_filter: .linear\n\t\tmag_filter: .linear\n\t\twrap_u:     .clamp_to_edge\n\t\twrap_v:     .clamp_to_edge\n\t}\n\n\tsg_smp := gfx.make_sampler(&smp_desc)\n\treturn sg_img, sg_smp\n}\n\nfn destroy_texture(sg_img gfx.Image) {\n\tgfx.destroy_image(sg_img)\n}\n\n// Use only if usage: .dynamic is enabled\nfn update_text_texture(sg_img gfx.Image, w int, h int, buf &u8) {\n\tsz := w * h * 4\n\tmut tmp_sbc := gfx.ImageData{}\n\ttmp_sbc.subimage[0][0] = gfx.Range{\n\t\tptr:  buf\n\t\tsize: usize(sz)\n\t}\n\tgfx.update_image(sg_img, &tmp_sbc)\n}\n\nfn draw_triangle() {\n\tsgl.defaults()\n\tsgl.begin_triangles()\n\tsgl.v2f_c3b(0.0, 0.5, 255, 0, 0)\n\tsgl.v2f_c3b(-0.5, -0.5, 0, 0, 255)\n\tsgl.v2f_c3b(0.5, -0.5, 0, 255, 0)\n\tsgl.end()\n}\n\n// vertex specification for a cube with colored sides and texture coords\nfn cube() {\n\tsgl.begin_quads()\n\t// edge color\n\tsgl.c3f(1.0, 0.0, 0.0)\n\t// edge coord\n\t// x,y,z, texture cord: u,v\n\tsgl.v3f_t2f(-1.0, 1.0, -1.0, -1.0, 1.0)\n\tsgl.v3f_t2f(1.0, 1.0, -1.0, 1.0, 1.0)\n\tsgl.v3f_t2f(1.0, -1.0, -1.0, 1.0, -1.0)\n\tsgl.v3f_t2f(-1.0, -1.0, -1.0, -1.0, -1.0)\n\tsgl.c3f(0.0, 1.0, 0.0)\n\tsgl.v3f_t2f(-1.0, -1.0, 1.0, -1.0, 1.0)\n\tsgl.v3f_t2f(1.0, -1.0, 1.0, 1.0, 1.0)\n\tsgl.v3f_t2f(1.0, 1.0, 1.0, 1.0, -1.0)\n\tsgl.v3f_t2f(-1.0, 1.0, 1.0, -1.0, -1.0)\n\tsgl.c3f(0.0, 0.0, 1.0)\n\tsgl.v3f_t2f(-1.0, -1.0, 1.0, -1.0, 1.0)\n\tsgl.v3f_t2f(-1.0, 1.0, 1.0, 1.0, 1.0)\n\tsgl.v3f_t2f(-1.0, 1.0, -1.0, 1.0, -1.0)\n\tsgl.v3f_t2f(-1.0, -1.0, -1.0, -1.0, -1.0)\n\tsgl.c3f(1.0, 0.5, 0.0)\n\tsgl.v3f_t2f(1.0, -1.0, 1.0, -1.0, 1.0)\n\tsgl.v3f_t2f(1.0, -1.0, -1.0, 1.0, 1.0)\n\tsgl.v3f_t2f(1.0, 1.0, -1.0, 1.0, -1.0)\n\tsgl.v3f_t2f(1.0, 1.0, 1.0, -1.0, -1.0)\n\tsgl.c3f(0.0, 0.5, 1.0)\n\tsgl.v3f_t2f(1.0, -1.0, -1.0, -1.0, 1.0)\n\tsgl.v3f_t2f(1.0, -1.0, 1.0, 1.0, 1.0)\n\tsgl.v3f_t2f(-1.0, -1.0, 1.0, 1.0, -1.0)\n\tsgl.v3f_t2f(-1.0, -1.0, -1.0, -1.0, -1.0)\n\tsgl.c3f(1.0, 0.0, 0.5)\n\tsgl.v3f_t2f(-1.0, 1.0, -1.0, -1.0, 1.0)\n\tsgl.v3f_t2f(-1.0, 1.0, 1.0, 1.0, 1.0)\n\tsgl.v3f_t2f(1.0, 1.0, 1.0, 1.0, -1.0)\n\tsgl.v3f_t2f(1.0, 1.0, -1.0, -1.0, -1.0)\n\tsgl.end()\n}\n\nfn draw_cubes(app App) {\n\trot := [f32(1.0) * (app.frame_count % 360), 0.5 * f32(app.frame_count % 360)]\n\n\tsgl.defaults()\n\tsgl.load_pipeline(app.pip_3d)\n\n\tsgl.matrix_mode_projection()\n\tsgl.perspective(sgl.rad(45.0), 1.0, 0.1, 100.0)\n\n\tsgl.matrix_mode_modelview()\n\tsgl.translate(0.0, 0.0, -12.0)\n\tsgl.rotate(sgl.rad(rot[0]), 1.0, 0.0, 0.0)\n\tsgl.rotate(sgl.rad(rot[1]), 0.0, 1.0, 0.0)\n\tcube()\n\tsgl.push_matrix()\n\tsgl.translate(0.0, 0.0, 3.0)\n\tsgl.scale(0.5, 0.5, 0.5)\n\tsgl.rotate(-2.0 * sgl.rad(rot[0]), 1.0, 0.0, 0.0)\n\tsgl.rotate(-2.0 * sgl.rad(rot[1]), 0.0, 1.0, 0.0)\n\tcube()\n\tsgl.push_matrix()\n\tsgl.translate(0.0, 0.0, 3.0)\n\tsgl.scale(0.5, 0.5, 0.5)\n\tsgl.rotate(-3.0 * sgl.rad(2 * rot[0]), 1.0, 0.0, 0.0)\n\tsgl.rotate(3.0 * sgl.rad(2 * rot[1]), 0.0, 0.0, 1.0)\n\tcube()\n\tsgl.pop_matrix()\n\tsgl.pop_matrix()\n}\n\nfn cube_t(r f32, g f32, b f32) {\n\tsgl.begin_quads()\n\t// edge color\n\tsgl.c3f(r, g, b)\n\t// edge coord\n\t// x,y,z, texture cord: u,v\n\tsgl.v3f_t2f(-1.0, 1.0, -1.0, 0.0, 0.25)\n\tsgl.v3f_t2f(1.0, 1.0, -1.0, 0.25, 0.25)\n\tsgl.v3f_t2f(1.0, -1.0, -1.0, 0.25, 0.0)\n\tsgl.v3f_t2f(-1.0, -1.0, -1.0, 0.0, 0.0)\n\tsgl.c3f(r, g, b)\n\tsgl.v3f_t2f(-1.0, -1.0, 1.0, 0.0, 0.25)\n\tsgl.v3f_t2f(1.0, -1.0, 1.0, 0.25, 0.25)\n\tsgl.v3f_t2f(1.0, 1.0, 1.0, 0.25, 0.0)\n\tsgl.v3f_t2f(-1.0, 1.0, 1.0, 0.0, 0.0)\n\tsgl.c3f(r, g, b)\n\tsgl.v3f_t2f(-1.0, -1.0, 1.0, 0.0, 0.25)\n\tsgl.v3f_t2f(-1.0, 1.0, 1.0, 0.25, 0.25)\n\tsgl.v3f_t2f(-1.0, 1.0, -1.0, 0.25, 0.0)\n\tsgl.v3f_t2f(-1.0, -1.0, -1.0, 0.0, 0.0)\n\tsgl.c3f(r, g, b)\n\tsgl.v3f_t2f(1.0, -1.0, 1.0, 0.0, 0.25)\n\tsgl.v3f_t2f(1.0, -1.0, -1.0, 0.25, 0.25)\n\tsgl.v3f_t2f(1.0, 1.0, -1.0, 0.25, 0.0)\n\tsgl.v3f_t2f(1.0, 1.0, 1.0, 0.0, 0.0)\n\tsgl.c3f(r, g, b)\n\tsgl.v3f_t2f(1.0, -1.0, -1.0, 0.0, 0.25)\n\tsgl.v3f_t2f(1.0, -1.0, 1.0, 0.25, 0.25)\n\tsgl.v3f_t2f(-1.0, -1.0, 1.0, 0.25, 0.0)\n\tsgl.v3f_t2f(-1.0, -1.0, -1.0, 0.0, 0.0)\n\tsgl.c3f(r, g, b)\n\tsgl.v3f_t2f(-1.0, 1.0, -1.0, 0.0, 0.25)\n\tsgl.v3f_t2f(-1.0, 1.0, 1.0, 0.25, 0.25)\n\tsgl.v3f_t2f(1.0, 1.0, 1.0, 0.25, 0.0)\n\tsgl.v3f_t2f(1.0, 1.0, -1.0, 0.0, 0.0)\n\tsgl.end()\n}\n\nfn draw_texture_cubes(app App) {\n\trot := [f32(app.mouse_x), f32(app.mouse_y)]\n\tsgl.defaults()\n\tsgl.load_pipeline(app.pip_3d)\n\n\tsgl.enable_texture()\n\tsgl.texture(app.texture, app.sampler)\n\n\tsgl.matrix_mode_projection()\n\tsgl.perspective(sgl.rad(45.0), 1.0, 0.1, 100.0)\n\n\tsgl.matrix_mode_modelview()\n\tsgl.translate(0.0, 0.0, -12.0)\n\tsgl.rotate(sgl.rad(rot[0]), 1.0, 0.0, 0.0)\n\tsgl.rotate(sgl.rad(rot[1]), 0.0, 1.0, 0.0)\n\tcube_t(1, 1, 1)\n\tsgl.push_matrix()\n\tsgl.translate(0.0, 0.0, 3.0)\n\tsgl.scale(0.5, 0.5, 0.5)\n\tsgl.rotate(-2.0 * sgl.rad(rot[0]), 1.0, 0.0, 0.0)\n\tsgl.rotate(-2.0 * sgl.rad(rot[1]), 0.0, 1.0, 0.0)\n\tcube_t(1, 1, 1)\n\tsgl.push_matrix()\n\tsgl.translate(0.0, 0.0, 3.0)\n\tsgl.scale(0.5, 0.5, 0.5)\n\tsgl.rotate(-3.0 * sgl.rad(2 * rot[0]), 1.0, 0.0, 0.0)\n\tsgl.rotate(3.0 * sgl.rad(2 * rot[1]), 0.0, 0.0, 1.0)\n\tcube_t(1, 1, 1)\n\tsgl.pop_matrix()\n\tsgl.pop_matrix()\n\n\tsgl.disable_texture()\n}\n\nfn cube_field(app App) {\n\trot := [f32(app.mouse_x), f32(app.mouse_y)]\n\txyz_sz := f32(2.0)\n\tfield_size := 20\n\n\tsgl.defaults()\n\tsgl.load_pipeline(app.pip_3d)\n\n\tsgl.enable_texture()\n\tsgl.texture(app.texture, app.sampler)\n\n\tsgl.matrix_mode_projection()\n\tsgl.perspective(sgl.rad(45.0), 1.0, 0.1, 200.0)\n\n\tsgl.matrix_mode_modelview()\n\n\tsgl.translate(field_size, 0.0, -120.0)\n\tsgl.rotate(sgl.rad(rot[0]), 0.0, 1.0, 0.0)\n\tsgl.rotate(sgl.rad(rot[1]), 1.0, 0.0, 0.0)\n\n\t// draw field_size*field_size cubes\n\tfor y in 0 .. field_size {\n\t\tfor x in 0 .. field_size {\n\t\t\tsgl.push_matrix()\n\t\t\tz := f32(math.cos(f32(x * 2) / field_size) * math.sin(f32(y * 2) / field_size) * xyz_sz) * (xyz_sz * 5)\n\t\t\tsgl.translate(x * xyz_sz, z, y * xyz_sz)\n\t\t\tcube_t(f32(f32(x) / field_size), f32(f32(y) / field_size), 1)\n\t\t\tsgl.pop_matrix()\n\t\t}\n\t}\n\tsgl.disable_texture()\n}\n\nfn frame(mut app App) {\n\tws := gg.window_size_real_pixels()\n\tratio := f32(ws.width) / ws.height\n\tdw := ws.width\n\tdh := ws.height\n\tww := int(dh / 3) // not a bug\n\thh := int(dh / 3)\n\tx0 := int(f32(dw) * 0.05)\n\t// x1 := dw/2\n\ty0 := 0\n\ty1 := int(f32(dh) * 0.5)\n\n\tapp.gg.begin()\n\t// sgl.defaults()\n\n\t// 2d triangle\n\tsgl.viewport(x0, y0, ww, hh, true)\n\tdraw_triangle()\n\n\t// colored cubes with viewport\n\tsgl.viewport(x0, y1, ww, hh, true)\n\tdraw_cubes(app)\n\n\t// textured cubed with viewport\n\tsgl.viewport(0, int(dh / 5), dw, int(dh * ratio), true)\n\tdraw_texture_cubes(app)\n\n\t// textured field of cubes with viewport\n\tsgl.viewport(0, int(dh / 5), dw, int(dh * ratio), true)\n\tcube_field(app)\n\n\tapp.frame_count++\n\n\tapp.gg.end()\n}\n\nfn my_init(mut app App) {\n\tapp.init_flag = true\n\n\t// set max vertices,\n\t// for a large number of the same type of object it is better use the instances!!\n\tdesc := sapp.create_desc()\n\tgfx.setup(&desc)\n\tsgl_desc := sgl.Desc{\n\t\tmax_vertices: 50 * 65536\n\t}\n\tsgl.setup(&sgl_desc)\n\n\t// 3d pipeline\n\tmut pipdesc := gfx.PipelineDesc{}\n\tunsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }\n\n\tcolor_state := gfx.ColorTargetState{\n\t\tblend: gfx.BlendState{\n\t\t\tenabled:        true\n\t\t\tsrc_factor_rgb: .src_alpha\n\t\t\tdst_factor_rgb: .one_minus_src_alpha\n\t\t}\n\t}\n\tpipdesc.colors[0] = color_state\n\n\tpipdesc.depth = gfx.DepthState{\n\t\twrite_enabled: true\n\t\tcompare:       .less_equal\n\t}\n\tpipdesc.cull_mode = .back\n\tapp.pip_3d = sgl.make_pipeline(&pipdesc)\n\n\t// create chessboard texture 256*256 RGBA\n\tw := 256\n\th := 256\n\tsz := w * h * 4\n\ttmp_txt := unsafe { malloc(sz) }\n\tmut i := 0\n\tfor i < sz {\n\t\tunsafe {\n\t\t\ty := (i >> 0x8) >> 5 // 8 cell\n\t\t\tx := (i & 0xFF) >> 5 // 8 cell\n\t\t\t// upper left corner\n\t\t\tif x == 0 && y == 0 {\n\t\t\t\ttmp_txt[i] = u8(0xFF)\n\t\t\t\ttmp_txt[i + 1] = u8(0)\n\t\t\t\ttmp_txt[i + 2] = u8(0)\n\t\t\t\ttmp_txt[i + 3] = u8(0xFF)\n\t\t\t}\n\t\t\t// low right corner\n\t\t\telse if x == 7 && y == 7 {\n\t\t\t\ttmp_txt[i] = u8(0)\n\t\t\t\ttmp_txt[i + 1] = u8(0xFF)\n\t\t\t\ttmp_txt[i + 2] = u8(0)\n\t\t\t\ttmp_txt[i + 3] = u8(0xFF)\n\t\t\t} else {\n\t\t\t\tcol := if ((x + y) & 1) == 1 { 0xFF } else { 0 }\n\t\t\t\ttmp_txt[i] = u8(col) // red\n\t\t\t\ttmp_txt[i + 1] = u8(col) // green\n\t\t\t\ttmp_txt[i + 2] = u8(col) // blue\n\t\t\t\ttmp_txt[i + 3] = u8(0xFF) // alpha\n\t\t\t}\n\t\t\ti += 4\n\t\t}\n\t}\n\tunsafe {\n\t\tapp.texture, app.sampler = create_texture(w, h, tmp_txt)\n\t\tfree(tmp_txt)\n\t}\n}\n\nfn my_event_manager(mut ev gg.Event, mut app App) {\n\tif ev.typ == .mouse_move {\n\t\tapp.mouse_x = int(ev.mouse_x)\n\t\tapp.mouse_y = int(ev.mouse_y)\n\t}\n\tif ev.typ == .touches_began || ev.typ == .touches_moved {\n\t\tif ev.num_touches > 0 {\n\t\t\ttouch_point := ev.touches[0]\n\t\t\tapp.mouse_x = int(touch_point.pos_x)\n\t\t\tapp.mouse_y = int(touch_point.pos_y)\n\t\t}\n\t}\n}\n\nfn main() {\n\tmut app := &App{}\n\tapp.gg = gg.new_context(\n\t\twidth:         win_width\n\t\theight:        win_height\n\t\tcreate_window: true\n\t\twindow_title:  '3D Cube Demo'\n\t\tuser_data:     app\n\t\tbg_color:      bg_color\n\t\tframe_fn:      frame\n\t\tinit_fn:       my_init\n\t\tevent_fn:      my_event_manager\n\t)\n\tapp.gg.run()\n}\n"
  },
  {
    "path": "examples/sokol/02_cubes_glsl/cube_glsl.glsl",
    "content": "//------------------------------------------------------------------------------\n//  Shader code for texcube-sapp sample.\n//\n//  NOTE: This source file also uses the '#pragma sokol' form of the\n//  custom tags.\n//------------------------------------------------------------------------------\n//#pragma sokol @ctype mat4 my_mat4\n\n#pragma sokol @vs vs\nuniform vs_params {\n    mat4 mvp;\n};\n\nin vec4 pos;\nin vec4 color0;\nin vec2 texcoord0;\n\nout vec4 color;\nout vec2 uv;\n\nvoid main() {\n    gl_Position = mvp * pos;\n    color = color0;\n    uv = texcoord0;\n}\n#pragma sokol @end\n\n#pragma sokol @fs fs\n\nuniform texture2D tex;\nuniform sampler smp;\n\nuniform fs_params {\n\tvec2 text_res;\n\tfloat iTime;\n};\n\nin vec4 color;\nin vec2 uv;\nout vec4 frag_color;\n\n//*********************************************************\n// RAY TRACE\n// original code from: https://www.shadertoy.com/view/ldS3DW\n//*********************************************************\nfloat sphere(vec3 ray, vec3 dir, vec3 center, float radius)\n{\n vec3 rc  = ray-center;\n float c  = dot(rc, rc) - (radius*radius);\n float b  = dot(dir, rc);\n float d  = b*b - c;\n float t  = -b - sqrt(abs(d));\n float st = step(0.0, min(t,d));\n return mix(-1.0, t, st);\n}\n\nvec3 background(float t, vec3 rd)\n{\n\tvec3 light = normalize(vec3(sin(t), 0.6, cos(t)));\n\tfloat sun = max(0.0, dot(rd, light));\n\tfloat sky = max(0.0, dot(rd, vec3(0.0, 1.0, 0.0)));\n\tfloat ground = max(0.0, -dot(rd, vec3(0.0, 1.0, 0.0)));\n\treturn (pow(sun, 256.0)+0.2*pow(sun, 2.0))*vec3(2.0, 1.6, 1.0) +\n\t\t\t\t\tpow(ground, 0.5)*vec3(0.4, 0.3, 0.2) +\n\t\t\t\t\tpow(sky, 1.0)*vec3(0.5, 0.6, 0.7);\n}\n\nvec4 mainImage(vec2 fragCoord)\n{\n vec2 uv = (fragCoord-vec2(0.4,0.4))*2.0;\n\n //vec2 uv  = (-1.0 + 2.0*fc.xy / text_res.xy) * vec2(text_res.x/text_res.y, 1.0);\n vec3 ro    = vec3(0.0, 0.0, -3.0);\n vec3 rd    = normalize(vec3(uv, 1.0));\n vec3 p     = vec3(0.0, 0.0, 0.0);\n float t    = sphere(ro, rd, p, 1.0);\n vec3 nml   = normalize(p - (ro+rd*t));\n vec3 bgCol = background(iTime, rd);\n rd         = reflect(rd, nml);\n vec3 col   = background(iTime, rd) * vec3(0.9, 0.8, 1.0);\n vec4 fragColor = vec4( mix(bgCol, col, step(0.0, t)), 1.0 );\n return fragColor;\n}\n//*********************************************************\n//*********************************************************\n\nvoid main() {\n\t\tvec4 c = color;\n\t\tvec4 txt = texture(sampler2D(tex, smp), uv/4.0);\n\t\tc = txt * c;\n\t\tvec4 col_ray = mainImage(uv);\n\t\tfloat txt_mix = mod(iTime,5);\n\t\tfrag_color = c*txt_mix*0.1 +\tcol_ray\t;\n}\n\n#pragma sokol @end\n\n#pragma sokol @program cube vs fs\n"
  },
  {
    "path": "examples/sokol/02_cubes_glsl/cube_glsl.v",
    "content": "// vtest build: misc-tooling // needs .h files that are produced by `v shader`\n/**********************************************************************\n*\n* Sokol 3d cube demo\n*\n* Copyright (c) 2021 Dario Deledda. All rights reserved.\n* Use of this source code is governed by an MIT license\n* that can be found in the LICENSE file.\n*\n* HOW TO COMPILE SHADERS:\n* Run `v shader .` in this directory to compile the shaders.\n* For more info and help with shader compilation see `docs.md` and `v help shader`.\n*\n* TODO:\n* - add instancing\n**********************************************************************/\nimport gg\n// import math\nimport sokol.sapp\nimport sokol.gfx\nimport sokol.sgl\nimport time\nimport gg.m4\n\n// GLSL Include and functions\n#include \"@VMODROOT/cube_glsl.h\" # It should be generated with `v shader .` (see the instructions at the top of this file)\n\nfn C.cube_shader_desc(gfx.Backend) &gfx.ShaderDesc\n\nconst win_width = 800\nconst win_height = 800\nconst bg_color = gg.white\n\nstruct App {\nmut:\n\tgg          &gg.Context = unsafe { nil }\n\tpip_3d      sgl.Pipeline\n\ttexture     gfx.Image\n\tsampler     gfx.Sampler\n\tinit_flag   bool\n\tframe_count int\n\tmouse_x     int = -1\n\tmouse_y     int = -1\n\t// glsl\n\tcube_pip_glsl gfx.Pipeline\n\tcube_bind     gfx.Bindings\n\t// time\n\tticks i64\n}\n\n/******************************************************************************\n*\n* Texture functions\n*\n******************************************************************************/\nfn create_texture(w int, h int, buf &u8) (gfx.Image, gfx.Sampler) {\n\tsz := w * h * 4\n\tmut img_desc := gfx.ImageDesc{\n\t\twidth:       w\n\t\theight:      h\n\t\tnum_mipmaps: 0\n\t\t// usage: .dynamic\n\t\tlabel:         &char(unsafe { nil })\n\t\td3d11_texture: 0\n\t}\n\t// comment if .dynamic is enabled\n\timg_desc.data.subimage[0][0] = gfx.Range{\n\t\tptr:  buf\n\t\tsize: usize(sz)\n\t}\n\n\tsg_img := gfx.make_image(&img_desc)\n\n\tmut smp_desc := gfx.SamplerDesc{\n\t\tmin_filter: .linear\n\t\tmag_filter: .linear\n\t\twrap_u:     .clamp_to_edge\n\t\twrap_v:     .clamp_to_edge\n\t}\n\n\tsg_smp := gfx.make_sampler(&smp_desc)\n\treturn sg_img, sg_smp\n}\n\nfn destroy_texture(sg_img gfx.Image) {\n\tgfx.destroy_image(sg_img)\n}\n\n// Use only if usage: .dynamic is enabled\nfn update_text_texture(sg_img gfx.Image, w int, h int, buf &u8) {\n\tsz := w * h * 4\n\tmut tmp_sbc := gfx.ImageData{}\n\ttmp_sbc.subimage[0][0] = gfx.Range{\n\t\tptr:  buf\n\t\tsize: usize(sz)\n\t}\n\tgfx.update_image(sg_img, &tmp_sbc)\n}\n\n/******************************************************************************\n*\n* Draw functions\n*\n******************************************************************************/\nfn draw_triangle() {\n\tsgl.defaults()\n\tsgl.begin_triangles()\n\t{\n\t\t// vfmt off\n\t\tsgl.v2f_c3b( 0.0,  0.5, 255, 0  , 0  )\n\t\tsgl.v2f_c3b(-0.5, -0.5,   0, 0  , 255)\n\t\tsgl.v2f_c3b( 0.5, -0.5,   0, 255, 0  )\n\t\t// vfmt on\n\t}\n\tsgl.end()\n}\n\n// vertex specification for a cube with colored sides and texture coords\nfn cube() {\n\tsgl.begin_quads()\n\t{\n\t\t// vfmt off\n\t\tsgl.c3f(1.0, 0.0, 0.0) // edge color\n\t\t// edge coordinates\n\t\t// x,y,z, texture cord: u,v\n\t\tsgl.v3f_t2f(-1.0,  1.0, -1.0, -1.0,  1.0)\n\t\tsgl.v3f_t2f( 1.0,  1.0, -1.0,  1.0,  1.0)\n\t\tsgl.v3f_t2f( 1.0, -1.0, -1.0,  1.0, -1.0)\n\t\tsgl.v3f_t2f(-1.0, -1.0, -1.0, -1.0, -1.0)\n\t\tsgl.c3f(0.0, 1.0, 0.0)\n\t\tsgl.v3f_t2f(-1.0, -1.0,  1.0, -1.0,  1.0)\n\t\tsgl.v3f_t2f( 1.0, -1.0,  1.0,  1.0,  1.0)\n\t\tsgl.v3f_t2f( 1.0,  1.0,  1.0,  1.0, -1.0)\n\t\tsgl.v3f_t2f(-1.0,  1.0,  1.0, -1.0, -1.0)\n\t\tsgl.c3f(0.0, 0.0, 1.0)\n\t\tsgl.v3f_t2f(-1.0, -1.0,  1.0, -1.0,  1.0)\n\t\tsgl.v3f_t2f(-1.0,  1.0,  1.0,  1.0,  1.0)\n\t\tsgl.v3f_t2f(-1.0,  1.0, -1.0,  1.0, -1.0)\n\t\tsgl.v3f_t2f(-1.0, -1.0, -1.0, -1.0, -1.0)\n\t\tsgl.c3f(1.0, 0.5, 0.0)\n\t\tsgl.v3f_t2f(1.0, -1.0,  1.0, -1.0,   1.0)\n\t\tsgl.v3f_t2f(1.0, -1.0, -1.0,  1.0,   1.0)\n\t\tsgl.v3f_t2f(1.0,  1.0, -1.0,  1.0,  -1.0)\n\t\tsgl.v3f_t2f(1.0,  1.0,  1.0, -1.0,  -1.0)\n\t\tsgl.c3f(0.0, 0.5, 1.0)\n\t\tsgl.v3f_t2f( 1.0, -1.0, -1.0, -1.0,  1.0)\n\t\tsgl.v3f_t2f( 1.0, -1.0,  1.0,  1.0,  1.0)\n\t\tsgl.v3f_t2f(-1.0, -1.0,  1.0,  1.0, -1.0)\n\t\tsgl.v3f_t2f(-1.0, -1.0, -1.0, -1.0, -1.0)\n\t\tsgl.c3f(1.0, 0.0, 0.5)\n\t\tsgl.v3f_t2f(-1.0,  1.0, -1.0, -1.0,  1.0)\n\t\tsgl.v3f_t2f(-1.0,  1.0,  1.0,  1.0,  1.0)\n\t\tsgl.v3f_t2f( 1.0,  1.0,  1.0,  1.0, -1.0)\n\t\tsgl.v3f_t2f( 1.0,  1.0, -1.0, -1.0, -1.0)\n\t\t// vfmt on\n\t}\n\tsgl.end()\n}\n\nfn draw_cubes(app App) {\n\trot := [f32(1.0) * (app.frame_count % 360), 0.5 * f32(app.frame_count % 360)]\n\t// rot := [f32(app.mouse_x), f32(app.mouse_y)]\n\n\tsgl.defaults()\n\tsgl.load_pipeline(app.pip_3d)\n\n\tsgl.matrix_mode_projection()\n\tsgl.perspective(sgl.rad(45.0), 1.0, 0.1, 100.0)\n\n\tsgl.matrix_mode_modelview()\n\tsgl.translate(0.0, 0.0, -12.0)\n\tsgl.rotate(sgl.rad(rot[0]), 1.0, 0.0, 0.0)\n\tsgl.rotate(sgl.rad(rot[1]), 0.0, 1.0, 0.0)\n\tcube()\n\tsgl.push_matrix()\n\t{\n\t\tsgl.translate(0.0, 0.0, 3.0)\n\t\tsgl.scale(0.5, 0.5, 0.5)\n\t\tsgl.rotate(-2.0 * sgl.rad(rot[0]), 1.0, 0.0, 0.0)\n\t\tsgl.rotate(-2.0 * sgl.rad(rot[1]), 0.0, 1.0, 0.0)\n\t\tcube()\n\t\tsgl.push_matrix()\n\t\t{\n\t\t\tsgl.translate(0.0, 0.0, 3.0)\n\t\t\tsgl.scale(0.5, 0.5, 0.5)\n\t\t\t// vfmt off\n\t\t\tsgl.rotate(-3.0 * sgl.rad(2 * rot[0]), 1.0, 0.0, 0.0)\n\t\t\tsgl.rotate( 3.0 * sgl.rad(2 * rot[1]), 0.0, 0.0, 1.0)\n\t\t\t// vfmt on\n\t\t\tcube()\n\t\t}\n\t\tsgl.pop_matrix()\n\t}\n\tsgl.pop_matrix()\n}\n\nfn cube_texture(r f32, g f32, b f32) {\n\tsgl.begin_quads()\n\t{\n\t\tsgl.c3f(r, g, b) // edge color\n\t\t// edge coord\n\t\t// x,y,z, texture cord: u,v\n\t\t// vfmt off\n\t\tsgl.v3f_t2f(-1.0,  1.0, -1.0,  0.0 , 0.25)\n\t\tsgl.v3f_t2f( 1.0,  1.0, -1.0,  0.25, 0.25)\n\t\tsgl.v3f_t2f( 1.0, -1.0, -1.0,  0.25, 0.0 )\n\t\tsgl.v3f_t2f(-1.0, -1.0, -1.0,  0.0 , 0.0 )\n\t\tsgl.c3f(r, g, b)\n\t\tsgl.v3f_t2f(-1.0, -1.0,  1.0,  0.0 , 0.25)\n\t\tsgl.v3f_t2f( 1.0, -1.0,  1.0,  0.25, 0.25)\n\t\tsgl.v3f_t2f( 1.0,  1.0,  1.0,  0.25, 0.0 )\n\t\tsgl.v3f_t2f(-1.0,  1.0,  1.0,  0.0 , 0.0 )\n\t\tsgl.c3f(r, g, b)\n\t\tsgl.v3f_t2f(-1.0, -1.0,  1.0,  0.0 , 0.25)\n\t\tsgl.v3f_t2f(-1.0,  1.0,  1.0,  0.25, 0.25)\n\t\tsgl.v3f_t2f(-1.0,  1.0, -1.0,  0.25, 0.0 )\n\t\tsgl.v3f_t2f(-1.0, -1.0, -1.0,  0.0 , 0.0 )\n\t\tsgl.c3f(r, g, b)\n\t\tsgl.v3f_t2f(1.0, -1.0,  1.0,  0.0 , 0.25)\n\t\tsgl.v3f_t2f(1.0, -1.0, -1.0,  0.25, 0.25)\n\t\tsgl.v3f_t2f(1.0,  1.0, -1.0,  0.25, 0.0 )\n\t\tsgl.v3f_t2f(1.0,  1.0,  1.0,  0.0 , 0.0 )\n\t\tsgl.c3f(r, g, b)\n\t\tsgl.v3f_t2f( 1.0, -1.0, -1.0, 0.0 , 0.25)\n\t\tsgl.v3f_t2f( 1.0, -1.0,  1.0, 0.25, 0.25)\n\t\tsgl.v3f_t2f(-1.0, -1.0,  1.0, 0.25, 0.0 )\n\t\tsgl.v3f_t2f(-1.0, -1.0, -1.0, 0.0 , 0.0 )\n\t\tsgl.c3f(r, g, b)\n\t\tsgl.v3f_t2f(-1.0,  1.0, -1.0,  0.0 , 0.25)\n\t\tsgl.v3f_t2f(-1.0,  1.0,  1.0,  0.25, 0.25)\n\t\tsgl.v3f_t2f( 1.0,  1.0,  1.0,  0.25, 0.0 )\n\t\tsgl.v3f_t2f( 1.0,  1.0, -1.0,  0.0 , 0.0 )\n\t\t// vfmt on\n\t}\n\tsgl.end()\n}\n\n/*\nCube vertex buffer with packed vertex formats for color and texture coords.\n\t\tNote that a vertex format which must be portable across all\n\t\tbackends must only use the normalized integer formats\n\t\t(BYTE4N, UBYTE4N, SHORT2N, SHORT4N), which can be converted\n\t\tto floating point formats in the vertex shader inputs.\n\t\tThe reason is that D3D11 cannot convert from non-normalized\n\t\tformats to floating point inputs (only to integer inputs),\n\t\tand WebGL2 / GLES2 don't support integer vertex shader inputs.\n*/\n\nstruct Vertex_t {\n\tx     f32\n\ty     f32\n\tz     f32\n\tcolor u32\n\t// u u16\n\t// v u16\n\tu f32\n\tv f32\n}\n\nfn init_cube_glsl(mut app App) {\n\t// cube vertex buffer\n\t// d := u16(32767/8)       // for compatibility with D3D11, 32767 stand for 1\n\td := f32(1.0) // 0.05)\n\tc := u32(0xFFFFFF_FF) // color RGBA8\n\t// vfmt off\n\tvertices := [\n\t\t// Face 0\n\t\tVertex_t{-1.0, -1.0, -1.0, c,  0, 0},\n\t\tVertex_t{ 1.0, -1.0, -1.0, c,  d, 0},\n\t\tVertex_t{ 1.0,  1.0, -1.0, c,  d, d},\n\t\tVertex_t{-1.0,  1.0, -1.0, c,  0, d},\n\t\t// Face 1\n\t\tVertex_t{-1.0, -1.0,  1.0, c,  0, 0},\n\t\tVertex_t{ 1.0, -1.0,  1.0, c,  d, 0},\n\t\tVertex_t{ 1.0,  1.0,  1.0, c,  d, d},\n\t\tVertex_t{-1.0,  1.0,  1.0, c,  0, d},\n\t\t// Face 2\n\t\tVertex_t{-1.0, -1.0, -1.0, c,  0, 0},\n\t\tVertex_t{-1.0,  1.0, -1.0, c,  d, 0},\n\t\tVertex_t{-1.0,  1.0,  1.0, c,  d, d},\n\t\tVertex_t{-1.0, -1.0,  1.0, c,  0, d},\n\t\t// Face 3\n\t\tVertex_t{ 1.0, -1.0, -1.0, c,  0, 0},\n\t\tVertex_t{ 1.0,  1.0, -1.0, c,  d, 0},\n\t\tVertex_t{ 1.0,  1.0,  1.0, c,  d, d},\n\t\tVertex_t{ 1.0, -1.0,  1.0, c,  0, d},\n\t\t// Face 4\n\t\tVertex_t{-1.0, -1.0, -1.0, c,  0, 0},\n\t\tVertex_t{-1.0, -1.0,  1.0, c,  d, 0},\n\t\tVertex_t{ 1.0, -1.0,  1.0, c,  d, d},\n\t\tVertex_t{ 1.0, -1.0, -1.0, c,  0, d},\n\t\t// Face 5\n\t\tVertex_t{-1.0,  1.0, -1.0, c,  0, 0},\n\t\tVertex_t{-1.0,  1.0,  1.0, c,  d, 0},\n\t\tVertex_t{ 1.0,  1.0,  1.0, c,  d, d},\n\t\tVertex_t{ 1.0,  1.0, -1.0, c,  0, d},\n\t]\n\t// vfmt on\n\n\tmut vert_buffer_desc := gfx.BufferDesc{\n\t\tlabel: c'cube-vertices'\n\t}\n\tunsafe { vmemset(&vert_buffer_desc, 0, int(sizeof(vert_buffer_desc))) }\n\n\tvert_buffer_desc.size = usize(vertices.len * int(sizeof(Vertex_t)))\n\tvert_buffer_desc.data = gfx.Range{\n\t\tptr:  vertices.data\n\t\tsize: usize(vertices.len * int(sizeof(Vertex_t)))\n\t}\n\n\tvert_buffer_desc.type = .vertexbuffer\n\t// vert_buffer_desc.usage   = .immutable\n\tvbuf := gfx.make_buffer(&vert_buffer_desc)\n\n\t// create an index buffer for the cube\n\t// vfmt off\n\tindices := [\n\t\tu16(0),  1,  2,    0,  2,  3,\n\t\t    6,   5,  4,    7,  6,  4,\n\t\t    8,   9, 10,    8, 10, 11,\n\t\t    14, 13, 12,   15, 14, 12,\n\t\t    16, 17, 18,   16, 18, 19,\n\t\t    22, 21, 20,   23, 22, 20,\n\t]\n\t// vfmt on\n\n\tmut index_buffer_desc := gfx.BufferDesc{\n\t\tlabel: c'cube-indices'\n\t}\n\tunsafe { vmemset(&index_buffer_desc, 0, int(sizeof(index_buffer_desc))) }\n\n\tindex_buffer_desc.size = usize(indices.len * int(sizeof(u16)))\n\tindex_buffer_desc.data = gfx.Range{\n\t\tptr:  indices.data\n\t\tsize: usize(indices.len * int(sizeof(u16)))\n\t}\n\n\tindex_buffer_desc.type = .indexbuffer\n\tibuf := gfx.make_buffer(&index_buffer_desc)\n\n\t// create shader\n\tshader := gfx.make_shader(voidptr(C.cube_shader_desc(C.sg_query_backend())))\n\n\tmut pipdesc := gfx.PipelineDesc{}\n\tunsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }\n\n\tpipdesc.layout.buffers[0].stride = int(sizeof(Vertex_t))\n\t// the constants [C.ATTR_vs_pos, C.ATTR_vs_color0, C.ATTR_vs_texcoord0] are generated bysokol-shdc\n\tpipdesc.layout.attrs[C.ATTR_vs_pos].format = .float3 // x,y,z as f32\n\tpipdesc.layout.attrs[C.ATTR_vs_color0].format = .ubyte4n // color as u32\n\tpipdesc.layout.attrs[C.ATTR_vs_texcoord0].format = .float2 // u,v as f32\n\t// pipdesc.layout.attrs[C.ATTR_vs_texcoord0].format  = .short2n  // u,v as u16\n\n\tpipdesc.shader = shader\n\tpipdesc.index_type = .uint16\n\n\tpipdesc.depth = gfx.DepthState{\n\t\twrite_enabled: true\n\t\tcompare:       .less_equal\n\t}\n\tpipdesc.cull_mode = .back\n\n\tpipdesc.label = c'glsl_shader pipeline'\n\n\tapp.cube_bind.vertex_buffers[0] = vbuf\n\tapp.cube_bind.index_buffer = ibuf\n\tapp.cube_bind.fs.images[C.SLOT_tex] = app.texture\n\tapp.cube_bind.fs.samplers[C.SLOT_smp] = app.sampler\n\tapp.cube_pip_glsl = gfx.make_pipeline(&pipdesc)\n\tprintln('GLSL init DONE!')\n}\n\nfn draw_cube_glsl(app App) {\n\tif app.init_flag == false {\n\t\treturn\n\t}\n\n\t// clear\n\tws := gg.window_size_real_pixels()\n\tmut color_action := gfx.ColorAttachmentAction{\n\t\tload_action: unsafe { gfx.LoadAction(C.SG_LOADACTION_DONTCARE) } // C.SG_ACTION_CLEAR)\n\t\tclear_value: gfx.Color{\n\t\t\tr: 1.0\n\t\t\tg: 1.0\n\t\t\tb: 1.0\n\t\t\ta: 1.0\n\t\t}\n\t}\n\tmut pass_action := gfx.PassAction{}\n\tpass_action.colors[0] = color_action\n\tpass := sapp.create_default_pass(pass_action)\n\tgfx.begin_pass(&pass)\n\t{\n\t\trot := [f32(app.mouse_y), f32(app.mouse_x)]\n\t\t// ratio := f32(ws.width)/ws.height\n\t\tdw := f32(ws.width / 2)\n\t\tdh := f32(ws.height / 2)\n\n\t\ttr_matrix := m4.calc_tr_matrices(dw, dh, rot[0], rot[1], 2.0)\n\t\tgfx.apply_viewport(ws.width / 2, 0, ws.width / 2, ws.height / 2, true)\n\n\t\t// apply the pipeline and bindings\n\t\tgfx.apply_pipeline(app.cube_pip_glsl)\n\t\tgfx.apply_bindings(app.cube_bind)\n\n\t\t// Uniforms:\n\t\t// passing the view matrix as uniform\n\t\t// res is a 4x4 matrix of f32 thus: 4*16 byte of size\n\t\tvs_uniforms_range := gfx.Range{\n\t\t\tptr:  &tr_matrix\n\t\t\tsize: usize(4 * 16)\n\t\t}\n\t\tgfx.apply_uniforms(.vs, C.SLOT_vs_params, &vs_uniforms_range)\n\n\t\t// fs uniforms\n\t\ttime_ticks := f32(time.ticks() - app.ticks) / 1000\n\t\tmut text_res := [\n\t\t\tf32(512),\n\t\t\t512, // x,y resolution to pass to FS\n\t\t\ttime_ticks, // time as f32\n\t\t\t0, // padding 4 Bytes == 1 f32\n\t\t]!\n\t\tfs_uniforms_range := gfx.Range{\n\t\t\tptr:  unsafe { &text_res }\n\t\t\tsize: usize(4 * 4)\n\t\t}\n\t\tgfx.apply_uniforms(.fs, C.SLOT_fs_params, &fs_uniforms_range)\n\n\t\tgfx.draw(0, (3 * 2) * 6, 1)\n\t}\n\tgfx.end_pass()\n\tgfx.commit()\n}\n\nfn draw_texture_cubes(app App) {\n\trot := [f32(app.mouse_x), f32(app.mouse_y)]\n\tsgl.defaults()\n\tsgl.load_pipeline(app.pip_3d)\n\n\tsgl.enable_texture()\n\tsgl.texture(app.texture, app.sampler)\n\n\tsgl.matrix_mode_projection()\n\tsgl.perspective(sgl.rad(45.0), 1.0, 0.1, 100.0)\n\n\tsgl.matrix_mode_modelview()\n\tsgl.translate(0.0, 0.0, -12.0)\n\tsgl.rotate(sgl.rad(rot[0]), 1.0, 0.0, 0.0)\n\tsgl.rotate(sgl.rad(rot[1]), 0.0, 1.0, 0.0)\n\tcube_texture(1, 1, 1)\n\n\tsgl.push_matrix()\n\t{\n\t\tsgl.translate(0.0, 0.0, 3.0)\n\t\tsgl.scale(0.5, 0.5, 0.5)\n\t\tsgl.rotate(-2.0 * sgl.rad(rot[0]), 1.0, 0.0, 0.0)\n\t\tsgl.rotate(-2.0 * sgl.rad(rot[1]), 0.0, 1.0, 0.0)\n\t\tcube_texture(1, 1, 1)\n\t\tsgl.push_matrix()\n\t\t{\n\t\t\tsgl.translate(0.0, 0.0, 3.0)\n\t\t\tsgl.scale(0.5, 0.5, 0.5)\n\t\t\t// vfmt off\n\t\t\tsgl.rotate(-3.0 * sgl.rad(2 * rot[0]), 1.0, 0.0, 0.0)\n\t\t\tsgl.rotate( 3.0 * sgl.rad(2 * rot[1]), 0.0, 0.0, 1.0)\n\t\t\t// vfmt on\n\t\t\tcube_texture(1, 1, 1)\n\t\t}\n\t\tsgl.pop_matrix()\n\t}\n\tsgl.pop_matrix()\n\n\tsgl.disable_texture()\n}\n\nfn frame(mut app App) {\n\tws := gg.window_size_real_pixels()\n\tratio := f32(ws.width) / ws.height\n\tdw := ws.width\n\tdh := ws.height\n\tww := int(dh / 3) // not a bug\n\thh := int(dh / 3)\n\tx0 := int(f32(dw) * 0.05)\n\t// x1 := dw/2\n\ty0 := 0\n\ty1 := int(f32(dh) * 0.5)\n\n\tapp.gg.begin()\n\t{\n\t\tsgl.defaults()\n\n\t\t// 2d triangle\n\t\tsgl.viewport(x0, y0, ww, hh, true)\n\t\tdraw_triangle()\n\n\t\t// colored cubes with viewport\n\t\tsgl.viewport(x0, y1, ww, hh, true)\n\t\tdraw_cubes(app)\n\n\t\t// textured cubed with viewport\n\t\tsgl.viewport(0, int(dh / 5), dw, int(dh * ratio), true)\n\t\tdraw_texture_cubes(app)\n\t}\n\tapp.gg.end()\n\n\t// glsl cube\n\tdraw_cube_glsl(app)\n\n\tapp.frame_count++\n}\n\n/******************************************************************************\n* Init / Cleanup\n******************************************************************************/\nfn my_init(mut app App) {\n\t// set max vertices,\n\t// for a large number of the same type of object it is better use the instances!!\n\tdesc := sapp.create_desc()\n\tgfx.setup(&desc)\n\tsgl_desc := sgl.Desc{\n\t\tmax_vertices: 50 * 65536\n\t}\n\tsgl.setup(&sgl_desc)\n\n\t// 3d pipeline\n\tmut pipdesc := gfx.PipelineDesc{}\n\tunsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }\n\n\tcolor_state := gfx.ColorTargetState{\n\t\tblend: gfx.BlendState{\n\t\t\tenabled:        true\n\t\t\tsrc_factor_rgb: .src_alpha\n\t\t\tdst_factor_rgb: .one_minus_src_alpha\n\t\t}\n\t}\n\tpipdesc.colors[0] = color_state\n\n\tpipdesc.depth = gfx.DepthState{\n\t\twrite_enabled: true\n\t\tcompare:       .less_equal\n\t}\n\tpipdesc.cull_mode = .back\n\n\tapp.pip_3d = sgl.make_pipeline(&pipdesc)\n\n\t// create chessboard texture 256*256 RGBA\n\tw := 256\n\th := 256\n\tsz := w * h * 4\n\ttmp_txt := unsafe { malloc(sz) }\n\tmut i := 0\n\tfor i < sz {\n\t\tunsafe {\n\t\t\ty := (i >> 0x8) >> 5 // 8 cell\n\t\t\tx := (i & 0xFF) >> 5 // 8 cell\n\t\t\t// upper left corner\n\t\t\tif x == 0 && y == 0 {\n\t\t\t\ttmp_txt[i] = u8(0xFF)\n\t\t\t\ttmp_txt[i + 1] = u8(0)\n\t\t\t\ttmp_txt[i + 2] = u8(0)\n\t\t\t\ttmp_txt[i + 3] = u8(0xFF)\n\t\t\t}\n\t\t\t// low right corner\n\t\t\telse if x == 7 && y == 7 {\n\t\t\t\ttmp_txt[i + 0] = u8(0)\n\t\t\t\ttmp_txt[i + 1] = u8(0xFF)\n\t\t\t\ttmp_txt[i + 2] = u8(0)\n\t\t\t\ttmp_txt[i + 3] = u8(0xFF)\n\t\t\t} else {\n\t\t\t\tcol := if ((x + y) & 1) == 1 { 0xFF } else { 128 }\n\t\t\t\ttmp_txt[i + 0] = u8(col) // red\n\t\t\t\ttmp_txt[i + 1] = u8(col) // green\n\t\t\t\ttmp_txt[i + 2] = u8(col) // blue\n\t\t\t\ttmp_txt[i + 3] = u8(0xFF) // alpha\n\t\t\t}\n\t\t\ti += 4\n\t\t}\n\t}\n\tapp.texture, app.sampler = create_texture(w, h, tmp_txt)\n\tunsafe { free(tmp_txt) }\n\n\t// glsl\n\tinit_cube_glsl(mut app)\n\tapp.init_flag = true\n}\n\n/******************************************************************************\n* event\n******************************************************************************/\nfn my_event_manager(mut ev gg.Event, mut app App) {\n\tif ev.typ == .mouse_move {\n\t\tapp.mouse_x = int(ev.mouse_x)\n\t\tapp.mouse_y = int(ev.mouse_y)\n\t}\n\tif ev.typ == .touches_began || ev.typ == .touches_moved {\n\t\tif ev.num_touches > 0 {\n\t\t\ttouch_point := ev.touches[0]\n\t\t\tapp.mouse_x = int(touch_point.pos_x)\n\t\t\tapp.mouse_y = int(touch_point.pos_y)\n\t\t}\n\t}\n}\n\nfn main() {\n\t// App init\n\tmut app := &App{}\n\n\tmut a := [5]int{}\n\ta[0] = 2\n\tprintln(a)\n\n\tapp.gg = gg.new_context(\n\t\twidth:         win_width\n\t\theight:        win_height\n\t\tcreate_window: true\n\t\twindow_title:  '3D Cube Demo'\n\t\tuser_data:     app\n\t\tbg_color:      bg_color\n\t\tframe_fn:      frame\n\t\tinit_fn:       my_init\n\t\tevent_fn:      my_event_manager\n\t)\n\n\tapp.ticks = time.ticks()\n\tapp.gg.run()\n}\n"
  },
  {
    "path": "examples/sokol/02_cubes_glsl/v.mod",
    "content": ""
  },
  {
    "path": "examples/sokol/03_march_tracing_glsl/rt_glsl.glsl",
    "content": "//------------------------------------------------------------------------------\n//  Shader code for texcube-sapp sample.\n//\n//  NOTE: This source file also uses the '#pragma sokol' form of the\n//  custom tags.\n//------------------------------------------------------------------------------\n//#pragma sokol @ctype mat4 hmm_mat4\n\n#pragma sokol @vs vs\nuniform vs_params {\n    mat4 mvp;\n};\n\nin vec4 pos;\nin vec4 color0;\nin vec2 texcoord0;\n\nout vec4 color;\nout vec2 uv;\n\nvoid main() {\n    gl_Position = mvp * pos;\n    color = color0;\n    uv = texcoord0;\n}\n#pragma sokol @end\n\n#pragma sokol @fs fs\nuniform texture2D tex;\nuniform sampler smp;\nuniform fs_params {\n\tvec2 iResolution;\n\tvec2 iMouse;\n\tfloat iTime;\n\tfloat iFrame;\n};\n\nin vec4 color;\nin vec2 uv;\nout vec4 frag_color;\n\n// change to 0 to 4 to increment the AntiAliasing,\n// increase AA will SLOW the rendering!!\n#define AA 1\n\n//*********************************************************\n// Ray Marching\n// original code from: https://www.shadertoy.com/view/Xds3zN\n//*********************************************************\n// The MIT License\n// Copyright © 2013 Inigo Quilez\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// A list of useful distance function to simple primitives. All\n// these functions (except for ellipsoid) return an exact\n// euclidean distance, meaning they produce a better SDF than\n// what you'd get if you were constructing them from boolean\n// operations.\n//\n// More info here:\n//\n// https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm\n\n//------------------------------------------------------------------\nfloat dot2( in vec2 v ) { return dot(v,v); }\nfloat dot2( in vec3 v ) { return dot(v,v); }\nfloat ndot( in vec2 a, in vec2 b ) { return a.x*b.x - a.y*b.y; }\n\nfloat sdPlane( vec3 p )\n{\n\treturn p.y;\n}\n\nfloat sdSphere( vec3 p, float s )\n{\n\treturn length(p)-s;\n}\n\nfloat sdBox( vec3 p, vec3 b )\n{\n\tvec3 d = abs(p) - b;\n\treturn min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));\n}\n\nfloat sdBoundingBox( vec3 p, vec3 b, float e )\n{\n\tp = abs(p  )-b;\n\tvec3 q = abs(p+e)-e;\n\n\treturn min(min(\n\t\tlength(max(vec3(p.x,q.y,q.z),0.0))+min(max(p.x,max(q.y,q.z)),0.0),\n\t\tlength(max(vec3(q.x,p.y,q.z),0.0))+min(max(q.x,max(p.y,q.z)),0.0)),\n\t\tlength(max(vec3(q.x,q.y,p.z),0.0))+min(max(q.x,max(q.y,p.z)),0.0));\n}\nfloat sdEllipsoid( in vec3 p, in vec3 r ) // approximated\n{\n\tfloat k0 = length(p/r);\n\tfloat k1 = length(p/(r*r));\n\treturn k0*(k0-1.0)/k1;\n}\n\nfloat sdTorus( vec3 p, vec2 t )\n{\n\treturn length( vec2(length(p.xz)-t.x,p.y) )-t.y;\n}\n\nfloat sdCappedTorus(in vec3 p, in vec2 sc, in float ra, in float rb)\n{\n\tp.x = abs(p.x);\n\tfloat k = (sc.y*p.x>sc.x*p.y) ? dot(p.xy,sc) : length(p.xy);\n\treturn sqrt( dot(p,p) + ra*ra - 2.0*ra*k ) - rb;\n}\n\nfloat sdHexPrism( vec3 p, vec2 h )\n{\n\tvec3 q = abs(p);\n\n\tconst vec3 k = vec3(-0.8660254, 0.5, 0.57735);\n\tp = abs(p);\n\tp.xy -= 2.0*min(dot(k.xy, p.xy), 0.0)*k.xy;\n\tvec2 d = vec2(\n\t\tlength(p.xy - vec2(clamp(p.x, -k.z*h.x, k.z*h.x), h.x))*sign(p.y - h.x),\n\t\tp.z-h.y );\n\treturn min(max(d.x,d.y),0.0) + length(max(d,0.0));\n}\n\nfloat sdOctogonPrism( in vec3 p, in float r, float h )\n{\n\tconst vec3 k = vec3(-0.9238795325,   // sqrt(2+sqrt(2))/2\n\t\t\t\t\t\t\t\t\t\t\t 0.3826834323,   // sqrt(2-sqrt(2))/2\n\t\t\t\t\t\t\t\t\t\t\t 0.4142135623 ); // sqrt(2)-1\n\t// reflections\n\tp = abs(p);\n\tp.xy -= 2.0*min(dot(vec2( k.x,k.y),p.xy),0.0)*vec2( k.x,k.y);\n\tp.xy -= 2.0*min(dot(vec2(-k.x,k.y),p.xy),0.0)*vec2(-k.x,k.y);\n\t// polygon side\n\tp.xy -= vec2(clamp(p.x, -k.z*r, k.z*r), r);\n\tvec2 d = vec2( length(p.xy)*sign(p.y), p.z-h );\n\treturn min(max(d.x,d.y),0.0) + length(max(d,0.0));\n}\n\nfloat sdCapsule( vec3 p, vec3 a, vec3 b, float r )\n{\n\tvec3 pa = p-a, ba = b-a;\n\tfloat h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n\treturn length( pa - ba*h ) - r;\n}\n\nfloat sdRoundCone( in vec3 p, in float r1, float r2, float h )\n{\n\tvec2 q = vec2( length(p.xz), p.y );\n\n\tfloat b = (r1-r2)/h;\n\tfloat a = sqrt(1.0-b*b);\n\tfloat k = dot(q,vec2(-b,a));\n\n\tif( k < 0.0 ) return length(q) - r1;\n\tif( k > a*h ) return length(q-vec2(0.0,h)) - r2;\n\n\treturn dot(q, vec2(a,b) ) - r1;\n}\n\nfloat sdRoundCone(vec3 p, vec3 a, vec3 b, float r1, float r2)\n{\n\t// sampling independent computations (only depend on shape)\n\tvec3  ba = b - a;\n\tfloat l2 = dot(ba,ba);\n\tfloat rr = r1 - r2;\n\tfloat a2 = l2 - rr*rr;\n\tfloat il2 = 1.0/l2;\n\n\t// sampling dependent computations\n\tvec3 pa = p - a;\n\tfloat y = dot(pa,ba);\n\tfloat z = y - l2;\n\tfloat x2 = dot2( pa*l2 - ba*y );\n\tfloat y2 = y*y*l2;\n\tfloat z2 = z*z*l2;\n\n\t// single square root!\n\tfloat k = sign(rr)*rr*rr*x2;\n\tif( sign(z)*a2*z2 > k ) return  sqrt(x2 + z2)        *il2 - r2;\n\tif( sign(y)*a2*y2 < k ) return  sqrt(x2 + y2)        *il2 - r1;\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn (sqrt(x2*a2*il2)+y*rr)*il2 - r1;\n}\n\nfloat sdTriPrism( vec3 p, vec2 h )\n{\n\tconst float k = sqrt(3.0);\n\th.x *= 0.5*k;\n\tp.xy /= h.x;\n\tp.x = abs(p.x) - 1.0;\n\tp.y = p.y + 1.0/k;\n\tif( p.x+k*p.y>0.0 ) p.xy=vec2(p.x-k*p.y,-k*p.x-p.y)/2.0;\n\tp.x -= clamp( p.x, -2.0, 0.0 );\n\tfloat d1 = length(p.xy)*sign(-p.y)*h.x;\n\tfloat d2 = abs(p.z)-h.y;\n\treturn length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.);\n}\n\n// vertical\nfloat sdCylinder( vec3 p, vec2 h )\n{\n\tvec2 d = abs(vec2(length(p.xz),p.y)) - h;\n\treturn min(max(d.x,d.y),0.0) + length(max(d,0.0));\n}\n\n// arbitrary orientation\nfloat sdCylinder(vec3 p, vec3 a, vec3 b, float r)\n{\n\tvec3 pa = p - a;\n\tvec3 ba = b - a;\n\tfloat baba = dot(ba,ba);\n\tfloat paba = dot(pa,ba);\n\n\tfloat x = length(pa*baba-ba*paba) - r*baba;\n\tfloat y = abs(paba-baba*0.5)-baba*0.5;\n\tfloat x2 = x*x;\n\tfloat y2 = y*y*baba;\n\tfloat d = (max(x,y)<0.0)?-min(x2,y2):(((x>0.0)?x2:0.0)+((y>0.0)?y2:0.0));\n\treturn sign(d)*sqrt(abs(d))/baba;\n}\n\n// vertical\nfloat sdCone( in vec3 p, in vec2 c, float h )\n{\n\tvec2 q = h*vec2(c.x,-c.y)/c.y;\n\tvec2 w = vec2( length(p.xz), p.y );\n\n\tvec2 a = w - q*clamp( dot(w,q)/dot(q,q), 0.0, 1.0 );\n\tvec2 b = w - q*vec2( clamp( w.x/q.x, 0.0, 1.0 ), 1.0 );\n\tfloat k = sign( q.y );\n\tfloat d = min(dot( a, a ),dot(b, b));\n\tfloat s = max( k*(w.x*q.y-w.y*q.x),k*(w.y-q.y)  );\n\treturn sqrt(d)*sign(s);\n}\n\nfloat sdCappedCone( in vec3 p, in float h, in float r1, in float r2 )\n{\n\tvec2 q = vec2( length(p.xz), p.y );\n\n\tvec2 k1 = vec2(r2,h);\n\tvec2 k2 = vec2(r2-r1,2.0*h);\n\tvec2 ca = vec2(q.x-min(q.x,(q.y < 0.0)?r1:r2), abs(q.y)-h);\n\tvec2 cb = q - k1 + k2*clamp( dot(k1-q,k2)/dot2(k2), 0.0, 1.0 );\n\tfloat s = (cb.x < 0.0 && ca.y < 0.0) ? -1.0 : 1.0;\n\treturn s*sqrt( min(dot2(ca),dot2(cb)) );\n}\n\nfloat sdCappedCone(vec3 p, vec3 a, vec3 b, float ra, float rb)\n{\n\tfloat rba  = rb-ra;\n\tfloat baba = dot(b-a,b-a);\n\tfloat papa = dot(p-a,p-a);\n\tfloat paba = dot(p-a,b-a)/baba;\n\n\tfloat x = sqrt( papa - paba*paba*baba );\n\n\tfloat cax = max(0.0,x-((paba<0.5)?ra:rb));\n\tfloat cay = abs(paba-0.5)-0.5;\n\n\tfloat k = rba*rba + baba;\n\tfloat f = clamp( (rba*(x-ra)+paba*baba)/k, 0.0, 1.0 );\n\n\tfloat cbx = x-ra - f*rba;\n\tfloat cby = paba - f;\n\n\tfloat s = (cbx < 0.0 && cay < 0.0) ? -1.0 : 1.0;\n\n\treturn s*sqrt( min(cax*cax + cay*cay*baba,\n\t\t\t\t\t\t\t\tcbx*cbx + cby*cby*baba) );\n}\n\n// c is the sin/cos of the desired cone angle\nfloat sdSolidAngle(vec3 pos, vec2 c, float ra)\n{\n\tvec2 p = vec2( length(pos.xz), pos.y );\n\tfloat l = length(p) - ra;\n\tfloat m = length(p - c*clamp(dot(p,c),0.0,ra) );\n\treturn max(l,m*sign(c.y*p.x-c.x*p.y));\n}\n\nfloat sdOctahedron(vec3 p, float s)\n{\n\tp = abs(p);\n\tfloat m = p.x + p.y + p.z - s;\n\n// exact distance\n#if 0\n\tvec3 o = min(3.0*p - m, 0.0);\n\to = max(6.0*p - m*2.0 - o*3.0 + (o.x+o.y+o.z), 0.0);\n\treturn length(p - s*o/(o.x+o.y+o.z));\n#endif\n\n// exact distance\n#if 1\n\tvec3 q;\n\t\t\t if( 3.0*p.x < m ) q = p.xyz;\n\telse if( 3.0*p.y < m ) q = p.yzx;\n\telse if( 3.0*p.z < m ) q = p.zxy;\n\telse return m*0.57735027;\n\tfloat k = clamp(0.5*(q.z-q.y+s),0.0,s);\n\treturn length(vec3(q.x,q.y-s+k,q.z-k));\n#endif\n\n// bound, not exact\n#if 0\n\treturn m*0.57735027;\n#endif\n}\n\nfloat sdPyramid( in vec3 p, in float h )\n{\n\tfloat m2 = h*h + 0.25;\n\n\t// symmetry\n\tp.xz = abs(p.xz);\n\tp.xz = (p.z>p.x) ? p.zx : p.xz;\n\tp.xz -= 0.5;\n\n\t// project into face plane (2D)\n\tvec3 q = vec3( p.z, h*p.y - 0.5*p.x, h*p.x + 0.5*p.y);\n\n\tfloat s = max(-q.x,0.0);\n\tfloat t = clamp( (q.y-0.5*p.z)/(m2+0.25), 0.0, 1.0 );\n\n\tfloat a = m2*(q.x+s)*(q.x+s) + q.y*q.y;\n\tfloat b = m2*(q.x+0.5*t)*(q.x+0.5*t) + (q.y-m2*t)*(q.y-m2*t);\n\n\tfloat d2 = min(q.y,-q.x*m2-q.y*0.5) > 0.0 ? 0.0 : min(a,b);\n\n\t// recover 3D and scale, and add sign\n\treturn sqrt( (d2+q.z*q.z)/m2 ) * sign(max(q.z,-p.y));\n}\n\n// la,lb=semi axis, h=height, ra=corner\nfloat sdRhombus(vec3 p, float la, float lb, float h, float ra)\n{\n\tp = abs(p);\n\tvec2 b = vec2(la,lb);\n\tfloat f = clamp( (ndot(b,b-2.0*p.xz))/dot(b,b), -1.0, 1.0 );\n\tvec2 q = vec2(length(p.xz-0.5*b*vec2(1.0-f,1.0+f))*sign(p.x*b.y+p.z*b.x-b.x*b.y)-ra, p.y-h);\n\treturn min(max(q.x,q.y),0.0) + length(max(q,0.0));\n}\n\n//------------------------------------------------------------------\n\nvec2 opU( vec2 d1, vec2 d2 )\n{\n\treturn (d1.x<d2.x) ? d1 : d2;\n}\n\n//------------------------------------------------------------------\n\n#define ZERO (min(int(iFrame),0))\n\n//------------------------------------------------------------------\n\nvec2 map( in vec3 pos )\n{\n\tvec2 res = vec2( 1e10, 0.0 );\n\n\t{\n\t\tres = opU( res, vec2( sdSphere(    pos-vec3(-2.0,0.25, 0.0), 0.25 ), 26.9 ) );\n\t}\n\n\t// bounding box\n\tif( sdBox( pos-vec3(0.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )\n\t{\n\t\t// more primitives\n\t\tres = opU( res, vec2( sdBoundingBox( pos-vec3( 0.0,0.25, 0.0), vec3(0.3,0.25,0.2), 0.025 ), 16.9 ) );\n\t\tres = opU( res, vec2( sdTorus(      (pos-vec3( 0.0,0.30, 1.0)).xzy, vec2(0.25,0.05) ), 25.0 ) );\n\t\tres = opU( res, vec2( sdCone(        pos-vec3( 0.0,0.45,-1.0), vec2(0.6,0.8),0.45 ), 55.0 ) );\n\t\tres = opU( res, vec2( sdCappedCone(  pos-vec3( 0.0,0.25,-2.0), 0.25, 0.25, 0.1 ), 13.67 ) );\n\t\tres = opU( res, vec2( sdSolidAngle(  pos-vec3( 0.0,0.00,-3.0), vec2(3,4)/5.0, 0.4 ), 49.13 ) );\n\t}\n\n\t// bounding box\n\tif( sdBox( pos-vec3(1.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )\n\t{\n\t\t// more primitives\n\t\tres = opU( res, vec2( sdCappedTorus((pos-vec3( 1.0,0.30, 1.0))*vec3(1,-1,1), vec2(0.866025,-0.5), 0.25, 0.05), 8.5) );\n\t\tres = opU( res, vec2( sdBox(         pos-vec3( 1.0,0.25, 0.0), vec3(0.3,0.25,0.1) ), 3.0 ) );\n\t\tres = opU( res, vec2( sdCapsule(     pos-vec3( 1.0,0.00,-1.0),vec3(-0.1,0.1,-0.1), vec3(0.2,0.4,0.2), 0.1  ), 31.9 ) );\n\t\tres = opU( res, vec2( sdCylinder(    pos-vec3( 1.0,0.25,-2.0), vec2(0.15,0.25) ), 8.0 ) );\n\t\tres = opU( res, vec2( sdHexPrism(    pos-vec3( 1.0,0.2,-3.0), vec2(0.2,0.05) ), 18.4 ) );\n\t}\n\n\t// bounding box\n\tif( sdBox( pos-vec3(-1.0,0.35,-1.0),vec3(0.35,0.35,2.5))<res.x )\n\t{\n\t\t// more primitives\n\t\tres = opU( res, vec2( sdPyramid(    pos-vec3(-1.0,-0.6,-3.0), 1.0 ), 13.56 ) );\n\t\tres = opU( res, vec2( sdOctahedron( pos-vec3(-1.0,0.15,-2.0), 0.35 ), 23.56 ) );\n\t\tres = opU( res, vec2( sdTriPrism(   pos-vec3(-1.0,0.15,-1.0), vec2(0.3,0.05) ),43.5 ) );\n\t\tres = opU( res, vec2( sdEllipsoid(  pos-vec3(-1.0,0.25, 0.0), vec3(0.2, 0.25, 0.05) ), 43.17 ) );\n\t\tres = opU( res, vec2( sdRhombus(   (pos-vec3(-1.0,0.34, 1.0)).xzy, 0.15, 0.25, 0.04, 0.08 ),17.0 ) );\n\t}\n\n\t// bounding box\n\tif( sdBox( pos-vec3(2.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )\n\t{\n\t\t// more primitives\n\t\tres = opU( res, vec2( sdOctogonPrism(pos-vec3( 2.0,0.2,-3.0), 0.2, 0.05), 51.8 ) );\n\t\tres = opU( res, vec2( sdCylinder(    pos-vec3( 2.0,0.15,-2.0), vec3(0.1,-0.1,0.0), vec3(-0.2,0.35,0.1), 0.08), 31.2 ) );\n\t\tres = opU( res, vec2( sdCappedCone(  pos-vec3( 2.0,0.10,-1.0), vec3(0.1,0.0,0.0), vec3(-0.2,0.40,0.1), 0.15, 0.05), 46.1 ) );\n\t\tres = opU( res, vec2( sdRoundCone(   pos-vec3( 2.0,0.15, 0.0), vec3(0.1,0.0,0.0), vec3(-0.1,0.35,0.1), 0.15, 0.05), 51.7 ) );\n\t\tres = opU( res, vec2( sdRoundCone(   pos-vec3( 2.0,0.20, 1.0), 0.2, 0.1, 0.3 ), 37.0 ) );\n\t}\n\n\treturn res;\n}\n\n// http://iquilezles.org/www/articles/boxfunctions/boxfunctions.htm\nvec2 iBox( in vec3 ro, in vec3 rd, in vec3 rad )\n{\n\tvec3 m = 1.0/rd;\n\tvec3 n = m*ro;\n\tvec3 k = abs(m)*rad;\n\tvec3 t1 = -n - k;\n\tvec3 t2 = -n + k;\n\treturn vec2( max( max( t1.x, t1.y ), t1.z ),\n\t\t\t\t\t\t\tmin( min( t2.x, t2.y ), t2.z ) );\n}\n\nvec2 raycast( in vec3 ro, in vec3 rd )\n{\n\tvec2 res = vec2(-1.0,-1.0);\n\n\tfloat tmin = 1.0;\n\tfloat tmax = 20.0;\n\n\t// raytrace floor plane\n\tfloat tp1 = (0.0-ro.y)/rd.y;\n\tif( tp1>0.0 )\n\t{\n\t\ttmax = min( tmax, tp1 );\n\t\tres = vec2( tp1, 1.0 );\n\t}\n\t//else return res;\n\n\t// raymarch primitives\n\tvec2 tb = iBox( ro-vec3(0.0,0.4,-0.5), rd, vec3(2.5,0.41,3.0) );\n\tif( tb.x<tb.y && tb.y>0.0 && tb.x<tmax)\n\t{\n\t\t//return vec2(tb.x,2.0);\n\t\ttmin = max(tb.x,tmin);\n\t\ttmax = min(tb.y,tmax);\n\n\t\tfloat t = tmin;\n\t\tfor( int i=0; i<70 && t<tmax; i++ )\n\t\t{\n\t\t\tvec2 h = map( ro+rd*t );\n\t\t\tif( abs(h.x)<(0.0001*t) )\n\t\t\t{\n\t\t\t\tres = vec2(t,h.y);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tt += h.x;\n\t\t}\n\t}\n\n\treturn res;\n}\n\n// http://iquilezles.org/www/articles/rmshadows/rmshadows.htm\nfloat calcSoftshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax )\n{\n\t// bounding volume\n\tfloat tp = (0.8-ro.y)/rd.y; if( tp>0.0 ) tmax = min( tmax, tp );\n\n\tfloat res = 1.0;\n\tfloat t = mint;\n\tfor( int i=ZERO; i<24; i++ )\n\t{\n\tfloat h = map( ro + rd*t ).x;\n\t\tfloat s = clamp(8.0*h/t,0.0,1.0);\n\t\tres = min( res, s*s*(3.0-2.0*s) );\n\t\tt += clamp( h, 0.02, 0.2 );\n\t\tif( res<0.004 || t>tmax ) break;\n\t}\n\treturn clamp( res, 0.0, 1.0 );\n}\n\n// http://iquilezles.org/www/articles/normalsSDF/normalsSDF.htm\nvec3 calcNormal( in vec3 pos )\n{\n#if 0\n\tvec2 e = vec2(1.0,-1.0)*0.5773*0.0005;\n\treturn normalize( e.xyy*map( pos + e.xyy ).x +\n\t\te.yyx*map( pos + e.yyx ).x +\n\t\te.yxy*map( pos + e.yxy ).x +\n\t\te.xxx*map( pos + e.xxx ).x );\n#else\n\t// inspired by tdhooper and klems - a way to prevent the compiler from inlining map() 4 times\n\tvec3 n = vec3(0.0);\n\tfor( int i=ZERO; i<4; i++ )\n\t{\n\t\tvec3 e = 0.5773*(2.0*vec3((((i+3)>>1)&1),((i>>1)&1),(i&1))-1.0);\n\t\tn += e*map(pos+0.0005*e).x;\n\t\t//if( n.x+n.y+n.z>100.0 ) break;\n\t}\n\treturn normalize(n);\n#endif\n}\n\nfloat calcAO( in vec3 pos, in vec3 nor )\n{\n\tfloat occ = 0.0;\n\tfloat sca = 1.0;\n\tfor( int i=ZERO; i<5; i++ )\n\t{\n\t\tfloat h = 0.01 + 0.12*float(i)/4.0;\n\t\tfloat d = map( pos + h*nor ).x;\n\t\tocc += (h-d)*sca;\n\t\tsca *= 0.95;\n\t\tif( occ>0.35 ) break;\n\t}\n\treturn clamp( 1.0 - 3.0*occ, 0.0, 1.0 ) * (0.5+0.5*nor.y);\n}\n\n// http://iquilezles.org/www/articles/checkerfiltering/checkerfiltering.htm\nfloat checkersGradBox( in vec2 p, in vec2 dpdx, in vec2 dpdy )\n{\n\t// filter kernel\n\tvec2 w = abs(dpdx)+abs(dpdy) + 0.001;\n\t// analytical integral (box filter)\n\tvec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w;\n\t// xor pattern\n\treturn 0.5 - 0.5*i.x*i.y;\n}\n\nvec3 render( in vec3 ro, in vec3 rd, in vec3 rdx, in vec3 rdy )\n{\n\t// background\n\tvec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3;\n\n\t// raycast scene\n\tvec2 res = raycast(ro,rd);\n\tfloat t = res.x;\n\tfloat m = res.y;\n\tif( m>-0.5 )\n\t{\n\t\tvec3 pos = ro + t*rd;\n\t\tvec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal( pos );\n\t\tvec3 ref = reflect( rd, nor );\n\n\t\t// material\n\t\tcol = 0.2 + 0.2*sin( m*2.0 + vec3(0.0,1.0,2.0) );\n\t\tfloat ks = 1.0;\n\n\t\tif( m<1.5 )\n\t\t{\n\t\t\t// project pixel footprint into the plane\n\t\t\tvec3 dpdx = ro.y*(rd/rd.y-rdx/rdx.y);\n\t\t\tvec3 dpdy = ro.y*(rd/rd.y-rdy/rdy.y);\n\n\t\t\tfloat f = checkersGradBox( 3.0*pos.xz, 3.0*dpdx.xz, 3.0*dpdy.xz );\n\t\t\tcol = 0.15 + f*vec3(0.05);\n\t\t\tks = 0.4;\n\t\t}\n\n\t\t// lighting\n\t\tfloat occ = calcAO( pos, nor );\n\n\t\tvec3 lin = vec3(0.0);\n\n\t\t// sun\n\t\t{\n\t\t\tvec3  lig = normalize( vec3(-0.5, 0.4, -0.6) );\n\t\t\tvec3  hal = normalize( lig-rd );\n\t\t\tfloat dif = clamp( dot( nor, lig ), 0.0, 1.0 );\n\t\t\t//if( dif>0.0001 )\n\t\t\t\tdif *= calcSoftshadow( pos, lig, 0.02, 2.5 );\n\t\t\tfloat spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0);\n\t\t\t\t\t\tspe *= dif;\n\t\t\t\t\t\tspe *= 0.04+0.96*pow(clamp(1.0-dot(hal,lig),0.0,1.0),5.0);\n\t\t\tlin += col*2.20*dif*vec3(1.30,1.00,0.70);\n\t\t\tlin +=     5.00*spe*vec3(1.30,1.00,0.70)*ks;\n\t\t}\n\t\t// sky\n\t\t{\n\t\t\tfloat dif = sqrt(clamp( 0.5+0.5*nor.y, 0.0, 1.0 ));\n\t\t\t\t\t\tdif *= occ;\n\t\t\tfloat spe = smoothstep( -0.2, 0.2, ref.y );\n\t\t\t\t\t\tspe *= dif;\n\t\t\t\t\t\tspe *= 0.04+0.96*pow(clamp(1.0+dot(nor,rd),0.0,1.0), 5.0 );\n\t\t\t//if( spe>0.001 )\n\t\t\t\t\t\tspe *= calcSoftshadow( pos, ref, 0.02, 2.5 );\n\t\t\tlin += col*0.60*dif*vec3(0.40,0.60,1.15);\n\t\t\tlin +=     2.00*spe*vec3(0.40,0.60,1.30)*ks;\n\t\t}\n\t\t// back\n\t\t{\n\t\t\tfloat dif = clamp( dot( nor, normalize(vec3(0.5,0.0,0.6))), 0.0, 1.0 )*clamp( 1.0-pos.y,0.0,1.0);\n\t\t\t\t\t\t\tdif *= occ;\n\t\t\tlin += col*0.55*dif*vec3(0.25,0.25,0.25);\n\t\t}\n\t\t// sss\n\t\t{\n\t\t\tfloat dif = pow(clamp(1.0+dot(nor,rd),0.0,1.0),2.0);\n\t\t\t\t\t\tdif *= occ;\n\t\t\tlin += col*0.25*dif*vec3(1.00,1.00,1.00);\n\t\t}\n\n\t\tcol = lin;\n\n\t\tcol = mix( col, vec3(0.7,0.7,0.9), 1.0-exp( -0.0001*t*t*t ) );\n\t}\n\n\treturn vec3( clamp(col,0.0,1.0) );\n}\n\nmat3 setCamera( in vec3 ro, in vec3 ta, float cr )\n{\n\tvec3 cw = normalize(ta-ro);\n\tvec3 cp = vec3(sin(cr), cos(cr),0.0);\n\tvec3 cu = normalize( cross(cw,cp) );\n\tvec3 cv =          ( cross(cu,cw) );\n\treturn mat3( cu, cv, cw );\n}\n\nvec4 mainImage( vec2 fragCoord )\n{\n\tvec2 mo = iMouse.xy/iResolution.xy;\n\tfloat time = 32.0 + iTime*1.5;\n\n\t// camera\n\tvec3 ta = vec3( 0.5, -0.5, -0.6 );\n\tvec3 ro = ta + vec3( 4.5*cos(0.1*time + 7.0*mo.x), 1.3 + 2.0*mo.y, 4.5*sin(0.1*time + 7.0*mo.x) );\n\t// camera-to-world transformation\n\tmat3 ca = setCamera( ro, ta, 0.0 );\n\n\tvec3 tot = vec3(0.0);\n#if AA>1\n\tfor( int m=ZERO; m<AA; m++ )\n\tfor( int n=ZERO; n<AA; n++ )\n\t{\n\t\t// pixel coordinates\n\t\tvec2 o = vec2(float(m),float(n)) / float(AA) - 0.5;\n\t\tvec2 p = (2.0*(fragCoord+o)-iResolution.xy)/iResolution.y;\n#else\n\t\tvec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y;\n#endif\n\n\t\t// focal length\n\t\tconst float fl = 2.5;\n\n\t\t// ray direction\n\t\tvec3 rd = ca * normalize( vec3(p,fl) );\n\n\t\t // ray differentials\n\t\tvec2 px = (2.0*(fragCoord+vec2(1.0,0.0))-iResolution.xy)/iResolution.y;\n\t\tvec2 py = (2.0*(fragCoord+vec2(0.0,1.0))-iResolution.xy)/iResolution.y;\n\t\tvec3 rdx = ca * normalize( vec3(px,fl) );\n\t\tvec3 rdy = ca * normalize( vec3(py,fl) );\n\n\t\t// render\n\t\tvec3 col = render( ro, rd, rdx, rdy );\n\n\t\t// gain\n\t\t// col = col*3.0/(2.5+col);\n\n\t\t// gamma\n\t\tcol = pow( col, vec3(0.4545) );\n\n\t\ttot += col;\n#if AA>1\n\t}\n\ttot /= float(AA*AA);\n#endif\n\n\t//fragColor = vec4( tot, 1.0 );\n\treturn vec4( tot, 1.0 );\n}\n\n//*********************************************************\n// END Ray Marching\n//*********************************************************\n\nvoid main() {\n\tvec4 c = color;\n\tvec4 txt = texture(sampler2D(tex, smp), uv);\n\tc = txt * c;\n\tvec2 uv1 = uv * iResolution;\n\tvec4 col_ray = mainImage(uv1);\n\n\t// use this to mix the chessboart texture with the ray marching\n\t//frag_color = clamp(c*iMouse.y/512.0,0.0,1.0) *\tcol_ray\t;\n\n\tfrag_color = c*0.00001 +\tcol_ray\t;\n}\n\n#pragma sokol @end\n\n#pragma sokol @program rt vs fs\n"
  },
  {
    "path": "examples/sokol/03_march_tracing_glsl/rt_glsl.v",
    "content": "// vtest build: misc-tooling // needs .h files that are produced by `v shader`\n/**********************************************************************\n*\n* Sokol 3d cube demo\n*\n* Copyright (c) 2021 Dario Deledda. All rights reserved.\n* Use of this source code is governed by an MIT license\n* that can be found in the LICENSE file.\n*\n* HOW TO COMPILE SHADERS:\n* Run `v shader .` in this directory to compile the shaders.\n* For more info and help with shader compilation see `docs.md` and `v help shader`.\n*\n* TODO:\n* - frame counter\n**********************************************************************/\nimport gg\nimport gg.m4\n// import math\nimport sokol.sapp\nimport sokol.gfx\nimport sokol.sgl\nimport time\n\n// GLSL Include and functions\n\n#include \"@VMODROOT/rt_glsl.h\" # It should be generated with `v shader .` (see the instructions at the top of this file)\n\nfn C.rt_shader_desc(gfx.Backend) &gfx.ShaderDesc\n\nconst win_width = 800\nconst win_height = 800\nconst bg_color = gg.white\n\nstruct App {\nmut:\n\tgg          &gg.Context = unsafe { nil }\n\ttexture     gfx.Image\n\tsampler     gfx.Sampler\n\tinit_flag   bool\n\tframe_count int\n\n\tmouse_x int = -1\n\tmouse_y int = -1\n\t// glsl\n\tcube_pip_glsl gfx.Pipeline\n\tcube_bind     gfx.Bindings\n\t// time\n\tticks i64\n}\n\n/******************************************************************************\n* Texture functions\n******************************************************************************/\nfn create_texture(w int, h int, buf &u8) (gfx.Image, gfx.Sampler) {\n\tsz := w * h * 4\n\tmut img_desc := gfx.ImageDesc{\n\t\twidth:       w\n\t\theight:      h\n\t\tnum_mipmaps: 0\n\t\t//\t\tmin_filter: .linear\n\t\t//\t\tmag_filter: .linear\n\t\t// usage: .dynamic\n\t\t//\t\twrap_u: .clamp_to_edge\n\t\t//\t\twrap_v: .clamp_to_edge\n\t\tlabel:         &char(unsafe { nil })\n\t\td3d11_texture: 0\n\t}\n\t// comment if .dynamic is enabled\n\timg_desc.data.subimage[0][0] = gfx.Range{\n\t\tptr:  buf\n\t\tsize: usize(sz)\n\t}\n\n\tsg_img := gfx.make_image(&img_desc)\n\n\tmut smp_desc := gfx.SamplerDesc{\n\t\tmin_filter: .linear\n\t\tmag_filter: .linear\n\t\twrap_u:     .clamp_to_edge\n\t\twrap_v:     .clamp_to_edge\n\t}\n\n\tsg_smp := gfx.make_sampler(&smp_desc)\n\treturn sg_img, sg_smp\n}\n\nfn destroy_texture(sg_img gfx.Image) {\n\tgfx.destroy_image(sg_img)\n}\n\n// Use only if usage: .dynamic is enabled\nfn update_text_texture(sg_img gfx.Image, w int, h int, buf &u8) {\n\tsz := w * h * 4\n\tmut tmp_sbc := gfx.ImageData{}\n\ttmp_sbc.subimage[0][0] = gfx.Range{\n\t\tptr:  buf\n\t\tsize: usize(sz)\n\t}\n\tgfx.update_image(sg_img, &tmp_sbc)\n}\n\n/******************************************************************************\n* Draw functions\n******************************************************************************\nCube vertex buffer with packed vertex formats for color and texture coords.\n\t\tNote that a vertex format which must be portable across all\n\t\tbackends must only use the normalized integer formats\n\t\t(BYTE4N, UBYTE4N, SHORT2N, SHORT4N), which can be converted\n\t\tto floating point formats in the vertex shader inputs.\n\t\tThe reason is that D3D11 cannot convert from non-normalized\n\t\tformats to floating point inputs (only to integer inputs),\n\t\tand WebGL2 / GLES2 don't support integer vertex shader inputs.\n*/\n\nstruct Vertex_t {\n\tx     f32\n\ty     f32\n\tz     f32\n\tcolor u32\n\tu     f32\n\tv     f32\n\t// u u16   // for compatibility with D3D11\n\t// v u16   // for compatibility with D3D11\n}\n\nfn init_cube_glsl(mut app App) {\n\t// cube vertex buffer\n\t// d := u16(32767)     // for compatibility with D3D11, 32767 stand for 1\n\td := f32(1.0)\n\tc := u32(0xFFFFFF_FF) // color RGBA8\n\t// vfmt off\n\tvertices := [\n\t\t// Face 0\n\t\tVertex_t{-1.0, -1.0, -1.0, c,  0, 0},\n\t\tVertex_t{ 1.0, -1.0, -1.0, c,  d, 0},\n\t\tVertex_t{ 1.0,  1.0, -1.0, c,  d, d},\n\t\tVertex_t{-1.0,  1.0, -1.0, c,  0, d},\n\t\t// Face 1\n\t\tVertex_t{-1.0, -1.0,  1.0, c,  0, 0},\n\t\tVertex_t{ 1.0, -1.0,  1.0, c,  d, 0},\n\t\tVertex_t{ 1.0,  1.0,  1.0, c,  d, d},\n\t\tVertex_t{-1.0,  1.0,  1.0, c,  0, d},\n\t\t// Face 2\n\t\tVertex_t{-1.0, -1.0, -1.0, c,  0, 0},\n\t\tVertex_t{-1.0,  1.0, -1.0, c,  d, 0},\n\t\tVertex_t{-1.0,  1.0,  1.0, c,  d, d},\n\t\tVertex_t{-1.0, -1.0,  1.0, c,  0, d},\n\t\t// Face 3\n\t\tVertex_t{ 1.0, -1.0, -1.0, c,  0, 0},\n\t\tVertex_t{ 1.0,  1.0, -1.0, c,  d, 0},\n\t\tVertex_t{ 1.0,  1.0,  1.0, c,  d, d},\n\t\tVertex_t{ 1.0, -1.0,  1.0, c,  0, d},\n\t\t// Face 4\n\t\tVertex_t{-1.0, -1.0, -1.0, c,  0, 0},\n\t\tVertex_t{-1.0, -1.0,  1.0, c,  d, 0},\n\t\tVertex_t{ 1.0, -1.0,  1.0, c,  d, d},\n\t\tVertex_t{ 1.0, -1.0, -1.0, c,  0, d},\n\t\t// Face 5\n\t\tVertex_t{-1.0,  1.0, -1.0, c,  0, 0},\n\t\tVertex_t{-1.0,  1.0,  1.0, c,  d, 0},\n\t\tVertex_t{ 1.0,  1.0,  1.0, c,  d, d},\n\t\tVertex_t{ 1.0,  1.0, -1.0, c,  0, d},\n\t]\n\t// vfmt on\n\n\tmut vert_buffer_desc := gfx.BufferDesc{\n\t\tlabel: c'cube-vertices'\n\t}\n\tunsafe { vmemset(&vert_buffer_desc, 0, int(sizeof(vert_buffer_desc))) }\n\n\tvert_buffer_desc.size = usize(vertices.len * int(sizeof(Vertex_t)))\n\tvert_buffer_desc.data = gfx.Range{\n\t\tptr:  vertices.data\n\t\tsize: usize(vertices.len * int(sizeof(Vertex_t)))\n\t}\n\n\tvert_buffer_desc.type = .vertexbuffer\n\tvbuf := gfx.make_buffer(&vert_buffer_desc)\n\n\t// create an index buffer for the cube\n\t// vfmt off\n\tindices := [\n\t\tu16(0),   1,   2,      0,    2,   3,\n\t\t    6,    5,   4,      7,    6,   4,\n\t\t    8,    9,  10,      8,   10,  11,\n\t\t   14,   13,  12,      15,  14,  12,\n\t\t   16,   17,  18,      16,  18,  19,\n\t\t   22,   21,  20,      23,  22,  20,\n\t]\n\t// vfmt on\n\n\tmut index_buffer_desc := gfx.BufferDesc{\n\t\tlabel: c'cube-indices'\n\t}\n\tunsafe { vmemset(&index_buffer_desc, 0, int(sizeof(index_buffer_desc))) }\n\n\tindex_buffer_desc.size = usize(indices.len * int(sizeof(u16)))\n\tindex_buffer_desc.data = gfx.Range{\n\t\tptr:  indices.data\n\t\tsize: usize(indices.len * int(sizeof(u16)))\n\t}\n\n\tindex_buffer_desc.type = .indexbuffer\n\tibuf := gfx.make_buffer(&index_buffer_desc)\n\n\t// create shader\n\tshader := gfx.make_shader(voidptr(C.rt_shader_desc(C.sg_query_backend())))\n\n\tmut pipdesc := gfx.PipelineDesc{}\n\tunsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }\n\tpipdesc.layout.buffers[0].stride = int(sizeof(Vertex_t))\n\n\t// the constants [C.ATTR_vs_pos, C.ATTR_vs_color0, C.ATTR_vs_texcoord0] are generated by sokol-shdc\n\tpipdesc.layout.attrs[C.ATTR_vs_pos].format = .float3 // x,y,z as f32\n\tpipdesc.layout.attrs[C.ATTR_vs_color0].format = .ubyte4n // color as u32\n\tpipdesc.layout.attrs[C.ATTR_vs_texcoord0].format = .float2 // u,v as f32\n\t// pipdesc.layout.attrs[C.ATTR_vs_texcoord0].format  = .short2n  // u,v as u16\n\n\tpipdesc.shader = shader\n\tpipdesc.index_type = .uint16\n\n\tpipdesc.depth = gfx.DepthState{\n\t\twrite_enabled: true\n\t\tcompare:       .less_equal\n\t}\n\tpipdesc.cull_mode = .back\n\n\tpipdesc.label = c'glsl_shader pipeline'\n\n\tapp.cube_bind.vertex_buffers[0] = vbuf\n\tapp.cube_bind.index_buffer = ibuf\n\tapp.cube_bind.fs.images[C.SLOT_tex] = app.texture\n\tapp.cube_bind.fs.samplers[C.SLOT_smp] = app.sampler\n\tapp.cube_pip_glsl = gfx.make_pipeline(&pipdesc)\n\tprintln('GLSL init DONE!')\n}\n\n@[inline]\nfn vec4(x f32, y f32, z f32, w f32) m4.Vec4 {\n\treturn m4.Vec4{\n\t\te: [x, y, z, w]!\n\t}\n}\n\nfn calc_tr_matrices(w f32, h f32, rx f32, ry f32, in_scale f32) m4.Mat4 {\n\tproj := m4.perspective(60, w / h, 0.01, 10.0)\n\tview := m4.look_at(vec4(f32(0.0), 0, 6, 0), vec4(f32(0), 0, 0, 0), vec4(f32(0), 1,\n\t\t0, 0))\n\tview_proj := view * proj\n\n\trxm := m4.rotate(m4.rad(rx), vec4(f32(1), 0, 0, 0))\n\trym := m4.rotate(m4.rad(ry), vec4(f32(0), 1, 0, 0))\n\n\tmodel := rym * rxm\n\tscale_m := m4.scale(vec4(in_scale, in_scale, in_scale, 1))\n\n\tres := (scale_m * model) * view_proj\n\treturn res\n}\n\nfn draw_cube_glsl(app App) {\n\tif app.init_flag == false {\n\t\treturn\n\t}\n\n\tws := gg.window_size_real_pixels()\n\tratio := f32(ws.width) / ws.height\n\tdw := f32(ws.width / 2)\n\tdh := f32(ws.height / 2)\n\n\t// use the following commented lines to rotate the 3d glsl cube\n\t// rot := [f32(app.mouse_y), f32(app.mouse_x)]\n\t// calc_tr_matrices(dw, dh, rot[0], rot[1] ,2.3)\n\ttr_matrix := calc_tr_matrices(dw, dh, 0, 0, 2.3)\n\tgfx.apply_viewport(0, 0, ws.width, ws.height, true)\n\n\t// apply the pipeline and bindings\n\tgfx.apply_pipeline(app.cube_pip_glsl)\n\tgfx.apply_bindings(app.cube_bind)\n\n\t// Uniforms\n\t// *** vertex shader uniforms ***\n\t// passing the view matrix as uniform\n\t// res is a 4x4 matrix of f32 thus: 4*16 byte of size\n\tvs_uniforms_range := gfx.Range{\n\t\tptr:  &tr_matrix\n\t\tsize: usize(4 * 16)\n\t}\n\tgfx.apply_uniforms(.vs, C.SLOT_vs_params, &vs_uniforms_range)\n\n\t// *** fragment shader uniforms ***\n\ttime_ticks := f32(time.ticks() - app.ticks) / 1000\n\tmut tmp_fs_params := [\n\t\tf32(ws.width),\n\t\tws.height * ratio, // x,y resolution to pass to FS\n\t\tapp.mouse_x, // mouse x\n\t\tws.height - app.mouse_y * 2, // mouse y scaled\n\t\ttime_ticks, // time as f32\n\t\tapp.frame_count, // frame count\n\t\t0,\n\t\t0, // padding bytes , see \"fs_params\" struct paddings in rt_glsl.h\n\t]!\n\tfs_uniforms_range := gfx.Range{\n\t\tptr:  unsafe { &tmp_fs_params }\n\t\tsize: usize(sizeof(tmp_fs_params))\n\t}\n\tgfx.apply_uniforms(.fs, C.SLOT_fs_params, &fs_uniforms_range)\n\n\t// 3 vertices for triangle * 2 triangles per face * 6 faces = 36 vertices to draw\n\tgfx.draw(0, (3 * 2) * 6, 1)\n\tgfx.end_pass()\n\tgfx.commit()\n}\n\nfn frame(mut app App) {\n\t// clear\n\tmut color_action := gfx.ColorAttachmentAction{\n\t\tload_action: .clear\n\t\tclear_value: gfx.Color{\n\t\t\tr: 0.0\n\t\t\tg: 0.0\n\t\t\tb: 0.0\n\t\t\ta: 1.0\n\t\t}\n\t}\n\n\tmut pass_action := gfx.PassAction{}\n\tpass_action.colors[0] = color_action\n\tpass := sapp.create_default_pass(pass_action)\n\tgfx.begin_pass(&pass)\n\n\t// glsl cube\n\tdraw_cube_glsl(app)\n\tapp.frame_count++\n}\n\n/******************************************************************************\n* Init / Cleanup\n******************************************************************************/\nfn my_init(mut app App) {\n\t// set max vertices,\n\t// for a large number of the same type of object it is better use the instances!!\n\tdesc := sapp.create_desc()\n\tgfx.setup(&desc)\n\tsgl_desc := sgl.Desc{\n\t\tmax_vertices: 50 * 65536\n\t}\n\tsgl.setup(&sgl_desc)\n\n\t// create chessboard texture 256*256 RGBA\n\tw := 256\n\th := 256\n\tsz := w * h * 4\n\ttmp_txt := unsafe { malloc(sz) }\n\tmut i := 0\n\tfor i < sz {\n\t\tunsafe {\n\t\t\ty := (i >> 0x8) >> 5 // 8 cell\n\t\t\tx := (i & 0xFF) >> 5 // 8 cell\n\t\t\t// upper left corner\n\t\t\tif x == 0 && y == 0 {\n\t\t\t\ttmp_txt[i + 0] = u8(0xFF)\n\t\t\t\ttmp_txt[i + 1] = u8(0)\n\t\t\t\ttmp_txt[i + 2] = u8(0)\n\t\t\t\ttmp_txt[i + 3] = u8(0xFF)\n\t\t\t}\n\t\t\t// low right corner\n\t\t\telse if x == 7 && y == 7 {\n\t\t\t\ttmp_txt[i + 0] = u8(0)\n\t\t\t\ttmp_txt[i + 1] = u8(0xFF)\n\t\t\t\ttmp_txt[i + 2] = u8(0)\n\t\t\t\ttmp_txt[i + 3] = u8(0xFF)\n\t\t\t} else {\n\t\t\t\tcol := if ((x + y) & 1) == 1 { 0xFF } else { 128 }\n\t\t\t\ttmp_txt[i + 0] = u8(col) // red\n\t\t\t\ttmp_txt[i + 1] = u8(col) // green\n\t\t\t\ttmp_txt[i + 2] = u8(col) // blue\n\t\t\t\ttmp_txt[i + 3] = u8(0xFF) // alpha\n\t\t\t}\n\t\t\ti += 4\n\t\t}\n\t}\n\tunsafe {\n\t\tapp.texture, app.sampler = create_texture(w, h, tmp_txt)\n\t\tfree(tmp_txt)\n\t}\n\t// glsl\n\tinit_cube_glsl(mut app)\n\tapp.init_flag = true\n}\n\n/******************************************************************************\n* events handling\n******************************************************************************/\nfn my_event_manager(mut ev gg.Event, mut app App) {\n\tif ev.typ == .mouse_move {\n\t\tapp.mouse_x = int(ev.mouse_x)\n\t\tapp.mouse_y = int(ev.mouse_y)\n\t}\n\tif ev.typ == .touches_began || ev.typ == .touches_moved {\n\t\tif ev.num_touches > 0 {\n\t\t\ttouch_point := ev.touches[0]\n\t\t\tapp.mouse_x = int(touch_point.pos_x)\n\t\t\tapp.mouse_y = int(touch_point.pos_y)\n\t\t}\n\t}\n}\n\nfn main() {\n\tmut app := &App{}\n\tapp.gg = gg.new_context(\n\t\twidth:         win_width\n\t\theight:        win_height\n\t\tcreate_window: true\n\t\twindow_title:  '3D Ray Marching Cube'\n\t\tuser_data:     app\n\t\tbg_color:      bg_color\n\t\tframe_fn:      frame\n\t\tinit_fn:       my_init\n\t\tevent_fn:      my_event_manager\n\t)\n\tapp.ticks = time.ticks()\n\tapp.gg.run()\n}\n"
  },
  {
    "path": "examples/sokol/03_march_tracing_glsl/v.mod",
    "content": ""
  },
  {
    "path": "examples/sokol/04_multi_shader_glsl/rt_glsl.v",
    "content": "// vtest build: misc-tooling // needs .h files that are produced by `v shader`\n/**********************************************************************\n* Sokol 3d cube multishader demo\n* Copyright (c) 2024 Dario Deledda. All rights reserved.\n* Use of this source code is governed by an MIT license\n* that can be found in the LICENSE file.\n*\n* HOW TO COMPILE SHADERS:\n* Run `v shader .` in this directory to compile the shaders.\n* For more info and help with shader compilation see `docs.md` and `v help shader`.\n**********************************************************************/\nimport gg\nimport gg.m4\nimport sokol.sapp\nimport sokol.gfx\nimport sokol.sgl\nimport time\n\n// GLSL Include and functions\n#include \"@VMODROOT/rt_glsl_march.h\" # It should be generated with `v shader .` (see the instructions at the top of this file)\n#include \"@VMODROOT/rt_glsl_puppy.h\" # It should be generated with `v shader .` (see the instructions at the top of this file)\n\nfn C.rt_march_shader_desc(gfx.Backend) &gfx.ShaderDesc\nfn C.rt_puppy_shader_desc(gfx.Backend) &gfx.ShaderDesc\n\nconst start_ticks = time.ticks()\n\n@[heap]\nstruct App {\nmut:\n\tgg         &gg.Context = unsafe { nil }\n\ttexture    gfx.Image\n\tsampler    gfx.Sampler\n\tinit_flag  bool\n\tmouse_x    int = 502\n\tmouse_y    int = 394\n\tmouse_down bool\n\t// glsl\n\tcube_pip_glsl gfx.Pipeline\n\tcube_bind     gfx.Bindings\n\tpipe          map[string]gfx.Pipeline\n\tbind          map[string]gfx.Bindings\n}\n\n/******************************************************************************\n* Texture functions\n******************************************************************************/\nfn create_texture(w int, h int, buf byteptr) (gfx.Image, gfx.Sampler) {\n\tsz := w * h * 4\n\tmut img_desc := gfx.ImageDesc{\n\t\twidth:  w\n\t\theight: h\n\t}\n\timg_desc.data.subimage[0][0] = gfx.Range{\n\t\tptr:  buf\n\t\tsize: usize(sz)\n\t}\n\tsg_img := gfx.make_image(&img_desc)\n\tmut smp_desc := gfx.SamplerDesc{\n\t\tmin_filter: .linear\n\t\tmag_filter: .linear\n\t\twrap_u:     .clamp_to_edge\n\t\twrap_v:     .clamp_to_edge\n\t}\n\tsg_smp := gfx.make_sampler(&smp_desc)\n\treturn sg_img, sg_smp\n}\n\n/******************************************************************************\n* Draw functions\n******************************************************************************\nCube vertex buffer with packed vertex formats for color and texture coords.\n\t\tNote that a vertex format which must be portable across all\n\t\tbackends must only use the normalized integer formats\n\t\t(BYTE4N, UBYTE4N, SHORT2N, SHORT4N), which can be converted\n\t\tto floating point formats in the vertex shader inputs.\n\t\tThe reason is that D3D11 cannot convert from non-normalized\n\t\tformats to floating point inputs (only to integer inputs),\n\t\tand WebGL2 / GLES2 does not support integer vertex shader inputs.\n*/\nstruct Vertex_t {\n\tx     f32\n\ty     f32\n\tz     f32\n\tcolor u32\n\tu     f32\n\tv     f32\n}\n\nconst vertices = cube_vertices()\n\nfn cube_vertices() []Vertex_t {\n\t// cube vertex buffer\n\td := f32(1.0)\n\tc := u32(0xFF_FF_FF_FF) // white color RGBA8\n\t// vfmt off\n\t// 6 faces, each defined by 4 vertices:\n\tcube := [\n\t\tVertex_t{-1.0, -1.0, -1.0, c, 0, 0}, Vertex_t{ 1.0, -1.0, -1.0, c, d, 0}, Vertex_t{ 1.0,  1.0, -1.0, c, d, d}, Vertex_t{-1.0,  1.0, -1.0, c, 0, d},\n\t\tVertex_t{-1.0, -1.0,  1.0, c, 0, 0}, Vertex_t{ 1.0, -1.0,  1.0, c, d, 0}, Vertex_t{ 1.0,  1.0,  1.0, c, d, d}, Vertex_t{-1.0,  1.0,  1.0, c, 0, d},\n\t\tVertex_t{-1.0, -1.0, -1.0, c, 0, 0}, Vertex_t{-1.0,  1.0, -1.0, c, d, 0}, Vertex_t{-1.0,  1.0,  1.0, c, d, d}, Vertex_t{-1.0, -1.0,  1.0, c, 0, d},\n\t\tVertex_t{ 1.0, -1.0, -1.0, c, 0, 0}, Vertex_t{ 1.0,  1.0, -1.0, c, d, 0}, Vertex_t{ 1.0,  1.0,  1.0, c, d, d}, Vertex_t{ 1.0, -1.0,  1.0, c, 0, d},\n\t\tVertex_t{-1.0, -1.0, -1.0, c, 0, 0}, Vertex_t{-1.0, -1.0,  1.0, c, d, 0}, Vertex_t{ 1.0, -1.0,  1.0, c, d, d}, Vertex_t{ 1.0, -1.0, -1.0, c, 0, d},\n\t\tVertex_t{-1.0,  1.0, -1.0, c, 0, 0}, Vertex_t{-1.0,  1.0,  1.0, c, d, 0}, Vertex_t{ 1.0,  1.0,  1.0, c, d, d}, Vertex_t{ 1.0,  1.0, -1.0, c, 0, d},\n\t]\n\t// vfmt off\n\treturn cube\n}\n\nfn (mut app App) init_glsl_shader(shader_name string, shader_desc &gfx.ShaderDesc, indices []u16) {\n\tmut vert_buffer_desc := gfx.BufferDesc{}\n\tunsafe { vmemset(&vert_buffer_desc, 0, sizeof(vert_buffer_desc)) }\n\tvert_buffer_desc.label = c'cube-vertices'\n\tvert_buffer_desc.size = usize(vertices.len) * sizeof(Vertex_t)\n\tvert_buffer_desc.data = gfx.Range{\n\t\tptr: vertices.data\n\t\tsize: vert_buffer_desc.size\n\t}\n\tvert_buffer_desc.type = .vertexbuffer\n\tvbuf := gfx.make_buffer(&vert_buffer_desc)\n\n\tmut index_buffer_desc := gfx.BufferDesc{}\n\tunsafe { vmemset(&index_buffer_desc, 0, sizeof(index_buffer_desc)) }\n\tindex_buffer_desc.label = c'cube-indices'\n\tindex_buffer_desc.size = usize(indices.len) * sizeof(u16)\n\tindex_buffer_desc.data = gfx.Range{\n\t\tptr: indices.data\n\t\tsize: index_buffer_desc.size\n\t}\n\tindex_buffer_desc.type = .indexbuffer\n\tibuf := gfx.make_buffer(&index_buffer_desc)\n\n\t// create shader\n\tshader := gfx.make_shader(shader_desc)\n\n\tmut pipdesc := gfx.PipelineDesc{}\n\tunsafe { vmemset(&pipdesc, 0, sizeof(pipdesc)) }\n\tpipdesc.label = c'glsl_shader pipeline'\n\tpipdesc.layout.buffers[0].stride = int(sizeof(Vertex_t))\n\n\t// the constants [C.ATTR_vs_m_pos, C.ATTR_vs_m_color0, C.ATTR_vs_m_texcoord0] are generated by sokol-shdc\n\tpipdesc.layout.attrs[C.ATTR_vs_m_pos].format = .float3 // x,y,z as f32\n\tpipdesc.layout.attrs[C.ATTR_vs_m_color0].format = .ubyte4n // color as u32\n\tpipdesc.layout.attrs[C.ATTR_vs_m_texcoord0].format = .float2 // u,v as f32\n\t// pipdesc.layout.attrs[C.ATTR_vs_m_texcoord0].format  = .short2n  // u,v as u16\n\tpipdesc.shader = shader\n\tpipdesc.index_type = .uint16\n\tpipdesc.depth = gfx.DepthState{\n\t\twrite_enabled: true\n\t\tcompare: .less_equal\n\t}\n\tpipdesc.cull_mode = .back\n\n\tmut bind := gfx.Bindings{}\n\tunsafe { vmemset(&bind, 0, sizeof(bind)) }\n\tbind.vertex_buffers[0] = vbuf\n\tbind.index_buffer = ibuf\n\tbind.fs.images[C.SLOT_tex] = app.texture\n\tbind.fs.samplers[C.SLOT_smp] = app.sampler\n\tapp.bind[shader_name] = bind\n\tapp.pipe[shader_name] = gfx.make_pipeline(&pipdesc)\n\tprintln('${@FN} for shader `${shader_name}` done.')\n}\n\nfn calc_tr_matrices(w f32, h f32, rx f32, ry f32, in_scale f32) m4.Mat4 {\n\tproj := m4.perspective(60, w / h, 0.01, 10.0)\n\tview := m4.look_at(m4.vec4(0.0, 0, 6, 0), m4.vec4(0, 0, 0, 0), m4.vec4(0, 1, 0, 0))\n\tview_proj := view * proj\n\n\trxm := m4.rotate(m4.rad(rx), m4.vec4(1, 0, 0, 0))\n\trym := m4.rotate(m4.rad(ry), m4.vec4(0, 1, 0, 0))\n\n\tmodel := rym * rxm\n\tscale_m := m4.scale(m4.vec4(in_scale, in_scale, in_scale, 1))\n\n\tres := (scale_m * model) * view_proj\n\treturn res\n}\n\nfn (app &App) draw_glsl_shader(shader_name string) {\n\tws := gg.window_size_real_pixels()\n\tratio := f32(ws.width) / ws.height\n\tdw := f32(ws.width / 2)\n\tdh := f32(ws.height / 2)\n\n\trot := [f32(app.mouse_y), f32(app.mouse_x)]\n\ttr_matrix := calc_tr_matrices(dw, dh, rot[0], rot[1], 2.3)\n\n\t// apply the pipeline and bindings\n\tgfx.apply_pipeline(app.pipe[shader_name])\n\tgfx.apply_bindings(app.bind[shader_name])\n\n\t// Uniforms\n\t// *** vertex shadeer uniforms ***\n\t// passing the view matrix as uniform\n\t// res is a 4x4 matrix of f32 thus: 4*16 byte of size\n\tvs_uniforms_range := gfx.Range{\n\t\tptr: &tr_matrix\n\t\tsize: usize(4 * 16)\n\t}\n\tgfx.apply_uniforms(.vs, C.SLOT_vs_params_m, &vs_uniforms_range)\n\n\t// *** fragment shader uniforms ***\n\ttime_ticks := f32(time.ticks() - start_ticks) / 1000\n\tmut tmp_fs_params := [\n\t\tf32(ws.width),\n\t\tws.height * ratio, // x,y resolution to pass to FS\n\t\t0,\n\t\t0, // dont send mouse position\n\t\t// app.mouse_x,               // mouse x\n\t\t// ws.height - app.mouse_y*2, // mouse y scaled\n\t\ttime_ticks, // time as f32\n\t\tf32(app.gg.frame), // frame count\n\t\t0,\n\t\t0, // padding bytes , see \"fs_params\" struct paddings in rt_glsl.h\n\t]!\n\tfs_uniforms_range := gfx.Range{\n\t\tptr: unsafe { &tmp_fs_params }\n\t\tsize: usize(sizeof(tmp_fs_params))\n\t}\n\tgfx.apply_uniforms(.fs, C.SLOT_fs_params_p, &fs_uniforms_range)\n\n\t// 3 vertices for triangle * 2 triangles per face * 6 faces = 36 vertices to draw\n\tgfx.draw(0, (3 * 2) * 3, 1)\n}\n\nfn (mut app App) frame() {\n\tmut pass_action := gfx.PassAction{}\n\tpass_action.colors[0] = gfx.ColorAttachmentAction{\n\t\tload_action: .clear\n\t\tclear_value: gfx.Color{b: 0.9}\n\t}\n\tgfx.begin_pass(sapp.create_default_pass(pass_action))\n\tif !app.init_flag {\n\t\treturn\n\t}\n\tws := gg.window_size_real_pixels()\n\tgfx.apply_viewport(0, 0, ws.width, ws.height, true)\n    app.draw_glsl_shader('march')\n    app.draw_glsl_shader('puppy')\n\tgfx.end_pass()\n\tgfx.commit()\n}\n\nfn (mut app App) on_init() {\n\t// set max vertices, but note, that for a large number of the same type of object it is better use the instances!!\n    gfx.setup(sapp.create_desc())\n    sgl.setup(sgl.Desc{max_vertices: 50 * 65536})\n\n\t// create chessboard texture 256*256 RGBA\n\tw := 256\n\th := 256\n\tsz := w * h * 4\n\ttmp_txt := unsafe { malloc(sz) }\n\tdefer {\n\t\tunsafe { free(tmp_txt) }\n\t}\n\tmut i := 0\n\tfor i < sz {\n\t\tunsafe {\n\t\t\ty := (i >> 0x8) >> 5 // 8 cell\n\t\t\tx := (i & 0xFF) >> 5 // 8 cell\n\t\t\t// upper left corner\n\t\t\tif x == 0 && y == 0 {\n\t\t\t\ttmp_txt[i + 0] = 0xFF\n\t\t\t\ttmp_txt[i + 1] = 0\n\t\t\t\ttmp_txt[i + 2] = 0\n\t\t\t\ttmp_txt[i + 3] = 0xFF\n\t\t\t}\n\t\t\t// low right corner\n\t\t\telse if x == 7 && y == 7 {\n\t\t\t\ttmp_txt[i + 0] = 0\n\t\t\t\ttmp_txt[i + 1] = 0xFF\n\t\t\t\ttmp_txt[i + 2] = 0\n\t\t\t\ttmp_txt[i + 3] = 0xFF\n\t\t\t} else {\n\t\t\t\tcol := if ((x + y) & 1) == 1 { u8(0xFF) } else { 128 }\n\t\t\t\ttmp_txt[i + 0] = col // red\n\t\t\t\ttmp_txt[i + 1] = col // green\n\t\t\t\ttmp_txt[i + 2] = col // blue\n\t\t\t\ttmp_txt[i + 3] = 0xFF // alpha\n\t\t\t}\n\t\t\ti += 4\n\t\t}\n\t}\n\tapp.texture, app.sampler = create_texture(w, h, tmp_txt)\n\n    // vfmt off\n    app.init_glsl_shader('march', voidptr(C.rt_march_shader_desc(C.sg_query_backend())), [\n        u16(0), 1,  2,    0,   2,  3,\n            6,  5,  4,    7,   6,  4,\n            8,  9, 10,    8,  10, 11,\n    ])\n    app.init_glsl_shader('puppy', voidptr(C.rt_puppy_shader_desc(C.sg_query_backend())), [\n        u16(14), 13, 12,  15, 14, 12,\n            16,  17, 18,  16, 18, 19,\n            22,  21, 20,  23, 22, 20,\n    ])\n\t// vfmt on\n\tapp.init_flag = true\n}\n\n/******************************************************************************\n* events handling\n******************************************************************************/\nfn (mut app App) on_event(ev &gg.Event, x voidptr) {\n\tif ev.typ == .mouse_down {\n\t\tapp.mouse_down = true\n\t}\n\tif ev.typ == .mouse_up {\n\t\tapp.mouse_down = false\n\t}\n\tif app.mouse_down == true && ev.typ == .mouse_move {\n\t\tapp.mouse_x = int(ev.mouse_x)\n\t\tapp.mouse_y = int(ev.mouse_y)\n\t}\n\tif ev.typ == .touches_began || ev.typ == .touches_moved {\n\t\tif ev.num_touches > 0 {\n\t\t\ttouch_point := ev.touches[0]\n\t\t\tapp.mouse_x = int(touch_point.pos_x)\n\t\t\tapp.mouse_y = int(touch_point.pos_y)\n\t\t}\n\t}\n\t// eprintln('> app.mouse_x: ${app.mouse_x} | app.mouse_y: ${app.mouse_y}')\n}\n\nfn main() {\n\tmut app := &App{}\n\tapp.gg = gg.new_context(\n\t\twidth:        800\n\t\theight:       800\n\t\twindow_title: '3D Dual shader Cube - click and rotate with the mouse'\n\t\tuser_data:    app\n\t\tframe_fn:     app.frame\n\t\tinit_fn:      app.on_init\n\t\tevent_fn:     app.on_event\n\t)\n\tapp.gg.run()\n}\n"
  },
  {
    "path": "examples/sokol/04_multi_shader_glsl/rt_glsl_march.glsl",
    "content": "//------------------------------------------------------------------------------\n//  Shader code for texcube-sapp sample.\n//\n//  NOTE: This source file also uses the '#pragma sokol' form of the\n//  custom tags.\n//------------------------------------------------------------------------------\n//#pragma sokol @ctype mat4 hmm_mat4\n\n#pragma sokol @vs vs_m\nuniform vs_params_m {\n    mat4 mvp;\n};\n\nin vec4 pos;\nin vec4 color0;\nin vec2 texcoord0;\n\nout vec4 color;\nout vec2 uv;\n\nvoid main() {\n    gl_Position = mvp * pos;\n    color = color0;\n    uv = texcoord0;\n}\n#pragma sokol @end\n\n#pragma sokol @fs fs_m\nuniform texture2D tex;\nuniform sampler smp;\n\nuniform fs_params_m {\n\tvec2 iResolution;\n\tvec2 iMouse;\n\tfloat iTime;\n\tfloat iFrame;\n};\n\nin vec4 color;\nin vec2 uv;\nout vec4 frag_color;\n\n// change to 0 to 4 to increment the AntiAliasing,\n// increase AA will SLOW the rendering!!\n#define AA 1\n\n//*********************************************************\n// Ray Marching\n// original code from: https://www.shadertoy.com/view/Xds3zN\n//*********************************************************\n// The MIT License\n// Copyright © 2013 Inigo Quilez\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// A list of useful distance function to simple primitives. All\n// these functions (except for ellipsoid) return an exact\n// euclidean distance, meaning they produce a better SDF than\n// what you'd get if you were constructing them from boolean\n// operations.\n//\n// More info here:\n//\n// https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm\n\n//------------------------------------------------------------------\nfloat dot2( in vec2 v ) { return dot(v,v); }\nfloat dot2( in vec3 v ) { return dot(v,v); }\nfloat ndot( in vec2 a, in vec2 b ) { return a.x*b.x - a.y*b.y; }\n\nfloat sdPlane( vec3 p )\n{\n\treturn p.y;\n}\n\nfloat sdSphere( vec3 p, float s )\n{\n\treturn length(p)-s;\n}\n\nfloat sdBox( vec3 p, vec3 b )\n{\n\tvec3 d = abs(p) - b;\n\treturn min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));\n}\n\nfloat sdBoundingBox( vec3 p, vec3 b, float e )\n{\n\tp = abs(p  )-b;\n\tvec3 q = abs(p+e)-e;\n\n\treturn min(min(\n\t\tlength(max(vec3(p.x,q.y,q.z),0.0))+min(max(p.x,max(q.y,q.z)),0.0),\n\t\tlength(max(vec3(q.x,p.y,q.z),0.0))+min(max(q.x,max(p.y,q.z)),0.0)),\n\t\tlength(max(vec3(q.x,q.y,p.z),0.0))+min(max(q.x,max(q.y,p.z)),0.0));\n}\nfloat sdEllipsoid( in vec3 p, in vec3 r ) // approximated\n{\n\tfloat k0 = length(p/r);\n\tfloat k1 = length(p/(r*r));\n\treturn k0*(k0-1.0)/k1;\n}\n\nfloat sdTorus( vec3 p, vec2 t )\n{\n\treturn length( vec2(length(p.xz)-t.x,p.y) )-t.y;\n}\n\nfloat sdCappedTorus(in vec3 p, in vec2 sc, in float ra, in float rb)\n{\n\tp.x = abs(p.x);\n\tfloat k = (sc.y*p.x>sc.x*p.y) ? dot(p.xy,sc) : length(p.xy);\n\treturn sqrt( dot(p,p) + ra*ra - 2.0*ra*k ) - rb;\n}\n\nfloat sdHexPrism( vec3 p, vec2 h )\n{\n\tvec3 q = abs(p);\n\n\tconst vec3 k = vec3(-0.8660254, 0.5, 0.57735);\n\tp = abs(p);\n\tp.xy -= 2.0*min(dot(k.xy, p.xy), 0.0)*k.xy;\n\tvec2 d = vec2(\n\t\tlength(p.xy - vec2(clamp(p.x, -k.z*h.x, k.z*h.x), h.x))*sign(p.y - h.x),\n\t\tp.z-h.y );\n\treturn min(max(d.x,d.y),0.0) + length(max(d,0.0));\n}\n\nfloat sdOctogonPrism( in vec3 p, in float r, float h )\n{\n\tconst vec3 k = vec3(-0.9238795325,   // sqrt(2+sqrt(2))/2\n\t\t\t\t\t\t\t\t\t\t\t 0.3826834323,   // sqrt(2-sqrt(2))/2\n\t\t\t\t\t\t\t\t\t\t\t 0.4142135623 ); // sqrt(2)-1\n\t// reflections\n\tp = abs(p);\n\tp.xy -= 2.0*min(dot(vec2( k.x,k.y),p.xy),0.0)*vec2( k.x,k.y);\n\tp.xy -= 2.0*min(dot(vec2(-k.x,k.y),p.xy),0.0)*vec2(-k.x,k.y);\n\t// polygon side\n\tp.xy -= vec2(clamp(p.x, -k.z*r, k.z*r), r);\n\tvec2 d = vec2( length(p.xy)*sign(p.y), p.z-h );\n\treturn min(max(d.x,d.y),0.0) + length(max(d,0.0));\n}\n\nfloat sdCapsule( vec3 p, vec3 a, vec3 b, float r )\n{\n\tvec3 pa = p-a, ba = b-a;\n\tfloat h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n\treturn length( pa - ba*h ) - r;\n}\n\nfloat sdRoundCone( in vec3 p, in float r1, float r2, float h )\n{\n\tvec2 q = vec2( length(p.xz), p.y );\n\n\tfloat b = (r1-r2)/h;\n\tfloat a = sqrt(1.0-b*b);\n\tfloat k = dot(q,vec2(-b,a));\n\n\tif( k < 0.0 ) return length(q) - r1;\n\tif( k > a*h ) return length(q-vec2(0.0,h)) - r2;\n\n\treturn dot(q, vec2(a,b) ) - r1;\n}\n\nfloat sdRoundCone(vec3 p, vec3 a, vec3 b, float r1, float r2)\n{\n\t// sampling independent computations (only depend on shape)\n\tvec3  ba = b - a;\n\tfloat l2 = dot(ba,ba);\n\tfloat rr = r1 - r2;\n\tfloat a2 = l2 - rr*rr;\n\tfloat il2 = 1.0/l2;\n\n\t// sampling dependent computations\n\tvec3 pa = p - a;\n\tfloat y = dot(pa,ba);\n\tfloat z = y - l2;\n\tfloat x2 = dot2( pa*l2 - ba*y );\n\tfloat y2 = y*y*l2;\n\tfloat z2 = z*z*l2;\n\n\t// single square root!\n\tfloat k = sign(rr)*rr*rr*x2;\n\tif( sign(z)*a2*z2 > k ) return  sqrt(x2 + z2)        *il2 - r2;\n\tif( sign(y)*a2*y2 < k ) return  sqrt(x2 + y2)        *il2 - r1;\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn (sqrt(x2*a2*il2)+y*rr)*il2 - r1;\n}\n\nfloat sdTriPrism( vec3 p, vec2 h )\n{\n\tconst float k = sqrt(3.0);\n\th.x *= 0.5*k;\n\tp.xy /= h.x;\n\tp.x = abs(p.x) - 1.0;\n\tp.y = p.y + 1.0/k;\n\tif( p.x+k*p.y>0.0 ) p.xy=vec2(p.x-k*p.y,-k*p.x-p.y)/2.0;\n\tp.x -= clamp( p.x, -2.0, 0.0 );\n\tfloat d1 = length(p.xy)*sign(-p.y)*h.x;\n\tfloat d2 = abs(p.z)-h.y;\n\treturn length(max(vec2(d1,d2),0.0)) + min(max(d1,d2), 0.);\n}\n\n// vertical\nfloat sdCylinder( vec3 p, vec2 h )\n{\n\tvec2 d = abs(vec2(length(p.xz),p.y)) - h;\n\treturn min(max(d.x,d.y),0.0) + length(max(d,0.0));\n}\n\n// arbitrary orientation\nfloat sdCylinder(vec3 p, vec3 a, vec3 b, float r)\n{\n\tvec3 pa = p - a;\n\tvec3 ba = b - a;\n\tfloat baba = dot(ba,ba);\n\tfloat paba = dot(pa,ba);\n\n\tfloat x = length(pa*baba-ba*paba) - r*baba;\n\tfloat y = abs(paba-baba*0.5)-baba*0.5;\n\tfloat x2 = x*x;\n\tfloat y2 = y*y*baba;\n\tfloat d = (max(x,y)<0.0)?-min(x2,y2):(((x>0.0)?x2:0.0)+((y>0.0)?y2:0.0));\n\treturn sign(d)*sqrt(abs(d))/baba;\n}\n\n// vertical\nfloat sdCone( in vec3 p, in vec2 c, float h )\n{\n\tvec2 q = h*vec2(c.x,-c.y)/c.y;\n\tvec2 w = vec2( length(p.xz), p.y );\n\n\tvec2 a = w - q*clamp( dot(w,q)/dot(q,q), 0.0, 1.0 );\n\tvec2 b = w - q*vec2( clamp( w.x/q.x, 0.0, 1.0 ), 1.0 );\n\tfloat k = sign( q.y );\n\tfloat d = min(dot( a, a ),dot(b, b));\n\tfloat s = max( k*(w.x*q.y-w.y*q.x),k*(w.y-q.y)  );\n\treturn sqrt(d)*sign(s);\n}\n\nfloat sdCappedCone( in vec3 p, in float h, in float r1, in float r2 )\n{\n\tvec2 q = vec2( length(p.xz), p.y );\n\n\tvec2 k1 = vec2(r2,h);\n\tvec2 k2 = vec2(r2-r1,2.0*h);\n\tvec2 ca = vec2(q.x-min(q.x,(q.y < 0.0)?r1:r2), abs(q.y)-h);\n\tvec2 cb = q - k1 + k2*clamp( dot(k1-q,k2)/dot2(k2), 0.0, 1.0 );\n\tfloat s = (cb.x < 0.0 && ca.y < 0.0) ? -1.0 : 1.0;\n\treturn s*sqrt( min(dot2(ca),dot2(cb)) );\n}\n\nfloat sdCappedCone(vec3 p, vec3 a, vec3 b, float ra, float rb)\n{\n\tfloat rba  = rb-ra;\n\tfloat baba = dot(b-a,b-a);\n\tfloat papa = dot(p-a,p-a);\n\tfloat paba = dot(p-a,b-a)/baba;\n\n\tfloat x = sqrt( papa - paba*paba*baba );\n\n\tfloat cax = max(0.0,x-((paba<0.5)?ra:rb));\n\tfloat cay = abs(paba-0.5)-0.5;\n\n\tfloat k = rba*rba + baba;\n\tfloat f = clamp( (rba*(x-ra)+paba*baba)/k, 0.0, 1.0 );\n\n\tfloat cbx = x-ra - f*rba;\n\tfloat cby = paba - f;\n\n\tfloat s = (cbx < 0.0 && cay < 0.0) ? -1.0 : 1.0;\n\n\treturn s*sqrt( min(cax*cax + cay*cay*baba,\n\t\t\t\t\t\t\t\tcbx*cbx + cby*cby*baba) );\n}\n\n// c is the sin/cos of the desired cone angle\nfloat sdSolidAngle(vec3 pos, vec2 c, float ra)\n{\n\tvec2 p = vec2( length(pos.xz), pos.y );\n\tfloat l = length(p) - ra;\n\tfloat m = length(p - c*clamp(dot(p,c),0.0,ra) );\n\treturn max(l,m*sign(c.y*p.x-c.x*p.y));\n}\n\nfloat sdOctahedron(vec3 p, float s)\n{\n\tp = abs(p);\n\tfloat m = p.x + p.y + p.z - s;\n\n// exact distance\n#if 0\n\tvec3 o = min(3.0*p - m, 0.0);\n\to = max(6.0*p - m*2.0 - o*3.0 + (o.x+o.y+o.z), 0.0);\n\treturn length(p - s*o/(o.x+o.y+o.z));\n#endif\n\n// exact distance\n#if 1\n\tvec3 q;\n\t\t\t if( 3.0*p.x < m ) q = p.xyz;\n\telse if( 3.0*p.y < m ) q = p.yzx;\n\telse if( 3.0*p.z < m ) q = p.zxy;\n\telse return m*0.57735027;\n\tfloat k = clamp(0.5*(q.z-q.y+s),0.0,s);\n\treturn length(vec3(q.x,q.y-s+k,q.z-k));\n#endif\n\n// bound, not exact\n#if 0\n\treturn m*0.57735027;\n#endif\n}\n\nfloat sdPyramid( in vec3 p, in float h )\n{\n\tfloat m2 = h*h + 0.25;\n\n\t// symmetry\n\tp.xz = abs(p.xz);\n\tp.xz = (p.z>p.x) ? p.zx : p.xz;\n\tp.xz -= 0.5;\n\n\t// project into face plane (2D)\n\tvec3 q = vec3( p.z, h*p.y - 0.5*p.x, h*p.x + 0.5*p.y);\n\n\tfloat s = max(-q.x,0.0);\n\tfloat t = clamp( (q.y-0.5*p.z)/(m2+0.25), 0.0, 1.0 );\n\n\tfloat a = m2*(q.x+s)*(q.x+s) + q.y*q.y;\n\tfloat b = m2*(q.x+0.5*t)*(q.x+0.5*t) + (q.y-m2*t)*(q.y-m2*t);\n\n\tfloat d2 = min(q.y,-q.x*m2-q.y*0.5) > 0.0 ? 0.0 : min(a,b);\n\n\t// recover 3D and scale, and add sign\n\treturn sqrt( (d2+q.z*q.z)/m2 ) * sign(max(q.z,-p.y));\n}\n\n// la,lb=semi axis, h=height, ra=corner\nfloat sdRhombus(vec3 p, float la, float lb, float h, float ra)\n{\n\tp = abs(p);\n\tvec2 b = vec2(la,lb);\n\tfloat f = clamp( (ndot(b,b-2.0*p.xz))/dot(b,b), -1.0, 1.0 );\n\tvec2 q = vec2(length(p.xz-0.5*b*vec2(1.0-f,1.0+f))*sign(p.x*b.y+p.z*b.x-b.x*b.y)-ra, p.y-h);\n\treturn min(max(q.x,q.y),0.0) + length(max(q,0.0));\n}\n\n//------------------------------------------------------------------\n\nvec2 opU( vec2 d1, vec2 d2 )\n{\n\treturn (d1.x<d2.x) ? d1 : d2;\n}\n\n//------------------------------------------------------------------\n\n#define ZERO (min(int(iFrame),0))\n\n//------------------------------------------------------------------\n\nvec2 map( in vec3 pos )\n{\n\tvec2 res = vec2( 1e10, 0.0 );\n\n\t{\n\t\tres = opU( res, vec2( sdSphere(    pos-vec3(-2.0,0.25, 0.0), 0.25 ), 26.9 ) );\n\t}\n\n\t// bounding box\n\tif( sdBox( pos-vec3(0.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )\n\t{\n\t\t// more primitives\n\t\tres = opU( res, vec2( sdBoundingBox( pos-vec3( 0.0,0.25, 0.0), vec3(0.3,0.25,0.2), 0.025 ), 16.9 ) );\n\t\tres = opU( res, vec2( sdTorus(      (pos-vec3( 0.0,0.30, 1.0)).xzy, vec2(0.25,0.05) ), 25.0 ) );\n\t\tres = opU( res, vec2( sdCone(        pos-vec3( 0.0,0.45,-1.0), vec2(0.6,0.8),0.45 ), 55.0 ) );\n\t\tres = opU( res, vec2( sdCappedCone(  pos-vec3( 0.0,0.25,-2.0), 0.25, 0.25, 0.1 ), 13.67 ) );\n\t\tres = opU( res, vec2( sdSolidAngle(  pos-vec3( 0.0,0.00,-3.0), vec2(3,4)/5.0, 0.4 ), 49.13 ) );\n\t}\n\n\t// bounding box\n\tif( sdBox( pos-vec3(1.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )\n\t{\n\t\t// more primitives\n\t\tres = opU( res, vec2( sdCappedTorus((pos-vec3( 1.0,0.30, 1.0))*vec3(1,-1,1), vec2(0.866025,-0.5), 0.25, 0.05), 8.5) );\n\t\tres = opU( res, vec2( sdBox(         pos-vec3( 1.0,0.25, 0.0), vec3(0.3,0.25,0.1) ), 3.0 ) );\n\t\tres = opU( res, vec2( sdCapsule(     pos-vec3( 1.0,0.00,-1.0),vec3(-0.1,0.1,-0.1), vec3(0.2,0.4,0.2), 0.1  ), 31.9 ) );\n\t\tres = opU( res, vec2( sdCylinder(    pos-vec3( 1.0,0.25,-2.0), vec2(0.15,0.25) ), 8.0 ) );\n\t\tres = opU( res, vec2( sdHexPrism(    pos-vec3( 1.0,0.2,-3.0), vec2(0.2,0.05) ), 18.4 ) );\n\t}\n\n\t// bounding box\n\tif( sdBox( pos-vec3(-1.0,0.35,-1.0),vec3(0.35,0.35,2.5))<res.x )\n\t{\n\t\t// more primitives\n\t\tres = opU( res, vec2( sdPyramid(    pos-vec3(-1.0,-0.6,-3.0), 1.0 ), 13.56 ) );\n\t\tres = opU( res, vec2( sdOctahedron( pos-vec3(-1.0,0.15,-2.0), 0.35 ), 23.56 ) );\n\t\tres = opU( res, vec2( sdTriPrism(   pos-vec3(-1.0,0.15,-1.0), vec2(0.3,0.05) ),43.5 ) );\n\t\tres = opU( res, vec2( sdEllipsoid(  pos-vec3(-1.0,0.25, 0.0), vec3(0.2, 0.25, 0.05) ), 43.17 ) );\n\t\tres = opU( res, vec2( sdRhombus(   (pos-vec3(-1.0,0.34, 1.0)).xzy, 0.15, 0.25, 0.04, 0.08 ),17.0 ) );\n\t}\n\n\t// bounding box\n\tif( sdBox( pos-vec3(2.0,0.3,-1.0),vec3(0.35,0.3,2.5) )<res.x )\n\t{\n\t\t// more primitives\n\t\tres = opU( res, vec2( sdOctogonPrism(pos-vec3( 2.0,0.2,-3.0), 0.2, 0.05), 51.8 ) );\n\t\tres = opU( res, vec2( sdCylinder(    pos-vec3( 2.0,0.15,-2.0), vec3(0.1,-0.1,0.0), vec3(-0.2,0.35,0.1), 0.08), 31.2 ) );\n\t\tres = opU( res, vec2( sdCappedCone(  pos-vec3( 2.0,0.10,-1.0), vec3(0.1,0.0,0.0), vec3(-0.2,0.40,0.1), 0.15, 0.05), 46.1 ) );\n\t\tres = opU( res, vec2( sdRoundCone(   pos-vec3( 2.0,0.15, 0.0), vec3(0.1,0.0,0.0), vec3(-0.1,0.35,0.1), 0.15, 0.05), 51.7 ) );\n\t\tres = opU( res, vec2( sdRoundCone(   pos-vec3( 2.0,0.20, 1.0), 0.2, 0.1, 0.3 ), 37.0 ) );\n\t}\n\n\treturn res;\n}\n\n// http://iquilezles.org/www/articles/boxfunctions/boxfunctions.htm\nvec2 iBox( in vec3 ro, in vec3 rd, in vec3 rad )\n{\n\tvec3 m = 1.0/rd;\n\tvec3 n = m*ro;\n\tvec3 k = abs(m)*rad;\n\tvec3 t1 = -n - k;\n\tvec3 t2 = -n + k;\n\treturn vec2( max( max( t1.x, t1.y ), t1.z ),\n\t\t\t\t\t\t\tmin( min( t2.x, t2.y ), t2.z ) );\n}\n\nvec2 raycast( in vec3 ro, in vec3 rd )\n{\n\tvec2 res = vec2(-1.0,-1.0);\n\n\tfloat tmin = 1.0;\n\tfloat tmax = 20.0;\n\n\t// raytrace floor plane\n\tfloat tp1 = (0.0-ro.y)/rd.y;\n\tif( tp1>0.0 )\n\t{\n\t\ttmax = min( tmax, tp1 );\n\t\tres = vec2( tp1, 1.0 );\n\t}\n\t//else return res;\n\n\t// raymarch primitives\n\tvec2 tb = iBox( ro-vec3(0.0,0.4,-0.5), rd, vec3(2.5,0.41,3.0) );\n\tif( tb.x<tb.y && tb.y>0.0 && tb.x<tmax)\n\t{\n\t\t//return vec2(tb.x,2.0);\n\t\ttmin = max(tb.x,tmin);\n\t\ttmax = min(tb.y,tmax);\n\n\t\tfloat t = tmin;\n\t\tfor( int i=0; i<70 && t<tmax; i++ )\n\t\t{\n\t\t\tvec2 h = map( ro+rd*t );\n\t\t\tif( abs(h.x)<(0.0001*t) )\n\t\t\t{\n\t\t\t\tres = vec2(t,h.y);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tt += h.x;\n\t\t}\n\t}\n\n\treturn res;\n}\n\n// http://iquilezles.org/www/articles/rmshadows/rmshadows.htm\nfloat calcSoftshadow( in vec3 ro, in vec3 rd, in float mint, in float tmax )\n{\n\t// bounding volume\n\tfloat tp = (0.8-ro.y)/rd.y; if( tp>0.0 ) tmax = min( tmax, tp );\n\n\tfloat res = 1.0;\n\tfloat t = mint;\n\tfor( int i=ZERO; i<24; i++ )\n\t{\n\tfloat h = map( ro + rd*t ).x;\n\t\tfloat s = clamp(8.0*h/t,0.0,1.0);\n\t\tres = min( res, s*s*(3.0-2.0*s) );\n\t\tt += clamp( h, 0.02, 0.2 );\n\t\tif( res<0.004 || t>tmax ) break;\n\t}\n\treturn clamp( res, 0.0, 1.0 );\n}\n\n// http://iquilezles.org/www/articles/normalsSDF/normalsSDF.htm\nvec3 calcNormal( in vec3 pos )\n{\n#if 0\n\tvec2 e = vec2(1.0,-1.0)*0.5773*0.0005;\n\treturn normalize( e.xyy*map( pos + e.xyy ).x +\n\t\te.yyx*map( pos + e.yyx ).x +\n\t\te.yxy*map( pos + e.yxy ).x +\n\t\te.xxx*map( pos + e.xxx ).x );\n#else\n\t// inspired by tdhooper and klems - a way to prevent the compiler from inlining map() 4 times\n\tvec3 n = vec3(0.0);\n\tfor( int i=ZERO; i<4; i++ )\n\t{\n\t\tvec3 e = 0.5773*(2.0*vec3((((i+3)>>1)&1),((i>>1)&1),(i&1))-1.0);\n\t\tn += e*map(pos+0.0005*e).x;\n\t\t//if( n.x+n.y+n.z>100.0 ) break;\n\t}\n\treturn normalize(n);\n#endif\n}\n\nfloat calcAO( in vec3 pos, in vec3 nor )\n{\n\tfloat occ = 0.0;\n\tfloat sca = 1.0;\n\tfor( int i=ZERO; i<5; i++ )\n\t{\n\t\tfloat h = 0.01 + 0.12*float(i)/4.0;\n\t\tfloat d = map( pos + h*nor ).x;\n\t\tocc += (h-d)*sca;\n\t\tsca *= 0.95;\n\t\tif( occ>0.35 ) break;\n\t}\n\treturn clamp( 1.0 - 3.0*occ, 0.0, 1.0 ) * (0.5+0.5*nor.y);\n}\n\n// http://iquilezles.org/www/articles/checkerfiltering/checkerfiltering.htm\nfloat checkersGradBox( in vec2 p, in vec2 dpdx, in vec2 dpdy )\n{\n\t// filter kernel\n\tvec2 w = abs(dpdx)+abs(dpdy) + 0.001;\n\t// analytical integral (box filter)\n\tvec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w;\n\t// xor pattern\n\treturn 0.5 - 0.5*i.x*i.y;\n}\n\nvec3 render( in vec3 ro, in vec3 rd, in vec3 rdx, in vec3 rdy )\n{\n\t// background\n\tvec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3;\n\n\t// raycast scene\n\tvec2 res = raycast(ro,rd);\n\tfloat t = res.x;\n\tfloat m = res.y;\n\tif( m>-0.5 )\n\t{\n\t\tvec3 pos = ro + t*rd;\n\t\tvec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal( pos );\n\t\tvec3 ref = reflect( rd, nor );\n\n\t\t// material\n\t\tcol = 0.2 + 0.2*sin( m*2.0 + vec3(0.0,1.0,2.0) );\n\t\tfloat ks = 1.0;\n\n\t\tif( m<1.5 )\n\t\t{\n\t\t\t// project pixel footprint into the plane\n\t\t\tvec3 dpdx = ro.y*(rd/rd.y-rdx/rdx.y);\n\t\t\tvec3 dpdy = ro.y*(rd/rd.y-rdy/rdy.y);\n\n\t\t\tfloat f = checkersGradBox( 3.0*pos.xz, 3.0*dpdx.xz, 3.0*dpdy.xz );\n\t\t\tcol = 0.15 + f*vec3(0.05);\n\t\t\tks = 0.4;\n\t\t}\n\n\t\t// lighting\n\t\tfloat occ = calcAO( pos, nor );\n\n\t\tvec3 lin = vec3(0.0);\n\n\t\t// sun\n\t\t{\n\t\t\tvec3  lig = normalize( vec3(-0.5, 0.4, -0.6) );\n\t\t\tvec3  hal = normalize( lig-rd );\n\t\t\tfloat dif = clamp( dot( nor, lig ), 0.0, 1.0 );\n\t\t\t//if( dif>0.0001 )\n\t\t\t\tdif *= calcSoftshadow( pos, lig, 0.02, 2.5 );\n\t\t\tfloat spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0);\n\t\t\t\t\t\tspe *= dif;\n\t\t\t\t\t\tspe *= 0.04+0.96*pow(clamp(1.0-dot(hal,lig),0.0,1.0),5.0);\n\t\t\tlin += col*2.20*dif*vec3(1.30,1.00,0.70);\n\t\t\tlin +=     5.00*spe*vec3(1.30,1.00,0.70)*ks;\n\t\t}\n\t\t// sky\n\t\t{\n\t\t\tfloat dif = sqrt(clamp( 0.5+0.5*nor.y, 0.0, 1.0 ));\n\t\t\t\t\t\tdif *= occ;\n\t\t\tfloat spe = smoothstep( -0.2, 0.2, ref.y );\n\t\t\t\t\t\tspe *= dif;\n\t\t\t\t\t\tspe *= 0.04+0.96*pow(clamp(1.0+dot(nor,rd),0.0,1.0), 5.0 );\n\t\t\t//if( spe>0.001 )\n\t\t\t\t\t\tspe *= calcSoftshadow( pos, ref, 0.02, 2.5 );\n\t\t\tlin += col*0.60*dif*vec3(0.40,0.60,1.15);\n\t\t\tlin +=     2.00*spe*vec3(0.40,0.60,1.30)*ks;\n\t\t}\n\t\t// back\n\t\t{\n\t\t\tfloat dif = clamp( dot( nor, normalize(vec3(0.5,0.0,0.6))), 0.0, 1.0 )*clamp( 1.0-pos.y,0.0,1.0);\n\t\t\t\t\t\t\tdif *= occ;\n\t\t\tlin += col*0.55*dif*vec3(0.25,0.25,0.25);\n\t\t}\n\t\t// sss\n\t\t{\n\t\t\tfloat dif = pow(clamp(1.0+dot(nor,rd),0.0,1.0),2.0);\n\t\t\t\t\t\tdif *= occ;\n\t\t\tlin += col*0.25*dif*vec3(1.00,1.00,1.00);\n\t\t}\n\n\t\tcol = lin;\n\n\t\tcol = mix( col, vec3(0.7,0.7,0.9), 1.0-exp( -0.0001*t*t*t ) );\n\t}\n\n\treturn vec3( clamp(col,0.0,1.0) );\n}\n\nmat3 setCamera( in vec3 ro, in vec3 ta, float cr )\n{\n\tvec3 cw = normalize(ta-ro);\n\tvec3 cp = vec3(sin(cr), cos(cr),0.0);\n\tvec3 cu = normalize( cross(cw,cp) );\n\tvec3 cv =          ( cross(cu,cw) );\n\treturn mat3( cu, cv, cw );\n}\n\nvec4 mainImage( vec2 fragCoord )\n{\n\tvec2 mo = iMouse.xy/iResolution.xy;\n\tfloat time = 32.0 + iTime*1.5;\n\n\t// camera\n\tvec3 ta = vec3( 0.5, -0.5, -0.6 );\n\tvec3 ro = ta + vec3( 4.5*cos(0.1*time + 7.0*mo.x), 1.3 + 2.0*mo.y, 4.5*sin(0.1*time + 7.0*mo.x) );\n\t// camera-to-world transformation\n\tmat3 ca = setCamera( ro, ta, 0.0 );\n\n\tvec3 tot = vec3(0.0);\n#if AA>1\n\tfor( int m=ZERO; m<AA; m++ )\n\tfor( int n=ZERO; n<AA; n++ )\n\t{\n\t\t// pixel coordinates\n\t\tvec2 o = vec2(float(m),float(n)) / float(AA) - 0.5;\n\t\tvec2 p = (2.0*(fragCoord+o)-iResolution.xy)/iResolution.y;\n#else\n\t\tvec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y;\n#endif\n\n\t\t// focal length\n\t\tconst float fl = 2.5;\n\n\t\t// ray direction\n\t\tvec3 rd = ca * normalize( vec3(p,fl) );\n\n\t\t // ray differentials\n\t\tvec2 px = (2.0*(fragCoord+vec2(1.0,0.0))-iResolution.xy)/iResolution.y;\n\t\tvec2 py = (2.0*(fragCoord+vec2(0.0,1.0))-iResolution.xy)/iResolution.y;\n\t\tvec3 rdx = ca * normalize( vec3(px,fl) );\n\t\tvec3 rdy = ca * normalize( vec3(py,fl) );\n\n\t\t// render\n\t\tvec3 col = render( ro, rd, rdx, rdy );\n\n\t\t// gain\n\t\t// col = col*3.0/(2.5+col);\n\n\t\t// gamma\n\t\tcol = pow( col, vec3(0.4545) );\n\n\t\ttot += col;\n#if AA>1\n\t}\n\ttot /= float(AA*AA);\n#endif\n\n\t//fragColor = vec4( tot, 1.0 );\n\treturn vec4( tot, 1.0 );\n}\n\n//*********************************************************\n// END Ray Marching\n//*********************************************************\n\nvoid main() {\n\tvec4 c = color;\n\tvec4 txt = texture(sampler2D(tex, smp), uv);\n\tc = txt * c;\n\tvec2 uv1 = uv * iResolution;\n\tvec4 col_ray = mainImage(uv1);\n\n\t// use this to mix the chessboart texture with the ray marching\n\t//frag_color = clamp(c*iMouse.y/512.0,0.0,1.0) *\tcol_ray\t;\n\n\tfrag_color = c*0.00001 +\tcol_ray\t;\n}\n\n#pragma sokol @end\n\n#pragma sokol @program rt_march vs_m fs_m\n"
  },
  {
    "path": "examples/sokol/04_multi_shader_glsl/rt_glsl_puppy.glsl",
    "content": "//------------------------------------------------------------------------------\n//  Shader code for texcube-sapp sample.\n//\n//  NOTE: This source file also uses the '#pragma sokol' form of the\n//  custom tags.\n//------------------------------------------------------------------------------\n//#pragma sokol @ctype mat4 hmm_mat4\n\n#pragma sokol @vs vs_p\nuniform vs_params_p {\n    mat4 mvp;\n};\n\nin vec4 pos;\nin vec4 color0;\nin vec2 texcoord0;\n\nout vec4 color;\nout vec2 uv;\n\nvoid main() {\n    gl_Position = mvp * pos;\n    color = color0;\n    uv = texcoord0;\n}\n#pragma sokol @end\n\n#pragma sokol @fs fs_p\nuniform texture2D tex;\nuniform sampler smp;\n\nuniform fs_params_p {\n\tvec2 iResolution;\n\tvec2 iMouse;\n\tfloat iTime;\n\tfloat iFrame;\n};\n\nin vec4 color;\nin vec2 uv;\nout vec4 frag_color;\n\n// change to 0 to 4 to increment the AntiAliasing,\n// increase AA will SLOW the rendering!!\n#define AA 1\n\n//*********************************************************\n// Ray Marching\n// original code from: https://www.shadertoy.com/view/Xds3zN\n//*********************************************************\n// Created by inigo quilez - iq/2019\n// I share this piece (art and code) here in Shadertoy and through its Public API, only for educational purposes.\n// You cannot use, share or host this piece or modifications of it as part of your own commercial or non-commercial product, website or project.\n// You can share a link to it or an unmodified screenshot of it provided you attribute \"by Inigo Quilez, @iquilezles and iquilezles.org\".\n// If you are a teacher, lecturer, educator or similar and these conditions are too restrictive for your needs, please contact me and we'll work it out.\n\n\n// An animation test - a happy and blobby creature\n// jumping and looking around. It gets off-model very\n// often, but it looks good enough I think.\n//\n// Making-of with math/shader/art explanations (6 hours\n// long): https://www.youtube.com/watch?v=Cfe5UQ-1L9Q\n//\n// Video capture: https://www.youtube.com/watch?v=s_UOFo2IULQ\n//\n// Buy a metal print here: https://www.redbubble.com/i/metal-print/Happy-Jumping-by-InigoQuilez/43594745.0JXQP\n\n//------------------------------------------------------------------\n\n\n// http://iquilezles.org/www/articles/smin/smin.htm\nfloat smin( float a, float b, float k )\n{\n    float h = max(k-abs(a-b),0.0);\n    return min(a, b) - h*h*0.25/k;\n}\n\n// http://iquilezles.org/www/articles/smin/smin.htm\nvec2 smin( vec2 a, vec2 b, float k )\n{\n    float h = clamp( 0.5+0.5*(b.x-a.x)/k, 0.0, 1.0 );\n    return mix( b, a, h ) - k*h*(1.0-h);\n}\n\n// http://iquilezles.org/www/articles/smin/smin.htm\nfloat smax( float a, float b, float k )\n{\n    float h = max(k-abs(a-b),0.0);\n    return max(a, b) + h*h*0.25/k;\n}\n\n// http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm\nfloat sdSphere( vec3 p, float s )\n{\n    return length(p)-s;\n}\n\n// http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm\nfloat sdEllipsoid( in vec3 p, in vec3 r ) // approximated\n{\n    float k0 = length(p/r);\n    float k1 = length(p/(r*r));\n    return k0*(k0-1.0)/k1;\n}\n\nvec2 sdStick(vec3 p, vec3 a, vec3 b, float r1, float r2) // approximated\n{\n    vec3 pa = p-a, ba = b-a;\n\tfloat h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n\treturn vec2( length( pa - ba*h ) - mix(r1,r2,h*h*(3.0-2.0*h)), h );\n}\n\n// http://iquilezles.org/www/articles/smin/smin.htm\nvec4 opU( vec4 d1, vec4 d2 )\n{\n\treturn (d1.x<d2.x) ? d1 : d2;\n}\n\n//------------------------------------------------------------------\n\n#define ZERO (min(int(iFrame),0))\n\n//------------------------------------------------------------------\n\nfloat href;\nfloat hsha;\n\nvec4 map( in vec3 pos, float atime )\n{\n    hsha = 1.0;\n\n    float t1 = fract(atime);\n    float t4 = abs(fract(atime*0.5)-0.5)/0.5;\n\n    float p = 4.0*t1*(1.0-t1);\n    float pp = 4.0*(1.0-2.0*t1); // derivative of p\n\n    vec3 cen = vec3( 0.5*(-1.0 + 2.0*t4),\n                     pow(p,2.0-p) + 0.1,\n                     floor(atime) + pow(t1,0.7) -1.0 );\n\n    // body\n    vec2 uu = normalize(vec2( 1.0, -pp ));\n    vec2 vv = vec2(-uu.y, uu.x);\n\n    float sy = 0.5 + 0.5*p;\n    float compress = 1.0-smoothstep(0.0,0.4,p);\n    sy = sy*(1.0-compress) + compress;\n    float sz = 1.0/sy;\n\n    vec3 q = pos - cen;\n    float rot = -0.25*(-1.0 + 2.0*t4);\n    float rc = cos(rot);\n    float rs = sin(rot);\n    q.xy = mat2x2(rc,rs,-rs,rc)*q.xy;\n    vec3 r = q;\n\thref = q.y;\n    q.yz = vec2( dot(uu,q.yz), dot(vv,q.yz) );\n\n    vec4 res = vec4( sdEllipsoid( q, vec3(0.25, 0.25*sy, 0.25*sz) ), 2.0, 0.0, 1.0 );\n\n    if( res.x-1.0 < pos.y ) // bounding volume\n\t{\n    float t2 = fract(atime+0.8);\n    float p2 = 0.5-0.5*cos(6.2831*t2);\n    r.z += 0.05-0.2*p2;\n    r.y += 0.2*sy-0.2;\n    vec3 sq = vec3( abs(r.x), r.yz );\n\n\t// head\n    vec3 h = r;\n    float hr = sin(0.791*atime);\n    hr = 0.7*sign(hr)*smoothstep(0.5,0.7,abs(hr));\n    h.xz = mat2x2(cos(hr),sin(hr),-sin(hr),cos(hr))*h.xz;\n    vec3 hq = vec3( abs(h.x), h.yz );\n\tfloat d  = sdEllipsoid( h-vec3(0.0,0.20,0.02), vec3(0.08,0.2,0.15) );\n\tfloat d2 = sdEllipsoid( h-vec3(0.0,0.21,-0.1), vec3(0.20,0.2,0.20) );\n\td = smin( d, d2, 0.1 );\n    res.x = smin( res.x, d, 0.1 );\n\n    // belly wrinkles\n    {\n    float yy = r.y-0.02-2.5*r.x*r.x;\n    res.x += 0.001*sin(yy*120.0)*(1.0-smoothstep(0.0,0.1,abs(yy)));\n    }\n\n    // arms\n    {\n    vec2 arms = sdStick( sq, vec3(0.18-0.06*hr*sign(r.x),0.2,-0.05), vec3(0.3+0.1*p2,-0.2+0.3*p2,-0.15), 0.03, 0.06 );\n    res.xz = smin( res.xz, arms, 0.01+0.04*(1.0-arms.y)*(1.0-arms.y)*(1.0-arms.y) );\n    }\n\n    // ears\n    {\n    float t3 = fract(atime+0.9);\n    float p3 = 4.0*t3*(1.0-t3);\n    vec2 ear = sdStick( hq, vec3(0.15,0.32,-0.05), vec3(0.2+0.05*p3,0.2+0.2*p3,-0.07), 0.01, 0.04 );\n    res.xz = smin( res.xz, ear, 0.01 );\n    }\n\n    // mouth\n    {\n\td = sdEllipsoid( h-vec3(0.0,0.15+4.0*hq.x*hq.x,0.15), vec3(0.1,0.04,0.2) );\n    res.w = 0.3+0.7*clamp( d*150.0,0.0,1.0);\n    res.x = smax( res.x, -d, 0.03 );\n    }\n\n\t// legs\n    {\n    float t6 = cos(6.2831*(atime*0.5+0.25));\n    float ccc = cos(1.57*t6*sign(r.x));\n    float sss = sin(1.57*t6*sign(r.x));\n\tvec3 base = vec3(0.12,-0.07,-0.1); base.y -= 0.1/sy;\n    vec2 legs = sdStick( sq, base, base + vec3(0.2,-ccc,sss)*0.2, 0.04, 0.07 );\n    res.xz = smin( res.xz, legs, 0.07 );\n    }\n\n    // eye\n    {\n    float blink = pow(0.5+0.5*sin(2.1*iTime),20.0);\n    float eyeball = sdSphere(hq-vec3(0.08,0.27,0.06),0.065+0.02*blink);\n    res.x = smin( res.x, eyeball, 0.03 );\n\n    vec3 cq = hq-vec3(0.1,0.34,0.08);\n    cq.xy = mat2x2(0.8,0.6,-0.6,0.8)*cq.xy;\n    d = sdEllipsoid( cq, vec3(0.06,0.03,0.03) );\n    res.x = smin( res.x, d, 0.03 );\n\n    float eo = 1.0-0.5*smoothstep(0.01,0.04,length((hq.xy-vec2(0.095,0.285))*vec2(1.0,1.1)));\n    res = opU( res, vec4(sdSphere(hq-vec3(0.08,0.28,0.08),0.060),3.0,0.0,eo));\n    res = opU( res, vec4(sdSphere(hq-vec3(0.075,0.28,0.102),0.0395),4.0,0.0,1.0));\n    }\n\t}\n\n    // ground\n    float fh = -0.1 - 0.05*(sin(pos.x*2.0)+sin(pos.z*2.0));\n    float t5f = fract(atime+0.05);\n    float t5i = floor(atime+0.05);\n    float bt4 = abs(fract(t5i*0.5)-0.5)/0.5;\n    vec2  bcen = vec2( 0.5*(-1.0+2.0*bt4),t5i+pow(t5f,0.7)-1.0 );\n\n    float k = length(pos.xz-bcen);\n    float tt = t5f*15.0-6.2831 - k*3.0;\n    fh -= 0.1*exp(-k*k)*sin(tt)*exp(-max(tt,0.0)/2.0)*smoothstep(0.0,0.01,t5f);\n    float d = pos.y - fh;\n\n    // bubbles\n    {\n    vec3 vp = vec3( mod(abs(pos.x),3.0)-1.5,pos.y,mod(pos.z+1.5,3.0)-1.5);\n    vec2 id = vec2( floor(pos.x/3.0), floor((pos.z+1.5)/3.0) );\n    float fid = id.x*11.1 + id.y*31.7;\n    float fy = fract(fid*1.312+atime*0.1);\n    float y = -1.0+4.0*fy;\n    vec3  rad = vec3(0.7,1.0+0.5*sin(fid),0.7);\n    rad -= 0.1*(sin(pos.x*3.0)+sin(pos.y*4.0)+sin(pos.z*5.0));\n    float siz = 4.0*fy*(1.0-fy);\n    float d2 = sdEllipsoid( vp-vec3(0.5,y,0.0), siz*rad );\n\n    d2 -= 0.03*smoothstep(-1.0,1.0,sin(18.0*pos.x)+sin(18.0*pos.y)+sin(18.0*pos.z));\n    d2 *= 0.6;\n    d2 = min(d2,2.0);\n    d = smin( d, d2, 0.32 );\n    if( d<res.x ) { res = vec4(d,1.0,0.0,1.0); hsha=sqrt(siz); }\n    }\n\n    // candy\n    {\n    float fs = 5.0;\n    vec3 qos = fs*vec3(pos.x, pos.y-fh, pos.z );\n    vec2 id = vec2( floor(qos.x+0.5), floor(qos.z+0.5) );\n    vec3 vp = vec3( fract(qos.x+0.5)-0.5,qos.y,fract(qos.z+0.5)-0.5);\n    vp.xz += 0.1*cos( id.x*130.143 + id.y*120.372 + vec2(0.0,2.0) );\n    float den = sin(id.x*0.1+sin(id.y*0.091))+sin(id.y*0.1);\n    float fid = id.x*0.143 + id.y*0.372;\n    float ra = smoothstep(0.0,0.1,den*0.1+fract(fid)-0.95);\n    d = sdSphere( vp, 0.35*ra )/fs;\n    if( d<res.x ) res = vec4(d,5.0,qos.y,1.0);\n    }\n\n    return res;\n}\n\nvec4 raycast( in vec3 ro, in vec3 rd, float time )\n{\n    vec4 res = vec4(-1.0,-1.0,0.0,1.0);\n\n    float tmin = 0.5;\n    float tmax = 20.0;\n\n\t#if 1\n    // raytrace bounding plane\n    float tp = (3.5-ro.y)/rd.y;\n    if( tp>0.0 ) tmax = min( tmax, tp );\n\t#endif\n\n    // raymarch scene\n    float t = tmin;\n    for( int i=0; i<256 && t<tmax; i++ )\n    {\n        vec4 h = map( ro+rd*t, time );\n        if( abs(h.x)<(0.0005*t) )\n        {\n            res = vec4(t,h.yzw);\n            break;\n        }\n        t += h.x;\n    }\n\n    return res;\n}\n\n// http://iquilezles.org/www/articles/rmshadows/rmshadows.htm\nfloat calcSoftshadow( in vec3 ro, in vec3 rd, float time )\n{\n    float res = 1.0;\n\n    float tmax = 12.0;\n    #if 1\n    float tp = (3.5-ro.y)/rd.y; // raytrace bounding plane\n    if( tp>0.0 ) tmax = min( tmax, tp );\n\t#endif\n\n    float t = 0.02;\n    for( int i=0; i<50; i++ )\n    {\n\t\tfloat h = map( ro + rd*t, time ).x;\n        res = min( res, mix(1.0,16.0*h/t, hsha) );\n        t += clamp( h, 0.05, 0.40 );\n        if( res<0.005 || t>tmax ) break;\n    }\n    return clamp( res, 0.0, 1.0 );\n}\n\n// http://iquilezles.org/www/articles/normalsSDF/normalsSDF.htm\nvec3 calcNormal( in vec3 pos, float time )\n{\n\n#if 0\n    vec2 e = vec2(1.0,-1.0)*0.5773*0.001;\n    return normalize( e.xyy*map( pos + e.xyy, time ).x +\n\t\t\t\t\t  e.yyx*map( pos + e.yyx, time ).x +\n\t\t\t\t\t  e.yxy*map( pos + e.yxy, time ).x +\n\t\t\t\t\t  e.xxx*map( pos + e.xxx, time ).x );\n#else\n    // inspired by tdhooper and klems - a way to prevent the compiler from inlining map() 4 times\n    vec3 n = vec3(0.0);\n    for( int i=ZERO; i<4; i++ )\n    {\n        vec3 e = 0.5773*(2.0*vec3((((i+3)>>1)&1),((i>>1)&1),(i&1))-1.0);\n        n += e*map(pos+0.001*e,time).x;\n    }\n    return normalize(n);\n#endif\n}\n\nfloat calcOcclusion( in vec3 pos, in vec3 nor, float time )\n{\n\tfloat occ = 0.0;\n    float sca = 1.0;\n    for( int i=ZERO; i<5; i++ )\n    {\n        float h = 0.01 + 0.11*float(i)/4.0;\n        vec3 opos = pos + h*nor;\n        float d = map( opos, time ).x;\n        occ += (h-d)*sca;\n        sca *= 0.95;\n    }\n    return clamp( 1.0 - 2.0*occ, 0.0, 1.0 );\n}\n\nvec3 render( in vec3 ro, in vec3 rd, float time )\n{\n    // sky dome\n    vec3 col = vec3(0.5, 0.8, 0.9) - max(rd.y,0.0)*0.5;\n    // sky clouds\n    vec2 uv = 1.5*rd.xz/rd.y;\n    float cl  = 1.0*(sin(uv.x)+sin(uv.y)); uv *= mat2(0.8,0.6,-0.6,0.8)*2.1;\n          cl += 0.5*(sin(uv.x)+sin(uv.y));\n    col += 0.1*(-1.0+2.0*smoothstep(-0.1,0.1,cl-0.4));\n    // sky horizon\n\tcol = mix( col, vec3(0.5, 0.7, .9), exp(-10.0*max(rd.y,0.0)) );\n\n\n    // scene geometry\n    vec4 res = raycast(ro,rd, time);\n    if( res.y>-0.5 )\n    {\n        float t = res.x;\n        vec3 pos = ro + t*rd;\n        vec3 nor = calcNormal( pos, time );\n        vec3 ref = reflect( rd, nor );\n        float focc = res.w;\n\n        // material\n\t\tcol = vec3(0.2);\n        float ks = 1.0;\n\n        if( res.y>4.5 )  // candy\n        {\n             col = vec3(0.14,0.048,0.0);\n             vec2 id = floor(5.0*pos.xz+0.5);\n\t\t     col += 0.036*cos((id.x*11.1+id.y*37.341) + vec3(0.0,1.0,2.0) );\n             col = max(col,0.0);\n             focc = clamp(4.0*res.z,0.0,1.0);\n        }\n        else if( res.y>3.5 ) // eyeball\n        {\n            col = vec3(0.0);\n        }\n        else if( res.y>2.5 ) // iris\n        {\n            col = vec3(0.4);\n        }\n        else if( res.y>1.5 ) // body\n        {\n            col = mix(vec3(0.144,0.09,0.0036),vec3(0.36,0.1,0.04),res.z*res.z);\n            col = mix(col,vec3(0.14,0.09,0.06)*2.0, (1.0-res.z)*smoothstep(-0.15, 0.15, -href));\n        }\n\t\telse // terrain\n        {\n            // base green\n            col = vec3(0.05,0.09,0.02);\n            float f = 0.2*(-1.0+2.0*smoothstep(-0.2,0.2,sin(18.0*pos.x)+sin(18.0*pos.y)+sin(18.0*pos.z)));\n            col += f*vec3(0.06,0.06,0.02);\n            ks = 0.5 + pos.y*0.15;\n\n\t\t\t// footprints\n            vec2 mp = vec2(pos.x-0.5*(mod(floor(pos.z+0.5),2.0)*2.0-1.0), fract(pos.z+0.5)-0.5 );\n            float mark = 1.0-smoothstep(0.1, 0.5, length(mp));\n            mark *= smoothstep(0.0, 0.1, floor(time) - floor(pos.z+0.5) );\n            col *= mix( vec3(1.0), vec3(0.5,0.5,0.4), mark );\n            ks *= 1.0-0.5*mark;\n        }\n\n        // lighting (sun, sky, bounce, back, sss)\n        float occ = calcOcclusion( pos, nor, time )*focc;\n        float fre = clamp(1.0+dot(nor,rd),0.0,1.0);\n\n        vec3  sun_lig = normalize( vec3(0.6, 0.35, 0.5) );\n        float sun_dif = clamp(dot( nor, sun_lig ), 0.0, 1.0 );\n        vec3  sun_hal = normalize( sun_lig-rd );\n        float sun_sha = calcSoftshadow( pos, sun_lig, time );\n\t\tfloat sun_spe = ks*pow(clamp(dot(nor,sun_hal),0.0,1.0),8.0)*sun_dif*(0.04+0.96*pow(clamp(1.0+dot(sun_hal,rd),0.0,1.0),5.0));\n\t\tfloat sky_dif = sqrt(clamp( 0.5+0.5*nor.y, 0.0, 1.0 ));\n        float sky_spe = ks*smoothstep( 0.0, 0.5, ref.y )*(0.04+0.96*pow(fre,4.0));\n        float bou_dif = sqrt(clamp( 0.1-0.9*nor.y, 0.0, 1.0 ))*clamp(1.0-0.1*pos.y,0.0,1.0);\n        float bac_dif = clamp(0.1+0.9*dot( nor, normalize(vec3(-sun_lig.x,0.0,-sun_lig.z))), 0.0, 1.0 );\n        float sss_dif = fre*sky_dif*(0.25+0.75*sun_dif*sun_sha);\n\n\t\tvec3 lin = vec3(0.0);\n        lin += sun_dif*vec3(8.10,6.00,4.20)*vec3(sun_sha,sun_sha*sun_sha*0.5+0.5*sun_sha,sun_sha*sun_sha);\n        lin += sky_dif*vec3(0.50,0.70,1.00)*occ;\n        lin += bou_dif*vec3(0.20,0.70,0.10)*occ;\n        lin += bac_dif*vec3(0.45,0.35,0.25)*occ;\n        lin += sss_dif*vec3(3.25,2.75,2.50)*occ;\n\t\tcol = col*lin;\n\t\tcol += sun_spe*vec3(9.90,8.10,6.30)*sun_sha;\n        col += sky_spe*vec3(0.20,0.30,0.65)*occ*occ;\n\n        col = pow(col,vec3(0.8,0.9,1.0) );\n\n        // fog\n        col = mix( col, vec3(0.5,0.7,0.9), 1.0-exp( -0.0001*t*t*t ) );\n    }\n\n    return col;\n}\n\nmat3 setCamera( in vec3 ro, in vec3 ta, float cr )\n{\n\tvec3 cw = normalize(ta-ro);\n\tvec3 cp = vec3(sin(cr), cos(cr),0.0);\n\tvec3 cu = normalize( cross(cw,cp) );\n\tvec3 cv =          ( cross(cu,cw) );\n    return mat3( cu, cv, cw );\n}\n\n//void mainImage( out vec4 fragColor, in vec2 fragCoord )\nvec4 mainImage( vec2 fragCoord )\n{\n    vec3 tot = vec3(0.0);\n#if AA>1\n    for( int m=ZERO; m<AA; m++ )\n    for( int n=ZERO; n<AA; n++ )\n    {\n        // pixel coordinates\n        vec2 o = vec2(float(m),float(n)) / float(AA) - 0.5;\n        vec2 p = (-iResolution.xy + 2.0*(fragCoord+o))/iResolution.y;\n        // time coordinate (motion blurred, shutter=0.5)\n        float d = 0.5+0.5*sin(fragCoord.x*147.0)*sin(fragCoord.y*131.0);\n        float time = iTime - 0.5*(1.0/24.0)*(float(m*AA+n)+d)/float(AA*AA);\n#else\n        vec2 p = (-iResolution.xy + 2.0*fragCoord)/iResolution.y;\n        float time = iTime;\n#endif\n        time += -2.6;\n        time *= 0.9;\n\n        // camera\n        float cl = sin(0.5*time);\n        float an = 1.57 + 0.7*sin(0.15*time);\n        vec3  ta = vec3( 0.0, 0.65, -0.6+time*1.0 - 0.4*cl);\n        vec3  ro = ta + vec3( 1.3*cos(an), -0.250, 1.3*sin(an) );\n        float ti = fract(time-0.15);\n        ti = 4.0*ti*(1.0-ti);\n        ta.y += 0.15*ti*ti*(3.0-2.0*ti)*smoothstep(0.4,0.9,cl);\n\n        // camera bounce\n        float t4 = abs(fract(time*0.5)-0.5)/0.5;\n        float bou = -1.0 + 2.0*t4;\n        ro += 0.06*sin(time*12.0+vec3(0.0,2.0,4.0))*smoothstep( 0.85, 1.0, abs(bou) );\n\n        // camera-to-world rotation\n        mat3 ca = setCamera( ro, ta, 0.0 );\n\n        // ray direction\n        vec3 rd = ca * normalize( vec3(p,1.8) );\n\n        // render\n        vec3 col = render( ro, rd, time );\n\n        // color grading\n        col = col*vec3(1.11,0.89,0.79);\n\n        // compress\n        col = 1.35*col/(1.0+col);\n\n        // gamma\n        col = pow( col, vec3(0.4545) );\n\n        tot += col;\n#if AA>1\n    }\n    tot /= float(AA*AA);\n#endif\n\n    // s-surve\n    tot = clamp(tot,0.0,1.0);\n    tot = tot*tot*(3.0-2.0*tot);\n\n    // vignetting\n    vec2 q = fragCoord/iResolution.xy;\n    tot *= 0.5 + 0.5*pow(16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.25);\n\n    // output\n    //fragColor = vec4( tot, 1.0 );\n\t\treturn vec4( tot, 1.0 );\n}\n\n//*********************************************************\n// END Ray Marching\n//*********************************************************\n\nvoid main() {\n\tvec4 c = color;\n\tvec4 txt = texture(sampler2D(tex, smp), uv);\n\tc = txt * c;\n\tvec2 uv1 = uv * iResolution;\n\tvec4 col_ray = mainImage(uv1);\n\n\t// use this to mix the chessboart texture with the ray marching\n\t//frag_color = clamp(c*iMouse.y/512.0,0.0,1.0) *\tcol_ray\t;\n\n\tfrag_color = c*0.00001 +\tcol_ray\t;\n}\n\n#pragma sokol @end\n\n#pragma sokol @program rt_puppy vs_p fs_p\n"
  },
  {
    "path": "examples/sokol/04_multi_shader_glsl/v.mod",
    "content": ""
  },
  {
    "path": "examples/sokol/05_instancing_glsl/rt_glsl.v",
    "content": "// vtest build: misc-tooling // needs .h files that are produced by `v shader`\n/**********************************************************************\n*\n* Sokol 3d cube multishader demo\n*\n* Copyright (c) 2021 Dario Deledda. All rights reserved.\n* Use of this source code is governed by an MIT license\n* that can be found in the LICENSE file.\n*\n* HOW TO COMPILE SHADERS:\n* Run `v shader .` in this directory to compile the shaders.\n* For more info and help with shader compilation see `docs.md` and `v help shader`.\n*\n* TODO:\n* - frame counter\n**********************************************************************/\nimport gg\nimport gg.m4\nimport math\nimport sokol.gfx\n// import sokol.sgl\nimport time\n\nconst win_width = 800\nconst win_height = 800\nconst bg_color = gg.white\nconst num_inst = 16384\n\nstruct App {\nmut:\n\tgg          &gg.Context = unsafe { nil }\n\ttexture     gfx.Image\n\tsampler     gfx.Sampler\n\tinit_flag   bool\n\tframe_count int\n\n\tmouse_x    int = 903\n\tmouse_y    int = 638\n\tmouse_down bool\n\t// glsl\n\tcube_pip_glsl gfx.Pipeline\n\tcube_bind     gfx.Bindings\n\n\tpipe map[string]gfx.Pipeline\n\tbind map[string]gfx.Bindings\n\t// time\n\tticks i64\n\t// instances\n\tinst_pos [num_inst]m4.Vec4\n\t// camera\n\tcamera_x f32 = -8\n\tcamera_z f32 = 47\n}\n\n/******************************************************************************\n* GLSL Include and functions\n******************************************************************************/\n#include \"@VMODROOT/rt_glsl_instancing.h\" # It should be generated with `v shader .` (see the instructions at the top of this file)\n\nfn C.instancing_shader_desc(gfx.Backend) &gfx.ShaderDesc\n\n/******************************************************************************\n* Texture functions\n******************************************************************************/\nfn create_texture(w int, h int, buf byteptr) (gfx.Image, gfx.Sampler) {\n\tsz := w * h * 4\n\t// vfmt off\n\tmut img_desc := gfx.ImageDesc{\n\t\twidth:         w\n\t\theight:        h\n\t\tnum_mipmaps:   0\n//\t\tmin_filter:    .linear\n//\t\tmag_filter:    .linear\n\t\t//usage: .dynamic\n//\t\twrap_u:        .clamp_to_edge\n//\t\twrap_v:        .clamp_to_edge\n\t\tlabel:         &char(unsafe { nil })\n\t\td3d11_texture: 0\n\t}\n\t// vfmt on\n\t// comment if .dynamic is enabled\n\timg_desc.data.subimage[0][0] = gfx.Range{\n\t\tptr:  buf\n\t\tsize: usize(sz)\n\t}\n\n\tsg_img := gfx.make_image(&img_desc)\n\n\tmut smp_desc := gfx.SamplerDesc{\n\t\tmin_filter: .linear\n\t\tmag_filter: .linear\n\t\twrap_u:     .clamp_to_edge\n\t\twrap_v:     .clamp_to_edge\n\t}\n\n\tsg_smp := gfx.make_sampler(&smp_desc)\n\treturn sg_img, sg_smp\n}\n\nfn destroy_texture(sg_img gfx.Image) {\n\tgfx.destroy_image(sg_img)\n}\n\n// Use only if usage: .dynamic is enabled\nfn update_text_texture(sg_img gfx.Image, w int, h int, buf byteptr) {\n\tsz := w * h * 4\n\tmut tmp_sbc := gfx.ImageData{}\n\ttmp_sbc.subimage[0][0] = gfx.Range{\n\t\tptr:  buf\n\t\tsize: usize(sz)\n\t}\n\tgfx.update_image(sg_img, &tmp_sbc)\n}\n\n/******************************************************************************\n* Draw functions\n******************************************************************************\n\t\tCube vertex buffer with packed vertex formats for color and texture coords.\n\t\tNote that a vertex format which must be portable across all\n\t\tbackends must only use the normalized integer formats\n\t\t(BYTE4N, UBYTE4N, SHORT2N, SHORT4N), which can be converted\n\t\tto floating point formats in the vertex shader inputs.\n\t\tThe reason is that D3D11 cannot convert from non-normalized\n\t\tformats to floating point inputs (only to integer inputs),\n\t\tand WebGL2 / GLES2 don't support integer vertex shader inputs.\n*/\n\nstruct Vertex_t {\n\tx     f32\n\ty     f32\n\tz     f32\n\tcolor u32\n\t// u u16   // for compatibility with D3D11\n\t// v u16   // for compatibility with D3D11\n\tu f32\n\tv f32\n}\n\n// march shader init\nfn init_cube_glsl_i(mut app App) {\n\t// cube vertex buffer\n\t// d := u16(32767)     // for compatibility with D3D11, 32767 stand for 1\n\td := f32(1.0)\n\tc := u32(0xFFFFFF_FF) // color RGBA8\n\t// vfmt off\n  \tvertices := [\n\t\t// Face 0\n\t\tVertex_t{-1.0, -1.0, -1.0, c,  0, 0},\n\t\tVertex_t{ 1.0, -1.0, -1.0, c,  d, 0},\n\t\tVertex_t{ 1.0,  1.0, -1.0, c,  d, d},\n\t\tVertex_t{-1.0,  1.0, -1.0, c,  0, d},\n\t\t// Face 1\n\t\tVertex_t{-1.0, -1.0,  1.0, c,  0, 0},\n\t\tVertex_t{ 1.0, -1.0,  1.0, c,  d, 0},\n\t\tVertex_t{ 1.0,  1.0,  1.0, c,  d, d},\n\t\tVertex_t{-1.0,  1.0,  1.0, c,  0, d},\n\t\t// Face 2\n\t\tVertex_t{-1.0, -1.0, -1.0, c,  0, 0},\n\t\tVertex_t{-1.0,  1.0, -1.0, c,  d, 0},\n\t\tVertex_t{-1.0,  1.0,  1.0, c,  d, d},\n\t\tVertex_t{-1.0, -1.0,  1.0, c,  0, d},\n\t\t// Face 3\n\t\tVertex_t{ 1.0, -1.0, -1.0, c,  0, 0},\n\t\tVertex_t{ 1.0,  1.0, -1.0, c,  d, 0},\n\t\tVertex_t{ 1.0,  1.0,  1.0, c,  d, d},\n\t\tVertex_t{ 1.0, -1.0,  1.0, c,  0, d},\n\t\t// Face 4\n\t\tVertex_t{-1.0, -1.0, -1.0, c,  0, 0},\n\t\tVertex_t{-1.0, -1.0,  1.0, c,  d, 0},\n\t\tVertex_t{ 1.0, -1.0,  1.0, c,  d, d},\n\t\tVertex_t{ 1.0, -1.0, -1.0, c,  0, d},\n\t\t// Face 5\n\t\tVertex_t{-1.0,  1.0, -1.0, c,  0, 0},\n\t\tVertex_t{-1.0,  1.0,  1.0, c,  d, 0},\n\t\tVertex_t{ 1.0,  1.0,  1.0, c,  d, d},\n\t\tVertex_t{ 1.0,  1.0, -1.0, c,  0, d},\n\t]\n\t// vfmt on\n\n\tmut vert_buffer_desc := gfx.BufferDesc{\n\t\tlabel: c'cube-vertices'\n\t}\n\tunsafe { vmemset(&vert_buffer_desc, 0, int(sizeof(vert_buffer_desc))) }\n\tvert_buffer_desc.size = usize(vertices.len * int(sizeof(Vertex_t)))\n\tvert_buffer_desc.data = gfx.Range{\n\t\tptr:  vertices.data\n\t\tsize: usize(vertices.len * int(sizeof(Vertex_t)))\n\t}\n\tvert_buffer_desc.type = .vertexbuffer\n\tvbuf := gfx.make_buffer(&vert_buffer_desc)\n\n\t// create an instance buffer for the cube\n\tmut inst_buffer_desc := gfx.BufferDesc{\n\t\tlabel: c'instance-data'\n\t}\n\tunsafe { vmemset(&inst_buffer_desc, 0, int(sizeof(inst_buffer_desc))) }\n\n\tinst_buffer_desc.size = usize(num_inst * int(sizeof(m4.Vec4)))\n\tinst_buffer_desc.type = .vertexbuffer\n\tinst_buffer_desc.usage = .stream\n\tinst_buf := gfx.make_buffer(&inst_buffer_desc)\n\n\t// create an index buffer for the cube\n\t// vfmt off\n\tindices := [\n\t\tu16(0),  1,  2,    0,  2,  3,\n\t\t     6,  5,  4,    7,  6,  4,\n\t\t     8,  9, 10,    8, 10, 11,\n\t\t    14, 13, 12,   15, 14, 12,\n\t\t    16, 17, 18,   16, 18, 19,\n\t\t    22, 21, 20,   23, 22, 20,\n\t]\n\t// vfmt on\n\n\tmut index_buffer_desc := gfx.BufferDesc{\n\t\tlabel: c'cube-indices'\n\t}\n\tunsafe { vmemset(&index_buffer_desc, 0, int(sizeof(index_buffer_desc))) }\n\tindex_buffer_desc.size = usize(indices.len * int(sizeof(u16)))\n\tindex_buffer_desc.data = gfx.Range{\n\t\tptr:  indices.data\n\t\tsize: usize(indices.len * int(sizeof(u16)))\n\t}\n\tindex_buffer_desc.type = .indexbuffer\n\tibuf := gfx.make_buffer(&index_buffer_desc)\n\n\t// create shader\n\tshader := gfx.make_shader(voidptr(C.instancing_shader_desc(C.sg_query_backend())))\n\n\tmut pipdesc := gfx.PipelineDesc{}\n\tunsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }\n\tpipdesc.layout.buffers[0].stride = int(sizeof(Vertex_t))\n\n\t// vfmt off\n\t// the constants [C.ATTR_vs_m_pos, C.ATTR_vs_m_color0, C.ATTR_vs_m_texcoord0] are generated by sokol-shdc\n\tpipdesc.layout.attrs[C.ATTR_vs_i_pos      ].format       = .float3   // x,y,z as f32\n\tpipdesc.layout.attrs[C.ATTR_vs_i_pos      ].buffer_index = 0\n\tpipdesc.layout.attrs[C.ATTR_vs_i_color0   ].format       = .ubyte4n  // color as u32\n\tpipdesc.layout.attrs[C.ATTR_vs_i_pos      ].buffer_index = 0\n\tpipdesc.layout.attrs[C.ATTR_vs_i_texcoord0].format       = .float2   // u,v as f32\n\tpipdesc.layout.attrs[C.ATTR_vs_i_pos      ].buffer_index = 0\n\n\t// instancing\n\t// the constant ATTR_vs_i_inst_pos is generated by sokol-shdc\n\tpipdesc.layout.buffers[1].stride    = int(sizeof(m4.Vec4))\n\tpipdesc.layout.buffers[1].step_func = .per_instance  // we will pass a single parameter for each instance!!\n\tpipdesc.layout.attrs[C.ATTR_vs_i_inst_pos ].format        = .float4\n\tpipdesc.layout.attrs[C.ATTR_vs_i_inst_pos ].buffer_index  = 1\n\t// vfmt on\n\n\tpipdesc.shader = shader\n\tpipdesc.index_type = .uint16\n\n\tpipdesc.depth = gfx.DepthState{\n\t\twrite_enabled: true\n\t\tcompare:       .less_equal\n\t}\n\tpipdesc.cull_mode = .back\n\n\tpipdesc.label = c'glsl_shader pipeline'\n\n\tmut bind := gfx.Bindings{}\n\tunsafe { vmemset(&bind, 0, int(sizeof(bind))) }\n\tbind.vertex_buffers[0] = vbuf // vertex buffer\n\tbind.vertex_buffers[1] = inst_buf // instance buffer\n\tbind.index_buffer = ibuf\n\tbind.fs.images[C.SLOT_tex] = app.texture\n\tbind.fs.samplers[C.SLOT_smp] = app.sampler\n\tapp.bind['inst'] = bind\n\tapp.pipe['inst'] = gfx.make_pipeline(&pipdesc)\n\n\tprintln('GLSL March init DONE!')\n}\n\nfn calc_tr_matrices(w f32, h f32, rx f32, ry f32, in_scale f32) m4.Mat4 {\n\t// vfmt off\n\tproj := m4.perspective(60, w/h, 0.01, 4000.0)\n\tview := m4.look_at(m4.Vec4{e:[f32(0.0),100,6,0]!}, m4.Vec4{e:[f32(0),0,0,0]!}, m4.Vec4{e:[f32(0),1.0,0,0]!})\n\tview_proj := view * proj\n\n\trxm := m4.rotate(m4.rad(rx), m4.Vec4{e:[f32(1),0,0,0]!})\n\trym := m4.rotate(m4.rad(ry), m4.Vec4{e:[f32(0),1,0,0]!})\n\t// vfmt on\n\n\tmodel := rym * rxm\n\tscale_m := m4.scale(m4.Vec4{ e: [in_scale, in_scale, in_scale, 1]! })\n\n\tres := (scale_m * model) * view_proj\n\treturn res\n}\n\n// triangles draw\nfn draw_cube_glsl_i(mut app App) {\n\tif app.init_flag == false {\n\t\treturn\n\t}\n\n\tws := gg.window_size_real_pixels()\n\t// ratio := f32(ws.width) / ws.height\n\tdw := f32(ws.width / 2)\n\tdh := f32(ws.height / 2)\n\n\trot := [f32(app.mouse_y), f32(app.mouse_x)]\n\ttr_matrix := calc_tr_matrices(dw, dh, rot[0], rot[1], 2.3)\n\n\tgfx.apply_pipeline(app.pipe['inst'])\n\tgfx.apply_bindings(app.bind['inst'])\n\n\t//***************\n\t// Instancing\n\t//***************\n\t// passing the instancing to the vs\n\ttime_ticks := f32(time.ticks() - app.ticks) / 1000\n\tcube_size := 2\n\tsz := 128 // field size dimension\n\tcx := 64 // x center for the cubes\n\tcz := 64 // z center for the cubes\n\t// frame := (app.frame_count/4) % 100\n\tfor index in 0 .. num_inst {\n\t\tx := f32(index % sz)\n\t\tz := f32(index / sz)\n\t\t// simply waves\n\t\ty := f32(math.cos((x + time_ticks) / 2.0) * math.sin(z / 2.0)) * 2\n\t\t// sombrero function\n\t\t// r := ((x-cx)*(x-cx)+(z-cz)*(z-cz))/(sz/2)\n\t\t// y := f32(math.sin(r+time_ticks)*4.0)\n\t\tspare_param := f32(index % 10)\n\t\t// vfmt off\n\t\tapp.inst_pos[index] = m4.Vec4{e:[f32((x - cx - app.camera_x) * cube_size),y ,f32( (z - cz - app.camera_z) * cube_size),spare_param]!}\n\t\t// vfmt on\n\t}\n\trange := gfx.Range{\n\t\tptr:  unsafe { &app.inst_pos }\n\t\tsize: usize(num_inst * int(sizeof(m4.Vec4)))\n\t}\n\tgfx.update_buffer(app.bind['inst'].vertex_buffers[1], &range)\n\n\t// Uniforms\n\t// *** vertex shadeer uniforms ***\n\t// passing the view matrix as uniform\n\t// res is a 4x4 matrix of f32 thus: 4*16 byte of size\n\tvs_uniforms_range := gfx.Range{\n\t\tptr:  unsafe { &tr_matrix }\n\t\tsize: usize(4 * 16)\n\t}\n\tgfx.apply_uniforms(.vs, C.SLOT_vs_params_i, &vs_uniforms_range)\n\n\t/*\n\t// *** fragment shader uniforms ***\n\ttime_ticks := f32(time.ticks() - app.ticks) / 1000\n\t// vfmt off\n\tmut tmp_fs_params := [\n\t\tf32(ws.width), ws.height * ratio,  // x,y resolution to pass to FS\n\t\t0,0,                         // dont send mouse position\n\t\t//app.mouse_x,               // mouse x\n\t\t//ws.height - app.mouse_y*2, // mouse y scaled\n\t\ttime_ticks,                  // time as f32\n\t\tapp.frame_count,             // frame count\n\t\t0,0                          // padding bytes , see \"fs_params\" struct paddings in rt_glsl.h\n\t]!\n\t// vfmt on\n\tfs_uniforms_range := gfx.Range{\n\t\tptr: unsafe { &tmp_fs_params }\n\t\tsize: usize(sizeof(tmp_fs_params))\n\t}\n\tgfx.apply_uniforms(.fs, C.SLOT_fs_params, &fs_uniforms_range)\n\t*/\n\t// 3 vertices for triangle * 2 triangles per face * 6 faces = 36 vertices to draw for num_inst times\n\tgfx.draw(0, (3 * 2) * 6, num_inst)\n}\n\nfn draw_start_glsl(app App) {\n\tif app.init_flag == false {\n\t\treturn\n\t}\n\n\tws := gg.window_size_real_pixels()\n\t// ratio := f32(ws.width) / ws.height\n\t// dw := f32(ws.width  / 2)\n\t// dh := f32(ws.height / 2)\n\n\tgfx.apply_viewport(0, 0, ws.width, ws.height, true)\n}\n\nfn draw_end_glsl(app App) {\n\tgfx.end_pass()\n\tgfx.commit()\n}\n\nfn frame(mut app App) {\n\t// clear\n\tmut color_action := gfx.ColorAttachmentAction{\n\t\tload_action: .clear\n\t\tclear_value: gfx.Color{\n\t\t\tr: 0.0\n\t\t\tg: 0.0\n\t\t\tb: 0.0\n\t\t\ta: 1.0\n\t\t}\n\t}\n\tmut pass_action := gfx.PassAction{}\n\tpass_action.colors[0] = color_action\n\tpass := gg.create_default_pass(pass_action)\n\tgfx.begin_pass(&pass)\n\n\tdraw_start_glsl(app)\n\tdraw_cube_glsl_i(mut app)\n\tdraw_end_glsl(app)\n\tapp.frame_count++\n}\n\n/******************************************************************************\n* Init / Cleanup\n******************************************************************************/\nfn my_init(mut app App) {\n\t// create chessboard texture 256*256 RGBA\n\tw := 256\n\th := 256\n\tsz := w * h * 4\n\ttmp_txt := unsafe { malloc(sz) }\n\tmut i := 0\n\tfor i < sz {\n\t\tunsafe {\n\t\t\ty := (i >> 0x8) >> 5 // 8 cell\n\t\t\tx := (i & 0xFF) >> 5 // 8 cell\n\t\t\t// upper left corner\n\t\t\tif x == 0 && y == 0 {\n\t\t\t\ttmp_txt[i + 0] = u8(0xFF)\n\t\t\t\ttmp_txt[i + 1] = u8(0)\n\t\t\t\ttmp_txt[i + 2] = u8(0)\n\t\t\t\ttmp_txt[i + 3] = u8(0xFF)\n\t\t\t}\n\t\t\t// low right corner\n\t\t\telse if x == 7 && y == 7 {\n\t\t\t\ttmp_txt[i + 0] = u8(0)\n\t\t\t\ttmp_txt[i + 1] = u8(0xFF)\n\t\t\t\ttmp_txt[i + 2] = u8(0)\n\t\t\t\ttmp_txt[i + 3] = u8(0xFF)\n\t\t\t} else {\n\t\t\t\tcol := if ((x + y) & 1) == 1 { 0xFF } else { 128 }\n\t\t\t\ttmp_txt[i + 0] = u8(col) // red\n\t\t\t\ttmp_txt[i + 1] = u8(col) // green\n\t\t\t\ttmp_txt[i + 2] = u8(col) // blue\n\t\t\t\ttmp_txt[i + 3] = u8(0xFF) // alpha\n\t\t\t}\n\t\t\ti += 4\n\t\t}\n\t}\n\tunsafe {\n\t\tapp.texture, app.sampler = create_texture(w, h, tmp_txt)\n\t\tfree(tmp_txt)\n\t}\n\t// glsl\n\tinit_cube_glsl_i(mut app)\n\tapp.init_flag = true\n}\n\n/******************************************************************************\n* events handling\n******************************************************************************/\nfn my_event_manager(mut ev gg.Event, mut app App) {\n\tif ev.typ == .mouse_down {\n\t\tapp.mouse_down = true\n\t}\n\tif ev.typ == .mouse_up {\n\t\tapp.mouse_down = false\n\t}\n\tif app.mouse_down == true && ev.typ == .mouse_move {\n\t\tapp.mouse_x = int(ev.mouse_x)\n\t\tapp.mouse_y = int(ev.mouse_y)\n\t}\n\tif ev.typ == .touches_began || ev.typ == .touches_moved {\n\t\tif ev.num_touches > 0 {\n\t\t\ttouch_point := ev.touches[0]\n\t\t\tapp.mouse_x = int(touch_point.pos_x)\n\t\t\tapp.mouse_y = int(touch_point.pos_y)\n\t\t}\n\t}\n\n\t// keyboard\n\tif ev.typ == .key_down {\n\t\tstep := f32(1.0)\n\t\tmatch ev.key_code {\n\t\t\t.w { app.camera_z += step }\n\t\t\t.s { app.camera_z -= step }\n\t\t\t.a { app.camera_x -= step }\n\t\t\t.d { app.camera_x += step }\n\t\t\telse {}\n\t\t}\n\t}\n\teprintln('>> app.camera_x: ${app.camera_x} , app.camera_z: ${app.camera_z}, app.mouse_x: ${app.mouse_x}, app.mouse_y: ${app.mouse_y}')\n}\n\nfn main() {\n\tmut app := &App{}\n\t// vfmt off\n\tapp.gg = gg.new_context(\n\t\twidth:         win_width\n\t\theight:        win_height\n\t\tcreate_window: true\n\t\twindow_title:  'Instancing Cube'\n\t\tuser_data:     app\n\t\tbg_color:      bg_color\n\t\tframe_fn:      frame\n\t\tinit_fn:       my_init\n\t\tevent_fn:      my_event_manager\n\t)\n\t// vfmt on\n\tapp.ticks = time.ticks()\n\tapp.gg.run()\n}\n"
  },
  {
    "path": "examples/sokol/05_instancing_glsl/rt_glsl_instancing.glsl",
    "content": "//------------------------------------------------------------------------------\n//  Shader code for texcube-sapp sample.\n//\n//  NOTE: This source file also uses the '#pragma sokol' form of the\n//  custom tags.\n//------------------------------------------------------------------------------\n//#pragma sokol @ctype mat4 hmm_mat4\n\n#pragma sokol @vs vs_i\nuniform vs_params_i {\n    mat4 mvp;\n};\n\nin vec4 pos;\nin vec4 color0;\nin vec2 texcoord0;\n\nin vec4 inst_pos;\n\nout vec4 color;\nout vec4 color_inst;\nout vec2 uv;\n\nconst vec4 palette[10] = vec4[10](\n\tvec4(1,0,0,1),\n\tvec4(0,1,0,1),\n\tvec4(0,0,1,1),\n\tvec4(1,1,0,1),\n\tvec4(0,1,1,1),\n\tvec4(1,1,1,1),\n\tvec4(0,0,0,1),\n\tvec4(0.2,0.2,0.2,1),\n\tvec4(0.3,0.3,0.3,1),\n\tvec4(0.9,0.9,0.9,1)\n);\n\nvoid main() {\n\t\tvec4 delta_pos = vec4(inst_pos.xyz,0);\n\t\tfloat w = inst_pos.w;\n\t\tcolor_inst = palette[int(w)];\n    gl_Position = mvp * (pos + delta_pos);\n    color = color0;\n    uv = texcoord0/4;\n}\n#pragma sokol @end\n\n#pragma sokol @fs fs_i\nuniform texture2D tex;\nuniform sampler smp;\n\nin vec4 color;\nin vec4 color_inst;\nin vec2 uv;\nout vec4 frag_color;\n\nvoid main() {\n\tvec4 c = color;\n\tvec4 txt = texture(sampler2D(tex, smp), uv);\n\tc = txt * c * color_inst;\n\tfrag_color = c ;\n}\n\n#pragma sokol @end\n\n#pragma sokol @program instancing vs_i fs_i\n"
  },
  {
    "path": "examples/sokol/05_instancing_glsl/v.mod",
    "content": ""
  },
  {
    "path": "examples/sokol/06_obj_viewer/assets/models/apple.mtl",
    "content": "# Blender MTL File: 'None'\n# Material Count: 2\n\nnewmtl Material.001\nNs 96.078443\nKa 1.000000 1.000000 1.000000\nKd 0.640000 0.640000 0.640000\nKs 0.500000 0.500000 0.500000\nKe 0.000000 0.000000 0.000000\nNi 1.000000\nd 1.000000\nillum 2\n\nmap_Kd apple.png\n\nnewmtl Material.002\nNs 96.078443\nKa 1.000000 1.000000 1.000000\nKd 0.640000 0.640000 0.640000\nKs 0.500000 0.500000 0.500000\nKe 0.000000 0.000000 0.000000\nNi 1.000000\nd 1.000000\nillum 2\n\nmap_Kd apple.png\n"
  },
  {
    "path": "examples/sokol/06_obj_viewer/assets/models/donut.mtl",
    "content": "# Blender MTL File: 'donut.blend'\n# Material Count: 1\n\nnewmtl Material.001\nNs 225.000000\nKa 1.000000 1.000000 1.000000\nKd 0.800000 0.800000 0.800000\nKs 0.500000 0.500000 0.500000\nKe 0.259059 0.005681 0.342383\nNi 1.450000\nd 0.800000\nillum 9\n"
  },
  {
    "path": "examples/sokol/06_obj_viewer/assets/models/v.mtl",
    "content": "# Blender MTL File: 'v-logo.blend'\n# Material Count: 2\nnewmtl Material.001\nNs 96.078431\nKa 0.2 0.2 0.2\nKd 0.365 0.529 0.749\nKs 0.85 0.85 0.85\nKe 0 0 0\nNi 1\nd 1\nillum 1\nnewmtl Material.002\nNs 96.078431\nKa 0.1 0.1 0.1\nKd 0.325 0.42 0.541\nKs 0.85 0.85 0.85\nKe 0 0 0\nNi 1\nd 1\nillum 1"
  },
  {
    "path": "examples/sokol/06_obj_viewer/gouraud.glsl",
    "content": "//#pragma sokol @ctype mat4 hmm_mat4\n\n#pragma sokol @vs vs\n\nuniform vs_params {\n\tmat4 u_MVMatrix;       // A constant representing the combined model/view matrix.\n\tmat4 u_MVPMatrix;      // A constant representing the combined model/view/projection matrix.\n\tmat4 u_NMatrix;        // A constant representing the Normal Matrix\n};\n\nin vec4 a_Position;     // Per-vertex position information we will pass in.\nin vec3 a_Normal;       // Per-vertex normal information we will pass in.\n//in vec4 a_Color;        // Per-vertex color information we will pass in.\nin vec2 a_Texcoord0;\n\nout vec3 v_Position;   // This will be passed into the fragment shader.\n//out vec4 v_Color;      // This will be passed into the fragment shader.\nout vec3 v_Normal;     // This will be passed into the fragment shader.\nout vec3 v_Normal1;\nout vec2 uv;           // This will be passed into the fragment shader.\n\n// The entry point for our vertex shader.\nvoid main()\n{\n\t// Transform the vertex into eye space.\n\tv_Position = vec3(u_MVMatrix * a_Position);\n\t// Pass through the color.\n\t//v_Color = a_Color;\n\t// calc eye space normal\n\tv_Normal = vec3(u_NMatrix * vec4(a_Normal, 1.0));\n\t// texture coord\n\tuv = a_Texcoord0;\n\n\tv_Normal1 = normalize(vec3(u_MVMatrix * vec4(a_Normal, 1.0)));\n\n\t// gl_Position is a special variable used to store the final position.\n\t// Multiply the vertex by the matrix to get the final point in normalized screen coordinates.\n\tgl_Position = u_MVPMatrix * a_Position;\n}\n\n#pragma sokol @end\n\n#pragma sokol @fs fs\n//precision mediump float;       // Set the default precision to medium. We don't need as high of a precision in the fragment shader\nuniform texture2D tex;\nuniform sampler smp;\nuniform fs_params {\n\tvec4 u_LightPos;       // The position of the light in eye space.\n\tvec4 ambientColor;\n\tvec4 diffuseColor;\n\tvec4 specularColor;\n\n};\nin vec3 v_Position;       // Interpolated position for this fragment.\n//in vec4 v_Color;          // This is the color from the vertex shader interpolated across the triangle per fragment.\nin vec3 v_Normal;         // Interpolated normal for this fragment.\nin vec3 v_Normal1;\nin vec2 uv;\nout vec4 frag_color;\n\nvec3 lightDirection = -u_LightPos.xyz;// vec3(0.0, -0.5, 0.5);\n//const vec4 ambientColor = vec4(0.094, 0.0, 0.0, 1.0);\n//const vec4 diffuseColor = vec4(0.5, 0.0, 0.0, 1.0);\n//const vec4 specularColor = vec4(1.0, 1.0, 1.0, 1.0);\n//const float shininess = 10.0;\nconst vec4 lightColor = vec4(1.0, 1.0, 1.0, 1.0);\n\nvec3 phongBRDF(vec3 lightDir, vec3 viewDir, vec3 normal, vec3 phongDiffuseCol, vec3 phongSpecularCol, float phongShininess) {\n  vec3 color = phongDiffuseCol;\n  vec3 reflectDir = reflect(-lightDir, normal);\n  float specDot = max(dot(reflectDir, viewDir), 0.0);\n  color += pow(specDot, phongShininess) * phongSpecularCol;\n  return color;\n}\n\nvec4 getPhong(in vec4 diffuseColor) {\n  vec3 lightDir = normalize(-lightDirection);\n  vec3 viewDir = normalize(-v_Position);\n  vec3 n = normalize(v_Normal);\n\n  vec3 luminance = ambientColor.rgb * 0.5;\n\n  float illuminance = dot(lightDir, n);\n  if(illuminance > 0.0) {\n\t\t// we save specular shiness in specularColor.a\n    vec3 brdf = phongBRDF(lightDir, viewDir, n, diffuseColor.rgb, specularColor.rgb, specularColor.a * 1000);\n    luminance += brdf * illuminance * lightColor.rgb;\n  }\n\n  vec4 outColor = vec4(luminance,1.0);\n  return outColor;\n}\n\n// The entry point for our fragment shader.\nvoid main()\n{\n\tvec4 txt = texture(sampler2D(tex, smp), uv);\n\n\t// Directional light\n\tfloat directional = dot(normalize(v_Normal1), normalize(vec3(0,0.5,1))) ;\n\tdirectional = directional * 0.15;\n\n  // Multiply the color by the diffuse illumination level to get final output color.\n\tfrag_color = vec4(clamp(directional + txt.rgb * getPhong(diffuseColor).rgb,0,1), txt.a * diffuseColor.a);\n\n}\n#pragma sokol @end\n\n#pragma sokol @program gouraud vs fs\n"
  },
  {
    "path": "examples/sokol/06_obj_viewer/modules/obj/obj.v",
    "content": "module obj\n\n/**********************************************************************\n*\n* .obj loader\n*\n* Copyright (c) 2021 Dario Deledda. All rights reserved.\n* Use of this source code is governed by an MIT license\n* that can be found in the LICENSE file.\n*\n* TODO:\n**********************************************************************/\nimport gg.m4\nimport strconv\n\nenum F_state {\n\tstart\n\tfirst\n\tints\n\tdecimals\n\texp_start\n\texp_sign\n\texp_int\n}\n\n// read a int from a string\nfn get_int(s string, start_index int) (int, int) {\n\tmut i := start_index\n\tmut res := 0\n\tmut sgn := 1\n\n\tmut state := F_state.start\n\tfor true {\n\t\tif i >= s.len {\n\t\t\tbreak\n\t\t}\n\t\tc := s[i]\n\t\tif state == .start {\n\t\t\tmatch c {\n\t\t\t\t`+` {\n\t\t\t\t\ti++\n\t\t\t\t\tstate = .ints\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t`-` {\n\t\t\t\t\tsgn = -1\n\t\t\t\t\ti++\n\t\t\t\t\tstate = .ints\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t`0`...`9` {\n\t\t\t\t\tstate = .ints\n\t\t\t\t}\n\t\t\t\t` `, `\\t` {\n\t\t\t\t\ti++\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\telse { // no number found\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif state == .ints {\n\t\t\tmatch c {\n\t\t\t\t`0`...`9` {\n\t\t\t\t\t// println(\"${res} => ${(int(c) - 48)}\")\n\t\t\t\t\tres = res * 10 + (int(c) - 48)\n\t\t\t\t\ti++\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// println(\"---\")\n\treturn res * sgn, i\n}\n\n// reas a float number from a string\nfn get_float(s string, start_index int) (f64, int) {\n\tmut i1 := start_index //+ 1\n\tfor i1 < s.len && s[i1] in [` `, `\\t`] {\n\t\ti1++\n\t}\n\tmut i := i1\n\tfor i < s.len {\n\t\tif s[i] in [` `, `\\t`] {\n\t\t\tbreak\n\t\t}\n\t\ti++\n\t}\n\t// println(\" get_float: (${start_index},${i}) [${s[start_index..i]}]\")\n\t// f_res := strconv.atof_quick(s[start_index..i])\n\tf_res := strconv.atof_quick(s[i1..i])\n\treturn f_res, i\n}\n\n// read 3 f32 in sequence from a string\nfn parse_3f(row string, start_index int) m4.Vec4 {\n\t// println(row)\n\tmut i := start_index //+ 1\n\tmut f1 := f64(0)\n\tmut f2 := f64(0)\n\tf0, mut p := get_float(row, i)\n\t// print(\"Here f0: ${f0} ${p} \")\n\tf1, p = get_float(row, p + 1)\n\t// print(\"Here f1: ${f1} ${p} \")\n\tf2, p = get_float(row, p + 1)\n\t// print(\"Here f2: ${f2} ${p} \")\n\treturn m4.Vec4{\n\t\te: [f32(f0), f32(f1), f32(f2), 1]!\n\t}\n}\n\n// reas a sequence of f32 from a string\nfn (mut m ObjPart) parse_floats(row string, start_index int) m4.Vec4 {\n\tmut i := start_index //+ 1\n\tmut res_f := f64(0)\n\tmut res := m4.Vec4{\n\t\te: [f32(0), 0, 0, 1]!\n\t}\n\tmut c := 0\n\tfor true {\n\t\tres_f, i = get_float(row, i)\n\t\tunsafe {\n\t\t\tres.e[c] = f32(res_f)\n\t\t}\n\t\tc++\n\t\ti++\n\t\tif i >= row.len {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn res\n}\n\n// read and manage all the faes from an .obj file data\nfn (mut p Part) parse_faces(row string, start_index int, obj_part ObjPart) {\n\tmut i := start_index + 1\n\tmut res := [][3]int{}\n\tmut v := 0\n\tmut t := 0\n\tmut n := 0\n\t// println(\"row: ${row[i..]}\")\n\tfor true {\n\t\tt = 0\n\t\tn = 0\n\t\tif i >= row.len {\n\t\t\tbreak\n\t\t}\n\t\tmut c := row[i]\n\t\tif (c > `9` || c < `0`) && c != `-` {\n\t\t\ti++\n\t\t\tcontinue\n\t\t}\n\t\tv, i = get_int(row, i)\n\t\tif i < row.len && row[i] == `/` {\n\t\t\tif row[i + 1] != `/` {\n\t\t\t\tt, i = get_int(row, i + 1)\n\t\t\t\tif i < row.len && row[i] == `/` {\n\t\t\t\t\tn, i = get_int(row, i + 1)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ti++\n\t\t\t\tn, i = get_int(row, i + 1)\n\t\t\t}\n\t\t}\n\t\t// manage negative indexes\n\t\t// NOTE: not well suporeted now\n\t\tif v < 0 {\n\t\t\t// println(\"${obj_part.v.len} ${obj_part.v.len-c}\")\n\t\t\tv = obj_part.v.len - v + 1\n\t\t\t// exit(0)\n\t\t}\n\t\tif n < 0 {\n\t\t\tn = obj_part.vn.len - n + 1\n\t\t}\n\t\tif t < 0 {\n\t\t\tt = obj_part.vt.len - t + 1\n\t\t}\n\t\tres << [v - 1, n - 1, t - 1]!\n\t}\n\t// println(\"ok res: ${res}\")\n\t// println(p.faces.len)\n\tp.faces << res\n}\n\n// parse the obj file, if single_material is true it use only one default material\npub fn (mut obj_part ObjPart) parse_obj_buffer(rows []string, single_material bool) {\n\tmut mat_count := 0\n\tmut row_count := 0\n\tdefault_part := Part{\n\t\tname: 'default part'\n\t}\n\tobj_part.part << default_part\n\t// println(\"OBJ file has ${rows.len} rows\")\n\tfor c, row in rows {\n\t\t// println(\"${c} ${row}\")\n\t\tmut i := 0\n\t\trow_count++\n\t\tfor true {\n\t\t\tif i >= row.len {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tmatch row[i] {\n\t\t\t\t`s` {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\t`m` {\n\t\t\t\t\tif row[i..i + 6] == 'mtllib' {\n\t\t\t\t\t\tobj_part.material_file = row[i + 7..].trim_space()\n\t\t\t\t\t\tobj_part.load_materials()\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\t`o`, `g` {\n\t\t\t\t\tmut part := Part{}\n\t\t\t\t\tpart.name = row[i + 1..].trim_space()\n\t\t\t\t\tobj_part.part << part\n\t\t\t\t\tmat_count = 0\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\t`u` {\n\t\t\t\t\tif single_material == false && row[i..i + 6] == 'usemtl' {\n\t\t\t\t\t\tmaterial := row[i + 7..].trim_space()\n\t\t\t\t\t\t// println(\"material: ${material}\")\n\t\t\t\t\t\t// manage multiple materials in an part\n\t\t\t\t\t\tif obj_part.part[obj_part.part.len - 1].material.len > 0 {\n\t\t\t\t\t\t\tmat_count++\n\t\t\t\t\t\t\tmut part := Part{}\n\t\t\t\t\t\t\tif mat_count > 1 {\n\t\t\t\t\t\t\t\tli := obj_part.part[obj_part.part.len - 1].name.last_index('_m') or {\n\t\t\t\t\t\t\t\t\tobj_part.part[obj_part.part.len - 1].name.len - 1\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tpart.name = obj_part.part[obj_part.part.len - 1].name[..li] +\n\t\t\t\t\t\t\t\t\t'_m${mat_count:02}'\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tpart.name = obj_part.part[obj_part.part.len - 1].name + '_m01'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tobj_part.part << part\n\t\t\t\t\t\t}\n\t\t\t\t\t\tobj_part.part[obj_part.part.len - 1].material = material\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\t`v` {\n\t\t\t\t\ti++\n\t\t\t\t\tmatch row[i] {\n\t\t\t\t\t\t// normals\n\t\t\t\t\t\t`n` {\n\t\t\t\t\t\t\tobj_part.vn << parse_3f(row, i + 2)\n\t\t\t\t\t\t\t// println(\"Vertex line: ${c}\")\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// parameters uvw\n\t\t\t\t\t\t`p` {\n\t\t\t\t\t\t\tobj_part.vp << parse_3f(row, i + 2)\n\t\t\t\t\t\t\t// println(\"Vertex line: ${obj_part.vp.len}\")\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// texture uvw\n\t\t\t\t\t\t`t` {\n\t\t\t\t\t\t\tobj_part.vt << obj_part.parse_floats(row, i + 2)\n\t\t\t\t\t\t\t// println(\"Vertex line: ${c}\")\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tobj_part.v << parse_3f(row, i + 1)\n\t\t\t\t\t\t\t// println(\"${row} => ${obj_part.v[obj_part.v.len-1]}\")\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t`f` {\n\t\t\t\t\t// println(\"${c} ${row}\")\n\t\t\t\t\tobj_part.part[obj_part.part.len - 1].parse_faces(row, i, obj_part)\n\t\t\t\t\t// println(obj_part.part[obj_part.part.len - 1].faces.len)\n\t\t\t\t\t// println(\"Faces line: ${c}\")\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\t// end of the line, comments\n\t\t\t\t`\\n`, `#` {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\telse {}\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t\t// if c == 2 { break }\n\t\tif c % 100000 == 0 && c > 0 {\n\t\t\tprintln('${c} rows parsed')\n\t\t}\n\t}\n\tprintln('${row_count} .obj Rows parsed')\n\t// remove default part if empty\n\tif obj_part.part.len > 1 && obj_part.part[0].faces.len == 0 {\n\t\tobj_part.part = obj_part.part[1..]\n\t}\n}\n\n// load the materials if found the .mtl file\nfn (mut obj_part ObjPart) load_materials() {\n\trows := read_lines_from_file(obj_part.material_file)\n\tprintln('Material file [${obj_part.material_file}] ${rows.len} Rows.')\n\tfor row in rows {\n\t\t// println(\"${row}\")\n\t\tmut i := 0\n\t\tfor true {\n\t\t\tif i >= row.len {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tmatch row[i] {\n\t\t\t\t`n` {\n\t\t\t\t\tif row[i..i + 6] == 'newmtl' {\n\t\t\t\t\t\tname := row[i + 6..].trim_space()\n\t\t\t\t\t\tmut mat := Material{\n\t\t\t\t\t\t\tname: name\n\t\t\t\t\t\t}\n\t\t\t\t\t\tobj_part.mat << mat\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t`K` {\n\t\t\t\t\tif row[i + 1] !in [`a`, `d`, `e`, `s`] {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tk_name := row[i..i + 2]\n\t\t\t\t\ti += 3\n\t\t\t\t\tvalue := parse_3f(row, i)\n\t\t\t\t\tobj_part.mat[obj_part.mat.len - 1].ks[k_name] = value\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\t`N` {\n\t\t\t\t\tn_name := row[i..i + 2]\n\t\t\t\t\ti += 3\n\t\t\t\t\tvalue, _ := get_float(row, i)\n\t\t\t\t\tobj_part.mat[obj_part.mat.len - 1].ns[n_name] = f32(value)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\t`m` {\n\t\t\t\t\tif row[i..i + 4] == 'map_' {\n\t\t\t\t\t\tname := row[i..i + 6]\n\t\t\t\t\t\tif (i + 7) < row.len {\n\t\t\t\t\t\t\tfile_name := row[i + 7..].trim_space()\n\t\t\t\t\t\t\tobj_part.mat[obj_part.mat.len - 1].maps[name] = file_name\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// transparency\n\t\t\t\t`d` {\n\t\t\t\t\tif row[i + 1] == ` ` {\n\t\t\t\t\t\tvalue, _ := get_float(row, i + 2)\n\t\t\t\t\t\tobj_part.mat[obj_part.mat.len - 1].ns['Tr'] = f32(value)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t`T` {\n\t\t\t\t\tif row[i + 1] == `r` {\n\t\t\t\t\t\tvalue, _ := get_float(row, i + 3)\n\t\t\t\t\t\tobj_part.mat[obj_part.mat.len - 1].ns['Tr'] = f32(1.0 - value)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// end of the line, comments\n\t\t\t\t`\\n`, `#` {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\t` `, `\\t` {\n\t\t\t\t\ti++\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n\n\t// create map material name => material index\n\tfor i, m in obj_part.mat {\n\t\tif m.name !in obj_part.mat_map {\n\t\t\tobj_part.mat_map[m.name] = i\n\t\t}\n\t}\n\n\tprintln('Material Loading Done!')\n}\n\n//==============================================================================\n// Sokol data\n//==============================================================================\n\n// vertex data struct\npub struct Vertex_pnct {\npub mut:\n\tx  f32 // position\n\ty  f32\n\tz  f32\n\tnx f32 // normal\n\tny f32\n\tnz f32\n\t// color u32 = 0xFFFFFFFF // color\n\tu f32 // uv\n\tv f32\n\t// u u16   // for compatibility with D3D11\n\t// v u16   // for compatibility with D3D11\n}\n\n// struct used to pass the data to the sokol calls\npub struct Skl_buffer {\npub mut:\n\tvbuf     []Vertex_pnct\n\tibuf     []u32\n\tn_vertex u32\n}\n\n// transforms data from .obj format to buffer ready to be used in the render\npub fn (mut obj_part ObjPart) get_buffer(in_part_list []int) Skl_buffer {\n\t// in_part           := 0\n\tmut v_count_index := 0\n\tmut out_buf := Skl_buffer{}\n\n\tmut cache := map[string]int{}\n\tmut cache_hit := 0\n\n\t// has_normals := obj_part.vn.len > 0\n\t// has_uvs     := obj_part.vt.len > 0\n\n\tfor in_part in in_part_list {\n\t\tpart := obj_part.part[in_part]\n\t\tfor fc, face in part.faces {\n\t\t\t// println(\"${fc} ${face}\")\n\t\t\t// default 3 faces\n\t\t\tmut v_seq := [0, 1, 2]\n\t\t\tif face.len == 4 {\n\t\t\t\tv_seq = [0, 1, 2, 0, 2, 3]\n\t\t\t}\n\n\t\t\t// if big faces => use the fan of triangles as solution\n\t\t\t// Note: this trick doesn't work with concave faces\n\t\t\tif face.len > 4 {\n\t\t\t\tv_seq = []\n\t\t\t\tmut i := 1\n\t\t\t\tfor i < (face.len - 1) {\n\t\t\t\t\tv_seq << 0\n\t\t\t\t\tv_seq << i\n\t\t\t\t\tv_seq << (i + 1)\n\t\t\t\t\ti++\n\t\t\t\t}\n\t\t\t\t// println(\"BIG FACES! ${fc} ${face.len} v_seq:${v_seq.len}\")\n\t\t\t}\n\n\t\t\t// no vertex index, generate normals\n\t\t\tif face[0][1] == -1 && face.len >= 3 {\n\t\t\t\tmut v_count := 0\n\t\t\t\tv0 := face[v_count + 0][0]\n\t\t\t\tv1 := face[v_count + 1][0]\n\t\t\t\tv2 := face[v_count + 2][0]\n\n\t\t\t\tvec0 := obj_part.v[v2] - obj_part.v[v1]\n\t\t\t\tvec1 := obj_part.v[v0] - obj_part.v[v1]\n\t\t\t\ttmp_normal := vec0 % vec1\n\n\t\t\t\tfor v_count < face.len {\n\t\t\t\t\tobj_part.vn << tmp_normal\n\t\t\t\t\tobj_part.part[in_part].faces[fc][v_count][1] = obj_part.vn.len - 1\n\t\t\t\t\tv_count++\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor vertex_index in v_seq {\n\t\t\t\t// position\n\t\t\t\tif vertex_index >= face.len {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tv_index := face[vertex_index][0] // vertex index\n\t\t\t\tn_index := face[vertex_index][1] // normal index\n\t\t\t\tt_index := face[vertex_index][2] // uv texture index\n\t\t\t\tkey := '${v_index}_${n_index}_${t_index}'\n\t\t\t\tif key !in cache {\n\t\t\t\t\tcache[key] = v_count_index\n\t\t\t\t\tmut pnct := Vertex_pnct{\n\t\t\t\t\t\tx: obj_part.v[v_index].e[0]\n\t\t\t\t\t\ty: obj_part.v[v_index].e[1]\n\t\t\t\t\t\tz: obj_part.v[v_index].e[2]\n\t\t\t\t\t}\n\t\t\t\t\t// normal\n\t\t\t\t\tif n_index >= 0 {\n\t\t\t\t\t\tpnct.nx = obj_part.vn[n_index].e[0]\n\t\t\t\t\t\tpnct.ny = obj_part.vn[n_index].e[1]\n\t\t\t\t\t\tpnct.nz = obj_part.vn[n_index].e[2]\n\t\t\t\t\t}\n\t\t\t\t\t// texture uv\n\t\t\t\t\tif t_index >= 0 {\n\t\t\t\t\t\tpnct.u = obj_part.vt[t_index].e[0]\n\t\t\t\t\t\tpnct.v = obj_part.vt[t_index].e[1]\n\t\t\t\t\t}\n\n\t\t\t\t\tout_buf.vbuf << pnct\n\t\t\t\t\tout_buf.ibuf << u32(v_count_index)\n\t\t\t\t\tv_count_index++\n\t\t\t\t} else {\n\t\t\t\t\t// println(\"Cache used! ${key}\")\n\t\t\t\t\tout_buf.ibuf << u32(cache[key])\n\t\t\t\t\tcache_hit++\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\tprintln(\"------------\")\n\tfor c1, x1 in out_buf.vbuf[..10] {\n\t\tprintln(\"${c1} ${x1}\")\n\t}\n\tprintln(out_buf.ibuf[..10])\n\t*/\n\t// println(\"vbuf size: ${out_buf.vbuf.len} ibuf size: ${out_buf.ibuf.len} Cache hit: ${cache_hit}\")\n\tout_buf.n_vertex = u32(out_buf.ibuf.len)\n\treturn out_buf\n}\n\n//==============================================================================\n// Utility\n//==============================================================================\n// print on the console the summary of the .obj model loaded\npub fn (obj_part ObjPart) summary() {\n\tprintln('---- Stats     ----')\n\tprintln('vertices: ${obj_part.v.len}')\n\tprintln('normals : ${obj_part.vn.len}')\n\tprintln('uv      : ${obj_part.vt.len}')\n\tprintln('parts   : ${obj_part.part.len}')\n\t// Parts\n\tprintln('---- Parts     ----')\n\tfor c, x in obj_part.part {\n\t\tprintln('${c:3} [${x.name:-16}] mat:[${x.material:-10}] ${x.faces.len:7} faces')\n\t}\n\t// Materials\n\tprintln('---- Materials ----')\n\tprintln('Material dict: ${obj_part.mat_map.keys()}')\n\tfor c, mat in obj_part.mat {\n\t\tprintln('${c:3} [${mat.name:-16}]')\n\t\tfor k, v in mat.ks {\n\t\t\tprint('${k} = ${v}')\n\t\t}\n\t\tfor k, v in mat.ns {\n\t\t\tprintln('${k} = ${v}')\n\t\t}\n\t\tfor k, v in mat.maps {\n\t\t\tprintln('${k} = ${v}')\n\t\t}\n\t}\n}\n\n// debug test function, do not remove.\npub fn tst() {\n\t/*\n\t//fname := \"capsule.obj\"\n\t//fname := \"Forklift.obj\"\n\tfname := \"cube.obj\"\n\t//fname := \"Orange Robot 3D ObjPart.obj\"\n\n\tmut obj := ObjPart{}\n\tbuf := os.read_lines(fname) or { panic(err.msg) }\n\tobj.parse_obj_buffer(buf)\n\tobj.summary()\n\t*/\n\t/*\n\ta :=\"f 7048 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7003\"\n\tmut f1 := 0\n\tmut f2 := 0\n\tf0,mut p := get_int(a,1)\n\tf1, p = get_int(a,p)\n\tf2, p = get_int(a,p)\n\tprintln(\"res: ${f0} ${f1} ${f2}\")\n\t*/\n\t/*\n\ta :=\"v -0 0.107769 -0.755914\"\n\tprintln(\"${parse_3f(a,1)}\")\n\t*/\n\t/*\n\tort := m4.ortho(0,300,0,200,0,0)\n\tprintln(ort)\n\ta := m4.vec3(0,0,0)\n\tprintln(\"a: ${a}\")\n\tres := m4.mul_vec(ort, a)\n\tprintln(\"res:\\n${res}\")\n\t*/\n\ts := 'K 1 1 1'\n\tr := strconv.atof_quick(s[1..s.len - 1])\n\tprintln(r)\n}\n"
  },
  {
    "path": "examples/sokol/06_obj_viewer/modules/obj/rend.v",
    "content": "/**********************************************************************\n*\n* .obj loader\n*\n* Copyright (c) 2021 Dario Deledda. All rights reserved.\n* Use of this source code is governed by an MIT license\n* that can be found in the LICENSE file.\n*\n* TODO:\n**********************************************************************/\nmodule obj\n\nimport sokol.gfx\nimport gg.m4\nimport math\nimport stbi\n\n/******************************************************************************\n* Texture functions\n******************************************************************************/\npub fn create_texture(w int, h int, buf &u8) (gfx.Image, gfx.Sampler) {\n\tsz := w * h * 4\n\tmut img_desc := gfx.ImageDesc{\n\t\twidth:       w\n\t\theight:      h\n\t\tnum_mipmaps: 0\n\t\t// min_filter: .linear\n\t\t// mag_filter: .linear\n\t\t// usage: .dynamic\n\t\t// wrap_u: .clamp_to_edge\n\t\t// wrap_v: .clamp_to_edge\n\t\tlabel:         &char(unsafe { nil })\n\t\td3d11_texture: 0\n\t}\n\t// comment if .dynamic is enabled\n\timg_desc.data.subimage[0][0] = gfx.Range{\n\t\tptr:  buf\n\t\tsize: usize(sz)\n\t}\n\n\tsg_img := gfx.make_image(&img_desc)\n\n\tmut smp_desc := gfx.SamplerDesc{\n\t\tmin_filter: .linear\n\t\tmag_filter: .linear\n\t\twrap_u:     .clamp_to_edge\n\t\twrap_v:     .clamp_to_edge\n\t}\n\n\tsg_smp := gfx.make_sampler(&smp_desc)\n\treturn sg_img, sg_smp\n}\n\npub fn destroy_texture(sg_img gfx.Image) {\n\tgfx.destroy_image(sg_img)\n}\n\npub fn load_texture(file_name string) (gfx.Image, gfx.Sampler) {\n\tbuffer := read_bytes_from_file(file_name)\n\tstbi.set_flip_vertically_on_load(true)\n\timg := stbi.load_from_memory(buffer.data, buffer.len) or {\n\t\teprintln('Texture file: [${file_name}] ERROR!')\n\t\texit(0)\n\t}\n\tsg_img, sg_smp := create_texture(int(img.width), int(img.height), img.data)\n\timg.free()\n\treturn sg_img, sg_smp\n}\n\n/******************************************************************************\n* Pipeline\n******************************************************************************/\npub fn (mut obj_part ObjPart) create_pipeline(in_part []int, shader gfx.Shader, texture gfx.Image, sampler gfx.Sampler) Render_data {\n\tmut res := Render_data{}\n\tobj_buf := obj_part.get_buffer(in_part)\n\tres.n_vert = obj_buf.n_vertex\n\tres.material = obj_part.part[in_part[0]].material\n\n\t// vertex buffer\n\tmut vert_buffer_desc := gfx.BufferDesc{}\n\tunsafe { vmemset(&vert_buffer_desc, 0, int(sizeof(vert_buffer_desc))) }\n\n\tvert_buffer_desc.size = usize(obj_buf.vbuf.len * int(sizeof(Vertex_pnct)))\n\tvert_buffer_desc.data = gfx.Range{\n\t\tptr:  obj_buf.vbuf.data\n\t\tsize: usize(obj_buf.vbuf.len * int(sizeof(Vertex_pnct)))\n\t}\n\n\tvert_buffer_desc.type = .vertexbuffer\n\tvert_buffer_desc.label = &char('vertbuf_part_${in_part:03}'.str)\n\tvbuf := gfx.make_buffer(&vert_buffer_desc)\n\n\t// index buffer\n\tmut index_buffer_desc := gfx.BufferDesc{}\n\tunsafe { vmemset(&index_buffer_desc, 0, int(sizeof(index_buffer_desc))) }\n\n\tindex_buffer_desc.size = usize(obj_buf.ibuf.len * int(sizeof(u32)))\n\tindex_buffer_desc.data = gfx.Range{\n\t\tptr:  obj_buf.ibuf.data\n\t\tsize: usize(obj_buf.ibuf.len * int(sizeof(u32)))\n\t}\n\n\tindex_buffer_desc.type = .indexbuffer\n\tindex_buffer_desc.label = &char('indbuf_part_${in_part:03}'.str)\n\tibuf := gfx.make_buffer(&index_buffer_desc)\n\n\tmut pipdesc := gfx.PipelineDesc{}\n\tunsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }\n\tpipdesc.layout.buffers[0].stride = int(sizeof(Vertex_pnct))\n\n\t// the constants [C.ATTR_vs_a_Position, C.ATTR_vs_a_Color, C.ATTR_vs_a_Texcoord0] are generated by sokol-shdc\n\tpipdesc.layout.attrs[C.ATTR_vs_a_Position].format = .float3 // x,y,z as f32\n\tpipdesc.layout.attrs[C.ATTR_vs_a_Normal].format = .float3 // x,y,z as f32\n\t// pipdesc.layout.attrs[C.ATTR_vs_a_Color].format = .ubyte4n // color as u32\n\tpipdesc.layout.attrs[C.ATTR_vs_a_Texcoord0].format = .float2 // u,v as f32\n\t// pipdesc.layout.attrs[C.ATTR_vs_a_Texcoord0].format  = .short2n  // u,v as u16\n\tpipdesc.index_type = .uint32\n\n\tcolor_state := gfx.ColorTargetState{\n\t\tblend: gfx.BlendState{\n\t\t\tenabled:        true\n\t\t\tsrc_factor_rgb: .src_alpha\n\t\t\tdst_factor_rgb: .one_minus_src_alpha\n\t\t}\n\t}\n\tpipdesc.colors[0] = color_state\n\n\tpipdesc.depth = gfx.DepthState{\n\t\twrite_enabled: true\n\t\tcompare:       .less_equal\n\t}\n\tpipdesc.cull_mode = .front\n\n\tpipdesc.label = &char('pip_part_${in_part:03}'.str)\n\n\t// shader\n\tpipdesc.shader = shader\n\n\tres.bind.vertex_buffers[0] = vbuf\n\tres.bind.index_buffer = ibuf\n\tres.bind.fs.images[C.SLOT_tex] = texture\n\tres.bind.fs.samplers[C.SLOT_smp] = sampler\n\tres.pipeline = gfx.make_pipeline(&pipdesc)\n\t// println('Buffers part [${in_part}] init done!')\n\n\treturn res\n}\n\n/******************************************************************************\n* Render functions\n******************************************************************************/\n// aggregate all the part by materials\npub fn (mut obj_part ObjPart) init_render_data(texture gfx.Image, sampler gfx.Sampler) {\n\t// create shader\n\t// One shader for all the model\n\tshader := gfx.make_shader(voidptr(C.gouraud_shader_desc(gfx.query_backend())))\n\n\tmut part_dict := map[string][]int{}\n\tfor i, p in obj_part.part {\n\t\tif p.faces.len > 0 {\n\t\t\tpart_dict[p.material] << i\n\t\t}\n\t}\n\tobj_part.rend_data.clear()\n\t// println(\"Material dict: ${obj_part.mat_map.keys()}\")\n\n\tfor k, v in part_dict {\n\t\t// println(\"${k} => Parts ${v}\")\n\n\t\tmut txt := texture\n\t\tmut smp := sampler\n\n\t\tif k in obj_part.mat_map {\n\t\t\tmat_map := obj_part.mat[obj_part.mat_map[k]]\n\t\t\tif 'map_Kd' in mat_map.maps {\n\t\t\t\tfile_name := mat_map.maps['map_Kd']\n\t\t\t\tif file_name in obj_part.texture {\n\t\t\t\t\ttxt = obj_part.texture[file_name]\n\t\t\t\t\t// println(\"Texture [${file_name}] => from CACHE\")\n\t\t\t\t} else {\n\t\t\t\t\ttxt, smp = load_texture(file_name)\n\t\t\t\t\tobj_part.texture[file_name] = txt\n\t\t\t\t\tobj_part.sampler[file_name] = smp\n\t\t\t\t\t// println(\"Texture [${file_name}] => LOADED\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// key := obj_part.texture.keys()[0]\n\t\t// obj_part.rend_data << obj_part.create_pipeline(v, shader, obj_part.texture[key])\n\t\tobj_part.rend_data << obj_part.create_pipeline(v, shader, txt, smp)\n\t}\n\t// println(\"Texture array len: ${obj_part.texture.len}\")\n\t// println(\"Calc bounding box.\")\n\tobj_part.calc_bbox()\n\tprintln('init_render_data DONE!')\n}\n\npub fn (obj_part ObjPart) bind_and_draw(rend_data_index int, in_data Shader_data) u32 {\n\t// apply the pipeline and bindings\n\tmut part_render_data := obj_part.rend_data[rend_data_index]\n\n\t// pass light position\n\tmut tmp_fs_params := Tmp_fs_param{}\n\ttmp_fs_params.light = in_data.fs_data.light\n\n\tif part_render_data.material in obj_part.mat_map {\n\t\tmat_index := obj_part.mat_map[part_render_data.material]\n\t\tmat := obj_part.mat[mat_index]\n\n\t\t// ambient\n\t\ttmp_fs_params.ka = in_data.fs_data.ka\n\t\tif 'Ka' in mat.ks {\n\t\t\ttmp_fs_params.ka = mat.ks['Ka']\n\t\t}\n\n\t\t// specular\n\t\ttmp_fs_params.ks = in_data.fs_data.ks\n\t\tif 'Ks' in mat.ks {\n\t\t\ttmp_fs_params.ks = mat.ks['Ks']\n\t\t}\n\n\t\t//  specular exponent Ns\n\t\tif 'Ns' in mat.ns {\n\t\t\ttmp_fs_params.ks.e[3] = mat.ns['Ns'] / 1000.0\n\t\t} else {\n\t\t\t// default value is 10\n\t\t\ttmp_fs_params.ks.e[3] = f32(10) / 1000.0\n\t\t}\n\n\t\t// diffuse\n\t\ttmp_fs_params.kd = in_data.fs_data.kd\n\t\tif 'Kd' in mat.ks {\n\t\t\ttmp_fs_params.kd = mat.ks['Kd']\n\t\t}\n\n\t\t// alpha/transparency\n\t\tif 'Tr' in mat.ns {\n\t\t\ttmp_fs_params.kd.e[3] = mat.ns['Tr']\n\t\t}\n\t}\n\n\tgfx.apply_pipeline(part_render_data.pipeline)\n\tgfx.apply_bindings(part_render_data.bind)\n\n\tvs_uniforms_range := gfx.Range{\n\t\tptr:  in_data.vs_data\n\t\tsize: usize(in_data.vs_len)\n\t}\n\tfs_uniforms_range := gfx.Range{\n\t\tptr:  unsafe { &tmp_fs_params }\n\t\tsize: usize(in_data.fs_len)\n\t}\n\n\tgfx.apply_uniforms(.vs, C.SLOT_vs_params, &vs_uniforms_range)\n\tgfx.apply_uniforms(.fs, C.SLOT_fs_params, &fs_uniforms_range)\n\tgfx.draw(0, int(part_render_data.n_vert), 1)\n\treturn part_render_data.n_vert\n}\n\npub fn (obj_part ObjPart) bind_and_draw_all(in_data Shader_data) u32 {\n\tmut n_vert := u32(0)\n\t// println(\"Parts: ${obj_part.rend_data.len}\")\n\tfor i, _ in obj_part.rend_data {\n\t\tn_vert += obj_part.bind_and_draw(i, in_data)\n\t}\n\treturn n_vert\n}\n\npub fn (mut obj_part ObjPart) calc_bbox() {\n\tobj_part.max = m4.Vec4{\n\t\te: [f32(-math.max_f32), -math.max_f32, -math.max_f32, 0]!\n\t}\n\tobj_part.min = m4.Vec4{\n\t\te: [f32(math.max_f32), math.max_f32, math.max_f32, 0]!\n\t}\n\tfor v in obj_part.v {\n\t\tif v.e[0] > obj_part.max.e[0] {\n\t\t\tobj_part.max.e[0] = v.e[0]\n\t\t}\n\t\tif v.e[1] > obj_part.max.e[1] {\n\t\t\tobj_part.max.e[1] = v.e[1]\n\t\t}\n\t\tif v.e[2] > obj_part.max.e[2] {\n\t\t\tobj_part.max.e[2] = v.e[2]\n\t\t}\n\n\t\tif v.e[0] < obj_part.min.e[0] {\n\t\t\tobj_part.min.e[0] = v.e[0]\n\t\t}\n\t\tif v.e[1] < obj_part.min.e[1] {\n\t\t\tobj_part.min.e[1] = v.e[1]\n\t\t}\n\t\tif v.e[2] < obj_part.min.e[2] {\n\t\t\tobj_part.min.e[2] = v.e[2]\n\t\t}\n\t}\n\tval1 := obj_part.max.mod3()\n\tval2 := obj_part.min.mod3()\n\tif val1 > val2 {\n\t\tobj_part.radius = f32(val1)\n\t} else {\n\t\tobj_part.radius = f32(val2)\n\t}\n\t// println(\"BBox: ${obj_part.min} <=> ${obj_part.max}\\nRadius: ${obj_part.radius}\")\n}\n"
  },
  {
    "path": "examples/sokol/06_obj_viewer/modules/obj/struct.v",
    "content": "/**********************************************************************\n*\n* .obj loader\n*\n* Copyright (c) 2021 Dario Deledda. All rights reserved.\n* Use of this source code is governed by an MIT license\n* that can be found in the LICENSE file.\n*\n* TODO:\n**********************************************************************/\nmodule obj\n\nimport gg.m4\nimport sokol.gfx\n\n// part struct maintaining the face indices\npub struct Part {\npub mut:\n\tfaces    [][][3]int // v n t index order, if -1 not available\n\tname     string\n\tmaterial string\n}\n\n// material struct, all Ks and Ns are stored as maps of string\npub struct Material {\npub mut:\n\tname string\n\tks   map[string]m4.Vec4\n\tns   map[string]f32\n\tmaps map[string]string\n}\n\n// render data used for the rendering\npub struct Render_data {\npub mut:\n\tpipeline gfx.Pipeline\n\tbind     gfx.Bindings\n\tn_vert   u32\n\tmaterial string\n}\n\n// base object parts struct\npub struct ObjPart {\npub mut:\n\tv  []m4.Vec4 // position\n\tvn []m4.Vec4 // normals\n\tvp []m4.Vec4 // vertex params\n\tvt []m4.Vec4 // textures\n\n\tname          string\n\tpart          []Part                 // parts of the ObjPart\n\tmat           []Material             // list of the materials of the ObjPart\n\tmat_map       map[string]int         // mapping material name to its material index\n\ttexture       map[string]gfx.Image   // GPU loaded texture map\n\tsampler       map[string]gfx.Sampler // GPU loaded sampler\n\tmaterial_file string                 // .mtl file name for the .obj\n\n\trend_data []Render_data // render data used for the rendering\n\n\tt_m m4.Mat4 = m4.unit_m4() // transform matrix for this ObjPart\n\t// child []ObjPart\n\t// stats\n\tmin    m4.Vec4 // min 3d position in the ObjPart\n\tmax    m4.Vec4 // max 3d position in the ObjPart\n\tradius f32     // bounding circle radius of the ObjPart\n}\n\n// used in to pass the matrices to the shader\npub struct Mats {\npub mut:\n\tmv  m4.Mat4\n\tmvp m4.Mat4\n\tnm  m4.Mat4\n}\n\n// data passed to the vertex shader\npub struct Tmp_vs_param {\npub mut:\n\tmv  m4.Mat4\n\tmvp m4.Mat4\n\tnm  m4.Mat4\n}\n\n// data passed to the pixel shader\npub struct Tmp_fs_param {\npub mut:\n\tlight m4.Vec4\n\tka    m4.Vec4 = m4.Vec4{\n\t\te: [f32(0.1), 0.0, 0.0, 1.0]!\n\t}\n\tkd    m4.Vec4 = m4.Vec4{\n\t\te: [f32(0.5), 0.5, 0.5, 1.0]!\n\t}\n\tks    m4.Vec4 = m4.Vec4{\n\t\te: [f32(1.0), 1.0, 1.0, 1.0]!\n\t}\n}\n\n// shader data for the rendering\npub struct Shader_data {\npub mut:\n\tvs_data &Tmp_vs_param = unsafe { nil }\n\tvs_len  int\n\tfs_data &Tmp_fs_param = unsafe { nil }\n\tfs_len  int\n}\n"
  },
  {
    "path": "examples/sokol/06_obj_viewer/modules/obj/util.v",
    "content": "module obj\n\nimport os\nimport os.asset\n\n// read a file as single lines\npub fn read_lines_from_file(file_path string) []string {\n\tif os.exists(file_path) {\n\t\treturn os.read_lines(file_path) or { [] }\n\t}\n\treturn read_bytes_from_file(file_path).bytestr().split_into_lines()\n}\n\n// read a file as []u8\npub fn read_bytes_from_file(file_path string) []u8 {\n\tif os.exists(file_path) {\n\t\treturn os.read_bytes(file_path) or { [] }\n\t}\n\tmpath := 'models/${file_path}'\n\treturn asset.read_bytes('assets', mpath) or {\n\t\teprintln('Model file NOT FOUND: `${mpath}`')\n\t\texit(0)\n\t}\n}\n"
  },
  {
    "path": "examples/sokol/06_obj_viewer/show_obj.v",
    "content": "// vtest build: misc-tooling // needs .h files that are produced by `v shader`\n/**********************************************************************\n*\n* .obj viewer\n*\n* Copyright (c) 2021 Dario Deledda. All rights reserved.\n* Use of this source code is governed by an MIT license\n* that can be found in the LICENSE file.\n*\n* Example .obj model of V from SurmanPP\n*\n* HOW TO COMPILE SHADERS:\n* Run `v shader .` in this directory to compile the shaders.\n* For more info and help with shader compilation see `docs.md` and `v help shader`.\n*\n* ALTERNATIVE .OBJ MODELS:\n* you can load alternative models putting them in the \"assets/model\" folder with or without their .mtl file.\n* use the program help for further instructions.\n*\n* TODO:\n* - frame counter\n**********************************************************************/\nimport gg\nimport gg.m4\nimport math\nimport sokol.sapp\nimport sokol.gfx\nimport sokol.sgl\nimport time\nimport os\nimport obj\n\n// GLSL Include and functions\n\n#include \"@VMODROOT/gouraud.h\" # It should be generated with `v shader .` (see the instructions at the top of this file)\n\nfn C.gouraud_shader_desc(gfx.Backend) &gfx.ShaderDesc\n\nconst win_width = 600\nconst win_height = 600\nconst bg_color = gg.white\n\nstruct App {\nmut:\n\tgg          &gg.Context = unsafe { nil }\n\ttexture     gfx.Image\n\tsampler     gfx.Sampler\n\tinit_flag   bool\n\tframe_count int\n\n\tmouse_x  int = -1\n\tmouse_y  int = -1\n\tscroll_y int // mouse wheel value\n\t// time\n\tticks i64\n\t// model\n\tobj_part &obj.ObjPart = unsafe { nil }\n\tn_vertex u32\n\t// init parameters\n\tfile_name            string\n\tsingle_material_flag bool\n}\n\n/******************************************************************************\n* Draw functions\n******************************************************************************/\n@[inline]\nfn vec4(x f32, y f32, z f32, w f32) m4.Vec4 {\n\treturn m4.Vec4{\n\t\te: [x, y, z, w]!\n\t}\n}\n\nfn calc_matrices(w f32, h f32, rx f32, ry f32, in_scale f32, pos m4.Vec4) obj.Mats {\n\tproj := m4.perspective(60, w / h, 0.01, 100.0) // set far plane to 100 fro the zoom function\n\tview := m4.look_at(vec4(f32(0.0), 0, 6, 0), vec4(f32(0), 0, 0, 0), vec4(f32(0), 1,\n\t\t0, 0))\n\tview_proj := view * proj\n\n\trxm := m4.rotate(m4.rad(rx), vec4(f32(1), 0, 0, 0))\n\trym := m4.rotate(m4.rad(ry), vec4(f32(0), 1, 0, 0))\n\n\tmodel_pos := m4.unit_m4().translate(pos)\n\n\tmodel_m := (rym * rxm) * model_pos\n\tscale_m := m4.scale(vec4(in_scale, in_scale, in_scale, 1))\n\n\tmv := scale_m * model_m // model view\n\tnm := mv.inverse().transpose() // normal matrix\n\tmvp := mv * view_proj // model view projection\n\n\treturn obj.Mats{\n\t\tmv:  mv\n\t\tmvp: mvp\n\t\tnm:  nm\n\t}\n}\n\nfn draw_model(app App, model_pos m4.Vec4) u32 {\n\tif app.init_flag == false {\n\t\treturn 0\n\t}\n\n\tws := gg.window_size_real_pixels()\n\tdw := ws.width / 2\n\tdh := ws.height / 2\n\n\tmut scale := f32(1)\n\tif app.obj_part.radius > 1 {\n\t\tscale = 1 / (app.obj_part.radius)\n\t} else {\n\t\tscale = app.obj_part.radius\n\t}\n\tscale *= 3\n\n\t// *** vertex shader uniforms ***\n\trot := [f32(app.mouse_y), f32(app.mouse_x)]\n\tmut zoom_scale := scale + f32(app.scroll_y) / (app.obj_part.radius * 4)\n\tmats := calc_matrices(dw, dh, rot[0], rot[1], zoom_scale, model_pos)\n\n\tmut tmp_vs_param := obj.Tmp_vs_param{\n\t\tmv:  mats.mv\n\t\tmvp: mats.mvp\n\t\tnm:  mats.nm\n\t}\n\n\t// *** fragment shader uniforms ***\n\ttime_ticks := f32(time.ticks() - app.ticks) / 1000\n\tradius_light := f32(app.obj_part.radius)\n\tx_light := f32(math.cos(time_ticks) * radius_light)\n\tz_light := f32(math.sin(time_ticks) * radius_light)\n\n\tmut tmp_fs_params := obj.Tmp_fs_param{}\n\ttmp_fs_params.light = m4.vec3(x_light, radius_light, z_light)\n\n\tsd := obj.Shader_data{\n\t\tvs_data: unsafe { &tmp_vs_param }\n\t\tvs_len:  int(sizeof(tmp_vs_param))\n\t\tfs_data: unsafe { &tmp_fs_params }\n\t\tfs_len:  int(sizeof(tmp_fs_params))\n\t}\n\n\treturn app.obj_part.bind_and_draw_all(sd)\n}\n\nfn frame(mut app App) {\n\t// clear\n\tmut color_action := gfx.ColorAttachmentAction{\n\t\tload_action: .clear\n\t\tclear_value: gfx.Color{\n\t\t\tr: 0.0\n\t\t\tg: 0.0\n\t\t\tb: 0.0\n\t\t\ta: 1.0\n\t\t}\n\t}\n\n\tmut pass_action := gfx.PassAction{}\n\tpass_action.colors[0] = color_action\n\tpass := sapp.create_default_pass(pass_action)\n\tgfx.begin_pass(&pass)\n\n\t// render the data\n\tdraw_start_glsl(app)\n\tdraw_model(app, m4.Vec4{})\n\t// uncomment if you want a raw benchmark mode\n\t/*\n\tmut n_vertex_drawn := u32(0)\n\tn_x_obj := 20\n\n\tfor x in 0..n_x_obj {\n\t\tfor z in 0..30 {\n\t\t\tfor y in 0..4 {\n\t\t\t\tn_vertex_drawn += draw_model(app, m4.Vec4{e:[f32((x-(n_x_obj>>1))*3),-3 + y*3,f32(-6*z),1]!})\n\t\t\t}\n\t\t}\n\t}\n\t*/\n\tdraw_end_glsl(app)\n\n\t// println(\"v:${n_vertex_drawn}\")\n\tapp.frame_count++\n}\n\nfn draw_start_glsl(app App) {\n\tif app.init_flag == false {\n\t\treturn\n\t}\n\tws := gg.window_size_real_pixels()\n\tgfx.apply_viewport(0, 0, ws.width, ws.height, true)\n}\n\nfn draw_end_glsl(app App) {\n\tgfx.end_pass()\n\tgfx.commit()\n}\n\n/******************************************************************************\n* Init / Cleanup\n******************************************************************************/\nfn my_init(mut app App) {\n\tmut object := &obj.ObjPart{}\n\tobj_file_lines := obj.read_lines_from_file(app.file_name)\n\tobject.parse_obj_buffer(obj_file_lines, app.single_material_flag)\n\tobject.summary()\n\tapp.obj_part = object\n\n\t// set max vertices,\n\t// for a large number of the same type of object it is better use the instances!!\n\tdesc := sapp.create_desc()\n\tgfx.setup(&desc)\n\tsgl_desc := sgl.Desc{\n\t\tmax_vertices: 128 * 65536\n\t}\n\tsgl.setup(&sgl_desc)\n\n\t// 1x1 pixel white, default texture\n\tunsafe {\n\t\ttmp_txt := malloc(4)\n\t\ttmp_txt[0] = u8(0xFF)\n\t\ttmp_txt[1] = u8(0xFF)\n\t\ttmp_txt[2] = u8(0xFF)\n\t\ttmp_txt[3] = u8(0xFF)\n\t\tapp.texture, app.sampler = obj.create_texture(1, 1, tmp_txt)\n\t\tfree(tmp_txt)\n\t}\n\t// glsl\n\tapp.obj_part.init_render_data(app.texture, app.sampler)\n\tapp.init_flag = true\n}\n\nfn cleanup(mut app App) {\n\t/*\n\tfor _, mat in app.obj_part.texture {\n\t\tobj.destroy_texture(mat)\n\t}\n\t*/\n}\n\n/******************************************************************************\n* events handling\n******************************************************************************/\nfn my_event_manager(mut ev gg.Event, mut app App) {\n\tif ev.typ == .mouse_move {\n\t\tapp.mouse_x = int(ev.mouse_x)\n\t\tapp.mouse_y = int(ev.mouse_y)\n\t}\n\n\tif ev.scroll_y != 0 {\n\t\tapp.scroll_y += int(ev.scroll_y)\n\t}\n\n\tif ev.typ == .touches_began || ev.typ == .touches_moved {\n\t\tif ev.num_touches > 0 {\n\t\t\ttouch_point := ev.touches[0]\n\t\t\tapp.mouse_x = int(touch_point.pos_x)\n\t\t\tapp.mouse_y = int(touch_point.pos_y)\n\t\t}\n\t}\n}\n\nfn main() {\n\t/*\n\tobj.tst()\n\texit(0)\n\t*/\n\t// App init\n\tmut app := &App{}\n\n\t// app.file_name = 'v.obj' // default object is the v logo\n\tapp.file_name = 'utahTeapot.obj' // default object is the v logo\n\n\tapp.single_material_flag = false\n\t$if !android {\n\t\tif os.args.len > 3 || (os.args.len >= 2 && os.args[1] in ['-h', '--help', '\\\\?', '-?']) {\n\t\t\teprintln('Usage:\\nshow_obj [file_name:string] [single_material_flag:(true|false)]\\n')\n\t\t\teprintln('file_name           : name of the .obj file.')\n\t\t\teprintln('                      If no file name is passed the default V logo will be showed.')\n\t\t\teprintln('                      Try one of the .obj files in the \"assets/models/\" folder.')\n\t\t\teprintln(\"single_material_flag: if true the viewer use for all the model's parts the default material\")\n\t\t\texit(0)\n\t\t}\n\n\t\tif os.args.len >= 2 {\n\t\t\tapp.file_name = os.args[1]\n\t\t}\n\t\tif os.args.len >= 3 {\n\t\t\tapp.single_material_flag = os.args[2].bool()\n\t\t}\n\t\tprintln('Loading model: ${app.file_name}')\n\t\tprintln('Using single material: ${app.single_material_flag}')\n\t}\n\n\tapp.gg = gg.new_context(\n\t\twidth:         win_width\n\t\theight:        win_height\n\t\tcreate_window: true\n\t\twindow_title:  'V Wavefront OBJ viewer - Use the mouse wheel to zoom'\n\t\tuser_data:     app\n\t\tbg_color:      bg_color\n\t\tframe_fn:      frame\n\t\tinit_fn:       my_init\n\t\tcleanup_fn:    cleanup\n\t\tevent_fn:      my_event_manager\n\t)\n\n\tapp.ticks = time.ticks()\n\tapp.gg.run()\n}\n"
  },
  {
    "path": "examples/sokol/06_obj_viewer/v.mod",
    "content": ""
  },
  {
    "path": "examples/sokol/07_simple_shader_glsl/.gitignore",
    "content": "simple_shader.h\n"
  },
  {
    "path": "examples/sokol/07_simple_shader_glsl/simple_shader.glsl",
    "content": "// The following defines a vertex shader main function\n@vs vs\nin vec4 position;\nin vec4 color0;\n\nout vec4 color;\n\n// You can add more functions here\n\nvoid main() {\n    gl_Position = position;\n    color = color0;\n}\n@end\n\n// The following defines a fragment shader main function\n@fs fs\nin vec4 color;\nout vec4 frag_color;\n\n// You can add more functions here\n\nvoid main() {\n    frag_color = color;\n}\n@end\n\n// The value after `@program` and before `vs fs` decide a part of the name\n// of the C function you need to define in V. The value entered is suffixed `_shader_desc`\n// in the generated C code. Thus the name for this becomes: `simple_shader_desc`.\n// In V it's signature then need to be defined as:\n// `fn C.simple_shader_desc(gfx.Backend) &gfx.ShaderDesc`. See `simple_shader.v` for the define.\n//\n// Running `v shader -v .` in this dir will also show you brief information\n// about how to use the compiled shader.\n@program simple vs fs\n"
  },
  {
    "path": "examples/sokol/07_simple_shader_glsl/simple_shader.v",
    "content": "// Copyright(C) 2022 Lars Pontoppidan. All rights reserved.\n// Use of this source code is governed by an MIT license file distributed with this software package\n// vtest build: misc-tooling // needs .h files that are produced by `v shader`\nmodule main\n\n// Example shader triangle adapted to V from https://github.com/floooh/sokol-samples/blob/1f2ad36/sapp/triangle-sapp.c\nimport sokol.sapp\nimport sokol.gfx\n\n// Use `v shader` or `sokol-shdc` to generate the necessary `.h` file\n// Using `v shader -v .` in this directory will show some additional\n// info - and what you should include to make things work.\n#include \"@VMODROOT/simple_shader.h\" # # It should be generated with `v shader .`\n\n// simple_shader_desc is a C function declaration defined by\n// the `@program` entry in the `simple_shader.glsl` shader file.\n// When the shader is compiled this function name is generated\n// by the shader compiler for easier inclusion of universal shader code\n// in C (and V) code.\nfn C.simple_shader_desc(gfx.Backend) &gfx.ShaderDesc\n\n// Vertex_t makes it possible to model vertex buffer data\n// for use with the shader system\nstruct Vertex_t {\n\t// Position\n\tx f32\n\ty f32\n\tz f32\n\t// Color\n\tr f32\n\tg f32\n\tb f32\n\ta f32\n}\n\nfn main() {\n\tmut app := &App{\n\t\twidth:       800\n\t\theight:      400\n\t\tpass_action: gfx.create_clear_pass_action(0.0, 0.0, 0.0, 1.0) // This will create a black color as a default pass (window background color)\n\t}\n\tapp.run()\n}\n\nstruct App {\n\tpass_action gfx.PassAction\nmut:\n\twidth           int\n\theight          int\n\tshader_pipeline gfx.Pipeline\n\tbind            gfx.Bindings\n}\n\nfn (mut a App) run() {\n\ttitle := 'V Simple Shader Example'\n\tdesc := sapp.Desc{\n\t\twidth:               a.width\n\t\theight:              a.height\n\t\tuser_data:           a\n\t\tinit_userdata_cb:    init\n\t\tframe_userdata_cb:   frame\n\t\twindow_title:        &char(title.str)\n\t\tcleanup_userdata_cb: cleanup\n\t\tsample_count:        4 // Enables MSAA (Multisample anti-aliasing) x4 on rendered output, this can be omitted.\n\t}\n\tsapp.run(&desc)\n}\n\nfn init(user_data voidptr) {\n\tmut app := unsafe { &App(user_data) }\n\tmut desc := sapp.create_desc()\n\n\tgfx.setup(&desc)\n\n\t// `vertices` defines a vertex buffer with 3 vertices\n\t// with 3 position fields XYZ and 4 color components RGBA -\n\t// for drawing a multi-colored triangle.\n\t//\n\t// C code:\n\t// float vertices[] = {\n\t//    // Positions     // Colors\n\t//    0.0,  0.5, 0.5,     1.0, 0.0, 0.0, 1.0,\n\t//    0.5, -0.5, 0.5,     0.0, 1.0, 0.0, 1.0,\n\t//   -0.5, -0.5, 0.5,     0.0, 0.0, 1.0, 1.0\n\t// };\n\t//\n\t// Array entries in the following V code is the equivalent\n\t// of the C code entry described above:\n\tvertices := [\n\t\tVertex_t{0.0, 0.5, 0.5, 1.0, 0.0, 0.0, 1.0},\n\t\tVertex_t{0.5, -0.5, 0.5, 0.0, 1.0, 0.0, 1.0},\n\t\tVertex_t{-0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0},\n\t]\n\n\t// Create a vertex buffer with the 3 vertices defined above.\n\tmut vertex_buffer_desc := gfx.BufferDesc{\n\t\tlabel: c'triangle-vertices'\n\t}\n\tunsafe { vmemset(&vertex_buffer_desc, 0, int(sizeof(vertex_buffer_desc))) }\n\n\tvertex_buffer_desc.size = usize(vertices.len * int(sizeof(Vertex_t)))\n\tvertex_buffer_desc.data = gfx.Range{\n\t\tptr:  vertices.data\n\t\tsize: vertex_buffer_desc.size\n\t}\n\n\tapp.bind.vertex_buffers[0] = gfx.make_buffer(&vertex_buffer_desc)\n\n\t// Create shader from the code-generated sg_shader_desc (gfx.ShaderDesc in V).\n\t// Note the function `C.simple_shader_desc()` (also defined above) - this is\n\t// the function that returns the compiled shader code/desciption we have\n\t// written in `simple_shader.glsl` and compiled with `v shader .` (`sokol-shdc`).\n\tshader := gfx.make_shader(voidptr(C.simple_shader_desc(gfx.query_backend())))\n\n\t// Create a pipeline object (default render states are fine for triangle)\n\tmut pipeline_desc := gfx.PipelineDesc{}\n\t// This will zero the memory used to store the pipeline in.\n\tunsafe { vmemset(&pipeline_desc, 0, int(sizeof(pipeline_desc))) }\n\n\t// Populate the essential struct fields\n\tpipeline_desc.shader = shader\n\t// The vertex shader (`simple_shader.glsl`) takes 2 inputs:\n\t// ```glsl\n\t// in vec4 position;\n\t// in vec4 color0;\n\t// ```\n\t// Also note the naming of the C.ATTR_* used as indices.\n\t// They are the prefixed versions of the names of the input variables in the shader code.\n\t// If they change in the shader code they will also change here.\n\tpipeline_desc.layout.attrs[C.ATTR_vs_position].format = .float3 // x,y,z as f32\n\tpipeline_desc.layout.attrs[C.ATTR_vs_color0].format = .float4 // r, g, b, a as f32\n\t// The .label is optional but can aid debugging sokol shader related issues\n\t// When things get complex - and you get tired :)\n\tpipeline_desc.label = c'triangle-pipeline'\n\n\tapp.shader_pipeline = gfx.make_pipeline(&pipeline_desc)\n}\n\nfn cleanup(user_data voidptr) {\n\tgfx.shutdown()\n}\n\nfn frame(user_data voidptr) {\n\tmut app := unsafe { &App(user_data) }\n\n\tpass := sapp.create_default_pass(app.pass_action)\n\tgfx.begin_pass(&pass)\n\n\tgfx.apply_pipeline(app.shader_pipeline)\n\tgfx.apply_bindings(&app.bind)\n\n\tgfx.draw(0, 3, 1)\n\n\tgfx.end_pass()\n\tgfx.commit()\n}\n"
  },
  {
    "path": "examples/sokol/07_simple_shader_glsl/v.mod",
    "content": ""
  },
  {
    "path": "examples/sokol/08_sdf/.gitignore",
    "content": "sdf-sapp.c\nsdf.h\n"
  },
  {
    "path": "examples/sokol/08_sdf/sdf.glsl",
    "content": "//------------------------------------------------------------------------------\n//  Signed-distance-field raymarching shaders, see:\n//  https://iquilezles.org/articles/mandelbulb\n//  https://www.shadertoy.com/view/ltfSWn\n//------------------------------------------------------------------------------\n\n//--- vertex shader\n@vs vs\nuniform vs_params {\n    float aspect;\n    float time;\n};\nin vec4 position;\n\nout vec2 pos;\nout vec3 eye;\nout vec3 up;\nout vec3 right;\nout vec3 fwd;\n\n// compute eye position (orbit around center)\nvec3 eye_pos(float time, vec3 center) {\n    return center + vec3(sin(time * 0.05) * 3.0, sin(time * 0.1) * 2.0, cos(time * 0.05) * 3.0);\n}\n\n// a lookat function\nvoid lookat(vec3 eye, vec3 center, vec3 up, out vec3 out_fwd, out vec3 out_right, out vec3 out_up) {\n    out_fwd = normalize(center - eye);\n    out_right = normalize(cross(out_fwd, up));\n    out_up = cross(out_right, out_fwd);\n}\n\nvoid main() {\n    gl_Position = position;\n    pos.x = position.x * aspect;\n    pos.y = position.y;\n    const vec3 center = vec3(0.0, 0.0, 0.0);\n    const vec3 up_vec = vec3(0.0, 1.0, 0.0);\n    eye = eye_pos(time * 5, center);\n    lookat(eye, center, up_vec, fwd, right, up);\n}\n@end\n\n//--- fragment shader\n@fs fs\nin vec2 pos;\nin vec3 eye;\nin vec3 up;\nin vec3 right;\nin vec3 fwd;\n\nout vec4 frag_color;\n\nfloat sd_sphere(vec3 p, float s) {\n    return length(p) - s;\n}\n\nfloat sd_mandelbulb(vec3 p, out vec4 res_color) {\n    vec3 w = p;\n    float m = dot(w,w);\n\n    vec4 trap = vec4(abs(w),m);\n    float dz = 1.0;\n\n    for( int i=0; i<4; i++ ) {\n        float m2 = m*m;\n        float m4 = m2*m2;\n        dz = 8.0*sqrt(m4*m2*m)*dz + 1.0;\n\n        float x = w.x; float x2 = x*x; float x4 = x2*x2;\n        float y = w.y; float y2 = y*y; float y4 = y2*y2;\n        float z = w.z; float z2 = z*z; float z4 = z2*z2;\n\n        float k3 = x2 + z2;\n        float k2 = inversesqrt( k3*k3*k3*k3*k3*k3*k3 );\n        float k1 = x4 + y4 + z4 - 6.0*y2*z2 - 6.0*x2*y2 + 2.0*z2*x2;\n        float k4 = x2 - y2 + z2;\n\n        w.x = p.x +  64.0*x*y*z*(x2-z2)*k4*(x4-6.0*x2*z2+z4)*k1*k2;\n        w.y = p.y + -16.0*y2*k3*k4*k4 + k1*k1;\n        w.z = p.z +  -8.0*y*k4*(x4*x4 - 28.0*x4*x2*z2 + 70.0*x4*z4 - 28.0*x2*z2*z4 + z4*z4)*k1*k2;\n\n        trap = min( trap, vec4(abs(w),m) );\n\n        m = dot(w,w);\n        if( m > 256.0 ) {\n            break;\n        }\n    }\n    res_color = vec4(m,trap.yzw);\n    return 0.25*log(m)*sqrt(m)/dz;\n}\n\nfloat d_scene(vec3 p, out vec4 res_color) {\n    float d = sd_sphere(p, 1.1);\n    if (d < 0.1) {\n        d = sd_mandelbulb(p, res_color);\n    }\n    else {\n        res_color = vec4(0.0);\n    }\n    return d;\n}\n\n// surface normal estimation\nvec3 surface_normal(vec3 p, float dp) {\n    const float eps = 0.001;\n    const vec2 d = vec2(eps, 0);\n    vec4 tra;\n    float x = d_scene(p + d.xyy, tra) - dp;\n    float y = d_scene(p + d.yxy, tra) - dp;\n    float z = d_scene(p + d.yyx, tra) - dp;\n    return normalize(vec3(x, y, z));\n}\n\nvec3 calc_color(vec3 ro, vec3 rd, float t, vec4 tra) {\n    const vec3 light1 = vec3( 0.577, 0.577, -0.577);\n    const vec3 light2 = vec3(-0.707, 0.000,  0.707);\n\n    vec3 pos = ro + rd * t;\n    vec3 nrm = surface_normal(pos, t);\n    vec3 hal = normalize(light1 - rd);\n    float occ = clamp(0.05 * log(tra.x), 0.0, 1.0);\n    float fac = clamp(1.0 + dot(rd, nrm), 0.0, 1.0);\n\n    // sun\n    float dif1 = clamp(dot( light1, nrm), 0.0, 1.0);\n    float spe1 = pow(clamp(dot(nrm, hal), 0.0, 1.0), 32.0 )*dif1*(0.04+0.96*pow(clamp(1.0-dot(hal,light1),0.0,1.0),5.0));\n    // bounce\n    float dif2 = clamp( 0.5 + 0.5*dot( light2, nrm ), 0.0, 1.0 )*occ;\n    // sky\n    float dif3 = (0.7+0.3*nrm.y)*(0.2+0.8*occ);\n\n    vec3 col = vec3(0.01);\n    col = mix(col, vec3(0.10,0.20,0.30), clamp(tra.y,0.0,1.0) );\n    col = mix(col, vec3(0.02,0.10,0.30), clamp(tra.z*tra.z,0.0,1.0) );\n    col = mix(col, vec3(0.30,0.10,0.02), clamp(pow(tra.w,6.0),0.0,1.0) );\n\n    vec3 lin = vec3(0.0);\n         lin += 7.0*vec3(1.50,1.10,0.70)*dif1;\n         lin += 4.0*vec3(0.25,0.20,0.15)*dif2;\n         lin += 1.5*vec3(0.10,0.20,0.30)*dif3;\n         lin += 2.5*vec3(0.35,0.30,0.25)*(0.05+0.95*occ); // ambient\n         lin += 4.0*fac*occ; // fake SSS\n    col *= lin;\n    col = pow( col, vec3(0.7,0.9,1.0)); // fake SSS\n    col += spe1*15.0;\n\n    // gamma\n    col = sqrt(col);\n\n    return col;\n}\n\nvoid main() {\n    const float epsilon = 0.001;\n    const float focal_length = 1.8;\n\n    vec3 ray_origin = eye + fwd * focal_length + right * pos.x + up * pos.y;\n    vec3 ray_direction = normalize(ray_origin - eye);\n\n    vec4 tra;\n    vec4 color = vec4(0.10,0.20,0.30,1.0);\n    float t = 0.0;\n    for (int i = 0; i < 96; i++) {\n        vec3 p = ray_origin + ray_direction * t;\n        float d = d_scene(p, tra);\n        if (d < epsilon) {\n            color.xyz = calc_color(p, ray_direction, d, tra);\n            break;\n        }\n        else {\n            color.xyz += vec3(0.003, 0.001, 0.0) * i;\n        }\n        if (t > 3) {\n            break;\n        }\n        t += d;\n    }\n    frag_color = color;\n}\n@end\n\n@program sdf vs fs\n"
  },
  {
    "path": "examples/sokol/08_sdf/sdf.v",
    "content": "// A Signed Distance Field rendering demo, ported from https://github.com/floooh/sokol-samples/blob/master/sapp/sdf-sapp.c\n// which in turn is based on https://iquilezles.org/articles/mandelbulb/ and https://www.shadertoy.com/view/ltfSWn\n// vtest build: misc-tooling // needs .h files that are produced by `v shader`\nimport sokol.sapp\nimport sokol.gfx\n\n#include \"@VMODROOT/sdf.h\" # It should be generated with `v shader .`\n\nfn C.sdf_shader_desc(gfx.Backend) &gfx.ShaderDesc\n\n@[packed]\nstruct C.vs_params_t {\nmut:\n\taspect f32\n\ttime   f32\n}\n\nstruct State {\nmut:\n\tpip     gfx.Pipeline\n\tbind    gfx.Bindings\n\tpaction gfx.PassAction\n\tparams  C.vs_params_t\n}\n\nfn init(mut state State) {\n\tgfx.setup(sapp.create_desc())\n\n\tfsq_verts := [f32(-1.0), -3.0, 3.0, 1.0, -1.0, 1.0]!\n\tstate.bind.vertex_buffers[0] = gfx.make_buffer(gfx.BufferDesc{\n\t\tlabel: c'fsq vertices'\n\t\tdata:  gfx.Range{&fsq_verts[0], sizeof(fsq_verts)}\n\t})\n\n\tmut pipeline := gfx.PipelineDesc{}\n\tpipeline.layout.attrs[C.ATTR_vs_position].format = .float2\n\tpipeline.shader = gfx.make_shader(voidptr(C.sdf_shader_desc(gfx.query_backend())))\n\tstate.pip = gfx.make_pipeline(&pipeline)\n\n\t// No need to clear the window, since the shader will overwrite the whole framebuffer\n\tstate.paction.colors[0].load_action = .dontcare\n}\n\nfn frame(mut state State) {\n\tw, h := sapp.width(), sapp.height()\n\tstate.params.time += f32(sapp.frame_duration())\n\tstate.params.aspect = f32(w) / f32(h)\n\tgfx.begin_pass(sapp.create_default_pass(state.paction))\n\tgfx.apply_pipeline(state.pip)\n\tgfx.apply_bindings(state.bind)\n\tgfx.apply_uniforms(.vs, C.SLOT_vs_params, gfx.Range{&state.params, sizeof(state.params)})\n\tgfx.draw(0, 3, 1)\n\tgfx.end_pass()\n\tgfx.commit()\n}\n\nfn main() {\n\tsapp.run(sapp.Desc{\n\t\twindow_title:      c'SDF Rendering'\n\t\twidth:             512\n\t\theight:            512\n\t\tframe_userdata_cb: frame\n\t\tinit_userdata_cb:  init\n\t\tcleanup_cb:        gfx.shutdown\n\t\ticon:              sapp.IconDesc{\n\t\t\tsokol_default: true\n\t\t}\n\t\tuser_data:         &State{}\n\t})\n}\n"
  },
  {
    "path": "examples/sokol/08_sdf/v.mod",
    "content": ""
  },
  {
    "path": "examples/sokol/clear.v",
    "content": "// This example shows how to clear your window on each frame, with a different color, using a Sokol pass.\n// It is ported from https://github.com/floooh/sokol-samples/blob/master/sapp/clear-sapp.c .\nimport sokol.gfx\nimport sokol.sapp\n\nfn frame(mut action gfx.PassAction) {\n\tg := f32(action.colors[0].clear_value.g + 0.01)\n\taction.colors[0].clear_value.g = if g > 1.0 { 0 } else { g }\n\tgfx.begin_pass(sapp.create_default_pass(action))\n\tgfx.end_pass()\n\tgfx.commit()\n}\n\nfn main() {\n\taction := gfx.create_clear_pass_action(1.0, 0, 0, 1.0)\n\tsapp.run(\n\t\twindow_title:      c'Clear (sokol app)'\n\t\twidth:             400\n\t\theight:            300\n\t\tinit_cb:           || gfx.setup(sapp.create_desc())\n\t\tcleanup_cb:        || gfx.shutdown()\n\t\tframe_userdata_cb: frame\n\t\tuser_data:         &action\n\t)\n}\n"
  },
  {
    "path": "examples/sokol/drawing.v",
    "content": "// vtest build: !solaris\nimport sokol.sapp\nimport sokol.gfx\nimport sokol.sgl\n\nstruct AppState {\n\tpass_action gfx.PassAction\n}\n\nfn main() {\n\tstate := &AppState{\n\t\tpass_action: gfx.create_clear_pass_action(0.1, 0.1, 0.1, 1.0)\n\t}\n\ttitle := 'Sokol Drawing Template'\n\tdesc := sapp.Desc{\n\t\twidth:             640\n\t\theight:            480\n\t\tuser_data:         state\n\t\tinit_userdata_cb:  init\n\t\tframe_userdata_cb: frame\n\t\twindow_title:      &char(title.str)\n\t}\n\tsapp.run(&desc)\n}\n\nfn init(_user_data voidptr) {\n\tdesc := sapp.create_desc() // gfx.Desc{\n\tgfx.setup(&desc)\n\tsgl_desc := sgl.Desc{}\n\tsgl.setup(&sgl_desc)\n}\n\nfn frame(state &AppState) {\n\t// println('frame')\n\tdraw()\n\tpass := sapp.create_default_pass(state.pass_action)\n\tgfx.begin_pass(&pass)\n\tsgl.draw()\n\tgfx.end_pass()\n\tgfx.commit()\n}\n\nfn draw() {\n\t// first, reset and setup ortho projection\n\tsgl.defaults()\n\tsgl.matrix_mode_projection()\n\tsgl.ortho(0.0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0)\n\tsgl.c4b(255, 0, 0, 128)\n\tdraw_hollow_rect(220, 140, 200, 200)\n\tsgl.c4b(25, 150, 255, 128)\n\tdraw_filled_rect(270, 190, 100, 100)\n\t// line(0, 0, 500, 500)\n}\n\nfn draw_hollow_rect(x f32, y f32, w f32, h f32) {\n\tsgl.begin_line_strip()\n\tsgl.v2f(x, y)\n\tsgl.v2f(x + w, y)\n\tsgl.v2f(x + w, y + h)\n\tsgl.v2f(x, y + h)\n\tsgl.v2f(x, y)\n\tsgl.end()\n}\n\nfn draw_filled_rect(x f32, y f32, w f32, h f32) {\n\tsgl.begin_quads()\n\tsgl.v2f(x, y)\n\tsgl.v2f(x + w, y)\n\tsgl.v2f(x + w, y + h)\n\tsgl.v2f(x, y + h)\n\tsgl.end()\n}\n"
  },
  {
    "path": "examples/sokol/fonts.v",
    "content": "// vtest build: !solaris\nimport sokol.sapp\nimport sokol.gfx\nimport sokol.sgl\nimport fontstash\nimport sokol.sfons\nimport os\n\nstruct AppState {\nmut:\n\tpass_action  gfx.PassAction\n\tfont_context &fontstash.Context\n\tfont_normal  int\n}\n\nfn main() {\n\tstate := &AppState{\n\t\tpass_action:  gfx.create_clear_pass_action(0.3, 0.3, 0.32, 1.0)\n\t\tfont_context: unsafe { nil } // &fontstash.Context(0)\n\t}\n\ttitle := 'V Metal/GL Text Rendering'\n\tdesc := sapp.Desc{\n\t\tuser_data:         state\n\t\tinit_userdata_cb:  init\n\t\tframe_userdata_cb: frame\n\t\twindow_title:      &char(title.str)\n\t}\n\tsapp.run(&desc)\n}\n\nfn init(mut state AppState) {\n\tdesc := sapp.create_desc()\n\tgfx.setup(&desc)\n\ts := &sgl.Desc{}\n\tsgl.setup(s)\n\tstate.font_context = sfons.create(512, 512, 1)\n\t// or use DroidSerif-Regular.ttf\n\tif bytes := os.read_bytes(os.resource_abs_path(os.join_path('..', 'assets', 'fonts',\n\t\t'RobotoMono-Regular.ttf')))\n\t{\n\t\tprintln('loaded font: ${bytes.len}')\n\t\tstate.font_normal = state.font_context.add_font_mem('sans', bytes.clone(), true)\n\t}\n}\n\nfn frame(mut state AppState) {\n\tstate.render_font()\n\tpass := sapp.create_default_pass(state.pass_action)\n\tgfx.begin_pass(&pass)\n\tsgl.draw()\n\tgfx.end_pass()\n\tgfx.commit()\n}\n\nfn (state &AppState) render_font() {\n\tmut sx := f32(0.0)\n\tmut sy := f32(0.0)\n\tmut dx := f32(0.0)\n\tmut dy := f32(0.0)\n\tlh := f32(0.0)\n\twhite := sfons.rgba(255, 255, 255, 255)\n\tblack := sfons.rgba(0, 0, 0, 255)\n\tbrown := sfons.rgba(192, 128, 0, 128)\n\tblue := sfons.rgba(0, 192, 255, 255)\n\n\tfont_context := state.font_context\n\tfont_context.clear_state()\n\tsgl.defaults()\n\tsgl.matrix_mode_projection()\n\tsgl.ortho(0.0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0)\n\tsx = 0\n\tsy = 50\n\tdx = sx\n\tdy = sy\n\tfont_context.set_font(state.font_normal)\n\tfont_context.set_size(100.0)\n\tascender := f32(0.0)\n\tdescender := f32(0.0)\n\tfont_context.vert_metrics(&ascender, &descender, &lh)\n\tdx = sx\n\tdy += lh\n\tfont_context.set_color(white)\n\tdx = font_context.draw_text(dx, dy, 'The quick ')\n\tfont_context.set_font(state.font_normal)\n\tfont_context.set_size(48.0)\n\tfont_context.set_color(brown)\n\tdx = font_context.draw_text(dx, dy, 'brown ')\n\tfont_context.set_font(state.font_normal)\n\tfont_context.set_size(24.0)\n\tfont_context.set_color(white)\n\tdx = font_context.draw_text(dx, dy, 'fox ')\n\tdx = sx\n\tdy += lh * 1.2\n\tfont_context.set_size(20.0)\n\tfont_context.set_font(state.font_normal)\n\tfont_context.set_color(blue)\n\tfont_context.draw_text(dx, dy, 'Now is the time for all good men to come to the aid of the party.')\n\tdx = 300\n\tdy = 350\n\tfont_context.set_alignment(.left | .baseline)\n\tfont_context.set_size(60.0)\n\tfont_context.set_font(state.font_normal)\n\tfont_context.set_color(white)\n\tfont_context.set_spacing(5.0)\n\tfont_context.set_blur(6.0)\n\tfont_context.draw_text(dx, dy, 'Blurry...')\n\tdx = 300\n\tdy += 50.0\n\tfont_context.set_size(28.0)\n\tfont_context.set_font(state.font_normal)\n\tfont_context.set_color(white)\n\tfont_context.set_spacing(0.0)\n\tfont_context.set_blur(3.0)\n\tfont_context.draw_text(dx, dy + 2, 'DROP SHADOW')\n\tfont_context.set_color(black)\n\tfont_context.set_blur(0)\n\tfont_context.draw_text(dx, dy, 'DROP SHADOW')\n\tfont_context.set_size(18.0)\n\tfont_context.set_font(state.font_normal)\n\tfont_context.set_color(white)\n\tdx = 50\n\tdy = 350\n\tline(f32(dx - 10), f32(dy), f32(dx + 250), f32(dy))\n\tfont_context.set_alignment(.left | .top)\n\tdx = font_context.draw_text(dx, dy, 'Top')\n\tdx += 10\n\tfont_context.set_alignment(.left | .middle)\n\tdx = font_context.draw_text(dx, dy, 'Middle')\n\tdx += 10\n\tfont_context.set_alignment(.left | .baseline)\n\tdx = font_context.draw_text(dx, dy, 'Baseline')\n\tdx += 10\n\tfont_context.set_alignment(.left | .bottom)\n\tfont_context.draw_text(dx, dy, 'Bottom')\n\tdx = 150\n\tdy = 400\n\tline(f32(dx), f32(dy - 30), f32(dx), f32(dy + 80.0))\n\tfont_context.set_alignment(.left | .baseline)\n\tfont_context.draw_text(dx, dy, 'Left')\n\tdy += 30\n\tfont_context.set_alignment(.center | .baseline)\n\tfont_context.draw_text(dx, dy, 'Center')\n\tdy += 30\n\tfont_context.set_alignment(.right | .baseline)\n\tfont_context.draw_text(dx, dy, 'Right')\n\tsfons.flush(font_context)\n}\n\nfn line(sx f32, sy f32, ex f32, ey f32) {\n\tsgl.begin_lines()\n\tsgl.c4b(255, 255, 0, 128)\n\tsgl.v2f(sx, sy)\n\tsgl.v2f(ex, ey)\n\tsgl.end()\n}\n"
  },
  {
    "path": "examples/sokol/freetype_raven.v",
    "content": "import sokol.sapp\nimport sokol.gfx\nimport sokol.sgl\nimport fontstash\nimport sokol.sfons\nimport os\n\nconst text = '\nOnce upon a midnight dreary, while I pondered, weak and weary,\nOver many a quaint and curious volume of forgotten lore—\n    While I nodded, nearly napping, suddenly there came a tapping,\nAs of some one gently rapping, rapping at my chamber door.\n“’Tis some visitor,” I muttered, “tapping at my chamber door—\n            Only this and nothing more.”\n\n    Ah, distinctly I remember it was in the bleak December;\nAnd each separate dying ember wrought its ghost upon the floor.\n    Eagerly I wished the morrow;—vainly I had sought to borrow\n    From my books surcease of sorrow—sorrow for the lost Lenore—\nFor the rare and radiant maiden whom the angels name Lenore—\n            Nameless here for evermore.\n\n    And the silken, sad, uncertain rustling of each purple curtain\nThrilled me—filled me with fantastic terrors never felt before;\n    So that now, to still the beating of my heart, I stood repeating\n    “’Tis some visitor entreating entrance at my chamber door—\nSome late visitor entreating entrance at my chamber door;—\n            This it is and nothing more.”\n\n    Presently my soul grew stronger; hesitating then no longer,\n“Sir,” said I, “or Madam, truly your forgiveness I implore;\n    But the fact is I was napping, and so gently you came rapping,\n    And so faintly you came tapping, tapping at my chamber door,\nThat I scarce was sure I heard you”—here I opened wide the door;—\n            Darkness there and nothing more.\n\nDeep into that darkness peering, long I stood there wondering, fearing,\nDoubting, dreaming dreams no mortal ever dared to dream before;\n    But the silence was unbroken, and the stillness gave no token,\n    And the only word there spoken was the whispered word, “Lenore?”\nThis I whispered, and an echo murmured back the word, “Lenore!”—\n            Merely this and nothing more.\n\n    Back into the chamber turning, all my soul within me burning,\nSoon again I heard a tapping somewhat louder than before.\n    “Surely,” said I, “surely that is something at my window lattice;\n      Let me see, then, what thereat is, and this mystery explore—\nLet my heart be still a moment and this mystery explore;—\n            ’Tis the wind and nothing more!”\n'\n\nconst lines = text.split('\\n')\n\nstruct AppState {\nmut:\n\tpass_action gfx.PassAction\n\tfons        &fontstash.Context = unsafe { nil }\n\tfont_normal int\n\tinited      bool\n}\n\nfn main() {\n\tmut color_action := gfx.ColorAttachmentAction{\n\t\tload_action: .clear\n\t\tclear_value: gfx.Color{\n\t\t\tr: 1.0\n\t\t\tg: 1.0\n\t\t\tb: 1.0\n\t\t\ta: 1.0\n\t\t}\n\t}\n\tmut pass_action := gfx.PassAction{}\n\tpass_action.colors[0] = color_action\n\tstate := &AppState{\n\t\tpass_action: pass_action\n\t\tfons:        unsafe { nil } // &fontstash.Context(0)\n\t}\n\ttitle := 'V Metal/GL Text Rendering'\n\tdesc := sapp.Desc{\n\t\tuser_data:         state\n\t\tinit_userdata_cb:  init\n\t\tframe_userdata_cb: frame\n\t\twindow_title:      &char(title.str)\n\t\twidth:             600\n\t\theight:            700\n\t\thigh_dpi:          true\n\t}\n\tsapp.run(&desc)\n}\n\nfn init(mut state AppState) {\n\tdesc := sapp.create_desc()\n\tgfx.setup(&desc)\n\ts := &sgl.Desc{}\n\tsgl.setup(s)\n\tstate.fons = sfons.create(512, 512, 1)\n\t// or use DroidSerif-Regular.ttf\n\tif bytes := os.read_bytes(os.resource_abs_path(os.join_path('..', 'assets', 'fonts',\n\t\t'RobotoMono-Regular.ttf')))\n\t{\n\t\tprintln('loaded font: ${bytes.len}')\n\t\tstate.font_normal = state.fons.add_font_mem('sans', bytes.clone(), true)\n\t}\n}\n\nfn frame(mut state AppState) {\n\tstate.render_font()\n\tpass := sapp.create_default_pass(state.pass_action)\n\tgfx.begin_pass(&pass)\n\tsgl.draw()\n\tgfx.end_pass()\n\tgfx.commit()\n}\n\nconst black = sfons.rgba(0, 0, 0, 255)\n\nfn (mut state AppState) render_font() {\n\tlh := 30\n\tmut dy := lh\n\tmut fons := state.fons\n\tif !state.inited {\n\t\tfons.clear_state()\n\t\tsgl.defaults()\n\t\tsgl.matrix_mode_projection()\n\t\tsgl.ortho(0.0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0)\n\t\tfons.set_font(state.font_normal)\n\t\tfons.set_size(100.0)\n\t\tfons.set_color(black)\n\t\tfons.set_font(state.font_normal)\n\t\tfons.set_size(35.0)\n\t\tstate.inited = true\n\t}\n\n\tfor line in lines {\n\t\tfons.draw_text(40, dy, line)\n\t\tdy += lh\n\t}\n\tsfons.flush(fons)\n}\n\nfn line(sx f32, sy f32, ex f32, ey f32) {\n\tsgl.begin_lines()\n\tsgl.c4b(255, 255, 0, 128)\n\tsgl.v2f(sx, sy)\n\tsgl.v2f(ex, ey)\n\tsgl.end()\n}\n"
  },
  {
    "path": "examples/sokol/particles/modules/particle/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 Lars Pontoppidan\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "examples/sokol/particles/modules/particle/color.v",
    "content": "// Copyright(C) 2019 Lars Pontoppidan. All rights reserved.\n// Use of this source code is governed by an MIT license file distributed with this software package\nmodule particle\n\n// * Color\npub struct Color {\nmut:\n\tr u8\n\tg u8\n\tb u8\n\ta u8\n}\n"
  },
  {
    "path": "examples/sokol/particles/modules/particle/particle.v",
    "content": "// Copyright(C) 2019 Lars Pontoppidan. All rights reserved.\n// Use of this source code is governed by an MIT license file distributed with this software package\nmodule particle\n\nimport math.vec\nimport sokol.sgl\n\nconst default_life_time = 1000\nconst default_v_color = Color{93, 136, 193, 255}\n\n// * Module public\npub fn new(location vec.Vec2[f64]) &Particle {\n\tp := &Particle{\n\t\tlocation:       location\n\t\tvelocity:       vec.Vec2[f64]{0, 0}\n\t\tacceleration:   vec.Vec2[f64]{0, 0}\n\t\tcolor:          default_v_color\n\t\tlife_time:      default_life_time\n\t\tlife_time_init: default_life_time\n\t}\n\treturn p\n}\n\nfn remap(v f64, min f64, max f64, new_min f64, new_max f64) f64 {\n\treturn (((v - min) * (new_max - new_min)) / (max - min)) + new_min\n}\n\n// Particle\npub struct Particle {\npub mut:\n\tlocation       vec.Vec2[f64]\n\tvelocity       vec.Vec2[f64]\n\tacceleration   vec.Vec2[f64]\n\tcolor          Color\n\tlife_time      f64\n\tlife_time_init f64\n}\n\npub fn (mut p Particle) update(dt f64) {\n\tmut acc := p.acceleration\n\tacc.multiply_scalar(dt)\n\tp.velocity = p.velocity.add(acc)\n\tp.location = p.location.add(p.velocity)\n\tlt := p.life_time - (1000 * dt)\n\tif lt > 0 {\n\t\tp.life_time = lt\n\t\tp.color.r = p.color.r - 1 // u8(remap(p.life_time,0.0,p.life_time_init,0,p.color.r))\n\t\tp.color.g = p.color.g - 1 // u8(remap(p.life_time,0.0,p.life_time_init,0,p.color.g))\n\t\tp.color.b = p.color.b - 1 // u8(remap(p.life_time,0.0,p.life_time_init,0,p.color.b))\n\t\tp.color.a = u8(int(remap(p.life_time, 0.0, p.life_time_init, 0, 255))) - 10\n\t} else {\n\t\tp.life_time = 0\n\t}\n}\n\npub fn (p Particle) is_dead() bool {\n\treturn p.life_time <= 0.0\n}\n\npub fn (p Particle) draw() {\n\tl := p.location\n\tsgl.c4b(p.color.r, p.color.g, p.color.b, p.color.a)\n\tlx := f32(l.x)\n\tly := f32(l.y)\n\tsgl.v2f(lx, ly)\n\tsgl.v2f(lx + 2, ly)\n\tsgl.v2f(lx + 2, ly + 2)\n\tsgl.v2f(lx, ly + 2)\n}\n\npub fn (mut p Particle) reset() {\n\tp.location.zero()\n\tp.acceleration.zero()\n\tp.velocity.zero()\n\t// p.color = Color{93, 136, 193, 255}\n\tp.color = default_v_color\n\tp.life_time = default_life_time\n\tp.life_time_init = p.life_time\n}\n"
  },
  {
    "path": "examples/sokol/particles/modules/particle/system.v",
    "content": "// Copyright(C) 2019 Lars Pontoppidan. All rights reserved.\n// Use of this source code is governed by an MIT license file distributed with this software package\nmodule particle\n\nimport math.vec\nimport rand\nimport sokol.sgl\n\npub struct SystemConfig {\npub:\n\tpool int\n}\n\npub struct System {\npub:\n\twidth  int\n\theight int\nmut:\n\tpool []&Particle\n\tbin  []&Particle\n}\n\npub fn (mut s System) init(sc SystemConfig) {\n\tunsafe { s.pool.flags.set(.noslices | .noshrink) }\n\tunsafe { s.bin.flags.set(.noslices | .noshrink) }\n\tfor i := 0; i < sc.pool; i++ {\n\t\tp := new(vec.Vec2[f64]{f32(s.width) * 0.5, f32(s.height) * 0.5})\n\t\ts.bin << p\n\t}\n}\n\npub fn (mut s System) update(dt f64) {\n\tmut p := &Particle(unsafe { nil })\n\tmut moved := 0\n\tfor i := 0; i < s.pool.len; i++ {\n\t\tp = s.pool[i]\n\t\tp.update(dt)\n\t\tif p.is_dead() {\n\t\t\ts.bin << p\n\t\t\ts.pool.delete(i)\n\t\t\tmoved++\n\t\t}\n\t}\n\tif moved != 0 {\n\t\t$if trace_moves_spool_to_sbin ? {\n\t\t\teprintln('${moved:4} particles s.pool -> s.bin')\n\t\t}\n\t}\n}\n\npub fn (s System) draw() {\n\tsgl.begin_quads()\n\tfor p in s.pool {\n\t\tp.draw()\n\t}\n\tsgl.end()\n}\n\npub fn (mut s System) reset() {\n\tfor i in 0 .. s.pool.len {\n\t\tmut p := s.pool[i]\n\t\tp.reset()\n\t\tp.life_time = 0\n\t}\n\tfor i in 0 .. s.bin.len {\n\t\tmut p := s.pool[i]\n\t\tp.reset()\n\t\tp.life_time = 0\n\t}\n}\n\npub fn (mut s System) explode(x f32, y f32) {\n\tmut reserve := 500\n\tcenter := vec.Vec2[f64]{x, y}\n\tmut p := &Particle(unsafe { nil })\n\tmut moved := 0\n\tfor i := 0; i < s.bin.len && reserve > 0; i++ {\n\t\tp = s.bin[i]\n\t\tp.reset()\n\t\tp.location.from(center)\n\t\tp.acceleration = vec.Vec2[f64]{rand.f32_in_range(-0.5, 0.5) or { -0.5 }, rand.f32_in_range(-0.5,\n\t\t\t0.5) or { -0.5 }}\n\t\tp.velocity = vec.Vec2[f64]{rand.f32_in_range(-0.5, 0.5) or { -0.5 }, rand.f32_in_range(-0.5,\n\t\t\t0.5) or { -0.5 }}\n\t\tp.life_time = rand.f64_in_range(500, 2000) or { 500 }\n\t\ts.pool << p\n\t\ts.bin.delete(i)\n\t\tmoved++\n\t\treserve--\n\t}\n\tif moved != 0 {\n\t\t$if trace_moves_sbin_to_spool ? {\n\t\t\teprintln('${moved:4} particles s.bin -> s.pool')\n\t\t}\n\t}\n}\n\npub fn (mut s System) free() {\n\tfor p in s.pool {\n\t\tif unsafe { p == 0 } {\n\t\t\tprint(ptr_str(p) + ' ouch')\n\t\t\tcontinue\n\t\t}\n\t\tunsafe { free(p) }\n\t}\n\ts.pool.clear()\n\tfor p in s.bin {\n\t\tif unsafe { p == 0 } {\n\t\t\tprint(ptr_str(p) + ' ouch')\n\t\t\tcontinue\n\t\t}\n\t\tunsafe {\n\t\t\t// println('Freeing from bin')\n\t\t\tfree(p)\n\t\t}\n\t}\n\ts.bin.clear()\n}\n"
  },
  {
    "path": "examples/sokol/particles/particles.v",
    "content": "// Copyright(C) 2019 Lars Pontoppidan. All rights reserved.\n// Use of this source code is governed by an MIT license file distributed with this software package\nmodule main\n\nimport time\nimport sokol.sapp\nimport sokol.gfx\nimport sokol.sgl\nimport particle\n\nfn main() {\n\tmut app := &App{\n\t\twidth:       800\n\t\theight:      400\n\t\tpass_action: gfx.create_clear_pass_action(0.1, 0.1, 0.1, 1.0)\n\t}\n\tapp.init()\n\tapp.run()\n}\n\nstruct App {\n\tpass_action gfx.PassAction\nmut:\n\twidth     int\n\theight    int\n\tframe     i64\n\tlast      i64\n\tps        particle.System\n\talpha_pip sgl.Pipeline\n}\n\nfn (mut a App) init() {\n\ta.frame = 0\n\ta.last = time.ticks()\n\ta.ps = particle.System{\n\t\twidth:  a.width\n\t\theight: a.height\n\t}\n\ta.ps.init(particle.SystemConfig{\n\t\tpool: 20000\n\t})\n}\n\nfn (mut a App) cleanup() {\n\tunsafe {\n\t\ta.ps.free()\n\t}\n}\n\nfn (mut a App) run() {\n\ttitle := 'V Particle Example'\n\tdesc := sapp.Desc{\n\t\twidth:               a.width\n\t\theight:              a.height\n\t\tuser_data:           a\n\t\tinit_userdata_cb:    init\n\t\tframe_userdata_cb:   frame\n\t\tevent_userdata_cb:   event\n\t\twindow_title:        &char(title.str)\n\t\tcleanup_userdata_cb: cleanup\n\t}\n\tsapp.run(&desc)\n}\n\nfn (a App) draw() {\n\tsgl.load_pipeline(a.alpha_pip)\n\ta.ps.draw()\n}\n\nfn init(mut app App) {\n\tdesc := sapp.create_desc()\n\tgfx.setup(&desc)\n\tsgl_desc := sgl.Desc{\n\t\tmax_vertices: 50 * 65536\n\t}\n\tsgl.setup(&sgl_desc)\n\tmut pipdesc := gfx.PipelineDesc{}\n\tunsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }\n\n\tcolor_state := gfx.ColorTargetState{\n\t\tblend: gfx.BlendState{\n\t\t\tenabled:        true\n\t\t\tsrc_factor_rgb: .src_alpha\n\t\t\tdst_factor_rgb: .one_minus_src_alpha\n\t\t}\n\t}\n\tpipdesc.colors[0] = color_state\n\n\tapp.alpha_pip = sgl.make_pipeline(&pipdesc)\n}\n\nfn cleanup(mut app App) {\n\tapp.cleanup()\n\tgfx.shutdown()\n}\n\nfn frame(mut app App) {\n\tapp.width = sapp.width()\n\tapp.height = sapp.height()\n\tt := time.ticks()\n\tdt := f64(t - app.last) / 1000.0\n\tapp.ps.update(dt)\n\tdraw(app)\n\tpass := sapp.create_default_pass(app.pass_action)\n\tgfx.begin_pass(&pass)\n\tsgl.default_pipeline()\n\tsgl.draw()\n\tgfx.end_pass()\n\tgfx.commit()\n\tapp.frame++\n\tapp.last = t\n}\n\nfn event(ev &sapp.Event, mut app App) {\n\tif ev.type == .mouse_move {\n\t\tapp.ps.explode(ev.mouse_x, ev.mouse_y)\n\t}\n\tif ev.type == .mouse_up || ev.type == .mouse_down {\n\t\tif ev.mouse_button == .left {\n\t\t\tis_pressed := ev.type == .mouse_down\n\t\t\tif is_pressed {\n\t\t\t\tapp.ps.explode(ev.mouse_x, ev.mouse_y)\n\t\t\t}\n\t\t}\n\t}\n\tif ev.type == .key_up || ev.type == .key_down {\n\t\tif ev.key_code == .r {\n\t\t\tis_pressed := ev.type == .key_down\n\t\t\tif is_pressed {\n\t\t\t\tapp.ps.reset()\n\t\t\t}\n\t\t}\n\t}\n\tif ev.type == .touches_began || ev.type == .touches_moved {\n\t\tif ev.num_touches > 0 {\n\t\t\ttouch_point := ev.touches[0]\n\t\t\tapp.ps.explode(touch_point.pos_x, touch_point.pos_y)\n\t\t}\n\t}\n}\n\nfn draw(a &App) {\n\tsgl.defaults()\n\tsgl.matrix_mode_projection()\n\tsgl.ortho(0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0)\n\tsgl.push_matrix()\n\ta.draw()\n\tsgl.pop_matrix()\n}\n"
  },
  {
    "path": "examples/sokol/sounds/melody.v",
    "content": "// vtest build: !openbsd\nimport gg\nimport sokol.audio\n\nstruct AppState {\nmut:\n\tframe_0 int       // offset of the current audio frames, relative to the start of the music\n\tframes  [2048]f32 // a copy of the last rendered audio frames\n\tgg      &gg.Context = unsafe { nil } // used for drawing\n}\n\nfn my_audio_stream_callback(mut soundbuffer &f32, num_frames int, num_channels int, mut acontext AppState) {\n\tfor frame := 0; frame < num_frames; frame++ {\n\t\tt := int(f32(acontext.frame_0 + frame) * 0.245)\n\t\t// \"Techno\" by Gabriel Miceli\n\t\ty := (t * (((t / 10 | 0) ^ ((t / 10 | 0) - 1280)) % 11) / 2 & 127) +\n\t\t\t(t * (((t / 640 | 0) ^ ((t / 640 | 0) - 2)) % 13) / 2 & 127)\n\t\tfor ch := 0; ch < num_channels; ch++ {\n\t\t\tidx := frame * num_channels + ch\n\t\t\ta := f32(y - 127) / 255.0\n\t\t\tsoundbuffer[idx] = a\n\t\t\tacontext.frames[idx & 2047] = a\n\t\t}\n\t}\n\tacontext.frame_0 += num_frames\n}\n\nfn graphics_frame(mut state AppState) {\n\tws := gg.window_size()\n\tcenter_y := f32(ws.height / 2)\n\tstate.gg.begin()\n\tfor x in 0 .. 1024 {\n\t\tvx := ws.width * f32(x) / 1024.0\n\t\tvy := center_y * 3.0 / 4.0 * (state.frames[2 * x] + state.frames[2 * x + 1])\n\t\tcolor := gg.Color{f(state, x), f(state, x + 300), f(state, x + 700), 255}\n\t\tstate.gg.draw_line(vx, center_y, vx, center_y + vy, color)\n\t}\n\tstate.gg.end()\n}\n\nfn f(state &AppState, idx int) u8 {\n\treturn u8(127 + state.frames[(int(state.gg.frame) + idx) & 2047] * 128)\n}\n\nfn main() {\n\tprintln('Based on the ByteBeat formula from: https://www.youtube.com/watch?v=V4GfkFbDojc \\n \"Techno\" by Gabriel Miceli')\n\tmut state := &AppState{}\n\taudio.setup(stream_userdata_cb: my_audio_stream_callback, user_data: state)\n\tdefer { audio.shutdown() }\n\tstate.gg = gg.new_context(\n\t\tbg_color:     gg.Color{50, 50, 50, 255}\n\t\twidth:        800\n\t\theight:       600\n\t\twindow_title: 'ByteBeat Music'\n\t\tframe_fn:     graphics_frame\n\t\tuser_data:    state\n\t)\n\tstate.gg.run()\n}\n"
  },
  {
    "path": "examples/sokol/sounds/ogg_player.v",
    "content": "// vtest build: !openbsd\nimport os\nimport time\nimport sokol.audio\nimport encoding.vorbis\n\nfn main() {\n\tunbuffer_stdout()\n\tif os.args.len < 2 {\n\t\teprintln('Usage: ogg_player file.ogg ...')\n\t\tplay_sounds([os.resource_abs_path('pickup.ogg')])!\n\t\texit(1)\n\t}\n\tplay_sounds(os.args[1..])!\n}\n\nfn play_sounds(files []string) ! {\n\tmut player := Player{\n\t\tdecoder: unsafe { nil }\n\t}\n\tplayer.init()\n\tfor f in files {\n\t\tif !os.exists(f) || os.is_dir(f) {\n\t\t\teprintln('skipping \"${f}\" (does not exist)')\n\t\t\tcontinue\n\t\t}\n\t\tfext := os.file_ext(f).to_lower()\n\t\tif fext != '.ogg' {\n\t\t\teprintln('skipping \"${f}\" (not an .ogg file)')\n\t\t\tcontinue\n\t\t}\n\t\tplayer.play_ogg_file(f)!\n\t}\n\tplayer.stop()\n}\n\nstruct Player {\nmut:\n\tchannels           int\n\tsample_rate        int\n\tpos                int\n\tfinished           bool\n\tpush_slack_ms      int = 5\n\tstream_rate        u32\n\tstream_channels    int\n\tstream_len_samples u32\n\tstream_len_seconds f32\n\txerror             vorbis.VorbisErrorCode\n\tallocator          C.stb_vorbis_alloc = C.stb_vorbis_alloc{\n\t\talloc_buffer:                 0\n\t\talloc_buffer_length_in_bytes: 0\n\t}\n\tdecoder            &C.stb_vorbis // TODO: cgen error with -cstrict -gcc, when this is = unsafe { nil } here\n}\n\nfn (mut p Player) init() {\n\taudio.setup()\n\tp.sample_rate = audio.sample_rate()\n\tp.channels = audio.channels()\n\talloc_size := 200 * 1024\n\tp.allocator = C.stb_vorbis_alloc{\n\t\talloc_buffer:                 unsafe { &char(vcalloc(alloc_size)) }\n\t\talloc_buffer_length_in_bytes: alloc_size\n\t}\n}\n\nfn (mut p Player) stop() {\n\tp.free()\n\taudio.shutdown()\n}\n\nfn (mut p Player) free() {\n\tp.finished = false\n\tp.pos = 0\n\tp.close_decoder()\n\tunsafe { free(p.allocator.alloc_buffer) }\n\tunsafe {\n\t\tp.allocator.alloc_buffer = nil\n\t}\n}\n\nfn (mut p Player) close_decoder() {\n\tif !isnil(p.decoder) {\n\t\tC.stb_vorbis_close(p.decoder)\n\t}\n}\n\nfn (mut p Player) play_ogg_file(fpath string) ! {\n\tp.close_decoder()\n\tp.pos = 0\n\tp.xerror = .no_error\n\tp.decoder = C.stb_vorbis_open_filename(&char(fpath.str), voidptr(&p.xerror), &p.allocator)\n\tif isnil(p.decoder) || p.xerror != .no_error {\n\t\treturn error('could not open ogg file: ${fpath}, xerror: ${p.xerror}')\n\t}\n\tinfo := C.stb_vorbis_get_info(p.decoder)\n\tp.stream_rate = info.sample_rate\n\tp.stream_channels = info.channels\n\tp.stream_len_samples = C.stb_vorbis_stream_length_in_samples(p.decoder)\n\tp.stream_len_seconds = C.stb_vorbis_stream_length_in_seconds(p.decoder)\n\tp.finished = false\n\n\tif !(p.channels == p.stream_channels && p.sample_rate == p.stream_rate) {\n\t\taudio.shutdown()\n\t\taudio.setup(\n\t\t\tnum_channels: p.stream_channels\n\t\t\tsample_rate:  int(p.stream_rate)\n\t\t)\n\t\tp.sample_rate = audio.sample_rate()\n\t\tp.channels = audio.channels()\n\t}\n\tprintln('> play_ogg_file: rate: ${p.sample_rate:5}, channels: ${p.channels:1} | stream rate: ${p.stream_rate:5}, channels: ${p.stream_channels:1}, samples: ${p.stream_len_samples:8} | seconds: ${p.stream_len_seconds:7.3f} | ${fpath}')\n\n\tframes := [16384]f32{}\n\tpframes := unsafe { &frames[0] }\n\tfor !p.finished {\n\t\tmut delay := p.push_slack_ms\n\t\texpected_frames := audio.expect()\n\t\tif expected_frames > 0 {\n\t\t\tmut decoded_frames := 0\n\t\t\tfor decoded_frames < expected_frames {\n\t\t\t\tsamples := C.stb_vorbis_get_samples_float_interleaved(p.decoder, p.channels,\n\t\t\t\t\tpframes, 1024)\n\t\t\t\tif samples == 0 {\n\t\t\t\t\tp.finished = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\twritten_frames := audio.push(pframes, samples)\n\t\t\t\tdecoded_frames += written_frames\n\t\t\t\tp.pos += samples\n\t\t\t}\n\t\t\tdelay = (1_000 * decoded_frames) / p.sample_rate\n\t\t}\n\t\tprint('\\r  position: ${p.pos:9} / ${p.stream_len_samples:-9} samples | ${p.pos * p.stream_len_seconds / p.stream_len_samples:7.3f} / ${p.stream_len_seconds:-7.3f} seconds')\n\t\ttime.sleep(int_max(p.push_slack_ms, delay - p.push_slack_ms) * time.millisecond)\n\t}\n\tprintln('')\n}\n"
  },
  {
    "path": "examples/sokol/sounds/simple_bytebeat.v",
    "content": "// vtest build: !openbsd\n\n// This program illustrates how to use sokol.audio in a simple console app, *without a gui*.\n// See melody.v for an example of how it can be integrated into a graphics app.\nimport time\nimport sokol.audio\n\nfn audio_callback(mut soundbuffer &f32, num_frames int, num_channels int, mut frame_0 &i32) {\n\tfor frame := 0; frame < num_frames; frame++ {\n\t\tt := i32(f32(*frame_0 + frame) * 0.245)\n\t\ty := (t * (((t / 10 | 0) ^ ((t / 10 | 0) - 1280)) % 11) / 2 & 127) +\n\t\t\t(t * (((t / 640 | 0) ^ ((t / 640 | 0) - 2)) % 13) / 2 & 127)\n\t\tfor ch := 0; ch < num_channels; ch++ {\n\t\t\tidx := frame * num_channels + ch\n\t\t\ta := f32(y - 127) / 255.0\n\t\t\tsoundbuffer[idx] = a\n\t\t}\n\t}\n\tframe_0 += num_frames\n}\n\n// The example uses \\r, to show a simple progress bar, while the music is playing.\n// That works best, if the output is not buffered at all.\nunbuffer_stdout()\n\nprintln('The ByteBeat formula used in this example is from https://www.youtube.com/watch?v=V4GfkFbDojc , \"Techno\" by Gabriel Miceli')\n\nmut frame_0 := i32(0) // offset of the current audio frames, relative to the start of the music\naudio.setup(stream_userdata_cb: audio_callback, user_data: &frame_0) // our state/user_data can be just a simple integer\n\nfor t in 0 .. 600 {\n\tprint('\\r> t: ${t:5}s , frame_0: ${frame_0:10} samples')\n\ttime.sleep(1 * time.second)\n}\nprintln('\\nGood bye.')\n\naudio.shutdown()\n"
  },
  {
    "path": "examples/sokol/sounds/simple_keyboard_synth.v",
    "content": "// vtest build: !openbsd\nimport time\nimport math\nimport term\nimport sokol.audio\n\nstruct Note {\nmut:\n\tphase     f32\n\tfreq      f32\n\tamplitude f32\n}\n\nstruct App {\nmut:\n\tnotes shared []Note\n}\n\nfn main() {\n\tprintln('Press the keys (a, s, d, f, g, h, j, k) to play notes. Press ESC to quit.')\n\tmut app := &App{\n\t\tnotes: []Note{len: 32}\n\t}\n\taudio.setup(\n\t\tstream_userdata_cb: audio_callback\n\t\tuser_data:          app\n\t)\n\tdefer { audio.shutdown() }\n\tterm.enable_echo(false)\n\tdefer { term.enable_echo(true) }\n\tfor {\n\t\tkey := term.key_pressed(blocking: false)\n\t\tapp.handle_key(key) or { break }\n\t\ttime.sleep(5 * time.millisecond)\n\t}\n}\n\nconst c_2_pi = 2 * math.pi\nconst c_phase_step_per_freq = c_2_pi / 44100.0\nconst c_note_start_amplitude = 0.33\nconst c_note_decay = 0.3 / 44100.0\n\nfn (mut app App) handle_key(key i64) ? {\n\tif key == -1 {\n\t\treturn\n\t}\n\tmut freq := f32(0.0)\n\tmatch key {\n\t\t27 { return none }\n\t\t` ` { app.silence() }\n\t\t`a` { freq = 261.63 }\n\t\t`s` { freq = 293.66 }\n\t\t`d` { freq = 329.63 }\n\t\t`f` { freq = 349.23 }\n\t\t`g` { freq = 392.00 }\n\t\t`h` { freq = 440.00 }\n\t\t`j` { freq = 493.88 }\n\t\t`k` { freq = 523.25 }\n\t\telse {}\n\t}\n\tif freq > 0 {\n\t\tapp.play(freq, c_note_start_amplitude)\n\t}\n}\n\nfn (mut app App) play(freq f32, volume f32) {\n\tlock app.notes {\n\t\tfor mut note in app.notes {\n\t\t\tnote.amplitude -= 0.2\n\t\t}\n\t\tfor mut note in app.notes {\n\t\t\tif note.amplitude <= 0 {\n\t\t\t\tnote = Note{\n\t\t\t\t\tphase:     0.0\n\t\t\t\t\tfreq:      freq\n\t\t\t\t\tamplitude: volume\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\nfn (mut app App) silence() {\n\tlock app.notes {\n\t\tfor mut note in app.notes {\n\t\t\tnote.amplitude = 0\n\t\t}\n\t}\n}\n\nfn audio_callback(mut soundbuffer &f32, num_frames int, num_channels int, mut app App) {\n\tlock app.notes {\n\t\tfor frame in 0 .. num_frames {\n\t\t\tmut sample := f32(0.0)\n\t\t\tfor mut note in app.notes {\n\t\t\t\tif note.amplitude <= 0 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tsample += note.amplitude * math.sinf(note.phase)\n\t\t\t\tsample += note.amplitude * math.sinf(note.phase * 2.718)\n\t\t\t\tsample += note.amplitude * math.sinf(note.phase * 3.141)\n\n\t\t\t\tnote.phase += note.freq * c_phase_step_per_freq\n\t\t\t\tfor note.phase >= c_2_pi {\n\t\t\t\t\tnote.phase -= c_2_pi\n\t\t\t\t}\n\t\t\t\tnote.amplitude -= c_note_decay\n\t\t\t}\n\t\t\tfor ch in 0 .. num_channels {\n\t\t\t\tsoundbuffer[frame * num_channels + ch] = sample\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/sokol/sounds/simple_sin_tone_using_audio_push.v",
    "content": "// vtest build: !openbsd && !sanitize-memory-clang // Fails compilation with: `ld: /lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line`\n// import log\nimport math\nimport time\nimport sokol.audio\n\nfn main() {\n\targs := arguments()\n\tfreq := args[1] or { '417' }.int()\n\tamplitude := args[2] or { '0.5' }.f32()\n\tdump(freq)\n\tdump(amplitude)\n\n\taudio.setup(num_channels: 1)\n\tsample_rate := dump(audio.sample_rate())\n\tdump(audio.buffer_frames())\n\tdump(audio.expect())\n\n\t// create an array of frames, filled with the desired pure sine tone:\n\tmut frames := []f32{len: sample_rate * 2} // 2 seconds\n\tfor i in 0 .. frames.len {\n\t\tt := f32(i) / f32(sample_rate)\n\t\tframes[i] = amplitude * math.sinf(f32(freq) * t * (2 * math.pi))\n\t}\n\n\t// play the sound by continuosly pushing samples from the generated\n\t// array of sound frames, when there is need for more:\n\tmut fpos := 0\n\tfor {\n\t\texpected_frames := audio.expect()\n\t\tif expected_frames > 0 {\n\t\t\twritten_frames := audio.push(unsafe { &frames[fpos] }, expected_frames)\n\t\t\tfpos += written_frames\n\t\t\t// log.info('> pushing done ... fpos: ${fpos:6} | expected_frames: ${expected_frames:6} | written: ${written:6}')\n\t\t\tif fpos > frames.len - 2 * written_frames {\n\t\t\t\t// log.info('> fpos too large: ${fpos}')\n\t\t\t\tfpos = find_loop_position(fpos, frames)\n\t\t\t\t// log.info('> fpos looped back to start: ${fpos}')\n\t\t\t}\n\t\t}\n\t\ttime.sleep(50 * time.millisecond)\n\t}\n\taudio.shutdown()\n}\n\nfn find_loop_position(fpos int, frames []f32) int {\n\treturn find_matching_position(frames, fpos, 0.01, 2) or {\n\t\tfind_matching_position(frames, fpos, 0.05, 2) or {\n\t\t\tfind_matching_position(frames, fpos, 0.1, 2) or { 0 }\n\t\t}\n\t}\n}\n\n@[direct_array_access]\nfn find_matching_position(frames []f32, fpos int, tol f32, d int) ?int {\n\tif fpos - d < 0 || fpos + d >= frames.len {\n\t\treturn none\n\t}\n\tp1, p2, p3 := frames[fpos - d], frames[fpos], frames[fpos + d]\n\tfor i in 2 .. fpos / 2 {\n\t\tnp1, np2, np3 := frames[i - d], frames[i], frames[i + d]\n\t\tif math.tolerance(np1, p1, tol) && math.tolerance(np2, p2, tol)\n\t\t\t&& math.tolerance(np3, p3, tol) {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn none\n}\n"
  },
  {
    "path": "examples/sokol/sounds/simple_sin_tones.v",
    "content": "// vtest build: !openbsd && !sanitize-memory-clang // Fails compilation with: `ld: /lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line`\nimport time\nimport math\nimport sokol.audio\n\nconst sw = time.new_stopwatch()\nconst sw_start_ms = sw.elapsed().milliseconds()\n\n@[inline]\nfn sintone(periods int, frame int, num_frames int) f32 {\n\treturn math.sinf(f32(periods) * (2 * math.pi) * f32(frame) / f32(num_frames))\n}\n\nfn my_audio_stream_callback(mut soundbuffer &f32, num_frames int, num_channels int) {\n\tms := sw.elapsed().milliseconds() - sw_start_ms\n\tfor frame := 0; frame < num_frames; frame++ {\n\t\tfor ch := 0; ch < num_channels; ch++ {\n\t\t\tidx := frame * num_channels + ch\n\t\t\tif ms < 250 {\n\t\t\t\tsoundbuffer[idx] = 0.5 * sintone(20, frame, num_frames)\n\t\t\t} else if ms < 300 {\n\t\t\t\tsoundbuffer[idx] = 0.5 * sintone(25, frame, num_frames)\n\t\t\t} else if ms < 1500 {\n\t\t\t\tsoundbuffer[idx] *= sintone(22, frame, num_frames)\n\t\t\t} else {\n\t\t\t\tsoundbuffer[idx] = 0.5 * sintone(25, frame, num_frames)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfn main() {\n\taudio.setup(\n\t\tstream_cb: my_audio_stream_callback\n\t)\n\ttime.sleep(2000 * time.millisecond)\n\taudio.shutdown()\n}\n"
  },
  {
    "path": "examples/sokol/sounds/wav_player.v",
    "content": "// vtest build: !openbsd\nimport os\nimport time\nimport sokol.audio\n\nstruct Player {\nmut:\n\tsample_rate int\n\tsamples     []f32\n\tpos         int\n\tfinished    bool\n}\n\nfn main() {\n\tif os.args.len < 2 {\n\t\teprintln('Usage: play_wav file1.wav file2.wav ...')\n\t\tplay_sounds([os.resource_abs_path('uhoh.wav')])!\n\t\texit(1)\n\t}\n\tplay_sounds(os.args[1..])!\n}\n\nfn play_sounds(files []string) ! {\n\tmut player := Player{}\n\tplayer.init()\n\tfor f in files {\n\t\tif !os.exists(f) || os.is_dir(f) {\n\t\t\teprintln('skipping \"${f}\" (does not exist)')\n\t\t\tcontinue\n\t\t}\n\t\tfext := os.file_ext(f).to_lower()\n\t\tif fext != '.wav' {\n\t\t\teprintln('skipping \"${f}\" (not a .wav file)')\n\t\t\tcontinue\n\t\t}\n\t\tplayer.play_wav_file(f)!\n\t}\n\tplayer.stop()\n}\n\n//\nfn audio_player_callback(mut buffer &f32, num_frames int, num_channels int, mut p Player) {\n\tntotal := num_channels * num_frames\n\tunsafe { vmemset(buffer, 0, ntotal * 4) }\n\tif p.finished {\n\t\treturn\n\t}\n\tnremaining := p.samples.len - p.pos\n\tnsamples := if nremaining < ntotal { nremaining } else { ntotal }\n\tif nsamples <= 0 {\n\t\tp.finished = true\n\t\treturn\n\t}\n\tunsafe { vmemcpy(buffer, &p.samples[p.pos], nsamples * 4) }\n\tp.pos += nsamples\n}\n\nfn (mut p Player) init() {\n\taudio.setup(\n\t\tnum_channels:       1\n\t\tstream_userdata_cb: audio_player_callback\n\t\tuser_data:          p\n\t\tsample_rate:        44100\n\t)\n\tp.sample_rate = audio.sample_rate()\n}\n\nfn (mut p Player) stop() {\n\taudio.shutdown()\n\tp.free()\n}\n\nfn (mut p Player) play_wav_file(fpath string) ! {\n\tprintln('> play_wav_file: ${fpath}')\n\tsamples := read_wav_file_samples(fpath)!\n\tp.finished = true\n\tp.samples << samples\n\tp.finished = false\n\tfor !p.finished {\n\t\ttime.sleep(16 * time.millisecond)\n\t}\n\tp.free()\n}\n\nfn (mut p Player) free() {\n\tp.finished = false\n\tp.samples = []f32{}\n\tp.pos = 0\n}\n\n// The read_wav_file_samples function below is based on the following sources:\n// http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html\n// http://www.lightlink.com/tjweber/StripWav/WAVE.html\n// http://www.lightlink.com/tjweber/StripWav/Canon.html\n// https://tools.ietf.org/html/draft-ema-vpim-wav-00\n// Note: > The chunks MAY appear in any order except that the Format chunk\n// > MUST be placed before the Sound data chunk (but not necessarily\n// > contiguous to the Sound data chunk).\nstruct RIFFHeader {\n\triff      [4]u8\n\tfile_size u32\n\tform_type [4]u8\n}\n\nstruct RIFFChunkHeader {\n\tchunk_type [4]u8\n\tchunk_size u32\n\tchunk_data voidptr\n}\n\nstruct RIFFFormat {\n\tformat_tag            u16    // PCM = 1; Values other than 1 indicate some form of compression.\n\tnchannels             u16    // Nc ; 1 = mono ; 2 = stereo\n\tsample_rate           u32    // F\n\tavg_bytes_per_second  u32    // F * M*Nc\n\tnblock_align          u16    // M*Nc\n\tbits_per_sample       u16    // 8 * M\n\tcbsize                u16    // Size of the extension: 22\n\tvalid_bits_per_sample u16    // at most 8*M\n\tchannel_mask          u32    // Speaker position mask\n\tsub_format            [16]u8 // GUID\n}\n\nfn read_wav_file_samples(fpath string) ![]f32 {\n\tmut res := []f32{}\n\t// eprintln('> read_wav_file_samples: ${fpath} -------------------------------------------------')\n\tmut bytes := os.read_bytes(fpath)!\n\tmut pbytes := &u8(bytes.data)\n\tmut offset := u32(0)\n\trh := unsafe { &RIFFHeader(pbytes) }\n\t// eprintln('rh: ${rh}')\n\tif rh.riff != [u8(`R`), `I`, `F`, `F`]! {\n\t\treturn error('WAV should start with `RIFF`')\n\t}\n\tif rh.form_type != [u8(`W`), `A`, `V`, `E`]! {\n\t\treturn error('WAV should have `WAVE` form type')\n\t}\n\tif rh.file_size + 8 != bytes.len {\n\t\treturn error('WAV should have valid length')\n\t}\n\toffset += sizeof(RIFFHeader)\n\tmut rf := &RIFFFormat(unsafe { nil })\n\tfor {\n\t\tif offset >= bytes.len {\n\t\t\tbreak\n\t\t}\n\t\t//\n\t\tch := unsafe { &RIFFChunkHeader(pbytes + offset) }\n\t\toffset += 8 + ch.chunk_size\n\t\t// eprintln('ch: ${ch}')\n\t\t// eprintln('p: ${pbytes} | offset: ${offset} | bytes.len: ${bytes.len}')\n\t\t// ////////\n\t\tif ch.chunk_type == [u8(`L`), `I`, `S`, `T`]! {\n\t\t\tcontinue\n\t\t}\n\t\t//\n\t\tif ch.chunk_type == [u8(`i`), `d`, `3`, ` `]! {\n\t\t\tcontinue\n\t\t}\n\t\t//\n\t\tif ch.chunk_type == [u8(`f`), `m`, `t`, ` `]! {\n\t\t\t// eprintln('`fmt ` chunk')\n\t\t\trf = unsafe { &RIFFFormat(&ch.chunk_data) }\n\t\t\t// eprintln('fmt riff format: ${rf}')\n\t\t\tif rf.format_tag != 1 {\n\t\t\t\treturn error('only PCM encoded WAVs are supported')\n\t\t\t}\n\t\t\tif rf.nchannels < 1 || rf.nchannels > 2 {\n\t\t\t\treturn error('only mono or stereo WAVs are supported')\n\t\t\t}\n\t\t\tif rf.bits_per_sample !in [u16(8), 16] {\n\t\t\t\treturn error('only 8 or 16 bits per sample WAVs are supported')\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\t//\n\t\tif ch.chunk_type == [u8(`d`), `a`, `t`, `a`]! {\n\t\t\tif unsafe { rf == 0 } {\n\t\t\t\treturn error('`data` chunk should be after `fmt ` chunk')\n\t\t\t}\n\t\t\t// eprintln('`fmt ` chunk: ${rf}\\n`data` chunk: ${ch}')\n\t\t\tmut doffset := 0\n\t\t\tmut dp := unsafe { &u8(&ch.chunk_data) }\n\t\t\tfor doffset < ch.chunk_size {\n\t\t\t\tfor c := 0; c < rf.nchannels; c++ {\n\t\t\t\t\tmut x := f32(0.0)\n\t\t\t\t\tmut step := 0\n\t\t\t\t\tppos := unsafe { dp + doffset }\n\t\t\t\t\tif rf.bits_per_sample == 8 {\n\t\t\t\t\t\td8 := unsafe { &u8(ppos) }\n\t\t\t\t\t\tx = (f32(*d8) - 128) / 128.0\n\t\t\t\t\t\tstep = 1\n\t\t\t\t\t\tdoffset++\n\t\t\t\t\t}\n\t\t\t\t\tif rf.bits_per_sample == 16 {\n\t\t\t\t\t\td16 := unsafe { &i16(ppos) }\n\t\t\t\t\t\tx = f32(*d16) / 32768.0\n\t\t\t\t\t\tstep = 2\n\t\t\t\t\t}\n\t\t\t\t\tdoffset += step\n\t\t\t\t\tif doffset < ch.chunk_size {\n\t\t\t\t\t\tfor _ in 0 .. (44100 / rf.sample_rate) {\n\t\t\t\t\t\t\tres << x\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn res\n}\n"
  },
  {
    "path": "examples/spectral.v",
    "content": "/*\nhttps://benchmarksgame-team.pages.debian.net/benchmarksgame/performance/spectralnorm.html\nAdded: Pradeep Verghese\nBenchmarks:\nUsed v -prod spectral.v\nCommand: time ./spectral 5500\nOutput: 1.274224153\n\nTime: 11.67s user 0.02s system 99% cpu 11.721 total\n*/\nmodule main\n\nimport math\nimport os\nimport strconv\n\nfn evala(i int, j int) int {\n\treturn (i + j) * (i + j + 1) / 2 + i + 1\n}\n\nfn times(mut v []f64, u []f64) {\n\tfor i in 0 .. v.len {\n\t\tmut a := f64(0)\n\t\tfor j in 0 .. u.len {\n\t\t\ta += u[j] / f64(evala(i, j))\n\t\t}\n\t\tv[i] = a\n\t}\n}\n\nfn times_trans(mut v []f64, u []f64) {\n\tfor i in 0 .. v.len {\n\t\tmut a := f64(0)\n\t\tfor j in 0 .. u.len {\n\t\t\ta += u[j] / f64(evala(j, i))\n\t\t}\n\t\tv[i] = a\n\t}\n}\n\nfn a_times_transp(mut v []f64, u []f64) {\n\tmut x := []f64{len: u.len, init: 0}\n\ttimes(mut x, u)\n\ttimes_trans(mut v, x)\n}\n\nfn main() {\n\tmut n := 0\n\tif os.args.len == 2 {\n\t\tn = strconv.atoi(os.args[1]) or { 0 }\n\t} else {\n\t\tn = 0\n\t}\n\tmut u := []f64{len: n, init: 1}\n\tmut v := []f64{len: n, init: 1}\n\tfor _ in 0 .. 10 {\n\t\ta_times_transp(mut v, u)\n\t\ta_times_transp(mut u, v)\n\t}\n\tmut vbv := f64(0)\n\tmut vv := f64(0)\n\tfor i in 0 .. n {\n\t\tvbv += u[i] * v[i]\n\t\tvv += v[i] * v[i]\n\t}\n\tans := math.sqrt(vbv / vv)\n\tprintln('${ans:0.9f}')\n}\n"
  },
  {
    "path": "examples/ssl_server/cert/ca.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDbTCCAlWgAwIBAgIUTbcFMmB84wg6eqDRJbmo49aOTdMwDQYJKoZIhvcNAQEL\nBQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM\nGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAgFw0yMzA3MzAxNzM0MThaGA8yMDUw\nMTIxNDE3MzQxOFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx\nITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBANPfvg3G/3+j2NX5qDf0gw9iSnCiUa1T1inxlnfP\nvMVINDkH22yUSeValyuIrpF94m23ANo0yOXQJxbIt8PbwaRYTq1EzxlGkkXUHob3\nm1qJLH1qLacJeLMPj3J7kUXVWL65Qb7d2gtwMvegJ5I5U4ntLjXAmIV4z4PpZ2tP\nMsERacj/alb0EDS77P4JcbRzYvP/3FyFokel5TF/nLV3hXc5Eu6LjCzbEEus1MLd\nrgcpODUlw8Gf0M0nAjxijVpXAVo6XYRQ/00+zjPaKxjtQ/ds/O7zRTNxnUVvh1oH\nPnif9rkVBLkVjmSU/C7jvAKqrWPU9b24hXpnfSIirkn3tO8CAwEAAaNTMFEwHQYD\nVR0OBBYEFPx8Ivgj5Gi4XyHFZ/zGgZU4kGc7MB8GA1UdIwQYMBaAFPx8Ivgj5Gi4\nXyHFZ/zGgZU4kGc7MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB\nAJYSckwJSZlj8baEMvAJLs55Bm5wR1QZaj7mz8tBxK8zd9PdW3fTebil6jtGLpXT\nCHi+vaa5HsM2QXnYaZCSlawD3WWZ+LZ9lJVuWC+iWfRq6TC/gEd+3zCE70CeeAAu\n0pZC2Luvvgm5a6qfKoA4lEvlB2Yr0pX2GhXYOGvIeSMWpohKyKmiJEi83kJvzjnl\nBsFIR6FB1wO2+nrfLCzmjwPQx0ie2h+fPwf5Y2C0pPBYVwXpP94EEZW+lQgPXx5I\n6X8HPVNMtu4lToe746ctQlA4YDwge5mmiGUgF95Y3/O9Z2vjPqeN826oR89YFFZF\nJFtrrBskGW5fOzKOXLc96pE=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "examples/ssl_server/cert/client.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIEEzCCAvsCFG64Q2g46jZb3kRbDOJWX/BwjSp5MA0GCSqGSIb3DQEBCwUAMEUx\nCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl\ncm5ldCBXaWRnaXRzIFB0eSBMdGQwIBcNMjMwNzMwMTczNDQzWhgPMjA1MDEyMTQx\nNzM0NDNaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD\nVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEBAQUA\nA4ICDwAwggIKAoICAQDqDmHNMesBQ6S/ZU+xW4sO18Q+WfvXEaMdEfN5D8wyazP3\nmA7VTsNjliHrLFDiaTX9dR9Js+SwqmLpZTZoxBzn6wDuuM9fswvISnVERgZZdFas\nlkgci4iXVE2TREEqh6Ak4CAUyGiBhHm1CaT7txvq7wTghs+cgDR5hItK7EpxD7gv\njc1sNco9Ha1GecUB0L4fCmp3ss88vvDU4ta4eLTsW/SZbTKRMawih4hp00d0v83s\nOf5iIP6kWsM9X5Oe2Fm5XaObMlCdWHIBP2aB5i2ZqYUKTl8uKExpeobcsmpvHiSb\ntAAaeFo/5shyCAXx/i55KYA2oRm71XeIBnllIBMEfKPV3AReO6p+MZFnioPxUWY0\ngWqlSzsoLJ6NxHYWeC15OQhKQ6jEO7u3SAivacG5VVEywQ7EiY3b+ncwcZt9QK8q\nUckwwnbWHZJwJcp0vHj3/Mmvawm1dWR3CVauFW3ze/l3Ik92wJBDkULhv6r07zfv\nSlL2Am7+wPWfeOomx+Kh/rnGcXATcH17dVFH/mjhTjclOuM38e7oGoQhm9lZ9kaD\nwIuu1X0+XutuY55uze9yVY9qRSIJraBuZ9mreVIVj9FG0kpVplrTr7oBlGA1Nc3i\n1IuilE36T4qmP50WzJ6Yy38+J7My23bUyyOXIFhX/LTpPVjhZq5tVH+WmmqW0wID\nAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAbD+EVc4Ev7uXKUQV0s3nETp2odz1G8eZ/\ndrAVnWJpZEeWW98ZeVfyYglqWc9G8McYpiKeac9WF+gga8F2Cn3RjMvufqr0Ggcy\nbyytgJeLolukhTV/JJk8o+CUAB2xgk8+DVEiZ+7G4L/4V613VmL1B+jRHWknO/Js\nuArppuSduvmkakWOGMBGLUPUcep/vIepHByjOeq1czsdrsLokjBXjMAwXAVRSkBs\nmazD9yK95R5oG0KDmIPpfDddwvp7Xq4t3pTtMwXPYaDG+sPovsGsGYRkTnouOlKh\nae4/jRb8ut9AqOxZRUsBzT8MJXg4cFec8qrhPe3abzxN4amqOxlj\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "examples/ssl_server/cert/client.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIIJKAIBAAKCAgEA6g5hzTHrAUOkv2VPsVuLDtfEPln71xGjHRHzeQ/MMmsz95gO\n1U7DY5Yh6yxQ4mk1/XUfSbPksKpi6WU2aMQc5+sA7rjPX7MLyEp1REYGWXRWrJZI\nHIuIl1RNk0RBKoegJOAgFMhogYR5tQmk+7cb6u8E4IbPnIA0eYSLSuxKcQ+4L43N\nbDXKPR2tRnnFAdC+Hwpqd7LPPL7w1OLWuHi07Fv0mW0ykTGsIoeIadNHdL/N7Dn+\nYiD+pFrDPV+TnthZuV2jmzJQnVhyAT9mgeYtmamFCk5fLihMaXqG3LJqbx4km7QA\nGnhaP+bIcggF8f4ueSmANqEZu9V3iAZ5ZSATBHyj1dwEXjuqfjGRZ4qD8VFmNIFq\npUs7KCyejcR2FngteTkISkOoxDu7t0gIr2nBuVVRMsEOxImN2/p3MHGbfUCvKlHJ\nMMJ21h2ScCXKdLx49/zJr2sJtXVkdwlWrhVt83v5dyJPdsCQQ5FC4b+q9O8370pS\n9gJu/sD1n3jqJsfiof65xnFwE3B9e3VRR/5o4U43JTrjN/Hu6BqEIZvZWfZGg8CL\nrtV9Pl7rbmOebs3vclWPakUiCa2gbmfZq3lSFY/RRtJKVaZa06+6AZRgNTXN4tSL\nopRN+k+Kpj+dFsyemMt/PiezMtt21MsjlyBYV/y06T1Y4WaubVR/lppqltMCAwEA\nAQKCAgBCiqQzeiWdzmVgJKVrfuMh7SXVtC9tDY6aDShzGpKrIt87XPeanTHfdide\nfNLiC5dV355tjb9OmqJUSHoXfunY5W72b4RFaNnIr6J3LpFPjUu29WK6+tBydX04\niQcd2EEnOrDkN7W+XLNdTMii54QAXsO8MZeEns5MXepb+qGPUzDCFEZ6pTBB/9Xr\nW2MvCPGEUanDLgrM8lv1qifxeh+1ss7vb6QYs06E4pNdwrtl7cHVjwdLTqYWg9dN\n84Y8erXHhV+mF7/je+mtgSDbfV0pepBgRbe5n6tZsYP16qNnw+IUgjAlVmISGMKT\n6MQH8IO13p6c6WAvjpjVC0IoBd5htPzP8Il4bACKLr4IbLyAcdQvkWGUD2AfXmsM\nQB8zQA+HzFPLuoN6Yijp0ZUA3e+WN+fns9tHrrdrlBUUp39OwpOtx6S+DpN+AAmW\n8HPgESRJJ6b+mIrw60PLhGmpn/4tNk6c57EoqVM056uQcMCjhZRC3dKZl2LYhg9n\nNdtld2kb11iMuspbKKqBcizBye8nUxlvpa/HJfi5SoLxgaR5AfNgCekAE1TKHrDs\na51qhe0M4QRBnnlQl5Rxy4qUOZ+dwo+8nlZeDnCBKhWoBr3zNUie0YGO2g39zUzh\nl2DbL6tTVznhM69mgHi8T2uBUhxB2UYyfPqk0yLXlc8DNQs+QQKCAQEA90LY21jg\nnixJMXn/EMXvAEFoQul42iQuqyQLb9wLGmvA4Dqh+f+AWUlN8o7nLBGNv9ioDib6\nwDMv2gAFr0K5+5TvO0LvsBEuUgdX8wcmF30pJboETmj/fvTDp1BXTh2TfXD4toS7\nANWLERH68GGYFd9pMaxUALnqpJkcnAxRQjpof3ZgzWng4X7tGDwM6fZcf2Ahq/0J\n5qzP0VJgkkX6YvOF9+gIsyIWn2hiNlKtDITA+BqDg2Dx3XBrJQ9PDIfzspywFOw+\na1QdF5RHyzvLO5BMrg48GwGUQQurfA8HcPtLqoOKcHiuULn6pNF4lkqK+6Wuyg9L\nhPGPvP6T6wnvrwKCAQEA8lQPZTnSZaQnYV3EcHD+tmzGc7B5Qvn5MjG02XIZAZtc\nSstZK3HMi60NoK0UmAjtYIQWruhKCK31gRMhkrKXDoympwhRu965APglzNRyhNPg\nQ1Qr8Ux+QjccBbtmzc1H3EvGVLxUSBXB6gk4MzAF0W9FU2HU+0VnFjT6YbjbFuEB\n+2knKUIFc1O2v9B6MOc8HvXA2YqpSx9e60QOIxrBpPX5GDS2yEQbf9PLe4hY9RWT\n0tV7xMqrM5gyTmG4zwD9c3+QgDY9aoffcsqTCLPwzY+jpB8V2p6eno/sFhHtRqn3\nBxSlyiBTvWuqqa0C+4XjIbRiTp01Z2czpiRx+giQHQKCAQAmaz2Uv3ePPCRXSrRm\nH8smCAOyOeKsSmjx8JTSWadkAJAkhxe554hC11AEO04SG9whjgF2yXm2uX1a6xv3\nAnAxdg/B7oGdot3Goxt4SIkTpz/oe8HFiS0BxfhMnAAkxBWxrQcIHRGNbKDCE0Ah\nb5iY9XC75iHbRwf9cUjvuj46AydPfs5FvIjToMwoMtRy2fO/WumAdr2+GOXliV41\n/CeOjnYncedAJjDLrgVsmWYIBuyQ4FXE6SBLnvcW+Az5TnqAKzZ02cxNEvG+Qyzw\nmCbY52/yr4WJULJ/dNe9W/x1AqbcJLozBZ1YL72RNHb/Ky/zL+g7vyqlyn7iB9Bl\n+dJDAoIBAQCB2vfRB7YuT1PnAidVFcf4m7uQnR2t/WRDOI2wBEtQKB/B2Mw00quI\nobhuxLEHc6k4ki/RlJqvogCwJT9VbCw0WLypP3UFFqnO0ir3Y1Tmxt8jVUSi7pmu\nA/gZPj4txHZgn55tI+qKIlaigkRCcdZ8T4M31nIaICvIo6UUnsmQrgyw271nh4CC\nN3bzvNTtxcvaz1iDeqGTpwDnU7W7rAfezQypov3bvVt7GVSuIveAhgqL7WiAoRYy\n9Ljodcdh7ibjMJWPjwFESAE+cz1taXd9wB4xwZKlb2CSmY8qmHqs5kGA4tigwsf8\n9mgiupqhjDKViiMv+2B1w8DSpC8LjHElAoIBAHd9s9Dp7yjHQyMuJmpSxI2kowi0\nXF23xWgu9i0p2THGwHZW44KwNOjkKcj2jQqQY0xXj3Q6M4xTvNqVW+JxTnXhzyJJ\nC+xJfX+uWndyd3EKq7Bpzr0xAOW1g3n+Vfagul82kR2xf5QneObAXIpMqXWHvyYv\nRPQxZWilluRPKGek3N5W8/IHvARnqs/4vetWyL1BXjr6LmdCjhVCR+NMatdSfAJJ\ntEz+mVWfFzGaKJu16veh8i6iDG9LQ+/i6iNoHUovggb5Mt2QagIo6yaMqDNTQm7V\nZTHGSFjWif70uphM+JXSU5WcFEBsufVTFJKEnBf6c9hl8g5zqmxKwuGox1g=\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "examples/ssl_server/cert/makecerts.sh",
    "content": "# generates the certificates used by the server_sni_advanced.v example\n\n# default\ngen_key type=rsa rsa_keysize=4096 filename=0x.dk.key\ncert_write selfsign=1 issuer_key=0x.dk.key                    \\\n                         issuer_name=CN=0x.dk,O=0x,C=DK        \\\n                         not_before=20130101000000 not_after=20251231235959   \\\n                         is_ca=1 max_pathlen=0 output_file=0x.dk.crt\n\n# 1x.dk\ngen_key type=rsa rsa_keysize=4096 filename=1x.dk.key\ncert_write selfsign=1 issuer_key=1x.dk.key                    \\\n                         issuer_name=CN=1x.dk,O=1x.dk,C=DK        \\\n                         not_before=20130101000000 not_after=20251231235959   \\\n                         is_ca=1 max_pathlen=0 output_file=1x.dk.crt\n\n# 2x.dk\ngen_key type=rsa rsa_keysize=4096 filename=2x.dk.key\ncert_write selfsign=1 issuer_key=2x.dk.key                    \\\n                         issuer_name=CN=2x.dk,O=2x.dk,C=DK        \\\n                         not_before=20130101000000 not_after=20251231235959   \\\n                         is_ca=1 max_pathlen=0 output_file=2x.dk.crt\n"
  },
  {
    "path": "examples/ssl_server/cert/server.crt",
    "content": "No extensions in certificate\n-----BEGIN CERTIFICATE-----\nMIIEOTCCAyECFG64Q2g46jZb3kRbDOJWX/BwjSp4MA0GCSqGSIb3DQEBCwUAMEUx\nCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl\ncm5ldCBXaWRnaXRzIFB0eSBMdGQwIBcNMjMwNzMwMTczNDE4WhgPMjA1MDEyMTQx\nNzM0MThaMGsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYD\nVQQHDAtMb3MgQW5nZWxlczEdMBsGA1UECgwUQ2F0YWx5c3QgRGV2ZWxvcG1lbnQx\nEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC\nggIBAKUcJ5cizbhreUlC0plQngCeE+/ysZJo8TmnhEF4cFnTVCHmvzz7f5w7/Zma\n4maRzE3KT52qSA2PkX6Wr9RgnM93K93a3dfiUHaZ+DbWFnb1w/gp7TG5bgvwfjcb\nKVnkP+BIMbT90kQrLI0H89LrouvCHDvl74EvAdyYgupLTdjZ5Q5Xe9P5rUhLajw6\niN8+NtfrQh2hDOWnbg9nQK/zjIVvvvjMQOUzda9Rq4ViAphiLNufojQhHJrlIpkP\noR+YENiDXRcaire5RVWjzfoQGDbTJLJL8fNV1HMjJArUuCg8yIyL1wooe+XWqscg\nMzJoiCjSdai5zTF+lzcBLrm0olqB7YDCHS3x3K4C3DDRSoyFSEHRQpbSQbc6jTo6\nTuWcC9o/5fIMzzHrahqoRZG7syFyHYNtezhsFobqMX4E15gV6tBf6CMpTlXMH3ss\nDreZl900n1UcNtp7aQw2JIdRrLMW2I6UAit1o/FBYjkg/QCqPL7lw1nv0COraI74\nCU+I7opYJJgEalOkZciapB6ARMgWD1/J9qO4q98H0jETP1bh78lwLPxRe1W5fukD\nYCazJONIt4Bgdff8C2r+KhEoWQxK5VnjIdbL9E1nxscPr/4U77siCmHKdPINCrsD\nCWqxUHiuyJmkw9NCrerZoIxTBFAUc+sdibvq1M528jf1IvXXAgMBAAEwDQYJKoZI\nhvcNAQELBQADggEBAGoxRyyY+YraVOlFMzmyf+TeCQVibOJvKmY/HUjqCujgoj6o\n7UwYDAPyfzuVerDj2IzJ9bFB818iOIQUaO8Gw70EOzDifZFCm9/pET3SD7aGd4Kk\nDjCbjml/MNidVezPXNcdAM+XJ56jd2owk/pB4jaw3bkNcmn0aSnFg421fZibrTcS\nVRPCHIvV8gSqJk9ENO5EGIGU1VmTR909aIYB2fYyyW/1fyP/gn7d1Afy8CimZ1uD\nmUl5qQ5/CY378MmnODiGhsHJeH+ws77yLPwnh8eVtISwYMu9qfNRYFnotK7a5mxU\nCWpoSR77NmCUCQOarzb34soL2zZlIK9Lx+4VQPo=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "examples/ssl_server/cert/server.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIIJKAIBAAKCAgEApRwnlyLNuGt5SULSmVCeAJ4T7/KxkmjxOaeEQXhwWdNUIea/\nPPt/nDv9mZriZpHMTcpPnapIDY+Rfpav1GCcz3cr3drd1+JQdpn4NtYWdvXD+Cnt\nMbluC/B+NxspWeQ/4EgxtP3SRCssjQfz0uui68IcO+XvgS8B3JiC6ktN2NnlDld7\n0/mtSEtqPDqI3z421+tCHaEM5aduD2dAr/OMhW+++MxA5TN1r1GrhWICmGIs25+i\nNCEcmuUimQ+hH5gQ2INdFxqKt7lFVaPN+hAYNtMkskvx81XUcyMkCtS4KDzIjIvX\nCih75daqxyAzMmiIKNJ1qLnNMX6XNwEuubSiWoHtgMIdLfHcrgLcMNFKjIVIQdFC\nltJBtzqNOjpO5ZwL2j/l8gzPMetqGqhFkbuzIXIdg217OGwWhuoxfgTXmBXq0F/o\nIylOVcwfeywOt5mX3TSfVRw22ntpDDYkh1GssxbYjpQCK3Wj8UFiOSD9AKo8vuXD\nWe/QI6tojvgJT4juilgkmARqU6RlyJqkHoBEyBYPX8n2o7ir3wfSMRM/VuHvyXAs\n/FF7Vbl+6QNgJrMk40i3gGB19/wLav4qEShZDErlWeMh1sv0TWfGxw+v/hTvuyIK\nYcp08g0KuwMJarFQeK7ImaTD00Kt6tmgjFMEUBRz6x2Ju+rUznbyN/Ui9dcCAwEA\nAQKCAgA9xjLp0RO3FD7ksiOpSQhUotBCzkKxzKG0OIC7Hhyq/u5TYMncPxyXj7pq\nZhCe353Y3QC8tKEQsc511lsi0qLY3HWFJAYsZ3hDZ4f+vErbZ0hS6RzdpcsOnIQc\nigUGpOdhOqGeXfj1mFGq0nbfS1pBava1UmoxoyzHJCiXEGWn5J5Wp1SlEp1KlyzA\nLAZZwCU008iA3Wi9487B5JfHPRAuPIju/TyqhH5bgerylKDz8odmBGvjpR/WtDQl\noDtgXryuxTdnFX8hDihqykaecLcejBEGxHNZ35sFGPi7NKtSIqvGKevi2RLCA3cR\n2XJOQd3vqA5telbTVdGturuIr5SuPmZgSTQM4PnbuzmwFaXZH6REBLsRkDYHUQsE\nnGKyh81Out2taBeJUoJ+CCuGmVsWU3UfRhOHMatSi+aasK3P1My1H2uCYzIpaUBG\nrQKOqJsuwQsAejkZ0b3D8s6Y1BoQey7qmwlNhmZ4pw0tdQsOyvht2ZwmU6U0cTXu\nLtaqwSWC6oz5yepVFGpF6FfuPHD7UrznGuFfiyONIxExqW5yYF+JjUdYg3At2kiX\nPv4IpfSbXu9Fivbw90zWGc+RrmtXmf3ZzAW4nD9tHNpz9EPDfYIiW3vYnYxWbWX8\noVqIz2/FLrOa+c0ZO0TBCHY0NFQ0tz1WCjz1Nc0sDbGuQsngAQKCAQEAzlkndsaj\nTIlBWveSd4dmGKTdKyo1xKeE1FhHw5YoOX3xjqrPLTUS9Dy04R8LGRQmceUyuGmL\nJBk6Ab0lAxuT4YpADBh8uXn5xBI/BjETby3x0511Dmfi8m0mwgGYJeWk9vPACTvI\nKLzvDF8FjLw/AMjpG62oHnGvVUTfwR5fw7o32yLkVZ5dBVXLp5z0wnT6lzICIzCr\nsQNpaNBoUkSNLQYvBsD97fJt2FzfLb3QWIf4ld6joP1236LfanJTOmYofS4RkC6h\nRkg6onlSEAvOXCKggRAX1XlHn73tehkMpndR/9xpfmO+E5Tz4Sx/WTiwXVKlJ41/\n2HUcGkTJOlRf1wKCAQEAzNbDim/JJw0hw/vjGPgzUC8XC4Ciavxs9YJQhIKgtdRA\nTosmJ3bb9UzL+6us6+/rECMSXYHLS6NijHuhAvtn0jCEgeja/JpYkkQG+MAJHN0a\n8XwjUce938T2PGZMxdk3Kdbhpgvfq5OUELPOk2mPO/YKOJDPIwSqZJBwRXvVYPkl\nImJ14wodjnKwVLCQWKw5XonoDWs8o6XeCkTN56ZjpzHUvptKiIdOK5GcLBwI+CrP\nRBExqwtMQkR9ecQmhaiocjNb7roH0GzqTPMTdNP26ZqS2B8/QFpsbyzKyRgEvCm0\nBXHkVmaQ4PC+tGO3AOQAe7klzwgvLimN1Q8HyCtaAQKCAQEAg+9PI0uId9Q+nFo1\nJQXGirVG0GWRsWZmsJqtb+nfWDslqtGd28rWjqEOCe6eWu+eUS55yp15IKCcjSYR\ntzX3zLpnjxRNEw5hWzNLZrsUMP8QYvyHLqnP2q9dm6gHTxvQ6TEatQyrQxjiQ2ey\nFbT7F5ZeLZtQJf8MWxnJcyHnmy7CrfNWSUQTN+kOaOIbQQYof2mzIirpbCnBSQoP\n2aIJHiOZB9l3wp9CCpf+/rEhuKlfkPukZbgKPJ1X+iiU/H77HmbJRgX6igR+sQmf\nJbFWxWRCeaL/ijecSw/V+j5v7zPVkyGrtesySjTv5iZcWoC7iz/fZzW663yddlJK\n02fFSwKCAQBTqIroKUuQJW7a6i8P7Z6XawQQcJLk+v9NLdHQrMESQgOZkH8esw6W\nmqzctnrDSZNJXemMQwxScgI3ue5Cl4cJc0NLA10cubTe1+W5BkUygqMUaUzLg7Zq\ng7jFZkqIq3Q6JEa4WDUbkARy5dzCm+Qh6xS1kX7noGou9EbGOhMlrduatXfMKD92\nBCU8EXiCnqQ3lj8t69QySfXrX7pwl6YvjMyEpEvGguxMIwYThcesA1/vPs54Ov8E\nOZC9gHzzLbTOH2e2kkfKuhDfKI+TsVYwhi7fEbP1hniu1y5i/upAJxAdASzulKkr\nFWftqKP/Ox9vaGimq4MJaXNBxwe4muwBAoIBAGPQnHogL1ZpS/sMhq3OyQyq40+K\n+GBWaziwPqDZpFvRx6y1KsTlKbdHI3lo9fuh2B+gxKh4ogM/5KBH0FlbbQdUxifk\nmsp33RH4C3zHt/EhPs01bGCPv2Iam40Q5X5exPMRNUG7OefEbahX5lnDUcBmeQpM\nBniOBwauG8sjQIKX0aU7e9ucfCLU6GqWIxylqJD+abDl0T2Bu5S5GLg3dWJfHCe1\n9ixWRbCodV04FZnsgY8jE7M70TjKAk2SIlMDbSdhsSa3sfEI5/hBxQSpiINTb9Vs\nYpjAuHLFnwTLx0HJ2L8lTLj6Q8lSH58PAzJml35TzPKOJ37Kwl3Hu4aaMr8=\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "examples/ssl_server/client.v",
    "content": "import io\nimport os\nimport net.mbedtls\n\nfn main() {\n\tmut client := mbedtls.new_ssl_conn(mbedtls.SSLConnectConfig{\n\t\tverify:   os.resource_abs_path('cert/ca.crt')\n\t\tcert:     os.resource_abs_path('cert/client.crt')\n\t\tcert_key: os.resource_abs_path('cert/client.key')\n\t\tvalidate: true\n\t})!\n\n\tclient.dial('localhost', 8443)!\n\tclient.write_string('GET / HTTP/1.1\\r\\n\\r\\n')!\n\tmut reader := io.new_buffered_reader(reader: client)\n\tprintln(reader.read_line()!)\n}\n"
  },
  {
    "path": "examples/ssl_server/server.v",
    "content": "import io\nimport os\nimport net.mbedtls\n\nfn main() {\n\tmut server := mbedtls.new_ssl_listener('0.0.0.0:8443', mbedtls.SSLConnectConfig{\n\t\tverify:   os.resource_abs_path('cert/ca.crt')\n\t\tcert:     os.resource_abs_path('cert/server.crt')\n\t\tcert_key: os.resource_abs_path('cert/server.key')\n\t\tvalidate: true // mTLS\n\t})!\n\n\tmut client := server.accept()!\n\tmut reader := io.new_buffered_reader(reader: client)\n\tmut request := reader.read_line()!\n\tprintln(request)\n\tclient.write_string('HTTP/1.1 200 OK\\r\\n')!\n\tclient.shutdown()!\n\tserver.shutdown()!\n}\n"
  },
  {
    "path": "examples/ssl_server/server_sni.v",
    "content": "import io\nimport os\nimport net.mbedtls\n\n// This example shows a very minimal HTTP server, that supports SNI.\n// Server Name Indication (SNI) is defined in RFC 6066.\n// See https://mbed-tls.readthedocs.io/en/latest/kb/how-to/use-sni/\n\n// Use the following commands, in separate shells, to test that it works,\n// after you start the server:\n//   curl -ik --resolve 1x.dk:8443:0.0.0.0        https://1x.dk:8443/abcd\n//   curl -ik --resolve example.com:8443:0.0.0.0  https://example.com:8443/xyz\n// Both of them should work, and the server should show that it tried to load\n// certificates, responding to the given domain name in each of the requests.\n\n// callback to return the certificates to use for the connection\nfn get_cert(mut _listener mbedtls.SSLListener, host string) !&mbedtls.SSLCerts {\n\tprintln('reading certificates for ${host} ...')\n\n\t// For our example, just always use the same certificates. In a real server,\n\t// that should be dependent on the host parameter, and perhaps there should\n\t// be some caching, so that they are not read each time for each request from\n\t// the filesystem.\n\n\tcert := os.read_file('cert/server.crt') or {\n\t\treturn error('Failed to read certificate ${host}: ${err}')\n\t}\n\tkey := os.read_file('cert/server.key') or { return error('Failed to read key ${host}: ${err}') }\n\tprintln('read certs for ${host}')\n\n\tif mut c := mbedtls.new_sslcerts_in_memory('', cert, key) {\n\t\treturn c\n\t} else {\n\t\treturn error('mbedtls.new_sslcerts_in_memory err: ${err}')\n\t}\n}\n\nfn main() {\n\tmut server := mbedtls.new_ssl_listener('0.0.0.0:8443', mbedtls.SSLConnectConfig{\n\t\tverify:          os.resource_abs_path('cert/ca.crt')\n\t\tcert:            os.resource_abs_path('cert/server.crt')\n\t\tcert_key:        os.resource_abs_path('cert/server.key')\n\t\tvalidate:        false\n\t\tget_certificate: get_cert // set the SNI callback to enable this feature\n\t})!\n\tprintln('Listening on https://0.0.0.0:8443/ ...')\n\tfor {\n\t\tmut client := server.accept() or {\n\t\t\tprintln('accept error: ${err}')\n\t\t\tcontinue\n\t\t}\n\t\tmut reader := io.new_buffered_reader(reader: client)\n\t\tfor {\n\t\t\tline := reader.read_line() or { break }\n\t\t\tif line.len == 0 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tprintln(line)\n\t\t}\n\t\tclient.write_string('HTTP/1.1 200 OK\\r\\n') or { continue }\n\n\t\tclient.write_string('Content-Type: text/html\\r\\n') or { continue }\n\t\tclient.write_string('Connection: close\\r\\n') or { continue }\n\t\tclient.write_string('\\r\\n') or { continue }\n\n\t\tclient.write_string('Hello\\n') or { continue }\n\t\tclient.shutdown()!\n\t}\n\tserver.shutdown()!\n}\n"
  },
  {
    "path": "examples/ssl_server/server_sni_advanced.v",
    "content": "import net.mbedtls\nimport os\nimport io\nimport net.http\n\n// first run cert/makecerts.sh to generate the certificates for this server\n\n// start the server with:\n// v run server_sni_advanced.v\n\n// test using curl:\n\n// connection using the 1x.dk certificate\n// curl -vik --resolve 1x.dk:8443:0.0.0.0 https://1x.dk:8443/\n\n// connection using the 2x.dk certificate\n// curl -vik --resolve 2x.dk:8443:0.0.0.0 https://2x.dk:8443/\n\n// default certificate (no sni callback)\n// curl -vik https://0.0.0.0:8443/\n\n@[heap]\nstruct CertManager {\nmut:\n\t// cache for the certificates\n\tcerts map[string]&mbedtls.SSLCerts\n}\n\nfn (mut cm CertManager) get_cert(mut _l mbedtls.SSLListener, host string) !&mbedtls.SSLCerts {\n\tprintln('${host}')\n\n\tif c := cm.certs[host] {\n\t\tprintln('read certs for ${host} already ready')\n\t\treturn c\n\t} else {\n\t\tcert := os.read_file('cert/${host}.crt') or {\n\t\t\treturn error('Failed to read certificate ${host}: ${err}')\n\t\t}\n\t\tkey := os.read_file('cert/${host}.key') or {\n\t\t\treturn error('Failed to read key ${host}: ${err}')\n\t\t}\n\t\tprintln('read certs for ${host}')\n\n\t\tif mut c := mbedtls.new_sslcerts_in_memory('', cert, key) {\n\t\t\tcm.certs[host] = c\n\t\t\treturn c\n\t\t} else {\n\t\t\treturn error('mbedtls.new_sslcerts_in_memory err: ${err}')\n\t\t}\n\t}\n}\n\nfn main() {\n\t// Load the default certificates\n\tcert := os.read_file('cert/0x.dk.crt') or {\n\t\teprintln('Failed to read certificate: ${err}')\n\t\treturn\n\t}\n\tkey := os.read_file('cert/0x.dk.key') or {\n\t\teprintln('Failed to read key: ${err}')\n\t\treturn\n\t}\n\n\tcm := CertManager{}\n\n\t// Create the SSL configuration\n\tmut config := mbedtls.SSLConnectConfig{\n\t\tcert:                   cert\n\t\tcert_key:               key\n\t\tin_memory_verification: true // !importent\n\t\tget_certificate:        cm.get_cert\n\t}\n\n\tmut server := mbedtls.new_ssl_listener('0.0.0.0:8443', config) or {\n\t\tprintln('new_ssl_listener : ${err.msg()} : ${err.code()}')\n\t\treturn\n\t}\n\tprintln('Listening on https://0.0.0.0:8443')\n\n\t// Accept and handle connections\n\tfor {\n\t\tmut client := server.accept() or {\n\t\t\tprintln('accept : ${err.msg()} : ${err.code()}')\n\t\t\tcontinue\n\t\t}\n\t\tgo handle_connection(mut client)\n\t}\n\n\tserver.shutdown() or {\n\t\tprintln('server.shutdown : ${err.msg()} : ${err.code()}')\n\t\treturn\n\t}\n}\n\nfn handle_connection(mut ssl_conn mbedtls.SSLConn) {\n\tmut reader := io.new_buffered_reader(reader: ssl_conn)\n\n\trequest := http.parse_request(mut reader) or {\n\t\tprintln('parse_request failed : ${err}')\n\t\treturn\n\t}\n\n\tprintln('Received request: ${request.url}')\n\n\t// Respond to the request\n\tbody := 'Hello, HTTPS!'\n\tres := http.new_response(http.ResponseConfig{\n\t\tbody: body\n\t})\n\n\tssl_conn.write(res.bytes()) or {\n\t\teprintln('Failed to write response: ${err}')\n\t\treturn\n\t}\n\n\tssl_conn.shutdown() or {\n\t\teprintln('Failed to shutdown connection: ${err}')\n\t\treturn\n\t}\n}\n"
  },
  {
    "path": "examples/submodule/main.v",
    "content": "import mymodules { add_xy }\nimport mymodules.submodule { sub_xy }\n\nfn main() {\n\tprintln(add_xy(2, 3)) // expected: 5\n\tprintln(sub_xy(10, 7)) // expected: 3\n}\n"
  },
  {
    "path": "examples/submodule/mymodules/main_functions.v",
    "content": "module mymodules\n\npub fn add_xy(x int, y int) int {\n\treturn x + y\n}\n"
  },
  {
    "path": "examples/submodule/mymodules/submodule/sub_functions.v",
    "content": "module submodule\n\npub fn sub_xy(x int, y int) int {\n\treturn x - y\n}\n"
  },
  {
    "path": "examples/submodule/v.mod",
    "content": "Module {\n\tname: 'submodule'\n\tdescription: ''\n\tversion: ''\n\tlicense: ''\n\tdependencies: []\n}\n"
  },
  {
    "path": "examples/sudoku.v",
    "content": "fn main() {\n\tmut grid := [\n\t\t[0, 3, 0, 0, 7, 0, 0, 0, 0],\n\t\t[0, 0, 0, 1, 3, 5, 0, 0, 0],\n\t\t[0, 0, 1, 0, 0, 0, 0, 5, 0],\n\t\t[1, 0, 0, 0, 6, 0, 0, 0, 3],\n\t\t[4, 0, 0, 8, 0, 3, 0, 0, 1],\n\t\t[7, 0, 0, 0, 2, 0, 0, 0, 6],\n\t\t[0, 0, 0, 0, 0, 0, 2, 1, 0],\n\t\t[0, 0, 0, 4, 1, 2, 0, 0, 5],\n\t\t[0, 0, 0, 0, 0, 0, 0, 7, 4],\n\t]\n\tprint_grid('Sudoku Puzzle:', grid)\n\tprintln('Solving...')\n\tif solve_sudoku(mut grid) {\n\t\tprint_grid('Solution:', grid)\n\t} else {\n\t\tprintln('No solution exists.')\n\t\texit(1)\n\t}\n}\n\n// is_valid checks if placing `num` at grid[row][col] is valid\nfn is_valid(grid [][]int, row int, col int, num int) bool {\n\t// check the row, if the number has been placed already:\n\tfor x := 0; x < 9; x++ {\n\t\tif grid[row][x] == num {\n\t\t\treturn false\n\t\t}\n\t}\n\t// check column\n\tfor x := 0; x < 9; x++ {\n\t\tif grid[x][col] == num {\n\t\t\treturn false\n\t\t}\n\t}\n\t// check 3x3 subgrid\n\tstart_row := row - row % 3\n\tstart_col := col - col % 3\n\tfor i := 0; i < 3; i++ {\n\t\tfor j := 0; j < 3; j++ {\n\t\t\tif grid[i + start_row][j + start_col] == num {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\treturn true\n}\n\n// find_empty finds an empty cell (0) in the grid:\nfn find_empty(grid [][]int) ?(int, int) {\n\tfor i := 0; i < 9; i++ {\n\t\tfor j := 0; j < 9; j++ {\n\t\t\tif grid[i][j] == 0 {\n\t\t\t\treturn i, j\n\t\t\t}\n\t\t}\n\t}\n\treturn none\n}\n\n// solve_sudoku solves the Sudoku puzzle using backtracking\nfn solve_sudoku(mut grid [][]int) bool {\n\t// If there is no empty cell, the puzzle is solved:\n\trow, col := find_empty(grid) or { return true }\n\t// Try placing all the digits in turn in the empty cell:\n\tfor num := 1; num <= 9; num++ {\n\t\tif is_valid(grid, row, col, num) {\n\t\t\tgrid[row][col] = num\n\t\t\t// Recursively try to solve the rest\n\t\t\tif solve_sudoku(mut grid) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\t// We could not find a solution using this number,\n\t\t\t// so backtrack and try another number instead:\n\t\t\tgrid[row][col] = 0\n\t\t}\n\t}\n\treturn false\n}\n\n// print_grid prints a labeled Sudoku grid\nfn print_grid(label string, grid [][]int) {\n\tprintln(label)\n\tfor i := 0; i < 9; i++ {\n\t\tif i % 3 == 0 && i != 0 {\n\t\t\tprintln('- - - - - - - - - - - -')\n\t\t}\n\t\tfor j := 0; j < 9; j++ {\n\t\t\tif j % 3 == 0 && j != 0 {\n\t\t\t\tprint(' | ')\n\t\t\t}\n\t\t\tprint('${grid[i][j]} ')\n\t\t}\n\t\tprintln('')\n\t}\n}\n"
  },
  {
    "path": "examples/sync_pool.v",
    "content": "// This example illustrates how to use `sync.pool`,\n// and how the various settings for VJOBS, work items etc can interact.\n@[has_globals]\nmodule main\n\nimport log\nimport time\nimport runtime\nimport sync.pool\n\nconst args = arguments()\nconst nitems = args[1] or { '10' }.int()\nconst njobs = args[2] or { runtime.nr_jobs().str() }.int()\nconst delay = args[3] or { '1000' }.int()\n\n__global msgs = chan string{cap: 1000}\n\nfn worker_sleep(mut p pool.PoolProcessor, item_idx int, worker_id int) voidptr {\n\titem := p.get_item[int](item_idx)\n\tmsgs <- '# worker_id: ${worker_id:3}, item_idx: ${item_idx + 1:03}, item: ${item:6}, started'\n\ttime.sleep(delay * time.millisecond)\n\tmsgs <- '# worker_id: ${worker_id:3}, item_idx: ${item_idx + 1:03}, item: ${item:6}, finished.'\n\treturn pool.no_result\n}\n\nfn logger() {\n\tfor {\n\t\tmsg := <-msgs\n\t\tlog.info(msg)\n\t\tif msg == '>>> done' {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfn main() {\n\tt := spawn logger()\n\tmsgs <- '>>> nitems: ${nitems:6} | njobs: ${njobs:6} | delay_ms: ${delay:6}'\n\titems := []int{len: nitems, init: index * 1000}\n\tmut fetcher_pool := pool.new_pool_processor(callback: worker_sleep)\n\tfetcher_pool.work_on_items(items)\n\tmsgs <- '>>> done'\n\tt.wait()\n}\n"
  },
  {
    "path": "examples/tcp_echo_server.v",
    "content": "import io\nimport net\n\n// This file shows how a basic TCP echo server can be implemented using\n// the net module. You can connect to the server by using netcat or telnet,\n// in separate shells, for example:\n// nc 127.0.0.1 12345\n// or\n// telnet 127.0.0.1 12345\n\nfn main() {\n\tmut server := net.listen_tcp(.ip6, ':12345')!\n\tladdr := server.addr()!\n\teprintln('Listen on ${laddr} ...')\n\tfor {\n\t\tmut socket := server.accept()!\n\t\tspawn handle_client(mut socket)\n\t}\n}\n\nfn handle_client(mut socket net.TcpConn) {\n\tdefer {\n\t\tsocket.close() or { panic(err) }\n\t}\n\tclient_addr := socket.peer_addr() or { return }\n\teprintln('> new client: ${client_addr}')\n\tmut reader := io.new_buffered_reader(reader: socket)\n\tdefer {\n\t\tunsafe {\n\t\t\treader.free()\n\t\t}\n\t}\n\tsocket.write_string('server: hello\\n') or { return }\n\tfor {\n\t\treceived_line := reader.read_line() or { return }\n\t\tif received_line == '' {\n\t\t\treturn\n\t\t}\n\t\tprintln('client ${client_addr}: ${received_line}')\n\t\tsocket.write_string('server: ${received_line}\\n') or { return }\n\t}\n}\n"
  },
  {
    "path": "examples/tcp_notify_echo_server.v",
    "content": "import os\nimport os.notify\nimport net\nimport time\n\n// This example demonstrates a single threaded TCP server using os.notify to be\n// notified of events on file descriptors. You can connect to the server using\n// netcat in separate shells, for example: `nc localhost 9001`\n\nfn main() {\n\t$if !linux {\n\t\teprintln('This example only works on Linux')\n\t\texit(1)\n\t}\n\n\t// create TCP listener\n\tmut listener := net.listen_tcp(.ip, 'localhost:9001')!\n\tdefer {\n\t\tlistener.close() or {}\n\t}\n\taddr := listener.addr()!\n\teprintln('Listening on ${addr}')\n\teprintln('Type `stop` to stop the server')\n\n\t// create file descriptor notifier\n\tmut notifier := notify.new()!\n\tdefer {\n\t\tnotifier.close() or {}\n\t}\n\tnotifier.add(os.stdin().fd, .read)!\n\tnotifier.add(listener.sock.handle, .read)!\n\n\tfor {\n\t\tfor event in notifier.wait(time.infinite) {\n\t\t\tmatch event.fd {\n\t\t\t\tlistener.sock.handle {\n\t\t\t\t\t// someone is trying to connect\n\t\t\t\t\teprint('trying to connect.. ')\n\t\t\t\t\tif conn := listener.accept() {\n\t\t\t\t\t\tnotifier.add(conn.sock.handle, .read | .peer_hangup) or {\n\t\t\t\t\t\t\teprintln('error adding to notifier: ${err}')\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\teprintln('connected')\n\t\t\t\t\t} else {\n\t\t\t\t\t\teprintln('unable to accept: ${err}')\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t0 {\n\t\t\t\t\t// stdin\n\t\t\t\t\ts, _ := os.fd_read(event.fd, 10)\n\t\t\t\t\tif s == 'stop\\n' {\n\t\t\t\t\t\teprintln('stopping')\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// remote connection\n\t\t\t\t\tif event.kind.has(.peer_hangup) {\n\t\t\t\t\t\tnotifier.remove(event.fd) or {\n\t\t\t\t\t\t\teprintln('error removing from notifier: ${err}')\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\teprintln('remote disconnected')\n\t\t\t\t\t} else {\n\t\t\t\t\t\ts, _ := os.fd_read(event.fd, 10)\n\t\t\t\t\t\tos.fd_write(event.fd, s)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/templates/data.json",
    "content": "[\n    {\n        \"name\": \"www_threefold_io\",\n        \"url\": \"https://github.com/threefoldfoundation/www_threefold_io\",\n        \"branch\": \"default\",\n        \"pull\": false,\n        \"cat\": 2,\n        \"alias\": \"tf\",\n        \"path_code\": \"/Users/despiegk/codewww/github/threefoldfoundation/www_threefold_io\",\n        \"domains\": [\n            \"www.threefold.io\",\n            \"www.threefold.me\"\n        ],\n        \"descr\": \"is our entry point for everyone, redirect to the detailed websites underneath.\"\n    },\n    {\n        \"name\": \"www_threefold_cloud\",\n        \"url\": \"https://github.com/threefoldfoundation/www_threefold_cloud\",\n        \"branch\": \"default\",\n        \"pull\": false,\n        \"cat\": 2,\n        \"alias\": \"cloud\",\n        \"path_code\": \"/Users/despiegk/codewww/github/threefoldfoundation/www_threefold_cloud\",\n        \"domains\": [\n            \"cloud.threefold.io\",\n            \"cloud.threefold.me\"\n        ],\n        \"descr\": \"for people looking to deploy solutions on top of a cloud, alternative to e.g. digital ocean\"\n    },\n    {\n        \"name\": \"www_threefold_farming\",\n        \"url\": \"https://github.com/threefoldfoundation/www_threefold_farming\",\n        \"branch\": \"default\",\n        \"pull\": false,\n        \"cat\": 2,\n        \"alias\": \"farming\",\n        \"path_code\": \"/Users/despiegk/codewww/github/threefoldfoundation/www_threefold_farming\",\n        \"domains\": [\n            \"farming.threefold.io\",\n            \"farming.threefold.me\"\n        ],\n        \"descr\": \"crypto & minining enthusiasts, be the internet, know about farming & tokens.\"\n    },\n    {\n        \"name\": \"www_threefold_twin\",\n        \"url\": \"https://github.com/threefoldfoundation/www_threefold_twin\",\n        \"branch\": \"default\",\n        \"pull\": false,\n        \"cat\": 2,\n        \"alias\": \"twin\",\n        \"path_code\": \"/Users/despiegk/codewww/github/threefoldfoundation/www_threefold_twin\",\n        \"domains\": [\n            \"twin.threefold.io\",\n            \"twin.threefold.me\"\n        ],\n        \"descr\": \"you digital life\"\n    },\n    {\n        \"name\": \"www_threefold_marketplace\",\n        \"url\": \"https://github.com/threefoldfoundation/www_threefold_marketplace\",\n        \"branch\": \"default\",\n        \"pull\": false,\n        \"cat\": 2,\n        \"alias\": \"marketplace\",\n        \"path_code\": \"/Users/despiegk/codewww/github/threefoldfoundation/www_threefold_marketplace\",\n        \"domains\": [\n            \"now.threefold.io\",\n            \"marketplace.threefold.io\",\n            \"now.threefold.me\",\n            \"marketplace.threefold.me\"\n        ],\n        \"descr\": \"apps for community builders, runs on top of evdc\"\n    },\n    {\n        \"name\": \"www_conscious_internet\",\n        \"url\": \"https://github.com/threefoldfoundation/www_conscious_internet\",\n        \"branch\": \"default\",\n        \"pull\": false,\n        \"cat\": 2,\n        \"alias\": \"conscious_internet\",\n        \"path_code\": \"/Users/despiegk/codewww/github/threefoldfoundation/www_conscious_internet\",\n        \"domains\": [\n            \"www.consciousinternet.org\",\n            \"eco.threefold.io\",\n            \"community.threefold.io\",\n            \"eco.threefold.me\",\n            \"community.threefold.me\"\n        ],\n        \"descr\": \"community around threefold, partners, friends, ...\"\n    },\n    {\n        \"name\": \"www_threefold_tech\",\n        \"url\": \"https://github.com/threefoldtech/www_threefold_tech\",\n        \"branch\": \"default\",\n        \"pull\": false,\n        \"cat\": 2,\n        \"alias\": \"tech\",\n        \"path_code\": \"/Users/despiegk/codewww/github/threefoldtech/www_threefold_tech\",\n        \"domains\": [\n            \"www.threefold.tech\"\n        ],\n        \"descr\": \"cyberpandemic, use the tech to build your own solutions with, certification for TFGrid\"\n    },\n    {\n        \"name\": \"www_examplesite\",\n        \"url\": \"https://github.com/threefoldfoundation/www_examplesite\",\n        \"branch\": \"default\",\n        \"pull\": false,\n        \"cat\": 2,\n        \"alias\": \"example\",\n        \"path_code\": \"/Users/despiegk/codewww/github/threefoldfoundation/www_examplesite\",\n        \"domains\": [\n            \"example.threefold.io\"\n        ],\n        \"descr\": \"\"\n    },\n    {\n        \"name\": \"info_threefold\",\n        \"url\": \"https://github.com/threefoldfoundation/info_foundation_archive\",\n        \"branch\": \"default\",\n        \"pull\": false,\n        \"cat\": 0,\n        \"alias\": \"threefold\",\n        \"path_code\": \"/Users/despiegk/codewww/github/threefoldfoundation/info_foundation_archive\",\n        \"domains\": [\n            \"info.threefold.io\"\n        ],\n        \"descr\": \"wiki for foundation, collaborate, what if farmings, tokens\"\n    },\n    {\n        \"name\": \"info_sdk\",\n        \"url\": \"https://github.com/threefoldfoundation/info_sdk\",\n        \"branch\": \"default\",\n        \"pull\": false,\n        \"cat\": 0,\n        \"alias\": \"sdk\",\n        \"path_code\": \"/Users/despiegk/codewww/github/threefoldfoundation/info_sdk\",\n        \"domains\": [\n            \"sdk.threefold.io\",\n            \"sdk_info.threefold.io\"\n        ],\n        \"descr\": \"for IAC, devops, how to do Infrastructure As Code, 3bot, Ansible, tfgrid-sdk, ...\"\n    },\n    {\n        \"name\": \"info_legal\",\n        \"url\": \"https://github.com/threefoldfoundation/info_legal\",\n        \"branch\": \"default\",\n        \"pull\": false,\n        \"cat\": 0,\n        \"alias\": \"legal\",\n        \"path_code\": \"/Users/despiegk/codewww/github/threefoldfoundation/info_legal\",\n        \"domains\": [\n            \"legal.threefold.io\",\n            \"legal_info.threefold.io\"\n        ],\n        \"descr\": \"\"\n    },\n    {\n        \"name\": \"info_cloud\",\n        \"url\": \"https://github.com/threefoldfoundation/info_cloud\",\n        \"branch\": \"default\",\n        \"pull\": false,\n        \"cat\": 0,\n        \"alias\": \"cloud\",\n        \"path_code\": \"/Users/despiegk/codewww/github/threefoldfoundation/info_cloud\",\n        \"domains\": [\n            \"cloud_info.threefold.io\"\n        ],\n        \"descr\": \"how to use the cloud for deploying apps: evdc, kubernetes, planetary fs, ... + marketplace solutions \"\n    },\n    {\n        \"name\": \"info_tftech\",\n        \"url\": \"https://github.com/threefoldtech/info_tftech\",\n        \"branch\": \"default\",\n        \"pull\": false,\n        \"cat\": 0,\n        \"alias\": \"tftech\",\n        \"path_code\": \"/Users/despiegk/codewww/github/threefoldtech/info_tftech\",\n        \"domains\": [\n            \"info.threefold.tech\"\n        ],\n        \"descr\": \"\"\n    },\n    {\n        \"name\": \"info_digitaltwin\",\n        \"url\": \"https://github.com/threefoldfoundation/info_digitaltwin.git\",\n        \"branch\": \"default\",\n        \"pull\": false,\n        \"cat\": 0,\n        \"alias\": \"twin\",\n        \"path_code\": \"/Users/despiegk/codewww/github/threefoldfoundation/info_digitaltwin\",\n        \"domains\": [\n            \"twin_info.threefold.io\"\n        ],\n        \"descr\": \"\"\n    }\n]\n"
  },
  {
    "path": "examples/templates/readme.md",
    "content": "# example how to work with templates\n\n- templates support\n  - if\n  - for loops\n  - even nesting of for loops\n  - syntax checking\n  - embed the template into the binary\n\nIts a very cool way how to do also do e.g. system administration, fill in \nconfig files, etc...\n\nThe example there is also a good demonstration of how to use json on a more \ncomplex object and read/write to file.\n"
  },
  {
    "path": "examples/templates/template.md",
    "content": "# WIKIs\n\n@for site in sites\n@if site.cat == .wiki\n\n## @{site.domains[0]}@port_str\n\n- [errors](\"//@{site.domains[0]}@port_str/errors\")\n\n### domains\n\n@for dom in site.domains\n- @dom\n@end\n@end\n@end\n"
  },
  {
    "path": "examples/templates/templates.v",
    "content": "module main\n\nimport os\nimport json\n\npub struct SiteConfig {\npub mut:\n\tname      string\n\turl       string\n\tbranch    string = 'default' // means is the default branch\n\tpull      bool\n\tcat       SiteCat\n\talias     string\n\tpath_code string\n\tdomains   []string\n\tdescr     string\n}\n\npub enum SiteCat {\n\twiki\n\tdata\n\tweb\n}\n\nfn data_get() []SiteConfig {\n\tdata := [\n\t\tSiteConfig{\n\t\t\tname:      'www_threefold_io'\n\t\t\turl:       'https://github.com/threefoldfoundation/www_threefold_io'\n\t\t\tbranch:    'default'\n\t\t\tpull:      false\n\t\t\tcat:       .web\n\t\t\talias:     'tf'\n\t\t\tpath_code: '/Users/despiegk/codewww/github/threefoldfoundation/www_threefold_io'\n\t\t\tdomains:   ['www.threefold.io', 'www.threefold.me']\n\t\t\tdescr:     'is our entry point for everyone, redirect to the detailed websites underneath.'\n\t\t},\n\t\tSiteConfig{\n\t\t\tname:      'www_threefold_cloud'\n\t\t\turl:       'https://github.com/threefoldfoundation/www_threefold_cloud'\n\t\t\tbranch:    'default'\n\t\t\tpull:      false\n\t\t\tcat:       .web\n\t\t\talias:     'cloud'\n\t\t\tpath_code: '/Users/despiegk/codewww/github/threefoldfoundation/www_threefold_cloud'\n\t\t\tdomains:   ['cloud.threefold.io', 'cloud.threefold.me']\n\t\t\tdescr:     'for people looking to deploy solutions on top of a cloud, alternative to e.g. digital ocean'\n\t\t},\n\t\tSiteConfig{\n\t\t\tname:      'www_threefold_farming'\n\t\t\turl:       'https://github.com/threefoldfoundation/www_threefold_farming'\n\t\t\tbranch:    'default'\n\t\t\tpull:      false\n\t\t\tcat:       .web\n\t\t\talias:     'farming'\n\t\t\tpath_code: '/Users/despiegk/codewww/github/threefoldfoundation/www_threefold_farming'\n\t\t\tdomains:   ['farming.threefold.io', 'farming.threefold.me']\n\t\t\tdescr:     'crypto & minining enthusiasts, be the internet, know about farming & tokens.'\n\t\t},\n\t\tSiteConfig{\n\t\t\tname:      'www_threefold_twin'\n\t\t\turl:       'https://github.com/threefoldfoundation/www_threefold_twin'\n\t\t\tbranch:    'default'\n\t\t\tpull:      false\n\t\t\tcat:       .web\n\t\t\talias:     'twin'\n\t\t\tpath_code: '/Users/despiegk/codewww/github/threefoldfoundation/www_threefold_twin'\n\t\t\tdomains:   ['twin.threefold.io', 'twin.threefold.me']\n\t\t\tdescr:     'you digital life'\n\t\t},\n\t\tSiteConfig{\n\t\t\tname:      'www_threefold_marketplace'\n\t\t\turl:       'https://github.com/threefoldfoundation/www_threefold_marketplace'\n\t\t\tbranch:    'default'\n\t\t\tpull:      false\n\t\t\tcat:       .web\n\t\t\talias:     'marketplace'\n\t\t\tpath_code: '/Users/despiegk/codewww/github/threefoldfoundation/www_threefold_marketplace'\n\t\t\tdomains:   ['now.threefold.io', 'marketplace.threefold.io', 'now.threefold.me',\n\t\t\t\t'marketplace.threefold.me']\n\t\t\tdescr:     'apps for community builders, runs on top of evdc'\n\t\t},\n\t\tSiteConfig{\n\t\t\tname:      'www_conscious_internet'\n\t\t\turl:       'https://github.com/threefoldfoundation/www_conscious_internet'\n\t\t\tbranch:    'default'\n\t\t\tpull:      false\n\t\t\tcat:       .web\n\t\t\talias:     'conscious_internet'\n\t\t\tpath_code: '/Users/despiegk/codewww/github/threefoldfoundation/www_conscious_internet'\n\t\t\tdomains:   ['www.consciousinternet.org', 'eco.threefold.io', 'community.threefold.io',\n\t\t\t\t'eco.threefold.me', 'community.threefold.me']\n\t\t\tdescr:     'community around threefold, partners, friends, ...'\n\t\t},\n\t\tSiteConfig{\n\t\t\tname:      'www_threefold_tech'\n\t\t\turl:       'https://github.com/threefoldtech/www_threefold_tech'\n\t\t\tbranch:    'default'\n\t\t\tpull:      false\n\t\t\tcat:       .web\n\t\t\talias:     'tech'\n\t\t\tpath_code: '/Users/despiegk/codewww/github/threefoldtech/www_threefold_tech'\n\t\t\tdomains:   ['www.threefold.tech']\n\t\t\tdescr:     'cyberpandemic, use the tech to build your own solutions with, certification for TFGrid'\n\t\t},\n\t\tSiteConfig{\n\t\t\tname:      'www_examplesite'\n\t\t\turl:       'https://github.com/threefoldfoundation/www_examplesite'\n\t\t\tbranch:    'default'\n\t\t\tpull:      false\n\t\t\tcat:       .web\n\t\t\talias:     'example'\n\t\t\tpath_code: '/Users/despiegk/codewww/github/threefoldfoundation/www_examplesite'\n\t\t\tdomains:   ['example.threefold.io']\n\t\t\tdescr:     ''\n\t\t},\n\t\tSiteConfig{\n\t\t\tname:      'info_threefold'\n\t\t\turl:       'https://github.com/threefoldfoundation/info_foundation_archive'\n\t\t\tbranch:    'default'\n\t\t\tpull:      false\n\t\t\tcat:       .wiki\n\t\t\talias:     'threefold'\n\t\t\tpath_code: '/Users/despiegk/codewww/github/threefoldfoundation/info_foundation_archive'\n\t\t\tdomains:   ['info.threefold.io']\n\t\t\tdescr:     'wiki for foundation, collaborate, what if farmings, tokens'\n\t\t},\n\t\tSiteConfig{\n\t\t\tname:      'info_sdk'\n\t\t\turl:       'https://github.com/threefoldfoundation/info_sdk'\n\t\t\tbranch:    'default'\n\t\t\tpull:      false\n\t\t\tcat:       .wiki\n\t\t\talias:     'sdk'\n\t\t\tpath_code: '/Users/despiegk/codewww/github/threefoldfoundation/info_sdk'\n\t\t\tdomains:   ['sdk.threefold.io', 'sdk_info.threefold.io']\n\t\t\tdescr:     'for IAC, devops, how to do Infrastructure As Code, 3bot, Ansible, tfgrid-sdk, ...'\n\t\t},\n\t\tSiteConfig{\n\t\t\tname:      'info_legal'\n\t\t\turl:       'https://github.com/threefoldfoundation/info_legal'\n\t\t\tbranch:    'default'\n\t\t\tpull:      false\n\t\t\tcat:       .wiki\n\t\t\talias:     'legal'\n\t\t\tpath_code: '/Users/despiegk/codewww/github/threefoldfoundation/info_legal'\n\t\t\tdomains:   ['legal.threefold.io', 'legal_info.threefold.io']\n\t\t\tdescr:     ''\n\t\t},\n\t\tSiteConfig{\n\t\t\tname:      'info_cloud'\n\t\t\turl:       'https://github.com/threefoldfoundation/info_cloud'\n\t\t\tbranch:    'default'\n\t\t\tpull:      false\n\t\t\tcat:       .wiki\n\t\t\talias:     'cloud'\n\t\t\tpath_code: '/Users/despiegk/codewww/github/threefoldfoundation/info_cloud'\n\t\t\tdomains:   ['cloud_info.threefold.io']\n\t\t\tdescr:     'how to use the cloud for deploying apps: evdc, kubernetes, planetary fs, ... + marketplace solutions '\n\t\t},\n\t\tSiteConfig{\n\t\t\tname:      'info_tftech'\n\t\t\turl:       'https://github.com/threefoldtech/info_tftech'\n\t\t\tbranch:    'default'\n\t\t\tpull:      false\n\t\t\tcat:       .wiki\n\t\t\talias:     'tftech'\n\t\t\tpath_code: '/Users/despiegk/codewww/github/threefoldtech/info_tftech'\n\t\t\tdomains:   ['info.threefold.tech']\n\t\t\tdescr:     ''\n\t\t},\n\t\tSiteConfig{\n\t\t\tname:      'info_digitaltwin'\n\t\t\turl:       'https://github.com/threefoldfoundation/info_digitaltwin.git'\n\t\t\tbranch:    'default'\n\t\t\tpull:      false\n\t\t\tcat:       .wiki\n\t\t\talias:     'twin'\n\t\t\tpath_code: '/Users/despiegk/codewww/github/threefoldfoundation/info_digitaltwin'\n\t\t\tdomains:   ['twin_info.threefold.io']\n\t\t\tdescr:     ''\n\t\t},\n\t]\n\treturn data\n}\n\nfn data_dump(data []SiteConfig) {\n\ta := json.encode_pretty(data)\n\tos.write_file(os.resource_abs_path('data.json'), a) or { panic(err) }\n}\n\nfn data_load() []SiteConfig {\n\tdata := os.read_file(os.resource_abs_path('data.json')) or { panic(err) }\n\ta := json.decode([]SiteConfig, data) or { panic(err) }\n\treturn a\n}\n\nfn filled_in_template() string {\n\tport_str := '80'\n\tsites := data_load()\n\treturn $tmpl('template.md')\n}\n\nfn main() {\n\t// A NICE test how to work with the json module\n\t// data := data_get()\n\t// data_dump(data)\n\tb := filled_in_template()\n\tprintln(b)\n}\n"
  },
  {
    "path": "examples/term.ui/README.md",
    "content": "<img src='https://raw.githubusercontent.com/vlang/v/master/examples/term.ui/screenshot_pong.png' width=300>\n"
  },
  {
    "path": "examples/term.ui/cursor_chaser.v",
    "content": "import term.ui as tui\n\nconst colors = [\n\ttui.Color{33, 150, 243},\n\ttui.Color{0, 150, 136},\n\ttui.Color{205, 220, 57},\n\ttui.Color{255, 152, 0},\n\ttui.Color{244, 67, 54},\n\ttui.Color{156, 39, 176},\n]\n\nstruct Point {\n\tx int\n\ty int\n}\n\nstruct App {\nmut:\n\ttui       &tui.Context = unsafe { nil }\n\tpoints    []Point\n\tcolor     tui.Color = colors[0]\n\tcolor_idx int\n\tcut_rate  f64 = 5\n}\n\nfn frame(mut app App) {\n\tapp.tui.clear()\n\n\tif app.points.len > 0 {\n\t\tapp.tui.set_bg_color(app.color)\n\t\tmut last := app.points[0]\n\t\tfor point in app.points {\n\t\t\t// if the cursor moves quickly enough, different events are not\n\t\t\t// necessarily touching, so we need to draw a line between them\n\t\t\tapp.tui.draw_line(last.x, last.y, point.x, point.y)\n\t\t\tlast = point\n\t\t}\n\t\tapp.tui.reset()\n\n\t\tl := int(app.points.len / app.cut_rate) + 1\n\t\tapp.points = app.points[l..].clone()\n\t}\n\n\tww := app.tui.window_width\n\n\tapp.tui.bold()\n\tapp.tui.draw_text(ww / 6, 2, 'V term.input: cursor chaser demo')\n\tapp.tui.draw_text((ww - ww / 6) - 14, 2, 'cut rate: ${(100 / app.cut_rate):3.0f}%')\n\tapp.tui.horizontal_separator(3)\n\tapp.tui.reset()\n\tapp.tui.flush()\n}\n\nfn event(e &tui.Event, mut app App) {\n\tmatch e.typ {\n\t\t.key_down {\n\t\t\tmatch e.code {\n\t\t\t\t.escape {\n\t\t\t\t\texit(0)\n\t\t\t\t}\n\t\t\t\t.space, .enter {\n\t\t\t\t\tapp.color_idx++\n\t\t\t\t\tif app.color_idx == colors.len {\n\t\t\t\t\t\tapp.color_idx = 0\n\t\t\t\t\t}\n\t\t\t\t\tapp.color = colors[app.color_idx]\n\t\t\t\t}\n\t\t\t\telse {}\n\t\t\t}\n\t\t}\n\t\t.mouse_move, .mouse_drag, .mouse_down {\n\t\t\tapp.points << Point{e.x, e.y}\n\t\t}\n\t\t.mouse_scroll {\n\t\t\td := if e.direction == .up { 0.1 } else { -0.1 }\n\t\t\tapp.cut_rate += d\n\t\t\tif app.cut_rate < 1 {\n\t\t\t\tapp.cut_rate = 1\n\t\t\t}\n\t\t}\n\t\telse {}\n\t}\n}\n\ntype EventFn = fn (&tui.Event, voidptr)\n\ntype FrameFn = fn (voidptr)\n\nfn main() {\n\tmut app := &App{}\n\tapp.tui = tui.init(\n\t\tuser_data:   app\n\t\tframe_fn:    FrameFn(frame)\n\t\tevent_fn:    EventFn(event)\n\t\thide_cursor: true\n\t)\n\tapp.tui.run()!\n}\n"
  },
  {
    "path": "examples/term.ui/event_viewer.v",
    "content": "import term.ui as tui\n\nstruct App {\nmut:\n\ttui &tui.Context = unsafe { nil }\n}\n\nfn (mut app App) show_header() {\n\tapp.tui.clear()\n\tapp.tui.set_cursor_position(0, 0)\n\tapp.tui.write('V term.input event viewer (press `esc` to exit)\\n\\n')\n\tapp.tui.flush()\n}\n\nfn event(e &tui.Event, mut app App) {\n\tapp.show_header()\n\tapp.tui.write('${e}')\n\tapp.tui.write('\\n\\nRaw event bytes: \"${e.utf8.bytes().hex()}\" = ${e.utf8.bytes()}')\n\tif !e.modifiers.is_empty() {\n\t\tapp.tui.write('\\nModifiers: ${e.modifiers} = ')\n\t\tif e.modifiers.has(.ctrl) {\n\t\t\tapp.tui.write('ctrl. ')\n\t\t}\n\t\tif e.modifiers.has(.shift) {\n\t\t\tapp.tui.write('shift ')\n\t\t}\n\t\tif e.modifiers.has(.alt) {\n\t\t\tapp.tui.write('alt. ')\n\t\t}\n\t}\n\tapp.tui.flush()\n\tif e.typ == .key_down && e.code == .escape {\n\t\tprintln('\\nGood bye.')\n\t\texit(0)\n\t}\n}\n\ntype EventFn = fn (&tui.Event, voidptr)\n\nfn main() {\n\tmut app := &App{}\n\tapp.tui = tui.init(\n\t\tuser_data:            app\n\t\tevent_fn:             EventFn(event)\n\t\twindow_title:         'V term.ui event viewer'\n\t\thide_cursor:          true\n\t\tcapture_events:       true\n\t\tframe_rate:           60\n\t\tuse_alternate_buffer: false\n\t)\n\tapp.show_header()\n\tapp.tui.run()!\n}\n"
  },
  {
    "path": "examples/term.ui/pong.v",
    "content": "// Copyright (c) 2020 Lars Pontoppidan. All rights reserved.\n// Use of this source code is governed by the MIT license distributed with this software.\nimport term\nimport term.ui\nimport time\n\nenum Mode {\n\tmenu\n\tgame\n}\n\nconst player_one = 1 // Human control this racket\n\nconst player_two = 0 // Take over this AI controller\n\nconst white = ui.Color{255, 255, 255}\nconst orange = ui.Color{255, 140, 0}\n\n@[heap]\nstruct App {\nmut:\n\ttui    &ui.Context = unsafe { nil }\n\tmode   Mode        = Mode.menu\n\twidth  int\n\theight int\n\tgame   &Game = unsafe { nil }\n\tdt     f32\n\tticks  i64\n}\n\nfn (mut a App) init() {\n\ta.game = &Game{\n\t\tapp: a\n\t}\n\tw, h := a.tui.window_width, a.tui.window_height\n\ta.width = w\n\ta.height = h\n\tterm.erase_del_clear()\n\tterm.set_cursor_position(\n\t\tx: 0\n\t\ty: 0\n\t)\n}\n\nfn (mut a App) start_game() {\n\tif a.mode != .game {\n\t\ta.mode = .game\n\t}\n\ta.game.init()\n}\n\nfn (mut a App) frame() {\n\tticks := time.ticks()\n\ta.dt = f32(ticks - a.ticks) / 1000.0\n\ta.width, a.height = a.tui.window_width, a.tui.window_height\n\tif a.mode == .game {\n\t\ta.game.update()\n\t}\n\ta.tui.clear()\n\ta.render()\n\ta.tui.flush()\n\ta.ticks = ticks\n}\n\nfn (mut a App) quit() {\n\tif a.mode != .menu {\n\t\ta.game.quit()\n\t\treturn\n\t}\n\tterm.set_cursor_position(\n\t\tx: 0\n\t\ty: 0\n\t)\n\texit(0)\n}\n\nfn (mut a App) event(e &ui.Event) {\n\tmatch e.typ {\n\t\t.mouse_move {\n\t\t\tif a.mode != .game {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// TODO: mouse movement for real Pong sharks\n\t\t\t// a.game.move_player(player_one, 0, -1)\n\t\t}\n\t\t.key_down {\n\t\t\tmatch e.code {\n\t\t\t\t.escape, .q {\n\t\t\t\t\ta.quit()\n\t\t\t\t}\n\t\t\t\t.w {\n\t\t\t\t\tif a.mode != .game {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ta.game.move_player(player_one, 0, -1)\n\t\t\t\t}\n\t\t\t\t.a {\n\t\t\t\t\tif a.mode != .game {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ta.game.move_player(player_one, 0, -1)\n\t\t\t\t}\n\t\t\t\t.s {\n\t\t\t\t\tif a.mode != .game {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ta.game.move_player(player_one, 0, 1)\n\t\t\t\t}\n\t\t\t\t.d {\n\t\t\t\t\tif a.mode != .game {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ta.game.move_player(player_one, 0, 1)\n\t\t\t\t}\n\t\t\t\t.left {\n\t\t\t\t\tif a.mode != .game {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ta.game.move_player(player_two, 0, -1)\n\t\t\t\t}\n\t\t\t\t.right {\n\t\t\t\t\tif a.mode != .game {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ta.game.move_player(player_two, 0, 1)\n\t\t\t\t}\n\t\t\t\t.up {\n\t\t\t\t\tif a.mode != .game {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ta.game.move_player(player_two, 0, -1)\n\t\t\t\t}\n\t\t\t\t.down {\n\t\t\t\t\tif a.mode != .game {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ta.game.move_player(player_two, 0, 1)\n\t\t\t\t}\n\t\t\t\t.enter, .space {\n\t\t\t\t\tif a.mode == .menu {\n\t\t\t\t\t\ta.start_game()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {}\n\t\t\t}\n\t\t}\n\t\telse {}\n\t}\n}\n\nfn (mut a App) free() {\n\tunsafe {\n\t\ta.game.free()\n\t\tfree(a.game)\n\t}\n}\n\nfn (mut a App) render() {\n\tmatch a.mode {\n\t\t.menu { a.draw_menu() }\n\t\telse { a.draw_game() }\n\t}\n}\n\nfn (mut a App) draw_menu() {\n\tcx := int(f32(a.width) * 0.5)\n\ty025 := int(f32(a.height) * 0.25)\n\ty075 := int(f32(a.height) * 0.75)\n\tcy := int(f32(a.height) * 0.5)\n\n\ta.tui.set_color(white)\n\ta.tui.bold()\n\ta.tui.draw_text(cx - 2, y025, 'VONG')\n\ta.tui.reset()\n\ta.tui.draw_text(cx - 13, y025 + 1, '(A game of Pong written in V)')\n\n\ta.tui.set_color(white)\n\ta.tui.bold()\n\ta.tui.draw_text(cx - 3, cy + 1, 'START')\n\ta.tui.reset()\n\n\ta.tui.draw_text(cx - 9, y075 + 1, 'Press SPACE to start')\n\ta.tui.reset()\n\ta.tui.draw_text(cx - 5, y075 + 3, 'ESC to Quit')\n\ta.tui.reset()\n}\n\nfn (mut a App) draw_game() {\n\ta.game.draw()\n}\n\nstruct Player {\nmut:\n\tgame        &Game = unsafe { nil }\n\tpos         Vec\n\tracket_size int = 4\n\tscore       int\n\tai          bool\n}\n\nfn (mut p Player) move(x f32, y f32) {\n\tp.pos.x += x\n\tp.pos.y += y\n}\n\nfn (mut p Player) update() {\n\tif !p.ai {\n\t\treturn\n\t}\n\tif isnil(p.game) {\n\t\treturn\n\t}\n\t// dt := p.game.app.dt\n\tball := unsafe { &p.game.ball }\n\t// Evil AI that eventually will take over the world\n\tp.pos.y = ball.pos.y - int(f32(p.racket_size) * 0.5)\n}\n\nstruct Vec {\nmut:\n\tx f32\n\ty f32\n}\n\nfn (mut v Vec) set(x f32, y f32) {\n\tv.x = x\n\tv.y = y\n}\n\nstruct Ball {\nmut:\n\tpos Vec\n\tvel Vec\n\tacc Vec\n}\n\nfn (mut b Ball) update(dt f32) {\n\tb.pos.x += b.vel.x * b.acc.x * dt\n\tb.pos.y += b.vel.y * b.acc.y * dt\n}\n\n@[heap]\nstruct Game {\nmut:\n\tapp     &App = unsafe { nil }\n\tplayers []Player\n\tball    Ball\n}\n\nfn (mut g Game) move_player(id int, x int, y int) {\n\tmut p := unsafe { &g.players[id] }\n\tif p.ai { // disable AI when moved\n\t\tp.ai = false\n\t}\n\tp.move(x, y)\n}\n\nfn (mut g Game) init() {\n\tif g.players.len == 0 {\n\t\tg.players = []Player{len: 2, init: Player{ // <- BUG omitting the init will result in smaller racket sizes???\n\t\t\tgame: g\n\t\t}}\n\t}\n\tg.reset()\n}\n\nfn (mut g Game) reset() {\n\tmut i := 0\n\tfor mut p in g.players {\n\t\tp.score = 0\n\t\tif i != player_one {\n\t\t\tp.ai = true\n\t\t}\n\t\ti++\n\t}\n\tg.new_round()\n}\n\nfn (mut g Game) new_round() {\n\tmut i := 0\n\tfor mut p in g.players {\n\t\tp.pos.x = if i == 0 { 3 } else { g.app.width - 2 }\n\t\tp.pos.y = f32(g.app.height) * 0.5 - f32(p.racket_size) * 0.5\n\t\ti++\n\t}\n\tg.ball.pos.set(f32(g.app.width) * 0.5, f32(g.app.height) * 0.5)\n\tg.ball.vel.set(-8, -15)\n\tg.ball.acc.set(2.0, 1.0)\n}\n\nfn (mut g Game) update() {\n\tdt := g.app.dt\n\tmut b := unsafe { &g.ball }\n\tfor mut p in g.players {\n\t\tp.update()\n\t\t// Keep rackets within the game area\n\t\tif p.pos.y <= 0 {\n\t\t\tp.pos.y = 1\n\t\t}\n\t\tif p.pos.y + p.racket_size >= g.app.height {\n\t\t\tp.pos.y = g.app.height - p.racket_size - 1\n\t\t}\n\t\t// Check ball collision\n\t\t// Player left side\n\t\tif p.pos.x < f32(g.app.width) * 0.5 {\n\t\t\t// Racket collision\n\t\t\tif b.pos.x <= p.pos.x + 1 {\n\t\t\t\tif b.pos.y >= p.pos.y && b.pos.y <= p.pos.y + p.racket_size {\n\t\t\t\t\tb.vel.x *= -1\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Behind racket\n\t\t\tif b.pos.x < p.pos.x {\n\t\t\t\tg.players[1].score++\n\t\t\t\tg.new_round()\n\t\t\t}\n\t\t} else {\n\t\t\t// Player right side\n\t\t\tif b.pos.x >= p.pos.x - 1 {\n\t\t\t\tif b.pos.y >= p.pos.y && b.pos.y <= p.pos.y + p.racket_size {\n\t\t\t\t\tb.vel.x *= -1\n\t\t\t\t}\n\t\t\t}\n\t\t\tif b.pos.x > p.pos.x {\n\t\t\t\tg.players[0].score++\n\t\t\t\tg.new_round()\n\t\t\t}\n\t\t}\n\t}\n\tif b.pos.x <= 1 || b.pos.x >= g.app.width {\n\t\tb.vel.x *= -1\n\t}\n\tif b.pos.y <= 2 || b.pos.y >= g.app.height {\n\t\tb.vel.y *= -1\n\t}\n\tb.update(dt)\n}\n\nfn (mut g Game) quit() {\n\tif g.app.mode != .game {\n\t\treturn\n\t}\n\tg.app.mode = .menu\n}\n\nfn (mut g Game) draw_big_digit(px f32, py f32, digit int) {\n\t// TODO: use draw_line or draw_point to fix tearing with non-monospaced terminal fonts\n\tmut gfx := g.app.tui\n\tx, y := int(px), int(py)\n\tmatch digit {\n\t\t0 {\n\t\t\tgfx.draw_text(x, y + 0, '█████')\n\t\t\tgfx.draw_text(x, y + 1, '█   █')\n\t\t\tgfx.draw_text(x, y + 2, '█   █')\n\t\t\tgfx.draw_text(x, y + 3, '█   █')\n\t\t\tgfx.draw_text(x, y + 4, '█████')\n\t\t}\n\t\t1 {\n\t\t\tgfx.draw_text(x + 3, y + 0, '█')\n\t\t\tgfx.draw_text(x + 3, y + 1, '█')\n\t\t\tgfx.draw_text(x + 3, y + 2, '█')\n\t\t\tgfx.draw_text(x + 3, y + 3, '█')\n\t\t\tgfx.draw_text(x + 3, y + 4, '█')\n\t\t}\n\t\t2 {\n\t\t\tgfx.draw_text(x, y + 0, '█████')\n\t\t\tgfx.draw_text(x, y + 1, '    █')\n\t\t\tgfx.draw_text(x, y + 2, '█████')\n\t\t\tgfx.draw_text(x, y + 3, '█')\n\t\t\tgfx.draw_text(x, y + 4, '█████')\n\t\t}\n\t\t3 {\n\t\t\tgfx.draw_text(x, y + 0, '█████')\n\t\t\tgfx.draw_text(x, y + 1, '   ██')\n\t\t\tgfx.draw_text(x, y + 2, ' ████')\n\t\t\tgfx.draw_text(x, y + 3, '   ██')\n\t\t\tgfx.draw_text(x, y + 4, '█████')\n\t\t}\n\t\t4 {\n\t\t\tgfx.draw_text(x, y + 0, '█   █')\n\t\t\tgfx.draw_text(x, y + 1, '█   █')\n\t\t\tgfx.draw_text(x, y + 2, '█████')\n\t\t\tgfx.draw_text(x, y + 3, '    █')\n\t\t\tgfx.draw_text(x, y + 4, '    █')\n\t\t}\n\t\t5 {\n\t\t\tgfx.draw_text(x, y + 0, '█████')\n\t\t\tgfx.draw_text(x, y + 1, '█')\n\t\t\tgfx.draw_text(x, y + 2, '█████')\n\t\t\tgfx.draw_text(x, y + 3, '    █')\n\t\t\tgfx.draw_text(x, y + 4, '█████')\n\t\t}\n\t\t6 {\n\t\t\tgfx.draw_text(x, y + 0, '█████')\n\t\t\tgfx.draw_text(x, y + 1, '█')\n\t\t\tgfx.draw_text(x, y + 2, '█████')\n\t\t\tgfx.draw_text(x, y + 3, '█   █')\n\t\t\tgfx.draw_text(x, y + 4, '█████')\n\t\t}\n\t\t7 {\n\t\t\tgfx.draw_text(x, y + 0, '█████')\n\t\t\tgfx.draw_text(x, y + 1, '    █')\n\t\t\tgfx.draw_text(x, y + 2, '    █')\n\t\t\tgfx.draw_text(x, y + 3, '    █')\n\t\t\tgfx.draw_text(x, y + 4, '    █')\n\t\t}\n\t\t8 {\n\t\t\tgfx.draw_text(x, y + 0, '█████')\n\t\t\tgfx.draw_text(x, y + 1, '█   █')\n\t\t\tgfx.draw_text(x, y + 2, '█████')\n\t\t\tgfx.draw_text(x, y + 3, '█   █')\n\t\t\tgfx.draw_text(x, y + 4, '█████')\n\t\t}\n\t\t9 {\n\t\t\tgfx.draw_text(x, y + 0, '█████')\n\t\t\tgfx.draw_text(x, y + 1, '█   █')\n\t\t\tgfx.draw_text(x, y + 2, '█████')\n\t\t\tgfx.draw_text(x, y + 3, '    █')\n\t\t\tgfx.draw_text(x, y + 4, '█████')\n\t\t}\n\t\telse {}\n\t}\n}\n\nfn (mut g Game) draw() {\n\tmut gfx := g.app.tui\n\tgfx.set_bg_color(white)\n\t// Border\n\tgfx.draw_empty_rect(1, 1, g.app.width, g.app.height)\n\t// Center line\n\tgfx.draw_dashed_line(int(f32(g.app.width) * 0.5), 0, int(f32(g.app.width) * 0.5),\n\t\tint(g.app.height))\n\tborder := 1\n\tmut y, mut x := 0, 0\n\tfor p in g.players {\n\t\tx = int(p.pos.x)\n\t\ty = int(p.pos.y)\n\t\tgfx.reset_bg_color()\n\t\tgfx.set_color(white)\n\t\tif x < f32(g.app.width) * 0.5 {\n\t\t\tg.draw_big_digit(f32(g.app.width) * 0.25, 3, p.score)\n\t\t} else {\n\t\t\tg.draw_big_digit(f32(g.app.width) * 0.75, 3, p.score)\n\t\t}\n\t\tgfx.reset_color()\n\t\tgfx.set_bg_color(white)\n\t\t// Racket\n\t\tgfx.draw_line(x, y + border, x, y + p.racket_size)\n\t}\n\t// Ball\n\tgfx.draw_point(int(g.ball.pos.x), int(g.ball.pos.y))\n\t// gfx.draw_text(22,2,'${g.ball.pos}')\n\tgfx.reset_bg_color()\n}\n\nfn (mut g Game) free() {\n\tg.players.clear()\n}\n\n// TODO: Remove these wrapper functions when we can assign methods as callbacks\nfn init(mut app App) {\n\tapp.init()\n}\n\nfn frame(mut app App) {\n\tapp.frame()\n}\n\nfn cleanup(mut app App) {\n\tunsafe {\n\t\tapp.free()\n\t}\n}\n\nfn fail(error string) {\n\teprintln(error)\n}\n\nfn event(e &ui.Event, mut app App) {\n\tapp.event(e)\n}\n\ntype InitFn = fn (voidptr)\n\ntype EventFn = fn (&ui.Event, voidptr)\n\ntype FrameFn = fn (voidptr)\n\ntype CleanupFn = fn (voidptr)\n\nfn main() {\n\tmut app := &App{}\n\tapp.tui = ui.init(\n\t\tuser_data:      app\n\t\tinit_fn:        InitFn(init)\n\t\tframe_fn:       FrameFn(frame)\n\t\tcleanup_fn:     CleanupFn(cleanup)\n\t\tevent_fn:       EventFn(event)\n\t\tfail_fn:        fail\n\t\tcapture_events: true\n\t\thide_cursor:    true\n\t\tframe_rate:     60\n\t)\n\tapp.tui.run()!\n}\n"
  },
  {
    "path": "examples/term.ui/rectangles.v",
    "content": "import term.ui as tui\nimport rand\n\nstruct Rect {\nmut:\n\tc  tui.Color\n\tx  int\n\ty  int\n\tx2 int\n\ty2 int\n}\n\nstruct App {\nmut:\n\ttui      &tui.Context = unsafe { nil }\n\trects    []Rect\n\tcur_rect Rect\n\tis_drag  bool\n\tredraw   bool\n}\n\nfn random_color() tui.Color {\n\treturn tui.Color{\n\t\tr: rand.u8()\n\t\tg: rand.u8()\n\t\tb: rand.u8()\n\t}\n}\n\nfn event(e &tui.Event, mut app App) {\n\tmatch e.typ {\n\t\t.mouse_down {\n\t\t\tapp.is_drag = true\n\t\t\tapp.cur_rect = Rect{\n\t\t\t\tc:  random_color()\n\t\t\t\tx:  e.x\n\t\t\t\ty:  e.y\n\t\t\t\tx2: e.x\n\t\t\t\ty2: e.y\n\t\t\t}\n\t\t}\n\t\t.mouse_drag {\n\t\t\tapp.cur_rect.x2 = e.x\n\t\t\tapp.cur_rect.y2 = e.y\n\t\t}\n\t\t.mouse_up {\n\t\t\tapp.rects << app.cur_rect\n\t\t\tapp.is_drag = false\n\t\t}\n\t\t.key_down {\n\t\t\tif e.code == .c {\n\t\t\t\tapp.rects.clear()\n\t\t\t} else if e.code == .escape {\n\t\t\t\texit(0)\n\t\t\t}\n\t\t}\n\t\telse {}\n\t}\n\tapp.redraw = true\n}\n\nfn frame(mut app App) {\n\tif !app.redraw {\n\t\treturn\n\t}\n\n\tapp.tui.clear()\n\n\tfor rect in app.rects {\n\t\tapp.tui.set_bg_color(rect.c)\n\t\tapp.tui.draw_rect(rect.x, rect.y, rect.x2, rect.y2)\n\t}\n\n\tif app.is_drag {\n\t\tr := app.cur_rect\n\t\tapp.tui.set_bg_color(r.c)\n\t\tapp.tui.draw_empty_rect(r.x, r.y, r.x2, r.y2)\n\t}\n\n\tapp.tui.reset_bg_color()\n\tapp.tui.flush()\n\tapp.redraw = false\n}\n\ntype EventFn = fn (&tui.Event, voidptr)\n\ntype FrameFn = fn (voidptr)\n\nfn main() {\n\tmut app := &App{}\n\tapp.tui = tui.init(\n\t\tuser_data:   app\n\t\tevent_fn:    EventFn(event)\n\t\tframe_fn:    FrameFn(frame)\n\t\thide_cursor: true\n\t\tframe_rate:  60\n\t)\n\tapp.tui.run()!\n}\n"
  },
  {
    "path": "examples/term.ui/term_drawing.v",
    "content": "// Copyright (c) 2020 Raúl Hernández. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nmodule main\n\nimport term.ui\n\n// The color palette, taken from Google's Material design\nconst colors = [\n\t[\n\t\tui.Color{239, 154, 154},\n\t\tui.Color{244, 143, 177},\n\t\tui.Color{206, 147, 216},\n\t\tui.Color{179, 157, 219},\n\t\tui.Color{159, 168, 218},\n\t\tui.Color{144, 202, 249},\n\t\tui.Color{129, 212, 250},\n\t\tui.Color{128, 222, 234},\n\t\tui.Color{128, 203, 196},\n\t\tui.Color{165, 214, 167},\n\t\tui.Color{197, 225, 165},\n\t\tui.Color{230, 238, 156},\n\t\tui.Color{255, 245, 157},\n\t\tui.Color{255, 224, 130},\n\t\tui.Color{255, 204, 128},\n\t\tui.Color{255, 171, 145},\n\t\tui.Color{188, 170, 164},\n\t\tui.Color{238, 238, 238},\n\t\tui.Color{176, 190, 197},\n\t],\n\t[\n\t\tui.Color{244, 67, 54},\n\t\tui.Color{233, 30, 99},\n\t\tui.Color{156, 39, 176},\n\t\tui.Color{103, 58, 183},\n\t\tui.Color{63, 81, 181},\n\t\tui.Color{33, 150, 243},\n\t\tui.Color{3, 169, 244},\n\t\tui.Color{0, 188, 212},\n\t\tui.Color{0, 150, 136},\n\t\tui.Color{76, 175, 80},\n\t\tui.Color{139, 195, 74},\n\t\tui.Color{205, 220, 57},\n\t\tui.Color{255, 235, 59},\n\t\tui.Color{255, 193, 7},\n\t\tui.Color{255, 152, 0},\n\t\tui.Color{255, 87, 34},\n\t\tui.Color{121, 85, 72},\n\t\tui.Color{120, 120, 120},\n\t\tui.Color{96, 125, 139},\n\t],\n\t[\n\t\tui.Color{198, 40, 40},\n\t\tui.Color{173, 20, 87},\n\t\tui.Color{106, 27, 154},\n\t\tui.Color{69, 39, 160},\n\t\tui.Color{40, 53, 147},\n\t\tui.Color{21, 101, 192},\n\t\tui.Color{2, 119, 189},\n\t\tui.Color{0, 131, 143},\n\t\tui.Color{0, 105, 92},\n\t\tui.Color{46, 125, 50},\n\t\tui.Color{85, 139, 47},\n\t\tui.Color{158, 157, 36},\n\t\tui.Color{249, 168, 37},\n\t\tui.Color{255, 143, 0},\n\t\tui.Color{239, 108, 0},\n\t\tui.Color{216, 67, 21},\n\t\tui.Color{78, 52, 46},\n\t\tui.Color{33, 33, 33},\n\t\tui.Color{55, 71, 79},\n\t],\n]\n\nconst frame_rate = 30 // fps\n\nconst msg_display_time = 5 * frame_rate\nconst w = 200\nconst h = 100\nconst space = ' '\nconst spaces = '  '\nconst select_color = 'Select color: '\nconst select_size = 'Size: ＋  －'\nconst help_1 = '╭────────╮'\nconst help_2 = '│  HELP  │'\nconst help_3 = '╰────────╯'\n\nstruct App {\nmut:\n\tui                  &ui.Context = unsafe { nil }\n\theader_text         []string\n\tmouse_pos           Point\n\tmsg                 string\n\tmsg_hide_tick       int\n\tprimary_color       ui.Color     = colors[1][6]\n\tsecondary_color     ui.Color     = colors[1][9]\n\tprimary_color_idx   int          = 25\n\tsecondary_color_idx int          = 28\n\tbg_color            ui.Color     = ui.Color{0, 0, 0}\n\tdrawing             [][]ui.Color = [][]ui.Color{len: h, init: []ui.Color{len: w}}\n\tsize                int          = 1\n\tshould_redraw       bool         = true\n\tis_dragging         bool\n}\n\nstruct Point {\nmut:\n\tx int\n\ty int\n}\n\ntype EventFn = fn (&ui.Event, voidptr)\n\ntype FrameFn = fn (voidptr)\n\nfn main() {\n\tmut app := &App{}\n\tapp.ui = ui.init(\n\t\tuser_data:    app\n\t\tframe_fn:     FrameFn(frame)\n\t\tevent_fn:     EventFn(event)\n\t\tframe_rate:   frame_rate\n\t\thide_cursor:  true\n\t\twindow_title: 'V terminal pixelart drawing app'\n\t)\n\tapp.mouse_pos.x = 40\n\tapp.mouse_pos.y = 15\n\tapp.ui.clear()\n\tapp.ui.run()!\n}\n\nfn frame(mut app App) {\n\tmut redraw := app.should_redraw\n\tif app.msg != '' && app.ui.frame_count >= app.msg_hide_tick {\n\t\tapp.msg = ''\n\t\tredraw = true\n\t}\n\tif redraw {\n\t\tapp.render(false)\n\t\tapp.should_redraw = false\n\t}\n}\n\nfn event(event &ui.Event, mut app App) {\n\tmatch event.typ {\n\t\t.mouse_down {\n\t\t\tapp.is_dragging = true\n\t\t\tif app.ui.window_height - event.y < 5 {\n\t\t\t\tapp.footer_click(event)\n\t\t\t} else {\n\t\t\t\tapp.paint(event)\n\t\t\t}\n\t\t}\n\t\t.mouse_up {\n\t\t\tapp.is_dragging = false\n\t\t}\n\t\t.mouse_drag {\n\t\t\tapp.mouse_pos = Point{\n\t\t\t\tx: event.x\n\t\t\t\ty: event.y\n\t\t\t}\n\t\t\tapp.paint(event)\n\t\t}\n\t\t.mouse_move {\n\t\t\tapp.mouse_pos = Point{\n\t\t\t\tx: event.x\n\t\t\t\ty: event.y\n\t\t\t}\n\t\t}\n\t\t.mouse_scroll {\n\t\t\tapp.mouse_pos = Point{\n\t\t\t\tx: event.x\n\t\t\t\ty: event.y\n\t\t\t}\n\t\t\td := event.direction == .down\n\t\t\tif event.modifiers.has(.ctrl) {\n\t\t\t\tp := !event.modifiers.has(.shift)\n\t\t\t\tc := if d {\n\t\t\t\t\tif p { app.primary_color_idx - 1 } else { app.secondary_color_idx - 1 }\n\t\t\t\t} else {\n\t\t\t\t\tif p { app.primary_color_idx + 1 } else { app.secondary_color_idx + 1 }\n\t\t\t\t}\n\t\t\t\tapp.select_color(p, c)\n\t\t\t} else {\n\t\t\t\tif d {\n\t\t\t\t\tapp.inc_size()\n\t\t\t\t} else {\n\t\t\t\t\tapp.dec_size()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t.key_down {\n\t\t\tmatch event.code {\n\t\t\t\t.f1, ._1 {\n\t\t\t\t\toevent := *event\n\t\t\t\t\tnevent := ui.Event{\n\t\t\t\t\t\t...oevent\n\t\t\t\t\t\tbutton: ui.MouseButton.left\n\t\t\t\t\t\tx:      app.mouse_pos.x\n\t\t\t\t\t\ty:      app.mouse_pos.y\n\t\t\t\t\t}\n\t\t\t\t\tapp.paint(nevent)\n\t\t\t\t}\n\t\t\t\t.f2, ._2 {\n\t\t\t\t\toevent := *event\n\t\t\t\t\tnevent := ui.Event{\n\t\t\t\t\t\t...oevent\n\t\t\t\t\t\tbutton: ui.MouseButton.right\n\t\t\t\t\t\tx:      app.mouse_pos.x\n\t\t\t\t\t\ty:      app.mouse_pos.y\n\t\t\t\t\t}\n\t\t\t\t\tapp.paint(nevent)\n\t\t\t\t}\n\t\t\t\t.space, .enter {\n\t\t\t\t\toevent := *event\n\t\t\t\t\tnevent := ui.Event{\n\t\t\t\t\t\t...oevent\n\t\t\t\t\t\tbutton: .left\n\t\t\t\t\t\tx:      app.mouse_pos.x\n\t\t\t\t\t\ty:      app.mouse_pos.y\n\t\t\t\t\t}\n\t\t\t\t\tapp.paint(nevent)\n\t\t\t\t}\n\t\t\t\t.delete, .backspace {\n\t\t\t\t\toevent := *event\n\t\t\t\t\tnevent := ui.Event{\n\t\t\t\t\t\t...oevent\n\t\t\t\t\t\tbutton: .middle\n\t\t\t\t\t\tx:      app.mouse_pos.x\n\t\t\t\t\t\ty:      app.mouse_pos.y\n\t\t\t\t\t}\n\t\t\t\t\tapp.paint(nevent)\n\t\t\t\t}\n\t\t\t\t.j, .down {\n\t\t\t\t\tif event.modifiers.has(.shift) {\n\t\t\t\t\t\tapp.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)\n\t\t\t\t\t}\n\t\t\t\t\tapp.mouse_pos.y++\n\t\t\t\t}\n\t\t\t\t.k, .up {\n\t\t\t\t\tif event.modifiers.has(.shift) {\n\t\t\t\t\t\tapp.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)\n\t\t\t\t\t}\n\t\t\t\t\tapp.mouse_pos.y--\n\t\t\t\t}\n\t\t\t\t.h, .left {\n\t\t\t\t\tif event.modifiers.has(.shift) {\n\t\t\t\t\t\tapp.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)\n\t\t\t\t\t}\n\t\t\t\t\tapp.mouse_pos.x -= 2\n\t\t\t\t}\n\t\t\t\t.l, .right {\n\t\t\t\t\tif event.modifiers.has(.shift) {\n\t\t\t\t\t\tapp.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)\n\t\t\t\t\t}\n\t\t\t\t\tapp.mouse_pos.x += 2\n\t\t\t\t}\n\t\t\t\t.t {\n\t\t\t\t\tp := !event.modifiers.has(.alt)\n\t\t\t\t\tc := if event.modifiers.has(.shift) {\n\t\t\t\t\t\tif p { app.primary_color_idx - 19 } else { app.secondary_color_idx - 19 }\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif p { app.primary_color_idx + 19 } else { app.secondary_color_idx + 19 }\n\t\t\t\t\t}\n\t\t\t\t\tapp.select_color(p, c)\n\t\t\t\t}\n\t\t\t\t.r {\n\t\t\t\t\tp := !event.modifiers.has(.alt)\n\t\t\t\t\tc := if event.modifiers.has(.shift) {\n\t\t\t\t\t\tif p { app.primary_color_idx - 1 } else { app.secondary_color_idx - 1 }\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif p { app.primary_color_idx + 1 } else { app.secondary_color_idx + 1 }\n\t\t\t\t\t}\n\t\t\t\t\tapp.select_color(p, c)\n\t\t\t\t}\n\t\t\t\t.plus {\n\t\t\t\t\tapp.inc_size()\n\t\t\t\t}\n\t\t\t\t.minus {\n\t\t\t\t\tapp.dec_size()\n\t\t\t\t}\n\t\t\t\t.c {\n\t\t\t\t\tapp.drawing = [][]ui.Color{len: h, init: []ui.Color{len: w}}\n\t\t\t\t}\n\t\t\t\t.q, .escape {\n\t\t\t\t\tapp.render(true)\n\t\t\t\t\texit(0)\n\t\t\t\t}\n\t\t\t\telse {}\n\t\t\t}\n\t\t}\n\t\telse {}\n\t}\n\tapp.should_redraw = true\n}\n\nfn (mut app App) render(paint_only bool) {\n\tapp.ui.clear()\n\tapp.draw_header()\n\tapp.draw_content()\n\tif !paint_only {\n\t\tapp.draw_footer()\n\t\tapp.draw_cursor()\n\t}\n\tapp.ui.flush()\n}\n\nfn (mut app App) select_color(primary bool, idx int) {\n\tc := (idx + 57) % 57\n\tcx := c % 19\n\tcy := (c / 19) % 3\n\tcolor := colors[cy][cx]\n\tif primary {\n\t\tapp.primary_color_idx = c % (19 * 3)\n\t\tapp.primary_color = color\n\t} else {\n\t\tapp.secondary_color_idx = c % (19 * 3)\n\t\tapp.secondary_color = color\n\t}\n\tc_str := if primary { 'primary' } else { 'secondary' }\n\tapp.show_msg('set ${c_str} color idx: ${idx}', 1)\n}\n\nfn (mut app App) set_pixel(x_ int, y_ int, c ui.Color) {\n\t// Term coords start at 1, and adjust for the header\n\tx, y := x_ - 1, y_ - 4\n\tif y < 0 || app.ui.window_height - y < 3 {\n\t\treturn\n\t}\n\tif y >= app.drawing.len || x < 0 || x >= app.drawing[0].len {\n\t\treturn\n\t}\n\tapp.drawing[y][x] = c\n}\n\nfn (mut app App) paint(event &ui.Event) {\n\tif event.y < 4 || app.ui.window_height - event.y < 4 {\n\t\treturn\n\t}\n\tx_start, y_start := int(f32((event.x - 1) / 2) - app.size / 2 + 1), event.y - app.size / 2\n\tcolor := match event.button {\n\t\t.left { app.primary_color }\n\t\t.right { app.secondary_color }\n\t\telse { app.bg_color }\n\t}\n\tfor x in x_start .. x_start + app.size {\n\t\tfor y in y_start .. y_start + app.size {\n\t\t\tapp.set_pixel(x, y, color)\n\t\t}\n\t}\n}\n\nfn (mut app App) draw_content() {\n\tw_, mut h_ := app.ui.window_width / 2, app.ui.window_height - 8\n\tif h_ > app.drawing.len {\n\t\th_ = app.drawing.len\n\t}\n\tfor row_idx, row in app.drawing[..h_] {\n\t\tapp.ui.set_cursor_position(0, row_idx + 4)\n\t\tmut last := ui.Color{0, 0, 0}\n\t\tfor cell in row[..w_] {\n\t\t\tif cell.r == 0 && cell.g == 0 && cell.b == 0 {\n\t\t\t\tif !(cell.r == last.r && cell.g == last.g && cell.b == last.b) {\n\t\t\t\t\tapp.ui.reset()\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif !(cell.r == last.r && cell.g == last.g && cell.b == last.b) {\n\t\t\t\t\tapp.ui.set_bg_color(cell)\n\t\t\t\t}\n\t\t\t}\n\t\t\tapp.ui.write(spaces)\n\t\t\tlast = cell\n\t\t}\n\t\tapp.ui.reset()\n\t}\n}\n\nfn (mut app App) draw_cursor() {\n\tif app.mouse_pos.y in [3, app.ui.window_height - 5] {\n\t\t// inside the horizontal separators\n\t\treturn\n\t}\n\tcursor_color := if app.is_dragging { ui.Color{220, 220, 220} } else { ui.Color{160, 160, 160} }\n\tapp.ui.set_bg_color(cursor_color)\n\tif app.mouse_pos.y >= 3 && app.mouse_pos.y <= app.ui.window_height - 4 {\n\t\t// inside the main content\n\t\tmut x_start := int(f32((app.mouse_pos.x - 1) / 2) - app.size / 2 + 1) * 2 - 1\n\t\tmut y_start := app.mouse_pos.y - app.size / 2\n\t\tmut x_end := x_start + app.size * 2 - 1\n\t\tmut y_end := y_start + app.size - 1\n\t\tif x_start < 1 {\n\t\t\tx_start = 1\n\t\t}\n\t\tif y_start < 4 {\n\t\t\ty_start = 4\n\t\t}\n\t\tif x_end > app.ui.window_width {\n\t\t\tx_end = app.ui.window_width\n\t\t}\n\t\tif y_end > app.ui.window_height - 5 {\n\t\t\ty_end = app.ui.window_height - 5\n\t\t}\n\t\tapp.ui.draw_rect(x_start, y_start, x_end, y_end)\n\t} else {\n\t\tapp.ui.draw_text(app.mouse_pos.x, app.mouse_pos.y, space)\n\t}\n\tapp.ui.reset()\n}\n\nfn (mut app App) draw_header() {\n\tif app.msg != '' {\n\t\tapp.ui.set_color(\n\t\t\tr: 0\n\t\t\tg: 0\n\t\t\tb: 0\n\t\t)\n\t\tapp.ui.set_bg_color(\n\t\t\tr: 220\n\t\t\tg: 220\n\t\t\tb: 220\n\t\t)\n\t\tapp.ui.draw_text(0, 0, ' ${app.msg} ')\n\t\tapp.ui.reset()\n\t}\n\t//'tick: ${app.ui.frame_count} | ' +\n\tapp.ui.draw_text(3, 2, 'terminal size: (${app.ui.window_width}, ${app.ui.window_height}) | primary color: ${app.primary_color.hex()} | secondary color: ${app.secondary_color.hex()}')\n\tapp.ui.horizontal_separator(3)\n}\n\nfn (mut app App) draw_footer() {\n\t_, wh := app.ui.window_width, app.ui.window_height\n\tapp.ui.horizontal_separator(wh - 4)\n\tfor i, color_row in colors {\n\t\tfor j, color in color_row {\n\t\t\tx := j * 3 + 19\n\t\t\ty := wh - 3 + i\n\t\t\tapp.ui.set_bg_color(color)\n\t\t\tif app.primary_color_idx == j + (i * 19) {\n\t\t\t\tapp.ui.set_color(r: 0, g: 0, b: 0)\n\t\t\t\tapp.ui.draw_text(x, y, '><')\n\t\t\t\tapp.ui.reset_color()\n\t\t\t} else if app.secondary_color_idx == j + (i * 19) {\n\t\t\t\tapp.ui.set_color(r: 255, g: 255, b: 255)\n\t\t\t\tapp.ui.draw_text(x, y, '><')\n\t\t\t\tapp.ui.reset_color()\n\t\t\t} else {\n\t\t\t\tapp.ui.draw_rect(x, y, x + 1, y)\n\t\t\t}\n\t\t}\n\t}\n\tapp.ui.reset_bg_color()\n\tapp.ui.draw_text(3, wh - 3, select_color)\n\tapp.ui.bold()\n\tapp.ui.draw_text(3, wh - 1, '${select_size} ${app.size}')\n\tapp.ui.reset()\n\n\t// TODO: help button\n\t// if ww >= 90 {\n\t// \tapp.ui.draw_text(80, wh - 3, help_1)\n\t// \tapp.ui.draw_text(80, wh - 2, help_2)\n\t// \tapp.ui.draw_text(80, wh - 1, help_3)\n\t// }\n}\n\n@[inline]\nfn (mut app App) inc_size() {\n\tif app.size < 30 {\n\t\tapp.size++\n\t}\n\tapp.show_msg('inc. size: ${app.size}', 1)\n}\n\n@[inline]\nfn (mut app App) dec_size() {\n\tif app.size > 1 {\n\t\tapp.size--\n\t}\n\tapp.show_msg('dec. size: ${app.size}', 1)\n}\n\nfn (mut app App) footer_click(event &ui.Event) {\n\tfooter_y := 3 - (app.ui.window_height - event.y)\n\tmatch event.x {\n\t\t8...11 {\n\t\t\tapp.inc_size()\n\t\t}\n\t\t12...15 {\n\t\t\tapp.dec_size()\n\t\t}\n\t\t18...75 {\n\t\t\tif (event.x % 3) == 0 {\n\t\t\t\t// Inside the gap between tiles\n\t\t\t\treturn\n\t\t\t}\n\t\t\tidx := footer_y * 19 - 6 + event.x / 3\n\t\t\tif idx < 0 || idx > 56 {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tapp.select_color(event.button == .left, idx)\n\t\t}\n\t\telse {}\n\t}\n}\n\nfn (mut app App) show_msg(text string, time int) {\n\tframes := time * frame_rate\n\tapp.msg_hide_tick = if time > 0 { int(app.ui.frame_count) + frames } else { -1 }\n\tapp.msg = text\n}\n"
  },
  {
    "path": "examples/term.ui/text_editor.v",
    "content": "// Copyright (c) 2020 Lars Pontoppidan. All rights reserved.\n// Use of this source code is governed by the MIT license distributed with this software.\n// Don't use this editor for any serious work.\n// A lot of functionality is missing compared to your favourite editor :)\nimport strings\nimport os\nimport math\nimport term.ui as tui\nimport encoding.utf8\nimport encoding.utf8.east_asian\n\nconst rune_digits = [`0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`]\n\nconst zero_width_unicode = [\n\t`\\u034f`, // U+034F COMBINING GRAPHEME JOINER\n\t`\\u061c`, // U+061C ARABIC LETTER MARK\n\t`\\u17b4`, // U+17B4 KHMER VOWEL INHERENT AQ\n\t`\\u17b5`, // U+17B5 KHMER VOWEL INHERENT AA\n\t`\\u200a`, // U+200A HAIR SPACE\n\t`\\u200b`, // U+200B ZERO WIDTH SPACE\n\t`\\u200c`, // U+200C ZERO WIDTH NON-JOINER\n\t`\\u200d`, // U+200D ZERO WIDTH JOINER\n\t`\\u200e`, // U+200E LEFT-TO-RIGHT MARK\n\t`\\u200f`, // U+200F RIGHT-TO-LEFT MARK\n\t`\\u2060`, // U+2060 WORD JOINER\n\t`\\u2061`, // U+2061 FUNCTION APPLICATION\n\t`\\u2062`, // U+2062 INVISIBLE TIMES\n\t`\\u2063`, // U+2063 INVISIBLE SEPARATOR\n\t`\\u2064`, // U+2064 INVISIBLE PLUS\n\t`\\u206a`, // U+206A INHIBIT SYMMETRIC SWAPPING\n\t`\\u206b`, // U+206B ACTIVATE SYMMETRIC SWAPPING\n\t`\\u206c`, // U+206C INHIBIT ARABIC FORM SHAPING\n\t`\\u206d`, // U+206D ACTIVATE ARABIC FORM SHAPING\n\t`\\u206e`, // U+206E NATIONAL DIGIT SHAPES\n\t`\\u206f`, // U+206F NOMINAL DIGIT SHAPES\n\t`\\ufeff`, // U+FEFF ZERO WIDTH NO-BREAK SPACE\n]\n\nenum Movement {\n\tup\n\tdown\n\tleft\n\tright\n\thome\n\tend\n\tpage_up\n\tpage_down\n}\n\nstruct View {\npub:\n\traw    string\n\tcursor Cursor\n}\n\nstruct App {\nmut:\n\ttui           &tui.Context = unsafe { nil }\n\ted            &Buffer      = unsafe { nil }\n\tcurrent_file  int\n\tfiles         []string\n\tstatus        string\n\tt             int\n\tmagnet_x      int\n\tfooter_height int = 2\n\tviewport      int\n}\n\nfn (mut a App) set_status(msg string, duration_ms int) {\n\ta.status = msg\n\ta.t = duration_ms\n}\n\nfn (mut a App) save() {\n\tif a.cfile().len > 0 {\n\t\tb := a.ed\n\t\tos.write_file(a.cfile(), b.raw()) or { panic(err) }\n\t\ta.set_status('Saved', 2000)\n\t} else {\n\t\ta.set_status('No file loaded', 4000)\n\t}\n}\n\nfn (mut a App) cfile() string {\n\tif a.files.len == 0 {\n\t\treturn ''\n\t}\n\tif a.current_file >= a.files.len {\n\t\treturn ''\n\t}\n\treturn a.files[a.current_file]\n}\n\nfn (mut a App) visit_prev_file() {\n\tif a.files.len == 0 {\n\t\ta.current_file = 0\n\t} else {\n\t\ta.current_file = (a.current_file + a.files.len - 1) % a.files.len\n\t}\n\ta.init_file()\n}\n\nfn (mut a App) visit_next_file() {\n\tif a.files.len == 0 {\n\t\ta.current_file = 0\n\t} else {\n\t\ta.current_file = (a.current_file + a.files.len + 1) % a.files.len\n\t}\n\ta.init_file()\n}\n\nfn (mut a App) footer() {\n\tw, h := a.tui.window_width, a.tui.window_height\n\tmut b := a.ed\n\t// flat := b.flat()\n\t// snip := if flat.len > 19 { flat[..20] } else { flat }\n\tfinfo := if a.cfile().len > 0 { ' (' + os.file_name(a.cfile()) + ')' } else { '' }\n\tmut status := a.status\n\ta.tui.draw_text(0, h - 1, '─'.repeat(w))\n\tfooter := '${finfo} Line ${b.cursor.pos_y + 1:4}/${b.lines.len:-4}, Column ${b.cursor.pos_x + 1:3}/${b.cur_line().len:-3} index: ${b.cursor_index():5} (ESC = quit, Ctrl+s = save)'\n\tif footer.len < w {\n\t\ta.tui.draw_text((w - footer.len) / 2, h, footer)\n\t} else if footer.len == w {\n\t\ta.tui.draw_text(0, h, footer)\n\t} else {\n\t\ta.tui.draw_text(0, h, footer[..w])\n\t}\n\tif a.t <= 0 {\n\t\tstatus = ''\n\t} else {\n\t\ta.tui.set_bg_color(\n\t\t\tr: 200\n\t\t\tg: 200\n\t\t\tb: 200\n\t\t)\n\t\ta.tui.set_color(\n\t\t\tr: 0\n\t\t\tg: 0\n\t\t\tb: 0\n\t\t)\n\t\ta.tui.draw_text((w + 4 - status.len) / 2, h - 1, ' ${status} ')\n\t\ta.tui.reset()\n\t\ta.t -= 33\n\t}\n}\n\nstruct Buffer {\n\ttab_width int = 4\npub mut:\n\tlines  []string\n\tcursor Cursor\n}\n\nfn (b Buffer) flat() string {\n\treturn b.raw().replace_each(['\\n', r'\\n', '\\t', r'\\t'])\n}\n\nfn (b Buffer) raw() string {\n\treturn b.lines.join('\\n')\n}\n\nfn (b Buffer) view(from int, to int) View {\n\tl := b.cur_line().runes()\n\tmut x := 0\n\tfor i := 0; i < b.cursor.pos_x && i < l.len; i++ {\n\t\tif l[i] == `\\t` {\n\t\t\tx += b.tab_width\n\t\t\tcontinue\n\t\t}\n\t\tx++\n\t}\n\tmut lines := []string{}\n\tfor i, line in b.lines {\n\t\tif i >= from && i <= to {\n\t\t\tlines << line\n\t\t}\n\t}\n\traw := lines.join('\\n')\n\treturn View{\n\t\traw:    raw.replace('\\t', strings.repeat(` `, b.tab_width))\n\t\tcursor: Cursor{\n\t\t\tpos_x: x\n\t\t\tpos_y: b.cursor.pos_y\n\t\t}\n\t}\n}\n\nfn (b Buffer) line(i int) string {\n\tif i < 0 || i >= b.lines.len {\n\t\treturn ''\n\t}\n\treturn b.lines[i]\n}\n\nfn (b Buffer) cur_line() string {\n\treturn b.line(b.cursor.pos_y)\n}\n\nfn (b Buffer) cur_slice() string {\n\tline := b.line(b.cursor.pos_y).runes()\n\tif b.cursor.pos_x == 0 || b.cursor.pos_x > line.len {\n\t\treturn ''\n\t}\n\treturn line[..b.cursor.pos_x].string()\n}\n\nfn (b Buffer) cursor_index() int {\n\tmut i := 0\n\tfor y, line in b.lines {\n\t\tif b.cursor.pos_y == y {\n\t\t\ti += b.cursor.pos_x\n\t\t\tbreak\n\t\t}\n\t\ti += line.runes().len + 1\n\t}\n\treturn i\n}\n\nfn (mut b Buffer) put(s string) {\n\thas_line_ending := s.contains('\\n')\n\tx, y := b.cursor.xy()\n\tif b.lines.len == 0 {\n\t\tb.lines.prepend('')\n\t}\n\tline := b.lines[y].runes()\n\tl, r := line[..x].string(), line[x..].string()\n\tif has_line_ending {\n\t\tmut lines := s.split('\\n')\n\t\tlines[0] = l + lines[0]\n\t\tlines[lines.len - 1] += r\n\t\tb.lines.delete(y)\n\t\tb.lines.insert(y, lines)\n\t\tlast := lines[lines.len - 1].runes()\n\t\tb.cursor.set(last.len, y + lines.len - 1)\n\t\tif s == '\\n' {\n\t\t\tb.cursor.set(0, b.cursor.pos_y)\n\t\t}\n\t} else {\n\t\tb.lines[y] = l + s + r\n\t\tb.cursor.set(x + s.runes().len, y)\n\t}\n\t$if debug {\n\t\tflat := s.replace('\\n', r'\\n')\n\t\teprintln(@MOD + '.' + @STRUCT + '::' + @FN + ' \"${flat}\"')\n\t}\n}\n\nfn (mut b Buffer) del(amount int) string {\n\tif amount == 0 {\n\t\treturn ''\n\t}\n\tx, y := b.cursor.xy()\n\tif amount < 0 { // don't delete left if we're at 0,0\n\t\tif x == 0 && y == 0 {\n\t\t\treturn ''\n\t\t}\n\t} else if x >= b.cur_line().runes().len && y >= b.lines.len - 1 {\n\t\treturn ''\n\t}\n\tmut removed := ''\n\tif amount < 0 { // backspace (backward)\n\t\ti := b.cursor_index()\n\t\traw_runes := b.raw().runes()\n\t\tremoved = raw_runes[i + amount..i].string()\n\t\tmut left := amount * -1\n\t\tfor li := y; li >= 0 && left > 0; li-- {\n\t\t\tln := b.lines[li].runes()\n\t\t\tif left == ln.len + 1 { // All of the line + 1 - since we're going backwards the \"+1\" is the line break delimiter.\n\t\t\t\tb.lines.delete(li)\n\t\t\t\tleft = 0\n\t\t\t\tif y == 0 {\n\t\t\t\t\treturn ''\n\t\t\t\t}\n\t\t\t\tline_above := b.lines[li - 1].runes()\n\t\t\t\tb.cursor.pos_x = line_above.len\n\t\t\t\tb.cursor.pos_y--\n\t\t\t\tbreak\n\t\t\t} else if left > ln.len {\n\t\t\t\tb.lines.delete(li)\n\t\t\t\tif ln.len == 0 { // line break delimiter\n\t\t\t\t\tleft--\n\t\t\t\t\tif y == 0 {\n\t\t\t\t\t\treturn ''\n\t\t\t\t\t}\n\t\t\t\t\tline_above := b.lines[li - 1].runes()\n\t\t\t\t\tb.cursor.pos_x = line_above.len\n\t\t\t\t} else {\n\t\t\t\t\tleft -= ln.len\n\t\t\t\t}\n\t\t\t\tb.cursor.pos_y--\n\t\t\t} else {\n\t\t\t\tif x == 0 {\n\t\t\t\t\tif y == 0 {\n\t\t\t\t\t\treturn ''\n\t\t\t\t\t}\n\t\t\t\t\tline_above := b.lines[li - 1].runes()\n\t\t\t\t\tif ln.len == 0 { // at line break\n\t\t\t\t\t\tb.lines.delete(li)\n\t\t\t\t\t\tb.cursor.pos_y--\n\t\t\t\t\t\tb.cursor.pos_x = line_above.len\n\t\t\t\t\t} else {\n\t\t\t\t\t\tb.lines[li - 1] = line_above.string() + ln.string()\n\t\t\t\t\t\tb.lines.delete(li)\n\t\t\t\t\t\tb.cursor.pos_y--\n\t\t\t\t\t\tb.cursor.pos_x = line_above.len\n\t\t\t\t\t}\n\t\t\t\t} else if x == 1 {\n\t\t\t\t\trunes := b.lines[li].runes()\n\t\t\t\t\tb.lines[li] = runes[left..].string()\n\t\t\t\t\tb.cursor.pos_x = 0\n\t\t\t\t} else {\n\t\t\t\t\tb.lines[li] = ln[..x - left].string() + ln[x..].string()\n\t\t\t\t\tb.cursor.pos_x -= left\n\t\t\t\t}\n\t\t\t\tleft = 0\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t} else { // delete (forward)\n\t\ti := b.cursor_index() + 1\n\t\traw_buffer := b.raw().runes()\n\t\tfrom_i := i\n\t\tmut to_i := i + amount\n\n\t\tif to_i > raw_buffer.len {\n\t\t\tto_i = raw_buffer.len\n\t\t}\n\t\tremoved = raw_buffer[from_i..to_i].string()\n\t\tmut left := amount\n\t\tfor li := y; li >= 0 && left > 0; li++ {\n\t\t\tln := b.lines[li].runes()\n\t\t\tif x == ln.len { // at line end\n\t\t\t\tif y + 1 <= b.lines.len {\n\t\t\t\t\tb.lines[li] = ln.string() + b.lines[y + 1]\n\t\t\t\t\tb.lines.delete(y + 1)\n\t\t\t\t\tleft--\n\t\t\t\t\tb.del(left)\n\t\t\t\t}\n\t\t\t} else if left > ln.len {\n\t\t\t\tb.lines.delete(li)\n\t\t\t\tleft -= ln.len\n\t\t\t} else {\n\t\t\t\tb.lines[li] = ln[..x].string() + ln[x + left..].string()\n\t\t\t\tleft = 0\n\t\t\t}\n\t\t}\n\t}\n\t$if debug {\n\t\tflat := removed.replace('\\n', r'\\n')\n\t\teprintln(@MOD + '.' + @STRUCT + '::' + @FN + ' \"${flat}\"')\n\t}\n\treturn removed\n}\n\nfn (mut b Buffer) free() {\n\t$if debug {\n\t\teprintln(@MOD + '.' + @STRUCT + '::' + @FN)\n\t}\n\tfor line in b.lines {\n\t\tunsafe { line.free() }\n\t}\n\tunsafe { b.lines.free() }\n}\n\nfn (mut b Buffer) move_updown(amount int) {\n\tb.cursor.move(0, amount)\n\t// Check the move\n\tline := b.cur_line().runes()\n\tif b.cursor.pos_x > line.len {\n\t\tb.cursor.set(line.len, b.cursor.pos_y)\n\t}\n}\n\n// move_cursor will navigate the cursor within the buffer bounds\nfn (mut b Buffer) move_cursor(amount int, movement Movement) {\n\tcur_line := b.cur_line().runes()\n\tmatch movement {\n\t\t.up {\n\t\t\tif b.cursor.pos_y - amount >= 0 {\n\t\t\t\tb.move_updown(-amount)\n\t\t\t}\n\t\t}\n\t\t.down {\n\t\t\tif b.cursor.pos_y + amount < b.lines.len {\n\t\t\t\tb.move_updown(amount)\n\t\t\t}\n\t\t}\n\t\t.page_up {\n\t\t\tdlines := math.min(b.cursor.pos_y, amount)\n\t\t\tb.move_updown(-dlines)\n\t\t}\n\t\t.page_down {\n\t\t\tdlines := math.min(b.lines.len - 1, b.cursor.pos_y + amount) - b.cursor.pos_y\n\t\t\tb.move_updown(dlines)\n\t\t}\n\t\t.left {\n\t\t\tif b.cursor.pos_x - amount >= 0 {\n\t\t\t\tb.cursor.move(-amount, 0)\n\t\t\t} else if b.cursor.pos_y > 0 {\n\t\t\t\tb.cursor.set(b.line(b.cursor.pos_y - 1).runes().len, b.cursor.pos_y - 1)\n\t\t\t}\n\t\t}\n\t\t.right {\n\t\t\tif b.cursor.pos_x + amount <= cur_line.len {\n\t\t\t\tb.cursor.move(amount, 0)\n\t\t\t} else if b.cursor.pos_y + 1 < b.lines.len {\n\t\t\t\tb.cursor.set(0, b.cursor.pos_y + 1)\n\t\t\t}\n\t\t}\n\t\t.home {\n\t\t\tb.cursor.set(0, b.cursor.pos_y)\n\t\t}\n\t\t.end {\n\t\t\tb.cursor.set(cur_line.len, b.cursor.pos_y)\n\t\t}\n\t}\n}\n\nfn (mut b Buffer) move_to_word(movement Movement) {\n\ta := if movement == .left { -1 } else { 1 }\n\n\tmut line := b.cur_line().runes()\n\tmut x, mut y := b.cursor.pos_x, b.cursor.pos_y\n\tif x + a < 0 && y > 0 {\n\t\ty--\n\t\tline = b.line(b.cursor.pos_y - 1).runes()\n\t\tx = line.len\n\t} else if x + a >= line.len && y + 1 < b.lines.len {\n\t\ty++\n\t\tline = b.line(b.cursor.pos_y + 1).runes()\n\t\tx = 0\n\t}\n\t// first, move past all non-`a-zA-Z0-9_` characters\n\tfor x + a >= 0 && x + a < line.len && !(utf8.is_letter(line[x + a])\n\t\t|| line[x + a] in rune_digits || line[x + a] == `_`) {\n\t\tx += a\n\t}\n\t// then, move past all the letters and numbers\n\tfor x + a >= 0 && x + a < line.len && (utf8.is_letter(line[x + a])\n\t\t|| line[x + a] in rune_digits || line[x + a] == `_`) {\n\t\tx += a\n\t}\n\t// if the cursor is out of bounds, move it to the next/previous line\n\tif x + a >= 0 && x + a <= line.len {\n\t\tx += a\n\t} else if a < 0 && y + 1 > b.lines.len && y - 1 >= 0 {\n\t\ty += a\n\t\tx = 0\n\t}\n\tb.cursor.set(x, y)\n}\n\nstruct Cursor {\npub mut:\n\tpos_x int\n\tpos_y int\n}\n\nfn (mut c Cursor) set(x int, y int) {\n\tc.pos_x = x\n\tc.pos_y = y\n}\n\nfn (mut c Cursor) move(x int, y int) {\n\tc.pos_x += x\n\tc.pos_y += y\n}\n\nfn (c Cursor) xy() (int, int) {\n\treturn c.pos_x, c.pos_y\n}\n\n// App callbacks\nfn init(mut app App) {\n\tapp.init_file()\n}\n\nfn (mut a App) init_file() {\n\ta.ed = &Buffer{}\n\tmut init_y := 0\n\tmut init_x := 0\n\tif a.files.len > 0 && a.current_file < a.files.len && a.files[a.current_file].len > 0 {\n\t\tif !os.is_file(a.files[a.current_file]) && a.files[a.current_file].contains(':') {\n\t\t\t// support the file:line:col: format\n\t\t\tfparts := a.files[a.current_file].split(':')\n\t\t\tif fparts.len > 0 {\n\t\t\t\ta.files[a.current_file] = fparts[0]\n\t\t\t}\n\t\t\tif fparts.len > 1 {\n\t\t\t\tinit_y = fparts[1].int() - 1\n\t\t\t}\n\t\t\tif fparts.len > 2 {\n\t\t\t\tinit_x = fparts[2].int() - 1\n\t\t\t}\n\t\t}\n\t\tif os.is_file(a.files[a.current_file]) {\n\t\t\t// 'vico: ' +\n\t\t\ta.tui.set_window_title(a.files[a.current_file])\n\t\t\tmut b := a.ed\n\t\t\tcontent := os.read_file(a.files[a.current_file]) or { panic(err) }\n\t\t\tb.put(content)\n\t\t\ta.ed.cursor.pos_x = init_x\n\t\t\ta.ed.cursor.pos_y = init_y\n\t\t}\n\t}\n}\n\nfn (a &App) view_height() int {\n\treturn a.tui.window_height - a.footer_height - 1\n}\n\n// magnet_cursor_x will place the cursor as close to it's last move left or right as possible\nfn (mut a App) magnet_cursor_x() {\n\tmut buffer := a.ed\n\tif buffer.cursor.pos_x < a.magnet_x {\n\t\tif a.magnet_x < buffer.cur_line().runes().len {\n\t\t\tmove_x := a.magnet_x - buffer.cursor.pos_x\n\t\t\tbuffer.move_cursor(move_x, .right)\n\t\t}\n\t}\n}\n\nfn frame(mut a App) {\n\tmut ed := a.ed\n\ta.tui.clear()\n\tscroll_limit := a.view_height()\n\t// scroll down\n\tif ed.cursor.pos_y > a.viewport + scroll_limit { // scroll down\n\t\ta.viewport = ed.cursor.pos_y - scroll_limit\n\t} else if ed.cursor.pos_y < a.viewport { // scroll up\n\t\ta.viewport = ed.cursor.pos_y\n\t}\n\tview := ed.view(a.viewport, scroll_limit + a.viewport)\n\ta.tui.draw_text(0, 0, view.raw)\n\ta.footer()\n\n\t// Unicode: Handle correct mapping of cursor X position in terminal.\n\tmut ch_x := view.cursor.pos_x\n\tmut sl := ed.cur_slice().replace('\\t', ' '.repeat(ed.tab_width))\n\tif sl.len > 0 {\n\t\t// Strip out any zero-width codepoints.\n\t\tsl = sl.runes().filter(it !in zero_width_unicode).string()\n\t\tch_x = east_asian.display_width(sl, 1)\n\t}\n\n\ta.tui.set_cursor_position(ch_x + 1, ed.cursor.pos_y + 1 - a.viewport)\n\ta.tui.flush()\n}\n\nfn event(e &tui.Event, mut a App) {\n\tmut buffer := a.ed\n\tif e.typ == .key_down {\n\t\tmatch e.code {\n\t\t\t.escape {\n\t\t\t\texit(0)\n\t\t\t}\n\t\t\t.enter {\n\t\t\t\tbuffer.put('\\n')\n\t\t\t}\n\t\t\t.backspace {\n\t\t\t\tbuffer.del(-1)\n\t\t\t}\n\t\t\t.delete {\n\t\t\t\tbuffer.del(1)\n\t\t\t}\n\t\t\t.left {\n\t\t\t\tif e.modifiers == .ctrl {\n\t\t\t\t\tbuffer.move_to_word(.left)\n\t\t\t\t} else if e.modifiers.is_empty() {\n\t\t\t\t\tbuffer.move_cursor(1, .left)\n\t\t\t\t}\n\t\t\t\ta.magnet_x = buffer.cursor.pos_x\n\t\t\t}\n\t\t\t.right {\n\t\t\t\tif e.modifiers == .ctrl {\n\t\t\t\t\tbuffer.move_to_word(.right)\n\t\t\t\t} else if e.modifiers.is_empty() {\n\t\t\t\t\tbuffer.move_cursor(1, .right)\n\t\t\t\t}\n\t\t\t\ta.magnet_x = buffer.cursor.pos_x\n\t\t\t}\n\t\t\t.up {\n\t\t\t\tbuffer.move_cursor(1, .up)\n\t\t\t\ta.magnet_cursor_x()\n\t\t\t}\n\t\t\t.down {\n\t\t\t\tbuffer.move_cursor(1, .down)\n\t\t\t\ta.magnet_cursor_x()\n\t\t\t}\n\t\t\t.page_up {\n\t\t\t\tbuffer.move_cursor(a.view_height(), .page_up)\n\t\t\t}\n\t\t\t.page_down {\n\t\t\t\tbuffer.move_cursor(a.view_height(), .page_down)\n\t\t\t}\n\t\t\t.home {\n\t\t\t\tbuffer.move_cursor(1, .home)\n\t\t\t}\n\t\t\t.end {\n\t\t\t\tbuffer.move_cursor(1, .end)\n\t\t\t}\n\t\t\t48...57, 97...122 { // 0-9a-zA-Z\n\t\t\t\tif e.modifiers == .ctrl {\n\t\t\t\t\tif e.code == .s {\n\t\t\t\t\t\ta.save()\n\t\t\t\t\t}\n\t\t\t\t} else if !(e.modifiers.has(.ctrl | .alt) || e.code == .null) {\n\t\t\t\t\tbuffer.put(e.ascii.ascii_str())\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif e.modifiers == .alt {\n\t\t\t\t\tif e.code == .comma {\n\t\t\t\t\t\ta.visit_prev_file()\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tif e.code == .period {\n\t\t\t\t\t\ta.visit_next_file()\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbuffer.put(e.utf8)\n\t\t\t}\n\t\t}\n\t} else if e.typ == .mouse_scroll {\n\t\tdirection := if e.direction == .up { Movement.down } else { Movement.up }\n\t\tbuffer.move_cursor(1, direction)\n\t}\n}\n\ntype InitFn = fn (voidptr)\n\ntype EventFn = fn (&tui.Event, voidptr)\n\ntype FrameFn = fn (voidptr)\n\nfn main() {\n\tmut files := []string{}\n\tif os.args.len > 1 {\n\t\tfiles << os.args[1..]\n\t}\n\tmut a := &App{\n\t\tfiles: files\n\t}\n\ta.tui = tui.init(\n\t\tuser_data:      a\n\t\tinit_fn:        InitFn(init)\n\t\tframe_fn:       FrameFn(frame)\n\t\tevent_fn:       EventFn(event)\n\t\tcapture_events: true\n\t)\n\ta.tui.run()!\n}\n"
  },
  {
    "path": "examples/term.ui/vyper.v",
    "content": "// import modules for use in app\nimport term.ui as termui\nimport rand\nimport math.vec\n\n// define some global constants\nconst block_size = 1\nconst buffer = 10\nconst green = termui.Color{0, 255, 0}\nconst grey = termui.Color{150, 150, 150}\nconst white = termui.Color{255, 255, 255}\nconst blue = termui.Color{0, 0, 255}\nconst red = termui.Color{255, 0, 0}\nconst black = termui.Color{0, 0, 0}\n\n// what edge of the screen are you facing\nenum Orientation {\n\ttop\n\tright\n\tbottom\n\tleft\n}\n\n// what's the current state of the game\nenum GameState {\n\tpause\n\tgameover\n\tgame\n\toob // snake out-of-bounds\n}\n\n// simple 2d vector representation\ntype Vec = vec.Vec2[int]\n\n// determine orientation from vector (hacky way to set facing from velocity)\nfn (v Vec) facing() Orientation {\n\tresult := if v.x >= 0 {\n\t\tOrientation.right\n\t} else if v.x < 0 {\n\t\tOrientation.left\n\t} else if v.y >= 0 {\n\t\tOrientation.bottom\n\t} else {\n\t\tOrientation.top\n\t}\n\treturn result\n}\n\n// generate a random vector with x in [min_x, max_x] and y in [min_y, max_y]\nfn (mut v Vec) randomize(min_x int, min_y int, max_x int, max_y int) {\n\tv.x = rand.int_in_range(min_x, max_x) or { min_x }\n\tv.y = rand.int_in_range(min_y, max_y) or { min_y }\n}\n\n// part of snake's body representation\nstruct BodyPart {\nmut:\n\tpos    Vec          = Vec{block_size, block_size}\n\tcolor  termui.Color = green\n\tfacing Orientation  = .top\n}\n\n// snake representation\nstruct Snake {\nmut:\n\tapp       &App = unsafe { nil }\n\tdirection Orientation\n\tbody      []BodyPart\n\tvelocity  Vec\n}\n\n// length returns the snake's current length\nfn (s Snake) length() int {\n\treturn s.body.len\n}\n\n// impulse provides a impulse to change the snake's direction\nfn (mut s Snake) impulse(direction Orientation) {\n\tmut vel := Vec{}\n\tmatch direction {\n\t\t.top {\n\t\t\tvel.x = 0\n\t\t\tvel.y = -1 * block_size\n\t\t}\n\t\t.right {\n\t\t\tvel.x = 2 * block_size\n\t\t\tvel.y = 0\n\t\t}\n\t\t.bottom {\n\t\t\tvel.x = 0\n\t\t\tvel.y = block_size\n\t\t}\n\t\t.left {\n\t\t\tvel.x = -2 * block_size\n\t\t\tvel.y = 0\n\t\t}\n\t}\n\ts.direction = direction\n\ts.velocity = vel\n}\n\n// move performs the calculations for the snake's movements\nfn (mut s Snake) move() {\n\tmut i := s.body.len - 1\n\twidth := s.app.width\n\theight := s.app.height\n\t// move the parts of the snake as appropriate\n\tfor i = s.body.len - 1; i >= 0; i-- {\n\t\tmut piece := s.body[i]\n\t\tif i > 0 { // just move the body of the snake up one position\n\t\t\tpiece.pos = s.body[i - 1].pos\n\t\t\tpiece.facing = s.body[i - 1].facing\n\t\t} else { // verify that the move is valid and move the head if so\n\t\t\tpiece.facing = s.direction\n\t\t\tnew_x := piece.pos.x + s.velocity.x\n\t\t\tnew_y := piece.pos.y + s.velocity.y\n\t\t\tpiece.pos.x += if new_x > block_size && new_x < width - block_size {\n\t\t\t\ts.velocity.x\n\t\t\t} else {\n\t\t\t\t0\n\t\t\t}\n\t\t\tpiece.pos.y += if new_y > block_size && new_y < height - block_size {\n\t\t\t\ts.velocity.y\n\t\t\t} else {\n\t\t\t\t0\n\t\t\t}\n\t\t}\n\t\ts.body[i] = piece\n\t}\n}\n\n// grow add another part to the snake when it catches the rat\nfn (mut s Snake) grow() {\n\thead := s.get_tail()\n\tmut pos := Vec{}\n\t// add the segment on the opposite side of the previous tail\n\tmatch head.facing {\n\t\t.bottom {\n\t\t\tpos.x = head.pos.x\n\t\t\tpos.y = head.pos.y - block_size\n\t\t}\n\t\t.left {\n\t\t\tpos.x = head.pos.x + block_size\n\t\t\tpos.y = head.pos.y\n\t\t}\n\t\t.top {\n\t\t\tpos.x = head.pos.x\n\t\t\tpos.y = head.pos.y + block_size\n\t\t}\n\t\t.right {\n\t\t\tpos.x = head.pos.x - block_size\n\t\t\tpos.y = head.pos.y\n\t\t}\n\t}\n\ts.body << BodyPart{\n\t\tpos:    pos\n\t\tfacing: head.facing\n\t}\n}\n\n// get_body gets the parts of the snakes body\nfn (s Snake) get_body() []BodyPart {\n\treturn s.body\n}\n\n// get_head get snake's head\nfn (s Snake) get_head() BodyPart {\n\treturn s.body[0]\n}\n\n// get_tail get snake's tail\nfn (s Snake) get_tail() BodyPart {\n\treturn s.body[s.body.len - 1]\n}\n\n// randomize randomizes position and veolcity of snake\nfn (mut s Snake) randomize() {\n\tspeeds := [-2, 0, 2]\n\tmut pos := s.get_head().pos\n\tpos.randomize(buffer, buffer, s.app.width - buffer, s.app.height - buffer)\n\tfor pos.x % 2 != 0 || (pos.x < buffer && pos.x > s.app.width - buffer) {\n\t\tpos.randomize(buffer, buffer, s.app.width - buffer, s.app.height - buffer)\n\t}\n\ts.velocity.y = rand.int_in_range(-1 * block_size, block_size) or { 0 }\n\ts.velocity.x = speeds[rand.intn(speeds.len) or { 0 }]\n\ts.direction = s.velocity.facing()\n\ts.body[0].pos = pos\n}\n\n// check_overlap determine if the snake's looped onto itself\nfn (s Snake) check_overlap() bool {\n\th := s.get_head()\n\thead_pos := h.pos\n\tfor i in 2 .. s.length() {\n\t\tpiece_pos := s.body[i].pos\n\t\tif head_pos.x == piece_pos.x && head_pos.y == piece_pos.y {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfn (s Snake) check_out_of_bounds() bool {\n\th := s.get_head()\n\treturn h.pos.x + s.velocity.x <= block_size\n\t\t|| h.pos.x + s.velocity.x > s.app.width - s.velocity.x\n\t\t|| h.pos.y + s.velocity.y <= block_size\n\t\t|| h.pos.y + s.velocity.y > s.app.height - block_size - s.velocity.y\n}\n\n// draw draws the parts of the snake\nfn (s Snake) draw() {\n\tmut a := s.app\n\tfor part in s.get_body() {\n\t\ta.termui.set_bg_color(part.color)\n\t\ta.termui.draw_rect(part.pos.x, part.pos.y, part.pos.x + block_size, part.pos.y + block_size)\n\t\t$if verbose ? {\n\t\t\ttext := match part.facing {\n\t\t\t\t.top { '^' }\n\t\t\t\t.bottom { 'v' }\n\t\t\t\t.right { '>' }\n\t\t\t\t.left { '<' }\n\t\t\t}\n\t\t\ta.termui.set_color(white)\n\t\t\ta.termui.draw_text(part.pos.x, part.pos.y, text)\n\t\t}\n\t}\n}\n\n// rat representation\nstruct Rat {\nmut:\n\tpos      Vec = Vec{block_size, block_size}\n\tcaptured bool\n\tcolor    termui.Color = grey\n\tapp      &App         = unsafe { nil }\n}\n\n// randomize spawn the rat in a new spot within the playable field\nfn (mut r Rat) randomize() {\n\tr.pos.randomize(2 * block_size + buffer, 2 * block_size + buffer, r.app.width - block_size - buffer,\n\t\tr.app.height - block_size - buffer)\n}\n\n@[heap]\nstruct App {\nmut:\n\ttermui &termui.Context = unsafe { nil }\n\tsnake  Snake\n\trat    Rat\n\twidth  int\n\theight int\n\tredraw bool      = true\n\tstate  GameState = .game\n}\n\n// new_game setups the rat and snake for play\nfn (mut a App) new_game() {\n\tmut snake := Snake{\n\t\tbody: []BodyPart{len: 1, init: BodyPart{}}\n\t\tapp:  a\n\t}\n\tsnake.randomize()\n\tmut rat := Rat{\n\t\tapp: a\n\t}\n\trat.randomize()\n\ta.snake = snake\n\ta.rat = rat\n\ta.state = .game\n\ta.redraw = true\n}\n\n// initialize the app and record the width and height of the window\nfn init(mut app App) {\n\tw, h := app.termui.window_width, app.termui.window_height\n\tapp.width = w\n\tapp.height = h\n\tapp.new_game()\n}\n\n// event handles different events for the app as they occur\nfn event(e &termui.Event, mut app App) {\n\tmatch e.typ {\n\t\t.mouse_down {}\n\t\t.mouse_drag {}\n\t\t.mouse_up {}\n\t\t.key_down {\n\t\t\tmatch e.code {\n\t\t\t\t.up, .w { app.move_snake(.top) }\n\t\t\t\t.down, .s { app.move_snake(.bottom) }\n\t\t\t\t.left, .a { app.move_snake(.left) }\n\t\t\t\t.right, .d { app.move_snake(.right) }\n\t\t\t\t.r { app.new_game() }\n\t\t\t\t.c {}\n\t\t\t\t.p { app.state = if app.state == .game { GameState.pause } else { GameState.game } }\n\t\t\t\t.escape, .q { exit(0) }\n\t\t\t\telse { exit(0) }\n\t\t\t}\n\t\t\tif e.code == .c {\n\t\t\t} else if e.code == .escape {\n\t\t\t\texit(0)\n\t\t\t}\n\t\t}\n\t\telse {}\n\t}\n\tapp.redraw = true\n}\n\n// frame perform actions on every tick\nfn frame(mut app App) {\n\tapp.update()\n\tapp.draw()\n}\n\n// update perform any calculations that are needed before drawing\nfn (mut a App) update() {\n\tif a.state == .game {\n\t\ta.snake.move()\n\t\tif a.snake.check_out_of_bounds() {\n\t\t\t$if verbose ? {\n\t\t\t\ta.snake.body[0].color = red\n\t\t\t} $else {\n\t\t\t\ta.state = .oob\n\t\t\t}\n\t\t}\n\t\tif a.snake.check_overlap() {\n\t\t\ta.state = .gameover\n\t\t\treturn\n\t\t}\n\t\tif a.check_capture() {\n\t\t\ta.rat.randomize()\n\t\t\ta.snake.grow()\n\t\t}\n\t}\n}\n\n// draw write to the screen\nfn (mut a App) draw() {\n\t// reset screen\n\ta.termui.clear()\n\ta.termui.set_bg_color(white)\n\ta.termui.draw_empty_rect(1, 1, a.width, a.height)\n\t// determine if a special screen needs to be draw\n\tmatch a.state {\n\t\t.gameover {\n\t\t\ta.draw_gameover()\n\t\t\ta.redraw = false\n\t\t}\n\t\t.pause {\n\t\t\ta.draw_pause()\n\t\t}\n\t\telse {\n\t\t\ta.redraw = true\n\t\t}\n\t}\n\ta.termui.set_color(blue)\n\ta.termui.set_bg_color(white)\n\ta.termui.draw_text(3 * block_size, a.height - (2 * block_size), 'p - (un)pause r - reset q - quit')\n\t// draw the snake, rat, and score if appropriate\n\tif a.redraw {\n\t\ta.termui.set_bg_color(black)\n\t\ta.draw_gamescreen()\n\t\tif a.state == .oob {\n\t\t\ta.state = .gameover\n\t\t}\n\t}\n\t// write to the screen\n\ta.termui.reset_bg_color()\n\ta.termui.flush()\n}\n\n// move_snake move the snake in specified direction\nfn (mut a App) move_snake(direction Orientation) {\n\ta.snake.impulse(direction)\n}\n\n// check_capture determine if the snake overlaps with the rat\nfn (a App) check_capture() bool {\n\tsnake_pos := a.snake.get_head().pos\n\trat_pos := a.rat.pos\n\treturn snake_pos.x <= rat_pos.x + block_size && snake_pos.x + block_size >= rat_pos.x\n\t\t&& snake_pos.y <= rat_pos.y + block_size && snake_pos.y + block_size >= rat_pos.y\n}\n\nfn (mut a App) draw_snake() {\n\ta.snake.draw()\n}\n\nfn (mut a App) draw_rat() {\n\ta.termui.set_bg_color(a.rat.color)\n\ta.termui.draw_rect(a.rat.pos.x, a.rat.pos.y, a.rat.pos.x + block_size, a.rat.pos.y + block_size)\n}\n\nfn (mut a App) draw_gamescreen() {\n\t$if verbose ? {\n\t\ta.draw_debug()\n\t}\n\ta.draw_score()\n\ta.draw_rat()\n\ta.draw_snake()\n}\n\nfn (mut a App) draw_score() {\n\ta.termui.set_color(blue)\n\ta.termui.set_bg_color(white)\n\tscore := a.snake.length() - 1\n\ta.termui.draw_text(a.width - (2 * block_size), block_size, '${score:03d}')\n}\n\nfn (mut a App) draw_pause() {\n\ta.termui.set_color(blue)\n\ta.termui.draw_text((a.width / 2) - block_size, 3 * block_size, 'Paused!')\n}\n\nfn (mut a App) draw_debug() {\n\ta.termui.set_color(blue)\n\ta.termui.set_bg_color(white)\n\tsnake := a.snake\n\ta.termui.draw_text(block_size, 1 * block_size, 'Display_width: ${a.width:04d} Display_height: ${a.height:04d}')\n\ta.termui.draw_text(block_size, 2 * block_size, 'Vx: ${snake.velocity.x:+02d} Vy: ${snake.velocity.y:+02d}')\n\ta.termui.draw_text(block_size, 3 * block_size, 'F: ${snake.direction}')\n\tsnake_head := snake.get_head()\n\trat := a.rat\n\ta.termui.draw_text(block_size, 4 * block_size, 'Sx: ${snake_head.pos.x:+03d} Sy: ${snake_head.pos.y:+03d}')\n\ta.termui.draw_text(block_size, 5 * block_size, 'Rx: ${rat.pos.x:+03d} Ry: ${rat.pos.y:+03d}')\n}\n\nfn (mut a App) draw_gameover() {\n\ta.termui.set_bg_color(white)\n\ta.termui.set_color(red)\n\ta.rat.pos = Vec{-1, -1}\n\tx_offset := '   #####                        '.len // take half of a line from the game over text and store the length\n\tstart_x := (a.width / 2) - x_offset\n\ta.termui.draw_text(start_x, (a.height / 2) - 3 * block_size, '   #####                         #######                       ')\n\ta.termui.draw_text(start_x, (a.height / 2) - 2 * block_size, '  #     #   ##   #    # ######   #     # #    # ###### #####   ')\n\ta.termui.draw_text(start_x, (a.height / 2) - 1 * block_size, '  #        #  #  ##  ## #        #     # #    # #      #    #  ')\n\ta.termui.draw_text(start_x, (a.height / 2) - 0 * block_size, '  #  #### #    # # ## # #####    #     # #    # #####  #    #  ')\n\ta.termui.draw_text(start_x, (a.height / 2) + 1 * block_size, '  #     # ###### #    # #        #     # #    # #      #####   ')\n\ta.termui.draw_text(start_x, (a.height / 2) + 2 * block_size, '  #     # #    # #    # #        #     #  #  #  #      #   #   ')\n\ta.termui.draw_text(start_x, (a.height / 2) + 3 * block_size, '   #####  #    # #    # ######   #######   ##   ###### #    #  ')\n}\n\ntype InitFn = fn (voidptr)\n\ntype EventFn = fn (&termui.Event, voidptr)\n\ntype FrameFn = fn (voidptr)\n\nfn main() {\n\tmut app := &App{}\n\tapp.termui = termui.init(\n\t\tuser_data:   app\n\t\tevent_fn:    EventFn(event)\n\t\tframe_fn:    FrameFn(frame)\n\t\tinit_fn:     InitFn(init)\n\t\thide_cursor: true\n\t\tframe_rate:  10\n\t)\n\tapp.termui.run()!\n}\n"
  },
  {
    "path": "examples/term_display_sixel.v",
    "content": "module main\n\nimport os\nimport term\n\nfn main() {\n\tprintln('If your terminal supports the sixel graphics format,')\n\tprintln('you should see a small green \"HI\" and a V logo below this text.\\n')\n\tif term.supports_sixel() {\n\t\t// Prints the original \"HI\" sixel image from the spec:\n\t\t// https://www.digiater.nl/openvms/decus/vax90b1/krypton-nasa/all-about-sixels.text (See \"V. EXAMPLE SIXEL IMAGE\" section)\n\t\tprintln('\\ePq\n#0;2;0;0;0#1;2;100;100;0#2;2;0;100;0\n#1~~@@vv@@~~@@~~$\n#2??}}GG}}??}}??-\n#1!14@\n\\e\\\\')\n\t\t// Prints a 128x128 pixels V logo\n\t\tbytes := os.read_bytes(os.resource_abs_path('assets/v.six'))!\n\t\tprintln(bytes.bytestr())\n\t\tdump(term.supports_sixel())\n\t\tdump(term.graphics_num_colors())\n\t}\n}\n"
  },
  {
    "path": "examples/term_key_pressed.v",
    "content": "module main\n\nimport term\nimport time\n\nfn main() {\n\tunbuffer_stdout()\n\tprintln('Press Ctrl-D or ESC to exit.')\n\n\tterm.enable_echo(false)\n\tmut frame := 0\n\tfor {\n\t\tprint('\\r${time.now()} | frame: ${frame:06} | ')\n\t\tx := term.key_pressed()\n\t\tif x in [i64(0), 4, 27] {\n\t\t\t// pressing Ctrl-D or ESC exits the loop\n\t\t\t// Ctrl-D mean EOF sometimes, so return 0\n\t\t\tbreak\n\t\t}\n\t\tif x > 0 {\n\t\t\tprintln('${x:08x}')\n\t\t}\n\t\ttime.sleep(16 * time.millisecond)\n\t\tframe++\n\t}\n\tterm.enable_echo(true)\n\n\tprintln('done')\n}\n"
  },
  {
    "path": "examples/terminal_control.v",
    "content": "import term\n\nfn main() {\n\tterm.erase_clear()\n\tsleeping_line(5, 5, 5, '*')\n\tstanding_line(5, 5, 5, '*')\n\tsleeping_line(5, 10, 5, '*')\n\tstanding_line(9, 5, 5, '*')\n\tterm.cursor_down(5)\n\tprint('\\n')\n\tprintln(term.bold(term.red('It Worked!')))\n}\n\nfn sleeping_line(x int, y int, size int, ch string) {\n\tmut i := 0\n\tfor i < size {\n\t\tterm.set_cursor_position(\n\t\t\tx: x + i\n\t\t\ty: y\n\t\t)\n\t\tprint(term.bold(term.yellow(ch)))\n\t\ti++\n\t}\n}\n\nfn standing_line(x int, y int, size int, ch string) {\n\tmut i := 0\n\tfor i < size {\n\t\tterm.set_cursor_position(\n\t\t\tx: x\n\t\t\ty: y + i\n\t\t)\n\t\tprint(term.bold(term.yellow(ch)))\n\t\ti++\n\t}\n}\n"
  },
  {
    "path": "examples/thread_safety/.gitignore",
    "content": "*.c\n*.out\n"
  },
  {
    "path": "examples/thread_safety/atomic_counter.v",
    "content": "/*\nThis code demonstrates thread safety using atomic operations in V.\n\nThread safety is achieved by using atomic functions to manipulate the shared counter variable.\nAtomic operations ensure that the read-modify-write sequence is performed as a single, indivisible operation,\npreventing race conditions and ensuring data integrity when accessed by multiple threads concurrently.\n\nKey points:\n1. **Atomic Fetch and Add**: The `C.atomic_fetch_add_u32` function atomically increments the counter.\n\tThis means that the increment operation is performed without interruption, ensuring that no two threads\n\tcan increment the counter simultaneously and cause a race condition.\n\n2. **Atomic Load**: The `C.atomic_load_u32` function atomically reads the value of the counter.\n\tThis ensures that the read operation is consistent and not affected by concurrent writes from other threads.\n\n3. **Thread Synchronization**: The `spawn` function is used to create new threads that run the `increment` function.\n\tThe `wait` method is called on each thread to ensure that the main thread waits for both threads to complete\n\tbefore reading the final value of the counter.\n\nBy using atomic operations and proper thread synchronization, the code ensures that the shared counter is\nincremented safely and correctly by multiple threads.\n*/\nimport sync as _\n\n// Function to increment the atomic counter\nfn increment(atomic_counter &u32) {\n\tC.atomic_fetch_add_u32(atomic_counter, 1)\n}\n\nfn main() {\n\tatomic_counter := u32(0) // Atomic counter variable\n\n\t// Spawn two threads that increment the atomic counter\n\tt1 := spawn increment(&atomic_counter)\n\tt2 := spawn increment(&atomic_counter)\n\n\t// Wait for both threads to complete\n\tt1.wait()\n\tt2.wait()\n\n\t// Load and print the final value of the atomic counter\n\tfinal_count := C.atomic_load_u32(&atomic_counter)\n\tprintln('Atomic Counter: ${final_count}')\n}\n"
  },
  {
    "path": "examples/thread_safety/concurrent_shared_data.v",
    "content": "/*\nThis example demonstrates thread safety using V's concurrency features.\nKey points:\n- The `SharedData` struct contains a mutable counter that will be accessed by multiple threads.\n- The `increment` function increments the counter within a lock to ensure that only one thread\ncan modify the counter at a time, preventing race conditions.\n- In the `main` function, two threads are spawned to increment the shared counter concurrently.\n- The `lock` keyword is used to ensure exclusive access to the shared data during modification,\nand the `rlock` keyword is used to allow multiple threads to read the data concurrently without\nmodification.\nThis ensures that the counter is incremented safely and the final value is printed correctly.\n*/\n\nstruct SharedData {\nmut:\n\tcounter int\n}\n\nfn increment(shared data SharedData) {\n\tlock data {\n\t\tdata.counter++\n\t}\n}\n\nfn main() {\n\tshared data := SharedData{}\n\tthreads := [spawn increment(shared data), spawn increment(shared data)]\n\n\tfor t in threads {\n\t\tt.wait() // Wait for both threads to complete\n\t}\n\n\trlock data {\n\t\tprintln('Counter: ${data.counter}')\n\t}\n}\n"
  },
  {
    "path": "examples/thread_safety/queue.v",
    "content": "/*\nThis example demonstrates thread safety using a queue of callbacks.\n\n### Functions:\n- `producer`: creates a callback and adds it to the queue.\n- `consumer`: consumes a callback from the queue and runs it.\n- `heavy_processing`: a heavy processing function that is added to the queue.\n\n### Thread Safety:\n- The `fn producer` function is protected by a mutex. It locks the mutex before adding a callback\nto the queue and unlocks it after adding the callback.\n- The `fn consumer` function is also protected by the same mutex. It locks the mutex before\nconsuming a callback from the queue and unlocks it after consuming the callback.\n- The `heavy_processing` function is added to the queue by the main thread before the producer\nthreads start producing callbacks. The main thread is the only thread that adds this function to\nthe queue, so it doesn't need to be protected by a mutex.\n*/\nimport time\nimport sync\n\ntype Callback = fn (id string)\n\nfn producer(producer_name string, mut arr []Callback, mut mtx sync.Mutex) {\n\tfor i in 1 .. 5 {\n\t\tmtx.lock()\n\t\tarr << fn [producer_name, i] (consumer_name string) {\n\t\t\tprintln('task ${i} created by producer ${producer_name}: consumed by ${consumer_name}')\n\t\t\ttime.sleep(500 * time.millisecond)\n\t\t}\n\t\tprintln('Produced: ${i}')\n\t\ttime.sleep(50 * time.millisecond)\n\t\tmtx.unlock()\n\t}\n}\n\nfn consumer(consumer_name string, mut arr []Callback, mut mtx sync.Mutex) {\n\tfor {\n\t\tmtx.lock()\n\t\tif arr.len > 0 {\n\t\t\tcallback := arr[0]\n\t\t\tarr.delete(0)\n\n\t\t\tmtx.unlock()\n\t\t\tcallback(consumer_name) // run after unlocking to allow other threads to consume\n\t\t\tcontinue\n\t\t} else {\n\t\t\tprintln('- No items to consume')\n\t\t\tmtx.unlock()\n\n\t\t\t// time.sleep(500 * time.millisecond)\n\t\t\t// continue // uncomment to run forever\n\n\t\t\tbreak // uncomment to stop after consuming all items\n\t\t}\n\t}\n}\n\nfn heavy_processing(queue_id string) {\n\tprintln('One more: ${queue_id}')\n\ttime.sleep(500 * time.millisecond)\n}\n\nfn main() {\n\tmut mtx := sync.new_mutex()\n\tmut arr := []Callback{}\n\n\tproducer_threads := [\n\t\tspawn producer('Paula', mut &arr, mut mtx),\n\t\tspawn producer('Adriano', mut &arr, mut mtx),\n\t\tspawn producer('Kaka', mut &arr, mut mtx),\n\t\tspawn producer('Hitalo', mut &arr, mut mtx),\n\t\tspawn producer('Jonh', mut &arr, mut mtx),\n\t]\n\n\tmut consumer_threads := [\n\t\tspawn consumer('consumer number 0', mut &arr, mut mtx),\n\t]\n\n\t// spawn 16 consumers\n\tfor i in 1 .. 16 {\n\t\tconsumer_threads << spawn consumer('consumer number ${i}', mut &arr, mut mtx)\n\t}\n\n\tmtx.lock()\n\tarr << heavy_processing\n\tmtx.unlock()\n\n\tfor t in producer_threads {\n\t\tt.wait()\n\t}\n\tfor t in consumer_threads {\n\t\tt.wait()\n\t}\n}\n"
  },
  {
    "path": "examples/thread_safety/readme.md",
    "content": "### Run\n\n```sh\nv -prod  -gc none -cc gcc ./queue.v && \\\n./queue\n```\n\n### Valgrind\n\n```sh\n# Helgrind: a tool for detecting synchronisation errors in programs that use the POSIX pthreads threading primitives.\nvalgrind --tool=helgrind ./queue\n\n# DRD: a tool for detecting errors in multithreaded programs. The tool works for any program that uses the POSIX threading primitives or that uses threading concepts built on top of the POSIX threading primitives. \nvalgrind --tool=drd ./queue \n```\n"
  },
  {
    "path": "examples/toml.v",
    "content": "import toml\nimport toml.to\n\n// Complete text from the example in the README.md:\n// https://github.com/toml-lang/toml/blob/3b11f6921da7b6f5db37af039aa021fee450c091/README.md#Example\nconst toml_text = '# This is a TOML document.\n\ntitle = \"TOML Example\"\n\n[owner]\nname = \"Tom Preston-Werner\"\ndob = 1979-05-27T07:32:00-08:00 # First class dates\n\n[database]\nserver = \"192.168.1.1\"\nports = [ 8000, 8001, 8002 ]\nconnection_max = 5000\nenabled = true\n\n[servers]\n\n  # Indentation (tabs and/or spaces) is allowed but not required\n  [servers.alpha]\n  ip = \"10.0.0.1\"\n  dc = \"eqdc10\"\n\n  [servers.beta]\n  ip = \"10.0.0.2\"\n  dc = \"eqdc10\"\n\n[clients]\ndata = [ [\"gamma\", \"delta\"], [1, 2] ]\n\n# Line breaks are OK when inside arrays\nhosts = [\n  \"alpha\",\n  \"omega\"\n]'\n\nfn main() {\n\tdoc := toml.parse_text(toml_text) or { panic(err) }\n\ttitle := doc.value('title').string()\n\tprintln('title: \"${title}\"')\n\tip := doc.value('servers.alpha.ip').string()\n\tprintln('Server IP: \"${ip}\"')\n\n\ttoml_json := to.json(doc)\n\tprintln(toml_json)\n}\n"
  },
  {
    "path": "examples/tree_of_nodes.v",
    "content": "type Tree = Empty | Node\n\nstruct Empty {}\n\nstruct Node {\n\tvalue int\n\tleft  Tree\n\tright Tree\n}\n\n// Note: a match expression, infers the type of its result\n// from the type of the return value in the first branch,\n// => it needs an explicit int(0) cast here:\nfn size(tree Tree) int {\n\treturn match tree {\n\t\tEmpty { int(0) }\n\t\tNode { 1 + size(tree.left) + size(tree.right) }\n\t}\n}\n\nfn main() {\n\tnode1 := Node{30, Empty{}, Empty{}}\n\tnode2 := Node{20, Empty{}, Empty{}}\n\ttree := Node{10, node1, node2}\n\tprintln('tree structure:\\n ${tree}')\n\tprintln('tree size: ${size(tree)}')\n}\n"
  },
  {
    "path": "examples/ttf_font/draw_static_text.txt",
    "content": "Hello\nòàèì@ò!£$%&\n满满登登博物馆\n༺ɮʟʊɛ ɛƈֆȶǟֆʏ༻\n尺乇爪丨丨乃ㄖ丨丨\n5 Пятёрочка Russian\nまろの港町 -Port town-\n"
  },
  {
    "path": "examples/ttf_font/draw_static_text.v",
    "content": "import gg\nimport sokol.sapp\nimport sokol.sgl\nimport x.ttf\nimport x.ttf.render_sokol\nimport os\n\nconst custom_font_path = os.args[1] or {\n\tos.resource_abs_path(os.join_path('..', 'assets', 'fonts', 'Imprima-Regular.ttf'))\n}\nconst custom_txt_path = os.args[2] or { os.resource_abs_path('draw_static_text.txt') }\n\nconst custom_text_start_y = 80\n\nconst win_width = 400\nconst win_height = 400\nconst bg_color = gg.Color{50, 255, 50, 255}\n\nconst block_txt = os.read_file(custom_txt_path) or { '' }\nconst font_paths = [\n\tos.resource_abs_path(os.join_path('..', 'assets', 'fonts', 'RobotoMono-Regular.ttf')),\n\tcustom_font_path,\n]\n\n// UI\nstruct App_data {\npub mut:\n\tgg              &gg.Context = unsafe { nil }\n\tinit_flag       bool\n\ttf              []ttf.TTF_File\n\tttf_render      []render_sokol.TTF_render_Sokol\n\ttext_ready_flag bool\n}\n\nfn my_init(mut app App_data) {\n\tapp.init_flag = true\n\ttexts := ['Hello, font: ${os.file_name(custom_font_path)}', block_txt]!\n\tdump(texts[0])\n\tfor i in 0 .. 2 {\n\t\tmut txt := unsafe { &app.ttf_render[i] }\n\t\ttxt.destroy_texture()\n\t\ttxt.create_text_block(texts[i], 1024, 1024, 24)\n\t\ttxt.create_texture()\n\t}\n}\n\nfn draw_frame(mut app App_data) {\n\tapp.gg.begin()\n\tsgl.defaults()\n\tsgl.matrix_mode_projection()\n\tsgl.ortho(0.0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0)\n\tsgl.c4b(0, 0, 0, 255) // black\n\t// draw text only if the app is already initialized\n\tif app.init_flag != true {\n\t\tapp.gg.end()\n\t}\n\n\t// draw hello\n\tmut txt1 := unsafe { &app.ttf_render[0] }\n\ttxt1.draw_text_bmp(app.gg, 5, 5)\n\n\t// draw the custom text\n\ttxt2 := unsafe { &app.ttf_render[1] }\n\ttxt2.draw_text_bmp(app.gg, 30, custom_text_start_y)\n\tapp.gg.end()\n}\n\nfn main() {\n\tprintln('Use `v run draw_static_text.v [FONT_PATH] [TEXT_FILE_PATH]`')\n\tprintln('> Current command: os.args[0] ${custom_font_path} ${custom_txt_path}')\n\tmut app := &App_data{}\n\tapp.gg = gg.new_context(\n\t\twidth:        win_width\n\t\theight:       win_height\n\t\twindow_title: 'Draw custom text, with custom font'\n\t\tuser_data:    app\n\t\tbg_color:     bg_color\n\t\tframe_fn:     draw_frame\n\t\tinit_fn:      my_init\n\t)\n\n\t// load the TTF fonts:\n\tfor font_path in font_paths {\n\t\tmut tf := ttf.TTF_File{}\n\t\ttf.buf = os.read_bytes(font_path) or { panic(err) }\n\t\tprintln('Read TrueTypeFont file [${font_path}], len: ${tf.buf.len}')\n\t\ttf.init()\n\t\tprintln('Unit per EM: ${tf.units_per_em}')\n\t\tapp.tf << tf\n\t}\n\n\t// TTF hello render\n\tapp.ttf_render << &render_sokol.TTF_render_Sokol{\n\t\tbmp: &ttf.BitMap{\n\t\t\ttf:       &app.tf[0]\n\t\t\tbuf:      unsafe { malloc_noscan(32000000) }\n\t\t\tbuf_size: (32000000)\n\t\t\tcolor:    0xFF0000FF\n\t\t}\n\t}\n\n\t// TTF custom text render\n\tapp.ttf_render << &render_sokol.TTF_render_Sokol{\n\t\tbmp: &ttf.BitMap{\n\t\t\ttf:       &app.tf[1]\n\t\t\tbuf:      unsafe { malloc_noscan(32000000) }\n\t\t\tbuf_size: (32000000)\n\t\t\tcolor:    0x2020EEFF\n\t\t}\n\t}\n\n\t// setup sokol_gfx\n\tapp.gg.run()\n}\n"
  },
  {
    "path": "examples/ttf_font/example_ttf.v",
    "content": "import gg\nimport sokol.sapp\nimport sokol.sgl\nimport sokol.gfx\nimport x.ttf\nimport x.ttf.render_sokol\nimport os\n\n// import math\nconst win_width = 600\nconst win_height = 700\nconst bg_color = gg.white\nconst font_paths = [\n\tos.resource_abs_path(os.join_path('..', 'assets', 'fonts', 'Imprima-Regular.ttf')),\n\tos.resource_abs_path(os.join_path('..', 'assets', 'fonts', 'Graduate-Regular.ttf')),\n]\n\n// UI\nstruct App_data {\npub mut:\n\tgg              &gg.Context = unsafe { nil }\n\tsg_img          gfx.Image\n\tinit_flag       bool\n\tframe_c         int\n\ttf              []ttf.TTF_File\n\tttf_render      []render_sokol.TTF_render_Sokol\n\ttext_ready_flag bool\n\tmouse_x         int = -1\n\tmouse_y         int = -1\n}\n\nfn my_init(mut app App_data) {\n\tapp.init_flag = true\n}\n\nfn draw_frame(mut app App_data) {\n\tcframe_txt := 'Current Frame: ${app.frame_c}'\n\tapp.gg.begin()\n\tsgl.defaults()\n\tsgl.matrix_mode_projection()\n\tsgl.ortho(0.0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0)\n\tsgl.c4b(0, 0, 0, 255) // black\n\t// draw a line as background\n\tsgl.begin_line_strip()\n\tsgl.v2f(10, 10)\n\tsgl.v2f(100, 100)\n\tsgl.end()\n\t// draw text only if the app is already initialized\n\tif app.init_flag == true {\n\t\tsgl.begin_line_strip()\n\t\tsgl.v2f(410, 400)\n\t\tsgl.v2f(510, 400)\n\t\tsgl.end()\n\t\t// update the text\n\t\tmut txt1 := unsafe { &app.ttf_render[0] }\n\t\tif app.frame_c % 2 == 0 {\n\t\t\ttxt1.destroy_texture()\n\t\t\ttxt1.create_text(cframe_txt, 43)\n\t\t\ttxt1.create_texture()\n\t\t}\n\t\t// ----- decomment if you want text rotation ----\n\t\t// txt1.bmp.angle = 3.141592 / 180 * f32(app.frame_c % 360)\n\t\t// txt1.draw_text_bmp(app.gg, 300, 350)\n\t\t// txt1.bmp.angle =  0\n\t\ttxt1.draw_text_bmp(app.gg, 30, 60)\n\t\t// block test\n\t\tblock_txt := \"Today it is a good day!\nTomorrow I'm not so sure :(\nFrame: ${app.frame_c}\nBut Vwill prevail for sure, V is the way!!\nòàèì@ò!£$%&\n\"\n\t\ttxt1 = unsafe { &app.ttf_render[1] }\n\t\tif app.frame_c % 2 == 0 {\n\t\t\ttxt1.bmp.justify = false\n\t\t\tif (app.frame_c >> 6) % 2 == 0 {\n\t\t\t\t// txt1.align = .left\n\t\t\t\ttxt1.bmp.justify = true\n\t\t\t}\n\t\t\ttxt1.bmp.align = .left\n\t\t\tif (app.frame_c >> 6) % 3 == 0 {\n\t\t\t\ttxt1.bmp.align = .right\n\t\t\t}\n\t\t\ttxt1.destroy_texture()\n\t\t\ttxt1.create_text_block(block_txt, 500, 500, 32)\n\t\t\ttxt1.create_texture()\n\t\t}\n\t\t// decomment if want block color change\n\t\t// txt1.bmp.color = ttf.color_multiply(0xFF00FFFF, f32(app.frame_c % 255)/255.0)\n\t\t// decomment if want block rotation wanted\n\t\t// txt1.bmp.angle = 3.141592/180 * f32(app.frame_c % 45)\n\t\ttxt1.draw_text_bmp(app.gg, 30 + (app.frame_c >> 1) & 0xFF, 200)\n\t\t// draw mouse position\n\t\tif app.mouse_x >= 0 {\n\t\t\ttxt1 = unsafe { &app.ttf_render[2] }\n\t\t\ttxt1.destroy_texture()\n\t\t\ttxt1.create_text('${app.mouse_x},${app.mouse_y}', 25)\n\t\t\ttxt1.create_texture()\n\t\t\tr := app.mouse_x % 255\n\t\t\tg := app.mouse_y % 255\n\t\t\tcolor := u32(r) << 24 | u32(g) << 16 | 0xFF\n\t\t\ttxt1.bmp.color = color\n\t\t\ttxt1.draw_text_bmp(app.gg, app.mouse_x, app.mouse_y)\n\t\t}\n\t\tapp.frame_c++\n\t}\n\tapp.gg.end()\n}\n\nfn my_event_manager(mut ev gg.Event, mut app App_data) {\n\tif ev.typ == .mouse_move {\n\t\tapp.mouse_x = int(ev.mouse_x)\n\t\tapp.mouse_y = int(ev.mouse_y)\n\t}\n}\n\nfn main() {\n\tmut app := &App_data{}\n\tapp.gg = gg.new_context(\n\t\twidth:         win_width\n\t\theight:        win_height\n\t\tcreate_window: true\n\t\twindow_title:  'Test TTF module'\n\t\tuser_data:     app\n\t\tbg_color:      bg_color\n\t\tframe_fn:      draw_frame\n\t\tevent_fn:      my_event_manager\n\t\tinit_fn:       my_init\n\t)\n\t// load TTF fonts\n\tfor font_path in font_paths {\n\t\tmut tf := ttf.TTF_File{}\n\t\ttf.buf = os.read_bytes(font_path) or { panic(err) }\n\t\tprintln('TrueTypeFont file [${font_path}] len: ${tf.buf.len}')\n\t\ttf.init()\n\t\tprintln('Unit per EM: ${tf.units_per_em}')\n\t\tapp.tf << tf\n\t}\n\t// TTF render 0 Frame counter\n\tapp.ttf_render << &render_sokol.TTF_render_Sokol{\n\t\tbmp: &ttf.BitMap{\n\t\t\ttf:       &app.tf[0]\n\t\t\tbuf:      unsafe { malloc_noscan(32000000) }\n\t\t\tbuf_size: (32000000)\n\t\t\tcolor:    0xFF0000FF\n\t\t\t// style: .raw\n\t\t\t// use_font_metrics: true\n\t\t}\n\t}\n\t// TTF render 1 Text Block\n\tapp.ttf_render << &render_sokol.TTF_render_Sokol{\n\t\tbmp: &ttf.BitMap{\n\t\t\ttf: &app.tf[1]\n\t\t\t// color : 0xFF0000_10\n\t\t\t// style: .raw\n\t\t\t// use_font_metrics: true\n\t\t}\n\t}\n\t// TTF mouse position render\n\tapp.ttf_render << &render_sokol.TTF_render_Sokol{\n\t\tbmp: &ttf.BitMap{\n\t\t\ttf: &app.tf[0]\n\t\t}\n\t}\n\t// setup sokol_gfx\n\tapp.gg.run()\n}\n"
  },
  {
    "path": "examples/v_script.vsh",
    "content": "#!/usr/local/bin/v\n\n// The shebang above associates the file to V on Unix-like systems,\n// so it can be run just by specifying the path to the file\n// once it's made executable using `chmod +x`.\n\n// Note that you can also use: `#!/usr/bin/env -S v crun`, if your system supports the -S flag to env\n// The benefit is that in this case, v could be anywhere in your path, while /usr/bin/env is guaranteed\n// to be present on most Unix systems in that exact place.\n\nfor _ in 0 .. 3 {\n\tprintln('V script')\n}\n\nprintln('\\nMaking dir \"v_script_dir\".')\nmkdir('v_script_dir')!\n\nprintln(\"\\nEntering into v_script_dir and listing it's files.\")\nchdir('v_script_dir')!\nfiles := ls('.') or { panic(err) }\nprintln(files)\n\nprintln('\\nCreating foo.txt')\ncreate('foo.txt')!\n\nprintln('\\nFiles:')\nagain_ls := ls('.') or { panic(err) }\nprintln(again_ls)\n\nprintln('\\nRemoving foo.txt and v_script_dir')\nrm('foo.txt')!\nchdir('../')!\nrmdir('v_script_dir')!\n\nprint('\\nDoes v_script_dir still exist? ')\nprintln(exists('v_script_dir'))\n"
  },
  {
    "path": "examples/vascii.v",
    "content": "// Sometimes you just want an ascii table\nfn main() {\n\tprintln('\nDEC  OCT   HEX  BIN        Sym   HTML    ENTITY    Description\n----------------------------------------------------------------------------------------\n0    000   00   00000000   NUL   &#00;             Null character\n1    001   01   00000001   SOH   &#01;             Start of Heading\n2    002   02   00000010   STX   &#02;             Start of Text\n3    003   03   00000011   ETX   &#03;             End of Text\n4    004   04   00000100   EOT   &#04;             End of Transmission\n5    005   05   00000101   ENQ   &#05;             Enquiry\n6    006   06   00000110   ACK   &#06;             Acknowledge\n7    007   07   00000111   BEL   &#07;             Bell, Alert\n8    010   08   00001000   BS    &#08;             Backspace\n9    011   09   00001001   HT    &#09;             Horizontal Tab\n10   012   0A   00001010   LF    &#10;             Line Feed\n11   013   0B   00001011   VT    &#11;             Vertical Tabulation\n12   014   0C   00001100   FF    &#12;             Form Feed\n13   015   0D   00001101   CR    &#13;             Carriage Return\n14   016   0E   00001110   SO    &#14;             Shift Out\n15   017   0F   00001111   SI    &#15;             Shift In\n16   020   10   00010000   DLE   &#16;             Data Link Escape\n17   021   11   00010001   DC1   &#17;             Device Control One (XON)\n18   022   12   00010010   DC2   &#18;             Device Control Two\n19   023   13   00010011   DC3   &#19;             Device Control Three (XOFF)\n20   024   14   00010100   DC4   &#20;             Device Control Four\n21   025   15   00010101   NAK   &#21;             Negative Acknowledge\n22   026   16   00010110   SYN   &#22;             Synchronous Idle\n23   027   17   00010111   ETB   &#23;             End of Transmission Block\n24   030   18   00011000   CAN   &#24;             Cancel\n25   031   19   00011001   EM    &#25;             End of medium\n26   032   1A   00011010   SUB   &#26;             Substitute\n27   033   1B   00011011   ESC   &#27;             Escape\n28   034   1C   00011100   FS    &#28;             File Separator\n29   035   1D   00011101   GS    &#29;             Group Separator\n30   036   1E   00011110   RS    &#30;             Record Separator\n31   037   1F   00011111   US    &#31;             Unit Separator\n32   040   20   00100000   SP    &#32;             Space\n33   041   21   00100001   !     &#33;   excl;     Exclamation mark\n34   042   22   00100010   \"     &#34;   quot;     Double quotes (or speech marks)\n35   043   23   00100011   #     &#35;   num;      Number sign\n36   044   24   00100100   $     &#36;   dollar;   Dollar\n37   045   25   00100101   %     &#37;   percnt;   Per cent sign\n38   046   26   00100110   &     &#38;   amp;      Ampersand\n39   047   27   00100111   \\'     &#39;   apos;     Single quote\n40   050   28   00101000   (     &#40;   lparen;   Open parenthesis (or open bracket)\n41   051   29   00101001   )     &#41;   rparen;   Close parenthesis (or close bracket)\n42   052   2A   00101010   *     &#42;   ast;      Asterisk\n43   053   2B   00101011   +     &#43;   plus;     Plus\n44   054   2C   00101100   ,     &#44;   comma;    Comma\n45   055   2D   00101101   -     &#45;             Hyphen-minus\n46   056   2E   00101110   .     &#46;   period;   Period, dot or full stop\n47   057   2F   00101111   /     &#47;   sol;      Slash or divide\n48   060   30   00110000   0     &#48;             Zero\n49   061   31   00110001   1     &#49;             One\n50   062   32   00110010   2     &#50;             Two\n51   063   33   00110011   3     &#51;             Three\n52   064   34   00110100   4     &#52;             Four\n53   065   35   00110101   5     &#53;             Five\n54   066   36   00110110   6     &#54;             Six\n55   067   37   00110111   7     &#55;             Seven\n56   070   38   00111000   8     &#56;             Eight\n57   071   39   00111001   9     &#57;             Nine\n58   072   3A   00111010   :     &#58;   colon;    Colon\n59   073   3B   00111011   ;     &#59;   semi;     Semicolon\n60   074   3C   00111100   <     &#60;   lt;       Less than (or open angled bracket)\n61   075   3D   00111101   =     &#61;   equals;   Equals\n62   076   3E   00111110   >     &#62;   gt;       Greater than (or close angled bracket)\n63   077   3F   00111111   ?     &#63;   quest;    Question mark\n64   100   40   01000000   @     &#64;   commat;   At sign\n65   101   41   01000001   A     &#65;             Uppercase A\n66   102   42   01000010   B     &#66;             Uppercase B\n67   103   43   01000011   C     &#67;             Uppercase C\n68   104   44   01000100   D     &#68;             Uppercase D\n69   105   45   01000101   E     &#69;             Uppercase E\n70   106   46   01000110   F     &#70;             Uppercase F\n71   107   47   01000111   G     &#71;             Uppercase G\n72   110   48   01001000   H     &#72;             Uppercase H\n73   111   49   01001001   I     &#73;             Uppercase I\n74   112   4A   01001010   J     &#74;             Uppercase J\n75   113   4B   01001011   K     &#75;             Uppercase K\n76   114   4C   01001100   L     &#76;             Uppercase L\n77   115   4D   01001101   M     &#77;             Uppercase M\n78   116   4E   01001110   N     &#78;             Uppercase N\n79   117   4F   01001111   O     &#79;             Uppercase O\n80   120   50   01010000   P     &#80;             Uppercase P\n81   121   51   01010001   Q     &#81;             Uppercase Q\n82   122   52   01010010   R     &#82;             Uppercase R\n83   123   53   01010011   S     &#83;             Uppercase S\n84   124   54   01010100   T     &#84;             Uppercase T\n85   125   55   01010101   U     &#85;             Uppercase U\n86   126   56   01010110   V     &#86;             Uppercase V\n87   127   57   01010111   W     &#87;             Uppercase W\n88   130   58   01011000   X     &#88;             Uppercase X\n89   131   59   01011001   Y     &#89;             Uppercase Y\n90   132   5A   01011010   Z     &#90;             Uppercase Z\n91   133   5B   01011011   [     &#91;   lsqb;     Opening bracket\n92   134   5C   01011100   \\\\     &#92;   bsol;     Backslash\n93   135   5D   01011101   ]     &#93;   rsqb;     Closing bracket\n94   136   5E   01011110   ^     &#94;   Hat;      Caret - circumflex\n95   137   5F   01011111   _     &#95;   lowbar;   Underscore\n96   140   60   01100000   `     &#96;   grave;    Grave accent\n97   141   61   01100001   a     &#97;             Lowercase a\n98   142   62   01100010   b     &#98;             Lowercase b\n99   143   63   01100011   c     &#99;             Lowercase c\n100  144   64   01100100   d     &#100;            Lowercase d\n101  145   65   01100101   e     &#101;            Lowercase e\n102  146   66   01100110   f     &#102;            Lowercase f\n103  147   67   01100111   g     &#103;            Lowercase g\n104  150   68   01101000   h     &#104;            Lowercase h\n105  151   69   01101001   i     &#105;            Lowercase i\n106  152   6A   01101010   j     &#106;            Lowercase j\n107  153   6B   01101011   k     &#107;            Lowercase k\n108  154   6C   01101100   l     &#108;            Lowercase l\n109  155   6D   01101101   m     &#109;            Lowercase m\n110  156   6E   01101110   n     &#110;            Lowercase n\n111  157   6F   01101111   o     &#111;            Lowercase o\n112  160   70   01110000   p     &#112;            Lowercase p\n113  161   71   01110001   q     &#113;            Lowercase q\n114  162   72   01110010   r     &#114;            Lowercase r\n115  163   73   01110011   s     &#115;            Lowercase s\n116  164   74   01110100   t     &#116;            Lowercase t\n117  165   75   01110101   u     &#117;            Lowercase u\n118  166   76   01110110   v     &#118;            Lowercase v\n119  167   77   01110111   w     &#119;            Lowercase w\n120  170   78   01111000   x     &#120;            Lowercase x\n121  171   79   01111001   y     &#121;            Lowercase y\n122  172   7A   01111010   z     &#122;            Lowercase z\n123  173   7B   01111011   {     &#123;  &lcub;    Opening brace\n124  174   7C   01111100   |     &#124;  &verbar;  Vertical bar\n125  175   7D   01111101   }     &#125;  &rcub;    Closing brace\n126  176   7E   01111110   ~     &#126;  &tilde;   Equivalency sign - tilde\n127  177   7F   01111111   DEL   &#127;            Delete\n----------------------------------------------------------------------------------------\nDEC  OCT   HEX  BIN        Sym   HTML    ENTITY    Description')\n}\n"
  },
  {
    "path": "examples/vcasino/README.md",
    "content": "# VCasino\nVCasino is a very simple game made to learn V.\n\n# Compile and Run\n\nUse this to generate a binary and then launch the game.\n```bash\nv VCasino.v\n./VCasino\n```\n\nAnd this to compile and launch the game directly.\n```bash\nv run VCasino.v\n```\n\nCreated by Thomas Senechal : https://github.com/thomas-senechal/VCasino\n"
  },
  {
    "path": "examples/vcasino/vcasino.v",
    "content": "import rand\nimport os\n\nconst help_text = ' Usage:\\t./VCasino\\n\n Description:\\n  VCasino is a little game only made to learn V.\\n'\n\nconst g_desc = \"  The object of Roulette is to pick the number where the spinning ball will land on the wheel.\n   If your number is the good one, you'll get your bet x3.\n   If your number is the same color as the ball one, you'll get your bet /2.\n   Otherwise, you will lose your bet.\\n\"\n\nconst odd = 'red'\nconst even = 'black'\n\nstruct Options {\n\tlong_opt  string\n\tshort_opt string\n}\n\nfn display_help() {\n\tprintln(help_text + g_desc)\n}\n\nfn option_parser() bool {\n\thelp := Options{'--help', '-h'}\n\tfor i in 0 .. os.args.len {\n\t\tif os.args[i] == help.long_opt || os.args[i] == help.short_opt {\n\t\t\tdisplay_help()\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfn str_is_nbr(s string) bool {\n\tfor i in 0 .. s.len {\n\t\tif !s[i].is_digit() {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\nfn get_bet_nbr() int {\n\tmut bet_nbr := -1\n\tfor bet_nbr < 0 || bet_nbr > 49 {\n\t\tprintln('Reminder: odd numbers are red and even are black.')\n\t\tprintln('Type the number you want to bet on (between 0 and 49):')\n\t\tline := os.get_line().trim_space()\n\t\tif line == '' {\n\t\t\tprintln('error: empty line.')\n\t\t\tcontinue\n\t\t}\n\t\tif !str_is_nbr(line) {\n\t\t\tprintln('error: ${line} is not a number.')\n\t\t\tcontinue\n\t\t}\n\t\tbet_nbr = line.int()\n\t\tif bet_nbr < 0 || bet_nbr > 49 {\n\t\t\tprintln('error: ${line} is not between 0 and 49.')\n\t\t\tbet_nbr = -1\n\t\t}\n\t}\n\treturn bet_nbr\n}\n\nfn get_bet(money int) int {\n\tmut bet := -1\n\tfor bet <= 0 || bet > money {\n\t\tprintln('You have ${money} V. Type in the amount of your bet:')\n\t\tline := os.get_line().trim_space()\n\t\tif line == '' {\n\t\t\tprintln('error: empty line.')\n\t\t\tcontinue\n\t\t}\n\t\tif !str_is_nbr(line) {\n\t\t\tprintln('error: ${line} is not a number.')\n\t\t\tcontinue\n\t\t}\n\t\tbet = line.int()\n\t\tif bet <= 0 {\n\t\t\tprintln('error: ${line} is not higher than 1.')\n\t\t\tcontinue\n\t\t} else if bet > money {\n\t\t\tprintln('error: ${line} is more money than you have.')\n\t\t}\n\t}\n\treturn bet\n}\n\nfn run_wheel(bet_nbr int, _bet int) int {\n\tmut bet := _bet\n\twinning_nbr := rand.intn(50) or { 0 }\n\tprint('Roulette Wheel spinning... and stops on the number ${winning_nbr} which is a ')\n\tif winning_nbr % 2 == 1 {\n\t\tprintln(odd)\n\t} else {\n\t\tprintln(even)\n\t}\n\tif winning_nbr == bet_nbr {\n\t\tbet *= 3\n\t\tprintln('Congratulations! You get ${bet} V!')\n\t} else if winning_nbr % 2 == bet_nbr % 2 {\n\t\tbet /= 2\n\t\tprintln('You bet the right color. You get ${bet} V!')\n\t} else {\n\t\tprintln('Sorry buddy. You lost ${bet} V!')\n\t\tbet *= -1\n\t}\n\treturn bet\n}\n\nfn is_broke(money int) bool {\n\tif money <= 0 {\n\t\tprintln(\"You're broke, the game is over..\")\n\t\treturn false\n\t}\n\tquit := Options{'yes', 'y'}\n\tprintln('You have ${money} V. Do you want to quit the casino with your winnings? (y/n)')\n\tline := os.get_line().trim_space().to_lower()\n\tif line == quit.long_opt || line == quit.short_opt {\n\t\treturn false\n\t}\n\treturn true\n}\n\nfn game_loop() {\n\tmut can_play := true\n\tmut money := 1000\n\tprintln(g_desc)\n\tprintln('You start the game with ${money} V.\\n')\n\tfor can_play {\n\t\tbet_nbr := get_bet_nbr()\n\t\tbet := get_bet(money)\n\t\tmoney += run_wheel(bet_nbr, bet)\n\t\tcan_play = is_broke(money)\n\t}\n}\n\nfn main() {\n\tif os.args.len >= 2 && option_parser() {\n\t\treturn\n\t}\n\tgame_loop()\n}\n"
  },
  {
    "path": "examples/veb/cors/veb_cors_example.v",
    "content": "import time\nimport veb\n\n// See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS\n// and https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#preflighted_requests\n// >  Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows\n// >  a server to indicate any origins (domain, scheme, or port) other than its own from\n// >  which a browser should permit loading resources...\n\n// Usage: do `./v run examples/xveb/cors/` to start the app,\n// then check the headers in another shell:\n//\n// 1) `curl -vvv -X OPTIONS http://localhost:45678/time`\n// 2) `curl -vvv -X POST http://localhost:45678/time`\n\npub struct Context {\n\tveb.Context\n}\n\npub struct App {\n\tveb.Middleware[Context]\n}\n\n// time is a simple POST request handler, that returns the current time. It should be available\n// to JS scripts, running on arbitrary other origins/domains.\n\n@[post]\npub fn (app &App) time() veb.Result {\n\treturn ctx.json({\n\t\t'time': time.now().format_ss_milli()\n\t})\n}\n\nfn main() {\n\tprintln(\"\nTo test if CORS works, copy this JS snippet, then go to for example https://stackoverflow.com/ ,\npress F12, then paste the snippet in the opened JS console. You should see the veb server's time:\nvar xhr = new XMLHttpRequest();\nxhr.onload = function(data) {\n\tconsole.log('xhr loaded');\n\tconsole.log(xhr.response);\n};\nxhr.open('POST', 'http://localhost:45678/time');\nxhr.send();\n\t\")\n\n\tmut app := &App{}\n\n\t// use veb's cors middleware to handle CORS requests\n\tapp.use(veb.cors[Context](veb.CorsOptions{\n\t\t// allow CORS requests from every domain\n\t\torigins: ['*']\n\t\t// allow CORS requests with the following request methods:\n\t\tallowed_methods: [.get, .head, .patch, .put, .post, .delete]\n\t}))\n\n\tveb.run[App, Context](mut app, 45678)\n}\n"
  },
  {
    "path": "examples/veb/custom.html",
    "content": "<b>custom template</b>\n"
  },
  {
    "path": "examples/veb/file_transform/file_transform.v",
    "content": "module main\n\nimport veb\n\nconst port = 8082\n\npub struct Context {\n\tveb.Context\n}\n\npub struct App {\n}\n\nfn main() {\n\tmut app := &App{}\n\tveb.run[App, Context](mut app, port)\n}\n\npub fn (mut app App) index() veb.Result {\n\treturn $veb.html()\n}\n\n@['/upload'; post]\npub fn (mut app App) upload(mut ctx Context) veb.Result {\n\tfdata := ctx.files['upfile']\n\n\tdata_rows := fdata[0].data.split('\\n')\n\n\tmut output_data := ''\n\n\tfor elem in data_rows {\n\t\tdelim_row := elem.split('\\t')\n\t\toutput_data += '${delim_row[0]}\\t${delim_row[1]}\\t${delim_row[0].int() + delim_row[1].int()}\\n'\n\t}\n\n\toutput_data = output_data.all_before_last('\\n')\n\n\tprintln(output_data)\n\n\tctx.set_header(.content_disposition, 'attachment; filename=results.txt')\n\tctx.send_response_to_client('application/octet-stream', output_data)\n\n\treturn $veb.html()\n}\n"
  },
  {
    "path": "examples/veb/file_transform/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\" />\n<title>Test file uploading data transformation</title>\n</head>\n<body>\n\n<h2>File Upload and Data Transformation</h2>\n\nUpload the <b>sample_input.txt</b> located in this example folder. \n<br>\n<br> \nV will apply data transformation, adding the first two columns into a third column, and return the results as a download. <br>\n<br>\n\nFor example:\n<table style=\"color:blue;\">\n\t<tr>\n\t  \t<td>10</td>\n\t  \t<td>13</td>\n\t</tr>\n\t<tr>\n\t\t<td>20</td>\n\t\t<td>54</td>\n\t</tr>\n\t<tr>\n\t\t<td>30</td>\n\t\t<td>82</td>\n\t</tr>\n\t<tr>\n\t\t<td>40</td>\n\t\t<td>11</td>\n\t</tr>\n\t<tr>\n\t\t<td>50</td>\n\t\t<td>47</td>\n\t</tr>\n  </table>\n<br>\nBecomes...\n<br>\n<table style=\"color:blue;\">\n\t<tr>\n\t  \t<td>10</td>\n\t  \t<td>13</td>\n\t\t<td>23</td>\n\t</tr>\n\t<tr>\n\t\t<td>20</td>\n\t\t<td>54</td>\n\t\t<td>74</td>\n\t</tr>\n\t<tr>\n\t\t<td>30</td>\n\t\t<td>82</td>\n\t\t<td>112</td>\n\t</tr>\n\t<tr>\n\t\t<td>40</td>\n\t\t<td>11</td>\n\t\t<td>51</td>\n\t</tr>\n\t<tr>\n\t\t<td>50</td>\n\t\t<td>47</td>\n\t\t<td>97</td>\n\t</tr>\n  </table>\n\n<hr>\n\nFile form:\n<form method=\"POST\" enctype=\"multipart/form-data\" action=\"http://localhost:8082/upload\">\n\t<input type=\"file\" name=\"upfile\"/>\n\t<input type=\"submit\" value=\"Upload & Transform\"/>\n</form>\n\n</body>\n</html>\n"
  },
  {
    "path": "examples/veb/file_transform/sample_input.txt",
    "content": "10\t13\n20\t54\n30\t82\n40\t11\n50\t47"
  },
  {
    "path": "examples/veb/file_transform/upload.html",
    "content": "<meta charset=\"utf-8\">\n<a href=\"/\">Back</a>\n"
  },
  {
    "path": "examples/veb/file_upload/file_uploading.v",
    "content": "module main\n\nimport veb\n\nconst port = 8082\n\nstruct App {\n}\n\nstruct Context {\n\tveb.Context\n}\n\nfn main() {\n\tmut app := &App{}\n\tveb.run[App, Context](mut app, port)\n}\n\npub fn (mut app App) index() veb.Result {\n\treturn $veb.html()\n}\n\n@['/upload'; post]\npub fn (mut app App) upload() veb.Result {\n\tdump(ctx.form)\n\tdump(ctx.files)\n\tfdata := ctx.files['upfile']\n\tmut files := []veb.RawHtml{}\n\tfor d in fdata {\n\t\tfiles << d.data.replace_each(['\\n', '<br>', '\\n\\r', '<br>', '\\t', '\t', ' ', '&nbsp;'])\n\t}\n\treturn $veb.html()\n}\n\n@['/submit'; post]\npub fn (mut app App) submit() veb.Result {\n\tdump(ctx.form)\n\tform_data := ctx.form.clone()\n\treturn $veb.html()\n}\n"
  },
  {
    "path": "examples/veb/file_upload/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\" />\n<title>Test multipart/form-data file uploading</title>\n</head>\n<body>\n\n<h2>File Upload</h2>\n\nFile form:\n<form method=\"POST\" enctype=\"multipart/form-data\" action=\"/upload\">\n\t<input type=\"hidden\" name=\"file_id\" value=\"aafueB5Quie\" />\n\t<input type=\"file\" name=\"upfile\" multiple/>\n\t<input type=\"hidden\" name=\"another_hidden_field\" value=\"abcxyz\" />\n\t<input type=\"submit\" value=\"Upload\"/>\n</form>\n\nText form:\n<form method=\"POST\" enctype=\"multipart/form-data\" action=\"/submit\">\n\t<input type=\"text\" name=\"content1\" value=\"abc\" />\n\t<input type=\"text\" name=\"content2\" value=\"xyz\" />\n\t<input type=\"submit\" value=\"Submit content\">\n</form>\n\n</body>\n</html>\n"
  },
  {
    "path": "examples/veb/file_upload/submit.html",
    "content": "<meta charset=\"utf-8\">\n\nSubmitted form info:\n\n@for name, value in form_data\n\n<h2>name: @name</h2>\n<p>value: @value</p>\n\n@end\n\n<a href=\"/\">Back</a>\n"
  },
  {
    "path": "examples/veb/file_upload/upload.html",
    "content": "<meta charset=\"utf-8\">\n\nFile amount: @fdata.len\n\n@for i, data in fdata\n\n<h2>Filename: @data.filename</h2>\n<h2>Length: @data.data.len</h2>\n<h2>Type: @data.content_type</h2>\n\n<p>@{files[i]}</p>\n\n@end\n\n<a href=\"/\">Back</a>\n"
  },
  {
    "path": "examples/veb/footer.html",
    "content": "<br/><br/>\nfooter\n</body>\n</html>\n"
  },
  {
    "path": "examples/veb/header.html",
    "content": "<!doctype html>\n<html lang=en>\n<head>\n<meta charset=utf-8>\n<title>veb example page</title>\n</head>\n<body>\nheader from included header.html <br><br>\n"
  },
  {
    "path": "examples/veb/index.html",
    "content": "@include 'header.html'\n\nTest <b>app</b>\n<br>\n<h1>@hello</h1>\n<hr>\n\nIf demo: <br>\n@if show\n\tshow = true\n@end\n\n<br><br>\n\nFor loop demo: <br>\n\n@for number in numbers\n\t@number <br>\n@end\n\n\n<hr>\nEnd.\n@include 'footer.html'\n"
  },
  {
    "path": "examples/veb/middleware/templates/base.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>@title</title>\n</head>\n<body>\n<nav>\n    <a href=\"/\">Home</a>\n    <a href=\"/admin/secrets\">\"/admin/secrets\"</a>\n    <a href=\"/admin/dynamic\">\"/admin/dynamic\"</a>\n    <a href=\"/early\">Early exit</a>\n</nav>\n<main>\n    @content\n</main>\n<footer></footer>\n</body>\n</html>"
  },
  {
    "path": "examples/veb/middleware/templates/early.html",
    "content": "<p>Early exit</p>"
  },
  {
    "path": "examples/veb/middleware/templates/index.html",
    "content": "\n\n<h1>Hello </h1>"
  },
  {
    "path": "examples/veb/middleware/templates/secret.html",
    "content": "<p>Super secret stuff</p>"
  },
  {
    "path": "examples/veb/middleware/using_middleware.v",
    "content": "module main\n\nimport vweb\n\n// for another example see vlib/vweb/tests/middleware_test_server.v\nconst http_port = 8080\n\nstruct App {\n\tvweb.Context\n\tmiddlewares map[string][]vweb.Middleware\nmut:\n\tis_authenticated bool\n}\n\nfn main() {\n\tmut app := new_app()\n\tvweb.run(app, http_port)\n}\n\nfn new_app() &App {\n\tmut app := &App{\n\t\tmiddlewares: {\n\t\t\t// chaining is allowed, middleware will be evaluated in order\n\t\t\t'/admin/': [other_func1, other_func2]\n\t\t\t'/early':  [middleware_early]\n\t\t}\n\t}\n\n\t// do stuff with app\n\t// ...\n\treturn app\n}\n\n@['/']\npub fn (mut app App) index() vweb.Result {\n\tprintln('Index page')\n\ttitle := 'Home Page'\n\n\tcontent := $tmpl('templates/index.html')\n\tbase := $tmpl('templates/base.html')\n\treturn app.html(base)\n}\n\n@[middleware: check_auth]\n@['/admin/secrets']\npub fn (mut app App) secrets() vweb.Result {\n\tprintln('Secrets page')\n\ttitle := 'Secret Admin Page'\n\n\tcontent := $tmpl('templates/secret.html')\n\tbase := $tmpl('templates/base.html')\n\treturn app.html(base)\n}\n\n@['/admin/:sub']\npub fn (mut app App) dynamic(sub string) vweb.Result {\n\tprintln('Dynamic page')\n\ttitle := 'Secret dynamic'\n\n\tcontent := sub\n\tbase := $tmpl('templates/base.html')\n\treturn app.html(base)\n}\n\n@['/early']\npub fn (mut app App) early() vweb.Result {\n\tprintln('Early page')\n\ttitle := 'Early Exit'\n\n\tcontent := $tmpl('templates/early.html')\n\tbase := $tmpl('templates/base.html')\n\treturn app.html(base)\n}\n\n// is always executed first!\npub fn (mut app App) before_request() {\n\tapp.is_authenticated = false\n\tprintln('0')\n}\n\npub fn (mut app App) check_auth() bool {\n\tprintln('3')\n\tif app.is_authenticated == false {\n\t\tapp.redirect('/')\n\t}\n\treturn app.is_authenticated\n}\n\nfn other_func1(mut _ctx vweb.Context) bool {\n\tprintln('1')\n\treturn true\n}\n\nfn other_func2(mut _ctx vweb.Context) bool {\n\tprintln('2')\n\treturn true\n}\n\nfn middleware_early(mut ctx vweb.Context) bool {\n\tprintln('4')\n\tctx.text(':(')\n\t// returns false, so the middleware propagation is stopped and the user will see the text \":(\"\n\treturn false\n}\n"
  },
  {
    "path": "examples/veb/server_sent_events/assets/site.css",
    "content": "body {\n\tfont-family: Arial, Helvetica, sans-serif;\n\tcolor: #eee;\n\tbackground-color: #333;\n\tbackground-image: url(\"v-logo.svg\");\n\tbackground-repeat: no-repeat;\n\tbackground-size: 10em;\n\tmargin: 0;\n\tpadding-left: 11em;\n}\n\nh1 {\n\tcolor: #6699CC;\n}\n\nimg.logo {\n\tfloat: left;\n\twidth: 10em;\n}\n"
  },
  {
    "path": "examples/veb/server_sent_events/index.html",
    "content": "<html>\n    <head>\n        <title>@title</title>\n        <meta charset=\"utf-8\"/>\n\t    @css 'assets/site.css'\n    </head>\n    <body>\n        <h1>@title</h1>\n        <button>Close the connection</button>\n        <ul></ul>\n        <script>\n         \"use strict\";\n         var button = document.querySelector('button');\n         var eventList = document.querySelector('ul');\n         const evtSource = new EventSource('/sse');\n         evtSource.onerror = function() { console.log(\"EventSource failed.\"); };\n         console.log(evtSource.withCredentials);\n         console.log(evtSource.readyState);\n         console.log(evtSource.url);\n         evtSource.onopen = function() {\n             console.log(\"Connection to server opened.\");\n         };\n         evtSource.onmessage = function(e) {\n             var newElement = document.createElement(\"li\");\n             newElement.textContent = \"message: \" + e.data;\n             eventList.appendChild(newElement);\n         };\n         evtSource.addEventListener(\"ping\", function(e) {\n             console.log(e)\n             var newElement = document.createElement(\"li\");\n             var obj = JSON.parse(e.data);\n             newElement.innerHTML = \"ping at \" + obj.time + ' server data: ' + e.data;\n             eventList.appendChild(newElement);\n         }, false);\n         button.onclick = function() { console.log('Connection closed'); evtSource.close(); };\n        </script>\n    </body>\n</html>\n"
  },
  {
    "path": "examples/veb/server_sent_events/server.v",
    "content": "module main\n\nimport os\nimport rand\nimport time\nimport veb\nimport veb.sse\n\nstruct App {\n\tveb.StaticHandler\n}\n\nstruct Context {\n\tveb.Context\n}\n\nfn main() {\n\tmut app := &App{}\n\tapp.serve_static('/favicon.ico', 'favicon.ico')!\n\tapp.mount_static_folder_at(os.resource_abs_path('.'), '/')!\n\tveb.run[App, Context](mut app, 8081)\n}\n\n// XTODO template broken (@)\npub fn (mut app App) index() veb.Result {\n\ttitle := 'SSE Example'\n\treturn $veb.html()\n}\n\nfn (mut app App) sse() veb.Result {\n\tmut session := sse.start_connection(mut ctx.Context)\n\t// Note: you can setup session.write_timeout and session.headers here\n\t// session.start() or { return app.server_error(501) }\n\tsession.send_message(data: 'ok') or { return ctx.server_error_with_status(.not_implemented) }\n\tfor {\n\t\tdata := '{\"time\": \"${time.now().str()}\", \"random_id\": \"${rand.ulid()}\"}'\n\t\tsession.send_message(event: 'ping', data: data) or {\n\t\t\treturn ctx.server_error_with_status(.not_implemented)\n\t\t}\n\t\tprintln('> sent event: ${data}')\n\t\ttime.sleep(1 * time.second)\n\t}\n\treturn ctx.server_error_with_status(.not_implemented)\n}\n"
  },
  {
    "path": "examples/veb/static_website/README.md",
    "content": "# Host a static website\n\nHere is an example on how to use the Veb server's static capabilities,\nto host a static website from the `dist/` folder. Just run the server,\nit will be available at http://localhost:8080/ :\n\n```bash\nv run server.v\n```\n"
  },
  {
    "path": "examples/veb/static_website/dist/another.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n    <head>\n        <meta charset=\"UTF-8\" />\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n        <title>Website other page</title>\n    </head>\n    <body>\n        <h1>Hello, another world!</h1>\n        <p>Welcome to this another page of a demo website.</p>\n        <p><a href=\"/\">Click here</a> to go to main page.</p>\n    </body>\n</html>\n"
  },
  {
    "path": "examples/veb/static_website/dist/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n    <head>\n        <meta charset=\"UTF-8\" />\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n        <title>Website main page</title>\n    </head>\n    <body>\n        <h1>Hello, world!</h1>\n        <p>Welcome to this demo website.</p>\n        <p><a href=\"another.html\">Click here</a> to go to another page.</p>\n    </body>\n</html>\n"
  },
  {
    "path": "examples/veb/static_website/server.v",
    "content": "module main\n\nimport veb\nimport os\n\npub struct Context {\n\tveb.Context\n}\n\npub struct App {\n\tveb.StaticHandler\n}\n\nfn main() {\n\t// make sure that the working folder is the one, containing the executable,\n\t// so that 'dist' is a valid relative path from it later:\n\tos.chdir(os.dir(os.executable()))!\n\tmut app := &App{}\n\tapp.handle_static('dist', true)!\n\tveb.run[App, Context](mut app, 8080)\n}\n"
  },
  {
    "path": "examples/veb/todo/.gitignore",
    "content": "*.db"
  },
  {
    "path": "examples/veb/todo/README.md",
    "content": "# A simple TODO app using x.vweb\n\nA simple TODO app using `x.vweb` showcasing how to build a basic web app with vweb.\n\n## Database\n\nThis example uses an sqlite database using the `db.sqlite` package, \nbut you can use any database from the `db` module.\n\n## Quick Start\n\nRun from this directory with \n```bash\nv run main.v\n```\nYou can also enable vweb's livereload feature with\n```bash\nv watch -d vweb_livereload run main.v`\n```"
  },
  {
    "path": "examples/veb/todo/assets/main.css",
    "content": "\nhtml, body {\n    font-family: Arial, Helvetica, sans-serif;\n    font-size: 16px;\n    margin: 0;\n}\n\nbody {\n    max-width: 900px;\n    padding: 50px;\n    margin: auto;\n}\n\n* {\n    box-sizing: border-box;\n}\n\n/* simple styles reset */\nbutton {\n    appearance: none;\n    outline: 0;\n    border: 0;\n    margin: 0;\n    padding: 0;\n}\n\ninput {\n    appearance: none;\n    outline: 0;\n    font-size: 16px;\n    height: 30px;\n    line-height: 30px;\n    border: 1px solid #d3d3d3;\n    border-radius: 5px;\n}\n\nbutton {\n    font-size: 14px;\n    height: 30px;\n    padding: 5px 20px;\n    border-radius: 5px;\n    cursor: pointer;\n}\n\nbutton.primary {\n    background-color: #3b71ca;\n    color: white;\n}\nbutton.error {\n    background-color: red;\n    color: white;\n}\nbutton.success {\n    background-color: green;\n    color: white;\n}\n\n.form-success {\n    color: green;\n}\n\n.form-error {\n    color: red;\n}\n\nh1 {\n    text-align: center;\n}\n\nsection {\n    padding: 20px;\n}\nsection.create-todo {\n    max-width: fit-content;\n    margin: auto;\n}\n\n.todo-list {\n    display: flex;\n    flex-direction: column;\n}\n\n.todo {\n    display: flex;\n    align-items: center;\n    gap: 10px;\n    padding: 20px;\n    border-top: 1px solid #d3d3d3;\n}\n\n.todo .name {\n    flex-grow: 1;\n    font-weight: bold;\n}\n\n.todo-id, .time {\n    font-size: 14px;\n    font-weight: normal;\n    color: #3d3d3d;\n    margin: 0px 10px;\n}\n\n/* we're mobile friendly */\n@media only screen and (max-width: 900px) {\n    body {\n        max-width: unset;\n    }\n\n    .todo {\n        flex-direction: column;\n        gap: 5px;\n    }\n    .todo p {\n        margin: 0;\n    }\n\n    section.create-todo form {\n        display: flex;\n        flex-direction: column;\n        gap: 10px;\n    }\n}"
  },
  {
    "path": "examples/veb/todo/main.v",
    "content": "// Simple TODO app using veb\n// Run from this directory with `v run main.v`\n// You can also enable vebs livereload feature with\n// `v watch -d veb_livereload run main.v`\nmodule main\n\nimport veb\nimport db.sqlite\nimport os\nimport time\n\nstruct Todo {\npub mut:\n\t// `id` is the primary field. The attribute `sql: serial` acts like AUTO INCREMENT in sql.\n\t// You can use this attribute if you want a unique id for each row.\n\tid        int @[primary; sql: serial]\n\tname      string\n\tcompleted bool\n\tcreated   time.Time\n\tupdated   time.Time\n}\n\npub struct Context {\n\tveb.Context\npub mut:\n\t// we can use this field to check whether we just created a TODO in our html templates\n\tcreated_todo bool\n}\n\npub struct App {\n\tveb.StaticHandler\npub:\n\t// we can access the SQLITE database directly via `app.db`\n\tdb sqlite.DB\n}\n\n// This method will only handle GET requests to the index page\n@[get]\npub fn (app &App) index(mut ctx Context) veb.Result {\n\ttodos := sql app.db {\n\t\tselect from Todo\n\t} or { return ctx.server_error('could not fetch todos from database!') }\n\treturn $veb.html()\n}\n\n// This method will only handle POST requests to the index page\n@['/'; post]\npub fn (app &App) create_todo(mut ctx Context, name string) veb.Result {\n\t// We can receive form input fields as arguments in a route!\n\t// we could also access the name field by doing `name := ctx.form['name']`\n\n\t// validate input field\n\tif name == '' {\n\t\t// set a form error\n\t\tctx.form_error = 'You must fill in all the fields!'\n\t\t// send a HTTP 400 response code indicating that the form fields are incorrect\n\t\tctx.res.set_status(.bad_request)\n\t\t// render the home page\n\t\treturn app.index(mut ctx)\n\t}\n\n\t// create a new todo\n\ttodo := Todo{\n\t\tname:    name\n\t\tcreated: time.now()\n\t\tupdated: time.now()\n\t}\n\n\t// insert the todo into our database\n\tsql app.db {\n\t\tinsert todo into Todo\n\t} or { return ctx.server_error('could not insert a new TODO in the database') }\n\n\tctx.created_todo = true\n\n\t// render the home page\n\treturn app.index(mut ctx)\n}\n\n@['/todo/:id/complete'; post]\npub fn (app &App) complete_todo(mut ctx Context, id int) veb.Result {\n\t// first check if there exist a TODO record with `id`\n\ttodos := sql app.db {\n\t\tselect from Todo where id == id\n\t} or { return ctx.server_error(\"could not fetch TODO's\") }\n\tif todos.len == 0 {\n\t\t// return HTTP 404 when the TODO does not exist\n\t\tctx.res.set_status(.not_found)\n\t\treturn ctx.text('There is no TODO item with id=${id}')\n\t}\n\n\t// update the TODO field\n\tsql app.db {\n\t\tupdate Todo set completed = true, updated = time.now() where id == id\n\t} or { return ctx.server_error('could not update TODO') }\n\n\t// redirect client to the home page and tell the browser to sent a GET request\n\treturn ctx.redirect('/', typ: .see_other)\n}\n\n@['/todo/:id/delete'; post]\npub fn (app &App) delete_todo(mut ctx Context, id int) veb.Result {\n\t// first check if there exist a TODO record with `id`\n\ttodos := sql app.db {\n\t\tselect from Todo where id == id\n\t} or { return ctx.server_error(\"could not fetch TODO's\") }\n\tif todos.len == 0 {\n\t\t// return HTTP 404 when the TODO does not exist\n\t\tctx.res.set_status(.not_found)\n\t\treturn ctx.text('There is no TODO item with id=${id}')\n\t}\n\n\t// prevent hackers from deleting TODO's that are not completed ;)\n\tto_be_deleted := todos[0]\n\tif !to_be_deleted.completed {\n\t\treturn ctx.request_error('You must first complete a TODO before you can delete it!')\n\t}\n\n\t// delete the todo\n\tsql app.db {\n\t\tdelete from Todo where id == id\n\t} or { return ctx.server_error('could not delete TODO') }\n\n\t// redirect client to the home page and tell the browser to sent a GET request\n\treturn ctx.redirect('/', typ: .see_other)\n}\n\nfn main() {\n\tos.chdir(os.dir(@FILE))!\n\t// create a new App instance with a connection to the database\n\tmut app := &App{\n\t\tdb: sqlite.connect('todo.db')!\n\t}\n\n\t// mount the assets folder at `/assets/`\n\tapp.handle_static('assets', false)!\n\n\t// create the table in our database, if it doesn't exist\n\tsql app.db {\n\t\tcreate table Todo\n\t}!\n\n\t// start our app at port 8080\n\tveb.run[App, Context](mut app, 8080)\n}\n"
  },
  {
    "path": "examples/veb/todo/templates/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>My TODO App</title>\n    <!-- include our css from the assets folder -->\n    @css '/assets/main.css'\n</head>\n<body>\n\n<header>\n    <h1>List of all my todos</h1>\n</header>\n\n<main>\n    <!-- Display a message when a new TODO is created -->\n    @if ctx.created_todo\n    <p class=\"form-success\">Created a new todo!</p>\n    @endif\n\n    <section class=\"todos\">\n        <div class=\"todo-list\">\n        @if todos.len == 0\n            <p>Nothing to see here...</p>\n        @endif\n        <!-- Loop over all the current todo's -->\n        @for todo in todos\n            <div class=\"todo\">\n                <p class=\"name\"><span class=\"todo-id\">(id: @{todo.id})</span>@{todo.name}</p>\n                @if !todo.completed\n                    <!-- We can also call methods of properties inside a template -->\n                    <p class=\"time\">Created at: <span class=\"time\">@{todo.created.hhmmss()}</span></p>\n                    <!-- Pass the id of the TODO as a route parameter to '/complete/:id' -->\n                    <form action=\"/todo/@{todo.id}/complete\" method=\"post\">\n                        <button class=\"success\" type=\"submit\">Complete</button>\n                    </form>\n                @else\n                 <p class=\"time\">Completed at: <span class=\"time\">@{todo.updated.hhmmss()}</span></p>\n                    <p class=\"completed\">✔️</p>\n                    <!-- Pass the id of the TODO as a route parameter to '/complete/:id' -->\n                    <form action=\"/todo/@{todo.id}/delete\" method=\"post\">\n                        <button class=\"error\" type=\"submit\">Delete</button>\n                    </form>\n                @endif\n            </div>\n        @endfor\n      \n        </div>\n    </section>\n\n    <section class=\"create-todo\">\n        <h2>Create a new TODO item</h2>\n        <form action=\"/\" method=\"post\">\n            <label for=\"task-name\">Name:</label>\n            <input autofocus id=\"task-name\" type=\"text\" name=\"name\">\n            <button class=\"primary\" type=\"submit\">Create</button>\n            <p class=\"form-error\">@{ctx.form_error}</p>\n        </form>\n    </section>\n</main>    \n\n</body>\n</html>"
  },
  {
    "path": "examples/veb/veb_assets/assets/index.css",
    "content": "body {\n\tfont-family: Arial, Helvetica, sans-serif;\n\tcolor: #eee;\n\tbackground-color: #333;\n\tbackground-image: url(\"v-logo.svg\");\n\tbackground-repeat: no-repeat;\n\tbackground-size: 10em;\n\tmargin: 0;\n\tpadding-left: 11em;\n}\n\nh1 {\n\tcolor: #6699CC;\n}\n\nimg.logo {\n\tfloat: left;\n\twidth: 10em;\n}\n\nhtml {\n\tdisplay:block;\n}\n\t\t\n\t\t\n"
  },
  {
    "path": "examples/veb/veb_assets/index.html",
    "content": "<html>\n<head>\n\t<title>@title</title>\n\t<style>html{display:none}</style>\n\t@css 'index.css'\n</head>\n<body>\n\t<h1>@title</h1>\n\t<h2>@subtitle</h2>\n\t<p>@message</p>\n</body>\n</html>\n"
  },
  {
    "path": "examples/veb/veb_assets/vweb_assets.v",
    "content": "module main\n\nimport os\nimport veb\n// import vweb.assets\nimport time\n\nconst port = 8081\n\npub struct Context {\n\tveb.Context\n}\n\npub struct App {\n\tveb.StaticHandler\n}\n\nfn main() {\n\tmut app := &App{}\n\tapp.serve_static('/favicon.ico', 'favicon.ico')!\n\t// Automatically make available known static mime types found in given directory.\n\tos.chdir(os.dir(os.executable()))!\n\tapp.handle_static('assets', true)!\n\tveb.run[App, Context](mut app, 8080)\n}\n\npub fn (mut app App) index() veb.Result {\n\t// We can dynamically specify which assets are to be used in template.\n\t// \tmut am := assets.new_manager()\n\t// \tam.add_css('assets/index.css')\n\t// \tcss := am.include_css(false)\n\ttitle := 'Veb Assets Example'\n\tsubtitle := 'Veb can serve static assets too!'\n\tmessage := 'It also has an Assets Manager that allows dynamically specifying which CSS and JS files to be used.'\n\treturn $veb.html()\n}\n\nfn (mut app App) text() veb.Result {\n\treturn ctx.text('Hello, world from veb!')\n}\n\nfn (mut app App) time() veb.Result {\n\treturn ctx.text(time.now().format())\n}\n"
  },
  {
    "path": "examples/veb/veb_example.v",
    "content": "module main\n\nimport veb\nimport rand\n\nconst port = 8082\n\nstruct State {\nmut:\n\tcnt int\n}\n\npub struct App {\nmut:\n\tstate shared State\n}\n\nstruct Context {\n\tveb.Context\n}\n\npub fn (ctx &Context) before_request() {\n\t$if trace_before_request ? {\n\t\teprintln('[veb] before_request: ${ctx.req.method} ${ctx.req.url}')\n\t}\n}\n\n@['/users/:user']\npub fn (mut app App) user_endpoint(mut ctx Context, user string) veb.Result {\n\t// pub fn (mut app App) user_endpoint(user string) veb.Result {\n\tid := rand.intn(100) or { 0 }\n\treturn ctx.json({\n\t\tuser: id\n\t})\n}\n\npub fn (mut app App) index() veb.Result {\n\tprintln('veb_example.v index()')\n\tmut c := 0\n\tlock app.state {\n\t\tapp.state.cnt++\n\t\tc = app.state.cnt\n\t\t//\n\t\t$if trace_address_of_app_state_cnt ? {\n\t\t\tdump(ptr_str(app.state.cnt))\n\t\t}\n\t}\n\tshow := true\n\thello := 'Hello world from veb, request number: ${c}'\n\tnumbers := [1, 2, 3]\n\treturn $veb.html()\n}\n\npub fn (mut app App) custom_template(mut ctx Context) veb.Result {\n\treturn $veb.html('custom.html')\n}\n\npub fn (mut app App) show_text(mut ctx Context) veb.Result {\n\treturn ctx.text('Hello world from veb')\n}\n\npub fn (mut app App) cookie(mut ctx Context) veb.Result {\n\tctx.set_cookie(name: 'cookie', value: 'test')\n\treturn ctx.text('Response Headers\\n${ctx.req.header}')\n}\n\n@[post]\npub fn (mut app App) post(mut ctx Context) veb.Result {\n\treturn ctx.text('Post body: ${ctx.req.data}')\n}\n\nfn main() {\n\tprintln('veb example')\n\tmut app := &App{}\n\t// veb.run(&App{}, port)\n\n\tveb.run_at[App, Context](mut app, port: port, family: .ip, timeout_in_seconds: 2) or {\n\t\tpanic(err)\n\t}\n}\n"
  },
  {
    "path": "examples/veb/websocket/assets/style.css",
    "content": "html {\n\tbox-sizing: border-box;\n}\n*, *:before, *:after {\n\tbox-sizing: inherit;\n}\nbody {\n\tpadding: 0px;\n\tmargin: 0px;\n\tmargin-left: 30px;\n\tmargin-right: 30px;\n}\n\n#message-list {\n\twidth: 100%;\t\t\n\theight: 250px;\n\tpadding: 5px;\n\tbox-sizing: border-box;\n\tmargin: 0px;\n\tmargin-bottom: 5px;\n\tborder: 1px solid lightgray;\n\toverflow-y: scroll;\n\toverscroll-behavior-y: contain;\n\tscroll-snap-type: y proximity;\n}\n#message-list > li {\n\tlist-style-type: none;\n}\n#message-list > li:last-child {\n\tscroll-snap-align: end;\n\tborder-top: 1px solid #eeeeff !important;\n}\n\n#message-input {\n\twidth: 100%;\n\tmargin: 0px;\n\tpadding: 0px;\n\tfont-size: 24px;\n\tline-height: 1;\n\tfont-weight: 600;\n}\n"
  },
  {
    "path": "examples/veb/websocket/index.html",
    "content": "<!doctype html>\n<html lang=en>\n  <head>\n    <meta charset=utf-8>\n    <title>veb websocket example</title>\n\t<link rel=\"stylesheet\" type=\"text/css\" href=\"/assets/style.css\">\n  </head>\n  <body>\n    <p>This is an example of using V's `veb` and `net.websocket` modules in \n\tthe same app, where the websocket connection happens on the /ws route of\n\tyour veb app.</p>\n    <ul id=\"message-list\"></ul>\n    <input id=\"message-input\" placeholder=\"Enter your message here\" value=\"\"/>\n    <div>Client status: <span id=\"message-status\">---</span></div>\n    <script type=\"text/javascript\" src=\"/assets/client.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/veb/websocket/server.v",
    "content": "module main\n\nimport os\nimport veb\nimport log\nimport time\nimport term\nimport net\nimport net.http\nimport net.websocket\n\nconst app_port = 8990\n\nfn main() {\n\tlog.use_stdout()\n\tmut app := &App{\n\t\twss: new_websocker_server()!\n\t}\n\tapp.mount_static_folder_at(os.resource_abs_path('assets'), '/assets')!\n\tapp.serve_static('/favicon.ico', os.resource_abs_path('assets/favicon.ico'))!\n\tveb.run[App, Context](mut app, app_port)\n}\n\npub struct Context {\n\tveb.Context\n}\n\npub struct App {\n\tveb.StaticHandler\nmut:\n\twss &websocket.Server\n}\n\npub fn (mut app App) index(mut ctx Context) veb.Result {\n\treturn $veb.html()\n}\n\npub fn (mut app App) ws(mut ctx Context) veb.Result {\n\tkey := ctx.get_header(http.CommonHeader.sec_websocket_key) or { '' }\n\tif key == '' {\n\t\tctx.error('Invalid websocket handshake. Key is missing.')\n\t\treturn ctx.redirect('/')\n\t}\n\tdump(ctx.req.cookie('token') or { http.Cookie{} }.value)\n\twlog('> transferring connection with key: ${key}, to the websocket server ${voidptr(app.wss)} ...')\n\tctx.takeover_conn()\n\tctx.conn.set_write_timeout(time.infinite)\n\tctx.conn.set_read_timeout(time.infinite)\n\tspawn fn (mut wss websocket.Server, mut connection net.TcpConn, key string) {\n\t\twss.handle_handshake(mut connection, key) or { wlog('handle_handshake error: ${err}') }\n\t\twlog('>> wss.handle_handshake finished, key: ${key}')\n\t}(mut app.wss, mut ctx.conn, key)\n\twlog('> done transferring connection')\n\treturn veb.no_result()\n}\n\nfn slog(message string) {\n\teprintln(term.colorize(term.bright_yellow, message))\n}\n\nfn wlog(message string) {\n\teprintln(term.colorize(term.bright_blue, message))\n}\n\nfn new_websocker_server() !&websocket.Server {\n\tmut logger := &log.Log{}\n\tlogger.set_level(.info)\n\tlogger.set_output_stream(os.stderr())\n\tmut wss := websocket.new_server(.ip, app_port, '', logger: logger)\n\twss.set_ping_interval(100)\n\twss.on_connect(fn [mut logger] (mut server_client websocket.ServerClient) !bool {\n\t\tserver_client.client.logger = logger\n\t\tslog('wss.on_connect client.id: ${server_client.client.id} | server_client.client_key: ${server_client.client_key}')\n\t\treturn true\n\t})!\n\twss.on_close(fn (mut client websocket.Client, code int, reason string) ! {\n\t\tslog('wss.on_close client.id: ${client.id} | code: ${code}, reason: ${reason}')\n\t})\n\twss.on_message(fn [mut wss] (mut client websocket.Client, msg &websocket.Message) ! {\n\t\tslog('wss.on_message client.id: ${client.id} | msg.opcode: ${msg.opcode} | msg.payload: `${msg.payload.bytestr()}`')\n\t\ttext := '${client.id} says: \"${msg.payload.bytestr()}\"'\n\t\t// client.write_string(text) or { slog('client.write err: ${err}') return err }\n\t\tfor i, _ in rlock wss.server_state {\n\t\t\twss.server_state.clients\n\t\t} {\n\t\t\tmut c := rlock wss.server_state {\n\t\t\t\twss.server_state.clients[i] or { continue }\n\t\t\t}\n\t\t\tif c.client.get_state() == .open {\n\t\t\t\tc.client.write_string(text) or {\n\t\t\t\t\tslog('error while broadcasting to i: ${i}, ${voidptr(c)}, err: ${err}')\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\n\tslog('Websocket Server initialized, wss: ${voidptr(wss)}')\n\treturn wss\n}\n"
  },
  {
    "path": "examples/viewer/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 Dario Deledda\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "examples/viewer/README.md",
    "content": "# vviewer\nImage viewer for V\n\nThis is an example of a simple image viewer written in V.\n\n## Usage\n\nThe program can be invoked by the command line:\n\nfile list: `viewer img1.jpg inmg2.bmp img3.tga`\nfolder list: `viewer folder1 folder2`\nzip list: `viewer folder1.zip folder2.zip`\n\nAll folders/zips are scanned for images.\nThe user can mix files, folders, and zips.\n\nmixed list: `viewer img1.jpg img2.bmp folder1 folder2 img2.tga folder1.zip` \n\n## Interactive usage\n\nRun the viewer then drag and drop files,folders and zips on it.\n\n## Accepted image format\n\nJPEG, PNG, BMP, PSD, TGA, GIF (not animated), HDR, PIC, PNM\n\n#### Functions\nThe user can navigate through the files passed to the viewer.\nThe following operations can be performed on each image:\n\n- **Pan**, move over the image\n- **Zoom**, magnify or reduce the image\n- **Rotate**, rotate by 90 degree steps\n\n## Key bindings\t\t\n\n**H** - show this help\n\n**ESC/q** - Quit\n**cursor right**  - Next image\n**cursor  left**  - Previous image\n**cursor  up**    - Next folder\n**cursor  down**  - Previous folder\n**F** - Toggle full screen\n**R** - Rotate image of 90 degree\n**I** - Toggle the info text\n\n**mouse wheel** - next/previous images\nHold **left  Mouse button** - Pan on the image\nHold  **right Mouse button** - Zoom on the image\n\n#### Author:\n\nDario Deledda 2021 (c)"
  },
  {
    "path": "examples/viewer/file_scan.v",
    "content": "/**********************************************************************\n*\n* File scanner\n*\n* Copyright (c) 2021 Dario Deledda. All rights reserved.\n* Use of this source code is governed by an MIT license\n* that can be found in the LICENSE file.\n*\n* TODO:\n**********************************************************************/\nimport os\n\n// STBI supported format\n//        STBI_NO_JPEG *\n//        STBI_NO_PNG  *\n//        STBI_NO_BMP  *\n//        STBI_NO_PSD\n//        STBI_NO_TGA  *\n//        STBI_NO_GIF  *\n//        STBI_NO_HDR  *\n//        STBI_NO_PIC  *\n//        STBI_NO_PNM  *\n\n/******************************************************************************\n*\n* Struct and Enums\n*\n******************************************************************************/\nenum Item_type {\n\tfile = 0\n\tfolder\n\t// archive format\n\tzip = 16\n\tarchive_file\n\t// graphic format, MUST stay after the other types!!\n\tbmp = 32\n\tjpg\n\tpng\n\tgif\n\ttga\n\tppm\n\tpgm\n\tpic\n\thdr\n}\n\npub struct Item {\npub mut:\n\tpath                 string\n\tname                 string\n\tsize                 u64\n\ti_type               Item_type = .file\n\tcontainer_index      int  // used if the item is in a container (.zip, .rar, etc)\n\tcontainer_item_index int  // index in the container if the item is contained\n\tneed_extract         bool // if true need to extraction from the container\n\tdrawable             bool // if true the image can be showed\n\tn_item               int  //\n\trotation             int  // number of rotation of PI/2\n}\n\nstruct Item_list {\npub mut:\n\tlst        []Item\n\tpath_sep   string\n\titem_index int = -1 // image currently shown\n\tn_item     int  // number of images scanned\n\tloaded     bool // flag that indicate that the list is ready to  be used\n}\n\n/******************************************************************************\n*\n* Utility functions\n*\n******************************************************************************/\n@[inline]\nfn modulo(x int, n int) int {\n\treturn (x % n + n) % n\n}\n\n@[inline]\nfn get_extension(x string) Item_type {\n\t// 4 char extension check\n\tif x.len > 4 {\n\t\text4 := x[x.len - 4..].to_lower()\n\t\tmatch ext4 {\n\t\t\t// containers\n\t\t\t'.zip' { return .zip }\n\t\t\t// graphic formats\n\t\t\t'.jpg' { return .jpg }\n\t\t\t'.png' { return .png }\n\t\t\t'.bmp' { return .bmp }\n\t\t\t'.gif' { return .gif }\n\t\t\t'.tga' { return .tga }\n\t\t\t'.ppm' { return .ppm }\n\t\t\t'.pgm' { return .pgm }\n\t\t\t'.pic' { return .pic }\n\t\t\t'.hdr' { return .hdr }\n\t\t\telse {}\n\t\t}\n\t}\n\t// 5 char extension check\n\tif x.len > 5 {\n\t\text5 := x[x.len - 5..].to_lower()\n\t\tif ext5 == '.jpeg' {\n\t\t\t{\n\t\t\t\treturn .jpg\n\t\t\t}\n\t\t}\n\t}\n\treturn .file\n}\n\n@[inline]\nfn is_image(x Item_type) bool {\n\tif int(x) >= int(Item_type.bmp) {\n\t\treturn true\n\t}\n\treturn false\n}\n\n@[inline]\nfn is_container(x Item_type) bool {\n\tif x in [.zip, .folder] {\n\t\treturn true\n\t}\n\treturn false\n}\n\n@[inline]\nfn (item_list Item_list) is_inside_a_container() bool {\n\tif item_list.lst.len <= 0 || item_list.n_item <= 0 {\n\t\treturn false\n\t}\n\treturn item_list.lst[item_list.item_index].need_extract\n}\n\n@[inline]\nfn (item_list Item_list) get_file_path() string {\n\tif item_list.lst.len <= 0 || item_list.n_item <= 0 {\n\t\treturn ''\n\t}\n\tif item_list.lst[item_list.item_index].path != '' {\n\t\treturn '${item_list.lst[item_list.item_index].path}${item_list.path_sep}${item_list.lst[item_list.item_index].name}'\n\t}\n\treturn item_list.lst[item_list.item_index].name\n}\n\n/******************************************************************************\n*\n* Scan functions\n*\n******************************************************************************/\nfn (mut item_list Item_list) scan_folder(path string, in_index int) ! {\n\tprintln('Scanning [${path}]')\n\tmut folder_list := []string{}\n\tlst := os.ls(path)!\n\n\t// manage the single files\n\tfor c, x in lst {\n\t\tpt := '${path}${item_list.path_sep}${x}'\n\t\tmut item := Item{\n\t\t\tpath:                 path\n\t\t\tname:                 x\n\t\t\tcontainer_index:      in_index\n\t\t\tcontainer_item_index: c\n\t\t}\n\t\tif os.is_dir(pt) {\n\t\t\tfolder_list << x\n\t\t} else {\n\t\t\text := get_extension(x)\n\t\t\tif ext == .zip {\n\t\t\t\titem.i_type = .zip\n\t\t\t\titem_list.lst << item\n\t\t\t\titem_list.scan_zip(pt, item_list.lst.len - 1)!\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif is_image(ext) == true {\n\t\t\t\titem_list.n_item += 1\n\t\t\t\titem.n_item = item_list.n_item\n\t\t\t\titem.i_type = ext\n\t\t\t\titem.drawable = true\n\t\t\t\titem_list.lst << item\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t}\n\n\t// manage the folders\n\tfor x in folder_list {\n\t\tpt := '${path}${item_list.path_sep}${x}'\n\t\titem := Item{\n\t\t\tpath:   path\n\t\t\tname:   x\n\t\t\ti_type: .folder\n\t\t}\n\t\titem_list.lst << item\n\t\titem_list.scan_folder(pt, item_list.lst.len - 1)!\n\t}\n\t// println(item_list.lst.len)\n\t// println(\"==================================\")\n}\n\nfn (item_list Item_list) print_list() {\n\tprintln('================================')\n\tfor x in item_list.lst {\n\t\tif x.i_type == .folder {\n\t\t\tprint('[]')\n\t\t}\n\t\tif x.i_type == .zip {\n\t\t\tprint('[ZIP]')\n\t\t}\n\t\tprintln('${x.path} => ${x.container_index} ${x.container_item_index} ${x.name} ne:${x.need_extract}')\n\t}\n\tprintln('n_item: ${item_list.n_item} index: ${item_list.item_index}')\n\tprintln('================================')\n}\n\nfn (mut item_list Item_list) get_items_list(args []string) {\n\titem_list.loaded = false\n\tprintln('Args: ${args}')\n\n\titem_list.path_sep = $if windows { '\\\\' } $else { '/' }\n\tfor x in args {\n\t\t// scan folder\n\t\tif os.is_dir(x) {\n\t\t\tmut item := Item{\n\t\t\t\tpath:            x\n\t\t\t\tname:            x\n\t\t\t\tcontainer_index: item_list.lst.len\n\t\t\t\ti_type:          .folder\n\t\t\t}\n\t\t\titem_list.lst << item\n\t\t\titem_list.scan_folder(x, item_list.lst.len - 1) or {\n\t\t\t\teprintln('ERROR: scanning folder [${x}]!')\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\tmut item := Item{\n\t\t\t\tpath:            ''\n\t\t\t\tname:            x\n\t\t\t\tcontainer_index: -1\n\t\t\t}\n\t\t\text := get_extension(x)\n\t\t\t// scan .zip\n\t\t\tif ext == .zip {\n\t\t\t\titem.i_type = .zip\n\t\t\t\titem_list.lst << item\n\t\t\t\titem_list.scan_zip(x, item_list.lst.len - 1) or {\n\t\t\t\t\teprintln('ERROR: scanning zip [${x}]!')\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// single images\n\t\t\tif is_image(ext) == true {\n\t\t\t\titem_list.n_item += 1\n\t\t\t\titem.n_item = item_list.n_item\n\t\t\t\titem.i_type = ext\n\t\t\t\titem.drawable = true\n\t\t\t\titem_list.lst << item\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t}\n\t// debug call for list all the loaded items\n\t// item_list.print_list()\n\n\tprintln('Items: ${item_list.n_item}')\n\tprintln('Scanning done.')\n\n\titem_list.get_next_item(1)\n\titem_list.loaded = true\n}\n\n/******************************************************************************\n*\n* Navigation functions\n*\n******************************************************************************/\nfn (mut item_list Item_list) get_next_item(in_inc int) {\n\t// if empty exit\n\tif item_list.lst.len <= 0 || item_list.n_item <= 0 {\n\t\treturn\n\t}\n\n\tinc := if in_inc > 0 { 1 } else { -1 }\n\tmut i := item_list.item_index + in_inc\n\ti = modulo(i, item_list.lst.len)\n\tstart := i\n\tfor {\n\t\tif item_list.lst[i].drawable == true {\n\t\t\titem_list.item_index = i\n\t\t\tbreak\n\t\t}\n\t\ti = i + inc\n\t\ti = modulo(i, item_list.lst.len)\n\t\t// if we are in a loop break it\n\t\tif i == start {\n\t\t\tbreak\n\t\t}\n\t}\n\t// println(\"Found: ${item_list.item_index}\")\n}\n\nfn (mut item_list Item_list) go_to_next_container(in_inc int) {\n\t// if empty exit\n\tif item_list.lst.len <= 0 || item_list.n_item <= 0 {\n\t\treturn\n\t}\n\tinc := if in_inc > 0 { 1 } else { -1 }\n\tmut i := item_list.item_index + in_inc\n\ti = modulo(i, item_list.lst.len)\n\tstart := i\n\tfor {\n\t\t// check if we found a folder\n\t\tif is_container(item_list.lst[i].i_type) == true\n\t\t\t&& i != item_list.lst[item_list.item_index].container_index {\n\t\t\titem_list.item_index = i\n\t\t\titem_list.get_next_item(1)\n\t\t\tbreak\n\t\t}\n\t\t// continue to search\n\t\ti = i + inc\n\t\ti = modulo(i, item_list.lst.len)\n\t\t// if we are in a loop break it\n\t\tif i == start {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n/******************************************************************************\n*\n* Other functions\n*\n******************************************************************************/\n@[inline]\nfn (mut item_list Item_list) rotate(in_inc int) {\n\titem_list.lst[item_list.item_index].rotation += in_inc\n\tif item_list.lst[item_list.item_index].rotation >= 4 {\n\t\titem_list.lst[item_list.item_index].rotation = 0\n\t}\n}\n"
  },
  {
    "path": "examples/viewer/v.mod",
    "content": "Module {\n\tname: 'vviewer',\n\tdescription: 'A simple image viewer written in V.',\n\tversion: '0.9',\n\trepo_url: 'https://github.com/vlang/v/tree/master/examples/viewer',\n\tdependencies: []\n}\n"
  },
  {
    "path": "examples/viewer/view.v",
    "content": "/**********************************************************************\n*\n* simple Picture Viewer V. 0.9\n*\n* Copyright (c) 2021 Dario Deledda. All rights reserved.\n* Use of this source code is governed by an MIT license\n* that can be found in the LICENSE file.\n*\n* TODO:\n* - add an example with shaders\n**********************************************************************/\nimport os\nimport gg\nimport sokol.gfx\nimport sokol.sgl\nimport sokol.sapp\nimport stbi\nimport compress.szip\nimport strings\n\n// Help text\nconst help_text_rows = [\n\t'Image Viewer 0.9 help.',\n\t'',\n\t'ESC/q - Quit',\n\t'cur. right - Next image',\n\t'cur. left  - Previous image',\n\t'cur. up    - Next folder',\n\t'cur. down  - Previous folder',\n\t'F - Toggle full screen',\n\t'R - Rotate image of 90 degree',\n\t'I - Toggle the info text',\n\t'',\n\t'mouse wheel - next/previous images',\n\t'keep pressed left  Mouse button - Pan on the image',\n\t'keep pressed right Mouse button - Zoom on the image',\n]\n\nconst win_width = 800\nconst win_height = 800\nconst bg_color = gg.black\nconst pi_2 = 3.14159265359 / 2.0\nconst uv = [f32(0), 0, 1, 0, 1, 1, 0, 1]! // used for zoom icon during rotations\n\nconst text_drop_files = 'Drop here some images/folder/zip to navigate in the pics'\nconst text_scanning = 'Scanning...'\nconst text_loading = 'Loading...'\n\nenum Viewer_state {\n\tloading\n\tscanning\n\tshow\n\terror\n}\n\nstruct App {\nmut:\n\tgg         &gg.Context = unsafe { nil }\n\tpip_viewer sgl.Pipeline\n\ttexture    gfx.Image\n\tsampler    gfx.Sampler\n\tinit_flag  bool\n\tmouse_x    int = -1\n\tmouse_y    int = -1\n\tscroll_y   int\n\n\tstate Viewer_state = .scanning\n\t// translation\n\ttr_flag   bool\n\ttr_x      f32 = 0.0\n\ttr_y      f32 = 0.0\n\tlast_tr_x f32 = 0.0\n\tlast_tr_y f32 = 0.0\n\t// scaling\n\tsc_flag   bool\n\tscale     f32 = 1.0\n\tsc_x      f32 = 0.0\n\tsc_y      f32 = 0.0\n\tlast_sc_x f32 = 0.0\n\tlast_sc_y f32 = 0.0\n\t// loaded image\n\timg_w     int\n\timg_h     int\n\timg_ratio f32 = 1.0\n\t// item list\n\titem_list &Item_list = unsafe { nil }\n\t// Text info and help\n\tshow_info_flag bool = true\n\tshow_help_flag bool\n\t// zip container\n\tzip       &szip.Zip = unsafe { nil } // pointer to the szip structure\n\tzip_index int       = -1             // index of the zip container item\n\t// memory buffer\n\tmem_buf      voidptr // buffer used to load items from files/containers\n\tmem_buf_size int     // size of the buffer\n\t// font\n\tfont_path string // path to the temp font file\n\t// logo\n\tlogo_path    string // path of the temp font logo\n\tlogo_texture gfx.Image\n\tlogo_sampler gfx.Sampler\n\tlogo_w       int\n\tlogo_h       int\n\tlogo_ratio   f32 = 1.0\n\t// string builder\n\tbl strings.Builder = strings.new_builder(512)\n}\n\n/******************************************************************************\n*\n* Texture functions\n*\n******************************************************************************/\nfn create_texture(w int, h int, buf &u8) (gfx.Image, gfx.Sampler) {\n\tsz := w * h * 4\n\tmut img_desc := gfx.ImageDesc{\n\t\twidth:       w\n\t\theight:      h\n\t\tnum_mipmaps: 0\n\t\t// usage: .dynamic\n\t\tlabel:         &u8(unsafe { nil })\n\t\td3d11_texture: 0\n\t}\n\t// comment if .dynamic is enabled\n\timg_desc.data.subimage[0][0] = gfx.Range{\n\t\tptr:  buf\n\t\tsize: usize(sz)\n\t}\n\n\tsg_img := gfx.make_image(&img_desc)\n\n\tmut smp_desc := gfx.SamplerDesc{\n\t\tmin_filter: .linear\n\t\tmag_filter: .linear\n\t\twrap_u:     .clamp_to_edge\n\t\twrap_v:     .clamp_to_edge\n\t}\n\n\tsg_smp := gfx.make_sampler(&smp_desc)\n\treturn sg_img, sg_smp\n}\n\nfn destroy_texture(sg_img gfx.Image) {\n\tgfx.destroy_image(sg_img)\n}\n\n// Use only if: .dynamic is enabled\nfn update_text_texture(sg_img gfx.Image, w int, h int, buf &u8) {\n\tsz := w * h * 4\n\tmut tmp_sbc := gfx.ImageData{}\n\ttmp_sbc.subimage[0][0] = gfx.Range{\n\t\tptr:  buf\n\t\tsize: usize(sz)\n\t}\n\tgfx.update_image(sg_img, &tmp_sbc)\n}\n\n/******************************************************************************\n*\n* Memory buffer\n*\n******************************************************************************/\n@[inline]\nfn (mut app App) resize_buf_if_needed(in_size int) {\n\t// manage the memory buffer\n\tif app.mem_buf_size < in_size {\n\t\tprintln('Managing FILE memory buffer, allocated [${in_size}]Bytes')\n\t\t// free previous buffer if any exist\n\t\tif app.mem_buf_size > 0 {\n\t\t\tunsafe {\n\t\t\t\tfree(app.mem_buf)\n\t\t\t}\n\t\t}\n\t\t// allocate the memory\n\t\tunsafe {\n\t\t\tapp.mem_buf = malloc(int(in_size))\n\t\t\tapp.mem_buf_size = int(in_size)\n\t\t}\n\t}\n}\n\n/******************************************************************************\n*\n* Loading functions\n*\n******************************************************************************/\n// read_bytes from file in `path` in the memory buffer of app.\n@[manualfree]\nfn (mut app App) read_bytes(path string) bool {\n\tmut fp := os.vfopen(path, 'rb') or {\n\t\teprintln('ERROR: Can not open the file [${path}].')\n\t\treturn false\n\t}\n\tdefer {\n\t\tC.fclose(fp)\n\t}\n\tcseek := C.fseek(fp, 0, C.SEEK_END)\n\tif cseek != 0 {\n\t\teprintln('ERROR: Can not seek in the file [${path}].')\n\t\treturn false\n\t}\n\tfsize := C.ftell(fp)\n\tif fsize < 0 {\n\t\teprintln('ERROR: File [${path}] has size is 0.')\n\t\treturn false\n\t}\n\tC.rewind(fp)\n\n\tapp.resize_buf_if_needed(int(fsize))\n\n\tnr_read_elements := int(C.fread(app.mem_buf, fsize, 1, fp))\n\tif nr_read_elements == 0 && fsize > 0 {\n\t\teprintln('ERROR: Can not read the file [${path}] in the memory buffer.')\n\t\treturn false\n\t}\n\treturn true\n}\n\n// read a file as []u8\npub fn read_bytes_from_file(file_path string) []u8 {\n\tmut buffer := []u8{}\n\tbuffer = os.read_bytes(file_path) or {\n\t\teprintln('ERROR: Texture file: [${file_path}] NOT FOUND.')\n\t\texit(0)\n\t}\n\treturn buffer\n}\n\nfn (mut app App) load_texture_from_buffer(buf voidptr, buf_len int) (gfx.Image, gfx.Sampler, int, int) {\n\t// load image\n\tstbi.set_flip_vertically_on_load(true)\n\timg := stbi.load_from_memory(buf, buf_len) or {\n\t\teprintln('ERROR: Can not load image from buffer, file: [${app.item_list.lst[app.item_list.item_index]}].')\n\t\treturn app.logo_texture, app.sampler, app.logo_w, app.logo_h\n\t\t// exit(1)\n\t}\n\tsg_img, sg_smp := create_texture(int(img.width), int(img.height), img.data)\n\tunsafe {\n\t\timg.free()\n\t}\n\treturn sg_img, sg_smp, int(img.width), int(img.height)\n}\n\npub fn (mut app App) load_texture_from_file(file_name string) (gfx.Image, gfx.Sampler, int, int) {\n\tapp.read_bytes(file_name)\n\treturn app.load_texture_from_buffer(app.mem_buf, app.mem_buf_size)\n}\n\npub fn show_logo(mut app App) {\n\tclear_modifier_params(mut app)\n\tif app.texture != app.logo_texture {\n\t\tdestroy_texture(app.texture)\n\t\tgfx.destroy_sampler(app.sampler)\n\t}\n\tapp.texture = app.logo_texture\n\tapp.sampler = app.logo_sampler\n\tapp.img_w = app.logo_w\n\tapp.img_h = app.logo_h\n\tapp.img_ratio = f32(app.img_w) / f32(app.img_h)\n\t// app.gg.refresh_ui()\n}\n\npub fn load_image(mut app App) {\n\tif app.item_list.loaded == false || app.init_flag == false {\n\t\t// show_logo(mut app)\n\t\t// app.state = .show\n\t\treturn\n\t}\n\tapp.state = .loading\n\tclear_modifier_params(mut app)\n\t// destroy the texture, avoid to destroy the logo\n\tif app.texture != app.logo_texture {\n\t\tdestroy_texture(app.texture)\n\t\tgfx.destroy_sampler(app.sampler)\n\t}\n\n\t// load from .ZIP file\n\tif app.item_list.is_inside_a_container() == true {\n\t\tapp.texture, app.sampler, app.img_w, app.img_h = app.load_texture_from_zip() or {\n\t\t\teprintln('ERROR: Can not load image from .ZIP file [${app.item_list.lst[app.item_list.item_index]}].')\n\t\t\tshow_logo(mut app)\n\t\t\tapp.state = .show\n\t\t\treturn\n\t\t}\n\t\tapp.img_ratio = f32(app.img_w) / f32(app.img_h)\n\t\tapp.state = .show\n\t\t// app.gg.refresh_ui()\n\t\treturn\n\t}\n\n\t// if we are out of the zip, close it\n\tif app.zip_index >= 0 {\n\t\tapp.zip_index = -1\n\t\tapp.zip.close()\n\t}\n\n\tfile_path := app.item_list.get_file_path()\n\tif file_path != '' {\n\t\t// println(\"${app.item_list.lst[app.item_list.item_index]} ${file_path} ${app.item_list.lst.len}\")\n\t\tapp.texture, app.sampler, app.img_w, app.img_h = app.load_texture_from_file(file_path)\n\t\tapp.img_ratio = f32(app.img_w) / f32(app.img_h)\n\t\t// println(\"texture: [${app.img_w},${app.img_h}] ratio: ${app.img_ratio}\")\n\t} else {\n\t\tapp.texture = app.logo_texture\n\t\tapp.sampler = app.logo_sampler\n\t\tapp.img_w = app.logo_w\n\t\tapp.img_h = app.logo_h\n\t\tapp.img_ratio = f32(app.img_w) / f32(app.img_h)\n\t\tprintln('texture NOT FOUND: use logo!')\n\t}\n\tapp.state = .show\n}\n\n/******************************************************************************\n*\n* Init / Cleanup\n*\n******************************************************************************/\nfn app_init(mut app App) {\n\tapp.init_flag = true\n\n\t// 3d pipeline\n\tmut pipdesc := gfx.PipelineDesc{}\n\tunsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }\n\n\tcolor_state := gfx.ColorTargetState{\n\t\tblend: gfx.BlendState{\n\t\t\tenabled:        true\n\t\t\tsrc_factor_rgb: .src_alpha\n\t\t\tdst_factor_rgb: .one_minus_src_alpha\n\t\t}\n\t}\n\tpipdesc.colors[0] = color_state\n\n\tpipdesc.depth = gfx.DepthState{\n\t\twrite_enabled: true\n\t\tcompare:       .less_equal\n\t}\n\tpipdesc.cull_mode = .back\n\tapp.pip_viewer = sgl.make_pipeline(&pipdesc)\n\n\t// load logo\n\tapp.logo_texture, app.logo_sampler, app.logo_w, app.logo_h = app.load_texture_from_file(app.logo_path)\n\tapp.logo_ratio = f32(app.img_w) / f32(app.img_h)\n\n\tapp.img_w = app.logo_w\n\tapp.img_h = app.logo_h\n\tapp.img_ratio = app.logo_ratio\n\tapp.texture = app.logo_texture\n\tapp.sampler = app.logo_sampler\n\n\tprintln('INIT DONE!')\n\n\t// init done, load the first image if any\n\tload_image(mut app)\n}\n\nfn cleanup(mut app App) {\n\tgfx.shutdown()\n\n\t// delete temp files\n\tos.rm(app.font_path) or { eprintln('ERROR: Can not delete temp font file.') }\n\tos.rm(app.logo_path) or { eprintln('ERROR: Can not delete temp logo file.') }\n\tprintln('Cleaning done.')\n}\n\n/******************************************************************************\n*\n* Draw functions\n*\n******************************************************************************/\n@[manualfree]\nfn frame(mut app App) {\n\tws := gg.window_size_real_pixels()\n\tif ws.width <= 0 || ws.height <= 0 {\n\t\treturn\n\t}\n\n\tmut ratio := f32(ws.width) / ws.height\n\tdw := ws.width\n\tdh := ws.height\n\n\tapp.gg.begin()\n\tsgl.defaults()\n\n\t// set viewport\n\tsgl.viewport(0, 0, dw, dh, true)\n\n\t// enable our pipeline\n\tsgl.load_pipeline(app.pip_viewer)\n\tsgl.enable_texture()\n\tsgl.texture(app.texture, app.sampler)\n\n\t// translation\n\ttr_x := app.tr_x / app.img_w\n\ttr_y := -app.tr_y / app.img_h\n\tsgl.push_matrix()\n\tsgl.translate(tr_x, tr_y, 0.0)\n\t// scaling/zoom\n\tsgl.scale(2.0 * app.scale, 2.0 * app.scale, 0.0)\n\t// rotation\n\tmut rotation := 0\n\tif app.state == .show && app.item_list.n_item > 0 {\n\t\trotation = app.item_list.lst[app.item_list.item_index].rotation\n\t\tsgl.rotate(pi_2 * f32(rotation), 0.0, 0.0, -1.0)\n\t}\n\n\t// draw the image\n\tmut w := f32(0.5)\n\tmut h := f32(0.5)\n\n\t// for 90 and 270 degree invert w and h\n\t// rotation change image ratio, manage it\n\tif rotation & 1 == 1 {\n\t\ttmp := w\n\t\tw = h\n\t\th = tmp\n\t\th /= app.img_ratio * ratio\n\t} else {\n\t\th /= app.img_ratio / ratio\n\t}\n\n\t// manage image overflow in case of strange scales\n\tif h > 0.5 {\n\t\treduction_factor := 0.5 / h\n\t\th = h * reduction_factor\n\t\tw = w * reduction_factor\n\t}\n\tif w > 0.5 {\n\t\treduction_factor := 0.5 / w\n\t\th = h * reduction_factor\n\t\tw = w * reduction_factor\n\t}\n\n\t// println(\"${w},${h}\")\n\t// white multiplicator for now\n\tmut c := [u8(255), 255, 255]!\n\tsgl.begin_quads()\n\tsgl.v2f_t2f_c3b(-w, -h, 0, 0, c[0], c[1], c[2])\n\tsgl.v2f_t2f_c3b(w, -h, 1, 0, c[0], c[1], c[2])\n\tsgl.v2f_t2f_c3b(w, h, 1, 1, c[0], c[1], c[2])\n\tsgl.v2f_t2f_c3b(-w, h, 0, 1, c[0], c[1], c[2])\n\tsgl.end()\n\n\t// restore all the transformations\n\tsgl.pop_matrix()\n\n\t// Zoom icon\n\t/*\n\tif app.show_info_flag == true && app.scale > 1 {\n\t\tmut bw := f32(0.25)\n\t\tmut bh := f32(0.25 / app.img_ratio)\n\n\t\t// manage the rotations\n\t\tif rotation & 1 == 1 {\n\t\t\tbw,bh = bh,bw\n\t\t}\n\t\tmut bx := f32(1 - bw)\n\t\tmut by := f32(1 - bh)\n\t\tif rotation & 1 == 1 {\n\t\t\tbx,by = by,bx\n\t\t}\n\n\t\tbh_old1 := bh\n\t\tbh *= ratio\n\t\tby += (bh_old1 - bh)\n\n\t\t// draw the zoom icon\n\t\tsgl.begin_quads()\n\t\tr := int(u32(rotation) << 1)\n\t\tsgl.v2f_t2f_c3b(bx     , by     , uv[(0 + r) & 7] , uv[(1 + r) & 7], c[0], c[1], c[2])\n\t\tsgl.v2f_t2f_c3b(bx + bw, by     , uv[(2 + r) & 7] , uv[(3 + r) & 7], c[0], c[1], c[2])\n\t\tsgl.v2f_t2f_c3b(bx + bw, by + bh, uv[(4 + r) & 7] , uv[(5 + r) & 7], c[0], c[1], c[2])\n\t\tsgl.v2f_t2f_c3b(bx     , by + bh, uv[(6 + r) & 7] , uv[(7 + r) & 7], c[0], c[1], c[2])\n\t\tsgl.end()\n\n\t\t// draw the zoom rectangle\n\t\tsgl.disable_texture()\n\n\t\tbw_old := bw\n\t\tbh_old := bh\n\t\tbw /=  app.scale\n\t\tbh /=  app.scale\n\t\tbx += (bw_old - bw) / 2 - (tr_x / 8) / app.scale\n\t\tby += (bh_old - bh) / 2 - ((tr_y / 8) / app.scale) * ratio\n\n\t\tc = [u8(255),255,0]! // yellow\n\t\tsgl.begin_line_strip()\n\t\tsgl.v2f_c3b(bx     , by     , c[0], c[1], c[2])\n\t\tsgl.v2f_c3b(bx + bw, by     , c[0], c[1], c[2])\n\t\tsgl.v2f_c3b(bx + bw, by + bh, c[0], c[1], c[2])\n\t\tsgl.v2f_c3b(bx     , by + bh, c[0], c[1], c[2])\n\t\tsgl.v2f_c3b(bx     , by     , c[0], c[1], c[2])\n\t\tsgl.end()\n\t}\n\t*/\n\tsgl.disable_texture()\n\n\t//\n\t// Draw info text\n\t//\n\tx := 10\n\ty := 10\n\n\tapp.gg.begin()\n\n\tif app.state in [.scanning, .loading] {\n\t\tif app.state == .scanning {\n\t\t\tdraw_text(mut app, text_scanning, x, y, 20)\n\t\t} else {\n\t\t\tdraw_text(mut app, text_loading, x, y, 20)\n\t\t}\n\t} else if app.state == .show {\n\t\t// print the info text if needed\n\t\tif app.item_list.n_item > 0 && app.show_info_flag == true {\n\t\t\t/*\n\t\t\t// waiting for better autofree\n\t\t\tnum := app.item_list.lst[app.item_list.item_index].n_item\n\t\t\tof_num := app.item_list.n_item\n\t\t\tx_screen := int(w*2*app.scale*dw)\n\t\t\ty_screen := int(h*2*app.scale*dw)\n\t\t\trotation_angle := 90 * rotation\n\t\t\tscale_str := \"${app.scale:.2}\"\n\t\t\ttext := \"${num}/${of_num} [${app.img_w},${app.img_h}]=>[${x_screen},${y_screen}] ${app.item_list.lst[app.item_list.item_index].name} scale: ${scale_str} rotation: ${rotation_angle}\"\n\t\t\t//text := \"${num}/${of_num}\"\n\t\t\tdraw_text(mut app, text, 10, 10, 20)\n\t\t\tunsafe{\n\t\t\t\ttext.free()\n\t\t\t}\n\t\t\t*/\n\n\t\t\t// Using string builder to avoid memory leak\n\t\t\tnum := app.item_list.lst[app.item_list.item_index].n_item\n\t\t\tof_num := app.item_list.n_item\n\t\t\tx_screen := int(w * 2 * app.scale * dw)\n\t\t\ty_screen := int(h * 2 * app.scale * dw)\n\t\t\trotation_angle := 90 * rotation\n\t\t\tscale_str := '${app.scale:.2}'\n\t\t\tapp.bl.clear()\n\t\t\tapp.bl.write_string('${num}/${of_num}')\n\t\t\tapp.bl.write_string(' [${app.img_w}x${app.img_h}]=>[${x_screen}x${y_screen}]')\n\t\t\tapp.bl.write_string(' ${app.item_list.lst[app.item_list.item_index].name}')\n\t\t\tapp.bl.write_string(' scale: ${scale_str} rotation: ${rotation_angle}')\n\t\t\tdraw_text(mut app, app.bl.str(), 10, 10, 20)\n\t\t} else {\n\t\t\tif app.item_list.n_item <= 0 {\n\t\t\t\tdraw_text(mut app, text_drop_files, 10, 10, 20)\n\t\t\t}\n\t\t}\n\t}\n\n\t//\n\t// Draw Help text\n\t//\n\tif app.show_help_flag == true {\n\t\tmut txt_y := 30\n\t\tfor r in help_text_rows {\n\t\t\tdraw_text(mut app, r, 10, txt_y, 20)\n\t\t\ttxt_y += 20\n\t\t}\n\t}\n\n\tapp.gg.end()\n}\n\n// draw readable text\nfn draw_text(mut app App, in_txt string, in_x int, in_y int, fnt_sz f32) {\n\tscale := app.gg.scale\n\tfont_size := int(fnt_sz * scale)\n\n\tmut txt_conf_c0 := gg.TextCfg{\n\t\tcolor: gg.white // gg.rgb( (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff)\n\t\talign: .left\n\t\tsize:  font_size\n\t}\n\tmut txt_conf_c1 := gg.TextCfg{\n\t\tcolor: gg.black // gg.rgb( (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff)\n\t\talign: .left\n\t\tsize:  font_size\n\t}\n\n\tx := int(in_x * scale)\n\ty := int(in_y * scale)\n\tapp.gg.draw_text(x + 2, y + 2, in_txt, txt_conf_c0)\n\tapp.gg.draw_text(x, y, in_txt, txt_conf_c1)\n}\n\n/******************************************************************************\n*\n* events management\n*\n******************************************************************************/\nfn clear_modifier_params(mut app App) {\n\tapp.scale = 1.0\n\n\tapp.sc_flag = false\n\tapp.sc_x = 0\n\tapp.sc_y = 0\n\tapp.last_sc_x = 0\n\tapp.last_sc_y = 0\n\n\tapp.tr_flag = false\n\tapp.tr_x = 0\n\tapp.tr_y = 0\n\tapp.last_tr_x = 0\n\tapp.last_tr_y = 0\n}\n\nfn my_event_manager(mut ev gg.Event, mut app App) {\n\t// Handle window closure\n\tif ev.typ == .quit_requested {\n\t\tcleanup(mut app)\n\t\texit(0)\n\t}\n\t// navigation using the mouse wheel\n\tapp.scroll_y = int(ev.scroll_y)\n\tif app.scroll_y != 0 {\n\t\tinc := int(-1 * app.scroll_y / 4)\n\t\tif app.item_list.n_item > 0 {\n\t\t\tapp.item_list.get_next_item(inc)\n\t\t\tload_image(mut app)\n\t\t}\n\t}\n\n\tif ev.typ == .mouse_move {\n\t\tapp.mouse_x = int(ev.mouse_x)\n\t\tapp.mouse_y = int(ev.mouse_y)\n\t}\n\tif ev.typ == .touches_began || ev.typ == .touches_moved {\n\t\tif ev.num_touches > 0 {\n\t\t\ttouch_point := ev.touches[0]\n\t\t\tapp.mouse_x = int(touch_point.pos_x)\n\t\t\tapp.mouse_y = int(touch_point.pos_y)\n\t\t}\n\t}\n\n\t// clear all parameters\n\tif ev.typ == .mouse_down && ev.mouse_button == .middle {\n\t\tclear_modifier_params(mut app)\n\t}\n\n\t// ws := gg.window_size_real_pixels()\n\t// ratio := f32(ws.width) / ws.height\n\t// dw := ws.width\n\t// dh := ws.height\n\n\t// --- translate ---\n\tif ev.typ == .mouse_down && ev.mouse_button == .left {\n\t\tapp.tr_flag = true\n\t\tapp.last_tr_x = app.mouse_x\n\t\tapp.last_tr_y = app.mouse_y\n\t}\n\tif ev.typ == .mouse_up && ev.mouse_button == .left && app.tr_flag == true {\n\t\tapp.tr_flag = false\n\t}\n\tif ev.typ == .mouse_move && app.tr_flag == true {\n\t\tapp.tr_x += (app.mouse_x - app.last_tr_x) * 3 * app.gg.scale\n\t\tapp.tr_y += (app.mouse_y - app.last_tr_y) * 3 * app.gg.scale\n\t\tapp.last_tr_x = app.mouse_x\n\t\tapp.last_tr_y = app.mouse_y\n\t\t// println(\"Translate: ${app.tr_x} ${app.tr_y}\")\n\t}\n\n\t// --- scaling ---\n\tif ev.typ == .mouse_down && ev.mouse_button == .right && app.sc_flag == false {\n\t\tapp.sc_flag = true\n\t\tapp.last_sc_x = app.mouse_x\n\t\tapp.last_sc_y = app.mouse_y\n\t}\n\tif ev.typ == .mouse_up && ev.mouse_button == .right && app.sc_flag == true {\n\t\tapp.sc_flag = false\n\t}\n\tif ev.typ == .mouse_move && app.sc_flag == true {\n\t\tapp.sc_x = app.mouse_x - app.last_sc_x\n\t\tapp.sc_y = app.mouse_y - app.last_sc_y\n\t\tapp.last_sc_x = app.mouse_x\n\t\tapp.last_sc_y = app.mouse_y\n\n\t\tapp.scale += f32(app.sc_x / 100)\n\t\tif app.scale < 0.1 {\n\t\t\tapp.scale = 0.1\n\t\t}\n\t\tif app.scale > 32 {\n\t\t\tapp.scale = 32\n\t\t}\n\t}\n\n\tif ev.typ == .key_down {\n\t\t// println(ev.key_code)\n\n\t\t// Exit using the ESC key or Q key\n\t\tif ev.key_code == .escape || ev.key_code == .q {\n\t\t\tcleanup(mut app)\n\t\t\texit(0)\n\t\t}\n\t\t// Toggle info text OSD\n\t\tif ev.key_code == .i {\n\t\t\tapp.show_info_flag = !app.show_info_flag\n\t\t}\n\t\t// Toggle help text\n\t\tif ev.key_code == .h {\n\t\t\tapp.show_help_flag = !app.show_help_flag\n\t\t}\n\n\t\t// do actions only if there are items in the list\n\t\tif app.item_list.loaded == true && app.item_list.n_item > 0 {\n\t\t\t// show previous image\n\t\t\tif ev.key_code == .left {\n\t\t\t\tapp.item_list.get_next_item(-1)\n\t\t\t\tload_image(mut app)\n\t\t\t}\n\t\t\t// show next image\n\t\t\tif ev.key_code == .right {\n\t\t\t\tapp.item_list.get_next_item(1)\n\t\t\t\tload_image(mut app)\n\t\t\t}\n\n\t\t\t// jump to the next container if possible\n\t\t\tif ev.key_code == .up {\n\t\t\t\tapp.item_list.go_to_next_container(1)\n\t\t\t\tload_image(mut app)\n\t\t\t}\n\t\t\t// jump to the previous container if possible\n\t\t\tif ev.key_code == .down {\n\t\t\t\tapp.item_list.go_to_next_container(-1)\n\t\t\t\tload_image(mut app)\n\t\t\t}\n\n\t\t\t// rotate the image\n\t\t\tif ev.key_code == .r {\n\t\t\t\tapp.item_list.rotate(1)\n\t\t\t}\n\n\t\t\t// full screen\n\t\t\tif ev.key_code == .f {\n\t\t\t\tprintln('Full screen state: ${sapp.is_fullscreen()}')\n\t\t\t\tsapp.toggle_fullscreen()\n\t\t\t}\n\t\t}\n\t}\n\n\t// drag&drop\n\tif ev.typ == .files_dropped {\n\t\tapp.state = .scanning\n\t\t// set logo texture during scanning\n\t\tshow_logo(mut app)\n\n\t\tnum := sapp.get_num_dropped_files()\n\t\tmut file_list := []string{}\n\t\tfor i in 0 .. num {\n\t\t\tfile_list << sapp.get_dropped_file_path(i)\n\t\t}\n\t\tprintln('Scanning: ${file_list}')\n\t\tapp.item_list = &Item_list{}\n\t\tapp.item_list.loaded = false\n\n\t\t// load_image(mut app)\n\t\t// go app.item_list.get_items_list(file_list)\n\n\t\tload_and_show(file_list, mut app)\n\t}\n}\n\nfn load_and_show(file_list []string, mut app App) {\n\tapp.item_list.get_items_list(file_list)\n\tload_image(mut app)\n}\n\n/******************************************************************************\n*\n* Main\n*\n******************************************************************************/\nfn main() {\n\t// mut font_path := os.resource_abs_path(os.join_path('../assets/fonts/', 'RobotoMono-Regular.ttf'))\n\tfont_name := 'RobotoMono-Regular.ttf'\n\tfont_path := os.join_path(os.temp_dir(), font_name)\n\tprintln('Temporary path for the font file: [${font_path}]')\n\n\t// if the font doesn't exist create it from the embedded one\n\tif os.exists(font_path) == false {\n\t\tprintln('Write font [${font_name}] in temp folder.')\n\t\tembedded_file := $embed_file('../assets/fonts/RobotoMono-Regular.ttf')\n\t\tos.write_file(font_path, embedded_file.to_string()) or {\n\t\t\teprintln('ERROR: not able to write font file to [${font_path}]')\n\t\t\texit(1)\n\t\t}\n\t}\n\n\t// logo image\n\tlogo_name := 'logo.png'\n\tlogo_path := os.join_path(os.temp_dir(), logo_name)\n\tprintln('Temporary path for the logo: [${logo_path}]')\n\t// if the logo doesn't exist create it from the embedded one\n\tif os.exists(logo_path) == false {\n\t\tprintln('Write logo [${logo_name}] in temp folder.')\n\t\tembedded_file := $embed_file('../assets/logo.png')\n\t\tos.write_file(logo_path, embedded_file.to_string()) or {\n\t\t\teprintln('ERROR: not able to write logo file to [${logo_path}]')\n\t\t\texit(1)\n\t\t}\n\t}\n\n\t// App init\n\tmut app := &App{\n\t\tgg: unsafe { nil }\n\t\t// zip fields\n\t\tzip:       unsafe { nil }\n\t\titem_list: unsafe { nil }\n\t}\n\n\tapp.state = .scanning\n\tapp.logo_path = logo_path\n\tapp.font_path = font_path\n\n\t// Scan all the arguments to find images\n\tapp.item_list = &Item_list{}\n\t// app.item_list.get_items_list(os.args[1..])\n\tload_and_show(os.args[1..], mut app)\n\n\tapp.gg = gg.new_context(\n\t\twidth:                        win_width\n\t\theight:                       win_height\n\t\tcreate_window:                true\n\t\twindow_title:                 'V Image viewer 0.8'\n\t\tuser_data:                    app\n\t\tbg_color:                     bg_color\n\t\tframe_fn:                     frame\n\t\tinit_fn:                      app_init\n\t\tcleanup_fn:                   cleanup\n\t\tevent_fn:                     my_event_manager\n\t\tfont_path:                    font_path\n\t\tenable_dragndrop:             true\n\t\tmax_dropped_files:            64\n\t\tmax_dropped_file_path_length: 2048\n\t\t// ui_mode: true\n\t)\n\n\tapp.gg.run()\n}\n"
  },
  {
    "path": "examples/viewer/zip_container.v",
    "content": "/**********************************************************************\n*\n* Zip container manager\n*\n* Copyright (c) 2021 Dario Deledda. All rights reserved.\n* Use of this source code is governed by an MIT license\n* that can be found in the LICENSE file.\n*\n* TODO:\n**********************************************************************/\nimport sokol.gfx\nimport compress.szip\n\nfn (mut il Item_list) scan_zip(path string, in_index int) ! {\n\tprintln('Scanning ZIP [${path}]')\n\tmut zp := szip.open(path, szip.CompressionLevel.no_compression, szip.OpenMode.read_only)!\n\tn_entries := zp.total()!\n\t// println(n_entries)\n\tfor index in 0 .. n_entries {\n\t\tzp.open_entry_by_index(index)!\n\t\tis_dir := zp.is_dir()!\n\t\tname := zp.name()\n\t\tsize := zp.size()\n\t\t// println(\"${index} ${name} ${size:10} ${is_dir}\")\n\n\t\tif !is_dir {\n\t\t\text := get_extension(name)\n\t\t\tif is_image(ext) == true {\n\t\t\t\til.n_item += 1\n\t\t\t\tmut item := Item{\n\t\t\t\t\tneed_extract:         true\n\t\t\t\t\tpath:                 path\n\t\t\t\t\tname:                 name.clone()\n\t\t\t\t\tcontainer_index:      in_index\n\t\t\t\t\tcontainer_item_index: index\n\t\t\t\t\ti_type:               ext\n\t\t\t\t\tn_item:               il.n_item\n\t\t\t\t\tdrawable:             true\n\t\t\t\t\tsize:                 size\n\t\t\t\t}\n\t\t\t\til.lst << item\n\t\t\t}\n\t\t}\n\t\t// IMPORTANT NOTE: don't close the zip entry before we have used all the items!!\n\t\tzp.close_entry()\n\t}\n\tzp.close()\n}\n\nfn (mut app App) load_texture_from_zip() !(gfx.Image, gfx.Sampler, int, int) {\n\titem := app.item_list.lst[app.item_list.item_index]\n\t// println(\"Load from zip [${item.path}]\")\n\n\t// open the zip\n\tif app.zip_index != item.container_index {\n\t\tif app.zip_index >= 0 {\n\t\t\tapp.zip.close()\n\t\t}\n\t\tapp.zip_index = item.container_index\n\t\t// println(\"Opening the zip [${item.path}]\")\n\t\tapp.zip = szip.open(item.path, szip.CompressionLevel.no_compression, szip.OpenMode.read_only)!\n\t}\n\t// println(\"Now get the image\")\n\tapp.zip.open_entry_by_index(item.container_item_index)!\n\tzip_entry_size := int(item.size)\n\n\tapp.resize_buf_if_needed(zip_entry_size)\n\n\tapp.zip.read_entry_buf(app.mem_buf, app.mem_buf_size)!\n\tapp.zip.close_entry()\n\treturn app.load_texture_from_buffer(app.mem_buf, zip_entry_size)\n}\n"
  },
  {
    "path": "examples/vmatrix.v",
    "content": "import os\nimport rand\nimport term\nimport term.termios\nimport time\n\nconst snooze = time.millisecond * 70\nconst symbols = '0123456789!@#$%^&*()-=+[]{}|;:<>?~bdjpqtvz'\n\nstruct RainColumn {\nmut:\n\tcol  int\n\tlen  int // length of the rain column\n\thead int = 1 // y position of the head of rain column\n}\n\nfn main() {\n\tinit_terminal()!\n\train() // ctrl-c to exit\n}\n\nfn rain() {\n\tmut rain_columns := []RainColumn{}\n\tmut width := 0\n\tmut height := 0\n\n\tfor {\n\t\t// clear screen and all rain columns if terminal resized\n\t\tw, h := term.get_terminal_size()\n\t\tif w != width || h != height {\n\t\t\twidth = w\n\t\t\theight = h\n\t\t\tterm.clear()\n\t\t\train_columns.clear()\n\t\t}\n\t\t// gradually add more rain columns\n\t\tif rain_columns.len < (width / 4 * 3) {\n\t\t\train_columns << random_rain_column(width, height)\n\t\t}\n\t\t// update and print all rain columns\n\t\tfor mut rc in rain_columns {\n\t\t\tupdate_rain_column(mut rc, width, height)\n\t\t\tprint_rain_column(rc, height)\n\t\t}\n\t\t// snooze controls update speed\n\t\ttime.sleep(snooze)\n\t}\n}\n\nfn update_rain_column(mut rc RainColumn, width int, height int) {\n\trc.head += 1\n\tif rc.head > height + rc.len {\n\t\trc = random_rain_column(width, height)\n\t}\n}\n\nfn random_rain_column(max_col int, max_height int) RainColumn {\n\treturn RainColumn{\n\t\t// console positions are 1 based, not zero\n\t\tcol: rand.int_in_range(1, max_col + 1) or { 1 }\n\t\tlen: rand.int_in_range(4, max_height / 4 * 3) or { 4 }\n\t}\n}\n\nfn print_rain_column(rc RainColumn, height int) {\n\t// print head in gray\n\tif rc.head <= height {\n\t\tprint_at(term.gray(random_symbol()), rc.col, rc.head)\n\t}\n\t// print the char above the head in green to remove\n\t// gray color of the previous head. Dim chars\n\t// randomly to add more interest to the effect\n\tif (rc.head - 1) <= height {\n\t\tsymbol := random_dim(term.green(random_symbol()))\n\t\tprint_at(symbol, rc.col, rc.head - 1)\n\t}\n\t// remove tail by printing a space\n\ttail := rc.head - rc.len + 1\n\tif tail > 0 && tail <= height {\n\t\tprint_at(' ', rc.col, tail)\n\t}\n}\n\nfn print_at(s string, x int, y int) {\n\tterm.set_cursor_position(term.Coord{ x: x, y: y })\n\tprint(s)\n}\n\nfn random_symbol() string {\n\tidx := rand.int_in_range(0, symbols.len) or { 0 }\n\treturn symbols[idx].ascii_str()\n}\n\nfn random_dim(s string) string {\n\ti := rand.int_in_range(0, 10) or { 0 }\n\treturn if i == 1 { term.dim(s) } else { s }\n}\n\nfn init_terminal() ! {\n\tmut old_state := termios.Termios{}\n\ttermios.tcgetattr(0, mut old_state)\n\t// restore terminal state on exit\n\tat_exit(fn [mut old_state] () {\n\t\ttermios.set_state(0, old_state)\n\t\tprintln('\\e[?1049l\\e[?25h') // cursor on, alternate buffer mode off\n\t})!\n\t// exit on Ctrl+C\n\tos.signal_opt(os.Signal.int, fn (sig os.Signal) {\n\t\texit(0)\n\t})!\n\t// exit/restore setup, ok to init terminal\n\tmut new_state := old_state\n\tnew_state.disable_echo()\n\ttermios.set_state(0, new_state)\n\tprint('\\e[?1049h\\e[?25l') // cursor off, alternate buffer mode on\n}\n"
  },
  {
    "path": "examples/vmod.v",
    "content": "module main\n\nimport v.vmod\n\nfn main() {\n\tmod := vmod.decode(@VMOD_FILE) or { panic('Error decoding v.mod') }\n\tprintln('${mod.name} has version ${mod.version}')\n\tprintln('\\nThe full mod struct: \\n${mod}')\n}\n"
  },
  {
    "path": "examples/vpwgen.v",
    "content": "import os\nimport os.cmdline\nimport crypto.rand\nimport strings\n\nfn main() {\n\tblocksize := 256\n\tsize := cmdline.option(os.args, '-size', '80').int()\n\trepeats := cmdline.option(os.args, '-repeats', '4').int()\n\tfor _ in 0 .. repeats {\n\t\tmut sb := strings.new_builder(blocksize)\n\t\tfor {\n\t\t\tx := rand.read(blocksize)!\n\t\t\tfor c in x {\n\t\t\t\tif c >= `0` && c <= `~` {\n\t\t\t\t\tsb.write_u8(c)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif sb.len > size {\n\t\t\t\tprintln(sb.str()[0..size])\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "examples/vtail.v",
    "content": "import os\nimport time\n\nif os.args.len == 1 {\n\teprintln('A small `tail -f file` like program, written in V.')\n\teprintln('Usage: `v run examples/vtail.v your_long_file.log`')\n\texit(0)\n}\n\ntfile := os.args[1] or { panic('pass 1 file path as argument') }\nmut f := os.open_file(tfile, 'r') or { panic('file ${tfile} does not exist') }\nf.seek(0, .end)!\nmut read_pos := f.tell()!\nmut buf := []u8{len: 10 * 1024}\nfor {\n\tbytes := f.read_bytes_with_newline(mut buf)!\n\tif bytes == 0 && f.eof() {\n\t\t// The end of the file has been reached, so wait a bit, and retry from the same position:\n\t\tf.close()\n\t\ttime.sleep(500 * time.millisecond)\n\t\tf = os.open_file(tfile, 'r')!\n\t\tf.seek(read_pos, .start)!\n\t\tcontinue\n\t}\n\tread_pos += bytes\n\tprint(unsafe { (&u8(buf.data)).vstring_with_len(bytes) })\n}\n"
  },
  {
    "path": "examples/vwatch/cli_clock/main.v",
    "content": "import time\n// This example demonstrates how to use `v watch` for simple CLI apps.\n\nfn main() {\n\tprintln('Run with: `v watch run examples/vwatch/cli_clock`,')\n\tprintln('then modify timer.v in your editor.')\n\tprintln('The application will be restarted,')\n\tprintln('as soon as you save your changes.')\n\tprintln('')\n\tfor {\n\t\tprintln('The time is now: ${time.now()}')\n\t\ttime.sleep(1000 * time.millisecond)\n\t}\n}\n"
  },
  {
    "path": "examples/vwatch/web_server/.gitignore",
    "content": "*\n!.gitignore\n!main.v\n\n"
  },
  {
    "path": "examples/vwatch/web_server/main.v",
    "content": "module main\n\n// This example demonstrates how to use `v watch` for vweb apps, that use sqlite .db files.\n//\n// Note 1: while developing services, it is useful to also add the `--keep` option of `v watch`,\n// which will restart the app right away, even when it exits on its own.\n//\n// Note 2: vweb supports a special live reload mode, where it will make the browser to check for server\n// restarts, and it will trigger a refresh of the current page, right after that is detected.\n//\n// The above means, that to get the most optimal prototyping experience for vweb apps, use:\n// `v -d vweb_livereload watch --only-watch=*.v,*.html,*.css,*.js --keep run .`\nimport os\nimport vweb\nimport db.sqlite\n\nfn mydb() !sqlite.DB {\n\treturn sqlite.connect(os.resource_abs_path('app.db'))\n}\n\nstruct State {\nmut:\n\tcounter int\n}\n\nstruct App {\n\tvweb.Context\nmut:\n\tstate shared State\n}\n\npub fn (mut app App) index() vweb.Result {\n\tmut c := 0\n\tlock app.state {\n\t\tapp.state.counter++\n\t\tc = app.state.counter\n\t}\n\tvisits := app.update_db() or { 0 }\n\treturn app.html('<!doctype html><html><body>\n\t<br/>Current request counter, after the server restart: ${c}.\n\t<br/>Total stored visits: ${visits}\n\t</body></html>')\n}\n\nfn (mut app App) update_db() !int {\n\tmut db := mydb()!\n\tdb.exec('INSERT INTO visits (created_at) VALUES (\"\")')!\n\tvisits := db.q_int('SELECT count(*) FROM visits')!\n\tdb.close()!\n\treturn visits\n}\n\nfn main() {\n\tprintln('App demonstrating the use of `vweb` & `db.sqlite` together.')\n\tprintln('For best prototyping experience, run with:')\n\tprintln('`v -d vweb_livereload watch --keep run examples/vwatch/web_server/`')\n\tprintln('')\n\tmut db := mydb()!\n\tdb.exec('CREATE TABLE visits (id integer primary key AUTOINCREMENT, created_at timestamp default current_timestamp);')!\n\tdb.exec('CREATE TRIGGER INSERT_visits AFTER INSERT ON visits BEGIN\n\t  UPDATE visits SET created_at = datetime(\"now\", \"localtime\") WHERE rowid = new.rowid ;\n\t\tEND')!\n\tdb.close()!\n\tvweb.run(&App{}, 19123)\n}\n"
  },
  {
    "path": "examples/vweb_fullstack/.editorconfig",
    "content": "[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.v]\nindent_style = tab\n"
  },
  {
    "path": "examples/vweb_fullstack/.gitattributes",
    "content": "* text=auto eol=lf\n*.bat eol=crlf\n\n**/*.v linguist-language=V\n**/*.vv linguist-language=V\n**/*.vsh linguist-language=V\n**/v.mod linguist-language=V\n"
  },
  {
    "path": "examples/vweb_fullstack/.gitignore",
    "content": "# Binaries for programs and plugins\nmain\nbatata\n*.exe\n*.exe~\n*.so\n*.dylib\n*.dll\n*.sql\n\n# Ignore binary output folders\nbin/\n\n# Ignore common editor/system specific metadata\n.DS_Store\n.idea/\n.vscode/\n*.iml\n"
  },
  {
    "path": "examples/vweb_fullstack/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2022 Hitalo Souza\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "examples/vweb_fullstack/readme.md",
    "content": "![image](https://user-images.githubusercontent.com/63821277/230925310-6b8aecfd-ad8d-4967-931b-9656e315f3dd.png)\n\n![image](https://user-images.githubusercontent.com/63821277/230925505-567e64af-343e-4385-9516-9cbf14a18f98.png)\n"
  },
  {
    "path": "examples/vweb_fullstack/src/auth_controllers.v",
    "content": "module main\n\nimport vweb\n\n@['/controller/auth'; post]\npub fn (mut app App) controller_auth(username string, password string) vweb.Result {\n\tresponse := app.service_auth(username, password) or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('error: ${err}')\n\t}\n\n\treturn app.json(response)\n}\n"
  },
  {
    "path": "examples/vweb_fullstack/src/auth_dto.v",
    "content": "module main\n\nstruct AuthRequestDto {\n\tusername string @[nonull]\n\tpassword string @[nonull]\n}\n"
  },
  {
    "path": "examples/vweb_fullstack/src/auth_services.v",
    "content": "module main\n\nimport crypto.hmac\nimport crypto.sha256\nimport crypto.bcrypt\nimport encoding.base64\nimport json\nimport databases\nimport time\n\nstruct JwtHeader {\n\talg string\n\ttyp string\n}\n\nstruct JwtPayload {\n\tsub         string    // (subject) = Entity to whom the token belongs, usually the user ID;\n\tiss         string    // (issuer) = Token issuer;\n\texp         string    // (expiration) = Timestamp of when the token will expire;\n\tiat         time.Time // (issued at) = Timestamp of when the token was created;\n\taud         string    // (audience) = Token recipient, represents the application that will use it.\n\tname        string\n\troles       string\n\tpermissions string\n}\n\nfn (mut app App) service_auth(username string, password string) !string {\n\tmut db := databases.create_db_connection() or {\n\t\teprintln(err)\n\t\tpanic(err)\n\t}\n\n\tdefer {\n\t\tdb.close() or { panic(err) }\n\t}\n\n\tusers := sql db {\n\t\tselect from User where username == username\n\t}!\n\tif users.len == 0 {\n\t\treturn error('user not found')\n\t}\n\tuser := users.first()\n\tif user.username != username {\n\t\treturn error('user not found')\n\t}\n\n\tif !user.active {\n\t\treturn error('user is not active')\n\t}\n\n\tbcrypt.compare_hash_and_password(password.bytes(), user.password.bytes()) or {\n\t\treturn error('Failed to auth user, ${err}')\n\t}\n\n\ttoken := make_token(user)\n\treturn token\n}\n\nfn make_token(user User) string {\n\tsecret := 'SECRET_KEY' // os.getenv('SECRET_KEY')\n\n\tjwt_header := JwtHeader{'HS256', 'JWT'}\n\tjwt_payload := JwtPayload{\n\t\tsub:  '${user.id}'\n\t\tname: '${user.username}'\n\t\tiat:  time.now()\n\t}\n\n\theader := base64.url_encode(json.encode(jwt_header).bytes())\n\tpayload := base64.url_encode(json.encode(jwt_payload).bytes())\n\tsignature := base64.url_encode(hmac.new(secret.bytes(), '${header}.${payload}'.bytes(),\n\t\tsha256.sum, sha256.block_size).bytestr().bytes())\n\n\tjwt := '${header}.${payload}.${signature}'\n\n\treturn jwt\n}\n\nfn auth_verify(token string) bool {\n\tif token == '' {\n\t\treturn false\n\t}\n\tsecret := 'SECRET_KEY' // os.getenv('SECRET_KEY')\n\ttoken_split := token.split('.')\n\n\tsignature_mirror := hmac.new(secret.bytes(), '${token_split[0]}.${token_split[1]}'.bytes(),\n\t\tsha256.sum, sha256.block_size).bytestr().bytes()\n\n\tsignature_from_token := base64.url_decode(token_split[2])\n\n\treturn hmac.equal(signature_from_token, signature_mirror)\n\t// return true\n}\n"
  },
  {
    "path": "examples/vweb_fullstack/src/databases/config_databases_sqlite.v",
    "content": "module databases\n\nimport db.sqlite // can change to 'db.mysql', 'db.pg'\n\npub fn create_db_connection() !sqlite.DB {\n\tmut db := sqlite.connect('app.db')!\n\treturn db\n}\n"
  },
  {
    "path": "examples/vweb_fullstack/src/index.html",
    "content": "<!DOCTYPE html>\n<head>\n   <!--Let browser know website is optimized for mobile-->\n   <meta charset=\"UTF-8\" name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n   <!-- Compiled and minified CSS -->\n   <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css\">\n   <!-- Compiled and minified JavaScript -->\n   <script src=\"https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js\"></script>\n   <!-- Material UI icons -->\n   <link href=\"https://fonts.googleapis.com/icon?family=Material+Icons\" rel=\"stylesheet\">\n   <title>${title}</title>\n</head>\n<body>\n   <div>@include 'templates/header_component.html'</div>\n   <div  class=\"card-panel center-align\" style=\"max-width: 240px; padding: 10px; margin: 10px; border-radius: 5px;\">\n      <form id=\"index_form\" method='post' action=''>\n         <div style=\"display:flex; flex-direction: column;\">\n            <input type='text' name='username' placeholder='Username' required autofocus>\n            <input type='password' name='password' placeholder='Password' required>\n         </div>\n         <div style=\"margin-top: 10px;\">\n            <input class=\"waves-effect waves-light btn-small\" type='submit' onclick=\"login()\" formaction=\"javascript:void(0);\" value='Login'>\n            <input class=\"waves-effect waves-light btn-small\" type='submit' onclick=\"addUser()\" formaction=\"javascript:void(0);\" value='Register'>\n         </div>\n      </form>\n      <script type=\"text/javascript\">\n        // function eraseCookie(name) {\n        //     document.cookie = name + '=; Max-Age=0'\n        // }\n         async function addUser() {\n         const form = document.querySelector('#index_form');\n         const formData = new FormData(form);\n            await fetch('/controller/user/create', {\n                 method: 'POST',\n                 body: formData\n             })                \n             .then( async (response) => {\n                 if (response.status != 201) {\n                     throw await response.text()\n                 }\n                 return await response.text()\n             })\n             .then((data) => {\n                 alert(\"User created successfully\")\n             })\n             .catch((error) => {\n                 alert(error);\n             });\n         }\n         async function login() {\n            const form = document.querySelector('#index_form');\n            const formData = new FormData(form);\n             await fetch('/controller/auth', {\n                 method: 'POST',\n                 body: formData\n             })  \n             .then( async (response) => {\n                 if (response.status != 200) {\n                     throw await response.text()\n                 }\n                 return response.json()\n             })\n             .then((data) => {\n                document.cookie = 'token='+data+';';\n                window.location.href = '/products'\n             })\n             .catch((error) => {\n                 alert(error);\n             });\n         }\n      </script>\n   </div>\n</body>\n</html>"
  },
  {
    "path": "examples/vweb_fullstack/src/main.v",
    "content": "module main\n\nimport vweb\nimport databases\nimport os\n\nconst port = 8082\n\nstruct App {\n\tvweb.Context\n}\n\npub fn (app App) before_request() {\n\tprintln('[web] before_request: ${app.req.method} ${app.req.url}')\n}\n\nfn main() {\n\tmut db := databases.create_db_connection() or { panic(err) }\n\n\tsql db {\n\t\tcreate table User\n\t\tcreate table Product\n\t} or { panic('error on create table: ${err}') }\n\n\tdb.close() or { panic(err) }\n\n\tmut app := &App{}\n\tapp.serve_static('/favicon.ico', 'src/assets/favicon.ico')\n\t// makes all static files available.\n\tapp.mount_static_folder_at(os.resource_abs_path('.'), '/')\n\n\tvweb.run(app, port)\n}\n\npub fn (mut app App) index() vweb.Result {\n\ttitle := 'vweb app'\n\n\treturn $vweb.html()\n}\n"
  },
  {
    "path": "examples/vweb_fullstack/src/product_controller.v",
    "content": "module main\n\nimport vweb\nimport encoding.base64\nimport json\n\n@['/controller/products'; get]\npub fn (mut app App) controller_get_all_products() vweb.Result {\n\ttoken := app.req.header.get_custom('token') or { '' }\n\n\tif !auth_verify(token) {\n\t\tapp.set_status(401, '')\n\t\treturn app.text('Not valid token')\n\t}\n\n\tjwt_payload_stringify := base64.url_decode_str(token.split('.')[1])\n\n\tjwt_payload := json.decode(JwtPayload, jwt_payload_stringify) or {\n\t\tapp.set_status(501, '')\n\t\treturn app.text('jwt decode error')\n\t}\n\n\tuser_id := jwt_payload.sub\n\n\tresponse := app.service_get_all_products_from(user_id.int()) or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('${err}')\n\t}\n\treturn app.json(response)\n\t// return app.text('response')\n}\n\n@['/controller/product/create'; post]\npub fn (mut app App) controller_create_product(product_name string) vweb.Result {\n\tif product_name == '' {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('product name cannot be empty')\n\t}\n\n\ttoken := app.req.header.get_custom('token') or { '' }\n\n\tif !auth_verify(token) {\n\t\tapp.set_status(401, '')\n\t\treturn app.text('Not valid token')\n\t}\n\n\tjwt_payload_stringify := base64.url_decode_str(token.split('.')[1])\n\n\tjwt_payload := json.decode(JwtPayload, jwt_payload_stringify) or {\n\t\tapp.set_status(501, '')\n\t\treturn app.text('jwt decode error')\n\t}\n\n\tuser_id := jwt_payload.sub\n\n\tapp.service_add_product(product_name, user_id.int()) or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('error: ${err}')\n\t}\n\tapp.set_status(201, '')\n\treturn app.text('product created successfully')\n}\n"
  },
  {
    "path": "examples/vweb_fullstack/src/product_entities.v",
    "content": "module main\n\n@[table: 'products']\nstruct Product {\n\tid         int @[primary; sql: serial]\n\tuser_id    int\n\tname       string @[sql_type: 'TEXT']\n\tcreated_at string @[default: 'CURRENT_TIMESTAMP']\n}\n"
  },
  {
    "path": "examples/vweb_fullstack/src/product_service.v",
    "content": "module main\n\nimport databases\n\nfn (mut app App) service_add_product(product_name string, user_id int) ! {\n\tmut db := databases.create_db_connection()!\n\n\tdefer {\n\t\tdb.close() or { panic(err) }\n\t}\n\n\tproduct_model := Product{\n\t\tname:    product_name\n\t\tuser_id: user_id\n\t}\n\n\tmut insert_error := ''\n\n\tsql db {\n\t\tinsert product_model into Product\n\t} or { insert_error = err.msg() }\n\n\tif insert_error != '' {\n\t\treturn error(insert_error)\n\t}\n}\n\nfn (mut app App) service_get_all_products_from(user_id int) ![]Product {\n\tmut db := databases.create_db_connection() or {\n\t\tprintln(err)\n\t\treturn err\n\t}\n\n\tdefer {\n\t\tdb.close() or { panic(err) }\n\t}\n\n\tresults := sql db {\n\t\tselect from Product where user_id == user_id\n\t}!\n\n\treturn results\n}\n"
  },
  {
    "path": "examples/vweb_fullstack/src/product_view.v",
    "content": "module main\n\nimport vweb\n\n@['/products'; get]\npub fn (mut app App) products() !vweb.Result {\n\ttoken := app.get_cookie('token') or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('${err}')\n\t}\n\n\tuser := get_user(token) or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('Failed to fetch data from the server. Error: ${err}')\n\t}\n\n\treturn $vweb.html()\n}\n"
  },
  {
    "path": "examples/vweb_fullstack/src/product_view_api.v",
    "content": "module main\n\nimport json\nimport net.http\n\npub fn get_products(token string) ![]Product {\n\tmut header := http.new_header()\n\theader.add_custom('token', token)!\n\turl := 'http://localhost:8082/controller/products'\n\n\tmut config := http.FetchConfig{\n\t\theader: header\n\t}\n\n\tresp := http.fetch(http.FetchConfig{ ...config, url: url })!\n\tproducts := json.decode([]Product, resp.body)!\n\n\treturn products\n}\n\npub fn get_product(token string) ![]User {\n\tmut header := http.new_header()\n\theader.add_custom('token', token)!\n\n\turl := 'http://localhost:8082/controller/product'\n\n\tmut config := http.FetchConfig{\n\t\theader: header\n\t}\n\n\tresp := http.fetch(http.FetchConfig{ ...config, url: url })!\n\tproducts := json.decode([]User, resp.body)!\n\n\treturn products\n}\n"
  },
  {
    "path": "examples/vweb_fullstack/src/templates/header_component.html",
    "content": "<nav>\n  <div class=\"nav-wrapper\">\n    <a href=\"javascript:window.history.back();\" class=\"left\">\n      <i class=\"material-icons\">arrow_back_ios_new</i>\n    </a>\n    <a href=\"/\">\n      <img src=\"src/assets/veasel.png\" alt=\"logo\" style=\"max-height: 100%\" />\n    </a>\n    <ul id=\"nav-mobile\" class=\"right\">\n      <li><a href=\"https://github.com/vlang/v\">github</a></li>\n      <li><a href=\"https://vlang.io/\">website</a></li>\n      <li><a href=\"https://github.com/sponsors/medvednikov\">support</a></li>\n    </ul>\n  </div>\n</nav>\n"
  },
  {
    "path": "examples/vweb_fullstack/src/templates/products.css",
    "content": "h1.title {\n    font-family: Arial, Helvetica, sans-serif;\n    color: #3b7bbf;\n}\n\ndiv.products-table {\n    border: 1px solid; \n    max-width: 720px;\n    padding: 10px;\n    margin: 10px;\n}"
  },
  {
    "path": "examples/vweb_fullstack/src/templates/products.html",
    "content": "<!DOCTYPE html>\n<head>\n    <!--Let browser know website is optimized for mobile-->\n    <meta charset=\"UTF-8\" name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    \n    <!-- Compiled and minified CSS -->\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css\">\n\n    <!-- Compiled and minified JavaScript -->\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js\"></script>\n    \n    <!-- Material UI icons -->\n    <link href=\"https://fonts.googleapis.com/icon?family=Material+Icons\" rel=\"stylesheet\">\n\n    <title>Login</title>\n    @css 'src/templates/products.css'\n</head>\n<body>\n    <div>@include 'header_component.html'</div>\n    <h1 class=\"title\">Hi, ${user.username}! you are online</h1>\n    <!-- <button onclick=\"document.location.reload(true)\">Lala</button> -->\n      <form id=\"product_form\" method='post' action=''>\n        <div class=\"row\">\n            <div class=\"input-field col s2\">\n              <input id=\"product_name\" name='product_name'  type=\"text\" class=\"validate\">\n              <label class=\"active\" for=\"product_name\">product name</label>\n            </div>\n            <div style=\"margin-top: 10px;\">\n               <input class=\"waves-effect waves-light btn-small\" type='submit' onclick=\"addProduct()\" formaction=\"javascript:void(0);\" value='Register' required autofocus>\n            </div>\n          </div>\n         <!-- <div style=\"width: 20; height: 300;\">\n            <input type='text' name='product_name' placeholder='product name' required autofocus>\n         </div> -->\n      </form>\n      <script type=\"text/javascript\">\n        function getCookie(cookieName) {\n            let cookie = {};\n            document.cookie.split(';').forEach(function(el) {\n                let [key,value] = el.split('=');\n                cookie[key.trim()] = value;\n            })\n            return cookie[cookieName];\n        }\n         async function addProduct() {\n            const form = document.querySelector('#product_form');\n            const formData = new FormData(form);\n            console.log(getCookie(\"token\"));\n            await fetch('/controller/product/create', {\n                 method: 'POST',\n                 body: formData,\n                 headers :{\n                    token: getCookie(\"token\")\n                 }\n             })                \n             .then( async (response) => {\n                 if (response.status != 201) {\n                     throw await response.text()\n                 }\n                 return await response.text()\n             })\n             .then((data) => {\n                //  alert(\"User created successfully\")\n                 document.location.reload(true)\n             })\n             .catch((error) => {\n                 alert(error);\n             });\n         }\n      </script>\n    <div class=\"products-table card-panel\">\n        <table class=\"highlight striped responsive-table\">\n            <thead>\n            <tr>\n                <th>ID</th>\n                <th>Name</th>\n                <th>Created date</th>\n            </tr>\n            </thead>\n\n            <tbody>\n                @for product in user.products\n                <tr>\n                    <td>${product.id}</td>\n                    <td>${product.name}</td>\n                    <td>${product.created_at}</td>\n                </tr>\n                @end\n            </tbody>\n        </table>\n    </div>\n</body>\n</html>"
  },
  {
    "path": "examples/vweb_fullstack/src/user_controllers.v",
    "content": "module main\n\nimport vweb\nimport encoding.base64\nimport json\n\n@['/controller/users'; get]\npub fn (mut app App) controller_get_all_user() vweb.Result {\n\t// token := app.get_cookie('token') or { '' }\n\ttoken := app.req.header.get_custom('token') or { '' }\n\n\tif !auth_verify(token) {\n\t\tapp.set_status(401, '')\n\t\treturn app.text('Not valid token')\n\t}\n\n\tresponse := app.service_get_all_user() or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('${err}')\n\t}\n\treturn app.json(response)\n}\n\n@['/controller/user'; get]\npub fn (mut app App) controller_get_user() vweb.Result {\n\t// token := app.get_cookie('token') or { '' }\n\ttoken := app.req.header.get_custom('token') or { '' }\n\n\tif !auth_verify(token) {\n\t\tapp.set_status(401, '')\n\t\treturn app.text('Not valid token')\n\t}\n\n\tjwt_payload_stringify := base64.url_decode_str(token.split('.')[1])\n\n\tjwt_payload := json.decode(JwtPayload, jwt_payload_stringify) or {\n\t\tapp.set_status(501, '')\n\t\treturn app.text('jwt decode error')\n\t}\n\n\tuser_id := jwt_payload.sub\n\n\tresponse := app.service_get_user(user_id.int()) or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('${err}')\n\t}\n\treturn app.json(response)\n}\n\n@['/controller/user/create'; post]\npub fn (mut app App) controller_create_user(username string, password string) vweb.Result {\n\tif username == '' {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('username cannot be empty')\n\t}\n\tif password == '' {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('password cannot be empty')\n\t}\n\tapp.service_add_user(username, password) or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('error: ${err}')\n\t}\n\tapp.set_status(201, '')\n\treturn app.text('User created successfully')\n}\n"
  },
  {
    "path": "examples/vweb_fullstack/src/user_entities.v",
    "content": "module main\n\n@[table: 'users']\npub struct User {\nmut:\n\tid       int    @[primary; sql: serial]\n\tusername string @[sql_type: 'TEXT'; unique]\n\tpassword string @[sql_type: 'TEXT']\n\tactive   bool\n\tproducts []Product @[fkey: 'user_id']\n}\n"
  },
  {
    "path": "examples/vweb_fullstack/src/user_services.v",
    "content": "module main\n\nimport crypto.bcrypt\nimport databases\n\nfn (mut app App) service_add_user(username string, password string) ! {\n\tmut db := databases.create_db_connection()!\n\n\tdefer {\n\t\tdb.close() or { panic(err) }\n\t}\n\n\thashed_password := bcrypt.generate_from_password(password.bytes(), bcrypt.min_cost) or {\n\t\teprintln(err)\n\t\treturn err\n\t}\n\n\tuser_model := User{\n\t\tusername: username\n\t\tpassword: hashed_password\n\t\tactive:   true\n\t}\n\n\tmut insert_error := ''\n\tsql db {\n\t\tinsert user_model into User\n\t} or { insert_error = err.msg() }\n\tif insert_error != '' {\n\t\treturn error(insert_error)\n\t}\n}\n\nfn (mut app App) service_get_all_user() ![]User {\n\tmut db := databases.create_db_connection() or {\n\t\tprintln(err)\n\t\treturn err\n\t}\n\n\tdefer {\n\t\tdb.close() or { panic(err) }\n\t}\n\n\tresults := sql db {\n\t\tselect from User\n\t}!\n\n\treturn results\n}\n\nfn (mut app App) service_get_user(id int) !User {\n\tmut db := databases.create_db_connection() or {\n\t\tprintln(err)\n\t\treturn err\n\t}\n\n\tdefer {\n\t\tdb.close() or { panic(err) }\n\t}\n\n\tresults := sql db {\n\t\tselect from User where id == id\n\t}!\n\n\treturn results.first()\n}\n"
  },
  {
    "path": "examples/vweb_fullstack/src/user_view_api.v",
    "content": "module main\n\nimport json\nimport net.http\n\npub fn get_users(token string) ![]User {\n\tmut header := http.new_header()\n\theader.add_custom('token', token)!\n\n\turl := 'http://localhost:8082/controller/users'\n\n\tmut config := http.FetchConfig{\n\t\theader: header\n\t}\n\n\tresp := http.fetch(http.FetchConfig{ ...config, url: url })!\n\tusers := json.decode([]User, resp.body)!\n\n\treturn users\n}\n\npub fn get_user(token string) !User {\n\tmut header := http.new_header()\n\theader.add_custom('token', token)!\n\n\turl := 'http://localhost:8082/controller/user'\n\n\tmut config := http.FetchConfig{\n\t\theader: header\n\t}\n\n\tresp := http.fetch(http.FetchConfig{ ...config, url: url })!\n\tusers := json.decode(User, resp.body)!\n\n\treturn users\n}\n"
  },
  {
    "path": "examples/vweb_fullstack/src/v.mod",
    "content": "Module {\n\tname: 'vweb_fullstack'\n\tdescription: ''\n\tversion: ''\n\tlicense: ''\n\tdependencies: []\n}\n"
  },
  {
    "path": "examples/vweb_orm_jwt/.editorconfig",
    "content": "[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.v]\nindent_style = tab\n"
  },
  {
    "path": "examples/vweb_orm_jwt/.gitattributes",
    "content": "*.v linguist-language=V text=auto eol=lf\n*.vv linguist-language=V text=auto eol=lf\n*.vsh linguist-language=V text=auto eol=lf\n**/v.mod linguist-language=V text=auto eol=lf\n"
  },
  {
    "path": "examples/vweb_orm_jwt/.gitignore",
    "content": "# Binaries for programs and plugins\nmain\nv\n*.exe\n*.exe~\n*.so\n*.dylib\n*.dll\nvls.log\n.env\n*.db\n"
  },
  {
    "path": "examples/vweb_orm_jwt/src/auth_controllers.v",
    "content": "module main\n\nimport vweb\nimport json\n\n@['/auth/login'; post]\npub fn (mut app App) controller_auth() vweb.Result {\n\tbody := json.decode(AuthRequestDto, app.req.data) or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('Failed to decode json, error: ${err}')\n\t}\n\n\tresponse := app.service_auth(body.username, body.password) or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('error: ${err}')\n\t}\n\n\treturn app.json(response)\n}\n"
  },
  {
    "path": "examples/vweb_orm_jwt/src/auth_dto.v",
    "content": "module main\n\nstruct AuthRequestDto {\n\t// Adding a @[required] attribute will make decoding fail, if that field is not present in the input.\n\t// If a field is not [required], but is missing, it will be assumed to have its default value, like 0 for numbers, or '' for strings, and decoding will not fail.\n\tusername string @[required]\n\tpassword string @[required]\n}\n"
  },
  {
    "path": "examples/vweb_orm_jwt/src/auth_services.v",
    "content": "module main\n\nimport crypto.hmac\nimport crypto.sha256\nimport crypto.bcrypt\nimport encoding.base64\nimport json\nimport databases\nimport time\nimport os\n\nstruct JwtHeader {\n\talg string\n\ttyp string\n}\n\nstruct JwtPayload {\n\tsub         string    // (subject) = Entity to whom the token belongs, usually the user ID;\n\tiss         string    // (issuer) = Token issuer;\n\texp         string    // (expiration) = Timestamp of when the token will expire;\n\tiat         time.Time // (issued at) = Timestamp of when the token was created;\n\taud         string    // (audience) = Token recipient, represents the application that will use it.\n\tname        string\n\troles       string\n\tpermissions string\n}\n\nfn (mut app App) service_auth(username string, password string) !string {\n\tmut db := databases.create_db_connection() or {\n\t\teprintln(err)\n\t\tpanic(err)\n\t}\n\n\tusers := sql db {\n\t\tselect from User where username == username\n\t}!\n\n\tif users.len == 0 {\n\t\treturn error('user not found')\n\t}\n\n\tuser := users.first()\n\tif !user.active {\n\t\treturn error('user is not active')\n\t}\n\n\tdb.close()!\n\n\tbcrypt.compare_hash_and_password(password.bytes(), user.password.bytes()) or {\n\t\treturn error('Failed to auth user, ${err}')\n\t}\n\n\ttoken := make_token(user)\n\n\treturn token\n}\n\nfn make_token(user User) string {\n\tsecret := os.getenv('SECRET_KEY')\n\n\tjwt_header := JwtHeader{'HS256', 'JWT'}\n\tjwt_payload := JwtPayload{\n\t\tsub:  '${user.id}'\n\t\tname: '${user.username}'\n\t\tiat:  time.now()\n\t}\n\n\theader := base64.url_encode(json.encode(jwt_header).bytes())\n\tpayload := base64.url_encode(json.encode(jwt_payload).bytes())\n\tsignature := base64.url_encode(hmac.new(secret.bytes(), '${header}.${payload}'.bytes(),\n\t\tsha256.sum, sha256.block_size).bytestr().bytes())\n\n\tjwt := '${header}.${payload}.${signature}'\n\n\treturn jwt\n}\n\nfn auth_verify(token string) bool {\n\tif token == '' {\n\t\treturn false\n\t}\n\tsecret := os.getenv('SECRET_KEY')\n\ttoken_split := token.split('.')\n\n\tsignature_mirror := hmac.new(secret.bytes(), '${token_split[0]}.${token_split[1]}'.bytes(),\n\t\tsha256.sum, sha256.block_size).bytestr().bytes()\n\n\tsignature_from_token := base64.url_decode(token_split[2])\n\n\treturn hmac.equal(signature_from_token, signature_mirror)\n}\n"
  },
  {
    "path": "examples/vweb_orm_jwt/src/databases/config_databases_sqlite.v",
    "content": "module databases\n\nimport db.sqlite\n\npub fn create_db_connection() !sqlite.DB {\n\tmut db := sqlite.connect('database.db')!\n\treturn db\n}\n"
  },
  {
    "path": "examples/vweb_orm_jwt/src/main.v",
    "content": "module main\n\nimport vweb\nimport databases\n\nconst http_port = 8081\n\nstruct App {\n\tvweb.Context\n}\n\npub fn (app App) before_request() {\n\tprintln('[Vweb] ${app.Context.req.method} ${app.Context.req.url}')\n}\n\nfn main() {\n\tmut db := databases.create_db_connection() or { panic(err) }\n\n\tsql db {\n\t\tcreate table User\n\t} or { panic('error on create table: ${err}') }\n\n\tdb.close() or { panic(err) }\n\n\tvweb.run(new_app(), http_port)\n}\n\nfn new_app() &App {\n\tmut app := &App{}\n\n\treturn app\n}\n\n@['/'; get]\npub fn (mut app App) ping() ?vweb.Result {\n\treturn app.text('ping')\n}\n"
  },
  {
    "path": "examples/vweb_orm_jwt/src/user_controllers.v",
    "content": "module main\n\nimport vweb\nimport json\nimport databases\n\n@['/user/:id/get'; get]\npub fn (mut app App) controller_get_user_by_id(id int) vweb.Result {\n\tresponse := app.service_get_user_by_id(id) or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('${err}')\n\t}\n\treturn app.json(response)\n}\n\n@['/user/create'; post]\npub fn (mut app App) controller_create_user() vweb.Result {\n\tbody := json.decode(User, app.req.data) or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('Failed to decode json, error: ${err}')\n\t}\n\n\tresponse := app.service_add_user(body.username, body.password) or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('error: ${err}')\n\t}\n\n\treturn app.json(response)\n}\n\n@['/user/get_all'; get]\npub fn (mut app App) controller_get_all_user() vweb.Result {\n\ttoken := app.get_header('token')\n\n\tif !auth_verify(token) {\n\t\tapp.set_status(401, '')\n\t\treturn app.text('Not valid token')\n\t}\n\n\tresponse := app.service_get_all_user() or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('${err}')\n\t}\n\treturn app.json(response)\n}\n\n@['/user/get_by_username/:username'; get]\npub fn (mut app App) controller_get_by_username(username string) vweb.Result {\n\tresponse := app.service_get_by_username(username) or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('${err}')\n\t}\n\treturn app.json(response)\n}\n\n@['/user/drop'; delete]\npub fn (mut app App) delete() vweb.Result {\n\tmut db := databases.create_db_connection() or {\n\t\tapp.set_status(400, '')\n\t\treturn app.text('${err}')\n\t}\n\n\tdefer {\n\t\tdb.close() or { panic(err) }\n\t}\n\n\tsql db {\n\t\tdrop table User\n\t} or { panic(err) }\n\n\treturn app.text('Successfully deleted table')\n}\n"
  },
  {
    "path": "examples/vweb_orm_jwt/src/user_entities.v",
    "content": "module main\n\n@[table: 'users']\nstruct User {\nmut:\n\tid         int    @[primary; sql: serial]\n\tusername   string @[required; sql_type: 'TEXT']\n\tpassword   string @[required; sql_type: 'TEXT']\n\tcreated_at string @[default: 'CURRENT_TIMESTAMP']\n\tupdated_at string @[default: 'CURRENT_TIMESTAMP']\n\tdeleted_at string @[default: 'CURRENT_TIMESTAMP']\n\tactive     bool\n}\n"
  },
  {
    "path": "examples/vweb_orm_jwt/src/user_services.v",
    "content": "module main\n\nimport crypto.bcrypt\nimport databases\n\nfn (mut app App) service_add_user(username string, password string) !User {\n\tmut db := databases.create_db_connection() or {\n\t\teprintln(err)\n\t\treturn err\n\t}\n\n\tdefer {\n\t\tdb.close() or { panic(err) }\n\t}\n\n\thashed_password := bcrypt.generate_from_password(password.bytes(), bcrypt.min_cost) or {\n\t\teprintln(err)\n\t\treturn err\n\t}\n\n\tuser_model := User{\n\t\tusername: username\n\t\tpassword: hashed_password\n\t\tactive:   true\n\t}\n\n\tsql db {\n\t\tinsert user_model into User\n\t} or {\n\t\teprintln(err)\n\t\treturn err\n\t}\n\n\tusers := sql db {\n\t\tselect from User where username == username limit 1\n\t}!\n\n\treturn users.first()\n}\n\nfn (mut app App) service_get_user_by_id(user_id int) !User {\n\tmut db := databases.create_db_connection() or {\n\t\tprintln(err)\n\t\treturn err\n\t}\n\n\tdefer {\n\t\tdb.close() or { panic(err) }\n\t}\n\n\tusers := sql db {\n\t\tselect from User where id == user_id\n\t}!\n\n\treturn users.first()\n}\n\nfn (mut app App) service_get_all_user() ![]User {\n\tmut db := databases.create_db_connection() or {\n\t\tprintln(err)\n\t\treturn err\n\t}\n\n\tdefer {\n\t\tdb.close() or { panic(err) }\n\t}\n\n\tresults := sql db {\n\t\tselect from User\n\t}!\n\n\treturn results\n}\n\nfn (mut app App) service_get_by_username(username string) !User {\n\tmut db := databases.create_db_connection() or {\n\t\tprintln(err)\n\t\treturn err\n\t}\n\n\tdefer {\n\t\tdb.close() or { panic(err) }\n\t}\n\n\tresults := sql db {\n\t\tselect from User where username == username\n\t}!\n\n\tif results.len == 0 {\n\t\treturn error('User not found')\n\t}\n\n\treturn results[0]\n}\n"
  },
  {
    "path": "examples/vweb_orm_jwt/src/v.mod",
    "content": "Module {\n\tname: 'vweb_orm_jwt'\n\tdescription: ''\n\tversion: ''\n\tlicense: ''\n\tdependencies: []\n}\n"
  },
  {
    "path": "examples/wasm/.gitignore",
    "content": "*.wasm\n"
  },
  {
    "path": "examples/wasm/change_color_by_id/README.md",
    "content": "# Run V Mandelbrot Example\n\n## Using only V\n\n```\nv run .\n```\n\n## Using Python or Emscripten\n\n1. First, create `change_color_by_id.wasm`. Compile with `-os browser`.\n\n```\nv -b wasm -os browser change_color_by_id.wasm.v\n```\n\n2. Then, open the `change_color_by_id.html` file in the browser.\n   - CORS errors do not allow `change_color_by_id.wasm` to be loaded.\n   - Use `python -m http.server 8080`\n   - Use `emrun change_color_by_id.html`\n"
  },
  {
    "path": "examples/wasm/change_color_by_id/change_color_by_id.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>App</title>\n  </head>\n  <body>\n    <p id=\"description\">Some cool description</p>\n    <p id=\"description1\">Some cool description</p>\n    <p id=\"description2\">Some cool description</p>\n    <p id=\"description3\">Some cool description</p>\n    <button id=\"myButton\" onclick=\"click_callback()\">Click here</button>\n\n    <script type=\"text/javascript\">\n      var memory;\n      var click_callback;\n\n      function get_string(ptr, len) {\n        const buf = new Uint8Array(memory.buffer, ptr, len);\n        const str = new TextDecoder(\"utf8\").decode(buf);\n        return str;\n      }\n\n      const env = {\n        change_color_by_id: (ptr, len, color_ptr, color_len) => {\n          const elementId = get_string(ptr, len);\n          const color = get_string(color_ptr, color_len);\n\n          var element = document.getElementById(elementId);\n          element.style.color = color;\n        },\n        __writeln: (ptr, len) => {\n          console.log(get_string(ptr, len));\n        },\n        __panic_abort: (ptr, len) => {\n          throw get_string(ptr, len);\n        },\n      };\n\n      WebAssembly.instantiateStreaming(fetch(\"change_color_by_id.wasm\"), {\n        env: env,\n      }).then((res) => {\n        memory = res.instance.exports[\"memory\"];\n\n        console.time(\"main.main\");\n        res.instance.exports[\"main.main\"]();\n        console.timeEnd(\"main.main\");\n\n        click_callback = res.instance.exports[\"main.click_callback\"];\n      });\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/wasm/change_color_by_id/change_color_by_id.wasm.v",
    "content": "// vtest build: false // requires special compilation flags: `-b wasm -os browser`\nfn JS.change_color_by_id(ptr u8, len int, color_ptr u8, color_len int)\n\n// `main` must be public!\npub fn main() {\n\tprintln('starting main.main...')\n\tchange_color_by_id('description', 'red')\n\tchange_color_by_id('description1', 'green')\n\tchange_color_by_id('description2', 'blue')\n\tchange_color_by_id('description3', 'black')\n}\n\npub fn click_callback() {\n\tprintln('Hello from V')\n}\n\nfn change_color_by_id(id string, color string) {\n\tJS.change_color_by_id(id.str, id.len, color.str, color.len)\n}\n"
  },
  {
    "path": "examples/wasm/change_color_by_id/serve_folder.v",
    "content": "module main\n\nimport vweb\nimport os\n\nstruct App {\n\tvweb.Context\n}\n\nfn main() {\n\tos.chdir(os.dir(@FILE))!\n\tcmd := '${os.quoted_path(@VEXE)} -b wasm -os browser change_color_by_id.wasm.v'\n\tprintln('>> compiling change_color_by_id.wasm.v, using: ${cmd}')\n\tos.execute_or_panic(cmd)\n\tmut app := App{}\n\tapp.mount_static_folder_at(os.resource_abs_path('.'), '/')\n\tvweb.run(app, 3001)\n}\n\npub fn (mut app App) index() vweb.Result {\n\treturn app.html(os.read_file('change_color_by_id.html') or { '' })\n}\n"
  },
  {
    "path": "examples/wasm/functions.v",
    "content": "// `pub` functions will be exported.\n//\n// ```\n// v -b wasm -no-builtin functions.v\n// wasmer functions.wasm -i main.powi <a> <b>\n// wasmer functions.wasm -i main.gcd <a> <b>\n// ```\n\npub fn gcd(a_ i64, b_ i64) i64 {\n\tmut a := a_\n\tmut b := b_\n\tif a < 0 {\n\t\ta = -a\n\t}\n\tif b < 0 {\n\t\tb = -b\n\t}\n\tfor b != 0 {\n\t\ta %= b\n\t\tif a == 0 {\n\t\t\treturn b\n\t\t}\n\t\tb %= a\n\t}\n\treturn a\n}\n\npub fn powi(a i64, b i64) i64 {\n\tmut b_ := b\n\tmut p := a\n\tmut v := i64(1)\n\n\tif b_ < 0 { // exponent < 0\n\t\tif a == 0 {\n\t\t\treturn -1 // division by 0\n\t\t}\n\t\treturn if a * a != 1 {\n\t\t\t0\n\t\t} else {\n\t\t\tif (b_ & 1) > 0 {\n\t\t\t\ta\n\t\t\t} else {\n\t\t\t\t1\n\t\t\t}\n\t\t}\n\t}\n\n\tfor b_ > 0 {\n\t\tif b_ & 1 > 0 {\n\t\t\tv *= p\n\t\t}\n\t\tp *= p\n\t\tb_ >>= 1\n\t}\n\n\treturn v\n}\n"
  },
  {
    "path": "examples/wasm/hello_world.v",
    "content": "//\n// $ v -b wasm hello_world.v\n// $ wasmer hello_world.wasm\n// Hello WASI!\n//\n\nfn main() {\n\tprintln('Hello WASI!')\n}\n"
  },
  {
    "path": "examples/wasm/mandelbrot/README.md",
    "content": "# Run V Mandelbrot Example\n\n## Using only V\n\n```\nv run .\n```\n\n## Using Python or Emscripten\n\n1. First, create `mandelbrot.wasm`. Compile with `-os browser`.\n\n```\nv -b wasm -os browser mandelbrot.wasm.v\n```\n\n2. Then, open the `mandelbrot.html` file in the browser.\n   - CORS errors do not allow `mandelbrot.wasm` to be loaded.\n   - Use `python -m http.server 8080`\n   - Use `emrun mandelbrot.html`\n"
  },
  {
    "path": "examples/wasm/mandelbrot/mandelbrot.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"UTF-8\" />\n\t\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n\t\t<title>V Mandelbrot WebAssembly Example</title>\n\t</head>\n\t<body>\n\t\t<p>Below you should see the picture of the Mandelbrot set,\n\t\t<br>calculated in WASM, and shown in a Canvas element.</p>\n\t\t<canvas\n\t\t\tid=\"canvas\"\n\t\t\twidth=\"400\"\n\t\t\theight=\"400\"\n\t\t\tstyle=\"image-rendering: crisp-edges\"\n\t\t></canvas>\n\t\t<script>\n\t\t\tvar canvas = document.getElementById(\"canvas\");\n\t\t\tvar ctx = canvas.getContext(\"2d\");\n\t\t\tctx.font = \"32px serif\";\n\t\t\tctx.fillText(\"Please wait...\", 100, 250);\n\t\t\tvar memory;\n\n\t\t\tfunction get_string(ptr, len) {\n\t\t\t\tconst buf = new Uint8Array(memory.buffer, ptr, len);\n\t\t\t\tconst str = new TextDecoder(\"utf8\").decode(buf);\n\t\t\t\treturn str;\n\t\t\t}\n\n\t\t\tconst env = {\n\t\t\t\tcanvas_x: () => canvas.width,\n\t\t\t\tcanvas_y: () => canvas.height,\n\t\t\t\tsetpixel: (x, y, c) => {\n\t\t\t\t\tctx.fillStyle = \"rgba(1,1,1,\" + c / 255 + \")\";\n\t\t\t\t\tctx.fillRect(x, y, 1, 1);\n\t\t\t\t},\n\t\t\t\t__writeln: (ptr, len) => {\n\t\t\t\t\tconsole.log(get_string(ptr, len));\n\t\t\t\t},\n\t\t\t\t__panic_abort: (ptr, len) => {\n\t\t\t\t\tthrow get_string(ptr, len);\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tWebAssembly.instantiateStreaming(fetch(\"mandelbrot.wasm\"), {\n\t\t\t\tenv: env,\n\t\t\t}).then((res) => {\n\t\t\t\tconsole.log(env.canvas_x())\n\t\t\t\tconsole.log(env.canvas_y())\n\t\t\t\tmemory = res.instance.exports[\"memory\"];\n\t\t\t\tconsole.time(\"main.main\");\n\t\t\t\tres.instance.exports[\"main.main\"]();\n\t\t\t\tconsole.timeEnd(\"main.main\");\n\t\t\t});\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/wasm/mandelbrot/mandelbrot.wasm.v",
    "content": "// vtest build: false // requires special compilation flags: `-b wasm -os browser`\nfn JS.canvas_x() int\nfn JS.canvas_y() int\nfn JS.setpixel(x int, y int, c f64)\n\n// `main` must be public!\npub fn main() {\n\tprintln('starting main.main...')\n\n\tmax_x := JS.canvas_x()\n\tmax_y := JS.canvas_y()\n\tmiddle_x := max_x / 2\n\tmiddle_y := max_y / 2\n\n\tmut y := 0\n\tfor y < max_y {\n\t\ty += 1\n\t\tmut x := 0\n\t\tfor x < max_x {\n\t\t\tx += 1\n\n\t\t\te := (f64(y) / middle_y) - 1.5\n\t\t\tf := (f64(x) / middle_x) - 1.0\n\n\t\t\tmut a := 0.0\n\t\t\tmut b := 0.0\n\t\t\tmut i := 0.0\n\t\t\tmut j := 0.0\n\t\t\tmut c := 0.0\n\n\t\t\tfor i * i + j * j < 4 && c < 255 {\n\t\t\t\ti = a * a - b * b + e\n\t\t\t\tj = 2 * a * b + f\n\t\t\t\ta = i\n\t\t\t\tb = j\n\t\t\t\tc += 1\n\t\t\t}\n\n\t\t\tJS.setpixel(x, y, c)\n\t\t}\n\t}\n\t// TODO: remove the need for panic here:\n\tpanic('reached the end of main.main')\n}\n"
  },
  {
    "path": "examples/wasm/mandelbrot/serve_folder.v",
    "content": "module main\n\nimport vweb\nimport os\n\nstruct App {\n\tvweb.Context\n}\n\nfn main() {\n\tos.chdir(os.dir(@FILE))!\n\tcmd := '${os.quoted_path(@VEXE)} -b wasm -os browser mandelbrot.wasm.v'\n\tprintln('>> compiling mandelbrot.wasm.v, using: ${cmd}')\n\tos.execute_or_panic(cmd)\n\tmut app := App{}\n\tapp.mount_static_folder_at(os.resource_abs_path('.'), '/')\n\tvweb.run(app, 3001)\n}\n\npub fn (mut app App) index() vweb.Result {\n\treturn app.html(os.read_file('mandelbrot.html') or { '' })\n}\n"
  },
  {
    "path": "examples/wasm_codegen/add.v",
    "content": "import wasm\n\nfn main() {\n\tmut m := wasm.Module{}\n\tmut func := m.new_function('add', [.i32_t, .i32_t], [.i32_t])\n\t{\n\t\tfunc.local_get(0)\n\t\tfunc.local_get(1)\n\t\tfunc.add(.i32_t)\n\t}\n\tm.commit(func, true) // `export: true`\n\tprint(m.compile().bytestr())\n}\n"
  },
  {
    "path": "examples/wasm_codegen/bf_compiler.v",
    "content": "import os\nimport wasm\n\nconst runtime_page = 1024 * 64 // 64 KiBs\n\nfn generate_ciovec(mut start wasm.Function, sp wasm.LocalIndex) {\n\t// construct struct __wasi_ciovec_t\n\t//\n\t// field, `const uint8_t *buf`\n\tstart.i32_const(runtime_page)\n\tstart.local_get(sp)\n\tstart.store(.i32_t, 2, 0)\n\t// field, `__wasi_size_t buf_len`\n\tstart.i32_const(runtime_page)\n\tstart.i32_const(1) // len\n\tstart.store(.i32_t, 2, 4)\n}\n\nfn generate_code(mut start wasm.Function, bf_expr string) {\n\t// locals are initialised to zero, by spec\n\tsp := start.new_local_named(.i32_t, 'sp')\n\n\tmut loop_labels := []wasm.LabelIndex{}\n\tmut block_labels := []wasm.LabelIndex{}\n\n\t// our page, the second one\n\n\tfor ch in bf_expr {\n\t\tmatch ch {\n\t\t\t`>` {\n\t\t\t\tstart.local_get(sp)\n\t\t\t\tstart.i32_const(1)\n\t\t\t\tstart.add(.i32_t)\n\t\t\t\tstart.local_set(sp)\n\t\t\t}\n\t\t\t`<` {\n\t\t\t\tstart.local_get(sp)\n\t\t\t\tstart.i32_const(1)\n\t\t\t\tstart.sub(.i32_t)\n\t\t\t\tstart.local_set(sp)\n\t\t\t}\n\t\t\t`+` {\n\t\t\t\tstart.local_get(sp)\n\t\t\t\t{\n\t\t\t\t\tstart.local_get(sp)\n\t\t\t\t\tstart.load8(.i32_t, false, 0, 0)\n\t\t\t\t\tstart.i32_const(1)\n\t\t\t\t\tstart.add(.i32_t)\n\t\t\t\t}\n\t\t\t\tstart.store8(.i32_t, 0, 0)\n\t\t\t}\n\t\t\t`-` {\n\t\t\t\tstart.local_get(sp)\n\t\t\t\t{\n\t\t\t\t\tstart.local_get(sp)\n\t\t\t\t\tstart.load8(.i32_t, false, 0, 0)\n\t\t\t\t\tstart.i32_const(1)\n\t\t\t\t\tstart.sub(.i32_t)\n\t\t\t\t}\n\t\t\t\tstart.store8(.i32_t, 0, 0)\n\t\t\t}\n\t\t\t`.` {\n\t\t\t\tgenerate_ciovec(mut start, sp)\n\n\t\t\t\tstart.i32_const(1) // stdout\n\t\t\t\tstart.i32_const(runtime_page) // *iovs\n\t\t\t\tstart.i32_const(1) // iovs_len\n\t\t\t\tstart.i32_const(runtime_page + 1024) // *nwritten\n\t\t\t\tstart.call_import('wasi_unstable', 'fd_write')\n\t\t\t\tstart.drop() // ignore errno\n\t\t\t}\n\t\t\t`,` {\n\t\t\t\tgenerate_ciovec(mut start, sp)\n\n\t\t\t\tstart.i32_const(0) // stdin\n\t\t\t\tstart.i32_const(runtime_page) // *iovs\n\t\t\t\tstart.i32_const(1) // iovs_len\n\t\t\t\tstart.i32_const(runtime_page + 1024) // *nwritten\n\t\t\t\tstart.call_import('wasi_unstable', 'fd_read')\n\t\t\t\tstart.drop() // ignore errno\n\t\t\t}\n\t\t\t`[` {\n\t\t\t\tblock_lbl := start.c_block([], [])\n\t\t\t\tloop_lbl := start.c_loop([], [])\n\t\t\t\t{\n\t\t\t\t\tstart.local_get(sp)\n\t\t\t\t\tstart.load8(.i32_t, false, 0, 0)\n\t\t\t\t\tstart.eqz(.i32_t)\n\t\t\t\t\tstart.c_br_if(block_lbl)\n\t\t\t\t}\n\t\t\t\tloop_labels << loop_lbl\n\t\t\t\tblock_labels << block_lbl\n\t\t\t}\n\t\t\t`]` {\n\t\t\t\tloop_lbl := loop_labels.pop()\n\t\t\t\tstart.c_br(loop_lbl) // jump back to top\n\t\t\t\tstart.c_end(loop_lbl)\n\t\t\t\tstart.c_end(block_labels.pop())\n\t\t\t}\n\t\t\telse {}\n\t\t}\n\t}\n}\n\n@[noreturn]\nfn usage() {\n\teprintln('Usage: bf <expr> <outfile.wasm>')\n\teprintln('   or: bf <path/input.b> <outfile.wasm> (note the `.b` extension)')\n\texit(1)\n}\n\nfn main() {\n\tmut bf_expr := os.args[1] or { usage() }\n\tif bf_expr.ends_with('.b') {\n\t\tbf_expr = os.read_file(bf_expr) or {\n\t\t\teprintln('file ${bf_expr} could not be read, error: ${err}')\n\t\t\tusage()\n\t\t}\n\t}\n\toutfile := os.args[2] or { usage() }\n\n\tmut m := wasm.Module{}\n\tm.enable_debug('wasm bf')\n\tm.new_function_import('wasi_unstable', 'fd_write', [.i32_t, .i32_t, .i32_t, .i32_t],\n\t\t[.i32_t])\n\tm.new_function_import('wasi_unstable', 'fd_read', [.i32_t, .i32_t, .i32_t, .i32_t],\n\t\t[.i32_t])\n\tm.assign_memory('memory', true, 2, none)\n\n\tmut start := m.new_function('_start', [], [])\n\t{\n\t\tgenerate_code(mut start, bf_expr)\n\t}\n\tm.commit(start, true)\n\n\tbytes := m.compile()\n\tos.write_file_array(outfile, bytes)!\n}\n"
  },
  {
    "path": "examples/wasm_codegen/control_flow.v",
    "content": "import wasm\n\nfn main() {\n\tmut m := wasm.Module{}\n\tmut bif := m.new_function('block_if', [.i32_t], [.i32_t])\n\t{\n\t\tloc := bif.new_local(.i32_t)\n\n\t\t// loc = i32.const 10\n\t\tbif.i32_const(10)\n\t\tbif.local_set(loc)\n\n\t\tblk := bif.c_block([], [])\n\t\t{\n\t\t\t// if argument[0], break\n\t\t\tbif.local_get(0)\n\t\t\tbif.c_br_if(blk)\n\t\t\t// loc = i32.const 11\n\t\t\tbif.i32_const(11)\n\t\t\tbif.local_set(loc)\n\t\t}\n\t\tbif.c_end(blk)\n\n\t\t// return loc\n\t\tbif.local_get(loc)\n\t}\n\tm.commit(bif, true)\n\tmut ifexpr := m.new_function('if_expr', [.i32_t], [.i64_t])\n\t{\n\t\tifexpr.local_get(0)\n\t\tif_blk := ifexpr.c_if([], [.i64_t])\n\t\t{\n\t\t\tifexpr.i64_const(5000)\n\t\t}\n\t\tifexpr.c_else(if_blk)\n\t\t{\n\t\t\tifexpr.i64_const(-5000)\n\t\t}\n\t\tifexpr.c_end(if_blk)\n\t}\n\tm.commit(ifexpr, true)\n\tprint(m.compile().bytestr())\n}\n"
  },
  {
    "path": "examples/wasm_codegen/factorial.v",
    "content": "import wasm\n\nfn main() {\n\tmut m := wasm.Module{}\n\tmut fac := m.new_function('fac', [.i64_t], [.i64_t])\n\t{\n\t\tfac.local_get(0)\n\t\tfac.eqz(.i64_t)\n\t\tbif := fac.c_if([], [.i64_t])\n\t\t{\n\t\t\tfac.i64_const(1)\n\t\t}\n\t\tfac.c_else(bif)\n\t\t{\n\t\t\t{\n\t\t\t\tfac.local_get(0)\n\t\t\t}\n\t\t\t{\n\t\t\t\tfac.local_get(0)\n\t\t\t\tfac.i64_const(1)\n\t\t\t\tfac.sub(.i64_t)\n\t\t\t\tfac.call('fac')\n\t\t\t}\n\t\t\tfac.mul(.i64_t)\n\t\t}\n\t\tfac.c_end(bif)\n\t}\n\tm.commit(fac, true)\n\tprint(m.compile().bytestr())\n\n\t// v run factorial.v > a.wasm\n\t// wasmer a.wasm -i fac 5\n}\n"
  },
  {
    "path": "examples/wasm_codegen/functions.v",
    "content": "import wasm\n\nfn main() {\n\tmut m := wasm.Module{}\n\tmut pyth := m.new_function('pythagoras', [.f32_t, .f32_t], [\n\t\t.f32_t,\n\t])\n\t{\n\t\tpyth.local_get(0)\n\t\tpyth.local_get(0)\n\t\tpyth.mul(.f32_t)\n\t\tpyth.local_get(1)\n\t\tpyth.local_get(1)\n\t\tpyth.mul(.f32_t)\n\t\tpyth.add(.f32_t)\n\t\tpyth.sqrt(.f32_t)\n\t\tpyth.cast(.f32_t, true, .f64_t)\n\t}\n\tm.commit(pyth, true)\n\tmut test := m.new_function('test', [.f32_t], [.f64_t])\n\t{\n\t\ttest.local_get(0)\n\t\ttest.f32_const(10.0)\n\t\ttest.call('pythagoras')\n\t\ttest.cast(.f32_t, true, .f64_t)\n\t}\n\tm.commit(test, true)\n\tprint(m.compile().bytestr())\n}\n"
  },
  {
    "path": "examples/wasm_codegen/hello_wasi.v",
    "content": "import wasm\n\nfn main() {\n\tmut m := wasm.Module{}\n\tm.enable_debug('vlang')\n\tm.new_function_import('wasi_unstable', 'proc_exit', [.i32_t], [])\n\tm.new_function_import('wasi_unstable', 'fd_write', [.i32_t, .i32_t, .i32_t, .i32_t],\n\t\t[.i32_t])\n\tm.assign_memory('memory', true, 1, none)\n\n\tm.new_data_segment('CIOVec.str', 0, [u8(8), 0, 0, 0]) // pointer to string\n\tm.new_data_segment('CIOVec.len', 4, [u8(13), 0, 0, 0]) // length of string\n\tm.new_data_segment(none, 8, 'Hello, WASI!\\n'.bytes())\n\n\tmut func := m.new_function('_start', [], [])\n\t{\n\t\tfunc.i32_const(1) // stdout\n\t\tfunc.i32_const(0) // *iovs\n\t\tfunc.i32_const(1) // 1 iov\n\t\tfunc.i32_const(-1) // *retptrs\n\t\tfunc.call_import('wasi_unstable', 'fd_write')\n\t\tfunc.drop()\n\t\tfunc.i32_const(0)\n\t\tfunc.call_import('wasi_unstable', 'proc_exit')\n\t}\n\tm.commit(func, true)\n\n\tprint(m.compile().bytestr())\n}\n"
  },
  {
    "path": "examples/wasm_codegen/memory.v",
    "content": "import wasm\n\nfn main() {\n\tmut m := wasm.Module{}\n\tmut mtest := m.new_function('mload', [.i32_t], [.i32_t])\n\t{\n\t\tmtest.local_get(0)\n\t\tmtest.load(.i32_t, 2, 0)\n\t}\n\tm.commit(mtest, false)\n\tprint(m.compile().bytestr())\n}\n"
  },
  {
    "path": "examples/web_crawler/README.md",
    "content": "# web_crawler\nThis simple web crawler fetches news from the homepage of HN (https://news.ycombinator.com/).\n\n# Compile and Run\n\nUse this to generate an executable, and then launch the web crawler:\n```bash\nv web_crawler.v\n./web_crawler\n```\n\nAnd this to compile and launch the web crawler directly:\n```bash\nv run web_crawler.v\n```\n\nThis project shows how to use http.fetch() to get http.Response, \nand then html.parse() to parse the returned html.\n\nIt's easy, isn't it?\n"
  },
  {
    "path": "examples/web_crawler/web_crawler.v",
    "content": "import net.http\nimport net.html\n\nfn main() {\n\tsite_url := 'https://news.ycombinator.com'\n\tresp := http.fetch(\n\t\turl:        site_url\n\t\tuser_agent: 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0'\n\t)!\n\tmut doc := html.parse(resp.body)\n\ttags := doc.get_tags_by_attribute_value('class', 'titleline')\n\tfor i, tag in tags {\n\t\tel := tag.children[0]\n\t\tmut href := el.attributes['href']!\n\t\tif !href.starts_with('http') {\n\t\t\thref = '${site_url}/${href}'\n\t\t}\n\t\ttitle := el.content\n\t\tprintln('${i + 1:2}. title: ${title:-90s} href: ${href}')\n\t}\n}\n"
  },
  {
    "path": "examples/websocket/client-server/client.v",
    "content": "// vtest build: present_openssl?\nmodule main\n\nimport os\nimport net.websocket\nimport term\n\n// This client should be compiled an run in different consoles\n// it connects to the server who will broadcast your messages\n// to all other connected clients\nfn main() {\n\tmut ws := start_client()!\n\tdefer {\n\t\tunsafe {\n\t\t\tws.free()\n\t\t}\n\t}\n\tprintln(term.green('client ${ws.id} ready'))\n\tprintln('Write message and enter to send...')\n\tfor {\n\t\tline := os.get_line()\n\t\tif line == '' {\n\t\t\tbreak\n\t\t}\n\t\tws.write_string(line)!\n\t}\n\tws.close(1000, 'normal') or {\n\t\teprintln(term.red('ws.close err: ${err}'))\n\t\texit(1)\n\t}\n}\n\nfn start_client() !&websocket.Client {\n\tmut ws := websocket.new_client('ws://localhost:30000')!\n\t// mut ws := websocket.new_client('wss://echo.websocket.org:443')?\n\t// use on_open_ref if you want to send any reference object\n\tws.on_open(fn (mut ws websocket.Client) ! {\n\t\tprintln(term.green('ws.on_open websocket connected to the server and ready to send messages...'))\n\t})\n\t// use on_error_ref if you want to send any reference object\n\tws.on_error(fn (mut ws websocket.Client, err string) ! {\n\t\tprintln(term.red('ws.on_error error: ${err}'))\n\t})\n\t// use on_close_ref if you want to send any reference object\n\tws.on_close(fn (mut ws websocket.Client, code int, reason string) ! {\n\t\tprintln(term.green('ws.on_close the connection to the server successfully closed'))\n\t})\n\t// on new messages from other clients, display them in blue text\n\tws.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ! {\n\t\tif msg.payload.len > 0 {\n\t\t\tmessage := msg.payload.bytestr()\n\t\t\tprintln(term.blue('ws.on_message `${message}`'))\n\t\t}\n\t})\n\n\tws.connect() or {\n\t\teprintln(term.red('ws.connect error: ${err}'))\n\t\treturn err\n\t}\n\n\tspawn ws.listen() // or { println(term.red('error on listen ${err}')) }\n\treturn ws\n}\n"
  },
  {
    "path": "examples/websocket/client-server/server.v",
    "content": "// vtest build: present_openssl?\nmodule main\n\nimport net.websocket\nimport term\n\nfn slog(message string) {\n\teprintln(term.colorize(term.bright_yellow, message))\n}\n\n// this server accepts client connections and broadcast all messages to other connected clients\nfn main() {\n\teprintln('press ctrl-c to quit...')\n\tstart_server()!\n}\n\nfn start_server() ! {\n\tslog('start_server')\n\tmut s := websocket.new_server(.ip6, 30000, '')\n\tdefer {\n\t\tunsafe {\n\t\t\ts.free()\n\t\t}\n\t}\n\t// Make that in execution test time give time to execute at least one time\n\ts.set_ping_interval(100)\n\ts.on_connect(fn (mut s websocket.ServerClient) !bool {\n\t\tslog('s.on_connect')\n\t\t// Here you can look att the client info and accept or not accept\n\t\t// just returning a true/false\n\t\tif s.resource_name != '/' {\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})!\n\n\t// on_message_ref, broadcast all incoming messages to all clients except the one sent it\n\ts.on_message_ref(fn (mut ws websocket.Client, msg &websocket.Message, mut m websocket.Server) ! {\n\t\tslog('s.on_message_ref')\n\t\t// for _, cli in m.clients {\n\t\tfor i, _ in rlock m.server_state {\n\t\t\tm.server_state.clients\n\t\t} {\n\t\t\tmut c := rlock m.server_state {\n\t\t\t\tm.server_state.clients[i] or { continue }\n\t\t\t}\n\t\t\tif c.client.get_state() == .open && c.client.id != ws.id {\n\t\t\t\tc.client.write(msg.payload, websocket.OPCode.text_frame) or { panic(err) }\n\t\t\t}\n\t\t}\n\t}, s)\n\n\ts.on_close(fn (mut ws websocket.Client, code int, reason string) ! {\n\t\tslog('s.on_close')\n\t\tprintln(term.green('client (${ws.id}) closed connection'))\n\t})\n\n\ts.listen() or { println(term.red('error on server listen: ${err}')) }\n\tslog('s.listen done')\n}\n"
  },
  {
    "path": "examples/websocket/ping.v",
    "content": "// vtest build: present_openssl?\nmodule main\n\nimport time\nimport term\nimport net.websocket\n\nfn main() {\n\tspawn start_server()\n\ttime.sleep(100 * time.millisecond)\n\tstart_client()!\n}\n\nfn slog(message string) {\n\teprintln(term.colorize(term.bright_yellow, message))\n}\n\nfn clog(message string) {\n\teprintln(term.colorize(term.cyan, message))\n}\n\nfn wlog(message string) {\n\teprintln(term.colorize(term.bright_blue, message))\n}\n\n// start_server starts the websocket server, it receives messages\n// and send it back to the client that sent it\nfn start_server() ! {\n\tmut s := websocket.new_server(.ip6, 30000, '')\n\tdefer {\n\t\tunsafe {\n\t\t\ts.free()\n\t\t}\n\t}\n\t// Make that in execution test time give time to execute at least one time\n\ts.set_ping_interval(100)\n\ts.on_connect(fn (mut s websocket.ServerClient) !bool {\n\t\tslog('ws.on_connect, s.client_key: ${s.client_key}')\n\t\t// Here you can look att the client info and accept or not accept\n\t\t// just returning a true/false\n\t\tif s.resource_name != '/' {\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})!\n\ts.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ! {\n\t\tslog('s.on_message msg.opcode: ${msg.opcode} | msg.payload: ${msg.payload}')\n\t\tws.write(msg.payload, msg.opcode) or {\n\t\t\teprintln('ws.write err: ${err}')\n\t\t\treturn err\n\t\t}\n\t})\n\ts.on_close(fn (mut ws websocket.Client, code int, reason string) ! {\n\t\tslog('s.on_close code: ${code}, reason: ${reason}')\n\t\t// println('client (${ws.id}) closed connection')\n\t})\n\ts.listen() or {\n\t\tslog('s.listen err: ${err}')\n\t\treturn err\n\t}\n\tslog('s.listen finished')\n}\n\n// start_client starts the websocket client, it writes a message to\n// the server and prints all the messages received\nfn start_client() ! {\n\tmut ws := websocket.new_client('ws://localhost:30000')!\n\tdefer {\n\t\tunsafe {\n\t\t\tws.free()\n\t\t}\n\t}\n\t// mut ws := websocket.new_client('wss://echo.websocket.org:443')?\n\t// use on_open_ref if you want to send any reference object\n\tws.on_open(fn (mut ws websocket.Client) ! {\n\t\tclog('ws.on_open')\n\t})\n\t// use on_error_ref if you want to send any reference object\n\tws.on_error(fn (mut ws websocket.Client, err string) ! {\n\t\tclog('ws.on_error error: ${err}')\n\t})\n\t// use on_close_ref if you want to send any reference object\n\tws.on_close(fn (mut ws websocket.Client, code int, reason string) ! {\n\t\tclog('ws.on_close')\n\t})\n\t// use on_message_ref if you want to send any reference object\n\tws.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ! {\n\t\tif msg.payload.len > 0 {\n\t\t\tmessage := msg.payload.bytestr()\n\t\t\tclog('ws.on_message client got type: ${msg.opcode} payload: `${message}`')\n\t\t}\n\t})\n\t// you can add any pointer reference to use in callback\n\t// t := TestRef{count: 10}\n\t// ws.on_message_ref(fn (mut ws websocket.Client, msg &websocket.Message, r &SomeRef) ? {\n\t// // eprintln('type: ${msg.opcode} payload:\\n${msg.payload} ref: ${r}')\n\t// }, &r)\n\tws.connect() or {\n\t\tclog('ws.connect err: ${err}')\n\t\treturn err\n\t}\n\tclog('ws.connect succeeded')\n\tspawn write_echo(mut ws) // or { println('error on write_echo ${err}') }\n\tws.listen() or {\n\t\tclog('ws.listen err: ${err}')\n\t\treturn err\n\t}\n\tclog('ws.listen finished')\n}\n\nfn write_echo(mut ws websocket.Client) ! {\n\twlog('write_echo, start')\n\tmessage := 'echo this'\n\tfor i := 0; i <= 5; i++ {\n\t\t// Server will send pings every 30 seconds\n\t\twlog('write_echo, writing message: `${message}` ...')\n\t\tws.write_string(message) or {\n\t\t\twlog('write_echo, ws.write_string err: ${err}')\n\t\t\treturn err\n\t\t}\n\t\ttime.sleep(100 * time.millisecond)\n\t}\n\tws.close(1000, 'normal') or {\n\t\twlog('write_echo, close err: ${err}')\n\t\treturn err\n\t}\n\twlog('write_echo, done')\n}\n"
  },
  {
    "path": "examples/word_counter/README.md",
    "content": "```\nusage: word_counter [text_file]\nusing cinderella.txt\na => 25\nable => 2\nafter => 1\nafterwards => 1\nagain => 10\nagainst => 2\nall => 12\nallow => 1\nallowed => 2\nalong => 1\nalso => 2\nalways => 2\nan => 4\nand => 140\nanew => 1\nanger => 1\nanother => 2\nanswered => 1\nany => 1\nanyone => 2\n...\n```\n"
  },
  {
    "path": "examples/word_counter/cinderella.txt",
    "content": "A rich man's wife became sick, and when she felt that her end was drawing near,\nshe called her only daughter to her bedside and said, \"Dear child, remain pious\nand good, and then our dear God will always protect you, and I will look down\non you from heaven and be near you.\" With this she closed her eyes and died.\n\nThe girl went out to her mother's grave every day and wept, and she remained\npious and good. When winter came the snow spread a white cloth over the grave,\nand when the spring sun had removed it again, the man took himself another\nwife.\n\nThis wife brought two daughters into the house with her. They were beautiful,\nwith fair faces, but evil and dark hearts. Times soon grew very bad for the\npoor stepchild.\n\n\"Why should that stupid goose sit in the parlor with us?\" they said. \"If she\nwants to eat bread, then she will have to earn it. Out with this kitchen maid!\"\n\nThey took her beautiful clothes away from her, dressed her in an old gray\nsmock, and gave her wooden shoes. \"Just look at the proud princess! How decked\nout she is!\" they shouted and laughed as they led her into the kitchen.\n\nThere she had to do hard work from morning until evening, get up before\ndaybreak, carry water, make the fires, cook, and wash. Besides this, the\nsisters did everything imaginable to hurt her. They made fun of her, scattered\npeas and lentils into the ashes for her, so that she had to sit and pick them\nout again. In the evening when she had worked herself weary, there was no bed\nfor her. Instead she had to sleep by the hearth in the ashes. And because she\nalways looked dusty and dirty, they called her Cinderella.\n\nOne day it happened that the father was going to the fair, and he asked his two\nstepdaughters what he should bring back for them.\n\n\"Beautiful dresses,\" said the one.\n\n\"Pearls and jewels,\" said the other.\n\n\"And you, Cinderella,\" he said, \"what do you want?\"\n\n\"Father, break off for me the first twig that brushes against your hat on your\nway home.\"\n\nSo he bought beautiful dresses, pearls, and jewels for his two stepdaughters.\nOn his way home, as he was riding through a green thicket, a hazel twig brushed\nagainst him and knocked off his hat. Then he broke off the twig and took it\nwith him. Arriving home, he gave his stepdaughters the things that they had\nasked for, and he gave Cinderella the twig from the hazel bush.\n\nCinderella thanked him, went to her mother's grave, and planted the branch on\nit, and she wept so much that her tears fell upon it and watered it. It grew\nand became a beautiful tree.\n\nCinderella went to this tree three times every day, and beneath it she wept and\nprayed. A white bird came to the tree every time, and whenever she expressed a\nwish, the bird would throw down to her what she had wished for.\n\nNow it happened that the king proclaimed a festival that was to last three\ndays. All the beautiful young girls in the land were invited, so that his son\ncould select a bride for himself. When the two stepsisters heard that they too\nhad been invited, they were in high spirits.\n\nThey called Cinderella, saying, \"Comb our hair for us. Brush our shoes and\nfasten our buckles. We are going to the festival at the king's castle.\"\n\nCinderella obeyed, but wept, because she too would have liked to go to the\ndance with them. She begged her stepmother to allow her to go.\n\n\"You, Cinderella?\" she said. \"You, all covered with dust and dirt, and you want\nto go to the festival?. You have neither clothes nor shoes, and yet you want to\ndance!\"\n\nHowever, because Cinderella kept asking, the stepmother finally said, \"I have\nscattered a bowl of lentils into the ashes for you. If you can pick them out\nagain in two hours, then you may go with us.\"\n\nThe girl went through the back door into the garden, and called out, \"You tame\npigeons, you turtledoves, and all you birds beneath the sky, come and help me\nto gather:\n\nThe good ones go into the pot, The bad ones go into your crop.\" Two white\npigeons came in through the kitchen window, and then the turtledoves, and\nfinally all the birds beneath the sky came whirring and swarming in, and lit\naround the ashes. The pigeons nodded their heads and began to pick, pick, pick,\npick. And the others also began to pick, pick, pick, pick. They gathered all\nthe good grains into the bowl. Hardly one hour had passed before they were\nfinished, and they all flew out again.  The girl took the bowl to her\nstepmother, and was happy, thinking that now she would be allowed to go to the\nfestival with them.\n\nBut the stepmother said, \"No, Cinderella, you have no clothes, and you don't\nknow how to dance. Everyone would only laugh at you.\"\n\nCinderella began to cry, and then the stepmother said, \"You may go if you are\nable to pick two bowls of lentils out of the ashes for me in one hour,\"\nthinking to herself, \"She will never be able to do that.\"\n\nThe girl went through the back door into the garden, and called out, \"You tame\npigeons, you turtledoves, and all you birds beneath the sky, come and help me\nto gather:\n\nThe good ones go into the pot, The bad ones go into your crop.\" Two white\npigeons came in through the kitchen window, and then the turtledoves, and\nfinally all the birds beneath the sky came whirring and swarming in, and lit\naround the ashes. The pigeons nodded their heads and began to pick, pick, pick,\npick. And the others also began to pick, pick, pick, pick. They gathered all\nthe good grains into the bowls. Before a half hour had passed they were\nfinished, and they all flew out again.  The girl took the bowls to her\nstepmother, and was happy, thinking that now she would be allowed to go to the\nfestival with them.\n\nBut the stepmother said, \"It's no use. You are not coming with us, for you have\nno clothes, and you don't know how to dance. We would be ashamed of you.\" With\nthis she turned her back on Cinderella, and hurried away with her two proud\ndaughters.\n\nNow that no one else was at home, Cinderella went to her mother's grave beneath\nthe hazel tree, and cried out:\n\nShake and quiver, little tree, Throw gold and silver down to me.  Then the bird\nthrew a gold and silver dress down to her, and slippers embroidered with silk\nand silver. She quickly put on the dress and went to the festival.  Her\nstepsisters and her stepmother did not recognize her. They thought she must be\na foreign princess, for she looked so beautiful in the golden dress. They never\nonce thought it was Cinderella, for they thought that she was sitting at home\nin the dirt, looking for lentils in the ashes.\n\nThe prince approached her, took her by the hand, and danced with her.\nFurthermore, he would dance with no one else. He never let go of her hand, and\nwhenever anyone else came and asked her to dance, he would say, \"She is my\ndance partner.\"\n\nShe danced until evening, and then she wanted to go home. But the prince said,\n\"I will go along and escort you,\" for he wanted to see to whom the beautiful\ngirl belonged. However, she eluded him and jumped into the pigeon coop. The\nprince waited until her father came, and then he told him that the unknown girl\nhad jumped into the pigeon coop.\n\nThe old man thought, \"Could it be Cinderella?\"\n\nHe had them bring him an ax and a pick so that he could break the pigeon coop\napart, but no one was inside. When they got home Cinderella was lying in the\nashes, dressed in her dirty clothes. A dim little oil-lamp was burning in the\nfireplace. Cinderella had quickly jumped down from the back of the pigeon coop\nand had run to the hazel tree. There she had taken off her beautiful clothes\nand laid them on the grave, and the bird had taken them away again. Then,\ndressed in her gray smock, she had returned to the ashes in the kitchen.\n\nThe next day when the festival began anew, and her parents and her stepsisters\nhad gone again, Cinderella went to the hazel tree and said:\n\nShake and quiver, little tree, Throw gold and silver down to me.  Then the bird\nthrew down an even more magnificent dress than on the preceding day. When\nCinderella appeared at the festival in this dress, everyone was astonished at\nher beauty. The prince had waited until she came, then immediately took her by\nthe hand, and danced only with her. When others came and asked her to dance\nwith them, he said, \"She is my dance partner.\" When evening came she wanted to\nleave, and the prince followed her, wanting to see into which house she went.\nBut she ran away from him and into the garden behind the house. A beautiful\ntall tree stood there, on which hung the most magnificent pears. She climbed as\nnimbly as a squirrel into the branches, and the prince did not know where she\nhad gone. He waited until her father came, then said to him, \"The unknown girl\nhas eluded me, and I believe she has climbed up the pear tree.\n\nThe father thought, \"Could it be Cinderella?\" He had an ax brought to him and\ncut down the tree, but no one was in it. When they came to the kitchen,\nCinderella was lying there in the ashes as usual, for she had jumped down from\nthe other side of the tree, had taken the beautiful dress back to the bird in\nthe hazel tree, and had put on her gray smock.\n\nOn the third day, when her parents and sisters had gone away, Cinderella went\nagain to her mother's grave and said to the tree:\n\nShake and quiver, little tree, Throw gold and silver down to me.  This time the\nbird threw down to her a dress that was more splendid and magnificent than any\nshe had yet had, and the slippers were of pure gold. When she arrived at the\nfestival in this dress, everyone was so astonished that they did not know what\nto say. The prince danced only with her, and whenever anyone else asked her to\ndance, he would say, \"She is my dance partner.\" When evening came Cinderella\nwanted to leave, and the prince tried to escort her, but she ran away from him\nso quickly that he could not follow her. The prince, however, had set a trap.\nHe had had the entire stairway smeared with pitch. When she ran down the\nstairs, her left slipper stuck in the pitch. The prince picked it up. It was\nsmall and dainty, and of pure gold.\n\nThe next morning, he went with it to the man, and said to him, \"No one shall be\nmy wife except for the one whose foot fits this golden shoe.\"\n\nThe two sisters were happy to hear this, for they had pretty feet. With her\nmother standing by, the older one took the shoe into her bedroom to try it on.\nShe could not get her big toe into it, for the shoe was too small for her. Then\nher mother gave her a knife and said, \"Cut off your toe. When you are queen you\nwill no longer have to go on foot.\"\n\nThe girl cut off her toe, forced her foot into the shoe, swallowed the pain,\nand went out to the prince. He took her on his horse as his bride and rode away\nwith her. However, they had to ride past the grave, and there, on the hazel\ntree, sat the two pigeons, crying out:\n\nRook di goo, rook di goo!  There's blood in the shoe.  The shoe is too tight,\nThis bride is not right!  Then he looked at her foot and saw how the blood was\nrunning from it. He turned his horse around and took the false bride home\nagain, saying that she was not the right one, and that the other sister should\ntry on the shoe. She went into her bedroom, and got her toes into the shoe all\nright, but her heel was too large.  Then her mother gave her a knife, and said,\n\"Cut a piece off your heel. When you are queen you will no longer have to go on\nfoot.\"\n\nThe girl cut a piece off her heel, forced her foot into the shoe, swallowed the\npain, and went out to the prince. He took her on his horse as his bride and\nrode away with her. When they passed the hazel tree, the two pigeons were\nsitting in it, and they cried out:\n\nRook di goo, rook di goo!  There's blood in the shoe.  The shoe is too tight,\nThis bride is not right!  He looked down at her foot and saw how the blood was\nrunning out of her shoe, and how it had stained her white stocking all red.\nThen he turned his horse around and took the false bride home again.  \"This is\nnot the right one, either,\" he said. \"Don't you have another daughter?\"\n\n\"No,\" said the man. \"There is only a deformed little Cinderella from my first\nwife, but she cannot possibly be the bride.\"\n\nThe prince told him to send her to him, but the mother answered, \"Oh, no, she\nis much too dirty. She cannot be seen.\"\n\nBut the prince insisted on it, and they had to call Cinderella. She first\nwashed her hands and face clean, and then went and bowed down before the\nprince, who gave her the golden shoe. She sat down on a stool, pulled her foot\nout of the heavy wooden shoe, and put it into the slipper, and it fitted her\nperfectly.\n\nWhen she stood up the prince looked into her face, and he recognized the\nbeautiful girl who had danced with him. He cried out, \"She is my true bride.\"\n\nThe stepmother and the two sisters were horrified and turned pale with anger.\nThe prince, however, took Cinderella onto his horse and rode away with her. As\nthey passed by the hazel tree, the two white pigeons cried out:\n\nRook di goo, rook di goo!  No blood's in the shoe.  The shoe's not too tight,\nThis bride is right!  After they had cried this out, they both flew down and\nlit on Cinderella's shoulders, one on the right, the other on the left, and\nremained sitting there.  When the wedding with the prince was to be held, the\ntwo false sisters came, wanting to gain favor with Cinderella and to share her\ngood fortune. When the bridal couple walked into the church, the older sister\nwalked on their right side and the younger on their left side, and the pigeons\npecked out one eye from each of them. Afterwards, as they came out of the\nchurch, the older one was on the left side, and the younger one on the right\nside, and then the pigeons pecked out the other eye from each of them. And\nthus, for their wickedness and falsehood, they were punished with blindness as\nlong as they lived.\n\n\n"
  },
  {
    "path": "examples/word_counter/word_counter.v",
    "content": "// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.\n// Use of this source code is governed by an MIT license\n// that can be found in the LICENSE file.\nimport os\n\nfn main() {\n\tmut path := 'cinderella.txt'\n\tif os.args.len != 2 {\n\t\tprintln('usage: word_counter [text_file]')\n\t\tprintln('using ${path}')\n\t} else {\n\t\tpath = os.args[1]\n\t}\n\tcontents := os.read_file(path.trim_space()) or {\n\t\tprintln('failed to open ${path}')\n\t\treturn\n\t}\n\tmut m := map[string]int{}\n\tfor word in extract_words(contents) {\n\t\tm[word]++\n\t}\n\t// Sort the keys\n\tmut keys := m.keys()\n\tkeys.sort()\n\t// Print the map\n\tfor key in keys {\n\t\tval := m[key]\n\t\tprintln('${key} => ${val}')\n\t}\n}\n\n// Creates an array of words from a given string\nfn extract_words(contents string) []string {\n\tmut splits := []string{}\n\tfor space_split in contents.to_lower().split(' ') {\n\t\tif space_split.contains('\\n') {\n\t\t\tsplits << space_split.split('\\n')\n\t\t} else {\n\t\t\tsplits << space_split\n\t\t}\n\t}\n\n\tmut results := []string{}\n\tfor s in splits {\n\t\tresult := filter_word(s)\n\t\tif result == '' {\n\t\t\tcontinue\n\t\t}\n\t\tresults << result\n\t}\n\n\treturn results\n}\n\n// Removes punctuation\nfn filter_word(word string) string {\n\tif word == '' || word == ' ' {\n\t\treturn ''\n\t}\n\tmut i := 0\n\tfor i < word.len && !word[i].is_letter() {\n\t\ti++\n\t}\n\tstart := i\n\tfor i < word.len && word[i].is_letter() {\n\t\ti++\n\t}\n\tend := i\n\treturn word[start..end]\n}\n"
  },
  {
    "path": "make.bat",
    "content": "@setlocal EnableDelayedExpansion EnableExtensions\r\n\r\n@IF NOT DEFINED VERBOSE_MAKE @echo off\r\n\r\nREM Option flags\r\nset /a shift_counter=0\r\nset /a flag_local=0\r\n\r\nREM Option variables\r\nset compiler=\r\nset subcmd=\r\nset target=build\r\n\r\nset V_EXE=./v.exe\r\nset V_BOOTSTRAP=./v_win_bootstrap.exe\r\nset V_OLD=./v_old.exe\r\nset V_UPDATED=./v_up.exe\r\nset V_C_FILE=./vc/v.c\r\nif not exist \"%V_C_FILE%\" set V_C_FILE=./vc/v_win.c\r\n\r\nREM TCC variables\r\nset tcc_url=https://github.com/vlang/tccbin\r\nset tcc_dir=%~dp0thirdparty\\tcc\r\nset tcc_exe=%tcc_dir%\\tcc.exe\r\nif \"%PROCESSOR_ARCHITECTURE%\" == \"x86\" ( set tcc_branch=\"thirdparty-windows-i386\" ) else ( set tcc_branch=\"thirdparty-windows-amd64\" )\r\nif \"%~1\" == \"-tcc32\" set tcc_branch=\"thirdparty-windows-i386\"\r\n\r\nREM VC settings\r\nset vc_url=https://github.com/vlang/vc\r\nset vc_dir=%~dp0vc\r\n\r\nREM Let a particular environment specify their own TCC and VC repos (to help mirrors)\r\nif /I not [\"%TCC_GIT%\"] == [\"\"] set tcc_url=%TCC_GIT%\r\nif /I not [\"%TCC_BRANCH%\"] == [\"\"] set tcc_branch=%TCC_BRANCH%\r\n\r\nif /I not [\"%VC_GIT%\"] == [\"\"] set vc_url=%VC_GIT%\r\n\r\npushd \"%~dp0\"\r\n\r\n:verifyopt\r\nREM Read stdin EOF\r\nif [\"%~1\"] == [\"\"] goto :init\r\n\r\nREM Target options\r\nif !shift_counter! LSS 1 (\r\n\tif \"%~1\" == \"help\" (\r\n\t\tif not [\"%~2\"] == [\"\"] set subcmd=%~2& shift& set /a shift_counter+=1\r\n\t)\r\n\tfor %%z in (build clean cleanall check help rebuild) do (\r\n\t\tif \"%~1\" == \"%%z\" set target=%1& shift& set /a shift_counter+=1& goto :verifyopt\r\n\t)\r\n)\r\n\r\nREM Compiler option\r\nfor %%g in (-gcc -msvc -tcc -tcc32 -clang) do (\r\n\tif \"%~1\" == \"%%g\" set compiler=%~1& set compiler=!compiler:~1!& shift& set /a shift_counter+=1& goto :verifyopt\r\n)\r\n\r\nREM Standard options\r\nif \"%~1\" == \"--local\" (\r\n\tif !flag_local! NEQ 0 (\r\n\t\techo The flag %~1 has already been specified. 1>&2\r\n\t\texit /b 2\r\n\t)\r\n\tset /a flag_local=1\r\n\tset /a shift_counter+=1\r\n\tshift\r\n\tgoto :verifyopt\r\n)\r\n\r\necho Undefined option: %~1\r\nexit /b 2\r\n\r\n:init\r\ngoto :!target!\r\n\r\n:check\r\necho.\r\necho Check everything\r\n\"%V_EXE%\" test-all\r\nexit /b 0\r\n\r\n:cleanall\r\ncall :clean\r\nif %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL%\r\necho.\r\necho Cleanup vc\r\necho  ^> Purge TCC binaries\r\nrmdir /s /q \"%tcc_dir%\"\r\necho  ^> Purge vc repository\r\nrmdir /s /q \"%vc_dir%\"\r\nexit /b 0\r\n\r\n:clean\r\necho Cleanup build artifacts\r\necho  ^> Purge debug symbols\r\ndel *.pdb *.lib *.bak *.out *.ilk *.exp *.obj *.o *.a *.so\r\n\r\necho  ^> Delete old V executable(s)\r\ndel v*.exe\r\nexit /b 0\r\n\r\n:rebuild\r\ncall :cleanall\r\ngoto :build\r\n\r\n:help\r\nif [!subcmd!] == [] (\r\n\tcall :usage\r\n) else (\r\n\tcall :help_!subcmd!\r\n)\r\nif %ERRORLEVEL% NEQ 0 echo Invalid subcommand: !subcmd!\r\nexit /b %ERRORLEVEL%\r\n\r\n:build\r\nif !flag_local! NEQ 1 (\r\n\tcall :download_tcc\r\n\tif %ERRORLEVEL% NEQ 0 goto :error\r\n\tif exist \"%vc_dir%\" (\r\n\t\tpushd \"%vc_dir%\" && (\r\n\t\t\techo Updating vc...\r\n\t\t\techo  ^> Sync with remote !vc_url!\r\n\t\t\tcd %vc_dir%\r\n\t\t\tgit pull --quiet\r\n\t\t\tcd ..\r\n\t\t\tpopd\r\n\t\t)\r\n\t) else (\r\n\t\tcall :cloning_vc\r\n\t)\r\n\techo.\r\n)\r\n\r\necho Building V...\r\nif not [!compiler!] == [] goto :!compiler!_strap\r\n\r\n\r\nREM By default, use tcc, since we have it prebuilt:\r\n:tcc_strap\r\n:tcc32_strap\r\necho  ^> Attempting to build \"%V_BOOTSTRAP%\" (from %V_C_FILE%) with \"!tcc_exe!\"\r\n\"!tcc_exe!\" -B\"%tcc_dir%\" -bt10 -g -w -o \"%V_BOOTSTRAP%\" \"%V_C_FILE%\" -ladvapi32 -lws2_32\r\nif %ERRORLEVEL% NEQ 0 goto :compile_error\r\necho  ^> Compiling \"%V_EXE%\" with \"%V_BOOTSTRAP%\"\r\nREM Keep the TCC root relative here; V forwards -cflags through a response file.\r\nREM An absolute -B path breaks there when the checkout path contains spaces.\r\n\"%V_BOOTSTRAP%\" -keepc -g -showcc -cc \"!tcc_exe!\" -cflags -Bthirdparty/tcc -o \"%V_UPDATED%\" cmd/v\r\nif %ERRORLEVEL% NEQ 0 goto :clang_strap\r\ncall :move_updated_to_v\r\ngoto :success\r\n\r\n:clang_strap\r\nwhere /q clang\r\nif %ERRORLEVEL% NEQ 0 (\r\n\techo  ^> Clang not found\r\n\tif not [!compiler!] == [] goto :error\r\n\tgoto :gcc_strap\r\n)\r\n\r\necho  ^> Attempting to build \"%V_BOOTSTRAP%\" (from %V_C_FILE%) with Clang\r\nclang -std=c99 -municode -g -w -o \"%V_BOOTSTRAP%\" \"%V_C_FILE%\" -ladvapi32 -lws2_32\r\nif %ERRORLEVEL% NEQ 0 (\r\n\techo In most cases, compile errors happen because the version of Clang installed is too old\r\n\tclang --version\r\n\tgoto :compile_error\r\n)\r\n\r\necho  ^> Compiling \"%V_EXE%\" with \"%V_BOOTSTRAP%\"\r\n\"%V_BOOTSTRAP%\" -keepc -g -showcc -cc clang -o \"%V_UPDATED%\" cmd/v\r\nif %ERRORLEVEL% NEQ 0 goto :compile_error\r\ncall :move_updated_to_v\r\ngoto :success\r\n\r\n:gcc_strap\r\nwhere /q gcc\r\nif %ERRORLEVEL% NEQ 0 (\r\n\techo  ^> GCC not found\r\n\tif not [!compiler!] == [] goto :error\r\n\tgoto :msvc_strap\r\n)\r\n\r\necho  ^> Attempting to build \"%V_BOOTSTRAP%\" (from %V_C_FILE%) with GCC\r\ngcc -std=c99 -municode -g -w -o \"%V_BOOTSTRAP%\" \"%V_C_FILE%\" -ladvapi32 -lws2_32\r\nif %ERRORLEVEL% NEQ 0 (\r\n\techo In most cases, compile errors happen because the version of GCC installed is too old\r\n\tgcc --version\r\n\tgoto :compile_error\r\n)\r\n\r\necho  ^> Compiling \"%V_EXE%\" with \"%V_BOOTSTRAP%\"\r\n\"%V_BOOTSTRAP%\" -keepc -g -showcc -cc gcc -o \"%V_UPDATED%\" cmd/v\r\nif %ERRORLEVEL% NEQ 0 goto :compile_error\r\ncall :move_updated_to_v\r\ngoto :success\r\n\r\n:msvc_strap\r\nset VsWhereDir=%ProgramFiles(x86)%\r\nset HostArch=x64\r\nif \"%PROCESSOR_ARCHITECTURE%\" == \"x86\" (\r\n\techo Using x86 Build Tools...\r\n\tset VsWhereDir=%ProgramFiles%\r\n\tset HostArch=x86\r\n)\r\n\r\nif not exist \"%VsWhereDir%/Microsoft Visual Studio/Installer/vswhere.exe\" (\r\n\techo  ^> MSVC not found\r\n\tif not [!compiler!] == [] goto :error\r\n\tgoto :compile_error\r\n)\r\n\r\nfor /f \"usebackq tokens=*\" %%i in (`\"%VsWhereDir%/Microsoft Visual Studio/Installer/vswhere.exe\" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do (\r\n\tset InstallDir=%%i\r\n)\r\n\r\nif exist \"%InstallDir%/Common7/Tools/vsdevcmd.bat\" (\r\n\tcall \"%InstallDir%/Common7/Tools/vsdevcmd.bat\" -arch=%HostArch% -host_arch=%HostArch% -no_logo\r\n) else if exist \"%VsWhereDir%/Microsoft Visual Studio 14.0/Common7/Tools/vsdevcmd.bat\" (\r\n\tcall \"%VsWhereDir%/Microsoft Visual Studio 14.0/Common7/Tools/vsdevcmd.bat\" -arch=%HostArch% -host_arch=%HostArch% -no_logo\r\n)\r\n\r\nset ObjFile=.v.c.obj\r\n\r\nif not exist \"%tcc_exe%\" call :download_tcc\r\nif exist \"%tcc_exe%\" (\r\n\techo  ^> Bootstrapping \"%V_BOOTSTRAP%\" from %V_C_FILE% with \"!tcc_exe!\" before compiling \"%V_EXE%\" with MSVC\r\n\t\"!tcc_exe!\" -B\"%tcc_dir%\" -bt10 -g -w -o \"%V_BOOTSTRAP%\" \"%V_C_FILE%\" -ladvapi32 -lws2_32\r\n\tif %ERRORLEVEL% NEQ 0 goto :compile_error\r\n) else (\r\n\techo  ^> Attempting to build \"%V_BOOTSTRAP%\" from %V_C_FILE% with MSVC\r\n\tcl.exe /volatile:ms /Fo%ObjFile% /W0 /MD /D_VBOOTSTRAP /F33554432 \"%V_C_FILE%\" user32.lib kernel32.lib advapi32.lib shell32.lib ws2_32.lib /link /nologo /out:\"%V_BOOTSTRAP%\" /incremental:no\r\n\tif %ERRORLEVEL% NEQ 0 (\r\n\t\techo In some cases, compile errors happen because of the MSVC compiler version\r\n\t\tcl.exe\r\n\t\tif exist %ObjFile% del %ObjFile%\r\n\t\tgoto :compile_error\r\n\t)\r\n)\r\n\r\necho  ^> Compiling \"%V_EXE%\" with \"%V_BOOTSTRAP%\"\r\n\"%V_BOOTSTRAP%\" -keepc -g -showcc -cc msvc -o \"%V_UPDATED%\" cmd/v\r\nif exist %ObjFile% del %ObjFile%\r\nif %ERRORLEVEL% NEQ 0 goto :compile_error\r\ncall :move_updated_to_v\r\ngoto :success\r\n\r\n:download_tcc\r\nif exist \"%tcc_dir%\" (\r\n\tpushd \"%tcc_dir%\" && (\r\n\t\techo Updating TCC\r\n\t\techo  ^> Syncing TCC from !tcc_url!\r\n\t\tgit pull --quiet\r\n\t\tpopd\r\n\t)\r\n) else (\r\n\tcall :bootstrap_tcc\r\n)\r\n\r\nif not exist \"%tcc_exe%\" echo  ^> TCC not found, even after cloning& goto :error\r\necho.\r\nexit /b 0\r\n\r\n:compile_error\r\necho.\r\necho Backend compiler error\r\ngoto :error\r\n\r\n:error\r\necho.\r\necho Exiting from error\r\necho ERROR: please follow the instructions in https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Windows\r\nexit /b 1\r\n\r\n:success\r\n\"%V_EXE%\" run cmd/tools/detect_tcc.v\r\necho  ^> V built successfully!\r\necho  ^> To add V to your PATH, run `%V_EXE% symlink`.\r\necho  ^> Note: Antivirus programs may sometimes tell you there is a virus in V (there aren't any).  They can also slow compilation by a considerable amount.  Consider adding exemptions for the V install directory as well as your V project folders.\r\n\r\n:version\r\necho.\r\necho | set /p=\"V version: \"\r\n\"%V_EXE%\" version\r\n\"%V_EXE%\" run .github/problem-matchers/register_all.vsh\r\ngoto :eof\r\n\r\n:usage\r\necho Usage:\r\necho     make.bat [target] [compiler] [options]\r\necho.\r\necho Compiler:\r\necho     -msvc ^| -gcc ^| -tcc ^| -tcc32 ^| -clang    Set C compiler\r\necho.\r\necho Target:\r\necho     build[default]    Compiles V using the given C compiler\r\necho     clean             Clean build artifacts and debugging symbols\r\necho     cleanall          Cleanup entire ALL build artifacts and vc repository\r\necho     check             Check that tests pass, and the repository is in a good shape for Pull Requests\r\necho     help              Display help for the given target\r\necho     rebuild           Fully clean/reset repository and rebuild V\r\necho.\r\necho Examples:\r\necho     make.bat -msvc\r\necho     make.bat -gcc --local\r\necho     make.bat build -tcc --local\r\necho     make.bat -tcc32\r\necho     make.bat help clean\r\necho.\r\necho Use \"make help <target>\" for more information about a target, for instance: \"make help clean\"\r\necho.\r\necho Note: Any undefined/unsupported options will be ignored\r\nexit /b 0\r\n\r\n:help_help\r\necho Usage:\r\necho     make.bat help [target]\r\necho.\r\necho Target:\r\necho     build ^| clean ^| cleanall ^| help    Query given target\r\nexit /b 0\r\n\r\n:help_clean\r\necho Usage:\r\necho     make.bat clean\r\necho.\r\nexit /b 0\r\n\r\n:help_cleanall\r\necho Usage:\r\necho     make.bat cleanall\r\necho.\r\nexit /b 0\r\n\r\n:help_build\r\necho Usage:\r\necho     make.bat build [compiler] [options]\r\necho.\r\necho Compiler:\r\necho     -msvc ^| -gcc ^| -tcc ^| -tcc32 ^| -clang    Set C compiler\r\necho.\r\necho Options:\r\necho    --local     Use the local vc repository without\r\necho                syncing with remote\r\nexit /b 0\r\n\r\n:help_rebuild\r\necho Usage:\r\necho     make.bat rebuild [compiler] [options]\r\necho.\r\necho Compiler:\r\necho     -msvc ^| -gcc ^| -tcc ^| -tcc32 ^| -clang    Set C compiler\r\necho.\r\necho Options:\r\necho    --local     Use the local vc repository without\r\necho                syncing with remote\r\nexit /b 0\r\n\r\n:bootstrap_tcc\r\necho Bootstrapping TCC...\r\necho  ^> TCC not found\r\nif \"!tcc_branch!\" == \"thirdparty-windows-i386\" ( echo  ^> Downloading TCC32 from !tcc_url! , branch !tcc_branch! ) else ( echo  ^> Downloading TCC64 from !tcc_url! , branch !tcc_branch! )\r\ngit clone --filter=blob:none --quiet --branch !tcc_branch! !tcc_url! \"%tcc_dir%\"\r\ngit --no-pager -C \"%tcc_dir%\" log -n3\r\nexit /b 0\r\n\r\n:cloning_vc\r\necho Cloning vc...\r\necho  ^> Cloning from remote !vc_url!\r\ngit clone --filter=blob:none --quiet \"%vc_url%\"\r\nexit /b 0\r\n\r\n:eof\r\npopd\r\nendlocal\r\nexit /b 0\r\n\r\n:move_updated_to_v\r\n@REM del \"%V_EXE%\" &:: breaks if `make.bat` is run from `v up` b/c of held file handle on `%V_EXE%`\r\nif exist \"%V_EXE%\" move \"%V_EXE%\" \"%V_OLD%\" >nul\r\nREM sleep for at most 100ms\r\nping 192.0.2.1 -n 1 -w 100 >nul\r\nmove \"%V_UPDATED%\" \"%V_EXE%\" >nul\r\nexit /b 0\r\n"
  },
  {
    "path": "thirdparty/.gitignore",
    "content": "!glfw/glfw3.dll\n!glfw/msvc/glfw3.lib\n\nfreetype/\nsdl2/\nSDL2_image/\nSDL2_mixer/\nSDL2_ttf/\npg/\ntcc/\nsqlite/\n"
  },
  {
    "path": "thirdparty/android/android.h",
    "content": "#if defined(__ANDROID__)\n\t#include <android/log.h>\n\n\t// Adapted from https://stackoverflow.com/a/196018/1904615\n\t#define V_ANDROID_LOG_STR_VALUE(arg) #arg\n\t#define V_ANDROID_LOG_NAME(tag_name) V_ANDROID_LOG_STR_VALUE(tag_name)\n\n\t#ifndef V_ANDROID_LOG_TAG\n\t\t#if defined(APPNAME)\n\t\t\t#define V_ANDROID_LOG_TAG APPNAME\n\t\t#else\n\t\t\t#define V_ANDROID_LOG_TAG \"V\"\n\t\t#endif\n\t#endif\n\n\t#define V_ANDROID_LOG_TAG_NAME V_ANDROID_LOG_NAME(V_ANDROID_LOG_TAG)\n\n\tint android_print(FILE *stream, const char *format, ...) {\n\t\t// int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap)\n\t\tint res;\n\t\tva_list argptr;\n\t\tva_start(argptr, format);\n\t\tif (stream == stdout) {\n\t\t\tres = __android_log_vprint(ANDROID_LOG_INFO, V_ANDROID_LOG_TAG_NAME, format, argptr);\n\t\t} else {\n\t\t\tres = __android_log_vprint(ANDROID_LOG_ERROR, V_ANDROID_LOG_TAG_NAME, format, argptr);\n\t\t}\n\t\treturn res;\n\t}\n#endif\n"
  },
  {
    "path": "thirdparty/build_scripts/README.md",
    "content": "This folder, contains build scripts used by the CI, to generate prebuilt versions\n(or latest version by default) of:\nA) TCC from https://repo.or.cz/tinycc.git/\nB) libgc from https://github.com/ivmai/bdwgc/\n\nIn time, if everything works fine, we can deprecate the older approach, keeping 2 *separate*\nbinary repos, tccbin/ and libgcbin/, with just pointers back to the build scripts here.\n\nNote: the previous approach (before 2024/08), used in https://github.com/vlang/tccbin/,\nwhere that separate repo contained both prebuilt binaries for tcc AND libgc.a,\nAND the separate scripts to generate them, in *separate branches*.\nIn contrast, this folder contains *all scripts in the same location, in the same branch*, just\nwith different names, thus making editing them all at the same time and in atomic commits,\nthat can be reviewed and tested separately in PRs on the CI *much easier*.\n\nWARNING: this is still experimental, and should not be used, except to ease testing on the CI.\n"
  },
  {
    "path": "thirdparty/build_scripts/thirdparty-freebsd-amd64_bdwgc.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nif ! test -f vlib/v/compiler_errors_test.v; then\n  echo \"this script should be run in V's main repo folder!\"\n  exit 1\nfi\n  \nexport CURRENT_SCRIPT_PATH=$(realpath \"$0\")\n\nexport CC=\"${CC:-gcc}\"\nexport TCC_FOLDER=\"${TCC_FOLDER:-thirdparty/tcc}\"\nexport LIBGC_COMMIT=\"${LIBGC_COMMIT:-master}\"\nmkdir -p $TCC_FOLDER/lib/\n\necho \"          CC: $CC\"\necho \"  TCC_FOLDER: $TCC_FOLDER\"\necho \"LIBGC_COMMIT: $LIBGC_COMMIT\"\necho ===============================================================\n\nrm -rf bdwgc/\n\npushd .\ngit clone https://github.com/ivmai/bdwgc\ncd bdwgc/\n\ngit checkout $LIBGC_COMMIT\nexport LIBGC_COMMIT_FULL_HASH=$(git rev-parse HEAD)\n\n./autogen.sh\n\nCC=$CC CFLAGS='-Os -mtune=generic -fPIC' LDFLAGS='-Os -fPIC' ./configure \\\n\t--disable-dependency-tracking \\\n\t--disable-docs \\\n\t--enable-handle-fork=yes \\\n\t--enable-rwlock \\\n\t--enable-threads=posix \\\n\t--enable-static \\\n\t--enable-shared=no \\\n\t--enable-parallel-mark \\\n\t--enable-single-obj-compilation \\\n\t--enable-gc-debug \\\n\t--with-libatomic-ops=yes \\\n\t--enable-sigrt-signals \\\n\t--enable-mmap\n\nmake\n\npopd\n\ncp bdwgc/.libs/libgc.a         $TCC_FOLDER/lib/libgc.a\n\ndate                         > $TCC_FOLDER/lib/libgc_build_on_date.txt\necho $LIBGC_COMMIT_FULL_HASH > $TCC_FOLDER/lib/libgc_build_source_hash.txt\nuname -a                     > $TCC_FOLDER/lib/libgc_build_machine_uname.txt\n\nls -la $TCC_FOLDER/lib/libgc.a\necho \"Done compiling libgc, at commit $LIBGC_COMMIT , full hash: $LIBGC_COMMIT_FULL_HASH . The static library is in $TCC_FOLDER/lib/libgc.a \"\n"
  },
  {
    "path": "thirdparty/build_scripts/thirdparty-freebsd-amd64_tcc.sh",
    "content": "## NOTE: this script does *not* use a shebang **deliberately**, in order to\n## access the same shell, to capture its own launching command with `fc`,\n## and to record it later in the new commit message in thirdpart/tcc.\n\n## WARNING: THE ORIGINAL OF THIS SCRIPT IS IN:\n## https://github.com/vlang/v/blob/master/thirdparty/build_scripts/thirdparty-freebsd-amd64_tcc.sh ,\n## I.E. IN THE MAIN V REPOSITORY. IF YOU NEED TO MAKE CHANGES, CHANGE THAT.\n##\n## THE `build.sh` FILE IN `vlang/tccbin` REPO IS A COPY, RECORDED AT THE TIME\n## OF REBUILDING, FOR EASIER/RELIABLE REPRODUCTION OF HISTORIC VERSIONS.\n## IT IS NOT INTENDED TO BE MODIFIED.\n\nBUILD_CMD=`fc -nl -0`\n## remove whitespaces before/after the actual command:\nBUILD_CMD=\"$(echo \"${BUILD_CMD}\" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')\"\n\nset -e\n\nif ! test -f vlib/v/compiler_errors_test.v; then\n  echo \"this script should be run in V's main repo folder!\"\n  exit 1\nfi\n\nexport CFLAGS='-O3'\nexport CURRENT_SCRIPT_PATH=$(realpath \"$0\")\n\nexport TCC_COMMIT=\"${TCC_COMMIT:-mob}\"\nexport TCC_FOLDER=\"${TCC_FOLDER:-thirdparty/tcc.$TCC_COMMIT}\"\nexport CC=\"${CC:-gcc}\"\n\necho \" BUILD_CMD: \\`$BUILD_CMD\\`\"\necho \"        CC: $CC\"\necho \"TCC_COMMIT: $TCC_COMMIT\"\necho \"TCC_FOLDER: \\`$TCC_FOLDER\\`\"\necho ===============================================================\n\nrm -rf tinycc/\nrm -rf thirdparty/tcc.original/\nrsync -a thirdparty/tcc/ thirdparty/tcc.original/\n## rm -rf $TCC_FOLDER\n\npushd .\n\ngit clone git://repo.or.cz/tinycc.git\n\ncd tinycc\n\ngit checkout $TCC_COMMIT\nexport TCC_COMMIT_FULL_HASH=$(git rev-parse HEAD)\n\n./configure \\\n            --prefix=$TCC_FOLDER \\\n            --bindir=$TCC_FOLDER \\\n            --crtprefix=$TCC_FOLDER/lib:/usr/lib:/usr/lib64 \\\n            --sysincludepaths=$TCC_FOLDER/lib/tcc/include:/usr/local/include:/usr/include \\\n            --libpaths=$TCC_FOLDER/lib/tcc:$TCC_FOLDER/lib:/usr/lib64:/usr/lib:/lib:/usr/local/lib \\\n            --cc=\"$CC\" \\\n            --extra-cflags=\"$CFLAGS\" \\\n\t    --config-backtrace=yes \\\n\t    --config-bcheck=yes \\\n            --debug\n\n##     --extra-ldflags=\"-L/usr/home/ec2-user/v/tinycc -ltcc\" \\\n\ngmake\ngmake install\n\npopd\n\nrsync -a --delete tinycc/$TCC_FOLDER/                 $TCC_FOLDER/\nrsync -a          thirdparty/tcc.original/.git/       $TCC_FOLDER/.git/\nrsync -a          thirdparty/tcc.original/lib/libgc*  $TCC_FOLDER/lib/\nrsync -a          thirdparty/tcc.original/lib/build*  $TCC_FOLDER/lib/\nrsync -a          thirdparty/tcc.original/README.md   $TCC_FOLDER/README.md\nrsync -a          $CURRENT_SCRIPT_PATH                $TCC_FOLDER/build.sh\nmv                $TCC_FOLDER/tcc                     $TCC_FOLDER/tcc.exe\n\ndate                                                > $TCC_FOLDER/build_on_date.txt\necho $TCC_COMMIT_FULL_HASH                          > $TCC_FOLDER/build_source_hash.txt\n$TCC_FOLDER/tcc.exe --version                       > $TCC_FOLDER/build_version.txt\nuname -a                                            > $TCC_FOLDER/build_machine_uname.txt\n\n## show the builtin search paths for sanity checking:\n$TCC_FOLDER/tcc.exe -v -v\n\npushd .\ncd $TCC_FOLDER\ngit add .\ngit commit -m \"build with \\`$BUILD_CMD\\`\"\npopd\n\necho \"tcc commit: $TCC_COMMIT , full hash: $TCC_COMMIT_FULL_HASH .\"\necho \"The tcc executable is ready in $TCC_FOLDER/tcc.exe\"\n\n"
  },
  {
    "path": "thirdparty/build_scripts/thirdparty-linux-amd64_bdwgc.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nif ! test -f vlib/v/compiler_errors_test.v; then\n  echo \"this script should be run in V's main repo folder!\"\n  exit 1\nfi\n  \nexport CURRENT_SCRIPT_PATH=$(realpath \"$0\")\n\nexport CC=\"${CC:-gcc}\"\nexport TCC_FOLDER=\"${TCC_FOLDER:-thirdparty/tcc}\"\nexport LIBGC_COMMIT=\"${LIBGC_COMMIT:-master}\"\nmkdir -p $TCC_FOLDER/lib/\n\necho \"          CC: $CC\"\necho \"  TCC_FOLDER: $TCC_FOLDER\"\necho \"LIBGC_COMMIT: $LIBGC_COMMIT\"\necho ===============================================================\n\nrm -rf bdwgc/\n\npushd .\ngit clone https://github.com/ivmai/bdwgc\ncd bdwgc/\n\ngit checkout $LIBGC_COMMIT\nexport LIBGC_COMMIT_FULL_HASH=$(git rev-parse HEAD)\n\n./autogen.sh\n\nCC=$CC CFLAGS='-Os -mtune=generic -fPIC' LDFLAGS='-Os -fPIC' ./configure \\\n\t--disable-dependency-tracking \\\n\t--disable-docs \\\n\t--enable-handle-fork=yes \\\n\t--enable-rwlock \\\n\t--enable-threads=pthreads \\\n\t--enable-static \\\n\t--enable-shared=no \\\n\t--enable-parallel-mark \\\n\t--enable-single-obj-compilation \\\n\t--enable-gc-debug \\\n\t--with-libatomic-ops=yes \\\n\t--enable-sigrt-signals\n\nmake\n\npopd\n\ncp bdwgc/.libs/libgc.a         $TCC_FOLDER/lib/libgc.a\n\ndate                         > $TCC_FOLDER/lib/libgc_build_on_date.txt\necho $LIBGC_COMMIT_FULL_HASH > $TCC_FOLDER/lib/libgc_build_source_hash.txt\nuname -a                     > $TCC_FOLDER/lib/libgc_build_machine_uname.txt\n\nls -la $TCC_FOLDER/lib/libgc.a\necho \"Done compiling libgc, at commit $LIBGC_COMMIT , full hash: $LIBGC_COMMIT_FULL_HASH . The static library is in $TCC_FOLDER/lib/libgc.a \"\n"
  },
  {
    "path": "thirdparty/build_scripts/thirdparty-linux-amd64_tcc.sh",
    "content": "## NOTE: this script does *not* use a shebang **deliberately**, in order to\n## access the same shell, to capture its own launching command with `fc`,\n## and to record it later in the new commit message in thirdpart/tcc.\n\n## WARNING: THE ORIGINAL OF THIS SCRIPT IS IN:\n## https://github.com/vlang/v/blob/master/thirdparty/build_scripts/thirdparty-linux-amd64_tcc.sh ,\n## I.E. IN THE MAIN V REPOSITORY. IF YOU NEED TO MAKE CHANGES, CHANGE THAT.\n##\n## THE `build.sh` FILE IN `vlang/tccbin` REPO IS A COPY, RECORDED AT THE TIME\n## OF REBUILDING, FOR EASIER/RELIABLE REPRODUCTION OF HISTORIC VERSIONS.\n## IT IS NOT INTENDED TO BE MODIFIED.\n\nBUILD_CMD=`fc -nl -0`\n## remove whitespaces before/after the actual command:\nBUILD_CMD=\"$(echo \"${BUILD_CMD}\" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')\"\n\nset -e\n\nif ! test -f vlib/v/compiler_errors_test.v; then\n  echo \"this script should be run in V's main repo folder!\"\n  exit 1\nfi\n\nexport CURRENT_SCRIPT_PATH=$(realpath \"$0\")\n\nexport TCC_COMMIT=\"${TCC_COMMIT:-mob}\"\nexport TCC_FOLDER=\"${TCC_FOLDER:-thirdparty/tcc.$TCC_COMMIT}\"\nexport CC=\"${CC:-gcc}\"\n\necho \" BUILD_CMD: \\`$BUILD_CMD\\`\"\necho \"        CC: $CC\"\necho \"TCC_COMMIT: $TCC_COMMIT\"\necho \"TCC_FOLDER: \\`$TCC_FOLDER\\`\"\necho ===============================================================\n\nrm -rf tinycc/\nrm -rf thirdparty/tcc.original/\nrsync -a thirdparty/tcc/ thirdparty/tcc.original/\n## rm -rf $TCC_FOLDER\n\npushd .\n\ngit clone git://repo.or.cz/tinycc.git\n\ncd tinycc\n\ngit checkout $TCC_COMMIT\nexport TCC_COMMIT_FULL_HASH=$(git rev-parse HEAD)\n\n## Note: crt1.o is located in:\n## /usr/lib/x86_64-linux-gnu on Debian/Ubuntu\n## /usr/lib64 on Redhat/CentOS\n## /usr/lib on ArchLinux\n\n./configure \\\n            --prefix=$TCC_FOLDER \\\n            --bindir=$TCC_FOLDER \\\n            --crtprefix=$TCC_FOLDER/lib:/usr/lib/x86_64-linux-gnu:/usr/lib64:/usr/lib:/lib/x86_64-linux-gnu:/lib \\\n            --libpaths=$TCC_FOLDER/lib/tcc:$TCC_FOLDER/lib:/usr/lib/x86_64-linux-gnu:/usr/lib64:/usr/lib:/lib/x86_64-linux-gnu:/lib:/usr/local/lib/x86_64-linux-gnu:/usr/local/lib \\\n            --cc=$CC \\\n            --extra-cflags=-O3 \\\n            --config-bcheck=yes \\\n            --config-backtrace=yes \\\n            --debug\n\nmake\nmake install\n\npopd\n\nrsync -a --delete tinycc/$TCC_FOLDER/                 $TCC_FOLDER/\nrsync -a          thirdparty/tcc.original/.git/       $TCC_FOLDER/.git/\nrsync -a          thirdparty/tcc.original/lib/libgc*  $TCC_FOLDER/lib/\nrsync -a          thirdparty/tcc.original/lib/build*  $TCC_FOLDER/lib/\nrsync -a          thirdparty/tcc.original/README.md   $TCC_FOLDER/README.md\nrsync -a          $CURRENT_SCRIPT_PATH                $TCC_FOLDER/build.sh\nmv                $TCC_FOLDER/tcc                     $TCC_FOLDER/tcc.exe\n\ndate                                                > $TCC_FOLDER/build_on_date.txt\necho $TCC_COMMIT_FULL_HASH                          > $TCC_FOLDER/build_source_hash.txt\n$TCC_FOLDER/tcc.exe --version                       > $TCC_FOLDER/build_version.txt\nuname -a                                            > $TCC_FOLDER/build_machine_uname.txt\n\n## show the builtin search paths for sanity checking:\n$TCC_FOLDER/tcc.exe -v -v\n\npushd .\ncd $TCC_FOLDER\ngit add .\ngit commit -m \"build with \\`$BUILD_CMD\\`\"\npopd\n\necho \"tcc commit: $TCC_COMMIT , full hash: $TCC_COMMIT_FULL_HASH . The tcc executable is ready in $TCC_FOLDER/tcc.exe \"\n\n"
  },
  {
    "path": "thirdparty/build_scripts/thirdparty-linux-armv7_bdwgc.sh",
    "content": "#!/usr/bin/env bash\n\n# NOTE: The configure step may require:\n# sudo apt-get install libatomic-ops-dev\n\nset -e\n\nif ! test -f vlib/v/compiler_errors_test.v; then\n  echo \"this script should be run in V's main repo folder!\"\n  exit 1\nfi\n\nexport CURRENT_SCRIPT_PATH=$(realpath \"$0\")\n\nexport CC=\"${CC:-gcc}\"\nexport TCC_FOLDER=\"${TCC_FOLDER:-thirdparty/tcc}\"\nexport LIBGC_COMMIT=\"${LIBGC_COMMIT:-master}\"\nmkdir -p $TCC_FOLDER/lib/\n\necho \"          CC: $CC\"\necho \"  TCC_FOLDER: $TCC_FOLDER\"\necho \"LIBGC_COMMIT: $LIBGC_COMMIT\"\necho ===============================================================\n\nrm -rf bdwgc/\n\npushd .\ngit clone https://github.com/ivmai/bdwgc\ncd bdwgc/\n\ngit checkout $LIBGC_COMMIT\nexport LIBGC_COMMIT_FULL_HASH=$(git rev-parse HEAD)\n\n./autogen.sh\n\nCC=$CC CFLAGS='-fPIC' LDFLAGS='-fPIC' ./configure \\\n\t--disable-dependency-tracking \\\n\t--disable-docs \\\n\t--enable-handle-fork=yes \\\n\t--enable-rwlock \\\n\t--enable-threads=pthreads \\\n\t--enable-static \\\n\t--enable-shared=no \\\n\t--enable-parallel-mark \\\n\t--enable-single-obj-compilation \\\n\t--enable-gc-debug \\\n\t--with-libatomic-ops=yes \\\n\t--enable-sigrt-signals\n\nmake\n\npopd\n\ncp bdwgc/.libs/libgc.a         $TCC_FOLDER/lib/libgc.a\n\ndate                         > $TCC_FOLDER/lib/libgc_build_on_date.txt\necho $LIBGC_COMMIT_FULL_HASH > $TCC_FOLDER/lib/libgc_build_source_hash.txt\nuname -a                     > $TCC_FOLDER/lib/libgc_build_machine_uname.txt\n\nls -la $TCC_FOLDER/lib/libgc.a\necho \"Done compiling libgc, at commit $LIBGC_COMMIT , full hash: $LIBGC_COMMIT_FULL_HASH . The static library is in $TCC_FOLDER/lib/libgc.a \"\n"
  },
  {
    "path": "thirdparty/build_scripts/thirdparty-macos-arm64_bdwgc.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nif ! test -f vlib/v/compiler_errors_test.v; then\n  echo \"this script should be run in V's main repo folder!\"\n  exit 1\nfi\n\n## ensure all output is in English, independent from the current user's local:\nexport LANG=C\n\nexport CURRENT_SCRIPT_PATH=$(realpath \"$0\")\n\nexport CC=\"${CC:-gcc}\"\nexport TCC_FOLDER=\"${TCC_FOLDER:-thirdparty/tcc}\"\nexport LIBGC_COMMIT=\"${LIBGC_COMMIT:-master}\"\nmkdir -p $TCC_FOLDER/lib/\n\necho \"          CC: $CC\"\necho \"  TCC_FOLDER: $TCC_FOLDER\"\necho \"LIBGC_COMMIT: $LIBGC_COMMIT\"\necho ===============================================================\n\nrm -rf bdwgc/\n\npushd .\ngit clone https://github.com/ivmai/bdwgc\ncd bdwgc/\n\ngit checkout $LIBGC_COMMIT\nexport LIBGC_COMMIT_FULL_HASH=$(git rev-parse HEAD)\n\ngit clone https://github.com/bdwgc/libatomic_ops\n\n./autogen.sh\n\nCC=$CC CFLAGS=\"-Os -mtune=generic -fPIC\" LDFLAGS=\"-Os -fPIC\" ./configure \\\n\t--disable-dependency-tracking \\\n\t--disable-docs \\\n\t--enable-static=yes \\\n\t--enable-shared=yes \\\n\t--enable-single-obj-compilation \\\n\t--enable-gc-debug \\\n\t--enable-large-config \\\n\t--enable-cplusplus \\\n\t--with-libatomic-ops=check \\\n\t--enable-sigrt-signals\n\nmake\n\ncd .libs/\nfor dname in *.dylib; do\n   echo \"Post processing ${dname} ...\"\n   install_name_tool -id \"@rpath/${dname}\" $dname;\n   otool -D $dname;\ndone\n\npopd\n\n################################################################################################\ndate                         > $TCC_FOLDER/lib/libgc_build_on_date.txt\necho $LIBGC_COMMIT_FULL_HASH > $TCC_FOLDER/lib/libgc_build_source_hash.txt\nuname -a                     > $TCC_FOLDER/lib/libgc_build_machine_uname.txt\necho \"$0\"                    > $TCC_FOLDER/lib/libgc_build_cmd.txt\n\nrsync -a bdwgc/.libs/         $TCC_FOLDER/lib/\nls -lad $TCC_FOLDER/lib/*\n\necho \"Done compiling libgc, at commit $LIBGC_COMMIT , full hash: $LIBGC_COMMIT_FULL_HASH . The static library is in $TCC_FOLDER/lib/libgc.a \"\n"
  },
  {
    "path": "thirdparty/build_scripts/thirdparty-macos-arm64_tcc.sh",
    "content": "## NOTE: this script does *not* use a shebang **deliberately**, in order to\n## access the same shell, to capture its own launching command with `fc`,\n## and to record it later in the new commit message in thirdpart/tcc.\n\n## WARNING: THE ORIGINAL OF THIS SCRIPT IS IN:\n## https://github.com/vlang/v/blob/master/thirdparty/build_scripts/thirdparty-macos-arm64_tcc.sh ,\n## I.E. IN THE MAIN V REPOSITORY. IF YOU NEED TO MAKE CHANGES, CHANGE THAT.\n##\n## THE `build.sh` FILE IN `vlang/tccbin` REPO IS A COPY, RECORDED AT THE TIME\n## OF REBUILDING, FOR EASIER/RELIABLE REPRODUCTION OF HISTORIC VERSIONS.\n## IT IS NOT INTENDED TO BE MODIFIED.\n\n\nBUILD_CMD=`fc -nl -0`\n## remove whitespaces before/after the actual command:\nBUILD_CMD=\"$(echo \"${BUILD_CMD}\" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')\"\n\nset -e\n\n## make sure that commands use English in their output, instead of the local system's local:\nexport LANG=C\n\nif ! test -f vlib/v/compiler_errors_test.v; then\n  echo \"this script should be run in V's main repo folder!\"\n  exit 1\nfi\n\nexport CFLAGS='-O3'\nexport CURRENT_SCRIPT_PATH=$(realpath \"$0\")\n\nexport TCC_COMMIT=\"${TCC_COMMIT:-mob}\"\nexport TCC_FOLDER=\"${TCC_FOLDER:-thirdparty/tcc.$TCC_COMMIT}\"\nexport CC=\"${CC:-clang}\"\n\necho \" BUILD_CMD: \\`$BUILD_CMD\\`\"\necho \"        CC: $CC\"\necho \"TCC_COMMIT: $TCC_COMMIT\"\necho \"TCC_FOLDER: \\`$TCC_FOLDER\\`\"\necho ===============================================================\n\nrm -rf tinycc/\nrm -rf thirdparty/tcc.original/\nrsync -a thirdparty/tcc/ thirdparty/tcc.original/\n## rm -rf $TCC_FOLDER\n\npushd .\n\ngit clone git://repo.or.cz/tinycc.git\n\ncd tinycc\n\ngit checkout $TCC_COMMIT\nexport TCC_COMMIT_FULL_HASH=$(git rev-parse HEAD)\n\n### NB: the symlinks below are needed, to ensure proper support for bootstrapping tcc, otherwise backtraces will be disabled .\nfor i in include/*.h; do echo $i; ln -s $i $(basename $i); done\n\n#\t    --libdir=$TCC_FOLDER/lib \\\n\n./configure \\\n        --prefix=$TCC_FOLDER \\\n        --bindir=$TCC_FOLDER \\\n\t    --tccdir=$TCC_FOLDER/lib \\\n        --includedir=$TCC_FOLDER/include \\\n        --crtprefix=$TCC_FOLDER/lib:/usr/lib \\\n        --sysincludepaths=$TCC_FOLDER/include:$TCC_FOLDER/lib/include:/usr/local/include:/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include:/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include \\\n        --libpaths=$TCC_FOLDER/lib:/usr/local/lib:/usr/lib:/lib \\\n\t    --config-new_macho=yes \\\n\t    --config-codesign \\\n        --cc=\"$CC\" \\\n        --extra-cflags=\"$CFLAGS\" \\\n\t    --config-bcheck=yes \\\n\t    --config-backtrace=yes \\\n\t    --enable-static \\\n\t    --dwarf=5 \\\n        --debug\n\ngmake\ngmake install\n\npopd\n\nrsync -a --delete tinycc/$TCC_FOLDER/*                $TCC_FOLDER/\nrsync -a          thirdparty/tcc.original/.git/       $TCC_FOLDER/.git/\nrsync -a          thirdparty/tcc.original/lib/libgc*  $TCC_FOLDER/lib/\nrsync -a          thirdparty/tcc.original/lib/build*  $TCC_FOLDER/lib/\nrsync -a          thirdparty/tcc.original/README.md   $TCC_FOLDER/README.md\nrsync -a          $CURRENT_SCRIPT_PATH                $TCC_FOLDER/build.sh\nmv                $TCC_FOLDER/tcc                     $TCC_FOLDER/tcc.exe\n\ndate                                                > $TCC_FOLDER/build_on_date.txt\necho $TCC_COMMIT_FULL_HASH                          > $TCC_FOLDER/build_source_hash.txt\n$TCC_FOLDER/tcc.exe --version                       > $TCC_FOLDER/build_version.txt\nuname -a                                            > $TCC_FOLDER/build_machine_uname.txt\n\n## needed for Big Sur\nln -s /System/DriverKit/usr/lib/libSystem.dylib $TCC_FOLDER/lib/libc.dylib\n\n## show the builtin search paths for sanity checking:\n$TCC_FOLDER/tcc.exe -v -v\n\npushd .\ncd $TCC_FOLDER\ngit add .\ngit commit -m \"build with \\`$BUILD_CMD\\`\"\npopd\n\necho \"tcc commit: $TCC_COMMIT , full hash: $TCC_COMMIT_FULL_HASH .\"\necho \"The tcc executable is ready in $TCC_FOLDER/tcc.exe\"\n\n"
  },
  {
    "path": "thirdparty/build_scripts/thirdparty-openbsd-amd64_tcc.sh",
    "content": "## NOTE: this script does *not* use a shebang **deliberately**, in order to\n## access the same shell, to capture its own launching command with `fc`,\n## and to record it later in the new commit message in thirdpart/tcc.\n\n## WARNING: THE ORIGINAL OF THIS SCRIPT IS IN:\n## https://github.com/vlang/v/blob/master/thirdparty/build_scripts/thirdparty-openbsd-amd64_tcc.sh ,\n## I.E. IN THE MAIN V REPOSITORY. IF YOU NEED TO MAKE CHANGES, CHANGE THAT.\n##\n## THE `build.sh` FILE IN `vlang/tccbin` REPO IS A COPY, RECORDED AT THE TIME\n## OF REBUILDING, FOR EASIER/RELIABLE REPRODUCTION OF HISTORIC VERSIONS.\n## IT IS NOT INTENDED TO BE MODIFIED.\n\nBUILD_CMD=`fc -nl -0`\n## remove whitespaces before/after the actual command:\nBUILD_CMD=\"$(echo \"${BUILD_CMD}\" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')\"\n\nset -e\n\nif ! test -f vlib/v/compiler_errors_test.v; then\n  echo \"this script should be run in V's main repo folder!\"\n  exit 1\nfi\n\nexport CFLAGS='-O3'\nexport CURRENT_SCRIPT_PATH=$(realpath \"$0\")\n\nexport TCC_COMMIT=\"${TCC_COMMIT:-mob}\"\nexport TCC_FOLDER=\"${TCC_FOLDER:-thirdparty/tcc.$TCC_COMMIT}\"\nexport CC=\"${CC:-clang}\"\n\necho \" BUILD_CMD: \\`$BUILD_CMD\\`\"\necho \"        CC: $CC\"\necho \"TCC_COMMIT: $TCC_COMMIT\"\necho \"TCC_FOLDER: \\`$TCC_FOLDER\\`\"\necho ===============================================================\n\nrm -rf tinycc/\nrm -rf thirdparty/tcc.original/\nrsync -a thirdparty/tcc/ thirdparty/tcc.original/\n\npushd .\n\ngit clone git://repo.or.cz/tinycc.git\n\ncd tinycc\n\ngit checkout $TCC_COMMIT\nexport TCC_COMMIT_FULL_HASH=$(git rev-parse HEAD)\n\n./configure \\\n            --prefix=$TCC_FOLDER \\\n            --bindir=$TCC_FOLDER \\\n            --crtprefix=$TCC_FOLDER/lib:/usr/lib \\\n            --sysincludepaths=$TCC_FOLDER/lib/tcc/include:/usr/local/include:/usr/include \\\n            --libpaths=$TCC_FOLDER/lib/tcc:$TCC_FOLDER/lib:/usr/lib:/usr/local/lib \\\n            --cc=\"$CC\" \\\n            --extra-cflags=\"$CFLAGS\" \\\n            --config-backtrace=yes \\\n            --config-bcheck=yes \\\n            --debug\n\ngmake\ngmake install\n\npopd\n\nrsync -a --delete tinycc/$TCC_FOLDER/                 $TCC_FOLDER/\nrsync -a          thirdparty/tcc.original/.git/       $TCC_FOLDER/.git/\n# rsync -a          thirdparty/tcc.original/lib/libgc*  $TCC_FOLDER/lib/\n# rsync -a          thirdparty/tcc.original/lib/build*  $TCC_FOLDER/lib/\nrsync -a          thirdparty/tcc.original/README.md   $TCC_FOLDER/README.md\nrsync -a          $CURRENT_SCRIPT_PATH                $TCC_FOLDER/build.sh\nmv                $TCC_FOLDER/tcc                     $TCC_FOLDER/tcc.exe\n\ndate                                                > $TCC_FOLDER/build_on_date.txt\necho $TCC_COMMIT_FULL_HASH                          > $TCC_FOLDER/build_source_hash.txt\n$TCC_FOLDER/tcc.exe --version                       > $TCC_FOLDER/build_version.txt\nuname -a                                            > $TCC_FOLDER/build_machine_uname.txt\n\n## show the builtin search paths for sanity checking:\n$TCC_FOLDER/tcc.exe -v -v\n\npushd .\ncd $TCC_FOLDER\ngit add .\ngit commit -m \"build with \\`$BUILD_CMD\\`\"\npopd\n\necho \"tcc commit: $TCC_COMMIT , full hash: $TCC_COMMIT_FULL_HASH .\"\necho \"The tcc executable is ready in $TCC_FOLDER/tcc.exe\"\n"
  },
  {
    "path": "thirdparty/cJSON/README.md",
    "content": "# [DaveGamble/cJSON](https://github.com/DaveGamble/cJSON)\n\nUltralightweight JSON parser in ANSI C.\n\n## MIT license\n\n```\nCopyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n```\n"
  },
  {
    "path": "thirdparty/cJSON/cJSON.c",
    "content": "#if defined(__APPLE__)\n#include <stddef.h>\n#endif\n\n/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files (the \"Software\"), to deal\n  in the Software without restriction, including without limitation the rights\n  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  copies of the Software, and to permit persons to whom the Software is\n  furnished to do so, subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  THE SOFTWARE.\n*/\n\n/* cJSON */\n/* JSON parser in C. */\n\n/* disable warnings about old C89 functions in MSVC */\n#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)\n#define _CRT_SECURE_NO_DEPRECATE\n#endif\n\n#ifdef __GNUC__\n#pragma GCC visibility push(default)\n#endif\n#if defined(_MSC_VER)\n#pragma warning (push)\n/* disable warning about single line comments in system headers */\n#pragma warning (disable : 4001)\n#endif\n\n#include <string.h>\n#include <stdio.h>\n#include <math.h>\n#include <stdlib.h>\n#include <limits.h>\n#include <ctype.h>\n#include <float.h>\n\n#ifdef ENABLE_LOCALES\n#include <locale.h>\n#endif\n\n#if defined(_MSC_VER)\n#pragma warning (pop)\n#endif\n#ifdef __GNUC__\n#pragma GCC visibility pop\n#endif\n\n#include \"cJSON.h\"\n\n/* define our own boolean type */\n#ifdef true\n#undef true\n#endif\n#define true ((cJSON_bool)1)\n\n#ifdef false\n#undef false\n#endif\n#define false ((cJSON_bool)0)\n\n/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */\n#ifndef isinf\n#define isinf(d) (isnan((d - d)) && !isnan(d))\n#endif\n#ifndef isnan\n#define isnan(d) (d != d)\n#endif\n\n#ifndef NAN\n#ifdef _WIN32\n#define NAN sqrt(-1.0)\n#else\n#define NAN 0.0/0.0\n#endif\n#endif\n\ntypedef struct {\n    const unsigned char *json;\n    size_t position;\n} error;\nstatic error global_error = { NULL, 0 };\n\nCJSON_PUBLIC(size_t) cJSON_GetErrorPos(void)\n{\n   return global_error.position;\n}\n\nCJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)\n{\n    return (const char*) (global_error.json + global_error.position);\n}\n\nCJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)\n{\n    if (!cJSON_IsString(item))\n    {\n        return NULL;\n    }\n\n    return item->valuestring;\n}\n\nCJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)\n{\n    if (!cJSON_IsNumber(item))\n    {\n        return (double) NAN;\n    }\n\n    return item->valuedouble;\n}\n\n/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */\n#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 17)\n    #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.\n#endif\n\nCJSON_PUBLIC(const char*) cJSON_Version(void)\n{\n    static char version[15];\n    sprintf(version, \"%i.%i.%i\", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);\n\n    return version;\n}\n\n/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */\nstatic int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)\n{\n    if ((string1 == NULL) || (string2 == NULL))\n    {\n        return 1;\n    }\n\n    if (string1 == string2)\n    {\n        return 0;\n    }\n\n    for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)\n    {\n        if (*string1 == '\\0')\n        {\n            return 0;\n        }\n    }\n\n    return tolower(*string1) - tolower(*string2);\n}\n\ntypedef struct internal_hooks\n{\n    void *(CJSON_CDECL *allocate)(size_t size);\n    void (CJSON_CDECL *deallocate)(void *pointer);\n    void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);\n} internal_hooks;\n\n#if defined(_MSC_VER)\n/* work around MSVC error C2322: '...' address of dllimport '...' is not static */\nstatic void * CJSON_CDECL internal_malloc(size_t size)\n{\n    return malloc(size);\n}\nstatic void CJSON_CDECL internal_free(void *pointer)\n{\n    free(pointer);\n}\nstatic void * CJSON_CDECL internal_realloc(void *pointer, size_t size)\n{\n    return realloc(pointer, size);\n}\n#else\n#define internal_malloc malloc\n#define internal_free free\n#define internal_realloc realloc\n#endif\n\n/* strlen of character literals resolved at compile time */\n#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(\"\"))\n\nstatic internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };\n\nstatic unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)\n{\n    size_t length = 0;\n    unsigned char *copy = NULL;\n\n    if (string == NULL)\n    {\n        return NULL;\n    }\n\n    length = strlen((const char*)string) + sizeof(\"\");\n    copy = (unsigned char*)hooks->allocate(length);\n    if (copy == NULL)\n    {\n        return NULL;\n    }\n    memcpy(copy, string, length);\n\n    return copy;\n}\n\nCJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)\n{\n    if (hooks == NULL)\n    {\n        /* Reset hooks */\n        global_hooks.allocate = malloc;\n        global_hooks.deallocate = free;\n        global_hooks.reallocate = realloc;\n        return;\n    }\n\n    global_hooks.allocate = malloc;\n    if (hooks->malloc_fn != NULL)\n    {\n        global_hooks.allocate = hooks->malloc_fn;\n    }\n\n    global_hooks.deallocate = free;\n    if (hooks->free_fn != NULL)\n    {\n        global_hooks.deallocate = hooks->free_fn;\n    }\n\n    /* use realloc only if both free and malloc are used */\n    global_hooks.reallocate = NULL;\n    if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))\n    {\n        global_hooks.reallocate = realloc;\n    }\n}\n\n/* Internal constructor. */\nstatic cJSON *cJSON_New_Item(const internal_hooks * const hooks)\n{\n    cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));\n    if (node)\n    {\n        memset(node, '\\0', sizeof(cJSON));\n    }\n\n    return node;\n}\n\n/* Delete a cJSON structure. */\nCJSON_PUBLIC(void) cJSON_Delete(cJSON *item)\n{\n    cJSON *next = NULL;\n    while (item != NULL)\n    {\n        next = item->next;\n        if (!(item->type & cJSON_IsReference) && (item->child != NULL))\n        {\n            cJSON_Delete(item->child);\n        }\n        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))\n        {\n            global_hooks.deallocate(item->valuestring);\n        }\n        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))\n        {\n            global_hooks.deallocate(item->string);\n        }\n        global_hooks.deallocate(item);\n        item = next;\n    }\n}\n\n/* get the decimal point character of the current locale */\nstatic unsigned char get_decimal_point(void)\n{\n#ifdef ENABLE_LOCALES\n    struct lconv *lconv = localeconv();\n    return (unsigned char) lconv->decimal_point[0];\n#else\n    return '.';\n#endif\n}\n\ntypedef struct\n{\n    const unsigned char *content;\n    size_t length;\n    size_t offset;\n    size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */\n    internal_hooks hooks;\n} parse_buffer;\n\n/* check if the given size is left to read in a given parse buffer (starting with 1) */\n#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))\n/* check if the buffer can be accessed at the given index (starting with 0) */\n#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))\n#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))\n/* get a pointer to the buffer at the position */\n#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)\n\n/* Parse the input text to generate a number, and populate the result into item. */\nstatic cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)\n{\n    double number = 0;\n    unsigned char *after_end = NULL;\n    unsigned char number_c_string[64];\n    unsigned char decimal_point = get_decimal_point();\n    size_t i = 0;\n\n    if ((input_buffer == NULL) || (input_buffer->content == NULL))\n    {\n        return false;\n    }\n\n    /* copy the number into a temporary buffer and replace '.' with the decimal point\n     * of the current locale (for strtod)\n     * This also takes care of '\\0' not necessarily being available for marking the end of the input */\n    for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)\n    {\n        switch (buffer_at_offset(input_buffer)[i])\n        {\n            case '0':\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n            case '5':\n            case '6':\n            case '7':\n            case '8':\n            case '9':\n            case '+':\n            case '-':\n            case 'e':\n            case 'E':\n                number_c_string[i] = buffer_at_offset(input_buffer)[i];\n                break;\n\n            case '.':\n                number_c_string[i] = decimal_point;\n                break;\n\n            default:\n                goto loop_end;\n        }\n    }\nloop_end:\n    number_c_string[i] = '\\0';\n\n    number = strtod((const char*)number_c_string, (char**)&after_end);\n    if (number_c_string == after_end)\n    {\n        return false; /* parse_error */\n    }\n\n    item->valuedouble = number;\n\n    /* use saturation in case of overflow */\n    if (number >= INT_MAX)\n    {\n        item->valueint = INT_MAX;\n    }\n    else if (number <= (double)INT_MIN)\n    {\n        item->valueint = INT_MIN;\n    }\n    else\n    {\n        item->valueint = (int)number;\n    }\n\n    item->type = cJSON_Number;\n\n    input_buffer->offset += (size_t)(after_end - number_c_string);\n    return true;\n}\n\n/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */\nCJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)\n{\n    if (number >= INT_MAX)\n    {\n        object->valueint = INT_MAX;\n    }\n    else if (number <= (double)INT_MIN)\n    {\n        object->valueint = INT_MIN;\n    }\n    else\n    {\n        object->valueint = (int)number;\n    }\n\n    return object->valuedouble = number;\n}\n\nCJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)\n{\n    char *copy = NULL;\n    /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */\n    if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference))\n    {\n        return NULL;\n    }\n    /* return NULL if the object is corrupted */\n    if (object->valuestring == NULL)\n    {\n        return NULL;\n    }\n    if (strlen(valuestring) <= strlen(object->valuestring))\n    {\n        strcpy(object->valuestring, valuestring);\n        return object->valuestring;\n    }\n    copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);\n    if (copy == NULL)\n    {\n        return NULL;\n    }\n    if (object->valuestring != NULL)\n    {\n        cJSON_free(object->valuestring);\n    }\n    object->valuestring = copy;\n\n    return copy;\n}\n\ntypedef struct\n{\n    unsigned char *buffer;\n    size_t length;\n    size_t offset;\n    size_t depth; /* current nesting depth (for formatted printing) */\n    cJSON_bool noalloc;\n    cJSON_bool format; /* is this print a formatted print */\n    internal_hooks hooks;\n} printbuffer;\n\n/* realloc printbuffer if necessary to have at least \"needed\" bytes more */\nstatic unsigned char* ensure(printbuffer * const p, size_t needed)\n{\n    unsigned char *newbuffer = NULL;\n    size_t newsize = 0;\n\n    if ((p == NULL) || (p->buffer == NULL))\n    {\n        return NULL;\n    }\n\n    if ((p->length > 0) && (p->offset >= p->length))\n    {\n        /* make sure that offset is valid */\n        return NULL;\n    }\n\n    if (needed > INT_MAX)\n    {\n        /* sizes bigger than INT_MAX are currently not supported */\n        return NULL;\n    }\n\n    needed += p->offset + 1;\n    if (needed <= p->length)\n    {\n        return p->buffer + p->offset;\n    }\n\n    if (p->noalloc) {\n        return NULL;\n    }\n\n    /* calculate new buffer size */\n    if (needed > (INT_MAX / 2))\n    {\n        /* overflow of int, use INT_MAX if possible */\n        if (needed <= INT_MAX)\n        {\n            newsize = INT_MAX;\n        }\n        else\n        {\n            return NULL;\n        }\n    }\n    else\n    {\n        newsize = needed * 2;\n    }\n\n    if (p->hooks.reallocate != NULL)\n    {\n        /* reallocate with realloc if available */\n        newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);\n        if (newbuffer == NULL)\n        {\n            p->hooks.deallocate(p->buffer);\n            p->length = 0;\n            p->buffer = NULL;\n\n            return NULL;\n        }\n    }\n    else\n    {\n        /* otherwise reallocate manually */\n        newbuffer = (unsigned char*)p->hooks.allocate(newsize);\n        if (!newbuffer)\n        {\n            p->hooks.deallocate(p->buffer);\n            p->length = 0;\n            p->buffer = NULL;\n\n            return NULL;\n        }\n\n        memcpy(newbuffer, p->buffer, p->offset + 1);\n        p->hooks.deallocate(p->buffer);\n    }\n    p->length = newsize;\n    p->buffer = newbuffer;\n\n    return newbuffer + p->offset;\n}\n\n/* calculate the new length of the string in a printbuffer and update the offset */\nstatic void update_offset(printbuffer * const buffer)\n{\n    const unsigned char *buffer_pointer = NULL;\n    if ((buffer == NULL) || (buffer->buffer == NULL))\n    {\n        return;\n    }\n    buffer_pointer = buffer->buffer + buffer->offset;\n\n    buffer->offset += strlen((const char*)buffer_pointer);\n}\n\n/* securely comparison of floating-point variables */\nstatic cJSON_bool compare_double(double a, double b)\n{\n    double maxVal = (a > 0 ? a : -a) > (b > 0 ? b : -b) ? (a > 0 ? a : -a) : (b > 0 ? b : -b);\n    return (a - b <= maxVal * DBL_EPSILON) && (b - a <= maxVal * DBL_EPSILON);\n}\n\n/* Render the number nicely from the given item into a string. */\nstatic cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)\n{\n    unsigned char *output_pointer = NULL;\n    double d = item->valuedouble;\n    int length = 0;\n    size_t i = 0;\n    unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */\n    unsigned char decimal_point = get_decimal_point();\n    double test = 0.0;\n\n    if (output_buffer == NULL)\n    {\n        return false;\n    }\n\n    /* This checks for NaN and Infinity */\n    if (isnan(d) || isinf(d))\n    {\n        length = sprintf((char*)number_buffer, \"null\");\n    }\n\telse if(d == (double)item->valueint)\n\t{\n\t\tlength = sprintf((char*)number_buffer, \"%d\", item->valueint);\n\t}\n    else\n    {\n        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */\n        length = sprintf((char*)number_buffer, \"%1.15g\", d);\n\n        /* Check whether the original double can be recovered */\n        if ((sscanf((char*)number_buffer, \"%lg\", &test) != 1) || !compare_double((double)test, d))\n        {\n            /* If not, print with 17 decimal places of precision */\n            length = sprintf((char*)number_buffer, \"%1.17g\", d);\n        }\n    }\n\n    /* sprintf failed or buffer overrun occurred */\n    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))\n    {\n        return false;\n    }\n\n    /* reserve appropriate space in the output */\n    output_pointer = ensure(output_buffer, (size_t)length + sizeof(\"\"));\n    if (output_pointer == NULL)\n    {\n        return false;\n    }\n\n    /* copy the printed number to the output and replace locale\n     * dependent decimal point with '.' */\n    for (i = 0; i < ((size_t)length); i++)\n    {\n        if (number_buffer[i] == decimal_point)\n        {\n            output_pointer[i] = '.';\n            continue;\n        }\n\n        output_pointer[i] = number_buffer[i];\n    }\n    output_pointer[i] = '\\0';\n\n    output_buffer->offset += (size_t)length;\n\n    return true;\n}\n\n/* parse 4 digit hexadecimal number */\nstatic unsigned parse_hex4(const unsigned char * const input)\n{\n    unsigned int h = 0;\n    size_t i = 0;\n\n    for (i = 0; i < 4; i++)\n    {\n        /* parse digit */\n        if ((input[i] >= '0') && (input[i] <= '9'))\n        {\n            h += (unsigned int) input[i] - '0';\n        }\n        else if ((input[i] >= 'A') && (input[i] <= 'F'))\n        {\n            h += (unsigned int) 10 + input[i] - 'A';\n        }\n        else if ((input[i] >= 'a') && (input[i] <= 'f'))\n        {\n            h += (unsigned int) 10 + input[i] - 'a';\n        }\n        else /* invalid */\n        {\n            return 0;\n        }\n\n        if (i < 3)\n        {\n            /* shift left to make place for the next nibble */\n            h = h << 4;\n        }\n    }\n\n    return h;\n}\n\n/* converts a UTF-16 literal to UTF-8\n * A literal can be one or two sequences of the form \\uXXXX */\nstatic unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)\n{\n    long unsigned int codepoint = 0;\n    unsigned int first_code = 0;\n    const unsigned char *first_sequence = input_pointer;\n    unsigned char utf8_length = 0;\n    unsigned char utf8_position = 0;\n    unsigned char sequence_length = 0;\n    unsigned char first_byte_mark = 0;\n\n    if ((input_end - first_sequence) < 6)\n    {\n        /* input ends unexpectedly */\n        goto fail;\n    }\n\n    /* get the first utf16 sequence */\n    first_code = parse_hex4(first_sequence + 2);\n\n    /* check that the code is valid */\n    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))\n    {\n        goto fail;\n    }\n\n    /* UTF16 surrogate pair */\n    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))\n    {\n        const unsigned char *second_sequence = first_sequence + 6;\n        unsigned int second_code = 0;\n        sequence_length = 12; /* \\uXXXX\\uXXXX */\n\n        if ((input_end - second_sequence) < 6)\n        {\n            /* input ends unexpectedly */\n            goto fail;\n        }\n\n        if ((second_sequence[0] != '\\\\') || (second_sequence[1] != 'u'))\n        {\n            /* missing second half of the surrogate pair */\n            goto fail;\n        }\n\n        /* get the second utf16 sequence */\n        second_code = parse_hex4(second_sequence + 2);\n        /* check that the code is valid */\n        if ((second_code < 0xDC00) || (second_code > 0xDFFF))\n        {\n            /* invalid second half of the surrogate pair */\n            goto fail;\n        }\n\n\n        /* calculate the unicode codepoint from the surrogate pair */\n        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));\n    }\n    else\n    {\n        sequence_length = 6; /* \\uXXXX */\n        codepoint = first_code;\n    }\n\n    /* encode as UTF-8\n     * takes at maximum 4 bytes to encode:\n     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */\n    if (codepoint < 0x80)\n    {\n        /* normal ascii, encoding 0xxxxxxx */\n        utf8_length = 1;\n    }\n    else if (codepoint < 0x800)\n    {\n        /* two bytes, encoding 110xxxxx 10xxxxxx */\n        utf8_length = 2;\n        first_byte_mark = 0xC0; /* 11000000 */\n    }\n    else if (codepoint < 0x10000)\n    {\n        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */\n        utf8_length = 3;\n        first_byte_mark = 0xE0; /* 11100000 */\n    }\n    else if (codepoint <= 0x10FFFF)\n    {\n        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */\n        utf8_length = 4;\n        first_byte_mark = 0xF0; /* 11110000 */\n    }\n    else\n    {\n        /* invalid unicode codepoint */\n        goto fail;\n    }\n\n    /* encode as utf8 */\n    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)\n    {\n        /* 10xxxxxx */\n        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);\n        codepoint >>= 6;\n    }\n    /* encode first byte */\n    if (utf8_length > 1)\n    {\n        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);\n    }\n    else\n    {\n        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);\n    }\n\n    *output_pointer += utf8_length;\n\n    return sequence_length;\n\nfail:\n    return 0;\n}\n\n/* Parse the input text into an unescaped cinput, and populate item. */\nstatic cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)\n{\n    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;\n    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;\n    unsigned char *output_pointer = NULL;\n    unsigned char *output = NULL;\n\n    /* not a string */\n    if (buffer_at_offset(input_buffer)[0] != '\\\"')\n    {\n        goto fail;\n    }\n\n    {\n        /* calculate approximate size of the output (overestimate) */\n        size_t allocation_length = 0;\n        size_t skipped_bytes = 0;\n        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\\\"'))\n        {\n            /* is escape sequence */\n            if (input_end[0] == '\\\\')\n            {\n                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)\n                {\n                    /* prevent buffer overflow when last input character is a backslash */\n                    goto fail;\n                }\n                skipped_bytes++;\n                input_end++;\n            }\n            input_end++;\n        }\n        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\\\"'))\n        {\n            goto fail; /* string ended unexpectedly */\n        }\n\n        /* This is at most how much we need for the output */\n        allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;\n        output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(\"\"));\n        if (output == NULL)\n        {\n            goto fail; /* allocation failure */\n        }\n    }\n\n    output_pointer = output;\n    /* loop through the string literal */\n    while (input_pointer < input_end)\n    {\n        if (*input_pointer != '\\\\')\n        {\n            *output_pointer++ = *input_pointer++;\n        }\n        /* escape sequence */\n        else\n        {\n            unsigned char sequence_length = 2;\n            if ((input_end - input_pointer) < 1)\n            {\n                goto fail;\n            }\n\n            switch (input_pointer[1])\n            {\n                case 'b':\n                    *output_pointer++ = '\\b';\n                    break;\n                case 'f':\n                    *output_pointer++ = '\\f';\n                    break;\n                case 'n':\n                    *output_pointer++ = '\\n';\n                    break;\n                case 'r':\n                    *output_pointer++ = '\\r';\n                    break;\n                case 't':\n                    *output_pointer++ = '\\t';\n                    break;\n                case '\\\"':\n                case '\\\\':\n                case '/':\n                    *output_pointer++ = input_pointer[1];\n                    break;\n\n                /* UTF-16 literal */\n                case 'u':\n                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);\n                    if (sequence_length == 0)\n                    {\n                        /* failed to convert UTF16-literal to UTF-8 */\n                        goto fail;\n                    }\n                    break;\n\n                default:\n                    goto fail;\n            }\n            input_pointer += sequence_length;\n        }\n    }\n\n    /* zero terminate the output */\n    *output_pointer = '\\0';\n\n    item->type = cJSON_String;\n    item->valuestring = (char*)output;\n\n    input_buffer->offset = (size_t) (input_end - input_buffer->content);\n    input_buffer->offset++;\n\n    return true;\n\nfail:\n    if (output != NULL)\n    {\n        input_buffer->hooks.deallocate(output);\n    }\n\n    if (input_pointer != NULL)\n    {\n        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);\n    }\n\n    return false;\n}\n\n/* Render the cstring provided to an escaped version that can be printed. */\nstatic cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)\n{\n    const unsigned char *input_pointer = NULL;\n    unsigned char *output = NULL;\n    unsigned char *output_pointer = NULL;\n    size_t output_length = 0;\n    /* numbers of additional characters needed for escaping */\n    size_t escape_characters = 0;\n\n    if (output_buffer == NULL)\n    {\n        return false;\n    }\n\n    /* empty string */\n    if (input == NULL)\n    {\n        output = ensure(output_buffer, sizeof(\"\\\"\\\"\"));\n        if (output == NULL)\n        {\n            return false;\n        }\n        strcpy((char*)output, \"\\\"\\\"\");\n\n        return true;\n    }\n\n    /* set \"flag\" to 1 if something needs to be escaped */\n    for (input_pointer = input; *input_pointer; input_pointer++)\n    {\n        switch (*input_pointer)\n        {\n            case '\\\"':\n            case '\\\\':\n            case '\\b':\n            case '\\f':\n            case '\\n':\n            case '\\r':\n            case '\\t':\n                /* one character escape sequence */\n                escape_characters++;\n                break;\n            default:\n                if (*input_pointer < 32)\n                {\n                    /* UTF-16 escape sequence uXXXX */\n                    escape_characters += 5;\n                }\n                break;\n        }\n    }\n    output_length = (size_t)(input_pointer - input) + escape_characters;\n\n    output = ensure(output_buffer, output_length + sizeof(\"\\\"\\\"\"));\n    if (output == NULL)\n    {\n        return false;\n    }\n\n    /* no characters have to be escaped */\n    if (escape_characters == 0)\n    {\n        output[0] = '\\\"';\n        memcpy(output + 1, input, output_length);\n        output[output_length + 1] = '\\\"';\n        output[output_length + 2] = '\\0';\n\n        return true;\n    }\n\n    output[0] = '\\\"';\n    output_pointer = output + 1;\n    /* copy the string */\n    for (input_pointer = input; *input_pointer != '\\0'; (void)input_pointer++, output_pointer++)\n    {\n        if ((*input_pointer > 31) && (*input_pointer != '\\\"') && (*input_pointer != '\\\\'))\n        {\n            /* normal character, copy */\n            *output_pointer = *input_pointer;\n        }\n        else\n        {\n            /* character needs to be escaped */\n            *output_pointer++ = '\\\\';\n            switch (*input_pointer)\n            {\n                case '\\\\':\n                    *output_pointer = '\\\\';\n                    break;\n                case '\\\"':\n                    *output_pointer = '\\\"';\n                    break;\n                case '\\b':\n                    *output_pointer = 'b';\n                    break;\n                case '\\f':\n                    *output_pointer = 'f';\n                    break;\n                case '\\n':\n                    *output_pointer = 'n';\n                    break;\n                case '\\r':\n                    *output_pointer = 'r';\n                    break;\n                case '\\t':\n                    *output_pointer = 't';\n                    break;\n                default:\n                    /* escape and print as unicode codepoint */\n                    sprintf((char*)output_pointer, \"u%04x\", *input_pointer);\n                    output_pointer += 4;\n                    break;\n            }\n        }\n    }\n    output[output_length + 1] = '\\\"';\n    output[output_length + 2] = '\\0';\n\n    return true;\n}\n\n/* Invoke print_string_ptr (which is useful) on an item. */\nstatic cJSON_bool print_string(const cJSON * const item, printbuffer * const p)\n{\n    return print_string_ptr((unsigned char*)item->valuestring, p);\n}\n\n/* Predeclare these prototypes. */\nstatic cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);\nstatic cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);\nstatic cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);\nstatic cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);\nstatic cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);\nstatic cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);\n\n/* Utility to jump whitespace and cr/lf */\nstatic parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)\n{\n    if ((buffer == NULL) || (buffer->content == NULL))\n    {\n        return NULL;\n    }\n\n    if (cannot_access_at_index(buffer, 0))\n    {\n        return buffer;\n    }\n\n    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))\n    {\n       buffer->offset++;\n    }\n\n    if (buffer->offset == buffer->length)\n    {\n        buffer->offset--;\n    }\n\n    return buffer;\n}\n\n/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */\nstatic parse_buffer *skip_utf8_bom(parse_buffer * const buffer)\n{\n    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))\n    {\n        return NULL;\n    }\n\n    if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), \"\\xEF\\xBB\\xBF\", 3) == 0))\n    {\n        buffer->offset += 3;\n    }\n\n    return buffer;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)\n{\n    size_t buffer_length;\n\n    if (NULL == value)\n    {\n        return NULL;\n    }\n\n    /* Adding null character size due to require_null_terminated. */\n    buffer_length = strlen(value) + sizeof(\"\");\n\n    return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);\n}\n\n/* Parse an object - create a new root, and populate. */\nCJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)\n{\n    parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };\n    cJSON *item = NULL;\n\n    /* reset error position */\n    global_error.json = NULL;\n    global_error.position = 0;\n\n    if (value == NULL || 0 == buffer_length)\n    {\n        goto fail;\n    }\n\n    buffer.content = (const unsigned char*)value;\n    buffer.length = buffer_length;\n    buffer.offset = 0;\n    buffer.hooks = global_hooks;\n\n    item = cJSON_New_Item(&global_hooks);\n    if (item == NULL) /* memory fail */\n    {\n        goto fail;\n    }\n\n    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))\n    {\n        /* parse failure. ep is set. */\n        goto fail;\n    }\n\n    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */\n    if (require_null_terminated)\n    {\n        buffer_skip_whitespace(&buffer);\n        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\\0')\n        {\n            goto fail;\n        }\n    }\n    if (return_parse_end)\n    {\n        *return_parse_end = (const char*)buffer_at_offset(&buffer);\n    }\n\n    return item;\n\nfail:\n    if (item != NULL)\n    {\n        cJSON_Delete(item);\n    }\n\n    if (value != NULL)\n    {\n        error local_error;\n        local_error.json = (const unsigned char*)value;\n        local_error.position = 0;\n\n        if (buffer.offset < buffer.length)\n        {\n            local_error.position = buffer.offset;\n        }\n        else if (buffer.length > 0)\n        {\n            local_error.position = buffer.length - 1;\n        }\n\n        if (return_parse_end != NULL)\n        {\n            *return_parse_end = (const char*)local_error.json + local_error.position;\n        }\n\n        global_error = local_error;\n    }\n\n    return NULL;\n}\n\n/* Default options for cJSON_Parse */\nCJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)\n{\n    return cJSON_ParseWithOpts(value, 0, 0);\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)\n{\n    return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);\n}\n\n#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))\n\nstatic unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)\n{\n    static const size_t default_buffer_size = 256;\n    printbuffer buffer[1];\n    unsigned char *printed = NULL;\n\n    memset(buffer, 0, sizeof(buffer));\n\n    /* create buffer */\n    buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);\n    buffer->length = default_buffer_size;\n    buffer->format = format;\n    buffer->hooks = *hooks;\n    if (buffer->buffer == NULL)\n    {\n        goto fail;\n    }\n\n    /* print the value */\n    if (!print_value(item, buffer))\n    {\n        goto fail;\n    }\n    update_offset(buffer);\n\n    /* check if reallocate is available */\n    if (hooks->reallocate != NULL)\n    {\n        printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);\n        if (printed == NULL) {\n            goto fail;\n        }\n        buffer->buffer = NULL;\n    }\n    else /* otherwise copy the JSON over to a new buffer */\n    {\n        printed = (unsigned char*) hooks->allocate(buffer->offset + 1);\n        if (printed == NULL)\n        {\n            goto fail;\n        }\n        memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));\n        printed[buffer->offset] = '\\0'; /* just to be sure */\n\n        /* free the buffer */\n        hooks->deallocate(buffer->buffer);\n    }\n\n    return printed;\n\nfail:\n    if (buffer->buffer != NULL)\n    {\n        hooks->deallocate(buffer->buffer);\n    }\n\n    if (printed != NULL)\n    {\n        hooks->deallocate(printed);\n    }\n\n    return NULL;\n}\n\n/* Render a cJSON item/entity/structure to text. */\nCJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)\n{\n    return (char*)print(item, true, &global_hooks);\n}\n\nCJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)\n{\n    return (char*)print(item, false, &global_hooks);\n}\n\nCJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)\n{\n    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };\n\n    if (prebuffer < 0)\n    {\n        return NULL;\n    }\n\n    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);\n    if (!p.buffer)\n    {\n        return NULL;\n    }\n\n    p.length = (size_t)prebuffer;\n    p.offset = 0;\n    p.noalloc = false;\n    p.format = fmt;\n    p.hooks = global_hooks;\n\n    if (!print_value(item, &p))\n    {\n        global_hooks.deallocate(p.buffer);\n        return NULL;\n    }\n\n    return (char*)p.buffer;\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)\n{\n    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };\n\n    if ((length < 0) || (buffer == NULL))\n    {\n        return false;\n    }\n\n    p.buffer = (unsigned char*)buffer;\n    p.length = (size_t)length;\n    p.offset = 0;\n    p.noalloc = true;\n    p.format = format;\n    p.hooks = global_hooks;\n\n    return print_value(item, &p);\n}\n\n/* Parser core - when encountering text, process appropriately. */\nstatic cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)\n{\n    if ((input_buffer == NULL) || (input_buffer->content == NULL))\n    {\n        return false; /* no input */\n    }\n\n    /* parse the different types of values */\n    /* null */\n    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), \"null\", 4) == 0))\n    {\n        item->type = cJSON_NULL;\n        input_buffer->offset += 4;\n        return true;\n    }\n    /* false */\n    if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), \"false\", 5) == 0))\n    {\n        item->type = cJSON_False;\n        input_buffer->offset += 5;\n        return true;\n    }\n    /* true */\n    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), \"true\", 4) == 0))\n    {\n        item->type = cJSON_True;\n        item->valueint = 1;\n        input_buffer->offset += 4;\n        return true;\n    }\n    /* string */\n    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\\\"'))\n    {\n        return parse_string(item, input_buffer);\n    }\n    /* number */\n    if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9'))))\n    {\n        return parse_number(item, input_buffer);\n    }\n    /* array */\n    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))\n    {\n        return parse_array(item, input_buffer);\n    }\n    /* object */\n    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))\n    {\n        return parse_object(item, input_buffer);\n    }\n\n    return false;\n}\n\n/* Render a value to text. */\nstatic cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)\n{\n    unsigned char *output = NULL;\n\n    if ((item == NULL) || (output_buffer == NULL))\n    {\n        return false;\n    }\n\n    switch ((item->type) & 0xFF)\n    {\n        case cJSON_NULL:\n            output = ensure(output_buffer, 5);\n            if (output == NULL)\n            {\n                return false;\n            }\n            strcpy((char*)output, \"null\");\n            return true;\n\n        case cJSON_False:\n            output = ensure(output_buffer, 6);\n            if (output == NULL)\n            {\n                return false;\n            }\n            strcpy((char*)output, \"false\");\n            return true;\n\n        case cJSON_True:\n            output = ensure(output_buffer, 5);\n            if (output == NULL)\n            {\n                return false;\n            }\n            strcpy((char*)output, \"true\");\n            return true;\n\n        case cJSON_Number:\n            return print_number(item, output_buffer);\n\n        case cJSON_Raw:\n        {\n            size_t raw_length = 0;\n            if (item->valuestring == NULL)\n            {\n                return false;\n            }\n\n            raw_length = strlen(item->valuestring) + sizeof(\"\");\n            output = ensure(output_buffer, raw_length);\n            if (output == NULL)\n            {\n                return false;\n            }\n            memcpy(output, item->valuestring, raw_length);\n            return true;\n        }\n\n        case cJSON_String:\n            return print_string(item, output_buffer);\n\n        case cJSON_Array:\n            return print_array(item, output_buffer);\n\n        case cJSON_Object:\n            return print_object(item, output_buffer);\n\n        default:\n            return false;\n    }\n}\n\n/* Build an array from input text. */\nstatic cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)\n{\n    cJSON *head = NULL; /* head of the linked list */\n    cJSON *current_item = NULL;\n\n    if (input_buffer->depth >= CJSON_NESTING_LIMIT)\n    {\n        return false; /* to deeply nested */\n    }\n    input_buffer->depth++;\n\n    if (buffer_at_offset(input_buffer)[0] != '[')\n    {\n        /* not an array */\n        goto fail;\n    }\n\n    input_buffer->offset++;\n    buffer_skip_whitespace(input_buffer);\n    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))\n    {\n        /* empty array */\n        goto success;\n    }\n\n    /* check if we skipped to the end of the buffer */\n    if (cannot_access_at_index(input_buffer, 0))\n    {\n        input_buffer->offset--;\n        goto fail;\n    }\n\n    /* step back to character in front of the first element */\n    input_buffer->offset--;\n    /* loop through the comma separated array elements */\n    do\n    {\n        /* allocate next item */\n        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));\n        if (new_item == NULL)\n        {\n            goto fail; /* allocation failure */\n        }\n\n        /* attach next item to list */\n        if (head == NULL)\n        {\n            /* start the linked list */\n            current_item = head = new_item;\n        }\n        else\n        {\n            /* add to the end and advance */\n            current_item->next = new_item;\n            new_item->prev = current_item;\n            current_item = new_item;\n        }\n\n        /* parse next value */\n        input_buffer->offset++;\n        buffer_skip_whitespace(input_buffer);\n        if (!parse_value(current_item, input_buffer))\n        {\n            goto fail; /* failed to parse value */\n        }\n        buffer_skip_whitespace(input_buffer);\n    }\n    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));\n\n    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')\n    {\n        goto fail; /* expected end of array */\n    }\n\nsuccess:\n    input_buffer->depth--;\n\n    if (head != NULL) {\n        head->prev = current_item;\n    }\n\n    item->type = cJSON_Array;\n    item->child = head;\n\n    input_buffer->offset++;\n\n    return true;\n\nfail:\n    if (head != NULL)\n    {\n        cJSON_Delete(head);\n    }\n\n    return false;\n}\n\n/* Render an array to text */\nstatic cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)\n{\n    unsigned char *output_pointer = NULL;\n    size_t length = 0;\n    cJSON *current_element = item->child;\n\n    if (output_buffer == NULL)\n    {\n        return false;\n    }\n\n    /* Compose the output array. */\n    /* opening square bracket */\n    output_pointer = ensure(output_buffer, 1);\n    if (output_pointer == NULL)\n    {\n        return false;\n    }\n\n    *output_pointer = '[';\n    output_buffer->offset++;\n    output_buffer->depth++;\n\n    while (current_element != NULL)\n    {\n        if (!print_value(current_element, output_buffer))\n        {\n            return false;\n        }\n        update_offset(output_buffer);\n        if (current_element->next)\n        {\n            length = (size_t) (output_buffer->format ? 2 : 1);\n            output_pointer = ensure(output_buffer, length + 1);\n            if (output_pointer == NULL)\n            {\n                return false;\n            }\n            *output_pointer++ = ',';\n            if(output_buffer->format)\n            {\n                *output_pointer++ = ' ';\n            }\n            *output_pointer = '\\0';\n            output_buffer->offset += length;\n        }\n        current_element = current_element->next;\n    }\n\n    output_pointer = ensure(output_buffer, 2);\n    if (output_pointer == NULL)\n    {\n        return false;\n    }\n    *output_pointer++ = ']';\n    *output_pointer = '\\0';\n    output_buffer->depth--;\n\n    return true;\n}\n\n/* Build an object from the text. */\nstatic cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)\n{\n    cJSON *head = NULL; /* linked list head */\n    cJSON *current_item = NULL;\n\n    if (input_buffer->depth >= CJSON_NESTING_LIMIT)\n    {\n        return false; /* to deeply nested */\n    }\n    input_buffer->depth++;\n\n    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))\n    {\n        goto fail; /* not an object */\n    }\n\n    input_buffer->offset++;\n    buffer_skip_whitespace(input_buffer);\n    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))\n    {\n        goto success; /* empty object */\n    }\n\n    /* check if we skipped to the end of the buffer */\n    if (cannot_access_at_index(input_buffer, 0))\n    {\n        input_buffer->offset--;\n        goto fail;\n    }\n\n    /* step back to character in front of the first element */\n    input_buffer->offset--;\n    /* loop through the comma separated array elements */\n    do\n    {\n        /* allocate next item */\n        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));\n        if (new_item == NULL)\n        {\n            goto fail; /* allocation failure */\n        }\n\n        /* attach next item to list */\n        if (head == NULL)\n        {\n            /* start the linked list */\n            current_item = head = new_item;\n        }\n        else\n        {\n            /* add to the end and advance */\n            current_item->next = new_item;\n            new_item->prev = current_item;\n            current_item = new_item;\n        }\n\n        /* parse the name of the child */\n        input_buffer->offset++;\n        buffer_skip_whitespace(input_buffer);\n        if (!parse_string(current_item, input_buffer))\n        {\n            goto fail; /* failed to parse name */\n        }\n        buffer_skip_whitespace(input_buffer);\n\n        /* swap valuestring and string, because we parsed the name */\n        current_item->string = current_item->valuestring;\n        current_item->valuestring = NULL;\n\n        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))\n        {\n            goto fail; /* invalid object */\n        }\n\n        /* parse the value */\n        input_buffer->offset++;\n        buffer_skip_whitespace(input_buffer);\n        if (!parse_value(current_item, input_buffer))\n        {\n            goto fail; /* failed to parse value */\n        }\n        buffer_skip_whitespace(input_buffer);\n    }\n    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));\n\n    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))\n    {\n        goto fail; /* expected end of object */\n    }\n\nsuccess:\n    input_buffer->depth--;\n\n    if (head != NULL) {\n        head->prev = current_item;\n    }\n\n    item->type = cJSON_Object;\n    item->child = head;\n\n    input_buffer->offset++;\n    return true;\n\nfail:\n    if (head != NULL)\n    {\n        cJSON_Delete(head);\n    }\n\n    return false;\n}\n\n/* Render an object to text. */\nstatic cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)\n{\n    unsigned char *output_pointer = NULL;\n    size_t length = 0;\n    cJSON *current_item = item->child;\n\n    if (output_buffer == NULL)\n    {\n        return false;\n    }\n\n    /* Compose the output: */\n    length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\\n */\n    output_pointer = ensure(output_buffer, length + 1);\n    if (output_pointer == NULL)\n    {\n        return false;\n    }\n\n    *output_pointer++ = '{';\n    output_buffer->depth++;\n    if (output_buffer->format)\n    {\n        *output_pointer++ = '\\n';\n    }\n    output_buffer->offset += length;\n\n    while (current_item)\n    {\n        if (output_buffer->format)\n        {\n            size_t i;\n            output_pointer = ensure(output_buffer, output_buffer->depth);\n            if (output_pointer == NULL)\n            {\n                return false;\n            }\n            for (i = 0; i < output_buffer->depth; i++)\n            {\n                *output_pointer++ = '\\t';\n            }\n            output_buffer->offset += output_buffer->depth;\n        }\n\n        /* print key */\n        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))\n        {\n            return false;\n        }\n        update_offset(output_buffer);\n\n        length = (size_t) (output_buffer->format ? 2 : 1);\n        output_pointer = ensure(output_buffer, length);\n        if (output_pointer == NULL)\n        {\n            return false;\n        }\n        *output_pointer++ = ':';\n        if (output_buffer->format)\n        {\n            *output_pointer++ = '\\t';\n        }\n        output_buffer->offset += length;\n\n        /* print value */\n        if (!print_value(current_item, output_buffer))\n        {\n            return false;\n        }\n        update_offset(output_buffer);\n\n        /* print comma if not last */\n        length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));\n        output_pointer = ensure(output_buffer, length + 1);\n        if (output_pointer == NULL)\n        {\n            return false;\n        }\n        if (current_item->next)\n        {\n            *output_pointer++ = ',';\n        }\n\n        if (output_buffer->format)\n        {\n            *output_pointer++ = '\\n';\n        }\n        *output_pointer = '\\0';\n        output_buffer->offset += length;\n\n        current_item = current_item->next;\n    }\n\n    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);\n    if (output_pointer == NULL)\n    {\n        return false;\n    }\n    if (output_buffer->format)\n    {\n        size_t i;\n        for (i = 0; i < (output_buffer->depth - 1); i++)\n        {\n            *output_pointer++ = '\\t';\n        }\n    }\n    *output_pointer++ = '}';\n    *output_pointer = '\\0';\n    output_buffer->depth--;\n\n    return true;\n}\n\n/* Get Array size/item / object item. */\nCJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)\n{\n    cJSON *child = NULL;\n    size_t size = 0;\n\n    if (array == NULL)\n    {\n        return 0;\n    }\n\n    child = array->child;\n\n    while(child != NULL)\n    {\n        size++;\n        child = child->next;\n    }\n\n    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */\n\n    return (int)size;\n}\n\nstatic cJSON* get_array_item(const cJSON *array, size_t index)\n{\n    cJSON *current_child = NULL;\n\n    if (array == NULL)\n    {\n        return NULL;\n    }\n\n    current_child = array->child;\n    while ((current_child != NULL) && (index > 0))\n    {\n        index--;\n        current_child = current_child->next;\n    }\n\n    return current_child;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)\n{\n    if (index < 0)\n    {\n        return NULL;\n    }\n\n    return get_array_item(array, (size_t)index);\n}\n\nstatic cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)\n{\n    cJSON *current_element = NULL;\n\n    if ((object == NULL) || (name == NULL))\n    {\n        return NULL;\n    }\n\n    current_element = object->child;\n    if (case_sensitive)\n    {\n        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))\n        {\n            current_element = current_element->next;\n        }\n    }\n    else\n    {\n        while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))\n        {\n            current_element = current_element->next;\n        }\n    }\n\n    if ((current_element == NULL) || (current_element->string == NULL)) {\n        return NULL;\n    }\n\n    return current_element;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)\n{\n    return get_object_item(object, string, false);\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)\n{\n    return get_object_item(object, string, true);\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)\n{\n    return cJSON_GetObjectItem(object, string) ? 1 : 0;\n}\n\n/* Utility for array list handling. */\nstatic void suffix_object(cJSON *prev, cJSON *item)\n{\n    prev->next = item;\n    item->prev = prev;\n}\n\n/* Utility for handling references. */\nstatic cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)\n{\n    cJSON *reference = NULL;\n    if (item == NULL)\n    {\n        return NULL;\n    }\n\n    reference = cJSON_New_Item(hooks);\n    if (reference == NULL)\n    {\n        return NULL;\n    }\n\n    memcpy(reference, item, sizeof(cJSON));\n    reference->string = NULL;\n    reference->type |= cJSON_IsReference;\n    reference->next = reference->prev = NULL;\n    return reference;\n}\n\nstatic cJSON_bool add_item_to_array(cJSON *array, cJSON *item)\n{\n    cJSON *child = NULL;\n\n    if ((item == NULL) || (array == NULL) || (array == item))\n    {\n        return false;\n    }\n\n    child = array->child;\n    /*\n     * To find the last item in array quickly, we use prev in array\n     */\n    if (child == NULL)\n    {\n        /* list is empty, start new one */\n        array->child = item;\n        item->prev = item;\n        item->next = NULL;\n    }\n    else\n    {\n        /* append to the end */\n        if (child->prev)\n        {\n            suffix_object(child->prev, item);\n            array->child->prev = item;\n        }\n    }\n\n    return true;\n}\n\n/* Add item to array/object. */\nCJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)\n{\n    return add_item_to_array(array, item);\n}\n\n#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))\n    #pragma GCC diagnostic push\n#endif\n#ifdef __GNUC__\n#pragma GCC diagnostic ignored \"-Wcast-qual\"\n#endif\n/* helper function to cast away const */\nstatic void* cast_away_const(const void* string)\n{\n    return (void*)string;\n}\n#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))\n    #pragma GCC diagnostic pop\n#endif\n\n\nstatic cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)\n{\n    char *new_key = NULL;\n    int new_type = cJSON_Invalid;\n\n    if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))\n    {\n        return false;\n    }\n\n    if (constant_key)\n    {\n        new_key = (char*)cast_away_const(string);\n        new_type = item->type | cJSON_StringIsConst;\n    }\n    else\n    {\n        new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);\n        if (new_key == NULL)\n        {\n            return false;\n        }\n\n        new_type = item->type & ~cJSON_StringIsConst;\n    }\n\n    if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))\n    {\n        hooks->deallocate(item->string);\n    }\n\n    item->string = new_key;\n    item->type = new_type;\n\n    return add_item_to_array(object, item);\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)\n{\n    return add_item_to_object(object, string, item, &global_hooks, false);\n}\n\n/* Add an item to an object with constant string as key */\nCJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)\n{\n    return add_item_to_object(object, string, item, &global_hooks, true);\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)\n{\n    if (array == NULL)\n    {\n        return false;\n    }\n\n    return add_item_to_array(array, create_reference(item, &global_hooks));\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)\n{\n    if ((object == NULL) || (string == NULL))\n    {\n        return false;\n    }\n\n    return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);\n}\n\nCJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)\n{\n    cJSON *null = cJSON_CreateNull();\n    if (add_item_to_object(object, name, null, &global_hooks, false))\n    {\n        return null;\n    }\n\n    cJSON_Delete(null);\n    return NULL;\n}\n\nCJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)\n{\n    cJSON *true_item = cJSON_CreateTrue();\n    if (add_item_to_object(object, name, true_item, &global_hooks, false))\n    {\n        return true_item;\n    }\n\n    cJSON_Delete(true_item);\n    return NULL;\n}\n\nCJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)\n{\n    cJSON *false_item = cJSON_CreateFalse();\n    if (add_item_to_object(object, name, false_item, &global_hooks, false))\n    {\n        return false_item;\n    }\n\n    cJSON_Delete(false_item);\n    return NULL;\n}\n\nCJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)\n{\n    cJSON *bool_item = cJSON_CreateBool(boolean);\n    if (add_item_to_object(object, name, bool_item, &global_hooks, false))\n    {\n        return bool_item;\n    }\n\n    cJSON_Delete(bool_item);\n    return NULL;\n}\n\nCJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)\n{\n    cJSON *number_item = cJSON_CreateNumber(number);\n    if (add_item_to_object(object, name, number_item, &global_hooks, false))\n    {\n        return number_item;\n    }\n\n    cJSON_Delete(number_item);\n    return NULL;\n}\n\nCJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)\n{\n    cJSON *string_item = cJSON_CreateString(string);\n    if (add_item_to_object(object, name, string_item, &global_hooks, false))\n    {\n        return string_item;\n    }\n\n    cJSON_Delete(string_item);\n    return NULL;\n}\n\nCJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)\n{\n    cJSON *raw_item = cJSON_CreateRaw(raw);\n    if (add_item_to_object(object, name, raw_item, &global_hooks, false))\n    {\n        return raw_item;\n    }\n\n    cJSON_Delete(raw_item);\n    return NULL;\n}\n\nCJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)\n{\n    cJSON *object_item = cJSON_CreateObject();\n    if (add_item_to_object(object, name, object_item, &global_hooks, false))\n    {\n        return object_item;\n    }\n\n    cJSON_Delete(object_item);\n    return NULL;\n}\n\nCJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)\n{\n    cJSON *array = cJSON_CreateArray();\n    if (add_item_to_object(object, name, array, &global_hooks, false))\n    {\n        return array;\n    }\n\n    cJSON_Delete(array);\n    return NULL;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)\n{\n    if ((parent == NULL) || (item == NULL))\n    {\n        return NULL;\n    }\n\n    if (item != parent->child)\n    {\n        /* not the first element */\n        item->prev->next = item->next;\n    }\n    if (item->next != NULL)\n    {\n        /* not the last element */\n        item->next->prev = item->prev;\n    }\n\n    if (item == parent->child)\n    {\n        /* first element */\n        parent->child = item->next;\n    }\n    else if (item->next == NULL)\n    {\n        /* last element */\n        parent->child->prev = item->prev;\n    }\n\n    /* make sure the detached item doesn't point anywhere anymore */\n    item->prev = NULL;\n    item->next = NULL;\n\n    return item;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)\n{\n    if (which < 0)\n    {\n        return NULL;\n    }\n\n    return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));\n}\n\nCJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)\n{\n    cJSON_Delete(cJSON_DetachItemFromArray(array, which));\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)\n{\n    cJSON *to_detach = cJSON_GetObjectItem(object, string);\n\n    return cJSON_DetachItemViaPointer(object, to_detach);\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)\n{\n    cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);\n\n    return cJSON_DetachItemViaPointer(object, to_detach);\n}\n\nCJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)\n{\n    cJSON_Delete(cJSON_DetachItemFromObject(object, string));\n}\n\nCJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)\n{\n    cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));\n}\n\n/* Replace array/object items with new ones. */\nCJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)\n{\n    cJSON *after_inserted = NULL;\n\n    if (which < 0 || newitem == NULL)\n    {\n        return false;\n    }\n\n    after_inserted = get_array_item(array, (size_t)which);\n    if (after_inserted == NULL)\n    {\n        return add_item_to_array(array, newitem);\n    }\n\n    if (after_inserted != array->child && after_inserted->prev == NULL) {\n        /* return false if after_inserted is a corrupted array item */\n        return false;\n    }\n\n    newitem->next = after_inserted;\n    newitem->prev = after_inserted->prev;\n    after_inserted->prev = newitem;\n    if (after_inserted == array->child)\n    {\n        array->child = newitem;\n    }\n    else\n    {\n        newitem->prev->next = newitem;\n    }\n    return true;\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)\n{\n    if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL))\n    {\n        return false;\n    }\n\n    if (replacement == item)\n    {\n        return true;\n    }\n\n    replacement->next = item->next;\n    replacement->prev = item->prev;\n\n    if (replacement->next != NULL)\n    {\n        replacement->next->prev = replacement;\n    }\n    if (parent->child == item)\n    {\n        if (parent->child->prev == parent->child)\n        {\n            replacement->prev = replacement;\n        }\n        parent->child = replacement;\n    }\n    else\n    {   /*\n         * To find the last item in array quickly, we use prev in array.\n         * We can't modify the last item's next pointer where this item was the parent's child\n         */\n        if (replacement->prev != NULL)\n        {\n            replacement->prev->next = replacement;\n        }\n        if (replacement->next == NULL)\n        {\n            parent->child->prev = replacement;\n        }\n    }\n\n    item->next = NULL;\n    item->prev = NULL;\n    cJSON_Delete(item);\n\n    return true;\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)\n{\n    if (which < 0)\n    {\n        return false;\n    }\n\n    return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);\n}\n\nstatic cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)\n{\n    if ((replacement == NULL) || (string == NULL))\n    {\n        return false;\n    }\n\n    /* replace the name in the replacement */\n    if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))\n    {\n        cJSON_free(replacement->string);\n    }\n    replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);\n    if (replacement->string == NULL)\n    {\n        return false;\n    }\n\n    replacement->type &= ~cJSON_StringIsConst;\n\n    return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)\n{\n    return replace_item_in_object(object, string, newitem, false);\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)\n{\n    return replace_item_in_object(object, string, newitem, true);\n}\n\n/* Create basic types: */\nCJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)\n{\n    cJSON *item = cJSON_New_Item(&global_hooks);\n    if(item)\n    {\n        item->type = cJSON_NULL;\n    }\n\n    return item;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)\n{\n    cJSON *item = cJSON_New_Item(&global_hooks);\n    if(item)\n    {\n        item->type = cJSON_True;\n    }\n\n    return item;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)\n{\n    cJSON *item = cJSON_New_Item(&global_hooks);\n    if(item)\n    {\n        item->type = cJSON_False;\n    }\n\n    return item;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)\n{\n    cJSON *item = cJSON_New_Item(&global_hooks);\n    if(item)\n    {\n        item->type = boolean ? cJSON_True : cJSON_False;\n    }\n\n    return item;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)\n{\n    cJSON *item = cJSON_New_Item(&global_hooks);\n    if(item)\n    {\n        item->type = cJSON_Number;\n        item->valuedouble = num;\n\n        /* use saturation in case of overflow */\n        if (num >= INT_MAX)\n        {\n            item->valueint = INT_MAX;\n        }\n        else if (num <= (double)INT_MIN)\n        {\n            item->valueint = INT_MIN;\n        }\n        else\n        {\n            item->valueint = (int)num;\n        }\n    }\n\n    return item;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)\n{\n    cJSON *item = cJSON_New_Item(&global_hooks);\n    if(item)\n    {\n        item->type = cJSON_String;\n        item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);\n        if(!item->valuestring)\n        {\n            cJSON_Delete(item);\n            return NULL;\n        }\n    }\n\n    return item;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)\n{\n    cJSON *item = cJSON_New_Item(&global_hooks);\n    if (item != NULL)\n    {\n        item->type = cJSON_String | cJSON_IsReference;\n        item->valuestring = (char*)cast_away_const(string);\n    }\n\n    return item;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)\n{\n    cJSON *item = cJSON_New_Item(&global_hooks);\n    if (item != NULL) {\n        item->type = cJSON_Object | cJSON_IsReference;\n        item->child = (cJSON*)cast_away_const(child);\n    }\n\n    return item;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {\n    cJSON *item = cJSON_New_Item(&global_hooks);\n    if (item != NULL) {\n        item->type = cJSON_Array | cJSON_IsReference;\n        item->child = (cJSON*)cast_away_const(child);\n    }\n\n    return item;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)\n{\n    cJSON *item = cJSON_New_Item(&global_hooks);\n    if(item)\n    {\n        item->type = cJSON_Raw;\n        item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);\n        if(!item->valuestring)\n        {\n            cJSON_Delete(item);\n            return NULL;\n        }\n    }\n\n    return item;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)\n{\n    cJSON *item = cJSON_New_Item(&global_hooks);\n    if(item)\n    {\n        item->type=cJSON_Array;\n    }\n\n    return item;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)\n{\n    cJSON *item = cJSON_New_Item(&global_hooks);\n    if (item)\n    {\n        item->type = cJSON_Object;\n    }\n\n    return item;\n}\n\n/* Create Arrays: */\nCJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)\n{\n    size_t i = 0;\n    cJSON *n = NULL;\n    cJSON *p = NULL;\n    cJSON *a = NULL;\n\n    if ((count < 0) || (numbers == NULL))\n    {\n        return NULL;\n    }\n\n    a = cJSON_CreateArray();\n\n    for(i = 0; a && (i < (size_t)count); i++)\n    {\n        n = cJSON_CreateNumber(numbers[i]);\n        if (!n)\n        {\n            cJSON_Delete(a);\n            return NULL;\n        }\n        if(!i)\n        {\n            a->child = n;\n        }\n        else\n        {\n            suffix_object(p, n);\n        }\n        p = n;\n    }\n\n    if (a && a->child) {\n        a->child->prev = n;\n    }\n\n    return a;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)\n{\n    size_t i = 0;\n    cJSON *n = NULL;\n    cJSON *p = NULL;\n    cJSON *a = NULL;\n\n    if ((count < 0) || (numbers == NULL))\n    {\n        return NULL;\n    }\n\n    a = cJSON_CreateArray();\n\n    for(i = 0; a && (i < (size_t)count); i++)\n    {\n        n = cJSON_CreateNumber((double)numbers[i]);\n        if(!n)\n        {\n            cJSON_Delete(a);\n            return NULL;\n        }\n        if(!i)\n        {\n            a->child = n;\n        }\n        else\n        {\n            suffix_object(p, n);\n        }\n        p = n;\n    }\n\n    if (a && a->child) {\n        a->child->prev = n;\n    }\n\n    return a;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)\n{\n    size_t i = 0;\n    cJSON *n = NULL;\n    cJSON *p = NULL;\n    cJSON *a = NULL;\n\n    if ((count < 0) || (numbers == NULL))\n    {\n        return NULL;\n    }\n\n    a = cJSON_CreateArray();\n\n    for(i = 0; a && (i < (size_t)count); i++)\n    {\n        n = cJSON_CreateNumber(numbers[i]);\n        if(!n)\n        {\n            cJSON_Delete(a);\n            return NULL;\n        }\n        if(!i)\n        {\n            a->child = n;\n        }\n        else\n        {\n            suffix_object(p, n);\n        }\n        p = n;\n    }\n\n    if (a && a->child) {\n        a->child->prev = n;\n    }\n\n    return a;\n}\n\nCJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)\n{\n    size_t i = 0;\n    cJSON *n = NULL;\n    cJSON *p = NULL;\n    cJSON *a = NULL;\n\n    if ((count < 0) || (strings == NULL))\n    {\n        return NULL;\n    }\n\n    a = cJSON_CreateArray();\n\n    for (i = 0; a && (i < (size_t)count); i++)\n    {\n        n = cJSON_CreateString(strings[i]);\n        if(!n)\n        {\n            cJSON_Delete(a);\n            return NULL;\n        }\n        if(!i)\n        {\n            a->child = n;\n        }\n        else\n        {\n            suffix_object(p,n);\n        }\n        p = n;\n    }\n\n    if (a && a->child) {\n        a->child->prev = n;\n    }\n\n    return a;\n}\n\n/* Duplication */\nCJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)\n{\n    cJSON *newitem = NULL;\n    cJSON *child = NULL;\n    cJSON *next = NULL;\n    cJSON *newchild = NULL;\n\n    /* Bail on bad ptr */\n    if (!item)\n    {\n        goto fail;\n    }\n    /* Create new item */\n    newitem = cJSON_New_Item(&global_hooks);\n    if (!newitem)\n    {\n        goto fail;\n    }\n    /* Copy over all vars */\n    newitem->type = item->type & (~cJSON_IsReference);\n    newitem->valueint = item->valueint;\n    newitem->valuedouble = item->valuedouble;\n    if (item->valuestring)\n    {\n        newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);\n        if (!newitem->valuestring)\n        {\n            goto fail;\n        }\n    }\n    if (item->string)\n    {\n        newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);\n        if (!newitem->string)\n        {\n            goto fail;\n        }\n    }\n    /* If non-recursive, then we're done! */\n    if (!recurse)\n    {\n        return newitem;\n    }\n    /* Walk the ->next chain for the child. */\n    child = item->child;\n    while (child != NULL)\n    {\n        newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */\n        if (!newchild)\n        {\n            goto fail;\n        }\n        if (next != NULL)\n        {\n            /* If newitem->child already set, then crosswire ->prev and ->next and move on */\n            next->next = newchild;\n            newchild->prev = next;\n            next = newchild;\n        }\n        else\n        {\n            /* Set newitem->child and move to it */\n            newitem->child = newchild;\n            next = newchild;\n        }\n        child = child->next;\n    }\n    if (newitem && newitem->child)\n    {\n        newitem->child->prev = newchild;\n    }\n\n    return newitem;\n\nfail:\n    if (newitem != NULL)\n    {\n        cJSON_Delete(newitem);\n    }\n\n    return NULL;\n}\n\nstatic void skip_oneline_comment(char **input)\n{\n    *input += static_strlen(\"//\");\n\n    for (; (*input)[0] != '\\0'; ++(*input))\n    {\n        if ((*input)[0] == '\\n') {\n            *input += static_strlen(\"\\n\");\n            return;\n        }\n    }\n}\n\nstatic void skip_multiline_comment(char **input)\n{\n    *input += static_strlen(\"/*\");\n\n    for (; (*input)[0] != '\\0'; ++(*input))\n    {\n        if (((*input)[0] == '*') && ((*input)[1] == '/'))\n        {\n            *input += static_strlen(\"*/\");\n            return;\n        }\n    }\n}\n\nstatic void minify_string(char **input, char **output) {\n    (*output)[0] = (*input)[0];\n    *input += static_strlen(\"\\\"\");\n    *output += static_strlen(\"\\\"\");\n\n\n    for (; (*input)[0] != '\\0'; (void)++(*input), ++(*output)) {\n        (*output)[0] = (*input)[0];\n\n        if ((*input)[0] == '\\\"') {\n            (*output)[0] = '\\\"';\n            *input += static_strlen(\"\\\"\");\n            *output += static_strlen(\"\\\"\");\n            return;\n        } else if (((*input)[0] == '\\\\') && ((*input)[1] == '\\\"')) {\n            (*output)[1] = (*input)[1];\n            *input += static_strlen(\"\\\"\");\n            *output += static_strlen(\"\\\"\");\n        }\n    }\n}\n\nCJSON_PUBLIC(void) cJSON_Minify(char *json)\n{\n    char *into = json;\n\n    if (json == NULL)\n    {\n        return;\n    }\n\n    while (json[0] != '\\0')\n    {\n        switch (json[0])\n        {\n            case ' ':\n            case '\\t':\n            case '\\r':\n            case '\\n':\n                json++;\n                break;\n\n            case '/':\n                if (json[1] == '/')\n                {\n                    skip_oneline_comment(&json);\n                }\n                else if (json[1] == '*')\n                {\n                    skip_multiline_comment(&json);\n                } else {\n                    json++;\n                }\n                break;\n\n            case '\\\"':\n                minify_string(&json, (char**)&into);\n                break;\n\n            default:\n                into[0] = json[0];\n                json++;\n                into++;\n        }\n    }\n\n    /* and null-terminate. */\n    *into = '\\0';\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)\n{\n    if (item == NULL)\n    {\n        return false;\n    }\n\n    return (item->type & 0xFF) == cJSON_Invalid;\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)\n{\n    if (item == NULL)\n    {\n        return false;\n    }\n\n    return (item->type & 0xFF) == cJSON_False;\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)\n{\n    if (item == NULL)\n    {\n        return false;\n    }\n\n    return (item->type & 0xff) == cJSON_True;\n}\n\n\nCJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)\n{\n    if (item == NULL)\n    {\n        return false;\n    }\n\n    return (item->type & (cJSON_True | cJSON_False)) != 0;\n}\nCJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)\n{\n    if (item == NULL)\n    {\n        return false;\n    }\n\n    return (item->type & 0xFF) == cJSON_NULL;\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)\n{\n    if (item == NULL)\n    {\n        return false;\n    }\n\n    return (item->type & 0xFF) == cJSON_Number;\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)\n{\n    if (item == NULL)\n    {\n        return false;\n    }\n\n    return (item->type & 0xFF) == cJSON_String;\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)\n{\n    if (item == NULL)\n    {\n        return false;\n    }\n\n    return (item->type & 0xFF) == cJSON_Array;\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)\n{\n    if (item == NULL)\n    {\n        return false;\n    }\n\n    return (item->type & 0xFF) == cJSON_Object;\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)\n{\n    if (item == NULL)\n    {\n        return false;\n    }\n\n    return (item->type & 0xFF) == cJSON_Raw;\n}\n\nCJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)\n{\n    if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))\n    {\n        return false;\n    }\n\n    /* check if type is valid */\n    switch (a->type & 0xFF)\n    {\n        case cJSON_False:\n        case cJSON_True:\n        case cJSON_NULL:\n        case cJSON_Number:\n        case cJSON_String:\n        case cJSON_Raw:\n        case cJSON_Array:\n        case cJSON_Object:\n            break;\n\n        default:\n            return false;\n    }\n\n    /* identical objects are equal */\n    if (a == b)\n    {\n        return true;\n    }\n\n    switch (a->type & 0xFF)\n    {\n        /* in these cases and equal type is enough */\n        case cJSON_False:\n        case cJSON_True:\n        case cJSON_NULL:\n            return true;\n\n        case cJSON_Number:\n            if (compare_double(a->valuedouble, b->valuedouble))\n            {\n                return true;\n            }\n            return false;\n\n        case cJSON_String:\n        case cJSON_Raw:\n            if ((a->valuestring == NULL) || (b->valuestring == NULL))\n            {\n                return false;\n            }\n            if (strcmp(a->valuestring, b->valuestring) == 0)\n            {\n                return true;\n            }\n\n            return false;\n\n        case cJSON_Array:\n        {\n            cJSON *a_element = a->child;\n            cJSON *b_element = b->child;\n\n            for (; (a_element != NULL) && (b_element != NULL);)\n            {\n                if (!cJSON_Compare(a_element, b_element, case_sensitive))\n                {\n                    return false;\n                }\n\n                a_element = a_element->next;\n                b_element = b_element->next;\n            }\n\n            /* one of the arrays is longer than the other */\n            if (a_element != b_element) {\n                return false;\n            }\n\n            return true;\n        }\n\n        case cJSON_Object:\n        {\n            cJSON *a_element = NULL;\n            cJSON *b_element = NULL;\n            cJSON_ArrayForEach(a_element, a)\n            {\n                /* TODO This has O(n^2) runtime, which is horrible! */\n                b_element = get_object_item(b, a_element->string, case_sensitive);\n                if (b_element == NULL)\n                {\n                    return false;\n                }\n\n                if (!cJSON_Compare(a_element, b_element, case_sensitive))\n                {\n                    return false;\n                }\n            }\n\n            /* doing this twice, once on a and b to prevent true comparison if a subset of b\n             * TODO: Do this the proper way, this is just a fix for now */\n            cJSON_ArrayForEach(b_element, b)\n            {\n                a_element = get_object_item(a, b_element->string, case_sensitive);\n                if (a_element == NULL)\n                {\n                    return false;\n                }\n\n                if (!cJSON_Compare(b_element, a_element, case_sensitive))\n                {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        default:\n            return false;\n    }\n}\n\nCJSON_PUBLIC(void *) cJSON_malloc(size_t size)\n{\n    return global_hooks.allocate(size);\n}\n\nCJSON_PUBLIC(void) cJSON_free(void *object)\n{\n    global_hooks.deallocate(object);\n}\n"
  },
  {
    "path": "thirdparty/cJSON/cJSON.h",
    "content": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files (the \"Software\"), to deal\n  in the Software without restriction, including without limitation the rights\n  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  copies of the Software, and to permit persons to whom the Software is\n  furnished to do so, subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  THE SOFTWARE.\n*/\n\n#ifndef cJSON__h\n#define cJSON__h\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))\n#define __WINDOWS__\n#endif\n\n#ifdef __WINDOWS__\n\n/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention.  For windows you have 3 define options:\n\nCJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols\nCJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)\nCJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol\n\nFor *nix builds that support visibility attribute, you can define similar behavior by\n\nsetting default visibility to hidden by adding\n-fvisibility=hidden (for gcc)\nor\n-xldscope=hidden (for sun cc)\nto CFLAGS\n\nthen using the CJSON_API_VISIBILITY flag to \"export\" the same symbols the way CJSON_EXPORT_SYMBOLS does\n\n*/\n\n#define CJSON_CDECL __cdecl\n#define CJSON_STDCALL __stdcall\n\n/* export symbols by default, this is necessary for copy pasting the C and header file */\n#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)\n#define CJSON_EXPORT_SYMBOLS\n#endif\n\n#if defined(CJSON_HIDE_SYMBOLS)\n#define CJSON_PUBLIC(type)   type CJSON_STDCALL\n#elif defined(CJSON_EXPORT_SYMBOLS)\n#define CJSON_PUBLIC(type)   __declspec(dllexport) type CJSON_STDCALL\n#elif defined(CJSON_IMPORT_SYMBOLS)\n#define CJSON_PUBLIC(type)   __declspec(dllimport) type CJSON_STDCALL\n#endif\n#else /* !__WINDOWS__ */\n#define CJSON_CDECL\n#define CJSON_STDCALL\n\n#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)\n#define CJSON_PUBLIC(type)   __attribute__((visibility(\"default\"))) type\n#else\n#define CJSON_PUBLIC(type) type\n#endif\n#endif\n\n/* project version */\n#define CJSON_VERSION_MAJOR 1\n#define CJSON_VERSION_MINOR 7\n#define CJSON_VERSION_PATCH 17\n\n#include <stddef.h>\n\n/* cJSON Types: */\n#define cJSON_Invalid (0)\n#define cJSON_False  (1 << 0)\n#define cJSON_True   (1 << 1)\n#define cJSON_NULL   (1 << 2)\n#define cJSON_Number (1 << 3)\n#define cJSON_String (1 << 4)\n#define cJSON_Array  (1 << 5)\n#define cJSON_Object (1 << 6)\n#define cJSON_Raw    (1 << 7) /* raw json */\n\n#define cJSON_IsReference 256\n#define cJSON_StringIsConst 512\n\n/* The cJSON structure: */\ntypedef struct cJSON\n{\n    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */\n    struct cJSON *next;\n    struct cJSON *prev;\n    /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */\n    struct cJSON *child;\n\n    /* The type of the item, as above. */\n    int type;\n\n    /* The item's string, if type==cJSON_String  and type == cJSON_Raw */\n    char *valuestring;\n    /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */\n    int valueint;\n    /* The item's number, if type==cJSON_Number */\n    double valuedouble;\n\n    /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */\n    char *string;\n} cJSON;\n\ntypedef struct cJSON_Hooks\n{\n      /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */\n      void *(CJSON_CDECL *malloc_fn)(size_t sz);\n      void (CJSON_CDECL *free_fn)(void *ptr);\n} cJSON_Hooks;\n\ntypedef int cJSON_bool;\n\n/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.\n * This is to prevent stack overflows. */\n#ifndef CJSON_NESTING_LIMIT\n#define CJSON_NESTING_LIMIT 1000\n#endif\n\n/* returns the version of cJSON as a string */\nCJSON_PUBLIC(const char*) cJSON_Version(void);\n\n/* Supply malloc, realloc and free functions to cJSON */\nCJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);\n\n/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */\n/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */\nCJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);\nCJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);\n/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */\n/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */\nCJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);\nCJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);\n\n/* Render a cJSON entity to text for transfer/storage. */\nCJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);\n/* Render a cJSON entity to text for transfer/storage without any formatting. */\nCJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);\n/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */\nCJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);\n/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */\n/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */\nCJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);\n/* Delete a cJSON entity and all subentities. */\nCJSON_PUBLIC(void) cJSON_Delete(cJSON *item);\n\n/* Returns the number of items in an array (or object). */\nCJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);\n/* Retrieve item number \"index\" from array \"array\". Returns NULL if unsuccessful. */\nCJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);\n/* Get item \"string\" from object. Case insensitive. */\nCJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);\nCJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);\nCJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);\n/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */\nCJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);\nCJSON_PUBLIC(size_t) cJSON_GetErrorPos(void);\n\n/* Check item type and return its value */\nCJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);\nCJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);\n\n/* These functions check the type of an item */\nCJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);\nCJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);\nCJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);\nCJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);\nCJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);\nCJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);\nCJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);\nCJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);\nCJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);\nCJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);\n\n/* These calls create a cJSON item of the appropriate type. */\nCJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);\nCJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);\nCJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);\nCJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);\nCJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);\nCJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);\n/* raw json */\nCJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);\nCJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);\nCJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);\n\n/* Create a string where valuestring references a string so\n * it will not be freed by cJSON_Delete */\nCJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);\n/* Create an object/array that only references it's elements so\n * they will not be freed by cJSON_Delete */\nCJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);\nCJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);\n\n/* These utilities create an Array of count items.\n * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/\nCJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);\nCJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);\nCJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);\nCJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);\n\n/* Append item to the specified array/object. */\nCJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);\nCJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);\n/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.\n * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before\n * writing to `item->string` */\nCJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);\n/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */\nCJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);\nCJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);\n\n/* Remove/Detach items from Arrays/Objects. */\nCJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);\nCJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);\nCJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);\nCJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);\nCJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);\nCJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);\nCJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);\n\n/* Update array items. */\nCJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */\nCJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);\nCJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);\nCJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);\nCJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);\n\n/* Duplicate a cJSON item */\nCJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);\n/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will\n * need to be released. With recurse!=0, it will duplicate any children connected to the item.\n * The item->next and ->prev pointers are always zero on return from Duplicate. */\n/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.\n * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */\nCJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);\n\n/* Minify a strings, remove blank characters(such as ' ', '\\t', '\\r', '\\n') from strings.\n * The input pointer json cannot point to a read-only address area, such as a string constant, \n * but should point to a readable and writable address area. */\nCJSON_PUBLIC(void) cJSON_Minify(char *json);\n\n/* Helper functions for creating and adding items to an object at the same time.\n * They return the added item or NULL on failure. */\nCJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);\nCJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);\nCJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);\nCJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);\nCJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);\nCJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);\nCJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);\nCJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);\nCJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);\n\n/* When assigning an integer value, it needs to be propagated to valuedouble too. */\n#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))\n/* helper for the cJSON_SetNumberValue macro */\nCJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);\n#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))\n/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */\nCJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);\n\n/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/\n#define cJSON_SetBoolValue(object, boolValue) ( \\\n    (object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \\\n    (object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \\\n    cJSON_Invalid\\\n)\n\n/* Macro for iterating over an array or object */\n#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)\n\n/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */\nCJSON_PUBLIC(void *) cJSON_malloc(size_t size);\nCJSON_PUBLIC(void) cJSON_free(void *object);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/fontstash/fontstash.h",
    "content": "//\n//  NOTE sokol: all IO functions have been removed\n//\n// Copyright (c) 2009-2013 Mikko Mononen memon@inside.org\n//\n// This software is provided 'as-is', without any express or implied\n// warranty.  In no event will the authors be held liable for any damages\n// arising from the use of this software.\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n// 1. The origin of this software must not be misrepresented; you must not\n//\tclaim that you wrote the original software. If you use this software\n//\tin a product, an acknowledgment in the product documentation would be\n//\tappreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n//\tmisrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n//\n\n#ifndef FONS_H\n#define FONS_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// To make the implementation private to the file that generates the implementation\n#ifdef FONS_STATIC\n#define FONS_DEF static\n#else\n#define FONS_DEF extern\n#endif\n\n#define FONS_INVALID -1\n\n#if !defined(FONTSTASH_MALLOC)\n#define FONTSTASH_MALLOC malloc\n#define FONTSTASH_REALLOC realloc\n#define FONTSTASH_FREE free\n// __v_ start\n#define FONTSTASH_MALLOC_ATOMIC malloc\n// __v_ end\n#endif\n\nenum FONSflags {\n\tFONS_ZERO_TOPLEFT = 1,\n\tFONS_ZERO_BOTTOMLEFT = 2,\n};\n\nenum FONSalign {\n\t// Horizontal align\n\tFONS_ALIGN_LEFT \t= 1<<0,\t// Default\n\tFONS_ALIGN_CENTER \t= 1<<1,\n\tFONS_ALIGN_RIGHT \t= 1<<2,\n\t// Vertical align\n\tFONS_ALIGN_TOP \t\t= 1<<3,\n\tFONS_ALIGN_MIDDLE\t= 1<<4,\n\tFONS_ALIGN_BOTTOM\t= 1<<5,\n\tFONS_ALIGN_BASELINE\t= 1<<6, // Default\n};\n\nenum FONSerrorCode {\n\t// Font atlas is full.\n\tFONS_ATLAS_FULL = 1,\n\t// Scratch memory used to render glyphs is full, requested size reported in 'val', you may need to bump up FONS_SCRATCH_BUF_SIZE.\n\tFONS_SCRATCH_FULL = 2,\n\t// Calls to fonsPushState has created too large stack, if you need deep state stack bump up FONS_MAX_STATES.\n\tFONS_STATES_OVERFLOW = 3,\n\t// Trying to pop too many states fonsPopState().\n\tFONS_STATES_UNDERFLOW = 4,\n};\n\nstruct FONSparams {\n\tint width, height;\n\tunsigned char flags;\n\tvoid* userPtr;\n\tint (*renderCreate)(void* uptr, int width, int height);\n\tint (*renderResize)(void* uptr, int width, int height);\n\tvoid (*renderUpdate)(void* uptr, int* rect, const unsigned char* data);\n\tvoid (*renderDraw)(void* uptr, const float* verts, const float* tcoords, const unsigned int* colors, int nverts);\n\tvoid (*renderDelete)(void* uptr);\n};\ntypedef struct FONSparams FONSparams;\n\nstruct FONSquad\n{\n\tfloat x0,y0,s0,t0;\n\tfloat x1,y1,s1,t1;\n};\ntypedef struct FONSquad FONSquad;\n\nstruct FONStextIter {\n\tfloat x, y, nextx, nexty, scale, spacing;\n\tunsigned int codepoint;\n\tshort isize, iblur;\n\tstruct FONSfont* font;\n\tint prevGlyphIndex;\n\tconst char* str;\n\tconst char* next;\n\tconst char* end;\n\tunsigned int utf8state;\n};\ntypedef struct FONStextIter FONStextIter;\n\ntypedef struct FONScontext FONScontext;\n\n// Constructor and destructor.\nFONS_DEF FONScontext* fonsCreateInternal(FONSparams* params);\nFONS_DEF void fonsDeleteInternal(FONScontext* s);\n\nFONS_DEF void fonsSetErrorCallback(FONScontext* s, void (*callback)(void* uptr, int error, int val), void* uptr);\n// Returns current atlas size.\nFONS_DEF void fonsGetAtlasSize(FONScontext* s, int* width, int* height);\n// Expands the atlas size.\nFONS_DEF int fonsExpandAtlas(FONScontext* s, int width, int height);\n// Resets the whole stash.\nFONS_DEF int fonsResetAtlas(FONScontext* stash, int width, int height);\n\n// Add fonts\nFONS_DEF int fonsGetFontByName(FONScontext* s, const char* name);\nFONS_DEF int fonsAddFallbackFont(FONScontext* stash, int base, int fallback);\n\n// State handling\nFONS_DEF void fonsPushState(FONScontext* s);\nFONS_DEF void fonsPopState(FONScontext* s);\nFONS_DEF void fonsClearState(FONScontext* s);\n\n// State setting\nFONS_DEF void fonsSetSize(FONScontext* s, float size);\nFONS_DEF void fonsSetColor(FONScontext* s, unsigned int color);\nFONS_DEF void fonsSetSpacing(FONScontext* s, float spacing);\nFONS_DEF void fonsSetBlur(FONScontext* s, float blur);\nFONS_DEF void fonsSetAlign(FONScontext* s, int align);\nFONS_DEF void fonsSetFont(FONScontext* s, int font);\n\n// Draw text\nFONS_DEF float fonsDrawText(FONScontext* s, float x, float y, const char* string, const char* end);\n\n// Measure text\nFONS_DEF float fonsTextBounds(FONScontext* s, float x, float y, const char* string, const char* end, float* bounds);\nFONS_DEF void fonsLineBounds(FONScontext* s, float y, float* miny, float* maxy);\nFONS_DEF void fonsVertMetrics(FONScontext* s, float* ascender, float* descender, float* lineh);\n\n// Text iterator\nFONS_DEF int fonsTextIterInit(FONScontext* stash, FONStextIter* iter, float x, float y, const char* str, const char* end);\nFONS_DEF int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, struct FONSquad* quad);\n\n// Pull texture changes\nFONS_DEF const unsigned char* fonsGetTextureData(FONScontext* stash, int* width, int* height);\nFONS_DEF int fonsValidateTexture(FONScontext* s, int* dirty);\n\n// Draws the stash texture for debugging\nFONS_DEF void fonsDrawDebug(FONScontext* s, float x, float y);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // FONS_H\n\n\n#ifdef FONTSTASH_IMPLEMENTATION\n\n#define FONS_NOTUSED(v)  (void)sizeof(v)\n\n\n// Use FreeType on non-Windows systems\n#ifndef _WIN32\n//#define FONS_USE_FREETYPE\n#endif\n\n#ifdef _WIN32\n#undef FONS_USE_FREETYPE\n#endif\n\n#ifdef __APPLE__\n    #include \"TargetConditionals.h\"\n    #if TARGET_OS_IPHONE\n\t#undef FONS_USE_FREETYPE\n    #endif\n#endif\n\n//#undef FONS_USE_FREETYPE\n\n//#define FONS_USE_FREETYPE 1\n\n#ifdef FONS_USE_FREETYPE\n\n#include <ft2build.h>\n#include FT_FREETYPE_H\n#include FT_ADVANCES_H\n#include <math.h>\n\nstruct FONSttFontImpl {\n\tFT_Face font;\n};\ntypedef struct FONSttFontImpl FONSttFontImpl;\n\nstatic FT_Library ftLibrary;\n\nstatic int fons__tt_init()\n{\n\tputs(\"free type fons init\");\n\tFT_Error ftError;\n\t//FONS_NOTUSED(context);\n\tftError = FT_Init_FreeType(&ftLibrary);\n\treturn ftError == 0;\n}\n\nstatic int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize)\n{\n\tFT_Error ftError;\n\tFONS_NOTUSED(context);\n\n\t//font->font.userdata = stash;\n\tftError = FT_New_Memory_Face(ftLibrary, (const FT_Byte*)data, dataSize, 0, &font->font);\n\treturn ftError == 0;\n}\n\nstatic void fons__tt_getFontVMetrics(FONSttFontImpl *font, int *ascent, int *descent, int *lineGap)\n{\n\t*ascent = font->font->ascender;\n\t*descent = font->font->descender;\n\t*lineGap = font->font->height - (*ascent - *descent);\n}\n\nstatic float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size)\n{\n\treturn size / (font->font->ascender - font->font->descender);\n}\n\nstatic int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint)\n{\n\treturn FT_Get_Char_Index(font->font, codepoint);\n}\n\nstatic int fons__tt_buildGlyphBitmap(FONSttFontImpl *font, int glyph, float size, float scale,\n\t\t\t\t\t\t\t  int *advance, int *lsb, int *x0, int *y0, int *x1, int *y1)\n{\n\tFT_Error ftError;\n\tFT_GlyphSlot ftGlyph;\n\tFT_Fixed advFixed;\n\tFONS_NOTUSED(scale);\n\n\tftError = FT_Set_Pixel_Sizes(font->font, 0, (FT_UInt)(size * (float)font->font->units_per_EM / (float)(font->font->ascender - font->font->descender)));\n\tif (ftError) return 0;\n\tftError = FT_Load_Glyph(font->font, glyph, FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT);\n\tif (ftError) return 0;\n\tftError = FT_Get_Advance(font->font, glyph, FT_LOAD_NO_SCALE, &advFixed);\n\tif (ftError) return 0;\n\tftGlyph = font->font->glyph;\n\t*advance = (int)advFixed;\n\t*lsb = (int)ftGlyph->metrics.horiBearingX;\n\t*x0 = ftGlyph->bitmap_left;\n\t*x1 = *x0 + ftGlyph->bitmap.width;\n\t*y0 = -ftGlyph->bitmap_top;\n\t*y1 = *y0 + ftGlyph->bitmap.rows;\n\treturn 1;\n}\n\nstatic void fons__tt_renderGlyphBitmap(FONSttFontImpl *font, unsigned char *output, int outWidth, int outHeight, int outStride,\n\t\t\t\t\t\t\t\tfloat scaleX, float scaleY, int glyph)\n{\n\tFT_GlyphSlot ftGlyph = font->font->glyph;\n\tint ftGlyphOffset = 0;\n\tint x, y;\n\tFONS_NOTUSED(outWidth);\n\tFONS_NOTUSED(outHeight);\n\tFONS_NOTUSED(scaleX);\n\tFONS_NOTUSED(scaleY);\n\tFONS_NOTUSED(glyph);\t// glyph has already been loaded by fons__tt_buildGlyphBitmap\n\n\tfor ( y = 0; y < ftGlyph->bitmap.rows; y++ ) {\n\t\tfor ( x = 0; x < ftGlyph->bitmap.width; x++ ) {\n\t\t\toutput[(y * outStride) + x] = ftGlyph->bitmap.buffer[ftGlyphOffset++];\n\t\t}\n\t}\n}\n\nstatic int fons__tt_getGlyphKernAdvance(FONSttFontImpl *font, int glyph1, int glyph2)\n{\n\tFT_Vector ftKerning;\n\tFT_Get_Kerning(font->font, glyph1, glyph2, FT_KERNING_DEFAULT, &ftKerning);\n\treturn (int)((ftKerning.x + 32) >> 6);  // Round up and convert to integer\n}\n\n#else\n\n#define STB_TRUETYPE_IMPLEMENTATION\n#define STBTT_STATIC\nstatic void* fons__tmpalloc(size_t size, void* up);\nstatic void fons__tmpfree(void* ptr, void* up);\n#define STBTT_malloc(x,u)    fons__tmpalloc(x,u)\n#define STBTT_free(x,u)      fons__tmpfree(x,u)\n#include \"stb_truetype.h\"\n\nstruct FONSttFontImpl {\n\tstbtt_fontinfo font;\n};\ntypedef struct FONSttFontImpl FONSttFontImpl;\n\nstatic int fons__tt_init(FONScontext *context)\n{\n\tFONS_NOTUSED(context);\n\treturn 1;\n}\n\nstatic int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize)\n{\n\tint stbError;\n\tFONS_NOTUSED(dataSize);\n\n\tfont->font.userdata = context;\n\tstbError = stbtt_InitFont(&font->font, data, 0);\n\treturn stbError;\n}\n\nstatic void fons__tt_getFontVMetrics(FONSttFontImpl *font, int *ascent, int *descent, int *lineGap)\n{\n\tstbtt_GetFontVMetrics(&font->font, ascent, descent, lineGap);\n}\n\nstatic float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size)\n{\n\treturn stbtt_ScaleForPixelHeight(&font->font, size);\n}\n\nstatic int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint)\n{\n\treturn stbtt_FindGlyphIndex(&font->font, codepoint);\n}\n\nstatic int fons__tt_buildGlyphBitmap(FONSttFontImpl *font, int glyph, float size, float scale,\n\t\t\t\t\t\t\t  int *advance, int *lsb, int *x0, int *y0, int *x1, int *y1)\n{\n\tFONS_NOTUSED(size);\n\tstbtt_GetGlyphHMetrics(&font->font, glyph, advance, lsb);\n\tstbtt_GetGlyphBitmapBox(&font->font, glyph, scale, scale, x0, y0, x1, y1);\n\treturn 1;\n}\n\nstatic void fons__tt_renderGlyphBitmap(FONSttFontImpl *font, unsigned char *output, int outWidth, int outHeight, int outStride,\n\t\t\t\t\t\t\t\tfloat scaleX, float scaleY, int glyph)\n{\n\tstbtt_MakeGlyphBitmap(&font->font, output, outWidth, outHeight, outStride, scaleX, scaleY, glyph);\n}\n\nstatic int fons__tt_getGlyphKernAdvance(FONSttFontImpl *font, int glyph1, int glyph2)\n{\n\treturn stbtt_GetGlyphKernAdvance(&font->font, glyph1, glyph2);\n}\n\n#endif\n\n#ifndef FONS_SCRATCH_BUF_SIZE\n#\tdefine FONS_SCRATCH_BUF_SIZE 64000\n#endif\n#ifndef FONS_HASH_LUT_SIZE\n#\tdefine FONS_HASH_LUT_SIZE 256\n#endif\n#ifndef FONS_INIT_FONTS\n#\tdefine FONS_INIT_FONTS 4\n#endif\n#ifndef FONS_INIT_GLYPHS\n#\tdefine FONS_INIT_GLYPHS 256\n#endif\n#ifndef FONS_INIT_ATLAS_NODES\n#\tdefine FONS_INIT_ATLAS_NODES 256\n#endif\n#ifndef FONS_VERTEX_COUNT\n#\tdefine FONS_VERTEX_COUNT 1024\n#endif\n#ifndef FONS_MAX_STATES\n#\tdefine FONS_MAX_STATES 20\n#endif\n#ifndef FONS_MAX_FALLBACKS\n#\tdefine FONS_MAX_FALLBACKS 20\n#endif\n\nstatic unsigned int fons__hashint(unsigned int a)\n{\n\ta += ~(a<<15);\n\ta ^=  (a>>10);\n\ta +=  (a<<3);\n\ta ^=  (a>>6);\n\ta += ~(a<<11);\n\ta ^=  (a>>16);\n\treturn a;\n}\n\nstatic int fons__mini(int a, int b)\n{\n\treturn a < b ? a : b;\n}\n\nstatic int fons__maxi(int a, int b)\n{\n\treturn a > b ? a : b;\n}\n\nstruct FONSglyph\n{\n\tunsigned int codepoint;\n\tint index;\n\tint next;\n\tshort size, blur;\n\tshort x0,y0,x1,y1;\n\tshort xadv,xoff,yoff;\n};\ntypedef struct FONSglyph FONSglyph;\n\nstruct FONSfont\n{\n\tFONSttFontImpl font;\n\tchar name[64];\n\tunsigned char* data;\n\tint dataSize;\n\tunsigned char freeData;\n\tfloat ascender;\n\tfloat descender;\n\tfloat lineh;\n\tFONSglyph* glyphs;\n\tint cglyphs;\n\tint nglyphs;\n\tint lut[FONS_HASH_LUT_SIZE];\n\tint fallbacks[FONS_MAX_FALLBACKS];\n\tint nfallbacks;\n};\ntypedef struct FONSfont FONSfont;\n\nstruct FONSstate\n{\n\tint font;\n\tint align;\n\tfloat size;\n\tunsigned int color;\n\tfloat blur;\n\tfloat spacing;\n};\ntypedef struct FONSstate FONSstate;\n\nstruct FONSatlasNode {\n\tshort x, y, width;\n};\ntypedef struct FONSatlasNode FONSatlasNode;\n\nstruct FONSatlas\n{\n\tint width, height;\n\tFONSatlasNode* nodes;\n\tint nnodes;\n\tint cnodes;\n};\ntypedef struct FONSatlas FONSatlas;\n\nstruct FONScontext\n{\n\tFONSparams params;\n\tfloat itw,ith;\n\tunsigned char* texData;\n\tint dirtyRect[4];\n\tFONSfont** fonts;\n\tFONSatlas* atlas;\n\tint cfonts;\n\tint nfonts;\n\tfloat verts[FONS_VERTEX_COUNT*2];\n\tfloat tcoords[FONS_VERTEX_COUNT*2];\n\tunsigned int colors[FONS_VERTEX_COUNT];\n\tint nverts;\n\tunsigned char* scratch;\n\tint nscratch;\n\tFONSstate states[FONS_MAX_STATES];\n\tint nstates;\n\tvoid (*handleError)(void* uptr, int error, int val);\n\tvoid* errorUptr;\n};\n\n#ifdef STB_TRUETYPE_IMPLEMENTATION\n\nstatic void* fons__tmpalloc(size_t size, void* up)\n{\n\tunsigned char* ptr;\n\tFONScontext* stash = (FONScontext*)up;\n\n\t// 16-byte align the returned pointer\n\tsize = (size + 0xf) & ~0xf;\n\n\tif (stash->nscratch+(int)size > FONS_SCRATCH_BUF_SIZE) {\n\t\tif (stash->handleError)\n\t\t\tstash->handleError(stash->errorUptr, FONS_SCRATCH_FULL, stash->nscratch+(int)size);\n\t\treturn NULL;\n\t}\n\tptr = stash->scratch + stash->nscratch;\n\tstash->nscratch += (int)size;\n\treturn ptr;\n}\n\nstatic void fons__tmpfree(void* ptr, void* up)\n{\n\t(void)ptr;\n\t(void)up;\n\t// empty\n}\n\n#endif // STB_TRUETYPE_IMPLEMENTATION\n\n// Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de>\n// See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.\n\n#define FONS_UTF8_ACCEPT 0\n#define FONS_UTF8_REJECT 12\n\nstatic unsigned int fons__decutf8(unsigned int* state, unsigned int* codep, unsigned int byte)\n{\n\tstatic const unsigned char utf8d[] = {\n\t\t// The first part of the table maps bytes to character classes that\n\t\t// to reduce the size of the transition table and create bitmasks.\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,\n\t\t7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n\t\t8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,\n\t\t10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,\n\n\t\t// The second part is a transition table that maps a combination\n\t\t// of a state of the automaton and a character class to a state.\n\t\t0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,\n\t\t12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,\n\t\t12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,\n\t\t12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,\n\t\t12,36,12,12,12,12,12,12,12,12,12,12,\n\t};\n\n\tunsigned int type = utf8d[byte];\n\n\t*codep = (*state != FONS_UTF8_ACCEPT) ?\n\t\t(byte & 0x3fu) | (*codep << 6) :\n\t\t(0xff >> type) & (byte);\n\n\t*state = utf8d[256 + *state + type];\n\treturn *state;\n}\n\n// Atlas based on Skyline Bin Packer by Jukka Jylänki\n\nstatic void fons__deleteAtlas(FONSatlas* atlas)\n{\n\tif (atlas == NULL) return;\n\tif (atlas->nodes != NULL) FONTSTASH_FREE(atlas->nodes);\n\tFONTSTASH_FREE(atlas);\n}\n\nstatic FONSatlas* fons__allocAtlas(int w, int h, int nnodes)\n{\n\tFONSatlas* atlas = NULL;\n\n\t// Allocate memory for the font stash.\n\tatlas = (FONSatlas*)FONTSTASH_MALLOC(sizeof(FONSatlas));\n\tif (atlas == NULL) goto error;\n\tmemset(atlas, 0, sizeof(FONSatlas));\n\n\tatlas->width = w;\n\tatlas->height = h;\n\n\t// Allocate space for skyline nodes\n\tatlas->nodes = (FONSatlasNode*)FONTSTASH_MALLOC_ATOMIC(sizeof(FONSatlasNode) * nnodes);\n\tif (atlas->nodes == NULL) goto error;\n\tmemset(atlas->nodes, 0, sizeof(FONSatlasNode) * nnodes);\n\tatlas->nnodes = 0;\n\tatlas->cnodes = nnodes;\n\n\t// Init root node.\n\tatlas->nodes[0].x = 0;\n\tatlas->nodes[0].y = 0;\n\tatlas->nodes[0].width = (short)w;\n\tatlas->nnodes++;\n\n\treturn atlas;\n\nerror:\n\tif (atlas) fons__deleteAtlas(atlas);\n\treturn NULL;\n}\n\nstatic int fons__atlasInsertNode(FONSatlas* atlas, int idx, int x, int y, int w)\n{\n\tint i;\n\t// Insert node\n\tif (atlas->nnodes+1 > atlas->cnodes) {\n\t\tatlas->cnodes = atlas->cnodes == 0 ? 8 : atlas->cnodes * 2;\n\t\tatlas->nodes = (FONSatlasNode*)FONTSTASH_REALLOC(atlas->nodes, sizeof(FONSatlasNode) * atlas->cnodes);\n\t\tif (atlas->nodes == NULL)\n\t\t\treturn 0;\n\t}\n\tfor (i = atlas->nnodes; i > idx; i--)\n\t\tatlas->nodes[i] = atlas->nodes[i-1];\n\tatlas->nodes[idx].x = (short)x;\n\tatlas->nodes[idx].y = (short)y;\n\tatlas->nodes[idx].width = (short)w;\n\tatlas->nnodes++;\n\n\treturn 1;\n}\n\nstatic void fons__atlasRemoveNode(FONSatlas* atlas, int idx)\n{\n\tint i;\n\tif (atlas->nnodes == 0) return;\n\tfor (i = idx; i < atlas->nnodes-1; i++)\n\t\tatlas->nodes[i] = atlas->nodes[i+1];\n\tatlas->nnodes--;\n}\n\nstatic void fons__atlasExpand(FONSatlas* atlas, int w, int h)\n{\n\t// Insert node for empty space\n\tif (w > atlas->width)\n\t\tfons__atlasInsertNode(atlas, atlas->nnodes, atlas->width, 0, w - atlas->width);\n\tatlas->width = w;\n\tatlas->height = h;\n}\n\nstatic void fons__atlasReset(FONSatlas* atlas, int w, int h)\n{\n\tatlas->width = w;\n\tatlas->height = h;\n\tatlas->nnodes = 0;\n\n\t// Init root node.\n\tatlas->nodes[0].x = 0;\n\tatlas->nodes[0].y = 0;\n\tatlas->nodes[0].width = (short)w;\n\tatlas->nnodes++;\n}\n\nstatic int fons__atlasAddSkylineLevel(FONSatlas* atlas, int idx, int x, int y, int w, int h)\n{\n\tint i;\n\n\t// Insert new node\n\tif (fons__atlasInsertNode(atlas, idx, x, y+h, w) == 0)\n\t\treturn 0;\n\n\t// Delete skyline segments that fall under the shadow of the new segment.\n\tfor (i = idx+1; i < atlas->nnodes; i++) {\n\t\tif (atlas->nodes[i].x < atlas->nodes[i-1].x + atlas->nodes[i-1].width) {\n\t\t\tint shrink = atlas->nodes[i-1].x + atlas->nodes[i-1].width - atlas->nodes[i].x;\n\t\t\tatlas->nodes[i].x += (short)shrink;\n\t\t\tatlas->nodes[i].width -= (short)shrink;\n\t\t\tif (atlas->nodes[i].width <= 0) {\n\t\t\t\tfons__atlasRemoveNode(atlas, i);\n\t\t\t\ti--;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Merge same height skyline segments that are next to each other.\n\tfor (i = 0; i < atlas->nnodes-1; i++) {\n\t\tif (atlas->nodes[i].y == atlas->nodes[i+1].y) {\n\t\t\tatlas->nodes[i].width += atlas->nodes[i+1].width;\n\t\t\tfons__atlasRemoveNode(atlas, i+1);\n\t\t\ti--;\n\t\t}\n\t}\n\n\treturn 1;\n}\n\nstatic int fons__atlasRectFits(FONSatlas* atlas, int i, int w, int h)\n{\n\t// Checks if there is enough space at the location of skyline span 'i',\n\t// and return the max height of all skyline spans under that at that location,\n\t// (think tetris block being dropped at that position). Or -1 if no space found.\n\tint x = atlas->nodes[i].x;\n\tint y = atlas->nodes[i].y;\n\tint spaceLeft;\n\tif (x + w > atlas->width)\n\t\treturn -1;\n\tspaceLeft = w;\n\twhile (spaceLeft > 0) {\n\t\tif (i == atlas->nnodes) return -1;\n\t\ty = fons__maxi(y, atlas->nodes[i].y);\n\t\tif (y + h > atlas->height) return -1;\n\t\tspaceLeft -= atlas->nodes[i].width;\n\t\t++i;\n\t}\n\treturn y;\n}\n\nstatic int fons__atlasAddRect(FONSatlas* atlas, int rw, int rh, int* rx, int* ry)\n{\n\tint besth = atlas->height, bestw = atlas->width, besti = -1;\n\tint bestx = -1, besty = -1, i;\n\n\t// Bottom left fit heuristic.\n\tfor (i = 0; i < atlas->nnodes; i++) {\n\t\tint y = fons__atlasRectFits(atlas, i, rw, rh);\n\t\tif (y != -1) {\n\t\t\tif (y + rh < besth || (y + rh == besth && atlas->nodes[i].width < bestw)) {\n\t\t\t\tbesti = i;\n\t\t\t\tbestw = atlas->nodes[i].width;\n\t\t\t\tbesth = y + rh;\n\t\t\t\tbestx = atlas->nodes[i].x;\n\t\t\t\tbesty = y;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (besti == -1)\n\t\treturn 0;\n\n\t// Perform the actual packing.\n\tif (fons__atlasAddSkylineLevel(atlas, besti, bestx, besty, rw, rh) == 0)\n\t\treturn 0;\n\n\t*rx = bestx;\n\t*ry = besty;\n\n\treturn 1;\n}\n\nstatic void fons__addWhiteRect(FONScontext* stash, int w, int h)\n{\n\tint x, y, gx, gy;\n\tunsigned char* dst;\n\tif (fons__atlasAddRect(stash->atlas, w, h, &gx, &gy) == 0)\n\t\treturn;\n\n\t// Rasterize\n\tdst = &stash->texData[gx + gy * stash->params.width];\n\tfor (y = 0; y < h; y++) {\n\t\tfor (x = 0; x < w; x++)\n\t\t\tdst[x] = 0xff;\n\t\tdst += stash->params.width;\n\t}\n\n\tstash->dirtyRect[0] = fons__mini(stash->dirtyRect[0], gx);\n\tstash->dirtyRect[1] = fons__mini(stash->dirtyRect[1], gy);\n\tstash->dirtyRect[2] = fons__maxi(stash->dirtyRect[2], gx+w);\n\tstash->dirtyRect[3] = fons__maxi(stash->dirtyRect[3], gy+h);\n}\n\nFONScontext* fonsCreateInternal(FONSparams* params)\n{\n\tFONScontext* stash = NULL;\n\n\t// Allocate memory for the font stash.\n\tstash = (FONScontext*)FONTSTASH_MALLOC(sizeof(FONScontext));\n\tif (stash == NULL) goto error;\n\tmemset(stash, 0, sizeof(FONScontext));\n\n\tstash->params = *params;\n\n\t// Allocate scratch buffer.\n\tstash->scratch = (unsigned char*)FONTSTASH_MALLOC(FONS_SCRATCH_BUF_SIZE);\n\tif (stash->scratch == NULL) goto error;\n\n\t// Initialize implementation library\n\tif (!fons__tt_init(stash)) goto error;\n\n\tif (stash->params.renderCreate != NULL) {\n\t\tif (stash->params.renderCreate(stash->params.userPtr, stash->params.width, stash->params.height) == 0)\n\t\t\tgoto error;\n\t}\n\n\tstash->atlas = fons__allocAtlas(stash->params.width, stash->params.height, FONS_INIT_ATLAS_NODES);\n\tif (stash->atlas == NULL) goto error;\n\n\t// Allocate space for fonts.\n\tstash->fonts = (FONSfont**)FONTSTASH_MALLOC(sizeof(FONSfont*) * FONS_INIT_FONTS);\n\tif (stash->fonts == NULL) goto error;\n\tmemset(stash->fonts, 0, sizeof(FONSfont*) * FONS_INIT_FONTS);\n\tstash->cfonts = FONS_INIT_FONTS;\n\tstash->nfonts = 0;\n\n\t// Create texture for the cache.\n\tstash->itw = 1.0f/stash->params.width;\n\tstash->ith = 1.0f/stash->params.height;\n\tstash->texData = (unsigned char*)FONTSTASH_MALLOC_ATOMIC(stash->params.width * stash->params.height);\n\tif (stash->texData == NULL) goto error;\n\tmemset(stash->texData, 0, stash->params.width * stash->params.height);\n\n\tstash->dirtyRect[0] = stash->params.width;\n\tstash->dirtyRect[1] = stash->params.height;\n\tstash->dirtyRect[2] = 0;\n\tstash->dirtyRect[3] = 0;\n\n\t// Add white rect at 0,0 for debug drawing.\n\tfons__addWhiteRect(stash, 2,2);\n\n\tfonsPushState(stash);\n\tfonsClearState(stash);\n\n\treturn stash;\n\nerror:\n\tfonsDeleteInternal(stash);\n\treturn NULL;\n}\n\nstatic FONSstate* fons__getState(FONScontext* stash)\n{\n\treturn &stash->states[stash->nstates-1];\n}\n\nint fonsAddFallbackFont(FONScontext* stash, int base, int fallback)\n{\n\tFONSfont* baseFont = stash->fonts[base];\n\tif (baseFont->nfallbacks < FONS_MAX_FALLBACKS) {\n\t\tbaseFont->fallbacks[baseFont->nfallbacks++] = fallback;\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nvoid fonsSetSize(FONScontext* stash, float size)\n{\n\tfons__getState(stash)->size = size;\n}\n\nvoid fonsSetColor(FONScontext* stash, unsigned int color)\n{\n\tfons__getState(stash)->color = color;\n}\n\nvoid fonsSetSpacing(FONScontext* stash, float spacing)\n{\n\tfons__getState(stash)->spacing = spacing;\n}\n\nvoid fonsSetBlur(FONScontext* stash, float blur)\n{\n\tfons__getState(stash)->blur = blur;\n}\n\nvoid fonsSetAlign(FONScontext* stash, int align)\n{\n\tfons__getState(stash)->align = align;\n}\n\nvoid fonsSetFont(FONScontext* stash, int font)\n{\n\tfons__getState(stash)->font = font;\n}\n\nvoid fonsPushState(FONScontext* stash)\n{\n\tif (stash->nstates >= FONS_MAX_STATES) {\n\t\tif (stash->handleError)\n\t\t\tstash->handleError(stash->errorUptr, FONS_STATES_OVERFLOW, 0);\n\t\treturn;\n\t}\n\tif (stash->nstates > 0)\n\t\tmemcpy(&stash->states[stash->nstates], &stash->states[stash->nstates-1], sizeof(FONSstate));\n\tstash->nstates++;\n}\n\nvoid fonsPopState(FONScontext* stash)\n{\n\tif (stash->nstates <= 1) {\n\t\tif (stash->handleError)\n\t\t\tstash->handleError(stash->errorUptr, FONS_STATES_UNDERFLOW, 0);\n\t\treturn;\n\t}\n\tstash->nstates--;\n}\n\nvoid fonsClearState(FONScontext* stash)\n{\n\tFONSstate* state = fons__getState(stash);\n\tstate->size = 12.0f;\n\tstate->color = 0xffffffff;\n\tstate->font = 0;\n\tstate->blur = 0;\n\tstate->spacing = 0;\n\tstate->align = FONS_ALIGN_LEFT | FONS_ALIGN_BASELINE;\n}\n\nstatic void fons__freeFont(FONSfont* font)\n{\n\tif (font == NULL) return;\n\tif (font->glyphs) FONTSTASH_FREE(font->glyphs);\n\tif (font->freeData && font->data) FONTSTASH_FREE(font->data);\n\tFONTSTASH_FREE(font);\n}\n\nstatic int fons__allocFont(FONScontext* stash)\n{\n\tFONSfont* font = NULL;\n\tif (stash->nfonts+1 > stash->cfonts) {\n\t\tstash->cfonts = stash->cfonts == 0 ? 8 : stash->cfonts * 2;\n\t\tstash->fonts = (FONSfont**)FONTSTASH_REALLOC(stash->fonts, sizeof(FONSfont*) * stash->cfonts);\n\t\tif (stash->fonts == NULL)\n\t\t\treturn -1;\n\t}\n\tfont = (FONSfont*)FONTSTASH_MALLOC(sizeof(FONSfont));\n\tif (font == NULL) goto error;\n\tmemset(font, 0, sizeof(FONSfont));\n\n\tfont->glyphs = (FONSglyph*)FONTSTASH_MALLOC_ATOMIC(sizeof(FONSglyph) * FONS_INIT_GLYPHS);\n\tif (font->glyphs == NULL) goto error;\n\tfont->cglyphs = FONS_INIT_GLYPHS;\n\tfont->nglyphs = 0;\n\n\tstash->fonts[stash->nfonts++] = font;\n\treturn stash->nfonts-1;\n\nerror:\n\tfons__freeFont(font);\n\n\treturn FONS_INVALID;\n}\n\nint fonsAddFontMem(FONScontext* stash, const char* name, unsigned char* data, int dataSize, int freeData)\n{\n\tint i, ascent, descent, fh, lineGap;\n\tFONSfont* font;\n\n\tint idx = fons__allocFont(stash);\n\tif (idx == FONS_INVALID)\n\t\treturn FONS_INVALID;\n\n\tfont = stash->fonts[idx];\n\n\tstrncpy(font->name, name, sizeof(font->name));\n\tfont->name[sizeof(font->name)-1] = '\\0';\n\n\t// Init hash lookup.\n\tfor (i = 0; i < FONS_HASH_LUT_SIZE; ++i)\n\t\tfont->lut[i] = -1;\n\n\t// Read in the font data.\n\tfont->dataSize = dataSize;\n\tfont->data = data;\n\tfont->freeData = (unsigned char)freeData;\n\n\t// Init font\n\tstash->nscratch = 0;\n\tif (!fons__tt_loadFont(stash, &font->font, data, dataSize)) goto error;\n\n\t// Store normalized line height. The real line height is got\n\t// by multiplying the lineh by font size.\n\tfons__tt_getFontVMetrics( &font->font, &ascent, &descent, &lineGap);\n\tfh = ascent - descent;\n\tfont->ascender = (float)ascent / (float)fh;\n\tfont->descender = (float)descent / (float)fh;\n\tfont->lineh = (float)(fh + lineGap) / (float)fh;\n\n\treturn idx;\n\nerror:\n\tfons__freeFont(font);\n\tstash->nfonts--;\n\treturn FONS_INVALID;\n}\n\nint fonsGetFontByName(FONScontext* s, const char* name)\n{\n\tint i;\n\tfor (i = 0; i < s->nfonts; i++) {\n\t\tif (strcmp(s->fonts[i]->name, name) == 0)\n\t\t\treturn i;\n\t}\n\treturn FONS_INVALID;\n}\n\n\nstatic FONSglyph* fons__allocGlyph(FONSfont* font)\n{\n\tif (font->nglyphs+1 > font->cglyphs) {\n\t\tfont->cglyphs = font->cglyphs == 0 ? 8 : font->cglyphs * 2;\n\t\tfont->glyphs = (FONSglyph*)FONTSTASH_REALLOC(font->glyphs, sizeof(FONSglyph) * font->cglyphs);\n\t\tif (font->glyphs == NULL) return NULL;\n\t}\n\tfont->nglyphs++;\n\treturn &font->glyphs[font->nglyphs-1];\n}\n\n\n// Based on Exponential blur, Jani Huhtanen, 2006\n\n#define APREC 16\n#define ZPREC 7\n\nstatic void fons__blurCols(unsigned char* dst, int w, int h, int dstStride, int alpha)\n{\n\tint x, y;\n\tfor (y = 0; y < h; y++) {\n\t\tint z = 0; // force zero border\n\t\tfor (x = 1; x < w; x++) {\n\t\t\tz += (alpha * (((int)(dst[x]) << ZPREC) - z)) >> APREC;\n\t\t\tdst[x] = (unsigned char)(z >> ZPREC);\n\t\t}\n\t\tdst[w-1] = 0; // force zero border\n\t\tz = 0;\n\t\tfor (x = w-2; x >= 0; x--) {\n\t\t\tz += (alpha * (((int)(dst[x]) << ZPREC) - z)) >> APREC;\n\t\t\tdst[x] = (unsigned char)(z >> ZPREC);\n\t\t}\n\t\tdst[0] = 0; // force zero border\n\t\tdst += dstStride;\n\t}\n}\n\nstatic void fons__blurRows(unsigned char* dst, int w, int h, int dstStride, int alpha)\n{\n\tint x, y;\n\tfor (x = 0; x < w; x++) {\n\t\tint z = 0; // force zero border\n\t\tfor (y = dstStride; y < h*dstStride; y += dstStride) {\n\t\t\tz += (alpha * (((int)(dst[y]) << ZPREC) - z)) >> APREC;\n\t\t\tdst[y] = (unsigned char)(z >> ZPREC);\n\t\t}\n\t\tdst[(h-1)*dstStride] = 0; // force zero border\n\t\tz = 0;\n\t\tfor (y = (h-2)*dstStride; y >= 0; y -= dstStride) {\n\t\t\tz += (alpha * (((int)(dst[y]) << ZPREC) - z)) >> APREC;\n\t\t\tdst[y] = (unsigned char)(z >> ZPREC);\n\t\t}\n\t\tdst[0] = 0; // force zero border\n\t\tdst++;\n\t}\n}\n\n\nstatic void fons__blur(FONScontext* stash, unsigned char* dst, int w, int h, int dstStride, int blur)\n{\n\tint alpha;\n\tfloat sigma;\n\t(void)stash;\n\n\tif (blur < 1)\n\t\treturn;\n\t// Calculate the alpha such that 90% of the kernel is within the radius. (Kernel extends to infinity)\n\tsigma = (float)blur * 0.57735f; // 1 / sqrt(3)\n\talpha = (int)((1<<APREC) * (1.0f - expf(-2.3f / (sigma+1.0f))));\n\tfons__blurRows(dst, w, h, dstStride, alpha);\n\tfons__blurCols(dst, w, h, dstStride, alpha);\n\tfons__blurRows(dst, w, h, dstStride, alpha);\n\tfons__blurCols(dst, w, h, dstStride, alpha);\n//\tfons__blurrows(dst, w, h, dstStride, alpha);\n//\tfons__blurcols(dst, w, h, dstStride, alpha);\n}\n\nstatic FONSglyph* fons__getGlyph(FONScontext* stash, FONSfont* font, unsigned int codepoint,\n\t\t\t\t\t\t\t\t short isize, short iblur)\n{\n\tint i, g, advance, lsb, x0, y0, x1, y1, gw, gh, gx, gy, x, y;\n\tfloat scale;\n\tFONSglyph* glyph = NULL;\n\tunsigned int h;\n\tfloat size = isize/10.0f;\n\tint pad, added;\n\tunsigned char* bdst;\n\tunsigned char* dst;\n\tFONSfont* renderFont = font;\n\n\tif (isize < 2) return NULL;\n\tif (iblur > 20) iblur = 20;\n\tpad = iblur+2;\n\n\t// Reset allocator.\n\tstash->nscratch = 0;\n\n\t// Find code point and size.\n\th = fons__hashint(codepoint) & (FONS_HASH_LUT_SIZE-1);\n\ti = font->lut[h];\n\twhile (i != -1) {\n\t\tif (font->glyphs[i].codepoint == codepoint && font->glyphs[i].size == isize && font->glyphs[i].blur == iblur)\n\t\t\treturn &font->glyphs[i];\n\t\ti = font->glyphs[i].next;\n\t}\n\n\t// Could not find glyph, create it.\n\tg = fons__tt_getGlyphIndex(&font->font, codepoint);\n\t// Try to find the glyph in fallback fonts.\n\tif (g == 0) {\n\t\tfor (i = 0; i < font->nfallbacks; ++i) {\n\t\t\tFONSfont* fallbackFont = stash->fonts[font->fallbacks[i]];\n\t\t\tint fallbackIndex = fons__tt_getGlyphIndex(&fallbackFont->font, codepoint);\n\t\t\tif (fallbackIndex != 0) {\n\t\t\t\tg = fallbackIndex;\n\t\t\t\trenderFont = fallbackFont;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t// It is possible that we did not find a fallback glyph.\n\t\t// In that case the glyph index 'g' is 0, and we'll proceed below and cache empty glyph.\n\t}\n\tscale = fons__tt_getPixelHeightScale(&renderFont->font, size);\n\tfons__tt_buildGlyphBitmap(&renderFont->font, g, size, scale, &advance, &lsb, &x0, &y0, &x1, &y1);\n\tgw = x1-x0 + pad*2;\n\tgh = y1-y0 + pad*2;\n\n\t// Find free spot for the rect in the atlas\n\tadded = fons__atlasAddRect(stash->atlas, gw, gh, &gx, &gy);\n\tif (added == 0 && stash->handleError != NULL) {\n\t\t// Atlas is full, let the user to resize the atlas (or not), and try again.\n\t\tstash->handleError(stash->errorUptr, FONS_ATLAS_FULL, 0);\n\t\tadded = fons__atlasAddRect(stash->atlas, gw, gh, &gx, &gy);\n\t}\n\tif (added == 0) return NULL;\n\n\t// Init glyph.\n\tglyph = fons__allocGlyph(font);\n\tglyph->codepoint = codepoint;\n\tglyph->size = isize;\n\tglyph->blur = iblur;\n\tglyph->index = g;\n\tglyph->x0 = (short)gx;\n\tglyph->y0 = (short)gy;\n\tglyph->x1 = (short)(glyph->x0+gw);\n\tglyph->y1 = (short)(glyph->y0+gh);\n\tglyph->xadv = (short)(scale * advance * 10.0f);\n\tglyph->xoff = (short)(x0 - pad);\n\tglyph->yoff = (short)(y0 - pad);\n\tglyph->next = 0;\n\n\t// Insert char to hash lookup.\n\tglyph->next = font->lut[h];\n\tfont->lut[h] = font->nglyphs-1;\n\n\t// Rasterize\n\tdst = &stash->texData[(glyph->x0+pad) + (glyph->y0+pad) * stash->params.width];\n\tfons__tt_renderGlyphBitmap(&renderFont->font, dst, gw-pad*2,gh-pad*2, stash->params.width, scale,scale, g);\n\n\t// Make sure there is one pixel empty border.\n\tdst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width];\n\tfor (y = 0; y < gh; y++) {\n\t\tdst[y*stash->params.width] = 0;\n\t\tdst[gw-1 + y*stash->params.width] = 0;\n\t}\n\tfor (x = 0; x < gw; x++) {\n\t\tdst[x] = 0;\n\t\tdst[x + (gh-1)*stash->params.width] = 0;\n\t}\n\n\t// Debug code to color the glyph background\n/*\tunsigned char* fdst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width];\n\tfor (y = 0; y < gh; y++) {\n\t\tfor (x = 0; x < gw; x++) {\n\t\t\tint a = (int)fdst[x+y*stash->params.width] + 20;\n\t\t\tif (a > 255) a = 255;\n\t\t\tfdst[x+y*stash->params.width] = a;\n\t\t}\n\t}*/\n\n\t// Blur\n\tif (iblur > 0) {\n\t\tstash->nscratch = 0;\n\t\tbdst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width];\n\t\tfons__blur(stash, bdst, gw,gh, stash->params.width, iblur);\n\t}\n\n\tstash->dirtyRect[0] = fons__mini(stash->dirtyRect[0], glyph->x0);\n\tstash->dirtyRect[1] = fons__mini(stash->dirtyRect[1], glyph->y0);\n\tstash->dirtyRect[2] = fons__maxi(stash->dirtyRect[2], glyph->x1);\n\tstash->dirtyRect[3] = fons__maxi(stash->dirtyRect[3], glyph->y1);\n\n\treturn glyph;\n}\n\nstatic void fons__getQuad(FONScontext* stash, FONSfont* font,\n\t\t\t\t\t\t   int prevGlyphIndex, FONSglyph* glyph,\n\t\t\t\t\t\t   float scale, float spacing, float* x, float* y, FONSquad* q)\n{\n\tfloat rx,ry,xoff,yoff,x0,y0,x1,y1;\n\n\tif (prevGlyphIndex != -1) {\n\t\tfloat adv = fons__tt_getGlyphKernAdvance(&font->font, prevGlyphIndex, glyph->index) * scale;\n\t\t*x += (int)(adv + spacing + 0.5f);\n\t}\n\n\t// Each glyph has 2px border to allow good interpolation,\n\t// one pixel to prevent leaking, and one to allow good interpolation for rendering.\n\t// Inset the texture region by one pixel for correct interpolation.\n\txoff = (short)(glyph->xoff+1);\n\tyoff = (short)(glyph->yoff+1);\n\tx0 = (float)(glyph->x0+1);\n\ty0 = (float)(glyph->y0+1);\n\tx1 = (float)(glyph->x1-1);\n\ty1 = (float)(glyph->y1-1);\n\n\tif (stash->params.flags & FONS_ZERO_TOPLEFT) {\n\t\trx = (float)(int)(*x + xoff);\n\t\try = (float)(int)(*y + yoff);\n\n\t\tq->x0 = rx;\n\t\tq->y0 = ry;\n\t\tq->x1 = rx + x1 - x0;\n\t\tq->y1 = ry + y1 - y0;\n\n\t\tq->s0 = x0 * stash->itw;\n\t\tq->t0 = y0 * stash->ith;\n\t\tq->s1 = x1 * stash->itw;\n\t\tq->t1 = y1 * stash->ith;\n\t} else {\n\t\trx = (float)(int)(*x + xoff);\n\t\try = (float)(int)(*y - yoff);\n\n\t\tq->x0 = rx;\n\t\tq->y0 = ry;\n\t\tq->x1 = rx + x1 - x0;\n\t\tq->y1 = ry - y1 + y0;\n\n\t\tq->s0 = x0 * stash->itw;\n\t\tq->t0 = y0 * stash->ith;\n\t\tq->s1 = x1 * stash->itw;\n\t\tq->t1 = y1 * stash->ith;\n\t}\n\n\t*x += (int)(glyph->xadv / 10.0f + 0.5f);\n}\n\nstatic void fons__flush(FONScontext* stash)\n{\n\t// Flush texture\n\tif (stash->dirtyRect[0] < stash->dirtyRect[2] && stash->dirtyRect[1] < stash->dirtyRect[3]) {\n\t\tif (stash->params.renderUpdate != NULL)\n\t\t\tstash->params.renderUpdate(stash->params.userPtr, stash->dirtyRect, stash->texData);\n\t\t// Reset dirty rect\n\t\tstash->dirtyRect[0] = stash->params.width;\n\t\tstash->dirtyRect[1] = stash->params.height;\n\t\tstash->dirtyRect[2] = 0;\n\t\tstash->dirtyRect[3] = 0;\n\t}\n\n\t// Flush triangles\n\tif (stash->nverts > 0) {\n\t\tif (stash->params.renderDraw != NULL)\n\t\t\tstash->params.renderDraw(stash->params.userPtr, stash->verts, stash->tcoords, stash->colors, stash->nverts);\n\t\tstash->nverts = 0;\n\t}\n}\n\nstatic __inline void fons__vertex(FONScontext* stash, float x, float y, float s, float t, unsigned int c)\n{\n\tstash->verts[stash->nverts*2+0] = x;\n\tstash->verts[stash->nverts*2+1] = y;\n\tstash->tcoords[stash->nverts*2+0] = s;\n\tstash->tcoords[stash->nverts*2+1] = t;\n\tstash->colors[stash->nverts] = c;\n\tstash->nverts++;\n}\n\nstatic float fons__getVertAlign(FONScontext* stash, FONSfont* font, int align, short isize)\n{\n\tif (stash->params.flags & FONS_ZERO_TOPLEFT) {\n\t\tif (align & FONS_ALIGN_TOP) {\n\t\t\treturn font->ascender * (float)isize/10.0f;\n\t\t} else if (align & FONS_ALIGN_MIDDLE) {\n\t\t\treturn (font->ascender + font->descender) / 2.0f * (float)isize/10.0f;\n\t\t} else if (align & FONS_ALIGN_BASELINE) {\n\t\t\treturn 0.0f;\n\t\t} else if (align & FONS_ALIGN_BOTTOM) {\n\t\t\treturn font->descender * (float)isize/10.0f;\n\t\t}\n\t} else {\n\t\tif (align & FONS_ALIGN_TOP) {\n\t\t\treturn -font->ascender * (float)isize/10.0f;\n\t\t} else if (align & FONS_ALIGN_MIDDLE) {\n\t\t\treturn -(font->ascender + font->descender) / 2.0f * (float)isize/10.0f;\n\t\t} else if (align & FONS_ALIGN_BASELINE) {\n\t\t\treturn 0.0f;\n\t\t} else if (align & FONS_ALIGN_BOTTOM) {\n\t\t\treturn -font->descender * (float)isize/10.0f;\n\t\t}\n\t}\n\treturn 0.0;\n}\n\nFONS_DEF float fonsDrawText(FONScontext* stash,\n\t\t\t\t   float x, float y,\n\t\t\t\t   const char* str, const char* end)\n{\n\tFONSstate* state = fons__getState(stash);\n\tunsigned int codepoint;\n\tunsigned int utf8state = 0;\n\tFONSglyph* glyph = NULL;\n\tFONSquad q;\n\tint prevGlyphIndex = -1;\n\tshort isize = (short)(state->size*10.0f);\n\tshort iblur = (short)state->blur;\n\tfloat scale;\n\tFONSfont* font;\n\tfloat width;\n\n\tif (stash == NULL) return x;\n\tif (state->font < 0 || state->font >= stash->nfonts) return x;\n\tfont = stash->fonts[state->font];\n\tif (font->data == NULL) return x;\n\n\tscale = fons__tt_getPixelHeightScale(&font->font, (float)isize/10.0f);\n\n\tif (end == NULL)\n\t\tend = str + strlen(str);\n\n\t// Align horizontally\n\tif (state->align & FONS_ALIGN_LEFT) {\n\t\t// empty\n\t} else if (state->align & FONS_ALIGN_RIGHT) {\n\t\twidth = fonsTextBounds(stash, x,y, str, end, NULL);\n\t\tx -= width;\n\t} else if (state->align & FONS_ALIGN_CENTER) {\n\t\twidth = fonsTextBounds(stash, x,y, str, end, NULL);\n\t\tx -= width * 0.5f;\n\t}\n\t// Align vertically.\n\ty += fons__getVertAlign(stash, font, state->align, isize);\n\n\tfor (; str != end; ++str) {\n\t\tif (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str))\n\t\t\tcontinue;\n\t\tglyph = fons__getGlyph(stash, font, codepoint, isize, iblur);\n\t\tif (glyph != NULL) {\n\t\t\tfons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q);\n\n\t\t\tif (stash->nverts+6 > FONS_VERTEX_COUNT)\n\t\t\t\tfons__flush(stash);\n\n\t\t\tfons__vertex(stash, q.x0, q.y0, q.s0, q.t0, state->color);\n\t\t\tfons__vertex(stash, q.x1, q.y1, q.s1, q.t1, state->color);\n\t\t\tfons__vertex(stash, q.x1, q.y0, q.s1, q.t0, state->color);\n\n\t\t\tfons__vertex(stash, q.x0, q.y0, q.s0, q.t0, state->color);\n\t\t\tfons__vertex(stash, q.x0, q.y1, q.s0, q.t1, state->color);\n\t\t\tfons__vertex(stash, q.x1, q.y1, q.s1, q.t1, state->color);\n\t\t}\n\t\tprevGlyphIndex = glyph != NULL ? glyph->index : -1;\n\t}\n\tfons__flush(stash);\n\n\treturn x;\n}\n\nFONS_DEF int fonsTextIterInit(FONScontext* stash, FONStextIter* iter,\n\t\t\t\t\t float x, float y, const char* str, const char* end)\n{\n\tFONSstate* state = fons__getState(stash);\n\tfloat width;\n\n\tmemset(iter, 0, sizeof(*iter));\n\n\tif (stash == NULL) return 0;\n\tif (state->font < 0 || state->font >= stash->nfonts) return 0;\n\titer->font = stash->fonts[state->font];\n\tif (iter->font->data == NULL) return 0;\n\n\titer->isize = (short)(state->size*10.0f);\n\titer->iblur = (short)state->blur;\n\titer->scale = fons__tt_getPixelHeightScale(&iter->font->font, (float)iter->isize/10.0f);\n\n\t// Align horizontally\n\tif (state->align & FONS_ALIGN_LEFT) {\n\t\t// empty\n\t} else if (state->align & FONS_ALIGN_RIGHT) {\n\t\twidth = fonsTextBounds(stash, x,y, str, end, NULL);\n\t\tx -= width;\n\t} else if (state->align & FONS_ALIGN_CENTER) {\n\t\twidth = fonsTextBounds(stash, x,y, str, end, NULL);\n\t\tx -= width * 0.5f;\n\t}\n\t// Align vertically.\n\ty += fons__getVertAlign(stash, iter->font, state->align, iter->isize);\n\n\tif (end == NULL)\n\t\tend = str + strlen(str);\n\n\titer->x = iter->nextx = x;\n\titer->y = iter->nexty = y;\n\titer->spacing = state->spacing;\n\titer->str = str;\n\titer->next = str;\n\titer->end = end;\n\titer->codepoint = 0;\n\titer->prevGlyphIndex = -1;\n\n\treturn 1;\n}\n\nFONS_DEF int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, FONSquad* quad)\n{\n\tFONSglyph* glyph = NULL;\n\tconst char* str = iter->next;\n\titer->str = iter->next;\n\n\tif (str == iter->end)\n\t\treturn 0;\n\n\tfor (; str != iter->end; str++) {\n\t\tif (fons__decutf8(&iter->utf8state, &iter->codepoint, *(const unsigned char*)str))\n\t\t\tcontinue;\n\t\tstr++;\n\t\t// Get glyph and quad\n\t\titer->x = iter->nextx;\n\t\titer->y = iter->nexty;\n\t\tglyph = fons__getGlyph(stash, iter->font, iter->codepoint, iter->isize, iter->iblur);\n\t\tif (glyph != NULL)\n\t\t\tfons__getQuad(stash, iter->font, iter->prevGlyphIndex, glyph, iter->scale, iter->spacing, &iter->nextx, &iter->nexty, quad);\n\t\titer->prevGlyphIndex = glyph != NULL ? glyph->index : -1;\n\t\tbreak;\n\t}\n\titer->next = str;\n\n\treturn 1;\n}\n\nFONS_DEF void fonsDrawDebug(FONScontext* stash, float x, float y)\n{\n\tint i;\n\tint w = stash->params.width;\n\tint h = stash->params.height;\n\tfloat u = w == 0 ? 0 : (1.0f / w);\n\tfloat v = h == 0 ? 0 : (1.0f / h);\n\n\tif (stash->nverts+6+6 > FONS_VERTEX_COUNT)\n\t\tfons__flush(stash);\n\n\t// Draw background\n\tfons__vertex(stash, x+0, y+0, u, v, 0x0fffffff);\n\tfons__vertex(stash, x+w, y+h, u, v, 0x0fffffff);\n\tfons__vertex(stash, x+w, y+0, u, v, 0x0fffffff);\n\n\tfons__vertex(stash, x+0, y+0, u, v, 0x0fffffff);\n\tfons__vertex(stash, x+0, y+h, u, v, 0x0fffffff);\n\tfons__vertex(stash, x+w, y+h, u, v, 0x0fffffff);\n\n\t// Draw texture\n\tfons__vertex(stash, x+0, y+0, 0, 0, 0xffffffff);\n\tfons__vertex(stash, x+w, y+h, 1, 1, 0xffffffff);\n\tfons__vertex(stash, x+w, y+0, 1, 0, 0xffffffff);\n\n\tfons__vertex(stash, x+0, y+0, 0, 0, 0xffffffff);\n\tfons__vertex(stash, x+0, y+h, 0, 1, 0xffffffff);\n\tfons__vertex(stash, x+w, y+h, 1, 1, 0xffffffff);\n\n\t// Drawbug draw atlas\n\tfor (i = 0; i < stash->atlas->nnodes; i++) {\n\t\tFONSatlasNode* n = &stash->atlas->nodes[i];\n\n\t\tif (stash->nverts+6 > FONS_VERTEX_COUNT)\n\t\t\tfons__flush(stash);\n\n\t\tfons__vertex(stash, x+n->x+0, y+n->y+0, u, v, 0xc00000ff);\n\t\tfons__vertex(stash, x+n->x+n->width, y+n->y+1, u, v, 0xc00000ff);\n\t\tfons__vertex(stash, x+n->x+n->width, y+n->y+0, u, v, 0xc00000ff);\n\n\t\tfons__vertex(stash, x+n->x+0, y+n->y+0, u, v, 0xc00000ff);\n\t\tfons__vertex(stash, x+n->x+0, y+n->y+1, u, v, 0xc00000ff);\n\t\tfons__vertex(stash, x+n->x+n->width, y+n->y+1, u, v, 0xc00000ff);\n\t}\n\n\tfons__flush(stash);\n}\n\nFONS_DEF float fonsTextBounds(FONScontext* stash,\n\t\t\t\t\t float x, float y,\n\t\t\t\t\t const char* str, const char* end,\n\t\t\t\t\t float* bounds)\n{\n\tFONSstate* state = fons__getState(stash);\n\tunsigned int codepoint;\n\tunsigned int utf8state = 0;\n\tFONSquad q;\n\tFONSglyph* glyph = NULL;\n\tint prevGlyphIndex = -1;\n\tshort isize = (short)(state->size*10.0f);\n\tshort iblur = (short)state->blur;\n\tfloat scale;\n\tFONSfont* font;\n\tfloat startx, advance;\n\tfloat minx, miny, maxx, maxy;\n\n\tif (stash == NULL) return 0;\n\tif (state->font < 0 || state->font >= stash->nfonts) return 0;\n\tfont = stash->fonts[state->font];\n\tif (font->data == NULL) return 0;\n\n\tscale = fons__tt_getPixelHeightScale(&font->font, (float)isize/10.0f);\n\n\t// Align vertically.\n\ty += fons__getVertAlign(stash, font, state->align, isize);\n\n\tminx = maxx = x;\n\tminy = maxy = y;\n\tstartx = x;\n\n\tif (end == NULL)\n\t\tend = str + strlen(str);\n\n\tfor (; str != end; ++str) {\n\t\tif (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str))\n\t\t\tcontinue;\n\t\tglyph = fons__getGlyph(stash, font, codepoint, isize, iblur);\n\t\tif (glyph != NULL) {\n\t\t\tfons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q);\n\t\t\tif (q.x0 < minx) minx = q.x0;\n\t\t\tif (q.x1 > maxx) maxx = q.x1;\n\t\t\tif (stash->params.flags & FONS_ZERO_TOPLEFT) {\n\t\t\t\tif (q.y0 < miny) miny = q.y0;\n\t\t\t\tif (q.y1 > maxy) maxy = q.y1;\n\t\t\t} else {\n\t\t\t\tif (q.y1 < miny) miny = q.y1;\n\t\t\t\tif (q.y0 > maxy) maxy = q.y0;\n\t\t\t}\n\t\t}\n\t\tprevGlyphIndex = glyph != NULL ? glyph->index : -1;\n\t}\n\n\tadvance = x - startx;\n\n\t// Align horizontally\n\tif (state->align & FONS_ALIGN_LEFT) {\n\t\t// empty\n\t} else if (state->align & FONS_ALIGN_RIGHT) {\n\t\tminx -= advance;\n\t\tmaxx -= advance;\n\t} else if (state->align & FONS_ALIGN_CENTER) {\n\t\tminx -= advance * 0.5f;\n\t\tmaxx -= advance * 0.5f;\n\t}\n\n\tif (bounds) {\n\t\tbounds[0] = minx;\n\t\tbounds[1] = miny;\n\t\tbounds[2] = maxx;\n\t\tbounds[3] = maxy;\n\t}\n\n\treturn advance;\n}\n\nFONS_DEF void fonsVertMetrics(FONScontext* stash,\n\t\t\t\t\t float* ascender, float* descender, float* lineh)\n{\n\tFONSfont* font;\n\tFONSstate* state = fons__getState(stash);\n\tshort isize;\n\n\tif (stash == NULL) return;\n\tif (state->font < 0 || state->font >= stash->nfonts) return;\n\tfont = stash->fonts[state->font];\n\tisize = (short)(state->size*10.0f);\n\tif (font->data == NULL) return;\n\n\tif (ascender)\n\t\t*ascender = font->ascender*isize/10.0f;\n\tif (descender)\n\t\t*descender = font->descender*isize/10.0f;\n\tif (lineh)\n\t\t*lineh = font->lineh*isize/10.0f;\n}\n\nFONS_DEF void fonsLineBounds(FONScontext* stash, float y, float* miny, float* maxy)\n{\n\tFONSfont* font;\n\tFONSstate* state = fons__getState(stash);\n\tshort isize;\n\n\tif (stash == NULL) return;\n\tif (state->font < 0 || state->font >= stash->nfonts) return;\n\tfont = stash->fonts[state->font];\n\tisize = (short)(state->size*10.0f);\n\tif (font->data == NULL) return;\n\n\ty += fons__getVertAlign(stash, font, state->align, isize);\n\n\tif (stash->params.flags & FONS_ZERO_TOPLEFT) {\n\t\t*miny = y - font->ascender * (float)isize/10.0f;\n\t\t*maxy = *miny + font->lineh*isize/10.0f;\n\t} else {\n\t\t*maxy = y + font->descender * (float)isize/10.0f;\n\t\t*miny = *maxy - font->lineh*isize/10.0f;\n\t}\n}\n\nFONS_DEF const unsigned char* fonsGetTextureData(FONScontext* stash, int* width, int* height)\n{\n\tif (width != NULL)\n\t\t*width = stash->params.width;\n\tif (height != NULL)\n\t\t*height = stash->params.height;\n\treturn stash->texData;\n}\n\nFONS_DEF int fonsValidateTexture(FONScontext* stash, int* dirty)\n{\n\tif (stash->dirtyRect[0] < stash->dirtyRect[2] && stash->dirtyRect[1] < stash->dirtyRect[3]) {\n\t\tdirty[0] = stash->dirtyRect[0];\n\t\tdirty[1] = stash->dirtyRect[1];\n\t\tdirty[2] = stash->dirtyRect[2];\n\t\tdirty[3] = stash->dirtyRect[3];\n\t\t// Reset dirty rect\n\t\tstash->dirtyRect[0] = stash->params.width;\n\t\tstash->dirtyRect[1] = stash->params.height;\n\t\tstash->dirtyRect[2] = 0;\n\t\tstash->dirtyRect[3] = 0;\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nFONS_DEF void fonsDeleteInternal(FONScontext* stash)\n{\n\tint i;\n\tif (stash == NULL) return;\n\n\tif (stash->params.renderDelete)\n\t\tstash->params.renderDelete(stash->params.userPtr);\n\n\tfor (i = 0; i < stash->nfonts; ++i)\n\t\tfons__freeFont(stash->fonts[i]);\n\n\tif (stash->atlas) fons__deleteAtlas(stash->atlas);\n\tif (stash->fonts) FONTSTASH_FREE(stash->fonts);\n\tif (stash->texData) FONTSTASH_FREE(stash->texData);\n\tif (stash->scratch) FONTSTASH_FREE(stash->scratch);\n\tFONTSTASH_FREE(stash);\n}\n\nFONS_DEF void fonsSetErrorCallback(FONScontext* stash, void (*callback)(void* uptr, int error, int val), void* uptr)\n{\n\tif (stash == NULL) return;\n\tstash->handleError = callback;\n\tstash->errorUptr = uptr;\n}\n\nFONS_DEF void fonsGetAtlasSize(FONScontext* stash, int* width, int* height)\n{\n\tif (stash == NULL) return;\n\t*width = stash->params.width;\n\t*height = stash->params.height;\n}\n\nFONS_DEF int fonsExpandAtlas(FONScontext* stash, int width, int height)\n{\n\tint i, maxy = 0;\n\tunsigned char* data = NULL;\n\tif (stash == NULL) return 0;\n\n\twidth = fons__maxi(width, stash->params.width);\n\theight = fons__maxi(height, stash->params.height);\n\n\tif (width == stash->params.width && height == stash->params.height)\n\t\treturn 1;\n\n\t// Flush pending glyphs.\n\tfons__flush(stash);\n\n\t// Create new texture\n\tif (stash->params.renderResize != NULL) {\n\t\tif (stash->params.renderResize(stash->params.userPtr, width, height) == 0)\n\t\t\treturn 0;\n\t}\n\t// Copy old texture data over.\n\tdata = (unsigned char*)FONTSTASH_MALLOC_ATOMIC(width * height);\n\tif (data == NULL)\n\t\treturn 0;\n\tfor (i = 0; i < stash->params.height; i++) {\n\t\tunsigned char* dst = &data[i*width];\n\t\tunsigned char* src = &stash->texData[i*stash->params.width];\n\t\tmemcpy(dst, src, stash->params.width);\n\t\tif (width > stash->params.width)\n\t\t\tmemset(dst+stash->params.width, 0, width - stash->params.width);\n\t}\n\tif (height > stash->params.height)\n\t\tmemset(&data[stash->params.height * width], 0, (height - stash->params.height) * width);\n\n\tFONTSTASH_FREE(stash->texData);\n\tstash->texData = data;\n\n\t// Increase atlas size\n\tfons__atlasExpand(stash->atlas, width, height);\n\n\t// Add existing data as dirty.\n\tfor (i = 0; i < stash->atlas->nnodes; i++)\n\t\tmaxy = fons__maxi(maxy, stash->atlas->nodes[i].y);\n\tstash->dirtyRect[0] = 0;\n\tstash->dirtyRect[1] = 0;\n\tstash->dirtyRect[2] = stash->params.width;\n\tstash->dirtyRect[3] = maxy;\n\n\tstash->params.width = width;\n\tstash->params.height = height;\n\tstash->itw = 1.0f/stash->params.width;\n\tstash->ith = 1.0f/stash->params.height;\n\n\treturn 1;\n}\n\nFONS_DEF int fonsResetAtlas(FONScontext* stash, int width, int height)\n{\n\tint i, j;\n\tif (stash == NULL) return 0;\n\n\t// Flush pending glyphs.\n\tfons__flush(stash);\n\n\t// Create new texture\n\tif (stash->params.renderResize != NULL) {\n\t\tif (stash->params.renderResize(stash->params.userPtr, width, height) == 0)\n\t\t\treturn 0;\n\t}\n\n\t// Reset atlas\n\tfons__atlasReset(stash->atlas, width, height);\n\n\t// Clear texture data.\n\tstash->texData = (unsigned char*)FONTSTASH_REALLOC(stash->texData, width * height);\n\tif (stash->texData == NULL) return 0;\n\tmemset(stash->texData, 0, width * height);\n\n\t// Reset dirty rect\n\tstash->dirtyRect[0] = width;\n\tstash->dirtyRect[1] = height;\n\tstash->dirtyRect[2] = 0;\n\tstash->dirtyRect[3] = 0;\n\n\t// Reset cached glyphs\n\tfor (i = 0; i < stash->nfonts; i++) {\n\t\tFONSfont* font = stash->fonts[i];\n\t\tfont->nglyphs = 0;\n\t\tfor (j = 0; j < FONS_HASH_LUT_SIZE; j++)\n\t\t\tfont->lut[j] = -1;\n\t}\n\n\tstash->params.width = width;\n\tstash->params.height = height;\n\tstash->itw = 1.0f/stash->params.width;\n\tstash->ith = 1.0f/stash->params.height;\n\n\t// Add white rect at 0,0 for debug drawing.\n\tfons__addWhiteRect(stash, 2,2);\n\n\treturn 1;\n}\n\n#endif // FONTSTASH_IMPLEMENTATION\n"
  },
  {
    "path": "thirdparty/fontstash/stb_truetype.h",
    "content": "// stb_truetype.h - v1.26 - public domain\n// authored from 2009-2021 by Sean Barrett / RAD Game Tools\n//\n// =======================================================================\n//\n//    NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES\n//\n// This library does no range checking of the offsets found in the file,\n// meaning an attacker can use it to read arbitrary memory.\n//\n// =======================================================================\n//\n//   This library processes TrueType files:\n//        parse files\n//        extract glyph metrics\n//        extract glyph shapes\n//        render glyphs to one-channel bitmaps with antialiasing (box filter)\n//        render glyphs to one-channel SDF bitmaps (signed-distance field/function)\n//\n//   Todo:\n//        non-MS cmaps\n//        crashproof on bad data\n//        hinting? (no longer patented)\n//        cleartype-style AA?\n//        optimize: use simple memory allocator for intermediates\n//        optimize: build edge-list directly from curves\n//        optimize: rasterize directly from curves?\n//\n// ADDITIONAL CONTRIBUTORS\n//\n//   Mikko Mononen: compound shape support, more cmap formats\n//   Tor Andersson: kerning, subpixel rendering\n//   Dougall Johnson: OpenType / Type 2 font handling\n//   Daniel Ribeiro Maciel: basic GPOS-based kerning\n//\n//   Misc other:\n//       Ryan Gordon\n//       Simon Glass\n//       github:IntellectualKitty\n//       Imanol Celaya\n//       Daniel Ribeiro Maciel\n//\n//   Bug/warning reports/fixes:\n//       \"Zer\" on mollyrocket       Fabian \"ryg\" Giesen   github:NiLuJe\n//       Cass Everitt               Martins Mozeiko       github:aloucks\n//       stoiko (Haemimont Games)   Cap Petschulat        github:oyvindjam\n//       Brian Hook                 Omar Cornut           github:vassvik\n//       Walter van Niftrik         Ryan Griege\n//       David Gow                  Peter LaValle\n//       David Given                Sergey Popov\n//       Ivan-Assen Ivanov          Giumo X. Clanjor\n//       Anthony Pesch              Higor Euripedes\n//       Johan Duparc               Thomas Fields\n//       Hou Qiming                 Derek Vinyard\n//       Rob Loach                  Cort Stratton\n//       Kenney Phillis Jr.         Brian Costabile\n//       Ken Voskuil (kaesve)\n//\n// VERSION HISTORY\n//\n//   1.26 (2021-08-28) fix broken rasterizer\n//   1.25 (2021-07-11) many fixes\n//   1.24 (2020-02-05) fix warning\n//   1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)\n//   1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined\n//   1.21 (2019-02-25) fix warning\n//   1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()\n//   1.19 (2018-02-11) GPOS kerning, STBTT_fmod\n//   1.18 (2018-01-29) add missing function\n//   1.17 (2017-07-23) make more arguments const; doc fix\n//   1.16 (2017-07-12) SDF support\n//   1.15 (2017-03-03) make more arguments const\n//   1.14 (2017-01-16) num-fonts-in-TTC function\n//   1.13 (2017-01-02) support OpenType fonts, certain Apple fonts\n//   1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual\n//   1.11 (2016-04-02) fix unused-variable warning\n//   1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef\n//   1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly\n//   1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges\n//   1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;\n//                     variant PackFontRanges to pack and render in separate phases;\n//                     fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);\n//                     fixed an assert() bug in the new rasterizer\n//                     replace assert() with STBTT_assert() in new rasterizer\n//\n//   Full history can be found at the end of this file.\n//\n// LICENSE\n//\n//   See end of file for license information.\n//\n// USAGE\n//\n//   Include this file in whatever places need to refer to it. In ONE C/C++\n//   file, write:\n//      #define STB_TRUETYPE_IMPLEMENTATION\n//   before the #include of this file. This expands out the actual\n//   implementation into that C/C++ file.\n//\n//   To make the implementation private to the file that generates the implementation,\n//      #define STBTT_STATIC\n//\n//   Simple 3D API (don't ship this, but it's fine for tools and quick start)\n//           stbtt_BakeFontBitmap()               -- bake a font to a bitmap for use as texture\n//           stbtt_GetBakedQuad()                 -- compute quad to draw for a given char\n//\n//   Improved 3D API (more shippable):\n//           #include \"stb_rect_pack.h\"           -- optional, but you really want it\n//           stbtt_PackBegin()\n//           stbtt_PackSetOversampling()          -- for improved quality on small fonts\n//           stbtt_PackFontRanges()               -- pack and renders\n//           stbtt_PackEnd()\n//           stbtt_GetPackedQuad()\n//\n//   \"Load\" a font file from a memory buffer (you have to keep the buffer loaded)\n//           stbtt_InitFont()\n//           stbtt_GetFontOffsetForIndex()        -- indexing for TTC font collections\n//           stbtt_GetNumberOfFonts()             -- number of fonts for TTC font collections\n//\n//   Render a unicode codepoint to a bitmap\n//           stbtt_GetCodepointBitmap()           -- allocates and returns a bitmap\n//           stbtt_MakeCodepointBitmap()          -- renders into bitmap you provide\n//           stbtt_GetCodepointBitmapBox()        -- how big the bitmap must be\n//\n//   Character advance/positioning\n//           stbtt_GetCodepointHMetrics()\n//           stbtt_GetFontVMetrics()\n//           stbtt_GetFontVMetricsOS2()\n//           stbtt_GetCodepointKernAdvance()\n//\n//   Starting with version 1.06, the rasterizer was replaced with a new,\n//   faster and generally-more-precise rasterizer. The new rasterizer more\n//   accurately measures pixel coverage for anti-aliasing, except in the case\n//   where multiple shapes overlap, in which case it overestimates the AA pixel\n//   coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If\n//   this turns out to be a problem, you can re-enable the old rasterizer with\n//        #define STBTT_RASTERIZER_VERSION 1\n//   which will incur about a 15% speed hit.\n//\n// ADDITIONAL DOCUMENTATION\n//\n//   Immediately after this block comment are a series of sample programs.\n//\n//   After the sample programs is the \"header file\" section. This section\n//   includes documentation for each API function.\n//\n//   Some important concepts to understand to use this library:\n//\n//      Codepoint\n//         Characters are defined by unicode codepoints, e.g. 65 is\n//         uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is\n//         the hiragana for \"ma\".\n//\n//      Glyph\n//         A visual character shape (every codepoint is rendered as\n//         some glyph)\n//\n//      Glyph index\n//         A font-specific integer ID representing a glyph\n//\n//      Baseline\n//         Glyph shapes are defined relative to a baseline, which is the\n//         bottom of uppercase characters. Characters extend both above\n//         and below the baseline.\n//\n//      Current Point\n//         As you draw text to the screen, you keep track of a \"current point\"\n//         which is the origin of each character. The current point's vertical\n//         position is the baseline. Even \"baked fonts\" use this model.\n//\n//      Vertical Font Metrics\n//         The vertical qualities of the font, used to vertically position\n//         and space the characters. See docs for stbtt_GetFontVMetrics.\n//\n//      Font Size in Pixels or Points\n//         The preferred interface for specifying font sizes in stb_truetype\n//         is to specify how tall the font's vertical extent should be in pixels.\n//         If that sounds good enough, skip the next paragraph.\n//\n//         Most font APIs instead use \"points\", which are a common typographic\n//         measurement for describing font size, defined as 72 points per inch.\n//         stb_truetype provides a point API for compatibility. However, true\n//         \"per inch\" conventions don't make much sense on computer displays\n//         since different monitors have different number of pixels per\n//         inch. For example, Windows traditionally uses a convention that\n//         there are 96 pixels per inch, thus making 'inch' measurements have\n//         nothing to do with inches, and thus effectively defining a point to\n//         be 1.333 pixels. Additionally, the TrueType font data provides\n//         an explicit scale factor to scale a given font's glyphs to points,\n//         but the author has observed that this scale factor is often wrong\n//         for non-commercial fonts, thus making fonts scaled in points\n//         according to the TrueType spec incoherently sized in practice.\n//\n// DETAILED USAGE:\n//\n//  Scale:\n//    Select how high you want the font to be, in points or pixels.\n//    Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute\n//    a scale factor SF that will be used by all other functions.\n//\n//  Baseline:\n//    You need to select a y-coordinate that is the baseline of where\n//    your text will appear. Call GetFontBoundingBox to get the baseline-relative\n//    bounding box for all characters. SF*-y0 will be the distance in pixels\n//    that the worst-case character could extend above the baseline, so if\n//    you want the top edge of characters to appear at the top of the\n//    screen where y=0, then you would set the baseline to SF*-y0.\n//\n//  Current point:\n//    Set the current point where the first character will appear. The\n//    first character could extend left of the current point; this is font\n//    dependent. You can either choose a current point that is the leftmost\n//    point and hope, or add some padding, or check the bounding box or\n//    left-side-bearing of the first character to be displayed and set\n//    the current point based on that.\n//\n//  Displaying a character:\n//    Compute the bounding box of the character. It will contain signed values\n//    relative to <current_point, baseline>. I.e. if it returns x0,y0,x1,y1,\n//    then the character should be displayed in the rectangle from\n//    <current_point+SF*x0, baseline+SF*y0> to <current_point+SF*x1,baseline+SF*y1).\n//\n//  Advancing for the next character:\n//    Call GlyphHMetrics, and compute 'current_point += SF * advance'.\n//\n//\n// ADVANCED USAGE\n//\n//   Quality:\n//\n//    - Use the functions with Subpixel at the end to allow your characters\n//      to have subpixel positioning. Since the font is anti-aliased, not\n//      hinted, this is very import for quality. (This is not possible with\n//      baked fonts.)\n//\n//    - Kerning is now supported, and if you're supporting subpixel rendering\n//      then kerning is worth using to give your text a polished look.\n//\n//   Performance:\n//\n//    - Convert Unicode codepoints to glyph indexes and operate on the glyphs;\n//      if you don't do this, stb_truetype is forced to do the conversion on\n//      every call.\n//\n//    - There are a lot of memory allocations. We should modify it to take\n//      a temp buffer and allocate from the temp buffer (without freeing),\n//      should help performance a lot.\n//\n// NOTES\n//\n//   The system uses the raw data found in the .ttf file without changing it\n//   and without building auxiliary data structures. This is a bit inefficient\n//   on little-endian systems (the data is big-endian), but assuming you're\n//   caching the bitmaps or glyph shapes this shouldn't be a big deal.\n//\n//   It appears to be very hard to programmatically determine what font a\n//   given file is in a general way. I provide an API for this, but I don't\n//   recommend it.\n//\n//\n// PERFORMANCE MEASUREMENTS FOR 1.06:\n//\n//                      32-bit     64-bit\n//   Previous release:  8.83 s     7.68 s\n//   Pool allocations:  7.72 s     6.34 s\n//   Inline sort     :  6.54 s     5.65 s\n//   New rasterizer  :  5.63 s     5.00 s\n\n//////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////////////////////////////////////////////\n////\n////  SAMPLE PROGRAMS\n////\n//\n//  Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless.\n//  See \"tests/truetype_demo_win32.c\" for a complete version.\n#if 0\n#define STB_TRUETYPE_IMPLEMENTATION  // force following include to generate implementation\n#include \"stb_truetype.h\"\n\nunsigned char ttf_buffer[1<<20];\nunsigned char temp_bitmap[512*512];\n\nstbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs\nGLuint ftex;\n\nvoid my_stbtt_initfont(void)\n{\n   fread(ttf_buffer, 1, 1<<20, fopen(\"c:/windows/fonts/times.ttf\", \"rb\"));\n   stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits!\n   // can free ttf_buffer at this point\n   glGenTextures(1, &ftex);\n   glBindTexture(GL_TEXTURE_2D, ftex);\n   glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);\n   // can free temp_bitmap at this point\n   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\n}\n\nvoid my_stbtt_print(float x, float y, char *text)\n{\n   // assume orthographic projection with units = screen pixels, origin at top left\n   glEnable(GL_BLEND);\n   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\n   glEnable(GL_TEXTURE_2D);\n   glBindTexture(GL_TEXTURE_2D, ftex);\n   glBegin(GL_QUADS);\n   while (*text) {\n      if (*text >= 32 && *text < 128) {\n         stbtt_aligned_quad q;\n         stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9\n         glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0);\n         glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0);\n         glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1);\n         glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1);\n      }\n      ++text;\n   }\n   glEnd();\n}\n#endif\n//\n//\n//////////////////////////////////////////////////////////////////////////////\n//\n// Complete program (this compiles): get a single bitmap, print as ASCII art\n//\n#if 0\n#include <stdio.h>\n#define STB_TRUETYPE_IMPLEMENTATION  // force following include to generate implementation\n#include \"stb_truetype.h\"\n\nchar ttf_buffer[1<<25];\n\nint main(int argc, char **argv)\n{\n   stbtt_fontinfo font;\n   unsigned char *bitmap;\n   int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);\n\n   fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : \"c:/windows/fonts/arialbd.ttf\", \"rb\"));\n\n   stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));\n   bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);\n\n   for (j=0; j < h; ++j) {\n      for (i=0; i < w; ++i)\n         putchar(\" .:ioVM@\"[bitmap[j*w+i]>>5]);\n      putchar('\\n');\n   }\n   return 0;\n}\n#endif\n//\n// Output:\n//\n//     .ii.\n//    @@@@@@.\n//   V@Mio@@o\n//   :i.  V@V\n//     :oM@@M\n//   :@@@MM@M\n//   @@o  o@M\n//  :@@.  M@M\n//   @@@o@@@@\n//   :M@@V:@@.\n//\n//////////////////////////////////////////////////////////////////////////////\n//\n// Complete program: print \"Hello World!\" banner, with bugs\n//\n#if 0\nchar buffer[24<<20];\nunsigned char screen[20][79];\n\nint main(int arg, char **argv)\n{\n   stbtt_fontinfo font;\n   int i,j,ascent,baseline,ch=0;\n   float scale, xpos=2; // leave a little padding in case the character extends left\n   char *text = \"Heljo World!\"; // intentionally misspelled to show 'lj' brokenness\n\n   fread(buffer, 1, 1000000, fopen(\"c:/windows/fonts/arialbd.ttf\", \"rb\"));\n   stbtt_InitFont(&font, buffer, 0);\n\n   scale = stbtt_ScaleForPixelHeight(&font, 15);\n   stbtt_GetFontVMetrics(&font, &ascent,0,0);\n   baseline = (int) (ascent*scale);\n\n   while (text[ch]) {\n      int advance,lsb,x0,y0,x1,y1;\n      float x_shift = xpos - (float) floor(xpos);\n      stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);\n      stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);\n      stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);\n      // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong\n      // because this API is really for baking character bitmaps into textures. if you want to render\n      // a sequence of characters, you really need to render each bitmap to a temp buffer, then\n      // \"alpha blend\" that into the working buffer\n      xpos += (advance * scale);\n      if (text[ch+1])\n         xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);\n      ++ch;\n   }\n\n   for (j=0; j < 20; ++j) {\n      for (i=0; i < 78; ++i)\n         putchar(\" .:ioVM@\"[screen[j][i]>>5]);\n      putchar('\\n');\n   }\n\n   return 0;\n}\n#endif\n\n\n//////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////////////////////////////////////////////\n////\n////   INTEGRATION WITH YOUR CODEBASE\n////\n////   The following sections allow you to supply alternate definitions\n////   of C library functions used by stb_truetype, e.g. if you don't\n////   link with the C runtime library.\n\n#ifdef STB_TRUETYPE_IMPLEMENTATION\n   // #define your own (u)stbtt_int8/16/32 before including to override this\n   #ifndef stbtt_uint8\n   typedef unsigned char   stbtt_uint8;\n   typedef signed   char   stbtt_int8;\n   typedef unsigned short  stbtt_uint16;\n   typedef signed   short  stbtt_int16;\n   typedef unsigned int    stbtt_uint32;\n   typedef signed   int    stbtt_int32;\n   #endif\n\n   typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];\n   typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];\n\n   // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h\n   #ifndef STBTT_ifloor\n   #include <math.h>\n   #define STBTT_ifloor(x)   ((int) floor(x))\n   #define STBTT_iceil(x)    ((int) ceil(x))\n   #endif\n\n   #ifndef STBTT_sqrt\n   #include <math.h>\n   #define STBTT_sqrt(x)      sqrt(x)\n   #define STBTT_pow(x,y)     pow(x,y)\n   #endif\n\n   #ifndef STBTT_fmod\n   #include <math.h>\n   #define STBTT_fmod(x,y)    fmod(x,y)\n   #endif\n\n   #ifndef STBTT_cos\n   #include <math.h>\n   #define STBTT_cos(x)       cos(x)\n   #define STBTT_acos(x)      acos(x)\n   #endif\n\n   #ifndef STBTT_fabs\n   #include <math.h>\n   #define STBTT_fabs(x)      fabs(x)\n   #endif\n\n   // #define your own functions \"STBTT_malloc\" / \"STBTT_free\" to avoid malloc.h\n   #ifndef STBTT_malloc\n   #include <stdlib.h>\n   #define STBTT_malloc(x,u)  ((void)(u),FONTSTASH_MALLOC(x))\n   #define STBTT_free(x,u)    ((void)(u),FONTSTASH_FREE(x))\n   #endif\n\n   #ifndef STBTT_assert\n   #include <assert.h>\n   #define STBTT_assert(x)    assert(x)\n   #endif\n\n   #ifndef STBTT_strlen\n   #include <string.h>\n   #define STBTT_strlen(x)    strlen(x)\n   #endif\n\n   #ifndef STBTT_memcpy\n   #include <string.h>\n   #define STBTT_memcpy       memcpy\n   #define STBTT_memset       memset\n   #endif\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n///////////////////////////////////////////////////////////////////////////////\n////\n////   INTERFACE\n////\n////\n\n#ifndef __STB_INCLUDE_STB_TRUETYPE_H__\n#define __STB_INCLUDE_STB_TRUETYPE_H__\n\n#ifdef STBTT_STATIC\n#define STBTT_DEF static\n#else\n#define STBTT_DEF extern\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// private structure\ntypedef struct\n{\n   unsigned char *data;\n   int cursor;\n   int size;\n} stbtt__buf;\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// TEXTURE BAKING API\n//\n// If you use this API, you only have to call two functions ever.\n//\n\ntypedef struct\n{\n   unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap\n   float xoff,yoff,xadvance;\n} stbtt_bakedchar;\n\nSTBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,  // font location (use offset=0 for plain .ttf)\n                                float pixel_height,                     // height of font in pixels\n                                unsigned char *pixels, int pw, int ph,  // bitmap to be filled in\n                                int first_char, int num_chars,          // characters to bake\n                                stbtt_bakedchar *chardata);             // you allocate this, it's num_chars long\n// if return is positive, the first unused row of the bitmap\n// if return is negative, returns the negative of the number of characters that fit\n// if return is 0, no characters fit and no rows were used\n// This uses a very crappy packing.\n\ntypedef struct\n{\n   float x0,y0,s0,t0; // top-left\n   float x1,y1,s1,t1; // bottom-right\n} stbtt_aligned_quad;\n\nSTBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph,  // same data as above\n                               int char_index,             // character to display\n                               float *xpos, float *ypos,   // pointers to current position in screen pixel space\n                               stbtt_aligned_quad *q,      // output: quad to draw\n                               int opengl_fillrule);       // true if opengl fill rule; false if DX9 or earlier\n// Call GetBakedQuad with char_index = 'character - first_char', and it\n// creates the quad you need to draw and advances the current position.\n//\n// The coordinate system used assumes y increases downwards.\n//\n// Characters will extend both above and below the current position;\n// see discussion of \"BASELINE\" above.\n//\n// It's inefficient; you might want to c&p it and optimize it.\n\nSTBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap);\n// Query the font vertical metrics without having to create a font first.\n\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// NEW TEXTURE BAKING API\n//\n// This provides options for packing multiple fonts into one atlas, not\n// perfectly but better than nothing.\n\ntypedef struct\n{\n   unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap\n   float xoff,yoff,xadvance;\n   float xoff2,yoff2;\n} stbtt_packedchar;\n\ntypedef struct stbtt_pack_context stbtt_pack_context;\ntypedef struct stbtt_fontinfo stbtt_fontinfo;\n#ifndef STB_RECT_PACK_VERSION\ntypedef struct stbrp_rect stbrp_rect;\n#endif\n\nSTBTT_DEF int  stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);\n// Initializes a packing context stored in the passed-in stbtt_pack_context.\n// Future calls using this context will pack characters into the bitmap passed\n// in here: a 1-channel bitmap that is width * height. stride_in_bytes is\n// the distance from one row to the next (or 0 to mean they are packed tightly\n// together). \"padding\" is the amount of padding to leave between each\n// character (normally you want '1' for bitmaps you'll use as textures with\n// bilinear filtering).\n//\n// Returns 0 on failure, 1 on success.\n\nSTBTT_DEF void stbtt_PackEnd  (stbtt_pack_context *spc);\n// Cleans up the packing context and frees all memory.\n\n#define STBTT_POINT_SIZE(x)   (-(x))\n\nSTBTT_DEF int  stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,\n                                int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range);\n// Creates character bitmaps from the font_index'th font found in fontdata (use\n// font_index=0 if you don't know what that is). It creates num_chars_in_range\n// bitmaps for characters with unicode values starting at first_unicode_char_in_range\n// and increasing. Data for how to render them is stored in chardata_for_range;\n// pass these to stbtt_GetPackedQuad to get back renderable quads.\n//\n// font_size is the full height of the character from ascender to descender,\n// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed\n// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE()\n// and pass that result as 'font_size':\n//       ...,                  20 , ... // font max minus min y is 20 pixels tall\n//       ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall\n\ntypedef struct\n{\n   float font_size;\n   int first_unicode_codepoint_in_range;  // if non-zero, then the chars are continuous, and this is the first codepoint\n   int *array_of_unicode_codepoints;       // if non-zero, then this is an array of unicode codepoints\n   int num_chars;\n   stbtt_packedchar *chardata_for_range; // output\n   unsigned char h_oversample, v_oversample; // don't set these, they're used internally\n} stbtt_pack_range;\n\nSTBTT_DEF int  stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);\n// Creates character bitmaps from multiple ranges of characters stored in\n// ranges. This will usually create a better-packed bitmap than multiple\n// calls to stbtt_PackFontRange. Note that you can call this multiple\n// times within a single PackBegin/PackEnd.\n\nSTBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);\n// Oversampling a font increases the quality by allowing higher-quality subpixel\n// positioning, and is especially valuable at smaller text sizes.\n//\n// This function sets the amount of oversampling for all following calls to\n// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given\n// pack context. The default (no oversampling) is achieved by h_oversample=1\n// and v_oversample=1. The total number of pixels required is\n// h_oversample*v_oversample larger than the default; for example, 2x2\n// oversampling requires 4x the storage of 1x1. For best results, render\n// oversampled textures with bilinear filtering. Look at the readme in\n// stb/tests/oversample for information about oversampled fonts\n//\n// To use with PackFontRangesGather etc., you must set it before calls\n// call to PackFontRangesGatherRects.\n\nSTBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);\n// If skip != 0, this tells stb_truetype to skip any codepoints for which\n// there is no corresponding glyph. If skip=0, which is the default, then\n// codepoints without a glyph received the font's \"missing character\" glyph,\n// typically an empty box by convention.\n\nSTBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph,  // same data as above\n                               int char_index,             // character to display\n                               float *xpos, float *ypos,   // pointers to current position in screen pixel space\n                               stbtt_aligned_quad *q,      // output: quad to draw\n                               int align_to_integer);\n\nSTBTT_DEF int  stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);\nSTBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects);\nSTBTT_DEF int  stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);\n// Calling these functions in sequence is roughly equivalent to calling\n// stbtt_PackFontRanges(). If you more control over the packing of multiple\n// fonts, or if you want to pack custom data into a font texture, take a look\n// at the source to of stbtt_PackFontRanges() and create a custom version\n// using these functions, e.g. call GatherRects multiple times,\n// building up a single array of rects, then call PackRects once,\n// then call RenderIntoRects repeatedly. This may result in a\n// better packing than calling PackFontRanges multiple times\n// (or it may not).\n\n// this is an opaque structure that you shouldn't mess with which holds\n// all the context needed from PackBegin to PackEnd.\nstruct stbtt_pack_context {\n   void *user_allocator_context;\n   void *pack_info;\n   int   width;\n   int   height;\n   int   stride_in_bytes;\n   int   padding;\n   int   skip_missing;\n   unsigned int   h_oversample, v_oversample;\n   unsigned char *pixels;\n   void  *nodes;\n};\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// FONT LOADING\n//\n//\n\nSTBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data);\n// This function will determine the number of fonts in a font file.  TrueType\n// collection (.ttc) files may contain multiple fonts, while TrueType font\n// (.ttf) files only contain one font. The number of fonts can be used for\n// indexing with the previous function where the index is between zero and one\n// less than the total fonts. If an error occurs, -1 is returned.\n\nSTBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);\n// Each .ttf/.ttc file may have more than one font. Each font has a sequential\n// index number starting from 0. Call this function to get the font offset for\n// a given index; it returns -1 if the index is out of range. A regular .ttf\n// file will only define one font and it always be at offset 0, so it will\n// return '0' for index 0, and -1 for all other indices.\n\n// The following structure is defined publicly so you can declare one on\n// the stack or as a global or etc, but you should treat it as opaque.\nstruct stbtt_fontinfo\n{\n   void           * userdata;\n   unsigned char  * data;              // pointer to .ttf file\n   int              fontstart;         // offset of start of font\n\n   int numGlyphs;                     // number of glyphs, needed for range checking\n\n   int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf\n   int index_map;                     // a cmap mapping for our chosen character encoding\n   int indexToLocFormat;              // format needed to map from glyph index to glyph\n\n   stbtt__buf cff;                    // cff font data\n   stbtt__buf charstrings;            // the charstring index\n   stbtt__buf gsubrs;                 // global charstring subroutines index\n   stbtt__buf subrs;                  // private charstring subroutines index\n   stbtt__buf fontdicts;              // array of font dicts\n   stbtt__buf fdselect;               // map from glyph to fontdict\n};\n\nSTBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);\n// Given an offset into the file that defines a font, this function builds\n// the necessary cached info for the rest of the system. You must allocate\n// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't\n// need to do anything special to free it, because the contents are pure\n// value data with no additional data structures. Returns 0 on failure.\n\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// CHARACTER TO GLYPH-INDEX CONVERSIOn\n\nSTBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);\n// If you're going to perform multiple operations on the same character\n// and you want a speed-up, call this function with the character you're\n// going to process, then use glyph-based functions instead of the\n// codepoint-based functions.\n// Returns 0 if the character codepoint is not defined in the font.\n\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// CHARACTER PROPERTIES\n//\n\nSTBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);\n// computes a scale factor to produce a font whose \"height\" is 'pixels' tall.\n// Height is measured as the distance from the highest ascender to the lowest\n// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics\n// and computing:\n//       scale = pixels / (ascent - descent)\n// so if you prefer to measure height by the ascent only, use a similar calculation.\n\nSTBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);\n// computes a scale factor to produce a font whose EM size is mapped to\n// 'pixels' tall. This is probably what traditional APIs compute, but\n// I'm not positive.\n\nSTBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);\n// ascent is the coordinate above the baseline the font extends; descent\n// is the coordinate below the baseline the font extends (i.e. it is typically negative)\n// lineGap is the spacing between one row's descent and the next row's ascent...\n// so you should advance the vertical position by \"*ascent - *descent + *lineGap\"\n//   these are expressed in unscaled coordinates, so you must multiply by\n//   the scale factor for a given size\n\nSTBTT_DEF int  stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap);\n// analogous to GetFontVMetrics, but returns the \"typographic\" values from the OS/2\n// table (specific to MS/Windows TTF files).\n//\n// Returns 1 on success (table present), 0 on failure.\n\nSTBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);\n// the bounding box around all possible characters\n\nSTBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);\n// leftSideBearing is the offset from the current horizontal position to the left edge of the character\n// advanceWidth is the offset from the current horizontal position to the next horizontal position\n//   these are expressed in unscaled coordinates\n\nSTBTT_DEF int  stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);\n// an additional amount to add to the 'advance' value between ch1 and ch2\n\nSTBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);\n// Gets the bounding box of the visible part of the glyph, in unscaled coordinates\n\nSTBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);\nSTBTT_DEF int  stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);\nSTBTT_DEF int  stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);\n// as above, but takes one or more glyph indices for greater efficiency\n\ntypedef struct stbtt_kerningentry\n{\n   int glyph1; // use stbtt_FindGlyphIndex\n   int glyph2;\n   int advance;\n} stbtt_kerningentry;\n\nSTBTT_DEF int  stbtt_GetKerningTableLength(const stbtt_fontinfo *info);\nSTBTT_DEF int  stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length);\n// Retrieves a complete list of all of the kerning pairs provided by the font\n// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write.\n// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1)\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// GLYPH SHAPES (you probably don't need these, but they have to go before\n// the bitmaps for C declaration-order reasons)\n//\n\n#ifndef STBTT_vmove // you can predefine these to use different values (but why?)\n   enum {\n      STBTT_vmove=1,\n      STBTT_vline,\n      STBTT_vcurve,\n      STBTT_vcubic\n   };\n#endif\n\n#ifndef stbtt_vertex // you can predefine this to use different values\n                   // (we share this with other code at RAD)\n   #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file\n   typedef struct\n   {\n      stbtt_vertex_type x,y,cx,cy,cx1,cy1;\n      unsigned char type,padding;\n   } stbtt_vertex;\n#endif\n\nSTBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);\n// returns non-zero if nothing is drawn for this glyph\n\nSTBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);\nSTBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);\n// returns # of vertices and fills *vertices with the pointer to them\n//   these are expressed in \"unscaled\" coordinates\n//\n// The shape is a series of contours. Each one starts with\n// a STBTT_moveto, then consists of a series of mixed\n// STBTT_lineto and STBTT_curveto segments. A lineto\n// draws a line from previous endpoint to its x,y; a curveto\n// draws a quadratic bezier from previous endpoint to\n// its x,y, using cx,cy as the bezier control point.\n\nSTBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);\n// frees the data allocated above\n\nSTBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl);\nSTBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);\nSTBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);\n// fills svg with the character's SVG data.\n// returns data size or 0 if SVG not found.\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// BITMAP RENDERING\n//\n\nSTBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);\n// frees the bitmap allocated below\n\nSTBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);\n// allocates a large-enough single-channel 8bpp bitmap and renders the\n// specified character/glyph at the specified scale into it, with\n// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque).\n// *width & *height are filled out with the width & height of the bitmap,\n// which is stored left-to-right, top-to-bottom.\n//\n// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap\n\nSTBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);\n// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel\n// shift for the character\n\nSTBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);\n// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap\n// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap\n// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the\n// width and height and positioning info for it first.\n\nSTBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint);\n// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel\n// shift for the character\n\nSTBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint);\n// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering\n// is performed (see stbtt_PackSetOversampling)\n\nSTBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);\n// get the bbox of the bitmap centered around the glyph origin; so the\n// bitmap width is ix1-ix0, height is iy1-iy0, and location to place\n// the bitmap top left is (leftSideBearing*scale,iy0).\n// (Note that the bitmap uses y-increases-down, but the shape uses\n// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)\n\nSTBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);\n// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel\n// shift for the character\n\n// the following functions are equivalent to the above functions, but operate\n// on glyph indices instead of Unicode codepoints (for efficiency)\nSTBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);\nSTBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff);\nSTBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph);\nSTBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph);\nSTBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph);\nSTBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);\nSTBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);\n\n\n// @TODO: don't expose this structure\ntypedef struct\n{\n   int w,h,stride;\n   unsigned char *pixels;\n} stbtt__bitmap;\n\n// rasterize a shape with quadratic beziers into a bitmap\nSTBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result,        // 1-channel bitmap to draw into\n                               float flatness_in_pixels,     // allowable error of curve in pixels\n                               stbtt_vertex *vertices,       // array of vertices defining shape\n                               int num_verts,                // number of vertices in above array\n                               float scale_x, float scale_y, // scale applied to input vertices\n                               float shift_x, float shift_y, // translation applied to input vertices\n                               int x_off, int y_off,         // another translation applied to input\n                               int invert,                   // if non-zero, vertically flip shape\n                               void *userdata);              // context for to STBTT_MALLOC\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// Signed Distance Function (or Field) rendering\n\nSTBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata);\n// frees the SDF bitmap allocated below\n\nSTBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);\nSTBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);\n// These functions compute a discretized SDF field for a single character, suitable for storing\n// in a single-channel texture, sampling with bilinear filtering, and testing against\n// larger than some threshold to produce scalable fonts.\n//        info              --  the font\n//        scale             --  controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap\n//        glyph/codepoint   --  the character to generate the SDF for\n//        padding           --  extra \"pixels\" around the character which are filled with the distance to the character (not 0),\n//                                 which allows effects like bit outlines\n//        onedge_value      --  value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character)\n//        pixel_dist_scale  --  what value the SDF should increase by when moving one SDF \"pixel\" away from the edge (on the 0..255 scale)\n//                                 if positive, > onedge_value is inside; if negative, < onedge_value is inside\n//        width,height      --  output height & width of the SDF bitmap (including padding)\n//        xoff,yoff         --  output origin of the character\n//        return value      --  a 2D array of bytes 0..255, width*height in size\n//\n// pixel_dist_scale & onedge_value are a scale & bias that allows you to make\n// optimal use of the limited 0..255 for your application, trading off precision\n// and special effects. SDF values outside the range 0..255 are clamped to 0..255.\n//\n// Example:\n//      scale = stbtt_ScaleForPixelHeight(22)\n//      padding = 5\n//      onedge_value = 180\n//      pixel_dist_scale = 180/5.0 = 36.0\n//\n//      This will create an SDF bitmap in which the character is about 22 pixels\n//      high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled\n//      shape, sample the SDF at each pixel and fill the pixel if the SDF value\n//      is greater than or equal to 180/255. (You'll actually want to antialias,\n//      which is beyond the scope of this example.) Additionally, you can compute\n//      offset outlines (e.g. to stroke the character border inside & outside,\n//      or only outside). For example, to fill outside the character up to 3 SDF\n//      pixels, you would compare against (180-36.0*3)/255 = 72/255. The above\n//      choice of variables maps a range from 5 pixels outside the shape to\n//      2 pixels inside the shape to 0..255; this is intended primarily for apply\n//      outside effects only (the interior range is needed to allow proper\n//      antialiasing of the font at *smaller* sizes)\n//\n// The function computes the SDF analytically at each SDF pixel, not by e.g.\n// building a higher-res bitmap and approximating it. In theory the quality\n// should be as high as possible for an SDF of this size & representation, but\n// unclear if this is true in practice (perhaps building a higher-res bitmap\n// and computing from that can allow drop-out prevention).\n//\n// The algorithm has not been optimized at all, so expect it to be slow\n// if computing lots of characters or very large sizes.\n\n\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// Finding the right font...\n//\n// You should really just solve this offline, keep your own tables\n// of what font is what, and don't try to get it out of the .ttf file.\n// That's because getting it out of the .ttf file is really hard, because\n// the names in the file can appear in many possible encodings, in many\n// possible languages, and e.g. if you need a case-insensitive comparison,\n// the details of that depend on the encoding & language in a complex way\n// (actually underspecified in truetype, but also gigantic).\n//\n// But you can use the provided functions in two possible ways:\n//     stbtt_FindMatchingFont() will use *case-sensitive* comparisons on\n//             unicode-encoded names to try to find the font you want;\n//             you can run this before calling stbtt_InitFont()\n//\n//     stbtt_GetFontNameString() lets you get any of the various strings\n//             from the file yourself and do your own comparisons on them.\n//             You have to have called stbtt_InitFont() first.\n\n\nSTBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);\n// returns the offset (not index) of the font that matches, or -1 if none\n//   if you use STBTT_MACSTYLE_DONTCARE, use a font name like \"Arial Bold\".\n//   if you use any other flag, use a font name like \"Arial\"; this checks\n//     the 'macStyle' header field; i don't know if fonts set this consistently\n#define STBTT_MACSTYLE_DONTCARE     0\n#define STBTT_MACSTYLE_BOLD         1\n#define STBTT_MACSTYLE_ITALIC       2\n#define STBTT_MACSTYLE_UNDERSCORE   4\n#define STBTT_MACSTYLE_NONE         8   // <= not same as 0, this makes us check the bitfield is 0\n\nSTBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);\n// returns 1/0 whether the first string interpreted as utf8 is identical to\n// the second string interpreted as big-endian utf16... useful for strings from next func\n\nSTBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);\n// returns the string (which may be big-endian double byte, e.g. for unicode)\n// and puts the length in bytes in *length.\n//\n// some of the values for the IDs are below; for more see the truetype spec:\n//     http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html\n//     http://www.microsoft.com/typography/otspec/name.htm\n\nenum { // platformID\n   STBTT_PLATFORM_ID_UNICODE   =0,\n   STBTT_PLATFORM_ID_MAC       =1,\n   STBTT_PLATFORM_ID_ISO       =2,\n   STBTT_PLATFORM_ID_MICROSOFT =3\n};\n\nenum { // encodingID for STBTT_PLATFORM_ID_UNICODE\n   STBTT_UNICODE_EID_UNICODE_1_0    =0,\n   STBTT_UNICODE_EID_UNICODE_1_1    =1,\n   STBTT_UNICODE_EID_ISO_10646      =2,\n   STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,\n   STBTT_UNICODE_EID_UNICODE_2_0_FULL=4\n};\n\nenum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT\n   STBTT_MS_EID_SYMBOL        =0,\n   STBTT_MS_EID_UNICODE_BMP   =1,\n   STBTT_MS_EID_SHIFTJIS      =2,\n   STBTT_MS_EID_UNICODE_FULL  =10\n};\n\nenum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes\n   STBTT_MAC_EID_ROMAN        =0,   STBTT_MAC_EID_ARABIC       =4,\n   STBTT_MAC_EID_JAPANESE     =1,   STBTT_MAC_EID_HEBREW       =5,\n   STBTT_MAC_EID_CHINESE_TRAD =2,   STBTT_MAC_EID_GREEK        =6,\n   STBTT_MAC_EID_KOREAN       =3,   STBTT_MAC_EID_RUSSIAN      =7\n};\n\nenum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...\n       // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs\n   STBTT_MS_LANG_ENGLISH     =0x0409,   STBTT_MS_LANG_ITALIAN     =0x0410,\n   STBTT_MS_LANG_CHINESE     =0x0804,   STBTT_MS_LANG_JAPANESE    =0x0411,\n   STBTT_MS_LANG_DUTCH       =0x0413,   STBTT_MS_LANG_KOREAN      =0x0412,\n   STBTT_MS_LANG_FRENCH      =0x040c,   STBTT_MS_LANG_RUSSIAN     =0x0419,\n   STBTT_MS_LANG_GERMAN      =0x0407,   STBTT_MS_LANG_SPANISH     =0x0409,\n   STBTT_MS_LANG_HEBREW      =0x040d,   STBTT_MS_LANG_SWEDISH     =0x041D\n};\n\nenum { // languageID for STBTT_PLATFORM_ID_MAC\n   STBTT_MAC_LANG_ENGLISH      =0 ,   STBTT_MAC_LANG_JAPANESE     =11,\n   STBTT_MAC_LANG_ARABIC       =12,   STBTT_MAC_LANG_KOREAN       =23,\n   STBTT_MAC_LANG_DUTCH        =4 ,   STBTT_MAC_LANG_RUSSIAN      =32,\n   STBTT_MAC_LANG_FRENCH       =1 ,   STBTT_MAC_LANG_SPANISH      =6 ,\n   STBTT_MAC_LANG_GERMAN       =2 ,   STBTT_MAC_LANG_SWEDISH      =5 ,\n   STBTT_MAC_LANG_HEBREW       =10,   STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,\n   STBTT_MAC_LANG_ITALIAN      =3 ,   STBTT_MAC_LANG_CHINESE_TRAD =19\n};\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // __STB_INCLUDE_STB_TRUETYPE_H__\n\n///////////////////////////////////////////////////////////////////////////////\n///////////////////////////////////////////////////////////////////////////////\n////\n////   IMPLEMENTATION\n////\n////\n\n#ifdef STB_TRUETYPE_IMPLEMENTATION\n\n#ifndef STBTT_MAX_OVERSAMPLE\n#define STBTT_MAX_OVERSAMPLE   8\n#endif\n\n#if STBTT_MAX_OVERSAMPLE > 255\n#error \"STBTT_MAX_OVERSAMPLE cannot be > 255\"\n#endif\n\ntypedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];\n\n#ifndef STBTT_RASTERIZER_VERSION\n#define STBTT_RASTERIZER_VERSION 2\n#endif\n\n#ifdef _MSC_VER\n#define STBTT__NOTUSED(v)  (void)(v)\n#else\n#define STBTT__NOTUSED(v)  (void)sizeof(v)\n#endif\n\n//////////////////////////////////////////////////////////////////////////\n//\n// stbtt__buf helpers to parse data from file\n//\n\nstatic stbtt_uint8 stbtt__buf_get8(stbtt__buf *b)\n{\n   if (b->cursor >= b->size)\n      return 0;\n   return b->data[b->cursor++];\n}\n\nstatic stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b)\n{\n   if (b->cursor >= b->size)\n      return 0;\n   return b->data[b->cursor];\n}\n\nstatic void stbtt__buf_seek(stbtt__buf *b, int o)\n{\n   STBTT_assert(!(o > b->size || o < 0));\n   b->cursor = (o > b->size || o < 0) ? b->size : o;\n}\n\nstatic void stbtt__buf_skip(stbtt__buf *b, int o)\n{\n   stbtt__buf_seek(b, b->cursor + o);\n}\n\nstatic stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n)\n{\n   stbtt_uint32 v = 0;\n   int i;\n   STBTT_assert(n >= 1 && n <= 4);\n   for (i = 0; i < n; i++)\n      v = (v << 8) | stbtt__buf_get8(b);\n   return v;\n}\n\nstatic stbtt__buf stbtt__new_buf(const void *p, size_t size)\n{\n   stbtt__buf r;\n   STBTT_assert(size < 0x40000000);\n   r.data = (stbtt_uint8*) p;\n   r.size = (int) size;\n   r.cursor = 0;\n   return r;\n}\n\n#define stbtt__buf_get16(b)  stbtt__buf_get((b), 2)\n#define stbtt__buf_get32(b)  stbtt__buf_get((b), 4)\n\nstatic stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s)\n{\n   stbtt__buf r = stbtt__new_buf(NULL, 0);\n   if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r;\n   r.data = b->data + o;\n   r.size = s;\n   return r;\n}\n\nstatic stbtt__buf stbtt__cff_get_index(stbtt__buf *b)\n{\n   int count, start, offsize;\n   start = b->cursor;\n   count = stbtt__buf_get16(b);\n   if (count) {\n      offsize = stbtt__buf_get8(b);\n      STBTT_assert(offsize >= 1 && offsize <= 4);\n      stbtt__buf_skip(b, offsize * count);\n      stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);\n   }\n   return stbtt__buf_range(b, start, b->cursor - start);\n}\n\nstatic stbtt_uint32 stbtt__cff_int(stbtt__buf *b)\n{\n   int b0 = stbtt__buf_get8(b);\n   if (b0 >= 32 && b0 <= 246)       return b0 - 139;\n   else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108;\n   else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108;\n   else if (b0 == 28)               return stbtt__buf_get16(b);\n   else if (b0 == 29)               return stbtt__buf_get32(b);\n   STBTT_assert(0);\n   return 0;\n}\n\nstatic void stbtt__cff_skip_operand(stbtt__buf *b) {\n   int v, b0 = stbtt__buf_peek8(b);\n   STBTT_assert(b0 >= 28);\n   if (b0 == 30) {\n      stbtt__buf_skip(b, 1);\n      while (b->cursor < b->size) {\n         v = stbtt__buf_get8(b);\n         if ((v & 0xF) == 0xF || (v >> 4) == 0xF)\n            break;\n      }\n   } else {\n      stbtt__cff_int(b);\n   }\n}\n\nstatic stbtt__buf stbtt__dict_get(stbtt__buf *b, int key)\n{\n   stbtt__buf_seek(b, 0);\n   while (b->cursor < b->size) {\n      int start = b->cursor, end, op;\n      while (stbtt__buf_peek8(b) >= 28)\n         stbtt__cff_skip_operand(b);\n      end = b->cursor;\n      op = stbtt__buf_get8(b);\n      if (op == 12)  op = stbtt__buf_get8(b) | 0x100;\n      if (op == key) return stbtt__buf_range(b, start, end-start);\n   }\n   return stbtt__buf_range(b, 0, 0);\n}\n\nstatic void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out)\n{\n   int i;\n   stbtt__buf operands = stbtt__dict_get(b, key);\n   for (i = 0; i < outcount && operands.cursor < operands.size; i++)\n      out[i] = stbtt__cff_int(&operands);\n}\n\nstatic int stbtt__cff_index_count(stbtt__buf *b)\n{\n   stbtt__buf_seek(b, 0);\n   return stbtt__buf_get16(b);\n}\n\nstatic stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)\n{\n   int count, offsize, start, end;\n   stbtt__buf_seek(&b, 0);\n   count = stbtt__buf_get16(&b);\n   offsize = stbtt__buf_get8(&b);\n   STBTT_assert(i >= 0 && i < count);\n   STBTT_assert(offsize >= 1 && offsize <= 4);\n   stbtt__buf_skip(&b, i*offsize);\n   start = stbtt__buf_get(&b, offsize);\n   end = stbtt__buf_get(&b, offsize);\n   return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start);\n}\n\n//////////////////////////////////////////////////////////////////////////\n//\n// accessors to parse data from file\n//\n\n// on platforms that don't allow misaligned reads, if we want to allow\n// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE\n\n#define ttBYTE(p)     (* (stbtt_uint8 *) (p))\n#define ttCHAR(p)     (* (stbtt_int8 *) (p))\n#define ttFixed(p)    ttLONG(p)\n\nstatic stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }\nstatic stbtt_int16 ttSHORT(stbtt_uint8 *p)   { return p[0]*256 + p[1]; }\nstatic stbtt_uint32 ttULONG(stbtt_uint8 *p)  { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }\nstatic stbtt_int32 ttLONG(stbtt_uint8 *p)    { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }\n\n#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))\n#define stbtt_tag(p,str)           stbtt_tag4(p,str[0],str[1],str[2],str[3])\n\nstatic int stbtt__isfont(stbtt_uint8 *font)\n{\n   // check the version number\n   if (stbtt_tag4(font, '1',0,0,0))  return 1; // TrueType 1\n   if (stbtt_tag(font, \"typ1\"))   return 1; // TrueType with type 1 font -- we don't support this!\n   if (stbtt_tag(font, \"OTTO\"))   return 1; // OpenType with CFF\n   if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0\n   if (stbtt_tag(font, \"true\"))   return 1; // Apple specification for TrueType fonts\n   return 0;\n}\n\n// @OPTIMIZE: binary search\nstatic stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)\n{\n   stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);\n   stbtt_uint32 tabledir = fontstart + 12;\n   stbtt_int32 i;\n   for (i=0; i < num_tables; ++i) {\n      stbtt_uint32 loc = tabledir + 16*i;\n      if (stbtt_tag(data+loc+0, tag))\n         return ttULONG(data+loc+8);\n   }\n   return 0;\n}\n\nstatic int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index)\n{\n   // if it's just a font, there's only one valid index\n   if (stbtt__isfont(font_collection))\n      return index == 0 ? 0 : -1;\n\n   // check if it's a TTC\n   if (stbtt_tag(font_collection, \"ttcf\")) {\n      // version 1?\n      if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {\n         stbtt_int32 n = ttLONG(font_collection+8);\n         if (index >= n)\n            return -1;\n         return ttULONG(font_collection+12+index*4);\n      }\n   }\n   return -1;\n}\n\nstatic int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection)\n{\n   // if it's just a font, there's only one valid font\n   if (stbtt__isfont(font_collection))\n      return 1;\n\n   // check if it's a TTC\n   if (stbtt_tag(font_collection, \"ttcf\")) {\n      // version 1?\n      if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {\n         return ttLONG(font_collection+8);\n      }\n   }\n   return 0;\n}\n\nstatic stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)\n{\n   stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };\n   stbtt__buf pdict;\n   stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);\n   if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0);\n   pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);\n   stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);\n   if (!subrsoff) return stbtt__new_buf(NULL, 0);\n   stbtt__buf_seek(&cff, private_loc[1]+subrsoff);\n   return stbtt__cff_get_index(&cff);\n}\n\n// since most people won't use this, find this table the first time it's needed\nstatic int stbtt__get_svg(stbtt_fontinfo *info)\n{\n   stbtt_uint32 t;\n   if (info->svg < 0) {\n      t = stbtt__find_table(info->data, info->fontstart, \"SVG \");\n      if (t) {\n         stbtt_uint32 offset = ttULONG(info->data + t + 2);\n         info->svg = t + offset;\n      } else {\n         info->svg = 0;\n      }\n   }\n   return info->svg;\n}\n\nstatic int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)\n{\n   stbtt_uint32 cmap, t;\n   stbtt_int32 i,numTables;\n\n   info->data = data;\n   info->fontstart = fontstart;\n   info->cff = stbtt__new_buf(NULL, 0);\n\n   cmap = stbtt__find_table(data, fontstart, \"cmap\");       // required\n   info->loca = stbtt__find_table(data, fontstart, \"loca\"); // required\n   info->head = stbtt__find_table(data, fontstart, \"head\"); // required\n   info->glyf = stbtt__find_table(data, fontstart, \"glyf\"); // required\n   info->hhea = stbtt__find_table(data, fontstart, \"hhea\"); // required\n   info->hmtx = stbtt__find_table(data, fontstart, \"hmtx\"); // required\n   info->kern = stbtt__find_table(data, fontstart, \"kern\"); // not required\n   info->gpos = stbtt__find_table(data, fontstart, \"GPOS\"); // not required\n\n   if (!cmap || !info->head || !info->hhea || !info->hmtx)\n      return 0;\n   if (info->glyf) {\n      // required for truetype\n      if (!info->loca) return 0;\n   } else {\n      // initialization for CFF / Type2 fonts (OTF)\n      stbtt__buf b, topdict, topdictidx;\n      stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;\n      stbtt_uint32 cff;\n\n      cff = stbtt__find_table(data, fontstart, \"CFF \");\n      if (!cff) return 0;\n\n      info->fontdicts = stbtt__new_buf(NULL, 0);\n      info->fdselect = stbtt__new_buf(NULL, 0);\n\n      // @TODO this should use size from table (not 512MB)\n      info->cff = stbtt__new_buf(data+cff, 512*1024*1024);\n      b = info->cff;\n\n      // read the header\n      stbtt__buf_skip(&b, 2);\n      stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize\n\n      // @TODO the name INDEX could list multiple fonts,\n      // but we just use the first one.\n      stbtt__cff_get_index(&b);  // name INDEX\n      topdictidx = stbtt__cff_get_index(&b);\n      topdict = stbtt__cff_index_get(topdictidx, 0);\n      stbtt__cff_get_index(&b);  // string INDEX\n      info->gsubrs = stbtt__cff_get_index(&b);\n\n      stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);\n      stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);\n      stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);\n      stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);\n      info->subrs = stbtt__get_subrs(b, topdict);\n\n      // we only support Type 2 charstrings\n      if (cstype != 2) return 0;\n      if (charstrings == 0) return 0;\n\n      if (fdarrayoff) {\n         // looks like a CID font\n         if (!fdselectoff) return 0;\n         stbtt__buf_seek(&b, fdarrayoff);\n         info->fontdicts = stbtt__cff_get_index(&b);\n         info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff);\n      }\n\n      stbtt__buf_seek(&b, charstrings);\n      info->charstrings = stbtt__cff_get_index(&b);\n   }\n\n   t = stbtt__find_table(data, fontstart, \"maxp\");\n   if (t)\n      info->numGlyphs = ttUSHORT(data+t+4);\n   else\n      info->numGlyphs = 0xffff;\n\n   info->svg = -1;\n\n   // find a cmap encoding table we understand *now* to avoid searching\n   // later. (todo: could make this installable)\n   // the same regardless of glyph.\n   numTables = ttUSHORT(data + cmap + 2);\n   info->index_map = 0;\n   for (i=0; i < numTables; ++i) {\n      stbtt_uint32 encoding_record = cmap + 4 + 8 * i;\n      // find an encoding we understand:\n      switch(ttUSHORT(data+encoding_record)) {\n         case STBTT_PLATFORM_ID_MICROSOFT:\n            switch (ttUSHORT(data+encoding_record+2)) {\n               case STBTT_MS_EID_UNICODE_BMP:\n               case STBTT_MS_EID_UNICODE_FULL:\n                  // MS/Unicode\n                  info->index_map = cmap + ttULONG(data+encoding_record+4);\n                  break;\n            }\n            break;\n        case STBTT_PLATFORM_ID_UNICODE:\n            // Mac/iOS has these\n            // all the encodingIDs are unicode, so we don't bother to check it\n            info->index_map = cmap + ttULONG(data+encoding_record+4);\n            break;\n      }\n   }\n   if (info->index_map == 0)\n      return 0;\n\n   info->indexToLocFormat = ttUSHORT(data+info->head + 50);\n   return 1;\n}\n\nSTBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)\n{\n   stbtt_uint8 *data = info->data;\n   stbtt_uint32 index_map = info->index_map;\n\n   stbtt_uint16 format = ttUSHORT(data + index_map + 0);\n   if (format == 0) { // apple byte encoding\n      stbtt_int32 bytes = ttUSHORT(data + index_map + 2);\n      if (unicode_codepoint < bytes-6)\n         return ttBYTE(data + index_map + 6 + unicode_codepoint);\n      return 0;\n   } else if (format == 6) {\n      stbtt_uint32 first = ttUSHORT(data + index_map + 6);\n      stbtt_uint32 count = ttUSHORT(data + index_map + 8);\n      if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)\n         return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);\n      return 0;\n   } else if (format == 2) {\n      STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean\n      return 0;\n   } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges\n      stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;\n      stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;\n      stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);\n      stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;\n\n      // do a binary search of the segments\n      stbtt_uint32 endCount = index_map + 14;\n      stbtt_uint32 search = endCount;\n\n      if (unicode_codepoint > 0xffff)\n         return 0;\n\n      // they lie from endCount .. endCount + segCount\n      // but searchRange is the nearest power of two, so...\n      if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))\n         search += rangeShift*2;\n\n      // now decrement to bias correctly to find smallest\n      search -= 2;\n      while (entrySelector) {\n         stbtt_uint16 end;\n         searchRange >>= 1;\n         end = ttUSHORT(data + search + searchRange*2);\n         if (unicode_codepoint > end)\n            search += searchRange*2;\n         --entrySelector;\n      }\n      search += 2;\n\n      {\n         stbtt_uint16 offset, start, last;\n         stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);\n\n         start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);\n         last = ttUSHORT(data + endCount + 2*item);\n         if (unicode_codepoint < start || unicode_codepoint > last)\n            return 0;\n\n         offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);\n         if (offset == 0)\n            return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));\n\n         return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);\n      }\n   } else if (format == 12 || format == 13) {\n      stbtt_uint32 ngroups = ttULONG(data+index_map+12);\n      stbtt_int32 low,high;\n      low = 0; high = (stbtt_int32)ngroups;\n      // Binary search the right group.\n      while (low < high) {\n         stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high\n         stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);\n         stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);\n         if ((stbtt_uint32) unicode_codepoint < start_char)\n            high = mid;\n         else if ((stbtt_uint32) unicode_codepoint > end_char)\n            low = mid+1;\n         else {\n            stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);\n            if (format == 12)\n               return start_glyph + unicode_codepoint-start_char;\n            else // format == 13\n               return start_glyph;\n         }\n      }\n      return 0; // not found\n   }\n   // @TODO\n   STBTT_assert(0);\n   return 0;\n}\n\nSTBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)\n{\n   return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);\n}\n\nstatic void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)\n{\n   v->type = type;\n   v->x = (stbtt_int16) x;\n   v->y = (stbtt_int16) y;\n   v->cx = (stbtt_int16) cx;\n   v->cy = (stbtt_int16) cy;\n}\n\nstatic int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)\n{\n   int g1,g2;\n\n   STBTT_assert(!info->cff.size);\n\n   if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range\n   if (info->indexToLocFormat >= 2)    return -1; // unknown index->glyph map format\n\n   if (info->indexToLocFormat == 0) {\n      g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;\n      g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;\n   } else {\n      g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);\n      g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);\n   }\n\n   return g1==g2 ? -1 : g1; // if length is 0, return -1\n}\n\nstatic int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);\n\nSTBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)\n{\n   if (info->cff.size) {\n      stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);\n   } else {\n      int g = stbtt__GetGlyfOffset(info, glyph_index);\n      if (g < 0) return 0;\n\n      if (x0) *x0 = ttSHORT(info->data + g + 2);\n      if (y0) *y0 = ttSHORT(info->data + g + 4);\n      if (x1) *x1 = ttSHORT(info->data + g + 6);\n      if (y1) *y1 = ttSHORT(info->data + g + 8);\n   }\n   return 1;\n}\n\nSTBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)\n{\n   return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);\n}\n\nSTBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)\n{\n   stbtt_int16 numberOfContours;\n   int g;\n   if (info->cff.size)\n      return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;\n   g = stbtt__GetGlyfOffset(info, glyph_index);\n   if (g < 0) return 1;\n   numberOfContours = ttSHORT(info->data + g);\n   return numberOfContours == 0;\n}\n\nstatic int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,\n    stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)\n{\n   if (start_off) {\n      if (was_off)\n         stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);\n      stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);\n   } else {\n      if (was_off)\n         stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);\n      else\n         stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);\n   }\n   return num_vertices;\n}\n\nstatic int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)\n{\n   stbtt_int16 numberOfContours;\n   stbtt_uint8 *endPtsOfContours;\n   stbtt_uint8 *data = info->data;\n   stbtt_vertex *vertices=0;\n   int num_vertices=0;\n   int g = stbtt__GetGlyfOffset(info, glyph_index);\n\n   *pvertices = NULL;\n\n   if (g < 0) return 0;\n\n   numberOfContours = ttSHORT(data + g);\n\n   if (numberOfContours > 0) {\n      stbtt_uint8 flags=0,flagcount;\n      stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;\n      stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;\n      stbtt_uint8 *points;\n      endPtsOfContours = (data + g + 10);\n      ins = ttUSHORT(data + g + 10 + numberOfContours * 2);\n      points = data + g + 10 + numberOfContours * 2 + 2 + ins;\n\n      n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);\n\n      m = n + 2*numberOfContours;  // a loose bound on how many vertices we might need\n      vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);\n      if (vertices == 0)\n         return 0;\n\n      next_move = 0;\n      flagcount=0;\n\n      // in first pass, we load uninterpreted data into the allocated array\n      // above, shifted to the end of the array so we won't overwrite it when\n      // we create our final data starting from the front\n\n      off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated\n\n      // first load flags\n\n      for (i=0; i < n; ++i) {\n         if (flagcount == 0) {\n            flags = *points++;\n            if (flags & 8)\n               flagcount = *points++;\n         } else\n            --flagcount;\n         vertices[off+i].type = flags;\n      }\n\n      // now load x coordinates\n      x=0;\n      for (i=0; i < n; ++i) {\n         flags = vertices[off+i].type;\n         if (flags & 2) {\n            stbtt_int16 dx = *points++;\n            x += (flags & 16) ? dx : -dx; // ???\n         } else {\n            if (!(flags & 16)) {\n               x = x + (stbtt_int16) (points[0]*256 + points[1]);\n               points += 2;\n            }\n         }\n         vertices[off+i].x = (stbtt_int16) x;\n      }\n\n      // now load y coordinates\n      y=0;\n      for (i=0; i < n; ++i) {\n         flags = vertices[off+i].type;\n         if (flags & 4) {\n            stbtt_int16 dy = *points++;\n            y += (flags & 32) ? dy : -dy; // ???\n         } else {\n            if (!(flags & 32)) {\n               y = y + (stbtt_int16) (points[0]*256 + points[1]);\n               points += 2;\n            }\n         }\n         vertices[off+i].y = (stbtt_int16) y;\n      }\n\n      // now convert them to our format\n      num_vertices=0;\n      sx = sy = cx = cy = scx = scy = 0;\n      for (i=0; i < n; ++i) {\n         flags = vertices[off+i].type;\n         x     = (stbtt_int16) vertices[off+i].x;\n         y     = (stbtt_int16) vertices[off+i].y;\n\n         if (next_move == i) {\n            if (i != 0)\n               num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);\n\n            // now start the new one\n            start_off = !(flags & 1);\n            if (start_off) {\n               // if we start off with an off-curve point, then when we need to find a point on the curve\n               // where we can start, and we need to save some state for when we wraparound.\n               scx = x;\n               scy = y;\n               if (!(vertices[off+i+1].type & 1)) {\n                  // next point is also a curve point, so interpolate an on-point curve\n                  sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;\n                  sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;\n               } else {\n                  // otherwise just use the next point as our start point\n                  sx = (stbtt_int32) vertices[off+i+1].x;\n                  sy = (stbtt_int32) vertices[off+i+1].y;\n                  ++i; // we're using point i+1 as the starting point, so skip it\n               }\n            } else {\n               sx = x;\n               sy = y;\n            }\n            stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);\n            was_off = 0;\n            next_move = 1 + ttUSHORT(endPtsOfContours+j*2);\n            ++j;\n         } else {\n            if (!(flags & 1)) { // if it's a curve\n               if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint\n                  stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);\n               cx = x;\n               cy = y;\n               was_off = 1;\n            } else {\n               if (was_off)\n                  stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);\n               else\n                  stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);\n               was_off = 0;\n            }\n         }\n      }\n      num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);\n   } else if (numberOfContours < 0) {\n      // Compound shapes.\n      int more = 1;\n      stbtt_uint8 *comp = data + g + 10;\n      num_vertices = 0;\n      vertices = 0;\n      while (more) {\n         stbtt_uint16 flags, gidx;\n         int comp_num_verts = 0, i;\n         stbtt_vertex *comp_verts = 0, *tmp = 0;\n         float mtx[6] = {1,0,0,1,0,0}, m, n;\n\n         flags = ttSHORT(comp); comp+=2;\n         gidx = ttSHORT(comp); comp+=2;\n\n         if (flags & 2) { // XY values\n            if (flags & 1) { // shorts\n               mtx[4] = ttSHORT(comp); comp+=2;\n               mtx[5] = ttSHORT(comp); comp+=2;\n            } else {\n               mtx[4] = ttCHAR(comp); comp+=1;\n               mtx[5] = ttCHAR(comp); comp+=1;\n            }\n         }\n         else {\n            // @TODO handle matching point\n            STBTT_assert(0);\n         }\n         if (flags & (1<<3)) { // WE_HAVE_A_SCALE\n            mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;\n            mtx[1] = mtx[2] = 0;\n         } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE\n            mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;\n            mtx[1] = mtx[2] = 0;\n            mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;\n         } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO\n            mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;\n            mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;\n            mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;\n            mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;\n         }\n\n         // Find transformation scales.\n         m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);\n         n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);\n\n         // Get indexed glyph.\n         comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);\n         if (comp_num_verts > 0) {\n            // Transform vertices.\n            for (i = 0; i < comp_num_verts; ++i) {\n               stbtt_vertex* v = &comp_verts[i];\n               stbtt_vertex_type x,y;\n               x=v->x; y=v->y;\n               v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));\n               v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));\n               x=v->cx; y=v->cy;\n               v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));\n               v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));\n            }\n            // Append vertices.\n            tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);\n            if (!tmp) {\n               if (vertices) STBTT_free(vertices, info->userdata);\n               if (comp_verts) STBTT_free(comp_verts, info->userdata);\n               return 0;\n            }\n            if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));\n            STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));\n            if (vertices) STBTT_free(vertices, info->userdata);\n            vertices = tmp;\n            STBTT_free(comp_verts, info->userdata);\n            num_vertices += comp_num_verts;\n         }\n         // More components ?\n         more = flags & (1<<5);\n      }\n   } else {\n      // numberOfCounters == 0, do nothing\n   }\n\n   *pvertices = vertices;\n   return num_vertices;\n}\n\ntypedef struct\n{\n   int bounds;\n   int started;\n   float first_x, first_y;\n   float x, y;\n   stbtt_int32 min_x, max_x, min_y, max_y;\n\n   stbtt_vertex *pvertices;\n   int num_vertices;\n} stbtt__csctx;\n\n#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}\n\nstatic void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y)\n{\n   if (x > c->max_x || !c->started) c->max_x = x;\n   if (y > c->max_y || !c->started) c->max_y = y;\n   if (x < c->min_x || !c->started) c->min_x = x;\n   if (y < c->min_y || !c->started) c->min_y = y;\n   c->started = 1;\n}\n\nstatic void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1)\n{\n   if (c->bounds) {\n      stbtt__track_vertex(c, x, y);\n      if (type == STBTT_vcubic) {\n         stbtt__track_vertex(c, cx, cy);\n         stbtt__track_vertex(c, cx1, cy1);\n      }\n   } else {\n      stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);\n      c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;\n      c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;\n   }\n   c->num_vertices++;\n}\n\nstatic void stbtt__csctx_close_shape(stbtt__csctx *ctx)\n{\n   if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)\n      stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0);\n}\n\nstatic void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy)\n{\n   stbtt__csctx_close_shape(ctx);\n   ctx->first_x = ctx->x = ctx->x + dx;\n   ctx->first_y = ctx->y = ctx->y + dy;\n   stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);\n}\n\nstatic void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy)\n{\n   ctx->x += dx;\n   ctx->y += dy;\n   stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);\n}\n\nstatic void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)\n{\n   float cx1 = ctx->x + dx1;\n   float cy1 = ctx->y + dy1;\n   float cx2 = cx1 + dx2;\n   float cy2 = cy1 + dy2;\n   ctx->x = cx2 + dx3;\n   ctx->y = cy2 + dy3;\n   stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2);\n}\n\nstatic stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)\n{\n   int count = stbtt__cff_index_count(&idx);\n   int bias = 107;\n   if (count >= 33900)\n      bias = 32768;\n   else if (count >= 1240)\n      bias = 1131;\n   n += bias;\n   if (n < 0 || n >= count)\n      return stbtt__new_buf(NULL, 0);\n   return stbtt__cff_index_get(idx, n);\n}\n\nstatic stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index)\n{\n   stbtt__buf fdselect = info->fdselect;\n   int nranges, start, end, v, fmt, fdselector = -1, i;\n\n   stbtt__buf_seek(&fdselect, 0);\n   fmt = stbtt__buf_get8(&fdselect);\n   if (fmt == 0) {\n      // untested\n      stbtt__buf_skip(&fdselect, glyph_index);\n      fdselector = stbtt__buf_get8(&fdselect);\n   } else if (fmt == 3) {\n      nranges = stbtt__buf_get16(&fdselect);\n      start = stbtt__buf_get16(&fdselect);\n      for (i = 0; i < nranges; i++) {\n         v = stbtt__buf_get8(&fdselect);\n         end = stbtt__buf_get16(&fdselect);\n         if (glyph_index >= start && glyph_index < end) {\n            fdselector = v;\n            break;\n         }\n         start = end;\n      }\n   }\n   if (fdselector == -1) stbtt__new_buf(NULL, 0);\n   return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));\n}\n\nstatic int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c)\n{\n   int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;\n   int has_subrs = 0, clear_stack;\n   float s[48];\n   stbtt__buf subr_stack[10], subrs = info->subrs, b;\n   float f;\n\n#define STBTT__CSERR(s) (0)\n\n   // this currently ignores the initial width value, which isn't needed if we have hmtx\n   b = stbtt__cff_index_get(info->charstrings, glyph_index);\n   while (b.cursor < b.size) {\n      i = 0;\n      clear_stack = 1;\n      b0 = stbtt__buf_get8(&b);\n      switch (b0) {\n      // @TODO implement hinting\n      case 0x13: // hintmask\n      case 0x14: // cntrmask\n         if (in_header)\n            maskbits += (sp / 2); // implicit \"vstem\"\n         in_header = 0;\n         stbtt__buf_skip(&b, (maskbits + 7) / 8);\n         break;\n\n      case 0x01: // hstem\n      case 0x03: // vstem\n      case 0x12: // hstemhm\n      case 0x17: // vstemhm\n         maskbits += (sp / 2);\n         break;\n\n      case 0x15: // rmoveto\n         in_header = 0;\n         if (sp < 2) return STBTT__CSERR(\"rmoveto stack\");\n         stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]);\n         break;\n      case 0x04: // vmoveto\n         in_header = 0;\n         if (sp < 1) return STBTT__CSERR(\"vmoveto stack\");\n         stbtt__csctx_rmove_to(c, 0, s[sp-1]);\n         break;\n      case 0x16: // hmoveto\n         in_header = 0;\n         if (sp < 1) return STBTT__CSERR(\"hmoveto stack\");\n         stbtt__csctx_rmove_to(c, s[sp-1], 0);\n         break;\n\n      case 0x05: // rlineto\n         if (sp < 2) return STBTT__CSERR(\"rlineto stack\");\n         for (; i + 1 < sp; i += 2)\n            stbtt__csctx_rline_to(c, s[i], s[i+1]);\n         break;\n\n      // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical\n      // starting from a different place.\n\n      case 0x07: // vlineto\n         if (sp < 1) return STBTT__CSERR(\"vlineto stack\");\n         goto vlineto;\n      case 0x06: // hlineto\n         if (sp < 1) return STBTT__CSERR(\"hlineto stack\");\n         for (;;) {\n            if (i >= sp) break;\n            stbtt__csctx_rline_to(c, s[i], 0);\n            i++;\n      vlineto:\n            if (i >= sp) break;\n            stbtt__csctx_rline_to(c, 0, s[i]);\n            i++;\n         }\n         break;\n\n      case 0x1F: // hvcurveto\n         if (sp < 4) return STBTT__CSERR(\"hvcurveto stack\");\n         goto hvcurveto;\n      case 0x1E: // vhcurveto\n         if (sp < 4) return STBTT__CSERR(\"vhcurveto stack\");\n         for (;;) {\n            if (i + 3 >= sp) break;\n            stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f);\n            i += 4;\n      hvcurveto:\n            if (i + 3 >= sp) break;\n            stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]);\n            i += 4;\n         }\n         break;\n\n      case 0x08: // rrcurveto\n         if (sp < 6) return STBTT__CSERR(\"rcurveline stack\");\n         for (; i + 5 < sp; i += 6)\n            stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);\n         break;\n\n      case 0x18: // rcurveline\n         if (sp < 8) return STBTT__CSERR(\"rcurveline stack\");\n         for (; i + 5 < sp - 2; i += 6)\n            stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);\n         if (i + 1 >= sp) return STBTT__CSERR(\"rcurveline stack\");\n         stbtt__csctx_rline_to(c, s[i], s[i+1]);\n         break;\n\n      case 0x19: // rlinecurve\n         if (sp < 8) return STBTT__CSERR(\"rlinecurve stack\");\n         for (; i + 1 < sp - 6; i += 2)\n            stbtt__csctx_rline_to(c, s[i], s[i+1]);\n         if (i + 5 >= sp) return STBTT__CSERR(\"rlinecurve stack\");\n         stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);\n         break;\n\n      case 0x1A: // vvcurveto\n      case 0x1B: // hhcurveto\n         if (sp < 4) return STBTT__CSERR(\"(vv|hh)curveto stack\");\n         f = 0.0;\n         if (sp & 1) { f = s[i]; i++; }\n         for (; i + 3 < sp; i += 4) {\n            if (b0 == 0x1B)\n               stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0);\n            else\n               stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]);\n            f = 0.0;\n         }\n         break;\n\n      case 0x0A: // callsubr\n         if (!has_subrs) {\n            if (info->fdselect.size)\n               subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);\n            has_subrs = 1;\n         }\n         // FALLTHROUGH\n      case 0x1D: // callgsubr\n         if (sp < 1) return STBTT__CSERR(\"call(g|)subr stack\");\n         v = (int) s[--sp];\n         if (subr_stack_height >= 10) return STBTT__CSERR(\"recursion limit\");\n         subr_stack[subr_stack_height++] = b;\n         b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v);\n         if (b.size == 0) return STBTT__CSERR(\"subr not found\");\n         b.cursor = 0;\n         clear_stack = 0;\n         break;\n\n      case 0x0B: // return\n         if (subr_stack_height <= 0) return STBTT__CSERR(\"return outside subr\");\n         b = subr_stack[--subr_stack_height];\n         clear_stack = 0;\n         break;\n\n      case 0x0E: // endchar\n         stbtt__csctx_close_shape(c);\n         return 1;\n\n      case 0x0C: { // two-byte escape\n         float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;\n         float dx, dy;\n         int b1 = stbtt__buf_get8(&b);\n         switch (b1) {\n         // @TODO These \"flex\" implementations ignore the flex-depth and resolution,\n         // and always draw beziers.\n         case 0x22: // hflex\n            if (sp < 7) return STBTT__CSERR(\"hflex stack\");\n            dx1 = s[0];\n            dx2 = s[1];\n            dy2 = s[2];\n            dx3 = s[3];\n            dx4 = s[4];\n            dx5 = s[5];\n            dx6 = s[6];\n            stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);\n            stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);\n            break;\n\n         case 0x23: // flex\n            if (sp < 13) return STBTT__CSERR(\"flex stack\");\n            dx1 = s[0];\n            dy1 = s[1];\n            dx2 = s[2];\n            dy2 = s[3];\n            dx3 = s[4];\n            dy3 = s[5];\n            dx4 = s[6];\n            dy4 = s[7];\n            dx5 = s[8];\n            dy5 = s[9];\n            dx6 = s[10];\n            dy6 = s[11];\n            //fd is s[12]\n            stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);\n            stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);\n            break;\n\n         case 0x24: // hflex1\n            if (sp < 9) return STBTT__CSERR(\"hflex1 stack\");\n            dx1 = s[0];\n            dy1 = s[1];\n            dx2 = s[2];\n            dy2 = s[3];\n            dx3 = s[4];\n            dx4 = s[5];\n            dx5 = s[6];\n            dy5 = s[7];\n            dx6 = s[8];\n            stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);\n            stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5));\n            break;\n\n         case 0x25: // flex1\n            if (sp < 11) return STBTT__CSERR(\"flex1 stack\");\n            dx1 = s[0];\n            dy1 = s[1];\n            dx2 = s[2];\n            dy2 = s[3];\n            dx3 = s[4];\n            dy3 = s[5];\n            dx4 = s[6];\n            dy4 = s[7];\n            dx5 = s[8];\n            dy5 = s[9];\n            dx6 = dy6 = s[10];\n            dx = dx1+dx2+dx3+dx4+dx5;\n            dy = dy1+dy2+dy3+dy4+dy5;\n            if (STBTT_fabs(dx) > STBTT_fabs(dy))\n               dy6 = -dy;\n            else\n               dx6 = -dx;\n            stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);\n            stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);\n            break;\n\n         default:\n            return STBTT__CSERR(\"unimplemented\");\n         }\n      } break;\n\n      default:\n         if (b0 != 255 && b0 != 28 && b0 < 32)\n            return STBTT__CSERR(\"reserved operator\");\n\n         // push immediate\n         if (b0 == 255) {\n            f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;\n         } else {\n            stbtt__buf_skip(&b, -1);\n            f = (float)(stbtt_int16)stbtt__cff_int(&b);\n         }\n         if (sp >= 48) return STBTT__CSERR(\"push stack overflow\");\n         s[sp++] = f;\n         clear_stack = 0;\n         break;\n      }\n      if (clear_stack) sp = 0;\n   }\n   return STBTT__CSERR(\"no endchar\");\n\n#undef STBTT__CSERR\n}\n\nstatic int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)\n{\n   // runs the charstring twice, once to count and once to output (to avoid realloc)\n   stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);\n   stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);\n   if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {\n      *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata);\n      output_ctx.pvertices = *pvertices;\n      if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {\n         STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);\n         return output_ctx.num_vertices;\n      }\n   }\n   *pvertices = NULL;\n   return 0;\n}\n\nstatic int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)\n{\n   stbtt__csctx c = STBTT__CSCTX_INIT(1);\n   int r = stbtt__run_charstring(info, glyph_index, &c);\n   if (x0)  *x0 = r ? c.min_x : 0;\n   if (y0)  *y0 = r ? c.min_y : 0;\n   if (x1)  *x1 = r ? c.max_x : 0;\n   if (y1)  *y1 = r ? c.max_y : 0;\n   return r ? c.num_vertices : 0;\n}\n\nSTBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)\n{\n   if (!info->cff.size)\n      return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);\n   else\n      return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);\n}\n\nSTBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)\n{\n   stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);\n   if (glyph_index < numOfLongHorMetrics) {\n      if (advanceWidth)     *advanceWidth    = ttSHORT(info->data + info->hmtx + 4*glyph_index);\n      if (leftSideBearing)  *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);\n   } else {\n      if (advanceWidth)     *advanceWidth    = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));\n      if (leftSideBearing)  *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));\n   }\n}\n\nSTBTT_DEF int  stbtt_GetKerningTableLength(const stbtt_fontinfo *info)\n{\n   stbtt_uint8 *data = info->data + info->kern;\n\n   // we only look at the first table. it must be 'horizontal' and format 0.\n   if (!info->kern)\n      return 0;\n   if (ttUSHORT(data+2) < 1) // number of tables, need at least 1\n      return 0;\n   if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format\n      return 0;\n\n   return ttUSHORT(data+10);\n}\n\nSTBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length)\n{\n   stbtt_uint8 *data = info->data + info->kern;\n   int k, length;\n\n   // we only look at the first table. it must be 'horizontal' and format 0.\n   if (!info->kern)\n      return 0;\n   if (ttUSHORT(data+2) < 1) // number of tables, need at least 1\n      return 0;\n   if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format\n      return 0;\n\n   length = ttUSHORT(data+10);\n   if (table_length < length)\n      length = table_length;\n\n   for (k = 0; k < length; k++)\n   {\n      table[k].glyph1 = ttUSHORT(data+18+(k*6));\n      table[k].glyph2 = ttUSHORT(data+20+(k*6));\n      table[k].advance = ttSHORT(data+22+(k*6));\n   }\n\n   return length;\n}\n\nstatic int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)\n{\n   stbtt_uint8 *data = info->data + info->kern;\n   stbtt_uint32 needle, straw;\n   int l, r, m;\n\n   // we only look at the first table. it must be 'horizontal' and format 0.\n   if (!info->kern)\n      return 0;\n   if (ttUSHORT(data+2) < 1) // number of tables, need at least 1\n      return 0;\n   if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format\n      return 0;\n\n   l = 0;\n   r = ttUSHORT(data+10) - 1;\n   needle = glyph1 << 16 | glyph2;\n   while (l <= r) {\n      m = (l + r) >> 1;\n      straw = ttULONG(data+18+(m*6)); // note: unaligned read\n      if (needle < straw)\n         r = m - 1;\n      else if (needle > straw)\n         l = m + 1;\n      else\n         return ttSHORT(data+22+(m*6));\n   }\n   return 0;\n}\n\nstatic stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)\n{\n   stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);\n   switch (coverageFormat) {\n      case 1: {\n         stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);\n\n         // Binary search.\n         stbtt_int32 l=0, r=glyphCount-1, m;\n         int straw, needle=glyph;\n         while (l <= r) {\n            stbtt_uint8 *glyphArray = coverageTable + 4;\n            stbtt_uint16 glyphID;\n            m = (l + r) >> 1;\n            glyphID = ttUSHORT(glyphArray + 2 * m);\n            straw = glyphID;\n            if (needle < straw)\n               r = m - 1;\n            else if (needle > straw)\n               l = m + 1;\n            else {\n               return m;\n            }\n         }\n         break;\n      }\n\n      case 2: {\n         stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);\n         stbtt_uint8 *rangeArray = coverageTable + 4;\n\n         // Binary search.\n         stbtt_int32 l=0, r=rangeCount-1, m;\n         int strawStart, strawEnd, needle=glyph;\n         while (l <= r) {\n            stbtt_uint8 *rangeRecord;\n            m = (l + r) >> 1;\n            rangeRecord = rangeArray + 6 * m;\n            strawStart = ttUSHORT(rangeRecord);\n            strawEnd = ttUSHORT(rangeRecord + 2);\n            if (needle < strawStart)\n               r = m - 1;\n            else if (needle > strawEnd)\n               l = m + 1;\n            else {\n               stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);\n               return startCoverageIndex + glyph - strawStart;\n            }\n         }\n         break;\n      }\n\n      default: return -1; // unsupported\n   }\n\n   return -1;\n}\n\nstatic stbtt_int32  stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)\n{\n   stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);\n   switch (classDefFormat)\n   {\n      case 1: {\n         stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);\n         stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);\n         stbtt_uint8 *classDef1ValueArray = classDefTable + 6;\n\n         if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)\n            return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));\n         break;\n      }\n\n      case 2: {\n         stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);\n         stbtt_uint8 *classRangeRecords = classDefTable + 4;\n\n         // Binary search.\n         stbtt_int32 l=0, r=classRangeCount-1, m;\n         int strawStart, strawEnd, needle=glyph;\n         while (l <= r) {\n            stbtt_uint8 *classRangeRecord;\n            m = (l + r) >> 1;\n            classRangeRecord = classRangeRecords + 6 * m;\n            strawStart = ttUSHORT(classRangeRecord);\n            strawEnd = ttUSHORT(classRangeRecord + 2);\n            if (needle < strawStart)\n               r = m - 1;\n            else if (needle > strawEnd)\n               l = m + 1;\n            else\n               return (stbtt_int32)ttUSHORT(classRangeRecord + 4);\n         }\n         break;\n      }\n\n      default:\n         return -1; // Unsupported definition type, return an error.\n   }\n\n   // \"All glyphs not assigned to a class fall into class 0\". (OpenType spec)\n   return 0;\n}\n\n// Define to STBTT_assert(x) if you want to break on unimplemented formats.\n#define STBTT_GPOS_TODO_assert(x)\n\nstatic stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)\n{\n   stbtt_uint16 lookupListOffset;\n   stbtt_uint8 *lookupList;\n   stbtt_uint16 lookupCount;\n   stbtt_uint8 *data;\n   stbtt_int32 i, sti;\n\n   if (!info->gpos) return 0;\n\n   data = info->data + info->gpos;\n\n   if (ttUSHORT(data+0) != 1) return 0; // Major version 1\n   if (ttUSHORT(data+2) != 0) return 0; // Minor version 0\n\n   lookupListOffset = ttUSHORT(data+8);\n   lookupList = data + lookupListOffset;\n   lookupCount = ttUSHORT(lookupList);\n\n   for (i=0; i<lookupCount; ++i) {\n      stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);\n      stbtt_uint8 *lookupTable = lookupList + lookupOffset;\n\n      stbtt_uint16 lookupType = ttUSHORT(lookupTable);\n      stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);\n      stbtt_uint8 *subTableOffsets = lookupTable + 6;\n      if (lookupType != 2) // Pair Adjustment Positioning Subtable\n         continue;\n\n      for (sti=0; sti<subTableCount; sti++) {\n         stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);\n         stbtt_uint8 *table = lookupTable + subtableOffset;\n         stbtt_uint16 posFormat = ttUSHORT(table);\n         stbtt_uint16 coverageOffset = ttUSHORT(table + 2);\n         stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);\n         if (coverageIndex == -1) continue;\n\n         switch (posFormat) {\n            case 1: {\n               stbtt_int32 l, r, m;\n               int straw, needle;\n               stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);\n               stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);\n               if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?\n                  stbtt_int32 valueRecordPairSizeInBytes = 2;\n                  stbtt_uint16 pairSetCount = ttUSHORT(table + 8);\n                  stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);\n                  stbtt_uint8 *pairValueTable = table + pairPosOffset;\n                  stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);\n                  stbtt_uint8 *pairValueArray = pairValueTable + 2;\n\n                  if (coverageIndex >= pairSetCount) return 0;\n\n                  needle=glyph2;\n                  r=pairValueCount-1;\n                  l=0;\n\n                  // Binary search.\n                  while (l <= r) {\n                     stbtt_uint16 secondGlyph;\n                     stbtt_uint8 *pairValue;\n                     m = (l + r) >> 1;\n                     pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;\n                     secondGlyph = ttUSHORT(pairValue);\n                     straw = secondGlyph;\n                     if (needle < straw)\n                        r = m - 1;\n                     else if (needle > straw)\n                        l = m + 1;\n                     else {\n                        stbtt_int16 xAdvance = ttSHORT(pairValue + 2);\n                        return xAdvance;\n                     }\n                  }\n               } else\n                  return 0;\n               break;\n            }\n\n            case 2: {\n               stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);\n               stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);\n               if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?\n                  stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);\n                  stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);\n                  int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);\n                  int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);\n\n                  stbtt_uint16 class1Count = ttUSHORT(table + 12);\n                  stbtt_uint16 class2Count = ttUSHORT(table + 14);\n                  stbtt_uint8 *class1Records, *class2Records;\n                  stbtt_int16 xAdvance;\n\n                  if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed\n                  if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed\n\n                  class1Records = table + 16;\n                  class2Records = class1Records + 2 * (glyph1class * class2Count);\n                  xAdvance = ttSHORT(class2Records + 2 * glyph2class);\n                  return xAdvance;\n               } else\n                  return 0;\n               break;\n            }\n\n            default:\n               return 0; // Unsupported position format\n         }\n      }\n   }\n\n   return 0;\n}\n\nSTBTT_DEF int  stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)\n{\n   int xAdvance = 0;\n\n   if (info->gpos)\n      xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);\n   else if (info->kern)\n      xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);\n\n   return xAdvance;\n}\n\nSTBTT_DEF int  stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)\n{\n   if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs\n      return 0;\n   return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));\n}\n\nSTBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)\n{\n   stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);\n}\n\nSTBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)\n{\n   if (ascent ) *ascent  = ttSHORT(info->data+info->hhea + 4);\n   if (descent) *descent = ttSHORT(info->data+info->hhea + 6);\n   if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);\n}\n\nSTBTT_DEF int  stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap)\n{\n   int tab = stbtt__find_table(info->data, info->fontstart, \"OS/2\");\n   if (!tab)\n      return 0;\n   if (typoAscent ) *typoAscent  = ttSHORT(info->data+tab + 68);\n   if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70);\n   if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72);\n   return 1;\n}\n\nSTBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)\n{\n   *x0 = ttSHORT(info->data + info->head + 36);\n   *y0 = ttSHORT(info->data + info->head + 38);\n   *x1 = ttSHORT(info->data + info->head + 40);\n   *y1 = ttSHORT(info->data + info->head + 42);\n}\n\nSTBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)\n{\n   int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);\n   return (float) height / fheight;\n}\n\nSTBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)\n{\n   int unitsPerEm = ttUSHORT(info->data + info->head + 18);\n   return pixels / unitsPerEm;\n}\n\nSTBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)\n{\n   STBTT_free(v, info->userdata);\n}\n\nSTBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl)\n{\n   int i;\n   stbtt_uint8 *data = info->data;\n   stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info);\n\n   int numEntries = ttUSHORT(svg_doc_list);\n   stbtt_uint8 *svg_docs = svg_doc_list + 2;\n\n   for(i=0; i<numEntries; i++) {\n      stbtt_uint8 *svg_doc = svg_docs + (12 * i);\n      if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))\n         return svg_doc;\n   }\n   return 0;\n}\n\nSTBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg)\n{\n   stbtt_uint8 *data = info->data;\n   stbtt_uint8 *svg_doc;\n\n   if (info->svg == 0)\n      return 0;\n\n   svg_doc = stbtt_FindSVGDoc(info, gl);\n   if (svg_doc != NULL) {\n      *svg = (char *) data + info->svg + ttULONG(svg_doc + 4);\n      return ttULONG(svg_doc + 8);\n   } else {\n      return 0;\n   }\n}\n\nSTBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg)\n{\n   return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);\n}\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// antialiasing software rasterizer\n//\n\nSTBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)\n{\n   int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning\n   if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {\n      // e.g. space character\n      if (ix0) *ix0 = 0;\n      if (iy0) *iy0 = 0;\n      if (ix1) *ix1 = 0;\n      if (iy1) *iy1 = 0;\n   } else {\n      // move to integral bboxes (treating pixels as little squares, what pixels get touched)?\n      if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);\n      if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);\n      if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);\n      if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);\n   }\n}\n\nSTBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)\n{\n   stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);\n}\n\nSTBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)\n{\n   stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);\n}\n\nSTBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)\n{\n   stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);\n}\n\n//////////////////////////////////////////////////////////////////////////////\n//\n//  Rasterizer\n\ntypedef struct stbtt__hheap_chunk\n{\n   struct stbtt__hheap_chunk *next;\n} stbtt__hheap_chunk;\n\ntypedef struct stbtt__hheap\n{\n   struct stbtt__hheap_chunk *head;\n   void   *first_free;\n   int    num_remaining_in_head_chunk;\n} stbtt__hheap;\n\nstatic void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)\n{\n   if (hh->first_free) {\n      void *p = hh->first_free;\n      hh->first_free = * (void **) p;\n      return p;\n   } else {\n      if (hh->num_remaining_in_head_chunk == 0) {\n         int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);\n         stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);\n         if (c == NULL)\n            return NULL;\n         c->next = hh->head;\n         hh->head = c;\n         hh->num_remaining_in_head_chunk = count;\n      }\n      --hh->num_remaining_in_head_chunk;\n      return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;\n   }\n}\n\nstatic void stbtt__hheap_free(stbtt__hheap *hh, void *p)\n{\n   *(void **) p = hh->first_free;\n   hh->first_free = p;\n}\n\nstatic void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)\n{\n   stbtt__hheap_chunk *c = hh->head;\n   while (c) {\n      stbtt__hheap_chunk *n = c->next;\n      STBTT_free(c, userdata);\n      c = n;\n   }\n}\n\ntypedef struct stbtt__edge {\n   float x0,y0, x1,y1;\n   int invert;\n} stbtt__edge;\n\n\ntypedef struct stbtt__active_edge\n{\n   struct stbtt__active_edge *next;\n   #if STBTT_RASTERIZER_VERSION==1\n   int x,dx;\n   float ey;\n   int direction;\n   #elif STBTT_RASTERIZER_VERSION==2\n   float fx,fdx,fdy;\n   float direction;\n   float sy;\n   float ey;\n   #else\n   #error \"Unrecognized value of STBTT_RASTERIZER_VERSION\"\n   #endif\n} stbtt__active_edge;\n\n#if STBTT_RASTERIZER_VERSION == 1\n#define STBTT_FIXSHIFT   10\n#define STBTT_FIX        (1 << STBTT_FIXSHIFT)\n#define STBTT_FIXMASK    (STBTT_FIX-1)\n\nstatic stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)\n{\n   stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);\n   float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);\n   STBTT_assert(z != NULL);\n   if (!z) return z;\n\n   // round dx down to avoid overshooting\n   if (dxdy < 0)\n      z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);\n   else\n      z->dx = STBTT_ifloor(STBTT_FIX * dxdy);\n\n   z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount\n   z->x -= off_x * STBTT_FIX;\n\n   z->ey = e->y1;\n   z->next = 0;\n   z->direction = e->invert ? 1 : -1;\n   return z;\n}\n#elif STBTT_RASTERIZER_VERSION == 2\nstatic stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)\n{\n   stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);\n   float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);\n   STBTT_assert(z != NULL);\n   //STBTT_assert(e->y0 <= start_point);\n   if (!z) return z;\n   z->fdx = dxdy;\n   z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;\n   z->fx = e->x0 + dxdy * (start_point - e->y0);\n   z->fx -= off_x;\n   z->direction = e->invert ? 1.0f : -1.0f;\n   z->sy = e->y0;\n   z->ey = e->y1;\n   z->next = 0;\n   return z;\n}\n#else\n#error \"Unrecognized value of STBTT_RASTERIZER_VERSION\"\n#endif\n\n#if STBTT_RASTERIZER_VERSION == 1\n// note: this routine clips fills that extend off the edges... ideally this\n// wouldn't happen, but it could happen if the truetype glyph bounding boxes\n// are wrong, or if the user supplies a too-small bitmap\nstatic void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)\n{\n   // non-zero winding fill\n   int x0=0, w=0;\n\n   while (e) {\n      if (w == 0) {\n         // if we're currently at zero, we need to record the edge start point\n         x0 = e->x; w += e->direction;\n      } else {\n         int x1 = e->x; w += e->direction;\n         // if we went to zero, we need to draw\n         if (w == 0) {\n            int i = x0 >> STBTT_FIXSHIFT;\n            int j = x1 >> STBTT_FIXSHIFT;\n\n            if (i < len && j >= 0) {\n               if (i == j) {\n                  // x0,x1 are the same pixel, so compute combined coverage\n                  scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);\n               } else {\n                  if (i >= 0) // add antialiasing for x0\n                     scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);\n                  else\n                     i = -1; // clip\n\n                  if (j < len) // add antialiasing for x1\n                     scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);\n                  else\n                     j = len; // clip\n\n                  for (++i; i < j; ++i) // fill pixels between x0 and x1\n                     scanline[i] = scanline[i] + (stbtt_uint8) max_weight;\n               }\n            }\n         }\n      }\n\n      e = e->next;\n   }\n}\n\nstatic void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)\n{\n   stbtt__hheap hh = { 0, 0, 0 };\n   stbtt__active_edge *active = NULL;\n   int y,j=0;\n   int max_weight = (255 / vsubsample);  // weight per vertical scanline\n   int s; // vertical subsample index\n   unsigned char scanline_data[512], *scanline;\n\n   if (result->w > 512)\n      scanline = (unsigned char *) STBTT_malloc(result->w, userdata);\n   else\n      scanline = scanline_data;\n\n   y = off_y * vsubsample;\n   e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;\n\n   while (j < result->h) {\n      STBTT_memset(scanline, 0, result->w);\n      for (s=0; s < vsubsample; ++s) {\n         // find center of pixel for this scanline\n         float scan_y = y + 0.5f;\n         stbtt__active_edge **step = &active;\n\n         // update all active edges;\n         // remove all active edges that terminate before the center of this scanline\n         while (*step) {\n            stbtt__active_edge * z = *step;\n            if (z->ey <= scan_y) {\n               *step = z->next; // delete from list\n               STBTT_assert(z->direction);\n               z->direction = 0;\n               stbtt__hheap_free(&hh, z);\n            } else {\n               z->x += z->dx; // advance to position for current scanline\n               step = &((*step)->next); // advance through list\n            }\n         }\n\n         // resort the list if needed\n         for(;;) {\n            int changed=0;\n            step = &active;\n            while (*step && (*step)->next) {\n               if ((*step)->x > (*step)->next->x) {\n                  stbtt__active_edge *t = *step;\n                  stbtt__active_edge *q = t->next;\n\n                  t->next = q->next;\n                  q->next = t;\n                  *step = q;\n                  changed = 1;\n               }\n               step = &(*step)->next;\n            }\n            if (!changed) break;\n         }\n\n         // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline\n         while (e->y0 <= scan_y) {\n            if (e->y1 > scan_y) {\n               stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);\n               if (z != NULL) {\n                  // find insertion point\n                  if (active == NULL)\n                     active = z;\n                  else if (z->x < active->x) {\n                     // insert at front\n                     z->next = active;\n                     active = z;\n                  } else {\n                     // find thing to insert AFTER\n                     stbtt__active_edge *p = active;\n                     while (p->next && p->next->x < z->x)\n                        p = p->next;\n                     // at this point, p->next->x is NOT < z->x\n                     z->next = p->next;\n                     p->next = z;\n                  }\n               }\n            }\n            ++e;\n         }\n\n         // now process all active edges in XOR fashion\n         if (active)\n            stbtt__fill_active_edges(scanline, result->w, active, max_weight);\n\n         ++y;\n      }\n      STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);\n      ++j;\n   }\n\n   stbtt__hheap_cleanup(&hh, userdata);\n\n   if (scanline != scanline_data)\n      STBTT_free(scanline, userdata);\n}\n\n#elif STBTT_RASTERIZER_VERSION == 2\n\n// the edge passed in here does not cross the vertical line at x or the vertical line at x+1\n// (i.e. it has already been clipped to those)\nstatic void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)\n{\n   if (y0 == y1) return;\n   STBTT_assert(y0 < y1);\n   STBTT_assert(e->sy <= e->ey);\n   if (y0 > e->ey) return;\n   if (y1 < e->sy) return;\n   if (y0 < e->sy) {\n      x0 += (x1-x0) * (e->sy - y0) / (y1-y0);\n      y0 = e->sy;\n   }\n   if (y1 > e->ey) {\n      x1 += (x1-x0) * (e->ey - y1) / (y1-y0);\n      y1 = e->ey;\n   }\n\n   if (x0 == x)\n      STBTT_assert(x1 <= x+1);\n   else if (x0 == x+1)\n      STBTT_assert(x1 >= x);\n   else if (x0 <= x)\n      STBTT_assert(x1 <= x);\n   else if (x0 >= x+1)\n      STBTT_assert(x1 >= x+1);\n   else\n      STBTT_assert(x1 >= x && x1 <= x+1);\n\n   if (x0 <= x && x1 <= x)\n      scanline[x] += e->direction * (y1-y0);\n   else if (x0 >= x+1 && x1 >= x+1)\n      ;\n   else {\n      STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);\n      scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position\n   }\n}\n\nstatic float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width)\n{\n   STBTT_assert(top_width >= 0);\n   STBTT_assert(bottom_width >= 0);\n   return (top_width + bottom_width) / 2.0f * height;\n}\n\nstatic float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1)\n{\n   return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);\n}\n\nstatic float stbtt__sized_triangle_area(float height, float width)\n{\n   return height * width / 2;\n}\n\nstatic void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)\n{\n   float y_bottom = y_top+1;\n\n   while (e) {\n      // brute force every pixel\n\n      // compute intersection points with top & bottom\n      STBTT_assert(e->ey >= y_top);\n\n      if (e->fdx == 0) {\n         float x0 = e->fx;\n         if (x0 < len) {\n            if (x0 >= 0) {\n               stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);\n               stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);\n            } else {\n               stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);\n            }\n         }\n      } else {\n         float x0 = e->fx;\n         float dx = e->fdx;\n         float xb = x0 + dx;\n         float x_top, x_bottom;\n         float sy0,sy1;\n         float dy = e->fdy;\n         STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);\n\n         // compute endpoints of line segment clipped to this scanline (if the\n         // line segment starts on this scanline. x0 is the intersection of the\n         // line with y_top, but that may be off the line segment.\n         if (e->sy > y_top) {\n            x_top = x0 + dx * (e->sy - y_top);\n            sy0 = e->sy;\n         } else {\n            x_top = x0;\n            sy0 = y_top;\n         }\n         if (e->ey < y_bottom) {\n            x_bottom = x0 + dx * (e->ey - y_top);\n            sy1 = e->ey;\n         } else {\n            x_bottom = xb;\n            sy1 = y_bottom;\n         }\n\n         if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {\n            // from here on, we don't have to range check x values\n\n            if ((int) x_top == (int) x_bottom) {\n               float height;\n               // simple case, only spans one pixel\n               int x = (int) x_top;\n               height = (sy1 - sy0) * e->direction;\n               STBTT_assert(x >= 0 && x < len);\n               scanline[x]      += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f);\n               scanline_fill[x] += height; // everything right of this pixel is filled\n            } else {\n               int x,x1,x2;\n               float y_crossing, y_final, step, sign, area;\n               // covers 2+ pixels\n               if (x_top > x_bottom) {\n                  // flip scanline vertically; signed area is the same\n                  float t;\n                  sy0 = y_bottom - (sy0 - y_top);\n                  sy1 = y_bottom - (sy1 - y_top);\n                  t = sy0, sy0 = sy1, sy1 = t;\n                  t = x_bottom, x_bottom = x_top, x_top = t;\n                  dx = -dx;\n                  dy = -dy;\n                  t = x0, x0 = xb, xb = t;\n               }\n               STBTT_assert(dy >= 0);\n               STBTT_assert(dx >= 0);\n\n               x1 = (int) x_top;\n               x2 = (int) x_bottom;\n               // compute intersection with y axis at x1+1\n               y_crossing = y_top + dy * (x1+1 - x0);\n\n               // compute intersection with y axis at x2\n               y_final = y_top + dy * (x2 - x0);\n\n               //           x1    x_top                            x2    x_bottom\n               //     y_top  +------|-----+------------+------------+--------|---+------------+\n               //            |            |            |            |            |            |\n               //            |            |            |            |            |            |\n               //       sy0  |      Txxxxx|............|............|............|............|\n               // y_crossing |            *xxxxx.......|............|............|............|\n               //            |            |     xxxxx..|............|............|............|\n               //            |            |     /-   xx*xxxx........|............|............|\n               //            |            | dy <       |    xxxxxx..|............|............|\n               //   y_final  |            |     \\-     |          xx*xxx.........|............|\n               //       sy1  |            |            |            |   xxxxxB...|............|\n               //            |            |            |            |            |            |\n               //            |            |            |            |            |            |\n               //  y_bottom  +------------+------------+------------+------------+------------+\n               //\n               // goal is to measure the area covered by '.' in each pixel\n\n               // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057\n               // @TODO: maybe test against sy1 rather than y_bottom?\n               if (y_crossing > y_bottom)\n                  y_crossing = y_bottom;\n\n               sign = e->direction;\n\n               // area of the rectangle covered from sy0..y_crossing\n               area = sign * (y_crossing-sy0);\n\n               // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing)\n               scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top);\n\n               // check if final y_crossing is blown up; no test case for this\n               if (y_final > y_bottom) {\n                  y_final = y_bottom;\n                  dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom\n               }\n\n               // in second pixel, area covered by line segment found in first pixel\n               // is always a rectangle 1 wide * the height of that line segment; this\n               // is exactly what the variable 'area' stores. it also gets a contribution\n               // from the line segment within it. the THIRD pixel will get the first\n               // pixel's rectangle contribution, the second pixel's rectangle contribution,\n               // and its own contribution. the 'own contribution' is the same in every pixel except\n               // the leftmost and rightmost, a trapezoid that slides down in each pixel.\n               // the second pixel's contribution to the third pixel will be the\n               // rectangle 1 wide times the height change in the second pixel, which is dy.\n\n               step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x,\n               // which multiplied by 1-pixel-width is how much pixel area changes for each step in x\n               // so the area advances by 'step' every time\n\n               for (x = x1+1; x < x2; ++x) {\n                  scanline[x] += area + step/2; // area of trapezoid is 1*step/2\n                  area += step;\n               }\n               STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down\n               STBTT_assert(sy1 > y_final-0.01f);\n\n               // area covered in the last pixel is the rectangle from all the pixels to the left,\n               // plus the trapezoid filled by the line segment in this pixel all the way to the right edge\n               scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f);\n\n               // the rest of the line is filled based on the total height of the line segment in this pixel\n               scanline_fill[x2] += sign * (sy1-sy0);\n            }\n         } else {\n            // if edge goes outside of box we're drawing, we require\n            // clipping logic. since this does not match the intended use\n            // of this library, we use a different, very slow brute\n            // force implementation\n            // note though that this does happen some of the time because\n            // x_top and x_bottom can be extrapolated at the top & bottom of\n            // the shape and actually lie outside the bounding box\n            int x;\n            for (x=0; x < len; ++x) {\n               // cases:\n               //\n               // there can be up to two intersections with the pixel. any intersection\n               // with left or right edges can be handled by splitting into two (or three)\n               // regions. intersections with top & bottom do not necessitate case-wise logic.\n               //\n               // the old way of doing this found the intersections with the left & right edges,\n               // then used some simple logic to produce up to three segments in sorted order\n               // from top-to-bottom. however, this had a problem: if an x edge was epsilon\n               // across the x border, then the corresponding y position might not be distinct\n               // from the other y segment, and it might ignored as an empty segment. to avoid\n               // that, we need to explicitly produce segments based on x positions.\n\n               // rename variables to clearly-defined pairs\n               float y0 = y_top;\n               float x1 = (float) (x);\n               float x2 = (float) (x+1);\n               float x3 = xb;\n               float y3 = y_bottom;\n\n               // x = e->x + e->dx * (y-y_top)\n               // (y-y_top) = (x - e->x) / e->dx\n               // y = (x - e->x) / e->dx + y_top\n               float y1 = (x - x0) / dx + y_top;\n               float y2 = (x+1 - x0) / dx + y_top;\n\n               if (x0 < x1 && x3 > x2) {         // three segments descending down-right\n                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);\n                  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);\n                  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);\n               } else if (x3 < x1 && x0 > x2) {  // three segments descending down-left\n                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);\n                  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);\n                  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);\n               } else if (x0 < x1 && x3 > x1) {  // two segments across x, down-right\n                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);\n                  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);\n               } else if (x3 < x1 && x0 > x1) {  // two segments across x, down-left\n                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);\n                  stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);\n               } else if (x0 < x2 && x3 > x2) {  // two segments across x+1, down-right\n                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);\n                  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);\n               } else if (x3 < x2 && x0 > x2) {  // two segments across x+1, down-left\n                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);\n                  stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);\n               } else {  // one segment\n                  stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);\n               }\n            }\n         }\n      }\n      e = e->next;\n   }\n}\n\n// directly AA rasterize edges w/o supersampling\nstatic void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)\n{\n   stbtt__hheap hh = { 0, 0, 0 };\n   stbtt__active_edge *active = NULL;\n   int y,j=0, i;\n   float scanline_data[129], *scanline, *scanline2;\n\n   STBTT__NOTUSED(vsubsample);\n\n   if (result->w > 64)\n      scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);\n   else\n      scanline = scanline_data;\n\n   scanline2 = scanline + result->w;\n\n   y = off_y;\n   e[n].y0 = (float) (off_y + result->h) + 1;\n\n   while (j < result->h) {\n      // find center of pixel for this scanline\n      float scan_y_top    = y + 0.0f;\n      float scan_y_bottom = y + 1.0f;\n      stbtt__active_edge **step = &active;\n\n      STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));\n      STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));\n\n      // update all active edges;\n      // remove all active edges that terminate before the top of this scanline\n      while (*step) {\n         stbtt__active_edge * z = *step;\n         if (z->ey <= scan_y_top) {\n            *step = z->next; // delete from list\n            STBTT_assert(z->direction);\n            z->direction = 0;\n            stbtt__hheap_free(&hh, z);\n         } else {\n            step = &((*step)->next); // advance through list\n         }\n      }\n\n      // insert all edges that start before the bottom of this scanline\n      while (e->y0 <= scan_y_bottom) {\n         if (e->y0 != e->y1) {\n            stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);\n            if (z != NULL) {\n               if (j == 0 && off_y != 0) {\n                  if (z->ey < scan_y_top) {\n                     // this can happen due to subpixel positioning and some kind of fp rounding error i think\n                     z->ey = scan_y_top;\n                  }\n               }\n               STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds\n               // insert at front\n               z->next = active;\n               active = z;\n            }\n         }\n         ++e;\n      }\n\n      // now process all active edges\n      if (active)\n         stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);\n\n      {\n         float sum = 0;\n         for (i=0; i < result->w; ++i) {\n            float k;\n            int m;\n            sum += scanline2[i];\n            k = scanline[i] + sum;\n            k = (float) STBTT_fabs(k)*255 + 0.5f;\n            m = (int) k;\n            if (m > 255) m = 255;\n            result->pixels[j*result->stride + i] = (unsigned char) m;\n         }\n      }\n      // advance all the edges\n      step = &active;\n      while (*step) {\n         stbtt__active_edge *z = *step;\n         z->fx += z->fdx; // advance to position for current scanline\n         step = &((*step)->next); // advance through list\n      }\n\n      ++y;\n      ++j;\n   }\n\n   stbtt__hheap_cleanup(&hh, userdata);\n\n   if (scanline != scanline_data)\n      STBTT_free(scanline, userdata);\n}\n#else\n#error \"Unrecognized value of STBTT_RASTERIZER_VERSION\"\n#endif\n\n#define STBTT__COMPARE(a,b)  ((a)->y0 < (b)->y0)\n\nstatic void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)\n{\n   int i,j;\n   for (i=1; i < n; ++i) {\n      stbtt__edge t = p[i], *a = &t;\n      j = i;\n      while (j > 0) {\n         stbtt__edge *b = &p[j-1];\n         int c = STBTT__COMPARE(a,b);\n         if (!c) break;\n         p[j] = p[j-1];\n         --j;\n      }\n      if (i != j)\n         p[j] = t;\n   }\n}\n\nstatic void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)\n{\n   /* threshold for transitioning to insertion sort */\n   while (n > 12) {\n      stbtt__edge t;\n      int c01,c12,c,m,i,j;\n\n      /* compute median of three */\n      m = n >> 1;\n      c01 = STBTT__COMPARE(&p[0],&p[m]);\n      c12 = STBTT__COMPARE(&p[m],&p[n-1]);\n      /* if 0 >= mid >= end, or 0 < mid < end, then use mid */\n      if (c01 != c12) {\n         /* otherwise, we'll need to swap something else to middle */\n         int z;\n         c = STBTT__COMPARE(&p[0],&p[n-1]);\n         /* 0>mid && mid<n:  0>n => n; 0<n => 0 */\n         /* 0<mid && mid>n:  0>n => 0; 0<n => n */\n         z = (c == c12) ? 0 : n-1;\n         t = p[z];\n         p[z] = p[m];\n         p[m] = t;\n      }\n      /* now p[m] is the median-of-three */\n      /* swap it to the beginning so it won't move around */\n      t = p[0];\n      p[0] = p[m];\n      p[m] = t;\n\n      /* partition loop */\n      i=1;\n      j=n-1;\n      for(;;) {\n         /* handling of equality is crucial here */\n         /* for sentinels & efficiency with duplicates */\n         for (;;++i) {\n            if (!STBTT__COMPARE(&p[i], &p[0])) break;\n         }\n         for (;;--j) {\n            if (!STBTT__COMPARE(&p[0], &p[j])) break;\n         }\n         /* make sure we haven't crossed */\n         if (i >= j) break;\n         t = p[i];\n         p[i] = p[j];\n         p[j] = t;\n\n         ++i;\n         --j;\n      }\n      /* recurse on smaller side, iterate on larger */\n      if (j < (n-i)) {\n         stbtt__sort_edges_quicksort(p,j);\n         p = p+i;\n         n = n-i;\n      } else {\n         stbtt__sort_edges_quicksort(p+i, n-i);\n         n = j;\n      }\n   }\n}\n\nstatic void stbtt__sort_edges(stbtt__edge *p, int n)\n{\n   stbtt__sort_edges_quicksort(p, n);\n   stbtt__sort_edges_ins_sort(p, n);\n}\n\ntypedef struct\n{\n   float x,y;\n} stbtt__point;\n\nstatic void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata)\n{\n   float y_scale_inv = invert ? -scale_y : scale_y;\n   stbtt__edge *e;\n   int n,i,j,k,m;\n#if STBTT_RASTERIZER_VERSION == 1\n   int vsubsample = result->h < 8 ? 15 : 5;\n#elif STBTT_RASTERIZER_VERSION == 2\n   int vsubsample = 1;\n#else\n   #error \"Unrecognized value of STBTT_RASTERIZER_VERSION\"\n#endif\n   // vsubsample should divide 255 evenly; otherwise we won't reach full opacity\n\n   // now we have to blow out the windings into explicit edge lists\n   n = 0;\n   for (i=0; i < windings; ++i)\n      n += wcount[i];\n\n   e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel\n   if (e == 0) return;\n   n = 0;\n\n   m=0;\n   for (i=0; i < windings; ++i) {\n      stbtt__point *p = pts + m;\n      m += wcount[i];\n      j = wcount[i]-1;\n      for (k=0; k < wcount[i]; j=k++) {\n         int a=k,b=j;\n         // skip the edge if horizontal\n         if (p[j].y == p[k].y)\n            continue;\n         // add edge from j to k to the list\n         e[n].invert = 0;\n         if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {\n            e[n].invert = 1;\n            a=j,b=k;\n         }\n         e[n].x0 = p[a].x * scale_x + shift_x;\n         e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;\n         e[n].x1 = p[b].x * scale_x + shift_x;\n         e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;\n         ++n;\n      }\n   }\n\n   // now sort the edges by their highest point (should snap to integer, and then by x)\n   //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);\n   stbtt__sort_edges(e, n);\n\n   // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule\n   stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);\n\n   STBTT_free(e, userdata);\n}\n\nstatic void stbtt__add_point(stbtt__point *points, int n, float x, float y)\n{\n   if (!points) return; // during first pass, it's unallocated\n   points[n].x = x;\n   points[n].y = y;\n}\n\n// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching\nstatic int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)\n{\n   // midpoint\n   float mx = (x0 + 2*x1 + x2)/4;\n   float my = (y0 + 2*y1 + y2)/4;\n   // versus directly drawn line\n   float dx = (x0+x2)/2 - mx;\n   float dy = (y0+y2)/2 - my;\n   if (n > 16) // 65536 segments on one curve better be enough!\n      return 1;\n   if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA\n      stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);\n      stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);\n   } else {\n      stbtt__add_point(points, *num_points,x2,y2);\n      *num_points = *num_points+1;\n   }\n   return 1;\n}\n\nstatic void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n)\n{\n   // @TODO this \"flatness\" calculation is just made-up nonsense that seems to work well enough\n   float dx0 = x1-x0;\n   float dy0 = y1-y0;\n   float dx1 = x2-x1;\n   float dy1 = y2-y1;\n   float dx2 = x3-x2;\n   float dy2 = y3-y2;\n   float dx = x3-x0;\n   float dy = y3-y0;\n   float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2));\n   float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy);\n   float flatness_squared = longlen*longlen-shortlen*shortlen;\n\n   if (n > 16) // 65536 segments on one curve better be enough!\n      return;\n\n   if (flatness_squared > objspace_flatness_squared) {\n      float x01 = (x0+x1)/2;\n      float y01 = (y0+y1)/2;\n      float x12 = (x1+x2)/2;\n      float y12 = (y1+y2)/2;\n      float x23 = (x2+x3)/2;\n      float y23 = (y2+y3)/2;\n\n      float xa = (x01+x12)/2;\n      float ya = (y01+y12)/2;\n      float xb = (x12+x23)/2;\n      float yb = (y12+y23)/2;\n\n      float mx = (xa+xb)/2;\n      float my = (ya+yb)/2;\n\n      stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1);\n      stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1);\n   } else {\n      stbtt__add_point(points, *num_points,x3,y3);\n      *num_points = *num_points+1;\n   }\n}\n\n// returns number of contours\nstatic stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)\n{\n   stbtt__point *points=0;\n   int num_points=0;\n\n   float objspace_flatness_squared = objspace_flatness * objspace_flatness;\n   int i,n=0,start=0, pass;\n\n   // count how many \"moves\" there are to get the contour count\n   for (i=0; i < num_verts; ++i)\n      if (vertices[i].type == STBTT_vmove)\n         ++n;\n\n   *num_contours = n;\n   if (n == 0) return 0;\n\n   *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);\n\n   if (*contour_lengths == 0) {\n      *num_contours = 0;\n      return 0;\n   }\n\n   // make two passes through the points so we don't need to realloc\n   for (pass=0; pass < 2; ++pass) {\n      float x=0,y=0;\n      if (pass == 1) {\n         points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);\n         if (points == NULL) goto error;\n      }\n      num_points = 0;\n      n= -1;\n      for (i=0; i < num_verts; ++i) {\n         switch (vertices[i].type) {\n            case STBTT_vmove:\n               // start the next contour\n               if (n >= 0)\n                  (*contour_lengths)[n] = num_points - start;\n               ++n;\n               start = num_points;\n\n               x = vertices[i].x, y = vertices[i].y;\n               stbtt__add_point(points, num_points++, x,y);\n               break;\n            case STBTT_vline:\n               x = vertices[i].x, y = vertices[i].y;\n               stbtt__add_point(points, num_points++, x, y);\n               break;\n            case STBTT_vcurve:\n               stbtt__tesselate_curve(points, &num_points, x,y,\n                                        vertices[i].cx, vertices[i].cy,\n                                        vertices[i].x,  vertices[i].y,\n                                        objspace_flatness_squared, 0);\n               x = vertices[i].x, y = vertices[i].y;\n               break;\n            case STBTT_vcubic:\n               stbtt__tesselate_cubic(points, &num_points, x,y,\n                                        vertices[i].cx, vertices[i].cy,\n                                        vertices[i].cx1, vertices[i].cy1,\n                                        vertices[i].x,  vertices[i].y,\n                                        objspace_flatness_squared, 0);\n               x = vertices[i].x, y = vertices[i].y;\n               break;\n         }\n      }\n      (*contour_lengths)[n] = num_points - start;\n   }\n\n   return points;\nerror:\n   STBTT_free(points, userdata);\n   STBTT_free(*contour_lengths, userdata);\n   *contour_lengths = 0;\n   *num_contours = 0;\n   return NULL;\n}\n\nSTBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)\n{\n   float scale            = scale_x > scale_y ? scale_y : scale_x;\n   int winding_count      = 0;\n   int *winding_lengths   = NULL;\n   stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);\n   if (windings) {\n      stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);\n      STBTT_free(winding_lengths, userdata);\n      STBTT_free(windings, userdata);\n   }\n}\n\nSTBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)\n{\n   STBTT_free(bitmap, userdata);\n}\n\nSTBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff)\n{\n   int ix0,iy0,ix1,iy1;\n   stbtt__bitmap gbm;\n   stbtt_vertex *vertices;\n   int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);\n\n   if (scale_x == 0) scale_x = scale_y;\n   if (scale_y == 0) {\n      if (scale_x == 0) {\n         STBTT_free(vertices, info->userdata);\n         return NULL;\n      }\n      scale_y = scale_x;\n   }\n\n   stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);\n\n   // now we get the size\n   gbm.w = (ix1 - ix0);\n   gbm.h = (iy1 - iy0);\n   gbm.pixels = NULL; // in case we error\n\n   if (width ) *width  = gbm.w;\n   if (height) *height = gbm.h;\n   if (xoff  ) *xoff   = ix0;\n   if (yoff  ) *yoff   = iy0;\n\n   if (gbm.w && gbm.h) {\n      gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);\n      if (gbm.pixels) {\n         gbm.stride = gbm.w;\n\n         stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);\n      }\n   }\n   STBTT_free(vertices, info->userdata);\n   return gbm.pixels;\n}\n\nSTBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)\n{\n   return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);\n}\n\nSTBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph)\n{\n   int ix0,iy0;\n   stbtt_vertex *vertices;\n   int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);\n   stbtt__bitmap gbm;\n\n   stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);\n   gbm.pixels = output;\n   gbm.w = out_w;\n   gbm.h = out_h;\n   gbm.stride = out_stride;\n\n   if (gbm.w && gbm.h)\n      stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);\n\n   STBTT_free(vertices, info->userdata);\n}\n\nSTBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph)\n{\n   stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);\n}\n\nSTBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)\n{\n   return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);\n}\n\nSTBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)\n{\n   stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));\n}\n\nSTBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)\n{\n   stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));\n}\n\nSTBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)\n{\n   return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);\n}\n\nSTBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)\n{\n   stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);\n}\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// bitmap baking\n//\n// This is SUPER-CRAPPY packing to keep source code small\n\nstatic int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset,  // font location (use offset=0 for plain .ttf)\n                                float pixel_height,                     // height of font in pixels\n                                unsigned char *pixels, int pw, int ph,  // bitmap to be filled in\n                                int first_char, int num_chars,          // characters to bake\n                                stbtt_bakedchar *chardata)\n{\n   float scale;\n   int x,y,bottom_y, i;\n   stbtt_fontinfo f;\n   f.userdata = NULL;\n   if (!stbtt_InitFont(&f, data, offset))\n      return -1;\n   STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels\n   x=y=1;\n   bottom_y = 1;\n\n   scale = stbtt_ScaleForPixelHeight(&f, pixel_height);\n\n   for (i=0; i < num_chars; ++i) {\n      int advance, lsb, x0,y0,x1,y1,gw,gh;\n      int g = stbtt_FindGlyphIndex(&f, first_char + i);\n      stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);\n      stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);\n      gw = x1-x0;\n      gh = y1-y0;\n      if (x + gw + 1 >= pw)\n         y = bottom_y, x = 1; // advance to next row\n      if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row\n         return -i;\n      STBTT_assert(x+gw < pw);\n      STBTT_assert(y+gh < ph);\n      stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);\n      chardata[i].x0 = (stbtt_int16) x;\n      chardata[i].y0 = (stbtt_int16) y;\n      chardata[i].x1 = (stbtt_int16) (x + gw);\n      chardata[i].y1 = (stbtt_int16) (y + gh);\n      chardata[i].xadvance = scale * advance;\n      chardata[i].xoff     = (float) x0;\n      chardata[i].yoff     = (float) y0;\n      x = x + gw + 1;\n      if (y+gh+1 > bottom_y)\n         bottom_y = y+gh+1;\n   }\n   return bottom_y;\n}\n\nSTBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)\n{\n   float d3d_bias = opengl_fillrule ? 0 : -0.5f;\n   float ipw = 1.0f / pw, iph = 1.0f / ph;\n   const stbtt_bakedchar *b = chardata + char_index;\n   int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);\n   int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);\n\n   q->x0 = round_x + d3d_bias;\n   q->y0 = round_y + d3d_bias;\n   q->x1 = round_x + b->x1 - b->x0 + d3d_bias;\n   q->y1 = round_y + b->y1 - b->y0 + d3d_bias;\n\n   q->s0 = b->x0 * ipw;\n   q->t0 = b->y0 * iph;\n   q->s1 = b->x1 * ipw;\n   q->t1 = b->y1 * iph;\n\n   *xpos += b->xadvance;\n}\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// rectangle packing replacement routines if you don't have stb_rect_pack.h\n//\n\n#ifndef STB_RECT_PACK_VERSION\n\ntypedef int stbrp_coord;\n\n////////////////////////////////////////////////////////////////////////////////////\n//                                                                                //\n//                                                                                //\n// COMPILER WARNING ?!?!?                                                         //\n//                                                                                //\n//                                                                                //\n// if you get a compile warning due to these symbols being defined more than      //\n// once, move #include \"stb_rect_pack.h\" before #include \"stb_truetype.h\"         //\n//                                                                                //\n////////////////////////////////////////////////////////////////////////////////////\n\ntypedef struct\n{\n   int width,height;\n   int x,y,bottom_y;\n} stbrp_context;\n\ntypedef struct\n{\n   unsigned char x;\n} stbrp_node;\n\nstruct stbrp_rect\n{\n   stbrp_coord x,y;\n   int id,w,h,was_packed;\n};\n\nstatic void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)\n{\n   con->width  = pw;\n   con->height = ph;\n   con->x = 0;\n   con->y = 0;\n   con->bottom_y = 0;\n   STBTT__NOTUSED(nodes);\n   STBTT__NOTUSED(num_nodes);\n}\n\nstatic void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)\n{\n   int i;\n   for (i=0; i < num_rects; ++i) {\n      if (con->x + rects[i].w > con->width) {\n         con->x = 0;\n         con->y = con->bottom_y;\n      }\n      if (con->y + rects[i].h > con->height)\n         break;\n      rects[i].x = con->x;\n      rects[i].y = con->y;\n      rects[i].was_packed = 1;\n      con->x += rects[i].w;\n      if (con->y + rects[i].h > con->bottom_y)\n         con->bottom_y = con->y + rects[i].h;\n   }\n   for (   ; i < num_rects; ++i)\n      rects[i].was_packed = 0;\n}\n#endif\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// bitmap baking\n//\n// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If\n// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy.\n\nSTBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context)\n{\n   stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context)            ,alloc_context);\n   int            num_nodes = pw - padding;\n   stbrp_node    *nodes   = (stbrp_node    *) STBTT_malloc(sizeof(*nodes  ) * num_nodes,alloc_context);\n\n   if (context == NULL || nodes == NULL) {\n      if (context != NULL) STBTT_free(context, alloc_context);\n      if (nodes   != NULL) STBTT_free(nodes  , alloc_context);\n      return 0;\n   }\n\n   spc->user_allocator_context = alloc_context;\n   spc->width = pw;\n   spc->height = ph;\n   spc->pixels = pixels;\n   spc->pack_info = context;\n   spc->nodes = nodes;\n   spc->padding = padding;\n   spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;\n   spc->h_oversample = 1;\n   spc->v_oversample = 1;\n   spc->skip_missing = 0;\n\n   stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);\n\n   if (pixels)\n      STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels\n\n   return 1;\n}\n\nSTBTT_DEF void stbtt_PackEnd  (stbtt_pack_context *spc)\n{\n   STBTT_free(spc->nodes    , spc->user_allocator_context);\n   STBTT_free(spc->pack_info, spc->user_allocator_context);\n}\n\nSTBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)\n{\n   STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);\n   STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);\n   if (h_oversample <= STBTT_MAX_OVERSAMPLE)\n      spc->h_oversample = h_oversample;\n   if (v_oversample <= STBTT_MAX_OVERSAMPLE)\n      spc->v_oversample = v_oversample;\n}\n\nSTBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)\n{\n   spc->skip_missing = skip;\n}\n\n#define STBTT__OVER_MASK  (STBTT_MAX_OVERSAMPLE-1)\n\nstatic void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)\n{\n   unsigned char buffer[STBTT_MAX_OVERSAMPLE];\n   int safe_w = w - kernel_width;\n   int j;\n   STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze\n   for (j=0; j < h; ++j) {\n      int i;\n      unsigned int total;\n      STBTT_memset(buffer, 0, kernel_width);\n\n      total = 0;\n\n      // make kernel_width a constant in common cases so compiler can optimize out the divide\n      switch (kernel_width) {\n         case 2:\n            for (i=0; i <= safe_w; ++i) {\n               total += pixels[i] - buffer[i & STBTT__OVER_MASK];\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];\n               pixels[i] = (unsigned char) (total / 2);\n            }\n            break;\n         case 3:\n            for (i=0; i <= safe_w; ++i) {\n               total += pixels[i] - buffer[i & STBTT__OVER_MASK];\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];\n               pixels[i] = (unsigned char) (total / 3);\n            }\n            break;\n         case 4:\n            for (i=0; i <= safe_w; ++i) {\n               total += pixels[i] - buffer[i & STBTT__OVER_MASK];\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];\n               pixels[i] = (unsigned char) (total / 4);\n            }\n            break;\n         case 5:\n            for (i=0; i <= safe_w; ++i) {\n               total += pixels[i] - buffer[i & STBTT__OVER_MASK];\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];\n               pixels[i] = (unsigned char) (total / 5);\n            }\n            break;\n         default:\n            for (i=0; i <= safe_w; ++i) {\n               total += pixels[i] - buffer[i & STBTT__OVER_MASK];\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];\n               pixels[i] = (unsigned char) (total / kernel_width);\n            }\n            break;\n      }\n\n      for (; i < w; ++i) {\n         STBTT_assert(pixels[i] == 0);\n         total -= buffer[i & STBTT__OVER_MASK];\n         pixels[i] = (unsigned char) (total / kernel_width);\n      }\n\n      pixels += stride_in_bytes;\n   }\n}\n\nstatic void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)\n{\n   unsigned char buffer[STBTT_MAX_OVERSAMPLE];\n   int safe_h = h - kernel_width;\n   int j;\n   STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze\n   for (j=0; j < w; ++j) {\n      int i;\n      unsigned int total;\n      STBTT_memset(buffer, 0, kernel_width);\n\n      total = 0;\n\n      // make kernel_width a constant in common cases so compiler can optimize out the divide\n      switch (kernel_width) {\n         case 2:\n            for (i=0; i <= safe_h; ++i) {\n               total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];\n               pixels[i*stride_in_bytes] = (unsigned char) (total / 2);\n            }\n            break;\n         case 3:\n            for (i=0; i <= safe_h; ++i) {\n               total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];\n               pixels[i*stride_in_bytes] = (unsigned char) (total / 3);\n            }\n            break;\n         case 4:\n            for (i=0; i <= safe_h; ++i) {\n               total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];\n               pixels[i*stride_in_bytes] = (unsigned char) (total / 4);\n            }\n            break;\n         case 5:\n            for (i=0; i <= safe_h; ++i) {\n               total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];\n               pixels[i*stride_in_bytes] = (unsigned char) (total / 5);\n            }\n            break;\n         default:\n            for (i=0; i <= safe_h; ++i) {\n               total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];\n               buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];\n               pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);\n            }\n            break;\n      }\n\n      for (; i < h; ++i) {\n         STBTT_assert(pixels[i*stride_in_bytes] == 0);\n         total -= buffer[i & STBTT__OVER_MASK];\n         pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);\n      }\n\n      pixels += 1;\n   }\n}\n\nstatic float stbtt__oversample_shift(int oversample)\n{\n   if (!oversample)\n      return 0.0f;\n\n   // The prefilter is a box filter of width \"oversample\",\n   // which shifts phase by (oversample - 1)/2 pixels in\n   // oversampled space. We want to shift in the opposite\n   // direction to counter this.\n   return (float)-(oversample - 1) / (2.0f * (float)oversample);\n}\n\n// rects array must be big enough to accommodate all characters in the given ranges\nSTBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)\n{\n   int i,j,k;\n   int missing_glyph_added = 0;\n\n   k=0;\n   for (i=0; i < num_ranges; ++i) {\n      float fh = ranges[i].font_size;\n      float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);\n      ranges[i].h_oversample = (unsigned char) spc->h_oversample;\n      ranges[i].v_oversample = (unsigned char) spc->v_oversample;\n      for (j=0; j < ranges[i].num_chars; ++j) {\n         int x0,y0,x1,y1;\n         int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];\n         int glyph = stbtt_FindGlyphIndex(info, codepoint);\n         if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) {\n            rects[k].w = rects[k].h = 0;\n         } else {\n            stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,\n                                            scale * spc->h_oversample,\n                                            scale * spc->v_oversample,\n                                            0,0,\n                                            &x0,&y0,&x1,&y1);\n            rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);\n            rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);\n            if (glyph == 0)\n               missing_glyph_added = 1;\n         }\n         ++k;\n      }\n   }\n\n   return k;\n}\n\nSTBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph)\n{\n   stbtt_MakeGlyphBitmapSubpixel(info,\n                                 output,\n                                 out_w - (prefilter_x - 1),\n                                 out_h - (prefilter_y - 1),\n                                 out_stride,\n                                 scale_x,\n                                 scale_y,\n                                 shift_x,\n                                 shift_y,\n                                 glyph);\n\n   if (prefilter_x > 1)\n      stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x);\n\n   if (prefilter_y > 1)\n      stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y);\n\n   *sub_x = stbtt__oversample_shift(prefilter_x);\n   *sub_y = stbtt__oversample_shift(prefilter_y);\n}\n\n// rects array must be big enough to accommodate all characters in the given ranges\nSTBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)\n{\n   int i,j,k, missing_glyph = -1, return_value = 1;\n\n   // save current values\n   int old_h_over = spc->h_oversample;\n   int old_v_over = spc->v_oversample;\n\n   k = 0;\n   for (i=0; i < num_ranges; ++i) {\n      float fh = ranges[i].font_size;\n      float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);\n      float recip_h,recip_v,sub_x,sub_y;\n      spc->h_oversample = ranges[i].h_oversample;\n      spc->v_oversample = ranges[i].v_oversample;\n      recip_h = 1.0f / spc->h_oversample;\n      recip_v = 1.0f / spc->v_oversample;\n      sub_x = stbtt__oversample_shift(spc->h_oversample);\n      sub_y = stbtt__oversample_shift(spc->v_oversample);\n      for (j=0; j < ranges[i].num_chars; ++j) {\n         stbrp_rect *r = &rects[k];\n         if (r->was_packed && r->w != 0 && r->h != 0) {\n            stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];\n            int advance, lsb, x0,y0,x1,y1;\n            int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];\n            int glyph = stbtt_FindGlyphIndex(info, codepoint);\n            stbrp_coord pad = (stbrp_coord) spc->padding;\n\n            // pad on left and top\n            r->x += pad;\n            r->y += pad;\n            r->w -= pad;\n            r->h -= pad;\n            stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);\n            stbtt_GetGlyphBitmapBox(info, glyph,\n                                    scale * spc->h_oversample,\n                                    scale * spc->v_oversample,\n                                    &x0,&y0,&x1,&y1);\n            stbtt_MakeGlyphBitmapSubpixel(info,\n                                          spc->pixels + r->x + r->y*spc->stride_in_bytes,\n                                          r->w - spc->h_oversample+1,\n                                          r->h - spc->v_oversample+1,\n                                          spc->stride_in_bytes,\n                                          scale * spc->h_oversample,\n                                          scale * spc->v_oversample,\n                                          0,0,\n                                          glyph);\n\n            if (spc->h_oversample > 1)\n               stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,\n                                  r->w, r->h, spc->stride_in_bytes,\n                                  spc->h_oversample);\n\n            if (spc->v_oversample > 1)\n               stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,\n                                  r->w, r->h, spc->stride_in_bytes,\n                                  spc->v_oversample);\n\n            bc->x0       = (stbtt_int16)  r->x;\n            bc->y0       = (stbtt_int16)  r->y;\n            bc->x1       = (stbtt_int16) (r->x + r->w);\n            bc->y1       = (stbtt_int16) (r->y + r->h);\n            bc->xadvance =                scale * advance;\n            bc->xoff     =       (float)  x0 * recip_h + sub_x;\n            bc->yoff     =       (float)  y0 * recip_v + sub_y;\n            bc->xoff2    =                (x0 + r->w) * recip_h + sub_x;\n            bc->yoff2    =                (y0 + r->h) * recip_v + sub_y;\n\n            if (glyph == 0)\n               missing_glyph = j;\n         } else if (spc->skip_missing) {\n            return_value = 0;\n         } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) {\n            ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph];\n         } else {\n            return_value = 0; // if any fail, report failure\n         }\n\n         ++k;\n      }\n   }\n\n   // restore original values\n   spc->h_oversample = old_h_over;\n   spc->v_oversample = old_v_over;\n\n   return return_value;\n}\n\nSTBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)\n{\n   stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);\n}\n\nSTBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)\n{\n   stbtt_fontinfo info;\n   int i,j,n, return_value = 1;\n   //stbrp_context *context = (stbrp_context *) spc->pack_info;\n   stbrp_rect    *rects;\n\n   // flag all characters as NOT packed\n   for (i=0; i < num_ranges; ++i)\n      for (j=0; j < ranges[i].num_chars; ++j)\n         ranges[i].chardata_for_range[j].x0 =\n         ranges[i].chardata_for_range[j].y0 =\n         ranges[i].chardata_for_range[j].x1 =\n         ranges[i].chardata_for_range[j].y1 = 0;\n\n   n = 0;\n   for (i=0; i < num_ranges; ++i)\n      n += ranges[i].num_chars;\n\n   rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);\n   if (rects == NULL)\n      return 0;\n\n   info.userdata = spc->user_allocator_context;\n   stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));\n\n   n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);\n\n   stbtt_PackFontRangesPackRects(spc, rects, n);\n\n   return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);\n\n   STBTT_free(rects, spc->user_allocator_context);\n   return return_value;\n}\n\nSTBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,\n            int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)\n{\n   stbtt_pack_range range;\n   range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range;\n   range.array_of_unicode_codepoints = NULL;\n   range.num_chars                   = num_chars_in_range;\n   range.chardata_for_range          = chardata_for_range;\n   range.font_size                   = font_size;\n   return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);\n}\n\nSTBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)\n{\n   int i_ascent, i_descent, i_lineGap;\n   float scale;\n   stbtt_fontinfo info;\n   stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));\n   scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);\n   stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);\n   *ascent  = (float) i_ascent  * scale;\n   *descent = (float) i_descent * scale;\n   *lineGap = (float) i_lineGap * scale;\n}\n\nSTBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)\n{\n   float ipw = 1.0f / pw, iph = 1.0f / ph;\n   const stbtt_packedchar *b = chardata + char_index;\n\n   if (align_to_integer) {\n      float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);\n      float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);\n      q->x0 = x;\n      q->y0 = y;\n      q->x1 = x + b->xoff2 - b->xoff;\n      q->y1 = y + b->yoff2 - b->yoff;\n   } else {\n      q->x0 = *xpos + b->xoff;\n      q->y0 = *ypos + b->yoff;\n      q->x1 = *xpos + b->xoff2;\n      q->y1 = *ypos + b->yoff2;\n   }\n\n   q->s0 = b->x0 * ipw;\n   q->t0 = b->y0 * iph;\n   q->s1 = b->x1 * ipw;\n   q->t1 = b->y1 * iph;\n\n   *xpos += b->xadvance;\n}\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// sdf computation\n//\n\n#define STBTT_min(a,b)  ((a) < (b) ? (a) : (b))\n#define STBTT_max(a,b)  ((a) < (b) ? (b) : (a))\n\nstatic int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2])\n{\n   float q0perp = q0[1]*ray[0] - q0[0]*ray[1];\n   float q1perp = q1[1]*ray[0] - q1[0]*ray[1];\n   float q2perp = q2[1]*ray[0] - q2[0]*ray[1];\n   float roperp = orig[1]*ray[0] - orig[0]*ray[1];\n\n   float a = q0perp - 2*q1perp + q2perp;\n   float b = q1perp - q0perp;\n   float c = q0perp - roperp;\n\n   float s0 = 0., s1 = 0.;\n   int num_s = 0;\n\n   if (a != 0.0) {\n      float discr = b*b - a*c;\n      if (discr > 0.0) {\n         float rcpna = -1 / a;\n         float d = (float) STBTT_sqrt(discr);\n         s0 = (b+d) * rcpna;\n         s1 = (b-d) * rcpna;\n         if (s0 >= 0.0 && s0 <= 1.0)\n            num_s = 1;\n         if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) {\n            if (num_s == 0) s0 = s1;\n            ++num_s;\n         }\n      }\n   } else {\n      // 2*b*s + c = 0\n      // s = -c / (2*b)\n      s0 = c / (-2 * b);\n      if (s0 >= 0.0 && s0 <= 1.0)\n         num_s = 1;\n   }\n\n   if (num_s == 0)\n      return 0;\n   else {\n      float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]);\n      float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2;\n\n      float q0d =   q0[0]*rayn_x +   q0[1]*rayn_y;\n      float q1d =   q1[0]*rayn_x +   q1[1]*rayn_y;\n      float q2d =   q2[0]*rayn_x +   q2[1]*rayn_y;\n      float rod = orig[0]*rayn_x + orig[1]*rayn_y;\n\n      float q10d = q1d - q0d;\n      float q20d = q2d - q0d;\n      float q0rd = q0d - rod;\n\n      hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d;\n      hits[0][1] = a*s0+b;\n\n      if (num_s > 1) {\n         hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d;\n         hits[1][1] = a*s1+b;\n         return 2;\n      } else {\n         return 1;\n      }\n   }\n}\n\nstatic int equal(float *a, float *b)\n{\n   return (a[0] == b[0] && a[1] == b[1]);\n}\n\nstatic int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts)\n{\n   int i;\n   float orig[2], ray[2] = { 1, 0 };\n   float y_frac;\n   int winding = 0;\n\n   // make sure y never passes through a vertex of the shape\n   y_frac = (float) STBTT_fmod(y, 1.0f);\n   if (y_frac < 0.01f)\n      y += 0.01f;\n   else if (y_frac > 0.99f)\n      y -= 0.01f;\n\n   orig[0] = x;\n   orig[1] = y;\n\n   // test a ray from (-infinity,y) to (x,y)\n   for (i=0; i < nverts; ++i) {\n      if (verts[i].type == STBTT_vline) {\n         int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y;\n         int x1 = (int) verts[i  ].x, y1 = (int) verts[i  ].y;\n         if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {\n            float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;\n            if (x_inter < x)\n               winding += (y0 < y1) ? 1 : -1;\n         }\n      }\n      if (verts[i].type == STBTT_vcurve) {\n         int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ;\n         int x1 = (int) verts[i  ].cx, y1 = (int) verts[i  ].cy;\n         int x2 = (int) verts[i  ].x , y2 = (int) verts[i  ].y ;\n         int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2));\n         int by = STBTT_max(y0,STBTT_max(y1,y2));\n         if (y > ay && y < by && x > ax) {\n            float q0[2],q1[2],q2[2];\n            float hits[2][2];\n            q0[0] = (float)x0;\n            q0[1] = (float)y0;\n            q1[0] = (float)x1;\n            q1[1] = (float)y1;\n            q2[0] = (float)x2;\n            q2[1] = (float)y2;\n            if (equal(q0,q1) || equal(q1,q2)) {\n               x0 = (int)verts[i-1].x;\n               y0 = (int)verts[i-1].y;\n               x1 = (int)verts[i  ].x;\n               y1 = (int)verts[i  ].y;\n               if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {\n                  float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;\n                  if (x_inter < x)\n                     winding += (y0 < y1) ? 1 : -1;\n               }\n            } else {\n               int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits);\n               if (num_hits >= 1)\n                  if (hits[0][0] < 0)\n                     winding += (hits[0][1] < 0 ? -1 : 1);\n               if (num_hits >= 2)\n                  if (hits[1][0] < 0)\n                     winding += (hits[1][1] < 0 ? -1 : 1);\n            }\n         }\n      }\n   }\n   return winding;\n}\n\nstatic float stbtt__cuberoot( float x )\n{\n   if (x<0)\n      return -(float) STBTT_pow(-x,1.0f/3.0f);\n   else\n      return  (float) STBTT_pow( x,1.0f/3.0f);\n}\n\n// x^3 + a*x^2 + b*x + c = 0\nstatic int stbtt__solve_cubic(float a, float b, float c, float* r)\n{\n   float s = -a / 3;\n   float p = b - a*a / 3;\n   float q = a * (2*a*a - 9*b) / 27 + c;\n   float p3 = p*p*p;\n   float d = q*q + 4*p3 / 27;\n   if (d >= 0) {\n      float z = (float) STBTT_sqrt(d);\n      float u = (-q + z) / 2;\n      float v = (-q - z) / 2;\n      u = stbtt__cuberoot(u);\n      v = stbtt__cuberoot(v);\n      r[0] = s + u + v;\n      return 1;\n   } else {\n      float u = (float) STBTT_sqrt(-p/3);\n      float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative\n      float m = (float) STBTT_cos(v);\n      float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;\n      r[0] = s + u * 2 * m;\n      r[1] = s - u * (m + n);\n      r[2] = s - u * (m - n);\n\n      //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f);  // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe?\n      //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);\n      //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);\n      return 3;\n   }\n}\n\nSTBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)\n{\n   float scale_x = scale, scale_y = scale;\n   int ix0,iy0,ix1,iy1;\n   int w,h;\n   unsigned char *data;\n\n   if (scale == 0) return NULL;\n\n   stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);\n\n   // if empty, return NULL\n   if (ix0 == ix1 || iy0 == iy1)\n      return NULL;\n\n   ix0 -= padding;\n   iy0 -= padding;\n   ix1 += padding;\n   iy1 += padding;\n\n   w = (ix1 - ix0);\n   h = (iy1 - iy0);\n\n   if (width ) *width  = w;\n   if (height) *height = h;\n   if (xoff  ) *xoff   = ix0;\n   if (yoff  ) *yoff   = iy0;\n\n   // invert for y-downwards bitmaps\n   scale_y = -scale_y;\n\n   {\n      int x,y,i,j;\n      float *precompute;\n      stbtt_vertex *verts;\n      int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);\n      data = (unsigned char *) STBTT_malloc(w * h, info->userdata);\n      precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata);\n\n      for (i=0,j=num_verts-1; i < num_verts; j=i++) {\n         if (verts[i].type == STBTT_vline) {\n            float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;\n            float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y;\n            float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));\n            precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist;\n         } else if (verts[i].type == STBTT_vcurve) {\n            float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y;\n            float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y;\n            float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;\n            float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;\n            float len2 = bx*bx + by*by;\n            if (len2 != 0.0f)\n               precompute[i] = 1.0f / (bx*bx + by*by);\n            else\n               precompute[i] = 0.0f;\n         } else\n            precompute[i] = 0.0f;\n      }\n\n      for (y=iy0; y < iy1; ++y) {\n         for (x=ix0; x < ix1; ++x) {\n            float val;\n            float min_dist = 999999.0f;\n            float sx = (float) x + 0.5f;\n            float sy = (float) y + 0.5f;\n            float x_gspace = (sx / scale_x);\n            float y_gspace = (sy / scale_y);\n\n            int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path\n\n            for (i=0; i < num_verts; ++i) {\n               float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;\n\n               if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {\n                  float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;\n\n                  float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);\n                  if (dist2 < min_dist*min_dist)\n                     min_dist = (float) STBTT_sqrt(dist2);\n\n                  // coarse culling against bbox\n                  //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&\n                  //    sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)\n                  dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];\n                  STBTT_assert(i != 0);\n                  if (dist < min_dist) {\n                     // check position along line\n                     // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0)\n                     // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy)\n                     float dx = x1-x0, dy = y1-y0;\n                     float px = x0-sx, py = y0-sy;\n                     // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy\n                     // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve\n                     float t = -(px*dx + py*dy) / (dx*dx + dy*dy);\n                     if (t >= 0.0f && t <= 1.0f)\n                        min_dist = dist;\n                  }\n               } else if (verts[i].type == STBTT_vcurve) {\n                  float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y;\n                  float x1 = verts[i  ].cx*scale_x, y1 = verts[i  ].cy*scale_y;\n                  float box_x0 = STBTT_min(STBTT_min(x0,x1),x2);\n                  float box_y0 = STBTT_min(STBTT_min(y0,y1),y2);\n                  float box_x1 = STBTT_max(STBTT_max(x0,x1),x2);\n                  float box_y1 = STBTT_max(STBTT_max(y0,y1),y2);\n                  // coarse culling against bbox to avoid computing cubic unnecessarily\n                  if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) {\n                     int num=0;\n                     float ax = x1-x0, ay = y1-y0;\n                     float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;\n                     float mx = x0 - sx, my = y0 - sy;\n                     float res[3] = {0.f,0.f,0.f};\n                     float px,py,t,it,dist2;\n                     float a_inv = precompute[i];\n                     if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula\n                        float a = 3*(ax*bx + ay*by);\n                        float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);\n                        float c = mx*ax+my*ay;\n                        if (a == 0.0) { // if a is 0, it's linear\n                           if (b != 0.0) {\n                              res[num++] = -c/b;\n                           }\n                        } else {\n                           float discriminant = b*b - 4*a*c;\n                           if (discriminant < 0)\n                              num = 0;\n                           else {\n                              float root = (float) STBTT_sqrt(discriminant);\n                              res[0] = (-b - root)/(2*a);\n                              res[1] = (-b + root)/(2*a);\n                              num = 2; // don't bother distinguishing 1-solution case, as code below will still work\n                           }\n                        }\n                     } else {\n                        float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point\n                        float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv;\n                        float d = (mx*ax+my*ay) * a_inv;\n                        num = stbtt__solve_cubic(b, c, d, res);\n                     }\n                     dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);\n                     if (dist2 < min_dist*min_dist)\n                        min_dist = (float) STBTT_sqrt(dist2);\n\n                     if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {\n                        t = res[0], it = 1.0f - t;\n                        px = it*it*x0 + 2*t*it*x1 + t*t*x2;\n                        py = it*it*y0 + 2*t*it*y1 + t*t*y2;\n                        dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);\n                        if (dist2 < min_dist * min_dist)\n                           min_dist = (float) STBTT_sqrt(dist2);\n                     }\n                     if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) {\n                        t = res[1], it = 1.0f - t;\n                        px = it*it*x0 + 2*t*it*x1 + t*t*x2;\n                        py = it*it*y0 + 2*t*it*y1 + t*t*y2;\n                        dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);\n                        if (dist2 < min_dist * min_dist)\n                           min_dist = (float) STBTT_sqrt(dist2);\n                     }\n                     if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) {\n                        t = res[2], it = 1.0f - t;\n                        px = it*it*x0 + 2*t*it*x1 + t*t*x2;\n                        py = it*it*y0 + 2*t*it*y1 + t*t*y2;\n                        dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);\n                        if (dist2 < min_dist * min_dist)\n                           min_dist = (float) STBTT_sqrt(dist2);\n                     }\n                  }\n               }\n            }\n            if (winding == 0)\n               min_dist = -min_dist;  // if outside the shape, value is negative\n            val = onedge_value + pixel_dist_scale * min_dist;\n            if (val < 0)\n               val = 0;\n            else if (val > 255)\n               val = 255;\n            data[(y-iy0)*w+(x-ix0)] = (unsigned char) val;\n         }\n      }\n      STBTT_free(precompute, info->userdata);\n      STBTT_free(verts, info->userdata);\n   }\n   return data;\n}\n\nSTBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)\n{\n   return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff);\n}\n\nSTBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)\n{\n   STBTT_free(bitmap, userdata);\n}\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// font name matching -- recommended not to use this\n//\n\n// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string\nstatic stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)\n{\n   stbtt_int32 i=0;\n\n   // convert utf16 to utf8 and compare the results while converting\n   while (len2) {\n      stbtt_uint16 ch = s2[0]*256 + s2[1];\n      if (ch < 0x80) {\n         if (i >= len1) return -1;\n         if (s1[i++] != ch) return -1;\n      } else if (ch < 0x800) {\n         if (i+1 >= len1) return -1;\n         if (s1[i++] != 0xc0 + (ch >> 6)) return -1;\n         if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;\n      } else if (ch >= 0xd800 && ch < 0xdc00) {\n         stbtt_uint32 c;\n         stbtt_uint16 ch2 = s2[2]*256 + s2[3];\n         if (i+3 >= len1) return -1;\n         c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;\n         if (s1[i++] != 0xf0 + (c >> 18)) return -1;\n         if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;\n         if (s1[i++] != 0x80 + ((c >>  6) & 0x3f)) return -1;\n         if (s1[i++] != 0x80 + ((c      ) & 0x3f)) return -1;\n         s2 += 2; // plus another 2 below\n         len2 -= 2;\n      } else if (ch >= 0xdc00 && ch < 0xe000) {\n         return -1;\n      } else {\n         if (i+2 >= len1) return -1;\n         if (s1[i++] != 0xe0 + (ch >> 12)) return -1;\n         if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;\n         if (s1[i++] != 0x80 + ((ch     ) & 0x3f)) return -1;\n      }\n      s2 += 2;\n      len2 -= 2;\n   }\n   return i;\n}\n\nstatic int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)\n{\n   return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);\n}\n\n// returns results in whatever encoding you request... but note that 2-byte encodings\n// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare\nSTBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)\n{\n   stbtt_int32 i,count,stringOffset;\n   stbtt_uint8 *fc = font->data;\n   stbtt_uint32 offset = font->fontstart;\n   stbtt_uint32 nm = stbtt__find_table(fc, offset, \"name\");\n   if (!nm) return NULL;\n\n   count = ttUSHORT(fc+nm+2);\n   stringOffset = nm + ttUSHORT(fc+nm+4);\n   for (i=0; i < count; ++i) {\n      stbtt_uint32 loc = nm + 6 + 12 * i;\n      if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)\n          && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {\n         *length = ttUSHORT(fc+loc+8);\n         return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));\n      }\n   }\n   return NULL;\n}\n\nstatic int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)\n{\n   stbtt_int32 i;\n   stbtt_int32 count = ttUSHORT(fc+nm+2);\n   stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);\n\n   for (i=0; i < count; ++i) {\n      stbtt_uint32 loc = nm + 6 + 12 * i;\n      stbtt_int32 id = ttUSHORT(fc+loc+6);\n      if (id == target_id) {\n         // find the encoding\n         stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);\n\n         // is this a Unicode encoding?\n         if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {\n            stbtt_int32 slen = ttUSHORT(fc+loc+8);\n            stbtt_int32 off = ttUSHORT(fc+loc+10);\n\n            // check if there's a prefix match\n            stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);\n            if (matchlen >= 0) {\n               // check for target_id+1 immediately following, with same encoding & language\n               if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) {\n                  slen = ttUSHORT(fc+loc+12+8);\n                  off = ttUSHORT(fc+loc+12+10);\n                  if (slen == 0) {\n                     if (matchlen == nlen)\n                        return 1;\n                  } else if (matchlen < nlen && name[matchlen] == ' ') {\n                     ++matchlen;\n                     if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))\n                        return 1;\n                  }\n               } else {\n                  // if nothing immediately following\n                  if (matchlen == nlen)\n                     return 1;\n               }\n            }\n         }\n\n         // @TODO handle other encodings\n      }\n   }\n   return 0;\n}\n\nstatic int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)\n{\n   stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);\n   stbtt_uint32 nm,hd;\n   if (!stbtt__isfont(fc+offset)) return 0;\n\n   // check italics/bold/underline flags in macStyle...\n   if (flags) {\n      hd = stbtt__find_table(fc, offset, \"head\");\n      if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;\n   }\n\n   nm = stbtt__find_table(fc, offset, \"name\");\n   if (!nm) return 0;\n\n   if (flags) {\n      // if we checked the macStyle flags, then just check the family and ignore the subfamily\n      if (stbtt__matchpair(fc, nm, name, nlen, 16, -1))  return 1;\n      if (stbtt__matchpair(fc, nm, name, nlen,  1, -1))  return 1;\n      if (stbtt__matchpair(fc, nm, name, nlen,  3, -1))  return 1;\n   } else {\n      if (stbtt__matchpair(fc, nm, name, nlen, 16, 17))  return 1;\n      if (stbtt__matchpair(fc, nm, name, nlen,  1,  2))  return 1;\n      if (stbtt__matchpair(fc, nm, name, nlen,  3, -1))  return 1;\n   }\n\n   return 0;\n}\n\nstatic int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags)\n{\n   stbtt_int32 i;\n   for (i=0;;++i) {\n      stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);\n      if (off < 0) return off;\n      if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))\n         return off;\n   }\n}\n\n#if defined(__GNUC__) || defined(__clang__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wcast-qual\"\n#endif\n\nSTBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,\n                                float pixel_height, unsigned char *pixels, int pw, int ph,\n                                int first_char, int num_chars, stbtt_bakedchar *chardata)\n{\n   return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);\n}\n\nSTBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)\n{\n   return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);\n}\n\nSTBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)\n{\n   return stbtt_GetNumberOfFonts_internal((unsigned char *) data);\n}\n\nSTBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)\n{\n   return stbtt_InitFont_internal(info, (unsigned char *) data, offset);\n}\n\nSTBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)\n{\n   return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags);\n}\n\nSTBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)\n{\n   return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2);\n}\n\n#if defined(__GNUC__) || defined(__clang__)\n#pragma GCC diagnostic pop\n#endif\n\n#endif // STB_TRUETYPE_IMPLEMENTATION\n\n\n// FULL VERSION HISTORY\n//\n//   1.25 (2021-07-11) many fixes\n//   1.24 (2020-02-05) fix warning\n//   1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)\n//   1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined\n//   1.21 (2019-02-25) fix warning\n//   1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()\n//   1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod\n//   1.18 (2018-01-29) add missing function\n//   1.17 (2017-07-23) make more arguments const; doc fix\n//   1.16 (2017-07-12) SDF support\n//   1.15 (2017-03-03) make more arguments const\n//   1.14 (2017-01-16) num-fonts-in-TTC function\n//   1.13 (2017-01-02) support OpenType fonts, certain Apple fonts\n//   1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual\n//   1.11 (2016-04-02) fix unused-variable warning\n//   1.10 (2016-04-02) allow user-defined fabs() replacement\n//                     fix memory leak if fontsize=0.0\n//                     fix warning from duplicate typedef\n//   1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges\n//   1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges\n//   1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;\n//                     allow PackFontRanges to pack and render in separate phases;\n//                     fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);\n//                     fixed an assert() bug in the new rasterizer\n//                     replace assert() with STBTT_assert() in new rasterizer\n//   1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine)\n//                     also more precise AA rasterizer, except if shapes overlap\n//                     remove need for STBTT_sort\n//   1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC\n//   1.04 (2015-04-15) typo in example\n//   1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes\n//   1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++\n//   1.01 (2014-12-08) fix subpixel position when oversampling to exactly match\n//                        non-oversampled; STBTT_POINT_SIZE for packed case only\n//   1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling\n//   0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg)\n//   0.9  (2014-08-07) support certain mac/iOS fonts without an MS platformID\n//   0.8b (2014-07-07) fix a warning\n//   0.8  (2014-05-25) fix a few more warnings\n//   0.7  (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back\n//   0.6c (2012-07-24) improve documentation\n//   0.6b (2012-07-20) fix a few more warnings\n//   0.6  (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,\n//                        stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty\n//   0.5  (2011-12-09) bugfixes:\n//                        subpixel glyph renderer computed wrong bounding box\n//                        first vertex of shape can be off-curve (FreeSans)\n//   0.4b (2011-12-03) fixed an error in the font baking example\n//   0.4  (2011-12-01) kerning, subpixel rendering (tor)\n//                    bugfixes for:\n//                        codepoint-to-glyph conversion using table fmt=12\n//                        codepoint-to-glyph conversion using table fmt=4\n//                        stbtt_GetBakedQuad with non-square texture (Zer)\n//                    updated Hello World! sample to use kerning and subpixel\n//                    fixed some warnings\n//   0.3  (2009-06-24) cmap fmt=12, compound shapes (MM)\n//                    userdata, malloc-from-userdata, non-zero fill (stb)\n//   0.2  (2009-03-11) Fix unsigned/signed char warnings\n//   0.1  (2009-03-09) First public release\n//\n\n/*\n------------------------------------------------------------------------------\nThis software is available under 2 licenses -- choose whichever you prefer.\n------------------------------------------------------------------------------\nALTERNATIVE A - MIT License\nCopyright (c) 2017 Sean Barrett\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n------------------------------------------------------------------------------\nALTERNATIVE B - Public Domain (www.unlicense.org)\nThis is free and unencumbered software released into the public domain.\nAnyone is free to copy, modify, publish, use, compile, sell, or distribute this\nsoftware, either in source code form or as a compiled binary, for any purpose,\ncommercial or non-commercial, and by any means.\nIn jurisdictions that recognize copyright laws, the author or authors of this\nsoftware dedicate any and all copyright interest in the software to the public\ndomain. We make this dedication for the benefit of the public at large and to\nthe detriment of our heirs and successors. We intend this dedication to be an\novert act of relinquishment in perpetuity of all present and future rights to\nthis software under copyright law.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\nACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n------------------------------------------------------------------------------\n*/\n"
  },
  {
    "path": "thirdparty/ios/ios.m",
    "content": "#import <Foundation/Foundation.h>\n\nvoid WrappedNSLog(const char *message,...) {\n    va_list args;\n    va_start(args, message);\n    NSLog(@\"%@\",[[NSString alloc] initWithFormat:[NSString stringWithUTF8String:message] arguments:args]);\n    va_end(args);\n}\n"
  },
  {
    "path": "thirdparty/libatomic_ops/LICENSE",
    "content": "MIT License (core library) / GPL-2.0 (gpl extension library)\n\nCopyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\nCopyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\nCopyright (c) 1999-2011 Hewlett-Packard Development Company, L.P.\nCopyright (c) 2005, 2007 Thiemo Seufer\nCopyright (c) 2007 by NEC LE-IT.  All rights reserved.\nCopyright (c) 2008-2022 Ivan Maidanski\nCopyright (c) 2009 Bradley Smith\nCopyright (c) 2009 by Takashi Yoshii.  All rights reserved.\n\n\nOur intent is to make it easy to use libatomic_ops, in both free and\nproprietary software.  Hence most of code (core library) that we expect to\nbe linked into a client application is covered by a MIT or MIT-style license.\n\nHowever, a few library routines (the gpl extension library) are covered by\nthe GNU General Public License.  These are put into a separate library,\nlibatomic_ops_gpl.a file.\n\nMost of the test code is covered by the GNU General Public License too.\n\n\nThe low-level (core) part of the library (libatomic_ops.a) is mostly covered\nby the MIT license:\n\n----------------------------------------\n\nCopyright (c) ...\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n--------------------------------\n\n\nSome files in the atomic_ops/sysdeps directory (part of core library) were\ninherited in part from the Boehm-Demers-Weiser conservative garbage collector,\nand are covered by its license, which is similar in spirit to MIT license:\n\n--------------------------------\n\nCopyright (c) ...\n\nTHIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\nOR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n\nPermission is hereby granted to use or copy this program\nfor any purpose, provided the above notices are retained on all copies.\nPermission to modify the code and to distribute modified code is granted,\nprovided the above notices are retained, and a notice that the code was\nmodified is included with the above copyright notice.\n\n----------------------------------\n\n\nA few files are covered by the GNU General Public License.  (See file\n\"COPYING\".)  This applies only to the test code and the atomic_ops_gpl\nportion of the library.  Thus, atomic_ops_gpl should generally not be\nlinked into proprietary code.  (This distinction was motivated by patent\nconsiderations.)\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/ao_version.h",
    "content": "/*\n * Copyright (c) 2003-2004 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2011-2018 Ivan Maidanski\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#ifndef AO_ATOMIC_OPS_H\n# error This file should not be included directly.\n#endif\n\n/* The policy regarding version numbers: development code has odd       */\n/* \"minor\" number (and \"micro\" part is 0); when development is finished */\n/* and a release is prepared, \"minor\" number is incremented (keeping    */\n/* \"micro\" number still zero), whenever a defect is fixed a new release */\n/* is prepared incrementing \"micro\" part to odd value (the most stable  */\n/* release has the biggest \"micro\" number).                             */\n\n/* The version here should match that in configure.ac and README.       */\n#define AO_VERSION_MAJOR 7\n#define AO_VERSION_MINOR 9\n#define AO_VERSION_MICRO 0 /* 7.9.0 */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/generalize-arithm.h",
    "content": "/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* char_compare_and_swap (based on fetch_compare_and_swap) */\n#if defined(AO_HAVE_char_fetch_compare_and_swap_full) \\\n    && !defined(AO_HAVE_char_compare_and_swap_full)\n  AO_INLINE int\n  AO_char_compare_and_swap_full(volatile unsigned/**/char *addr, unsigned/**/char old_val,\n                                 unsigned/**/char new_val)\n  {\n    return AO_char_fetch_compare_and_swap_full(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_char_compare_and_swap_full\n#endif\n\n#if defined(AO_HAVE_char_fetch_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_char_compare_and_swap_acquire)\n  AO_INLINE int\n  AO_char_compare_and_swap_acquire(volatile unsigned/**/char *addr, unsigned/**/char old_val,\n                                    unsigned/**/char new_val)\n  {\n    return AO_char_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_char_compare_and_swap_acquire\n#endif\n\n#if defined(AO_HAVE_char_fetch_compare_and_swap_release) \\\n    && !defined(AO_HAVE_char_compare_and_swap_release)\n  AO_INLINE int\n  AO_char_compare_and_swap_release(volatile unsigned/**/char *addr, unsigned/**/char old_val,\n                                    unsigned/**/char new_val)\n  {\n    return AO_char_fetch_compare_and_swap_release(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_char_compare_and_swap_release\n#endif\n\n#if defined(AO_HAVE_char_fetch_compare_and_swap_write) \\\n    && !defined(AO_HAVE_char_compare_and_swap_write)\n  AO_INLINE int\n  AO_char_compare_and_swap_write(volatile unsigned/**/char *addr, unsigned/**/char old_val,\n                                  unsigned/**/char new_val)\n  {\n    return AO_char_fetch_compare_and_swap_write(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_char_compare_and_swap_write\n#endif\n\n#if defined(AO_HAVE_char_fetch_compare_and_swap_read) \\\n    && !defined(AO_HAVE_char_compare_and_swap_read)\n  AO_INLINE int\n  AO_char_compare_and_swap_read(volatile unsigned/**/char *addr, unsigned/**/char old_val,\n                                 unsigned/**/char new_val)\n  {\n    return AO_char_fetch_compare_and_swap_read(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_char_compare_and_swap_read\n#endif\n\n#if defined(AO_HAVE_char_fetch_compare_and_swap) \\\n    && !defined(AO_HAVE_char_compare_and_swap)\n  AO_INLINE int\n  AO_char_compare_and_swap(volatile unsigned/**/char *addr, unsigned/**/char old_val,\n                            unsigned/**/char new_val)\n  {\n    return AO_char_fetch_compare_and_swap(addr, old_val, new_val) == old_val;\n  }\n# define AO_HAVE_char_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_char_fetch_compare_and_swap_release_write) \\\n    && !defined(AO_HAVE_char_compare_and_swap_release_write)\n  AO_INLINE int\n  AO_char_compare_and_swap_release_write(volatile unsigned/**/char *addr,\n                                          unsigned/**/char old_val, unsigned/**/char new_val)\n  {\n    return AO_char_fetch_compare_and_swap_release_write(addr, old_val,\n                                                         new_val) == old_val;\n  }\n# define AO_HAVE_char_compare_and_swap_release_write\n#endif\n\n#if defined(AO_HAVE_char_fetch_compare_and_swap_acquire_read) \\\n    && !defined(AO_HAVE_char_compare_and_swap_acquire_read)\n  AO_INLINE int\n  AO_char_compare_and_swap_acquire_read(volatile unsigned/**/char *addr,\n                                         unsigned/**/char old_val, unsigned/**/char new_val)\n  {\n    return AO_char_fetch_compare_and_swap_acquire_read(addr, old_val,\n                                                        new_val) == old_val;\n  }\n# define AO_HAVE_char_compare_and_swap_acquire_read\n#endif\n\n#if defined(AO_HAVE_char_fetch_compare_and_swap_dd_acquire_read) \\\n    && !defined(AO_HAVE_char_compare_and_swap_dd_acquire_read)\n  AO_INLINE int\n  AO_char_compare_and_swap_dd_acquire_read(volatile unsigned/**/char *addr,\n                                            unsigned/**/char old_val, unsigned/**/char new_val)\n  {\n    return AO_char_fetch_compare_and_swap_dd_acquire_read(addr, old_val,\n                                                           new_val) == old_val;\n  }\n# define AO_HAVE_char_compare_and_swap_dd_acquire_read\n#endif\n\n/* char_fetch_and_add */\n/* We first try to implement fetch_and_add variants in terms of the     */\n/* corresponding compare_and_swap variants to minimize adding barriers. */\n#if defined(AO_HAVE_char_compare_and_swap_full) \\\n    && !defined(AO_HAVE_char_fetch_and_add_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/char\n  AO_char_fetch_and_add_full(volatile unsigned/**/char *addr, unsigned/**/char incr)\n  {\n    unsigned/**/char old;\n\n    do\n      {\n        old = *(unsigned/**/char *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_char_compare_and_swap_full(addr, old,\n                                                           old + incr)));\n    return old;\n  }\n# define AO_HAVE_char_fetch_and_add_full\n#endif\n\n#if defined(AO_HAVE_char_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_char_fetch_and_add_acquire)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/char\n  AO_char_fetch_and_add_acquire(volatile unsigned/**/char *addr, unsigned/**/char incr)\n  {\n    unsigned/**/char old;\n\n    do\n      {\n        old = *(unsigned/**/char *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_char_compare_and_swap_acquire(addr, old,\n                                                              old + incr)));\n    return old;\n  }\n# define AO_HAVE_char_fetch_and_add_acquire\n#endif\n\n#if defined(AO_HAVE_char_compare_and_swap_release) \\\n    && !defined(AO_HAVE_char_fetch_and_add_release)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/char\n  AO_char_fetch_and_add_release(volatile unsigned/**/char *addr, unsigned/**/char incr)\n  {\n    unsigned/**/char old;\n\n    do\n      {\n        old = *(unsigned/**/char *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_char_compare_and_swap_release(addr, old,\n                                                              old + incr)));\n    return old;\n  }\n# define AO_HAVE_char_fetch_and_add_release\n#endif\n\n#if defined(AO_HAVE_char_compare_and_swap) \\\n    && !defined(AO_HAVE_char_fetch_and_add)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/char\n  AO_char_fetch_and_add(volatile unsigned/**/char *addr, unsigned/**/char incr)\n  {\n    unsigned/**/char old;\n\n    do\n      {\n        old = *(unsigned/**/char *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_char_compare_and_swap(addr, old,\n                                                      old + incr)));\n    return old;\n  }\n# define AO_HAVE_char_fetch_and_add\n#endif\n\n#if defined(AO_HAVE_char_fetch_and_add_full)\n# if !defined(AO_HAVE_char_fetch_and_add_release)\n#   define AO_char_fetch_and_add_release(addr, val) \\\n                                AO_char_fetch_and_add_full(addr, val)\n#   define AO_HAVE_char_fetch_and_add_release\n# endif\n# if !defined(AO_HAVE_char_fetch_and_add_acquire)\n#   define AO_char_fetch_and_add_acquire(addr, val) \\\n                                AO_char_fetch_and_add_full(addr, val)\n#   define AO_HAVE_char_fetch_and_add_acquire\n# endif\n# if !defined(AO_HAVE_char_fetch_and_add_write)\n#   define AO_char_fetch_and_add_write(addr, val) \\\n                                AO_char_fetch_and_add_full(addr, val)\n#   define AO_HAVE_char_fetch_and_add_write\n# endif\n# if !defined(AO_HAVE_char_fetch_and_add_read)\n#   define AO_char_fetch_and_add_read(addr, val) \\\n                                AO_char_fetch_and_add_full(addr, val)\n#   define AO_HAVE_char_fetch_and_add_read\n# endif\n#endif /* AO_HAVE_char_fetch_and_add_full */\n\n#if defined(AO_HAVE_char_fetch_and_add) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_fetch_and_add_acquire)\n  AO_INLINE unsigned/**/char\n  AO_char_fetch_and_add_acquire(volatile unsigned/**/char *addr, unsigned/**/char incr)\n  {\n    unsigned/**/char result = AO_char_fetch_and_add(addr, incr);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_char_fetch_and_add_acquire\n#endif\n#if defined(AO_HAVE_char_fetch_and_add) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_fetch_and_add_release)\n# define AO_char_fetch_and_add_release(addr, incr) \\\n                (AO_nop_full(), AO_char_fetch_and_add(addr, incr))\n# define AO_HAVE_char_fetch_and_add_release\n#endif\n\n#if !defined(AO_HAVE_char_fetch_and_add) \\\n    && defined(AO_HAVE_char_fetch_and_add_release)\n# define AO_char_fetch_and_add(addr, val) \\\n                                AO_char_fetch_and_add_release(addr, val)\n# define AO_HAVE_char_fetch_and_add\n#endif\n#if !defined(AO_HAVE_char_fetch_and_add) \\\n    && defined(AO_HAVE_char_fetch_and_add_acquire)\n# define AO_char_fetch_and_add(addr, val) \\\n                                AO_char_fetch_and_add_acquire(addr, val)\n# define AO_HAVE_char_fetch_and_add\n#endif\n#if !defined(AO_HAVE_char_fetch_and_add) \\\n    && defined(AO_HAVE_char_fetch_and_add_write)\n# define AO_char_fetch_and_add(addr, val) \\\n                                AO_char_fetch_and_add_write(addr, val)\n# define AO_HAVE_char_fetch_and_add\n#endif\n#if !defined(AO_HAVE_char_fetch_and_add) \\\n    && defined(AO_HAVE_char_fetch_and_add_read)\n# define AO_char_fetch_and_add(addr, val) \\\n                                AO_char_fetch_and_add_read(addr, val)\n# define AO_HAVE_char_fetch_and_add\n#endif\n\n#if defined(AO_HAVE_char_fetch_and_add_acquire) \\\n    && defined(AO_HAVE_nop_full) && !defined(AO_HAVE_char_fetch_and_add_full)\n# define AO_char_fetch_and_add_full(addr, val) \\\n                (AO_nop_full(), AO_char_fetch_and_add_acquire(addr, val))\n# define AO_HAVE_char_fetch_and_add_full\n#endif\n\n#if !defined(AO_HAVE_char_fetch_and_add_release_write) \\\n    && defined(AO_HAVE_char_fetch_and_add_write)\n# define AO_char_fetch_and_add_release_write(addr, val) \\\n                                AO_char_fetch_and_add_write(addr, val)\n# define AO_HAVE_char_fetch_and_add_release_write\n#endif\n#if !defined(AO_HAVE_char_fetch_and_add_release_write) \\\n    && defined(AO_HAVE_char_fetch_and_add_release)\n# define AO_char_fetch_and_add_release_write(addr, val) \\\n                                AO_char_fetch_and_add_release(addr, val)\n# define AO_HAVE_char_fetch_and_add_release_write\n#endif\n\n#if !defined(AO_HAVE_char_fetch_and_add_acquire_read) \\\n    && defined(AO_HAVE_char_fetch_and_add_read)\n# define AO_char_fetch_and_add_acquire_read(addr, val) \\\n                                AO_char_fetch_and_add_read(addr, val)\n# define AO_HAVE_char_fetch_and_add_acquire_read\n#endif\n#if !defined(AO_HAVE_char_fetch_and_add_acquire_read) \\\n    && defined(AO_HAVE_char_fetch_and_add_acquire)\n# define AO_char_fetch_and_add_acquire_read(addr, val) \\\n                                AO_char_fetch_and_add_acquire(addr, val)\n# define AO_HAVE_char_fetch_and_add_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_char_fetch_and_add_acquire_read)\n#   define AO_char_fetch_and_add_dd_acquire_read(addr, val) \\\n                                AO_char_fetch_and_add_acquire_read(addr, val)\n#   define AO_HAVE_char_fetch_and_add_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_char_fetch_and_add)\n#   define AO_char_fetch_and_add_dd_acquire_read(addr, val) \\\n                                AO_char_fetch_and_add(addr, val)\n#   define AO_HAVE_char_fetch_and_add_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* char_fetch_and_add1 */\n#if defined(AO_HAVE_char_fetch_and_add_full) \\\n    && !defined(AO_HAVE_char_fetch_and_add1_full)\n# define AO_char_fetch_and_add1_full(addr) \\\n                                AO_char_fetch_and_add_full(addr, 1)\n# define AO_HAVE_char_fetch_and_add1_full\n#endif\n#if defined(AO_HAVE_char_fetch_and_add_release) \\\n    && !defined(AO_HAVE_char_fetch_and_add1_release)\n# define AO_char_fetch_and_add1_release(addr) \\\n                                AO_char_fetch_and_add_release(addr, 1)\n# define AO_HAVE_char_fetch_and_add1_release\n#endif\n#if defined(AO_HAVE_char_fetch_and_add_acquire) \\\n    && !defined(AO_HAVE_char_fetch_and_add1_acquire)\n# define AO_char_fetch_and_add1_acquire(addr) \\\n                                AO_char_fetch_and_add_acquire(addr, 1)\n# define AO_HAVE_char_fetch_and_add1_acquire\n#endif\n#if defined(AO_HAVE_char_fetch_and_add_write) \\\n    && !defined(AO_HAVE_char_fetch_and_add1_write)\n# define AO_char_fetch_and_add1_write(addr) \\\n                                AO_char_fetch_and_add_write(addr, 1)\n# define AO_HAVE_char_fetch_and_add1_write\n#endif\n#if defined(AO_HAVE_char_fetch_and_add_read) \\\n    && !defined(AO_HAVE_char_fetch_and_add1_read)\n# define AO_char_fetch_and_add1_read(addr) \\\n                                AO_char_fetch_and_add_read(addr, 1)\n# define AO_HAVE_char_fetch_and_add1_read\n#endif\n#if defined(AO_HAVE_char_fetch_and_add_release_write) \\\n    && !defined(AO_HAVE_char_fetch_and_add1_release_write)\n# define AO_char_fetch_and_add1_release_write(addr) \\\n                                AO_char_fetch_and_add_release_write(addr, 1)\n# define AO_HAVE_char_fetch_and_add1_release_write\n#endif\n#if defined(AO_HAVE_char_fetch_and_add_acquire_read) \\\n    && !defined(AO_HAVE_char_fetch_and_add1_acquire_read)\n# define AO_char_fetch_and_add1_acquire_read(addr) \\\n                                AO_char_fetch_and_add_acquire_read(addr, 1)\n# define AO_HAVE_char_fetch_and_add1_acquire_read\n#endif\n#if defined(AO_HAVE_char_fetch_and_add) \\\n    && !defined(AO_HAVE_char_fetch_and_add1)\n# define AO_char_fetch_and_add1(addr) AO_char_fetch_and_add(addr, 1)\n# define AO_HAVE_char_fetch_and_add1\n#endif\n\n#if defined(AO_HAVE_char_fetch_and_add1_full)\n# if !defined(AO_HAVE_char_fetch_and_add1_release)\n#   define AO_char_fetch_and_add1_release(addr) \\\n                                AO_char_fetch_and_add1_full(addr)\n#   define AO_HAVE_char_fetch_and_add1_release\n# endif\n# if !defined(AO_HAVE_char_fetch_and_add1_acquire)\n#   define AO_char_fetch_and_add1_acquire(addr) \\\n                                AO_char_fetch_and_add1_full(addr)\n#   define AO_HAVE_char_fetch_and_add1_acquire\n# endif\n# if !defined(AO_HAVE_char_fetch_and_add1_write)\n#   define AO_char_fetch_and_add1_write(addr) \\\n                                AO_char_fetch_and_add1_full(addr)\n#   define AO_HAVE_char_fetch_and_add1_write\n# endif\n# if !defined(AO_HAVE_char_fetch_and_add1_read)\n#   define AO_char_fetch_and_add1_read(addr) \\\n                                AO_char_fetch_and_add1_full(addr)\n#   define AO_HAVE_char_fetch_and_add1_read\n# endif\n#endif /* AO_HAVE_char_fetch_and_add1_full */\n\n#if !defined(AO_HAVE_char_fetch_and_add1) \\\n    && defined(AO_HAVE_char_fetch_and_add1_release)\n# define AO_char_fetch_and_add1(addr) AO_char_fetch_and_add1_release(addr)\n# define AO_HAVE_char_fetch_and_add1\n#endif\n#if !defined(AO_HAVE_char_fetch_and_add1) \\\n    && defined(AO_HAVE_char_fetch_and_add1_acquire)\n# define AO_char_fetch_and_add1(addr) AO_char_fetch_and_add1_acquire(addr)\n# define AO_HAVE_char_fetch_and_add1\n#endif\n#if !defined(AO_HAVE_char_fetch_and_add1) \\\n    && defined(AO_HAVE_char_fetch_and_add1_write)\n# define AO_char_fetch_and_add1(addr) AO_char_fetch_and_add1_write(addr)\n# define AO_HAVE_char_fetch_and_add1\n#endif\n#if !defined(AO_HAVE_char_fetch_and_add1) \\\n    && defined(AO_HAVE_char_fetch_and_add1_read)\n# define AO_char_fetch_and_add1(addr) AO_char_fetch_and_add1_read(addr)\n# define AO_HAVE_char_fetch_and_add1\n#endif\n\n#if defined(AO_HAVE_char_fetch_and_add1_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_fetch_and_add1_full)\n# define AO_char_fetch_and_add1_full(addr) \\\n                        (AO_nop_full(), AO_char_fetch_and_add1_acquire(addr))\n# define AO_HAVE_char_fetch_and_add1_full\n#endif\n\n#if !defined(AO_HAVE_char_fetch_and_add1_release_write) \\\n    && defined(AO_HAVE_char_fetch_and_add1_write)\n# define AO_char_fetch_and_add1_release_write(addr) \\\n                                AO_char_fetch_and_add1_write(addr)\n# define AO_HAVE_char_fetch_and_add1_release_write\n#endif\n#if !defined(AO_HAVE_char_fetch_and_add1_release_write) \\\n    && defined(AO_HAVE_char_fetch_and_add1_release)\n# define AO_char_fetch_and_add1_release_write(addr) \\\n                                AO_char_fetch_and_add1_release(addr)\n# define AO_HAVE_char_fetch_and_add1_release_write\n#endif\n#if !defined(AO_HAVE_char_fetch_and_add1_acquire_read) \\\n    && defined(AO_HAVE_char_fetch_and_add1_read)\n# define AO_char_fetch_and_add1_acquire_read(addr) \\\n                                AO_char_fetch_and_add1_read(addr)\n# define AO_HAVE_char_fetch_and_add1_acquire_read\n#endif\n#if !defined(AO_HAVE_char_fetch_and_add1_acquire_read) \\\n    && defined(AO_HAVE_char_fetch_and_add1_acquire)\n# define AO_char_fetch_and_add1_acquire_read(addr) \\\n                                AO_char_fetch_and_add1_acquire(addr)\n# define AO_HAVE_char_fetch_and_add1_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_char_fetch_and_add1_acquire_read)\n#   define AO_char_fetch_and_add1_dd_acquire_read(addr) \\\n                                AO_char_fetch_and_add1_acquire_read(addr)\n#   define AO_HAVE_char_fetch_and_add1_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_char_fetch_and_add1)\n#   define AO_char_fetch_and_add1_dd_acquire_read(addr) \\\n                                AO_char_fetch_and_add1(addr)\n#   define AO_HAVE_char_fetch_and_add1_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* char_fetch_and_sub1 */\n#if defined(AO_HAVE_char_fetch_and_add_full) \\\n    && !defined(AO_HAVE_char_fetch_and_sub1_full)\n# define AO_char_fetch_and_sub1_full(addr) \\\n                AO_char_fetch_and_add_full(addr, (unsigned/**/char)(-1))\n# define AO_HAVE_char_fetch_and_sub1_full\n#endif\n#if defined(AO_HAVE_char_fetch_and_add_release) \\\n    && !defined(AO_HAVE_char_fetch_and_sub1_release)\n# define AO_char_fetch_and_sub1_release(addr) \\\n                AO_char_fetch_and_add_release(addr, (unsigned/**/char)(-1))\n# define AO_HAVE_char_fetch_and_sub1_release\n#endif\n#if defined(AO_HAVE_char_fetch_and_add_acquire) \\\n    && !defined(AO_HAVE_char_fetch_and_sub1_acquire)\n# define AO_char_fetch_and_sub1_acquire(addr) \\\n                AO_char_fetch_and_add_acquire(addr, (unsigned/**/char)(-1))\n# define AO_HAVE_char_fetch_and_sub1_acquire\n#endif\n#if defined(AO_HAVE_char_fetch_and_add_write) \\\n    && !defined(AO_HAVE_char_fetch_and_sub1_write)\n# define AO_char_fetch_and_sub1_write(addr) \\\n                AO_char_fetch_and_add_write(addr, (unsigned/**/char)(-1))\n# define AO_HAVE_char_fetch_and_sub1_write\n#endif\n#if defined(AO_HAVE_char_fetch_and_add_read) \\\n    && !defined(AO_HAVE_char_fetch_and_sub1_read)\n# define AO_char_fetch_and_sub1_read(addr) \\\n                AO_char_fetch_and_add_read(addr, (unsigned/**/char)(-1))\n# define AO_HAVE_char_fetch_and_sub1_read\n#endif\n#if defined(AO_HAVE_char_fetch_and_add_release_write) \\\n    && !defined(AO_HAVE_char_fetch_and_sub1_release_write)\n# define AO_char_fetch_and_sub1_release_write(addr) \\\n                AO_char_fetch_and_add_release_write(addr, (unsigned/**/char)(-1))\n# define AO_HAVE_char_fetch_and_sub1_release_write\n#endif\n#if defined(AO_HAVE_char_fetch_and_add_acquire_read) \\\n    && !defined(AO_HAVE_char_fetch_and_sub1_acquire_read)\n# define AO_char_fetch_and_sub1_acquire_read(addr) \\\n                AO_char_fetch_and_add_acquire_read(addr, (unsigned/**/char)(-1))\n# define AO_HAVE_char_fetch_and_sub1_acquire_read\n#endif\n#if defined(AO_HAVE_char_fetch_and_add) \\\n    && !defined(AO_HAVE_char_fetch_and_sub1)\n# define AO_char_fetch_and_sub1(addr) \\\n                AO_char_fetch_and_add(addr, (unsigned/**/char)(-1))\n# define AO_HAVE_char_fetch_and_sub1\n#endif\n\n#if defined(AO_HAVE_char_fetch_and_sub1_full)\n# if !defined(AO_HAVE_char_fetch_and_sub1_release)\n#   define AO_char_fetch_and_sub1_release(addr) \\\n                                AO_char_fetch_and_sub1_full(addr)\n#   define AO_HAVE_char_fetch_and_sub1_release\n# endif\n# if !defined(AO_HAVE_char_fetch_and_sub1_acquire)\n#   define AO_char_fetch_and_sub1_acquire(addr) \\\n                                AO_char_fetch_and_sub1_full(addr)\n#   define AO_HAVE_char_fetch_and_sub1_acquire\n# endif\n# if !defined(AO_HAVE_char_fetch_and_sub1_write)\n#   define AO_char_fetch_and_sub1_write(addr) \\\n                                AO_char_fetch_and_sub1_full(addr)\n#   define AO_HAVE_char_fetch_and_sub1_write\n# endif\n# if !defined(AO_HAVE_char_fetch_and_sub1_read)\n#   define AO_char_fetch_and_sub1_read(addr) \\\n                                AO_char_fetch_and_sub1_full(addr)\n#   define AO_HAVE_char_fetch_and_sub1_read\n# endif\n#endif /* AO_HAVE_char_fetch_and_sub1_full */\n\n#if !defined(AO_HAVE_char_fetch_and_sub1) \\\n    && defined(AO_HAVE_char_fetch_and_sub1_release)\n# define AO_char_fetch_and_sub1(addr) AO_char_fetch_and_sub1_release(addr)\n# define AO_HAVE_char_fetch_and_sub1\n#endif\n#if !defined(AO_HAVE_char_fetch_and_sub1) \\\n    && defined(AO_HAVE_char_fetch_and_sub1_acquire)\n# define AO_char_fetch_and_sub1(addr) AO_char_fetch_and_sub1_acquire(addr)\n# define AO_HAVE_char_fetch_and_sub1\n#endif\n#if !defined(AO_HAVE_char_fetch_and_sub1) \\\n    && defined(AO_HAVE_char_fetch_and_sub1_write)\n# define AO_char_fetch_and_sub1(addr) AO_char_fetch_and_sub1_write(addr)\n# define AO_HAVE_char_fetch_and_sub1\n#endif\n#if !defined(AO_HAVE_char_fetch_and_sub1) \\\n    && defined(AO_HAVE_char_fetch_and_sub1_read)\n# define AO_char_fetch_and_sub1(addr) AO_char_fetch_and_sub1_read(addr)\n# define AO_HAVE_char_fetch_and_sub1\n#endif\n\n#if defined(AO_HAVE_char_fetch_and_sub1_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_fetch_and_sub1_full)\n# define AO_char_fetch_and_sub1_full(addr) \\\n                        (AO_nop_full(), AO_char_fetch_and_sub1_acquire(addr))\n# define AO_HAVE_char_fetch_and_sub1_full\n#endif\n\n#if !defined(AO_HAVE_char_fetch_and_sub1_release_write) \\\n    && defined(AO_HAVE_char_fetch_and_sub1_write)\n# define AO_char_fetch_and_sub1_release_write(addr) \\\n                                AO_char_fetch_and_sub1_write(addr)\n# define AO_HAVE_char_fetch_and_sub1_release_write\n#endif\n#if !defined(AO_HAVE_char_fetch_and_sub1_release_write) \\\n    && defined(AO_HAVE_char_fetch_and_sub1_release)\n# define AO_char_fetch_and_sub1_release_write(addr) \\\n                                AO_char_fetch_and_sub1_release(addr)\n# define AO_HAVE_char_fetch_and_sub1_release_write\n#endif\n#if !defined(AO_HAVE_char_fetch_and_sub1_acquire_read) \\\n    && defined(AO_HAVE_char_fetch_and_sub1_read)\n# define AO_char_fetch_and_sub1_acquire_read(addr) \\\n                                AO_char_fetch_and_sub1_read(addr)\n# define AO_HAVE_char_fetch_and_sub1_acquire_read\n#endif\n#if !defined(AO_HAVE_char_fetch_and_sub1_acquire_read) \\\n    && defined(AO_HAVE_char_fetch_and_sub1_acquire)\n# define AO_char_fetch_and_sub1_acquire_read(addr) \\\n                                AO_char_fetch_and_sub1_acquire(addr)\n# define AO_HAVE_char_fetch_and_sub1_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_char_fetch_and_sub1_acquire_read)\n#   define AO_char_fetch_and_sub1_dd_acquire_read(addr) \\\n                                AO_char_fetch_and_sub1_acquire_read(addr)\n#   define AO_HAVE_char_fetch_and_sub1_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_char_fetch_and_sub1)\n#   define AO_char_fetch_and_sub1_dd_acquire_read(addr) \\\n                                AO_char_fetch_and_sub1(addr)\n#   define AO_HAVE_char_fetch_and_sub1_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* char_and */\n#if defined(AO_HAVE_char_compare_and_swap_full) \\\n    && !defined(AO_HAVE_char_and_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_char_and_full(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    unsigned/**/char old;\n\n    do\n      {\n        old = *(unsigned/**/char *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_char_compare_and_swap_full(addr, old,\n                                                           old & value)));\n  }\n# define AO_HAVE_char_and_full\n#endif\n\n#if defined(AO_HAVE_char_and_full)\n# if !defined(AO_HAVE_char_and_release)\n#   define AO_char_and_release(addr, val) AO_char_and_full(addr, val)\n#   define AO_HAVE_char_and_release\n# endif\n# if !defined(AO_HAVE_char_and_acquire)\n#   define AO_char_and_acquire(addr, val) AO_char_and_full(addr, val)\n#   define AO_HAVE_char_and_acquire\n# endif\n# if !defined(AO_HAVE_char_and_write)\n#   define AO_char_and_write(addr, val) AO_char_and_full(addr, val)\n#   define AO_HAVE_char_and_write\n# endif\n# if !defined(AO_HAVE_char_and_read)\n#   define AO_char_and_read(addr, val) AO_char_and_full(addr, val)\n#   define AO_HAVE_char_and_read\n# endif\n#endif /* AO_HAVE_char_and_full */\n\n#if !defined(AO_HAVE_char_and) && defined(AO_HAVE_char_and_release)\n# define AO_char_and(addr, val) AO_char_and_release(addr, val)\n# define AO_HAVE_char_and\n#endif\n#if !defined(AO_HAVE_char_and) && defined(AO_HAVE_char_and_acquire)\n# define AO_char_and(addr, val) AO_char_and_acquire(addr, val)\n# define AO_HAVE_char_and\n#endif\n#if !defined(AO_HAVE_char_and) && defined(AO_HAVE_char_and_write)\n# define AO_char_and(addr, val) AO_char_and_write(addr, val)\n# define AO_HAVE_char_and\n#endif\n#if !defined(AO_HAVE_char_and) && defined(AO_HAVE_char_and_read)\n# define AO_char_and(addr, val) AO_char_and_read(addr, val)\n# define AO_HAVE_char_and\n#endif\n\n#if defined(AO_HAVE_char_and_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_and_full)\n# define AO_char_and_full(addr, val) \\\n                        (AO_nop_full(), AO_char_and_acquire(addr, val))\n# define AO_HAVE_char_and_full\n#endif\n\n#if !defined(AO_HAVE_char_and_release_write) \\\n    && defined(AO_HAVE_char_and_write)\n# define AO_char_and_release_write(addr, val) AO_char_and_write(addr, val)\n# define AO_HAVE_char_and_release_write\n#endif\n#if !defined(AO_HAVE_char_and_release_write) \\\n    && defined(AO_HAVE_char_and_release)\n# define AO_char_and_release_write(addr, val) AO_char_and_release(addr, val)\n# define AO_HAVE_char_and_release_write\n#endif\n#if !defined(AO_HAVE_char_and_acquire_read) \\\n    && defined(AO_HAVE_char_and_read)\n# define AO_char_and_acquire_read(addr, val) AO_char_and_read(addr, val)\n# define AO_HAVE_char_and_acquire_read\n#endif\n#if !defined(AO_HAVE_char_and_acquire_read) \\\n    && defined(AO_HAVE_char_and_acquire)\n# define AO_char_and_acquire_read(addr, val) AO_char_and_acquire(addr, val)\n# define AO_HAVE_char_and_acquire_read\n#endif\n\n/* char_or */\n#if defined(AO_HAVE_char_compare_and_swap_full) \\\n    && !defined(AO_HAVE_char_or_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_char_or_full(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    unsigned/**/char old;\n\n    do\n      {\n        old = *(unsigned/**/char *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_char_compare_and_swap_full(addr, old,\n                                                           old | value)));\n  }\n# define AO_HAVE_char_or_full\n#endif\n\n#if defined(AO_HAVE_char_or_full)\n# if !defined(AO_HAVE_char_or_release)\n#   define AO_char_or_release(addr, val) AO_char_or_full(addr, val)\n#   define AO_HAVE_char_or_release\n# endif\n# if !defined(AO_HAVE_char_or_acquire)\n#   define AO_char_or_acquire(addr, val) AO_char_or_full(addr, val)\n#   define AO_HAVE_char_or_acquire\n# endif\n# if !defined(AO_HAVE_char_or_write)\n#   define AO_char_or_write(addr, val) AO_char_or_full(addr, val)\n#   define AO_HAVE_char_or_write\n# endif\n# if !defined(AO_HAVE_char_or_read)\n#   define AO_char_or_read(addr, val) AO_char_or_full(addr, val)\n#   define AO_HAVE_char_or_read\n# endif\n#endif /* AO_HAVE_char_or_full */\n\n#if !defined(AO_HAVE_char_or) && defined(AO_HAVE_char_or_release)\n# define AO_char_or(addr, val) AO_char_or_release(addr, val)\n# define AO_HAVE_char_or\n#endif\n#if !defined(AO_HAVE_char_or) && defined(AO_HAVE_char_or_acquire)\n# define AO_char_or(addr, val) AO_char_or_acquire(addr, val)\n# define AO_HAVE_char_or\n#endif\n#if !defined(AO_HAVE_char_or) && defined(AO_HAVE_char_or_write)\n# define AO_char_or(addr, val) AO_char_or_write(addr, val)\n# define AO_HAVE_char_or\n#endif\n#if !defined(AO_HAVE_char_or) && defined(AO_HAVE_char_or_read)\n# define AO_char_or(addr, val) AO_char_or_read(addr, val)\n# define AO_HAVE_char_or\n#endif\n\n#if defined(AO_HAVE_char_or_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_or_full)\n# define AO_char_or_full(addr, val) \\\n                        (AO_nop_full(), AO_char_or_acquire(addr, val))\n# define AO_HAVE_char_or_full\n#endif\n\n#if !defined(AO_HAVE_char_or_release_write) \\\n    && defined(AO_HAVE_char_or_write)\n# define AO_char_or_release_write(addr, val) AO_char_or_write(addr, val)\n# define AO_HAVE_char_or_release_write\n#endif\n#if !defined(AO_HAVE_char_or_release_write) \\\n    && defined(AO_HAVE_char_or_release)\n# define AO_char_or_release_write(addr, val) AO_char_or_release(addr, val)\n# define AO_HAVE_char_or_release_write\n#endif\n#if !defined(AO_HAVE_char_or_acquire_read) && defined(AO_HAVE_char_or_read)\n# define AO_char_or_acquire_read(addr, val) AO_char_or_read(addr, val)\n# define AO_HAVE_char_or_acquire_read\n#endif\n#if !defined(AO_HAVE_char_or_acquire_read) \\\n    && defined(AO_HAVE_char_or_acquire)\n# define AO_char_or_acquire_read(addr, val) AO_char_or_acquire(addr, val)\n# define AO_HAVE_char_or_acquire_read\n#endif\n\n/* char_xor */\n#if defined(AO_HAVE_char_compare_and_swap_full) \\\n    && !defined(AO_HAVE_char_xor_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_char_xor_full(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    unsigned/**/char old;\n\n    do\n      {\n        old = *(unsigned/**/char *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_char_compare_and_swap_full(addr, old,\n                                                           old ^ value)));\n  }\n# define AO_HAVE_char_xor_full\n#endif\n\n#if defined(AO_HAVE_char_xor_full)\n# if !defined(AO_HAVE_char_xor_release)\n#   define AO_char_xor_release(addr, val) AO_char_xor_full(addr, val)\n#   define AO_HAVE_char_xor_release\n# endif\n# if !defined(AO_HAVE_char_xor_acquire)\n#   define AO_char_xor_acquire(addr, val) AO_char_xor_full(addr, val)\n#   define AO_HAVE_char_xor_acquire\n# endif\n# if !defined(AO_HAVE_char_xor_write)\n#   define AO_char_xor_write(addr, val) AO_char_xor_full(addr, val)\n#   define AO_HAVE_char_xor_write\n# endif\n# if !defined(AO_HAVE_char_xor_read)\n#   define AO_char_xor_read(addr, val) AO_char_xor_full(addr, val)\n#   define AO_HAVE_char_xor_read\n# endif\n#endif /* AO_HAVE_char_xor_full */\n\n#if !defined(AO_HAVE_char_xor) && defined(AO_HAVE_char_xor_release)\n# define AO_char_xor(addr, val) AO_char_xor_release(addr, val)\n# define AO_HAVE_char_xor\n#endif\n#if !defined(AO_HAVE_char_xor) && defined(AO_HAVE_char_xor_acquire)\n# define AO_char_xor(addr, val) AO_char_xor_acquire(addr, val)\n# define AO_HAVE_char_xor\n#endif\n#if !defined(AO_HAVE_char_xor) && defined(AO_HAVE_char_xor_write)\n# define AO_char_xor(addr, val) AO_char_xor_write(addr, val)\n# define AO_HAVE_char_xor\n#endif\n#if !defined(AO_HAVE_char_xor) && defined(AO_HAVE_char_xor_read)\n# define AO_char_xor(addr, val) AO_char_xor_read(addr, val)\n# define AO_HAVE_char_xor\n#endif\n\n#if defined(AO_HAVE_char_xor_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_xor_full)\n# define AO_char_xor_full(addr, val) \\\n                        (AO_nop_full(), AO_char_xor_acquire(addr, val))\n# define AO_HAVE_char_xor_full\n#endif\n\n#if !defined(AO_HAVE_char_xor_release_write) \\\n    && defined(AO_HAVE_char_xor_write)\n# define AO_char_xor_release_write(addr, val) AO_char_xor_write(addr, val)\n# define AO_HAVE_char_xor_release_write\n#endif\n#if !defined(AO_HAVE_char_xor_release_write) \\\n    && defined(AO_HAVE_char_xor_release)\n# define AO_char_xor_release_write(addr, val) AO_char_xor_release(addr, val)\n# define AO_HAVE_char_xor_release_write\n#endif\n#if !defined(AO_HAVE_char_xor_acquire_read) \\\n    && defined(AO_HAVE_char_xor_read)\n# define AO_char_xor_acquire_read(addr, val) AO_char_xor_read(addr, val)\n# define AO_HAVE_char_xor_acquire_read\n#endif\n#if !defined(AO_HAVE_char_xor_acquire_read) \\\n    && defined(AO_HAVE_char_xor_acquire)\n# define AO_char_xor_acquire_read(addr, val) AO_char_xor_acquire(addr, val)\n# define AO_HAVE_char_xor_acquire_read\n#endif\n\n/* char_and/or/xor_dd_acquire_read are meaningless.    */\n/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* short_compare_and_swap (based on fetch_compare_and_swap) */\n#if defined(AO_HAVE_short_fetch_compare_and_swap_full) \\\n    && !defined(AO_HAVE_short_compare_and_swap_full)\n  AO_INLINE int\n  AO_short_compare_and_swap_full(volatile unsigned/**/short *addr, unsigned/**/short old_val,\n                                 unsigned/**/short new_val)\n  {\n    return AO_short_fetch_compare_and_swap_full(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_short_compare_and_swap_full\n#endif\n\n#if defined(AO_HAVE_short_fetch_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_short_compare_and_swap_acquire)\n  AO_INLINE int\n  AO_short_compare_and_swap_acquire(volatile unsigned/**/short *addr, unsigned/**/short old_val,\n                                    unsigned/**/short new_val)\n  {\n    return AO_short_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_short_compare_and_swap_acquire\n#endif\n\n#if defined(AO_HAVE_short_fetch_compare_and_swap_release) \\\n    && !defined(AO_HAVE_short_compare_and_swap_release)\n  AO_INLINE int\n  AO_short_compare_and_swap_release(volatile unsigned/**/short *addr, unsigned/**/short old_val,\n                                    unsigned/**/short new_val)\n  {\n    return AO_short_fetch_compare_and_swap_release(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_short_compare_and_swap_release\n#endif\n\n#if defined(AO_HAVE_short_fetch_compare_and_swap_write) \\\n    && !defined(AO_HAVE_short_compare_and_swap_write)\n  AO_INLINE int\n  AO_short_compare_and_swap_write(volatile unsigned/**/short *addr, unsigned/**/short old_val,\n                                  unsigned/**/short new_val)\n  {\n    return AO_short_fetch_compare_and_swap_write(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_short_compare_and_swap_write\n#endif\n\n#if defined(AO_HAVE_short_fetch_compare_and_swap_read) \\\n    && !defined(AO_HAVE_short_compare_and_swap_read)\n  AO_INLINE int\n  AO_short_compare_and_swap_read(volatile unsigned/**/short *addr, unsigned/**/short old_val,\n                                 unsigned/**/short new_val)\n  {\n    return AO_short_fetch_compare_and_swap_read(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_short_compare_and_swap_read\n#endif\n\n#if defined(AO_HAVE_short_fetch_compare_and_swap) \\\n    && !defined(AO_HAVE_short_compare_and_swap)\n  AO_INLINE int\n  AO_short_compare_and_swap(volatile unsigned/**/short *addr, unsigned/**/short old_val,\n                            unsigned/**/short new_val)\n  {\n    return AO_short_fetch_compare_and_swap(addr, old_val, new_val) == old_val;\n  }\n# define AO_HAVE_short_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_short_fetch_compare_and_swap_release_write) \\\n    && !defined(AO_HAVE_short_compare_and_swap_release_write)\n  AO_INLINE int\n  AO_short_compare_and_swap_release_write(volatile unsigned/**/short *addr,\n                                          unsigned/**/short old_val, unsigned/**/short new_val)\n  {\n    return AO_short_fetch_compare_and_swap_release_write(addr, old_val,\n                                                         new_val) == old_val;\n  }\n# define AO_HAVE_short_compare_and_swap_release_write\n#endif\n\n#if defined(AO_HAVE_short_fetch_compare_and_swap_acquire_read) \\\n    && !defined(AO_HAVE_short_compare_and_swap_acquire_read)\n  AO_INLINE int\n  AO_short_compare_and_swap_acquire_read(volatile unsigned/**/short *addr,\n                                         unsigned/**/short old_val, unsigned/**/short new_val)\n  {\n    return AO_short_fetch_compare_and_swap_acquire_read(addr, old_val,\n                                                        new_val) == old_val;\n  }\n# define AO_HAVE_short_compare_and_swap_acquire_read\n#endif\n\n#if defined(AO_HAVE_short_fetch_compare_and_swap_dd_acquire_read) \\\n    && !defined(AO_HAVE_short_compare_and_swap_dd_acquire_read)\n  AO_INLINE int\n  AO_short_compare_and_swap_dd_acquire_read(volatile unsigned/**/short *addr,\n                                            unsigned/**/short old_val, unsigned/**/short new_val)\n  {\n    return AO_short_fetch_compare_and_swap_dd_acquire_read(addr, old_val,\n                                                           new_val) == old_val;\n  }\n# define AO_HAVE_short_compare_and_swap_dd_acquire_read\n#endif\n\n/* short_fetch_and_add */\n/* We first try to implement fetch_and_add variants in terms of the     */\n/* corresponding compare_and_swap variants to minimize adding barriers. */\n#if defined(AO_HAVE_short_compare_and_swap_full) \\\n    && !defined(AO_HAVE_short_fetch_and_add_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/short\n  AO_short_fetch_and_add_full(volatile unsigned/**/short *addr, unsigned/**/short incr)\n  {\n    unsigned/**/short old;\n\n    do\n      {\n        old = *(unsigned/**/short *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_short_compare_and_swap_full(addr, old,\n                                                           old + incr)));\n    return old;\n  }\n# define AO_HAVE_short_fetch_and_add_full\n#endif\n\n#if defined(AO_HAVE_short_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_short_fetch_and_add_acquire)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/short\n  AO_short_fetch_and_add_acquire(volatile unsigned/**/short *addr, unsigned/**/short incr)\n  {\n    unsigned/**/short old;\n\n    do\n      {\n        old = *(unsigned/**/short *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_short_compare_and_swap_acquire(addr, old,\n                                                              old + incr)));\n    return old;\n  }\n# define AO_HAVE_short_fetch_and_add_acquire\n#endif\n\n#if defined(AO_HAVE_short_compare_and_swap_release) \\\n    && !defined(AO_HAVE_short_fetch_and_add_release)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/short\n  AO_short_fetch_and_add_release(volatile unsigned/**/short *addr, unsigned/**/short incr)\n  {\n    unsigned/**/short old;\n\n    do\n      {\n        old = *(unsigned/**/short *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_short_compare_and_swap_release(addr, old,\n                                                              old + incr)));\n    return old;\n  }\n# define AO_HAVE_short_fetch_and_add_release\n#endif\n\n#if defined(AO_HAVE_short_compare_and_swap) \\\n    && !defined(AO_HAVE_short_fetch_and_add)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/short\n  AO_short_fetch_and_add(volatile unsigned/**/short *addr, unsigned/**/short incr)\n  {\n    unsigned/**/short old;\n\n    do\n      {\n        old = *(unsigned/**/short *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_short_compare_and_swap(addr, old,\n                                                      old + incr)));\n    return old;\n  }\n# define AO_HAVE_short_fetch_and_add\n#endif\n\n#if defined(AO_HAVE_short_fetch_and_add_full)\n# if !defined(AO_HAVE_short_fetch_and_add_release)\n#   define AO_short_fetch_and_add_release(addr, val) \\\n                                AO_short_fetch_and_add_full(addr, val)\n#   define AO_HAVE_short_fetch_and_add_release\n# endif\n# if !defined(AO_HAVE_short_fetch_and_add_acquire)\n#   define AO_short_fetch_and_add_acquire(addr, val) \\\n                                AO_short_fetch_and_add_full(addr, val)\n#   define AO_HAVE_short_fetch_and_add_acquire\n# endif\n# if !defined(AO_HAVE_short_fetch_and_add_write)\n#   define AO_short_fetch_and_add_write(addr, val) \\\n                                AO_short_fetch_and_add_full(addr, val)\n#   define AO_HAVE_short_fetch_and_add_write\n# endif\n# if !defined(AO_HAVE_short_fetch_and_add_read)\n#   define AO_short_fetch_and_add_read(addr, val) \\\n                                AO_short_fetch_and_add_full(addr, val)\n#   define AO_HAVE_short_fetch_and_add_read\n# endif\n#endif /* AO_HAVE_short_fetch_and_add_full */\n\n#if defined(AO_HAVE_short_fetch_and_add) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_fetch_and_add_acquire)\n  AO_INLINE unsigned/**/short\n  AO_short_fetch_and_add_acquire(volatile unsigned/**/short *addr, unsigned/**/short incr)\n  {\n    unsigned/**/short result = AO_short_fetch_and_add(addr, incr);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_short_fetch_and_add_acquire\n#endif\n#if defined(AO_HAVE_short_fetch_and_add) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_fetch_and_add_release)\n# define AO_short_fetch_and_add_release(addr, incr) \\\n                (AO_nop_full(), AO_short_fetch_and_add(addr, incr))\n# define AO_HAVE_short_fetch_and_add_release\n#endif\n\n#if !defined(AO_HAVE_short_fetch_and_add) \\\n    && defined(AO_HAVE_short_fetch_and_add_release)\n# define AO_short_fetch_and_add(addr, val) \\\n                                AO_short_fetch_and_add_release(addr, val)\n# define AO_HAVE_short_fetch_and_add\n#endif\n#if !defined(AO_HAVE_short_fetch_and_add) \\\n    && defined(AO_HAVE_short_fetch_and_add_acquire)\n# define AO_short_fetch_and_add(addr, val) \\\n                                AO_short_fetch_and_add_acquire(addr, val)\n# define AO_HAVE_short_fetch_and_add\n#endif\n#if !defined(AO_HAVE_short_fetch_and_add) \\\n    && defined(AO_HAVE_short_fetch_and_add_write)\n# define AO_short_fetch_and_add(addr, val) \\\n                                AO_short_fetch_and_add_write(addr, val)\n# define AO_HAVE_short_fetch_and_add\n#endif\n#if !defined(AO_HAVE_short_fetch_and_add) \\\n    && defined(AO_HAVE_short_fetch_and_add_read)\n# define AO_short_fetch_and_add(addr, val) \\\n                                AO_short_fetch_and_add_read(addr, val)\n# define AO_HAVE_short_fetch_and_add\n#endif\n\n#if defined(AO_HAVE_short_fetch_and_add_acquire) \\\n    && defined(AO_HAVE_nop_full) && !defined(AO_HAVE_short_fetch_and_add_full)\n# define AO_short_fetch_and_add_full(addr, val) \\\n                (AO_nop_full(), AO_short_fetch_and_add_acquire(addr, val))\n# define AO_HAVE_short_fetch_and_add_full\n#endif\n\n#if !defined(AO_HAVE_short_fetch_and_add_release_write) \\\n    && defined(AO_HAVE_short_fetch_and_add_write)\n# define AO_short_fetch_and_add_release_write(addr, val) \\\n                                AO_short_fetch_and_add_write(addr, val)\n# define AO_HAVE_short_fetch_and_add_release_write\n#endif\n#if !defined(AO_HAVE_short_fetch_and_add_release_write) \\\n    && defined(AO_HAVE_short_fetch_and_add_release)\n# define AO_short_fetch_and_add_release_write(addr, val) \\\n                                AO_short_fetch_and_add_release(addr, val)\n# define AO_HAVE_short_fetch_and_add_release_write\n#endif\n\n#if !defined(AO_HAVE_short_fetch_and_add_acquire_read) \\\n    && defined(AO_HAVE_short_fetch_and_add_read)\n# define AO_short_fetch_and_add_acquire_read(addr, val) \\\n                                AO_short_fetch_and_add_read(addr, val)\n# define AO_HAVE_short_fetch_and_add_acquire_read\n#endif\n#if !defined(AO_HAVE_short_fetch_and_add_acquire_read) \\\n    && defined(AO_HAVE_short_fetch_and_add_acquire)\n# define AO_short_fetch_and_add_acquire_read(addr, val) \\\n                                AO_short_fetch_and_add_acquire(addr, val)\n# define AO_HAVE_short_fetch_and_add_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_short_fetch_and_add_acquire_read)\n#   define AO_short_fetch_and_add_dd_acquire_read(addr, val) \\\n                                AO_short_fetch_and_add_acquire_read(addr, val)\n#   define AO_HAVE_short_fetch_and_add_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_short_fetch_and_add)\n#   define AO_short_fetch_and_add_dd_acquire_read(addr, val) \\\n                                AO_short_fetch_and_add(addr, val)\n#   define AO_HAVE_short_fetch_and_add_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* short_fetch_and_add1 */\n#if defined(AO_HAVE_short_fetch_and_add_full) \\\n    && !defined(AO_HAVE_short_fetch_and_add1_full)\n# define AO_short_fetch_and_add1_full(addr) \\\n                                AO_short_fetch_and_add_full(addr, 1)\n# define AO_HAVE_short_fetch_and_add1_full\n#endif\n#if defined(AO_HAVE_short_fetch_and_add_release) \\\n    && !defined(AO_HAVE_short_fetch_and_add1_release)\n# define AO_short_fetch_and_add1_release(addr) \\\n                                AO_short_fetch_and_add_release(addr, 1)\n# define AO_HAVE_short_fetch_and_add1_release\n#endif\n#if defined(AO_HAVE_short_fetch_and_add_acquire) \\\n    && !defined(AO_HAVE_short_fetch_and_add1_acquire)\n# define AO_short_fetch_and_add1_acquire(addr) \\\n                                AO_short_fetch_and_add_acquire(addr, 1)\n# define AO_HAVE_short_fetch_and_add1_acquire\n#endif\n#if defined(AO_HAVE_short_fetch_and_add_write) \\\n    && !defined(AO_HAVE_short_fetch_and_add1_write)\n# define AO_short_fetch_and_add1_write(addr) \\\n                                AO_short_fetch_and_add_write(addr, 1)\n# define AO_HAVE_short_fetch_and_add1_write\n#endif\n#if defined(AO_HAVE_short_fetch_and_add_read) \\\n    && !defined(AO_HAVE_short_fetch_and_add1_read)\n# define AO_short_fetch_and_add1_read(addr) \\\n                                AO_short_fetch_and_add_read(addr, 1)\n# define AO_HAVE_short_fetch_and_add1_read\n#endif\n#if defined(AO_HAVE_short_fetch_and_add_release_write) \\\n    && !defined(AO_HAVE_short_fetch_and_add1_release_write)\n# define AO_short_fetch_and_add1_release_write(addr) \\\n                                AO_short_fetch_and_add_release_write(addr, 1)\n# define AO_HAVE_short_fetch_and_add1_release_write\n#endif\n#if defined(AO_HAVE_short_fetch_and_add_acquire_read) \\\n    && !defined(AO_HAVE_short_fetch_and_add1_acquire_read)\n# define AO_short_fetch_and_add1_acquire_read(addr) \\\n                                AO_short_fetch_and_add_acquire_read(addr, 1)\n# define AO_HAVE_short_fetch_and_add1_acquire_read\n#endif\n#if defined(AO_HAVE_short_fetch_and_add) \\\n    && !defined(AO_HAVE_short_fetch_and_add1)\n# define AO_short_fetch_and_add1(addr) AO_short_fetch_and_add(addr, 1)\n# define AO_HAVE_short_fetch_and_add1\n#endif\n\n#if defined(AO_HAVE_short_fetch_and_add1_full)\n# if !defined(AO_HAVE_short_fetch_and_add1_release)\n#   define AO_short_fetch_and_add1_release(addr) \\\n                                AO_short_fetch_and_add1_full(addr)\n#   define AO_HAVE_short_fetch_and_add1_release\n# endif\n# if !defined(AO_HAVE_short_fetch_and_add1_acquire)\n#   define AO_short_fetch_and_add1_acquire(addr) \\\n                                AO_short_fetch_and_add1_full(addr)\n#   define AO_HAVE_short_fetch_and_add1_acquire\n# endif\n# if !defined(AO_HAVE_short_fetch_and_add1_write)\n#   define AO_short_fetch_and_add1_write(addr) \\\n                                AO_short_fetch_and_add1_full(addr)\n#   define AO_HAVE_short_fetch_and_add1_write\n# endif\n# if !defined(AO_HAVE_short_fetch_and_add1_read)\n#   define AO_short_fetch_and_add1_read(addr) \\\n                                AO_short_fetch_and_add1_full(addr)\n#   define AO_HAVE_short_fetch_and_add1_read\n# endif\n#endif /* AO_HAVE_short_fetch_and_add1_full */\n\n#if !defined(AO_HAVE_short_fetch_and_add1) \\\n    && defined(AO_HAVE_short_fetch_and_add1_release)\n# define AO_short_fetch_and_add1(addr) AO_short_fetch_and_add1_release(addr)\n# define AO_HAVE_short_fetch_and_add1\n#endif\n#if !defined(AO_HAVE_short_fetch_and_add1) \\\n    && defined(AO_HAVE_short_fetch_and_add1_acquire)\n# define AO_short_fetch_and_add1(addr) AO_short_fetch_and_add1_acquire(addr)\n# define AO_HAVE_short_fetch_and_add1\n#endif\n#if !defined(AO_HAVE_short_fetch_and_add1) \\\n    && defined(AO_HAVE_short_fetch_and_add1_write)\n# define AO_short_fetch_and_add1(addr) AO_short_fetch_and_add1_write(addr)\n# define AO_HAVE_short_fetch_and_add1\n#endif\n#if !defined(AO_HAVE_short_fetch_and_add1) \\\n    && defined(AO_HAVE_short_fetch_and_add1_read)\n# define AO_short_fetch_and_add1(addr) AO_short_fetch_and_add1_read(addr)\n# define AO_HAVE_short_fetch_and_add1\n#endif\n\n#if defined(AO_HAVE_short_fetch_and_add1_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_fetch_and_add1_full)\n# define AO_short_fetch_and_add1_full(addr) \\\n                        (AO_nop_full(), AO_short_fetch_and_add1_acquire(addr))\n# define AO_HAVE_short_fetch_and_add1_full\n#endif\n\n#if !defined(AO_HAVE_short_fetch_and_add1_release_write) \\\n    && defined(AO_HAVE_short_fetch_and_add1_write)\n# define AO_short_fetch_and_add1_release_write(addr) \\\n                                AO_short_fetch_and_add1_write(addr)\n# define AO_HAVE_short_fetch_and_add1_release_write\n#endif\n#if !defined(AO_HAVE_short_fetch_and_add1_release_write) \\\n    && defined(AO_HAVE_short_fetch_and_add1_release)\n# define AO_short_fetch_and_add1_release_write(addr) \\\n                                AO_short_fetch_and_add1_release(addr)\n# define AO_HAVE_short_fetch_and_add1_release_write\n#endif\n#if !defined(AO_HAVE_short_fetch_and_add1_acquire_read) \\\n    && defined(AO_HAVE_short_fetch_and_add1_read)\n# define AO_short_fetch_and_add1_acquire_read(addr) \\\n                                AO_short_fetch_and_add1_read(addr)\n# define AO_HAVE_short_fetch_and_add1_acquire_read\n#endif\n#if !defined(AO_HAVE_short_fetch_and_add1_acquire_read) \\\n    && defined(AO_HAVE_short_fetch_and_add1_acquire)\n# define AO_short_fetch_and_add1_acquire_read(addr) \\\n                                AO_short_fetch_and_add1_acquire(addr)\n# define AO_HAVE_short_fetch_and_add1_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_short_fetch_and_add1_acquire_read)\n#   define AO_short_fetch_and_add1_dd_acquire_read(addr) \\\n                                AO_short_fetch_and_add1_acquire_read(addr)\n#   define AO_HAVE_short_fetch_and_add1_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_short_fetch_and_add1)\n#   define AO_short_fetch_and_add1_dd_acquire_read(addr) \\\n                                AO_short_fetch_and_add1(addr)\n#   define AO_HAVE_short_fetch_and_add1_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* short_fetch_and_sub1 */\n#if defined(AO_HAVE_short_fetch_and_add_full) \\\n    && !defined(AO_HAVE_short_fetch_and_sub1_full)\n# define AO_short_fetch_and_sub1_full(addr) \\\n                AO_short_fetch_and_add_full(addr, (unsigned/**/short)(-1))\n# define AO_HAVE_short_fetch_and_sub1_full\n#endif\n#if defined(AO_HAVE_short_fetch_and_add_release) \\\n    && !defined(AO_HAVE_short_fetch_and_sub1_release)\n# define AO_short_fetch_and_sub1_release(addr) \\\n                AO_short_fetch_and_add_release(addr, (unsigned/**/short)(-1))\n# define AO_HAVE_short_fetch_and_sub1_release\n#endif\n#if defined(AO_HAVE_short_fetch_and_add_acquire) \\\n    && !defined(AO_HAVE_short_fetch_and_sub1_acquire)\n# define AO_short_fetch_and_sub1_acquire(addr) \\\n                AO_short_fetch_and_add_acquire(addr, (unsigned/**/short)(-1))\n# define AO_HAVE_short_fetch_and_sub1_acquire\n#endif\n#if defined(AO_HAVE_short_fetch_and_add_write) \\\n    && !defined(AO_HAVE_short_fetch_and_sub1_write)\n# define AO_short_fetch_and_sub1_write(addr) \\\n                AO_short_fetch_and_add_write(addr, (unsigned/**/short)(-1))\n# define AO_HAVE_short_fetch_and_sub1_write\n#endif\n#if defined(AO_HAVE_short_fetch_and_add_read) \\\n    && !defined(AO_HAVE_short_fetch_and_sub1_read)\n# define AO_short_fetch_and_sub1_read(addr) \\\n                AO_short_fetch_and_add_read(addr, (unsigned/**/short)(-1))\n# define AO_HAVE_short_fetch_and_sub1_read\n#endif\n#if defined(AO_HAVE_short_fetch_and_add_release_write) \\\n    && !defined(AO_HAVE_short_fetch_and_sub1_release_write)\n# define AO_short_fetch_and_sub1_release_write(addr) \\\n                AO_short_fetch_and_add_release_write(addr, (unsigned/**/short)(-1))\n# define AO_HAVE_short_fetch_and_sub1_release_write\n#endif\n#if defined(AO_HAVE_short_fetch_and_add_acquire_read) \\\n    && !defined(AO_HAVE_short_fetch_and_sub1_acquire_read)\n# define AO_short_fetch_and_sub1_acquire_read(addr) \\\n                AO_short_fetch_and_add_acquire_read(addr, (unsigned/**/short)(-1))\n# define AO_HAVE_short_fetch_and_sub1_acquire_read\n#endif\n#if defined(AO_HAVE_short_fetch_and_add) \\\n    && !defined(AO_HAVE_short_fetch_and_sub1)\n# define AO_short_fetch_and_sub1(addr) \\\n                AO_short_fetch_and_add(addr, (unsigned/**/short)(-1))\n# define AO_HAVE_short_fetch_and_sub1\n#endif\n\n#if defined(AO_HAVE_short_fetch_and_sub1_full)\n# if !defined(AO_HAVE_short_fetch_and_sub1_release)\n#   define AO_short_fetch_and_sub1_release(addr) \\\n                                AO_short_fetch_and_sub1_full(addr)\n#   define AO_HAVE_short_fetch_and_sub1_release\n# endif\n# if !defined(AO_HAVE_short_fetch_and_sub1_acquire)\n#   define AO_short_fetch_and_sub1_acquire(addr) \\\n                                AO_short_fetch_and_sub1_full(addr)\n#   define AO_HAVE_short_fetch_and_sub1_acquire\n# endif\n# if !defined(AO_HAVE_short_fetch_and_sub1_write)\n#   define AO_short_fetch_and_sub1_write(addr) \\\n                                AO_short_fetch_and_sub1_full(addr)\n#   define AO_HAVE_short_fetch_and_sub1_write\n# endif\n# if !defined(AO_HAVE_short_fetch_and_sub1_read)\n#   define AO_short_fetch_and_sub1_read(addr) \\\n                                AO_short_fetch_and_sub1_full(addr)\n#   define AO_HAVE_short_fetch_and_sub1_read\n# endif\n#endif /* AO_HAVE_short_fetch_and_sub1_full */\n\n#if !defined(AO_HAVE_short_fetch_and_sub1) \\\n    && defined(AO_HAVE_short_fetch_and_sub1_release)\n# define AO_short_fetch_and_sub1(addr) AO_short_fetch_and_sub1_release(addr)\n# define AO_HAVE_short_fetch_and_sub1\n#endif\n#if !defined(AO_HAVE_short_fetch_and_sub1) \\\n    && defined(AO_HAVE_short_fetch_and_sub1_acquire)\n# define AO_short_fetch_and_sub1(addr) AO_short_fetch_and_sub1_acquire(addr)\n# define AO_HAVE_short_fetch_and_sub1\n#endif\n#if !defined(AO_HAVE_short_fetch_and_sub1) \\\n    && defined(AO_HAVE_short_fetch_and_sub1_write)\n# define AO_short_fetch_and_sub1(addr) AO_short_fetch_and_sub1_write(addr)\n# define AO_HAVE_short_fetch_and_sub1\n#endif\n#if !defined(AO_HAVE_short_fetch_and_sub1) \\\n    && defined(AO_HAVE_short_fetch_and_sub1_read)\n# define AO_short_fetch_and_sub1(addr) AO_short_fetch_and_sub1_read(addr)\n# define AO_HAVE_short_fetch_and_sub1\n#endif\n\n#if defined(AO_HAVE_short_fetch_and_sub1_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_fetch_and_sub1_full)\n# define AO_short_fetch_and_sub1_full(addr) \\\n                        (AO_nop_full(), AO_short_fetch_and_sub1_acquire(addr))\n# define AO_HAVE_short_fetch_and_sub1_full\n#endif\n\n#if !defined(AO_HAVE_short_fetch_and_sub1_release_write) \\\n    && defined(AO_HAVE_short_fetch_and_sub1_write)\n# define AO_short_fetch_and_sub1_release_write(addr) \\\n                                AO_short_fetch_and_sub1_write(addr)\n# define AO_HAVE_short_fetch_and_sub1_release_write\n#endif\n#if !defined(AO_HAVE_short_fetch_and_sub1_release_write) \\\n    && defined(AO_HAVE_short_fetch_and_sub1_release)\n# define AO_short_fetch_and_sub1_release_write(addr) \\\n                                AO_short_fetch_and_sub1_release(addr)\n# define AO_HAVE_short_fetch_and_sub1_release_write\n#endif\n#if !defined(AO_HAVE_short_fetch_and_sub1_acquire_read) \\\n    && defined(AO_HAVE_short_fetch_and_sub1_read)\n# define AO_short_fetch_and_sub1_acquire_read(addr) \\\n                                AO_short_fetch_and_sub1_read(addr)\n# define AO_HAVE_short_fetch_and_sub1_acquire_read\n#endif\n#if !defined(AO_HAVE_short_fetch_and_sub1_acquire_read) \\\n    && defined(AO_HAVE_short_fetch_and_sub1_acquire)\n# define AO_short_fetch_and_sub1_acquire_read(addr) \\\n                                AO_short_fetch_and_sub1_acquire(addr)\n# define AO_HAVE_short_fetch_and_sub1_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_short_fetch_and_sub1_acquire_read)\n#   define AO_short_fetch_and_sub1_dd_acquire_read(addr) \\\n                                AO_short_fetch_and_sub1_acquire_read(addr)\n#   define AO_HAVE_short_fetch_and_sub1_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_short_fetch_and_sub1)\n#   define AO_short_fetch_and_sub1_dd_acquire_read(addr) \\\n                                AO_short_fetch_and_sub1(addr)\n#   define AO_HAVE_short_fetch_and_sub1_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* short_and */\n#if defined(AO_HAVE_short_compare_and_swap_full) \\\n    && !defined(AO_HAVE_short_and_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_short_and_full(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    unsigned/**/short old;\n\n    do\n      {\n        old = *(unsigned/**/short *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_short_compare_and_swap_full(addr, old,\n                                                           old & value)));\n  }\n# define AO_HAVE_short_and_full\n#endif\n\n#if defined(AO_HAVE_short_and_full)\n# if !defined(AO_HAVE_short_and_release)\n#   define AO_short_and_release(addr, val) AO_short_and_full(addr, val)\n#   define AO_HAVE_short_and_release\n# endif\n# if !defined(AO_HAVE_short_and_acquire)\n#   define AO_short_and_acquire(addr, val) AO_short_and_full(addr, val)\n#   define AO_HAVE_short_and_acquire\n# endif\n# if !defined(AO_HAVE_short_and_write)\n#   define AO_short_and_write(addr, val) AO_short_and_full(addr, val)\n#   define AO_HAVE_short_and_write\n# endif\n# if !defined(AO_HAVE_short_and_read)\n#   define AO_short_and_read(addr, val) AO_short_and_full(addr, val)\n#   define AO_HAVE_short_and_read\n# endif\n#endif /* AO_HAVE_short_and_full */\n\n#if !defined(AO_HAVE_short_and) && defined(AO_HAVE_short_and_release)\n# define AO_short_and(addr, val) AO_short_and_release(addr, val)\n# define AO_HAVE_short_and\n#endif\n#if !defined(AO_HAVE_short_and) && defined(AO_HAVE_short_and_acquire)\n# define AO_short_and(addr, val) AO_short_and_acquire(addr, val)\n# define AO_HAVE_short_and\n#endif\n#if !defined(AO_HAVE_short_and) && defined(AO_HAVE_short_and_write)\n# define AO_short_and(addr, val) AO_short_and_write(addr, val)\n# define AO_HAVE_short_and\n#endif\n#if !defined(AO_HAVE_short_and) && defined(AO_HAVE_short_and_read)\n# define AO_short_and(addr, val) AO_short_and_read(addr, val)\n# define AO_HAVE_short_and\n#endif\n\n#if defined(AO_HAVE_short_and_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_and_full)\n# define AO_short_and_full(addr, val) \\\n                        (AO_nop_full(), AO_short_and_acquire(addr, val))\n# define AO_HAVE_short_and_full\n#endif\n\n#if !defined(AO_HAVE_short_and_release_write) \\\n    && defined(AO_HAVE_short_and_write)\n# define AO_short_and_release_write(addr, val) AO_short_and_write(addr, val)\n# define AO_HAVE_short_and_release_write\n#endif\n#if !defined(AO_HAVE_short_and_release_write) \\\n    && defined(AO_HAVE_short_and_release)\n# define AO_short_and_release_write(addr, val) AO_short_and_release(addr, val)\n# define AO_HAVE_short_and_release_write\n#endif\n#if !defined(AO_HAVE_short_and_acquire_read) \\\n    && defined(AO_HAVE_short_and_read)\n# define AO_short_and_acquire_read(addr, val) AO_short_and_read(addr, val)\n# define AO_HAVE_short_and_acquire_read\n#endif\n#if !defined(AO_HAVE_short_and_acquire_read) \\\n    && defined(AO_HAVE_short_and_acquire)\n# define AO_short_and_acquire_read(addr, val) AO_short_and_acquire(addr, val)\n# define AO_HAVE_short_and_acquire_read\n#endif\n\n/* short_or */\n#if defined(AO_HAVE_short_compare_and_swap_full) \\\n    && !defined(AO_HAVE_short_or_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_short_or_full(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    unsigned/**/short old;\n\n    do\n      {\n        old = *(unsigned/**/short *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_short_compare_and_swap_full(addr, old,\n                                                           old | value)));\n  }\n# define AO_HAVE_short_or_full\n#endif\n\n#if defined(AO_HAVE_short_or_full)\n# if !defined(AO_HAVE_short_or_release)\n#   define AO_short_or_release(addr, val) AO_short_or_full(addr, val)\n#   define AO_HAVE_short_or_release\n# endif\n# if !defined(AO_HAVE_short_or_acquire)\n#   define AO_short_or_acquire(addr, val) AO_short_or_full(addr, val)\n#   define AO_HAVE_short_or_acquire\n# endif\n# if !defined(AO_HAVE_short_or_write)\n#   define AO_short_or_write(addr, val) AO_short_or_full(addr, val)\n#   define AO_HAVE_short_or_write\n# endif\n# if !defined(AO_HAVE_short_or_read)\n#   define AO_short_or_read(addr, val) AO_short_or_full(addr, val)\n#   define AO_HAVE_short_or_read\n# endif\n#endif /* AO_HAVE_short_or_full */\n\n#if !defined(AO_HAVE_short_or) && defined(AO_HAVE_short_or_release)\n# define AO_short_or(addr, val) AO_short_or_release(addr, val)\n# define AO_HAVE_short_or\n#endif\n#if !defined(AO_HAVE_short_or) && defined(AO_HAVE_short_or_acquire)\n# define AO_short_or(addr, val) AO_short_or_acquire(addr, val)\n# define AO_HAVE_short_or\n#endif\n#if !defined(AO_HAVE_short_or) && defined(AO_HAVE_short_or_write)\n# define AO_short_or(addr, val) AO_short_or_write(addr, val)\n# define AO_HAVE_short_or\n#endif\n#if !defined(AO_HAVE_short_or) && defined(AO_HAVE_short_or_read)\n# define AO_short_or(addr, val) AO_short_or_read(addr, val)\n# define AO_HAVE_short_or\n#endif\n\n#if defined(AO_HAVE_short_or_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_or_full)\n# define AO_short_or_full(addr, val) \\\n                        (AO_nop_full(), AO_short_or_acquire(addr, val))\n# define AO_HAVE_short_or_full\n#endif\n\n#if !defined(AO_HAVE_short_or_release_write) \\\n    && defined(AO_HAVE_short_or_write)\n# define AO_short_or_release_write(addr, val) AO_short_or_write(addr, val)\n# define AO_HAVE_short_or_release_write\n#endif\n#if !defined(AO_HAVE_short_or_release_write) \\\n    && defined(AO_HAVE_short_or_release)\n# define AO_short_or_release_write(addr, val) AO_short_or_release(addr, val)\n# define AO_HAVE_short_or_release_write\n#endif\n#if !defined(AO_HAVE_short_or_acquire_read) && defined(AO_HAVE_short_or_read)\n# define AO_short_or_acquire_read(addr, val) AO_short_or_read(addr, val)\n# define AO_HAVE_short_or_acquire_read\n#endif\n#if !defined(AO_HAVE_short_or_acquire_read) \\\n    && defined(AO_HAVE_short_or_acquire)\n# define AO_short_or_acquire_read(addr, val) AO_short_or_acquire(addr, val)\n# define AO_HAVE_short_or_acquire_read\n#endif\n\n/* short_xor */\n#if defined(AO_HAVE_short_compare_and_swap_full) \\\n    && !defined(AO_HAVE_short_xor_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_short_xor_full(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    unsigned/**/short old;\n\n    do\n      {\n        old = *(unsigned/**/short *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_short_compare_and_swap_full(addr, old,\n                                                           old ^ value)));\n  }\n# define AO_HAVE_short_xor_full\n#endif\n\n#if defined(AO_HAVE_short_xor_full)\n# if !defined(AO_HAVE_short_xor_release)\n#   define AO_short_xor_release(addr, val) AO_short_xor_full(addr, val)\n#   define AO_HAVE_short_xor_release\n# endif\n# if !defined(AO_HAVE_short_xor_acquire)\n#   define AO_short_xor_acquire(addr, val) AO_short_xor_full(addr, val)\n#   define AO_HAVE_short_xor_acquire\n# endif\n# if !defined(AO_HAVE_short_xor_write)\n#   define AO_short_xor_write(addr, val) AO_short_xor_full(addr, val)\n#   define AO_HAVE_short_xor_write\n# endif\n# if !defined(AO_HAVE_short_xor_read)\n#   define AO_short_xor_read(addr, val) AO_short_xor_full(addr, val)\n#   define AO_HAVE_short_xor_read\n# endif\n#endif /* AO_HAVE_short_xor_full */\n\n#if !defined(AO_HAVE_short_xor) && defined(AO_HAVE_short_xor_release)\n# define AO_short_xor(addr, val) AO_short_xor_release(addr, val)\n# define AO_HAVE_short_xor\n#endif\n#if !defined(AO_HAVE_short_xor) && defined(AO_HAVE_short_xor_acquire)\n# define AO_short_xor(addr, val) AO_short_xor_acquire(addr, val)\n# define AO_HAVE_short_xor\n#endif\n#if !defined(AO_HAVE_short_xor) && defined(AO_HAVE_short_xor_write)\n# define AO_short_xor(addr, val) AO_short_xor_write(addr, val)\n# define AO_HAVE_short_xor\n#endif\n#if !defined(AO_HAVE_short_xor) && defined(AO_HAVE_short_xor_read)\n# define AO_short_xor(addr, val) AO_short_xor_read(addr, val)\n# define AO_HAVE_short_xor\n#endif\n\n#if defined(AO_HAVE_short_xor_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_xor_full)\n# define AO_short_xor_full(addr, val) \\\n                        (AO_nop_full(), AO_short_xor_acquire(addr, val))\n# define AO_HAVE_short_xor_full\n#endif\n\n#if !defined(AO_HAVE_short_xor_release_write) \\\n    && defined(AO_HAVE_short_xor_write)\n# define AO_short_xor_release_write(addr, val) AO_short_xor_write(addr, val)\n# define AO_HAVE_short_xor_release_write\n#endif\n#if !defined(AO_HAVE_short_xor_release_write) \\\n    && defined(AO_HAVE_short_xor_release)\n# define AO_short_xor_release_write(addr, val) AO_short_xor_release(addr, val)\n# define AO_HAVE_short_xor_release_write\n#endif\n#if !defined(AO_HAVE_short_xor_acquire_read) \\\n    && defined(AO_HAVE_short_xor_read)\n# define AO_short_xor_acquire_read(addr, val) AO_short_xor_read(addr, val)\n# define AO_HAVE_short_xor_acquire_read\n#endif\n#if !defined(AO_HAVE_short_xor_acquire_read) \\\n    && defined(AO_HAVE_short_xor_acquire)\n# define AO_short_xor_acquire_read(addr, val) AO_short_xor_acquire(addr, val)\n# define AO_HAVE_short_xor_acquire_read\n#endif\n\n/* short_and/or/xor_dd_acquire_read are meaningless.    */\n/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* int_compare_and_swap (based on fetch_compare_and_swap) */\n#if defined(AO_HAVE_int_fetch_compare_and_swap_full) \\\n    && !defined(AO_HAVE_int_compare_and_swap_full)\n  AO_INLINE int\n  AO_int_compare_and_swap_full(volatile unsigned *addr, unsigned old_val,\n                                 unsigned new_val)\n  {\n    return AO_int_fetch_compare_and_swap_full(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_int_compare_and_swap_full\n#endif\n\n#if defined(AO_HAVE_int_fetch_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_int_compare_and_swap_acquire)\n  AO_INLINE int\n  AO_int_compare_and_swap_acquire(volatile unsigned *addr, unsigned old_val,\n                                    unsigned new_val)\n  {\n    return AO_int_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_int_compare_and_swap_acquire\n#endif\n\n#if defined(AO_HAVE_int_fetch_compare_and_swap_release) \\\n    && !defined(AO_HAVE_int_compare_and_swap_release)\n  AO_INLINE int\n  AO_int_compare_and_swap_release(volatile unsigned *addr, unsigned old_val,\n                                    unsigned new_val)\n  {\n    return AO_int_fetch_compare_and_swap_release(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_int_compare_and_swap_release\n#endif\n\n#if defined(AO_HAVE_int_fetch_compare_and_swap_write) \\\n    && !defined(AO_HAVE_int_compare_and_swap_write)\n  AO_INLINE int\n  AO_int_compare_and_swap_write(volatile unsigned *addr, unsigned old_val,\n                                  unsigned new_val)\n  {\n    return AO_int_fetch_compare_and_swap_write(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_int_compare_and_swap_write\n#endif\n\n#if defined(AO_HAVE_int_fetch_compare_and_swap_read) \\\n    && !defined(AO_HAVE_int_compare_and_swap_read)\n  AO_INLINE int\n  AO_int_compare_and_swap_read(volatile unsigned *addr, unsigned old_val,\n                                 unsigned new_val)\n  {\n    return AO_int_fetch_compare_and_swap_read(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_int_compare_and_swap_read\n#endif\n\n#if defined(AO_HAVE_int_fetch_compare_and_swap) \\\n    && !defined(AO_HAVE_int_compare_and_swap)\n  AO_INLINE int\n  AO_int_compare_and_swap(volatile unsigned *addr, unsigned old_val,\n                            unsigned new_val)\n  {\n    return AO_int_fetch_compare_and_swap(addr, old_val, new_val) == old_val;\n  }\n# define AO_HAVE_int_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_int_fetch_compare_and_swap_release_write) \\\n    && !defined(AO_HAVE_int_compare_and_swap_release_write)\n  AO_INLINE int\n  AO_int_compare_and_swap_release_write(volatile unsigned *addr,\n                                          unsigned old_val, unsigned new_val)\n  {\n    return AO_int_fetch_compare_and_swap_release_write(addr, old_val,\n                                                         new_val) == old_val;\n  }\n# define AO_HAVE_int_compare_and_swap_release_write\n#endif\n\n#if defined(AO_HAVE_int_fetch_compare_and_swap_acquire_read) \\\n    && !defined(AO_HAVE_int_compare_and_swap_acquire_read)\n  AO_INLINE int\n  AO_int_compare_and_swap_acquire_read(volatile unsigned *addr,\n                                         unsigned old_val, unsigned new_val)\n  {\n    return AO_int_fetch_compare_and_swap_acquire_read(addr, old_val,\n                                                        new_val) == old_val;\n  }\n# define AO_HAVE_int_compare_and_swap_acquire_read\n#endif\n\n#if defined(AO_HAVE_int_fetch_compare_and_swap_dd_acquire_read) \\\n    && !defined(AO_HAVE_int_compare_and_swap_dd_acquire_read)\n  AO_INLINE int\n  AO_int_compare_and_swap_dd_acquire_read(volatile unsigned *addr,\n                                            unsigned old_val, unsigned new_val)\n  {\n    return AO_int_fetch_compare_and_swap_dd_acquire_read(addr, old_val,\n                                                           new_val) == old_val;\n  }\n# define AO_HAVE_int_compare_and_swap_dd_acquire_read\n#endif\n\n/* int_fetch_and_add */\n/* We first try to implement fetch_and_add variants in terms of the     */\n/* corresponding compare_and_swap variants to minimize adding barriers. */\n#if defined(AO_HAVE_int_compare_and_swap_full) \\\n    && !defined(AO_HAVE_int_fetch_and_add_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned\n  AO_int_fetch_and_add_full(volatile unsigned *addr, unsigned incr)\n  {\n    unsigned old;\n\n    do\n      {\n        old = *(unsigned *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_int_compare_and_swap_full(addr, old,\n                                                           old + incr)));\n    return old;\n  }\n# define AO_HAVE_int_fetch_and_add_full\n#endif\n\n#if defined(AO_HAVE_int_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_int_fetch_and_add_acquire)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned\n  AO_int_fetch_and_add_acquire(volatile unsigned *addr, unsigned incr)\n  {\n    unsigned old;\n\n    do\n      {\n        old = *(unsigned *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_int_compare_and_swap_acquire(addr, old,\n                                                              old + incr)));\n    return old;\n  }\n# define AO_HAVE_int_fetch_and_add_acquire\n#endif\n\n#if defined(AO_HAVE_int_compare_and_swap_release) \\\n    && !defined(AO_HAVE_int_fetch_and_add_release)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned\n  AO_int_fetch_and_add_release(volatile unsigned *addr, unsigned incr)\n  {\n    unsigned old;\n\n    do\n      {\n        old = *(unsigned *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_int_compare_and_swap_release(addr, old,\n                                                              old + incr)));\n    return old;\n  }\n# define AO_HAVE_int_fetch_and_add_release\n#endif\n\n#if defined(AO_HAVE_int_compare_and_swap) \\\n    && !defined(AO_HAVE_int_fetch_and_add)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned\n  AO_int_fetch_and_add(volatile unsigned *addr, unsigned incr)\n  {\n    unsigned old;\n\n    do\n      {\n        old = *(unsigned *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_int_compare_and_swap(addr, old,\n                                                      old + incr)));\n    return old;\n  }\n# define AO_HAVE_int_fetch_and_add\n#endif\n\n#if defined(AO_HAVE_int_fetch_and_add_full)\n# if !defined(AO_HAVE_int_fetch_and_add_release)\n#   define AO_int_fetch_and_add_release(addr, val) \\\n                                AO_int_fetch_and_add_full(addr, val)\n#   define AO_HAVE_int_fetch_and_add_release\n# endif\n# if !defined(AO_HAVE_int_fetch_and_add_acquire)\n#   define AO_int_fetch_and_add_acquire(addr, val) \\\n                                AO_int_fetch_and_add_full(addr, val)\n#   define AO_HAVE_int_fetch_and_add_acquire\n# endif\n# if !defined(AO_HAVE_int_fetch_and_add_write)\n#   define AO_int_fetch_and_add_write(addr, val) \\\n                                AO_int_fetch_and_add_full(addr, val)\n#   define AO_HAVE_int_fetch_and_add_write\n# endif\n# if !defined(AO_HAVE_int_fetch_and_add_read)\n#   define AO_int_fetch_and_add_read(addr, val) \\\n                                AO_int_fetch_and_add_full(addr, val)\n#   define AO_HAVE_int_fetch_and_add_read\n# endif\n#endif /* AO_HAVE_int_fetch_and_add_full */\n\n#if defined(AO_HAVE_int_fetch_and_add) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_fetch_and_add_acquire)\n  AO_INLINE unsigned\n  AO_int_fetch_and_add_acquire(volatile unsigned *addr, unsigned incr)\n  {\n    unsigned result = AO_int_fetch_and_add(addr, incr);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_int_fetch_and_add_acquire\n#endif\n#if defined(AO_HAVE_int_fetch_and_add) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_fetch_and_add_release)\n# define AO_int_fetch_and_add_release(addr, incr) \\\n                (AO_nop_full(), AO_int_fetch_and_add(addr, incr))\n# define AO_HAVE_int_fetch_and_add_release\n#endif\n\n#if !defined(AO_HAVE_int_fetch_and_add) \\\n    && defined(AO_HAVE_int_fetch_and_add_release)\n# define AO_int_fetch_and_add(addr, val) \\\n                                AO_int_fetch_and_add_release(addr, val)\n# define AO_HAVE_int_fetch_and_add\n#endif\n#if !defined(AO_HAVE_int_fetch_and_add) \\\n    && defined(AO_HAVE_int_fetch_and_add_acquire)\n# define AO_int_fetch_and_add(addr, val) \\\n                                AO_int_fetch_and_add_acquire(addr, val)\n# define AO_HAVE_int_fetch_and_add\n#endif\n#if !defined(AO_HAVE_int_fetch_and_add) \\\n    && defined(AO_HAVE_int_fetch_and_add_write)\n# define AO_int_fetch_and_add(addr, val) \\\n                                AO_int_fetch_and_add_write(addr, val)\n# define AO_HAVE_int_fetch_and_add\n#endif\n#if !defined(AO_HAVE_int_fetch_and_add) \\\n    && defined(AO_HAVE_int_fetch_and_add_read)\n# define AO_int_fetch_and_add(addr, val) \\\n                                AO_int_fetch_and_add_read(addr, val)\n# define AO_HAVE_int_fetch_and_add\n#endif\n\n#if defined(AO_HAVE_int_fetch_and_add_acquire) \\\n    && defined(AO_HAVE_nop_full) && !defined(AO_HAVE_int_fetch_and_add_full)\n# define AO_int_fetch_and_add_full(addr, val) \\\n                (AO_nop_full(), AO_int_fetch_and_add_acquire(addr, val))\n# define AO_HAVE_int_fetch_and_add_full\n#endif\n\n#if !defined(AO_HAVE_int_fetch_and_add_release_write) \\\n    && defined(AO_HAVE_int_fetch_and_add_write)\n# define AO_int_fetch_and_add_release_write(addr, val) \\\n                                AO_int_fetch_and_add_write(addr, val)\n# define AO_HAVE_int_fetch_and_add_release_write\n#endif\n#if !defined(AO_HAVE_int_fetch_and_add_release_write) \\\n    && defined(AO_HAVE_int_fetch_and_add_release)\n# define AO_int_fetch_and_add_release_write(addr, val) \\\n                                AO_int_fetch_and_add_release(addr, val)\n# define AO_HAVE_int_fetch_and_add_release_write\n#endif\n\n#if !defined(AO_HAVE_int_fetch_and_add_acquire_read) \\\n    && defined(AO_HAVE_int_fetch_and_add_read)\n# define AO_int_fetch_and_add_acquire_read(addr, val) \\\n                                AO_int_fetch_and_add_read(addr, val)\n# define AO_HAVE_int_fetch_and_add_acquire_read\n#endif\n#if !defined(AO_HAVE_int_fetch_and_add_acquire_read) \\\n    && defined(AO_HAVE_int_fetch_and_add_acquire)\n# define AO_int_fetch_and_add_acquire_read(addr, val) \\\n                                AO_int_fetch_and_add_acquire(addr, val)\n# define AO_HAVE_int_fetch_and_add_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_int_fetch_and_add_acquire_read)\n#   define AO_int_fetch_and_add_dd_acquire_read(addr, val) \\\n                                AO_int_fetch_and_add_acquire_read(addr, val)\n#   define AO_HAVE_int_fetch_and_add_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_int_fetch_and_add)\n#   define AO_int_fetch_and_add_dd_acquire_read(addr, val) \\\n                                AO_int_fetch_and_add(addr, val)\n#   define AO_HAVE_int_fetch_and_add_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* int_fetch_and_add1 */\n#if defined(AO_HAVE_int_fetch_and_add_full) \\\n    && !defined(AO_HAVE_int_fetch_and_add1_full)\n# define AO_int_fetch_and_add1_full(addr) \\\n                                AO_int_fetch_and_add_full(addr, 1)\n# define AO_HAVE_int_fetch_and_add1_full\n#endif\n#if defined(AO_HAVE_int_fetch_and_add_release) \\\n    && !defined(AO_HAVE_int_fetch_and_add1_release)\n# define AO_int_fetch_and_add1_release(addr) \\\n                                AO_int_fetch_and_add_release(addr, 1)\n# define AO_HAVE_int_fetch_and_add1_release\n#endif\n#if defined(AO_HAVE_int_fetch_and_add_acquire) \\\n    && !defined(AO_HAVE_int_fetch_and_add1_acquire)\n# define AO_int_fetch_and_add1_acquire(addr) \\\n                                AO_int_fetch_and_add_acquire(addr, 1)\n# define AO_HAVE_int_fetch_and_add1_acquire\n#endif\n#if defined(AO_HAVE_int_fetch_and_add_write) \\\n    && !defined(AO_HAVE_int_fetch_and_add1_write)\n# define AO_int_fetch_and_add1_write(addr) \\\n                                AO_int_fetch_and_add_write(addr, 1)\n# define AO_HAVE_int_fetch_and_add1_write\n#endif\n#if defined(AO_HAVE_int_fetch_and_add_read) \\\n    && !defined(AO_HAVE_int_fetch_and_add1_read)\n# define AO_int_fetch_and_add1_read(addr) \\\n                                AO_int_fetch_and_add_read(addr, 1)\n# define AO_HAVE_int_fetch_and_add1_read\n#endif\n#if defined(AO_HAVE_int_fetch_and_add_release_write) \\\n    && !defined(AO_HAVE_int_fetch_and_add1_release_write)\n# define AO_int_fetch_and_add1_release_write(addr) \\\n                                AO_int_fetch_and_add_release_write(addr, 1)\n# define AO_HAVE_int_fetch_and_add1_release_write\n#endif\n#if defined(AO_HAVE_int_fetch_and_add_acquire_read) \\\n    && !defined(AO_HAVE_int_fetch_and_add1_acquire_read)\n# define AO_int_fetch_and_add1_acquire_read(addr) \\\n                                AO_int_fetch_and_add_acquire_read(addr, 1)\n# define AO_HAVE_int_fetch_and_add1_acquire_read\n#endif\n#if defined(AO_HAVE_int_fetch_and_add) \\\n    && !defined(AO_HAVE_int_fetch_and_add1)\n# define AO_int_fetch_and_add1(addr) AO_int_fetch_and_add(addr, 1)\n# define AO_HAVE_int_fetch_and_add1\n#endif\n\n#if defined(AO_HAVE_int_fetch_and_add1_full)\n# if !defined(AO_HAVE_int_fetch_and_add1_release)\n#   define AO_int_fetch_and_add1_release(addr) \\\n                                AO_int_fetch_and_add1_full(addr)\n#   define AO_HAVE_int_fetch_and_add1_release\n# endif\n# if !defined(AO_HAVE_int_fetch_and_add1_acquire)\n#   define AO_int_fetch_and_add1_acquire(addr) \\\n                                AO_int_fetch_and_add1_full(addr)\n#   define AO_HAVE_int_fetch_and_add1_acquire\n# endif\n# if !defined(AO_HAVE_int_fetch_and_add1_write)\n#   define AO_int_fetch_and_add1_write(addr) \\\n                                AO_int_fetch_and_add1_full(addr)\n#   define AO_HAVE_int_fetch_and_add1_write\n# endif\n# if !defined(AO_HAVE_int_fetch_and_add1_read)\n#   define AO_int_fetch_and_add1_read(addr) \\\n                                AO_int_fetch_and_add1_full(addr)\n#   define AO_HAVE_int_fetch_and_add1_read\n# endif\n#endif /* AO_HAVE_int_fetch_and_add1_full */\n\n#if !defined(AO_HAVE_int_fetch_and_add1) \\\n    && defined(AO_HAVE_int_fetch_and_add1_release)\n# define AO_int_fetch_and_add1(addr) AO_int_fetch_and_add1_release(addr)\n# define AO_HAVE_int_fetch_and_add1\n#endif\n#if !defined(AO_HAVE_int_fetch_and_add1) \\\n    && defined(AO_HAVE_int_fetch_and_add1_acquire)\n# define AO_int_fetch_and_add1(addr) AO_int_fetch_and_add1_acquire(addr)\n# define AO_HAVE_int_fetch_and_add1\n#endif\n#if !defined(AO_HAVE_int_fetch_and_add1) \\\n    && defined(AO_HAVE_int_fetch_and_add1_write)\n# define AO_int_fetch_and_add1(addr) AO_int_fetch_and_add1_write(addr)\n# define AO_HAVE_int_fetch_and_add1\n#endif\n#if !defined(AO_HAVE_int_fetch_and_add1) \\\n    && defined(AO_HAVE_int_fetch_and_add1_read)\n# define AO_int_fetch_and_add1(addr) AO_int_fetch_and_add1_read(addr)\n# define AO_HAVE_int_fetch_and_add1\n#endif\n\n#if defined(AO_HAVE_int_fetch_and_add1_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_fetch_and_add1_full)\n# define AO_int_fetch_and_add1_full(addr) \\\n                        (AO_nop_full(), AO_int_fetch_and_add1_acquire(addr))\n# define AO_HAVE_int_fetch_and_add1_full\n#endif\n\n#if !defined(AO_HAVE_int_fetch_and_add1_release_write) \\\n    && defined(AO_HAVE_int_fetch_and_add1_write)\n# define AO_int_fetch_and_add1_release_write(addr) \\\n                                AO_int_fetch_and_add1_write(addr)\n# define AO_HAVE_int_fetch_and_add1_release_write\n#endif\n#if !defined(AO_HAVE_int_fetch_and_add1_release_write) \\\n    && defined(AO_HAVE_int_fetch_and_add1_release)\n# define AO_int_fetch_and_add1_release_write(addr) \\\n                                AO_int_fetch_and_add1_release(addr)\n# define AO_HAVE_int_fetch_and_add1_release_write\n#endif\n#if !defined(AO_HAVE_int_fetch_and_add1_acquire_read) \\\n    && defined(AO_HAVE_int_fetch_and_add1_read)\n# define AO_int_fetch_and_add1_acquire_read(addr) \\\n                                AO_int_fetch_and_add1_read(addr)\n# define AO_HAVE_int_fetch_and_add1_acquire_read\n#endif\n#if !defined(AO_HAVE_int_fetch_and_add1_acquire_read) \\\n    && defined(AO_HAVE_int_fetch_and_add1_acquire)\n# define AO_int_fetch_and_add1_acquire_read(addr) \\\n                                AO_int_fetch_and_add1_acquire(addr)\n# define AO_HAVE_int_fetch_and_add1_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_int_fetch_and_add1_acquire_read)\n#   define AO_int_fetch_and_add1_dd_acquire_read(addr) \\\n                                AO_int_fetch_and_add1_acquire_read(addr)\n#   define AO_HAVE_int_fetch_and_add1_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_int_fetch_and_add1)\n#   define AO_int_fetch_and_add1_dd_acquire_read(addr) \\\n                                AO_int_fetch_and_add1(addr)\n#   define AO_HAVE_int_fetch_and_add1_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* int_fetch_and_sub1 */\n#if defined(AO_HAVE_int_fetch_and_add_full) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1_full)\n# define AO_int_fetch_and_sub1_full(addr) \\\n                AO_int_fetch_and_add_full(addr, (unsigned)(-1))\n# define AO_HAVE_int_fetch_and_sub1_full\n#endif\n#if defined(AO_HAVE_int_fetch_and_add_release) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1_release)\n# define AO_int_fetch_and_sub1_release(addr) \\\n                AO_int_fetch_and_add_release(addr, (unsigned)(-1))\n# define AO_HAVE_int_fetch_and_sub1_release\n#endif\n#if defined(AO_HAVE_int_fetch_and_add_acquire) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1_acquire)\n# define AO_int_fetch_and_sub1_acquire(addr) \\\n                AO_int_fetch_and_add_acquire(addr, (unsigned)(-1))\n# define AO_HAVE_int_fetch_and_sub1_acquire\n#endif\n#if defined(AO_HAVE_int_fetch_and_add_write) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1_write)\n# define AO_int_fetch_and_sub1_write(addr) \\\n                AO_int_fetch_and_add_write(addr, (unsigned)(-1))\n# define AO_HAVE_int_fetch_and_sub1_write\n#endif\n#if defined(AO_HAVE_int_fetch_and_add_read) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1_read)\n# define AO_int_fetch_and_sub1_read(addr) \\\n                AO_int_fetch_and_add_read(addr, (unsigned)(-1))\n# define AO_HAVE_int_fetch_and_sub1_read\n#endif\n#if defined(AO_HAVE_int_fetch_and_add_release_write) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1_release_write)\n# define AO_int_fetch_and_sub1_release_write(addr) \\\n                AO_int_fetch_and_add_release_write(addr, (unsigned)(-1))\n# define AO_HAVE_int_fetch_and_sub1_release_write\n#endif\n#if defined(AO_HAVE_int_fetch_and_add_acquire_read) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1_acquire_read)\n# define AO_int_fetch_and_sub1_acquire_read(addr) \\\n                AO_int_fetch_and_add_acquire_read(addr, (unsigned)(-1))\n# define AO_HAVE_int_fetch_and_sub1_acquire_read\n#endif\n#if defined(AO_HAVE_int_fetch_and_add) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1)\n# define AO_int_fetch_and_sub1(addr) \\\n                AO_int_fetch_and_add(addr, (unsigned)(-1))\n# define AO_HAVE_int_fetch_and_sub1\n#endif\n\n#if defined(AO_HAVE_int_fetch_and_sub1_full)\n# if !defined(AO_HAVE_int_fetch_and_sub1_release)\n#   define AO_int_fetch_and_sub1_release(addr) \\\n                                AO_int_fetch_and_sub1_full(addr)\n#   define AO_HAVE_int_fetch_and_sub1_release\n# endif\n# if !defined(AO_HAVE_int_fetch_and_sub1_acquire)\n#   define AO_int_fetch_and_sub1_acquire(addr) \\\n                                AO_int_fetch_and_sub1_full(addr)\n#   define AO_HAVE_int_fetch_and_sub1_acquire\n# endif\n# if !defined(AO_HAVE_int_fetch_and_sub1_write)\n#   define AO_int_fetch_and_sub1_write(addr) \\\n                                AO_int_fetch_and_sub1_full(addr)\n#   define AO_HAVE_int_fetch_and_sub1_write\n# endif\n# if !defined(AO_HAVE_int_fetch_and_sub1_read)\n#   define AO_int_fetch_and_sub1_read(addr) \\\n                                AO_int_fetch_and_sub1_full(addr)\n#   define AO_HAVE_int_fetch_and_sub1_read\n# endif\n#endif /* AO_HAVE_int_fetch_and_sub1_full */\n\n#if !defined(AO_HAVE_int_fetch_and_sub1) \\\n    && defined(AO_HAVE_int_fetch_and_sub1_release)\n# define AO_int_fetch_and_sub1(addr) AO_int_fetch_and_sub1_release(addr)\n# define AO_HAVE_int_fetch_and_sub1\n#endif\n#if !defined(AO_HAVE_int_fetch_and_sub1) \\\n    && defined(AO_HAVE_int_fetch_and_sub1_acquire)\n# define AO_int_fetch_and_sub1(addr) AO_int_fetch_and_sub1_acquire(addr)\n# define AO_HAVE_int_fetch_and_sub1\n#endif\n#if !defined(AO_HAVE_int_fetch_and_sub1) \\\n    && defined(AO_HAVE_int_fetch_and_sub1_write)\n# define AO_int_fetch_and_sub1(addr) AO_int_fetch_and_sub1_write(addr)\n# define AO_HAVE_int_fetch_and_sub1\n#endif\n#if !defined(AO_HAVE_int_fetch_and_sub1) \\\n    && defined(AO_HAVE_int_fetch_and_sub1_read)\n# define AO_int_fetch_and_sub1(addr) AO_int_fetch_and_sub1_read(addr)\n# define AO_HAVE_int_fetch_and_sub1\n#endif\n\n#if defined(AO_HAVE_int_fetch_and_sub1_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1_full)\n# define AO_int_fetch_and_sub1_full(addr) \\\n                        (AO_nop_full(), AO_int_fetch_and_sub1_acquire(addr))\n# define AO_HAVE_int_fetch_and_sub1_full\n#endif\n\n#if !defined(AO_HAVE_int_fetch_and_sub1_release_write) \\\n    && defined(AO_HAVE_int_fetch_and_sub1_write)\n# define AO_int_fetch_and_sub1_release_write(addr) \\\n                                AO_int_fetch_and_sub1_write(addr)\n# define AO_HAVE_int_fetch_and_sub1_release_write\n#endif\n#if !defined(AO_HAVE_int_fetch_and_sub1_release_write) \\\n    && defined(AO_HAVE_int_fetch_and_sub1_release)\n# define AO_int_fetch_and_sub1_release_write(addr) \\\n                                AO_int_fetch_and_sub1_release(addr)\n# define AO_HAVE_int_fetch_and_sub1_release_write\n#endif\n#if !defined(AO_HAVE_int_fetch_and_sub1_acquire_read) \\\n    && defined(AO_HAVE_int_fetch_and_sub1_read)\n# define AO_int_fetch_and_sub1_acquire_read(addr) \\\n                                AO_int_fetch_and_sub1_read(addr)\n# define AO_HAVE_int_fetch_and_sub1_acquire_read\n#endif\n#if !defined(AO_HAVE_int_fetch_and_sub1_acquire_read) \\\n    && defined(AO_HAVE_int_fetch_and_sub1_acquire)\n# define AO_int_fetch_and_sub1_acquire_read(addr) \\\n                                AO_int_fetch_and_sub1_acquire(addr)\n# define AO_HAVE_int_fetch_and_sub1_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_int_fetch_and_sub1_acquire_read)\n#   define AO_int_fetch_and_sub1_dd_acquire_read(addr) \\\n                                AO_int_fetch_and_sub1_acquire_read(addr)\n#   define AO_HAVE_int_fetch_and_sub1_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_int_fetch_and_sub1)\n#   define AO_int_fetch_and_sub1_dd_acquire_read(addr) \\\n                                AO_int_fetch_and_sub1(addr)\n#   define AO_HAVE_int_fetch_and_sub1_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* int_and */\n#if defined(AO_HAVE_int_compare_and_swap_full) \\\n    && !defined(AO_HAVE_int_and_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_int_and_full(volatile unsigned *addr, unsigned value)\n  {\n    unsigned old;\n\n    do\n      {\n        old = *(unsigned *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_int_compare_and_swap_full(addr, old,\n                                                           old & value)));\n  }\n# define AO_HAVE_int_and_full\n#endif\n\n#if defined(AO_HAVE_int_and_full)\n# if !defined(AO_HAVE_int_and_release)\n#   define AO_int_and_release(addr, val) AO_int_and_full(addr, val)\n#   define AO_HAVE_int_and_release\n# endif\n# if !defined(AO_HAVE_int_and_acquire)\n#   define AO_int_and_acquire(addr, val) AO_int_and_full(addr, val)\n#   define AO_HAVE_int_and_acquire\n# endif\n# if !defined(AO_HAVE_int_and_write)\n#   define AO_int_and_write(addr, val) AO_int_and_full(addr, val)\n#   define AO_HAVE_int_and_write\n# endif\n# if !defined(AO_HAVE_int_and_read)\n#   define AO_int_and_read(addr, val) AO_int_and_full(addr, val)\n#   define AO_HAVE_int_and_read\n# endif\n#endif /* AO_HAVE_int_and_full */\n\n#if !defined(AO_HAVE_int_and) && defined(AO_HAVE_int_and_release)\n# define AO_int_and(addr, val) AO_int_and_release(addr, val)\n# define AO_HAVE_int_and\n#endif\n#if !defined(AO_HAVE_int_and) && defined(AO_HAVE_int_and_acquire)\n# define AO_int_and(addr, val) AO_int_and_acquire(addr, val)\n# define AO_HAVE_int_and\n#endif\n#if !defined(AO_HAVE_int_and) && defined(AO_HAVE_int_and_write)\n# define AO_int_and(addr, val) AO_int_and_write(addr, val)\n# define AO_HAVE_int_and\n#endif\n#if !defined(AO_HAVE_int_and) && defined(AO_HAVE_int_and_read)\n# define AO_int_and(addr, val) AO_int_and_read(addr, val)\n# define AO_HAVE_int_and\n#endif\n\n#if defined(AO_HAVE_int_and_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_and_full)\n# define AO_int_and_full(addr, val) \\\n                        (AO_nop_full(), AO_int_and_acquire(addr, val))\n# define AO_HAVE_int_and_full\n#endif\n\n#if !defined(AO_HAVE_int_and_release_write) \\\n    && defined(AO_HAVE_int_and_write)\n# define AO_int_and_release_write(addr, val) AO_int_and_write(addr, val)\n# define AO_HAVE_int_and_release_write\n#endif\n#if !defined(AO_HAVE_int_and_release_write) \\\n    && defined(AO_HAVE_int_and_release)\n# define AO_int_and_release_write(addr, val) AO_int_and_release(addr, val)\n# define AO_HAVE_int_and_release_write\n#endif\n#if !defined(AO_HAVE_int_and_acquire_read) \\\n    && defined(AO_HAVE_int_and_read)\n# define AO_int_and_acquire_read(addr, val) AO_int_and_read(addr, val)\n# define AO_HAVE_int_and_acquire_read\n#endif\n#if !defined(AO_HAVE_int_and_acquire_read) \\\n    && defined(AO_HAVE_int_and_acquire)\n# define AO_int_and_acquire_read(addr, val) AO_int_and_acquire(addr, val)\n# define AO_HAVE_int_and_acquire_read\n#endif\n\n/* int_or */\n#if defined(AO_HAVE_int_compare_and_swap_full) \\\n    && !defined(AO_HAVE_int_or_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_int_or_full(volatile unsigned *addr, unsigned value)\n  {\n    unsigned old;\n\n    do\n      {\n        old = *(unsigned *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_int_compare_and_swap_full(addr, old,\n                                                           old | value)));\n  }\n# define AO_HAVE_int_or_full\n#endif\n\n#if defined(AO_HAVE_int_or_full)\n# if !defined(AO_HAVE_int_or_release)\n#   define AO_int_or_release(addr, val) AO_int_or_full(addr, val)\n#   define AO_HAVE_int_or_release\n# endif\n# if !defined(AO_HAVE_int_or_acquire)\n#   define AO_int_or_acquire(addr, val) AO_int_or_full(addr, val)\n#   define AO_HAVE_int_or_acquire\n# endif\n# if !defined(AO_HAVE_int_or_write)\n#   define AO_int_or_write(addr, val) AO_int_or_full(addr, val)\n#   define AO_HAVE_int_or_write\n# endif\n# if !defined(AO_HAVE_int_or_read)\n#   define AO_int_or_read(addr, val) AO_int_or_full(addr, val)\n#   define AO_HAVE_int_or_read\n# endif\n#endif /* AO_HAVE_int_or_full */\n\n#if !defined(AO_HAVE_int_or) && defined(AO_HAVE_int_or_release)\n# define AO_int_or(addr, val) AO_int_or_release(addr, val)\n# define AO_HAVE_int_or\n#endif\n#if !defined(AO_HAVE_int_or) && defined(AO_HAVE_int_or_acquire)\n# define AO_int_or(addr, val) AO_int_or_acquire(addr, val)\n# define AO_HAVE_int_or\n#endif\n#if !defined(AO_HAVE_int_or) && defined(AO_HAVE_int_or_write)\n# define AO_int_or(addr, val) AO_int_or_write(addr, val)\n# define AO_HAVE_int_or\n#endif\n#if !defined(AO_HAVE_int_or) && defined(AO_HAVE_int_or_read)\n# define AO_int_or(addr, val) AO_int_or_read(addr, val)\n# define AO_HAVE_int_or\n#endif\n\n#if defined(AO_HAVE_int_or_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_or_full)\n# define AO_int_or_full(addr, val) \\\n                        (AO_nop_full(), AO_int_or_acquire(addr, val))\n# define AO_HAVE_int_or_full\n#endif\n\n#if !defined(AO_HAVE_int_or_release_write) \\\n    && defined(AO_HAVE_int_or_write)\n# define AO_int_or_release_write(addr, val) AO_int_or_write(addr, val)\n# define AO_HAVE_int_or_release_write\n#endif\n#if !defined(AO_HAVE_int_or_release_write) \\\n    && defined(AO_HAVE_int_or_release)\n# define AO_int_or_release_write(addr, val) AO_int_or_release(addr, val)\n# define AO_HAVE_int_or_release_write\n#endif\n#if !defined(AO_HAVE_int_or_acquire_read) && defined(AO_HAVE_int_or_read)\n# define AO_int_or_acquire_read(addr, val) AO_int_or_read(addr, val)\n# define AO_HAVE_int_or_acquire_read\n#endif\n#if !defined(AO_HAVE_int_or_acquire_read) \\\n    && defined(AO_HAVE_int_or_acquire)\n# define AO_int_or_acquire_read(addr, val) AO_int_or_acquire(addr, val)\n# define AO_HAVE_int_or_acquire_read\n#endif\n\n/* int_xor */\n#if defined(AO_HAVE_int_compare_and_swap_full) \\\n    && !defined(AO_HAVE_int_xor_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_int_xor_full(volatile unsigned *addr, unsigned value)\n  {\n    unsigned old;\n\n    do\n      {\n        old = *(unsigned *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_int_compare_and_swap_full(addr, old,\n                                                           old ^ value)));\n  }\n# define AO_HAVE_int_xor_full\n#endif\n\n#if defined(AO_HAVE_int_xor_full)\n# if !defined(AO_HAVE_int_xor_release)\n#   define AO_int_xor_release(addr, val) AO_int_xor_full(addr, val)\n#   define AO_HAVE_int_xor_release\n# endif\n# if !defined(AO_HAVE_int_xor_acquire)\n#   define AO_int_xor_acquire(addr, val) AO_int_xor_full(addr, val)\n#   define AO_HAVE_int_xor_acquire\n# endif\n# if !defined(AO_HAVE_int_xor_write)\n#   define AO_int_xor_write(addr, val) AO_int_xor_full(addr, val)\n#   define AO_HAVE_int_xor_write\n# endif\n# if !defined(AO_HAVE_int_xor_read)\n#   define AO_int_xor_read(addr, val) AO_int_xor_full(addr, val)\n#   define AO_HAVE_int_xor_read\n# endif\n#endif /* AO_HAVE_int_xor_full */\n\n#if !defined(AO_HAVE_int_xor) && defined(AO_HAVE_int_xor_release)\n# define AO_int_xor(addr, val) AO_int_xor_release(addr, val)\n# define AO_HAVE_int_xor\n#endif\n#if !defined(AO_HAVE_int_xor) && defined(AO_HAVE_int_xor_acquire)\n# define AO_int_xor(addr, val) AO_int_xor_acquire(addr, val)\n# define AO_HAVE_int_xor\n#endif\n#if !defined(AO_HAVE_int_xor) && defined(AO_HAVE_int_xor_write)\n# define AO_int_xor(addr, val) AO_int_xor_write(addr, val)\n# define AO_HAVE_int_xor\n#endif\n#if !defined(AO_HAVE_int_xor) && defined(AO_HAVE_int_xor_read)\n# define AO_int_xor(addr, val) AO_int_xor_read(addr, val)\n# define AO_HAVE_int_xor\n#endif\n\n#if defined(AO_HAVE_int_xor_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_xor_full)\n# define AO_int_xor_full(addr, val) \\\n                        (AO_nop_full(), AO_int_xor_acquire(addr, val))\n# define AO_HAVE_int_xor_full\n#endif\n\n#if !defined(AO_HAVE_int_xor_release_write) \\\n    && defined(AO_HAVE_int_xor_write)\n# define AO_int_xor_release_write(addr, val) AO_int_xor_write(addr, val)\n# define AO_HAVE_int_xor_release_write\n#endif\n#if !defined(AO_HAVE_int_xor_release_write) \\\n    && defined(AO_HAVE_int_xor_release)\n# define AO_int_xor_release_write(addr, val) AO_int_xor_release(addr, val)\n# define AO_HAVE_int_xor_release_write\n#endif\n#if !defined(AO_HAVE_int_xor_acquire_read) \\\n    && defined(AO_HAVE_int_xor_read)\n# define AO_int_xor_acquire_read(addr, val) AO_int_xor_read(addr, val)\n# define AO_HAVE_int_xor_acquire_read\n#endif\n#if !defined(AO_HAVE_int_xor_acquire_read) \\\n    && defined(AO_HAVE_int_xor_acquire)\n# define AO_int_xor_acquire_read(addr, val) AO_int_xor_acquire(addr, val)\n# define AO_HAVE_int_xor_acquire_read\n#endif\n\n/* int_and/or/xor_dd_acquire_read are meaningless.    */\n/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* compare_and_swap (based on fetch_compare_and_swap) */\n#if defined(AO_HAVE_fetch_compare_and_swap_full) \\\n    && !defined(AO_HAVE_compare_and_swap_full)\n  AO_INLINE int\n  AO_compare_and_swap_full(volatile AO_t *addr, AO_t old_val,\n                                 AO_t new_val)\n  {\n    return AO_fetch_compare_and_swap_full(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_compare_and_swap_full\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_compare_and_swap_acquire)\n  AO_INLINE int\n  AO_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val,\n                                    AO_t new_val)\n  {\n    return AO_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_compare_and_swap_acquire\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap_release) \\\n    && !defined(AO_HAVE_compare_and_swap_release)\n  AO_INLINE int\n  AO_compare_and_swap_release(volatile AO_t *addr, AO_t old_val,\n                                    AO_t new_val)\n  {\n    return AO_fetch_compare_and_swap_release(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_compare_and_swap_release\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap_write) \\\n    && !defined(AO_HAVE_compare_and_swap_write)\n  AO_INLINE int\n  AO_compare_and_swap_write(volatile AO_t *addr, AO_t old_val,\n                                  AO_t new_val)\n  {\n    return AO_fetch_compare_and_swap_write(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_compare_and_swap_write\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap_read) \\\n    && !defined(AO_HAVE_compare_and_swap_read)\n  AO_INLINE int\n  AO_compare_and_swap_read(volatile AO_t *addr, AO_t old_val,\n                                 AO_t new_val)\n  {\n    return AO_fetch_compare_and_swap_read(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_compare_and_swap_read\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap) \\\n    && !defined(AO_HAVE_compare_and_swap)\n  AO_INLINE int\n  AO_compare_and_swap(volatile AO_t *addr, AO_t old_val,\n                            AO_t new_val)\n  {\n    return AO_fetch_compare_and_swap(addr, old_val, new_val) == old_val;\n  }\n# define AO_HAVE_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap_release_write) \\\n    && !defined(AO_HAVE_compare_and_swap_release_write)\n  AO_INLINE int\n  AO_compare_and_swap_release_write(volatile AO_t *addr,\n                                          AO_t old_val, AO_t new_val)\n  {\n    return AO_fetch_compare_and_swap_release_write(addr, old_val,\n                                                         new_val) == old_val;\n  }\n# define AO_HAVE_compare_and_swap_release_write\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap_acquire_read) \\\n    && !defined(AO_HAVE_compare_and_swap_acquire_read)\n  AO_INLINE int\n  AO_compare_and_swap_acquire_read(volatile AO_t *addr,\n                                         AO_t old_val, AO_t new_val)\n  {\n    return AO_fetch_compare_and_swap_acquire_read(addr, old_val,\n                                                        new_val) == old_val;\n  }\n# define AO_HAVE_compare_and_swap_acquire_read\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap_dd_acquire_read) \\\n    && !defined(AO_HAVE_compare_and_swap_dd_acquire_read)\n  AO_INLINE int\n  AO_compare_and_swap_dd_acquire_read(volatile AO_t *addr,\n                                            AO_t old_val, AO_t new_val)\n  {\n    return AO_fetch_compare_and_swap_dd_acquire_read(addr, old_val,\n                                                           new_val) == old_val;\n  }\n# define AO_HAVE_compare_and_swap_dd_acquire_read\n#endif\n\n/* fetch_and_add */\n/* We first try to implement fetch_and_add variants in terms of the     */\n/* corresponding compare_and_swap variants to minimize adding barriers. */\n#if defined(AO_HAVE_compare_and_swap_full) \\\n    && !defined(AO_HAVE_fetch_and_add_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE AO_t\n  AO_fetch_and_add_full(volatile AO_t *addr, AO_t incr)\n  {\n    AO_t old;\n\n    do\n      {\n        old = *(AO_t *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_compare_and_swap_full(addr, old,\n                                                           old + incr)));\n    return old;\n  }\n# define AO_HAVE_fetch_and_add_full\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_fetch_and_add_acquire)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE AO_t\n  AO_fetch_and_add_acquire(volatile AO_t *addr, AO_t incr)\n  {\n    AO_t old;\n\n    do\n      {\n        old = *(AO_t *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_compare_and_swap_acquire(addr, old,\n                                                              old + incr)));\n    return old;\n  }\n# define AO_HAVE_fetch_and_add_acquire\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_release) \\\n    && !defined(AO_HAVE_fetch_and_add_release)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE AO_t\n  AO_fetch_and_add_release(volatile AO_t *addr, AO_t incr)\n  {\n    AO_t old;\n\n    do\n      {\n        old = *(AO_t *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_compare_and_swap_release(addr, old,\n                                                              old + incr)));\n    return old;\n  }\n# define AO_HAVE_fetch_and_add_release\n#endif\n\n#if defined(AO_HAVE_compare_and_swap) \\\n    && !defined(AO_HAVE_fetch_and_add)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE AO_t\n  AO_fetch_and_add(volatile AO_t *addr, AO_t incr)\n  {\n    AO_t old;\n\n    do\n      {\n        old = *(AO_t *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_compare_and_swap(addr, old,\n                                                      old + incr)));\n    return old;\n  }\n# define AO_HAVE_fetch_and_add\n#endif\n\n#if defined(AO_HAVE_fetch_and_add_full)\n# if !defined(AO_HAVE_fetch_and_add_release)\n#   define AO_fetch_and_add_release(addr, val) \\\n                                AO_fetch_and_add_full(addr, val)\n#   define AO_HAVE_fetch_and_add_release\n# endif\n# if !defined(AO_HAVE_fetch_and_add_acquire)\n#   define AO_fetch_and_add_acquire(addr, val) \\\n                                AO_fetch_and_add_full(addr, val)\n#   define AO_HAVE_fetch_and_add_acquire\n# endif\n# if !defined(AO_HAVE_fetch_and_add_write)\n#   define AO_fetch_and_add_write(addr, val) \\\n                                AO_fetch_and_add_full(addr, val)\n#   define AO_HAVE_fetch_and_add_write\n# endif\n# if !defined(AO_HAVE_fetch_and_add_read)\n#   define AO_fetch_and_add_read(addr, val) \\\n                                AO_fetch_and_add_full(addr, val)\n#   define AO_HAVE_fetch_and_add_read\n# endif\n#endif /* AO_HAVE_fetch_and_add_full */\n\n#if defined(AO_HAVE_fetch_and_add) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_fetch_and_add_acquire)\n  AO_INLINE AO_t\n  AO_fetch_and_add_acquire(volatile AO_t *addr, AO_t incr)\n  {\n    AO_t result = AO_fetch_and_add(addr, incr);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_fetch_and_add_acquire\n#endif\n#if defined(AO_HAVE_fetch_and_add) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_fetch_and_add_release)\n# define AO_fetch_and_add_release(addr, incr) \\\n                (AO_nop_full(), AO_fetch_and_add(addr, incr))\n# define AO_HAVE_fetch_and_add_release\n#endif\n\n#if !defined(AO_HAVE_fetch_and_add) \\\n    && defined(AO_HAVE_fetch_and_add_release)\n# define AO_fetch_and_add(addr, val) \\\n                                AO_fetch_and_add_release(addr, val)\n# define AO_HAVE_fetch_and_add\n#endif\n#if !defined(AO_HAVE_fetch_and_add) \\\n    && defined(AO_HAVE_fetch_and_add_acquire)\n# define AO_fetch_and_add(addr, val) \\\n                                AO_fetch_and_add_acquire(addr, val)\n# define AO_HAVE_fetch_and_add\n#endif\n#if !defined(AO_HAVE_fetch_and_add) \\\n    && defined(AO_HAVE_fetch_and_add_write)\n# define AO_fetch_and_add(addr, val) \\\n                                AO_fetch_and_add_write(addr, val)\n# define AO_HAVE_fetch_and_add\n#endif\n#if !defined(AO_HAVE_fetch_and_add) \\\n    && defined(AO_HAVE_fetch_and_add_read)\n# define AO_fetch_and_add(addr, val) \\\n                                AO_fetch_and_add_read(addr, val)\n# define AO_HAVE_fetch_and_add\n#endif\n\n#if defined(AO_HAVE_fetch_and_add_acquire) \\\n    && defined(AO_HAVE_nop_full) && !defined(AO_HAVE_fetch_and_add_full)\n# define AO_fetch_and_add_full(addr, val) \\\n                (AO_nop_full(), AO_fetch_and_add_acquire(addr, val))\n# define AO_HAVE_fetch_and_add_full\n#endif\n\n#if !defined(AO_HAVE_fetch_and_add_release_write) \\\n    && defined(AO_HAVE_fetch_and_add_write)\n# define AO_fetch_and_add_release_write(addr, val) \\\n                                AO_fetch_and_add_write(addr, val)\n# define AO_HAVE_fetch_and_add_release_write\n#endif\n#if !defined(AO_HAVE_fetch_and_add_release_write) \\\n    && defined(AO_HAVE_fetch_and_add_release)\n# define AO_fetch_and_add_release_write(addr, val) \\\n                                AO_fetch_and_add_release(addr, val)\n# define AO_HAVE_fetch_and_add_release_write\n#endif\n\n#if !defined(AO_HAVE_fetch_and_add_acquire_read) \\\n    && defined(AO_HAVE_fetch_and_add_read)\n# define AO_fetch_and_add_acquire_read(addr, val) \\\n                                AO_fetch_and_add_read(addr, val)\n# define AO_HAVE_fetch_and_add_acquire_read\n#endif\n#if !defined(AO_HAVE_fetch_and_add_acquire_read) \\\n    && defined(AO_HAVE_fetch_and_add_acquire)\n# define AO_fetch_and_add_acquire_read(addr, val) \\\n                                AO_fetch_and_add_acquire(addr, val)\n# define AO_HAVE_fetch_and_add_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_fetch_and_add_acquire_read)\n#   define AO_fetch_and_add_dd_acquire_read(addr, val) \\\n                                AO_fetch_and_add_acquire_read(addr, val)\n#   define AO_HAVE_fetch_and_add_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_fetch_and_add)\n#   define AO_fetch_and_add_dd_acquire_read(addr, val) \\\n                                AO_fetch_and_add(addr, val)\n#   define AO_HAVE_fetch_and_add_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* fetch_and_add1 */\n#if defined(AO_HAVE_fetch_and_add_full) \\\n    && !defined(AO_HAVE_fetch_and_add1_full)\n# define AO_fetch_and_add1_full(addr) \\\n                                AO_fetch_and_add_full(addr, 1)\n# define AO_HAVE_fetch_and_add1_full\n#endif\n#if defined(AO_HAVE_fetch_and_add_release) \\\n    && !defined(AO_HAVE_fetch_and_add1_release)\n# define AO_fetch_and_add1_release(addr) \\\n                                AO_fetch_and_add_release(addr, 1)\n# define AO_HAVE_fetch_and_add1_release\n#endif\n#if defined(AO_HAVE_fetch_and_add_acquire) \\\n    && !defined(AO_HAVE_fetch_and_add1_acquire)\n# define AO_fetch_and_add1_acquire(addr) \\\n                                AO_fetch_and_add_acquire(addr, 1)\n# define AO_HAVE_fetch_and_add1_acquire\n#endif\n#if defined(AO_HAVE_fetch_and_add_write) \\\n    && !defined(AO_HAVE_fetch_and_add1_write)\n# define AO_fetch_and_add1_write(addr) \\\n                                AO_fetch_and_add_write(addr, 1)\n# define AO_HAVE_fetch_and_add1_write\n#endif\n#if defined(AO_HAVE_fetch_and_add_read) \\\n    && !defined(AO_HAVE_fetch_and_add1_read)\n# define AO_fetch_and_add1_read(addr) \\\n                                AO_fetch_and_add_read(addr, 1)\n# define AO_HAVE_fetch_and_add1_read\n#endif\n#if defined(AO_HAVE_fetch_and_add_release_write) \\\n    && !defined(AO_HAVE_fetch_and_add1_release_write)\n# define AO_fetch_and_add1_release_write(addr) \\\n                                AO_fetch_and_add_release_write(addr, 1)\n# define AO_HAVE_fetch_and_add1_release_write\n#endif\n#if defined(AO_HAVE_fetch_and_add_acquire_read) \\\n    && !defined(AO_HAVE_fetch_and_add1_acquire_read)\n# define AO_fetch_and_add1_acquire_read(addr) \\\n                                AO_fetch_and_add_acquire_read(addr, 1)\n# define AO_HAVE_fetch_and_add1_acquire_read\n#endif\n#if defined(AO_HAVE_fetch_and_add) \\\n    && !defined(AO_HAVE_fetch_and_add1)\n# define AO_fetch_and_add1(addr) AO_fetch_and_add(addr, 1)\n# define AO_HAVE_fetch_and_add1\n#endif\n\n#if defined(AO_HAVE_fetch_and_add1_full)\n# if !defined(AO_HAVE_fetch_and_add1_release)\n#   define AO_fetch_and_add1_release(addr) \\\n                                AO_fetch_and_add1_full(addr)\n#   define AO_HAVE_fetch_and_add1_release\n# endif\n# if !defined(AO_HAVE_fetch_and_add1_acquire)\n#   define AO_fetch_and_add1_acquire(addr) \\\n                                AO_fetch_and_add1_full(addr)\n#   define AO_HAVE_fetch_and_add1_acquire\n# endif\n# if !defined(AO_HAVE_fetch_and_add1_write)\n#   define AO_fetch_and_add1_write(addr) \\\n                                AO_fetch_and_add1_full(addr)\n#   define AO_HAVE_fetch_and_add1_write\n# endif\n# if !defined(AO_HAVE_fetch_and_add1_read)\n#   define AO_fetch_and_add1_read(addr) \\\n                                AO_fetch_and_add1_full(addr)\n#   define AO_HAVE_fetch_and_add1_read\n# endif\n#endif /* AO_HAVE_fetch_and_add1_full */\n\n#if !defined(AO_HAVE_fetch_and_add1) \\\n    && defined(AO_HAVE_fetch_and_add1_release)\n# define AO_fetch_and_add1(addr) AO_fetch_and_add1_release(addr)\n# define AO_HAVE_fetch_and_add1\n#endif\n#if !defined(AO_HAVE_fetch_and_add1) \\\n    && defined(AO_HAVE_fetch_and_add1_acquire)\n# define AO_fetch_and_add1(addr) AO_fetch_and_add1_acquire(addr)\n# define AO_HAVE_fetch_and_add1\n#endif\n#if !defined(AO_HAVE_fetch_and_add1) \\\n    && defined(AO_HAVE_fetch_and_add1_write)\n# define AO_fetch_and_add1(addr) AO_fetch_and_add1_write(addr)\n# define AO_HAVE_fetch_and_add1\n#endif\n#if !defined(AO_HAVE_fetch_and_add1) \\\n    && defined(AO_HAVE_fetch_and_add1_read)\n# define AO_fetch_and_add1(addr) AO_fetch_and_add1_read(addr)\n# define AO_HAVE_fetch_and_add1\n#endif\n\n#if defined(AO_HAVE_fetch_and_add1_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_fetch_and_add1_full)\n# define AO_fetch_and_add1_full(addr) \\\n                        (AO_nop_full(), AO_fetch_and_add1_acquire(addr))\n# define AO_HAVE_fetch_and_add1_full\n#endif\n\n#if !defined(AO_HAVE_fetch_and_add1_release_write) \\\n    && defined(AO_HAVE_fetch_and_add1_write)\n# define AO_fetch_and_add1_release_write(addr) \\\n                                AO_fetch_and_add1_write(addr)\n# define AO_HAVE_fetch_and_add1_release_write\n#endif\n#if !defined(AO_HAVE_fetch_and_add1_release_write) \\\n    && defined(AO_HAVE_fetch_and_add1_release)\n# define AO_fetch_and_add1_release_write(addr) \\\n                                AO_fetch_and_add1_release(addr)\n# define AO_HAVE_fetch_and_add1_release_write\n#endif\n#if !defined(AO_HAVE_fetch_and_add1_acquire_read) \\\n    && defined(AO_HAVE_fetch_and_add1_read)\n# define AO_fetch_and_add1_acquire_read(addr) \\\n                                AO_fetch_and_add1_read(addr)\n# define AO_HAVE_fetch_and_add1_acquire_read\n#endif\n#if !defined(AO_HAVE_fetch_and_add1_acquire_read) \\\n    && defined(AO_HAVE_fetch_and_add1_acquire)\n# define AO_fetch_and_add1_acquire_read(addr) \\\n                                AO_fetch_and_add1_acquire(addr)\n# define AO_HAVE_fetch_and_add1_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_fetch_and_add1_acquire_read)\n#   define AO_fetch_and_add1_dd_acquire_read(addr) \\\n                                AO_fetch_and_add1_acquire_read(addr)\n#   define AO_HAVE_fetch_and_add1_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_fetch_and_add1)\n#   define AO_fetch_and_add1_dd_acquire_read(addr) \\\n                                AO_fetch_and_add1(addr)\n#   define AO_HAVE_fetch_and_add1_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* fetch_and_sub1 */\n#if defined(AO_HAVE_fetch_and_add_full) \\\n    && !defined(AO_HAVE_fetch_and_sub1_full)\n# define AO_fetch_and_sub1_full(addr) \\\n                AO_fetch_and_add_full(addr, (AO_t)(-1))\n# define AO_HAVE_fetch_and_sub1_full\n#endif\n#if defined(AO_HAVE_fetch_and_add_release) \\\n    && !defined(AO_HAVE_fetch_and_sub1_release)\n# define AO_fetch_and_sub1_release(addr) \\\n                AO_fetch_and_add_release(addr, (AO_t)(-1))\n# define AO_HAVE_fetch_and_sub1_release\n#endif\n#if defined(AO_HAVE_fetch_and_add_acquire) \\\n    && !defined(AO_HAVE_fetch_and_sub1_acquire)\n# define AO_fetch_and_sub1_acquire(addr) \\\n                AO_fetch_and_add_acquire(addr, (AO_t)(-1))\n# define AO_HAVE_fetch_and_sub1_acquire\n#endif\n#if defined(AO_HAVE_fetch_and_add_write) \\\n    && !defined(AO_HAVE_fetch_and_sub1_write)\n# define AO_fetch_and_sub1_write(addr) \\\n                AO_fetch_and_add_write(addr, (AO_t)(-1))\n# define AO_HAVE_fetch_and_sub1_write\n#endif\n#if defined(AO_HAVE_fetch_and_add_read) \\\n    && !defined(AO_HAVE_fetch_and_sub1_read)\n# define AO_fetch_and_sub1_read(addr) \\\n                AO_fetch_and_add_read(addr, (AO_t)(-1))\n# define AO_HAVE_fetch_and_sub1_read\n#endif\n#if defined(AO_HAVE_fetch_and_add_release_write) \\\n    && !defined(AO_HAVE_fetch_and_sub1_release_write)\n# define AO_fetch_and_sub1_release_write(addr) \\\n                AO_fetch_and_add_release_write(addr, (AO_t)(-1))\n# define AO_HAVE_fetch_and_sub1_release_write\n#endif\n#if defined(AO_HAVE_fetch_and_add_acquire_read) \\\n    && !defined(AO_HAVE_fetch_and_sub1_acquire_read)\n# define AO_fetch_and_sub1_acquire_read(addr) \\\n                AO_fetch_and_add_acquire_read(addr, (AO_t)(-1))\n# define AO_HAVE_fetch_and_sub1_acquire_read\n#endif\n#if defined(AO_HAVE_fetch_and_add) \\\n    && !defined(AO_HAVE_fetch_and_sub1)\n# define AO_fetch_and_sub1(addr) \\\n                AO_fetch_and_add(addr, (AO_t)(-1))\n# define AO_HAVE_fetch_and_sub1\n#endif\n\n#if defined(AO_HAVE_fetch_and_sub1_full)\n# if !defined(AO_HAVE_fetch_and_sub1_release)\n#   define AO_fetch_and_sub1_release(addr) \\\n                                AO_fetch_and_sub1_full(addr)\n#   define AO_HAVE_fetch_and_sub1_release\n# endif\n# if !defined(AO_HAVE_fetch_and_sub1_acquire)\n#   define AO_fetch_and_sub1_acquire(addr) \\\n                                AO_fetch_and_sub1_full(addr)\n#   define AO_HAVE_fetch_and_sub1_acquire\n# endif\n# if !defined(AO_HAVE_fetch_and_sub1_write)\n#   define AO_fetch_and_sub1_write(addr) \\\n                                AO_fetch_and_sub1_full(addr)\n#   define AO_HAVE_fetch_and_sub1_write\n# endif\n# if !defined(AO_HAVE_fetch_and_sub1_read)\n#   define AO_fetch_and_sub1_read(addr) \\\n                                AO_fetch_and_sub1_full(addr)\n#   define AO_HAVE_fetch_and_sub1_read\n# endif\n#endif /* AO_HAVE_fetch_and_sub1_full */\n\n#if !defined(AO_HAVE_fetch_and_sub1) \\\n    && defined(AO_HAVE_fetch_and_sub1_release)\n# define AO_fetch_and_sub1(addr) AO_fetch_and_sub1_release(addr)\n# define AO_HAVE_fetch_and_sub1\n#endif\n#if !defined(AO_HAVE_fetch_and_sub1) \\\n    && defined(AO_HAVE_fetch_and_sub1_acquire)\n# define AO_fetch_and_sub1(addr) AO_fetch_and_sub1_acquire(addr)\n# define AO_HAVE_fetch_and_sub1\n#endif\n#if !defined(AO_HAVE_fetch_and_sub1) \\\n    && defined(AO_HAVE_fetch_and_sub1_write)\n# define AO_fetch_and_sub1(addr) AO_fetch_and_sub1_write(addr)\n# define AO_HAVE_fetch_and_sub1\n#endif\n#if !defined(AO_HAVE_fetch_and_sub1) \\\n    && defined(AO_HAVE_fetch_and_sub1_read)\n# define AO_fetch_and_sub1(addr) AO_fetch_and_sub1_read(addr)\n# define AO_HAVE_fetch_and_sub1\n#endif\n\n#if defined(AO_HAVE_fetch_and_sub1_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_fetch_and_sub1_full)\n# define AO_fetch_and_sub1_full(addr) \\\n                        (AO_nop_full(), AO_fetch_and_sub1_acquire(addr))\n# define AO_HAVE_fetch_and_sub1_full\n#endif\n\n#if !defined(AO_HAVE_fetch_and_sub1_release_write) \\\n    && defined(AO_HAVE_fetch_and_sub1_write)\n# define AO_fetch_and_sub1_release_write(addr) \\\n                                AO_fetch_and_sub1_write(addr)\n# define AO_HAVE_fetch_and_sub1_release_write\n#endif\n#if !defined(AO_HAVE_fetch_and_sub1_release_write) \\\n    && defined(AO_HAVE_fetch_and_sub1_release)\n# define AO_fetch_and_sub1_release_write(addr) \\\n                                AO_fetch_and_sub1_release(addr)\n# define AO_HAVE_fetch_and_sub1_release_write\n#endif\n#if !defined(AO_HAVE_fetch_and_sub1_acquire_read) \\\n    && defined(AO_HAVE_fetch_and_sub1_read)\n# define AO_fetch_and_sub1_acquire_read(addr) \\\n                                AO_fetch_and_sub1_read(addr)\n# define AO_HAVE_fetch_and_sub1_acquire_read\n#endif\n#if !defined(AO_HAVE_fetch_and_sub1_acquire_read) \\\n    && defined(AO_HAVE_fetch_and_sub1_acquire)\n# define AO_fetch_and_sub1_acquire_read(addr) \\\n                                AO_fetch_and_sub1_acquire(addr)\n# define AO_HAVE_fetch_and_sub1_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_fetch_and_sub1_acquire_read)\n#   define AO_fetch_and_sub1_dd_acquire_read(addr) \\\n                                AO_fetch_and_sub1_acquire_read(addr)\n#   define AO_HAVE_fetch_and_sub1_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_fetch_and_sub1)\n#   define AO_fetch_and_sub1_dd_acquire_read(addr) \\\n                                AO_fetch_and_sub1(addr)\n#   define AO_HAVE_fetch_and_sub1_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* and */\n#if defined(AO_HAVE_compare_and_swap_full) \\\n    && !defined(AO_HAVE_and_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_and_full(volatile AO_t *addr, AO_t value)\n  {\n    AO_t old;\n\n    do\n      {\n        old = *(AO_t *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_compare_and_swap_full(addr, old,\n                                                           old & value)));\n  }\n# define AO_HAVE_and_full\n#endif\n\n#if defined(AO_HAVE_and_full)\n# if !defined(AO_HAVE_and_release)\n#   define AO_and_release(addr, val) AO_and_full(addr, val)\n#   define AO_HAVE_and_release\n# endif\n# if !defined(AO_HAVE_and_acquire)\n#   define AO_and_acquire(addr, val) AO_and_full(addr, val)\n#   define AO_HAVE_and_acquire\n# endif\n# if !defined(AO_HAVE_and_write)\n#   define AO_and_write(addr, val) AO_and_full(addr, val)\n#   define AO_HAVE_and_write\n# endif\n# if !defined(AO_HAVE_and_read)\n#   define AO_and_read(addr, val) AO_and_full(addr, val)\n#   define AO_HAVE_and_read\n# endif\n#endif /* AO_HAVE_and_full */\n\n#if !defined(AO_HAVE_and) && defined(AO_HAVE_and_release)\n# define AO_and(addr, val) AO_and_release(addr, val)\n# define AO_HAVE_and\n#endif\n#if !defined(AO_HAVE_and) && defined(AO_HAVE_and_acquire)\n# define AO_and(addr, val) AO_and_acquire(addr, val)\n# define AO_HAVE_and\n#endif\n#if !defined(AO_HAVE_and) && defined(AO_HAVE_and_write)\n# define AO_and(addr, val) AO_and_write(addr, val)\n# define AO_HAVE_and\n#endif\n#if !defined(AO_HAVE_and) && defined(AO_HAVE_and_read)\n# define AO_and(addr, val) AO_and_read(addr, val)\n# define AO_HAVE_and\n#endif\n\n#if defined(AO_HAVE_and_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_and_full)\n# define AO_and_full(addr, val) \\\n                        (AO_nop_full(), AO_and_acquire(addr, val))\n# define AO_HAVE_and_full\n#endif\n\n#if !defined(AO_HAVE_and_release_write) \\\n    && defined(AO_HAVE_and_write)\n# define AO_and_release_write(addr, val) AO_and_write(addr, val)\n# define AO_HAVE_and_release_write\n#endif\n#if !defined(AO_HAVE_and_release_write) \\\n    && defined(AO_HAVE_and_release)\n# define AO_and_release_write(addr, val) AO_and_release(addr, val)\n# define AO_HAVE_and_release_write\n#endif\n#if !defined(AO_HAVE_and_acquire_read) \\\n    && defined(AO_HAVE_and_read)\n# define AO_and_acquire_read(addr, val) AO_and_read(addr, val)\n# define AO_HAVE_and_acquire_read\n#endif\n#if !defined(AO_HAVE_and_acquire_read) \\\n    && defined(AO_HAVE_and_acquire)\n# define AO_and_acquire_read(addr, val) AO_and_acquire(addr, val)\n# define AO_HAVE_and_acquire_read\n#endif\n\n/* or */\n#if defined(AO_HAVE_compare_and_swap_full) \\\n    && !defined(AO_HAVE_or_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_or_full(volatile AO_t *addr, AO_t value)\n  {\n    AO_t old;\n\n    do\n      {\n        old = *(AO_t *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_compare_and_swap_full(addr, old,\n                                                           old | value)));\n  }\n# define AO_HAVE_or_full\n#endif\n\n#if defined(AO_HAVE_or_full)\n# if !defined(AO_HAVE_or_release)\n#   define AO_or_release(addr, val) AO_or_full(addr, val)\n#   define AO_HAVE_or_release\n# endif\n# if !defined(AO_HAVE_or_acquire)\n#   define AO_or_acquire(addr, val) AO_or_full(addr, val)\n#   define AO_HAVE_or_acquire\n# endif\n# if !defined(AO_HAVE_or_write)\n#   define AO_or_write(addr, val) AO_or_full(addr, val)\n#   define AO_HAVE_or_write\n# endif\n# if !defined(AO_HAVE_or_read)\n#   define AO_or_read(addr, val) AO_or_full(addr, val)\n#   define AO_HAVE_or_read\n# endif\n#endif /* AO_HAVE_or_full */\n\n#if !defined(AO_HAVE_or) && defined(AO_HAVE_or_release)\n# define AO_or(addr, val) AO_or_release(addr, val)\n# define AO_HAVE_or\n#endif\n#if !defined(AO_HAVE_or) && defined(AO_HAVE_or_acquire)\n# define AO_or(addr, val) AO_or_acquire(addr, val)\n# define AO_HAVE_or\n#endif\n#if !defined(AO_HAVE_or) && defined(AO_HAVE_or_write)\n# define AO_or(addr, val) AO_or_write(addr, val)\n# define AO_HAVE_or\n#endif\n#if !defined(AO_HAVE_or) && defined(AO_HAVE_or_read)\n# define AO_or(addr, val) AO_or_read(addr, val)\n# define AO_HAVE_or\n#endif\n\n#if defined(AO_HAVE_or_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_or_full)\n# define AO_or_full(addr, val) \\\n                        (AO_nop_full(), AO_or_acquire(addr, val))\n# define AO_HAVE_or_full\n#endif\n\n#if !defined(AO_HAVE_or_release_write) \\\n    && defined(AO_HAVE_or_write)\n# define AO_or_release_write(addr, val) AO_or_write(addr, val)\n# define AO_HAVE_or_release_write\n#endif\n#if !defined(AO_HAVE_or_release_write) \\\n    && defined(AO_HAVE_or_release)\n# define AO_or_release_write(addr, val) AO_or_release(addr, val)\n# define AO_HAVE_or_release_write\n#endif\n#if !defined(AO_HAVE_or_acquire_read) && defined(AO_HAVE_or_read)\n# define AO_or_acquire_read(addr, val) AO_or_read(addr, val)\n# define AO_HAVE_or_acquire_read\n#endif\n#if !defined(AO_HAVE_or_acquire_read) \\\n    && defined(AO_HAVE_or_acquire)\n# define AO_or_acquire_read(addr, val) AO_or_acquire(addr, val)\n# define AO_HAVE_or_acquire_read\n#endif\n\n/* xor */\n#if defined(AO_HAVE_compare_and_swap_full) \\\n    && !defined(AO_HAVE_xor_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_xor_full(volatile AO_t *addr, AO_t value)\n  {\n    AO_t old;\n\n    do\n      {\n        old = *(AO_t *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_compare_and_swap_full(addr, old,\n                                                           old ^ value)));\n  }\n# define AO_HAVE_xor_full\n#endif\n\n#if defined(AO_HAVE_xor_full)\n# if !defined(AO_HAVE_xor_release)\n#   define AO_xor_release(addr, val) AO_xor_full(addr, val)\n#   define AO_HAVE_xor_release\n# endif\n# if !defined(AO_HAVE_xor_acquire)\n#   define AO_xor_acquire(addr, val) AO_xor_full(addr, val)\n#   define AO_HAVE_xor_acquire\n# endif\n# if !defined(AO_HAVE_xor_write)\n#   define AO_xor_write(addr, val) AO_xor_full(addr, val)\n#   define AO_HAVE_xor_write\n# endif\n# if !defined(AO_HAVE_xor_read)\n#   define AO_xor_read(addr, val) AO_xor_full(addr, val)\n#   define AO_HAVE_xor_read\n# endif\n#endif /* AO_HAVE_xor_full */\n\n#if !defined(AO_HAVE_xor) && defined(AO_HAVE_xor_release)\n# define AO_xor(addr, val) AO_xor_release(addr, val)\n# define AO_HAVE_xor\n#endif\n#if !defined(AO_HAVE_xor) && defined(AO_HAVE_xor_acquire)\n# define AO_xor(addr, val) AO_xor_acquire(addr, val)\n# define AO_HAVE_xor\n#endif\n#if !defined(AO_HAVE_xor) && defined(AO_HAVE_xor_write)\n# define AO_xor(addr, val) AO_xor_write(addr, val)\n# define AO_HAVE_xor\n#endif\n#if !defined(AO_HAVE_xor) && defined(AO_HAVE_xor_read)\n# define AO_xor(addr, val) AO_xor_read(addr, val)\n# define AO_HAVE_xor\n#endif\n\n#if defined(AO_HAVE_xor_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_xor_full)\n# define AO_xor_full(addr, val) \\\n                        (AO_nop_full(), AO_xor_acquire(addr, val))\n# define AO_HAVE_xor_full\n#endif\n\n#if !defined(AO_HAVE_xor_release_write) \\\n    && defined(AO_HAVE_xor_write)\n# define AO_xor_release_write(addr, val) AO_xor_write(addr, val)\n# define AO_HAVE_xor_release_write\n#endif\n#if !defined(AO_HAVE_xor_release_write) \\\n    && defined(AO_HAVE_xor_release)\n# define AO_xor_release_write(addr, val) AO_xor_release(addr, val)\n# define AO_HAVE_xor_release_write\n#endif\n#if !defined(AO_HAVE_xor_acquire_read) \\\n    && defined(AO_HAVE_xor_read)\n# define AO_xor_acquire_read(addr, val) AO_xor_read(addr, val)\n# define AO_HAVE_xor_acquire_read\n#endif\n#if !defined(AO_HAVE_xor_acquire_read) \\\n    && defined(AO_HAVE_xor_acquire)\n# define AO_xor_acquire_read(addr, val) AO_xor_acquire(addr, val)\n# define AO_HAVE_xor_acquire_read\n#endif\n\n/* and/or/xor_dd_acquire_read are meaningless.    */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/generalize-arithm.template",
    "content": "/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* XSIZE_compare_and_swap (based on fetch_compare_and_swap) */\n#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_full) \\\n    && !defined(AO_HAVE_XSIZE_compare_and_swap_full)\n  AO_INLINE int\n  AO_XSIZE_compare_and_swap_full(volatile XCTYPE *addr, XCTYPE old_val,\n                                 XCTYPE new_val)\n  {\n    return AO_XSIZE_fetch_compare_and_swap_full(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_XSIZE_compare_and_swap_full\n#endif\n\n#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_XSIZE_compare_and_swap_acquire)\n  AO_INLINE int\n  AO_XSIZE_compare_and_swap_acquire(volatile XCTYPE *addr, XCTYPE old_val,\n                                    XCTYPE new_val)\n  {\n    return AO_XSIZE_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_XSIZE_compare_and_swap_acquire\n#endif\n\n#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_release) \\\n    && !defined(AO_HAVE_XSIZE_compare_and_swap_release)\n  AO_INLINE int\n  AO_XSIZE_compare_and_swap_release(volatile XCTYPE *addr, XCTYPE old_val,\n                                    XCTYPE new_val)\n  {\n    return AO_XSIZE_fetch_compare_and_swap_release(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_XSIZE_compare_and_swap_release\n#endif\n\n#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_write) \\\n    && !defined(AO_HAVE_XSIZE_compare_and_swap_write)\n  AO_INLINE int\n  AO_XSIZE_compare_and_swap_write(volatile XCTYPE *addr, XCTYPE old_val,\n                                  XCTYPE new_val)\n  {\n    return AO_XSIZE_fetch_compare_and_swap_write(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_XSIZE_compare_and_swap_write\n#endif\n\n#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_read) \\\n    && !defined(AO_HAVE_XSIZE_compare_and_swap_read)\n  AO_INLINE int\n  AO_XSIZE_compare_and_swap_read(volatile XCTYPE *addr, XCTYPE old_val,\n                                 XCTYPE new_val)\n  {\n    return AO_XSIZE_fetch_compare_and_swap_read(addr, old_val, new_val)\n             == old_val;\n  }\n# define AO_HAVE_XSIZE_compare_and_swap_read\n#endif\n\n#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap) \\\n    && !defined(AO_HAVE_XSIZE_compare_and_swap)\n  AO_INLINE int\n  AO_XSIZE_compare_and_swap(volatile XCTYPE *addr, XCTYPE old_val,\n                            XCTYPE new_val)\n  {\n    return AO_XSIZE_fetch_compare_and_swap(addr, old_val, new_val) == old_val;\n  }\n# define AO_HAVE_XSIZE_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_release_write) \\\n    && !defined(AO_HAVE_XSIZE_compare_and_swap_release_write)\n  AO_INLINE int\n  AO_XSIZE_compare_and_swap_release_write(volatile XCTYPE *addr,\n                                          XCTYPE old_val, XCTYPE new_val)\n  {\n    return AO_XSIZE_fetch_compare_and_swap_release_write(addr, old_val,\n                                                         new_val) == old_val;\n  }\n# define AO_HAVE_XSIZE_compare_and_swap_release_write\n#endif\n\n#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_acquire_read) \\\n    && !defined(AO_HAVE_XSIZE_compare_and_swap_acquire_read)\n  AO_INLINE int\n  AO_XSIZE_compare_and_swap_acquire_read(volatile XCTYPE *addr,\n                                         XCTYPE old_val, XCTYPE new_val)\n  {\n    return AO_XSIZE_fetch_compare_and_swap_acquire_read(addr, old_val,\n                                                        new_val) == old_val;\n  }\n# define AO_HAVE_XSIZE_compare_and_swap_acquire_read\n#endif\n\n#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_dd_acquire_read) \\\n    && !defined(AO_HAVE_XSIZE_compare_and_swap_dd_acquire_read)\n  AO_INLINE int\n  AO_XSIZE_compare_and_swap_dd_acquire_read(volatile XCTYPE *addr,\n                                            XCTYPE old_val, XCTYPE new_val)\n  {\n    return AO_XSIZE_fetch_compare_and_swap_dd_acquire_read(addr, old_val,\n                                                           new_val) == old_val;\n  }\n# define AO_HAVE_XSIZE_compare_and_swap_dd_acquire_read\n#endif\n\n/* XSIZE_fetch_and_add */\n/* We first try to implement fetch_and_add variants in terms of the     */\n/* corresponding compare_and_swap variants to minimize adding barriers. */\n#if defined(AO_HAVE_XSIZE_compare_and_swap_full) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_add_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE XCTYPE\n  AO_XSIZE_fetch_and_add_full(volatile XCTYPE *addr, XCTYPE incr)\n  {\n    XCTYPE old;\n\n    do\n      {\n        old = *(XCTYPE *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_XSIZE_compare_and_swap_full(addr, old,\n                                                           old + incr)));\n    return old;\n  }\n# define AO_HAVE_XSIZE_fetch_and_add_full\n#endif\n\n#if defined(AO_HAVE_XSIZE_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_add_acquire)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE XCTYPE\n  AO_XSIZE_fetch_and_add_acquire(volatile XCTYPE *addr, XCTYPE incr)\n  {\n    XCTYPE old;\n\n    do\n      {\n        old = *(XCTYPE *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_XSIZE_compare_and_swap_acquire(addr, old,\n                                                              old + incr)));\n    return old;\n  }\n# define AO_HAVE_XSIZE_fetch_and_add_acquire\n#endif\n\n#if defined(AO_HAVE_XSIZE_compare_and_swap_release) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_add_release)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE XCTYPE\n  AO_XSIZE_fetch_and_add_release(volatile XCTYPE *addr, XCTYPE incr)\n  {\n    XCTYPE old;\n\n    do\n      {\n        old = *(XCTYPE *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_XSIZE_compare_and_swap_release(addr, old,\n                                                              old + incr)));\n    return old;\n  }\n# define AO_HAVE_XSIZE_fetch_and_add_release\n#endif\n\n#if defined(AO_HAVE_XSIZE_compare_and_swap) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_add)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE XCTYPE\n  AO_XSIZE_fetch_and_add(volatile XCTYPE *addr, XCTYPE incr)\n  {\n    XCTYPE old;\n\n    do\n      {\n        old = *(XCTYPE *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_XSIZE_compare_and_swap(addr, old,\n                                                      old + incr)));\n    return old;\n  }\n# define AO_HAVE_XSIZE_fetch_and_add\n#endif\n\n#if defined(AO_HAVE_XSIZE_fetch_and_add_full)\n# if !defined(AO_HAVE_XSIZE_fetch_and_add_release)\n#   define AO_XSIZE_fetch_and_add_release(addr, val) \\\n                                AO_XSIZE_fetch_and_add_full(addr, val)\n#   define AO_HAVE_XSIZE_fetch_and_add_release\n# endif\n# if !defined(AO_HAVE_XSIZE_fetch_and_add_acquire)\n#   define AO_XSIZE_fetch_and_add_acquire(addr, val) \\\n                                AO_XSIZE_fetch_and_add_full(addr, val)\n#   define AO_HAVE_XSIZE_fetch_and_add_acquire\n# endif\n# if !defined(AO_HAVE_XSIZE_fetch_and_add_write)\n#   define AO_XSIZE_fetch_and_add_write(addr, val) \\\n                                AO_XSIZE_fetch_and_add_full(addr, val)\n#   define AO_HAVE_XSIZE_fetch_and_add_write\n# endif\n# if !defined(AO_HAVE_XSIZE_fetch_and_add_read)\n#   define AO_XSIZE_fetch_and_add_read(addr, val) \\\n                                AO_XSIZE_fetch_and_add_full(addr, val)\n#   define AO_HAVE_XSIZE_fetch_and_add_read\n# endif\n#endif /* AO_HAVE_XSIZE_fetch_and_add_full */\n\n#if defined(AO_HAVE_XSIZE_fetch_and_add) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_add_acquire)\n  AO_INLINE XCTYPE\n  AO_XSIZE_fetch_and_add_acquire(volatile XCTYPE *addr, XCTYPE incr)\n  {\n    XCTYPE result = AO_XSIZE_fetch_and_add(addr, incr);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_XSIZE_fetch_and_add_acquire\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_and_add) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_add_release)\n# define AO_XSIZE_fetch_and_add_release(addr, incr) \\\n                (AO_nop_full(), AO_XSIZE_fetch_and_add(addr, incr))\n# define AO_HAVE_XSIZE_fetch_and_add_release\n#endif\n\n#if !defined(AO_HAVE_XSIZE_fetch_and_add) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add_release)\n# define AO_XSIZE_fetch_and_add(addr, val) \\\n                                AO_XSIZE_fetch_and_add_release(addr, val)\n# define AO_HAVE_XSIZE_fetch_and_add\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_add) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add_acquire)\n# define AO_XSIZE_fetch_and_add(addr, val) \\\n                                AO_XSIZE_fetch_and_add_acquire(addr, val)\n# define AO_HAVE_XSIZE_fetch_and_add\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_add) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add_write)\n# define AO_XSIZE_fetch_and_add(addr, val) \\\n                                AO_XSIZE_fetch_and_add_write(addr, val)\n# define AO_HAVE_XSIZE_fetch_and_add\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_add) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add_read)\n# define AO_XSIZE_fetch_and_add(addr, val) \\\n                                AO_XSIZE_fetch_and_add_read(addr, val)\n# define AO_HAVE_XSIZE_fetch_and_add\n#endif\n\n#if defined(AO_HAVE_XSIZE_fetch_and_add_acquire) \\\n    && defined(AO_HAVE_nop_full) && !defined(AO_HAVE_XSIZE_fetch_and_add_full)\n# define AO_XSIZE_fetch_and_add_full(addr, val) \\\n                (AO_nop_full(), AO_XSIZE_fetch_and_add_acquire(addr, val))\n# define AO_HAVE_XSIZE_fetch_and_add_full\n#endif\n\n#if !defined(AO_HAVE_XSIZE_fetch_and_add_release_write) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add_write)\n# define AO_XSIZE_fetch_and_add_release_write(addr, val) \\\n                                AO_XSIZE_fetch_and_add_write(addr, val)\n# define AO_HAVE_XSIZE_fetch_and_add_release_write\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_add_release_write) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add_release)\n# define AO_XSIZE_fetch_and_add_release_write(addr, val) \\\n                                AO_XSIZE_fetch_and_add_release(addr, val)\n# define AO_HAVE_XSIZE_fetch_and_add_release_write\n#endif\n\n#if !defined(AO_HAVE_XSIZE_fetch_and_add_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add_read)\n# define AO_XSIZE_fetch_and_add_acquire_read(addr, val) \\\n                                AO_XSIZE_fetch_and_add_read(addr, val)\n# define AO_HAVE_XSIZE_fetch_and_add_acquire_read\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_add_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add_acquire)\n# define AO_XSIZE_fetch_and_add_acquire_read(addr, val) \\\n                                AO_XSIZE_fetch_and_add_acquire(addr, val)\n# define AO_HAVE_XSIZE_fetch_and_add_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_XSIZE_fetch_and_add_acquire_read)\n#   define AO_XSIZE_fetch_and_add_dd_acquire_read(addr, val) \\\n                                AO_XSIZE_fetch_and_add_acquire_read(addr, val)\n#   define AO_HAVE_XSIZE_fetch_and_add_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_XSIZE_fetch_and_add)\n#   define AO_XSIZE_fetch_and_add_dd_acquire_read(addr, val) \\\n                                AO_XSIZE_fetch_and_add(addr, val)\n#   define AO_HAVE_XSIZE_fetch_and_add_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* XSIZE_fetch_and_add1 */\n#if defined(AO_HAVE_XSIZE_fetch_and_add_full) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_add1_full)\n# define AO_XSIZE_fetch_and_add1_full(addr) \\\n                                AO_XSIZE_fetch_and_add_full(addr, 1)\n# define AO_HAVE_XSIZE_fetch_and_add1_full\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_and_add_release) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_add1_release)\n# define AO_XSIZE_fetch_and_add1_release(addr) \\\n                                AO_XSIZE_fetch_and_add_release(addr, 1)\n# define AO_HAVE_XSIZE_fetch_and_add1_release\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_and_add_acquire) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_add1_acquire)\n# define AO_XSIZE_fetch_and_add1_acquire(addr) \\\n                                AO_XSIZE_fetch_and_add_acquire(addr, 1)\n# define AO_HAVE_XSIZE_fetch_and_add1_acquire\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_and_add_write) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_add1_write)\n# define AO_XSIZE_fetch_and_add1_write(addr) \\\n                                AO_XSIZE_fetch_and_add_write(addr, 1)\n# define AO_HAVE_XSIZE_fetch_and_add1_write\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_and_add_read) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_add1_read)\n# define AO_XSIZE_fetch_and_add1_read(addr) \\\n                                AO_XSIZE_fetch_and_add_read(addr, 1)\n# define AO_HAVE_XSIZE_fetch_and_add1_read\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_and_add_release_write) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_add1_release_write)\n# define AO_XSIZE_fetch_and_add1_release_write(addr) \\\n                                AO_XSIZE_fetch_and_add_release_write(addr, 1)\n# define AO_HAVE_XSIZE_fetch_and_add1_release_write\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_and_add_acquire_read) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_add1_acquire_read)\n# define AO_XSIZE_fetch_and_add1_acquire_read(addr) \\\n                                AO_XSIZE_fetch_and_add_acquire_read(addr, 1)\n# define AO_HAVE_XSIZE_fetch_and_add1_acquire_read\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_and_add) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_add1)\n# define AO_XSIZE_fetch_and_add1(addr) AO_XSIZE_fetch_and_add(addr, 1)\n# define AO_HAVE_XSIZE_fetch_and_add1\n#endif\n\n#if defined(AO_HAVE_XSIZE_fetch_and_add1_full)\n# if !defined(AO_HAVE_XSIZE_fetch_and_add1_release)\n#   define AO_XSIZE_fetch_and_add1_release(addr) \\\n                                AO_XSIZE_fetch_and_add1_full(addr)\n#   define AO_HAVE_XSIZE_fetch_and_add1_release\n# endif\n# if !defined(AO_HAVE_XSIZE_fetch_and_add1_acquire)\n#   define AO_XSIZE_fetch_and_add1_acquire(addr) \\\n                                AO_XSIZE_fetch_and_add1_full(addr)\n#   define AO_HAVE_XSIZE_fetch_and_add1_acquire\n# endif\n# if !defined(AO_HAVE_XSIZE_fetch_and_add1_write)\n#   define AO_XSIZE_fetch_and_add1_write(addr) \\\n                                AO_XSIZE_fetch_and_add1_full(addr)\n#   define AO_HAVE_XSIZE_fetch_and_add1_write\n# endif\n# if !defined(AO_HAVE_XSIZE_fetch_and_add1_read)\n#   define AO_XSIZE_fetch_and_add1_read(addr) \\\n                                AO_XSIZE_fetch_and_add1_full(addr)\n#   define AO_HAVE_XSIZE_fetch_and_add1_read\n# endif\n#endif /* AO_HAVE_XSIZE_fetch_and_add1_full */\n\n#if !defined(AO_HAVE_XSIZE_fetch_and_add1) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add1_release)\n# define AO_XSIZE_fetch_and_add1(addr) AO_XSIZE_fetch_and_add1_release(addr)\n# define AO_HAVE_XSIZE_fetch_and_add1\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_add1) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add1_acquire)\n# define AO_XSIZE_fetch_and_add1(addr) AO_XSIZE_fetch_and_add1_acquire(addr)\n# define AO_HAVE_XSIZE_fetch_and_add1\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_add1) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add1_write)\n# define AO_XSIZE_fetch_and_add1(addr) AO_XSIZE_fetch_and_add1_write(addr)\n# define AO_HAVE_XSIZE_fetch_and_add1\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_add1) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add1_read)\n# define AO_XSIZE_fetch_and_add1(addr) AO_XSIZE_fetch_and_add1_read(addr)\n# define AO_HAVE_XSIZE_fetch_and_add1\n#endif\n\n#if defined(AO_HAVE_XSIZE_fetch_and_add1_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_add1_full)\n# define AO_XSIZE_fetch_and_add1_full(addr) \\\n                        (AO_nop_full(), AO_XSIZE_fetch_and_add1_acquire(addr))\n# define AO_HAVE_XSIZE_fetch_and_add1_full\n#endif\n\n#if !defined(AO_HAVE_XSIZE_fetch_and_add1_release_write) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add1_write)\n# define AO_XSIZE_fetch_and_add1_release_write(addr) \\\n                                AO_XSIZE_fetch_and_add1_write(addr)\n# define AO_HAVE_XSIZE_fetch_and_add1_release_write\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_add1_release_write) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add1_release)\n# define AO_XSIZE_fetch_and_add1_release_write(addr) \\\n                                AO_XSIZE_fetch_and_add1_release(addr)\n# define AO_HAVE_XSIZE_fetch_and_add1_release_write\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_add1_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add1_read)\n# define AO_XSIZE_fetch_and_add1_acquire_read(addr) \\\n                                AO_XSIZE_fetch_and_add1_read(addr)\n# define AO_HAVE_XSIZE_fetch_and_add1_acquire_read\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_add1_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_add1_acquire)\n# define AO_XSIZE_fetch_and_add1_acquire_read(addr) \\\n                                AO_XSIZE_fetch_and_add1_acquire(addr)\n# define AO_HAVE_XSIZE_fetch_and_add1_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_XSIZE_fetch_and_add1_acquire_read)\n#   define AO_XSIZE_fetch_and_add1_dd_acquire_read(addr) \\\n                                AO_XSIZE_fetch_and_add1_acquire_read(addr)\n#   define AO_HAVE_XSIZE_fetch_and_add1_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_XSIZE_fetch_and_add1)\n#   define AO_XSIZE_fetch_and_add1_dd_acquire_read(addr) \\\n                                AO_XSIZE_fetch_and_add1(addr)\n#   define AO_HAVE_XSIZE_fetch_and_add1_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* XSIZE_fetch_and_sub1 */\n#if defined(AO_HAVE_XSIZE_fetch_and_add_full) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_sub1_full)\n# define AO_XSIZE_fetch_and_sub1_full(addr) \\\n                AO_XSIZE_fetch_and_add_full(addr, (XCTYPE)(-1))\n# define AO_HAVE_XSIZE_fetch_and_sub1_full\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_and_add_release) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_sub1_release)\n# define AO_XSIZE_fetch_and_sub1_release(addr) \\\n                AO_XSIZE_fetch_and_add_release(addr, (XCTYPE)(-1))\n# define AO_HAVE_XSIZE_fetch_and_sub1_release\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_and_add_acquire) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire)\n# define AO_XSIZE_fetch_and_sub1_acquire(addr) \\\n                AO_XSIZE_fetch_and_add_acquire(addr, (XCTYPE)(-1))\n# define AO_HAVE_XSIZE_fetch_and_sub1_acquire\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_and_add_write) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_sub1_write)\n# define AO_XSIZE_fetch_and_sub1_write(addr) \\\n                AO_XSIZE_fetch_and_add_write(addr, (XCTYPE)(-1))\n# define AO_HAVE_XSIZE_fetch_and_sub1_write\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_and_add_read) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_sub1_read)\n# define AO_XSIZE_fetch_and_sub1_read(addr) \\\n                AO_XSIZE_fetch_and_add_read(addr, (XCTYPE)(-1))\n# define AO_HAVE_XSIZE_fetch_and_sub1_read\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_and_add_release_write) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_sub1_release_write)\n# define AO_XSIZE_fetch_and_sub1_release_write(addr) \\\n                AO_XSIZE_fetch_and_add_release_write(addr, (XCTYPE)(-1))\n# define AO_HAVE_XSIZE_fetch_and_sub1_release_write\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_and_add_acquire_read) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire_read)\n# define AO_XSIZE_fetch_and_sub1_acquire_read(addr) \\\n                AO_XSIZE_fetch_and_add_acquire_read(addr, (XCTYPE)(-1))\n# define AO_HAVE_XSIZE_fetch_and_sub1_acquire_read\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_and_add) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_sub1)\n# define AO_XSIZE_fetch_and_sub1(addr) \\\n                AO_XSIZE_fetch_and_add(addr, (XCTYPE)(-1))\n# define AO_HAVE_XSIZE_fetch_and_sub1\n#endif\n\n#if defined(AO_HAVE_XSIZE_fetch_and_sub1_full)\n# if !defined(AO_HAVE_XSIZE_fetch_and_sub1_release)\n#   define AO_XSIZE_fetch_and_sub1_release(addr) \\\n                                AO_XSIZE_fetch_and_sub1_full(addr)\n#   define AO_HAVE_XSIZE_fetch_and_sub1_release\n# endif\n# if !defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire)\n#   define AO_XSIZE_fetch_and_sub1_acquire(addr) \\\n                                AO_XSIZE_fetch_and_sub1_full(addr)\n#   define AO_HAVE_XSIZE_fetch_and_sub1_acquire\n# endif\n# if !defined(AO_HAVE_XSIZE_fetch_and_sub1_write)\n#   define AO_XSIZE_fetch_and_sub1_write(addr) \\\n                                AO_XSIZE_fetch_and_sub1_full(addr)\n#   define AO_HAVE_XSIZE_fetch_and_sub1_write\n# endif\n# if !defined(AO_HAVE_XSIZE_fetch_and_sub1_read)\n#   define AO_XSIZE_fetch_and_sub1_read(addr) \\\n                                AO_XSIZE_fetch_and_sub1_full(addr)\n#   define AO_HAVE_XSIZE_fetch_and_sub1_read\n# endif\n#endif /* AO_HAVE_XSIZE_fetch_and_sub1_full */\n\n#if !defined(AO_HAVE_XSIZE_fetch_and_sub1) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_sub1_release)\n# define AO_XSIZE_fetch_and_sub1(addr) AO_XSIZE_fetch_and_sub1_release(addr)\n# define AO_HAVE_XSIZE_fetch_and_sub1\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_sub1) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire)\n# define AO_XSIZE_fetch_and_sub1(addr) AO_XSIZE_fetch_and_sub1_acquire(addr)\n# define AO_HAVE_XSIZE_fetch_and_sub1\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_sub1) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_sub1_write)\n# define AO_XSIZE_fetch_and_sub1(addr) AO_XSIZE_fetch_and_sub1_write(addr)\n# define AO_HAVE_XSIZE_fetch_and_sub1\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_sub1) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_sub1_read)\n# define AO_XSIZE_fetch_and_sub1(addr) AO_XSIZE_fetch_and_sub1_read(addr)\n# define AO_HAVE_XSIZE_fetch_and_sub1\n#endif\n\n#if defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_fetch_and_sub1_full)\n# define AO_XSIZE_fetch_and_sub1_full(addr) \\\n                        (AO_nop_full(), AO_XSIZE_fetch_and_sub1_acquire(addr))\n# define AO_HAVE_XSIZE_fetch_and_sub1_full\n#endif\n\n#if !defined(AO_HAVE_XSIZE_fetch_and_sub1_release_write) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_sub1_write)\n# define AO_XSIZE_fetch_and_sub1_release_write(addr) \\\n                                AO_XSIZE_fetch_and_sub1_write(addr)\n# define AO_HAVE_XSIZE_fetch_and_sub1_release_write\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_sub1_release_write) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_sub1_release)\n# define AO_XSIZE_fetch_and_sub1_release_write(addr) \\\n                                AO_XSIZE_fetch_and_sub1_release(addr)\n# define AO_HAVE_XSIZE_fetch_and_sub1_release_write\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_sub1_read)\n# define AO_XSIZE_fetch_and_sub1_acquire_read(addr) \\\n                                AO_XSIZE_fetch_and_sub1_read(addr)\n# define AO_HAVE_XSIZE_fetch_and_sub1_acquire_read\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire)\n# define AO_XSIZE_fetch_and_sub1_acquire_read(addr) \\\n                                AO_XSIZE_fetch_and_sub1_acquire(addr)\n# define AO_HAVE_XSIZE_fetch_and_sub1_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_XSIZE_fetch_and_sub1_acquire_read)\n#   define AO_XSIZE_fetch_and_sub1_dd_acquire_read(addr) \\\n                                AO_XSIZE_fetch_and_sub1_acquire_read(addr)\n#   define AO_HAVE_XSIZE_fetch_and_sub1_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_XSIZE_fetch_and_sub1)\n#   define AO_XSIZE_fetch_and_sub1_dd_acquire_read(addr) \\\n                                AO_XSIZE_fetch_and_sub1(addr)\n#   define AO_HAVE_XSIZE_fetch_and_sub1_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* XSIZE_and */\n#if defined(AO_HAVE_XSIZE_compare_and_swap_full) \\\n    && !defined(AO_HAVE_XSIZE_and_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_XSIZE_and_full(volatile XCTYPE *addr, XCTYPE value)\n  {\n    XCTYPE old;\n\n    do\n      {\n        old = *(XCTYPE *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_XSIZE_compare_and_swap_full(addr, old,\n                                                           old & value)));\n  }\n# define AO_HAVE_XSIZE_and_full\n#endif\n\n#if defined(AO_HAVE_XSIZE_and_full)\n# if !defined(AO_HAVE_XSIZE_and_release)\n#   define AO_XSIZE_and_release(addr, val) AO_XSIZE_and_full(addr, val)\n#   define AO_HAVE_XSIZE_and_release\n# endif\n# if !defined(AO_HAVE_XSIZE_and_acquire)\n#   define AO_XSIZE_and_acquire(addr, val) AO_XSIZE_and_full(addr, val)\n#   define AO_HAVE_XSIZE_and_acquire\n# endif\n# if !defined(AO_HAVE_XSIZE_and_write)\n#   define AO_XSIZE_and_write(addr, val) AO_XSIZE_and_full(addr, val)\n#   define AO_HAVE_XSIZE_and_write\n# endif\n# if !defined(AO_HAVE_XSIZE_and_read)\n#   define AO_XSIZE_and_read(addr, val) AO_XSIZE_and_full(addr, val)\n#   define AO_HAVE_XSIZE_and_read\n# endif\n#endif /* AO_HAVE_XSIZE_and_full */\n\n#if !defined(AO_HAVE_XSIZE_and) && defined(AO_HAVE_XSIZE_and_release)\n# define AO_XSIZE_and(addr, val) AO_XSIZE_and_release(addr, val)\n# define AO_HAVE_XSIZE_and\n#endif\n#if !defined(AO_HAVE_XSIZE_and) && defined(AO_HAVE_XSIZE_and_acquire)\n# define AO_XSIZE_and(addr, val) AO_XSIZE_and_acquire(addr, val)\n# define AO_HAVE_XSIZE_and\n#endif\n#if !defined(AO_HAVE_XSIZE_and) && defined(AO_HAVE_XSIZE_and_write)\n# define AO_XSIZE_and(addr, val) AO_XSIZE_and_write(addr, val)\n# define AO_HAVE_XSIZE_and\n#endif\n#if !defined(AO_HAVE_XSIZE_and) && defined(AO_HAVE_XSIZE_and_read)\n# define AO_XSIZE_and(addr, val) AO_XSIZE_and_read(addr, val)\n# define AO_HAVE_XSIZE_and\n#endif\n\n#if defined(AO_HAVE_XSIZE_and_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_and_full)\n# define AO_XSIZE_and_full(addr, val) \\\n                        (AO_nop_full(), AO_XSIZE_and_acquire(addr, val))\n# define AO_HAVE_XSIZE_and_full\n#endif\n\n#if !defined(AO_HAVE_XSIZE_and_release_write) \\\n    && defined(AO_HAVE_XSIZE_and_write)\n# define AO_XSIZE_and_release_write(addr, val) AO_XSIZE_and_write(addr, val)\n# define AO_HAVE_XSIZE_and_release_write\n#endif\n#if !defined(AO_HAVE_XSIZE_and_release_write) \\\n    && defined(AO_HAVE_XSIZE_and_release)\n# define AO_XSIZE_and_release_write(addr, val) AO_XSIZE_and_release(addr, val)\n# define AO_HAVE_XSIZE_and_release_write\n#endif\n#if !defined(AO_HAVE_XSIZE_and_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_and_read)\n# define AO_XSIZE_and_acquire_read(addr, val) AO_XSIZE_and_read(addr, val)\n# define AO_HAVE_XSIZE_and_acquire_read\n#endif\n#if !defined(AO_HAVE_XSIZE_and_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_and_acquire)\n# define AO_XSIZE_and_acquire_read(addr, val) AO_XSIZE_and_acquire(addr, val)\n# define AO_HAVE_XSIZE_and_acquire_read\n#endif\n\n/* XSIZE_or */\n#if defined(AO_HAVE_XSIZE_compare_and_swap_full) \\\n    && !defined(AO_HAVE_XSIZE_or_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_XSIZE_or_full(volatile XCTYPE *addr, XCTYPE value)\n  {\n    XCTYPE old;\n\n    do\n      {\n        old = *(XCTYPE *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_XSIZE_compare_and_swap_full(addr, old,\n                                                           old | value)));\n  }\n# define AO_HAVE_XSIZE_or_full\n#endif\n\n#if defined(AO_HAVE_XSIZE_or_full)\n# if !defined(AO_HAVE_XSIZE_or_release)\n#   define AO_XSIZE_or_release(addr, val) AO_XSIZE_or_full(addr, val)\n#   define AO_HAVE_XSIZE_or_release\n# endif\n# if !defined(AO_HAVE_XSIZE_or_acquire)\n#   define AO_XSIZE_or_acquire(addr, val) AO_XSIZE_or_full(addr, val)\n#   define AO_HAVE_XSIZE_or_acquire\n# endif\n# if !defined(AO_HAVE_XSIZE_or_write)\n#   define AO_XSIZE_or_write(addr, val) AO_XSIZE_or_full(addr, val)\n#   define AO_HAVE_XSIZE_or_write\n# endif\n# if !defined(AO_HAVE_XSIZE_or_read)\n#   define AO_XSIZE_or_read(addr, val) AO_XSIZE_or_full(addr, val)\n#   define AO_HAVE_XSIZE_or_read\n# endif\n#endif /* AO_HAVE_XSIZE_or_full */\n\n#if !defined(AO_HAVE_XSIZE_or) && defined(AO_HAVE_XSIZE_or_release)\n# define AO_XSIZE_or(addr, val) AO_XSIZE_or_release(addr, val)\n# define AO_HAVE_XSIZE_or\n#endif\n#if !defined(AO_HAVE_XSIZE_or) && defined(AO_HAVE_XSIZE_or_acquire)\n# define AO_XSIZE_or(addr, val) AO_XSIZE_or_acquire(addr, val)\n# define AO_HAVE_XSIZE_or\n#endif\n#if !defined(AO_HAVE_XSIZE_or) && defined(AO_HAVE_XSIZE_or_write)\n# define AO_XSIZE_or(addr, val) AO_XSIZE_or_write(addr, val)\n# define AO_HAVE_XSIZE_or\n#endif\n#if !defined(AO_HAVE_XSIZE_or) && defined(AO_HAVE_XSIZE_or_read)\n# define AO_XSIZE_or(addr, val) AO_XSIZE_or_read(addr, val)\n# define AO_HAVE_XSIZE_or\n#endif\n\n#if defined(AO_HAVE_XSIZE_or_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_or_full)\n# define AO_XSIZE_or_full(addr, val) \\\n                        (AO_nop_full(), AO_XSIZE_or_acquire(addr, val))\n# define AO_HAVE_XSIZE_or_full\n#endif\n\n#if !defined(AO_HAVE_XSIZE_or_release_write) \\\n    && defined(AO_HAVE_XSIZE_or_write)\n# define AO_XSIZE_or_release_write(addr, val) AO_XSIZE_or_write(addr, val)\n# define AO_HAVE_XSIZE_or_release_write\n#endif\n#if !defined(AO_HAVE_XSIZE_or_release_write) \\\n    && defined(AO_HAVE_XSIZE_or_release)\n# define AO_XSIZE_or_release_write(addr, val) AO_XSIZE_or_release(addr, val)\n# define AO_HAVE_XSIZE_or_release_write\n#endif\n#if !defined(AO_HAVE_XSIZE_or_acquire_read) && defined(AO_HAVE_XSIZE_or_read)\n# define AO_XSIZE_or_acquire_read(addr, val) AO_XSIZE_or_read(addr, val)\n# define AO_HAVE_XSIZE_or_acquire_read\n#endif\n#if !defined(AO_HAVE_XSIZE_or_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_or_acquire)\n# define AO_XSIZE_or_acquire_read(addr, val) AO_XSIZE_or_acquire(addr, val)\n# define AO_HAVE_XSIZE_or_acquire_read\n#endif\n\n/* XSIZE_xor */\n#if defined(AO_HAVE_XSIZE_compare_and_swap_full) \\\n    && !defined(AO_HAVE_XSIZE_xor_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_XSIZE_xor_full(volatile XCTYPE *addr, XCTYPE value)\n  {\n    XCTYPE old;\n\n    do\n      {\n        old = *(XCTYPE *)addr;\n      }\n    while (AO_EXPECT_FALSE(!AO_XSIZE_compare_and_swap_full(addr, old,\n                                                           old ^ value)));\n  }\n# define AO_HAVE_XSIZE_xor_full\n#endif\n\n#if defined(AO_HAVE_XSIZE_xor_full)\n# if !defined(AO_HAVE_XSIZE_xor_release)\n#   define AO_XSIZE_xor_release(addr, val) AO_XSIZE_xor_full(addr, val)\n#   define AO_HAVE_XSIZE_xor_release\n# endif\n# if !defined(AO_HAVE_XSIZE_xor_acquire)\n#   define AO_XSIZE_xor_acquire(addr, val) AO_XSIZE_xor_full(addr, val)\n#   define AO_HAVE_XSIZE_xor_acquire\n# endif\n# if !defined(AO_HAVE_XSIZE_xor_write)\n#   define AO_XSIZE_xor_write(addr, val) AO_XSIZE_xor_full(addr, val)\n#   define AO_HAVE_XSIZE_xor_write\n# endif\n# if !defined(AO_HAVE_XSIZE_xor_read)\n#   define AO_XSIZE_xor_read(addr, val) AO_XSIZE_xor_full(addr, val)\n#   define AO_HAVE_XSIZE_xor_read\n# endif\n#endif /* AO_HAVE_XSIZE_xor_full */\n\n#if !defined(AO_HAVE_XSIZE_xor) && defined(AO_HAVE_XSIZE_xor_release)\n# define AO_XSIZE_xor(addr, val) AO_XSIZE_xor_release(addr, val)\n# define AO_HAVE_XSIZE_xor\n#endif\n#if !defined(AO_HAVE_XSIZE_xor) && defined(AO_HAVE_XSIZE_xor_acquire)\n# define AO_XSIZE_xor(addr, val) AO_XSIZE_xor_acquire(addr, val)\n# define AO_HAVE_XSIZE_xor\n#endif\n#if !defined(AO_HAVE_XSIZE_xor) && defined(AO_HAVE_XSIZE_xor_write)\n# define AO_XSIZE_xor(addr, val) AO_XSIZE_xor_write(addr, val)\n# define AO_HAVE_XSIZE_xor\n#endif\n#if !defined(AO_HAVE_XSIZE_xor) && defined(AO_HAVE_XSIZE_xor_read)\n# define AO_XSIZE_xor(addr, val) AO_XSIZE_xor_read(addr, val)\n# define AO_HAVE_XSIZE_xor\n#endif\n\n#if defined(AO_HAVE_XSIZE_xor_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_xor_full)\n# define AO_XSIZE_xor_full(addr, val) \\\n                        (AO_nop_full(), AO_XSIZE_xor_acquire(addr, val))\n# define AO_HAVE_XSIZE_xor_full\n#endif\n\n#if !defined(AO_HAVE_XSIZE_xor_release_write) \\\n    && defined(AO_HAVE_XSIZE_xor_write)\n# define AO_XSIZE_xor_release_write(addr, val) AO_XSIZE_xor_write(addr, val)\n# define AO_HAVE_XSIZE_xor_release_write\n#endif\n#if !defined(AO_HAVE_XSIZE_xor_release_write) \\\n    && defined(AO_HAVE_XSIZE_xor_release)\n# define AO_XSIZE_xor_release_write(addr, val) AO_XSIZE_xor_release(addr, val)\n# define AO_HAVE_XSIZE_xor_release_write\n#endif\n#if !defined(AO_HAVE_XSIZE_xor_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_xor_read)\n# define AO_XSIZE_xor_acquire_read(addr, val) AO_XSIZE_xor_read(addr, val)\n# define AO_HAVE_XSIZE_xor_acquire_read\n#endif\n#if !defined(AO_HAVE_XSIZE_xor_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_xor_acquire)\n# define AO_XSIZE_xor_acquire_read(addr, val) AO_XSIZE_xor_acquire(addr, val)\n# define AO_HAVE_XSIZE_xor_acquire_read\n#endif\n\n/* XSIZE_and/or/xor_dd_acquire_read are meaningless.    */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/generalize-small.h",
    "content": "/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* char_fetch_compare_and_swap */\n#if defined(AO_HAVE_char_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_fetch_compare_and_swap_acquire)\n  AO_INLINE unsigned/**/char\n  AO_char_fetch_compare_and_swap_acquire(volatile unsigned/**/char *addr,\n                                          unsigned/**/char old_val, unsigned/**/char new_val)\n  {\n    unsigned/**/char result = AO_char_fetch_compare_and_swap(addr, old_val, new_val);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_char_fetch_compare_and_swap_acquire\n#endif\n#if defined(AO_HAVE_char_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_fetch_compare_and_swap_release)\n# define AO_char_fetch_compare_and_swap_release(addr, old_val, new_val) \\\n                (AO_nop_full(), \\\n                 AO_char_fetch_compare_and_swap(addr, old_val, new_val))\n# define AO_HAVE_char_fetch_compare_and_swap_release\n#endif\n#if defined(AO_HAVE_char_fetch_compare_and_swap_full)\n# if !defined(AO_HAVE_char_fetch_compare_and_swap_release)\n#   define AO_char_fetch_compare_and_swap_release(addr, old_val, new_val) \\\n                AO_char_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_char_fetch_compare_and_swap_release\n# endif\n# if !defined(AO_HAVE_char_fetch_compare_and_swap_acquire)\n#   define AO_char_fetch_compare_and_swap_acquire(addr, old_val, new_val) \\\n                AO_char_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_char_fetch_compare_and_swap_acquire\n# endif\n# if !defined(AO_HAVE_char_fetch_compare_and_swap_write)\n#   define AO_char_fetch_compare_and_swap_write(addr, old_val, new_val) \\\n                AO_char_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_char_fetch_compare_and_swap_write\n# endif\n# if !defined(AO_HAVE_char_fetch_compare_and_swap_read)\n#   define AO_char_fetch_compare_and_swap_read(addr, old_val, new_val) \\\n                AO_char_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_char_fetch_compare_and_swap_read\n# endif\n#endif /* AO_HAVE_char_fetch_compare_and_swap_full */\n\n#if !defined(AO_HAVE_char_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_char_fetch_compare_and_swap_release)\n# define AO_char_fetch_compare_and_swap(addr, old_val, new_val) \\\n            AO_char_fetch_compare_and_swap_release(addr, old_val, new_val)\n# define AO_HAVE_char_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_char_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_char_fetch_compare_and_swap_acquire)\n# define AO_char_fetch_compare_and_swap(addr, old_val, new_val) \\\n            AO_char_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n# define AO_HAVE_char_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_char_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_char_fetch_compare_and_swap_write)\n# define AO_char_fetch_compare_and_swap(addr, old_val, new_val) \\\n                AO_char_fetch_compare_and_swap_write(addr, old_val, new_val)\n# define AO_HAVE_char_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_char_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_char_fetch_compare_and_swap_read)\n# define AO_char_fetch_compare_and_swap(addr, old_val, new_val) \\\n                AO_char_fetch_compare_and_swap_read(addr, old_val, new_val)\n# define AO_HAVE_char_fetch_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_char_fetch_compare_and_swap_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_fetch_compare_and_swap_full)\n# define AO_char_fetch_compare_and_swap_full(addr, old_val, new_val) \\\n            (AO_nop_full(), \\\n             AO_char_fetch_compare_and_swap_acquire(addr, old_val, new_val))\n# define AO_HAVE_char_fetch_compare_and_swap_full\n#endif\n\n#if !defined(AO_HAVE_char_fetch_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_char_fetch_compare_and_swap_write)\n# define AO_char_fetch_compare_and_swap_release_write(addr,old_val,new_val) \\\n                AO_char_fetch_compare_and_swap_write(addr, old_val, new_val)\n# define AO_HAVE_char_fetch_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_char_fetch_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_char_fetch_compare_and_swap_release)\n# define AO_char_fetch_compare_and_swap_release_write(addr,old_val,new_val) \\\n            AO_char_fetch_compare_and_swap_release(addr, old_val, new_val)\n# define AO_HAVE_char_fetch_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_char_fetch_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_char_fetch_compare_and_swap_read)\n# define AO_char_fetch_compare_and_swap_acquire_read(addr,old_val,new_val) \\\n                AO_char_fetch_compare_and_swap_read(addr, old_val, new_val)\n# define AO_HAVE_char_fetch_compare_and_swap_acquire_read\n#endif\n#if !defined(AO_HAVE_char_fetch_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_char_fetch_compare_and_swap_acquire)\n# define AO_char_fetch_compare_and_swap_acquire_read(addr,old_val,new_val) \\\n            AO_char_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n# define AO_HAVE_char_fetch_compare_and_swap_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_char_fetch_compare_and_swap_acquire_read)\n#   define AO_char_fetch_compare_and_swap_dd_acquire_read(addr,old_val,new_val) \\\n        AO_char_fetch_compare_and_swap_acquire_read(addr, old_val, new_val)\n#   define AO_HAVE_char_fetch_compare_and_swap_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_char_fetch_compare_and_swap)\n#   define AO_char_fetch_compare_and_swap_dd_acquire_read(addr,old_val,new_val) \\\n                AO_char_fetch_compare_and_swap(addr, old_val, new_val)\n#   define AO_HAVE_char_fetch_compare_and_swap_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* char_compare_and_swap */\n#if defined(AO_HAVE_char_compare_and_swap) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_compare_and_swap_acquire)\n  AO_INLINE int\n  AO_char_compare_and_swap_acquire(volatile unsigned/**/char *addr, unsigned/**/char old,\n                                    unsigned/**/char new_val)\n  {\n    int result = AO_char_compare_and_swap(addr, old, new_val);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_char_compare_and_swap_acquire\n#endif\n#if defined(AO_HAVE_char_compare_and_swap) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_compare_and_swap_release)\n# define AO_char_compare_and_swap_release(addr, old, new_val) \\\n                (AO_nop_full(), AO_char_compare_and_swap(addr, old, new_val))\n# define AO_HAVE_char_compare_and_swap_release\n#endif\n#if defined(AO_HAVE_char_compare_and_swap_full)\n# if !defined(AO_HAVE_char_compare_and_swap_release)\n#   define AO_char_compare_and_swap_release(addr, old, new_val) \\\n                AO_char_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_char_compare_and_swap_release\n# endif\n# if !defined(AO_HAVE_char_compare_and_swap_acquire)\n#   define AO_char_compare_and_swap_acquire(addr, old, new_val) \\\n                AO_char_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_char_compare_and_swap_acquire\n# endif\n# if !defined(AO_HAVE_char_compare_and_swap_write)\n#   define AO_char_compare_and_swap_write(addr, old, new_val) \\\n                AO_char_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_char_compare_and_swap_write\n# endif\n# if !defined(AO_HAVE_char_compare_and_swap_read)\n#   define AO_char_compare_and_swap_read(addr, old, new_val) \\\n                AO_char_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_char_compare_and_swap_read\n# endif\n#endif /* AO_HAVE_char_compare_and_swap_full */\n\n#if !defined(AO_HAVE_char_compare_and_swap) \\\n    && defined(AO_HAVE_char_compare_and_swap_release)\n# define AO_char_compare_and_swap(addr, old, new_val) \\\n                AO_char_compare_and_swap_release(addr, old, new_val)\n# define AO_HAVE_char_compare_and_swap\n#endif\n#if !defined(AO_HAVE_char_compare_and_swap) \\\n    && defined(AO_HAVE_char_compare_and_swap_acquire)\n# define AO_char_compare_and_swap(addr, old, new_val) \\\n                AO_char_compare_and_swap_acquire(addr, old, new_val)\n# define AO_HAVE_char_compare_and_swap\n#endif\n#if !defined(AO_HAVE_char_compare_and_swap) \\\n    && defined(AO_HAVE_char_compare_and_swap_write)\n# define AO_char_compare_and_swap(addr, old, new_val) \\\n                AO_char_compare_and_swap_write(addr, old, new_val)\n# define AO_HAVE_char_compare_and_swap\n#endif\n#if !defined(AO_HAVE_char_compare_and_swap) \\\n    && defined(AO_HAVE_char_compare_and_swap_read)\n# define AO_char_compare_and_swap(addr, old, new_val) \\\n                AO_char_compare_and_swap_read(addr, old, new_val)\n# define AO_HAVE_char_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_char_compare_and_swap_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_compare_and_swap_full)\n# define AO_char_compare_and_swap_full(addr, old, new_val) \\\n                (AO_nop_full(), \\\n                 AO_char_compare_and_swap_acquire(addr, old, new_val))\n# define AO_HAVE_char_compare_and_swap_full\n#endif\n\n#if !defined(AO_HAVE_char_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_char_compare_and_swap_write)\n# define AO_char_compare_and_swap_release_write(addr, old, new_val) \\\n                AO_char_compare_and_swap_write(addr, old, new_val)\n# define AO_HAVE_char_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_char_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_char_compare_and_swap_release)\n# define AO_char_compare_and_swap_release_write(addr, old, new_val) \\\n                AO_char_compare_and_swap_release(addr, old, new_val)\n# define AO_HAVE_char_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_char_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_char_compare_and_swap_read)\n# define AO_char_compare_and_swap_acquire_read(addr, old, new_val) \\\n                AO_char_compare_and_swap_read(addr, old, new_val)\n# define AO_HAVE_char_compare_and_swap_acquire_read\n#endif\n#if !defined(AO_HAVE_char_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_char_compare_and_swap_acquire)\n# define AO_char_compare_and_swap_acquire_read(addr, old, new_val) \\\n                AO_char_compare_and_swap_acquire(addr, old, new_val)\n# define AO_HAVE_char_compare_and_swap_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_char_compare_and_swap_acquire_read)\n#   define AO_char_compare_and_swap_dd_acquire_read(addr, old, new_val) \\\n                AO_char_compare_and_swap_acquire_read(addr, old, new_val)\n#   define AO_HAVE_char_compare_and_swap_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_char_compare_and_swap)\n#   define AO_char_compare_and_swap_dd_acquire_read(addr, old, new_val) \\\n                AO_char_compare_and_swap(addr, old, new_val)\n#   define AO_HAVE_char_compare_and_swap_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* char_load */\n#if defined(AO_HAVE_char_load_full) && !defined(AO_HAVE_char_load_acquire)\n# define AO_char_load_acquire(addr) AO_char_load_full(addr)\n# define AO_HAVE_char_load_acquire\n#endif\n\n#if defined(AO_HAVE_char_load_acquire) && !defined(AO_HAVE_char_load)\n# define AO_char_load(addr) AO_char_load_acquire(addr)\n# define AO_HAVE_char_load\n#endif\n\n#if defined(AO_HAVE_char_load_full) && !defined(AO_HAVE_char_load_read)\n# define AO_char_load_read(addr) AO_char_load_full(addr)\n# define AO_HAVE_char_load_read\n#endif\n\n#if !defined(AO_HAVE_char_load_acquire_read) \\\n    && defined(AO_HAVE_char_load_acquire)\n# define AO_char_load_acquire_read(addr) AO_char_load_acquire(addr)\n# define AO_HAVE_char_load_acquire_read\n#endif\n\n#if defined(AO_HAVE_char_load) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_load_acquire)\n  AO_INLINE unsigned/**/char\n  AO_char_load_acquire(const volatile unsigned/**/char *addr)\n  {\n    unsigned/**/char result = AO_char_load(addr);\n\n    /* Acquire barrier would be useless, since the load could be delayed    */\n    /* beyond it.                                                           */\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_char_load_acquire\n#endif\n\n#if defined(AO_HAVE_char_load) && defined(AO_HAVE_nop_read) \\\n    && !defined(AO_HAVE_char_load_read)\n  AO_INLINE unsigned/**/char\n  AO_char_load_read(const volatile unsigned/**/char *addr)\n  {\n    unsigned/**/char result = AO_char_load(addr);\n\n    AO_nop_read();\n    return result;\n  }\n# define AO_HAVE_char_load_read\n#endif\n\n#if defined(AO_HAVE_char_load_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_load_full)\n# define AO_char_load_full(addr) (AO_nop_full(), AO_char_load_acquire(addr))\n# define AO_HAVE_char_load_full\n#endif\n\n#if defined(AO_HAVE_char_compare_and_swap_read) \\\n    && !defined(AO_HAVE_char_load_read)\n# define AO_char_CAS_BASED_LOAD_READ\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/char\n  AO_char_load_read(const volatile unsigned/**/char *addr)\n  {\n    unsigned/**/char result;\n\n    do {\n      result = *(const unsigned/**/char *)addr;\n    } while (AO_EXPECT_FALSE(!AO_char_compare_and_swap_read(\n                                                (volatile unsigned/**/char *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_char_load_read\n#endif\n\n#if !defined(AO_HAVE_char_load_acquire_read) \\\n    && defined(AO_HAVE_char_load_read)\n# define AO_char_load_acquire_read(addr) AO_char_load_read(addr)\n# define AO_HAVE_char_load_acquire_read\n#endif\n\n#if defined(AO_HAVE_char_load_acquire_read) && !defined(AO_HAVE_char_load) \\\n    && (!defined(AO_char_CAS_BASED_LOAD_READ) \\\n        || !defined(AO_HAVE_char_compare_and_swap))\n# define AO_char_load(addr) AO_char_load_acquire_read(addr)\n# define AO_HAVE_char_load\n#endif\n\n#if defined(AO_HAVE_char_compare_and_swap_full) \\\n    && !defined(AO_HAVE_char_load_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/char\n  AO_char_load_full(const volatile unsigned/**/char *addr)\n  {\n    unsigned/**/char result;\n\n    do {\n      result = *(const unsigned/**/char *)addr;\n    } while (AO_EXPECT_FALSE(!AO_char_compare_and_swap_full(\n                                                (volatile unsigned/**/char *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_char_load_full\n#endif\n\n#if defined(AO_HAVE_char_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_char_load_acquire)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/char\n  AO_char_load_acquire(const volatile unsigned/**/char *addr)\n  {\n    unsigned/**/char result;\n\n    do {\n      result = *(const unsigned/**/char *)addr;\n    } while (AO_EXPECT_FALSE(!AO_char_compare_and_swap_acquire(\n                                                (volatile unsigned/**/char *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_char_load_acquire\n#endif\n\n#if defined(AO_HAVE_char_compare_and_swap) && !defined(AO_HAVE_char_load)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/char\n  AO_char_load(const volatile unsigned/**/char *addr)\n  {\n    unsigned/**/char result;\n\n    do {\n      result = *(const unsigned/**/char *)addr;\n    } while (AO_EXPECT_FALSE(!AO_char_compare_and_swap(\n                                                (volatile unsigned/**/char *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_char_load\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_char_load_acquire_read)\n#   define AO_char_load_dd_acquire_read(addr) \\\n                                AO_char_load_acquire_read(addr)\n#   define AO_HAVE_char_load_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_char_load)\n#   define AO_char_load_dd_acquire_read(addr) AO_char_load(addr)\n#   define AO_HAVE_char_load_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* char_store */\n#if defined(AO_HAVE_char_store_full) && !defined(AO_HAVE_char_store_release)\n# define AO_char_store_release(addr, val) AO_char_store_full(addr, val)\n# define AO_HAVE_char_store_release\n#endif\n\n#if defined(AO_HAVE_char_store_release) && !defined(AO_HAVE_char_store)\n# define AO_char_store(addr, val) AO_char_store_release(addr, val)\n# define AO_HAVE_char_store\n#endif\n\n#if defined(AO_HAVE_char_store_full) && !defined(AO_HAVE_char_store_write)\n# define AO_char_store_write(addr, val) AO_char_store_full(addr, val)\n# define AO_HAVE_char_store_write\n#endif\n\n#if defined(AO_HAVE_char_store_release) \\\n    && !defined(AO_HAVE_char_store_release_write)\n# define AO_char_store_release_write(addr, val) \\\n                                AO_char_store_release(addr, val)\n# define AO_HAVE_char_store_release_write\n#endif\n\n#if defined(AO_HAVE_char_store_write) && !defined(AO_HAVE_char_store)\n# define AO_char_store(addr, val) AO_char_store_write(addr, val)\n# define AO_HAVE_char_store\n#endif\n\n#if defined(AO_HAVE_char_store) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_store_release)\n# define AO_char_store_release(addr, val) \\\n                                (AO_nop_full(), AO_char_store(addr, val))\n# define AO_HAVE_char_store_release\n#endif\n\n#if defined(AO_HAVE_char_store) && defined(AO_HAVE_nop_write) \\\n    && !defined(AO_HAVE_char_store_write)\n# define AO_char_store_write(addr, val) \\\n                                (AO_nop_write(), AO_char_store(addr, val))\n# define AO_HAVE_char_store_write\n#endif\n\n#if defined(AO_HAVE_char_compare_and_swap_write) \\\n    && !defined(AO_HAVE_char_store_write)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_char_store_write(volatile unsigned/**/char *addr, unsigned/**/char new_val)\n  {\n    unsigned/**/char old_val;\n\n    do {\n      old_val = *(unsigned/**/char *)addr;\n    } while (AO_EXPECT_FALSE(!AO_char_compare_and_swap_write(addr, old_val,\n                                                              new_val)));\n  }\n# define AO_HAVE_char_store_write\n#endif\n\n#if defined(AO_HAVE_char_store_write) \\\n    && !defined(AO_HAVE_char_store_release_write)\n# define AO_char_store_release_write(addr, val) \\\n                                AO_char_store_write(addr, val)\n# define AO_HAVE_char_store_release_write\n#endif\n\n#if defined(AO_HAVE_char_store_release) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_char_store_full)\n# define AO_char_store_full(addr, val) \\\n                                (AO_char_store_release(addr, val), \\\n                                 AO_nop_full())\n# define AO_HAVE_char_store_full\n#endif\n\n#if defined(AO_HAVE_char_compare_and_swap) && !defined(AO_HAVE_char_store)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_char_store(volatile unsigned/**/char *addr, unsigned/**/char new_val)\n  {\n    unsigned/**/char old_val;\n\n    do {\n      old_val = *(unsigned/**/char *)addr;\n    } while (AO_EXPECT_FALSE(!AO_char_compare_and_swap(addr,\n                                                        old_val, new_val)));\n  }\n# define AO_HAVE_char_store\n#endif\n\n#if defined(AO_HAVE_char_compare_and_swap_release) \\\n    && !defined(AO_HAVE_char_store_release)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_char_store_release(volatile unsigned/**/char *addr, unsigned/**/char new_val)\n  {\n    unsigned/**/char old_val;\n\n    do {\n      old_val = *(unsigned/**/char *)addr;\n    } while (AO_EXPECT_FALSE(!AO_char_compare_and_swap_release(addr, old_val,\n                                                                new_val)));\n  }\n# define AO_HAVE_char_store_release\n#endif\n\n#if defined(AO_HAVE_char_compare_and_swap_full) \\\n    && !defined(AO_HAVE_char_store_full)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_char_store_full(volatile unsigned/**/char *addr, unsigned/**/char new_val)\n  {\n    unsigned/**/char old_val;\n\n    do {\n      old_val = *(unsigned/**/char *)addr;\n    } while (AO_EXPECT_FALSE(!AO_char_compare_and_swap_full(addr, old_val,\n                                                             new_val)));\n  }\n# define AO_HAVE_char_store_full\n#endif\n/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* short_fetch_compare_and_swap */\n#if defined(AO_HAVE_short_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_fetch_compare_and_swap_acquire)\n  AO_INLINE unsigned/**/short\n  AO_short_fetch_compare_and_swap_acquire(volatile unsigned/**/short *addr,\n                                          unsigned/**/short old_val, unsigned/**/short new_val)\n  {\n    unsigned/**/short result = AO_short_fetch_compare_and_swap(addr, old_val, new_val);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_short_fetch_compare_and_swap_acquire\n#endif\n#if defined(AO_HAVE_short_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_fetch_compare_and_swap_release)\n# define AO_short_fetch_compare_and_swap_release(addr, old_val, new_val) \\\n                (AO_nop_full(), \\\n                 AO_short_fetch_compare_and_swap(addr, old_val, new_val))\n# define AO_HAVE_short_fetch_compare_and_swap_release\n#endif\n#if defined(AO_HAVE_short_fetch_compare_and_swap_full)\n# if !defined(AO_HAVE_short_fetch_compare_and_swap_release)\n#   define AO_short_fetch_compare_and_swap_release(addr, old_val, new_val) \\\n                AO_short_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_short_fetch_compare_and_swap_release\n# endif\n# if !defined(AO_HAVE_short_fetch_compare_and_swap_acquire)\n#   define AO_short_fetch_compare_and_swap_acquire(addr, old_val, new_val) \\\n                AO_short_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_short_fetch_compare_and_swap_acquire\n# endif\n# if !defined(AO_HAVE_short_fetch_compare_and_swap_write)\n#   define AO_short_fetch_compare_and_swap_write(addr, old_val, new_val) \\\n                AO_short_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_short_fetch_compare_and_swap_write\n# endif\n# if !defined(AO_HAVE_short_fetch_compare_and_swap_read)\n#   define AO_short_fetch_compare_and_swap_read(addr, old_val, new_val) \\\n                AO_short_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_short_fetch_compare_and_swap_read\n# endif\n#endif /* AO_HAVE_short_fetch_compare_and_swap_full */\n\n#if !defined(AO_HAVE_short_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_short_fetch_compare_and_swap_release)\n# define AO_short_fetch_compare_and_swap(addr, old_val, new_val) \\\n            AO_short_fetch_compare_and_swap_release(addr, old_val, new_val)\n# define AO_HAVE_short_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_short_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_short_fetch_compare_and_swap_acquire)\n# define AO_short_fetch_compare_and_swap(addr, old_val, new_val) \\\n            AO_short_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n# define AO_HAVE_short_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_short_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_short_fetch_compare_and_swap_write)\n# define AO_short_fetch_compare_and_swap(addr, old_val, new_val) \\\n                AO_short_fetch_compare_and_swap_write(addr, old_val, new_val)\n# define AO_HAVE_short_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_short_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_short_fetch_compare_and_swap_read)\n# define AO_short_fetch_compare_and_swap(addr, old_val, new_val) \\\n                AO_short_fetch_compare_and_swap_read(addr, old_val, new_val)\n# define AO_HAVE_short_fetch_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_short_fetch_compare_and_swap_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_fetch_compare_and_swap_full)\n# define AO_short_fetch_compare_and_swap_full(addr, old_val, new_val) \\\n            (AO_nop_full(), \\\n             AO_short_fetch_compare_and_swap_acquire(addr, old_val, new_val))\n# define AO_HAVE_short_fetch_compare_and_swap_full\n#endif\n\n#if !defined(AO_HAVE_short_fetch_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_short_fetch_compare_and_swap_write)\n# define AO_short_fetch_compare_and_swap_release_write(addr,old_val,new_val) \\\n                AO_short_fetch_compare_and_swap_write(addr, old_val, new_val)\n# define AO_HAVE_short_fetch_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_short_fetch_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_short_fetch_compare_and_swap_release)\n# define AO_short_fetch_compare_and_swap_release_write(addr,old_val,new_val) \\\n            AO_short_fetch_compare_and_swap_release(addr, old_val, new_val)\n# define AO_HAVE_short_fetch_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_short_fetch_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_short_fetch_compare_and_swap_read)\n# define AO_short_fetch_compare_and_swap_acquire_read(addr,old_val,new_val) \\\n                AO_short_fetch_compare_and_swap_read(addr, old_val, new_val)\n# define AO_HAVE_short_fetch_compare_and_swap_acquire_read\n#endif\n#if !defined(AO_HAVE_short_fetch_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_short_fetch_compare_and_swap_acquire)\n# define AO_short_fetch_compare_and_swap_acquire_read(addr,old_val,new_val) \\\n            AO_short_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n# define AO_HAVE_short_fetch_compare_and_swap_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_short_fetch_compare_and_swap_acquire_read)\n#   define AO_short_fetch_compare_and_swap_dd_acquire_read(addr,old_val,new_val) \\\n        AO_short_fetch_compare_and_swap_acquire_read(addr, old_val, new_val)\n#   define AO_HAVE_short_fetch_compare_and_swap_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_short_fetch_compare_and_swap)\n#   define AO_short_fetch_compare_and_swap_dd_acquire_read(addr,old_val,new_val) \\\n                AO_short_fetch_compare_and_swap(addr, old_val, new_val)\n#   define AO_HAVE_short_fetch_compare_and_swap_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* short_compare_and_swap */\n#if defined(AO_HAVE_short_compare_and_swap) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_compare_and_swap_acquire)\n  AO_INLINE int\n  AO_short_compare_and_swap_acquire(volatile unsigned/**/short *addr, unsigned/**/short old,\n                                    unsigned/**/short new_val)\n  {\n    int result = AO_short_compare_and_swap(addr, old, new_val);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_short_compare_and_swap_acquire\n#endif\n#if defined(AO_HAVE_short_compare_and_swap) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_compare_and_swap_release)\n# define AO_short_compare_and_swap_release(addr, old, new_val) \\\n                (AO_nop_full(), AO_short_compare_and_swap(addr, old, new_val))\n# define AO_HAVE_short_compare_and_swap_release\n#endif\n#if defined(AO_HAVE_short_compare_and_swap_full)\n# if !defined(AO_HAVE_short_compare_and_swap_release)\n#   define AO_short_compare_and_swap_release(addr, old, new_val) \\\n                AO_short_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_short_compare_and_swap_release\n# endif\n# if !defined(AO_HAVE_short_compare_and_swap_acquire)\n#   define AO_short_compare_and_swap_acquire(addr, old, new_val) \\\n                AO_short_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_short_compare_and_swap_acquire\n# endif\n# if !defined(AO_HAVE_short_compare_and_swap_write)\n#   define AO_short_compare_and_swap_write(addr, old, new_val) \\\n                AO_short_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_short_compare_and_swap_write\n# endif\n# if !defined(AO_HAVE_short_compare_and_swap_read)\n#   define AO_short_compare_and_swap_read(addr, old, new_val) \\\n                AO_short_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_short_compare_and_swap_read\n# endif\n#endif /* AO_HAVE_short_compare_and_swap_full */\n\n#if !defined(AO_HAVE_short_compare_and_swap) \\\n    && defined(AO_HAVE_short_compare_and_swap_release)\n# define AO_short_compare_and_swap(addr, old, new_val) \\\n                AO_short_compare_and_swap_release(addr, old, new_val)\n# define AO_HAVE_short_compare_and_swap\n#endif\n#if !defined(AO_HAVE_short_compare_and_swap) \\\n    && defined(AO_HAVE_short_compare_and_swap_acquire)\n# define AO_short_compare_and_swap(addr, old, new_val) \\\n                AO_short_compare_and_swap_acquire(addr, old, new_val)\n# define AO_HAVE_short_compare_and_swap\n#endif\n#if !defined(AO_HAVE_short_compare_and_swap) \\\n    && defined(AO_HAVE_short_compare_and_swap_write)\n# define AO_short_compare_and_swap(addr, old, new_val) \\\n                AO_short_compare_and_swap_write(addr, old, new_val)\n# define AO_HAVE_short_compare_and_swap\n#endif\n#if !defined(AO_HAVE_short_compare_and_swap) \\\n    && defined(AO_HAVE_short_compare_and_swap_read)\n# define AO_short_compare_and_swap(addr, old, new_val) \\\n                AO_short_compare_and_swap_read(addr, old, new_val)\n# define AO_HAVE_short_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_short_compare_and_swap_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_compare_and_swap_full)\n# define AO_short_compare_and_swap_full(addr, old, new_val) \\\n                (AO_nop_full(), \\\n                 AO_short_compare_and_swap_acquire(addr, old, new_val))\n# define AO_HAVE_short_compare_and_swap_full\n#endif\n\n#if !defined(AO_HAVE_short_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_short_compare_and_swap_write)\n# define AO_short_compare_and_swap_release_write(addr, old, new_val) \\\n                AO_short_compare_and_swap_write(addr, old, new_val)\n# define AO_HAVE_short_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_short_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_short_compare_and_swap_release)\n# define AO_short_compare_and_swap_release_write(addr, old, new_val) \\\n                AO_short_compare_and_swap_release(addr, old, new_val)\n# define AO_HAVE_short_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_short_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_short_compare_and_swap_read)\n# define AO_short_compare_and_swap_acquire_read(addr, old, new_val) \\\n                AO_short_compare_and_swap_read(addr, old, new_val)\n# define AO_HAVE_short_compare_and_swap_acquire_read\n#endif\n#if !defined(AO_HAVE_short_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_short_compare_and_swap_acquire)\n# define AO_short_compare_and_swap_acquire_read(addr, old, new_val) \\\n                AO_short_compare_and_swap_acquire(addr, old, new_val)\n# define AO_HAVE_short_compare_and_swap_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_short_compare_and_swap_acquire_read)\n#   define AO_short_compare_and_swap_dd_acquire_read(addr, old, new_val) \\\n                AO_short_compare_and_swap_acquire_read(addr, old, new_val)\n#   define AO_HAVE_short_compare_and_swap_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_short_compare_and_swap)\n#   define AO_short_compare_and_swap_dd_acquire_read(addr, old, new_val) \\\n                AO_short_compare_and_swap(addr, old, new_val)\n#   define AO_HAVE_short_compare_and_swap_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* short_load */\n#if defined(AO_HAVE_short_load_full) && !defined(AO_HAVE_short_load_acquire)\n# define AO_short_load_acquire(addr) AO_short_load_full(addr)\n# define AO_HAVE_short_load_acquire\n#endif\n\n#if defined(AO_HAVE_short_load_acquire) && !defined(AO_HAVE_short_load)\n# define AO_short_load(addr) AO_short_load_acquire(addr)\n# define AO_HAVE_short_load\n#endif\n\n#if defined(AO_HAVE_short_load_full) && !defined(AO_HAVE_short_load_read)\n# define AO_short_load_read(addr) AO_short_load_full(addr)\n# define AO_HAVE_short_load_read\n#endif\n\n#if !defined(AO_HAVE_short_load_acquire_read) \\\n    && defined(AO_HAVE_short_load_acquire)\n# define AO_short_load_acquire_read(addr) AO_short_load_acquire(addr)\n# define AO_HAVE_short_load_acquire_read\n#endif\n\n#if defined(AO_HAVE_short_load) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_load_acquire)\n  AO_INLINE unsigned/**/short\n  AO_short_load_acquire(const volatile unsigned/**/short *addr)\n  {\n    unsigned/**/short result = AO_short_load(addr);\n\n    /* Acquire barrier would be useless, since the load could be delayed    */\n    /* beyond it.                                                           */\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_short_load_acquire\n#endif\n\n#if defined(AO_HAVE_short_load) && defined(AO_HAVE_nop_read) \\\n    && !defined(AO_HAVE_short_load_read)\n  AO_INLINE unsigned/**/short\n  AO_short_load_read(const volatile unsigned/**/short *addr)\n  {\n    unsigned/**/short result = AO_short_load(addr);\n\n    AO_nop_read();\n    return result;\n  }\n# define AO_HAVE_short_load_read\n#endif\n\n#if defined(AO_HAVE_short_load_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_load_full)\n# define AO_short_load_full(addr) (AO_nop_full(), AO_short_load_acquire(addr))\n# define AO_HAVE_short_load_full\n#endif\n\n#if defined(AO_HAVE_short_compare_and_swap_read) \\\n    && !defined(AO_HAVE_short_load_read)\n# define AO_short_CAS_BASED_LOAD_READ\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/short\n  AO_short_load_read(const volatile unsigned/**/short *addr)\n  {\n    unsigned/**/short result;\n\n    do {\n      result = *(const unsigned/**/short *)addr;\n    } while (AO_EXPECT_FALSE(!AO_short_compare_and_swap_read(\n                                                (volatile unsigned/**/short *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_short_load_read\n#endif\n\n#if !defined(AO_HAVE_short_load_acquire_read) \\\n    && defined(AO_HAVE_short_load_read)\n# define AO_short_load_acquire_read(addr) AO_short_load_read(addr)\n# define AO_HAVE_short_load_acquire_read\n#endif\n\n#if defined(AO_HAVE_short_load_acquire_read) && !defined(AO_HAVE_short_load) \\\n    && (!defined(AO_short_CAS_BASED_LOAD_READ) \\\n        || !defined(AO_HAVE_short_compare_and_swap))\n# define AO_short_load(addr) AO_short_load_acquire_read(addr)\n# define AO_HAVE_short_load\n#endif\n\n#if defined(AO_HAVE_short_compare_and_swap_full) \\\n    && !defined(AO_HAVE_short_load_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/short\n  AO_short_load_full(const volatile unsigned/**/short *addr)\n  {\n    unsigned/**/short result;\n\n    do {\n      result = *(const unsigned/**/short *)addr;\n    } while (AO_EXPECT_FALSE(!AO_short_compare_and_swap_full(\n                                                (volatile unsigned/**/short *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_short_load_full\n#endif\n\n#if defined(AO_HAVE_short_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_short_load_acquire)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/short\n  AO_short_load_acquire(const volatile unsigned/**/short *addr)\n  {\n    unsigned/**/short result;\n\n    do {\n      result = *(const unsigned/**/short *)addr;\n    } while (AO_EXPECT_FALSE(!AO_short_compare_and_swap_acquire(\n                                                (volatile unsigned/**/short *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_short_load_acquire\n#endif\n\n#if defined(AO_HAVE_short_compare_and_swap) && !defined(AO_HAVE_short_load)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned/**/short\n  AO_short_load(const volatile unsigned/**/short *addr)\n  {\n    unsigned/**/short result;\n\n    do {\n      result = *(const unsigned/**/short *)addr;\n    } while (AO_EXPECT_FALSE(!AO_short_compare_and_swap(\n                                                (volatile unsigned/**/short *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_short_load\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_short_load_acquire_read)\n#   define AO_short_load_dd_acquire_read(addr) \\\n                                AO_short_load_acquire_read(addr)\n#   define AO_HAVE_short_load_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_short_load)\n#   define AO_short_load_dd_acquire_read(addr) AO_short_load(addr)\n#   define AO_HAVE_short_load_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* short_store */\n#if defined(AO_HAVE_short_store_full) && !defined(AO_HAVE_short_store_release)\n# define AO_short_store_release(addr, val) AO_short_store_full(addr, val)\n# define AO_HAVE_short_store_release\n#endif\n\n#if defined(AO_HAVE_short_store_release) && !defined(AO_HAVE_short_store)\n# define AO_short_store(addr, val) AO_short_store_release(addr, val)\n# define AO_HAVE_short_store\n#endif\n\n#if defined(AO_HAVE_short_store_full) && !defined(AO_HAVE_short_store_write)\n# define AO_short_store_write(addr, val) AO_short_store_full(addr, val)\n# define AO_HAVE_short_store_write\n#endif\n\n#if defined(AO_HAVE_short_store_release) \\\n    && !defined(AO_HAVE_short_store_release_write)\n# define AO_short_store_release_write(addr, val) \\\n                                AO_short_store_release(addr, val)\n# define AO_HAVE_short_store_release_write\n#endif\n\n#if defined(AO_HAVE_short_store_write) && !defined(AO_HAVE_short_store)\n# define AO_short_store(addr, val) AO_short_store_write(addr, val)\n# define AO_HAVE_short_store\n#endif\n\n#if defined(AO_HAVE_short_store) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_store_release)\n# define AO_short_store_release(addr, val) \\\n                                (AO_nop_full(), AO_short_store(addr, val))\n# define AO_HAVE_short_store_release\n#endif\n\n#if defined(AO_HAVE_short_store) && defined(AO_HAVE_nop_write) \\\n    && !defined(AO_HAVE_short_store_write)\n# define AO_short_store_write(addr, val) \\\n                                (AO_nop_write(), AO_short_store(addr, val))\n# define AO_HAVE_short_store_write\n#endif\n\n#if defined(AO_HAVE_short_compare_and_swap_write) \\\n    && !defined(AO_HAVE_short_store_write)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_short_store_write(volatile unsigned/**/short *addr, unsigned/**/short new_val)\n  {\n    unsigned/**/short old_val;\n\n    do {\n      old_val = *(unsigned/**/short *)addr;\n    } while (AO_EXPECT_FALSE(!AO_short_compare_and_swap_write(addr, old_val,\n                                                              new_val)));\n  }\n# define AO_HAVE_short_store_write\n#endif\n\n#if defined(AO_HAVE_short_store_write) \\\n    && !defined(AO_HAVE_short_store_release_write)\n# define AO_short_store_release_write(addr, val) \\\n                                AO_short_store_write(addr, val)\n# define AO_HAVE_short_store_release_write\n#endif\n\n#if defined(AO_HAVE_short_store_release) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_short_store_full)\n# define AO_short_store_full(addr, val) \\\n                                (AO_short_store_release(addr, val), \\\n                                 AO_nop_full())\n# define AO_HAVE_short_store_full\n#endif\n\n#if defined(AO_HAVE_short_compare_and_swap) && !defined(AO_HAVE_short_store)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_short_store(volatile unsigned/**/short *addr, unsigned/**/short new_val)\n  {\n    unsigned/**/short old_val;\n\n    do {\n      old_val = *(unsigned/**/short *)addr;\n    } while (AO_EXPECT_FALSE(!AO_short_compare_and_swap(addr,\n                                                        old_val, new_val)));\n  }\n# define AO_HAVE_short_store\n#endif\n\n#if defined(AO_HAVE_short_compare_and_swap_release) \\\n    && !defined(AO_HAVE_short_store_release)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_short_store_release(volatile unsigned/**/short *addr, unsigned/**/short new_val)\n  {\n    unsigned/**/short old_val;\n\n    do {\n      old_val = *(unsigned/**/short *)addr;\n    } while (AO_EXPECT_FALSE(!AO_short_compare_and_swap_release(addr, old_val,\n                                                                new_val)));\n  }\n# define AO_HAVE_short_store_release\n#endif\n\n#if defined(AO_HAVE_short_compare_and_swap_full) \\\n    && !defined(AO_HAVE_short_store_full)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_short_store_full(volatile unsigned/**/short *addr, unsigned/**/short new_val)\n  {\n    unsigned/**/short old_val;\n\n    do {\n      old_val = *(unsigned/**/short *)addr;\n    } while (AO_EXPECT_FALSE(!AO_short_compare_and_swap_full(addr, old_val,\n                                                             new_val)));\n  }\n# define AO_HAVE_short_store_full\n#endif\n/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* int_fetch_compare_and_swap */\n#if defined(AO_HAVE_int_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_fetch_compare_and_swap_acquire)\n  AO_INLINE unsigned\n  AO_int_fetch_compare_and_swap_acquire(volatile unsigned *addr,\n                                          unsigned old_val, unsigned new_val)\n  {\n    unsigned result = AO_int_fetch_compare_and_swap(addr, old_val, new_val);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_int_fetch_compare_and_swap_acquire\n#endif\n#if defined(AO_HAVE_int_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_fetch_compare_and_swap_release)\n# define AO_int_fetch_compare_and_swap_release(addr, old_val, new_val) \\\n                (AO_nop_full(), \\\n                 AO_int_fetch_compare_and_swap(addr, old_val, new_val))\n# define AO_HAVE_int_fetch_compare_and_swap_release\n#endif\n#if defined(AO_HAVE_int_fetch_compare_and_swap_full)\n# if !defined(AO_HAVE_int_fetch_compare_and_swap_release)\n#   define AO_int_fetch_compare_and_swap_release(addr, old_val, new_val) \\\n                AO_int_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_int_fetch_compare_and_swap_release\n# endif\n# if !defined(AO_HAVE_int_fetch_compare_and_swap_acquire)\n#   define AO_int_fetch_compare_and_swap_acquire(addr, old_val, new_val) \\\n                AO_int_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_int_fetch_compare_and_swap_acquire\n# endif\n# if !defined(AO_HAVE_int_fetch_compare_and_swap_write)\n#   define AO_int_fetch_compare_and_swap_write(addr, old_val, new_val) \\\n                AO_int_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_int_fetch_compare_and_swap_write\n# endif\n# if !defined(AO_HAVE_int_fetch_compare_and_swap_read)\n#   define AO_int_fetch_compare_and_swap_read(addr, old_val, new_val) \\\n                AO_int_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_int_fetch_compare_and_swap_read\n# endif\n#endif /* AO_HAVE_int_fetch_compare_and_swap_full */\n\n#if !defined(AO_HAVE_int_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_int_fetch_compare_and_swap_release)\n# define AO_int_fetch_compare_and_swap(addr, old_val, new_val) \\\n            AO_int_fetch_compare_and_swap_release(addr, old_val, new_val)\n# define AO_HAVE_int_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_int_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_int_fetch_compare_and_swap_acquire)\n# define AO_int_fetch_compare_and_swap(addr, old_val, new_val) \\\n            AO_int_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n# define AO_HAVE_int_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_int_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_int_fetch_compare_and_swap_write)\n# define AO_int_fetch_compare_and_swap(addr, old_val, new_val) \\\n                AO_int_fetch_compare_and_swap_write(addr, old_val, new_val)\n# define AO_HAVE_int_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_int_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_int_fetch_compare_and_swap_read)\n# define AO_int_fetch_compare_and_swap(addr, old_val, new_val) \\\n                AO_int_fetch_compare_and_swap_read(addr, old_val, new_val)\n# define AO_HAVE_int_fetch_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_int_fetch_compare_and_swap_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_fetch_compare_and_swap_full)\n# define AO_int_fetch_compare_and_swap_full(addr, old_val, new_val) \\\n            (AO_nop_full(), \\\n             AO_int_fetch_compare_and_swap_acquire(addr, old_val, new_val))\n# define AO_HAVE_int_fetch_compare_and_swap_full\n#endif\n\n#if !defined(AO_HAVE_int_fetch_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_int_fetch_compare_and_swap_write)\n# define AO_int_fetch_compare_and_swap_release_write(addr,old_val,new_val) \\\n                AO_int_fetch_compare_and_swap_write(addr, old_val, new_val)\n# define AO_HAVE_int_fetch_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_int_fetch_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_int_fetch_compare_and_swap_release)\n# define AO_int_fetch_compare_and_swap_release_write(addr,old_val,new_val) \\\n            AO_int_fetch_compare_and_swap_release(addr, old_val, new_val)\n# define AO_HAVE_int_fetch_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_int_fetch_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_int_fetch_compare_and_swap_read)\n# define AO_int_fetch_compare_and_swap_acquire_read(addr,old_val,new_val) \\\n                AO_int_fetch_compare_and_swap_read(addr, old_val, new_val)\n# define AO_HAVE_int_fetch_compare_and_swap_acquire_read\n#endif\n#if !defined(AO_HAVE_int_fetch_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_int_fetch_compare_and_swap_acquire)\n# define AO_int_fetch_compare_and_swap_acquire_read(addr,old_val,new_val) \\\n            AO_int_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n# define AO_HAVE_int_fetch_compare_and_swap_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_int_fetch_compare_and_swap_acquire_read)\n#   define AO_int_fetch_compare_and_swap_dd_acquire_read(addr,old_val,new_val) \\\n        AO_int_fetch_compare_and_swap_acquire_read(addr, old_val, new_val)\n#   define AO_HAVE_int_fetch_compare_and_swap_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_int_fetch_compare_and_swap)\n#   define AO_int_fetch_compare_and_swap_dd_acquire_read(addr,old_val,new_val) \\\n                AO_int_fetch_compare_and_swap(addr, old_val, new_val)\n#   define AO_HAVE_int_fetch_compare_and_swap_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* int_compare_and_swap */\n#if defined(AO_HAVE_int_compare_and_swap) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_compare_and_swap_acquire)\n  AO_INLINE int\n  AO_int_compare_and_swap_acquire(volatile unsigned *addr, unsigned old,\n                                    unsigned new_val)\n  {\n    int result = AO_int_compare_and_swap(addr, old, new_val);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_int_compare_and_swap_acquire\n#endif\n#if defined(AO_HAVE_int_compare_and_swap) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_compare_and_swap_release)\n# define AO_int_compare_and_swap_release(addr, old, new_val) \\\n                (AO_nop_full(), AO_int_compare_and_swap(addr, old, new_val))\n# define AO_HAVE_int_compare_and_swap_release\n#endif\n#if defined(AO_HAVE_int_compare_and_swap_full)\n# if !defined(AO_HAVE_int_compare_and_swap_release)\n#   define AO_int_compare_and_swap_release(addr, old, new_val) \\\n                AO_int_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_int_compare_and_swap_release\n# endif\n# if !defined(AO_HAVE_int_compare_and_swap_acquire)\n#   define AO_int_compare_and_swap_acquire(addr, old, new_val) \\\n                AO_int_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_int_compare_and_swap_acquire\n# endif\n# if !defined(AO_HAVE_int_compare_and_swap_write)\n#   define AO_int_compare_and_swap_write(addr, old, new_val) \\\n                AO_int_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_int_compare_and_swap_write\n# endif\n# if !defined(AO_HAVE_int_compare_and_swap_read)\n#   define AO_int_compare_and_swap_read(addr, old, new_val) \\\n                AO_int_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_int_compare_and_swap_read\n# endif\n#endif /* AO_HAVE_int_compare_and_swap_full */\n\n#if !defined(AO_HAVE_int_compare_and_swap) \\\n    && defined(AO_HAVE_int_compare_and_swap_release)\n# define AO_int_compare_and_swap(addr, old, new_val) \\\n                AO_int_compare_and_swap_release(addr, old, new_val)\n# define AO_HAVE_int_compare_and_swap\n#endif\n#if !defined(AO_HAVE_int_compare_and_swap) \\\n    && defined(AO_HAVE_int_compare_and_swap_acquire)\n# define AO_int_compare_and_swap(addr, old, new_val) \\\n                AO_int_compare_and_swap_acquire(addr, old, new_val)\n# define AO_HAVE_int_compare_and_swap\n#endif\n#if !defined(AO_HAVE_int_compare_and_swap) \\\n    && defined(AO_HAVE_int_compare_and_swap_write)\n# define AO_int_compare_and_swap(addr, old, new_val) \\\n                AO_int_compare_and_swap_write(addr, old, new_val)\n# define AO_HAVE_int_compare_and_swap\n#endif\n#if !defined(AO_HAVE_int_compare_and_swap) \\\n    && defined(AO_HAVE_int_compare_and_swap_read)\n# define AO_int_compare_and_swap(addr, old, new_val) \\\n                AO_int_compare_and_swap_read(addr, old, new_val)\n# define AO_HAVE_int_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_int_compare_and_swap_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_compare_and_swap_full)\n# define AO_int_compare_and_swap_full(addr, old, new_val) \\\n                (AO_nop_full(), \\\n                 AO_int_compare_and_swap_acquire(addr, old, new_val))\n# define AO_HAVE_int_compare_and_swap_full\n#endif\n\n#if !defined(AO_HAVE_int_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_int_compare_and_swap_write)\n# define AO_int_compare_and_swap_release_write(addr, old, new_val) \\\n                AO_int_compare_and_swap_write(addr, old, new_val)\n# define AO_HAVE_int_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_int_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_int_compare_and_swap_release)\n# define AO_int_compare_and_swap_release_write(addr, old, new_val) \\\n                AO_int_compare_and_swap_release(addr, old, new_val)\n# define AO_HAVE_int_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_int_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_int_compare_and_swap_read)\n# define AO_int_compare_and_swap_acquire_read(addr, old, new_val) \\\n                AO_int_compare_and_swap_read(addr, old, new_val)\n# define AO_HAVE_int_compare_and_swap_acquire_read\n#endif\n#if !defined(AO_HAVE_int_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_int_compare_and_swap_acquire)\n# define AO_int_compare_and_swap_acquire_read(addr, old, new_val) \\\n                AO_int_compare_and_swap_acquire(addr, old, new_val)\n# define AO_HAVE_int_compare_and_swap_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_int_compare_and_swap_acquire_read)\n#   define AO_int_compare_and_swap_dd_acquire_read(addr, old, new_val) \\\n                AO_int_compare_and_swap_acquire_read(addr, old, new_val)\n#   define AO_HAVE_int_compare_and_swap_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_int_compare_and_swap)\n#   define AO_int_compare_and_swap_dd_acquire_read(addr, old, new_val) \\\n                AO_int_compare_and_swap(addr, old, new_val)\n#   define AO_HAVE_int_compare_and_swap_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* int_load */\n#if defined(AO_HAVE_int_load_full) && !defined(AO_HAVE_int_load_acquire)\n# define AO_int_load_acquire(addr) AO_int_load_full(addr)\n# define AO_HAVE_int_load_acquire\n#endif\n\n#if defined(AO_HAVE_int_load_acquire) && !defined(AO_HAVE_int_load)\n# define AO_int_load(addr) AO_int_load_acquire(addr)\n# define AO_HAVE_int_load\n#endif\n\n#if defined(AO_HAVE_int_load_full) && !defined(AO_HAVE_int_load_read)\n# define AO_int_load_read(addr) AO_int_load_full(addr)\n# define AO_HAVE_int_load_read\n#endif\n\n#if !defined(AO_HAVE_int_load_acquire_read) \\\n    && defined(AO_HAVE_int_load_acquire)\n# define AO_int_load_acquire_read(addr) AO_int_load_acquire(addr)\n# define AO_HAVE_int_load_acquire_read\n#endif\n\n#if defined(AO_HAVE_int_load) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_load_acquire)\n  AO_INLINE unsigned\n  AO_int_load_acquire(const volatile unsigned *addr)\n  {\n    unsigned result = AO_int_load(addr);\n\n    /* Acquire barrier would be useless, since the load could be delayed    */\n    /* beyond it.                                                           */\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_int_load_acquire\n#endif\n\n#if defined(AO_HAVE_int_load) && defined(AO_HAVE_nop_read) \\\n    && !defined(AO_HAVE_int_load_read)\n  AO_INLINE unsigned\n  AO_int_load_read(const volatile unsigned *addr)\n  {\n    unsigned result = AO_int_load(addr);\n\n    AO_nop_read();\n    return result;\n  }\n# define AO_HAVE_int_load_read\n#endif\n\n#if defined(AO_HAVE_int_load_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_load_full)\n# define AO_int_load_full(addr) (AO_nop_full(), AO_int_load_acquire(addr))\n# define AO_HAVE_int_load_full\n#endif\n\n#if defined(AO_HAVE_int_compare_and_swap_read) \\\n    && !defined(AO_HAVE_int_load_read)\n# define AO_int_CAS_BASED_LOAD_READ\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned\n  AO_int_load_read(const volatile unsigned *addr)\n  {\n    unsigned result;\n\n    do {\n      result = *(const unsigned *)addr;\n    } while (AO_EXPECT_FALSE(!AO_int_compare_and_swap_read(\n                                                (volatile unsigned *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_int_load_read\n#endif\n\n#if !defined(AO_HAVE_int_load_acquire_read) \\\n    && defined(AO_HAVE_int_load_read)\n# define AO_int_load_acquire_read(addr) AO_int_load_read(addr)\n# define AO_HAVE_int_load_acquire_read\n#endif\n\n#if defined(AO_HAVE_int_load_acquire_read) && !defined(AO_HAVE_int_load) \\\n    && (!defined(AO_int_CAS_BASED_LOAD_READ) \\\n        || !defined(AO_HAVE_int_compare_and_swap))\n# define AO_int_load(addr) AO_int_load_acquire_read(addr)\n# define AO_HAVE_int_load\n#endif\n\n#if defined(AO_HAVE_int_compare_and_swap_full) \\\n    && !defined(AO_HAVE_int_load_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned\n  AO_int_load_full(const volatile unsigned *addr)\n  {\n    unsigned result;\n\n    do {\n      result = *(const unsigned *)addr;\n    } while (AO_EXPECT_FALSE(!AO_int_compare_and_swap_full(\n                                                (volatile unsigned *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_int_load_full\n#endif\n\n#if defined(AO_HAVE_int_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_int_load_acquire)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned\n  AO_int_load_acquire(const volatile unsigned *addr)\n  {\n    unsigned result;\n\n    do {\n      result = *(const unsigned *)addr;\n    } while (AO_EXPECT_FALSE(!AO_int_compare_and_swap_acquire(\n                                                (volatile unsigned *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_int_load_acquire\n#endif\n\n#if defined(AO_HAVE_int_compare_and_swap) && !defined(AO_HAVE_int_load)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE unsigned\n  AO_int_load(const volatile unsigned *addr)\n  {\n    unsigned result;\n\n    do {\n      result = *(const unsigned *)addr;\n    } while (AO_EXPECT_FALSE(!AO_int_compare_and_swap(\n                                                (volatile unsigned *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_int_load\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_int_load_acquire_read)\n#   define AO_int_load_dd_acquire_read(addr) \\\n                                AO_int_load_acquire_read(addr)\n#   define AO_HAVE_int_load_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_int_load)\n#   define AO_int_load_dd_acquire_read(addr) AO_int_load(addr)\n#   define AO_HAVE_int_load_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* int_store */\n#if defined(AO_HAVE_int_store_full) && !defined(AO_HAVE_int_store_release)\n# define AO_int_store_release(addr, val) AO_int_store_full(addr, val)\n# define AO_HAVE_int_store_release\n#endif\n\n#if defined(AO_HAVE_int_store_release) && !defined(AO_HAVE_int_store)\n# define AO_int_store(addr, val) AO_int_store_release(addr, val)\n# define AO_HAVE_int_store\n#endif\n\n#if defined(AO_HAVE_int_store_full) && !defined(AO_HAVE_int_store_write)\n# define AO_int_store_write(addr, val) AO_int_store_full(addr, val)\n# define AO_HAVE_int_store_write\n#endif\n\n#if defined(AO_HAVE_int_store_release) \\\n    && !defined(AO_HAVE_int_store_release_write)\n# define AO_int_store_release_write(addr, val) \\\n                                AO_int_store_release(addr, val)\n# define AO_HAVE_int_store_release_write\n#endif\n\n#if defined(AO_HAVE_int_store_write) && !defined(AO_HAVE_int_store)\n# define AO_int_store(addr, val) AO_int_store_write(addr, val)\n# define AO_HAVE_int_store\n#endif\n\n#if defined(AO_HAVE_int_store) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_store_release)\n# define AO_int_store_release(addr, val) \\\n                                (AO_nop_full(), AO_int_store(addr, val))\n# define AO_HAVE_int_store_release\n#endif\n\n#if defined(AO_HAVE_int_store) && defined(AO_HAVE_nop_write) \\\n    && !defined(AO_HAVE_int_store_write)\n# define AO_int_store_write(addr, val) \\\n                                (AO_nop_write(), AO_int_store(addr, val))\n# define AO_HAVE_int_store_write\n#endif\n\n#if defined(AO_HAVE_int_compare_and_swap_write) \\\n    && !defined(AO_HAVE_int_store_write)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_int_store_write(volatile unsigned *addr, unsigned new_val)\n  {\n    unsigned old_val;\n\n    do {\n      old_val = *(unsigned *)addr;\n    } while (AO_EXPECT_FALSE(!AO_int_compare_and_swap_write(addr, old_val,\n                                                              new_val)));\n  }\n# define AO_HAVE_int_store_write\n#endif\n\n#if defined(AO_HAVE_int_store_write) \\\n    && !defined(AO_HAVE_int_store_release_write)\n# define AO_int_store_release_write(addr, val) \\\n                                AO_int_store_write(addr, val)\n# define AO_HAVE_int_store_release_write\n#endif\n\n#if defined(AO_HAVE_int_store_release) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_int_store_full)\n# define AO_int_store_full(addr, val) \\\n                                (AO_int_store_release(addr, val), \\\n                                 AO_nop_full())\n# define AO_HAVE_int_store_full\n#endif\n\n#if defined(AO_HAVE_int_compare_and_swap) && !defined(AO_HAVE_int_store)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_int_store(volatile unsigned *addr, unsigned new_val)\n  {\n    unsigned old_val;\n\n    do {\n      old_val = *(unsigned *)addr;\n    } while (AO_EXPECT_FALSE(!AO_int_compare_and_swap(addr,\n                                                        old_val, new_val)));\n  }\n# define AO_HAVE_int_store\n#endif\n\n#if defined(AO_HAVE_int_compare_and_swap_release) \\\n    && !defined(AO_HAVE_int_store_release)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_int_store_release(volatile unsigned *addr, unsigned new_val)\n  {\n    unsigned old_val;\n\n    do {\n      old_val = *(unsigned *)addr;\n    } while (AO_EXPECT_FALSE(!AO_int_compare_and_swap_release(addr, old_val,\n                                                                new_val)));\n  }\n# define AO_HAVE_int_store_release\n#endif\n\n#if defined(AO_HAVE_int_compare_and_swap_full) \\\n    && !defined(AO_HAVE_int_store_full)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_int_store_full(volatile unsigned *addr, unsigned new_val)\n  {\n    unsigned old_val;\n\n    do {\n      old_val = *(unsigned *)addr;\n    } while (AO_EXPECT_FALSE(!AO_int_compare_and_swap_full(addr, old_val,\n                                                             new_val)));\n  }\n# define AO_HAVE_int_store_full\n#endif\n/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* fetch_compare_and_swap */\n#if defined(AO_HAVE_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_fetch_compare_and_swap_acquire)\n  AO_INLINE AO_t\n  AO_fetch_compare_and_swap_acquire(volatile AO_t *addr,\n                                          AO_t old_val, AO_t new_val)\n  {\n    AO_t result = AO_fetch_compare_and_swap(addr, old_val, new_val);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_fetch_compare_and_swap_acquire\n#endif\n#if defined(AO_HAVE_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_fetch_compare_and_swap_release)\n# define AO_fetch_compare_and_swap_release(addr, old_val, new_val) \\\n                (AO_nop_full(), \\\n                 AO_fetch_compare_and_swap(addr, old_val, new_val))\n# define AO_HAVE_fetch_compare_and_swap_release\n#endif\n#if defined(AO_HAVE_fetch_compare_and_swap_full)\n# if !defined(AO_HAVE_fetch_compare_and_swap_release)\n#   define AO_fetch_compare_and_swap_release(addr, old_val, new_val) \\\n                AO_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_fetch_compare_and_swap_release\n# endif\n# if !defined(AO_HAVE_fetch_compare_and_swap_acquire)\n#   define AO_fetch_compare_and_swap_acquire(addr, old_val, new_val) \\\n                AO_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_fetch_compare_and_swap_acquire\n# endif\n# if !defined(AO_HAVE_fetch_compare_and_swap_write)\n#   define AO_fetch_compare_and_swap_write(addr, old_val, new_val) \\\n                AO_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_fetch_compare_and_swap_write\n# endif\n# if !defined(AO_HAVE_fetch_compare_and_swap_read)\n#   define AO_fetch_compare_and_swap_read(addr, old_val, new_val) \\\n                AO_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_fetch_compare_and_swap_read\n# endif\n#endif /* AO_HAVE_fetch_compare_and_swap_full */\n\n#if !defined(AO_HAVE_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_fetch_compare_and_swap_release)\n# define AO_fetch_compare_and_swap(addr, old_val, new_val) \\\n            AO_fetch_compare_and_swap_release(addr, old_val, new_val)\n# define AO_HAVE_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_fetch_compare_and_swap_acquire)\n# define AO_fetch_compare_and_swap(addr, old_val, new_val) \\\n            AO_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n# define AO_HAVE_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_fetch_compare_and_swap_write)\n# define AO_fetch_compare_and_swap(addr, old_val, new_val) \\\n                AO_fetch_compare_and_swap_write(addr, old_val, new_val)\n# define AO_HAVE_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_fetch_compare_and_swap_read)\n# define AO_fetch_compare_and_swap(addr, old_val, new_val) \\\n                AO_fetch_compare_and_swap_read(addr, old_val, new_val)\n# define AO_HAVE_fetch_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_fetch_compare_and_swap_full)\n# define AO_fetch_compare_and_swap_full(addr, old_val, new_val) \\\n            (AO_nop_full(), \\\n             AO_fetch_compare_and_swap_acquire(addr, old_val, new_val))\n# define AO_HAVE_fetch_compare_and_swap_full\n#endif\n\n#if !defined(AO_HAVE_fetch_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_fetch_compare_and_swap_write)\n# define AO_fetch_compare_and_swap_release_write(addr,old_val,new_val) \\\n                AO_fetch_compare_and_swap_write(addr, old_val, new_val)\n# define AO_HAVE_fetch_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_fetch_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_fetch_compare_and_swap_release)\n# define AO_fetch_compare_and_swap_release_write(addr,old_val,new_val) \\\n            AO_fetch_compare_and_swap_release(addr, old_val, new_val)\n# define AO_HAVE_fetch_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_fetch_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_fetch_compare_and_swap_read)\n# define AO_fetch_compare_and_swap_acquire_read(addr,old_val,new_val) \\\n                AO_fetch_compare_and_swap_read(addr, old_val, new_val)\n# define AO_HAVE_fetch_compare_and_swap_acquire_read\n#endif\n#if !defined(AO_HAVE_fetch_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_fetch_compare_and_swap_acquire)\n# define AO_fetch_compare_and_swap_acquire_read(addr,old_val,new_val) \\\n            AO_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n# define AO_HAVE_fetch_compare_and_swap_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_fetch_compare_and_swap_acquire_read)\n#   define AO_fetch_compare_and_swap_dd_acquire_read(addr,old_val,new_val) \\\n        AO_fetch_compare_and_swap_acquire_read(addr, old_val, new_val)\n#   define AO_HAVE_fetch_compare_and_swap_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_fetch_compare_and_swap)\n#   define AO_fetch_compare_and_swap_dd_acquire_read(addr,old_val,new_val) \\\n                AO_fetch_compare_and_swap(addr, old_val, new_val)\n#   define AO_HAVE_fetch_compare_and_swap_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* compare_and_swap */\n#if defined(AO_HAVE_compare_and_swap) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_compare_and_swap_acquire)\n  AO_INLINE int\n  AO_compare_and_swap_acquire(volatile AO_t *addr, AO_t old,\n                                    AO_t new_val)\n  {\n    int result = AO_compare_and_swap(addr, old, new_val);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_compare_and_swap_acquire\n#endif\n#if defined(AO_HAVE_compare_and_swap) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_compare_and_swap_release)\n# define AO_compare_and_swap_release(addr, old, new_val) \\\n                (AO_nop_full(), AO_compare_and_swap(addr, old, new_val))\n# define AO_HAVE_compare_and_swap_release\n#endif\n#if defined(AO_HAVE_compare_and_swap_full)\n# if !defined(AO_HAVE_compare_and_swap_release)\n#   define AO_compare_and_swap_release(addr, old, new_val) \\\n                AO_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_compare_and_swap_release\n# endif\n# if !defined(AO_HAVE_compare_and_swap_acquire)\n#   define AO_compare_and_swap_acquire(addr, old, new_val) \\\n                AO_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_compare_and_swap_acquire\n# endif\n# if !defined(AO_HAVE_compare_and_swap_write)\n#   define AO_compare_and_swap_write(addr, old, new_val) \\\n                AO_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_compare_and_swap_write\n# endif\n# if !defined(AO_HAVE_compare_and_swap_read)\n#   define AO_compare_and_swap_read(addr, old, new_val) \\\n                AO_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_compare_and_swap_read\n# endif\n#endif /* AO_HAVE_compare_and_swap_full */\n\n#if !defined(AO_HAVE_compare_and_swap) \\\n    && defined(AO_HAVE_compare_and_swap_release)\n# define AO_compare_and_swap(addr, old, new_val) \\\n                AO_compare_and_swap_release(addr, old, new_val)\n# define AO_HAVE_compare_and_swap\n#endif\n#if !defined(AO_HAVE_compare_and_swap) \\\n    && defined(AO_HAVE_compare_and_swap_acquire)\n# define AO_compare_and_swap(addr, old, new_val) \\\n                AO_compare_and_swap_acquire(addr, old, new_val)\n# define AO_HAVE_compare_and_swap\n#endif\n#if !defined(AO_HAVE_compare_and_swap) \\\n    && defined(AO_HAVE_compare_and_swap_write)\n# define AO_compare_and_swap(addr, old, new_val) \\\n                AO_compare_and_swap_write(addr, old, new_val)\n# define AO_HAVE_compare_and_swap\n#endif\n#if !defined(AO_HAVE_compare_and_swap) \\\n    && defined(AO_HAVE_compare_and_swap_read)\n# define AO_compare_and_swap(addr, old, new_val) \\\n                AO_compare_and_swap_read(addr, old, new_val)\n# define AO_HAVE_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_compare_and_swap_full)\n# define AO_compare_and_swap_full(addr, old, new_val) \\\n                (AO_nop_full(), \\\n                 AO_compare_and_swap_acquire(addr, old, new_val))\n# define AO_HAVE_compare_and_swap_full\n#endif\n\n#if !defined(AO_HAVE_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_compare_and_swap_write)\n# define AO_compare_and_swap_release_write(addr, old, new_val) \\\n                AO_compare_and_swap_write(addr, old, new_val)\n# define AO_HAVE_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_compare_and_swap_release)\n# define AO_compare_and_swap_release_write(addr, old, new_val) \\\n                AO_compare_and_swap_release(addr, old, new_val)\n# define AO_HAVE_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_compare_and_swap_read)\n# define AO_compare_and_swap_acquire_read(addr, old, new_val) \\\n                AO_compare_and_swap_read(addr, old, new_val)\n# define AO_HAVE_compare_and_swap_acquire_read\n#endif\n#if !defined(AO_HAVE_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_compare_and_swap_acquire)\n# define AO_compare_and_swap_acquire_read(addr, old, new_val) \\\n                AO_compare_and_swap_acquire(addr, old, new_val)\n# define AO_HAVE_compare_and_swap_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_compare_and_swap_acquire_read)\n#   define AO_compare_and_swap_dd_acquire_read(addr, old, new_val) \\\n                AO_compare_and_swap_acquire_read(addr, old, new_val)\n#   define AO_HAVE_compare_and_swap_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_compare_and_swap)\n#   define AO_compare_and_swap_dd_acquire_read(addr, old, new_val) \\\n                AO_compare_and_swap(addr, old, new_val)\n#   define AO_HAVE_compare_and_swap_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* load */\n#if defined(AO_HAVE_load_full) && !defined(AO_HAVE_load_acquire)\n# define AO_load_acquire(addr) AO_load_full(addr)\n# define AO_HAVE_load_acquire\n#endif\n\n#if defined(AO_HAVE_load_acquire) && !defined(AO_HAVE_load)\n# define AO_load(addr) AO_load_acquire(addr)\n# define AO_HAVE_load\n#endif\n\n#if defined(AO_HAVE_load_full) && !defined(AO_HAVE_load_read)\n# define AO_load_read(addr) AO_load_full(addr)\n# define AO_HAVE_load_read\n#endif\n\n#if !defined(AO_HAVE_load_acquire_read) \\\n    && defined(AO_HAVE_load_acquire)\n# define AO_load_acquire_read(addr) AO_load_acquire(addr)\n# define AO_HAVE_load_acquire_read\n#endif\n\n#if defined(AO_HAVE_load) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_load_acquire)\n  AO_INLINE AO_t\n  AO_load_acquire(const volatile AO_t *addr)\n  {\n    AO_t result = AO_load(addr);\n\n    /* Acquire barrier would be useless, since the load could be delayed    */\n    /* beyond it.                                                           */\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_load_acquire\n#endif\n\n#if defined(AO_HAVE_load) && defined(AO_HAVE_nop_read) \\\n    && !defined(AO_HAVE_load_read)\n  AO_INLINE AO_t\n  AO_load_read(const volatile AO_t *addr)\n  {\n    AO_t result = AO_load(addr);\n\n    AO_nop_read();\n    return result;\n  }\n# define AO_HAVE_load_read\n#endif\n\n#if defined(AO_HAVE_load_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_load_full)\n# define AO_load_full(addr) (AO_nop_full(), AO_load_acquire(addr))\n# define AO_HAVE_load_full\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_read) \\\n    && !defined(AO_HAVE_load_read)\n# define AO_CAS_BASED_LOAD_READ\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE AO_t\n  AO_load_read(const volatile AO_t *addr)\n  {\n    AO_t result;\n\n    do {\n      result = *(const AO_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_compare_and_swap_read(\n                                                (volatile AO_t *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_load_read\n#endif\n\n#if !defined(AO_HAVE_load_acquire_read) \\\n    && defined(AO_HAVE_load_read)\n# define AO_load_acquire_read(addr) AO_load_read(addr)\n# define AO_HAVE_load_acquire_read\n#endif\n\n#if defined(AO_HAVE_load_acquire_read) && !defined(AO_HAVE_load) \\\n    && (!defined(AO_CAS_BASED_LOAD_READ) \\\n        || !defined(AO_HAVE_compare_and_swap))\n# define AO_load(addr) AO_load_acquire_read(addr)\n# define AO_HAVE_load\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_full) \\\n    && !defined(AO_HAVE_load_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE AO_t\n  AO_load_full(const volatile AO_t *addr)\n  {\n    AO_t result;\n\n    do {\n      result = *(const AO_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_compare_and_swap_full(\n                                                (volatile AO_t *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_load_full\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_load_acquire)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE AO_t\n  AO_load_acquire(const volatile AO_t *addr)\n  {\n    AO_t result;\n\n    do {\n      result = *(const AO_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_compare_and_swap_acquire(\n                                                (volatile AO_t *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_load_acquire\n#endif\n\n#if defined(AO_HAVE_compare_and_swap) && !defined(AO_HAVE_load)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE AO_t\n  AO_load(const volatile AO_t *addr)\n  {\n    AO_t result;\n\n    do {\n      result = *(const AO_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_compare_and_swap(\n                                                (volatile AO_t *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_load\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_load_acquire_read)\n#   define AO_load_dd_acquire_read(addr) \\\n                                AO_load_acquire_read(addr)\n#   define AO_HAVE_load_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_load)\n#   define AO_load_dd_acquire_read(addr) AO_load(addr)\n#   define AO_HAVE_load_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* store */\n#if defined(AO_HAVE_store_full) && !defined(AO_HAVE_store_release)\n# define AO_store_release(addr, val) AO_store_full(addr, val)\n# define AO_HAVE_store_release\n#endif\n\n#if defined(AO_HAVE_store_release) && !defined(AO_HAVE_store)\n# define AO_store(addr, val) AO_store_release(addr, val)\n# define AO_HAVE_store\n#endif\n\n#if defined(AO_HAVE_store_full) && !defined(AO_HAVE_store_write)\n# define AO_store_write(addr, val) AO_store_full(addr, val)\n# define AO_HAVE_store_write\n#endif\n\n#if defined(AO_HAVE_store_release) \\\n    && !defined(AO_HAVE_store_release_write)\n# define AO_store_release_write(addr, val) \\\n                                AO_store_release(addr, val)\n# define AO_HAVE_store_release_write\n#endif\n\n#if defined(AO_HAVE_store_write) && !defined(AO_HAVE_store)\n# define AO_store(addr, val) AO_store_write(addr, val)\n# define AO_HAVE_store\n#endif\n\n#if defined(AO_HAVE_store) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_store_release)\n# define AO_store_release(addr, val) \\\n                                (AO_nop_full(), AO_store(addr, val))\n# define AO_HAVE_store_release\n#endif\n\n#if defined(AO_HAVE_store) && defined(AO_HAVE_nop_write) \\\n    && !defined(AO_HAVE_store_write)\n# define AO_store_write(addr, val) \\\n                                (AO_nop_write(), AO_store(addr, val))\n# define AO_HAVE_store_write\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_write) \\\n    && !defined(AO_HAVE_store_write)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_store_write(volatile AO_t *addr, AO_t new_val)\n  {\n    AO_t old_val;\n\n    do {\n      old_val = *(AO_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_compare_and_swap_write(addr, old_val,\n                                                              new_val)));\n  }\n# define AO_HAVE_store_write\n#endif\n\n#if defined(AO_HAVE_store_write) \\\n    && !defined(AO_HAVE_store_release_write)\n# define AO_store_release_write(addr, val) \\\n                                AO_store_write(addr, val)\n# define AO_HAVE_store_release_write\n#endif\n\n#if defined(AO_HAVE_store_release) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_store_full)\n# define AO_store_full(addr, val) \\\n                                (AO_store_release(addr, val), \\\n                                 AO_nop_full())\n# define AO_HAVE_store_full\n#endif\n\n#if defined(AO_HAVE_compare_and_swap) && !defined(AO_HAVE_store)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_store(volatile AO_t *addr, AO_t new_val)\n  {\n    AO_t old_val;\n\n    do {\n      old_val = *(AO_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_compare_and_swap(addr,\n                                                        old_val, new_val)));\n  }\n# define AO_HAVE_store\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_release) \\\n    && !defined(AO_HAVE_store_release)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_store_release(volatile AO_t *addr, AO_t new_val)\n  {\n    AO_t old_val;\n\n    do {\n      old_val = *(AO_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_compare_and_swap_release(addr, old_val,\n                                                                new_val)));\n  }\n# define AO_HAVE_store_release\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_full) \\\n    && !defined(AO_HAVE_store_full)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_store_full(volatile AO_t *addr, AO_t new_val)\n  {\n    AO_t old_val;\n\n    do {\n      old_val = *(AO_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_compare_and_swap_full(addr, old_val,\n                                                             new_val)));\n  }\n# define AO_HAVE_store_full\n#endif\n/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* double_fetch_compare_and_swap */\n#if defined(AO_HAVE_double_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_double_fetch_compare_and_swap_acquire)\n  AO_INLINE AO_double_t\n  AO_double_fetch_compare_and_swap_acquire(volatile AO_double_t *addr,\n                                          AO_double_t old_val, AO_double_t new_val)\n  {\n    AO_double_t result = AO_double_fetch_compare_and_swap(addr, old_val, new_val);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_double_fetch_compare_and_swap_acquire\n#endif\n#if defined(AO_HAVE_double_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_double_fetch_compare_and_swap_release)\n# define AO_double_fetch_compare_and_swap_release(addr, old_val, new_val) \\\n                (AO_nop_full(), \\\n                 AO_double_fetch_compare_and_swap(addr, old_val, new_val))\n# define AO_HAVE_double_fetch_compare_and_swap_release\n#endif\n#if defined(AO_HAVE_double_fetch_compare_and_swap_full)\n# if !defined(AO_HAVE_double_fetch_compare_and_swap_release)\n#   define AO_double_fetch_compare_and_swap_release(addr, old_val, new_val) \\\n                AO_double_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_double_fetch_compare_and_swap_release\n# endif\n# if !defined(AO_HAVE_double_fetch_compare_and_swap_acquire)\n#   define AO_double_fetch_compare_and_swap_acquire(addr, old_val, new_val) \\\n                AO_double_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_double_fetch_compare_and_swap_acquire\n# endif\n# if !defined(AO_HAVE_double_fetch_compare_and_swap_write)\n#   define AO_double_fetch_compare_and_swap_write(addr, old_val, new_val) \\\n                AO_double_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_double_fetch_compare_and_swap_write\n# endif\n# if !defined(AO_HAVE_double_fetch_compare_and_swap_read)\n#   define AO_double_fetch_compare_and_swap_read(addr, old_val, new_val) \\\n                AO_double_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_double_fetch_compare_and_swap_read\n# endif\n#endif /* AO_HAVE_double_fetch_compare_and_swap_full */\n\n#if !defined(AO_HAVE_double_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_double_fetch_compare_and_swap_release)\n# define AO_double_fetch_compare_and_swap(addr, old_val, new_val) \\\n            AO_double_fetch_compare_and_swap_release(addr, old_val, new_val)\n# define AO_HAVE_double_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_double_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_double_fetch_compare_and_swap_acquire)\n# define AO_double_fetch_compare_and_swap(addr, old_val, new_val) \\\n            AO_double_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n# define AO_HAVE_double_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_double_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_double_fetch_compare_and_swap_write)\n# define AO_double_fetch_compare_and_swap(addr, old_val, new_val) \\\n                AO_double_fetch_compare_and_swap_write(addr, old_val, new_val)\n# define AO_HAVE_double_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_double_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_double_fetch_compare_and_swap_read)\n# define AO_double_fetch_compare_and_swap(addr, old_val, new_val) \\\n                AO_double_fetch_compare_and_swap_read(addr, old_val, new_val)\n# define AO_HAVE_double_fetch_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_double_fetch_compare_and_swap_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_double_fetch_compare_and_swap_full)\n# define AO_double_fetch_compare_and_swap_full(addr, old_val, new_val) \\\n            (AO_nop_full(), \\\n             AO_double_fetch_compare_and_swap_acquire(addr, old_val, new_val))\n# define AO_HAVE_double_fetch_compare_and_swap_full\n#endif\n\n#if !defined(AO_HAVE_double_fetch_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_double_fetch_compare_and_swap_write)\n# define AO_double_fetch_compare_and_swap_release_write(addr,old_val,new_val) \\\n                AO_double_fetch_compare_and_swap_write(addr, old_val, new_val)\n# define AO_HAVE_double_fetch_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_double_fetch_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_double_fetch_compare_and_swap_release)\n# define AO_double_fetch_compare_and_swap_release_write(addr,old_val,new_val) \\\n            AO_double_fetch_compare_and_swap_release(addr, old_val, new_val)\n# define AO_HAVE_double_fetch_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_double_fetch_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_double_fetch_compare_and_swap_read)\n# define AO_double_fetch_compare_and_swap_acquire_read(addr,old_val,new_val) \\\n                AO_double_fetch_compare_and_swap_read(addr, old_val, new_val)\n# define AO_HAVE_double_fetch_compare_and_swap_acquire_read\n#endif\n#if !defined(AO_HAVE_double_fetch_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_double_fetch_compare_and_swap_acquire)\n# define AO_double_fetch_compare_and_swap_acquire_read(addr,old_val,new_val) \\\n            AO_double_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n# define AO_HAVE_double_fetch_compare_and_swap_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_double_fetch_compare_and_swap_acquire_read)\n#   define AO_double_fetch_compare_and_swap_dd_acquire_read(addr,old_val,new_val) \\\n        AO_double_fetch_compare_and_swap_acquire_read(addr, old_val, new_val)\n#   define AO_HAVE_double_fetch_compare_and_swap_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_double_fetch_compare_and_swap)\n#   define AO_double_fetch_compare_and_swap_dd_acquire_read(addr,old_val,new_val) \\\n                AO_double_fetch_compare_and_swap(addr, old_val, new_val)\n#   define AO_HAVE_double_fetch_compare_and_swap_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* double_compare_and_swap */\n#if defined(AO_HAVE_double_compare_and_swap) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_double_compare_and_swap_acquire)\n  AO_INLINE int\n  AO_double_compare_and_swap_acquire(volatile AO_double_t *addr, AO_double_t old,\n                                    AO_double_t new_val)\n  {\n    int result = AO_double_compare_and_swap(addr, old, new_val);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_double_compare_and_swap_acquire\n#endif\n#if defined(AO_HAVE_double_compare_and_swap) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_double_compare_and_swap_release)\n# define AO_double_compare_and_swap_release(addr, old, new_val) \\\n                (AO_nop_full(), AO_double_compare_and_swap(addr, old, new_val))\n# define AO_HAVE_double_compare_and_swap_release\n#endif\n#if defined(AO_HAVE_double_compare_and_swap_full)\n# if !defined(AO_HAVE_double_compare_and_swap_release)\n#   define AO_double_compare_and_swap_release(addr, old, new_val) \\\n                AO_double_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_double_compare_and_swap_release\n# endif\n# if !defined(AO_HAVE_double_compare_and_swap_acquire)\n#   define AO_double_compare_and_swap_acquire(addr, old, new_val) \\\n                AO_double_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_double_compare_and_swap_acquire\n# endif\n# if !defined(AO_HAVE_double_compare_and_swap_write)\n#   define AO_double_compare_and_swap_write(addr, old, new_val) \\\n                AO_double_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_double_compare_and_swap_write\n# endif\n# if !defined(AO_HAVE_double_compare_and_swap_read)\n#   define AO_double_compare_and_swap_read(addr, old, new_val) \\\n                AO_double_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_double_compare_and_swap_read\n# endif\n#endif /* AO_HAVE_double_compare_and_swap_full */\n\n#if !defined(AO_HAVE_double_compare_and_swap) \\\n    && defined(AO_HAVE_double_compare_and_swap_release)\n# define AO_double_compare_and_swap(addr, old, new_val) \\\n                AO_double_compare_and_swap_release(addr, old, new_val)\n# define AO_HAVE_double_compare_and_swap\n#endif\n#if !defined(AO_HAVE_double_compare_and_swap) \\\n    && defined(AO_HAVE_double_compare_and_swap_acquire)\n# define AO_double_compare_and_swap(addr, old, new_val) \\\n                AO_double_compare_and_swap_acquire(addr, old, new_val)\n# define AO_HAVE_double_compare_and_swap\n#endif\n#if !defined(AO_HAVE_double_compare_and_swap) \\\n    && defined(AO_HAVE_double_compare_and_swap_write)\n# define AO_double_compare_and_swap(addr, old, new_val) \\\n                AO_double_compare_and_swap_write(addr, old, new_val)\n# define AO_HAVE_double_compare_and_swap\n#endif\n#if !defined(AO_HAVE_double_compare_and_swap) \\\n    && defined(AO_HAVE_double_compare_and_swap_read)\n# define AO_double_compare_and_swap(addr, old, new_val) \\\n                AO_double_compare_and_swap_read(addr, old, new_val)\n# define AO_HAVE_double_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_double_compare_and_swap_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_double_compare_and_swap_full)\n# define AO_double_compare_and_swap_full(addr, old, new_val) \\\n                (AO_nop_full(), \\\n                 AO_double_compare_and_swap_acquire(addr, old, new_val))\n# define AO_HAVE_double_compare_and_swap_full\n#endif\n\n#if !defined(AO_HAVE_double_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_double_compare_and_swap_write)\n# define AO_double_compare_and_swap_release_write(addr, old, new_val) \\\n                AO_double_compare_and_swap_write(addr, old, new_val)\n# define AO_HAVE_double_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_double_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_double_compare_and_swap_release)\n# define AO_double_compare_and_swap_release_write(addr, old, new_val) \\\n                AO_double_compare_and_swap_release(addr, old, new_val)\n# define AO_HAVE_double_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_double_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_double_compare_and_swap_read)\n# define AO_double_compare_and_swap_acquire_read(addr, old, new_val) \\\n                AO_double_compare_and_swap_read(addr, old, new_val)\n# define AO_HAVE_double_compare_and_swap_acquire_read\n#endif\n#if !defined(AO_HAVE_double_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_double_compare_and_swap_acquire)\n# define AO_double_compare_and_swap_acquire_read(addr, old, new_val) \\\n                AO_double_compare_and_swap_acquire(addr, old, new_val)\n# define AO_HAVE_double_compare_and_swap_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_double_compare_and_swap_acquire_read)\n#   define AO_double_compare_and_swap_dd_acquire_read(addr, old, new_val) \\\n                AO_double_compare_and_swap_acquire_read(addr, old, new_val)\n#   define AO_HAVE_double_compare_and_swap_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_double_compare_and_swap)\n#   define AO_double_compare_and_swap_dd_acquire_read(addr, old, new_val) \\\n                AO_double_compare_and_swap(addr, old, new_val)\n#   define AO_HAVE_double_compare_and_swap_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* double_load */\n#if defined(AO_HAVE_double_load_full) && !defined(AO_HAVE_double_load_acquire)\n# define AO_double_load_acquire(addr) AO_double_load_full(addr)\n# define AO_HAVE_double_load_acquire\n#endif\n\n#if defined(AO_HAVE_double_load_acquire) && !defined(AO_HAVE_double_load)\n# define AO_double_load(addr) AO_double_load_acquire(addr)\n# define AO_HAVE_double_load\n#endif\n\n#if defined(AO_HAVE_double_load_full) && !defined(AO_HAVE_double_load_read)\n# define AO_double_load_read(addr) AO_double_load_full(addr)\n# define AO_HAVE_double_load_read\n#endif\n\n#if !defined(AO_HAVE_double_load_acquire_read) \\\n    && defined(AO_HAVE_double_load_acquire)\n# define AO_double_load_acquire_read(addr) AO_double_load_acquire(addr)\n# define AO_HAVE_double_load_acquire_read\n#endif\n\n#if defined(AO_HAVE_double_load) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_double_load_acquire)\n  AO_INLINE AO_double_t\n  AO_double_load_acquire(const volatile AO_double_t *addr)\n  {\n    AO_double_t result = AO_double_load(addr);\n\n    /* Acquire barrier would be useless, since the load could be delayed    */\n    /* beyond it.                                                           */\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_double_load_acquire\n#endif\n\n#if defined(AO_HAVE_double_load) && defined(AO_HAVE_nop_read) \\\n    && !defined(AO_HAVE_double_load_read)\n  AO_INLINE AO_double_t\n  AO_double_load_read(const volatile AO_double_t *addr)\n  {\n    AO_double_t result = AO_double_load(addr);\n\n    AO_nop_read();\n    return result;\n  }\n# define AO_HAVE_double_load_read\n#endif\n\n#if defined(AO_HAVE_double_load_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_double_load_full)\n# define AO_double_load_full(addr) (AO_nop_full(), AO_double_load_acquire(addr))\n# define AO_HAVE_double_load_full\n#endif\n\n#if defined(AO_HAVE_double_compare_and_swap_read) \\\n    && !defined(AO_HAVE_double_load_read)\n# define AO_double_CAS_BASED_LOAD_READ\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE AO_double_t\n  AO_double_load_read(const volatile AO_double_t *addr)\n  {\n    AO_double_t result;\n\n    do {\n      result = *(const AO_double_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_double_compare_and_swap_read(\n                                                (volatile AO_double_t *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_double_load_read\n#endif\n\n#if !defined(AO_HAVE_double_load_acquire_read) \\\n    && defined(AO_HAVE_double_load_read)\n# define AO_double_load_acquire_read(addr) AO_double_load_read(addr)\n# define AO_HAVE_double_load_acquire_read\n#endif\n\n#if defined(AO_HAVE_double_load_acquire_read) && !defined(AO_HAVE_double_load) \\\n    && (!defined(AO_double_CAS_BASED_LOAD_READ) \\\n        || !defined(AO_HAVE_double_compare_and_swap))\n# define AO_double_load(addr) AO_double_load_acquire_read(addr)\n# define AO_HAVE_double_load\n#endif\n\n#if defined(AO_HAVE_double_compare_and_swap_full) \\\n    && !defined(AO_HAVE_double_load_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE AO_double_t\n  AO_double_load_full(const volatile AO_double_t *addr)\n  {\n    AO_double_t result;\n\n    do {\n      result = *(const AO_double_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_double_compare_and_swap_full(\n                                                (volatile AO_double_t *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_double_load_full\n#endif\n\n#if defined(AO_HAVE_double_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_double_load_acquire)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE AO_double_t\n  AO_double_load_acquire(const volatile AO_double_t *addr)\n  {\n    AO_double_t result;\n\n    do {\n      result = *(const AO_double_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_double_compare_and_swap_acquire(\n                                                (volatile AO_double_t *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_double_load_acquire\n#endif\n\n#if defined(AO_HAVE_double_compare_and_swap) && !defined(AO_HAVE_double_load)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE AO_double_t\n  AO_double_load(const volatile AO_double_t *addr)\n  {\n    AO_double_t result;\n\n    do {\n      result = *(const AO_double_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_double_compare_and_swap(\n                                                (volatile AO_double_t *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_double_load\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_double_load_acquire_read)\n#   define AO_double_load_dd_acquire_read(addr) \\\n                                AO_double_load_acquire_read(addr)\n#   define AO_HAVE_double_load_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_double_load)\n#   define AO_double_load_dd_acquire_read(addr) AO_double_load(addr)\n#   define AO_HAVE_double_load_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* double_store */\n#if defined(AO_HAVE_double_store_full) && !defined(AO_HAVE_double_store_release)\n# define AO_double_store_release(addr, val) AO_double_store_full(addr, val)\n# define AO_HAVE_double_store_release\n#endif\n\n#if defined(AO_HAVE_double_store_release) && !defined(AO_HAVE_double_store)\n# define AO_double_store(addr, val) AO_double_store_release(addr, val)\n# define AO_HAVE_double_store\n#endif\n\n#if defined(AO_HAVE_double_store_full) && !defined(AO_HAVE_double_store_write)\n# define AO_double_store_write(addr, val) AO_double_store_full(addr, val)\n# define AO_HAVE_double_store_write\n#endif\n\n#if defined(AO_HAVE_double_store_release) \\\n    && !defined(AO_HAVE_double_store_release_write)\n# define AO_double_store_release_write(addr, val) \\\n                                AO_double_store_release(addr, val)\n# define AO_HAVE_double_store_release_write\n#endif\n\n#if defined(AO_HAVE_double_store_write) && !defined(AO_HAVE_double_store)\n# define AO_double_store(addr, val) AO_double_store_write(addr, val)\n# define AO_HAVE_double_store\n#endif\n\n#if defined(AO_HAVE_double_store) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_double_store_release)\n# define AO_double_store_release(addr, val) \\\n                                (AO_nop_full(), AO_double_store(addr, val))\n# define AO_HAVE_double_store_release\n#endif\n\n#if defined(AO_HAVE_double_store) && defined(AO_HAVE_nop_write) \\\n    && !defined(AO_HAVE_double_store_write)\n# define AO_double_store_write(addr, val) \\\n                                (AO_nop_write(), AO_double_store(addr, val))\n# define AO_HAVE_double_store_write\n#endif\n\n#if defined(AO_HAVE_double_compare_and_swap_write) \\\n    && !defined(AO_HAVE_double_store_write)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_double_store_write(volatile AO_double_t *addr, AO_double_t new_val)\n  {\n    AO_double_t old_val;\n\n    do {\n      old_val = *(AO_double_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_double_compare_and_swap_write(addr, old_val,\n                                                              new_val)));\n  }\n# define AO_HAVE_double_store_write\n#endif\n\n#if defined(AO_HAVE_double_store_write) \\\n    && !defined(AO_HAVE_double_store_release_write)\n# define AO_double_store_release_write(addr, val) \\\n                                AO_double_store_write(addr, val)\n# define AO_HAVE_double_store_release_write\n#endif\n\n#if defined(AO_HAVE_double_store_release) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_double_store_full)\n# define AO_double_store_full(addr, val) \\\n                                (AO_double_store_release(addr, val), \\\n                                 AO_nop_full())\n# define AO_HAVE_double_store_full\n#endif\n\n#if defined(AO_HAVE_double_compare_and_swap) && !defined(AO_HAVE_double_store)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_double_store(volatile AO_double_t *addr, AO_double_t new_val)\n  {\n    AO_double_t old_val;\n\n    do {\n      old_val = *(AO_double_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_double_compare_and_swap(addr,\n                                                        old_val, new_val)));\n  }\n# define AO_HAVE_double_store\n#endif\n\n#if defined(AO_HAVE_double_compare_and_swap_release) \\\n    && !defined(AO_HAVE_double_store_release)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_double_store_release(volatile AO_double_t *addr, AO_double_t new_val)\n  {\n    AO_double_t old_val;\n\n    do {\n      old_val = *(AO_double_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_double_compare_and_swap_release(addr, old_val,\n                                                                new_val)));\n  }\n# define AO_HAVE_double_store_release\n#endif\n\n#if defined(AO_HAVE_double_compare_and_swap_full) \\\n    && !defined(AO_HAVE_double_store_full)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_double_store_full(volatile AO_double_t *addr, AO_double_t new_val)\n  {\n    AO_double_t old_val;\n\n    do {\n      old_val = *(AO_double_t *)addr;\n    } while (AO_EXPECT_FALSE(!AO_double_compare_and_swap_full(addr, old_val,\n                                                             new_val)));\n  }\n# define AO_HAVE_double_store_full\n#endif\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/generalize-small.template",
    "content": "/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* XSIZE_fetch_compare_and_swap */\n#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_fetch_compare_and_swap_acquire)\n  AO_INLINE XCTYPE\n  AO_XSIZE_fetch_compare_and_swap_acquire(volatile XCTYPE *addr,\n                                          XCTYPE old_val, XCTYPE new_val)\n  {\n    XCTYPE result = AO_XSIZE_fetch_compare_and_swap(addr, old_val, new_val);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_XSIZE_fetch_compare_and_swap_acquire\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_fetch_compare_and_swap_release)\n# define AO_XSIZE_fetch_compare_and_swap_release(addr, old_val, new_val) \\\n                (AO_nop_full(), \\\n                 AO_XSIZE_fetch_compare_and_swap(addr, old_val, new_val))\n# define AO_HAVE_XSIZE_fetch_compare_and_swap_release\n#endif\n#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_full)\n# if !defined(AO_HAVE_XSIZE_fetch_compare_and_swap_release)\n#   define AO_XSIZE_fetch_compare_and_swap_release(addr, old_val, new_val) \\\n                AO_XSIZE_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_XSIZE_fetch_compare_and_swap_release\n# endif\n# if !defined(AO_HAVE_XSIZE_fetch_compare_and_swap_acquire)\n#   define AO_XSIZE_fetch_compare_and_swap_acquire(addr, old_val, new_val) \\\n                AO_XSIZE_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_XSIZE_fetch_compare_and_swap_acquire\n# endif\n# if !defined(AO_HAVE_XSIZE_fetch_compare_and_swap_write)\n#   define AO_XSIZE_fetch_compare_and_swap_write(addr, old_val, new_val) \\\n                AO_XSIZE_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_XSIZE_fetch_compare_and_swap_write\n# endif\n# if !defined(AO_HAVE_XSIZE_fetch_compare_and_swap_read)\n#   define AO_XSIZE_fetch_compare_and_swap_read(addr, old_val, new_val) \\\n                AO_XSIZE_fetch_compare_and_swap_full(addr, old_val, new_val)\n#   define AO_HAVE_XSIZE_fetch_compare_and_swap_read\n# endif\n#endif /* AO_HAVE_XSIZE_fetch_compare_and_swap_full */\n\n#if !defined(AO_HAVE_XSIZE_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_XSIZE_fetch_compare_and_swap_release)\n# define AO_XSIZE_fetch_compare_and_swap(addr, old_val, new_val) \\\n            AO_XSIZE_fetch_compare_and_swap_release(addr, old_val, new_val)\n# define AO_HAVE_XSIZE_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_XSIZE_fetch_compare_and_swap_acquire)\n# define AO_XSIZE_fetch_compare_and_swap(addr, old_val, new_val) \\\n            AO_XSIZE_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n# define AO_HAVE_XSIZE_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_XSIZE_fetch_compare_and_swap_write)\n# define AO_XSIZE_fetch_compare_and_swap(addr, old_val, new_val) \\\n                AO_XSIZE_fetch_compare_and_swap_write(addr, old_val, new_val)\n# define AO_HAVE_XSIZE_fetch_compare_and_swap\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_compare_and_swap) \\\n    && defined(AO_HAVE_XSIZE_fetch_compare_and_swap_read)\n# define AO_XSIZE_fetch_compare_and_swap(addr, old_val, new_val) \\\n                AO_XSIZE_fetch_compare_and_swap_read(addr, old_val, new_val)\n# define AO_HAVE_XSIZE_fetch_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_fetch_compare_and_swap_full)\n# define AO_XSIZE_fetch_compare_and_swap_full(addr, old_val, new_val) \\\n            (AO_nop_full(), \\\n             AO_XSIZE_fetch_compare_and_swap_acquire(addr, old_val, new_val))\n# define AO_HAVE_XSIZE_fetch_compare_and_swap_full\n#endif\n\n#if !defined(AO_HAVE_XSIZE_fetch_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_XSIZE_fetch_compare_and_swap_write)\n# define AO_XSIZE_fetch_compare_and_swap_release_write(addr,old_val,new_val) \\\n                AO_XSIZE_fetch_compare_and_swap_write(addr, old_val, new_val)\n# define AO_HAVE_XSIZE_fetch_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_XSIZE_fetch_compare_and_swap_release)\n# define AO_XSIZE_fetch_compare_and_swap_release_write(addr,old_val,new_val) \\\n            AO_XSIZE_fetch_compare_and_swap_release(addr, old_val, new_val)\n# define AO_HAVE_XSIZE_fetch_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_fetch_compare_and_swap_read)\n# define AO_XSIZE_fetch_compare_and_swap_acquire_read(addr,old_val,new_val) \\\n                AO_XSIZE_fetch_compare_and_swap_read(addr, old_val, new_val)\n# define AO_HAVE_XSIZE_fetch_compare_and_swap_acquire_read\n#endif\n#if !defined(AO_HAVE_XSIZE_fetch_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_fetch_compare_and_swap_acquire)\n# define AO_XSIZE_fetch_compare_and_swap_acquire_read(addr,old_val,new_val) \\\n            AO_XSIZE_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n# define AO_HAVE_XSIZE_fetch_compare_and_swap_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_acquire_read)\n#   define AO_XSIZE_fetch_compare_and_swap_dd_acquire_read(addr,old_val,new_val) \\\n        AO_XSIZE_fetch_compare_and_swap_acquire_read(addr, old_val, new_val)\n#   define AO_HAVE_XSIZE_fetch_compare_and_swap_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_XSIZE_fetch_compare_and_swap)\n#   define AO_XSIZE_fetch_compare_and_swap_dd_acquire_read(addr,old_val,new_val) \\\n                AO_XSIZE_fetch_compare_and_swap(addr, old_val, new_val)\n#   define AO_HAVE_XSIZE_fetch_compare_and_swap_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* XSIZE_compare_and_swap */\n#if defined(AO_HAVE_XSIZE_compare_and_swap) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_compare_and_swap_acquire)\n  AO_INLINE int\n  AO_XSIZE_compare_and_swap_acquire(volatile XCTYPE *addr, XCTYPE old,\n                                    XCTYPE new_val)\n  {\n    int result = AO_XSIZE_compare_and_swap(addr, old, new_val);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_XSIZE_compare_and_swap_acquire\n#endif\n#if defined(AO_HAVE_XSIZE_compare_and_swap) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_compare_and_swap_release)\n# define AO_XSIZE_compare_and_swap_release(addr, old, new_val) \\\n                (AO_nop_full(), AO_XSIZE_compare_and_swap(addr, old, new_val))\n# define AO_HAVE_XSIZE_compare_and_swap_release\n#endif\n#if defined(AO_HAVE_XSIZE_compare_and_swap_full)\n# if !defined(AO_HAVE_XSIZE_compare_and_swap_release)\n#   define AO_XSIZE_compare_and_swap_release(addr, old, new_val) \\\n                AO_XSIZE_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_XSIZE_compare_and_swap_release\n# endif\n# if !defined(AO_HAVE_XSIZE_compare_and_swap_acquire)\n#   define AO_XSIZE_compare_and_swap_acquire(addr, old, new_val) \\\n                AO_XSIZE_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_XSIZE_compare_and_swap_acquire\n# endif\n# if !defined(AO_HAVE_XSIZE_compare_and_swap_write)\n#   define AO_XSIZE_compare_and_swap_write(addr, old, new_val) \\\n                AO_XSIZE_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_XSIZE_compare_and_swap_write\n# endif\n# if !defined(AO_HAVE_XSIZE_compare_and_swap_read)\n#   define AO_XSIZE_compare_and_swap_read(addr, old, new_val) \\\n                AO_XSIZE_compare_and_swap_full(addr, old, new_val)\n#   define AO_HAVE_XSIZE_compare_and_swap_read\n# endif\n#endif /* AO_HAVE_XSIZE_compare_and_swap_full */\n\n#if !defined(AO_HAVE_XSIZE_compare_and_swap) \\\n    && defined(AO_HAVE_XSIZE_compare_and_swap_release)\n# define AO_XSIZE_compare_and_swap(addr, old, new_val) \\\n                AO_XSIZE_compare_and_swap_release(addr, old, new_val)\n# define AO_HAVE_XSIZE_compare_and_swap\n#endif\n#if !defined(AO_HAVE_XSIZE_compare_and_swap) \\\n    && defined(AO_HAVE_XSIZE_compare_and_swap_acquire)\n# define AO_XSIZE_compare_and_swap(addr, old, new_val) \\\n                AO_XSIZE_compare_and_swap_acquire(addr, old, new_val)\n# define AO_HAVE_XSIZE_compare_and_swap\n#endif\n#if !defined(AO_HAVE_XSIZE_compare_and_swap) \\\n    && defined(AO_HAVE_XSIZE_compare_and_swap_write)\n# define AO_XSIZE_compare_and_swap(addr, old, new_val) \\\n                AO_XSIZE_compare_and_swap_write(addr, old, new_val)\n# define AO_HAVE_XSIZE_compare_and_swap\n#endif\n#if !defined(AO_HAVE_XSIZE_compare_and_swap) \\\n    && defined(AO_HAVE_XSIZE_compare_and_swap_read)\n# define AO_XSIZE_compare_and_swap(addr, old, new_val) \\\n                AO_XSIZE_compare_and_swap_read(addr, old, new_val)\n# define AO_HAVE_XSIZE_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_XSIZE_compare_and_swap_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_compare_and_swap_full)\n# define AO_XSIZE_compare_and_swap_full(addr, old, new_val) \\\n                (AO_nop_full(), \\\n                 AO_XSIZE_compare_and_swap_acquire(addr, old, new_val))\n# define AO_HAVE_XSIZE_compare_and_swap_full\n#endif\n\n#if !defined(AO_HAVE_XSIZE_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_XSIZE_compare_and_swap_write)\n# define AO_XSIZE_compare_and_swap_release_write(addr, old, new_val) \\\n                AO_XSIZE_compare_and_swap_write(addr, old, new_val)\n# define AO_HAVE_XSIZE_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_XSIZE_compare_and_swap_release_write) \\\n    && defined(AO_HAVE_XSIZE_compare_and_swap_release)\n# define AO_XSIZE_compare_and_swap_release_write(addr, old, new_val) \\\n                AO_XSIZE_compare_and_swap_release(addr, old, new_val)\n# define AO_HAVE_XSIZE_compare_and_swap_release_write\n#endif\n#if !defined(AO_HAVE_XSIZE_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_compare_and_swap_read)\n# define AO_XSIZE_compare_and_swap_acquire_read(addr, old, new_val) \\\n                AO_XSIZE_compare_and_swap_read(addr, old, new_val)\n# define AO_HAVE_XSIZE_compare_and_swap_acquire_read\n#endif\n#if !defined(AO_HAVE_XSIZE_compare_and_swap_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_compare_and_swap_acquire)\n# define AO_XSIZE_compare_and_swap_acquire_read(addr, old, new_val) \\\n                AO_XSIZE_compare_and_swap_acquire(addr, old, new_val)\n# define AO_HAVE_XSIZE_compare_and_swap_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_XSIZE_compare_and_swap_acquire_read)\n#   define AO_XSIZE_compare_and_swap_dd_acquire_read(addr, old, new_val) \\\n                AO_XSIZE_compare_and_swap_acquire_read(addr, old, new_val)\n#   define AO_HAVE_XSIZE_compare_and_swap_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_XSIZE_compare_and_swap)\n#   define AO_XSIZE_compare_and_swap_dd_acquire_read(addr, old, new_val) \\\n                AO_XSIZE_compare_and_swap(addr, old, new_val)\n#   define AO_HAVE_XSIZE_compare_and_swap_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* XSIZE_load */\n#if defined(AO_HAVE_XSIZE_load_full) && !defined(AO_HAVE_XSIZE_load_acquire)\n# define AO_XSIZE_load_acquire(addr) AO_XSIZE_load_full(addr)\n# define AO_HAVE_XSIZE_load_acquire\n#endif\n\n#if defined(AO_HAVE_XSIZE_load_acquire) && !defined(AO_HAVE_XSIZE_load)\n# define AO_XSIZE_load(addr) AO_XSIZE_load_acquire(addr)\n# define AO_HAVE_XSIZE_load\n#endif\n\n#if defined(AO_HAVE_XSIZE_load_full) && !defined(AO_HAVE_XSIZE_load_read)\n# define AO_XSIZE_load_read(addr) AO_XSIZE_load_full(addr)\n# define AO_HAVE_XSIZE_load_read\n#endif\n\n#if !defined(AO_HAVE_XSIZE_load_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_load_acquire)\n# define AO_XSIZE_load_acquire_read(addr) AO_XSIZE_load_acquire(addr)\n# define AO_HAVE_XSIZE_load_acquire_read\n#endif\n\n#if defined(AO_HAVE_XSIZE_load) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_load_acquire)\n  AO_INLINE XCTYPE\n  AO_XSIZE_load_acquire(const volatile XCTYPE *addr)\n  {\n    XCTYPE result = AO_XSIZE_load(addr);\n\n    /* Acquire barrier would be useless, since the load could be delayed    */\n    /* beyond it.                                                           */\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_XSIZE_load_acquire\n#endif\n\n#if defined(AO_HAVE_XSIZE_load) && defined(AO_HAVE_nop_read) \\\n    && !defined(AO_HAVE_XSIZE_load_read)\n  AO_INLINE XCTYPE\n  AO_XSIZE_load_read(const volatile XCTYPE *addr)\n  {\n    XCTYPE result = AO_XSIZE_load(addr);\n\n    AO_nop_read();\n    return result;\n  }\n# define AO_HAVE_XSIZE_load_read\n#endif\n\n#if defined(AO_HAVE_XSIZE_load_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_load_full)\n# define AO_XSIZE_load_full(addr) (AO_nop_full(), AO_XSIZE_load_acquire(addr))\n# define AO_HAVE_XSIZE_load_full\n#endif\n\n#if defined(AO_HAVE_XSIZE_compare_and_swap_read) \\\n    && !defined(AO_HAVE_XSIZE_load_read)\n# define AO_XSIZE_CAS_BASED_LOAD_READ\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE XCTYPE\n  AO_XSIZE_load_read(const volatile XCTYPE *addr)\n  {\n    XCTYPE result;\n\n    do {\n      result = *(const XCTYPE *)addr;\n    } while (AO_EXPECT_FALSE(!AO_XSIZE_compare_and_swap_read(\n                                                (volatile XCTYPE *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_XSIZE_load_read\n#endif\n\n#if !defined(AO_HAVE_XSIZE_load_acquire_read) \\\n    && defined(AO_HAVE_XSIZE_load_read)\n# define AO_XSIZE_load_acquire_read(addr) AO_XSIZE_load_read(addr)\n# define AO_HAVE_XSIZE_load_acquire_read\n#endif\n\n#if defined(AO_HAVE_XSIZE_load_acquire_read) && !defined(AO_HAVE_XSIZE_load) \\\n    && (!defined(AO_XSIZE_CAS_BASED_LOAD_READ) \\\n        || !defined(AO_HAVE_XSIZE_compare_and_swap))\n# define AO_XSIZE_load(addr) AO_XSIZE_load_acquire_read(addr)\n# define AO_HAVE_XSIZE_load\n#endif\n\n#if defined(AO_HAVE_XSIZE_compare_and_swap_full) \\\n    && !defined(AO_HAVE_XSIZE_load_full)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE XCTYPE\n  AO_XSIZE_load_full(const volatile XCTYPE *addr)\n  {\n    XCTYPE result;\n\n    do {\n      result = *(const XCTYPE *)addr;\n    } while (AO_EXPECT_FALSE(!AO_XSIZE_compare_and_swap_full(\n                                                (volatile XCTYPE *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_XSIZE_load_full\n#endif\n\n#if defined(AO_HAVE_XSIZE_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_XSIZE_load_acquire)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE XCTYPE\n  AO_XSIZE_load_acquire(const volatile XCTYPE *addr)\n  {\n    XCTYPE result;\n\n    do {\n      result = *(const XCTYPE *)addr;\n    } while (AO_EXPECT_FALSE(!AO_XSIZE_compare_and_swap_acquire(\n                                                (volatile XCTYPE *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_XSIZE_load_acquire\n#endif\n\n#if defined(AO_HAVE_XSIZE_compare_and_swap) && !defined(AO_HAVE_XSIZE_load)\n  AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE XCTYPE\n  AO_XSIZE_load(const volatile XCTYPE *addr)\n  {\n    XCTYPE result;\n\n    do {\n      result = *(const XCTYPE *)addr;\n    } while (AO_EXPECT_FALSE(!AO_XSIZE_compare_and_swap(\n                                                (volatile XCTYPE *)addr,\n                                                result, result)));\n    return result;\n  }\n# define AO_HAVE_XSIZE_load\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_XSIZE_load_acquire_read)\n#   define AO_XSIZE_load_dd_acquire_read(addr) \\\n                                AO_XSIZE_load_acquire_read(addr)\n#   define AO_HAVE_XSIZE_load_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_XSIZE_load)\n#   define AO_XSIZE_load_dd_acquire_read(addr) AO_XSIZE_load(addr)\n#   define AO_HAVE_XSIZE_load_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* XSIZE_store */\n#if defined(AO_HAVE_XSIZE_store_full) && !defined(AO_HAVE_XSIZE_store_release)\n# define AO_XSIZE_store_release(addr, val) AO_XSIZE_store_full(addr, val)\n# define AO_HAVE_XSIZE_store_release\n#endif\n\n#if defined(AO_HAVE_XSIZE_store_release) && !defined(AO_HAVE_XSIZE_store)\n# define AO_XSIZE_store(addr, val) AO_XSIZE_store_release(addr, val)\n# define AO_HAVE_XSIZE_store\n#endif\n\n#if defined(AO_HAVE_XSIZE_store_full) && !defined(AO_HAVE_XSIZE_store_write)\n# define AO_XSIZE_store_write(addr, val) AO_XSIZE_store_full(addr, val)\n# define AO_HAVE_XSIZE_store_write\n#endif\n\n#if defined(AO_HAVE_XSIZE_store_release) \\\n    && !defined(AO_HAVE_XSIZE_store_release_write)\n# define AO_XSIZE_store_release_write(addr, val) \\\n                                AO_XSIZE_store_release(addr, val)\n# define AO_HAVE_XSIZE_store_release_write\n#endif\n\n#if defined(AO_HAVE_XSIZE_store_write) && !defined(AO_HAVE_XSIZE_store)\n# define AO_XSIZE_store(addr, val) AO_XSIZE_store_write(addr, val)\n# define AO_HAVE_XSIZE_store\n#endif\n\n#if defined(AO_HAVE_XSIZE_store) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_store_release)\n# define AO_XSIZE_store_release(addr, val) \\\n                                (AO_nop_full(), AO_XSIZE_store(addr, val))\n# define AO_HAVE_XSIZE_store_release\n#endif\n\n#if defined(AO_HAVE_XSIZE_store) && defined(AO_HAVE_nop_write) \\\n    && !defined(AO_HAVE_XSIZE_store_write)\n# define AO_XSIZE_store_write(addr, val) \\\n                                (AO_nop_write(), AO_XSIZE_store(addr, val))\n# define AO_HAVE_XSIZE_store_write\n#endif\n\n#if defined(AO_HAVE_XSIZE_compare_and_swap_write) \\\n    && !defined(AO_HAVE_XSIZE_store_write)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_XSIZE_store_write(volatile XCTYPE *addr, XCTYPE new_val)\n  {\n    XCTYPE old_val;\n\n    do {\n      old_val = *(XCTYPE *)addr;\n    } while (AO_EXPECT_FALSE(!AO_XSIZE_compare_and_swap_write(addr, old_val,\n                                                              new_val)));\n  }\n# define AO_HAVE_XSIZE_store_write\n#endif\n\n#if defined(AO_HAVE_XSIZE_store_write) \\\n    && !defined(AO_HAVE_XSIZE_store_release_write)\n# define AO_XSIZE_store_release_write(addr, val) \\\n                                AO_XSIZE_store_write(addr, val)\n# define AO_HAVE_XSIZE_store_release_write\n#endif\n\n#if defined(AO_HAVE_XSIZE_store_release) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_XSIZE_store_full)\n# define AO_XSIZE_store_full(addr, val) \\\n                                (AO_XSIZE_store_release(addr, val), \\\n                                 AO_nop_full())\n# define AO_HAVE_XSIZE_store_full\n#endif\n\n#if defined(AO_HAVE_XSIZE_compare_and_swap) && !defined(AO_HAVE_XSIZE_store)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_XSIZE_store(volatile XCTYPE *addr, XCTYPE new_val)\n  {\n    XCTYPE old_val;\n\n    do {\n      old_val = *(XCTYPE *)addr;\n    } while (AO_EXPECT_FALSE(!AO_XSIZE_compare_and_swap(addr,\n                                                        old_val, new_val)));\n  }\n# define AO_HAVE_XSIZE_store\n#endif\n\n#if defined(AO_HAVE_XSIZE_compare_and_swap_release) \\\n    && !defined(AO_HAVE_XSIZE_store_release)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_XSIZE_store_release(volatile XCTYPE *addr, XCTYPE new_val)\n  {\n    XCTYPE old_val;\n\n    do {\n      old_val = *(XCTYPE *)addr;\n    } while (AO_EXPECT_FALSE(!AO_XSIZE_compare_and_swap_release(addr, old_val,\n                                                                new_val)));\n  }\n# define AO_HAVE_XSIZE_store_release\n#endif\n\n#if defined(AO_HAVE_XSIZE_compare_and_swap_full) \\\n    && !defined(AO_HAVE_XSIZE_store_full)\n  AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD\n  AO_INLINE void\n  AO_XSIZE_store_full(volatile XCTYPE *addr, XCTYPE new_val)\n  {\n    XCTYPE old_val;\n\n    do {\n      old_val = *(XCTYPE *)addr;\n    } while (AO_EXPECT_FALSE(!AO_XSIZE_compare_and_swap_full(addr, old_val,\n                                                             new_val)));\n  }\n# define AO_HAVE_XSIZE_store_full\n#endif\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/generalize.h",
    "content": "/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/*\n * Generalize atomic operations for atomic_ops.h.\n * Should not be included directly.\n *\n * We make no attempt to define useless operations, such as\n * AO_nop_acquire\n * AO_nop_release\n *\n * We have also so far neglected to define some others, which\n * do not appear likely to be useful, e.g. stores with acquire\n * or read barriers.\n *\n * This file is sometimes included twice by atomic_ops.h.\n * All definitions include explicit checks that we are not replacing\n * an earlier definition.  In general, more desirable expansions\n * appear earlier so that we are more likely to use them.\n *\n * We only make safe generalizations, except that by default we define\n * the ...dd_acquire_read operations to be equivalent to those without\n * a barrier.  On platforms for which this is unsafe, the platform-specific\n * file must define AO_NO_DD_ORDERING.\n */\n\n#ifndef AO_ATOMIC_OPS_H\n# error This file should not be included directly.\n#endif\n\n/* Generate test_and_set_full, if necessary and possible.       */\n#if !defined(AO_HAVE_test_and_set) && !defined(AO_HAVE_test_and_set_release) \\\n    && !defined(AO_HAVE_test_and_set_acquire) \\\n    && !defined(AO_HAVE_test_and_set_read) \\\n    && !defined(AO_HAVE_test_and_set_full)\n\n  /* Emulate AO_compare_and_swap() via AO_fetch_compare_and_swap().     */\n# if defined(AO_HAVE_fetch_compare_and_swap) \\\n     && !defined(AO_HAVE_compare_and_swap)\n    AO_INLINE int\n    AO_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val)\n    {\n      return AO_fetch_compare_and_swap(addr, old_val, new_val) == old_val;\n    }\n#   define AO_HAVE_compare_and_swap\n# endif\n\n# if defined(AO_HAVE_fetch_compare_and_swap_full) \\\n     && !defined(AO_HAVE_compare_and_swap_full)\n    AO_INLINE int\n    AO_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, AO_t new_val)\n    {\n      return AO_fetch_compare_and_swap_full(addr, old_val, new_val)\n               == old_val;\n    }\n#   define AO_HAVE_compare_and_swap_full\n# endif\n\n# if defined(AO_HAVE_fetch_compare_and_swap_acquire) \\\n     && !defined(AO_HAVE_compare_and_swap_acquire)\n    AO_INLINE int\n    AO_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val,\n                                AO_t new_val)\n    {\n      return AO_fetch_compare_and_swap_acquire(addr, old_val, new_val)\n               == old_val;\n    }\n#   define AO_HAVE_compare_and_swap_acquire\n# endif\n\n# if defined(AO_HAVE_fetch_compare_and_swap_release) \\\n     && !defined(AO_HAVE_compare_and_swap_release)\n    AO_INLINE int\n    AO_compare_and_swap_release(volatile AO_t *addr, AO_t old_val,\n                                AO_t new_val)\n    {\n      return AO_fetch_compare_and_swap_release(addr, old_val, new_val)\n               == old_val;\n    }\n#   define AO_HAVE_compare_and_swap_release\n# endif\n\n# if defined(AO_CHAR_TS_T)\n#   define AO_TS_COMPARE_AND_SWAP_FULL(a,o,n) \\\n                                AO_char_compare_and_swap_full(a,o,n)\n#   define AO_TS_COMPARE_AND_SWAP_ACQUIRE(a,o,n) \\\n                                AO_char_compare_and_swap_acquire(a,o,n)\n#   define AO_TS_COMPARE_AND_SWAP_RELEASE(a,o,n) \\\n                                AO_char_compare_and_swap_release(a,o,n)\n#   define AO_TS_COMPARE_AND_SWAP(a,o,n) AO_char_compare_and_swap(a,o,n)\n# endif\n\n# if defined(AO_AO_TS_T)\n#   define AO_TS_COMPARE_AND_SWAP_FULL(a,o,n) AO_compare_and_swap_full(a,o,n)\n#   define AO_TS_COMPARE_AND_SWAP_ACQUIRE(a,o,n) \\\n                                AO_compare_and_swap_acquire(a,o,n)\n#   define AO_TS_COMPARE_AND_SWAP_RELEASE(a,o,n) \\\n                                AO_compare_and_swap_release(a,o,n)\n#   define AO_TS_COMPARE_AND_SWAP(a,o,n) AO_compare_and_swap(a,o,n)\n# endif\n\n# if (defined(AO_AO_TS_T) && defined(AO_HAVE_compare_and_swap_full)) \\\n     || (defined(AO_CHAR_TS_T) && defined(AO_HAVE_char_compare_and_swap_full))\n    AO_INLINE AO_TS_VAL_t\n    AO_test_and_set_full(volatile AO_TS_t *addr)\n    {\n      if (AO_TS_COMPARE_AND_SWAP_FULL(addr, AO_TS_CLEAR, AO_TS_SET))\n        return AO_TS_CLEAR;\n      else\n        return AO_TS_SET;\n    }\n#   define AO_HAVE_test_and_set_full\n# endif /* AO_HAVE_compare_and_swap_full */\n\n# if (defined(AO_AO_TS_T) && defined(AO_HAVE_compare_and_swap_acquire)) \\\n     || (defined(AO_CHAR_TS_T) \\\n         && defined(AO_HAVE_char_compare_and_swap_acquire))\n    AO_INLINE AO_TS_VAL_t\n    AO_test_and_set_acquire(volatile AO_TS_t *addr)\n    {\n      if (AO_TS_COMPARE_AND_SWAP_ACQUIRE(addr, AO_TS_CLEAR, AO_TS_SET))\n        return AO_TS_CLEAR;\n      else\n        return AO_TS_SET;\n    }\n#   define AO_HAVE_test_and_set_acquire\n# endif /* AO_HAVE_compare_and_swap_acquire */\n\n# if (defined(AO_AO_TS_T) && defined(AO_HAVE_compare_and_swap_release)) \\\n     || (defined(AO_CHAR_TS_T) \\\n         && defined(AO_HAVE_char_compare_and_swap_release))\n    AO_INLINE AO_TS_VAL_t\n    AO_test_and_set_release(volatile AO_TS_t *addr)\n    {\n      if (AO_TS_COMPARE_AND_SWAP_RELEASE(addr, AO_TS_CLEAR, AO_TS_SET))\n        return AO_TS_CLEAR;\n      else\n        return AO_TS_SET;\n    }\n#   define AO_HAVE_test_and_set_release\n# endif /* AO_HAVE_compare_and_swap_release */\n\n# if (defined(AO_AO_TS_T) && defined(AO_HAVE_compare_and_swap)) \\\n     || (defined(AO_CHAR_TS_T) && defined(AO_HAVE_char_compare_and_swap))\n    AO_INLINE AO_TS_VAL_t\n    AO_test_and_set(volatile AO_TS_t *addr)\n    {\n      if (AO_TS_COMPARE_AND_SWAP(addr, AO_TS_CLEAR, AO_TS_SET))\n        return AO_TS_CLEAR;\n      else\n        return AO_TS_SET;\n    }\n#   define AO_HAVE_test_and_set\n# endif /* AO_HAVE_compare_and_swap */\n#endif /* No prior test and set */\n\n/* Nop */\n#if !defined(AO_HAVE_nop)\n  AO_INLINE void AO_nop(void) {}\n# define AO_HAVE_nop\n#endif\n\n#if defined(AO_HAVE_test_and_set_full) && !defined(AO_HAVE_nop_full)\n  AO_INLINE void\n  AO_nop_full(void)\n  {\n    AO_TS_t dummy = AO_TS_INITIALIZER;\n    AO_test_and_set_full(&dummy);\n  }\n# define AO_HAVE_nop_full\n#endif\n\n#if defined(AO_HAVE_nop_acquire) && !defined(CPPCHECK)\n# error AO_nop_acquire is useless: do not define.\n#endif\n\n#if defined(AO_HAVE_nop_release) && !defined(CPPCHECK)\n# error AO_nop_release is useless: do not define.\n#endif\n\n#if defined(AO_HAVE_nop_full) && !defined(AO_HAVE_nop_read)\n# define AO_nop_read() AO_nop_full()\n# define AO_HAVE_nop_read\n#endif\n\n#if defined(AO_HAVE_nop_full) && !defined(AO_HAVE_nop_write)\n# define AO_nop_write() AO_nop_full()\n# define AO_HAVE_nop_write\n#endif\n\n/* Test_and_set */\n#if defined(AO_HAVE_test_and_set) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_test_and_set_release)\n# define AO_test_and_set_release(addr) (AO_nop_full(), AO_test_and_set(addr))\n# define AO_HAVE_test_and_set_release\n#endif\n\n#if defined(AO_HAVE_test_and_set) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_test_and_set_acquire)\n  AO_INLINE AO_TS_VAL_t\n  AO_test_and_set_acquire(volatile AO_TS_t *addr)\n  {\n    AO_TS_VAL_t result = AO_test_and_set(addr);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_test_and_set_acquire\n#endif\n\n#if defined(AO_HAVE_test_and_set_full)\n# if !defined(AO_HAVE_test_and_set_release)\n#   define AO_test_and_set_release(addr) AO_test_and_set_full(addr)\n#   define AO_HAVE_test_and_set_release\n# endif\n# if !defined(AO_HAVE_test_and_set_acquire)\n#   define AO_test_and_set_acquire(addr) AO_test_and_set_full(addr)\n#   define AO_HAVE_test_and_set_acquire\n# endif\n# if !defined(AO_HAVE_test_and_set_write)\n#   define AO_test_and_set_write(addr) AO_test_and_set_full(addr)\n#   define AO_HAVE_test_and_set_write\n# endif\n# if !defined(AO_HAVE_test_and_set_read)\n#   define AO_test_and_set_read(addr) AO_test_and_set_full(addr)\n#   define AO_HAVE_test_and_set_read\n# endif\n#endif /* AO_HAVE_test_and_set_full */\n\n#if !defined(AO_HAVE_test_and_set) && defined(AO_HAVE_test_and_set_release)\n# define AO_test_and_set(addr) AO_test_and_set_release(addr)\n# define AO_HAVE_test_and_set\n#endif\n#if !defined(AO_HAVE_test_and_set) && defined(AO_HAVE_test_and_set_acquire)\n# define AO_test_and_set(addr) AO_test_and_set_acquire(addr)\n# define AO_HAVE_test_and_set\n#endif\n#if !defined(AO_HAVE_test_and_set) && defined(AO_HAVE_test_and_set_write)\n# define AO_test_and_set(addr) AO_test_and_set_write(addr)\n# define AO_HAVE_test_and_set\n#endif\n#if !defined(AO_HAVE_test_and_set) && defined(AO_HAVE_test_and_set_read)\n# define AO_test_and_set(addr) AO_test_and_set_read(addr)\n# define AO_HAVE_test_and_set\n#endif\n\n#if defined(AO_HAVE_test_and_set_acquire) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_test_and_set_full)\n# define AO_test_and_set_full(addr) \\\n                        (AO_nop_full(), AO_test_and_set_acquire(addr))\n# define AO_HAVE_test_and_set_full\n#endif\n\n#if !defined(AO_HAVE_test_and_set_release_write) \\\n    && defined(AO_HAVE_test_and_set_write)\n# define AO_test_and_set_release_write(addr) AO_test_and_set_write(addr)\n# define AO_HAVE_test_and_set_release_write\n#endif\n#if !defined(AO_HAVE_test_and_set_release_write) \\\n    && defined(AO_HAVE_test_and_set_release)\n# define AO_test_and_set_release_write(addr) AO_test_and_set_release(addr)\n# define AO_HAVE_test_and_set_release_write\n#endif\n#if !defined(AO_HAVE_test_and_set_acquire_read) \\\n    && defined(AO_HAVE_test_and_set_read)\n# define AO_test_and_set_acquire_read(addr) AO_test_and_set_read(addr)\n# define AO_HAVE_test_and_set_acquire_read\n#endif\n#if !defined(AO_HAVE_test_and_set_acquire_read) \\\n    && defined(AO_HAVE_test_and_set_acquire)\n# define AO_test_and_set_acquire_read(addr) AO_test_and_set_acquire(addr)\n# define AO_HAVE_test_and_set_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_test_and_set_acquire_read)\n#   define AO_test_and_set_dd_acquire_read(addr) \\\n                                        AO_test_and_set_acquire_read(addr)\n#   define AO_HAVE_test_and_set_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_test_and_set)\n#   define AO_test_and_set_dd_acquire_read(addr) AO_test_and_set(addr)\n#   define AO_HAVE_test_and_set_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n#include \"generalize-small.h\"\n\n#include \"generalize-arithm.h\"\n\n/* Compare_double_and_swap_double based on double_compare_and_swap.     */\n#ifdef AO_HAVE_DOUBLE_PTR_STORAGE\n# if defined(AO_HAVE_double_compare_and_swap) \\\n     && !defined(AO_HAVE_compare_double_and_swap_double)\n   AO_INLINE int\n   AO_compare_double_and_swap_double(volatile AO_double_t *addr,\n                                     AO_t old_val1, AO_t old_val2,\n                                     AO_t new_val1, AO_t new_val2)\n   {\n     AO_double_t old_w;\n     AO_double_t new_w;\n     old_w.AO_val1 = old_val1;\n     old_w.AO_val2 = old_val2;\n     new_w.AO_val1 = new_val1;\n     new_w.AO_val2 = new_val2;\n     return AO_double_compare_and_swap(addr, old_w, new_w);\n   }\n#  define AO_HAVE_compare_double_and_swap_double\n# endif\n# if defined(AO_HAVE_double_compare_and_swap_acquire) \\\n     && !defined(AO_HAVE_compare_double_and_swap_double_acquire)\n    AO_INLINE int\n    AO_compare_double_and_swap_double_acquire(volatile AO_double_t *addr,\n                                              AO_t old_val1, AO_t old_val2,\n                                              AO_t new_val1, AO_t new_val2)\n    {\n      AO_double_t old_w;\n      AO_double_t new_w;\n      old_w.AO_val1 = old_val1;\n      old_w.AO_val2 = old_val2;\n      new_w.AO_val1 = new_val1;\n      new_w.AO_val2 = new_val2;\n      return AO_double_compare_and_swap_acquire(addr, old_w, new_w);\n    }\n#   define AO_HAVE_compare_double_and_swap_double_acquire\n# endif\n# if defined(AO_HAVE_double_compare_and_swap_release) \\\n     && !defined(AO_HAVE_compare_double_and_swap_double_release)\n    AO_INLINE int\n    AO_compare_double_and_swap_double_release(volatile AO_double_t *addr,\n                                              AO_t old_val1, AO_t old_val2,\n                                              AO_t new_val1, AO_t new_val2)\n    {\n      AO_double_t old_w;\n      AO_double_t new_w;\n      old_w.AO_val1 = old_val1;\n      old_w.AO_val2 = old_val2;\n      new_w.AO_val1 = new_val1;\n      new_w.AO_val2 = new_val2;\n      return AO_double_compare_and_swap_release(addr, old_w, new_w);\n    }\n#   define AO_HAVE_compare_double_and_swap_double_release\n# endif\n# if defined(AO_HAVE_double_compare_and_swap_full) \\\n     && !defined(AO_HAVE_compare_double_and_swap_double_full)\n    AO_INLINE int\n    AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,\n                                           AO_t old_val1, AO_t old_val2,\n                                           AO_t new_val1, AO_t new_val2)\n    {\n      AO_double_t old_w;\n      AO_double_t new_w;\n      old_w.AO_val1 = old_val1;\n      old_w.AO_val2 = old_val2;\n      new_w.AO_val1 = new_val1;\n      new_w.AO_val2 = new_val2;\n      return AO_double_compare_and_swap_full(addr, old_w, new_w);\n    }\n#   define AO_HAVE_compare_double_and_swap_double_full\n# endif\n#endif /* AO_HAVE_DOUBLE_PTR_STORAGE */\n\n/* Compare_double_and_swap_double */\n#if defined(AO_HAVE_compare_double_and_swap_double) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_compare_double_and_swap_double_acquire)\n  AO_INLINE int\n  AO_compare_double_and_swap_double_acquire(volatile AO_double_t *addr,\n                                            AO_t o1, AO_t o2,\n                                            AO_t n1, AO_t n2)\n  {\n    int result = AO_compare_double_and_swap_double(addr, o1, o2, n1, n2);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_compare_double_and_swap_double_acquire\n#endif\n#if defined(AO_HAVE_compare_double_and_swap_double) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_compare_double_and_swap_double_release)\n# define AO_compare_double_and_swap_double_release(addr,o1,o2,n1,n2) \\\n      (AO_nop_full(), AO_compare_double_and_swap_double(addr,o1,o2,n1,n2))\n# define AO_HAVE_compare_double_and_swap_double_release\n#endif\n#if defined(AO_HAVE_compare_double_and_swap_double_full)\n# if !defined(AO_HAVE_compare_double_and_swap_double_release)\n#   define AO_compare_double_and_swap_double_release(addr,o1,o2,n1,n2) \\\n                AO_compare_double_and_swap_double_full(addr,o1,o2,n1,n2)\n#   define AO_HAVE_compare_double_and_swap_double_release\n# endif\n# if !defined(AO_HAVE_compare_double_and_swap_double_acquire)\n#   define AO_compare_double_and_swap_double_acquire(addr,o1,o2,n1,n2) \\\n                AO_compare_double_and_swap_double_full(addr,o1,o2,n1,n2)\n#   define AO_HAVE_compare_double_and_swap_double_acquire\n# endif\n# if !defined(AO_HAVE_compare_double_and_swap_double_write)\n#   define AO_compare_double_and_swap_double_write(addr,o1,o2,n1,n2) \\\n                AO_compare_double_and_swap_double_full(addr,o1,o2,n1,n2)\n#   define AO_HAVE_compare_double_and_swap_double_write\n# endif\n# if !defined(AO_HAVE_compare_double_and_swap_double_read)\n#   define AO_compare_double_and_swap_double_read(addr,o1,o2,n1,n2) \\\n                AO_compare_double_and_swap_double_full(addr,o1,o2,n1,n2)\n#   define AO_HAVE_compare_double_and_swap_double_read\n# endif\n#endif /* AO_HAVE_compare_double_and_swap_double_full */\n\n#if !defined(AO_HAVE_compare_double_and_swap_double) \\\n    && defined(AO_HAVE_compare_double_and_swap_double_release)\n# define AO_compare_double_and_swap_double(addr,o1,o2,n1,n2) \\\n                AO_compare_double_and_swap_double_release(addr,o1,o2,n1,n2)\n# define AO_HAVE_compare_double_and_swap_double\n#endif\n#if !defined(AO_HAVE_compare_double_and_swap_double) \\\n    && defined(AO_HAVE_compare_double_and_swap_double_acquire)\n# define AO_compare_double_and_swap_double(addr,o1,o2,n1,n2) \\\n                AO_compare_double_and_swap_double_acquire(addr,o1,o2,n1,n2)\n# define AO_HAVE_compare_double_and_swap_double\n#endif\n#if !defined(AO_HAVE_compare_double_and_swap_double) \\\n    && defined(AO_HAVE_compare_double_and_swap_double_write)\n# define AO_compare_double_and_swap_double(addr,o1,o2,n1,n2) \\\n                AO_compare_double_and_swap_double_write(addr,o1,o2,n1,n2)\n# define AO_HAVE_compare_double_and_swap_double\n#endif\n#if !defined(AO_HAVE_compare_double_and_swap_double) \\\n    && defined(AO_HAVE_compare_double_and_swap_double_read)\n# define AO_compare_double_and_swap_double(addr,o1,o2,n1,n2) \\\n                AO_compare_double_and_swap_double_read(addr,o1,o2,n1,n2)\n# define AO_HAVE_compare_double_and_swap_double\n#endif\n\n#if defined(AO_HAVE_compare_double_and_swap_double_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_compare_double_and_swap_double_full)\n# define AO_compare_double_and_swap_double_full(addr,o1,o2,n1,n2) \\\n                (AO_nop_full(), \\\n                 AO_compare_double_and_swap_double_acquire(addr,o1,o2,n1,n2))\n# define AO_HAVE_compare_double_and_swap_double_full\n#endif\n\n#if !defined(AO_HAVE_compare_double_and_swap_double_release_write) \\\n    && defined(AO_HAVE_compare_double_and_swap_double_write)\n# define AO_compare_double_and_swap_double_release_write(addr,o1,o2,n1,n2) \\\n                AO_compare_double_and_swap_double_write(addr,o1,o2,n1,n2)\n# define AO_HAVE_compare_double_and_swap_double_release_write\n#endif\n#if !defined(AO_HAVE_compare_double_and_swap_double_release_write) \\\n    && defined(AO_HAVE_compare_double_and_swap_double_release)\n# define AO_compare_double_and_swap_double_release_write(addr,o1,o2,n1,n2) \\\n                AO_compare_double_and_swap_double_release(addr,o1,o2,n1,n2)\n# define AO_HAVE_compare_double_and_swap_double_release_write\n#endif\n#if !defined(AO_HAVE_compare_double_and_swap_double_acquire_read) \\\n    && defined(AO_HAVE_compare_double_and_swap_double_read)\n# define AO_compare_double_and_swap_double_acquire_read(addr,o1,o2,n1,n2) \\\n                AO_compare_double_and_swap_double_read(addr,o1,o2,n1,n2)\n# define AO_HAVE_compare_double_and_swap_double_acquire_read\n#endif\n#if !defined(AO_HAVE_compare_double_and_swap_double_acquire_read) \\\n    && defined(AO_HAVE_compare_double_and_swap_double_acquire)\n# define AO_compare_double_and_swap_double_acquire_read(addr,o1,o2,n1,n2) \\\n                AO_compare_double_and_swap_double_acquire(addr,o1,o2,n1,n2)\n# define AO_HAVE_compare_double_and_swap_double_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_compare_double_and_swap_double_acquire_read)\n#   define AO_compare_double_and_swap_double_dd_acquire_read(addr,o1,o2,n1,n2) \\\n             AO_compare_double_and_swap_double_acquire_read(addr,o1,o2,n1,n2)\n#   define AO_HAVE_compare_double_and_swap_double_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_compare_double_and_swap_double)\n#   define AO_compare_double_and_swap_double_dd_acquire_read(addr,o1,o2,n1,n2) \\\n                        AO_compare_double_and_swap_double(addr,o1,o2,n1,n2)\n#   define AO_HAVE_compare_double_and_swap_double_dd_acquire_read\n# endif\n#endif /* !AO_NO_DD_ORDERING */\n\n/* Compare_and_swap_double */\n#if defined(AO_HAVE_compare_and_swap_double) && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_compare_and_swap_double_acquire)\n  AO_INLINE int\n  AO_compare_and_swap_double_acquire(volatile AO_double_t *addr,\n                                            AO_t o1,\n                                            AO_t n1, AO_t n2)\n  {\n    int result = AO_compare_and_swap_double(addr, o1, n1, n2);\n    AO_nop_full();\n    return result;\n  }\n# define AO_HAVE_compare_and_swap_double_acquire\n#endif\n#if defined(AO_HAVE_compare_and_swap_double) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_compare_and_swap_double_release)\n# define AO_compare_and_swap_double_release(addr,o1,n1,n2) \\\n                (AO_nop_full(), AO_compare_and_swap_double(addr,o1,n1,n2))\n# define AO_HAVE_compare_and_swap_double_release\n#endif\n#if defined(AO_HAVE_compare_and_swap_double_full)\n# if !defined(AO_HAVE_compare_and_swap_double_release)\n#   define AO_compare_and_swap_double_release(addr,o1,n1,n2) \\\n                                AO_compare_and_swap_double_full(addr,o1,n1,n2)\n#   define AO_HAVE_compare_and_swap_double_release\n# endif\n# if !defined(AO_HAVE_compare_and_swap_double_acquire)\n#   define AO_compare_and_swap_double_acquire(addr,o1,n1,n2) \\\n                                AO_compare_and_swap_double_full(addr,o1,n1,n2)\n#   define AO_HAVE_compare_and_swap_double_acquire\n# endif\n# if !defined(AO_HAVE_compare_and_swap_double_write)\n#   define AO_compare_and_swap_double_write(addr,o1,n1,n2) \\\n                                AO_compare_and_swap_double_full(addr,o1,n1,n2)\n#   define AO_HAVE_compare_and_swap_double_write\n# endif\n# if !defined(AO_HAVE_compare_and_swap_double_read)\n#   define AO_compare_and_swap_double_read(addr,o1,n1,n2) \\\n                                AO_compare_and_swap_double_full(addr,o1,n1,n2)\n#   define AO_HAVE_compare_and_swap_double_read\n# endif\n#endif /* AO_HAVE_compare_and_swap_double_full */\n\n#if !defined(AO_HAVE_compare_and_swap_double) \\\n    && defined(AO_HAVE_compare_and_swap_double_release)\n# define AO_compare_and_swap_double(addr,o1,n1,n2) \\\n                        AO_compare_and_swap_double_release(addr,o1,n1,n2)\n# define AO_HAVE_compare_and_swap_double\n#endif\n#if !defined(AO_HAVE_compare_and_swap_double) \\\n    && defined(AO_HAVE_compare_and_swap_double_acquire)\n# define AO_compare_and_swap_double(addr,o1,n1,n2) \\\n                        AO_compare_and_swap_double_acquire(addr,o1,n1,n2)\n# define AO_HAVE_compare_and_swap_double\n#endif\n#if !defined(AO_HAVE_compare_and_swap_double) \\\n    && defined(AO_HAVE_compare_and_swap_double_write)\n# define AO_compare_and_swap_double(addr,o1,n1,n2) \\\n                        AO_compare_and_swap_double_write(addr,o1,n1,n2)\n# define AO_HAVE_compare_and_swap_double\n#endif\n#if !defined(AO_HAVE_compare_and_swap_double) \\\n    && defined(AO_HAVE_compare_and_swap_double_read)\n# define AO_compare_and_swap_double(addr,o1,n1,n2) \\\n                        AO_compare_and_swap_double_read(addr,o1,n1,n2)\n# define AO_HAVE_compare_and_swap_double\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_double_acquire) \\\n    && defined(AO_HAVE_nop_full) \\\n    && !defined(AO_HAVE_compare_and_swap_double_full)\n# define AO_compare_and_swap_double_full(addr,o1,n1,n2) \\\n        (AO_nop_full(), AO_compare_and_swap_double_acquire(addr,o1,n1,n2))\n# define AO_HAVE_compare_and_swap_double_full\n#endif\n\n#if !defined(AO_HAVE_compare_and_swap_double_release_write) \\\n    && defined(AO_HAVE_compare_and_swap_double_write)\n# define AO_compare_and_swap_double_release_write(addr,o1,n1,n2) \\\n                        AO_compare_and_swap_double_write(addr,o1,n1,n2)\n# define AO_HAVE_compare_and_swap_double_release_write\n#endif\n#if !defined(AO_HAVE_compare_and_swap_double_release_write) \\\n    && defined(AO_HAVE_compare_and_swap_double_release)\n# define AO_compare_and_swap_double_release_write(addr,o1,n1,n2) \\\n                        AO_compare_and_swap_double_release(addr,o1,n1,n2)\n# define AO_HAVE_compare_and_swap_double_release_write\n#endif\n#if !defined(AO_HAVE_compare_and_swap_double_acquire_read) \\\n    && defined(AO_HAVE_compare_and_swap_double_read)\n# define AO_compare_and_swap_double_acquire_read(addr,o1,n1,n2) \\\n                        AO_compare_and_swap_double_read(addr,o1,n1,n2)\n# define AO_HAVE_compare_and_swap_double_acquire_read\n#endif\n#if !defined(AO_HAVE_compare_and_swap_double_acquire_read) \\\n    && defined(AO_HAVE_compare_and_swap_double_acquire)\n# define AO_compare_and_swap_double_acquire_read(addr,o1,n1,n2) \\\n                        AO_compare_and_swap_double_acquire(addr,o1,n1,n2)\n# define AO_HAVE_compare_and_swap_double_acquire_read\n#endif\n\n#ifdef AO_NO_DD_ORDERING\n# if defined(AO_HAVE_compare_and_swap_double_acquire_read)\n#   define AO_compare_and_swap_double_dd_acquire_read(addr,o1,n1,n2) \\\n                        AO_compare_and_swap_double_acquire_read(addr,o1,n1,n2)\n#   define AO_HAVE_compare_and_swap_double_dd_acquire_read\n# endif\n#else\n# if defined(AO_HAVE_compare_and_swap_double)\n#   define AO_compare_and_swap_double_dd_acquire_read(addr,o1,n1,n2) \\\n                        AO_compare_and_swap_double(addr,o1,n1,n2)\n#   define AO_HAVE_compare_and_swap_double_dd_acquire_read\n# endif\n#endif\n\n/* Convenience functions for AO_double compare-and-swap which types and */\n/* reads easier in code.                                                */\n#if defined(AO_HAVE_compare_double_and_swap_double) \\\n    && !defined(AO_HAVE_double_compare_and_swap)\n  AO_INLINE int\n  AO_double_compare_and_swap(volatile AO_double_t *addr,\n                             AO_double_t old_val, AO_double_t new_val)\n  {\n    return AO_compare_double_and_swap_double(addr,\n                                        old_val.AO_val1, old_val.AO_val2,\n                                        new_val.AO_val1, new_val.AO_val2);\n  }\n# define AO_HAVE_double_compare_and_swap\n#endif\n#if defined(AO_HAVE_compare_double_and_swap_double_release) \\\n    && !defined(AO_HAVE_double_compare_and_swap_release)\n  AO_INLINE int\n  AO_double_compare_and_swap_release(volatile AO_double_t *addr,\n                                     AO_double_t old_val, AO_double_t new_val)\n  {\n    return AO_compare_double_and_swap_double_release(addr,\n                                          old_val.AO_val1, old_val.AO_val2,\n                                          new_val.AO_val1, new_val.AO_val2);\n  }\n# define AO_HAVE_double_compare_and_swap_release\n#endif\n#if defined(AO_HAVE_compare_double_and_swap_double_acquire) \\\n    && !defined(AO_HAVE_double_compare_and_swap_acquire)\n  AO_INLINE int\n  AO_double_compare_and_swap_acquire(volatile AO_double_t *addr,\n                                     AO_double_t old_val, AO_double_t new_val)\n  {\n    return AO_compare_double_and_swap_double_acquire(addr,\n                                          old_val.AO_val1, old_val.AO_val2,\n                                          new_val.AO_val1, new_val.AO_val2);\n  }\n# define AO_HAVE_double_compare_and_swap_acquire\n#endif\n#if defined(AO_HAVE_compare_double_and_swap_double_read) \\\n    && !defined(AO_HAVE_double_compare_and_swap_read)\n  AO_INLINE int\n  AO_double_compare_and_swap_read(volatile AO_double_t *addr,\n                                  AO_double_t old_val, AO_double_t new_val)\n  {\n    return AO_compare_double_and_swap_double_read(addr,\n                                          old_val.AO_val1, old_val.AO_val2,\n                                          new_val.AO_val1, new_val.AO_val2);\n  }\n# define AO_HAVE_double_compare_and_swap_read\n#endif\n#if defined(AO_HAVE_compare_double_and_swap_double_write) \\\n    && !defined(AO_HAVE_double_compare_and_swap_write)\n  AO_INLINE int\n  AO_double_compare_and_swap_write(volatile AO_double_t *addr,\n                                   AO_double_t old_val, AO_double_t new_val)\n  {\n    return AO_compare_double_and_swap_double_write(addr,\n                                          old_val.AO_val1, old_val.AO_val2,\n                                          new_val.AO_val1, new_val.AO_val2);\n  }\n# define AO_HAVE_double_compare_and_swap_write\n#endif\n#if defined(AO_HAVE_compare_double_and_swap_double_release_write) \\\n    && !defined(AO_HAVE_double_compare_and_swap_release_write)\n  AO_INLINE int\n  AO_double_compare_and_swap_release_write(volatile AO_double_t *addr,\n                                AO_double_t old_val, AO_double_t new_val)\n  {\n    return AO_compare_double_and_swap_double_release_write(addr,\n                                          old_val.AO_val1, old_val.AO_val2,\n                                          new_val.AO_val1, new_val.AO_val2);\n  }\n# define AO_HAVE_double_compare_and_swap_release_write\n#endif\n#if defined(AO_HAVE_compare_double_and_swap_double_acquire_read) \\\n    && !defined(AO_HAVE_double_compare_and_swap_acquire_read)\n  AO_INLINE int\n  AO_double_compare_and_swap_acquire_read(volatile AO_double_t *addr,\n                                AO_double_t old_val, AO_double_t new_val)\n  {\n    return AO_compare_double_and_swap_double_acquire_read(addr,\n                                          old_val.AO_val1, old_val.AO_val2,\n                                          new_val.AO_val1, new_val.AO_val2);\n  }\n# define AO_HAVE_double_compare_and_swap_acquire_read\n#endif\n#if defined(AO_HAVE_compare_double_and_swap_double_full) \\\n    && !defined(AO_HAVE_double_compare_and_swap_full)\n  AO_INLINE int\n  AO_double_compare_and_swap_full(volatile AO_double_t *addr,\n                                  AO_double_t old_val, AO_double_t new_val)\n  {\n    return AO_compare_double_and_swap_double_full(addr,\n                                          old_val.AO_val1, old_val.AO_val2,\n                                          new_val.AO_val1, new_val.AO_val2);\n  }\n# define AO_HAVE_double_compare_and_swap_full\n#endif\n\n#ifndef AO_HAVE_double_compare_and_swap_dd_acquire_read\n  /* Duplicated from generalize-small because double CAS might be       */\n  /* defined after the include.                                         */\n# ifdef AO_NO_DD_ORDERING\n#   if defined(AO_HAVE_double_compare_and_swap_acquire_read)\n#     define AO_double_compare_and_swap_dd_acquire_read(addr, old, new_val) \\\n                AO_double_compare_and_swap_acquire_read(addr, old, new_val)\n#     define AO_HAVE_double_compare_and_swap_dd_acquire_read\n#   endif\n# elif defined(AO_HAVE_double_compare_and_swap)\n#   define AO_double_compare_and_swap_dd_acquire_read(addr, old, new_val) \\\n                AO_double_compare_and_swap(addr, old, new_val)\n#   define AO_HAVE_double_compare_and_swap_dd_acquire_read\n# endif /* !AO_NO_DD_ORDERING */\n#endif\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/all_acquire_release_volatile.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Describes architectures on which volatile AO_t, unsigned char,       */\n/* unsigned short, and unsigned int loads and stores have               */\n/* acquire/release semantics for all normally legal alignments.         */\n\n#include \"loadstore/acquire_release_volatile.h\"\n#include \"loadstore/char_acquire_release_volatile.h\"\n#include \"loadstore/short_acquire_release_volatile.h\"\n#include \"loadstore/int_acquire_release_volatile.h\"\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/all_aligned_atomic_load_store.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Describes architectures on which AO_t, unsigned char, unsigned       */\n/* short, and unsigned int loads and stores are atomic but only if data */\n/* is suitably aligned.                                                 */\n\n#if defined(__m68k__) && !defined(AO_ALIGNOF_SUPPORTED)\n  /* Even though AO_t is redefined in m68k.h, some clients use AO       */\n  /* pointer size primitives to access variables not declared as AO_t.  */\n  /* Such variables may have 2-byte alignment, while their sizeof is 4. */\n#else\n# define AO_ACCESS_CHECK_ALIGNED\n#endif\n\n/* Check for char type is a misnomer.   */\n#define AO_ACCESS_short_CHECK_ALIGNED\n#define AO_ACCESS_int_CHECK_ALIGNED\n#include \"all_atomic_load_store.h\"\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/all_atomic_load_store.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Describes architectures on which AO_t, unsigned char, unsigned       */\n/* short, and unsigned int loads and stores are atomic for all normally */\n/* legal alignments.                                                    */\n\n#include \"all_atomic_only_load.h\"\n\n#include \"loadstore/atomic_store.h\"\n#include \"loadstore/char_atomic_store.h\"\n#include \"loadstore/short_atomic_store.h\"\n#include \"loadstore/int_atomic_store.h\"\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/all_atomic_only_load.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Describes architectures on which AO_t, unsigned char, unsigned       */\n/* short, and unsigned int loads are atomic for all normally legal      */\n/* alignments.                                                          */\n\n#include \"loadstore/atomic_load.h\"\n#include \"loadstore/char_atomic_load.h\"\n#include \"loadstore/short_atomic_load.h\"\n#include \"loadstore/int_atomic_load.h\"\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/ao_t_is_int.h",
    "content": "/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Inclusion of this file signifies that AO_t is in fact int.           */\n/* Hence any AO_... operation can also serve as AO_int_... operation.   */\n\n#if defined(AO_HAVE_load) && !defined(AO_HAVE_int_load)\n# define AO_int_load(addr) \\\n                (unsigned)AO_load((const volatile AO_t *)(addr))\n# define AO_HAVE_int_load\n#endif\n\n#if defined(AO_HAVE_store) && !defined(AO_HAVE_int_store)\n# define AO_int_store(addr, val) \\\n                AO_store((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_store\n#endif\n\n#if defined(AO_HAVE_fetch_and_add) \\\n    && !defined(AO_HAVE_int_fetch_and_add)\n# define AO_int_fetch_and_add(addr, incr) \\\n                (unsigned)AO_fetch_and_add((volatile AO_t *)(addr), \\\n                                                (AO_t)(incr))\n# define AO_HAVE_int_fetch_and_add\n#endif\n\n#if defined(AO_HAVE_fetch_and_add1) \\\n    && !defined(AO_HAVE_int_fetch_and_add1)\n# define AO_int_fetch_and_add1(addr) \\\n                (unsigned)AO_fetch_and_add1((volatile AO_t *)(addr))\n# define AO_HAVE_int_fetch_and_add1\n#endif\n\n#if defined(AO_HAVE_fetch_and_sub1) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1)\n# define AO_int_fetch_and_sub1(addr) \\\n                (unsigned)AO_fetch_and_sub1((volatile AO_t *)(addr))\n# define AO_HAVE_int_fetch_and_sub1\n#endif\n\n#if defined(AO_HAVE_and) && !defined(AO_HAVE_int_and)\n# define AO_int_and(addr, val) \\\n                AO_and((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_and\n#endif\n\n#if defined(AO_HAVE_or) && !defined(AO_HAVE_int_or)\n# define AO_int_or(addr, val) \\\n                AO_or((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_or\n#endif\n\n#if defined(AO_HAVE_xor) && !defined(AO_HAVE_int_xor)\n# define AO_int_xor(addr, val) \\\n                AO_xor((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_xor\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap) \\\n    && !defined(AO_HAVE_int_fetch_compare_and_swap)\n# define AO_int_fetch_compare_and_swap(addr, old, new_val) \\\n        (unsigned)AO_fetch_compare_and_swap((volatile AO_t *)(addr), \\\n                                                 (AO_t)(old), (AO_t)(new_val))\n# define AO_HAVE_int_fetch_compare_and_swap\n#endif\n\n#if defined(AO_HAVE_compare_and_swap) \\\n    && !defined(AO_HAVE_int_compare_and_swap)\n# define AO_int_compare_and_swap(addr, old, new_val) \\\n                AO_compare_and_swap((volatile AO_t *)(addr), \\\n                                         (AO_t)(old), (AO_t)(new_val))\n# define AO_HAVE_int_compare_and_swap\n#endif\n/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Inclusion of this file signifies that AO_t is in fact int.           */\n/* Hence any AO_... operation can also serve as AO_int_... operation.   */\n\n#if defined(AO_HAVE_load_full) && !defined(AO_HAVE_int_load_full)\n# define AO_int_load_full(addr) \\\n                (unsigned)AO_load_full((const volatile AO_t *)(addr))\n# define AO_HAVE_int_load_full\n#endif\n\n#if defined(AO_HAVE_store_full) && !defined(AO_HAVE_int_store_full)\n# define AO_int_store_full(addr, val) \\\n                AO_store_full((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_store_full\n#endif\n\n#if defined(AO_HAVE_fetch_and_add_full) \\\n    && !defined(AO_HAVE_int_fetch_and_add_full)\n# define AO_int_fetch_and_add_full(addr, incr) \\\n                (unsigned)AO_fetch_and_add_full((volatile AO_t *)(addr), \\\n                                                (AO_t)(incr))\n# define AO_HAVE_int_fetch_and_add_full\n#endif\n\n#if defined(AO_HAVE_fetch_and_add1_full) \\\n    && !defined(AO_HAVE_int_fetch_and_add1_full)\n# define AO_int_fetch_and_add1_full(addr) \\\n                (unsigned)AO_fetch_and_add1_full((volatile AO_t *)(addr))\n# define AO_HAVE_int_fetch_and_add1_full\n#endif\n\n#if defined(AO_HAVE_fetch_and_sub1_full) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1_full)\n# define AO_int_fetch_and_sub1_full(addr) \\\n                (unsigned)AO_fetch_and_sub1_full((volatile AO_t *)(addr))\n# define AO_HAVE_int_fetch_and_sub1_full\n#endif\n\n#if defined(AO_HAVE_and_full) && !defined(AO_HAVE_int_and_full)\n# define AO_int_and_full(addr, val) \\\n                AO_and_full((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_and_full\n#endif\n\n#if defined(AO_HAVE_or_full) && !defined(AO_HAVE_int_or_full)\n# define AO_int_or_full(addr, val) \\\n                AO_or_full((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_or_full\n#endif\n\n#if defined(AO_HAVE_xor_full) && !defined(AO_HAVE_int_xor_full)\n# define AO_int_xor_full(addr, val) \\\n                AO_xor_full((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_xor_full\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap_full) \\\n    && !defined(AO_HAVE_int_fetch_compare_and_swap_full)\n# define AO_int_fetch_compare_and_swap_full(addr, old, new_val) \\\n        (unsigned)AO_fetch_compare_and_swap_full((volatile AO_t *)(addr), \\\n                                                 (AO_t)(old), (AO_t)(new_val))\n# define AO_HAVE_int_fetch_compare_and_swap_full\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_full) \\\n    && !defined(AO_HAVE_int_compare_and_swap_full)\n# define AO_int_compare_and_swap_full(addr, old, new_val) \\\n                AO_compare_and_swap_full((volatile AO_t *)(addr), \\\n                                         (AO_t)(old), (AO_t)(new_val))\n# define AO_HAVE_int_compare_and_swap_full\n#endif\n/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Inclusion of this file signifies that AO_t is in fact int.           */\n/* Hence any AO_... operation can also serve as AO_int_... operation.   */\n\n#if defined(AO_HAVE_load_acquire) && !defined(AO_HAVE_int_load_acquire)\n# define AO_int_load_acquire(addr) \\\n                (unsigned)AO_load_acquire((const volatile AO_t *)(addr))\n# define AO_HAVE_int_load_acquire\n#endif\n\n#if defined(AO_HAVE_store_acquire) && !defined(AO_HAVE_int_store_acquire)\n# define AO_int_store_acquire(addr, val) \\\n                AO_store_acquire((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_store_acquire\n#endif\n\n#if defined(AO_HAVE_fetch_and_add_acquire) \\\n    && !defined(AO_HAVE_int_fetch_and_add_acquire)\n# define AO_int_fetch_and_add_acquire(addr, incr) \\\n                (unsigned)AO_fetch_and_add_acquire((volatile AO_t *)(addr), \\\n                                                (AO_t)(incr))\n# define AO_HAVE_int_fetch_and_add_acquire\n#endif\n\n#if defined(AO_HAVE_fetch_and_add1_acquire) \\\n    && !defined(AO_HAVE_int_fetch_and_add1_acquire)\n# define AO_int_fetch_and_add1_acquire(addr) \\\n                (unsigned)AO_fetch_and_add1_acquire((volatile AO_t *)(addr))\n# define AO_HAVE_int_fetch_and_add1_acquire\n#endif\n\n#if defined(AO_HAVE_fetch_and_sub1_acquire) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1_acquire)\n# define AO_int_fetch_and_sub1_acquire(addr) \\\n                (unsigned)AO_fetch_and_sub1_acquire((volatile AO_t *)(addr))\n# define AO_HAVE_int_fetch_and_sub1_acquire\n#endif\n\n#if defined(AO_HAVE_and_acquire) && !defined(AO_HAVE_int_and_acquire)\n# define AO_int_and_acquire(addr, val) \\\n                AO_and_acquire((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_and_acquire\n#endif\n\n#if defined(AO_HAVE_or_acquire) && !defined(AO_HAVE_int_or_acquire)\n# define AO_int_or_acquire(addr, val) \\\n                AO_or_acquire((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_or_acquire\n#endif\n\n#if defined(AO_HAVE_xor_acquire) && !defined(AO_HAVE_int_xor_acquire)\n# define AO_int_xor_acquire(addr, val) \\\n                AO_xor_acquire((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_xor_acquire\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_int_fetch_compare_and_swap_acquire)\n# define AO_int_fetch_compare_and_swap_acquire(addr, old, new_val) \\\n        (unsigned)AO_fetch_compare_and_swap_acquire((volatile AO_t *)(addr), \\\n                                                 (AO_t)(old), (AO_t)(new_val))\n# define AO_HAVE_int_fetch_compare_and_swap_acquire\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_int_compare_and_swap_acquire)\n# define AO_int_compare_and_swap_acquire(addr, old, new_val) \\\n                AO_compare_and_swap_acquire((volatile AO_t *)(addr), \\\n                                         (AO_t)(old), (AO_t)(new_val))\n# define AO_HAVE_int_compare_and_swap_acquire\n#endif\n/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Inclusion of this file signifies that AO_t is in fact int.           */\n/* Hence any AO_... operation can also serve as AO_int_... operation.   */\n\n#if defined(AO_HAVE_load_release) && !defined(AO_HAVE_int_load_release)\n# define AO_int_load_release(addr) \\\n                (unsigned)AO_load_release((const volatile AO_t *)(addr))\n# define AO_HAVE_int_load_release\n#endif\n\n#if defined(AO_HAVE_store_release) && !defined(AO_HAVE_int_store_release)\n# define AO_int_store_release(addr, val) \\\n                AO_store_release((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_store_release\n#endif\n\n#if defined(AO_HAVE_fetch_and_add_release) \\\n    && !defined(AO_HAVE_int_fetch_and_add_release)\n# define AO_int_fetch_and_add_release(addr, incr) \\\n                (unsigned)AO_fetch_and_add_release((volatile AO_t *)(addr), \\\n                                                (AO_t)(incr))\n# define AO_HAVE_int_fetch_and_add_release\n#endif\n\n#if defined(AO_HAVE_fetch_and_add1_release) \\\n    && !defined(AO_HAVE_int_fetch_and_add1_release)\n# define AO_int_fetch_and_add1_release(addr) \\\n                (unsigned)AO_fetch_and_add1_release((volatile AO_t *)(addr))\n# define AO_HAVE_int_fetch_and_add1_release\n#endif\n\n#if defined(AO_HAVE_fetch_and_sub1_release) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1_release)\n# define AO_int_fetch_and_sub1_release(addr) \\\n                (unsigned)AO_fetch_and_sub1_release((volatile AO_t *)(addr))\n# define AO_HAVE_int_fetch_and_sub1_release\n#endif\n\n#if defined(AO_HAVE_and_release) && !defined(AO_HAVE_int_and_release)\n# define AO_int_and_release(addr, val) \\\n                AO_and_release((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_and_release\n#endif\n\n#if defined(AO_HAVE_or_release) && !defined(AO_HAVE_int_or_release)\n# define AO_int_or_release(addr, val) \\\n                AO_or_release((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_or_release\n#endif\n\n#if defined(AO_HAVE_xor_release) && !defined(AO_HAVE_int_xor_release)\n# define AO_int_xor_release(addr, val) \\\n                AO_xor_release((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_xor_release\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap_release) \\\n    && !defined(AO_HAVE_int_fetch_compare_and_swap_release)\n# define AO_int_fetch_compare_and_swap_release(addr, old, new_val) \\\n        (unsigned)AO_fetch_compare_and_swap_release((volatile AO_t *)(addr), \\\n                                                 (AO_t)(old), (AO_t)(new_val))\n# define AO_HAVE_int_fetch_compare_and_swap_release\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_release) \\\n    && !defined(AO_HAVE_int_compare_and_swap_release)\n# define AO_int_compare_and_swap_release(addr, old, new_val) \\\n                AO_compare_and_swap_release((volatile AO_t *)(addr), \\\n                                         (AO_t)(old), (AO_t)(new_val))\n# define AO_HAVE_int_compare_and_swap_release\n#endif\n/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Inclusion of this file signifies that AO_t is in fact int.           */\n/* Hence any AO_... operation can also serve as AO_int_... operation.   */\n\n#if defined(AO_HAVE_load_write) && !defined(AO_HAVE_int_load_write)\n# define AO_int_load_write(addr) \\\n                (unsigned)AO_load_write((const volatile AO_t *)(addr))\n# define AO_HAVE_int_load_write\n#endif\n\n#if defined(AO_HAVE_store_write) && !defined(AO_HAVE_int_store_write)\n# define AO_int_store_write(addr, val) \\\n                AO_store_write((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_store_write\n#endif\n\n#if defined(AO_HAVE_fetch_and_add_write) \\\n    && !defined(AO_HAVE_int_fetch_and_add_write)\n# define AO_int_fetch_and_add_write(addr, incr) \\\n                (unsigned)AO_fetch_and_add_write((volatile AO_t *)(addr), \\\n                                                (AO_t)(incr))\n# define AO_HAVE_int_fetch_and_add_write\n#endif\n\n#if defined(AO_HAVE_fetch_and_add1_write) \\\n    && !defined(AO_HAVE_int_fetch_and_add1_write)\n# define AO_int_fetch_and_add1_write(addr) \\\n                (unsigned)AO_fetch_and_add1_write((volatile AO_t *)(addr))\n# define AO_HAVE_int_fetch_and_add1_write\n#endif\n\n#if defined(AO_HAVE_fetch_and_sub1_write) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1_write)\n# define AO_int_fetch_and_sub1_write(addr) \\\n                (unsigned)AO_fetch_and_sub1_write((volatile AO_t *)(addr))\n# define AO_HAVE_int_fetch_and_sub1_write\n#endif\n\n#if defined(AO_HAVE_and_write) && !defined(AO_HAVE_int_and_write)\n# define AO_int_and_write(addr, val) \\\n                AO_and_write((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_and_write\n#endif\n\n#if defined(AO_HAVE_or_write) && !defined(AO_HAVE_int_or_write)\n# define AO_int_or_write(addr, val) \\\n                AO_or_write((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_or_write\n#endif\n\n#if defined(AO_HAVE_xor_write) && !defined(AO_HAVE_int_xor_write)\n# define AO_int_xor_write(addr, val) \\\n                AO_xor_write((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_xor_write\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap_write) \\\n    && !defined(AO_HAVE_int_fetch_compare_and_swap_write)\n# define AO_int_fetch_compare_and_swap_write(addr, old, new_val) \\\n        (unsigned)AO_fetch_compare_and_swap_write((volatile AO_t *)(addr), \\\n                                                 (AO_t)(old), (AO_t)(new_val))\n# define AO_HAVE_int_fetch_compare_and_swap_write\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_write) \\\n    && !defined(AO_HAVE_int_compare_and_swap_write)\n# define AO_int_compare_and_swap_write(addr, old, new_val) \\\n                AO_compare_and_swap_write((volatile AO_t *)(addr), \\\n                                         (AO_t)(old), (AO_t)(new_val))\n# define AO_HAVE_int_compare_and_swap_write\n#endif\n/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Inclusion of this file signifies that AO_t is in fact int.           */\n/* Hence any AO_... operation can also serve as AO_int_... operation.   */\n\n#if defined(AO_HAVE_load_read) && !defined(AO_HAVE_int_load_read)\n# define AO_int_load_read(addr) \\\n                (unsigned)AO_load_read((const volatile AO_t *)(addr))\n# define AO_HAVE_int_load_read\n#endif\n\n#if defined(AO_HAVE_store_read) && !defined(AO_HAVE_int_store_read)\n# define AO_int_store_read(addr, val) \\\n                AO_store_read((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_store_read\n#endif\n\n#if defined(AO_HAVE_fetch_and_add_read) \\\n    && !defined(AO_HAVE_int_fetch_and_add_read)\n# define AO_int_fetch_and_add_read(addr, incr) \\\n                (unsigned)AO_fetch_and_add_read((volatile AO_t *)(addr), \\\n                                                (AO_t)(incr))\n# define AO_HAVE_int_fetch_and_add_read\n#endif\n\n#if defined(AO_HAVE_fetch_and_add1_read) \\\n    && !defined(AO_HAVE_int_fetch_and_add1_read)\n# define AO_int_fetch_and_add1_read(addr) \\\n                (unsigned)AO_fetch_and_add1_read((volatile AO_t *)(addr))\n# define AO_HAVE_int_fetch_and_add1_read\n#endif\n\n#if defined(AO_HAVE_fetch_and_sub1_read) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1_read)\n# define AO_int_fetch_and_sub1_read(addr) \\\n                (unsigned)AO_fetch_and_sub1_read((volatile AO_t *)(addr))\n# define AO_HAVE_int_fetch_and_sub1_read\n#endif\n\n#if defined(AO_HAVE_and_read) && !defined(AO_HAVE_int_and_read)\n# define AO_int_and_read(addr, val) \\\n                AO_and_read((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_and_read\n#endif\n\n#if defined(AO_HAVE_or_read) && !defined(AO_HAVE_int_or_read)\n# define AO_int_or_read(addr, val) \\\n                AO_or_read((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_or_read\n#endif\n\n#if defined(AO_HAVE_xor_read) && !defined(AO_HAVE_int_xor_read)\n# define AO_int_xor_read(addr, val) \\\n                AO_xor_read((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_xor_read\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap_read) \\\n    && !defined(AO_HAVE_int_fetch_compare_and_swap_read)\n# define AO_int_fetch_compare_and_swap_read(addr, old, new_val) \\\n        (unsigned)AO_fetch_compare_and_swap_read((volatile AO_t *)(addr), \\\n                                                 (AO_t)(old), (AO_t)(new_val))\n# define AO_HAVE_int_fetch_compare_and_swap_read\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_read) \\\n    && !defined(AO_HAVE_int_compare_and_swap_read)\n# define AO_int_compare_and_swap_read(addr, old, new_val) \\\n                AO_compare_and_swap_read((volatile AO_t *)(addr), \\\n                                         (AO_t)(old), (AO_t)(new_val))\n# define AO_HAVE_int_compare_and_swap_read\n#endif\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/ao_t_is_int.template",
    "content": "/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Inclusion of this file signifies that AO_t is in fact int.           */\n/* Hence any AO_... operation can also serve as AO_int_... operation.   */\n\n#if defined(AO_HAVE_load_XBAR) && !defined(AO_HAVE_int_load_XBAR)\n# define AO_int_load_XBAR(addr) \\\n                (unsigned)AO_load_XBAR((const volatile AO_t *)(addr))\n# define AO_HAVE_int_load_XBAR\n#endif\n\n#if defined(AO_HAVE_store_XBAR) && !defined(AO_HAVE_int_store_XBAR)\n# define AO_int_store_XBAR(addr, val) \\\n                AO_store_XBAR((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_store_XBAR\n#endif\n\n#if defined(AO_HAVE_fetch_and_add_XBAR) \\\n    && !defined(AO_HAVE_int_fetch_and_add_XBAR)\n# define AO_int_fetch_and_add_XBAR(addr, incr) \\\n                (unsigned)AO_fetch_and_add_XBAR((volatile AO_t *)(addr), \\\n                                                (AO_t)(incr))\n# define AO_HAVE_int_fetch_and_add_XBAR\n#endif\n\n#if defined(AO_HAVE_fetch_and_add1_XBAR) \\\n    && !defined(AO_HAVE_int_fetch_and_add1_XBAR)\n# define AO_int_fetch_and_add1_XBAR(addr) \\\n                (unsigned)AO_fetch_and_add1_XBAR((volatile AO_t *)(addr))\n# define AO_HAVE_int_fetch_and_add1_XBAR\n#endif\n\n#if defined(AO_HAVE_fetch_and_sub1_XBAR) \\\n    && !defined(AO_HAVE_int_fetch_and_sub1_XBAR)\n# define AO_int_fetch_and_sub1_XBAR(addr) \\\n                (unsigned)AO_fetch_and_sub1_XBAR((volatile AO_t *)(addr))\n# define AO_HAVE_int_fetch_and_sub1_XBAR\n#endif\n\n#if defined(AO_HAVE_and_XBAR) && !defined(AO_HAVE_int_and_XBAR)\n# define AO_int_and_XBAR(addr, val) \\\n                AO_and_XBAR((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_and_XBAR\n#endif\n\n#if defined(AO_HAVE_or_XBAR) && !defined(AO_HAVE_int_or_XBAR)\n# define AO_int_or_XBAR(addr, val) \\\n                AO_or_XBAR((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_or_XBAR\n#endif\n\n#if defined(AO_HAVE_xor_XBAR) && !defined(AO_HAVE_int_xor_XBAR)\n# define AO_int_xor_XBAR(addr, val) \\\n                AO_xor_XBAR((volatile AO_t *)(addr), (AO_t)(val))\n# define AO_HAVE_int_xor_XBAR\n#endif\n\n#if defined(AO_HAVE_fetch_compare_and_swap_XBAR) \\\n    && !defined(AO_HAVE_int_fetch_compare_and_swap_XBAR)\n# define AO_int_fetch_compare_and_swap_XBAR(addr, old, new_val) \\\n        (unsigned)AO_fetch_compare_and_swap_XBAR((volatile AO_t *)(addr), \\\n                                                 (AO_t)(old), (AO_t)(new_val))\n# define AO_HAVE_int_fetch_compare_and_swap_XBAR\n#endif\n\n#if defined(AO_HAVE_compare_and_swap_XBAR) \\\n    && !defined(AO_HAVE_int_compare_and_swap_XBAR)\n# define AO_int_compare_and_swap_XBAR(addr, old, new_val) \\\n                AO_compare_and_swap_XBAR((volatile AO_t *)(addr), \\\n                                         (AO_t)(old), (AO_t)(new_val))\n# define AO_HAVE_int_compare_and_swap_XBAR\n#endif\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/armcc/arm_v6.h",
    "content": "/*\n * Copyright (c) 2007 by NEC LE-IT:               All rights reserved.\n * A transcription of ARMv6 atomic operations for the ARM Realview Toolchain.\n * This code works with armcc from RVDS 3.1\n * This is based on work in gcc/arm.h by\n *   Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n *   Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n *   Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved.\n *\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#include \"../test_and_set_t_is_ao_t.h\" /* Probably suboptimal */\n\n#if __TARGET_ARCH_ARM < 6\n# if !defined(CPPCHECK)\n#   error Do not use with ARM instruction sets lower than v6\n# endif\n#else\n\n#define AO_ACCESS_CHECK_ALIGNED\n#define AO_ACCESS_short_CHECK_ALIGNED\n#define AO_ACCESS_int_CHECK_ALIGNED\n#include \"../all_atomic_only_load.h\"\n\n#include \"../standard_ao_double_t.h\"\n\n/* NEC LE-IT: ARMv6 is the first architecture providing support for simple LL/SC\n * A data memory barrier must be raised via CP15 command (see documentation).\n *\n * ARMv7 is compatible to ARMv6 but has a simpler command for issuing a\n * memory barrier (DMB). Raising it via CP15 should still work as told me by the\n * support engineers. If it turns out to be much quicker than we should implement\n * custom code for ARMv7 using the asm { dmb } command.\n *\n * If only a single processor is used, we can define AO_UNIPROCESSOR\n * and do not need to access CP15 for ensuring a DMB at all.\n*/\n\nAO_INLINE void\nAO_nop_full(void)\n{\n# ifndef AO_UNIPROCESSOR\n    unsigned int dest=0;\n    /* Issue a data memory barrier (keeps ordering of memory transactions  */\n    /* before and after this operation).                                   */\n    __asm {\n            mcr p15,0,dest,c7,c10,5\n            };\n# else\n    AO_compiler_barrier();\n# endif\n}\n#define AO_HAVE_nop_full\n\n/* NEC LE-IT: atomic \"store\" - according to ARM documentation this is\n * the only safe way to set variables also used in LL/SC environment.\n * A direct write won't be recognized by the LL/SC construct in other CPUs.\n *\n * HB: Based on subsequent discussion, I think it would be OK to use an\n * ordinary store here if we knew that interrupt handlers always cleared\n * the reservation.  They should, but there is some doubt that this is\n * currently always the case for e.g. Linux.\n*/\nAO_INLINE void AO_store(volatile AO_t *addr, AO_t value)\n{\n        unsigned long tmp;\n\nretry:\n__asm {\n        ldrex   tmp, [addr]\n        strex   tmp, value, [addr]\n        teq     tmp, #0\n        bne     retry\n        };\n}\n#define AO_HAVE_store\n\n/* NEC LE-IT: replace the SWAP as recommended by ARM:\n\n   \"Applies to: ARM11 Cores\n        Though the SWP instruction will still work with ARM V6 cores, it is recommended\n        to use the new V6 synchronization instructions. The SWP instruction produces\n        locked read and write accesses which are atomic, i.e. another operation cannot\n        be done between these locked accesses which ties up external bus (AHB,AXI)\n        bandwidth and can increase worst case interrupt latencies. LDREX,STREX are\n        more flexible, other instructions can be done between the LDREX and STREX accesses.\n   \"\n*/\n#ifndef AO_PREFER_GENERALIZED\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set(volatile AO_TS_t *addr) {\n        AO_TS_VAL_t oldval;\n        unsigned long tmp;\n        unsigned long one = 1;\nretry:\n__asm {\n        ldrex   oldval, [addr]\n        strex   tmp, one, [addr]\n        teq     tmp, #0\n        bne     retry\n        }\n\n        return oldval;\n}\n#define AO_HAVE_test_and_set\n\nAO_INLINE AO_t\nAO_fetch_and_add(volatile AO_t *p, AO_t incr)\n{\n        unsigned long tmp,tmp2;\n        AO_t result;\n\nretry:\n__asm {\n        ldrex   result, [p]\n        add     tmp, incr, result\n        strex   tmp2, tmp, [p]\n        teq     tmp2, #0\n        bne     retry\n        }\n\n        return result;\n}\n#define AO_HAVE_fetch_and_add\n\nAO_INLINE AO_t\nAO_fetch_and_add1(volatile AO_t *p)\n{\n        unsigned long tmp,tmp2;\n        AO_t result;\n\nretry:\n__asm {\n        ldrex   result, [p]\n        add     tmp, result, #1\n        strex   tmp2, tmp, [p]\n        teq     tmp2, #0\n        bne     retry\n        }\n\n        return result;\n}\n#define AO_HAVE_fetch_and_add1\n\nAO_INLINE AO_t\nAO_fetch_and_sub1(volatile AO_t *p)\n{\n        unsigned long tmp,tmp2;\n        AO_t result;\n\nretry:\n__asm {\n        ldrex   result, [p]\n        sub     tmp, result, #1\n        strex   tmp2, tmp, [p]\n        teq     tmp2, #0\n        bne     retry\n        }\n\n        return result;\n}\n#define AO_HAVE_fetch_and_sub1\n#endif /* !AO_PREFER_GENERALIZED */\n\n#ifndef AO_GENERALIZE_ASM_BOOL_CAS\n  /* Returns nonzero if the comparison succeeded.       */\n  AO_INLINE int\n  AO_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val)\n  {\n    AO_t result, tmp;\n\n  retry:\n    __asm__ {\n      mov     result, #2\n      ldrex   tmp, [addr]\n      teq     tmp, old_val\n#     ifdef __thumb__\n        it      eq\n#     endif\n      strexeq result, new_val, [addr]\n      teq     result, #1\n      beq     retry\n    }\n    return !(result&2);\n  }\n# define AO_HAVE_compare_and_swap\n#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val)\n{\n         AO_t fetched_val, tmp;\n\nretry:\n__asm__ {\n        mov     tmp, #2\n        ldrex   fetched_val, [addr]\n        teq     fetched_val, old_val\n#     ifdef __thumb__\n        it      eq\n#     endif\n        strexeq tmp, new_val, [addr]\n        teq     tmp, #1\n        beq     retry\n        }\n        return fetched_val;\n}\n#define AO_HAVE_fetch_compare_and_swap\n\n/* helper functions for the Realview compiler: LDREXD is not usable\n * with inline assembler, so use the \"embedded\" assembler as\n * suggested by ARM Dev. support (June 2008). */\n__asm inline double_ptr_storage AO_load_ex(const volatile AO_double_t *addr) {\n        LDREXD r0,r1,[r0]\n}\n\n__asm inline int AO_store_ex(AO_t val1, AO_t val2, volatile AO_double_t *addr) {\n        STREXD r3,r0,r1,[r2]\n        MOV    r0,r3\n}\n\nAO_INLINE AO_double_t\nAO_double_load(const volatile AO_double_t *addr)\n{\n  AO_double_t result;\n\n  result.AO_whole = AO_load_ex(addr);\n  return result;\n}\n#define AO_HAVE_double_load\n\nAO_INLINE int\nAO_compare_double_and_swap_double(volatile AO_double_t *addr,\n                                  AO_t old_val1, AO_t old_val2,\n                                  AO_t new_val1, AO_t new_val2)\n{\n        double_ptr_storage old_val =\n                        ((double_ptr_storage)old_val2 << 32) | old_val1;\n        double_ptr_storage tmp;\n        int result;\n\n        while(1) {\n                tmp = AO_load_ex(addr);\n                if(tmp != old_val)      return 0;\n                result = AO_store_ex(new_val1, new_val2, addr);\n                if(!result)     return 1;\n        }\n}\n#define AO_HAVE_compare_double_and_swap_double\n\n#endif /* __TARGET_ARCH_ARM >= 6 */\n\n#define AO_T_IS_INT\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/emul_cas.h",
    "content": "/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/*\n * Ensure, if at all possible, that AO_compare_and_swap_full() is\n * available.  The emulation should be brute-force signal-safe, even\n * though it actually blocks.\n * Including this file will generate an error if AO_compare_and_swap_full()\n * cannot be made available.\n * This will be included from platform-specific atomic_ops files\n * if appropriate, and if AO_REQUIRE_CAS is defined.  It should not be\n * included directly, especially since it affects the implementation\n * of other atomic update primitives.\n * The implementation assumes that only AO_store_XXX and AO_test_and_set_XXX\n * variants are defined, and that AO_test_and_set_XXX is not used to\n * operate on compare_and_swap locations.\n */\n\n#ifndef AO_ATOMIC_OPS_H\n# error This file should not be included directly.\n#endif\n\n#ifndef AO_HAVE_double_t\n# include \"standard_ao_double_t.h\"\n#endif\n\n#ifdef __cplusplus\n  extern \"C\" {\n#endif\n\nAO_API AO_t AO_fetch_compare_and_swap_emulation(volatile AO_t *addr,\n                                                AO_t old_val, AO_t new_val);\n\nAO_API int\nAO_compare_double_and_swap_double_emulation(volatile AO_double_t *addr,\n                                            AO_t old_val1, AO_t old_val2,\n                                            AO_t new_val1, AO_t new_val2);\n\nAO_API void AO_store_full_emulation(volatile AO_t *addr, AO_t val);\n\n#ifndef AO_HAVE_fetch_compare_and_swap_full\n# define AO_fetch_compare_and_swap_full(addr, old, newval) \\\n                AO_fetch_compare_and_swap_emulation(addr, old, newval)\n# define AO_HAVE_fetch_compare_and_swap_full\n#endif\n\n#ifndef AO_HAVE_compare_double_and_swap_double_full\n# define AO_compare_double_and_swap_double_full(addr, old1, old2, \\\n                                                newval1, newval2) \\\n        AO_compare_double_and_swap_double_emulation(addr, old1, old2, \\\n                                                    newval1, newval2)\n# define AO_HAVE_compare_double_and_swap_double_full\n#endif\n\n#undef AO_store\n#undef AO_HAVE_store\n#undef AO_store_write\n#undef AO_HAVE_store_write\n#undef AO_store_release\n#undef AO_HAVE_store_release\n#undef AO_store_full\n#undef AO_HAVE_store_full\n#define AO_store_full(addr, val) AO_store_full_emulation(addr, val)\n#define AO_HAVE_store_full\n\n#ifdef __cplusplus\n  } /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/aarch64.h",
    "content": "/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved.\n * Copyright (c) 2013-2017 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n/* As of clang-5.0 (and gcc-5.4), __atomic_thread_fence is always       */\n/* translated to DMB (which is inefficient for AO_nop_write).           */\n/* TODO: Update it for newer Clang and GCC releases. */\n#if !defined(AO_PREFER_BUILTIN_ATOMICS) && !defined(AO_THREAD_SANITIZER) \\\n    && !defined(AO_UNIPROCESSOR)\n  AO_INLINE void\n  AO_nop_write(void)\n  {\n    __asm__ __volatile__(\"dmb ishst\" : : : \"memory\");\n  }\n# define AO_HAVE_nop_write\n#endif\n\n/* There were some bugs in the older clang releases (related to         */\n/* optimization of functions dealing with __int128 values, supposedly), */\n/* so even asm-based implementation did not work correctly.             */\n#if !defined(__clang__) || AO_CLANG_PREREQ(3, 9)\n\n# include \"../standard_ao_double_t.h\"\n\n/* As of gcc-5.4, all built-in load/store and CAS atomics for double    */\n/* word require -latomic, are not lock-free and cause test_stack        */\n/* failure, so the asm-based implementation is used for now.            */\n/* TODO: Update it for newer GCC releases. */\n#if (!defined(__ILP32__) && !defined(__clang__)) \\\n    || defined(AO_AARCH64_ASM_LOAD_STORE_CAS)\n\n# ifndef AO_PREFER_GENERALIZED\n    AO_INLINE AO_double_t\n    AO_double_load(const volatile AO_double_t *addr)\n    {\n      AO_double_t result;\n      int status;\n\n      /* Note that STXP cannot be discarded because LD[A]XP is not      */\n      /* single-copy atomic (unlike LDREXD for 32-bit ARM).             */\n      do {\n        __asm__ __volatile__(\"//AO_double_load\\n\"\n#       ifdef __ILP32__\n          \"       ldxp  %w0, %w1, %3\\n\"\n          \"       stxp %w2, %w0, %w1, %3\"\n#       else\n          \"       ldxp  %0, %1, %3\\n\"\n          \"       stxp %w2, %0, %1, %3\"\n#       endif\n        : \"=&r\" (result.AO_val1), \"=&r\" (result.AO_val2), \"=&r\" (status)\n        : \"Q\" (*addr));\n      } while (AO_EXPECT_FALSE(status));\n      return result;\n    }\n#   define AO_HAVE_double_load\n\n    AO_INLINE AO_double_t\n    AO_double_load_acquire(const volatile AO_double_t *addr)\n    {\n      AO_double_t result;\n      int status;\n\n      do {\n        __asm__ __volatile__(\"//AO_double_load_acquire\\n\"\n#       ifdef __ILP32__\n          \"       ldaxp  %w0, %w1, %3\\n\"\n          \"       stxp %w2, %w0, %w1, %3\"\n#       else\n          \"       ldaxp  %0, %1, %3\\n\"\n          \"       stxp %w2, %0, %1, %3\"\n#       endif\n        : \"=&r\" (result.AO_val1), \"=&r\" (result.AO_val2), \"=&r\" (status)\n        : \"Q\" (*addr));\n      } while (AO_EXPECT_FALSE(status));\n      return result;\n    }\n#   define AO_HAVE_double_load_acquire\n\n    AO_INLINE void\n    AO_double_store(volatile AO_double_t *addr, AO_double_t value)\n    {\n      AO_double_t old_val;\n      int status;\n\n      do {\n        __asm__ __volatile__(\"//AO_double_store\\n\"\n#       ifdef __ILP32__\n          \"       ldxp  %w0, %w1, %3\\n\"\n          \"       stxp %w2, %w4, %w5, %3\"\n#       else\n          \"       ldxp  %0, %1, %3\\n\"\n          \"       stxp %w2, %4, %5, %3\"\n#       endif\n        : \"=&r\" (old_val.AO_val1), \"=&r\" (old_val.AO_val2), \"=&r\" (status),\n          \"=Q\" (*addr)\n        : \"r\" (value.AO_val1), \"r\" (value.AO_val2));\n        /* Compared to the arm.h implementation, the 'cc' (flags) are   */\n        /* not clobbered because A64 has no concept of conditional      */\n        /* execution.                                                   */\n      } while (AO_EXPECT_FALSE(status));\n    }\n#   define AO_HAVE_double_store\n\n    AO_INLINE void\n    AO_double_store_release(volatile AO_double_t *addr, AO_double_t value)\n    {\n      AO_double_t old_val;\n      int status;\n\n      do {\n        __asm__ __volatile__(\"//AO_double_store_release\\n\"\n#       ifdef __ILP32__\n          \"       ldxp  %w0, %w1, %3\\n\"\n          \"       stlxp %w2, %w4, %w5, %3\"\n#       else\n          \"       ldxp  %0, %1, %3\\n\"\n          \"       stlxp %w2, %4, %5, %3\"\n#       endif\n        : \"=&r\" (old_val.AO_val1), \"=&r\" (old_val.AO_val2), \"=&r\" (status),\n          \"=Q\" (*addr)\n        : \"r\" (value.AO_val1), \"r\" (value.AO_val2));\n      } while (AO_EXPECT_FALSE(status));\n    }\n#   define AO_HAVE_double_store_release\n# endif /* !AO_PREFER_GENERALIZED */\n\n  AO_INLINE int\n  AO_double_compare_and_swap(volatile AO_double_t *addr,\n                             AO_double_t old_val, AO_double_t new_val)\n  {\n    AO_double_t tmp;\n    int result = 1;\n\n    do {\n      __asm__ __volatile__(\"//AO_double_compare_and_swap\\n\"\n#       ifdef __ILP32__\n          \"       ldxp  %w0, %w1, %2\\n\"\n#       else\n          \"       ldxp  %0, %1, %2\\n\"\n#       endif\n        : \"=&r\" (tmp.AO_val1), \"=&r\" (tmp.AO_val2)\n        : \"Q\" (*addr));\n      if (tmp.AO_val1 != old_val.AO_val1 || tmp.AO_val2 != old_val.AO_val2)\n        break;\n      __asm__ __volatile__(\n#       ifdef __ILP32__\n          \"       stxp %w0, %w2, %w3, %1\\n\"\n#       else\n          \"       stxp %w0, %2, %3, %1\\n\"\n#       endif\n        : \"=&r\" (result), \"=Q\" (*addr)\n        : \"r\" (new_val.AO_val1), \"r\" (new_val.AO_val2));\n    } while (AO_EXPECT_FALSE(result));\n    return !result;\n  }\n# define AO_HAVE_double_compare_and_swap\n\n  AO_INLINE int\n  AO_double_compare_and_swap_acquire(volatile AO_double_t *addr,\n                                     AO_double_t old_val, AO_double_t new_val)\n  {\n    AO_double_t tmp;\n    int result = 1;\n\n    do {\n      __asm__ __volatile__(\"//AO_double_compare_and_swap_acquire\\n\"\n#       ifdef __ILP32__\n          \"       ldaxp  %w0, %w1, %2\\n\"\n#       else\n          \"       ldaxp  %0, %1, %2\\n\"\n#       endif\n        : \"=&r\" (tmp.AO_val1), \"=&r\" (tmp.AO_val2)\n        : \"Q\" (*addr));\n      if (tmp.AO_val1 != old_val.AO_val1 || tmp.AO_val2 != old_val.AO_val2)\n        break;\n      __asm__ __volatile__(\n#       ifdef __ILP32__\n          \"       stxp %w0, %w2, %w3, %1\\n\"\n#       else\n          \"       stxp %w0, %2, %3, %1\\n\"\n#       endif\n        : \"=&r\" (result), \"=Q\" (*addr)\n        : \"r\" (new_val.AO_val1), \"r\" (new_val.AO_val2));\n    } while (AO_EXPECT_FALSE(result));\n    return !result;\n  }\n# define AO_HAVE_double_compare_and_swap_acquire\n\n  AO_INLINE int\n  AO_double_compare_and_swap_release(volatile AO_double_t *addr,\n                                     AO_double_t old_val, AO_double_t new_val)\n  {\n    AO_double_t tmp;\n    int result = 1;\n\n    do {\n      __asm__ __volatile__(\"//AO_double_compare_and_swap_release\\n\"\n#       ifdef __ILP32__\n          \"       ldxp  %w0, %w1, %2\\n\"\n#       else\n          \"       ldxp  %0, %1, %2\\n\"\n#       endif\n        : \"=&r\" (tmp.AO_val1), \"=&r\" (tmp.AO_val2)\n        : \"Q\" (*addr));\n      if (tmp.AO_val1 != old_val.AO_val1 || tmp.AO_val2 != old_val.AO_val2)\n        break;\n      __asm__ __volatile__(\n#       ifdef __ILP32__\n          \"       stlxp %w0, %w2, %w3, %1\\n\"\n#       else\n          \"       stlxp %w0, %2, %3, %1\\n\"\n#       endif\n        : \"=&r\" (result), \"=Q\" (*addr)\n        : \"r\" (new_val.AO_val1), \"r\" (new_val.AO_val2));\n    } while (AO_EXPECT_FALSE(result));\n    return !result;\n  }\n# define AO_HAVE_double_compare_and_swap_release\n\n  AO_INLINE int\n  AO_double_compare_and_swap_full(volatile AO_double_t *addr,\n                                  AO_double_t old_val, AO_double_t new_val)\n  {\n    AO_double_t tmp;\n    int result = 1;\n\n    do {\n      __asm__ __volatile__(\"//AO_double_compare_and_swap_full\\n\"\n#       ifdef __ILP32__\n          \"       ldaxp  %w0, %w1, %2\\n\"\n#       else\n          \"       ldaxp  %0, %1, %2\\n\"\n#       endif\n        : \"=&r\" (tmp.AO_val1), \"=&r\" (tmp.AO_val2)\n        : \"Q\" (*addr));\n      if (tmp.AO_val1 != old_val.AO_val1 || tmp.AO_val2 != old_val.AO_val2)\n        break;\n      __asm__ __volatile__(\n#       ifdef __ILP32__\n          \"       stlxp %w0, %w2, %w3, %1\\n\"\n#       else\n          \"       stlxp %w0, %2, %3, %1\\n\"\n#       endif\n        : \"=&r\" (result), \"=Q\" (*addr)\n        : \"r\" (new_val.AO_val1), \"r\" (new_val.AO_val2));\n    } while (AO_EXPECT_FALSE(result));\n    return !result;\n  }\n# define AO_HAVE_double_compare_and_swap_full\n\n#endif /* !__ILP32__ && !__clang__ || AO_AARCH64_ASM_LOAD_STORE_CAS */\n\n/* As of clang-5.0 and gcc-8.1, __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16     */\n/* macro is still missing (while the double-word CAS is available).     */\n# ifndef __ILP32__\n#   define AO_GCC_HAVE_double_SYNC_CAS\n# endif\n\n#endif /* !__clang__ || AO_CLANG_PREREQ(3, 9) */\n\n#if (defined(__clang__) && !AO_CLANG_PREREQ(3, 8)) || defined(__APPLE_CC__)\n  /* __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n macros are missing.     */\n# define AO_GCC_FORCE_HAVE_CAS\n#endif\n\n#include \"generic.h\"\n\n#undef AO_GCC_FORCE_HAVE_CAS\n#undef AO_GCC_HAVE_double_SYNC_CAS\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/alpha.h",
    "content": "/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#include \"../loadstore/atomic_load.h\"\n#include \"../loadstore/atomic_store.h\"\n\n#include \"../test_and_set_t_is_ao_t.h\"\n\n#define AO_NO_DD_ORDERING\n        /* Data dependence does not imply read ordering.        */\n\nAO_INLINE void\nAO_nop_full(void)\n{\n  __asm__ __volatile__(\"mb\" : : : \"memory\");\n}\n#define AO_HAVE_nop_full\n\nAO_INLINE void\nAO_nop_write(void)\n{\n  __asm__ __volatile__(\"wmb\" : : : \"memory\");\n}\n#define AO_HAVE_nop_write\n\n/* mb should be used for AO_nop_read().  That's the default.    */\n\n/* TODO: implement AO_fetch_and_add explicitly. */\n\n/* We believe that ldq_l ... stq_c does not imply any memory barrier.   */\nAO_INLINE int\nAO_compare_and_swap(volatile AO_t *addr,\n                    AO_t old, AO_t new_val)\n{\n  unsigned long was_equal;\n  unsigned long temp;\n\n  __asm__ __volatile__(\n                     \"1:     ldq_l %0,%1\\n\"\n                     \"       cmpeq %0,%4,%2\\n\"\n                     \"       mov %3,%0\\n\"\n                     \"       beq %2,2f\\n\"\n                     \"       stq_c %0,%1\\n\"\n                     \"       beq %0,1b\\n\"\n                     \"2:\\n\"\n                     : \"=&r\" (temp), \"+m\" (*addr), \"=&r\" (was_equal)\n                     : \"r\" (new_val), \"Ir\" (old)\n                     :\"memory\");\n  return (int)was_equal;\n}\n#define AO_HAVE_compare_and_swap\n\n/* TODO: implement AO_fetch_compare_and_swap */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/arm.h",
    "content": "/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved.\n * Copyright (c) 2008-2017 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#if (AO_GNUC_PREREQ(4, 8) || AO_CLANG_PREREQ(3, 5)) \\\n    && !defined(AO_DISABLE_GCC_ATOMICS)\n  /* Probably, it could be enabled even for earlier gcc/clang versions. */\n# define AO_GCC_ATOMIC_TEST_AND_SET\n#endif\n\n#ifdef __native_client__\n  /* Mask instruction should immediately precede access instruction.    */\n# define AO_MASK_PTR(reg) \"       bical \" reg \", \" reg \", #0xc0000000\\n\"\n# define AO_BR_ALIGN \"       .align 4\\n\"\n#else\n# define AO_MASK_PTR(reg) /* empty */\n# define AO_BR_ALIGN /* empty */\n#endif\n\n#if defined(__thumb__) && !defined(__thumb2__)\n  /* Thumb One mode does not have ARM \"mcr\", \"swp\" and some load/store  */\n  /* instructions, so we temporarily switch to ARM mode and go back     */\n  /* afterwards (clobbering \"r3\" register).                             */\n# define AO_THUMB_GO_ARM \\\n           \"       adr     r3, 4f\\n\" \\\n           \"       bx      r3\\n\" \\\n           \"      .align\\n\" \\\n           \"      .arm\\n\" \\\n           AO_BR_ALIGN \\\n           \"4:\\n\"\n# define AO_THUMB_RESTORE_MODE \\\n           \"       adr     r3, 5f + 1\\n\" \\\n           \"       bx      r3\\n\" \\\n           \"       .thumb\\n\" \\\n           AO_BR_ALIGN \\\n           \"5:\\n\"\n# define AO_THUMB_SWITCH_CLOBBERS \"r3\",\n#else\n# define AO_THUMB_GO_ARM /* empty */\n# define AO_THUMB_RESTORE_MODE /* empty */\n# define AO_THUMB_SWITCH_CLOBBERS /* empty */\n#endif /* !__thumb__ */\n\n/* NEC LE-IT: gcc has no way to easily check the arm architecture       */\n/* but it defines only one (or several) of __ARM_ARCH_x__ to be true.   */\n#if !defined(__ARM_ARCH_2__) && !defined(__ARM_ARCH_3__) \\\n    && !defined(__ARM_ARCH_3M__) && !defined(__ARM_ARCH_4__) \\\n    && !defined(__ARM_ARCH_4T__) \\\n    && ((!defined(__ARM_ARCH_5__) && !defined(__ARM_ARCH_5E__) \\\n         && !defined(__ARM_ARCH_5T__) && !defined(__ARM_ARCH_5TE__) \\\n         && !defined(__ARM_ARCH_5TEJ__) && !defined(__ARM_ARCH_6M__)) \\\n        || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \\\n        || defined(__ARM_ARCH_8A__))\n# define AO_ARM_HAVE_LDREX\n# if !defined(__ARM_ARCH_6__) && !defined(__ARM_ARCH_6J__) \\\n     && !defined(__ARM_ARCH_6T2__)\n    /* LDREXB/STREXB and LDREXH/STREXH are present in ARMv6K/Z+.        */\n#   define AO_ARM_HAVE_LDREXBH\n# endif\n# if !defined(__ARM_ARCH_6__) && !defined(__ARM_ARCH_6J__) \\\n     && !defined(__ARM_ARCH_6T2__) && !defined(__ARM_ARCH_6Z__) \\\n     && !defined(__ARM_ARCH_6ZT2__)\n#   if !defined(__ARM_ARCH_6K__) && !defined(__ARM_ARCH_6KZ__) \\\n       && !defined(__ARM_ARCH_6ZK__)\n      /* DMB is present in ARMv6M and ARMv7+.   */\n#     define AO_ARM_HAVE_DMB\n#   endif\n#   if (!defined(__thumb__) \\\n        || (defined(__thumb2__) && !defined(__ARM_ARCH_7__) \\\n            && !defined(__ARM_ARCH_7M__) && !defined(__ARM_ARCH_7EM__))) \\\n       && (!defined(__clang__) || AO_CLANG_PREREQ(3, 3))\n      /* LDREXD/STREXD present in ARMv6K/M+ (see gas/config/tc-arm.c).  */\n      /* In the Thumb mode, this works only starting from ARMv7 (except */\n      /* for the base and 'M' models).  Clang3.2 (and earlier) does not */\n      /* allocate register pairs for LDREXD/STREXD properly (besides,   */\n      /* Clang3.1 does not support \"%H<r>\" operand specification).      */\n#     define AO_ARM_HAVE_LDREXD\n#   endif /* !thumb || ARMv7A || ARMv7R+ */\n# endif /* ARMv7+ */\n#endif /* ARMv6+ */\n\n#if !defined(__ARM_ARCH_2__) && !defined(__ARM_ARCH_6M__) \\\n    && !defined(__ARM_ARCH_8A__) && !defined(__thumb2__)\n# define AO_ARM_HAVE_SWP\n                /* Note: ARMv6M is excluded due to no ARM mode support. */\n                /* Also, SWP is obsoleted for ARMv8+.                   */\n#endif /* !__thumb2__ */\n\n#if !defined(AO_UNIPROCESSOR) && defined(AO_ARM_HAVE_DMB) \\\n    && !defined(AO_PREFER_BUILTIN_ATOMICS)\n  AO_INLINE void\n  AO_nop_write(void)\n  {\n    /* AO_THUMB_GO_ARM is empty. */\n    /* This will target the system domain and thus be overly            */\n    /* conservative as the CPUs (even in case of big.LITTLE SoC) will   */\n    /* occupy the inner shareable domain.                               */\n    /* The plain variant (dmb st) is theoretically slower, and should   */\n    /* not be needed.  That said, with limited experimentation, a CPU   */\n    /* implementation for which it actually matters has not been found  */\n    /* yet, though they should already exist.                           */\n    /* Anyway, note that the \"st\" and \"ishst\" barriers are actually     */\n    /* quite weak and, as the libatomic_ops documentation states,       */\n    /* usually not what you really want.                                */\n    __asm__ __volatile__(\"dmb ishst\" : : : \"memory\");\n  }\n# define AO_HAVE_nop_write\n#endif /* AO_ARM_HAVE_DMB */\n\n#ifndef AO_GCC_ATOMIC_TEST_AND_SET\n\n#ifdef AO_UNIPROCESSOR\n  /* If only a single processor (core) is used, AO_UNIPROCESSOR could   */\n  /* be defined by the client to avoid unnecessary memory barrier.      */\n  AO_INLINE void\n  AO_nop_full(void)\n  {\n    AO_compiler_barrier();\n  }\n# define AO_HAVE_nop_full\n\n#elif defined(AO_ARM_HAVE_DMB)\n  /* ARMv7 is compatible to ARMv6 but has a simpler command for issuing */\n  /* a memory barrier (DMB).  Raising it via CP15 should still work     */\n  /* (but slightly less efficient because it requires the use of        */\n  /* a general-purpose register).                                       */\n  AO_INLINE void\n  AO_nop_full(void)\n  {\n    /* AO_THUMB_GO_ARM is empty. */\n    __asm__ __volatile__(\"dmb\" : : : \"memory\");\n  }\n# define AO_HAVE_nop_full\n\n#elif defined(AO_ARM_HAVE_LDREX)\n  /* ARMv6 is the first architecture providing support for a simple     */\n  /* LL/SC.  A data memory barrier must be raised via CP15 command.     */\n  AO_INLINE void\n  AO_nop_full(void)\n  {\n    unsigned dest = 0;\n\n    /* Issue a data memory barrier (keeps ordering of memory    */\n    /* transactions before and after this operation).           */\n    __asm__ __volatile__(\"@AO_nop_full\\n\"\n      AO_THUMB_GO_ARM\n      \"       mcr p15,0,%0,c7,c10,5\\n\"\n      AO_THUMB_RESTORE_MODE\n      : \"=&r\"(dest)\n      : /* empty */\n      : AO_THUMB_SWITCH_CLOBBERS \"memory\");\n  }\n# define AO_HAVE_nop_full\n\n#else\n  /* AO_nop_full() is emulated using AO_test_and_set_full().    */\n#endif /* !AO_UNIPROCESSOR && !AO_ARM_HAVE_LDREX */\n\n#endif /* !AO_GCC_ATOMIC_TEST_AND_SET */\n\n#ifdef AO_ARM_HAVE_LDREX\n\n  /* \"ARM Architecture Reference Manual\" (chapter A3.5.3) says that the */\n  /* single-copy atomic processor accesses are all byte accesses, all   */\n  /* halfword accesses to halfword-aligned locations, all word accesses */\n  /* to word-aligned locations.                                         */\n  /* There is only a single concern related to AO store operations:     */\n  /* a direct write (by STR[B/H] instruction) will not be recognized    */\n  /* by the LL/SC construct on the same CPU (i.e., according to ARM     */\n  /* documentation, e.g., see CortexA8 TRM reference, point 8.5,        */\n  /* atomic \"store\" (using LDREX/STREX[B/H]) is the only safe way to    */\n  /* set variables also used in LL/SC environment).                     */\n  /* This is only a problem if interrupt handlers do not clear the      */\n  /* reservation (by CLREX instruction or a dummy STREX one), as they   */\n  /* almost certainly should (e.g., see restore_user_regs defined in    */\n  /* arch/arm/kernel/entry-header.S of Linux.  Nonetheless, there is    */\n  /* a doubt this was properly implemented in some ancient OS releases. */\n# ifdef AO_BROKEN_TASKSWITCH_CLREX\n\n#   define AO_SKIPATOMIC_store\n#   define AO_SKIPATOMIC_store_release\n#   define AO_SKIPATOMIC_char_store\n#   define AO_SKIPATOMIC_char_store_release\n#   define AO_SKIPATOMIC_short_store\n#   define AO_SKIPATOMIC_short_store_release\n#   define AO_SKIPATOMIC_int_store\n#   define AO_SKIPATOMIC_int_store_release\n\n#   ifndef AO_PREFER_BUILTIN_ATOMICS\n\n    AO_INLINE void AO_store(volatile AO_t *addr, AO_t value)\n    {\n      int flag;\n\n      __asm__ __volatile__(\"@AO_store\\n\"\n        AO_THUMB_GO_ARM\n        AO_BR_ALIGN\n        \"1: \" AO_MASK_PTR(\"%2\")\n        \"       ldrex %0, [%2]\\n\"\n        AO_MASK_PTR(\"%2\")\n        \"       strex %0, %3, [%2]\\n\"\n        \"       teq %0, #0\\n\"\n        \"       bne 1b\\n\"\n        AO_THUMB_RESTORE_MODE\n        : \"=&r\" (flag), \"+m\" (*addr)\n        : \"r\" (addr), \"r\" (value)\n        : AO_THUMB_SWITCH_CLOBBERS \"cc\");\n    }\n#   define AO_HAVE_store\n\n#   ifdef AO_ARM_HAVE_LDREXBH\n      AO_INLINE void AO_char_store(volatile unsigned char *addr,\n                                   unsigned char value)\n      {\n        int flag;\n\n        __asm__ __volatile__(\"@AO_char_store\\n\"\n          AO_THUMB_GO_ARM\n          AO_BR_ALIGN\n          \"1: \" AO_MASK_PTR(\"%2\")\n          \"       ldrexb %0, [%2]\\n\"\n          AO_MASK_PTR(\"%2\")\n          \"       strexb %0, %3, [%2]\\n\"\n          \"       teq    %0, #0\\n\"\n          \"       bne 1b\\n\"\n          AO_THUMB_RESTORE_MODE\n          : \"=&r\" (flag), \"+m\" (*addr)\n          : \"r\" (addr), \"r\" (value)\n          : AO_THUMB_SWITCH_CLOBBERS \"cc\");\n      }\n#     define AO_HAVE_char_store\n\n      AO_INLINE void AO_short_store(volatile unsigned short *addr,\n                                    unsigned short value)\n      {\n        int flag;\n\n        __asm__ __volatile__(\"@AO_short_store\\n\"\n          AO_THUMB_GO_ARM\n          AO_BR_ALIGN\n          \"1: \" AO_MASK_PTR(\"%2\")\n          \"       ldrexh %0, [%2]\\n\"\n          AO_MASK_PTR(\"%2\")\n          \"       strexh %0, %3, [%2]\\n\"\n          \"       teq    %0, #0\\n\"\n          \"       bne 1b\\n\"\n          AO_THUMB_RESTORE_MODE\n          : \"=&r\" (flag), \"+m\" (*addr)\n          : \"r\" (addr), \"r\" (value)\n          : AO_THUMB_SWITCH_CLOBBERS \"cc\");\n      }\n#     define AO_HAVE_short_store\n#   endif /* AO_ARM_HAVE_LDREXBH */\n\n#   endif /* !AO_PREFER_BUILTIN_ATOMICS */\n\n# elif !defined(AO_GCC_ATOMIC_TEST_AND_SET)\n#   include \"../loadstore/atomic_store.h\"\n    /* AO_int_store is defined in ao_t_is_int.h.    */\n# endif /* !AO_BROKEN_TASKSWITCH_CLREX */\n\n#endif /* AO_ARM_HAVE_LDREX */\n\n#ifndef AO_GCC_ATOMIC_TEST_AND_SET\n\n# include \"../test_and_set_t_is_ao_t.h\" /* Probably suboptimal  */\n\n#ifdef AO_ARM_HAVE_LDREX\n\n  /* AO_t/char/short/int load is simple reading.                */\n  /* Unaligned accesses are not guaranteed to be atomic.        */\n# define AO_ACCESS_CHECK_ALIGNED\n# define AO_ACCESS_short_CHECK_ALIGNED\n# define AO_ACCESS_int_CHECK_ALIGNED\n# include \"../all_atomic_only_load.h\"\n\n# ifndef AO_HAVE_char_store\n#   include \"../loadstore/char_atomic_store.h\"\n#   include \"../loadstore/short_atomic_store.h\"\n# endif\n\n/* NEC LE-IT: replace the SWAP as recommended by ARM:\n   \"Applies to: ARM11 Cores\n      Though the SWP instruction will still work with ARM V6 cores, it is\n      recommended to use the new V6 synchronization instructions.  The SWP\n      instruction produces 'locked' read and write accesses which are atomic,\n      i.e. another operation cannot be done between these locked accesses which\n      ties up external bus (AHB, AXI) bandwidth and can increase worst case\n      interrupt latencies. LDREX, STREX are more flexible, other instructions\n      can be done between the LDREX and STREX accesses.\"\n*/\n#ifndef AO_PREFER_GENERALIZED\n#if !defined(AO_FORCE_USE_SWP) || !defined(AO_ARM_HAVE_SWP)\n  /* But, on the other hand, there could be a considerable performance  */\n  /* degradation in case of a race.  Eg., test_atomic.c executing       */\n  /* test_and_set test on a dual-core ARMv7 processor using LDREX/STREX */\n  /* showed around 35 times lower performance than that using SWP.      */\n  /* To force use of SWP instruction, use -D AO_FORCE_USE_SWP option    */\n  /* (the latter is ignored if SWP instruction is unsupported).         */\n  AO_INLINE AO_TS_VAL_t\n  AO_test_and_set(volatile AO_TS_t *addr)\n  {\n    AO_TS_VAL_t oldval;\n    int flag;\n\n    __asm__ __volatile__(\"@AO_test_and_set\\n\"\n      AO_THUMB_GO_ARM\n      AO_BR_ALIGN\n      \"1: \" AO_MASK_PTR(\"%3\")\n      \"       ldrex   %0, [%3]\\n\"\n      AO_MASK_PTR(\"%3\")\n      \"       strex   %1, %4, [%3]\\n\"\n      \"       teq     %1, #0\\n\"\n      \"       bne     1b\\n\"\n      AO_THUMB_RESTORE_MODE\n      : \"=&r\"(oldval), \"=&r\"(flag), \"+m\"(*addr)\n      : \"r\"(addr), \"r\"(1)\n      : AO_THUMB_SWITCH_CLOBBERS \"cc\");\n    return oldval;\n  }\n# define AO_HAVE_test_and_set\n#endif /* !AO_FORCE_USE_SWP */\n\nAO_INLINE AO_t\nAO_fetch_and_add(volatile AO_t *p, AO_t incr)\n{\n  AO_t result, tmp;\n  int flag;\n\n  __asm__ __volatile__(\"@AO_fetch_and_add\\n\"\n    AO_THUMB_GO_ARM\n    AO_BR_ALIGN\n    \"1: \" AO_MASK_PTR(\"%5\")\n    \"       ldrex   %0, [%5]\\n\"         /* get original         */\n    \"       add     %2, %0, %4\\n\"       /* sum up in incr       */\n    AO_MASK_PTR(\"%5\")\n    \"       strex   %1, %2, [%5]\\n\"     /* store them           */\n    \"       teq     %1, #0\\n\"\n    \"       bne     1b\\n\"\n    AO_THUMB_RESTORE_MODE\n    : \"=&r\"(result), \"=&r\"(flag), \"=&r\"(tmp), \"+m\"(*p) /* 0..3 */\n    : \"r\"(incr), \"r\"(p)                                /* 4..5 */\n    : AO_THUMB_SWITCH_CLOBBERS \"cc\");\n  return result;\n}\n#define AO_HAVE_fetch_and_add\n\nAO_INLINE AO_t\nAO_fetch_and_add1(volatile AO_t *p)\n{\n  AO_t result, tmp;\n  int flag;\n\n  __asm__ __volatile__(\"@AO_fetch_and_add1\\n\"\n    AO_THUMB_GO_ARM\n    AO_BR_ALIGN\n    \"1: \" AO_MASK_PTR(\"%4\")\n    \"       ldrex   %0, [%4]\\n\"         /* get original */\n    \"       add     %1, %0, #1\\n\"       /* increment */\n    AO_MASK_PTR(\"%4\")\n    \"       strex   %2, %1, [%4]\\n\"     /* store them */\n    \"       teq     %2, #0\\n\"\n    \"       bne     1b\\n\"\n    AO_THUMB_RESTORE_MODE\n    : \"=&r\"(result), \"=&r\"(tmp), \"=&r\"(flag), \"+m\"(*p)\n    : \"r\"(p)\n    : AO_THUMB_SWITCH_CLOBBERS \"cc\");\n  return result;\n}\n#define AO_HAVE_fetch_and_add1\n\nAO_INLINE AO_t\nAO_fetch_and_sub1(volatile AO_t *p)\n{\n  AO_t result, tmp;\n  int flag;\n\n  __asm__ __volatile__(\"@AO_fetch_and_sub1\\n\"\n    AO_THUMB_GO_ARM\n    AO_BR_ALIGN\n    \"1: \" AO_MASK_PTR(\"%4\")\n    \"       ldrex   %0, [%4]\\n\"         /* get original */\n    \"       sub     %1, %0, #1\\n\"       /* decrement */\n    AO_MASK_PTR(\"%4\")\n    \"       strex   %2, %1, [%4]\\n\"     /* store them */\n    \"       teq     %2, #0\\n\"\n    \"       bne     1b\\n\"\n    AO_THUMB_RESTORE_MODE\n    : \"=&r\"(result), \"=&r\"(tmp), \"=&r\"(flag), \"+m\"(*p)\n    : \"r\"(p)\n    : AO_THUMB_SWITCH_CLOBBERS \"cc\");\n  return result;\n}\n#define AO_HAVE_fetch_and_sub1\n\nAO_INLINE void\nAO_and(volatile AO_t *p, AO_t value)\n{\n  AO_t tmp, result;\n\n  __asm__ __volatile__(\"@AO_and\\n\"\n    AO_THUMB_GO_ARM\n    AO_BR_ALIGN\n    \"1: \" AO_MASK_PTR(\"%4\")\n    \"       ldrex   %0, [%4]\\n\"\n    \"       and     %1, %0, %3\\n\"\n    AO_MASK_PTR(\"%4\")\n    \"       strex   %0, %1, [%4]\\n\"\n    \"       teq     %0, #0\\n\"\n    \"       bne     1b\\n\"\n    AO_THUMB_RESTORE_MODE\n    : \"=&r\" (tmp), \"=&r\" (result), \"+m\" (*p)\n    : \"r\" (value), \"r\" (p)\n    : AO_THUMB_SWITCH_CLOBBERS \"cc\");\n}\n#define AO_HAVE_and\n\nAO_INLINE void\nAO_or(volatile AO_t *p, AO_t value)\n{\n  AO_t tmp, result;\n\n  __asm__ __volatile__(\"@AO_or\\n\"\n    AO_THUMB_GO_ARM\n    AO_BR_ALIGN\n    \"1: \" AO_MASK_PTR(\"%4\")\n    \"       ldrex   %0, [%4]\\n\"\n    \"       orr     %1, %0, %3\\n\"\n    AO_MASK_PTR(\"%4\")\n    \"       strex   %0, %1, [%4]\\n\"\n    \"       teq     %0, #0\\n\"\n    \"       bne     1b\\n\"\n    AO_THUMB_RESTORE_MODE\n    : \"=&r\" (tmp), \"=&r\" (result), \"+m\" (*p)\n    : \"r\" (value), \"r\" (p)\n    : AO_THUMB_SWITCH_CLOBBERS \"cc\");\n}\n#define AO_HAVE_or\n\nAO_INLINE void\nAO_xor(volatile AO_t *p, AO_t value)\n{\n  AO_t tmp, result;\n\n  __asm__ __volatile__(\"@AO_xor\\n\"\n    AO_THUMB_GO_ARM\n    AO_BR_ALIGN\n    \"1: \" AO_MASK_PTR(\"%4\")\n    \"       ldrex   %0, [%4]\\n\"\n    \"       eor     %1, %0, %3\\n\"\n    AO_MASK_PTR(\"%4\")\n    \"       strex   %0, %1, [%4]\\n\"\n    \"       teq     %0, #0\\n\"\n    \"       bne     1b\\n\"\n    AO_THUMB_RESTORE_MODE\n    : \"=&r\" (tmp), \"=&r\" (result), \"+m\" (*p)\n    : \"r\" (value), \"r\" (p)\n    : AO_THUMB_SWITCH_CLOBBERS \"cc\");\n}\n#define AO_HAVE_xor\n#endif /* !AO_PREFER_GENERALIZED */\n\n#ifdef AO_ARM_HAVE_LDREXBH\n  AO_INLINE unsigned char\n  AO_char_fetch_and_add(volatile unsigned char *p, unsigned char incr)\n  {\n    unsigned result, tmp;\n    int flag;\n\n    __asm__ __volatile__(\"@AO_char_fetch_and_add\\n\"\n      AO_THUMB_GO_ARM\n      AO_BR_ALIGN\n      \"1: \" AO_MASK_PTR(\"%5\")\n      \"       ldrexb  %0, [%5]\\n\"\n      \"       add     %2, %0, %4\\n\"\n      AO_MASK_PTR(\"%5\")\n      \"       strexb  %1, %2, [%5]\\n\"\n      \"       teq     %1, #0\\n\"\n      \"       bne     1b\\n\"\n      AO_THUMB_RESTORE_MODE\n      : \"=&r\" (result), \"=&r\" (flag), \"=&r\" (tmp), \"+m\" (*p)\n      : \"r\" ((unsigned)incr), \"r\" (p)\n      : AO_THUMB_SWITCH_CLOBBERS \"cc\");\n    return (unsigned char)result;\n  }\n# define AO_HAVE_char_fetch_and_add\n\n  AO_INLINE unsigned short\n  AO_short_fetch_and_add(volatile unsigned short *p, unsigned short incr)\n  {\n    unsigned result, tmp;\n    int flag;\n\n    __asm__ __volatile__(\"@AO_short_fetch_and_add\\n\"\n      AO_THUMB_GO_ARM\n      AO_BR_ALIGN\n      \"1: \" AO_MASK_PTR(\"%5\")\n      \"       ldrexh  %0, [%5]\\n\"\n      \"       add     %2, %0, %4\\n\"\n      AO_MASK_PTR(\"%5\")\n      \"       strexh  %1, %2, [%5]\\n\"\n      \"       teq     %1, #0\\n\"\n      \"       bne     1b\\n\"\n      AO_THUMB_RESTORE_MODE\n      : \"=&r\" (result), \"=&r\" (flag), \"=&r\" (tmp), \"+m\" (*p)\n      : \"r\" ((unsigned)incr), \"r\" (p)\n      : AO_THUMB_SWITCH_CLOBBERS \"cc\");\n    return (unsigned short)result;\n  }\n# define AO_HAVE_short_fetch_and_add\n#endif /* AO_ARM_HAVE_LDREXBH */\n\n#ifndef AO_GENERALIZE_ASM_BOOL_CAS\n  /* Returns nonzero if the comparison succeeded.       */\n  AO_INLINE int\n  AO_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val)\n  {\n    AO_t result, tmp;\n\n    __asm__ __volatile__(\"@AO_compare_and_swap\\n\"\n      AO_THUMB_GO_ARM\n      AO_BR_ALIGN\n      \"1:     mov     %0, #2\\n\"         /* store a flag */\n      AO_MASK_PTR(\"%3\")\n      \"       ldrex   %1, [%3]\\n\"       /* get original */\n      \"       teq     %1, %4\\n\"         /* see if match */\n      AO_MASK_PTR(\"%3\")\n#     ifdef __thumb2__\n        /* TODO: Eliminate warning: it blocks containing wide Thumb */\n        /* instructions are deprecated in ARMv8.                    */\n        \"       it      eq\\n\"\n#     endif\n      \"       strexeq %0, %5, [%3]\\n\"   /* store new one if matched */\n      \"       teq     %0, #1\\n\"\n      \"       beq     1b\\n\"             /* if update failed, repeat */\n      AO_THUMB_RESTORE_MODE\n      : \"=&r\"(result), \"=&r\"(tmp), \"+m\"(*addr)\n      : \"r\"(addr), \"r\"(old_val), \"r\"(new_val)\n      : AO_THUMB_SWITCH_CLOBBERS \"cc\");\n    return !(result&2); /* if succeeded then return 1 else 0 */\n  }\n# define AO_HAVE_compare_and_swap\n#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val)\n{\n  AO_t fetched_val;\n  int flag;\n\n  __asm__ __volatile__(\"@AO_fetch_compare_and_swap\\n\"\n    AO_THUMB_GO_ARM\n    AO_BR_ALIGN\n    \"1:     mov     %0, #2\\n\"           /* store a flag */\n    AO_MASK_PTR(\"%3\")\n    \"       ldrex   %1, [%3]\\n\"         /* get original */\n    \"       teq     %1, %4\\n\"           /* see if match */\n    AO_MASK_PTR(\"%3\")\n#   ifdef __thumb2__\n      \"       it      eq\\n\"\n#   endif\n    \"       strexeq %0, %5, [%3]\\n\"     /* store new one if matched */\n    \"       teq     %0, #1\\n\"\n    \"       beq     1b\\n\"               /* if update failed, repeat */\n    AO_THUMB_RESTORE_MODE\n    : \"=&r\"(flag), \"=&r\"(fetched_val), \"+m\"(*addr)\n    : \"r\"(addr), \"r\"(old_val), \"r\"(new_val)\n    : AO_THUMB_SWITCH_CLOBBERS \"cc\");\n  return fetched_val;\n}\n#define AO_HAVE_fetch_compare_and_swap\n\n#ifdef AO_ARM_HAVE_LDREXD\n# include \"../standard_ao_double_t.h\"\n\n  /* \"ARM Architecture Reference Manual ARMv7-A/R edition\" (chapter     */\n  /* A3.5.3) says that memory accesses caused by LDREXD and STREXD      */\n  /* instructions to doubleword-aligned locations are single-copy       */\n  /* atomic; accesses to 64-bit elements by other instructions might    */\n  /* not be single-copy atomic as they are executed as a sequence of    */\n  /* 32-bit accesses.                                                   */\n  AO_INLINE AO_double_t\n  AO_double_load(const volatile AO_double_t *addr)\n  {\n    AO_double_t result;\n\n    /* AO_THUMB_GO_ARM is empty. */\n    __asm__ __volatile__(\"@AO_double_load\\n\"\n      AO_MASK_PTR(\"%1\")\n      \"       ldrexd  %0, %H0, [%1]\"\n      : \"=&r\" (result.AO_whole)\n      : \"r\" (addr)\n      /* : no clobber */);\n    return result;\n  }\n# define AO_HAVE_double_load\n\n  AO_INLINE void\n  AO_double_store(volatile AO_double_t *addr, AO_double_t new_val)\n  {\n    AO_double_t old_val;\n    int status;\n\n    do {\n      /* AO_THUMB_GO_ARM is empty. */\n      __asm__ __volatile__(\"@AO_double_store\\n\"\n        AO_MASK_PTR(\"%3\")\n        \"       ldrexd  %0, %H0, [%3]\\n\"\n        AO_MASK_PTR(\"%3\")\n        \"       strexd  %1, %4, %H4, [%3]\"\n        : \"=&r\" (old_val.AO_whole), \"=&r\" (status), \"+m\" (*addr)\n        : \"r\" (addr), \"r\" (new_val.AO_whole)\n        : \"cc\");\n    } while (AO_EXPECT_FALSE(status));\n  }\n# define AO_HAVE_double_store\n\n  AO_INLINE int\n  AO_double_compare_and_swap(volatile AO_double_t *addr,\n                             AO_double_t old_val, AO_double_t new_val)\n  {\n    double_ptr_storage tmp;\n    int result = 1;\n\n    do {\n      /* AO_THUMB_GO_ARM is empty. */\n      __asm__ __volatile__(\"@AO_double_compare_and_swap\\n\"\n        AO_MASK_PTR(\"%1\")\n        \"       ldrexd  %0, %H0, [%1]\\n\" /* get original to r1 & r2 */\n        : \"=&r\"(tmp)\n        : \"r\"(addr)\n        /* : no clobber */);\n      if (tmp != old_val.AO_whole)\n        break;\n      __asm__ __volatile__(\n        AO_MASK_PTR(\"%2\")\n        \"       strexd  %0, %3, %H3, [%2]\\n\" /* store new one if matched */\n        : \"=&r\"(result), \"+m\"(*addr)\n        : \"r\" (addr), \"r\" (new_val.AO_whole)\n        : \"cc\");\n    } while (AO_EXPECT_FALSE(result));\n    return !result;   /* if succeeded then return 1 else 0 */\n  }\n# define AO_HAVE_double_compare_and_swap\n#endif /* AO_ARM_HAVE_LDREXD */\n\n#else\n/* pre ARMv6 architectures ... */\n\n/* I found a slide set that, if I read it correctly, claims that        */\n/* Loads followed by either a Load or Store are ordered, but nothing    */\n/* else is.                                                             */\n/* It appears that SWP is the only simple memory barrier.               */\n#include \"../all_aligned_atomic_load_store.h\"\n\n/* The code should run correctly on a multi-core ARMv6+ as well.        */\n\n#endif /* !AO_ARM_HAVE_LDREX */\n\n#if !defined(AO_HAVE_test_and_set_full) && !defined(AO_HAVE_test_and_set) \\\n    && defined (AO_ARM_HAVE_SWP) && (!defined(AO_PREFER_GENERALIZED) \\\n                                || !defined(AO_HAVE_fetch_compare_and_swap))\n  AO_INLINE AO_TS_VAL_t\n  AO_test_and_set_full(volatile AO_TS_t *addr)\n  {\n    AO_TS_VAL_t oldval;\n    /* SWP on ARM is very similar to XCHG on x86.                       */\n    /* The first operand is the result, the second the value            */\n    /* to be stored.  Both registers must be different from addr.       */\n    /* Make the address operand an early clobber output so it           */\n    /* doesn't overlap with the other operands.  The early clobber      */\n    /* on oldval is necessary to prevent the compiler allocating        */\n    /* them to the same register if they are both unused.               */\n\n    __asm__ __volatile__(\"@AO_test_and_set_full\\n\"\n      AO_THUMB_GO_ARM\n      AO_MASK_PTR(\"%3\")\n      \"       swp %0, %2, [%3]\\n\"\n                /* Ignore GCC \"SWP is deprecated for this architecture\" */\n                /* warning here (for ARMv6+).                           */\n      AO_THUMB_RESTORE_MODE\n      : \"=&r\"(oldval), \"=&r\"(addr)\n      : \"r\"(1), \"1\"(addr)\n      : AO_THUMB_SWITCH_CLOBBERS \"memory\");\n    return oldval;\n  }\n# define AO_HAVE_test_and_set_full\n#endif /* !AO_HAVE_test_and_set[_full] && AO_ARM_HAVE_SWP */\n\n#define AO_T_IS_INT\n\n#else /* AO_GCC_ATOMIC_TEST_AND_SET */\n\n# if defined(__clang__) && !defined(AO_ARM_HAVE_LDREX)\n    /* As of clang-3.8, it cannot compile __atomic_and/or/xor_fetch     */\n    /* library calls yet for pre ARMv6.                                 */\n#   define AO_SKIPATOMIC_ANY_and_ANY\n#   define AO_SKIPATOMIC_ANY_or_ANY\n#   define AO_SKIPATOMIC_ANY_xor_ANY\n# endif\n\n# ifdef AO_ARM_HAVE_LDREXD\n#   include \"../standard_ao_double_t.h\"\n# endif\n# include \"generic.h\"\n\n#endif /* AO_GCC_ATOMIC_TEST_AND_SET */\n\n#undef AO_ARM_HAVE_DMB\n#undef AO_ARM_HAVE_LDREX\n#undef AO_ARM_HAVE_LDREXBH\n#undef AO_ARM_HAVE_LDREXD\n#undef AO_ARM_HAVE_SWP\n#undef AO_BR_ALIGN\n#undef AO_MASK_PTR\n#undef AO_SKIPATOMIC_ANY_and_ANY\n#undef AO_SKIPATOMIC_ANY_or_ANY\n#undef AO_SKIPATOMIC_ANY_xor_ANY\n#undef AO_SKIPATOMIC_char_store\n#undef AO_SKIPATOMIC_char_store_release\n#undef AO_SKIPATOMIC_int_store\n#undef AO_SKIPATOMIC_int_store_release\n#undef AO_SKIPATOMIC_short_store\n#undef AO_SKIPATOMIC_short_store_release\n#undef AO_SKIPATOMIC_store\n#undef AO_SKIPATOMIC_store_release\n#undef AO_THUMB_GO_ARM\n#undef AO_THUMB_RESTORE_MODE\n#undef AO_THUMB_SWITCH_CLOBBERS\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/avr32.h",
    "content": "/*\n * Copyright (C) 2009 Bradley Smith <brad@brad-smith.co.uk>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n *\n */\n\n#include \"../all_atomic_load_store.h\"\n\n#include \"../ordered.h\" /* There are no multiprocessor implementations. */\n\n#include \"../test_and_set_t_is_ao_t.h\"\n\n#ifndef AO_PREFER_GENERALIZED\n  AO_INLINE AO_TS_VAL_t\n  AO_test_and_set_full(volatile AO_TS_t *addr)\n  {\n        register long ret;\n\n        __asm__ __volatile__(\n                \"xchg %[oldval], %[mem], %[newval]\"\n                : [oldval] \"=&r\"(ret)\n                : [mem] \"r\"(addr), [newval] \"r\"(1)\n                : \"memory\");\n\n        return (AO_TS_VAL_t)ret;\n  }\n# define AO_HAVE_test_and_set_full\n#endif /* !AO_PREFER_GENERALIZED */\n\nAO_INLINE int\nAO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val)\n{\n       register long ret;\n\n       __asm__ __volatile__(\n               \"1: ssrf    5\\n\"\n               \"   ld.w    %[res], %[mem]\\n\"\n               \"   eor     %[res], %[oldval]\\n\"\n               \"   brne    2f\\n\"\n               \"   stcond  %[mem], %[newval]\\n\"\n               \"   brne    1b\\n\"\n               \"2:\\n\"\n               : [res] \"=&r\"(ret), [mem] \"=m\"(*addr)\n               : \"m\"(*addr), [newval] \"r\"(new_val), [oldval] \"r\"(old)\n               : \"cc\", \"memory\");\n\n       return (int)ret;\n}\n#define AO_HAVE_compare_and_swap_full\n\n/* TODO: implement AO_fetch_compare_and_swap.   */\n\n#define AO_T_IS_INT\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/cris.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* FIXME: seems to be untested.         */\n\n#include \"../all_atomic_load_store.h\"\n\n#include \"../ordered.h\"  /* There are no multiprocessor implementations. */\n\n#include \"../test_and_set_t_is_ao_t.h\"\n\n/*\n * The architecture apparently supports an \"f\" flag which is\n * set on preemption.  This essentially gives us load-locked,\n * store-conditional primitives, though I'm not quite sure how\n * this would work on a hypothetical multiprocessor.  -HB\n *\n * For details, see\n * http://developer.axis.com/doc/hardware/etrax100lx/prog_man/\n *      1_architectural_description.pdf\n *\n * TODO: Presumably many other primitives (notably CAS, including the double-\n * width versions) could be implemented in this manner, if someone got\n * around to it.\n */\n\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set_full(volatile AO_TS_t *addr) {\n    /* Ripped from linuxthreads/sysdeps/cris/pt-machine.h */\n    register unsigned long int ret;\n\n    /* Note the use of a dummy output of *addr to expose the write.  The\n       memory barrier is to stop *other* writes being moved past this code.  */\n      __asm__ __volatile__(\"clearf\\n\"\n                           \"0:\\n\\t\"\n                           \"movu.b [%2],%0\\n\\t\"\n                           \"ax\\n\\t\"\n                           \"move.b %3,[%2]\\n\\t\"\n                           \"bwf 0b\\n\\t\"\n                           \"clearf\"\n                           : \"=&r\" (ret), \"=m\" (*addr)\n                           : \"r\" (addr), \"r\" ((int) 1), \"m\" (*addr)\n                           : \"memory\");\n    return ret;\n}\n#define AO_HAVE_test_and_set_full\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/e2k.h",
    "content": "/*\n * Copyright (c) 2022 Ivan Maidanski\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* As of clang-9, all __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n are missing.   */\n#define AO_GCC_FORCE_HAVE_CAS\n\n#if (__SIZEOF_SIZE_T__ == 4) \\\n    || (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) && !defined(__clang__)) \\\n    || (defined(__clang__) && __iset__ >= 5 /* elbrus-v5 or later */ \\\n        && defined(AO_PREFER_BUILTIN_ATOMICS))\n  /* Note for 128-bit operations: clang reports warning                 */\n  /* \"large atomic operation may incur significant performance penalty\" */\n  /* and requires LDFLAGS=\"-latomic\", thus this is not on by default.   */\n# define AO_GCC_HAVE_double_SYNC_CAS\n# include \"../standard_ao_double_t.h\"\n#endif\n\n#include \"generic.h\"\n\n#undef AO_GCC_FORCE_HAVE_CAS\n#undef AO_GCC_HAVE_double_SYNC_CAS\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/generic-arithm.h",
    "content": "/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_char_ARITHM\n\nAO_INLINE unsigned/**/char\nAO_char_fetch_and_add(volatile unsigned/**/char *addr, unsigned/**/char incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_RELAXED);\n}\n#define AO_HAVE_char_fetch_and_add\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_char_and(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_char_and\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_char_or(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_char_or\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_char_xor(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_char_xor\n#endif\n\n#endif /* !AO_NO_char_ARITHM */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_short_ARITHM\n\nAO_INLINE unsigned/**/short\nAO_short_fetch_and_add(volatile unsigned/**/short *addr, unsigned/**/short incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_RELAXED);\n}\n#define AO_HAVE_short_fetch_and_add\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_short_and(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_short_and\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_short_or(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_short_or\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_short_xor(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_short_xor\n#endif\n\n#endif /* !AO_NO_short_ARITHM */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_int_ARITHM\n\nAO_INLINE unsigned\nAO_int_fetch_and_add(volatile unsigned *addr, unsigned incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_RELAXED);\n}\n#define AO_HAVE_int_fetch_and_add\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_int_and(volatile unsigned *addr, unsigned value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_int_and\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_int_or(volatile unsigned *addr, unsigned value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_int_or\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_int_xor(volatile unsigned *addr, unsigned value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_int_xor\n#endif\n\n#endif /* !AO_NO_int_ARITHM */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_ARITHM\n\nAO_INLINE AO_t\nAO_fetch_and_add(volatile AO_t *addr, AO_t incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_RELAXED);\n}\n#define AO_HAVE_fetch_and_add\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_and(volatile AO_t *addr, AO_t value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_and\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_or(volatile AO_t *addr, AO_t value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_or\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_xor(volatile AO_t *addr, AO_t value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_xor\n#endif\n\n#endif /* !AO_NO_ARITHM */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_char_ARITHM\n\nAO_INLINE unsigned/**/char\nAO_char_fetch_and_add_acquire(volatile unsigned/**/char *addr, unsigned/**/char incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_ACQUIRE);\n}\n#define AO_HAVE_char_fetch_and_add_acquire\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_char_and_acquire(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_ACQUIRE);\n  }\n# define AO_HAVE_char_and_acquire\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_char_or_acquire(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_ACQUIRE);\n  }\n# define AO_HAVE_char_or_acquire\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_char_xor_acquire(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_ACQUIRE);\n  }\n# define AO_HAVE_char_xor_acquire\n#endif\n\n#endif /* !AO_NO_char_ARITHM */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_short_ARITHM\n\nAO_INLINE unsigned/**/short\nAO_short_fetch_and_add_acquire(volatile unsigned/**/short *addr, unsigned/**/short incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_ACQUIRE);\n}\n#define AO_HAVE_short_fetch_and_add_acquire\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_short_and_acquire(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_ACQUIRE);\n  }\n# define AO_HAVE_short_and_acquire\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_short_or_acquire(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_ACQUIRE);\n  }\n# define AO_HAVE_short_or_acquire\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_short_xor_acquire(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_ACQUIRE);\n  }\n# define AO_HAVE_short_xor_acquire\n#endif\n\n#endif /* !AO_NO_short_ARITHM */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_int_ARITHM\n\nAO_INLINE unsigned\nAO_int_fetch_and_add_acquire(volatile unsigned *addr, unsigned incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_ACQUIRE);\n}\n#define AO_HAVE_int_fetch_and_add_acquire\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_int_and_acquire(volatile unsigned *addr, unsigned value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_ACQUIRE);\n  }\n# define AO_HAVE_int_and_acquire\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_int_or_acquire(volatile unsigned *addr, unsigned value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_ACQUIRE);\n  }\n# define AO_HAVE_int_or_acquire\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_int_xor_acquire(volatile unsigned *addr, unsigned value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_ACQUIRE);\n  }\n# define AO_HAVE_int_xor_acquire\n#endif\n\n#endif /* !AO_NO_int_ARITHM */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_ARITHM\n\nAO_INLINE AO_t\nAO_fetch_and_add_acquire(volatile AO_t *addr, AO_t incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_ACQUIRE);\n}\n#define AO_HAVE_fetch_and_add_acquire\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_and_acquire(volatile AO_t *addr, AO_t value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_ACQUIRE);\n  }\n# define AO_HAVE_and_acquire\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_or_acquire(volatile AO_t *addr, AO_t value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_ACQUIRE);\n  }\n# define AO_HAVE_or_acquire\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_xor_acquire(volatile AO_t *addr, AO_t value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_ACQUIRE);\n  }\n# define AO_HAVE_xor_acquire\n#endif\n\n#endif /* !AO_NO_ARITHM */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_char_ARITHM\n\nAO_INLINE unsigned/**/char\nAO_char_fetch_and_add_release(volatile unsigned/**/char *addr, unsigned/**/char incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_RELEASE);\n}\n#define AO_HAVE_char_fetch_and_add_release\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_char_and_release(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_char_and_release\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_char_or_release(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_char_or_release\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_char_xor_release(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_char_xor_release\n#endif\n\n#endif /* !AO_NO_char_ARITHM */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_short_ARITHM\n\nAO_INLINE unsigned/**/short\nAO_short_fetch_and_add_release(volatile unsigned/**/short *addr, unsigned/**/short incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_RELEASE);\n}\n#define AO_HAVE_short_fetch_and_add_release\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_short_and_release(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_short_and_release\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_short_or_release(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_short_or_release\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_short_xor_release(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_short_xor_release\n#endif\n\n#endif /* !AO_NO_short_ARITHM */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_int_ARITHM\n\nAO_INLINE unsigned\nAO_int_fetch_and_add_release(volatile unsigned *addr, unsigned incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_RELEASE);\n}\n#define AO_HAVE_int_fetch_and_add_release\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_int_and_release(volatile unsigned *addr, unsigned value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_int_and_release\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_int_or_release(volatile unsigned *addr, unsigned value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_int_or_release\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_int_xor_release(volatile unsigned *addr, unsigned value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_int_xor_release\n#endif\n\n#endif /* !AO_NO_int_ARITHM */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_ARITHM\n\nAO_INLINE AO_t\nAO_fetch_and_add_release(volatile AO_t *addr, AO_t incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_RELEASE);\n}\n#define AO_HAVE_fetch_and_add_release\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_and_release(volatile AO_t *addr, AO_t value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_and_release\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_or_release(volatile AO_t *addr, AO_t value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_or_release\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_xor_release(volatile AO_t *addr, AO_t value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_xor_release\n#endif\n\n#endif /* !AO_NO_ARITHM */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_char_ARITHM\n\nAO_INLINE unsigned/**/char\nAO_char_fetch_and_add_full(volatile unsigned/**/char *addr, unsigned/**/char incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_SEQ_CST);\n}\n#define AO_HAVE_char_fetch_and_add_full\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_char_and_full(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_SEQ_CST);\n  }\n# define AO_HAVE_char_and_full\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_char_or_full(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_SEQ_CST);\n  }\n# define AO_HAVE_char_or_full\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_char_xor_full(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_SEQ_CST);\n  }\n# define AO_HAVE_char_xor_full\n#endif\n\n#endif /* !AO_NO_char_ARITHM */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_short_ARITHM\n\nAO_INLINE unsigned/**/short\nAO_short_fetch_and_add_full(volatile unsigned/**/short *addr, unsigned/**/short incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_SEQ_CST);\n}\n#define AO_HAVE_short_fetch_and_add_full\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_short_and_full(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_SEQ_CST);\n  }\n# define AO_HAVE_short_and_full\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_short_or_full(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_SEQ_CST);\n  }\n# define AO_HAVE_short_or_full\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_short_xor_full(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_SEQ_CST);\n  }\n# define AO_HAVE_short_xor_full\n#endif\n\n#endif /* !AO_NO_short_ARITHM */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_int_ARITHM\n\nAO_INLINE unsigned\nAO_int_fetch_and_add_full(volatile unsigned *addr, unsigned incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_SEQ_CST);\n}\n#define AO_HAVE_int_fetch_and_add_full\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_int_and_full(volatile unsigned *addr, unsigned value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_SEQ_CST);\n  }\n# define AO_HAVE_int_and_full\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_int_or_full(volatile unsigned *addr, unsigned value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_SEQ_CST);\n  }\n# define AO_HAVE_int_or_full\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_int_xor_full(volatile unsigned *addr, unsigned value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_SEQ_CST);\n  }\n# define AO_HAVE_int_xor_full\n#endif\n\n#endif /* !AO_NO_int_ARITHM */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_ARITHM\n\nAO_INLINE AO_t\nAO_fetch_and_add_full(volatile AO_t *addr, AO_t incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_SEQ_CST);\n}\n#define AO_HAVE_fetch_and_add_full\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_and_full(volatile AO_t *addr, AO_t value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_SEQ_CST);\n  }\n# define AO_HAVE_and_full\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_or_full(volatile AO_t *addr, AO_t value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_SEQ_CST);\n  }\n# define AO_HAVE_or_full\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_xor_full(volatile AO_t *addr, AO_t value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_SEQ_CST);\n  }\n# define AO_HAVE_xor_full\n#endif\n\n#endif /* !AO_NO_ARITHM */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/generic-arithm.template",
    "content": "/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#ifndef AO_NO_XSIZE_ARITHM\n\nAO_INLINE XCTYPE\nAO_XSIZE_fetch_and_add_XBAR(volatile XCTYPE *addr, XCTYPE incr)\n{\n  return __atomic_fetch_add(addr, incr, __ATOMIC_XGCCBAR);\n}\n#define AO_HAVE_XSIZE_fetch_and_add_XBAR\n\n#ifndef AO_SKIPATOMIC_ANY_and_ANY\n  AO_INLINE void\n  AO_XSIZE_and_XBAR(volatile XCTYPE *addr, XCTYPE value)\n  {\n    (void)__atomic_and_fetch(addr, value, __ATOMIC_XGCCBAR);\n  }\n# define AO_HAVE_XSIZE_and_XBAR\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_or_ANY\n  AO_INLINE void\n  AO_XSIZE_or_XBAR(volatile XCTYPE *addr, XCTYPE value)\n  {\n    (void)__atomic_or_fetch(addr, value, __ATOMIC_XGCCBAR);\n  }\n# define AO_HAVE_XSIZE_or_XBAR\n#endif\n\n#ifndef AO_SKIPATOMIC_ANY_xor_ANY\n  AO_INLINE void\n  AO_XSIZE_xor_XBAR(volatile XCTYPE *addr, XCTYPE value)\n  {\n    (void)__atomic_xor_fetch(addr, value, __ATOMIC_XGCCBAR);\n  }\n# define AO_HAVE_XSIZE_xor_XBAR\n#endif\n\n#endif /* !AO_NO_XSIZE_ARITHM */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/generic-small.h",
    "content": "/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#if !defined(AO_GCC_HAVE_char_SYNC_CAS) || !defined(AO_PREFER_GENERALIZED)\n\nAO_INLINE unsigned/**/char\nAO_char_load(const volatile unsigned/**/char *addr)\n{\n  return __atomic_load_n(addr, __ATOMIC_RELAXED);\n}\n#define AO_HAVE_char_load\n\nAO_INLINE unsigned/**/char\nAO_char_load_acquire(const volatile unsigned/**/char *addr)\n{\n  return __atomic_load_n(addr, __ATOMIC_ACQUIRE);\n}\n#define AO_HAVE_char_load_acquire\n\n/* char_load_read is defined using load and nop_read.                  */\n/* TODO: Map it to ACQUIRE.  We should be strengthening the read and    */\n/* write stuff to the more general acquire/release versions.  It almost */\n/* never makes a difference and is much less error-prone.               */\n\n/* char_load_full is generalized using load and nop_full.              */\n/* TODO: Map it to SEQ_CST and clarify the documentation.               */\n\n/* TODO: Map load_dd_acquire_read to ACQUIRE.  Ideally it should be     */\n/* mapped to CONSUME, but the latter is currently broken.               */\n\n/* char_store_full definition is omitted similar to load_full reason.  */\n\n/* TODO: Map store_write to RELEASE.    */\n\n#ifndef AO_SKIPATOMIC_char_store\n  AO_INLINE void\n  AO_char_store(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    __atomic_store_n(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_char_store\n#endif\n\n#ifndef AO_SKIPATOMIC_char_store_release\n  AO_INLINE void\n  AO_char_store_release(volatile unsigned/**/char *addr, unsigned/**/char value)\n  {\n    __atomic_store_n(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_char_store_release\n#endif\n\n#endif /* !AO_GCC_HAVE_char_SYNC_CAS || !AO_PREFER_GENERALIZED */\n\n#ifdef AO_GCC_HAVE_char_SYNC_CAS\n\n  AO_INLINE unsigned/**/char\n  AO_char_fetch_compare_and_swap(volatile unsigned/**/char *addr,\n                                  unsigned/**/char old_val, unsigned/**/char new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr,\n                                      &old_val /* p_expected */,\n                                      new_val /* desired */,\n                                      0 /* is_weak: false */,\n                                      __ATOMIC_RELAXED /* success */,\n                                      __ATOMIC_RELAXED /* failure */);\n    return old_val;\n  }\n# define AO_HAVE_char_fetch_compare_and_swap\n\n  AO_INLINE unsigned/**/char\n  AO_char_fetch_compare_and_swap_acquire(volatile unsigned/**/char *addr,\n                                          unsigned/**/char old_val, unsigned/**/char new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                      __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);\n    return old_val;\n  }\n# define AO_HAVE_char_fetch_compare_and_swap_acquire\n\n  AO_INLINE unsigned/**/char\n  AO_char_fetch_compare_and_swap_release(volatile unsigned/**/char *addr,\n                                          unsigned/**/char old_val, unsigned/**/char new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                      __ATOMIC_RELEASE,\n                                      __ATOMIC_RELAXED /* failure */);\n    return old_val;\n  }\n# define AO_HAVE_char_fetch_compare_and_swap_release\n\n  AO_INLINE unsigned/**/char\n  AO_char_fetch_compare_and_swap_full(volatile unsigned/**/char *addr,\n                                       unsigned/**/char old_val, unsigned/**/char new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                      __ATOMIC_ACQ_REL,\n                                      __ATOMIC_ACQUIRE /* failure */);\n    return old_val;\n  }\n# define AO_HAVE_char_fetch_compare_and_swap_full\n\n# ifndef AO_GENERALIZE_ASM_BOOL_CAS\n    AO_INLINE int\n    AO_char_compare_and_swap(volatile unsigned/**/char *addr,\n                              unsigned/**/char old_val, unsigned/**/char new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                        __ATOMIC_RELAXED, __ATOMIC_RELAXED);\n    }\n#   define AO_HAVE_char_compare_and_swap\n\n    AO_INLINE int\n    AO_char_compare_and_swap_acquire(volatile unsigned/**/char *addr,\n                                      unsigned/**/char old_val, unsigned/**/char new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                        __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);\n    }\n#   define AO_HAVE_char_compare_and_swap_acquire\n\n    AO_INLINE int\n    AO_char_compare_and_swap_release(volatile unsigned/**/char *addr,\n                                      unsigned/**/char old_val, unsigned/**/char new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                              __ATOMIC_RELEASE,\n                                              __ATOMIC_RELAXED /* failure */);\n    }\n#   define AO_HAVE_char_compare_and_swap_release\n\n    AO_INLINE int\n    AO_char_compare_and_swap_full(volatile unsigned/**/char *addr,\n                                   unsigned/**/char old_val, unsigned/**/char new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                              __ATOMIC_ACQ_REL,\n                                              __ATOMIC_ACQUIRE /* failure */);\n    }\n#   define AO_HAVE_char_compare_and_swap_full\n\n# endif /* !AO_GENERALIZE_ASM_BOOL_CAS */\n\n#endif /* AO_GCC_HAVE_char_SYNC_CAS */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#if !defined(AO_GCC_HAVE_short_SYNC_CAS) || !defined(AO_PREFER_GENERALIZED)\n\nAO_INLINE unsigned/**/short\nAO_short_load(const volatile unsigned/**/short *addr)\n{\n  return __atomic_load_n(addr, __ATOMIC_RELAXED);\n}\n#define AO_HAVE_short_load\n\nAO_INLINE unsigned/**/short\nAO_short_load_acquire(const volatile unsigned/**/short *addr)\n{\n  return __atomic_load_n(addr, __ATOMIC_ACQUIRE);\n}\n#define AO_HAVE_short_load_acquire\n\n/* short_load_read is defined using load and nop_read.                  */\n/* TODO: Map it to ACQUIRE.  We should be strengthening the read and    */\n/* write stuff to the more general acquire/release versions.  It almost */\n/* never makes a difference and is much less error-prone.               */\n\n/* short_load_full is generalized using load and nop_full.              */\n/* TODO: Map it to SEQ_CST and clarify the documentation.               */\n\n/* TODO: Map load_dd_acquire_read to ACQUIRE.  Ideally it should be     */\n/* mapped to CONSUME, but the latter is currently broken.               */\n\n/* short_store_full definition is omitted similar to load_full reason.  */\n\n/* TODO: Map store_write to RELEASE.    */\n\n#ifndef AO_SKIPATOMIC_short_store\n  AO_INLINE void\n  AO_short_store(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    __atomic_store_n(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_short_store\n#endif\n\n#ifndef AO_SKIPATOMIC_short_store_release\n  AO_INLINE void\n  AO_short_store_release(volatile unsigned/**/short *addr, unsigned/**/short value)\n  {\n    __atomic_store_n(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_short_store_release\n#endif\n\n#endif /* !AO_GCC_HAVE_short_SYNC_CAS || !AO_PREFER_GENERALIZED */\n\n#ifdef AO_GCC_HAVE_short_SYNC_CAS\n\n  AO_INLINE unsigned/**/short\n  AO_short_fetch_compare_and_swap(volatile unsigned/**/short *addr,\n                                  unsigned/**/short old_val, unsigned/**/short new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr,\n                                      &old_val /* p_expected */,\n                                      new_val /* desired */,\n                                      0 /* is_weak: false */,\n                                      __ATOMIC_RELAXED /* success */,\n                                      __ATOMIC_RELAXED /* failure */);\n    return old_val;\n  }\n# define AO_HAVE_short_fetch_compare_and_swap\n\n  AO_INLINE unsigned/**/short\n  AO_short_fetch_compare_and_swap_acquire(volatile unsigned/**/short *addr,\n                                          unsigned/**/short old_val, unsigned/**/short new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                      __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);\n    return old_val;\n  }\n# define AO_HAVE_short_fetch_compare_and_swap_acquire\n\n  AO_INLINE unsigned/**/short\n  AO_short_fetch_compare_and_swap_release(volatile unsigned/**/short *addr,\n                                          unsigned/**/short old_val, unsigned/**/short new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                      __ATOMIC_RELEASE,\n                                      __ATOMIC_RELAXED /* failure */);\n    return old_val;\n  }\n# define AO_HAVE_short_fetch_compare_and_swap_release\n\n  AO_INLINE unsigned/**/short\n  AO_short_fetch_compare_and_swap_full(volatile unsigned/**/short *addr,\n                                       unsigned/**/short old_val, unsigned/**/short new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                      __ATOMIC_ACQ_REL,\n                                      __ATOMIC_ACQUIRE /* failure */);\n    return old_val;\n  }\n# define AO_HAVE_short_fetch_compare_and_swap_full\n\n# ifndef AO_GENERALIZE_ASM_BOOL_CAS\n    AO_INLINE int\n    AO_short_compare_and_swap(volatile unsigned/**/short *addr,\n                              unsigned/**/short old_val, unsigned/**/short new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                        __ATOMIC_RELAXED, __ATOMIC_RELAXED);\n    }\n#   define AO_HAVE_short_compare_and_swap\n\n    AO_INLINE int\n    AO_short_compare_and_swap_acquire(volatile unsigned/**/short *addr,\n                                      unsigned/**/short old_val, unsigned/**/short new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                        __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);\n    }\n#   define AO_HAVE_short_compare_and_swap_acquire\n\n    AO_INLINE int\n    AO_short_compare_and_swap_release(volatile unsigned/**/short *addr,\n                                      unsigned/**/short old_val, unsigned/**/short new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                              __ATOMIC_RELEASE,\n                                              __ATOMIC_RELAXED /* failure */);\n    }\n#   define AO_HAVE_short_compare_and_swap_release\n\n    AO_INLINE int\n    AO_short_compare_and_swap_full(volatile unsigned/**/short *addr,\n                                   unsigned/**/short old_val, unsigned/**/short new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                              __ATOMIC_ACQ_REL,\n                                              __ATOMIC_ACQUIRE /* failure */);\n    }\n#   define AO_HAVE_short_compare_and_swap_full\n\n# endif /* !AO_GENERALIZE_ASM_BOOL_CAS */\n\n#endif /* AO_GCC_HAVE_short_SYNC_CAS */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#if !defined(AO_GCC_HAVE_int_SYNC_CAS) || !defined(AO_PREFER_GENERALIZED)\n\nAO_INLINE unsigned\nAO_int_load(const volatile unsigned *addr)\n{\n  return __atomic_load_n(addr, __ATOMIC_RELAXED);\n}\n#define AO_HAVE_int_load\n\nAO_INLINE unsigned\nAO_int_load_acquire(const volatile unsigned *addr)\n{\n  return __atomic_load_n(addr, __ATOMIC_ACQUIRE);\n}\n#define AO_HAVE_int_load_acquire\n\n/* int_load_read is defined using load and nop_read.                  */\n/* TODO: Map it to ACQUIRE.  We should be strengthening the read and    */\n/* write stuff to the more general acquire/release versions.  It almost */\n/* never makes a difference and is much less error-prone.               */\n\n/* int_load_full is generalized using load and nop_full.              */\n/* TODO: Map it to SEQ_CST and clarify the documentation.               */\n\n/* TODO: Map load_dd_acquire_read to ACQUIRE.  Ideally it should be     */\n/* mapped to CONSUME, but the latter is currently broken.               */\n\n/* int_store_full definition is omitted similar to load_full reason.  */\n\n/* TODO: Map store_write to RELEASE.    */\n\n#ifndef AO_SKIPATOMIC_int_store\n  AO_INLINE void\n  AO_int_store(volatile unsigned *addr, unsigned value)\n  {\n    __atomic_store_n(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_int_store\n#endif\n\n#ifndef AO_SKIPATOMIC_int_store_release\n  AO_INLINE void\n  AO_int_store_release(volatile unsigned *addr, unsigned value)\n  {\n    __atomic_store_n(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_int_store_release\n#endif\n\n#endif /* !AO_GCC_HAVE_int_SYNC_CAS || !AO_PREFER_GENERALIZED */\n\n#ifdef AO_GCC_HAVE_int_SYNC_CAS\n\n  AO_INLINE unsigned\n  AO_int_fetch_compare_and_swap(volatile unsigned *addr,\n                                  unsigned old_val, unsigned new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr,\n                                      &old_val /* p_expected */,\n                                      new_val /* desired */,\n                                      0 /* is_weak: false */,\n                                      __ATOMIC_RELAXED /* success */,\n                                      __ATOMIC_RELAXED /* failure */);\n    return old_val;\n  }\n# define AO_HAVE_int_fetch_compare_and_swap\n\n  AO_INLINE unsigned\n  AO_int_fetch_compare_and_swap_acquire(volatile unsigned *addr,\n                                          unsigned old_val, unsigned new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                      __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);\n    return old_val;\n  }\n# define AO_HAVE_int_fetch_compare_and_swap_acquire\n\n  AO_INLINE unsigned\n  AO_int_fetch_compare_and_swap_release(volatile unsigned *addr,\n                                          unsigned old_val, unsigned new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                      __ATOMIC_RELEASE,\n                                      __ATOMIC_RELAXED /* failure */);\n    return old_val;\n  }\n# define AO_HAVE_int_fetch_compare_and_swap_release\n\n  AO_INLINE unsigned\n  AO_int_fetch_compare_and_swap_full(volatile unsigned *addr,\n                                       unsigned old_val, unsigned new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                      __ATOMIC_ACQ_REL,\n                                      __ATOMIC_ACQUIRE /* failure */);\n    return old_val;\n  }\n# define AO_HAVE_int_fetch_compare_and_swap_full\n\n# ifndef AO_GENERALIZE_ASM_BOOL_CAS\n    AO_INLINE int\n    AO_int_compare_and_swap(volatile unsigned *addr,\n                              unsigned old_val, unsigned new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                        __ATOMIC_RELAXED, __ATOMIC_RELAXED);\n    }\n#   define AO_HAVE_int_compare_and_swap\n\n    AO_INLINE int\n    AO_int_compare_and_swap_acquire(volatile unsigned *addr,\n                                      unsigned old_val, unsigned new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                        __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);\n    }\n#   define AO_HAVE_int_compare_and_swap_acquire\n\n    AO_INLINE int\n    AO_int_compare_and_swap_release(volatile unsigned *addr,\n                                      unsigned old_val, unsigned new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                              __ATOMIC_RELEASE,\n                                              __ATOMIC_RELAXED /* failure */);\n    }\n#   define AO_HAVE_int_compare_and_swap_release\n\n    AO_INLINE int\n    AO_int_compare_and_swap_full(volatile unsigned *addr,\n                                   unsigned old_val, unsigned new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                              __ATOMIC_ACQ_REL,\n                                              __ATOMIC_ACQUIRE /* failure */);\n    }\n#   define AO_HAVE_int_compare_and_swap_full\n\n# endif /* !AO_GENERALIZE_ASM_BOOL_CAS */\n\n#endif /* AO_GCC_HAVE_int_SYNC_CAS */\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#if !defined(AO_GCC_HAVE_SYNC_CAS) || !defined(AO_PREFER_GENERALIZED)\n\nAO_INLINE AO_t\nAO_load(const volatile AO_t *addr)\n{\n  return __atomic_load_n(addr, __ATOMIC_RELAXED);\n}\n#define AO_HAVE_load\n\nAO_INLINE AO_t\nAO_load_acquire(const volatile AO_t *addr)\n{\n  return __atomic_load_n(addr, __ATOMIC_ACQUIRE);\n}\n#define AO_HAVE_load_acquire\n\n/* load_read is defined using load and nop_read.                  */\n/* TODO: Map it to ACQUIRE.  We should be strengthening the read and    */\n/* write stuff to the more general acquire/release versions.  It almost */\n/* never makes a difference and is much less error-prone.               */\n\n/* load_full is generalized using load and nop_full.              */\n/* TODO: Map it to SEQ_CST and clarify the documentation.               */\n\n/* TODO: Map load_dd_acquire_read to ACQUIRE.  Ideally it should be     */\n/* mapped to CONSUME, but the latter is currently broken.               */\n\n/* store_full definition is omitted similar to load_full reason.  */\n\n/* TODO: Map store_write to RELEASE.    */\n\n#ifndef AO_SKIPATOMIC_store\n  AO_INLINE void\n  AO_store(volatile AO_t *addr, AO_t value)\n  {\n    __atomic_store_n(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_store\n#endif\n\n#ifndef AO_SKIPATOMIC_store_release\n  AO_INLINE void\n  AO_store_release(volatile AO_t *addr, AO_t value)\n  {\n    __atomic_store_n(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_store_release\n#endif\n\n#endif /* !AO_GCC_HAVE_SYNC_CAS || !AO_PREFER_GENERALIZED */\n\n#ifdef AO_GCC_HAVE_SYNC_CAS\n\n  AO_INLINE AO_t\n  AO_fetch_compare_and_swap(volatile AO_t *addr,\n                                  AO_t old_val, AO_t new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr,\n                                      &old_val /* p_expected */,\n                                      new_val /* desired */,\n                                      0 /* is_weak: false */,\n                                      __ATOMIC_RELAXED /* success */,\n                                      __ATOMIC_RELAXED /* failure */);\n    return old_val;\n  }\n# define AO_HAVE_fetch_compare_and_swap\n\n  AO_INLINE AO_t\n  AO_fetch_compare_and_swap_acquire(volatile AO_t *addr,\n                                          AO_t old_val, AO_t new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                      __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);\n    return old_val;\n  }\n# define AO_HAVE_fetch_compare_and_swap_acquire\n\n  AO_INLINE AO_t\n  AO_fetch_compare_and_swap_release(volatile AO_t *addr,\n                                          AO_t old_val, AO_t new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                      __ATOMIC_RELEASE,\n                                      __ATOMIC_RELAXED /* failure */);\n    return old_val;\n  }\n# define AO_HAVE_fetch_compare_and_swap_release\n\n  AO_INLINE AO_t\n  AO_fetch_compare_and_swap_full(volatile AO_t *addr,\n                                       AO_t old_val, AO_t new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                      __ATOMIC_ACQ_REL,\n                                      __ATOMIC_ACQUIRE /* failure */);\n    return old_val;\n  }\n# define AO_HAVE_fetch_compare_and_swap_full\n\n# ifndef AO_GENERALIZE_ASM_BOOL_CAS\n    AO_INLINE int\n    AO_compare_and_swap(volatile AO_t *addr,\n                              AO_t old_val, AO_t new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                        __ATOMIC_RELAXED, __ATOMIC_RELAXED);\n    }\n#   define AO_HAVE_compare_and_swap\n\n    AO_INLINE int\n    AO_compare_and_swap_acquire(volatile AO_t *addr,\n                                      AO_t old_val, AO_t new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                        __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);\n    }\n#   define AO_HAVE_compare_and_swap_acquire\n\n    AO_INLINE int\n    AO_compare_and_swap_release(volatile AO_t *addr,\n                                      AO_t old_val, AO_t new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                              __ATOMIC_RELEASE,\n                                              __ATOMIC_RELAXED /* failure */);\n    }\n#   define AO_HAVE_compare_and_swap_release\n\n    AO_INLINE int\n    AO_compare_and_swap_full(volatile AO_t *addr,\n                                   AO_t old_val, AO_t new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                              __ATOMIC_ACQ_REL,\n                                              __ATOMIC_ACQUIRE /* failure */);\n    }\n#   define AO_HAVE_compare_and_swap_full\n\n# endif /* !AO_GENERALIZE_ASM_BOOL_CAS */\n\n#endif /* AO_GCC_HAVE_SYNC_CAS */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/generic-small.template",
    "content": "/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#if !defined(AO_GCC_HAVE_XSIZE_SYNC_CAS) || !defined(AO_PREFER_GENERALIZED)\n\nAO_INLINE XCTYPE\nAO_XSIZE_load(const volatile XCTYPE *addr)\n{\n  return __atomic_load_n(addr, __ATOMIC_RELAXED);\n}\n#define AO_HAVE_XSIZE_load\n\nAO_INLINE XCTYPE\nAO_XSIZE_load_acquire(const volatile XCTYPE *addr)\n{\n  return __atomic_load_n(addr, __ATOMIC_ACQUIRE);\n}\n#define AO_HAVE_XSIZE_load_acquire\n\n/* XSIZE_load_read is defined using load and nop_read.                  */\n/* TODO: Map it to ACQUIRE.  We should be strengthening the read and    */\n/* write stuff to the more general acquire/release versions.  It almost */\n/* never makes a difference and is much less error-prone.               */\n\n/* XSIZE_load_full is generalized using load and nop_full.              */\n/* TODO: Map it to SEQ_CST and clarify the documentation.               */\n\n/* TODO: Map load_dd_acquire_read to ACQUIRE.  Ideally it should be     */\n/* mapped to CONSUME, but the latter is currently broken.               */\n\n/* XSIZE_store_full definition is omitted similar to load_full reason.  */\n\n/* TODO: Map store_write to RELEASE.    */\n\n#ifndef AO_SKIPATOMIC_XSIZE_store\n  AO_INLINE void\n  AO_XSIZE_store(volatile XCTYPE *addr, XCTYPE value)\n  {\n    __atomic_store_n(addr, value, __ATOMIC_RELAXED);\n  }\n# define AO_HAVE_XSIZE_store\n#endif\n\n#ifndef AO_SKIPATOMIC_XSIZE_store_release\n  AO_INLINE void\n  AO_XSIZE_store_release(volatile XCTYPE *addr, XCTYPE value)\n  {\n    __atomic_store_n(addr, value, __ATOMIC_RELEASE);\n  }\n# define AO_HAVE_XSIZE_store_release\n#endif\n\n#endif /* !AO_GCC_HAVE_XSIZE_SYNC_CAS || !AO_PREFER_GENERALIZED */\n\n#ifdef AO_GCC_HAVE_XSIZE_SYNC_CAS\n\n  AO_INLINE XCTYPE\n  AO_XSIZE_fetch_compare_and_swap(volatile XCTYPE *addr,\n                                  XCTYPE old_val, XCTYPE new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr,\n                                      &old_val /* p_expected */,\n                                      new_val /* desired */,\n                                      0 /* is_weak: false */,\n                                      __ATOMIC_RELAXED /* success */,\n                                      __ATOMIC_RELAXED /* failure */);\n    return old_val;\n  }\n# define AO_HAVE_XSIZE_fetch_compare_and_swap\n\n  AO_INLINE XCTYPE\n  AO_XSIZE_fetch_compare_and_swap_acquire(volatile XCTYPE *addr,\n                                          XCTYPE old_val, XCTYPE new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                      __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);\n    return old_val;\n  }\n# define AO_HAVE_XSIZE_fetch_compare_and_swap_acquire\n\n  AO_INLINE XCTYPE\n  AO_XSIZE_fetch_compare_and_swap_release(volatile XCTYPE *addr,\n                                          XCTYPE old_val, XCTYPE new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                      __ATOMIC_RELEASE,\n                                      __ATOMIC_RELAXED /* failure */);\n    return old_val;\n  }\n# define AO_HAVE_XSIZE_fetch_compare_and_swap_release\n\n  AO_INLINE XCTYPE\n  AO_XSIZE_fetch_compare_and_swap_full(volatile XCTYPE *addr,\n                                       XCTYPE old_val, XCTYPE new_val)\n  {\n    (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                      __ATOMIC_ACQ_REL,\n                                      __ATOMIC_ACQUIRE /* failure */);\n    return old_val;\n  }\n# define AO_HAVE_XSIZE_fetch_compare_and_swap_full\n\n# ifndef AO_GENERALIZE_ASM_BOOL_CAS\n    AO_INLINE int\n    AO_XSIZE_compare_and_swap(volatile XCTYPE *addr,\n                              XCTYPE old_val, XCTYPE new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                        __ATOMIC_RELAXED, __ATOMIC_RELAXED);\n    }\n#   define AO_HAVE_XSIZE_compare_and_swap\n\n    AO_INLINE int\n    AO_XSIZE_compare_and_swap_acquire(volatile XCTYPE *addr,\n                                      XCTYPE old_val, XCTYPE new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                        __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);\n    }\n#   define AO_HAVE_XSIZE_compare_and_swap_acquire\n\n    AO_INLINE int\n    AO_XSIZE_compare_and_swap_release(volatile XCTYPE *addr,\n                                      XCTYPE old_val, XCTYPE new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                              __ATOMIC_RELEASE,\n                                              __ATOMIC_RELAXED /* failure */);\n    }\n#   define AO_HAVE_XSIZE_compare_and_swap_release\n\n    AO_INLINE int\n    AO_XSIZE_compare_and_swap_full(volatile XCTYPE *addr,\n                                   XCTYPE old_val, XCTYPE new_val)\n    {\n      return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                                              __ATOMIC_ACQ_REL,\n                                              __ATOMIC_ACQUIRE /* failure */);\n    }\n#   define AO_HAVE_XSIZE_compare_and_swap_full\n\n# endif /* !AO_GENERALIZE_ASM_BOOL_CAS */\n\n#endif /* AO_GCC_HAVE_XSIZE_SYNC_CAS */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/generic.h",
    "content": "/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2013-2017 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n/* The following implementation assumes GCC 4.7 or later.               */\n/* For the details, see GNU Manual, chapter 6.52 (Built-in functions    */\n/* for memory model aware atomic operations).                           */\n\n#define AO_GCC_ATOMIC_TEST_AND_SET\n#include \"../test_and_set_t_is_char.h\"\n\n#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) \\\n    || defined(AO_GCC_FORCE_HAVE_CAS)\n# define AO_GCC_HAVE_char_SYNC_CAS\n#endif\n\n#if (__SIZEOF_SHORT__ == 2 && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)) \\\n    || defined(AO_GCC_FORCE_HAVE_CAS)\n# define AO_GCC_HAVE_short_SYNC_CAS\n#endif\n\n#if (__SIZEOF_INT__ == 4 && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) \\\n    || (__SIZEOF_INT__ == 8 && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)) \\\n    || defined(AO_GCC_FORCE_HAVE_CAS)\n# define AO_GCC_HAVE_int_SYNC_CAS\n#endif\n\n#if (__SIZEOF_SIZE_T__ == 4 && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) \\\n    || (__SIZEOF_SIZE_T__ == 8 \\\n        && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)) \\\n    || defined(AO_GCC_FORCE_HAVE_CAS)\n# define AO_GCC_HAVE_SYNC_CAS\n#endif\n\n#undef AO_compiler_barrier\n#define AO_compiler_barrier() __atomic_signal_fence(__ATOMIC_SEQ_CST)\n\n#ifdef AO_UNIPROCESSOR\n  /* If only a single processor (core) is used, AO_UNIPROCESSOR could   */\n  /* be defined by the client to avoid unnecessary memory barrier.      */\n  AO_INLINE void\n  AO_nop_full(void)\n  {\n    AO_compiler_barrier();\n  }\n# define AO_HAVE_nop_full\n\n#elif defined(AO_THREAD_SANITIZER) && !defined(AO_USE_ATOMIC_THREAD_FENCE)\n  /* Workaround a compiler warning (reported by gcc-11, at least)   */\n  /* that atomic_thread_fence is unsupported with thread sanitizer. */\n\n#else\n  AO_INLINE void\n  AO_nop_read(void)\n  {\n    __atomic_thread_fence(__ATOMIC_ACQUIRE);\n  }\n# define AO_HAVE_nop_read\n\n# ifndef AO_HAVE_nop_write\n    AO_INLINE void\n    AO_nop_write(void)\n    {\n      __atomic_thread_fence(__ATOMIC_RELEASE);\n    }\n#   define AO_HAVE_nop_write\n# endif\n\n  AO_INLINE void\n  AO_nop_full(void)\n  {\n    /* __sync_synchronize() could be used instead.      */\n    __atomic_thread_fence(__ATOMIC_SEQ_CST);\n  }\n# define AO_HAVE_nop_full\n#endif /* !AO_UNIPROCESSOR && !AO_THREAD_SANITIZER */\n\n#include \"generic-small.h\"\n\n#ifndef AO_PREFER_GENERALIZED\n# include \"generic-arithm.h\"\n\n# define AO_CLEAR(addr) __atomic_clear(addr, __ATOMIC_RELEASE)\n# define AO_HAVE_CLEAR\n\n  AO_INLINE AO_TS_VAL_t\n  AO_test_and_set(volatile AO_TS_t *addr)\n  {\n    return (AO_TS_VAL_t)(__atomic_test_and_set(addr, __ATOMIC_RELAXED)\n                         ? AO_TS_SET : AO_TS_CLEAR);\n  }\n# define AO_HAVE_test_and_set\n\n  AO_INLINE AO_TS_VAL_t\n  AO_test_and_set_acquire(volatile AO_TS_t *addr)\n  {\n    return (AO_TS_VAL_t)(__atomic_test_and_set(addr, __ATOMIC_ACQUIRE)\n                         ? AO_TS_SET : AO_TS_CLEAR);\n  }\n# define AO_HAVE_test_and_set_acquire\n\n  AO_INLINE AO_TS_VAL_t\n  AO_test_and_set_release(volatile AO_TS_t *addr)\n  {\n    return (AO_TS_VAL_t)(__atomic_test_and_set(addr, __ATOMIC_RELEASE)\n                         ? AO_TS_SET : AO_TS_CLEAR);\n  }\n# define AO_HAVE_test_and_set_release\n\n  AO_INLINE AO_TS_VAL_t\n  AO_test_and_set_full(volatile AO_TS_t *addr)\n  {\n    return (AO_TS_VAL_t)(__atomic_test_and_set(addr, __ATOMIC_SEQ_CST)\n                         ? AO_TS_SET : AO_TS_CLEAR);\n  }\n# define AO_HAVE_test_and_set_full\n#endif /* !AO_PREFER_GENERALIZED */\n\n#ifdef AO_HAVE_DOUBLE_PTR_STORAGE\n\n# if ((__SIZEOF_SIZE_T__ == 4 \\\n       && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)) \\\n      || (__SIZEOF_SIZE_T__ == 8 /* half of AO_double_t */ \\\n          && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16))) \\\n     && !defined(AO_SKIPATOMIC_double_compare_and_swap_ANY)\n#   define AO_GCC_HAVE_double_SYNC_CAS\n# endif\n\n# if !defined(AO_GCC_HAVE_double_SYNC_CAS) || !defined(AO_PREFER_GENERALIZED)\n\n# if !defined(AO_HAVE_double_load) && !defined(AO_SKIPATOMIC_double_load)\n    AO_INLINE AO_double_t\n    AO_double_load(const volatile AO_double_t *addr)\n    {\n      AO_double_t result;\n\n      result.AO_whole = __atomic_load_n(&addr->AO_whole, __ATOMIC_RELAXED);\n      return result;\n    }\n#   define AO_HAVE_double_load\n# endif\n\n# if !defined(AO_HAVE_double_load_acquire) \\\n     && !defined(AO_SKIPATOMIC_double_load_acquire)\n    AO_INLINE AO_double_t\n    AO_double_load_acquire(const volatile AO_double_t *addr)\n    {\n      AO_double_t result;\n\n      result.AO_whole = __atomic_load_n(&addr->AO_whole, __ATOMIC_ACQUIRE);\n      return result;\n    }\n#   define AO_HAVE_double_load_acquire\n# endif\n\n# if !defined(AO_HAVE_double_store) && !defined(AO_SKIPATOMIC_double_store)\n    AO_INLINE void\n    AO_double_store(volatile AO_double_t *addr, AO_double_t value)\n    {\n      __atomic_store_n(&addr->AO_whole, value.AO_whole, __ATOMIC_RELAXED);\n    }\n#   define AO_HAVE_double_store\n# endif\n\n# if !defined(AO_HAVE_double_store_release) \\\n     && !defined(AO_SKIPATOMIC_double_store_release)\n    AO_INLINE void\n    AO_double_store_release(volatile AO_double_t *addr, AO_double_t value)\n    {\n      __atomic_store_n(&addr->AO_whole, value.AO_whole, __ATOMIC_RELEASE);\n    }\n#   define AO_HAVE_double_store_release\n# endif\n\n#endif /* !AO_GCC_HAVE_double_SYNC_CAS || !AO_PREFER_GENERALIZED */\n\n#endif /* AO_HAVE_DOUBLE_PTR_STORAGE */\n\n#ifdef AO_GCC_HAVE_double_SYNC_CAS\n# ifndef AO_HAVE_double_compare_and_swap\n    AO_INLINE int\n    AO_double_compare_and_swap(volatile AO_double_t *addr,\n                               AO_double_t old_val, AO_double_t new_val)\n    {\n      return (int)__atomic_compare_exchange_n(&addr->AO_whole,\n                                &old_val.AO_whole /* p_expected */,\n                                new_val.AO_whole /* desired */,\n                                0 /* is_weak: false */,\n                                __ATOMIC_RELAXED /* success */,\n                                __ATOMIC_RELAXED /* failure */);\n    }\n#   define AO_HAVE_double_compare_and_swap\n# endif\n\n# ifndef AO_HAVE_double_compare_and_swap_acquire\n    AO_INLINE int\n    AO_double_compare_and_swap_acquire(volatile AO_double_t *addr,\n                                       AO_double_t old_val,\n                                       AO_double_t new_val)\n    {\n      return (int)__atomic_compare_exchange_n(&addr->AO_whole,\n                                &old_val.AO_whole, new_val.AO_whole, 0,\n                                __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);\n    }\n#   define AO_HAVE_double_compare_and_swap_acquire\n# endif\n\n# ifndef AO_HAVE_double_compare_and_swap_release\n    AO_INLINE int\n    AO_double_compare_and_swap_release(volatile AO_double_t *addr,\n                                       AO_double_t old_val,\n                                       AO_double_t new_val)\n    {\n      return (int)__atomic_compare_exchange_n(&addr->AO_whole,\n                                &old_val.AO_whole, new_val.AO_whole, 0,\n                                __ATOMIC_RELEASE,\n                                __ATOMIC_RELAXED /* failure */);\n    }\n#   define AO_HAVE_double_compare_and_swap_release\n# endif\n\n# ifndef AO_HAVE_double_compare_and_swap_full\n    AO_INLINE int\n    AO_double_compare_and_swap_full(volatile AO_double_t *addr,\n                                    AO_double_t old_val, AO_double_t new_val)\n    {\n      return (int)__atomic_compare_exchange_n(&addr->AO_whole,\n                                &old_val.AO_whole, new_val.AO_whole, 0,\n                                __ATOMIC_ACQ_REL,\n                                __ATOMIC_ACQUIRE /* failure */);\n    }\n#   define AO_HAVE_double_compare_and_swap_full\n# endif\n#endif /* AO_GCC_HAVE_double_SYNC_CAS */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/hexagon.h",
    "content": "/*\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n#if AO_CLANG_PREREQ(3, 9) && !defined(AO_DISABLE_GCC_ATOMICS)\n  /* Probably, it could be enabled for earlier clang versions as well.  */\n\n  /* As of clang-3.9, __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n are missing.   */\n# define AO_GCC_FORCE_HAVE_CAS\n\n# define AO_GCC_HAVE_double_SYNC_CAS\n# include \"../standard_ao_double_t.h\"\n\n# include \"generic.h\"\n\n#else /* AO_DISABLE_GCC_ATOMICS */\n\n#include \"../all_aligned_atomic_load_store.h\"\n\n#include \"../test_and_set_t_is_ao_t.h\"\n\n/* There's also \"isync\" and \"barrier\"; however, for all current CPU     */\n/* versions, \"syncht\" should suffice.  Likewise, it seems that the      */\n/* auto-defined versions of *_acquire, *_release or *_full suffice for  */\n/* all current ISA implementations.                                     */\nAO_INLINE void\nAO_nop_full(void)\n{\n  __asm__ __volatile__(\"syncht\" : : : \"memory\");\n}\n#define AO_HAVE_nop_full\n\n/* The Hexagon has load-locked, store-conditional primitives, and so    */\n/* resulting code is very nearly identical to that of PowerPC.          */\n\n#ifndef AO_PREFER_GENERALIZED\nAO_INLINE AO_t\nAO_fetch_and_add(volatile AO_t *addr, AO_t incr)\n{\n  AO_t oldval;\n  AO_t newval;\n  __asm__ __volatile__(\n     \"1:\\n\"\n     \"  %0 = memw_locked(%3);\\n\"        /* load and reserve             */\n     \"  %1 = add (%0,%4);\\n\"            /* increment                    */\n     \"  memw_locked(%3,p1) = %1;\\n\"     /* store conditional            */\n     \"  if (!p1) jump 1b;\\n\"            /* retry if lost reservation    */\n     : \"=&r\"(oldval), \"=&r\"(newval), \"+m\"(*addr)\n     : \"r\"(addr), \"r\"(incr)\n     : \"memory\", \"p1\");\n  return oldval;\n}\n#define AO_HAVE_fetch_and_add\n\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set(volatile AO_TS_t *addr)\n{\n  int oldval;\n  int locked_value = 1;\n\n  __asm__ __volatile__(\n     \"1:\\n\"\n     \"  %0 = memw_locked(%2);\\n\"        /* load and reserve             */\n     \"  {\\n\"\n     \"    p2 = cmp.eq(%0,#0);\\n\"        /* if load is not zero,         */\n     \"    if (!p2.new) jump:nt 2f;\\n\"   /* we are done                  */\n     \"  }\\n\"\n     \"  memw_locked(%2,p1) = %3;\\n\"     /* else store conditional       */\n     \"  if (!p1) jump 1b;\\n\"            /* retry if lost reservation    */\n     \"2:\\n\"                             /* oldval is zero if we set     */\n     : \"=&r\"(oldval), \"+m\"(*addr)\n     : \"r\"(addr), \"r\"(locked_value)\n     : \"memory\", \"p1\", \"p2\");\n  return (AO_TS_VAL_t)oldval;\n}\n#define AO_HAVE_test_and_set\n#endif /* !AO_PREFER_GENERALIZED */\n\n#ifndef AO_GENERALIZE_ASM_BOOL_CAS\n  AO_INLINE int\n  AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val)\n  {\n    AO_t __oldval;\n    int result = 0;\n    __asm__ __volatile__(\n      \"1:\\n\"\n      \"  %0 = memw_locked(%3);\\n\"       /* load and reserve             */\n      \"  {\\n\"\n      \"    p2 = cmp.eq(%0,%4);\\n\"       /* if load is not equal to      */\n      \"    if (!p2.new) jump:nt 2f;\\n\"  /* old, fail                    */\n      \"  }\\n\"\n      \"  memw_locked(%3,p1) = %5;\\n\"    /* else store conditional       */\n      \"  if (!p1) jump 1b;\\n\"           /* retry if lost reservation    */\n      \"  %1 = #1\\n\"                     /* success, result = 1          */\n      \"2:\\n\"\n      : \"=&r\" (__oldval), \"+r\" (result), \"+m\"(*addr)\n      : \"r\" (addr), \"r\" (old), \"r\" (new_val)\n      : \"p1\", \"p2\", \"memory\"\n    );\n    return result;\n  }\n# define AO_HAVE_compare_and_swap\n#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val)\n{\n  AO_t __oldval;\n\n  __asm__ __volatile__(\n     \"1:\\n\"\n     \"  %0 = memw_locked(%2);\\n\"        /* load and reserve             */\n     \"  {\\n\"\n     \"    p2 = cmp.eq(%0,%3);\\n\"        /* if load is not equal to      */\n     \"    if (!p2.new) jump:nt 2f;\\n\"   /* old_val, fail                */\n     \"  }\\n\"\n     \"  memw_locked(%2,p1) = %4;\\n\"     /* else store conditional       */\n     \"  if (!p1) jump 1b;\\n\"            /* retry if lost reservation    */\n     \"2:\\n\"\n     : \"=&r\" (__oldval), \"+m\"(*addr)\n     : \"r\" (addr), \"r\" (old_val), \"r\" (new_val)\n     : \"p1\", \"p2\", \"memory\"\n  );\n  return __oldval;\n}\n#define AO_HAVE_fetch_compare_and_swap\n\n#define AO_T_IS_INT\n\n#endif /* AO_DISABLE_GCC_ATOMICS */\n\n#undef AO_GCC_FORCE_HAVE_CAS\n#undef AO_GCC_HAVE_double_SYNC_CAS\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/hppa.h",
    "content": "/*\n * Copyright (c) 2003 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#include \"../all_atomic_load_store.h\"\n\n/* Some architecture set descriptions include special \"ordered\" memory  */\n/* operations.  As far as we can tell, no existing processors actually  */\n/* require those.  Nor does it appear likely that future processors     */\n/* will.                                                                */\n#include \"../ordered.h\"\n\n/* GCC will not guarantee the alignment we need, use four lock words    */\n/* and select the correctly aligned datum. See the glibc 2.3.2          */\n/* linuxthread port for the original implementation.                    */\nstruct AO_pa_clearable_loc {\n  int data[4];\n};\n\n#undef AO_TS_INITIALIZER\n#define AO_TS_t struct AO_pa_clearable_loc\n#define AO_TS_INITIALIZER { { 1, 1, 1, 1 } }\n/* Switch meaning of set and clear, since we only have an atomic clear  */\n/* instruction.                                                         */\ntypedef enum {AO_PA_TS_set = 0, AO_PA_TS_clear = 1} AO_PA_TS_val;\n#define AO_TS_VAL_t AO_PA_TS_val\n#define AO_TS_CLEAR AO_PA_TS_clear\n#define AO_TS_SET AO_PA_TS_set\n\n/* The hppa only has one atomic read and modify memory operation,       */\n/* load and clear, so hppa spinlocks must use zero to signify that      */\n/* someone is holding the lock.  The address used for the ldcw          */\n/* semaphore must be 16-byte aligned.                                   */\n#define AO_ldcw(a, ret) \\\n  __asm__ __volatile__(\"ldcw 0(%2), %0\" \\\n                       : \"=r\" (ret), \"=m\" (*(a)) : \"r\" (a))\n\n/* Because malloc only guarantees 8-byte alignment for malloc'd data,   */\n/* and GCC only guarantees 8-byte alignment for stack locals, we can't  */\n/* be assured of 16-byte alignment for atomic lock data even if we      */\n/* specify \"__attribute ((aligned(16)))\" in the type declaration.  So,  */\n/* we use a struct containing an array of four ints for the atomic lock */\n/* type and dynamically select the 16-byte aligned int from the array   */\n/* for the semaphore.                                                   */\n#define AO_PA_LDCW_ALIGNMENT 16\n#define AO_ldcw_align(addr) \\\n            ((volatile unsigned *)(((unsigned long)(addr) \\\n                                        + (AO_PA_LDCW_ALIGNMENT - 1)) \\\n                                   & ~(AO_PA_LDCW_ALIGNMENT - 1)))\n\n/* Works on PA 1.1 and PA 2.0 systems */\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set_full(volatile AO_TS_t * addr)\n{\n  volatile unsigned int ret;\n  volatile unsigned *a = AO_ldcw_align(addr);\n\n  AO_ldcw(a, ret);\n  return (AO_TS_VAL_t)ret;\n}\n#define AO_HAVE_test_and_set_full\n\nAO_INLINE void\nAO_pa_clear(volatile AO_TS_t * addr)\n{\n  volatile unsigned *a = AO_ldcw_align(addr);\n\n  AO_compiler_barrier();\n  *a = 1;\n}\n#define AO_CLEAR(addr) AO_pa_clear(addr)\n#define AO_HAVE_CLEAR\n\n#undef AO_PA_LDCW_ALIGNMENT\n#undef AO_ldcw\n#undef AO_ldcw_align\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/ia64.h",
    "content": "/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#include \"../all_atomic_load_store.h\"\n\n#include \"../all_acquire_release_volatile.h\"\n\n#include \"../test_and_set_t_is_char.h\"\n\n#ifdef _ILP32\n  /* 32-bit HP/UX code. */\n  /* This requires pointer \"swizzling\".  Pointers need to be expanded   */\n  /* to 64 bits using the addp4 instruction before use.  This makes it  */\n  /* hard to share code, but we try anyway.                             */\n# define AO_LEN \"4\"\n  /* We assume that addr always appears in argument position 1 in asm   */\n  /* code.  If it is clobbered due to swizzling, we also need it in     */\n  /* second position.  Any later arguments are referenced symbolically, */\n  /* so that we don't have to worry about their position.  This requires*/\n  /* gcc 3.1, but you shouldn't be using anything older than that on    */\n  /* IA64 anyway.                                                       */\n  /* The AO_MASK macro is a workaround for the fact that HP/UX gcc      */\n  /* appears to otherwise store 64-bit pointers in ar.ccv, i.e. it      */\n  /* doesn't appear to clear high bits in a pointer value we pass into  */\n  /* assembly code, even if it is supposedly of type AO_t.              */\n# define AO_IN_ADDR \"1\"(addr)\n# define AO_OUT_ADDR , \"=r\"(addr)\n# define AO_SWIZZLE \"addp4 %1=0,%1;;\\n\"\n# define AO_MASK(ptr) __asm__ __volatile__(\"zxt4 %1=%1\": \"=r\"(ptr) : \"0\"(ptr))\n#else\n# define AO_LEN \"8\"\n# define AO_IN_ADDR \"r\"(addr)\n# define AO_OUT_ADDR\n# define AO_SWIZZLE\n# define AO_MASK(ptr) /* empty */\n#endif /* !_ILP32 */\n\nAO_INLINE void\nAO_nop_full(void)\n{\n  __asm__ __volatile__(\"mf\" : : : \"memory\");\n}\n#define AO_HAVE_nop_full\n\n#ifndef AO_PREFER_GENERALIZED\nAO_INLINE AO_t\nAO_fetch_and_add1_acquire (volatile AO_t *addr)\n{\n  AO_t result;\n\n  __asm__ __volatile__ (AO_SWIZZLE\n                        \"fetchadd\" AO_LEN \".acq %0=[%1],1\":\n                        \"=r\" (result) AO_OUT_ADDR: AO_IN_ADDR :\"memory\");\n  return result;\n}\n#define AO_HAVE_fetch_and_add1_acquire\n\nAO_INLINE AO_t\nAO_fetch_and_add1_release (volatile AO_t *addr)\n{\n  AO_t result;\n\n  __asm__ __volatile__ (AO_SWIZZLE\n                        \"fetchadd\" AO_LEN \".rel %0=[%1],1\":\n                        \"=r\" (result) AO_OUT_ADDR: AO_IN_ADDR :\"memory\");\n  return result;\n}\n#define AO_HAVE_fetch_and_add1_release\n\nAO_INLINE AO_t\nAO_fetch_and_sub1_acquire (volatile AO_t *addr)\n{\n  AO_t result;\n\n  __asm__ __volatile__ (AO_SWIZZLE\n                        \"fetchadd\" AO_LEN \".acq %0=[%1],-1\":\n                        \"=r\" (result) AO_OUT_ADDR: AO_IN_ADDR :\"memory\");\n  return result;\n}\n#define AO_HAVE_fetch_and_sub1_acquire\n\nAO_INLINE AO_t\nAO_fetch_and_sub1_release (volatile AO_t *addr)\n{\n  AO_t result;\n\n  __asm__ __volatile__ (AO_SWIZZLE\n                        \"fetchadd\" AO_LEN \".rel %0=[%1],-1\":\n                        \"=r\" (result) AO_OUT_ADDR: AO_IN_ADDR :\"memory\");\n  return result;\n}\n#define AO_HAVE_fetch_and_sub1_release\n#endif /* !AO_PREFER_GENERALIZED */\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_acquire(volatile AO_t *addr, AO_t old, AO_t new_val)\n{\n  AO_t fetched_val;\n  AO_MASK(old);\n  __asm__ __volatile__(AO_SWIZZLE\n                       \"mov ar.ccv=%[old] ;; cmpxchg\" AO_LEN\n                       \".acq %0=[%1],%[new_val],ar.ccv\"\n                       : \"=r\"(fetched_val) AO_OUT_ADDR\n                       : AO_IN_ADDR, [new_val]\"r\"(new_val), [old]\"r\"(old)\n                       : \"memory\");\n  return fetched_val;\n}\n#define AO_HAVE_fetch_compare_and_swap_acquire\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_release(volatile AO_t *addr, AO_t old, AO_t new_val)\n{\n  AO_t fetched_val;\n  AO_MASK(old);\n  __asm__ __volatile__(AO_SWIZZLE\n                       \"mov ar.ccv=%[old] ;; cmpxchg\" AO_LEN\n                       \".rel %0=[%1],%[new_val],ar.ccv\"\n                       : \"=r\"(fetched_val) AO_OUT_ADDR\n                       : AO_IN_ADDR, [new_val]\"r\"(new_val), [old]\"r\"(old)\n                       : \"memory\");\n  return fetched_val;\n}\n#define AO_HAVE_fetch_compare_and_swap_release\n\nAO_INLINE unsigned char\nAO_char_fetch_compare_and_swap_acquire(volatile unsigned char *addr,\n                                unsigned char old, unsigned char new_val)\n{\n  unsigned char fetched_val;\n  __asm__ __volatile__(AO_SWIZZLE\n               \"mov ar.ccv=%[old] ;; cmpxchg1.acq %0=[%1],%[new_val],ar.ccv\"\n               : \"=r\"(fetched_val) AO_OUT_ADDR\n               : AO_IN_ADDR, [new_val]\"r\"(new_val), [old]\"r\"((AO_t)old)\n               : \"memory\");\n  return fetched_val;\n}\n#define AO_HAVE_char_fetch_compare_and_swap_acquire\n\nAO_INLINE unsigned char\nAO_char_fetch_compare_and_swap_release(volatile unsigned char *addr,\n                                unsigned char old, unsigned char new_val)\n{\n  unsigned char fetched_val;\n  __asm__ __volatile__(AO_SWIZZLE\n                \"mov ar.ccv=%[old] ;; cmpxchg1.rel %0=[%1],%[new_val],ar.ccv\"\n                : \"=r\"(fetched_val) AO_OUT_ADDR\n                : AO_IN_ADDR, [new_val]\"r\"(new_val), [old]\"r\"((AO_t)old)\n                : \"memory\");\n  return fetched_val;\n}\n#define AO_HAVE_char_fetch_compare_and_swap_release\n\nAO_INLINE unsigned short\nAO_short_fetch_compare_and_swap_acquire(volatile unsigned short *addr,\n                                unsigned short old, unsigned short new_val)\n{\n  unsigned short fetched_val;\n  __asm__ __volatile__(AO_SWIZZLE\n                \"mov ar.ccv=%[old] ;; cmpxchg2.acq %0=[%1],%[new_val],ar.ccv\"\n                : \"=r\"(fetched_val) AO_OUT_ADDR\n                : AO_IN_ADDR, [new_val]\"r\"(new_val), [old]\"r\"((AO_t)old)\n                : \"memory\");\n  return fetched_val;\n}\n#define AO_HAVE_short_fetch_compare_and_swap_acquire\n\nAO_INLINE unsigned short\nAO_short_fetch_compare_and_swap_release(volatile unsigned short *addr,\n                                unsigned short old, unsigned short new_val)\n{\n  unsigned short fetched_val;\n  __asm__ __volatile__(AO_SWIZZLE\n                \"mov ar.ccv=%[old] ;; cmpxchg2.rel %0=[%1],%[new_val],ar.ccv\"\n                : \"=r\"(fetched_val) AO_OUT_ADDR\n                : AO_IN_ADDR, [new_val]\"r\"(new_val), [old]\"r\"((AO_t)old)\n                : \"memory\");\n  return fetched_val;\n}\n#define AO_HAVE_short_fetch_compare_and_swap_release\n\n#ifdef _ILP32\n\n# define AO_T_IS_INT\n\n  /* TODO: Add compare_double_and_swap_double for the _ILP32 case.      */\n#else\n\n# ifndef AO_PREFER_GENERALIZED\n  AO_INLINE unsigned int\n  AO_int_fetch_and_add1_acquire(volatile unsigned int *addr)\n  {\n    unsigned int result;\n    __asm__ __volatile__(\"fetchadd4.acq %0=[%1],1\"\n                         : \"=r\" (result) : AO_IN_ADDR\n                         : \"memory\");\n    return result;\n  }\n# define AO_HAVE_int_fetch_and_add1_acquire\n\n  AO_INLINE unsigned int\n  AO_int_fetch_and_add1_release(volatile unsigned int *addr)\n  {\n    unsigned int result;\n    __asm__ __volatile__(\"fetchadd4.rel %0=[%1],1\"\n                         : \"=r\" (result) : AO_IN_ADDR\n                         : \"memory\");\n    return result;\n  }\n# define AO_HAVE_int_fetch_and_add1_release\n\n  AO_INLINE unsigned int\n  AO_int_fetch_and_sub1_acquire(volatile unsigned int *addr)\n  {\n    unsigned int result;\n    __asm__ __volatile__(\"fetchadd4.acq %0=[%1],-1\"\n                         : \"=r\" (result) : AO_IN_ADDR\n                         : \"memory\");\n    return result;\n  }\n# define AO_HAVE_int_fetch_and_sub1_acquire\n\n  AO_INLINE unsigned int\n  AO_int_fetch_and_sub1_release(volatile unsigned int *addr)\n  {\n    unsigned int result;\n    __asm__ __volatile__(\"fetchadd4.rel %0=[%1],-1\"\n                         : \"=r\" (result) : AO_IN_ADDR\n                         : \"memory\");\n    return result;\n  }\n# define AO_HAVE_int_fetch_and_sub1_release\n# endif /* !AO_PREFER_GENERALIZED */\n\n  AO_INLINE unsigned int\n  AO_int_fetch_compare_and_swap_acquire(volatile unsigned int *addr,\n                                        unsigned int old, unsigned int new_val)\n  {\n    unsigned int fetched_val;\n    __asm__ __volatile__(\"mov ar.ccv=%3 ;; cmpxchg4.acq %0=[%1],%2,ar.ccv\"\n                         : \"=r\"(fetched_val)\n                         : AO_IN_ADDR, \"r\"(new_val), \"r\"((AO_t)old)\n                         : \"memory\");\n    return fetched_val;\n  }\n# define AO_HAVE_int_fetch_compare_and_swap_acquire\n\n  AO_INLINE unsigned int\n  AO_int_fetch_compare_and_swap_release(volatile unsigned int *addr,\n                                        unsigned int old, unsigned int new_val)\n  {\n    unsigned int fetched_val;\n    __asm__ __volatile__(\"mov ar.ccv=%3 ;; cmpxchg4.rel %0=[%1],%2,ar.ccv\"\n                         : \"=r\"(fetched_val)\n                         : AO_IN_ADDR, \"r\"(new_val), \"r\"((AO_t)old)\n                         : \"memory\");\n    return fetched_val;\n  }\n# define AO_HAVE_int_fetch_compare_and_swap_release\n#endif /* !_ILP32 */\n\n/* TODO: Add compare_and_swap_double as soon as there is widely         */\n/* available hardware that implements it.                               */\n\n#undef AO_IN_ADDR\n#undef AO_LEN\n#undef AO_MASK\n#undef AO_OUT_ADDR\n#undef AO_SWIZZLE\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/m68k.h",
    "content": "/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n/* The cas instruction causes an emulation trap for the */\n/* 060 with a misaligned pointer, so let's avoid this.  */\n#undef AO_t\ntypedef unsigned long AO_t __attribute__((__aligned__(4)));\n\n/* FIXME.  Very incomplete.  */\n#include \"../all_aligned_atomic_load_store.h\"\n\n/* Are there any m68k multiprocessors still around?     */\n/* AFAIK, Alliants were sequentially consistent.        */\n#include \"../ordered.h\"\n\n#include \"../test_and_set_t_is_char.h\"\n\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set_full(volatile AO_TS_t *addr) {\n  AO_TS_t oldval;\n\n  /* The value at addr is semi-phony.   */\n  /* 'tas' sets bit 7 while the return  */\n  /* value pretends all bits were set,  */\n  /* which at least matches AO_TS_SET.  */\n  __asm__ __volatile__(\n                \"tas %1; sne %0\"\n                : \"=d\" (oldval), \"=m\" (*addr)\n                : \"m\" (*addr)\n                : \"memory\");\n  /* This cast works due to the above.  */\n  return (AO_TS_VAL_t)oldval;\n}\n#define AO_HAVE_test_and_set_full\n\n/* Returns nonzero if the comparison succeeded. */\nAO_INLINE int\nAO_compare_and_swap_full(volatile AO_t *addr,\n                         AO_t old, AO_t new_val)\n{\n  char result;\n\n  __asm__ __volatile__(\n                \"cas.l %3,%4,%1; seq %0\"\n                : \"=d\" (result), \"=m\" (*addr)\n                : \"m\" (*addr), \"d\" (old), \"d\" (new_val)\n                : \"memory\");\n  return -result;\n}\n#define AO_HAVE_compare_and_swap_full\n\n/* TODO: implement AO_fetch_compare_and_swap.   */\n\n#define AO_T_IS_INT\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/mips.h",
    "content": "/*\n * Copyright (c) 2005,2007  Thiemo Seufer <ths@networkno.de>\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * FIXME:  This should probably make finer distinctions.  SGI MIPS is\n * much more strongly ordered, and in fact closer to sequentially\n * consistent.  This is really aimed at modern embedded implementations.\n */\n\n/* Data dependence does not imply read ordering.  */\n#define AO_NO_DD_ORDERING\n\n/* #include \"../standard_ao_double_t.h\" */\n/* TODO: Implement double-wide operations if available. */\n\n#if (AO_GNUC_PREREQ(4, 9) || AO_CLANG_PREREQ(3, 5)) \\\n    && !defined(AO_DISABLE_GCC_ATOMICS)\n  /* Probably, it could be enabled even for earlier gcc/clang versions. */\n\n  /* As of clang-3.6/mips[64], __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n missing. */\n# if defined(__clang__)\n#   define AO_GCC_FORCE_HAVE_CAS\n# endif\n\n# include \"generic.h\"\n\n#else /* AO_DISABLE_GCC_ATOMICS */\n\n# include \"../test_and_set_t_is_ao_t.h\"\n# include \"../all_aligned_atomic_load_store.h\"\n\n# if !defined(_ABI64) || _MIPS_SIM != _ABI64\n#   define AO_T_IS_INT\n#   if __mips_isa_rev >= 6\n      /* Encoding of ll/sc in mips rel6 differs from that of mips2/3. */\n#     define AO_MIPS_SET_ISA  \"\"\n#   else\n#     define AO_MIPS_SET_ISA  \"       .set mips2\\n\"\n#   endif\n#   define AO_MIPS_LL_1(args) \"       ll \" args \"\\n\"\n#   define AO_MIPS_SC(args)   \"       sc \" args \"\\n\"\n# else\n#   if __mips_isa_rev >= 6\n#     define AO_MIPS_SET_ISA  \"\"\n#   else\n#     define AO_MIPS_SET_ISA  \"       .set mips3\\n\"\n#   endif\n#   define AO_MIPS_LL_1(args) \"       lld \" args \"\\n\"\n#   define AO_MIPS_SC(args)   \"       scd \" args \"\\n\"\n# endif /* _MIPS_SIM == _ABI64 */\n\n#ifdef AO_ICE9A1_LLSC_WAR\n  /* ICE9 rev A1 chip (used in very few systems) is reported to */\n  /* have a low-frequency bug that causes LL to fail.           */\n  /* To workaround, just issue the second 'LL'.                 */\n# define AO_MIPS_LL(args) AO_MIPS_LL_1(args) AO_MIPS_LL_1(args)\n#else\n# define AO_MIPS_LL(args) AO_MIPS_LL_1(args)\n#endif\n\nAO_INLINE void\nAO_nop_full(void)\n{\n  __asm__ __volatile__(\n      \"       .set push\\n\"\n      AO_MIPS_SET_ISA\n      \"       .set noreorder\\n\"\n      \"       .set nomacro\\n\"\n      \"       sync\\n\"\n      \"       .set pop\"\n      : : : \"memory\");\n}\n#define AO_HAVE_nop_full\n\n#ifndef AO_PREFER_GENERALIZED\nAO_INLINE AO_t\nAO_fetch_and_add(volatile AO_t *addr, AO_t incr)\n{\n  register int result;\n  register int temp;\n\n  __asm__ __volatile__(\n      \"       .set push\\n\"\n      AO_MIPS_SET_ISA\n      \"       .set noreorder\\n\"\n      \"       .set nomacro\\n\"\n      \"1: \"\n      AO_MIPS_LL(\"%0, %2\")\n      \"       addu %1, %0, %3\\n\"\n      AO_MIPS_SC(\"%1, %2\")\n      \"       beqz %1, 1b\\n\"\n      \"       nop\\n\"\n      \"       .set pop\"\n      : \"=&r\" (result), \"=&r\" (temp), \"+m\" (*addr)\n      : \"Ir\" (incr)\n      : \"memory\");\n  return (AO_t)result;\n}\n#define AO_HAVE_fetch_and_add\n\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set(volatile AO_TS_t *addr)\n{\n  register int oldval;\n  register int temp;\n\n  __asm__ __volatile__(\n      \"       .set push\\n\"\n      AO_MIPS_SET_ISA\n      \"       .set noreorder\\n\"\n      \"       .set nomacro\\n\"\n      \"1: \"\n      AO_MIPS_LL(\"%0, %2\")\n      \"       move %1, %3\\n\"\n      AO_MIPS_SC(\"%1, %2\")\n      \"       beqz %1, 1b\\n\"\n      \"       nop\\n\"\n      \"       .set pop\"\n      : \"=&r\" (oldval), \"=&r\" (temp), \"+m\" (*addr)\n      : \"r\" (1)\n      : \"memory\");\n  return (AO_TS_VAL_t)oldval;\n}\n#define AO_HAVE_test_and_set\n\n  /* TODO: Implement AO_and/or/xor primitives directly. */\n#endif /* !AO_PREFER_GENERALIZED */\n\n#ifndef AO_GENERALIZE_ASM_BOOL_CAS\n  AO_INLINE int\n  AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val)\n  {\n    register int was_equal = 0;\n    register int temp;\n\n    __asm__ __volatile__(\n        \"       .set push\\n\"\n        AO_MIPS_SET_ISA\n        \"       .set noreorder\\n\"\n        \"       .set nomacro\\n\"\n        \"1: \"\n        AO_MIPS_LL(\"%0, %1\")\n        \"       bne     %0, %4, 2f\\n\"\n        \"       move    %0, %3\\n\"\n        AO_MIPS_SC(\"%0, %1\")\n        \"       .set pop\\n\"\n        \"       beqz    %0, 1b\\n\"\n        \"       li      %2, 1\\n\"\n        \"2:\"\n        : \"=&r\" (temp), \"+m\" (*addr), \"+r\" (was_equal)\n        : \"r\" (new_val), \"r\" (old)\n        : \"memory\");\n    return was_equal;\n  }\n# define AO_HAVE_compare_and_swap\n#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val)\n{\n  register int fetched_val;\n  register int temp;\n\n  __asm__ __volatile__(\n      \"       .set push\\n\"\n      AO_MIPS_SET_ISA\n      \"       .set noreorder\\n\"\n      \"       .set nomacro\\n\"\n      \"1: \"\n      AO_MIPS_LL(\"%0, %2\")\n      \"       bne  %0, %4, 2f\\n\"\n      \"       move %1, %3\\n\"\n      AO_MIPS_SC(\"%1, %2\")\n      \"       beqz %1, 1b\\n\"\n      \"       nop\\n\"\n      \"       .set pop\\n\"\n      \"2:\"\n      : \"=&r\" (fetched_val), \"=&r\" (temp), \"+m\" (*addr)\n      : \"r\" (new_val), \"Jr\" (old)\n      : \"memory\");\n  return (AO_t)fetched_val;\n}\n#define AO_HAVE_fetch_compare_and_swap\n\n#endif /* AO_DISABLE_GCC_ATOMICS */\n\n/* CAS primitives with acquire, release and full semantics are  */\n/* generated automatically (and AO_int_... primitives are       */\n/* defined properly after the first generalization pass).       */\n\n#undef AO_GCC_FORCE_HAVE_CAS\n#undef AO_MIPS_LL\n#undef AO_MIPS_LL_1\n#undef AO_MIPS_SC\n#undef AO_MIPS_SET_ISA\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/powerpc.h",
    "content": "/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n/* Memory model documented at http://www-106.ibm.com/developerworks/    */\n/* eserver/articles/archguide.html and (clearer)                        */\n/* http://www-106.ibm.com/developerworks/eserver/articles/powerpc.html. */\n/* There appears to be no implicit ordering between any kind of         */\n/* independent memory references.                                       */\n\n/* TODO: Implement double-wide operations if available. */\n\n#if (AO_GNUC_PREREQ(4, 8) || AO_CLANG_PREREQ(3, 8)) \\\n    && !defined(AO_DISABLE_GCC_ATOMICS)\n  /* Probably, it could be enabled even for earlier gcc/clang versions. */\n\n  /* TODO: As of clang-3.8.1, it emits lwsync in AO_load_acquire        */\n  /* (i.e., the code is less efficient than the one given below).       */\n\n# include \"generic.h\"\n\n#else /* AO_DISABLE_GCC_ATOMICS */\n\n/* Architecture enforces some ordering based on control dependence.     */\n/* I don't know if that could help.                                     */\n/* Data-dependent loads are always ordered.                             */\n/* Based on the above references, eieio is intended for use on          */\n/* uncached memory, which we don't support.  It does not order loads    */\n/* from cached memory.                                                  */\n\n#include \"../all_aligned_atomic_load_store.h\"\n\n#include \"../test_and_set_t_is_ao_t.h\"\n        /* There seems to be no byte equivalent of lwarx, so this       */\n        /* may really be what we want, at least in the 32-bit case.     */\n\nAO_INLINE void\nAO_nop_full(void)\n{\n  __asm__ __volatile__(\"sync\" : : : \"memory\");\n}\n#define AO_HAVE_nop_full\n\n/* lwsync apparently works for everything but a StoreLoad barrier.      */\nAO_INLINE void\nAO_lwsync(void)\n{\n#ifdef __NO_LWSYNC__\n  __asm__ __volatile__(\"sync\" : : : \"memory\");\n#else\n  __asm__ __volatile__(\"lwsync\" : : : \"memory\");\n#endif\n}\n\n#define AO_nop_write() AO_lwsync()\n#define AO_HAVE_nop_write\n\n#define AO_nop_read() AO_lwsync()\n#define AO_HAVE_nop_read\n\n#if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__)\n  /* ppc64 uses ld not lwz */\n# define AO_PPC_LD      \"ld\"\n# define AO_PPC_LxARX   \"ldarx\"\n# define AO_PPC_CMPx    \"cmpd\"\n# define AO_PPC_STxCXd  \"stdcx.\"\n# define AO_PPC_LOAD_CLOBBER \"cr0\"\n#else\n# define AO_PPC_LD      \"lwz\"\n# define AO_PPC_LxARX   \"lwarx\"\n# define AO_PPC_CMPx    \"cmpw\"\n# define AO_PPC_STxCXd  \"stwcx.\"\n# define AO_PPC_LOAD_CLOBBER \"cc\"\n        /* FIXME: We should get gcc to allocate one of the condition    */\n        /* registers.  I always got \"impossible constraint\" when I      */\n        /* tried the \"y\" constraint.                                    */\n# define AO_T_IS_INT\n#endif\n\n#ifdef _AIX\n  /* Labels are not supported on AIX.                   */\n  /* ppc64 has same size of instructions as 32-bit one. */\n# define AO_PPC_L(label) /* empty */\n# define AO_PPC_BR_A(labelBF, addr) addr\n#else\n# define AO_PPC_L(label) label \": \"\n# define AO_PPC_BR_A(labelBF, addr) labelBF\n#endif\n\n/* We explicitly specify load_acquire, since it is important, and can   */\n/* be implemented relatively cheaply.  It could be implemented          */\n/* with an ordinary load followed by a lwsync.  But the general wisdom  */\n/* seems to be that a data dependent branch followed by an isync is     */\n/* cheaper.  And the documentation is fairly explicit that this also    */\n/* has acquire semantics.                                               */\nAO_INLINE AO_t\nAO_load_acquire(const volatile AO_t *addr)\n{\n  AO_t result;\n\n  __asm__ __volatile__ (\n    AO_PPC_LD \"%U1%X1 %0,%1\\n\"\n    \"cmpw %0,%0\\n\"\n    \"bne- \" AO_PPC_BR_A(\"1f\", \"$+4\") \"\\n\"\n    AO_PPC_L(\"1\") \"isync\\n\"\n    : \"=r\" (result)\n    : \"m\"(*addr) : \"memory\", AO_PPC_LOAD_CLOBBER);\n  return result;\n}\n#define AO_HAVE_load_acquire\n\n/* We explicitly specify store_release, since it relies         */\n/* on the fact that lwsync is also a LoadStore barrier.         */\nAO_INLINE void\nAO_store_release(volatile AO_t *addr, AO_t value)\n{\n  AO_lwsync();\n  *addr = value;\n}\n#define AO_HAVE_store_release\n\n#ifndef AO_PREFER_GENERALIZED\n/* This is similar to the code in the garbage collector.  Deleting      */\n/* this and having it synthesized from compare_and_swap would probably  */\n/* only cost us a load immediate instruction.                           */\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set(volatile AO_TS_t *addr) {\n  /* TODO: And we should be using smaller objects anyway.       */\n  AO_t oldval;\n  AO_t temp = 1; /* locked value */\n\n  __asm__ __volatile__(\n               AO_PPC_L(\"1\") AO_PPC_LxARX \" %0,0,%1\\n\"\n                                                /* load and reserve     */\n               AO_PPC_CMPx \"i %0, 0\\n\"          /* if load is           */\n               \"bne \" AO_PPC_BR_A(\"2f\", \"$+12\") \"\\n\"\n                                    /* non-zero, return already set     */\n               AO_PPC_STxCXd \" %2,0,%1\\n\"   /* else store conditional   */\n               \"bne- \" AO_PPC_BR_A(\"1b\", \"$-16\") \"\\n\"\n                                    /* retry if lost reservation        */\n               AO_PPC_L(\"2\") \"\\n\"   /* oldval is zero if we set         */\n              : \"=&r\"(oldval)\n              : \"r\"(addr), \"r\"(temp)\n              : \"memory\", \"cr0\");\n  return (AO_TS_VAL_t)oldval;\n}\n#define AO_HAVE_test_and_set\n\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set_acquire(volatile AO_TS_t *addr) {\n  AO_TS_VAL_t result = AO_test_and_set(addr);\n  AO_lwsync();\n  return result;\n}\n#define AO_HAVE_test_and_set_acquire\n\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set_release(volatile AO_TS_t *addr) {\n  AO_lwsync();\n  return AO_test_and_set(addr);\n}\n#define AO_HAVE_test_and_set_release\n\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set_full(volatile AO_TS_t *addr) {\n  AO_TS_VAL_t result;\n  AO_lwsync();\n  result = AO_test_and_set(addr);\n  AO_lwsync();\n  return result;\n}\n#define AO_HAVE_test_and_set_full\n#endif /* !AO_PREFER_GENERALIZED */\n\n#ifndef AO_GENERALIZE_ASM_BOOL_CAS\n\n  AO_INLINE int\n  AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val)\n  {\n    AO_t oldval;\n    int result = 0;\n\n    __asm__ __volatile__(\n        AO_PPC_L(\"1\") AO_PPC_LxARX \" %0,0,%2\\n\" /* load and reserve */\n        AO_PPC_CMPx \" %0, %4\\n\" /* if load is not equal to      */\n        \"bne \" AO_PPC_BR_A(\"2f\", \"$+16\") \"\\n\"   /*   old, fail  */\n        AO_PPC_STxCXd \" %3,0,%2\\n\"  /* else store conditional   */\n        \"bne- \" AO_PPC_BR_A(\"1b\", \"$-16\") \"\\n\"\n                                /* retry if lost reservation    */\n        \"li %1,1\\n\"             /* result = 1;                  */\n        AO_PPC_L(\"2\") \"\\n\"\n        : \"=&r\"(oldval), \"=&r\"(result)\n        : \"r\"(addr), \"r\"(new_val), \"r\"(old), \"1\"(result)\n        : \"memory\", \"cr0\");\n    return result;\n  }\n# define AO_HAVE_compare_and_swap\n\n  AO_INLINE int\n  AO_compare_and_swap_acquire(volatile AO_t *addr, AO_t old, AO_t new_val)\n  {\n    int result = AO_compare_and_swap(addr, old, new_val);\n    AO_lwsync();\n    return result;\n  }\n# define AO_HAVE_compare_and_swap_acquire\n\n  AO_INLINE int\n  AO_compare_and_swap_release(volatile AO_t *addr, AO_t old, AO_t new_val)\n  {\n    AO_lwsync();\n    return AO_compare_and_swap(addr, old, new_val);\n  }\n# define AO_HAVE_compare_and_swap_release\n\n  AO_INLINE int\n  AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val)\n  {\n    int result;\n    AO_lwsync();\n    result = AO_compare_and_swap(addr, old, new_val);\n    if (result)\n      AO_lwsync();\n    return result;\n  }\n# define AO_HAVE_compare_and_swap_full\n\n#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val)\n{\n  AO_t fetched_val;\n\n  __asm__ __volatile__(\n      AO_PPC_L(\"1\") AO_PPC_LxARX \" %0,0,%1\\n\" /* load and reserve */\n      AO_PPC_CMPx \" %0, %3\\n\"   /* if load is not equal to      */\n      \"bne \" AO_PPC_BR_A(\"2f\", \"$+12\") \"\\n\" /*   old_val, fail  */\n      AO_PPC_STxCXd \" %2,0,%1\\n\"    /* else store conditional   */\n      \"bne- \" AO_PPC_BR_A(\"1b\", \"$-16\") \"\\n\"\n                                /* retry if lost reservation    */\n      AO_PPC_L(\"2\") \"\\n\"\n      : \"=&r\"(fetched_val)\n      : \"r\"(addr), \"r\"(new_val), \"r\"(old_val)\n      : \"memory\", \"cr0\");\n  return fetched_val;\n}\n#define AO_HAVE_fetch_compare_and_swap\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val,\n                                  AO_t new_val)\n{\n  AO_t result = AO_fetch_compare_and_swap(addr, old_val, new_val);\n  AO_lwsync();\n  return result;\n}\n#define AO_HAVE_fetch_compare_and_swap_acquire\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_release(volatile AO_t *addr, AO_t old_val,\n                                  AO_t new_val)\n{\n  AO_lwsync();\n  return AO_fetch_compare_and_swap(addr, old_val, new_val);\n}\n#define AO_HAVE_fetch_compare_and_swap_release\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val,\n                               AO_t new_val)\n{\n  AO_t result;\n  AO_lwsync();\n  result = AO_fetch_compare_and_swap(addr, old_val, new_val);\n  if (result == old_val)\n    AO_lwsync();\n  return result;\n}\n#define AO_HAVE_fetch_compare_and_swap_full\n\n#ifndef AO_PREFER_GENERALIZED\nAO_INLINE AO_t\nAO_fetch_and_add(volatile AO_t *addr, AO_t incr) {\n  AO_t oldval;\n  AO_t newval;\n\n  __asm__ __volatile__(\n               AO_PPC_L(\"1\") AO_PPC_LxARX \" %0,0,%2\\n\" /* load and reserve */\n               \"add %1,%0,%3\\n\"                 /* increment            */\n               AO_PPC_STxCXd \" %1,0,%2\\n\"       /* store conditional    */\n               \"bne- \" AO_PPC_BR_A(\"1b\", \"$-12\") \"\\n\"\n                                    /* retry if lost reservation        */\n              : \"=&r\"(oldval), \"=&r\"(newval)\n              : \"r\"(addr), \"r\"(incr)\n              : \"memory\", \"cr0\");\n  return oldval;\n}\n#define AO_HAVE_fetch_and_add\n\nAO_INLINE AO_t\nAO_fetch_and_add_acquire(volatile AO_t *addr, AO_t incr) {\n  AO_t result = AO_fetch_and_add(addr, incr);\n  AO_lwsync();\n  return result;\n}\n#define AO_HAVE_fetch_and_add_acquire\n\nAO_INLINE AO_t\nAO_fetch_and_add_release(volatile AO_t *addr, AO_t incr) {\n  AO_lwsync();\n  return AO_fetch_and_add(addr, incr);\n}\n#define AO_HAVE_fetch_and_add_release\n\nAO_INLINE AO_t\nAO_fetch_and_add_full(volatile AO_t *addr, AO_t incr) {\n  AO_t result;\n  AO_lwsync();\n  result = AO_fetch_and_add(addr, incr);\n  AO_lwsync();\n  return result;\n}\n#define AO_HAVE_fetch_and_add_full\n#endif /* !AO_PREFER_GENERALIZED */\n\n#undef AO_PPC_BR_A\n#undef AO_PPC_CMPx\n#undef AO_PPC_L\n#undef AO_PPC_LD\n#undef AO_PPC_LOAD_CLOBBER\n#undef AO_PPC_LxARX\n#undef AO_PPC_STxCXd\n\n#endif /* AO_DISABLE_GCC_ATOMICS */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/riscv.h",
    "content": "/*\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n#if defined(__clang__) || defined(AO_PREFER_BUILTIN_ATOMICS)\n  /* All __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n macros are still missing.   */\n  /* The operations are lock-free even for the types smaller than word. */\n# define AO_GCC_FORCE_HAVE_CAS\n#else\n\n  /* As of gcc-7.5, CAS and arithmetic atomic operations for char and   */\n  /* short are supported by the compiler but require -latomic flag.     */\n# if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1)\n#   define AO_NO_char_ARITHM\n# endif\n# if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)\n#   define AO_NO_short_ARITHM\n# endif\n#endif /* !__clang__ */\n\n#if defined(__riscv_zacas) && __riscv_xlen == 64 && !defined(AO_NO_DOUBLE_CAS)\n  /* TODO: Support also rv32, i.e. use amocas.w.        */\n\n# define AO_SKIPATOMIC_double_load\n# define AO_SKIPATOMIC_double_load_acquire\n# define AO_SKIPATOMIC_double_store\n# define AO_SKIPATOMIC_double_store_release\n\n# include \"../standard_ao_double_t.h\"\n\n  AO_INLINE int\n  AO_double_compare_and_swap(volatile AO_double_t *addr,\n                             AO_double_t old_val, AO_double_t new_val)\n  {\n    AO_double_t expected = old_val;\n\n    __asm__ __volatile__(\"amocas.q %0, %z2, %1\"\n                         : \"+rJ\" (expected.AO_whole), \"+A\" (*addr)\n                         : \"rJ\" (new_val.AO_whole));\n    return expected.AO_whole == old_val.AO_whole;\n  }\n# define AO_HAVE_double_compare_and_swap\n\n  AO_INLINE int\n  AO_double_compare_and_swap_acquire(volatile AO_double_t *addr,\n                                     AO_double_t old_val, AO_double_t new_val)\n  {\n    AO_double_t expected = old_val;\n\n    __asm__ __volatile__(\"amocas.q.aq %0, %z2, %1\"\n                         : \"+rJ\" (expected.AO_whole), \"+A\" (*addr)\n                         : \"rJ\" (new_val.AO_whole));\n    return expected.AO_whole == old_val.AO_whole;\n  }\n# define AO_HAVE_double_compare_and_swap_acquire\n\n  AO_INLINE int\n  AO_double_compare_and_swap_release(volatile AO_double_t *addr,\n                                     AO_double_t old_val, AO_double_t new_val)\n  {\n    AO_double_t expected = old_val;\n\n    __asm__ __volatile__(\"amocas.q.rl %0, %z2, %1\"\n                         : \"+rJ\" (expected.AO_whole), \"+A\" (*addr)\n                         : \"rJ\" (new_val.AO_whole));\n    return expected.AO_whole == old_val.AO_whole;\n  }\n# define AO_HAVE_double_compare_and_swap_release\n\n  AO_INLINE int\n  AO_double_compare_and_swap_full(volatile AO_double_t *addr,\n                                  AO_double_t old_val, AO_double_t new_val)\n  {\n    AO_double_t expected = old_val;\n\n    __asm__ __volatile__(\"amocas.q.aqrl %0, %z2, %1\"\n                         : \"+rJ\" (expected.AO_whole), \"+A\" (*addr)\n                         : \"rJ\" (new_val.AO_whole));\n    return expected.AO_whole == old_val.AO_whole;\n  }\n# define AO_HAVE_double_compare_and_swap_full\n\n#endif /* __riscv_zacas */\n\n#include \"generic.h\"\n\n#undef AO_GCC_FORCE_HAVE_CAS\n#undef AO_NO_char_ARITHM\n#undef AO_NO_short_ARITHM\n#undef AO_SKIPATOMIC_double_load\n#undef AO_SKIPATOMIC_double_load_acquire\n#undef AO_SKIPATOMIC_double_store\n#undef AO_SKIPATOMIC_double_store_release\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/s390.h",
    "content": "/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#if (AO_GNUC_PREREQ(5, 4) || AO_CLANG_PREREQ(8, 0)) && defined(__s390x__) \\\n    && !defined(AO_DISABLE_GCC_ATOMICS)\n  /* Probably, it could be enabled for earlier clang/gcc versions.      */\n  /* But, e.g., clang-3.8.0 produces a backend error for AtomicFence.   */\n\n# include \"generic.h\"\n\n#else /* AO_DISABLE_GCC_ATOMICS */\n\n/* The relevant documentation appears to be at                  */\n/* http://publibz.boulder.ibm.com/epubs/pdf/dz9zr003.pdf        */\n/* around page 5-96.  Apparently:                               */\n/* - Memory references in general are atomic only for a single  */\n/*   byte.  But it appears that the most common load/store      */\n/*   instructions also guarantee atomicity for aligned          */\n/*   operands of standard types.  WE FOOLISHLY ASSUME that      */\n/*   compilers only generate those.  If that turns out to be    */\n/*   wrong, we need inline assembly code for AO_load and        */\n/*   AO_store.                                                  */\n/* - A store followed by a load is unordered since the store    */\n/*   may be delayed.  Otherwise everything is ordered.          */\n/* - There is a hardware compare-and-swap (CS) instruction.     */\n\n#include \"../all_aligned_atomic_load_store.h\"\n\n#include \"../ordered_except_wr.h\"\n\n#include \"../test_and_set_t_is_ao_t.h\"\n/* TODO: Is there a way to do byte-sized test-and-set? */\n\n/* TODO: AO_nop_full should probably be implemented directly.   */\n/* It appears that certain BCR instructions have that effect.   */\n/* Presumably they're cheaper than CS?                          */\n\n#ifndef AO_GENERALIZE_ASM_BOOL_CAS\nAO_INLINE int AO_compare_and_swap_full(volatile AO_t *addr,\n                                       AO_t old, AO_t new_val)\n{\n  int retval;\n  __asm__ __volatile__ (\n# ifndef __s390x__\n    \"     cs  %1,%2,0(%3)\\n\"\n# else\n    \"     csg %1,%2,0(%3)\\n\"\n# endif\n  \"     ipm %0\\n\"\n  \"     srl %0,28\\n\"\n  : \"=&d\" (retval), \"+d\" (old)\n  : \"d\" (new_val), \"a\" (addr)\n  : \"cc\", \"memory\");\n  return retval == 0;\n}\n#define AO_HAVE_compare_and_swap_full\n#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_full(volatile AO_t *addr,\n                               AO_t old, AO_t new_val)\n{\n  __asm__ __volatile__ (\n#   ifndef __s390x__\n      \"     cs %0,%2,%1\\n\"\n#   else\n      \"     csg %0,%2,%1\\n\"\n#   endif\n    : \"+d\" (old), \"=Q\" (*addr)\n    : \"d\" (new_val), \"m\" (*addr)\n    : \"cc\", \"memory\");\n  return old;\n}\n#define AO_HAVE_fetch_compare_and_swap_full\n\n#endif /* AO_DISABLE_GCC_ATOMICS */\n\n/* TODO: Add double-wide operations for 32-bit executables.       */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/sh.h",
    "content": "/*\n * Copyright (c) 2009 by Takashi YOSHII. All rights reserved.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n#include \"../all_atomic_load_store.h\"\n#include \"../ordered.h\"\n\n/* sh has tas.b(byte) only */\n#include \"../test_and_set_t_is_char.h\"\n\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set_full(volatile AO_TS_t *addr)\n{\n  int oldval;\n  __asm__ __volatile__(\n        \"tas.b @%1; movt %0\"\n        : \"=r\" (oldval)\n        : \"r\" (addr)\n        : \"t\", \"memory\");\n  return oldval? AO_TS_CLEAR : AO_TS_SET;\n}\n#define AO_HAVE_test_and_set_full\n\n/* TODO: Very incomplete.       */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/sparc.h",
    "content": "/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved.\n *\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n */\n\n#if (AO_GNUC_PREREQ(12, 0) || AO_CLANG_PREREQ(13, 0)) \\\n    && !defined(AO_DISABLE_GCC_ATOMICS)\n  /* Probably, it could be enabled for earlier compiler versions as well. */\n\n# include \"generic.h\"\n\n#else /* AO_DISABLE_GCC_ATOMICS */\n\n#include \"../all_atomic_load_store.h\"\n\n/* Real SPARC code uses TSO:                            */\n#include \"../ordered_except_wr.h\"\n\n/* Test_and_set location is just a byte.                */\n#include \"../test_and_set_t_is_char.h\"\n\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set_full(volatile AO_TS_t *addr) {\n   AO_TS_VAL_t oldval;\n\n   __asm__ __volatile__(\"ldstub %1,%0\"\n                        : \"=r\"(oldval), \"=m\"(*addr)\n                        : \"m\"(*addr) : \"memory\");\n   return oldval;\n}\n#define AO_HAVE_test_and_set_full\n\n#ifndef AO_NO_SPARC_V9\n\n# ifndef AO_GENERALIZE_ASM_BOOL_CAS\n/* Returns nonzero if the comparison succeeded. */\nAO_INLINE int\nAO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) {\n  __asm__ __volatile__ (\"membar #StoreLoad | #LoadLoad\\n\\t\"\n#                       if defined(__arch64__)\n                          \"casx [%1],%2,%0\\n\\t\"\n#                       else\n                          \"cas [%1],%2,%0\\n\\t\" /* 32-bit version */\n#                       endif\n                        \"membar #StoreLoad | #StoreStore\\n\\t\"\n                        : \"+r\" (new_val)\n                        : \"r\" (addr), \"r\" (old)\n                        : \"memory\");\n  return new_val == old;\n}\n#   define AO_HAVE_compare_and_swap_full\n# endif /* !AO_GENERALIZE_ASM_BOOL_CAS */\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) {\n  __asm__ __volatile__ (\"membar #StoreLoad | #LoadLoad\\n\\t\"\n#                       if defined(__arch64__)\n                          \"casx [%1],%2,%0\\n\\t\"\n#                       else\n                          \"cas [%1],%2,%0\\n\\t\" /* 32-bit version */\n#                       endif\n                        \"membar #StoreLoad | #StoreStore\\n\\t\"\n                        : \"+r\" (new_val)\n                        : \"r\" (addr), \"r\" (old)\n                        : \"memory\");\n  return new_val;\n}\n#define AO_HAVE_fetch_compare_and_swap_full\n\n#endif /* !AO_NO_SPARC_V9 */\n\n/* TODO: Extend this for SPARC v8 and v9 (V8 also has swap, V9 has CAS, */\n/* there are barriers like membar #LoadStore, CASA (32-bit) and         */\n/* CASXA (64-bit) instructions added in V9).                            */\n\n#endif /* AO_DISABLE_GCC_ATOMICS */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/tile.h",
    "content": "/*\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n#if (AO_GNUC_PREREQ(4, 8) || AO_CLANG_PREREQ(3, 4)) \\\n    && !defined(AO_DISABLE_GCC_ATOMICS)\n\n# include \"generic.h\"\n\n#else /* AO_DISABLE_GCC_ATOMICS */\n\n  /* Minimal support for tile.  */\n\n# include \"../all_atomic_load_store.h\"\n\n# include \"../test_and_set_t_is_ao_t.h\"\n\n  AO_INLINE void\n  AO_nop_full(void)\n  {\n    __sync_synchronize();\n  }\n# define AO_HAVE_nop_full\n\n  AO_INLINE AO_t\n  AO_fetch_and_add_full(volatile AO_t *p, AO_t incr)\n  {\n    return __sync_fetch_and_add(p, incr);\n  }\n# define AO_HAVE_fetch_and_add_full\n\n  AO_INLINE AO_t\n  AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val,\n                                 AO_t new_val)\n  {\n    return __sync_val_compare_and_swap(addr, old_val, new_val\n                                       /* empty protection list */);\n  }\n# define AO_HAVE_fetch_compare_and_swap_full\n\n#endif /* AO_DISABLE_GCC_ATOMICS */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/gcc/x86.h",
    "content": "/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved.\n * Copyright (c) 2008-2018 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n * Some of the machine specific code was borrowed from our GC distribution.\n */\n\n#if (AO_GNUC_PREREQ(4, 8) || AO_CLANG_PREREQ(3, 4)) \\\n    && !defined(__INTEL_COMPILER) /* TODO: test and enable icc */ \\\n    && !defined(AO_DISABLE_GCC_ATOMICS)\n# define AO_GCC_ATOMIC_TEST_AND_SET\n\n# if defined(__APPLE_CC__)\n    /* OS X 10.7 clang-425 lacks __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n     */\n    /* predefined macro (unlike e.g. OS X 10.11 clang-703).             */\n#   define AO_GCC_FORCE_HAVE_CAS\n\n#   ifdef __x86_64__\n#     if !AO_CLANG_PREREQ(9, 0) /* < Apple clang-900 */\n        /* Older Apple clang (e.g., clang-600 based on LLVM 3.5svn) had */\n        /* some bug in the double word CAS implementation for x64.      */\n#       define AO_SKIPATOMIC_double_compare_and_swap_ANY\n#     endif\n\n#   elif defined(__MACH__)\n      /* OS X 10.8 lacks __atomic_load/store symbols for arch i386      */\n      /* (even with a non-Apple clang).                                 */\n#     ifndef MAC_OS_X_VERSION_MIN_REQUIRED\n        /* Include this header just to import the version macro. */\n#       include <AvailabilityMacros.h>\n#     endif\n#     if MAC_OS_X_VERSION_MIN_REQUIRED < 1090 /* MAC_OS_X_VERSION_10_9  */\n#       define AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY\n#     endif\n#   endif /* __i386__ */\n\n# elif defined(__clang__)\n#   if !defined(__x86_64__)\n#     if !defined(AO_PREFER_BUILTIN_ATOMICS) && !defined(__CYGWIN__) \\\n         && !AO_CLANG_PREREQ(5, 0)\n        /* At least clang-3.8/i686 (from NDK r11c) required to specify  */\n        /* -latomic in case of a double-word atomic operation use.      */\n#       define AO_SKIPATOMIC_double_compare_and_swap_ANY\n#       define AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY\n#     endif /* !AO_PREFER_BUILTIN_ATOMICS */\n\n#   elif !defined(__ILP32__)\n#     if (!AO_CLANG_PREREQ(3, 5) && !defined(AO_PREFER_BUILTIN_ATOMICS)) \\\n         || (!AO_CLANG_PREREQ(4, 0) && defined(AO_ADDRESS_SANITIZER)) \\\n         || defined(AO_THREAD_SANITIZER)\n        /* clang-3.4/x64 required -latomic.  clang-3.9/x64 seems to     */\n        /* pass double-wide arguments to atomic operations incorrectly  */\n        /* in case of ASan/TSan.                                        */\n        /* TODO: As of clang-4.0, lock-free test_stack fails if TSan.   */\n#       define AO_SKIPATOMIC_double_compare_and_swap_ANY\n#       define AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY\n#     endif\n#   endif /* __x86_64__ */\n\n# elif defined(__x86_64__) && !defined(AO_PREFER_BUILTIN_ATOMICS) \\\n       && !defined(AO_THREAD_SANITIZER)\n    /* gcc/x64 (as of gcc-12.2) requires -latomic flag in case          */\n    /* of double-word atomic operations use (but not in case of TSan).  */\n    /* TODO: Revise it for the future gcc releases. */\n#   define AO_SKIPATOMIC_double_compare_and_swap_ANY\n#   define AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY\n# endif /* __x86_64__ && !__clang__ */\n\n# ifdef AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY\n#   define AO_SKIPATOMIC_double_load\n#   define AO_SKIPATOMIC_double_load_acquire\n#   define AO_SKIPATOMIC_double_store\n#   define AO_SKIPATOMIC_double_store_release\n#   undef AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY\n# endif\n\n#else /* AO_DISABLE_GCC_ATOMICS */\n\n/* The following really assume we have a 486 or better.  Unfortunately  */\n/* gcc doesn't define a suitable feature test macro based on command    */\n/* line options.                                                        */\n/* We should perhaps test dynamically.                                  */\n\n#include \"../all_aligned_atomic_load_store.h\"\n\n#include \"../test_and_set_t_is_char.h\"\n\n#if defined(__SSE2__) && !defined(AO_USE_PENTIUM4_INSTRS)\n  /* \"mfence\" is a part of SSE2 set (introduced on Intel Pentium 4).    */\n# define AO_USE_PENTIUM4_INSTRS\n#endif\n\n#if defined(AO_USE_PENTIUM4_INSTRS)\n  AO_INLINE void\n  AO_nop_full(void)\n  {\n    __asm__ __volatile__(\"mfence\" : : : \"memory\");\n  }\n# define AO_HAVE_nop_full\n\n#else\n  /* We could use the cpuid instruction.  But that seems to be slower   */\n  /* than the default implementation based on test_and_set_full.  Thus  */\n  /* we omit that bit of misinformation here.                           */\n#endif /* !AO_USE_PENTIUM4_INSTRS */\n\n/* As far as we can tell, the lfence and sfence instructions are not    */\n/* currently needed or useful for cached memory accesses.               */\n\n/* Really only works for 486 and later */\n#ifndef AO_PREFER_GENERALIZED\n  AO_INLINE AO_t\n  AO_fetch_and_add_full (volatile AO_t *p, AO_t incr)\n  {\n    AO_t result;\n\n    __asm__ __volatile__ (\"lock; xadd %0, %1\"\n                        : \"=r\" (result), \"+m\" (*p)\n                        : \"0\" (incr)\n                        : \"memory\");\n    return result;\n  }\n# define AO_HAVE_fetch_and_add_full\n#endif /* !AO_PREFER_GENERALIZED */\n\nAO_INLINE unsigned char\nAO_char_fetch_and_add_full (volatile unsigned char *p, unsigned char incr)\n{\n  unsigned char result;\n\n  __asm__ __volatile__ (\"lock; xaddb %0, %1\"\n                        : \"=q\" (result), \"+m\" (*p)\n                        : \"0\" (incr)\n                        : \"memory\");\n  return result;\n}\n#define AO_HAVE_char_fetch_and_add_full\n\nAO_INLINE unsigned short\nAO_short_fetch_and_add_full (volatile unsigned short *p, unsigned short incr)\n{\n  unsigned short result;\n\n  __asm__ __volatile__ (\"lock; xaddw %0, %1\"\n                        : \"=r\" (result), \"+m\" (*p)\n                        : \"0\" (incr)\n                        : \"memory\");\n  return result;\n}\n#define AO_HAVE_short_fetch_and_add_full\n\n#ifndef AO_PREFER_GENERALIZED\n  AO_INLINE void\n  AO_and_full (volatile AO_t *p, AO_t value)\n  {\n    __asm__ __volatile__ (\"lock; and %1, %0\"\n                        : \"+m\" (*p)\n                        : \"r\" (value)\n                        : \"memory\");\n  }\n# define AO_HAVE_and_full\n\n  AO_INLINE void\n  AO_or_full (volatile AO_t *p, AO_t value)\n  {\n    __asm__ __volatile__ (\"lock; or %1, %0\"\n                        : \"+m\" (*p)\n                        : \"r\" (value)\n                        : \"memory\");\n  }\n# define AO_HAVE_or_full\n\n  AO_INLINE void\n  AO_xor_full (volatile AO_t *p, AO_t value)\n  {\n    __asm__ __volatile__ (\"lock; xor %1, %0\"\n                        : \"+m\" (*p)\n                        : \"r\" (value)\n                        : \"memory\");\n  }\n# define AO_HAVE_xor_full\n\n  /* AO_store_full could be implemented directly using \"xchg\" but it    */\n  /* could be generalized efficiently as an ordinary store accomplished */\n  /* with AO_nop_full (\"mfence\" instruction).                           */\n\nAO_INLINE void\nAO_char_and_full (volatile unsigned char *p, unsigned char value)\n{\n  __asm__ __volatile__ (\"lock; andb %1, %0\"\n                        : \"+m\" (*p)\n                        : \"r\" (value)\n                        : \"memory\");\n}\n#define AO_HAVE_char_and_full\n\nAO_INLINE void\nAO_char_or_full (volatile unsigned char *p, unsigned char value)\n{\n  __asm__ __volatile__ (\"lock; orb %1, %0\"\n                        : \"+m\" (*p)\n                        : \"r\" (value)\n                        : \"memory\");\n}\n#define AO_HAVE_char_or_full\n\nAO_INLINE void\nAO_char_xor_full (volatile unsigned char *p, unsigned char value)\n{\n  __asm__ __volatile__ (\"lock; xorb %1, %0\"\n                        : \"+m\" (*p)\n                        : \"r\" (value)\n                        : \"memory\");\n}\n#define AO_HAVE_char_xor_full\n\nAO_INLINE void\nAO_short_and_full (volatile unsigned short *p, unsigned short value)\n{\n  __asm__ __volatile__ (\"lock; andw %1, %0\"\n                        : \"+m\" (*p)\n                        : \"r\" (value)\n                        : \"memory\");\n}\n#define AO_HAVE_short_and_full\n\nAO_INLINE void\nAO_short_or_full (volatile unsigned short *p, unsigned short value)\n{\n  __asm__ __volatile__ (\"lock; orw %1, %0\"\n                        : \"+m\" (*p)\n                        : \"r\" (value)\n                        : \"memory\");\n}\n#define AO_HAVE_short_or_full\n\nAO_INLINE void\nAO_short_xor_full (volatile unsigned short *p, unsigned short value)\n{\n  __asm__ __volatile__ (\"lock; xorw %1, %0\"\n                        : \"+m\" (*p)\n                        : \"r\" (value)\n                        : \"memory\");\n}\n#define AO_HAVE_short_xor_full\n#endif /* !AO_PREFER_GENERALIZED */\n\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set_full(volatile AO_TS_t *addr)\n{\n  unsigned char oldval;\n  /* Note: the \"xchg\" instruction does not need a \"lock\" prefix */\n  __asm__ __volatile__ (\"xchgb %0, %1\"\n                        : \"=q\" (oldval), \"+m\" (*addr)\n                        : \"0\" ((unsigned char)0xff)\n                        : \"memory\");\n  return (AO_TS_VAL_t)oldval;\n}\n#define AO_HAVE_test_and_set_full\n\n#ifndef AO_GENERALIZE_ASM_BOOL_CAS\n  /* Returns nonzero if the comparison succeeded.       */\n  AO_INLINE int\n  AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val)\n  {\n#   ifdef AO_USE_SYNC_CAS_BUILTIN\n      return (int)__sync_bool_compare_and_swap(addr, old, new_val\n                                               /* empty protection list */);\n                /* Note: an empty list of variables protected by the    */\n                /* memory barrier should mean all globally accessible   */\n                /* variables are protected.                             */\n#   else\n      char result;\n#     if defined(__GCC_ASM_FLAG_OUTPUTS__)\n        AO_t dummy;\n\n        __asm__ __volatile__ (\"lock; cmpxchg %3, %0\"\n                        : \"+m\" (*addr), \"=@ccz\" (result), \"=a\" (dummy)\n                        : \"r\" (new_val), \"a\" (old)\n                        : \"memory\");\n#     else\n        __asm__ __volatile__ (\"lock; cmpxchg %2, %0; setz %1\"\n                        : \"+m\" (*addr), \"=a\" (result)\n                        : \"r\" (new_val), \"a\" (old)\n                        : \"memory\");\n#     endif\n      return (int)result;\n#   endif\n  }\n# define AO_HAVE_compare_and_swap_full\n#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val,\n                               AO_t new_val)\n{\n# ifdef AO_USE_SYNC_CAS_BUILTIN\n    return __sync_val_compare_and_swap(addr, old_val, new_val\n                                       /* empty protection list */);\n# else\n    AO_t fetched_val;\n    __asm__ __volatile__ (\"lock; cmpxchg %3, %1\"\n                        : \"=a\" (fetched_val), \"+m\" (*addr)\n                        : \"a\" (old_val), \"r\" (new_val)\n                        : \"memory\");\n    return fetched_val;\n# endif\n}\n#define AO_HAVE_fetch_compare_and_swap_full\n\n  AO_INLINE unsigned char\n  AO_char_fetch_compare_and_swap_full(volatile unsigned char *addr,\n                                      unsigned char old_val,\n                                      unsigned char new_val)\n  {\n#   ifdef AO_USE_SYNC_CAS_BUILTIN\n      return __sync_val_compare_and_swap(addr, old_val, new_val\n                                         /* empty protection list */);\n#   else\n      unsigned char fetched_val;\n\n      __asm__ __volatile__ (\"lock; cmpxchgb %3, %1\"\n                            : \"=a\" (fetched_val), \"+m\" (*addr)\n                            : \"a\" (old_val), \"q\" (new_val)\n                            : \"memory\");\n      return fetched_val;\n#   endif\n  }\n# define AO_HAVE_char_fetch_compare_and_swap_full\n\n  AO_INLINE unsigned short\n  AO_short_fetch_compare_and_swap_full(volatile unsigned short *addr,\n                                       unsigned short old_val,\n                                       unsigned short new_val)\n  {\n#   ifdef AO_USE_SYNC_CAS_BUILTIN\n      return __sync_val_compare_and_swap(addr, old_val, new_val\n                                         /* empty protection list */);\n#   else\n      unsigned short fetched_val;\n\n      __asm__ __volatile__ (\"lock; cmpxchgw %3, %1\"\n                            : \"=a\" (fetched_val), \"+m\" (*addr)\n                            : \"a\" (old_val), \"r\" (new_val)\n                            : \"memory\");\n      return fetched_val;\n#   endif\n  }\n# define AO_HAVE_short_fetch_compare_and_swap_full\n\n# if defined(__x86_64__) && !defined(__ILP32__)\n    AO_INLINE unsigned int\n    AO_int_fetch_compare_and_swap_full(volatile unsigned int *addr,\n                                       unsigned int old_val,\n                                       unsigned int new_val)\n    {\n#     ifdef AO_USE_SYNC_CAS_BUILTIN\n        return __sync_val_compare_and_swap(addr, old_val, new_val\n                                           /* empty protection list */);\n#     else\n        unsigned int fetched_val;\n\n        __asm__ __volatile__ (\"lock; cmpxchgl %3, %1\"\n                            : \"=a\" (fetched_val), \"+m\" (*addr)\n                            : \"a\" (old_val), \"r\" (new_val)\n                            : \"memory\");\n        return fetched_val;\n#     endif\n    }\n#   define AO_HAVE_int_fetch_compare_and_swap_full\n\n#   ifndef AO_PREFER_GENERALIZED\n    AO_INLINE unsigned int\n    AO_int_fetch_and_add_full (volatile unsigned int *p, unsigned int incr)\n    {\n      unsigned int result;\n\n      __asm__ __volatile__ (\"lock; xaddl %0, %1\"\n                            : \"=r\" (result), \"+m\" (*p)\n                            : \"0\" (incr)\n                            : \"memory\");\n      return result;\n    }\n#   define AO_HAVE_int_fetch_and_add_full\n\n    AO_INLINE void\n    AO_int_and_full (volatile unsigned int *p, unsigned int value)\n    {\n      __asm__ __volatile__ (\"lock; andl %1, %0\"\n                            : \"+m\" (*p)\n                            : \"r\" (value)\n                            : \"memory\");\n    }\n#   define AO_HAVE_int_and_full\n\n    AO_INLINE void\n    AO_int_or_full (volatile unsigned int *p, unsigned int value)\n    {\n      __asm__ __volatile__ (\"lock; orl %1, %0\"\n                            : \"+m\" (*p)\n                            : \"r\" (value)\n                            : \"memory\");\n    }\n#   define AO_HAVE_int_or_full\n\n    AO_INLINE void\n    AO_int_xor_full (volatile unsigned int *p, unsigned int value)\n    {\n      __asm__ __volatile__ (\"lock; xorl %1, %0\"\n                            : \"+m\" (*p)\n                            : \"r\" (value)\n                            : \"memory\");\n    }\n#   define AO_HAVE_int_xor_full\n#   endif /* !AO_PREFER_GENERALIZED */\n\n# else\n#   define AO_T_IS_INT\n# endif /* !x86_64 || ILP32 */\n\n  /* Real X86 implementations, except for some old 32-bit WinChips,     */\n  /* appear to enforce ordering between memory operations, EXCEPT that  */\n  /* a later read can pass earlier writes, presumably due to the        */\n  /* visible presence of store buffers.                                 */\n  /* We ignore both the WinChips and the fact that the official specs   */\n  /* seem to be much weaker (and arguably too weak to be usable).       */\n# include \"../ordered_except_wr.h\"\n\n#endif /* AO_DISABLE_GCC_ATOMICS */\n\n#if defined(AO_GCC_ATOMIC_TEST_AND_SET) \\\n    && !defined(AO_SKIPATOMIC_double_compare_and_swap_ANY)\n\n# if defined(__ILP32__) || !defined(__x86_64__) /* 32-bit AO_t */ \\\n     || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) /* 64-bit AO_t */\n#   include \"../standard_ao_double_t.h\"\n# endif\n\n#elif !defined(__x86_64__) && (!defined(AO_USE_SYNC_CAS_BUILTIN) \\\n                               || defined(AO_GCC_ATOMIC_TEST_AND_SET))\n# include \"../standard_ao_double_t.h\"\n\n  /* Reading or writing a quadword aligned on a 64-bit boundary is      */\n  /* always carried out atomically on at least a Pentium according to   */\n  /* Chapter 8.1.1 of Volume 3A Part 1 of Intel processor manuals.      */\n# ifndef AO_PREFER_GENERALIZED\n#   define AO_ACCESS_double_CHECK_ALIGNED\n#   include \"../loadstore/double_atomic_load_store.h\"\n# endif\n\n  /* Returns nonzero if the comparison succeeded.       */\n  /* Really requires at least a Pentium.                */\n  AO_INLINE int\n  AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,\n                                         AO_t old_val1, AO_t old_val2,\n                                         AO_t new_val1, AO_t new_val2)\n  {\n    char result;\n#   if defined(__PIC__) && !(AO_GNUC_PREREQ(5, 1) || AO_CLANG_PREREQ(4, 0))\n      AO_t saved_ebx;\n      AO_t dummy;\n\n      /* The following applies to an ancient GCC (and, probably, it was   */\n      /* never needed for Clang):                                         */\n      /* If PIC is turned on, we cannot use ebx as it is reserved for the */\n      /* GOT pointer.  We should save and restore ebx.  The proposed      */\n      /* solution is not so efficient as the older alternatives using     */\n      /* push ebx or edi as new_val1 (w/o clobbering edi and temporary    */\n      /* local variable usage) but it is more portable (it works even if  */\n      /* ebx is not used as GOT pointer, and it works for the buggy GCC   */\n      /* releases that incorrectly evaluate memory operands offset in the */\n      /* inline assembly after push).                                     */\n#     ifdef __OPTIMIZE__\n        __asm__ __volatile__(\"mov %%ebx, %2\\n\\t\" /* save ebx */\n                             \"lea %0, %%edi\\n\\t\" /* in case addr is in ebx */\n                             \"mov %7, %%ebx\\n\\t\" /* load new_val1 */\n                             \"lock; cmpxchg8b (%%edi)\\n\\t\"\n                             \"mov %2, %%ebx\\n\\t\" /* restore ebx */\n                             \"setz %1\"\n                        : \"+m\" (*addr), \"=a\" (result),\n                          \"=m\" (saved_ebx), \"=d\" (dummy)\n                        : \"d\" (old_val2), \"a\" (old_val1),\n                          \"c\" (new_val2), \"m\" (new_val1)\n                        : \"%edi\", \"memory\");\n#     else\n        /* A less-efficient code manually preserving edi if GCC invoked */\n        /* with -O0 option (otherwise it fails while finding a register */\n        /* in class 'GENERAL_REGS').                                    */\n        AO_t saved_edi;\n        __asm__ __volatile__(\"mov %%edi, %3\\n\\t\" /* save edi */\n                             \"mov %%ebx, %2\\n\\t\" /* save ebx */\n                             \"lea %0, %%edi\\n\\t\" /* in case addr is in ebx */\n                             \"mov %8, %%ebx\\n\\t\" /* load new_val1 */\n                             \"lock; cmpxchg8b (%%edi)\\n\\t\"\n                             \"mov %2, %%ebx\\n\\t\" /* restore ebx */\n                             \"mov %3, %%edi\\n\\t\" /* restore edi */\n                             \"setz %1\"\n                        : \"+m\" (*addr), \"=a\" (result),\n                          \"=m\" (saved_ebx), \"=m\" (saved_edi), \"=d\" (dummy)\n                        : \"d\" (old_val2), \"a\" (old_val1),\n                          \"c\" (new_val2), \"m\" (new_val1)\n                        : \"memory\");\n#     endif\n#   else\n      /* For non-PIC mode, this operation could be simplified (and be   */\n      /* faster) by using ebx as new_val1.  Reuse of the PIC hard       */\n      /* register, instead of using a fixed register, is implemented    */\n      /* in Clang and GCC 5.1+, at least. (Older GCC refused to compile */\n      /* such code for PIC mode).                                       */\n#     if defined(__GCC_ASM_FLAG_OUTPUTS__)\n        __asm__ __volatile__ (\"lock; cmpxchg8b %0\"\n                        : \"+m\" (*addr), \"=@ccz\" (result),\n                          \"+d\" (old_val2), \"+a\" (old_val1)\n                        : \"c\" (new_val2), \"b\" (new_val1)\n                        : \"memory\");\n#     else\n        AO_t dummy; /* an output for clobbered edx */\n\n        __asm__ __volatile__ (\"lock; cmpxchg8b %0; setz %1\"\n                        : \"+m\" (*addr), \"=a\" (result), \"=d\" (dummy)\n                        : \"d\" (old_val2), \"a\" (old_val1),\n                          \"c\" (new_val2), \"b\" (new_val1)\n                        : \"memory\");\n#     endif\n#   endif\n    return (int) result;\n  }\n# define AO_HAVE_compare_double_and_swap_double_full\n\n#elif defined(__ILP32__) || !defined(__x86_64__)\n# include \"../standard_ao_double_t.h\"\n\n  /* Reading or writing a quadword aligned on a 64-bit boundary is      */\n  /* always carried out atomically (requires at least a Pentium).       */\n# ifndef AO_PREFER_GENERALIZED\n#   define AO_ACCESS_double_CHECK_ALIGNED\n#   include \"../loadstore/double_atomic_load_store.h\"\n# endif\n\n  /* X32 has native support for 64-bit integer operations (AO_double_t  */\n  /* is a 64-bit integer and we could use 64-bit cmpxchg).              */\n  /* This primitive is used by compare_double_and_swap_double_full.     */\n  AO_INLINE int\n  AO_double_compare_and_swap_full(volatile AO_double_t *addr,\n                                  AO_double_t old_val, AO_double_t new_val)\n  {\n    /* It is safe to use __sync CAS built-in here.      */\n    return __sync_bool_compare_and_swap(&addr->AO_whole,\n                                        old_val.AO_whole, new_val.AO_whole\n                                        /* empty protection list */);\n  }\n# define AO_HAVE_double_compare_and_swap_full\n\n#elif defined(AO_CMPXCHG16B_AVAILABLE) \\\n      || (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) \\\n          && !defined(AO_THREAD_SANITIZER))\n# include \"../standard_ao_double_t.h\"\n\n  /* The Intel and AMD Architecture Programmer Manuals state roughly    */\n  /* the following:                                                     */\n  /* - CMPXCHG16B (with a LOCK prefix) can be used to perform 16-byte   */\n  /* atomic accesses in 64-bit mode (with certain alignment             */\n  /* restrictions);                                                     */\n  /* - SSE instructions that access data larger than a quadword (like   */\n  /* MOVDQA) may be implemented using multiple memory accesses;         */\n  /* - LOCK prefix causes an invalid-opcode exception when used with    */\n  /* 128-bit media (SSE) instructions.                                  */\n  /* Thus, currently, the only way to implement lock-free double_load   */\n  /* and double_store on x86_64 is to use CMPXCHG16B (if available).    */\n\n  /* NEC LE-IT: older AMD Opterons are missing this instruction.        */\n  /* On these machines SIGILL will be thrown.                           */\n  /* Define AO_WEAK_DOUBLE_CAS_EMULATION to have an emulated (lock      */\n  /* based) version available.                                          */\n  /* HB: Changed this to not define either by default.  There are       */\n  /* enough machines and tool chains around on which cmpxchg16b         */\n  /* doesn't work.  And the emulation is unsafe by our usual rules.     */\n  /* However both are clearly useful in certain cases.                  */\n\n  AO_INLINE int\n  AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,\n                                         AO_t old_val1, AO_t old_val2,\n                                         AO_t new_val1, AO_t new_val2)\n  {\n    char result;\n\n#   if defined(__GCC_ASM_FLAG_OUTPUTS__)\n      __asm__ __volatile__(\"lock; cmpxchg16b %0\"\n                        : \"+m\" (*addr), \"=@ccz\" (result),\n                          \"+d\" (old_val2), \"+a\" (old_val1)\n                        : \"c\" (new_val2), \"b\" (new_val1)\n                        : \"memory\");\n#   else\n      AO_t dummy; /* an output for clobbered rdx */\n\n      __asm__ __volatile__(\"lock; cmpxchg16b %0; setz %1\"\n                        : \"+m\" (*addr), \"=a\" (result), \"=d\" (dummy)\n                        : \"d\" (old_val2), \"a\" (old_val1),\n                          \"c\" (new_val2), \"b\" (new_val1)\n                        : \"memory\");\n#   endif\n    return (int) result;\n  }\n# define AO_HAVE_compare_double_and_swap_double_full\n\n#elif defined(AO_WEAK_DOUBLE_CAS_EMULATION)\n# include \"../standard_ao_double_t.h\"\n\n# ifdef __cplusplus\n    extern \"C\" {\n# endif\n\n  /* This one provides spinlock based emulation of CAS implemented in   */\n  /* atomic_ops.c.  We probably do not want to do this here, since it   */\n  /* is not atomic with respect to other kinds of updates of *addr.     */\n  /* On the other hand, this may be a useful facility on occasion.      */\n  int AO_compare_double_and_swap_double_emulation(\n                                        volatile AO_double_t *addr,\n                                        AO_t old_val1, AO_t old_val2,\n                                        AO_t new_val1, AO_t new_val2);\n\n# ifdef __cplusplus\n    } /* extern \"C\" */\n# endif\n\n  AO_INLINE int\n  AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,\n                                         AO_t old_val1, AO_t old_val2,\n                                         AO_t new_val1, AO_t new_val2)\n  {\n    return AO_compare_double_and_swap_double_emulation(addr,\n                                old_val1, old_val2, new_val1, new_val2);\n  }\n# define AO_HAVE_compare_double_and_swap_double_full\n#endif /* x86_64 && !ILP32 && CAS_EMULATION && !AO_CMPXCHG16B_AVAILABLE */\n\n#ifdef AO_GCC_ATOMIC_TEST_AND_SET\n# include \"generic.h\"\n#endif\n\n#undef AO_GCC_FORCE_HAVE_CAS\n#undef AO_SKIPATOMIC_double_compare_and_swap_ANY\n#undef AO_SKIPATOMIC_double_load\n#undef AO_SKIPATOMIC_double_load_acquire\n#undef AO_SKIPATOMIC_double_store\n#undef AO_SKIPATOMIC_double_store_release\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/generic_pthread.h",
    "content": "/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* The following is useful primarily for debugging and documentation.   */\n/* We define various atomic operations by acquiring a global pthread    */\n/* lock.  The resulting implementation will perform poorly, but should  */\n/* be correct unless it is used from signal handlers.                   */\n/* We assume that all pthread operations act like full memory barriers. */\n/* (We believe that is the intent of the specification.)                */\n\n#include <pthread.h>\n\n#include \"test_and_set_t_is_ao_t.h\"\n        /* This is not necessarily compatible with the native           */\n        /* implementation.  But those can't be safely mixed anyway.     */\n\n#ifdef __cplusplus\n  extern \"C\" {\n#endif\n\n/* We define only the full barrier variants, and count on the           */\n/* generalization section below to fill in the rest.                    */\nAO_API pthread_mutex_t AO_pt_lock;\n\n#ifdef __cplusplus\n  } /* extern \"C\" */\n#endif\n\nAO_INLINE void\nAO_nop_full(void)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_nop_full\n\nAO_INLINE AO_t\nAO_load_full(const volatile AO_t *addr)\n{\n  AO_t result;\n  pthread_mutex_lock(&AO_pt_lock);\n  result = *addr;\n  pthread_mutex_unlock(&AO_pt_lock);\n  return result;\n}\n#define AO_HAVE_load_full\n\nAO_INLINE void\nAO_store_full(volatile AO_t *addr, AO_t val)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *addr = val;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_store_full\n\nAO_INLINE unsigned char\nAO_char_load_full(const volatile unsigned char *addr)\n{\n  unsigned char result;\n  pthread_mutex_lock(&AO_pt_lock);\n  result = *addr;\n  pthread_mutex_unlock(&AO_pt_lock);\n  return result;\n}\n#define AO_HAVE_char_load_full\n\nAO_INLINE void\nAO_char_store_full(volatile unsigned char *addr, unsigned char val)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *addr = val;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_char_store_full\n\nAO_INLINE unsigned short\nAO_short_load_full(const volatile unsigned short *addr)\n{\n  unsigned short result;\n  pthread_mutex_lock(&AO_pt_lock);\n  result = *addr;\n  pthread_mutex_unlock(&AO_pt_lock);\n  return result;\n}\n#define AO_HAVE_short_load_full\n\nAO_INLINE void\nAO_short_store_full(volatile unsigned short *addr, unsigned short val)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *addr = val;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_short_store_full\n\nAO_INLINE unsigned int\nAO_int_load_full(const volatile unsigned int *addr)\n{\n  unsigned int result;\n  pthread_mutex_lock(&AO_pt_lock);\n  result = *addr;\n  pthread_mutex_unlock(&AO_pt_lock);\n  return result;\n}\n#define AO_HAVE_int_load_full\n\nAO_INLINE void\nAO_int_store_full(volatile unsigned int *addr, unsigned int val)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *addr = val;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_int_store_full\n\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set_full(volatile AO_TS_t *addr)\n{\n  AO_TS_VAL_t result;\n  pthread_mutex_lock(&AO_pt_lock);\n  result = (AO_TS_VAL_t)(*addr);\n  *addr = AO_TS_SET;\n  pthread_mutex_unlock(&AO_pt_lock);\n  assert(result == AO_TS_SET || result == AO_TS_CLEAR);\n  return result;\n}\n#define AO_HAVE_test_and_set_full\n\nAO_INLINE AO_t\nAO_fetch_and_add_full(volatile AO_t *p, AO_t incr)\n{\n  AO_t old_val;\n\n  pthread_mutex_lock(&AO_pt_lock);\n  old_val = *p;\n  *p = old_val + incr;\n  pthread_mutex_unlock(&AO_pt_lock);\n  return old_val;\n}\n#define AO_HAVE_fetch_and_add_full\n\nAO_INLINE unsigned char\nAO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr)\n{\n  unsigned char old_val;\n\n  pthread_mutex_lock(&AO_pt_lock);\n  old_val = *p;\n  *p = old_val + incr;\n  pthread_mutex_unlock(&AO_pt_lock);\n  return old_val;\n}\n#define AO_HAVE_char_fetch_and_add_full\n\nAO_INLINE unsigned short\nAO_short_fetch_and_add_full(volatile unsigned short *p, unsigned short incr)\n{\n  unsigned short old_val;\n\n  pthread_mutex_lock(&AO_pt_lock);\n  old_val = *p;\n  *p = old_val + incr;\n  pthread_mutex_unlock(&AO_pt_lock);\n  return old_val;\n}\n#define AO_HAVE_short_fetch_and_add_full\n\nAO_INLINE unsigned int\nAO_int_fetch_and_add_full(volatile unsigned int *p, unsigned int incr)\n{\n  unsigned int old_val;\n\n  pthread_mutex_lock(&AO_pt_lock);\n  old_val = *p;\n  *p = old_val + incr;\n  pthread_mutex_unlock(&AO_pt_lock);\n  return old_val;\n}\n#define AO_HAVE_int_fetch_and_add_full\n\nAO_INLINE void\nAO_and_full(volatile AO_t *p, AO_t value)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *p &= value;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_and_full\n\nAO_INLINE void\nAO_or_full(volatile AO_t *p, AO_t value)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *p |= value;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_or_full\n\nAO_INLINE void\nAO_xor_full(volatile AO_t *p, AO_t value)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *p ^= value;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_xor_full\n\nAO_INLINE void\nAO_char_and_full(volatile unsigned char *p, unsigned char value)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *p &= value;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_char_and_full\n\nAO_INLINE void\nAO_char_or_full(volatile unsigned char *p, unsigned char value)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *p |= value;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_char_or_full\n\nAO_INLINE void\nAO_char_xor_full(volatile unsigned char *p, unsigned char value)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *p ^= value;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_char_xor_full\n\nAO_INLINE void\nAO_short_and_full(volatile unsigned short *p, unsigned short value)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *p &= value;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_short_and_full\n\nAO_INLINE void\nAO_short_or_full(volatile unsigned short *p, unsigned short value)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *p |= value;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_short_or_full\n\nAO_INLINE void\nAO_short_xor_full(volatile unsigned short *p, unsigned short value)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *p ^= value;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_short_xor_full\n\nAO_INLINE void\nAO_int_and_full(volatile unsigned *p, unsigned value)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *p &= value;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_int_and_full\n\nAO_INLINE void\nAO_int_or_full(volatile unsigned *p, unsigned value)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *p |= value;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_int_or_full\n\nAO_INLINE void\nAO_int_xor_full(volatile unsigned *p, unsigned value)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  *p ^= value;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_int_xor_full\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val,\n                               AO_t new_val)\n{\n  AO_t fetched_val;\n\n  pthread_mutex_lock(&AO_pt_lock);\n  fetched_val = *addr;\n  if (fetched_val == old_val)\n    *addr = new_val;\n  pthread_mutex_unlock(&AO_pt_lock);\n  return fetched_val;\n}\n#define AO_HAVE_fetch_compare_and_swap_full\n\nAO_INLINE unsigned char\nAO_char_fetch_compare_and_swap_full(volatile unsigned char *addr,\n                                    unsigned char old_val,\n                                    unsigned char new_val)\n{\n  unsigned char fetched_val;\n\n  pthread_mutex_lock(&AO_pt_lock);\n  fetched_val = *addr;\n  if (fetched_val == old_val)\n    *addr = new_val;\n  pthread_mutex_unlock(&AO_pt_lock);\n  return fetched_val;\n}\n#define AO_HAVE_char_fetch_compare_and_swap_full\n\nAO_INLINE unsigned short\nAO_short_fetch_compare_and_swap_full(volatile unsigned short *addr,\n                                     unsigned short old_val,\n                                     unsigned short new_val)\n{\n  unsigned short fetched_val;\n\n  pthread_mutex_lock(&AO_pt_lock);\n  fetched_val = *addr;\n  if (fetched_val == old_val)\n    *addr = new_val;\n  pthread_mutex_unlock(&AO_pt_lock);\n  return fetched_val;\n}\n#define AO_HAVE_short_fetch_compare_and_swap_full\n\nAO_INLINE unsigned\nAO_int_fetch_compare_and_swap_full(volatile unsigned *addr, unsigned old_val,\n                                   unsigned new_val)\n{\n  unsigned fetched_val;\n\n  pthread_mutex_lock(&AO_pt_lock);\n  fetched_val = *addr;\n  if (fetched_val == old_val)\n    *addr = new_val;\n  pthread_mutex_unlock(&AO_pt_lock);\n  return fetched_val;\n}\n#define AO_HAVE_int_fetch_compare_and_swap_full\n\n/* Unlike real architectures, we define both double-width CAS variants. */\n\ntypedef struct {\n        AO_t AO_val1;\n        AO_t AO_val2;\n} AO_double_t;\n#define AO_HAVE_double_t\n\n#define AO_DOUBLE_T_INITIALIZER { (AO_t)0, (AO_t)0 }\n\nAO_INLINE AO_double_t\nAO_double_load_full(const volatile AO_double_t *addr)\n{\n  AO_double_t result;\n\n  pthread_mutex_lock(&AO_pt_lock);\n  result.AO_val1 = addr->AO_val1;\n  result.AO_val2 = addr->AO_val2;\n  pthread_mutex_unlock(&AO_pt_lock);\n  return result;\n}\n#define AO_HAVE_double_load_full\n\nAO_INLINE void\nAO_double_store_full(volatile AO_double_t *addr, AO_double_t value)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  addr->AO_val1 = value.AO_val1;\n  addr->AO_val2 = value.AO_val2;\n  pthread_mutex_unlock(&AO_pt_lock);\n}\n#define AO_HAVE_double_store_full\n\nAO_INLINE int\nAO_compare_double_and_swap_double_full(volatile AO_double_t *addr,\n                                       AO_t old1, AO_t old2,\n                                       AO_t new1, AO_t new2)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  if (addr -> AO_val1 == old1 && addr -> AO_val2 == old2)\n    {\n      addr -> AO_val1 = new1;\n      addr -> AO_val2 = new2;\n      pthread_mutex_unlock(&AO_pt_lock);\n      return 1;\n    }\n  else\n    pthread_mutex_unlock(&AO_pt_lock);\n  return 0;\n}\n#define AO_HAVE_compare_double_and_swap_double_full\n\nAO_INLINE int\nAO_compare_and_swap_double_full(volatile AO_double_t *addr,\n                                AO_t old1, AO_t new1, AO_t new2)\n{\n  pthread_mutex_lock(&AO_pt_lock);\n  if (addr -> AO_val1 == old1)\n    {\n      addr -> AO_val1 = new1;\n      addr -> AO_val2 = new2;\n      pthread_mutex_unlock(&AO_pt_lock);\n      return 1;\n    }\n  else\n    pthread_mutex_unlock(&AO_pt_lock);\n  return 0;\n}\n#define AO_HAVE_compare_and_swap_double_full\n\n/* We can't use hardware loads and stores, since they don't     */\n/* interact correctly with atomic updates.                      */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/hpc/hppa.h",
    "content": "/*\n * Copyright (c) 2003 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n *\n * Derived from the corresponding header file for gcc.\n */\n\n#include \"../loadstore/atomic_load.h\"\n#include \"../loadstore/atomic_store.h\"\n\n/* Some architecture set descriptions include special \"ordered\" memory  */\n/* operations.  As far as we can tell, no existing processors actually  */\n/* require those.  Nor does it appear likely that future processors     */\n/* will.                                                                */\n/* FIXME: The PA emulator on Itanium may obey weaker restrictions.      */\n/* There should be a mode in which we don't assume sequential           */\n/* consistency here.                                                    */\n#include \"../ordered.h\"\n\n#include <machine/inline.h>\n\n/* GCC will not guarantee the alignment we need, use four lock words    */\n/* and select the correctly aligned datum. See the glibc 2.3.2          */\n/* linuxthread port for the original implementation.                    */\nstruct AO_pa_clearable_loc {\n  int data[4];\n};\n\n#undef AO_TS_INITIALIZER\n#define AO_TS_t struct AO_pa_clearable_loc\n#define AO_TS_INITIALIZER {1,1,1,1}\n/* Switch meaning of set and clear, since we only have an atomic clear  */\n/* instruction.                                                         */\ntypedef enum {AO_PA_TS_set = 0, AO_PA_TS_clear = 1} AO_PA_TS_val;\n#define AO_TS_VAL_t AO_PA_TS_val\n#define AO_TS_CLEAR AO_PA_TS_clear\n#define AO_TS_SET AO_PA_TS_set\n\n/* The hppa only has one atomic read and modify memory operation,       */\n/* load and clear, so hppa spinlocks must use zero to signify that      */\n/* someone is holding the lock.  The address used for the ldcw          */\n/* semaphore must be 16-byte aligned.                                   */\n#define AO_ldcw(a, ret) \\\n  _LDCWX(0 /* index */, 0 /* s */, a /* base */, ret)\n\n/* Because malloc only guarantees 8-byte alignment for malloc'd data,   */\n/* and GCC only guarantees 8-byte alignment for stack locals, we can't  */\n/* be assured of 16-byte alignment for atomic lock data even if we      */\n/* specify \"__attribute ((aligned(16)))\" in the type declaration.  So,  */\n/* we use a struct containing an array of four ints for the atomic lock */\n/* type and dynamically select the 16-byte aligned int from the array   */\n/* for the semaphore.                                                   */\n#define AO_PA_LDCW_ALIGNMENT 16\n#define AO_ldcw_align(addr) \\\n            ((volatile unsigned *)(((unsigned long)(addr) \\\n                                        + (AO_PA_LDCW_ALIGNMENT - 1)) \\\n                                   & ~(AO_PA_LDCW_ALIGNMENT - 1)))\n\n/* Works on PA 1.1 and PA 2.0 systems */\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set_full(volatile AO_TS_t * addr)\n{\n  register unsigned int ret;\n  register unsigned long a = (unsigned long)AO_ldcw_align(addr);\n\n# if defined(CPPCHECK)\n    ret = 0; /* to void 'uninitialized variable' warning */\n# endif\n  AO_ldcw(a, ret);\n  return (AO_TS_VAL_t)ret;\n}\n#define AO_HAVE_test_and_set_full\n\nAO_INLINE void\nAO_pa_clear(volatile AO_TS_t * addr)\n{\n  volatile unsigned *a = AO_ldcw_align(addr);\n\n  AO_compiler_barrier();\n  *a = 1;\n}\n#define AO_CLEAR(addr) AO_pa_clear(addr)\n#define AO_HAVE_CLEAR\n\n#undef AO_PA_LDCW_ALIGNMENT\n#undef AO_ldcw\n#undef AO_ldcw_align\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/hpc/ia64.h",
    "content": "/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/*\n * This file specifies Itanimum primitives for use with the HP compiler\n * under HP/UX.  We use intrinsics instead of the inline assembly code in the\n * gcc file.\n */\n\n#include \"../all_atomic_load_store.h\"\n\n#include \"../all_acquire_release_volatile.h\"\n\n#include \"../test_and_set_t_is_char.h\"\n\n#include <machine/sys/inline.h>\n\n#ifdef __LP64__\n# define AO_T_FASIZE _FASZ_D\n# define AO_T_SIZE _SZ_D\n#else\n# define AO_T_FASIZE _FASZ_W\n# define AO_T_SIZE _SZ_W\n#endif\n\nAO_INLINE void\nAO_nop_full(void)\n{\n  _Asm_mf();\n}\n#define AO_HAVE_nop_full\n\n#ifndef AO_PREFER_GENERALIZED\nAO_INLINE AO_t\nAO_fetch_and_add1_acquire (volatile AO_t *p)\n{\n  return _Asm_fetchadd(AO_T_FASIZE, _SEM_ACQ, p, 1,\n                       _LDHINT_NONE, _DOWN_MEM_FENCE);\n}\n#define AO_HAVE_fetch_and_add1_acquire\n\nAO_INLINE AO_t\nAO_fetch_and_add1_release (volatile AO_t *p)\n{\n  return _Asm_fetchadd(AO_T_FASIZE, _SEM_REL, p, 1,\n                       _LDHINT_NONE, _UP_MEM_FENCE);\n}\n#define AO_HAVE_fetch_and_add1_release\n\nAO_INLINE AO_t\nAO_fetch_and_sub1_acquire (volatile AO_t *p)\n{\n  return _Asm_fetchadd(AO_T_FASIZE, _SEM_ACQ, p, -1,\n                       _LDHINT_NONE, _DOWN_MEM_FENCE);\n}\n#define AO_HAVE_fetch_and_sub1_acquire\n\nAO_INLINE AO_t\nAO_fetch_and_sub1_release (volatile AO_t *p)\n{\n  return _Asm_fetchadd(AO_T_FASIZE, _SEM_REL, p, -1,\n                       _LDHINT_NONE, _UP_MEM_FENCE);\n}\n#define AO_HAVE_fetch_and_sub1_release\n#endif /* !AO_PREFER_GENERALIZED */\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val,\n                                  AO_t new_val)\n{\n  _Asm_mov_to_ar(_AREG_CCV, old_val, _DOWN_MEM_FENCE);\n  return _Asm_cmpxchg(AO_T_SIZE, _SEM_ACQ, addr,\n                      new_val, _LDHINT_NONE, _DOWN_MEM_FENCE);\n}\n#define AO_HAVE_fetch_compare_and_swap_acquire\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_release(volatile AO_t *addr, AO_t old_val,\n                                  AO_t new_val)\n{\n  _Asm_mov_to_ar(_AREG_CCV, old_val, _UP_MEM_FENCE);\n  return _Asm_cmpxchg(AO_T_SIZE, _SEM_REL, addr,\n                      new_val, _LDHINT_NONE, _UP_MEM_FENCE);\n}\n#define AO_HAVE_fetch_compare_and_swap_release\n\nAO_INLINE unsigned char\nAO_char_fetch_compare_and_swap_acquire(volatile unsigned char *addr,\n                                unsigned char old_val, unsigned char new_val)\n{\n  _Asm_mov_to_ar(_AREG_CCV, old_val, _DOWN_MEM_FENCE);\n  return _Asm_cmpxchg(_SZ_B, _SEM_ACQ, addr,\n                      new_val, _LDHINT_NONE, _DOWN_MEM_FENCE);\n}\n#define AO_HAVE_char_fetch_compare_and_swap_acquire\n\nAO_INLINE unsigned char\nAO_char_fetch_compare_and_swap_release(volatile unsigned char *addr,\n                                unsigned char old_val, unsigned char new_val)\n{\n  _Asm_mov_to_ar(_AREG_CCV, old_val, _UP_MEM_FENCE);\n  return _Asm_cmpxchg(_SZ_B, _SEM_REL, addr,\n                      new_val, _LDHINT_NONE, _UP_MEM_FENCE);\n}\n#define AO_HAVE_char_fetch_compare_and_swap_release\n\nAO_INLINE unsigned short\nAO_short_fetch_compare_and_swap_acquire(volatile unsigned short *addr,\n                                        unsigned short old_val,\n                                        unsigned short new_val)\n{\n  _Asm_mov_to_ar(_AREG_CCV, old_val, _DOWN_MEM_FENCE);\n  return _Asm_cmpxchg(_SZ_B, _SEM_ACQ, addr,\n                      new_val, _LDHINT_NONE, _DOWN_MEM_FENCE);\n}\n#define AO_HAVE_short_fetch_compare_and_swap_acquire\n\nAO_INLINE unsigned short\nAO_short_fetch_compare_and_swap_release(volatile unsigned short *addr,\n                                        unsigned short old_val,\n                                        unsigned short new_val)\n{\n  _Asm_mov_to_ar(_AREG_CCV, old_val, _UP_MEM_FENCE);\n  return _Asm_cmpxchg(_SZ_B, _SEM_REL, addr,\n                      new_val, _LDHINT_NONE, _UP_MEM_FENCE);\n}\n#define AO_HAVE_short_fetch_compare_and_swap_release\n\n#ifndef __LP64__\n# define AO_T_IS_INT\n#endif\n\n#undef AO_T_FASIZE\n#undef AO_T_SIZE\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/ibmc/powerpc.h",
    "content": "\n/* Memory model documented at http://www-106.ibm.com/developerworks/    */\n/* eserver/articles/archguide.html and (clearer)                        */\n/* http://www-106.ibm.com/developerworks/eserver/articles/powerpc.html. */\n/* There appears to be no implicit ordering between any kind of         */\n/* independent memory references.                                       */\n/* Architecture enforces some ordering based on control dependence.     */\n/* I don't know if that could help.                                     */\n/* Data-dependent loads are always ordered.                             */\n/* Based on the above references, eieio is intended for use on          */\n/* uncached memory, which we don't support.  It does not order loads    */\n/* from cached memory.                                                  */\n/* Thanks to Maged Michael, Doug Lea, and Roger Hoover for helping to   */\n/* track some of this down and correcting my misunderstandings. -HB     */\n\n#include \"../all_aligned_atomic_load_store.h\"\n\n#include \"../test_and_set_t_is_ao_t.h\"\n\nvoid AO_sync(void);\n#pragma mc_func AO_sync { \"7c0004ac\" }\n\n#ifdef __NO_LWSYNC__\n# define AO_lwsync AO_sync\n#else\n  void AO_lwsync(void);\n#pragma mc_func AO_lwsync { \"7c2004ac\" }\n#endif\n\n#define AO_nop_write() AO_lwsync()\n#define AO_HAVE_nop_write\n\n#define AO_nop_read() AO_lwsync()\n#define AO_HAVE_nop_read\n\n/* We explicitly specify load_acquire and store_release, since these    */\n/* rely on the fact that lwsync is also a LoadStore barrier.            */\nAO_INLINE AO_t\nAO_load_acquire(const volatile AO_t *addr)\n{\n  AO_t result = *addr;\n  AO_lwsync();\n  return result;\n}\n#define AO_HAVE_load_acquire\n\nAO_INLINE void\nAO_store_release(volatile AO_t *addr, AO_t value)\n{\n  AO_lwsync();\n  *addr = value;\n}\n#define AO_HAVE_store_release\n\n#ifndef AO_PREFER_GENERALIZED\n/* This is similar to the code in the garbage collector.  Deleting      */\n/* this and having it synthesized from compare_and_swap would probably  */\n/* only cost us a load immediate instruction.                           */\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set(volatile AO_TS_t *addr) {\n#if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__)\n/* Completely untested.  And we should be using smaller objects anyway. */\n  unsigned long oldval;\n  unsigned long temp = 1; /* locked value */\n\n  __asm__ __volatile__(\n               \"1:ldarx %0,0,%1\\n\"   /* load and reserve               */\n               \"cmpdi %0, 0\\n\"       /* if load is                     */\n               \"bne 2f\\n\"            /*   non-zero, return already set */\n               \"stdcx. %2,0,%1\\n\"    /* else store conditional         */\n               \"bne- 1b\\n\"           /* retry if lost reservation      */\n               \"2:\\n\"                /* oldval is zero if we set       */\n              : \"=&r\"(oldval)\n              : \"r\"(addr), \"r\"(temp)\n              : \"memory\", \"cr0\");\n#else\n  int oldval;\n  int temp = 1; /* locked value */\n\n  __asm__ __volatile__(\n               \"1:lwarx %0,0,%1\\n\"   /* load and reserve               */\n               \"cmpwi %0, 0\\n\"       /* if load is                     */\n               \"bne 2f\\n\"            /*   non-zero, return already set */\n               \"stwcx. %2,0,%1\\n\"    /* else store conditional         */\n               \"bne- 1b\\n\"           /* retry if lost reservation      */\n               \"2:\\n\"                /* oldval is zero if we set       */\n              : \"=&r\"(oldval)\n              : \"r\"(addr), \"r\"(temp)\n              : \"memory\", \"cr0\");\n#endif\n  return (AO_TS_VAL_t)oldval;\n}\n#define AO_HAVE_test_and_set\n\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set_acquire(volatile AO_TS_t *addr) {\n  AO_TS_VAL_t result = AO_test_and_set(addr);\n  AO_lwsync();\n  return result;\n}\n#define AO_HAVE_test_and_set_acquire\n\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set_release(volatile AO_TS_t *addr) {\n  AO_lwsync();\n  return AO_test_and_set(addr);\n}\n#define AO_HAVE_test_and_set_release\n\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set_full(volatile AO_TS_t *addr) {\n  AO_TS_VAL_t result;\n  AO_lwsync();\n  result = AO_test_and_set(addr);\n  AO_lwsync();\n  return result;\n}\n#define AO_HAVE_test_and_set_full\n#endif /* !AO_PREFER_GENERALIZED */\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val)\n{\n  AO_t fetched_val;\n# if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__)\n    __asm__ __volatile__(\n      \"1:ldarx %0,0,%1\\n\"       /* load and reserve             */\n      \"cmpd %0, %3\\n\"           /* if load is not equal to      */\n      \"bne 2f\\n\"                /*   old_val, fail              */\n      \"stdcx. %2,0,%1\\n\"        /* else store conditional       */\n      \"bne- 1b\\n\"               /* retry if lost reservation    */\n      \"2:\\n\"\n      : \"=&r\"(fetched_val)\n      : \"r\"(addr), \"r\"(new_val), \"r\"(old_val)\n      : \"memory\", \"cr0\");\n# else\n    __asm__ __volatile__(\n      \"1:lwarx %0,0,%1\\n\"       /* load and reserve             */\n      \"cmpw %0, %3\\n\"           /* if load is not equal to      */\n      \"bne 2f\\n\"                /*   old_val, fail              */\n      \"stwcx. %2,0,%1\\n\"        /* else store conditional       */\n      \"bne- 1b\\n\"               /* retry if lost reservation    */\n      \"2:\\n\"\n      : \"=&r\"(fetched_val)\n      : \"r\"(addr), \"r\"(new_val), \"r\"(old_val)\n      : \"memory\", \"cr0\");\n# endif\n  return fetched_val;\n}\n#define AO_HAVE_fetch_compare_and_swap\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val,\n                                  AO_t new_val)\n{\n  AO_t result = AO_fetch_compare_and_swap(addr, old_val, new_val);\n  AO_lwsync();\n  return result;\n}\n#define AO_HAVE_fetch_compare_and_swap_acquire\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_release(volatile AO_t *addr, AO_t old_val,\n                                  AO_t new_val)\n{\n  AO_lwsync();\n  return AO_fetch_compare_and_swap(addr, old_val, new_val);\n}\n#define AO_HAVE_fetch_compare_and_swap_release\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val,\n                               AO_t new_val)\n{\n  AO_t result;\n  AO_lwsync();\n  result = AO_fetch_compare_and_swap(addr, old_val, new_val);\n  AO_lwsync();\n  return result;\n}\n#define AO_HAVE_fetch_compare_and_swap_full\n\n/* TODO: Implement AO_fetch_and_add, AO_and/or/xor directly.    */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/icc/ia64.h",
    "content": "/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/*\n * This file specifies Itanimum primitives for use with the Intel (ecc)\n * compiler.  We use intrinsics instead of the inline assembly code in the\n * gcc file.\n */\n\n#include \"../all_atomic_load_store.h\"\n\n#include \"../test_and_set_t_is_char.h\"\n\n#include <ia64intrin.h>\n\n/* The acquire release semantics of volatile can be turned off.  And volatile   */\n/* operations in icc9 don't imply ordering with respect to other nonvolatile    */\n/* operations.                                                                  */\n\n#define AO_INTEL_PTR_t void *\n\nAO_INLINE AO_t\nAO_load_acquire(const volatile AO_t *p)\n{\n  return (AO_t)(__ld8_acq((AO_INTEL_PTR_t)p));\n}\n#define AO_HAVE_load_acquire\n\nAO_INLINE void\nAO_store_release(volatile AO_t *p, AO_t val)\n{\n  __st8_rel((AO_INTEL_PTR_t)p, (__int64)val);\n}\n#define AO_HAVE_store_release\n\nAO_INLINE unsigned char\nAO_char_load_acquire(const volatile unsigned char *p)\n{\n  /* A normal volatile load generates an ld.acq         */\n  return (__ld1_acq((AO_INTEL_PTR_t)p));\n}\n#define AO_HAVE_char_load_acquire\n\nAO_INLINE void\nAO_char_store_release(volatile unsigned char *p, unsigned char val)\n{\n  __st1_rel((AO_INTEL_PTR_t)p, val);\n}\n#define AO_HAVE_char_store_release\n\nAO_INLINE unsigned short\nAO_short_load_acquire(const volatile unsigned short *p)\n{\n  /* A normal volatile load generates an ld.acq         */\n  return (__ld2_acq((AO_INTEL_PTR_t)p));\n}\n#define AO_HAVE_short_load_acquire\n\nAO_INLINE void\nAO_short_store_release(volatile unsigned short *p, unsigned short val)\n{\n  __st2_rel((AO_INTEL_PTR_t)p, val);\n}\n#define AO_HAVE_short_store_release\n\nAO_INLINE unsigned int\nAO_int_load_acquire(const volatile unsigned int *p)\n{\n  /* A normal volatile load generates an ld.acq         */\n  return (__ld4_acq((AO_INTEL_PTR_t)p));\n}\n#define AO_HAVE_int_load_acquire\n\nAO_INLINE void\nAO_int_store_release(volatile unsigned int *p, unsigned int val)\n{\n  __st4_rel((AO_INTEL_PTR_t)p, val);\n}\n#define AO_HAVE_int_store_release\n\nAO_INLINE void\nAO_nop_full(void)\n{\n  __mf();\n}\n#define AO_HAVE_nop_full\n\n#ifndef AO_PREFER_GENERALIZED\nAO_INLINE AO_t\nAO_fetch_and_add1_acquire(volatile AO_t *p)\n{\n  return __fetchadd8_acq((unsigned __int64 *)p, 1);\n}\n#define AO_HAVE_fetch_and_add1_acquire\n\nAO_INLINE AO_t\nAO_fetch_and_add1_release(volatile AO_t *p)\n{\n  return __fetchadd8_rel((unsigned __int64 *)p, 1);\n}\n#define AO_HAVE_fetch_and_add1_release\n\nAO_INLINE AO_t\nAO_fetch_and_sub1_acquire(volatile AO_t *p)\n{\n  return __fetchadd8_acq((unsigned __int64 *)p, -1);\n}\n#define AO_HAVE_fetch_and_sub1_acquire\n\nAO_INLINE AO_t\nAO_fetch_and_sub1_release(volatile AO_t *p)\n{\n  return __fetchadd8_rel((unsigned __int64 *)p, -1);\n}\n#define AO_HAVE_fetch_and_sub1_release\n#endif /* !AO_PREFER_GENERALIZED */\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val,\n                                  AO_t new_val)\n{\n  return _InterlockedCompareExchange64_acq(addr, new_val, old_val);\n}\n#define AO_HAVE_fetch_compare_and_swap_acquire\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_release(volatile AO_t *addr, AO_t old_val,\n                                  AO_t new_val)\n{\n  return _InterlockedCompareExchange64_rel(addr, new_val, old_val);\n}\n#define AO_HAVE_fetch_compare_and_swap_release\n\nAO_INLINE unsigned char\nAO_char_fetch_compare_and_swap_acquire(volatile unsigned char *addr,\n                                       unsigned char old_val,\n                                       unsigned char new_val)\n{\n  return _InterlockedCompareExchange8_acq(addr, new_val, old_val);\n}\n#define AO_HAVE_char_fetch_compare_and_swap_acquire\n\nAO_INLINE unsigned char\nAO_char_fetch_compare_and_swap_release(volatile unsigned char *addr,\n                                       unsigned char old_val,\n                                       unsigned char new_val)\n{\n  return _InterlockedCompareExchange8_rel(addr, new_val, old_val);\n}\n#define AO_HAVE_char_fetch_compare_and_swap_release\n\nAO_INLINE unsigned short\nAO_short_fetch_compare_and_swap_acquire(volatile unsigned short *addr,\n                                        unsigned short old_val,\n                                        unsigned short new_val)\n{\n  return _InterlockedCompareExchange16_acq(addr, new_val, old_val);\n}\n#define AO_HAVE_short_fetch_compare_and_swap_acquire\n\nAO_INLINE unsigned short\nAO_short_fetch_compare_and_swap_release(volatile unsigned short *addr,\n                                        unsigned short old_val,\n                                        unsigned short new_val)\n{\n  return _InterlockedCompareExchange16_rel(addr, new_val, old_val);\n}\n#define AO_HAVE_short_fetch_compare_and_swap_release\n\nAO_INLINE unsigned int\nAO_int_fetch_compare_and_swap_acquire(volatile unsigned int *addr,\n                                      unsigned int old_val,\n                                      unsigned int new_val)\n{\n  return _InterlockedCompareExchange_acq(addr, new_val, old_val);\n}\n#define AO_HAVE_int_fetch_compare_and_swap_acquire\n\nAO_INLINE unsigned int\nAO_int_fetch_compare_and_swap_release(volatile unsigned int *addr,\n                                      unsigned int old_val,\n                                      unsigned int new_val)\n{\n  return _InterlockedCompareExchange_rel(addr, new_val, old_val);\n}\n#define AO_HAVE_int_fetch_compare_and_swap_release\n\n#undef AO_INTEL_PTR_t\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/acquire_release_volatile.h",
    "content": "/*\n * Copyright (c) 2003-2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* This file adds definitions appropriate for environments in which     */\n/* volatile load of a given type has acquire semantics, and volatile    */\n/* store of a given type has release semantics.  This is arguably       */\n/* supposed to be true with the standard Itanium software conventions.  */\n/* Empirically gcc/ia64 does some reordering of ordinary operations     */\n/* around volatiles even when we think it should not.  GCC v3.3 and     */\n/* earlier could reorder a volatile store with another store.  As of    */\n/* March 2005, gcc pre-4 reuses some previously computed common         */\n/* subexpressions across a volatile load; hence, we now add compiler    */\n/* barriers for gcc.                                                    */\n\n#ifndef AO_HAVE_GCC_BARRIER\n  /* TODO: Check GCC version (if workaround not needed for modern GCC). */\n# if defined(__GNUC__)\n#   define AO_GCC_BARRIER() AO_compiler_barrier()\n# else\n#   define AO_GCC_BARRIER() (void)0\n# endif\n# define AO_HAVE_GCC_BARRIER\n#endif\n\nAO_INLINE AO_t\nAO_load_acquire(const volatile AO_t *addr)\n{\n  AO_t result = *addr;\n\n  /* A normal volatile load generates an ld.acq (on IA-64).     */\n  AO_GCC_BARRIER();\n  return result;\n}\n#define AO_HAVE_load_acquire\n\nAO_INLINE void\nAO_store_release(volatile AO_t *addr, AO_t new_val)\n{\n  AO_GCC_BARRIER();\n  /* A normal volatile store generates an st.rel (on IA-64).    */\n  *addr = new_val;\n}\n#define AO_HAVE_store_release\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/acquire_release_volatile.template",
    "content": "/*\n * Copyright (c) 2003-2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* This file adds definitions appropriate for environments in which     */\n/* volatile load of a given type has acquire semantics, and volatile    */\n/* store of a given type has release semantics.  This is arguably       */\n/* supposed to be true with the standard Itanium software conventions.  */\n/* Empirically gcc/ia64 does some reordering of ordinary operations     */\n/* around volatiles even when we think it should not.  GCC v3.3 and     */\n/* earlier could reorder a volatile store with another store.  As of    */\n/* March 2005, gcc pre-4 reuses some previously computed common         */\n/* subexpressions across a volatile load; hence, we now add compiler    */\n/* barriers for gcc.                                                    */\n\n#ifndef AO_HAVE_GCC_BARRIER\n  /* TODO: Check GCC version (if workaround not needed for modern GCC). */\n# if defined(__GNUC__)\n#   define AO_GCC_BARRIER() AO_compiler_barrier()\n# else\n#   define AO_GCC_BARRIER() (void)0\n# endif\n# define AO_HAVE_GCC_BARRIER\n#endif\n\nAO_INLINE XCTYPE\nAO_XSIZE_load_acquire(const volatile XCTYPE *addr)\n{\n  XCTYPE result = *addr;\n\n  /* A normal volatile load generates an ld.acq (on IA-64).     */\n  AO_GCC_BARRIER();\n  return result;\n}\n#define AO_HAVE_XSIZE_load_acquire\n\nAO_INLINE void\nAO_XSIZE_store_release(volatile XCTYPE *addr, XCTYPE new_val)\n{\n  AO_GCC_BARRIER();\n  /* A normal volatile store generates an st.rel (on IA-64).    */\n  *addr = new_val;\n}\n#define AO_HAVE_XSIZE_store_release\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/atomic_load.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Definitions for architectures on which loads of given type are       */\n/* atomic (either for suitably aligned data only or for any legal       */\n/* alignment).                                                          */\n\nAO_INLINE AO_t\nAO_load(const volatile AO_t *addr)\n{\n# ifdef AO_ACCESS_CHECK_ALIGNED\n    AO_ASSERT_ADDR_ALIGNED(addr);\n# endif\n  /* Cast away the volatile for architectures like IA64 where   */\n  /* volatile adds barrier (fence) semantics.                   */\n  return *(const AO_t *)addr;\n}\n#define AO_HAVE_load\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/atomic_load.template",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Definitions for architectures on which loads of given type are       */\n/* atomic (either for suitably aligned data only or for any legal       */\n/* alignment).                                                          */\n\nAO_INLINE XCTYPE\nAO_XSIZE_load(const volatile XCTYPE *addr)\n{\n# ifdef AO_ACCESS_XSIZE_CHECK_ALIGNED\n    AO_ASSERT_ADDR_ALIGNED(addr);\n# endif\n  /* Cast away the volatile for architectures like IA64 where   */\n  /* volatile adds barrier (fence) semantics.                   */\n  return *(const XCTYPE *)addr;\n}\n#define AO_HAVE_XSIZE_load\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/atomic_store.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Definitions for architectures on which stores of given type are      */\n/* atomic (either for suitably aligned data only or for any legal       */\n/* alignment).                                                          */\n\nAO_INLINE void\nAO_store(volatile AO_t *addr, AO_t new_val)\n{\n# ifdef AO_ACCESS_CHECK_ALIGNED\n    AO_ASSERT_ADDR_ALIGNED(addr);\n# endif\n  *(AO_t *)addr = new_val;\n}\n#define AO_HAVE_store\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/atomic_store.template",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Definitions for architectures on which stores of given type are      */\n/* atomic (either for suitably aligned data only or for any legal       */\n/* alignment).                                                          */\n\nAO_INLINE void\nAO_XSIZE_store(volatile XCTYPE *addr, XCTYPE new_val)\n{\n# ifdef AO_ACCESS_XSIZE_CHECK_ALIGNED\n    AO_ASSERT_ADDR_ALIGNED(addr);\n# endif\n  *(XCTYPE *)addr = new_val;\n}\n#define AO_HAVE_XSIZE_store\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/char_acquire_release_volatile.h",
    "content": "/*\n * Copyright (c) 2003-2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* This file adds definitions appropriate for environments in which     */\n/* volatile load of a given type has acquire semantics, and volatile    */\n/* store of a given type has release semantics.  This is arguably       */\n/* supposed to be true with the standard Itanium software conventions.  */\n/* Empirically gcc/ia64 does some reordering of ordinary operations     */\n/* around volatiles even when we think it should not.  GCC v3.3 and     */\n/* earlier could reorder a volatile store with another store.  As of    */\n/* March 2005, gcc pre-4 reuses some previously computed common         */\n/* subexpressions across a volatile load; hence, we now add compiler    */\n/* barriers for gcc.                                                    */\n\n#ifndef AO_HAVE_GCC_BARRIER\n  /* TODO: Check GCC version (if workaround not needed for modern GCC). */\n# if defined(__GNUC__)\n#   define AO_GCC_BARRIER() AO_compiler_barrier()\n# else\n#   define AO_GCC_BARRIER() (void)0\n# endif\n# define AO_HAVE_GCC_BARRIER\n#endif\n\nAO_INLINE unsigned/**/char\nAO_char_load_acquire(const volatile unsigned/**/char *addr)\n{\n  unsigned/**/char result = *addr;\n\n  /* A normal volatile load generates an ld.acq (on IA-64).     */\n  AO_GCC_BARRIER();\n  return result;\n}\n#define AO_HAVE_char_load_acquire\n\nAO_INLINE void\nAO_char_store_release(volatile unsigned/**/char *addr, unsigned/**/char new_val)\n{\n  AO_GCC_BARRIER();\n  /* A normal volatile store generates an st.rel (on IA-64).    */\n  *addr = new_val;\n}\n#define AO_HAVE_char_store_release\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/char_atomic_load.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Definitions for architectures on which loads of given type are       */\n/* atomic (either for suitably aligned data only or for any legal       */\n/* alignment).                                                          */\n\nAO_INLINE unsigned/**/char\nAO_char_load(const volatile unsigned/**/char *addr)\n{\n# ifdef AO_ACCESS_char_CHECK_ALIGNED\n    AO_ASSERT_ADDR_ALIGNED(addr);\n# endif\n  /* Cast away the volatile for architectures like IA64 where   */\n  /* volatile adds barrier (fence) semantics.                   */\n  return *(const unsigned/**/char *)addr;\n}\n#define AO_HAVE_char_load\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/char_atomic_store.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Definitions for architectures on which stores of given type are      */\n/* atomic (either for suitably aligned data only or for any legal       */\n/* alignment).                                                          */\n\nAO_INLINE void\nAO_char_store(volatile unsigned/**/char *addr, unsigned/**/char new_val)\n{\n# ifdef AO_ACCESS_char_CHECK_ALIGNED\n    AO_ASSERT_ADDR_ALIGNED(addr);\n# endif\n  *(unsigned/**/char *)addr = new_val;\n}\n#define AO_HAVE_char_store\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/double_atomic_load_store.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2013 Ivan Maidanski\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Definitions for architectures on which AO_double_t loads and stores  */\n/* are atomic (either for suitably aligned data only or for any legal   */\n/* alignment).                                                          */\n\nAO_INLINE AO_double_t\nAO_double_load(const volatile AO_double_t *addr)\n{\n  AO_double_t result;\n\n# ifdef AO_ACCESS_double_CHECK_ALIGNED\n    AO_ASSERT_ADDR_ALIGNED(addr);\n# endif\n  /* Cast away the volatile in case it adds fence semantics.  */\n  result.AO_whole = ((const AO_double_t *)addr)->AO_whole;\n  return result;\n}\n#define AO_HAVE_double_load\n\nAO_INLINE void\nAO_double_store(volatile AO_double_t *addr, AO_double_t new_val)\n{\n# ifdef AO_ACCESS_double_CHECK_ALIGNED\n    AO_ASSERT_ADDR_ALIGNED(addr);\n# endif\n  ((AO_double_t *)addr)->AO_whole = new_val.AO_whole;\n}\n#define AO_HAVE_double_store\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/int_acquire_release_volatile.h",
    "content": "/*\n * Copyright (c) 2003-2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* This file adds definitions appropriate for environments in which     */\n/* volatile load of a given type has acquire semantics, and volatile    */\n/* store of a given type has release semantics.  This is arguably       */\n/* supposed to be true with the standard Itanium software conventions.  */\n/* Empirically gcc/ia64 does some reordering of ordinary operations     */\n/* around volatiles even when we think it should not.  GCC v3.3 and     */\n/* earlier could reorder a volatile store with another store.  As of    */\n/* March 2005, gcc pre-4 reuses some previously computed common         */\n/* subexpressions across a volatile load; hence, we now add compiler    */\n/* barriers for gcc.                                                    */\n\n#ifndef AO_HAVE_GCC_BARRIER\n  /* TODO: Check GCC version (if workaround not needed for modern GCC). */\n# if defined(__GNUC__)\n#   define AO_GCC_BARRIER() AO_compiler_barrier()\n# else\n#   define AO_GCC_BARRIER() (void)0\n# endif\n# define AO_HAVE_GCC_BARRIER\n#endif\n\nAO_INLINE unsigned\nAO_int_load_acquire(const volatile unsigned *addr)\n{\n  unsigned result = *addr;\n\n  /* A normal volatile load generates an ld.acq (on IA-64).     */\n  AO_GCC_BARRIER();\n  return result;\n}\n#define AO_HAVE_int_load_acquire\n\nAO_INLINE void\nAO_int_store_release(volatile unsigned *addr, unsigned new_val)\n{\n  AO_GCC_BARRIER();\n  /* A normal volatile store generates an st.rel (on IA-64).    */\n  *addr = new_val;\n}\n#define AO_HAVE_int_store_release\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/int_atomic_load.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Definitions for architectures on which loads of given type are       */\n/* atomic (either for suitably aligned data only or for any legal       */\n/* alignment).                                                          */\n\nAO_INLINE unsigned\nAO_int_load(const volatile unsigned *addr)\n{\n# ifdef AO_ACCESS_int_CHECK_ALIGNED\n    AO_ASSERT_ADDR_ALIGNED(addr);\n# endif\n  /* Cast away the volatile for architectures like IA64 where   */\n  /* volatile adds barrier (fence) semantics.                   */\n  return *(const unsigned *)addr;\n}\n#define AO_HAVE_int_load\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/int_atomic_store.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Definitions for architectures on which stores of given type are      */\n/* atomic (either for suitably aligned data only or for any legal       */\n/* alignment).                                                          */\n\nAO_INLINE void\nAO_int_store(volatile unsigned *addr, unsigned new_val)\n{\n# ifdef AO_ACCESS_int_CHECK_ALIGNED\n    AO_ASSERT_ADDR_ALIGNED(addr);\n# endif\n  *(unsigned *)addr = new_val;\n}\n#define AO_HAVE_int_store\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/ordered_loads_only.h",
    "content": "/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#ifdef AO_HAVE_char_load\n  /* char_load_read is defined in generalize-small.    */\n# define AO_char_load_acquire(addr) AO_char_load_read(addr)\n# define AO_HAVE_char_load_acquire\n#endif\n/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#ifdef AO_HAVE_short_load\n  /* short_load_read is defined in generalize-small.    */\n# define AO_short_load_acquire(addr) AO_short_load_read(addr)\n# define AO_HAVE_short_load_acquire\n#endif\n/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#ifdef AO_HAVE_int_load\n  /* int_load_read is defined in generalize-small.    */\n# define AO_int_load_acquire(addr) AO_int_load_read(addr)\n# define AO_HAVE_int_load_acquire\n#endif\n/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#ifdef AO_HAVE_load\n  /* load_read is defined in generalize-small.    */\n# define AO_load_acquire(addr) AO_load_read(addr)\n# define AO_HAVE_load_acquire\n#endif\n/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#ifdef AO_HAVE_double_load\n  /* double_load_read is defined in generalize-small.    */\n# define AO_double_load_acquire(addr) AO_double_load_read(addr)\n# define AO_HAVE_double_load_acquire\n#endif\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/ordered_loads_only.template",
    "content": "/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#ifdef AO_HAVE_XSIZE_load\n  /* XSIZE_load_read is defined in generalize-small.    */\n# define AO_XSIZE_load_acquire(addr) AO_XSIZE_load_read(addr)\n# define AO_HAVE_XSIZE_load_acquire\n#endif\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/ordered_stores_only.h",
    "content": "/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#ifdef AO_HAVE_char_store\n# define AO_char_store_release(addr, val) \\\n                                (AO_nop_write(), AO_char_store(addr, val))\n# define AO_HAVE_char_store_release\n#endif\n/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#ifdef AO_HAVE_short_store\n# define AO_short_store_release(addr, val) \\\n                                (AO_nop_write(), AO_short_store(addr, val))\n# define AO_HAVE_short_store_release\n#endif\n/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#ifdef AO_HAVE_int_store\n# define AO_int_store_release(addr, val) \\\n                                (AO_nop_write(), AO_int_store(addr, val))\n# define AO_HAVE_int_store_release\n#endif\n/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#ifdef AO_HAVE_store\n# define AO_store_release(addr, val) \\\n                                (AO_nop_write(), AO_store(addr, val))\n# define AO_HAVE_store_release\n#endif\n/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#ifdef AO_HAVE_double_store\n# define AO_double_store_release(addr, val) \\\n                                (AO_nop_write(), AO_double_store(addr, val))\n# define AO_HAVE_double_store_release\n#endif\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/ordered_stores_only.template",
    "content": "/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#ifdef AO_HAVE_XSIZE_store\n# define AO_XSIZE_store_release(addr, val) \\\n                                (AO_nop_write(), AO_XSIZE_store(addr, val))\n# define AO_HAVE_XSIZE_store_release\n#endif\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/short_acquire_release_volatile.h",
    "content": "/*\n * Copyright (c) 2003-2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* This file adds definitions appropriate for environments in which     */\n/* volatile load of a given type has acquire semantics, and volatile    */\n/* store of a given type has release semantics.  This is arguably       */\n/* supposed to be true with the standard Itanium software conventions.  */\n/* Empirically gcc/ia64 does some reordering of ordinary operations     */\n/* around volatiles even when we think it should not.  GCC v3.3 and     */\n/* earlier could reorder a volatile store with another store.  As of    */\n/* March 2005, gcc pre-4 reuses some previously computed common         */\n/* subexpressions across a volatile load; hence, we now add compiler    */\n/* barriers for gcc.                                                    */\n\n#ifndef AO_HAVE_GCC_BARRIER\n  /* TODO: Check GCC version (if workaround not needed for modern GCC). */\n# if defined(__GNUC__)\n#   define AO_GCC_BARRIER() AO_compiler_barrier()\n# else\n#   define AO_GCC_BARRIER() (void)0\n# endif\n# define AO_HAVE_GCC_BARRIER\n#endif\n\nAO_INLINE unsigned/**/short\nAO_short_load_acquire(const volatile unsigned/**/short *addr)\n{\n  unsigned/**/short result = *addr;\n\n  /* A normal volatile load generates an ld.acq (on IA-64).     */\n  AO_GCC_BARRIER();\n  return result;\n}\n#define AO_HAVE_short_load_acquire\n\nAO_INLINE void\nAO_short_store_release(volatile unsigned/**/short *addr, unsigned/**/short new_val)\n{\n  AO_GCC_BARRIER();\n  /* A normal volatile store generates an st.rel (on IA-64).    */\n  *addr = new_val;\n}\n#define AO_HAVE_short_store_release\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/short_atomic_load.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Definitions for architectures on which loads of given type are       */\n/* atomic (either for suitably aligned data only or for any legal       */\n/* alignment).                                                          */\n\nAO_INLINE unsigned/**/short\nAO_short_load(const volatile unsigned/**/short *addr)\n{\n# ifdef AO_ACCESS_short_CHECK_ALIGNED\n    AO_ASSERT_ADDR_ALIGNED(addr);\n# endif\n  /* Cast away the volatile for architectures like IA64 where   */\n  /* volatile adds barrier (fence) semantics.                   */\n  return *(const unsigned/**/short *)addr;\n}\n#define AO_HAVE_short_load\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/loadstore/short_atomic_store.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Definitions for architectures on which stores of given type are      */\n/* atomic (either for suitably aligned data only or for any legal       */\n/* alignment).                                                          */\n\nAO_INLINE void\nAO_short_store(volatile unsigned/**/short *addr, unsigned/**/short new_val)\n{\n# ifdef AO_ACCESS_short_CHECK_ALIGNED\n    AO_ASSERT_ADDR_ALIGNED(addr);\n# endif\n  *(unsigned/**/short *)addr = new_val;\n}\n#define AO_HAVE_short_store\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/msftc/arm.h",
    "content": "/*\n * Copyright (c) 2003 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2009-2021 Ivan Maidanski\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Some ARM slide set, if it has been read correctly, claims that Loads */\n/* followed by either a Load or a Store are ordered, but nothing else.  */\n/* It is assumed that Windows interrupt handlers clear the LL/SC flag.  */\n/* Unaligned accesses are not guaranteed to be atomic.                  */\n#include \"../all_aligned_atomic_load_store.h\"\n\n#define AO_T_IS_INT\n\n#ifndef AO_ASSUME_WINDOWS98\n  /* CAS is always available */\n# define AO_ASSUME_WINDOWS98\n#endif\n#include \"common32_defs.h\"\n\n/* If only a single processor is used, we can define AO_UNIPROCESSOR.   */\n#ifdef AO_UNIPROCESSOR\n  AO_INLINE void AO_nop_full(void)\n  {\n    AO_compiler_barrier();\n  }\n# define AO_HAVE_nop_full\n#else\n  /* AO_nop_full() is emulated using AO_test_and_set_full().            */\n#endif\n\n#ifndef AO_HAVE_test_and_set_full\n# include \"../test_and_set_t_is_ao_t.h\"\n  /* AO_test_and_set_full() is emulated. */\n#endif\n\n#if _M_ARM >= 7 && !defined(AO_NO_DOUBLE_CAS)\n\n# include \"../standard_ao_double_t.h\"\n\n/* These intrinsics are supposed to use LDREXD/STREXD.  */\n# pragma intrinsic (_InterlockedCompareExchange64)\n# pragma intrinsic (_InterlockedCompareExchange64_acq)\n# pragma intrinsic (_InterlockedCompareExchange64_nf)\n# pragma intrinsic (_InterlockedCompareExchange64_rel)\n\n  AO_INLINE int\n  AO_double_compare_and_swap(volatile AO_double_t *addr,\n                             AO_double_t old_val, AO_double_t new_val)\n  {\n    AO_ASSERT_ADDR_ALIGNED(addr);\n    return (double_ptr_storage)_InterlockedCompareExchange64_nf(\n                                        (__int64 volatile *)addr,\n                                        new_val.AO_whole /* exchange */,\n                                        old_val.AO_whole) == old_val.AO_whole;\n  }\n# define AO_HAVE_double_compare_and_swap\n\n  AO_INLINE int\n  AO_double_compare_and_swap_acquire(volatile AO_double_t *addr,\n                                     AO_double_t old_val, AO_double_t new_val)\n  {\n    AO_ASSERT_ADDR_ALIGNED(addr);\n    return (double_ptr_storage)_InterlockedCompareExchange64_acq(\n                                        (__int64 volatile *)addr,\n                                        new_val.AO_whole /* exchange */,\n                                        old_val.AO_whole) == old_val.AO_whole;\n  }\n# define AO_HAVE_double_compare_and_swap_acquire\n\n  AO_INLINE int\n  AO_double_compare_and_swap_release(volatile AO_double_t *addr,\n                                     AO_double_t old_val, AO_double_t new_val)\n  {\n    AO_ASSERT_ADDR_ALIGNED(addr);\n    return (double_ptr_storage)_InterlockedCompareExchange64_rel(\n                                        (__int64 volatile *)addr,\n                                        new_val.AO_whole /* exchange */,\n                                        old_val.AO_whole) == old_val.AO_whole;\n  }\n# define AO_HAVE_double_compare_and_swap_release\n\n  AO_INLINE int\n  AO_double_compare_and_swap_full(volatile AO_double_t *addr,\n                                  AO_double_t old_val, AO_double_t new_val)\n  {\n    AO_ASSERT_ADDR_ALIGNED(addr);\n    return (double_ptr_storage)_InterlockedCompareExchange64(\n                                        (__int64 volatile *)addr,\n                                        new_val.AO_whole /* exchange */,\n                                        old_val.AO_whole) == old_val.AO_whole;\n  }\n# define AO_HAVE_double_compare_and_swap_full\n\n#endif /* _M_ARM >= 7 && !AO_NO_DOUBLE_CAS */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/msftc/arm64.h",
    "content": "/*\n * Copyright (c) 2003 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2021 Ivan Maidanski\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#include \"../all_aligned_atomic_load_store.h\"\n\n#ifndef AO_ASSUME_WINDOWS98\n# define AO_ASSUME_WINDOWS98\n#endif\n#ifndef AO_USE_INTERLOCKED_INTRINSICS\n# define AO_USE_INTERLOCKED_INTRINSICS\n#endif\n#include \"common32_defs.h\"\n\n#ifndef AO_HAVE_test_and_set_full\n# include \"../test_and_set_t_is_ao_t.h\"\n  /* AO_test_and_set_full() is emulated using word-wide CAS.    */\n#endif\n\n#ifndef AO_NO_DOUBLE_CAS\n\n# include \"../standard_ao_double_t.h\"\n\n# pragma intrinsic (_InterlockedCompareExchange128)\n# pragma intrinsic (_InterlockedCompareExchange128_acq)\n# pragma intrinsic (_InterlockedCompareExchange128_nf)\n# pragma intrinsic (_InterlockedCompareExchange128_rel)\n\n  AO_INLINE int\n  AO_compare_double_and_swap_double(volatile AO_double_t *addr,\n                                    AO_t old_val1, AO_t old_val2,\n                                    AO_t new_val1, AO_t new_val2)\n  {\n    __int64 comparandResult[2];\n\n    AO_ASSERT_ADDR_ALIGNED(addr);\n    comparandResult[0] = old_val1; /* low */\n    comparandResult[1] = old_val2; /* high */\n    return _InterlockedCompareExchange128_nf((volatile __int64 *)addr,\n                                             new_val2 /* high */,\n                                             new_val1 /* low */,\n                                             comparandResult);\n  }\n# define AO_HAVE_compare_double_and_swap_double\n\n  AO_INLINE int\n  AO_compare_double_and_swap_double_acquire(volatile AO_double_t *addr,\n                                            AO_t old_val1, AO_t old_val2,\n                                            AO_t new_val1, AO_t new_val2)\n  {\n    __int64 comparandResult[2];\n\n    AO_ASSERT_ADDR_ALIGNED(addr);\n    comparandResult[0] = old_val1; /* low */\n    comparandResult[1] = old_val2; /* high */\n    return _InterlockedCompareExchange128_acq((volatile __int64 *)addr,\n                                              new_val2 /* high */,\n                                              new_val1 /* low */,\n                                              comparandResult);\n  }\n# define AO_HAVE_compare_double_and_swap_double_acquire\n\n  AO_INLINE int\n  AO_compare_double_and_swap_double_release(volatile AO_double_t *addr,\n                                            AO_t old_val1, AO_t old_val2,\n                                            AO_t new_val1, AO_t new_val2)\n  {\n    __int64 comparandResult[2];\n\n    AO_ASSERT_ADDR_ALIGNED(addr);\n    comparandResult[0] = old_val1; /* low */\n    comparandResult[1] = old_val2; /* high */\n    return _InterlockedCompareExchange128_rel((volatile __int64 *)addr,\n                                              new_val2 /* high */,\n                                              new_val1 /* low */,\n                                              comparandResult);\n  }\n# define AO_HAVE_compare_double_and_swap_double_release\n\n  AO_INLINE int\n  AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,\n                                         AO_t old_val1, AO_t old_val2,\n                                         AO_t new_val1, AO_t new_val2)\n  {\n    __int64 comparandResult[2];\n\n    AO_ASSERT_ADDR_ALIGNED(addr);\n    comparandResult[0] = old_val1; /* low */\n    comparandResult[1] = old_val2; /* high */\n    return _InterlockedCompareExchange128((volatile __int64 *)addr,\n                                          new_val2 /* high */,\n                                          new_val1 /* low */,\n                                          comparandResult);\n  }\n# define AO_HAVE_compare_double_and_swap_double_full\n\n#endif /* !AO_NO_DOUBLE_CAS */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/msftc/common32_defs.h",
    "content": "/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2009-2021 Ivan Maidanski\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* This file contains AO primitives based on VC++ built-in intrinsic    */\n/* functions commonly available across 32- and 64-bit architectures.    */\n\n/* This file should be included from arch-specific header files.        */\n/* Define AO_USE_INTERLOCKED_INTRINSICS if _Interlocked primitives      */\n/* (used below) are available as intrinsic ones for a target arch       */\n/* (otherwise \"Interlocked\" functions family is used instead).          */\n/* Define AO_ASSUME_WINDOWS98 if CAS is available.                      */\n\n#if _MSC_VER <= 1400 || !defined(AO_USE_INTERLOCKED_INTRINSICS) \\\n    || defined(_WIN32_WCE)\n# include <windows.h>\n        /* Seems like over-kill, but that's what MSDN recommends.       */\n        /* And apparently winbase.h is not always self-contained.       */\n        /* Optionally, client could define WIN32_LEAN_AND_MEAN before   */\n        /* include atomic_ops.h to reduce amount of Windows internal    */\n        /* headers included by windows.h one.                           */\n#endif\n\n#if _MSC_VER < 1310 || !defined(AO_USE_INTERLOCKED_INTRINSICS)\n\n# define _InterlockedIncrement       InterlockedIncrement\n# define _InterlockedDecrement       InterlockedDecrement\n# define _InterlockedExchangeAdd     InterlockedExchangeAdd\n# define _InterlockedCompareExchange InterlockedCompareExchange\n\n# define AO_INTERLOCKED_VOLATILE /**/\n\n#else /* elif _MSC_VER >= 1310 */\n\n# if _MSC_VER >= 1400\n#   ifndef _WIN32_WCE\n#     include <intrin.h>\n#   endif\n\n# else /* elif _MSC_VER < 1400 */\n#  ifdef __cplusplus\n     extern \"C\" {\n#  endif\n   LONG __cdecl _InterlockedIncrement(LONG volatile *);\n   LONG __cdecl _InterlockedDecrement(LONG volatile *);\n   LONG __cdecl _InterlockedExchangeAdd(LONG volatile *, LONG);\n   LONG __cdecl _InterlockedCompareExchange(LONG volatile *,\n                                        LONG /* Exchange */, LONG /* Comp */);\n#  ifdef __cplusplus\n     } /* extern \"C\" */\n#  endif\n# endif /* _MSC_VER < 1400 */\n\n# if !defined(AO_PREFER_GENERALIZED) || !defined(AO_ASSUME_WINDOWS98)\n#   pragma intrinsic (_InterlockedIncrement)\n#   pragma intrinsic (_InterlockedDecrement)\n#   pragma intrinsic (_InterlockedExchangeAdd)\n#   ifndef AO_T_IS_INT\n#     pragma intrinsic (_InterlockedIncrement64)\n#     pragma intrinsic (_InterlockedDecrement64)\n#     pragma intrinsic (_InterlockedExchangeAdd64)\n#   endif\n# endif /* !AO_PREFER_GENERALIZED */\n\n# pragma intrinsic (_InterlockedCompareExchange)\n# ifndef AO_T_IS_INT\n#   pragma intrinsic (_InterlockedCompareExchange64)\n# endif\n\n# define AO_INTERLOCKED_VOLATILE volatile\n\n#endif /* _MSC_VER >= 1310 */\n\n#if !defined(AO_PREFER_GENERALIZED) || !defined(AO_ASSUME_WINDOWS98)\n  AO_INLINE AO_t\n  AO_fetch_and_add_full(volatile AO_t *p, AO_t incr)\n  {\n#   ifdef AO_T_IS_INT\n      return _InterlockedExchangeAdd((long AO_INTERLOCKED_VOLATILE *)p, incr);\n#   else\n      return _InterlockedExchangeAdd64((__int64 volatile *)p, incr);\n#   endif\n  }\n# define AO_HAVE_fetch_and_add_full\n\n  AO_INLINE AO_t\n  AO_fetch_and_add1_full(volatile AO_t *p)\n  {\n#   ifdef AO_T_IS_INT\n      return _InterlockedIncrement((long AO_INTERLOCKED_VOLATILE *)p) - 1;\n#   else\n      return _InterlockedIncrement64((__int64 volatile *)p) - 1;\n#   endif\n  }\n# define AO_HAVE_fetch_and_add1_full\n\n  AO_INLINE AO_t\n  AO_fetch_and_sub1_full(volatile AO_t *p)\n  {\n#   ifdef AO_T_IS_INT\n      return _InterlockedDecrement((long AO_INTERLOCKED_VOLATILE *)p) + 1;\n#   else\n      return _InterlockedDecrement64((__int64 volatile *)p) + 1;\n#   endif\n  }\n# define AO_HAVE_fetch_and_sub1_full\n\n# ifndef AO_T_IS_INT\n    AO_INLINE unsigned int\n    AO_int_fetch_and_add_full(volatile unsigned int *p, unsigned int incr)\n    {\n      return _InterlockedExchangeAdd((long volatile *)p, incr);\n    }\n#   define AO_HAVE_int_fetch_and_add_full\n\n    AO_INLINE unsigned int\n    AO_int_fetch_and_add1_full(volatile unsigned int *p)\n    {\n      return _InterlockedIncrement((long volatile *)p) - 1;\n    }\n#   define AO_HAVE_int_fetch_and_add1_full\n\n    AO_INLINE unsigned int\n    AO_int_fetch_and_sub1_full(volatile unsigned int *p)\n    {\n      return _InterlockedDecrement((long volatile *)p) + 1;\n    }\n#   define AO_HAVE_int_fetch_and_sub1_full\n# endif /* !AO_T_IS_INT */\n#endif /* !AO_PREFER_GENERALIZED */\n\n#ifdef AO_ASSUME_WINDOWS98\n  AO_INLINE AO_t\n  AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val,\n                                 AO_t new_val)\n  {\n#   ifndef AO_T_IS_INT\n      return (AO_t)_InterlockedCompareExchange64((__int64 volatile *)addr,\n                                                 new_val, old_val);\n#   elif defined(AO_OLD_STYLE_INTERLOCKED_COMPARE_EXCHANGE)\n      return (AO_t)_InterlockedCompareExchange(\n                                        (void *AO_INTERLOCKED_VOLATILE *)addr,\n                                        (void *)new_val, (void *)old_val);\n#   else\n      return _InterlockedCompareExchange((long AO_INTERLOCKED_VOLATILE *)addr,\n                                         new_val, old_val);\n#   endif\n  }\n# define AO_HAVE_fetch_compare_and_swap_full\n\n# ifndef AO_T_IS_INT\n    AO_INLINE unsigned int\n    AO_int_fetch_compare_and_swap_full(volatile unsigned int *addr,\n                                       unsigned int old_val,\n                                       unsigned int new_val)\n    {\n      return _InterlockedCompareExchange((long volatile *)addr,\n                                         new_val, old_val);\n    }\n#   define AO_HAVE_int_fetch_compare_and_swap_full\n# endif /* !AO_T_IS_INT */\n#endif /* AO_ASSUME_WINDOWS98 */\n\n#if (_MSC_VER > 1400) && (!defined(_M_ARM) || _MSC_VER >= 1800)\n\n# if _MSC_VER < 1800 || !defined(AO_PREFER_GENERALIZED)\n#   pragma intrinsic (_InterlockedAnd8)\n#   pragma intrinsic (_InterlockedOr8)\n#   pragma intrinsic (_InterlockedXor8)\n\n    AO_INLINE void\n    AO_char_and_full(volatile unsigned char *p, unsigned char value)\n    {\n      _InterlockedAnd8((char volatile *)p, value);\n    }\n#   define AO_HAVE_char_and_full\n\n    AO_INLINE void\n    AO_char_or_full(volatile unsigned char *p, unsigned char value)\n    {\n      _InterlockedOr8((char volatile *)p, value);\n    }\n#   define AO_HAVE_char_or_full\n\n    AO_INLINE void\n    AO_char_xor_full(volatile unsigned char *p, unsigned char value)\n    {\n      _InterlockedXor8((char volatile *)p, value);\n    }\n#   define AO_HAVE_char_xor_full\n# endif /* _MSC_VER < 1800 || !AO_PREFER_GENERALIZED */\n\n# pragma intrinsic (_InterlockedCompareExchange16)\n\n  AO_INLINE unsigned short\n  AO_short_fetch_compare_and_swap_full(volatile unsigned short *addr,\n                                       unsigned short old_val,\n                                       unsigned short new_val)\n  {\n    return _InterlockedCompareExchange16((short volatile *)addr,\n                                         new_val, old_val);\n  }\n# define AO_HAVE_short_fetch_compare_and_swap_full\n\n# ifndef AO_PREFER_GENERALIZED\n#   pragma intrinsic (_InterlockedIncrement16)\n#   pragma intrinsic (_InterlockedDecrement16)\n\n    AO_INLINE unsigned short\n    AO_short_fetch_and_add1_full(volatile unsigned short *p)\n    {\n      return _InterlockedIncrement16((short volatile *)p) - 1;\n    }\n#   define AO_HAVE_short_fetch_and_add1_full\n\n    AO_INLINE unsigned short\n    AO_short_fetch_and_sub1_full(volatile unsigned short *p)\n    {\n      return _InterlockedDecrement16((short volatile *)p) + 1;\n    }\n#   define AO_HAVE_short_fetch_and_sub1_full\n# endif /* !AO_PREFER_GENERALIZED */\n\n#endif /* _MSC_VER > 1400 */\n\n#if _MSC_VER >= 1800 /* Visual Studio 2013+ */\n\n# ifndef AO_PREFER_GENERALIZED\n#   pragma intrinsic (_InterlockedAnd16)\n#   pragma intrinsic (_InterlockedOr16)\n#   pragma intrinsic (_InterlockedXor16)\n\n    AO_INLINE void\n    AO_short_and_full(volatile unsigned short *p, unsigned short value)\n    {\n      (void)_InterlockedAnd16((short volatile *)p, value);\n    }\n#   define AO_HAVE_short_and_full\n\n    AO_INLINE void\n    AO_short_or_full(volatile unsigned short *p, unsigned short value)\n    {\n      (void)_InterlockedOr16((short volatile *)p, value);\n    }\n#   define AO_HAVE_short_or_full\n\n    AO_INLINE void\n    AO_short_xor_full(volatile unsigned short *p, unsigned short value)\n    {\n      (void)_InterlockedXor16((short volatile *)p, value);\n    }\n#   define AO_HAVE_short_xor_full\n\n#   pragma intrinsic (_InterlockedAnd)\n#   pragma intrinsic (_InterlockedOr)\n#   pragma intrinsic (_InterlockedXor)\n\n#   ifndef AO_T_IS_INT\n      AO_INLINE void\n      AO_int_and_full(volatile unsigned int *p, unsigned int value)\n      {\n        (void)_InterlockedAnd((long volatile *)p, value);\n      }\n#     define AO_HAVE_int_and_full\n\n      AO_INLINE void\n      AO_int_or_full(volatile unsigned int *p, unsigned int value)\n      {\n        (void)_InterlockedOr((long volatile *)p, value);\n      }\n#     define AO_HAVE_int_or_full\n\n      AO_INLINE void\n      AO_int_xor_full(volatile unsigned int *p, unsigned int value)\n      {\n        (void)_InterlockedXor((long volatile *)p, value);\n      }\n#     define AO_HAVE_int_xor_full\n\n#     pragma intrinsic (_InterlockedAnd64)\n#     pragma intrinsic (_InterlockedOr64)\n#     pragma intrinsic (_InterlockedXor64)\n#   endif /* !AO_T_IS_INT */\n\n    AO_INLINE void\n    AO_and_full(volatile AO_t *p, AO_t value)\n    {\n#     ifdef AO_T_IS_INT\n        (void)_InterlockedAnd((long volatile *)p, value);\n#     else\n        (void)_InterlockedAnd64((__int64 volatile *)p, value);\n#     endif\n    }\n#   define AO_HAVE_and_full\n\n    AO_INLINE void\n    AO_or_full(volatile AO_t *p, AO_t value)\n    {\n#     ifdef AO_T_IS_INT\n        (void)_InterlockedOr((long volatile *)p, value);\n#     else\n        (void)_InterlockedOr64((__int64 volatile *)p, value);\n#     endif\n    }\n#   define AO_HAVE_or_full\n\n    AO_INLINE void\n    AO_xor_full(volatile AO_t *p, AO_t value)\n    {\n#     ifdef AO_T_IS_INT\n        (void)_InterlockedXor((long volatile *)p, value);\n#     else\n        (void)_InterlockedXor64((__int64 volatile *)p, value);\n#     endif\n    }\n#   define AO_HAVE_xor_full\n# endif /* !AO_PREFER_GENERALIZED */\n\n# if !defined(AO_PREFER_GENERALIZED) && (defined(_M_ARM) || defined(_M_ARM64))\n#   pragma intrinsic (_InterlockedAnd8_acq)\n#   pragma intrinsic (_InterlockedAnd8_nf)\n#   pragma intrinsic (_InterlockedAnd8_rel)\n#   pragma intrinsic (_InterlockedOr8_acq)\n#   pragma intrinsic (_InterlockedOr8_nf)\n#   pragma intrinsic (_InterlockedOr8_rel)\n#   pragma intrinsic (_InterlockedXor8_acq)\n#   pragma intrinsic (_InterlockedXor8_nf)\n#   pragma intrinsic (_InterlockedXor8_rel)\n\n    AO_INLINE void\n    AO_char_and(volatile unsigned char *p, unsigned char value)\n    {\n      _InterlockedAnd8_nf((char volatile *)p, value);\n    }\n#   define AO_HAVE_char_and\n\n    AO_INLINE void\n    AO_char_or(volatile unsigned char *p, unsigned char value)\n    {\n      _InterlockedOr8_nf((char volatile *)p, value);\n    }\n#   define AO_HAVE_char_or\n\n    AO_INLINE void\n    AO_char_xor(volatile unsigned char *p, unsigned char value)\n    {\n      _InterlockedXor8_nf((char volatile *)p, value);\n    }\n#   define AO_HAVE_char_xor\n\n    AO_INLINE void\n    AO_char_and_acquire(volatile unsigned char *p, unsigned char value)\n    {\n      _InterlockedAnd8_acq((char volatile *)p, value);\n    }\n#   define AO_HAVE_char_and_acquire\n\n    AO_INLINE void\n    AO_char_or_acquire(volatile unsigned char *p, unsigned char value)\n    {\n      _InterlockedOr8_acq((char volatile *)p, value);\n    }\n#   define AO_HAVE_char_or_acquire\n\n    AO_INLINE void\n    AO_char_xor_acquire(volatile unsigned char *p, unsigned char value)\n    {\n      _InterlockedXor8_acq((char volatile *)p, value);\n    }\n#   define AO_HAVE_char_xor_acquire\n\n    AO_INLINE void\n    AO_char_and_release(volatile unsigned char *p, unsigned char value)\n    {\n      _InterlockedAnd8_rel((char volatile *)p, value);\n    }\n#   define AO_HAVE_char_and_release\n\n    AO_INLINE void\n    AO_char_or_release(volatile unsigned char *p, unsigned char value)\n    {\n      _InterlockedOr8_rel((char volatile *)p, value);\n    }\n#   define AO_HAVE_char_or_release\n\n    AO_INLINE void\n    AO_char_xor_release(volatile unsigned char *p, unsigned char value)\n    {\n      _InterlockedXor8_rel((char volatile *)p, value);\n    }\n#   define AO_HAVE_char_xor_release\n\n#   pragma intrinsic (_InterlockedAnd16_acq)\n#   pragma intrinsic (_InterlockedAnd16_nf)\n#   pragma intrinsic (_InterlockedAnd16_rel)\n#   pragma intrinsic (_InterlockedOr16_acq)\n#   pragma intrinsic (_InterlockedOr16_nf)\n#   pragma intrinsic (_InterlockedOr16_rel)\n#   pragma intrinsic (_InterlockedXor16_acq)\n#   pragma intrinsic (_InterlockedXor16_nf)\n#   pragma intrinsic (_InterlockedXor16_rel)\n\n    AO_INLINE void\n    AO_short_and(volatile unsigned short *p, unsigned short value)\n    {\n      (void)_InterlockedAnd16_nf((short volatile *)p, value);\n    }\n#   define AO_HAVE_short_and\n\n    AO_INLINE void\n    AO_short_or(volatile unsigned short *p, unsigned short value)\n    {\n      (void)_InterlockedOr16_nf((short volatile *)p, value);\n    }\n#   define AO_HAVE_short_or\n\n    AO_INLINE void\n    AO_short_xor(volatile unsigned short *p, unsigned short value)\n    {\n      (void)_InterlockedXor16_nf((short volatile *)p, value);\n    }\n#   define AO_HAVE_short_xor\n\n    AO_INLINE void\n    AO_short_and_acquire(volatile unsigned short *p, unsigned short value)\n    {\n      (void)_InterlockedAnd16_acq((short volatile *)p, value);\n    }\n#   define AO_HAVE_short_and_acquire\n\n    AO_INLINE void\n    AO_short_or_acquire(volatile unsigned short *p, unsigned short value)\n    {\n      (void)_InterlockedOr16_acq((short volatile *)p, value);\n    }\n#   define AO_HAVE_short_or_acquire\n\n    AO_INLINE void\n    AO_short_xor_acquire(volatile unsigned short *p, unsigned short value)\n    {\n      (void)_InterlockedXor16_acq((short volatile *)p, value);\n    }\n#   define AO_HAVE_short_xor_acquire\n\n    AO_INLINE void\n    AO_short_and_release(volatile unsigned short *p, unsigned short value)\n    {\n      (void)_InterlockedAnd16_rel((short volatile *)p, value);\n    }\n#   define AO_HAVE_short_and_release\n\n    AO_INLINE void\n    AO_short_or_release(volatile unsigned short *p, unsigned short value)\n    {\n      (void)_InterlockedOr16_rel((short volatile *)p, value);\n    }\n#   define AO_HAVE_short_or_release\n\n    AO_INLINE void\n    AO_short_xor_release(volatile unsigned short *p, unsigned short value)\n    {\n      (void)_InterlockedXor16_rel((short volatile *)p, value);\n    }\n#   define AO_HAVE_short_xor_release\n\n#   pragma intrinsic (_InterlockedAnd_acq)\n#   pragma intrinsic (_InterlockedAnd_nf)\n#   pragma intrinsic (_InterlockedAnd_rel)\n#   pragma intrinsic (_InterlockedOr_acq)\n#   pragma intrinsic (_InterlockedOr_nf)\n#   pragma intrinsic (_InterlockedOr_rel)\n#   pragma intrinsic (_InterlockedXor_acq)\n#   pragma intrinsic (_InterlockedXor_nf)\n#   pragma intrinsic (_InterlockedXor_rel)\n\n#   ifndef AO_T_IS_INT\n      AO_INLINE void\n      AO_int_and(volatile unsigned int *p, unsigned int value)\n      {\n        (void)_InterlockedAnd_nf((long volatile *)p, value);\n      }\n#     define AO_HAVE_int_and\n\n      AO_INLINE void\n      AO_int_or(volatile unsigned int *p, unsigned int value)\n      {\n        (void)_InterlockedOr_nf((long volatile *)p, value);\n      }\n#     define AO_HAVE_int_or\n\n      AO_INLINE void\n      AO_int_xor(volatile unsigned int *p, unsigned int value)\n      {\n        (void)_InterlockedXor_nf((long volatile *)p, value);\n      }\n#     define AO_HAVE_int_xor\n\n      AO_INLINE void\n      AO_int_and_acquire(volatile unsigned int *p, unsigned int value)\n      {\n        (void)_InterlockedAnd_acq((long volatile *)p, value);\n      }\n#     define AO_HAVE_int_and_acquire\n\n      AO_INLINE void\n      AO_int_or_acquire(volatile unsigned int *p, unsigned int value)\n      {\n        (void)_InterlockedOr_acq((long volatile *)p, value);\n      }\n#     define AO_HAVE_int_or_acquire\n\n      AO_INLINE void\n      AO_int_xor_acquire(volatile unsigned int *p, unsigned int value)\n      {\n        (void)_InterlockedXor_acq((long volatile *)p, value);\n      }\n#     define AO_HAVE_int_xor_acquire\n\n      AO_INLINE void\n      AO_int_and_release(volatile unsigned int *p, unsigned int value)\n      {\n        (void)_InterlockedAnd_rel((long volatile *)p, value);\n      }\n#     define AO_HAVE_int_and_release\n\n      AO_INLINE void\n      AO_int_or_release(volatile unsigned int *p, unsigned int value)\n      {\n        (void)_InterlockedOr_rel((long volatile *)p, value);\n      }\n#     define AO_HAVE_int_or_release\n\n      AO_INLINE void\n      AO_int_xor_release(volatile unsigned int *p, unsigned int value)\n      {\n        (void)_InterlockedXor_rel((long volatile *)p, value);\n      }\n#     define AO_HAVE_int_xor_release\n\n#     pragma intrinsic (_InterlockedAnd64_acq)\n#     pragma intrinsic (_InterlockedAnd64_nf)\n#     pragma intrinsic (_InterlockedAnd64_rel)\n#     pragma intrinsic (_InterlockedOr64_acq)\n#     pragma intrinsic (_InterlockedOr64_nf)\n#     pragma intrinsic (_InterlockedOr64_rel)\n#     pragma intrinsic (_InterlockedXor64_acq)\n#     pragma intrinsic (_InterlockedXor64_nf)\n#     pragma intrinsic (_InterlockedXor64_rel)\n#   endif /* !AO_T_IS_INT */\n\n    AO_INLINE void\n    AO_and(volatile AO_t *p, AO_t value)\n    {\n#     ifdef AO_T_IS_INT\n        (void)_InterlockedAnd_nf((long volatile *)p, value);\n#     else\n        (void)_InterlockedAnd64_nf((__int64 volatile *)p, value);\n#     endif\n    }\n#   define AO_HAVE_and\n\n    AO_INLINE void\n    AO_or(volatile AO_t *p, AO_t value)\n    {\n#     ifdef AO_T_IS_INT\n        (void)_InterlockedOr_nf((long volatile *)p, value);\n#     else\n        (void)_InterlockedOr64_nf((__int64 volatile *)p, value);\n#     endif\n    }\n#   define AO_HAVE_or\n\n    AO_INLINE void\n    AO_xor(volatile AO_t *p, AO_t value)\n    {\n#     ifdef AO_T_IS_INT\n        (void)_InterlockedXor_nf((long volatile *)p, value);\n#     else\n        (void)_InterlockedXor64_nf((__int64 volatile *)p, value);\n#     endif\n    }\n#   define AO_HAVE_xor\n\n    AO_INLINE void\n    AO_and_acquire(volatile AO_t *p, AO_t value)\n    {\n#     ifdef AO_T_IS_INT\n        (void)_InterlockedAnd_acq((long volatile *)p, value);\n#     else\n        (void)_InterlockedAnd64_acq((__int64 volatile *)p, value);\n#     endif\n    }\n#   define AO_HAVE_and_acquire\n\n    AO_INLINE void\n    AO_or_acquire(volatile AO_t *p, AO_t value)\n    {\n#     ifdef AO_T_IS_INT\n        (void)_InterlockedOr_acq((long volatile *)p, value);\n#     else\n        (void)_InterlockedOr64_acq((__int64 volatile *)p, value);\n#     endif\n    }\n#   define AO_HAVE_or_acquire\n\n    AO_INLINE void\n    AO_xor_acquire(volatile AO_t *p, AO_t value)\n    {\n#     ifdef AO_T_IS_INT\n        (void)_InterlockedXor_acq((long volatile *)p, value);\n#     else\n        (void)_InterlockedXor64_acq((__int64 volatile *)p, value);\n#     endif\n    }\n#   define AO_HAVE_xor_acquire\n\n    AO_INLINE void\n    AO_and_release(volatile AO_t *p, AO_t value)\n    {\n#     ifdef AO_T_IS_INT\n        (void)_InterlockedAnd_rel((long volatile *)p, value);\n#     else\n        (void)_InterlockedAnd64_rel((__int64 volatile *)p, value);\n#     endif\n    }\n#   define AO_HAVE_and_release\n\n    AO_INLINE void\n    AO_or_release(volatile AO_t *p, AO_t value)\n    {\n#     ifdef AO_T_IS_INT\n        (void)_InterlockedOr_rel((long volatile *)p, value);\n#     else\n        (void)_InterlockedOr64_rel((__int64 volatile *)p, value);\n#     endif\n    }\n#   define AO_HAVE_or_release\n\n    AO_INLINE void\n    AO_xor_release(volatile AO_t *p, AO_t value)\n    {\n#     ifdef AO_T_IS_INT\n        (void)_InterlockedXor_rel((long volatile *)p, value);\n#     else\n        (void)_InterlockedXor64_rel((__int64 volatile *)p, value);\n#     endif\n    }\n#   define AO_HAVE_xor_release\n\n#   pragma intrinsic (_InterlockedDecrement16_acq)\n#   pragma intrinsic (_InterlockedDecrement16_nf)\n#   pragma intrinsic (_InterlockedDecrement16_rel)\n#   pragma intrinsic (_InterlockedIncrement16_acq)\n#   pragma intrinsic (_InterlockedIncrement16_nf)\n#   pragma intrinsic (_InterlockedIncrement16_rel)\n\n    AO_INLINE unsigned short\n    AO_short_fetch_and_add1(volatile unsigned short *p)\n    {\n      return _InterlockedIncrement16_nf((short volatile *)p) - 1;\n    }\n#   define AO_HAVE_short_fetch_and_add1\n\n    AO_INLINE unsigned short\n    AO_short_fetch_and_sub1(volatile unsigned short *p)\n    {\n      return _InterlockedDecrement16_nf((short volatile *)p) + 1;\n    }\n#   define AO_HAVE_short_fetch_and_sub1\n\n    AO_INLINE unsigned short\n    AO_short_fetch_and_add1_acquire(volatile unsigned short *p)\n    {\n      return _InterlockedIncrement16_acq((short volatile *)p) - 1;\n    }\n#   define AO_HAVE_short_fetch_and_add1_acquire\n\n    AO_INLINE unsigned short\n    AO_short_fetch_and_sub1_acquire(volatile unsigned short *p)\n    {\n      return _InterlockedDecrement16_acq((short volatile *)p) + 1;\n    }\n#   define AO_HAVE_short_fetch_and_sub1_acquire\n\n    AO_INLINE unsigned short\n    AO_short_fetch_and_add1_release(volatile unsigned short *p)\n    {\n      return _InterlockedIncrement16_rel((short volatile *)p) - 1;\n    }\n#   define AO_HAVE_short_fetch_and_add1_release\n\n    AO_INLINE unsigned short\n    AO_short_fetch_and_sub1_release(volatile unsigned short *p)\n    {\n      return _InterlockedDecrement16_rel((short volatile *)p) + 1;\n    }\n#   define AO_HAVE_short_fetch_and_sub1_release\n\n#   pragma intrinsic (_InterlockedExchangeAdd_acq)\n#   pragma intrinsic (_InterlockedExchangeAdd_nf)\n#   pragma intrinsic (_InterlockedExchangeAdd_rel)\n\n#   pragma intrinsic (_InterlockedDecrement_acq)\n#   pragma intrinsic (_InterlockedDecrement_nf)\n#   pragma intrinsic (_InterlockedDecrement_rel)\n#   pragma intrinsic (_InterlockedIncrement_acq)\n#   pragma intrinsic (_InterlockedIncrement_nf)\n#   pragma intrinsic (_InterlockedIncrement_rel)\n\n#   ifndef AO_T_IS_INT\n#     pragma intrinsic (_InterlockedExchangeAdd64_acq)\n#     pragma intrinsic (_InterlockedExchangeAdd64_nf)\n#     pragma intrinsic (_InterlockedExchangeAdd64_rel)\n\n#     pragma intrinsic (_InterlockedDecrement64_acq)\n#     pragma intrinsic (_InterlockedDecrement64_nf)\n#     pragma intrinsic (_InterlockedDecrement64_rel)\n#     pragma intrinsic (_InterlockedIncrement64_acq)\n#     pragma intrinsic (_InterlockedIncrement64_nf)\n#     pragma intrinsic (_InterlockedIncrement64_rel)\n#   endif\n\n    AO_INLINE AO_t\n    AO_fetch_and_add(volatile AO_t *p, AO_t incr)\n    {\n#     ifdef AO_T_IS_INT\n        return _InterlockedExchangeAdd_nf((long volatile *)p, incr);\n#     else\n        return _InterlockedExchangeAdd64_nf((__int64 volatile *)p, incr);\n#     endif\n    }\n#   define AO_HAVE_fetch_and_add\n\n    AO_INLINE AO_t\n    AO_fetch_and_add1(volatile AO_t *p)\n    {\n#     ifdef AO_T_IS_INT\n        return _InterlockedIncrement_nf((long volatile *)p) - 1;\n#     else\n        return _InterlockedIncrement64_nf((__int64 volatile *)p) - 1;\n#     endif\n    }\n#   define AO_HAVE_fetch_and_add1\n\n    AO_INLINE AO_t\n    AO_fetch_and_sub1(volatile AO_t *p)\n    {\n#     ifdef AO_T_IS_INT\n        return _InterlockedDecrement_nf((long volatile *)p) + 1;\n#     else\n        return _InterlockedDecrement64_nf((__int64 volatile *)p) + 1;\n#     endif\n    }\n#   define AO_HAVE_fetch_and_sub1\n\n    AO_INLINE AO_t\n    AO_fetch_and_add_acquire(volatile AO_t *p, AO_t incr)\n    {\n#     ifdef AO_T_IS_INT\n        return _InterlockedExchangeAdd_acq((long volatile *)p, incr);\n#     else\n        return _InterlockedExchangeAdd64_acq((__int64 volatile *)p, incr);\n#     endif\n    }\n#   define AO_HAVE_fetch_and_add_acquire\n\n    AO_INLINE AO_t\n    AO_fetch_and_add1_acquire(volatile AO_t *p)\n    {\n#     ifdef AO_T_IS_INT\n        return _InterlockedIncrement_acq((long volatile *)p) - 1;\n#     else\n        return _InterlockedIncrement64_acq((__int64 volatile *)p) - 1;\n#     endif\n    }\n#   define AO_HAVE_fetch_and_add1_acquire\n\n    AO_INLINE AO_t\n    AO_fetch_and_sub1_acquire(volatile AO_t *p)\n    {\n#     ifdef AO_T_IS_INT\n        return _InterlockedDecrement_acq((long volatile *)p) + 1;\n#     else\n        return _InterlockedDecrement64_acq((__int64 volatile *)p) + 1;\n#     endif\n    }\n#   define AO_HAVE_fetch_and_sub1_acquire\n\n    AO_INLINE AO_t\n    AO_fetch_and_add_release(volatile AO_t *p, AO_t incr)\n    {\n#     ifdef AO_T_IS_INT\n        return _InterlockedExchangeAdd_rel((long volatile *)p, incr);\n#     else\n        return _InterlockedExchangeAdd64_rel((__int64 volatile *)p, incr);\n#     endif\n    }\n#   define AO_HAVE_fetch_and_add_release\n\n    AO_INLINE AO_t\n    AO_fetch_and_add1_release(volatile AO_t *p)\n    {\n#     ifdef AO_T_IS_INT\n        return _InterlockedIncrement_rel((long volatile *)p) - 1;\n#     else\n        return _InterlockedIncrement64_rel((__int64 volatile *)p) - 1;\n#     endif\n    }\n#   define AO_HAVE_fetch_and_add1_release\n\n    AO_INLINE AO_t\n    AO_fetch_and_sub1_release(volatile AO_t *p)\n    {\n#     ifdef AO_T_IS_INT\n        return _InterlockedDecrement_rel((long volatile *)p) + 1;\n#     else\n        return _InterlockedDecrement64_rel((__int64 volatile *)p) + 1;\n#     endif\n    }\n#   define AO_HAVE_fetch_and_sub1_release\n\n#   ifndef AO_T_IS_INT\n      AO_INLINE unsigned int\n      AO_int_fetch_and_add(volatile unsigned int *p, unsigned int incr)\n      {\n        return _InterlockedExchangeAdd_nf((long volatile *)p, incr);\n      }\n#     define AO_HAVE_int_fetch_and_add\n\n      AO_INLINE unsigned int\n      AO_int_fetch_and_add1(volatile unsigned int *p)\n      {\n        return _InterlockedIncrement_nf((long volatile *)p) - 1;\n      }\n#     define AO_HAVE_int_fetch_and_add1\n\n      AO_INLINE unsigned int\n      AO_int_fetch_and_sub1(volatile unsigned int *p)\n      {\n        return _InterlockedDecrement_nf((long volatile *)p) + 1;\n      }\n#     define AO_HAVE_int_fetch_and_sub1\n\n      AO_INLINE unsigned int\n      AO_int_fetch_and_add_acquire(volatile unsigned int *p,\n                                   unsigned int incr)\n      {\n        return _InterlockedExchangeAdd_acq((long volatile *)p, incr);\n      }\n#     define AO_HAVE_int_fetch_and_add_acquire\n\n      AO_INLINE unsigned int\n      AO_int_fetch_and_add1_acquire(volatile unsigned int *p)\n      {\n        return _InterlockedIncrement_acq((long volatile *)p) - 1;\n      }\n#     define AO_HAVE_int_fetch_and_add1_acquire\n\n      AO_INLINE unsigned int\n      AO_int_fetch_and_sub1_acquire(volatile unsigned int *p)\n      {\n        return _InterlockedDecrement_acq((long volatile *)p) + 1;\n      }\n#     define AO_HAVE_int_fetch_and_sub1_acquire\n\n      AO_INLINE unsigned int\n      AO_int_fetch_and_add_release(volatile unsigned int *p,\n                                   unsigned int incr)\n      {\n        return _InterlockedExchangeAdd_rel((long volatile *)p, incr);\n      }\n#     define AO_HAVE_int_fetch_and_add_release\n\n      AO_INLINE unsigned int\n      AO_int_fetch_and_add1_release(volatile unsigned int *p)\n      {\n        return _InterlockedIncrement_rel((long volatile *)p) - 1;\n      }\n#     define AO_HAVE_int_fetch_and_add1_release\n\n      AO_INLINE unsigned int\n      AO_int_fetch_and_sub1_release(volatile unsigned int *p)\n      {\n        return _InterlockedDecrement_rel((long volatile *)p) + 1;\n      }\n#     define AO_HAVE_int_fetch_and_sub1_release\n#   endif /* !AO_T_IS_INT */\n\n# endif /* !AO_PREFER_GENERALIZED && (_M_ARM || _M_ARM64) */\n\n# pragma intrinsic (_InterlockedCompareExchange8)\n\n  AO_INLINE unsigned char\n  AO_char_fetch_compare_and_swap_full(volatile unsigned char *addr,\n                                      unsigned char old_val,\n                                      unsigned char new_val)\n  {\n    return _InterlockedCompareExchange8((char volatile *)addr,\n                                        new_val, old_val);\n  }\n# define AO_HAVE_char_fetch_compare_and_swap_full\n\n# if defined(_M_ARM) || defined(_M_ARM64)\n\n#   pragma intrinsic (_InterlockedCompareExchange_acq)\n#   pragma intrinsic (_InterlockedCompareExchange_nf)\n#   pragma intrinsic (_InterlockedCompareExchange_rel)\n#   ifndef AO_T_IS_INT\n#     pragma intrinsic (_InterlockedCompareExchange64_acq)\n#     pragma intrinsic (_InterlockedCompareExchange64_nf)\n#     pragma intrinsic (_InterlockedCompareExchange64_rel)\n#   endif\n\n    AO_INLINE AO_t\n    AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val)\n    {\n#     ifdef AO_T_IS_INT\n        return _InterlockedCompareExchange_nf((long volatile *)addr,\n                                              new_val, old_val);\n#     else\n        return (AO_t)_InterlockedCompareExchange64_nf(\n                        (__int64 volatile *)addr, new_val, old_val);\n#     endif\n    }\n#   define AO_HAVE_fetch_compare_and_swap\n\n    AO_INLINE AO_t\n    AO_fetch_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val,\n                                      AO_t new_val)\n    {\n#     ifdef AO_T_IS_INT\n        return _InterlockedCompareExchange_acq((long volatile *)addr,\n                                               new_val, old_val);\n#     else\n        return (AO_t)_InterlockedCompareExchange64_acq(\n                        (__int64 volatile *)addr, new_val, old_val);\n#     endif\n    }\n#   define AO_HAVE_fetch_compare_and_swap_acquire\n\n    AO_INLINE AO_t\n    AO_fetch_compare_and_swap_release(volatile AO_t *addr, AO_t old_val,\n                                      AO_t new_val)\n    {\n#     ifdef AO_T_IS_INT\n        return _InterlockedCompareExchange_rel((long volatile *)addr,\n                                               new_val, old_val);\n#     else\n        return (AO_t)_InterlockedCompareExchange64_rel(\n                        (__int64 volatile *)addr, new_val, old_val);\n#     endif\n    }\n#   define AO_HAVE_fetch_compare_and_swap_release\n\n#   ifndef AO_T_IS_INT\n      AO_INLINE unsigned int\n      AO_int_fetch_compare_and_swap(volatile unsigned int *addr,\n                                    unsigned int old_val,\n                                    unsigned int new_val)\n      {\n        return _InterlockedCompareExchange_nf((long volatile *)addr,\n                                              new_val, old_val);\n      }\n#     define AO_HAVE_int_fetch_compare_and_swap\n\n      AO_INLINE unsigned int\n      AO_int_fetch_compare_and_swap_acquire(volatile unsigned int *addr,\n                                            unsigned int old_val,\n                                            unsigned int new_val)\n      {\n        return _InterlockedCompareExchange_acq((long volatile *)addr,\n                                               new_val, old_val);\n      }\n#     define AO_HAVE_int_fetch_compare_and_swap_acquire\n\n      AO_INLINE unsigned int\n      AO_int_fetch_compare_and_swap_release(volatile unsigned int *addr,\n                                            unsigned int old_val,\n                                            unsigned int new_val)\n      {\n        return _InterlockedCompareExchange_rel((long volatile *)addr,\n                                               new_val, old_val);\n      }\n#     define AO_HAVE_int_fetch_compare_and_swap_release\n#   endif /* !AO_T_IS_INT */\n\n#   pragma intrinsic (_InterlockedCompareExchange16_acq)\n#   pragma intrinsic (_InterlockedCompareExchange16_nf)\n#   pragma intrinsic (_InterlockedCompareExchange16_rel)\n#   pragma intrinsic (_InterlockedCompareExchange8_acq)\n#   pragma intrinsic (_InterlockedCompareExchange8_nf)\n#   pragma intrinsic (_InterlockedCompareExchange8_rel)\n\n    AO_INLINE unsigned short\n    AO_short_fetch_compare_and_swap(volatile unsigned short *addr,\n                                    unsigned short old_val,\n                                    unsigned short new_val)\n    {\n      return _InterlockedCompareExchange16_nf((short volatile *)addr,\n                                              new_val, old_val);\n    }\n#   define AO_HAVE_short_fetch_compare_and_swap\n\n    AO_INLINE unsigned short\n    AO_short_fetch_compare_and_swap_acquire(volatile unsigned short *addr,\n                                            unsigned short old_val,\n                                            unsigned short new_val)\n    {\n      return _InterlockedCompareExchange16_acq((short volatile *)addr,\n                                               new_val, old_val);\n    }\n#   define AO_HAVE_short_fetch_compare_and_swap_acquire\n\n    AO_INLINE unsigned short\n    AO_short_fetch_compare_and_swap_release(volatile unsigned short *addr,\n                                            unsigned short old_val,\n                                            unsigned short new_val)\n    {\n      return _InterlockedCompareExchange16_rel((short volatile *)addr,\n                                               new_val, old_val);\n    }\n#   define AO_HAVE_short_fetch_compare_and_swap_release\n\n    AO_INLINE unsigned char\n    AO_char_fetch_compare_and_swap(volatile unsigned char *addr,\n                                   unsigned char old_val,\n                                   unsigned char new_val)\n    {\n      return _InterlockedCompareExchange8_nf((char volatile *)addr,\n                                             new_val, old_val);\n    }\n#   define AO_HAVE_char_fetch_compare_and_swap\n\n    AO_INLINE unsigned char\n    AO_char_fetch_compare_and_swap_acquire(volatile unsigned char *addr,\n                                           unsigned char old_val,\n                                           unsigned char new_val)\n    {\n      return _InterlockedCompareExchange8_acq((char volatile *)addr,\n                                              new_val, old_val);\n    }\n#   define AO_HAVE_char_fetch_compare_and_swap_acquire\n\n    AO_INLINE unsigned char\n    AO_char_fetch_compare_and_swap_release(volatile unsigned char *addr,\n                                           unsigned char old_val,\n                                           unsigned char new_val)\n    {\n      return _InterlockedCompareExchange8_rel((char volatile *)addr,\n                                              new_val, old_val);\n    }\n#   define AO_HAVE_char_fetch_compare_and_swap_release\n# endif /* _M_ARM || _M_ARM64 */\n\n# if !defined(AO_PREFER_GENERALIZED) && !defined(_M_ARM)\n#   pragma intrinsic (_InterlockedExchangeAdd16)\n#   pragma intrinsic (_InterlockedExchangeAdd8)\n\n    AO_INLINE unsigned char\n    AO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr)\n    {\n      return _InterlockedExchangeAdd8((char volatile *)p, incr);\n    }\n#   define AO_HAVE_char_fetch_and_add_full\n\n    AO_INLINE unsigned short\n    AO_short_fetch_and_add_full(volatile unsigned short *p,\n                                unsigned short incr)\n    {\n      return _InterlockedExchangeAdd16((short volatile *)p, incr);\n    }\n#   define AO_HAVE_short_fetch_and_add_full\n\n#   if defined(_M_ARM64)\n#     pragma intrinsic (_InterlockedExchangeAdd16_acq)\n#     pragma intrinsic (_InterlockedExchangeAdd16_nf)\n#     pragma intrinsic (_InterlockedExchangeAdd16_rel)\n#     pragma intrinsic (_InterlockedExchangeAdd8_acq)\n#     pragma intrinsic (_InterlockedExchangeAdd8_nf)\n#     pragma intrinsic (_InterlockedExchangeAdd8_rel)\n\n      AO_INLINE unsigned char\n      AO_char_fetch_and_add(volatile unsigned char *p, unsigned char incr)\n      {\n        return _InterlockedExchangeAdd8_nf((char volatile *)p, incr);\n      }\n#     define AO_HAVE_char_fetch_and_add\n\n      AO_INLINE unsigned short\n      AO_short_fetch_and_add(volatile unsigned short *p, unsigned short incr)\n      {\n        return _InterlockedExchangeAdd16_nf((short volatile *)p, incr);\n      }\n#     define AO_HAVE_short_fetch_and_add\n\n      AO_INLINE unsigned char\n      AO_char_fetch_and_add_acquire(volatile unsigned char *p,\n                                    unsigned char incr)\n      {\n        return _InterlockedExchangeAdd8_acq((char volatile *)p, incr);\n      }\n#     define AO_HAVE_char_fetch_and_add_acquire\n\n      AO_INLINE unsigned short\n      AO_short_fetch_and_add_acquire(volatile unsigned short *p,\n                                     unsigned short incr)\n      {\n        return _InterlockedExchangeAdd16_acq((short volatile *)p, incr);\n      }\n#     define AO_HAVE_short_fetch_and_add_acquire\n\n      AO_INLINE unsigned char\n      AO_char_fetch_and_add_release(volatile unsigned char *p,\n                                    unsigned char incr)\n      {\n        return _InterlockedExchangeAdd8_rel((char volatile *)p, incr);\n      }\n#     define AO_HAVE_char_fetch_and_add_release\n\n      AO_INLINE unsigned short\n      AO_short_fetch_and_add_release(volatile unsigned short *p,\n                                     unsigned short incr)\n      {\n        return _InterlockedExchangeAdd16_rel((short volatile *)p, incr);\n      }\n#     define AO_HAVE_short_fetch_and_add_release\n#   endif /* _M_ARM64 */\n\n# endif /* !AO_PREFER_GENERALIZED && !_M_ARM */\n\n# if !defined(_M_ARM) || _M_ARM >= 6\n#   include \"../test_and_set_t_is_char.h\"\n\n#   pragma intrinsic (_InterlockedExchange8)\n\n    AO_INLINE AO_TS_VAL_t\n    AO_test_and_set_full(volatile AO_TS_t *addr)\n    {\n      return (AO_TS_VAL_t)(_InterlockedExchange8((char volatile *)addr,\n                                                 (AO_TS_t)AO_TS_SET) & 0xff);\n      /* Note: bitwise \"and 0xff\" is applied to the result because cast */\n      /* to unsigned char does not work properly (for a reason) if /J   */\n      /* option is passed to the MS VC compiler.                        */\n    }\n#   define AO_HAVE_test_and_set_full\n# endif /* !_M_ARM || _M_ARM >= 6 */\n\n# if _M_ARM >= 6 || defined(_M_ARM64)\n#   pragma intrinsic (_InterlockedExchange8_acq)\n#   pragma intrinsic (_InterlockedExchange8_nf)\n#   pragma intrinsic (_InterlockedExchange8_rel)\n\n    AO_INLINE AO_TS_VAL_t\n    AO_test_and_set(volatile AO_TS_t *addr)\n    {\n      return (AO_TS_VAL_t)(_InterlockedExchange8_nf((char volatile *)addr,\n                                                (AO_TS_t)AO_TS_SET) & 0xff);\n    }\n#   define AO_HAVE_test_and_set\n\n    AO_INLINE AO_TS_VAL_t\n    AO_test_and_set_acquire(volatile AO_TS_t *addr)\n    {\n      return (AO_TS_VAL_t)(_InterlockedExchange8_acq((char volatile *)addr,\n                                                (AO_TS_t)AO_TS_SET) & 0xff);\n    }\n#   define AO_HAVE_test_and_set_acquire\n\n    AO_INLINE AO_TS_VAL_t\n    AO_test_and_set_release(volatile AO_TS_t *addr)\n    {\n      return (AO_TS_VAL_t)(_InterlockedExchange8_rel((char volatile *)addr,\n                                                (AO_TS_t)AO_TS_SET) & 0xff);\n    }\n#   define AO_HAVE_test_and_set_release\n# endif /* _M_ARM >= 6 || _M_ARM64 */\n\n#endif /* _MSC_VER >= 1800 */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/msftc/x86.h",
    "content": "/*\n * Copyright (c) 2003 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2009-2021 Ivan Maidanski\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#include \"../all_aligned_atomic_load_store.h\"\n\n#if !defined(AO_ASSUME_VISTA) && _MSC_VER >= 1910\n  /* Visual Studio 2017 (15.0) discontinued support of Windows XP.  */\n  /* We assume Windows Server 2003, Vista or later.                 */\n# define AO_ASSUME_VISTA\n#endif\n\n#if !defined(AO_ASSUME_WINDOWS98) \\\n    && (defined(AO_ASSUME_VISTA) || _MSC_VER >= 1400)\n   /* Visual Studio 2005 (MS VC++ 8.0) discontinued support of Windows 95. */\n# define AO_ASSUME_WINDOWS98\n#endif\n\n#if !defined(AO_USE_PENTIUM4_INSTRS) && _M_IX86_FP >= 2 /* SSE2 */\n  /* \"mfence\" is a part of SSE2 set (introduced on Intel Pentium 4).    */\n# define AO_USE_PENTIUM4_INSTRS\n#endif\n\n#define AO_T_IS_INT\n\n#ifndef AO_USE_INTERLOCKED_INTRINSICS\n  /* _Interlocked primitives (Inc, Dec, Xchg, Add) are always available */\n# define AO_USE_INTERLOCKED_INTRINSICS\n#endif\n#include \"common32_defs.h\"\n\n/* As far as we can tell, the lfence and sfence instructions are not    */\n/* currently needed or useful for cached memory accesses.               */\n\n/* Unfortunately mfence doesn't exist everywhere.               */\n/* IsProcessorFeaturePresent(PF_COMPARE_EXCHANGE128) is         */\n/* probably a conservative test for it?                         */\n\n#if defined(AO_USE_PENTIUM4_INSTRS)\n\nAO_INLINE void\nAO_nop_full(void)\n{\n  __asm { mfence }\n}\n#define AO_HAVE_nop_full\n\n#else\n\n/* We could use the cpuid instruction.  But that seems to be slower     */\n/* than the default implementation based on test_and_set_full.  Thus    */\n/* we omit that bit of misinformation here.                             */\n\n#endif\n\n#if !defined(AO_NO_ASM_XADD) && !defined(AO_HAVE_char_fetch_and_add_full)\n  AO_INLINE unsigned char\n  AO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr)\n  {\n    __asm\n    {\n      mov al, incr\n      mov ebx, p\n      lock xadd byte ptr [ebx], al\n    }\n    /* Ignore possible \"missing return value\" warning here.     */\n  }\n# define AO_HAVE_char_fetch_and_add_full\n\n  AO_INLINE unsigned short\n  AO_short_fetch_and_add_full(volatile unsigned short *p, unsigned short incr)\n  {\n    __asm\n    {\n      mov ax, incr\n      mov ebx, p\n      lock xadd word ptr [ebx], ax\n    }\n    /* Ignore possible \"missing return value\" warning here.     */\n  }\n# define AO_HAVE_short_fetch_and_add_full\n#endif /* !AO_NO_ASM_XADD */\n\n#ifndef AO_HAVE_test_and_set_full\n# include \"../test_and_set_t_is_char.h\"\n\n  AO_INLINE AO_TS_VAL_t\n  AO_test_and_set_full(volatile AO_TS_t *addr)\n  {\n    __asm\n    {\n        mov     eax,0xff                ; /* AO_TS_SET */\n        mov     ebx,addr                ;\n        xchg    byte ptr [ebx],al       ;\n    }\n    /* Ignore possible \"missing return value\" warning here. */\n  }\n# define AO_HAVE_test_and_set_full\n#endif\n\n#if defined(_WIN64) && !defined(CPPCHECK)\n# error wrong architecture\n#endif\n\n#ifdef AO_ASSUME_VISTA\n# include \"../standard_ao_double_t.h\"\n\n  /* Reading or writing a quadword aligned on a 64-bit boundary is      */\n  /* always carried out atomically (requires at least a Pentium).       */\n# define AO_ACCESS_double_CHECK_ALIGNED\n# include \"../loadstore/double_atomic_load_store.h\"\n\n  /* Whenever we run on a Pentium class machine, we have that certain   */\n  /* function.                                                          */\n# pragma intrinsic (_InterlockedCompareExchange64)\n\n  /* Returns nonzero if the comparison succeeded.       */\n  AO_INLINE int\n  AO_double_compare_and_swap_full(volatile AO_double_t *addr,\n                                  AO_double_t old_val, AO_double_t new_val)\n  {\n    AO_ASSERT_ADDR_ALIGNED(addr);\n    return (double_ptr_storage)_InterlockedCompareExchange64(\n                                        (__int64 volatile *)addr,\n                                        new_val.AO_whole /* exchange */,\n                                        old_val.AO_whole) == old_val.AO_whole;\n  }\n# define AO_HAVE_double_compare_and_swap_full\n#endif /* AO_ASSUME_VISTA */\n\n/* Real X86 implementations, except for some old WinChips, appear       */\n/* to enforce ordering between memory operations, EXCEPT that a later   */\n/* read can pass earlier writes, presumably due to the visible          */\n/* presence of store buffers.                                           */\n/* We ignore both the WinChips, and the fact that the official specs    */\n/* seem to be much weaker (and arguably too weak to be usable).         */\n#include \"../ordered_except_wr.h\"\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/msftc/x86_64.h",
    "content": "/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2009-2021 Ivan Maidanski\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#include \"../all_aligned_atomic_load_store.h\"\n\n/* Real X86 implementations appear                                      */\n/* to enforce ordering between memory operations, EXCEPT that a later   */\n/* read can pass earlier writes, presumably due to the visible          */\n/* presence of store buffers.                                           */\n/* We ignore the fact that the official specs                           */\n/* seem to be much weaker (and arguably too weak to be usable).         */\n#include \"../ordered_except_wr.h\"\n\n#ifndef AO_ASSUME_WINDOWS98\n  /* CAS is always available */\n# define AO_ASSUME_WINDOWS98\n#endif\n#ifndef AO_USE_INTERLOCKED_INTRINSICS\n# define AO_USE_INTERLOCKED_INTRINSICS\n#endif\n#include \"common32_defs.h\"\n\n#ifdef AO_ASM_X64_AVAILABLE\n\n#if _MSC_VER < 1800\n  AO_INLINE unsigned char\n  AO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr)\n  {\n    __asm\n    {\n      mov al, incr\n      mov rbx, p\n      lock xadd byte ptr [rbx], al\n    }\n  }\n# define AO_HAVE_char_fetch_and_add_full\n\n  AO_INLINE unsigned short\n  AO_short_fetch_and_add_full(volatile unsigned short *p, unsigned short incr)\n  {\n    __asm\n    {\n      mov ax, incr\n      mov rbx, p\n      lock xadd word ptr [rbx], ax\n    }\n  }\n# define AO_HAVE_short_fetch_and_add_full\n#endif /* _MSC_VER < 1800 */\n\n  /* As far as we can tell, the lfence and sfence instructions are not  */\n  /* currently needed or useful for cached memory accesses.             */\n\n  AO_INLINE void\n  AO_nop_full(void)\n  {\n    /* Note: \"mfence\" (SSE2) is supported on all x86_64/amd64 chips.    */\n    __asm { mfence }\n  }\n# define AO_HAVE_nop_full\n\n# ifndef AO_HAVE_test_and_set_full\n#   include \"../test_and_set_t_is_char.h\"\n\n    AO_INLINE AO_TS_VAL_t\n    AO_test_and_set_full(volatile AO_TS_t *addr)\n    {\n      __asm\n      {\n        mov     rax,AO_TS_SET           ;\n        mov     rbx,addr                ;\n        xchg    byte ptr [rbx],al       ;\n      }\n    }\n#   define AO_HAVE_test_and_set_full\n# endif\n\n#endif /* AO_ASM_X64_AVAILABLE */\n\n#ifndef AO_HAVE_test_and_set_full\n# include \"../test_and_set_t_is_ao_t.h\"\n  /* AO_test_and_set_full() is emulated using word-wide CAS.    */\n#endif\n\n#ifdef AO_CMPXCHG16B_AVAILABLE\n\n# if _MSC_VER >= 1500\n#   include \"../standard_ao_double_t.h\"\n#   pragma intrinsic (_InterlockedCompareExchange128)\n\n    AO_INLINE int\n    AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,\n                                           AO_t old_val1, AO_t old_val2,\n                                           AO_t new_val1, AO_t new_val2)\n    {\n      __int64 comparandResult[2];\n\n      AO_ASSERT_ADDR_ALIGNED(addr);\n      comparandResult[0] = old_val1; /* low */\n      comparandResult[1] = old_val2; /* high */\n      return _InterlockedCompareExchange128((volatile __int64 *)addr,\n                                            new_val2 /* high */,\n                                            new_val1 /* low */,\n                                            comparandResult);\n    }\n#   define AO_HAVE_compare_double_and_swap_double_full\n\n# elif defined(AO_ASM_X64_AVAILABLE)\n#   include \"../standard_ao_double_t.h\"\n\n    /* If there is no intrinsic _InterlockedCompareExchange128 then we  */\n    /* need basically what's given below.                               */\n    AO_INLINE int\n    AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,\n                                           AO_t old_val1, AO_t old_val2,\n                                           AO_t new_val1, AO_t new_val2)\n    {\n        __asm\n        {\n                mov     rdx,QWORD PTR [old_val2]        ;\n                mov     rax,QWORD PTR [old_val1]        ;\n                mov     rcx,QWORD PTR [new_val2]        ;\n                mov     rbx,QWORD PTR [new_val1]        ;\n                lock cmpxchg16b [addr]                  ;\n                setz    rax                             ;\n        }\n    }\n#   define AO_HAVE_compare_double_and_swap_double_full\n# endif /* AO_ASM_X64_AVAILABLE && (_MSC_VER < 1500) */\n\n#endif /* AO_CMPXCHG16B_AVAILABLE */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/ordered.h",
    "content": "/*\n * Copyright (c) 2003 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* These are common definitions for architectures that provide  */\n/* processor ordered memory operations.                         */\n\n#include \"ordered_except_wr.h\"\n\nAO_INLINE void\nAO_nop_full(void)\n{\n  AO_compiler_barrier();\n}\n#define AO_HAVE_nop_full\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/ordered_except_wr.h",
    "content": "/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/*\n * These are common definitions for architectures that provide processor\n * ordered memory operations except that a later read may pass an\n * earlier write.  Real x86 implementations seem to be in this category,\n * except apparently for some IDT WinChips, which we ignore.\n */\n\n#include \"read_ordered.h\"\n\nAO_INLINE void\nAO_nop_write(void)\n{\n  /* AO_nop_write implementation is the same as of AO_nop_read. */\n  AO_compiler_barrier();\n  /* sfence according to Intel docs.  Pentium 3 and up. */\n  /* Unnecessary for cached accesses?                   */\n}\n#define AO_HAVE_nop_write\n\n#include \"loadstore/ordered_stores_only.h\"\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/read_ordered.h",
    "content": "/*\n * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/*\n * These are common definitions for architectures that provide processor\n * ordered memory operations except that a later read may pass an\n * earlier write.  Real x86 implementations seem to be in this category,\n * except apparently for some IDT WinChips, which we ignore.\n */\n\nAO_INLINE void\nAO_nop_read(void)\n{\n  AO_compiler_barrier();\n}\n#define AO_HAVE_nop_read\n\n#include \"loadstore/ordered_loads_only.h\"\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/standard_ao_double_t.h",
    "content": "/*\n * Copyright (c) 2004-2011 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2012-2021 Ivan Maidanski\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* For 64-bit systems, we expect the double type to hold two int64's.   */\n\n#if (((defined(__x86_64__) && defined(AO_GCC_ATOMIC_TEST_AND_SET)) \\\n      || defined(__aarch64__)) && !defined(__ILP32__)) \\\n    || (defined(__e2k__) && __SIZEOF_SIZE_T__ == 8) \\\n    || (defined(__riscv) && __riscv_xlen == 64)\n  /* x86-64: __m128 is not applicable to atomic intrinsics.     */\n# if AO_GNUC_PREREQ(4, 7) || AO_CLANG_PREREQ(3, 6)\n#   pragma GCC diagnostic push\n    /* Suppress warning about __int128 type.      */\n#   if defined(__clang__) || AO_GNUC_PREREQ(6, 0)\n#     pragma GCC diagnostic ignored \"-Wpedantic\"\n#   else\n      /* GCC before ~4.8 does not accept \"-Wpedantic\" quietly.  */\n#     pragma GCC diagnostic ignored \"-pedantic\"\n#   endif\n    typedef unsigned __int128 double_ptr_storage;\n#   pragma GCC diagnostic pop\n# else /* pragma diagnostic is not supported */\n    typedef unsigned __int128 double_ptr_storage;\n# endif\n#elif defined(_M_ARM64) && defined(_MSC_VER)\n  /* __int128 does not seem to be available.    */\n  typedef __declspec(align(16)) unsigned __int64 double_ptr_storage[2];\n#elif ((defined(__x86_64__) && AO_GNUC_PREREQ(4, 0)) || defined(_WIN64)) \\\n      && !defined(__ILP32__)\n  /* x86-64 (except for x32): __m128 serves as a placeholder which also */\n  /* requires the compiler to align it on 16-byte boundary (as required */\n  /* by cmpxchg16b).                                                    */\n  /* Similar things could be done for PPC 64-bit using a VMX data type. */\n# include <xmmintrin.h>\n  typedef __m128 double_ptr_storage;\n#elif defined(_WIN32) && !defined(__GNUC__)\n  typedef unsigned __int64 double_ptr_storage;\n#elif defined(__i386__) && defined(__GNUC__)\n  typedef unsigned long long double_ptr_storage\n                                __attribute__((__aligned__(8)));\n#else\n  typedef unsigned long long double_ptr_storage;\n#endif\n# define AO_HAVE_DOUBLE_PTR_STORAGE\n\ntypedef union {\n    struct { AO_t AO_v1; AO_t AO_v2; } AO_parts;\n        /* Note that AO_v1 corresponds to the low or the high part of   */\n        /* AO_whole depending on the machine endianness.                */\n    double_ptr_storage AO_whole;\n        /* AO_whole is now (starting from v7.3alpha3) the 2nd element   */\n        /* of this union to make AO_DOUBLE_T_INITIALIZER portable       */\n        /* (because __m128 definition could vary from a primitive type  */\n        /* to a structure or array/vector).                             */\n} AO_double_t;\n#define AO_HAVE_double_t\n\n/* Note: AO_double_t volatile variables are not intended to be local    */\n/* ones (at least those which are passed to AO double-wide primitives   */\n/* as the first argument), otherwise it is the client responsibility to */\n/* ensure they have double-word alignment.                              */\n\n/* Dummy declaration as a compile-time assertion for AO_double_t size.  */\nstruct AO_double_t_size_static_assert {\n    char dummy[sizeof(AO_double_t) == 2 * sizeof(AO_t) ? 1 : -1];\n};\n\n#define AO_DOUBLE_T_INITIALIZER { { (AO_t)0, (AO_t)0 } }\n\n#define AO_val1 AO_parts.AO_v1\n#define AO_val2 AO_parts.AO_v2\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/sunc/sparc.S",
    "content": "        .seg    \"text\"\n        .globl  AO_test_and_set_full\nAO_test_and_set_full:\n        retl\n          ldstub        [%o0],%o0\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/sunc/sparc.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#include \"../all_atomic_load_store.h\"\n\n/* Real SPARC code uses TSO:                            */\n#include \"../ordered_except_wr.h\"\n\n/* Test_and_set location is just a byte.                */\n#include \"../test_and_set_t_is_char.h\"\n\n#ifdef __cplusplus\n  extern \"C\" {\n#endif\n\nextern AO_TS_VAL_t\nAO_test_and_set_full(volatile AO_TS_t *addr);\n/* Implemented in separate .S file, for now.    */\n#define AO_HAVE_test_and_set_full\n\n/* TODO: Like the gcc version, extend this for V8 and V9.   */\n\n#ifdef __cplusplus\n  } /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/sunc/x86.h",
    "content": "/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved.\n * Copyright (c) 2009-2016 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n *\n * Some of the machine specific code was borrowed from our GC distribution.\n */\n\n/* The following really assume we have a 486 or better.                 */\n\n#include \"../all_aligned_atomic_load_store.h\"\n\n#include \"../test_and_set_t_is_char.h\"\n\n#if !defined(AO_USE_PENTIUM4_INSTRS) && !defined(__i386)\n  /* \"mfence\" (SSE2) is supported on all x86_64/amd64 chips.            */\n# define AO_USE_PENTIUM4_INSTRS\n#endif\n\n#if defined(AO_USE_PENTIUM4_INSTRS)\n  AO_INLINE void\n  AO_nop_full(void)\n  {\n    __asm__ __volatile__ (\"mfence\" : : : \"memory\");\n  }\n# define AO_HAVE_nop_full\n\n#else\n  /* We could use the cpuid instruction.  But that seems to be slower   */\n  /* than the default implementation based on test_and_set_full.  Thus  */\n  /* we omit that bit of misinformation here.                           */\n#endif /* !AO_USE_PENTIUM4_INSTRS */\n\n/* As far as we can tell, the lfence and sfence instructions are not    */\n/* currently needed or useful for cached memory accesses.               */\n\n/* Really only works for 486 and later */\n#ifndef AO_PREFER_GENERALIZED\n  AO_INLINE AO_t\n  AO_fetch_and_add_full (volatile AO_t *p, AO_t incr)\n  {\n    AO_t result;\n\n    __asm__ __volatile__ (\"lock; xadd %0, %1\"\n                        : \"=r\" (result), \"+m\" (*p)\n                        : \"0\" (incr)\n                        : \"memory\");\n    return result;\n  }\n# define AO_HAVE_fetch_and_add_full\n#endif /* !AO_PREFER_GENERALIZED */\n\nAO_INLINE unsigned char\nAO_char_fetch_and_add_full (volatile unsigned char *p, unsigned char incr)\n{\n  unsigned char result;\n\n  __asm__ __volatile__ (\"lock; xaddb %0, %1\"\n                        : \"=q\" (result), \"+m\" (*p)\n                        : \"0\" (incr)\n                        : \"memory\");\n  return result;\n}\n#define AO_HAVE_char_fetch_and_add_full\n\nAO_INLINE unsigned short\nAO_short_fetch_and_add_full (volatile unsigned short *p, unsigned short incr)\n{\n  unsigned short result;\n\n  __asm__ __volatile__ (\"lock; xaddw %0, %1\"\n                        : \"=r\" (result), \"+m\" (*p)\n                        : \"0\" (incr)\n                        : \"memory\");\n  return result;\n}\n#define AO_HAVE_short_fetch_and_add_full\n\n#ifndef AO_PREFER_GENERALIZED\n  AO_INLINE void\n  AO_and_full (volatile AO_t *p, AO_t value)\n  {\n    __asm__ __volatile__ (\"lock; and %1, %0\"\n                        : \"+m\" (*p)\n                        : \"r\" (value)\n                        : \"memory\");\n  }\n# define AO_HAVE_and_full\n\n  AO_INLINE void\n  AO_or_full (volatile AO_t *p, AO_t value)\n  {\n    __asm__ __volatile__ (\"lock; or %1, %0\"\n                        : \"+m\" (*p)\n                        : \"r\" (value)\n                        : \"memory\");\n  }\n# define AO_HAVE_or_full\n\n  AO_INLINE void\n  AO_xor_full (volatile AO_t *p, AO_t value)\n  {\n    __asm__ __volatile__ (\"lock; xor %1, %0\"\n                        : \"+m\" (*p)\n                        : \"r\" (value)\n                        : \"memory\");\n  }\n# define AO_HAVE_xor_full\n#endif /* !AO_PREFER_GENERALIZED */\n\nAO_INLINE AO_TS_VAL_t\nAO_test_and_set_full (volatile AO_TS_t *addr)\n{\n  AO_TS_t oldval;\n  /* Note: the \"xchg\" instruction does not need a \"lock\" prefix */\n  __asm__ __volatile__ (\"xchg %b0, %1\"\n                        : \"=q\" (oldval), \"+m\" (*addr)\n                        : \"0\" (0xff)\n                        : \"memory\");\n  return (AO_TS_VAL_t)oldval;\n}\n#define AO_HAVE_test_and_set_full\n\n#ifndef AO_GENERALIZE_ASM_BOOL_CAS\n  /* Returns nonzero if the comparison succeeded.       */\n  AO_INLINE int\n  AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val)\n  {\n    char result;\n    __asm__ __volatile__ (\"lock; cmpxchg %2, %0; setz %1\"\n                        : \"+m\" (*addr), \"=a\" (result)\n                        : \"r\" (new_val), \"a\" (old)\n                        : \"memory\");\n    return (int) result;\n  }\n# define AO_HAVE_compare_and_swap_full\n#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */\n\nAO_INLINE AO_t\nAO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val,\n                               AO_t new_val)\n{\n  AO_t fetched_val;\n  __asm__ __volatile__ (\"lock; cmpxchg %2, %0\"\n                        : \"+m\" (*addr), \"=a\" (fetched_val)\n                        : \"r\" (new_val), \"a\" (old_val)\n                        : \"memory\");\n  return fetched_val;\n}\n#define AO_HAVE_fetch_compare_and_swap_full\n\n#if defined(__i386)\n\n# ifndef AO_NO_CMPXCHG8B\n#   include \"../standard_ao_double_t.h\"\n\n    /* Reading or writing a quadword aligned on a 64-bit boundary is    */\n    /* always carried out atomically (requires at least a Pentium).     */\n#   define AO_ACCESS_double_CHECK_ALIGNED\n#   include \"../loadstore/double_atomic_load_store.h\"\n\n    /* Returns nonzero if the comparison succeeded.     */\n    /* Really requires at least a Pentium.              */\n    AO_INLINE int\n    AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,\n                                           AO_t old_val1, AO_t old_val2,\n                                           AO_t new_val1, AO_t new_val2)\n    {\n      AO_t dummy;   /* an output for clobbered edx */\n      char result;\n\n      __asm__ __volatile__ (\"lock; cmpxchg8b %0; setz %1\"\n                        : \"+m\" (*addr), \"=a\" (result), \"=d\" (dummy)\n                        : \"d\" (old_val2), \"a\" (old_val1),\n                          \"c\" (new_val2), \"b\" (new_val1)\n                        : \"memory\");\n      return (int) result;\n    }\n#   define AO_HAVE_compare_double_and_swap_double_full\n# endif /* !AO_NO_CMPXCHG8B */\n\n# define AO_T_IS_INT\n\n#else /* x64 */\n\n  AO_INLINE unsigned int\n  AO_int_fetch_and_add_full (volatile unsigned int *p, unsigned int incr)\n  {\n    unsigned int result;\n\n    __asm__ __volatile__ (\"lock; xaddl %0, %1\"\n                        : \"=r\" (result), \"+m\" (*p)\n                        : \"0\" (incr)\n                        : \"memory\");\n    return result;\n  }\n# define AO_HAVE_int_fetch_and_add_full\n\n# ifdef AO_CMPXCHG16B_AVAILABLE\n#   include \"../standard_ao_double_t.h\"\n\n    /* Older AMD Opterons are missing this instruction (SIGILL should   */\n    /* be thrown in this case).                                         */\n    AO_INLINE int\n    AO_compare_double_and_swap_double_full (volatile AO_double_t *addr,\n                                            AO_t old_val1, AO_t old_val2,\n                                            AO_t new_val1, AO_t new_val2)\n    {\n      AO_t dummy;\n      char result;\n\n      __asm__ __volatile__ (\"lock; cmpxchg16b %0; setz %1\"\n                        : \"+m\" (*addr), \"=a\" (result), \"=d\" (dummy)\n                        : \"d\" (old_val2), \"a\" (old_val1),\n                          \"c\" (new_val2), \"b\" (new_val1)\n                        : \"memory\");\n      return (int) result;\n    }\n#   define AO_HAVE_compare_double_and_swap_double_full\n# endif /* !AO_CMPXCHG16B_AVAILABLE */\n\n#endif /* x64 */\n\n/* Real X86 implementations, except for some old 32-bit WinChips,       */\n/* appear to enforce ordering between memory operations, EXCEPT that    */\n/* a later read can pass earlier writes, presumably due to the visible  */\n/* presence of store buffers.                                           */\n/* We ignore both the WinChips and the fact that the official specs     */\n/* seem to be much weaker (and arguably too weak to be usable).         */\n#include \"../ordered_except_wr.h\"\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/test_and_set_t_is_ao_t.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/*\n * These are common definitions for architectures on which test_and_set\n * operates on pointer-sized quantities, the \"clear\" value contains\n * all zeroes, and the \"set\" value contains only one lowest bit set.\n * This can be used if test_and_set is synthesized from compare_and_swap.\n */\ntypedef enum {AO_TS_clear = 0, AO_TS_set = 1} AO_TS_val;\n#define AO_TS_VAL_t AO_TS_val\n#define AO_TS_CLEAR AO_TS_clear\n#define AO_TS_SET AO_TS_set\n\n#define AO_TS_t AO_t\n\n#define AO_AO_TS_T 1\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops/sysdeps/test_and_set_t_is_char.h",
    "content": "/*\n * Copyright (c) 2004 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/*\n * These are common definitions for architectures on which test_and_set\n * operates on byte sized quantities, the \"clear\" value contains\n * all zeroes, and the \"set\" value contains all ones typically.\n */\n\n#ifndef AO_GCC_ATOMIC_TEST_AND_SET\n# define AO_TS_SET_TRUEVAL 0xff\n#elif defined(__GCC_ATOMIC_TEST_AND_SET_TRUEVAL) \\\n      && !defined(AO_PREFER_GENERALIZED)\n# define AO_TS_SET_TRUEVAL __GCC_ATOMIC_TEST_AND_SET_TRUEVAL\n#else\n# define AO_TS_SET_TRUEVAL 1 /* true */\n#endif\n\ntypedef enum {\n  AO_BYTE_TS_clear = 0,\n  AO_BYTE_TS_set = AO_TS_SET_TRUEVAL\n} AO_BYTE_TS_val;\n\n#define AO_TS_VAL_t AO_BYTE_TS_val\n#define AO_TS_CLEAR AO_BYTE_TS_clear\n#define AO_TS_SET AO_BYTE_TS_set\n\n#define AO_TS_t unsigned char\n\n#define AO_CHAR_TS_T 1\n\n#undef AO_TS_SET_TRUEVAL\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops.c",
    "content": "/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/*\n * Initialized data and out-of-line functions to support atomic_ops.h\n * go here.  Currently this is needed only for pthread-based atomics\n * emulation, or for compare-and-swap emulation.\n * Pthreads emulation isn't useful on a native Windows platform, and\n * cas emulation is not needed.  Thus we skip this on Windows.\n */\n\n#if defined(HAVE_CONFIG_H)\n# include \"config.h\"\n#endif\n\n#if (defined(__hexagon__) || defined(__native_client__)) \\\n    && !defined(AO_USE_NO_SIGNALS) && !defined(AO_USE_NANOSLEEP)\n  /* Hexagon QuRT does not have sigprocmask (but Hexagon does not need  */\n  /* emulation, so it is OK not to bother about signals blocking).      */\n  /* Since NaCl is not recognized by configure yet, we do it here.      */\n# define AO_USE_NO_SIGNALS\n# define AO_USE_NANOSLEEP\n#endif\n\n#if defined(AO_USE_WIN32_PTHREADS) && !defined(AO_USE_NO_SIGNALS)\n# define AO_USE_NO_SIGNALS\n#endif\n\n#if (defined(__CYGWIN__) || defined(__GLIBC__) || defined(__GNU__) \\\n     || defined(__linux__)) \\\n    && !defined(AO_USE_NO_SIGNALS) && !defined(_GNU_SOURCE)\n# define _GNU_SOURCE 1\n#endif\n\n#ifndef AO_BUILD\n# define AO_BUILD\n#endif\n\n#undef AO_REQUIRE_CAS\n#include \"atomic_ops.h\" /* Without cas emulation! */\n\n#ifdef __cplusplus\n  extern \"C\" {\n#endif\n\nAO_API void AO_pause(int); /* defined below */\n\n#ifdef __cplusplus\n  } /* extern \"C\" */\n#endif\n\n#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__BORLANDC__) \\\n    || defined(AO_USE_NO_SIGNALS)\n\n#ifndef AO_NO_PTHREADS\n# include <pthread.h>\n#endif\n\n#ifndef AO_USE_NO_SIGNALS\n# include <signal.h>\n#endif\n\n#ifdef AO_USE_NANOSLEEP\n  /* This requires _POSIX_TIMERS feature. */\n# include <sys/time.h>\n# include <time.h>\n#elif defined(AO_USE_WIN32_PTHREADS)\n# include <windows.h> /* for Sleep() */\n#elif defined(_HPUX_SOURCE)\n# include <sys/time.h>\n#else\n# include <sys/select.h>\n#endif\n\n#ifndef AO_HAVE_double_t\n# include \"atomic_ops/sysdeps/standard_ao_double_t.h\"\n#endif\n\n#ifdef __cplusplus\n  extern \"C\" {\n#endif\n\nAO_API AO_t AO_fetch_compare_and_swap_emulation(volatile AO_t *addr,\n                                                AO_t old_val, AO_t new_val);\n\nAO_API int\nAO_compare_double_and_swap_double_emulation(volatile AO_double_t *addr,\n                                            AO_t old_val1, AO_t old_val2,\n                                            AO_t new_val1, AO_t new_val2);\n\nAO_API void AO_store_full_emulation(volatile AO_t *addr, AO_t val);\n\n/* Lock for pthreads-based implementation.      */\n#ifndef AO_NO_PTHREADS\n  AO_API pthread_mutex_t AO_pt_lock;\n#endif\n\n#ifdef __cplusplus\n  } /* extern \"C\" */\n#endif\n\n#ifndef AO_NO_PTHREADS\n  pthread_mutex_t AO_pt_lock = PTHREAD_MUTEX_INITIALIZER;\n#endif\n\n/*\n * Out of line compare-and-swap emulation based on test and set.\n *\n * We use a small table of locks for different compare_and_swap locations.\n * Before we update perform a compare-and-swap, we grab the corresponding\n * lock.  Different locations may hash to the same lock, but since we\n * never acquire more than one lock at a time, this can't deadlock.\n * We explicitly disable signals while we perform this operation.\n *\n * TODO: Probably also support emulation based on Lamport\n * locks, since we may not have test_and_set either.\n */\n#define AO_HASH_SIZE 16\n\n#define AO_HASH(x) ((unsigned)((AO_uintptr_t)(x) >> 12) & (AO_HASH_SIZE-1))\n\nstatic AO_TS_t AO_locks[AO_HASH_SIZE] = {\n  AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER,\n  AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER,\n  AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER,\n  AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER,\n};\n\nstatic void lock_ool(volatile AO_TS_t *l)\n{\n  int i = 0;\n\n  while (AO_test_and_set_acquire(l) == AO_TS_SET)\n    AO_pause(++i);\n}\n\nAO_INLINE void lock(volatile AO_TS_t *l)\n{\n  if (AO_EXPECT_FALSE(AO_test_and_set_acquire(l) == AO_TS_SET))\n    lock_ool(l);\n}\n\nAO_INLINE void unlock(volatile AO_TS_t *l)\n{\n  AO_CLEAR(l);\n}\n\n#ifndef AO_USE_NO_SIGNALS\n  static sigset_t all_sigs;\n  static volatile AO_t initialized = 0;\n  static volatile AO_TS_t init_lock = AO_TS_INITIALIZER;\n\n  AO_INLINE void block_all_signals(sigset_t *old_sigs_ptr)\n  {\n    if (AO_EXPECT_FALSE(!AO_load_acquire(&initialized)))\n    {\n      lock(&init_lock);\n      if (!initialized)\n        sigfillset(&all_sigs);\n      unlock(&init_lock);\n      AO_store_release(&initialized, 1);\n    }\n    sigprocmask(SIG_BLOCK, &all_sigs, old_sigs_ptr);\n        /* Neither sigprocmask nor pthread_sigmask is 100%      */\n        /* guaranteed to work here.  Sigprocmask is not         */\n        /* guaranteed be thread safe, and pthread_sigmask       */\n        /* is not async-signal-safe.  Under linuxthreads,       */\n        /* sigprocmask may block some pthreads-internal         */\n        /* signals.  So long as we do that for short periods,   */\n        /* we should be OK.                                     */\n  }\n#endif /* !AO_USE_NO_SIGNALS */\n\nAO_API AO_t AO_fetch_compare_and_swap_emulation(volatile AO_t *addr,\n                                                AO_t old_val, AO_t new_val)\n{\n  AO_TS_t *my_lock = AO_locks + AO_HASH(addr);\n  AO_t fetched_val;\n\n# ifndef AO_USE_NO_SIGNALS\n    sigset_t old_sigs;\n    block_all_signals(&old_sigs);\n# endif\n  lock(my_lock);\n  fetched_val = *addr;\n  if (fetched_val == old_val)\n    *addr = new_val;\n  unlock(my_lock);\n# ifndef AO_USE_NO_SIGNALS\n    sigprocmask(SIG_SETMASK, &old_sigs, NULL);\n# endif\n  return fetched_val;\n}\n\nAO_API int\nAO_compare_double_and_swap_double_emulation(volatile AO_double_t *addr,\n                                            AO_t old_val1, AO_t old_val2,\n                                            AO_t new_val1, AO_t new_val2)\n{\n  AO_TS_t *my_lock = AO_locks + AO_HASH(addr);\n  int result;\n\n# ifndef AO_USE_NO_SIGNALS\n    sigset_t old_sigs;\n    block_all_signals(&old_sigs);\n# endif\n  lock(my_lock);\n  if (addr -> AO_val1 == old_val1 && addr -> AO_val2 == old_val2)\n    {\n      addr -> AO_val1 = new_val1;\n      addr -> AO_val2 = new_val2;\n      result = 1;\n    }\n  else\n    result = 0;\n  unlock(my_lock);\n# ifndef AO_USE_NO_SIGNALS\n    sigprocmask(SIG_SETMASK, &old_sigs, NULL);\n# endif\n  return result;\n}\n\nAO_API void AO_store_full_emulation(volatile AO_t *addr, AO_t val)\n{\n  AO_TS_t *my_lock = AO_locks + AO_HASH(addr);\n  lock(my_lock);\n  *addr = val;\n  unlock(my_lock);\n}\n\n#else /* Non-posix platform */\n\n# include <windows.h>\n\n# define AO_USE_WIN32_PTHREADS\n                /* define to use Sleep() */\n\n  extern int AO_non_posix_implementation_is_entirely_in_headers;\n\n#endif\n\nstatic volatile AO_t spin_dummy = 0;\n\n/* Spin for 2**n units. */\nstatic void AO_spin(int n)\n{\n  AO_t j = AO_load(&spin_dummy);\n  int i = 2 << n;\n\n  while (i-- > 0)\n    j += j << 2;\n  /* Given spin_dummy is initialized to 0, j is 0 after the loop.   */\n  AO_store(&spin_dummy, j);\n}\n\nAO_API void AO_pause(int n)\n{\n  if (n < 12) {\n    AO_spin(n);\n  } else {\n#   ifdef AO_USE_NANOSLEEP\n      struct timespec ts;\n      ts.tv_sec = 0;\n      ts.tv_nsec = n > 28 ? 100000L * 1000 : 1L << (n - 2);\n      nanosleep(&ts, 0);\n#   elif defined(AO_USE_WIN32_PTHREADS)\n      Sleep(n > 28 ? 100 /* millis */\n                   : n < 22 ? 1 : (DWORD)1 << (n - 22));\n#   else\n      struct timeval tv;\n      /* Short async-signal-safe sleep. */\n      int usec = n > 28 ? 100000 : 1 << (n - 12);\n                /* Use an intermediate variable (of int type) to avoid  */\n                /* \"shift followed by widening conversion\" warning.     */\n\n      tv.tv_sec = 0;\n      tv.tv_usec = usec;\n      (void)select(0, 0, 0, 0, &tv);\n#   endif\n  }\n}\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops.h",
    "content": "/*\n * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2008-2022 Ivan Maidanski\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#ifndef AO_ATOMIC_OPS_H\n#define AO_ATOMIC_OPS_H\n\n#include \"atomic_ops/ao_version.h\"\n                        /* Define version numbers here to allow         */\n                        /* test on build machines for cross-builds.     */\n\n#include <assert.h>\n#include <stddef.h>\n\n/* We define various atomic operations on memory in a           */\n/* machine-specific way.  Unfortunately, this is complicated    */\n/* by the fact that these may or may not be combined with       */\n/* various memory barriers.  Thus the actual operations we      */\n/* define have the form AO_<atomic-op>_<barrier>, for all       */\n/* plausible combinations of <atomic-op> and <barrier>.         */\n/* This of course results in a mild combinatorial explosion.    */\n/* To deal with it, we try to generate derived                  */\n/* definitions for as many of the combinations as we can, as    */\n/* automatically as possible.                                   */\n/*                                                              */\n/* Our assumption throughout is that the programmer will        */\n/* specify the least demanding operation and memory barrier     */\n/* that will guarantee correctness for the implementation.      */\n/* Our job is to find the least expensive way to implement it   */\n/* on the applicable hardware.  In many cases that will         */\n/* involve, for example, a stronger memory barrier, or a        */\n/* combination of hardware primitives.                          */\n/*                                                              */\n/* Conventions:                                                 */\n/* \"plain\" atomic operations are not guaranteed to include      */\n/* a barrier.  The suffix in the name specifies the barrier     */\n/* type.  Suffixes are:                                         */\n/* _release: Earlier operations may not be delayed past it.     */\n/* _acquire: Later operations may not move ahead of it.         */\n/* _read: Subsequent reads must follow this operation and       */\n/*        preceding reads.                                      */\n/* _write: Earlier writes precede both this operation and       */\n/*        later writes.                                         */\n/* _full: Ordered with respect to both earlier and later memory */\n/*        operations.                                           */\n/* _release_write: Ordered with respect to earlier writes.      */\n/* _acquire_read: Ordered with respect to later reads.          */\n/*                                                              */\n/* Currently we try to define the following atomic memory       */\n/* operations, in combination with the above barriers:          */\n/* AO_nop                                                       */\n/* AO_load                                                      */\n/* AO_store                                                     */\n/* AO_test_and_set (binary)                                     */\n/* AO_fetch_and_add                                             */\n/* AO_fetch_and_add1                                            */\n/* AO_fetch_and_sub1                                            */\n/* AO_and                                                       */\n/* AO_or                                                        */\n/* AO_xor                                                       */\n/* AO_compare_and_swap                                          */\n/* AO_fetch_compare_and_swap                                    */\n/*                                                              */\n/* Note that atomicity guarantees are valid only if both        */\n/* readers and writers use AO_ operations to access the         */\n/* shared value, while ordering constraints are intended to     */\n/* apply all memory operations.  If a location can potentially  */\n/* be accessed simultaneously from multiple threads, and one of */\n/* those accesses may be a write access, then all such          */\n/* accesses to that location should be through AO_ primitives.  */\n/* However if AO_ operations enforce sufficient ordering to     */\n/* ensure that a location x cannot be accessed concurrently,    */\n/* or can only be read concurrently, then x can be accessed     */\n/* via ordinary references and assignments.                     */\n/*                                                              */\n/* AO_compare_and_swap takes an address and an expected old     */\n/* value and a new value, and returns an int.  Non-zero result  */\n/* indicates that it succeeded.                                 */\n/* AO_fetch_compare_and_swap takes an address and an expected   */\n/* old value and a new value, and returns the real old value.   */\n/* The operation succeeded if and only if the expected old      */\n/* value matches the old value returned.                        */\n/*                                                              */\n/* Test_and_set takes an address, atomically replaces it by     */\n/* AO_TS_SET, and returns the prior value.                      */\n/* An AO_TS_t location can be reset with the                    */\n/* AO_CLEAR macro, which normally uses AO_store_release.        */\n/* AO_fetch_and_add takes an address and an AO_t increment      */\n/* value.  The AO_fetch_and_add1 and AO_fetch_and_sub1 variants */\n/* are provided, since they allow faster implementations on     */\n/* some hardware. AO_and, AO_or, AO_xor do atomically and, or,  */\n/* xor (respectively) an AO_t value into a memory location,     */\n/* but do not provide access to the original.                   */\n/*                                                              */\n/* We expect this list to grow slowly over time.                */\n/*                                                              */\n/* Note that AO_nop_full is a full memory barrier.              */\n/*                                                              */\n/* Note that if some data is initialized with                   */\n/*      data.x = ...; data.y = ...; ...                         */\n/*      AO_store_release_write(&data_is_initialized, 1)         */\n/* then data is guaranteed to be initialized after the test     */\n/*      if (AO_load_acquire_read(&data_is_initialized)) ...     */\n/* succeeds.  Furthermore, this should generate near-optimal    */\n/* code on all common platforms.                                */\n/*                                                              */\n/* All operations operate on unsigned AO_t, which               */\n/* is the natural word size, and usually unsigned long.         */\n/* It is possible to check whether a particular operation op    */\n/* is available on a particular platform by checking whether    */\n/* AO_HAVE_op is defined.  We make heavy use of these macros    */\n/* internally.                                                  */\n\n/* The rest of this file basically has three sections:          */\n/*                                                              */\n/* Some utility and default definitions.                        */\n/*                                                              */\n/* The architecture dependent section:                          */\n/* This defines atomic operations that have direct hardware     */\n/* support on a particular platform, mostly by including the    */\n/* appropriate compiler- and hardware-dependent file.           */\n/*                                                              */\n/* The synthesis section:                                       */\n/* This tries to define other atomic operations in terms of     */\n/* those that are explicitly available on the platform.         */\n/* This section is hardware independent.                        */\n/* We make no attempt to synthesize operations in ways that     */\n/* effectively introduce locks, except for the debugging/demo   */\n/* pthread-based implementation at the beginning.  A more       */\n/* realistic implementation that falls back to locks could be   */\n/* added as a higher layer.  But that would sacrifice           */\n/* usability from signal handlers.                              */\n/* The synthesis section is implemented almost entirely in      */\n/* atomic_ops/generalize.h.                                     */\n\n/* Some common defaults.  Overridden for some architectures.    */\n\n#define AO_t size_t\n\n#if defined(__SIZEOF_POINTER__) \\\n    && (__SIZEOF_POINTER__ == 2 * __SIZEOF_SIZE_T__)\n  /* Pointers are twice bigger than the machine word.   */\n# define AO_FAT_POINTER\n#endif\n\n#ifndef AO_FAT_POINTER\n# define AO_uintptr_t AO_t\n#elif defined(__e2k__)\n  /* For some reason uintptr_t is 64-bit on E2K in the protected mode.  */\n  typedef unsigned __int128 AO_uintptr_t;\n#else\n# include <inttypes.h>\n# define AO_uintptr_t uintptr_t\n#endif\n\n/* A compile-time assertion for AO_uintptr_t size.      */\nstruct AO_uintptr_t_size_static_assert {\n  char dummy[sizeof(AO_uintptr_t) == sizeof(void *) ? 1 : -1];\n};\n\n/* The test_and_set primitive returns an AO_TS_VAL_t value.     */\n/* AO_TS_t is the type of an in-memory test-and-set location.   */\n\n#define AO_TS_INITIALIZER ((AO_TS_t)AO_TS_CLEAR)\n\n/* Convenient internal macro to test version of GCC.    */\n#if defined(__GNUC__) && defined(__GNUC_MINOR__)\n# define AO_GNUC_PREREQ(major, minor) \\\n            ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((major) << 16) + (minor))\n#else\n# define AO_GNUC_PREREQ(major, minor) 0 /* false */\n#endif\n\n/* Convenient internal macro to test version of Clang.  */\n#if defined(__clang__) && defined(__clang_major__)\n# define AO_CLANG_PREREQ(major, minor) \\\n    ((__clang_major__ << 16) + __clang_minor__ >= ((major) << 16) + (minor))\n#else\n# define AO_CLANG_PREREQ(major, minor) 0 /* false */\n#endif\n\n/* Platform-dependent stuff:                                    */\n#if (defined(__GNUC__) || defined(_MSC_VER) || defined(__INTEL_COMPILER) \\\n        || defined(__DMC__) || defined(__WATCOMC__)) && !defined(AO_NO_INLINE)\n# define AO_INLINE static __inline\n#elif defined(__sun) && !defined(AO_NO_INLINE)\n# define AO_INLINE static inline\n#else\n# define AO_INLINE static\n#endif\n\n#if AO_GNUC_PREREQ(3, 0) && !defined(LINT2)\n# define AO_EXPECT_FALSE(expr) __builtin_expect(expr, 0)\n  /* Equivalent to (expr) but predict that usually (expr) == 0. */\n#else\n# define AO_EXPECT_FALSE(expr) (expr)\n#endif /* !__GNUC__ */\n\n#if defined(__has_feature)\n  /* __has_feature() is supported.      */\n# if __has_feature(address_sanitizer)\n#   define AO_ADDRESS_SANITIZER\n# endif\n# if __has_feature(memory_sanitizer)\n#   define AO_MEMORY_SANITIZER\n# endif\n# if __has_feature(thread_sanitizer)\n#   define AO_THREAD_SANITIZER\n# endif\n#else\n# ifdef __SANITIZE_ADDRESS__\n    /* GCC v4.8+ */\n#   define AO_ADDRESS_SANITIZER\n# endif\n#endif /* !__has_feature */\n\n#ifndef AO_ATTR_NO_SANITIZE_MEMORY\n# ifndef AO_MEMORY_SANITIZER\n#   define AO_ATTR_NO_SANITIZE_MEMORY /* empty */\n# elif AO_CLANG_PREREQ(3, 8)\n#   define AO_ATTR_NO_SANITIZE_MEMORY __attribute__((no_sanitize(\"memory\")))\n# else\n#   define AO_ATTR_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))\n# endif\n#endif /* !AO_ATTR_NO_SANITIZE_MEMORY */\n\n#ifndef AO_ATTR_NO_SANITIZE_THREAD\n# ifndef AO_THREAD_SANITIZER\n#   define AO_ATTR_NO_SANITIZE_THREAD /* empty */\n# elif AO_CLANG_PREREQ(3, 8)\n#   define AO_ATTR_NO_SANITIZE_THREAD __attribute__((no_sanitize(\"thread\")))\n# else\n#   define AO_ATTR_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))\n# endif\n#endif /* !AO_ATTR_NO_SANITIZE_THREAD */\n\n#if (AO_GNUC_PREREQ(7, 5) || __STDC_VERSION__ >= 201112L) && !defined(LINT2)\n# define AO_ALIGNOF_SUPPORTED 1\n#endif\n\n#if defined(AO_DLL) && !defined(AO_API)\n# ifdef AO_BUILD\n#   if defined(__CEGCC__) || (defined(__MINGW32__) && !defined(__cplusplus))\n#     define AO_API __declspec(dllexport)\n#   elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) \\\n         || defined(__DMC__) || defined(__MINGW32__) || defined(__WATCOMC__)\n#     define AO_API extern __declspec(dllexport)\n#   endif\n# else\n#   if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CEGCC__) \\\n       || defined(__CYGWIN__) || defined(__DMC__)\n#     define AO_API __declspec(dllimport)\n#   elif defined(__MINGW32_DELAY_LOAD__)\n#     define AO_API __declspec(dllexport)\n#   elif defined(__MINGW32__) || defined(__WATCOMC__)\n#     define AO_API extern __declspec(dllimport)\n#   endif\n# endif\n#endif /* AO_DLL */\n\n#ifndef AO_API\n# define AO_API extern\n#endif\n\n#ifdef AO_ALIGNOF_SUPPORTED\n# define AO_ASSERT_ADDR_ALIGNED(addr) \\\n    assert(((AO_uintptr_t)(addr) & (__alignof__(*(addr)) - 1)) == 0)\n#else\n# define AO_ASSERT_ADDR_ALIGNED(addr) \\\n    assert(((AO_uintptr_t)(addr) & (sizeof(*(addr)) - 1)) == 0)\n#endif /* !AO_ALIGNOF_SUPPORTED */\n\n#if defined(__GNUC__) && !defined(__INTEL_COMPILER)\n# define AO_compiler_barrier() __asm__ __volatile__(\"\" : : : \"memory\")\n#elif defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \\\n        || defined(__WATCOMC__)\n# if defined(_AMD64_) || defined(_M_X64) || _MSC_VER >= 1400\n#   if defined(_WIN32_WCE)\n/* #     include <cmnintrin.h> */\n#   elif defined(_MSC_VER)\n#     include <intrin.h>\n#   endif\n#   pragma intrinsic(_ReadWriteBarrier)\n#   define AO_compiler_barrier() _ReadWriteBarrier()\n        /* We assume this does not generate a fence instruction.        */\n        /* The documentation is a bit unclear.                          */\n# else\n#   define AO_compiler_barrier() __asm { }\n        /* The preceding implementation may be preferable here too.     */\n        /* But the documentation warns about VC++ 2003 and earlier.     */\n# endif\n#elif defined(__INTEL_COMPILER)\n# define AO_compiler_barrier() __memory_barrier()\n                                        /* FIXME: Too strong? IA64-only? */\n#elif defined(_HPUX_SOURCE)\n# if defined(__ia64)\n#   include <machine/sys/inline.h>\n#   define AO_compiler_barrier() _Asm_sched_fence()\n# else\n    /* FIXME - We do not know how to do this.  This is a guess. */\n    /* And probably a bad one.                                  */\n    static volatile int AO_barrier_dummy;\n#   define AO_compiler_barrier() (void)(AO_barrier_dummy = AO_barrier_dummy)\n# endif\n#else\n  /* We conjecture that the following usually gives us the right        */\n  /* semantics or an error.                                             */\n# define AO_compiler_barrier() asm(\"\")\n#endif\n\n#if defined(AO_USE_PTHREAD_DEFS)\n# include \"atomic_ops/sysdeps/generic_pthread.h\"\n#endif /* AO_USE_PTHREAD_DEFS */\n\n#if (defined(__CC_ARM) || defined(__ARMCC__)) && !defined(__GNUC__) \\\n    && !defined(AO_USE_PTHREAD_DEFS)\n# include \"atomic_ops/sysdeps/armcc/arm_v6.h\"\n# define AO_GENERALIZE_TWICE\n#endif\n\n#if defined(__GNUC__) && !defined(AO_USE_PTHREAD_DEFS) \\\n    && !defined(__INTEL_COMPILER)\n# if defined(__i386__)\n    /* We don't define AO_USE_SYNC_CAS_BUILTIN for x86 here because     */\n    /* it might require specifying additional options (like -march)     */\n    /* or additional link libraries (if -march is not specified).       */\n#   include \"atomic_ops/sysdeps/gcc/x86.h\"\n# elif defined(__x86_64__)\n#   if AO_GNUC_PREREQ(4, 2) && !defined(AO_USE_SYNC_CAS_BUILTIN)\n      /* It is safe to use __sync CAS built-in on this architecture.    */\n#     define AO_USE_SYNC_CAS_BUILTIN\n#   endif\n#   include \"atomic_ops/sysdeps/gcc/x86.h\"\n# elif defined(__ia64__)\n#   include \"atomic_ops/sysdeps/gcc/ia64.h\"\n#   define AO_GENERALIZE_TWICE\n# elif defined(__hppa__)\n#   include \"atomic_ops/sysdeps/gcc/hppa.h\"\n#   define AO_CAN_EMUL_CAS\n# elif defined(__alpha__)\n#   include \"atomic_ops/sysdeps/gcc/alpha.h\"\n#   define AO_GENERALIZE_TWICE\n# elif defined(__s390__)\n#   include \"atomic_ops/sysdeps/gcc/s390.h\"\n# elif defined(__sparc__)\n#   include \"atomic_ops/sysdeps/gcc/sparc.h\"\n#   define AO_CAN_EMUL_CAS\n# elif defined(__m68k__)\n#   include \"atomic_ops/sysdeps/gcc/m68k.h\"\n# elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) \\\n       || defined(__powerpc64__) || defined(__ppc64__) || defined(_ARCH_PPC)\n#   include \"atomic_ops/sysdeps/gcc/powerpc.h\"\n# elif defined(__aarch64__)\n#   include \"atomic_ops/sysdeps/gcc/aarch64.h\"\n#   define AO_CAN_EMUL_CAS\n# elif defined(__arm__)\n#   include \"atomic_ops/sysdeps/gcc/arm.h\"\n#   define AO_CAN_EMUL_CAS\n# elif defined(__cris__) || defined(CRIS)\n#   include \"atomic_ops/sysdeps/gcc/cris.h\"\n#   define AO_CAN_EMUL_CAS\n#   define AO_GENERALIZE_TWICE\n# elif defined(__mips__)\n#   include \"atomic_ops/sysdeps/gcc/mips.h\"\n# elif defined(__sh__) || defined(SH4)\n#   include \"atomic_ops/sysdeps/gcc/sh.h\"\n#   define AO_CAN_EMUL_CAS\n# elif defined(__avr32__)\n#   include \"atomic_ops/sysdeps/gcc/avr32.h\"\n# elif defined(__e2k__)\n#   include \"atomic_ops/sysdeps/gcc/e2k.h\"\n# elif defined(__hexagon__)\n#   include \"atomic_ops/sysdeps/gcc/hexagon.h\"\n# elif defined(__nios2__)\n#   include \"atomic_ops/sysdeps/gcc/generic.h\"\n#   define AO_CAN_EMUL_CAS\n# elif defined(__riscv)\n#   include \"atomic_ops/sysdeps/gcc/riscv.h\"\n# elif defined(__tile__)\n#   include \"atomic_ops/sysdeps/gcc/tile.h\"\n# else /* etc. */\n#   include \"atomic_ops/sysdeps/gcc/generic.h\"\n# endif\n#endif /* __GNUC__ && !AO_USE_PTHREAD_DEFS */\n\n#if (defined(__IBMC__) || defined(__IBMCPP__)) && !defined(__GNUC__) \\\n    && !defined(AO_USE_PTHREAD_DEFS)\n# if defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) \\\n     || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) \\\n     || defined(_ARCH_PWR)\n#   include \"atomic_ops/sysdeps/ibmc/powerpc.h\"\n#   define AO_GENERALIZE_TWICE\n# endif\n#endif\n\n#if defined(__INTEL_COMPILER) && !defined(AO_USE_PTHREAD_DEFS)\n# if defined(__ia64__)\n#   include \"atomic_ops/sysdeps/icc/ia64.h\"\n#   define AO_GENERALIZE_TWICE\n# endif\n# if defined(__GNUC__)\n    /* Intel Compiler in GCC compatible mode */\n#   if defined(__i386__)\n#     include \"atomic_ops/sysdeps/gcc/x86.h\"\n#   endif /* __i386__ */\n#   if defined(__x86_64__)\n#     if (__INTEL_COMPILER > 1110) && !defined(AO_USE_SYNC_CAS_BUILTIN)\n#       define AO_USE_SYNC_CAS_BUILTIN\n#     endif\n#     include \"atomic_ops/sysdeps/gcc/x86.h\"\n#   endif /* __x86_64__ */\n# endif\n#endif\n\n#if defined(_HPUX_SOURCE) && !defined(__GNUC__) && !defined(AO_USE_PTHREAD_DEFS)\n# if defined(__ia64)\n#   include \"atomic_ops/sysdeps/hpc/ia64.h\"\n#   define AO_GENERALIZE_TWICE\n# else\n#   include \"atomic_ops/sysdeps/hpc/hppa.h\"\n#   define AO_CAN_EMUL_CAS\n# endif\n#endif\n\n#if defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \\\n        || (defined(__WATCOMC__) && defined(__NT__))\n# if defined(_AMD64_) || defined(_M_X64)\n#   include \"atomic_ops/sysdeps/msftc/x86_64.h\"\n# elif defined(_M_ARM64)\n#   include \"atomic_ops/sysdeps/msftc/arm64.h\"\n# elif defined(_M_IX86) || defined(x86)\n#   include \"atomic_ops/sysdeps/msftc/x86.h\"\n# elif defined(_M_ARM) || defined(ARM) || defined(_ARM_)\n#   include \"atomic_ops/sysdeps/msftc/arm.h\"\n#   define AO_GENERALIZE_TWICE\n# endif\n#endif\n\n#if defined(__sun) && !defined(__GNUC__) && !defined(AO_USE_PTHREAD_DEFS)\n  /* Note: use -DAO_USE_PTHREAD_DEFS if Sun CC does not handle inline asm. */\n# if defined(__i386) || defined(__x86_64) || defined(__amd64)\n#   include \"atomic_ops/sysdeps/sunc/x86.h\"\n# endif\n#endif\n\n#if !defined(__GNUC__) && (defined(sparc) || defined(__sparc)) \\\n    && !defined(AO_USE_PTHREAD_DEFS)\n# include \"atomic_ops/sysdeps/sunc/sparc.h\"\n# define AO_CAN_EMUL_CAS\n#endif\n\n#if (defined(AO_REQUIRE_CAS) && !defined(AO_HAVE_compare_and_swap) \\\n    && !defined(AO_HAVE_fetch_compare_and_swap) \\\n    && !defined(AO_HAVE_compare_and_swap_full) \\\n    && !defined(AO_HAVE_fetch_compare_and_swap_full) \\\n    && !defined(AO_HAVE_compare_and_swap_acquire) \\\n    && !defined(AO_HAVE_fetch_compare_and_swap_acquire)) || defined(CPPCHECK)\n# if defined(AO_CAN_EMUL_CAS)\n#   include \"atomic_ops/sysdeps/emul_cas.h\"\n# elif !defined(CPPCHECK)\n#   error Cannot implement AO_compare_and_swap_full on this architecture.\n# endif\n#endif /* AO_REQUIRE_CAS && !AO_HAVE_compare_and_swap ... */\n\n/* The most common way to clear a test-and-set location         */\n/* at the end of a critical section.                            */\n#if defined(AO_AO_TS_T) && !defined(AO_HAVE_CLEAR)\n# define AO_CLEAR(addr) AO_store_release((AO_TS_t *)(addr), AO_TS_CLEAR)\n# define AO_HAVE_CLEAR\n#endif\n#if defined(AO_CHAR_TS_T) && !defined(AO_HAVE_CLEAR)\n# define AO_CLEAR(addr) AO_char_store_release((AO_TS_t *)(addr), AO_TS_CLEAR)\n# define AO_HAVE_CLEAR\n#endif\n\n/* The generalization section.  */\n#if !defined(AO_GENERALIZE_TWICE) && defined(AO_CAN_EMUL_CAS) \\\n    && !defined(AO_HAVE_compare_and_swap_full) \\\n    && !defined(AO_HAVE_fetch_compare_and_swap_full)\n# define AO_GENERALIZE_TWICE\n#endif\n\n/* Theoretically we should repeatedly include atomic_ops/generalize.h.  */\n/* In fact, we observe that this converges after a small fixed number   */\n/* of iterations, usually one.                                          */\n#include \"atomic_ops/generalize.h\"\n\n#if !defined(AO_GENERALIZE_TWICE) \\\n    && defined(AO_HAVE_compare_double_and_swap_double) \\\n    && (!defined(AO_HAVE_double_load) || !defined(AO_HAVE_double_store))\n# define AO_GENERALIZE_TWICE\n#endif\n\n#ifdef AO_T_IS_INT\n  /* Included after the first generalization pass.      */\n# include \"atomic_ops/sysdeps/ao_t_is_int.h\"\n# ifndef AO_GENERALIZE_TWICE\n    /* Always generalize again. */\n#   define AO_GENERALIZE_TWICE\n# endif\n#endif /* AO_T_IS_INT */\n\n#ifdef AO_GENERALIZE_TWICE\n# include \"atomic_ops/generalize.h\"\n#endif\n\n/* For compatibility with version 0.4 and earlier       */\n#define AO_TS_T AO_TS_t\n#define AO_T AO_t\n#define AO_TS_VAL AO_TS_VAL_t\n\n#endif /* !AO_ATOMIC_OPS_H */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops_malloc.c",
    "content": "/*\n * Copyright (c) 2005 Hewlett-Packard Development Company, L.P.\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License along\n * with this program; if not, write to the Free Software Foundation, Inc.,\n * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n */\n\n#if defined(HAVE_CONFIG_H)\n# include \"config.h\"\n#endif\n\n#ifdef DONT_USE_MMAP /* for testing */\n# undef HAVE_MMAP\n#endif\n\n#ifndef AO_BUILD\n# define AO_BUILD\n#endif\n\n#define AO_REQUIRE_CAS\n#include \"atomic_ops_malloc.h\"\n\n#include <string.h>     /* for ffs, which is assumed reentrant. */\n#include <stdlib.h>\n#include <assert.h>\n\n#ifdef AO_TRACE_MALLOC\n# include <stdio.h>\n# include <pthread.h>\n#endif\n\n#if defined(AO_ADDRESS_SANITIZER) && !defined(AO_NO_MALLOC_POISON)\n  /* #include \"sanitizer/asan_interface.h\" */\n  void __asan_poison_memory_region(void *, size_t);\n  void __asan_unpoison_memory_region(void *, size_t);\n# define ASAN_POISON_MEMORY_REGION(addr, size) \\\n                __asan_poison_memory_region(addr, size)\n# define ASAN_UNPOISON_MEMORY_REGION(addr, size) \\\n                __asan_unpoison_memory_region(addr, size)\n#else\n# define ASAN_POISON_MEMORY_REGION(addr, size) (void)0\n# define ASAN_UNPOISON_MEMORY_REGION(addr, size) (void)0\n#endif /* !AO_ADDRESS_SANITIZER */\n\n#if (defined(_WIN32_WCE) || defined(__MINGW32CE__)) && !defined(AO_HAVE_abort)\n# define abort() _exit(-1) /* there is no abort() in WinCE */\n#endif\n\n/*\n * We round up each allocation request to the next power of two\n * minus one word.\n * We keep one stack of free objects for each size.  Each object has\n * an initial word (offset from the visible pointer is -sizeof(AO_uintptr_t))\n * which contains either:\n * - the binary log of the object size in bytes (for small objects), or\n * - the object size (a multiple of CHUNK_SIZE) for large objects.\n * The second case only arises if mmap-based allocation is supported.\n * We align the user-visible part of each object on an ALIGNMENT\n * byte boundary.  That means that the actual (hidden) start of\n * the object starts a word before this boundary.\n */\n\n#ifndef LOG_MAX_SIZE\n# define LOG_MAX_SIZE 16\n        /* We assume that 2**LOG_MAX_SIZE is a multiple of page size. */\n#endif\n\n#ifndef ALIGNMENT\n# define ALIGNMENT 16\n        /* Assumed to be at least sizeof(AO_uintptr_t).         */\n#endif\n\n#define CHUNK_SIZE (1 << LOG_MAX_SIZE)\n\n#ifndef AO_INITIAL_HEAP_SIZE\n# ifndef AO_INITIAL_HEAP_CHUNKS\n#   define AO_INITIAL_HEAP_CHUNKS 2*(LOG_MAX_SIZE+1)\n# endif\n# define AO_INITIAL_HEAP_SIZE (AO_INITIAL_HEAP_CHUNKS * CHUNK_SIZE)\n#endif /* !AO_INITIAL_HEAP_SIZE */\n\nstatic char AO_initial_heap[AO_INITIAL_HEAP_SIZE]; /* ~2MB by default */\n\nstatic AO_internal_ptr_t volatile initial_heap_ptr = 0;\n\n#if defined(HAVE_MMAP)\n\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <sys/mman.h>\n\n#if defined(MAP_ANONYMOUS) || defined(MAP_ANON)\n# define USE_MMAP_ANON\n#endif\n\n#ifdef USE_MMAP_FIXED\n# define GC_MMAP_FLAGS (MAP_FIXED | MAP_PRIVATE)\n        /* Seems to yield better performance on Solaris 2, but can      */\n        /* be unreliable if something is already mapped at the address. */\n#else\n# define GC_MMAP_FLAGS MAP_PRIVATE\n#endif\n\n#ifdef USE_MMAP_ANON\n# if defined(CPPCHECK)\n#   define OPT_MAP_ANON 0x20 /* taken from linux */\n# elif defined(MAP_ANONYMOUS)\n#   define OPT_MAP_ANON MAP_ANONYMOUS\n# else\n#   define OPT_MAP_ANON MAP_ANON\n# endif\n#else\n# include <unistd.h> /* for close() */\n# define OPT_MAP_ANON 0\n#endif\n\nstatic volatile AO_t mmap_enabled = 0;\n\nAO_API void\nAO_malloc_enable_mmap(void)\n{\n# if defined(__sun)\n    AO_store_release(&mmap_enabled, 1);\n            /* Workaround for Sun CC */\n# else\n    AO_store(&mmap_enabled, 1);\n# endif\n}\n\nstatic char *get_mmaped(size_t sz)\n{\n  char * result;\n# ifdef USE_MMAP_ANON\n#   define zero_fd -1\n# else\n    int zero_fd;\n# endif\n\n  assert(!(sz & (CHUNK_SIZE - 1)));\n  if (!mmap_enabled)\n    return 0;\n\n# ifndef USE_MMAP_ANON\n    zero_fd = open(\"/dev/zero\", O_RDONLY);\n    if (zero_fd == -1)\n      return 0;\n# endif\n  result = (char *)mmap(0, sz, PROT_READ | PROT_WRITE,\n                        GC_MMAP_FLAGS | OPT_MAP_ANON,\n                        zero_fd, 0 /* offset */);\n# ifndef USE_MMAP_ANON\n    close(zero_fd);\n# endif\n  if (AO_EXPECT_FALSE(result == MAP_FAILED))\n    result = NULL;\n  return result;\n}\n\n#ifndef SIZE_MAX\n# include <limits.h>\n#endif\n#if defined(SIZE_MAX) && !defined(CPPCHECK)\n# define AO_SIZE_MAX ((size_t)SIZE_MAX)\n            /* Extra cast to workaround some buggy SIZE_MAX definitions. */\n#else\n# define AO_SIZE_MAX (~(size_t)0)\n#endif\n\n/* Saturated addition of size_t values.  Used to avoid value wrap       */\n/* around on overflow.  The arguments should have no side effects.      */\n#define SIZET_SAT_ADD(a, b) \\\n    (AO_EXPECT_FALSE((a) >= AO_SIZE_MAX - (b)) ? AO_SIZE_MAX : (a) + (b))\n\n/* Allocate an object of size (incl. header) of size > CHUNK_SIZE.      */\n/* sz includes space for a pointer-sized header.                        */\nstatic char *\nAO_malloc_large(size_t sz)\n{\n  void *result;\n\n  /* The header will force us to waste ALIGNMENT bytes, including the   */\n  /* header.  Round to multiple of CHUNK_SIZE.                          */\n  sz = SIZET_SAT_ADD(sz, ALIGNMENT + CHUNK_SIZE - 1)\n            & ~(size_t)(CHUNK_SIZE - 1);\n  assert(sz > LOG_MAX_SIZE);\n  result = get_mmaped(sz);\n  if (AO_EXPECT_FALSE(NULL == result))\n    return NULL;\n\n  result = (AO_uintptr_t *)result + ALIGNMENT / sizeof(AO_uintptr_t);\n  ((AO_uintptr_t *)result)[-1] = (AO_uintptr_t)sz;\n  return (char *)result;\n}\n\nstatic void\nAO_free_large(void *p)\n{\n  size_t sz = (size_t)(((AO_uintptr_t *)p)[-1]);\n\n  if (munmap((AO_uintptr_t *)p - ALIGNMENT / sizeof(AO_uintptr_t), sz) != 0)\n    abort();  /* Programmer error.  Not really async-signal-safe, but ... */\n}\n\n#else /* !HAVE_MMAP */\n\nAO_API void\nAO_malloc_enable_mmap(void)\n{\n}\n\n#define get_mmaped(sz) ((char*)0)\n#define AO_malloc_large(sz) ((char*)0)\n#define AO_free_large(p) abort()\n                /* Programmer error.  Not really async-signal-safe, but ... */\n\n#endif /* !HAVE_MMAP */\n\n/* TODO: Duplicates (partially) the definitions in atomic_ops_stack.c.  */\n#if defined(AO_FAT_POINTER) || defined(AO_STACK_USE_CPTR)\n  AO_INLINE int\n  AO_cptr_compare_and_swap(AO_internal_ptr_t volatile *addr,\n                        AO_internal_ptr_t old_val, AO_internal_ptr_t new_val)\n  {\n    return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                        __ATOMIC_RELAXED, __ATOMIC_RELAXED);\n  }\n\n  AO_INLINE int\n  AO_cptr_compare_and_swap_acquire(AO_internal_ptr_t volatile *addr,\n                        AO_internal_ptr_t old_val, AO_internal_ptr_t new_val)\n  {\n    return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0,\n                        __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);\n  }\n\n# define AO_cptr_load(p) __atomic_load_n(p, __ATOMIC_RELAXED)\n#else\n# define AO_cptr_compare_and_swap AO_compare_and_swap\n# define AO_cptr_compare_and_swap_acquire AO_compare_and_swap_acquire\n# define AO_cptr_load AO_load\n#endif\n\nstatic char *\nget_chunk(void)\n{\n  AO_internal_ptr_t my_chunk_ptr;\n\n  for (;;) {\n    AO_internal_ptr_t initial_ptr = AO_cptr_load(&initial_heap_ptr);\n\n    my_chunk_ptr = AO_EXPECT_FALSE(0 == initial_ptr) ?\n                    (AO_internal_ptr_t)AO_initial_heap : initial_ptr;\n    /* Round up the pointer to ALIGNMENT.       */\n#   ifdef AO_STACK_USE_CPTR\n      my_chunk_ptr += ((size_t)ALIGNMENT - (size_t)(AO_uintptr_t)my_chunk_ptr)\n                         & (ALIGNMENT - 1);\n#   else\n      my_chunk_ptr = (AO_internal_ptr_t)(((AO_uintptr_t)my_chunk_ptr\n                                            + ALIGNMENT-1)\n                                         & ~(AO_uintptr_t)(ALIGNMENT-1));\n#   endif\n    if (initial_ptr != my_chunk_ptr) {\n      /* Align correctly.  If this fails, someone else did it for us.   */\n      assert(my_chunk_ptr != 0);\n      (void)AO_cptr_compare_and_swap_acquire(&initial_heap_ptr, initial_ptr,\n                                             my_chunk_ptr);\n    }\n\n    if (AO_EXPECT_FALSE((AO_uintptr_t)my_chunk_ptr\n                            < (AO_uintptr_t)AO_initial_heap)\n        || AO_EXPECT_FALSE((AO_uintptr_t)my_chunk_ptr\n                            > (AO_uintptr_t)(AO_initial_heap\n                                    + AO_INITIAL_HEAP_SIZE - CHUNK_SIZE))) {\n      /* We failed.  The initial heap is used up.       */\n      my_chunk_ptr = (AO_internal_ptr_t)get_mmaped(CHUNK_SIZE);\n#     if !defined(CPPCHECK)\n        assert(((AO_uintptr_t)my_chunk_ptr & (ALIGNMENT - 1)) == 0);\n#     endif\n      break;\n    }\n    if (AO_cptr_compare_and_swap(&initial_heap_ptr, my_chunk_ptr,\n                                 my_chunk_ptr + CHUNK_SIZE)) {\n      break;\n    }\n  }\n  return (char *)my_chunk_ptr;\n}\n\n/* Object free lists.  I-th entry corresponds to objects        */\n/* of total size 2**i bytes.                                    */\nstatic AO_stack_t AO_free_list[LOG_MAX_SIZE+1];\n\n/* Break up the chunk, and add it to the object free list for   */\n/* the given size.  We have exclusive access to chunk.          */\nstatic void add_chunk_as(void * chunk, unsigned log_sz)\n{\n  size_t ofs, limit;\n  size_t sz = (size_t)1 << log_sz;\n\n  assert((size_t)CHUNK_SIZE >= sz);\n  assert(sz % sizeof(AO_uintptr_t) == 0);\n  limit = (size_t)CHUNK_SIZE - sz;\n  for (ofs = ALIGNMENT - sizeof(AO_uintptr_t); ofs <= limit; ofs += sz) {\n    ASAN_POISON_MEMORY_REGION((char *)chunk + ofs + sizeof(AO_uintptr_t),\n                              sz - sizeof(AO_uintptr_t));\n    AO_stack_push(&AO_free_list[log_sz],\n                  (AO_uintptr_t *)chunk + ofs / sizeof(AO_uintptr_t));\n  }\n}\n\nstatic const unsigned char msbs[16] = {\n  0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4\n};\n\n/* Return the position of the most significant set bit in the   */\n/* argument.                                                    */\n/* We follow the conventions of ffs(), i.e. the least           */\n/* significant bit is number one.                               */\nstatic unsigned msb(size_t s)\n{\n  unsigned result = 0;\n  if ((s & 0xff) != s) {\n#   if (__SIZEOF_SIZE_T__ == 8) && !defined(CPPCHECK)\n      unsigned v = (unsigned)(s >> 32);\n      if (AO_EXPECT_FALSE(v != 0))\n        {\n          s = v;\n          result += 32;\n        }\n#   elif __SIZEOF_SIZE_T__ == 4\n      /* No op. */\n#   else\n      unsigned v;\n      /* The following is a tricky code ought to be equivalent to       */\n      /* \"(v = s >> 32) != 0\" but suppresses warnings on 32-bit arch's. */\n#     define SIZEOF_SIZE_T_GT_4 (sizeof(size_t) > 4)\n      if (SIZEOF_SIZE_T_GT_4\n          && (v = (unsigned)(s >> (SIZEOF_SIZE_T_GT_4 ? 32 : 0))) != 0)\n        {\n          s = v;\n          result += 32;\n        }\n#   endif /* !defined(__SIZEOF_SIZE_T__) */\n    if (AO_EXPECT_FALSE((s >> 16) != 0))\n      {\n        s >>= 16;\n        result += 16;\n      }\n    if ((s >> 8) != 0)\n      {\n        s >>= 8;\n        result += 8;\n      }\n  }\n  if (s > 15)\n    {\n      s >>= 4;\n      result += 4;\n    }\n  result += msbs[s];\n  return result;\n}\n\nAO_API AO_ATTR_MALLOC AO_ATTR_ALLOC_SIZE(1)\nvoid *\nAO_malloc(size_t sz)\n{\n  AO_uintptr_t *result;\n  unsigned log_sz;\n\n  if (AO_EXPECT_FALSE(sz > CHUNK_SIZE - sizeof(AO_uintptr_t)))\n    return AO_malloc_large(sz);\n  log_sz = msb(sz + sizeof(AO_uintptr_t) - 1);\n  assert(log_sz <= LOG_MAX_SIZE);\n  assert(((size_t)1 << log_sz) >= sz + sizeof(AO_uintptr_t));\n  result = AO_stack_pop(AO_free_list + log_sz);\n  while (AO_EXPECT_FALSE(NULL == result)) {\n    void *chunk = get_chunk();\n\n    if (AO_EXPECT_FALSE(NULL == chunk))\n      return NULL;\n    add_chunk_as(chunk, log_sz);\n    result = AO_stack_pop(AO_free_list + log_sz);\n  }\n  *result = log_sz;\n# ifdef AO_TRACE_MALLOC\n    fprintf(stderr, \"%p: AO_malloc(%lu) = %p\\n\",\n            (void *)pthread_self(), (unsigned long)sz, (void *)(result + 1));\n# endif\n  ASAN_UNPOISON_MEMORY_REGION(result + 1, sz);\n  return result + 1;\n}\n\nAO_API void\nAO_free(void *p)\n{\n  AO_uintptr_t *base;\n  int log_sz;\n\n  if (AO_EXPECT_FALSE(NULL == p))\n    return;\n\n  base = (AO_uintptr_t *)p - 1;\n  log_sz = (int)(*base);\n# ifdef AO_TRACE_MALLOC\n    fprintf(stderr, \"%p: AO_free(%p sz:%lu)\\n\", (void *)pthread_self(), p,\n            log_sz > LOG_MAX_SIZE ? (unsigned)log_sz : 1UL << log_sz);\n# endif\n  if (AO_EXPECT_FALSE(log_sz > LOG_MAX_SIZE)) {\n    AO_free_large(p);\n  } else {\n    ASAN_POISON_MEMORY_REGION(base + 1,\n                              ((size_t)1 << log_sz) - sizeof(AO_uintptr_t));\n    AO_stack_push(AO_free_list + log_sz, base);\n  }\n}\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops_malloc.h",
    "content": "/*\n * Copyright (c) 2005 Hewlett-Packard Development Company, L.P.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/* Almost lock-free malloc implementation based on stack implementation. */\n/* See README_malloc.txt file for detailed usage rules.                  */\n\n#ifndef AO_MALLOC_H\n#define AO_MALLOC_H\n\n#include \"atomic_ops_stack.h\"\n\n#include <stddef.h> /* for size_t */\n\n#ifdef __cplusplus\n  extern \"C\" {\n#endif\n\n#ifdef AO_STACK_IS_LOCK_FREE\n# define AO_MALLOC_IS_LOCK_FREE\n#endif\n\n#ifndef AO_ATTR_MALLOC\n# if AO_GNUC_PREREQ(3, 1)\n#   define AO_ATTR_MALLOC __attribute__((__malloc__))\n# elif defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(__EDG__)\n#   define AO_ATTR_MALLOC \\\n                __declspec(allocator) __declspec(noalias) __declspec(restrict)\n# elif defined(_MSC_VER) && _MSC_VER >= 1400\n#   define AO_ATTR_MALLOC __declspec(noalias) __declspec(restrict)\n# else\n#   define AO_ATTR_MALLOC /* empty */\n# endif\n#endif\n\n#ifndef AO_ATTR_ALLOC_SIZE\n# ifdef __clang__\n#   if __has_attribute(__alloc_size__)\n#     define AO_ATTR_ALLOC_SIZE(argnum) \\\n                __attribute__((__alloc_size__(argnum)))\n#   else\n#     define AO_ATTR_ALLOC_SIZE(argnum) /* empty */\n#   endif\n# elif AO_GNUC_PREREQ(4, 3) && !defined(__ICC)\n#   define AO_ATTR_ALLOC_SIZE(argnum) __attribute__((__alloc_size__(argnum)))\n# else\n#   define AO_ATTR_ALLOC_SIZE(argnum) /* empty */\n# endif\n#endif\n\nAO_API void AO_free(void *);\n\nAO_API AO_ATTR_MALLOC AO_ATTR_ALLOC_SIZE(1)\nvoid * AO_malloc(size_t);\n\n/* Allow use of mmap to grow the heap.  No-op on some platforms.        */\nAO_API void AO_malloc_enable_mmap(void);\n\n#ifdef __cplusplus\n  } /* extern \"C\" */\n#endif\n\n#endif /* !AO_MALLOC_H */\n"
  },
  {
    "path": "thirdparty/libatomic_ops/atomic_ops_sysdeps.S",
    "content": "/*\n * Include the appropriate system-dependent assembly file, if any.\n * This is used only if the platform supports neither inline assembly\n * code, nor appropriate compiler intrinsics.\n */\n\n#if !defined(__GNUC__) && (defined(sparc) || defined(__sparc))\n#  include \"atomic_ops/sysdeps/sunc/sparc.S\"\n#endif\n"
  },
  {
    "path": "thirdparty/libbacktrace/amalgamation.txt",
    "content": "The libbacktrace source is distributed here as an amalgamation (https://sqlite.org/amalgamation.html).\nThis means that, rather than mirroring the entire libbacktrace repo here, most of the source code is\npackaged into one C file while other platform-specific code are into their respective C files which\nis much easier to handle."
  },
  {
    "path": "thirdparty/libbacktrace/backtrace.c",
    "content": "/* Copyright (C) 2012-2021 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#define HAVE_ATOMIC_FUNCTIONS 1\n#define HAVE_CLOCK_GETTIME 1\n#define HAVE_DECL_GETPAGESIZE 0\n#define HAVE_DECL_STRNLEN 1\n#define HAVE_DL_ITERATE_PHDR 1\n#define HAVE_GETIPINFO 1\n#define HAVE_LSTAT 1\n#define HAVE_READLINK 1\n#define HAVE_SYNC_FUNCTIONS 1\n\n#define HAVE_DLFCN_H 1\n#define HAVE_INTTYPES_H 1\n#define HAVE_LINK_H 1\n#define HAVE_MEMORY_H 1\n#define HAVE_STDINT_H 1\n#define HAVE_STDLIB_H 1\n#define HAVE_STRINGS_H 1\n#define HAVE_STRING_H 1\n#define HAVE_UNISTD_H 1\n#define STDC_HEADERS 1\n#include <stdint.h>\n#if UINTPTR_MAX == 0xFFFFFFFF\n  #define BACKTRACE_ELF_SIZE 32\n  #define BACKTRACE_XCOFF_SIZE 32\n#elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFu\n  #define BACKTRACE_ELF_SIZE 64\n  #define BACKTRACE_XCOFF_SIZE 64\n#endif\n#ifdef __TINYC__\n  #undef HAVE_ATOMIC_FUNCTIONS\n  #undef HAVE_SYNC_FUNCTIONS\n#endif\n#ifndef _WIN32\n#define HAVE_FCNTL 1\n#endif\n#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)\n  #define HAVE_KERN_PROC 1\n  #define HAVE_KERN_PROC_ARGS 1\n#endif\n#ifdef __APPLE__\n  #define HAVE_MACH_O_DYLD_H 1\n#endif\n#ifndef _ALL_SOURCE\n  #define _ALL_SOURCE 1\n#endif\n#ifndef _GNU_SOURCE\n  #define _GNU_SOURCE 1\n  #undef HAVE_DL_ITERATE_PHDR\n#endif\n#ifndef _POSIX_PTHREAD_SEMANTICS\n  #define _POSIX_PTHREAD_SEMANTICS 1\n#endif\n#ifndef _TANDEM_SOURCE\n  #define _TANDEM_SOURCE 1\n#endif\n#ifndef __EXTENSIONS__\n  #define __EXTENSIONS__ 1\n#endif\n#ifndef _DARWIN_USE_64_BIT_INODE\n  #define _DARWIN_USE_64_BIT_INODE 1\n#endif\n\n#define BACKTRACE_SUPPORTED 1\n#define BACKTRACE_USES_MALLOC 1\n#define BACKTRACE_SUPPORTS_THREADS 1\n#define BACKTRACE_SUPPORTS_DATA 0\n\n#if __TINYC__\n  #undef BACKTRACE_SUPPORTED\n#endif\n\n#include \"base.c\"\n\n#if defined(__linux__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)\n  #include \"linux.c\"\n#elif defined(__APPLE__)\n  #include \"darwin.c\"\n#elif defined(_WIN32)\n  #include \"windows.c\"\n#endif\n"
  },
  {
    "path": "thirdparty/libbacktrace/backtrace.h",
    "content": "/* backtrace.h -- Public header file for stack backtrace library.\n   Copyright (C) 2012-2021 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#ifndef BACKTRACE_H\n#define BACKTRACE_H\n\n#include <stddef.h>\n#include <stdint.h>\n#include <stdio.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* The backtrace state.  This struct is intentionally not defined in\n   the public interface.  */\n\nstruct backtrace_state;\n\n/* The type of the error callback argument to backtrace functions.\n   This function, if not NULL, will be called for certain error cases.\n   The DATA argument is passed to the function that calls this one.\n   The MSG argument is an error message.  The ERRNUM argument, if\n   greater than 0, holds an errno value.  The MSG buffer may become\n   invalid after this function returns.\n\n   As a special case, the ERRNUM argument will be passed as -1 if no\n   debug info can be found for the executable, or if the debug info\n   exists but has an unsupported version, but the function requires\n   debug info (e.g., backtrace_full, backtrace_pcinfo).  The MSG in\n   this case will be something along the lines of \"no debug info\".\n   Similarly, ERRNUM will be passed as -1 if there is no symbol table,\n   but the function requires a symbol table (e.g., backtrace_syminfo).\n   This may be used as a signal that some other approach should be\n   tried.  */\n\ntypedef void (*backtrace_error_callback) (void *data, const char *msg,\n\t\t\t\t\t  int errnum);\n\n/* Create state information for the backtrace routines.  This must be\n   called before any of the other routines, and its return value must\n   be passed to all of the other routines.  FILENAME is the path name\n   of the executable file; if it is NULL the library will try\n   system-specific path names.  If not NULL, FILENAME must point to a\n   permanent buffer.  If THREADED is non-zero the state may be\n   accessed by multiple threads simultaneously, and the library will\n   use appropriate atomic operations.  If THREADED is zero the state\n   may only be accessed by one thread at a time.  This returns a state\n   pointer on success, NULL on error.  If an error occurs, this will\n   call the ERROR_CALLBACK routine.\n\n   Calling this function allocates resources that cannot be freed.\n   There is no backtrace_free_state function.  The state is used to\n   cache information that is expensive to recompute.  Programs are\n   expected to call this function at most once and to save the return\n   value for all later calls to backtrace functions.  */\n\nextern struct backtrace_state *backtrace_create_state (\n    const char *filename, int threaded,\n    backtrace_error_callback error_callback, void *data);\n\n/* The type of the callback argument to the backtrace_full function.\n   DATA is the argument passed to backtrace_full.  PC is the program\n   counter.  FILENAME is the name of the file containing PC, or NULL\n   if not available.  LINENO is the line number in FILENAME containing\n   PC, or 0 if not available.  FUNCTION is the name of the function\n   containing PC, or NULL if not available.  This should return 0 to\n   continuing tracing.  The FILENAME and FUNCTION buffers may become\n   invalid after this function returns.  */\n\ntypedef int (*backtrace_full_callback) (void *data, uintptr_t pc,\n\t\t\t\t\tconst char *filename, int lineno,\n\t\t\t\t\tconst char *function);\n\n/* Get a full stack backtrace.  SKIP is the number of frames to skip;\n   passing 0 will start the trace with the function calling\n   backtrace_full.  DATA is passed to the callback routine.  If any\n   call to CALLBACK returns a non-zero value, the stack backtrace\n   stops, and backtrace returns that value; this may be used to limit\n   the number of stack frames desired.  If all calls to CALLBACK\n   return 0, backtrace returns 0.  The backtrace_full function will\n   make at least one call to either CALLBACK or ERROR_CALLBACK.  This\n   function requires debug info for the executable.  */\n\nextern int backtrace_full (struct backtrace_state *state, int skip,\n\t\t\t   backtrace_full_callback callback,\n\t\t\t   backtrace_error_callback error_callback,\n\t\t\t   void *data);\n\n/* The type of the callback argument to the backtrace_simple function.\n   DATA is the argument passed to simple_backtrace.  PC is the program\n   counter.  This should return 0 to continue tracing.  */\n\ntypedef int (*backtrace_simple_callback) (void *data, uintptr_t pc);\n\n/* Get a simple backtrace.  SKIP is the number of frames to skip, as\n   in backtrace.  DATA is passed to the callback routine.  If any call\n   to CALLBACK returns a non-zero value, the stack backtrace stops,\n   and backtrace_simple returns that value.  Otherwise\n   backtrace_simple returns 0.  The backtrace_simple function will\n   make at least one call to either CALLBACK or ERROR_CALLBACK.  This\n   function does not require any debug info for the executable.  */\n\nextern int backtrace_simple (struct backtrace_state *state, int skip,\n\t\t\t     backtrace_simple_callback callback,\n\t\t\t     backtrace_error_callback error_callback,\n\t\t\t     void *data);\n\n/* Print the current backtrace in a user readable format to a FILE.\n   SKIP is the number of frames to skip, as in backtrace_full.  Any\n   error messages are printed to stderr.  This function requires debug\n   info for the executable.  */\n\nextern void backtrace_print (struct backtrace_state *state, int skip, FILE *);\n\n/* Given PC, a program counter in the current program, call the\n   callback function with filename, line number, and function name\n   information.  This will normally call the callback function exactly\n   once.  However, if the PC happens to describe an inlined call, and\n   the debugging information contains the necessary information, then\n   this may call the callback function multiple times.  This will make\n   at least one call to either CALLBACK or ERROR_CALLBACK.  This\n   returns the first non-zero value returned by CALLBACK, or 0.  */\n\nextern int backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,\n\t\t\t     backtrace_full_callback callback,\n\t\t\t     backtrace_error_callback error_callback,\n\t\t\t     void *data);\n\n/* The type of the callback argument to backtrace_syminfo.  DATA and\n   PC are the arguments passed to backtrace_syminfo.  SYMNAME is the\n   name of the symbol for the corresponding code.  SYMVAL is the\n   value and SYMSIZE is the size of the symbol.  SYMNAME will be NULL\n   if no error occurred but the symbol could not be found.  */\n\ntypedef void (*backtrace_syminfo_callback) (void *data, uintptr_t pc,\n\t\t\t\t\t    const char *symname,\n\t\t\t\t\t    uintptr_t symval,\n\t\t\t\t\t    uintptr_t symsize);\n\n/* Given ADDR, an address or program counter in the current program,\n   call the callback information with the symbol name and value\n   describing the function or variable in which ADDR may be found.\n   This will call either CALLBACK or ERROR_CALLBACK exactly once.\n   This returns 1 on success, 0 on failure.  This function requires\n   the symbol table but does not require the debug info.  Note that if\n   the symbol table is present but ADDR could not be found in the\n   table, CALLBACK will be called with a NULL SYMNAME argument.\n   Returns 1 on success, 0 on error.  */\n\nextern int backtrace_syminfo (struct backtrace_state *state, uintptr_t addr,\n\t\t\t      backtrace_syminfo_callback callback,\n\t\t\t      backtrace_error_callback error_callback,\n\t\t\t      void *data);\n\n#ifdef __cplusplus\n} /* End extern \"C\".  */\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/libbacktrace/base.c",
    "content": "// NOTE: Portions of the code have been modified in order to fix compilation in TCC - Ned\n\n// backtrace.h:\n#ifndef BACKTRACE_H\n#define BACKTRACE_H\n\n#include <stddef.h>\n#include <stdint.h>\n#include <stdio.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nstruct backtrace_state;\n\ntypedef void (*backtrace_error_callback)(void *data, const char *msg,\n                                         int errnum);\n\nextern struct backtrace_state *backtrace_create_state(\n    const char *filename, int threaded, backtrace_error_callback error_callback,\n    void *data);\n\ntypedef int (*backtrace_full_callback)(void *data, uintptr_t pc,\n                                       const char *filename, int lineno,\n                                       const char *function);\n\nextern int backtrace_full(struct backtrace_state *state, int skip,\n                          backtrace_full_callback callback,\n                          backtrace_error_callback error_callback, void *data);\n\ntypedef int (*backtrace_simple_callback)(void *data, uintptr_t pc);\n\nextern int backtrace_simple(struct backtrace_state *state, int skip,\n                            backtrace_simple_callback callback,\n                            backtrace_error_callback error_callback,\n                            void *data);\n\nextern void backtrace_print(struct backtrace_state *state, int skip, FILE *);\n\nextern int backtrace_pcinfo(struct backtrace_state *state, uintptr_t pc,\n                            backtrace_full_callback callback,\n                            backtrace_error_callback error_callback,\n                            void *data);\n\ntypedef void (*backtrace_syminfo_callback)(void *data, uintptr_t pc,\n                                           const char *symname,\n                                           uintptr_t symval, uintptr_t symsize);\n\nextern int backtrace_syminfo(struct backtrace_state *state, uintptr_t addr,\n                             backtrace_syminfo_callback callback,\n                             backtrace_error_callback error_callback,\n                             void *data);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n\n// internal.h:\n#ifndef BACKTRACE_INTERNAL_H\n#define BACKTRACE_INTERNAL_H\n\n#ifndef GCC_VERSION\n#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)\n#endif\n\n#if (GCC_VERSION < 2007)\n#define __attribute__(x)\n#endif\n\n#ifndef ATTRIBUTE_UNUSED\n#define ATTRIBUTE_UNUSED __attribute__((__unused__))\n#endif\n\n#ifndef ATTRIBUTE_MALLOC\n#if (GCC_VERSION >= 2096)\n#define ATTRIBUTE_MALLOC __attribute__((__malloc__))\n#else\n#define ATTRIBUTE_MALLOC\n#endif\n#endif\n\n#ifndef ATTRIBUTE_FALLTHROUGH\n#if (GCC_VERSION >= 7000)\n#define ATTRIBUTE_FALLTHROUGH __attribute__((__fallthrough__))\n#else\n#define ATTRIBUTE_FALLTHROUGH\n#endif\n#endif\n\n#ifndef HAVE_SYNC_FUNCTIONS\n\n#define __sync_bool_compare_and_swap(A, B, C) (abort(), 1)\n#define __sync_lock_test_and_set(A, B) (abort(), 0)\n#define __sync_lock_release(A) abort()\n\n#endif\n#ifdef HAVE_ATOMIC_FUNCTIONS\n\n#define backtrace_atomic_load_pointer(p) __atomic_load_n((p), __ATOMIC_ACQUIRE)\n#define backtrace_atomic_load_int(p) __atomic_load_n((p), __ATOMIC_ACQUIRE)\n#define backtrace_atomic_store_pointer(p, v) \\\n  __atomic_store_n((p), (v), __ATOMIC_RELEASE)\n#define backtrace_atomic_store_size_t(p, v) \\\n  __atomic_store_n((p), (v), __ATOMIC_RELEASE)\n#define backtrace_atomic_store_int(p, v) \\\n  __atomic_store_n((p), (v), __ATOMIC_RELEASE)\n\n#else\n#ifdef HAVE_SYNC_FUNCTIONS\n\nextern void *backtrace_atomic_load_pointer(void *);\nextern int backtrace_atomic_load_int(int *);\nextern void backtrace_atomic_store_pointer(void *, void *);\nextern void backtrace_atomic_store_size_t(size_t *, size_t);\nextern void backtrace_atomic_store_int(int *, int);\n\n#else\n\n#define backtrace_atomic_load_pointer(p) (abort(), (void *)NULL)\n#define backtrace_atomic_load_int(p) (abort(), 0)\n#define backtrace_atomic_store_pointer(p, v) abort()\n#define backtrace_atomic_store_size_t(p, v) abort()\n#define backtrace_atomic_store_int(p, v) abort()\n\n#endif\n#endif\n\ntypedef int (*fileline)(struct backtrace_state *state, uintptr_t pc,\n                        backtrace_full_callback callback,\n                        backtrace_error_callback error_callback, void *data);\n\ntypedef void (*syminfo)(struct backtrace_state *state, uintptr_t pc,\n                        backtrace_syminfo_callback callback,\n                        backtrace_error_callback error_callback, void *data);\n\nstruct backtrace_state {\n  const char *filename;\n\n  int threaded;\n\n  void *lock;\n\n  fileline fileline_fn;\n\n  void *fileline_data;\n\n  syminfo syminfo_fn;\n\n  void *syminfo_data;\n\n  int fileline_initialization_failed;\n\n  int lock_alloc;\n\n  struct backtrace_freelist_struct *freelist;\n};\n\nextern int backtrace_open(const char *filename,\n                          backtrace_error_callback error_callback, void *data,\n                          int *does_not_exist);\n\nstruct backtrace_view {\n  const void *data;\n\n  void *base;\n\n  size_t len;\n};\n\nextern int backtrace_get_view(struct backtrace_state *state, int descriptor,\n                              off_t offset, uint64_t size,\n                              backtrace_error_callback error_callback,\n                              void *data, struct backtrace_view *view);\n\nextern void backtrace_release_view(struct backtrace_state *state,\n                                   struct backtrace_view *view,\n                                   backtrace_error_callback error_callback,\n                                   void *data);\n\nextern int backtrace_close(int descriptor,\n                           backtrace_error_callback error_callback, void *data);\n\nextern void backtrace_qsort(void *base, size_t count, size_t size,\n                            int (*compar)(const void *, const void *));\n\nextern void *backtrace_alloc(struct backtrace_state *state, size_t size,\n                             backtrace_error_callback error_callback,\n                             void *data) ATTRIBUTE_MALLOC;\n\nextern void backtrace_free(struct backtrace_state *state, void *mem,\n                           size_t size, backtrace_error_callback error_callback,\n                           void *data);\n\nstruct backtrace_vector {\n  void *base;\n\n  size_t size;\n\n  size_t alc;\n};\n\nextern void *backtrace_vector_grow(struct backtrace_state *state, size_t size,\n                                   backtrace_error_callback error_callback,\n                                   void *data, struct backtrace_vector *vec);\n\nextern void *backtrace_vector_finish(struct backtrace_state *state,\n                                     struct backtrace_vector *vec,\n                                     backtrace_error_callback error_callback,\n                                     void *data);\n\nextern int backtrace_vector_release(struct backtrace_state *state,\n                                    struct backtrace_vector *vec,\n                                    backtrace_error_callback error_callback,\n                                    void *data);\n\nstatic inline void backtrace_vector_free(\n    struct backtrace_state *state, struct backtrace_vector *vec,\n    backtrace_error_callback error_callback, void *data) {\n  vec->alc += vec->size;\n  vec->size = 0;\n  backtrace_vector_release(state, vec, error_callback, data);\n}\n\nextern int backtrace_initialize(struct backtrace_state *state,\n                                const char *filename, int descriptor,\n                                backtrace_error_callback error_callback,\n                                void *data, fileline *fileline_fn);\n\nenum dwarf_section {\n  DEBUG_INFO,\n  DEBUG_LINE,\n  DEBUG_ABBREV,\n  DEBUG_RANGES,\n  DEBUG_STR,\n  DEBUG_ADDR,\n  DEBUG_STR_OFFSETS,\n  DEBUG_LINE_STR,\n  DEBUG_RNGLISTS,\n\n  DEBUG_MAX\n};\n\nstruct dwarf_sections {\n  const unsigned char *data[DEBUG_MAX];\n  size_t size[DEBUG_MAX];\n};\n\nstruct dwarf_data;\n\nextern int backtrace_dwarf_add(struct backtrace_state *state,\n                               uintptr_t base_address,\n                               const struct dwarf_sections *dwarf_sections,\n                               int is_bigendian,\n                               struct dwarf_data *fileline_altlink,\n                               backtrace_error_callback error_callback,\n                               void *data, fileline *fileline_fn,\n                               struct dwarf_data **fileline_entry);\n\nstruct backtrace_call_full {\n  backtrace_full_callback full_callback;\n  backtrace_error_callback full_error_callback;\n  void *full_data;\n  int ret;\n};\n\nextern void backtrace_syminfo_to_full_callback(void *data, uintptr_t pc,\n                                               const char *symname,\n                                               uintptr_t symval,\n                                               uintptr_t symsize);\n\nextern void backtrace_syminfo_to_full_error_callback(void *, const char *, int);\n\nextern int backtrace_uncompress_zdebug(struct backtrace_state *,\n                                       const unsigned char *compressed,\n                                       size_t compressed_size,\n                                       backtrace_error_callback, void *data,\n                                       unsigned char **uncompressed,\n                                       size_t *uncompressed_size);\n\nextern int backtrace_uncompress_lzma(struct backtrace_state *,\n                                     const unsigned char *compressed,\n                                     size_t compressed_size,\n                                     backtrace_error_callback, void *data,\n                                     unsigned char **uncompressed,\n                                     size_t *uncompressed_size);\n\n#endif\n\n// filenames.h:\n#ifndef GCC_VERSION\n#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)\n#endif\n\n#if (GCC_VERSION < 2007)\n#define __attribute__(x)\n#endif\n\n#ifndef ATTRIBUTE_UNUSED\n#define ATTRIBUTE_UNUSED __attribute__((__unused__))\n#endif\n\n#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || \\\n    defined(__CYGWIN__)\n#define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\\\')\n#define HAS_DRIVE_SPEC(f) ((f)[0] != '\\0' && (f)[1] == ':')\n#define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]) || HAS_DRIVE_SPEC(f))\n#else\n#define IS_DIR_SEPARATOR(c) ((c) == '/')\n#define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]))\n#endif\n\n// atomic.c:\n#include <sys/types.h>\n\n// dwarf.c:\n#include <errno.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n\nenum dwarf_tag {\n  DW_TAG_entry_point = 0x3,\n  DW_TAG_compile_unit = 0x11,\n  DW_TAG_inlined_subroutine = 0x1d,\n  DW_TAG_subprogram = 0x2e,\n  DW_TAG_skeleton_unit = 0x4a,\n};\n\nenum dwarf_form {\n  DW_FORM_addr = 0x01,\n  DW_FORM_block2 = 0x03,\n  DW_FORM_block4 = 0x04,\n  DW_FORM_data2 = 0x05,\n  DW_FORM_data4 = 0x06,\n  DW_FORM_data8 = 0x07,\n  DW_FORM_string = 0x08,\n  DW_FORM_block = 0x09,\n  DW_FORM_block1 = 0x0a,\n  DW_FORM_data1 = 0x0b,\n  DW_FORM_flag = 0x0c,\n  DW_FORM_sdata = 0x0d,\n  DW_FORM_strp = 0x0e,\n  DW_FORM_udata = 0x0f,\n  DW_FORM_ref_addr = 0x10,\n  DW_FORM_ref1 = 0x11,\n  DW_FORM_ref2 = 0x12,\n  DW_FORM_ref4 = 0x13,\n  DW_FORM_ref8 = 0x14,\n  DW_FORM_ref_udata = 0x15,\n  DW_FORM_indirect = 0x16,\n  DW_FORM_sec_offset = 0x17,\n  DW_FORM_exprloc = 0x18,\n  DW_FORM_flag_present = 0x19,\n  DW_FORM_ref_sig8 = 0x20,\n  DW_FORM_strx = 0x1a,\n  DW_FORM_addrx = 0x1b,\n  DW_FORM_ref_sup4 = 0x1c,\n  DW_FORM_strp_sup = 0x1d,\n  DW_FORM_data16 = 0x1e,\n  DW_FORM_line_strp = 0x1f,\n  DW_FORM_implicit_const = 0x21,\n  DW_FORM_loclistx = 0x22,\n  DW_FORM_rnglistx = 0x23,\n  DW_FORM_ref_sup8 = 0x24,\n  DW_FORM_strx1 = 0x25,\n  DW_FORM_strx2 = 0x26,\n  DW_FORM_strx3 = 0x27,\n  DW_FORM_strx4 = 0x28,\n  DW_FORM_addrx1 = 0x29,\n  DW_FORM_addrx2 = 0x2a,\n  DW_FORM_addrx3 = 0x2b,\n  DW_FORM_addrx4 = 0x2c,\n  DW_FORM_GNU_addr_index = 0x1f01,\n  DW_FORM_GNU_str_index = 0x1f02,\n  DW_FORM_GNU_ref_alt = 0x1f20,\n  DW_FORM_GNU_strp_alt = 0x1f21\n};\n\nenum dwarf_attribute {\n  DW_AT_sibling = 0x01,\n  DW_AT_location = 0x02,\n  DW_AT_name = 0x03,\n  DW_AT_ordering = 0x09,\n  DW_AT_subscr_data = 0x0a,\n  DW_AT_byte_size = 0x0b,\n  DW_AT_bit_offset = 0x0c,\n  DW_AT_bit_size = 0x0d,\n  DW_AT_element_list = 0x0f,\n  DW_AT_stmt_list = 0x10,\n  DW_AT_low_pc = 0x11,\n  DW_AT_high_pc = 0x12,\n  DW_AT_language = 0x13,\n  DW_AT_member = 0x14,\n  DW_AT_discr = 0x15,\n  DW_AT_discr_value = 0x16,\n  DW_AT_visibility = 0x17,\n  DW_AT_import = 0x18,\n  DW_AT_string_length = 0x19,\n  DW_AT_common_reference = 0x1a,\n  DW_AT_comp_dir = 0x1b,\n  DW_AT_const_value = 0x1c,\n  DW_AT_containing_type = 0x1d,\n  DW_AT_default_value = 0x1e,\n  DW_AT_inline = 0x20,\n  DW_AT_is_optional = 0x21,\n  DW_AT_lower_bound = 0x22,\n  DW_AT_producer = 0x25,\n  DW_AT_prototyped = 0x27,\n  DW_AT_return_addr = 0x2a,\n  DW_AT_start_scope = 0x2c,\n  DW_AT_bit_stride = 0x2e,\n  DW_AT_upper_bound = 0x2f,\n  DW_AT_abstract_origin = 0x31,\n  DW_AT_accessibility = 0x32,\n  DW_AT_address_class = 0x33,\n  DW_AT_artificial = 0x34,\n  DW_AT_base_types = 0x35,\n  DW_AT_calling_convention = 0x36,\n  DW_AT_count = 0x37,\n  DW_AT_data_member_location = 0x38,\n  DW_AT_decl_column = 0x39,\n  DW_AT_decl_file = 0x3a,\n  DW_AT_decl_line = 0x3b,\n  DW_AT_declaration = 0x3c,\n  DW_AT_discr_list = 0x3d,\n  DW_AT_encoding = 0x3e,\n  DW_AT_external = 0x3f,\n  DW_AT_frame_base = 0x40,\n  DW_AT_friend = 0x41,\n  DW_AT_identifier_case = 0x42,\n  DW_AT_macro_info = 0x43,\n  DW_AT_namelist_items = 0x44,\n  DW_AT_priority = 0x45,\n  DW_AT_segment = 0x46,\n  DW_AT_specification = 0x47,\n  DW_AT_static_link = 0x48,\n  DW_AT_type = 0x49,\n  DW_AT_use_location = 0x4a,\n  DW_AT_variable_parameter = 0x4b,\n  DW_AT_virtuality = 0x4c,\n  DW_AT_vtable_elem_location = 0x4d,\n  DW_AT_allocated = 0x4e,\n  DW_AT_associated = 0x4f,\n  DW_AT_data_location = 0x50,\n  DW_AT_byte_stride = 0x51,\n  DW_AT_entry_pc = 0x52,\n  DW_AT_use_UTF8 = 0x53,\n  DW_AT_extension = 0x54,\n  DW_AT_ranges = 0x55,\n  DW_AT_trampoline = 0x56,\n  DW_AT_call_column = 0x57,\n  DW_AT_call_file = 0x58,\n  DW_AT_call_line = 0x59,\n  DW_AT_description = 0x5a,\n  DW_AT_binary_scale = 0x5b,\n  DW_AT_decimal_scale = 0x5c,\n  DW_AT_small = 0x5d,\n  DW_AT_decimal_sign = 0x5e,\n  DW_AT_digit_count = 0x5f,\n  DW_AT_picture_string = 0x60,\n  DW_AT_mutable = 0x61,\n  DW_AT_threads_scaled = 0x62,\n  DW_AT_explicit = 0x63,\n  DW_AT_object_pointer = 0x64,\n  DW_AT_endianity = 0x65,\n  DW_AT_elemental = 0x66,\n  DW_AT_pure = 0x67,\n  DW_AT_recursive = 0x68,\n  DW_AT_signature = 0x69,\n  DW_AT_main_subprogram = 0x6a,\n  DW_AT_data_bit_offset = 0x6b,\n  DW_AT_const_expr = 0x6c,\n  DW_AT_enum_class = 0x6d,\n  DW_AT_linkage_name = 0x6e,\n  DW_AT_string_length_bit_size = 0x6f,\n  DW_AT_string_length_byte_size = 0x70,\n  DW_AT_rank = 0x71,\n  DW_AT_str_offsets_base = 0x72,\n  DW_AT_addr_base = 0x73,\n  DW_AT_rnglists_base = 0x74,\n  DW_AT_dwo_name = 0x76,\n  DW_AT_reference = 0x77,\n  DW_AT_rvalue_reference = 0x78,\n  DW_AT_macros = 0x79,\n  DW_AT_call_all_calls = 0x7a,\n  DW_AT_call_all_source_calls = 0x7b,\n  DW_AT_call_all_tail_calls = 0x7c,\n  DW_AT_call_return_pc = 0x7d,\n  DW_AT_call_value = 0x7e,\n  DW_AT_call_origin = 0x7f,\n  DW_AT_call_parameter = 0x80,\n  DW_AT_call_pc = 0x81,\n  DW_AT_call_tail_call = 0x82,\n  DW_AT_call_target = 0x83,\n  DW_AT_call_target_clobbered = 0x84,\n  DW_AT_call_data_location = 0x85,\n  DW_AT_call_data_value = 0x86,\n  DW_AT_noreturn = 0x87,\n  DW_AT_alignment = 0x88,\n  DW_AT_export_symbols = 0x89,\n  DW_AT_deleted = 0x8a,\n  DW_AT_defaulted = 0x8b,\n  DW_AT_loclists_base = 0x8c,\n  DW_AT_lo_user = 0x2000,\n  DW_AT_hi_user = 0x3fff,\n  DW_AT_MIPS_fde = 0x2001,\n  DW_AT_MIPS_loop_begin = 0x2002,\n  DW_AT_MIPS_tail_loop_begin = 0x2003,\n  DW_AT_MIPS_epilog_begin = 0x2004,\n  DW_AT_MIPS_loop_unroll_factor = 0x2005,\n  DW_AT_MIPS_software_pipeline_depth = 0x2006,\n  DW_AT_MIPS_linkage_name = 0x2007,\n  DW_AT_MIPS_stride = 0x2008,\n  DW_AT_MIPS_abstract_name = 0x2009,\n  DW_AT_MIPS_clone_origin = 0x200a,\n  DW_AT_MIPS_has_inlines = 0x200b,\n  DW_AT_HP_block_index = 0x2000,\n  DW_AT_HP_unmodifiable = 0x2001,\n  DW_AT_HP_prologue = 0x2005,\n  DW_AT_HP_epilogue = 0x2008,\n  DW_AT_HP_actuals_stmt_list = 0x2010,\n  DW_AT_HP_proc_per_section = 0x2011,\n  DW_AT_HP_raw_data_ptr = 0x2012,\n  DW_AT_HP_pass_by_reference = 0x2013,\n  DW_AT_HP_opt_level = 0x2014,\n  DW_AT_HP_prof_version_id = 0x2015,\n  DW_AT_HP_opt_flags = 0x2016,\n  DW_AT_HP_cold_region_low_pc = 0x2017,\n  DW_AT_HP_cold_region_high_pc = 0x2018,\n  DW_AT_HP_all_variables_modifiable = 0x2019,\n  DW_AT_HP_linkage_name = 0x201a,\n  DW_AT_HP_prof_flags = 0x201b,\n  DW_AT_HP_unit_name = 0x201f,\n  DW_AT_HP_unit_size = 0x2020,\n  DW_AT_HP_widened_byte_size = 0x2021,\n  DW_AT_HP_definition_points = 0x2022,\n  DW_AT_HP_default_location = 0x2023,\n  DW_AT_HP_is_result_param = 0x2029,\n  DW_AT_sf_names = 0x2101,\n  DW_AT_src_info = 0x2102,\n  DW_AT_mac_info = 0x2103,\n  DW_AT_src_coords = 0x2104,\n  DW_AT_body_begin = 0x2105,\n  DW_AT_body_end = 0x2106,\n  DW_AT_GNU_vector = 0x2107,\n  DW_AT_GNU_guarded_by = 0x2108,\n  DW_AT_GNU_pt_guarded_by = 0x2109,\n  DW_AT_GNU_guarded = 0x210a,\n  DW_AT_GNU_pt_guarded = 0x210b,\n  DW_AT_GNU_locks_excluded = 0x210c,\n  DW_AT_GNU_exclusive_locks_required = 0x210d,\n  DW_AT_GNU_shared_locks_required = 0x210e,\n  DW_AT_GNU_odr_signature = 0x210f,\n  DW_AT_GNU_template_name = 0x2110,\n  DW_AT_GNU_call_site_value = 0x2111,\n  DW_AT_GNU_call_site_data_value = 0x2112,\n  DW_AT_GNU_call_site_target = 0x2113,\n  DW_AT_GNU_call_site_target_clobbered = 0x2114,\n  DW_AT_GNU_tail_call = 0x2115,\n  DW_AT_GNU_all_tail_call_sites = 0x2116,\n  DW_AT_GNU_all_call_sites = 0x2117,\n  DW_AT_GNU_all_source_call_sites = 0x2118,\n  DW_AT_GNU_macros = 0x2119,\n  DW_AT_GNU_deleted = 0x211a,\n  DW_AT_GNU_dwo_name = 0x2130,\n  DW_AT_GNU_dwo_id = 0x2131,\n  DW_AT_GNU_ranges_base = 0x2132,\n  DW_AT_GNU_addr_base = 0x2133,\n  DW_AT_GNU_pubnames = 0x2134,\n  DW_AT_GNU_pubtypes = 0x2135,\n  DW_AT_GNU_discriminator = 0x2136,\n  DW_AT_GNU_locviews = 0x2137,\n  DW_AT_GNU_entry_view = 0x2138,\n  DW_AT_VMS_rtnbeg_pd_address = 0x2201,\n  DW_AT_use_GNAT_descriptive_type = 0x2301,\n  DW_AT_GNAT_descriptive_type = 0x2302,\n  DW_AT_GNU_numerator = 0x2303,\n  DW_AT_GNU_denominator = 0x2304,\n  DW_AT_GNU_bias = 0x2305,\n  DW_AT_upc_threads_scaled = 0x3210,\n  DW_AT_PGI_lbase = 0x3a00,\n  DW_AT_PGI_soffset = 0x3a01,\n  DW_AT_PGI_lstride = 0x3a02,\n  DW_AT_APPLE_optimized = 0x3fe1,\n  DW_AT_APPLE_flags = 0x3fe2,\n  DW_AT_APPLE_isa = 0x3fe3,\n  DW_AT_APPLE_block = 0x3fe4,\n  DW_AT_APPLE_major_runtime_vers = 0x3fe5,\n  DW_AT_APPLE_runtime_class = 0x3fe6,\n  DW_AT_APPLE_omit_frame_ptr = 0x3fe7,\n  DW_AT_APPLE_property_name = 0x3fe8,\n  DW_AT_APPLE_property_getter = 0x3fe9,\n  DW_AT_APPLE_property_setter = 0x3fea,\n  DW_AT_APPLE_property_attribute = 0x3feb,\n  DW_AT_APPLE_objc_complete_type = 0x3fec,\n  DW_AT_APPLE_property = 0x3fed\n};\n\nenum dwarf_line_number_op {\n  DW_LNS_extended_op = 0x0,\n  DW_LNS_copy = 0x1,\n  DW_LNS_advance_pc = 0x2,\n  DW_LNS_advance_line = 0x3,\n  DW_LNS_set_file = 0x4,\n  DW_LNS_set_column = 0x5,\n  DW_LNS_negate_stmt = 0x6,\n  DW_LNS_set_basic_block = 0x7,\n  DW_LNS_const_add_pc = 0x8,\n  DW_LNS_fixed_advance_pc = 0x9,\n  DW_LNS_set_prologue_end = 0xa,\n  DW_LNS_set_epilogue_begin = 0xb,\n  DW_LNS_set_isa = 0xc,\n};\n\nenum dwarf_extended_line_number_op {\n  DW_LNE_end_sequence = 0x1,\n  DW_LNE_set_address = 0x2,\n  DW_LNE_define_file = 0x3,\n  DW_LNE_set_discriminator = 0x4,\n};\n\nenum dwarf_line_number_content_type {\n  DW_LNCT_path = 0x1,\n  DW_LNCT_directory_index = 0x2,\n  DW_LNCT_timestamp = 0x3,\n  DW_LNCT_size = 0x4,\n  DW_LNCT_MD5 = 0x5,\n  DW_LNCT_lo_user = 0x2000,\n  DW_LNCT_hi_user = 0x3fff\n};\n\nenum dwarf_range_list_entry {\n  DW_RLE_end_of_list = 0x00,\n  DW_RLE_base_addressx = 0x01,\n  DW_RLE_startx_endx = 0x02,\n  DW_RLE_startx_length = 0x03,\n  DW_RLE_offset_pair = 0x04,\n  DW_RLE_base_address = 0x05,\n  DW_RLE_start_end = 0x06,\n  DW_RLE_start_length = 0x07\n};\n\nenum dwarf_unit_type {\n  DW_UT_compile = 0x01,\n  DW_UT_type = 0x02,\n  DW_UT_partial = 0x03,\n  DW_UT_skeleton = 0x04,\n  DW_UT_split_compile = 0x05,\n  DW_UT_split_type = 0x06,\n  DW_UT_lo_user = 0x80,\n  DW_UT_hi_user = 0xff\n};\n\n#if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN\n\nstatic size_t xstrnlen(const char *s, size_t maxlen) {\n  size_t i;\n\n  for (i = 0; i < maxlen; ++i)\n    if (s[i] == '\\0') break;\n  return i;\n}\n\n#define strnlen xstrnlen\n\n#endif\n\nstruct dwarf_buf {\n  const char *name;\n\n  const unsigned char *start;\n\n  const unsigned char *buf;\n\n  size_t left;\n\n  int is_bigendian;\n\n  backtrace_error_callback error_callback;\n\n  void *data;\n\n  int reported_underflow;\n};\n\nstruct attr {\n  enum dwarf_attribute name;\n\n  enum dwarf_form form;\n\n  int64_t val;\n};\n\nstruct abbrev {\n  uint64_t code;\n\n  enum dwarf_tag tag;\n\n  int has_children;\n\n  size_t num_attrs;\n\n  struct attr *attrs;\n};\n\nstruct abbrevs {\n  size_t num_abbrevs;\n\n  struct abbrev *abbrevs;\n};\n\nenum attr_val_encoding {\n\n  ATTR_VAL_NONE,\n\n  ATTR_VAL_ADDRESS,\n\n  ATTR_VAL_ADDRESS_INDEX,\n\n  ATTR_VAL_UINT,\n\n  ATTR_VAL_SINT,\n\n  ATTR_VAL_STRING,\n\n  ATTR_VAL_STRING_INDEX,\n\n  ATTR_VAL_REF_UNIT,\n\n  ATTR_VAL_REF_INFO,\n\n  ATTR_VAL_REF_ALT_INFO,\n\n  ATTR_VAL_REF_SECTION,\n\n  ATTR_VAL_REF_TYPE,\n\n  ATTR_VAL_RNGLISTS_INDEX,\n\n  ATTR_VAL_BLOCK,\n\n  ATTR_VAL_EXPR,\n};\n\nstruct attr_val {\n  enum attr_val_encoding encoding;\n  union {\n    uint64_t uint;\n\n    int64_t sint;\n\n    const char *string;\n\n  } u;\n};\n\nstruct line_header {\n  int version;\n\n  int addrsize;\n\n  unsigned int min_insn_len;\n\n  unsigned int max_ops_per_insn;\n\n  int line_base;\n\n  unsigned int line_range;\n\n  unsigned int opcode_base;\n\n  const unsigned char *opcode_lengths;\n\n  size_t dirs_count;\n\n  const char **dirs;\n\n  size_t filenames_count;\n\n  const char **filenames;\n};\n\nstruct line_header_format {\n  int lnct;\n  enum dwarf_form form;\n};\n\nstruct line {\n  uintptr_t pc;\n\n  const char *filename;\n\n  int lineno;\n\n  int idx;\n};\n\nstruct line_vector {\n  struct backtrace_vector vec;\n\n  size_t count;\n};\n\nstruct function {\n  const char *name;\n\n  const char *caller_filename;\n\n  int caller_lineno;\n\n  struct function_addrs *function_addrs;\n  size_t function_addrs_count;\n};\n\nstruct function_addrs {\n  uint64_t low;\n  uint64_t high;\n\n  struct function *function;\n};\n\nstruct function_vector {\n  struct backtrace_vector vec;\n\n  size_t count;\n};\n\nstruct unit {\n  const unsigned char *unit_data;\n\n  size_t unit_data_len;\n\n  size_t unit_data_offset;\n\n  size_t low_offset;\n\n  size_t high_offset;\n\n  int version;\n\n  int is_dwarf64;\n\n  int addrsize;\n\n  off_t lineoff;\n\n  uint64_t str_offsets_base;\n\n  uint64_t addr_base;\n\n  uint64_t rnglists_base;\n\n  const char *filename;\n\n  const char *comp_dir;\n\n  const char *abs_filename;\n\n  struct abbrevs abbrevs;\n\n  struct line *lines;\n\n  size_t lines_count;\n\n  struct function_addrs *function_addrs;\n  size_t function_addrs_count;\n};\n\nstruct unit_addrs {\n  uint64_t low;\n  uint64_t high;\n\n  struct unit *u;\n};\n\nstruct unit_addrs_vector {\n  struct backtrace_vector vec;\n\n  size_t count;\n};\n\nstruct unit_vector {\n  struct backtrace_vector vec;\n  size_t count;\n};\n\nstruct dwarf_data {\n  struct dwarf_data *next;\n\n  struct dwarf_data *altlink;\n\n  uintptr_t base_address;\n\n  struct unit_addrs *addrs;\n\n  size_t addrs_count;\n\n  struct unit **units;\n\n  size_t units_count;\n\n  struct dwarf_sections dwarf_sections;\n\n  int is_bigendian;\n\n  struct function_vector fvec;\n};\n\nstatic void dwarf_buf_error(struct dwarf_buf *buf, const char *msg,\n                            int errnum) {\n  char b[200];\n\n  snprintf(b, sizeof b, \"%s in %s at %d\", msg, buf->name,\n           (int)(buf->buf - buf->start));\n  buf->error_callback(buf->data, b, errnum);\n}\n\nstatic int require(struct dwarf_buf *buf, size_t count) {\n  if (buf->left >= count) return 1;\n\n  if (!buf->reported_underflow) {\n    dwarf_buf_error(buf, \"DWARF underflow\", 0);\n    buf->reported_underflow = 1;\n  }\n\n  return 0;\n}\n\nstatic int advance(struct dwarf_buf *buf, size_t count) {\n  if (!require(buf, count)) return 0;\n  buf->buf += count;\n  buf->left -= count;\n  return 1;\n}\n\nstatic const char *read_string(struct dwarf_buf *buf) {\n  const char *p = (const char *)buf->buf;\n  size_t len = strnlen(p, buf->left);\n\n  size_t count = len + 1;\n\n  if (!advance(buf, count)) return NULL;\n\n  return p;\n}\n\nstatic unsigned char read_byte(struct dwarf_buf *buf) {\n  const unsigned char *p = buf->buf;\n\n  if (!advance(buf, 1)) return 0;\n  return p[0];\n}\n\nstatic signed char read_sbyte(struct dwarf_buf *buf) {\n  const unsigned char *p = buf->buf;\n\n  if (!advance(buf, 1)) return 0;\n  return (*p ^ 0x80) - 0x80;\n}\n\nstatic uint16_t read_uint16(struct dwarf_buf *buf) {\n  const unsigned char *p = buf->buf;\n\n  if (!advance(buf, 2)) return 0;\n  if (buf->is_bigendian)\n    return ((uint16_t)p[0] << 8) | (uint16_t)p[1];\n  else\n    return ((uint16_t)p[1] << 8) | (uint16_t)p[0];\n}\n\nstatic uint32_t read_uint24(struct dwarf_buf *buf) {\n  const unsigned char *p = buf->buf;\n\n  if (!advance(buf, 3)) return 0;\n  if (buf->is_bigendian)\n    return (((uint32_t)p[0] << 16) | ((uint32_t)p[1] << 8) | (uint32_t)p[2]);\n  else\n    return (((uint32_t)p[2] << 16) | ((uint32_t)p[1] << 8) | (uint32_t)p[0]);\n}\n\nstatic uint32_t read_uint32(struct dwarf_buf *buf) {\n  const unsigned char *p = buf->buf;\n\n  if (!advance(buf, 4)) return 0;\n  if (buf->is_bigendian)\n    return (((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) |\n            ((uint32_t)p[2] << 8) | (uint32_t)p[3]);\n  else\n    return (((uint32_t)p[3] << 24) | ((uint32_t)p[2] << 16) |\n            ((uint32_t)p[1] << 8) | (uint32_t)p[0]);\n}\n\nstatic uint64_t read_uint64(struct dwarf_buf *buf) {\n  const unsigned char *p = buf->buf;\n\n  if (!advance(buf, 8)) return 0;\n  if (buf->is_bigendian)\n    return (((uint64_t)p[0] << 56) | ((uint64_t)p[1] << 48) |\n            ((uint64_t)p[2] << 40) | ((uint64_t)p[3] << 32) |\n            ((uint64_t)p[4] << 24) | ((uint64_t)p[5] << 16) |\n            ((uint64_t)p[6] << 8) | (uint64_t)p[7]);\n  else\n    return (((uint64_t)p[7] << 56) | ((uint64_t)p[6] << 48) |\n            ((uint64_t)p[5] << 40) | ((uint64_t)p[4] << 32) |\n            ((uint64_t)p[3] << 24) | ((uint64_t)p[2] << 16) |\n            ((uint64_t)p[1] << 8) | (uint64_t)p[0]);\n}\n\nstatic uint64_t read_offset(struct dwarf_buf *buf, int is_dwarf64) {\n  if (is_dwarf64)\n    return read_uint64(buf);\n  else\n    return read_uint32(buf);\n}\n\nstatic uint64_t read_address(struct dwarf_buf *buf, int addrsize) {\n  switch (addrsize) {\n    case 1:\n      return read_byte(buf);\n    case 2:\n      return read_uint16(buf);\n    case 4:\n      return read_uint32(buf);\n    case 8:\n      return read_uint64(buf);\n    default:\n      dwarf_buf_error(buf, \"unrecognized address size\", 0);\n      return 0;\n  }\n}\n\nstatic int is_highest_address(uint64_t address, int addrsize) {\n  switch (addrsize) {\n    case 1:\n      return address == (unsigned char)-1;\n    case 2:\n      return address == (uint16_t)-1;\n    case 4:\n      return address == (uint32_t)-1;\n    case 8:\n      return address == (uint64_t)-1;\n    default:\n      return 0;\n  }\n}\n\nstatic uint64_t read_uleb128(struct dwarf_buf *buf) {\n  uint64_t ret;\n  unsigned int shift;\n  int overflow;\n  unsigned char b;\n\n  ret = 0;\n  shift = 0;\n  overflow = 0;\n  do {\n    const unsigned char *p;\n\n    p = buf->buf;\n    if (!advance(buf, 1)) return 0;\n    b = *p;\n    if (shift < 64)\n      ret |= ((uint64_t)(b & 0x7f)) << shift;\n    else if (!overflow) {\n      dwarf_buf_error(buf, \"LEB128 overflows uint64_t\", 0);\n      overflow = 1;\n    }\n    shift += 7;\n  } while ((b & 0x80) != 0);\n\n  return ret;\n}\n\nstatic int64_t read_sleb128(struct dwarf_buf *buf) {\n  uint64_t val;\n  unsigned int shift;\n  int overflow;\n  unsigned char b;\n\n  val = 0;\n  shift = 0;\n  overflow = 0;\n  do {\n    const unsigned char *p;\n\n    p = buf->buf;\n    if (!advance(buf, 1)) return 0;\n    b = *p;\n    if (shift < 64)\n      val |= ((uint64_t)(b & 0x7f)) << shift;\n    else if (!overflow) {\n      dwarf_buf_error(buf, \"signed LEB128 overflows uint64_t\", 0);\n      overflow = 1;\n    }\n    shift += 7;\n  } while ((b & 0x80) != 0);\n\n  if ((b & 0x40) != 0 && shift < 64) val |= ((uint64_t)-1) << shift;\n\n  return (int64_t)val;\n}\n\nstatic size_t leb128_len(const unsigned char *p) {\n  size_t ret;\n\n  ret = 1;\n  while ((*p & 0x80) != 0) {\n    ++p;\n    ++ret;\n  }\n  return ret;\n}\n\nstatic uint64_t read_initial_length(struct dwarf_buf *buf, int *is_dwarf64) {\n  uint64_t len;\n\n  len = read_uint32(buf);\n  if (len == 0xffffffff) {\n    len = read_uint64(buf);\n    *is_dwarf64 = 1;\n  } else\n    *is_dwarf64 = 0;\n\n  return len;\n}\n\nstatic void free_abbrevs(struct backtrace_state *state, struct abbrevs *abbrevs,\n                         backtrace_error_callback error_callback, void *data) {\n  size_t i;\n\n  for (i = 0; i < abbrevs->num_abbrevs; ++i)\n    backtrace_free(state, abbrevs->abbrevs[i].attrs,\n                   abbrevs->abbrevs[i].num_attrs * sizeof(struct attr),\n                   error_callback, data);\n  backtrace_free(state, abbrevs->abbrevs,\n                 abbrevs->num_abbrevs * sizeof(struct abbrev), error_callback,\n                 data);\n  abbrevs->num_abbrevs = 0;\n  abbrevs->abbrevs = NULL;\n}\n\nstatic int read_attribute(enum dwarf_form form, uint64_t implicit_val,\n                          struct dwarf_buf *buf, int is_dwarf64, int version,\n                          int addrsize,\n                          const struct dwarf_sections *dwarf_sections,\n                          struct dwarf_data *altlink, struct attr_val *val) {\n  memset(val, 0, sizeof *val);\n\n  switch (form) {\n    case DW_FORM_addr:\n      val->encoding = ATTR_VAL_ADDRESS;\n      val->u.uint = read_address(buf, addrsize);\n      return 1;\n    case DW_FORM_block2:\n      val->encoding = ATTR_VAL_BLOCK;\n      return advance(buf, read_uint16(buf));\n    case DW_FORM_block4:\n      val->encoding = ATTR_VAL_BLOCK;\n      return advance(buf, read_uint32(buf));\n    case DW_FORM_data2:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = read_uint16(buf);\n      return 1;\n    case DW_FORM_data4:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = read_uint32(buf);\n      return 1;\n    case DW_FORM_data8:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = read_uint64(buf);\n      return 1;\n    case DW_FORM_data16:\n      val->encoding = ATTR_VAL_BLOCK;\n      return advance(buf, 16);\n    case DW_FORM_string:\n      val->encoding = ATTR_VAL_STRING;\n      val->u.string = read_string(buf);\n      return val->u.string == NULL ? 0 : 1;\n    case DW_FORM_block:\n      val->encoding = ATTR_VAL_BLOCK;\n      return advance(buf, read_uleb128(buf));\n    case DW_FORM_block1:\n      val->encoding = ATTR_VAL_BLOCK;\n      return advance(buf, read_byte(buf));\n    case DW_FORM_data1:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = read_byte(buf);\n      return 1;\n    case DW_FORM_flag:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = read_byte(buf);\n      return 1;\n    case DW_FORM_sdata:\n      val->encoding = ATTR_VAL_SINT;\n      val->u.sint = read_sleb128(buf);\n      return 1;\n    case DW_FORM_strp: {\n      uint64_t offset;\n\n      offset = read_offset(buf, is_dwarf64);\n      if (offset >= dwarf_sections->size[DEBUG_STR]) {\n        dwarf_buf_error(buf, \"DW_FORM_strp out of range\", 0);\n        return 0;\n      }\n      val->encoding = ATTR_VAL_STRING;\n      val->u.string = (const char *)dwarf_sections->data[DEBUG_STR] + offset;\n      return 1;\n    }\n    case DW_FORM_line_strp: {\n      uint64_t offset;\n\n      offset = read_offset(buf, is_dwarf64);\n      if (offset >= dwarf_sections->size[DEBUG_LINE_STR]) {\n        dwarf_buf_error(buf, \"DW_FORM_line_strp out of range\", 0);\n        return 0;\n      }\n      val->encoding = ATTR_VAL_STRING;\n      val->u.string =\n          (const char *)dwarf_sections->data[DEBUG_LINE_STR] + offset;\n      return 1;\n    }\n    case DW_FORM_udata:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = read_uleb128(buf);\n      return 1;\n    case DW_FORM_ref_addr:\n      val->encoding = ATTR_VAL_REF_INFO;\n      if (version == 2)\n        val->u.uint = read_address(buf, addrsize);\n      else\n        val->u.uint = read_offset(buf, is_dwarf64);\n      return 1;\n    case DW_FORM_ref1:\n      val->encoding = ATTR_VAL_REF_UNIT;\n      val->u.uint = read_byte(buf);\n      return 1;\n    case DW_FORM_ref2:\n      val->encoding = ATTR_VAL_REF_UNIT;\n      val->u.uint = read_uint16(buf);\n      return 1;\n    case DW_FORM_ref4:\n      val->encoding = ATTR_VAL_REF_UNIT;\n      val->u.uint = read_uint32(buf);\n      return 1;\n    case DW_FORM_ref8:\n      val->encoding = ATTR_VAL_REF_UNIT;\n      val->u.uint = read_uint64(buf);\n      return 1;\n    case DW_FORM_ref_udata:\n      val->encoding = ATTR_VAL_REF_UNIT;\n      val->u.uint = read_uleb128(buf);\n      return 1;\n    case DW_FORM_indirect: {\n      uint64_t form;\n\n      form = read_uleb128(buf);\n      if (form == DW_FORM_implicit_const) {\n        dwarf_buf_error(buf, \"DW_FORM_indirect to DW_FORM_implicit_const\", 0);\n        return 0;\n      }\n      return read_attribute((enum dwarf_form)form, 0, buf, is_dwarf64, version,\n                            addrsize, dwarf_sections, altlink, val);\n    }\n    case DW_FORM_sec_offset:\n      val->encoding = ATTR_VAL_REF_SECTION;\n      val->u.uint = read_offset(buf, is_dwarf64);\n      return 1;\n    case DW_FORM_exprloc:\n      val->encoding = ATTR_VAL_EXPR;\n      return advance(buf, read_uleb128(buf));\n    case DW_FORM_flag_present:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = 1;\n      return 1;\n    case DW_FORM_ref_sig8:\n      val->encoding = ATTR_VAL_REF_TYPE;\n      val->u.uint = read_uint64(buf);\n      return 1;\n    case DW_FORM_strx:\n    case DW_FORM_strx1:\n    case DW_FORM_strx2:\n    case DW_FORM_strx3:\n    case DW_FORM_strx4: {\n      uint64_t offset;\n\n      switch (form) {\n        case DW_FORM_strx:\n          offset = read_uleb128(buf);\n          break;\n        case DW_FORM_strx1:\n          offset = read_byte(buf);\n          break;\n        case DW_FORM_strx2:\n          offset = read_uint16(buf);\n          break;\n        case DW_FORM_strx3:\n          offset = read_uint24(buf);\n          break;\n        case DW_FORM_strx4:\n          offset = read_uint32(buf);\n          break;\n        default:\n\n          return 0;\n      }\n      val->encoding = ATTR_VAL_STRING_INDEX;\n      val->u.uint = offset;\n      return 1;\n    }\n    case DW_FORM_addrx:\n    case DW_FORM_addrx1:\n    case DW_FORM_addrx2:\n    case DW_FORM_addrx3:\n    case DW_FORM_addrx4: {\n      uint64_t offset;\n\n      switch (form) {\n        case DW_FORM_addrx:\n          offset = read_uleb128(buf);\n          break;\n        case DW_FORM_addrx1:\n          offset = read_byte(buf);\n          break;\n        case DW_FORM_addrx2:\n          offset = read_uint16(buf);\n          break;\n        case DW_FORM_addrx3:\n          offset = read_uint24(buf);\n          break;\n        case DW_FORM_addrx4:\n          offset = read_uint32(buf);\n          break;\n        default:\n\n          return 0;\n      }\n      val->encoding = ATTR_VAL_ADDRESS_INDEX;\n      val->u.uint = offset;\n      return 1;\n    }\n    case DW_FORM_ref_sup4:\n      val->encoding = ATTR_VAL_REF_SECTION;\n      val->u.uint = read_uint32(buf);\n      return 1;\n    case DW_FORM_ref_sup8:\n      val->encoding = ATTR_VAL_REF_SECTION;\n      val->u.uint = read_uint64(buf);\n      return 1;\n    case DW_FORM_implicit_const:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = implicit_val;\n      return 1;\n    case DW_FORM_loclistx:\n\n      val->encoding = ATTR_VAL_REF_SECTION;\n      val->u.uint = read_uleb128(buf);\n      return 1;\n    case DW_FORM_rnglistx:\n      val->encoding = ATTR_VAL_RNGLISTS_INDEX;\n      val->u.uint = read_uleb128(buf);\n      return 1;\n    case DW_FORM_GNU_addr_index:\n      val->encoding = ATTR_VAL_REF_SECTION;\n      val->u.uint = read_uleb128(buf);\n      return 1;\n    case DW_FORM_GNU_str_index:\n      val->encoding = ATTR_VAL_REF_SECTION;\n      val->u.uint = read_uleb128(buf);\n      return 1;\n    case DW_FORM_GNU_ref_alt:\n      val->u.uint = read_offset(buf, is_dwarf64);\n      if (altlink == NULL) {\n        val->encoding = ATTR_VAL_NONE;\n        return 1;\n      }\n      val->encoding = ATTR_VAL_REF_ALT_INFO;\n      return 1;\n    case DW_FORM_strp_sup:\n    case DW_FORM_GNU_strp_alt: {\n      uint64_t offset;\n\n      offset = read_offset(buf, is_dwarf64);\n      if (altlink == NULL) {\n        val->encoding = ATTR_VAL_NONE;\n        return 1;\n      }\n      if (offset >= altlink->dwarf_sections.size[DEBUG_STR]) {\n        dwarf_buf_error(buf, \"DW_FORM_strp_sup out of range\", 0);\n        return 0;\n      }\n      val->encoding = ATTR_VAL_STRING;\n      val->u.string =\n          (const char *)altlink->dwarf_sections.data[DEBUG_STR] + offset;\n      return 1;\n    }\n    default:\n      dwarf_buf_error(buf, \"unrecognized DWARF form\", -1);\n      return 0;\n  }\n}\n\nstatic int resolve_string(const struct dwarf_sections *dwarf_sections,\n                          int is_dwarf64, int is_bigendian,\n                          uint64_t str_offsets_base, const struct attr_val *val,\n                          backtrace_error_callback error_callback, void *data,\n                          const char **string) {\n  switch (val->encoding) {\n    case ATTR_VAL_STRING:\n      *string = val->u.string;\n      return 1;\n\n    case ATTR_VAL_STRING_INDEX: {\n      uint64_t offset;\n      struct dwarf_buf offset_buf;\n\n      offset = val->u.uint * (is_dwarf64 ? 8 : 4) + str_offsets_base;\n      if (offset + (is_dwarf64 ? 8 : 4) >\n          dwarf_sections->size[DEBUG_STR_OFFSETS]) {\n        error_callback(data, \"DW_FORM_strx value out of range\", 0);\n        return 0;\n      }\n\n      offset_buf.name = \".debug_str_offsets\";\n      offset_buf.start = dwarf_sections->data[DEBUG_STR_OFFSETS];\n      offset_buf.buf = dwarf_sections->data[DEBUG_STR_OFFSETS] + offset;\n      offset_buf.left = dwarf_sections->size[DEBUG_STR_OFFSETS] - offset;\n      offset_buf.is_bigendian = is_bigendian;\n      offset_buf.error_callback = error_callback;\n      offset_buf.data = data;\n      offset_buf.reported_underflow = 0;\n\n      offset = read_offset(&offset_buf, is_dwarf64);\n      if (offset >= dwarf_sections->size[DEBUG_STR]) {\n        dwarf_buf_error(&offset_buf, \"DW_FORM_strx offset out of range\", 0);\n        return 0;\n      }\n      *string = (const char *)dwarf_sections->data[DEBUG_STR] + offset;\n      return 1;\n    }\n\n    default:\n      return 1;\n  }\n}\n\nstatic int resolve_addr_index(const struct dwarf_sections *dwarf_sections,\n                              uint64_t addr_base, int addrsize,\n                              int is_bigendian, uint64_t addr_index,\n                              backtrace_error_callback error_callback,\n                              void *data, uint64_t *address) {\n  uint64_t offset;\n  struct dwarf_buf addr_buf;\n\n  offset = addr_index * addrsize + addr_base;\n  if (offset + addrsize > dwarf_sections->size[DEBUG_ADDR]) {\n    error_callback(data, \"DW_FORM_addrx value out of range\", 0);\n    return 0;\n  }\n\n  addr_buf.name = \".debug_addr\";\n  addr_buf.start = dwarf_sections->data[DEBUG_ADDR];\n  addr_buf.buf = dwarf_sections->data[DEBUG_ADDR] + offset;\n  addr_buf.left = dwarf_sections->size[DEBUG_ADDR] - offset;\n  addr_buf.is_bigendian = is_bigendian;\n  addr_buf.error_callback = error_callback;\n  addr_buf.data = data;\n  addr_buf.reported_underflow = 0;\n\n  *address = read_address(&addr_buf, addrsize);\n  return 1;\n}\n\nstatic int units_search(const void *vkey, const void *ventry) {\n  const size_t *key = (const size_t *)vkey;\n  const struct unit *entry = *((const struct unit *const *)ventry);\n  size_t offset;\n\n  offset = *key;\n  if (offset < entry->low_offset)\n    return -1;\n  else if (offset >= entry->high_offset)\n    return 1;\n  else\n    return 0;\n}\n\nstatic struct unit *find_unit(struct unit **pu, size_t units_count,\n                              size_t offset) {\n  struct unit **u;\n  u = bsearch(&offset, pu, units_count, sizeof(struct unit *), units_search);\n  return u == NULL ? NULL : *u;\n}\n\nstatic int function_addrs_compare(const void *v1, const void *v2) {\n  const struct function_addrs *a1 = (const struct function_addrs *)v1;\n  const struct function_addrs *a2 = (const struct function_addrs *)v2;\n\n  if (a1->low < a2->low) return -1;\n  if (a1->low > a2->low) return 1;\n  if (a1->high < a2->high) return 1;\n  if (a1->high > a2->high) return -1;\n  return strcmp(a1->function->name, a2->function->name);\n}\n\nstatic int function_addrs_search(const void *vkey, const void *ventry) {\n  const uintptr_t *key = (const uintptr_t *)vkey;\n  const struct function_addrs *entry = (const struct function_addrs *)ventry;\n  uintptr_t pc;\n\n  pc = *key;\n  if (pc < entry->low)\n    return -1;\n  else if (pc > (entry + 1)->low)\n    return 1;\n  else\n    return 0;\n}\n\nstatic int add_unit_addr(struct backtrace_state *state, void *rdata,\n                         uint64_t lowpc, uint64_t highpc,\n                         backtrace_error_callback error_callback, void *data,\n                         void *pvec) {\n  struct unit *u = (struct unit *)rdata;\n  struct unit_addrs_vector *vec = (struct unit_addrs_vector *)pvec;\n  struct unit_addrs *p;\n\n  if (vec->count > 0) {\n    p = (struct unit_addrs *)vec->vec.base + (vec->count - 1);\n    if ((lowpc == p->high || lowpc == p->high + 1) && u == p->u) {\n      if (highpc > p->high) p->high = highpc;\n      return 1;\n    }\n  }\n\n  p = ((struct unit_addrs *)backtrace_vector_grow(\n      state, sizeof(struct unit_addrs), error_callback, data, &vec->vec));\n  if (p == NULL) return 0;\n\n  p->low = lowpc;\n  p->high = highpc;\n  p->u = u;\n\n  ++vec->count;\n\n  return 1;\n}\n\nstatic int unit_addrs_compare(const void *v1, const void *v2) {\n  const struct unit_addrs *a1 = (const struct unit_addrs *)v1;\n  const struct unit_addrs *a2 = (const struct unit_addrs *)v2;\n\n  if (a1->low < a2->low) return -1;\n  if (a1->low > a2->low) return 1;\n  if (a1->high < a2->high) return 1;\n  if (a1->high > a2->high) return -1;\n  if (a1->u->lineoff < a2->u->lineoff) return -1;\n  if (a1->u->lineoff > a2->u->lineoff) return 1;\n  return 0;\n}\n\nstatic int unit_addrs_search(const void *vkey, const void *ventry) {\n  const uintptr_t *key = (const uintptr_t *)vkey;\n  const struct unit_addrs *entry = (const struct unit_addrs *)ventry;\n  uintptr_t pc;\n\n  pc = *key;\n  if (pc < entry->low)\n    return -1;\n  else if (pc > (entry + 1)->low)\n    return 1;\n  else\n    return 0;\n}\n\nstatic int line_compare(const void *v1, const void *v2) {\n  const struct line *ln1 = (const struct line *)v1;\n  const struct line *ln2 = (const struct line *)v2;\n\n  if (ln1->pc < ln2->pc)\n    return -1;\n  else if (ln1->pc > ln2->pc)\n    return 1;\n  else if (ln1->idx < ln2->idx)\n    return -1;\n  else if (ln1->idx > ln2->idx)\n    return 1;\n  else\n    return 0;\n}\n\nstatic int line_search(const void *vkey, const void *ventry) {\n  const uintptr_t *key = (const uintptr_t *)vkey;\n  const struct line *entry = (const struct line *)ventry;\n  uintptr_t pc;\n\n  pc = *key;\n  if (pc < entry->pc)\n    return -1;\n  else if (pc >= (entry + 1)->pc)\n    return 1;\n  else\n    return 0;\n}\n\nstatic int abbrev_compare(const void *v1, const void *v2) {\n  const struct abbrev *a1 = (const struct abbrev *)v1;\n  const struct abbrev *a2 = (const struct abbrev *)v2;\n\n  if (a1->code < a2->code)\n    return -1;\n  else if (a1->code > a2->code)\n    return 1;\n  else {\n    return 0;\n  }\n}\n\nstatic int read_abbrevs(struct backtrace_state *state, uint64_t abbrev_offset,\n                        const unsigned char *dwarf_abbrev,\n                        size_t dwarf_abbrev_size, int is_bigendian,\n                        backtrace_error_callback error_callback, void *data,\n                        struct abbrevs *abbrevs) {\n  struct dwarf_buf abbrev_buf;\n  struct dwarf_buf count_buf;\n  size_t num_abbrevs;\n\n  abbrevs->num_abbrevs = 0;\n  abbrevs->abbrevs = NULL;\n\n  if (abbrev_offset >= dwarf_abbrev_size) {\n    error_callback(data, \"abbrev offset out of range\", 0);\n    return 0;\n  }\n\n  abbrev_buf.name = \".debug_abbrev\";\n  abbrev_buf.start = dwarf_abbrev;\n  abbrev_buf.buf = dwarf_abbrev + abbrev_offset;\n  abbrev_buf.left = dwarf_abbrev_size - abbrev_offset;\n  abbrev_buf.is_bigendian = is_bigendian;\n  abbrev_buf.error_callback = error_callback;\n  abbrev_buf.data = data;\n  abbrev_buf.reported_underflow = 0;\n\n  count_buf = abbrev_buf;\n  num_abbrevs = 0;\n  while (read_uleb128(&count_buf) != 0) {\n    if (count_buf.reported_underflow) return 0;\n    ++num_abbrevs;\n\n    read_uleb128(&count_buf);\n\n    read_byte(&count_buf);\n\n    while (read_uleb128(&count_buf) != 0) {\n      uint64_t form;\n\n      form = read_uleb128(&count_buf);\n      if ((enum dwarf_form)form == DW_FORM_implicit_const)\n        read_sleb128(&count_buf);\n    }\n\n    read_uleb128(&count_buf);\n  }\n\n  if (count_buf.reported_underflow) return 0;\n\n  if (num_abbrevs == 0) return 1;\n\n  abbrevs->abbrevs = ((struct abbrev *)backtrace_alloc(\n      state, num_abbrevs * sizeof(struct abbrev), error_callback, data));\n  if (abbrevs->abbrevs == NULL) return 0;\n  abbrevs->num_abbrevs = num_abbrevs;\n  memset(abbrevs->abbrevs, 0, num_abbrevs * sizeof(struct abbrev));\n\n  num_abbrevs = 0;\n  while (1) {\n    uint64_t code;\n    struct abbrev a;\n    size_t num_attrs;\n    struct attr *attrs;\n\n    if (abbrev_buf.reported_underflow) goto fail;\n\n    code = read_uleb128(&abbrev_buf);\n    if (code == 0) break;\n\n    a.code = code;\n    a.tag = (enum dwarf_tag)read_uleb128(&abbrev_buf);\n    a.has_children = read_byte(&abbrev_buf);\n\n    count_buf = abbrev_buf;\n    num_attrs = 0;\n    while (read_uleb128(&count_buf) != 0) {\n      uint64_t form;\n\n      ++num_attrs;\n      form = read_uleb128(&count_buf);\n      if ((enum dwarf_form)form == DW_FORM_implicit_const)\n        read_sleb128(&count_buf);\n    }\n\n    if (num_attrs == 0) {\n      attrs = NULL;\n      read_uleb128(&abbrev_buf);\n      read_uleb128(&abbrev_buf);\n    } else {\n      attrs = ((struct attr *)backtrace_alloc(state, num_attrs * sizeof *attrs,\n                                              error_callback, data));\n      if (attrs == NULL) goto fail;\n      num_attrs = 0;\n      while (1) {\n        uint64_t name;\n        uint64_t form;\n\n        name = read_uleb128(&abbrev_buf);\n        form = read_uleb128(&abbrev_buf);\n        if (name == 0) break;\n        attrs[num_attrs].name = (enum dwarf_attribute)name;\n        attrs[num_attrs].form = (enum dwarf_form)form;\n        if ((enum dwarf_form)form == DW_FORM_implicit_const)\n          attrs[num_attrs].val = read_sleb128(&abbrev_buf);\n        else\n          attrs[num_attrs].val = 0;\n        ++num_attrs;\n      }\n    }\n\n    a.num_attrs = num_attrs;\n    a.attrs = attrs;\n\n    abbrevs->abbrevs[num_abbrevs] = a;\n    ++num_abbrevs;\n  }\n\n  backtrace_qsort(abbrevs->abbrevs, abbrevs->num_abbrevs, sizeof(struct abbrev),\n                  abbrev_compare);\n\n  return 1;\n\nfail:\n  free_abbrevs(state, abbrevs, error_callback, data);\n  return 0;\n}\n\nstatic const struct abbrev *lookup_abbrev(\n    struct abbrevs *abbrevs, uint64_t code,\n    backtrace_error_callback error_callback, void *data) {\n  struct abbrev key;\n  void *p;\n\n  if (code - 1 < abbrevs->num_abbrevs &&\n      abbrevs->abbrevs[code - 1].code == code)\n    return &abbrevs->abbrevs[code - 1];\n\n  memset(&key, 0, sizeof key);\n  key.code = code;\n  p = bsearch(&key, abbrevs->abbrevs, abbrevs->num_abbrevs,\n              sizeof(struct abbrev), abbrev_compare);\n  if (p == NULL) {\n    error_callback(data, \"invalid abbreviation code\", 0);\n    return NULL;\n  }\n  return (const struct abbrev *)p;\n}\n\nstruct pcrange {\n  uint64_t lowpc;\n  int have_lowpc;\n  int lowpc_is_addr_index;\n  uint64_t highpc;\n  int have_highpc;\n  int highpc_is_relative;\n  int highpc_is_addr_index;\n  uint64_t ranges;\n  int have_ranges;\n  int ranges_is_index;\n};\n\nstatic void update_pcrange(const struct attr *attr, const struct attr_val *val,\n                           struct pcrange *pcrange) {\n  switch (attr->name) {\n    case DW_AT_low_pc:\n      if (val->encoding == ATTR_VAL_ADDRESS) {\n        pcrange->lowpc = val->u.uint;\n        pcrange->have_lowpc = 1;\n      } else if (val->encoding == ATTR_VAL_ADDRESS_INDEX) {\n        pcrange->lowpc = val->u.uint;\n        pcrange->have_lowpc = 1;\n        pcrange->lowpc_is_addr_index = 1;\n      }\n      break;\n\n    case DW_AT_high_pc:\n      if (val->encoding == ATTR_VAL_ADDRESS) {\n        pcrange->highpc = val->u.uint;\n        pcrange->have_highpc = 1;\n      } else if (val->encoding == ATTR_VAL_UINT) {\n        pcrange->highpc = val->u.uint;\n        pcrange->have_highpc = 1;\n        pcrange->highpc_is_relative = 1;\n      } else if (val->encoding == ATTR_VAL_ADDRESS_INDEX) {\n        pcrange->highpc = val->u.uint;\n        pcrange->have_highpc = 1;\n        pcrange->highpc_is_addr_index = 1;\n      }\n      break;\n\n    case DW_AT_ranges:\n      if (val->encoding == ATTR_VAL_UINT ||\n          val->encoding == ATTR_VAL_REF_SECTION) {\n        pcrange->ranges = val->u.uint;\n        pcrange->have_ranges = 1;\n      } else if (val->encoding == ATTR_VAL_RNGLISTS_INDEX) {\n        pcrange->ranges = val->u.uint;\n        pcrange->have_ranges = 1;\n        pcrange->ranges_is_index = 1;\n      }\n      break;\n\n    default:\n      break;\n  }\n}\n\nstatic int add_low_high_range(\n    struct backtrace_state *state, const struct dwarf_sections *dwarf_sections,\n    uintptr_t base_address, int is_bigendian, struct unit *u,\n    const struct pcrange *pcrange,\n    int (*add_range)(struct backtrace_state *state, void *rdata, uint64_t lowpc,\n                     uint64_t highpc, backtrace_error_callback error_callback,\n                     void *data, void *vec),\n    void *rdata, backtrace_error_callback error_callback, void *data,\n    void *vec) {\n  uint64_t lowpc;\n  uint64_t highpc;\n\n  lowpc = pcrange->lowpc;\n  if (pcrange->lowpc_is_addr_index) {\n    if (!resolve_addr_index(dwarf_sections, u->addr_base, u->addrsize,\n                            is_bigendian, lowpc, error_callback, data, &lowpc))\n      return 0;\n  }\n\n  highpc = pcrange->highpc;\n  if (pcrange->highpc_is_addr_index) {\n    if (!resolve_addr_index(dwarf_sections, u->addr_base, u->addrsize,\n                            is_bigendian, highpc, error_callback, data,\n                            &highpc))\n      return 0;\n  }\n  if (pcrange->highpc_is_relative) highpc += lowpc;\n\n  lowpc += base_address;\n  highpc += base_address;\n\n  return add_range(state, rdata, lowpc, highpc, error_callback, data, vec);\n}\n\nstatic int add_ranges_from_ranges(\n    struct backtrace_state *state, const struct dwarf_sections *dwarf_sections,\n    uintptr_t base_address, int is_bigendian, struct unit *u, uint64_t base,\n    const struct pcrange *pcrange,\n    int (*add_range)(struct backtrace_state *state, void *rdata, uint64_t lowpc,\n                     uint64_t highpc, backtrace_error_callback error_callback,\n                     void *data, void *vec),\n    void *rdata, backtrace_error_callback error_callback, void *data,\n    void *vec) {\n  struct dwarf_buf ranges_buf;\n\n  if (pcrange->ranges >= dwarf_sections->size[DEBUG_RANGES]) {\n    error_callback(data, \"ranges offset out of range\", 0);\n    return 0;\n  }\n\n  ranges_buf.name = \".debug_ranges\";\n  ranges_buf.start = dwarf_sections->data[DEBUG_RANGES];\n  ranges_buf.buf = dwarf_sections->data[DEBUG_RANGES] + pcrange->ranges;\n  ranges_buf.left = dwarf_sections->size[DEBUG_RANGES] - pcrange->ranges;\n  ranges_buf.is_bigendian = is_bigendian;\n  ranges_buf.error_callback = error_callback;\n  ranges_buf.data = data;\n  ranges_buf.reported_underflow = 0;\n\n  while (1) {\n    uint64_t low;\n    uint64_t high;\n\n    if (ranges_buf.reported_underflow) return 0;\n\n    low = read_address(&ranges_buf, u->addrsize);\n    high = read_address(&ranges_buf, u->addrsize);\n\n    if (low == 0 && high == 0) break;\n\n    if (is_highest_address(low, u->addrsize))\n      base = high;\n    else {\n      if (!add_range(state, rdata, low + base + base_address,\n                     high + base + base_address, error_callback, data, vec))\n        return 0;\n    }\n  }\n\n  if (ranges_buf.reported_underflow) return 0;\n\n  return 1;\n}\n\nstatic int add_ranges_from_rnglists(\n    struct backtrace_state *state, const struct dwarf_sections *dwarf_sections,\n    uintptr_t base_address, int is_bigendian, struct unit *u, uint64_t base,\n    const struct pcrange *pcrange,\n    int (*add_range)(struct backtrace_state *state, void *rdata, uint64_t lowpc,\n                     uint64_t highpc, backtrace_error_callback error_callback,\n                     void *data, void *vec),\n    void *rdata, backtrace_error_callback error_callback, void *data,\n    void *vec) {\n  uint64_t offset;\n  struct dwarf_buf rnglists_buf;\n\n  if (!pcrange->ranges_is_index)\n    offset = pcrange->ranges;\n  else\n    offset = u->rnglists_base + pcrange->ranges * (u->is_dwarf64 ? 8 : 4);\n  if (offset >= dwarf_sections->size[DEBUG_RNGLISTS]) {\n    error_callback(data, \"rnglists offset out of range\", 0);\n    return 0;\n  }\n\n  rnglists_buf.name = \".debug_rnglists\";\n  rnglists_buf.start = dwarf_sections->data[DEBUG_RNGLISTS];\n  rnglists_buf.buf = dwarf_sections->data[DEBUG_RNGLISTS] + offset;\n  rnglists_buf.left = dwarf_sections->size[DEBUG_RNGLISTS] - offset;\n  rnglists_buf.is_bigendian = is_bigendian;\n  rnglists_buf.error_callback = error_callback;\n  rnglists_buf.data = data;\n  rnglists_buf.reported_underflow = 0;\n\n  if (pcrange->ranges_is_index) {\n    offset = read_offset(&rnglists_buf, u->is_dwarf64);\n    offset += u->rnglists_base;\n    if (offset >= dwarf_sections->size[DEBUG_RNGLISTS]) {\n      error_callback(data, \"rnglists index offset out of range\", 0);\n      return 0;\n    }\n    rnglists_buf.buf = dwarf_sections->data[DEBUG_RNGLISTS] + offset;\n    rnglists_buf.left = dwarf_sections->size[DEBUG_RNGLISTS] - offset;\n  }\n\n  while (1) {\n    unsigned char rle;\n\n    rle = read_byte(&rnglists_buf);\n    if (rle == DW_RLE_end_of_list) break;\n    switch (rle) {\n      case DW_RLE_base_addressx: {\n        uint64_t index;\n\n        index = read_uleb128(&rnglists_buf);\n        if (!resolve_addr_index(dwarf_sections, u->addr_base, u->addrsize,\n                                is_bigendian, index, error_callback, data,\n                                &base))\n          return 0;\n      } break;\n\n      case DW_RLE_startx_endx: {\n        uint64_t index;\n        uint64_t low;\n        uint64_t high;\n\n        index = read_uleb128(&rnglists_buf);\n        if (!resolve_addr_index(dwarf_sections, u->addr_base, u->addrsize,\n                                is_bigendian, index, error_callback, data,\n                                &low))\n          return 0;\n        index = read_uleb128(&rnglists_buf);\n        if (!resolve_addr_index(dwarf_sections, u->addr_base, u->addrsize,\n                                is_bigendian, index, error_callback, data,\n                                &high))\n          return 0;\n        if (!add_range(state, rdata, low + base_address, high + base_address,\n                       error_callback, data, vec))\n          return 0;\n      } break;\n\n      case DW_RLE_startx_length: {\n        uint64_t index;\n        uint64_t low;\n        uint64_t length;\n\n        index = read_uleb128(&rnglists_buf);\n        if (!resolve_addr_index(dwarf_sections, u->addr_base, u->addrsize,\n                                is_bigendian, index, error_callback, data,\n                                &low))\n          return 0;\n        length = read_uleb128(&rnglists_buf);\n        low += base_address;\n        if (!add_range(state, rdata, low, low + length, error_callback, data,\n                       vec))\n          return 0;\n      } break;\n\n      case DW_RLE_offset_pair: {\n        uint64_t low;\n        uint64_t high;\n\n        low = read_uleb128(&rnglists_buf);\n        high = read_uleb128(&rnglists_buf);\n        if (!add_range(state, rdata, low + base + base_address,\n                       high + base + base_address, error_callback, data, vec))\n          return 0;\n      } break;\n\n      case DW_RLE_base_address:\n        base = read_address(&rnglists_buf, u->addrsize);\n        break;\n\n      case DW_RLE_start_end: {\n        uint64_t low;\n        uint64_t high;\n\n        low = read_address(&rnglists_buf, u->addrsize);\n        high = read_address(&rnglists_buf, u->addrsize);\n        if (!add_range(state, rdata, low + base_address, high + base_address,\n                       error_callback, data, vec))\n          return 0;\n      } break;\n\n      case DW_RLE_start_length: {\n        uint64_t low;\n        uint64_t length;\n\n        low = read_address(&rnglists_buf, u->addrsize);\n        length = read_uleb128(&rnglists_buf);\n        low += base_address;\n        if (!add_range(state, rdata, low, low + length, error_callback, data,\n                       vec))\n          return 0;\n      } break;\n\n      default:\n        dwarf_buf_error(&rnglists_buf, \"unrecognized DW_RLE value\", -1);\n        return 0;\n    }\n  }\n\n  if (rnglists_buf.reported_underflow) return 0;\n\n  return 1;\n}\n\nstatic int add_ranges(\n    struct backtrace_state *state, const struct dwarf_sections *dwarf_sections,\n    uintptr_t base_address, int is_bigendian, struct unit *u, uint64_t base,\n    const struct pcrange *pcrange,\n    int (*add_range)(struct backtrace_state *state, void *rdata, uint64_t lowpc,\n                     uint64_t highpc, backtrace_error_callback error_callback,\n                     void *data, void *vec),\n    void *rdata, backtrace_error_callback error_callback, void *data,\n    void *vec) {\n  if (pcrange->have_lowpc && pcrange->have_highpc)\n    return add_low_high_range(state, dwarf_sections, base_address, is_bigendian,\n                              u, pcrange, add_range, rdata, error_callback,\n                              data, vec);\n\n  if (!pcrange->have_ranges) {\n    return 1;\n  }\n\n  if (u->version < 5)\n    return add_ranges_from_ranges(state, dwarf_sections, base_address,\n                                  is_bigendian, u, base, pcrange, add_range,\n                                  rdata, error_callback, data, vec);\n  else\n    return add_ranges_from_rnglists(state, dwarf_sections, base_address,\n                                    is_bigendian, u, base, pcrange, add_range,\n                                    rdata, error_callback, data, vec);\n}\n\nstatic int find_address_ranges(\n    struct backtrace_state *state, uintptr_t base_address,\n    struct dwarf_buf *unit_buf, const struct dwarf_sections *dwarf_sections,\n    int is_bigendian, struct dwarf_data *altlink,\n    backtrace_error_callback error_callback, void *data, struct unit *u,\n    struct unit_addrs_vector *addrs, enum dwarf_tag *unit_tag) {\n  while (unit_buf->left > 0) {\n    uint64_t code;\n    const struct abbrev *abbrev;\n    struct pcrange pcrange;\n    struct attr_val name_val;\n    int have_name_val;\n    struct attr_val comp_dir_val;\n    int have_comp_dir_val;\n    size_t i;\n\n    code = read_uleb128(unit_buf);\n    if (code == 0) return 1;\n\n    abbrev = lookup_abbrev(&u->abbrevs, code, error_callback, data);\n    if (abbrev == NULL) return 0;\n\n    if (unit_tag != NULL) *unit_tag = abbrev->tag;\n\n    memset(&pcrange, 0, sizeof pcrange);\n    memset(&name_val, 0, sizeof name_val);\n    have_name_val = 0;\n    memset(&comp_dir_val, 0, sizeof comp_dir_val);\n    have_comp_dir_val = 0;\n    for (i = 0; i < abbrev->num_attrs; ++i) {\n      struct attr_val val;\n\n      if (!read_attribute(abbrev->attrs[i].form, abbrev->attrs[i].val, unit_buf,\n                          u->is_dwarf64, u->version, u->addrsize,\n                          dwarf_sections, altlink, &val))\n        return 0;\n\n      switch (abbrev->attrs[i].name) {\n        case DW_AT_low_pc:\n        case DW_AT_high_pc:\n        case DW_AT_ranges:\n          update_pcrange(&abbrev->attrs[i], &val, &pcrange);\n          break;\n\n        case DW_AT_stmt_list:\n          if ((abbrev->tag == DW_TAG_compile_unit ||\n               abbrev->tag == DW_TAG_skeleton_unit) &&\n              (val.encoding == ATTR_VAL_UINT ||\n               val.encoding == ATTR_VAL_REF_SECTION))\n            u->lineoff = val.u.uint;\n          break;\n\n        case DW_AT_name:\n          if (abbrev->tag == DW_TAG_compile_unit ||\n              abbrev->tag == DW_TAG_skeleton_unit) {\n            name_val = val;\n            have_name_val = 1;\n          }\n          break;\n\n        case DW_AT_comp_dir:\n          if (abbrev->tag == DW_TAG_compile_unit ||\n              abbrev->tag == DW_TAG_skeleton_unit) {\n            comp_dir_val = val;\n            have_comp_dir_val = 1;\n          }\n          break;\n\n        case DW_AT_str_offsets_base:\n          if ((abbrev->tag == DW_TAG_compile_unit ||\n               abbrev->tag == DW_TAG_skeleton_unit) &&\n              val.encoding == ATTR_VAL_REF_SECTION)\n            u->str_offsets_base = val.u.uint;\n          break;\n\n        case DW_AT_addr_base:\n          if ((abbrev->tag == DW_TAG_compile_unit ||\n               abbrev->tag == DW_TAG_skeleton_unit) &&\n              val.encoding == ATTR_VAL_REF_SECTION)\n            u->addr_base = val.u.uint;\n          break;\n\n        case DW_AT_rnglists_base:\n          if ((abbrev->tag == DW_TAG_compile_unit ||\n               abbrev->tag == DW_TAG_skeleton_unit) &&\n              val.encoding == ATTR_VAL_REF_SECTION)\n            u->rnglists_base = val.u.uint;\n          break;\n\n        default:\n          break;\n      }\n    }\n\n    if (have_name_val) {\n      if (!resolve_string(dwarf_sections, u->is_dwarf64, is_bigendian,\n                          u->str_offsets_base, &name_val, error_callback, data,\n                          &u->filename))\n        return 0;\n    }\n    if (have_comp_dir_val) {\n      if (!resolve_string(dwarf_sections, u->is_dwarf64, is_bigendian,\n                          u->str_offsets_base, &comp_dir_val, error_callback,\n                          data, &u->comp_dir))\n        return 0;\n    }\n\n    if (abbrev->tag == DW_TAG_compile_unit ||\n        abbrev->tag == DW_TAG_subprogram ||\n        abbrev->tag == DW_TAG_skeleton_unit) {\n      if (!add_ranges(state, dwarf_sections, base_address, is_bigendian, u,\n                      pcrange.lowpc, &pcrange, add_unit_addr, (void *)u,\n                      error_callback, data, (void *)addrs))\n        return 0;\n\n      if ((abbrev->tag == DW_TAG_compile_unit ||\n           abbrev->tag == DW_TAG_skeleton_unit) &&\n          (pcrange.have_ranges || (pcrange.have_lowpc && pcrange.have_highpc)))\n        return 1;\n    }\n\n    if (abbrev->has_children) {\n      if (!find_address_ranges(state, base_address, unit_buf, dwarf_sections,\n                               is_bigendian, altlink, error_callback, data, u,\n                               addrs, NULL))\n        return 0;\n    }\n  }\n\n  return 1;\n}\n\nstatic int build_address_map(struct backtrace_state *state,\n                             uintptr_t base_address,\n                             const struct dwarf_sections *dwarf_sections,\n                             int is_bigendian, struct dwarf_data *altlink,\n                             backtrace_error_callback error_callback,\n                             void *data, struct unit_addrs_vector *addrs,\n                             struct unit_vector *unit_vec) {\n  struct dwarf_buf info;\n  struct backtrace_vector units;\n  size_t units_count;\n  size_t i;\n  struct unit **pu;\n  size_t unit_offset = 0;\n  struct unit_addrs *pa;\n\n  memset(&addrs->vec, 0, sizeof addrs->vec);\n  memset(&unit_vec->vec, 0, sizeof unit_vec->vec);\n  addrs->count = 0;\n  unit_vec->count = 0;\n\n  info.name = \".debug_info\";\n  info.start = dwarf_sections->data[DEBUG_INFO];\n  info.buf = info.start;\n  info.left = dwarf_sections->size[DEBUG_INFO];\n  info.is_bigendian = is_bigendian;\n  info.error_callback = error_callback;\n  info.data = data;\n  info.reported_underflow = 0;\n\n  memset(&units, 0, sizeof units);\n  units_count = 0;\n\n  while (info.left > 0) {\n    const unsigned char *unit_data_start;\n    uint64_t len;\n    int is_dwarf64;\n    struct dwarf_buf unit_buf;\n    int version;\n    int unit_type;\n    uint64_t abbrev_offset;\n    int addrsize;\n    struct unit *u;\n    enum dwarf_tag unit_tag;\n\n    if (info.reported_underflow) goto fail;\n\n    unit_data_start = info.buf;\n\n    len = read_initial_length(&info, &is_dwarf64);\n    unit_buf = info;\n    unit_buf.left = len;\n\n    if (!advance(&info, len)) goto fail;\n\n    version = read_uint16(&unit_buf);\n    if (version < 2 || version > 5) {\n      dwarf_buf_error(&unit_buf, \"unrecognized DWARF version\", -1);\n      goto fail;\n    }\n\n    if (version < 5)\n      unit_type = 0;\n    else {\n      unit_type = read_byte(&unit_buf);\n      if (unit_type == DW_UT_type || unit_type == DW_UT_split_type) {\n        continue;\n      }\n    }\n\n    pu = ((struct unit **)backtrace_vector_grow(state, sizeof(struct unit *),\n                                                error_callback, data, &units));\n    if (pu == NULL) goto fail;\n\n    u = ((struct unit *)backtrace_alloc(state, sizeof *u, error_callback,\n                                        data));\n    if (u == NULL) goto fail;\n\n    *pu = u;\n    ++units_count;\n\n    if (version < 5)\n      addrsize = 0;\n    else\n      addrsize = read_byte(&unit_buf);\n\n    memset(&u->abbrevs, 0, sizeof u->abbrevs);\n    abbrev_offset = read_offset(&unit_buf, is_dwarf64);\n    if (!read_abbrevs(state, abbrev_offset, dwarf_sections->data[DEBUG_ABBREV],\n                      dwarf_sections->size[DEBUG_ABBREV], is_bigendian,\n                      error_callback, data, &u->abbrevs))\n      goto fail;\n\n    if (version < 5) addrsize = read_byte(&unit_buf);\n\n    switch (unit_type) {\n      case 0:\n        break;\n      case DW_UT_compile:\n      case DW_UT_partial:\n        break;\n      case DW_UT_skeleton:\n      case DW_UT_split_compile:\n        read_uint64(&unit_buf);\n        break;\n      default:\n        break;\n    }\n\n    u->low_offset = unit_offset;\n    unit_offset += len + (is_dwarf64 ? 12 : 4);\n    u->high_offset = unit_offset;\n    u->unit_data = unit_buf.buf;\n    u->unit_data_len = unit_buf.left;\n    u->unit_data_offset = unit_buf.buf - unit_data_start;\n    u->version = version;\n    u->is_dwarf64 = is_dwarf64;\n    u->addrsize = addrsize;\n    u->filename = NULL;\n    u->comp_dir = NULL;\n    u->abs_filename = NULL;\n    u->lineoff = 0;\n    u->str_offsets_base = 0;\n    u->addr_base = 0;\n    u->rnglists_base = 0;\n\n    u->lines = NULL;\n    u->lines_count = 0;\n    u->function_addrs = NULL;\n    u->function_addrs_count = 0;\n\n    if (!find_address_ranges(state, base_address, &unit_buf, dwarf_sections,\n                             is_bigendian, altlink, error_callback, data, u,\n                             addrs, &unit_tag))\n      goto fail;\n\n    if (unit_buf.reported_underflow) goto fail;\n  }\n  if (info.reported_underflow) goto fail;\n\n  pa = ((struct unit_addrs *)backtrace_vector_grow(\n      state, sizeof(struct unit_addrs), error_callback, data, &addrs->vec));\n  if (pa == NULL) goto fail;\n  pa->low = 0;\n  --pa->low;\n  pa->high = pa->low;\n  pa->u = NULL;\n\n  unit_vec->vec = units;\n  unit_vec->count = units_count;\n  return 1;\n\nfail:\n  if (units_count > 0) {\n    pu = (struct unit **)units.base;\n    for (i = 0; i < units_count; i++) {\n      free_abbrevs(state, &pu[i]->abbrevs, error_callback, data);\n      backtrace_free(state, pu[i], sizeof **pu, error_callback, data);\n    }\n    backtrace_vector_free(state, &units, error_callback, data);\n  }\n  if (addrs->count > 0) {\n    backtrace_vector_free(state, &addrs->vec, error_callback, data);\n    addrs->count = 0;\n  }\n  return 0;\n}\n\nstatic int add_line(struct backtrace_state *state, struct dwarf_data *ddata,\n                    uintptr_t pc, const char *filename, int lineno,\n                    backtrace_error_callback error_callback, void *data,\n                    struct line_vector *vec) {\n  struct line *ln;\n\n  if (vec->count > 0) {\n    ln = (struct line *)vec->vec.base + (vec->count - 1);\n    if (pc == ln->pc && filename == ln->filename && lineno == ln->lineno)\n      return 1;\n  }\n\n  ln = ((struct line *)backtrace_vector_grow(state, sizeof(struct line),\n                                             error_callback, data, &vec->vec));\n  if (ln == NULL) return 0;\n\n  ln->pc = pc + ddata->base_address;\n\n  ln->filename = filename;\n  ln->lineno = lineno;\n  ln->idx = vec->count;\n\n  ++vec->count;\n\n  return 1;\n}\n\nstatic void free_line_header(struct backtrace_state *state,\n                             struct line_header *hdr,\n                             backtrace_error_callback error_callback,\n                             void *data) {\n  if (hdr->dirs_count != 0)\n    backtrace_free(state, hdr->dirs, hdr->dirs_count * sizeof(const char *),\n                   error_callback, data);\n  backtrace_free(state, hdr->filenames, hdr->filenames_count * sizeof(char *),\n                 error_callback, data);\n}\n\nstatic int read_v2_paths(struct backtrace_state *state, struct unit *u,\n                         struct dwarf_buf *hdr_buf, struct line_header *hdr) {\n  const unsigned char *p;\n  const unsigned char *pend;\n  size_t i;\n\n  hdr->dirs_count = 0;\n  p = hdr_buf->buf;\n  pend = p + hdr_buf->left;\n  while (p < pend && *p != '\\0') {\n    p += strnlen((const char *)p, pend - p) + 1;\n    ++hdr->dirs_count;\n  }\n\n  ++hdr->dirs_count;\n  hdr->dirs = ((const char **)backtrace_alloc(\n      state, hdr->dirs_count * sizeof(const char *), hdr_buf->error_callback,\n      hdr_buf->data));\n  if (hdr->dirs == NULL) return 0;\n\n  hdr->dirs[0] = u->comp_dir;\n  i = 1;\n  while (*hdr_buf->buf != '\\0') {\n    if (hdr_buf->reported_underflow) return 0;\n\n    hdr->dirs[i] = read_string(hdr_buf);\n    if (hdr->dirs[i] == NULL) return 0;\n    ++i;\n  }\n  if (!advance(hdr_buf, 1)) return 0;\n\n  hdr->filenames_count = 0;\n  p = hdr_buf->buf;\n  pend = p + hdr_buf->left;\n  while (p < pend && *p != '\\0') {\n    p += strnlen((const char *)p, pend - p) + 1;\n    p += leb128_len(p);\n    p += leb128_len(p);\n    p += leb128_len(p);\n    ++hdr->filenames_count;\n  }\n\n  ++hdr->filenames_count;\n  hdr->filenames = ((const char **)backtrace_alloc(\n      state, hdr->filenames_count * sizeof(char *), hdr_buf->error_callback,\n      hdr_buf->data));\n  if (hdr->filenames == NULL) return 0;\n  hdr->filenames[0] = u->filename;\n  i = 1;\n  while (*hdr_buf->buf != '\\0') {\n    const char *filename;\n    uint64_t dir_index;\n\n    if (hdr_buf->reported_underflow) return 0;\n\n    filename = read_string(hdr_buf);\n    if (filename == NULL) return 0;\n    dir_index = read_uleb128(hdr_buf);\n    if (IS_ABSOLUTE_PATH(filename) ||\n        (dir_index < hdr->dirs_count && hdr->dirs[dir_index] == NULL))\n      hdr->filenames[i] = filename;\n    else {\n      const char *dir;\n      size_t dir_len;\n      size_t filename_len;\n      char *s;\n\n      if (dir_index < hdr->dirs_count)\n        dir = hdr->dirs[dir_index];\n      else {\n        dwarf_buf_error(hdr_buf,\n                        (\"invalid directory index in \"\n                         \"line number program header\"),\n                        0);\n        return 0;\n      }\n      dir_len = strlen(dir);\n      filename_len = strlen(filename);\n      s = ((char *)backtrace_alloc(state, dir_len + filename_len + 2,\n                                   hdr_buf->error_callback, hdr_buf->data));\n      if (s == NULL) return 0;\n      memcpy(s, dir, dir_len);\n\n      s[dir_len] = '/';\n      memcpy(s + dir_len + 1, filename, filename_len + 1);\n      hdr->filenames[i] = s;\n    }\n\n    read_uleb128(hdr_buf);\n    read_uleb128(hdr_buf);\n\n    ++i;\n  }\n\n  return 1;\n}\n\nstatic int read_lnct(struct backtrace_state *state, struct dwarf_data *ddata,\n                     struct unit *u, struct dwarf_buf *hdr_buf,\n                     const struct line_header *hdr, size_t formats_count,\n                     const struct line_header_format *formats,\n                     const char **string) {\n  size_t i;\n  const char *dir;\n  const char *path;\n\n  dir = NULL;\n  path = NULL;\n  for (i = 0; i < formats_count; i++) {\n    struct attr_val val;\n\n    if (!read_attribute(formats[i].form, 0, hdr_buf, u->is_dwarf64, u->version,\n                        hdr->addrsize, &ddata->dwarf_sections, ddata->altlink,\n                        &val))\n      return 0;\n    switch (formats[i].lnct) {\n      case DW_LNCT_path:\n        if (!resolve_string(&ddata->dwarf_sections, u->is_dwarf64,\n                            ddata->is_bigendian, u->str_offsets_base, &val,\n                            hdr_buf->error_callback, hdr_buf->data, &path))\n          return 0;\n        break;\n      case DW_LNCT_directory_index:\n        if (val.encoding == ATTR_VAL_UINT) {\n          if (val.u.uint >= hdr->dirs_count) {\n            dwarf_buf_error(hdr_buf,\n                            (\"invalid directory index in \"\n                             \"line number program header\"),\n                            0);\n            return 0;\n          }\n          dir = hdr->dirs[val.u.uint];\n        }\n        break;\n      default:\n\n        break;\n    }\n  }\n\n  if (path == NULL) {\n    dwarf_buf_error(hdr_buf, \"missing file name in line number program header\",\n                    0);\n    return 0;\n  }\n\n  if (dir == NULL)\n    *string = path;\n  else {\n    size_t dir_len;\n    size_t path_len;\n    char *s;\n\n    dir_len = strlen(dir);\n    path_len = strlen(path);\n    s = (char *)backtrace_alloc(state, dir_len + path_len + 2,\n                                hdr_buf->error_callback, hdr_buf->data);\n    if (s == NULL) return 0;\n    memcpy(s, dir, dir_len);\n\n    s[dir_len] = '/';\n    memcpy(s + dir_len + 1, path, path_len + 1);\n    *string = s;\n  }\n\n  return 1;\n}\n\nstatic int read_line_header_format_entries(\n    struct backtrace_state *state, struct dwarf_data *ddata, struct unit *u,\n    struct dwarf_buf *hdr_buf, struct line_header *hdr, size_t *pcount,\n    const char ***ppaths) {\n  size_t formats_count;\n  struct line_header_format *formats;\n  size_t paths_count;\n  const char **paths;\n  size_t i;\n  int ret;\n\n  formats_count = read_byte(hdr_buf);\n  if (formats_count == 0)\n    formats = NULL;\n  else {\n    formats = ((struct line_header_format *)backtrace_alloc(\n        state, (formats_count * sizeof(struct line_header_format)),\n        hdr_buf->error_callback, hdr_buf->data));\n    if (formats == NULL) return 0;\n\n    for (i = 0; i < formats_count; i++) {\n      formats[i].lnct = (int)read_uleb128(hdr_buf);\n      formats[i].form = (enum dwarf_form)read_uleb128(hdr_buf);\n    }\n  }\n\n  paths_count = read_uleb128(hdr_buf);\n  if (paths_count == 0) {\n    *pcount = 0;\n    *ppaths = NULL;\n    ret = 1;\n    goto exit;\n  }\n\n  paths =\n      ((const char **)backtrace_alloc(state, paths_count * sizeof(const char *),\n                                      hdr_buf->error_callback, hdr_buf->data));\n  if (paths == NULL) {\n    ret = 0;\n    goto exit;\n  }\n  for (i = 0; i < paths_count; i++) {\n    if (!read_lnct(state, ddata, u, hdr_buf, hdr, formats_count, formats,\n                   &paths[i])) {\n      backtrace_free(state, paths, paths_count * sizeof(const char *),\n                     hdr_buf->error_callback, hdr_buf->data);\n      ret = 0;\n      goto exit;\n    }\n  }\n\n  *pcount = paths_count;\n  *ppaths = paths;\n\n  ret = 1;\n\nexit:\n  if (formats != NULL)\n    backtrace_free(state, formats,\n                   formats_count * sizeof(struct line_header_format),\n                   hdr_buf->error_callback, hdr_buf->data);\n\n  return ret;\n}\n\nstatic int read_line_header(struct backtrace_state *state,\n                            struct dwarf_data *ddata, struct unit *u,\n                            int is_dwarf64, struct dwarf_buf *line_buf,\n                            struct line_header *hdr) {\n  uint64_t hdrlen;\n  struct dwarf_buf hdr_buf;\n\n  hdr->version = read_uint16(line_buf);\n  if (hdr->version < 2 || hdr->version > 5) {\n    dwarf_buf_error(line_buf, \"unsupported line number version\", -1);\n    return 0;\n  }\n\n  if (hdr->version < 5)\n    hdr->addrsize = u->addrsize;\n  else {\n    hdr->addrsize = read_byte(line_buf);\n\n    if (read_byte(line_buf) != 0) {\n      dwarf_buf_error(line_buf, \"non-zero segment_selector_size not supported\",\n                      -1);\n      return 0;\n    }\n  }\n\n  hdrlen = read_offset(line_buf, is_dwarf64);\n\n  hdr_buf = *line_buf;\n  hdr_buf.left = hdrlen;\n\n  if (!advance(line_buf, hdrlen)) return 0;\n\n  hdr->min_insn_len = read_byte(&hdr_buf);\n  if (hdr->version < 4)\n    hdr->max_ops_per_insn = 1;\n  else\n    hdr->max_ops_per_insn = read_byte(&hdr_buf);\n\n  read_byte(&hdr_buf);\n\n  hdr->line_base = read_sbyte(&hdr_buf);\n  hdr->line_range = read_byte(&hdr_buf);\n\n  hdr->opcode_base = read_byte(&hdr_buf);\n  hdr->opcode_lengths = hdr_buf.buf;\n  if (!advance(&hdr_buf, hdr->opcode_base - 1)) return 0;\n\n  if (hdr->version < 5) {\n    if (!read_v2_paths(state, u, &hdr_buf, hdr)) return 0;\n  } else {\n    if (!read_line_header_format_entries(state, ddata, u, &hdr_buf, hdr,\n                                         &hdr->dirs_count, &hdr->dirs))\n      return 0;\n    if (!read_line_header_format_entries(state, ddata, u, &hdr_buf, hdr,\n                                         &hdr->filenames_count,\n                                         &hdr->filenames))\n      return 0;\n  }\n\n  if (hdr_buf.reported_underflow) return 0;\n\n  return 1;\n}\n\nstatic int read_line_program(struct backtrace_state *state,\n                             struct dwarf_data *ddata,\n                             const struct line_header *hdr,\n                             struct dwarf_buf *line_buf,\n                             struct line_vector *vec) {\n  uint64_t address;\n  unsigned int op_index;\n  const char *reset_filename;\n  const char *filename;\n  int lineno;\n\n  address = 0;\n  op_index = 0;\n  if (hdr->filenames_count > 1)\n    reset_filename = hdr->filenames[1];\n  else\n    reset_filename = \"\";\n  filename = reset_filename;\n  lineno = 1;\n  while (line_buf->left > 0) {\n    unsigned int op;\n\n    op = read_byte(line_buf);\n    if (op >= hdr->opcode_base) {\n      unsigned int advance;\n\n      op -= hdr->opcode_base;\n      advance = op / hdr->line_range;\n      address +=\n          (hdr->min_insn_len * (op_index + advance) / hdr->max_ops_per_insn);\n      op_index = (op_index + advance) % hdr->max_ops_per_insn;\n      lineno += hdr->line_base + (int)(op % hdr->line_range);\n      add_line(state, ddata, address, filename, lineno,\n               line_buf->error_callback, line_buf->data, vec);\n    } else if (op == DW_LNS_extended_op) {\n      uint64_t len;\n\n      len = read_uleb128(line_buf);\n      op = read_byte(line_buf);\n      switch (op) {\n        case DW_LNE_end_sequence:\n\n          address = 0;\n          op_index = 0;\n          filename = reset_filename;\n          lineno = 1;\n          break;\n        case DW_LNE_set_address:\n          address = read_address(line_buf, hdr->addrsize);\n          break;\n        case DW_LNE_define_file: {\n          const char *f;\n          unsigned int dir_index;\n\n          f = read_string(line_buf);\n          if (f == NULL) return 0;\n          dir_index = read_uleb128(line_buf);\n\n          read_uleb128(line_buf);\n          read_uleb128(line_buf);\n          if (IS_ABSOLUTE_PATH(f))\n            filename = f;\n          else {\n            const char *dir;\n            size_t dir_len;\n            size_t f_len;\n            char *p;\n\n            if (dir_index < hdr->dirs_count)\n              dir = hdr->dirs[dir_index];\n            else {\n              dwarf_buf_error(line_buf,\n                              (\"invalid directory index \"\n                               \"in line number program\"),\n                              0);\n              return 0;\n            }\n            dir_len = strlen(dir);\n            f_len = strlen(f);\n            p = ((char *)backtrace_alloc(state, dir_len + f_len + 2,\n                                         line_buf->error_callback,\n                                         line_buf->data));\n            if (p == NULL) return 0;\n            memcpy(p, dir, dir_len);\n\n            p[dir_len] = '/';\n            memcpy(p + dir_len + 1, f, f_len + 1);\n            filename = p;\n          }\n        } break;\n        case DW_LNE_set_discriminator:\n\n          read_uleb128(line_buf);\n          break;\n        default:\n          if (!advance(line_buf, len - 1)) return 0;\n          break;\n      }\n    } else {\n      switch (op) {\n        case DW_LNS_copy:\n          add_line(state, ddata, address, filename, lineno,\n                   line_buf->error_callback, line_buf->data, vec);\n          break;\n        case DW_LNS_advance_pc: {\n          uint64_t advance;\n\n          advance = read_uleb128(line_buf);\n          address += (hdr->min_insn_len * (op_index + advance) /\n                      hdr->max_ops_per_insn);\n          op_index = (op_index + advance) % hdr->max_ops_per_insn;\n        } break;\n        case DW_LNS_advance_line:\n          lineno += (int)read_sleb128(line_buf);\n          break;\n        case DW_LNS_set_file: {\n          uint64_t fileno;\n\n          fileno = read_uleb128(line_buf);\n          if (fileno >= hdr->filenames_count) {\n            dwarf_buf_error(line_buf,\n                            (\"invalid file number in \"\n                             \"line number program\"),\n                            0);\n            return 0;\n          }\n          filename = hdr->filenames[fileno];\n        } break;\n        case DW_LNS_set_column:\n          read_uleb128(line_buf);\n          break;\n        case DW_LNS_negate_stmt:\n          break;\n        case DW_LNS_set_basic_block:\n          break;\n        case DW_LNS_const_add_pc: {\n          unsigned int advance;\n\n          op = 255 - hdr->opcode_base;\n          advance = op / hdr->line_range;\n          address += (hdr->min_insn_len * (op_index + advance) /\n                      hdr->max_ops_per_insn);\n          op_index = (op_index + advance) % hdr->max_ops_per_insn;\n        } break;\n        case DW_LNS_fixed_advance_pc:\n          address += read_uint16(line_buf);\n          op_index = 0;\n          break;\n        case DW_LNS_set_prologue_end:\n          break;\n        case DW_LNS_set_epilogue_begin:\n          break;\n        case DW_LNS_set_isa:\n          read_uleb128(line_buf);\n          break;\n        default: {\n          unsigned int i;\n\n          for (i = hdr->opcode_lengths[op - 1]; i > 0; --i)\n            read_uleb128(line_buf);\n        } break;\n      }\n    }\n  }\n\n  return 1;\n}\n\nstatic int read_line_info(struct backtrace_state *state,\n                          struct dwarf_data *ddata,\n                          backtrace_error_callback error_callback, void *data,\n                          struct unit *u, struct line_header *hdr,\n                          struct line **lines, size_t *lines_count) {\n  struct line_vector vec;\n  struct dwarf_buf line_buf;\n  uint64_t len;\n  int is_dwarf64;\n  struct line *ln;\n\n  memset(&vec.vec, 0, sizeof vec.vec);\n  vec.count = 0;\n\n  memset(hdr, 0, sizeof *hdr);\n\n  if (u->lineoff != (off_t)(size_t)u->lineoff ||\n      (size_t)u->lineoff >= ddata->dwarf_sections.size[DEBUG_LINE]) {\n    error_callback(data, \"unit line offset out of range\", 0);\n    goto fail;\n  }\n\n  line_buf.name = \".debug_line\";\n  line_buf.start = ddata->dwarf_sections.data[DEBUG_LINE];\n  line_buf.buf = ddata->dwarf_sections.data[DEBUG_LINE] + u->lineoff;\n  line_buf.left = ddata->dwarf_sections.size[DEBUG_LINE] - u->lineoff;\n  line_buf.is_bigendian = ddata->is_bigendian;\n  line_buf.error_callback = error_callback;\n  line_buf.data = data;\n  line_buf.reported_underflow = 0;\n\n  len = read_initial_length(&line_buf, &is_dwarf64);\n  line_buf.left = len;\n\n  if (!read_line_header(state, ddata, u, is_dwarf64, &line_buf, hdr)) goto fail;\n\n  if (!read_line_program(state, ddata, hdr, &line_buf, &vec)) goto fail;\n\n  if (line_buf.reported_underflow) goto fail;\n\n  if (vec.count == 0) {\n    goto fail;\n  }\n\n  ln = ((struct line *)backtrace_vector_grow(state, sizeof(struct line),\n                                             error_callback, data, &vec.vec));\n  if (ln == NULL) goto fail;\n  ln->pc = (uintptr_t)-1;\n  ln->filename = NULL;\n  ln->lineno = 0;\n  ln->idx = 0;\n\n  if (!backtrace_vector_release(state, &vec.vec, error_callback, data))\n    goto fail;\n\n  ln = (struct line *)vec.vec.base;\n  backtrace_qsort(ln, vec.count, sizeof(struct line), line_compare);\n\n  *lines = ln;\n  *lines_count = vec.count;\n\n  return 1;\n\nfail:\n  backtrace_vector_free(state, &vec.vec, error_callback, data);\n  free_line_header(state, hdr, error_callback, data);\n  *lines = (struct line *)(uintptr_t)-1;\n  *lines_count = 0;\n  return 0;\n}\n\nstatic const char *read_referenced_name(struct dwarf_data *, struct unit *,\n                                        uint64_t, backtrace_error_callback,\n                                        void *);\n\nstatic const char *read_referenced_name_from_attr(\n    struct dwarf_data *ddata, struct unit *u, struct attr *attr,\n    struct attr_val *val, backtrace_error_callback error_callback, void *data) {\n  switch (attr->name) {\n    case DW_AT_abstract_origin:\n    case DW_AT_specification:\n      break;\n    default:\n      return NULL;\n  }\n\n  if (attr->form == DW_FORM_ref_sig8) return NULL;\n\n  if (val->encoding == ATTR_VAL_REF_INFO) {\n    struct unit *unit =\n        find_unit(ddata->units, ddata->units_count, val->u.uint);\n    if (unit == NULL) return NULL;\n\n    uint64_t offset = val->u.uint - unit->low_offset;\n    return read_referenced_name(ddata, unit, offset, error_callback, data);\n  }\n\n  if (val->encoding == ATTR_VAL_UINT || val->encoding == ATTR_VAL_REF_UNIT)\n    return read_referenced_name(ddata, u, val->u.uint, error_callback, data);\n\n  if (val->encoding == ATTR_VAL_REF_ALT_INFO) {\n    struct unit *alt_unit = find_unit(ddata->altlink->units,\n                                      ddata->altlink->units_count, val->u.uint);\n    if (alt_unit == NULL) return NULL;\n\n    uint64_t offset = val->u.uint - alt_unit->low_offset;\n    return read_referenced_name(ddata->altlink, alt_unit, offset,\n                                error_callback, data);\n  }\n\n  return NULL;\n}\n\nstatic const char *read_referenced_name(struct dwarf_data *ddata,\n                                        struct unit *u, uint64_t offset,\n                                        backtrace_error_callback error_callback,\n                                        void *data) {\n  struct dwarf_buf unit_buf;\n  uint64_t code;\n  const struct abbrev *abbrev;\n  const char *ret;\n  size_t i;\n\n  if (offset < u->unit_data_offset ||\n      offset - u->unit_data_offset >= u->unit_data_len) {\n    error_callback(data, \"abstract origin or specification out of range\", 0);\n    return NULL;\n  }\n\n  offset -= u->unit_data_offset;\n\n  unit_buf.name = \".debug_info\";\n  unit_buf.start = ddata->dwarf_sections.data[DEBUG_INFO];\n  unit_buf.buf = u->unit_data + offset;\n  unit_buf.left = u->unit_data_len - offset;\n  unit_buf.is_bigendian = ddata->is_bigendian;\n  unit_buf.error_callback = error_callback;\n  unit_buf.data = data;\n  unit_buf.reported_underflow = 0;\n\n  code = read_uleb128(&unit_buf);\n  if (code == 0) {\n    dwarf_buf_error(&unit_buf, \"invalid abstract origin or specification\", 0);\n    return NULL;\n  }\n\n  abbrev = lookup_abbrev(&u->abbrevs, code, error_callback, data);\n  if (abbrev == NULL) return NULL;\n\n  ret = NULL;\n  for (i = 0; i < abbrev->num_attrs; ++i) {\n    struct attr_val val;\n\n    if (!read_attribute(abbrev->attrs[i].form, abbrev->attrs[i].val, &unit_buf,\n                        u->is_dwarf64, u->version, u->addrsize,\n                        &ddata->dwarf_sections, ddata->altlink, &val))\n      return NULL;\n\n    switch (abbrev->attrs[i].name) {\n      case DW_AT_name:\n\n        if (ret != NULL) break;\n        if (!resolve_string(&ddata->dwarf_sections, u->is_dwarf64,\n                            ddata->is_bigendian, u->str_offsets_base, &val,\n                            error_callback, data, &ret))\n          return NULL;\n        break;\n\n      case DW_AT_linkage_name:\n      case DW_AT_MIPS_linkage_name:\n\n      {\n        const char *s;\n\n        s = NULL;\n        if (!resolve_string(&ddata->dwarf_sections, u->is_dwarf64,\n                            ddata->is_bigendian, u->str_offsets_base, &val,\n                            error_callback, data, &s))\n          return NULL;\n        if (s != NULL) return s;\n      } break;\n\n      case DW_AT_specification:\n\n      {\n        const char *name;\n\n        name = read_referenced_name_from_attr(ddata, u, &abbrev->attrs[i], &val,\n                                              error_callback, data);\n        if (name != NULL) ret = name;\n      } break;\n\n      default:\n        break;\n    }\n  }\n\n  return ret;\n}\n\nstatic int add_function_range(struct backtrace_state *state, void *rdata,\n                              uint64_t lowpc, uint64_t highpc,\n                              backtrace_error_callback error_callback,\n                              void *data, void *pvec) {\n  struct function *function = (struct function *)rdata;\n  struct function_vector *vec = (struct function_vector *)pvec;\n  struct function_addrs *p;\n\n  if (vec->count > 0) {\n    p = (struct function_addrs *)vec->vec.base + (vec->count - 1);\n    if ((lowpc == p->high || lowpc == p->high + 1) && function == p->function) {\n      if (highpc > p->high) p->high = highpc;\n      return 1;\n    }\n  }\n\n  p = ((struct function_addrs *)backtrace_vector_grow(\n      state, sizeof(struct function_addrs), error_callback, data, &vec->vec));\n  if (p == NULL) return 0;\n\n  p->low = lowpc;\n  p->high = highpc;\n  p->function = function;\n\n  ++vec->count;\n\n  return 1;\n}\n\nstatic int read_function_entry(struct backtrace_state *state,\n                               struct dwarf_data *ddata, struct unit *u,\n                               uint64_t base, struct dwarf_buf *unit_buf,\n                               const struct line_header *lhdr,\n                               backtrace_error_callback error_callback,\n                               void *data, struct function_vector *vec_function,\n                               struct function_vector *vec_inlined) {\n  while (unit_buf->left > 0) {\n    uint64_t code;\n    const struct abbrev *abbrev;\n    int is_function;\n    struct function *function;\n    struct function_vector *vec;\n    size_t i;\n    struct pcrange pcrange;\n    int have_linkage_name;\n\n    code = read_uleb128(unit_buf);\n    if (code == 0) return 1;\n\n    abbrev = lookup_abbrev(&u->abbrevs, code, error_callback, data);\n    if (abbrev == NULL) return 0;\n\n    is_function = (abbrev->tag == DW_TAG_subprogram ||\n                   abbrev->tag == DW_TAG_entry_point ||\n                   abbrev->tag == DW_TAG_inlined_subroutine);\n\n    if (abbrev->tag == DW_TAG_inlined_subroutine)\n      vec = vec_inlined;\n    else\n      vec = vec_function;\n\n    function = NULL;\n    if (is_function) {\n      function = ((struct function *)backtrace_alloc(state, sizeof *function,\n                                                     error_callback, data));\n      if (function == NULL) return 0;\n      memset(function, 0, sizeof *function);\n    }\n\n    memset(&pcrange, 0, sizeof pcrange);\n    have_linkage_name = 0;\n    for (i = 0; i < abbrev->num_attrs; ++i) {\n      struct attr_val val;\n\n      if (!read_attribute(abbrev->attrs[i].form, abbrev->attrs[i].val, unit_buf,\n                          u->is_dwarf64, u->version, u->addrsize,\n                          &ddata->dwarf_sections, ddata->altlink, &val))\n        return 0;\n\n      if ((abbrev->tag == DW_TAG_compile_unit ||\n           abbrev->tag == DW_TAG_skeleton_unit) &&\n          abbrev->attrs[i].name == DW_AT_low_pc) {\n        if (val.encoding == ATTR_VAL_ADDRESS)\n          base = val.u.uint;\n        else if (val.encoding == ATTR_VAL_ADDRESS_INDEX) {\n          if (!resolve_addr_index(&ddata->dwarf_sections, u->addr_base,\n                                  u->addrsize, ddata->is_bigendian, val.u.uint,\n                                  error_callback, data, &base))\n            return 0;\n        }\n      }\n\n      if (is_function) {\n        switch (abbrev->attrs[i].name) {\n          case DW_AT_call_file:\n            if (val.encoding == ATTR_VAL_UINT) {\n              if (val.u.uint >= lhdr->filenames_count) {\n                dwarf_buf_error(unit_buf,\n                                (\"invalid file number in \"\n                                 \"DW_AT_call_file attribute\"),\n                                0);\n                return 0;\n              }\n              function->caller_filename = lhdr->filenames[val.u.uint];\n            }\n            break;\n\n          case DW_AT_call_line:\n            if (val.encoding == ATTR_VAL_UINT)\n              function->caller_lineno = val.u.uint;\n            break;\n\n          case DW_AT_abstract_origin:\n          case DW_AT_specification:\n\n            if (have_linkage_name) break;\n            {\n              const char *name;\n\n              name = read_referenced_name_from_attr(ddata, u, &abbrev->attrs[i],\n                                                    &val, error_callback, data);\n              if (name != NULL) function->name = name;\n            }\n            break;\n\n          case DW_AT_name:\n\n            if (function->name != NULL) break;\n            if (!resolve_string(&ddata->dwarf_sections, u->is_dwarf64,\n                                ddata->is_bigendian, u->str_offsets_base, &val,\n                                error_callback, data, &function->name))\n              return 0;\n            break;\n\n          case DW_AT_linkage_name:\n          case DW_AT_MIPS_linkage_name:\n\n          {\n            const char *s;\n\n            s = NULL;\n            if (!resolve_string(&ddata->dwarf_sections, u->is_dwarf64,\n                                ddata->is_bigendian, u->str_offsets_base, &val,\n                                error_callback, data, &s))\n              return 0;\n            if (s != NULL) {\n              function->name = s;\n              have_linkage_name = 1;\n            }\n          } break;\n\n          case DW_AT_low_pc:\n          case DW_AT_high_pc:\n          case DW_AT_ranges:\n            update_pcrange(&abbrev->attrs[i], &val, &pcrange);\n            break;\n\n          default:\n            break;\n        }\n      }\n    }\n\n    if (is_function && function->name == NULL) {\n      backtrace_free(state, function, sizeof *function, error_callback, data);\n      is_function = 0;\n    }\n\n    if (is_function) {\n      if (pcrange.have_ranges || (pcrange.have_lowpc && pcrange.have_highpc)) {\n        if (!add_ranges(state, &ddata->dwarf_sections, ddata->base_address,\n                        ddata->is_bigendian, u, base, &pcrange,\n                        add_function_range, (void *)function, error_callback,\n                        data, (void *)vec))\n          return 0;\n      } else {\n        backtrace_free(state, function, sizeof *function, error_callback, data);\n        is_function = 0;\n      }\n    }\n\n    if (abbrev->has_children) {\n      if (!is_function) {\n        if (!read_function_entry(state, ddata, u, base, unit_buf, lhdr,\n                                 error_callback, data, vec_function,\n                                 vec_inlined))\n          return 0;\n      } else {\n        struct function_vector fvec;\n\n        memset(&fvec, 0, sizeof fvec);\n\n        if (!read_function_entry(state, ddata, u, base, unit_buf, lhdr,\n                                 error_callback, data, vec_function, &fvec))\n          return 0;\n\n        if (fvec.count > 0) {\n          struct function_addrs *p;\n          struct function_addrs *faddrs;\n\n          p = ((struct function_addrs *)backtrace_vector_grow(\n              state, sizeof(struct function_addrs), error_callback, data,\n              &fvec.vec));\n          if (p == NULL) return 0;\n          p->low = 0;\n          --p->low;\n          p->high = p->low;\n          p->function = NULL;\n\n          if (!backtrace_vector_release(state, &fvec.vec, error_callback, data))\n            return 0;\n\n          faddrs = (struct function_addrs *)fvec.vec.base;\n          backtrace_qsort(faddrs, fvec.count, sizeof(struct function_addrs),\n                          function_addrs_compare);\n\n          function->function_addrs = faddrs;\n          function->function_addrs_count = fvec.count;\n        }\n      }\n    }\n  }\n\n  return 1;\n}\n\nstatic void read_function_info(\n    struct backtrace_state *state, struct dwarf_data *ddata,\n    const struct line_header *lhdr, backtrace_error_callback error_callback,\n    void *data, struct unit *u, struct function_vector *fvec,\n    struct function_addrs **ret_addrs, size_t *ret_addrs_count) {\n  struct function_vector lvec;\n  struct function_vector *pfvec;\n  struct dwarf_buf unit_buf;\n  struct function_addrs *p;\n  struct function_addrs *addrs;\n  size_t addrs_count;\n\n  if (fvec != NULL)\n    pfvec = fvec;\n  else {\n    memset(&lvec, 0, sizeof lvec);\n    pfvec = &lvec;\n  }\n\n  unit_buf.name = \".debug_info\";\n  unit_buf.start = ddata->dwarf_sections.data[DEBUG_INFO];\n  unit_buf.buf = u->unit_data;\n  unit_buf.left = u->unit_data_len;\n  unit_buf.is_bigendian = ddata->is_bigendian;\n  unit_buf.error_callback = error_callback;\n  unit_buf.data = data;\n  unit_buf.reported_underflow = 0;\n\n  while (unit_buf.left > 0) {\n    if (!read_function_entry(state, ddata, u, 0, &unit_buf, lhdr,\n                             error_callback, data, pfvec, pfvec))\n      return;\n  }\n\n  if (pfvec->count == 0) return;\n\n  p = ((struct function_addrs *)backtrace_vector_grow(\n      state, sizeof(struct function_addrs), error_callback, data, &pfvec->vec));\n  if (p == NULL) return;\n  p->low = 0;\n  --p->low;\n  p->high = p->low;\n  p->function = NULL;\n\n  addrs_count = pfvec->count;\n\n  if (fvec == NULL) {\n    if (!backtrace_vector_release(state, &lvec.vec, error_callback, data))\n      return;\n    addrs = (struct function_addrs *)pfvec->vec.base;\n  } else {\n    addrs = ((struct function_addrs *)backtrace_vector_finish(\n        state, &fvec->vec, error_callback, data));\n    if (addrs == NULL) return;\n    fvec->count = 0;\n  }\n\n  backtrace_qsort(addrs, addrs_count, sizeof(struct function_addrs),\n                  function_addrs_compare);\n\n  *ret_addrs = addrs;\n  *ret_addrs_count = addrs_count;\n}\n\nstatic int report_inlined_functions(uintptr_t pc, struct function *function,\n                                    backtrace_full_callback callback,\n                                    void *data, const char **filename,\n                                    int *lineno) {\n  struct function_addrs *p;\n  struct function_addrs *match;\n  struct function *inlined;\n  int ret;\n\n  if (function->function_addrs_count == 0) return 0;\n\n  if (pc + 1 == 0) return 0;\n\n  p = ((struct function_addrs *)bsearch(\n      &pc, function->function_addrs, function->function_addrs_count,\n      sizeof(struct function_addrs), function_addrs_search));\n  if (p == NULL) return 0;\n\n  while (pc == (p + 1)->low) ++p;\n  match = NULL;\n  while (1) {\n    if (pc < p->high) {\n      match = p;\n      break;\n    }\n    if (p == function->function_addrs) break;\n    if ((p - 1)->low < p->low) break;\n    --p;\n  }\n  if (match == NULL) return 0;\n\n  inlined = match->function;\n\n  ret = report_inlined_functions(pc, inlined, callback, data, filename, lineno);\n  if (ret != 0) return ret;\n\n  ret = callback(data, pc, *filename, *lineno, inlined->name);\n  if (ret != 0) return ret;\n\n  *filename = inlined->caller_filename;\n  *lineno = inlined->caller_lineno;\n\n  return 0;\n}\n\nstatic int dwarf_lookup_pc(struct backtrace_state *state,\n                           struct dwarf_data *ddata, uintptr_t pc,\n                           backtrace_full_callback callback,\n                           backtrace_error_callback error_callback, void *data,\n                           int *found) {\n  struct unit_addrs *entry;\n  int found_entry;\n  struct unit *u;\n  int new_data;\n  struct line *lines;\n  struct line *ln;\n  struct function_addrs *p;\n  struct function_addrs *fmatch;\n  struct function *function;\n  const char *filename;\n  int lineno;\n  int ret;\n\n  *found = 1;\n\n  entry = (ddata->addrs_count == 0 || pc + 1 == 0\n               ? NULL\n               : bsearch(&pc, ddata->addrs, ddata->addrs_count,\n                         sizeof(struct unit_addrs), unit_addrs_search));\n\n  if (entry == NULL) {\n    *found = 0;\n    return 0;\n  }\n\n  while (pc == (entry + 1)->low) ++entry;\n  found_entry = 0;\n  while (1) {\n    if (pc < entry->high) {\n      found_entry = 1;\n      break;\n    }\n    if (entry == ddata->addrs) break;\n    if ((entry - 1)->low < entry->low) break;\n    --entry;\n  }\n  if (!found_entry) {\n    *found = 0;\n    return 0;\n  }\n\n  u = entry->u;\n  lines = u->lines;\n\n  while (entry > ddata->addrs && pc >= (entry - 1)->low &&\n         pc < (entry - 1)->high) {\n    if (state->threaded)\n      lines = (struct line *)backtrace_atomic_load_pointer(&u->lines);\n\n    if (lines != (struct line *)(uintptr_t)-1) break;\n\n    --entry;\n\n    u = entry->u;\n    lines = u->lines;\n  }\n\n  if (state->threaded) lines = backtrace_atomic_load_pointer(&u->lines);\n\n  new_data = 0;\n  if (lines == NULL) {\n    struct function_addrs *function_addrs;\n    size_t function_addrs_count;\n    struct line_header lhdr;\n    size_t count;\n\n    function_addrs = NULL;\n    function_addrs_count = 0;\n    if (read_line_info(state, ddata, error_callback, data, entry->u, &lhdr,\n                       &lines, &count)) {\n      struct function_vector *pfvec;\n\n      if (state->threaded)\n        pfvec = NULL;\n      else\n        pfvec = &ddata->fvec;\n      read_function_info(state, ddata, &lhdr, error_callback, data, entry->u,\n                         pfvec, &function_addrs, &function_addrs_count);\n      free_line_header(state, &lhdr, error_callback, data);\n      new_data = 1;\n    }\n\n    if (!state->threaded) {\n      u->lines_count = count;\n      u->function_addrs = function_addrs;\n      u->function_addrs_count = function_addrs_count;\n      u->lines = lines;\n    } else {\n      backtrace_atomic_store_size_t(&u->lines_count, count);\n      backtrace_atomic_store_pointer(&u->function_addrs, function_addrs);\n      backtrace_atomic_store_size_t(&u->function_addrs_count,\n                                    function_addrs_count);\n      backtrace_atomic_store_pointer(&u->lines, lines);\n    }\n  }\n\n  if (lines == (struct line *)(uintptr_t)-1) {\n    if (new_data)\n      return dwarf_lookup_pc(state, ddata, pc, callback, error_callback, data,\n                             found);\n    return callback(data, pc, NULL, 0, NULL);\n  }\n\n  ln = (struct line *)bsearch(&pc, lines, entry->u->lines_count,\n                              sizeof(struct line), line_search);\n  if (ln == NULL) {\n    if (entry->u->abs_filename == NULL) {\n      const char *filename;\n\n      filename = entry->u->filename;\n      if (filename != NULL && !IS_ABSOLUTE_PATH(filename) &&\n          entry->u->comp_dir != NULL) {\n        size_t filename_len;\n        const char *dir;\n        size_t dir_len;\n        char *s;\n\n        filename_len = strlen(filename);\n        dir = entry->u->comp_dir;\n        dir_len = strlen(dir);\n        s = (char *)backtrace_alloc(state, dir_len + filename_len + 2,\n                                    error_callback, data);\n        if (s == NULL) {\n          *found = 0;\n          return 0;\n        }\n        memcpy(s, dir, dir_len);\n\n        s[dir_len] = '/';\n        memcpy(s + dir_len + 1, filename, filename_len + 1);\n        filename = s;\n      }\n      entry->u->abs_filename = filename;\n    }\n\n    return callback(data, pc, entry->u->abs_filename, 0, NULL);\n  }\n\n  if (entry->u->function_addrs_count == 0)\n    return callback(data, pc, ln->filename, ln->lineno, NULL);\n\n  p = ((struct function_addrs *)bsearch(\n      &pc, entry->u->function_addrs, entry->u->function_addrs_count,\n      sizeof(struct function_addrs), function_addrs_search));\n  if (p == NULL) return callback(data, pc, ln->filename, ln->lineno, NULL);\n\n  while (pc == (p + 1)->low) ++p;\n  fmatch = NULL;\n  while (1) {\n    if (pc < p->high) {\n      fmatch = p;\n      break;\n    }\n    if (p == entry->u->function_addrs) break;\n    if ((p - 1)->low < p->low) break;\n    --p;\n  }\n  if (fmatch == NULL) return callback(data, pc, ln->filename, ln->lineno, NULL);\n\n  function = fmatch->function;\n\n  filename = ln->filename;\n  lineno = ln->lineno;\n\n  ret = report_inlined_functions(pc, function, callback, data, &filename,\n                                 &lineno);\n  if (ret != 0) return ret;\n\n  return callback(data, pc, filename, lineno, function->name);\n}\n\nstatic int dwarf_fileline(struct backtrace_state *state, uintptr_t pc,\n                          backtrace_full_callback callback,\n                          backtrace_error_callback error_callback, void *data) {\n  struct dwarf_data *ddata;\n  int found;\n  int ret;\n\n  if (!state->threaded) {\n    for (ddata = (struct dwarf_data *)state->fileline_data; ddata != NULL;\n         ddata = ddata->next) {\n      ret = dwarf_lookup_pc(state, ddata, pc, callback, error_callback, data,\n                            &found);\n      if (ret != 0 || found) return ret;\n    }\n  } else {\n    struct dwarf_data **pp;\n\n    pp = (struct dwarf_data **)(void *)&state->fileline_data;\n    while (1) {\n      ddata = backtrace_atomic_load_pointer(pp);\n      if (ddata == NULL) break;\n\n      ret = dwarf_lookup_pc(state, ddata, pc, callback, error_callback, data,\n                            &found);\n      if (ret != 0 || found) return ret;\n\n      pp = &ddata->next;\n    }\n  }\n\n  return callback(data, pc, NULL, 0, NULL);\n}\n\nstatic struct dwarf_data *build_dwarf_data(\n    struct backtrace_state *state, uintptr_t base_address,\n    const struct dwarf_sections *dwarf_sections, int is_bigendian,\n    struct dwarf_data *altlink, backtrace_error_callback error_callback,\n    void *data) {\n  struct unit_addrs_vector addrs_vec;\n  struct unit_addrs *addrs;\n  size_t addrs_count;\n  struct unit_vector units_vec;\n  struct unit **units;\n  size_t units_count;\n  struct dwarf_data *fdata;\n\n  if (!build_address_map(state, base_address, dwarf_sections, is_bigendian,\n                         altlink, error_callback, data, &addrs_vec, &units_vec))\n    return NULL;\n\n  if (!backtrace_vector_release(state, &addrs_vec.vec, error_callback, data))\n    return NULL;\n  if (!backtrace_vector_release(state, &units_vec.vec, error_callback, data))\n    return NULL;\n  addrs = (struct unit_addrs *)addrs_vec.vec.base;\n  units = (struct unit **)units_vec.vec.base;\n  addrs_count = addrs_vec.count;\n  units_count = units_vec.count;\n  backtrace_qsort(addrs, addrs_count, sizeof(struct unit_addrs),\n                  unit_addrs_compare);\n\n  fdata = ((struct dwarf_data *)backtrace_alloc(\n      state, sizeof(struct dwarf_data), error_callback, data));\n  if (fdata == NULL) return NULL;\n\n  fdata->next = NULL;\n  fdata->altlink = altlink;\n  fdata->base_address = base_address;\n  fdata->addrs = addrs;\n  fdata->addrs_count = addrs_count;\n  fdata->units = units;\n  fdata->units_count = units_count;\n  fdata->dwarf_sections = *dwarf_sections;\n  fdata->is_bigendian = is_bigendian;\n  memset(&fdata->fvec, 0, sizeof fdata->fvec);\n\n  return fdata;\n}\n\nint backtrace_dwarf_add(struct backtrace_state *state, uintptr_t base_address,\n                        const struct dwarf_sections *dwarf_sections,\n                        int is_bigendian, struct dwarf_data *fileline_altlink,\n                        backtrace_error_callback error_callback, void *data,\n                        fileline *fileline_fn,\n                        struct dwarf_data **fileline_entry) {\n  struct dwarf_data *fdata;\n\n  fdata = build_dwarf_data(state, base_address, dwarf_sections, is_bigendian,\n                           fileline_altlink, error_callback, data);\n  if (fdata == NULL) return 0;\n\n  if (fileline_entry != NULL) *fileline_entry = fdata;\n\n  if (!state->threaded) {\n    struct dwarf_data **pp;\n\n    for (pp = (struct dwarf_data **)(void *)&state->fileline_data; *pp != NULL;\n         pp = &(*pp)->next)\n      ;\n    *pp = fdata;\n  } else {\n    while (1) {\n      struct dwarf_data **pp;\n\n      pp = (struct dwarf_data **)(void *)&state->fileline_data;\n\n      while (1) {\n        struct dwarf_data *p;\n\n        p = backtrace_atomic_load_pointer(pp);\n\n        if (p == NULL) break;\n\n        pp = &p->next;\n      }\n\n      if (__sync_bool_compare_and_swap(pp, NULL, fdata)) break;\n    }\n  }\n\n  *fileline_fn = dwarf_fileline;\n\n  return 1;\n}\n\n// fileline.c:\n#include <errno.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#if defined(HAVE_KERN_PROC_ARGS) || defined(HAVE_KERN_PROC)\n#include <sys/sysctl.h>\n#endif\n\n#ifdef HAVE_MACH_O_DYLD_H\n#include <mach-o/dyld.h>\n#endif\n\n#ifndef HAVE_GETEXECNAME\n#define getexecname() NULL\n#endif\n\n#if !defined(HAVE_KERN_PROC_ARGS) && !defined(HAVE_KERN_PROC)\n\n#define sysctl_exec_name1(state, error_callback, data) NULL\n#define sysctl_exec_name2(state, error_callback, data) NULL\n\n#else\nstatic char *sysctl_exec_name(struct backtrace_state *state, int mib0, int mib1,\n                              int mib2, int mib3,\n                              backtrace_error_callback error_callback,\n                              void *data) {\n  int mib[4];\n  size_t len;\n  char *name;\n  size_t rlen;\n\n  mib[0] = mib0;\n  mib[1] = mib1;\n  mib[2] = mib2;\n  mib[3] = mib3;\n\n  if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) return NULL;\n  name = (char *)backtrace_alloc(state, len, error_callback, data);\n  if (name == NULL) return NULL;\n  rlen = len;\n  if (sysctl(mib, 4, name, &rlen, NULL, 0) < 0) {\n    backtrace_free(state, name, len, error_callback, data);\n    return NULL;\n  }\n  return name;\n}\n\n#ifdef HAVE_KERN_PROC_ARGS\n\nstatic char *sysctl_exec_name1(struct backtrace_state *state,\n                               backtrace_error_callback error_callback,\n                               void *data) {\n  return sysctl_exec_name(state, CTL_KERN, KERN_PROC_ARGS, -1,\n                          KERN_PROC_PATHNAME, error_callback, data);\n}\n\n#else\n\n#define sysctl_exec_name1(state, error_callback, data) NULL\n\n#endif\n\n#ifdef HAVE_KERN_PROC\n\nstatic char *sysctl_exec_name2(struct backtrace_state *state,\n                               backtrace_error_callback error_callback,\n                               void *data) {\n  return sysctl_exec_name(state, CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1,\n                          error_callback, data);\n}\n\n#else\n\n#define sysctl_exec_name2(state, error_callback, data) NULL\n\n#endif\n\n#endif\n#ifdef HAVE_MACH_O_DYLD_H\n\nstatic char *macho_get_executable_path(struct backtrace_state *state,\n                                       backtrace_error_callback error_callback,\n                                       void *data) {\n  uint32_t len;\n  char *name;\n\n  len = 0;\n  if (_NSGetExecutablePath(NULL, &len) == 0) return NULL;\n  name = (char *)backtrace_alloc(state, len, error_callback, data);\n  if (name == NULL) return NULL;\n  if (_NSGetExecutablePath(name, &len) != 0) {\n    backtrace_free(state, name, len, error_callback, data);\n    return NULL;\n  }\n  return name;\n}\n\n#else\n#define macho_get_executable_path(state, error_callback, data) NULL\n\n#endif\n\nstatic int fileline_initialize(struct backtrace_state *state,\n                               backtrace_error_callback error_callback,\n                               void *data) {\n  int failed;\n  fileline fileline_fn;\n  int pass;\n  int called_error_callback;\n  int descriptor;\n  const char *filename;\n  char buf[64];\n\n  if (!state->threaded)\n    failed = state->fileline_initialization_failed;\n  else\n    failed = backtrace_atomic_load_int(&state->fileline_initialization_failed);\n\n  if (failed) {\n    error_callback(data, \"failed to read executable information\", -1);\n    return 0;\n  }\n\n  if (!state->threaded)\n    fileline_fn = state->fileline_fn;\n  else\n    fileline_fn = backtrace_atomic_load_pointer(&state->fileline_fn);\n  if (fileline_fn != NULL) return 1;\n\n  descriptor = -1;\n  called_error_callback = 0;\n  for (pass = 0; pass < 8; ++pass) {\n    int does_not_exist;\n\n    switch (pass) {\n      case 0:\n        filename = state->filename;\n        break;\n      case 1:\n        filename = getexecname();\n        break;\n      case 2:\n        filename = \"/proc/self/exe\";\n        break;\n      case 3:\n        filename = \"/proc/curproc/file\";\n        break;\n      case 4:\n        snprintf(buf, sizeof(buf), \"/proc/%ld/object/a.out\", (long)getpid());\n        filename = buf;\n        break;\n      case 5:\n        filename = sysctl_exec_name1(state, error_callback, data);\n        break;\n      case 6:\n        filename = sysctl_exec_name2(state, error_callback, data);\n        break;\n      case 7:\n        filename = macho_get_executable_path(state, error_callback, data);\n        break;\n      default:\n        abort();\n    }\n\n    if (filename == NULL) continue;\n\n    descriptor =\n        backtrace_open(filename, error_callback, data, &does_not_exist);\n    if (descriptor < 0 && !does_not_exist) {\n      called_error_callback = 1;\n      break;\n    }\n    if (descriptor >= 0) break;\n  }\n\n  if (descriptor < 0) {\n    if (!called_error_callback) {\n      if (state->filename != NULL)\n        error_callback(data, state->filename, ENOENT);\n      else\n        error_callback(data, \"libbacktrace could not find executable to open\",\n                       0);\n    }\n    failed = 1;\n  }\n\n  if (!failed) {\n    if (!backtrace_initialize(state, filename, descriptor, error_callback, data,\n                              &fileline_fn))\n      failed = 1;\n  }\n\n  if (failed) {\n    if (!state->threaded)\n      state->fileline_initialization_failed = 1;\n    else\n      backtrace_atomic_store_int(&state->fileline_initialization_failed, 1);\n    return 0;\n  }\n\n  if (!state->threaded)\n    state->fileline_fn = fileline_fn;\n  else {\n    backtrace_atomic_store_pointer(&state->fileline_fn, fileline_fn);\n  }\n\n  return 1;\n}\n\nint backtrace_pcinfo(struct backtrace_state *state, uintptr_t pc,\n                     backtrace_full_callback callback,\n                     backtrace_error_callback error_callback, void *data) {\n  if (!fileline_initialize(state, error_callback, data)) return 0;\n\n  if (state->fileline_initialization_failed) return 0;\n\n  return state->fileline_fn(state, pc, callback, error_callback, data);\n}\n\nint backtrace_syminfo(struct backtrace_state *state, uintptr_t pc,\n                      backtrace_syminfo_callback callback,\n                      backtrace_error_callback error_callback, void *data) {\n  if (!fileline_initialize(state, error_callback, data)) return 0;\n\n  if (state->fileline_initialization_failed) return 0;\n\n  state->syminfo_fn(state, pc, callback, error_callback, data);\n  return 1;\n}\n\nvoid backtrace_syminfo_to_full_callback(void *data, uintptr_t pc,\n                                        const char *symname,\n                                        uintptr_t symval ATTRIBUTE_UNUSED,\n                                        uintptr_t symsize ATTRIBUTE_UNUSED) {\n  struct backtrace_call_full *bdata = (struct backtrace_call_full *)data;\n\n  bdata->ret = bdata->full_callback(bdata->full_data, pc, NULL, 0, symname);\n}\n\nvoid backtrace_syminfo_to_full_error_callback(void *data, const char *msg,\n                                              int errnum) {\n  struct backtrace_call_full *bdata = (struct backtrace_call_full *)data;\n\n  bdata->full_error_callback(bdata->full_data, msg, errnum);\n}\n\n// posix.c:\n#include <errno.h>\n#include <fcntl.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#ifndef O_BINARY\n#define O_BINARY 0\n#endif\n\n#ifndef O_CLOEXEC\n#define O_CLOEXEC 0\n#endif\n\n#ifndef FD_CLOEXEC\n#define FD_CLOEXEC 1\n#endif\n\nint backtrace_open(const char *filename,\n                   backtrace_error_callback error_callback, void *data,\n                   int *does_not_exist) {\n  int descriptor;\n\n  if (does_not_exist != NULL) *does_not_exist = 0;\n\n  descriptor = open(filename, (int)(O_RDONLY | O_BINARY | O_CLOEXEC));\n  if (descriptor < 0) {\n    if (does_not_exist != NULL && (errno == ENOENT || errno == EACCES))\n      *does_not_exist = 1;\n    else\n      error_callback(data, filename, errno);\n    return -1;\n  }\n\n#ifdef HAVE_FCNTL\n\n  fcntl(descriptor, F_SETFD, FD_CLOEXEC);\n#endif\n\n  return descriptor;\n}\n\nint backtrace_close(int descriptor, backtrace_error_callback error_callback,\n                    void *data) {\n  if (close(descriptor) < 0) {\n    error_callback(data, \"close\", errno);\n    return 0;\n  }\n  return 1;\n}\n\n// print.c:\n#include <stdio.h>\n#include <string.h>\n#include <sys/types.h>\n\nstruct print_data {\n  struct backtrace_state *state;\n  FILE *f;\n};\n\nstatic int print_callback(void *data, uintptr_t pc, const char *filename,\n                          int lineno, const char *function) {\n  struct print_data *pdata = (struct print_data *)data;\n\n  fprintf(pdata->f, \"0x%lx %s\\n\\t%s:%d\\n\", (unsigned long)pc,\n          function == NULL ? \"???\" : function,\n          filename == NULL ? \"???\" : filename, lineno);\n  return 0;\n}\n\nstatic void error_callback(void *data, const char *msg, int errnum) {\n  struct print_data *pdata = (struct print_data *)data;\n\n  if (pdata->state->filename != NULL)\n    fprintf(stderr, \"%s: \", pdata->state->filename);\n  fprintf(stderr, \"libbacktrace: %s\", msg);\n  if (errnum > 0) fprintf(stderr, \": %s\", strerror(errnum));\n  fputc('\\n', stderr);\n}\n\nvoid __attribute__((noinline))\nbacktrace_print(struct backtrace_state *state, int skip, FILE *f) {\n  struct print_data data;\n\n  data.state = state;\n  data.f = f;\n  backtrace_full(state, skip + 1, print_callback, error_callback,\n                 (void *)&data);\n}\n\n// sort.c:\n#include <stddef.h>\n#include <sys/types.h>\n\nstatic void swap(char *a, char *b, size_t size) {\n  size_t i;\n\n  for (i = 0; i < size; i++, a++, b++) {\n    char t;\n\n    t = *a;\n    *a = *b;\n    *b = t;\n  }\n}\n\nvoid backtrace_qsort(void *basearg, size_t count, size_t size,\n                     int (*compar)(const void *, const void *)) {\n  char *base = (char *)basearg;\n  size_t i;\n  size_t mid;\n\ntail_recurse:\n  if (count < 2) return;\n\n  swap(base, base + (count / 2) * size, size);\n\n  mid = 0;\n  for (i = 1; i < count; i++) {\n    if ((*compar)(base, base + i * size) > 0) {\n      ++mid;\n      if (i != mid) swap(base + mid * size, base + i * size, size);\n    }\n  }\n\n  if (mid > 0) swap(base, base + mid * size, size);\n\n  if (2 * mid < count) {\n    backtrace_qsort(base, mid, size, compar);\n    base += (mid + 1) * size;\n    count -= mid + 1;\n    goto tail_recurse;\n  } else {\n    backtrace_qsort(base + (mid + 1) * size, count - (mid + 1), size, compar);\n    count = mid;\n    goto tail_recurse;\n  }\n}\n\n// state.c:\n#include <string.h>\n#include <sys/types.h>\n\nstruct backtrace_state *backtrace_create_state(\n    const char *filename, int threaded, backtrace_error_callback error_callback,\n    void *data) {\n  struct backtrace_state init_state;\n  struct backtrace_state *state;\n\n#ifndef HAVE_SYNC_FUNCTIONS\n  if (threaded) {\n    error_callback(data, \"backtrace library does not support threads\", 0);\n    return NULL;\n  }\n#endif\n\n  memset(&init_state, 0, sizeof init_state);\n  init_state.filename = filename;\n  init_state.threaded = threaded;\n\n  state = ((struct backtrace_state *)backtrace_alloc(&init_state, sizeof *state,\n                                                     error_callback, data));\n  if (state == NULL) return NULL;\n  *state = init_state;\n\n  return state;\n}\n\n// backtrace.c:\n#include <sys/types.h>\n\n#ifdef BACKTRACE_SUPPORTED\n#include <unwind.h>\n\nstruct backtrace_data {\n  int skip;\n\n  struct backtrace_state *state;\n\n  backtrace_full_callback callback;\n\n  backtrace_error_callback error_callback;\n\n  void *data;\n\n  int ret;\n\n  int can_alloc;\n};\n\nstatic _Unwind_Reason_Code unwind(struct _Unwind_Context *context,\n                                  void *vdata) {\n  struct backtrace_data *bdata = (struct backtrace_data *)vdata;\n  uintptr_t pc;\n  int ip_before_insn = 0;\n\n#ifdef HAVE_GETIPINFO\n  pc = _Unwind_GetIPInfo(context, &ip_before_insn);\n#else\n  pc = _Unwind_GetIP(context);\n#endif\n\n  if (bdata->skip > 0) {\n    --bdata->skip;\n    return _URC_NO_REASON;\n  }\n\n  if (!ip_before_insn) --pc;\n\n  if (!bdata->can_alloc)\n    bdata->ret = bdata->callback(bdata->data, pc, NULL, 0, NULL);\n  else\n    bdata->ret = backtrace_pcinfo(bdata->state, pc, bdata->callback,\n                                  bdata->error_callback, bdata->data);\n  if (bdata->ret != 0) return _URC_END_OF_STACK;\n\n  return _URC_NO_REASON;\n}\n\nint __attribute__((noinline))\nbacktrace_full(struct backtrace_state *state, int skip,\n               backtrace_full_callback callback,\n               backtrace_error_callback error_callback, void *data) {\n  struct backtrace_data bdata;\n  void *p;\n\n  bdata.skip = skip + 1;\n  bdata.state = state;\n  bdata.callback = callback;\n  bdata.error_callback = error_callback;\n  bdata.data = data;\n  bdata.ret = 0;\n\n  p = backtrace_alloc(state, 4096, NULL, NULL);\n  if (p == NULL)\n    bdata.can_alloc = 0;\n  else {\n    backtrace_free(state, p, 4096, NULL, NULL);\n    bdata.can_alloc = 1;\n  }\n\n  _Unwind_Backtrace(unwind, &bdata);\n  return bdata.ret;\n}\n#else\n// Copied from nounwind.c\nint\nbacktrace_full (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t\tint skip ATTRIBUTE_UNUSED,\n\t\tbacktrace_full_callback callback ATTRIBUTE_UNUSED,\n\t\tbacktrace_error_callback error_callback, void *data)\n{\n  error_callback (data,\n\t\t  \"no stack trace because unwind library not available\",\n\t\t  0);\n  return 0;\n}\n#endif\n\n// simple.c:\n#ifdef BACKTRACE_SUPPORTED\n#include <unwind.h>\n\nstruct backtrace_simple_data {\n  int skip;\n\n  struct backtrace_state *state;\n\n  backtrace_simple_callback callback;\n\n  backtrace_error_callback error_callback;\n\n  void *data;\n\n  int ret;\n};\n\nstatic _Unwind_Reason_Code simple_unwind(struct _Unwind_Context *context,\n                                         void *vdata) {\n  struct backtrace_simple_data *bdata = (struct backtrace_simple_data *)vdata;\n  uintptr_t pc;\n  int ip_before_insn = 0;\n\n#ifdef HAVE_GETIPINFO\n  pc = _Unwind_GetIPInfo(context, &ip_before_insn);\n#else\n  pc = _Unwind_GetIP(context);\n#endif\n\n  if (bdata->skip > 0) {\n    --bdata->skip;\n    return _URC_NO_REASON;\n  }\n\n  if (!ip_before_insn) --pc;\n\n  bdata->ret = bdata->callback(bdata->data, pc);\n\n  if (bdata->ret != 0) return _URC_END_OF_STACK;\n\n  return _URC_NO_REASON;\n}\n\nint __attribute__((noinline))\nbacktrace_simple(struct backtrace_state *state, int skip,\n                 backtrace_simple_callback callback,\n                 backtrace_error_callback error_callback, void *data) {\n  struct backtrace_simple_data bdata;\n\n  bdata.skip = skip + 1;\n  bdata.state = state;\n  bdata.callback = callback;\n  bdata.error_callback = error_callback;\n  bdata.data = data;\n  bdata.ret = 0;\n  _Unwind_Backtrace(simple_unwind, &bdata);\n  return bdata.ret;\n}\n#else\nint\nbacktrace_simple (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t\t  int skip ATTRIBUTE_UNUSED,\n\t\t  backtrace_simple_callback callback ATTRIBUTE_UNUSED,\n\t\t  backtrace_error_callback error_callback, void *data)\n{\n  error_callback (data,\n\t\t  \"no stack trace because unwind library not available\",\n\t\t  0);\n  return 0;\n}\n#endif\n"
  },
  {
    "path": "thirdparty/libbacktrace/darwin.c",
    "content": "// macho.c:\n#include <dirent.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n\n#ifdef HAVE_MACH_O_DYLD_H\n#include <mach-o/dyld.h>\n#endif\n\nstruct macho_header_32 {\n  uint32_t magic;\n  uint32_t cputype;\n  uint32_t cpusubtype;\n  uint32_t filetype;\n  uint32_t ncmds;\n  uint32_t sizeofcmds;\n  uint32_t flags;\n};\n\nstruct macho_header_64 {\n  uint32_t magic;\n  uint32_t cputype;\n  uint32_t cpusubtype;\n  uint32_t filetype;\n  uint32_t ncmds;\n  uint32_t sizeofcmds;\n  uint32_t flags;\n  uint32_t reserved;\n};\n\nstruct macho_header_fat {\n  uint32_t magic;\n  uint32_t nfat_arch;\n};\n\n#define MACH_O_MH_MAGIC_32 0xfeedface\n#define MACH_O_MH_MAGIC_64 0xfeedfacf\n#define MACH_O_MH_MAGIC_FAT 0xcafebabe\n#define MACH_O_MH_CIGAM_FAT 0xbebafeca\n#define MACH_O_MH_MAGIC_FAT_64 0xcafebabf\n#define MACH_O_MH_CIGAM_FAT_64 0xbfbafeca\n\n#define MACH_O_MH_EXECUTE 0x02\n#define MACH_O_MH_DYLIB 0x06\n#define MACH_O_MH_DSYM 0x0a\n\nstruct macho_fat_arch {\n  uint32_t cputype;\n  uint32_t cpusubtype;\n  uint32_t offset;\n  uint32_t size;\n  uint32_t align;\n};\n\nstruct macho_fat_arch_64 {\n  uint32_t cputype;\n  uint32_t cpusubtype;\n  uint64_t offset;\n  uint64_t size;\n  uint32_t align;\n  uint32_t reserved;\n};\n\n#define MACH_O_CPU_ARCH_ABI64 0x01000000\n\n#define MACH_O_CPU_TYPE_X86 7\n#define MACH_O_CPU_TYPE_ARM 12\n#define MACH_O_CPU_TYPE_PPC 18\n\n#define MACH_O_CPU_TYPE_X86_64 (MACH_O_CPU_TYPE_X86 | MACH_O_CPU_ARCH_ABI64)\n#define MACH_O_CPU_TYPE_ARM64 (MACH_O_CPU_TYPE_ARM | MACH_O_CPU_ARCH_ABI64)\n#define MACH_O_CPU_TYPE_PPC64 (MACH_O_CPU_TYPE_PPC | MACH_O_CPU_ARCH_ABI64)\n\nstruct macho_load_command {\n  uint32_t cmd;\n  uint32_t cmdsize;\n};\n\n#define MACH_O_LC_SEGMENT 0x01\n#define MACH_O_LC_SYMTAB 0x02\n#define MACH_O_LC_SEGMENT_64 0x19\n#define MACH_O_LC_UUID 0x1b\n\n#define MACH_O_NAMELEN (16)\n\nstruct macho_segment_command {\n  uint32_t cmd;\n  uint32_t cmdsize;\n  char segname[MACH_O_NAMELEN];\n  uint32_t vmaddr;\n  uint32_t vmsize;\n  uint32_t fileoff;\n  uint32_t filesize;\n  uint32_t maxprot;\n  uint32_t initprot;\n  uint32_t nsects;\n  uint32_t flags;\n};\n\nstruct macho_segment_64_command {\n  uint32_t cmd;\n  uint32_t cmdsize;\n  char segname[MACH_O_NAMELEN];\n  uint64_t vmaddr;\n  uint64_t vmsize;\n  uint64_t fileoff;\n  uint64_t filesize;\n  uint32_t maxprot;\n  uint32_t initprot;\n  uint32_t nsects;\n  uint32_t flags;\n};\n\nstruct macho_symtab_command {\n  uint32_t cmd;\n  uint32_t cmdsize;\n  uint32_t symoff;\n  uint32_t nsyms;\n  uint32_t stroff;\n  uint32_t strsize;\n};\n\n#define MACH_O_UUID_LEN (16)\n\nstruct macho_uuid_command {\n  uint32_t cmd;\n  uint32_t cmdsize;\n  unsigned char uuid[MACH_O_UUID_LEN];\n};\n\nstruct macho_section {\n  char sectname[MACH_O_NAMELEN];\n  char segment[MACH_O_NAMELEN];\n  uint32_t addr;\n  uint32_t size;\n  uint32_t offset;\n  uint32_t align;\n  uint32_t reloff;\n  uint32_t nreloc;\n  uint32_t flags;\n  uint32_t reserved1;\n  uint32_t reserved2;\n};\n\nstruct macho_section_64 {\n  char sectname[MACH_O_NAMELEN];\n  char segment[MACH_O_NAMELEN];\n  uint64_t addr;\n  uint64_t size;\n  uint32_t offset;\n  uint32_t align;\n  uint32_t reloff;\n  uint32_t nreloc;\n  uint32_t flags;\n  uint32_t reserved1;\n  uint32_t reserved2;\n  uint32_t reserved3;\n};\n\nstruct macho_nlist {\n  uint32_t n_strx;\n  uint8_t n_type;\n  uint8_t n_sect;\n  uint16_t n_desc;\n  uint32_t n_value;\n};\n\nstruct macho_nlist_64 {\n  uint32_t n_strx;\n  uint8_t n_type;\n  uint8_t n_sect;\n  uint16_t n_desc;\n  uint64_t n_value;\n};\n\n#define MACH_O_N_EXT 0x01\n#define MACH_O_N_ABS 0x02\n#define MACH_O_N_SECT 0x0e\n#define MACH_O_N_TYPE 0x0e\n#define MACH_O_N_STAB 0xe0\n\nstruct macho_symbol {\n  const char *name;\n  uintptr_t address;\n};\n\nstruct macho_syminfo_data {\n  struct macho_syminfo_data *next;\n  struct macho_symbol *symbols;\n  size_t count;\n};\n\nstatic const char *const dwarf_section_names[DEBUG_MAX] = {\n    \"__debug_info\",     \"__debug_line\",\n    \"__debug_abbrev\",   \"__debug_ranges\",\n    \"__debug_str\",      \"\",\n    \"__debug_str_offs\", \"\",\n    \"__debug_rnglists\"};\n\nstatic int macho_add(struct backtrace_state *, const char *, int, off_t,\n                     const unsigned char *, uintptr_t, int,\n                     backtrace_error_callback, void *, fileline *, int *);\n\nstatic int macho_nodebug(struct backtrace_state *state ATTRIBUTE_UNUSED,\n                         uintptr_t pc ATTRIBUTE_UNUSED,\n                         backtrace_full_callback callback ATTRIBUTE_UNUSED,\n                         backtrace_error_callback error_callback, void *data) {\n  error_callback(data, \"no debug info in Mach-O executable\", -1);\n  return 0;\n}\n\nstatic void macho_nosyms(struct backtrace_state *state ATTRIBUTE_UNUSED,\n                         uintptr_t addr ATTRIBUTE_UNUSED,\n                         backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,\n                         backtrace_error_callback error_callback, void *data) {\n  error_callback(data, \"no symbol table in Mach-O executable\", -1);\n}\n\nstatic int macho_add_dwarf_section(struct backtrace_state *state,\n                                   int descriptor, const char *sectname,\n                                   uint32_t offset, uint64_t size,\n                                   backtrace_error_callback error_callback,\n                                   void *data,\n                                   struct dwarf_sections *dwarf_sections) {\n  int i;\n\n  for (i = 0; i < (int)DEBUG_MAX; ++i) {\n    if (dwarf_section_names[i][0] != '\\0' &&\n        strncmp(sectname, dwarf_section_names[i], MACH_O_NAMELEN) == 0) {\n      struct backtrace_view section_view;\n\n      if (!backtrace_get_view(state, descriptor, offset, size, error_callback,\n                              data, &section_view))\n        return 0;\n      dwarf_sections->data[i] = (const unsigned char *)section_view.data;\n      dwarf_sections->size[i] = size;\n      break;\n    }\n  }\n  return 1;\n}\n\nstatic int macho_add_dwarf_segment(struct backtrace_state *state,\n                                   int descriptor, off_t offset,\n                                   unsigned int cmd, const char *psecs,\n                                   size_t sizesecs, unsigned int nsects,\n                                   backtrace_error_callback error_callback,\n                                   void *data,\n                                   struct dwarf_sections *dwarf_sections) {\n  size_t sec_header_size;\n  size_t secoffset;\n  unsigned int i;\n\n  switch (cmd) {\n    case MACH_O_LC_SEGMENT:\n      sec_header_size = sizeof(struct macho_section);\n      break;\n    case MACH_O_LC_SEGMENT_64:\n      sec_header_size = sizeof(struct macho_section_64);\n      break;\n    default:\n      abort();\n  }\n\n  secoffset = 0;\n  for (i = 0; i < nsects; ++i) {\n    if (secoffset + sec_header_size > sizesecs) {\n      error_callback(data, \"section overflow withing segment\", 0);\n      return 0;\n    }\n\n    switch (cmd) {\n      case MACH_O_LC_SEGMENT: {\n        struct macho_section section;\n\n        memcpy(&section, psecs + secoffset, sizeof section);\n        macho_add_dwarf_section(state, descriptor, section.sectname,\n                                offset + section.offset, section.size,\n                                error_callback, data, dwarf_sections);\n      } break;\n\n      case MACH_O_LC_SEGMENT_64: {\n        struct macho_section_64 section;\n\n        memcpy(&section, psecs + secoffset, sizeof section);\n        macho_add_dwarf_section(state, descriptor, section.sectname,\n                                offset + section.offset, section.size,\n                                error_callback, data, dwarf_sections);\n      } break;\n\n      default:\n        abort();\n    }\n\n    secoffset += sec_header_size;\n  }\n\n  return 1;\n}\n\nstatic int macho_symbol_compare(const void *v1, const void *v2) {\n  const struct macho_symbol *m1 = (const struct macho_symbol *)v1;\n  const struct macho_symbol *m2 = (const struct macho_symbol *)v2;\n\n  if (m1->address < m2->address)\n    return -1;\n  else if (m1->address > m2->address)\n    return 1;\n  else\n    return 0;\n}\n\nstatic int macho_symbol_search(const void *vkey, const void *ventry) {\n  const uintptr_t *key = (const uintptr_t *)vkey;\n  const struct macho_symbol *entry = (const struct macho_symbol *)ventry;\n  uintptr_t addr;\n\n  addr = *key;\n  if (addr < entry->address)\n    return -1;\n  else if (entry->name[0] == '\\0' && entry->address == ~(uintptr_t)0)\n    return -1;\n  else if ((entry + 1)->name[0] == '\\0' &&\n           (entry + 1)->address == ~(uintptr_t)0)\n    return -1;\n  else if (addr >= (entry + 1)->address)\n    return 1;\n  else\n    return 0;\n}\n\nstatic int macho_defined_symbol(uint8_t type) {\n  if ((type & MACH_O_N_STAB) != 0) return 0;\n  if ((type & MACH_O_N_EXT) != 0) return 0;\n  switch (type & MACH_O_N_TYPE) {\n    case MACH_O_N_ABS:\n      return 1;\n    case MACH_O_N_SECT:\n      return 1;\n    default:\n      return 0;\n  }\n}\n\nstatic int macho_add_symtab(struct backtrace_state *state, int descriptor,\n                            uintptr_t base_address, int is_64, off_t symoff,\n                            unsigned int nsyms, off_t stroff,\n                            unsigned int strsize,\n                            backtrace_error_callback error_callback,\n                            void *data) {\n  size_t symsize;\n  struct backtrace_view sym_view;\n  int sym_view_valid;\n  struct backtrace_view str_view;\n  int str_view_valid;\n  size_t ndefs;\n  size_t symtaboff;\n  unsigned int i;\n  size_t macho_symbol_size;\n  struct macho_symbol *macho_symbols;\n  unsigned int j;\n  struct macho_syminfo_data *sdata;\n\n  sym_view_valid = 0;\n  str_view_valid = 0;\n  macho_symbol_size = 0;\n  macho_symbols = NULL;\n\n  if (is_64)\n    symsize = sizeof(struct macho_nlist_64);\n  else\n    symsize = sizeof(struct macho_nlist);\n\n  if (!backtrace_get_view(state, descriptor, symoff, nsyms * symsize,\n                          error_callback, data, &sym_view))\n    goto fail;\n  sym_view_valid = 1;\n\n  if (!backtrace_get_view(state, descriptor, stroff, strsize, error_callback,\n                          data, &str_view))\n    return 0;\n  str_view_valid = 1;\n\n  ndefs = 0;\n  symtaboff = 0;\n  for (i = 0; i < nsyms; ++i, symtaboff += symsize) {\n    if (is_64) {\n      struct macho_nlist_64 nlist;\n\n      memcpy(&nlist, (const char *)sym_view.data + symtaboff, sizeof nlist);\n      if (macho_defined_symbol(nlist.n_type)) ++ndefs;\n    } else {\n      struct macho_nlist nlist;\n\n      memcpy(&nlist, (const char *)sym_view.data + symtaboff, sizeof nlist);\n      if (macho_defined_symbol(nlist.n_type)) ++ndefs;\n    }\n  }\n\n  macho_symbol_size = (ndefs + 1) * sizeof(struct macho_symbol);\n  macho_symbols = ((struct macho_symbol *)backtrace_alloc(\n      state, macho_symbol_size, error_callback, data));\n  if (macho_symbols == NULL) goto fail;\n\n  j = 0;\n  symtaboff = 0;\n  for (i = 0; i < nsyms; ++i, symtaboff += symsize) {\n    uint32_t strx;\n    uint64_t value;\n    const char *name;\n\n    strx = 0;\n    value = 0;\n    if (is_64) {\n      struct macho_nlist_64 nlist;\n\n      memcpy(&nlist, (const char *)sym_view.data + symtaboff, sizeof nlist);\n      if (!macho_defined_symbol(nlist.n_type)) continue;\n\n      strx = nlist.n_strx;\n      value = nlist.n_value;\n    } else {\n      struct macho_nlist nlist;\n\n      memcpy(&nlist, (const char *)sym_view.data + symtaboff, sizeof nlist);\n      if (!macho_defined_symbol(nlist.n_type)) continue;\n\n      strx = nlist.n_strx;\n      value = nlist.n_value;\n    }\n\n    if (strx >= strsize) {\n      error_callback(data, \"symbol string index out of range\", 0);\n      goto fail;\n    }\n\n    name = (const char *)str_view.data + strx;\n    if (name[0] == '_') ++name;\n    macho_symbols[j].name = name;\n    macho_symbols[j].address = value + base_address;\n    ++j;\n  }\n\n  sdata = ((struct macho_syminfo_data *)backtrace_alloc(state, sizeof *sdata,\n                                                        error_callback, data));\n  if (sdata == NULL) goto fail;\n\n  backtrace_release_view(state, &sym_view, error_callback, data);\n  sym_view_valid = 0;\n  str_view_valid = 0;\n\n  macho_symbols[j].name = \"\";\n  macho_symbols[j].address = ~(uintptr_t)0;\n\n  backtrace_qsort(macho_symbols, ndefs + 1, sizeof(struct macho_symbol),\n                  macho_symbol_compare);\n\n  sdata->next = NULL;\n  sdata->symbols = macho_symbols;\n  sdata->count = ndefs;\n\n  if (!state->threaded) {\n    struct macho_syminfo_data **pp;\n\n    for (pp = (struct macho_syminfo_data **)(void *)&state->syminfo_data;\n         *pp != NULL; pp = &(*pp)->next)\n      ;\n    *pp = sdata;\n  } else {\n    while (1) {\n      struct macho_syminfo_data **pp;\n\n      pp = (struct macho_syminfo_data **)(void *)&state->syminfo_data;\n\n      while (1) {\n        struct macho_syminfo_data *p;\n\n        p = backtrace_atomic_load_pointer(pp);\n\n        if (p == NULL) break;\n\n        pp = &p->next;\n      }\n\n      if (__sync_bool_compare_and_swap(pp, NULL, sdata)) break;\n    }\n  }\n\n  return 1;\n\nfail:\n  if (macho_symbols != NULL)\n    backtrace_free(state, macho_symbols, macho_symbol_size, error_callback,\n                   data);\n  if (sym_view_valid)\n    backtrace_release_view(state, &sym_view, error_callback, data);\n  if (str_view_valid)\n    backtrace_release_view(state, &str_view, error_callback, data);\n  return 0;\n}\n\nstatic void macho_syminfo(\n    struct backtrace_state *state, uintptr_t addr,\n    backtrace_syminfo_callback callback,\n    backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data) {\n  struct macho_syminfo_data *sdata;\n  struct macho_symbol *sym;\n\n  sym = NULL;\n  if (!state->threaded) {\n    for (sdata = (struct macho_syminfo_data *)state->syminfo_data;\n         sdata != NULL; sdata = sdata->next) {\n      sym = ((struct macho_symbol *)bsearch(&addr, sdata->symbols, sdata->count,\n                                            sizeof(struct macho_symbol),\n                                            macho_symbol_search));\n      if (sym != NULL) break;\n    }\n  } else {\n    struct macho_syminfo_data **pp;\n\n    pp = (struct macho_syminfo_data **)(void *)&state->syminfo_data;\n    while (1) {\n      sdata = backtrace_atomic_load_pointer(pp);\n      if (sdata == NULL) break;\n\n      sym = ((struct macho_symbol *)bsearch(&addr, sdata->symbols, sdata->count,\n                                            sizeof(struct macho_symbol),\n                                            macho_symbol_search));\n      if (sym != NULL) break;\n\n      pp = &sdata->next;\n    }\n  }\n\n  if (sym == NULL)\n    callback(data, addr, NULL, 0, 0);\n  else\n    callback(data, addr, sym->name, sym->address, 0);\n}\n\nstatic int macho_add_fat(struct backtrace_state *state, const char *filename,\n                         int descriptor, int swapped, off_t offset,\n                         const unsigned char *match_uuid,\n                         uintptr_t base_address, int skip_symtab,\n                         uint32_t nfat_arch, int is_64,\n                         backtrace_error_callback error_callback, void *data,\n                         fileline *fileline_fn, int *found_sym) {\n  int arch_view_valid;\n  unsigned int cputype;\n  size_t arch_size;\n  struct backtrace_view arch_view;\n  unsigned int i;\n\n  arch_view_valid = 0;\n\n#if defined(__x86_64__)\n  cputype = MACH_O_CPU_TYPE_X86_64;\n#elif defined(__i386__)\n  cputype = MACH_O_CPU_TYPE_X86;\n#elif defined(__aarch64__)\n  cputype = MACH_O_CPU_TYPE_ARM64;\n#elif defined(__arm__)\n  cputype = MACH_O_CPU_TYPE_ARM;\n#elif defined(__ppc__)\n  cputype = MACH_O_CPU_TYPE_PPC;\n#elif defined(__ppc64__)\n  cputype = MACH_O_CPU_TYPE_PPC64;\n#else\n  error_callback(data, \"unknown Mach-O architecture\", 0);\n  goto fail;\n#endif\n\n  if (is_64)\n    arch_size = sizeof(struct macho_fat_arch_64);\n  else\n    arch_size = sizeof(struct macho_fat_arch);\n\n  if (!backtrace_get_view(state, descriptor, offset, nfat_arch * arch_size,\n                          error_callback, data, &arch_view))\n    goto fail;\n\n  for (i = 0; i < nfat_arch; ++i) {\n    uint32_t fcputype;\n    uint64_t foffset;\n\n    if (is_64) {\n      struct macho_fat_arch_64 fat_arch_64;\n\n      memcpy(&fat_arch_64, (const char *)arch_view.data + i * arch_size,\n             arch_size);\n      fcputype = fat_arch_64.cputype;\n      foffset = fat_arch_64.offset;\n      if (swapped) {\n        fcputype = __builtin_bswap32(fcputype);\n        foffset = __builtin_bswap64(foffset);\n      }\n    } else {\n      struct macho_fat_arch fat_arch_32;\n\n      memcpy(&fat_arch_32, (const char *)arch_view.data + i * arch_size,\n             arch_size);\n      fcputype = fat_arch_32.cputype;\n      foffset = (uint64_t)fat_arch_32.offset;\n      if (swapped) {\n        fcputype = __builtin_bswap32(fcputype);\n        foffset = (uint64_t)__builtin_bswap32((uint32_t)foffset);\n      }\n    }\n\n    if (fcputype == cputype) {\n      backtrace_release_view(state, &arch_view, error_callback, data);\n      return macho_add(state, filename, descriptor, foffset, match_uuid,\n                       base_address, skip_symtab, error_callback, data,\n                       fileline_fn, found_sym);\n    }\n  }\n\n  error_callback(data, \"could not find executable in fat file\", 0);\n\nfail:\n  if (arch_view_valid)\n    backtrace_release_view(state, &arch_view, error_callback, data);\n  if (descriptor != -1) backtrace_close(descriptor, error_callback, data);\n  return 0;\n}\n\nstatic int macho_add_dsym(struct backtrace_state *state, const char *filename,\n                          uintptr_t base_address, const unsigned char *uuid,\n                          backtrace_error_callback error_callback, void *data,\n                          fileline *fileline_fn) {\n  const char *p;\n  const char *dirname;\n  char *diralc;\n  size_t dirnamelen;\n  const char *basename;\n  size_t basenamelen;\n  const char *dsymsuffixdir;\n  size_t dsymsuffixdirlen;\n  size_t dsymlen;\n  char *dsym;\n  char *ps;\n  int d;\n  int does_not_exist;\n  int dummy_found_sym;\n\n  diralc = NULL;\n  dirnamelen = 0;\n  dsym = NULL;\n  dsymlen = 0;\n\n  p = strrchr(filename, '/');\n  if (p == NULL) {\n    dirname = \".\";\n    dirnamelen = 1;\n    basename = filename;\n    basenamelen = strlen(basename);\n    diralc = NULL;\n  } else {\n    dirnamelen = p - filename;\n    diralc = backtrace_alloc(state, dirnamelen + 1, error_callback, data);\n    if (diralc == NULL) goto fail;\n    memcpy(diralc, filename, dirnamelen);\n    diralc[dirnamelen] = '\\0';\n    dirname = diralc;\n    basename = p + 1;\n    basenamelen = strlen(basename);\n  }\n\n  dsymsuffixdir = \".dSYM/Contents/Resources/DWARF/\";\n  dsymsuffixdirlen = strlen(dsymsuffixdir);\n\n  dsymlen = (dirnamelen + 1 + basenamelen + dsymsuffixdirlen + basenamelen + 1);\n  dsym = backtrace_alloc(state, dsymlen, error_callback, data);\n  if (dsym == NULL) goto fail;\n\n  ps = dsym;\n  memcpy(ps, dirname, dirnamelen);\n  ps += dirnamelen;\n  *ps++ = '/';\n  memcpy(ps, basename, basenamelen);\n  ps += basenamelen;\n  memcpy(ps, dsymsuffixdir, dsymsuffixdirlen);\n  ps += dsymsuffixdirlen;\n  memcpy(ps, basename, basenamelen);\n  ps += basenamelen;\n  *ps = '\\0';\n\n  if (diralc != NULL) {\n    backtrace_free(state, diralc, dirnamelen + 1, error_callback, data);\n    diralc = NULL;\n  }\n\n  d = backtrace_open(dsym, error_callback, data, &does_not_exist);\n  if (d < 0) {\n    backtrace_free(state, dsym, dsymlen, error_callback, data);\n    return 1;\n  }\n\n  if (!macho_add(state, dsym, d, 0, uuid, base_address, 1, error_callback, data,\n                 fileline_fn, &dummy_found_sym))\n    goto fail;\n\n  backtrace_free(state, dsym, dsymlen, error_callback, data);\n\n  return 1;\n\nfail:\n  if (dsym != NULL) backtrace_free(state, dsym, dsymlen, error_callback, data);\n  if (diralc != NULL)\n    backtrace_free(state, diralc, dirnamelen, error_callback, data);\n  return 0;\n}\n\nstatic int macho_add(struct backtrace_state *state, const char *filename,\n                     int descriptor, off_t offset,\n                     const unsigned char *match_uuid, uintptr_t base_address,\n                     int skip_symtab, backtrace_error_callback error_callback,\n                     void *data, fileline *fileline_fn, int *found_sym) {\n  struct backtrace_view header_view;\n  struct macho_header_32 header;\n  off_t hdroffset;\n  int is_64;\n  struct backtrace_view cmds_view;\n  int cmds_view_valid;\n  struct dwarf_sections dwarf_sections;\n  int have_dwarf;\n  unsigned char uuid[MACH_O_UUID_LEN];\n  int have_uuid;\n  size_t cmdoffset;\n  unsigned int i;\n\n  *found_sym = 0;\n\n  cmds_view_valid = 0;\n\n  if (!backtrace_get_view(state, descriptor, offset,\n                          sizeof(struct macho_header_32), error_callback, data,\n                          &header_view))\n    goto fail;\n\n  memcpy(&header, header_view.data, sizeof header);\n\n  backtrace_release_view(state, &header_view, error_callback, data);\n\n  switch (header.magic) {\n    case MACH_O_MH_MAGIC_32:\n      is_64 = 0;\n      hdroffset = offset + sizeof(struct macho_header_32);\n      break;\n    case MACH_O_MH_MAGIC_64:\n      is_64 = 1;\n      hdroffset = offset + sizeof(struct macho_header_64);\n      break;\n    case MACH_O_MH_MAGIC_FAT:\n    case MACH_O_MH_MAGIC_FAT_64: {\n      struct macho_header_fat fat_header;\n\n      hdroffset = offset + sizeof(struct macho_header_fat);\n      memcpy(&fat_header, &header, sizeof fat_header);\n      return macho_add_fat(state, filename, descriptor, 0, hdroffset,\n                           match_uuid, base_address, skip_symtab,\n                           fat_header.nfat_arch,\n                           header.magic == MACH_O_MH_MAGIC_FAT_64,\n                           error_callback, data, fileline_fn, found_sym);\n    }\n    case MACH_O_MH_CIGAM_FAT:\n    case MACH_O_MH_CIGAM_FAT_64: {\n      struct macho_header_fat fat_header;\n      uint32_t nfat_arch;\n\n      hdroffset = offset + sizeof(struct macho_header_fat);\n      memcpy(&fat_header, &header, sizeof fat_header);\n      nfat_arch = __builtin_bswap32(fat_header.nfat_arch);\n      return macho_add_fat(state, filename, descriptor, 1, hdroffset,\n                           match_uuid, base_address, skip_symtab, nfat_arch,\n                           header.magic == MACH_O_MH_CIGAM_FAT_64,\n                           error_callback, data, fileline_fn, found_sym);\n    }\n    default:\n      error_callback(data, \"executable file is not in Mach-O format\", 0);\n      goto fail;\n  }\n\n  switch (header.filetype) {\n    case MACH_O_MH_EXECUTE:\n    case MACH_O_MH_DYLIB:\n    case MACH_O_MH_DSYM:\n      break;\n    default:\n      error_callback(data, \"executable file is not an executable\", 0);\n      goto fail;\n  }\n\n  if (!backtrace_get_view(state, descriptor, hdroffset, header.sizeofcmds,\n                          error_callback, data, &cmds_view))\n    goto fail;\n  cmds_view_valid = 1;\n\n  memset(&dwarf_sections, 0, sizeof dwarf_sections);\n  have_dwarf = 0;\n  memset(&uuid, 0, sizeof uuid);\n  have_uuid = 0;\n\n  cmdoffset = 0;\n  for (i = 0; i < header.ncmds; ++i) {\n    const char *pcmd;\n    struct macho_load_command load_command;\n\n    if (cmdoffset + sizeof load_command > header.sizeofcmds) break;\n\n    pcmd = (const char *)cmds_view.data + cmdoffset;\n    memcpy(&load_command, pcmd, sizeof load_command);\n\n    switch (load_command.cmd) {\n      case MACH_O_LC_SEGMENT: {\n        struct macho_segment_command segcmd;\n\n        memcpy(&segcmd, pcmd, sizeof segcmd);\n        if (memcmp(segcmd.segname, \"__DWARF\\0\\0\\0\\0\\0\\0\\0\\0\\0\",\n                   MACH_O_NAMELEN) == 0) {\n          if (!macho_add_dwarf_segment(\n                  state, descriptor, offset, load_command.cmd,\n                  pcmd + sizeof segcmd, (load_command.cmdsize - sizeof segcmd),\n                  segcmd.nsects, error_callback, data, &dwarf_sections))\n            goto fail;\n          have_dwarf = 1;\n        }\n      } break;\n\n      case MACH_O_LC_SEGMENT_64: {\n        struct macho_segment_64_command segcmd;\n\n        memcpy(&segcmd, pcmd, sizeof segcmd);\n        if (memcmp(segcmd.segname, \"__DWARF\\0\\0\\0\\0\\0\\0\\0\\0\\0\",\n                   MACH_O_NAMELEN) == 0) {\n          if (!macho_add_dwarf_segment(\n                  state, descriptor, offset, load_command.cmd,\n                  pcmd + sizeof segcmd, (load_command.cmdsize - sizeof segcmd),\n                  segcmd.nsects, error_callback, data, &dwarf_sections))\n            goto fail;\n          have_dwarf = 1;\n        }\n      } break;\n\n      case MACH_O_LC_SYMTAB:\n        if (!skip_symtab) {\n          struct macho_symtab_command symcmd;\n\n          memcpy(&symcmd, pcmd, sizeof symcmd);\n          if (!macho_add_symtab(state, descriptor, base_address, is_64,\n                                offset + symcmd.symoff, symcmd.nsyms,\n                                offset + symcmd.stroff, symcmd.strsize,\n                                error_callback, data))\n            goto fail;\n\n          *found_sym = 1;\n        }\n        break;\n\n      case MACH_O_LC_UUID: {\n        struct macho_uuid_command uuidcmd;\n\n        memcpy(&uuidcmd, pcmd, sizeof uuidcmd);\n        memcpy(&uuid[0], &uuidcmd.uuid[0], MACH_O_UUID_LEN);\n        have_uuid = 1;\n      } break;\n\n      default:\n        break;\n    }\n\n    cmdoffset += load_command.cmdsize;\n  }\n\n  if (!backtrace_close(descriptor, error_callback, data)) goto fail;\n  descriptor = -1;\n\n  backtrace_release_view(state, &cmds_view, error_callback, data);\n  cmds_view_valid = 0;\n\n  if (match_uuid != NULL) {\n    if (!have_uuid || memcmp(match_uuid, &uuid[0], MACH_O_UUID_LEN) != 0)\n      return 1;\n  }\n\n  if (have_dwarf) {\n    int is_big_endian;\n\n    is_big_endian = 0;\n#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)\n#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n    is_big_endian = 1;\n#endif\n#endif\n\n    if (!backtrace_dwarf_add(state, base_address, &dwarf_sections,\n                             is_big_endian, NULL, error_callback, data,\n                             fileline_fn, NULL))\n      goto fail;\n  }\n\n  if (!have_dwarf && have_uuid) {\n    if (!macho_add_dsym(state, filename, base_address, &uuid[0], error_callback,\n                        data, fileline_fn))\n      goto fail;\n  }\n\n  return 1;\n\nfail:\n  if (cmds_view_valid)\n    backtrace_release_view(state, &cmds_view, error_callback, data);\n  if (descriptor != -1) backtrace_close(descriptor, error_callback, data);\n  return 0;\n}\n\n#ifdef HAVE_MACH_O_DYLD_H\n\nint backtrace_initialize(struct backtrace_state *state, const char *filename,\n                         int descriptor,\n                         backtrace_error_callback error_callback, void *data,\n                         fileline *fileline_fn) {\n  uint32_t c;\n  uint32_t i;\n  int closed_descriptor;\n  int found_sym;\n  fileline macho_fileline_fn;\n\n  closed_descriptor = 0;\n  found_sym = 0;\n  macho_fileline_fn = macho_nodebug;\n\n  c = _dyld_image_count();\n  for (i = 0; i < c; ++i) {\n    uintptr_t base_address;\n    const char *name;\n    int d;\n    fileline mff;\n    int mfs;\n\n    name = _dyld_get_image_name(i);\n    if (name == NULL) continue;\n\n    if (strcmp(name, filename) == 0 && !closed_descriptor) {\n      d = descriptor;\n      closed_descriptor = 1;\n    } else {\n      int does_not_exist;\n\n      d = backtrace_open(name, error_callback, data, &does_not_exist);\n      if (d < 0) continue;\n    }\n\n    base_address = _dyld_get_image_vmaddr_slide(i);\n\n    mff = macho_nodebug;\n    if (!macho_add(state, name, d, 0, NULL, base_address, 0, error_callback,\n                   data, &mff, &mfs))\n      return 0;\n\n    if (mff != macho_nodebug) macho_fileline_fn = mff;\n    if (mfs) found_sym = 1;\n  }\n\n  if (!closed_descriptor) backtrace_close(descriptor, error_callback, data);\n\n  if (!state->threaded) {\n    if (found_sym)\n      state->syminfo_fn = macho_syminfo;\n    else if (state->syminfo_fn == NULL)\n      state->syminfo_fn = macho_nosyms;\n  } else {\n    if (found_sym)\n      backtrace_atomic_store_pointer(&state->syminfo_fn, macho_syminfo);\n    else\n      (void)__sync_bool_compare_and_swap(&state->syminfo_fn, NULL,\n                                         macho_nosyms);\n  }\n\n  if (!state->threaded)\n    *fileline_fn = state->fileline_fn;\n  else\n    *fileline_fn = backtrace_atomic_load_pointer(&state->fileline_fn);\n\n  if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)\n    *fileline_fn = macho_fileline_fn;\n\n  return 1;\n}\n\n#else\n\nint backtrace_initialize(struct backtrace_state *state, const char *filename,\n                         int descriptor,\n                         backtrace_error_callback error_callback, void *data,\n                         fileline *fileline_fn) {\n  fileline macho_fileline_fn;\n  int found_sym;\n\n  macho_fileline_fn = macho_nodebug;\n  if (!macho_add(state, filename, descriptor, 0, NULL, 0, 0, error_callback,\n                 data, &macho_fileline_fn, &found_sym))\n    return 0;\n\n  if (!state->threaded) {\n    if (found_sym)\n      state->syminfo_fn = macho_syminfo;\n    else if (state->syminfo_fn == NULL)\n      state->syminfo_fn = macho_nosyms;\n  } else {\n    if (found_sym)\n      backtrace_atomic_store_pointer(&state->syminfo_fn, macho_syminfo);\n    else\n      (void)__sync_bool_compare_and_swap(&state->syminfo_fn, NULL,\n                                         macho_nosyms);\n  }\n\n  if (!state->threaded)\n    *fileline_fn = state->fileline_fn;\n  else\n    *fileline_fn = backtrace_atomic_load_pointer(&state->fileline_fn);\n\n  if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)\n    *fileline_fn = macho_fileline_fn;\n\n  return 1;\n}\n\n#endif\n\n// mmapio.c:\n#include <errno.h>\n#include <sys/mman.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#ifndef HAVE_DECL_GETPAGESIZE\nextern int getpagesize(void);\n#endif\n\n#ifndef MAP_FAILED\n#define MAP_FAILED ((void *)-1)\n#endif\n\nint backtrace_get_view(struct backtrace_state *state ATTRIBUTE_UNUSED,\n                       int descriptor, off_t offset, uint64_t size,\n                       backtrace_error_callback error_callback, void *data,\n                       struct backtrace_view *view) {\n  size_t pagesize;\n  unsigned int inpage;\n  off_t pageoff;\n  void *map;\n\n  if ((uint64_t)(size_t)size != size) {\n    error_callback(data, \"file size too large\", 0);\n    return 0;\n  }\n\n  pagesize = getpagesize();\n  inpage = offset % pagesize;\n  pageoff = offset - inpage;\n\n  size += inpage;\n  size = (size + (pagesize - 1)) & ~(pagesize - 1);\n\n  map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, descriptor, pageoff);\n  if (map == MAP_FAILED) {\n    error_callback(data, \"mmap\", errno);\n    return 0;\n  }\n\n  view->data = (char *)map + inpage;\n  view->base = map;\n  view->len = size;\n\n  return 1;\n}\n\nvoid backtrace_release_view(struct backtrace_state *state ATTRIBUTE_UNUSED,\n                            struct backtrace_view *view,\n                            backtrace_error_callback error_callback,\n                            void *data) {\n  union {\n    const void *cv;\n    void *v;\n  } const_cast;\n\n  const_cast.cv = view->base;\n  if (munmap(const_cast.v, view->len) < 0)\n    error_callback(data, \"munmap\", errno);\n}\n\n// mmap.c:\n#include <errno.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#ifndef HAVE_DECL_GETPAGESIZE\nextern int getpagesize(void);\n#endif\n\n#ifndef MAP_ANONYMOUS\n#define MAP_ANONYMOUS MAP_ANON\n#endif\n\n#ifndef MAP_FAILED\n#define MAP_FAILED ((void *)-1)\n#endif\n\nstruct backtrace_freelist_struct {\n  struct backtrace_freelist_struct *next;\n\n  size_t size;\n};\n\nstatic void backtrace_free_locked(struct backtrace_state *state, void *addr,\n                                  size_t size) {\n  if (size >= sizeof(struct backtrace_freelist_struct)) {\n    size_t c;\n    struct backtrace_freelist_struct **ppsmall;\n    struct backtrace_freelist_struct **pp;\n    struct backtrace_freelist_struct *p;\n\n    c = 0;\n    ppsmall = NULL;\n    for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next) {\n      if (ppsmall == NULL || (*pp)->size < (*ppsmall)->size) ppsmall = pp;\n      ++c;\n    }\n    if (c >= 16) {\n      if (size <= (*ppsmall)->size) return;\n      *ppsmall = (*ppsmall)->next;\n    }\n\n    p = (struct backtrace_freelist_struct *)addr;\n    p->next = state->freelist;\n    p->size = size;\n    state->freelist = p;\n  }\n}\n\nvoid *backtrace_alloc(struct backtrace_state *state, size_t size,\n                      backtrace_error_callback error_callback, void *data) {\n  void *ret;\n  int locked;\n  struct backtrace_freelist_struct **pp;\n  size_t pagesize;\n  size_t asksize;\n  void *page;\n\n  ret = NULL;\n\n  if (!state->threaded)\n    locked = 1;\n  else\n    locked = __sync_lock_test_and_set(&state->lock_alloc, 1) == 0;\n\n  if (locked) {\n    for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next) {\n      if ((*pp)->size >= size) {\n        struct backtrace_freelist_struct *p;\n\n        p = *pp;\n        *pp = p->next;\n\n        size = (size + 7) & ~(size_t)7;\n        if (size < p->size)\n          backtrace_free_locked(state, (char *)p + size, p->size - size);\n\n        ret = (void *)p;\n\n        break;\n      }\n    }\n\n    if (state->threaded) __sync_lock_release(&state->lock_alloc);\n  }\n\n  if (ret == NULL) {\n    pagesize = getpagesize();\n    asksize = (size + pagesize - 1) & ~(pagesize - 1);\n    page = mmap(NULL, asksize, PROT_READ | PROT_WRITE,\n                MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n    if (page == MAP_FAILED) {\n      if (error_callback) error_callback(data, \"mmap\", errno);\n    } else {\n      size = (size + 7) & ~(size_t)7;\n      if (size < asksize)\n        backtrace_free(state, (char *)page + size, asksize - size,\n                       error_callback, data);\n\n      ret = page;\n    }\n  }\n\n  return ret;\n}\n\nvoid backtrace_free(struct backtrace_state *state, void *addr, size_t size,\n                    backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n                    void *data ATTRIBUTE_UNUSED) {\n  int locked;\n\n  if (size >= 16 * 4096) {\n    size_t pagesize;\n\n    pagesize = getpagesize();\n    if (((uintptr_t)addr & (pagesize - 1)) == 0 &&\n        (size & (pagesize - 1)) == 0) {\n      if (munmap(addr, size) == 0) return;\n    }\n  }\n\n  if (!state->threaded)\n    locked = 1;\n  else\n    locked = __sync_lock_test_and_set(&state->lock_alloc, 1) == 0;\n\n  if (locked) {\n    backtrace_free_locked(state, addr, size);\n\n    if (state->threaded) __sync_lock_release(&state->lock_alloc);\n  }\n}\n\nvoid *backtrace_vector_grow(struct backtrace_state *state, size_t size,\n                            backtrace_error_callback error_callback, void *data,\n                            struct backtrace_vector *vec) {\n  void *ret;\n\n  if (size > vec->alc) {\n    size_t pagesize;\n    size_t alc;\n    void *base;\n\n    pagesize = getpagesize();\n    alc = vec->size + size;\n    if (vec->size == 0)\n      alc = 16 * size;\n    else if (alc < pagesize) {\n      alc *= 2;\n      if (alc > pagesize) alc = pagesize;\n    } else {\n      alc *= 2;\n      alc = (alc + pagesize - 1) & ~(pagesize - 1);\n    }\n    base = backtrace_alloc(state, alc, error_callback, data);\n    if (base == NULL) return NULL;\n    if (vec->base != NULL) {\n      memcpy(base, vec->base, vec->size);\n      backtrace_free(state, vec->base, vec->size + vec->alc, error_callback,\n                     data);\n    }\n    vec->base = base;\n    vec->alc = alc - vec->size;\n  }\n\n  ret = (char *)vec->base + vec->size;\n  vec->size += size;\n  vec->alc -= size;\n  return ret;\n}\n\nvoid *backtrace_vector_finish(struct backtrace_state *state ATTRIBUTE_UNUSED,\n                              struct backtrace_vector *vec,\n                              backtrace_error_callback error_callback\n                                  ATTRIBUTE_UNUSED,\n                              void *data ATTRIBUTE_UNUSED) {\n  void *ret;\n\n  ret = vec->base;\n  vec->base = (char *)vec->base + vec->size;\n  vec->size = 0;\n  return ret;\n}\n\nint backtrace_vector_release(struct backtrace_state *state,\n                             struct backtrace_vector *vec,\n                             backtrace_error_callback error_callback,\n                             void *data) {\n  size_t size;\n  size_t alc;\n  size_t aligned;\n\n  size = vec->size;\n  alc = vec->alc;\n  aligned = (size + 7) & ~(size_t)7;\n  alc -= aligned - size;\n\n  backtrace_free(state, (char *)vec->base + aligned, alc, error_callback, data);\n  vec->alc = 0;\n  if (vec->size == 0) vec->base = NULL;\n  return 1;\n}\n"
  },
  {
    "path": "thirdparty/libbacktrace/linux.c",
    "content": "// elf.c:\n#include <errno.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#ifdef HAVE_DL_ITERATE_PHDR\n#include <link.h>\n#endif\n\n#ifndef S_ISLNK\n#ifndef S_IFLNK\n#define S_IFLNK 0120000\n#endif\n#ifndef S_IFMT\n#define S_IFMT 0170000\n#endif\n#define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK)\n#endif\n\n#ifndef __GNUC__\n#define __builtin_prefetch(p, r, l)\n#define unlikely(x) (x)\n#else\n#define unlikely(x) __builtin_expect(!!(x), 0)\n#endif\n\n#if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN\n\nstatic size_t xstrnlen(const char *s, size_t maxlen) {\n  size_t i;\n\n  for (i = 0; i < maxlen; ++i)\n    if (s[i] == '\\0') break;\n  return i;\n}\n\n#define strnlen xstrnlen\n\n#endif\n\n#ifndef HAVE_LSTAT\n\nstatic int xlstat(const char *path ATTRIBUTE_UNUSED,\n                  struct stat *st ATTRIBUTE_UNUSED) {\n  return -1;\n}\n\n#define lstat xlstat\n\n#endif\n\n#ifndef HAVE_READLINK\n\nstatic ssize_t xreadlink(const char *path ATTRIBUTE_UNUSED,\n                         char *buf ATTRIBUTE_UNUSED,\n                         size_t bufsz ATTRIBUTE_UNUSED) {\n  return -1;\n}\n\n#define readlink xreadlink\n\n#endif\n\n#ifndef HAVE_DL_ITERATE_PHDR\n\n#define dl_phdr_info x_dl_phdr_info\n#define dl_iterate_phdr x_dl_iterate_phdr\n\nstruct dl_phdr_info {\n  uintptr_t dlpi_addr;\n  const char *dlpi_name;\n};\n\nstatic int dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t,\n                                           void *) ATTRIBUTE_UNUSED,\n                           void *data ATTRIBUTE_UNUSED) {\n  return 0;\n}\n\n#endif\n\n#if BACKTRACE_ELF_SIZE != 32 && BACKTRACE_ELF_SIZE != 64\n#error \"Unknown BACKTRACE_ELF_SIZE\"\n#endif\n\n#undef EI_NIDENT\n#undef EI_MAG0\n#undef EI_MAG1\n#undef EI_MAG2\n#undef EI_MAG3\n#undef EI_CLASS\n#undef EI_DATA\n#undef EI_VERSION\n#undef ELF_MAG0\n#undef ELF_MAG1\n#undef ELF_MAG2\n#undef ELF_MAG3\n#undef ELFCLASS32\n#undef ELFCLASS64\n#undef ELFDATA2LSB\n#undef ELFDATA2MSB\n#undef EV_CURRENT\n#undef ET_DYN\n#undef EM_PPC64\n#undef EF_PPC64_ABI\n#undef SHN_LORESERVE\n#undef SHN_XINDEX\n#undef SHN_UNDEF\n#undef SHT_PROGBITS\n#undef SHT_SYMTAB\n#undef SHT_STRTAB\n#undef SHT_DYNSYM\n#undef SHF_COMPRESSED\n#undef STT_OBJECT\n#undef STT_FUNC\n#undef NT_GNU_BUILD_ID\n#undef ELFCOMPRESS_ZLIB\n\ntypedef uint16_t b_elf_half;\ntypedef uint32_t b_elf_word;\ntypedef int32_t b_elf_sword;\n#if BACKTRACE_ELF_SIZE == 32\n\ntypedef uint32_t b_elf_addr;\ntypedef uint32_t b_elf_off;\ntypedef uint32_t b_elf_wxword;\n#else\n\ntypedef uint64_t b_elf_addr;\ntypedef uint64_t b_elf_off;\ntypedef uint64_t b_elf_xword;\ntypedef int64_t b_elf_sxword;\ntypedef uint64_t b_elf_wxword;\n#endif\n\n#define EI_NIDENT 16\n\ntypedef struct {\n  unsigned char e_ident[EI_NIDENT];\n  b_elf_half e_type;\n  b_elf_half e_machine;\n  b_elf_word e_version;\n  b_elf_addr e_entry;\n  b_elf_off e_phoff;\n  b_elf_off e_shoff;\n  b_elf_word e_flags;\n  b_elf_half e_ehsize;\n  b_elf_half e_phentsize;\n  b_elf_half e_phnum;\n  b_elf_half e_shentsize;\n  b_elf_half e_shnum;\n  b_elf_half e_shstrndx;\n} b_elf_ehdr;\n#define EI_MAG0 0\n#define EI_MAG1 1\n#define EI_MAG2 2\n#define EI_MAG3 3\n#define EI_CLASS 4\n#define EI_DATA 5\n#define EI_VERSION 6\n\n#define ELFMAG0 0x7f\n#define ELFMAG1 'E'\n#define ELFMAG2 'L'\n#define ELFMAG3 'F'\n\n#define ELFCLASS32 1\n#define ELFCLASS64 2\n\n#define ELFDATA2LSB 1\n#define ELFDATA2MSB 2\n\n#define EV_CURRENT 1\n\n#define ET_DYN 3\n\n#define EM_PPC64 21\n#define EF_PPC64_ABI 3\n\ntypedef struct {\n  b_elf_word sh_name;\n  b_elf_word sh_type;\n  b_elf_wxword sh_flags;\n  b_elf_addr sh_addr;\n  b_elf_off sh_offset;\n  b_elf_wxword sh_size;\n  b_elf_word sh_link;\n  b_elf_word sh_info;\n  b_elf_wxword sh_addralign;\n  b_elf_wxword sh_entsize;\n} b_elf_shdr;\n#define SHN_UNDEF 0x0000\n#define SHN_LORESERVE 0xFF00\n#define SHN_XINDEX 0xFFFF\n#define SHT_PROGBITS 1\n#define SHT_SYMTAB 2\n#define SHT_STRTAB 3\n#define SHT_DYNSYM 11\n\n#define SHF_COMPRESSED 0x800\n\n#if BACKTRACE_ELF_SIZE == 32\n\ntypedef struct {\n  b_elf_word st_name;\n  b_elf_addr st_value;\n  b_elf_word st_size;\n  unsigned char st_info;\n  unsigned char st_other;\n  b_elf_half st_shndx;\n} b_elf_sym;\n#else\ntypedef struct {\n  b_elf_word st_name;\n  unsigned char st_info;\n  unsigned char st_other;\n  b_elf_half st_shndx;\n  b_elf_addr st_value;\n  b_elf_xword st_size;\n} b_elf_sym;\n#endif\n#define STT_OBJECT 1\n#define STT_FUNC 2\n\ntypedef struct {\n  uint32_t namesz;\n  uint32_t descsz;\n  uint32_t type;\n  char name[1];\n} b_elf_note;\n\n#define NT_GNU_BUILD_ID 3\n\n#if BACKTRACE_ELF_SIZE == 32\n\ntypedef struct {\n  b_elf_word ch_type;\n  b_elf_word ch_size;\n  b_elf_word ch_addralign;\n} b_elf_chdr;\n#else\ntypedef struct {\n  b_elf_word ch_type;\n  b_elf_word ch_reserved;\n  b_elf_xword ch_size;\n  b_elf_xword ch_addralign;\n} b_elf_chdr;\n#endif\n#define ELFCOMPRESS_ZLIB 1\n\nstatic const char *const dwarf_section_names[DEBUG_MAX] = {\n    \".debug_info\",        \".debug_line\",     \".debug_abbrev\",\n    \".debug_ranges\",      \".debug_str\",      \".debug_addr\",\n    \".debug_str_offsets\", \".debug_line_str\", \".debug_rnglists\"};\n\nstruct debug_section_info {\n  off_t offset;\n\n  size_t size;\n\n  const unsigned char *data;\n\n  int compressed;\n};\n\nstruct elf_symbol {\n  const char *name;\n\n  uintptr_t address;\n\n  size_t size;\n};\n\nstruct elf_syminfo_data {\n  struct elf_syminfo_data *next;\n\n  struct elf_symbol *symbols;\n\n  size_t count;\n};\n\nstruct elf_view {\n  struct backtrace_view view;\n  int release;\n};\n\nstruct elf_ppc64_opd_data {\n  b_elf_addr addr;\n\n  const char *data;\n\n  size_t size;\n\n  struct elf_view view;\n};\n\nstatic int elf_get_view(struct backtrace_state *state, int descriptor,\n                        const unsigned char *memory, size_t memory_size,\n                        off_t offset, uint64_t size,\n                        backtrace_error_callback error_callback, void *data,\n                        struct elf_view *view) {\n  if (memory == NULL) {\n    view->release = 1;\n    return backtrace_get_view(state, descriptor, offset, size, error_callback,\n                              data, &view->view);\n  } else {\n    if ((uint64_t)offset + size > (uint64_t)memory_size) {\n      error_callback(data, \"out of range for in-memory file\", 0);\n      return 0;\n    }\n    view->view.data = (const void *)(memory + offset);\n    view->view.base = NULL;\n    view->view.len = size;\n    view->release = 0;\n    return 1;\n  }\n}\n\nstatic void elf_release_view(struct backtrace_state *state,\n                             struct elf_view *view,\n                             backtrace_error_callback error_callback,\n                             void *data) {\n  if (view->release)\n    backtrace_release_view(state, &view->view, error_callback, data);\n}\n\nstatic uint32_t elf_crc32(uint32_t crc, const unsigned char *buf, size_t len) {\n  static const uint32_t crc32_table[256] = {\n      0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,\n      0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,\n      0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,\n      0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,\n      0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,\n      0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,\n      0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,\n      0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,\n      0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,\n      0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,\n      0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,\n      0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,\n      0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,\n      0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,\n      0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,\n      0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,\n      0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,\n      0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,\n      0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,\n      0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\n      0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,\n      0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,\n      0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,\n      0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,\n      0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,\n      0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,\n      0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,\n      0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,\n      0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,\n      0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,\n      0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,\n      0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,\n      0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,\n      0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,\n      0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,\n      0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,\n      0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,\n      0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,\n      0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,\n      0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\n      0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,\n      0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,\n      0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};\n  const unsigned char *end;\n\n  crc = ~crc;\n  for (end = buf + len; buf < end; ++buf)\n    crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);\n  return ~crc;\n}\n\nstatic uint32_t elf_crc32_file(struct backtrace_state *state, int descriptor,\n                               backtrace_error_callback error_callback,\n                               void *data) {\n  struct stat st;\n  struct backtrace_view file_view;\n  uint32_t ret;\n\n  if (fstat(descriptor, &st) < 0) {\n    error_callback(data, \"fstat\", errno);\n    return 0;\n  }\n\n  if (!backtrace_get_view(state, descriptor, 0, st.st_size, error_callback,\n                          data, &file_view))\n    return 0;\n\n  ret = elf_crc32(0, (const unsigned char *)file_view.data, st.st_size);\n\n  backtrace_release_view(state, &file_view, error_callback, data);\n\n  return ret;\n}\n\nstatic void elf_nosyms(struct backtrace_state *state ATTRIBUTE_UNUSED,\n                       uintptr_t addr ATTRIBUTE_UNUSED,\n                       backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,\n                       backtrace_error_callback error_callback, void *data) {\n  error_callback(data, \"no symbol table in ELF executable\", -1);\n}\n\nstatic int elf_nodebug(struct backtrace_state *state, uintptr_t pc,\n                       backtrace_full_callback callback,\n                       backtrace_error_callback error_callback, void *data) {\n  if (state->syminfo_fn != NULL && state->syminfo_fn != elf_nosyms) {\n    struct backtrace_call_full bdata;\n\n    bdata.full_callback = callback;\n    bdata.full_error_callback = error_callback;\n    bdata.full_data = data;\n    bdata.ret = 0;\n    state->syminfo_fn(state, pc, backtrace_syminfo_to_full_callback,\n                      backtrace_syminfo_to_full_error_callback, &bdata);\n    return bdata.ret;\n  }\n\n  error_callback(data, \"no debug info in ELF executable\", -1);\n  return 0;\n}\n\nstatic int elf_symbol_compare(const void *v1, const void *v2) {\n  const struct elf_symbol *e1 = (const struct elf_symbol *)v1;\n  const struct elf_symbol *e2 = (const struct elf_symbol *)v2;\n\n  if (e1->address < e2->address)\n    return -1;\n  else if (e1->address > e2->address)\n    return 1;\n  else\n    return 0;\n}\n\nstatic int elf_symbol_search(const void *vkey, const void *ventry) {\n  const uintptr_t *key = (const uintptr_t *)vkey;\n  const struct elf_symbol *entry = (const struct elf_symbol *)ventry;\n  uintptr_t addr;\n\n  addr = *key;\n  if (addr < entry->address)\n    return -1;\n  else if (addr >= entry->address + entry->size)\n    return 1;\n  else\n    return 0;\n}\n\nstatic int elf_initialize_syminfo(\n    struct backtrace_state *state, uintptr_t base_address,\n    const unsigned char *symtab_data, size_t symtab_size,\n    const unsigned char *strtab, size_t strtab_size,\n    backtrace_error_callback error_callback, void *data,\n    struct elf_syminfo_data *sdata, struct elf_ppc64_opd_data *opd) {\n  size_t sym_count;\n  const b_elf_sym *sym;\n  size_t elf_symbol_count;\n  size_t elf_symbol_size;\n  struct elf_symbol *elf_symbols;\n  size_t i;\n  unsigned int j;\n\n  sym_count = symtab_size / sizeof(b_elf_sym);\n\n  sym = (const b_elf_sym *)symtab_data;\n  elf_symbol_count = 0;\n  for (i = 0; i < sym_count; ++i, ++sym) {\n    int info;\n\n    info = sym->st_info & 0xf;\n    if ((info == STT_FUNC || info == STT_OBJECT) && sym->st_shndx != SHN_UNDEF)\n      ++elf_symbol_count;\n  }\n\n  elf_symbol_size = elf_symbol_count * sizeof(struct elf_symbol);\n  elf_symbols = ((struct elf_symbol *)backtrace_alloc(state, elf_symbol_size,\n                                                      error_callback, data));\n  if (elf_symbols == NULL) return 0;\n\n  sym = (const b_elf_sym *)symtab_data;\n  j = 0;\n  for (i = 0; i < sym_count; ++i, ++sym) {\n    int info;\n\n    info = sym->st_info & 0xf;\n    if (info != STT_FUNC && info != STT_OBJECT) continue;\n    if (sym->st_shndx == SHN_UNDEF) continue;\n    if (sym->st_name >= strtab_size) {\n      error_callback(data, \"symbol string index out of range\", 0);\n      backtrace_free(state, elf_symbols, elf_symbol_size, error_callback, data);\n      return 0;\n    }\n    elf_symbols[j].name = (const char *)strtab + sym->st_name;\n\n    if (opd && sym->st_value >= opd->addr &&\n        sym->st_value < opd->addr + opd->size)\n      elf_symbols[j].address =\n          *(const b_elf_addr *)(opd->data + (sym->st_value - opd->addr));\n    else\n      elf_symbols[j].address = sym->st_value;\n    elf_symbols[j].address += base_address;\n    elf_symbols[j].size = sym->st_size;\n    ++j;\n  }\n\n  backtrace_qsort(elf_symbols, elf_symbol_count, sizeof(struct elf_symbol),\n                  elf_symbol_compare);\n\n  sdata->next = NULL;\n  sdata->symbols = elf_symbols;\n  sdata->count = elf_symbol_count;\n\n  return 1;\n}\n\nstatic void elf_add_syminfo_data(struct backtrace_state *state,\n                                 struct elf_syminfo_data *edata) {\n  if (!state->threaded) {\n    struct elf_syminfo_data **pp;\n\n    for (pp = (struct elf_syminfo_data **)(void *)&state->syminfo_data;\n         *pp != NULL; pp = &(*pp)->next)\n      ;\n    *pp = edata;\n  } else {\n    while (1) {\n      struct elf_syminfo_data **pp;\n\n      pp = (struct elf_syminfo_data **)(void *)&state->syminfo_data;\n\n      while (1) {\n        struct elf_syminfo_data *p;\n\n        p = backtrace_atomic_load_pointer(pp);\n\n        if (p == NULL) break;\n\n        pp = &p->next;\n      }\n\n      if (__sync_bool_compare_and_swap(pp, NULL, edata)) break;\n    }\n  }\n}\n\nstatic void elf_syminfo(\n    struct backtrace_state *state, uintptr_t addr,\n    backtrace_syminfo_callback callback,\n    backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data) {\n  struct elf_syminfo_data *edata;\n  struct elf_symbol *sym = NULL;\n\n  if (!state->threaded) {\n    for (edata = (struct elf_syminfo_data *)state->syminfo_data; edata != NULL;\n         edata = edata->next) {\n      sym = ((struct elf_symbol *)bsearch(&addr, edata->symbols, edata->count,\n                                          sizeof(struct elf_symbol),\n                                          elf_symbol_search));\n      if (sym != NULL) break;\n    }\n  } else {\n    struct elf_syminfo_data **pp;\n\n    pp = (struct elf_syminfo_data **)(void *)&state->syminfo_data;\n    while (1) {\n      edata = backtrace_atomic_load_pointer(pp);\n      if (edata == NULL) break;\n\n      sym = ((struct elf_symbol *)bsearch(&addr, edata->symbols, edata->count,\n                                          sizeof(struct elf_symbol),\n                                          elf_symbol_search));\n      if (sym != NULL) break;\n\n      pp = &edata->next;\n    }\n  }\n\n  if (sym == NULL)\n    callback(data, addr, NULL, 0, 0);\n  else\n    callback(data, addr, sym->name, sym->address, sym->size);\n}\n\nstatic int elf_is_symlink(const char *filename) {\n  struct stat st;\n\n  if (lstat(filename, &st) < 0) return 0;\n  return S_ISLNK(st.st_mode);\n}\n\nstatic char *elf_readlink(struct backtrace_state *state, const char *filename,\n                          backtrace_error_callback error_callback, void *data,\n                          size_t *plen) {\n  size_t len;\n  char *buf;\n\n  len = 128;\n  while (1) {\n    ssize_t rl;\n\n    buf = backtrace_alloc(state, len, error_callback, data);\n    if (buf == NULL) return NULL;\n    rl = readlink(filename, buf, len);\n    if (rl < 0) {\n      backtrace_free(state, buf, len, error_callback, data);\n      return NULL;\n    }\n    if ((size_t)rl < len - 1) {\n      buf[rl] = '\\0';\n      *plen = len;\n      return buf;\n    }\n    backtrace_free(state, buf, len, error_callback, data);\n    len *= 2;\n  }\n}\n\n#define SYSTEM_BUILD_ID_DIR \"/usr/lib/debug/.build-id/\"\n\nstatic int elf_open_debugfile_by_buildid(\n    struct backtrace_state *state, const char *buildid_data,\n    size_t buildid_size, backtrace_error_callback error_callback, void *data) {\n  const char *const prefix = SYSTEM_BUILD_ID_DIR;\n  const size_t prefix_len = strlen(prefix);\n  const char *const suffix = \".debug\";\n  const size_t suffix_len = strlen(suffix);\n  size_t len;\n  char *bd_filename;\n  char *t;\n  size_t i;\n  int ret;\n  int does_not_exist;\n\n  len = prefix_len + buildid_size * 2 + suffix_len + 2;\n  bd_filename = backtrace_alloc(state, len, error_callback, data);\n  if (bd_filename == NULL) return -1;\n\n  t = bd_filename;\n  memcpy(t, prefix, prefix_len);\n  t += prefix_len;\n  for (i = 0; i < buildid_size; i++) {\n    unsigned char b;\n    unsigned char nib;\n\n    b = (unsigned char)buildid_data[i];\n    nib = (b & 0xf0) >> 4;\n    *t++ = nib < 10 ? '0' + nib : 'a' + nib - 10;\n    nib = b & 0x0f;\n    *t++ = nib < 10 ? '0' + nib : 'a' + nib - 10;\n    if (i == 0) *t++ = '/';\n  }\n  memcpy(t, suffix, suffix_len);\n  t[suffix_len] = '\\0';\n\n  ret = backtrace_open(bd_filename, error_callback, data, &does_not_exist);\n\n  backtrace_free(state, bd_filename, len, error_callback, data);\n\n  return ret;\n}\n\nstatic int elf_try_debugfile(struct backtrace_state *state, const char *prefix,\n                             size_t prefix_len, const char *prefix2,\n                             size_t prefix2_len, const char *debuglink_name,\n                             backtrace_error_callback error_callback,\n                             void *data) {\n  size_t debuglink_len;\n  size_t try_len;\n  char *try;\n  int does_not_exist;\n  int ret;\n\n  debuglink_len = strlen(debuglink_name);\n  try_len = prefix_len + prefix2_len + debuglink_len + 1;\n  try = backtrace_alloc(state, try_len, error_callback, data);\n  if (try == NULL) return -1;\n\n  memcpy(try, prefix, prefix_len);\n  memcpy(try + prefix_len, prefix2, prefix2_len);\n  memcpy(try + prefix_len + prefix2_len, debuglink_name, debuglink_len);\n  try[prefix_len + prefix2_len + debuglink_len] = '\\0';\n\n  ret = backtrace_open(try, error_callback, data, &does_not_exist);\n\n  backtrace_free(state, try, try_len, error_callback, data);\n\n  return ret;\n}\n\nstatic int elf_find_debugfile_by_debuglink(\n    struct backtrace_state *state, const char *filename,\n    const char *debuglink_name, backtrace_error_callback error_callback,\n    void *data) {\n  int ret;\n  char *alc;\n  size_t alc_len;\n  const char *slash;\n  int ddescriptor;\n  const char *prefix;\n  size_t prefix_len;\n\n  ret = -1;\n  alc = NULL;\n  alc_len = 0;\n  while (elf_is_symlink(filename)) {\n    char *new_buf;\n    size_t new_len;\n\n    new_buf = elf_readlink(state, filename, error_callback, data, &new_len);\n    if (new_buf == NULL) break;\n\n    if (new_buf[0] == '/')\n      filename = new_buf;\n    else {\n      slash = strrchr(filename, '/');\n      if (slash == NULL)\n        filename = new_buf;\n      else {\n        size_t clen;\n        char *c;\n\n        slash++;\n        clen = slash - filename + strlen(new_buf) + 1;\n        c = backtrace_alloc(state, clen, error_callback, data);\n        if (c == NULL) goto done;\n\n        memcpy(c, filename, slash - filename);\n        memcpy(c + (slash - filename), new_buf, strlen(new_buf));\n        c[slash - filename + strlen(new_buf)] = '\\0';\n        backtrace_free(state, new_buf, new_len, error_callback, data);\n        filename = c;\n        new_buf = c;\n        new_len = clen;\n      }\n    }\n\n    if (alc != NULL) backtrace_free(state, alc, alc_len, error_callback, data);\n    alc = new_buf;\n    alc_len = new_len;\n  }\n\n  slash = strrchr(filename, '/');\n  if (slash == NULL) {\n    prefix = \"\";\n    prefix_len = 0;\n  } else {\n    slash++;\n    prefix = filename;\n    prefix_len = slash - filename;\n  }\n\n  ddescriptor = elf_try_debugfile(state, prefix, prefix_len, \"\", 0,\n                                  debuglink_name, error_callback, data);\n  if (ddescriptor >= 0) {\n    ret = ddescriptor;\n    goto done;\n  }\n\n  ddescriptor =\n      elf_try_debugfile(state, prefix, prefix_len, \".debug/\", strlen(\".debug/\"),\n                        debuglink_name, error_callback, data);\n  if (ddescriptor >= 0) {\n    ret = ddescriptor;\n    goto done;\n  }\n\n  ddescriptor = elf_try_debugfile(state, \"/usr/lib/debug/\",\n                                  strlen(\"/usr/lib/debug/\"), prefix, prefix_len,\n                                  debuglink_name, error_callback, data);\n  if (ddescriptor >= 0) ret = ddescriptor;\n\ndone:\n  if (alc != NULL && alc_len > 0)\n    backtrace_free(state, alc, alc_len, error_callback, data);\n  return ret;\n}\n\nstatic int elf_open_debugfile_by_debuglink(\n    struct backtrace_state *state, const char *filename,\n    const char *debuglink_name, uint32_t debuglink_crc,\n    backtrace_error_callback error_callback, void *data) {\n  int ddescriptor;\n\n  ddescriptor = elf_find_debugfile_by_debuglink(state, filename, debuglink_name,\n                                                error_callback, data);\n  if (ddescriptor < 0) return -1;\n\n  if (debuglink_crc != 0) {\n    uint32_t got_crc;\n\n    got_crc = elf_crc32_file(state, ddescriptor, error_callback, data);\n    if (got_crc != debuglink_crc) {\n      backtrace_close(ddescriptor, error_callback, data);\n      return -1;\n    }\n  }\n\n  return ddescriptor;\n}\n\nstatic void elf_uncompress_failed(void) {}\n\nstatic int elf_zlib_fetch(const unsigned char **ppin,\n                          const unsigned char *pinend, uint64_t *pval,\n                          unsigned int *pbits) {\n  unsigned int bits;\n  const unsigned char *pin;\n  uint64_t val;\n  uint32_t next;\n\n  bits = *pbits;\n  if (bits >= 15) return 1;\n  pin = *ppin;\n  val = *pval;\n\n  if (unlikely(pinend - pin < 4)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \\\n    defined(__ORDER_BIG_ENDIAN__) &&                               \\\n    (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ||                     \\\n     __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n\n  next = *(const uint32_t *)pin;\n\n#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n  next = __builtin_bswap32(next);\n#endif\n#else\n  next = pin[0] | (pin[1] << 8) | (pin[2] << 16) | (pin[3] << 24);\n#endif\n\n  val |= (uint64_t)next << bits;\n  bits += 32;\n  pin += 4;\n\n  __builtin_prefetch(pin, 0, 0);\n\n  *ppin = pin;\n  *pval = val;\n  *pbits = bits;\n  return 1;\n}\n\n#define HUFFMAN_TABLE_SIZE (1024)\n\n#define HUFFMAN_VALUE_MASK 0x01ff\n#define HUFFMAN_BITS_SHIFT 9\n#define HUFFMAN_BITS_MASK 0x7\n#define HUFFMAN_SECONDARY_SHIFT 12\n\n#define ZDEBUG_TABLE_SIZE                                                      \\\n  (2 * HUFFMAN_TABLE_SIZE * sizeof(uint16_t) + (286 + 30) * sizeof(uint16_t) + \\\n   (286 + 30) * sizeof(unsigned char))\n\n#define ZDEBUG_TABLE_CODELEN_OFFSET \\\n  (2 * HUFFMAN_TABLE_SIZE * sizeof(uint16_t) + (286 + 30) * sizeof(uint16_t))\n\n#define ZDEBUG_TABLE_WORK_OFFSET (2 * HUFFMAN_TABLE_SIZE * sizeof(uint16_t))\n\n#ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE\n\nstatic size_t final_next_secondary;\n\n#endif\n\nstatic int elf_zlib_inflate_table(unsigned char *codes, size_t codes_len,\n                                  uint16_t *zdebug_table, uint16_t *table) {\n  uint16_t count[16];\n  uint16_t start[16];\n  uint16_t prev[16];\n  uint16_t firstcode[7];\n  uint16_t *next;\n  size_t i;\n  size_t j;\n  unsigned int code;\n  size_t next_secondary;\n\n  next =\n      (uint16_t *)(((unsigned char *)zdebug_table) + ZDEBUG_TABLE_WORK_OFFSET);\n\n  memset(&count[0], 0, 16 * sizeof(uint16_t));\n  for (i = 0; i < codes_len; ++i) {\n    if (unlikely(codes[i] >= 16)) {\n      elf_uncompress_failed();\n      return 0;\n    }\n\n    if (count[codes[i]] == 0) {\n      start[codes[i]] = i;\n      prev[codes[i]] = i;\n    } else {\n      next[prev[codes[i]]] = i;\n      prev[codes[i]] = i;\n    }\n\n    ++count[codes[i]];\n  }\n\n  memset(table, 0, HUFFMAN_TABLE_SIZE * sizeof(uint16_t));\n\n  code = 0;\n  for (j = 1; j <= 8; ++j) {\n    unsigned int jcnt;\n    unsigned int val;\n\n    jcnt = count[j];\n    if (jcnt == 0) continue;\n\n    if (unlikely(jcnt > (1U << j))) {\n      elf_uncompress_failed();\n      return 0;\n    }\n\n    val = start[j];\n    for (i = 0; i < jcnt; ++i) {\n      uint16_t tval;\n      size_t ind;\n      unsigned int incr;\n\n      if (unlikely((val & ~HUFFMAN_VALUE_MASK) != 0)) {\n        elf_uncompress_failed();\n        return 0;\n      }\n\n      tval = val | ((j - 1) << HUFFMAN_BITS_SHIFT);\n\n      for (ind = code; ind < 0x100; ind += 1 << j) {\n        if (unlikely(table[ind] != 0)) {\n          elf_uncompress_failed();\n          return 0;\n        }\n        table[ind] = tval;\n      }\n\n      if (i + 1 < jcnt) val = next[val];\n\n      incr = 1U << (j - 1);\n      while ((code & incr) != 0) incr >>= 1;\n      if (incr == 0)\n        code = 0;\n      else {\n        code &= incr - 1;\n        code += incr;\n      }\n    }\n  }\n\n  for (j = 9; j < 16; j++) {\n    unsigned int jcnt;\n    unsigned int k;\n\n    jcnt = count[j];\n    if (jcnt == 0) continue;\n\n    firstcode[j - 9] = code;\n\n    for (k = 0; k < j; ++k) {\n      if ((jcnt & (1U << k)) != 0) {\n        unsigned int m;\n        unsigned int bit;\n\n        bit = 1U << (j - k - 1);\n        for (m = 0; m < j - k; ++m, bit >>= 1) {\n          if ((code & bit) == 0) {\n            code += bit;\n            break;\n          }\n          code &= ~bit;\n        }\n        jcnt &= ~(1U << k);\n      }\n    }\n    if (unlikely(jcnt != 0)) {\n      elf_uncompress_failed();\n      return 0;\n    }\n  }\n\n  next_secondary = 0;\n  for (j = 15; j >= 9; j--) {\n    unsigned int jcnt;\n    unsigned int val;\n    size_t primary;\n    size_t secondary;\n    size_t secondary_bits;\n    jcnt = count[j];\n    if (jcnt == 0) continue;\n\n    val = start[j];\n    code = firstcode[j - 9];\n    primary = 0x100;\n    secondary = 0;\n    secondary_bits = 0;\n    for (i = 0; i < jcnt; ++i) {\n      uint16_t tval;\n      size_t ind;\n      unsigned int incr;\n\n      if ((code & 0xff) != primary) {\n        uint16_t tprimary;\n\n        primary = code & 0xff;\n\n        tprimary = table[primary];\n        if (tprimary == 0) {\n          if (unlikely((next_secondary & HUFFMAN_VALUE_MASK) !=\n                       next_secondary)) {\n            elf_uncompress_failed();\n            return 0;\n          }\n\n          secondary = next_secondary;\n          secondary_bits = j - 8;\n          next_secondary += 1 << secondary_bits;\n          table[primary] = (secondary + ((j - 8) << HUFFMAN_BITS_SHIFT) +\n                            (1U << HUFFMAN_SECONDARY_SHIFT));\n        } else {\n          if (unlikely((tprimary & (1U << HUFFMAN_SECONDARY_SHIFT)) == 0)) {\n            elf_uncompress_failed();\n            return 0;\n          }\n          secondary = tprimary & HUFFMAN_VALUE_MASK;\n          secondary_bits =\n              ((tprimary >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK);\n          if (unlikely(secondary_bits < j - 8)) {\n            elf_uncompress_failed();\n            return 0;\n          }\n        }\n      }\n\n      tval = val | ((j - 8) << HUFFMAN_BITS_SHIFT);\n\n      for (ind = code >> 8; ind < (1U << secondary_bits);\n           ind += 1U << (j - 8)) {\n        if (unlikely(table[secondary + 0x100 + ind] != 0)) {\n          elf_uncompress_failed();\n          return 0;\n        }\n        table[secondary + 0x100 + ind] = tval;\n      }\n\n      if (i + 1 < jcnt) val = next[val];\n\n      incr = 1U << (j - 1);\n      while ((code & incr) != 0) incr >>= 1;\n      if (incr == 0)\n        code = 0;\n      else {\n        code &= incr - 1;\n        code += incr;\n      }\n    }\n  }\n\n#ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE\n  final_next_secondary = next_secondary;\n#endif\n\n  return 1;\n}\n\nstatic const uint16_t elf_zlib_default_table[0x170] = {\n    0xd00, 0xe50,  0xe10, 0xf18,  0xd10, 0xe70,  0xe30, 0x1230, 0xd08, 0xe60,\n    0xe20, 0x1210, 0xe00, 0xe80,  0xe40, 0x1250, 0xd04, 0xe58,  0xe18, 0x1200,\n    0xd14, 0xe78,  0xe38, 0x1240, 0xd0c, 0xe68,  0xe28, 0x1220, 0xe08, 0xe88,\n    0xe48, 0x1260, 0xd02, 0xe54,  0xe14, 0xf1c,  0xd12, 0xe74,  0xe34, 0x1238,\n    0xd0a, 0xe64,  0xe24, 0x1218, 0xe04, 0xe84,  0xe44, 0x1258, 0xd06, 0xe5c,\n    0xe1c, 0x1208, 0xd16, 0xe7c,  0xe3c, 0x1248, 0xd0e, 0xe6c,  0xe2c, 0x1228,\n    0xe0c, 0xe8c,  0xe4c, 0x1268, 0xd01, 0xe52,  0xe12, 0xf1a,  0xd11, 0xe72,\n    0xe32, 0x1234, 0xd09, 0xe62,  0xe22, 0x1214, 0xe02, 0xe82,  0xe42, 0x1254,\n    0xd05, 0xe5a,  0xe1a, 0x1204, 0xd15, 0xe7a,  0xe3a, 0x1244, 0xd0d, 0xe6a,\n    0xe2a, 0x1224, 0xe0a, 0xe8a,  0xe4a, 0x1264, 0xd03, 0xe56,  0xe16, 0xf1e,\n    0xd13, 0xe76,  0xe36, 0x123c, 0xd0b, 0xe66,  0xe26, 0x121c, 0xe06, 0xe86,\n    0xe46, 0x125c, 0xd07, 0xe5e,  0xe1e, 0x120c, 0xd17, 0xe7e,  0xe3e, 0x124c,\n    0xd0f, 0xe6e,  0xe2e, 0x122c, 0xe0e, 0xe8e,  0xe4e, 0x126c, 0xd00, 0xe51,\n    0xe11, 0xf19,  0xd10, 0xe71,  0xe31, 0x1232, 0xd08, 0xe61,  0xe21, 0x1212,\n    0xe01, 0xe81,  0xe41, 0x1252, 0xd04, 0xe59,  0xe19, 0x1202, 0xd14, 0xe79,\n    0xe39, 0x1242, 0xd0c, 0xe69,  0xe29, 0x1222, 0xe09, 0xe89,  0xe49, 0x1262,\n    0xd02, 0xe55,  0xe15, 0xf1d,  0xd12, 0xe75,  0xe35, 0x123a, 0xd0a, 0xe65,\n    0xe25, 0x121a, 0xe05, 0xe85,  0xe45, 0x125a, 0xd06, 0xe5d,  0xe1d, 0x120a,\n    0xd16, 0xe7d,  0xe3d, 0x124a, 0xd0e, 0xe6d,  0xe2d, 0x122a, 0xe0d, 0xe8d,\n    0xe4d, 0x126a, 0xd01, 0xe53,  0xe13, 0xf1b,  0xd11, 0xe73,  0xe33, 0x1236,\n    0xd09, 0xe63,  0xe23, 0x1216, 0xe03, 0xe83,  0xe43, 0x1256, 0xd05, 0xe5b,\n    0xe1b, 0x1206, 0xd15, 0xe7b,  0xe3b, 0x1246, 0xd0d, 0xe6b,  0xe2b, 0x1226,\n    0xe0b, 0xe8b,  0xe4b, 0x1266, 0xd03, 0xe57,  0xe17, 0xf1f,  0xd13, 0xe77,\n    0xe37, 0x123e, 0xd0b, 0xe67,  0xe27, 0x121e, 0xe07, 0xe87,  0xe47, 0x125e,\n    0xd07, 0xe5f,  0xe1f, 0x120e, 0xd17, 0xe7f,  0xe3f, 0x124e, 0xd0f, 0xe6f,\n    0xe2f, 0x122e, 0xe0f, 0xe8f,  0xe4f, 0x126e, 0x290, 0x291,  0x292, 0x293,\n    0x294, 0x295,  0x296, 0x297,  0x298, 0x299,  0x29a, 0x29b,  0x29c, 0x29d,\n    0x29e, 0x29f,  0x2a0, 0x2a1,  0x2a2, 0x2a3,  0x2a4, 0x2a5,  0x2a6, 0x2a7,\n    0x2a8, 0x2a9,  0x2aa, 0x2ab,  0x2ac, 0x2ad,  0x2ae, 0x2af,  0x2b0, 0x2b1,\n    0x2b2, 0x2b3,  0x2b4, 0x2b5,  0x2b6, 0x2b7,  0x2b8, 0x2b9,  0x2ba, 0x2bb,\n    0x2bc, 0x2bd,  0x2be, 0x2bf,  0x2c0, 0x2c1,  0x2c2, 0x2c3,  0x2c4, 0x2c5,\n    0x2c6, 0x2c7,  0x2c8, 0x2c9,  0x2ca, 0x2cb,  0x2cc, 0x2cd,  0x2ce, 0x2cf,\n    0x2d0, 0x2d1,  0x2d2, 0x2d3,  0x2d4, 0x2d5,  0x2d6, 0x2d7,  0x2d8, 0x2d9,\n    0x2da, 0x2db,  0x2dc, 0x2dd,  0x2de, 0x2df,  0x2e0, 0x2e1,  0x2e2, 0x2e3,\n    0x2e4, 0x2e5,  0x2e6, 0x2e7,  0x2e8, 0x2e9,  0x2ea, 0x2eb,  0x2ec, 0x2ed,\n    0x2ee, 0x2ef,  0x2f0, 0x2f1,  0x2f2, 0x2f3,  0x2f4, 0x2f5,  0x2f6, 0x2f7,\n    0x2f8, 0x2f9,  0x2fa, 0x2fb,  0x2fc, 0x2fd,  0x2fe, 0x2ff,\n};\n\nstatic const uint16_t elf_zlib_default_dist_table[0x100] = {\n    0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c, 0x802, 0x812, 0x80a,\n    0x81a, 0x806, 0x816, 0x80e, 0x81e, 0x801, 0x811, 0x809, 0x819, 0x805, 0x815,\n    0x80d, 0x81d, 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, 0x800,\n    0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c, 0x802, 0x812, 0x80a, 0x81a,\n    0x806, 0x816, 0x80e, 0x81e, 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d,\n    0x81d, 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, 0x800, 0x810,\n    0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c, 0x802, 0x812, 0x80a, 0x81a, 0x806,\n    0x816, 0x80e, 0x81e, 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,\n    0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, 0x800, 0x810, 0x808,\n    0x818, 0x804, 0x814, 0x80c, 0x81c, 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816,\n    0x80e, 0x81e, 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, 0x803,\n    0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, 0x800, 0x810, 0x808, 0x818,\n    0x804, 0x814, 0x80c, 0x81c, 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e,\n    0x81e, 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, 0x803, 0x813,\n    0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, 0x800, 0x810, 0x808, 0x818, 0x804,\n    0x814, 0x80c, 0x81c, 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,\n    0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, 0x803, 0x813, 0x80b,\n    0x81b, 0x807, 0x817, 0x80f, 0x81f, 0x800, 0x810, 0x808, 0x818, 0x804, 0x814,\n    0x80c, 0x81c, 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e, 0x801,\n    0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, 0x803, 0x813, 0x80b, 0x81b,\n    0x807, 0x817, 0x80f, 0x81f, 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c,\n    0x81c, 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e, 0x801, 0x811,\n    0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, 0x803, 0x813, 0x80b, 0x81b, 0x807,\n    0x817, 0x80f, 0x81f,\n};\n\nstatic int elf_zlib_inflate(const unsigned char *pin, size_t sin,\n                            uint16_t *zdebug_table, unsigned char *pout,\n                            size_t sout) {\n  unsigned char *porigout;\n  const unsigned char *pinend;\n  unsigned char *poutend;\n\n  porigout = pout;\n  pinend = pin + sin;\n  poutend = pout + sout;\n  while ((pinend - pin) > 4) {\n    uint64_t val;\n    unsigned int bits;\n    int last;\n\n    if (unlikely((pin[0] & 0xf) != 8)) {\n      elf_uncompress_failed();\n      return 0;\n    }\n    if (unlikely((pin[0] >> 4) > 7)) {\n      elf_uncompress_failed();\n      return 0;\n    }\n    if (unlikely((pin[1] & 0x20) != 0)) {\n      elf_uncompress_failed();\n      return 0;\n    }\n    val = (pin[0] << 8) | pin[1];\n    if (unlikely(val % 31 != 0)) {\n      elf_uncompress_failed();\n      return 0;\n    }\n    pin += 2;\n\n    val = 0;\n    bits = 0;\n    while ((((uintptr_t)pin) & 3) != 0) {\n      val |= (uint64_t)*pin << bits;\n      bits += 8;\n      ++pin;\n    }\n\n    last = 0;\n\n    while (!last) {\n      unsigned int type;\n      const uint16_t *tlit;\n      const uint16_t *tdist;\n\n      if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0;\n\n      last = val & 1;\n      type = (val >> 1) & 3;\n      val >>= 3;\n      bits -= 3;\n\n      if (unlikely(type == 3)) {\n        elf_uncompress_failed();\n        return 0;\n      }\n\n      if (type == 0) {\n        uint16_t len;\n        uint16_t lenc;\n\n        while (bits >= 8) {\n          --pin;\n          bits -= 8;\n        }\n\n        val = 0;\n        bits = 0;\n        if (unlikely((pinend - pin) < 4)) {\n          elf_uncompress_failed();\n          return 0;\n        }\n        len = pin[0] | (pin[1] << 8);\n        lenc = pin[2] | (pin[3] << 8);\n        pin += 4;\n        lenc = ~lenc;\n        if (unlikely(len != lenc)) {\n          elf_uncompress_failed();\n          return 0;\n        }\n        if (unlikely(len > (unsigned int)(pinend - pin) ||\n                     len > (unsigned int)(poutend - pout))) {\n          elf_uncompress_failed();\n          return 0;\n        }\n        memcpy(pout, pin, len);\n        pout += len;\n        pin += len;\n\n        while ((((uintptr_t)pin) & 3) != 0) {\n          val |= (uint64_t)*pin << bits;\n          bits += 8;\n          ++pin;\n        }\n\n        continue;\n      }\n\n      if (type == 1) {\n        tlit = elf_zlib_default_table;\n        tdist = elf_zlib_default_dist_table;\n      } else {\n        unsigned int nlit;\n        unsigned int ndist;\n        unsigned int nclen;\n        unsigned char codebits[19];\n        unsigned char *plenbase;\n        unsigned char *plen;\n        unsigned char *plenend;\n\n        if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0;\n\n        nlit = (val & 0x1f) + 257;\n        val >>= 5;\n        ndist = (val & 0x1f) + 1;\n        val >>= 5;\n        nclen = (val & 0xf) + 4;\n        val >>= 4;\n        bits -= 14;\n        if (unlikely(nlit > 286 || ndist > 30)) {\n          elf_uncompress_failed();\n          return 0;\n        }\n\n        memset(&codebits[0], 0, 19);\n\n        if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0;\n\n        codebits[16] = val & 7;\n        codebits[17] = (val >> 3) & 7;\n        codebits[18] = (val >> 6) & 7;\n        codebits[0] = (val >> 9) & 7;\n        val >>= 12;\n        bits -= 12;\n\n        if (nclen == 4) goto codebitsdone;\n\n        codebits[8] = val & 7;\n        val >>= 3;\n        bits -= 3;\n\n        if (nclen == 5) goto codebitsdone;\n\n        if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0;\n\n        codebits[7] = val & 7;\n        val >>= 3;\n        bits -= 3;\n\n        if (nclen == 6) goto codebitsdone;\n\n        codebits[9] = val & 7;\n        val >>= 3;\n        bits -= 3;\n\n        if (nclen == 7) goto codebitsdone;\n\n        codebits[6] = val & 7;\n        val >>= 3;\n        bits -= 3;\n\n        if (nclen == 8) goto codebitsdone;\n\n        codebits[10] = val & 7;\n        val >>= 3;\n        bits -= 3;\n\n        if (nclen == 9) goto codebitsdone;\n\n        codebits[5] = val & 7;\n        val >>= 3;\n        bits -= 3;\n\n        if (nclen == 10) goto codebitsdone;\n\n        if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0;\n\n        codebits[11] = val & 7;\n        val >>= 3;\n        bits -= 3;\n\n        if (nclen == 11) goto codebitsdone;\n\n        codebits[4] = val & 7;\n        val >>= 3;\n        bits -= 3;\n\n        if (nclen == 12) goto codebitsdone;\n\n        codebits[12] = val & 7;\n        val >>= 3;\n        bits -= 3;\n\n        if (nclen == 13) goto codebitsdone;\n\n        codebits[3] = val & 7;\n        val >>= 3;\n        bits -= 3;\n\n        if (nclen == 14) goto codebitsdone;\n\n        codebits[13] = val & 7;\n        val >>= 3;\n        bits -= 3;\n\n        if (nclen == 15) goto codebitsdone;\n\n        if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0;\n\n        codebits[2] = val & 7;\n        val >>= 3;\n        bits -= 3;\n\n        if (nclen == 16) goto codebitsdone;\n\n        codebits[14] = val & 7;\n        val >>= 3;\n        bits -= 3;\n\n        if (nclen == 17) goto codebitsdone;\n\n        codebits[1] = val & 7;\n        val >>= 3;\n        bits -= 3;\n\n        if (nclen == 18) goto codebitsdone;\n\n        codebits[15] = val & 7;\n        val >>= 3;\n        bits -= 3;\n\n      codebitsdone:\n\n        if (!elf_zlib_inflate_table(codebits, 19, zdebug_table, zdebug_table))\n          return 0;\n\n        plenbase =\n            (((unsigned char *)zdebug_table) + ZDEBUG_TABLE_CODELEN_OFFSET);\n        plen = plenbase;\n        plenend = plen + nlit + ndist;\n        while (plen < plenend) {\n          uint16_t t;\n          unsigned int b;\n          uint16_t v;\n\n          if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0;\n\n          t = zdebug_table[val & 0xff];\n\n          if (unlikely((t & (1U << HUFFMAN_SECONDARY_SHIFT)) != 0)) {\n            elf_uncompress_failed();\n            return 0;\n          }\n\n          b = (t >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK;\n          val >>= b + 1;\n          bits -= b + 1;\n\n          v = t & HUFFMAN_VALUE_MASK;\n          if (v < 16)\n            *plen++ = v;\n          else if (v == 16) {\n            unsigned int c;\n            unsigned int prev;\n\n            if (unlikely(plen == plenbase)) {\n              elf_uncompress_failed();\n              return 0;\n            }\n\n            c = 3 + (val & 0x3);\n            val >>= 2;\n            bits -= 2;\n            if (unlikely((unsigned int)(plenend - plen) < c)) {\n              elf_uncompress_failed();\n              return 0;\n            }\n\n            prev = plen[-1];\n            switch (c) {\n              case 6:\n                *plen++ = prev;\n                ATTRIBUTE_FALLTHROUGH;\n              case 5:\n                *plen++ = prev;\n                ATTRIBUTE_FALLTHROUGH;\n              case 4:\n                *plen++ = prev;\n            }\n            *plen++ = prev;\n            *plen++ = prev;\n            *plen++ = prev;\n          } else if (v == 17) {\n            unsigned int c;\n\n            c = 3 + (val & 0x7);\n            val >>= 3;\n            bits -= 3;\n            if (unlikely((unsigned int)(plenend - plen) < c)) {\n              elf_uncompress_failed();\n              return 0;\n            }\n\n            switch (c) {\n              case 10:\n                *plen++ = 0;\n                ATTRIBUTE_FALLTHROUGH;\n              case 9:\n                *plen++ = 0;\n                ATTRIBUTE_FALLTHROUGH;\n              case 8:\n                *plen++ = 0;\n                ATTRIBUTE_FALLTHROUGH;\n              case 7:\n                *plen++ = 0;\n                ATTRIBUTE_FALLTHROUGH;\n              case 6:\n                *plen++ = 0;\n                ATTRIBUTE_FALLTHROUGH;\n              case 5:\n                *plen++ = 0;\n                ATTRIBUTE_FALLTHROUGH;\n              case 4:\n                *plen++ = 0;\n            }\n            *plen++ = 0;\n            *plen++ = 0;\n            *plen++ = 0;\n          } else if (v == 18) {\n            unsigned int c;\n\n            c = 11 + (val & 0x7f);\n            val >>= 7;\n            bits -= 7;\n            if (unlikely((unsigned int)(plenend - plen) < c)) {\n              elf_uncompress_failed();\n              return 0;\n            }\n\n            memset(plen, 0, c);\n            plen += c;\n          } else {\n            elf_uncompress_failed();\n            return 0;\n          }\n        }\n\n        plen = plenbase;\n        if (unlikely(plen[256] == 0)) {\n          elf_uncompress_failed();\n          return 0;\n        }\n\n        if (!elf_zlib_inflate_table(plen, nlit, zdebug_table, zdebug_table))\n          return 0;\n        if (!elf_zlib_inflate_table(plen + nlit, ndist, zdebug_table,\n                                    zdebug_table + HUFFMAN_TABLE_SIZE))\n          return 0;\n        tlit = zdebug_table;\n        tdist = zdebug_table + HUFFMAN_TABLE_SIZE;\n      }\n\n      while (1) {\n        uint16_t t;\n        unsigned int b;\n        uint16_t v;\n        unsigned int lit;\n\n        if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0;\n\n        t = tlit[val & 0xff];\n        b = (t >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK;\n        v = t & HUFFMAN_VALUE_MASK;\n\n        if ((t & (1U << HUFFMAN_SECONDARY_SHIFT)) == 0) {\n          lit = v;\n          val >>= b + 1;\n          bits -= b + 1;\n        } else {\n          t = tlit[v + 0x100 + ((val >> 8) & ((1U << b) - 1))];\n          b = (t >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK;\n          lit = t & HUFFMAN_VALUE_MASK;\n          val >>= b + 8;\n          bits -= b + 8;\n        }\n\n        if (lit < 256) {\n          if (unlikely(pout == poutend)) {\n            elf_uncompress_failed();\n            return 0;\n          }\n\n          *pout++ = lit;\n\n          __builtin_prefetch(pout, 1, 3);\n        } else if (lit == 256) {\n          break;\n        } else {\n          unsigned int dist;\n          unsigned int len;\n\n          if (lit < 265)\n            len = lit - 257 + 3;\n          else if (lit == 285)\n            len = 258;\n          else if (unlikely(lit > 285)) {\n            elf_uncompress_failed();\n            return 0;\n          } else {\n            unsigned int extra;\n\n            if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0;\n\n            lit -= 265;\n            extra = (lit >> 2) + 1;\n            len = (lit & 3) << extra;\n            len += 11;\n            len += ((1U << (extra - 1)) - 1) << 3;\n            len += val & ((1U << extra) - 1);\n            val >>= extra;\n            bits -= extra;\n          }\n\n          if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0;\n\n          t = tdist[val & 0xff];\n          b = (t >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK;\n          v = t & HUFFMAN_VALUE_MASK;\n\n          if ((t & (1U << HUFFMAN_SECONDARY_SHIFT)) == 0) {\n            dist = v;\n            val >>= b + 1;\n            bits -= b + 1;\n          } else {\n            t = tdist[v + 0x100 + ((val >> 8) & ((1U << b) - 1))];\n            b = (t >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK;\n            dist = t & HUFFMAN_VALUE_MASK;\n            val >>= b + 8;\n            bits -= b + 8;\n          }\n\n          if (dist == 0) {\n            if (unlikely(pout == porigout)) {\n              elf_uncompress_failed();\n              return 0;\n            }\n\n            if (unlikely((unsigned int)(poutend - pout) < len)) {\n              elf_uncompress_failed();\n              return 0;\n            }\n\n            memset(pout, pout[-1], len);\n            pout += len;\n          } else if (unlikely(dist > 29)) {\n            elf_uncompress_failed();\n            return 0;\n          } else {\n            if (dist < 4)\n              dist = dist + 1;\n            else {\n              unsigned int extra;\n\n              if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0;\n\n              dist -= 4;\n              extra = (dist >> 1) + 1;\n              dist = (dist & 1) << extra;\n              dist += 5;\n              dist += ((1U << (extra - 1)) - 1) << 2;\n              dist += val & ((1U << extra) - 1);\n              val >>= extra;\n              bits -= extra;\n            }\n\n            if (unlikely((unsigned int)(pout - porigout) < dist)) {\n              elf_uncompress_failed();\n              return 0;\n            }\n\n            if (unlikely((unsigned int)(poutend - pout) < len)) {\n              elf_uncompress_failed();\n              return 0;\n            }\n\n            if (dist >= len) {\n              memcpy(pout, pout - dist, len);\n              pout += len;\n            } else {\n              while (len > 0) {\n                unsigned int copy;\n\n                copy = len < dist ? len : dist;\n                memcpy(pout, pout - dist, copy);\n                len -= copy;\n                pout += copy;\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n\n  if (unlikely(pout != poutend)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  return 1;\n}\n\nstatic int elf_zlib_verify_checksum(const unsigned char *checkbytes,\n                                    const unsigned char *uncompressed,\n                                    size_t uncompressed_size) {\n  unsigned int i;\n  unsigned int cksum;\n  const unsigned char *p;\n  uint32_t s1;\n  uint32_t s2;\n  size_t hsz;\n\n  cksum = 0;\n  for (i = 0; i < 4; i++) cksum = (cksum << 8) | checkbytes[i];\n\n  s1 = 1;\n  s2 = 0;\n\n  p = uncompressed;\n  hsz = uncompressed_size;\n  while (hsz >= 5552) {\n    for (i = 0; i < 5552; i += 16) {\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n    }\n    hsz -= 5552;\n    s1 %= 65521;\n    s2 %= 65521;\n  }\n\n  while (hsz >= 16) {\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n\n    hsz -= 16;\n  }\n\n  for (i = 0; i < hsz; ++i) {\n    s1 = s1 + *p++;\n    s2 = s2 + s1;\n  }\n\n  s1 %= 65521;\n  s2 %= 65521;\n\n  if (unlikely((s2 << 16) + s1 != cksum)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  return 1;\n}\n\nstatic int elf_zlib_inflate_and_verify(const unsigned char *pin, size_t sin,\n                                       uint16_t *zdebug_table,\n                                       unsigned char *pout, size_t sout) {\n  if (!elf_zlib_inflate(pin, sin, zdebug_table, pout, sout)) return 0;\n  if (!elf_zlib_verify_checksum(pin + sin - 4, pout, sout)) return 0;\n  return 1;\n}\n\nstatic int elf_uncompress_zdebug(struct backtrace_state *state,\n                                 const unsigned char *compressed,\n                                 size_t compressed_size, uint16_t *zdebug_table,\n                                 backtrace_error_callback error_callback,\n                                 void *data, unsigned char **uncompressed,\n                                 size_t *uncompressed_size) {\n  size_t sz;\n  size_t i;\n  unsigned char *po;\n\n  *uncompressed = NULL;\n  *uncompressed_size = 0;\n\n  if (compressed_size < 12 || memcmp(compressed, \"ZLIB\", 4) != 0) return 1;\n\n  sz = 0;\n  for (i = 0; i < 8; i++) sz = (sz << 8) | compressed[i + 4];\n\n  if (*uncompressed != NULL && *uncompressed_size >= sz)\n    po = *uncompressed;\n  else {\n    po = (unsigned char *)backtrace_alloc(state, sz, error_callback, data);\n    if (po == NULL) return 0;\n  }\n\n  if (!elf_zlib_inflate_and_verify(compressed + 12, compressed_size - 12,\n                                   zdebug_table, po, sz))\n    return 1;\n\n  *uncompressed = po;\n  *uncompressed_size = sz;\n\n  return 1;\n}\n\nstatic int elf_uncompress_chdr(struct backtrace_state *state,\n                               const unsigned char *compressed,\n                               size_t compressed_size, uint16_t *zdebug_table,\n                               backtrace_error_callback error_callback,\n                               void *data, unsigned char **uncompressed,\n                               size_t *uncompressed_size) {\n  const b_elf_chdr *chdr;\n  unsigned char *po;\n\n  *uncompressed = NULL;\n  *uncompressed_size = 0;\n\n  if (compressed_size < sizeof(b_elf_chdr)) return 1;\n\n  chdr = (const b_elf_chdr *)compressed;\n\n  if (chdr->ch_type != ELFCOMPRESS_ZLIB) {\n    return 1;\n  }\n\n  if (*uncompressed != NULL && *uncompressed_size >= chdr->ch_size)\n    po = *uncompressed;\n  else {\n    po = (unsigned char *)backtrace_alloc(state, chdr->ch_size, error_callback,\n                                          data);\n    if (po == NULL) return 0;\n  }\n\n  if (!elf_zlib_inflate_and_verify(compressed + sizeof(b_elf_chdr),\n                                   compressed_size - sizeof(b_elf_chdr),\n                                   zdebug_table, po, chdr->ch_size))\n    return 1;\n\n  *uncompressed = po;\n  *uncompressed_size = chdr->ch_size;\n\n  return 1;\n}\n\nint backtrace_uncompress_zdebug(struct backtrace_state *state,\n                                const unsigned char *compressed,\n                                size_t compressed_size,\n                                backtrace_error_callback error_callback,\n                                void *data, unsigned char **uncompressed,\n                                size_t *uncompressed_size) {\n  uint16_t *zdebug_table;\n  int ret;\n\n  zdebug_table = ((uint16_t *)backtrace_alloc(state, ZDEBUG_TABLE_SIZE,\n                                              error_callback, data));\n  if (zdebug_table == NULL) return 0;\n  ret = elf_uncompress_zdebug(state, compressed, compressed_size, zdebug_table,\n                              error_callback, data, uncompressed,\n                              uncompressed_size);\n  backtrace_free(state, zdebug_table, ZDEBUG_TABLE_SIZE, error_callback, data);\n  return ret;\n}\n\n#define LZMA_STATES (12)\n\n#define LZMA_POS_STATES (16)\n\n#define LZMA_DIST_STATES (4)\n\n#define LZMA_DIST_SLOTS (64)\n\n#define LZMA_DIST_MODEL_START (4)\n\n#define LZMA_DIST_MODEL_END (14)\n\n#define LZMA_FULL_DISTANCES (128)\n\n#define LZMA_ALIGN_SIZE (16)\n\n#define LZMA_LEN_LOW_SYMBOLS (8)\n#define LZMA_LEN_MID_SYMBOLS (8)\n#define LZMA_LEN_HIGH_SYMBOLS (256)\n\n#define LZMA_LITERAL_CODERS_MAX (16)\n#define LZMA_LITERAL_CODER_SIZE (0x300)\n\n#define LZMA_PROB_IS_MATCH_LEN (LZMA_STATES * LZMA_POS_STATES)\n#define LZMA_PROB_IS_REP_LEN LZMA_STATES\n#define LZMA_PROB_IS_REP0_LEN LZMA_STATES\n#define LZMA_PROB_IS_REP1_LEN LZMA_STATES\n#define LZMA_PROB_IS_REP2_LEN LZMA_STATES\n#define LZMA_PROB_IS_REP0_LONG_LEN (LZMA_STATES * LZMA_POS_STATES)\n#define LZMA_PROB_DIST_SLOT_LEN (LZMA_DIST_STATES * LZMA_DIST_SLOTS)\n#define LZMA_PROB_DIST_SPECIAL_LEN (LZMA_FULL_DISTANCES - LZMA_DIST_MODEL_END)\n#define LZMA_PROB_DIST_ALIGN_LEN LZMA_ALIGN_SIZE\n#define LZMA_PROB_MATCH_LEN_CHOICE_LEN 1\n#define LZMA_PROB_MATCH_LEN_CHOICE2_LEN 1\n#define LZMA_PROB_MATCH_LEN_LOW_LEN (LZMA_POS_STATES * LZMA_LEN_LOW_SYMBOLS)\n#define LZMA_PROB_MATCH_LEN_MID_LEN (LZMA_POS_STATES * LZMA_LEN_MID_SYMBOLS)\n#define LZMA_PROB_MATCH_LEN_HIGH_LEN LZMA_LEN_HIGH_SYMBOLS\n#define LZMA_PROB_REP_LEN_CHOICE_LEN 1\n#define LZMA_PROB_REP_LEN_CHOICE2_LEN 1\n#define LZMA_PROB_REP_LEN_LOW_LEN (LZMA_POS_STATES * LZMA_LEN_LOW_SYMBOLS)\n#define LZMA_PROB_REP_LEN_MID_LEN (LZMA_POS_STATES * LZMA_LEN_MID_SYMBOLS)\n#define LZMA_PROB_REP_LEN_HIGH_LEN LZMA_LEN_HIGH_SYMBOLS\n#define LZMA_PROB_LITERAL_LEN \\\n  (LZMA_LITERAL_CODERS_MAX * LZMA_LITERAL_CODER_SIZE)\n\n#define LZMA_PROB_IS_MATCH_OFFSET 0\n#define LZMA_PROB_IS_REP_OFFSET \\\n  (LZMA_PROB_IS_MATCH_OFFSET + LZMA_PROB_IS_MATCH_LEN)\n#define LZMA_PROB_IS_REP0_OFFSET \\\n  (LZMA_PROB_IS_REP_OFFSET + LZMA_PROB_IS_REP_LEN)\n#define LZMA_PROB_IS_REP1_OFFSET \\\n  (LZMA_PROB_IS_REP0_OFFSET + LZMA_PROB_IS_REP0_LEN)\n#define LZMA_PROB_IS_REP2_OFFSET \\\n  (LZMA_PROB_IS_REP1_OFFSET + LZMA_PROB_IS_REP1_LEN)\n#define LZMA_PROB_IS_REP0_LONG_OFFSET \\\n  (LZMA_PROB_IS_REP2_OFFSET + LZMA_PROB_IS_REP2_LEN)\n#define LZMA_PROB_DIST_SLOT_OFFSET \\\n  (LZMA_PROB_IS_REP0_LONG_OFFSET + LZMA_PROB_IS_REP0_LONG_LEN)\n#define LZMA_PROB_DIST_SPECIAL_OFFSET \\\n  (LZMA_PROB_DIST_SLOT_OFFSET + LZMA_PROB_DIST_SLOT_LEN)\n#define LZMA_PROB_DIST_ALIGN_OFFSET \\\n  (LZMA_PROB_DIST_SPECIAL_OFFSET + LZMA_PROB_DIST_SPECIAL_LEN)\n#define LZMA_PROB_MATCH_LEN_CHOICE_OFFSET \\\n  (LZMA_PROB_DIST_ALIGN_OFFSET + LZMA_PROB_DIST_ALIGN_LEN)\n#define LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET \\\n  (LZMA_PROB_MATCH_LEN_CHOICE_OFFSET + LZMA_PROB_MATCH_LEN_CHOICE_LEN)\n#define LZMA_PROB_MATCH_LEN_LOW_OFFSET \\\n  (LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET + LZMA_PROB_MATCH_LEN_CHOICE2_LEN)\n#define LZMA_PROB_MATCH_LEN_MID_OFFSET \\\n  (LZMA_PROB_MATCH_LEN_LOW_OFFSET + LZMA_PROB_MATCH_LEN_LOW_LEN)\n#define LZMA_PROB_MATCH_LEN_HIGH_OFFSET \\\n  (LZMA_PROB_MATCH_LEN_MID_OFFSET + LZMA_PROB_MATCH_LEN_MID_LEN)\n#define LZMA_PROB_REP_LEN_CHOICE_OFFSET \\\n  (LZMA_PROB_MATCH_LEN_HIGH_OFFSET + LZMA_PROB_MATCH_LEN_HIGH_LEN)\n#define LZMA_PROB_REP_LEN_CHOICE2_OFFSET \\\n  (LZMA_PROB_REP_LEN_CHOICE_OFFSET + LZMA_PROB_REP_LEN_CHOICE_LEN)\n#define LZMA_PROB_REP_LEN_LOW_OFFSET \\\n  (LZMA_PROB_REP_LEN_CHOICE2_OFFSET + LZMA_PROB_REP_LEN_CHOICE2_LEN)\n#define LZMA_PROB_REP_LEN_MID_OFFSET \\\n  (LZMA_PROB_REP_LEN_LOW_OFFSET + LZMA_PROB_REP_LEN_LOW_LEN)\n#define LZMA_PROB_REP_LEN_HIGH_OFFSET \\\n  (LZMA_PROB_REP_LEN_MID_OFFSET + LZMA_PROB_REP_LEN_MID_LEN)\n#define LZMA_PROB_LITERAL_OFFSET \\\n  (LZMA_PROB_REP_LEN_HIGH_OFFSET + LZMA_PROB_REP_LEN_HIGH_LEN)\n\n#define LZMA_PROB_TOTAL_COUNT (LZMA_PROB_LITERAL_OFFSET + LZMA_PROB_LITERAL_LEN)\n\n#if LZMA_PROB_TOTAL_COUNT != 1846 + (1 << 4) * 0x300\n#error Wrong number of LZMA probabilities\n#endif\n\n#define LZMA_IS_MATCH(state, pos) \\\n  (LZMA_PROB_IS_MATCH_OFFSET + (state)*LZMA_POS_STATES + (pos))\n#define LZMA_IS_REP(state) (LZMA_PROB_IS_REP_OFFSET + (state))\n#define LZMA_IS_REP0(state) (LZMA_PROB_IS_REP0_OFFSET + (state))\n#define LZMA_IS_REP1(state) (LZMA_PROB_IS_REP1_OFFSET + (state))\n#define LZMA_IS_REP2(state) (LZMA_PROB_IS_REP2_OFFSET + (state))\n#define LZMA_IS_REP0_LONG(state, pos) \\\n  (LZMA_PROB_IS_REP0_LONG_OFFSET + (state)*LZMA_POS_STATES + (pos))\n#define LZMA_DIST_SLOT(dist, slot) \\\n  (LZMA_PROB_DIST_SLOT_OFFSET + (dist)*LZMA_DIST_SLOTS + (slot))\n#define LZMA_DIST_SPECIAL(dist) (LZMA_PROB_DIST_SPECIAL_OFFSET + (dist))\n#define LZMA_DIST_ALIGN(dist) (LZMA_PROB_DIST_ALIGN_OFFSET + (dist))\n#define LZMA_MATCH_LEN_CHOICE LZMA_PROB_MATCH_LEN_CHOICE_OFFSET\n#define LZMA_MATCH_LEN_CHOICE2 LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET\n#define LZMA_MATCH_LEN_LOW(pos, sym) \\\n  (LZMA_PROB_MATCH_LEN_LOW_OFFSET + (pos)*LZMA_LEN_LOW_SYMBOLS + (sym))\n#define LZMA_MATCH_LEN_MID(pos, sym) \\\n  (LZMA_PROB_MATCH_LEN_MID_OFFSET + (pos)*LZMA_LEN_MID_SYMBOLS + (sym))\n#define LZMA_MATCH_LEN_HIGH(sym) (LZMA_PROB_MATCH_LEN_HIGH_OFFSET + (sym))\n#define LZMA_REP_LEN_CHOICE LZMA_PROB_REP_LEN_CHOICE_OFFSET\n#define LZMA_REP_LEN_CHOICE2 LZMA_PROB_REP_LEN_CHOICE2_OFFSET\n#define LZMA_REP_LEN_LOW(pos, sym) \\\n  (LZMA_PROB_REP_LEN_LOW_OFFSET + (pos)*LZMA_LEN_LOW_SYMBOLS + (sym))\n#define LZMA_REP_LEN_MID(pos, sym) \\\n  (LZMA_PROB_REP_LEN_MID_OFFSET + (pos)*LZMA_LEN_MID_SYMBOLS + (sym))\n#define LZMA_REP_LEN_HIGH(sym) (LZMA_PROB_REP_LEN_HIGH_OFFSET + (sym))\n#define LZMA_LITERAL(code, size) \\\n  (LZMA_PROB_LITERAL_OFFSET + (code)*LZMA_LITERAL_CODER_SIZE + (size))\n\nstatic int elf_lzma_varint(const unsigned char *compressed,\n                           size_t compressed_size, size_t *poffset,\n                           uint64_t *val) {\n  size_t off;\n  int i;\n  uint64_t v;\n  unsigned char b;\n\n  off = *poffset;\n  i = 0;\n  v = 0;\n  while (1) {\n    if (unlikely(off >= compressed_size)) {\n      elf_uncompress_failed();\n      return 0;\n    }\n    b = compressed[off];\n    v |= (b & 0x7f) << (i * 7);\n    ++off;\n    if ((b & 0x80) == 0) {\n      *poffset = off;\n      *val = v;\n      return 1;\n    }\n    ++i;\n    if (unlikely(i >= 9)) {\n      elf_uncompress_failed();\n      return 0;\n    }\n  }\n}\n\nstatic void elf_lzma_range_normalize(const unsigned char *compressed,\n                                     size_t compressed_size, size_t *poffset,\n                                     uint32_t *prange, uint32_t *pcode) {\n  if (*prange < (1U << 24)) {\n    if (unlikely(*poffset >= compressed_size)) {\n      elf_uncompress_failed();\n      return;\n    }\n    *prange <<= 8;\n    *pcode <<= 8;\n    *pcode += compressed[*poffset];\n    ++*poffset;\n  }\n}\n\nstatic int elf_lzma_bit(const unsigned char *compressed, size_t compressed_size,\n                        uint16_t *prob, size_t *poffset, uint32_t *prange,\n                        uint32_t *pcode) {\n  uint32_t bound;\n\n  elf_lzma_range_normalize(compressed, compressed_size, poffset, prange, pcode);\n  bound = (*prange >> 11) * (uint32_t)*prob;\n  if (*pcode < bound) {\n    *prange = bound;\n    *prob += ((1U << 11) - *prob) >> 5;\n    return 0;\n  } else {\n    *prange -= bound;\n    *pcode -= bound;\n    *prob -= *prob >> 5;\n    return 1;\n  }\n}\n\nstatic uint32_t elf_lzma_integer(const unsigned char *compressed,\n                                 size_t compressed_size, uint16_t *probs,\n                                 uint32_t bits, size_t *poffset,\n                                 uint32_t *prange, uint32_t *pcode) {\n  uint32_t sym;\n  uint32_t i;\n\n  sym = 1;\n  for (i = 0; i < bits; i++) {\n    int bit;\n\n    bit = elf_lzma_bit(compressed, compressed_size, probs + sym, poffset,\n                       prange, pcode);\n    sym <<= 1;\n    sym += bit;\n  }\n  return sym - (1 << bits);\n}\n\nstatic uint32_t elf_lzma_reverse_integer(const unsigned char *compressed,\n                                         size_t compressed_size,\n                                         uint16_t *probs, uint32_t bits,\n                                         size_t *poffset, uint32_t *prange,\n                                         uint32_t *pcode) {\n  uint32_t sym;\n  uint32_t val;\n  uint32_t i;\n\n  sym = 1;\n  val = 0;\n  for (i = 0; i < bits; i++) {\n    int bit;\n\n    bit = elf_lzma_bit(compressed, compressed_size, probs + sym, poffset,\n                       prange, pcode);\n    sym <<= 1;\n    sym += bit;\n    val += bit << i;\n  }\n  return val;\n}\n\nstatic uint32_t elf_lzma_len(const unsigned char *compressed,\n                             size_t compressed_size, uint16_t *probs,\n                             int is_rep, unsigned int pos_state,\n                             size_t *poffset, uint32_t *prange,\n                             uint32_t *pcode) {\n  uint16_t *probs_choice;\n  uint16_t *probs_sym;\n  uint32_t bits;\n  uint32_t len;\n\n  probs_choice = probs + (is_rep ? LZMA_REP_LEN_CHOICE : LZMA_MATCH_LEN_CHOICE);\n  if (elf_lzma_bit(compressed, compressed_size, probs_choice, poffset, prange,\n                   pcode)) {\n    probs_choice =\n        probs + (is_rep ? LZMA_REP_LEN_CHOICE2 : LZMA_MATCH_LEN_CHOICE2);\n    if (elf_lzma_bit(compressed, compressed_size, probs_choice, poffset, prange,\n                     pcode)) {\n      probs_sym =\n          probs + (is_rep ? LZMA_REP_LEN_HIGH(0) : LZMA_MATCH_LEN_HIGH(0));\n      bits = 8;\n      len = 2 + 8 + 8;\n    } else {\n      probs_sym = probs + (is_rep ? LZMA_REP_LEN_MID(pos_state, 0)\n                                  : LZMA_MATCH_LEN_MID(pos_state, 0));\n      bits = 3;\n      len = 2 + 8;\n    }\n  } else {\n    probs_sym = probs + (is_rep ? LZMA_REP_LEN_LOW(pos_state, 0)\n                                : LZMA_MATCH_LEN_LOW(pos_state, 0));\n    bits = 3;\n    len = 2;\n  }\n\n  len += elf_lzma_integer(compressed, compressed_size, probs_sym, bits, poffset,\n                          prange, pcode);\n  return len;\n}\n\nstatic int elf_uncompress_lzma_block(const unsigned char *compressed,\n                                     size_t compressed_size,\n                                     unsigned char check, uint16_t *probs,\n                                     unsigned char *uncompressed,\n                                     size_t uncompressed_size,\n                                     size_t *poffset) {\n  size_t off;\n  size_t block_header_offset;\n  size_t block_header_size;\n  unsigned char block_flags;\n  uint64_t header_compressed_size;\n  uint64_t header_uncompressed_size;\n  unsigned char lzma2_properties;\n  uint32_t computed_crc;\n  uint32_t stream_crc;\n  size_t uncompressed_offset;\n  size_t dict_start_offset;\n  unsigned int lc;\n  unsigned int lp;\n  unsigned int pb;\n  uint32_t range;\n  uint32_t code;\n  uint32_t lstate;\n  uint32_t dist[4];\n\n  off = *poffset;\n  block_header_offset = off;\n\n  if (unlikely(off >= compressed_size)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n  block_header_size = (compressed[off] + 1) * 4;\n  if (unlikely(off + block_header_size > compressed_size)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  block_flags = compressed[off + 1];\n  if (unlikely((block_flags & 0x3c) != 0)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  off += 2;\n\n  header_compressed_size = 0;\n  if ((block_flags & 0x40) != 0) {\n    *poffset = off;\n    if (!elf_lzma_varint(compressed, compressed_size, poffset,\n                         &header_compressed_size))\n      return 0;\n    off = *poffset;\n  }\n\n  header_uncompressed_size = 0;\n  if ((block_flags & 0x80) != 0) {\n    *poffset = off;\n    if (!elf_lzma_varint(compressed, compressed_size, poffset,\n                         &header_uncompressed_size))\n      return 0;\n    off = *poffset;\n  }\n\n  if (unlikely((block_flags & 0x3) != 0)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  if (unlikely(off + 2 >= block_header_offset + block_header_size)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  if (unlikely(compressed[off] != 0x21)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n  ++off;\n\n  if (unlikely(compressed[off] != 1)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n  ++off;\n\n  lzma2_properties = compressed[off];\n  ++off;\n\n  if (unlikely(lzma2_properties > 40)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  if (unlikely(off + 4 > compressed_size)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  off = (off + 3) & ~(size_t)3;\n\n  if (unlikely(off + 4 > compressed_size)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  computed_crc =\n      elf_crc32(0, compressed + block_header_offset, block_header_size - 4);\n  stream_crc = (compressed[off] | (compressed[off + 1] << 8) |\n                (compressed[off + 2] << 16) | (compressed[off + 3] << 24));\n  if (unlikely(computed_crc != stream_crc)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n  off += 4;\n\n  uncompressed_offset = 0;\n  dict_start_offset = 0;\n  lc = 0;\n  lp = 0;\n  pb = 0;\n  lstate = 0;\n  while (off < compressed_size) {\n    unsigned char control;\n\n    range = 0xffffffff;\n    code = 0;\n\n    control = compressed[off];\n    ++off;\n    if (unlikely(control == 0)) {\n      break;\n    }\n\n    if (control == 1 || control >= 0xe0) {\n      dict_start_offset = uncompressed_offset;\n    }\n\n    if (control < 0x80) {\n      size_t chunk_size;\n\n      if (unlikely(control > 2)) {\n        elf_uncompress_failed();\n        return 0;\n      }\n\n      if (unlikely(off + 2 > compressed_size)) {\n        elf_uncompress_failed();\n        return 0;\n      }\n\n      chunk_size = compressed[off] << 8;\n      chunk_size += compressed[off + 1];\n      ++chunk_size;\n\n      off += 2;\n\n      if (unlikely(off + chunk_size > compressed_size)) {\n        elf_uncompress_failed();\n        return 0;\n      }\n      if (unlikely(uncompressed_offset + chunk_size > uncompressed_size)) {\n        elf_uncompress_failed();\n        return 0;\n      }\n\n      memcpy(uncompressed + uncompressed_offset, compressed + off, chunk_size);\n      uncompressed_offset += chunk_size;\n      off += chunk_size;\n    } else {\n      size_t uncompressed_chunk_start;\n      size_t uncompressed_chunk_size;\n      size_t compressed_chunk_size;\n      size_t limit;\n\n      if (unlikely(off + 4 >= compressed_size)) {\n        elf_uncompress_failed();\n        return 0;\n      }\n\n      uncompressed_chunk_start = uncompressed_offset;\n\n      uncompressed_chunk_size = (control & 0x1f) << 16;\n      uncompressed_chunk_size += compressed[off] << 8;\n      uncompressed_chunk_size += compressed[off + 1];\n      ++uncompressed_chunk_size;\n\n      compressed_chunk_size = compressed[off + 2] << 8;\n      compressed_chunk_size += compressed[off + 3];\n      ++compressed_chunk_size;\n\n      off += 4;\n\n      if (control >= 0xc0) {\n        unsigned char props;\n\n        if (unlikely(off >= compressed_size)) {\n          elf_uncompress_failed();\n          return 0;\n        }\n        props = compressed[off];\n        ++off;\n        if (unlikely(props > (4 * 5 + 4) * 9 + 8)) {\n          elf_uncompress_failed();\n          return 0;\n        }\n        pb = 0;\n        while (props >= 9 * 5) {\n          props -= 9 * 5;\n          ++pb;\n        }\n        lp = 0;\n        while (props > 9) {\n          props -= 9;\n          ++lp;\n        }\n        lc = props;\n        if (unlikely(lc + lp > 4)) {\n          elf_uncompress_failed();\n          return 0;\n        }\n      }\n\n      if (control >= 0xa0) {\n        size_t i;\n\n        lstate = 0;\n        memset(&dist, 0, sizeof dist);\n        for (i = 0; i < LZMA_PROB_TOTAL_COUNT; i++) probs[i] = 1 << 10;\n        range = 0xffffffff;\n        code = 0;\n      }\n\n      if (unlikely(off + 5 > compressed_size)) {\n        elf_uncompress_failed();\n        return 0;\n      }\n\n      code = ((compressed[off + 1] << 24) + (compressed[off + 2] << 16) +\n              (compressed[off + 3] << 8) + compressed[off + 4]);\n      off += 5;\n\n      limit = off + compressed_chunk_size;\n      *poffset = off;\n      while (*poffset < limit) {\n        unsigned int pos_state;\n\n        if (unlikely(uncompressed_offset ==\n                     (uncompressed_chunk_start + uncompressed_chunk_size))) {\n          break;\n        }\n\n        pos_state =\n            ((uncompressed_offset - dict_start_offset) & ((1 << pb) - 1));\n\n        if (elf_lzma_bit(compressed, compressed_size,\n                         probs + LZMA_IS_MATCH(lstate, pos_state), poffset,\n                         &range, &code)) {\n          uint32_t len;\n\n          if (elf_lzma_bit(compressed, compressed_size,\n                           probs + LZMA_IS_REP(lstate), poffset, &range,\n                           &code)) {\n            int short_rep;\n            uint32_t next_dist;\n\n            short_rep = 0;\n            if (elf_lzma_bit(compressed, compressed_size,\n                             probs + LZMA_IS_REP0(lstate), poffset, &range,\n                             &code)) {\n              if (elf_lzma_bit(compressed, compressed_size,\n                               probs + LZMA_IS_REP1(lstate), poffset, &range,\n                               &code)) {\n                if (elf_lzma_bit(compressed, compressed_size,\n                                 probs + LZMA_IS_REP2(lstate), poffset, &range,\n                                 &code)) {\n                  next_dist = dist[3];\n                  dist[3] = dist[2];\n                } else {\n                  next_dist = dist[2];\n                }\n                dist[2] = dist[1];\n              } else {\n                next_dist = dist[1];\n              }\n\n              dist[1] = dist[0];\n              dist[0] = next_dist;\n            } else {\n              if (!elf_lzma_bit(compressed, compressed_size,\n                                (probs + LZMA_IS_REP0_LONG(lstate, pos_state)),\n                                poffset, &range, &code))\n                short_rep = 1;\n            }\n\n            if (lstate < 7)\n              lstate = short_rep ? 9 : 8;\n            else\n              lstate = 11;\n\n            if (short_rep)\n              len = 1;\n            else\n              len = elf_lzma_len(compressed, compressed_size, probs, 1,\n                                 pos_state, poffset, &range, &code);\n          } else {\n            uint32_t dist_state;\n            uint32_t dist_slot;\n            uint16_t *probs_dist;\n\n            if (lstate < 7)\n              lstate = 7;\n            else\n              lstate = 10;\n            dist[3] = dist[2];\n            dist[2] = dist[1];\n            dist[1] = dist[0];\n            len = elf_lzma_len(compressed, compressed_size, probs, 0, pos_state,\n                               poffset, &range, &code);\n\n            if (len < 4 + 2)\n              dist_state = len - 2;\n            else\n              dist_state = 3;\n            probs_dist = probs + LZMA_DIST_SLOT(dist_state, 0);\n            dist_slot = elf_lzma_integer(compressed, compressed_size,\n                                         probs_dist, 6, poffset, &range, &code);\n            if (dist_slot < LZMA_DIST_MODEL_START)\n              dist[0] = dist_slot;\n            else {\n              uint32_t limit;\n\n              limit = (dist_slot >> 1) - 1;\n              dist[0] = 2 + (dist_slot & 1);\n              if (dist_slot < LZMA_DIST_MODEL_END) {\n                dist[0] <<= limit;\n                probs_dist =\n                    (probs + LZMA_DIST_SPECIAL(dist[0] - dist_slot - 1));\n                dist[0] += elf_lzma_reverse_integer(compressed, compressed_size,\n                                                    probs_dist, limit, poffset,\n                                                    &range, &code);\n              } else {\n                uint32_t dist0;\n                uint32_t i;\n\n                dist0 = dist[0];\n                for (i = 0; i < limit - 4; i++) {\n                  uint32_t mask;\n\n                  elf_lzma_range_normalize(compressed, compressed_size, poffset,\n                                           &range, &code);\n                  range >>= 1;\n                  code -= range;\n                  mask = -(code >> 31);\n                  code += range & mask;\n                  dist0 <<= 1;\n                  dist0 += mask + 1;\n                }\n                dist0 <<= 4;\n                probs_dist = probs + LZMA_DIST_ALIGN(0);\n                dist0 += elf_lzma_reverse_integer(compressed, compressed_size,\n                                                  probs_dist, 4, poffset,\n                                                  &range, &code);\n                dist[0] = dist0;\n              }\n            }\n          }\n\n          if (unlikely(uncompressed_offset - dict_start_offset < dist[0] + 1)) {\n            elf_uncompress_failed();\n            return 0;\n          }\n          if (unlikely(uncompressed_offset + len > uncompressed_size)) {\n            elf_uncompress_failed();\n            return 0;\n          }\n\n          if (dist[0] == 0) {\n            memset(uncompressed + uncompressed_offset,\n                   uncompressed[uncompressed_offset - 1], len);\n            uncompressed_offset += len;\n          } else if (dist[0] + 1 >= len) {\n            memcpy(uncompressed + uncompressed_offset,\n                   uncompressed + uncompressed_offset - dist[0] - 1, len);\n            uncompressed_offset += len;\n          } else {\n            while (len > 0) {\n              uint32_t copy;\n\n              copy = len < dist[0] + 1 ? len : dist[0] + 1;\n              memcpy(uncompressed + uncompressed_offset,\n                     (uncompressed + uncompressed_offset - dist[0] - 1), copy);\n              len -= copy;\n              uncompressed_offset += copy;\n            }\n          }\n        } else {\n          unsigned char prev;\n          unsigned char low;\n          size_t high;\n          uint16_t *lit_probs;\n          unsigned int sym;\n\n          if (uncompressed_offset > 0)\n            prev = uncompressed[uncompressed_offset - 1];\n          else\n            prev = 0;\n          low = prev >> (8 - lc);\n          high = (((uncompressed_offset - dict_start_offset) & ((1 << lp) - 1))\n                  << lc);\n          lit_probs = probs + LZMA_LITERAL(low + high, 0);\n          if (lstate < 7)\n            sym = elf_lzma_integer(compressed, compressed_size, lit_probs, 8,\n                                   poffset, &range, &code);\n          else {\n            unsigned int match;\n            unsigned int bit;\n            unsigned int match_bit;\n            unsigned int idx;\n\n            sym = 1;\n            if (uncompressed_offset >= dist[0] + 1)\n              match = uncompressed[uncompressed_offset - dist[0] - 1];\n            else\n              match = 0;\n            match <<= 1;\n            bit = 0x100;\n            do {\n              match_bit = match & bit;\n              match <<= 1;\n              idx = bit + match_bit + sym;\n              sym <<= 1;\n              if (elf_lzma_bit(compressed, compressed_size, lit_probs + idx,\n                               poffset, &range, &code)) {\n                ++sym;\n                bit &= match_bit;\n              } else {\n                bit &= ~match_bit;\n              }\n            } while (sym < 0x100);\n          }\n\n          if (unlikely(uncompressed_offset >= uncompressed_size)) {\n            elf_uncompress_failed();\n            return 0;\n          }\n\n          uncompressed[uncompressed_offset] = (unsigned char)sym;\n          ++uncompressed_offset;\n          if (lstate <= 3)\n            lstate = 0;\n          else if (lstate <= 9)\n            lstate -= 3;\n          else\n            lstate -= 6;\n        }\n      }\n\n      elf_lzma_range_normalize(compressed, compressed_size, poffset, &range,\n                               &code);\n\n      off = *poffset;\n    }\n  }\n\n  off = (off + 3) & ~(size_t)3;\n  if (unlikely(off > compressed_size)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  switch (check) {\n    case 0:\n\n      break;\n\n    case 1:\n\n      if (unlikely(off + 4 > compressed_size)) {\n        elf_uncompress_failed();\n        return 0;\n      }\n      computed_crc = elf_crc32(0, uncompressed, uncompressed_offset);\n      stream_crc = (compressed[off] | (compressed[off + 1] << 8) |\n                    (compressed[off + 2] << 16) | (compressed[off + 3] << 24));\n      if (computed_crc != stream_crc) {\n        elf_uncompress_failed();\n        return 0;\n      }\n      off += 4;\n      break;\n\n    case 4:\n\n      if (unlikely(off + 8 > compressed_size)) {\n        elf_uncompress_failed();\n        return 0;\n      }\n      off += 8;\n      break;\n\n    case 10:\n\n      if (unlikely(off + 32 > compressed_size)) {\n        elf_uncompress_failed();\n        return 0;\n      }\n      off += 32;\n      break;\n\n    default:\n      elf_uncompress_failed();\n      return 0;\n  }\n\n  *poffset = off;\n\n  return 1;\n}\n\nstatic int elf_uncompress_lzma(struct backtrace_state *state,\n                               const unsigned char *compressed,\n                               size_t compressed_size,\n                               backtrace_error_callback error_callback,\n                               void *data, unsigned char **uncompressed,\n                               size_t *uncompressed_size) {\n  size_t header_size;\n  size_t footer_size;\n  unsigned char check;\n  uint32_t computed_crc;\n  uint32_t stream_crc;\n  size_t offset;\n  size_t index_size;\n  size_t footer_offset;\n  size_t index_offset;\n  uint64_t index_compressed_size;\n  uint64_t index_uncompressed_size;\n  unsigned char *mem;\n  uint16_t *probs;\n  size_t compressed_block_size;\n\n  header_size = 12;\n  footer_size = 12;\n  if (unlikely(compressed_size < header_size + footer_size)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  if (unlikely(memcmp(compressed,\n                      \"\\375\"\n                      \"7zXZ\\0\",\n                      6) != 0)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  if (unlikely(compressed[6] != 0)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n  check = compressed[7];\n  if (unlikely((check & 0xf8) != 0)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  computed_crc = elf_crc32(0, compressed + 6, 2);\n  stream_crc = (compressed[8] | (compressed[9] << 8) | (compressed[10] << 16) |\n                (compressed[11] << 24));\n  if (unlikely(computed_crc != stream_crc)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  offset = compressed_size;\n  if (unlikely(memcmp(compressed + offset - 2, \"YZ\", 2) != 0)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n  offset -= 2;\n\n  if (unlikely(compressed[offset - 2] != 0 ||\n               compressed[offset - 1] != check)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n  offset -= 2;\n\n  index_size =\n      (compressed[offset - 4] | (compressed[offset - 3] << 8) |\n       (compressed[offset - 2] << 16) | (compressed[offset - 1] << 24));\n  index_size = (index_size + 1) * 4;\n  offset -= 4;\n\n  computed_crc = elf_crc32(0, compressed + offset, 6);\n  stream_crc =\n      (compressed[offset - 4] | (compressed[offset - 3] << 8) |\n       (compressed[offset - 2] << 16) | (compressed[offset - 1] << 24));\n  if (unlikely(computed_crc != stream_crc)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n  offset -= 4;\n\n  if (unlikely(offset < index_size + header_size)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  footer_offset = offset;\n  offset -= index_size;\n  index_offset = offset;\n\n  if (unlikely(compressed[offset] != 0)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n  ++offset;\n\n  if (unlikely(compressed[offset] == 0)) {\n    *uncompressed = NULL;\n    *uncompressed_size = 0;\n    return 1;\n  }\n  if (unlikely(compressed[offset] != 1)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n  ++offset;\n\n  if (!elf_lzma_varint(compressed, compressed_size, &offset,\n                       &index_compressed_size))\n    return 0;\n  if (!elf_lzma_varint(compressed, compressed_size, &offset,\n                       &index_uncompressed_size))\n    return 0;\n\n  offset = (offset + 3) & ~(size_t)3;\n\n  computed_crc = elf_crc32(0, compressed + index_offset, offset - index_offset);\n  stream_crc =\n      (compressed[offset] | (compressed[offset + 1] << 8) |\n       (compressed[offset + 2] << 16) | (compressed[offset + 3] << 24));\n  if (unlikely(computed_crc != stream_crc)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n  offset += 4;\n\n  if (unlikely(offset != footer_offset)) {\n    elf_uncompress_failed();\n    return 0;\n  }\n\n  mem = (unsigned char *)backtrace_alloc(state, index_uncompressed_size,\n                                         error_callback, data);\n  if (unlikely(mem == NULL)) return 0;\n  *uncompressed = mem;\n  *uncompressed_size = index_uncompressed_size;\n\n  probs = ((uint16_t *)backtrace_alloc(\n      state, LZMA_PROB_TOTAL_COUNT * sizeof(uint16_t), error_callback, data));\n  if (unlikely(probs == NULL)) {\n    backtrace_free(state, mem, index_uncompressed_size, error_callback, data);\n    return 0;\n  }\n\n  offset = 12;\n  if (!elf_uncompress_lzma_block(compressed, compressed_size, check, probs, mem,\n                                 index_uncompressed_size, &offset)) {\n    backtrace_free(state, mem, index_uncompressed_size, error_callback, data);\n    return 0;\n  }\n\n  compressed_block_size = offset - 12;\n  if (unlikely(compressed_block_size !=\n               ((index_compressed_size + 3) & ~(size_t)3))) {\n    elf_uncompress_failed();\n    backtrace_free(state, mem, index_uncompressed_size, error_callback, data);\n    return 0;\n  }\n\n  offset = (offset + 3) & ~(size_t)3;\n  if (unlikely(offset != index_offset)) {\n    elf_uncompress_failed();\n    backtrace_free(state, mem, index_uncompressed_size, error_callback, data);\n    return 0;\n  }\n\n  return 1;\n}\n\nint backtrace_uncompress_lzma(struct backtrace_state *state,\n                              const unsigned char *compressed,\n                              size_t compressed_size,\n                              backtrace_error_callback error_callback,\n                              void *data, unsigned char **uncompressed,\n                              size_t *uncompressed_size) {\n  return elf_uncompress_lzma(state, compressed, compressed_size, error_callback,\n                             data, uncompressed, uncompressed_size);\n}\n\nstatic int elf_add(struct backtrace_state *state, const char *filename,\n                   int descriptor, const unsigned char *memory,\n                   size_t memory_size, uintptr_t base_address,\n                   backtrace_error_callback error_callback, void *data,\n                   fileline *fileline_fn, int *found_sym, int *found_dwarf,\n                   struct dwarf_data **fileline_entry, int exe, int debuginfo,\n                   const char *with_buildid_data, uint32_t with_buildid_size) {\n  struct elf_view ehdr_view;\n  b_elf_ehdr ehdr;\n  off_t shoff;\n  unsigned int shnum;\n  unsigned int shstrndx;\n  struct elf_view shdrs_view;\n  int shdrs_view_valid;\n  const b_elf_shdr *shdrs;\n  const b_elf_shdr *shstrhdr;\n  size_t shstr_size;\n  off_t shstr_off;\n  struct elf_view names_view;\n  int names_view_valid;\n  const char *names;\n  unsigned int symtab_shndx;\n  unsigned int dynsym_shndx;\n  unsigned int i;\n  struct debug_section_info sections[DEBUG_MAX];\n  struct debug_section_info zsections[DEBUG_MAX];\n  struct elf_view symtab_view;\n  int symtab_view_valid;\n  struct elf_view strtab_view;\n  int strtab_view_valid;\n  struct elf_view buildid_view;\n  int buildid_view_valid;\n  const char *buildid_data;\n  uint32_t buildid_size;\n  struct elf_view debuglink_view;\n  int debuglink_view_valid;\n  const char *debuglink_name;\n  uint32_t debuglink_crc;\n  struct elf_view debugaltlink_view;\n  int debugaltlink_view_valid;\n  const char *debugaltlink_name;\n  const char *debugaltlink_buildid_data;\n  uint32_t debugaltlink_buildid_size;\n  struct elf_view gnu_debugdata_view;\n  int gnu_debugdata_view_valid;\n  size_t gnu_debugdata_size;\n  unsigned char *gnu_debugdata_uncompressed;\n  size_t gnu_debugdata_uncompressed_size;\n  off_t min_offset;\n  off_t max_offset;\n  off_t debug_size;\n  struct elf_view debug_view;\n  int debug_view_valid;\n  unsigned int using_debug_view;\n  uint16_t *zdebug_table;\n  struct elf_view split_debug_view[DEBUG_MAX];\n  unsigned char split_debug_view_valid[DEBUG_MAX];\n  struct elf_ppc64_opd_data opd_data, *opd;\n  struct dwarf_sections dwarf_sections;\n\n  if (!debuginfo) {\n    *found_sym = 0;\n    *found_dwarf = 0;\n  }\n\n  shdrs_view_valid = 0;\n  names_view_valid = 0;\n  symtab_view_valid = 0;\n  strtab_view_valid = 0;\n  buildid_view_valid = 0;\n  buildid_data = NULL;\n  buildid_size = 0;\n  debuglink_view_valid = 0;\n  debuglink_name = NULL;\n  debuglink_crc = 0;\n  debugaltlink_view_valid = 0;\n  debugaltlink_name = NULL;\n  debugaltlink_buildid_data = NULL;\n  debugaltlink_buildid_size = 0;\n  gnu_debugdata_view_valid = 0;\n  gnu_debugdata_size = 0;\n  debug_view_valid = 0;\n  memset(&split_debug_view_valid[0], 0, sizeof split_debug_view_valid);\n  opd = NULL;\n\n  if (!elf_get_view(state, descriptor, memory, memory_size, 0, sizeof ehdr,\n                    error_callback, data, &ehdr_view))\n    goto fail;\n\n  memcpy(&ehdr, ehdr_view.view.data, sizeof ehdr);\n\n  elf_release_view(state, &ehdr_view, error_callback, data);\n\n  if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 ||\n      ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3) {\n    error_callback(data, \"executable file is not ELF\", 0);\n    goto fail;\n  }\n  if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) {\n    error_callback(data, \"executable file is unrecognized ELF version\", 0);\n    goto fail;\n  }\n\n#if BACKTRACE_ELF_SIZE == 32\n#define BACKTRACE_ELFCLASS ELFCLASS32\n#else\n#define BACKTRACE_ELFCLASS ELFCLASS64\n#endif\n\n  if (ehdr.e_ident[EI_CLASS] != BACKTRACE_ELFCLASS) {\n    error_callback(data, \"executable file is unexpected ELF class\", 0);\n    goto fail;\n  }\n\n  if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB &&\n      ehdr.e_ident[EI_DATA] != ELFDATA2MSB) {\n    error_callback(data, \"executable file has unknown endianness\", 0);\n    goto fail;\n  }\n\n  if (exe && ehdr.e_type == ET_DYN) return -1;\n\n  shoff = ehdr.e_shoff;\n  shnum = ehdr.e_shnum;\n  shstrndx = ehdr.e_shstrndx;\n\n  if ((shnum == 0 || shstrndx == SHN_XINDEX) && shoff != 0) {\n    struct elf_view shdr_view;\n    const b_elf_shdr *shdr;\n\n    if (!elf_get_view(state, descriptor, memory, memory_size, shoff,\n                      sizeof shdr, error_callback, data, &shdr_view))\n      goto fail;\n\n    shdr = (const b_elf_shdr *)shdr_view.view.data;\n\n    if (shnum == 0) shnum = shdr->sh_size;\n\n    if (shstrndx == SHN_XINDEX) {\n      shstrndx = shdr->sh_link;\n\n      if (shstrndx >= shnum && shstrndx >= SHN_LORESERVE + 0x100)\n        shstrndx -= 0x100;\n    }\n\n    elf_release_view(state, &shdr_view, error_callback, data);\n  }\n\n  if (shnum == 0 || shstrndx == 0) goto fail;\n\n  if (!elf_get_view(\n          state, descriptor, memory, memory_size, shoff + sizeof(b_elf_shdr),\n          (shnum - 1) * sizeof(b_elf_shdr), error_callback, data, &shdrs_view))\n    goto fail;\n  shdrs_view_valid = 1;\n  shdrs = (const b_elf_shdr *)shdrs_view.view.data;\n\n  shstrhdr = &shdrs[shstrndx - 1];\n  shstr_size = shstrhdr->sh_size;\n  shstr_off = shstrhdr->sh_offset;\n\n  if (!elf_get_view(state, descriptor, memory, memory_size, shstr_off,\n                    shstrhdr->sh_size, error_callback, data, &names_view))\n    goto fail;\n  names_view_valid = 1;\n  names = (const char *)names_view.view.data;\n\n  symtab_shndx = 0;\n  dynsym_shndx = 0;\n\n  memset(sections, 0, sizeof sections);\n  memset(zsections, 0, sizeof zsections);\n\n  for (i = 1; i < shnum; ++i) {\n    const b_elf_shdr *shdr;\n    unsigned int sh_name;\n    const char *name;\n    int j;\n\n    shdr = &shdrs[i - 1];\n\n    if (shdr->sh_type == SHT_SYMTAB)\n      symtab_shndx = i;\n    else if (shdr->sh_type == SHT_DYNSYM)\n      dynsym_shndx = i;\n\n    sh_name = shdr->sh_name;\n    if (sh_name >= shstr_size) {\n      error_callback(data, \"ELF section name out of range\", 0);\n      goto fail;\n    }\n\n    name = names + sh_name;\n\n    for (j = 0; j < (int)DEBUG_MAX; ++j) {\n      if (strcmp(name, dwarf_section_names[j]) == 0) {\n        sections[j].offset = shdr->sh_offset;\n        sections[j].size = shdr->sh_size;\n        sections[j].compressed = (shdr->sh_flags & SHF_COMPRESSED) != 0;\n        break;\n      }\n    }\n\n    if (name[0] == '.' && name[1] == 'z') {\n      for (j = 0; j < (int)DEBUG_MAX; ++j) {\n        if (strcmp(name + 2, dwarf_section_names[j] + 1) == 0) {\n          zsections[j].offset = shdr->sh_offset;\n          zsections[j].size = shdr->sh_size;\n          break;\n        }\n      }\n    }\n\n    if ((!debuginfo || with_buildid_data != NULL) && !buildid_view_valid &&\n        strcmp(name, \".note.gnu.build-id\") == 0) {\n      const b_elf_note *note;\n\n      if (!elf_get_view(state, descriptor, memory, memory_size, shdr->sh_offset,\n                        shdr->sh_size, error_callback, data, &buildid_view))\n        goto fail;\n\n      buildid_view_valid = 1;\n      note = (const b_elf_note *)buildid_view.view.data;\n      if (note->type == NT_GNU_BUILD_ID && note->namesz == 4 &&\n          strncmp(note->name, \"GNU\", 4) == 0 &&\n          shdr->sh_size <= 12 + ((note->namesz + 3) & ~3) + note->descsz) {\n        buildid_data = &note->name[0] + ((note->namesz + 3) & ~3);\n        buildid_size = note->descsz;\n      }\n\n      if (with_buildid_size != 0) {\n        if (buildid_size != with_buildid_size) goto fail;\n\n        if (memcmp(buildid_data, with_buildid_data, buildid_size) != 0)\n          goto fail;\n      }\n    }\n\n    if (!debuginfo && !debuglink_view_valid &&\n        strcmp(name, \".gnu_debuglink\") == 0) {\n      const char *debuglink_data;\n      size_t crc_offset;\n\n      if (!elf_get_view(state, descriptor, memory, memory_size, shdr->sh_offset,\n                        shdr->sh_size, error_callback, data, &debuglink_view))\n        goto fail;\n\n      debuglink_view_valid = 1;\n      debuglink_data = (const char *)debuglink_view.view.data;\n      crc_offset = strnlen(debuglink_data, shdr->sh_size);\n      crc_offset = (crc_offset + 3) & ~3;\n      if (crc_offset + 4 <= shdr->sh_size) {\n        debuglink_name = debuglink_data;\n        debuglink_crc = *(const uint32_t *)(debuglink_data + crc_offset);\n      }\n    }\n\n    if (!debugaltlink_view_valid && strcmp(name, \".gnu_debugaltlink\") == 0) {\n      const char *debugaltlink_data;\n      size_t debugaltlink_name_len;\n\n      if (!elf_get_view(state, descriptor, memory, memory_size, shdr->sh_offset,\n                        shdr->sh_size, error_callback, data,\n                        &debugaltlink_view))\n        goto fail;\n\n      debugaltlink_view_valid = 1;\n      debugaltlink_data = (const char *)debugaltlink_view.view.data;\n      debugaltlink_name = debugaltlink_data;\n      debugaltlink_name_len = strnlen(debugaltlink_data, shdr->sh_size);\n      if (debugaltlink_name_len < shdr->sh_size) {\n        debugaltlink_name_len += 1;\n\n        debugaltlink_buildid_data = debugaltlink_data + debugaltlink_name_len;\n        debugaltlink_buildid_size = shdr->sh_size - debugaltlink_name_len;\n      }\n    }\n\n    if (!gnu_debugdata_view_valid && strcmp(name, \".gnu_debugdata\") == 0) {\n      if (!elf_get_view(state, descriptor, memory, memory_size, shdr->sh_offset,\n                        shdr->sh_size, error_callback, data,\n                        &gnu_debugdata_view))\n        goto fail;\n\n      gnu_debugdata_size = shdr->sh_size;\n      gnu_debugdata_view_valid = 1;\n    }\n\n    if (ehdr.e_machine == EM_PPC64 && (ehdr.e_flags & EF_PPC64_ABI) < 2 &&\n        shdr->sh_type == SHT_PROGBITS && strcmp(name, \".opd\") == 0) {\n      if (!elf_get_view(state, descriptor, memory, memory_size, shdr->sh_offset,\n                        shdr->sh_size, error_callback, data, &opd_data.view))\n        goto fail;\n\n      opd = &opd_data;\n      opd->addr = shdr->sh_addr;\n      opd->data = (const char *)opd_data.view.view.data;\n      opd->size = shdr->sh_size;\n    }\n  }\n\n  if (symtab_shndx == 0) symtab_shndx = dynsym_shndx;\n  if (symtab_shndx != 0 && !debuginfo) {\n    const b_elf_shdr *symtab_shdr;\n    unsigned int strtab_shndx;\n    const b_elf_shdr *strtab_shdr;\n    struct elf_syminfo_data *sdata;\n\n    symtab_shdr = &shdrs[symtab_shndx - 1];\n    strtab_shndx = symtab_shdr->sh_link;\n    if (strtab_shndx >= shnum) {\n      error_callback(data, \"ELF symbol table strtab link out of range\", 0);\n      goto fail;\n    }\n    strtab_shdr = &shdrs[strtab_shndx - 1];\n\n    if (!elf_get_view(state, descriptor, memory, memory_size,\n                      symtab_shdr->sh_offset, symtab_shdr->sh_size,\n                      error_callback, data, &symtab_view))\n      goto fail;\n    symtab_view_valid = 1;\n\n    if (!elf_get_view(state, descriptor, memory, memory_size,\n                      strtab_shdr->sh_offset, strtab_shdr->sh_size,\n                      error_callback, data, &strtab_view))\n      goto fail;\n    strtab_view_valid = 1;\n\n    sdata = ((struct elf_syminfo_data *)backtrace_alloc(state, sizeof *sdata,\n                                                        error_callback, data));\n    if (sdata == NULL) goto fail;\n\n    if (!elf_initialize_syminfo(state, base_address, symtab_view.view.data,\n                                symtab_shdr->sh_size, strtab_view.view.data,\n                                strtab_shdr->sh_size, error_callback, data,\n                                sdata, opd)) {\n      backtrace_free(state, sdata, sizeof *sdata, error_callback, data);\n      goto fail;\n    }\n\n    elf_release_view(state, &symtab_view, error_callback, data);\n    symtab_view_valid = 0;\n    strtab_view_valid = 0;\n\n    *found_sym = 1;\n\n    elf_add_syminfo_data(state, sdata);\n  }\n\n  elf_release_view(state, &shdrs_view, error_callback, data);\n  shdrs_view_valid = 0;\n  elf_release_view(state, &names_view, error_callback, data);\n  names_view_valid = 0;\n\n  if (buildid_data != NULL) {\n    int d;\n\n    d = elf_open_debugfile_by_buildid(state, buildid_data, buildid_size,\n                                      error_callback, data);\n    if (d >= 0) {\n      int ret;\n\n      elf_release_view(state, &buildid_view, error_callback, data);\n      if (debuglink_view_valid)\n        elf_release_view(state, &debuglink_view, error_callback, data);\n      if (debugaltlink_view_valid)\n        elf_release_view(state, &debugaltlink_view, error_callback, data);\n      ret = elf_add(state, \"\", d, NULL, 0, base_address, error_callback, data,\n                    fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL, 0);\n      if (ret < 0)\n        backtrace_close(d, error_callback, data);\n      else if (descriptor >= 0)\n        backtrace_close(descriptor, error_callback, data);\n      return ret;\n    }\n  }\n\n  if (buildid_view_valid) {\n    elf_release_view(state, &buildid_view, error_callback, data);\n    buildid_view_valid = 0;\n  }\n\n  if (opd) {\n    elf_release_view(state, &opd->view, error_callback, data);\n    opd = NULL;\n  }\n\n  if (debuglink_name != NULL) {\n    int d;\n\n    d = elf_open_debugfile_by_debuglink(state, filename, debuglink_name,\n                                        debuglink_crc, error_callback, data);\n    if (d >= 0) {\n      int ret;\n\n      elf_release_view(state, &debuglink_view, error_callback, data);\n      if (debugaltlink_view_valid)\n        elf_release_view(state, &debugaltlink_view, error_callback, data);\n      ret = elf_add(state, \"\", d, NULL, 0, base_address, error_callback, data,\n                    fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL, 0);\n      if (ret < 0)\n        backtrace_close(d, error_callback, data);\n      else if (descriptor >= 0)\n        backtrace_close(descriptor, error_callback, data);\n      return ret;\n    }\n  }\n\n  if (debuglink_view_valid) {\n    elf_release_view(state, &debuglink_view, error_callback, data);\n    debuglink_view_valid = 0;\n  }\n\n  struct dwarf_data *fileline_altlink = NULL;\n  if (debugaltlink_name != NULL) {\n    int d;\n\n    d = elf_open_debugfile_by_debuglink(state, filename, debugaltlink_name, 0,\n                                        error_callback, data);\n    if (d >= 0) {\n      int ret;\n\n      ret =\n          elf_add(state, filename, d, NULL, 0, base_address, error_callback,\n                  data, fileline_fn, found_sym, found_dwarf, &fileline_altlink,\n                  0, 1, debugaltlink_buildid_data, debugaltlink_buildid_size);\n      elf_release_view(state, &debugaltlink_view, error_callback, data);\n      debugaltlink_view_valid = 0;\n      if (ret < 0) {\n        backtrace_close(d, error_callback, data);\n        return ret;\n      }\n    }\n  }\n\n  if (debugaltlink_view_valid) {\n    elf_release_view(state, &debugaltlink_view, error_callback, data);\n    debugaltlink_view_valid = 0;\n  }\n\n  if (gnu_debugdata_view_valid) {\n    int ret;\n\n    ret = elf_uncompress_lzma(\n        state, ((const unsigned char *)gnu_debugdata_view.view.data),\n        gnu_debugdata_size, error_callback, data, &gnu_debugdata_uncompressed,\n        &gnu_debugdata_uncompressed_size);\n\n    elf_release_view(state, &gnu_debugdata_view, error_callback, data);\n    gnu_debugdata_view_valid = 0;\n\n    if (ret) {\n      ret = elf_add(state, filename, -1, gnu_debugdata_uncompressed,\n                    gnu_debugdata_uncompressed_size, base_address,\n                    error_callback, data, fileline_fn, found_sym, found_dwarf,\n                    NULL, 0, 0, NULL, 0);\n      if (ret >= 0 && descriptor >= 0)\n        backtrace_close(descriptor, error_callback, data);\n      return ret;\n    }\n  }\n\n  min_offset = 0;\n  max_offset = 0;\n  debug_size = 0;\n  for (i = 0; i < (int)DEBUG_MAX; ++i) {\n    off_t end;\n\n    if (sections[i].size != 0) {\n      if (min_offset == 0 || sections[i].offset < min_offset)\n        min_offset = sections[i].offset;\n      end = sections[i].offset + sections[i].size;\n      if (end > max_offset) max_offset = end;\n      debug_size += sections[i].size;\n    }\n    if (zsections[i].size != 0) {\n      if (min_offset == 0 || zsections[i].offset < min_offset)\n        min_offset = zsections[i].offset;\n      end = zsections[i].offset + zsections[i].size;\n      if (end > max_offset) max_offset = end;\n      debug_size += zsections[i].size;\n    }\n  }\n  if (min_offset == 0 || max_offset == 0) {\n    if (descriptor >= 0) {\n      if (!backtrace_close(descriptor, error_callback, data)) goto fail;\n    }\n    return 1;\n  }\n\n  if (max_offset - min_offset < 0x20000000 ||\n      max_offset - min_offset < debug_size + 0x10000) {\n    if (!elf_get_view(state, descriptor, memory, memory_size, min_offset,\n                      max_offset - min_offset, error_callback, data,\n                      &debug_view))\n      goto fail;\n    debug_view_valid = 1;\n  } else {\n    memset(&split_debug_view[0], 0, sizeof split_debug_view);\n    for (i = 0; i < (int)DEBUG_MAX; ++i) {\n      struct debug_section_info *dsec;\n\n      if (sections[i].size != 0)\n        dsec = &sections[i];\n      else if (zsections[i].size != 0)\n        dsec = &zsections[i];\n      else\n        continue;\n\n      if (!elf_get_view(state, descriptor, memory, memory_size, dsec->offset,\n                        dsec->size, error_callback, data, &split_debug_view[i]))\n        goto fail;\n      split_debug_view_valid[i] = 1;\n\n      if (sections[i].size != 0)\n        sections[i].data =\n            ((const unsigned char *)split_debug_view[i].view.data);\n      else\n        zsections[i].data =\n            ((const unsigned char *)split_debug_view[i].view.data);\n    }\n  }\n\n  if (descriptor >= 0) {\n    if (!backtrace_close(descriptor, error_callback, data)) goto fail;\n    descriptor = -1;\n  }\n\n  using_debug_view = 0;\n  if (debug_view_valid) {\n    for (i = 0; i < (int)DEBUG_MAX; ++i) {\n      if (sections[i].size == 0)\n        sections[i].data = NULL;\n      else {\n        sections[i].data = ((const unsigned char *)debug_view.view.data +\n                            (sections[i].offset - min_offset));\n        ++using_debug_view;\n      }\n\n      if (zsections[i].size == 0)\n        zsections[i].data = NULL;\n      else\n        zsections[i].data = ((const unsigned char *)debug_view.view.data +\n                             (zsections[i].offset - min_offset));\n    }\n  }\n\n  zdebug_table = NULL;\n  for (i = 0; i < (int)DEBUG_MAX; ++i) {\n    if (sections[i].size == 0 && zsections[i].size > 0) {\n      unsigned char *uncompressed_data;\n      size_t uncompressed_size;\n\n      if (zdebug_table == NULL) {\n        zdebug_table = ((uint16_t *)backtrace_alloc(state, ZDEBUG_TABLE_SIZE,\n                                                    error_callback, data));\n        if (zdebug_table == NULL) goto fail;\n      }\n\n      uncompressed_data = NULL;\n      uncompressed_size = 0;\n      if (!elf_uncompress_zdebug(state, zsections[i].data, zsections[i].size,\n                                 zdebug_table, error_callback, data,\n                                 &uncompressed_data, &uncompressed_size))\n        goto fail;\n      sections[i].data = uncompressed_data;\n      sections[i].size = uncompressed_size;\n      sections[i].compressed = 0;\n\n      if (split_debug_view_valid[i]) {\n        elf_release_view(state, &split_debug_view[i], error_callback, data);\n        split_debug_view_valid[i] = 0;\n      }\n    }\n  }\n\n  for (i = 0; i < (int)DEBUG_MAX; ++i) {\n    unsigned char *uncompressed_data;\n    size_t uncompressed_size;\n\n    if (sections[i].size == 0 || !sections[i].compressed) continue;\n\n    if (zdebug_table == NULL) {\n      zdebug_table = ((uint16_t *)backtrace_alloc(state, ZDEBUG_TABLE_SIZE,\n                                                  error_callback, data));\n      if (zdebug_table == NULL) goto fail;\n    }\n\n    uncompressed_data = NULL;\n    uncompressed_size = 0;\n    if (!elf_uncompress_chdr(state, sections[i].data, sections[i].size,\n                             zdebug_table, error_callback, data,\n                             &uncompressed_data, &uncompressed_size))\n      goto fail;\n    sections[i].data = uncompressed_data;\n    sections[i].size = uncompressed_size;\n    sections[i].compressed = 0;\n\n    if (debug_view_valid)\n      --using_debug_view;\n    else if (split_debug_view_valid[i]) {\n      elf_release_view(state, &split_debug_view[i], error_callback, data);\n      split_debug_view_valid[i] = 0;\n    }\n  }\n\n  if (zdebug_table != NULL)\n    backtrace_free(state, zdebug_table, ZDEBUG_TABLE_SIZE, error_callback,\n                   data);\n\n  if (debug_view_valid && using_debug_view == 0) {\n    elf_release_view(state, &debug_view, error_callback, data);\n    debug_view_valid = 0;\n  }\n\n  for (i = 0; i < (int)DEBUG_MAX; ++i) {\n    dwarf_sections.data[i] = sections[i].data;\n    dwarf_sections.size[i] = sections[i].size;\n  }\n\n  if (!backtrace_dwarf_add(state, base_address, &dwarf_sections,\n                           ehdr.e_ident[EI_DATA] == ELFDATA2MSB,\n                           fileline_altlink, error_callback, data, fileline_fn,\n                           fileline_entry))\n    goto fail;\n\n  *found_dwarf = 1;\n\n  return 1;\n\nfail:\n  if (shdrs_view_valid)\n    elf_release_view(state, &shdrs_view, error_callback, data);\n  if (names_view_valid)\n    elf_release_view(state, &names_view, error_callback, data);\n  if (symtab_view_valid)\n    elf_release_view(state, &symtab_view, error_callback, data);\n  if (strtab_view_valid)\n    elf_release_view(state, &strtab_view, error_callback, data);\n  if (debuglink_view_valid)\n    elf_release_view(state, &debuglink_view, error_callback, data);\n  if (debugaltlink_view_valid)\n    elf_release_view(state, &debugaltlink_view, error_callback, data);\n  if (gnu_debugdata_view_valid)\n    elf_release_view(state, &gnu_debugdata_view, error_callback, data);\n  if (buildid_view_valid)\n    elf_release_view(state, &buildid_view, error_callback, data);\n  if (debug_view_valid)\n    elf_release_view(state, &debug_view, error_callback, data);\n  for (i = 0; i < (int)DEBUG_MAX; ++i) {\n    if (split_debug_view_valid[i])\n      elf_release_view(state, &split_debug_view[i], error_callback, data);\n  }\n  if (opd) elf_release_view(state, &opd->view, error_callback, data);\n  if (descriptor >= 0) backtrace_close(descriptor, error_callback, data);\n  return 0;\n}\n\nstruct phdr_data {\n  struct backtrace_state *state;\n  backtrace_error_callback error_callback;\n  void *data;\n  fileline *fileline_fn;\n  int *found_sym;\n  int *found_dwarf;\n  const char *exe_filename;\n  int exe_descriptor;\n};\n\nstatic int\n#ifdef __i386__\n    __attribute__((__force_align_arg_pointer__))\n#endif\n    phdr_callback(struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,\n                  void *pdata) {\n  struct phdr_data *pd = (struct phdr_data *)pdata;\n  const char *filename;\n  int descriptor;\n  int does_not_exist;\n  fileline elf_fileline_fn;\n  int found_dwarf;\n\n  if (info->dlpi_name == NULL || info->dlpi_name[0] == '\\0') {\n    if (pd->exe_descriptor == -1) return 0;\n    filename = pd->exe_filename;\n    descriptor = pd->exe_descriptor;\n    pd->exe_descriptor = -1;\n  } else {\n    if (pd->exe_descriptor != -1) {\n      backtrace_close(pd->exe_descriptor, pd->error_callback, pd->data);\n      pd->exe_descriptor = -1;\n    }\n\n    filename = info->dlpi_name;\n    descriptor = backtrace_open(info->dlpi_name, pd->error_callback, pd->data,\n                                &does_not_exist);\n    if (descriptor < 0) return 0;\n  }\n\n  if (elf_add(pd->state, filename, descriptor, NULL, 0, info->dlpi_addr,\n              pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym,\n              &found_dwarf, NULL, 0, 0, NULL, 0)) {\n    if (found_dwarf) {\n      *pd->found_dwarf = 1;\n      *pd->fileline_fn = elf_fileline_fn;\n    }\n  }\n\n  return 0;\n}\n\nint backtrace_initialize(struct backtrace_state *state, const char *filename,\n                         int descriptor,\n                         backtrace_error_callback error_callback, void *data,\n                         fileline *fileline_fn) {\n  int ret;\n  int found_sym;\n  int found_dwarf;\n  fileline elf_fileline_fn = elf_nodebug;\n  struct phdr_data pd;\n\n  ret =\n      elf_add(state, filename, descriptor, NULL, 0, 0, error_callback, data,\n              &elf_fileline_fn, &found_sym, &found_dwarf, NULL, 1, 0, NULL, 0);\n  if (!ret) return 0;\n\n  pd.state = state;\n  pd.error_callback = error_callback;\n  pd.data = data;\n  pd.fileline_fn = &elf_fileline_fn;\n  pd.found_sym = &found_sym;\n  pd.found_dwarf = &found_dwarf;\n  pd.exe_filename = filename;\n  pd.exe_descriptor = ret < 0 ? descriptor : -1;\n\n  dl_iterate_phdr(phdr_callback, (void *)&pd);\n\n  if (!state->threaded) {\n    if (found_sym)\n      state->syminfo_fn = elf_syminfo;\n    else if (state->syminfo_fn == NULL)\n      state->syminfo_fn = elf_nosyms;\n  } else {\n    if (found_sym)\n      backtrace_atomic_store_pointer(&state->syminfo_fn, elf_syminfo);\n    else\n      (void)__sync_bool_compare_and_swap(&state->syminfo_fn, NULL, elf_nosyms);\n  }\n\n  if (!state->threaded)\n    *fileline_fn = state->fileline_fn;\n  else\n    *fileline_fn = backtrace_atomic_load_pointer(&state->fileline_fn);\n\n  if (*fileline_fn == NULL || *fileline_fn == elf_nodebug)\n    *fileline_fn = elf_fileline_fn;\n\n  return 1;\n}\n\n// mmapio.c:\n#include <errno.h>\n#include <sys/mman.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#ifndef HAVE_DECL_GETPAGESIZE\nextern int getpagesize(void);\n#endif\n\n#ifndef MAP_FAILED\n#define MAP_FAILED ((void *)-1)\n#endif\n\nint backtrace_get_view(struct backtrace_state *state ATTRIBUTE_UNUSED,\n                       int descriptor, off_t offset, uint64_t size,\n                       backtrace_error_callback error_callback, void *data,\n                       struct backtrace_view *view) {\n  size_t pagesize;\n  unsigned int inpage;\n  off_t pageoff;\n  void *map;\n\n  if ((uint64_t)(size_t)size != size) {\n    error_callback(data, \"file size too large\", 0);\n    return 0;\n  }\n\n  pagesize = getpagesize();\n  inpage = offset % pagesize;\n  pageoff = offset - inpage;\n\n  size += inpage;\n  size = (size + (pagesize - 1)) & ~(pagesize - 1);\n\n  map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, descriptor, pageoff);\n  if (map == MAP_FAILED) {\n    error_callback(data, \"mmap\", errno);\n    return 0;\n  }\n\n  view->data = (char *)map + inpage;\n  view->base = map;\n  view->len = size;\n\n  return 1;\n}\n\nvoid backtrace_release_view(struct backtrace_state *state ATTRIBUTE_UNUSED,\n                            struct backtrace_view *view,\n                            backtrace_error_callback error_callback,\n                            void *data) {\n  union {\n    const void *cv;\n    void *v;\n  } const_cast;\n\n  const_cast.cv = view->base;\n  if (munmap(const_cast.v, view->len) < 0)\n    error_callback(data, \"munmap\", errno);\n}\n\n// mmap.c:\n#include <errno.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#ifndef HAVE_DECL_GETPAGESIZE\nextern int getpagesize(void);\n#endif\n\n#ifndef MAP_ANONYMOUS\n#define MAP_ANONYMOUS MAP_ANON\n#endif\n\n#ifndef MAP_FAILED\n#define MAP_FAILED ((void *)-1)\n#endif\n\nstruct backtrace_freelist_struct {\n  struct backtrace_freelist_struct *next;\n\n  size_t size;\n};\n\nstatic void backtrace_free_locked(struct backtrace_state *state, void *addr,\n                                  size_t size) {\n  if (size >= sizeof(struct backtrace_freelist_struct)) {\n    size_t c;\n    struct backtrace_freelist_struct **ppsmall;\n    struct backtrace_freelist_struct **pp;\n    struct backtrace_freelist_struct *p;\n\n    c = 0;\n    ppsmall = NULL;\n    for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next) {\n      if (ppsmall == NULL || (*pp)->size < (*ppsmall)->size) ppsmall = pp;\n      ++c;\n    }\n    if (c >= 16) {\n      if (size <= (*ppsmall)->size) return;\n      *ppsmall = (*ppsmall)->next;\n    }\n\n    p = (struct backtrace_freelist_struct *)addr;\n    p->next = state->freelist;\n    p->size = size;\n    state->freelist = p;\n  }\n}\n\nvoid *backtrace_alloc(struct backtrace_state *state, size_t size,\n                      backtrace_error_callback error_callback, void *data) {\n  void *ret;\n  int locked;\n  struct backtrace_freelist_struct **pp;\n  size_t pagesize;\n  size_t asksize;\n  void *page;\n\n  ret = NULL;\n\n  if (!state->threaded)\n    locked = 1;\n  else\n    locked = __sync_lock_test_and_set(&state->lock_alloc, 1) == 0;\n\n  if (locked) {\n    for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next) {\n      if ((*pp)->size >= size) {\n        struct backtrace_freelist_struct *p;\n\n        p = *pp;\n        *pp = p->next;\n\n        size = (size + 7) & ~(size_t)7;\n        if (size < p->size)\n          backtrace_free_locked(state, (char *)p + size, p->size - size);\n\n        ret = (void *)p;\n\n        break;\n      }\n    }\n\n    if (state->threaded) __sync_lock_release(&state->lock_alloc);\n  }\n\n  if (ret == NULL) {\n    pagesize = getpagesize();\n    asksize = (size + pagesize - 1) & ~(pagesize - 1);\n    page = mmap(NULL, asksize, PROT_READ | PROT_WRITE,\n                MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n    if (page == MAP_FAILED) {\n      if (error_callback) error_callback(data, \"mmap\", errno);\n    } else {\n      size = (size + 7) & ~(size_t)7;\n      if (size < asksize)\n        backtrace_free(state, (char *)page + size, asksize - size,\n                       error_callback, data);\n\n      ret = page;\n    }\n  }\n\n  return ret;\n}\n\nvoid backtrace_free(struct backtrace_state *state, void *addr, size_t size,\n                    backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n                    void *data ATTRIBUTE_UNUSED) {\n  int locked;\n\n  if (size >= 16 * 4096) {\n    size_t pagesize;\n\n    pagesize = getpagesize();\n    if (((uintptr_t)addr & (pagesize - 1)) == 0 &&\n        (size & (pagesize - 1)) == 0) {\n      if (munmap(addr, size) == 0) return;\n    }\n  }\n\n  if (!state->threaded)\n    locked = 1;\n  else\n    locked = __sync_lock_test_and_set(&state->lock_alloc, 1) == 0;\n\n  if (locked) {\n    backtrace_free_locked(state, addr, size);\n\n    if (state->threaded) __sync_lock_release(&state->lock_alloc);\n  }\n}\n\nvoid *backtrace_vector_grow(struct backtrace_state *state, size_t size,\n                            backtrace_error_callback error_callback, void *data,\n                            struct backtrace_vector *vec) {\n  void *ret;\n\n  if (size > vec->alc) {\n    size_t pagesize;\n    size_t alc;\n    void *base;\n\n    pagesize = getpagesize();\n    alc = vec->size + size;\n    if (vec->size == 0)\n      alc = 16 * size;\n    else if (alc < pagesize) {\n      alc *= 2;\n      if (alc > pagesize) alc = pagesize;\n    } else {\n      alc *= 2;\n      alc = (alc + pagesize - 1) & ~(pagesize - 1);\n    }\n    base = backtrace_alloc(state, alc, error_callback, data);\n    if (base == NULL) return NULL;\n    if (vec->base != NULL) {\n      memcpy(base, vec->base, vec->size);\n      backtrace_free(state, vec->base, vec->size + vec->alc, error_callback,\n                     data);\n    }\n    vec->base = base;\n    vec->alc = alc - vec->size;\n  }\n\n  ret = (char *)vec->base + vec->size;\n  vec->size += size;\n  vec->alc -= size;\n  return ret;\n}\n\nvoid *backtrace_vector_finish(struct backtrace_state *state ATTRIBUTE_UNUSED,\n                              struct backtrace_vector *vec,\n                              backtrace_error_callback error_callback\n                                  ATTRIBUTE_UNUSED,\n                              void *data ATTRIBUTE_UNUSED) {\n  void *ret;\n\n  ret = vec->base;\n  vec->base = (char *)vec->base + vec->size;\n  vec->size = 0;\n  return ret;\n}\n\nint backtrace_vector_release(struct backtrace_state *state,\n                             struct backtrace_vector *vec,\n                             backtrace_error_callback error_callback,\n                             void *data) {\n  size_t size;\n  size_t alc;\n  size_t aligned;\n\n  size = vec->size;\n  alc = vec->alc;\n  aligned = (size + 7) & ~(size_t)7;\n  alc -= aligned - size;\n\n  backtrace_free(state, (char *)vec->base + aligned, alc, error_callback, data);\n  vec->alc = 0;\n  if (vec->size == 0) vec->base = NULL;\n  return 1;\n}\n"
  },
  {
    "path": "thirdparty/libbacktrace/windows.c",
    "content": "// pecoff.c:\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n\ntypedef struct {\n  uint16_t machine;\n  uint16_t number_of_sections;\n  uint32_t time_date_stamp;\n  uint32_t pointer_to_symbol_table;\n  uint32_t number_of_symbols;\n  uint16_t size_of_optional_header;\n  uint16_t characteristics;\n} b_coff_file_header;\n\ntypedef struct {\n  uint16_t magic;\n  uint8_t major_linker_version;\n  uint8_t minor_linker_version;\n  uint32_t size_of_code;\n  uint32_t size_of_initialized_data;\n  uint32_t size_of_uninitialized_data;\n  uint32_t address_of_entry_point;\n  uint32_t base_of_code;\n  union {\n    struct {\n      uint32_t base_of_data;\n      uint32_t image_base;\n    } pe;\n    struct {\n      uint64_t image_base;\n    } pep;\n  } u;\n} b_coff_optional_header;\n\n#define PE_MAGIC 0x10b\n#define PEP_MAGIC 0x20b\n\ntypedef struct {\n  char name[8];\n  uint32_t virtual_size;\n  uint32_t virtual_address;\n  uint32_t size_of_raw_data;\n  uint32_t pointer_to_raw_data;\n  uint32_t pointer_to_relocations;\n  uint32_t pointer_to_line_numbers;\n  uint16_t number_of_relocations;\n  uint16_t number_of_line_numbers;\n  uint32_t characteristics;\n} b_coff_section_header;\n\ntypedef union {\n  char short_name[8];\n  struct {\n    unsigned char zeroes[4];\n    unsigned char off[4];\n  } long_name;\n} b_coff_name;\n\ntypedef struct {\n  b_coff_name name;\n  unsigned char value[4];\n  unsigned char section_number[2];\n  unsigned char type[2];\n  unsigned char storage_class;\n  unsigned char number_of_aux_symbols;\n} b_coff_external_symbol;\n\n#define N_TBSHFT 4\n#define IMAGE_SYM_DTYPE_FUNCTION 2\n\n#define SYM_SZ 18\n\ntypedef struct {\n  const char *name;\n  uint32_t value;\n  int16_t sec;\n  uint16_t type;\n  uint16_t sc;\n} b_coff_internal_symbol;\n\nstatic const char *const debug_section_names[DEBUG_MAX] = {\n    \".debug_info\",        \".debug_line\",     \".debug_abbrev\",\n    \".debug_ranges\",      \".debug_str\",      \".debug_addr\",\n    \".debug_str_offsets\", \".debug_line_str\", \".debug_rnglists\"};\n\nstruct debug_section_info {\n  off_t offset;\n\n  size_t size;\n};\n\nstruct coff_symbol {\n  const char *name;\n\n  uintptr_t address;\n};\n\nstruct coff_syminfo_data {\n  struct coff_syminfo_data *next;\n\n  struct coff_symbol *symbols;\n\n  size_t count;\n};\n\nstatic int coff_nodebug(struct backtrace_state *state ATTRIBUTE_UNUSED,\n                        uintptr_t pc ATTRIBUTE_UNUSED,\n                        backtrace_full_callback callback ATTRIBUTE_UNUSED,\n                        backtrace_error_callback error_callback, void *data) {\n  error_callback(data, \"no debug info in PE/COFF executable\", -1);\n  return 0;\n}\n\nstatic void coff_nosyms(struct backtrace_state *state ATTRIBUTE_UNUSED,\n                        uintptr_t addr ATTRIBUTE_UNUSED,\n                        backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,\n                        backtrace_error_callback error_callback, void *data) {\n  error_callback(data, \"no symbol table in PE/COFF executable\", -1);\n}\n\nstatic uint32_t coff_read4(const unsigned char *p) {\n  uint32_t res;\n\n  memcpy(&res, p, 4);\n  return res;\n}\n\nstatic uint16_t coff_read2(const unsigned char *p) {\n  uint16_t res;\n\n  memcpy(&res, p, sizeof(res));\n  return res;\n}\n\nstatic size_t coff_short_name_len(const char *name) {\n  int i;\n\n  for (i = 0; i < 8; i++)\n    if (name[i] == 0) return i;\n  return 8;\n}\n\nstatic int coff_short_name_eq(const char *name, const char *cname) {\n  int i;\n\n  for (i = 0; i < 8; i++) {\n    if (name[i] != cname[i]) return 0;\n    if (name[i] == 0) return 1;\n  }\n  return name[8] == 0;\n}\n\nstatic int coff_long_name_eq(const char *name, unsigned int off,\n                             struct backtrace_view *str_view) {\n  if (off >= str_view->len) return 0;\n  return strcmp(name, (const char *)str_view->data + off) == 0;\n}\n\nstatic int coff_symbol_compare(const void *v1, const void *v2) {\n  const struct coff_symbol *e1 = (const struct coff_symbol *)v1;\n  const struct coff_symbol *e2 = (const struct coff_symbol *)v2;\n\n  if (e1->address < e2->address)\n    return -1;\n  else if (e1->address > e2->address)\n    return 1;\n  else\n    return 0;\n}\n\nstatic int coff_expand_symbol(b_coff_internal_symbol *isym,\n                              const b_coff_external_symbol *sym,\n                              uint16_t sects_num, const unsigned char *strtab,\n                              size_t strtab_size) {\n  isym->type = coff_read2(sym->type);\n  isym->sec = coff_read2(sym->section_number);\n  isym->sc = sym->storage_class;\n\n  if (isym->sec > 0 && (uint16_t)isym->sec > sects_num) return -1;\n  if (sym->name.short_name[0] != 0)\n    isym->name = sym->name.short_name;\n  else {\n    uint32_t off = coff_read4(sym->name.long_name.off);\n\n    if (off >= strtab_size) return -1;\n    isym->name = (const char *)strtab + off;\n  }\n  return 0;\n}\n\nstatic int coff_is_function_symbol(const b_coff_internal_symbol *isym) {\n  return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION && isym->sec > 0;\n}\n\nstatic int coff_initialize_syminfo(\n    struct backtrace_state *state, uintptr_t base_address, int is_64,\n    const b_coff_section_header *sects, size_t sects_num,\n    const b_coff_external_symbol *syms, size_t syms_size,\n    const unsigned char *strtab, size_t strtab_size,\n    backtrace_error_callback error_callback, void *data,\n    struct coff_syminfo_data *sdata) {\n  size_t syms_count;\n  char *coff_symstr;\n  size_t coff_symstr_len;\n  size_t coff_symbol_count;\n  size_t coff_symbol_size;\n  struct coff_symbol *coff_symbols;\n  struct coff_symbol *coff_sym;\n  char *coff_str;\n  size_t i;\n\n  syms_count = syms_size / SYM_SZ;\n\n  coff_symbol_count = 0;\n  coff_symstr_len = 0;\n  for (i = 0; i < syms_count; ++i) {\n    const b_coff_external_symbol *asym = &syms[i];\n    b_coff_internal_symbol isym;\n\n    if (coff_expand_symbol(&isym, asym, sects_num, strtab, strtab_size) < 0) {\n      error_callback(data, \"invalid section or offset in coff symbol\", 0);\n      return 0;\n    }\n    if (coff_is_function_symbol(&isym)) {\n      ++coff_symbol_count;\n      if (asym->name.short_name[0] != 0)\n        coff_symstr_len += coff_short_name_len(asym->name.short_name) + 1;\n    }\n\n    i += asym->number_of_aux_symbols;\n  }\n\n  coff_symbol_size = (coff_symbol_count + 1) * sizeof(struct coff_symbol);\n  coff_symbols = ((struct coff_symbol *)backtrace_alloc(state, coff_symbol_size,\n                                                        error_callback, data));\n  if (coff_symbols == NULL) return 0;\n\n  if (coff_symstr_len > 0) {\n    coff_symstr =\n        ((char *)backtrace_alloc(state, coff_symstr_len, error_callback, data));\n    if (coff_symstr == NULL) {\n      backtrace_free(state, coff_symbols, coff_symbol_size, error_callback,\n                     data);\n      return 0;\n    }\n  } else\n    coff_symstr = NULL;\n\n  coff_sym = coff_symbols;\n  coff_str = coff_symstr;\n  for (i = 0; i < syms_count; ++i) {\n    const b_coff_external_symbol *asym = &syms[i];\n    b_coff_internal_symbol isym;\n\n    if (coff_expand_symbol(&isym, asym, sects_num, strtab, strtab_size)) {\n      abort();\n    }\n    if (coff_is_function_symbol(&isym)) {\n      const char *name;\n      int16_t secnum;\n\n      if (asym->name.short_name[0] != 0) {\n        size_t len = coff_short_name_len(isym.name);\n        name = coff_str;\n        memcpy(coff_str, isym.name, len);\n        coff_str[len] = 0;\n        coff_str += len + 1;\n      } else\n        name = isym.name;\n\n      if (!is_64) {\n        if (name[0] == '_') name++;\n      }\n\n      secnum = coff_read2(asym->section_number);\n\n      coff_sym->name = name;\n      coff_sym->address = (coff_read4(asym->value) +\n                           sects[secnum - 1].virtual_address + base_address);\n      coff_sym++;\n    }\n\n    i += asym->number_of_aux_symbols;\n  }\n\n  coff_sym->name = NULL;\n  coff_sym->address = -1;\n\n  backtrace_qsort(coff_symbols, coff_symbol_count, sizeof(struct coff_symbol),\n                  coff_symbol_compare);\n\n  sdata->next = NULL;\n  sdata->symbols = coff_symbols;\n  sdata->count = coff_symbol_count;\n\n  return 1;\n}\n\nstatic void coff_add_syminfo_data(struct backtrace_state *state,\n                                  struct coff_syminfo_data *sdata) {\n  if (!state->threaded) {\n    struct coff_syminfo_data **pp;\n\n    for (pp = (struct coff_syminfo_data **)(void *)&state->syminfo_data;\n         *pp != NULL; pp = &(*pp)->next)\n      ;\n    *pp = sdata;\n  } else {\n    while (1) {\n      struct coff_syminfo_data **pp;\n\n      pp = (struct coff_syminfo_data **)(void *)&state->syminfo_data;\n\n      while (1) {\n        struct coff_syminfo_data *p;\n\n        p = backtrace_atomic_load_pointer(pp);\n\n        if (p == NULL) break;\n\n        pp = &p->next;\n      }\n\n      if (__sync_bool_compare_and_swap(pp, NULL, sdata)) break;\n    }\n  }\n}\n\nstatic int coff_symbol_search(const void *vkey, const void *ventry) {\n  const uintptr_t *key = (const uintptr_t *)vkey;\n  const struct coff_symbol *entry = (const struct coff_symbol *)ventry;\n  uintptr_t addr;\n\n  addr = *key;\n  if (addr < entry->address)\n    return -1;\n  else if (addr >= entry[1].address)\n    return 1;\n  else\n    return 0;\n}\n\nstatic void coff_syminfo(\n    struct backtrace_state *state, uintptr_t addr,\n    backtrace_syminfo_callback callback,\n    backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data) {\n  struct coff_syminfo_data *sdata;\n  struct coff_symbol *sym = NULL;\n\n  if (!state->threaded) {\n    for (sdata = (struct coff_syminfo_data *)state->syminfo_data; sdata != NULL;\n         sdata = sdata->next) {\n      sym = ((struct coff_symbol *)bsearch(&addr, sdata->symbols, sdata->count,\n                                           sizeof(struct coff_symbol),\n                                           coff_symbol_search));\n      if (sym != NULL) break;\n    }\n  } else {\n    struct coff_syminfo_data **pp;\n\n    pp = (struct coff_syminfo_data **)(void *)&state->syminfo_data;\n    while (1) {\n      sdata = backtrace_atomic_load_pointer(pp);\n      if (sdata == NULL) break;\n\n      sym = ((struct coff_symbol *)bsearch(&addr, sdata->symbols, sdata->count,\n                                           sizeof(struct coff_symbol),\n                                           coff_symbol_search));\n      if (sym != NULL) break;\n\n      pp = &sdata->next;\n    }\n  }\n\n  if (sym == NULL)\n    callback(data, addr, NULL, 0, 0);\n  else\n    callback(data, addr, sym->name, sym->address, 0);\n}\n\nstatic int coff_add(struct backtrace_state *state, int descriptor,\n                    backtrace_error_callback error_callback, void *data,\n                    fileline *fileline_fn, int *found_sym, int *found_dwarf) {\n  struct backtrace_view fhdr_view;\n  off_t fhdr_off;\n  int magic_ok;\n  b_coff_file_header fhdr;\n  off_t opt_sects_off;\n  size_t opt_sects_size;\n  unsigned int sects_num;\n  struct backtrace_view sects_view;\n  int sects_view_valid;\n  const b_coff_optional_header *opt_hdr;\n  const b_coff_section_header *sects;\n  struct backtrace_view str_view;\n  int str_view_valid;\n  size_t str_size;\n  off_t str_off;\n  struct backtrace_view syms_view;\n  off_t syms_off;\n  size_t syms_size;\n  int syms_view_valid;\n  unsigned int syms_num;\n  unsigned int i;\n  struct debug_section_info sections[DEBUG_MAX];\n  off_t min_offset;\n  off_t max_offset;\n  struct backtrace_view debug_view;\n  int debug_view_valid;\n  int is_64;\n  uintptr_t image_base;\n  struct dwarf_sections dwarf_sections;\n\n  *found_sym = 0;\n  *found_dwarf = 0;\n\n  sects_view_valid = 0;\n  syms_view_valid = 0;\n  str_view_valid = 0;\n  debug_view_valid = 0;\n\n  if (!backtrace_get_view(state, descriptor, 0, 0x40, error_callback, data,\n                          &fhdr_view))\n    goto fail;\n\n  {\n    const unsigned char *vptr = fhdr_view.data;\n\n    if (vptr[0] == 'M' && vptr[1] == 'Z')\n      fhdr_off = coff_read4(vptr + 0x3c);\n    else\n      fhdr_off = 0;\n  }\n\n  backtrace_release_view(state, &fhdr_view, error_callback, data);\n\n  if (!backtrace_get_view(state, descriptor, fhdr_off,\n                          sizeof(b_coff_file_header) + 4, error_callback, data,\n                          &fhdr_view))\n    goto fail;\n\n  if (fhdr_off != 0) {\n    const char *magic = (const char *)fhdr_view.data;\n    magic_ok = memcmp(magic, \"PE\\0\", 4) == 0;\n    fhdr_off += 4;\n\n    memcpy(&fhdr, fhdr_view.data + 4, sizeof fhdr);\n  } else {\n    memcpy(&fhdr, fhdr_view.data, sizeof fhdr);\n\n    magic_ok = 0;\n  }\n  backtrace_release_view(state, &fhdr_view, error_callback, data);\n\n  if (!magic_ok) {\n    error_callback(data, \"executable file is not COFF\", 0);\n    goto fail;\n  }\n\n  sects_num = fhdr.number_of_sections;\n  syms_num = fhdr.number_of_symbols;\n\n  opt_sects_off = fhdr_off + sizeof(fhdr);\n  opt_sects_size = (fhdr.size_of_optional_header +\n                    sects_num * sizeof(b_coff_section_header));\n\n  if (!backtrace_get_view(state, descriptor, opt_sects_off, opt_sects_size,\n                          error_callback, data, &sects_view))\n    goto fail;\n  sects_view_valid = 1;\n  opt_hdr = (const b_coff_optional_header *)sects_view.data;\n  sects = (const b_coff_section_header *)(sects_view.data +\n                                          fhdr.size_of_optional_header);\n\n  is_64 = 0;\n  if (fhdr.size_of_optional_header > sizeof(*opt_hdr)) {\n    if (opt_hdr->magic == PE_MAGIC)\n      image_base = opt_hdr->u.pe.image_base;\n    else if (opt_hdr->magic == PEP_MAGIC) {\n      image_base = opt_hdr->u.pep.image_base;\n      is_64 = 1;\n    } else {\n      error_callback(data, \"bad magic in PE optional header\", 0);\n      goto fail;\n    }\n  } else\n    image_base = 0;\n\n  if (fhdr.pointer_to_symbol_table == 0) {\n    str_off = 0;\n    str_size = 0;\n    syms_num = 0;\n    syms_size = 0;\n  } else {\n    syms_off = fhdr.pointer_to_symbol_table;\n    syms_size = syms_num * SYM_SZ;\n\n    if (!backtrace_get_view(state, descriptor, syms_off, syms_size + 4,\n                            error_callback, data, &syms_view))\n      goto fail;\n    syms_view_valid = 1;\n\n    str_size = coff_read4(syms_view.data + syms_size);\n\n    str_off = syms_off + syms_size;\n\n    if (str_size > 4) {\n      if (!backtrace_get_view(state, descriptor, str_off, str_size,\n                              error_callback, data, &str_view))\n        goto fail;\n      str_view_valid = 1;\n    }\n  }\n\n  memset(sections, 0, sizeof sections);\n\n  for (i = 0; i < sects_num; ++i) {\n    const b_coff_section_header *s = sects + i;\n    unsigned int str_off;\n    int j;\n\n    if (s->name[0] == '/') {\n      str_off = atoi(s->name + 1);\n    } else\n      str_off = 0;\n\n    for (j = 0; j < (int)DEBUG_MAX; ++j) {\n      const char *dbg_name = debug_section_names[j];\n      int match;\n\n      if (str_off != 0)\n        match = coff_long_name_eq(dbg_name, str_off, &str_view);\n      else\n        match = coff_short_name_eq(dbg_name, s->name);\n      if (match) {\n        sections[j].offset = s->pointer_to_raw_data;\n        sections[j].size = s->virtual_size <= s->size_of_raw_data\n                               ? s->virtual_size\n                               : s->size_of_raw_data;\n        break;\n      }\n    }\n  }\n\n  if (syms_num != 0) {\n    struct coff_syminfo_data *sdata;\n\n    sdata = ((struct coff_syminfo_data *)backtrace_alloc(state, sizeof *sdata,\n                                                         error_callback, data));\n    if (sdata == NULL) goto fail;\n\n    if (!coff_initialize_syminfo(state, image_base, is_64, sects, sects_num,\n                                 syms_view.data, syms_size, str_view.data,\n                                 str_size, error_callback, data, sdata)) {\n      backtrace_free(state, sdata, sizeof *sdata, error_callback, data);\n      goto fail;\n    }\n\n    *found_sym = 1;\n\n    coff_add_syminfo_data(state, sdata);\n  }\n\n  backtrace_release_view(state, &sects_view, error_callback, data);\n  sects_view_valid = 0;\n  if (syms_view_valid) {\n    backtrace_release_view(state, &syms_view, error_callback, data);\n    syms_view_valid = 0;\n  }\n\n  min_offset = 0;\n  max_offset = 0;\n  for (i = 0; i < (int)DEBUG_MAX; ++i) {\n    off_t end;\n\n    if (sections[i].size == 0) continue;\n    if (min_offset == 0 || sections[i].offset < min_offset)\n      min_offset = sections[i].offset;\n    end = sections[i].offset + sections[i].size;\n    if (end > max_offset) max_offset = end;\n  }\n  if (min_offset == 0 || max_offset == 0) {\n    if (!backtrace_close(descriptor, error_callback, data)) goto fail;\n    *fileline_fn = coff_nodebug;\n    return 1;\n  }\n\n  if (!backtrace_get_view(state, descriptor, min_offset,\n                          max_offset - min_offset, error_callback, data,\n                          &debug_view))\n    goto fail;\n  debug_view_valid = 1;\n\n  if (!backtrace_close(descriptor, error_callback, data)) goto fail;\n  descriptor = -1;\n\n  for (i = 0; i < (int)DEBUG_MAX; ++i) {\n    size_t size = sections[i].size;\n    dwarf_sections.size[i] = size;\n    if (size == 0)\n      dwarf_sections.data[i] = NULL;\n    else\n      dwarf_sections.data[i] = ((const unsigned char *)debug_view.data +\n                                (sections[i].offset - min_offset));\n  }\n\n  if (!backtrace_dwarf_add(state, 0, &dwarf_sections, 0, NULL, error_callback,\n                           data, fileline_fn, NULL))\n    goto fail;\n\n  *found_dwarf = 1;\n\n  return 1;\n\nfail:\n  if (sects_view_valid)\n    backtrace_release_view(state, &sects_view, error_callback, data);\n  if (str_view_valid)\n    backtrace_release_view(state, &str_view, error_callback, data);\n  if (syms_view_valid)\n    backtrace_release_view(state, &syms_view, error_callback, data);\n  if (debug_view_valid)\n    backtrace_release_view(state, &debug_view, error_callback, data);\n  if (descriptor != -1) backtrace_close(descriptor, error_callback, data);\n  return 0;\n}\n\nint backtrace_initialize(struct backtrace_state *state,\n                         const char *filename ATTRIBUTE_UNUSED, int descriptor,\n                         backtrace_error_callback error_callback, void *data,\n                         fileline *fileline_fn) {\n  int ret;\n  int found_sym;\n  int found_dwarf;\n  fileline coff_fileline_fn;\n\n  ret = coff_add(state, descriptor, error_callback, data, &coff_fileline_fn,\n                 &found_sym, &found_dwarf);\n  if (!ret) return 0;\n\n  if (!state->threaded) {\n    if (found_sym)\n      state->syminfo_fn = coff_syminfo;\n    else if (state->syminfo_fn == NULL)\n      state->syminfo_fn = coff_nosyms;\n  } else {\n    if (found_sym)\n      backtrace_atomic_store_pointer(&state->syminfo_fn, coff_syminfo);\n    else\n      (void)__sync_bool_compare_and_swap(&state->syminfo_fn, NULL, coff_nosyms);\n  }\n\n  if (!state->threaded) {\n    if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)\n      *fileline_fn = coff_fileline_fn;\n  } else {\n    fileline current_fn;\n\n    current_fn = backtrace_atomic_load_pointer(&state->fileline_fn);\n    if (current_fn == NULL || current_fn == coff_nodebug)\n      *fileline_fn = coff_fileline_fn;\n  }\n\n  return 1;\n}\n\n// read.c:\n#include <errno.h>\n#include <stdlib.h>\n#include <sys/types.h>\n#include <unistd.h>\n\nint backtrace_get_view(struct backtrace_state *state, int descriptor,\n                       off_t offset, uint64_t size,\n                       backtrace_error_callback error_callback, void *data,\n                       struct backtrace_view *view) {\n  uint64_t got;\n  ssize_t r;\n\n  if ((uint64_t)(size_t)size != size) {\n    error_callback(data, \"file size too large\", 0);\n    return 0;\n  }\n\n  if (lseek(descriptor, offset, SEEK_SET) < 0) {\n    error_callback(data, \"lseek\", errno);\n    return 0;\n  }\n\n  view->base = backtrace_alloc(state, size, error_callback, data);\n  if (view->base == NULL) return 0;\n  view->data = view->base;\n  view->len = size;\n\n  got = 0;\n  while (got < size) {\n    r = read(descriptor, view->base, size - got);\n    if (r < 0) {\n      error_callback(data, \"read\", errno);\n      free(view->base);\n      return 0;\n    }\n    if (r == 0) break;\n    got += (uint64_t)r;\n  }\n\n  if (got < size) {\n    error_callback(data, \"file too short\", 0);\n    free(view->base);\n    return 0;\n  }\n\n  return 1;\n}\n\nvoid backtrace_release_view(struct backtrace_state *state,\n                            struct backtrace_view *view,\n                            backtrace_error_callback error_callback,\n                            void *data) {\n  backtrace_free(state, view->base, view->len, error_callback, data);\n  view->data = NULL;\n  view->base = NULL;\n}\n\n// alloc.c:\n#include <errno.h>\n#include <stdlib.h>\n#include <sys/types.h>\n\nvoid *backtrace_alloc(struct backtrace_state *state ATTRIBUTE_UNUSED,\n                      size_t size, backtrace_error_callback error_callback,\n                      void *data) {\n  void *ret;\n\n  ret = malloc(size);\n  if (ret == NULL) {\n    if (error_callback) error_callback(data, \"malloc\", errno);\n  }\n  return ret;\n}\n\nvoid backtrace_free(struct backtrace_state *state ATTRIBUTE_UNUSED, void *p,\n                    size_t size ATTRIBUTE_UNUSED,\n                    backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n                    void *data ATTRIBUTE_UNUSED) {\n  free(p);\n}\n\nvoid *backtrace_vector_grow(struct backtrace_state *state ATTRIBUTE_UNUSED,\n                            size_t size,\n                            backtrace_error_callback error_callback, void *data,\n                            struct backtrace_vector *vec) {\n  void *ret;\n\n  if (size > vec->alc) {\n    size_t alc;\n    void *base;\n\n    if (vec->size == 0)\n      alc = 32 * size;\n    else if (vec->size >= 4096)\n      alc = vec->size + 4096;\n    else\n      alc = 2 * vec->size;\n\n    if (alc < vec->size + size) alc = vec->size + size;\n\n    base = realloc(vec->base, alc);\n    if (base == NULL) {\n      error_callback(data, \"realloc\", errno);\n      return NULL;\n    }\n\n    vec->base = base;\n    vec->alc = alc - vec->size;\n  }\n\n  ret = (char *)vec->base + vec->size;\n  vec->size += size;\n  vec->alc -= size;\n  return ret;\n}\n\nvoid *backtrace_vector_finish(struct backtrace_state *state,\n                              struct backtrace_vector *vec,\n                              backtrace_error_callback error_callback,\n                              void *data) {\n  void *ret;\n\n  if (!backtrace_vector_release(state, vec, error_callback, data)) return NULL;\n  ret = vec->base;\n  vec->base = NULL;\n  vec->size = 0;\n  vec->alc = 0;\n  return ret;\n}\n\nint backtrace_vector_release(struct backtrace_state *state ATTRIBUTE_UNUSED,\n                             struct backtrace_vector *vec,\n                             backtrace_error_callback error_callback,\n                             void *data) {\n  vec->alc = 0;\n\n  if (vec->size == 0) {\n    free(vec->base);\n    vec->base = NULL;\n    return 1;\n  }\n\n  vec->base = realloc(vec->base, vec->size);\n  if (vec->base == NULL) {\n    error_callback(data, \"realloc\", errno);\n    return 0;\n  }\n\n  return 1;\n}\n"
  },
  {
    "path": "thirdparty/libgc/amalgamation.txt",
    "content": "The libgc source is distributed here as an amalgamation (https://sqlite.org/amalgamation.html).\nThis means that, rather than mirroring the entire bdwgc repo here, the amalgamate tool\nwas used to bundle all C files and local includes together into a single C file, which is\nmuch easier to handle.  This helps keep the V source distribution small, can reduce compile\ntimes by 3%-15%, and can help C compilers generate more optimized code.\n\nFor generating the libgc amalgamation, the following commands were used:\n\n    git clone https://github.com/ivmai/bdwgc.git\n    cd bdwgc\n    ./autogen.sh\n    ./configure --enable-threads=pthreads \\\n        --enable-static \\\n        --enable-shared=no \\\n        --enable-thread-local-alloc=no \\\n        --enable-parallel-mark \\\n        --enable-single-obj-compilation \\\n        --enable-gc-debug\n        \n    ../../../cmd/tools/amalgamate -o ../gc.c \\\n        -b atomic_ops.h \\\n        -b gc/gc.h \\\n        -b gc/gc_backptr.h \\\n        -b gc/gc_disclaim.h \\\n        -b gc/gc_gcj.h \\\n        -b gc/gc_inline.h \\\n        -b gc/gc_mark.h \\\n        -b gc/gc_pthread_redirects.h \\\n        -b gc/gc_tiny_fl.h \\\n        -b gc/gc_typed.h \\\n        -b gc/javaxfc.h \\\n        -b il/PCR_IL.h \\\n        -b mm/PCR_MM.h \\\n        -b psp2-support.h \\\n        -b stubinfo.h \\\n        -b th/PCR_ThCtl.h \\\n        -b vd/PCR_VD.h \\\n        -s include \\\n        -s include/private \\\n        extra/gc.c\n\nThe updated header files are then copied into the include/gc directory.  We can delete\ninclude/gc/gc_cpp.h since this header is not needed by V.  And, we can remove the git\nrepo for bdwgc.\n\n    cp include/gc/*.h ../include/gc\n    cd ..\n    rm include/gc/gc_cpp.h\n    rm -rf bdwgc\n\n"
  },
  {
    "path": "thirdparty/libgc/gc.c",
    "content": "/*\n * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.\n * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.\n * All rights reserved.\n * Copyright (c) 2009-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * This file could be used for the following purposes:\n *   - get the complete collector as a single link object file (module);\n *   - enable more compiler optimizations.\n *\n * Tip: to get the highest level of compiler optimizations, the typical\n * compiler options to use (assuming gcc) are:\n * `-O3 -march=native -fprofile-generate`\n *\n * Warning: gcc for Linux (for C++ clients only): use `-fexceptions` both for\n * the collector library and the client as otherwise `GC_thread_exit_proc()`\n * is not guaranteed to be invoked (see the comments in `pthread_start.c`\n * file).\n */\n\n#define GC_SINGLE_OBJ_BUILD\n\n#ifndef __cplusplus\n/* `static` is desirable here for more efficient linkage. */\n/* TODO: Enable this in case of the compilation as C++ code. */\n#  define GC_INNER STATIC\n#  define GC_EXTERN GC_INNER\n/* Note: `STATIC` macro is defined in `gcconfig.h` file. */\n#endif\n\n/* Small files go first... */\n/*\n * Copyright (c) 2001 by Hewlett-Packard Company. All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1997 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999 by Hewlett-Packard Company.  All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * This is mostly an internal header file.  Typical clients should\n * not use it.  Clients that define their own object kinds with\n * debugging allocators will probably want to include this, however.\n * No attempt is made to keep the namespace clean.  This should not be\n * included from header files that are frequently included by clients.\n */\n\n#ifndef GC_DBG_MLC_H\n#define GC_DBG_MLC_H\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n#ifndef GC_PRIVATE_H\n#define GC_PRIVATE_H\n\n#ifdef HAVE_CONFIG_H\n/* include/config.h.  Generated from config.h.in by configure.  */\n/* include/config.h.in.  Generated from configure.ac by autoheader.  */\n\n/* Define to recognize all pointers to the interior of objects. */\n#define ALL_INTERIOR_POINTERS 1\n\n/* AO load, store and/or test-and-set primitives are implemented in\n   `libatomic_ops` using locks. */\n/* #undef BASE_ATOMIC_OPS_EMULATED */\n\n/* Erroneously cleared dirty bits checking. Use only for debugging of the\n   incremental collector. */\n/* #undef CHECKSUMS */\n\n/* Define to discover thread stack bounds on Darwin without trying to walk the\n   frames on the stack. */\n/* #undef DARWIN_DONT_PARSE_STACK */\n\n/* Define to force debug headers on all objects. */\n#define DBG_HDRS_ALL 1\n\n/* Do not use user32.dll import library (Win32). */\n/* #undef DONT_USE_USER32_DLL */\n\n/* Define to support pointer mask/shift set at runtime. */\n/* #undef DYNAMIC_POINTER_MASK */\n\n/* Define to enable eCos target support. */\n/* #undef ECOS */\n\n/* Wine `getenv` may not return `NULL` for missing entry. */\n/* #undef EMPTY_GETENV_RESULTS */\n\n/* Define to enable alternative finalization interface. */\n#define ENABLE_DISCLAIM 1\n\n/* Define to enable internal debug assertions. */\n/* #undef GC_ASSERTIONS */\n\n/* Define to enable atomic uncollectible allocation. */\n#define GC_ATOMIC_UNCOLLECTABLE 1\n\n/* Use GCC atomic intrinsics instead of `libatomic_ops` primitives. */\n#define GC_BUILTIN_ATOMIC 1\n\n/* Define to build dynamic libraries with only API symbols exposed. */\n/* #undef GC_DLL */\n\n/* Skip the initial guess of data root sets. */\n/* #undef GC_DONT_REGISTER_MAIN_STATIC_DATA */\n\n/* Define to turn on `GC_suspend_thread` support (Linux only). */\n#define GC_ENABLE_SUSPEND_THREAD 1\n\n/* Define to include support for `gcj`. */\n#define GC_GCJ_SUPPORT 1\n\n/* Define if backtrace information is supported. */\n/* #undef GC_HAVE_BUILTIN_BACKTRACE */\n\n/* Define to use `pthread_sigmask` function if needed. */\n/* #undef GC_HAVE_PTHREAD_SIGMASK */\n\n/* Enable Win32 `DllMain`-based approach of threads registering. */\n/* #undef GC_INSIDE_DLL */\n\n/* Missing execinfo.h header. */\n/* #undef GC_MISSING_EXECINFO_H */\n\n/* Missing `sigsetjmp` function. */\n/* #undef GC_NO_SIGSETJMP */\n\n/* Disable threads discovery in the collector. */\n/* #undef GC_NO_THREADS_DISCOVERY */\n\n/* Read environment variables from the GC 'env' file. */\n/* #undef GC_READ_ENV_FILE */\n\n/* Define and export `GC_wcsdup` function. */\n#define GC_REQUIRE_WCSDUP 1\n\n/* Define to support platform-specific threads. */\n#define GC_THREADS 1\n\n/* Force the GC to use signals based on `SIGRTMIN+k`. */\n/* #undef GC_USESIGRT_SIGNALS */\n\n/* Define to cause the collector to redefine `malloc` and intercepted\n   `pthreads` routines with their real names while using `dlsym` to refer to\n   the original routines. */\n/* #undef GC_USE_DLOPEN_WRAP */\n\n/* The major version number of this GC release. */\n#define GC_VERSION_MAJOR 8\n\n/* The micro version number of this GC release. */\n#define GC_VERSION_MICRO 0\n\n/* The minor version number of this GC release. */\n#define GC_VERSION_MINOR 3\n\n/* Define to support pthreads-win32 or winpthreads. */\n/* #undef GC_WIN32_PTHREADS */\n\n/* Define to install `pthread_atfork` handlers by default. */\n#define HANDLE_FORK 1\n\n/* Define to use `dladdr` function. */\n#define HAVE_DLADDR 1\n\n/* Define to 1 if you have the <dlfcn.h> header file. */\n#define HAVE_DLFCN_H 1\n\n/* Define to 1 if you have the 'dl_iterate_phdr' function. */\n/* #undef HAVE_DL_ITERATE_PHDR */\n\n/* Define to 1 if you have the <inttypes.h> header file. */\n#define HAVE_INTTYPES_H 1\n\n/* `libatomic_ops` `AO_or` primitive implementation is lock-free. */\n/* #undef HAVE_LOCKFREE_AO_OR */\n\n/* Define to use `pthread_setname_np(const char *)` function. */\n#define HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID 1\n\n/* Define to use `pthread_setname_np(pthread_t, const char *)` function. */\n/* #undef HAVE_PTHREAD_SETNAME_NP_WITH_TID */\n\n/* Define to use `pthread_setname_np(pthread_t, const char *, void *)`\n   function. */\n/* #undef HAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG */\n\n/* Define to use `pthread_set_name_np(pthread_t, const char *)` function. */\n/* #undef HAVE_PTHREAD_SET_NAME_NP */\n\n/* Define to 1 if you have the <stdint.h> header file. */\n#define HAVE_STDINT_H 1\n\n/* Define to 1 if you have the <stdio.h> header file. */\n#define HAVE_STDIO_H 1\n\n/* Define to 1 if you have the <stdlib.h> header file. */\n#define HAVE_STDLIB_H 1\n\n/* Define to 1 if you have the <strings.h> header file. */\n#define HAVE_STRINGS_H 1\n\n/* Define to 1 if you have the <string.h> header file. */\n#define HAVE_STRING_H 1\n\n/* Define to 1 if you have the <sys/stat.h> header file. */\n#define HAVE_SYS_STAT_H 1\n\n/* Define to 1 if you have the <sys/types.h> header file. */\n#define HAVE_SYS_TYPES_H 1\n\n/* Define to 1 if you have the <unistd.h> header file. */\n#define HAVE_UNISTD_H 1\n\n/* Do not define `DYNAMIC_LOADING` even if supported (i.e., build the\n   collector with disabled tracing of dynamic library data roots). */\n/* #undef IGNORE_DYNAMIC_LOADING */\n\n/* Define to make it somewhat safer by default to finalize objects out of\n   order by specifying a nonstandard finalization mark procedure. */\n#define JAVA_FINALIZATION 1\n\n/* Define to save back-pointers in debugging headers. */\n#define KEEP_BACK_PTRS 1\n\n/* Define to optimize for large heaps or root sets. */\n/* #undef LARGE_CONFIG */\n\n/* Define to the sub-directory where libtool stores uninstalled libraries. */\n#define LT_OBJDIR \".libs/\"\n\n/* Define to build the collector with the support of the functionality to\n   print max length of chain through unreachable objects ending in a reachable\n   one. */\n/* #undef MAKE_BACK_GRAPH */\n\n/* Number of sequential garbage collections during those a candidate block for\n   unmapping should be marked as free. */\n#define MUNMAP_THRESHOLD 7\n\n/* Define to not use system clock (cross compiling). */\n/* #undef NO_CLOCK */\n\n/* Disable debugging, like `GC_dump` and its callees. */\n/* #undef NO_DEBUGGING */\n\n/* Define to make the collector not allocate executable memory by default. */\n#define NO_EXECUTE_PERMISSION 1\n\n/* Missing `getcontext` function. */\n/* #undef NO_GETCONTEXT */\n\n/* Prohibit installation of `pthread_atfork` handlers. */\n/* #undef NO_HANDLE_FORK */\n\n/* Name of package */\n#define PACKAGE \"gc\"\n\n/* Define to the address where bug reports for this package should be sent. */\n#define PACKAGE_BUGREPORT \"https://github.com/bdwgc/bdwgc/issues\"\n\n/* Define to the full name of this package. */\n#define PACKAGE_NAME \"gc\"\n\n/* Define to the full name and version of this package. */\n#define PACKAGE_STRING \"gc 8.3.0\"\n\n/* Define to the one symbol short name of this package. */\n#define PACKAGE_TARNAME \"gc\"\n\n/* Define to the home page for this package. */\n#define PACKAGE_URL \"\"\n\n/* Define to the version of this package. */\n#define PACKAGE_VERSION \"8.3.0\"\n\n/* Define to enable parallel marking. */\n#define PARALLEL_MARK 1\n\n/* If defined, redirect `free` to this function. */\n/* #undef REDIRECT_FREE */\n\n/* If defined, redirect `malloc` to this function. */\n/* #undef REDIRECT_MALLOC */\n\n/* If defined, redirect `realloc` to this function. */\n/* #undef REDIRECT_REALLOC */\n\n/* The number of caller frames saved when allocating with the debugging API.\n   */\n/* #undef SAVE_CALL_COUNT */\n\n/* Shorten the headers to minimize object size at the expense of checking for\n   writes past the end. */\n/* #undef SHORT_DBG_HDRS */\n\n/* Define to tune the collector for small heap sizes. */\n/* #undef SMALL_CONFIG */\n\n/* Define to 1 if all of the C89 standard headers exist (not just the ones\n   required in a freestanding environment). This macro is provided for\n   backward compatibility; new code need not use it. */\n#define STDC_HEADERS 1\n\n/* Define to work around a Solaris 5.3 bug (see dyn_load.c). */\n/* #undef SUNOS53_SHARED_LIB */\n\n/* Define to enable thread-local allocation optimization. */\n/* #undef THREAD_LOCAL_ALLOC */\n\n/* Use Unicode (W) variant of Win32 API instead of ASCII (A) one. */\n/* #undef UNICODE */\n\n/* Define to use of compiler-support for thread-local variables. */\n/* #undef USE_COMPILER_TLS */\n\n/* Define to use `mmap` instead of `sbrk` to expand the heap. */\n#define USE_MMAP 1\n\n/* Define to return memory to OS with `munmap` calls. */\n#define USE_MUNMAP 1\n\n/* Use `rwlock` for the allocator lock instead of mutex. */\n/* #undef USE_RWLOCK */\n\n/* Define to use Win32 `VirtualAlloc` (instead of `sbrk` or `mmap`) to expand\n   the heap. */\n/* #undef USE_WINALLOC */\n\n/* Define to support tracking `GC_malloc` and friends for heap profiling\n   tools. */\n/* #undef VALGRIND_TRACKING */\n\n/* Version number of package */\n#define VERSION \"8.3.0\"\n\n/* The POSIX feature macro. */\n/* #undef _POSIX_C_SOURCE */\n\n/* Indicates the use of `pthreads` (NetBSD). */\n/* #undef _PTHREADS */\n\n/* Required define if using POSIX threads. */\n#define _REENTRANT 1\n\n/* Define to '__inline__' or '__inline' if that's what the C compiler\n   calls it, or to nothing if 'inline' is not supported under any name.  */\n#ifndef __cplusplus\n/* #undef inline */\n#endif\n\n#endif\n\n#if !defined(GC_BUILD) && !defined(NOT_GCBUILD)\n#  define GC_BUILD\n#endif\n\n#if (defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) \\\n     || defined(__CYGWIN__) || defined(HAVE_DLADDR)               \\\n     || (defined(__COSMOPOLITAN__) && defined(USE_MUNMAP))        \\\n     || defined(GC_HAVE_PTHREAD_SIGMASK)                          \\\n     || defined(HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID)              \\\n     || defined(HAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG)         \\\n     || defined(HAVE_PTHREAD_SETNAME_NP_WITH_TID))                \\\n    && !defined(_GNU_SOURCE)\n/* Cannot test `LINUX`, since this must be defined before other includes. */\n#  define _GNU_SOURCE 1\n#endif\n\n#if defined(__INTERIX) && !defined(_ALL_SOURCE)\n#  define _ALL_SOURCE 1\n#endif\n\n#if (defined(DGUX) && defined(GC_THREADS) || defined(DGUX386_THREADS) \\\n     || defined(GC_DGUX386_THREADS))                                  \\\n    && !defined(_USING_POSIX4A_DRAFT10)\n#  define _USING_POSIX4A_DRAFT10 1\n#endif\n\n#if defined(__MINGW32__) && !defined(__MINGW_EXCPT_DEFINE_PSDK) \\\n    && defined(__i386__)                                        \\\n    && defined(GC_EXTERN) /*< defined in `extra/gc.c` file */\n/* See the description in `mark.c` file. */\n#  define __MINGW_EXCPT_DEFINE_PSDK 1\n#endif\n\n#if defined(NO_DEBUGGING) && !defined(GC_ASSERTIONS) && !defined(NDEBUG)\n/* To turn off assertion checking (in `atomic_ops.h` file). */\n#  define NDEBUG 1\n#endif\n\n#ifndef GC_H\n#  include \"gc/gc.h\"\n#endif\n\n#include <stdlib.h>\n#if !defined(sony_news)\n#  include <stddef.h>\n#endif\n\n#ifdef DGUX\n#  include <sys/resource.h>\n#  include <sys/time.h>\n#endif\n\n#ifdef BSD_TIME\n#  include <sys/resource.h>\n#  include <sys/time.h>\n#endif\n\n#ifdef PARALLEL_MARK\n#  define AO_REQUIRE_CAS\n#  if !defined(__GNUC__) && !defined(AO_ASSUME_WINDOWS98)\n#    define AO_ASSUME_WINDOWS98\n#  endif\n#endif\n\n#include \"gc/gc_mark.h\"\n#include \"gc/gc_tiny_fl.h\"\n\ntypedef GC_word word;\n\n#ifndef PTR_T_DEFINED\n/*\n * A generic pointer to which we can add byte displacements and which\n * can be used for address comparisons.\n */\ntypedef char *ptr_t;\n#  define PTR_T_DEFINED\n#endif\n\n#ifndef SIZE_MAX\n#  include <limits.h>\n#endif\n#if defined(SIZE_MAX) && !defined(CPPCHECK)\n/*\n * A constant representing maximum value for `size_t` type.  Note: an extra\n * cast is used to workaround some buggy `SIZE_MAX` definitions.\n */\n#  define GC_SIZE_MAX ((size_t)SIZE_MAX)\n#else\n#  define GC_SIZE_MAX (~(size_t)0)\n#endif\n\n#if (GC_GNUC_PREREQ(3, 0) || defined(__clang__)) && !defined(LINT2)\n/* Equivalent to `e`, but predict that usually `e` is true (false). */\n#  define LIKELY(e) __builtin_expect(e, 1 /* `TRUE` */)\n#  define UNLIKELY(e) __builtin_expect(e, 0 /* `FALSE` */)\n#else\n#  define LIKELY(e) (e)\n#  define UNLIKELY(e) (e)\n#endif /* __GNUC__ */\n\n/*\n * Saturated addition of `size_t` values.  Used to avoid value wrap around\n * on overflow.  The arguments should have no side effects.\n */\n#define SIZET_SAT_ADD(a, b) \\\n  (LIKELY((a) < GC_SIZE_MAX - (b)) ? (a) + (b) : GC_SIZE_MAX)\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2000-2004 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2009-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * This header is private to the collector.  It is almost always\n * included from `gc_priv.h` file.  However it is possible to include\n * it by itself if just the configuration macros are needed.  In that\n * case, a few declarations relying on types declared in `gc_priv.h`\n * file will be omitted.\n */\n\n#ifndef GCCONFIG_H\n#define GCCONFIG_H\n\n#ifndef GC_H\n#  ifdef HAVE_CONFIG_H\n#  endif\n\n\n#endif\n\n#ifdef CPPCHECK\n#  undef CLOCKS_PER_SEC\n#  undef FIXUP_POINTER\n#  undef POINTER_MASK\n#  undef POINTER_SHIFT\n#  undef REDIRECT_REALLOC\n#  undef _MAX_PATH\n#endif\n\n#ifndef PTR_T_DEFINED\ntypedef char *ptr_t;\n#  define PTR_T_DEFINED\n#endif\n\n#if !defined(sony_news)\n#  include <stddef.h> /*< for `size_t`, etc. */\n#endif\n\n/*\n * Note: only wrap our own declarations, and not the included headers;\n * in this case, wrap our entire file, but temporarily unwrap/rewrap\n * around `#include` entities; macros do not need such wrapping.\n */\n#ifdef __cplusplus\n#  define EXTERN_C_BEGIN extern \"C\" {\n#  define EXTERN_C_END } /* extern \"C\" */\n#else\n#  define EXTERN_C_BEGIN\n#  define EXTERN_C_END\n#endif\n\nEXTERN_C_BEGIN\n\n/* Convenient internal macro to test version of Clang. */\n#if defined(__clang__) && defined(__clang_major__)\n#  define GC_CLANG_PREREQ(major, minor) \\\n    ((__clang_major__ << 8) + __clang_minor__ >= ((major) << 8) + (minor))\n#  define GC_CLANG_PREREQ_FULL(major, minor, patchlevel)          \\\n    (GC_CLANG_PREREQ(major, (minor) + 1)                          \\\n     || (__clang_major__ == (major) && __clang_minor__ == (minor) \\\n         && __clang_patchlevel__ >= (patchlevel)))\n#else\n#  define GC_CLANG_PREREQ(major, minor) 0 /*< `FALSE` */\n#  define GC_CLANG_PREREQ_FULL(major, minor, patchlevel) 0\n#endif\n\n/*\n * Machine-dependent parameters.  Some tuning parameters can be found\n * near the top of `gc_priv.h` file.\n */\n\n/* Machine-specific parts contributed by various people.  See `README` file. */\n\n#if defined(__ANDROID__) && !defined(HOST_ANDROID)\n/* A Linux-based OS.  `__ANDROID__` macro is defined by Android NDK gcc. */\n#  define HOST_ANDROID 1\n#endif\n\n#if defined(TIZEN) && !defined(HOST_TIZEN)\n/* A Linux-based OS. */\n#  define HOST_TIZEN 1\n#endif\n\n#if defined(__SYMBIAN32__) && !defined(SYMBIAN)\n#  define SYMBIAN\n#  ifdef __WINS__\n#    pragma data_seg(\".data2\")\n#  endif\n#endif\n\n/* First a unified test for Linux. */\n#if (defined(linux) || defined(__linux__) || defined(HOST_ANDROID) \\\n     || defined(HOST_TIZEN))                                       \\\n    && !defined(LINUX) && !defined(__native_client__)\n#  define LINUX\n#endif\n\n/* And one for NetBSD. */\n#if defined(__NetBSD__)\n#  define NETBSD\n#endif\n\n/* And one for OpenBSD. */\n#if defined(__OpenBSD__)\n#  define OPENBSD\n#endif\n\n/* And one for FreeBSD. */\n#if (defined(__FreeBSD__) || defined(__DragonFly__) \\\n     || defined(__FreeBSD_kernel__))                \\\n    && !defined(FREEBSD)                            \\\n    && !defined(GC_NO_FREEBSD) /*< Orbis compiler defines `__FreeBSD__` */\n#  define FREEBSD\n#endif\n\n#if defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD)\n#  define ANY_BSD\n#endif\n\n#if defined(__COSMOPOLITAN__)\n#  define COSMO\n#endif\n\n#if defined(__EMBOX__)\n#  define EMBOX\n#endif\n\n#if defined(__KOS__)\n#  define KOS\n#endif\n\n#if defined(__QNX__) && !defined(QNX)\n#  define QNX\n#endif\n\n#if defined(__serenity__)\n#  define SERENITY\n#endif\n\n/* And one for Darwin. */\n#if defined(macosx) || (defined(__APPLE__) && defined(__MACH__))\n#  define DARWIN\nEXTERN_C_END\n#  include <TargetConditionals.h>\nEXTERN_C_BEGIN\n#endif\n\n/* Determine the machine type. */\n#if defined(__native_client__)\n#  define NACL\n#  if !defined(__portable_native_client__) && !defined(__arm__)\n#    define I386\n#    define mach_type_known\n#  else\n/* Here we will rely upon arch-specific defines. */\n#  endif\n#endif\n#if defined(__aarch64__) && !defined(ANY_BSD) && !defined(COSMO) \\\n    && !defined(DARWIN) && !defined(LINUX) && !defined(KOS)      \\\n    && !defined(NN_BUILD_TARGET_PLATFORM_NX) && !defined(QNX)    \\\n    && !defined(SERENITY) && !defined(_WIN32)\n#  define AARCH64\n#  define NOSYS\n#  define mach_type_known\n#endif\n#if defined(__arm) || defined(__arm__) || defined(__thumb__)\n#  define ARM32\n#  if defined(NACL) || defined(SYMBIAN)\n#    define mach_type_known\n#  elif !defined(ANY_BSD) && !defined(DARWIN) && !defined(LINUX)             \\\n      && !defined(QNX) && !defined(NN_PLATFORM_CTR)                          \\\n      && !defined(SN_TARGET_PSP2) && !defined(_WIN32) && !defined(__CEGCC__) \\\n      && !defined(GC_NO_NOSYS)\n#    define NOSYS\n#    define mach_type_known\n#  endif\n#endif\n#if defined(__riscv) && !defined(ANY_BSD) && !defined(LINUX)\n#  define RISCV\n#  define NOSYS\n#  define mach_type_known\n#endif\n#if defined(vax) || defined(__vax__)\n#  define VAX\n#  ifdef ultrix\n#    define ULTRIX\n#  else\n#    define BSD\n#  endif\n#  define mach_type_known\n#endif\n#if defined(NETBSD) && defined(__vax__)\n#  define VAX\n#  define mach_type_known\n#endif\n#if (defined(mips) || defined(__mips) || defined(_mips)) \\\n    && !defined(__TANDEM) && !defined(ANY_BSD) && !defined(LINUX)\n#  define MIPS\n#  if defined(nec_ews) || defined(_nec_ews)\n#    define EWS4800\n#    define mach_type_known\n#  elif defined(ultrix) || defined(__ultrix)\n#    define ULTRIX\n#    define mach_type_known\n#  elif !defined(_WIN32_WCE) && !defined(__CEGCC__) && !defined(__MINGW32CE__)\n#    define IRIX5 /*< or Irix 6.x */\n#    define mach_type_known\n#  endif /* !MSWINCE */\n#endif\n#if defined(DGUX) && (defined(i386) || defined(__i386__))\n#  define I386\n#  ifndef _USING_DGUX\n#    define _USING_DGUX\n#  endif\n#  define mach_type_known\n#endif\n#if defined(sequent) && (defined(i386) || defined(__i386__))\n#  define I386\n#  define SEQUENT\n#  define mach_type_known\n#endif\n#if (defined(sun) || defined(__sun)) && (defined(i386) || defined(__i386__))\n#  define I386\n#  define SOLARIS\n#  define mach_type_known\n#endif\n#if (defined(sun) || defined(__sun)) && defined(__amd64)\n#  define X86_64\n#  define SOLARIS\n#  define mach_type_known\n#endif\n#if (defined(__OS2__) || defined(__EMX__)) && defined(__32BIT__)\n#  define I386\n#  define OS2\n#  define mach_type_known\n#endif\n#if (defined(sun) || defined(__sun)) && (defined(sparc) || defined(__sparc))\n/* SunOS 5.x */\nEXTERN_C_END\n#  include <errno.h>\nEXTERN_C_BEGIN\n#  define SPARC\n#  define SOLARIS\n#  define mach_type_known\n#elif defined(sparc) && defined(unix) && !defined(sun) && !defined(linux) \\\n    && !defined(ANY_BSD)\n#  define SPARC\n#  define DRSNX\n#  define mach_type_known\n#endif\n#if defined(_IBMR2) /* `&& defined(_AIX)` */\n#  define POWERPC\n#  define AIX\n#  define mach_type_known\n#endif\n#if defined(_M_XENIX) && defined(_M_SYSV) && defined(_M_I386)\n/* TODO: The above test may need refinement. */\n#  define I386\n#  if defined(_SCO_ELF)\n#    define SCO_ELF\n#  else\n#    define SCO\n#  endif\n#  define mach_type_known\n#endif\n#if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \\\n    || defined(hppa) || defined(__hppa__)\n#  define HP_PA\n#  if !defined(LINUX) && !defined(HPUX) && !defined(OPENBSD)\n#    define HPUX\n#  endif\n#  define mach_type_known\n#endif\n#if defined(__ia64) && (defined(_HPUX_SOURCE) || defined(__HP_aCC))\n#  define IA64\n#  ifndef HPUX\n#    define HPUX\n#  endif\n#  define mach_type_known\n#endif\n#if (defined(__BEOS__) || defined(__HAIKU__)) && defined(_X86_)\n#  define I386\n#  define HAIKU\n#  define mach_type_known\n#endif\n#if defined(__HAIKU__) && (defined(__amd64__) || defined(__x86_64__))\n#  define X86_64\n#  define HAIKU\n#  define mach_type_known\n#endif\n#if defined(__alpha) || defined(__alpha__)\n#  define ALPHA\n#  if !defined(ANY_BSD) && !defined(LINUX)\n#    define OSF1 /*< Compaq Tru64 UNIX (Digital UNIX) */\n#  endif\n#  define mach_type_known\n#endif\n#if defined(__rtems__) && (defined(i386) || defined(__i386__))\n#  define I386\n#  define RTEMS\n#  define mach_type_known\n#endif\n#if defined(NeXT) && defined(mc68000)\n#  define M68K\n#  define NEXT\n#  define mach_type_known\n#endif\n#if defined(NeXT) && (defined(i386) || defined(__i386__))\n#  define I386\n#  define NEXT\n#  define mach_type_known\n#endif\n#if defined(bsdi) && (defined(i386) || defined(__i386__))\n#  define I386\n#  define BSDI\n#  define mach_type_known\n#endif\n#if defined(__386BSD__) && !defined(mach_type_known)\n#  define I386\n#  define THREE86BSD\n#  define mach_type_known\n#endif\n#if defined(_CX_UX) && defined(_M88K)\n#  define M88K\n#  define CX_UX\n#  define mach_type_known\n#endif\n#if defined(DGUX) && defined(m88k)\n#  define M88K\n/* `DGUX` macro is already defined. */\n#  define mach_type_known\n#endif\n#if defined(_WIN32_WCE) || defined(__CEGCC__) || defined(__MINGW32CE__)\n/*\n * `SH3`, `SH4`, `MIPS` macros are already defined for the corresponding\n * architectures.\n */\n#  if defined(SH3) || defined(SH4)\n#    define SH\n#  endif\n#  if defined(x86) || defined(__i386__)\n#    define I386\n#  endif\n#  if defined(_M_ARM) || defined(ARM) || defined(_ARM_)\n#    define ARM32\n#  endif\n#  define MSWINCE\n#  define mach_type_known\n#else\n#  if ((defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300))          \\\n      || (defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__) \\\n          && !defined(__INTERIX) && !defined(SYMBIAN))                      \\\n      || defined(__MINGW32__)\n#    if defined(__LP64__) || defined(_M_X64)\n#      define X86_64\n#    elif defined(_M_ARM)\n#      define ARM32\n#    elif defined(_M_ARM64)\n#      define AARCH64\n#    else /* _M_IX86 */\n#      define I386\n#    endif\n#    ifdef _XBOX_ONE\n#      define MSWIN_XBOX1\n#    else\n#      ifndef MSWIN32\n#        define MSWIN32 /*< or Win64 */\n#      endif\n#      if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)\n#        define MSWINRT_FLAVOR\n#      endif\n#    endif\n#    define mach_type_known\n#  endif\n#  if defined(_MSC_VER) && defined(_M_IA64)\n#    define IA64\n/*\n * Really Win64, but we do not treat 64-bit variants as a different\n * platform.\n */\n#    define MSWIN32\n#  endif\n#endif /* !_WIN32_WCE && !__CEGCC__ && !__MINGW32CE__ */\n#if defined(__DJGPP__)\n#  define I386\n#  ifndef DJGPP\n/* MSDOS running the DJGPP port of gcc. */\n#    define DJGPP\n#  endif\n#  define mach_type_known\n#endif\n#if defined(__CYGWIN32__) || defined(__CYGWIN__)\n#  if defined(__LP64__)\n#    define X86_64\n#  else\n#    define I386\n#  endif\n#  define CYGWIN32\n#  define mach_type_known\n#endif /* __CYGWIN__ */\n#if defined(__INTERIX)\n#  define I386\n#  define INTERIX\n#  define mach_type_known\n#endif\n#if defined(_UTS) && !defined(mach_type_known)\n#  define S370\n#  define UTS4\n#  define mach_type_known\n#endif\n#if defined(__embedded__) && defined(PPC)\n#  define POWERPC\n#  define NOSYS\n#  define mach_type_known\n#endif\n#if defined(__WATCOMC__) && defined(__386__)\n#  define I386\n#  if !defined(OS2) && !defined(MSWIN32) && !defined(DOS4GW)\n#    if defined(__OS2__)\n#      define OS2\n#    elif defined(__WINDOWS_386__) || defined(__NT__)\n#      define MSWIN32\n#    else\n#      define DOS4GW\n#    endif\n#  endif\n#  define mach_type_known\n#endif /* __WATCOMC__ && __386__ */\n#if defined(__GNU__) && defined(__i386__)\n/* The Debian Hurd running on generic PC. */\n#  define HURD\n#  define I386\n#  define mach_type_known\n#endif\n#if defined(__GNU__) && defined(__x86_64__)\n#  define HURD\n#  define X86_64\n#  define mach_type_known\n#endif\n#if defined(__TANDEM)\n/* Nonstop S-series. */\n/* FIXME: Should recognize Integrity series? */\n#  define MIPS\n#  define NONSTOP\n#  define mach_type_known\n#endif\n#if defined(__tile__) && defined(LINUX)\n#  ifdef __tilegx__\n#    define TILEGX\n#  else\n#    define TILEPRO\n#  endif\n#  define mach_type_known\n#endif\n#if defined(NN_BUILD_TARGET_PLATFORM_NX)\n#  define AARCH64\n#  define NINTENDO_SWITCH\n#  define mach_type_known\n#endif\n#if defined(__EMSCRIPTEN__) || defined(EMSCRIPTEN)\n#  define WEBASSEMBLY\n#  ifndef EMSCRIPTEN\n#    define EMSCRIPTEN\n#  endif\n#  define mach_type_known\n#endif\n#if defined(__wasi__)\n/* The WebAssembly System Interface (WASI). */\n#  define WEBASSEMBLY\n#  define WASI\n#  define mach_type_known\n#endif\n\n#if defined(__aarch64__)                                      \\\n    && (defined(ANY_BSD) || defined(COSMO) || defined(DARWIN) \\\n        || defined(LINUX) || defined(KOS) || defined(QNX)     \\\n        || defined(SERENITY))\n#  define AARCH64\n#  define mach_type_known\n#elif defined(__arc__) && defined(LINUX)\n#  define ARC\n#  define mach_type_known\n#elif (defined(__arm) || defined(__arm__) || defined(__arm32__)               \\\n       || defined(__ARM__))                                                   \\\n    && (defined(ANY_BSD) || defined(DARWIN) || defined(LINUX) || defined(QNX) \\\n        || defined(NN_PLATFORM_CTR) || defined(SN_TARGET_PSP2))\n#  define ARM32\n#  define mach_type_known\n#elif defined(__avr32__) && defined(LINUX)\n#  define AVR32\n#  define mach_type_known\n#elif defined(__cris__) && defined(LINUX)\n#  ifndef CRIS\n#    define CRIS\n#  endif\n#  define mach_type_known\n#elif defined(__e2k__) && defined(LINUX)\n#  define E2K\n#  define mach_type_known\n#elif defined(__hexagon__) && defined(LINUX)\n#  define HEXAGON\n#  define mach_type_known\n#elif (defined(__i386__) || defined(i386) || defined(__X86__)) \\\n    && (defined(ANY_BSD) || defined(DARWIN) || defined(EMBOX)  \\\n        || defined(LINUX) || defined(QNX) || defined(SERENITY))\n#  define I386\n#  define mach_type_known\n#elif (defined(__ia64) || defined(__ia64__)) && defined(LINUX)\n#  define IA64\n#  define mach_type_known\n#elif defined(__loongarch__) && defined(LINUX)\n#  define LOONGARCH\n#  define mach_type_known\n#elif defined(__m32r__) && defined(LINUX)\n#  define M32R\n#  define mach_type_known\n#elif ((defined(__m68k__) || defined(m68k))      \\\n       && (defined(NETBSD) || defined(OPENBSD))) \\\n    || (defined(__mc68000__) && defined(LINUX))\n#  define M68K\n#  define mach_type_known\n#elif (defined(__mips) || defined(_mips) || defined(mips)) \\\n    && (defined(ANY_BSD) || defined(LINUX))\n#  define MIPS\n#  define mach_type_known\n#elif (defined(__NIOS2__) || defined(__NIOS2) || defined(__nios2__)) \\\n    && defined(LINUX)\n#  define NIOS2 /*< Altera NIOS2 */\n#  define mach_type_known\n#elif defined(__or1k__) && defined(LINUX)\n#  define OR1K /*< OpenRISC (or1k) */\n#  define mach_type_known\n#elif (defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) \\\n       || defined(__ppc64__) || defined(powerpc) || defined(powerpc64))   \\\n    && (defined(ANY_BSD) || defined(DARWIN) || defined(LINUX))\n#  define POWERPC\n#  define mach_type_known\n#elif defined(__riscv) && (defined(ANY_BSD) || defined(LINUX))\n#  define RISCV\n#  define mach_type_known\n#elif defined(__s390__) && defined(LINUX)\n#  define S390\n#  define mach_type_known\n#elif defined(__sh__) \\\n    && (defined(LINUX) || defined(NETBSD) || defined(OPENBSD))\n#  define SH\n#  define mach_type_known\n#elif (defined(__sparc) || defined(sparc)) \\\n    && (defined(ANY_BSD) || defined(LINUX))\n#  define SPARC\n#  define mach_type_known\n#elif defined(__sw_64__) && defined(LINUX)\n#  define SW_64\n#  define mach_type_known\n#elif (defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) \\\n       || defined(__X86_64__))                                        \\\n    && (defined(ANY_BSD) || defined(COSMO) || defined(DARWIN)         \\\n        || defined(LINUX) || defined(QNX) || defined(SERENITY))\n#  define X86_64\n#  define mach_type_known\n#endif\n\n/*\n * Feel free to add more clauses here.  Or manually define the machine\n * type here.  A machine type is characterized by the architecture.\n * Some machine types are further subdivided by OS.  Macros such as\n * `LINUX`, `FREEBSD`, etc. distinguish them.  The distinction in these\n * cases is usually the stack starting address.\n */\n\n#if !defined(mach_type_known) && !defined(CPPCHECK)\n#  error The collector has not been ported to this machine/OS combination\n#endif\n\n/*\n * The CPU architecture mapping is:\n *   - `AARCH64`: ARM AArch64 ILP32/64-bit (running `COSMO` environment,\n *     `DARWIN` (OS X or iOS), `KOS`, `LINUX`, `MSWIN32`, `NETBSD`,\n *     `NINTENDO_SWITCH`, `NOSYS` environment, `OPENBSD`, `QNX`, `SERENITY`);\n *   - `ALPHA`: DEC Alpha (running `FREEBSD`, `LINUX`, `NETBSD`, `OPENBSD`,\n *     `OSF1`);\n *   - `ARC`: Synopsys ARC (running `LINUX`);\n *   - `ARM32`: ARMv7 (running `DARWIN` (iOS), `FREEBSD`, `LINUX`, `MSWIN32`,\n *     `MSWINCE`, `NETBSD`, `NN_PLATFORM_CTR`, `NOSYS` environment,\n *     `OPENBSD`, `QNX`, `SN_TARGET_PSP2`, `SYMBIAN`);\n *   - `AVR32`: Atmel RISC (running `LINUX`);\n *   - `CRIS`: Axis Etrax (running `LINUX`);\n *   - `E2K`: Elbrus 2000 32/64-bit (running `LINUX`);\n *   - `HEXAGON`: Qualcomm Hexagon (running `LINUX`);\n *   - `HP_PA`: HP9000/700 and HP9000/800 32/64-bit (running `HPUX`, `LINUX`,\n *     `OPENBSD`);\n *   - `I386`: Intel 486/586/686 (running `BSDI`, `CYGWIN32` environment,\n *     `DARWIN` (macOS), `DGUX`, `DJGPP` environment, `DOS4GW` environment,\n *     `EMBOX`, `FREEBSD`, `HAIKU`, `HURD`, `INTERIX`, `LINUX`, `MSWIN32`,\n *     `MSWINCE`, `NACL` environment, `NETBSD`, `NEXT`, `OPENBSD`, `OS2`,\n *     `QNX`, `RTEMS`, `SCO`, `SCO_ELF`, `SEQUENT`, `SERENITY`, `SOLARIS`,\n *     `THREE86BSD`);\n *   - `IA64`: Intel IPF, e.g. Itanium 32/64-bit (running `HPUX`, `LINUX`,\n *     `MSWIN32`);\n *   - `LOONGARCH`: Loongson LoongArch 32/64-bit (running `LINUX`);\n *   - `M32R`: Renesas M32R (running `LINUX`);\n *   - `M68K`: Motorola 680x0 (running `LINUX`, `NETBSD`, `NEXT`, `OPENBSD`);\n *   - `M88K`: Motorola 88xx0 (running `CX_UX`, `DGUX`);\n *   - `MIPS`: R2000+ 32/64-bit (running `EWS4800`, `FREEBSD`, `IRIX5`,\n *     `LINUX`, `MSWINCE`, `NETBSD`, `NONSTOP`, `OPENBSD`, `ULTRIX`);\n *   - `NIOS2`: Altera NIOS2 (running `LINUX`);\n *   - `OR1K`: OpenRISC/or1k (running `LINUX`);\n *   - `POWERPC`: IBM/Apple PowerPC 32/64-bit (running `AIX`, `DARWIN`,\n *     `FREEBSD`, `LINUX`, `NETBSD`, `NOSYS` environment, `OPENBSD`,\n *     `SN_TARGET_PS3`);\n *   - `RISCV`: RISC-V 32/64-bit (running `FREEBSD`, `LINUX`, `NETBSD`,\n *     `NOSYS` environment, `OPENBSD`);\n *   - `S370`: A 370-like machine (running `UTS4`);\n *   - `S390`: A 390-like machine 32/64-bit (running `LINUX`);\n *   - `SH`: Hitachi SuperH (running `LINUX`, `MSWINCE`, `NETBSD`,\n *     `OPENBSD`);\n *   - `SH4`: Hitachi SH4 (running `MSWINCE`);\n *   - `SPARC`: SPARC v7/v8/v9 32/64-bit (running `DRSNX`, `FREEBSD`,\n *     `LINUX`, `NETBSD`, `OPENBSD`, `SOLARIS`);\n *   - `SW_64`: Sunway/Shenwei (running `LINUX`);\n *   - `TILEGX`: Tilera TILE-Gx 32/64-bit (running `LINUX`);\n *   - `TILEPRO`: Tilera TILEPro (running `LINUX`);\n *   - `VAX`: DEC VAX (running `BSD`, `ULTRIX`);\n *   - `WEBASSEMBLY`: WebAssembly/Wasm (running `EMSCRIPTEN` environment,\n *     `WASI` environment);\n *   - `X86_64`: AMD x86-64 ILP32/64-bit (running `COSMO` environment,\n *     `CYGWIN32` environment, `DARWIN` (macOS), `FREEBSD`, `HAIKU`,\n *     `HURD`, `LINUX`, `MSWIN32`, `MSWIN_XBOX1`, `NETBSD`, `OPENBSD`,\n *     `PLATFORM_GETMEM` environment, `QNX`, `SERENITY`, `SOLARIS`).\n */\n\n/*\n * For each architecture and OS, the following need to be defined:\n *\n * `CPP_WORDSZ` is a simple integer constant representing the word size\n * in bits.  We assume byte addressability, where a byte has 8 bits.\n * We also assume `CPP_WORDSZ` is either 32 or 64.\n * (We care about the length of a pointer address, not hardware\n * bus widths.  Thus a 64-bit processor with a C compiler that uses\n * 32-bit pointers should use `CPP_WORDSZ` of 32, not 64.)\n *\n * `CPP_PTRSZ` is the pointer size in bits.  For most of the supported\n * targets, it is equal to `CPP_WORDSZ`.\n *\n * `MACH_TYPE` is a string representation of the machine type.\n * `OS_TYPE` is analogous for the OS.\n *\n * `ALIGNMENT` is the largest `n`, such that all pointer are guaranteed\n * to be aligned on `n`-byte boundary.  Defining it to be 1 will always\n * work, but will perform poorly.  Should not be larger than size of\n * a pointer.\n *\n * `DATASTART` is the beginning of the data segment.  On some platforms\n * `SEARCH_FOR_DATA_START` is defined.  The latter will cause\n * `GC_data_start` to be set to an address determined by accessing data\n * backwards from `_end` until an unmapped page is found.  `DATASTART` will\n * be defined to be `GC_data_start`.   On UNIX-like systems, the collector\n * will scan the area between `DATASTART` and `DATAEND` for root pointers.\n *\n * `DATAEND`, if not `end`, where `end` is defined as `extern int end[]`.\n * RTH suggests gaining access to linker script synth'd values with\n * this idiom instead of `&end`, where `end` is defined as `extern int end`.\n * Otherwise, \"gcc will assume these are in .sdata/.sbss\" and it will, e.g.,\n * cause failures on `alpha*-*-*` with `-msmall-data` or `-fpic` or\n * `mips-*-*` without any special options.\n *\n * `STACKBOTTOM` is the cold end of the stack, which is usually the\n * highest address in the stack.\n * Under OS/2, we have other ways of finding thread stacks.\n * For each machine, the following should:\n *   1. Define `STACK_GROWS_UP` if the stack grows toward higher addresses;\n *   2. Define exactly one of\n *      - `STACKBOTTOM` (should be defined to be an expression),\n *      - `HEURISTIC1`,\n *      - `SPECIFIC_MAIN_STACKBOTTOM`,\n *      - `HEURISTIC2`.\n *\n * If `STACKBOTTOM` is defined, then its value will be used directly (as\n * the stack bottom).  If `SPECIFIC_MAIN_STACKBOTTOM` is defined, then it\n * will be determined with a specific method appropriate for the operating\n * system.  Currently we look first for `__libc_stack_end` (currently only\n * if `USE_LIBC_PRIVATES` is defined), and if that fails, read it from\n * `/proc` pseudo-file.  (If `USE_LIBC_PRIVATES` is not defined and\n * `NO_PROC_STAT` is defined, we revert to `HEURISTIC2`.)\n * If either of the last two macros are defined, then `STACKBOTTOM` is\n * computed during collector startup using one of the following two\n * heuristics:\n *   - `HEURISTIC1`: Take an address inside `GC_init`'s frame, and round it\n *     up to the next multiple of `STACK_GRAN`;\n *   - `HEURISTIC2`: Take an address inside `GC_init`'s frame, increment it\n *     repeatedly in small steps (decrement if `STACK_GROWS_UP`), and read\n *     the value at each location, remember the value when the first\n *     Segmentation violation or Bus error is signaled, round that to the\n *     nearest plausible page boundary, and use that instead of\n *     `STACKBOTTOM`.\n *\n * Gustavo Rodriguez-Rivera points out that on most (all?) UNIX machines,\n * the value of `environ` is a pointer that can serve as `STACKBOTTOM`.\n * I expect that `HEURISTIC2` can be replaced by this approach, which\n * interferes far less with debugging.  However it has the disadvantage that\n * it is confused by a `putenv()` call before the collector is initialized.\n * This could be dealt with by intercepting `putenv()`...\n *\n * If no expression for `STACKBOTTOM` can be found, and neither of the above\n * heuristics are usable, the collector can still be used with all of the\n * above undefined, provided one of the following is done:\n *   1. `GC_mark_roots` can be changed to somehow mark from the correct\n *      stack(s) without reference to `STACKBOTTOM`.  This is appropriate for\n *      use in conjunction with thread packages, since there will be multiple\n *      stacks.  (Allocating thread stacks in the heap, and treating them as\n *      ordinary heap data objects is also possible as a last resort.\n *      However, this is likely to introduce significant amounts of excess\n *      storage retention unless the dead parts of the thread stacks are\n *      periodically cleared.)\n *   2. Client code may set `GC_stackbottom` before calling any `GC_`\n *      routines.  If the author of the client code owns the main program,\n *      this could be accomplished by introducing a new `main` function,\n *      calling `GC_call_with_gc_active()` which sets `GC_stackbottom` and\n *      then calls the original (real) `main` function.\n *\n * Each architecture may also define the style of virtual dirty bit\n * implementation to be used:\n *   - `GWW_VDB`: use Win32 `GetWriteWatch` primitive;\n *   - `MPROTECT_VDB`: write-protect the heap and catch faults;\n *   - `PROC_VDB`: use the SVR4 `/proc` primitives to read dirty bits;\n *   - `SOFT_VDB`: use the Linux `/proc` primitives to track dirty bits.\n *\n * The first and second one may be combined, in which case a runtime\n * selection will be made, based on `GetWriteWatch` availability.\n *\n * An architecture may define `DYNAMIC_LOADING` if `dyn_load.c` file\n * implements `GC_register_dynamic_libraries()` for the architecture.\n *\n * An architecture may define `PREFETCH(x)` to preload the cache with `*x`.\n * This defaults to gcc built-in operation (or a no-op for other compilers).\n *\n * `GC_PREFETCH_FOR_WRITE(x)` is used if `*x` is about to be written.\n *\n * An architecture may also define `CLEAR_DOUBLE(x)` to be a fast way to\n * clear 2 pointers at `GC_malloc`-aligned address `x`.  The default\n * implementation is just to store two `NULL` pointers.\n *\n * `HEAP_START` may be defined as the initial address hint for `mmap`-based\n * allocation.\n */\n\n#ifdef LINUX\n/* TODO: FreeBSD too? */\nEXTERN_C_END\n#  include <features.h> /*< for `__GLIBC__` and `__GLIBC_MINOR__`, at least */\nEXTERN_C_BEGIN\n#endif\n\n/* Convenient internal macro to test `glibc` version (if compiled against). */\n#if defined(__GLIBC__) && defined(__GLIBC_MINOR__)\n#  define GC_GLIBC_PREREQ(major, minor) \\\n    ((__GLIBC__ << 8) + __GLIBC_MINOR__ >= ((major) << 8) + (minor))\n#else\n#  define GC_GLIBC_PREREQ(major, minor) 0 /*< `FALSE` */\n#endif\n\n/*\n * Align a `ptr_t` pointer down/up to a given boundary.  The latter should\n * be a power of two.\n */\n#if GC_CLANG_PREREQ(11, 0)\n#  define PTR_ALIGN_DOWN(p, b) __builtin_align_down(p, b)\n#  if defined(DARWIN) && defined(GC_SINGLE_OBJ_BUILD) && GC_CLANG_PREREQ(17, 0)\n/* Workaround a crash in Apple clang-17. */\n/* TODO: Disable for later clang versions when the bug is fixed. */\n#    define PTR_ALIGN_UP(p, b) \\\n      ((ptr_t)__builtin_align_up((GC_uintptr_t)(p), b))\n#  else\n#    define PTR_ALIGN_UP(p, b) __builtin_align_up(p, b)\n#  endif\n#else\n#  define PTR_ALIGN_DOWN(p, b) \\\n    ((ptr_t)((GC_uintptr_t)(p) & ~((GC_uintptr_t)(b) - (GC_uintptr_t)1)))\n#  define PTR_ALIGN_UP(p, b)                                           \\\n    ((ptr_t)(((GC_uintptr_t)(p) + (GC_uintptr_t)(b) - (GC_uintptr_t)1) \\\n             & ~((GC_uintptr_t)(b) - (GC_uintptr_t)1)))\n#endif\n\n/*\n * If available, we can use `__builtin_unwind_init()` to push the relevant\n * registers onto the stack.\n */\n#if GC_GNUC_PREREQ(2, 8)                                                   \\\n    && !GC_GNUC_PREREQ(11, 0) /*< broken at least in 11.2.0 on cygwin64 */ \\\n    && !defined(__INTEL_COMPILER) && !defined(__PATHCC__)                  \\\n    && !defined(__FUJITSU)                    /*< for FX10 system */       \\\n    && !(defined(POWERPC) && defined(DARWIN)) /*< for MacOS X 10.3.9 */    \\\n    && !defined(E2K) && !defined(RTEMS)                                    \\\n    && !defined(__ARMCC_VERSION) /*< does not exist in armcc gnu emu */    \\\n    && !(defined(__clang__)                                                \\\n         && defined(__ARM_ARCH_5TE__) /* clang-19 emits `vpush`/`vpop` */) \\\n    && (!defined(__clang__)                                                \\\n        || GC_CLANG_PREREQ(8, 0) /* was no-op in clang-3 at least */)\n#  define HAVE_BUILTIN_UNWIND_INIT\n#endif\n\n#if (defined(__CC_ARM) || defined(CX_UX) || defined(DJGPP) || defined(EMBOX) \\\n     || defined(EWS4800) || defined(LINUX) || defined(OS2) || defined(RTEMS) \\\n     || defined(UTS4) || defined(MSWIN32) || defined(MSWINCE)                \\\n     || (defined(NOSYS) && defined(RISCV)))                                  \\\n    && !defined(NO_UNDERSCORE_SETJMP)\n#  define NO_UNDERSCORE_SETJMP\n#endif\n\n/*\n * The common OS-specific definitions.  Should be applicable to all\n * (or most, at least) supported architectures.\n */\n\n#ifdef CYGWIN32\n#  define OS_TYPE \"CYGWIN32\"\n#  define RETRY_GET_THREAD_CONTEXT\n#  ifdef USE_WINALLOC\n#    define GWW_VDB\n#  elif defined(USE_MMAP)\n#    define USE_MMAP_ANON\n#  endif\n#endif /* CYGWIN32 */\n\n#ifdef COSMO\n#  define OS_TYPE \"COSMO\"\n#  ifndef USE_GET_STACKBASE_FOR_MAIN\n#    define USE_GET_STACKBASE_FOR_MAIN\n#  endif\nextern int __data_start[] __attribute__((__weak__));\n#  define DATASTART ((ptr_t)__data_start)\nextern int _end[];\n#  define DATAEND ((ptr_t)_end)\n#  define USE_MMAP_ANON\n#  ifndef HAVE_CLOCK_GETTIME\n#    define HAVE_CLOCK_GETTIME 1\n#  endif\n#  ifndef HAVE_PTHREAD_SETNAME_NP_WITH_TID\n/* Normally should be defined by `configure`, etc. */\n#    define HAVE_PTHREAD_SETNAME_NP_WITH_TID 1\n#  endif\n#  if !defined(GC_THREADS) || defined(NO_HANDLE_FORK) \\\n      || defined(GC_NO_CAN_CALL_ATFORK)\n#    define MPROTECT_VDB\n/* FIXME: Otherwise `gctest` crashes in child process. */\n#  endif\n/* FIXME: A deadlock occurs in markers, thus disabled for now. */\n#  undef PARALLEL_MARK\n#endif /* COSMO */\n\n#ifdef DARWIN\n#  define OS_TYPE \"DARWIN\"\n#  define DYNAMIC_LOADING\n/*\n * TODO: See `get_end(3)`, `get_etext` and `get_end` should not be used.\n * These are not used when `dyld` support is enabled (it is the default).\n */\n#  define DATASTART ((ptr_t)get_etext())\n#  define DATAEND ((ptr_t)get_end())\n#  define USE_MMAP_ANON\n/* There seems to be some issues with try-lock hanging on Darwin. */\n/* TODO: This should be looked into some more. */\n#  define NO_PTHREAD_TRYLOCK\n#  ifndef TARGET_OS_XR\n#    define TARGET_OS_XR 0\n#  endif\n#  ifndef TARGET_OS_VISION\n#    define TARGET_OS_VISION 0\n#  endif\n#endif /* DARWIN */\n\n#ifdef EMBOX\n#  define OS_TYPE \"EMBOX\"\nextern int _modules_data_start[], _apps_bss_end[];\n#  define DATASTART ((ptr_t)_modules_data_start)\n#  define DATAEND ((ptr_t)_apps_bss_end)\n/*\n * Note: the designated area might be quite large (several dozens of MBs)\n * as it includes `.data` and `.bss` of all apps and modules of the built\n * binary image.\n */\n#endif /* EMBOX */\n\n#ifdef FREEBSD\n#  define OS_TYPE \"FREEBSD\"\n#  define SPECIFIC_MAIN_STACKBOTTOM\n#  ifdef __ELF__\n#    define DYNAMIC_LOADING\n#  endif\n#  ifndef USE_MMAP\n/* `sbrk()` is not available. */\n#    define USE_MMAP 1\n#  endif\n#  if !defined(ALPHA) && !defined(SPARC)\nextern char etext[];\n#    define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)etext)\n#    define DATASTART_USES_XGETDATASTART\n#    ifndef REDIRECT_MALLOC\n#      define MPROTECT_VDB\n#    else\n/* Similar as on Linux, `fread()` might use `malloc()`. */\n#    endif\n#  endif\n#endif /* FREEBSD */\n\n#ifdef HAIKU\n#  define OS_TYPE \"HAIKU\"\n#  define DYNAMIC_LOADING\n/* Note: `DATASTART` is not used really, see `GC_register_main_static_data`. */\nextern int etext[];\n#  define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x1000)\n#  ifndef USE_GET_STACKBASE_FOR_MAIN\n#    define USE_GET_STACKBASE_FOR_MAIN\n#  endif\n#  define USE_MMAP_ANON\n/*\n * On Haiku R1, at least, `pthreads` locks never spin but always call\n * into the kernel if the lock cannot be acquired with a simple atomic\n * operation.  (Up to 5x overall performance improvement of the\n * collector is observed by forcing use of spin locks.)\n */\n#  ifndef USE_SPIN_LOCK\n#    define USE_SPIN_LOCK\n#  endif\n/*\n * TODO: `MPROTECT_VDB` is not working correctly on anything other than\n * recent nightly Haiku OS builds (as of Nov 2024), and also it is\n * considerably slower than regular collecting, so do not enable it for now.\n */\nEXTERN_C_END\n#  include <OS.h>\nEXTERN_C_BEGIN\n#  define GETPAGESIZE() (unsigned)B_PAGE_SIZE\n#  ifndef HAVE_CLOCK_GETTIME\n#    define HAVE_CLOCK_GETTIME 1\n#  endif\n#endif /* HAIKU */\n\n#ifdef HPUX\n#  define OS_TYPE \"HPUX\"\nextern int __data_start[];\n#  define DATASTART ((ptr_t)__data_start)\n#  ifdef USE_MMAP\n#    define USE_MMAP_ANON\n#  endif\n#  define DYNAMIC_LOADING\n#  define GETPAGESIZE() (unsigned)sysconf(_SC_PAGE_SIZE)\n#endif /* HPUX */\n\n#ifdef HURD\n#  define OS_TYPE \"HURD\"\n#  define HEURISTIC2\n#  define SEARCH_FOR_DATA_START\nextern int _end[];\n#  define DATAEND ((ptr_t)_end)\n/* TODO: `MPROTECT_VDB` is not quite working yet? */\n#  define DYNAMIC_LOADING\n#  define USE_MMAP_ANON\n#endif /* HURD */\n\n#ifdef LINUX\n#  define OS_TYPE \"LINUX\"\n#  if defined(FORCE_MPROTECT_BEFORE_MADVISE) || defined(PREFER_MMAP_PROT_NONE)\n#    define COUNT_UNMAPPED_REGIONS\n#  endif\n#  define RETRY_TKILL_ON_EAGAIN\n#  if !defined(MIPS) && !defined(POWERPC)\n#    define SPECIFIC_MAIN_STACKBOTTOM\n#  endif\n#  if defined(__ELF__) && !defined(IA64)\n#    define DYNAMIC_LOADING\n#  endif\n#  if defined(__ELF__) && !defined(ARC) && !defined(RISCV) && !defined(S390) \\\n      && !defined(TILEGX) && !defined(TILEPRO)\nextern int _end[];\n#    define DATAEND ((ptr_t)_end)\n#  endif\n#  if !defined(REDIRECT_MALLOC) && !defined(E2K)\n/* Requires Linux 2.3.47 or later. */\n#    define MPROTECT_VDB\n#  else\n/*\n * We seem to get random errors in the incremental mode, possibly because\n * the Linux threads implementation itself is a `malloc` client and cannot\n * deal with the signals.  `fread()` uses `malloc()` too.\n * In case of e2k, unless `-fsemi-spec-ld` (or `-O0`) option is passed\n * to gcc (both when compiling the collector library and the client),\n * a semi-speculative optimization may lead to `SIGILL` (with `ILL_ILLOPN`\n * `si_code`) instead of `SIGSEGV`.\n */\n#  endif\n#endif /* LINUX */\n\n#ifdef KOS\n#  define OS_TYPE \"KOS\"\n#  ifndef USE_GET_STACKBASE_FOR_MAIN\n/* Note: this requires `-lpthread` option. */\n#    define USE_GET_STACKBASE_FOR_MAIN\n#  endif\nextern int __data_start[];\n#  define DATASTART ((ptr_t)__data_start)\n#endif /* KOS */\n\n#ifdef MSWIN32\n#  define OS_TYPE \"MSWIN32\"\n/* `STACKBOTTOM` and `DATASTART` are handled specially in `os_dep.c` file. */\n#  if !defined(CPPCHECK)\n#    define DATAEND /*< not needed */\n#  endif\n#  if defined(USE_GLOBAL_ALLOC) && !defined(MSWINRT_FLAVOR)\n/* Cannot pass `MEM_WRITE_WATCH` to `GlobalAlloc()`. */\n#  else\n#    define GWW_VDB\n#  endif\n#endif\n\n#ifdef MSWINCE\n#  define OS_TYPE \"MSWINCE\"\n#  if !defined(CPPCHECK)\n#    define DATAEND /*< not needed */\n#  endif\n#endif\n\n#ifdef NACL\n#  define OS_TYPE \"NACL\"\n#  if defined(__GLIBC__)\n#    define DYNAMIC_LOADING\n#  endif\n#  define DATASTART MAKE_CPTR(0x10020000)\nextern int _end[];\n#  define DATAEND ((ptr_t)_end)\n#  define STACK_GRAN 0x10000\n#  define HEURISTIC1\n#  define NO_PTHREAD_GETATTR_NP\n#  define USE_MMAP_ANON\n/* FIXME: Not real page size. */\n#  define GETPAGESIZE() 65536\n#  define MAX_NACL_GC_THREADS 1024\n#endif /* NACL */\n\n#ifdef NETBSD\n#  define OS_TYPE \"NETBSD\"\n#  define HEURISTIC2\n#  ifdef __ELF__\n#    define SEARCH_FOR_DATA_START\n#    define DYNAMIC_LOADING\n#  elif !defined(MIPS)\n/* TODO: Probably do not exclude it. */\nextern char etext[];\n#    define DATASTART ((ptr_t)etext)\n#  endif\n#  define MPROTECT_VDB\n#endif /* NETBSD */\n\n#ifdef NEXT\n#  define OS_TYPE \"NEXT\"\n#  define DATASTART ((ptr_t)get_etext())\n#  define DATAEND /*< not needed */\n#  undef USE_MUNMAP\n#endif\n\n#ifdef OPENBSD\n#  define OS_TYPE \"OPENBSD\"\n#  ifndef GC_THREADS\n#    define HEURISTIC2\n#  endif\n#  ifdef __ELF__\nextern int __data_start[], _end[];\n#    define DATASTART ((ptr_t)__data_start)\n#    define DATAEND ((ptr_t)_end)\n#    define DYNAMIC_LOADING\n#  else\nextern char etext[];\n#    define DATASTART ((ptr_t)etext)\n#  endif\n#  define MPROTECT_VDB\n#endif /* OPENBSD */\n\n#ifdef QNX\n#  define OS_TYPE \"QNX\"\n#  define SA_RESTART 0\n#  ifndef SPECIFIC_MAIN_STACKBOTTOM\n/* TODO: This is not used by default. */\n#    define STACK_GRAN 0x1000000\n#    define HEURISTIC1\n#  endif\nextern char etext[];\n#  define DATASTART ((ptr_t)etext)\nextern int _end[];\n#  define DATAEND ((ptr_t)_end)\n#endif /* QNX */\n\n#ifdef SERENITY\n#  define OS_TYPE \"SERENITY\"\nextern int etext[], _end[];\n#  define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x1000)\n#  define DATAEND ((ptr_t)_end)\n#  define DYNAMIC_LOADING\n/* TODO: Enable `mprotect`-based VDB. */\n#  define USE_MMAP_ANON\n#endif /* SERENITY */\n\n#ifdef SOLARIS\n#  define OS_TYPE \"SOLARIS\"\nextern int _end[];\n#  define DATAEND ((ptr_t)_end)\n#  if !defined(USE_MMAP) && defined(REDIRECT_MALLOC)\n#    define USE_MMAP 1\n/*\n * Otherwise we now use `calloc()`.  `mmap()` may result in the heap\n * interleaved with thread stacks, which can result in excessive\n * black-listing.  `sbrk()` is unusable since it does not interact\n * correctly with the system `malloc()`.\n */\n#  endif\n#  ifdef USE_MMAP\n#    define HEAP_START ((word)0x40000000)\n#  else\n#    define HEAP_START ADDR(DATAEND)\n#  endif\n#  ifndef GC_THREADS\n#    define MPROTECT_VDB\n#  endif\n#  define DYNAMIC_LOADING\n/*\n * Define `STACKBOTTOM` as `(ptr_t)_start` worked through 2.7, but\n * reportedly breaks under 2.8.  It appears that the stack base is\n * a property of the executable, so this should not break old executables.\n * `HEURISTIC1` reportedly no longer works under Solaris 2.7.\n * `HEURISTIC2` probably works, but this appears to be preferable.\n * Apparently `USRSTACK` is defined to be `USERLIMIT`, but in some\n * installations that is undefined.  We work around this with a gross hack.\n */\nEXTERN_C_END\n#  include <sys/vmparam.h>\nEXTERN_C_BEGIN\n#  ifdef USERLIMIT\n/* This should work everywhere, but does not. */\n#    define STACKBOTTOM ((ptr_t)USRSTACK)\n#  else\n#    define HEURISTIC2\n#  endif\n#endif /* SOLARIS */\n\n#ifdef SYMBIAN\n#  define OS_TYPE \"SYMBIAN\"\n#  define DATASTART ((ptr_t)ALIGNMENT) /*< cannot be `NULL` */\n#  define DATAEND ((ptr_t)ALIGNMENT)\n#  ifndef USE_MMAP\n/* `sbrk()` is not available. */\n#    define USE_MMAP 1\n#  endif\n#endif /* SYMBIAN */\n\n/*\n * Below are the definitions specific to each supported architecture\n * and OS, grouped by the former.\n */\n\n#ifdef M68K\n#  define MACH_TYPE \"M68K\"\n#  define CPP_WORDSZ 32\n#  define ALIGNMENT 2 /*< not 4 */\n#  ifdef OPENBSD\n/* Nothing specific. */\n#  endif\n#  ifdef NETBSD\n/* Nothing specific. */\n#  endif\n#  ifdef LINUX\n#    ifdef __ELF__\n#      if GC_GLIBC_PREREQ(2, 0)\n#        define SEARCH_FOR_DATA_START\n#      else\n/*\n * Hideous kludge: `__environ` is the first word in platform `crt0.o` file,\n * and delimits the start of the data segment, no matter which `ld` options\n * were passed through.  We could use `_etext` instead, but that would\n * include `.rodata`, which may contain large read-only data tables that\n * we would rather not scan.\n */\nextern char **__environ;\n#        define DATASTART ((ptr_t)(&__environ))\n#      endif\n#    else\nextern int etext[];\n#      define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x1000)\n#    endif\n#  endif\n#  ifdef NEXT\n#    define STACKBOTTOM MAKE_CPTR(0x4000000)\n#  endif\n#endif\n\n#ifdef POWERPC\n#  define MACH_TYPE \"POWERPC\"\n#  ifdef LINUX\n#    if defined(__powerpc64__)\n#      define CPP_WORDSZ 64\n#      ifndef HBLKSIZE\n#        define HBLKSIZE 4096\n#      endif\n#    else\n#      define CPP_WORDSZ 32\n#    endif\n/*\n * `HEURISTIC1` has been reliably reported to fail for a 32-bit executable\n * on a 64-bit kernel.\n */\n#    if defined(__bg__)\n/*\n * The Linux Compute Node Kernel (used on BlueGene systems) does not\n * support the `SPECIFIC_MAIN_STACKBOTTOM` way.\n */\n#      define HEURISTIC2\n#      define NO_PTHREAD_GETATTR_NP\n#    else\n#      define SPECIFIC_MAIN_STACKBOTTOM\n#    endif\n#    define SEARCH_FOR_DATA_START\n#    ifndef SOFT_VDB\n#      define SOFT_VDB\n#    endif\n#  endif\n#  ifdef DARWIN\n#    if defined(__ppc64__)\n#      define CPP_WORDSZ 64\n#      define STACKBOTTOM MAKE_CPTR(0x7fff5fc00000)\n#      define CACHE_LINE_SIZE 64\n#      ifndef HBLKSIZE\n#        define HBLKSIZE 4096\n#      endif\n#    else\n#      define CPP_WORDSZ 32\n#      define STACKBOTTOM MAKE_CPTR(0xc0000000)\n#    endif\n#    define MPROTECT_VDB\n#    if defined(USE_PPC_PREFETCH) && defined(__GNUC__)\n/* The performance impact of prefetches is untested. */\n#      define PREFETCH(x) \\\n        __asm__ __volatile__(\"dcbt 0,%0\" : : \"r\"((const void *)(x)))\n#      define GC_PREFETCH_FOR_WRITE(x) \\\n        __asm__ __volatile__(\"dcbtst 0,%0\" : : \"r\"((const void *)(x)))\n#    endif\n#  endif\n#  ifdef OPENBSD\n#    if defined(__powerpc64__)\n#      define CPP_WORDSZ 64\n#    else\n#      define CPP_WORDSZ 32\n#    endif\n#  endif\n#  ifdef FREEBSD\n#    if defined(__powerpc64__)\n#      define CPP_WORDSZ 64\n#      ifndef HBLKSIZE\n#        define HBLKSIZE 4096\n#      endif\n#    else\n#      define CPP_WORDSZ 32\n#    endif\n#  endif\n#  ifdef NETBSD\n#    define CPP_WORDSZ 32\n#  endif\n#  ifdef SN_TARGET_PS3\n#    define OS_TYPE \"SN_TARGET_PS3\"\n#    define CPP_WORDSZ 32\n#    define NO_GETENV\nextern int _end[], __bss_start;\n#    define DATASTART ((ptr_t)__bss_start)\n#    define DATAEND ((ptr_t)_end)\n#    define STACKBOTTOM ((ptr_t)ps3_get_stack_bottom())\nvoid *ps3_get_mem(size_t lb);\n#    define GET_MEM(lb) ps3_get_mem(lb)\n/*\n * The current `LOCK()` implementation for PS3 explicitly uses\n * `pthread_mutex_lock()` for some reason.\n */\n#    define NO_PTHREAD_TRYLOCK\n#  endif\n#  ifdef AIX\n#    define OS_TYPE \"AIX\"\n#    undef ALIGNMENT /*< in case it is defined */\n#    undef IA64\n/*\n * DOB: some AIX installs stupidly define `IA64` in platform\n * `sys/systemcfg.h` file.\n */\n#    ifdef __64BIT__\n#      define CPP_WORDSZ 64\n#      define STACKBOTTOM MAKE_CPTR(0x1000000000000000)\n#    else\n#      define CPP_WORDSZ 32\nextern int errno;\n#      define STACKBOTTOM ((ptr_t)(&errno))\n#    endif\n#    define USE_MMAP_ANON\n/*\n * From AIX linker man page:\n *   - `_text` specifies the first location of the program;\n *   - `_etext` specifies the first location after the program;\n *   - `_data` specifies the first location of the data;\n *   - `_edata` specifies the first location after the initialized data;\n *   - `_end` (or `end`) specifies the first location after all data.\n */\nextern int _data[], _end[];\n#    define DATASTART ((ptr_t)_data)\n#    define DATAEND ((ptr_t)_end)\n#    define MPROTECT_VDB\n#    define DYNAMIC_LOADING\n/*\n * Note: for really old versions of AIX, `DYNAMIC_LOADING` may have to\n * be removed.\n */\n#  endif\n#  ifdef NOSYS\n#    define OS_TYPE \"NOSYS\"\n#    define CPP_WORDSZ 32\nextern void __end[], __dso_handle[];\n#    define DATASTART ((ptr_t)__dso_handle) /*< OK, that is ugly */\n#    define DATAEND ((ptr_t)__end)\n/* Note: stack starts at 0xE0000000 for the simulator. */\n#    define STACKBOTTOM PTR_ALIGN_UP(GC_approx_sp(), 0x10000000)\n#  endif\n#endif /* POWERPC */\n\n#ifdef VAX\n#  define MACH_TYPE \"VAX\"\n#  define CPP_WORDSZ 32\n/* Pointers are `longword`-aligned by C compiler v4.2. */\nextern char etext[];\n#  define DATASTART ((ptr_t)etext)\n#  ifdef BSD\n#    define OS_TYPE \"BSD\"\n#    define STACK_GRAN 0x1000000\n#    define HEURISTIC1\n/* Note: `HEURISTIC2` may be OK, but it is hard to test. */\n#  endif\n#  ifdef ULTRIX\n#    define OS_TYPE \"ULTRIX\"\n#    define STACKBOTTOM MAKE_CPTR(0x7fffc800)\n#  endif\n#endif /* VAX */\n\n#ifdef SPARC\n#  define MACH_TYPE \"SPARC\"\n#  if defined(__arch64__) || defined(__sparcv9)\n#    define CPP_WORDSZ 64\n#    define ELF_CLASS ELFCLASS64\n#  else\n#    define CPP_WORDSZ 32\n#    define ALIGNMENT 4 /*< required by hardware */\n#  endif\n#  ifdef SOLARIS\nextern int _etext[];\n#    define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)\n#    define PROC_VDB\n/*\n * `getpagesize()` appeared to be missing from at least one Solaris 5.4\n * installation.  Weird.\n */\n#    define GETPAGESIZE() (unsigned)sysconf(_SC_PAGESIZE)\n#  endif\n#  ifdef DRSNX\n#    define OS_TYPE \"DRSNX\"\nextern int etext[];\n#    define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)etext)\n#    define MPROTECT_VDB\n#    define STACKBOTTOM MAKE_CPTR(0xdfff0000)\n#    define DYNAMIC_LOADING\n#  endif\n#  ifdef LINUX\nextern int _etext[];\n#    ifdef __arch64__\n#      define DATASTART GC_SysVGetDataStart(0x100000, (ptr_t)_etext)\n#    else\n#      define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)\n#    endif\n#  endif\n#  ifdef OPENBSD\n/* Nothing specific. */\n#  endif\n#  ifdef NETBSD\n/* Nothing specific. */\n#  endif\n#  ifdef FREEBSD\nextern char etext[];\n#    define DATASTART ((ptr_t)(&etext))\n#    define DATAEND ((ptr_t)GC_find_limit(DATASTART, TRUE))\n#    define DATAEND_IS_FUNC\n#    define GC_HAVE_DATAREGION2\nextern char edata[], end[];\n#    define DATASTART2 ((ptr_t)(&edata))\n#    define DATAEND2 ((ptr_t)(&end))\n#  endif\n#endif /* SPARC */\n\n#ifdef I386\n#  define MACH_TYPE \"I386\"\n#  if (defined(__LP64__) || defined(_WIN64)) && !defined(CPPCHECK)\n#    error This should be handled as X86_64\n#  endif\n#  define CPP_WORDSZ 32\n/*\n * The 4-byte alignment appears to hold for all 32-bit compilers\n * except Borland and Watcom.  If using the Borland (bcc32) or\n * Watcom (wcc386) compiler, `-a4` or `-zp4` option, respectively,\n * should be passed to the compiler, both for building the library\n * and client code.  (The alternate solution is to define\n * `FORCE_ALIGNMENT_ONE` macro but this would have significant\n * negative performance implications.)\n */\n#  if defined(FORCE_ALIGNMENT_ONE) \\\n      && (defined(__BORLANDC__) || defined(__WATCOMC__))\n#    define ALIGNMENT 1\n#  endif\n#  ifdef SEQUENT\n#    define OS_TYPE \"SEQUENT\"\nextern int etext[];\n#    define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x1000)\n#    define STACKBOTTOM MAKE_CPTR(0x3ffff000)\n#  endif\n#  ifdef HAIKU\n/* Nothing specific. */\n#  endif\n#  ifdef HURD\n/* Nothing specific. */\n#  endif\n#  ifdef EMBOX\n/* Nothing specific. */\n#  endif\n#  ifdef NACL\n/* Nothing specific. */\n#  endif\n#  ifdef QNX\n/* Nothing specific. */\n#  endif\n#  ifdef SERENITY\n/* Nothing specific. */\n#  endif\n#  ifdef SOLARIS\nextern int _etext[];\n#    define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)_etext)\n#    define PROC_VDB\n#  endif\n#  ifdef SCO\n#    define OS_TYPE \"SCO\"\nextern int etext[];\n#    define DATASTART \\\n      (PTR_ALIGN_UP((ptr_t)etext, 0x400000) + (ADDR(etext) & 0xfff))\n#    define STACKBOTTOM MAKE_CPTR(0x7ffffffc)\n#  endif\n#  ifdef SCO_ELF\n#    define OS_TYPE \"SCO_ELF\"\nextern int etext[];\n#    define DATASTART ((ptr_t)etext)\n#    define STACKBOTTOM MAKE_CPTR(0x8048000)\n#    define DYNAMIC_LOADING\n#    define ELF_CLASS ELFCLASS32\n#  endif\n#  ifdef DGUX\n#    define OS_TYPE \"DGUX\"\nextern int _etext, _end;\n#    define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)(&_etext))\n#    define DATASTART_USES_XGETDATASTART\n#    define DATAEND ((ptr_t)(&_end))\n#    define HEURISTIC2\n#    define DYNAMIC_LOADING\n#    ifndef USE_MMAP\n#      define USE_MMAP 1\n#    endif\n#    define MAP_FAILED ((void *)(~(GC_uintptr_t)0))\n#    define HEAP_START ((word)0x40000000)\n#  endif /* DGUX */\n#  ifdef LINUX\n/*\n * This encourages `mmap()` to give us low addresses, thus allowing the\n * heap to grow to ~3 GB.\n */\n#    define HEAP_START ((word)0x1000)\n#    ifdef __ELF__\n#      if GC_GLIBC_PREREQ(2, 0) || defined(HOST_ANDROID)\n#        define SEARCH_FOR_DATA_START\n#      else\n/* See the comment of the Linux/m68k case. */\nextern char **__environ;\n#        define DATASTART ((ptr_t)(&__environ))\n#      endif\n#      if !defined(GC_NO_SIGSETJMP)                                  \\\n          && (defined(HOST_TIZEN)                                    \\\n              || (defined(HOST_ANDROID)                              \\\n                  && !(GC_GNUC_PREREQ(4, 8) || GC_CLANG_PREREQ(3, 2) \\\n                       || __ANDROID_API__ >= 18)))\n/*\n * Older Android NDK releases lack `sigsetjmp` in x86 `libc` (`setjmp` is\n * used instead to find `data_start`).  The bug is fixed in Android NDK r8e\n * (so, it is OK to use `sigsetjmp` if gcc-4.8+, clang-3.2+ or Android\n * API level 18+).\n */\n#        define GC_NO_SIGSETJMP 1\n#      endif\n#    else\nextern int etext[];\n#      define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x1000)\n#    endif\n#    ifdef USE_I686_PREFETCH\n/*\n * Empirically `prefetcht0` is much more effective at reducing cache miss\n * stalls for the targeted load instructions.  But it seems to interfere\n * enough with other cache traffic that the net result is worse than\n * `prefetchnta`.\n */\n#      define PREFETCH(x) \\\n        __asm__ __volatile__(\"prefetchnta %0\" : : \"m\"(*(char *)(x)))\n#      ifdef FORCE_WRITE_PREFETCH\n/*\n * Using prefetches for write seems to have a slight negative impact on\n * performance, at least for a PIII/500.\n */\n#        define GC_PREFETCH_FOR_WRITE(x) \\\n          __asm__ __volatile__(\"prefetcht0 %0\" : : \"m\"(*(char *)(x)))\n#      else\n#        define GC_NO_PREFETCH_FOR_WRITE\n#      endif\n#    elif defined(USE_3DNOW_PREFETCH)\n#      define PREFETCH(x) \\\n        __asm__ __volatile__(\"prefetch %0\" : : \"m\"(*(char *)(x)))\n#      define GC_PREFETCH_FOR_WRITE(x) \\\n        __asm__ __volatile__(\"prefetchw %0\" : : \"m\"(*(char *)(x)))\n#    endif\n#    if defined(__GLIBC__) && !defined(__UCLIBC__) \\\n        && !defined(GLIBC_TSX_BUG_FIXED)\n/* Workaround lock elision implementation for some `glibc`. */\n#      define GLIBC_2_19_TSX_BUG\nEXTERN_C_END\n#      include <gnu/libc-version.h> /*< for `gnu_get_libc_version()` */\nEXTERN_C_BEGIN\n#    endif\n#    ifndef SOFT_VDB\n#      define SOFT_VDB\n#    endif\n#  endif\n#  ifdef CYGWIN32\n#    define WOW64_THREAD_CONTEXT_WORKAROUND\n#    define DATASTART ((ptr_t)GC_DATASTART) /*< defined in `gc.h` file */\n#    define DATAEND ((ptr_t)GC_DATAEND)\n#    ifndef USE_WINALLOC\n/* `MPROTECT_VDB` does not work, it leads to a spurious exit. */\n#    endif\n#  endif\n#  ifdef INTERIX\n#    define OS_TYPE \"INTERIX\"\nextern int _data_start__[], _bss_end__[];\n#    define DATASTART ((ptr_t)_data_start__)\n#    define DATAEND ((ptr_t)_bss_end__)\n#    define STACKBOTTOM                                        \\\n      ({                                                       \\\n        ptr_t rv;                                              \\\n        __asm__ __volatile__(\"movl %%fs:4, %%eax\" : \"=a\"(rv)); \\\n        rv;                                                    \\\n      })\n#    define USE_MMAP_ANON\n#  endif\n#  ifdef OS2\n#    define OS_TYPE \"OS2\"\n/*\n * `STACKBOTTOM` and `DATASTART` are handled specially in `os_dep.c`\n * file.  OS/2 actually has the right system call!\n */\n#    define DATAEND /*< not needed */\n#    undef USE_MUNMAP\n#    define GETPAGESIZE() os2_getpagesize()\n#  endif\n#  ifdef MSWIN32\n#    define WOW64_THREAD_CONTEXT_WORKAROUND\n#    define RETRY_GET_THREAD_CONTEXT\n#    if defined(__BORLANDC__)\n/*\n * TODO: VDB based on `VirtualProtect` and `SetUnhandledExceptionFilter`\n * does not work correctly.\n */\n#    else\n#      define MPROTECT_VDB\n#    endif\n#  endif\n#  ifdef MSWINCE\n/* Nothing specific. */\n#  endif\n#  ifdef DJGPP\n#    define OS_TYPE \"DJGPP\"\nEXTERN_C_END\n#    include \"stubinfo.h\"\nEXTERN_C_BEGIN\nextern int etext[];\n#    define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x200)\nextern int __djgpp_stack_limit, _stklen;\n#    define STACKBOTTOM (MAKE_CPTR(__djgpp_stack_limit) + _stklen)\n#  endif\n#  ifdef OPENBSD\n/* Nothing specific. */\n#  endif\n#  ifdef FREEBSD\n#    if defined(__GLIBC__)\nextern int _end[];\n#      define DATAEND ((ptr_t)_end)\n#    endif\n#  endif\n#  ifdef NETBSD\n/* Nothing specific. */\n#  endif\n#  ifdef THREE86BSD\n#    define OS_TYPE \"THREE86BSD\"\n#    define HEURISTIC2\nextern char etext[];\n#    define DATASTART ((ptr_t)etext)\n#  endif\n#  ifdef BSDI\n#    define OS_TYPE \"BSDI\"\n#    define HEURISTIC2\nextern char etext[];\n#    define DATASTART ((ptr_t)etext)\n#  endif\n#  ifdef NEXT\n#    define STACKBOTTOM MAKE_CPTR(0xc0000000)\n#  endif\n#  ifdef RTEMS\n#    define OS_TYPE \"RTEMS\"\nEXTERN_C_END\n#    include <sys/unistd.h>\nEXTERN_C_BEGIN\nextern int etext[];\n#    define DATASTART ((ptr_t)etext)\nvoid *rtems_get_stack_bottom(void);\n#    define InitStackBottom rtems_get_stack_bottom()\n#    define STACKBOTTOM ((ptr_t)InitStackBottom)\n#    undef USE_MUNMAP\n#  endif\n#  ifdef DOS4GW\n#    define OS_TYPE \"DOS4GW\"\nextern long __nullarea;\nextern char _end;\nextern char *_STACKTOP;\n/*\n * Depending on calling conventions Watcom C either precedes or does not\n * precede the names of the C variables with an underscore.\n * Make sure the startup code variables always have the same name.\n */\n#    pragma aux __nullarea \"*\";\n#    pragma aux _end \"*\";\n#    define STACKBOTTOM ((ptr_t)_STACKTOP) /*< confused? me too */\n#    define DATASTART ((ptr_t)(&__nullarea))\n#    define DATAEND ((ptr_t)(&_end))\n#    undef USE_MUNMAP\n#    define GETPAGESIZE() 4096\n#  endif\n#  ifdef DARWIN\n#    define DARWIN_DONT_PARSE_STACK 1\n#    define STACKBOTTOM MAKE_CPTR(0xc0000000)\n#    define MPROTECT_VDB\n#  endif\n#endif /* I386 */\n\n#ifdef LOONGARCH\n#  define MACH_TYPE \"LOONGARCH\"\n#  define CPP_WORDSZ (__SIZEOF_SIZE_T__ * 8)\n#  ifdef LINUX\n#    pragma weak __data_start\nextern int __data_start[];\n#    define DATASTART ((ptr_t)__data_start)\n#  endif\n#endif /* LOONGARCH */\n\n#ifdef SW_64\n#  define MACH_TYPE \"SW_64\"\n#  define CPP_WORDSZ 64\n#  ifdef LINUX\n/* Nothing specific. */\n#  endif\n#endif /* SW_64 */\n\n#ifdef MIPS\n#  define MACH_TYPE \"MIPS\"\n#  ifdef LINUX\n#    ifdef _MIPS_SZPTR\n#      define CPP_WORDSZ _MIPS_SZPTR\n#    else\n#      define CPP_WORDSZ 32\n#    endif\n#    pragma weak __data_start\nextern int __data_start[];\n#    define DATASTART ((ptr_t)__data_start)\n#    ifndef HBLKSIZE\n#      define HBLKSIZE 4096\n#    endif\n#    if GC_GLIBC_PREREQ(2, 2)\n#      define SPECIFIC_MAIN_STACKBOTTOM\n#    else\n#      define STACKBOTTOM MAKE_CPTR(0x7fff8000)\n#    endif\n#  endif\n#  ifdef EWS4800\n#    define OS_TYPE \"EWS4800\"\n#    define HEURISTIC2\n#    if defined(_MIPS_SZPTR) && (_MIPS_SZPTR == 64)\n#      define CPP_WORDSZ _MIPS_SZPTR\nextern int _fdata[], _end[];\n#      define DATASTART ((ptr_t)_fdata)\n#      define DATAEND ((ptr_t)_end)\n#    else\n#      define CPP_WORDSZ 32\nextern int etext[], edata[];\n#      define DATASTART \\\n        (PTR_ALIGN_UP((ptr_t)etext, 0x40000) + (ADDR(etext) & 0xffff))\n#      define DATAEND ((ptr_t)edata)\n#      define GC_HAVE_DATAREGION2\nextern int _DYNAMIC_LINKING[], _gp[];\n#      define DATASTART2                                               \\\n        (_DYNAMIC_LINKING ? PTR_ALIGN_UP((ptr_t)_gp + 0x8000, 0x40000) \\\n                          : (ptr_t)edata)\nextern int end[];\n#      define DATAEND2 ((ptr_t)end)\n#    endif\n#  endif\n#  ifdef ULTRIX\n#    define OS_TYPE \"ULTRIX\"\n#    define CPP_WORDSZ 32\n#    define HEURISTIC2\n/*\n * Note: the actual beginning of the data segment could probably be\n * slightly higher since startup code allocates lots of stuff.\n */\n#    define DATASTART MAKE_CPTR(0x10000000)\n#  endif\n#  ifdef IRIX5\n#    define OS_TYPE \"IRIX5\"\n#    ifdef _MIPS_SZPTR\n#      define CPP_WORDSZ _MIPS_SZPTR\n#    else\n#      define CPP_WORDSZ 32\n#    endif\n#    define HEURISTIC2\nextern int _fdata[];\n#    define DATASTART ((ptr_t)_fdata)\n/*\n * Lowest plausible heap address.  In the `USE_MMAP` case, we map there.\n * In either case it is used to identify heap sections so they are not\n * considered as roots.\n */\n#    ifdef USE_MMAP\n#      define HEAP_START ((word)0x30000000)\n#    else\n#      define HEAP_START ADDR(DATASTART)\n#    endif\n/* `MPROTECT_VDB` should work, but there is evidence of a breakage. */\n#    define DYNAMIC_LOADING\n#  endif\n#  ifdef MSWINCE\n#    define CPP_WORDSZ 32\n#  endif\n#  ifdef NETBSD\n#    define CPP_WORDSZ 32\n#    ifndef __ELF__\n#      define DATASTART MAKE_CPTR(0x10000000)\n#      define STACKBOTTOM MAKE_CPTR(0x7ffff000)\n#    endif\n#  endif\n#  ifdef OPENBSD\n#    define CPP_WORDSZ 64 /*< all OpenBSD/mips platforms are 64-bit */\n#  endif\n#  ifdef FREEBSD\n#    define CPP_WORDSZ 32\n#  endif\n#  ifdef NONSTOP\n#    define OS_TYPE \"NONSTOP\"\n#    define CPP_WORDSZ 32\n#    define DATASTART MAKE_CPTR(0x8000000)\nextern char **environ;\n#    define DATAEND ((ptr_t)(environ - 0x10))\n#    define STACKBOTTOM MAKE_CPTR(0x4fffffff)\n#    undef USE_MUNMAP\n#  endif\n#endif /* MIPS */\n\n#ifdef NIOS2\n#  define MACH_TYPE \"NIOS2\"\n#  define CPP_WORDSZ 32\n#  ifndef HBLKSIZE\n#    define HBLKSIZE 4096\n#  endif\n#  ifdef LINUX\nextern int __data_start[];\n#    define DATASTART ((ptr_t)__data_start)\n#  endif\n#endif /* NIOS2 */\n\n#ifdef OR1K\n#  define MACH_TYPE \"OR1K\"\n#  define CPP_WORDSZ 32\n#  ifndef HBLKSIZE\n#    define HBLKSIZE 4096\n#  endif\n#  ifdef LINUX\nextern int __data_start[];\n#    define DATASTART ((ptr_t)__data_start)\n#  endif\n#endif /* OR1K */\n\n#ifdef HP_PA\n#  define MACH_TYPE \"HP_PA\"\n#  ifdef __LP64__\n#    define CPP_WORDSZ 64\n#  else\n#    define CPP_WORDSZ 32\n#  endif\n#  define STACK_GROWS_UP\n#  ifdef HPUX\n#    ifndef GC_THREADS\n#      define MPROTECT_VDB\n#    endif\n#    ifdef USE_HPUX_FIXED_STACKBOTTOM\n/*\n * The following appears to work for 7xx systems running HP/UX 9.xx.\n * Furthermore, it might result in much faster collections than `HEURISTIC2`,\n * which may involve scanning segments that directly precede the stack.\n * It is not the default, since it may not work on older machine/OS\n * combinations. (Thanks to Raymond X.T. Nijssen for uncovering this.)\n * This technique also does not work with HP/UX 11.xx.  The stack size is\n * settable using the kernel `maxssiz` variable, and the size can be set\n * dynamically in HP/UX 11.23 and later.  It also does not handle\n * `SHMEM_MAGIC` binaries that have stack and data in the first quadrant.\n * This is from platform `/etc/conf/h/param.h` file.\n */\n#      define STACKBOTTOM MAKE_CPTR(0x7b033000)\n#    elif defined(USE_ENVIRON_POINTER)\n/*\n * Gustavo Rodriguez-Rivera suggested changing `HEURISTIC2` to this.\n * Note that the collector must be initialized before the first `putenv()`\n * call.  Unfortunately, some clients do not obey.\n */\nextern char **environ;\n#      define STACKBOTTOM ((ptr_t)environ)\n#    elif !defined(HEURISTIC2)\n/* This uses `pst_vm_status` support. */\n#      define SPECIFIC_MAIN_STACKBOTTOM\n#    endif\n#    ifndef __GNUC__\n#      define PREFETCH(x)                   \\\n        do {                                \\\n          register long addr = (long)(x);   \\\n          (void)_asm(\"LDW\", 0, 0, addr, 0); \\\n        } while (0)\n#    endif\n#  endif /* HPUX */\n#  ifdef LINUX\n#    define SEARCH_FOR_DATA_START\n#  endif\n#  ifdef OPENBSD\n/* Nothing specific. */\n#  endif\n#endif /* HP_PA */\n\n#ifdef ALPHA\n#  define MACH_TYPE \"ALPHA\"\n#  define CPP_WORDSZ 64\n#  ifdef NETBSD\n#    define ELFCLASS32 32\n#    define ELFCLASS64 64\n#    define ELF_CLASS ELFCLASS64\n#  endif\n#  ifdef OPENBSD\n/* Nothing specific. */\n#  endif\n#  ifdef FREEBSD\nextern char etext[];\n#    define DATASTART ((ptr_t)(&etext))\n#    define DATAEND ((ptr_t)GC_find_limit(DATASTART, TRUE))\n#    define DATAEND_IS_FUNC\n/*\n * Handle unmapped hole which `alpha*-*-freebsd[45]*` puts between\n * `etext` and `edata`.\n */\n#    define GC_HAVE_DATAREGION2\nextern char edata[], end[];\n#    define DATASTART2 ((ptr_t)(&edata))\n#    define DATAEND2 ((ptr_t)(&end))\n/* `MPROTECT_VDB` is not yet supported at all on FreeBSD/alpha. */\n#  endif\n#  ifdef OSF1\n#    define OS_TYPE \"OSF1\"\n#    define DATASTART MAKE_CPTR(0x140000000)\nextern int _end[];\n#    define DATAEND ((ptr_t)(&_end))\nextern char **environ;\n/*\n * Round up from the value of `environ` to the nearest page boundary.\n * Probably this is broken if `putenv()` is called before the collector\n * initialization.\n */\n#    define STACKBOTTOM PTR_ALIGN_UP((ptr_t)environ, getpagesize())\n/*\n * Normally `HEURISTIC2` is too conservative, since the text segment\n * immediately follows the stack.  Hence we give an upper bound.\n * This is currently unused, since `HEURISTIC2` is not defined.\n */\nextern int __start[];\n#    define HEURISTIC2_LIMIT PTR_ALIGN_DOWN((ptr_t)__start, getpagesize())\n#    ifndef GC_THREADS\n/* FIXME: Unresolved signal issues with threads. */\n#      define MPROTECT_VDB\n#    endif\n#    define DYNAMIC_LOADING\n#  endif\n#  ifdef LINUX\n#    ifdef __ELF__\n#      define SEARCH_FOR_DATA_START\n#    else\n#      define DATASTART MAKE_CPTR(0x140000000)\nextern int _end[];\n#      define DATAEND ((ptr_t)_end)\n#    endif\n#  endif\n#endif /* ALPHA */\n\n#ifdef IA64\n#  define MACH_TYPE \"IA64\"\n#  ifdef HPUX\n#    ifdef _ILP32\n#      define CPP_WORDSZ 32\n/* Note: requires 8-byte alignment (granularity) for `malloc()`. */\n#      define ALIGNMENT 4\n#    else\n#      if !defined(_LP64) && !defined(CPPCHECK)\n#        error Unknown ABI\n#      endif\n#      define CPP_WORDSZ 64\n/* Note: requires 16-byte alignment (granularity) for `malloc()`. */\n#      define ALIGNMENT 8\n#    endif\n/*\n * Note that the collector must be initialized before the 1st `putenv`\n * call.\n */\nextern char **environ;\n#    define STACKBOTTOM ((ptr_t)environ)\n/*\n * The following was empirically determined, and is probably not very\n * robust.  Note that the backing store base seems to be at a nice address\n * minus one page.\n */\n#    define BACKING_STORE_DISPLACEMENT 0x1000000\n#    define BACKING_STORE_ALIGNMENT 0x1000\n/* Known to be wrong for recent HP/UX versions!!! */\n#  endif\n#  ifdef LINUX\n#    define CPP_WORDSZ 64\n/*\n * The following works on NUE and older kernels:\n * `define STACKBOTTOM MAKE_CPTR(0xa000000000000000l)`.\n */\n/* TODO: `SPECIFIC_MAIN_STACKBOTTOM` does not work on NUE. */\n/* We also need the base address of the register stack backing store. */\n#    define SEARCH_FOR_DATA_START\n#    ifdef __GNUC__\n#      define DYNAMIC_LOADING\n#    else\n/*\n * In the Intel compiler environment, we seem to end up with statically\n * linked executables and an undefined reference to `_DYNAMIC`.\n */\n#    endif\n#    ifdef __GNUC__\n#      ifndef __INTEL_COMPILER\n#        define PREFETCH(x) __asm__(\"        lfetch  [%0]\" : : \"r\"(x))\n#        define GC_PREFETCH_FOR_WRITE(x) \\\n          __asm__(\"        lfetch.excl     [%0]\" : : \"r\"(x))\n#        define CLEAR_DOUBLE(x) \\\n          __asm__(\"        stf.spill       [%0]=f0\" : : \"r\"((void *)(x)))\n#      else\nEXTERN_C_END\n#        include <ia64intrin.h>\nEXTERN_C_BEGIN\n#        define PREFETCH(x) __lfetch(__lfhint_none, (x))\n#        define GC_PREFETCH_FOR_WRITE(x) __lfetch(__lfhint_nta, (x))\n#        define CLEAR_DOUBLE(x) __stf_spill((void *)(x), 0)\n#      endif /* __INTEL_COMPILER */\n#    endif\n#  endif\n#  ifdef MSWIN32\n/* FIXME: This is a very partial guess.  There is no port, yet. */\n#    if defined(_WIN64)\n#      define CPP_WORDSZ 64\n#    else\n/* TODO: Is this possible? */\n#      define CPP_WORDSZ 32\n#    endif\n#  endif\n#endif /* IA64 */\n\n#ifdef E2K\n#  define MACH_TYPE \"E2K\"\n#  ifdef __LP64__\n#    define CPP_WORDSZ 64\n#  else\n#    define CPP_WORDSZ 32\n#  endif\n#  ifndef HBLKSIZE\n#    define HBLKSIZE 4096\n#  endif\n#  ifdef LINUX\nextern int __dso_handle[];\n#    define DATASTART ((ptr_t)__dso_handle)\n#    ifdef REDIRECT_MALLOC\n#      define NO_PROC_FOR_LIBRARIES\n#    endif\n#  endif\n#endif /* E2K */\n\n#ifdef M88K\n#  define MACH_TYPE \"M88K\"\n#  define CPP_WORDSZ 32\n#  define STACKBOTTOM MAKE_CPTR(0xf0000000) /*< determined empirically */\nextern int etext[];\n#  ifdef CX_UX\n#    define OS_TYPE \"CX_UX\"\n#    define DATASTART (PTR_ALIGN_UP((ptr_t)etext, 0x400000) + 0x10000)\n#  endif\n#  ifdef DGUX\n#    define OS_TYPE \"DGUX\"\n#    define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)etext)\n#    define DATASTART_USES_XGETDATASTART\n#  endif\n#endif /* M88K */\n\n#ifdef S370\n/*\n * If this still works, and if anyone cares, this should probably be moved\n * to the `S390` category.\n */\n#  define MACH_TYPE \"S370\"\n#  define CPP_WORDSZ 32\n#  define ALIGNMENT 4 /*< required by hardware */\n#  ifdef UTS4\n#    define OS_TYPE \"UTS4\"\nextern int _etext[], _end[];\n#    define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)\n#    define DATAEND ((ptr_t)_end)\n#    define HEURISTIC2\n#  endif\n#endif /* S370 */\n\n#ifdef S390\n#  define MACH_TYPE \"S390\"\n#  ifndef __s390x__\n#    define CPP_WORDSZ 32\n#  else\n#    define CPP_WORDSZ 64\n#    ifndef HBLKSIZE\n#      define HBLKSIZE 4096\n#    endif\n#  endif\n#  ifdef LINUX\nextern int __data_start[] __attribute__((__weak__));\nextern int _end[] __attribute__((__weak__));\n#    define DATASTART ((ptr_t)__data_start)\n#    define DATAEND ((ptr_t)_end)\n#    define CACHE_LINE_SIZE 256\n#    define GETPAGESIZE() 4096\n#    ifndef SOFT_VDB\n#      define SOFT_VDB\n#    endif\n#  endif\n#endif /* S390 */\n\n#ifdef AARCH64\n#  define MACH_TYPE \"AARCH64\"\n#  ifdef __ILP32__\n#    define CPP_WORDSZ 32\n#  else\n#    define CPP_WORDSZ 64\n#  endif\n#  ifndef HBLKSIZE\n#    define HBLKSIZE 4096\n#  endif\n#  ifdef LINUX\n#    if defined(HOST_ANDROID)\n#      define SEARCH_FOR_DATA_START\n#    else\nextern int __data_start[] __attribute__((__weak__));\n#      define DATASTART ((ptr_t)__data_start)\n#    endif\n#  endif\n#  ifdef COSMO\n/* Empty. */\n#  endif\n#  ifdef DARWIN\n/* OS X, iOS, visionOS */\n#    define DARWIN_DONT_PARSE_STACK 1\n#    define STACKBOTTOM MAKE_CPTR(0x16fdfffff)\n#    if (TARGET_OS_IPHONE || TARGET_OS_XR || TARGET_OS_VISION)\n/*\n * `MPROTECT_VDB` causes use of non-public API like `exc_server`, this\n * could be a reason for blocking the client application in the store.\n */\n#    elif TARGET_OS_OSX\n#      define MPROTECT_VDB\n#    endif\n#  endif\n#  ifdef FREEBSD\n/* Nothing specific. */\n#  endif\n#  ifdef NETBSD\n#    define ELF_CLASS ELFCLASS64\n#  endif\n#  ifdef OPENBSD\n/* Nothing specific. */\n#  endif\n#  ifdef NINTENDO_SWITCH\n#    define OS_TYPE \"NINTENDO_SWITCH\"\n#    define NO_HANDLE_FORK 1\nextern int __bss_end[];\n#    define DATASTART ((ptr_t)ALIGNMENT) /*< cannot be `NULL` */\n#    define DATAEND ((ptr_t)(&__bss_end))\nvoid *switch_get_stack_bottom(void);\n#    define STACKBOTTOM ((ptr_t)switch_get_stack_bottom())\nvoid *switch_get_mem(size_t lb);\n#    define GET_MEM(lb) switch_get_mem(lb)\n#    define GETPAGESIZE() 4096\n#    undef USE_MMAP\n#    undef USE_MUNMAP\n#    ifndef HAVE_CLOCK_GETTIME\n#      define HAVE_CLOCK_GETTIME 1\n#    endif\n#  endif\n#  ifdef KOS\n/* Nothing specific. */\n#  endif\n#  ifdef QNX\n/* Nothing specific. */\n#  endif\n#  ifdef SERENITY\n/* Nothing specific. */\n#  endif\n#  ifdef MSWIN32\n/* UWP */\n/* TODO: Enable `MPROTECT_VDB`. */\n#  endif\n#  ifdef NOSYS\n#    define OS_TYPE \"NOSYS\"\n/* `__data_start` is usually defined in the target linker script. */\nextern int __data_start[];\n#    define DATASTART ((ptr_t)__data_start)\nextern void *__stack_base__;\n#    define STACKBOTTOM ((ptr_t)__stack_base__)\n#  endif\n#endif /* AARCH64 */\n\n#ifdef ARM32\n#  define MACH_TYPE \"ARM32\"\n#  define CPP_WORDSZ 32\n#  ifdef LINUX\n#    if GC_GLIBC_PREREQ(2, 0) || defined(HOST_ANDROID)\n#      define SEARCH_FOR_DATA_START\n#    else\n/* See the comment of the Linux/m68k case. */\nextern char **__environ;\n#      define DATASTART ((ptr_t)(&__environ))\n#    endif\n#  endif\n#  ifdef MSWINCE\n/* Nothing specific. */\n#  endif\n#  ifdef FREEBSD\n/* Nothing specific. */\n#  endif\n#  ifdef DARWIN\n/* iOS */\n#    define DARWIN_DONT_PARSE_STACK 1\n#    define STACKBOTTOM MAKE_CPTR(0x30000000)\n/* `MPROTECT_VDB` causes use of non-public API. */\n#  endif\n#  ifdef NETBSD\n/* Nothing specific. */\n#  endif\n#  ifdef OPENBSD\n/* Nothing specific. */\n#  endif\n#  ifdef QNX\n/* Nothing specific. */\n#  endif\n#  ifdef SN_TARGET_PSP2\n#    define OS_TYPE \"SN_TARGET_PSP2\"\n#    define NO_HANDLE_FORK 1\n#    ifndef HBLKSIZE\n#      define HBLKSIZE 65536 /*< page size is 64 KB */\n#    endif\n#    define DATASTART ((ptr_t)ALIGNMENT)\n#    define DATAEND ((ptr_t)ALIGNMENT)\nvoid *psp2_get_stack_bottom(void);\n#    define STACKBOTTOM ((ptr_t)psp2_get_stack_bottom())\nvoid *psp2_get_mem(size_t lb);\n#    define GET_MEM(lb) psp2_get_mem(lb)\n#  endif\n#  ifdef NN_PLATFORM_CTR\n#    define OS_TYPE \"NN_PLATFORM_CTR\"\nextern unsigned char Image$$ZI$$ZI$$Base[];\n#    define DATASTART ((ptr_t)Image$$ZI$$ZI$$Base)\nextern unsigned char Image$$ZI$$ZI$$Limit[];\n#    define DATAEND ((ptr_t)Image$$ZI$$ZI$$Limit)\nvoid *n3ds_get_stack_bottom(void);\n#    define STACKBOTTOM ((ptr_t)n3ds_get_stack_bottom())\n#  endif\n#  ifdef MSWIN32\n/* UWP */\n/* TODO: Enable `MPROTECT_VDB`. */\n#  endif\n#  ifdef NOSYS\n#    define OS_TYPE \"NOSYS\"\n/* `__data_start` is usually defined in the target linker script. */\nextern int __data_start[];\n#    define DATASTART ((ptr_t)__data_start)\n/* `__stack_base__` is set in platform `newlib/libc/sys/arm/crt0.S` file. */\nextern void *__stack_base__;\n#    define STACKBOTTOM ((ptr_t)__stack_base__)\n#  endif\n#  ifdef SYMBIAN\n/* Nothing specific. */\n#  endif\n#endif /* ARM32 */\n\n#ifdef CRIS\n#  define MACH_TYPE \"CRIS\"\n#  define CPP_WORDSZ 32\n#  define ALIGNMENT 1\n#  ifdef LINUX\n#    define SEARCH_FOR_DATA_START\n#  endif\n#endif /* CRIS */\n\n#if defined(SH) && !defined(SH4)\n#  define MACH_TYPE \"SH\"\n#  define CPP_WORDSZ 32\n#  ifdef LINUX\n#    define SEARCH_FOR_DATA_START\n#  endif\n#  ifdef NETBSD\n/* Nothing specific. */\n#  endif\n#  ifdef OPENBSD\n/* Nothing specific. */\n#  endif\n#  ifdef MSWINCE\n/* Nothing specific. */\n#  endif\n#endif\n\n#ifdef SH4\n#  define MACH_TYPE \"SH4\"\n#  define CPP_WORDSZ 32\n#  ifdef MSWINCE\n/* Nothing specific. */\n#  endif\n#endif /* SH4 */\n\n#ifdef AVR32\n#  define MACH_TYPE \"AVR32\"\n#  define CPP_WORDSZ 32\n#  ifdef LINUX\n#    define SEARCH_FOR_DATA_START\n#  endif\n#endif /* AVR32 */\n\n#ifdef M32R\n#  define MACH_TYPE \"M32R\"\n#  define CPP_WORDSZ 32\n#  ifdef LINUX\n#    define SEARCH_FOR_DATA_START\n#  endif\n#endif /* M32R */\n\n#ifdef X86_64\n#  define MACH_TYPE \"X86_64\"\n#  ifdef __ILP32__\n#    define CPP_WORDSZ 32\n#  else\n#    define CPP_WORDSZ 64\n#  endif\n#  ifndef HBLKSIZE\n#    define HBLKSIZE 4096\n#  endif\n#  ifndef CACHE_LINE_SIZE\n#    define CACHE_LINE_SIZE 64\n#  endif\n#  ifdef PLATFORM_GETMEM\n#    define OS_TYPE \"PLATFORM_GETMEM\"\n#    define DATASTART ((ptr_t)ALIGNMENT)\n#    define DATAEND ((ptr_t)ALIGNMENT)\nEXTERN_C_END\n#    include <pthread.h>\nEXTERN_C_BEGIN\nvoid *platform_get_stack_bottom(void);\n#    define STACKBOTTOM ((ptr_t)platform_get_stack_bottom())\nvoid *platform_get_mem(size_t lb);\n#    define GET_MEM(lb) platform_get_mem(lb)\n#  endif\n#  ifdef LINUX\n#    define SEARCH_FOR_DATA_START\n#    if defined(__GLIBC__) && !defined(__UCLIBC__)\n/*\n * A workaround for GCF (Google Cloud Function) which does not support\n * `mmap()` for `/dev/zero` pseudo-file.  Should not cause any harm to\n * other targets.\n */\n#      define USE_MMAP_ANON\n#    endif\n#    if defined(__GLIBC__) && !defined(__UCLIBC__) \\\n        && !defined(GETCONTEXT_FPU_BUG_FIXED)\n/*\n * At present, there is a bug in `glibc` `getcontext()` on Linux/x86_64\n * (it clears FPU exception mask).  We define this macro to workaround it.\n */\n/* TODO: This seems to be fixed in `glibc` 2.14. */\n#      define GETCONTEXT_FPU_EXCMASK_BUG\n#    endif\n#    if defined(__GLIBC__) && !defined(__UCLIBC__) \\\n        && !defined(GLIBC_TSX_BUG_FIXED)\n/* Workaround lock elision implementation for some `glibc`. */\n#      define GLIBC_2_19_TSX_BUG\nEXTERN_C_END\n#      include <gnu/libc-version.h> /*< for `gnu_get_libc_version()` */\nEXTERN_C_BEGIN\n#    endif\n#    ifndef SOFT_VDB\n#      define SOFT_VDB\n#    endif\n#  endif\n#  ifdef COSMO\n/* Empty. */\n#  endif\n#  ifdef DARWIN\n#    define DARWIN_DONT_PARSE_STACK 1\n#    define STACKBOTTOM MAKE_CPTR(0x7fff5fc00000)\n#    define MPROTECT_VDB\n#  endif\n#  ifdef FREEBSD\n#    if defined(__GLIBC__)\nextern int _end[];\n#      define DATAEND ((ptr_t)_end)\n#    endif\n#    if defined(__DragonFly__)\n/*\n * DragonFly BSD still has `vm.max_proc_mmap`, according to its\n * `mmap(2)` man page.\n */\n#      define COUNT_UNMAPPED_REGIONS\n#    endif\n#  endif\n#  ifdef NETBSD\n/* Nothing specific. */\n#  endif\n#  ifdef OPENBSD\n/* Nothing specific. */\n#  endif\n#  ifdef HAIKU\n/* Nothing specific. */\n#  endif\n#  ifdef HURD\n/* Nothing specific. */\n#  endif\n#  ifdef QNX\n/* Nothing specific. */\n#  endif\n#  ifdef SERENITY\n/* Nothing specific. */\n#  endif\n#  ifdef SOLARIS\n#    define ELF_CLASS ELFCLASS64\nextern int _etext[];\n#    define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)_etext)\n#    define PROC_VDB\n#  endif\n#  ifdef CYGWIN32\n#    ifndef USE_WINALLOC\n#      if defined(THREAD_LOCAL_ALLOC)\n/*\n * TODO: For an unknown reason, thread-local allocations lead to spurious\n * process exit after the fault handler is once invoked.\n */\n#      else\n#        define MPROTECT_VDB\n#      endif\n#    endif\n#  endif\n#  ifdef MSWIN_XBOX1\n#    define OS_TYPE \"MSWIN_XBOX1\"\n#    define NO_GETENV\n#    define DATASTART ((ptr_t)ALIGNMENT)\n#    define DATAEND ((ptr_t)ALIGNMENT)\nLONG64 durango_get_stack_bottom(void);\n#    define STACKBOTTOM ((ptr_t)durango_get_stack_bottom())\n#    define GETPAGESIZE() 4096\n#    ifndef USE_MMAP\n#      define USE_MMAP 1\n#    endif\n/* The following is from platform `sys/mman.h` file. */\n#    define PROT_NONE 0\n#    define PROT_READ 1\n#    define PROT_WRITE 2\n#    define PROT_EXEC 4\n#    define MAP_PRIVATE 2\n#    define MAP_FIXED 0x10\n#    define MAP_FAILED ((void *)(~(GC_uintptr_t)0))\n#  endif\n#  ifdef MSWIN32\n#    define RETRY_GET_THREAD_CONTEXT\n#    if !defined(__GNUC__) || defined(__INTEL_COMPILER) \\\n        || (GC_GNUC_PREREQ(4, 7) && !defined(__MINGW64__))\n/*\n * Older gcc and Mingw-w64 (both gcc and clang) do not support\n * `SetUnhandledExceptionFilter()` properly on x86_64.\n */\n#      define MPROTECT_VDB\n#    endif\n#  endif\n#endif /* X86_64 */\n\n#ifdef ARC\n#  define MACH_TYPE \"ARC\"\n#  define CPP_WORDSZ 32\n#  define CACHE_LINE_SIZE 64\n#  ifdef LINUX\nextern int __data_start[] __attribute__((__weak__));\n#    define DATASTART ((ptr_t)__data_start)\n#  endif\n#endif /* ARC */\n\n#ifdef HEXAGON\n#  define MACH_TYPE \"HEXAGON\"\n#  define CPP_WORDSZ 32\n#  ifdef LINUX\n#    if defined(__GLIBC__)\n#      define SEARCH_FOR_DATA_START\n#    elif !defined(CPPCHECK)\n#      error Unknown Hexagon libc configuration\n#    endif\n#  endif\n#endif /* HEXAGON */\n\n#ifdef TILEPRO\n#  define MACH_TYPE \"TILEPRO\"\n#  define CPP_WORDSZ 32\n#  define PREFETCH(x) __insn_prefetch(x)\n#  define CACHE_LINE_SIZE 64\n#  ifdef LINUX\nextern int __data_start[];\n#    define DATASTART ((ptr_t)__data_start)\n#  endif\n#endif /* TILEPRO */\n\n#ifdef TILEGX\n#  define MACH_TYPE \"TILEGX\"\n#  define CPP_WORDSZ (__SIZEOF_PTRDIFF_T__ * 8)\n#  if CPP_WORDSZ == 32\n#    define CLEAR_DOUBLE(x) (void)(*(long long *)(x) = 0)\n#  endif\n#  define PREFETCH(x) __insn_prefetch_l1(x)\n#  define CACHE_LINE_SIZE 64\n#  ifdef LINUX\nextern int __data_start[];\n#    define DATASTART ((ptr_t)__data_start)\n#  endif\n#endif /* TILEGX */\n\n#ifdef RISCV\n#  define MACH_TYPE \"RISCV\"\n#  define CPP_WORDSZ (__SIZEOF_SIZE_T__ * 8) /*< 32 or 64 */\n#  ifdef FREEBSD\n/* Nothing specific. */\n#  endif\n#  ifdef LINUX\nextern int __data_start[] __attribute__((__weak__));\n#    define DATASTART ((ptr_t)__data_start)\n#  endif\n#  ifdef NETBSD\n/* Nothing specific. */\n#  endif\n#  ifdef OPENBSD\n/* Nothing specific. */\n#  endif\n#  ifdef NOSYS\n#    define OS_TYPE \"NOSYS\"\nextern char etext[];\n#    define DATASTART ((ptr_t)etext)\n/* FIXME: `STACKBOTTOM` is wrong! */\nextern char **environ;\n#    define STACKBOTTOM ((ptr_t)environ)\n/* TODO: Support 64K page size. */\n#    define GETPAGESIZE() 4096\n#  endif\n#endif /* RISCV */\n\n#ifdef WEBASSEMBLY\n#  define MACH_TYPE \"WEBASSEMBLY\"\n#  if defined(__wasm64__) && !defined(CPPCHECK)\n#    error 64-bit WebAssembly is not yet supported\n#  endif\n#  define CPP_WORDSZ 32\n/*\n * Emscripten does emulate `mmap` and `munmap`, but those should not be\n * used in the collector, since WebAssembly lacks the native support of\n * memory mapping.  Use `sbrk()` instead (by default).\n */\n#  undef USE_MMAP\n#  undef USE_MUNMAP\n#  ifdef EMSCRIPTEN_TINY\nvoid *emmalloc_memalign(size_t align, size_t lb);\n#    define GET_MEM(lb) emmalloc_memalign(GC_page_size, lb)\n#  endif\n#  ifdef EMSCRIPTEN\n#    define OS_TYPE \"EMSCRIPTEN\"\n#    define DATASTART ((ptr_t)ALIGNMENT)\n#    define DATAEND ((ptr_t)ALIGNMENT)\n#    if defined(GC_THREADS) && !defined(CPPCHECK)\n#      error No thread support yet\n#    endif\n#  endif\n#  ifdef WASI\n#    define OS_TYPE \"WASI\"\nextern char __global_base, __heap_base;\n#    define DATASTART ((ptr_t)(&__global_base))\n#    define DATAEND ((ptr_t)(&__heap_base))\n#    define STACKBOTTOM DATASTART\n#    ifndef GC_NO_SIGSETJMP\n#      define GC_NO_SIGSETJMP 1 /*< no support of signals */\n#    endif\n#    ifndef NO_CLOCK\n#      define NO_CLOCK 1 /*< no support of `clock()` */\n#    endif\n#    if defined(GC_THREADS) && !defined(CPPCHECK)\n#      error No thread support yet\n#    endif\n#  endif\n#endif /* WEBASSEMBLY */\n\n#if defined(CYGWIN32) || defined(MSWIN32) || defined(MSWINCE)\n/* Note: it does not include Xbox One. */\n#  define ANY_MSWIN\n#endif\n\n#if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)          \\\n    || ((defined(NN_PLATFORM_CTR) || defined(NINTENDO_SWITCH)  \\\n         || defined(SN_TARGET_PS3) || defined(SN_TARGET_PSP2)) \\\n        && defined(GC_THREADS))\n#  define THREADS\n#endif\n\n/*\n * If the client app is known not to create threads (even indirectly in\n * the used libraries) and the collector is not multi-threaded, then the\n * collector could be built with `SINGLE_THREADED_PROCESS` macro defined.\n * But in practice the macro should never be defined.\n */\n#if defined(THREADS) && defined(SINGLE_THREADED_PROCESS)\n#  undef SINGLE_THREADED_PROCESS\n#endif\n\n#if defined(__CHERI_PURE_CAPABILITY__)\n#  define CHERI_PURECAP\n#endif\n\n#if defined(__GLIBC__) && !defined(DONT_USE_LIBC_PRIVATES)\n/* Use the stack-end marker of `glibc`. */\n#  define USE_LIBC_PRIVATES\n#endif\n\n#ifdef NO_RETRY_GET_THREAD_CONTEXT\n#  undef RETRY_GET_THREAD_CONTEXT\n#endif\n\n#if defined(LINUX) && defined(SPECIFIC_MAIN_STACKBOTTOM) \\\n    && defined(NO_PROC_STAT) && !defined(USE_LIBC_PRIVATES)\n/*\n * This combination will fail, since we have no way to get the stack bottom.\n * Use `HEURISTIC2` instead.\n */\n#  undef SPECIFIC_MAIN_STACKBOTTOM\n#  define HEURISTIC2\n/* This may still fail on some architectures like `IA64`.  We tried... */\n#endif\n\n#if defined(USE_MMAP_ANON) && !defined(USE_MMAP)\n#  define USE_MMAP 1\n#elif (defined(LINUX) || defined(OPENBSD)) && defined(USE_MMAP)\n/*\n * The OS kernel may do a somewhat better job merging mappings with\n * anonymous mappings.\n */\n#  define USE_MMAP_ANON\n#endif\n\n#if defined(CHERI_PURECAP) && defined(USE_MMAP)\n/* TODO: Currently turned off to avoid downgrading permissions on CHERI. */\n#  undef USE_MUNMAP\n#endif\n\n#if (defined(E2K) && defined(USE_PTR_HWTAG) || defined(CHERI_PURECAP)) \\\n    && !defined(NO_BLACK_LISTING)\n/*\n * Misinterpreting of an integer is not possible on the platforms with\n * H/W-tagged pointers, thus the black-listing mechanism is redundant.\n */\n#  define NO_BLACK_LISTING\n#endif\n\n#if defined(REDIRECT_MALLOC) && defined(THREADS) \\\n    && (defined(LINUX) || defined(NACL))\n/* TODO: Unclear if NaCl really needs this. */\n#  define REDIR_MALLOC_AND_LINUXTHREADS\n#endif\n\n#if defined(REDIR_MALLOC_AND_LINUXTHREADS) && !defined(NO_PROC_FOR_LIBRARIES) \\\n    && !defined(USE_PROC_FOR_LIBRARIES)\n/*\n * NPTL allocates thread stacks with `mmap`, which is fine.  But it\n * keeps a cache of thread stacks.  Each thread stack contains a thread\n * control block (TCB).  The latter, in turn, contains a pointer to\n * (`sizeof(void*)` from the beginning of) the `dtv` for thread-local\n * storage, which is `calloc`-allocated.  If we do not scan the cached\n * thread stacks, we appear to lose the `dtv`.  This tends to result in\n * something that looks like a bogus `dtv` count, which tends to result\n * in a `memset()` call on a block that is way too large.  Sometimes\n * we are lucky and the process just dies...  There seems to be\n * a similar issue with some other memory allocated by the dynamic\n * loader.  This should be avoidable by either:\n *   - Defining `USE_PROC_FOR_LIBRARIES` here (that performs very poorly,\n *     precisely because we end up scanning cached stacks);\n *   - Have `calloc()` look at its callers (in spite of the fact that it\n *     is gross and disgusting).\n *\n * In fact, neither seems to suffice, probably in part because even\n * with `USE_PROC_FOR_LIBRARIES`, we do not scan parts of stack\n * segments that appear to be out of bounds.  Thus we actually do both,\n * which seems to yield the best results.\n */\n#  define USE_PROC_FOR_LIBRARIES\n#endif\n\n#ifndef OS_TYPE\n#  define OS_TYPE \"\"\n#endif\n\n#ifndef MACH_TYPE\n#  define MACH_TYPE \"\"\n#endif\n\n#ifndef DATAEND\nextern int end[];\n#  define DATAEND ((ptr_t)end)\n#endif\n\n/*\n * Workaround for Android NDK clang-3.5+ (as of NDK r10e) which does\n * not provide correct `_end` symbol.  Unfortunately, alternate `__end__`\n * symbol is provided only by NDK `bfd` linker.\n */\n#if defined(HOST_ANDROID) && defined(__clang__) && !defined(BROKEN_UUENDUU_SYM)\n#  undef DATAEND\n#  pragma weak __end__\nextern int __end__[];\n#  define DATAEND (__end__ != 0 ? (ptr_t)__end__ : (ptr_t)_end)\n#endif\n\n#if defined(SOLARIS) || defined(DRSNX) || defined(UTS4) \\\n    || (defined(LINUX) && defined(SPARC))\n/* OS has SVR4 generic features.  Probably others also qualify. */\n#  define SVR4\n#  define DATASTART_USES_XGETDATASTART\n#endif\n\n#if defined(HAVE_SYS_TYPES_H)                                      \\\n    || !(defined(__CC_ARM) || defined(GC_NO_TYPES) || defined(OS2) \\\n         || defined(MSWINCE) || defined(SN_TARGET_PSP2))\nEXTERN_C_END\n#  if defined(COSMO) && defined(MPROTECT_VDB) && !defined(_GNU_SOURCE)\n#    define _GNU_SOURCE 1\n#  endif\n#  include <sys/types.h>\nEXTERN_C_BEGIN\n#endif /* HAVE_SYS_TYPES_H */\n\n#if defined(HAVE_UNISTD_H)                                                \\\n    || !(defined(GC_NO_TYPES) || defined(MSWIN32) || defined(MSWINCE)     \\\n         || defined(MSWIN_XBOX1) || defined(NINTENDO_SWITCH)              \\\n         || defined(NN_PLATFORM_CTR) || defined(OS2) || defined(SERENITY) \\\n         || defined(SN_TARGET_PSP2) || defined(__CC_ARM))\nEXTERN_C_END\n#  include <unistd.h>\nEXTERN_C_BEGIN\n#endif /* HAVE_UNISTD_H */\n\n#if !defined(ANY_MSWIN) && !defined(GETPAGESIZE)\n#  if defined(DGUX) || defined(HOST_ANDROID) || defined(HOST_TIZEN) \\\n      || defined(KOS) || defined(SERENITY)                          \\\n      || (defined(LINUX) && defined(SPARC))\n#    define GETPAGESIZE() (unsigned)sysconf(_SC_PAGESIZE)\n#  else\n#    define GETPAGESIZE() (unsigned)getpagesize()\n#  endif\n#endif /* !ANY_MSWIN && !GETPAGESIZE */\n\n#if defined(HOST_ANDROID) && !(__ANDROID_API__ >= 23)           \\\n    && ((defined(MIPS) && (CPP_WORDSZ == 32)) || defined(ARM32) \\\n        || defined(I386) /* but not x32 */)\n/*\n * `tkill()` exists only on arm32/mips(32)/x86.\n * NDK r11+ deprecates `tkill()` but keeps it for Mono clients.\n */\n#  define USE_TKILL_ON_ANDROID\n#endif\n\n#if defined(MPROTECT_VDB) && defined(__GLIBC__) && !GC_GLIBC_PREREQ(2, 2)\n#  error glibc too old?\n#endif\n\n#if defined(SOLARIS) || defined(DRSNX)\n/* OS has Solaris-style semi-undocumented interface to dynamic loader. */\n#  define SOLARISDL\n/* OS has Solaris-style signal handlers. */\n#  define SUNOS5SIGS\n#endif\n\n#if (defined(FREEBSD)                                     \\\n     && (defined(__DragonFly__) || defined(__GLIBC__)     \\\n         || __FreeBSD_kernel__ >= 4 || __FreeBSD__ >= 4)) \\\n    || defined(HPUX)\n#  define SUNOS5SIGS\n#endif\n\n#if defined(COSMO) || defined(HPUX) || defined(HURD) || defined(NETBSD) \\\n    || defined(SERENITY) || (defined(FREEBSD) && defined(SUNOS5SIGS))   \\\n    || (defined(IRIX5) && defined(_sigargs)) /*< Irix 5.x, not 6.x */\n#  define USE_SEGV_SIGACT\n/* We may also get `SIGBUS`. */\n#  define USE_BUS_SIGACT\n#elif defined(ANY_BSD) || defined(HAIKU) || defined(IRIX5) || defined(OSF1) \\\n    || defined(SUNOS5SIGS)\n#  define USE_SEGV_SIGACT\n#endif\n\n#if !defined(GC_EXPLICIT_SIGNALS_UNBLOCK) && defined(SUNOS5SIGS) \\\n    && !defined(GC_NO_PTHREAD_SIGMASK)\n#  define GC_EXPLICIT_SIGNALS_UNBLOCK\n#endif\n\n#if !defined(NO_SIGNALS_UNBLOCK_IN_MAIN) && defined(GC_NO_PTHREAD_SIGMASK)\n#  define NO_SIGNALS_UNBLOCK_IN_MAIN\n#endif\n\n#ifndef PARALLEL_MARK\n#  undef GC_PTHREADS_PARAMARK /*< just in case it is defined by client */\n#elif defined(GC_PTHREADS) && !defined(GC_PTHREADS_PARAMARK) \\\n    && !defined(__MINGW32__)\n/*\n * Use `pthreads`-based parallel mark implementation.  Except for\n * MinGW 32/64 to workaround a deadlock in winpthreads-3.0b internals.\n */\n#  define GC_PTHREADS_PARAMARK\n#endif\n\n#if !defined(NO_MARKER_SPECIAL_SIGMASK)                                 \\\n    && (defined(NACL) || defined(GC_WIN32_PTHREADS)                     \\\n        || (defined(GC_PTHREADS_PARAMARK) && defined(GC_WIN32_THREADS)) \\\n        || defined(GC_NO_PTHREAD_SIGMASK))\n/*\n * Either there is no `pthread_sigmask()`, or the GC marker thread cannot\n * steal and drop user signal calls.\n */\n#  define NO_MARKER_SPECIAL_SIGMASK\n#endif\n\n#if defined(NETBSD) && defined(THREADS)\n#  define SIGRTMIN 33\n#  define SIGRTMAX 63\n/*\n * It seems to be necessary to wait until threads have restarted.\n * But it is unclear why that is the case.\n */\n#  define GC_NETBSD_THREADS_WORKAROUND\n#endif\n\n#if defined(OPENBSD) && defined(THREADS)\nEXTERN_C_END\n#  include <sys/param.h>\nEXTERN_C_BEGIN\n#endif\n\n#if defined(AIX) || defined(ANY_BSD) || defined(BSD) || defined(COSMO)     \\\n    || defined(DARWIN) || defined(DGUX) || defined(HAIKU) || defined(HPUX) \\\n    || defined(HURD) || defined(IRIX5) || defined(LINUX) || defined(OSF1)  \\\n    || defined(QNX) || defined(SERENITY) || defined(SVR4)\n/* Basic UNIX-like system calls work. */\n#  define UNIX_LIKE\n#endif\n\n#if defined(CPPCHECK)\n#  undef CPP_WORDSZ\n#  define CPP_WORDSZ (__SIZEOF_PTRDIFF_T__ * 8)\n#elif CPP_WORDSZ != 32 && CPP_WORDSZ != 64\n#  error Bad word size\n#endif\n\n#ifndef CPP_PTRSZ\n#  ifdef CHERI_PURECAP\n#    define CPP_PTRSZ (__SIZEOF_POINTER__ * 8)\n#  else\n#    define CPP_PTRSZ CPP_WORDSZ\n#  endif\n#endif\n\n#ifndef CPPCHECK\n#  if GC_SIZEOF_PTR * 8 != CPP_PTRSZ\n#    error Bad pointer size\n#  endif\n#endif /* !CPPCHECK */\n\n#ifndef ALIGNMENT\n#  define ALIGNMENT (CPP_PTRSZ >> 3)\n#endif\n\n#if !defined(STACKBOTTOM) && (defined(ECOS) || defined(NOSYS)) \\\n    && !defined(CPPCHECK)\n#  error Undefined STACKBOTTOM\n#endif\n\n#ifdef IGNORE_DYNAMIC_LOADING\n#  undef DYNAMIC_LOADING\n#endif\n\n#if defined(SMALL_CONFIG) && !defined(GC_DISABLE_INCREMENTAL)\n/* Presumably not worth the space it takes. */\n#  define GC_DISABLE_INCREMENTAL\n#endif\n\n/* `USE_WINALLOC` is only an option for Cygwin. */\n#ifndef CYGWIN32\n#  undef USE_WINALLOC\n#endif\n#if defined(MSWIN32) || defined(MSWINCE)\n#  define USE_WINALLOC 1\n#endif\n\n#ifdef USE_WINALLOC\n#  undef USE_MMAP\n#endif\n\n#if defined(ANY_BSD) || defined(DARWIN) || defined(IRIX5) || defined(LINUX) \\\n    || defined(SERENITY) || defined(SOLARIS)                                \\\n    || ((defined(CYGWIN32) || defined(USE_MMAP) || defined(USE_MUNMAP))     \\\n        && !defined(USE_WINALLOC))\n/* Try both `sbrk` and `mmap`, in that order. */\n#  define MMAP_SUPPORTED\n#endif\n\n/*\n * Xbox One (DURANGO) may not need to be this aggressive, but the\n * default is likely too lax under heavy allocation pressure.\n * The platform does not have a virtual paging system, so it does not\n * have a large virtual address space that a standard x86_64 platform has.\n */\n#if defined(USE_MUNMAP) && !defined(MUNMAP_THRESHOLD)     \\\n    && (defined(SN_TARGET_PS3) || defined(SN_TARGET_PSP2) \\\n        || defined(MSWIN_XBOX1))\n#  define MUNMAP_THRESHOLD 3\n#endif\n\n#if defined(GC_DISABLE_INCREMENTAL) || defined(DEFAULT_VDB)\n#  undef GWW_VDB\n#  undef MPROTECT_VDB\n#  undef PROC_VDB\n#  undef SOFT_VDB\n#endif\n\n#ifdef NO_GWW_VDB\n#  undef GWW_VDB\n#endif\n\n#ifdef NO_MPROTECT_VDB\n#  undef MPROTECT_VDB\n#endif\n\n#ifdef NO_SOFT_VDB\n#  undef SOFT_VDB\n#endif\n\n#if defined(SOFT_VDB) && defined(SOFT_VDB_LINUX_VER_STATIC_CHECK)\nEXTERN_C_END\n#  include <linux/version.h> /*< for `LINUX_VERSION`, `LINUX_VERSION_CODE` */\nEXTERN_C_BEGIN\n#  if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)\n/* Not reliable in Linux kernels prior to v3.18. */\n#    undef SOFT_VDB\n#  endif\n#endif /* SOFT_VDB */\n\n#ifdef GC_DISABLE_INCREMENTAL\n#  undef CHECKSUMS\n#endif\n\n#if defined(BASE_ATOMIC_OPS_EMULATED)\n/*\n * `GC_write_fault_handler()` cannot use lock-based atomic primitives\n * as this could lead to a deadlock.\n */\n#  undef MPROTECT_VDB\n#endif\n\n#if defined(USE_PROC_FOR_LIBRARIES) && defined(LINUX) && defined(THREADS)\n/* Incremental GC based on `mprotect` is incompatible with `/proc` roots. */\n#  undef MPROTECT_VDB\n#endif\n\n#if defined(MPROTECT_VDB) && defined(GC_PREFER_MPROTECT_VDB)\n/* Choose `MPROTECT_VDB` manually (if multiple strategies available). */\n#  undef PROC_VDB\n/* `GWW_VDB`, `SOFT_VDB` are handled in `os_dep.c` file. */\n#endif\n\n#ifdef PROC_VDB\n/* Mutually exclusive VDB implementations (for now). */\n#  undef MPROTECT_VDB\n/* For a test purpose only. */\n#  undef SOFT_VDB\n#endif\n\n#if defined(MPROTECT_VDB) && !defined(MSWIN32) && !defined(MSWINCE)\nEXTERN_C_END\n#  include <signal.h> /*< for `SA_SIGINFO`, `SIGBUS` */\nEXTERN_C_BEGIN\n#endif\n\n#if defined(SIGBUS) && !defined(HAVE_SIGBUS) && !defined(CPPCHECK)\n#  define HAVE_SIGBUS\n#endif\n\n#ifndef SA_SIGINFO\n#  define NO_SA_SIGACTION\n#endif\n\n#if (defined(NO_SA_SIGACTION) || defined(GC_NO_SIGSETJMP))            \\\n    && defined(MPROTECT_VDB) && !defined(DARWIN) && !defined(MSWIN32) \\\n    && !defined(MSWINCE)\n#  undef MPROTECT_VDB\n#endif\n\n#if !defined(DEFAULT_VDB) && !defined(GWW_VDB) && !defined(MPROTECT_VDB) \\\n    && !defined(PROC_VDB) && !defined(SOFT_VDB)                          \\\n    && !defined(GC_DISABLE_INCREMENTAL)\n#  define DEFAULT_VDB\n#endif\n\n#if defined(CHECK_SOFT_VDB) && !defined(CPPCHECK)             \\\n    && (defined(GC_PREFER_MPROTECT_VDB) || !defined(SOFT_VDB) \\\n        || !defined(MPROTECT_VDB))\n#  error Invalid config for CHECK_SOFT_VDB\n#endif\n\n#if (defined(GC_DISABLE_INCREMENTAL) || defined(BASE_ATOMIC_OPS_EMULATED) \\\n     || defined(REDIRECT_MALLOC) || defined(SMALL_CONFIG)                 \\\n     || defined(REDIRECT_MALLOC_IN_HEADER) || defined(CHECKSUMS))         \\\n    && !defined(NO_MANUAL_VDB)\n/* TODO: Implement `CHECKSUMS` for manual VDB. */\n#  define NO_MANUAL_VDB\n#endif\n\n#if !defined(PROC_VDB) && !defined(SOFT_VDB) \\\n    && !defined(NO_VDB_FOR_STATIC_ROOTS)\n/* Cannot determine whether a static root page is dirty. */\n#  define NO_VDB_FOR_STATIC_ROOTS\n#endif\n\n#if defined(MPROTECT_VDB) && !defined(DONT_COUNT_PROTECTED_REGIONS) \\\n    && !defined(COUNT_PROTECTED_REGIONS)                            \\\n    && (defined(LINUX) || defined(__DragonFly__))\n#  define COUNT_PROTECTED_REGIONS\n#endif\n\n#if (defined(COUNT_PROTECTED_REGIONS) || defined(COUNT_UNMAPPED_REGIONS)) \\\n    && !defined(GC_UNMAPPED_REGIONS_SOFT_LIMIT)\n/*\n * The default limit of `vm.max_map_count` on Linux is ~65530.\n * There is approximately one mapped region to every protected or\n * unmapped region.  Therefore if we aim to use up to half of\n * `vm.max_map_count` for the collector (leaving half for the rest\n * of the process), then the number of such regions should be one\n * quarter of `vm.max_map_count`.\n */\n#  if defined(__DragonFly__)\n#    define GC_UNMAPPED_REGIONS_SOFT_LIMIT (1000000 / 4)\n#  else\n#    define GC_UNMAPPED_REGIONS_SOFT_LIMIT 16384\n#  endif\n#endif\n\n#if (((defined(ARM32) || defined(AVR32) || defined(MIPS) || defined(NIOS2) \\\n       || defined(OR1K))                                                   \\\n      && defined(UNIX_LIKE))                                               \\\n     || defined(DARWIN) || defined(HAIKU) || defined(HURD)                 \\\n     || defined(OPENBSD) || defined(QNX) || defined(RTEMS)                 \\\n     || defined(SERENITY) || defined(HOST_ANDROID)                         \\\n     || (defined(LINUX) && !defined(__gnu_linux__)))                       \\\n    && !defined(NO_GETCONTEXT)\n#  define NO_GETCONTEXT 1\n#endif\n\n#if defined(MSWIN32) && !defined(CONSOLE_LOG) && defined(_MSC_VER) \\\n    && defined(_DEBUG) && !defined(NO_CRT)\n/*\n * This should be included before the platform `intrin.h` file to\n * workaround some bug in Windows Kit (as of 10.0.17763) headers\n * causing redefinition of `_malloca` macro.\n */\nEXTERN_C_END\n#  include <crtdbg.h> /*< for `_CrtDbgReport` */\nEXTERN_C_BEGIN\n#endif\n\n#ifndef PREFETCH\n#  if (GC_GNUC_PREREQ(3, 0) || defined(__clang__)) && !defined(NO_PREFETCH)\n#    define PREFETCH(x) __builtin_prefetch((x), 0, 0)\n#  elif defined(_MSC_VER) && !defined(NO_PREFETCH)                      \\\n      && (defined(_M_IX86) || defined(_M_X64)) && !defined(_CHPE_ONLY_) \\\n      && (_MSC_VER >= 1900 /* VS 2015+ */)\nEXTERN_C_END\n#    include <intrin.h>\nEXTERN_C_BEGIN\n#    define PREFETCH(x) _mm_prefetch((const char *)(x), _MM_HINT_T0)\n/* TODO: Support also `_M_ARM` and `_M_ARM64` (`__prefetch`). */\n#  else\n#    define PREFETCH(x) (void)0\n#  endif\n#endif /* !PREFETCH */\n\n#ifndef GC_PREFETCH_FOR_WRITE\n/*\n * The default `GC_PREFETCH_FOR_WRITE(x)` is defined in `gc_inline.h` file,\n * the latter one is included from `gc_priv.h` file.\n */\n#endif\n\n#ifndef CACHE_LINE_SIZE\n#  define CACHE_LINE_SIZE 32 /*< wild guess */\n#endif\n\n#ifndef STATIC\n#  ifdef GC_ASSERTIONS\n#    define STATIC /*< ignore to aid debugging (or profiling) */\n#  else\n#    define STATIC static\n#  endif\n#endif\n\n/*\n * Do we need the `GC_find_limit` machinery to find the end of\n * a data segment (or the backing store base)?\n */\n#if defined(HEURISTIC2) || defined(SEARCH_FOR_DATA_START) || defined(IA64)    \\\n    || defined(DGUX) || defined(FREEBSD) || defined(OPENBSD) || defined(SVR4) \\\n    || (defined(HPUX) && defined(SPECIFIC_MAIN_STACKBOTTOM))                  \\\n    || (defined(CYGWIN32) && defined(I386) && defined(USE_MMAP)               \\\n        && !defined(USE_WINALLOC))                                            \\\n    || (defined(NETBSD) && defined(__ELF__))\n#  define NEED_FIND_LIMIT\n#endif\n\n#if defined(LINUX)                                       \\\n    && (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) \\\n        || !defined(SMALL_CONFIG))\n#  define NEED_PROC_MAPS\n#endif\n\n#if defined(LINUX) || defined(HURD) || defined(__GLIBC__)\n#  define REGISTER_LIBRARIES_EARLY\n/*\n * We sometimes use `dl_iterate_phdr`, which may acquire an internal lock.\n * This is not safe after the world has stopped.  So we must call\n * `GC_register_dynamic_libraries` before stopping the world.\n * For performance reasons, this may be beneficial on other platforms\n * as well, though it should be avoided on Windows.\n */\n#endif /* LINUX */\n\n#if defined(SEARCH_FOR_DATA_START)\nextern ptr_t GC_data_start;\n#  define DATASTART GC_data_start\n#endif\n\n#ifndef HEAP_START\n#  define HEAP_START 0\n#endif\n\n#ifndef CLEAR_DOUBLE\n#  define CLEAR_DOUBLE(x) \\\n    (void)(((ptr_t *)(x))[0] = NULL, ((ptr_t *)(x))[1] = NULL)\n#endif\n\n/*\n * Some `libc` implementations like `bionic`, `musl` and `glibc` 2.34+\n * do not have `libpthread.so` file because the `pthreads`-related code\n * is located in `libc.so` file, thus potential `calloc()` calls from\n * such code are forwarded to real (`libc`) `calloc()` without any\n * special handling on the collector side.  Checking `glibc` version at\n * compile time for the purpose seems to be fine.\n */\n#if defined(REDIR_MALLOC_AND_LINUXTHREADS) && !defined(HAVE_LIBPTHREAD_SO) \\\n    && defined(__GLIBC__) && !GC_GLIBC_PREREQ(2, 34)\n#  define HAVE_LIBPTHREAD_SO\n#endif\n\n#if defined(REDIR_MALLOC_AND_LINUXTHREADS) \\\n    && !defined(INCLUDE_LINUX_THREAD_DESCR)\n/*\n * Will not work, since `libc` and the dynamic loader use thread locals,\n * sometimes as the only reference.\n */\n#  define INCLUDE_LINUX_THREAD_DESCR\n#endif\n\n#ifndef CPPCHECK\n#  if defined(GC_AIX_THREADS) && !defined(AIX)                            \\\n      || (defined(GC_DARWIN_THREADS) && !defined(DARWIN))                 \\\n      || (defined(GC_DGUX386_THREADS) && !defined(DGUX))                  \\\n      || (defined(GC_FREEBSD_THREADS) && !defined(FREEBSD))               \\\n      || (defined(GC_HAIKU_THREADS) && !defined(HAIKU))                   \\\n      || (defined(GC_HPUX_THREADS) && !defined(HPUX))                     \\\n      || (defined(GC_IRIX_THREADS) && !defined(IRIX5))                    \\\n      || (defined(GC_LINUX_THREADS) && !defined(LINUX) && !defined(NACL)) \\\n      || (defined(GC_NETBSD_THREADS) && !defined(NETBSD))                 \\\n      || (defined(GC_OPENBSD_THREADS) && !defined(OPENBSD))               \\\n      || (defined(GC_OSF1_THREADS) && !defined(OSF1))                     \\\n      || (defined(GC_RTEMS_PTHREADS) && !defined(RTEMS))                  \\\n      || (defined(GC_SOLARIS_THREADS) && !defined(SOLARIS))               \\\n      || (defined(GC_WIN32_THREADS) && !defined(ANY_MSWIN)                \\\n          && !defined(MSWIN_XBOX1))\n#    error Inconsistent configuration\n#  elif defined(GC_WIN32_PTHREADS) && defined(CYGWIN32)\n#    error Inconsistent configuration (GC_PTHREADS)\n#  endif\n#  if defined(PARALLEL_MARK) && !defined(THREADS)\n#    error Invalid config: PARALLEL_MARK requires GC_THREADS\n#  endif\n#  if defined(GWW_VDB) && !defined(USE_WINALLOC)\n#    error Invalid config: GWW_VDB requires USE_WINALLOC\n#  endif\n#  if (defined(GC_FINDLEAK_DELAY_FREE) && defined(SHORT_DBG_HDRS)) \\\n      || ((defined(FIND_LEAK) || defined(GC_FINDLEAK_DELAY_FREE))  \\\n          && defined(NO_FIND_LEAK))\n#    error Invalid config: FIND_LEAK and NO_FIND_LEAK are mutually exclusive\n#  endif\n#endif /* !CPPCHECK */\n\n#if defined(NO_FIND_LEAK) && !defined(DONT_USE_ATEXIT)\n#  define DONT_USE_ATEXIT\n#endif\n\n/* Whether `GC_page_size` is to be set to a value other than page size. */\n#if defined(CYGWIN32) && (defined(MPROTECT_VDB) || defined(USE_MUNMAP)) \\\n    || (!defined(ANY_MSWIN) && !defined(WASI) && !defined(USE_MMAP)     \\\n        && (defined(GC_DISABLE_INCREMENTAL) || defined(DEFAULT_VDB)))\n/*\n * Cygwin: use the allocation granularity instead.\n * Other than WASI and Windows: use `HBLKSIZE` instead (unless `mmap()`\n * is used).\n */\n#  define ALT_PAGESIZE_USED\n#  ifndef GC_NO_VALLOC\n/* Nonetheless, we need the real page size is some extra functions. */\n#    define REAL_PAGESIZE_NEEDED\n#  endif\n#endif\n\n#if defined(GC_PTHREADS) && !defined(DARWIN) && !defined(GC_WIN32_THREADS) \\\n    && !defined(PLATFORM_STOP_WORLD) && !defined(SN_TARGET_PSP2)\n#  define PTHREAD_STOP_WORLD_IMPL\n#endif\n\n#if defined(PTHREAD_STOP_WORLD_IMPL) && !defined(NACL)\n#  define SIGNAL_BASED_STOP_WORLD\n#endif\n\n#if (defined(E2K) || defined(HP_PA) || defined(IA64) || defined(M68K) \\\n     || defined(NO_SA_SIGACTION))                                     \\\n    && defined(SIGNAL_BASED_STOP_WORLD)\n#  define SUSPEND_HANDLER_NO_CONTEXT\n#endif\n\n#if (defined(MSWIN32) || defined(MSWINCE)                      \\\n     || (defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS))) \\\n    && !defined(NO_CRT) && !defined(NO_WRAP_MARK_SOME)\n/*\n * Under rare conditions, we may end up marking from nonexistent memory.\n * Hence we need to be prepared to recover by running `GC_mark_some` with\n * a suitable handler in place.\n */\n/* TODO: Should we also define it for Cygwin? */\n#  define WRAP_MARK_SOME\n#endif\n\n#if !defined(MSWIN32) && !defined(MSWINCE) || defined(__GNUC__) \\\n    || defined(NO_CRT)\n#  define NO_SEH_AVAILABLE\n#endif\n\n#ifdef GC_WIN32_THREADS\n/* The number of copied registers in `copy_ptr_regs()`. */\n#  if defined(I386)\n#    ifdef WOW64_THREAD_CONTEXT_WORKAROUND\n#      define PUSHED_REGS_COUNT 9\n#    else\n#      define PUSHED_REGS_COUNT 7\n#    endif\n#  elif defined(X86_64)\n#    ifdef XMM_CANT_STORE_PTRS\n/* If pointers cannot be located in Xmm registers. */\n#      define PUSHED_REGS_COUNT 15\n#    else\n/*\n * gcc-13 may store pointers into SIMD registers when certain compiler\n * optimizations are enabled.\n */\n#      define PUSHED_REGS_COUNT (15 + 32)\n#    endif\n#  elif defined(SHx)\n#    define PUSHED_REGS_COUNT 15\n#  elif defined(ARM32)\n#    define PUSHED_REGS_COUNT 13\n#  elif defined(AARCH64)\n#    define PUSHED_REGS_COUNT 30\n#  elif defined(MIPS) || defined(ALPHA)\n#    define PUSHED_REGS_COUNT 28\n#  elif defined(PPC)\n#    define PUSHED_REGS_COUNT 29\n#  endif\n#endif /* GC_WIN32_THREADS */\n\n#if !defined(GC_PTHREADS) && !defined(GC_PTHREADS_PARAMARK)\n#  undef HAVE_PTHREAD_SETNAME_NP_WITH_TID\n#  undef HAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG\n#  undef HAVE_PTHREAD_SET_NAME_NP\n#endif\n\n#if !(defined(GC_PTHREADS) || defined(GC_PTHREADS_PARAMARK) \\\n      || (defined(MPROTECT_VDB) && defined(DARWIN)))\n#  undef HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID\n#endif\n\n#if defined(USE_RWLOCK) || defined(GC_DISABLE_SUSPEND_THREAD)\n/*\n * At least in the Linux threads implementation, `rwlock` primitives are\n * not atomic in respect to signals, and suspending externally a thread\n * which is running inside `pthread_rwlock_rdlock()` may lead to a deadlock.\n */\n/* TODO: As a workaround `GC_suspend_thread()` API is disabled. */\n#  undef GC_ENABLE_SUSPEND_THREAD\n#endif\n\n#ifndef GC_NO_THREADS_DISCOVERY\n#  if defined(DARWIN) && defined(THREADS)\n/* Task-based thread registration requires stack-frame-walking code. */\n#    if defined(DARWIN_DONT_PARSE_STACK)\n#      define GC_NO_THREADS_DISCOVERY\n#    endif\n#  elif defined(GC_WIN32_THREADS)\n/*\n * `DllMain`-based thread registration is currently incompatible with\n * thread-local allocation, `pthreads` and WinCE.\n */\n#    if (!defined(GC_DLL) && !defined(GC_INSIDE_DLL)) || defined(GC_PTHREADS) \\\n        || defined(MSWINCE) || defined(NO_CRT) || defined(THREAD_LOCAL_ALLOC)\n#      define GC_NO_THREADS_DISCOVERY\n#    endif\n#  else\n#    define GC_NO_THREADS_DISCOVERY\n#  endif\n#endif /* !GC_NO_THREADS_DISCOVERY */\n\n#if defined(GC_DISCOVER_TASK_THREADS) && defined(GC_NO_THREADS_DISCOVERY) \\\n    && !defined(CPPCHECK)\n#  error Defined both GC_DISCOVER_TASK_THREADS and GC_NO_THREADS_DISCOVERY\n#endif\n\n#if defined(PARALLEL_MARK) && !defined(DEFAULT_STACK_MAYBE_SMALL) \\\n    && (defined(DGUX) || defined(HPUX)                            \\\n        || defined(NO_GETCONTEXT) /* e.g. musl */)\n/* TODO: Test default stack size in configure. */\n#  define DEFAULT_STACK_MAYBE_SMALL\n#endif\n\n#ifdef PARALLEL_MARK\n/* The minimum stack size for a marker thread. */\n#  define MIN_STACK_SIZE (8 * HBLKSIZE * sizeof(ptr_t))\n#endif\n\n#if defined(HOST_ANDROID) && !defined(THREADS) \\\n    && !defined(USE_GET_STACKBASE_FOR_MAIN)\n/*\n * Always use `pthread_attr_getstack` on Android (`-lpthread` option\n * is not needed to be specified manually) since Linux-specific\n * `os_main_stackbottom()` causes application crash if invoked inside\n * Dalvik VM.\n */\n#  define USE_GET_STACKBASE_FOR_MAIN\n#endif\n\n/*\n * Outline `pthreads` primitives to use in `GC_get_stack_base()` and\n * `GC_get_main_stack_base()`.\n */\n#if ((defined(FREEBSD) && defined(__GLIBC__) /* kFreeBSD */)               \\\n     || defined(COSMO) || defined(HAIKU) || defined(LINUX) || defined(KOS) \\\n     || defined(NETBSD))                                                   \\\n    && !defined(NO_PTHREAD_GETATTR_NP)\n#  define HAVE_PTHREAD_GETATTR_NP 1\n#elif defined(FREEBSD) && !defined(__GLIBC__) \\\n    && !defined(NO_PTHREAD_ATTR_GET_NP)\n#  define HAVE_PTHREAD_NP_H 1 /*< requires include `pthread_np.h` file */\n#  define HAVE_PTHREAD_ATTR_GET_NP 1\n#endif\n\n#if (defined(HAVE_PTHREAD_ATTR_GET_NP) || defined(HAVE_PTHREAD_GETATTR_NP)) \\\n    && defined(USE_GET_STACKBASE_FOR_MAIN) && !defined(STACKBOTTOM)         \\\n    && !defined(HEURISTIC1) && !defined(HEURISTIC2) && !defined(STACK_GRAN) \\\n    && !defined(SPECIFIC_MAIN_STACKBOTTOM)\n/* Dummy definitions; rely on `pthread_attr_getstack` actually. */\n#  define HEURISTIC1\n#  define STACK_GRAN 0x1000000\n#endif\n\n#if !defined(HAVE_CLOCK_GETTIME) && defined(_POSIX_TIMERS) \\\n    && (defined(CYGWIN32) || (defined(LINUX) && defined(__USE_POSIX199309)))\n#  define HAVE_CLOCK_GETTIME 1\n#endif\n\n#if defined(GC_PTHREADS) && !defined(E2K) && !defined(IA64)   \\\n    && (!defined(DARWIN) || defined(DARWIN_DONT_PARSE_STACK)) \\\n    && !defined(SN_TARGET_PSP2) && !defined(REDIRECT_MALLOC)\n/*\n * Note: unimplemented in case of redirection of `malloc()` because\n * the client-provided function might call some `pthreads` primitive\n * which, in turn, may use `malloc()` internally.\n */\n#  define STACKPTR_CORRECTOR_AVAILABLE\n#endif\n\n#if defined(UNIX_LIKE) && defined(THREADS) && !defined(NO_CANCEL_SAFE) \\\n    && !defined(HOST_ANDROID)\n/*\n * Make the code cancellation-safe.  This basically means that we ensure\n * that cancellation requests are ignored while we are in the collector.\n * This applies only to POSIX deferred cancellation; we do not handle POSIX\n * asynchronous cancellation.  Note that this only works if\n * `pthread_setcancelstate` is async-signal-safe, at least in the absence of\n * asynchronous cancellation.  This appears to be true for `glibc`, though it\n * is not documented.  Without that assumption, there seems to be no way to\n * safely wait in a signal handler, which we need to do for thread suspension.\n * Also note that little other code appears to be cancellation-safe.\n * Hence it may make sense to turn this off for performance.\n */\n#  define CANCEL_SAFE\n#endif\n\n#ifdef CANCEL_SAFE\n#  define IF_CANCEL(x) x\n#else\n#  define IF_CANCEL(x) /*< empty */\n#endif\n\n#if defined(DARWIN) && defined(MPROTECT_VDB)   \\\n    && !defined(NO_DESC_CATCH_EXCEPTION_RAISE) \\\n    && !defined(FORCE_DESC_CATCH_EXCEPTION_RAISE) && GC_CLANG_PREREQ(17, 0)\n/*\n * Workaround \"REFERENCED_DYNAMICALLY flag on _catch_exception_raise\"\n * linker deprecation warnings on macOS 15.4.\n */\n#  define NO_DESC_CATCH_EXCEPTION_RAISE\n#endif\n\n#if !defined(CAN_HANDLE_FORK) && !defined(NO_HANDLE_FORK)                 \\\n    && !defined(HAVE_NO_FORK)                                             \\\n    && ((defined(GC_PTHREADS) && !defined(NACL)                           \\\n         && !defined(GC_WIN32_PTHREADS) && !defined(USE_WINALLOC))        \\\n        || (defined(DARWIN) && defined(MPROTECT_VDB) /* `&& !THREADS` */) \\\n        || (defined(HANDLE_FORK) && defined(GC_PTHREADS)))\n/*\n * Attempts (where supported and requested) to make `GC_malloc` work in\n * a child process forked from a multi-threaded parent process.\n */\n#  define CAN_HANDLE_FORK\n#endif\n\n/*\n * Workaround \"failed to create new win32 semaphore\" Cygwin fatal error\n * during semaphores fixup-after-fork.\n */\n#if defined(CYGWIN32) && defined(THREADS) && defined(CAN_HANDLE_FORK) \\\n    && !defined(CYGWIN_SEM_FIXUP_AFTER_FORK_BUG_FIXED)                \\\n    && !defined(EMULATE_PTHREAD_SEMAPHORE)\n#  define EMULATE_PTHREAD_SEMAPHORE\n#endif\n\n#if defined(CAN_HANDLE_FORK) && !defined(CAN_CALL_ATFORK)      \\\n    && !defined(GC_NO_CAN_CALL_ATFORK) && !defined(HOST_TIZEN) \\\n    && !defined(HURD) && (!defined(HOST_ANDROID) || __ANDROID_API__ >= 21)\n/* Have working `pthread_atfork()`. */\n#  define CAN_CALL_ATFORK\n#endif\n\n#if !defined(CAN_HANDLE_FORK) && !defined(HAVE_NO_FORK) \\\n    && !(defined(CYGWIN32) || defined(SOLARIS) || defined(UNIX_LIKE))\n#  define HAVE_NO_FORK\n#endif\n\n#if !defined(USE_MARK_BITS) && !defined(USE_MARK_BYTES) \\\n    && defined(PARALLEL_MARK)\n/* Minimize compare-and-swap usage. */\n#  define USE_MARK_BYTES\n#endif\n\n#if (defined(MSWINCE) && !defined(__CEGCC__) || defined(MSWINRT_FLAVOR)) \\\n    && !defined(NO_GETENV)\n#  define NO_GETENV\n#endif\n\n#if (defined(NO_GETENV) || defined(MSWINCE)) && !defined(NO_GETENV_WIN32)\n#  define NO_GETENV_WIN32\n#endif\n\n#if !defined(MSGBOX_ON_ERROR) && !defined(NO_MSGBOX_ON_ERROR)                \\\n    && defined(MSWIN32) && !defined(MSWINRT_FLAVOR) && !defined(MSWIN_XBOX1) \\\n    && !defined(SMALL_CONFIG)\n/*\n * Show a Windows message box with \"OK\" button on a GC fatal error.\n * Client application is terminated once the user clicks the button.\n */\n#  define MSGBOX_ON_ERROR\n#endif\n\n#ifndef STRTOULL\n#  if defined(_WIN64) && !defined(__GNUC__)\n#    define STRTOULL _strtoui64\n#  elif defined(_LLP64) || defined(__LLP64__) || defined(_WIN64)\n#    define STRTOULL strtoull\n#  else\n/* `strtoul()` fits since `sizeof(long)` is not less than `sizeof(word)`. */\n#    define STRTOULL strtoul\n#  endif\n#endif /* !STRTOULL */\n\n#ifndef GC_WORD_C\n#  if defined(_WIN64) && !defined(__GNUC__)\n#    define GC_WORD_C(val) val##ui64\n#  elif defined(_LLP64) || defined(__LLP64__) || defined(_WIN64)\n#    define GC_WORD_C(val) val##ULL\n#  else\n#    define GC_WORD_C(val) ((word)val##UL)\n#  endif\n#endif /* !GC_WORD_C */\n\n#if defined(__has_feature)\n/* `__has_feature()` is supported. */\n#  if __has_feature(address_sanitizer)\n#    define ADDRESS_SANITIZER\n#  endif\n#  if __has_feature(memory_sanitizer)\n#    define MEMORY_SANITIZER\n#  endif\n#  if __has_feature(thread_sanitizer) && defined(THREADS)\n#    define THREAD_SANITIZER\n#  endif\n#else\n#  ifdef __SANITIZE_ADDRESS__\n/* gcc v4.8+ */\n#    define ADDRESS_SANITIZER\n#  endif\n#  if defined(__SANITIZE_THREAD__) && defined(THREADS)\n/* gcc v7.1+ */\n#    define THREAD_SANITIZER\n#  endif\n#endif /* !__has_feature */\n\n#if defined(SPARC)\n/* Stack clearing is crucial, and we include assembly code to do it well. */\n#  define ASM_CLEAR_CODE\n#endif\n\n/*\n * Can we save call chain in objects for debugging?  Set `NFRAMES`\n * (number of saved frames) and `NARGS` (number of arguments for each\n * frame) to reasonable values for the platform.\n * Define `SAVE_CALL_CHAIN` if we can.  `SAVE_CALL_COUNT` can be\n * specified at build time, though we feel free to adjust it slightly.\n * Define `NEED_CALLINFO` if we either save the call stack or\n * `GC_ADD_CALLER` is defined.  Note: `GC_CAN_SAVE_CALL_STACKS` is\n * defined (for certain platforms) in `gc_config_macros.h` file.\n */\n#if defined(SPARC)                         \\\n    || ((defined(I386) || defined(X86_64)) \\\n        && (defined(LINUX) || defined(__GLIBC__)))\n/*\n * Linux/x86: `SAVE_CALL_CHAIN` is supported if the code is compiled to save\n * frame pointers by default, i.e. no `-fomit-frame-pointer` flag is given.\n */\n#  define CAN_SAVE_CALL_ARGS\n#endif\n\n#if defined(SAVE_CALL_COUNT) && !defined(GC_ADD_CALLER) \\\n    && defined(GC_CAN_SAVE_CALL_STACKS)\n#  define SAVE_CALL_CHAIN\n#endif\n\n#ifdef SAVE_CALL_CHAIN\n/* Number of arguments to save for each call. */\n#  if defined(SAVE_CALL_NARGS) && defined(CAN_SAVE_CALL_ARGS)\n#    define NARGS SAVE_CALL_NARGS\n#  else\n#    define NARGS 0\n#  endif\n/* Number of frames to save.  Even for alignment reasons. */\n#  if !defined(SAVE_CALL_COUNT) || defined(CPPCHECK)\n#    define NFRAMES 6\n#  else\n#    define NFRAMES ((SAVE_CALL_COUNT + 1) & ~1)\n#  endif\n#  define NEED_CALLINFO\n#elif defined(GC_ADD_CALLER)\n#  define NFRAMES 1\n#  define NARGS 0\n#  define NEED_CALLINFO\n#endif\n\n#if (defined(FREEBSD) || (defined(DARWIN) && !defined(_POSIX_C_SOURCE)) \\\n     || (defined(SOLARIS)                                               \\\n         && (!defined(_XOPEN_SOURCE) || defined(__EXTENSIONS__)))       \\\n     || defined(LINUX))                                                 \\\n    && !defined(HAVE_DLADDR)\n#  define HAVE_DLADDR 1\n#endif\n\n#if defined(MAKE_BACK_GRAPH) && !defined(DBG_HDRS_ALL)\n#  define DBG_HDRS_ALL 1\n#endif\n\n#if defined(POINTER_MASK) && !defined(POINTER_SHIFT)\n#  define POINTER_SHIFT 0\n#elif !defined(POINTER_MASK) && defined(POINTER_SHIFT)\n#  define POINTER_MASK GC_WORD_MAX\n#endif\n\n#if defined(FIXUP_POINTER)\n/* Custom `FIXUP_POINTER(p)`. */\n#  define NEED_FIXUP_POINTER\n#elif defined(DYNAMIC_POINTER_MASK)\n#  define FIXUP_POINTER(p) \\\n    (p = (ptr_t)((((word)(p)) & GC_pointer_mask) << GC_pointer_shift))\n#  undef POINTER_MASK\n#  undef POINTER_SHIFT\n#  define NEED_FIXUP_POINTER\n#elif defined(POINTER_MASK)\n/*\n * Note: extra parentheses around custom-defined `POINTER_MASK` and\n *`POINTER_SHIFT` are intentional.\n */\n#  define FIXUP_POINTER(p) \\\n    (p = (ptr_t)(((word)(p) & (POINTER_MASK)) << (POINTER_SHIFT)))\n#  define NEED_FIXUP_POINTER\n#else\n#  define FIXUP_POINTER(p) (void)(p)\n#endif\n\n#ifdef LINT2\n/*\n * A macro (based on a tricky expression) to prevent false warnings\n * like \"Array compared to 0\", \"Comparison of identical expressions\",\n * \"Untrusted loop bound\" output by some static code analysis tools.\n * The argument should not be a literal value.  The result is\n * converted to `word` type.  (Actually, `GC_word` is used instead of\n * `word` type as the latter might be undefined at the place of use.)\n */\n#  define COVERT_DATAFLOW(w) (~(GC_word)(w) ^ (~(GC_word)0))\n#else\n#  define COVERT_DATAFLOW(w) ((GC_word)(w))\n#endif\n\n#if CPP_PTRSZ > CPP_WORDSZ\n/* TODO: Cannot use tricky operations on a pointer. */\n#  define COVERT_DATAFLOW_P(p) ((ptr_t)(p))\n#else\n#  define COVERT_DATAFLOW_P(p) ((ptr_t)COVERT_DATAFLOW(p))\n#endif\n\n#if defined(REDIRECT_MALLOC) && defined(THREADS) && !defined(LINUX) \\\n    && !defined(REDIRECT_MALLOC_IN_HEADER)\n/*\n * May work on other platforms (e.g. Darwin) provided the client\n * ensures all the client threads are registered with the collector,\n * e.g. by using the preprocessor-based interception of the thread\n * primitives (i.e., define `GC_THREADS` and include `gc.h` file from\n * all the client files those are using `pthread_create` and friends).\n */\n#endif\n\nEXTERN_C_END\n\n#endif /* GCCONFIG_H */\n\n\n#ifdef __cplusplus\ntypedef bool GC_bool;\n#elif defined(__BORLANDC__) || defined(__WATCOMC__)\ntypedef int GC_bool;\n#else\ntypedef char GC_bool;\n#endif\n\n#if defined(__cplusplus) && !defined(ANY_MSWIN)\n/* Avoid macro redefinition on a Windows platform. */\n#  define TRUE true\n#  define FALSE false\n#else\n#  define TRUE 1\n#  define FALSE 0\n#endif\n\n#if !defined(GC_ATOMIC_UNCOLLECTABLE) && defined(ATOMIC_UNCOLLECTABLE)\n/* For compatibility with old-style naming. */\n#  define GC_ATOMIC_UNCOLLECTABLE\n#endif\n\n#ifndef GC_INNER\n/*\n * This tagging macro must be used at the start of every variable definition\n * which is declared with `GC_EXTERN`.  Should be also used for the GC-scope\n * function definitions and prototypes.  Must not be used in `gcconfig.h`\n * file.  Should not be used for the debugging-only functions.\n */\n#  if defined(GC_DLL) && defined(__GNUC__) && !defined(ANY_MSWIN)\n#    if GC_GNUC_PREREQ(4, 0) && !defined(GC_NO_VISIBILITY)\n/* See the corresponding `GC_API` definition. */\n#      define GC_INNER __attribute__((__visibility__(\"hidden\")))\n#    else\n/* The attribute is unsupported. */\n#      define GC_INNER /*< empty */\n#    endif\n#  else\n#    define GC_INNER /*< empty */\n#  endif\n\n#  define GC_EXTERN extern GC_INNER\n/*\n * Used only for the GC-scope variables (prefixed with `GC_`) declared\n * in the private header files.  Must not be used for thread-local\n * variables.  Must not be used in `gcconfig.h` file.\n * The corresponding variable definition must start with `GC_INNER`.\n * Should not be used for the debugging- or profiling-only variables.\n * As of now, there are some other exceptions, e.g. for the variables\n * that are known to be used by some popular clients.\n */\n#endif /* !GC_INNER */\n\n#ifdef __cplusplus\n/* `register` storage specifier is deprecated in C++11. */\n#  define REGISTER /*< empty */\n#else\n/*\n * Used only for several local variables in the performance-critical\n * functions.  Should not be used for new code.\n */\n#  define REGISTER register\n#endif\n\n#if defined(CPPCHECK)\n#  define MACRO_BLKSTMT_BEGIN {\n#  define MACRO_BLKSTMT_END }\n#  define LOCAL_VAR_INIT_OK = 0 /*< to avoid \"uninit var\" false positive */\n#else\n#  define MACRO_BLKSTMT_BEGIN do {\n#  define MACRO_BLKSTMT_END \\\n    }                       \\\n    while (0)\n#  define LOCAL_VAR_INIT_OK /*< empty */\n#endif\n\n#if defined(M68K) && defined(__GNUC__)\n/*\n * By default, `__alignof__(void *)` is 2 on m68k architecture.\n * Use this attribute to have the machine-word alignment (i.e. 4-byte one\n * on the given 32-bit architecture).\n */\n#  define GC_ATTR_PTRT_ALIGNED __attribute__((__aligned__(sizeof(ptr_t))))\n#else\n#  define GC_ATTR_PTRT_ALIGNED /*< empty */\n#endif\n\n#ifdef CHERI_PURECAP\n#  include <cheriintrin.h>\n#endif\n\nEXTERN_C_BEGIN\n\ntypedef GC_uintptr_t GC_funcptr_uint;\n#define FUNCPTR_IS_DATAPTR\n\ntypedef unsigned int unsigned32;\n\n#define hblk GC_hblk_s\nstruct hblk;\n\ntypedef struct hblkhdr hdr;\n\nEXTERN_C_END\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n#ifndef GC_HEADERS_H\n#define GC_HEADERS_H\n\n#if !defined(GC_PRIVATE_H) && !defined(CPPCHECK)\n#  error gc_hdrs.h should be included from gc_priv.h\n#endif\n\n#if CPP_WORDSZ != 32 && CPP_WORDSZ < 36 && !defined(CPPCHECK)\n#  error Get a real machine\n#endif\n\nEXTERN_C_BEGIN\n\n/*\n * The 2-level tree data structure that is used to find block headers.\n * If there are more than 32 bits in a pointer, the top level is a hash\n * table.\n *\n * This defines `HDR()`, `GET_HDR()`, and `SET_HDR()`, the main macros\n * used to retrieve and set object headers.\n *\n * We take advantage of a header lookup cache.  This is a locally declared\n * direct mapped cache, used inside the marker.  The `HC_GET_HDR()` macro\n * uses and maintains this cache.  Assuming we get reasonable hit rates,\n * this saves a few memory references from each pointer validation.\n */\n\n#if CPP_WORDSZ > 32\n#  define HASH_TL\n#endif\n\n/* Define appropriate out-degrees for each of the two tree levels. */\n#if defined(LARGE_CONFIG) || !defined(SMALL_CONFIG)\n#  define LOG_BOTTOM_SZ 10\n#else\n/* Keep top index size reasonable with smaller blocks. */\n#  define LOG_BOTTOM_SZ 11\n#endif\n#define BOTTOM_SZ (1 << LOG_BOTTOM_SZ)\n\n#ifndef HASH_TL\n#  define LOG_TOP_SZ (CPP_WORDSZ - LOG_BOTTOM_SZ - LOG_HBLKSIZE)\n#else\n#  define LOG_TOP_SZ 11\n#endif\n#define TOP_SZ (1 << LOG_TOP_SZ)\n\n#ifdef COUNT_HDR_CACHE_HITS\nextern word GC_hdr_cache_hits; /*< used for debugging/profiling */\nextern word GC_hdr_cache_misses;\n#  define HC_HIT() (void)(++GC_hdr_cache_hits)\n#  define HC_MISS() (void)(++GC_hdr_cache_misses)\n#else\n#  define HC_HIT() (void)0\n#  define HC_MISS() (void)0\n#endif\n\ntypedef struct hce {\n  word block_addr; /*< right-shifted by `LOG_HBLKSIZE` */\n  hdr *hce_hdr;\n} hdr_cache_entry;\n\n#define HDR_CACHE_SIZE 8 /*< a power of two */\n\n#define DECLARE_HDR_CACHE hdr_cache_entry hdr_cache[HDR_CACHE_SIZE]\n\n#define INIT_HDR_CACHE BZERO(hdr_cache, sizeof(hdr_cache))\n\n#define HCE(h) (hdr_cache + ((ADDR(h) >> LOG_HBLKSIZE) & (HDR_CACHE_SIZE - 1)))\n\n#define HCE_VALID_FOR(hce, h) ((hce)->block_addr == (ADDR(h) >> LOG_HBLKSIZE))\n\n#define HCE_HDR(h) ((hce)->hce_hdr)\n\n#ifdef PRINT_BLACK_LIST\n/*\n * Handle a header cache miss.  Returns a pointer to the header\n * corresponding to `p`, if the latter can possibly be a valid object\n * pointer, and `NULL` otherwise.  Guaranteed to return `NULL` for\n * a pointer past the first page of an object unless both\n * `GC_all_interior_pointers` is set and `p` is in fact a valid object\n * pointer.  Never returns a pointer to a free `hblk`.\n */\nGC_INNER hdr *GC_header_cache_miss(ptr_t p, hdr_cache_entry *hce,\n                                   ptr_t source);\n\n#  define HEADER_CACHE_MISS(p, hce, source) \\\n    GC_header_cache_miss(p, hce, source)\n#else\nGC_INNER hdr *GC_header_cache_miss(ptr_t p, hdr_cache_entry *hce);\n#  define HEADER_CACHE_MISS(p, hce, source) GC_header_cache_miss(p, hce)\n#endif\n\n/*\n * Set `hhdr` to the header for `p`.  Analogous to `GET_HDR()` below,\n * except that in the case of large objects, it gets the header for the\n * object beginning if `GC_all_interior_pointers` is true.  Sets `hhdr`\n * to `NULL` if `p` points to somewhere other than the first page of an\n * object, and it is not a valid pointer to the object.\n */\n#define HC_GET_HDR(p, hhdr, source)                \\\n  { /*< cannot use `do ... while (0)` here */      \\\n    hdr_cache_entry *hce = HCE(p);                 \\\n    if (LIKELY(HCE_VALID_FOR(hce, p))) {           \\\n      HC_HIT();                                    \\\n      hhdr = hce->hce_hdr;                         \\\n    } else {                                       \\\n      hhdr = HEADER_CACHE_MISS(p, hce, source);    \\\n      if (NULL == hhdr)                            \\\n        break; /*< go to the enclosing loop end */ \\\n    }                                              \\\n  }\n\ntypedef struct bi {\n  /*\n   * The bottom-level index contains one of three kinds of values:\n   *   - 0 means we are not responsible for this block, or this is\n   *     a block other than the first one in a free block;\n   *   - 1 < (long)`x` <= `MAX_JUMP` means the block starts at least\n   *     `x * HBLKSIZE` bytes before the current address;\n   *   - a valid pointer points to a `hdr` structure (the above cannot\n   *     be valid pointers due to the `GET_MEM()` return convention).\n   */\n  hdr *index[BOTTOM_SZ];\n\n  /*\n   * All indices are linked in the ascending and descending orders,\n   * respectively.\n   */\n  struct bi *asc_link;\n  struct bi *desc_link;\n\n  word key; /*< high-order address bits */\n#ifdef HASH_TL\n  struct bi *hash_link; /*< hash chain link */\n#endif\n} bottom_index;\n\n#define MAX_JUMP (HBLKSIZE - 1)\n\n#define HDR_FROM_BI(bi, p) \\\n  (bi)->index[(ADDR(p) >> LOG_HBLKSIZE) & (BOTTOM_SZ - 1)]\n#ifndef HASH_TL\n#  define BI(p) GC_top_index[ADDR(p) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE)]\n#  define HDR_INNER(p) HDR_FROM_BI(BI(p), p)\n#  ifdef SMALL_CONFIG\n#    define HDR(p) GC_find_header(p)\n#  else\n#    define HDR(p) HDR_INNER(p)\n#  endif\n#  define GET_BI(p, bottom_indx) (void)((bottom_indx) = BI(p))\n#  define GET_HDR(p, hhdr) (void)((hhdr) = HDR(p))\n#  define SET_HDR(p, hhdr) (void)(HDR_INNER(p) = (hhdr))\n#  define GET_HDR_ADDR(p, ha) (void)((ha) = &HDR_INNER(p))\n#else\n/* A hash function for the tree top level. */\n#  define TL_HASH(hi) ((hi) & (TOP_SZ - 1))\n/* Set `bottom_indx` to point to the bottom index for address `p`. */\n#  define GET_BI(p, bottom_indx)                                    \\\n    do {                                                            \\\n      REGISTER word hi = ADDR(p) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE); \\\n      REGISTER bottom_index *_bi = GC_top_index[TL_HASH(hi)];       \\\n      while (_bi->key != hi && _bi != GC_all_nils)                  \\\n        _bi = _bi->hash_link;                                       \\\n      (bottom_indx) = _bi;                                          \\\n    } while (0)\n#  define GET_HDR_ADDR(p, ha)     \\\n    do {                          \\\n      REGISTER bottom_index *bi;  \\\n      GET_BI(p, bi);              \\\n      (ha) = &HDR_FROM_BI(bi, p); \\\n    } while (0)\n#  define GET_HDR(p, hhdr)  \\\n    do {                    \\\n      REGISTER hdr **_ha;   \\\n      GET_HDR_ADDR(p, _ha); \\\n      (hhdr) = *_ha;        \\\n    } while (0)\n#  define SET_HDR(p, hhdr)          \\\n    do {                            \\\n      REGISTER bottom_index *bi;    \\\n      GET_BI(p, bi);                \\\n      GC_ASSERT(bi != GC_all_nils); \\\n      HDR_FROM_BI(bi, p) = (hhdr);  \\\n    } while (0)\n#  define HDR(p) GC_find_header(p)\n#endif\n\n/*\n * Is the result a forwarding address to someplace closer to the\n * beginning of the block or `NULL`?\n */\n#define IS_FORWARDING_ADDR_OR_NIL(hhdr) ((size_t)ADDR(hhdr) <= MAX_JUMP)\n\n/*\n * Get an `HBLKSIZE`-aligned address closer to the beginning of the\n * block `h`.  Assumes that `hhdr` is equal to `HDR(h)`,\n * `IS_FORWARDING_ADDR(hhdr)` is true and `hhdr` is not `NULL`.\n * `HDR(result)` is expected to be non-`NULL`.\n */\n#define FORWARDED_ADDR(h, hhdr) \\\n  ((struct hblk *)(h) - (size_t)(GC_uintptr_t)(hhdr))\n\nEXTERN_C_END\n\n#endif /* GC_HEADERS_H */\n\n\n#ifndef GC_ATTR_NO_SANITIZE_ADDR\n#  ifndef ADDRESS_SANITIZER\n#    define GC_ATTR_NO_SANITIZE_ADDR /*< empty */\n#  elif GC_CLANG_PREREQ(3, 8)\n#    define GC_ATTR_NO_SANITIZE_ADDR \\\n      __attribute__((__no_sanitize__(\"address\")))\n#  else\n#    define GC_ATTR_NO_SANITIZE_ADDR __attribute__((__no_sanitize_address__))\n#  endif\n#endif /* !GC_ATTR_NO_SANITIZE_ADDR */\n\n#ifndef GC_ATTR_NO_SANITIZE_MEMORY\n#  ifndef MEMORY_SANITIZER\n#    define GC_ATTR_NO_SANITIZE_MEMORY /*< empty */\n#  elif GC_CLANG_PREREQ(3, 8)\n#    define GC_ATTR_NO_SANITIZE_MEMORY \\\n      __attribute__((__no_sanitize__(\"memory\")))\n#  else\n#    define GC_ATTR_NO_SANITIZE_MEMORY __attribute__((__no_sanitize_memory__))\n#  endif\n#endif /* !GC_ATTR_NO_SANITIZE_MEMORY */\n\n#ifndef GC_ATTR_NO_SANITIZE_THREAD\n#  ifndef THREAD_SANITIZER\n#    define GC_ATTR_NO_SANITIZE_THREAD /*< empty */\n#  elif GC_CLANG_PREREQ(3, 8)\n#    define GC_ATTR_NO_SANITIZE_THREAD \\\n      __attribute__((__no_sanitize__(\"thread\")))\n#  else\n/*\n * It seems that `no_sanitize_thread` attribute has no effect if the\n * function is inlined (as of gcc-11.1.0, at least).\n */\n#    define GC_ATTR_NO_SANITIZE_THREAD \\\n      GC_ATTR_NOINLINE __attribute__((__no_sanitize_thread__))\n#  endif\n#endif /* !GC_ATTR_NO_SANITIZE_THREAD */\n\n#define GC_ATTR_NO_SANITIZE_ADDR_MEM_THREAD           \\\n  GC_ATTR_NO_SANITIZE_ADDR GC_ATTR_NO_SANITIZE_MEMORY \\\n      GC_ATTR_NO_SANITIZE_THREAD\n\n#ifndef UNUSED_ARG\n#  define UNUSED_ARG(arg) ((void)(arg))\n#endif\n\n#ifdef HAVE_CONFIG_H\n/* The `inline` keyword is determined by `AC_C_INLINE` of `autoconf`. */\n#  define GC_INLINE static inline\n#elif defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined(__DMC__) \\\n    || (GC_GNUC_PREREQ(3, 0) && defined(__STRICT_ANSI__))                \\\n    || defined(__BORLANDC__) || defined(__WATCOMC__)\n#  define GC_INLINE static __inline\n#elif GC_GNUC_PREREQ(3, 0) || defined(__sun)\n#  define GC_INLINE static inline\n#else\n#  define GC_INLINE static\n#endif\n\n#ifndef GC_ATTR_NOINLINE\n#  if GC_GNUC_PREREQ(4, 0)\n#    define GC_ATTR_NOINLINE __attribute__((__noinline__))\n#  elif _MSC_VER >= 1400\n#    define GC_ATTR_NOINLINE __declspec(noinline)\n#  else\n#    define GC_ATTR_NOINLINE /*< empty */\n#  endif\n#endif\n\n#ifndef GC_API_OSCALL\n/* This is used to identify GC routines called by name from OS. */\n#  if defined(__GNUC__)\n#    if GC_GNUC_PREREQ(4, 0) && !defined(GC_NO_VISIBILITY)\n/* Same as `GC_API` macro if `GC_DLL` one is defined. */\n#      define GC_API_OSCALL extern __attribute__((__visibility__(\"default\")))\n#    else\n/* The attribute is unsupported. */\n#      define GC_API_OSCALL extern\n#    endif\n#  else\n#    define GC_API_OSCALL GC_API\n#  endif\n#endif\n\n#ifndef GC_API_PRIV\n#  define GC_API_PRIV GC_API\n#endif\n\n#ifndef GC_API_PATCHABLE\n#  define GC_API_PATCHABLE GC_ATTR_NOINLINE GC_API\n#endif\n\n#if defined(THREADS) && !defined(NN_PLATFORM_CTR)\n/*\n * Copyright (c) 2017 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * This is a private collector header which provides an implementation of\n * `libatomic_ops` subset primitives sufficient for the collector assuming\n * that gcc atomic intrinsics are available (and have the correct\n * implementation).  This is enabled by defining `GC_BUILTIN_ATOMIC` macro.\n * Otherwise, `libatomic_ops` library is used to define the primitives.\n */\n\n#ifndef GC_ATOMIC_OPS_H\n#define GC_ATOMIC_OPS_H\n\n#ifdef GC_BUILTIN_ATOMIC\n\n\n\n\n#  ifdef __cplusplus\nextern \"C\" {\n#  endif\n\ntypedef size_t AO_t;\n\n#  ifdef GC_PRIVATE_H /*< i.e. have `GC_INLINE` */\n#    define AO_INLINE GC_INLINE\n#  else\n#    define AO_INLINE static __inline\n#  endif\n\n#  if !defined(THREAD_SANITIZER) && !defined(GC_PRIVATE_H)\n/* Similar to that in `gcconfig.h` file. */\n#    if defined(__has_feature)\n#      if __has_feature(thread_sanitizer)\n#        define THREAD_SANITIZER\n#      endif\n#    elif defined(__SANITIZE_THREAD__)\n#      define THREAD_SANITIZER\n#    endif\n#  endif /* !THREAD_SANITIZER && !GC_PRIVATE_H */\n\ntypedef unsigned char AO_TS_t;\n#  define AO_TS_CLEAR 0\n#  define AO_TS_INITIALIZER ((AO_TS_t)AO_TS_CLEAR)\n#  if defined(__GCC_ATOMIC_TEST_AND_SET_TRUEVAL) && !defined(CPPCHECK)\n#    define AO_TS_SET __GCC_ATOMIC_TEST_AND_SET_TRUEVAL\n#  else\n#    define AO_TS_SET (AO_TS_t)1 /*< true */\n#  endif\n#  define AO_CLEAR(p) __atomic_clear(p, __ATOMIC_RELEASE)\n#  define AO_test_and_set_acquire(p) \\\n    (__atomic_test_and_set(p, __ATOMIC_ACQUIRE) ? AO_TS_SET : AO_TS_CLEAR)\n#  define AO_HAVE_test_and_set_acquire\n\n#  define AO_compiler_barrier() __atomic_signal_fence(__ATOMIC_SEQ_CST)\n\n#  if defined(THREAD_SANITIZER) && !defined(AO_USE_ATOMIC_THREAD_FENCE)\n/*\n * Workaround a compiler warning (reported by gcc-11, at least) that\n * `__atomic_thread_fence` is unsupported with thread sanitizer.\n */\nAO_INLINE void\nAO_nop_full(void)\n{\n  volatile AO_TS_t dummy = AO_TS_INITIALIZER;\n  (void)__atomic_test_and_set(&dummy, __ATOMIC_SEQ_CST);\n}\n#  else\n#    define AO_nop_full() __atomic_thread_fence(__ATOMIC_SEQ_CST)\n#  endif\n#  define AO_HAVE_nop_full\n\n#  define AO_fetch_and_add(p, v) __atomic_fetch_add(p, v, __ATOMIC_RELAXED)\n#  define AO_HAVE_fetch_and_add\n#  define AO_fetch_and_add1(p) AO_fetch_and_add(p, 1)\n#  define AO_HAVE_fetch_and_add1\n#  define AO_fetch_and_sub1(p) AO_fetch_and_add(p, ~(AO_t)0 /* -1 */)\n#  define AO_HAVE_fetch_and_sub1\n\n#  define AO_or(p, v) (void)__atomic_or_fetch(p, v, __ATOMIC_RELAXED)\n#  define AO_HAVE_or\n\n#  define AO_load(p) __atomic_load_n(p, __ATOMIC_RELAXED)\n#  define AO_HAVE_load\n#  define AO_load_acquire(p) __atomic_load_n(p, __ATOMIC_ACQUIRE)\n#  define AO_HAVE_load_acquire\n/*\n * `AO_load_acquire_read(p)` is not defined as it is unused, but we need\n * its `AO_HAVE_` macro defined.\n */\n#  define AO_HAVE_load_acquire_read\n\n#  define AO_store(p, v) __atomic_store_n(p, v, __ATOMIC_RELAXED)\n#  define AO_HAVE_store\n#  define AO_store_release(p, v) __atomic_store_n(p, v, __ATOMIC_RELEASE)\n#  define AO_HAVE_store_release\n#  define AO_store_release_write(p, v) AO_store_release(p, v)\n#  define AO_HAVE_store_release_write\n\n#  define AO_char_load(p) __atomic_load_n(p, __ATOMIC_RELAXED)\n#  define AO_HAVE_char_load\n#  define AO_char_store(p, v) __atomic_store_n(p, v, __ATOMIC_RELAXED)\n#  define AO_HAVE_char_store\n#  define AO_char_fetch_and_add1(p) __atomic_fetch_add(p, 1, __ATOMIC_RELAXED)\n#  define AO_HAVE_char_fetch_and_add1\n\n#  ifdef AO_REQUIRE_CAS\nAO_INLINE int\nAO_compare_and_swap_release(volatile AO_t *p, AO_t ov, AO_t nv)\n{\n  return (int)__atomic_compare_exchange_n(p, &ov, nv, 0, __ATOMIC_RELEASE,\n                                          __ATOMIC_RELAXED /* on fail */);\n}\n#    define AO_HAVE_compare_and_swap_release\n#  endif\n\n#  ifdef __cplusplus\n} /* extern \"C\" */\n#  endif\n\n#  ifndef NO_LOCKFREE_AO_OR\n/* `__atomic_or_fetch()` is assumed to be lock-free. */\n#    define HAVE_LOCKFREE_AO_OR 1\n#  endif\n\n#else\n/* Fall back to `libatomic_ops`. */\n#  include \"atomic_ops.h\"\n\n/*\n * `AO_compiler_barrier`, `AO_load` and `AO_store` should be defined\n * for all targets; the rest of the primitives are guaranteed to exist\n * only if `AO_REQUIRE_CAS` is defined (or if the corresponding\n * `AO_HAVE_` macro is defined).  i686 and x86_64 targets have\n * `AO_nop_full`, `AO_load_acquire`, `AO_store_release`, at least.\n */\n#  if (!defined(AO_HAVE_load) || !defined(AO_HAVE_store)) && !defined(CPPCHECK)\n#    error AO_load or AO_store is missing; probably old version of atomic_ops\n#  endif\n\n#endif /* !GC_BUILTIN_ATOMIC */\n\n#if defined(GC_BUILTIN_ATOMIC) || defined(__CHERI_PURE_CAPABILITY__)\n/*\n * Assume that gcc atomic intrinsics are available (and have correct\n * implementation).  `p` should be of a pointer to `ptr_t` (`char *`) value.\n */\n#  define GC_cptr_load(p) __atomic_load_n(p, __ATOMIC_RELAXED)\n#  define GC_cptr_load_acquire(p) __atomic_load_n(p, __ATOMIC_ACQUIRE)\n#  define GC_cptr_load_acquire_read(p) GC_cptr_load_acquire(p)\n#  define GC_cptr_store(p, v) __atomic_store_n(p, v, __ATOMIC_RELAXED)\n#  define GC_cptr_store_release(p, v) __atomic_store_n(p, v, __ATOMIC_RELEASE)\n#  define GC_cptr_store_release_write(p, v) GC_cptr_store_release(p, v)\n#  ifdef AO_REQUIRE_CAS\nAO_INLINE int\nGC_cptr_compare_and_swap(char *volatile *p, char *ov, char *nv)\n{\n  return (int)__atomic_compare_exchange_n(p, &ov, nv, 0, __ATOMIC_RELAXED,\n                                          __ATOMIC_RELAXED);\n}\n#  endif\n#else\n/*\n * Redirect to the `AO_` primitives.  Assume the size of `AO_t` matches\n * that of a pointer.\n */\n#  define GC_cptr_load(p) (char *)AO_load((volatile AO_t *)(p))\n#  define GC_cptr_load_acquire(p) (char *)AO_load_acquire((volatile AO_t *)(p))\n#  define GC_cptr_load_acquire_read(p) \\\n    (char *)AO_load_acquire_read((volatile AO_t *)(p))\n#  define GC_cptr_store(p, v) AO_store((volatile AO_t *)(p), (AO_t)(v))\n#  define GC_cptr_store_release(p, v) \\\n    AO_store_release((volatile AO_t *)(p), (AO_t)(v))\n#  define GC_cptr_store_release_write(p, v) \\\n    AO_store_release_write((volatile AO_t *)(p), (AO_t)(v))\n#  ifdef AO_REQUIRE_CAS\n#    define GC_cptr_compare_and_swap(p, ov, nv) \\\n      AO_compare_and_swap((volatile AO_t *)(p), (AO_t)(ov), (AO_t)(nv))\n#  endif\n#endif /* !GC_BUILTIN_ATOMIC */\n\n#endif /* GC_ATOMIC_OPS_H */\n\n#  ifndef AO_HAVE_compiler_barrier\n#    define AO_HAVE_compiler_barrier 1\n#  endif\n#endif\n\n#ifdef ANY_MSWIN\n#  ifndef WIN32_LEAN_AND_MEAN\n#    define WIN32_LEAN_AND_MEAN 1\n#  endif\n#  define NOSERVICE\n#  include <windows.h>\n\n/* This is included strictly after the platform `windows.h` file. */\n#  include <winbase.h>\n#endif /* ANY_MSWIN */\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n#ifndef GC_LOCKS_H\n#define GC_LOCKS_H\n\n#if !defined(GC_PRIVATE_H) && !defined(CPPCHECK)\n#  error gc_locks.h should be included from gc_priv.h\n#endif\n\n/*\n * Mutual exclusion between allocator/collector routines.  Needed if\n * there is more than one allocator thread.  Note that `I_HOLD_LOCK`,\n * `I_DONT_HOLD_LOCK` and `I_HOLD_READER_LOCK` macros are used only\n * positively in assertions, and may return `TRUE` in the \"do not know\"\n * case.\n */\n\n#ifdef THREADS\n\nEXTERN_C_BEGIN\n\n#  if defined(NN_PLATFORM_CTR) || defined(NINTENDO_SWITCH)\nextern void GC_lock(void);\nextern void GC_unlock(void);\n#    define UNCOND_LOCK() GC_lock()\n#    define UNCOND_UNLOCK() GC_unlock()\n#    ifdef GC_ASSERTIONS\n#      define SET_LOCK_HOLDER() (void)0\n#    endif\n#  endif\n\n#  if (!defined(AO_HAVE_test_and_set_acquire) || defined(GC_WIN32_THREADS) \\\n       || defined(LINT2) || defined(RTEMS) || defined(SN_TARGET_PS3)       \\\n       || defined(BASE_ATOMIC_OPS_EMULATED) || defined(USE_RWLOCK))        \\\n      && defined(GC_PTHREADS)\n#    define USE_PTHREAD_LOCKS\n#    undef USE_SPIN_LOCK\n#    if (defined(GC_WIN32_THREADS) || defined(LINT2) || defined(USE_RWLOCK)) \\\n        && !defined(NO_PTHREAD_TRYLOCK)\n/*\n * `pthread_mutex_trylock` may not win in `GC_lock` on Win32, due to\n * built-in support for spinning first?\n */\n#      define NO_PTHREAD_TRYLOCK\n#    endif\n#  endif\n\n#  if defined(GC_WIN32_THREADS) && !defined(USE_PTHREAD_LOCKS) \\\n      || defined(GC_PTHREADS)\n/* A value which is not equal to `NUMERIC_THREAD_ID(id)` for any thread. */\n#    define NO_THREAD ((unsigned long)(-1L))\n#    ifdef GC_ASSERTIONS\nGC_EXTERN unsigned long GC_lock_holder;\n#      define UNSET_LOCK_HOLDER() (void)(GC_lock_holder = NO_THREAD)\n#    endif\n#  endif /* GC_WIN32_THREADS || GC_PTHREADS */\n\n#  if defined(GC_WIN32_THREADS) && !defined(USE_PTHREAD_LOCKS)\n#    ifdef USE_RWLOCK\nGC_EXTERN SRWLOCK GC_allocate_ml;\n#    else\nGC_EXTERN CRITICAL_SECTION GC_allocate_ml;\n#    endif\n#    ifdef GC_ASSERTIONS\n#      define SET_LOCK_HOLDER() (void)(GC_lock_holder = GetCurrentThreadId())\n#      define I_HOLD_LOCK() \\\n        (!GC_need_to_lock || GC_lock_holder == GetCurrentThreadId())\n#      ifdef THREAD_SANITIZER\n#        define I_DONT_HOLD_LOCK() TRUE /*< conservatively say yes */\n#      else\n#        define I_DONT_HOLD_LOCK() \\\n          (!GC_need_to_lock || GC_lock_holder != GetCurrentThreadId())\n#      endif\n#      ifdef USE_RWLOCK\n#        define UNCOND_READER_LOCK()               \\\n          {                                        \\\n            GC_ASSERT(I_DONT_HOLD_LOCK());         \\\n            AcquireSRWLockShared(&GC_allocate_ml); \\\n          }\n#        define UNCOND_READER_UNLOCK()             \\\n          {                                        \\\n            GC_ASSERT(I_DONT_HOLD_LOCK());         \\\n            ReleaseSRWLockShared(&GC_allocate_ml); \\\n          }\n#        define UNCOND_LOCK()                         \\\n          {                                           \\\n            GC_ASSERT(I_DONT_HOLD_LOCK());            \\\n            AcquireSRWLockExclusive(&GC_allocate_ml); \\\n            SET_LOCK_HOLDER();                        \\\n          }\n#        define UNCOND_UNLOCK()                       \\\n          {                                           \\\n            GC_ASSERT(I_HOLD_LOCK());                 \\\n            UNSET_LOCK_HOLDER();                      \\\n            ReleaseSRWLockExclusive(&GC_allocate_ml); \\\n          }\n#      else\n#        define UNCOND_LOCK()                      \\\n          {                                        \\\n            GC_ASSERT(I_DONT_HOLD_LOCK());         \\\n            EnterCriticalSection(&GC_allocate_ml); \\\n            SET_LOCK_HOLDER();                     \\\n          }\n#        define UNCOND_UNLOCK()                    \\\n          {                                        \\\n            GC_ASSERT(I_HOLD_LOCK());              \\\n            UNSET_LOCK_HOLDER();                   \\\n            LeaveCriticalSection(&GC_allocate_ml); \\\n          }\n#      endif\n#    else\n#      ifdef USE_RWLOCK\n#        define UNCOND_READER_LOCK() AcquireSRWLockShared(&GC_allocate_ml)\n#        define UNCOND_READER_UNLOCK() ReleaseSRWLockShared(&GC_allocate_ml)\n#        define UNCOND_LOCK() AcquireSRWLockExclusive(&GC_allocate_ml)\n#        define UNCOND_UNLOCK() ReleaseSRWLockExclusive(&GC_allocate_ml)\n#      else\n#        define UNCOND_LOCK() EnterCriticalSection(&GC_allocate_ml)\n#        define UNCOND_UNLOCK() LeaveCriticalSection(&GC_allocate_ml)\n#      endif\n#    endif /* !GC_ASSERTIONS */\n#  elif defined(GC_PTHREADS)\nEXTERN_C_END\n#    include <pthread.h>\nEXTERN_C_BEGIN\n/*\n * POSIX allows `pthread_t` to be a structure type, though it rarely is.\n * Unfortunately, we need to use a `pthread_t` to index a data structure.\n * It also helps if comparisons do not involve a function call.\n * Hence we introduce platform-dependent macros to compare `pthread_t` ids\n * and to map them to integers (of `unsigned long` type).  This mapping\n * does not need to result in different values for each thread, though\n * that should be true as much as possible.\n */\n#    if !defined(GC_WIN32_PTHREADS)\n#      define NUMERIC_THREAD_ID(id) ((unsigned long)(GC_uintptr_t)(id))\n#      define THREAD_EQUAL(id1, id2) ((id1) == (id2))\n#      define NUMERIC_THREAD_ID_UNIQUE\n#    elif defined(__WINPTHREADS_VERSION_MAJOR) /*< winpthreads */\n#      define NUMERIC_THREAD_ID(id) ((unsigned long)(id))\n#      define THREAD_EQUAL(id1, id2) ((id1) == (id2))\n/* `NUMERIC_THREAD_ID()` is 32-bit and, thus, not unique on Win64. */\n#      ifndef _WIN64\n#        define NUMERIC_THREAD_ID_UNIQUE\n#      endif\n#    else /* pthreads-win32 */\n#      define NUMERIC_THREAD_ID(id) ((unsigned long)(word)(id.p))\n/*\n * The platform on which `pthread_t` is a structure.\n * Using documented internal details of pthreads-win32 library.\n * Faster than `pthread_equal()`.  Should not change with the\n * future versions of pthreads-win32 library.\n */\n#      define THREAD_EQUAL(id1, id2) (id1.p == id2.p && id1.x == id2.x)\n/*\n * Generic definitions based on `pthread_equal()` always work but will\n * result in poor performance (as `NUMERIC_THREAD_ID()` might give\n * a constant value) and weak assertion checking.\n */\n#      undef NUMERIC_THREAD_ID_UNIQUE\n#    endif\n\n#    ifdef SN_TARGET_PSP2\nEXTERN_C_END\n#      include \"psp2-support.h\"\nEXTERN_C_BEGIN\nGC_EXTERN WapiMutex GC_allocate_ml_PSP2;\n#      define UNCOND_LOCK()                           \\\n        {                                             \\\n          int res;                                    \\\n          GC_ASSERT(I_DONT_HOLD_LOCK());              \\\n          res = PSP2_MutexLock(&GC_allocate_ml_PSP2); \\\n          GC_ASSERT(0 == res);                        \\\n          (void)res;                                  \\\n          SET_LOCK_HOLDER();                          \\\n        }\n#      define UNCOND_UNLOCK()                           \\\n        {                                               \\\n          int res;                                      \\\n          GC_ASSERT(I_HOLD_LOCK());                     \\\n          UNSET_LOCK_HOLDER();                          \\\n          res = PSP2_MutexUnlock(&GC_allocate_ml_PSP2); \\\n          GC_ASSERT(0 == res);                          \\\n          (void)res;                                    \\\n        }\n\n#    elif (!defined(THREAD_LOCAL_ALLOC) || defined(USE_SPIN_LOCK))   \\\n        && !defined(USE_PTHREAD_LOCKS) && !defined(THREAD_SANITIZER) \\\n        && !defined(USE_RWLOCK)\n/*\n * In the `THREAD_LOCAL_ALLOC` case, the allocator lock tends to\n * be held for long periods, if it is held at all.\n * Thus spinning and sleeping for fixed periods are likely to result\n * in significant wasted time.  We thus rely mostly on queued locks.\n */\n#      undef USE_SPIN_LOCK\n#      define USE_SPIN_LOCK\nGC_INNER void GC_lock(void);\n#      ifdef GC_ASSERTIONS\n#        define UNCOND_LOCK()                                            \\\n          {                                                              \\\n            GC_ASSERT(I_DONT_HOLD_LOCK());                               \\\n            if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_SET) \\\n              GC_lock();                                                 \\\n            SET_LOCK_HOLDER();                                           \\\n          }\n#        define UNCOND_UNLOCK()          \\\n          {                              \\\n            GC_ASSERT(I_HOLD_LOCK());    \\\n            UNSET_LOCK_HOLDER();         \\\n            AO_CLEAR(&GC_allocate_lock); \\\n          }\n#      else\n#        define UNCOND_LOCK()                                            \\\n          {                                                              \\\n            if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_SET) \\\n              GC_lock();                                                 \\\n          }\n#        define UNCOND_UNLOCK() AO_CLEAR(&GC_allocate_lock)\n#      endif /* !GC_ASSERTIONS */\n#    else\n#      ifndef USE_PTHREAD_LOCKS\n#        define USE_PTHREAD_LOCKS\n#      endif\n#    endif /* THREAD_LOCAL_ALLOC || USE_PTHREAD_LOCKS */\n#    ifdef USE_PTHREAD_LOCKS\nEXTERN_C_END\n#      include <pthread.h>\nEXTERN_C_BEGIN\n#      ifdef GC_ASSERTIONS\nGC_INNER void GC_lock(void);\n#        define UNCOND_LOCK()              \\\n          {                                \\\n            GC_ASSERT(I_DONT_HOLD_LOCK()); \\\n            GC_lock();                     \\\n            SET_LOCK_HOLDER();             \\\n          }\n#      endif\n#      ifdef USE_RWLOCK\nGC_EXTERN pthread_rwlock_t GC_allocate_ml;\n#        ifdef GC_ASSERTIONS\n#          define UNCOND_READER_LOCK()                      \\\n            {                                               \\\n              GC_ASSERT(I_DONT_HOLD_LOCK());                \\\n              (void)pthread_rwlock_rdlock(&GC_allocate_ml); \\\n            }\n#          define UNCOND_READER_UNLOCK()                    \\\n            {                                               \\\n              GC_ASSERT(I_DONT_HOLD_LOCK());                \\\n              (void)pthread_rwlock_unlock(&GC_allocate_ml); \\\n            }\n#          define UNCOND_UNLOCK()                           \\\n            {                                               \\\n              GC_ASSERT(I_HOLD_LOCK());                     \\\n              UNSET_LOCK_HOLDER();                          \\\n              (void)pthread_rwlock_unlock(&GC_allocate_ml); \\\n            }\n#        else\n#          define UNCOND_READER_LOCK() \\\n            (void)pthread_rwlock_rdlock(&GC_allocate_ml)\n#          define UNCOND_READER_UNLOCK() UNCOND_UNLOCK()\n#          define UNCOND_LOCK() (void)pthread_rwlock_wrlock(&GC_allocate_ml)\n#          define UNCOND_UNLOCK() (void)pthread_rwlock_unlock(&GC_allocate_ml)\n#        endif /* !GC_ASSERTIONS */\n#      else\nGC_EXTERN pthread_mutex_t GC_allocate_ml;\n#        ifdef GC_ASSERTIONS\n#          define UNCOND_UNLOCK()                    \\\n            {                                        \\\n              GC_ASSERT(I_HOLD_LOCK());              \\\n              UNSET_LOCK_HOLDER();                   \\\n              pthread_mutex_unlock(&GC_allocate_ml); \\\n            }\n#        else\n#          if defined(NO_PTHREAD_TRYLOCK)\n#            define UNCOND_LOCK() pthread_mutex_lock(&GC_allocate_ml)\n#          else\nGC_INNER void GC_lock(void);\n#            define UNCOND_LOCK()                                \\\n              {                                                  \\\n                if (pthread_mutex_trylock(&GC_allocate_ml) != 0) \\\n                  GC_lock();                                     \\\n              }\n#          endif\n#          define UNCOND_UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)\n#        endif /* !GC_ASSERTIONS */\n#      endif\n#    endif /* USE_PTHREAD_LOCKS */\n#    ifdef GC_ASSERTIONS\n/* The allocator lock holder. */\n#      define SET_LOCK_HOLDER() \\\n        (void)(GC_lock_holder = NUMERIC_THREAD_ID(pthread_self()))\n#      define I_HOLD_LOCK() \\\n        (!GC_need_to_lock   \\\n         || GC_lock_holder == NUMERIC_THREAD_ID(pthread_self()))\n#      if !defined(NUMERIC_THREAD_ID_UNIQUE) || defined(THREAD_SANITIZER)\n#        define I_DONT_HOLD_LOCK() TRUE /*< conservatively say yes */\n#      else\n#        define I_DONT_HOLD_LOCK() \\\n          (!GC_need_to_lock        \\\n           || GC_lock_holder != NUMERIC_THREAD_ID(pthread_self()))\n#      endif\n#    endif /* GC_ASSERTIONS */\n#    if !defined(GC_WIN32_THREADS)\n/*\n * A hint that we are in the collector and holding the allocator lock\n * for an extended period.\n */\nGC_EXTERN volatile unsigned char GC_collecting;\n\n#      ifdef AO_HAVE_char_store\n#        if defined(GC_ASSERTIONS) && defined(AO_HAVE_char_fetch_and_add1)\n/* Ensure `ENTER_GC()` is not used recursively. */\n#          define ENTER_GC() GC_ASSERT(!AO_char_fetch_and_add1(&GC_collecting))\n#        else\n#          define ENTER_GC() AO_char_store(&GC_collecting, TRUE)\n#        endif\n#        define EXIT_GC() AO_char_store(&GC_collecting, FALSE)\n#      else\n#        define ENTER_GC() (void)(GC_collecting = TRUE)\n#        define EXIT_GC() (void)(GC_collecting = FALSE)\n#      endif\n#    endif\n#  endif /* GC_PTHREADS */\n#  if defined(GC_ALWAYS_MULTITHREADED) \\\n      && (defined(USE_PTHREAD_LOCKS) || defined(USE_SPIN_LOCK))\n#    define GC_need_to_lock TRUE\n#    define set_need_to_lock() (void)0\n#  else\n#    if defined(GC_ALWAYS_MULTITHREADED) && !defined(CPPCHECK)\n#      error Runtime initialization of the allocator lock is needed!\n#    endif\n#    undef GC_ALWAYS_MULTITHREADED\n#    ifdef THREAD_SANITIZER\n/*\n * To workaround TSan false positive (e.g., when `GC_pthread_create()` is\n * called from multiple threads in parallel), do not set `GC_need_to_lock`\n * if it is already set.\n */\n#      define set_need_to_lock()                     \\\n        (void)(*(GC_bool volatile *)&GC_need_to_lock \\\n                   ? FALSE                           \\\n                   : (GC_need_to_lock = TRUE))\n#    else\n#      define set_need_to_lock() (void)(GC_need_to_lock = TRUE)\n/* We are multi-threaded now. */\n#    endif\n#  endif\n\nEXTERN_C_END\n\n#else /* !THREADS */\n#  define LOCK() (void)0\n#  define UNLOCK() (void)0\n#  ifdef GC_ASSERTIONS\n/*\n * `I_HOLD_LOCK()` and `I_DONT_HOLD_LOCK()` are used only in positive\n * assertions or to test whether we still need to acquire the allocator\n * lock; `TRUE` works in either case.\n */\n#    define I_HOLD_LOCK() TRUE\n#    define I_DONT_HOLD_LOCK() TRUE\n#  endif\n#endif /* !THREADS */\n\n#if defined(UNCOND_LOCK) && !defined(LOCK)\n#  if (defined(LINT2) && defined(USE_PTHREAD_LOCKS)) \\\n      || defined(GC_ALWAYS_MULTITHREADED)\n/*\n * Instruct code analysis tools not to care about `GC_need_to_lock`\n * influence to `LOCK`/`UNLOCK` semantic.\n */\n#    define LOCK() UNCOND_LOCK()\n#    define UNLOCK() UNCOND_UNLOCK()\n#    ifdef UNCOND_READER_LOCK\n#      define READER_LOCK() UNCOND_READER_LOCK()\n#      define READER_UNLOCK() UNCOND_READER_UNLOCK()\n#    endif\n#  else\n/* At least two thread running; need to lock. */\n#    define LOCK()           \\\n      do {                   \\\n        if (GC_need_to_lock) \\\n          UNCOND_LOCK();     \\\n      } while (0)\n#    define UNLOCK()         \\\n      do {                   \\\n        if (GC_need_to_lock) \\\n          UNCOND_UNLOCK();   \\\n      } while (0)\n#    ifdef UNCOND_READER_LOCK\n#      define READER_LOCK()       \\\n        do {                      \\\n          if (GC_need_to_lock)    \\\n            UNCOND_READER_LOCK(); \\\n        } while (0)\n#      define READER_UNLOCK()       \\\n        do {                        \\\n          if (GC_need_to_lock)      \\\n            UNCOND_READER_UNLOCK(); \\\n        } while (0)\n#    endif\n#  endif\n#endif /* UNCOND_LOCK && !LOCK */\n\n#ifdef READER_LOCK\n#  define HAS_REAL_READER_LOCK\n/* TODO: Implement I_HOLD_READER_LOCK, conservatively say yes for now. */\n#  define I_HOLD_READER_LOCK() TRUE\n#else\n#  define READER_LOCK() LOCK()\n#  define READER_UNLOCK() UNLOCK()\n#  ifdef GC_ASSERTIONS\n/*\n * A macro to check that the allocator lock is held at least in the\n * reader mode.\n */\n#    define I_HOLD_READER_LOCK() I_HOLD_LOCK()\n#  endif\n#endif /* !READER_LOCK */\n\n/*\n * A variant of `READER_UNLOCK()` which ensures that data written\n * before the unlock will be visible to the thread which acquires the\n * allocator lock in the exclusive mode.  But according to some `rwlock`\n * documentation: writers synchronize with prior writers and readers.\n */\n#define READER_UNLOCK_RELEASE() READER_UNLOCK()\n\n#ifndef ENTER_GC\n#  define ENTER_GC()\n#  define EXIT_GC()\n#endif\n\n#endif /* GC_LOCKS_H */\n\n\n#ifdef GC_ASSERTIONS\n#  define GC_ASSERT(e)                                                   \\\n    do {                                                                 \\\n      if (UNLIKELY(!(e))) {                                              \\\n        GC_err_printf(\"Assertion failure: %s:%d\\n\", __FILE__, __LINE__); \\\n        ABORT(\"assertion failure\");                                      \\\n      }                                                                  \\\n    } while (0)\n#else\n#  define GC_ASSERT(e)\n#endif\n\n#include \"gc/gc_inline.h\"\n\n/*\n * Prevent certain compiler warnings by making a pointer-related cast\n * through a \"pointer-sized\" numeric type.\n */\n#define CAST_THRU_UINTPTR(t, x) ((t)(GC_uintptr_t)(x))\n\n#define CAST_AWAY_VOLATILE_PVOID(p) \\\n  CAST_THRU_UINTPTR(/* no volatile */ void *, p)\n\n/*\n * Convert an `unsigned` value to a `void` pointer.  Typically used to\n * print a numeric value using \"%p\" format specifier.  The pointer is not\n * supposed to be dereferenced.\n */\n#define NUMERIC_TO_VPTR(v) ((void *)(GC_uintptr_t)(v))\n\n/* Create a `ptr_t` pointer from a number (of `word` type). */\n#define MAKE_CPTR(w) ((ptr_t)(GC_uintptr_t)(word)(w))\n\n#define GC_WORD_MAX (~(word)0)\n\n/* Convert given pointer to its address.  Result is of `word` type. */\n#ifdef CHERI_PURECAP\n#  define ADDR(p) cheri_address_get(p)\n#else\n#  define ADDR(p) ((word)(GC_uintptr_t)(p))\n#endif\n\n#define ADDR_LT(p, q) GC_ADDR_LT(p, q)\n#define ADDR_GE(p, q) (!ADDR_LT(p, q))\n\n/*\n * Check whether pointer `p` is in range [`s`, `e_p1`).\n * `p` should not have side effects.\n */\n#define ADDR_INSIDE(p, s, e_p1) (ADDR_GE(p, s) && ADDR_LT(p, e_p1))\n\n/* Handy definitions to compare and adjust pointers in a stack. */\n#ifdef STACK_GROWS_UP\n#  define HOTTER_THAN(p, q) ADDR_LT(q, p) /*< inverse */\n#  define MAKE_COOLER(p, d) \\\n    (void)((p) -= ADDR(p) > (word)((d) * sizeof(*(p))) ? (d) : 0)\n#  define MAKE_HOTTER(p, d) (void)((p) += (d))\n#else\n#  define HOTTER_THAN(p, q) ADDR_LT(p, q)\n#  define MAKE_COOLER(p, d) \\\n    (void)((p)              \\\n           += ADDR(p) <= (word)(GC_WORD_MAX - (d) * sizeof(*(p))) ? (d) : 0)\n#  define MAKE_HOTTER(p, d) (void)((p) -= (d))\n#endif /* !STACK_GROWS_UP */\n\n/* Clear/set flags (given by a mask) in a pointer. */\n#define CPTR_CLEAR_FLAGS(p, mask) \\\n  (ptr_t)((GC_uintptr_t)(p) & ~(GC_uintptr_t)(word)(mask))\n#define CPTR_SET_FLAGS(p, mask) (ptr_t)((GC_uintptr_t)(p) | (word)(mask))\n\n/* Easily changeable parameters are below. */\n\n#ifdef ALL_INTERIOR_POINTERS\n/*\n * Forces all pointers into the interior of an object to be considered valid.\n * Also causes the sizes of all objects to be inflated by at least one byte.\n * This should suffice to guarantee that in the presence of a compiler that\n * does not perform garbage-collector-unsafe optimizations, all portable,\n * strictly ANSI conforming C programs should be safely usable with `malloc`\n * replaced by `GC_malloc` and `free` calls removed.  There are several\n * disadvantages:\n *   1. There are probably no interesting, portable, strictly ANSI-conforming\n *      C programs;\n *   2. This option makes it hard for the collector to allocate space that is\n *      not \"pointed to\" by integers, etc.  (Under SunOS 4.x with a statically\n *      linked `libc`, we empirically observed that it would be difficult to\n *      allocate individual objects larger than 100 KB; even if only smaller\n *      objects are allocated, more swap space is likely to be needed;\n *      fortunately, much of this will never be touched.)\n *\n * If you can easily avoid using this option, do.  If not, try to keep\n * individual objects small.  This is really controlled at startup, through\n * `GC_all_interior_pointers` variable.\n */\n#endif\n\nEXTERN_C_BEGIN\n\n#ifndef GC_NO_FINALIZATION\n/*\n * If `GC_finalize_on_demand` is not set, invoke eligible finalizers.\n * Otherwise: call `(*GC_finalizer_notifier)()` if there are finalizers to\n * be run, and we have not called this procedure yet this collection cycle.\n */\nGC_INNER void GC_notify_or_invoke_finalizers(void);\n\n/*\n * Perform all indicated finalization actions on unmarked objects.\n * Unreachable finalizable objects are enqueued for processing by\n * `GC_invoke_finalizers()`.  Cause disappearing links to disappear\n * and unreachable objects to be enqueued for finalization.\n * Invoked with the allocator lock held but the world is running.\n */\nGC_INNER void GC_finalize(void);\n\n#  ifndef GC_TOGGLE_REFS_NOT_NEEDED\n/* Process the \"toggle-refs\" before GC starts. */\nGC_INNER void GC_process_togglerefs(void);\n#  endif\n#  ifndef SMALL_CONFIG\nGC_INNER void GC_print_finalization_stats(void);\n#  endif\n#else\n#  define GC_notify_or_invoke_finalizers() (void)0\n#endif /* GC_NO_FINALIZATION */\n\n#if !defined(DONT_ADD_BYTE_AT_END)\n#  ifdef LINT2\n/*\n * Explicitly instruct the code analysis tool that `GC_all_interior_pointers`\n * is assumed to have only value of 0 or 1.\n */\n#    define EXTRA_BYTES ((size_t)(GC_all_interior_pointers ? 1 : 0))\n#  else\n#    define EXTRA_BYTES ((size_t)GC_all_interior_pointers)\n#  endif\n#  define MAX_EXTRA_BYTES 1\n#else\n#  define EXTRA_BYTES 0\n#  define MAX_EXTRA_BYTES 0\n#endif\n\n#ifdef LARGE_CONFIG\n#  define MINHINCR 64\n#  define MAXHINCR 4096\n#else\n/*\n * Minimum heap increment, in blocks of `HBLKSIZE`.  Note: must be multiple\n * of largest page size.\n */\n#  define MINHINCR 16\n\n/* Maximum heap increment, in blocks. */\n#  define MAXHINCR 2048\n#endif /* !LARGE_CONFIG */\n\n/* Stack saving for debugging. */\n\n#ifdef NEED_CALLINFO\nstruct callinfo {\n  GC_return_addr_t ci_pc; /*< `pc` of caller, not callee */\n#  if NARGS > 0\n  GC_hidden_pointer ci_arg[NARGS]; /*< hide to avoid retention */\n#  endif\n#  if (NFRAMES * (NARGS + 1)) % 2 == 1\n  /* Likely alignment problem. */\n  ptr_t ci_dummy;\n#  endif\n};\n\n#  ifdef SAVE_CALL_CHAIN\n/*\n * Fill in the `pc` and argument information for up to `NFRAMES` of\n * my callers.  Ignore my frame and my callers frame.\n */\nGC_INNER void GC_save_callers(struct callinfo info[NFRAMES]);\n#  endif\n\n/* Print `info` to `stderr`.  We do not hold the allocator lock. */\nGC_INNER void GC_print_callers(struct callinfo info[NFRAMES]);\n#endif /* NEED_CALLINFO */\n\nEXTERN_C_END\n\n/*\n * Macros to ensure same formatting of C array/struct/union initializer\n * across multiple versions of clang-format.\n */\n#define C_INITIALIZER_BEGIN {\n#define C_INITIALIZER_END }\n\n/* OS interface routines. */\n\n#ifndef NO_CLOCK\n#  ifdef BSD_TIME\n#    undef CLOCK_TYPE\n#    undef GET_TIME\n#    undef MS_TIME_DIFF\n#    define CLOCK_TYPE struct timeval\n#    define CLOCK_TYPE_INITIALIZER C_INITIALIZER_BEGIN 0, 0 C_INITIALIZER_END\n#    define GET_TIME(x)                  \\\n      do {                               \\\n        struct rusage rusage;            \\\n        getrusage(RUSAGE_SELF, &rusage); \\\n        x = rusage.ru_utime;             \\\n      } while (0)\n\n/*\n * Compute time difference.  `a` time is expected to be not earlier\n * than `b` one; the result has `unsigned long` type.\n */\n#    define MS_TIME_DIFF(a, b)                                            \\\n      ((unsigned long)((long)(a.tv_sec - b.tv_sec) * 1000                 \\\n                       + (long)(a.tv_usec - b.tv_usec) / 1000             \\\n                       - (a.tv_usec < b.tv_usec                           \\\n                                  && (long)(a.tv_usec - b.tv_usec) % 1000 \\\n                                         != 0                             \\\n                              ? 1                                         \\\n                              : 0)))\n\n/*\n * The nanosecond part of the time difference.  The total time difference\n * could be computed as:\n * `MS_TIME_DIFF(a, b) * 1000000 + NS_FRAC_TIME_DIFF(a, b)`.\n */\n#    define NS_FRAC_TIME_DIFF(a, b)                                          \\\n      ((unsigned long)((a.tv_usec < b.tv_usec                                \\\n                                && (long)(a.tv_usec - b.tv_usec) % 1000 != 0 \\\n                            ? 1000L                                          \\\n                            : 0)                                             \\\n                       + (long)(a.tv_usec - b.tv_usec) % 1000)               \\\n       * 1000)\n\n#  elif defined(MSWIN32) || defined(MSWINCE) || defined(WINXP_USE_PERF_COUNTER)\n#    if defined(MSWINRT_FLAVOR) || defined(WINXP_USE_PERF_COUNTER)\n#      define CLOCK_TYPE ULONGLONG\n/*\n * Note: two standalone `if` statements below are used to avoid MS VC\n * false warning (FP) about potentially uninitialized `tc` variable.\n */\n#      define GET_TIME(x)                                              \\\n        do {                                                           \\\n          LARGE_INTEGER freq, tc;                                      \\\n          if (!QueryPerformanceFrequency(&freq))                       \\\n            ABORT(\"QueryPerformanceFrequency requires WinXP+\");        \\\n          if (!QueryPerformanceCounter(&tc))                           \\\n            ABORT(\"QueryPerformanceCounter failed\");                   \\\n          x = (CLOCK_TYPE)((double)tc.QuadPart / freq.QuadPart * 1e9); \\\n          /* TODO: Call QueryPerformanceFrequency once at GC init. */  \\\n        } while (0)\n#      define MS_TIME_DIFF(a, b) ((unsigned long)(((a) - (b)) / 1000000UL))\n#      define NS_FRAC_TIME_DIFF(a, b) \\\n        ((unsigned long)(((a) - (b)) % 1000000UL))\n#    else\n#      define CLOCK_TYPE DWORD\n#      define GET_TIME(x) (void)(x = GetTickCount())\n#      define MS_TIME_DIFF(a, b) ((unsigned long)((a) - (b)))\n#      define NS_FRAC_TIME_DIFF(a, b) 0UL\n#    endif /* !WINXP_USE_PERF_COUNTER */\n\n#  elif defined(NN_PLATFORM_CTR)\n#    define CLOCK_TYPE long long\nEXTERN_C_BEGIN\nCLOCK_TYPE n3ds_get_system_tick(void);\nCLOCK_TYPE n3ds_convert_tick_to_ms(CLOCK_TYPE tick);\nEXTERN_C_END\n#    define GET_TIME(x) (void)(x = n3ds_get_system_tick())\n#    define MS_TIME_DIFF(a, b) \\\n      ((unsigned long)n3ds_convert_tick_to_ms((a) - (b)))\n/* TODO: Implement NS_FRAC_TIME_DIFF(). */\n#    define NS_FRAC_TIME_DIFF(a, b) 0UL\n\n#  elif defined(HAVE_CLOCK_GETTIME)\n#    include <time.h>\n#    define CLOCK_TYPE struct timespec\n#    define CLOCK_TYPE_INITIALIZER C_INITIALIZER_BEGIN 0, 0 C_INITIALIZER_END\n#    if defined(_POSIX_MONOTONIC_CLOCK) && !defined(NINTENDO_SWITCH)\n#      define GET_TIME(x)                               \\\n        do {                                            \\\n          if (clock_gettime(CLOCK_MONOTONIC, &x) == -1) \\\n            ABORT(\"clock_gettime failed\");              \\\n        } while (0)\n#    else\n#      define GET_TIME(x)                              \\\n        do {                                           \\\n          if (clock_gettime(CLOCK_REALTIME, &x) == -1) \\\n            ABORT(\"clock_gettime failed\");             \\\n        } while (0)\n#    endif\n#    define MS_TIME_DIFF(a, b)                                            \\\n      /* `a.tv_nsec - b.tv_nsec` is in range -1e9 to 1e9, exclusively. */ \\\n      ((unsigned long)((a).tv_nsec + (1000000L * 1000 - (b).tv_nsec))     \\\n           / 1000000UL                                                    \\\n       + ((unsigned long)((a).tv_sec - (b).tv_sec) * 1000UL) - 1000UL)\n#    define NS_FRAC_TIME_DIFF(a, b)                                   \\\n      ((unsigned long)((a).tv_nsec + (1000000L * 1000 - (b).tv_nsec)) \\\n       % 1000000UL)\n\n#  else /* !BSD_TIME && !LINUX && !NN_PLATFORM_CTR && !MSWIN32 */\n#    include <time.h>\n#    if defined(FREEBSD) && !defined(CLOCKS_PER_SEC)\n#      include <machine/limits.h>\n#      define CLOCKS_PER_SEC CLK_TCK\n#    endif\n#    if !defined(CLOCKS_PER_SEC)\n/*\n * This is technically a bug in the implementation.\n * ANSI requires that `CLOCKS_PER_SEC` be defined.  But at least under\n * SunOS 4.1.1, it is not.  Also note that the combination of ANSI C\n * and POSIX is incredibly gross here.  The type `clock_t` is used by\n * both `clock()` and `times()`.  But on some machines these use\n * different notions of a clock tick, `CLOCKS_PER_SEC` seems to apply\n * only to `clock()`.  Hence we use it here.  On many machines,\n * including SunOS, `clock()` actually uses units of microseconds (that\n * are not really clock ticks).\n */\n#      define CLOCKS_PER_SEC 1000000\n#    endif\n#    define CLOCK_TYPE clock_t\n#    define GET_TIME(x) (void)(x = clock())\n#    define MS_TIME_DIFF(a, b)                            \\\n      (CLOCKS_PER_SEC % 1000 == 0                         \\\n           ? (unsigned long)((a) - (b))                   \\\n                 / (unsigned long)(CLOCKS_PER_SEC / 1000) \\\n           : ((unsigned long)((a) - (b)) * 1000)          \\\n                 / (unsigned long)CLOCKS_PER_SEC)\n/*\n * Avoid using `double` type since some targets (like ARM) might\n * require `-lm` option for `double`-to-`long` conversion.\n */\n#    define NS_FRAC_TIME_DIFF(a, b)                                         \\\n      (CLOCKS_PER_SEC <= 1000                                               \\\n           ? 0UL                                                            \\\n           : (unsigned long)(CLOCKS_PER_SEC <= (clock_t)1000000UL           \\\n                                 ? (((a) - (b))                             \\\n                                    * ((clock_t)1000000UL / CLOCKS_PER_SEC) \\\n                                    % 1000)                                 \\\n                                       * 1000                               \\\n                                 : (CLOCKS_PER_SEC                          \\\n                                            <= (clock_t)1000000UL * 1000    \\\n                                        ? ((a) - (b))                       \\\n                                              * ((clock_t)1000000UL * 1000  \\\n                                                 / CLOCKS_PER_SEC)          \\\n                                        : (((a) - (b)) * (clock_t)1000000UL \\\n                                           * 1000)                          \\\n                                              / CLOCKS_PER_SEC)             \\\n                                       % (clock_t)1000000UL))\n#  endif /* !BSD_TIME && !MSWIN32 */\n#  ifndef CLOCK_TYPE_INITIALIZER\n/*\n * This is used to initialize `CLOCK_TYPE` variables (to some value)\n * to avoid \"variable might be uninitialized\" compiler warnings.\n */\n#    define CLOCK_TYPE_INITIALIZER 0\n#  endif\n#endif /* !NO_CLOCK */\n\n/* We use `bzero()` and `bcopy()` internally.  They may not be available. */\n#if defined(M68K) && defined(NEXT) || defined(VAX)\n#  define BCOPY_EXISTS\n#elif defined(DARWIN)\n#  include <string.h>\n#  define BCOPY_EXISTS\n#endif\n\n#if !defined(BCOPY_EXISTS) || defined(CPPCHECK)\n#  include <string.h>\n#  define BCOPY(x, y, n) memcpy(y, x, (size_t)(n))\n#  define BZERO(x, n) memset(x, 0, (size_t)(n))\n#else\n#  define BCOPY(x, y, n) bcopy((void *)(x), (void *)(y), (size_t)(n))\n#  define BZERO(x, n) bzero((void *)(x), (size_t)(n))\n#endif\n\nEXTERN_C_BEGIN\n\n#if defined(CPPCHECK) && defined(ANY_MSWIN)\n#  undef TEXT\n#  ifdef UNICODE\n#    define TEXT(s) L##s\n#  else\n#    define TEXT(s) s\n#  endif\n#endif /* CPPCHECK && ANY_MSWIN */\n\n/* Stop and restart mutator threads. */\n#if defined(NN_PLATFORM_CTR) || defined(NINTENDO_SWITCH) \\\n    || defined(GC_WIN32_THREADS) || defined(GC_PTHREADS)\nGC_INNER void GC_stop_world(void);\nGC_INNER void GC_start_world(void);\n#  define STOP_WORLD() GC_stop_world()\n#  define START_WORLD() GC_start_world()\n#else\n/* Just do a sanity check: we are not inside `GC_do_blocking()`. */\n#  define STOP_WORLD() GC_ASSERT(GC_blocked_sp == NULL)\n#  define START_WORLD()\n#endif\n\n/* Abandon ship. */\n#ifdef SMALL_CONFIG\n#  define GC_on_abort(msg) (void)0 /*< be silent on abort */\n#else\nGC_API_PRIV GC_abort_func GC_on_abort;\n#endif\n#if defined(CPPCHECK)\n#  define ABORT(msg)    \\\n    {                   \\\n      GC_on_abort(msg); \\\n      abort();          \\\n    }\n#else\n#  if defined(MSWIN_XBOX1) && !defined(DebugBreak)\n#    define DebugBreak() __debugbreak()\n#  elif defined(MSWINCE) && !defined(DebugBreak) \\\n      && (!defined(UNDER_CE) || (defined(__MINGW32CE__) && !defined(ARM32)))\n/*\n * This simplifies linking for WinCE (and, probably, does not\n * hurt debugging much); use `-D DebugBreak=DebugBreak` to override\n * this behavior if really needed.  This is also a workaround for\n * x86mingw32ce toolchain (if it is still declaring `DebugBreak()`\n * instead of defining it as a macro).\n */\n#    define DebugBreak() _exit(-1) /*< there is no `abort()` in WinCE */\n#  endif\n#  if defined(MSWIN32) && (defined(NO_DEBUGGING) || defined(LINT2))\n/*\n * A more user-friendly abort after showing fatal message.\n * Exit on error without running \"at-exit\" callbacks.\n */\n#    define ABORT(msg) (GC_on_abort(msg), _exit(-1))\n#  elif defined(MSWINCE) && defined(NO_DEBUGGING)\n#    define ABORT(msg) (GC_on_abort(msg), ExitProcess(-1))\n#  elif defined(MSWIN32) || defined(MSWINCE)\n#    if defined(_CrtDbgBreak) && defined(_DEBUG) && defined(_MSC_VER)\n#      define ABORT(msg)                          \\\n        {                                         \\\n          GC_on_abort(msg);                       \\\n          _CrtDbgBreak() /*< `__debugbreak()` */; \\\n        }\n#    else\n#      define ABORT(msg)    \\\n        {                   \\\n          GC_on_abort(msg); \\\n          DebugBreak();     \\\n        }\n/*\n * Note: on a WinCE box, this could be silently ignored (i.e., the program\n * is not aborted); `DebugBreak()` is a statement in some toolchains.\n */\n#    endif\n#  else /* !MSWIN32 */\n#    define ABORT(msg) (GC_on_abort(msg), abort())\n#  endif\n#endif /* !CPPCHECK */\n\n/*\n * For the abort message with 1 .. 3 arguments.  `C_msg` and `C_fmt`\n * should be literals.  `C_msg` should not contain format specifiers.\n * Arguments should match their format specifiers.\n */\n#define ABORT_ARG1(C_msg, C_fmt, arg1)               \\\n  MACRO_BLKSTMT_BEGIN                                \\\n  GC_ERRINFO_PRINTF(C_msg /* + */ C_fmt \"\\n\", arg1); \\\n  ABORT(C_msg);                                      \\\n  MACRO_BLKSTMT_END\n#define ABORT_ARG2(C_msg, C_fmt, arg1, arg2)               \\\n  MACRO_BLKSTMT_BEGIN                                      \\\n  GC_ERRINFO_PRINTF(C_msg /* + */ C_fmt \"\\n\", arg1, arg2); \\\n  ABORT(C_msg);                                            \\\n  MACRO_BLKSTMT_END\n#define ABORT_ARG3(C_msg, C_fmt, arg1, arg2, arg3)               \\\n  MACRO_BLKSTMT_BEGIN                                            \\\n  GC_ERRINFO_PRINTF(C_msg /* + */ C_fmt \"\\n\", arg1, arg2, arg3); \\\n  ABORT(C_msg);                                                  \\\n  MACRO_BLKSTMT_END\n\n/*\n * Same as `ABORT` but does not have a `noreturn` attribute.\n * I.e. `ABORT` on a dummy condition (which is always true).\n */\n#define ABORT_RET(msg)                                                \\\n  if ((GC_funcptr_uint)GC_current_warn_proc == ~(GC_funcptr_uint)0) { \\\n  } else                                                              \\\n    ABORT(msg)\n\n/* Exit process abnormally, but without making a mess (e.g. out of memory). */\n#define EXIT() (GC_on_abort(NULL), exit(1 /* `EXIT_FAILURE` */))\n\n/*\n * Print warning message, e.g. almost out of memory.  The argument (if any)\n * format specifier should be: \"%s\", \"%p\", \"%\"`WARN_PRIdPTR` or\n * \"%\"`WARN_PRIuPTR`.\n */\n#define WARN(msg, arg) \\\n  GC_current_warn_proc(\"GC Warning: \" msg, (GC_uintptr_t)(arg))\nGC_EXTERN GC_warn_proc GC_current_warn_proc;\n\n/*\n * Print format type macro for decimal `GC_signed_word` value passed to\n * `WARN()`.  This could be redefined for Win64 or LLP64, but typically\n * should not be done as the `WARN` format string is, possibly,\n * processed on the client side, so non-standard print type modifiers\n * (like MS \"I64d\") should be avoided here if possible.\n * TODO: Assuming `sizeof(void *)` is equal to `sizeof(long)` or this\n * is a little-endian machine.\n */\n#ifndef WARN_PRIdPTR\n#  define WARN_PRIdPTR \"ld\"\n#  define WARN_PRIuPTR \"lu\"\n#endif\n\n/*\n * A tagging macro (for a code static analyzer) to indicate that the\n * string obtained from an untrusted source (e.g., `argv[]`, `getenv`)\n * is safe to use in a vulnerable operation (e.g., `open`, `exec`).\n */\n#define TRUSTED_STRING(s) COVERT_DATAFLOW_P(s)\n\n#ifdef GC_READ_ENV_FILE\n/*\n * This routine scans `GC_envfile_content` for the specified environment\n * variable (and returns its value if found).\n */\nGC_INNER char *GC_envfile_getenv(const char *name);\n\n/* Get the process environment entry. */\n#  define GETENV(name) GC_envfile_getenv(name)\n#elif defined(NO_GETENV) && !defined(CPPCHECK)\n#  define GETENV(name) NULL\n#elif defined(EMPTY_GETENV_RESULTS) && !defined(CPPCHECK)\n/* Workaround for a reputed Wine bug. */\nGC_INLINE char *\nfixed_getenv(const char *name)\n{\n  char *value = getenv(name);\n  return value != NULL && *value != '\\0' ? value : NULL;\n}\n#  define GETENV(name) fixed_getenv(name)\n#else\n#  define GETENV(name) getenv(name)\n#endif\n\nEXTERN_C_END\n\n#if defined(DARWIN)\n#  include <mach/thread_status.h>\n#  ifndef MAC_OS_X_VERSION_MAX_ALLOWED\n/* Include this header just to import the above macro. */\n#    include <AvailabilityMacros.h>\n#  endif\n#  if defined(POWERPC)\n#    if CPP_WORDSZ == 32\n#      define GC_THREAD_STATE_T ppc_thread_state_t\n#    else\n#      define GC_THREAD_STATE_T ppc_thread_state64_t\n#      define GC_MACH_THREAD_STATE PPC_THREAD_STATE64\n#      define GC_MACH_THREAD_STATE_COUNT PPC_THREAD_STATE64_COUNT\n#    endif\n#  elif defined(I386) || defined(X86_64)\n#    if CPP_WORDSZ == 32\n#      if defined(i386_THREAD_STATE_COUNT) \\\n          && !defined(x86_THREAD_STATE32_COUNT)\n/* Use old naming convention for i686. */\n#        define GC_THREAD_STATE_T i386_thread_state_t\n#        define GC_MACH_THREAD_STATE i386_THREAD_STATE\n#        define GC_MACH_THREAD_STATE_COUNT i386_THREAD_STATE_COUNT\n#      else\n#        define GC_THREAD_STATE_T x86_thread_state32_t\n#        define GC_MACH_THREAD_STATE x86_THREAD_STATE32\n#        define GC_MACH_THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT\n#      endif\n#    else\n#      define GC_THREAD_STATE_T x86_thread_state64_t\n#      define GC_MACH_THREAD_STATE x86_THREAD_STATE64\n#      define GC_MACH_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT\n#    endif\n#  elif defined(ARM32) && defined(ARM_UNIFIED_THREAD_STATE) \\\n      && !defined(CPPCHECK)\n#    define GC_THREAD_STATE_T arm_unified_thread_state_t\n#    define GC_MACH_THREAD_STATE ARM_UNIFIED_THREAD_STATE\n#    define GC_MACH_THREAD_STATE_COUNT ARM_UNIFIED_THREAD_STATE_COUNT\n#  elif defined(ARM32)\n#    define GC_THREAD_STATE_T arm_thread_state_t\n#    ifdef ARM_MACHINE_THREAD_STATE_COUNT\n#      define GC_MACH_THREAD_STATE ARM_MACHINE_THREAD_STATE\n#      define GC_MACH_THREAD_STATE_COUNT ARM_MACHINE_THREAD_STATE_COUNT\n#    endif\n#  elif defined(AARCH64)\n#    define GC_THREAD_STATE_T arm_thread_state64_t\n#    define GC_MACH_THREAD_STATE ARM_THREAD_STATE64\n#    define GC_MACH_THREAD_STATE_COUNT ARM_THREAD_STATE64_COUNT\n#  elif !defined(CPPCHECK)\n#    error define GC_THREAD_STATE_T\n#  endif\n#  ifndef GC_MACH_THREAD_STATE\n#    define GC_MACH_THREAD_STATE MACHINE_THREAD_STATE\n#    define GC_MACH_THREAD_STATE_COUNT MACHINE_THREAD_STATE_COUNT\n#  endif\n\n/*\n * Try to work out the right way to access thread state structure members.\n * The structure has different definition in different Darwin versions.\n * This now defaults to the (older) names without `__`, thus hopefully\n * not breaking any existing `Makefile.direct` builds.\n */\n#  if __DARWIN_UNIX03\n#    define THREAD_FLD_NAME(x) __##x\n#  else\n#    define THREAD_FLD_NAME(x) x\n#  endif\n#  if defined(ARM32) && defined(ARM_UNIFIED_THREAD_STATE)\n#    define THREAD_FLD(x) ts_32.THREAD_FLD_NAME(x)\n#  else\n#    define THREAD_FLD(x) THREAD_FLD_NAME(x)\n#  endif\n#endif /* DARWIN */\n\n#ifndef WASI\n#  include <setjmp.h>\n#endif\n\n#include <stdio.h>\n\n#if defined(CAN_HANDLE_FORK) && defined(GC_PTHREADS)\n#  include <pthread.h> /*< for `pthread_t` */\n#endif\n\n#if __STDC_VERSION__ >= 201112L\n#  include <assert.h> /*< for `static_assert` */\n#endif\n\nEXTERN_C_BEGIN\n\n/* Definitions depending on `word` size. */\n\n#define modWORDSZ(n) ((n) & (CPP_WORDSZ - 1)) /*< `n mod size_of_word` */\n#define divWORDSZ(n) ((n) / CPP_WORDSZ)\n\n#define SIGNB ((word)1 << (CPP_WORDSZ - 1))\n#define SIZET_SIGNB (GC_SIZE_MAX ^ (GC_SIZE_MAX >> 1))\n\n#if CPP_PTRSZ / 8 != ALIGNMENT\n#  define UNALIGNED_PTRS\n#endif\n\n#define BYTES_TO_GRANULES(lb) ((lb) / GC_GRANULE_BYTES)\n#define GRANULES_TO_BYTES(lg) (GC_GRANULE_BYTES * (lg))\n#define BYTES_TO_PTRS(lb) ((lb) / sizeof(ptr_t))\n#define PTRS_TO_BYTES(lpw) ((lpw) * sizeof(ptr_t))\n#define GRANULES_TO_PTRS(lg) (GC_GRANULE_PTRS * (lg))\n\n/*\n * Convert size in bytes to that in pointers rounding up (but not adding\n * extra byte at end).\n */\n#define BYTES_TO_PTRS_ROUNDUP(lb) BYTES_TO_PTRS((lb) + sizeof(ptr_t) - 1)\n\n/* Size parameters. */\n\n/*\n * Heap block size, in bytes.  Should be a power of two.\n * Incremental collection with `MPROTECT_VDB` currently requires the\n * page size to be a multiple of `HBLKSIZE`.  Since most modern\n * architectures support variable page sizes down to 4 KB, and i686 and\n * x86_64 are generally 4 KB, we now default to 4 KB, except for:\n *   - Alpha: seems to be used with 8 KB pages;\n *   - `SMALL_CONFIG`: want less block-level fragmentation.\n */\n#ifndef HBLKSIZE\n#  if defined(SMALL_CONFIG) && !defined(LARGE_CONFIG)\n#    define CPP_LOG_HBLKSIZE 10\n#  elif defined(ALPHA)\n#    define CPP_LOG_HBLKSIZE 13\n#  else\n#    define CPP_LOG_HBLKSIZE 12\n#  endif\n#else\n#  if HBLKSIZE == 512\n#    define CPP_LOG_HBLKSIZE 9\n#  elif HBLKSIZE == 1024\n#    define CPP_LOG_HBLKSIZE 10\n#  elif HBLKSIZE == 2048\n#    define CPP_LOG_HBLKSIZE 11\n#  elif HBLKSIZE == 4096\n#    define CPP_LOG_HBLKSIZE 12\n#  elif HBLKSIZE == 8192\n#    define CPP_LOG_HBLKSIZE 13\n#  elif HBLKSIZE == 16384\n#    define CPP_LOG_HBLKSIZE 14\n#  elif HBLKSIZE == 32768\n#    define CPP_LOG_HBLKSIZE 15\n#  elif HBLKSIZE == 65536\n#    define CPP_LOG_HBLKSIZE 16\n#  elif !defined(CPPCHECK)\n#    error Bad HBLKSIZE value\n#  endif\n#  undef HBLKSIZE\n#endif\n\n#define LOG_HBLKSIZE ((size_t)CPP_LOG_HBLKSIZE)\n#define HBLKSIZE ((size_t)1 << CPP_LOG_HBLKSIZE)\n\n#define GC_SQRT_SIZE_MAX ((((size_t)1) << (sizeof(size_t) * 8 / 2)) - 1)\n\n/*\n * Maximum size of objects supported by free list (larger objects are\n * allocated directly with `GC_alloc_large()`, by rounding to the next\n * multiple of `HBLKSIZE`).\n */\n#define MAXOBJBYTES (HBLKSIZE >> 1)\n#define MAXOBJGRANULES BYTES_TO_GRANULES(MAXOBJBYTES)\n\n#define divHBLKSZ(n) ((n) >> LOG_HBLKSIZE)\n\n/*\n * Equivalent to subtracting one `hblk` pointer from another.  We do it\n * this way because a compiler should find it hard to use an integer\n * division instead of a shift.  The bundled SunOS 4.1 otherwise sometimes\n * pessimizes the subtraction to involve a call to `.div`.\n */\n#define HBLK_PTR_DIFF(p, q) divHBLKSZ((ptr_t)p - (ptr_t)q)\n\n#define modHBLKSZ(n) ((n) & (HBLKSIZE - 1))\n\n#define HBLKPTR(objptr) \\\n  ((struct hblk *)PTR_ALIGN_DOWN((ptr_t)(objptr), HBLKSIZE))\n#define HBLKDISPL(objptr) modHBLKSZ((size_t)ADDR(objptr))\n\n/* Same as `HBLKPTR` but points to the first block in the page. */\n#define HBLK_PAGE_ALIGNED(objptr) \\\n  ((struct hblk *)PTR_ALIGN_DOWN((ptr_t)(objptr), GC_page_size))\n\n/* Round up allocation size (in bytes) to a multiple of a granule. */\n#define ROUNDUP_GRANULE_SIZE(lb) /*< `lb` should have no side-effect */ \\\n  (SIZET_SAT_ADD(lb, GC_GRANULE_BYTES - 1) & ~(size_t)(GC_GRANULE_BYTES - 1))\n\n/*\n * Round up byte allocation request (after adding `EXTRA_BYTES`) to\n * a multiple of a granule, then convert it to granules.\n */\n#define ALLOC_REQUEST_GRANS(lb) /*< `lb` should have no side-effect */ \\\n  BYTES_TO_GRANULES(SIZET_SAT_ADD(lb, GC_GRANULE_BYTES - 1 + EXTRA_BYTES))\n\n#if MAX_EXTRA_BYTES == 0\n#  define ADD_EXTRA_BYTES(lb) (lb)\n#  define SMALL_OBJ(lb) LIKELY((lb) <= MAXOBJBYTES)\n#else\n#  define ADD_EXTRA_BYTES(lb) /*< `lb` should have no side-effect */ \\\n    SIZET_SAT_ADD(lb, EXTRA_BYTES)\n\n/*\n * This really just tests that `lb` is not greater than\n * `MAXOBJBYTES - EXTRA_BYTES`, but we try to avoid looking up `EXTRA_BYTES`.\n */\n#  define SMALL_OBJ(lb) /*< `lb` should have no side-effect */ \\\n    (LIKELY((lb) <= MAXOBJBYTES - MAX_EXTRA_BYTES)             \\\n     || (lb) <= MAXOBJBYTES - EXTRA_BYTES)\n#endif\n\n/*\n * Hash table representation of sets of pages.  Implements a map from\n * `HBLKSIZE`-aligned chunks of the address space to one bit each.\n * This assumes it is OK to spuriously set bits, e.g. because multiple\n * addresses are represented by a single location.  Used by\n * black-listing code, and perhaps by dirty bit maintenance code.\n */\n#ifndef LOG_PHT_ENTRIES\n#  ifdef LARGE_CONFIG\n#    if CPP_WORDSZ == 32\n/*\n * Collisions are impossible (because of a 4 GB space limit).\n * Each table takes 128 KB, some of which may never be touched.\n */\n#      define LOG_PHT_ENTRIES 20\n#    else\n/*\n * Collisions likely at 2M blocks, which is greater than 8 GB.\n * Each table takes 256 KB, some of which may never be touched.\n */\n#      define LOG_PHT_ENTRIES 21\n#    endif\n#  elif !defined(SMALL_CONFIG)\n/*\n * Collisions are likely if heap grows to more than 256K blocks,\n * which is greater than 1 GB.  Each hash table occupies 32 KB.\n * Even for somewhat smaller heaps, say half of that, collisions may\n * be an issue because we blacklist addresses outside the heap.\n */\n#    define LOG_PHT_ENTRIES 18\n#  else\n/*\n * Collisions are likely if heap grows to more than 32K blocks,\n * which is 128 MB.  Each hash table occupies 4 KB.\n */\n#    define LOG_PHT_ENTRIES 15\n#  endif\n#endif /* !LOG_PHT_ENTRIES */\n\n#define PHT_ENTRIES (1 << LOG_PHT_ENTRIES)\n#define PHT_SIZE (PHT_ENTRIES > CPP_WORDSZ ? PHT_ENTRIES / CPP_WORDSZ : 1)\ntypedef word page_hash_table[PHT_SIZE];\n\n#define PHT_HASH(p) ((size_t)((ADDR(p) >> LOG_HBLKSIZE) & (PHT_ENTRIES - 1)))\n\n#define get_pht_entry_from_index(bl, index) \\\n  (((bl)[divWORDSZ(index)] >> modWORDSZ(index)) & 1)\n#define set_pht_entry_from_index(bl, index) \\\n  (void)((bl)[divWORDSZ(index)] |= (word)1 << modWORDSZ(index))\n\n#if defined(THREADS) && defined(AO_HAVE_or)\n/*\n * And, one more variant for `GC_add_to_black_list_normal` and\n *`GC_add_to_black_list_stack` (invoked indirectly by `GC_do_local_mark()`)\n * and `async_set_pht_entry_from_index()` (invoked by `GC_dirty()` or the\n * write fault handler).\n */\n#  define set_pht_entry_from_index_concurrent(bl, index) \\\n    AO_or((volatile AO_t *)&(bl)[divWORDSZ(index)],      \\\n          (AO_t)1 << modWORDSZ(index))\n#  ifdef MPROTECT_VDB\n#    define set_pht_entry_from_index_concurrent_volatile(bl, index) \\\n      set_pht_entry_from_index_concurrent(bl, index)\n#  endif\n#else\n#  define set_pht_entry_from_index_concurrent(bl, index) \\\n    set_pht_entry_from_index(bl, index)\n#  ifdef MPROTECT_VDB\n/*\n * Same as `set_pht_entry_from_index` but avoiding the compound assignment\n * for a `volatile` array.\n */\n#    define set_pht_entry_from_index_concurrent_volatile(bl, index) \\\n      (void)((bl)[divWORDSZ(index)]                                 \\\n             = (bl)[divWORDSZ(index)] | ((word)1 << modWORDSZ(index)))\n#  endif\n#endif\n\n/* Heap blocks. */\n\n/*\n * The upper bound.  We allocate 1 bit per allocation granule.\n * If `MARK_BIT_PER_OBJ` is not defined, we use every `n`-th bit, where\n * `n` is the number of allocation granules per object.  Otherwise, we only\n * use the initial group of mark bits, and it is safe to allocate smaller\n * header for large objects.\n */\n#define MARK_BITS_PER_HBLK (HBLKSIZE / GC_GRANULE_BYTES)\n\n#ifndef MARK_BIT_PER_OBJ\n/*\n * We maintain layout maps for heap blocks containing objects of\n * a given size.  Each entry in this map describes a byte offset\n * (displacement) and has the following type.\n */\n#  if (1 << (CPP_LOG_HBLKSIZE - 1)) / GC_GRANULE_BYTES <= 0x100\ntypedef unsigned char hb_map_entry_t;\n#  else\ntypedef unsigned short hb_map_entry_t;\n#  endif\n#endif /* !MARK_BIT_PER_OBJ */\n\nstruct hblkhdr {\n  /*\n   * Link field for `hblk` free list and for lists of chunks waiting to\n   * be reclaimed.\n   */\n  struct hblk *hb_next;\n\n  struct hblk *hb_prev; /*< backwards link for free list */\n\n  struct hblk *hb_block; /*< the corresponding block */\n\n  /*\n   * Kind of objects in the block.  Each kind identifies a mark\n   * procedure and a set of list headers.  Sometimes called regions.\n   */\n  unsigned char hb_obj_kind;\n\n  unsigned char hb_flags;\n\n  /* Ignore pointers that do not point to the first `hblk` of this object. */\n#define IGNORE_OFF_PAGE 1\n\n  /*\n   * This is a free block, which has been unmapped from the address space.\n   * `GC_remap()` must be invoked on it before it can be reallocated.\n   * Set only if `USE_MUNMAP` macro is defined.\n   */\n#define WAS_UNMAPPED 2\n\n  /* Block is free, i.e. not in use. */\n#define FREE_BLK 4\n\n#ifdef ENABLE_DISCLAIM\n  /* This kind has a callback on reclaim. */\n#  define HAS_DISCLAIM 8\n\n  /*\n   * Mark from all objects, marked or not.  Used to mark objects needed\n   * by reclaim notifier.\n   */\n#  define MARK_UNCONDITIONALLY 0x10\n#endif\n\n#ifndef MARK_BIT_PER_OBJ\n#  define LARGE_BLOCK 0x20\n#endif\n\n  /*\n   * Value of `GC_gc_no` when block was last allocated or swept.\n   * May wrap.  For a free block, this is maintained only for `USE_MUNMAP`,\n   * and indicates when the header was allocated, or when the size of the\n   * block last changed.\n   */\n  unsigned short hb_last_reclaimed;\n\n#ifdef MARK_BIT_PER_OBJ\n#  define LARGE_INV_SZ ((unsigned32)1 << 16)\n\n  /*\n   * A good upper bound for `2**32 / hb_sz`.\n   * For large objects, we use `LARGE_INV_SZ`.\n   */\n  unsigned32 hb_inv_sz;\n#endif\n\n  /*\n   * If in use, size in bytes, of objects in the block.\n   * Otherwise, the size of the whole free block.  We assume that this is\n   * convertible to `GC_signed_word` without generating a negative result.\n   * We avoid generating free blocks larger than that.\n   */\n  size_t hb_sz;\n\n  /* Object descriptor for marking.  See `gc_mark.h` file. */\n  word hb_descr;\n\n#ifndef MARK_BIT_PER_OBJ\n  /*\n   * A table of remainders `mod BYTES_TO_GRANULES(hb_sz)` essentially,\n   * except for large blocks.  See `GC_obj_map`.\n   */\n  hb_map_entry_t *hb_map;\n#endif\n\n#ifdef PARALLEL_MARK\n  /*\n   * Number of set mark bits, excluding the one always set at the end.\n   * Currently it is updated concurrently and hence only approximate.\n   * But a zero value does guarantee that the block contains\n   * no marked objects.  Ensuring this property means that we never\n   * decrement it to zero during a collection, and hence the count may\n   * be one too high.  Due to concurrent updates, an arbitrary number\n   * of increments, but not all of them (!) may be lost, hence it may,\n   * in theory, be much too low.  The count may also be too high\n   * if multiple mark threads mark the same object due to a race.\n   */\n  volatile AO_t hb_n_marks;\n#else\n  /* Without parallel marking, the count is accurate. */\n  size_t hb_n_marks;\n#endif\n\n#ifdef USE_MARK_BYTES\n  /*\n   * Unlike the other case, this is in units of bytes.  Since we force\n   * certain alignment, we need at most one mark bit per a granule.\n   * But we do allocate and set one extra mark bit to avoid\n   * an explicit check for the partial object at the end of each block.\n   */\n#  define HB_MARKS_SZ (MARK_BITS_PER_HBLK + 1)\n  union {\n    /*\n     * The `i`-th byte is 1 if the object starting at granule `i`\n     * or object `i` is marked, 0 otherwise.  The mark bit for the\n     * \"one past the end\" object is always set to avoid a special case\n     * test in the marker.\n     */\n    char _hb_marks[HB_MARKS_SZ];\n    word dummy; /*< force word alignment of mark bytes */\n  } _mark_byte_union;\n#  define hb_marks _mark_byte_union._hb_marks\n#else\n#  define HB_MARKS_SZ (MARK_BITS_PER_HBLK / CPP_WORDSZ + 1)\n\n#  if defined(PARALLEL_MARK) || (defined(THREAD_SANITIZER) && defined(THREADS))\n  volatile AO_t hb_marks[HB_MARKS_SZ];\n#  else\n  word hb_marks[HB_MARKS_SZ];\n#  endif\n#endif /* !USE_MARK_BYTES */\n};\n\n/* A \"random\" mark bit index for assertions. */\n#define ANY_INDEX 23\n\n/* Heap block body. */\n\n#define HBLK_WORDS (HBLKSIZE / sizeof(word))\n#define HBLK_GRANULES (HBLKSIZE / GC_GRANULE_BYTES)\n\n/*\n * The number of objects in a block dedicated to a certain size.\n * May erroneously yield zero (instead of one) for large objects.\n */\n#define HBLK_OBJS(sz_in_bytes) (HBLKSIZE / (sz_in_bytes))\n\nstruct hblk {\n  char hb_body[HBLKSIZE];\n};\n\n#define HBLK_IS_FREE(hhdr) (((hhdr)->hb_flags & FREE_BLK) != 0)\n\n#define OBJ_SZ_TO_BLOCKS(lb) divHBLKSZ((lb) + HBLKSIZE - 1)\n\n/*\n * Size of block (in units of `HBLKSIZE`) needed to hold objects of\n * given `lb` (in bytes).  The checked variant prevents wrap around.\n */\n#define OBJ_SZ_TO_BLOCKS_CHECKED(lb) /*< `lb` should have no side-effect */ \\\n  divHBLKSZ(SIZET_SAT_ADD(lb, HBLKSIZE - 1))\n\n/* The object free-list link. */\n#define obj_link(p) (*(void **)(p))\n\n/*\n * Root sets.  Logically private to `mark_rts.c` file.  But we do not\n * want the tables scanned, so we put them here.\n */\n\n/* The maximum number of ranges that can be registered as static roots. */\n#ifdef LARGE_CONFIG\n#  define MAX_ROOT_SETS 8192\n#elif !defined(SMALL_CONFIG)\n#  define MAX_ROOT_SETS 2048\n#else\n#  define MAX_ROOT_SETS 512\n#endif\n\n/* Maximum number of segments that can be excluded from root sets. */\n#define MAX_EXCLUSIONS (MAX_ROOT_SETS / 4)\n\n/* A data structure for excluded static roots. */\nstruct exclusion {\n  ptr_t e_start;\n  ptr_t e_end;\n};\n\n/*\n * A data structure for list of root sets.  We keep a hash table, so that\n * we can filter out duplicate additions.  Under Win32, we need to do\n * a better job of filtering overlaps, so we resort to sequential search,\n * and pay the price.\n */\nstruct roots {\n  ptr_t r_start; /*< multiple of pointer size */\n  ptr_t r_end;   /*< multiple of pointer size and greater than `r_start` */\n#ifndef ANY_MSWIN\n  struct roots *r_next;\n#endif\n  /* Delete before registering new dynamic libraries if set. */\n  GC_bool r_tmp;\n};\n\n#ifndef ANY_MSWIN\n/* Size of hash table index to roots. */\n#  define LOG_RT_SIZE 6\n\n/* `RT_SIZE` should be a power of 2, may be not equal to `MAX_ROOT_SETS`. */\n#  define RT_SIZE (1 << LOG_RT_SIZE)\n#endif\n\n#if (!defined(MAX_HEAP_SECTS) || defined(CPPCHECK)) \\\n    && (defined(ANY_MSWIN) || defined(USE_PROC_FOR_LIBRARIES))\n#  ifdef LARGE_CONFIG\n#    if CPP_WORDSZ > 32\n#      define MAX_HEAP_SECTS 81920\n#    else\n#      define MAX_HEAP_SECTS 7680\n#    endif\n#  elif defined(SMALL_CONFIG) && !defined(USE_PROC_FOR_LIBRARIES)\n#    if defined(PARALLEL_MARK) && (defined(MSWIN32) || defined(CYGWIN32))\n#      define MAX_HEAP_SECTS 384\n#    else\n#      define MAX_HEAP_SECTS 128 /*< roughly 256 MB (`128 * 2048 * 1024`) */\n#    endif\n#  elif CPP_WORDSZ > 32\n#    define MAX_HEAP_SECTS 1024 /*< roughly 8 GB */\n#  else\n#    define MAX_HEAP_SECTS 512 /*< roughly 4 GB */\n#  endif\n#endif /* !MAX_HEAP_SECTS */\n\ntypedef struct GC_ms_entry {\n  ptr_t mse_start; /*< beginning of object, pointer-aligned one */\n#ifdef PARALLEL_MARK\n  volatile AO_t mse_descr;\n#else\n  /*\n   * The descriptor; the low-order two bits are tags, as described\n   * in `gc_mark.h` file.\n   */\n  word mse_descr;\n#endif\n} mse;\n\n/*\n * Current state of marking.  Used to remember where we are during the\n * concurrent marking.\n */\ntypedef int mark_state_t;\n\nstruct disappearing_link;\nstruct finalizable_object;\n\nstruct dl_hashtbl_s {\n  struct disappearing_link **head;\n  size_t entries;\n  unsigned log_size;\n};\n\nstruct fnlz_roots_s {\n  struct finalizable_object **fo_head;\n  /* List of objects that should be finalized now. */\n  struct finalizable_object *finalize_now;\n};\n\nunion toggle_ref_u {\n  /* The least significant bit is used to distinguish between choices. */\n  void *strong_ref;\n  GC_hidden_pointer weak_ref;\n};\n\n/*\n * Extended descriptors.  `GC_typed_mark_proc` understands these.\n * These are used for simple objects that are larger than what can\n * be described by a `BITMAP_BITS`-sized bitmap.\n */\ntypedef struct {\n  /*\n   * The least significant bit corresponds to the first \"pointer-sized\"\n   * word.\n   */\n  word ed_bitmap;\n  GC_bool ed_continued; /*< next entry is continuation */\n} typed_ext_descr_t;\n\nstruct HeapSect {\n  ptr_t hs_start;\n  size_t hs_bytes;\n};\n\n#ifdef MAKE_BACK_GRAPH\n/* The maximum in-degree we handle directly. */\n#  define BACKGRAPH_MAX_IN 10\n\nstruct back_edges_s {\n  /* Number of edges, including those in continuation structures. */\n  word n_edges;\n\n  unsigned short flags;\n\n  /*\n   * If `height` is greater than zero, then keeps the `GC_gc_no` value\n   * when it was computed.  If it was computed this cycle, then it is\n   * current.  If it was computed during the last cycle, then it belongs\n   * to the old height, which is only saved for live objects referenced by\n   * dead ones.  This may grow due to references from newly dead objects.\n   */\n  unsigned short height_gc_no;\n\n  /*\n   * Longest path through unreachable nodes to this node that we found\n   * using depth first search.\n   */\n  GC_signed_word height;\n\n  ptr_t edges[BACKGRAPH_MAX_IN];\n\n  /*\n   * Pointer to continuation structure; we use only the edges field in\n   * the continuation.  Also used as a free-list link.\n   */\n  struct back_edges_s *cont;\n};\n#endif\n\n/*\n * Lists of all heap blocks and free lists as well as other random data\n * structures that should not be scanned by the collector.  These are\n * grouped together in a structure so that they can be easily skipped by\n * `GC_push_conditional_with_exclusions()`.  The ordering is weird to\n * make `GC_malloc` faster by keeping the important fields sufficiently\n * close together that a single load of a base register will do.\n * Scalars that could easily appear to be pointers are also put here.\n * The main fields should precede any conditionally included fields, where\n * possible.\n */\nstruct _GC_arrays {\n#define GC_heapsize GC_arrays._heapsize\n  word _heapsize; /*< heap size in bytes (value never goes down) */\n\n#define GC_requested_heapsize GC_arrays._requested_heapsize\n  word _requested_heapsize; /*< heap size due to explicit expansion */\n\n#define GC_heapsize_on_gc_disable GC_arrays._heapsize_on_gc_disable\n  word _heapsize_on_gc_disable;\n\n#define GC_heapsize_at_forced_unmap GC_arrays._heapsize_at_forced_unmap\n  word _heapsize_at_forced_unmap; /*< accessed with the allocator lock held */\n\n#define GC_last_heap_addr GC_arrays._last_heap_addr\n  word _last_heap_addr;\n\n  /*\n   * Total bytes contained in blocks on the free list of large objects.\n   * (A large object is the one that occupies a block of at least\n   * two `HBLKSIZE`.)\n   */\n#define GC_large_free_bytes GC_arrays._large_free_bytes\n  word _large_free_bytes;\n\n  /* Total number of bytes in allocated large objects blocks. */\n#define GC_large_allocd_bytes GC_arrays._large_allocd_bytes\n  word _large_allocd_bytes;\n\n  /*\n   * Maximum number of bytes that were ever allocated in large object blocks.\n   * This is used to help decide when it is safe to split up a large block.\n   */\n#define GC_max_large_allocd_bytes GC_arrays._max_large_allocd_bytes\n  word _max_large_allocd_bytes;\n\n  /* Number of bytes allocated before this collection cycle. */\n#define GC_bytes_allocd_before_gc GC_arrays._bytes_allocd_before_gc\n  word _bytes_allocd_before_gc;\n\n#define GC_our_mem_bytes GC_arrays._our_mem_bytes\n  word _our_mem_bytes;\n\n  /* Number of bytes allocated during this collection cycle. */\n#define GC_bytes_allocd GC_arrays._bytes_allocd\n  word _bytes_allocd;\n\n  /*\n   * Number of black-listed bytes dropped during GC cycle as a result\n   * of repeated scanning during allocation attempts.  These are treated\n   * largely as allocated, even though they are not useful to the client.\n   */\n#define GC_bytes_dropped GC_arrays._bytes_dropped\n  word _bytes_dropped;\n\n  /*\n   * Approximate number of bytes in objects (and headers) that became\n   * ready for finalization in the last collection.\n   */\n#define GC_bytes_finalized GC_arrays._bytes_finalized\n  word _bytes_finalized;\n\n  /*\n   * Number of explicitly deallocated bytes of memory since last\n   * collection.\n   */\n#define GC_bytes_freed GC_arrays._bytes_freed\n  word _bytes_freed;\n\n  /*\n   * Bytes of memory explicitly deallocated while finalizers were running.\n   * Used to approximate size of memory explicitly deallocated by finalizers.\n   */\n#define GC_finalizer_bytes_freed GC_arrays._finalizer_bytes_freed\n  word _finalizer_bytes_freed;\n\n  /*\n   * Pointer to the first (lowest address) `bottom_index` entity;\n   * assumes the allocator lock is held.\n   */\n#define GC_all_bottom_indices GC_arrays._all_bottom_indices\n  bottom_index *_all_bottom_indices;\n\n  /*\n   * Pointer to the last (highest address) `bottom_index` entity;\n   * assumes the allocator lock is held.\n   */\n#define GC_all_bottom_indices_end GC_arrays._all_bottom_indices_end\n  bottom_index *_all_bottom_indices_end;\n\n#define GC_scratch_free_ptr GC_arrays._scratch_free_ptr\n  ptr_t _scratch_free_ptr;\n\n#define GC_hdr_free_list GC_arrays._hdr_free_list\n  hdr *_hdr_free_list;\n\n#define GC_scratch_end_addr GC_arrays._scratch_end_addr\n  word _scratch_end_addr; /*< the end point of the current scratch area */\n\n#if defined(IRIX5) || (defined(USE_PROC_FOR_LIBRARIES) && !defined(LINUX))\n#  define USE_SCRATCH_LAST_END_PTR\n  /*\n   * The address of the end point of the last obtained scratch area.\n   * Used by `GC_register_dynamic_libraries()`.\n   */\n#  define GC_scratch_last_end_addr GC_arrays._scratch_last_end_addr\n  word _scratch_last_end_addr;\n#endif\n\n#if defined(GC_ASSERTIONS) || defined(MAKE_BACK_GRAPH) \\\n    || defined(INCLUDE_LINUX_THREAD_DESCR)             \\\n    || (defined(KEEP_BACK_PTRS) && ALIGNMENT == 1)\n#  define SET_REAL_HEAP_BOUNDS\n\n  /*\n   * Similar to `GC_least_plausible_heap_addr` and\n   * `GC_greatest_plausible_heap_addr` but do not include future\n   * (potential) heap expansion.  Both variables are zero initially.\n   */\n#  define GC_least_real_heap_addr GC_arrays._least_real_heap_addr\n#  define GC_greatest_real_heap_addr GC_arrays._greatest_real_heap_addr\n  word _least_real_heap_addr;\n  word _greatest_real_heap_addr;\n#endif\n\n#define GC_used_heap_size_after_full GC_arrays._used_heap_size_after_full\n  word _used_heap_size_after_full;\n\n  /* Number of explicitly managed bytes of storage at last collection. */\n#define GC_non_gc_bytes_at_gc GC_arrays._non_gc_bytes_at_gc\n  word _non_gc_bytes_at_gc;\n\n  /* The number of extra calls to `GC_mark_some` that we have made. */\n#define GC_mark_deficit GC_arrays._mark_deficit\n  size_t _mark_deficit;\n\n#ifndef NO_BLACK_LISTING\n  /*\n   * Counter of the cases when found block by `GC_allochblk_nth` is\n   * black-listed completely.\n   */\n#  define GC_drop_blacklisted_count GC_arrays._drop_blacklisted_count\n  unsigned _drop_blacklisted_count;\n\n  /* Number of warnings suppressed so far. */\n#  define GC_large_alloc_warn_suppressed GC_arrays._large_alloc_warn_suppressed\n  long _large_alloc_warn_suppressed;\n\n  /* Non-stack false references seen at last full collection. */\n#  define GC_old_normal_bl GC_arrays._old_normal_bl\n  word *_old_normal_bl;\n  /* Non-stack false references seen since last full collection. */\n#  define GC_incomplete_normal_bl GC_arrays._incomplete_normal_bl\n  word *_incomplete_normal_bl;\n\n#  define GC_old_stack_bl GC_arrays._old_stack_bl\n#  define GC_incomplete_stack_bl GC_arrays._incomplete_stack_bl\n  word *_old_stack_bl;\n  word *_incomplete_stack_bl;\n#endif\n\n  /* The limits of stack for `GC_mark_some()` and friends. */\n#define GC_mark_stack GC_arrays._mark_stack\n#define GC_mark_stack_limit GC_arrays._mark_stack_limit\n  mse *_mark_stack;\n  mse *_mark_stack_limit;\n\n  /*\n   * All ranges between `GC_mark_stack` (incl.) and `GC_mark_stack_top`\n   * (incl.) still need to be marked from.\n   */\n#define GC_mark_stack_top GC_arrays._mark_stack_top\n#ifdef PARALLEL_MARK\n  /* Updated only with the mark lock held, but read asynchronously. */\n  mse *volatile _mark_stack_top;\n\n#  define GC_mark_no GC_arrays._mark_no\n  word _mark_no; /*< protected by the mark lock */\n\n  /*\n   * Number of bytes of memory allocated since we released the allocator lock.\n   * Instead of reacquiring the allocator lock just to add this in, we add it\n   * in the next time we reacquire the allocator lock.  (Atomically adding it\n   * does not work, since we would have to atomically update it in\n   * `GC_malloc`, which is too expensive.)\n   */\n#  define GC_bytes_allocd_tmp GC_arrays._bytes_allocd_tmp\n  volatile AO_t _bytes_allocd_tmp;\n#else\n  mse *_mark_stack_top;\n#endif\n\n#ifdef DYNAMIC_POINTER_MASK\n  /*\n   * Both mask and shift are zeros by default; if mask is zero, then\n   * correct it to ~0 at the collector initialization.\n   */\n#  define GC_pointer_mask GC_arrays._pointer_mask\n#  define GC_pointer_shift GC_arrays._pointer_shift\n  word _pointer_mask;\n  unsigned char _pointer_shift;\n#endif\n\n#ifdef THREADS\n#  ifdef USE_SPIN_LOCK\n#    define GC_allocate_lock GC_arrays._allocate_lock\n  volatile AO_TS_t _allocate_lock;\n#  endif\n#  if !defined(HAVE_LOCKFREE_AO_OR) && defined(AO_HAVE_test_and_set_acquire) \\\n      && (!defined(NO_MANUAL_VDB) || defined(MPROTECT_VDB))\n#    define NEED_FAULT_HANDLER_LOCK\n#    define GC_fault_handler_lock GC_arrays._fault_handler_lock\n  volatile AO_TS_t _fault_handler_lock;\n#  endif\n#  if !(defined(GC_ALWAYS_MULTITHREADED) \\\n        && (defined(USE_PTHREAD_LOCKS) || defined(USE_SPIN_LOCK)))\n#    define GC_need_to_lock GC_arrays._need_to_lock\n  GC_bool _need_to_lock;\n#  endif\n\n#  ifdef GC_ASSERTIONS\n#    define GC_thr_initialized GC_arrays._thr_initialized\n  GC_bool _thr_initialized;\n#  endif\n#  if defined(GC_USE_DLOPEN_WRAP) && !defined(GC_WIN32_THREADS) \\\n      && !defined(PLATFORM_THREADS) && !defined(SN_TARGET_PSP2)\n#    define GC_syms_wrap_initialized GC_arrays._syms_wrap_initialized\n  GC_bool _syms_wrap_initialized;\n#  endif\n\n#  define GC_roots_were_cleared GC_arrays._roots_were_cleared\n  GC_bool _roots_were_cleared;\n#else\n#  ifndef GC_NO_FINALIZATION\n/*\n * The variables to minimize the level of recursion when a client\n * finalizer allocates memory.\n */\n#    define GC_finalizer_nested GC_arrays._finalizer_nested\n#    define GC_finalizer_skipped GC_arrays._finalizer_skipped\n  unsigned char _finalizer_nested;\n  unsigned short _finalizer_skipped;\n#  endif\n#endif\n\n  /* Has `GC_init()` been run? */\n#define GC_is_initialized GC_arrays._is_initialized\n  GC_bool _is_initialized;\n\n  /*\n   * Do we need a larger mark stack?  May be set by client-supplied\n   * mark routines.\n   */\n#define GC_mark_stack_too_small GC_arrays._mark_stack_too_small\n  GC_bool _mark_stack_too_small;\n\n  /* Are there collectible marked objects in the heap? */\n#define GC_objects_are_marked GC_arrays._objects_are_marked\n  GC_bool _objects_are_marked;\n\n#ifndef GC_DISABLE_INCREMENTAL\n#  define GC_should_start_incremental_collection \\\n    GC_arrays._should_start_incremental_collection\n  GC_bool _should_start_incremental_collection;\n#endif\n\n#ifndef GC_NO_FINALIZATION\n  /* Avoid the work if unreachable finalizable objects are not used. */\n  /* TODO: Turn this variable into a counter. */\n#  define GC_need_unreachable_finalization \\\n    GC_arrays._need_unreachable_finalization\n  GC_bool _need_unreachable_finalization;\n#endif\n\n#ifndef DONT_USE_ATEXIT\n#  ifdef SMALL_CONFIG\n#    define GC_skip_collect_atexit FALSE\n#  else\n  /*\n   * A dedicated variable to avoid a garbage collection on abort.\n   * `GC_find_leak` cannot be used for this purpose as otherwise\n   * TSan finds a data race (between `GC_default_on_abort` and, e.g.,\n   * `GC_finish_collection`).\n   */\n#    define GC_skip_collect_atexit GC_arrays._skip_collect_atexit\n  GC_bool _skip_collect_atexit;\n#  endif\n#endif\n\n#if defined(NO_FIND_LEAK) && defined(SHORT_DBG_HDRS)\n#  define GC_debugging_initialized GC_arrays._debugging_initialized\n  GC_bool _debugging_initialized;\n#  define GC_debugging_started FALSE\n#else\n#  define GC_debugging_initialized GC_debugging_started\n  /* `GC_debug_malloc()` has been called, once at least. */\n#  define GC_debugging_started GC_arrays._debugging_started\n  GC_bool _debugging_started;\n\n#  define GC_have_errors GC_arrays._have_errors\n#  ifdef AO_HAVE_store\n  volatile AO_t _have_errors;\n#  else\n  GC_bool _have_errors;\n#  endif\n#endif\n\n#define GC_explicit_typing_initialized GC_arrays._explicit_typing_initialized\n#ifdef AO_HAVE_load_acquire\n  volatile AO_t _explicit_typing_initialized;\n#else\n  GC_bool _explicit_typing_initialized;\n#endif\n\n  /* Indicate whether a full collection due to heap growth is needed. */\n#define GC_need_full_gc GC_arrays._need_full_gc\n  GC_bool _need_full_gc;\n\n#ifndef NO_CLOCK\n  /*\n   * Do performance measurements if set to true (e.g., accumulation of the\n   * total time of full collections).\n   */\n#  define GC_measure_performance GC_arrays._measure_performance\n  GC_bool _measure_performance;\n\n  /*\n   * Variables for world-stop average delay time statistic computation.\n   * `GC_world_stopped_total_divisor` is incremented every world stop and\n   * halved when reached its maximum (or upon `GC_world_stopped_total_time`\n   * overflow).  In milliseconds.\n   */\n  /* TODO: Store the nanosecond part. */\n#  define GC_world_stopped_total_time GC_arrays._world_stopped_total_time\n#  define GC_world_stopped_total_divisor GC_arrays._world_stopped_total_divisor\n  unsigned _world_stopped_total_time;\n  unsigned _world_stopped_total_divisor;\n#endif\n\n#ifndef NO_FIND_LEAK\n#  define GC_n_leaked GC_arrays._n_leaked\n  unsigned _n_leaked;\n#endif\n#ifndef SHORT_DBG_HDRS\n#  define GC_n_smashed GC_arrays._n_smashed\n  unsigned _n_smashed;\n#endif\n\n  /* Number of bytes in the accessible composite objects. */\n#define GC_composite_in_use GC_arrays._composite_in_use\n  word _composite_in_use;\n\n  /* Number of bytes in the accessible atomic objects. */\n#define GC_atomic_in_use GC_arrays._atomic_in_use\n  word _atomic_in_use;\n\n  /* GC number of latest successful `GC_expand_hp_inner()` call. */\n#define GC_last_heap_growth_gc_no GC_arrays._last_heap_growth_gc_no\n  word _last_heap_growth_gc_no;\n\n  /*\n   * Number of bytes of memory reclaimed minus the number of bytes originally\n   * on free lists that we had to drop.  Protected by the allocator lock.\n   */\n#define GC_bytes_found GC_arrays._bytes_found\n  GC_signed_word _bytes_found;\n\n#ifndef GC_GET_HEAP_USAGE_NOT_NEEDED\n  /*\n   * Number of bytes reclaimed before this collection cycle; used for\n   * statistics only.\n   */\n#  define GC_reclaimed_bytes_before_gc GC_arrays._reclaimed_bytes_before_gc\n  word _reclaimed_bytes_before_gc;\n#endif\n\n#ifdef USE_MUNMAP\n#  define GC_unmapped_bytes GC_arrays._unmapped_bytes\n  word _unmapped_bytes;\n#else\n#  define GC_unmapped_bytes 0\n#endif\n\n#if defined(COUNT_UNMAPPED_REGIONS) && defined(USE_MUNMAP)\n#  define GC_num_unmapped_regions GC_arrays._num_unmapped_regions\n  GC_signed_word _num_unmapped_regions;\n#else\n#  define GC_num_unmapped_regions 0\n#endif\n\n#define GC_all_nils GC_arrays._all_nils\n  bottom_index *_all_nils;\n\n#define GC_scan_ptr GC_arrays._scan_ptr\n  struct hblk *_scan_ptr;\n\n#ifdef PARALLEL_MARK\n#  define GC_main_local_mark_stack GC_arrays._main_local_mark_stack\n  mse *_main_local_mark_stack;\n\n  /*\n   * The lowest entry on mark stack that may not be empty.\n   * Updated only by the initiating thread.\n   */\n#  define GC_first_nonempty GC_arrays._first_nonempty\n  volatile ptr_t _first_nonempty;\n#endif\n\n#ifdef ENABLE_TRACE\n#  define GC_trace_ptr GC_arrays._trace_ptr\n  ptr_t _trace_ptr;\n#endif\n\n#if !defined(ALWAYS_SMALL_CLEAR_STACK) && !defined(STACK_NOT_SCANNED) \\\n    && !defined(THREADS)\n  /*\n   * Coolest stack pointer value from which we have already cleared\n   * the stack.\n   */\n#  define GC_min_sp GC_arrays._min_sp\n  ptr_t _min_sp;\n\n  /*\n   * The \"hottest\" stack pointer value we have seen recently.\n   * Degrades over time.\n   */\n#  define GC_high_water GC_arrays._high_water\n  ptr_t _high_water;\n#endif\n\n#if CPP_PTRSZ > CPP_WORDSZ\n#  define GC_noop_sink_ptr GC_arrays._noop_sink_ptr\n  volatile ptr_t _noop_sink_ptr;\n#endif\n\n#define GC_noop_sink GC_arrays._noop_sink\n#if defined(AO_HAVE_store) && defined(THREAD_SANITIZER)\n  volatile AO_t _noop_sink;\n#else\n  volatile word _noop_sink;\n#endif\n\n#if !defined(SMALL_CONFIG) && !defined(GC_NO_FINALIZATION)\n  /* Saved number of disappearing links for stats printing. */\n#  define GC_old_dl_entries GC_arrays._old_dl_entries\n  size_t _old_dl_entries;\n#  ifndef GC_LONG_REFS_NOT_NEEDED\n#    define GC_old_ll_entries GC_arrays._old_ll_entries\n  size_t _old_ll_entries;\n#  endif\n#endif\n\n#define GC_mark_stack_size GC_arrays._mark_stack_size\n  size_t _mark_stack_size;\n\n#define GC_mark_state GC_arrays._mark_state\n  mark_state_t _mark_state; /*< initialized to `MS_NONE` (0) */\n\n#define GC_capacity_heap_sects GC_arrays._capacity_heap_sects\n  size_t _capacity_heap_sects;\n\n#define GC_n_heap_sects GC_arrays._n_heap_sects\n  size_t _n_heap_sects; /*< number of separately added heap sections */\n\n#ifdef ANY_MSWIN\n#  define GC_n_heap_bases GC_arrays._n_heap_bases\n  size_t _n_heap_bases; /*< see `GC_heap_bases[]` */\n#endif\n\n#ifdef USE_PROC_FOR_LIBRARIES\n  /* Number of `GET_MEM`-allocated memory sections. */\n#  define GC_n_memory GC_arrays._n_memory\n  word _n_memory;\n#endif\n\n#ifdef GC_GCJ_SUPPORT\n#  define GC_last_finalized_no GC_arrays._last_finalized_no\n#  define GC_gcjobjfreelist GC_arrays._gcjobjfreelist\n  word _last_finalized_no;\n  ptr_t *_gcjobjfreelist;\n#endif\n\n#define GC_fo_entries GC_arrays._fo_entries\n  size_t _fo_entries;\n\n#ifndef GC_NO_FINALIZATION\n#  define GC_dl_hashtbl GC_arrays._dl_hashtbl\n#  define GC_fnlz_roots GC_arrays._fnlz_roots\n#  define GC_log_fo_table_size GC_arrays._log_fo_table_size\n#  ifndef GC_LONG_REFS_NOT_NEEDED\n#    define GC_ll_hashtbl GC_arrays._ll_hashtbl\n  struct dl_hashtbl_s _ll_hashtbl;\n#  endif\n  struct dl_hashtbl_s _dl_hashtbl;\n  struct fnlz_roots_s _fnlz_roots;\n  unsigned _log_fo_table_size;\n\n#  ifndef GC_TOGGLE_REFS_NOT_NEEDED\n#    define GC_toggleref_arr GC_arrays._toggleref_arr\n#    define GC_toggleref_array_size GC_arrays._toggleref_array_size\n#    define GC_toggleref_array_capacity GC_arrays._toggleref_array_capacity\n  union toggle_ref_u *_toggleref_arr;\n  size_t _toggleref_array_size;\n  size_t _toggleref_array_capacity;\n#  endif\n#endif\n\n#ifdef TRACE_BUF\n#  define GC_trace_buf_pos GC_arrays._trace_buf_pos\n  size_t _trace_buf_pos; /*< an index in the circular buffer */\n#endif\n\n  /*\n   * How many consecutive collection/expansion failures?\n   * Reset by `GC_allochblk()`.\n   */\n#define GC_alloc_fail_count GC_arrays._alloc_fail_count\n  unsigned _alloc_fail_count;\n\n#ifdef ENABLE_DISCLAIM\n#  define GC_finalized_kind GC_arrays._finalized_kind\n  unsigned _finalized_kind;\n#endif\n\n#ifndef NO_CLOCK\n#  define GC_full_gc_total_time GC_arrays._full_gc_total_time\n#  define GC_stopped_mark_total_time GC_arrays._stopped_mark_total_time\n#  define GC_full_gc_total_ns_frac GC_arrays._full_gc_total_ns_frac\n#  define GC_stopped_mark_total_ns_frac GC_arrays._stopped_mark_total_ns_frac\n  unsigned long _full_gc_total_time; /*< in ms, may wrap */\n  unsigned long _stopped_mark_total_time;\n  unsigned32 _full_gc_total_ns_frac; /*< fraction of 1 ms */\n  unsigned32 _stopped_mark_total_ns_frac;\n#endif\n\n#ifdef GC_WIN32_THREADS\n  /* Largest index in `dll_thread_table` that was ever used. */\n#  define GC_max_thread_index GC_arrays._max_thread_index\n  volatile LONG _max_thread_index;\n#endif\n\n  /* Total size of registered root sections. */\n#define GC_root_size GC_arrays._root_size\n  word _root_size;\n\n  /* `GC_static_roots[0..n_root_sets-1]` contains the valid root sets. */\n#define n_root_sets GC_arrays._n_root_sets\n  size_t _n_root_sets;\n\n#define GC_excl_table_entries GC_arrays._excl_table_entries\n  size_t _excl_table_entries; /*< number of entries in use */\n\n#define GC_ed_size GC_arrays._ed_size\n  size_t _ed_size; /*< current size of above arrays */\n\n#define GC_avail_descr GC_arrays._avail_descr\n  size_t _avail_descr; /*< next available slot */\n\n#if defined(CAN_HANDLE_FORK) && defined(GC_PTHREADS)\n  /* Value of `pthread_self()` of the thread which called `fork()`. */\n#  define GC_parent_pthread_self GC_arrays._parent_pthread_self\n  pthread_t _parent_pthread_self;\n#endif\n\n  /* Points to array of extended descriptors. */\n#define GC_ext_descriptors GC_arrays._ext_descriptors\n  typed_ext_descr_t *_ext_descriptors;\n\n  /*\n   * Table of user-defined mark procedures.  There is a small number\n   * of these, which can be referenced by `DS_PROC` mark descriptors.\n   * See `gc_mark.h` file.\n   */\n#define GC_mark_procs GC_arrays._mark_procs\n  GC_mark_proc _mark_procs[GC_MAX_MARK_PROCS];\n\n  /*\n   * `GC_valid_offsets[i]` implies\n   * `GC_modws_valid_offsets[i % sizeof(ptr_t)]`.\n   */\n#define GC_modws_valid_offsets GC_arrays._modws_valid_offsets\n  char _modws_valid_offsets[sizeof(ptr_t)];\n\n#ifdef MAKE_BACK_GRAPH\n  /* Points to never-used `back_edges` space. */\n#  define GC_n_back_edge_structs GC_arrays._n_back_edge_structs\n  int _n_back_edge_structs;\n\n#  define GC_back_edge_space GC_arrays._back_edge_space\n  struct back_edges_s *_back_edge_space;\n\n  /* Pointer to free list of deallocated `back_edges` structures. */\n#  define GC_avail_back_edges GC_arrays._avail_back_edges\n  struct back_edges_s *_avail_back_edges;\n\n  /*\n   * Table of objects that are currently on the depth-first search stack.\n   * Only objects with in-degree one are in this table.  Other objects are\n   * identified using `HEIGHT_IN_PROGRESS`.\n   */\n  /* FIXME: This data structure needs improvement. */\n#  define GC_backgraph_in_progress_space GC_arrays._backgraph_in_progress_space\n#  define GC_backgraph_in_progress_size GC_arrays._backgraph_in_progress_size\n#  define GC_backgraph_n_in_progress GC_arrays._backgraph_n_in_progress\n  ptr_t *_backgraph_in_progress_space;\n  size_t _backgraph_in_progress_size;\n  size_t _backgraph_n_in_progress;\n\n#  define GC_backgraph_max_deepest_h GC_arrays._backgraph_max_deepest_h\n#  define GC_backgraph_deepest_height GC_arrays._backgraph_deepest_height\n#  define GC_backgraph_deepest_obj GC_arrays._backgraph_deepest_obj\n  word _backgraph_max_deepest_h;\n  word _backgraph_deepest_height;\n  ptr_t _backgraph_deepest_obj;\n#endif\n\n#ifdef GC_READ_ENV_FILE\n  /*\n   * The content of the `.gc.env` file with CR and LF replaced to '\\0'.\n   * `NULL` if the file is missing or empty.  Otherwise, always ends\n   * with '\\0' (designating the end of the file).\n   */\n#  define GC_envfile_content GC_arrays._envfile_content\n  char *_envfile_content;\n\n  /* Length of `GC_envfile_content` (if non-`NULL`). */\n#  define GC_envfile_length GC_arrays._envfile_length\n  size_t _envfile_length;\n#endif\n\n#ifndef ANY_MSWIN\n  /*\n   * The hash table header.  Used only to check whether a range\n   * is already present.\n   */\n#  define GC_root_index GC_arrays._root_index\n  struct roots *_root_index[RT_SIZE];\n#endif\n\n#if defined(SAVE_CALL_CHAIN) && !defined(DONT_SAVE_TO_LAST_STACK) \\\n    && (!defined(REDIRECT_MALLOC) || !defined(GC_HAVE_BUILTIN_BACKTRACE))\n  /*\n   * Stack at last garbage collection.  Useful for debugging mysterious\n   * object disappearances.  In the multi-threaded case, we currently only\n   * save the calling stack.  Not supported in case of `malloc` redirection\n   * because `backtrace()` may call `malloc()`.\n   */\n  struct callinfo _last_stack[NFRAMES];\n#  define SAVE_CALLERS_TO_LAST_STACK() GC_save_callers(GC_arrays._last_stack)\n#else\n#  define SAVE_CALLERS_TO_LAST_STACK() (void)0\n#endif\n\n  /* Free list for `NORMAL` objects. */\n#define GC_objfreelist GC_arrays._objfreelist\n  void *_objfreelist[MAXOBJGRANULES + 1];\n\n  /* Free list for atomic objects. */\n#define GC_aobjfreelist GC_arrays._aobjfreelist\n  void *_aobjfreelist[MAXOBJGRANULES + 1];\n\n  /*\n   * Uncollectible but traced objects.  Objects on this and `_auobjfreelist`\n   * are always marked, except during garbage collections.\n   */\n#define GC_uobjfreelist GC_arrays._uobjfreelist\n  void *_uobjfreelist[MAXOBJGRANULES + 1];\n\n#ifdef GC_ATOMIC_UNCOLLECTABLE\n  /* Atomic uncollectible but traced objects. */\n#  define GC_auobjfreelist GC_arrays._auobjfreelist\n  void *_auobjfreelist[MAXOBJGRANULES + 1];\n#endif\n\n  /*\n   * Number of granules to allocate when asked for a certain number of bytes\n   * (plus `EXTRA_BYTES`).  Should be accessed with the allocator lock held.\n   */\n#define GC_size_map GC_arrays._size_map\n  size_t _size_map[MAXOBJBYTES + 1];\n\n#ifndef MARK_BIT_PER_OBJ\n  /*\n   * If the element is not `NULL`, then it points to a map of valid object\n   * addresses.  `GC_obj_map[lg][i]` is `i % lg`.  This is now used purely\n   * to replace a division in the marker by a table lookup.\n   * `GC_obj_map[0]` is used for large objects and contains all nonzero\n   * entries.  This gets us out of the marker fast path without an extra test.\n   */\n#  define GC_obj_map GC_arrays._obj_map\n  hb_map_entry_t *_obj_map[MAXOBJGRANULES + 1];\n\n#  define OBJ_MAP_LEN BYTES_TO_GRANULES(HBLKSIZE)\n#endif\n\n#define VALID_OFFSET_SZ HBLKSIZE\n  /*\n   * A nonzero `GC_valid_offsets[i]` means `i` is registered as\n   * a displacement.\n   */\n#define GC_valid_offsets GC_arrays._valid_offsets\n  char _valid_offsets[VALID_OFFSET_SZ];\n\n#ifndef GC_DISABLE_INCREMENTAL\n  /* Pages that were dirty at last `GC_read_dirty()` call. */\n#  define GC_grungy_pages GC_arrays._grungy_pages\n  page_hash_table _grungy_pages;\n\n  /* Pages dirtied since last `GC_read_dirty()` call. */\n#  define GC_dirty_pages GC_arrays._dirty_pages\n#  ifdef MPROTECT_VDB\n  volatile\n#  endif\n      page_hash_table _dirty_pages;\n#endif\n\n#if (defined(CHECKSUMS) && (defined(GWW_VDB) || defined(SOFT_VDB))) \\\n    || defined(PROC_VDB)\n  /* A table to indicate the pages ever dirtied. */\n#  define GC_written_pages GC_arrays._written_pages\n  page_hash_table _written_pages;\n#endif\n\n  /* Heap segments potentially containing client objects. */\n#define GC_heap_sects GC_arrays._heap_sects\n  struct HeapSect *_heap_sects;\n\n#if defined(USE_PROC_FOR_LIBRARIES)\n  /* All `GET_MEM`-allocated memory.  Includes block headers and the like. */\n#  define GC_our_memory GC_arrays._our_memory\n  struct HeapSect _our_memory[MAX_HEAP_SECTS];\n#endif\n\n#ifdef ANY_MSWIN\n  /* Start address of memory regions obtained from OS. */\n#  define GC_heap_bases GC_arrays._heap_bases\n  ptr_t _heap_bases[MAX_HEAP_SECTS];\n#endif\n\n#ifdef MSWINCE\n  /* Committed lengths of memory regions obtained from OS. */\n#  define GC_heap_lengths GC_arrays._heap_lengths\n  word _heap_lengths[MAX_HEAP_SECTS];\n#endif\n\n#define GC_static_roots GC_arrays._static_roots\n  struct roots _static_roots[MAX_ROOT_SETS];\n\n  /* Array of exclusions, ascending address order. */\n#define GC_excl_table GC_arrays._excl_table\n  struct exclusion _excl_table[MAX_EXCLUSIONS];\n\n  /*\n   * The block header index.  Each entry points to a `bottom_index` entity.\n   * On a 32-bit machine, it points to the index for a set of the high-order\n   * bits equal to the index.  For longer addresses, we hash the high-order\n   * bits to compute the index in `GC_top_index`, and each entry points to\n   * a hash chain.  The last entry in each chain is `GC_all_nils`.\n   */\n#define GC_top_index GC_arrays._top_index\n  bottom_index *_top_index[TOP_SZ];\n\n#ifdef ECOS\n#  ifndef ECOS_GC_MEMORY_SIZE\n#    define ECOS_GC_MEMORY_SIZE (448 * 1024)\n#  endif\n#  define GC_ecos_brk_idx GC_arrays._ecos_brk_idx\n#  define GC_ecos_memory GC_arrays._ecos_memory\n  size_t _ecos_brk_idx;\n  char _ecos_memory[ECOS_GC_MEMORY_SIZE];\n#endif\n};\n\nGC_API_PRIV struct _GC_arrays GC_arrays;\n#define beginGC_arrays ((ptr_t)(&GC_arrays))\n#define endGC_arrays (beginGC_arrays + sizeof(GC_arrays))\n\n/* Object kinds. */\n#ifndef MAXOBJKINDS\n#  ifdef SMALL_CONFIG\n#    define MAXOBJKINDS 16\n#  else\n#    define MAXOBJKINDS 24\n#  endif\n#endif\nGC_EXTERN struct obj_kind {\n  /*\n   * Array of free-list headers for this kind of object.  Point either\n   * to `GC_arrays` or to storage allocated with `GC_scratch_alloc()`.\n   */\n  void **ok_freelist;\n\n  /*\n   * List headers for lists of blocks waiting to be swept.\n   * Indexed by object size in granules.\n   */\n  struct hblk **ok_reclaim_list;\n\n  /* Descriptor template for objects in this block. */\n  word ok_descriptor;\n\n  /*\n   * Add object size in bytes to descriptor template to obtain descriptor.\n   * Otherwise the template is used as is.\n   */\n  GC_bool ok_relocate_descr;\n\n  /* Clear objects before putting them on the free list. */\n  GC_bool ok_init;\n\n#ifdef ENABLE_DISCLAIM\n  /*\n   * Mark from all, including unmarked, objects in block.\n   * Used to protect objects reachable from reclaim notifiers.\n   */\n  GC_bool ok_mark_unconditionally;\n\n  /*\n   * The disclaim procedure is called before `obj` is reclaimed, but\n   * must also tolerate being called with object from free list.\n   * A nonzero exit prevents object from being reclaimed.\n   */\n  int(GC_CALLBACK *ok_disclaim_proc)(void * /* `obj` */);\n\n#  define OK_DISCLAIM_INITZ /* comma */ , FALSE, 0\n#else\n#  define OK_DISCLAIM_INITZ /*< empty */\n#endif\n} GC_obj_kinds[MAXOBJKINDS];\n\n#define beginGC_obj_kinds ((ptr_t)(&GC_obj_kinds[0]))\n#define endGC_obj_kinds (beginGC_obj_kinds + sizeof(GC_obj_kinds))\n\n/* The predefined kinds. */\n#define PTRFREE GC_I_PTRFREE\n#define NORMAL GC_I_NORMAL\n#define UNCOLLECTABLE 2\n#ifdef GC_ATOMIC_UNCOLLECTABLE\n#  define AUNCOLLECTABLE 3\n#  define IS_UNCOLLECTABLE(k) (((k) & ~1) == UNCOLLECTABLE)\n#  define GC_N_KINDS_INITIAL_VALUE 4\n#else\n#  define IS_UNCOLLECTABLE(k) ((k) == UNCOLLECTABLE)\n#  define GC_N_KINDS_INITIAL_VALUE 3\n#endif\n\nGC_EXTERN unsigned GC_n_kinds;\n\n/* May mean the allocation granularity size, not page size. */\nGC_EXTERN size_t GC_page_size;\n\n#ifdef REAL_PAGESIZE_NEEDED\nGC_EXTERN size_t GC_real_page_size;\n#else\n#  define GC_real_page_size GC_page_size\n#endif\n\n/*\n * Get heap memory from the OS.\n * Note that `sbrk`-like allocation is preferred, since it usually\n * makes it possible to merge consecutively allocated chunks.\n * It also avoids unintended recursion with `REDIRECT_MALLOC` macro\n * defined.  `GET_MEM()` argument should be of `size_t` type and\n * have no side-effect.  `GET_MEM()` returns `HBLKSIZE`-aligned chunk\n * (`NULL` means a failure).  In case of `MMAP_SUPPORTED`, the argument\n * must also be a multiple of a physical page size.\n * `GET_MEM` is currently not assumed to retrieve zero-filled space.\n */\n/* TODO: Take advantage of `GET_MEM()` returning a zero-filled space. */\n#if defined(ANY_MSWIN) || defined(MSWIN_XBOX1) || defined(OS2)\nGC_INNER void *GC_get_mem(size_t lb);\n#  define GET_MEM(lb) GC_get_mem(lb)\n#  if defined(CYGWIN32) && !defined(USE_WINALLOC)\n#    define NEED_UNIX_GET_MEM\n#  endif\n#elif defined(DOS4GW) || defined(EMBOX) || defined(KOS) || defined(NEXT) \\\n    || defined(NONSTOP) || defined(RTEMS) || defined(__CC_ARM)           \\\n    || (defined(SOLARIS) && !defined(USE_MMAP))\n/* TODO: Use `page_alloc()` directly on Embox. */\n#  if defined(REDIRECT_MALLOC) && !defined(CPPCHECK)\n#    error Malloc redirection is unsupported\n#  endif\n#  define GET_MEM(lb)                                                  \\\n    ((void *)HBLKPTR((ptr_t)calloc(1, SIZET_SAT_ADD(lb, GC_page_size)) \\\n                     + GC_page_size - 1))\n#elif !defined(GET_MEM)\nGC_INNER void *GC_unix_get_mem(size_t lb);\n#  define GET_MEM(lb) GC_unix_get_mem(lb)\n#  define NEED_UNIX_GET_MEM\n#endif\n\n/*\n * Round up allocation size to a multiple of a page size.\n * `GC_setpagesize()` is assumed to be already invoked.\n */\n#define ROUNDUP_PAGESIZE(lb) /*< `lb` should have no side-effect */ \\\n  (SIZET_SAT_ADD(lb, GC_page_size - 1) & ~(GC_page_size - 1))\n\n/*\n * Same as `ROUNDUP_PAGESIZE` but is used to make `GET_MEM()` argument\n * safe.\n */\n#ifdef MMAP_SUPPORTED\n#  define ROUNDUP_PAGESIZE_IF_MMAP(lb) ROUNDUP_PAGESIZE(lb)\n#else\n#  define ROUNDUP_PAGESIZE_IF_MMAP(lb) (lb)\n#endif\n\n#ifdef ANY_MSWIN\nGC_EXTERN SYSTEM_INFO GC_sysinfo;\n\n/*\n * Is `p` the start of either the `malloc` heap, or of one of the collector\n * heap sections?\n */\nGC_INNER GC_bool GC_is_heap_base(const void *p);\n#endif\n\n#ifdef GC_GCJ_SUPPORT\n/* Note: `GC_hblkfreelist` and `GC_free_bytes` remain visible to GNU `gcj`. */\nextern struct hblk *GC_hblkfreelist[];\nextern word GC_free_bytes[];\n#endif\n\n/* This is used by `GC_do_blocking()`. */\nstruct blocking_data {\n  GC_fn_type fn;\n  void *client_data; /*< and result */\n};\n\n/* This is used by `GC_call_with_gc_active`, `GC_push_all_stack_sections`. */\nstruct GC_traced_stack_sect_s {\n  ptr_t saved_stack_ptr;\n#ifdef IA64\n  ptr_t saved_backing_store_ptr;\n  ptr_t backing_store_end;\n#endif\n  struct GC_traced_stack_sect_s *prev;\n};\n\n#ifdef THREADS\n/*\n * Process all \"traced stack sections\" - scan entire stack except for\n * frames belonging to the user functions invoked by `GC_do_blocking`.\n */\nGC_INNER void\nGC_push_all_stack_sections(ptr_t lo, ptr_t hi,\n                           struct GC_traced_stack_sect_s *traced_stack_sect);\n\n/*\n * The total size, in bytes, of all stacks.\n * Updated on every `GC_push_all_stacks()` call.\n */\nGC_EXTERN word GC_total_stacksize;\n\n#else\n/* Note: `NULL` value means we are not inside `GC_do_blocking()` call. */\nGC_EXTERN ptr_t GC_blocked_sp;\n\n/*\n * Points to the \"frame\" data held in stack by the innermost\n * `GC_call_with_gc_active()`.  `NULL` if no such \"frame\" active.\n */\nGC_EXTERN struct GC_traced_stack_sect_s *GC_traced_stack_sect;\n#endif /* !THREADS */\n\n#if defined(E2K) && defined(THREADS) || defined(IA64)\n/*\n * The bottom of the register stack of the primordial thread.\n * E2K: holds the offset (`ps_ofs`) instead of a pointer.\n */\nGC_EXTERN ptr_t GC_register_stackbottom;\n#endif\n\n#ifdef IA64\n/* Similar to `GC_push_all_stack_sections` but for IA-64 registers store. */\nGC_INNER void GC_push_all_register_sections(\n    ptr_t bs_lo, ptr_t bs_hi, GC_bool eager,\n    struct GC_traced_stack_sect_s *traced_stack_sect);\n#endif\n\n/*\n * Mark bit operations.\n *\n * The marks are in a reserved area of each heap block.\n * Each object or granule has one mark bit associated with it.\n * Only those corresponding to the beginning of an object are used.\n */\n\n/*\n * Retrieve, set, clear the `n`-th mark bit in a given heap block.\n * (Recall that bit `n` corresponds to `n`-th object or allocation granule\n * relative to the beginning of the block, including unused space.)\n */\n\n#ifdef USE_MARK_BYTES\n#  define mark_bit_from_hdr(hhdr, n) ((hhdr)->hb_marks[n])\n#  define set_mark_bit_from_hdr(hhdr, n) (void)((hhdr)->hb_marks[n] = 1)\n#  define clear_mark_bit_from_hdr(hhdr, n) (void)((hhdr)->hb_marks[n] = 0)\n#else\n/* Set mark bit correctly, even if mark bits may be concurrently accessed. */\n#  if defined(PARALLEL_MARK) || (defined(THREAD_SANITIZER) && defined(THREADS))\n/*\n * Workaround TSan false positive: there is no race between\n * `mark_bit_from_hdr` and `set_mark_bit_from_hdr` when `n` is different\n * (alternatively, `USE_MARK_BYTES` could be used).  If TSan is off, then\n * `AO_or()` is used only if we define `USE_MARK_BITS` macro explicitly.\n */\n#    define OR_WORD(addr, bits) AO_or(addr, bits)\n#  else\n#    define OR_WORD(addr, bits) (void)(*(addr) |= (bits))\n#  endif\n#  define mark_bit_from_hdr(hhdr, n) \\\n    (((hhdr)->hb_marks[divWORDSZ(n)] >> modWORDSZ(n)) & (word)1)\n#  define set_mark_bit_from_hdr(hhdr, n) \\\n    OR_WORD((hhdr)->hb_marks + divWORDSZ(n), (word)1 << modWORDSZ(n))\n#  define clear_mark_bit_from_hdr(hhdr, n)                                    \\\n    (void)(((word *)CAST_AWAY_VOLATILE_PVOID((hhdr)->hb_marks))[divWORDSZ(n)] \\\n           &= ~((word)1 << modWORDSZ(n)))\n#endif /* !USE_MARK_BYTES */\n\n#ifdef MARK_BIT_PER_OBJ\n/*\n * Get the mark bit index corresponding to the given byte offset and\n * size (in bytes).\n */\n#  define MARK_BIT_NO(offset, sz) ((offset) / (sz))\n\n/* Spacing between useful mark bits. */\n#  define MARK_BIT_OFFSET(sz) 1\n\n/* Position of final, always set, mark bit. */\n#  define FINAL_MARK_BIT(sz) ((sz) > MAXOBJBYTES ? 1 : HBLK_OBJS(sz))\n#else\n#  define MARK_BIT_NO(offset, sz) BYTES_TO_GRANULES(offset)\n#  define MARK_BIT_OFFSET(sz) BYTES_TO_GRANULES(sz)\n#  define FINAL_MARK_BIT(sz)                 \\\n    ((sz) > MAXOBJBYTES ? MARK_BITS_PER_HBLK \\\n                        : BYTES_TO_GRANULES(HBLK_OBJS(sz) * (sz)))\n#endif /* !MARK_BIT_PER_OBJ */\n\n/* Important internal collector routines. */\n\n/* Return the current stack pointer, approximately. */\nGC_INNER ptr_t GC_approx_sp(void);\n\n/*\n * Same as `GC_approx_sp` but a macro.  `sp` should be a local variable\n * of `volatile` `ptr_t` type.\n */\n#if (defined(E2K) && defined(__clang__)         \\\n     || (defined(S390) && __clang_major__ < 8)) \\\n    && !defined(CPPCHECK)\n/*\n * Workaround some bugs in clang:\n *   - \"undefined reference to llvm.frameaddress\" error (clang-9/e2k);\n *   - a crash in SystemZTargetLowering of libLLVM-3.8 (s390).\n */\n#  define STORE_APPROX_SP_TO(sp) (void)(sp = (ptr_t)(&sp))\n#elif defined(CPPCHECK)                              \\\n    || ((__GNUC__ >= 4 /* `GC_GNUC_PREREQ(4, 0)` */) \\\n        && !defined(STACK_NOT_SCANNED))\n/* TODO: Use `GC_GNUC_PREREQ` after fixing a bug in cppcheck. */\n/* Note: l-value is passed instead of pointer to `sp` (because of cppcheck). */\n#  define STORE_APPROX_SP_TO(sp) (void)(sp = (ptr_t)__builtin_frame_address(0))\n#else\n#  define STORE_APPROX_SP_TO(sp) (void)(sp = (ptr_t)(&sp))\n#endif\n\n/* Have we allocated enough to amortize a collection? */\nGC_INNER GC_bool GC_should_collect(void);\n\n/*\n * Get the next block whose address is at least `h`.  Returned block\n * is managed by the collector.  The block must be in use unless\n * `allow_free` is TRUE.  Return `NULL` if there is no such block.\n */\nGC_INNER struct hblk *GC_next_block(struct hblk *h, GC_bool allow_free);\n\n/*\n * Get the last (highest address) block whose address is at most `h`.\n * Returned block is managed by the collector, but may or may not be in use.\n * Return `NULL` if there is no such block.\n */\nGC_INNER struct hblk *GC_prev_block(struct hblk *h);\n\nGC_INNER void GC_mark_init(void);\n\n/*\n * Clear mark bits in all allocated heap blocks (i.e. for all heap objects).\n * This invalidates the marker invariant, and sets `GC_mark_state` to\n * reflect this.  (This implicitly starts marking to reestablish the\n * invariant.)\n */\nGC_INNER void GC_clear_marks(void);\n\n/*\n * Tell the marker that marked objects may point to unmarked ones, and\n * roots may point to unmarked objects.  Reset mark stack.\n */\nGC_INNER void GC_invalidate_mark_state(void);\n\n/*\n * Perform a small amount of marking.  We try to touch roughly a page\n * of memory.  Returns quickly if no collection is in progress.\n * Returns `TRUE` if we just finished a mark phase.\n * `cold_gc_frame` argument is an address inside a frame of the\n * collector that remains valid until all marking is complete;\n * `NULL` value indicates that it is OK to miss some register values.\n * In the case of an incremental collection, the world may be running.\n */\nGC_INNER GC_bool GC_mark_some(ptr_t cold_gc_frame);\n\n/*\n * Initiate a garbage collection.  Initiates a full collection if the\n * mark state is invalid; otherwise it is a partial one.\n */\nGC_INNER void GC_initiate_gc(void);\n\n/*\n * Is a collection in progress?  Note that this can return `TRUE` in\n * the non-incremental case, if a collection has been abandoned and\n * the mark state is now `MS_INVALID`.\n */\nGC_INNER GC_bool GC_collection_in_progress(void);\n\n/*\n * Push contents of the symbol residing in the static roots area excluded\n * from scanning by the collector for a reason.  Note: it should be used only\n * for symbols of relatively small size (containing one or several pointers).\n */\n#define GC_PUSH_ALL_SYM(sym) GC_push_all_eager(&(sym), &(sym) + 1)\n\n/* Same as `GC_push_all` but consider interior pointers as valid. */\nGC_INNER void GC_push_all_stack(ptr_t b, ptr_t t);\n\n#ifdef NO_VDB_FOR_STATIC_ROOTS\n#  define GC_push_conditional_static(b, t, all) \\\n    ((void)(all), GC_push_all(b, t))\n#else\n/*\n * Same as `GC_push_conditional` (does either of `GC_push_all` or\n * `GC_push_selected` depending on the third argument) but the caller\n * guarantees the region belongs to the registered static roots.\n */\nGC_INNER void GC_push_conditional_static(void *b, void *t, GC_bool all);\n#endif\n\n#if defined(WRAP_MARK_SOME) && defined(PARALLEL_MARK)\n/*\n * Similar to `GC_push_conditional` but scans the whole region immediately.\n * `GC_mark_local` does not handle memory protection faults yet.\n * So, the static data regions are scanned immediately by `GC_push_roots`.\n */\nGC_INNER void GC_push_conditional_eager(void *bottom, void *top, GC_bool all);\n#endif\n\n/*\n * In the multi-threaded case, we push part of the current thread stack\n * with `GC_push_all_eager` when we push the registers.  This gets the\n * callee-save registers that may disappear.  The remainder of the stacks\n * are scheduled for scanning in `(*GC_push_other_roots)()`, which is\n * thread-package-specific.\n */\n\n/*\n * Push all or dirty roots.  Call the mark routine (`GC_push_one` for\n * a single pointer, `GC_push_conditional` on groups of pointers) on every\n * top level accessible pointer.  If not `all`, then arrange to push only\n * possibly altered values.  `cold_gc_frame` is an address inside\n * a collector frame that remains valid until all marking is complete;\n * a `NULL` pointer indicates that it is OK to miss some register values.\n */\nGC_INNER void GC_push_roots(GC_bool all, ptr_t cold_gc_frame);\n\n/*\n * Push system or application specific roots onto the mark stack.\n * In some environments (e.g. a multi-threaded one) this is predefined\n * to be nonzero.  A client-supplied replacement should also call the\n * original function.  Remains externally visible as used by some\n * well-known 3rd-party software (e.g., ECL) currently.\n */\nGC_API_PRIV GC_push_other_roots_proc GC_push_other_roots;\n\n#ifdef THREADS\nGC_INNER void GC_push_thread_structures(void);\n#endif\n\n/*\n * A pointer set to `GC_push_typed_structures_proc` lazily so that we can\n * avoid linking in the typed allocation support if the latter is unused.\n */\nGC_EXTERN void (*GC_push_typed_structures)(void);\n\ntypedef void (*GC_with_callee_saves_func)(ptr_t arg, void *context);\n\n/*\n * Ensure that either registers are pushed, or callee-save registers are\n * somewhere on the stack, and then call `fn(arg, ctxt)`.  `ctxt` is either\n * a pointer to a `ucontext_t` entity we generated, or `NULL`.  Could be\n * called with or w/o the allocator lock held; could be called from a signal\n * handler as well.\n */\nGC_INNER void GC_with_callee_saves_pushed(GC_with_callee_saves_func fn,\n                                          ptr_t arg);\n\n#if defined(IA64) || defined(SPARC)\n/*\n * Cause all stacked registers to be saved in memory.  Return a pointer to\n * the top of the corresponding memory stack.\n */\nptr_t GC_save_regs_in_stack(void);\n#endif\n\n#ifdef E2K\n#  include <asm/e2k_syswork.h>\n#  include <errno.h>\n#  include <sys/syscall.h>\n\n#  if defined(CPPCHECK)\n/*\n * Workaround \"Uninitialized bs_lo\" and \"obsolete alloca() called\"\n * false positive (FP) warnings.\n */\n#    define PS_ALLOCA_BUF(pbuf, sz) \\\n      (void)(GC_noop1_ptr(pbuf), *(pbuf) = (ptr_t)__builtin_alloca(sz))\n#  else\n#    define PS_ALLOCA_BUF(pbuf, sz) (void)(*(pbuf) = (ptr_t)alloca(sz))\n#  endif\n\n/*\n * Approximate size (in bytes) of the obtained procedure stack part\n * belonging to `syscall()` itself.\n */\n#  define PS_SYSCALL_TAIL_BYTES 0x100\n\n/*\n * Determine the current size of the whole procedure stack.  The size\n * is valid only within the current function.\n */\n#  define GET_PROCEDURE_STACK_SIZE_INNER(psz_ull)                            \\\n    do {                                                                     \\\n      *(psz_ull) = 0; /*< might be redundant */                              \\\n      if (syscall(__NR_access_hw_stacks, E2K_GET_PROCEDURE_STACK_SIZE, NULL, \\\n                  NULL, 0, psz_ull)                                          \\\n          == -1)                                                             \\\n        ABORT_ARG1(\"Cannot get size of procedure stack\", \": errno= %d\",      \\\n                   errno);                                                   \\\n      GC_ASSERT(*(psz_ull) > 0 && *(psz_ull) % sizeof(ptr_t) == 0);          \\\n    } while (0)\n\n#  ifdef THREADS\n#    define PS_COMPUTE_ADJUSTED_OFS(padj_ps_ofs, ps_ofs, ofs_sz_ull)      \\\n      do {                                                                \\\n        if ((ofs_sz_ull) <= (ps_ofs) /* `&& ofs_sz_ull > 0` */)           \\\n          ABORT_ARG2(\"Incorrect size of procedure stack\",                 \\\n                     \": ofs= %lu, size= %lu\", (unsigned long)(ps_ofs),    \\\n                     (unsigned long)(ofs_sz_ull));                        \\\n        *(padj_ps_ofs) = (ps_ofs) > (unsigned)PS_SYSCALL_TAIL_BYTES       \\\n                             ? (ps_ofs) - (unsigned)PS_SYSCALL_TAIL_BYTES \\\n                             : 0;                                         \\\n      } while (0)\n#  else\n/* A simplified variant of the above assuming `ps_ofs` is a zero const. */\n#    define PS_COMPUTE_ADJUSTED_OFS(padj_ps_ofs, ps_ofs, ofs_sz_ull) \\\n      do {                                                           \\\n        GC_STATIC_ASSERT((ps_ofs) == 0);                             \\\n        (void)(ofs_sz_ull);                                          \\\n        *(padj_ps_ofs) = 0;                                          \\\n      } while (0)\n#  endif /* !THREADS */\n\n/*\n * Copy procedure (register) stack to a stack-allocated buffer.\n * Usable from a signal handler.  The buffer (`*pbuf`) is valid only\n * within the current function.  `ps_ofs` designates the offset in the\n * procedure stack to copy the contents from.  Note: this macro cannot\n * be changed to a function because `alloca()` and both `syscall()`\n * should be called in the context of the caller.\n */\n#  define GET_PROCEDURE_STACK_LOCAL(ps_ofs, pbuf, psz)                      \\\n    do {                                                                    \\\n      unsigned long long ofs_sz_ull;                                        \\\n      size_t adj_ps_ofs;                                                    \\\n                                                                            \\\n      GET_PROCEDURE_STACK_SIZE_INNER(&ofs_sz_ull);                          \\\n      PS_COMPUTE_ADJUSTED_OFS(&adj_ps_ofs, ps_ofs, ofs_sz_ull);             \\\n      *(psz) = (size_t)ofs_sz_ull - adj_ps_ofs;                             \\\n      /* Allocate buffer on the stack; cannot return `NULL`. */             \\\n      PS_ALLOCA_BUF(pbuf, *(psz));                                          \\\n      /* Copy the procedure stack at the given offset to the buffer. */     \\\n      for (;;) {                                                            \\\n        ofs_sz_ull = adj_ps_ofs;                                            \\\n        if (syscall(__NR_access_hw_stacks, E2K_READ_PROCEDURE_STACK_EX,     \\\n                    &ofs_sz_ull, *(pbuf), *(psz), NULL)                     \\\n            != -1)                                                          \\\n          break;                                                            \\\n        if (errno != EAGAIN)                                                \\\n          ABORT_ARG2(\"Cannot read procedure stack\", \": sz= %lu, errno= %d\", \\\n                     (unsigned long)(*(psz)), errno);                       \\\n      }                                                                     \\\n    } while (0)\n#endif /* E2K */\n\n#if defined(E2K) && defined(USE_PTR_HWTAG)\n/* Load value and get tag of the target memory. */\n#  if defined(__ptr64__)\n#    define LOAD_TAGGED_VALUE(v, tag, p)                        \\\n      do {                                                      \\\n        ptr_t val;                                              \\\n        __asm__ __volatile__(\"ldd, sm %[adr], 0x0, %[val]\\n\\t\"  \\\n                             \"gettagd %[val], %[tag]\\n\"         \\\n                             : [val] \"=r\"(val), [tag] \"=r\"(tag) \\\n                             : [adr] \"r\"(p));                   \\\n        v = val;                                                \\\n      } while (0)\n#  elif !defined(CPPCHECK)\n#    error Unsupported -march for e2k target\n#  endif\n\n#  define LOAD_PTR_OR_CONTINUE(v, p) \\\n    {                                \\\n      int tag LOCAL_VAR_INIT_OK;     \\\n      LOAD_TAGGED_VALUE(v, tag, p);  \\\n      if (tag != 0)                  \\\n        continue;                    \\\n    }\n#elif defined(CHERI_PURECAP)\n#  define HAS_TAG_AND_PERM_LOAD(cap) \\\n    (cheri_tag_get(cap) != 0 && (cheri_perms_get(cap) & CHERI_PERM_LOAD) != 0)\n\n#  define LOAD_PTR_OR_CONTINUE(v, p)                                         \\\n    {                                                                        \\\n      word base_addr;                                                        \\\n      v = *(ptr_t *)(p);                                                     \\\n      if (!HAS_TAG_AND_PERM_LOAD(v))                                         \\\n        continue;                                                            \\\n      base_addr = cheri_base_get(v);                                         \\\n      if (ADDR(v) < base_addr || ADDR(v) >= base_addr + cheri_length_get(v)) \\\n        continue;                                                            \\\n    }\n\n#  define CAPABILITY_COVERS_RANGE(cap, b_addr, e_addr) \\\n    (cheri_base_get(cap) <= (b_addr)                   \\\n     && cheri_base_get(cap) + cheri_length_get(cap) >= (e_addr))\n#  define SPANNING_CAPABILITY(cap, b_addr, e_addr)                       \\\n    (cheri_tag_get(cap) && CAPABILITY_COVERS_RANGE(cap, b_addr, e_addr)  \\\n     && (cheri_perms_get(cap) & (CHERI_PERM_LOAD | CHERI_PERM_LOAD_CAP)) \\\n            != 0)\n#else\n#  define LOAD_PTR_OR_CONTINUE(v, p) (void)(v = *(ptr_t *)(p))\n#endif /* !CHERI_PURECAP */\n\n#if defined(DARWIN) && defined(THREADS)\n/*\n * If `p` points to an object, mark it and push contents on the mark stack.\n * Pointer recognition test always accepts interior pointers, i.e. this is\n * appropriate for pointers found on the thread stack.\n */\nvoid GC_push_one(word p);\n#endif\n\n/*\n * Mark and push (i.e. gray) a single object `p` onto the main mark stack.\n * Consider `p` to be valid if it is an interior pointer.  The object `p`\n * has passed a preliminary pointer validity test, but we do not definitely\n * know whether it is valid.  Mark bits are not atomically updated; thus\n * this must be the only thread setting them.\n */\n#if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS)\nGC_INNER void GC_mark_and_push_stack(ptr_t p, ptr_t source);\n#else\nGC_INNER void GC_mark_and_push_stack(ptr_t p);\n#endif\n\n/* Is the block with the given header containing no pointers? */\n#define IS_PTRFREE(hhdr) (0 == (hhdr)->hb_descr)\n\n/* Clear all mark bits in the header. */\nGC_INNER void GC_clear_hdr_marks(hdr *hhdr);\n\n/* Set all mark bits in the header.  Used for uncollectible blocks. */\nGC_INNER void GC_set_hdr_marks(hdr *hhdr);\n\n/* Set all mark bits associated with a free list. */\nGC_INNER void GC_set_fl_marks(ptr_t);\n\n#if defined(GC_ASSERTIONS) && defined(THREAD_LOCAL_ALLOC)\n/*\n * Check that all mark bits associated with a free list are set.\n * Abort if not.\n */\nvoid GC_check_fl_marks(void **);\n#endif\n\n/*\n * Add [`b`,`e`) to the root set.  Adding the same interval a second\n * time is a moderately fast no-op, and hence benign.  We do not handle\n * different but overlapping intervals efficiently.  (But we do handle\n * them correctly.)  `tmp` specifies that the interval may be deleted\n * before re-registering dynamic libraries.\n */\nGC_INNER void GC_add_roots_inner(ptr_t b, ptr_t e, GC_bool tmp);\n\n#ifdef USE_PROC_FOR_LIBRARIES\n/*\n * Remove given range from every static root which intersects with the range.\n * `GC_remove_tmp_roots` is assumed to be called before this function is\n * called (repeatedly) by `GC_register_map_entries`.\n */\nGC_INNER void GC_remove_roots_subregion(ptr_t b, ptr_t e);\n#endif\n\n/*\n * Inform the collector that a certain section of statically allocated\n * memory contains no pointers to garbage-collected memory.\n * The range boundaries should be properly aligned and valid.\n */\nGC_INNER void GC_exclude_static_roots_inner(ptr_t start, ptr_t finish);\n\n#if defined(ANY_MSWIN) || defined(DYNAMIC_LOADING)\n/* Add dynamic library data sections to the root set. */\nGC_INNER void GC_register_dynamic_libraries(void);\n#endif\n\n/*\n * Remove and re-register dynamic libraries if we are configured to do\n * that at each collection.\n */\nGC_INNER void GC_cond_register_dynamic_libraries(void);\n\n/* Machine-dependent startup routines. */\n\n/*\n * Get the cold end of the stack of the primordial thread.  This is always\n * called from the main (primordial) thread.\n */\nGC_INNER ptr_t GC_get_main_stack_base(void);\n\n#ifdef IA64\n/* Get the cold end of register stack. */\nGC_INNER ptr_t GC_get_register_stack_base(void);\n#endif\n\nGC_INNER void GC_register_data_segments(void);\n\n#ifdef THREADS\n/* Both are invoked from `GC_init()` only. */\nGC_INNER void GC_thr_init(void);\n\n/*\n * Perform all initializations, including those that may require allocation,\n * e.g. initialize thread-local free lists if used.  Called by `GC_init()`.\n */\nGC_INNER void GC_init_parallel(void);\n\n#  ifndef DONT_USE_ATEXIT\nGC_INNER GC_bool GC_is_main_thread(void);\n#  endif\n#else\n#  ifdef TRACE_BUF\nvoid GC_add_trace_entry(const char *caller_fn_name, ptr_t arg1, ptr_t arg2);\n#  endif\n#endif /* !THREADS */\n\n#ifdef NO_BLACK_LISTING\n#  define GC_bl_init() (void)0\n/* Do not define `GC_bl_init_no_interiors()`. */\n#  define GC_ADD_TO_BLACK_LIST_NORMAL(p, source) ((void)(p))\n#  define GC_ADD_TO_BLACK_LIST_STACK(p, source) ((void)(p))\n#  define GC_promote_black_lists() (void)0\n#  define GC_unpromote_black_lists() (void)0\n#else\n\n/*\n * If we need a block of `n` bytes, and we have a block of `n + BL_LIMIT`\n * bytes available, and `n` is greater than `BL_LIMIT`, but all possible\n * positions in it are black-listed, we just use it anyway (and print\n * a warning, if warnings are enabled).  This risks subsequently leaking\n * the block due to a false reference.  But not using the block risks\n * unreasonable immediate heap growth.\n */\n#  define BL_LIMIT GC_black_list_spacing\n\n/*\n * Average number of bytes between black-listed blocks.  Approximate.\n * Counts only blocks that are \"stack black-listed\", i.e. that are\n * problematic in the interior of an object.\n */\nGC_EXTERN word GC_black_list_spacing;\n\n/*\n * The interval between unsuppressed warnings about repeated allocation\n * of a very large block.\n */\nGC_EXTERN long GC_large_alloc_warn_interval;\n\n/* Initialize the black listing mechanism. */\nGC_INNER void GC_bl_init(void);\nGC_INNER void GC_bl_init_no_interiors(void);\n\n#  ifdef PRINT_BLACK_LIST\n/*\n * Register bits as a possible future false reference from the heap\n * or static data.  The argument `p` is not a valid pointer reference,\n * but it falls inside the plausible heap bounds.\n */\nGC_INNER void GC_add_to_black_list_normal(ptr_t p, ptr_t source);\n#    define GC_ADD_TO_BLACK_LIST_NORMAL(p, source) \\\n      if (GC_all_interior_pointers) {              \\\n        GC_add_to_black_list_stack(p, source);     \\\n      } else                                       \\\n        GC_add_to_black_list_normal(p, source)\nGC_INNER void GC_add_to_black_list_stack(ptr_t p, ptr_t source);\n#    define GC_ADD_TO_BLACK_LIST_STACK(p, source) \\\n      GC_add_to_black_list_stack(p, source)\n#  else\nGC_INNER void GC_add_to_black_list_normal(ptr_t p);\n#    define GC_ADD_TO_BLACK_LIST_NORMAL(p, source) \\\n      if (GC_all_interior_pointers) {              \\\n        GC_add_to_black_list_stack(p);             \\\n      } else                                       \\\n        GC_add_to_black_list_normal(p)\nGC_INNER void GC_add_to_black_list_stack(ptr_t p);\n#    define GC_ADD_TO_BLACK_LIST_STACK(p, source) GC_add_to_black_list_stack(p)\n#  endif /* PRINT_BLACK_LIST */\n\n/*\n * Declare an end to a black listing phase.  (I.e. signal the completion of\n * a collection.)  Turn the incomplete black lists into new black lists, etc.\n */\nGC_INNER void GC_promote_black_lists(void);\n\n/*\n * Approximately undo the effect of `GC_promote_black_lists()`.\n * This actually loses some information, but only in a reasonably safe way.\n */\nGC_INNER void GC_unpromote_black_lists(void);\n#endif\n\n/*\n * The collector internal memory allocation for small objects.\n * Deallocation is not possible.  May return `NULL`.\n */\nGC_INNER ptr_t GC_scratch_alloc(size_t bytes);\n\n#ifdef GWW_VDB\n/* `GC_scratch_recycle_no_gww()` is not used. */\n#else\n#  define GC_scratch_recycle_no_gww GC_scratch_recycle_inner\n#endif\n/* Reuse the memory region by the heap. */\nGC_INNER void GC_scratch_recycle_inner(void *ptr, size_t sz);\n\n#ifndef MARK_BIT_PER_OBJ\n/*\n * Add a heap block map for objects of a size in granules to `GC_obj_map`.\n * A size of zero is used for large objects.  Returns `FALSE` on failure.\n */\nGC_INNER GC_bool GC_add_map_entry(size_t lg);\n#endif\n\n/*\n * Same as `GC_register_displacement` but assuming the allocator lock\n * is already held.\n */\nGC_INNER void GC_register_displacement_inner(size_t offset);\n\n/*\n * Allocate a new heap block for small objects of size `lg` (in granules)\n * and `kind`.  Add all of the block's objects to the free list for objects\n * of that size.  Set all mark bits if objects are uncollectible.\n * Will fail to do anything if out of memory.\n */\nGC_INNER void GC_new_hblk(size_t lg, int kind);\n\n/*\n * Build a free list for objects of size `lg` (in granules) inside heap\n * block `h`.  Clear objects inside `h` if `clear` argument is set.\n * Add `list` to the end of the free list we build.  Return the new\n * free list.  Normally called by `GC_new_hblk()`, but this could also\n * be called without the allocator lock, if we ensure that there is no\n * concurrent collection which might reclaim objects that we have not\n * yet allocated.\n */\nGC_INNER ptr_t GC_build_fl(struct hblk *h, ptr_t list, size_t lg,\n                           GC_bool clear);\n\n/*\n * Allocate (and return pointer to) a heap block for objects of the\n * given size and alignment (in bytes), searching over the appropriate\n * free block lists; inform the marker that the found block is valid\n * for objects of the indicated size.  Assumes (as implied by the argument\n * name) that `EXTRA_BYTES` value is already added to the size, if needed.\n * The client is responsible for clearing the block, if needed.\n * Note: we set `GC_obj_map` field in the header correctly; the caller\n * is responsible for building an object's free list in the block.\n */\nGC_INNER struct hblk *GC_allochblk(size_t lb_adjusted, int kind,\n                                   unsigned flags, size_t align_m1);\n\n/*\n * Deallocate (free) a heap block and mark it as invalid.  Coalesce it\n * with its neighbors if possible.  All mark words are assumed to be cleared.\n */\nGC_INNER void GC_freehblk(struct hblk *p);\n\n/*  Miscellaneous GC routines. */\n\n/*\n * This explicitly increases the size of the heap.  It is used internally,\n * but may also be invoked from `GC_expand_hp` by client.  The argument is\n * in units of `HBLKSIZE`.  (An argument of zero is treated as 1.)\n * Returns `FALSE` on failure.\n */\nGC_INNER GC_bool GC_expand_hp_inner(word n);\n\n/*\n * Restore unmarked objects to free lists, or (if `abort_if_found` is `TRUE`)\n * report them.  (I.e. perform `GC_reclaim_block()` on the entire heap,\n * after first clearing small-object free lists if we are not just looking\n * for leaks.)  Sweeping of small object pages is largely deferred.\n */\nGC_INNER void GC_start_reclaim(GC_bool abort_if_found);\n\n/*\n * Sweep blocks of the indicated object size (in granules) and kind\n * until either the appropriate nonempty free list is found, or there\n * are no more blocks to sweep.\n */\nGC_INNER void GC_continue_reclaim(size_t lg, int kind);\n\n/*\n * Reclaim all small blocks waiting to be reclaimed.  Abort and return\n * `FALSE` when/if `(*stop_func)()` returns `TRUE`.  If this returns `TRUE`,\n * then it is safe to restart the world with incorrectly cleared mark bits.\n * If `ignore_old`, then reclaim only blocks that have been reclaimed\n * recently, and discard the rest.  `stop_func` may be 0.\n */\nGC_INNER GC_bool GC_reclaim_all(GC_stop_func stop_func, GC_bool ignore_old);\n\n/*\n * Generic procedure to rebuild a free list in `hbp` with header `hhdr`,\n * with objects of size `sz` bytes.  Add `list` to the end of the free list.\n * Add the number of reclaimed bytes to `*pcount`.  Note: it could be called\n * directly from `GC_malloc_many`.\n */\nGC_INNER ptr_t GC_reclaim_generic(struct hblk *hbp, hdr *hhdr, size_t sz,\n                                  GC_bool init, ptr_t list, word *pcount);\n\n/*\n * Is given heap block completely unmarked (i.e. contains no marked objects)?\n * This does not require the block to be in physical memory.\n */\nGC_INNER GC_bool GC_block_empty(const hdr *hhdr);\n\n/* Always returns 0 (`FALSE`). */\nGC_INNER int GC_CALLBACK GC_never_stop_func(void);\n\n/*\n * Stop-the-world garbage collection.  The caller must have acquired\n * the allocator lock.  If `stop_func` is not `GC_never_stop_func`, then\n * abort if `stop_func` returns `TRUE`.  Return `TRUE` if we successfully\n * completed the collection (otherwise the collection is aborted).\n */\nGC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func);\n\n#define GC_gcollect_inner() (void)GC_try_to_collect_inner(GC_never_stop_func)\n\n#ifdef THREADS\n/*\n * We may currently be in thread creation or destruction.  Only set to `TRUE`\n * while the allocator lock is held.  When set, it is OK to run the garbage\n * collection from an unknown thread.  Protected by the allocator lock.\n */\nGC_EXTERN GC_bool GC_in_thread_creation;\n#endif\n\n/*\n * Do `n_blocks` units of a garbage collection work, if appropriate.\n * A unit is an amount appropriate for `HBLKSIZE` bytes of allocation.\n */\nGC_INNER void GC_collect_a_little_inner(size_t n_blocks);\n\nGC_INNER void *GC_malloc_kind_aligned_global(size_t lb, int kind,\n                                             size_t align_m1);\n\nGC_INNER void *GC_generic_malloc_aligned(size_t lb, int kind, unsigned flags,\n                                         size_t align_m1);\n\n/*\n * Allocate an object of the given `kind` but assuming the allocator\n * lock is already held.  Should not be used to directly allocate\n * objects requiring special handling on allocation.  `flags` argument\n * should be 0 or `IGNORE_OFF_PAGE`; in the latter case the client\n * guarantees there will always be a pointer to the beginning (i.e.\n * within the first `hblk`) of the object while it is live.\n */\nGC_INNER void *GC_generic_malloc_inner(size_t lb, int kind, unsigned flags);\n\n/*\n * Collect or expand heap in an attempt make the indicated number of\n * free blocks available.  Should be called until the blocks are\n * available (setting `retry` value to `TRUE` unless this is the first\n * call in a loop) or until it fails by returning `FALSE`.  The `flags`\n * argument should be `IGNORE_OFF_PAGE` or 0.\n */\nGC_INNER GC_bool GC_collect_or_expand(word needed_blocks, unsigned flags,\n                                      GC_bool retry);\n\n/*\n * Make the indicated object free list nonempty, and return its head (the\n * first object on the free list).  The object must be removed from the free\n * list by the caller.  The size is in granules.\n */\nGC_INNER ptr_t GC_allocobj(size_t lg, int kind);\n\n#ifdef GC_ADD_CALLER\n/*\n * `GC_DBG_EXTRAS` is used by the collector debug API functions (unlike\n * `GC_EXTRAS` used by the debug API macros) thus `GC_RETURN_ADDR_PARENT`\n * (pointing to client caller) should be used if possible.\n */\n#  ifdef GC_HAVE_RETURN_ADDR_PARENT\n#    define GC_DBG_EXTRAS GC_RETURN_ADDR_PARENT, NULL, 0\n#  else\n#    define GC_DBG_EXTRAS GC_RETURN_ADDR, NULL, 0\n#  endif\n#else\n#  define GC_DBG_EXTRAS \"unknown\", 0\n#endif /* !GC_ADD_CALLER */\n\n#ifdef GC_COLLECT_AT_MALLOC\n/*\n * Parameter to force collection at every `malloc` of size greater or\n * equal to the given value.  This might be handy during debugging.\n * Note: this variable is visible outside for debugging purpose.\n */\nextern size_t GC_dbg_collect_at_malloc_min_lb;\n\n#  define GC_DBG_COLLECT_AT_MALLOC(lb) \\\n    (void)((lb) >= GC_dbg_collect_at_malloc_min_lb ? (GC_gcollect(), 0) : 0)\n#else\n#  define GC_DBG_COLLECT_AT_MALLOC(lb) (void)0\n#endif /* !GC_COLLECT_AT_MALLOC */\n\n/* Allocation routines that bypass the thread-local cache. */\n\n#if defined(THREAD_LOCAL_ALLOC) && defined(GC_GCJ_SUPPORT)\n/*\n * Allocate an object, clear it, and store the pointer to the type\n * structure (\"vtable\" in `gcj`).  This adds a byte at the end of the\n * object if `GC_malloc` would.\n */\nGC_INNER void *GC_core_gcj_malloc(size_t lb, const void *vtable_ptr,\n                                  unsigned flags);\n#endif\n\nGC_INNER void GC_init_headers(void);\n\n/*\n * Install a header for block `h`.  Return `NULL` on failure, or the\n * uninitialized header otherwise.\n */\nGC_INNER hdr *GC_install_header(struct hblk *h);\n\n/*\n * Set up forwarding counts for block `h` of size `sz`.  Return `FALSE`\n * on failure.\n */\nGC_INNER GC_bool GC_install_counts(struct hblk *h, size_t sz);\n\n/* Remove the header for block `h`. */\nGC_INNER void GC_remove_header(struct hblk *h);\n\n/* Remove forwarding counts for `h`. */\nGC_INNER void GC_remove_counts(struct hblk *h, size_t sz);\n\n/* A non-macro variant of the header location routine. */\nGC_INNER hdr *GC_find_header(const void *h);\n\n/*\n * Get `HBLKSIZE`-aligned heap memory chunk from the OS and add the\n * chunk to `GC_our_memory`.  Return `NULL` if out of memory.\n */\nGC_INNER ptr_t GC_os_get_mem(size_t bytes);\n\n#if defined(NO_FIND_LEAK) && defined(SHORT_DBG_HDRS)\n#  define GC_print_all_errors() (void)0\n#  define GC_check_heap() (void)0\n#  define GC_print_all_smashed() (void)0\n#else\n/*\n * Print smashed and leaked objects, if any.  Clear the lists of such\n * objects.  Called without the allocator lock held.\n */\nGC_INNER void GC_print_all_errors(void);\n\n/*\n * Check that all objects in the heap with debugging info are intact.\n * Add any that are not to `GC_smashed` list.\n */\nGC_EXTERN void (*GC_check_heap)(void);\n\n/* Print `GC_smashed` list if it is not empty.  Then clear the list. */\nGC_EXTERN void (*GC_print_all_smashed)(void);\n#endif\n\n/*\n * If possible, print (using `GC_err_printf()`) a more detailed\n * description (terminated with \"\\n\") of the object referred to by `p`.\n */\nGC_EXTERN void (*GC_print_heap_obj)(ptr_t p);\n\nGC_INNER void GC_default_print_heap_obj_proc(ptr_t p);\n\n#if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)\n/*\n * Print an address map of the process.  The caller should hold the\n * allocator lock.\n */\nvoid GC_print_address_map(void);\n#endif\n\n#ifdef NO_FIND_LEAK\n#  define GC_find_leak_inner FALSE\n#else\n#  define GC_find_leak_inner GC_find_leak\n#  ifndef SHORT_DBG_HDRS\n/*\n * Do not immediately deallocate object on `free()` in the find-leak mode,\n * just mark it as freed (and deallocate it after collection).\n */\nGC_EXTERN GC_bool GC_findleak_delay_free;\n#  endif\n#endif /* !NO_FIND_LEAK */\n\n#if defined(NO_FIND_LEAK) && defined(SHORT_DBG_HDRS)\n#  define get_have_errors() FALSE\n#elif defined(AO_HAVE_store)\n#  define GC_SET_HAVE_ERRORS() AO_store(&GC_have_errors, (AO_t)TRUE)\n#  define get_have_errors() \\\n    ((GC_bool)AO_load(&GC_have_errors)) /*< no barrier */\n#else\n#  define GC_SET_HAVE_ERRORS() (void)(GC_have_errors = TRUE)\n/*\n * We saw a smashed or leaked object.  Call error printing routine\n * occasionally.  It is OK to read it not acquiring the allocator lock.\n * Once set to `TRUE`, it is never cleared.\n */\n#  define get_have_errors() GC_have_errors\n#endif /* !AO_HAVE_store */\n\n#define VERBOSE 2\n#if !defined(NO_CLOCK) || !defined(SMALL_CONFIG)\n/*\n * Value of 1 generates basic collector log; `VERBOSE` generates additional\n * messages.\n */\nGC_EXTERN int GC_print_stats;\n#else /* SMALL_CONFIG */\n/*\n * Defined as a macro to aid the compiler to remove the relevant message\n * character strings from the executable (with a particular level of\n * optimizations).\n */\n#  define GC_print_stats 0\n#endif\n\n#ifdef KEEP_BACK_PTRS\n/* Number of random backtraces to generate for each collection. */\nGC_EXTERN long GC_backtraces;\n#endif\n\n/*\n * A trivial (linear congruential) pseudo-random numbers generator,\n * safe for the concurrent usage.\n */\n#define GC_RAND_MAX ((int)(~0U >> 1))\n#if defined(AO_HAVE_store) && defined(THREAD_SANITIZER)\n#  define GC_RAND_STATE_T volatile AO_t\n#  define GC_RAND_NEXT(pseed) GC_rand_next(pseed)\nGC_INLINE int\nGC_rand_next(GC_RAND_STATE_T *pseed)\n{\n  AO_t next = (AO_t)((AO_load(pseed) * (unsigned32)1103515245UL + 12345)\n                     & (unsigned32)((unsigned)GC_RAND_MAX));\n  AO_store(pseed, next);\n  return (int)next;\n}\n#else\n#  define GC_RAND_STATE_T unsigned32\n#  define GC_RAND_NEXT(pseed) /*< overflow and race are OK */      \\\n    (int)(*(pseed) = (*(pseed) * (unsigned32)1103515245UL + 12345) \\\n                     & (unsigned32)((unsigned)GC_RAND_MAX))\n#endif\n\n#ifdef MAKE_BACK_GRAPH\nGC_EXTERN GC_bool GC_print_back_height;\nvoid GC_print_back_graph_stats(void);\n#endif\n\n#ifdef THREADS\n/*\n * Explicitly deallocate the object when we already hold the allocator lock.\n * Only used for internally allocated objects.\n */\nGC_INNER void GC_free_inner(void *p);\n#endif\n\n#ifdef VALGRIND_TRACKING\n#  define FREE_PROFILER_HOOK(p) GC_free_profiler_hook(p)\n#else\n#  define FREE_PROFILER_HOOK(p) (void)(p)\n#endif\n\n/*\n * Macros used for collector internal allocation.  These assume the\n * allocator lock is held.\n */\n#ifdef DBG_HDRS_ALL\n\n/*\n * An allocation function for internal use.  Normally internally allocated\n * objects do not have debug information.  But in this case, we need to make\n * sure that all objects have debug headers.\n */\nGC_INNER void *GC_debug_generic_malloc_inner(size_t lb, int kind,\n                                             unsigned flags);\n\n#  define GC_INTERNAL_MALLOC(lb, k) GC_debug_generic_malloc_inner(lb, k, 0)\n#  define GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE(lb, k) \\\n    GC_debug_generic_malloc_inner(lb, k, IGNORE_OFF_PAGE)\n#  ifdef THREADS\n/* Used internally; we assume it is called correctly. */\nGC_INNER void GC_debug_free_inner(void *p);\n\n#    define GC_INTERNAL_FREE GC_debug_free_inner\n#  else\n#    define GC_INTERNAL_FREE GC_debug_free\n#  endif\n#else\n#  define GC_INTERNAL_MALLOC(lb, k) GC_generic_malloc_inner(lb, k, 0)\n#  define GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE(lb, k) \\\n    GC_generic_malloc_inner(lb, k, IGNORE_OFF_PAGE)\n#  ifdef THREADS\n#    define GC_INTERNAL_FREE GC_free_inner\n#  else\n#    define GC_INTERNAL_FREE GC_free\n#  endif\n#endif /* !DBG_HDRS_ALL */\n\n/* Memory unmapping routines. */\n#ifdef USE_MUNMAP\n\n/*\n * Unmap blocks that have not been recently touched.  This is the only\n * way blocks are ever unmapped.\n */\nGC_INNER void GC_unmap_old(unsigned threshold);\n\n/*\n * Merge all unmapped blocks that are adjacent to other free blocks.\n * This may involve remapping, since all blocks are either fully mapped\n * or fully unmapped.  Returns `TRUE` if at least one block was merged.\n */\nGC_INNER GC_bool GC_merge_unmapped(void);\n\nGC_INNER void GC_unmap(ptr_t start, size_t bytes);\nGC_INNER void GC_remap(ptr_t start, size_t bytes);\n\n/*\n * Two adjacent blocks have already been unmapped and are about to be merged.\n * Unmap the whole block.  This typically requires that we unmap a small\n * section in the middle that was not previously unmapped due to alignment\n * constraints.\n */\nGC_INNER void GC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2,\n                           size_t bytes2);\n#endif\n\n#ifdef CAN_HANDLE_FORK\n/*\n * Fork-handling mode:\n *   - 0 means no `fork` handling is requested (but client could anyway\n *     call `fork()` provided it is surrounded with `GC_atfork_prepare`,\n *     `GC_atfork_parent`, `GC_atfork_child` calls);\n *   - (-1) means the collector tries to use `pthread_at_fork()` if it is\n *     available (if it succeeds, then `GC_handle_fork` value is changed to\n *     one), a portable client should nonetheless surround `fork()` with\n *     `GC_atfork_prepare()` and the accompanying routines (for the case\n *     of `pthread_at_fork()` failure or absence);\n *   - 1 (or other values) means client fully relies on `pthread_at_fork`\n *     (so if it is missing or failed, then `abort` occurs in `GC_init()`),\n *     `GC_atfork_prepare` and the accompanying routines are no-op in such\n *     a case.\n *\n * Note: the value is examined by `GC_thr_init`.\n */\nGC_EXTERN int GC_handle_fork;\n\n#  ifdef THREADS\n#    if defined(SOLARIS) && !defined(_STRICT_STDC)\n/* Update `pthreads` id in the child process right after `fork`. */\nGC_INNER void GC_stackbase_info_update_after_fork(void);\n#    else\n#      define GC_stackbase_info_update_after_fork() (void)0\n#    endif\n#  endif\n#endif /* CAN_HANDLE_FORK */\n\n#ifdef NO_MANUAL_VDB\n#  define GC_manual_vdb FALSE\n#  define GC_auto_incremental GC_incremental\n#  define GC_dirty(p) (void)(p)\n#  define REACHABLE_AFTER_DIRTY(p) (void)(p)\n#else\n/*\n * The incremental collection is in the manual VDB mode.\n * Assumes `GC_incremental` is `TRUE`.  Should not be modified once\n * `GC_incremental` is set to `TRUE`.\n */\nGC_EXTERN GC_bool GC_manual_vdb;\n\n#  define GC_auto_incremental (GC_incremental && !GC_manual_vdb)\n\n/*\n * Manually mark the page containing `p` as dirty.  Logically, this\n * dirties the entire object.  Does not require locking.\n * Exported and marked as `noinline` for the purpose of some clients that\n * need to patch the symbol when using write barrier validation.\n */\nGC_API_PATCHABLE void GC_dirty_inner(const void *p);\n\n#  define GC_dirty(p) (GC_manual_vdb ? GC_dirty_inner(p) : (void)0)\n#  define REACHABLE_AFTER_DIRTY(p) GC_reachable_here(p)\n#endif /* !NO_MANUAL_VDB */\n\n#ifdef GC_DISABLE_INCREMENTAL\n#  define GC_incremental FALSE\n#else\n/*\n * Using incremental/generational collection.  Assumes dirty bits are\n * being maintained.\n */\nGC_EXTERN GC_bool GC_incremental;\n\n/* Virtual dirty bit (VDB) implementations; each one exports the following. */\n\n/*\n * Initialize the virtual dirty bit implementation.  Returns `TRUE` if\n * virtual dirty bits are maintained (otherwise it is OK to be called again\n * if the client calls `GC_enable_incremental()` once more).\n */\nGC_INNER GC_bool GC_dirty_init(void);\n\n/*\n * Retrieve system dirty bits for the heap to a local buffer (unless\n * `output_unneeded`).  The caller should set `output_unneeded` to indicate\n * that reading of the retrieved dirty bits is not planned till the next\n * retrieval.  Restore the systems notion of which pages are dirty.\n * We assume that either the world is stopped or it is OK to lose dirty bits\n * while it is happening (`GC_enable_incremental()` is the caller and\n * `output_unneeded` is `TRUE` at least if the multi-threading support is on).\n */\nGC_INNER void GC_read_dirty(GC_bool output_unneeded);\n\n/*\n * Is the `HBLKSIZE`-sized page at `h` marked dirty in the local buffer?\n * If the actual page size is different, this returns `TRUE` if any of\n * the pages overlapping `h` are dirty.  This routine may err on the side\n * of labeling pages as dirty (and this implementation does).\n */\nGC_INNER GC_bool GC_page_was_dirty(struct hblk *h);\n\n/*\n * Block `h` is about to be written or allocated shortly.  Ensure that\n * all pages containing any part of the `nblocks` `hblk` entities starting\n * at `h` are no longer write-protected (by the virtual dirty bit\n * implementation).  I.e., this is a call that:\n *   - hints that [`h`, `h + nblocks`) is about to be written;\n *   - guarantees that protection is removed;\n *   - may speed up some virtual dirty bit implementations;\n *   - may be essential if we need to ensure that pointer-free system\n *     call buffers in the heap are not protected.\n */\nGC_INNER void GC_remove_protection(struct hblk *h, size_t nblocks,\n                                   GC_bool is_ptrfree);\n\n#  if !defined(NO_VDB_FOR_STATIC_ROOTS) && !defined(PROC_VDB)\n/* Is VDB working for static roots? */\nGC_INNER GC_bool GC_is_vdb_for_static_roots(void);\n#  endif\n\n#  ifdef CAN_HANDLE_FORK\n#    if defined(PROC_VDB) || defined(SOFT_VDB) \\\n        || (defined(MPROTECT_VDB) && defined(DARWIN) && defined(THREADS))\n/*\n * Update pid-specific resources (like `/proc` file descriptors) needed\n * by the dirty bits implementation after `fork` in the child process.\n */\nGC_INNER void GC_dirty_update_child(void);\n#    else\n#      define GC_dirty_update_child() (void)0\n#    endif\n#  endif /* CAN_HANDLE_FORK */\n\n#  if defined(MPROTECT_VDB) && defined(DARWIN)\nEXTERN_C_END\n#    include <pthread.h>\nEXTERN_C_BEGIN\n#    ifdef THREADS\nGC_INNER int GC_inner_pthread_create(pthread_t *t,\n                                     GC_PTHREAD_CREATE_CONST pthread_attr_t *a,\n                                     void *(*fn)(void *), void *arg);\n#    else\n#      define GC_inner_pthread_create pthread_create\n#    endif\n#  endif\n#endif /* !GC_DISABLE_INCREMENTAL */\n\n#if defined(COUNT_PROTECTED_REGIONS) && defined(MPROTECT_VDB)\n/*\n * Do actions on heap growth, if needed, to prevent hitting the OS kernel\n * limit on the VM map regions.\n */\nGC_INNER void GC_handle_protected_regions_limit(void);\n#else\n#  define GC_handle_protected_regions_limit() (void)0\n#endif\n\n/* Same as `GC_base` but accepts and returns a pointer to `const` object. */\n#define GC_base_C(p) ((const void *)GC_base(GC_CAST_AWAY_CONST_PVOID(p)))\n\n/* Some debugging print routines. */\nvoid GC_print_block_list(void);\nvoid GC_print_hblkfreelist(void);\nvoid GC_print_heap_sects(void);\nvoid GC_print_static_roots(void);\n\n#ifdef KEEP_BACK_PTRS\n/*\n * Store back pointer to `source` in `dest`, if that appears to be\n * possible.  This is not completely safe, since we may mistakenly\n * conclude that `dest` has a debugging wrapper.  But the error\n * probability is very small, and this should not be used in\n * production code.  We assume that `dest` is the real base pointer.\n * `source` should usually be a pointer to the interior of an object.\n */\nGC_INNER void GC_store_back_pointer(ptr_t source, ptr_t dest);\n\nGC_INNER void GC_marked_for_finalization(ptr_t dest);\n#  define GC_STORE_BACK_PTR(source, dest) GC_store_back_pointer(source, dest)\n#  define GC_MARKED_FOR_FINALIZATION(dest) GC_marked_for_finalization(dest)\n#else\n#  define GC_STORE_BACK_PTR(source, dest) (void)(source)\n#  define GC_MARKED_FOR_FINALIZATION(dest)\n#endif /* !KEEP_BACK_PTRS */\n\n/* Make arguments appear live to compiler. */\nvoid GC_noop6(word, word, word, word, word, word);\n\n#ifndef GC_ATTR_FORMAT_PRINTF\n#  if GC_GNUC_PREREQ(3, 0)\n#    define GC_ATTR_FORMAT_PRINTF(spec_argnum, first_checked) \\\n      __attribute__((__format__(__printf__, spec_argnum, first_checked)))\n#  else\n#    define GC_ATTR_FORMAT_PRINTF(spec_argnum, first_checked)\n#  endif\n#endif\n\n/* Logging and diagnostic output. */\n\n/*\n * `GC_printf` is used typically on client explicit print requests.\n * A variant of `printf` that does not allocate, 1 KB total output length.\n * (It uses `sprintf()` internally; hopefully the latter does not allocate\n * memory for `long` arguments.)  For all `GC_*_printf` routines,\n * it is recommended to put \"\\n\" at the end of `format` string (for the\n * output atomicity).\n */\nGC_API_PRIV void GC_printf(const char *format, ...)\n    GC_ATTR_FORMAT_PRINTF(1, 2);\nGC_API_PRIV void GC_err_printf(const char *format, ...)\n    GC_ATTR_FORMAT_PRINTF(1, 2);\n\n/*\n * The basic logging routine.  Typically, it is called directly only inside\n * various `DEBUG_*` blocks.\n */\nGC_API_PRIV void GC_log_printf(const char *format, ...)\n    GC_ATTR_FORMAT_PRINTF(1, 2);\n\n#ifndef GC_ANDROID_LOG\n#  define GC_PRINT_STATS_FLAG (GC_print_stats != 0)\n#  define GC_INFOLOG_PRINTF GC_COND_LOG_PRINTF\n/*\n * The \"verbose\" logging routine which is called only if `GC_print_stats`\n * is `VERBOSE`.\n */\n#  define GC_verbose_log_printf GC_log_printf\n#else\nextern GC_bool GC_quiet;\n#  define GC_PRINT_STATS_FLAG (!GC_quiet)\n/* `INFO`/`DBG` loggers are enabled even if `GC_print_stats` is off. */\n#  ifndef GC_INFOLOG_PRINTF\n#    define GC_INFOLOG_PRINTF \\\n      if (GC_quiet) {         \\\n      } else                  \\\n        GC_info_log_printf\n#  endif\nGC_INNER void GC_info_log_printf(const char *format, ...)\n    GC_ATTR_FORMAT_PRINTF(1, 2);\nGC_INNER void GC_verbose_log_printf(const char *format, ...)\n    GC_ATTR_FORMAT_PRINTF(1, 2);\n#endif /* GC_ANDROID_LOG */\n\n#if defined(SMALL_CONFIG) || defined(GC_ANDROID_LOG)\n#  define GC_ERRINFO_PRINTF GC_INFOLOG_PRINTF\n#else\n#  define GC_ERRINFO_PRINTF GC_log_printf\n#endif\n\n/*\n * Convenient wrapper macros over `GC_log_printf()` and\n * `GC_verbose_log_printf()`.\n */\n#define GC_COND_LOG_PRINTF       \\\n  if (LIKELY(!GC_print_stats)) { \\\n  } else                         \\\n    GC_log_printf\n#define GC_VERBOSE_LOG_PRINTF              \\\n  if (LIKELY(GC_print_stats != VERBOSE)) { \\\n  } else                                   \\\n    GC_verbose_log_printf\n#ifndef GC_DBGLOG_PRINTF\n#  define GC_DBGLOG_PRINTF      \\\n    if (!GC_PRINT_STATS_FLAG) { \\\n    } else                      \\\n      GC_log_printf\n#endif\n\n/* Write `s` to `stderr`, but do not buffer, do not add newlines, do not... */\nvoid GC_err_puts(const char *s);\n\n/*\n * A handy macro for logging size values (of `word` type) in KiB, rounding\n * to nearest value.\n */\n#define TO_KiB_UL(v) ((unsigned long)(((v) + ((1 << 9) - 1)) >> 10))\n\n#ifdef USE_MUNMAP\nGC_EXTERN unsigned GC_unmap_threshold; /*< defined in `alloc.c` file */\n\n/*\n * Force memory unmapping on every collection.  Has no effect on\n * implicitly-initiated collections.\n */\nGC_EXTERN GC_bool GC_force_unmap_on_gcollect;\n#endif\n\n#ifdef MSWIN32\nGC_EXTERN GC_bool GC_no_win32_dlls; /*< defined in `os_dep.c` file */\n\n/* Is this a Windows NT derivative (i.e. NT, Win2K, XP or later)? */\nGC_EXTERN GC_bool GC_wnt;\n#endif\n\n#ifdef THREADS\n#  if (defined(MSWIN32) && !defined(CONSOLE_LOG)) || defined(MSWINCE)\nGC_EXTERN CRITICAL_SECTION GC_write_cs;\n#    ifdef GC_ASSERTIONS\n/*\n * Set to `TRUE` only if `GC_stop_world()` has acquired `GC_write_cs`.\n * Protected by `GC_write_cs`.\n */\nGC_EXTERN GC_bool GC_write_disabled;\n#    endif\n#  endif /* MSWIN32 || MSWINCE */\n#  ifdef NEED_FAULT_HANDLER_LOCK\n/*\n * Acquire the spin lock we use to update dirty bits.  Threads should\n * not get stopped holding it.  But we may acquire and release it during\n * `GC_remove_protection()` call.\n */\n#    define GC_acquire_dirty_lock() \\\n      do { /* Empty. */             \\\n      } while (AO_test_and_set_acquire(&GC_fault_handler_lock) == AO_TS_SET)\n#    define GC_release_dirty_lock() AO_CLEAR(&GC_fault_handler_lock)\n#  else\n#    define GC_acquire_dirty_lock() (void)0\n#    define GC_release_dirty_lock() (void)0\n#  endif\n#  ifdef MSWINCE\nGC_EXTERN GC_bool GC_dont_query_stack_min;\n#  endif\n#elif defined(IA64)\n/* Value returned from register flushing routine (`ar.bsp`). */\nGC_EXTERN ptr_t GC_save_regs_ret_val;\n#endif /* !THREADS */\n\n#ifdef THREAD_LOCAL_ALLOC\nGC_EXTERN GC_bool GC_world_stopped; /*< defined in `alloc.c` file */\n\n/*\n * We must explicitly mark `ptrfree` and `gcj` free lists, since the\n * free list links would not otherwise be found.  We also set them in\n * the normal free lists, since that involves touching less memory than\n * if we scanned them normally.\n */\nGC_INNER void GC_mark_thread_local_free_lists(void);\n#endif\n\n#if defined(GLIBC_2_19_TSX_BUG) && defined(GC_PTHREADS_PARAMARK)\n/* Parse string like `<major>[.<minor>[<tail>]]` and return `major` value. */\nGC_INNER int GC_parse_version(int *pminor, const char *pverstr);\n#endif\n\n#if defined(MPROTECT_VDB) && defined(GWW_VDB)\n/*\n * Returns `TRUE` if `GetWriteWatch()` is available.  May be called\n * repeatedly.  May be called with or without the allocator lock held.\n */\nGC_INNER GC_bool GC_gww_dirty_init(void);\n#endif\n\n#if defined(CHECKSUMS) || defined(PROC_VDB)\n/* Could any valid GC heap pointer ever have been written to this page? */\nGC_INNER GC_bool GC_page_was_ever_dirty(struct hblk *h);\n#endif\n\n#ifndef GC_NO_DEINIT\nGC_INNER void GC_reset_freelist(void);\nGC_INNER void GC_reset_obj_kinds(void);\n#  ifdef CHECKSUMS\nvoid GC_reset_check_page(void);\n#  endif\n#  ifdef THREADS\nGC_INNER void GC_reset_threads(void);\n#  endif\n#  ifdef THREAD_LOCAL_ALLOC\nGC_INNER void GC_reset_thread_local_initialization(void);\n#  endif\n#endif\n\n#ifdef CHECKSUMS\n#  ifdef MPROTECT_VDB\nvoid GC_record_fault(struct hblk *h);\n#  endif\nvoid GC_check_dirty(void);\n#endif\n\nGC_INNER void GC_setpagesize(void);\n\nGC_INNER void GC_initialize_offsets(void);\n\n#if defined(REDIR_MALLOC_AND_LINUXTHREADS) \\\n    && !defined(REDIRECT_MALLOC_IN_HEADER)\nGC_INNER void GC_init_lib_bounds(void);\n#else\n#  define GC_init_lib_bounds() (void)0\n#endif\n\n#ifdef REDIR_MALLOC_AND_LINUXTHREADS\n/*\n * Find the text (code) mapping for the library whose name, after\n * stripping the directory part, starts with `nm`.\n */\nGC_INNER GC_bool GC_text_mapping(const char *nm, ptr_t *startp, ptr_t *endp);\n#endif\n\n#if defined(USE_WINALLOC) && !defined(REDIRECT_MALLOC)\nGC_INNER void GC_add_current_malloc_heap(void);\n#endif\n\n#ifdef MAKE_BACK_GRAPH\n/*\n * Rebuild the representation of the backward reachability graph.\n * Does not examine mark bits.  Could be called before collection.\n */\nGC_INNER void GC_build_back_graph(void);\n\nGC_INNER void GC_traverse_back_graph(void);\n#endif\n\n#ifdef MSWIN32\nGC_INNER void GC_init_win32(void);\n#endif\n\n#ifndef ANY_MSWIN\n/*\n * Is a particular static root (with the given start) registered?\n * If so, then return a pointer to it, else `NULL`.  The type is a lie,\n * since the real type does not make sense here, and we only test for `NULL`.\n */\nGC_INNER void *GC_roots_present(ptr_t);\n#endif\n\n#if defined(GC_WIN32_THREADS)\n/* Same as `GC_push_one` but for a sequence of registers. */\nGC_INNER void GC_push_many_regs(const word *regs, unsigned count);\n\n/*\n * Find stack with the lowest address which overlaps the interval\n * [`start`, `limit`).  Return stack bounds in `*plo` and `*phi`.\n * If no such stack is found, both `*phi` and `*plo` will be set to an\n * address higher than `limit`.\n */\nGC_INNER void GC_get_next_stack(ptr_t start, ptr_t limit, ptr_t *plo,\n                                ptr_t *phi);\n\n#  if defined(MPROTECT_VDB) && !defined(CYGWIN32)\nGC_INNER void GC_set_write_fault_handler(void);\n#  endif\n#  if defined(WRAP_MARK_SOME) && !defined(GC_PTHREADS)\n/*\n * Did we invalidate mark phase with an unexpected thread start?\n * Return `TRUE` if a thread was attached since we last asked or since\n * `GC_attached_thread` was explicitly reset.\n */\nGC_INNER GC_bool GC_started_thread_while_stopped(void);\n#  endif\n#endif /* GC_WIN32_THREADS */\n\n#if defined(MPROTECT_VDB) && defined(DARWIN) && defined(THREADS)\nGC_INNER void GC_mprotect_stop(void);\nGC_INNER void GC_mprotect_resume(void);\n#  ifndef GC_NO_THREADS_DISCOVERY\nGC_INNER void GC_darwin_register_self_mach_handler(void);\n#  endif\n#endif\n\n#ifndef NOT_GCBUILD\n/*\n * Iterate over forwarding addresses, if any, to get the beginning of\n * the block and its header.  Assumes `*phhdr` is non-`NULL` on entry,\n * and guarantees `*phhdr` is non-`NULL` on return.\n */\nGC_INLINE struct hblk *\nGC_find_starting_hblk(struct hblk *h, hdr **phhdr)\n{\n  hdr *hhdr = *phhdr;\n\n  GC_ASSERT(HDR(h) == hhdr);\n  for (; IS_FORWARDING_ADDR_OR_NIL(hhdr); hhdr = HDR(h)) {\n    GC_ASSERT(hhdr != NULL);\n    h = FORWARDED_ADDR(h, hhdr);\n  }\n  *phhdr = hhdr;\n  return h;\n}\n#endif /* !NOT_GCBUILD */\n\n#if (defined(PARALLEL_MARK)                                      \\\n     && !defined(HAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG)       \\\n     && (defined(HAVE_PTHREAD_SETNAME_NP_WITH_TID)               \\\n         || defined(HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID)         \\\n         || defined(HAVE_PTHREAD_SET_NAME_NP)))                  \\\n    || (defined(DYNAMIC_LOADING)                                 \\\n        && ((defined(USE_PROC_FOR_LIBRARIES) && !defined(LINUX)) \\\n            || defined(DARWIN) || defined(IRIX5)))               \\\n    || defined(PROC_VDB) || defined(SOFT_VDB)\n/*\n * A function to convert a long integer value `lv` to a string adding\n * the `prefix` and optional `suffix`.  The resulting string is put to\n * `buf` of the designated size (`buf_sz`).  Guaranteed to append\n * a trailing \"\\0\" and not to exceed the buffer size.  (Note that it is\n * recommended to reserve at least 20 characters for the number part of\n * the string in `buf` to avoid a compiler warning about potential\n * number truncation.)\n */\n#  ifndef GC_DISABLE_SNPRINTF\n#    define GC_snprintf_s_ld_s(buf, buf_sz, prefix, lv, suffix)    \\\n      (void)(snprintf(buf, buf_sz, \"%s%ld%s\", prefix, lv, suffix), \\\n             (buf)[(buf_sz) - (size_t)1] = '\\0')\n#  else\n#    define NEED_SNPRINTF_SLDS\nGC_INNER void GC_snprintf_s_ld_s(char *buf, size_t buf_sz, const char *prefix,\n                                 long lv, const char *suffix);\n#  endif\n#endif\n\n#ifdef THREADS\n#  ifndef GC_NO_FINALIZATION\n/* Called by `GC_finalize()` (in case of an allocation failure observed). */\nGC_INNER void GC_reset_finalizer_nested(void);\n\n/*\n * Check and update the thread-local level of finalizers recursion.\n * Returns `NULL` if `GC_invoke_finalizers()` should not be called by\n * the collector (to minimize the risk of a deep finalizers recursion),\n * otherwise returns a pointer to the thread-local `finalizer_nested`.\n * Called by `GC_notify_or_invoke_finalizers()` only.\n */\nGC_INNER unsigned char *GC_check_finalizer_nested(void);\n#  endif\n\nGC_INNER void GC_do_blocking_inner(ptr_t data, void *context);\n\n/*\n * Should do exactly the right thing if the world is stopped; should\n * not fail if it is not stopped.\n */\nGC_INNER void GC_push_all_stacks(void);\n\n#  ifdef USE_PROC_FOR_LIBRARIES\nGC_INNER GC_bool GC_segment_is_thread_stack(ptr_t lo, ptr_t hi);\n#  endif\n#  if (defined(HAVE_PTHREAD_ATTR_GET_NP) || defined(HAVE_PTHREAD_GETATTR_NP)) \\\n      && defined(IA64)\n/*\n * Find the largest stack base smaller than `bound`.  May be used to find\n * the boundary between a register stack and adjacent immediately preceding\n * memory stack.\n */\nGC_INNER ptr_t GC_greatest_stack_base_below(ptr_t bound);\n#  endif\n#endif /* THREADS */\n\n#ifdef DYNAMIC_LOADING\n/* Do we need to separately register the main static data segment? */\nGC_INNER GC_bool GC_register_main_static_data(void);\n\n#  ifdef DARWIN\nGC_INNER void GC_init_dyld(void);\n#  endif\n#endif /* DYNAMIC_LOADING */\n\n#ifdef SEARCH_FOR_DATA_START\nGC_INNER void GC_init_linux_data_start(void);\n#endif\n\n#ifdef NEED_PROC_MAPS\n#  if defined(DYNAMIC_LOADING) && defined(USE_PROC_FOR_LIBRARIES) \\\n      || defined(IA64) || defined(INCLUDE_LINUX_THREAD_DESCR)     \\\n      || (defined(CHECK_SOFT_VDB) && defined(MPROTECT_VDB))       \\\n      || defined(REDIR_MALLOC_AND_LINUXTHREADS)\n/*\n * Assign various fields of the first line in `maps_ptr` to `*p_start`,\n * `*p_end`, `*p_prot`, `*p_maj_dev` and `*p_mapping_name`.\n * `p_mapping_name` may be `NULL`. `*p_prot` and `*p_mapping_name` are\n * assigned pointers into the original buffer.\n */\nGC_INNER const char *GC_parse_map_entry(const char *maps_ptr, ptr_t *p_start,\n                                        ptr_t *p_end, const char **p_prot,\n                                        unsigned *p_maj_dev,\n                                        const char **p_mapping_name);\n#  endif\n#  if defined(IA64) || defined(INCLUDE_LINUX_THREAD_DESCR) \\\n      || (defined(CHECK_SOFT_VDB) && defined(MPROTECT_VDB))\n/*\n * Try to read the backing store base from `/proc/self/maps` file.\n * Return the bounds of the writable mapping with a zero major device,\n * which includes the address passed as data.  Return `FALSE` if there\n * is no such mapping.\n */\nGC_INNER GC_bool GC_enclosing_writable_mapping(ptr_t addr, ptr_t *startp,\n                                               ptr_t *endp);\n#  endif\n\n/*\n * Copy the content of `/proc/self/maps` file to a buffer in our\n * address space.  Return the address of the buffer.\n */\nGC_INNER const char *GC_get_maps(void);\n#endif /* NEED_PROC_MAPS */\n\n#ifdef GC_ASSERTIONS\n/* Should return the same value as `GC_large_free_bytes`. */\nGC_INNER word GC_compute_large_free_bytes(void);\n\n/* Should return the same value as `GC_root_size`. */\nGC_INNER word GC_compute_root_size(void);\n#endif\n\n/* Check a compile time assertion at compile time. */\n#if defined(_MSC_VER) && (_MSC_VER >= 1700)\n#  define GC_STATIC_ASSERT(e) static_assert(e, \"static assertion failed: \" #e)\n#elif defined(static_assert) && !defined(CPPCHECK) \\\n    && (__STDC_VERSION__ >= 201112L)\n#  define GC_STATIC_ASSERT(e)                                               \\\n    do { /* placed in `do`-`while` for proper formatting by clang-format */ \\\n      static_assert(e, #e);                                                 \\\n    } while (0)\n#elif defined(mips) && !defined(__GNUC__) && !defined(CPPCHECK)\n/*\n * DOB: MIPSPro C gets an internal error taking the `sizeof` an array type.\n * This code works correctly (ugliness is to avoid \"unused var\" warnings).\n */\n#  define GC_STATIC_ASSERT(e) \\\n    do {                      \\\n      if (0) {                \\\n        char j[(e) ? 1 : -1]; \\\n        j[0] = '\\0';          \\\n        j[0] = j[0];          \\\n      }                       \\\n    } while (0)\n#else\n/* The error message for failure is a bit baroque, but... */\n#  define GC_STATIC_ASSERT(e) (void)sizeof(char[(e) ? 1 : -1])\n#endif\n\n/*\n * Runtime check for an argument declared as non-`NULL` is actually\n * not `NULL`.\n */\n#if GC_GNUC_PREREQ(4, 0)\n/* Workaround tautological-pointer-compare Clang warning. */\n#  define NONNULL_ARG_NOT_NULL(arg) \\\n    (*CAST_THRU_UINTPTR(volatile void **, &(arg)) != NULL)\n#else\n#  define NONNULL_ARG_NOT_NULL(arg) ((arg) != NULL)\n#endif\n\n#define COND_DUMP_CHECKS                                             \\\n  do {                                                               \\\n    GC_ASSERT(I_HOLD_LOCK());                                        \\\n    GC_ASSERT(GC_compute_large_free_bytes() == GC_large_free_bytes); \\\n    GC_ASSERT(GC_compute_root_size() == GC_root_size);               \\\n  } while (0)\n\n#ifndef NO_DEBUGGING\n/* A flag to generate regular debugging dumps. */\nGC_EXTERN GC_bool GC_dump_regularly;\n#  define COND_DUMP                    \\\n    if (UNLIKELY(GC_dump_regularly)) { \\\n      GC_dump_named(NULL);             \\\n    } else                             \\\n      COND_DUMP_CHECKS\n#else\n#  define COND_DUMP COND_DUMP_CHECKS\n#endif\n\n/*\n * We need additional synchronization facilities from the thread support.\n * We believe these are less performance critical than the allocator lock;\n * standard `pthreads`-based implementations should be sufficient.\n */\n#ifdef PARALLEL_MARK\n\n/*\n * Number of mark threads we would like to have excluding the initiating\n * thread.\n */\n#  define GC_markers_m1 GC_parallel\n\n/* A flag to temporarily avoid parallel marking. */\nGC_EXTERN GC_bool GC_parallel_mark_disabled;\n\n/*\n * The routines to deal with the mark lock and condition variables.\n * If the allocator lock is also acquired, it must be done first.\n * The mark lock is used to both protect some variables used by the\n * parallel marker, and to protect `GC_fl_builder_count`.\n * `GC_notify_all_marker()` is called when the state of the parallel marker\n * changes in some significant way (see `gc_mark.h` file for details).\n * The latter set of events includes incrementing `GC_mark_no`.\n * `GC_notify_all_builder()` is called when `GC_fl_builder_count` reaches\n * zero.\n */\n\n/*\n * Wait all markers to finish initialization (i.e. store `marker_sp`,\n * `marker_bsp`, `marker_mach_threads`, `GC_marker_Id`).\n */\nGC_INNER void GC_wait_for_markers_init(void);\n\nGC_INNER void GC_acquire_mark_lock(void);\nGC_INNER void GC_release_mark_lock(void);\nGC_INNER void GC_notify_all_builder(void);\nGC_INNER void GC_wait_for_reclaim(void);\n\n/*\n * Number of threads currently building free lists without holding\n * the allocator lock.  It is not safe to collect if this is nonzero.\n * Also, together with the mark lock, it is used as a semaphore during\n * marker threads startup.  Protected by the mark lock.\n */\nGC_EXTERN GC_signed_word GC_fl_builder_count;\n\nGC_INNER void GC_notify_all_marker(void);\nGC_INNER void GC_wait_marker(void);\n\n/*\n * Try to help out parallel marker, if it is running, for mark cycle\n * `my_mark_no`.  Returns if the mark cycle finishes or was already\n * done, or there was nothing to do for some other reason.  We hold the\n * mark lock only, the initiating thread holds the allocator lock.\n */\nGC_INNER void GC_help_marker(word my_mark_no);\n\nGC_INNER void GC_start_mark_threads_inner(void);\n\n#  define INCR_MARKS(hhdr) \\\n    AO_store(&(hhdr)->hb_n_marks, AO_load(&(hhdr)->hb_n_marks) + 1)\n#else\n#  define INCR_MARKS(hhdr) (void)(++(hhdr)->hb_n_marks)\n#endif /* !PARALLEL_MARK */\n\n#if defined(SIGNAL_BASED_STOP_WORLD) && !defined(SIG_SUSPEND)\n/*\n * We define the thread suspension signal here, so that we can refer\n * to it in the virtual dirty bit (VDB) implementation, if necessary.\n * Ideally we would allocate a (real-time?) signal using the standard\n * mechanism.  Unfortunately, there is no such one.  (There is one in\n * Linux `glibc`, but it is not exported.)  Thus we continue to use\n * the same hard-coded signals we have always used.\n */\n#  ifdef THREAD_SANITIZER\n/*\n * Unfortunately, use of an asynchronous signal to suspend threads leads to\n * the situation when the signal is not delivered (it is stored to\n * `pending_signals` in TSan runtime actually) while the destination thread\n * is blocked in `pthread_mutex_lock()`.  Thus, we use some synchronous one\n * instead (which is again unlikely to be used by clients directly).\n */\n#    define SIG_SUSPEND SIGSYS\n#  elif (defined(DGUX) || defined(LINUX)) && !defined(GC_USESIGRT_SIGNALS)\n#    if defined(SPARC) && !defined(SIGPWR)\n/*\n * Linux/SPARC does not properly define `SIGPWR` in platform `signal.h` file.\n * It is aliased to `SIGLOST` in platform `asm/signal.h` file, though.\n */\n#      define SIG_SUSPEND SIGLOST\n#    else\n/* LinuxThreads itself uses `SIGUSR1` and `SIGUSR2`. */\n#      define SIG_SUSPEND SIGPWR\n#    endif\n#  elif defined(FREEBSD) && defined(__GLIBC__) && !defined(GC_USESIGRT_SIGNALS)\n#    define SIG_SUSPEND (32 + 6)\n#  elif (defined(FREEBSD) || defined(HURD) || defined(RTEMS)) \\\n      && !defined(GC_USESIGRT_SIGNALS)\n#    define SIG_SUSPEND SIGUSR1\n/* `SIGTSTP` and `SIGCONT` could be used alternatively on FreeBSD. */\n#  elif (defined(OPENBSD) && !defined(GC_USESIGRT_SIGNALS)) \\\n      || defined(SERENITY)\n#    define SIG_SUSPEND SIGXFSZ\n#  elif defined(_SIGRTMIN) && !defined(CPPCHECK)\n#    define SIG_SUSPEND _SIGRTMIN + 6\n#  else\n#    define SIG_SUSPEND SIGRTMIN + 6\n#  endif\n#endif /* GC_PTHREADS && !SIG_SUSPEND */\n\n#if defined(GC_PTHREADS) && !defined(GC_SEM_INIT_PSHARED)\n#  define GC_SEM_INIT_PSHARED 0\n#endif\n\n/*\n * Some macros for `setjmp()` working across signal handlers, where\n * possible.\n */\n#if (defined(UNIX_LIKE) || (defined(NEED_FIND_LIMIT) && defined(CYGWIN32))) \\\n    && !defined(GC_NO_SIGSETJMP)\n#  if defined(SUNOS5SIGS) && !defined(FREEBSD) && !defined(LINUX)\nEXTERN_C_END\n#    include <sys/siginfo.h>\nEXTERN_C_BEGIN\n#  endif\n/*\n * Define `SETJMP()` and friends to be the variant restoring the signal\n * mask.\n */\n#  define SETJMP(env) sigsetjmp(env, 1)\n#  define LONGJMP(env, val) siglongjmp(env, val)\n#  define JMP_BUF sigjmp_buf\n#else\n#  ifdef ECOS\n#    define SETJMP(env) hal_setjmp(env)\n#  else\n#    define SETJMP(env) setjmp(env)\n#  endif\n#  define LONGJMP(env, val) longjmp(env, val)\n#  define JMP_BUF jmp_buf\n#endif /* !UNIX_LIKE || GC_NO_SIGSETJMP */\n\n#ifdef DATASTART_USES_XGETDATASTART\n#  ifdef FREEBSD\nEXTERN_C_END\n#    include <machine/trap.h>\nEXTERN_C_BEGIN\n#  endif\nGC_INNER ptr_t GC_SysVGetDataStart(size_t, ptr_t);\n#endif /* DATASTART_USES_XGETDATASTART */\n\n#if defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS) \\\n    || defined(NEED_FIND_LIMIT) || defined(SEARCH_FOR_DATA_START)\n#  if (defined(HOST_ANDROID) || defined(__ANDROID__)) \\\n      && defined(IGNORE_DYNAMIC_LOADING)\n/* Declared as public one in `gc.h` file. */\n#  else\nvoid *GC_find_limit(void *p, int up);\n#  endif\n#endif\n\n#if defined(NEED_FIND_LIMIT)                                 \\\n    || (defined(UNIX_LIKE) && !defined(NO_DEBUGGING))        \\\n    || (defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS)) \\\n    || (defined(WRAP_MARK_SOME) && defined(NO_SEH_AVAILABLE))\ntypedef void (*GC_fault_handler_t)(int);\nGC_INNER void GC_set_and_save_fault_handler(GC_fault_handler_t);\n#endif\n\n#if defined(NEED_FIND_LIMIT)                                 \\\n    || (defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS)) \\\n    || (defined(WRAP_MARK_SOME) && defined(NO_SEH_AVAILABLE))\nGC_EXTERN JMP_BUF GC_jmp_buf;\n\n/*\n * Set up a handler for address faults which will `longjmp`\n * to `GC_jmp_buf`.\n */\nGC_INNER void GC_setup_temporary_fault_handler(void);\n\n/* Undo the effect of `GC_setup_temporary_fault_handler`. */\nGC_INNER void GC_reset_fault_handler(void);\n#endif /* NEED_FIND_LIMIT || USE_PROC_FOR_LIBRARIES || WRAP_MARK_SOME */\n\n/* Some convenience macros for cancellation support. */\n#ifdef CANCEL_SAFE\n#  if defined(GC_ASSERTIONS)                                            \\\n      && (defined(USE_COMPILER_TLS)                                     \\\n          || (defined(LINUX) && !defined(ARM32) && GC_GNUC_PREREQ(3, 3) \\\n              || defined(HPUX) /* and probably others... */))\nextern __thread unsigned char GC_cancel_disable_count;\n#    define NEED_CANCEL_DISABLE_COUNT\n#    define INCR_CANCEL_DISABLE() ++GC_cancel_disable_count\n#    define DECR_CANCEL_DISABLE() --GC_cancel_disable_count\n#    define ASSERT_CANCEL_DISABLED() GC_ASSERT(GC_cancel_disable_count > 0)\n#  else\n#    define INCR_CANCEL_DISABLE()\n#    define DECR_CANCEL_DISABLE()\n#    define ASSERT_CANCEL_DISABLED() (void)0\n#  endif /* !GC_ASSERTIONS */\n#  define DISABLE_CANCEL(state)                               \\\n    do {                                                      \\\n      pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state); \\\n      INCR_CANCEL_DISABLE();                                  \\\n    } while (0)\n#  define RESTORE_CANCEL(state)            \\\n    do {                                   \\\n      ASSERT_CANCEL_DISABLED();            \\\n      pthread_setcancelstate(state, NULL); \\\n      DECR_CANCEL_DISABLE();               \\\n    } while (0)\n#else\n#  define DISABLE_CANCEL(state) (void)0\n#  define RESTORE_CANCEL(state) (void)0\n#  define ASSERT_CANCEL_DISABLED() (void)0\n#endif /* !CANCEL_SAFE */\n\n/* Multiply 32-bit unsigned values (used by `GC_push_contents_hdr()`). */\n#ifdef NO_LONGLONG64\n#  define LONG_MULT(hprod, lprod, x, y)                                 \\\n    do {                                                                \\\n      unsigned32 lx = (x) & (0xffffU);                                  \\\n      unsigned32 ly = (y) & (0xffffU);                                  \\\n      unsigned32 hx = (x) >> 16;                                        \\\n      unsigned32 hy = (y) >> 16;                                        \\\n      unsigned32 lxhy = lx * hy;                                        \\\n      unsigned32 mid = hx * ly + lxhy; /*< may overflow */              \\\n      unsigned32 lxly = lx * ly;                                        \\\n                                                                        \\\n      lprod = (mid << 16) + lxly; /*< may overflow */                   \\\n      hprod = hx * hy + ((lprod) < lxly ? 1U : 0)                       \\\n              + (mid < lxhy ? (unsigned32)0x10000UL : 0) + (mid >> 16); \\\n    } while (0)\n#elif defined(I386) && defined(__GNUC__) && !defined(NACL)\n#  define LONG_MULT(hprod, lprod, x, y) \\\n    __asm__ __volatile__(\"mull %2\" : \"=a\"(lprod), \"=d\"(hprod) : \"r\"(y), \"0\"(x))\n#else\n#  if (defined(__int64) && !defined(__GNUC__) || defined(__BORLANDC__)) \\\n      && !defined(CPPCHECK)\n#    define ULONG_MULT_T unsigned __int64\n#  else\n#    define ULONG_MULT_T unsigned long long\n#  endif\n#  define LONG_MULT(hprod, lprod, x, y)                          \\\n    do {                                                         \\\n      ULONG_MULT_T prod = (ULONG_MULT_T)(x) * (ULONG_MULT_T)(y); \\\n                                                                 \\\n      GC_STATIC_ASSERT(sizeof(x) + sizeof(y) <= sizeof(prod));   \\\n      hprod = (unsigned32)(prod >> 32);                          \\\n      lprod = (unsigned32)prod;                                  \\\n    } while (0)\n#endif /* !I386 && !NO_LONGLONG64 */\n\nEXTERN_C_END\n\n#endif /* GC_PRIVATE_H */\n\n#ifdef KEEP_BACK_PTRS\n#  include \"gc/gc_backptr.h\"\n#endif\n\nEXTERN_C_BEGIN\n\n#ifndef GC_FREED_MEM_MARKER\n#  if CPP_WORDSZ == 32\n#    define GC_FREED_MEM_MARKER (GC_uintptr_t)0xdeadbeef\n#  else\n#    define GC_FREED_MEM_MARKER ((GC_uintptr_t)GC_WORD_C(0xEFBEADDEdeadbeef))\n#  endif\n#endif /* !GC_FREED_MEM_MARKER */\n\n/*\n * Stored both one past the end of user object, and one before the end of\n * the object as seen by the allocator.\n */\n#if CPP_WORDSZ == 32\n#  define START_FLAG (GC_uintptr_t)0xfedcedcb\n#  define END_FLAG (GC_uintptr_t)0xbcdecdef\n#else\n#  define START_FLAG ((GC_uintptr_t)GC_WORD_C(0xFEDCEDCBfedcedcb))\n#  define END_FLAG ((GC_uintptr_t)GC_WORD_C(0xBCDECDEFbcdecdef))\n#endif\n\n#if defined(KEEP_BACK_PTRS) || defined(PRINT_BLACK_LIST)\n/*\n * Pointer \"source\" variants that are not real locations.  Used in\n * `oh_back_ptr` fields and as `source` argument to some marking functions.\n */\n\n/* Object was marked because it is finalizable. */\n#  define MARKED_FOR_FINALIZATION ((ptr_t)NUMERIC_TO_VPTR(2))\n\n/*\n * Object was marked from a register.  Hence the \"source\" of the reference\n * does not have an address.\n */\n#  define MARKED_FROM_REGISTER ((ptr_t)NUMERIC_TO_VPTR(4))\n\n#  define NOT_MARKED ((ptr_t)NUMERIC_TO_VPTR(8))\n#endif /* KEEP_BACK_PTRS || PRINT_BLACK_LIST */\n\n/*\n * Object debug header.  The size of the structure is assumed not to\n * de-align things, and to be a multiple of a double-pointer length.\n */\ntypedef struct {\n#if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)\n  /*\n   * We potentially keep two different kinds of back pointers.\n   * `KEEP_BACK_PTRS` stores a single back pointer in each reachable\n   * object to allow reporting of why an object was retained.\n   * `MAKE_BACK_GRAPH` builds a graph containing the inverse of all\n   * \"points-to\" edges including those involving objects that have just\n   * become unreachable.  This allows detection of growing chains of\n   * unreachable objects.  It may be possible to eventually combine both,\n   * but for now we keep them separate.  Both kinds of back pointers are\n   * hidden using the following macros.  In both cases, the plain variant\n   * is constrained to have the least significant bit of 1, to allow it\n   * to be distinguished from a free-list link.  This means the plain\n   * variant must have the least significant bit of zero.\n   * Note that blocks dropped by black-listing will also have the least\n   * significant bit clear once debugging has started; we are careful never\n   * to overwrite such a value.\n   */\n#  if ALIGNMENT == 1\n  /* Fudge back pointer to be even. */\n#    define HIDE_BACK_PTR(p) \\\n      GC_HIDE_POINTER((ptr_t)(~(GC_uintptr_t)1 & (GC_uintptr_t)(p)))\n#  else\n#    define HIDE_BACK_PTR(p) GC_HIDE_POINTER(p)\n#  endif\n  /*\n   * Always define either none or both of the fields to ensure\n   * double-pointer alignment.\n   */\n  GC_hidden_pointer oh_back_ptr;\n  GC_hidden_pointer oh_bg_ptr;\n#endif\n  const char *oh_string; /*< object descriptor string (file name) */\n  GC_signed_word oh_int; /*< object descriptor integer (line number) */\n#ifdef NEED_CALLINFO\n  struct callinfo oh_ci[NFRAMES];\n#endif\n#ifndef SHORT_DBG_HDRS\n  GC_uintptr_t oh_sz; /*< the original `malloc` argument */\n  GC_uintptr_t oh_sf; /*< the \"start\" flag (marker) */\n#endif\n} oh;\n\n#define GET_OH_LINENUM(ohdr) ((int)(ohdr)->oh_int)\n\n#ifdef SHORT_DBG_HDRS\n#  define DEBUG_BYTES sizeof(oh)\n#  define UNCOLLECTABLE_DEBUG_BYTES DEBUG_BYTES\n#else\n/*\n * Add space for `END_FLAG`, but use any extra space that was already\n * added to catch off-the-end pointers.  For uncollectible objects, the\n * extra byte is not added.\n */\n#  define UNCOLLECTABLE_DEBUG_BYTES (sizeof(oh) + sizeof(GC_uintptr_t))\n#  define DEBUG_BYTES (UNCOLLECTABLE_DEBUG_BYTES - EXTRA_BYTES)\n#endif\n\n/*\n * `ADD_CALL_CHAIN` stores a (partial) call chain into an object header;\n * it should be called with the allocator lock held.\n * `PRINT_CALL_CHAIN` prints the call chain stored in an object to `stderr`;\n * it requires we do not hold the allocator lock.\n */\n#if defined(SAVE_CALL_CHAIN)\n#  define ADD_CALL_CHAIN(base, ra) GC_save_callers(((oh *)(base))->oh_ci)\n#  if defined(REDIRECT_MALLOC) && defined(THREADS) && defined(DBG_HDRS_ALL) \\\n      && NARGS == 0 && NFRAMES % 2 == 0 && defined(GC_HAVE_BUILTIN_BACKTRACE)\n/*\n * A dummy variant of `GC_save_callers()` which does not call\n * `backtrace()`.\n */\nGC_INNER void GC_save_callers_no_unlock(struct callinfo info[NFRAMES]);\n\n#    define ADD_CALL_CHAIN_INNER(base) \\\n      GC_save_callers_no_unlock(((oh *)(base))->oh_ci)\n#  endif\n#  define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base))->oh_ci)\n#elif defined(GC_ADD_CALLER)\n#  define ADD_CALL_CHAIN(base, ra) ((oh *)(base))->oh_ci[0].ci_pc = (ra)\n#  define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base))->oh_ci)\n#else\n#  define ADD_CALL_CHAIN(base, ra)\n#  define PRINT_CALL_CHAIN(base)\n#endif\n\n#if !defined(ADD_CALL_CHAIN_INNER) && defined(DBG_HDRS_ALL)\n/* A variant of `ADD_CALL_CHAIN()` used for internal allocations. */\n#  define ADD_CALL_CHAIN_INNER(base) ADD_CALL_CHAIN(base, GC_RETURN_ADDR)\n#endif\n\n#ifdef GC_ADD_CALLER\n#  define OPT_RA ra,\n#else\n#  define OPT_RA\n#endif\n\n/*\n * Check whether object given by its base pointer has debugging info.\n * The argument (`base`) is assumed to point to a legitimate object in the\n * collector heap.  This excludes the check as to whether the back pointer\n * is odd, which is added by the `GC_HAS_DEBUG_INFO` macro.  Note that\n * if `DBG_HDRS_ALL` is defined, uncollectible objects on free lists\n * may not have debug information set.  Thus, it is not always safe to\n * return 1 (true), even if the client does its part.  Return -1 if the\n * object with debug info has been marked as deallocated.\n */\n#ifdef SHORT_DBG_HDRS\n#  define GC_has_other_debug_info(base) 1\n#else\nGC_INNER int GC_has_other_debug_info(ptr_t base);\n\nGC_INNER void GC_add_smashed(ptr_t smashed);\n\n/*\n * Use `GC_err_printf()` and friends to print a description of the object\n * whose client-visible address is `p`, and which was smashed at memory\n * location pointed by `clobbered`.\n */\nGC_INNER void GC_print_smashed_obj(const char *msg, void *p, ptr_t clobbered);\n\n/* Print all objects on the list.  Clear the list. */\nGC_INNER void GC_print_all_smashed_proc(void);\n#endif /* !SHORT_DBG_HDRS */\n\n#if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)\n#  if defined(SHORT_DBG_HDRS) && !defined(CPPCHECK)\n#    error Non-ptr stored in object results in GC_HAS_DEBUG_INFO malfunction\n/* We may mistakenly conclude that base has a debugging wrapper. */\n#  endif\n#  if defined(PARALLEL_MARK) && defined(KEEP_BACK_PTRS)\n/*\n * Note: the atomic load is used as `GC_store_back_pointer` stores\n * `oh_back_ptr` atomically (`base` might point to the field); this prevents\n * a TSan warning.\n */\n#    define GC_HAS_DEBUG_INFO(base)                                    \\\n      (((GC_uintptr_t)GC_cptr_load((volatile ptr_t *)(base)) & 1) != 0 \\\n       && GC_has_other_debug_info(base) > 0)\n#  else\n#    define GC_HAS_DEBUG_INFO(base)         \\\n      (((*(GC_uintptr_t *)(base)) & 1) != 0 \\\n       && GC_has_other_debug_info(base) > 0)\n#  endif\n#else\n#  define GC_HAS_DEBUG_INFO(base) (GC_has_other_debug_info(base) > 0)\n#endif /* !KEEP_BACK_PTRS && !MAKE_BACK_GRAPH */\n\nEXTERN_C_END\n\n#endif /* GC_DBG_MLC_H */\n\n\n/*\n * This implements a full, though not well-tuned, representation of the\n * backwards points-to graph.  This is used to test for non-GC-robust\n * data structures; the code is not used during normal garbage collection.\n *\n * One restriction is that we drop all back-edges from nodes with very\n * high in-degree, and simply add them to a list of such nodes.  They are\n * then treated as permanent roots.  If this by itself does not introduce\n * a space leak, then such nodes cannot contribute to a growing space leak.\n */\n\n#ifdef MAKE_BACK_GRAPH\n\n#  if (!defined(DBG_HDRS_ALL)                                          \\\n       || (ALIGNMENT != CPP_PTRSZ / 8) /* `|| !defined(UNIX_LIKE)` */) \\\n      && !defined(CPPCHECK)\n#    error The configuration does not support MAKE_BACK_GRAPH\n#  endif\n\n/*\n * We store single back pointers directly in the object's `oh_bg_ptr` field.\n * If there is more than one pointer to an object, we store `q` or'ed with\n * `FLAG_MANY`, where `q` is a pointer to a `back_edges` object.\n * Every once in a while we use a `back_edges` object even for a single\n * pointer, since we need the other fields in the `back_edges` structure to\n * be present in some fraction of the objects.  Otherwise we get serious\n * performance issues.\n */\n#  define FLAG_MANY 2\n\n/* Directly points to a reachable object; retain for the next collection. */\n#  define RETAIN 1\n\n/* Special values of `height` field of `back_edges`. */\n#  define HEIGHT_UNKNOWN (-2)\n#  define HEIGHT_IN_PROGRESS (-1)\n\ntypedef struct back_edges_s back_edges;\n\n#  define MAX_BACK_EDGE_STRUCTS 100000\n\n/*\n * Allocate a new back edge structure.  Should be more sophisticated\n * if this were production code.\n */\nstatic back_edges *\nnew_back_edges(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  if (NULL == GC_back_edge_space) {\n    size_t bytes_to_get;\n\n    GC_ASSERT(0 == GC_n_back_edge_structs);\n    GC_ASSERT(NULL == GC_avail_back_edges);\n    GC_ASSERT(GC_page_size != 0);\n    bytes_to_get\n        = ROUNDUP_PAGESIZE_IF_MMAP(MAX_BACK_EDGE_STRUCTS * sizeof(back_edges));\n\n    GC_back_edge_space = (back_edges *)GC_os_get_mem(bytes_to_get);\n    if (NULL == GC_back_edge_space)\n      ABORT(\"Insufficient memory for back edges\");\n  }\n  if (GC_avail_back_edges != NULL) {\n    back_edges *result = GC_avail_back_edges;\n    GC_avail_back_edges = result->cont;\n    result->cont = NULL;\n    return result;\n  }\n  if (GC_n_back_edge_structs >= MAX_BACK_EDGE_STRUCTS - 1) {\n    ABORT(\"Needed too much space for back edges: adjust \"\n          \"MAX_BACK_EDGE_STRUCTS\");\n  }\n  return &GC_back_edge_space[GC_n_back_edge_structs++];\n}\n\n/* Deallocate `p` and its associated continuation structures. */\nstatic void\ndeallocate_back_edges(back_edges *p)\n{\n  back_edges *last;\n\n  for (last = p; last->cont != NULL;)\n    last = last->cont;\n\n  last->cont = GC_avail_back_edges;\n  GC_avail_back_edges = p;\n}\n\n#  define INITIAL_IN_PROGRESS 10000\n\nstatic void\npush_in_progress(ptr_t p)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  if (GC_backgraph_n_in_progress >= GC_backgraph_in_progress_size) {\n    ptr_t *new_in_progress_space;\n\n    GC_ASSERT(GC_page_size != 0);\n    if (NULL == GC_backgraph_in_progress_space) {\n      GC_ASSERT(0 == GC_backgraph_n_in_progress);\n      GC_ASSERT(0 == GC_backgraph_in_progress_size);\n      GC_backgraph_in_progress_size\n          = ROUNDUP_PAGESIZE_IF_MMAP(INITIAL_IN_PROGRESS * sizeof(ptr_t))\n            / sizeof(ptr_t);\n      new_in_progress_space = (ptr_t *)GC_os_get_mem(\n          GC_backgraph_in_progress_size * sizeof(ptr_t));\n    } else {\n      GC_backgraph_in_progress_size *= 2;\n      new_in_progress_space = (ptr_t *)GC_os_get_mem(\n          GC_backgraph_in_progress_size * sizeof(ptr_t));\n      if (new_in_progress_space != NULL)\n        BCOPY(GC_backgraph_in_progress_space, new_in_progress_space,\n              GC_backgraph_n_in_progress * sizeof(ptr_t));\n    }\n#  ifndef GWW_VDB\n    GC_scratch_recycle_no_gww(GC_backgraph_in_progress_space,\n                              GC_backgraph_n_in_progress * sizeof(ptr_t));\n#  elif defined(LINT2)\n    /* TODO: Implement GWW-aware recycling as in `alloc_mark_stack`. */\n    GC_noop1_ptr(GC_backgraph_in_progress_space);\n#  endif\n    GC_backgraph_in_progress_space = new_in_progress_space;\n  }\n  if (NULL == GC_backgraph_in_progress_space)\n    ABORT(\"MAKE_BACK_GRAPH: Out of in-progress space: \"\n          \"Huge linear data structure?\");\n  GC_backgraph_in_progress_space[GC_backgraph_n_in_progress++] = p;\n}\n\nstatic GC_bool\nis_in_progress(const char *p)\n{\n  size_t i;\n  for (i = 0; i < GC_backgraph_n_in_progress; ++i) {\n    if (GC_backgraph_in_progress_space[i] == p)\n      return TRUE;\n  }\n  return FALSE;\n}\n\nGC_INLINE void\npop_in_progress(ptr_t p)\n{\n#  ifndef GC_ASSERTIONS\n  UNUSED_ARG(p);\n#  endif\n  --GC_backgraph_n_in_progress;\n  GC_ASSERT(GC_backgraph_in_progress_space[GC_backgraph_n_in_progress] == p);\n}\n\n#  define GET_OH_BG_PTR(p) (ptr_t) GC_REVEAL_POINTER(((oh *)(p))->oh_bg_ptr)\n#  define SET_OH_BG_PTR(p, q) (((oh *)(p))->oh_bg_ptr = GC_HIDE_POINTER(q))\n\n/* Ensure that `p` has a `back_edges` structure associated with it. */\nstatic void\nensure_struct(ptr_t p)\n{\n  ptr_t old_back_ptr = GET_OH_BG_PTR(p);\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if ((ADDR(old_back_ptr) & FLAG_MANY) == 0) {\n    back_edges *be = new_back_edges();\n\n    be->flags = 0;\n#  if defined(CPPCHECK)\n    GC_noop1_ptr(&old_back_ptr);\n    /* Workaround a false positive that `old_back_ptr` cannot be `NULL`. */\n#  endif\n    if (NULL == old_back_ptr) {\n      be->n_edges = 0;\n    } else {\n      be->n_edges = 1;\n      be->edges[0] = old_back_ptr;\n    }\n    be->height = HEIGHT_UNKNOWN;\n    be->height_gc_no = (unsigned short)(GC_gc_no - 1);\n    GC_ASSERT(ADDR_GE((ptr_t)be, (ptr_t)GC_back_edge_space));\n    SET_OH_BG_PTR(p, CPTR_SET_FLAGS(be, FLAG_MANY));\n  }\n}\n\n/*\n * Add the (forward) edge from `p` to `q` to the backward graph.  Both `p`\n * and `q` are pointers to the object base, i.e. pointers to an `oh`.\n */\nstatic void\nadd_edge(ptr_t p, ptr_t q)\n{\n  ptr_t pred = GET_OH_BG_PTR(q);\n  back_edges *be, *be_cont;\n  word i;\n\n  GC_ASSERT(p == GC_base(p) && q == GC_base(q));\n  GC_ASSERT(I_HOLD_LOCK());\n  if (!GC_HAS_DEBUG_INFO(q) || !GC_HAS_DEBUG_INFO(p)) {\n    /*\n     * This is really a misinterpreted free-list link, since we saw\n     * a pointer to a free list.  Do not overwrite it!\n     */\n    return;\n  }\n#  if defined(CPPCHECK)\n  GC_noop1_ptr(&pred);\n#  endif\n  if (NULL == pred) {\n    /*\n     * A not very random number we use to occasionally allocate\n     * a `back_edges` structure even for a single backward edge.\n     * This prevents us from repeatedly tracing back through very long\n     * chains, since we will have some place to store `height` and\n     * `HEIGHT_IN_PROGRESS` flag along the way.\n     */\n#  define GOT_LUCKY_NUMBER (((++random_number) & 0x7f) == 0)\n    static unsigned random_number = 13;\n\n    SET_OH_BG_PTR(q, p);\n    if (GOT_LUCKY_NUMBER)\n      ensure_struct(q);\n    return;\n  }\n\n  /* Check whether it was already in the list of predecessors. */\n  {\n    back_edges *e = (back_edges *)CPTR_CLEAR_FLAGS(pred, FLAG_MANY);\n    word n_edges;\n    word total;\n    int local = 0;\n\n    if ((ADDR(pred) & FLAG_MANY) != 0) {\n      n_edges = e->n_edges;\n    } else if ((COVERT_DATAFLOW(ADDR(pred)) & 1) == 0) {\n      /* A misinterpreted free-list link. */\n      n_edges = 1;\n      local = -1;\n    } else {\n      n_edges = 0;\n    }\n    for (total = 0; total < n_edges; ++total) {\n      if (local == BACKGRAPH_MAX_IN) {\n        e = e->cont;\n        local = 0;\n      }\n      if (local >= 0)\n        pred = e->edges[local++];\n      if (pred == p)\n        return;\n    }\n  }\n\n  ensure_struct(q);\n  be = (back_edges *)CPTR_CLEAR_FLAGS(GET_OH_BG_PTR(q), FLAG_MANY);\n  for (i = be->n_edges, be_cont = be; i > BACKGRAPH_MAX_IN;\n       i -= BACKGRAPH_MAX_IN)\n    be_cont = be_cont->cont;\n  if (i == BACKGRAPH_MAX_IN) {\n    be_cont->cont = new_back_edges();\n    be_cont = be_cont->cont;\n    i = 0;\n  }\n  be_cont->edges[i] = p;\n  be->n_edges++;\n#  ifdef DEBUG_PRINT_BIG_N_EDGES\n  if (GC_print_stats == VERBOSE && be->n_edges == 100) {\n    GC_err_printf(\"The following object has big in-degree:\\n\");\n#    ifdef THREADS\n    /*\n     * Note: we cannot call the debug variant of `GC_print_heap_obj` here\n     * because the allocator lock is held.\n     */\n    GC_default_print_heap_obj_proc(q);\n#    else\n    GC_print_heap_obj(q);\n#    endif\n  }\n#  endif\n}\n\ntypedef void (*per_object_func)(ptr_t p, size_t sz, word descr);\n\nstatic GC_CALLBACK void\nper_object_helper(struct hblk *h, void *fn_ptr)\n{\n  const hdr *hhdr = HDR(h);\n  word descr = hhdr->hb_descr;\n  per_object_func fn = *(per_object_func *)fn_ptr;\n  size_t sz = hhdr->hb_sz;\n  size_t i = 0;\n\n  do {\n    fn((ptr_t)(h->hb_body + i), sz, descr);\n    i += sz;\n  } while (i + sz <= HBLKSIZE);\n}\n\nGC_INLINE void\nGC_apply_to_each_object(per_object_func fn)\n{\n  GC_apply_to_all_blocks(per_object_helper, &fn);\n}\n\nstatic void\nreset_back_edge(ptr_t p, size_t sz, word descr)\n{\n  UNUSED_ARG(sz);\n  UNUSED_ARG(descr);\n  GC_ASSERT(I_HOLD_LOCK());\n  /* Skip any free-list links, or dropped blocks. */\n  if (GC_HAS_DEBUG_INFO(p)) {\n    ptr_t old_back_ptr = GET_OH_BG_PTR(p);\n\n    if ((ADDR(old_back_ptr) & FLAG_MANY) != 0) {\n      back_edges *be = (back_edges *)CPTR_CLEAR_FLAGS(old_back_ptr, FLAG_MANY);\n\n      if (!(be->flags & RETAIN)) {\n        deallocate_back_edges(be);\n        SET_OH_BG_PTR(p, NULL);\n      } else {\n        GC_ASSERT(GC_is_marked(p));\n\n        /*\n         * Back edges may point to objects that will not be retained.\n         * Delete them for now, but remember the height.  Some will be\n         * added back at next collection.\n         */\n        be->n_edges = 0;\n        if (be->cont != NULL) {\n          deallocate_back_edges(be->cont);\n          be->cont = NULL;\n        }\n\n        GC_ASSERT(GC_is_marked(p));\n        /* We only retain things for one collection cycle at a time. */\n        be->flags &= (unsigned short)~RETAIN;\n      }\n    } else /* simple back pointer */ {\n      /* Clear to avoid dangling pointer. */\n      SET_OH_BG_PTR(p, NULL);\n    }\n  }\n}\n\nstatic void\nadd_back_edges(ptr_t p, size_t sz, word descr)\n{\n  ptr_t current_p = p + sizeof(oh);\n\n  /* For now, fix up non-length descriptors conservatively. */\n  if ((descr & GC_DS_TAGS) != GC_DS_LENGTH) {\n    descr = sz;\n  }\n\n  for (; ADDR_LT(current_p, p + descr); current_p += sizeof(ptr_t)) {\n    ptr_t q;\n\n    LOAD_PTR_OR_CONTINUE(q, current_p);\n    FIXUP_POINTER(q);\n    if (GC_least_real_heap_addr < ADDR(q)\n        && ADDR(q) < GC_greatest_real_heap_addr) {\n      ptr_t target = (ptr_t)GC_base(q);\n\n      if (target != NULL)\n        add_edge(p, target);\n    }\n  }\n}\n\nGC_INNER void\nGC_build_back_graph(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_apply_to_each_object(add_back_edges);\n}\n\n/*\n * Return an approximation to the length of the longest simple path through\n * unreachable objects to `p`.  We refer to this as the height of `p`.\n */\nstatic word\nbackwards_height(ptr_t p)\n{\n  word result;\n  ptr_t pred = GET_OH_BG_PTR(p);\n  back_edges *be;\n\n  GC_ASSERT(I_HOLD_LOCK());\n#  if defined(CPPCHECK)\n  GC_noop1_ptr(&pred);\n#  endif\n  if (NULL == pred)\n    return 1;\n  if ((ADDR(pred) & FLAG_MANY) == 0) {\n    if (is_in_progress(p)) {\n      /*\n       * DFS (depth-first search) back edge, i.e. we followed an edge to\n       * an object already on our stack.  Ignore.\n       */\n      return 0;\n    }\n    push_in_progress(p);\n    result = backwards_height(pred) + 1;\n    pop_in_progress(p);\n    return result;\n  }\n  be = (back_edges *)CPTR_CLEAR_FLAGS(pred, FLAG_MANY);\n  if (be->height >= 0 && be->height_gc_no == (unsigned short)GC_gc_no)\n    return (word)be->height;\n  /* Ignore back edges in DFS. */\n  if (be->height == HEIGHT_IN_PROGRESS)\n    return 0;\n\n  result = be->height > 0 ? (word)be->height : 1U;\n  be->height = HEIGHT_IN_PROGRESS;\n\n  {\n    back_edges *e = be;\n    word n_edges;\n    word total;\n    int local = 0;\n\n    if ((ADDR(pred) & FLAG_MANY) != 0) {\n      n_edges = e->n_edges;\n    } else if ((ADDR(pred) & 1) == 0) {\n      /* A misinterpreted free-list link. */\n      n_edges = 1;\n      local = -1;\n    } else {\n      n_edges = 0;\n    }\n    for (total = 0; total < n_edges; ++total) {\n      word this_height;\n      if (local == BACKGRAPH_MAX_IN) {\n        e = e->cont;\n        local = 0;\n      }\n      if (local >= 0)\n        pred = e->edges[local++];\n\n      /*\n       * Execute the following once for each predecessor `pred` of `p`\n       * in the points-to graph.\n       */\n      if (GC_is_marked(pred) && (ADDR(GET_OH_BG_PTR(p)) & FLAG_MANY) == 0) {\n        GC_COND_LOG_PRINTF(\"Found bogus pointer from %p to %p\\n\", (void *)pred,\n                           (void *)p);\n        /*\n         * Reachable object \"points to\" unreachable one.  Could be caused\n         * by our lax treatment of the collector descriptors.\n         */\n        this_height = 1;\n      } else {\n        this_height = backwards_height(pred);\n      }\n      if (this_height >= result)\n        result = this_height + 1;\n    }\n  }\n\n  be->height = (GC_signed_word)result;\n  be->height_gc_no = (unsigned short)GC_gc_no;\n  return result;\n}\n\n/*\n * Compute the maximum height of every unreachable predecessor `p` of\n * a reachable object.  Arrange to save the heights of all such objects `p`\n * so that they can be used in calculating the height of objects in the next\n * collection.  Set `GC_backgraph_deepest_height` to be the maximum height we\n * encounter, and `GC_backgraph_deepest_obj` to be the corresponding object.\n */\nstatic void\nupdate_deepest_height(ptr_t p, size_t sz, word descr)\n{\n  UNUSED_ARG(sz);\n  UNUSED_ARG(descr);\n  GC_ASSERT(I_HOLD_LOCK());\n  if (GC_is_marked(p) && GC_HAS_DEBUG_INFO(p)) {\n    word p_height = 0;\n    ptr_t p_deepest_obj = NULL;\n    ptr_t back_ptr;\n    back_edges *be = NULL;\n\n    /*\n     * If we remembered a height last time, use it as a minimum.\n     * It may have increased due to newly unreachable chains pointing\n     * to `p`, but it cannot have decreased.\n     */\n    back_ptr = GET_OH_BG_PTR(p);\n#  if defined(CPPCHECK)\n    GC_noop1_ptr(&back_ptr);\n#  endif\n    if (back_ptr != NULL && (ADDR(back_ptr) & FLAG_MANY) != 0) {\n      be = (back_edges *)CPTR_CLEAR_FLAGS(back_ptr, FLAG_MANY);\n      if (be->height != HEIGHT_UNKNOWN)\n        p_height = (word)be->height;\n    }\n\n    {\n      ptr_t pred = back_ptr;\n      back_edges *e = (back_edges *)CPTR_CLEAR_FLAGS(pred, FLAG_MANY);\n      word n_edges;\n      word total;\n      int local = 0;\n\n      if ((ADDR(pred) & FLAG_MANY) != 0) {\n        n_edges = e->n_edges;\n      } else if (pred != NULL && (ADDR(pred) & 1) == 0) {\n        /* A misinterpreted free-list link. */\n        n_edges = 1;\n        local = -1;\n      } else {\n        n_edges = 0;\n      }\n      for (total = 0; total < n_edges; ++total) {\n        if (local == BACKGRAPH_MAX_IN) {\n          e = e->cont;\n          local = 0;\n        }\n        if (local >= 0)\n          pred = e->edges[local++];\n\n        /*\n         * Execute the following once for each predecessor `pred` of `p`\n         * in the points-to graph.\n         */\n        if (!GC_is_marked(pred) && GC_HAS_DEBUG_INFO(pred)) {\n          word this_height = backwards_height(pred);\n\n          if (this_height > p_height) {\n            p_height = this_height;\n            p_deepest_obj = pred;\n          }\n        }\n      }\n    }\n\n    if (p_height > 0) {\n      /* Remember the height for next time. */\n      if (NULL == be) {\n        ensure_struct(p);\n        back_ptr = GET_OH_BG_PTR(p);\n        be = (back_edges *)CPTR_CLEAR_FLAGS(back_ptr, FLAG_MANY);\n      }\n      be->flags |= RETAIN;\n      be->height = (GC_signed_word)p_height;\n      be->height_gc_no = (unsigned short)GC_gc_no;\n    }\n    if (p_height > GC_backgraph_deepest_height) {\n      GC_backgraph_deepest_height = p_height;\n      GC_backgraph_deepest_obj = p_deepest_obj;\n    }\n  }\n}\n\nGC_INNER void\nGC_traverse_back_graph(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_backgraph_deepest_height = 0;\n  GC_apply_to_each_object(update_deepest_height);\n  if (GC_backgraph_deepest_obj != NULL) {\n    /* Keep the pointer until we can print it. */\n    GC_set_mark_bit(GC_backgraph_deepest_obj);\n  }\n}\n\nvoid\nGC_print_back_graph_stats(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_printf(\"Maximum backwards height of reachable objects\"\n            \" at GC #%lu is %lu\\n\",\n            (unsigned long)GC_gc_no,\n            (unsigned long)GC_backgraph_deepest_height);\n  if (GC_backgraph_deepest_height > GC_backgraph_max_deepest_h) {\n    ptr_t obj = GC_backgraph_deepest_obj;\n\n    GC_backgraph_max_deepest_h = GC_backgraph_deepest_height;\n    UNLOCK();\n    GC_err_printf(\n        \"The following unreachable object is last in a longest chain \"\n        \"of unreachable objects:\\n\");\n    GC_print_heap_obj(obj);\n    LOCK();\n  }\n  GC_COND_LOG_PRINTF(\"Needed max total of %d back-edge structs\\n\",\n                     GC_n_back_edge_structs);\n  GC_apply_to_each_object(reset_back_edge);\n  GC_backgraph_deepest_obj = NULL;\n}\n\n#endif /* MAKE_BACK_GRAPH */\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#ifndef NO_BLACK_LISTING\n\n/*\n * We maintain several hash tables of `hblk` entities that have had false\n * hits.  Each contains one bit per hash bucket.  If any page in the bucket\n * has had a false hit, we assume that all of them have.\n * See the definition of `page_hash_table` in `gc_priv.h` file.\n * False hits from the stack(s) are much more dangerous than false hits\n * from elsewhere, since the former can pin a large object that spans the\n * block, even though it does not start on the dangerous block.\n */\n\n/*\n * Externally callable routines are:\n *   - `GC_add_to_black_list_normal`,\n *   - `GC_add_to_black_list_stack`,\n *   - `GC_promote_black_lists`.\n */\n\nGC_INNER word GC_black_list_spacing = 0;\n\nSTATIC void\nGC_clear_bl(word *bl)\n{\n  BZERO(bl, sizeof(page_hash_table));\n}\n\nSTATIC void\nGC_copy_bl(const word *old, word *dest)\n{\n  BCOPY(old, dest, sizeof(page_hash_table));\n}\n\n#  ifdef PRINT_BLACK_LIST\nSTATIC void\nGC_print_blacklisted_ptr(ptr_t p, ptr_t source, const char *kind_str)\n{\n  ptr_t base = (ptr_t)GC_base(source);\n\n  if (0 == base) {\n    GC_err_printf(\"Black listing (%s) %p referenced from %p in %s\\n\", kind_str,\n                  (void *)p, (void *)source,\n                  NULL != source ? \"root set\" : \"register\");\n  } else {\n    /*\n     * FIXME: We cannot call the debug variant of `GC_print_heap_obj`\n     * (with `PRINT_CALL_CHAIN`) here because the allocator lock is held\n     * and the world is stopped.\n     */\n    GC_err_printf(\"Black listing (%s) %p referenced from %p in\"\n                  \" object at %p of appr. %lu bytes\\n\",\n                  kind_str, (void *)p, (void *)source, (void *)base,\n                  (unsigned long)GC_size(base));\n  }\n}\n#  endif /* PRINT_BLACK_LIST */\n\nGC_INNER void\nGC_bl_init_no_interiors(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  if (NULL == GC_incomplete_normal_bl) {\n    GC_old_normal_bl = (word *)GC_scratch_alloc(sizeof(page_hash_table));\n    GC_incomplete_normal_bl\n        = (word *)GC_scratch_alloc(sizeof(page_hash_table));\n    if (NULL == GC_old_normal_bl || NULL == GC_incomplete_normal_bl) {\n      GC_err_printf(\"Insufficient memory for black list\\n\");\n      EXIT();\n    }\n    GC_clear_bl(GC_old_normal_bl);\n    GC_clear_bl(GC_incomplete_normal_bl);\n  }\n}\n\nGC_INNER void\nGC_bl_init(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_black_list_spacing = MINHINCR * HBLKSIZE; /*< initial guess */\n  if (!GC_all_interior_pointers) {\n    GC_bl_init_no_interiors();\n  }\n  GC_ASSERT(NULL == GC_old_stack_bl && NULL == GC_incomplete_stack_bl);\n  GC_old_stack_bl = (word *)GC_scratch_alloc(sizeof(page_hash_table));\n  GC_incomplete_stack_bl = (word *)GC_scratch_alloc(sizeof(page_hash_table));\n  if (NULL == GC_old_stack_bl || NULL == GC_incomplete_stack_bl) {\n    GC_err_printf(\"Insufficient memory for black list\\n\");\n    EXIT();\n  }\n  GC_clear_bl(GC_old_stack_bl);\n  GC_clear_bl(GC_incomplete_stack_bl);\n}\n\nstatic word compute_total_stack_black_listed(void);\n\nGC_INNER void\nGC_promote_black_lists(void)\n{\n  word *very_old_normal_bl = GC_old_normal_bl;\n  word *very_old_stack_bl = GC_old_stack_bl;\n  word total_stack_black_listed; /*< number of bytes on stack blacklist */\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_old_normal_bl = GC_incomplete_normal_bl;\n  GC_old_stack_bl = GC_incomplete_stack_bl;\n  if (!GC_all_interior_pointers) {\n    GC_clear_bl(very_old_normal_bl);\n  }\n  GC_clear_bl(very_old_stack_bl);\n  GC_incomplete_normal_bl = very_old_normal_bl;\n  GC_incomplete_stack_bl = very_old_stack_bl;\n  total_stack_black_listed = compute_total_stack_black_listed();\n  GC_VERBOSE_LOG_PRINTF(\n      \"%lu bytes in heap blacklisted for interior pointers\\n\",\n      (unsigned long)total_stack_black_listed);\n  if (total_stack_black_listed != 0)\n    GC_black_list_spacing\n        = HBLKSIZE * (GC_heapsize / total_stack_black_listed);\n  if (GC_black_list_spacing < 3 * HBLKSIZE)\n    GC_black_list_spacing = 3 * HBLKSIZE;\n  if (GC_black_list_spacing > MAXHINCR * HBLKSIZE) {\n    /*\n     * Make it easier to allocate really huge blocks, which otherwise may\n     * have problems with nonuniform blacklist distributions.\n     * This way we should always succeed immediately after growing the heap.\n     */\n    GC_black_list_spacing = MAXHINCR * HBLKSIZE;\n  }\n}\n\nGC_INNER void\nGC_unpromote_black_lists(void)\n{\n  if (!GC_all_interior_pointers) {\n    GC_copy_bl(GC_old_normal_bl, GC_incomplete_normal_bl);\n  }\n  GC_copy_bl(GC_old_stack_bl, GC_incomplete_stack_bl);\n}\n\n#  if defined(PARALLEL_MARK) && defined(THREAD_SANITIZER)\n#    define backlist_set_pht_entry_from_index(db, index) \\\n      set_pht_entry_from_index_concurrent(db, index)\n#  else\n/*\n * It is safe to set a bit in a blacklist even without synchronization,\n * the only drawback is that we might have to redo black-listing sometimes.\n */\n#    define backlist_set_pht_entry_from_index(bl, index) \\\n      set_pht_entry_from_index(bl, index)\n#  endif\n\n#  ifdef PRINT_BLACK_LIST\nGC_INNER void\nGC_add_to_black_list_normal(ptr_t p, ptr_t source)\n#  else\nGC_INNER void\nGC_add_to_black_list_normal(ptr_t p)\n#  endif\n{\n#  ifndef PARALLEL_MARK\n  GC_ASSERT(I_HOLD_LOCK());\n#  endif\n  if (GC_modws_valid_offsets[ADDR(p) & (sizeof(ptr_t) - 1)]) {\n    size_t index = PHT_HASH(p);\n\n    if (NULL == HDR(p) || get_pht_entry_from_index(GC_old_normal_bl, index)) {\n#  ifdef PRINT_BLACK_LIST\n      if (!get_pht_entry_from_index(GC_incomplete_normal_bl, index)) {\n        GC_print_blacklisted_ptr(p, source, \"normal\");\n      }\n#  endif\n      backlist_set_pht_entry_from_index(GC_incomplete_normal_bl, index);\n    } else {\n      /*\n       * This is probably just an interior pointer to an allocated object,\n       * and is not worth black listing.\n       */\n    }\n  }\n}\n\n#  ifdef PRINT_BLACK_LIST\nGC_INNER void\nGC_add_to_black_list_stack(ptr_t p, ptr_t source)\n#  else\nGC_INNER void\nGC_add_to_black_list_stack(ptr_t p)\n#  endif\n{\n  size_t index = PHT_HASH(p);\n\n#  ifndef PARALLEL_MARK\n  GC_ASSERT(I_HOLD_LOCK());\n#  endif\n  if (NULL == HDR(p) || get_pht_entry_from_index(GC_old_stack_bl, index)) {\n#  ifdef PRINT_BLACK_LIST\n    if (!get_pht_entry_from_index(GC_incomplete_stack_bl, index)) {\n      GC_print_blacklisted_ptr(p, source, \"stack\");\n    }\n#  endif\n    backlist_set_pht_entry_from_index(GC_incomplete_stack_bl, index);\n  }\n}\n\n#endif /* !NO_BLACK_LISTING */\n\nGC_API struct GC_hblk_s *GC_CALL\nGC_is_black_listed(struct GC_hblk_s *h, size_t len)\n{\n#ifdef NO_BLACK_LISTING\n  UNUSED_ARG(h);\n  UNUSED_ARG(len);\n#else\n  size_t index = PHT_HASH(h);\n  size_t i, nblocks;\n\n  if (!GC_all_interior_pointers\n      && (get_pht_entry_from_index(GC_old_normal_bl, index)\n          || get_pht_entry_from_index(GC_incomplete_normal_bl, index))) {\n    return h + 1;\n  }\n\n  nblocks = divHBLKSZ(len);\n  for (i = 0;;) {\n    if (GC_old_stack_bl[divWORDSZ(index)] == 0\n        && GC_incomplete_stack_bl[divWORDSZ(index)] == 0) {\n      /* An easy case. */\n      i += CPP_WORDSZ - modWORDSZ(index);\n    } else {\n      if (get_pht_entry_from_index(GC_old_stack_bl, index)\n          || get_pht_entry_from_index(GC_incomplete_stack_bl, index)) {\n        return &h[i + 1];\n      }\n      i++;\n    }\n    if (i >= nblocks)\n      break;\n    index = PHT_HASH(h + i);\n  }\n#endif\n  return NULL;\n}\n\n#ifndef NO_BLACK_LISTING\n/*\n * Return the number of black-listed blocks in a given range.  Used only\n * for statistical purposes.  Looks only at the `GC_incomplete_stack_bl`.\n */\nSTATIC word\nGC_number_stack_black_listed(struct hblk *start, struct hblk *endp1)\n{\n  struct hblk *h;\n  word result = 0;\n\n  for (h = start; ADDR_LT((ptr_t)h, (ptr_t)endp1); h++) {\n    size_t index = PHT_HASH(h);\n\n    if (get_pht_entry_from_index(GC_old_stack_bl, index))\n      result++;\n  }\n  return result;\n}\n\n/* Return the total number of (stack) black-listed bytes. */\nstatic word\ncompute_total_stack_black_listed(void)\n{\n  size_t i;\n  word total = 0;\n\n  for (i = 0; i < GC_n_heap_sects; i++) {\n    struct hblk *start = (struct hblk *)GC_heap_sects[i].hs_start;\n    struct hblk *endp1 = start + divHBLKSZ(GC_heap_sects[i].hs_bytes);\n\n    total += GC_number_stack_black_listed(start, endp1);\n  }\n  return total * HBLKSIZE;\n}\n#endif /* !NO_BLACK_LISTING */\n\n/*\n * Copyright (c) 1992-1994 by Xerox Corporation.  All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#ifdef CHECKSUMS\n\n/*\n * This is debugging code intended to verify the results of dirty bit\n * computations.  Currently works only in a single-threaded environment.\n */\n\n#  define NSUMS 10000\n#  define OFFSET 0x10000\n\ntypedef struct {\n  GC_bool new_valid;\n  word old_sum;\n  word new_sum;\n\n  /*\n   * Block to which this refers plus `OFFSET` to hide it from the\n   * garbage collector.\n   */\n  struct hblk *block;\n} page_entry;\n\npage_entry GC_sums[NSUMS] = { { FALSE, 0, 0, NULL } };\n\n/* Record of pages on which we saw a write fault. */\nSTATIC word GC_faulted[NSUMS] = { 0 };\n\nSTATIC size_t GC_n_faulted = 0;\n\n#  ifndef GC_NO_DEINIT\nvoid\nGC_reset_check_page(void)\n{\n  BZERO(GC_sums, sizeof(GC_sums));\n  GC_n_faulted = 0;\n}\n#  endif\n\n#  ifdef MPROTECT_VDB\nvoid\nGC_record_fault(struct hblk *h)\n{\n  GC_ASSERT(GC_page_size != 0);\n  if (GC_n_faulted >= NSUMS)\n    ABORT(\"write fault log overflowed\");\n  GC_faulted[GC_n_faulted++] = ADDR(HBLK_PAGE_ALIGNED(h));\n}\n#  endif\n\nSTATIC GC_bool\nGC_was_faulted(struct hblk *h)\n{\n  size_t i;\n  word page = ADDR(HBLK_PAGE_ALIGNED(h));\n\n  for (i = 0; i < GC_n_faulted; ++i) {\n    if (GC_faulted[i] == page)\n      return TRUE;\n  }\n  return FALSE;\n}\n\nSTATIC word\nGC_checksum(struct hblk *h)\n{\n  word *p;\n  word *lim = (word *)(h + 1);\n  word result = 0;\n\n  for (p = (word *)h; ADDR_LT((ptr_t)p, (ptr_t)lim); p++) {\n    result += *p;\n  }\n  return result | SIGNB; /*< does not look like pointer */\n}\n\nint GC_n_dirty_errors = 0;\nint GC_n_faulted_dirty_errors = 0;\nunsigned long GC_n_clean = 0;\nunsigned long GC_n_dirty = 0;\n\nSTATIC void\nGC_update_check_page(struct hblk *h, int index)\n{\n  page_entry *pe = &GC_sums[index];\n  hdr *hhdr = HDR(h);\n\n  if (pe->block != 0 && pe->block != h + OFFSET)\n    ABORT(\"goofed\");\n  pe->old_sum = pe->new_sum;\n  pe->new_sum = GC_checksum(h);\n#  if !defined(MSWIN32) && !defined(MSWINCE)\n  if (pe->new_sum != SIGNB && !GC_page_was_ever_dirty(h)) {\n    GC_err_printf(\"GC_page_was_ever_dirty(%p) is wrong\\n\", (void *)h);\n  }\n#  endif\n  if (GC_page_was_dirty(h)) {\n    GC_n_dirty++;\n  } else {\n    GC_n_clean++;\n  }\n  if (hhdr != NULL) {\n    (void)GC_find_starting_hblk(h, &hhdr);\n    if (pe->new_valid\n#  ifdef SOFT_VDB\n        && !HBLK_IS_FREE(hhdr)\n#  endif\n        && !IS_PTRFREE(hhdr) && pe->old_sum != pe->new_sum) {\n      if (!GC_page_was_dirty(h) || !GC_page_was_ever_dirty(h)) {\n        GC_bool was_faulted = GC_was_faulted(h);\n\n        GC_n_dirty_errors++; /*< set breakpoint here */\n        if (was_faulted)\n          GC_n_faulted_dirty_errors++;\n      }\n    }\n  }\n  pe->new_valid = TRUE;\n  pe->block = h + OFFSET;\n}\n\n/* Should be called immediately after `GC_read_dirty`. */\nvoid\nGC_check_dirty(void)\n{\n  int index;\n  size_t i;\n\n  GC_n_dirty_errors = 0;\n  GC_n_faulted_dirty_errors = 0;\n  GC_n_clean = 0;\n  GC_n_dirty = 0;\n\n  index = 0;\n  for (i = 0; i < GC_n_heap_sects; i++) {\n    ptr_t start = GC_heap_sects[i].hs_start;\n    struct hblk *h;\n\n    for (h = (struct hblk *)start;\n         ADDR_LT((ptr_t)h, start + GC_heap_sects[i].hs_bytes); h++) {\n      GC_update_check_page(h, index);\n      index++;\n      if (index >= NSUMS) {\n        i = GC_n_heap_sects;\n        break;\n      }\n    }\n  }\n\n  GC_COND_LOG_PRINTF(\"Checked %lu clean and %lu dirty pages\\n\", GC_n_clean,\n                     GC_n_dirty);\n  if (GC_n_dirty_errors > 0) {\n    GC_err_printf(\"Found %d dirty bit errors (%d were faulted)\\n\",\n                  GC_n_dirty_errors, GC_n_faulted_dirty_errors);\n  }\n  if (GC_n_faulted > 0) {\n    /* Do not expose block addresses to the garbage collector. */\n    BZERO(GC_faulted, GC_n_faulted * sizeof(word));\n    GC_n_faulted = 0;\n  }\n}\n\n#endif /* CHECKSUMS */\n\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 2001 by Hewlett-Packard Company. All rights reserved.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * Private declarations of the collector marker data structures (like the\n * mark stack) and macros.  Needed by the marker and the client-supplied\n * mark routines.  Transitively includes `gc_priv.h` file.\n */\n\n#ifndef GC_PMARK_H\n#define GC_PMARK_H\n\n#if defined(HAVE_CONFIG_H) && !defined(GC_PRIVATE_H)\n/*\n * When `gc_pmark.h` file is included from `gc_priv.h` file, some of\n * macros might be undefined in `gcconfig.h` file, so skip `config.h`\n * file in this case.\n */\n#endif\n\n#ifndef GC_BUILD\n#  define GC_BUILD\n#endif\n\n#if (defined(__linux__) || defined(__GLIBC__) || defined(__GNU__)) \\\n    && !defined(_GNU_SOURCE) && defined(GC_PTHREADS)               \\\n    && !defined(GC_NO_PTHREAD_SIGMASK)\n#  define _GNU_SOURCE 1\n#endif\n\n#if defined(KEEP_BACK_PTRS) || defined(PRINT_BLACK_LIST)\n#endif\n\n\n\n\nEXTERN_C_BEGIN\n\n/*\n * The real declarations of the following is in `gc_priv.h` file, so\n * that we can avoid scanning `GC_mark_procs` table.\n */\n\n/*\n * Mark descriptor stuff that should remain private for now, mostly\n * because it is hard to export `CPP_WORDSZ` macro without include\n * `gcconfig.h` file.\n */\n#define BITMAP_BITS (CPP_WORDSZ - GC_DS_TAG_BITS)\n#define PROC(descr) \\\n  (GC_mark_procs[((descr) >> GC_DS_TAG_BITS) & (GC_MAX_MARK_PROCS - 1)])\n#define ENV(descr) ((descr) >> (GC_DS_TAG_BITS + GC_LOG_MAX_MARK_PROCS))\n#define MAX_ENV (((word)1 << (BITMAP_BITS - GC_LOG_MAX_MARK_PROCS)) - 1)\n\nGC_EXTERN unsigned GC_n_mark_procs;\n\n/* Number of mark stack entries to discard on overflow. */\n#define GC_MARK_STACK_DISCARDS (INITIAL_MARK_STACK_SIZE / 8)\n\n#ifdef PARALLEL_MARK\n/*\n * Allow multiple threads to participate in the marking process.\n * This works roughly as follows:\n *   - The main mark stack never shrinks, but it can grow.\n *   - The initiating threads holds the allocator lock, sets\n *     `GC_help_wanted`.\n *   - Other threads:\n *     1. Update `GC_helper_count` (while holding the mark lock).\n *     2. Allocate a local mark stack repeatedly:\n *        2.1. Steal a global mark stack entry by atomically replacing\n *             its descriptor with 0;\n *        2.2. Copy it to the local stack;\n *        2.3. Mark on the local stack until it is empty, or it may be\n *             profitable to copy it back;\n *        2.4. If necessary, copy local stack to global one, holding the\n *             mark lock;\n *        2.5. Stop when the global mark stack is empty.\n *     3. Decrement `GC_helper_count` (holding the mark lock).\n *\n * This is an experiment to see if we can do something along the lines\n * of the University of Tokyo SGC in a less intrusive, though probably\n * also less performant, way.\n */\n\n/* `GC_mark_stack_top` is protected by the mark lock. */\n\n/*\n * `GC_notify_all_marker()` is used when `GC_help_wanted` is first set,\n * when the last helper becomes inactive, when something is added to the\n * global mark stack, and just after `GC_mark_no` is incremented.\n * This could be split into multiple conditional variables (and probably\n * should be) to scale to really large numbers of processors.\n */\n#endif /* PARALLEL_MARK */\n\n/*\n * Push the object `obj` with corresponding heap block header `hhdr`\n * onto the mark stack.  Returns the updated `mark_stack_top` value.\n */\nGC_INLINE mse *\nGC_push_obj(ptr_t obj, const hdr *hhdr, mse *mark_stack_top,\n            mse *mark_stack_limit)\n{\n  GC_ASSERT(!HBLK_IS_FREE(hhdr));\n  if (!IS_PTRFREE(hhdr)) {\n    mark_stack_top = GC_custom_push_proc(hhdr->hb_descr, obj, mark_stack_top,\n                                         mark_stack_limit);\n  }\n  return mark_stack_top;\n}\n\n/*\n * Push the contents of `current` onto the mark stack if it is a valid\n * pointer to a currently unmarked object.  Mark it.\n */\n#define PUSH_CONTENTS(current, mark_stack_top, mark_stack_limit, source)   \\\n  do {                                                                     \\\n    hdr *my_hhdr;                                                          \\\n    HC_GET_HDR(current, my_hhdr, source); /*< contains `break` */          \\\n    mark_stack_top = GC_push_contents_hdr(                                 \\\n        current, mark_stack_top, mark_stack_limit, source, my_hhdr, TRUE); \\\n  } while (0)\n\n/* Set mark bit, exit (using `break` statement) if it is already set. */\n#ifdef USE_MARK_BYTES\n#  if defined(PARALLEL_MARK) && defined(AO_HAVE_char_store) \\\n      && !defined(BASE_ATOMIC_OPS_EMULATED)\n/*\n * There is a race here, and we may set the bit twice in the concurrent\n * case.  This can result in the object being pushed twice.  But that is\n * only a performance issue.\n */\n#    define SET_MARK_BIT_EXIT_IF_SET(hhdr, bit_no)                 \\\n      { /*< cannot use `do ... while (0)` here */                  \\\n        volatile unsigned char *mark_byte_addr                     \\\n            = (unsigned char *)(hhdr)->hb_marks + (bit_no);        \\\n        /* Unordered atomic load and store are sufficient here. */ \\\n        if (AO_char_load(mark_byte_addr) != 0)                     \\\n          break; /*< go to the enclosing loop end */               \\\n        AO_char_store(mark_byte_addr, 1);                          \\\n      }\n#  else\n#    define SET_MARK_BIT_EXIT_IF_SET(hhdr, bit_no)                 \\\n      { /*< cannot use `do ... while (0)` here */                  \\\n        ptr_t mark_byte_addr = (ptr_t)(hhdr)->hb_marks + (bit_no); \\\n                                                                   \\\n        if (*mark_byte_addr != 0)                                  \\\n          break; /*< go to the enclosing loop end */               \\\n        *mark_byte_addr = 1;                                       \\\n      }\n#  endif /* !PARALLEL_MARK */\n#else\n#  if defined(PARALLEL_MARK) || (defined(THREAD_SANITIZER) && defined(THREADS))\n#    ifdef THREAD_SANITIZER\n#      define MARK_WORD_READ(addr) AO_load(addr)\n#    else\n#      define MARK_WORD_READ(addr) (*(addr))\n#    endif\n/*\n * This is used only if we explicitly define `USE_MARK_BITS` macro.\n * The following may fail to exit even if the bit was already set.\n * For our uses, that is benign.\n */\n#    define SET_MARK_BIT_EXIT_IF_SET(hhdr, bit_no)                            \\\n      { /*< cannot use `do ... while (0)` here */                             \\\n        volatile AO_t *mark_word_addr = (hhdr)->hb_marks + divWORDSZ(bit_no); \\\n        word my_bits = (word)1 << modWORDSZ(bit_no);                          \\\n                                                                              \\\n        if ((MARK_WORD_READ(mark_word_addr) & my_bits) != 0)                  \\\n          break; /*< go to the enclosing loop end */                          \\\n        AO_or(mark_word_addr, my_bits);                                       \\\n      }\n#  else /* !PARALLEL_MARK */\n#    define SET_MARK_BIT_EXIT_IF_SET(hhdr, bit_no)                   \\\n      { /*< cannot use `do ... while (0)` here */                    \\\n        word *mark_word_addr = (hhdr)->hb_marks + divWORDSZ(bit_no); \\\n        word old = *mark_word_addr;                                  \\\n        word my_bits = (word)1 << modWORDSZ(bit_no);                 \\\n                                                                     \\\n        if ((old & my_bits) != 0)                                    \\\n          break; /*< go to the enclosing loop end */                 \\\n        *(mark_word_addr) = old | my_bits;                           \\\n      }\n#  endif\n#endif /* !USE_MARK_BYTES */\n\n#ifdef ENABLE_TRACE\n#  define TRACE(source, cmd)                                     \\\n    if (GC_trace_ptr != NULL && (ptr_t)(source) == GC_trace_ptr) \\\n    cmd\n#  define TRACE_TARGET(target, cmd)                          \\\n    if (GC_trace_ptr != NULL && GC_is_heap_ptr(GC_trace_ptr) \\\n        && (target) == *(ptr_t *)GC_trace_ptr)               \\\n    cmd\n#else\n#  define TRACE(source, cmd)\n#  define TRACE_TARGET(source, cmd)\n#endif\n\n/*\n * If the mark bit corresponding to `current` is not set, set it, and\n * push the contents of the object on the mark stack.  `current` points\n * to the beginning of the object.  We rely on the fact that the\n * preceding header calculation will succeed for a pointer past the\n * first page of an object, only if it is in fact a valid pointer\n * to the object.  Thus we can omit the otherwise necessary tests here.\n */\nGC_INLINE mse *\nGC_push_contents_hdr(ptr_t current, mse *mark_stack_top, mse *mark_stack_limit,\n                     ptr_t source, hdr *hhdr, GC_bool do_offset_check)\n{\n  do {\n    /*\n     * Displacement in the block, in bytes; always within range.\n     * Note, in particular, that this value is the displacement from the\n     * beginning of the heap block, which may itself be in the interior\n     * of a large object.  If `current` does not point to the first block,\n     * then we are in the all-interior-pointers mode, and it is safe to\n     * use any displacement value.\n     */\n    size_t displ = HBLKDISPL(current);\n    ptr_t base = current;\n#ifdef MARK_BIT_PER_OBJ\n    unsigned32 gran_displ; /*< `high_prod` */\n    unsigned32 inv_sz = hhdr->hb_inv_sz;\n\n#else\n    size_t gran_displ = BYTES_TO_GRANULES(displ);\n    size_t gran_offset = hhdr->hb_map[gran_displ];\n    size_t byte_offset = displ & (GC_GRANULE_BYTES - 1);\n\n    /* The following always fails for large block references. */\n    if (UNLIKELY((gran_offset | byte_offset) != 0))\n#endif\n    {\n#ifdef MARK_BIT_PER_OBJ\n      if (UNLIKELY(inv_sz == LARGE_INV_SZ))\n#else\n      if ((hhdr->hb_flags & LARGE_BLOCK) != 0)\n#endif\n      {\n        /* `gran_offset` is bogus. */\n        size_t obj_displ;\n\n        base = (ptr_t)hhdr->hb_block;\n        obj_displ = (size_t)(current - base);\n        if (obj_displ != displ) {\n          GC_ASSERT(obj_displ < hhdr->hb_sz);\n          /*\n           * Must be in the all-interior-pointers mode, non-first block\n           * already did validity check on cache miss.\n           */\n        } else if (do_offset_check && !GC_valid_offsets[obj_displ]) {\n          GC_ADD_TO_BLACK_LIST_NORMAL(current, source);\n          break;\n        }\n        GC_ASSERT(hhdr->hb_sz > HBLKSIZE\n                  || hhdr->hb_block == HBLKPTR(current));\n        GC_ASSERT(ADDR_GE(current, (ptr_t)hhdr->hb_block));\n        gran_displ = 0;\n      } else {\n#ifdef MARK_BIT_PER_OBJ\n        unsigned32 low_prod;\n\n        LONG_MULT(gran_displ, low_prod, (unsigned32)displ, inv_sz);\n        if ((low_prod >> 16) != 0)\n#endif\n        {\n          size_t obj_displ;\n\n#ifdef MARK_BIT_PER_OBJ\n          /* Accurate enough if `HBLKSIZE` is not greater than 2**15. */\n          GC_STATIC_ASSERT(HBLKSIZE <= (1 << 15));\n          obj_displ = (((low_prod >> 16) + 1) * hhdr->hb_sz) >> 16;\n#else\n          obj_displ = GRANULES_TO_BYTES(gran_offset) + byte_offset;\n#endif\n\n          if (do_offset_check && !GC_valid_offsets[obj_displ]) {\n            GC_ADD_TO_BLACK_LIST_NORMAL(current, source);\n            break;\n          }\n#ifndef MARK_BIT_PER_OBJ\n          gran_displ -= gran_offset;\n#endif\n          base -= obj_displ;\n        }\n      }\n    }\n#ifdef MARK_BIT_PER_OBJ\n    /*\n     * May get here for pointer to start of block not at the beginning\n     * of object.  If so, it is valid, and we are fine.\n     */\n    GC_ASSERT(gran_displ <= HBLK_OBJS(hhdr->hb_sz));\n#else\n    GC_ASSERT(hhdr == GC_find_header(base));\n    GC_ASSERT(gran_displ % BYTES_TO_GRANULES(hhdr->hb_sz) == 0);\n#endif\n    TRACE(source, GC_log_printf(\"GC #%lu: passed validity tests\\n\",\n                                (unsigned long)GC_gc_no));\n    SET_MARK_BIT_EXIT_IF_SET(hhdr, gran_displ); /*< contains `break` */\n    TRACE(source, GC_log_printf(\"GC #%lu: previously unmarked\\n\",\n                                (unsigned long)GC_gc_no));\n    TRACE_TARGET(base, GC_log_printf(\"GC #%lu: marking %p from %p instead\\n\",\n                                     (unsigned long)GC_gc_no, (void *)base,\n                                     (void *)source));\n    INCR_MARKS(hhdr);\n    GC_STORE_BACK_PTR(source, base);\n    mark_stack_top = GC_push_obj(base, hhdr, mark_stack_top, mark_stack_limit);\n  } while (0);\n  return mark_stack_top;\n}\n\n#if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS)\n#  define PUSH_ONE_CHECKED_STACK(p, source) \\\n    GC_mark_and_push_stack(p, (ptr_t)(source))\n#else\n#  define PUSH_ONE_CHECKED_STACK(p, source) GC_mark_and_push_stack(p)\n#endif\n\n/*\n * Push a single value onto mark stack.  Mark from the object\n * pointed to by `p`.  The argument should be of `ptr_t` type.\n * Invoke `FIXUP_POINTER()` before any further processing.\n * p` is considered valid even if it is an interior pointer.\n * Previously marked objects are not pushed.  Hence we make progress\n * even if the mark stack overflows.\n */\n#ifdef NEED_FIXUP_POINTER\n/* Try both the raw variant and the fixed up one. */\n#  define GC_PUSH_ONE_STACK(p, source)                              \\\n    do {                                                            \\\n      ptr_t pp = (p);                                               \\\n                                                                    \\\n      if (ADDR_LT((ptr_t)GC_least_plausible_heap_addr, p)           \\\n          && ADDR_LT(p, (ptr_t)GC_greatest_plausible_heap_addr)) {  \\\n        PUSH_ONE_CHECKED_STACK(p, source);                          \\\n      }                                                             \\\n      FIXUP_POINTER(pp);                                            \\\n      if (ADDR_LT((ptr_t)GC_least_plausible_heap_addr, pp)          \\\n          && ADDR_LT(pp, (ptr_t)GC_greatest_plausible_heap_addr)) { \\\n        PUSH_ONE_CHECKED_STACK(pp, source);                         \\\n      }                                                             \\\n    } while (0)\n#else /* !NEED_FIXUP_POINTER */\n#  define GC_PUSH_ONE_STACK(p, source)                             \\\n    do {                                                           \\\n      if (ADDR_LT((ptr_t)GC_least_plausible_heap_addr, p)          \\\n          && ADDR_LT(p, (ptr_t)GC_greatest_plausible_heap_addr)) { \\\n        PUSH_ONE_CHECKED_STACK(p, source);                         \\\n      }                                                            \\\n    } while (0)\n#endif\n\n/*\n * Same as `GC_PUSH_ONE_STACK`, but the interior pointers recognition as\n * for normal heap pointers.\n */\n#define GC_PUSH_ONE_HEAP(p, source, mark_stack_top)                   \\\n  do {                                                                \\\n    FIXUP_POINTER(p);                                                 \\\n    if (ADDR_LT((ptr_t)GC_least_plausible_heap_addr, p)               \\\n        && ADDR_LT(p, (ptr_t)GC_greatest_plausible_heap_addr))        \\\n      mark_stack_top = GC_mark_and_push(                              \\\n          p, mark_stack_top, GC_mark_stack_limit, (void **)(source)); \\\n  } while (0)\n\n/*\n * Mark objects pointed to by the regions described by mark stack entries\n * between `mark_stack` and `mark_stack_top`, inclusive.  Assumes the upper\n * limit of a mark stack entry is never `NULL`.  A mark stack entry never\n * has zero size.  Return the new value of `mark_stack_top`.\n * We try to traverse on the order of a `hblk` of memory before we return.\n * Caller is responsible for calling this until the mark stack is empty.\n * Note that this is the most performance critical routine in the collector.\n * Hence it contains all sorts of ugly hacks to speed things up.\n * In particular, we avoid procedure calls on the common path, we take\n * advantage of peculiarities of the mark descriptor encoding, we optionally\n * maintain a cache for the block address to header mapping, we prefetch\n * when an object is \"grayed\", etc.\n */\nGC_INNER mse *GC_mark_from(mse *mark_stack_top, mse *mark_stack,\n                           mse *mark_stack_limit);\n\n#define MARK_FROM_MARK_STACK()                                       \\\n  GC_mark_stack_top = GC_mark_from(GC_mark_stack_top, GC_mark_stack, \\\n                                   GC_mark_stack + GC_mark_stack_size);\n\n#define GC_mark_stack_empty() \\\n  ADDR_LT((ptr_t)GC_mark_stack_top, (ptr_t)GC_mark_stack)\n\n/*\n * The current state of marking, as follows.  We say something is dirty\n * if it was written since the last time we retrieved dirty bits.\n * We say it is grungy if it was marked dirty in the last set of bits\n * we retrieved.  Invariant \"I\": all roots and marked objects `p` are\n * either dirty, or point to objects `q` that are either marked or\n * a pointer to `q` appears in a range on the mark stack.\n */\n\n/* No marking in progress.  \"I\" holds.  Mark stack is empty. */\n#define MS_NONE 0\n\n/*\n * Rescuing objects are currently being pushed.  \"I\" holds, except that\n * grungy roots may point to unmarked objects, as may marked grungy objects\n * above `GC_scan_ptr`.\n */\n#define MS_PUSH_RESCUERS 1\n\n/*\n * Uncollectible objects are currently being pushed.  \"I\" holds, except\n * that marked uncollectible objects above `GC_scan_ptr` may point to\n * unmarked objects.  Roots may point to unmarked objects too.\n */\n#define MS_PUSH_UNCOLLECTABLE 2\n\n/* \"I\" holds, mark stack may be nonempty. */\n#define MS_ROOTS_PUSHED 3\n\n/*\n * \"I\" may not hold, e.g. because of the mark stack overflow.  However,\n * marked heap objects below `GC_scan_ptr` point to marked or stacked\n * objects.\n */\n#define MS_PARTIALLY_INVALID 4\n\n/* \"I\" may not hold. */\n#define MS_INVALID 5\n\nEXTERN_C_END\n\n#endif /* GC_PMARK_H */\n\n\n#ifdef GC_GCJ_SUPPORT\n\n/*\n * This is an allocator interface tuned for `gcj` (the GNU static Java\n * compiler).\n *\n * Each allocated object has a pointer in its beginning to a \"vtable\",\n * which for our purposes is simply a structure describing the type of\n * the object.  This descriptor structure contains a GC marking\n * descriptor at offset `GC_GCJ_MARK_DESCR_OFFSET`.\n *\n * It is hoped that this interface may also be useful for other systems,\n * possibly with some tuning of the constants.  But the immediate goal\n * is to get better `gcj` performance.\n *\n * We assume: counting on explicit initialization of this interface is OK.\n */\n\n#  include \"gc/gc_gcj.h\"\n\n/* Object kind for objects with descriptors in \"vtable\". */\nint GC_gcj_kind = 0;\n\n/* The kind of objects that are always marked with a mark procedure call. */\nint GC_gcj_debug_kind = 0;\n\nSTATIC struct GC_ms_entry *GC_CALLBACK\nGC_gcj_fake_mark_proc(word *addr, struct GC_ms_entry *mark_stack_top,\n                      struct GC_ms_entry *mark_stack_limit, word env)\n{\n  UNUSED_ARG(addr);\n  UNUSED_ARG(mark_stack_limit);\n  UNUSED_ARG(env);\n#  if defined(FUNCPTR_IS_DATAPTR) && defined(CPPCHECK)\n  GC_noop1((word)(GC_funcptr_uint)(&GC_init_gcj_malloc));\n#  endif\n  ABORT_RET(\"No client gcj mark proc is specified\");\n  return mark_stack_top;\n}\n\n#  ifdef FUNCPTR_IS_DATAPTR\nGC_API void GC_CALL\nGC_init_gcj_malloc(int mp_index, void *mp)\n{\n  GC_init_gcj_malloc_mp((unsigned)mp_index,\n                        CAST_THRU_UINTPTR(GC_mark_proc, mp),\n                        GC_GCJ_MARK_DESCR_OFFSET);\n}\n#  endif /* FUNCPTR_IS_DATAPTR */\n\nGC_API void GC_CALL\nGC_init_gcj_malloc_mp(unsigned mp_index, GC_mark_proc mp, size_t descr_offset)\n{\n#  ifndef GC_IGNORE_GCJ_INFO\n  GC_bool ignore_gcj_info;\n#  endif\n\n  GC_STATIC_ASSERT(GC_GCJ_MARK_DESCR_OFFSET >= sizeof(ptr_t));\n  if (0 == mp) {\n    /* In case `GC_DS_PROC` is unused. */\n    mp = GC_gcj_fake_mark_proc;\n  }\n\n  /* Initialize the collector just in case it is not done yet. */\n  GC_init();\n  if (descr_offset != GC_GCJ_MARK_DESCR_OFFSET)\n    ABORT(\"GC_init_gcj_malloc_mp: bad offset\");\n\n  LOCK();\n  if (GC_gcjobjfreelist != NULL) {\n    /* Already initialized. */\n    UNLOCK();\n    return;\n  }\n#  ifdef GC_IGNORE_GCJ_INFO\n  /* This is useful for debugging on platforms with missing `getenv()`. */\n#    define ignore_gcj_info TRUE\n#  else\n  ignore_gcj_info = GETENV(\"GC_IGNORE_GCJ_INFO\") != NULL;\n#  endif\n  if (ignore_gcj_info) {\n    GC_COND_LOG_PRINTF(\"Gcj-style type information is disabled!\\n\");\n  }\n  GC_ASSERT(GC_mark_procs[mp_index] == (GC_mark_proc)0); /*< unused */\n  GC_mark_procs[mp_index] = mp;\n  if (mp_index >= GC_n_mark_procs)\n    ABORT(\"GC_init_gcj_malloc_mp: bad index\");\n  /* Set up object kind `gcj`-style indirect descriptor. */\n  GC_gcjobjfreelist = (ptr_t *)GC_new_free_list_inner();\n  if (ignore_gcj_info) {\n    /*\n     * Use a simple length-based descriptor, thus forcing a fully\n     * conservative scan.\n     */\n    GC_gcj_kind = (int)GC_new_kind_inner((void **)GC_gcjobjfreelist,\n                                         /* 0 | */ GC_DS_LENGTH, TRUE, TRUE);\n    GC_gcj_debug_kind = GC_gcj_kind;\n  } else {\n    GC_gcj_kind = (int)GC_new_kind_inner(\n        (void **)GC_gcjobjfreelist,\n        (((word)(-(GC_signed_word)GC_GCJ_MARK_DESCR_OFFSET\n                 - GC_INDIR_PER_OBJ_BIAS))\n         | GC_DS_PER_OBJECT),\n        FALSE, TRUE);\n    /* Set up object kind for objects that require mark procedure call. */\n    GC_gcj_debug_kind = (int)GC_new_kind_inner(\n        GC_new_free_list_inner(),\n        GC_MAKE_PROC(mp_index, 1 /* allocated with debug info */), FALSE,\n        TRUE);\n  }\n  UNLOCK();\n#  undef ignore_gcj_info\n}\n\n#  ifdef THREAD_LOCAL_ALLOC\nGC_INNER\n#  else\nSTATIC\n#  endif\nvoid *\nGC_core_gcj_malloc(size_t lb, const void *vtable_ptr, unsigned flags)\n{\n  ptr_t op;\n  size_t lg;\n\n  GC_DBG_COLLECT_AT_MALLOC(lb);\n  LOCK();\n  if (SMALL_OBJ(lb)\n      && (op = GC_gcjobjfreelist[lg = GC_size_map[lb]], LIKELY(op != NULL))) {\n    GC_gcjobjfreelist[lg] = (ptr_t)obj_link(op);\n    GC_bytes_allocd += GRANULES_TO_BYTES((word)lg);\n    GC_ASSERT(NULL == ((void **)op)[1]);\n  } else {\n    /*\n     * A mechanism to release the allocator lock and invoke finalizers.\n     * We do not really have an opportunity to do this on a rarely\n     * executed path on which the allocator lock is not held.  Thus we\n     * check at a rarely executed point at which it is safe to release\n     * the allocator lock; we do this even where we could just call\n     * `GC_notify_or_invoke_finalizers()`, since it is probably cheaper\n     * and certainly more uniform.\n     */\n    /* TODO: Consider doing the same elsewhere? */\n    if (GC_gc_no != GC_last_finalized_no) {\n      UNLOCK();\n      GC_notify_or_invoke_finalizers();\n      LOCK();\n      GC_last_finalized_no = GC_gc_no;\n    }\n\n    op = (ptr_t)GC_generic_malloc_inner(lb, GC_gcj_kind, flags);\n    if (NULL == op) {\n      GC_oom_func oom_fn = GC_oom_fn;\n      UNLOCK();\n      return (*oom_fn)(lb);\n    }\n  }\n  *(const void **)op = vtable_ptr;\n  UNLOCK();\n  GC_dirty(op);\n  REACHABLE_AFTER_DIRTY(vtable_ptr);\n  return GC_clear_stack(op);\n}\n\n#  ifndef THREAD_LOCAL_ALLOC\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_gcj_malloc(size_t lb, const void *vtable_ptr)\n{\n  return GC_core_gcj_malloc(lb, vtable_ptr, 0 /* `flags` */);\n}\n#  endif /* !THREAD_LOCAL_ALLOC */\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_gcj_malloc_ignore_off_page(size_t lb, const void *vtable_ptr)\n{\n  return GC_core_gcj_malloc(lb, vtable_ptr, IGNORE_OFF_PAGE);\n}\n\n#endif /* GC_GCJ_SUPPORT */\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#if defined(KEEP_BACK_PTRS) && defined(GC_ASSERTIONS)\n#endif\n\n/*\n * This implements:\n *   1. Allocation of heap block headers;\n *   2. A map from addresses to heap block addresses to heap block headers.\n *\n * Access speed is crucial.  We implement an index structure based on\n * a two-level tree.\n */\n\nGC_INNER hdr *\nGC_find_header(const void *h)\n{\n#ifdef HASH_TL\n  hdr *result;\n  GET_HDR(h, result);\n  return result;\n#else\n  return HDR_INNER(h);\n#endif\n}\n\nGC_INNER hdr *\n#ifdef PRINT_BLACK_LIST\nGC_header_cache_miss(ptr_t p, hdr_cache_entry *hce, ptr_t source)\n#else\nGC_header_cache_miss(ptr_t p, hdr_cache_entry *hce)\n#endif\n{\n  hdr *hhdr;\n\n  HC_MISS();\n  GET_HDR(p, hhdr);\n  if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {\n    if (GC_all_interior_pointers) {\n      if (hhdr != NULL) {\n        /* Pointer to near the start of the large object. */\n        ptr_t current = (ptr_t)GC_find_starting_hblk(HBLKPTR(p), &hhdr);\n\n        if (hhdr->hb_flags & IGNORE_OFF_PAGE)\n          return 0;\n        if (HBLK_IS_FREE(hhdr) || p - current >= (GC_signed_word)hhdr->hb_sz) {\n          GC_ADD_TO_BLACK_LIST_NORMAL(p, source);\n          /* The pointer is past the end of the block. */\n          return 0;\n        }\n      } else {\n        GC_ADD_TO_BLACK_LIST_NORMAL(p, source);\n        /* And return `NULL`. */\n      }\n      GC_ASSERT(NULL == hhdr || !HBLK_IS_FREE(hhdr));\n      /*\n       * Pointers past the first page are probably too rare to add them to\n       * the cache.  We do not.  And correctness relies on the fact that\n       * we do not.\n       */\n      return hhdr;\n    } else {\n      if (NULL == hhdr) {\n        GC_ADD_TO_BLACK_LIST_NORMAL(p, source);\n      }\n      return 0;\n    }\n  } else {\n    if (HBLK_IS_FREE(hhdr)) {\n      GC_ADD_TO_BLACK_LIST_NORMAL(p, source);\n      return 0;\n    } else {\n      hce->block_addr = ADDR(p) >> LOG_HBLKSIZE;\n      hce->hce_hdr = hhdr;\n      return hhdr;\n    }\n  }\n}\n\n/*\n * Routines to dynamically allocate collector data structures that will\n * never be freed.\n */\n\nGC_INNER ptr_t\nGC_scratch_alloc(size_t bytes)\n{\n  ptr_t result = GC_scratch_free_ptr;\n  size_t bytes_to_get;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  bytes = ROUNDUP_GRANULE_SIZE(bytes);\n  for (;;) {\n    GC_ASSERT(GC_scratch_end_addr >= ADDR(result));\n    if (bytes <= GC_scratch_end_addr - ADDR(result)) {\n      /* Unallocated space of scratch buffer has enough size. */\n      GC_scratch_free_ptr = result + bytes;\n      return result;\n    }\n\n    GC_ASSERT(GC_page_size != 0);\n    if (bytes >= MINHINCR * HBLKSIZE) {\n      bytes_to_get = ROUNDUP_PAGESIZE_IF_MMAP(bytes);\n      result = GC_os_get_mem(bytes_to_get);\n      if (result != NULL) {\n#if defined(KEEP_BACK_PTRS) && (GC_GRANULE_BYTES < 0x10)\n        GC_ASSERT(ADDR(result) > (word)NOT_MARKED);\n#endif\n        /* No update of scratch free area pointer; get memory directly. */\n#ifdef USE_SCRATCH_LAST_END_PTR\n        /*\n         * Update end point of last obtained area (needed only by\n         * `GC_register_dynamic_libraries` for some targets).\n         */\n        GC_scratch_last_end_addr = ADDR(result) + bytes;\n#endif\n      }\n      return result;\n    }\n\n    /* This is rounded up for a safety reason. */\n    bytes_to_get = ROUNDUP_PAGESIZE_IF_MMAP(MINHINCR * HBLKSIZE);\n\n    result = GC_os_get_mem(bytes_to_get);\n    if (UNLIKELY(NULL == result)) {\n      WARN(\"Out of memory - trying to allocate requested amount\"\n           \" (%\" WARN_PRIuPTR \" bytes)...\\n\",\n           bytes);\n      bytes_to_get = ROUNDUP_PAGESIZE_IF_MMAP(bytes);\n      result = GC_os_get_mem(bytes_to_get);\n      if (result != NULL) {\n#ifdef USE_SCRATCH_LAST_END_PTR\n        GC_scratch_last_end_addr = ADDR(result) + bytes;\n#endif\n      }\n      return result;\n    }\n\n    /* TODO: Some amount of unallocated space may remain unused forever. */\n    /* Update scratch area pointers and retry. */\n    GC_scratch_free_ptr = result;\n    GC_scratch_end_addr = ADDR(GC_scratch_free_ptr) + bytes_to_get;\n#ifdef USE_SCRATCH_LAST_END_PTR\n    GC_scratch_last_end_addr = GC_scratch_end_addr;\n#endif\n  }\n}\n\n/* Return an uninitialized header. */\nstatic hdr *\nalloc_hdr(void)\n{\n  hdr *result;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (NULL == GC_hdr_free_list) {\n    result = (hdr *)GC_scratch_alloc(sizeof(hdr));\n  } else {\n    result = GC_hdr_free_list;\n    GC_hdr_free_list = (hdr *)result->hb_next;\n  }\n  return result;\n}\n\nGC_INLINE void\nfree_hdr(hdr *hhdr)\n{\n  hhdr->hb_next = (struct hblk *)GC_hdr_free_list;\n  GC_hdr_free_list = hhdr;\n}\n\n#ifdef COUNT_HDR_CACHE_HITS\n/* Used for debugging/profiling (the symbols are externally visible). */\nword GC_hdr_cache_hits = 0;\nword GC_hdr_cache_misses = 0;\n#endif\n\nGC_INNER void\nGC_init_headers(void)\n{\n  unsigned i;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(NULL == GC_all_nils);\n  GC_all_nils = (bottom_index *)GC_scratch_alloc(sizeof(bottom_index));\n  if (GC_all_nils == NULL) {\n    GC_err_printf(\"Insufficient memory for GC_all_nils\\n\");\n    EXIT();\n  }\n  BZERO(GC_all_nils, sizeof(bottom_index));\n  for (i = 0; i < TOP_SZ; i++) {\n    GC_top_index[i] = GC_all_nils;\n  }\n}\n\n/*\n * Make sure that there is a bottom-level index block for address `addr`.\n * Returns `FALSE` on failure.\n */\nstatic GC_bool\nget_index(word addr)\n{\n  word hi = addr >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE);\n  bottom_index *r;\n  bottom_index *p;\n  bottom_index **prev;\n  bottom_index *pi; /*< `old_p` */\n  word i;\n\n  GC_ASSERT(I_HOLD_LOCK());\n#ifdef HASH_TL\n  i = TL_HASH(hi);\n  pi = GC_top_index[i];\n  for (p = pi; p != GC_all_nils; p = p->hash_link) {\n    if (p->key == hi)\n      return TRUE;\n  }\n#else\n  if (GC_top_index[hi] != GC_all_nils)\n    return TRUE;\n  i = hi;\n#endif\n  r = (bottom_index *)GC_scratch_alloc(sizeof(bottom_index));\n  if (UNLIKELY(NULL == r))\n    return FALSE;\n  BZERO(r, sizeof(bottom_index));\n  r->key = hi;\n#ifdef HASH_TL\n  r->hash_link = pi;\n#endif\n\n  /* Add it to the list of bottom indices. */\n  prev = &GC_all_bottom_indices; /*< pointer to `p` */\n\n  pi = NULL; /*< `bottom_index` preceding `p` */\n  while ((p = *prev) != 0 && p->key < hi) {\n    pi = p;\n    prev = &p->asc_link;\n  }\n  r->desc_link = pi;\n  if (NULL == p) {\n    GC_all_bottom_indices_end = r;\n  } else {\n    p->desc_link = r;\n  }\n  r->asc_link = p;\n  *prev = r;\n\n  GC_top_index[i] = r;\n  return TRUE;\n}\n\nGC_INNER hdr *\nGC_install_header(struct hblk *h)\n{\n  hdr *result;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (UNLIKELY(!get_index(ADDR(h))))\n    return NULL;\n\n  result = alloc_hdr();\n  if (LIKELY(result != NULL)) {\n    GC_ASSERT(!IS_FORWARDING_ADDR_OR_NIL(result));\n    SET_HDR(h, result);\n#ifdef USE_MUNMAP\n    result->hb_last_reclaimed = (unsigned short)GC_gc_no;\n#endif\n  }\n  return result;\n}\n\nGC_INNER GC_bool\nGC_install_counts(struct hblk *h, size_t sz /* bytes */)\n{\n  struct hblk *hbp;\n\n  for (hbp = h; ADDR_LT((ptr_t)hbp, (ptr_t)h + sz); hbp += BOTTOM_SZ) {\n    if (!get_index(ADDR(hbp)))\n      return FALSE;\n    /* Is overflow of `hbp` expected? */\n    if (ADDR(hbp) > GC_WORD_MAX - (word)BOTTOM_SZ * HBLKSIZE)\n      break;\n  }\n  if (!get_index(ADDR(h) + sz - 1))\n    return FALSE;\n\n  GC_ASSERT(!IS_FORWARDING_ADDR_OR_NIL(HDR(h)));\n  for (hbp = h + 1; ADDR_LT((ptr_t)hbp, (ptr_t)h + sz); hbp++) {\n    word i = (word)HBLK_PTR_DIFF(hbp, h);\n\n    SET_HDR(hbp, (hdr *)NUMERIC_TO_VPTR(i > MAX_JUMP ? MAX_JUMP : i));\n  }\n  return TRUE;\n}\n\nGC_INNER void\nGC_remove_header(struct hblk *h)\n{\n  hdr **ha;\n  GET_HDR_ADDR(h, ha);\n  free_hdr(*ha);\n  *ha = 0;\n}\n\nGC_INNER void\nGC_remove_counts(struct hblk *h, size_t sz /* bytes */)\n{\n  struct hblk *hbp;\n\n  if (sz <= HBLKSIZE)\n    return;\n  if (NULL == HDR(h + 1)) {\n#ifdef GC_ASSERTIONS\n    for (hbp = h + 2; ADDR_LT((ptr_t)hbp, (ptr_t)h + sz); hbp++) {\n      GC_ASSERT(NULL == HDR(hbp));\n    }\n#endif\n    return;\n  }\n\n  for (hbp = h + 1; ADDR_LT((ptr_t)hbp, (ptr_t)h + sz); hbp++) {\n    SET_HDR(hbp, NULL);\n  }\n}\n\n#define HBLK_ADDR(bi, j) \\\n  ((((bi)->key << LOG_BOTTOM_SZ) + (word)(j)) << LOG_HBLKSIZE)\n\nGC_API void GC_CALL\nGC_apply_to_all_blocks(GC_walk_hblk_fn fn, void *client_data)\n{\n  bottom_index *bi;\n\n  for (bi = GC_all_bottom_indices; bi != NULL; bi = bi->asc_link) {\n    GC_signed_word j;\n\n    for (j = BOTTOM_SZ - 1; j >= 0;) {\n      hdr *hhdr = bi->index[j];\n\n      if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {\n        j -= (GC_signed_word)(hhdr != NULL ? ADDR(hhdr) : 1);\n      } else {\n        if (!HBLK_IS_FREE(hhdr)) {\n          GC_ASSERT(HBLK_ADDR(bi, j) == ADDR(hhdr->hb_block));\n          fn(hhdr->hb_block, client_data);\n        }\n        j--;\n      }\n    }\n  }\n}\n\nGC_INNER struct hblk *\nGC_next_block(struct hblk *h, GC_bool allow_free)\n{\n  REGISTER bottom_index *bi;\n  REGISTER size_t j = (size_t)(ADDR(h) >> LOG_HBLKSIZE) & (BOTTOM_SZ - 1);\n\n  GC_ASSERT(I_HOLD_READER_LOCK());\n  GET_BI(h, bi);\n  if (bi == GC_all_nils) {\n    REGISTER word hi = ADDR(h) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE);\n\n    bi = GC_all_bottom_indices;\n    while (bi != NULL && bi->key < hi)\n      bi = bi->asc_link;\n    j = 0;\n  }\n\n  for (; bi != NULL; bi = bi->asc_link) {\n    while (j < BOTTOM_SZ) {\n      hdr *hhdr = bi->index[j];\n\n      if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {\n        j++;\n      } else {\n        if (allow_free || !HBLK_IS_FREE(hhdr)) {\n          GC_ASSERT(HBLK_ADDR(bi, j) == ADDR(hhdr->hb_block));\n          return hhdr->hb_block;\n        }\n        j += divHBLKSZ(hhdr->hb_sz);\n      }\n    }\n    j = 0;\n  }\n  return NULL;\n}\n\nGC_INNER struct hblk *\nGC_prev_block(struct hblk *h)\n{\n  bottom_index *bi;\n  GC_signed_word j = (ADDR(h) >> LOG_HBLKSIZE) & (BOTTOM_SZ - 1);\n\n  GC_ASSERT(I_HOLD_READER_LOCK());\n  GET_BI(h, bi);\n  if (bi == GC_all_nils) {\n    word hi = ADDR(h) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE);\n\n    bi = GC_all_bottom_indices_end;\n    while (bi != NULL && bi->key > hi)\n      bi = bi->desc_link;\n    j = BOTTOM_SZ - 1;\n  }\n  for (; bi != NULL; bi = bi->desc_link) {\n    while (j >= 0) {\n      hdr *hhdr = bi->index[j];\n\n      if (NULL == hhdr) {\n        --j;\n      } else if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {\n        j -= (GC_signed_word)ADDR(hhdr);\n      } else {\n        GC_ASSERT(HBLK_ADDR(bi, j) == ADDR(hhdr->hb_block));\n        return hhdr->hb_block;\n      }\n    }\n    j = BOTTOM_SZ - 1;\n  }\n  return NULL;\n}\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#ifndef SMALL_CONFIG\n/*\n * Build a free list for two-pointer cleared objects inside the given block.\n * Set the last link to be `ofl`.  Return a pointer to the first free-list\n * entry.\n */\nSTATIC ptr_t\nGC_build_fl_clear2(struct hblk *h, ptr_t ofl)\n{\n  ptr_t *p = (ptr_t *)h->hb_body;\n  ptr_t plim = (ptr_t)(h + 1);\n\n  p[0] = ofl;\n  p[1] = NULL;\n  p[2] = (ptr_t)p;\n  p[3] = NULL;\n  for (p += 4; ADDR_LT((ptr_t)p, plim); p += 4) {\n    p[0] = (ptr_t)(p - 2);\n    p[1] = NULL;\n    p[2] = (ptr_t)p;\n    p[3] = NULL;\n  }\n  return (ptr_t)(p - 2);\n}\n\n/* The same as above but uncleared objects. */\nSTATIC ptr_t\nGC_build_fl2(struct hblk *h, ptr_t ofl)\n{\n  ptr_t *p = (ptr_t *)h->hb_body;\n  ptr_t plim = (ptr_t)(h + 1);\n\n  p[0] = ofl;\n  p[2] = (ptr_t)p;\n  for (p += 4; ADDR_LT((ptr_t)p, plim); p += 4) {\n    p[0] = (ptr_t)(p - 2);\n    p[2] = (ptr_t)p;\n  }\n  return (ptr_t)(p - 2);\n}\n\n/* The same as above but for four-pointer cleared objects. */\nSTATIC ptr_t\nGC_build_fl_clear4(struct hblk *h, ptr_t ofl)\n{\n  ptr_t *p = (ptr_t *)h->hb_body;\n  ptr_t plim = (ptr_t)(h + 1);\n\n  p[0] = ofl;\n  p[1] = NULL;\n  p[2] = NULL;\n  p[3] = NULL;\n  for (p += 4; ADDR_LT((ptr_t)p, plim); p += 4) {\n    GC_PREFETCH_FOR_WRITE((ptr_t)(p + 64));\n    p[0] = (ptr_t)(p - 4);\n    p[1] = NULL;\n    CLEAR_DOUBLE(p + 2);\n  }\n  return (ptr_t)(p - 4);\n}\n\n/* The same as `GC_build_fl_clear4()` but uncleared objects. */\nSTATIC ptr_t\nGC_build_fl4(struct hblk *h, ptr_t ofl)\n{\n  ptr_t *p = (ptr_t *)h->hb_body;\n  ptr_t plim = (ptr_t)(h + 1);\n\n  p[0] = ofl;\n  p[4] = (ptr_t)p;\n  /* Unroll the loop by 2. */\n  for (p += 8; ADDR_LT((ptr_t)p, plim); p += 8) {\n    GC_PREFETCH_FOR_WRITE((ptr_t)(p + 64));\n    p[0] = (ptr_t)(p - 4);\n    p[4] = (ptr_t)p;\n  }\n  return (ptr_t)(p - 4);\n}\n#endif /* !SMALL_CONFIG */\n\nGC_INNER ptr_t\nGC_build_fl(struct hblk *h, ptr_t list, size_t lg, GC_bool clear)\n{\n  ptr_t *p, *prev;\n  ptr_t plim; /*< points to last object in new `hblk` entity */\n  size_t lpw = GRANULES_TO_PTRS(lg);\n\n  /*\n   * Do a few prefetches here, just because it is cheap.\n   * If we were more serious about it, these should go inside the loops.\n   * But write prefetches usually do not seem to matter much.\n   */\n  GC_PREFETCH_FOR_WRITE((ptr_t)h);\n  GC_PREFETCH_FOR_WRITE((ptr_t)h + 128);\n  GC_PREFETCH_FOR_WRITE((ptr_t)h + 256);\n  GC_PREFETCH_FOR_WRITE((ptr_t)h + 378);\n#ifndef SMALL_CONFIG\n  /*\n   * Handle small objects sizes more efficiently.  For larger objects\n   * the difference is less significant.\n   */\n  switch (lpw) {\n  case 2:\n    if (clear) {\n      return GC_build_fl_clear2(h, list);\n    } else {\n      return GC_build_fl2(h, list);\n    }\n  case 4:\n    if (clear) {\n      return GC_build_fl_clear4(h, list);\n    } else {\n      return GC_build_fl4(h, list);\n    }\n  default:\n    break;\n  }\n#endif /* !SMALL_CONFIG */\n\n  /* Clear the page if necessary. */\n  if (clear)\n    BZERO(h, HBLKSIZE);\n\n  /* Add objects to free list. */\n  prev = (ptr_t *)h->hb_body; /*< one object behind `p` */\n\n  /* The last place for the last object to start. */\n  plim = (ptr_t)h + HBLKSIZE - lpw * sizeof(ptr_t);\n\n  /* Make a list of all objects in `*h` with head as last object. */\n  for (p = prev + lpw; ADDR_GE(plim, (ptr_t)p); p += lpw) {\n    /* The current object's link points to last object. */\n    obj_link(p) = (ptr_t)prev;\n    prev = p;\n  }\n  p -= lpw;\n  /* `p` now points to the last object. */\n\n  /*\n   * Put `p` (which is now head of list of objects in `*h`) as first pointer\n   * in the appropriate free list for this size.\n   */\n  *(ptr_t *)h = list;\n  return (ptr_t)p;\n}\n\nGC_INNER void\nGC_new_hblk(size_t lg, int kind)\n{\n  struct hblk *h; /*< the new heap block */\n  size_t lb_adjusted = GRANULES_TO_BYTES(lg);\n\n  GC_STATIC_ASSERT(sizeof(struct hblk) == HBLKSIZE);\n  GC_ASSERT(I_HOLD_LOCK());\n  /* Allocate a new heap block. */\n  h = GC_allochblk(lb_adjusted, kind, 0 /* `flags` */, 0 /* `align_m1` */);\n  if (UNLIKELY(NULL == h))\n    return; /*< out of memory */\n\n  /* Mark all objects if appropriate. */\n  if (IS_UNCOLLECTABLE(kind))\n    GC_set_hdr_marks(HDR(h));\n\n  /* Build the free list. */\n  GC_obj_kinds[kind].ok_freelist[lg]\n      = GC_build_fl(h, (ptr_t)GC_obj_kinds[kind].ok_freelist[lg], lg,\n                    GC_debugging_started || GC_obj_kinds[kind].ok_init);\n}\n\n/*\n * Routines for maintaining maps describing heap block layouts for various\n * object sizes.  Allows fast pointer validity checks and fast location of\n * object start locations on machines (such as SPARC) with slow division.\n */\n\nGC_API void GC_CALL\nGC_register_displacement(size_t offset)\n{\n  LOCK();\n  GC_register_displacement_inner(offset);\n  UNLOCK();\n}\n\nGC_INNER void\nGC_register_displacement_inner(size_t offset)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  if (offset >= VALID_OFFSET_SZ) {\n    ABORT(\"Bad argument to GC_register_displacement\");\n  }\n  if (!GC_valid_offsets[offset]) {\n    GC_valid_offsets[offset] = TRUE;\n    GC_modws_valid_offsets[offset % sizeof(ptr_t)] = TRUE;\n  }\n}\n\n#ifndef MARK_BIT_PER_OBJ\nGC_INNER GC_bool\nGC_add_map_entry(size_t lg)\n{\n  size_t displ;\n  hb_map_entry_t *new_map;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  /*\n   * Ensure `displ % lg` fits into `hb_map_entry_t` type.\n   * Note: the maximum value is computed in this way to avoid compiler\n   * complains about constant truncation or expression overflow.\n   */\n  GC_STATIC_ASSERT(\n      MAXOBJGRANULES - 1\n      <= (~(size_t)0 >> ((sizeof(size_t) - sizeof(hb_map_entry_t)) * 8)));\n\n  if (lg > MAXOBJGRANULES)\n    lg = 0;\n  if (LIKELY(GC_obj_map[lg] != NULL))\n    return TRUE;\n\n  new_map = (hb_map_entry_t *)GC_scratch_alloc(OBJ_MAP_LEN\n                                               * sizeof(hb_map_entry_t));\n  if (UNLIKELY(NULL == new_map))\n    return FALSE;\n\n  GC_COND_LOG_PRINTF(\"Adding block map for size of %u granules (%u bytes)\\n\",\n                     (unsigned)lg, (unsigned)GRANULES_TO_BYTES(lg));\n  if (0 == lg) {\n    for (displ = 0; displ < OBJ_MAP_LEN; displ++) {\n      /* Set to a nonzero to get us out of the marker fast path. */\n      new_map[displ] = 1;\n    }\n  } else {\n    for (displ = 0; displ < OBJ_MAP_LEN; displ++) {\n      new_map[displ] = (hb_map_entry_t)(displ % lg);\n    }\n  }\n  GC_obj_map[lg] = new_map;\n  return TRUE;\n}\n#endif /* !MARK_BIT_PER_OBJ */\n\nGC_INNER void\nGC_initialize_offsets(void)\n{\n  size_t i;\n\n  if (GC_all_interior_pointers) {\n    for (i = 0; i < VALID_OFFSET_SZ; ++i)\n      GC_valid_offsets[i] = TRUE;\n  } else {\n    BZERO(GC_valid_offsets, sizeof(GC_valid_offsets));\n    for (i = 0; i < sizeof(ptr_t); ++i)\n      GC_modws_valid_offsets[i] = FALSE;\n  }\n}\n\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n/*\n * These are checking routines calls to which could be inserted by\n * a preprocessor to validate C pointer arithmetic.\n */\n\nSTATIC void GC_CALLBACK\nGC_default_same_obj_print_proc(void *p, void *q)\n{\n  ABORT_ARG2(\"GC_same_obj test failed\",\n             \": %p and %p are not in the same object\", p, q);\n}\n\nGC_same_obj_print_proc_t GC_same_obj_print_proc\n    = GC_default_same_obj_print_proc;\n\nGC_API void *GC_CALL\nGC_same_obj(void *p, void *q)\n{\n  hdr *hhdr;\n  ptr_t base, limit;\n  size_t sz;\n\n  if (UNLIKELY(!GC_is_initialized))\n    GC_init();\n  hhdr = HDR(p);\n  if (NULL == hhdr) {\n    if (divHBLKSZ(ADDR(p)) != divHBLKSZ(ADDR(q)) && HDR(q) != NULL) {\n      GC_same_obj_print_proc((ptr_t)p, (ptr_t)q);\n    }\n    return p;\n  }\n  /*\n   * If it is a pointer to the middle of a large object, move it to\n   * the beginning.\n   */\n  if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {\n    struct hblk *h = GC_find_starting_hblk(HBLKPTR(p), &hhdr);\n\n    limit = (ptr_t)h + hhdr->hb_sz;\n    if (ADDR_GE((ptr_t)p, limit) || ADDR_GE((ptr_t)q, limit)\n        || ADDR_LT((ptr_t)q, (ptr_t)h)) {\n      GC_same_obj_print_proc((ptr_t)p, (ptr_t)q);\n    }\n    return p;\n  }\n  sz = hhdr->hb_sz;\n  if (sz > MAXOBJBYTES) {\n    base = (ptr_t)HBLKPTR(p);\n    limit = base + sz;\n    if (ADDR_GE((ptr_t)p, limit)) {\n      GC_same_obj_print_proc((ptr_t)p, (ptr_t)q);\n      return p;\n    }\n  } else {\n    size_t offset;\n\n    if (HBLKPTR(p) != HBLKPTR(q)) {\n      /*\n       * Without this check, we might miss an error if `q` points to\n       * the first object on a page, and points just before the page.\n       */\n      GC_same_obj_print_proc((ptr_t)p, (ptr_t)q);\n      return p;\n    }\n    offset = HBLKDISPL(p) % sz;\n    base = (ptr_t)p - offset;\n    limit = base + sz;\n  }\n  /*\n   * [`base`,`limit`) delimits the object containing `p`, if any.\n   * If `p` is not inside a valid object, then either `q` is also\n   * outside any valid object, or it is outside [`base`,`limit`).\n   */\n  if (!ADDR_INSIDE((ptr_t)q, base, limit)) {\n    GC_same_obj_print_proc((ptr_t)p, (ptr_t)q);\n  }\n  return p;\n}\n\nSTATIC void GC_CALLBACK\nGC_default_is_valid_displacement_print_proc(void *p)\n{\n  ABORT_ARG1(\"GC_is_valid_displacement test failed\", \": %p not valid\", p);\n}\n\nGC_valid_ptr_print_proc_t GC_is_valid_displacement_print_proc\n    = GC_default_is_valid_displacement_print_proc;\n\nGC_API void *GC_CALL\nGC_is_valid_displacement(void *p)\n{\n  hdr *hhdr;\n  size_t offset;\n  struct hblk *h;\n  size_t sz;\n\n  if (UNLIKELY(!GC_is_initialized))\n    GC_init();\n  if (NULL == p)\n    return NULL;\n  hhdr = HDR(p);\n  if (NULL == hhdr)\n    return p;\n  h = HBLKPTR(p);\n  if (GC_all_interior_pointers) {\n    h = GC_find_starting_hblk(h, &hhdr);\n  } else if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {\n    GC_is_valid_displacement_print_proc((ptr_t)p);\n    return p;\n  }\n  sz = hhdr->hb_sz;\n  offset = HBLKDISPL(p) % sz;\n  if ((sz > MAXOBJBYTES && ADDR_GE((ptr_t)p, (ptr_t)h + sz))\n      || !GC_valid_offsets[offset]\n      || (ADDR_LT((ptr_t)(h + 1), (ptr_t)p + sz - offset)\n          && !IS_FORWARDING_ADDR_OR_NIL(HDR(h + 1)))) {\n    GC_is_valid_displacement_print_proc((ptr_t)p);\n  }\n  return p;\n}\n\nSTATIC void GC_CALLBACK\nGC_default_is_visible_print_proc(void *p)\n{\n  ABORT_ARG1(\"GC_is_visible test failed\", \": %p not GC-visible\", p);\n}\n\nGC_valid_ptr_print_proc_t GC_is_visible_print_proc\n    = GC_default_is_visible_print_proc;\n\n#ifndef THREADS\n/* Could `p` be a stack address? */\nSTATIC GC_bool\nGC_on_stack(ptr_t p)\n{\n  return HOTTER_THAN(p, GC_stackbottom) && !HOTTER_THAN(p, GC_approx_sp());\n}\n\n/* Is the address `p` in one of the registered static root sections? */\nSTATIC GC_bool\nGC_is_static_root(ptr_t p)\n{\n  static size_t last_static_root_set = MAX_ROOT_SETS;\n  size_t i;\n\n#  if defined(CPPCHECK)\n  if (n_root_sets > MAX_ROOT_SETS)\n    ABORT(\"Bad n_root_sets\");\n#  endif\n  if (last_static_root_set < n_root_sets\n      && ADDR_INSIDE(p, GC_static_roots[last_static_root_set].r_start,\n                     GC_static_roots[last_static_root_set].r_end))\n    return TRUE;\n  for (i = 0; i < n_root_sets; i++) {\n    if (ADDR_INSIDE(p, GC_static_roots[i].r_start, GC_static_roots[i].r_end)) {\n      last_static_root_set = i;\n      return TRUE;\n    }\n  }\n  return FALSE;\n}\n#endif /* !THREADS */\n\nGC_API void *GC_CALL\nGC_is_visible(void *p)\n{\n  const hdr *hhdr;\n\n  if ((ADDR(p) & (ALIGNMENT - 1)) != 0)\n    goto fail;\n  if (UNLIKELY(!GC_is_initialized))\n    GC_init();\n#ifdef THREADS\n  hhdr = HDR(p);\n  if (hhdr != NULL && NULL == GC_base(p)) {\n    goto fail;\n  } else {\n    /* May be inside thread stack.  We cannot do much. */\n    return p;\n  }\n#else\n  /* Check stack first. */\n  if (GC_on_stack((ptr_t)p))\n    return p;\n\n  hhdr = HDR(p);\n  if (NULL == hhdr) {\n    if (GC_is_static_root((ptr_t)p)) {\n      return p;\n    }\n    /* Else do it again correctly. */\n#  if defined(ANY_MSWIN) || defined(DYNAMIC_LOADING)\n    if (!GC_no_dls) {\n      GC_register_dynamic_libraries();\n      if (GC_is_static_root((ptr_t)p))\n        return p;\n    }\n#  endif\n  } else {\n    /* `p` points to the heap. */\n    word descr;\n    /* TODO: Should `GC_base` be manually inlined? */\n    ptr_t base = (ptr_t)GC_base(p);\n\n    if (NULL == base)\n      goto fail;\n    if (HBLKPTR(base) != HBLKPTR(p))\n      hhdr = HDR(base);\n    descr = hhdr->hb_descr;\n  retry:\n    switch (descr & GC_DS_TAGS) {\n    case GC_DS_LENGTH:\n      if ((word)((ptr_t)p - base) >= descr)\n        goto fail;\n      break;\n    case GC_DS_BITMAP:\n      if ((ptr_t)p - base >= (ptrdiff_t)PTRS_TO_BYTES(BITMAP_BITS))\n        goto fail;\n#  if ALIGNMENT != CPP_PTRSZ / 8\n      if ((ADDR(p) & (sizeof(ptr_t) - 1)) != 0)\n        goto fail;\n#  endif\n      if (!(((word)1 << (CPP_WORDSZ - 1 - (word)((ptr_t)p - base))) & descr))\n        goto fail;\n      break;\n    case GC_DS_PROC:\n      /* We could try to decipher this partially.  For now we just punt. */\n      break;\n    case GC_DS_PER_OBJECT:\n      if (!(descr & SIGNB)) {\n        descr = *(word *)((ptr_t)base + (descr & ~(word)GC_DS_TAGS));\n      } else {\n        ptr_t type_descr = *(ptr_t *)base;\n\n        if (UNLIKELY(NULL == type_descr)) {\n          /* See the comment in `GC_mark_from`. */\n          goto fail;\n        }\n        descr = *(word *)(type_descr\n                          - ((GC_signed_word)descr\n                             + (GC_INDIR_PER_OBJ_BIAS - GC_DS_PER_OBJECT)));\n      }\n      goto retry;\n    }\n    return p;\n  }\n#endif\nfail:\n  GC_is_visible_print_proc((ptr_t)p);\n  return p;\n}\n\nGC_API void *GC_CALL\nGC_pre_incr(void **p, ptrdiff_t how_much)\n{\n  void *initial = *p;\n  void *result = GC_same_obj((ptr_t)initial + how_much, initial);\n\n  if (!GC_all_interior_pointers) {\n    (void)GC_is_valid_displacement(result);\n  }\n  *p = result;\n  return result; /*< updated pointer */\n}\n\nGC_API void *GC_CALL\nGC_post_incr(void **p, ptrdiff_t how_much)\n{\n  void *initial = *p;\n  void *result = GC_same_obj((ptr_t)initial + how_much, initial);\n\n  if (!GC_all_interior_pointers) {\n    (void)GC_is_valid_displacement(result);\n  }\n  *p = result;\n  return initial; /*< original `*p` */\n}\n\nGC_API void GC_CALL\nGC_set_same_obj_print_proc(GC_same_obj_print_proc_t fn)\n{\n  GC_ASSERT(NONNULL_ARG_NOT_NULL(fn));\n  GC_same_obj_print_proc = fn;\n}\n\nGC_API GC_same_obj_print_proc_t GC_CALL\nGC_get_same_obj_print_proc(void)\n{\n  return GC_same_obj_print_proc;\n}\n\nGC_API void GC_CALL\nGC_set_is_valid_displacement_print_proc(GC_valid_ptr_print_proc_t fn)\n{\n  GC_ASSERT(NONNULL_ARG_NOT_NULL(fn));\n  GC_is_valid_displacement_print_proc = fn;\n}\n\nGC_API GC_valid_ptr_print_proc_t GC_CALL\nGC_get_is_valid_displacement_print_proc(void)\n{\n  return GC_is_valid_displacement_print_proc;\n}\n\nGC_API void GC_CALL\nGC_set_is_visible_print_proc(GC_valid_ptr_print_proc_t fn)\n{\n  GC_ASSERT(NONNULL_ARG_NOT_NULL(fn));\n  GC_is_visible_print_proc = fn;\n}\n\nGC_API GC_valid_ptr_print_proc_t GC_CALL\nGC_get_is_visible_print_proc(void)\n{\n  return GC_is_visible_print_proc;\n}\n\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1998-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#ifdef GC_USE_ENTIRE_HEAP\nint GC_use_entire_heap = TRUE;\n#else\nint GC_use_entire_heap = FALSE;\n#endif\n\n/*\n * Free heap blocks are kept on one of several free lists, depending on\n * the size of the block.  Each free list is doubly linked.  Adjacent\n * free blocks are coalesced.\n */\n\n/*\n * Largest block we will be allocated starting on a black-listed block.\n * Must be not smaller than `HBLKSIZE`.\n */\n#define MAX_BLACK_LIST_ALLOC (2 * HBLKSIZE)\n\n/* Sizes up to this many `hblk` entities each have their own free list. */\n#define UNIQUE_THRESHOLD 32\n\n/*\n * Sizes of at least this many heap blocks are mapped to a single free\n * list.\n */\n#define HUGE_THRESHOLD 256\n\n/* In between sizes map this many distinct sizes to a single bin. */\n#define FL_COMPRESSION 8\n\n#define N_HBLK_FLS \\\n  ((HUGE_THRESHOLD - UNIQUE_THRESHOLD) / FL_COMPRESSION + UNIQUE_THRESHOLD)\n\n/*\n * List of completely empty heap blocks.  Linked through `hb_next` field\n * of header structure associated with block.  Remains externally visible\n * as used by GNU `gcj`.\n */\n#ifndef GC_GCJ_SUPPORT\nSTATIC\n#endif\nstruct hblk *GC_hblkfreelist[N_HBLK_FLS + 1] = { 0 };\n\nGC_API void GC_CALL\nGC_iterate_free_hblks(GC_walk_free_blk_fn fn, void *client_data)\n{\n  int i;\n\n  for (i = 0; i <= N_HBLK_FLS; ++i) {\n    struct hblk *h;\n\n    for (h = GC_hblkfreelist[i]; h != NULL; h = HDR(h)->hb_next) {\n      fn(h, i, client_data);\n    }\n  }\n}\n\n/* Number of free bytes on each list.  Remains visible to `gcj`. */\n#ifndef GC_GCJ_SUPPORT\nSTATIC\n#endif\nword GC_free_bytes[N_HBLK_FLS + 1] = { 0 };\n\n#ifndef GC_NO_DEINIT\nGC_INNER void\nGC_reset_freelist(void)\n{\n  BZERO(GC_hblkfreelist, sizeof(GC_hblkfreelist));\n  BZERO(GC_free_bytes, sizeof(GC_free_bytes));\n}\n#endif\n\n/*\n * Return the largest `n` such that the number of free bytes on lists\n * `n` .. `N_HBLK_FLS` is greater or equal to `GC_max_large_allocd_bytes`\n * minus `GC_large_allocd_bytes`.  If there is no such `n`, return 0.\n */\nGC_INLINE size_t\nGC_enough_large_bytes_left(void)\n{\n  size_t n;\n  word bytes = GC_large_allocd_bytes;\n\n  GC_ASSERT(GC_max_large_allocd_bytes <= GC_heapsize);\n  for (n = N_HBLK_FLS; n > 0; n--) {\n    bytes += GC_free_bytes[n];\n    if (bytes >= GC_max_large_allocd_bytes)\n      break;\n  }\n  return n;\n}\n\n/* Map a number of blocks to the appropriate large block free-list index. */\nSTATIC size_t\nGC_hblk_fl_from_blocks(size_t blocks_needed)\n{\n  if (blocks_needed <= UNIQUE_THRESHOLD)\n    return blocks_needed;\n  if (blocks_needed >= HUGE_THRESHOLD)\n    return N_HBLK_FLS;\n  return (blocks_needed - UNIQUE_THRESHOLD) / FL_COMPRESSION\n         + UNIQUE_THRESHOLD;\n}\n\n#define PHDR(hhdr) HDR((hhdr)->hb_prev)\n#define NHDR(hhdr) HDR((hhdr)->hb_next)\n\n#ifdef USE_MUNMAP\n#  define IS_MAPPED(hhdr) (((hhdr)->hb_flags & WAS_UNMAPPED) == 0)\n#else\n#  define IS_MAPPED(hhdr) TRUE\n#endif /* !USE_MUNMAP */\n\n#if !defined(NO_DEBUGGING) || defined(GC_ASSERTIONS)\nstatic void GC_CALLBACK\nadd_hb_sz(struct hblk *h, int i, void *total_free_ptr)\n{\n  UNUSED_ARG(i);\n  *(word *)total_free_ptr += HDR(h)->hb_sz;\n#  if defined(CPPCHECK)\n  GC_noop1_ptr(h);\n#  endif\n}\n\nGC_INNER word\nGC_compute_large_free_bytes(void)\n{\n  word total_free = 0;\n\n  GC_iterate_free_hblks(add_hb_sz, &total_free);\n  return total_free;\n}\n#endif /* !NO_DEBUGGING || GC_ASSERTIONS */\n\n#ifndef NO_DEBUGGING\nstatic void GC_CALLBACK\nprint_hblkfreelist_item(struct hblk *h, int i, void *prev_index_ptr)\n{\n  hdr *hhdr = HDR(h);\n\n#  if defined(CPPCHECK)\n  GC_noop1_ptr(h);\n#  endif\n  if (i != *(int *)prev_index_ptr) {\n    GC_printf(\"Free list %d (total size %lu):\\n\", i,\n              (unsigned long)GC_free_bytes[i]);\n    *(int *)prev_index_ptr = i;\n  }\n\n#  ifdef NO_BLACK_LISTING\n  GC_printf(\"\\t%p size %lu\\n\", (void *)h, (unsigned long)hhdr->hb_sz);\n#  else\n  GC_printf(\"\\t%p size %lu %s black listed\\n\", (void *)h,\n            (unsigned long)hhdr->hb_sz,\n            GC_is_black_listed(h, HBLKSIZE) != NULL      ? \"start\"\n            : GC_is_black_listed(h, hhdr->hb_sz) != NULL ? \"partially\"\n                                                         : \"not\");\n#  endif\n}\n\nvoid\nGC_print_hblkfreelist(void)\n{\n  word total;\n  int prev_index = -1;\n\n  GC_iterate_free_hblks(print_hblkfreelist_item, &prev_index);\n  GC_printf(\"GC_large_free_bytes: %lu\\n\", (unsigned long)GC_large_free_bytes);\n  total = GC_compute_large_free_bytes();\n  if (total != GC_large_free_bytes)\n    GC_err_printf(\"GC_large_free_bytes INCONSISTENT!! Should be: %lu\\n\",\n                  (unsigned long)total);\n}\n\n/*\n * Return the free-list index on which the block described by the header\n * appears, or -1 if it appears nowhere.\n */\nstatic int\nfree_list_index_of(const hdr *wanted)\n{\n  int i;\n\n  for (i = 0; i <= N_HBLK_FLS; ++i) {\n    const struct hblk *h;\n    const hdr *hhdr;\n\n    for (h = GC_hblkfreelist[i]; h != NULL; h = hhdr->hb_next) {\n      hhdr = HDR(h);\n      if (hhdr == wanted)\n        return i;\n    }\n  }\n  return -1;\n}\n\nGC_API void GC_CALL\nGC_foreach_heap_section_inner(GC_heap_section_proc fn, void *client_data)\n{\n  size_t i;\n\n  /*\n   * The collector memory is organized in heap sections that are split in\n   * blocks.  Each such block has a header (obtained by `HDR(p)`) and the\n   * block size is aligned to `HBLKSIZE`.  The block headers are kept\n   * separately from the memory they point to.\n   */\n  for (i = 0; i < GC_n_heap_sects; ++i) {\n    ptr_t start = GC_heap_sects[i].hs_start;\n    ptr_t finish = start + GC_heap_sects[i].hs_bytes;\n    ptr_t p;\n\n    /* Merge in contiguous sections. */\n    while (i + 1 < GC_n_heap_sects\n           && GC_heap_sects[i + 1].hs_start == finish) {\n      ++i;\n      finish = GC_heap_sects[i].hs_start + GC_heap_sects[i].hs_bytes;\n    }\n\n    fn(start, finish, GC_HEAP_SECTION_TYPE_WHOLE_SECT, client_data);\n    for (p = start; ADDR_LT(p, finish);) {\n      /*\n       * Lookup into 2-level tree data structure which uses address\n       * as a hash key to find the block header.\n       */\n      hdr *hhdr = HDR(p);\n\n      if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {\n        /*\n         * The pointer has no header registered in the headers cache.\n         * Skip one `HBLKSIZE` and retry.  Might be mapped or not.\n         */\n        fn(p, p + HBLKSIZE, GC_HEAP_SECTION_TYPE_FORWARDING, client_data);\n        p += HBLKSIZE;\n        continue;\n      }\n\n      if (HBLK_IS_FREE(hhdr)) {\n        /*\n         * The block is marked as free.  Note: `hb_sz` is the size in bytes\n         * of the whole block.\n         */\n        fn(p, p + hhdr->hb_sz,\n           IS_MAPPED(hhdr) ? GC_HEAP_SECTION_TYPE_FREE\n                           : GC_HEAP_SECTION_TYPE_UNMAPPED,\n           client_data);\n        p += hhdr->hb_sz;\n      } else {\n        /*\n         * This heap block is used.  Report also the padding, if any.\n         * Note: `hb_sz` is the size (in bytes) of objects in the block.\n         */\n        ptr_t blockEnd = p + HBLKSIZE * OBJ_SZ_TO_BLOCKS(hhdr->hb_sz);\n        ptr_t usedBlockEnd = p + hhdr->hb_sz;\n\n        fn(p, usedBlockEnd, GC_HEAP_SECTION_TYPE_USED, client_data);\n        if (ADDR_LT(usedBlockEnd, blockEnd))\n          fn(usedBlockEnd, blockEnd, GC_HEAP_SECTION_TYPE_PADDING,\n             client_data);\n        p = blockEnd;\n      }\n    }\n  }\n}\n\nstatic void GC_CALLBACK\ndump_regions_proc(void *start, void *finish, GC_heap_section_type type,\n                  void *client_data)\n{\n  hdr *hhdr;\n  int correct_index, actual_index;\n\n  UNUSED_ARG(client_data);\n  switch (type) {\n  case GC_HEAP_SECTION_TYPE_WHOLE_SECT:\n    GC_printf(\"***Section from %p to %p\\n\", start, finish);\n    break;\n  case GC_HEAP_SECTION_TYPE_FORWARDING:\n    GC_printf(\"\\t%p Missing header!!(%p)\\n\", start, (void *)HDR(start));\n    break;\n  case GC_HEAP_SECTION_TYPE_FREE:\n  case GC_HEAP_SECTION_TYPE_UNMAPPED:\n    hhdr = HDR(start);\n    GC_printf(\"\\t%p\\tfree block of size 0x%lx bytes%s\\n\", start,\n              (unsigned long)hhdr->hb_sz,\n              type == GC_HEAP_SECTION_TYPE_UNMAPPED ? \" (unmapped)\" : \"\");\n    actual_index = free_list_index_of(hhdr);\n    correct_index = (int)GC_hblk_fl_from_blocks(divHBLKSZ(hhdr->hb_sz));\n    if (-1 == actual_index) {\n      GC_printf(\"\\t\\tBlock not on free list %d!!\\n\", correct_index);\n    } else if (correct_index != actual_index) {\n      GC_printf(\"\\t\\tBlock on list %d, should be on %d!!\\n\", actual_index,\n                correct_index);\n    }\n    break;\n  case GC_HEAP_SECTION_TYPE_USED:\n    GC_printf(\"\\t%p\\tused for blocks of size 0x%lx bytes\\n\", start,\n              (unsigned long)(ADDR(finish) - ADDR(start)));\n    break;\n  case GC_HEAP_SECTION_TYPE_PADDING:\n    /* Empty. */\n    break;\n  }\n}\n\nGC_API void GC_CALL\nGC_dump_regions(void)\n{\n  GC_foreach_heap_section_inner(dump_regions_proc, NULL);\n}\n#endif /* !NO_DEBUGGING */\n\n/*\n * Initialize `hhdr` for a `block` containing the indicated size\n * `lb_adjusted` and `kind` of objects.  Return `FALSE` on failure.\n */\nstatic GC_bool\nsetup_header(hdr *hhdr, struct hblk *block, size_t lb_adjusted, int kind,\n             unsigned flags)\n{\n  const struct obj_kind *ok;\n  word descr;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(lb_adjusted >= ALIGNMENT);\n#ifndef MARK_BIT_PER_OBJ\n  if (lb_adjusted > MAXOBJBYTES)\n    flags |= LARGE_BLOCK;\n#endif\n  ok = &GC_obj_kinds[kind];\n#ifdef ENABLE_DISCLAIM\n  if (ok->ok_disclaim_proc)\n    flags |= HAS_DISCLAIM;\n  if (ok->ok_mark_unconditionally)\n    flags |= MARK_UNCONDITIONALLY;\n#endif\n\n  /* Set size, kind and mark procedure fields. */\n  hhdr->hb_sz = lb_adjusted;\n  hhdr->hb_obj_kind = (unsigned char)kind;\n  hhdr->hb_flags = (unsigned char)flags;\n  hhdr->hb_block = block;\n  descr = ok->ok_descriptor;\n#if ALIGNMENT > GC_DS_TAGS\n  /*\n   * An extra byte is not added in case of ignore-off-page allocated objects\n   * not smaller than `HBLKSIZE`.\n   */\n  if (EXTRA_BYTES != 0 && (flags & IGNORE_OFF_PAGE) != 0 && kind == NORMAL\n      && lb_adjusted >= HBLKSIZE)\n    descr += ALIGNMENT; /*< or set to 0 */\n#endif\n  if (ok->ok_relocate_descr)\n    descr += lb_adjusted;\n  hhdr->hb_descr = descr;\n\n#ifdef MARK_BIT_PER_OBJ\n  /*\n   * Set `hb_inv_sz` as portably as possible.  We set it to the smallest\n   * value such that `lb_adjusted * inv_sz >= 2**32`.\n   * This may be more precision than necessary.\n   */\n  if (lb_adjusted > MAXOBJBYTES) {\n    hhdr->hb_inv_sz = LARGE_INV_SZ;\n  } else {\n    unsigned32 inv_sz;\n\n    GC_ASSERT(lb_adjusted > 1);\n#  if CPP_WORDSZ > 32\n    inv_sz = (unsigned32)(((word)1 << 32) / lb_adjusted);\n    if (((inv_sz * (word)lb_adjusted) >> 32) == 0)\n      ++inv_sz;\n#  else\n    inv_sz = (((unsigned32)1 << 31) / lb_adjusted) << 1;\n    while ((inv_sz * lb_adjusted) > lb_adjusted)\n      inv_sz++;\n#  endif\n#  if (CPP_WORDSZ == 32) && defined(__GNUC__)\n    GC_ASSERT(((1ULL << 32) + lb_adjusted - 1) / lb_adjusted == inv_sz);\n#  endif\n    hhdr->hb_inv_sz = inv_sz;\n  }\n#else\n  {\n    size_t lg = BYTES_TO_GRANULES(lb_adjusted);\n\n    if (UNLIKELY(!GC_add_map_entry(lg))) {\n      /* Make it look like a valid block. */\n      hhdr->hb_sz = HBLKSIZE;\n      hhdr->hb_descr = 0;\n      hhdr->hb_flags |= LARGE_BLOCK;\n      hhdr->hb_map = NULL;\n      return FALSE;\n    }\n    hhdr->hb_map = GC_obj_map[(hhdr->hb_flags & LARGE_BLOCK) != 0 ? 0 : lg];\n  }\n#endif\n\n  /* Clear mark bits. */\n  GC_clear_hdr_marks(hhdr);\n\n  hhdr->hb_last_reclaimed = (unsigned short)GC_gc_no;\n  return TRUE;\n}\n\n/*\n * Remove `hhdr` from the free list (it is assumed to be specified by\n * `index`).\n */\nSTATIC void\nGC_remove_from_fl_at(hdr *hhdr, size_t index)\n{\n  GC_ASSERT(modHBLKSZ(hhdr->hb_sz) == 0);\n  if (hhdr->hb_prev == 0) {\n    GC_ASSERT(HDR(GC_hblkfreelist[index]) == hhdr);\n    GC_hblkfreelist[index] = hhdr->hb_next;\n  } else {\n    hdr *phdr;\n    GET_HDR(hhdr->hb_prev, phdr);\n    phdr->hb_next = hhdr->hb_next;\n  }\n  /* We always need index to maintain free counts. */\n  GC_ASSERT(GC_free_bytes[index] >= hhdr->hb_sz);\n  GC_free_bytes[index] -= hhdr->hb_sz;\n  if (hhdr->hb_next != NULL) {\n    hdr *nhdr;\n\n    GC_ASSERT(!IS_FORWARDING_ADDR_OR_NIL(NHDR(hhdr)));\n    GET_HDR(hhdr->hb_next, nhdr);\n    nhdr->hb_prev = hhdr->hb_prev;\n  }\n}\n\n/*\n * Remove `hhdr` from the appropriate free list (we assume it is on the\n * size-appropriate free list).\n */\nGC_INLINE void\nGC_remove_from_fl(hdr *hhdr)\n{\n  GC_remove_from_fl_at(hhdr, GC_hblk_fl_from_blocks(divHBLKSZ(hhdr->hb_sz)));\n}\n\n/* Return a pointer to the block ending just before `h`, if any. */\nstatic struct hblk *\nget_block_ending_at(struct hblk *h)\n{\n  struct hblk *p = h - 1;\n  hdr *hhdr;\n\n  GET_HDR(p, hhdr);\n  if (hhdr != NULL) {\n    return GC_find_starting_hblk(p, &hhdr);\n  }\n  p = GC_prev_block(p);\n  if (p != NULL) {\n    hhdr = HDR(p);\n    if ((ptr_t)p + hhdr->hb_sz == (ptr_t)h) {\n      return p;\n    }\n  }\n  return NULL;\n}\n\n/* Return a pointer to the free block ending just before `h`, if any. */\nSTATIC struct hblk *\nGC_free_block_ending_at(struct hblk *h)\n{\n  struct hblk *p = get_block_ending_at(h);\n\n  if (p /* `!= NULL` */) { /*< CPPCHECK */\n    const hdr *hhdr = HDR(p);\n\n    if (HBLK_IS_FREE(hhdr)) {\n      return p;\n    }\n  }\n  return 0;\n}\n\n/*\n * Add `hhdr` to the appropriate free list.  We maintain individual\n * free lists sorted by address.\n */\nSTATIC void\nGC_add_to_fl(struct hblk *h, hdr *hhdr)\n{\n  size_t index = GC_hblk_fl_from_blocks(divHBLKSZ(hhdr->hb_sz));\n  struct hblk *second = GC_hblkfreelist[index];\n\n#if defined(GC_ASSERTIONS) && !defined(USE_MUNMAP) && !defined(CHERI_PURECAP)\n  {\n    struct hblk *next = (struct hblk *)((ptr_t)h + hhdr->hb_sz);\n    const hdr *nexthdr = HDR(next);\n    struct hblk *prev = GC_free_block_ending_at(h);\n    const hdr *prevhdr = HDR(prev);\n\n    GC_ASSERT(NULL == nexthdr || !HBLK_IS_FREE(nexthdr)\n              || (GC_heapsize & SIGNB) != 0);\n    /* In the last case, blocks may be too large to be merged. */\n    GC_ASSERT(NULL == prev || !HBLK_IS_FREE(prevhdr)\n              || (GC_heapsize & SIGNB) != 0);\n  }\n#endif\n  GC_ASSERT(modHBLKSZ(hhdr->hb_sz) == 0);\n  GC_hblkfreelist[index] = h;\n  GC_free_bytes[index] += hhdr->hb_sz;\n  GC_ASSERT(GC_free_bytes[index] <= GC_large_free_bytes);\n  hhdr->hb_next = second;\n  hhdr->hb_prev = NULL;\n  if (second /* `!= NULL` */) { /*< CPPCHECK */\n    hdr *second_hdr;\n\n    GET_HDR(second, second_hdr);\n    second_hdr->hb_prev = h;\n  }\n  hhdr->hb_flags |= FREE_BLK;\n}\n\n#define BLOCKS_MERGE_OVERFLOW(hhdr, nexthdr) \\\n  ((((hhdr)->hb_sz + (nexthdr)->hb_sz) & SIZET_SIGNB) != 0)\n\n#ifdef USE_MUNMAP\n\n/*\n * `GC_unmap_old` will avoid creating more than this many unmapped regions,\n * but an unmapped region may be split again so exceeding the limit.\n */\n#  ifdef COUNT_UNMAPPED_REGIONS\n\n/*\n * Return the change in number of unmapped regions if the block `h` swaps\n * from its current state of mapped/unmapped to the opposite state.\n */\nstatic int\ncalc_num_unmapped_regions_delta(struct hblk *h, hdr *hhdr)\n{\n  struct hblk *prev = get_block_ending_at(h);\n  struct hblk *next;\n  GC_bool prev_unmapped = FALSE;\n  GC_bool next_unmapped = FALSE;\n\n  next = GC_next_block((struct hblk *)((ptr_t)h + hhdr->hb_sz), TRUE);\n  /* Ensure next is contiguous with `h`. */\n  if (next != HBLK_PAGE_ALIGNED((ptr_t)h + hhdr->hb_sz)) {\n    next = NULL;\n  }\n  if (prev != NULL) {\n    const hdr *prevhdr = HDR(prev);\n    prev_unmapped = !IS_MAPPED(prevhdr);\n  }\n  if (next != NULL) {\n    const hdr *nexthdr = HDR(next);\n    next_unmapped = !IS_MAPPED(nexthdr);\n  }\n\n  if (prev_unmapped && next_unmapped) {\n    /*\n     * If `h` is unmapped, merge two unmapped regions into one.\n     * If `h` is remapped, split one unmapped region into two.\n     */\n    return IS_MAPPED(hhdr) ? -1 : 1;\n  }\n  if (!prev_unmapped && !next_unmapped) {\n    /*\n     * If `h` is unmapped, create an isolated unmapped region.\n     * If `h` is remapped, remove it.\n     */\n    return IS_MAPPED(hhdr) ? 1 : -1;\n  }\n  /*\n   * If `h` is unmapped, merge it with previous or next unmapped region.\n   * If `h` is remapped, reduce either previous or next unmapped region.\n   * In either way, no change to the number of unmapped regions.\n   */\n  return 0;\n}\n#  endif /* COUNT_UNMAPPED_REGIONS */\n\n/*\n * Update `GC_num_unmapped_regions` assuming the block `h` changes from\n * its current state of mapped/unmapped to the opposite state.\n */\nGC_INLINE void\nGC_adjust_num_unmapped(struct hblk *h, hdr *hhdr)\n{\n#  ifdef COUNT_UNMAPPED_REGIONS\n  GC_num_unmapped_regions += calc_num_unmapped_regions_delta(h, hhdr);\n#  else\n  UNUSED_ARG(h);\n  UNUSED_ARG(hhdr);\n#  endif\n}\n\nGC_INNER void\nGC_unmap_old(unsigned threshold)\n{\n  size_t i;\n\n#  ifdef COUNT_UNMAPPED_REGIONS\n  /*\n   * Skip unmapping if we have already exceeded the soft limit.\n   * This forgoes any opportunities to merge unmapped regions though.\n   */\n  if (GC_num_unmapped_regions >= GC_UNMAPPED_REGIONS_SOFT_LIMIT)\n    return;\n#  endif\n\n  for (i = 0; i <= N_HBLK_FLS; ++i) {\n    struct hblk *h;\n    hdr *hhdr;\n\n    for (h = GC_hblkfreelist[i]; h != NULL; h = hhdr->hb_next) {\n      hhdr = HDR(h);\n      if (!IS_MAPPED(hhdr))\n        continue;\n\n      /*\n       * Check that the interval is not smaller than the `threshold`.\n       * The truncated counter value wrapping is handled correctly.\n       */\n      if ((unsigned short)(GC_gc_no - hhdr->hb_last_reclaimed)\n          >= (unsigned short)threshold) {\n#  ifdef COUNT_UNMAPPED_REGIONS\n        /*\n         * Continue with unmapping the block only if it will not create\n         * too many unmapped regions, or if unmapping reduces the number\n         * of regions.\n         */\n        int delta = calc_num_unmapped_regions_delta(h, hhdr);\n        GC_signed_word regions = GC_num_unmapped_regions + delta;\n\n        if (delta >= 0 && regions >= GC_UNMAPPED_REGIONS_SOFT_LIMIT) {\n          GC_COND_LOG_PRINTF(\"Unmapped regions limit reached!\\n\");\n          return;\n        }\n        GC_num_unmapped_regions = regions;\n#  endif\n        GC_unmap((ptr_t)h, hhdr->hb_sz);\n        hhdr->hb_flags |= WAS_UNMAPPED;\n      }\n    }\n  }\n}\n\nGC_INNER GC_bool\nGC_merge_unmapped(void)\n{\n  size_t i;\n  GC_bool merged = FALSE;\n\n  for (i = 0; i <= N_HBLK_FLS; ++i) {\n    struct hblk *h = GC_hblkfreelist[i];\n\n    while (h != NULL) {\n      struct hblk *next;\n      hdr *hhdr, *nexthdr;\n      size_t size, next_size;\n\n      GET_HDR(h, hhdr);\n      size = hhdr->hb_sz;\n      next = (struct hblk *)((ptr_t)h + size);\n      GET_HDR(next, nexthdr);\n      /* Coalesce with successor, if possible. */\n      if (NULL == nexthdr || !HBLK_IS_FREE(nexthdr)\n          || BLOCKS_MERGE_OVERFLOW(hhdr, nexthdr)) {\n        /* Not mergeable with the successor. */\n        h = hhdr->hb_next;\n        continue;\n      }\n\n      next_size = nexthdr->hb_sz;\n#  ifdef CHERI_PURECAP\n      /* FIXME: Coalesce with super-capability. */\n      if (!CAPABILITY_COVERS_RANGE(h, ADDR(next), ADDR(next) + nextsize)) {\n        h = hhdr->hb_next;\n        continue;\n      }\n#  endif\n\n      /*\n       * Note that we usually try to avoid adjacent free blocks that are\n       * either both mapped or both unmapped.  But that is not guaranteed\n       * to hold since we remap blocks when we split them, and do not merge\n       * at that point.  It may also not hold if the merged block would be\n       * too big.\n       */\n      if (IS_MAPPED(hhdr) && !IS_MAPPED(nexthdr)) {\n        /* Make both consistent, so that we can merge. */\n        if (size > next_size) {\n          GC_adjust_num_unmapped(next, nexthdr);\n          GC_remap((ptr_t)next, next_size);\n        } else {\n          GC_adjust_num_unmapped(h, hhdr);\n          GC_unmap((ptr_t)h, size);\n          GC_unmap_gap((ptr_t)h, size, (ptr_t)next, next_size);\n          hhdr->hb_flags |= WAS_UNMAPPED;\n        }\n      } else if (IS_MAPPED(nexthdr) && !IS_MAPPED(hhdr)) {\n        if (size > next_size) {\n          GC_adjust_num_unmapped(next, nexthdr);\n          GC_unmap((ptr_t)next, next_size);\n          GC_unmap_gap((ptr_t)h, size, (ptr_t)next, next_size);\n        } else {\n          GC_adjust_num_unmapped(h, hhdr);\n          GC_remap((ptr_t)h, size);\n          hhdr->hb_flags &= (unsigned char)~WAS_UNMAPPED;\n          hhdr->hb_last_reclaimed = nexthdr->hb_last_reclaimed;\n        }\n      } else if (!IS_MAPPED(hhdr) && !IS_MAPPED(nexthdr)) {\n        /* Unmap any gap in the middle. */\n        GC_unmap_gap((ptr_t)h, size, (ptr_t)next, next_size);\n      }\n      /* If they are both unmapped, we merge, but leave unmapped. */\n      GC_remove_from_fl_at(hhdr, i);\n      GC_remove_from_fl(nexthdr);\n      hhdr->hb_sz += nexthdr->hb_sz;\n      GC_remove_header(next);\n      GC_add_to_fl(h, hhdr);\n      merged = TRUE;\n      /* Start over at the beginning of list. */\n      h = GC_hblkfreelist[i];\n    }\n  }\n  return merged;\n}\n\n#endif /* USE_MUNMAP */\n\n/*\n * Return a pointer to a block starting at `h`.  Memory for the block\n * is mapped.  Remove the block from its free list, and return the\n * remainder (if any) to its appropriate free list.  May fail by\n * returning `NULL`.  The header for the returned block must be set up\n * by the caller.  If the returned pointer is not `NULL`, then `hhdr`\n * is the header for it.\n */\nSTATIC struct hblk *\nGC_get_first_part(struct hblk *h, hdr *hhdr, size_t size_needed, size_t index)\n{\n  size_t total_size;\n  struct hblk *rest;\n  hdr *rest_hdr;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(modHBLKSZ(size_needed) == 0);\n  total_size = hhdr->hb_sz;\n  GC_ASSERT(modHBLKSZ(total_size) == 0);\n  GC_remove_from_fl_at(hhdr, index);\n  if (total_size == size_needed)\n    return h;\n\n  rest = (struct hblk *)((ptr_t)h + size_needed);\n  rest_hdr = GC_install_header(rest);\n  if (UNLIKELY(NULL == rest_hdr)) {\n    /* FIXME: This is likely to be very bad news... */\n    WARN(\"Header allocation failed: dropping block\\n\", 0);\n    return NULL;\n  }\n  rest_hdr->hb_block = rest;\n  rest_hdr->hb_sz = total_size - size_needed;\n  rest_hdr->hb_flags = 0;\n#ifdef GC_ASSERTIONS\n  /* Mark `h` as non-free, to avoid assertion about adjacent free blocks. */\n  hhdr->hb_flags &= (unsigned char)~FREE_BLK;\n#endif\n  GC_add_to_fl(rest, rest_hdr);\n  return h;\n}\n\n/*\n * Split the block.  `hbp` is a free block; `last_hbp` points at address\n * inside it; a new header for `last_hbp` is assumed to be already set up.\n * Fix up the header of `hbp` to reflect the fact that it is being split,\n * move it to the appropriate free list.  `last_hbp` replaces `hbp` in the\n * original free list.  `last_hdr` is not completely filled in, since it\n * is about to be allocated.  It may, in fact, end up on the wrong free\n * list for its size.  That is not a disaster, since `last_hbp` is to be\n * allocated by our caller.  (Hence adding it to a free list is silly.\n * But this path is hopefully rare enough that it does not matter.\n * The code is cleaner this way.)\n */\nSTATIC void\nGC_split_block(struct hblk *hbp, hdr *hhdr, struct hblk *last_hbp,\n               hdr *last_hdr, size_t index /* of free list */)\n{\n  size_t h_size = (size_t)((ptr_t)last_hbp - (ptr_t)hbp);\n  struct hblk *prev = hhdr->hb_prev;\n  struct hblk *next = hhdr->hb_next;\n\n  /* Replace `hbp` with `last_hbp` on its free list. */\n  last_hdr->hb_prev = prev;\n  last_hdr->hb_next = next;\n  last_hdr->hb_block = last_hbp;\n  last_hdr->hb_sz = hhdr->hb_sz - h_size;\n  last_hdr->hb_flags = 0;\n  if (prev /* `!= NULL` */) { /*< CPPCHECK */\n    HDR(prev)->hb_next = last_hbp;\n  } else {\n    GC_hblkfreelist[index] = last_hbp;\n  }\n  if (next /* `!= NULL` */) {\n    HDR(next)->hb_prev = last_hbp;\n  }\n  GC_ASSERT(GC_free_bytes[index] > h_size);\n  GC_free_bytes[index] -= h_size;\n#ifdef USE_MUNMAP\n  hhdr->hb_last_reclaimed = (unsigned short)GC_gc_no;\n#endif\n  hhdr->hb_sz = h_size;\n  GC_add_to_fl(hbp, hhdr);\n  last_hdr->hb_flags |= FREE_BLK;\n}\n\nSTATIC struct hblk *GC_allochblk_nth(size_t lb_adjusted, int kind,\n                                     unsigned flags, size_t index,\n                                     int may_split, size_t align_m1);\n\n#ifdef USE_MUNMAP\n#  define AVOID_SPLIT_REMAPPED 2\n#endif\n\nGC_INNER struct hblk *\nGC_allochblk(size_t lb_adjusted, int kind,\n             unsigned flags /* `IGNORE_OFF_PAGE` or 0 */, size_t align_m1)\n{\n  size_t blocks, start_list;\n  struct hblk *result;\n  int may_split;\n  size_t split_limit; /* highest index of free list whose blocks we split */\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT((lb_adjusted & (GC_GRANULE_BYTES - 1)) == 0);\n  blocks = OBJ_SZ_TO_BLOCKS_CHECKED(lb_adjusted);\n  if (UNLIKELY(SIZET_SAT_ADD(blocks * HBLKSIZE, align_m1)\n               >= (GC_SIZE_MAX >> 1)))\n    return NULL; /* overflow */\n\n  start_list = GC_hblk_fl_from_blocks(blocks);\n  /* Try for an exact match first. */\n  result = GC_allochblk_nth(lb_adjusted, kind, flags, start_list, FALSE,\n                            align_m1);\n  if (result != NULL)\n    return result;\n\n  may_split = TRUE;\n  if (GC_use_entire_heap || GC_dont_gc\n      || GC_heapsize - GC_large_free_bytes < GC_requested_heapsize\n      || GC_incremental || !GC_should_collect()) {\n    /* Should use more of the heap, even if it requires splitting. */\n    split_limit = N_HBLK_FLS;\n  } else if (GC_finalizer_bytes_freed > (GC_heapsize >> 4)) {\n    /*\n     * If we are deallocating lots of memory from finalizers, then fail\n     * and collect sooner rather than later.\n     */\n    split_limit = 0;\n  } else {\n    /*\n     * If we have enough large blocks left to cover any previous request\n     * for large blocks, we go ahead and split.  Assuming a steady state,\n     * that should be safe.  It means that we can use the full heap\n     * if we allocate only small objects.\n     */\n    split_limit = GC_enough_large_bytes_left();\n#ifdef USE_MUNMAP\n    if (split_limit > 0)\n      may_split = AVOID_SPLIT_REMAPPED;\n#endif\n  }\n  if (start_list < UNIQUE_THRESHOLD && 0 == align_m1) {\n    /*\n     * No reason to try `start_list` again, since all blocks are exact\n     * matches.\n     */\n    ++start_list;\n  }\n  for (; start_list <= split_limit; ++start_list) {\n    result = GC_allochblk_nth(lb_adjusted, kind, flags, start_list, may_split,\n                              align_m1);\n    if (result != NULL)\n      break;\n  }\n  return result;\n}\n\n#define ALIGN_PAD_SZ(p, align_m1) \\\n  (((align_m1) + 1 - (size_t)ADDR(p)) & (align_m1))\n\nstatic GC_bool\nnext_hblk_fits_better(const hdr *hhdr, size_t size_avail, size_t size_needed,\n                      size_t align_m1)\n{\n  const hdr *nexthdr;\n  size_t next_size;\n  size_t next_ofs;\n  struct hblk *next_hbp = hhdr->hb_next;\n\n  if (NULL == next_hbp)\n    return FALSE; /*< no next block */\n  GET_HDR(next_hbp, nexthdr);\n  next_size = nexthdr->hb_sz;\n  if (size_avail <= next_size)\n    return FALSE; /*< not enough size */\n\n  next_ofs = ALIGN_PAD_SZ(next_hbp, align_m1);\n  return next_size >= size_needed + next_ofs\n#ifndef NO_BLACK_LISTING\n         && !GC_is_black_listed(next_hbp + divHBLKSZ(next_ofs), size_needed)\n#endif\n      ;\n}\n\nstatic struct hblk *\nfind_nonbl_hblk(struct hblk *last_hbp, size_t size_remain,\n                size_t eff_size_needed, size_t align_m1)\n{\n#ifdef NO_BLACK_LISTING\n  UNUSED_ARG(size_remain);\n  UNUSED_ARG(eff_size_needed);\n  return last_hbp + divHBLKSZ(ALIGN_PAD_SZ(last_hbp, align_m1));\n#else\n  ptr_t search_end\n      = PTR_ALIGN_DOWN((ptr_t)last_hbp + size_remain, align_m1 + 1);\n\n  do {\n    struct hblk *next_hbp;\n\n    last_hbp += divHBLKSZ(ALIGN_PAD_SZ(last_hbp, align_m1));\n    next_hbp = GC_is_black_listed(last_hbp, eff_size_needed);\n    if (NULL == next_hbp)\n      return last_hbp; /*< not black-listed */\n    last_hbp = next_hbp;\n  } while (ADDR_GE(search_end, (ptr_t)last_hbp));\n  return NULL;\n#endif\n}\n\n#ifndef NO_BLACK_LISTING\n/*\n * Allocate and drop the block in small chunks, to maximize the chance\n * that we will recover some later.  `hhdr` should correspond to `hbp`.\n */\nstatic void\ndrop_hblk_in_chunks(size_t n, struct hblk *hbp, hdr *hhdr)\n{\n  size_t total_size = hhdr->hb_sz;\n  const struct hblk *limit = hbp + divHBLKSZ(total_size);\n\n  GC_ASSERT(HDR(hbp) == hhdr);\n  GC_ASSERT(modHBLKSZ(total_size) == 0 && total_size > 0);\n  GC_large_free_bytes -= total_size;\n  GC_bytes_dropped += total_size;\n  GC_remove_from_fl_at(hhdr, n);\n  do {\n    (void)setup_header(hhdr, hbp, HBLKSIZE, PTRFREE, 0); /*< cannot fail */\n    if (GC_debugging_started)\n      BZERO(hbp, HBLKSIZE);\n    hbp++;\n    if (ADDR_GE(hbp, limit))\n      break;\n\n    hhdr = GC_install_header(hbp);\n  } while (LIKELY(hhdr != NULL)); /*< no header allocation failure? */\n}\n#endif /* !NO_BLACK_LISTING */\n\n#if defined(MPROTECT_VDB) && defined(DONT_PROTECT_PTRFREE)\nstatic GC_bool\nis_hblks_mix_in_page(struct hblk *hbp, GC_bool is_ptrfree)\n{\n  struct hblk *h = HBLK_PAGE_ALIGNED(hbp);\n  size_t i, cnt = divHBLKSZ(GC_page_size);\n\n  /*\n   * Iterate over blocks in the page to check if all the occupied blocks\n   * are pointer-free if we are going to allocate a pointer-free one,\n   * and vice versa.\n   */\n  for (i = 0; i < cnt; i++) {\n    hdr *hhdr;\n\n    GET_HDR(&h[i], hhdr);\n    if (NULL == hhdr)\n      continue;\n    (void)GC_find_starting_hblk(&h[i], &hhdr);\n    if (!HBLK_IS_FREE(hhdr)) {\n      /* It is OK to check only the first found occupied block. */\n      return IS_PTRFREE(hhdr) != is_ptrfree;\n    }\n  }\n  /* All blocks are free. */\n  return FALSE;\n}\n#endif /* MPROTECT_VDB && DONT_PROTECT_PTRFREE */\n\n/*\n * The same as `GC_allochblk`, but with search restricted to the\n * `index`-th free list.  `flags` should be `IGNORE_OFF_PAGE` or zero;\n * `may_split` indicates whether it is OK to split larger blocks; size\n * `lb_adjusted` is in bytes.  If `may_split` is set to\n * `AVOID_SPLIT_REMAPPED`, then memory remapping followed by splitting\n * should be generally avoided.  Rounded-up `lb_adjusted` plus\n * `align_m1` value should be less than `GC_SIZE_MAX / 2`.\n */\nSTATIC struct hblk *\nGC_allochblk_nth(size_t lb_adjusted, int kind, unsigned flags, size_t index,\n                 int may_split, size_t align_m1)\n{\n  struct hblk *hbp, *last_hbp;\n  /* The header corresponding to `hbp`. */\n  hdr *hhdr;\n  /* Number of bytes in requested objects. */\n  size_t size_needed = (lb_adjusted + HBLKSIZE - 1) & ~(HBLKSIZE - 1);\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(((align_m1 + 1) & align_m1) == 0 && lb_adjusted > 0);\n  GC_ASSERT(0 == align_m1 || modHBLKSZ(align_m1 + 1) == 0);\n#ifndef NO_BLACK_LISTING\nretry:\n#endif\n  /* Search for a big enough block in free list. */\n  for (hbp = GC_hblkfreelist[index];; hbp = hhdr->hb_next) {\n    size_t size_avail; /*< bytes available in this block */\n    size_t align_ofs;\n\n    if (hbp /* `!= NULL` */) {\n      /* CPPCHECK */\n    } else {\n      return NULL;\n    }\n    GET_HDR(hbp, hhdr); /*< set `hhdr` value */\n    size_avail = hhdr->hb_sz;\n    if (!may_split && size_avail != size_needed)\n      continue;\n\n    align_ofs = ALIGN_PAD_SZ(hbp, align_m1);\n    if (size_avail < size_needed + align_ofs)\n      continue; /*< the block is too small */\n\n    if (size_avail != size_needed) {\n      /*\n       * If the next heap block is obviously better, go on.\n       * This prevents us from disassembling a single large block to get\n       * tiny blocks.\n       */\n      if (next_hblk_fits_better(hhdr, size_avail, size_needed, align_m1))\n        continue;\n    }\n\n#if defined(MPROTECT_VDB) && defined(DONT_PROTECT_PTRFREE)\n    /*\n     * Avoid write-protecting pointer-free blocks (only the case\n     * if page size is larger than the block size).\n     */\n    GC_ASSERT(GC_page_size != 0);\n    if (GC_page_size != HBLKSIZE\n        && (!GC_incremental /*< not enabled yet */\n            || GC_incremental_protection_needs() != GC_PROTECTS_NONE)\n        && is_hblks_mix_in_page(hbp, kind == PTRFREE))\n      continue;\n#endif\n\n    if (IS_UNCOLLECTABLE(kind)\n        || (kind == PTRFREE && size_needed <= MAX_BLACK_LIST_ALLOC)) {\n      last_hbp = hbp + divHBLKSZ(align_ofs);\n      break;\n    }\n\n    last_hbp = find_nonbl_hblk(\n        hbp, size_avail - size_needed,\n        (flags & IGNORE_OFF_PAGE) != 0 ? HBLKSIZE : size_needed, align_m1);\n    /* Is non-black-listed part of enough size? */\n    if (last_hbp != NULL) {\n#ifdef USE_MUNMAP\n      /* Avoid remapping followed by splitting. */\n      if (may_split == AVOID_SPLIT_REMAPPED && last_hbp != hbp\n          && !IS_MAPPED(hhdr))\n        continue;\n#endif\n      break;\n    }\n\n#ifndef NO_BLACK_LISTING\n    /*\n     * The block is completely black-listed.  If so, we need to\n     * drop some such blocks, since otherwise we spend all our\n     * time traversing them if pointer-free blocks are unpopular.\n     * A dropped block will be reconsidered at next collection.\n     */\n    if (size_needed == HBLKSIZE && 0 == align_m1 && !GC_find_leak_inner\n        && IS_MAPPED(hhdr) && (++GC_drop_blacklisted_count & 3) == 0) {\n      const struct hblk *prev = hhdr->hb_prev;\n\n      drop_hblk_in_chunks(index, hbp, hhdr);\n      if (NULL == prev)\n        goto retry;\n      /* Restore `hhdr` to point at free block. */\n      hhdr = HDR(prev);\n      continue;\n    }\n\n    if (size_needed > BL_LIMIT && size_avail - size_needed > BL_LIMIT) {\n      /* Punt, since anything else risks unreasonable heap growth. */\n      if (++GC_large_alloc_warn_suppressed >= GC_large_alloc_warn_interval) {\n        WARN(\"Repeated allocation of very large block\"\n             \" (appr. size %\" WARN_PRIuPTR \" KiB):\\n\"\n             \"\\tMay lead to memory leak and poor performance\\n\",\n             size_needed >> 10);\n        GC_large_alloc_warn_suppressed = 0;\n      }\n      last_hbp = hbp + divHBLKSZ(align_ofs);\n      break;\n    }\n#endif\n  }\n\n  GC_ASSERT((ADDR(last_hbp) & align_m1) == 0);\n  if (last_hbp != hbp) {\n    hdr *last_hdr = GC_install_header(last_hbp);\n\n    if (UNLIKELY(NULL == last_hdr))\n      return NULL;\n#ifdef USE_MUNMAP\n    /* Make sure it is mapped before we mangle it. */\n    if (!IS_MAPPED(hhdr)) {\n      GC_adjust_num_unmapped(hbp, hhdr);\n      GC_remap((ptr_t)hbp, hhdr->hb_sz);\n      hhdr->hb_flags &= (unsigned char)~WAS_UNMAPPED;\n    }\n#endif\n    /* Split the block at `last_hbp`. */\n    GC_split_block(hbp, hhdr, last_hbp, last_hdr, index);\n    /*\n     * We must now allocate `last_hbp`, since it may be on the wrong\n     * free list.\n     */\n    hbp = last_hbp;\n    hhdr = last_hdr;\n  }\n  GC_ASSERT(hhdr->hb_sz >= size_needed);\n\n#ifdef USE_MUNMAP\n  if (!IS_MAPPED(hhdr)) {\n    GC_adjust_num_unmapped(hbp, hhdr);\n    GC_remap((ptr_t)hbp, hhdr->hb_sz);\n    hhdr->hb_flags &= (unsigned char)~WAS_UNMAPPED;\n    /* Note: this may leave adjacent, mapped free blocks. */\n  }\n#endif\n  /*\n   * `hbp` may be on the wrong free list; the parameter `index` is\n   * important.\n   */\n  hbp = GC_get_first_part(hbp, hhdr, size_needed, index);\n  if (UNLIKELY(NULL == hbp))\n    return NULL;\n\n  /* Add it to map of valid blocks. */\n  if (UNLIKELY(!GC_install_counts(hbp, size_needed)))\n    return NULL; /*< note: this leaks memory under very rare conditions */\n\n  /* Set up the header. */\n  GC_ASSERT(HDR(hbp) == hhdr);\n#ifdef MARK_BIT_PER_OBJ\n  (void)setup_header(hhdr, hbp, lb_adjusted, kind, flags);\n  /* Result is always `TRUE`, not checked to avoid a cppcheck warning. */\n#else\n  if (UNLIKELY(!setup_header(hhdr, hbp, lb_adjusted, kind, flags))) {\n    GC_remove_counts(hbp, size_needed);\n    return NULL; /*< ditto */\n  }\n#endif\n\n#ifndef GC_DISABLE_INCREMENTAL\n  /*\n   * Notify virtual dirty bit implementation that we are about to write.\n   * Ensure that pointer-free objects are not protected if it is avoidable.\n   * This also ensures that newly allocated blocks are treated as\n   * dirty - it is necessary since we do not protect free blocks.\n   */\n  GC_ASSERT(modHBLKSZ(size_needed) == 0);\n  GC_remove_protection(hbp, divHBLKSZ(size_needed), IS_PTRFREE(hhdr));\n#endif\n  /*\n   * We just successfully allocated a block.  Restart count of consecutive\n   * failures.\n   */\n  GC_alloc_fail_count = 0;\n\n  GC_large_free_bytes -= size_needed;\n  GC_ASSERT(IS_MAPPED(hhdr));\n  return hbp;\n}\n\n#ifdef VALGRIND_TRACKING\n/*\n * Note: this is intentionally defined in a file other than `malloc.c`\n * and `reclaim.c` files.\n */\nGC_ATTR_NOINLINE\nGC_API void GC_CALLBACK\nGC_free_profiler_hook(void *p)\n{\n#  ifndef PARALLEL_MARK\n  GC_ASSERT(I_HOLD_LOCK());\n#  endif\n  /* Prevent treating this function by the compiler as a no-op one. */\n  GC_noop1_ptr(p);\n}\n#endif /* VALGRIND_TRACKING */\n\nGC_INNER void\nGC_freehblk(struct hblk *hbp)\n{\n  struct hblk *next, *prev;\n  hdr *hhdr, *prevhdr, *nexthdr;\n  size_t size;\n\n  GET_HDR(hbp, hhdr);\n  size = HBLKSIZE * OBJ_SZ_TO_BLOCKS(hhdr->hb_sz);\n  if ((size & SIZET_SIGNB) != 0) {\n    /*\n     * Probably possible if we try to allocate more than half the address\n     * space at once.  If we do not catch it here, strange things happen\n     * later.\n     */\n    ABORT(\"Deallocating excessively large block.  Too large an allocation?\");\n  }\n  GC_remove_counts(hbp, size);\n  hhdr->hb_sz = size;\n#ifdef USE_MUNMAP\n  hhdr->hb_last_reclaimed = (unsigned short)GC_gc_no;\n#endif\n\n  /* Check for duplicate deallocation in the easy case. */\n  if (HBLK_IS_FREE(hhdr)) {\n    ABORT_ARG1(\"Duplicate large block deallocation\", \" of %p\", (void *)hbp);\n  }\n\n  GC_ASSERT(IS_MAPPED(hhdr));\n  hhdr->hb_flags |= FREE_BLK;\n  next = (struct hblk *)((ptr_t)hbp + size);\n  GET_HDR(next, nexthdr);\n  prev = GC_free_block_ending_at(hbp);\n  /* Coalesce with successor, if possible. */\n  if (nexthdr != NULL && HBLK_IS_FREE(nexthdr)\n      && IS_MAPPED(nexthdr)\n#ifdef CHERI_PURECAP\n      /* FIXME: Coalesce with super-capability. */\n      /*\n       * Bounds of capability should span the entire coalesced memory;\n       * bounds being larger than the block size is OK; bounded by the\n       * imprecision of original capability obtained from system memory.\n       */\n      && CAPABILITY_COVERS_RANGE(hbp, ADDR(next), ADDR(next) + nexthdr->hb_sz)\n#endif\n      && !BLOCKS_MERGE_OVERFLOW(hhdr, nexthdr)) {\n    GC_remove_from_fl(nexthdr);\n    hhdr->hb_sz += nexthdr->hb_sz;\n    GC_remove_header(next);\n  }\n\n  /* Coalesce with predecessor, if possible. */\n  if (prev /* `!= NULL` */) { /*< CPPCHECK */\n    prevhdr = HDR(prev);\n    if (IS_MAPPED(prevhdr)\n#ifdef CHERI_PURECAP\n        /* FIXME: Coalesce with super-capability. */\n        && cheri_base_get(hbp) <= ADDR(prev)\n#endif\n        && !BLOCKS_MERGE_OVERFLOW(prevhdr, hhdr)) {\n      GC_remove_from_fl(prevhdr);\n      prevhdr->hb_sz += hhdr->hb_sz;\n#ifdef USE_MUNMAP\n      prevhdr->hb_last_reclaimed = (unsigned short)GC_gc_no;\n#endif\n      GC_remove_header(hbp);\n      hbp = prev;\n      hhdr = prevhdr;\n    }\n  }\n  /*\n   * FIXME: It is not clear if we really always want to do these merges\n   * with `USE_MUNMAP`, since it updates ages and hence prevents unmapping.\n   */\n\n  GC_large_free_bytes += size;\n  GC_add_to_fl(hbp, hhdr);\n}\n\n/*\n * Copyright (c) 1988-1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1996 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999-2011 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n/*\n * Separate free lists are maintained for different sized objects up\n * to `MAXOBJBYTES`.\n * The call `GC_allocobj(lg, kind)` ensures that the free list for the given\n * kind of objects of the given size in granules is a nonempty one.\n * It returns a pointer to the first entry on the free list.\n * In a single-threaded world, `GC_allocobj` may be called to allocate\n * an object of small size `lb` (and `NORMAL` kind) as follows\n * (`GC_generic_malloc_inner` is a wrapper over `GC_allocobj` which also\n * fills in `GC_size_map` if needed):\n *\n * ```\n *   lg = GC_size_map[lb];\n *   op = GC_objfreelist[lg];\n *   if (NULL == op) {\n *     op = GC_generic_malloc_inner(lb, NORMAL, 0);\n *   } else {\n *     GC_objfreelist[lg] = obj_link(op);\n *     GC_bytes_allocd += GRANULES_TO_BYTES((word)lg);\n *   }\n * ```\n *\n * Note that this is very fast if the free list is not empty; it should\n * only involve the execution of 4 or 5 simple instructions.\n * All composite objects on freelists are cleared, except for\n * their first \"pointer-sized\" word.\n */\n\n/*\n * The allocator uses `GC_allochblk` to allocate large chunks of objects.\n * These chunks all start on addresses that are multiples of `HBLKSIZE`.\n * Each allocated chunk has an associated header, which can be located\n * quickly based on the address of the chunk.  This makes it possible\n * to check quickly whether an arbitrary address corresponds to an object\n * administered by the allocator.  (See `headers.c` file for details.)\n */\n\n/* Number of bytes not intended to be collected. */\nword GC_non_gc_bytes = 0;\n\nword GC_gc_no = 0;\n\n#ifndef NO_CLOCK\n\nGC_API void GC_CALL\nGC_start_performance_measurement(void)\n{\n  GC_measure_performance = TRUE;\n}\n\nGC_API unsigned long GC_CALL\nGC_get_full_gc_total_time(void)\n{\n  return GC_full_gc_total_time;\n}\n\nGC_API unsigned long GC_CALL\nGC_get_stopped_mark_total_time(void)\n{\n  return GC_stopped_mark_total_time;\n}\n\n#  ifndef MAX_TOTAL_TIME_DIVISOR\n/*\n * We shall not use big values here (so \"outdated\" delay time values would\n * have less impact on \"average\" delay time value than newer ones).\n */\n#    define MAX_TOTAL_TIME_DIVISOR 1000\n#  endif\n\nGC_API unsigned long GC_CALL\nGC_get_avg_stopped_mark_time_ns(void)\n{\n  unsigned long total_time;\n  unsigned divisor;\n\n  READER_LOCK();\n  total_time = (unsigned long)GC_world_stopped_total_time;\n  divisor = GC_world_stopped_total_divisor;\n  READER_UNLOCK();\n  if (0 == divisor) {\n    GC_ASSERT(0 == total_time);\n    /*\n     * No world-stopped collection has occurred since the start of\n     * performance measurements.\n     */\n    return 0;\n  }\n\n  /* Halve values to prevent overflow during the multiplication. */\n  for (; total_time > ~0UL / (1000UL * 1000); total_time >>= 1) {\n    divisor >>= 1;\n    if (UNLIKELY(0 == divisor)) {\n      /* The actual result is larger than representable value. */\n      return ~0UL;\n    }\n  }\n\n  return total_time * (1000UL * 1000) / divisor;\n}\n\n#endif /* !NO_CLOCK */\n\n#ifndef GC_DISABLE_INCREMENTAL\nGC_INNER GC_bool GC_incremental = FALSE; /*< by default, stop the world */\n#endif\n\nGC_API int GC_CALL\nGC_is_incremental_mode(void)\n{\n  return (int)GC_incremental;\n}\n\n#ifdef THREADS\nint GC_parallel = FALSE; /*< parallel collection is off by default */\n#endif\n\n#if defined(GC_FULL_FREQ) && !defined(CPPCHECK)\nint GC_full_freq = GC_FULL_FREQ;\n#else\n/*\n * Every `GC_full_freq + 1` collection is a full collection, whether we\n * need it or not.\n */\nint GC_full_freq = 19;\n#endif\n\n#ifdef THREAD_LOCAL_ALLOC\nGC_INNER GC_bool GC_world_stopped = FALSE;\n#endif\n\nSTATIC GC_bool GC_disable_automatic_collection = FALSE;\n\nGC_API void GC_CALL\nGC_set_disable_automatic_collection(int value)\n{\n  LOCK();\n  GC_disable_automatic_collection = (GC_bool)value;\n  UNLOCK();\n}\n\nGC_API int GC_CALL\nGC_get_disable_automatic_collection(void)\n{\n  int value;\n\n  READER_LOCK();\n  value = (int)GC_disable_automatic_collection;\n  READER_UNLOCK();\n  return value;\n}\n\n/*\n * The version macros are now defined in `gc_version.h` file, which is\n * included by `gc.h` file, which, in turn, is included by `gc_priv.h` file.\n */\n#ifndef GC_NO_VERSION_VAR\nEXTERN_C_BEGIN\nextern const GC_VERSION_VAL_T GC_version;\nEXTERN_C_END\n\nconst GC_VERSION_VAL_T GC_version = ((GC_VERSION_VAL_T)GC_VERSION_MAJOR << 16)\n                                    | (GC_VERSION_MINOR << 8)\n                                    | GC_VERSION_MICRO;\n#endif\n\nGC_API GC_VERSION_VAL_T GC_CALL\nGC_get_version(void)\n{\n  return ((GC_VERSION_VAL_T)GC_VERSION_MAJOR << 16) | (GC_VERSION_MINOR << 8)\n         | GC_VERSION_MICRO;\n}\n\nGC_API int GC_CALL\nGC_get_dont_add_byte_at_end(void)\n{\n#ifdef DONT_ADD_BYTE_AT_END\n  return 1;\n#else\n  /* This is meaningful only if `GC_all_interior_pointers`. */\n  return 0;\n#endif\n}\n\n/* Some more variables. */\n\n#ifdef GC_DONT_EXPAND\nint GC_dont_expand = TRUE;\n#else\nint GC_dont_expand = FALSE;\n#endif\n\n#if defined(GC_FREE_SPACE_DIVISOR) && !defined(CPPCHECK)\nword GC_free_space_divisor = GC_FREE_SPACE_DIVISOR; /*< must be positive */\n#else\nword GC_free_space_divisor = 3;\n#endif\n\nGC_INNER int GC_CALLBACK\nGC_never_stop_func(void)\n{\n  return FALSE;\n}\n\n#if defined(GC_TIME_LIMIT) && !defined(CPPCHECK)\n/*\n * We try to keep pause times from exceeding this by much.\n * In milliseconds.\n */\nunsigned long GC_time_limit = GC_TIME_LIMIT;\n#elif defined(PARALLEL_MARK)\n/*\n * The parallel marker cannot be interrupted for now, so the time limit\n * is absent by default.\n */\nunsigned long GC_time_limit = GC_TIME_UNLIMITED;\n#else\nunsigned long GC_time_limit = 15;\n#endif\n\n#ifndef NO_CLOCK\n/*\n * The nanoseconds add-on to `GC_time_limit` value.\n * Not updated by `GC_set_time_limit()`.\n * Ignored if the value of `GC_time_limit` is `GC_TIME_UNLIMITED`.\n */\nSTATIC unsigned long GC_time_lim_nsec = 0;\n\n#  define TV_NSEC_LIMIT (1000UL * 1000) /*< amount of nanoseconds in 1 ms */\n\nGC_API void GC_CALL\nGC_set_time_limit_tv(struct GC_timeval_s tv)\n{\n  GC_ASSERT(tv.tv_ms <= GC_TIME_UNLIMITED);\n  GC_ASSERT(tv.tv_nsec < TV_NSEC_LIMIT);\n  GC_time_limit = tv.tv_ms;\n  GC_time_lim_nsec = tv.tv_nsec;\n}\n\nGC_API struct GC_timeval_s GC_CALL\nGC_get_time_limit_tv(void)\n{\n  struct GC_timeval_s tv;\n\n  tv.tv_ms = GC_time_limit;\n  tv.tv_nsec = GC_time_lim_nsec;\n  return tv;\n}\n\n/* Time at which we stopped world.  Used only by `GC_timeout_stop_func()`. */\nSTATIC CLOCK_TYPE GC_start_time = CLOCK_TYPE_INITIALIZER;\n#endif /* !NO_CLOCK */\n\n/* Number of attempts at finishing collection within `GC_time_limit`. */\nSTATIC int GC_n_attempts = 0;\n\n/* Note: accessed holding the allocator lock. */\nSTATIC GC_stop_func GC_default_stop_func = GC_never_stop_func;\n\nGC_API void GC_CALL\nGC_set_stop_func(GC_stop_func stop_func)\n{\n  GC_ASSERT(NONNULL_ARG_NOT_NULL(stop_func));\n  LOCK();\n  GC_default_stop_func = stop_func;\n  UNLOCK();\n}\n\nGC_API GC_stop_func GC_CALL\nGC_get_stop_func(void)\n{\n  GC_stop_func stop_func;\n\n  READER_LOCK();\n  stop_func = GC_default_stop_func;\n  READER_UNLOCK();\n  return stop_func;\n}\n\n#if defined(GC_DISABLE_INCREMENTAL) || defined(NO_CLOCK)\n#  define GC_timeout_stop_func GC_default_stop_func\n#else\nSTATIC int GC_CALLBACK\nGC_timeout_stop_func(void)\n{\n  CLOCK_TYPE current_time;\n  static unsigned count = 0;\n  unsigned long time_diff, nsec_diff;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (GC_default_stop_func())\n    return TRUE;\n\n  if (GC_time_limit == GC_TIME_UNLIMITED || (count++ & 3) != 0)\n    return FALSE;\n\n  GET_TIME(current_time);\n  time_diff = MS_TIME_DIFF(current_time, GC_start_time);\n  nsec_diff = NS_FRAC_TIME_DIFF(current_time, GC_start_time);\n#  if defined(CPPCHECK)\n  GC_noop1_ptr(&nsec_diff);\n#  endif\n  if (time_diff >= GC_time_limit\n      && (time_diff > GC_time_limit || nsec_diff >= GC_time_lim_nsec)) {\n    GC_COND_LOG_PRINTF(\"Abandoning stopped marking after %lu ms %lu ns\"\n                       \" (attempt %d)\\n\",\n                       time_diff, nsec_diff, GC_n_attempts);\n    return TRUE;\n  }\n\n  return FALSE;\n}\n#endif /* !GC_DISABLE_INCREMENTAL */\n\n#ifdef THREADS\nGC_INNER word GC_total_stacksize = 0;\n#endif\n\n/* The lowest value returned by `min_bytes_allocd()`. */\nstatic size_t min_bytes_allocd_minimum = 1;\n\nGC_API void GC_CALL\nGC_set_min_bytes_allocd(size_t value)\n{\n  GC_ASSERT(value > 0);\n  min_bytes_allocd_minimum = value;\n}\n\nGC_API size_t GC_CALL\nGC_get_min_bytes_allocd(void)\n{\n  return min_bytes_allocd_minimum;\n}\n\n/*\n * Return the minimum number of bytes that must be allocated between\n * collections to amortize the cost of the latter.  Should be nonzero.\n */\nstatic word\nmin_bytes_allocd(void)\n{\n  word result;\n  word stack_size;\n  /*\n   * Total size of roots, it includes double stack size, since the stack\n   * is expensive to scan.\n   */\n  word total_root_size;\n  /* Estimate of memory to be scanned during normal collection. */\n  word scan_size;\n\n  GC_ASSERT(I_HOLD_LOCK());\n#ifdef THREADS\n  if (GC_need_to_lock) {\n    /* We are multi-threaded... */\n    stack_size = GC_total_stacksize;\n    /*\n     * For now, we just use the value computed during the latest garbage\n     * collection.\n     */\n#  ifdef DEBUG_THREADS\n    GC_log_printf(\"Total stacks size: %lu\\n\", (unsigned long)stack_size);\n#  endif\n  } else\n#endif\n  /* else */ {\n#ifdef STACK_NOT_SCANNED\n    stack_size = 0;\n#elif defined(STACK_GROWS_UP)\n    stack_size = (word)(GC_approx_sp() - GC_stackbottom);\n#else\n    stack_size = (word)(GC_stackbottom - GC_approx_sp());\n#endif\n  }\n\n  total_root_size = 2 * stack_size + GC_root_size;\n  scan_size = 2 * GC_composite_in_use + GC_atomic_in_use / 4 + total_root_size;\n  result = scan_size / GC_free_space_divisor;\n  if (GC_incremental) {\n    result /= 2;\n  }\n  return result > min_bytes_allocd_minimum ? result : min_bytes_allocd_minimum;\n}\n\n/*\n * Return the number of bytes allocated, adjusted for explicit storage\n * management, etc.  This number is used in deciding when to trigger\n * collections.\n */\nSTATIC word\nGC_adj_bytes_allocd(void)\n{\n  GC_signed_word result;\n  GC_signed_word expl_managed = (GC_signed_word)GC_non_gc_bytes\n                                - (GC_signed_word)GC_non_gc_bytes_at_gc;\n\n  /*\n   * Do not count what was explicitly freed, or newly allocated for\n   * explicit management.  Note that deallocating an explicitly managed\n   * object should not alter result, assuming the client is playing by\n   * the rules.\n   */\n  result = (GC_signed_word)GC_bytes_allocd + (GC_signed_word)GC_bytes_dropped\n           - (GC_signed_word)GC_bytes_freed\n           + (GC_signed_word)GC_finalizer_bytes_freed - expl_managed;\n  if (result > (GC_signed_word)GC_bytes_allocd) {\n    /* Probably a client bug or unfortunate scheduling. */\n    result = (GC_signed_word)GC_bytes_allocd;\n  }\n  /*\n   * We count objects enqueued for finalization as though they had been\n   * reallocated this round.  Finalization is visible to user.\n   * And if we do not count this, we have stability problems for programs\n   * that finalize all objects.\n   */\n  result += (GC_signed_word)GC_bytes_finalized;\n  if (result < (GC_signed_word)(GC_bytes_allocd >> 3)) {\n    /*\n     * Always count at least 1/8 of the allocations.  We do not want to\n     * collect too infrequently, since that would inhibit coalescing of\n     * free storage blocks.  This also makes us partially robust against\n     * client bugs.\n     */\n    result = (GC_signed_word)(GC_bytes_allocd >> 3);\n  }\n  return (word)result;\n}\n\n/*\n * Clear up a few frames worth of garbage left at the top of the stack.\n * This is used to prevent us from accidentally treating garbage left\n * on the stack by other parts of the collector as roots.\n * This differs from the code in `misc.c` file, which actually tries\n * to keep the stack clear of long-lived, client-generated garbage.\n */\nSTATIC void\nGC_clear_a_few_frames(void)\n{\n#ifndef CLEAR_STACK_NPTRS\n#  define CLEAR_STACK_NPTRS 64 /*< pointers */\n#endif\n  volatile ptr_t frames[CLEAR_STACK_NPTRS];\n\n  BZERO(CAST_AWAY_VOLATILE_PVOID(frames), sizeof(frames));\n}\n\nGC_API void GC_CALL\nGC_start_incremental_collection(void)\n{\n#ifndef GC_DISABLE_INCREMENTAL\n  LOCK();\n  if (GC_incremental) {\n    GC_should_start_incremental_collection = TRUE;\n    if (!GC_dont_gc) {\n      GC_collect_a_little_inner(1);\n    }\n  }\n  UNLOCK();\n#endif\n}\n\nGC_INNER GC_bool\nGC_should_collect(void)\n{\n  static word last_min_bytes_allocd, last_gc_no;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (last_gc_no != GC_gc_no) {\n    last_min_bytes_allocd = min_bytes_allocd();\n    last_gc_no = GC_gc_no;\n  }\n#ifndef GC_DISABLE_INCREMENTAL\n  if (GC_should_start_incremental_collection) {\n    GC_should_start_incremental_collection = FALSE;\n    return TRUE;\n  }\n#endif\n  if (GC_disable_automatic_collection)\n    return FALSE;\n\n  if (GC_last_heap_growth_gc_no == GC_gc_no) {\n    /* Avoid expanding past limits used by black-listing. */\n    return TRUE;\n  }\n\n  return GC_adj_bytes_allocd() >= last_min_bytes_allocd;\n}\n\n/*\n * Called at start of full collections.  Not called if zero.\n * Called with the allocator lock held.  Not used by the collector itself.\n */\n/* `STATIC` */ GC_start_callback_proc GC_start_call_back = 0;\n\nGC_API void GC_CALL\nGC_set_start_callback(GC_start_callback_proc fn)\n{\n  LOCK();\n  GC_start_call_back = fn;\n  UNLOCK();\n}\n\nGC_API GC_start_callback_proc GC_CALL\nGC_get_start_callback(void)\n{\n  GC_start_callback_proc fn;\n\n  READER_LOCK();\n  fn = GC_start_call_back;\n  READER_UNLOCK();\n  return fn;\n}\n\nGC_INLINE void\nGC_notify_full_gc(void)\n{\n  if (GC_start_call_back != 0) {\n    (*GC_start_call_back)();\n  }\n}\n\nSTATIC GC_bool GC_is_full_gc = FALSE;\n\nSTATIC GC_bool GC_stopped_mark(GC_stop_func stop_func);\nSTATIC void GC_finish_collection(void);\n\n/*\n * Initiate a garbage collection if appropriate.  Choose judiciously\n * between partial, full, and stop-world collections.\n */\nSTATIC void\nGC_maybe_gc(void)\n{\n  static int n_partial_gcs = 0;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  ASSERT_CANCEL_DISABLED();\n  if (!GC_should_collect())\n    return;\n\n  if (!GC_incremental) {\n    GC_gcollect_inner();\n    return;\n  }\n\n  GC_ASSERT(!GC_collection_in_progress());\n#ifdef PARALLEL_MARK\n  if (GC_parallel)\n    GC_wait_for_reclaim();\n#endif\n  if (GC_need_full_gc || n_partial_gcs >= GC_full_freq) {\n    GC_COND_LOG_PRINTF(\n        \"***>Full mark for collection #%lu after %lu allocd bytes\\n\",\n        (unsigned long)GC_gc_no + 1, (unsigned long)GC_bytes_allocd);\n    GC_notify_full_gc();\n    ENTER_GC();\n    GC_promote_black_lists();\n    (void)GC_reclaim_all((GC_stop_func)0, TRUE);\n    GC_clear_marks();\n    EXIT_GC();\n    n_partial_gcs = 0;\n    GC_is_full_gc = TRUE;\n  } else {\n    n_partial_gcs++;\n  }\n\n  /*\n   * Try to mark with the world stopped.  If we run out of time, then this\n   * turns into an incremental marking.\n   */\n#ifndef NO_CLOCK\n  if (GC_time_limit != GC_TIME_UNLIMITED)\n    GET_TIME(GC_start_time);\n#endif\n  if (GC_stopped_mark(GC_timeout_stop_func)) {\n    SAVE_CALLERS_TO_LAST_STACK();\n    GC_finish_collection();\n  } else if (!GC_is_full_gc) {\n    /* Count this as the first attempt. */\n    GC_n_attempts++;\n  }\n}\n\nSTATIC GC_on_collection_event_proc GC_on_collection_event = 0;\n\nGC_API void GC_CALL\nGC_set_on_collection_event(GC_on_collection_event_proc fn)\n{\n  /* `fn` may be 0 (means no event notifier). */\n  LOCK();\n  GC_on_collection_event = fn;\n  UNLOCK();\n}\n\nGC_API GC_on_collection_event_proc GC_CALL\nGC_get_on_collection_event(void)\n{\n  GC_on_collection_event_proc fn;\n\n  READER_LOCK();\n  fn = GC_on_collection_event;\n  READER_UNLOCK();\n  return fn;\n}\n\nGC_INNER GC_bool\nGC_try_to_collect_inner(GC_stop_func stop_func)\n{\n#ifndef NO_CLOCK\n  CLOCK_TYPE start_time = CLOCK_TYPE_INITIALIZER;\n  GC_bool start_time_valid;\n#endif\n\n  ASSERT_CANCEL_DISABLED();\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_is_initialized);\n  if (GC_dont_gc || (*stop_func)())\n    return FALSE;\n  if (GC_on_collection_event)\n    GC_on_collection_event(GC_EVENT_START);\n  if (GC_incremental && GC_collection_in_progress()) {\n    GC_COND_LOG_PRINTF(\n        \"GC_try_to_collect_inner: finishing collection in progress\\n\");\n    /* Just finish collection already in progress. */\n    do {\n      if ((*stop_func)()) {\n        /* TODO: Notify `GC_EVENT_ABANDON`. */\n        return FALSE;\n      }\n      GC_collect_a_little_inner(1);\n    } while (GC_collection_in_progress());\n  }\n  GC_notify_full_gc();\n#ifndef NO_CLOCK\n  start_time_valid = FALSE;\n  if ((GC_print_stats | (int)GC_measure_performance) != 0) {\n    if (GC_print_stats)\n      GC_log_printf(\"Initiating full world-stop collection!\\n\");\n    start_time_valid = TRUE;\n    GET_TIME(start_time);\n  }\n#endif\n  GC_promote_black_lists();\n  /*\n   * Make sure all blocks have been reclaimed, so sweep routines do not\n   * see cleared mark bits.  If we are guaranteed to finish, then this\n   * is unnecessary.  In the find-leak case, we have to finish to\n   * guarantee that previously unmarked objects are not reported as leaks.\n   */\n#ifdef PARALLEL_MARK\n  if (GC_parallel)\n    GC_wait_for_reclaim();\n#endif\n  ENTER_GC();\n  if ((GC_find_leak_inner || stop_func != GC_never_stop_func)\n      && !GC_reclaim_all(stop_func, FALSE)) {\n    /* Aborted.  So far everything is still consistent. */\n    EXIT_GC();\n    /* TODO: Notify `GC_EVENT_ABANDON`. */\n    return FALSE;\n  }\n  GC_invalidate_mark_state(); /*< flush mark stack */\n  GC_clear_marks();\n  SAVE_CALLERS_TO_LAST_STACK();\n  GC_is_full_gc = TRUE;\n  EXIT_GC();\n  if (!GC_stopped_mark(stop_func)) {\n    if (!GC_incremental) {\n      /*\n       * We are partially done and have no way to complete or use\n       * current work.  Reestablish invariants as cheaply as possible.\n       */\n      GC_invalidate_mark_state();\n      GC_unpromote_black_lists();\n    } else {\n      /*\n       * We claim the world is already (or still) consistent.\n       * We will finish incrementally.\n       */\n    }\n    /* TODO: Notify `GC_EVENT_ABANDON`. */\n    return FALSE;\n  }\n  GC_finish_collection();\n#ifndef NO_CLOCK\n  if (start_time_valid) {\n    CLOCK_TYPE current_time;\n    unsigned long time_diff, ns_frac_diff;\n\n    GET_TIME(current_time);\n    time_diff = MS_TIME_DIFF(current_time, start_time);\n    ns_frac_diff = NS_FRAC_TIME_DIFF(current_time, start_time);\n    if (GC_measure_performance) {\n      GC_full_gc_total_time += time_diff; /*< may wrap */\n      GC_full_gc_total_ns_frac += (unsigned32)ns_frac_diff;\n      if (GC_full_gc_total_ns_frac >= (unsigned32)1000000UL) {\n        /* Overflow of the nanoseconds part. */\n        GC_full_gc_total_ns_frac -= (unsigned32)1000000UL;\n        GC_full_gc_total_time++;\n      }\n    }\n    if (GC_print_stats)\n      GC_log_printf(\"Complete collection took %lu ms %lu ns\\n\", time_diff,\n                    ns_frac_diff);\n  }\n#endif\n  if (GC_on_collection_event)\n    GC_on_collection_event(GC_EVENT_END);\n  return TRUE;\n}\n\n/* The default value of `GC_rate`. */\n#ifndef GC_RATE\n#  define GC_RATE 10\n#endif\n\n/*\n * When `GC_collect_a_little_inner()` performs `n_blocks` units of garbage\n * collection work, a unit is intended to touch roughly `GC_rate` pages.\n * (But, every once in a while, we do more than that.)  This needs to be\n * a fairly large number with our current incremental collection strategy,\n * since otherwise we allocate too much during garbage collection, and\n * the cleanup gets expensive.\n */\nSTATIC unsigned GC_rate = GC_RATE;\n\nGC_API void GC_CALL\nGC_set_rate(int value)\n{\n  GC_ASSERT(value > 0);\n  GC_rate = (unsigned)value;\n}\n\nGC_API int GC_CALL\nGC_get_rate(void)\n{\n  return (int)GC_rate;\n}\n\n/* The default maximum number of prior attempts at world stop marking. */\n#ifndef MAX_PRIOR_ATTEMPTS\n#  define MAX_PRIOR_ATTEMPTS 3\n#endif\n\n/*\n * The maximum number of prior attempts at world stop marking.\n * A value of 1 means that we finish the second time, no matter how long\n * it takes.  Does not count the initial root scan for a full collection.\n */\nstatic int max_prior_attempts = MAX_PRIOR_ATTEMPTS;\n\nGC_API void GC_CALL\nGC_set_max_prior_attempts(int value)\n{\n  GC_ASSERT(value >= 0);\n  max_prior_attempts = value;\n}\n\nGC_API int GC_CALL\nGC_get_max_prior_attempts(void)\n{\n  return max_prior_attempts;\n}\n\nGC_INNER void\nGC_collect_a_little_inner(size_t n_blocks)\n{\n  IF_CANCEL(int cancel_state;)\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_is_initialized);\n  DISABLE_CANCEL(cancel_state);\n  if (GC_incremental && GC_collection_in_progress()) {\n    size_t i;\n    size_t max_deficit = GC_rate * n_blocks;\n\n    ENTER_GC();\n#ifdef PARALLEL_MARK\n    if (GC_time_limit != GC_TIME_UNLIMITED)\n      GC_parallel_mark_disabled = TRUE;\n#endif\n    for (i = GC_mark_deficit; i < max_deficit; i++) {\n      if (GC_mark_some(NULL))\n        break;\n    }\n#ifdef PARALLEL_MARK\n    GC_parallel_mark_disabled = FALSE;\n#endif\n    EXIT_GC();\n\n    if (i < max_deficit && !GC_dont_gc) {\n      GC_ASSERT(!GC_collection_in_progress());\n      /* Need to follow up with a full collection. */\n      SAVE_CALLERS_TO_LAST_STACK();\n#ifdef PARALLEL_MARK\n      if (GC_parallel)\n        GC_wait_for_reclaim();\n#endif\n#ifndef NO_CLOCK\n      if (GC_time_limit != GC_TIME_UNLIMITED\n          && GC_n_attempts < max_prior_attempts)\n        GET_TIME(GC_start_time);\n#endif\n      if (GC_stopped_mark(GC_n_attempts < max_prior_attempts\n                              ? GC_timeout_stop_func\n                              : GC_never_stop_func)) {\n        GC_finish_collection();\n      } else {\n        GC_n_attempts++;\n      }\n    }\n    if (GC_mark_deficit > 0) {\n      GC_mark_deficit\n          = GC_mark_deficit > max_deficit ? GC_mark_deficit - max_deficit : 0;\n    }\n  } else if (!GC_dont_gc) {\n    GC_maybe_gc();\n  }\n  RESTORE_CANCEL(cancel_state);\n}\n\n#if !defined(NO_FIND_LEAK) || !defined(SHORT_DBG_HDRS)\nGC_INNER void (*GC_check_heap)(void) = 0;\nGC_INNER void (*GC_print_all_smashed)(void) = 0;\n#endif\n\nGC_API int GC_CALL\nGC_collect_a_little(void)\n{\n  int result;\n\n  if (UNLIKELY(!GC_is_initialized))\n    GC_init();\n  LOCK();\n  /*\n   * Note: if the collection is in progress, this may do marking (not\n   * stopping the world) even in case of disabled garbage collection.\n   */\n  GC_collect_a_little_inner(1);\n  result = (int)GC_collection_in_progress();\n  UNLOCK();\n  if (GC_debugging_started && !result)\n    GC_print_all_smashed();\n  return result;\n}\n\n#ifdef THREADS\nGC_API void GC_CALL\nGC_stop_world_external(void)\n{\n  GC_ASSERT(GC_is_initialized);\n  LOCK();\n#  ifdef THREAD_LOCAL_ALLOC\n  GC_ASSERT(!GC_world_stopped);\n#  endif\n  ENTER_GC();\n  STOP_WORLD();\n#  ifdef THREAD_LOCAL_ALLOC\n  GC_world_stopped = TRUE;\n#  endif\n}\n\nGC_API void GC_CALL\nGC_start_world_external(void)\n{\n#  ifdef THREAD_LOCAL_ALLOC\n  GC_ASSERT(GC_world_stopped);\n  GC_world_stopped = FALSE;\n#  else\n  GC_ASSERT(GC_is_initialized);\n#  endif\n  START_WORLD();\n  EXIT_GC();\n  UNLOCK();\n}\n#endif /* THREADS */\n\n#ifdef USE_MUNMAP\n#  ifndef MUNMAP_THRESHOLD\n#    define MUNMAP_THRESHOLD 7\n#  endif\nGC_INNER unsigned GC_unmap_threshold = MUNMAP_THRESHOLD;\n\n#  define IF_USE_MUNMAP(x) x\n#  define COMMA_IF_USE_MUNMAP(x) /* comma */ , x\n#else\n#  define IF_USE_MUNMAP(x)\n#  define COMMA_IF_USE_MUNMAP(x)\n#endif /* !USE_MUNMAP */\n\n/*\n * We stop the world and mark from all roots.  If `stop_func()` ever\n * returns `TRUE`, we may fail and return `FALSE`.  Increment `GC_gc_no`\n * if we succeed.\n */\nSTATIC GC_bool\nGC_stopped_mark(GC_stop_func stop_func)\n{\n  ptr_t cold_gc_frame = GC_approx_sp();\n  unsigned abandoned_at;\n#ifndef NO_CLOCK\n  CLOCK_TYPE start_time = CLOCK_TYPE_INITIALIZER;\n  GC_bool start_time_valid = FALSE;\n#endif\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_is_initialized);\n  ENTER_GC();\n#if !defined(REDIRECT_MALLOC) && defined(USE_WINALLOC)\n  GC_add_current_malloc_heap();\n#endif\n#if defined(REGISTER_LIBRARIES_EARLY)\n  GC_cond_register_dynamic_libraries();\n#endif\n\n#if !defined(GC_NO_FINALIZATION) && !defined(GC_TOGGLE_REFS_NOT_NEEDED)\n  GC_process_togglerefs();\n#endif\n\n  /* Output blank line for convenience here. */\n  GC_COND_LOG_PRINTF(\n      \"\\n--> Marking for collection #%lu after %lu allocated bytes\\n\",\n      (unsigned long)GC_gc_no + 1, (unsigned long)GC_bytes_allocd);\n#ifndef NO_CLOCK\n  if (GC_PRINT_STATS_FLAG || GC_measure_performance) {\n    GET_TIME(start_time);\n    start_time_valid = TRUE;\n  }\n#endif\n#ifdef THREADS\n  if (GC_on_collection_event)\n    GC_on_collection_event(GC_EVENT_PRE_STOP_WORLD);\n#endif\n  STOP_WORLD();\n#ifdef THREADS\n  if (GC_on_collection_event)\n    GC_on_collection_event(GC_EVENT_POST_STOP_WORLD);\n#  ifdef THREAD_LOCAL_ALLOC\n  GC_world_stopped = TRUE;\n#  elif defined(CPPCHECK)\n  /* Workaround a warning about adjacent same `if` condition. */\n  (void)0;\n#  endif\n#endif\n\n#ifdef MAKE_BACK_GRAPH\n  if (GC_print_back_height) {\n    GC_build_back_graph();\n  }\n#endif\n\n  /* Notify about marking from all roots. */\n  if (GC_on_collection_event)\n    GC_on_collection_event(GC_EVENT_MARK_START);\n\n  /* Minimize junk left in my registers and on the stack. */\n  GC_clear_a_few_frames();\n  GC_noop6(0, 0, 0, 0, 0, 0);\n\n  GC_initiate_gc();\n#ifdef PARALLEL_MARK\n  if (stop_func != GC_never_stop_func)\n    GC_parallel_mark_disabled = TRUE;\n#endif\n  for (abandoned_at = 1; !(*stop_func)(); abandoned_at++) {\n    if (GC_mark_some(cold_gc_frame)) {\n#ifdef PARALLEL_MARK\n      if (GC_parallel && GC_parallel_mark_disabled) {\n        GC_COND_LOG_PRINTF(\"Stopped marking done after %u iterations\"\n                           \" with disabled parallel marker\\n\",\n                           abandoned_at - 1);\n      }\n#endif\n      abandoned_at = 0;\n      break;\n    }\n  }\n#ifdef PARALLEL_MARK\n  GC_parallel_mark_disabled = FALSE;\n#endif\n\n  if (abandoned_at > 0) {\n    /* Give the mutator a chance. */\n    GC_mark_deficit = abandoned_at - 1;\n    /* TODO: Notify `GC_EVENT_MARK_ABANDON`. */\n  } else {\n    GC_gc_no++;\n    /* Check all debugged objects for consistency. */\n    if (GC_debugging_started)\n      GC_check_heap();\n    if (GC_on_collection_event)\n      GC_on_collection_event(GC_EVENT_MARK_END);\n  }\n\n#ifdef THREADS\n  if (GC_on_collection_event)\n    GC_on_collection_event(GC_EVENT_PRE_START_WORLD);\n#endif\n#ifdef THREAD_LOCAL_ALLOC\n  GC_world_stopped = FALSE;\n#endif\n  START_WORLD();\n#ifdef THREADS\n  if (GC_on_collection_event)\n    GC_on_collection_event(GC_EVENT_POST_START_WORLD);\n#endif\n\n#ifndef NO_CLOCK\n  if (start_time_valid) {\n    CLOCK_TYPE current_time;\n    unsigned long time_diff, ns_frac_diff;\n\n    /* TODO: Avoid code duplication from `GC_try_to_collect_inner`. */\n    GET_TIME(current_time);\n    time_diff = MS_TIME_DIFF(current_time, start_time);\n    ns_frac_diff = NS_FRAC_TIME_DIFF(current_time, start_time);\n    if (GC_measure_performance) {\n      GC_stopped_mark_total_time += time_diff; /*< may wrap */\n      GC_stopped_mark_total_ns_frac += (unsigned32)ns_frac_diff;\n      if (GC_stopped_mark_total_ns_frac >= (unsigned32)1000000UL) {\n        GC_stopped_mark_total_ns_frac -= (unsigned32)1000000UL;\n        GC_stopped_mark_total_time++;\n      }\n    }\n\n    if (GC_PRINT_STATS_FLAG || GC_measure_performance) {\n      unsigned total_time = GC_world_stopped_total_time;\n      unsigned divisor = GC_world_stopped_total_divisor;\n\n      /* Compute new world-stop delay total time. */\n      if (total_time > (((unsigned)-1) >> 1)\n          || divisor >= MAX_TOTAL_TIME_DIVISOR) {\n        /* Halve values if overflow occurs. */\n        total_time >>= 1;\n        divisor >>= 1;\n      }\n      total_time += time_diff < (((unsigned)-1) >> 1) ? (unsigned)time_diff\n                                                      : ((unsigned)-1) >> 1;\n      /* Update old `GC_world_stopped_total_time` and its divisor. */\n      GC_world_stopped_total_time = total_time;\n      GC_world_stopped_total_divisor = ++divisor;\n      if (GC_PRINT_STATS_FLAG && 0 == abandoned_at) {\n        GC_ASSERT(divisor != 0);\n        GC_log_printf(\"World-stopped marking took %lu ms %lu ns\"\n                      \" (%u ms in average)\\n\",\n                      time_diff, ns_frac_diff, total_time / divisor);\n      }\n    }\n  }\n#endif\n\n  EXIT_GC();\n  if (0 == abandoned_at)\n    return TRUE;\n  GC_COND_LOG_PRINTF(\"Abandoned stopped marking after %u iterations\\n\",\n                     abandoned_at - 1);\n  return FALSE;\n}\n\nGC_INNER void\nGC_set_fl_marks(ptr_t q)\n{\n#ifdef GC_ASSERTIONS\n  ptr_t q2;\n#endif\n  struct hblk *h = HBLKPTR(q);\n  const struct hblk *last_h = h;\n  hdr *hhdr;\n#ifdef MARK_BIT_PER_OBJ\n  size_t sz;\n#endif\n\n  GC_ASSERT(q != NULL);\n  hhdr = HDR(h);\n#ifdef MARK_BIT_PER_OBJ\n  sz = hhdr->hb_sz;\n#endif\n#ifdef GC_ASSERTIONS\n  q2 = (ptr_t)obj_link(q);\n#endif\n  for (;;) {\n    size_t bit_no = MARK_BIT_NO((size_t)((ptr_t)q - (ptr_t)h), sz);\n\n    if (!mark_bit_from_hdr(hhdr, bit_no)) {\n      set_mark_bit_from_hdr(hhdr, bit_no);\n      INCR_MARKS(hhdr);\n    }\n    q = (ptr_t)obj_link(q);\n    if (NULL == q)\n      break;\n#ifdef GC_ASSERTIONS\n    /*\n     * Detect a cycle in the free list.  The algorithm is to have\n     * a \"twice faster\" iterator over the list which meets the first\n     * one in case of a cycle existing in the list.\n     */\n    if (q2 != NULL) {\n      q2 = (ptr_t)obj_link(q2);\n      GC_ASSERT(q2 != q);\n      if (q2 != NULL) {\n        q2 = (ptr_t)obj_link(q2);\n        GC_ASSERT(q2 != q);\n      }\n    }\n#endif\n\n    h = HBLKPTR(q);\n    if (UNLIKELY(h != last_h)) {\n      last_h = h;\n      /* Update `hhdr` and `sz`. */\n      hhdr = HDR(h);\n#ifdef MARK_BIT_PER_OBJ\n      sz = hhdr->hb_sz;\n#endif\n    }\n  }\n}\n\n#if defined(GC_ASSERTIONS) && defined(THREAD_LOCAL_ALLOC)\n/*\n * Check that all mark bits for the free list, whose first entry is\n * `*pfreelist`, are set.  The check is skipped if `*pfreelist` points to\n * a special value.\n */\nvoid\nGC_check_fl_marks(void **pfreelist)\n{\n  /*\n   * TODO: There is a data race with `GC_FAST_MALLOC_GRANS` (which does\n   * not do atomic updates to the free-list).  The race seems to be\n   * harmless, and for now we just skip this check in case of TSan.\n   */\n#  if defined(AO_HAVE_load_acquire_read) && !defined(THREAD_SANITIZER)\n  ptr_t list = GC_cptr_load_acquire_read((volatile ptr_t *)pfreelist);\n  /* Atomic operations are used because the world is running. */\n  ptr_t p, prev, next;\n\n  if (ADDR(list) <= HBLKSIZE)\n    return;\n\n  prev = (ptr_t)pfreelist;\n  for (p = list; p != NULL; p = next) {\n    if (!GC_is_marked(p)) {\n      ABORT_ARG2(\"Unmarked local free-list entry\", \": object %p on list %p\",\n                 (void *)p, (void *)list);\n    }\n\n    /*\n     * While traversing the free-list, it re-reads the pointer to the\n     * current node before accepting its next pointer and bails out\n     * if the latter has changed.  That way, it will not try to follow\n     * the pointer which might be been modified after the object was\n     * returned to the client.  It might perform the mark-check on the\n     * just allocated object but that should be harmless.\n     */\n    next = GC_cptr_load_acquire_read((volatile ptr_t *)p);\n    if (GC_cptr_load((volatile ptr_t *)prev) != p)\n      break;\n    prev = p;\n  }\n#  else\n  /* FIXME: Not implemented (just skipped). */\n  (void)pfreelist;\n#  endif\n}\n#endif /* GC_ASSERTIONS && THREAD_LOCAL_ALLOC */\n\n/*\n * Clear all mark bits for the free list (specified by the first entry).\n * Decrement `GC_bytes_found` by number of bytes on free list.\n */\nSTATIC void\nGC_clear_fl_marks(ptr_t q)\n{\n  struct hblk *h = HBLKPTR(q);\n  const struct hblk *last_h = h;\n  hdr *hhdr = HDR(h);\n  size_t sz = hhdr->hb_sz; /*< normally set only once */\n\n  for (;;) {\n    size_t bit_no = MARK_BIT_NO((size_t)((ptr_t)q - (ptr_t)h), sz);\n\n    if (mark_bit_from_hdr(hhdr, bit_no)) {\n      size_t n_marks = hhdr->hb_n_marks;\n\n#ifdef LINT2\n      if (0 == n_marks)\n        ABORT(\"hhdr->hb_n_marks cannot be zero\");\n#else\n      GC_ASSERT(n_marks != 0);\n#endif\n      clear_mark_bit_from_hdr(hhdr, bit_no);\n      n_marks--;\n#ifdef PARALLEL_MARK\n      /* Approximate count, do not decrement to zero! */\n      if (n_marks != 0 || !GC_parallel) {\n        hhdr->hb_n_marks = n_marks;\n      }\n#else\n      hhdr->hb_n_marks = n_marks;\n#endif\n    }\n    GC_bytes_found -= (GC_signed_word)sz;\n\n    q = (ptr_t)obj_link(q);\n    if (NULL == q)\n      break;\n\n    h = HBLKPTR(q);\n    if (UNLIKELY(h != last_h)) {\n      last_h = h;\n      /* Update `hhdr` and `sz`. */\n      hhdr = HDR(h);\n      sz = hhdr->hb_sz;\n    }\n  }\n}\n\n/* Mark all objects on the free lists for every object kind. */\nstatic void\nset_all_fl_marks(void)\n{\n  unsigned kind;\n\n  for (kind = 0; kind < GC_n_kinds; kind++) {\n    word size; /*< current object size */\n\n    for (size = 1; size <= MAXOBJGRANULES; size++) {\n      ptr_t q = (ptr_t)GC_obj_kinds[kind].ok_freelist[size];\n\n      if (q != NULL)\n        GC_set_fl_marks(q);\n    }\n  }\n}\n\n/*\n * Clear free-list mark bits.  Also subtract memory remaining from\n * `GC_bytes_found` count.\n */\nstatic void\nclear_all_fl_marks(void)\n{\n  unsigned kind;\n\n  for (kind = 0; kind < GC_n_kinds; kind++) {\n    word size; /*< current object size */\n\n    for (size = 1; size <= MAXOBJGRANULES; size++) {\n      ptr_t q = (ptr_t)GC_obj_kinds[kind].ok_freelist[size];\n\n      if (q != NULL)\n        GC_clear_fl_marks(q);\n    }\n  }\n}\n\n#if defined(GC_ASSERTIONS) && defined(THREAD_LOCAL_ALLOC)\nvoid GC_check_tls(void);\n#endif\n\nGC_on_heap_resize_proc GC_on_heap_resize = 0;\n\n/* Used for logging only. */\nGC_INLINE int\nGC_compute_heap_usage_percent(void)\n{\n  word used = GC_composite_in_use + GC_atomic_in_use + GC_bytes_allocd;\n  word heap_sz = GC_heapsize - GC_unmapped_bytes;\n#if defined(CPPCHECK)\n  word limit = (GC_WORD_MAX >> 1) / 50; /*< to avoid a false positive */\n#else\n  const word limit = GC_WORD_MAX / 100;\n#endif\n\n  return used >= heap_sz ? 0\n         : used < limit  ? (int)((used * 100) / heap_sz)\n                         : (int)(used / (heap_sz / 100));\n}\n\n#define GC_DBGLOG_PRINT_HEAP_IN_USE()                                        \\\n  GC_DBGLOG_PRINTF(\"In-use heap: %d%% (%lu KiB pointers + %lu KiB other)\\n\", \\\n                   GC_compute_heap_usage_percent(),                          \\\n                   TO_KiB_UL(GC_composite_in_use),                           \\\n                   TO_KiB_UL(GC_atomic_in_use + GC_bytes_allocd))\n\n/*\n * Finish up a collection.  Assumes mark bits are consistent, but the\n * world is otherwise running.\n */\nSTATIC void\nGC_finish_collection(void)\n{\n#ifndef NO_CLOCK\n  CLOCK_TYPE start_time = CLOCK_TYPE_INITIALIZER;\n  CLOCK_TYPE finalize_time = CLOCK_TYPE_INITIALIZER;\n#endif\n\n  GC_ASSERT(I_HOLD_LOCK());\n#if defined(GC_ASSERTIONS) && defined(THREAD_LOCAL_ALLOC) \\\n    && !defined(DBG_HDRS_ALL)\n  /* Check that we marked some of our own data. */\n  GC_check_tls();\n  /* TODO: Add more checks. */\n#endif\n\n#ifndef NO_CLOCK\n  if (GC_print_stats)\n    GET_TIME(start_time);\n#endif\n  if (GC_on_collection_event)\n    GC_on_collection_event(GC_EVENT_RECLAIM_START);\n\n#ifndef GC_GET_HEAP_USAGE_NOT_NEEDED\n  if (GC_bytes_found > 0)\n    GC_reclaimed_bytes_before_gc += (word)GC_bytes_found;\n#endif\n  GC_bytes_found = 0;\n#if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)\n  if (GETENV(\"GC_PRINT_ADDRESS_MAP\") != NULL) {\n    GC_print_address_map();\n  }\n#endif\n  COND_DUMP;\n  if (GC_find_leak_inner) {\n    set_all_fl_marks();\n    /* This just checks; it does not really reclaim anything. */\n    GC_start_reclaim(TRUE);\n  }\n\n#ifndef GC_NO_FINALIZATION\n  GC_finalize();\n#endif\n#ifndef NO_CLOCK\n  if (GC_print_stats)\n    GET_TIME(finalize_time);\n#endif\n#ifdef MAKE_BACK_GRAPH\n  if (GC_print_back_height) {\n    GC_traverse_back_graph();\n  }\n#endif\n\n  /*\n   * Clear free-list mark bits, in case they got accidentally marked\n   * (or `GC_find_leak` is set and they were intentionally marked).\n   * Note that composite objects on free list are cleared, thus\n   * accidentally marking a free list is not a problem; but some objects\n   * on the list itself might be marked, and the given function call\n   * fixes it.\n   */\n  clear_all_fl_marks();\n\n  GC_VERBOSE_LOG_PRINTF(\"Bytes recovered before sweep - f.l. count = %ld\\n\",\n                        (long)GC_bytes_found);\n\n  /* Reconstruct free lists to contain everything not marked. */\n  GC_start_reclaim(FALSE);\n\n#ifdef USE_MUNMAP\n  if (GC_unmap_threshold > 0    /*< memory unmapping enabled? */\n      && LIKELY(GC_gc_no != 1)) /*< do not unmap during `GC_init` */\n    GC_unmap_old(GC_unmap_threshold);\n\n  GC_ASSERT(GC_heapsize >= GC_unmapped_bytes);\n#endif\n  GC_ASSERT(GC_our_mem_bytes >= GC_heapsize);\n  GC_DBGLOG_PRINTF(\n      \"GC #%lu freed %ld bytes, heap %lu KiB (\" IF_USE_MUNMAP(\n          \"+ %lu KiB unmapped \") \"+ %lu KiB internal)\\n\",\n      (unsigned long)GC_gc_no, (long)GC_bytes_found,\n      TO_KiB_UL(GC_heapsize - GC_unmapped_bytes) /*, */\n      COMMA_IF_USE_MUNMAP(TO_KiB_UL(GC_unmapped_bytes)),\n      TO_KiB_UL(GC_our_mem_bytes - GC_heapsize + sizeof(GC_arrays)));\n  GC_DBGLOG_PRINT_HEAP_IN_USE();\n  if (GC_is_full_gc) {\n    GC_used_heap_size_after_full = GC_heapsize - GC_large_free_bytes;\n    GC_need_full_gc = FALSE;\n  } else {\n    GC_need_full_gc = GC_heapsize - GC_used_heap_size_after_full\n                      > min_bytes_allocd() + GC_large_free_bytes;\n  }\n\n  /* Reset or increment counters for next cycle. */\n  GC_n_attempts = 0;\n  GC_is_full_gc = FALSE;\n  GC_bytes_allocd_before_gc += GC_bytes_allocd;\n  GC_non_gc_bytes_at_gc = GC_non_gc_bytes;\n  GC_bytes_allocd = 0;\n  GC_bytes_dropped = 0;\n  GC_bytes_freed = 0;\n  GC_finalizer_bytes_freed = 0;\n\n  if (GC_on_collection_event)\n    GC_on_collection_event(GC_EVENT_RECLAIM_END);\n#ifndef NO_CLOCK\n  if (GC_print_stats) {\n    CLOCK_TYPE done_time;\n\n    GET_TIME(done_time);\n#  if !defined(SMALL_CONFIG) && !defined(GC_NO_FINALIZATION)\n    /* A convenient place to output finalization statistics. */\n    GC_print_finalization_stats();\n#  endif\n    GC_log_printf(\"Finalize and initiate sweep took %lu ms %lu ns\"\n                  \" + %lu ms %lu ns\\n\",\n                  MS_TIME_DIFF(finalize_time, start_time),\n                  NS_FRAC_TIME_DIFF(finalize_time, start_time),\n                  MS_TIME_DIFF(done_time, finalize_time),\n                  NS_FRAC_TIME_DIFF(done_time, finalize_time));\n  }\n#elif !defined(SMALL_CONFIG) && !defined(GC_NO_FINALIZATION)\n  if (GC_print_stats)\n    GC_print_finalization_stats();\n#endif\n}\n\n/* Note: if `stop_func` is 0, then `GC_default_stop_func` is used instead. */\nSTATIC GC_bool\nGC_try_to_collect_general(GC_stop_func stop_func, GC_bool force_unmap)\n{\n  GC_bool result;\n#ifdef USE_MUNMAP\n  unsigned old_unmap_threshold;\n#endif\n  IF_CANCEL(int cancel_state;)\n\n  if (UNLIKELY(!GC_is_initialized))\n    GC_init();\n  if (GC_debugging_started)\n    GC_print_all_smashed();\n  GC_notify_or_invoke_finalizers();\n  LOCK();\n  if (force_unmap) {\n    /*\n     * Record current heap size to make heap growth more conservative\n     * afterwards (as if the heap is growing from zero size again).\n     */\n    GC_heapsize_at_forced_unmap = GC_heapsize;\n  }\n  DISABLE_CANCEL(cancel_state);\n#ifdef USE_MUNMAP\n  old_unmap_threshold = GC_unmap_threshold;\n  if (force_unmap || (GC_force_unmap_on_gcollect && old_unmap_threshold > 0))\n    GC_unmap_threshold = 1; /*< unmap as much as possible */\n#endif\n  /* Minimize junk left in my registers. */\n  GC_noop6(0, 0, 0, 0, 0, 0);\n  result = GC_try_to_collect_inner(stop_func != 0 ? stop_func\n                                                  : GC_default_stop_func);\n#ifdef USE_MUNMAP\n  /* Restore it. */\n  GC_unmap_threshold = old_unmap_threshold;\n#endif\n  RESTORE_CANCEL(cancel_state);\n  UNLOCK();\n  if (result) {\n    if (GC_debugging_started)\n      GC_print_all_smashed();\n    GC_notify_or_invoke_finalizers();\n  }\n  return result;\n}\n\n/* Externally callable routines to invoke full, stop-the-world collection. */\n\nGC_API int GC_CALL\nGC_try_to_collect(GC_stop_func stop_func)\n{\n  GC_ASSERT(NONNULL_ARG_NOT_NULL(stop_func));\n  return (int)GC_try_to_collect_general(stop_func, FALSE);\n}\n\nGC_API void GC_CALL\nGC_gcollect(void)\n{\n  /*\n   * Zero is passed as stop_func to get `GC_default_stop_func` value\n   * while holding the allocator lock (to prevent data race).\n   */\n  (void)GC_try_to_collect_general(0, FALSE);\n  if (get_have_errors())\n    GC_print_all_errors();\n}\n\nGC_API void GC_CALL\nGC_gcollect_and_unmap(void)\n{\n  /* Collect and force memory unmapping to OS. */\n  (void)GC_try_to_collect_general(GC_never_stop_func, TRUE);\n}\n\nGC_INNER ptr_t\nGC_os_get_mem(size_t bytes)\n{\n  ptr_t space;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  space = (ptr_t)GET_MEM(bytes); /*< `HBLKSIZE`-aligned */\n  if (UNLIKELY(NULL == space))\n    return NULL;\n#ifdef USE_PROC_FOR_LIBRARIES\n  /* Add `HBLKSIZE`-aligned `GET_MEM`-generated block to `GC_our_memory`. */\n  if (GC_n_memory >= MAX_HEAP_SECTS)\n    ABORT(\"Too many GC-allocated memory sections: Increase MAX_HEAP_SECTS\");\n  GC_our_memory[GC_n_memory].hs_start = space;\n  GC_our_memory[GC_n_memory].hs_bytes = bytes;\n  GC_n_memory++;\n#endif\n  GC_our_mem_bytes += bytes;\n  GC_VERBOSE_LOG_PRINTF(\"Got %lu bytes from OS\\n\", (unsigned long)bytes);\n  return space;\n}\n\n/*\n * Use the chunk of memory starting at `h` of size `sz` as part of the heap.\n * Assumes `h` is `HBLKSIZE`-aligned, `sz` is a multiple of `HBLKSIZE`.\n */\nSTATIC void\nGC_add_to_heap(struct hblk *h, size_t sz)\n{\n  hdr *hhdr;\n  ptr_t endp;\n  size_t old_capacity = 0;\n  void *old_heap_sects = NULL;\n#ifdef GC_ASSERTIONS\n  size_t i;\n#endif\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(ADDR(h) % HBLKSIZE == 0);\n  GC_ASSERT(sz % HBLKSIZE == 0);\n  GC_ASSERT(sz > 0);\n  GC_ASSERT(GC_all_nils != NULL);\n\n  if (UNLIKELY(GC_n_heap_sects == GC_capacity_heap_sects)) {\n    /* Allocate new `GC_heap_sects` with sufficient capacity. */\n#ifndef INITIAL_HEAP_SECTS\n#  define INITIAL_HEAP_SECTS 32\n#endif\n    size_t new_capacity\n        = GC_n_heap_sects > 0 ? GC_n_heap_sects * 2 : INITIAL_HEAP_SECTS;\n    void *new_heap_sects\n        = GC_scratch_alloc(new_capacity * sizeof(struct HeapSect));\n\n    if (NULL == new_heap_sects) {\n      /* Retry with smaller yet sufficient capacity. */\n      new_capacity = GC_n_heap_sects + INITIAL_HEAP_SECTS;\n      new_heap_sects\n          = GC_scratch_alloc(new_capacity * sizeof(struct HeapSect));\n      if (NULL == new_heap_sects)\n        ABORT(\"Insufficient memory for heap sections\");\n    }\n    old_capacity = GC_capacity_heap_sects;\n    old_heap_sects = GC_heap_sects;\n    /* Transfer `GC_heap_sects` contents to the newly allocated array. */\n    if (GC_n_heap_sects > 0)\n      BCOPY(old_heap_sects, new_heap_sects,\n            GC_n_heap_sects * sizeof(struct HeapSect));\n    GC_capacity_heap_sects = new_capacity;\n    GC_heap_sects = (struct HeapSect *)new_heap_sects;\n    GC_COND_LOG_PRINTF(\"Grew heap sections array to %lu elements\\n\",\n                       (unsigned long)new_capacity);\n  }\n\n  while (UNLIKELY(ADDR(h) <= HBLKSIZE)) {\n    /* Cannot handle memory near address zero. */\n    ++h;\n    sz -= HBLKSIZE;\n    if (0 == sz)\n      return;\n  }\n  while (UNLIKELY(ADDR(h) >= GC_WORD_MAX - sz)) {\n    /* Prevent overflow when calculating `endp`. */\n    sz -= HBLKSIZE;\n    if (0 == sz)\n      return;\n  }\n  endp = (ptr_t)h + sz;\n\n  hhdr = GC_install_header(h);\n  if (UNLIKELY(NULL == hhdr)) {\n    /*\n     * This is extremely unlikely. Cannot add it.  This will almost\n     * certainly result in a `NULL` returned from the allocator, which\n     * is entirely appropriate.\n     */\n    return;\n  }\n#ifdef GC_ASSERTIONS\n  /* Ensure no intersection between sections. */\n  for (i = 0; i < GC_n_heap_sects; i++) {\n    ptr_t hs_start = GC_heap_sects[i].hs_start;\n    ptr_t hs_end = hs_start + GC_heap_sects[i].hs_bytes;\n\n    GC_ASSERT(!(ADDR_INSIDE((ptr_t)h, hs_start, hs_end)\n                || (ADDR_LT(hs_start, endp) && ADDR_GE(hs_end, endp))\n                || (ADDR_LT((ptr_t)h, hs_start) && ADDR_LT(hs_end, endp))));\n  }\n#endif\n  GC_heap_sects[GC_n_heap_sects].hs_start = (ptr_t)h;\n  GC_heap_sects[GC_n_heap_sects].hs_bytes = sz;\n  GC_n_heap_sects++;\n  hhdr->hb_block = h;\n  hhdr->hb_sz = sz;\n  hhdr->hb_flags = 0;\n  GC_freehblk(h);\n  GC_heapsize += sz;\n\n  if (ADDR_GE((ptr_t)GC_least_plausible_heap_addr, (ptr_t)h)\n      || UNLIKELY(NULL == GC_least_plausible_heap_addr)) {\n    /*\n     * Making it a little smaller than necessary prevents us from\n     * getting a false hit from the variable itself.  There is some\n     * unintentional reflection here.\n     */\n    GC_least_plausible_heap_addr = (ptr_t)h - sizeof(ptr_t);\n  }\n  if (ADDR_LT((ptr_t)GC_greatest_plausible_heap_addr, endp)) {\n    GC_greatest_plausible_heap_addr = endp;\n  }\n#ifdef SET_REAL_HEAP_BOUNDS\n  if (ADDR(h) < GC_least_real_heap_addr\n      || UNLIKELY(0 == GC_least_real_heap_addr))\n    GC_least_real_heap_addr = ADDR(h) - sizeof(ptr_t);\n  if (GC_greatest_real_heap_addr < ADDR(endp)) {\n#  ifdef INCLUDE_LINUX_THREAD_DESCR\n    /* Avoid heap intersection with the static data roots. */\n    GC_exclude_static_roots_inner((ptr_t)h, endp);\n#  endif\n    GC_greatest_real_heap_addr = ADDR(endp);\n  }\n#endif\n  GC_handle_protected_regions_limit();\n  if (UNLIKELY(old_capacity > 0)) {\n#ifndef GWW_VDB\n    /*\n     * Recycling may call `GC_add_to_heap()` again but should not cause\n     * resizing of `GC_heap_sects`.\n     */\n    GC_scratch_recycle_no_gww(old_heap_sects,\n                              old_capacity * sizeof(struct HeapSect));\n#else\n    /* TODO: Implement GWW-aware recycling as in `alloc_mark_stack`. */\n    GC_noop1_ptr(old_heap_sects);\n#endif\n  }\n}\n\n#ifndef NO_DEBUGGING\nvoid\nGC_print_heap_sects(void)\n{\n  size_t i;\n\n  GC_printf(\"Total heap size: %lu\" IF_USE_MUNMAP(\" (%lu unmapped)\") \"\\n\",\n            (unsigned long)GC_heapsize /*, */\n                COMMA_IF_USE_MUNMAP((unsigned long)GC_unmapped_bytes));\n\n  for (i = 0; i < GC_n_heap_sects; i++) {\n    ptr_t start = GC_heap_sects[i].hs_start;\n    size_t len = GC_heap_sects[i].hs_bytes;\n    unsigned nbl = 0;\n#  ifndef NO_BLACK_LISTING\n    struct hblk *h;\n\n    for (h = (struct hblk *)start; ADDR_LT((ptr_t)h, start + len); h++) {\n      if (GC_is_black_listed(h, HBLKSIZE))\n        nbl++;\n    }\n#  endif\n    GC_printf(\"Section %u from %p to %p %u/%lu blacklisted\\n\", (unsigned)i,\n              (void *)start, (void *)&start[len], nbl,\n              (unsigned long)divHBLKSZ(len));\n  }\n}\n#endif /* !NO_DEBUGGING */\n\nvoid *GC_least_plausible_heap_addr = MAKE_CPTR(GC_WORD_MAX);\nvoid *GC_greatest_plausible_heap_addr = NULL;\n\nSTATIC word GC_max_heapsize = 0;\n\nGC_API void GC_CALL\nGC_set_max_heap_size(GC_word n)\n{\n  GC_max_heapsize = n;\n}\n\nword GC_max_retries = 0;\n\nGC_INNER void\nGC_scratch_recycle_inner(void *ptr, size_t sz)\n{\n  size_t page_offset;\n  size_t displ = 0;\n  size_t recycled_bytes;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (NULL == ptr)\n    return;\n\n  GC_ASSERT(sz != 0);\n  GC_ASSERT(GC_page_size != 0);\n  /* TODO: Assert correct memory flags if `GWW_VDB`. */\n  page_offset = ADDR(ptr) & (GC_page_size - 1);\n  if (page_offset != 0)\n    displ = GC_page_size - page_offset;\n  recycled_bytes = sz > displ ? (sz - displ) & ~(GC_page_size - 1) : 0;\n  GC_COND_LOG_PRINTF(\"Recycle %lu/%lu scratch-allocated bytes at %p\\n\",\n                     (unsigned long)recycled_bytes, (unsigned long)sz, ptr);\n  if (recycled_bytes > 0)\n    GC_add_to_heap((struct hblk *)((ptr_t)ptr + displ), recycled_bytes);\n}\n\nGC_INNER GC_bool\nGC_expand_hp_inner(word n)\n{\n  size_t sz;\n  struct hblk *space;\n  /* Number of bytes by which we expect the heap to expand soon. */\n  word expansion_slop;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_page_size != 0);\n  if (0 == n)\n    n = 1;\n  sz = ROUNDUP_PAGESIZE((size_t)n * HBLKSIZE);\n  GC_DBGLOG_PRINT_HEAP_IN_USE();\n  if (GC_max_heapsize != 0\n      && (GC_max_heapsize < (word)sz\n          || GC_heapsize > GC_max_heapsize - (word)sz)) {\n    /* Exceeded the self-imposed limit. */\n    return FALSE;\n  }\n  space = (struct hblk *)GC_os_get_mem(sz);\n  if (UNLIKELY(NULL == space)) {\n    WARN(\"Failed to expand heap by %\" WARN_PRIuPTR \" KiB\\n\", sz >> 10);\n    return FALSE;\n  }\n  GC_last_heap_growth_gc_no = GC_gc_no;\n  GC_INFOLOG_PRINTF(\"Grow heap to %lu KiB after %lu bytes allocated\\n\",\n                    TO_KiB_UL(GC_heapsize + sz),\n                    (unsigned long)GC_bytes_allocd);\n\n  /*\n   * Adjust heap limits generously for black-listing to work better.\n   * `GC_add_to_heap()` performs minimal adjustment needed for correctness.\n   */\n  expansion_slop = min_bytes_allocd() + 4 * MAXHINCR * HBLKSIZE;\n  if ((0 == GC_last_heap_addr && (ADDR(space) & SIGNB) == 0)\n      || (GC_last_heap_addr != 0 && GC_last_heap_addr < ADDR(space))) {\n    /* Assume the heap is growing up. */\n    if (LIKELY(ADDR(space) < GC_WORD_MAX - (sz + expansion_slop))) {\n      ptr_t new_limit = (ptr_t)space + sz + expansion_slop;\n\n      if (ADDR_LT((ptr_t)GC_greatest_plausible_heap_addr, new_limit))\n        GC_greatest_plausible_heap_addr = new_limit;\n    }\n  } else {\n    /* Heap is growing down. */\n    if (LIKELY(ADDR(space) > expansion_slop + sizeof(ptr_t))) {\n      ptr_t new_limit = (ptr_t)space - expansion_slop - sizeof(ptr_t);\n\n      if (ADDR_LT(new_limit, (ptr_t)GC_least_plausible_heap_addr))\n        GC_least_plausible_heap_addr = new_limit;\n    }\n  }\n  GC_last_heap_addr = ADDR(space);\n\n  GC_add_to_heap(space, sz);\n  if (GC_on_heap_resize)\n    (*GC_on_heap_resize)(GC_heapsize);\n\n  return TRUE;\n}\n\nGC_API int GC_CALL\nGC_expand_hp(size_t bytes)\n{\n  size_t n_blocks = OBJ_SZ_TO_BLOCKS_CHECKED(bytes);\n  word old_heapsize;\n  GC_bool result;\n\n  if (UNLIKELY(!GC_is_initialized))\n    GC_init();\n  LOCK();\n  old_heapsize = GC_heapsize;\n  result = GC_expand_hp_inner(n_blocks);\n  if (result) {\n    GC_requested_heapsize += bytes;\n    if (GC_dont_gc) {\n      /* Do not call `WARN()` if the heap growth is intentional. */\n      GC_ASSERT(GC_heapsize >= old_heapsize);\n      GC_heapsize_on_gc_disable += GC_heapsize - old_heapsize;\n    }\n  }\n  UNLOCK();\n  /*\n   * Really returns a `GC_bool` value, but the function is externally\n   * visible, so that is clumsy.\n   */\n  return (int)result;\n}\n\n/*\n * The minimum value of the ratio of allocated bytes since the latest\n * collection to the amount of finalizers created since that collection\n * which triggers the collection instead heap expansion.  Has no effect\n * in the incremental mode.\n */\n#if defined(GC_ALLOCD_BYTES_PER_FINALIZER) && !defined(CPPCHECK)\nSTATIC word GC_allocd_bytes_per_finalizer = GC_ALLOCD_BYTES_PER_FINALIZER;\n#else\nSTATIC word GC_allocd_bytes_per_finalizer = 10000;\n#endif\n\nGC_API void GC_CALL\nGC_set_allocd_bytes_per_finalizer(GC_word value)\n{\n  GC_allocd_bytes_per_finalizer = value;\n}\n\nGC_API GC_word GC_CALL\nGC_get_allocd_bytes_per_finalizer(void)\n{\n  return GC_allocd_bytes_per_finalizer;\n}\n\nGC_INNER GC_bool\nGC_collect_or_expand(word needed_blocks, unsigned flags, GC_bool retry)\n{\n  static word last_fo_entries, last_bytes_finalized;\n\n  GC_bool gc_not_stopped = TRUE;\n  word blocks_to_get;\n  IF_CANCEL(int cancel_state;)\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_is_initialized);\n  DISABLE_CANCEL(cancel_state);\n  if (!GC_incremental && !GC_dont_gc\n      && ((GC_dont_expand && GC_bytes_allocd > 0)\n          || (GC_fo_entries > last_fo_entries\n              && (last_bytes_finalized | GC_bytes_finalized) != 0\n              && (GC_fo_entries - last_fo_entries)\n                         * GC_allocd_bytes_per_finalizer\n                     > GC_bytes_allocd)\n          || GC_should_collect())) {\n    /*\n     * Try to do a full collection using \"default\" `stop_func` (unless\n     * nothing has been allocated since the latest collection or heap\n     * expansion is disabled).\n     */\n    gc_not_stopped = GC_try_to_collect_inner(\n        GC_bytes_allocd > 0 && (!GC_dont_expand || !retry)\n            ? GC_default_stop_func\n            : GC_never_stop_func);\n    if (gc_not_stopped || !retry) {\n      /*\n       * Either the collection has not been aborted or this is the\n       * first attempt (in a loop).\n       */\n      last_fo_entries = GC_fo_entries;\n      last_bytes_finalized = GC_bytes_finalized;\n      RESTORE_CANCEL(cancel_state);\n      return TRUE;\n    }\n  }\n\n  blocks_to_get = (GC_heapsize - GC_heapsize_at_forced_unmap)\n                      / (HBLKSIZE * GC_free_space_divisor)\n                  + needed_blocks;\n  if (blocks_to_get > MAXHINCR) {\n#ifdef NO_BLACK_LISTING\n    UNUSED_ARG(flags);\n    blocks_to_get = needed_blocks > MAXHINCR ? needed_blocks : MAXHINCR;\n#else\n    word slop;\n\n    /*\n     * Get the minimum required to make it likely that we can satisfy\n     * the current request in the presence of black-listing.  This will\n     * probably be bigger than `MAXHINCR`.\n     */\n    if ((flags & IGNORE_OFF_PAGE) != 0) {\n      slop = 4;\n    } else {\n      slop = 2 * divHBLKSZ(BL_LIMIT);\n      if (slop > needed_blocks)\n        slop = needed_blocks;\n    }\n    if (needed_blocks + slop > MAXHINCR) {\n      blocks_to_get = needed_blocks + slop;\n    } else {\n      blocks_to_get = MAXHINCR;\n    }\n#endif\n    if (blocks_to_get > divHBLKSZ(GC_WORD_MAX))\n      blocks_to_get = divHBLKSZ(GC_WORD_MAX);\n  } else if (blocks_to_get < MINHINCR) {\n    blocks_to_get = MINHINCR;\n  }\n\n  if (GC_max_heapsize > GC_heapsize) {\n    word max_get_blocks = divHBLKSZ(GC_max_heapsize - GC_heapsize);\n    if (blocks_to_get > max_get_blocks)\n      blocks_to_get\n          = max_get_blocks > needed_blocks ? max_get_blocks : needed_blocks;\n  }\n\n#ifdef USE_MUNMAP\n  if (GC_unmap_threshold > 1) {\n    /*\n     * Return as much memory to the OS as possible before trying to\n     * get memory from it.\n     */\n    GC_unmap_old(0);\n  }\n#endif\n  if (!GC_expand_hp_inner(blocks_to_get)\n      && (blocks_to_get == needed_blocks\n          || !GC_expand_hp_inner(needed_blocks))) {\n    if (!gc_not_stopped) {\n      /* Do not increment `GC_alloc_fail_count` here (and no warning). */\n      GC_gcollect_inner();\n      GC_ASSERT(0 == GC_bytes_allocd);\n    } else if (GC_alloc_fail_count++ < GC_max_retries) {\n      WARN(\"Out of Memory!  Trying to continue...\\n\", 0);\n      GC_gcollect_inner();\n    } else {\n#ifdef USE_MUNMAP\n      GC_ASSERT(GC_heapsize >= GC_unmapped_bytes);\n#endif\n#if !defined(SMALL_CONFIG) && (CPP_WORDSZ >= 32)\n#  define MAX_HEAPSIZE_WARNED_IN_BYTES (5 << 20) /*< 5 MB */\n\n      if (GC_heapsize > (word)MAX_HEAPSIZE_WARNED_IN_BYTES) {\n        WARN(\"Out of Memory! Heap size: %\" WARN_PRIuPTR \" MiB.\"\n             \" Returning NULL!\\n\",\n             (GC_heapsize - GC_unmapped_bytes) >> 20);\n      } else\n#endif\n      /* else */ {\n        WARN(\"Out of Memory! Heap size: %\" WARN_PRIuPTR \" bytes.\"\n             \" Returning NULL!\\n\",\n             GC_heapsize - GC_unmapped_bytes);\n      }\n      RESTORE_CANCEL(cancel_state);\n      return FALSE;\n    }\n  } else if (GC_alloc_fail_count > 0) {\n    GC_COND_LOG_PRINTF(\"Memory available again...\\n\");\n  }\n  RESTORE_CANCEL(cancel_state);\n  return TRUE;\n}\n\nGC_INNER ptr_t\nGC_allocobj(size_t lg, int kind)\n{\n#define MAX_ALLOCOBJ_RETRIES 3\n  int retry_cnt = 0;\n  void **flh = &GC_obj_kinds[kind].ok_freelist[lg];\n#ifndef GC_DISABLE_INCREMENTAL\n  GC_bool tried_minor = FALSE;\n#endif\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_is_initialized);\n  if (UNLIKELY(0 == lg))\n    return NULL;\n\n  while (NULL == *flh) {\n    /*\n     * Only a few iterations are expected at most, otherwise something\n     * is wrong in one of the functions called below.\n     */\n    if (retry_cnt > MAX_ALLOCOBJ_RETRIES)\n      ABORT(\"Too many retries in GC_allocobj\");\n#ifndef GC_DISABLE_INCREMENTAL\n    if (GC_incremental && GC_time_limit != GC_TIME_UNLIMITED && !GC_dont_gc) {\n      /*\n       * True incremental mode, not just generational.\n       * Do our share of marking work.\n       */\n      GC_collect_a_little_inner(1);\n    }\n#endif\n    /* Sweep blocks for objects of this size. */\n    GC_ASSERT(!GC_is_full_gc || NULL == GC_obj_kinds[kind].ok_reclaim_list\n              || NULL == GC_obj_kinds[kind].ok_reclaim_list[lg]);\n    GC_continue_reclaim(lg, kind);\n#if defined(CPPCHECK)\n    GC_noop1_ptr(&flh);\n#endif\n    if (*flh != NULL)\n      break;\n\n    GC_new_hblk(lg, kind);\n#if defined(CPPCHECK)\n    GC_noop1_ptr(&flh);\n#endif\n    if (*flh != NULL)\n      break;\n\n#ifndef GC_DISABLE_INCREMENTAL\n    if (GC_incremental && GC_time_limit == GC_TIME_UNLIMITED && !tried_minor\n        && !GC_dont_gc) {\n      GC_collect_a_little_inner(1);\n      tried_minor = TRUE;\n      continue;\n    }\n#endif\n    if (UNLIKELY(!GC_collect_or_expand(1, 0 /* flags */, retry_cnt > 0)))\n      return NULL;\n    retry_cnt++;\n  }\n  /* Successful allocation; reset failure count. */\n  GC_alloc_fail_count = 0;\n  return (ptr_t)(*flh);\n}\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1997 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2007 Free Software Foundation, Inc.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#ifndef MSWINCE\n#  include <errno.h>\n#endif\n#include <string.h>\n\n#ifdef KEEP_BACK_PTRS\n\n/*\n * Use a custom trivial `random()` implementation as the standard one might\n * lead to crashes (if used from a multi-threaded code) or to a compiler\n * warning about the deterministic result.\n */\nstatic int\nGC_rand(void)\n{\n  static GC_RAND_STATE_T seed;\n\n  return GC_RAND_NEXT(&seed);\n}\n\n#  define RANDOM() (long)GC_rand()\n\nGC_INNER void\nGC_store_back_pointer(ptr_t source, ptr_t dest)\n{\n  if (GC_HAS_DEBUG_INFO(dest)) {\n#  ifdef PARALLEL_MARK\n    GC_cptr_store((volatile ptr_t *)&((oh *)dest)->oh_back_ptr,\n                  (ptr_t)HIDE_BACK_PTR(source));\n#  else\n    ((oh *)dest)->oh_back_ptr = HIDE_BACK_PTR(source);\n#  endif\n  }\n}\n\nGC_INNER void\nGC_marked_for_finalization(ptr_t dest)\n{\n  GC_store_back_pointer(MARKED_FOR_FINALIZATION, dest);\n}\n\nGC_API GC_ref_kind GC_CALL\nGC_get_back_ptr_info(void *dest, void **base_p, size_t *offset_p)\n{\n  oh *ohdr = (oh *)GC_base(dest);\n  ptr_t bp, bp_base;\n\n#  ifdef LINT2\n  /*\n   * Explicitly instruct the code analysis tool that `GC_get_back_ptr_info`\n   * is not expected to be called with an incorrect `dest` value.\n   */\n  if (!ohdr)\n    ABORT(\"Invalid GC_get_back_ptr_info argument\");\n#  endif\n  if (!GC_HAS_DEBUG_INFO((ptr_t)ohdr))\n    return GC_NO_SPACE;\n  bp = (ptr_t)GC_REVEAL_POINTER(ohdr->oh_back_ptr);\n  if (MARKED_FOR_FINALIZATION == bp)\n    return GC_FINALIZER_REFD;\n  if (MARKED_FROM_REGISTER == bp)\n    return GC_REFD_FROM_REG;\n  if (NOT_MARKED == bp)\n    return GC_UNREFERENCED;\n#  if ALIGNMENT == 1\n  /*\n   * Heuristically try to fix off-by-one errors we introduced by\n   * insisting on even addresses.\n   */\n  {\n    ptr_t alternate_ptr = bp + 1;\n    ptr_t target = *(ptr_t *)bp;\n    ptr_t alternate_target = *(ptr_t *)alternate_ptr;\n\n    if (GC_least_real_heap_addr < ADDR(alternate_target)\n        && ADDR(alternate_target) < GC_greatest_real_heap_addr\n        && (GC_least_real_heap_addr >= ADDR(target)\n            || ADDR(target) >= GC_greatest_real_heap_addr)) {\n      bp = alternate_ptr;\n    }\n  }\n#  endif\n  bp_base = (ptr_t)GC_base(bp);\n  if (NULL == bp_base) {\n    *base_p = bp;\n    *offset_p = 0;\n    return GC_REFD_FROM_ROOT;\n  } else {\n    if (GC_HAS_DEBUG_INFO(bp_base))\n      bp_base += sizeof(oh);\n    *base_p = bp_base;\n    *offset_p = (size_t)(bp - bp_base);\n    return GC_REFD_FROM_HEAP;\n  }\n}\n\nGC_API void *GC_CALL\nGC_generate_random_heap_address(void)\n{\n  size_t i;\n  word heap_offset = (word)RANDOM();\n\n  if (GC_heapsize > (word)GC_RAND_MAX) {\n    heap_offset *= GC_RAND_MAX;\n    heap_offset += (word)RANDOM();\n  }\n\n  /*\n   * This does not yield a uniform distribution, especially if e.g.\n   * `RAND_MAX` is `1.5 * GC_heapsize`.  But for typical cases,  it is\n   * not too bad.\n   */\n  heap_offset %= GC_heapsize;\n\n  for (i = 0;; ++i) {\n    size_t size;\n\n    if (i >= GC_n_heap_sects)\n      ABORT(\"GC_generate_random_heap_address: size inconsistency\");\n\n    size = GC_heap_sects[i].hs_bytes;\n    if (heap_offset < size)\n      break;\n    heap_offset -= size;\n  }\n  return GC_heap_sects[i].hs_start + heap_offset;\n}\n\nGC_API void *GC_CALL\nGC_generate_random_valid_address(void)\n{\n  ptr_t result;\n  ptr_t base;\n\n  do {\n    result = (ptr_t)GC_generate_random_heap_address();\n    base = (ptr_t)GC_base(result);\n  } while (NULL == base || !GC_is_marked(base));\n  return result;\n}\n\nGC_API void GC_CALL\nGC_print_backtrace(void *p)\n{\n  void *current = p;\n  int i;\n\n  GC_ASSERT(I_DONT_HOLD_LOCK());\n  GC_print_heap_obj((ptr_t)GC_base(current));\n\n  for (i = 0;; ++i) {\n    void *base;\n    size_t offset;\n    GC_ref_kind source = GC_get_back_ptr_info(current, &base, &offset);\n\n    if (GC_UNREFERENCED == source) {\n      GC_err_printf(\"Reference could not be found\\n\");\n      break;\n    }\n    if (GC_NO_SPACE == source) {\n      GC_err_printf(\"No debug info in object: Can't find reference\\n\");\n      break;\n    }\n    GC_err_printf(\"Reachable via %d levels of pointers from \", i);\n    switch (source) {\n    case GC_REFD_FROM_ROOT:\n      GC_err_printf(\"root at %p\\n\\n\", base);\n      return;\n    case GC_REFD_FROM_REG:\n      GC_err_printf(\"root in register\\n\\n\");\n      return;\n    case GC_FINALIZER_REFD:\n      GC_err_printf(\"list of finalizable objects\\n\\n\");\n      return;\n    case GC_REFD_FROM_HEAP:\n      GC_err_printf(\"offset %ld in object:\\n\", (long)offset);\n      /* Take `GC_base(base)` to get real base, i.e. header. */\n      GC_print_heap_obj((ptr_t)GC_base(base));\n      break;\n    default:\n      GC_err_printf(\"INTERNAL ERROR: UNEXPECTED SOURCE!!!!\\n\");\n      return;\n    }\n    current = base;\n  }\n}\n\nGC_API void GC_CALL\nGC_generate_random_backtrace(void)\n{\n  void *current;\n\n  GC_ASSERT(I_DONT_HOLD_LOCK());\n  if (GC_try_to_collect(GC_never_stop_func) == 0) {\n    GC_err_printf(\"Cannot generate a backtrace: \"\n                  \"garbage collection is disabled!\\n\");\n    return;\n  }\n\n  /* Generate/print a backtrace from a random heap address. */\n  LOCK();\n  current = GC_generate_random_valid_address();\n  UNLOCK();\n  GC_printf(\"\\n***Chosen address %p in object\\n\", current);\n  GC_print_backtrace(current);\n}\n\n#endif /* KEEP_BACK_PTRS */\n\n#define CROSSES_HBLK(p, sz) \\\n  ((ADDR((p) + (sizeof(oh) - 1) + (sz)) ^ ADDR(p)) >= HBLKSIZE)\n\n/*\n * Store debugging info into `p`.  Return displaced pointer.  Assume we hold\n * the allocator lock.\n */\nSTATIC void *\nGC_store_debug_info_inner(void *base, size_t sz, const char *string,\n                          int linenum)\n{\n  GC_uintptr_t *result = (GC_uintptr_t *)((oh *)base + 1);\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_size(base) >= sizeof(oh) + sz);\n  GC_ASSERT(!(SMALL_OBJ(sz) && CROSSES_HBLK((ptr_t)base, sz)));\n#ifdef KEEP_BACK_PTRS\n  ((oh *)base)->oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED);\n#endif\n#ifdef MAKE_BACK_GRAPH\n  ((oh *)base)->oh_bg_ptr = HIDE_BACK_PTR((ptr_t)0);\n#endif\n  ((oh *)base)->oh_string = string;\n  ((oh *)base)->oh_int = linenum;\n#ifdef SHORT_DBG_HDRS\n  UNUSED_ARG(sz);\n#else\n  ((oh *)base)->oh_sz = (GC_uintptr_t)sz;\n  ((oh *)base)->oh_sf = START_FLAG ^ (GC_uintptr_t)result;\n  ((GC_uintptr_t *)base)[BYTES_TO_PTRS(GC_size(base)) - 1]\n      = result[BYTES_TO_PTRS_ROUNDUP(sz)] = END_FLAG ^ (GC_uintptr_t)result;\n#endif\n  return result;\n}\n\n#ifndef SHORT_DBG_HDRS\n/*\n * Check the object with debugging info at `ohdr`.  Return `NULL` if it\n * is OK.  Else return clobbered address.\n */\nSTATIC ptr_t\nGC_check_annotated_obj(oh *ohdr)\n{\n  ptr_t body = (ptr_t)(ohdr + 1);\n  size_t gc_sz = GC_size(ohdr);\n  size_t lpw_up;\n\n  if (ohdr->oh_sz + DEBUG_BYTES > (GC_uintptr_t)gc_sz) {\n    return (ptr_t)(&ohdr->oh_sz);\n  }\n  if (ohdr->oh_sf != (START_FLAG ^ (GC_uintptr_t)body)) {\n    return (ptr_t)(&ohdr->oh_sf);\n  }\n\n  {\n    size_t lpw_m1 = BYTES_TO_PTRS(gc_sz) - 1;\n\n    if (((GC_uintptr_t *)ohdr)[lpw_m1] != (END_FLAG ^ (GC_uintptr_t)body)) {\n      return (ptr_t)(&((GC_uintptr_t *)ohdr)[lpw_m1]);\n    }\n  }\n  lpw_up = BYTES_TO_PTRS_ROUNDUP((size_t)ohdr->oh_sz);\n  if (((GC_uintptr_t *)body)[lpw_up] != (END_FLAG ^ (GC_uintptr_t)body)) {\n    return (ptr_t)(&((GC_uintptr_t *)body)[lpw_up]);\n  }\n  return NULL;\n}\n#endif /* !SHORT_DBG_HDRS */\n\nSTATIC GC_describe_type_fn GC_describe_type_fns[MAXOBJKINDS] = { 0 };\n\nGC_API void GC_CALL\nGC_register_describe_type_fn(int kind, GC_describe_type_fn fn)\n{\n  GC_ASSERT((unsigned)kind < MAXOBJKINDS);\n  GC_describe_type_fns[kind] = fn;\n}\n\n#ifndef SHORT_DBG_HDRS\n#  define IF_NOT_SHORTDBG_HDRS(x) x\n#  define COMMA_IFNOT_SHORTDBG_HDRS(x) /* comma */ , x\n#else\n#  define IF_NOT_SHORTDBG_HDRS(x)\n#  define COMMA_IFNOT_SHORTDBG_HDRS(x)\n#endif\n\n/*\n * Print a human-readable description of the object to `stderr`.\n * The object is assumed to have the debugging info.\n */\nSTATIC void\nGC_print_obj(ptr_t base)\n{\n  oh *ohdr = (oh *)base;\n  ptr_t q;\n  hdr *hhdr;\n  int kind;\n  const char *kind_str;\n  char buffer[GC_TYPE_DESCR_LEN + 1];\n\n  GC_ASSERT(I_DONT_HOLD_LOCK());\n#ifdef LINT2\n  if (!ohdr)\n    ABORT(\"Invalid GC_print_obj argument\");\n#endif\n\n  q = (ptr_t)(ohdr + 1);\n  /*\n   * Print a type description for the object whose client-visible address\n   * is `q`.\n   */\n  hhdr = GC_find_header(q);\n  kind = hhdr->hb_obj_kind;\n  if (GC_describe_type_fns[kind] != 0 && GC_is_marked(ohdr)) {\n    /*\n     * This should preclude free-list objects except with thread-local\n     * allocation.\n     */\n    buffer[GC_TYPE_DESCR_LEN] = 0;\n    (*GC_describe_type_fns[kind])(q, buffer);\n    GC_ASSERT(buffer[GC_TYPE_DESCR_LEN] == 0);\n    kind_str = buffer;\n  } else {\n    switch (kind) {\n    case PTRFREE:\n      kind_str = \"PTRFREE\";\n      break;\n    case NORMAL:\n      kind_str = \"NORMAL\";\n      break;\n    case UNCOLLECTABLE:\n      kind_str = \"UNCOLLECTABLE\";\n      break;\n#ifdef GC_ATOMIC_UNCOLLECTABLE\n    case AUNCOLLECTABLE:\n      kind_str = \"ATOMIC_UNCOLLECTABLE\";\n      break;\n#endif\n    default:\n      kind_str = NULL;\n      /*\n       * The alternative is to use `snprintf(buffer)` but the latter is\n       * not quite portable (see `vsnprintf` in `misc.c` file).\n       */\n    }\n  }\n\n  if (NULL != kind_str) {\n    GC_err_printf(\"%p (%s:%d,\" IF_NOT_SHORTDBG_HDRS(\" sz= %lu,\") \" %s)\\n\",\n                  (void *)((ptr_t)ohdr + sizeof(oh)), ohdr->oh_string,\n                  GET_OH_LINENUM(ohdr) /*, */\n                  COMMA_IFNOT_SHORTDBG_HDRS((unsigned long)ohdr->oh_sz),\n                  kind_str);\n  } else {\n    GC_err_printf(\"%p (%s:%d,\" IF_NOT_SHORTDBG_HDRS(\n                      \" sz= %lu,\") \" kind= %d, descr= 0x%lx)\\n\",\n                  (void *)((ptr_t)ohdr + sizeof(oh)), ohdr->oh_string,\n                  GET_OH_LINENUM(ohdr) /*, */\n                  COMMA_IFNOT_SHORTDBG_HDRS((unsigned long)ohdr->oh_sz),\n                  kind, (unsigned long)hhdr->hb_descr);\n  }\n  PRINT_CALL_CHAIN(ohdr);\n}\n\nSTATIC void\nGC_debug_print_heap_obj_proc(ptr_t base)\n{\n  GC_ASSERT(I_DONT_HOLD_LOCK());\n  if (GC_HAS_DEBUG_INFO(base)) {\n    GC_print_obj(base);\n  } else {\n    GC_default_print_heap_obj_proc(base);\n  }\n}\n\n#ifndef SHORT_DBG_HDRS\nSTATIC void GC_check_heap_proc(void);\n#elif !defined(NO_FIND_LEAK)\nstatic void\ndo_nothing(void)\n{\n}\n#endif /* SHORT_DBG_HDRS */\n\n/*\n * Turn on the debugging mode.  Should not be called if\n * `GC_debugging_initialized` is already set.\n */\nSTATIC void\nGC_start_debugging_inner(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n#ifndef SHORT_DBG_HDRS\n  GC_check_heap = GC_check_heap_proc;\n  GC_print_all_smashed = GC_print_all_smashed_proc;\n#elif !defined(NO_FIND_LEAK)\n  GC_check_heap = do_nothing;\n  GC_print_all_smashed = do_nothing;\n#endif\n  GC_print_heap_obj = GC_debug_print_heap_obj_proc;\n  GC_debugging_initialized = TRUE;\n  GC_register_displacement_inner(sizeof(oh));\n#if defined(CPPCHECK)\n  GC_noop1(GC_debug_header_size);\n#endif\n}\n\n/*\n * Check the allocation is successful, store debugging info into `base`,\n * start the debugging mode (if not yet), and return displaced pointer.\n */\nstatic void *\nstore_debug_info(void *base, size_t lb, const char *fn, GC_EXTRA_PARAMS)\n{\n  void *result;\n\n  if (NULL == base) {\n    GC_err_printf(\"%s(%lu) returning NULL (%s:%d)\\n\", fn, (unsigned long)lb, s,\n                  i);\n    return NULL;\n  }\n  LOCK();\n  if (!GC_debugging_initialized)\n    GC_start_debugging_inner();\n  result = GC_store_debug_info_inner(base, lb, s, i);\n  ADD_CALL_CHAIN(base, ra);\n  UNLOCK();\n  return result;\n}\n\nconst size_t GC_debug_header_size = sizeof(oh);\n\nGC_API size_t GC_CALL\nGC_get_debug_header_size(void)\n{\n  return sizeof(oh);\n}\n\nGC_API void GC_CALL\nGC_debug_register_displacement(size_t offset)\n{\n  LOCK();\n  GC_register_displacement_inner(offset);\n  GC_register_displacement_inner(sizeof(oh) + offset);\n  UNLOCK();\n}\n\n#ifdef GC_ADD_CALLER\n#  if defined(HAVE_DLADDR) && defined(GC_HAVE_RETURN_ADDR_PARENT) \\\n      && defined(FUNCPTR_IS_DATAPTR)\n#    include <dlfcn.h>\n\nSTATIC void\nGC_caller_func_offset(GC_return_addr_t ra, const char **symp, int *offp)\n{\n  Dl_info caller;\n\n  if (ra != 0 && dladdr((void *)ra, &caller) && caller.dli_sname != NULL) {\n    *symp = caller.dli_sname;\n    *offp = (int)((ptr_t)ra - (ptr_t)caller.dli_saddr);\n  }\n  if (NULL == *symp) {\n    *symp = \"unknown\";\n    /* Note: `*offp` is unchanged. */\n  }\n}\n#  else\n#    define GC_caller_func_offset(ra, symp, offp) (void)(*(symp) = \"unknown\")\n#  endif\n#endif /* GC_ADD_CALLER */\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_debug_malloc(size_t lb, GC_EXTRA_PARAMS)\n{\n  void *base;\n\n  /*\n   * Note that according to `malloc()` specification, if size (`lb`) is\n   * zero, then `malloc()` returns either `NULL`, or a unique pointer\n   * value that can later be successfully passed to `free()`.\n   * We always do the latter.\n   */\n#if defined(_FORTIFY_SOURCE) && !defined(__clang__)\n  /* Workaround to avoid \"exceeds maximum object size\" gcc warning. */\n  base = GC_malloc(lb < GC_SIZE_MAX - DEBUG_BYTES ? lb + DEBUG_BYTES\n                                                  : GC_SIZE_MAX >> 1);\n#else\n  base = GC_malloc(SIZET_SAT_ADD(lb, DEBUG_BYTES));\n#endif\n#ifdef GC_ADD_CALLER\n  if (NULL == s) {\n    GC_caller_func_offset(ra, &s, &i);\n  }\n#endif\n  return store_debug_info(base, lb, \"GC_debug_malloc\", OPT_RA s, i);\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_debug_malloc_ignore_off_page(size_t lb, GC_EXTRA_PARAMS)\n{\n  void *base = GC_malloc_ignore_off_page(SIZET_SAT_ADD(lb, DEBUG_BYTES));\n\n  return store_debug_info(base, lb, \"GC_debug_malloc_ignore_off_page\",\n                          OPT_RA s, i);\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_debug_malloc_atomic_ignore_off_page(size_t lb, GC_EXTRA_PARAMS)\n{\n  void *base\n      = GC_malloc_atomic_ignore_off_page(SIZET_SAT_ADD(lb, DEBUG_BYTES));\n\n  return store_debug_info(base, lb, \"GC_debug_malloc_atomic_ignore_off_page\",\n                          OPT_RA s, i);\n}\n\nSTATIC void *\nGC_debug_generic_malloc(size_t lb, int kind, GC_EXTRA_PARAMS)\n{\n  void *base = GC_generic_malloc_aligned(SIZET_SAT_ADD(lb, DEBUG_BYTES), kind,\n                                         0 /* `flags` */, 0 /* `align_m1` */);\n\n  return store_debug_info(base, lb, \"GC_debug_generic_malloc\", OPT_RA s, i);\n}\n\n#ifdef DBG_HDRS_ALL\nGC_INNER void *\nGC_debug_generic_malloc_inner(size_t lb, int kind, unsigned flags)\n{\n  void *base, *result;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  base = GC_generic_malloc_inner(SIZET_SAT_ADD(lb, DEBUG_BYTES), kind, flags);\n  if (NULL == base) {\n    GC_err_printf(\"GC internal allocation (%lu bytes) returning NULL\\n\",\n                  (unsigned long)lb);\n    return NULL;\n  }\n  if (!GC_debugging_initialized)\n    GC_start_debugging_inner();\n  result = GC_store_debug_info_inner(base, lb, \"INTERNAL\", 0);\n  ADD_CALL_CHAIN_INNER(base);\n  return result;\n}\n#endif /* DBG_HDRS_ALL */\n\n#ifndef CPPCHECK\nGC_API void *GC_CALL\nGC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS)\n{\n  return GC_debug_malloc(lb, OPT_RA s, i);\n}\n\nGC_API void GC_CALL\nGC_debug_change_stubborn(const void *p)\n{\n  UNUSED_ARG(p);\n}\n#endif /* !CPPCHECK */\n\nGC_API void GC_CALL\nGC_debug_end_stubborn_change(const void *p)\n{\n  const void *q = GC_base_C(p);\n\n  if (NULL == q) {\n    ABORT_ARG1(\"GC_debug_end_stubborn_change: bad arg\", \": %p\", p);\n  }\n  GC_end_stubborn_change(q);\n}\n\nGC_API void GC_CALL\nGC_debug_ptr_store_and_dirty(void *p, const void *q)\n{\n  *(void **)GC_is_visible(p)\n      = GC_is_valid_displacement(GC_CAST_AWAY_CONST_PVOID(q));\n  GC_debug_end_stubborn_change(p);\n  REACHABLE_AFTER_DIRTY(q);\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS)\n{\n  void *base = GC_malloc_atomic(SIZET_SAT_ADD(lb, DEBUG_BYTES));\n\n  return store_debug_info(base, lb, \"GC_debug_malloc_atomic\", OPT_RA s, i);\n}\n\nGC_API GC_ATTR_MALLOC char *GC_CALL\nGC_debug_strdup(const char *str, GC_EXTRA_PARAMS)\n{\n  char *copy;\n  size_t lb;\n  if (str == NULL) {\n    if (GC_find_leak_inner)\n      GC_err_printf(\"strdup(NULL) behavior is undefined\\n\");\n    return NULL;\n  }\n\n  lb = strlen(str) + 1;\n  copy = (char *)GC_debug_malloc_atomic(lb, OPT_RA s, i);\n  if (copy == NULL) {\n#ifndef MSWINCE\n    errno = ENOMEM;\n#endif\n    return NULL;\n  }\n  BCOPY(str, copy, lb);\n  return copy;\n}\n\nGC_API GC_ATTR_MALLOC char *GC_CALL\nGC_debug_strndup(const char *str, size_t size, GC_EXTRA_PARAMS)\n{\n  char *copy;\n  /* `str` is expected to be non-`NULL`. */\n  size_t len = strlen(str);\n\n  if (len > size)\n    len = size;\n  copy = (char *)GC_debug_malloc_atomic(len + 1, OPT_RA s, i);\n  if (copy == NULL) {\n#ifndef MSWINCE\n    errno = ENOMEM;\n#endif\n    return NULL;\n  }\n  if (len > 0)\n    BCOPY(str, copy, len);\n  copy[len] = '\\0';\n  return copy;\n}\n\n#ifdef GC_REQUIRE_WCSDUP\n#  include <wchar.h> /*< for `wcslen()` */\n\nGC_API GC_ATTR_MALLOC wchar_t *GC_CALL\nGC_debug_wcsdup(const wchar_t *str, GC_EXTRA_PARAMS)\n{\n  size_t lb = (wcslen(str) + 1) * sizeof(wchar_t);\n  wchar_t *copy = (wchar_t *)GC_debug_malloc_atomic(lb, OPT_RA s, i);\n  if (copy == NULL) {\n#  ifndef MSWINCE\n    errno = ENOMEM;\n#  endif\n    return NULL;\n  }\n  BCOPY(str, copy, lb);\n  return copy;\n}\n#endif /* GC_REQUIRE_WCSDUP */\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_debug_malloc_uncollectable(size_t lb, GC_EXTRA_PARAMS)\n{\n  void *base\n      = GC_malloc_uncollectable(SIZET_SAT_ADD(lb, UNCOLLECTABLE_DEBUG_BYTES));\n\n  return store_debug_info(base, lb, \"GC_debug_malloc_uncollectable\", OPT_RA s,\n                          i);\n}\n\n#ifdef GC_ATOMIC_UNCOLLECTABLE\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_debug_malloc_atomic_uncollectable(size_t lb, GC_EXTRA_PARAMS)\n{\n  void *base = GC_malloc_atomic_uncollectable(\n      SIZET_SAT_ADD(lb, UNCOLLECTABLE_DEBUG_BYTES));\n\n  return store_debug_info(base, lb, \"GC_debug_malloc_atomic_uncollectable\",\n                          OPT_RA s, i);\n}\n#endif /* GC_ATOMIC_UNCOLLECTABLE */\n\n#ifdef LINT2\n/*\n * Copyright (c) 1996-1998 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2018-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/* This file is kept for a binary compatibility purpose only. */\n\n#ifndef GC_ALLOC_PTRS_H\n#define GC_ALLOC_PTRS_H\n\n\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifndef GC_API_PRIV\n#  define GC_API_PRIV GC_API\n#endif\n\n/*\n * Some compilers do not accept `const` together with the `dllimport`\n * attribute, so the symbols below are exported as non-constant ones.\n */\n#ifndef GC_APIVAR_CONST\n#  if defined(GC_BUILD) || !defined(GC_DLL)\n#    define GC_APIVAR_CONST const\n#  else\n#    define GC_APIVAR_CONST /*< empty */\n#  endif\n#endif\n\nGC_API_PRIV void **GC_APIVAR_CONST GC_objfreelist_ptr;\nGC_API_PRIV void **GC_APIVAR_CONST GC_aobjfreelist_ptr;\nGC_API_PRIV void **GC_APIVAR_CONST GC_uobjfreelist_ptr;\n\n#ifdef GC_ATOMIC_UNCOLLECTABLE\nGC_API_PRIV void **GC_APIVAR_CONST GC_auobjfreelist_ptr;\n#endif\n\n/*\n * Manually update the number of bytes allocated during the current\n * collection cycle and the number of explicitly deallocated bytes of\n * memory since the last collection, respectively.  Both functions are\n * unsynchronized, `GC_call_with_alloc_lock()` should be used to avoid\n * data race.\n */\nGC_API_PRIV void GC_CALL GC_incr_bytes_allocd(size_t /* `bytes` */);\nGC_API_PRIV void GC_CALL GC_incr_bytes_freed(size_t /* `bytes` */);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#endif /* GC_ALLOC_PTRS_H */\n\n#endif\n\nGC_API void GC_CALL\nGC_debug_free(void *p)\n{\n  ptr_t base;\n  if (0 == p)\n    return;\n\n  base = (ptr_t)GC_base(p);\n  if (NULL == base) {\n#if defined(REDIRECT_MALLOC)                                           \\\n    && ((defined(NEED_CALLINFO) && defined(GC_HAVE_BUILTIN_BACKTRACE)) \\\n        || defined(REDIR_MALLOC_AND_LINUXTHREADS)                      \\\n        || (defined(SOLARIS) && defined(THREADS)) || defined(MSWIN32))\n    /*\n     * In some cases, we should ignore objects that do not belong to\n     * the collector heap.  See the comment in `GC_free()`.\n     */\n    if (!GC_is_heap_ptr(p))\n      return;\n#endif\n    ABORT_ARG1(\"Invalid pointer passed to free()\", \": %p\", p);\n  }\n  if ((word)((ptr_t)p - base) != sizeof(oh)) {\n#if defined(REDIRECT_FREE) && defined(USE_PROC_FOR_LIBRARIES)\n    /*\n     * TODO: Suppress the warning if `free()` caller is in `libpthread`\n     * or `libdl`.\n     */\n#endif\n    /*\n     * TODO: Suppress the warning for objects allocated by `GC_memalign`\n     * and friends (these ones do not have the debugging counterpart).\n     */\n    GC_err_printf(\"GC_debug_free called on pointer %p w/o debugging info\\n\",\n                  p);\n  } else {\n#ifndef SHORT_DBG_HDRS\n    ptr_t clobbered = GC_check_annotated_obj((oh *)base);\n    size_t sz = GC_size(base);\n\n    if (clobbered != NULL) {\n      /* No \"release\" barrier is needed. */\n      GC_SET_HAVE_ERRORS();\n      if (((oh *)base)->oh_sz == (GC_uintptr_t)sz) {\n        GC_print_smashed_obj(\n            \"GC_debug_free: found previously deallocated (?) object at\", p,\n            clobbered);\n        /* Ignore double free. */\n        return;\n      } else {\n        GC_print_smashed_obj(\"GC_debug_free: found smashed location at\", p,\n                             clobbered);\n      }\n    }\n    /* Invalidate the size (mark the object as deallocated). */\n    ((oh *)base)->oh_sz = (GC_uintptr_t)sz;\n#endif /* !SHORT_DBG_HDRS */\n  }\n#ifndef NO_FIND_LEAK\n  if (GC_find_leak_inner\n#  ifndef SHORT_DBG_HDRS\n      && ((word)((ptr_t)p - base) != sizeof(oh) || !GC_findleak_delay_free)\n#  endif\n  ) {\n    GC_free(base);\n  } else\n#endif\n  /* else */ {\n    const hdr *hhdr = HDR(p);\n\n    if (hhdr->hb_obj_kind == UNCOLLECTABLE\n#ifdef GC_ATOMIC_UNCOLLECTABLE\n        || hhdr->hb_obj_kind == AUNCOLLECTABLE\n#endif\n    ) {\n      GC_free(base);\n    } else {\n      size_t sz = hhdr->hb_sz;\n      size_t i;\n      size_t lpw = BYTES_TO_PTRS(sz - sizeof(oh));\n\n      for (i = 0; i < lpw; ++i)\n        ((GC_uintptr_t *)p)[i] = GC_FREED_MEM_MARKER;\n      GC_ASSERT((GC_uintptr_t *)p + i == (GC_uintptr_t *)(base + sz));\n      /*\n       * Update the counter even though the real deallocation\n       * is deferred.\n       */\n      LOCK();\n#ifdef LINT2\n      GC_incr_bytes_freed(sz);\n#else\n      GC_bytes_freed += sz;\n#endif\n      UNLOCK();\n    }\n  }\n}\n\n#if defined(THREADS) && defined(DBG_HDRS_ALL)\nGC_INNER void\nGC_debug_free_inner(void *p)\n{\n  ptr_t base = (ptr_t)GC_base(p);\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT((word)((ptr_t)p - base) == sizeof(oh));\n#  ifdef LINT2\n  if (!base)\n    ABORT(\"Invalid GC_debug_free_inner argument\");\n#  endif\n#  ifndef SHORT_DBG_HDRS\n  /* Invalidate the size. */\n  ((oh *)base)->oh_sz = (GC_uintptr_t)GC_size(base);\n#  endif\n  GC_free_inner(base);\n}\n#endif\n\nGC_API void *GC_CALL\nGC_debug_realloc(void *p, size_t lb, GC_EXTRA_PARAMS)\n{\n  ptr_t base;\n  void *result;\n  const hdr *hhdr;\n\n  if (NULL == p) {\n    return GC_debug_malloc(lb, OPT_RA s, i);\n  }\n  if (0 == lb) /* `&& p != NULL` */ {\n    GC_debug_free(p);\n    return NULL;\n  }\n\n#ifdef GC_ADD_CALLER\n  if (NULL == s) {\n    GC_caller_func_offset(ra, &s, &i);\n  }\n#endif\n  base = (ptr_t)GC_base(p);\n  if (NULL == base) {\n    ABORT_ARG1(\"Invalid pointer passed to realloc()\", \": %p\", p);\n  }\n  if ((word)((ptr_t)p - base) != sizeof(oh)) {\n    GC_err_printf(\"GC_debug_realloc called on pointer %p w/o debugging info\\n\",\n                  p);\n    return GC_realloc(p, lb);\n  }\n  hhdr = HDR(base);\n  result\n      = GC_debug_generic_or_special_malloc(lb, hhdr->hb_obj_kind, OPT_RA s, i);\n  if (result != NULL) {\n    size_t old_sz;\n#ifdef SHORT_DBG_HDRS\n    old_sz = GC_size(base) - sizeof(oh);\n#else\n    old_sz = (size_t)(((oh *)base)->oh_sz);\n#endif\n    if (old_sz > 0)\n      BCOPY(p, result, old_sz < lb ? old_sz : lb);\n    GC_debug_free(p);\n  }\n  return result;\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_debug_generic_or_special_malloc(size_t lb, int kind, GC_EXTRA_PARAMS)\n{\n  switch (kind) {\n  case PTRFREE:\n    return GC_debug_malloc_atomic(lb, OPT_RA s, i);\n  case NORMAL:\n    return GC_debug_malloc(lb, OPT_RA s, i);\n  case UNCOLLECTABLE:\n    return GC_debug_malloc_uncollectable(lb, OPT_RA s, i);\n#ifdef GC_ATOMIC_UNCOLLECTABLE\n  case AUNCOLLECTABLE:\n    return GC_debug_malloc_atomic_uncollectable(lb, OPT_RA s, i);\n#endif\n  default:\n    return GC_debug_generic_malloc(lb, kind, OPT_RA s, i);\n  }\n}\n\n#ifndef SHORT_DBG_HDRS\n\n/*\n * Check all marked objects in the given block for validity.\n * Note: avoid `GC_apply_to_each_object` for performance reasons.\n */\nSTATIC void GC_CALLBACK\nGC_check_heap_block(struct hblk *hbp, void *dummy)\n{\n  const hdr *hhdr = HDR(hbp);\n  ptr_t p = hbp->hb_body;\n  ptr_t plim;\n  size_t sz = hhdr->hb_sz;\n  size_t bit_no;\n\n  UNUSED_ARG(dummy);\n  GC_ASSERT((ptr_t)hhdr->hb_block == p);\n  plim = sz > MAXOBJBYTES ? p : p + HBLKSIZE - sz;\n  /* Go through all objects in block. */\n  for (bit_no = 0; ADDR_GE(plim, p); bit_no += MARK_BIT_OFFSET(sz), p += sz) {\n    if (mark_bit_from_hdr(hhdr, bit_no) && GC_HAS_DEBUG_INFO(p)) {\n      ptr_t clobbered = GC_check_annotated_obj((oh *)p);\n\n      if (clobbered != NULL)\n        GC_add_smashed(clobbered);\n    }\n  }\n}\n\n/*\n * This assumes that all accessible objects are marked.\n * Normally called by collector.\n */\nSTATIC void\nGC_check_heap_proc(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_STATIC_ASSERT((sizeof(oh) & (GC_GRANULE_BYTES - 1)) == 0);\n  /* FIXME: Should we check for twice that alignment? */\n  GC_apply_to_all_blocks(GC_check_heap_block, NULL);\n}\n\n#endif /* !SHORT_DBG_HDRS */\n\n#ifndef GC_NO_FINALIZATION\n\nstruct closure {\n  GC_finalization_proc cl_fn;\n  void *cl_data;\n};\n\nSTATIC void *\nGC_make_closure(GC_finalization_proc fn, void *data)\n{\n  struct closure *result =\n#  ifdef DBG_HDRS_ALL\n      (struct closure *)GC_debug_malloc(sizeof(struct closure), GC_EXTRAS);\n#  else\n      (struct closure *)GC_malloc(sizeof(struct closure));\n#  endif\n  if (result != NULL) {\n    result->cl_fn = fn;\n    result->cl_data = data;\n  }\n  return result;\n}\n\n/*\n * An auxiliary function to make finalization work correctly with\n * displaced pointers introduced by the debugging allocators.\n */\nSTATIC void GC_CALLBACK\nGC_debug_invoke_finalizer(void *obj, void *data)\n{\n  struct closure *cl = (struct closure *)data;\n\n  cl->cl_fn((ptr_t)obj + sizeof(oh), cl->cl_data);\n}\n\n/* Special `finalizer_proc` value to detect `GC_register_finalizer` failure. */\n#  define OFN_UNSET ((GC_finalization_proc)(~(GC_funcptr_uint)0))\n\n/* Set `ofn` and `ocd` to reflect the values we got back. */\nstatic void\nstore_old(void *obj, GC_finalization_proc my_old_fn, struct closure *my_old_cd,\n          GC_finalization_proc *ofn, void **ocd)\n{\n  if (my_old_fn != 0) {\n    if (my_old_fn == OFN_UNSET) {\n      /* `GC_register_finalizer()` failed; `*ofn` and `*ocd` are unchanged. */\n      return;\n    }\n    if (my_old_fn != GC_debug_invoke_finalizer) {\n      GC_err_printf(\"Debuggable object at %p had a non-debug finalizer\\n\",\n                    obj);\n      /* This should probably be fatal. */\n    } else {\n      if (ofn)\n        *ofn = my_old_cd->cl_fn;\n      if (ocd)\n        *ocd = my_old_cd->cl_data;\n    }\n  } else {\n    if (ofn)\n      *ofn = 0;\n    if (ocd)\n      *ocd = NULL;\n  }\n}\n\nGC_API void GC_CALL\nGC_debug_register_finalizer(void *obj, GC_finalization_proc fn, void *cd,\n                            GC_finalization_proc *ofn, void **ocd)\n{\n  GC_finalization_proc my_old_fn = OFN_UNSET;\n  void *my_old_cd = NULL; /*< to avoid \"might be uninitialized\" warning */\n  ptr_t base = (ptr_t)GC_base(obj);\n\n  if (NULL == base) {\n    /* We will not collect it, hence finalizer would not be run. */\n    if (ocd)\n      *ocd = NULL;\n    if (ofn)\n      *ofn = 0;\n    return;\n  }\n  if ((ptr_t)obj - base != sizeof(oh)) {\n    GC_err_printf(\"GC_debug_register_finalizer called with\"\n                  \" non-base-pointer %p\\n\",\n                  obj);\n  }\n  if (0 == fn) {\n    GC_register_finalizer(base, 0, NULL, &my_old_fn, &my_old_cd);\n  } else {\n    cd = GC_make_closure(fn, cd);\n    if (NULL == cd) {\n      /* Out of memory; `*ofn` and `*ocd` are unchanged. */\n      return;\n    }\n    GC_register_finalizer(base, GC_debug_invoke_finalizer, cd, &my_old_fn,\n                          &my_old_cd);\n  }\n  store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);\n}\n\nGC_API void GC_CALL\nGC_debug_register_finalizer_no_order(void *obj, GC_finalization_proc fn,\n                                     void *cd, GC_finalization_proc *ofn,\n                                     void **ocd)\n{\n  GC_finalization_proc my_old_fn = OFN_UNSET;\n  void *my_old_cd = NULL;\n  ptr_t base = (ptr_t)GC_base(obj);\n  if (NULL == base) {\n    if (ocd)\n      *ocd = NULL;\n    if (ofn)\n      *ofn = 0;\n    return;\n  }\n  if ((ptr_t)obj - base != sizeof(oh)) {\n    GC_err_printf(\"GC_debug_register_finalizer_no_order called with\"\n                  \" non-base-pointer %p\\n\",\n                  obj);\n  }\n  if (0 == fn) {\n    GC_register_finalizer_no_order(base, 0, NULL, &my_old_fn, &my_old_cd);\n  } else {\n    cd = GC_make_closure(fn, cd);\n    if (NULL == cd) {\n      /* Out of memory. */\n      return;\n    }\n    GC_register_finalizer_no_order(base, GC_debug_invoke_finalizer, cd,\n                                   &my_old_fn, &my_old_cd);\n  }\n  store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);\n}\n\nGC_API void GC_CALL\nGC_debug_register_finalizer_unreachable(void *obj, GC_finalization_proc fn,\n                                        void *cd, GC_finalization_proc *ofn,\n                                        void **ocd)\n{\n  GC_finalization_proc my_old_fn = OFN_UNSET;\n  void *my_old_cd = NULL;\n  ptr_t base = (ptr_t)GC_base(obj);\n  if (NULL == base) {\n    if (ocd)\n      *ocd = NULL;\n    if (ofn)\n      *ofn = 0;\n    return;\n  }\n  if ((ptr_t)obj - base != sizeof(oh)) {\n    GC_err_printf(\"GC_debug_register_finalizer_unreachable called with\"\n                  \" non-base-pointer %p\\n\",\n                  obj);\n  }\n  if (0 == fn) {\n    GC_register_finalizer_unreachable(base, 0, NULL, &my_old_fn, &my_old_cd);\n  } else {\n    cd = GC_make_closure(fn, cd);\n    if (NULL == cd) {\n      /* Out of memory. */\n      return;\n    }\n    GC_register_finalizer_unreachable(base, GC_debug_invoke_finalizer, cd,\n                                      &my_old_fn, &my_old_cd);\n  }\n  store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);\n}\n\nGC_API void GC_CALL\nGC_debug_register_finalizer_ignore_self(void *obj, GC_finalization_proc fn,\n                                        void *cd, GC_finalization_proc *ofn,\n                                        void **ocd)\n{\n  GC_finalization_proc my_old_fn = OFN_UNSET;\n  void *my_old_cd = NULL;\n  ptr_t base = (ptr_t)GC_base(obj);\n  if (NULL == base) {\n    if (ocd)\n      *ocd = NULL;\n    if (ofn)\n      *ofn = 0;\n    return;\n  }\n  if ((ptr_t)obj - base != sizeof(oh)) {\n    GC_err_printf(\"GC_debug_register_finalizer_ignore_self called with\"\n                  \" non-base-pointer %p\\n\",\n                  obj);\n  }\n  if (0 == fn) {\n    GC_register_finalizer_ignore_self(base, 0, NULL, &my_old_fn, &my_old_cd);\n  } else {\n    cd = GC_make_closure(fn, cd);\n    if (NULL == cd) {\n      /* Out of memory. */\n      return;\n    }\n    GC_register_finalizer_ignore_self(base, GC_debug_invoke_finalizer, cd,\n                                      &my_old_fn, &my_old_cd);\n  }\n  store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);\n}\n\n#  ifndef GC_TOGGLE_REFS_NOT_NEEDED\nGC_API int GC_CALL\nGC_debug_toggleref_add(void *obj, int is_strong_ref)\n{\n  ptr_t base = (ptr_t)GC_base(obj);\n\n  if ((ptr_t)obj - base != sizeof(oh)) {\n    GC_err_printf(\"GC_debug_toggleref_add called with\"\n                  \" non-base-pointer %p\\n\",\n                  obj);\n  }\n  return GC_toggleref_add(base, is_strong_ref);\n}\n#  endif /* !GC_TOGGLE_REFS_NOT_NEEDED */\n\n#endif /* !GC_NO_FINALIZATION */\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_debug_malloc_replacement(size_t lb)\n{\n  return GC_debug_malloc(lb, GC_DBG_EXTRAS);\n}\n\nGC_API void *GC_CALL\nGC_debug_realloc_replacement(void *p, size_t lb)\n{\n  return GC_debug_realloc(p, lb, GC_DBG_EXTRAS);\n}\n\n#ifdef GC_GCJ_SUPPORT\n\n\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_debug_gcj_malloc(size_t lb, const void *vtable_ptr, GC_EXTRA_PARAMS)\n{\n  void *base, *result;\n\n  /* We are careful to avoid extra calls those could confuse the backtrace. */\n  LOCK();\n  /* A mechanism to invoke finalizers (same as in `GC_core_gcj_malloc`). */\n  if (GC_gc_no != GC_last_finalized_no) {\n    UNLOCK();\n    GC_notify_or_invoke_finalizers();\n    LOCK();\n    GC_last_finalized_no = GC_gc_no;\n  }\n\n  base = GC_generic_malloc_inner(SIZET_SAT_ADD(lb, DEBUG_BYTES),\n                                 GC_gcj_debug_kind, 0 /* `flags` */);\n  if (NULL == base) {\n    GC_oom_func oom_fn = GC_oom_fn;\n    UNLOCK();\n    GC_err_printf(\"GC_debug_gcj_malloc(%lu, %p) returning NULL (%s:%d)\\n\",\n                  (unsigned long)lb, vtable_ptr, s, i);\n    return (*oom_fn)(lb);\n  }\n  *((const void **)((ptr_t)base + sizeof(oh))) = vtable_ptr;\n  if (!GC_debugging_initialized)\n    GC_start_debugging_inner();\n  result = GC_store_debug_info_inner(base, lb, s, i);\n  ADD_CALL_CHAIN(base, ra);\n  UNLOCK();\n  GC_dirty(result);\n  REACHABLE_AFTER_DIRTY(vtable_ptr);\n  return result;\n}\n#endif /* GC_GCJ_SUPPORT */\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1996 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2007 Free Software Foundation, Inc.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#ifndef GC_NO_FINALIZATION\n#  include \"gc/javaxfc.h\" /*< to get `GC_finalize_all()` as `extern \"C\"` */\n\n/*\n * Type of mark procedure used for marking from finalizable object.\n * This procedure normally does not mark the object, only its descendants.\n */\ntypedef void (*finalization_mark_proc)(ptr_t /* `finalizable_obj_ptr` */);\n\n#  define HASH3(addr, size, log_size)                               \\\n    ((size_t)((ADDR(addr) >> 3) ^ (ADDR(addr) >> (3 + (log_size)))) \\\n     & ((size) - (size_t)1))\n#  define HASH2(addr, log_size) HASH3(addr, (size_t)1 << (log_size), log_size)\n\nstruct hash_chain_entry {\n  GC_hidden_pointer hidden_key;\n  struct hash_chain_entry *next;\n};\n\nstruct disappearing_link {\n  struct hash_chain_entry prolog;\n#  define dl_hidden_link prolog.hidden_key /*< field to be cleared */\n#  define dl_next(x) (struct disappearing_link *)((x)->prolog.next)\n#  define dl_set_next(x, y) \\\n    (void)((x)->prolog.next = (struct hash_chain_entry *)(y))\n  GC_hidden_pointer dl_hidden_obj; /*< pointer to object base */\n};\n\nstruct finalizable_object {\n  struct hash_chain_entry prolog;\n  /*\n   * Pointer to object base.  No longer hidden once object is on\n   * `finalize_now` queue.\n   */\n#  define fo_hidden_base prolog.hidden_key\n#  define fo_next(x) (struct finalizable_object *)((x)->prolog.next)\n#  define fo_set_next(x, y) ((x)->prolog.next = (struct hash_chain_entry *)(y))\n  GC_finalization_proc fo_fn;          /*< the finalizer */\n  finalization_mark_proc fo_mark_proc; /*< mark-through procedure */\n  ptr_t fo_client_data;\n  size_t fo_object_sz; /*< in bytes */\n};\n\n#  ifdef AO_HAVE_store\n/*\n * Update `finalize_now` atomically as `GC_should_invoke_finalizers`\n * does not acquire the allocator lock.\n */\n#    define SET_FINALIZE_NOW(fo) \\\n      GC_cptr_store((volatile ptr_t *)&GC_fnlz_roots.finalize_now, (ptr_t)(fo))\n#  else\n#    define SET_FINALIZE_NOW(fo) (void)(GC_fnlz_roots.finalize_now = (fo))\n#  endif /* !THREADS */\n\nGC_API void GC_CALL\nGC_push_finalizer_structures(void)\n{\n  GC_ASSERT(ADDR(&GC_dl_hashtbl.head) % ALIGNMENT == 0);\n  GC_ASSERT(ADDR(&GC_fnlz_roots) % ALIGNMENT == 0);\n#  ifndef GC_LONG_REFS_NOT_NEEDED\n  GC_ASSERT(ADDR(&GC_ll_hashtbl.head) % ALIGNMENT == 0);\n  GC_PUSH_ALL_SYM(GC_ll_hashtbl.head);\n#  endif\n  GC_PUSH_ALL_SYM(GC_dl_hashtbl.head);\n  GC_PUSH_ALL_SYM(GC_fnlz_roots);\n  /* `GC_toggleref_arr` is pushed specially by `GC_mark_togglerefs`. */\n}\n\n/*\n * Threshold of `log_size` to initiate full collection before growing\n * a hash table.\n */\n#  ifndef GC_ON_GROW_LOG_SIZE_MIN\n#    define GC_ON_GROW_LOG_SIZE_MIN LOG_HBLKSIZE\n#  endif\n\n/*\n * Ensure the hash table has enough capacity.  `*table_ptr` is a pointer\n * to an array of hash headers.  `*log_size_ptr` is the log of its current\n * size.  We update both `*table_ptr` and `*log_size_ptr` on success.\n */\nSTATIC void\nGC_grow_table(struct hash_chain_entry ***table_ptr, unsigned *log_size_ptr,\n              const size_t *entries_ptr)\n{\n  size_t i;\n  struct hash_chain_entry *p;\n  unsigned log_old_size = *log_size_ptr;\n  unsigned log_new_size = log_old_size + 1;\n  size_t old_size = NULL == *table_ptr ? 0 : (size_t)1 << log_old_size;\n  size_t new_size = (size_t)1 << log_new_size;\n  /* FIXME: Power-of-two size often gets rounded up to one more page. */\n  struct hash_chain_entry **new_table;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  /*\n   * Avoid growing the table in case of at least 25% of entries can\n   * be deleted by enforcing a collection.  Ignored for small tables.\n   * In the incremental mode we skip this optimization, as we want to\n   * avoid triggering a full collection whenever possible.\n   */\n  if (log_old_size >= (unsigned)GC_ON_GROW_LOG_SIZE_MIN && !GC_incremental) {\n    IF_CANCEL(int cancel_state;)\n\n    DISABLE_CANCEL(cancel_state);\n    GC_gcollect_inner();\n    RESTORE_CANCEL(cancel_state);\n    /* `GC_finalize` might decrease entries value. */\n    if (*entries_ptr < ((size_t)1 << log_old_size) - (*entries_ptr >> 2))\n      return;\n  }\n\n  new_table = (struct hash_chain_entry **)GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE(\n      new_size * sizeof(struct hash_chain_entry *), NORMAL);\n  if (NULL == new_table) {\n    if (NULL == *table_ptr) {\n      ABORT(\"Insufficient space for initial table allocation\");\n    } else {\n      return;\n    }\n  }\n  for (i = 0; i < old_size; i++) {\n    for (p = (*table_ptr)[i]; p != NULL;) {\n      ptr_t real_key = (ptr_t)GC_REVEAL_POINTER(p->hidden_key);\n      struct hash_chain_entry *next = p->next;\n      size_t new_hash = HASH3(real_key, new_size, log_new_size);\n\n      p->next = new_table[new_hash];\n      GC_dirty(p);\n      new_table[new_hash] = p;\n      p = next;\n    }\n  }\n  *log_size_ptr = log_new_size;\n  *table_ptr = new_table;\n  GC_dirty(new_table); /*< entire object */\n}\n\nGC_API int GC_CALL\nGC_register_disappearing_link(void **link)\n{\n  ptr_t base;\n\n  base = (ptr_t)GC_base(link);\n  if (base == 0)\n    ABORT(\"Bad arg to GC_register_disappearing_link\");\n  return GC_general_register_disappearing_link(link, base);\n}\n\nSTATIC int\nGC_register_disappearing_link_inner(struct dl_hashtbl_s *dl_hashtbl,\n                                    void **link, const void *obj,\n                                    const char *tbl_log_name)\n{\n  struct disappearing_link *curr_dl;\n  size_t index;\n  struct disappearing_link *new_dl;\n\n  GC_ASSERT(GC_is_initialized);\n  if (UNLIKELY(GC_find_leak_inner))\n    return GC_UNIMPLEMENTED;\n#  ifdef GC_ASSERTIONS\n  /* Just check accessibility. */\n  GC_noop1_ptr(*link);\n#  endif\n  LOCK();\n  GC_ASSERT(obj != NULL && GC_base_C(obj) == obj);\n  if (UNLIKELY(NULL == dl_hashtbl->head)\n      || UNLIKELY(dl_hashtbl->entries > ((size_t)1 << dl_hashtbl->log_size))) {\n    GC_grow_table((struct hash_chain_entry ***)&dl_hashtbl->head,\n                  &dl_hashtbl->log_size, &dl_hashtbl->entries);\n    GC_COND_LOG_PRINTF(\"Grew %s table to %u entries\\n\", tbl_log_name,\n                       1U << dl_hashtbl->log_size);\n  }\n  index = HASH2(link, dl_hashtbl->log_size);\n  for (curr_dl = dl_hashtbl->head[index]; curr_dl != 0;\n       curr_dl = dl_next(curr_dl)) {\n    if (curr_dl->dl_hidden_link == GC_HIDE_POINTER(link)) {\n      /* Alternatively, `GC_HIDE_NZ_POINTER()` could be used instead. */\n      curr_dl->dl_hidden_obj = GC_HIDE_POINTER(obj);\n      UNLOCK();\n      return GC_DUPLICATE;\n    }\n  }\n  new_dl = (struct disappearing_link *)GC_INTERNAL_MALLOC(\n      sizeof(struct disappearing_link), NORMAL);\n  if (UNLIKELY(NULL == new_dl)) {\n    GC_oom_func oom_fn = GC_oom_fn;\n    UNLOCK();\n    new_dl = (struct disappearing_link *)(*oom_fn)(\n        sizeof(struct disappearing_link));\n    if (0 == new_dl) {\n      return GC_NO_MEMORY;\n    }\n    /* It is not likely we will make it here, but... */\n    LOCK();\n    /* Recalculate `index` since the table may grow. */\n    index = HASH2(link, dl_hashtbl->log_size);\n    /* Check again that our disappearing link not in the table. */\n    for (curr_dl = dl_hashtbl->head[index]; curr_dl != 0;\n         curr_dl = dl_next(curr_dl)) {\n      if (curr_dl->dl_hidden_link == GC_HIDE_POINTER(link)) {\n        curr_dl->dl_hidden_obj = GC_HIDE_POINTER(obj);\n        UNLOCK();\n#  ifndef DBG_HDRS_ALL\n        /* Free unused `new_dl` returned by `GC_oom_fn()`. */\n        GC_free(new_dl);\n#  endif\n        return GC_DUPLICATE;\n      }\n    }\n  }\n  new_dl->dl_hidden_obj = GC_HIDE_POINTER(obj);\n  new_dl->dl_hidden_link = GC_HIDE_POINTER(link);\n  dl_set_next(new_dl, dl_hashtbl->head[index]);\n  GC_dirty(new_dl);\n  dl_hashtbl->head[index] = new_dl;\n  dl_hashtbl->entries++;\n  GC_dirty(dl_hashtbl->head + index);\n  UNLOCK();\n  return GC_SUCCESS;\n}\n\nGC_API int GC_CALL\nGC_general_register_disappearing_link(void **link, const void *obj)\n{\n  if ((ADDR(link) & (ALIGNMENT - 1)) != 0 || !NONNULL_ARG_NOT_NULL(link))\n    ABORT(\"Bad arg to GC_general_register_disappearing_link\");\n  return GC_register_disappearing_link_inner(&GC_dl_hashtbl, link, obj, \"dl\");\n}\n\n#  ifdef DBG_HDRS_ALL\n#    define FREE_DL_ENTRY(curr_dl) dl_set_next(curr_dl, NULL)\n#  else\n#    define FREE_DL_ENTRY(curr_dl) GC_free(curr_dl)\n#  endif\n\n/* Unregisters given `link` and returns the link entry to free. */\nGC_INLINE struct disappearing_link *\nGC_unregister_disappearing_link_inner(struct dl_hashtbl_s *dl_hashtbl,\n                                      void **link)\n{\n  struct disappearing_link *curr_dl;\n  struct disappearing_link *prev_dl = NULL;\n  size_t index;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (UNLIKELY(NULL == dl_hashtbl->head))\n    return NULL;\n\n  index = HASH2(link, dl_hashtbl->log_size);\n  for (curr_dl = dl_hashtbl->head[index]; curr_dl;\n       curr_dl = dl_next(curr_dl)) {\n    if (curr_dl->dl_hidden_link == GC_HIDE_POINTER(link)) {\n      /* Remove found entry from the table. */\n      if (NULL == prev_dl) {\n        dl_hashtbl->head[index] = dl_next(curr_dl);\n        GC_dirty(dl_hashtbl->head + index);\n      } else {\n        dl_set_next(prev_dl, dl_next(curr_dl));\n        GC_dirty(prev_dl);\n      }\n      dl_hashtbl->entries--;\n      break;\n    }\n    prev_dl = curr_dl;\n  }\n  return curr_dl;\n}\n\nGC_API int GC_CALL\nGC_unregister_disappearing_link(void **link)\n{\n  struct disappearing_link *curr_dl;\n\n  if ((ADDR(link) & (ALIGNMENT - 1)) != 0) {\n    /* Nothing to do. */\n    return 0;\n  }\n\n  LOCK();\n  curr_dl = GC_unregister_disappearing_link_inner(&GC_dl_hashtbl, link);\n  UNLOCK();\n  if (NULL == curr_dl)\n    return 0;\n  FREE_DL_ENTRY(curr_dl);\n  return 1;\n}\n\n/*\n * Mark from one finalizable object using the specified mark procedure.\n * May not mark the object pointed to by `real_ptr` (i.e, it is the job\n * of the caller, if appropriate).  Note that this is called with the\n * mutator running.  This is safe only if the mutator (client) gets\n * the allocator lock to reveal hidden pointers.\n */\nGC_INLINE void\nGC_mark_fo(ptr_t real_ptr, finalization_mark_proc fo_mark_proc)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  fo_mark_proc(real_ptr);\n  /* Process objects pushed by the mark procedure. */\n  while (!GC_mark_stack_empty())\n    MARK_FROM_MARK_STACK();\n}\n\n/* Complete a collection in progress, if any. */\nGC_INLINE void\nGC_complete_ongoing_collection(void)\n{\n  if (UNLIKELY(GC_collection_in_progress())) {\n    while (!GC_mark_some(NULL)) {\n      /* Empty. */\n    }\n  }\n}\n\n/* Toggle-refs support. */\n\n#  ifndef GC_TOGGLE_REFS_NOT_NEEDED\ntypedef union toggle_ref_u GCToggleRef;\n\nSTATIC GC_toggleref_func GC_toggleref_callback = 0;\n\nGC_INNER void\nGC_process_togglerefs(void)\n{\n  size_t i;\n  size_t new_size = 0;\n  GC_bool needs_barrier = FALSE;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  for (i = 0; i < GC_toggleref_array_size; ++i) {\n    GCToggleRef *r = &GC_toggleref_arr[i];\n    void *obj = r->strong_ref;\n\n    if ((ADDR(obj) & 1) != 0) {\n      obj = GC_REVEAL_POINTER(r->weak_ref);\n      GC_ASSERT((ADDR(obj) & 1) == 0);\n    }\n    if (NULL == obj)\n      continue;\n\n    switch (GC_toggleref_callback(obj)) {\n    case GC_TOGGLE_REF_DROP:\n      break;\n    case GC_TOGGLE_REF_STRONG:\n      GC_toggleref_arr[new_size++].strong_ref = obj;\n      needs_barrier = TRUE;\n      break;\n    case GC_TOGGLE_REF_WEAK:\n      GC_toggleref_arr[new_size++].weak_ref = GC_HIDE_POINTER(obj);\n      break;\n    default:\n      ABORT(\"Bad toggle-ref status returned by callback\");\n    }\n  }\n\n  if (new_size < GC_toggleref_array_size) {\n    BZERO(&GC_toggleref_arr[new_size],\n          (GC_toggleref_array_size - new_size) * sizeof(GCToggleRef));\n    GC_toggleref_array_size = new_size;\n  }\n  if (needs_barrier)\n    GC_dirty(GC_toggleref_arr); /*< entire object */\n}\n\nSTATIC void GC_normal_finalize_mark_proc(ptr_t);\n\nSTATIC void\nGC_mark_togglerefs(void)\n{\n  size_t i;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (NULL == GC_toggleref_arr)\n    return;\n\n  GC_set_mark_bit(GC_toggleref_arr);\n  for (i = 0; i < GC_toggleref_array_size; ++i) {\n    void *obj = GC_toggleref_arr[i].strong_ref;\n    if (obj != NULL && (ADDR(obj) & 1) == 0) {\n      /* Push and mark the object. */\n      GC_mark_fo((ptr_t)obj, GC_normal_finalize_mark_proc);\n      GC_set_mark_bit(obj);\n      GC_complete_ongoing_collection();\n    }\n  }\n}\n\nSTATIC void\nGC_clear_togglerefs(void)\n{\n  size_t i;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  for (i = 0; i < GC_toggleref_array_size; ++i) {\n    GCToggleRef *r = &GC_toggleref_arr[i];\n\n    if ((ADDR(r->strong_ref) & 1) != 0) {\n      if (!GC_is_marked(GC_REVEAL_POINTER(r->weak_ref))) {\n        r->weak_ref = 0;\n      } else {\n        /* No need to copy, this garbage collector is a non-moving one. */\n      }\n    }\n  }\n}\n\nGC_API void GC_CALL\nGC_set_toggleref_func(GC_toggleref_func fn)\n{\n  LOCK();\n  GC_toggleref_callback = fn;\n  UNLOCK();\n}\n\nGC_API GC_toggleref_func GC_CALL\nGC_get_toggleref_func(void)\n{\n  GC_toggleref_func fn;\n\n  READER_LOCK();\n  fn = GC_toggleref_callback;\n  READER_UNLOCK();\n  return fn;\n}\n\nstatic GC_bool\nensure_toggleref_capacity(size_t capacity_inc)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  if (NULL == GC_toggleref_arr) {\n    /* Set the initial capacity. */\n    GC_toggleref_array_capacity = 32;\n\n    GC_toggleref_arr = (GCToggleRef *)GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE(\n        GC_toggleref_array_capacity * sizeof(GCToggleRef), NORMAL);\n    if (NULL == GC_toggleref_arr)\n      return FALSE;\n  }\n  if (GC_toggleref_array_size + capacity_inc >= GC_toggleref_array_capacity) {\n    GCToggleRef *new_array;\n    while (GC_toggleref_array_capacity\n           < GC_toggleref_array_size + capacity_inc) {\n      GC_toggleref_array_capacity *= 2;\n      if ((GC_toggleref_array_capacity\n           & ((size_t)1 << (sizeof(size_t) * 8 - 1)))\n          != 0) {\n        /* An overflow. */\n        return FALSE;\n      }\n    }\n\n    new_array = (GCToggleRef *)GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE(\n        GC_toggleref_array_capacity * sizeof(GCToggleRef), NORMAL);\n    if (UNLIKELY(NULL == new_array))\n      return FALSE;\n    if (LIKELY(GC_toggleref_array_size > 0))\n      BCOPY(GC_toggleref_arr, new_array,\n            GC_toggleref_array_size * sizeof(GCToggleRef));\n    GC_INTERNAL_FREE(GC_toggleref_arr);\n    GC_toggleref_arr = new_array;\n  }\n  return TRUE;\n}\n\nGC_API int GC_CALL\nGC_toggleref_add(void *obj, int is_strong_ref)\n{\n  int res = GC_SUCCESS;\n\n  GC_ASSERT(NONNULL_ARG_NOT_NULL(obj));\n  LOCK();\n  GC_ASSERT((ADDR(obj) & 1) == 0 && obj == GC_base(obj));\n  if (GC_toggleref_callback != 0) {\n    if (!ensure_toggleref_capacity(1)) {\n      res = GC_NO_MEMORY;\n    } else {\n      GCToggleRef *r = &GC_toggleref_arr[GC_toggleref_array_size];\n\n      if (is_strong_ref) {\n        r->strong_ref = obj;\n        GC_dirty(GC_toggleref_arr + GC_toggleref_array_size);\n      } else {\n        r->weak_ref = GC_HIDE_POINTER(obj);\n        GC_ASSERT((r->weak_ref & 1) != 0);\n      }\n      GC_toggleref_array_size++;\n    }\n  }\n  UNLOCK();\n  return res;\n}\n#  endif /* !GC_TOGGLE_REFS_NOT_NEEDED */\n\n/* Finalizer callback support. */\n\nSTATIC GC_await_finalize_proc GC_object_finalized_proc = 0;\n\nGC_API void GC_CALL\nGC_set_await_finalize_proc(GC_await_finalize_proc fn)\n{\n  LOCK();\n  GC_object_finalized_proc = fn;\n  UNLOCK();\n}\n\nGC_API GC_await_finalize_proc GC_CALL\nGC_get_await_finalize_proc(void)\n{\n  GC_await_finalize_proc fn;\n\n  READER_LOCK();\n  fn = GC_object_finalized_proc;\n  READER_UNLOCK();\n  return fn;\n}\n\n#  ifndef GC_LONG_REFS_NOT_NEEDED\nGC_API int GC_CALL\nGC_register_long_link(void **link, const void *obj)\n{\n  if ((ADDR(link) & (ALIGNMENT - 1)) != 0 || !NONNULL_ARG_NOT_NULL(link))\n    ABORT(\"Bad arg to GC_register_long_link\");\n  return GC_register_disappearing_link_inner(&GC_ll_hashtbl, link, obj,\n                                             \"long dl\");\n}\n\nGC_API int GC_CALL\nGC_unregister_long_link(void **link)\n{\n  struct disappearing_link *curr_dl;\n\n  if ((ADDR(link) & (ALIGNMENT - 1)) != 0) {\n    /* Nothing to do. */\n    return 0;\n  }\n  LOCK();\n  curr_dl = GC_unregister_disappearing_link_inner(&GC_ll_hashtbl, link);\n  UNLOCK();\n  if (NULL == curr_dl)\n    return 0;\n  FREE_DL_ENTRY(curr_dl);\n  return 1;\n}\n#  endif /* !GC_LONG_REFS_NOT_NEEDED */\n\n#  ifndef GC_MOVE_DISAPPEARING_LINK_NOT_NEEDED\nSTATIC int\nGC_move_disappearing_link_inner(struct dl_hashtbl_s *dl_hashtbl, void **link,\n                                void **new_link)\n{\n  struct disappearing_link *curr_dl, *new_dl;\n  struct disappearing_link *prev_dl = NULL;\n  size_t curr_index, new_index;\n  GC_hidden_pointer curr_hidden_link, new_hidden_link;\n\n#    ifdef GC_ASSERTIONS\n  GC_noop1_ptr(*new_link);\n#    endif\n  GC_ASSERT(I_HOLD_LOCK());\n  if (UNLIKELY(NULL == dl_hashtbl->head))\n    return GC_NOT_FOUND;\n\n  /* Find current link. */\n  curr_index = HASH2(link, dl_hashtbl->log_size);\n  curr_hidden_link = GC_HIDE_POINTER(link);\n  for (curr_dl = dl_hashtbl->head[curr_index]; curr_dl;\n       curr_dl = dl_next(curr_dl)) {\n    if (curr_dl->dl_hidden_link == curr_hidden_link)\n      break;\n    prev_dl = curr_dl;\n  }\n  if (UNLIKELY(NULL == curr_dl)) {\n    return GC_NOT_FOUND;\n  } else if (link == new_link) {\n    /* Nothing to do. */\n    return GC_SUCCESS;\n  }\n\n  /* `link` is found; now check `new_link` is not present. */\n  new_index = HASH2(new_link, dl_hashtbl->log_size);\n  new_hidden_link = GC_HIDE_POINTER(new_link);\n  for (new_dl = dl_hashtbl->head[new_index]; new_dl;\n       new_dl = dl_next(new_dl)) {\n    if (new_dl->dl_hidden_link == new_hidden_link) {\n      /* Target already registered; bail out. */\n      return GC_DUPLICATE;\n    }\n  }\n\n  /* Remove from old, add to new, update `link`. */\n  if (NULL == prev_dl) {\n    dl_hashtbl->head[curr_index] = dl_next(curr_dl);\n  } else {\n    dl_set_next(prev_dl, dl_next(curr_dl));\n    GC_dirty(prev_dl);\n  }\n  curr_dl->dl_hidden_link = new_hidden_link;\n  dl_set_next(curr_dl, dl_hashtbl->head[new_index]);\n  dl_hashtbl->head[new_index] = curr_dl;\n  GC_dirty(curr_dl);\n  GC_dirty(dl_hashtbl->head); /*< entire object */\n  return GC_SUCCESS;\n}\n\nGC_API int GC_CALL\nGC_move_disappearing_link(void **link, void **new_link)\n{\n  int result;\n\n  if ((ADDR(new_link) & (ALIGNMENT - 1)) != 0\n      || !NONNULL_ARG_NOT_NULL(new_link))\n    ABORT(\"Bad new_link arg to GC_move_disappearing_link\");\n  if ((ADDR(link) & (ALIGNMENT - 1)) != 0) {\n    /* Nothing to do. */\n    return GC_NOT_FOUND;\n  }\n  LOCK();\n  result = GC_move_disappearing_link_inner(&GC_dl_hashtbl, link, new_link);\n  UNLOCK();\n  return result;\n}\n\n#    ifndef GC_LONG_REFS_NOT_NEEDED\nGC_API int GC_CALL\nGC_move_long_link(void **link, void **new_link)\n{\n  int result;\n\n  if ((ADDR(new_link) & (ALIGNMENT - 1)) != 0\n      || !NONNULL_ARG_NOT_NULL(new_link))\n    ABORT(\"Bad new_link arg to GC_move_long_link\");\n  if ((ADDR(link) & (ALIGNMENT - 1)) != 0) {\n    /* Nothing to do. */\n    return GC_NOT_FOUND;\n  }\n  LOCK();\n  result = GC_move_disappearing_link_inner(&GC_ll_hashtbl, link, new_link);\n  UNLOCK();\n  return result;\n}\n#    endif\n#  endif /* !GC_MOVE_DISAPPEARING_LINK_NOT_NEEDED */\n\n/*\n * Various finalization marker procedures.  Note that mark stack overflow\n * is handled by the caller, and is not a disaster.\n */\n\n#  if defined(_MSC_VER) && defined(I386)\nGC_ATTR_NOINLINE\n/* Otherwise some optimizer bug is tickled in VC for x86 (v19, at least). */\n#  endif\nSTATIC void\nGC_normal_finalize_mark_proc(ptr_t p)\n{\n  GC_mark_stack_top = GC_push_obj(p, HDR(p), GC_mark_stack_top,\n                                  GC_mark_stack + GC_mark_stack_size);\n}\n\n/*\n * This only pays very partial attention to the mark descriptor.\n * It does the right thing for normal and atomic objects, and treats\n * most others as normal.\n */\nSTATIC void\nGC_ignore_self_finalize_mark_proc(ptr_t p)\n{\n  const hdr *hhdr = HDR(p);\n  word descr = hhdr->hb_descr;\n  ptr_t current_p;\n  ptr_t scan_limit;\n  ptr_t target_limit = p + hhdr->hb_sz - 1;\n\n  if ((descr & GC_DS_TAGS) == GC_DS_LENGTH) {\n    scan_limit = p + descr - sizeof(ptr_t);\n  } else {\n    scan_limit = target_limit + 1 - sizeof(ptr_t);\n  }\n  for (current_p = p; ADDR_GE(scan_limit, current_p); current_p += ALIGNMENT) {\n    ptr_t q;\n\n    LOAD_PTR_OR_CONTINUE(q, current_p);\n    if (ADDR_LT(q, p) || ADDR_LT(target_limit, q)) {\n      GC_PUSH_ONE_HEAP(q, current_p, GC_mark_stack_top);\n    }\n  }\n}\n\nSTATIC void\nGC_null_finalize_mark_proc(ptr_t p)\n{\n  UNUSED_ARG(p);\n}\n\n/*\n * `GC_unreachable_finalize_mark_proc` is an alias for normal marking,\n * but it is explicitly tested for, and triggers different behavior.\n * Objects registered in this way are not finalized if they are reachable\n * by other finalizable objects, even if those other objects specify\n * no ordering.\n */\nSTATIC void\nGC_unreachable_finalize_mark_proc(ptr_t p)\n{\n  /*\n   * A dummy comparison to ensure the compiler not to optimize two\n   * identical functions into a single one (thus, to ensure a unique\n   * address of each).  Alternatively, `GC_noop1_ptr(p)` could be used.\n   */\n  if (UNLIKELY(NULL == p))\n    return;\n\n  GC_normal_finalize_mark_proc(p);\n}\n\n/*\n * Register a finalization function.  See `gc.h` file for details.\n * The last parameter is a procedure that determines marking for\n * finalization ordering.  Any objects marked by that procedure will be\n * guaranteed to not have been finalized when this finalizer is invoked.\n */\nSTATIC void\nGC_register_finalizer_inner(void *obj, GC_finalization_proc fn, void *cd,\n                            GC_finalization_proc *ofn, void **ocd,\n                            finalization_mark_proc mp)\n{\n  struct finalizable_object *curr_fo;\n  size_t index;\n  struct finalizable_object *new_fo = 0;\n  const hdr *hhdr = NULL; /*< initialized to prevent warning */\n\n  GC_ASSERT(GC_is_initialized);\n  if (UNLIKELY(GC_find_leak_inner)) {\n    /* No-op.  `*ocd` and `*ofn` remain unchanged. */\n    return;\n  }\n  LOCK();\n  GC_ASSERT(obj != NULL && GC_base_C(obj) == obj);\n  if (mp == GC_unreachable_finalize_mark_proc)\n    GC_need_unreachable_finalization = TRUE;\n  if (UNLIKELY(NULL == GC_fnlz_roots.fo_head)\n      || UNLIKELY(GC_fo_entries > ((size_t)1 << GC_log_fo_table_size))) {\n    GC_grow_table((struct hash_chain_entry ***)&GC_fnlz_roots.fo_head,\n                  &GC_log_fo_table_size, &GC_fo_entries);\n    GC_COND_LOG_PRINTF(\"Grew fo table to %u entries\\n\",\n                       1U << GC_log_fo_table_size);\n  }\n  for (;;) {\n    struct finalizable_object *prev_fo = NULL;\n    GC_oom_func oom_fn;\n\n    index = HASH2(obj, GC_log_fo_table_size);\n    curr_fo = GC_fnlz_roots.fo_head[index];\n    while (curr_fo != NULL) {\n      GC_ASSERT(GC_size(curr_fo) >= sizeof(struct finalizable_object));\n      if (curr_fo->fo_hidden_base == GC_HIDE_POINTER(obj)) {\n        /*\n         * Interruption by a signal in the middle of this should be safe.\n         * The client may see only `*ocd` updated, but we will declare that\n         * to be his problem.\n         */\n        if (ocd)\n          *ocd = curr_fo->fo_client_data;\n        if (ofn)\n          *ofn = curr_fo->fo_fn;\n        /* Delete the structure for `obj`. */\n        if (prev_fo == 0) {\n          GC_fnlz_roots.fo_head[index] = fo_next(curr_fo);\n        } else {\n          fo_set_next(prev_fo, fo_next(curr_fo));\n          GC_dirty(prev_fo);\n        }\n        if (fn == 0) {\n          GC_fo_entries--;\n          /*\n           * May not happen if we get a signal.  But a high estimate will\n           * only make the table larger than necessary.\n           */\n#  if !defined(THREADS) && !defined(DBG_HDRS_ALL)\n          GC_free(curr_fo);\n#  endif\n        } else {\n          curr_fo->fo_fn = fn;\n          curr_fo->fo_client_data = (ptr_t)cd;\n          curr_fo->fo_mark_proc = mp;\n          GC_dirty(curr_fo);\n          /*\n           * Reinsert it.  We deleted it first to maintain consistency in\n           * the event of a signal.\n           */\n          if (prev_fo == 0) {\n            GC_fnlz_roots.fo_head[index] = curr_fo;\n          } else {\n            fo_set_next(prev_fo, curr_fo);\n            GC_dirty(prev_fo);\n          }\n        }\n        if (NULL == prev_fo)\n          GC_dirty(GC_fnlz_roots.fo_head + index);\n        UNLOCK();\n#  ifndef DBG_HDRS_ALL\n        /* Free unused `new_fo` returned by `GC_oom_fn()`. */\n        GC_free(new_fo);\n#  endif\n        return;\n      }\n      prev_fo = curr_fo;\n      curr_fo = fo_next(curr_fo);\n    }\n    if (UNLIKELY(new_fo != 0)) {\n      /* `new_fo` is returned by `GC_oom_fn()`. */\n      GC_ASSERT(fn != 0);\n#  ifdef LINT2\n      if (NULL == hhdr)\n        ABORT(\"Bad hhdr in GC_register_finalizer_inner\");\n#  endif\n      break;\n    }\n    if (fn == 0) {\n      if (ocd)\n        *ocd = 0;\n      if (ofn)\n        *ofn = 0;\n      UNLOCK();\n      return;\n    }\n    GET_HDR(obj, hhdr);\n    if (UNLIKELY(NULL == hhdr)) {\n      /* We will not collect it, hence finalizer would not be run. */\n      if (ocd)\n        *ocd = 0;\n      if (ofn)\n        *ofn = 0;\n      UNLOCK();\n      return;\n    }\n    new_fo = (struct finalizable_object *)GC_INTERNAL_MALLOC(\n        sizeof(struct finalizable_object), NORMAL);\n    if (LIKELY(new_fo != 0))\n      break;\n    oom_fn = GC_oom_fn;\n    UNLOCK();\n    new_fo = (struct finalizable_object *)(*oom_fn)(\n        sizeof(struct finalizable_object));\n    if (0 == new_fo) {\n      /* No enough memory.  `*ocd` and `*ofn` remain unchanged. */\n      return;\n    }\n    /* It is not likely we will make it here, but... */\n    LOCK();\n    /*\n     * Recalculate index since the table may grow and check again that\n     * our finalizer is not in the table.\n     */\n  }\n  GC_ASSERT(GC_size(new_fo) >= sizeof(struct finalizable_object));\n  if (ocd)\n    *ocd = 0;\n  if (ofn)\n    *ofn = 0;\n  new_fo->fo_hidden_base = GC_HIDE_POINTER(obj);\n  new_fo->fo_fn = fn;\n  new_fo->fo_client_data = (ptr_t)cd;\n  new_fo->fo_object_sz = hhdr->hb_sz;\n  new_fo->fo_mark_proc = mp;\n  fo_set_next(new_fo, GC_fnlz_roots.fo_head[index]);\n  GC_dirty(new_fo);\n  GC_fo_entries++;\n  GC_fnlz_roots.fo_head[index] = new_fo;\n  GC_dirty(GC_fnlz_roots.fo_head + index);\n  UNLOCK();\n}\n\nGC_API void GC_CALL\nGC_register_finalizer(void *obj, GC_finalization_proc fn, void *cd,\n                      GC_finalization_proc *ofn, void **ocd)\n{\n  GC_register_finalizer_inner(obj, fn, cd, ofn, ocd,\n                              GC_normal_finalize_mark_proc);\n}\n\nGC_API void GC_CALL\nGC_register_finalizer_ignore_self(void *obj, GC_finalization_proc fn, void *cd,\n                                  GC_finalization_proc *ofn, void **ocd)\n{\n  GC_register_finalizer_inner(obj, fn, cd, ofn, ocd,\n                              GC_ignore_self_finalize_mark_proc);\n}\n\nGC_API void GC_CALL\nGC_register_finalizer_no_order(void *obj, GC_finalization_proc fn, void *cd,\n                               GC_finalization_proc *ofn, void **ocd)\n{\n  GC_register_finalizer_inner(obj, fn, cd, ofn, ocd,\n                              GC_null_finalize_mark_proc);\n}\n\nGC_API void GC_CALL\nGC_register_finalizer_unreachable(void *obj, GC_finalization_proc fn, void *cd,\n                                  GC_finalization_proc *ofn, void **ocd)\n{\n  GC_ASSERT(GC_java_finalization);\n  GC_register_finalizer_inner(obj, fn, cd, ofn, ocd,\n                              GC_unreachable_finalize_mark_proc);\n}\n\n#  ifndef NO_DEBUGGING\nSTATIC void\nGC_dump_finalization_links(const struct dl_hashtbl_s *dl_hashtbl)\n{\n  size_t dl_size = (size_t)1 << dl_hashtbl->log_size;\n  size_t i;\n\n  if (NULL == dl_hashtbl->head) {\n    /* The table is empty. */\n    return;\n  }\n\n  for (i = 0; i < dl_size; i++) {\n    struct disappearing_link *curr_dl;\n\n    for (curr_dl = dl_hashtbl->head[i]; curr_dl != 0;\n         curr_dl = dl_next(curr_dl)) {\n      ptr_t real_ptr = (ptr_t)GC_REVEAL_POINTER(curr_dl->dl_hidden_obj);\n      ptr_t real_link = (ptr_t)GC_REVEAL_POINTER(curr_dl->dl_hidden_link);\n\n      GC_printf(\"Object: %p, link value: %p, link addr: %p\\n\",\n                (void *)real_ptr, *(void **)real_link, (void *)real_link);\n    }\n  }\n}\n\nGC_API void GC_CALL\nGC_dump_finalization(void)\n{\n  struct finalizable_object *curr_fo;\n  size_t i;\n  size_t fo_size\n      = GC_fnlz_roots.fo_head == NULL ? 0 : (size_t)1 << GC_log_fo_table_size;\n\n  GC_printf(\"\\n***Disappearing (short) links:\\n\");\n  GC_dump_finalization_links(&GC_dl_hashtbl);\n#    ifndef GC_LONG_REFS_NOT_NEEDED\n  GC_printf(\"\\n***Disappearing long links:\\n\");\n  GC_dump_finalization_links(&GC_ll_hashtbl);\n#    endif\n  GC_printf(\"\\n***Finalizers:\\n\");\n  for (i = 0; i < fo_size; i++) {\n    for (curr_fo = GC_fnlz_roots.fo_head[i]; curr_fo != NULL;\n         curr_fo = fo_next(curr_fo)) {\n      ptr_t real_ptr = (ptr_t)GC_REVEAL_POINTER(curr_fo->fo_hidden_base);\n\n      GC_printf(\"Finalizable object: %p\\n\", (void *)real_ptr);\n    }\n  }\n}\n#  endif /* !NO_DEBUGGING */\n\n#  ifndef THREADS\n/*\n * Checks and updates the level of finalizers recursion.\n * Returns `NULL` if `GC_invoke_finalizers()` should not be called by\n * the collector (to minimize the risk of a deep finalizers recursion),\n * otherwise returns a pointer to `GC_finalizer_nested`.\n */\nSTATIC unsigned char *\nGC_check_finalizer_nested(void)\n{\n  unsigned nesting_level = GC_finalizer_nested;\n  if (nesting_level) {\n    /*\n     * We are inside another `GC_invoke_finalizers()`.  Skip some\n     * implicitly-called `GC_invoke_finalizers()` depending on the\n     * nesting (recursion) level.\n     */\n    if ((unsigned)(++GC_finalizer_skipped) < (1U << nesting_level))\n      return NULL;\n    GC_finalizer_skipped = 0;\n  }\n  GC_finalizer_nested = (unsigned char)(nesting_level + 1);\n  return &GC_finalizer_nested;\n}\n#  endif /* !THREADS */\n\nGC_INLINE void\nGC_make_disappearing_links_disappear(struct dl_hashtbl_s *dl_hashtbl,\n                                     GC_bool is_remove_dangling)\n{\n  size_t i;\n  size_t dl_size = (size_t)1 << dl_hashtbl->log_size;\n  GC_bool needs_barrier = FALSE;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (NULL == dl_hashtbl->head) {\n    /* The table is empty. */\n    return;\n  }\n\n  for (i = 0; i < dl_size; i++) {\n    struct disappearing_link *curr_dl, *next_dl;\n    struct disappearing_link *prev_dl = NULL;\n\n    for (curr_dl = dl_hashtbl->head[i]; curr_dl != NULL; curr_dl = next_dl) {\n      next_dl = dl_next(curr_dl);\n#  if defined(GC_ASSERTIONS) && !defined(THREAD_SANITIZER)\n      /* Check accessibility of the location pointed by the link. */\n      GC_noop1_ptr(*(ptr_t *)GC_REVEAL_POINTER(curr_dl->dl_hidden_link));\n#  endif\n      if (is_remove_dangling) {\n        ptr_t real_link\n            = (ptr_t)GC_base(GC_REVEAL_POINTER(curr_dl->dl_hidden_link));\n\n        if (NULL == real_link || LIKELY(GC_is_marked(real_link))) {\n          prev_dl = curr_dl;\n          continue;\n        }\n      } else {\n        if (LIKELY(GC_is_marked(\n                (ptr_t)GC_REVEAL_POINTER(curr_dl->dl_hidden_obj)))) {\n          prev_dl = curr_dl;\n          continue;\n        }\n        *(ptr_t *)GC_REVEAL_POINTER(curr_dl->dl_hidden_link) = NULL;\n      }\n\n      /* Delete `curr_dl` entry from `dl_hashtbl`. */\n      if (NULL == prev_dl) {\n        dl_hashtbl->head[i] = next_dl;\n        needs_barrier = TRUE;\n      } else {\n        dl_set_next(prev_dl, next_dl);\n        GC_dirty(prev_dl);\n      }\n      GC_clear_mark_bit(curr_dl);\n      dl_hashtbl->entries--;\n    }\n  }\n  if (needs_barrier)\n    GC_dirty(dl_hashtbl->head); /*< entire object */\n}\n\nGC_INNER void\nGC_finalize(void)\n{\n  struct finalizable_object *curr_fo, *prev_fo, *next_fo;\n  ptr_t real_ptr;\n  size_t i;\n  size_t fo_size\n      = GC_fnlz_roots.fo_head == NULL ? 0 : (size_t)1 << GC_log_fo_table_size;\n  GC_bool needs_barrier = FALSE;\n\n  GC_ASSERT(I_HOLD_LOCK());\n#  ifndef SMALL_CONFIG\n  /* Save current `GC_dl_entries` value for stats printing. */\n  GC_old_dl_entries = GC_dl_hashtbl.entries;\n#    ifndef GC_LONG_REFS_NOT_NEEDED\n  /* Save current `GC_ll_entries` value for stats printing. */\n  GC_old_ll_entries = GC_ll_hashtbl.entries;\n#    endif\n#  endif\n\n#  ifndef GC_TOGGLE_REFS_NOT_NEEDED\n  GC_mark_togglerefs();\n#  endif\n  GC_make_disappearing_links_disappear(&GC_dl_hashtbl, FALSE);\n\n  /*\n   * Mark all objects reachable via chains of 1 or more pointers from\n   * finalizable objects.\n   */\n  GC_ASSERT(!GC_collection_in_progress());\n  for (i = 0; i < fo_size; i++) {\n    for (curr_fo = GC_fnlz_roots.fo_head[i]; curr_fo != NULL;\n         curr_fo = fo_next(curr_fo)) {\n      GC_ASSERT(GC_size(curr_fo) >= sizeof(struct finalizable_object));\n      real_ptr = (ptr_t)GC_REVEAL_POINTER(curr_fo->fo_hidden_base);\n      if (!GC_is_marked(real_ptr)) {\n        GC_MARKED_FOR_FINALIZATION(real_ptr);\n        GC_mark_fo(real_ptr, curr_fo->fo_mark_proc);\n        if (GC_is_marked(real_ptr)) {\n          WARN(\"Finalization cycle involving %p\\n\", real_ptr);\n        }\n      }\n    }\n  }\n  /* Enqueue for finalization all objects that are still unreachable. */\n  GC_bytes_finalized = 0;\n  for (i = 0; i < fo_size; i++) {\n    curr_fo = GC_fnlz_roots.fo_head[i];\n    prev_fo = NULL;\n    while (curr_fo != NULL) {\n      real_ptr = (ptr_t)GC_REVEAL_POINTER(curr_fo->fo_hidden_base);\n      if (!GC_is_marked(real_ptr)) {\n        if (!GC_java_finalization) {\n          GC_set_mark_bit(real_ptr);\n        }\n        /* Delete from hash table. */\n        next_fo = fo_next(curr_fo);\n        if (NULL == prev_fo) {\n          GC_fnlz_roots.fo_head[i] = next_fo;\n          if (GC_object_finalized_proc) {\n            GC_dirty(GC_fnlz_roots.fo_head + i);\n          } else {\n            needs_barrier = TRUE;\n          }\n        } else {\n          fo_set_next(prev_fo, next_fo);\n          GC_dirty(prev_fo);\n        }\n        GC_fo_entries--;\n        if (GC_object_finalized_proc)\n          GC_object_finalized_proc(real_ptr);\n\n        /* Add to list of objects awaiting finalization. */\n        fo_set_next(curr_fo, GC_fnlz_roots.finalize_now);\n        GC_dirty(curr_fo);\n        SET_FINALIZE_NOW(curr_fo);\n        /* Unhide object pointer so any future collections will see it. */\n        curr_fo->fo_hidden_base\n            = (GC_hidden_pointer)GC_REVEAL_POINTER(curr_fo->fo_hidden_base);\n\n        GC_bytes_finalized\n            += (word)curr_fo->fo_object_sz + sizeof(struct finalizable_object);\n        GC_ASSERT(GC_is_marked(GC_base(curr_fo)));\n        curr_fo = next_fo;\n      } else {\n        prev_fo = curr_fo;\n        curr_fo = fo_next(curr_fo);\n      }\n    }\n  }\n\n  if (GC_java_finalization) {\n    /*\n     * Make sure we mark everything reachable from objects finalized\n     * using the no-order `fo_mark_proc`.\n     */\n    for (curr_fo = GC_fnlz_roots.finalize_now; curr_fo != NULL;\n         curr_fo = fo_next(curr_fo)) {\n      real_ptr = (ptr_t)curr_fo->fo_hidden_base; /*< revealed */\n      if (!GC_is_marked(real_ptr)) {\n        if (curr_fo->fo_mark_proc == GC_null_finalize_mark_proc) {\n          GC_mark_fo(real_ptr, GC_normal_finalize_mark_proc);\n        }\n        if (curr_fo->fo_mark_proc != GC_unreachable_finalize_mark_proc) {\n          GC_set_mark_bit(real_ptr);\n        }\n      }\n    }\n\n    /*\n     * Now revive finalize-when-unreachable objects reachable from other\n     * finalizable objects.\n     */\n    if (GC_need_unreachable_finalization) {\n      curr_fo = GC_fnlz_roots.finalize_now;\n#  if defined(GC_ASSERTIONS) || defined(LINT2)\n      if (curr_fo != NULL && NULL == GC_fnlz_roots.fo_head)\n        ABORT(\"GC_fnlz_roots.fo_head is null\");\n#  endif\n      for (prev_fo = NULL; curr_fo != NULL;\n           prev_fo = curr_fo, curr_fo = next_fo) {\n        next_fo = fo_next(curr_fo);\n        if (curr_fo->fo_mark_proc != GC_unreachable_finalize_mark_proc)\n          continue;\n\n        real_ptr = (ptr_t)curr_fo->fo_hidden_base; /*< revealed */\n        if (!GC_is_marked(real_ptr)) {\n          GC_set_mark_bit(real_ptr);\n          continue;\n        }\n        if (NULL == prev_fo) {\n          SET_FINALIZE_NOW(next_fo);\n        } else {\n          fo_set_next(prev_fo, next_fo);\n          GC_dirty(prev_fo);\n        }\n        curr_fo->fo_hidden_base = GC_HIDE_POINTER(real_ptr);\n        GC_bytes_finalized\n            -= (word)curr_fo->fo_object_sz + sizeof(struct finalizable_object);\n\n        i = HASH2(real_ptr, GC_log_fo_table_size);\n        fo_set_next(curr_fo, GC_fnlz_roots.fo_head[i]);\n        GC_dirty(curr_fo);\n        GC_fo_entries++;\n        GC_fnlz_roots.fo_head[i] = curr_fo;\n        curr_fo = prev_fo;\n        needs_barrier = TRUE;\n      }\n    }\n  }\n  if (needs_barrier)\n    GC_dirty(GC_fnlz_roots.fo_head); /*< entire object */\n\n  /* Remove dangling disappearing links. */\n  GC_make_disappearing_links_disappear(&GC_dl_hashtbl, TRUE);\n\n#  ifndef GC_TOGGLE_REFS_NOT_NEEDED\n  GC_clear_togglerefs();\n#  endif\n#  ifndef GC_LONG_REFS_NOT_NEEDED\n  GC_make_disappearing_links_disappear(&GC_ll_hashtbl, FALSE);\n  GC_make_disappearing_links_disappear(&GC_ll_hashtbl, TRUE);\n#  endif\n\n  if (GC_alloc_fail_count > 0) {\n    /*\n     * Do not prevent running finalizers if there has been an allocation\n     * failure recently.\n     */\n#  ifdef THREADS\n    GC_reset_finalizer_nested();\n#  else\n    GC_finalizer_nested = 0;\n#  endif\n  }\n}\n\n/*\n * Count of finalizers to run, at most, during a single invocation\n * of `GC_invoke_finalizers()`; zero means no limit.  Accessed with the\n * allocator lock held.\n */\nSTATIC unsigned GC_interrupt_finalizers = 0;\n\n#  ifndef JAVA_FINALIZATION_NOT_NEEDED\n\n/*\n * Enqueue all remaining finalizers to be run.  A collection in progress,\n * if any, is completed when the first finalizer is enqueued.\n */\nSTATIC void\nGC_enqueue_all_finalizers(void)\n{\n  size_t i;\n  size_t fo_size\n      = GC_fnlz_roots.fo_head == NULL ? 0 : (size_t)1 << GC_log_fo_table_size;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_bytes_finalized = 0;\n  for (i = 0; i < fo_size; i++) {\n    struct finalizable_object *curr_fo = GC_fnlz_roots.fo_head[i];\n\n    GC_fnlz_roots.fo_head[i] = NULL;\n    while (curr_fo != NULL) {\n      struct finalizable_object *next_fo;\n      ptr_t real_ptr = (ptr_t)GC_REVEAL_POINTER(curr_fo->fo_hidden_base);\n\n      GC_mark_fo(real_ptr, GC_normal_finalize_mark_proc);\n      GC_set_mark_bit(real_ptr);\n      GC_complete_ongoing_collection();\n      next_fo = fo_next(curr_fo);\n\n      /* Add to list of objects awaiting finalization. */\n      fo_set_next(curr_fo, GC_fnlz_roots.finalize_now);\n      GC_dirty(curr_fo);\n      SET_FINALIZE_NOW(curr_fo);\n\n      /* Unhide object pointer so any future collections will see it. */\n      curr_fo->fo_hidden_base\n          = (GC_hidden_pointer)GC_REVEAL_POINTER(curr_fo->fo_hidden_base);\n      GC_bytes_finalized\n          += curr_fo->fo_object_sz + sizeof(struct finalizable_object);\n      curr_fo = next_fo;\n    }\n  }\n  /* All entries are deleted from the hash table. */\n  GC_fo_entries = 0;\n}\n\nGC_API void GC_CALL\nGC_finalize_all(void)\n{\n  LOCK();\n  while (GC_fo_entries > 0) {\n    unsigned saved_interrupt_finalizers;\n\n    GC_enqueue_all_finalizers();\n    /* Reset temporarily. */\n    saved_interrupt_finalizers = GC_interrupt_finalizers;\n    GC_interrupt_finalizers = 0;\n    UNLOCK();\n    GC_invoke_finalizers();\n    /*\n     * Running the finalizers in this thread is arguably not a good idea\n     * when we should be notifying another thread to run them.\n     * But otherwise we do not have a great way to wait for them to run.\n     */\n    LOCK();\n    GC_interrupt_finalizers = saved_interrupt_finalizers;\n  }\n  UNLOCK();\n}\n\n#  endif /* !JAVA_FINALIZATION_NOT_NEEDED */\n\nGC_API void GC_CALL\nGC_set_interrupt_finalizers(unsigned value)\n{\n  LOCK();\n  GC_interrupt_finalizers = value;\n  UNLOCK();\n}\n\nGC_API unsigned GC_CALL\nGC_get_interrupt_finalizers(void)\n{\n  unsigned value;\n\n  READER_LOCK();\n  value = GC_interrupt_finalizers;\n  READER_UNLOCK();\n  return value;\n}\n\nGC_API int GC_CALL\nGC_should_invoke_finalizers(void)\n{\n#  ifdef AO_HAVE_load\n  return GC_cptr_load((volatile ptr_t *)&GC_fnlz_roots.finalize_now) != NULL;\n#  else\n  return GC_fnlz_roots.finalize_now != NULL;\n#  endif /* !THREADS */\n}\n\nGC_API int GC_CALL\nGC_invoke_finalizers(void)\n{\n  int count = 0;\n  word bytes_freed_before = 0; /*< initialized to prevent warning */\n\n  GC_ASSERT(I_DONT_HOLD_LOCK());\n  while (GC_should_invoke_finalizers()) {\n    struct finalizable_object *curr_fo;\n    ptr_t real_ptr;\n\n    LOCK();\n    if (count == 0) {\n      /* Note: we hold the allocator lock here. */\n      bytes_freed_before = GC_bytes_freed;\n    } else if (UNLIKELY(GC_interrupt_finalizers != 0)\n               && (unsigned)count >= GC_interrupt_finalizers) {\n      UNLOCK();\n      break;\n    }\n    curr_fo = GC_fnlz_roots.finalize_now;\n#  ifdef THREADS\n    if (UNLIKELY(NULL == curr_fo)) {\n      UNLOCK();\n      break;\n    }\n#  endif\n    SET_FINALIZE_NOW(fo_next(curr_fo));\n    UNLOCK();\n    fo_set_next(curr_fo, 0);\n    real_ptr = (ptr_t)curr_fo->fo_hidden_base; /*< revealed */\n    curr_fo->fo_fn(real_ptr, curr_fo->fo_client_data);\n    curr_fo->fo_client_data = NULL;\n    ++count;\n    /*\n     * Explicit freeing of `curr_fo` is probably a bad idea.\n     * It throws off accounting if nearly all objects are finalizable.\n     * Otherwise it should not matter.\n     */\n  }\n  /* `bytes_freed_before` is initialized whenever `count` is nonzero. */\n  if (count != 0\n#  if defined(THREADS) && !defined(THREAD_SANITIZER)\n      /*\n       * A quick check whether some memory was freed.  The race with\n       * `GC_free()` is safe to be ignored because we only need to know\n       * if the current thread has deallocated something.\n       */\n      && bytes_freed_before != GC_bytes_freed\n#  endif\n  ) {\n    LOCK();\n    GC_finalizer_bytes_freed += (GC_bytes_freed - bytes_freed_before);\n    UNLOCK();\n  }\n  return count;\n}\n\nstatic word last_finalizer_notification = 0;\n\nGC_INNER void\nGC_notify_or_invoke_finalizers(void)\n{\n#  if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)\n  static word last_back_trace_gc_no = 0;\n#  endif\n  GC_finalizer_notifier_proc notifier_fn = 0;\n\n#  if defined(THREADS) && !defined(KEEP_BACK_PTRS) && !defined(MAKE_BACK_GRAPH)\n  /* Quick check (while unlocked) for an empty finalization queue. */\n  if (!GC_should_invoke_finalizers())\n    return;\n#  endif\n  LOCK();\n\n#  if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)\n  /*\n   * This is a convenient place to generate backtraces if appropriate,\n   * since that code is not callable with the allocator lock.\n   */\n  if (GC_gc_no != last_back_trace_gc_no\n      && LIKELY(GC_gc_no > 1) /*< skip initial collection */) {\n#    ifdef KEEP_BACK_PTRS\n    static GC_bool bt_in_progress = FALSE;\n\n    if (!bt_in_progress) {\n      long i;\n\n      /* Prevent a recursion or parallel usage. */\n      bt_in_progress = TRUE;\n      for (i = 0; i < GC_backtraces; ++i) {\n        /*\n         * FIXME: This tolerates concurrent heap mutation, which may\n         * cause occasional mysterious results.  We need to release\n         * the allocator lock, since `GC_print_callers()` acquires it.\n         * It probably should not.\n         */\n        void *current = GC_generate_random_valid_address();\n\n        UNLOCK();\n        GC_printf(\"\\n***Chosen address %p in object\\n\", current);\n        GC_print_backtrace(current);\n        LOCK();\n      }\n      bt_in_progress = FALSE;\n    }\n#    endif\n    last_back_trace_gc_no = GC_gc_no;\n#    ifdef MAKE_BACK_GRAPH\n    if (GC_print_back_height) {\n      GC_print_back_graph_stats();\n    }\n#    endif\n  }\n#  endif\n  if (NULL == GC_fnlz_roots.finalize_now) {\n    UNLOCK();\n    return;\n  }\n\n  if (!GC_finalize_on_demand) {\n    unsigned char *pnested;\n\n#  ifdef THREADS\n    if (UNLIKELY(GC_in_thread_creation)) {\n      UNLOCK();\n      return;\n    }\n#  endif\n    pnested = GC_check_finalizer_nested();\n    UNLOCK();\n    /* Skip `GC_invoke_finalizers()` if nested. */\n    if (pnested != NULL) {\n      (void)GC_invoke_finalizers();\n      /* Reset since no more finalizers or interrupted. */\n      *pnested = 0;\n#  ifndef THREADS\n      GC_ASSERT(NULL == GC_fnlz_roots.finalize_now\n                || GC_interrupt_finalizers > 0);\n#  else\n      /*\n       * Note: in the multi-threaded case GC can run concurrently and\n       * add more finalizers to run.\n       */\n#  endif\n    }\n    return;\n  }\n\n  /* These variables require synchronization to avoid data race. */\n  if (last_finalizer_notification != GC_gc_no) {\n    notifier_fn = GC_finalizer_notifier;\n    last_finalizer_notification = GC_gc_no;\n  }\n  UNLOCK();\n  if (notifier_fn != 0) {\n    /* Invoke the notifier. */\n    (*notifier_fn)();\n  }\n}\n\n#  ifndef SMALL_CONFIG\n#    ifndef GC_LONG_REFS_NOT_NEEDED\n#      define IF_LONG_REFS_PRESENT_ELSE(x, y) (x)\n#    else\n#      define IF_LONG_REFS_PRESENT_ELSE(x, y) (y)\n#    endif\n\nGC_INNER void\nGC_print_finalization_stats(void)\n{\n  const struct finalizable_object *fo;\n  unsigned long ready = 0;\n\n  GC_log_printf(\n      \"%lu finalization entries;\"\n      \" %lu/%lu short/long disappearing links alive\\n\",\n      (unsigned long)GC_fo_entries, (unsigned long)GC_dl_hashtbl.entries,\n      (unsigned long)IF_LONG_REFS_PRESENT_ELSE(GC_ll_hashtbl.entries, 0));\n\n  for (fo = GC_fnlz_roots.finalize_now; fo != NULL; fo = fo_next(fo))\n    ++ready;\n  GC_log_printf(\"%lu finalization-ready objects;\"\n                \" %ld/%ld short/long links cleared\\n\",\n                ready, (long)GC_old_dl_entries - (long)GC_dl_hashtbl.entries,\n                (long)IF_LONG_REFS_PRESENT_ELSE(\n                    GC_old_ll_entries - GC_ll_hashtbl.entries, 0));\n}\n#  endif /* !SMALL_CONFIG */\n\n#endif /* !GC_NO_FINALIZATION */\n\n/*\n * Copyright (c) 2011 by Hewlett-Packard Company.  All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#ifdef ENABLE_DISCLAIM\n\n#  include \"gc/gc_disclaim.h\"\n\n#  if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)\n/* The first bit is already used for a debug purpose. */\n#    define FINALIZER_CLOSURE_FLAG 0x2\n#  else\n#    define FINALIZER_CLOSURE_FLAG 0x1\n#  endif\n\nSTATIC int GC_CALLBACK\nGC_finalized_disclaim(void *obj)\n{\n#  ifdef AO_HAVE_load\n  ptr_t fc_p = GC_cptr_load((volatile ptr_t *)obj);\n#  else\n  ptr_t fc_p = *(ptr_t *)obj;\n#  endif\n\n  if ((ADDR(fc_p) & FINALIZER_CLOSURE_FLAG) != 0) {\n    /*\n     * The disclaim function may be passed fragments from the free-list,\n     * on which it should not run finalization.  To recognize this case,\n     * we use the fact that the value of the first pointer of such\n     * fragments is always, at least, multiple of a pointer size (a link\n     * to the next fragment, or `NULL`).\n     *\n     * Note: if it is desirable to have a finalizer which does not use\n     * the first pointer for storing the finalization information,\n     * `GC_disclaim_and_reclaim()` must be extended to clear fragments\n     * so that the assumption holds for the selected pointer location.\n     */\n    const struct GC_finalizer_closure *fc\n        = (struct GC_finalizer_closure *)CPTR_CLEAR_FLAGS(\n            fc_p, FINALIZER_CLOSURE_FLAG);\n\n    GC_ASSERT(!GC_find_leak_inner);\n    fc->proc((ptr_t *)obj + 1, fc->cd);\n  }\n  return 0;\n}\n\nSTATIC void\nGC_register_disclaim_proc_inner(unsigned kind, GC_disclaim_proc proc,\n                                GC_bool mark_unconditionally)\n{\n  GC_ASSERT(kind < MAXOBJKINDS);\n  if (UNLIKELY(GC_find_leak_inner))\n    return;\n\n  GC_obj_kinds[kind].ok_disclaim_proc = proc;\n  GC_obj_kinds[kind].ok_mark_unconditionally = mark_unconditionally;\n}\n\nGC_API void GC_CALL\nGC_init_finalized_malloc(void)\n{\n  /* Initialize the collector just in case it is not done yet. */\n  GC_init();\n\n  LOCK();\n  if (GC_finalized_kind != 0) {\n    UNLOCK();\n    return;\n  }\n\n  /*\n   * The finalizer closure is placed in the first pointer of the\n   * object in order to use the lower bits to distinguish live\n   * objects from objects on the free list.  The downside of this is\n   * that we need one-pointer offset interior pointers, and that\n   * `GC_base()` does not return the start of the user region.\n   */\n  GC_register_displacement_inner(sizeof(ptr_t));\n\n  /*\n   * And, the pointer to the finalizer closure object itself is displaced\n   * due to baking in this indicator.\n   */\n  GC_register_displacement_inner(FINALIZER_CLOSURE_FLAG);\n  GC_register_displacement_inner(sizeof(oh) | FINALIZER_CLOSURE_FLAG);\n\n  GC_finalized_kind\n      = GC_new_kind_inner(GC_new_free_list_inner(), GC_DS_LENGTH, TRUE, TRUE);\n  GC_ASSERT(GC_finalized_kind != 0);\n  GC_register_disclaim_proc_inner(GC_finalized_kind, GC_finalized_disclaim,\n                                  TRUE);\n  UNLOCK();\n}\n\nGC_API void GC_CALL\nGC_register_disclaim_proc(int kind, GC_disclaim_proc proc,\n                          int mark_unconditionally)\n{\n  LOCK();\n  GC_register_disclaim_proc_inner((unsigned)kind, proc,\n                                  (GC_bool)mark_unconditionally);\n  UNLOCK();\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_finalized_malloc(size_t lb, const struct GC_finalizer_closure *fclos)\n{\n  void *op;\n  ptr_t fc_p;\n\n#  ifndef LINT2\n  /* Actually, there is no data race because the variable is set once. */\n  GC_ASSERT(GC_finalized_kind != 0);\n#  endif\n  GC_ASSERT(NONNULL_ARG_NOT_NULL(fclos));\n  GC_ASSERT((ADDR(fclos) & FINALIZER_CLOSURE_FLAG) == 0);\n  op = GC_malloc_kind(SIZET_SAT_ADD(lb, sizeof(ptr_t)),\n                      (int)GC_finalized_kind);\n  if (UNLIKELY(NULL == op))\n    return NULL;\n\n  /*\n   * Set the flag (w/o conversion to a numeric type) and store\n   * the finalizer closure.\n   */\n  fc_p = CPTR_SET_FLAGS(GC_CAST_AWAY_CONST_PVOID(fclos),\n                        FINALIZER_CLOSURE_FLAG);\n#  ifdef AO_HAVE_store\n  GC_cptr_store((volatile ptr_t *)op, fc_p);\n#  else\n  *(ptr_t *)op = fc_p;\n#  endif\n  GC_dirty(op);\n  REACHABLE_AFTER_DIRTY(fc_p);\n  return (ptr_t *)op + 1;\n}\n\n#endif /* ENABLE_DISCLAIM */\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#include <string.h>\n\n/* Allocate reclaim list for the kind.  Returns `TRUE` on success. */\nSTATIC GC_bool\nGC_alloc_reclaim_list(struct obj_kind *ok)\n{\n  struct hblk **result;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  result = (struct hblk **)GC_scratch_alloc((MAXOBJGRANULES + 1)\n                                            * sizeof(struct hblk *));\n  if (UNLIKELY(NULL == result))\n    return FALSE;\n\n  BZERO(result, (MAXOBJGRANULES + 1) * sizeof(struct hblk *));\n  ok->ok_reclaim_list = result;\n  return TRUE;\n}\n\n/*\n * Allocate a large block of size `lb_adjusted` bytes with the requested\n * alignment (`align_m1 + 1`).  The block is not cleared.  We assume that\n * the size is nonzero and a multiple of `GC_GRANULE_BYTES`, and that\n * it already includes `EXTRA_BYTES` value.  The `flags` argument should\n * be `IGNORE_OFF_PAGE` or 0.  Calls `GC_allochblk()` to do the actual\n * allocation, but also triggers collection and/or heap expansion\n * as appropriate.  Updates value of `GC_bytes_allocd`; does also other\n * accounting.\n */\nSTATIC ptr_t\nGC_alloc_large(size_t lb_adjusted, int kind, unsigned flags, size_t align_m1)\n{\n  /*\n   * TODO: It is unclear which retries limit is sufficient (value of 3 leads\n   * to fail in some 32-bit applications, 10 is a kind of arbitrary value).\n   */\n#define MAX_ALLOCLARGE_RETRIES 10\n\n  int retry_cnt;\n  size_t n_blocks; /*< includes alignment */\n  struct hblk *h;\n  ptr_t result;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(lb_adjusted != 0 && (lb_adjusted & (GC_GRANULE_BYTES - 1)) == 0);\n  n_blocks = OBJ_SZ_TO_BLOCKS_CHECKED(SIZET_SAT_ADD(lb_adjusted, align_m1));\n  if (UNLIKELY(!GC_is_initialized)) {\n    UNLOCK(); /*< just to unset `GC_lock_holder` */\n    GC_init();\n    LOCK();\n  }\n  /* Do our share of marking work. */\n  if (GC_incremental && !GC_dont_gc) {\n    GC_collect_a_little_inner(n_blocks);\n  }\n\n  h = GC_allochblk(lb_adjusted, kind, flags, align_m1);\n#ifdef USE_MUNMAP\n  if (NULL == h && GC_merge_unmapped()) {\n    h = GC_allochblk(lb_adjusted, kind, flags, align_m1);\n  }\n#endif\n  for (retry_cnt = 0; NULL == h; retry_cnt++) {\n    /*\n     * Only a few iterations are expected at most, otherwise something\n     * is wrong in one of the functions called below.\n     */\n    if (retry_cnt > MAX_ALLOCLARGE_RETRIES)\n      ABORT(\"Too many retries in GC_alloc_large\");\n    if (UNLIKELY(!GC_collect_or_expand(n_blocks, flags, retry_cnt > 0)))\n      return NULL;\n    h = GC_allochblk(lb_adjusted, kind, flags, align_m1);\n  }\n\n  GC_bytes_allocd += lb_adjusted;\n  if (lb_adjusted > HBLKSIZE) {\n    GC_large_allocd_bytes += HBLKSIZE * OBJ_SZ_TO_BLOCKS(lb_adjusted);\n    if (GC_large_allocd_bytes > GC_max_large_allocd_bytes)\n      GC_max_large_allocd_bytes = GC_large_allocd_bytes;\n  }\n  /* FIXME: Do we need some way to reset `GC_max_large_allocd_bytes`? */\n  result = h->hb_body;\n  GC_ASSERT((ADDR(result) & align_m1) == 0);\n  return result;\n}\n\n/*\n * Allocate a large block of given size in bytes, clear it if appropriate.\n * We assume that the size is nonzero and a multiple of `GC_GRANULE_BYTES`,\n * and that it already includes `EXTRA_BYTES` value.  Update value of\n * `GC_bytes_allocd`.\n */\nSTATIC ptr_t\nGC_alloc_large_and_clear(size_t lb_adjusted, int kind, unsigned flags)\n{\n  ptr_t result;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  result = GC_alloc_large(lb_adjusted, kind, flags, 0 /* `align_m1` */);\n  if (LIKELY(result != NULL)\n      && (GC_debugging_started || GC_obj_kinds[kind].ok_init)) {\n    /* Clear the whole block, in case of `GC_realloc` call. */\n    BZERO(result, HBLKSIZE * OBJ_SZ_TO_BLOCKS(lb_adjusted));\n  }\n  return result;\n}\n\n/*\n * Fill in additional entries in `GC_size_map`, including the `i`-th one.\n * Note that a filled in section of the array ending at `n` always has\n * the length of at least `n / 4`.\n */\nSTATIC void\nGC_extend_size_map(size_t i)\n{\n  size_t original_lg = ALLOC_REQUEST_GRANS(i);\n  size_t lg;\n  /*\n   * The size we try to preserve.  Close to `i`, unless this would\n   * introduce too many distinct sizes.\n   */\n  size_t byte_sz = GRANULES_TO_BYTES(original_lg);\n  size_t smaller_than_i = byte_sz - (byte_sz >> 3);\n  /* The lowest indexed entry we initialize. */\n  size_t low_limit;\n  size_t number_of_objs;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(0 == GC_size_map[i]);\n  if (0 == GC_size_map[smaller_than_i]) {\n    low_limit = byte_sz - (byte_sz >> 2); /*< much smaller than `i` */\n    lg = original_lg;\n    while (GC_size_map[low_limit] != 0)\n      low_limit++;\n  } else {\n    low_limit = smaller_than_i + 1;\n    while (GC_size_map[low_limit] != 0)\n      low_limit++;\n\n    lg = ALLOC_REQUEST_GRANS(low_limit);\n    lg += lg >> 3;\n    if (lg < original_lg)\n      lg = original_lg;\n  }\n\n  /*\n   * For these larger sizes, we use an even number of granules.\n   * This makes it easier to, e.g., construct a 16-byte-aligned\n   * allocator even if `GC_GRANULE_BYTES` is 8.\n   */\n  lg = (lg + 1) & ~(size_t)1;\n  if (lg > MAXOBJGRANULES)\n    lg = MAXOBJGRANULES;\n\n  /* If we can fit the same number of larger objects in a block, do so. */\n  GC_ASSERT(lg != 0);\n  number_of_objs = HBLK_GRANULES / lg;\n  GC_ASSERT(number_of_objs != 0);\n  lg = (HBLK_GRANULES / number_of_objs) & ~(size_t)1;\n\n  /*\n   * We may need one extra byte; do not always fill in\n   * `GC_size_map[byte_sz]`.\n   */\n  byte_sz = GRANULES_TO_BYTES(lg) - EXTRA_BYTES;\n\n  for (; low_limit <= byte_sz; low_limit++)\n    GC_size_map[low_limit] = lg;\n}\n\nSTATIC void *\nGC_generic_malloc_inner_small(size_t lb, int kind)\n{\n  struct obj_kind *ok = &GC_obj_kinds[kind];\n  size_t lg = GC_size_map[lb];\n  void **opp = &ok->ok_freelist[lg];\n  void *op = *opp;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (UNLIKELY(NULL == op)) {\n    if (0 == lg) {\n      if (UNLIKELY(!GC_is_initialized)) {\n        UNLOCK(); /*< just to unset `GC_lock_holder` */\n        GC_init();\n        LOCK();\n        lg = GC_size_map[lb];\n      }\n      if (0 == lg) {\n        GC_extend_size_map(lb);\n        lg = GC_size_map[lb];\n        GC_ASSERT(lg != 0);\n      }\n      /* Retry. */\n      opp = &ok->ok_freelist[lg];\n      op = *opp;\n    }\n    if (NULL == op) {\n      if (NULL == ok->ok_reclaim_list && !GC_alloc_reclaim_list(ok))\n        return NULL;\n      op = GC_allocobj(lg, kind);\n      if (NULL == op)\n        return NULL;\n    }\n  }\n  *opp = obj_link(op);\n  obj_link(op) = NULL;\n  GC_bytes_allocd += GRANULES_TO_BYTES((word)lg);\n  return op;\n}\n\nGC_INNER void *\nGC_generic_malloc_inner(size_t lb, int kind, unsigned flags)\n{\n  size_t lb_adjusted;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(kind < MAXOBJKINDS);\n  if (SMALL_OBJ(lb)) {\n    return GC_generic_malloc_inner_small(lb, kind);\n  }\n\n#if MAX_EXTRA_BYTES > 0\n  if ((flags & IGNORE_OFF_PAGE) != 0 && lb >= HBLKSIZE) {\n    /* No need to add `EXTRA_BYTES`. */\n    lb_adjusted = lb;\n  } else\n#endif\n  /* else */ {\n    lb_adjusted = ADD_EXTRA_BYTES(lb);\n  }\n  return GC_alloc_large_and_clear(ROUNDUP_GRANULE_SIZE(lb_adjusted), kind,\n                                  flags);\n}\n\n#ifdef GC_COLLECT_AT_MALLOC\n#  if defined(CPPCHECK)\nsize_t GC_dbg_collect_at_malloc_min_lb = 16 * 1024; /*< some value */\n#  else\nsize_t GC_dbg_collect_at_malloc_min_lb = (GC_COLLECT_AT_MALLOC);\n#  endif\n#endif\n\nGC_INNER void *\nGC_generic_malloc_aligned(size_t lb, int kind, unsigned flags, size_t align_m1)\n{\n  void *result;\n\n  GC_ASSERT(kind < MAXOBJKINDS);\n  if (UNLIKELY(get_have_errors()))\n    GC_print_all_errors();\n  GC_notify_or_invoke_finalizers();\n  GC_DBG_COLLECT_AT_MALLOC(lb);\n  if (SMALL_OBJ(lb) && LIKELY(align_m1 < GC_GRANULE_BYTES)) {\n    LOCK();\n    result = GC_generic_malloc_inner_small(lb, kind);\n    UNLOCK();\n  } else {\n#ifdef THREADS\n    size_t lg;\n#endif\n    size_t lb_adjusted;\n    GC_bool init;\n\n#if MAX_EXTRA_BYTES > 0\n    if ((flags & IGNORE_OFF_PAGE) != 0 && lb >= HBLKSIZE) {\n      /* No need to add `EXTRA_BYTES`. */\n      lb_adjusted = ROUNDUP_GRANULE_SIZE(lb);\n#  ifdef THREADS\n      lg = BYTES_TO_GRANULES(lb_adjusted);\n#  endif\n    } else\n#endif\n    /* else */ {\n#ifndef THREADS\n      size_t lg; /*< CPPCHECK */\n#endif\n\n      if (UNLIKELY(0 == lb))\n        lb = 1;\n      lg = ALLOC_REQUEST_GRANS(lb);\n      lb_adjusted = GRANULES_TO_BYTES(lg);\n    }\n\n    init = GC_obj_kinds[kind].ok_init;\n    if (LIKELY(align_m1 < GC_GRANULE_BYTES)) {\n      align_m1 = 0;\n    } else if (align_m1 < HBLKSIZE) {\n      align_m1 = HBLKSIZE - 1;\n    }\n    LOCK();\n    result = GC_alloc_large(lb_adjusted, kind, flags, align_m1);\n    if (LIKELY(result != NULL)) {\n      if (GC_debugging_started\n#ifndef THREADS\n          || init\n#endif\n      ) {\n        BZERO(result, HBLKSIZE * OBJ_SZ_TO_BLOCKS(lb_adjusted));\n      } else {\n#ifdef THREADS\n        GC_ASSERT(GRANULES_TO_PTRS(lg) >= 2);\n        /*\n         * Clear any memory that might be used for the GC descriptors\n         * before we release the allocator lock.\n         */\n        ((ptr_t *)result)[0] = NULL;\n        ((ptr_t *)result)[1] = NULL;\n        ((ptr_t *)result)[GRANULES_TO_PTRS(lg) - 1] = NULL;\n        ((ptr_t *)result)[GRANULES_TO_PTRS(lg) - 2] = NULL;\n#endif\n      }\n    }\n    UNLOCK();\n#ifdef THREADS\n    if (init && !GC_debugging_started && result != NULL) {\n      /* Clear the rest (i.e. excluding the initial 2 words). */\n      BZERO((ptr_t *)result + 2,\n            HBLKSIZE * OBJ_SZ_TO_BLOCKS(lb_adjusted) - 2 * sizeof(ptr_t));\n    }\n#endif\n  }\n  if (UNLIKELY(NULL == result)) {\n    result = (*GC_get_oom_fn())(lb);\n    /* Note: result might be misaligned. */\n  }\n  return result;\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_generic_malloc(size_t lb, int kind)\n{\n  return GC_generic_malloc_aligned(lb, kind, 0 /* `flags` */,\n                                   0 /* `align_m1` */);\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_malloc_kind_global(size_t lb, int kind)\n{\n  return GC_malloc_kind_aligned_global(lb, kind, 0 /* `align_m1` */);\n}\n\nGC_INNER void *\nGC_malloc_kind_aligned_global(size_t lb, int kind, size_t align_m1)\n{\n  GC_ASSERT(kind < MAXOBJKINDS);\n  if (SMALL_OBJ(lb) && LIKELY(align_m1 < HBLKSIZE / 2)) {\n    void *op;\n    void **opp;\n    size_t lg;\n\n    GC_DBG_COLLECT_AT_MALLOC(lb);\n    LOCK();\n    lg = GC_size_map[lb];\n    opp = &GC_obj_kinds[kind].ok_freelist[lg];\n    op = *opp;\n    if (UNLIKELY(align_m1 >= GC_GRANULE_BYTES)) {\n      /* TODO: Avoid linear search. */\n      for (; (ADDR(op) & align_m1) != 0; op = *opp) {\n        opp = &obj_link(op);\n      }\n    }\n    if (LIKELY(op != NULL)) {\n      GC_ASSERT(PTRFREE == kind || NULL == obj_link(op)\n                || (ADDR(obj_link(op)) < GC_greatest_real_heap_addr\n                    && GC_least_real_heap_addr < ADDR(obj_link(op))));\n      *opp = obj_link(op);\n      if (kind != PTRFREE)\n        obj_link(op) = NULL;\n      GC_bytes_allocd += GRANULES_TO_BYTES((word)lg);\n      UNLOCK();\n      GC_ASSERT((ADDR(op) & align_m1) == 0);\n      return op;\n    }\n    UNLOCK();\n  }\n\n  /*\n   * We make the `GC_clear_stack()` call a tail one, hoping to get more\n   * of the stack.\n   */\n  return GC_clear_stack(\n      GC_generic_malloc_aligned(lb, kind, 0 /* `flags` */, align_m1));\n}\n\n#if defined(THREADS) && !defined(THREAD_LOCAL_ALLOC)\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_malloc_kind(size_t lb, int kind)\n{\n  return GC_malloc_kind_global(lb, kind);\n}\n#endif\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_malloc_atomic(size_t lb)\n{\n  /* Allocate `lb` bytes of atomic (pointer-free) data. */\n  return GC_malloc_kind(lb, PTRFREE);\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_malloc(size_t lb)\n{\n  /* Allocate `lb` bytes of composite (pointerful) data. */\n  return GC_malloc_kind(lb, NORMAL);\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_generic_malloc_uncollectable(size_t lb, int kind)\n{\n  void *op;\n  size_t lb_orig = lb;\n\n  GC_ASSERT(kind < MAXOBJKINDS);\n  if (EXTRA_BYTES != 0 && LIKELY(lb != 0)) {\n    /*\n     * We do not need the extra byte, since this will not be collected\n     * anyway.\n     */\n    lb--;\n  }\n\n  if (SMALL_OBJ(lb)) {\n    void **opp;\n    size_t lg;\n\n    if (UNLIKELY(get_have_errors()))\n      GC_print_all_errors();\n    GC_notify_or_invoke_finalizers();\n    GC_DBG_COLLECT_AT_MALLOC(lb_orig);\n    LOCK();\n    lg = GC_size_map[lb];\n    opp = &GC_obj_kinds[kind].ok_freelist[lg];\n    op = *opp;\n    if (LIKELY(op != NULL)) {\n      *opp = obj_link(op);\n      obj_link(op) = 0;\n      GC_bytes_allocd += GRANULES_TO_BYTES((word)lg);\n      /*\n       * Mark bit was already set on free list.  It will be cleared only\n       * temporarily during a collection, as a result of the normal\n       * free-list mark bit clearing.\n       */\n      GC_non_gc_bytes += GRANULES_TO_BYTES((word)lg);\n    } else {\n      op = GC_generic_malloc_inner_small(lb, kind);\n      if (NULL == op) {\n        GC_oom_func oom_fn = GC_oom_fn;\n        UNLOCK();\n        return (*oom_fn)(lb_orig);\n      }\n      /* For small objects, the free lists are completely marked. */\n    }\n    GC_ASSERT(GC_is_marked(op));\n    UNLOCK();\n  } else {\n    op = GC_generic_malloc_aligned(lb, kind, 0 /* `flags` */,\n                                   0 /* `align_m1` */);\n    if (op /* `!= NULL` */) { /*< CPPCHECK */\n      hdr *hhdr = HDR(op);\n\n      GC_ASSERT(HBLKDISPL(op) == 0); /*< large block */\n\n      /*\n       * We do not need to acquire the allocator lock before `HDR(op)`,\n       * since we have an undisguised pointer, but we need it while we\n       * adjust the mark bits.\n       */\n      LOCK();\n      set_mark_bit_from_hdr(hhdr, 0); /*< the only object */\n#ifndef THREADS\n      /*\n       * This is not guaranteed in the multi-threaded case because the\n       * counter could be updated before locking.\n       */\n      GC_ASSERT(hhdr->hb_n_marks == 0);\n#endif\n      hhdr->hb_n_marks = 1;\n      UNLOCK();\n    }\n  }\n  return op;\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_malloc_uncollectable(size_t lb)\n{\n  /* Allocate `lb` bytes of pointerful, traced, but not collectible data. */\n  return GC_generic_malloc_uncollectable(lb, UNCOLLECTABLE);\n}\n\n#ifdef GC_ATOMIC_UNCOLLECTABLE\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_malloc_atomic_uncollectable(size_t lb)\n{\n  return GC_generic_malloc_uncollectable(lb, AUNCOLLECTABLE);\n}\n#endif /* GC_ATOMIC_UNCOLLECTABLE */\n\n#if defined(REDIRECT_MALLOC) && !defined(REDIRECT_MALLOC_IN_HEADER)\n\n#  ifndef MSWINCE\n#    include <errno.h>\n#  endif\n\n/*\n * Avoid unnecessary nested procedure calls here, by `#define` some `malloc`\n * replacements.  Otherwise we end up saving a meaningless return address in\n * the object.  It also speeds things up, but it is admittedly quite ugly.\n */\n#  define GC_debug_malloc_replacement(lb) GC_debug_malloc(lb, GC_DBG_EXTRAS)\n\n#  if defined(CPPCHECK)\n#    define REDIRECT_MALLOC_F GC_malloc /*< e.g. */\n#  else\n#    define REDIRECT_MALLOC_F REDIRECT_MALLOC\n#  endif\n\nvoid *\nmalloc(size_t lb)\n{\n  /*\n   * It might help to manually inline the `GC_malloc` call here.\n   * But any decent compiler should reduce the extra procedure call\n   * to at most a jump instruction in this case.\n   */\n#  if defined(SOLARIS) && defined(THREADS) && defined(I386)\n  /*\n   * Thread initialization can call `malloc` before we are ready for.\n   * It is not clear that this is enough to help matters.  The thread\n   * implementation may well call `malloc` at other inopportune times.\n   */\n  if (UNLIKELY(!GC_is_initialized))\n    return sbrk(lb);\n#  endif\n  return (void *)REDIRECT_MALLOC_F(lb);\n}\n\n#  ifdef REDIR_MALLOC_AND_LINUXTHREADS\n#    ifdef HAVE_LIBPTHREAD_SO\nSTATIC ptr_t GC_libpthread_start = NULL;\nSTATIC ptr_t GC_libpthread_end = NULL;\n#    endif\nSTATIC ptr_t GC_libld_start = NULL;\nSTATIC ptr_t GC_libld_end = NULL;\nstatic GC_bool lib_bounds_set = FALSE;\n\nGC_INNER void\nGC_init_lib_bounds(void)\n{\n  IF_CANCEL(int cancel_state;)\n\n  /*\n   * This test does not need to ensure memory visibility, since the bounds\n   * will be set when/if we create another thread.\n   */\n  if (LIKELY(lib_bounds_set))\n    return;\n\n  DISABLE_CANCEL(cancel_state);\n  GC_init(); /*< if not called yet */\n\n#    if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED)\n  LOCK(); /*< just to set `GC_lock_holder` */\n#    endif\n#    ifdef HAVE_LIBPTHREAD_SO\n  if (!GC_text_mapping(\"libpthread-\", &GC_libpthread_start,\n                       &GC_libpthread_end)) {\n    WARN(\"Failed to find libpthread.so text mapping: Expect crash\\n\", 0);\n    /*\n     * This might still work with some versions of `libpthread`,\n     * so we do not `abort`.\n     */\n  }\n#    endif\n  if (!GC_text_mapping(\"ld-\", &GC_libld_start, &GC_libld_end)) {\n    WARN(\"Failed to find ld.so text mapping: Expect crash\\n\", 0);\n  }\n#    if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED)\n  UNLOCK();\n#    endif\n  RESTORE_CANCEL(cancel_state);\n  lib_bounds_set = TRUE;\n}\n#  endif /* REDIR_MALLOC_AND_LINUXTHREADS */\n\nvoid *\ncalloc(size_t n, size_t lb)\n{\n  if (UNLIKELY((lb | n) > GC_SQRT_SIZE_MAX) /*< fast initial test */\n      && lb && n > GC_SIZE_MAX / lb)\n    return (*GC_get_oom_fn())(GC_SIZE_MAX); /*< `n * lb` overflow */\n#  ifdef REDIR_MALLOC_AND_LINUXTHREADS\n  /*\n   * The linker may allocate some memory that is only pointed to by\n   * memory-mapped thread stacks.  Make sure it is not collectible.\n   */\n  {\n    ptr_t caller = (ptr_t)__builtin_return_address(0);\n\n    GC_init_lib_bounds();\n    if (ADDR_INSIDE(caller, GC_libld_start, GC_libld_end)\n#    ifdef HAVE_LIBPTHREAD_SO\n        /*\n         * Note: the two ranges are actually usually adjacent, so there\n         * may be a way to speed this up.\n         */\n        || ADDR_INSIDE(caller, GC_libpthread_start, GC_libpthread_end)\n#    endif\n    ) {\n      return GC_generic_malloc_uncollectable(n * lb, UNCOLLECTABLE);\n    }\n  }\n#  endif\n  return (void *)REDIRECT_MALLOC_F(n * lb);\n}\n\n#  ifndef strdup\nchar *\nstrdup(const char *s)\n{\n  size_t lb = strlen(s) + 1;\n  char *result = (char *)REDIRECT_MALLOC_F(lb);\n\n  if (UNLIKELY(NULL == result)) {\n    errno = ENOMEM;\n    return NULL;\n  }\n  BCOPY(s, result, lb);\n  return result;\n}\n#  else\n/*\n * If `strdup` is macro defined, we assume that it actually calls `malloc`,\n * and thus the right thing will happen even without overriding it.\n * This seems to be true on most Linux systems.\n */\n#  endif /* strdup */\n\n#  ifndef strndup\n/* This is similar to `strdup()`. */\nchar *\nstrndup(const char *str, size_t size)\n{\n  char *copy;\n  size_t len = strlen(str);\n  if (UNLIKELY(len > size))\n    len = size;\n  copy = (char *)REDIRECT_MALLOC_F(len + 1);\n  if (UNLIKELY(NULL == copy)) {\n    errno = ENOMEM;\n    return NULL;\n  }\n  if (LIKELY(len > 0))\n    BCOPY(str, copy, len);\n  copy[len] = '\\0';\n  return copy;\n}\n#  endif /* !strndup */\n\n#  undef GC_debug_malloc_replacement\n\n#endif /* REDIRECT_MALLOC */\n\n/* Explicitly deallocate the object.  `hhdr` should correspond to `p`. */\nstatic void\nfree_internal(void *p, const hdr *hhdr)\n{\n  size_t lb = hhdr->hb_sz;           /*< size in bytes */\n  size_t lg = BYTES_TO_GRANULES(lb); /*< size in granules */\n  int kind = hhdr->hb_obj_kind;\n\n  GC_bytes_freed += lb;\n  if (IS_UNCOLLECTABLE(kind))\n    GC_non_gc_bytes -= lb;\n  if (LIKELY(lg <= MAXOBJGRANULES)) {\n    struct obj_kind *ok = &GC_obj_kinds[kind];\n    void **flh;\n\n    /*\n     * It is unnecessary to clear the mark bit.  If the object is\n     * reallocated, it does not matter.  Otherwise, the collector will\n     * do it, since it is on a free list.\n     */\n    if (ok->ok_init && LIKELY(lb > sizeof(ptr_t))) {\n      BZERO((ptr_t *)p + 1, lb - sizeof(ptr_t));\n    }\n\n    flh = &ok->ok_freelist[lg];\n    obj_link(p) = *flh;\n    *flh = (ptr_t)p;\n  } else {\n    if (lb > HBLKSIZE) {\n      GC_large_allocd_bytes -= HBLKSIZE * OBJ_SZ_TO_BLOCKS(lb);\n    }\n    GC_ASSERT(ADDR(HBLKPTR(p)) == ADDR(hhdr->hb_block));\n    GC_freehblk(hhdr->hb_block);\n  }\n}\n\nGC_API void GC_CALL\nGC_free(void *p)\n{\n  const hdr *hhdr;\n\n  if (p /* `!= NULL` */) {\n    /* CPPCHECK */\n  } else {\n    /* Required by ANSI.  It is not my fault... */\n    return;\n  }\n\n#ifdef LOG_ALLOCS\n  GC_log_printf(\"GC_free(%p) after GC #%lu\\n\", p, (unsigned long)GC_gc_no);\n#endif\n  hhdr = HDR(p);\n#if defined(REDIRECT_MALLOC)                                           \\\n    && ((defined(NEED_CALLINFO) && defined(GC_HAVE_BUILTIN_BACKTRACE)) \\\n        || defined(REDIR_MALLOC_AND_LINUXTHREADS)                      \\\n        || (defined(SOLARIS) && defined(THREADS)) || defined(MSWIN32))\n  /*\n   * This might be called indirectly by `GC_print_callers` to free the\n   * result of `backtrace_symbols()`.  For Solaris, we have to redirect\n   * `malloc` calls during initialization.  For the others, this seems\n   * to happen implicitly.  Do not try to deallocate that memory.\n   */\n  if (UNLIKELY(NULL == hhdr))\n    return;\n#endif\n  GC_ASSERT(GC_base(p) == p);\n  LOCK();\n  free_internal(p, hhdr);\n  FREE_PROFILER_HOOK(p);\n  UNLOCK();\n}\n\n#ifdef THREADS\nGC_INNER void\nGC_free_inner(void *p)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  free_internal(p, HDR(p));\n}\n#endif /* THREADS */\n\n#if defined(REDIRECT_MALLOC) && !defined(REDIRECT_FREE)\n#  define REDIRECT_FREE GC_free\n#endif\n\n#if defined(REDIRECT_FREE) && !defined(REDIRECT_MALLOC_IN_HEADER)\n\n#  if defined(CPPCHECK)\n#    define REDIRECT_FREE_F GC_free /*< e.g. */\n#  else\n#    define REDIRECT_FREE_F REDIRECT_FREE\n#  endif\n\nvoid\nfree(void *p)\n{\n#  ifdef IGNORE_FREE\n  UNUSED_ARG(p);\n#  else\n#    if defined(REDIR_MALLOC_AND_LINUXTHREADS) \\\n        && !defined(USE_PROC_FOR_LIBRARIES)\n  /*\n   * Do not bother with initialization checks.  If nothing has been\n   * initialized, then the check fails, and that is safe, since we have\n   * not allocated uncollectible objects neither.\n   */\n  ptr_t caller = (ptr_t)__builtin_return_address(0);\n\n  /*\n   * This test does not need to ensure memory visibility, since the bounds\n   * will be set when/if we create another thread.\n   */\n  if (ADDR_INSIDE(caller, GC_libld_start, GC_libld_end)\n#      ifdef HAVE_LIBPTHREAD_SO\n      || ADDR_INSIDE(caller, GC_libpthread_start, GC_libpthread_end)\n#      endif\n  ) {\n    GC_free(p);\n    return;\n  }\n#    endif\n  REDIRECT_FREE_F(p);\n#  endif\n}\n#endif /* REDIRECT_FREE */\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2000 by Hewlett-Packard Company.  All rights reserved.\n * Copyright (c) 2009-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n/*\n * These are extra allocation routines that are likely to be less\n * frequently used than those in `malloc.c` file.  They are separate in\n * the hope that the `.o` file will be excluded from statically linked\n * executables.  We should probably break this up further.\n */\n\n#include <string.h>\n\n#ifndef MSWINCE\n#  include <errno.h>\n#endif\n\n/*\n * Some externally visible but unadvertised variables to allow access\n * to free lists from inlined allocators without include `gc_priv.h` file\n * or introducing dependencies on internal data structure layouts.\n */\nvoid **const GC_objfreelist_ptr = GC_objfreelist;\nvoid **const GC_aobjfreelist_ptr = GC_aobjfreelist;\nvoid **const GC_uobjfreelist_ptr = GC_uobjfreelist;\n#ifdef GC_ATOMIC_UNCOLLECTABLE\nvoid **const GC_auobjfreelist_ptr = GC_auobjfreelist;\n#endif\n\nGC_API int GC_CALL\nGC_get_kind_and_size(const void *p, size_t *psize)\n{\n  const hdr *hhdr = HDR(p);\n\n  if (psize != NULL) {\n    *psize = hhdr->hb_sz;\n  }\n  return hhdr->hb_obj_kind;\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_generic_or_special_malloc(size_t lb, int kind)\n{\n  switch (kind) {\n  case PTRFREE:\n  case NORMAL:\n    return GC_malloc_kind(lb, kind);\n  case UNCOLLECTABLE:\n#ifdef GC_ATOMIC_UNCOLLECTABLE\n  case AUNCOLLECTABLE:\n#endif\n    return GC_generic_malloc_uncollectable(lb, kind);\n  default:\n    return GC_generic_malloc_aligned(lb, kind, 0 /* `flags` */, 0);\n  }\n}\n\nGC_API void *GC_CALL\nGC_realloc(void *p, size_t lb)\n{\n  hdr *hhdr;\n  void *result;\n#if defined(_FORTIFY_SOURCE) && defined(__GNUC__) && !defined(__clang__)\n  /*\n   * Use `cleared_p` instead of `p` as a workaround to avoid passing\n   * `alloc_size(lb)` attribute associated with `p` to `memset`\n   * (including a `memset` call inside `GC_free`).\n   */\n  volatile GC_uintptr_t cleared_p = (GC_uintptr_t)p;\n#else\n#  define cleared_p p\n#endif\n  size_t sz;      /*< current size in bytes */\n  size_t orig_sz; /*< original `sz` (in bytes) */\n  int obj_kind;\n\n  if (NULL == p) {\n    /* Required by ANSI. */\n    return GC_malloc(lb);\n  }\n  if (0 == lb) /* `&& p != NULL` */ {\n#ifndef IGNORE_FREE\n    GC_free(p);\n#endif\n    return NULL;\n  }\n  hhdr = HDR(HBLKPTR(p));\n  sz = hhdr->hb_sz;\n  obj_kind = hhdr->hb_obj_kind;\n  orig_sz = sz;\n\n  if (sz > MAXOBJBYTES) {\n    const struct obj_kind *ok = &GC_obj_kinds[obj_kind];\n    word descr = ok->ok_descriptor;\n\n    /* Round it up to the next whole heap block. */\n    sz = (sz + HBLKSIZE - 1) & ~(HBLKSIZE - 1);\n#if ALIGNMENT > GC_DS_TAGS\n    /*\n     * An extra byte is not added in case of ignore-off-page allocated\n     * objects not smaller than `HBLKSIZE`.\n     */\n    GC_ASSERT(sz >= HBLKSIZE);\n    if (EXTRA_BYTES != 0 && (hhdr->hb_flags & IGNORE_OFF_PAGE) != 0\n        && obj_kind == NORMAL)\n      descr += ALIGNMENT; /*< or set to 0 */\n#endif\n    if (ok->ok_relocate_descr) {\n      descr += sz;\n    }\n\n    /*\n     * `GC_realloc` might be changing the block size while\n     * `GC_reclaim_block` or `GC_clear_hdr_marks` is examining it.\n     * The change to the size field is benign, in that `GC_reclaim`\n     * (and `GC_clear_hdr_marks`) would work correctly with either\n     * value, since we are not changing the number of objects in\n     * the block.  But seeing a half-updated value (though unlikely\n     * to occur in practice) could be probably bad.\n     * Using unordered atomic accesses on `hb_sz` and `hb_descr`\n     * fields would solve the issue.  (The alternate solution might\n     * be to initially overallocate large objects, so we do not\n     * have to adjust the size in `GC_realloc`, if they still fit.\n     * But that is probably more expensive, since we may end up\n     * scanning a bunch of zeros during the collection.)\n     */\n#ifdef AO_HAVE_store\n    AO_store(&hhdr->hb_sz, sz);\n    AO_store((AO_t *)&hhdr->hb_descr, descr);\n#else\n    {\n      LOCK();\n      hhdr->hb_sz = sz;\n      hhdr->hb_descr = descr;\n      UNLOCK();\n    }\n#endif\n\n#ifdef MARK_BIT_PER_OBJ\n    GC_ASSERT(hhdr->hb_inv_sz == LARGE_INV_SZ);\n#else\n    GC_ASSERT((hhdr->hb_flags & LARGE_BLOCK) != 0\n              && hhdr->hb_map[ANY_INDEX] == 1);\n#endif\n    if (IS_UNCOLLECTABLE(obj_kind))\n      GC_non_gc_bytes += (sz - orig_sz);\n    /* Extra area is already cleared by `GC_alloc_large_and_clear`. */\n  }\n  if (ADD_EXTRA_BYTES(lb) <= sz) {\n    if (lb >= (sz >> 1)) {\n      if (orig_sz > lb) {\n        /* Clear unneeded part of object to avoid bogus pointer tracing. */\n        BZERO((ptr_t)cleared_p + lb, orig_sz - lb);\n      }\n      return p;\n    }\n    /*\n     * Shrink it.  Note: shrinking of large blocks is not implemented\n     * efficiently.\n     */\n    sz = lb;\n  }\n  result = GC_generic_or_special_malloc((word)lb, obj_kind);\n  if (LIKELY(result != NULL)) {\n    /*\n     * In case of shrink, it could also return original object.\n     * But this gives the client warning of imminent disaster.\n     */\n    BCOPY(p, result, sz);\n#ifndef IGNORE_FREE\n    GC_free((ptr_t)cleared_p);\n#endif\n  }\n  return result;\n#undef cleared_p\n}\n\n#if defined(REDIRECT_MALLOC) && !defined(REDIRECT_REALLOC)\n#  define REDIRECT_REALLOC GC_realloc\n#endif\n\n#ifdef REDIRECT_REALLOC\n\n/* As with `malloc`, avoid two levels of extra calls here. */\n#  define GC_debug_realloc_replacement(p, lb) \\\n    GC_debug_realloc(p, lb, GC_DBG_EXTRAS)\n\n#  if !defined(REDIRECT_MALLOC_IN_HEADER)\nvoid *\nrealloc(void *p, size_t lb)\n{\n  return REDIRECT_REALLOC(p, lb);\n}\n#  endif\n\n#  undef GC_debug_realloc_replacement\n#endif /* REDIRECT_REALLOC */\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_generic_malloc_ignore_off_page(size_t lb, int kind)\n{\n  return GC_generic_malloc_aligned(lb, kind, IGNORE_OFF_PAGE,\n                                   0 /* `align_m1` */);\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_malloc_ignore_off_page(size_t lb)\n{\n  return GC_generic_malloc_aligned(lb, NORMAL, IGNORE_OFF_PAGE, 0);\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_malloc_atomic_ignore_off_page(size_t lb)\n{\n  return GC_generic_malloc_aligned(lb, PTRFREE, IGNORE_OFF_PAGE, 0);\n}\n\n/*\n * Increment `GC_bytes_allocd` from code that does not have direct access\n * to `GC_arrays`.\n */\nvoid GC_CALL\nGC_incr_bytes_allocd(size_t n)\n{\n  GC_bytes_allocd += n;\n}\n\n/* The same as `GC_incr_bytes_allocd` but for `GC_bytes_freed`. */\nvoid GC_CALL\nGC_incr_bytes_freed(size_t n)\n{\n  GC_bytes_freed += n;\n}\n\nGC_API size_t GC_CALL\nGC_get_expl_freed_bytes_since_gc(void)\n{\n  return (size_t)GC_bytes_freed;\n}\n\nGC_API void GC_CALL\nGC_generic_malloc_many(size_t lb_adjusted, int kind, void **result)\n{\n  void *op;\n  void *p;\n  void **opp;\n  /* The value of `lb_adjusted` converted to granules. */\n  size_t lg;\n  word my_bytes_allocd = 0;\n  struct obj_kind *ok;\n  struct hblk **rlh;\n\n  GC_ASSERT(lb_adjusted != 0 && (lb_adjusted & (GC_GRANULE_BYTES - 1)) == 0);\n  /* Currently a single object is always allocated if manual VDB. */\n  /*\n   * TODO: `GC_dirty` should be called for each linked object (but the\n   * last one) to support multiple objects allocation.\n   */\n  if (UNLIKELY(lb_adjusted > MAXOBJBYTES) || GC_manual_vdb) {\n    op = GC_generic_malloc_aligned(lb_adjusted - EXTRA_BYTES, kind,\n                                   0 /* `flags` */, 0 /* `align_m1` */);\n    if (LIKELY(op != NULL))\n      obj_link(op) = NULL;\n    *result = op;\n#ifndef NO_MANUAL_VDB\n    if (GC_manual_vdb && GC_is_heap_ptr(result)) {\n      GC_dirty_inner(result);\n      REACHABLE_AFTER_DIRTY(op);\n    }\n#endif\n    return;\n  }\n  GC_ASSERT(kind < MAXOBJKINDS);\n  lg = BYTES_TO_GRANULES(lb_adjusted);\n  if (UNLIKELY(get_have_errors()))\n    GC_print_all_errors();\n  GC_notify_or_invoke_finalizers();\n  GC_DBG_COLLECT_AT_MALLOC(lb_adjusted - EXTRA_BYTES);\n  if (UNLIKELY(!GC_is_initialized))\n    GC_init();\n  LOCK();\n  /* Do our share of marking work. */\n  if (GC_incremental && !GC_dont_gc) {\n    GC_collect_a_little_inner(1);\n  }\n\n  /* First see if we can reclaim a page of objects waiting to be reclaimed. */\n  ok = &GC_obj_kinds[kind];\n  rlh = ok->ok_reclaim_list;\n  if (rlh != NULL) {\n    struct hblk *hbp;\n    hdr *hhdr;\n\n    while ((hbp = rlh[lg]) != NULL) {\n      hhdr = HDR(hbp);\n      rlh[lg] = hhdr->hb_next;\n      GC_ASSERT(hhdr->hb_sz == lb_adjusted);\n      hhdr->hb_last_reclaimed = (unsigned short)GC_gc_no;\n#ifdef PARALLEL_MARK\n      if (GC_parallel) {\n        GC_signed_word my_bytes_allocd_tmp\n            = (GC_signed_word)AO_load(&GC_bytes_allocd_tmp);\n        GC_ASSERT(my_bytes_allocd_tmp >= 0);\n        /*\n         * We only decrement it while holding the allocator lock.\n         * Thus, we cannot accidentally adjust it down in more than\n         * one thread simultaneously.\n         */\n        if (my_bytes_allocd_tmp != 0) {\n          (void)AO_fetch_and_add(&GC_bytes_allocd_tmp,\n                                 (AO_t)(-my_bytes_allocd_tmp));\n          GC_bytes_allocd += (word)my_bytes_allocd_tmp;\n        }\n        GC_acquire_mark_lock();\n        ++GC_fl_builder_count;\n        UNLOCK();\n        GC_release_mark_lock();\n      }\n#endif\n      op = GC_reclaim_generic(hbp, hhdr, lb_adjusted, ok->ok_init, 0,\n                              &my_bytes_allocd);\n      if (op != 0) {\n#ifdef PARALLEL_MARK\n        if (GC_parallel) {\n          *result = op;\n          (void)AO_fetch_and_add(&GC_bytes_allocd_tmp, (AO_t)my_bytes_allocd);\n          GC_acquire_mark_lock();\n          --GC_fl_builder_count;\n          if (GC_fl_builder_count == 0)\n            GC_notify_all_builder();\n#  ifdef THREAD_SANITIZER\n          GC_release_mark_lock();\n          LOCK();\n          GC_bytes_found += (GC_signed_word)my_bytes_allocd;\n          UNLOCK();\n#  else\n          /* The resulting `GC_bytes_found` may be inaccurate. */\n          GC_bytes_found += (GC_signed_word)my_bytes_allocd;\n          GC_release_mark_lock();\n#  endif\n          (void)GC_clear_stack(0);\n          return;\n        }\n#endif\n        /* We also reclaimed memory, so we need to adjust that count. */\n        GC_bytes_found += (GC_signed_word)my_bytes_allocd;\n        GC_bytes_allocd += my_bytes_allocd;\n        goto out;\n      }\n#ifdef PARALLEL_MARK\n      if (GC_parallel) {\n        GC_acquire_mark_lock();\n        --GC_fl_builder_count;\n        if (GC_fl_builder_count == 0)\n          GC_notify_all_builder();\n        GC_release_mark_lock();\n        /*\n         * The allocator lock is needed for access to the reclaim list.\n         * We must decrement `GC_fl_builder_count` before reacquiring\n         * the allocator lock.  Hopefully this path is rare.\n         */\n        LOCK();\n\n        /* Reload `rlh` after locking. */\n        rlh = ok->ok_reclaim_list;\n        if (NULL == rlh)\n          break;\n      }\n#endif\n    }\n  }\n  /*\n   * Next try to use prefix of global free list if there is one.\n   * We do not refill it, but we need to use it up before allocating\n   * a new block ourselves.\n   */\n  opp = &ok->ok_freelist[lg];\n  if ((op = *opp) != NULL) {\n    *opp = NULL;\n    my_bytes_allocd = 0;\n    for (p = op; p != NULL; p = obj_link(p)) {\n      my_bytes_allocd += lb_adjusted;\n      if ((word)my_bytes_allocd >= HBLKSIZE) {\n        *opp = obj_link(p);\n        obj_link(p) = NULL;\n        break;\n      }\n    }\n    GC_bytes_allocd += my_bytes_allocd;\n    goto out;\n  }\n\n  /* Next try to allocate a new block worth of objects of this size. */\n  {\n    struct hblk *h\n        = GC_allochblk(lb_adjusted, kind, 0 /* `flags` */, 0 /* `align_m1` */);\n\n    if (h /* `!= NULL` */) { /*< CPPCHECK */\n      if (IS_UNCOLLECTABLE(kind))\n        GC_set_hdr_marks(HDR(h));\n      GC_bytes_allocd += HBLKSIZE - (HBLKSIZE % lb_adjusted);\n#ifdef PARALLEL_MARK\n      if (GC_parallel) {\n        GC_acquire_mark_lock();\n        ++GC_fl_builder_count;\n        UNLOCK();\n        GC_release_mark_lock();\n\n        op = GC_build_fl(h, NULL, lg, ok->ok_init || GC_debugging_started);\n        *result = op;\n        GC_acquire_mark_lock();\n        --GC_fl_builder_count;\n        if (GC_fl_builder_count == 0)\n          GC_notify_all_builder();\n        GC_release_mark_lock();\n        (void)GC_clear_stack(0);\n        return;\n      }\n#endif\n      op = GC_build_fl(h, NULL, lg, ok->ok_init || GC_debugging_started);\n      goto out;\n    }\n  }\n\n  /*\n   * As a last attempt, try allocating a single object.\n   * Note that this may trigger a collection or expand the heap.\n   */\n  op = GC_generic_malloc_inner(lb_adjusted - EXTRA_BYTES, kind,\n                               0 /* `flags` */);\n  if (op != NULL)\n    obj_link(op) = NULL;\n\nout:\n  *result = op;\n  UNLOCK();\n  (void)GC_clear_stack(0);\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_malloc_many(size_t lb)\n{\n  void *result;\n  size_t lg, lb_adjusted;\n\n  if (UNLIKELY(0 == lb))\n    lb = 1;\n  lg = ALLOC_REQUEST_GRANS(lb);\n  lb_adjusted = GRANULES_TO_BYTES(lg);\n  GC_generic_malloc_many(lb_adjusted, NORMAL, &result);\n  return result;\n}\n\n/*\n * TODO: The debugging variant of `GC_memalign` and friends is tricky\n * and currently missing.  The major difficulty is: `store_debug_info`\n * should return the pointer of the object with the requested alignment\n * (unlike the object header).\n */\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_memalign(size_t align, size_t lb)\n{\n  size_t align_m1 = align - 1;\n\n  /* Check the alignment argument. */\n  if (UNLIKELY(0 == align || (align & align_m1) != 0))\n    return NULL;\n\n  /* TODO: Use thread-local allocation. */\n  if (align <= GC_GRANULE_BYTES)\n    return GC_malloc(lb);\n  return GC_malloc_kind_aligned_global(lb, NORMAL, align_m1);\n}\n\nGC_API int GC_CALL\nGC_posix_memalign(void **memptr, size_t align, size_t lb)\n{\n  void *p;\n  size_t align_minus_one = align - 1; /*< to workaround a cppcheck warning */\n\n  /* Check alignment properly. */\n  if (UNLIKELY(align < sizeof(void *) || (align_minus_one & align) != 0)) {\n#ifdef MSWINCE\n    return ERROR_INVALID_PARAMETER;\n#else\n    return EINVAL;\n#endif\n  }\n\n  p = GC_memalign(align, lb);\n  if (UNLIKELY(NULL == p)) {\n#ifdef MSWINCE\n    return ERROR_NOT_ENOUGH_MEMORY;\n#else\n    return ENOMEM;\n#endif\n  }\n  *memptr = p;\n  return 0; /*< success */\n}\n\n#ifndef GC_NO_VALLOC\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_valloc(size_t lb)\n{\n  if (UNLIKELY(!GC_is_initialized))\n    GC_init();\n  GC_ASSERT(GC_real_page_size != 0);\n  return GC_memalign(GC_real_page_size, lb);\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_pvalloc(size_t lb)\n{\n  if (UNLIKELY(!GC_is_initialized))\n    GC_init();\n  GC_ASSERT(GC_real_page_size != 0);\n  lb = SIZET_SAT_ADD(lb, GC_real_page_size - 1) & ~(GC_real_page_size - 1);\n  return GC_memalign(GC_real_page_size, lb);\n}\n#endif /* !GC_NO_VALLOC */\n\nGC_API GC_ATTR_MALLOC char *GC_CALL\nGC_strdup(const char *s)\n{\n  /*\n   * Implementation of a variant of `strdup()` that uses the collector\n   * to allocate a copy of the string.\n   */\n  char *copy;\n  size_t lb;\n  if (s == NULL)\n    return NULL;\n  lb = strlen(s) + 1;\n  copy = (char *)GC_malloc_atomic(lb);\n  if (UNLIKELY(NULL == copy)) {\n#ifndef MSWINCE\n    errno = ENOMEM;\n#endif\n    return NULL;\n  }\n  BCOPY(s, copy, lb);\n  return copy;\n}\n\nGC_API GC_ATTR_MALLOC char *GC_CALL\nGC_strndup(const char *str, size_t size)\n{\n  char *copy;\n  /* Note: `str` is expected to be non-`NULL`. */\n  size_t len = strlen(str);\n  if (UNLIKELY(len > size))\n    len = size;\n  copy = (char *)GC_malloc_atomic(len + 1);\n  if (UNLIKELY(NULL == copy)) {\n#ifndef MSWINCE\n    errno = ENOMEM;\n#endif\n    return NULL;\n  }\n  if (LIKELY(len > 0))\n    BCOPY(str, copy, len);\n  copy[len] = '\\0';\n  return copy;\n}\n\n#ifdef GC_REQUIRE_WCSDUP\n#  include <wchar.h> /*< for `wcslen()` */\n\nGC_API GC_ATTR_MALLOC wchar_t *GC_CALL\nGC_wcsdup(const wchar_t *str)\n{\n  size_t lb = (wcslen(str) + 1) * sizeof(wchar_t);\n  wchar_t *copy = (wchar_t *)GC_malloc_atomic(lb);\n\n  if (UNLIKELY(NULL == copy)) {\n#  ifndef MSWINCE\n    errno = ENOMEM;\n#  endif\n    return NULL;\n  }\n  BCOPY(str, copy, lb);\n  return copy;\n}\n\n#  if !defined(wcsdup) && defined(REDIRECT_MALLOC) \\\n      && !defined(REDIRECT_MALLOC_IN_HEADER)\nwchar_t *\nwcsdup(const wchar_t *str)\n{\n  return GC_wcsdup(str);\n}\n#  endif\n#endif /* GC_REQUIRE_WCSDUP */\n\n#ifndef CPPCHECK\nGC_API void *GC_CALL\nGC_malloc_stubborn(size_t lb)\n{\n  return GC_malloc(lb);\n}\n\nGC_API void GC_CALL\nGC_change_stubborn(const void *p)\n{\n  UNUSED_ARG(p);\n}\n#endif /* !CPPCHECK */\n\nGC_API void GC_CALL\nGC_end_stubborn_change(const void *p)\n{\n  GC_dirty(p); /*< entire object */\n}\n\nGC_API void GC_CALL\nGC_ptr_store_and_dirty(void *p, const void *q)\n{\n  *(const void **)p = q;\n  GC_dirty(p);\n  REACHABLE_AFTER_DIRTY(q);\n}\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 2000 by Hewlett-Packard Company.  All rights reserved.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n/*\n * Make arguments appear live to compiler.  Put here to minimize the\n * risk of inlining.  Used to minimize junk left in registers.\n */\nGC_ATTR_NOINLINE\nvoid\nGC_noop6(word arg1, word arg2, word arg3, word arg4, word arg5, word arg6)\n{\n  UNUSED_ARG(arg1);\n  UNUSED_ARG(arg2);\n  UNUSED_ARG(arg3);\n  UNUSED_ARG(arg4);\n  UNUSED_ARG(arg5);\n  UNUSED_ARG(arg6);\n  /* Avoid `GC_noop6` calls to be optimized away. */\n#if defined(AO_HAVE_compiler_barrier) && !defined(BASE_ATOMIC_OPS_EMULATED)\n  AO_compiler_barrier(); /*< to serve as a special side-effect */\n#else\n  GC_noop1(0);\n#endif\n}\n\nGC_API void GC_CALL\nGC_noop1(GC_word x)\n{\n#if defined(AO_HAVE_store) && defined(THREAD_SANITIZER)\n  AO_store(&GC_noop_sink, (AO_t)x);\n#else\n  GC_noop_sink = x;\n#endif\n}\n\nGC_API void GC_CALL\nGC_noop1_ptr(volatile void *p)\n{\n#if CPP_PTRSZ > CPP_WORDSZ\n#  if defined(AO_HAVE_store) && defined(THREAD_SANITIZER)\n  GC_cptr_store(&GC_noop_sink_ptr, (ptr_t)CAST_AWAY_VOLATILE_PVOID(p));\n#  else\n  GC_noop_sink_ptr = (ptr_t)CAST_AWAY_VOLATILE_PVOID(p);\n#  endif\n#else\n  GC_noop1(ADDR(p));\n#endif\n}\n\n/*\n * Initialize `GC_obj_kinds` properly and standard free lists properly.\n * This must be done statically since they may be accessed before\n * `GC_init` is called.  It is done here, since we need to deal with\n * mark descriptors.  Note: `GC_obj_kinds[NORMAL].ok_descriptor` is\n * adjusted in `GC_init()` for `EXTRA_BYTES`.\n */\nGC_INNER struct obj_kind GC_obj_kinds[MAXOBJKINDS] = {\n  /* `PTRFREE` */\n  { &GC_aobjfreelist[0], 0 /*< filled in dynamically */,\n    /* `0 |` */ GC_DS_LENGTH, FALSE,\n    FALSE\n        /*, */ OK_DISCLAIM_INITZ },\n  /* `NORMAL` */\n  { &GC_objfreelist[0], 0,\n    /* `0 |` */ GC_DS_LENGTH, TRUE /*< add length to descriptor template */,\n    TRUE\n        /*, */ OK_DISCLAIM_INITZ },\n  /* `UNCOLLECTABLE` */\n  { &GC_uobjfreelist[0], 0,\n    /* `0 |` */ GC_DS_LENGTH, TRUE /*< add length to descriptor template */,\n    TRUE\n        /*, */ OK_DISCLAIM_INITZ },\n#ifdef GC_ATOMIC_UNCOLLECTABLE\n  /* `AUNCOLLECTABLE` */\n  { &GC_auobjfreelist[0], 0,\n    /* `0 |` */ GC_DS_LENGTH, FALSE,\n    FALSE\n        /*, */ OK_DISCLAIM_INITZ },\n#endif\n};\n\n#ifndef GC_NO_DEINIT\n/* Note: keep this close to `GC_obj_kinds` definition. */\nGC_INNER void\nGC_reset_obj_kinds(void)\n{\n  unsigned i;\n\n  for (i = 0; i < GC_N_KINDS_INITIAL_VALUE; i++)\n    GC_obj_kinds[i].ok_reclaim_list = NULL;\n  GC_obj_kinds[PTRFREE].ok_freelist = &GC_aobjfreelist[0];\n  GC_obj_kinds[NORMAL].ok_freelist = &GC_objfreelist[0];\n  GC_obj_kinds[UNCOLLECTABLE].ok_freelist = &GC_uobjfreelist[0];\n#  ifdef GC_ATOMIC_UNCOLLECTABLE\n  GC_obj_kinds[AUNCOLLECTABLE].ok_freelist = &GC_auobjfreelist[0];\n#  endif\n  GC_obj_kinds[NORMAL].ok_descriptor = GC_DS_LENGTH;\n  GC_n_kinds = GC_N_KINDS_INITIAL_VALUE;\n}\n#endif\n\n#ifndef INITIAL_MARK_STACK_SIZE\n/*\n * `INITIAL_MARK_STACK_SIZE * sizeof(mse)` should be a multiple of `HBLKSIZE`.\n * The incremental collector actually likes a larger size, since it wants to\n * push all marked dirty objects before marking anything new.\n * Currently we let it grow dynamically.\n */\n#  define INITIAL_MARK_STACK_SIZE (1 * HBLKSIZE)\n#endif\n\n#if !defined(GC_DISABLE_INCREMENTAL)\n/*\n * The number of dirty pages we marked from, excluding pointer-free pages,\n * etc.  Used for logging only.\n */\nSTATIC word GC_n_rescuing_pages = 0;\n#endif\n\nGC_API void GC_CALL\nGC_set_pointer_mask(GC_word value)\n{\n#ifdef DYNAMIC_POINTER_MASK\n  GC_ASSERT(value >= 0xff); /*< a simple sanity check */\n  GC_pointer_mask = value;\n#else\n  if (value\n#  ifdef POINTER_MASK\n      != (word)(POINTER_MASK)\n#  else\n      != GC_WORD_MAX\n#  endif\n  ) {\n    ABORT(\"Dynamic pointer mask/shift is unsupported\");\n  }\n#endif\n}\n\nGC_API GC_word GC_CALL\nGC_get_pointer_mask(void)\n{\n#ifdef DYNAMIC_POINTER_MASK\n  GC_word value = GC_pointer_mask;\n\n  if (0 == value) {\n    GC_ASSERT(!GC_is_initialized);\n    value = GC_WORD_MAX;\n  }\n  return value;\n#elif defined(POINTER_MASK)\n  return POINTER_MASK;\n#else\n  return GC_WORD_MAX;\n#endif\n}\n\nGC_API void GC_CALL\nGC_set_pointer_shift(unsigned value)\n{\n#ifdef DYNAMIC_POINTER_MASK\n  GC_ASSERT(value < CPP_WORDSZ);\n  GC_pointer_shift = (unsigned char)value;\n#else\n  if (value\n#  ifdef POINTER_SHIFT\n      != (unsigned)(POINTER_SHIFT)\n#  endif\n  ) {\n    ABORT(\"Dynamic pointer mask/shift is unsupported\");\n  }\n#endif\n}\n\nGC_API unsigned GC_CALL\nGC_get_pointer_shift(void)\n{\n#ifdef DYNAMIC_POINTER_MASK\n  return GC_pointer_shift;\n#elif defined(POINTER_SHIFT)\n  GC_STATIC_ASSERT((unsigned)(POINTER_SHIFT) < CPP_WORDSZ);\n  return POINTER_SHIFT;\n#else\n  return 0;\n#endif\n}\n\nGC_INNER GC_bool\nGC_collection_in_progress(void)\n{\n  return GC_mark_state != MS_NONE;\n}\n\nGC_INNER void\nGC_clear_hdr_marks(hdr *hhdr)\n{\n  size_t last_bit;\n\n#ifdef AO_HAVE_load\n  /* Atomic access is used to avoid racing with `GC_realloc`. */\n  last_bit = FINAL_MARK_BIT(AO_load((volatile AO_t *)&hhdr->hb_sz));\n#else\n  /*\n   * No race as `GC_realloc` holds the allocator lock while updating\n   * `hb_sz` field.\n   */\n  last_bit = FINAL_MARK_BIT(hhdr->hb_sz);\n#endif\n\n  BZERO(CAST_AWAY_VOLATILE_PVOID(hhdr->hb_marks), sizeof(hhdr->hb_marks));\n  set_mark_bit_from_hdr(hhdr, last_bit);\n  hhdr->hb_n_marks = 0;\n}\n\nGC_INNER void\nGC_set_hdr_marks(hdr *hhdr)\n{\n  size_t i;\n  size_t sz = hhdr->hb_sz;\n  size_t n_marks = FINAL_MARK_BIT(sz);\n\n#ifdef USE_MARK_BYTES\n  for (i = 0; i <= n_marks; i += MARK_BIT_OFFSET(sz)) {\n    hhdr->hb_marks[i] = 1;\n  }\n#else\n  /*\n   * Note that all bits are set even in case of not `MARK_BIT_PER_OBJ`,\n   * instead of setting every `n`-th bit where `n` is `MARK_BIT_OFFSET(sz)`.\n   *  This is done for a performance reason.\n   */\n  for (i = 0; i < divWORDSZ(n_marks); ++i) {\n    hhdr->hb_marks[i] = GC_WORD_MAX;\n  }\n  /* Set the remaining bits near the end (plus one bit past the end). */\n  hhdr->hb_marks[i] = ((((word)1 << modWORDSZ(n_marks)) - 1) << 1) | 1;\n#endif\n#ifdef MARK_BIT_PER_OBJ\n  hhdr->hb_n_marks = n_marks;\n#else\n  hhdr->hb_n_marks = HBLK_OBJS(sz);\n#endif\n}\n\n/* Clear all mark bits associated with block `h`. */\nstatic void GC_CALLBACK\nclear_marks_for_block(struct hblk *h, void *dummy)\n{\n  hdr *hhdr = HDR(h);\n\n  UNUSED_ARG(dummy);\n  if (IS_UNCOLLECTABLE(hhdr->hb_obj_kind)) {\n    /*\n     * Mark bit for these is cleared only once the object is deallocated\n     * explicitly.  This either frees the block, or the bit is cleared\n     * once the object is on the free list.\n     */\n    return;\n  }\n  GC_clear_hdr_marks(hhdr);\n#if defined(CPPCHECK)\n  GC_noop1_ptr(h);\n#endif\n}\n\n/* Slow but general routines for setting/clearing/getting mark bits. */\n\nGC_API void GC_CALL\nGC_set_mark_bit(const void *p)\n{\n  struct hblk *h = HBLKPTR(p);\n  hdr *hhdr = HDR(h);\n  size_t bit_no = MARK_BIT_NO((size_t)((ptr_t)p - (ptr_t)h), hhdr->hb_sz);\n\n  if (!mark_bit_from_hdr(hhdr, bit_no)) {\n    set_mark_bit_from_hdr(hhdr, bit_no);\n    INCR_MARKS(hhdr);\n  }\n}\n\nGC_API void GC_CALL\nGC_clear_mark_bit(const void *p)\n{\n  struct hblk *h = HBLKPTR(p);\n  hdr *hhdr = HDR(h);\n  size_t bit_no = MARK_BIT_NO((size_t)((ptr_t)p - (ptr_t)h), hhdr->hb_sz);\n\n  if (mark_bit_from_hdr(hhdr, bit_no)) {\n    size_t n_marks = hhdr->hb_n_marks;\n\n    GC_ASSERT(n_marks != 0);\n    clear_mark_bit_from_hdr(hhdr, bit_no);\n    n_marks--;\n#ifdef PARALLEL_MARK\n    /*\n     * Do not decrement to zero.  The counts are approximate due to\n     * concurrency issues, but we need to ensure that a count of zero\n     * implies an empty block.\n     */\n    if (n_marks != 0 || !GC_parallel)\n      hhdr->hb_n_marks = n_marks;\n#else\n    hhdr->hb_n_marks = n_marks;\n#endif\n  }\n}\n\nGC_API int GC_CALL\nGC_is_marked(const void *p)\n{\n  struct hblk *h = HBLKPTR(p);\n  hdr *hhdr = HDR(h);\n  size_t bit_no = MARK_BIT_NO((size_t)((ptr_t)p - (ptr_t)h), hhdr->hb_sz);\n\n  return (int)mark_bit_from_hdr(hhdr, bit_no); /*< 0 or 1 */\n}\n\nGC_INNER void\nGC_clear_marks(void)\n{\n  /* The initialization is needed for `GC_push_roots()`. */\n  GC_ASSERT(GC_is_initialized);\n\n  GC_apply_to_all_blocks(clear_marks_for_block, NULL);\n  GC_objects_are_marked = FALSE;\n  GC_mark_state = MS_INVALID;\n  GC_scan_ptr = NULL;\n}\n\nGC_INNER void\nGC_initiate_gc(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_is_initialized);\n#ifndef GC_DISABLE_INCREMENTAL\n  if (GC_incremental) {\n#  ifdef CHECKSUMS\n    GC_read_dirty(FALSE);\n    GC_check_dirty();\n#  else\n    GC_read_dirty(GC_mark_state == MS_INVALID);\n#  endif\n  }\n  GC_n_rescuing_pages = 0;\n#endif\n  if (GC_mark_state == MS_NONE) {\n    GC_mark_state = MS_PUSH_RESCUERS;\n  } else {\n    /* This is really a full collection, and mark bits are invalid. */\n    GC_ASSERT(GC_mark_state == MS_INVALID);\n  }\n  GC_scan_ptr = NULL;\n}\n\n#ifdef PARALLEL_MARK\n/* Initiate parallel marking. */\nSTATIC void GC_do_parallel_mark(void);\n#endif\n\n#ifdef GC_DISABLE_INCREMENTAL\n#  define GC_push_next_marked_dirty(h) GC_push_next_marked(h)\n#else\nSTATIC struct hblk *GC_push_next_marked_dirty(struct hblk *h);\n#endif /* !GC_DISABLE_INCREMENTAL */\n\nSTATIC struct hblk *GC_push_next_marked(struct hblk *h);\nSTATIC struct hblk *GC_push_next_marked_uncollectable(struct hblk *h);\n\nstatic void alloc_mark_stack(size_t);\n\nstatic void\npush_roots_and_advance(GC_bool push_all, ptr_t cold_gc_frame)\n{\n  if (GC_scan_ptr != NULL) {\n    /* Not ready to push. */\n    return;\n  }\n  GC_push_roots(push_all, cold_gc_frame);\n  GC_objects_are_marked = TRUE;\n  if (GC_mark_state != MS_INVALID)\n    GC_mark_state = MS_ROOTS_PUSHED;\n}\n\nSTATIC GC_on_mark_stack_empty_proc GC_on_mark_stack_empty = 0;\n\nGC_API void GC_CALL\nGC_set_on_mark_stack_empty(GC_on_mark_stack_empty_proc fn)\n{\n  LOCK();\n  GC_on_mark_stack_empty = fn;\n  UNLOCK();\n}\n\nGC_API GC_on_mark_stack_empty_proc GC_CALL\nGC_get_on_mark_stack_empty(void)\n{\n  GC_on_mark_stack_empty_proc fn;\n\n  READER_LOCK();\n  fn = GC_on_mark_stack_empty;\n  READER_UNLOCK();\n  return fn;\n}\n\n#ifdef WRAP_MARK_SOME\n/*\n * For Win32, this is called after we establish a structured exception\n * (or signal) handler, in case Windows unmaps one of our root segments.\n * Note that this code should never generate an incremental GC write fault.\n */\nSTATIC GC_bool\nGC_mark_some_inner(ptr_t cold_gc_frame)\n#else\nGC_INNER GC_bool\nGC_mark_some(ptr_t cold_gc_frame)\n#endif\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  switch (GC_mark_state) {\n  case MS_NONE:\n    return TRUE;\n\n  case MS_PUSH_RESCUERS:\n    if (ADDR_GE((ptr_t)GC_mark_stack_top,\n                (ptr_t)(GC_mark_stack_limit - INITIAL_MARK_STACK_SIZE / 2))) {\n      /*\n       * Go ahead and mark, even though that might cause us to see more\n       * marked dirty objects later on.  Avoid this in the future.\n       */\n      GC_mark_stack_too_small = TRUE;\n      MARK_FROM_MARK_STACK();\n    } else {\n      GC_scan_ptr = GC_push_next_marked_dirty(GC_scan_ptr);\n#ifndef GC_DISABLE_INCREMENTAL\n      if (NULL == GC_scan_ptr) {\n        GC_COND_LOG_PRINTF(\"Marked from %lu dirty pages\\n\",\n                           (unsigned long)GC_n_rescuing_pages);\n      }\n#endif\n      push_roots_and_advance(FALSE, cold_gc_frame);\n    }\n    GC_ASSERT(GC_mark_state == MS_PUSH_RESCUERS\n              || GC_mark_state == MS_ROOTS_PUSHED\n              || GC_mark_state == MS_INVALID);\n    break;\n\n  case MS_PUSH_UNCOLLECTABLE:\n    if (ADDR_GE((ptr_t)GC_mark_stack_top,\n                (ptr_t)(GC_mark_stack + GC_mark_stack_size / 4))) {\n#ifdef PARALLEL_MARK\n      /* Avoid this, since we do not parallelize the marker here. */\n      if (GC_parallel)\n        GC_mark_stack_too_small = TRUE;\n#endif\n      MARK_FROM_MARK_STACK();\n    } else {\n      GC_scan_ptr = GC_push_next_marked_uncollectable(GC_scan_ptr);\n      push_roots_and_advance(TRUE, cold_gc_frame);\n    }\n    GC_ASSERT(GC_mark_state == MS_PUSH_UNCOLLECTABLE\n              || GC_mark_state == MS_ROOTS_PUSHED\n              || GC_mark_state == MS_INVALID);\n    break;\n\n  case MS_ROOTS_PUSHED:\n#ifdef PARALLEL_MARK\n    /*\n     * Eventually, incremental marking should run asynchronously\n     * in multiple threads, without acquiring the allocator lock.\n     * For now, parallel marker is disabled if there is a chance that\n     * marking could be interrupted by a client-supplied time limit\n     * or custom stop function.\n     */\n    if (GC_parallel && !GC_parallel_mark_disabled) {\n      GC_do_parallel_mark();\n      GC_ASSERT(ADDR_LT((ptr_t)GC_mark_stack_top, GC_first_nonempty));\n      GC_mark_stack_top = GC_mark_stack - 1;\n      if (GC_mark_stack_too_small) {\n        alloc_mark_stack(2 * GC_mark_stack_size);\n      }\n      if (GC_mark_state == MS_ROOTS_PUSHED) {\n        GC_mark_state = MS_NONE;\n        return TRUE;\n      }\n      GC_ASSERT(GC_mark_state == MS_INVALID);\n      break;\n    }\n#endif\n    if (ADDR_GE((ptr_t)GC_mark_stack_top, (ptr_t)GC_mark_stack)) {\n      MARK_FROM_MARK_STACK();\n    } else {\n      GC_on_mark_stack_empty_proc on_ms_empty = GC_on_mark_stack_empty;\n\n      if (on_ms_empty != 0) {\n        GC_mark_stack_top\n            = on_ms_empty(GC_mark_stack_top, GC_mark_stack_limit);\n        /* If we pushed new items, we need to continue processing. */\n        if (ADDR_GE((ptr_t)GC_mark_stack_top, (ptr_t)GC_mark_stack))\n          break;\n      }\n      if (GC_mark_stack_too_small) {\n        alloc_mark_stack(2 * GC_mark_stack_size);\n      }\n      GC_mark_state = MS_NONE;\n      return TRUE;\n    }\n    GC_ASSERT(GC_mark_state == MS_ROOTS_PUSHED || GC_mark_state == MS_INVALID);\n    break;\n\n  case MS_INVALID:\n  case MS_PARTIALLY_INVALID:\n    if (!GC_objects_are_marked) {\n      GC_mark_state = MS_PUSH_UNCOLLECTABLE;\n      break;\n    }\n    if (ADDR_GE((ptr_t)GC_mark_stack_top, (ptr_t)GC_mark_stack)) {\n      MARK_FROM_MARK_STACK();\n      GC_ASSERT(GC_mark_state == MS_PARTIALLY_INVALID\n                || GC_mark_state == MS_INVALID);\n      break;\n    }\n    if (NULL == GC_scan_ptr && GC_mark_state == MS_INVALID) {\n      /*\n       * About to start a heap scan for marked objects.\n       * Mark stack is empty.  OK to reallocate.\n       */\n      if (GC_mark_stack_too_small) {\n        alloc_mark_stack(2 * GC_mark_stack_size);\n      }\n      GC_mark_state = MS_PARTIALLY_INVALID;\n    }\n    GC_scan_ptr = GC_push_next_marked(GC_scan_ptr);\n    if (GC_mark_state == MS_PARTIALLY_INVALID)\n      push_roots_and_advance(TRUE, cold_gc_frame);\n    GC_ASSERT(GC_mark_state == MS_ROOTS_PUSHED\n              || GC_mark_state == MS_PARTIALLY_INVALID\n              || GC_mark_state == MS_INVALID);\n    break;\n\n  default:\n    ABORT(\"GC_mark_some: bad state\");\n  }\n  return FALSE;\n}\n\n#ifdef PARALLEL_MARK\nGC_INNER GC_bool GC_parallel_mark_disabled = FALSE;\n#endif\n\n#ifdef WRAP_MARK_SOME\nGC_INNER GC_bool\nGC_mark_some(ptr_t cold_gc_frame)\n{\n  GC_bool ret_val;\n\n  if (GC_no_dls) {\n    ret_val = GC_mark_some_inner(cold_gc_frame);\n  } else {\n    /*\n     * Windows appears to asynchronously create and remove writable\n     * memory mappings, for reasons we have not yet understood.\n     * Since we look for writable regions to determine the root set, we\n     * may try to mark from an address range that disappeared since we\n     * started the collection.  Thus we have to recover from faults here.\n     * This code seems to be necessary for WinCE (at least in the case\n     * we would decide to add `MEM_PRIVATE` sections to data roots in\n     * `GC_register_dynamic_libraries`).  It is conceivable that this is\n     * the same issue as with terminating threads that we see with Linux\n     * and `USE_PROC_FOR_LIBRARIES`.\n     */\n#  ifndef NO_SEH_AVAILABLE\n    __try {\n      ret_val = GC_mark_some_inner(cold_gc_frame);\n    } __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION\n                    ? EXCEPTION_EXECUTE_HANDLER\n                    : EXCEPTION_CONTINUE_SEARCH) {\n      goto handle_ex;\n    }\n#  else\n#    if defined(USE_PROC_FOR_LIBRARIES) && !defined(DEFAULT_VDB)\n    if (GC_auto_incremental) {\n      static GC_bool is_warned = FALSE;\n\n      if (!is_warned) {\n        is_warned = TRUE;\n        WARN(\"Incremental GC incompatible with /proc roots\\n\", 0);\n      }\n      /* Unclear if this could still work... */\n    }\n#    endif\n    /*\n     * If `USE_PROC_FOR_LIBRARIES`, then we are handling the case in\n     * which `/proc` is used for root finding, and we have threads.\n     * We may find a stack for a thread that is in the process of\n     * exiting, and disappears while we are marking it.\n     * This seems extremely difficult to avoid otherwise.\n     */\n    GC_setup_temporary_fault_handler();\n    if (SETJMP(GC_jmp_buf) != 0)\n      goto handle_ex;\n    ret_val = GC_mark_some_inner(cold_gc_frame);\n    GC_reset_fault_handler();\n#  endif\n  }\n\n#  if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)\n  /*\n   * With `DllMain`-based thread tracking, a thread may have started\n   * while we were marking.  This is logically equivalent to the\n   * exception case; our results are invalid and we have to start over.\n   * This cannot be prevented since we cannot block in `DllMain()`.\n   */\n  if (GC_started_thread_while_stopped())\n    goto handle_thr_start;\n#  endif\n  return ret_val;\n\nhandle_ex:\n  /* Exception handler starts here for all cases. */\n#  if defined(NO_SEH_AVAILABLE)\n  GC_reset_fault_handler();\n#  endif\n  {\n    static word warned_gc_no;\n\n    /* Report caught `ACCESS_VIOLATION`, once per collection. */\n    if (warned_gc_no != GC_gc_no) {\n      GC_COND_LOG_PRINTF(\"Memory mapping disappeared at collection #%lu\\n\",\n                         (unsigned long)GC_gc_no + 1);\n      warned_gc_no = GC_gc_no;\n    }\n  }\n#  if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)\nhandle_thr_start:\n#  endif\n  /*\n   * We have bad roots on the mark stack - discard it.\n   * Rescan from the marked objects; redetermine the roots.\n   */\n#  ifdef REGISTER_LIBRARIES_EARLY\n  START_WORLD();\n  GC_cond_register_dynamic_libraries();\n  STOP_WORLD();\n#  endif\n  GC_invalidate_mark_state();\n  GC_scan_ptr = NULL;\n  return FALSE;\n}\n#endif /* WRAP_MARK_SOME */\n\nGC_INNER void\nGC_invalidate_mark_state(void)\n{\n  GC_mark_state = MS_INVALID;\n  GC_mark_stack_top = GC_mark_stack - 1;\n}\n\nSTATIC mse *\nGC_signal_mark_stack_overflow(mse *msp)\n{\n  GC_mark_state = MS_INVALID;\n#ifdef PARALLEL_MARK\n  /*\n   * We are using a `local_mark_stack` in parallel mode, so do\n   * not signal the global mark stack to be resized.\n   * That will be done in `GC_return_mark_stack` if required.\n   */\n  if (!GC_parallel)\n    GC_mark_stack_too_small = TRUE;\n#else\n  GC_mark_stack_too_small = TRUE;\n#endif\n  GC_COND_LOG_PRINTF(\"Mark stack overflow; current size: %lu entries\\n\",\n                     (unsigned long)GC_mark_stack_size);\n#if defined(CPPCHECK)\n  GC_noop1_ptr(msp);\n#endif\n  return msp - GC_MARK_STACK_DISCARDS;\n}\n\nGC_ATTR_NO_SANITIZE_ADDR_MEM_THREAD\nGC_INNER mse *\nGC_mark_from(mse *mark_stack_top, mse *mark_stack, mse *mark_stack_limit)\n{\n  GC_signed_word credit = HBLKSIZE; /*< remaining credit for marking work */\n  word descr;\n  ptr_t current_p;    /*< pointer to the current candidate pointer */\n  ptr_t q;            /*< the candidate pointer itself */\n  ptr_t limit = NULL; /*< the limit (incl.) of the current candidate range */\n  ptr_t greatest_ha = (ptr_t)GC_greatest_plausible_heap_addr;\n  ptr_t least_ha = (ptr_t)GC_least_plausible_heap_addr;\n  DECLARE_HDR_CACHE;\n\n#define SPLIT_RANGE_PTRS 128 /*< must be power of 2 */\n\n  GC_objects_are_marked = TRUE;\n  INIT_HDR_CACHE;\n#if defined(OS2) || CPP_PTRSZ > CPP_WORDSZ\n  /* OS/2: use untweaked variant to circumvent a compiler problem. */\n  while (ADDR_GE((ptr_t)mark_stack_top, (ptr_t)mark_stack) && credit >= 0)\n#else\n  while (((((word)mark_stack_top - (word)mark_stack) | (word)credit) & SIGNB)\n         == 0)\n#endif\n  {\n    current_p = mark_stack_top->mse_start;\n    descr = mark_stack_top->mse_descr;\n  retry:\n    /*\n     * `current_p` and `descr` describe the current object.\n     * `*mark_stack_top` is vacant.\n     * The following is zero only for small objects described by a simple\n     * length descriptor.  For many applications this is the common case,\n     * so we try to detect it quickly.\n     */\n    if (descr & (~(word)(PTRS_TO_BYTES(SPLIT_RANGE_PTRS) - 1) | GC_DS_TAGS)) {\n      word tag = descr & GC_DS_TAGS;\n\n      GC_STATIC_ASSERT(GC_DS_TAGS == 0x3);\n      switch (tag) {\n      case GC_DS_LENGTH:\n        /*\n         * Large length.  Process part of the range to avoid pushing\n         * too much on the stack.\n         */\n\n        /* Either it is a heap object or a region outside the heap. */\n        GC_ASSERT(descr < GC_greatest_real_heap_addr - GC_least_real_heap_addr\n                  || GC_least_real_heap_addr + sizeof(ptr_t)\n                         >= ADDR(current_p) + descr\n                  || ADDR(current_p) >= GC_greatest_real_heap_addr);\n#ifdef PARALLEL_MARK\n#  define SHARE_BYTES 2048\n        if (descr > SHARE_BYTES && GC_parallel\n            && ADDR_LT((ptr_t)mark_stack_top, (ptr_t)(mark_stack_limit - 1))) {\n          word new_size = (descr >> 1) & ~(word)(sizeof(ptr_t) - 1);\n\n          mark_stack_top->mse_start = current_p;\n          /* This makes sure we handle misaligned pointers. */\n          mark_stack_top->mse_descr\n              = (new_size + sizeof(ptr_t)) | GC_DS_LENGTH;\n          mark_stack_top++;\n#  ifdef ENABLE_TRACE\n          if (ADDR_INSIDE(GC_trace_ptr, current_p, current_p + descr)) {\n            GC_log_printf(\"GC #%lu: large section; start %p, len %lu,\"\n                          \" splitting (parallel) at %p\\n\",\n                          (unsigned long)GC_gc_no, (void *)current_p,\n                          (unsigned long)descr,\n                          (void *)(current_p + new_size));\n          }\n#  endif\n          current_p += new_size;\n          descr -= new_size;\n          goto retry;\n        }\n#endif /* PARALLEL_MARK */\n        limit = current_p + PTRS_TO_BYTES(SPLIT_RANGE_PTRS - 1);\n        mark_stack_top->mse_start = limit;\n        mark_stack_top->mse_descr\n            = descr - PTRS_TO_BYTES(SPLIT_RANGE_PTRS - 1);\n#ifdef ENABLE_TRACE\n        if (ADDR_INSIDE(GC_trace_ptr, current_p, current_p + descr)) {\n          GC_log_printf(\"GC #%lu: large section; start %p, len %lu,\"\n                        \" splitting at %p\\n\",\n                        (unsigned long)GC_gc_no, (void *)current_p,\n                        (unsigned long)descr, (void *)limit);\n        }\n#endif\n        /*\n         * Make sure that pointers overlapping the two ranges are\n         * considered.\n         */\n        limit += sizeof(ptr_t) - ALIGNMENT;\n        break;\n      case GC_DS_BITMAP:\n        mark_stack_top--;\n#ifdef ENABLE_TRACE\n        if (ADDR_INSIDE(GC_trace_ptr, current_p,\n                        current_p + PTRS_TO_BYTES(BITMAP_BITS))) {\n          GC_log_printf(\"GC #%lu: tracing from %p bitmap descr 0x%lx\\n\",\n                        (unsigned long)GC_gc_no, (void *)current_p,\n                        (unsigned long)descr);\n        }\n#endif\n        descr &= ~(word)GC_DS_TAGS;\n        credit -= (GC_signed_word)PTRS_TO_BYTES(CPP_PTRSZ / 2); /*< guess */\n        for (; descr != 0;\n             descr <<= 1, current_p += sizeof(ptr_t)) { /*< not `ALIGNMENT` */\n          if ((descr & SIGNB) == 0)\n            continue;\n          LOAD_PTR_OR_CONTINUE(q, current_p);\n          FIXUP_POINTER(q);\n          if (ADDR_LT(least_ha, q) && ADDR_LT(q, greatest_ha)) {\n            PREFETCH(q);\n#ifdef ENABLE_TRACE\n            if (GC_trace_ptr == current_p) {\n              GC_log_printf(\"GC #%lu: considering(3) %p -> %p\\n\",\n                            (unsigned long)GC_gc_no, (void *)current_p,\n                            (void *)q);\n            }\n#endif\n            PUSH_CONTENTS(q, mark_stack_top, mark_stack_limit, current_p);\n          }\n        }\n        continue;\n      case GC_DS_PROC:\n        mark_stack_top--;\n#ifdef ENABLE_TRACE\n        if (ADDR_GE(GC_trace_ptr, current_p)) {\n          const void *base = GC_base(current_p);\n\n          if (base != NULL && GC_base(GC_trace_ptr) == base) {\n            GC_log_printf(\"GC #%lu: tracing from %p, proc descr 0x%lx\\n\",\n                          (unsigned long)GC_gc_no, (void *)current_p,\n                          (unsigned long)descr);\n          }\n        }\n#endif\n        credit -= GC_PROC_BYTES;\n        mark_stack_top = (*PROC(descr))((word *)current_p, mark_stack_top,\n                                        mark_stack_limit, ENV(descr));\n        continue;\n      case GC_DS_PER_OBJECT:\n        if (!(descr & SIGNB)) {\n          /* Descriptor is in the object. */\n          descr = *(word *)(current_p + descr - GC_DS_PER_OBJECT);\n        } else {\n          /*\n           * Descriptor is in the type descriptor pointed to by the first\n           * \"pointer-sized\" word of the object.\n           */\n          ptr_t type_descr = *(ptr_t *)current_p;\n\n          /*\n           * `type_descr` is either a valid pointer to the descriptor\n           * structure, or this object was on a free list.\n           * If it was anything but the last object on the free list,\n           * we will misinterpret the next object on the free list as\n           * the type descriptor, and get a zero GC descriptor, which\n           * is ideal.  Unfortunately, we need to check for the last\n           * object case explicitly.\n           */\n          if (UNLIKELY(NULL == type_descr)) {\n            mark_stack_top--;\n            continue;\n          }\n          descr = *(word *)(type_descr\n                            - ((GC_signed_word)descr\n                               + (GC_INDIR_PER_OBJ_BIAS - GC_DS_PER_OBJECT)));\n        }\n        if (0 == descr) {\n          /*\n           * Can happen either because we generated a zero GC descriptor\n           * or we saw a pointer to a free object.\n           */\n          mark_stack_top--;\n          continue;\n        }\n        goto retry;\n      }\n    } else {\n      /* Small object with length descriptor. */\n      mark_stack_top--;\n#ifndef SMALL_CONFIG\n      if (descr < sizeof(ptr_t))\n        continue;\n#endif\n#ifdef ENABLE_TRACE\n      if (ADDR_INSIDE(GC_trace_ptr, current_p, current_p + descr)) {\n        GC_log_printf(\"GC #%lu: small object; start %p, len %lu\\n\",\n                      (unsigned long)GC_gc_no, (void *)current_p,\n                      (unsigned long)descr);\n      }\n#endif\n      limit = current_p + descr;\n    }\n    /* The simple case in which we are scanning a range. */\n    GC_ASSERT((ADDR(current_p) & (ALIGNMENT - 1)) == 0);\n    credit -= limit - current_p;\n    limit -= sizeof(ptr_t);\n    {\n#define PREF_DIST 4\n\n#if !defined(SMALL_CONFIG) && !(defined(E2K) && defined(USE_PTR_HWTAG))\n      ptr_t deferred;\n\n#  ifdef CHERI_PURECAP\n      /*\n       * Check each pointer for validity before dereferencing to prevent\n       * capability exceptions.  Utilize the pointer meta-data to speed-up\n       * the loop.  If the loop is below the pointer bounds, skip the rest\n       * of marking for that chunk.  If the limit capability restricts us to\n       * reading fewer than size of a pointer, then there cannot possibly be\n       * a pointer at `limit`'s pointer, and reading at that location will\n       * raise a capability exception.\n       */\n      {\n        word cap_limit = cheri_base_get(limit) + cheri_length_get(limit);\n\n        if (ADDR(limit) + sizeof(ptr_t) > cap_limit) {\n          /* Decrement limit so that it to be within bounds of `current_p`. */\n          GC_ASSERT(cap_limit > sizeof(ptr_t));\n          limit = (ptr_t)cheri_address_set(\n              current_p, (cap_limit - sizeof(ptr_t)) & ~(sizeof(ptr_t) - 1));\n          goto check_limit;\n        }\n      }\n#  endif\n      /*\n       * Try to prefetch the next pointer to be examined as soon as possible.\n       * Empirically, this also seems to help slightly without prefetches,\n       * at least on Linux/i686.  Presumably this loop ends up with less\n       * register pressure, and gcc thus ends up generating slightly better\n       * code.  Overall gcc code quality for this loop is still not great.\n       */\n      for (;;) {\n        PREFETCH(limit - PREF_DIST * CACHE_LINE_SIZE);\n        GC_ASSERT(ADDR_GE(limit, current_p));\n#  ifdef CHERI_PURECAP\n        if (ADDR(limit) < cheri_base_get(limit))\n          goto next_object;\n        if (!HAS_TAG_AND_PERM_LOAD(limit)) {\n          limit -= ALIGNMENT;\n          goto check_limit;\n        }\n#  endif\n        deferred = *(ptr_t *)limit;\n        FIXUP_POINTER(deferred);\n        limit -= ALIGNMENT;\n#  ifdef CHERI_PURECAP\n        if (!HAS_TAG_AND_PERM_LOAD(deferred))\n          goto check_limit;\n#  endif\n        if (ADDR_LT(least_ha, deferred) && ADDR_LT(deferred, greatest_ha)) {\n          PREFETCH(deferred);\n          break;\n        }\n#  ifndef CHERI_PURECAP\n        if (ADDR_LT(limit, current_p))\n          goto next_object;\n        /*\n         * Unroll once, so we do not do too many of the prefetches based\n         * on `limit`.\n         */\n        deferred = *(ptr_t *)limit;\n        FIXUP_POINTER(deferred);\n        limit -= ALIGNMENT;\n        if (ADDR_LT(least_ha, deferred) && ADDR_LT(deferred, greatest_ha)) {\n          PREFETCH(deferred);\n          break;\n        }\n#  else\n      check_limit:\n#  endif\n        if (ADDR_LT(limit, current_p))\n          goto next_object;\n      }\n#endif\n\n      for (; ADDR_GE(limit, current_p); current_p += ALIGNMENT) {\n        /*\n         * Empirically, unrolling this loop does not help a lot.\n         * Since `PUSH_CONTENTS` expands to a lot of code, we do not.\n         */\n        LOAD_PTR_OR_CONTINUE(q, current_p);\n        FIXUP_POINTER(q);\n        PREFETCH(current_p + PREF_DIST * CACHE_LINE_SIZE);\n        if (ADDR_LT(least_ha, q) && ADDR_LT(q, greatest_ha)) {\n          /*\n           * Prefetch the content of the object we just pushed.\n           * It is likely we will need them soon.\n           */\n          PREFETCH(q);\n#ifdef ENABLE_TRACE\n          if (GC_trace_ptr == current_p) {\n            GC_log_printf(\"GC #%lu: considering(1) %p -> %p\\n\",\n                          (unsigned long)GC_gc_no, (void *)current_p,\n                          (void *)q);\n          }\n#endif\n          PUSH_CONTENTS(q, mark_stack_top, mark_stack_limit, current_p);\n        }\n      }\n\n#if !defined(SMALL_CONFIG) && !(defined(E2K) && defined(USE_PTR_HWTAG))\n      /*\n       * We still need to mark the entry we previously prefetched.\n       * We already know that it passes the preliminary pointer validity test.\n       */\n#  ifdef ENABLE_TRACE\n      if (GC_trace_ptr == current_p) {\n        GC_log_printf(\"GC #%lu: considering(2) %p -> %p\\n\",\n                      (unsigned long)GC_gc_no, (void *)current_p,\n                      (void *)deferred);\n      }\n#  endif\n      PUSH_CONTENTS(deferred, mark_stack_top, mark_stack_limit, current_p);\n    next_object:;\n#endif\n    }\n  }\n  return mark_stack_top;\n}\n\n#ifdef PARALLEL_MARK\n\n/* Note: this is protected by the mark lock. */\nSTATIC GC_bool GC_help_wanted = FALSE;\n\n/* Number of running helpers.  Protected by the mark lock. */\nSTATIC unsigned GC_helper_count = 0;\n\n/*\n * Number of active helpers.  May increase and decrease within each\n * mark cycle; but once it returns to zero, it stays for the cycle.\n * Protected by the mark lock.\n */\nSTATIC unsigned GC_active_count = 0;\n\n#  ifdef LINT2\n#    define LOCAL_MARK_STACK_SIZE (HBLKSIZE / 8)\n#  else\n/*\n * Under normal circumstances, this is big enough to guarantee we do not\n * overflow half of it in a single call to `GC_mark_from`.\n */\n#    define LOCAL_MARK_STACK_SIZE HBLKSIZE\n#  endif\n\nGC_INNER void\nGC_wait_for_markers_init(void)\n{\n  GC_signed_word count;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (0 == GC_markers_m1)\n    return;\n\n#  ifndef CAN_HANDLE_FORK\n  GC_ASSERT(NULL == GC_main_local_mark_stack);\n#  else\n  if (NULL == GC_main_local_mark_stack)\n#  endif\n  {\n    size_t bytes_to_get\n        = ROUNDUP_PAGESIZE_IF_MMAP(LOCAL_MARK_STACK_SIZE * sizeof(mse));\n\n    /*\n     * Allocate the local mark stack for the thread that holds the\n     * allocator lock.\n     */\n    GC_ASSERT(GC_page_size != 0);\n    GC_main_local_mark_stack = (mse *)GC_os_get_mem(bytes_to_get);\n    if (NULL == GC_main_local_mark_stack)\n      ABORT(\"Insufficient memory for main local_mark_stack\");\n  }\n\n  /*\n   * Reuse the mark lock and builders count to synchronize marker threads\n   * startup.\n   */\n  GC_acquire_mark_lock();\n  GC_fl_builder_count += GC_markers_m1;\n  count = GC_fl_builder_count;\n  GC_release_mark_lock();\n  if (count != 0) {\n    GC_ASSERT(count > 0);\n    GC_wait_for_reclaim();\n  }\n}\n\n/*\n * Steal mark stack entries starting at `mse` `low` into mark stack `local`\n * until we either steal `mse` `high`, or we have `n_to_get` entries.\n * Return a pointer to the top of the local mark stack.  `*next` is replaced\n * by a pointer to the next unscanned mark stack entry.\n */\nSTATIC mse *\nGC_steal_mark_stack(mse *low, mse *high, mse *local, size_t n_to_get,\n                    mse **next)\n{\n  mse *p;\n  mse *top = local - 1;\n  size_t i = 0;\n\n  GC_ASSERT(ADDR_GE((ptr_t)high, (ptr_t)(low - 1))\n            && (word)(high - low + 1) <= GC_mark_stack_size);\n  for (p = low; ADDR_GE((ptr_t)high, (ptr_t)p) && i <= n_to_get; ++p) {\n    word descr = AO_load(&p->mse_descr);\n\n    if (descr != 0) {\n      /* Must be ordered after read of `mse_descr`. */\n      AO_store_release_write(&p->mse_descr, 0);\n      /*\n       * More than one thread may get this entry, but that is only\n       * a minor performance problem.\n       */\n      ++top;\n      top->mse_start = p->mse_start;\n      top->mse_descr = descr;\n      GC_ASSERT((descr & GC_DS_TAGS) != GC_DS_LENGTH /* 0 */\n                || descr < GC_greatest_real_heap_addr - GC_least_real_heap_addr\n                || GC_least_real_heap_addr + sizeof(ptr_t)\n                       >= ADDR(p->mse_start) + descr\n                || ADDR(p->mse_start) >= GC_greatest_real_heap_addr);\n      /* If this is a big object, count it as `descr / 256 + 1` objects. */\n      ++i;\n      if ((descr & GC_DS_TAGS) == GC_DS_LENGTH)\n        i += (size_t)(descr >> 8);\n    }\n  }\n  *next = p;\n#  if defined(CPPCHECK)\n  GC_noop1_ptr(local);\n#  endif\n  return top;\n}\n\n/* Copy back a local mark stack.  `low` and `high` are inclusive bounds. */\nSTATIC void\nGC_return_mark_stack(mse *low, mse *high)\n{\n  mse *my_top;\n  mse *my_start;\n  size_t stack_size;\n\n  if (ADDR_LT((ptr_t)high, (ptr_t)low))\n    return;\n  stack_size = high - low + 1;\n  GC_acquire_mark_lock();\n  /* Note: the concurrent modification is impossible. */\n  my_top = GC_mark_stack_top;\n  my_start = my_top + 1;\n  if ((word)(my_start - GC_mark_stack + stack_size)\n      > (word)GC_mark_stack_size) {\n    GC_COND_LOG_PRINTF(\"No room to copy back mark stack\\n\");\n    GC_mark_state = MS_INVALID;\n    GC_mark_stack_too_small = TRUE;\n    /* We drop the local mark stack.  We will fix things later. */\n  } else {\n    BCOPY(low, my_start, stack_size * sizeof(mse));\n    GC_ASSERT((mse *)GC_cptr_load((volatile ptr_t *)&GC_mark_stack_top)\n              == my_top);\n    /* Ensures visibility of previously written stack contents. */\n    GC_cptr_store_release_write((volatile ptr_t *)&GC_mark_stack_top,\n                                (ptr_t)(my_top + stack_size));\n  }\n  GC_release_mark_lock();\n  GC_notify_all_marker();\n}\n\n#  ifndef N_LOCAL_ITERS\n#    define N_LOCAL_ITERS 1\n#  endif\n\n/*\n * Note: called only when the local and the main mark stacks are both\n * empty.\n */\nstatic GC_bool\nhas_inactive_helpers(void)\n{\n  GC_bool res;\n\n  GC_acquire_mark_lock();\n  res = GC_active_count < GC_helper_count;\n  GC_release_mark_lock();\n  return res;\n}\n\n/*\n * Mark from the local mark stack.  On return, the local mark stack\n * is empty.  But this may be achieved by copying the local mark stack\n * back into the global one.  We do not hold the mark lock.\n */\nSTATIC void\nGC_do_local_mark(mse *local_mark_stack, mse *local_top)\n{\n  unsigned n;\n\n  for (;;) {\n    for (n = 0; n < N_LOCAL_ITERS; ++n) {\n      local_top = GC_mark_from(local_top, local_mark_stack,\n                               local_mark_stack + LOCAL_MARK_STACK_SIZE);\n      if (ADDR_LT((ptr_t)local_top, (ptr_t)local_mark_stack))\n        return;\n      if ((word)(local_top - local_mark_stack) >= LOCAL_MARK_STACK_SIZE / 2) {\n        GC_return_mark_stack(local_mark_stack, local_top);\n        return;\n      }\n    }\n    if (ADDR_LT(GC_cptr_load((volatile ptr_t *)&GC_mark_stack_top),\n                GC_cptr_load(&GC_first_nonempty))\n        && ADDR_LT((ptr_t)(local_mark_stack + 1), (ptr_t)local_top)\n        && has_inactive_helpers()) {\n      /*\n       * Try to share the load, since the main stack is empty, and the helper\n       * threads are waiting for a refill.  The entries near the bottom of\n       * the stack are likely to require more work.  Thus we return those,\n       * even though it is harder.\n       */\n      mse *new_bottom = local_mark_stack + (local_top - local_mark_stack) / 2;\n\n      GC_ASSERT(ADDR_LT((ptr_t)local_mark_stack, (ptr_t)new_bottom)\n                && ADDR_LT((ptr_t)new_bottom, (ptr_t)local_top));\n      GC_return_mark_stack(local_mark_stack, new_bottom - 1);\n      memmove(local_mark_stack, new_bottom,\n              (local_top - new_bottom + 1) * sizeof(mse));\n      local_top -= new_bottom - local_mark_stack;\n    }\n  }\n}\n\n#  ifndef ENTRIES_TO_GET\n#    define ENTRIES_TO_GET 5\n#  endif\n\n/*\n * Mark using the local mark stack until the global mark stack is empty and\n * there are no active workers.  Update `GC_first_nonempty` to reflect the\n * progress.  Caller holds the mark lock.  Caller has already incremented\n * `GC_helper_count`; we decrement it, and maintain `GC_active_count`.\n */\nSTATIC void\nGC_mark_local(mse *local_mark_stack, int id)\n{\n  mse *my_first_nonempty;\n\n  GC_active_count++;\n  my_first_nonempty = (mse *)GC_cptr_load(&GC_first_nonempty);\n  GC_ASSERT(ADDR_GE((ptr_t)my_first_nonempty, (ptr_t)GC_mark_stack));\n  GC_ASSERT(\n      ADDR_GE(GC_cptr_load((volatile ptr_t *)&GC_mark_stack_top) + sizeof(mse),\n              (ptr_t)my_first_nonempty));\n  GC_VERBOSE_LOG_PRINTF(\"Starting mark helper %d\\n\", id);\n  GC_release_mark_lock();\n  for (;;) {\n    size_t n_on_stack, n_to_get;\n    mse *my_top, *local_top;\n    mse *global_first_nonempty = (mse *)GC_cptr_load(&GC_first_nonempty);\n\n    GC_ASSERT(ADDR_GE((ptr_t)my_first_nonempty, (ptr_t)GC_mark_stack)\n              && ADDR_GE(GC_cptr_load((volatile ptr_t *)&GC_mark_stack_top)\n                             + sizeof(mse),\n                         (ptr_t)my_first_nonempty));\n    GC_ASSERT(ADDR_GE((ptr_t)global_first_nonempty, (ptr_t)GC_mark_stack));\n    if (ADDR_LT((ptr_t)my_first_nonempty, (ptr_t)global_first_nonempty)) {\n      my_first_nonempty = global_first_nonempty;\n    } else if (ADDR_LT((ptr_t)global_first_nonempty,\n                       (ptr_t)my_first_nonempty)) {\n      (void)GC_cptr_compare_and_swap(&GC_first_nonempty,\n                                     (ptr_t)global_first_nonempty,\n                                     (ptr_t)my_first_nonempty);\n      /*\n       * If this fails, then we just go ahead, without updating\n       * `GC_first_nonempty`.\n       */\n    }\n    /*\n     * Perhaps we should also update `GC_first_nonempty`, if it is less.\n     * But that would require usage of the atomic updates.\n     */\n    my_top = (mse *)GC_cptr_load_acquire((volatile ptr_t *)&GC_mark_stack_top);\n    if (ADDR_LT((ptr_t)my_top, (ptr_t)my_first_nonempty)) {\n      GC_acquire_mark_lock();\n      /*\n       * Note: asynchronous modification is impossible here, since\n       * we hold the mark lock.\n       */\n      my_top = GC_mark_stack_top;\n      n_on_stack = my_top - my_first_nonempty + 1;\n      if (0 == n_on_stack) {\n        GC_active_count--;\n        GC_ASSERT(GC_active_count <= GC_helper_count);\n        /* Other markers may redeposit objects on the stack. */\n        if (0 == GC_active_count)\n          GC_notify_all_marker();\n        while (GC_active_count > 0\n               && ADDR_LT((ptr_t)GC_mark_stack_top,\n                          GC_cptr_load(&GC_first_nonempty))) {\n          /*\n           * We will be notified if either `GC_active_count` reaches zero,\n           * or if more objects are pushed on the global mark stack.\n           */\n          GC_wait_marker();\n        }\n        if (0 == GC_active_count\n            && ADDR_LT((ptr_t)GC_mark_stack_top,\n                       GC_cptr_load(&GC_first_nonempty))) {\n          GC_bool need_to_notify = FALSE;\n\n          /*\n           * The above conditions cannot be falsified while we hold\n           * the mark lock, since neither `GC_active_count` nor\n           * `GC_mark_stack_top` can change.  `GC_first_nonempty` can\n           * only be incremented asynchronously.  Thus we know that\n           * both conditions are actually held simultaneously.\n           */\n          GC_helper_count--;\n          if (0 == GC_helper_count)\n            need_to_notify = TRUE;\n          GC_VERBOSE_LOG_PRINTF(\"Finished mark helper %d\\n\", id);\n          if (need_to_notify)\n            GC_notify_all_marker();\n          return;\n        }\n        /*\n         * Else there is something on the stack again, or another helper\n         * may push something.\n         */\n        GC_active_count++;\n        GC_ASSERT(GC_active_count > 0);\n        GC_release_mark_lock();\n        continue;\n      } else {\n        GC_release_mark_lock();\n      }\n    } else {\n      n_on_stack = my_top - my_first_nonempty + 1;\n    }\n    n_to_get = ENTRIES_TO_GET;\n    if (n_on_stack < 2 * ENTRIES_TO_GET)\n      n_to_get = 1;\n    local_top\n        = GC_steal_mark_stack(my_first_nonempty, my_top, local_mark_stack,\n                              n_to_get, &my_first_nonempty);\n    GC_ASSERT(ADDR_GE((ptr_t)my_first_nonempty, (ptr_t)GC_mark_stack)\n              && ADDR_GE(GC_cptr_load((volatile ptr_t *)&GC_mark_stack_top)\n                             + sizeof(mse),\n                         (ptr_t)my_first_nonempty));\n    GC_do_local_mark(local_mark_stack, local_top);\n  }\n}\n\n/*\n * Perform parallel mark.  We hold the allocator lock, but not the mark lock.\n * Currently runs until the mark stack is empty.\n */\nSTATIC void\nGC_do_parallel_mark(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_acquire_mark_lock();\n  GC_ASSERT(!GC_help_wanted);\n  GC_ASSERT(0 == GC_active_count && 0 == GC_helper_count);\n  GC_VERBOSE_LOG_PRINTF(\"Starting marking for mark phase number %lu\\n\",\n                        (unsigned long)GC_mark_no);\n\n  GC_cptr_store(&GC_first_nonempty, (ptr_t)GC_mark_stack);\n  GC_active_count = 0;\n  GC_helper_count = 1;\n  GC_help_wanted = TRUE;\n  /* Wake up potential helpers. */\n  GC_notify_all_marker();\n  GC_mark_local(GC_main_local_mark_stack, 0);\n  GC_help_wanted = FALSE;\n  /* Done; clean up. */\n  while (GC_helper_count > 0) {\n    GC_wait_marker();\n  }\n  /* `GC_helper_count` cannot be incremented while not `GC_help_wanted`. */\n  GC_VERBOSE_LOG_PRINTF(\"Finished marking for mark phase number %lu\\n\",\n                        (unsigned long)GC_mark_no);\n  GC_mark_no++;\n  GC_release_mark_lock();\n  GC_notify_all_marker();\n}\n\nGC_INNER void\nGC_help_marker(word my_mark_no)\n{\n#  define my_id my_id_mse.mse_descr\n  /*\n   * Put `my_id` inside the structure to keep `local_mark_stack` aligned\n   * explicitly.\n   */\n  mse my_id_mse;\n  mse local_mark_stack[LOCAL_MARK_STACK_SIZE];\n  /* Note: `local_mark_stack` is quite big (up to 128 KiB). */\n\n  GC_ASSERT(I_DONT_HOLD_LOCK());\n  GC_ASSERT(GC_parallel);\n  while (GC_mark_no < my_mark_no\n         || (!GC_help_wanted && GC_mark_no == my_mark_no)) {\n    GC_wait_marker();\n  }\n  my_id = GC_helper_count;\n  if (GC_mark_no != my_mark_no || my_id > (unsigned)GC_markers_m1) {\n    /*\n     * The second test is useful only if the original threads can also\n     * act as helpers.  Under Linux they cannot.\n     */\n    return;\n  }\n  GC_helper_count = (unsigned)my_id + 1;\n  GC_mark_local(local_mark_stack, (int)my_id);\n  /* `GC_mark_local` decrements `GC_helper_count`. */\n#  undef my_id\n}\n\n#endif /* PARALLEL_MARK */\n\n/*\n * Allocate or reallocate space for mark stack of size `n` entries.\n * May silently fail.\n */\nstatic void\nalloc_mark_stack(size_t n)\n{\n#ifdef GWW_VDB\n  static GC_bool GC_incremental_at_stack_alloc = FALSE;\n\n  GC_bool recycle_old;\n#endif\n  mse *new_stack;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  new_stack = (mse *)GC_scratch_alloc(n * sizeof(struct GC_ms_entry));\n#ifdef GWW_VDB\n  /*\n   * Do not recycle a stack segment obtained with the wrong flags.\n   * Win32 `GetWriteWatch` requires the right kind of memory.\n   */\n  recycle_old = !GC_auto_incremental || GC_incremental_at_stack_alloc;\n  GC_incremental_at_stack_alloc = GC_auto_incremental;\n#endif\n\n  GC_mark_stack_too_small = FALSE;\n  if (GC_mark_stack != NULL) {\n    if (new_stack != 0) {\n#ifdef GWW_VDB\n      if (recycle_old)\n#endif\n      {\n        /* Recycle old space. */\n        GC_scratch_recycle_inner(\n            GC_mark_stack, GC_mark_stack_size * sizeof(struct GC_ms_entry));\n      }\n      GC_mark_stack = new_stack;\n      GC_mark_stack_size = n;\n      /* FIXME: Do we need some way to reset `GC_mark_stack_size`? */\n      GC_mark_stack_limit = new_stack + n;\n      GC_COND_LOG_PRINTF(\"Grew mark stack to %lu frames\\n\",\n                         (unsigned long)GC_mark_stack_size);\n    } else {\n      WARN(\"Failed to grow mark stack to %\" WARN_PRIuPTR \" frames\\n\", n);\n    }\n  } else if (NULL == new_stack) {\n    GC_err_printf(\"No space for mark stack\\n\");\n    EXIT();\n  } else {\n    GC_mark_stack = new_stack;\n    GC_mark_stack_size = n;\n    GC_mark_stack_limit = new_stack + n;\n  }\n  GC_mark_stack_top = GC_mark_stack - 1;\n}\n\nGC_INNER void\nGC_mark_init(void)\n{\n  alloc_mark_stack(INITIAL_MARK_STACK_SIZE);\n}\n\nGC_API void GC_CALL\nGC_push_all(void *bottom, void *top)\n{\n  mse *mark_stack_top;\n  word length;\n\n  bottom = PTR_ALIGN_UP((ptr_t)bottom, ALIGNMENT);\n  top = PTR_ALIGN_DOWN((ptr_t)top, ALIGNMENT);\n  if (ADDR_GE((ptr_t)bottom, (ptr_t)top))\n    return;\n\n  mark_stack_top = GC_mark_stack_top + 1;\n  if (ADDR_GE((ptr_t)mark_stack_top, (ptr_t)GC_mark_stack_limit)) {\n    ABORT(\"Unexpected mark stack overflow\");\n  }\n  length = (word)((ptr_t)top - (ptr_t)bottom);\n#if GC_DS_TAGS > ALIGNMENT - 1\n  length = (length + GC_DS_TAGS) & ~(word)GC_DS_TAGS; /*< round up */\n#endif\n  mark_stack_top->mse_start = (ptr_t)bottom;\n  mark_stack_top->mse_descr = length | GC_DS_LENGTH;\n  GC_mark_stack_top = mark_stack_top;\n}\n\nGC_API struct GC_ms_entry *GC_CALL\nGC_custom_push_range(void *bottom, void *top,\n                     struct GC_ms_entry *mark_stack_top,\n                     struct GC_ms_entry *mark_stack_limit)\n{\n  word length;\n\n  bottom = PTR_ALIGN_UP((ptr_t)bottom, ALIGNMENT);\n  top = PTR_ALIGN_DOWN((ptr_t)top, ALIGNMENT);\n  if (ADDR_GE((ptr_t)bottom, (ptr_t)top))\n    return mark_stack_top;\n\n  length = (word)((ptr_t)top - (ptr_t)bottom);\n#if GC_DS_TAGS > ALIGNMENT - 1\n  length = (length + GC_DS_TAGS) & ~(word)GC_DS_TAGS; /*< round up */\n#endif\n  return GC_custom_push_proc(length | GC_DS_LENGTH, bottom, mark_stack_top,\n                             mark_stack_limit);\n}\n\nGC_API struct GC_ms_entry *GC_CALL\nGC_custom_push_proc(GC_word descr, void *obj,\n                    struct GC_ms_entry *mark_stack_top,\n                    struct GC_ms_entry *mark_stack_limit)\n{\n  mark_stack_top++;\n  if (ADDR_GE((ptr_t)mark_stack_top, (ptr_t)mark_stack_limit)) {\n    mark_stack_top = GC_signal_mark_stack_overflow(mark_stack_top);\n  }\n  mark_stack_top->mse_start = (ptr_t)obj;\n  mark_stack_top->mse_descr = descr;\n  return mark_stack_top;\n}\n\nGC_API void GC_CALL\nGC_push_proc(GC_word descr, void *obj)\n{\n  GC_mark_stack_top = GC_custom_push_proc(descr, obj, GC_mark_stack_top,\n                                          GC_mark_stack_limit);\n}\n\n#ifndef GC_DISABLE_INCREMENTAL\n\n/*\n * Analogous to `GC_push_all`, but push only those pages `h` with\n * `dirty_fn(h) != 0`.  We use `GC_push_all` to actually push the block.\n * Used both to selectively push dirty pages, or to push a block in\n * a piecemeal fashion, to allow for more marking concurrency.\n * Will not overflow mark stack if `GC_push_all` pushes a small fixed\n * number of entries.  (This is invoked only if `GC_push_all` pushes\n * a single entry, or if it marks each object before pushing it, thus\n * ensuring progress in the event of a stack overflow.)\n */\nSTATIC void\nGC_push_selected(ptr_t bottom, ptr_t top, GC_bool (*dirty_fn)(struct hblk *))\n{\n  struct hblk *h;\n\n  bottom = PTR_ALIGN_UP(bottom, ALIGNMENT);\n  top = PTR_ALIGN_DOWN(top, ALIGNMENT);\n  if (ADDR_GE(bottom, top))\n    return;\n\n  h = HBLKPTR(bottom + HBLKSIZE);\n  if (ADDR_GE((ptr_t)h, top)) {\n    if ((*dirty_fn)(h - 1)) {\n      GC_push_all(bottom, top);\n    }\n    return;\n  }\n  if ((*dirty_fn)(h - 1)) {\n    if ((word)(GC_mark_stack_top - GC_mark_stack)\n        > 3 * GC_mark_stack_size / 4) {\n      GC_push_all(bottom, top);\n      return;\n    }\n    GC_push_all(bottom, h);\n  }\n\n  while (ADDR_GE(top, (ptr_t)(h + 1))) {\n    if ((*dirty_fn)(h)) {\n      if ((word)(GC_mark_stack_top - GC_mark_stack)\n          > 3 * GC_mark_stack_size / 4) {\n        /* Danger of mark stack overflow. */\n        GC_push_all(h, top);\n        return;\n      } else {\n        GC_push_all(h, h + 1);\n      }\n    }\n    h++;\n  }\n\n  if ((ptr_t)h != top && (*dirty_fn)(h)) {\n    GC_push_all(h, top);\n  }\n}\n\nGC_API void GC_CALL\nGC_push_conditional(void *bottom, void *top, int all)\n{\n  if (!all) {\n    GC_push_selected((ptr_t)bottom, (ptr_t)top, GC_page_was_dirty);\n  } else {\n#  ifdef PROC_VDB\n    if (GC_auto_incremental) {\n      /* Pages that were never dirtied cannot contain pointers. */\n      GC_push_selected((ptr_t)bottom, (ptr_t)top, GC_page_was_ever_dirty);\n    } else\n#  endif\n    /* else */ {\n      GC_push_all(bottom, top);\n    }\n  }\n}\n\n#  ifndef NO_VDB_FOR_STATIC_ROOTS\n#    ifndef PROC_VDB\n/*\n * Same as `GC_page_was_dirty` but `h` is allowed to point to some page\n * in the registered static roots only.  Not used if the manual VDB is on.\n */\nSTATIC GC_bool\nGC_static_page_was_dirty(struct hblk *h)\n{\n  return get_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h));\n}\n#    endif\n\nGC_INNER void\nGC_push_conditional_static(void *bottom, void *top, GC_bool all)\n{\n#    ifdef PROC_VDB\n  /*\n   * Just redirect to the generic routine because `PROC_VDB`\n   * implementation gets the dirty bits map for the whole process memory.\n   */\n  GC_push_conditional(bottom, top, all);\n#    else\n  if (all || !GC_is_vdb_for_static_roots()) {\n    GC_push_all(bottom, top);\n  } else {\n    GC_push_selected((ptr_t)bottom, (ptr_t)top, GC_static_page_was_dirty);\n  }\n#    endif\n}\n#  endif /* !NO_VDB_FOR_STATIC_ROOTS */\n\n#else\nGC_API void GC_CALL\nGC_push_conditional(void *bottom, void *top, int all)\n{\n  UNUSED_ARG(all);\n  GC_push_all(bottom, top);\n}\n#endif /* GC_DISABLE_INCREMENTAL */\n\n#if defined(DARWIN) && defined(THREADS)\nvoid\nGC_push_one(word p)\n{\n  GC_PUSH_ONE_STACK((ptr_t)p, MARKED_FROM_REGISTER);\n}\n#endif /* DARWIN && THREADS */\n\n#if defined(GC_WIN32_THREADS)\nGC_INNER void\nGC_push_many_regs(const word *regs, unsigned count)\n{\n  unsigned i;\n\n  for (i = 0; i < count; i++)\n    GC_PUSH_ONE_STACK((ptr_t)regs[i], MARKED_FROM_REGISTER);\n}\n#endif /* GC_WIN32_THREADS */\n\nGC_API struct GC_ms_entry *GC_CALL\nGC_mark_and_push(void *obj, mse *mark_stack_top, mse *mark_stack_limit,\n                 void **src)\n{\n  hdr *hhdr;\n\n  PREFETCH(obj);\n  GET_HDR(obj, hhdr);\n  if ((UNLIKELY(IS_FORWARDING_ADDR_OR_NIL(hhdr))\n       && (!GC_all_interior_pointers\n           || NULL == (hhdr = GC_find_header(GC_base(obj)))))\n      || UNLIKELY(HBLK_IS_FREE(hhdr))) {\n    GC_ADD_TO_BLACK_LIST_NORMAL((ptr_t)obj, (ptr_t)src);\n    return mark_stack_top;\n  }\n  return GC_push_contents_hdr((ptr_t)obj, mark_stack_top, mark_stack_limit,\n                              (ptr_t)src, hhdr, TRUE);\n}\n\nGC_ATTR_NO_SANITIZE_ADDR\nGC_INNER void\n#if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS)\nGC_mark_and_push_stack(ptr_t p, ptr_t source)\n#else\nGC_mark_and_push_stack(ptr_t p)\n#  define source ((ptr_t)0)\n#endif\n{\n  hdr *hhdr;\n  ptr_t r = p;\n\n  PREFETCH(p);\n  GET_HDR(p, hhdr);\n  if (UNLIKELY(IS_FORWARDING_ADDR_OR_NIL(hhdr))) {\n    if (NULL == hhdr || (r = (ptr_t)GC_base(p)) == NULL\n        || (hhdr = HDR(r)) == NULL) {\n      GC_ADD_TO_BLACK_LIST_STACK(p, source);\n      return;\n    }\n  }\n  if (UNLIKELY(HBLK_IS_FREE(hhdr))) {\n    GC_ADD_TO_BLACK_LIST_NORMAL(p, source);\n    return;\n  }\n#ifdef THREADS\n  /*\n   * Pointer is on the stack.  We may have dirtied the object it points to,\n   * but have not called `GC_dirty` yet.\n   */\n  GC_dirty(p); /*< entire object */\n#endif\n  GC_mark_stack_top = GC_push_contents_hdr(\n      r, GC_mark_stack_top, GC_mark_stack_limit, source, hhdr, FALSE);\n  /*\n   * We silently ignore pointers to near the end of a block, which is\n   * very mildly suboptimal.\n   */\n  /* FIXME: We should probably add a header word to address this. */\n#undef source\n}\n\n#ifdef TRACE_BUF\n#  ifndef TRACE_ENTRIES\n#    define TRACE_ENTRIES 1000\n#  endif\n\nstruct trace_entry {\n  const char *caller_fn_name;\n  word gc_no;\n  word bytes_allocd;\n  GC_hidden_pointer arg1;\n  GC_hidden_pointer arg2;\n} GC_trace_buf[TRACE_ENTRIES] = { { (const char *)NULL, 0, 0, 0, 0 } };\n\nvoid\nGC_add_trace_entry(const char *caller_fn_name, ptr_t arg1, ptr_t arg2)\n{\n  size_t i = GC_trace_buf_pos;\n\n  GC_trace_buf[i].caller_fn_name = caller_fn_name;\n  GC_trace_buf[i].gc_no = GC_gc_no;\n  GC_trace_buf[i].bytes_allocd = GC_bytes_allocd;\n  GC_trace_buf[i].arg1 = GC_HIDE_POINTER(arg1);\n  GC_trace_buf[i].arg2 = GC_HIDE_POINTER(arg2);\n  i++;\n  if (i >= TRACE_ENTRIES)\n    i = 0;\n  GC_trace_buf_pos = i;\n}\n\nGC_API void GC_CALL\nGC_print_trace_inner(GC_word gc_no)\n{\n  size_t i;\n\n  for (i = GC_trace_buf_pos;; i--) {\n    struct trace_entry *p;\n\n    if (0 == i)\n      i = TRACE_ENTRIES;\n    p = &GC_trace_buf[i - 1];\n    /*\n     * Compare `gc_no` values (`p->gc_no` is less than given `gc_no`)\n     * taking into account that the counter may overflow.\n     */\n    if (((p->gc_no - gc_no) & SIGNB) != 0 || NULL == p->caller_fn_name) {\n      return;\n    }\n    GC_printf(\"Trace:%s (gc:%lu, bytes:%lu) %p, %p\\n\", p->caller_fn_name,\n              (unsigned long)p->gc_no, (unsigned long)p->bytes_allocd,\n              GC_REVEAL_POINTER(p->arg1), GC_REVEAL_POINTER(p->arg2));\n    if (i == GC_trace_buf_pos + 1)\n      break;\n  }\n  GC_printf(\"Trace incomplete\\n\");\n}\n\nGC_API void GC_CALL\nGC_print_trace(GC_word gc_no)\n{\n  READER_LOCK();\n  GC_print_trace_inner(gc_no);\n  READER_UNLOCK();\n}\n#endif /* TRACE_BUF */\n\nGC_ATTR_NO_SANITIZE_ADDR_MEM_THREAD\nGC_API void GC_CALL\nGC_push_all_eager(void *bottom, void *top)\n{\n  REGISTER ptr_t current_p;\n  REGISTER word lim_addr;\n  REGISTER ptr_t greatest_ha = (ptr_t)GC_greatest_plausible_heap_addr;\n  REGISTER ptr_t least_ha = (ptr_t)GC_least_plausible_heap_addr;\n#define GC_greatest_plausible_heap_addr greatest_ha\n#define GC_least_plausible_heap_addr least_ha\n\n  if (NULL == top)\n    return;\n  /* Check all pointers in range and push if they appear to be valid. */\n  current_p = PTR_ALIGN_UP((ptr_t)bottom, ALIGNMENT);\n  lim_addr = ADDR(PTR_ALIGN_DOWN((ptr_t)top, ALIGNMENT)) - sizeof(ptr_t);\n#ifdef CHERI_PURECAP\n  {\n    word cap_limit = cheri_base_get(current_p) + cheri_length_get(current_p);\n\n    if (lim_addr >= cap_limit)\n      lim_addr = cap_limit - sizeof(ptr_t);\n  }\n#endif\n  for (; ADDR(current_p) <= lim_addr; current_p += ALIGNMENT) {\n    REGISTER ptr_t q;\n\n    LOAD_PTR_OR_CONTINUE(q, current_p);\n    GC_PUSH_ONE_STACK(q, current_p);\n  }\n#undef GC_greatest_plausible_heap_addr\n#undef GC_least_plausible_heap_addr\n}\n\nGC_INNER void\nGC_push_all_stack(ptr_t bottom, ptr_t top)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n#ifndef NEED_FIXUP_POINTER\n  if (GC_all_interior_pointers\n#  if defined(THREADS) && defined(MPROTECT_VDB)\n      && !GC_auto_incremental\n#  endif\n      && ADDR_LT((ptr_t)GC_mark_stack_top,\n                 (ptr_t)(GC_mark_stack_limit - INITIAL_MARK_STACK_SIZE / 8))) {\n    GC_push_all(bottom, top);\n  } else\n#endif\n  /* else */ {\n    GC_push_all_eager(bottom, top);\n  }\n}\n\n#if defined(WRAP_MARK_SOME) && defined(PARALLEL_MARK)\nGC_ATTR_NO_SANITIZE_ADDR_MEM_THREAD\nGC_INNER void\nGC_push_conditional_eager(void *bottom, void *top, GC_bool all)\n{\n  REGISTER ptr_t current_p;\n  REGISTER ptr_t lim;\n  REGISTER ptr_t greatest_ha = (ptr_t)GC_greatest_plausible_heap_addr;\n  REGISTER ptr_t least_ha = (ptr_t)GC_least_plausible_heap_addr;\n#  define GC_greatest_plausible_heap_addr greatest_ha\n#  define GC_least_plausible_heap_addr least_ha\n\n  if (NULL == top)\n    return;\n\n  /* TODO: If not `all`, then scan only dirty pages. */\n  (void)all;\n\n  current_p = PTR_ALIGN_UP((ptr_t)bottom, ALIGNMENT);\n  lim = PTR_ALIGN_DOWN((ptr_t)top, ALIGNMENT) - sizeof(ptr_t);\n  for (; ADDR_GE(lim, current_p); current_p += ALIGNMENT) {\n    REGISTER ptr_t q;\n\n    LOAD_PTR_OR_CONTINUE(q, current_p);\n    GC_PUSH_ONE_HEAP(q, current_p, GC_mark_stack_top);\n  }\n#  undef GC_greatest_plausible_heap_addr\n#  undef GC_least_plausible_heap_addr\n}\n#endif /* WRAP_MARK_SOME && PARALLEL_MARK */\n\n#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES) \\\n    && !defined(MARK_BIT_PER_OBJ) && GC_GRANULE_PTRS <= 4\n#  define USE_PUSH_MARKED_ACCELERATORS\n#  if GC_GRANULE_PTRS == 1\n#    define PUSH_GRANULE(q)                                \\\n      do {                                                 \\\n        ptr_t qcontents = (q)[0];                          \\\n        GC_PUSH_ONE_HEAP(qcontents, q, GC_mark_stack_top); \\\n      } while (0)\n#  elif GC_GRANULE_PTRS == 2\n#    define PUSH_GRANULE(q)                                      \\\n      do {                                                       \\\n        ptr_t qcontents = (q)[0];                                \\\n        GC_PUSH_ONE_HEAP(qcontents, q, GC_mark_stack_top);       \\\n        qcontents = (q)[1];                                      \\\n        GC_PUSH_ONE_HEAP(qcontents, (q) + 1, GC_mark_stack_top); \\\n      } while (0)\n#  else\n#    define PUSH_GRANULE(q)                                      \\\n      do {                                                       \\\n        ptr_t qcontents = (q)[0];                                \\\n        GC_PUSH_ONE_HEAP(qcontents, q, GC_mark_stack_top);       \\\n        qcontents = (q)[1];                                      \\\n        GC_PUSH_ONE_HEAP(qcontents, (q) + 1, GC_mark_stack_top); \\\n        qcontents = (q)[2];                                      \\\n        GC_PUSH_ONE_HEAP(qcontents, (q) + 2, GC_mark_stack_top); \\\n        qcontents = (q)[3];                                      \\\n        GC_PUSH_ONE_HEAP(qcontents, (q) + 3, GC_mark_stack_top); \\\n      } while (0)\n#  endif\n\n/*\n * Push all objects reachable from marked objects in the given block\n * containing objects of size 1 granule.\n */\nGC_ATTR_NO_SANITIZE_THREAD\nSTATIC void\nGC_push_marked1(struct hblk *h, const hdr *hhdr)\n{\n  const word *mark_word_addr\n      = (word *)CAST_AWAY_VOLATILE_PVOID(hhdr->hb_marks);\n  ptr_t *p;\n  ptr_t plim;\n\n  /*\n   * Allow registers to be used for some frequently accessed global variables.\n   * Otherwise aliasing issues are likely to prevent that.\n   */\n  ptr_t greatest_ha = (ptr_t)GC_greatest_plausible_heap_addr;\n  ptr_t least_ha = (ptr_t)GC_least_plausible_heap_addr;\n  mse *mark_stack_top = GC_mark_stack_top;\n  mse *mark_stack_limit = GC_mark_stack_limit;\n\n#  undef GC_mark_stack_top\n#  undef GC_mark_stack_limit\n#  define GC_mark_stack_top mark_stack_top\n#  define GC_mark_stack_limit mark_stack_limit\n#  define GC_greatest_plausible_heap_addr greatest_ha\n#  define GC_least_plausible_heap_addr least_ha\n\n  p = (ptr_t *)h->hb_body;\n  plim = (ptr_t)h + HBLKSIZE;\n\n  /* Go through all granules in block. */\n  while (ADDR_LT((ptr_t)p, plim)) {\n    word mark_word = *mark_word_addr++;\n    ptr_t *q;\n\n    for (q = p; mark_word != 0; mark_word >>= 1) {\n      if ((mark_word & 1) != 0)\n        PUSH_GRANULE(q);\n      q += GC_GRANULE_PTRS;\n    }\n    p += CPP_WORDSZ * GC_GRANULE_PTRS;\n  }\n\n#  undef GC_greatest_plausible_heap_addr\n#  undef GC_least_plausible_heap_addr\n#  undef GC_mark_stack_top\n#  undef GC_mark_stack_limit\n#  define GC_mark_stack_limit GC_arrays._mark_stack_limit\n#  define GC_mark_stack_top GC_arrays._mark_stack_top\n  GC_mark_stack_top = mark_stack_top;\n}\n\n#  ifndef UNALIGNED_PTRS\n/*\n * Push all objects reachable from marked objects in the given block\n * of two-granule objects.\n */\nGC_ATTR_NO_SANITIZE_THREAD\nSTATIC void\nGC_push_marked2(struct hblk *h, const hdr *hhdr)\n{\n  const word *mark_word_addr\n      = (word *)CAST_AWAY_VOLATILE_PVOID(hhdr->hb_marks);\n  ptr_t *p;\n  ptr_t plim;\n  ptr_t greatest_ha = (ptr_t)GC_greatest_plausible_heap_addr;\n  ptr_t least_ha = (ptr_t)GC_least_plausible_heap_addr;\n  mse *mark_stack_top = GC_mark_stack_top;\n  mse *mark_stack_limit = GC_mark_stack_limit;\n\n#    undef GC_mark_stack_top\n#    undef GC_mark_stack_limit\n#    define GC_mark_stack_top mark_stack_top\n#    define GC_mark_stack_limit mark_stack_limit\n#    define GC_greatest_plausible_heap_addr greatest_ha\n#    define GC_least_plausible_heap_addr least_ha\n\n  p = (ptr_t *)h->hb_body;\n  plim = (ptr_t)h + HBLKSIZE;\n\n  /* Go through all granules in block. */\n  while (ADDR_LT((ptr_t)p, plim)) {\n    word mark_word = *mark_word_addr++;\n    ptr_t *q;\n\n    for (q = p; mark_word != 0; mark_word >>= 2) {\n      if (mark_word & 1) {\n        PUSH_GRANULE(q);\n        PUSH_GRANULE(q + GC_GRANULE_PTRS);\n      }\n      q += 2 * GC_GRANULE_PTRS;\n    }\n    p += CPP_WORDSZ * GC_GRANULE_PTRS;\n  }\n\n#    undef GC_greatest_plausible_heap_addr\n#    undef GC_least_plausible_heap_addr\n#    undef GC_mark_stack_top\n#    undef GC_mark_stack_limit\n#    define GC_mark_stack_limit GC_arrays._mark_stack_limit\n#    define GC_mark_stack_top GC_arrays._mark_stack_top\n  GC_mark_stack_top = mark_stack_top;\n}\n\n#    if GC_GRANULE_PTRS < 4\n/*\n * Push all objects reachable from marked objects in the given block of\n * four-granule objects.  There is a risk of mark stack overflow here.\n * But we handle that.  And only unmarked objects get pushed, so it is\n * not very likely.\n */\nGC_ATTR_NO_SANITIZE_THREAD\nSTATIC void\nGC_push_marked4(struct hblk *h, const hdr *hhdr)\n{\n  const word *mark_word_addr\n      = (word *)CAST_AWAY_VOLATILE_PVOID(hhdr->hb_marks);\n  ptr_t *p;\n  ptr_t plim;\n  ptr_t greatest_ha = (ptr_t)GC_greatest_plausible_heap_addr;\n  ptr_t least_ha = (ptr_t)GC_least_plausible_heap_addr;\n  mse *mark_stack_top = GC_mark_stack_top;\n  mse *mark_stack_limit = GC_mark_stack_limit;\n\n#      undef GC_mark_stack_top\n#      undef GC_mark_stack_limit\n#      define GC_mark_stack_top mark_stack_top\n#      define GC_mark_stack_limit mark_stack_limit\n#      define GC_greatest_plausible_heap_addr greatest_ha\n#      define GC_least_plausible_heap_addr least_ha\n\n  p = (ptr_t *)h->hb_body;\n  plim = (ptr_t)h + HBLKSIZE;\n\n  /* Go through all granules in block. */\n  while (ADDR_LT((ptr_t)p, plim)) {\n    word mark_word = *mark_word_addr++;\n    ptr_t *q;\n\n    for (q = p; mark_word != 0; mark_word >>= 4) {\n      if (mark_word & 1) {\n        PUSH_GRANULE(q);\n        PUSH_GRANULE(q + GC_GRANULE_PTRS);\n        PUSH_GRANULE(q + 2 * GC_GRANULE_PTRS);\n        PUSH_GRANULE(q + 3 * GC_GRANULE_PTRS);\n      }\n      q += 4 * GC_GRANULE_PTRS;\n    }\n    p += CPP_WORDSZ * GC_GRANULE_PTRS;\n  }\n#      undef GC_greatest_plausible_heap_addr\n#      undef GC_least_plausible_heap_addr\n#      undef GC_mark_stack_top\n#      undef GC_mark_stack_limit\n#      define GC_mark_stack_limit GC_arrays._mark_stack_limit\n#      define GC_mark_stack_top GC_arrays._mark_stack_top\n  GC_mark_stack_top = mark_stack_top;\n}\n#    endif\n#  endif\n#endif /* !USE_MARK_BYTES && !MARK_BIT_PER_OBJ && !SMALL_CONFIG */\n\n/* Push all objects reachable from marked objects in the given block. */\nSTATIC void\nGC_push_marked(struct hblk *h, const hdr *hhdr)\n{\n  size_t sz = hhdr->hb_sz;\n  ptr_t p;\n  size_t bit_no;\n  ptr_t plim;\n  mse *mark_stack_top;\n  mse *mark_stack_limit = GC_mark_stack_limit;\n\n  /* Some quick shortcuts: */\n  if ((/* `0 |` */ GC_DS_LENGTH) == hhdr->hb_descr)\n    return;\n  if (GC_block_empty(hhdr))\n    return; /*< nothing marked */\n\n#if !defined(GC_DISABLE_INCREMENTAL)\n  GC_n_rescuing_pages++;\n#endif\n  GC_objects_are_marked = TRUE;\n  switch (BYTES_TO_GRANULES(sz)) {\n#ifdef USE_PUSH_MARKED_ACCELERATORS\n  case 1:\n    GC_push_marked1(h, hhdr);\n    break;\n#  ifndef UNALIGNED_PTRS\n  case 2:\n    GC_push_marked2(h, hhdr);\n    break;\n#    if GC_GRANULE_PTRS < 4\n  case 4:\n    GC_push_marked4(h, hhdr);\n    break;\n#    endif\n#  endif /* !UNALIGNED_PTRS */\n#else\n  case 1: /*< to suppress \"switch statement contains no case\" warning */\n#endif\n  default:\n    plim = sz > MAXOBJBYTES ? h->hb_body\n                            : CAST_THRU_UINTPTR(ptr_t, (h + 1)->hb_body) - sz;\n    mark_stack_top = GC_mark_stack_top;\n    for (p = h->hb_body, bit_no = 0; ADDR_GE(plim, p);\n         p += sz, bit_no += MARK_BIT_OFFSET(sz)) {\n      /* Mark from fields inside the object. */\n      if (mark_bit_from_hdr(hhdr, bit_no)) {\n        mark_stack_top\n            = GC_push_obj(p, hhdr, mark_stack_top, mark_stack_limit);\n      }\n    }\n    GC_mark_stack_top = mark_stack_top;\n  }\n}\n\n#ifdef ENABLE_DISCLAIM\n/*\n * Unconditionally mark from all objects that have not been reclaimed.\n * This is useful in order to retain pointers reachable from the disclaim\n * notifiers.  To determine whether an object has been reclaimed, we\n * require that any live object has a nonzero as one of the two least\n * significant bits of the first \"pointer-sized\" word.  On the other hand,\n * the reclaimed object is a member of free lists, and thus contains\n * a pointer-aligned next-pointer as the first \"pointer-sized\" word.\n */\nGC_ATTR_NO_SANITIZE_THREAD\nSTATIC void\nGC_push_unconditionally(struct hblk *h, const hdr *hhdr)\n{\n  size_t sz = hhdr->hb_sz;\n  ptr_t p;\n  ptr_t plim;\n  mse *mark_stack_top;\n  mse *mark_stack_limit = GC_mark_stack_limit;\n\n  if ((/* `0 |` */ GC_DS_LENGTH) == hhdr->hb_descr)\n    return;\n\n#  if !defined(GC_DISABLE_INCREMENTAL)\n  GC_n_rescuing_pages++;\n#  endif\n  GC_objects_are_marked = TRUE;\n  plim = sz > MAXOBJBYTES ? h->hb_body\n                          : CAST_THRU_UINTPTR(ptr_t, (h + 1)->hb_body) - sz;\n  mark_stack_top = GC_mark_stack_top;\n  for (p = h->hb_body; ADDR_GE(plim, p); p += sz) {\n    if ((ADDR(*(ptr_t *)p) & 0x3) != 0) {\n      mark_stack_top = GC_push_obj(p, hhdr, mark_stack_top, mark_stack_limit);\n    }\n  }\n  GC_mark_stack_top = mark_stack_top;\n}\n#endif /* ENABLE_DISCLAIM */\n\n#ifndef GC_DISABLE_INCREMENTAL\n/* Test whether any page in the given block is dirty. */\nSTATIC GC_bool\nGC_block_was_dirty(struct hblk *h, const hdr *hhdr)\n{\n  size_t sz;\n  ptr_t p;\n\n#  ifdef AO_HAVE_load\n  /* Atomic access is used to avoid racing with `GC_realloc`. */\n  sz = AO_load((volatile AO_t *)&hhdr->hb_sz);\n#  else\n  sz = hhdr->hb_sz;\n#  endif\n  if (sz <= MAXOBJBYTES) {\n    return GC_page_was_dirty(h);\n  }\n\n  for (p = (ptr_t)h; ADDR_LT(p, (ptr_t)h + sz); p += HBLKSIZE) {\n    if (GC_page_was_dirty((struct hblk *)p))\n      return TRUE;\n  }\n  return FALSE;\n}\n#endif /* GC_DISABLE_INCREMENTAL */\n\n/*\n * Similar to `GC_push_marked`, but skip over unallocated blocks and\n * return address of next plausible block.\n */\nSTATIC struct hblk *\nGC_push_next_marked(struct hblk *h)\n{\n  hdr *hhdr = HDR(h);\n\n  if (UNLIKELY(IS_FORWARDING_ADDR_OR_NIL(hhdr) || HBLK_IS_FREE(hhdr))) {\n    h = GC_next_block(h, FALSE);\n    if (NULL == h)\n      return NULL;\n    hhdr = GC_find_header(h);\n  } else {\n#ifdef LINT2\n    if (NULL == h)\n      ABORT(\"Bad HDR() definition\");\n#endif\n  }\n  GC_push_marked(h, hhdr);\n  return h + OBJ_SZ_TO_BLOCKS(hhdr->hb_sz);\n}\n\n#ifndef GC_DISABLE_INCREMENTAL\n/* Identical to `GC_push_next_marked`, but mark only from dirty pages. */\nSTATIC struct hblk *\nGC_push_next_marked_dirty(struct hblk *h)\n{\n  hdr *hhdr;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (!GC_incremental)\n    ABORT(\"Dirty bits not set up\");\n  for (;; h += OBJ_SZ_TO_BLOCKS(hhdr->hb_sz)) {\n    hhdr = HDR(h);\n    if (UNLIKELY(IS_FORWARDING_ADDR_OR_NIL(hhdr) || HBLK_IS_FREE(hhdr))) {\n      h = GC_next_block(h, FALSE);\n      if (NULL == h)\n        return NULL;\n      hhdr = GC_find_header(h);\n    } else {\n#  ifdef LINT2\n      if (NULL == h)\n        ABORT(\"Bad HDR() definition\");\n#  endif\n    }\n    if (GC_block_was_dirty(h, hhdr))\n      break;\n  }\n#  ifdef ENABLE_DISCLAIM\n  if ((hhdr->hb_flags & MARK_UNCONDITIONALLY) != 0) {\n    GC_push_unconditionally(h, hhdr);\n\n    /*\n     * Then we may ask, why not also add the `MARK_UNCONDITIONALLY`\n     * case to `GC_push_next_marked`, which is also applied to\n     * uncollectible blocks?  But it seems to me that the function\n     * does not need to scan uncollectible (and unconditionally\n     * marked) blocks since those are already handled in the\n     * `MS_PUSH_UNCOLLECTABLE` phase.\n     */\n  } else\n#  endif\n  /* else */ {\n    GC_push_marked(h, hhdr);\n  }\n  return h + OBJ_SZ_TO_BLOCKS(hhdr->hb_sz);\n}\n#endif /* !GC_DISABLE_INCREMENTAL */\n\n/*\n * Similar to `GC_push_next_marked`, but for uncollectible pages.\n * Needed since we do not clear marks for such pages, even for full\n * collections.\n */\nSTATIC struct hblk *\nGC_push_next_marked_uncollectable(struct hblk *h)\n{\n  hdr *hhdr = HDR(h);\n\n  for (;;) {\n    if (UNLIKELY(IS_FORWARDING_ADDR_OR_NIL(hhdr) || HBLK_IS_FREE(hhdr))) {\n      h = GC_next_block(h, FALSE);\n      if (NULL == h)\n        return NULL;\n      hhdr = GC_find_header(h);\n    } else {\n#ifdef LINT2\n      if (NULL == h)\n        ABORT(\"Bad HDR() definition\");\n#endif\n    }\n    if (hhdr->hb_obj_kind == UNCOLLECTABLE) {\n      GC_push_marked(h, hhdr);\n      break;\n    }\n#ifdef ENABLE_DISCLAIM\n    if ((hhdr->hb_flags & MARK_UNCONDITIONALLY) != 0) {\n      GC_push_unconditionally(h, hhdr);\n      break;\n    }\n#endif\n    h += OBJ_SZ_TO_BLOCKS(hhdr->hb_sz);\n    hhdr = HDR(h);\n  }\n  return h + OBJ_SZ_TO_BLOCKS(hhdr->hb_sz);\n}\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 2009-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#if defined(E2K) && !defined(THREADS)\n#  include <alloca.h>\n#endif\n\n/*\n * Data structure for list of root sets.\n * We keep a hash table, so that we can filter out duplicate additions.\n * Under Win32, we need to do a better job of filtering overlaps, so\n * we resort to sequential search, and pay the price.\n */\n\n/* Register dynamic library data segments. */\nint GC_no_dls = 0;\n\n#if !defined(NO_DEBUGGING) || defined(GC_ASSERTIONS)\nGC_INNER word\nGC_compute_root_size(void)\n{\n  size_t i;\n  word size = 0;\n\n  for (i = 0; i < n_root_sets; i++) {\n    size += (word)(GC_static_roots[i].r_end - GC_static_roots[i].r_start);\n  }\n  return size;\n}\n#endif /* !NO_DEBUGGING || GC_ASSERTIONS */\n\n#if !defined(NO_DEBUGGING)\n/* For the debugging purpose. */\nvoid\nGC_print_static_roots(void)\n{\n  size_t i;\n  word size;\n\n  for (i = 0; i < n_root_sets; i++) {\n    GC_printf(\"From %p to %p%s\\n\", (void *)GC_static_roots[i].r_start,\n              (void *)GC_static_roots[i].r_end,\n              GC_static_roots[i].r_tmp ? \" (temporary)\" : \"\");\n  }\n  GC_printf(\"GC_root_size= %lu\\n\", (unsigned long)GC_root_size);\n\n  if ((size = GC_compute_root_size()) != GC_root_size)\n    GC_err_printf(\"GC_root_size incorrect!! Should be: %lu\\n\",\n                  (unsigned long)size);\n}\n#endif /* !NO_DEBUGGING */\n\n#ifndef ANY_MSWIN\nGC_INLINE size_t\nrt_hash(ptr_t addr)\n{\n  word val = ADDR(addr);\n\n#  if CPP_WORDSZ > 4 * LOG_RT_SIZE\n#    if CPP_WORDSZ > 8 * LOG_RT_SIZE\n  val ^= val >> (8 * LOG_RT_SIZE);\n#    endif\n  val ^= val >> (4 * LOG_RT_SIZE);\n#  endif\n  val ^= val >> (2 * LOG_RT_SIZE);\n  return (size_t)((val >> LOG_RT_SIZE) ^ val) & (RT_SIZE - 1);\n}\n\nGC_INNER void *\nGC_roots_present(ptr_t b)\n{\n  size_t h;\n  struct roots *p;\n\n  GC_ASSERT(I_HOLD_READER_LOCK());\n  h = rt_hash(b);\n  for (p = GC_root_index[h]; p != NULL; p = p->r_next) {\n    if (p->r_start == (ptr_t)b)\n      break;\n  }\n  return p;\n}\n\n/* Add the given root structure to the index. */\nGC_INLINE void\nadd_roots_to_index(struct roots *p)\n{\n  size_t h = rt_hash(p->r_start);\n\n  p->r_next = GC_root_index[h];\n  GC_root_index[h] = p;\n}\n#endif /* !ANY_MSWIN */\n\nGC_API void GC_CALL\nGC_add_roots(void *b, void *e)\n{\n  if (UNLIKELY(!GC_is_initialized))\n    GC_init();\n  LOCK();\n  GC_add_roots_inner((ptr_t)b, (ptr_t)e, FALSE);\n  UNLOCK();\n}\n\nGC_INNER void\nGC_add_roots_inner(ptr_t b, ptr_t e, GC_bool tmp)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(ADDR_GE(e, b));\n  b = PTR_ALIGN_UP(b, ALIGNMENT);\n  e = PTR_ALIGN_DOWN(e, ALIGNMENT);\n  if (ADDR_GE(b, e)) {\n    /* Nothing to do. */\n    return;\n  }\n\n#ifdef ANY_MSWIN\n  /*\n   * Spend the time to ensure that there are no overlapping or adjacent\n   * intervals.  This could be done faster with e.g. a balanced tree.\n   * But the execution time here is virtually guaranteed to be dominated\n   * by the time it takes to scan the roots.\n   */\n  {\n    size_t i;\n    struct roots *old = NULL; /*< initialized to prevent warning */\n\n    for (i = 0; i < n_root_sets; i++) {\n      old = GC_static_roots + i;\n      if (ADDR_GE(old->r_end, b) && ADDR_GE(e, old->r_start)) {\n        if (ADDR_LT(b, old->r_start)) {\n          GC_root_size += (word)(old->r_start - b);\n          old->r_start = b;\n        }\n        if (ADDR_LT(old->r_end, e)) {\n          GC_root_size += (word)(e - old->r_end);\n          old->r_end = e;\n        }\n        old->r_tmp &= tmp;\n        break;\n      }\n    }\n    if (i < n_root_sets) {\n      /* Merge other overlapping intervals. */\n      struct roots *other;\n\n      for (i++; i < n_root_sets; i++) {\n        other = GC_static_roots + i;\n        b = other->r_start;\n        e = other->r_end;\n        if (ADDR_GE(old->r_end, b) && ADDR_GE(e, old->r_start)) {\n          if (ADDR_LT(b, old->r_start)) {\n            GC_root_size += (word)(old->r_start - b);\n            old->r_start = b;\n          }\n          if (ADDR_LT(old->r_end, e)) {\n            GC_root_size += (word)(e - old->r_end);\n            old->r_end = e;\n          }\n          old->r_tmp &= other->r_tmp;\n          /* Delete this entry. */\n          GC_root_size -= (word)(other->r_end - other->r_start);\n          other->r_start = GC_static_roots[n_root_sets - 1].r_start;\n          other->r_end = GC_static_roots[n_root_sets - 1].r_end;\n          n_root_sets--;\n        }\n      }\n      return;\n    }\n  }\n#else\n  {\n    struct roots *old = (struct roots *)GC_roots_present(b);\n\n    if (old != NULL) {\n      if (ADDR_GE(old->r_end, e)) {\n        old->r_tmp &= tmp;\n        /* Already there. */\n        return;\n      }\n      if (old->r_tmp == tmp || !tmp) {\n        /* Extend the existing root. */\n        GC_root_size += (word)(e - old->r_end);\n        old->r_end = e;\n        old->r_tmp = tmp;\n        return;\n      }\n      b = old->r_end;\n    }\n  }\n#endif\n  if (n_root_sets == MAX_ROOT_SETS) {\n    ABORT(\"Too many root sets\");\n  }\n\n#ifdef DEBUG_ADD_DEL_ROOTS\n  GC_log_printf(\"Adding data root section %u: %p .. %p%s\\n\",\n                (unsigned)n_root_sets, (void *)b, (void *)e,\n                tmp ? \" (temporary)\" : \"\");\n#endif\n  GC_static_roots[n_root_sets].r_start = (ptr_t)b;\n  GC_static_roots[n_root_sets].r_end = (ptr_t)e;\n  GC_static_roots[n_root_sets].r_tmp = tmp;\n#ifndef ANY_MSWIN\n  GC_static_roots[n_root_sets].r_next = 0;\n  add_roots_to_index(GC_static_roots + n_root_sets);\n#endif\n  GC_root_size += (word)(e - b);\n  n_root_sets++;\n}\n\nGC_API void GC_CALL\nGC_clear_roots(void)\n{\n  if (UNLIKELY(!GC_is_initialized))\n    GC_init();\n  LOCK();\n#ifdef THREADS\n  GC_roots_were_cleared = TRUE;\n#endif\n  n_root_sets = 0;\n  GC_root_size = 0;\n#ifndef ANY_MSWIN\n  BZERO(GC_root_index, sizeof(GC_root_index));\n#endif\n#ifdef DEBUG_ADD_DEL_ROOTS\n  GC_log_printf(\"Clear all data root sections\\n\");\n#endif\n  UNLOCK();\n}\n\nSTATIC void\nGC_remove_root_at_pos(size_t i)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(i < n_root_sets);\n#ifdef DEBUG_ADD_DEL_ROOTS\n  GC_log_printf(\"Remove data root section at %u: %p .. %p%s\\n\", (unsigned)i,\n                (void *)GC_static_roots[i].r_start,\n                (void *)GC_static_roots[i].r_end,\n                GC_static_roots[i].r_tmp ? \" (temporary)\" : \"\");\n#endif\n  GC_root_size\n      -= (word)(GC_static_roots[i].r_end - GC_static_roots[i].r_start);\n  GC_static_roots[i].r_start = GC_static_roots[n_root_sets - 1].r_start;\n  GC_static_roots[i].r_end = GC_static_roots[n_root_sets - 1].r_end;\n  GC_static_roots[i].r_tmp = GC_static_roots[n_root_sets - 1].r_tmp;\n  n_root_sets--;\n}\n\n#ifndef ANY_MSWIN\nSTATIC void\nGC_rebuild_root_index(void)\n{\n  size_t i;\n\n  BZERO(GC_root_index, sizeof(GC_root_index));\n  for (i = 0; i < n_root_sets; i++)\n    add_roots_to_index(GC_static_roots + i);\n}\n#endif /* !ANY_MSWIN */\n\n#if defined(ANY_MSWIN) || defined(DYNAMIC_LOADING)\nSTATIC void\nGC_remove_tmp_roots(void)\n{\n  size_t i;\n#  ifndef ANY_MSWIN\n  size_t old_n_roots = n_root_sets;\n#  endif\n\n  GC_ASSERT(I_HOLD_LOCK());\n  for (i = 0; i < n_root_sets;) {\n    if (GC_static_roots[i].r_tmp) {\n      GC_remove_root_at_pos(i);\n    } else {\n      i++;\n    }\n  }\n#  ifndef ANY_MSWIN\n  if (n_root_sets < old_n_roots)\n    GC_rebuild_root_index();\n#  endif\n}\n#endif /* ANY_MSWIN || DYNAMIC_LOADING */\n\nSTATIC void GC_remove_roots_inner(ptr_t b, ptr_t e);\n\nGC_API void GC_CALL\nGC_remove_roots(void *b, void *e)\n{\n  /* A quick check whether has nothing to do. */\n  if (ADDR_GE(PTR_ALIGN_UP((ptr_t)b, ALIGNMENT),\n              PTR_ALIGN_DOWN((ptr_t)e, ALIGNMENT)))\n    return;\n\n  LOCK();\n  GC_remove_roots_inner((ptr_t)b, (ptr_t)e);\n  UNLOCK();\n}\n\nSTATIC void\nGC_remove_roots_inner(ptr_t b, ptr_t e)\n{\n  size_t i;\n#ifndef ANY_MSWIN\n  size_t old_n_roots = n_root_sets;\n#endif\n\n  GC_ASSERT(I_HOLD_LOCK());\n  for (i = 0; i < n_root_sets;) {\n    if (ADDR_GE(GC_static_roots[i].r_start, b)\n        && ADDR_GE(e, GC_static_roots[i].r_end)) {\n      GC_remove_root_at_pos(i);\n    } else {\n      i++;\n    }\n  }\n#ifndef ANY_MSWIN\n  if (n_root_sets < old_n_roots)\n    GC_rebuild_root_index();\n#endif\n}\n\n#ifdef USE_PROC_FOR_LIBRARIES\n/*\n * Exchange the elements of the roots table.  Requires rebuild of the roots\n * index table after the swap.\n */\nGC_INLINE void\nswap_static_roots(size_t i, size_t j)\n{\n  ptr_t r_start = GC_static_roots[i].r_start;\n  ptr_t r_end = GC_static_roots[i].r_end;\n  GC_bool r_tmp = GC_static_roots[i].r_tmp;\n\n  GC_static_roots[i].r_start = GC_static_roots[j].r_start;\n  GC_static_roots[i].r_end = GC_static_roots[j].r_end;\n  GC_static_roots[i].r_tmp = GC_static_roots[j].r_tmp;\n  /* No need to swap `r_next` values. */\n  GC_static_roots[j].r_start = r_start;\n  GC_static_roots[j].r_end = r_end;\n  GC_static_roots[j].r_tmp = r_tmp;\n}\n\nGC_INNER void\nGC_remove_roots_subregion(ptr_t b, ptr_t e)\n{\n  size_t i;\n  GC_bool rebuild = FALSE;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(ADDR(b) % ALIGNMENT == 0 && ADDR(e) % ALIGNMENT == 0);\n  for (i = 0; i < n_root_sets; i++) {\n    ptr_t r_start, r_end;\n\n    if (GC_static_roots[i].r_tmp) {\n      /* The remaining roots are skipped as they are all temporary. */\n#  ifdef GC_ASSERTIONS\n      size_t j;\n\n      for (j = i + 1; j < n_root_sets; j++) {\n        GC_ASSERT(GC_static_roots[j].r_tmp);\n      }\n#  endif\n      break;\n    }\n    r_start = GC_static_roots[i].r_start;\n    r_end = GC_static_roots[i].r_end;\n    if (ADDR_GE(r_start, e) || LIKELY(ADDR_GE(b, r_end)))\n      continue;\n\n#  ifdef DEBUG_ADD_DEL_ROOTS\n    GC_log_printf(\"Removing %p .. %p from root section %u (%p .. %p)\\n\",\n                  (void *)b, (void *)e, (unsigned)i, (void *)r_start,\n                  (void *)r_end);\n#  endif\n    if (ADDR_LT(r_start, b)) {\n      GC_root_size -= (word)(r_end - b);\n      GC_static_roots[i].r_end = b;\n      /* No need to rebuild as hash does not use `r_end` value. */\n      if (ADDR_LT(e, r_end)) {\n        size_t j;\n\n        if (rebuild) {\n          GC_rebuild_root_index();\n          rebuild = FALSE;\n        }\n        /* Note: updates `n_root_sets` as well. */\n        GC_add_roots_inner(e, r_end, FALSE);\n        for (j = i + 1; j < n_root_sets; j++)\n          if (GC_static_roots[j].r_tmp)\n            break;\n        if (j < n_root_sets - 1 && !GC_static_roots[n_root_sets - 1].r_tmp) {\n          /* Exchange the roots to have all temporary ones at the end. */\n          swap_static_roots(j, n_root_sets - 1);\n          rebuild = TRUE;\n        }\n      }\n    } else {\n      if (ADDR_LT(e, r_end)) {\n        GC_root_size -= (word)(e - r_start);\n        GC_static_roots[i].r_start = e;\n      } else {\n        GC_remove_root_at_pos(i);\n        if (i + 1 < n_root_sets && GC_static_roots[i].r_tmp\n            && !GC_static_roots[i + 1].r_tmp) {\n          size_t j;\n\n          for (j = i + 2; j < n_root_sets; j++)\n            if (GC_static_roots[j].r_tmp)\n              break;\n          /* Exchange the roots to have all temporary ones at the end. */\n          swap_static_roots(i, j - 1);\n        }\n        i--;\n      }\n      rebuild = TRUE;\n    }\n  }\n  if (rebuild)\n    GC_rebuild_root_index();\n}\n#endif /* USE_PROC_FOR_LIBRARIES */\n\n#if !defined(NO_DEBUGGING)\nGC_API int GC_CALL\nGC_is_tmp_root(void *p)\n{\n#  ifndef HAS_REAL_READER_LOCK\n  static size_t last_root_set; /*< initialized to 0; no shared access */\n#  elif defined(AO_HAVE_load) || defined(AO_HAVE_store)\n  static volatile AO_t last_root_set;\n#  else\n  /* Note: a race is acceptable, it is just a cached index. */\n  static volatile size_t last_root_set;\n#  endif\n  size_t i;\n  int res;\n\n  READER_LOCK();\n  /* First try the cached root. */\n#  if defined(AO_HAVE_load) && defined(HAS_REAL_READER_LOCK)\n  i = AO_load(&last_root_set);\n#  else\n  i = last_root_set;\n#  endif\n  if (i < n_root_sets\n      && ADDR_INSIDE((ptr_t)p, GC_static_roots[i].r_start,\n                     GC_static_roots[i].r_end)) {\n    res = (int)GC_static_roots[i].r_tmp;\n  } else {\n    res = 0;\n    for (i = 0; i < n_root_sets; i++) {\n      if (ADDR_INSIDE((ptr_t)p, GC_static_roots[i].r_start,\n                      GC_static_roots[i].r_end)) {\n        res = (int)GC_static_roots[i].r_tmp;\n#  if defined(AO_HAVE_store) && defined(HAS_REAL_READER_LOCK)\n        AO_store(&last_root_set, i);\n#  else\n        last_root_set = i;\n#  endif\n        break;\n      }\n    }\n  }\n  READER_UNLOCK();\n  return res;\n}\n#endif /* !NO_DEBUGGING */\n\nGC_INNER ptr_t\nGC_approx_sp(void)\n{\n  volatile ptr_t sp;\n\n  /*\n   * This also forces stack to grow if necessary.  Otherwise the later\n   * accesses might cause the kernel to think we are doing something wrong.\n   */\n  STORE_APPROX_SP_TO(sp);\n  return (/* no volatile */ ptr_t)sp;\n}\n\nGC_API void GC_CALL\nGC_clear_exclusion_table(void)\n{\n#ifdef DEBUG_ADD_DEL_ROOTS\n  GC_log_printf(\"Clear static root exclusions (%u elements)\\n\",\n                (unsigned)GC_excl_table_entries);\n#endif\n  GC_excl_table_entries = 0;\n}\n\n/*\n * Return the first exclusion range that includes an address not lower\n * than `start_addr`.\n */\nSTATIC struct exclusion *\nGC_next_exclusion(ptr_t start_addr)\n{\n  size_t low = 0;\n  size_t high;\n\n  if (UNLIKELY(0 == GC_excl_table_entries))\n    return NULL;\n  high = GC_excl_table_entries - 1;\n  while (high > low) {\n    size_t mid = (low + high) >> 1;\n\n    /* `low` <= `mid` < `high`. */\n    if (ADDR_GE(start_addr, GC_excl_table[mid].e_end)) {\n      low = mid + 1;\n    } else {\n      high = mid;\n    }\n  }\n  if (ADDR_GE(start_addr, GC_excl_table[low].e_end))\n    return NULL;\n\n  return GC_excl_table + low;\n}\n\nGC_INNER void\nGC_exclude_static_roots_inner(ptr_t start, ptr_t finish)\n{\n  struct exclusion *next;\n  size_t next_index;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(ADDR(start) % ALIGNMENT == 0);\n  GC_ASSERT(ADDR_LT(start, finish));\n\n  next = GC_next_exclusion(start);\n  if (next != NULL) {\n    if (ADDR_LT(next->e_start, finish)) {\n      /* Incomplete error check. */\n      ABORT(\"Exclusion ranges overlap\");\n    }\n    if (ADDR(next->e_start) == ADDR(finish)) {\n      /* Extend old range backwards. */\n      next->e_start = start;\n#ifdef DEBUG_ADD_DEL_ROOTS\n      GC_log_printf(\"Updating static root exclusion to %p .. %p\\n\",\n                    (void *)start, (void *)next->e_end);\n#endif\n      return;\n    }\n  }\n\n  next_index = GC_excl_table_entries;\n  if (next_index >= MAX_EXCLUSIONS)\n    ABORT(\"Too many exclusions\");\n  if (next != NULL) {\n    size_t i;\n\n    next_index = (size_t)(next - GC_excl_table);\n    for (i = GC_excl_table_entries; i > next_index; --i) {\n      GC_excl_table[i] = GC_excl_table[i - 1];\n    }\n  }\n#ifdef DEBUG_ADD_DEL_ROOTS\n  GC_log_printf(\"Adding static root exclusion at %u: %p .. %p\\n\",\n                (unsigned)next_index, (void *)start, (void *)finish);\n#endif\n  GC_excl_table[next_index].e_start = start;\n  GC_excl_table[next_index].e_end = finish;\n  ++GC_excl_table_entries;\n}\n\nGC_API void GC_CALL\nGC_exclude_static_roots(void *b, void *e)\n{\n  if (b == e) {\n    /* Nothing to exclude. */\n    return;\n  }\n\n  /* Round boundaries in direction reverse to that of `GC_add_roots`. */\n#if ALIGNMENT > 1\n  b = PTR_ALIGN_DOWN((ptr_t)b, ALIGNMENT);\n  e = UNLIKELY(ADDR(e) > ~(word)(ALIGNMENT - 1))\n          ? PTR_ALIGN_DOWN((ptr_t)e, ALIGNMENT) /*< overflow */\n          : PTR_ALIGN_UP((ptr_t)e, ALIGNMENT);\n#endif\n\n  LOCK();\n  GC_exclude_static_roots_inner((ptr_t)b, (ptr_t)e);\n  UNLOCK();\n}\n\n#if defined(WRAP_MARK_SOME) && defined(PARALLEL_MARK)\n#  define GC_PUSH_CONDITIONAL(b, t, all)                \\\n    (GC_parallel ? GC_push_conditional_eager(b, t, all) \\\n                 : GC_push_conditional_static(b, t, all))\n#else\n#  define GC_PUSH_CONDITIONAL(b, t, all) GC_push_conditional_static(b, t, all)\n#endif\n\n/* Invoke `GC_push_conditional` on ranges that are not excluded. */\nSTATIC void\nGC_push_conditional_with_exclusions(ptr_t bottom, ptr_t top, GC_bool all)\n{\n  while (ADDR_LT(bottom, top)) {\n    struct exclusion *next = GC_next_exclusion(bottom);\n    ptr_t excl_start = top;\n\n    if (next != NULL) {\n      if (ADDR_GE(next->e_start, top)) {\n        next = NULL;\n      } else {\n        excl_start = next->e_start;\n      }\n    }\n    if (ADDR_LT(bottom, excl_start))\n      GC_PUSH_CONDITIONAL(bottom, excl_start, all);\n    if (NULL == next)\n      break;\n    bottom = next->e_end;\n  }\n}\n\n#ifdef IA64\nGC_INNER void\nGC_push_all_register_sections(ptr_t bs_lo, ptr_t bs_hi, GC_bool eager,\n                              struct GC_traced_stack_sect_s *traced_stack_sect)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  while (traced_stack_sect != NULL) {\n    ptr_t frame_bs_lo = traced_stack_sect->backing_store_end;\n\n    GC_ASSERT(ADDR_GE(bs_hi, frame_bs_lo));\n    if (eager) {\n      GC_push_all_eager(frame_bs_lo, bs_hi);\n    } else {\n      GC_push_all_stack(frame_bs_lo, bs_hi);\n    }\n    bs_hi = traced_stack_sect->saved_backing_store_ptr;\n    traced_stack_sect = traced_stack_sect->prev;\n  }\n  GC_ASSERT(ADDR_GE(bs_hi, bs_lo));\n  if (eager) {\n    GC_push_all_eager(bs_lo, bs_hi);\n  } else {\n    GC_push_all_stack(bs_lo, bs_hi);\n  }\n}\n#endif /* IA64 */\n\n#ifdef THREADS\n\nGC_INNER void\nGC_push_all_stack_sections(ptr_t lo /* top */, ptr_t hi /* bottom */,\n                           struct GC_traced_stack_sect_s *traced_stack_sect)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  while (traced_stack_sect != NULL) {\n    GC_ASSERT(HOTTER_THAN(lo, (ptr_t)traced_stack_sect));\n#  ifdef STACK_GROWS_UP\n    GC_push_all_stack((ptr_t)traced_stack_sect, lo);\n#  else\n    GC_push_all_stack(lo, (ptr_t)traced_stack_sect);\n#  endif\n    lo = traced_stack_sect->saved_stack_ptr;\n    GC_ASSERT(lo != NULL);\n    traced_stack_sect = traced_stack_sect->prev;\n  }\n  GC_ASSERT(!HOTTER_THAN(hi, lo));\n#  ifdef STACK_GROWS_UP\n  /* We got them backwards! */\n  GC_push_all_stack(hi, lo);\n#  else\n  GC_push_all_stack(lo, hi);\n#  endif\n}\n\n#else /* !THREADS */\n\n/*\n * Similar to `GC_push_all_eager`, but only the part hotter than\n * `cold_gc_frame` is scanned immediately.  Needed to ensure that\n * callee-save registers are not missed.  Treats all interior pointers\n * as valid and scans part of the area immediately, to make sure that\n * saved register values are not lost.  `cold_gc_frame` delimits the\n * stack section that must be scanned eagerly.  A zero value indicates\n * that no eager scanning is needed.  We do not need to worry about\n * the manual VDB case here, since this is only called in the\n * single-threaded case.  We assume that we cannot collect between\n * an assignment and the corresponding `GC_dirty()` call.\n */\nSTATIC void\nGC_push_all_stack_partially_eager(ptr_t bottom, ptr_t top, ptr_t cold_gc_frame)\n{\n#  ifndef NEED_FIXUP_POINTER\n  if (GC_all_interior_pointers) {\n    /*\n     * Push the hot end of the stack eagerly, so that register values saved\n     * inside GC frames are marked before they disappear.  The rest of the\n     * marking can be deferred until later.\n     */\n    if (0 == cold_gc_frame) {\n      GC_push_all_stack(bottom, top);\n      return;\n    }\n    GC_ASSERT(ADDR_GE(cold_gc_frame, bottom) && ADDR_GE(top, cold_gc_frame));\n#    ifdef STACK_GROWS_UP\n    GC_push_all(bottom, cold_gc_frame + sizeof(ptr_t));\n    GC_push_all_eager(cold_gc_frame, top);\n#    else\n    GC_push_all(cold_gc_frame - sizeof(ptr_t), top);\n    GC_push_all_eager(bottom, cold_gc_frame);\n#    endif\n  } else\n#  endif\n  /* else */ {\n    GC_push_all_eager(bottom, top);\n  }\n#  ifdef TRACE_BUF\n  GC_add_trace_entry(\"GC_push_all_stack\", bottom, top);\n#  endif\n}\n\n/* Similar to `GC_push_all_stack_sections()` but also uses `cold_gc_frame`. */\nSTATIC void\nGC_push_all_stack_part_eager_sections(\n    ptr_t lo /* top */, ptr_t hi /* bottom */, ptr_t cold_gc_frame,\n    struct GC_traced_stack_sect_s *traced_stack_sect)\n{\n  GC_ASSERT(traced_stack_sect == NULL || cold_gc_frame == NULL\n            || HOTTER_THAN(cold_gc_frame, (ptr_t)traced_stack_sect));\n\n  while (traced_stack_sect != NULL) {\n    GC_ASSERT(HOTTER_THAN(lo, (ptr_t)traced_stack_sect));\n#  ifdef STACK_GROWS_UP\n    GC_push_all_stack_partially_eager((ptr_t)traced_stack_sect, lo,\n                                      cold_gc_frame);\n#  else\n    GC_push_all_stack_partially_eager(lo, (ptr_t)traced_stack_sect,\n                                      cold_gc_frame);\n#  endif\n    lo = traced_stack_sect->saved_stack_ptr;\n    GC_ASSERT(lo != NULL);\n    traced_stack_sect = traced_stack_sect->prev;\n    /* Note: use at most once. */\n    cold_gc_frame = NULL;\n  }\n\n  GC_ASSERT(!HOTTER_THAN(hi, lo));\n#  ifdef STACK_GROWS_UP\n  /* We got them backwards! */\n  GC_push_all_stack_partially_eager(hi, lo, cold_gc_frame);\n#  else\n  GC_push_all_stack_partially_eager(lo, hi, cold_gc_frame);\n#  endif\n}\n\n#endif /* !THREADS */\n\n/*\n * Push enough of the current stack eagerly to ensure that callee-save\n * registers saved in GC frames are scanned.  In the single-threaded case,\n * schedule the entire stack for scanning.  The 2nd argument (`context`)\n * is a pointer to the (possibly `NULL`) thread context, for (currently\n * hypothetical) more precise stack scanning.  In the presence of threads,\n * push enough of the current stack to ensure that callee-save registers\n * saved in collector frames have been seen.\n */\n/* TODO: Merge it with per-thread stuff. */\nSTATIC void\nGC_push_current_stack(ptr_t cold_gc_frame, void *context)\n{\n  UNUSED_ARG(context);\n  GC_ASSERT(I_HOLD_LOCK());\n#if defined(THREADS)\n  /* `cold_gc_frame` is non-`NULL`. */\n#  ifdef STACK_GROWS_UP\n  GC_push_all_eager(cold_gc_frame, GC_approx_sp());\n#  else\n  GC_push_all_eager(GC_approx_sp(), cold_gc_frame);\n  /*\n   * For IA-64, the register stack backing store is handled in the\n   * thread-specific code.\n   */\n#  endif\n#else\n  GC_push_all_stack_part_eager_sections(GC_approx_sp(), GC_stackbottom,\n                                        cold_gc_frame, GC_traced_stack_sect);\n#  ifdef IA64\n  /*\n   * We also need to push the register stack backing store.\n   * This should really be done in the same way as the regular stack.\n   * For now we fudge it a bit.  Note that the backing store grows up,\n   * so we cannot use `GC_push_all_stack_partially_eager`.\n   */\n  {\n    ptr_t bsp = GC_save_regs_ret_val;\n    ptr_t cold_gc_bs_pointer = bsp - 2048;\n    if (GC_all_interior_pointers\n        && ADDR_LT(GC_register_stackbottom, cold_gc_bs_pointer)) {\n      /*\n       * Adjust `cold_gc_bs_pointer` if below our innermost\n       * \"traced stack section\" in backing store.\n       */\n      if (GC_traced_stack_sect != NULL\n          && ADDR_LT(cold_gc_bs_pointer,\n                     GC_traced_stack_sect->backing_store_end)) {\n        cold_gc_bs_pointer = GC_traced_stack_sect->backing_store_end;\n      }\n      GC_push_all_register_sections(GC_register_stackbottom,\n                                    cold_gc_bs_pointer, FALSE,\n                                    GC_traced_stack_sect);\n      GC_push_all_eager(cold_gc_bs_pointer, bsp);\n    } else {\n      GC_push_all_register_sections(GC_register_stackbottom, bsp,\n                                    TRUE /* `eager` */, GC_traced_stack_sect);\n    }\n    /*\n     * All values should be sufficiently aligned that we do not have to\n     * worry about the boundary.\n     */\n  }\n#  elif defined(E2K)\n  /* We also need to push procedure stack store.  Procedure stack grows up. */\n  {\n    ptr_t bs_lo;\n    size_t stack_size;\n\n    /* TODO: Support `ps_ofs` here and in `GC_do_blocking_inner`. */\n    GET_PROCEDURE_STACK_LOCAL(0, &bs_lo, &stack_size);\n    GC_push_all_eager(bs_lo, bs_lo + stack_size);\n  }\n#  endif\n#endif /* !THREADS */\n}\n\nGC_INNER void (*GC_push_typed_structures)(void) = 0;\n\nGC_INNER void\nGC_cond_register_dynamic_libraries(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n#if defined(DYNAMIC_LOADING) && !defined(MSWIN_XBOX1) || defined(ANY_MSWIN)\n  GC_remove_tmp_roots();\n  if (!GC_no_dls)\n    GC_register_dynamic_libraries();\n#else\n  GC_no_dls = TRUE;\n#endif\n}\n\nSTATIC void\nGC_push_regs_and_stack(ptr_t cold_gc_frame)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n#ifdef THREADS\n  if (NULL == cold_gc_frame) {\n    /* `GC_push_all_stacks` should push registers and stack. */\n    return;\n  }\n#endif\n  GC_with_callee_saves_pushed(GC_push_current_stack, cold_gc_frame);\n}\n\nGC_INNER void\nGC_push_roots(GC_bool all, ptr_t cold_gc_frame)\n{\n  size_t i;\n  unsigned kind;\n\n  GC_ASSERT(I_HOLD_LOCK());\n\n  /* The initialization is needed for `GC_push_all_stacks`. */\n  GC_ASSERT(GC_is_initialized);\n\n  /*\n   * Next push static data.  This must happen early on, since it is not\n   * robust against mark stack overflow.  Re-register dynamic libraries,\n   * in case one got added.  There is some argument for doing this as late\n   * as possible, especially on Win32, where it can change asynchronously.\n   * In those cases, we do it here.  But on other platforms, it is not safe\n   * with the world stopped, so we do it earlier.\n   */\n#if !defined(REGISTER_LIBRARIES_EARLY)\n  GC_cond_register_dynamic_libraries();\n#endif\n\n  /* Mark everything in static data areas. */\n  for (i = 0; i < n_root_sets; i++) {\n    GC_push_conditional_with_exclusions(GC_static_roots[i].r_start,\n                                        GC_static_roots[i].r_end, all);\n  }\n\n  /*\n   * Mark all free-list header blocks, if those were allocated from\n   * the garbage-collected heap.  This makes sure they do not disappear\n   * if we are not marking from static data.  It also saves us the trouble\n   * of scanning them, and possibly that of marking the free lists.\n   */\n  for (kind = 0; kind < GC_n_kinds; kind++) {\n    const void *base = GC_base(GC_obj_kinds[kind].ok_freelist);\n\n    if (base != NULL) {\n      GC_set_mark_bit(base);\n    }\n  }\n\n  /*\n   * Mark from the collector internal roots if those might otherwise\n   * have been excluded.\n   */\n#ifndef GC_NO_FINALIZATION\n  GC_push_finalizer_structures();\n#endif\n#ifdef THREADS\n  if (GC_no_dls || GC_roots_were_cleared)\n    GC_push_thread_structures();\n#endif\n  if (GC_push_typed_structures) {\n    GC_push_typed_structures();\n  }\n\n#if defined(THREAD_LOCAL_ALLOC)\n  /*\n   * Mark thread-local free lists, even if their mark descriptor excludes\n   * the link field.  If the world is not stopped, this is unsafe.\n   * It is also unnecessary, since we will do this again with the world\n   * stopped.\n   */\n  if (GC_world_stopped) {\n    GC_mark_thread_local_free_lists();\n  }\n#endif\n\n  /*\n   * Now traverse stacks, and mark from register contents.\n   * These must be done last, since they can legitimately overflow\n   * the mark stack.  This is usually done by saving the current\n   * context on the stack, and then just tracing from the stack.\n   */\n#ifdef STACK_NOT_SCANNED\n  UNUSED_ARG(cold_gc_frame);\n#else\n  GC_push_regs_and_stack(cold_gc_frame);\n#endif\n\n  if (GC_push_other_roots != 0) {\n    /*\n     * In the multi-threaded case, this also pushes thread stacks.\n     * Note that without the interior pointers recognition lots of stuff\n     * may have already been pushed, and this should be careful about\n     * mark stack overflows.\n     */\n    (*GC_push_other_roots)();\n  }\n}\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1996 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2009-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#ifdef ENABLE_DISCLAIM\n\n\n#endif\n\n#ifdef PARALLEL_MARK\nGC_INNER GC_signed_word GC_fl_builder_count = 0;\n#endif\n\n/*\n * We defer printing of leaked objects until we are done with the\n * collection cycle, since the routine for printing objects needs\n * to run outside the collector, e.g. without the allocator lock.\n */\n\n#ifndef NO_FIND_LEAK\n#  ifndef MAX_LEAKED\n#    define MAX_LEAKED 40\n#  endif\nSTATIC ptr_t GC_leaked[MAX_LEAKED] = { NULL };\n#endif\n\n#if !defined(EAGER_SWEEP) && defined(ENABLE_DISCLAIM)\nSTATIC void GC_reclaim_unconditionally_marked(void);\n#endif\n\n#ifndef SHORT_DBG_HDRS\n\n\n#  ifndef MAX_SMASHED\n#    define MAX_SMASHED 20\n#  endif\n\n/*\n * List of smashed (clobbered) locations.  We defer printing these,\n * since we cannot always print them nicely with the allocator lock held.\n * We put them here instead of in `GC_arrays`, since it may be useful to\n * be able to look at them with the debugger.\n */\nSTATIC ptr_t GC_smashed[MAX_SMASHED] = { NULL };\n\nGC_INNER void\nGC_add_smashed(ptr_t smashed)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_is_marked(GC_base(smashed)));\n  /* FIXME: Prevent adding an object while printing smashed list. */\n  GC_smashed[GC_n_smashed] = smashed;\n  /*\n   * In case of overflow, we keep the first `MAX_SMASHED - 1` entries\n   * plus the last one.\n   */\n  if (GC_n_smashed < MAX_SMASHED - 1)\n    ++GC_n_smashed;\n  GC_SET_HAVE_ERRORS();\n}\n\nGC_INNER void\nGC_print_smashed_obj(const char *msg, void *p, ptr_t clobbered)\n{\n  oh *ohdr = (oh *)GC_base(p);\n\n  GC_ASSERT(I_DONT_HOLD_LOCK());\n#  ifdef LINT2\n  if (!ohdr)\n    ABORT(\"Invalid GC_print_smashed_obj argument\");\n#  endif\n  if (ADDR_GE((ptr_t)(&ohdr->oh_sz), clobbered) || NULL == ohdr->oh_string) {\n    GC_err_printf(\"%s %p in or near object at %p(<smashed>, appr. sz= %lu)\\n\",\n                  msg, (void *)clobbered, p,\n                  (unsigned long)(GC_size(ohdr) - DEBUG_BYTES));\n  } else {\n    GC_err_printf(\"%s %p in or near object at %p (%s:%d, sz= %lu)\\n\", msg,\n                  (void *)clobbered, p,\n                  ADDR(ohdr->oh_string) < HBLKSIZE ? \"(smashed string)\"\n                  : ohdr->oh_string[0] == '\\0'     ? \"EMPTY(smashed?)\"\n                                                   : ohdr->oh_string,\n                  GET_OH_LINENUM(ohdr), (unsigned long)ohdr->oh_sz);\n    PRINT_CALL_CHAIN(ohdr);\n  }\n}\n\nGC_INNER void\nGC_print_all_smashed_proc(void)\n{\n  unsigned i;\n\n  GC_ASSERT(I_DONT_HOLD_LOCK());\n  if (GC_n_smashed == 0)\n    return;\n  GC_err_printf(\"GC_check_heap_block: found %u smashed heap objects:\\n\",\n                GC_n_smashed);\n  for (i = 0; i < GC_n_smashed; ++i) {\n    ptr_t base = (ptr_t)GC_base(GC_smashed[i]);\n\n#  ifdef LINT2\n    if (!base)\n      ABORT(\"Invalid GC_smashed element\");\n#  endif\n    GC_print_smashed_obj(\"\", base + sizeof(oh), GC_smashed[i]);\n    GC_smashed[i] = 0;\n  }\n  GC_n_smashed = 0;\n}\n\nGC_INNER int\nGC_has_other_debug_info(ptr_t base)\n{\n  ptr_t body = (ptr_t)((oh *)base + 1);\n  size_t sz = GC_size(base);\n\n  if (HBLKPTR(base) != HBLKPTR(body) || sz < DEBUG_BYTES + EXTRA_BYTES) {\n    return 0;\n  }\n  if (((oh *)base)->oh_sf != (START_FLAG ^ (GC_uintptr_t)body)\n      && ((GC_uintptr_t *)base)[BYTES_TO_PTRS(sz) - 1]\n             != (END_FLAG ^ (GC_uintptr_t)body)) {\n    return 0;\n  }\n  if (((oh *)base)->oh_sz == (GC_uintptr_t)sz) {\n    /* Object may have had debug info, but has been deallocated. */\n    return -1;\n  }\n  return 1;\n}\n#endif /* !SHORT_DBG_HDRS */\n\nGC_INNER void\nGC_default_print_heap_obj_proc(ptr_t p)\n{\n  ptr_t base = (ptr_t)GC_base(p);\n  int kind = HDR(base)->hb_obj_kind;\n\n  GC_err_printf(\"object at %p of appr. %lu bytes (%s)\\n\", (void *)base,\n                (unsigned long)GC_size(base),\n                kind == PTRFREE          ? \"atomic\"\n                : IS_UNCOLLECTABLE(kind) ? \"uncollectable\"\n                                         : \"composite\");\n}\n\nGC_INNER void (*GC_print_heap_obj)(ptr_t p) = GC_default_print_heap_obj_proc;\n\n#if !defined(NO_FIND_LEAK) || !defined(SHORT_DBG_HDRS)\nGC_INNER void\nGC_print_all_errors(void)\n{\n  static GC_bool printing_errors = FALSE;\n  GC_bool have_errors;\n#  ifndef NO_FIND_LEAK\n  unsigned i, n_leaked;\n  ptr_t leaked[MAX_LEAKED];\n#  endif\n\n  LOCK();\n  if (printing_errors) {\n    UNLOCK();\n    return;\n  }\n  have_errors = get_have_errors();\n  printing_errors = TRUE;\n#  ifndef NO_FIND_LEAK\n  n_leaked = GC_n_leaked;\n  if (n_leaked > 0) {\n    GC_ASSERT(n_leaked <= MAX_LEAKED);\n    BCOPY(GC_leaked, leaked, n_leaked * sizeof(ptr_t));\n    GC_n_leaked = 0;\n    BZERO(GC_leaked, n_leaked * sizeof(ptr_t));\n  }\n#  endif\n  UNLOCK();\n\n  if (GC_debugging_started) {\n    GC_print_all_smashed();\n  } else {\n    have_errors = FALSE;\n  }\n\n#  ifndef NO_FIND_LEAK\n  if (n_leaked > 0) {\n    GC_err_printf(\"Found %u leaked objects:\\n\", n_leaked);\n    have_errors = TRUE;\n  }\n  for (i = 0; i < n_leaked; i++) {\n    ptr_t p = leaked[i];\n\n#    ifndef SKIP_LEAKED_OBJECTS_PRINTING\n    GC_print_heap_obj(p);\n#    endif\n    GC_free(p);\n  }\n#  endif\n\n  if (have_errors\n#  ifndef GC_ABORT_ON_LEAK\n      && GETENV(\"GC_ABORT_ON_LEAK\") != NULL\n#  endif\n  ) {\n    ABORT(\"Leaked or smashed objects encountered\");\n  }\n\n  LOCK();\n  printing_errors = FALSE;\n  UNLOCK();\n}\n#endif\n\n/* The reclaim phase. */\n\nGC_INNER GC_bool\nGC_block_empty(const hdr *hhdr)\n{\n  return 0 == hhdr->hb_n_marks;\n}\n\nSTATIC GC_bool\nGC_block_nearly_full(const hdr *hhdr, size_t sz)\n{\n  return hhdr->hb_n_marks > HBLK_OBJS(sz) * 7 / 8;\n}\n\n/*\n * TODO: This should perhaps again be specialized for `USE_MARK_BYTES`\n * and `USE_MARK_BITS` cases.\n */\n\nGC_INLINE ptr_t\nGC_clear_block(ptr_t q, size_t sz, word *pcount)\n{\n  ptr_t *p = (ptr_t *)q;\n  ptr_t plim = q + sz;\n\n  /* Clear object, advance `p` to next object in the process. */\n#ifdef USE_MARK_BYTES\n  GC_ASSERT((sz & 1) == 0);\n  GC_ASSERT((ADDR(p) & (2 * sizeof(ptr_t) - 1)) == 0);\n  p[1] = NULL; /*< but do not clear link field */\n  for (p += 2; ADDR_LT((ptr_t)p, plim); p += 2) {\n    CLEAR_DOUBLE(p);\n  }\n#else\n  /* Skip link field. */\n  p++;\n\n  while (ADDR_LT((ptr_t)p, plim)) {\n    *p++ = NULL;\n  }\n#endif\n  *pcount += sz;\n  return (ptr_t)p;\n}\n\n/*\n * Restore unmarked small objects in `h` of size `sz` (in bytes) to the\n * object free list.  Returns the new list.  Clears unmarked objects.\n */\nSTATIC ptr_t\nGC_reclaim_clear(struct hblk *hbp, const hdr *hhdr, size_t sz, ptr_t list,\n                 word *pcount)\n{\n  size_t bit_no;\n  ptr_t p, plim;\n\n  GC_ASSERT(hhdr == GC_find_header(hbp));\n#ifndef THREADS\n  GC_ASSERT(sz == hhdr->hb_sz);\n#else\n  /* Skip the assertion because of a potential race with `GC_realloc`. */\n#endif\n  GC_ASSERT((sz & (sizeof(ptr_t) - 1)) == 0);\n\n  /* Go through all objects in the block. */\n  p = hbp->hb_body;\n  plim = p + HBLKSIZE - sz;\n  for (bit_no = 0; ADDR_GE(plim, p); bit_no += MARK_BIT_OFFSET(sz)) {\n    if (mark_bit_from_hdr(hhdr, bit_no)) {\n      p += sz;\n    } else {\n      /* The object is available - put it on list. */\n      obj_link(p) = list;\n      list = p;\n      FREE_PROFILER_HOOK(p);\n      p = GC_clear_block(p, sz, pcount);\n    }\n  }\n  return list;\n}\n\n/* The same thing as `GC_reclaim_clear`, but do not clear objects. */\nSTATIC ptr_t\nGC_reclaim_uninit(struct hblk *hbp, const hdr *hhdr, size_t sz, ptr_t list,\n                  word *pcount)\n{\n  size_t bit_no;\n  word n_bytes_found = 0;\n  ptr_t p, plim;\n\n#ifndef THREADS\n  GC_ASSERT(sz == hhdr->hb_sz);\n#endif\n\n  /* Go through all objects in the block. */\n  p = hbp->hb_body;\n  plim = (ptr_t)hbp + HBLKSIZE - sz;\n  for (bit_no = 0; ADDR_GE(plim, p); bit_no += MARK_BIT_OFFSET(sz), p += sz) {\n    if (!mark_bit_from_hdr(hhdr, bit_no)) {\n      n_bytes_found += sz;\n      /* The object is available - put it on list. */\n      obj_link(p) = list;\n      list = p;\n      FREE_PROFILER_HOOK(p);\n    }\n  }\n  *pcount += n_bytes_found;\n  return list;\n}\n\n#ifdef ENABLE_DISCLAIM\n/*\n * Call reclaim notifier for block's kind on each unmarked object in block,\n * all within a pair of corresponding enter/leave callbacks.\n */\nSTATIC ptr_t\nGC_disclaim_and_reclaim(struct hblk *hbp, hdr *hhdr, size_t sz, ptr_t list,\n                        word *pcount)\n{\n  size_t bit_no;\n  ptr_t p, plim;\n  int(GC_CALLBACK * disclaim)(void *)\n      = GC_obj_kinds[hhdr->hb_obj_kind].ok_disclaim_proc;\n\n  GC_ASSERT(disclaim != 0);\n#  ifndef THREADS\n  GC_ASSERT(sz == hhdr->hb_sz);\n#  endif\n  p = hbp->hb_body;\n  plim = p + HBLKSIZE - sz;\n\n  for (bit_no = 0; ADDR_GE(plim, p); bit_no += MARK_BIT_OFFSET(sz)) {\n    if (mark_bit_from_hdr(hhdr, bit_no)) {\n      p += sz;\n    } else if (disclaim(p)) {\n      set_mark_bit_from_hdr(hhdr, bit_no);\n      INCR_MARKS(hhdr);\n      p += sz;\n    } else {\n      obj_link(p) = list;\n      list = p;\n      FREE_PROFILER_HOOK(p);\n      p = GC_clear_block(p, sz, pcount);\n    }\n  }\n  return list;\n}\n#endif /* ENABLE_DISCLAIM */\n\n#ifndef NO_FIND_LEAK\n\n#  ifndef SHORT_DBG_HDRS\nSTATIC GC_bool\nGC_check_leaked(ptr_t base)\n{\n  size_t i;\n  size_t lpw;\n  ptr_t *p;\n\n  if (\n#    if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)\n      (*(GC_uintptr_t *)base & 1) != 0 &&\n#    endif\n      GC_has_other_debug_info(base) >= 0)\n    return TRUE; /*< object has leaked */\n\n  /* Validate freed object's content. */\n  p = (ptr_t *)(base + sizeof(oh));\n  lpw = BYTES_TO_PTRS(HDR(base)->hb_sz - sizeof(oh));\n  for (i = 0; i < lpw; ++i)\n    if ((GC_uintptr_t)p[i] != GC_FREED_MEM_MARKER) {\n      /* Do not reclaim it in this cycle. */\n      GC_set_mark_bit(base);\n      /* Alter-after-free has been detected. */\n      GC_add_smashed((ptr_t)(&p[i]));\n      /* Do not report any other smashed locations in the object. */\n      break;\n    }\n\n  return FALSE; /*< `GC_debug_free()` has been called */\n}\n#  endif /* !SHORT_DBG_HDRS */\n\nGC_INLINE void\nGC_add_leaked(ptr_t leaked)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n#  ifndef SHORT_DBG_HDRS\n  if (GC_findleak_delay_free && !GC_check_leaked(leaked))\n    return;\n#  endif\n\n  GC_SET_HAVE_ERRORS();\n  if (GC_n_leaked < MAX_LEAKED) {\n    GC_leaked[GC_n_leaked++] = leaked;\n    /* Make sure it is not reclaimed this cycle. */\n    GC_set_mark_bit(leaked);\n  }\n}\n\n/* Do not really reclaim objects, just check for unmarked ones. */\nSTATIC void\nGC_reclaim_check(struct hblk *hbp, const hdr *hhdr, size_t sz)\n{\n  size_t bit_no;\n  ptr_t p, plim;\n\n#  ifndef THREADS\n  GC_ASSERT(sz == hhdr->hb_sz);\n#  endif\n  /* Go through all objects in the block. */\n  p = hbp->hb_body;\n  plim = p + HBLKSIZE - sz;\n  for (bit_no = 0; ADDR_GE(plim, p); bit_no += MARK_BIT_OFFSET(sz), p += sz) {\n    if (!mark_bit_from_hdr(hhdr, bit_no))\n      GC_add_leaked(p);\n  }\n}\n\n#endif /* !NO_FIND_LEAK */\n\n/*\n * Is a pointer-free block?  Same as `IS_PTRFREE()` macro but uses\n * unordered atomic access to avoid racing with `GC_realloc`.\n */\n#ifdef AO_HAVE_load\n#  define IS_PTRFREE_SAFE(hhdr) (AO_load((AO_t *)&(hhdr)->hb_descr) == 0)\n#else\n/*\n * No race as `GC_realloc` holds the allocator lock when updating\n * `hb_descr` field.\n */\n#  define IS_PTRFREE_SAFE(hhdr) IS_PTRFREE(hhdr)\n#endif\n\nGC_INNER ptr_t\nGC_reclaim_generic(struct hblk *hbp, hdr *hhdr, size_t sz, GC_bool init,\n                   ptr_t list, word *pcount)\n{\n  ptr_t result;\n\n#ifndef PARALLEL_MARK\n  GC_ASSERT(I_HOLD_LOCK());\n#endif\n  GC_ASSERT(GC_find_header(hbp) == hhdr);\n#ifndef GC_DISABLE_INCREMENTAL\n  GC_remove_protection(hbp, 1, IS_PTRFREE_SAFE(hhdr));\n#endif\n#ifdef ENABLE_DISCLAIM\n  if ((hhdr->hb_flags & HAS_DISCLAIM) != 0) {\n    result = GC_disclaim_and_reclaim(hbp, hhdr, sz, list, pcount);\n  } else\n#endif\n  /* else */ {\n    if (init || GC_debugging_started) {\n      result = GC_reclaim_clear(hbp, hhdr, sz, list, pcount);\n    } else {\n#ifndef AO_HAVE_load\n      GC_ASSERT(IS_PTRFREE(hhdr));\n#endif\n      result = GC_reclaim_uninit(hbp, hhdr, sz, list, pcount);\n    }\n  }\n  if (IS_UNCOLLECTABLE(hhdr->hb_obj_kind))\n    GC_set_hdr_marks(hhdr);\n  return result;\n}\n\n/*\n * Restore unmarked small objects in the block pointed to by `hbp` to\n * the appropriate object free list.  If entirely empty blocks are to\n * be completely deallocated, then caller should perform that check.\n */\nSTATIC void\nGC_reclaim_small_nonempty_block(struct hblk *hbp, size_t sz,\n                                GC_bool report_if_found)\n{\n  hdr *hhdr;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  hhdr = HDR(hbp);\n  hhdr->hb_last_reclaimed = (unsigned short)GC_gc_no;\n  if (report_if_found) {\n#ifndef NO_FIND_LEAK\n    GC_reclaim_check(hbp, hhdr, sz);\n#endif\n  } else {\n    struct obj_kind *ok = &GC_obj_kinds[hhdr->hb_obj_kind];\n    void **flh = &ok->ok_freelist[BYTES_TO_GRANULES(sz)];\n\n    *flh = GC_reclaim_generic(hbp, hhdr, sz, ok->ok_init, (ptr_t)(*flh),\n                              (/* unsigned */ word *)&GC_bytes_found);\n  }\n}\n\n#ifdef ENABLE_DISCLAIM\nSTATIC void\nGC_disclaim_and_reclaim_or_free_small_block(struct hblk *hbp)\n{\n  hdr *hhdr;\n  size_t sz;\n  struct obj_kind *ok;\n  void **flh;\n  void *flh_next;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  hhdr = HDR(hbp);\n  sz = hhdr->hb_sz;\n  ok = &GC_obj_kinds[hhdr->hb_obj_kind];\n  flh = &ok->ok_freelist[BYTES_TO_GRANULES(sz)];\n\n  hhdr->hb_last_reclaimed = (unsigned short)GC_gc_no;\n  flh_next = GC_reclaim_generic(hbp, hhdr, sz, ok->ok_init, (ptr_t)(*flh),\n                                (/* unsigned */ word *)&GC_bytes_found);\n  if (hhdr->hb_n_marks) {\n    *flh = flh_next;\n  } else {\n    GC_ASSERT(hbp == hhdr->hb_block);\n    GC_bytes_found += (GC_signed_word)HBLKSIZE;\n    GC_freehblk(hbp);\n  }\n}\n#endif /* ENABLE_DISCLAIM */\n\n/*\n * Restore an unmarked large object or an entirely empty block of\n * small objects to the heap block free list.  Otherwise enqueue the\n * block for later processing by `GC_reclaim_small_nonempty_block()`.\n * If `report_if_found` is `TRUE`, then process any block immediately,\n * and simply report free objects; do not actually reclaim them.\n */\nSTATIC void GC_CALLBACK\nGC_reclaim_block(struct hblk *hbp, void *report_if_found)\n{\n  hdr *hhdr;\n  size_t sz; /*< size of objects in current block */\n  struct obj_kind *ok;\n\n  GC_ASSERT(I_HOLD_LOCK());\n#if defined(CPPCHECK)\n  GC_noop1_ptr(report_if_found);\n#endif\n  hhdr = HDR(hbp);\n  ok = &GC_obj_kinds[hhdr->hb_obj_kind];\n#ifdef AO_HAVE_load\n  /* Atomic access is used to avoid racing with `GC_realloc`. */\n  sz = AO_load((volatile AO_t *)&hhdr->hb_sz);\n#else\n  /*\n   * No race as `GC_realloc` holds the allocator lock while\n   * updating `hb_sz`.\n   */\n  sz = hhdr->hb_sz;\n#endif\n  if (sz > MAXOBJBYTES) {\n    /* The case of 1 big object. */\n    if (!mark_bit_from_hdr(hhdr, 0)) {\n      if (report_if_found) {\n        GC_ASSERT(hbp == hhdr->hb_block);\n#ifndef NO_FIND_LEAK\n        GC_add_leaked((ptr_t)hbp);\n#endif\n      } else {\n#ifdef ENABLE_DISCLAIM\n        if (UNLIKELY((hhdr->hb_flags & HAS_DISCLAIM) != 0)) {\n          if (ok->ok_disclaim_proc(hbp)) {\n            /* Not disclaimed, thus resurrect the object. */\n            set_mark_bit_from_hdr(hhdr, 0);\n            goto in_use;\n          }\n        }\n#endif\n        GC_ASSERT(hbp == hhdr->hb_block);\n        if (sz > HBLKSIZE) {\n          GC_large_allocd_bytes -= HBLKSIZE * OBJ_SZ_TO_BLOCKS(sz);\n        }\n        GC_bytes_found += (GC_signed_word)sz;\n        GC_freehblk(hbp);\n        FREE_PROFILER_HOOK(hbp);\n      }\n    } else {\n#ifdef ENABLE_DISCLAIM\n    in_use:\n#endif\n      if (IS_PTRFREE_SAFE(hhdr)) {\n        GC_atomic_in_use += sz;\n      } else {\n        GC_composite_in_use += sz;\n      }\n    }\n  } else {\n    GC_bool empty = GC_block_empty(hhdr);\n\n#ifdef PARALLEL_MARK\n    /*\n     * Count can be low or one too high because we sometimes have to\n     * ignore decrements.  Objects can also potentially be repeatedly\n     * marked by each marker.  Here we assume 3 markers at most, but\n     * this is extremely unlikely to fail spuriously with more.\n     * And if it does, it should be looked at.\n     */\n    GC_ASSERT(sz != 0\n              && (GC_markers_m1 > 1 ? 3 : GC_markers_m1 + 1)\n                             * (HBLKSIZE / sz + 1)\n                         + 16\n                     >= hhdr->hb_n_marks);\n#else\n    GC_ASSERT(sz * hhdr->hb_n_marks <= HBLKSIZE);\n#endif\n#ifdef VALGRIND_TRACKING\n    /*\n     * Call `GC_free_profiler_hook()` on freed objects so that\n     * a profiling tool could track the allocations.\n     */\n    {\n      ptr_t p = hbp->hb_body;\n      ptr_t plim = p + HBLKSIZE - sz;\n      size_t bit_no;\n\n      for (bit_no = 0; ADDR_GE(plim, p);\n           bit_no += MARK_BIT_OFFSET(sz), p += sz) {\n        if (!mark_bit_from_hdr(hhdr, bit_no))\n          FREE_PROFILER_HOOK(p);\n      }\n    }\n#endif\n    GC_ASSERT(hbp == hhdr->hb_block);\n    if (report_if_found) {\n      GC_reclaim_small_nonempty_block(hbp, sz, TRUE /* `report_if_found` */);\n    } else if (empty) {\n#ifdef ENABLE_DISCLAIM\n      if ((hhdr->hb_flags & HAS_DISCLAIM) != 0) {\n        GC_disclaim_and_reclaim_or_free_small_block(hbp);\n      } else\n#endif\n      /* else */ {\n        GC_bytes_found += (GC_signed_word)HBLKSIZE;\n        GC_freehblk(hbp);\n        FREE_PROFILER_HOOK(hbp);\n      }\n    } else if (GC_find_leak_inner || !GC_block_nearly_full(hhdr, sz)) {\n      /* Group of smaller objects, enqueue the real work. */\n      struct hblk **rlh = ok->ok_reclaim_list;\n\n      if (rlh != NULL) {\n        rlh += BYTES_TO_GRANULES(sz);\n        hhdr->hb_next = *rlh;\n        *rlh = hbp;\n      }\n    } else {\n      /* Not worth salvaging. */\n    }\n    /*\n     * We used to do the `GC_block_nearly_full` check later, but we\n     * already have the right cache context here.  Also doing it here\n     * avoids some silly lock contention in `GC_malloc_many()`.\n     */\n    if (IS_PTRFREE_SAFE(hhdr)) {\n      GC_atomic_in_use += (word)sz * hhdr->hb_n_marks;\n    } else {\n      GC_composite_in_use += (word)sz * hhdr->hb_n_marks;\n    }\n  }\n}\n\n#if !defined(NO_DEBUGGING)\n/*\n * Routines to gather and print heap block info intended for debugging.\n * Otherwise should be called with the allocator lock held.\n */\n\nstruct Print_stats {\n  size_t number_of_blocks;\n  size_t total_bytes;\n};\n\nEXTERN_C_BEGIN /*< to avoid \"no previous prototype\" clang warning */\n    unsigned\n    GC_n_set_marks(const hdr *);\nEXTERN_C_END\n\n#  ifdef USE_MARK_BYTES\n/*\n * Return the number of set mark bits in the given header.\n * Remains externally visible as used by GNU `gcj` currently.\n * There could be a race between `GC_clear_hdr_marks` and this\n * function but the latter is for a debug purpose.\n */\nGC_ATTR_NO_SANITIZE_THREAD\nunsigned\nGC_n_set_marks(const hdr *hhdr)\n{\n  unsigned result = 0;\n  size_t i;\n  size_t offset = MARK_BIT_OFFSET(hhdr->hb_sz);\n  size_t limit = FINAL_MARK_BIT(hhdr->hb_sz);\n\n  for (i = 0; i < limit; i += offset) {\n    result += (unsigned)hhdr->hb_marks[i];\n  }\n\n  /* The one should be set past the end. */\n  GC_ASSERT(hhdr->hb_marks[limit]);\n  return result;\n}\n\n#  else\n/* Number of set bits in a word.  Not performance critical. */\nstatic unsigned\ncount_ones(word v)\n{\n  unsigned result = 0;\n\n  for (; v > 0; v >>= 1) {\n    if (v & 1)\n      result++;\n  }\n  return result;\n}\n\nunsigned\nGC_n_set_marks(const hdr *hhdr)\n{\n  unsigned result = 0;\n  size_t i;\n#    ifdef MARK_BIT_PER_OBJ\n  size_t n_objs = HBLK_OBJS(hhdr->hb_sz);\n  size_t n_mark_words = divWORDSZ(n_objs > 0 ? n_objs : 1); /*< round down */\n\n  for (i = 0; i <= n_mark_words; i++) {\n    result += count_ones(hhdr->hb_marks[i]);\n  }\n#    else\n\n  for (i = 0; i < HB_MARKS_SZ; i++) {\n    result += count_ones(hhdr->hb_marks[i]);\n  }\n#    endif\n  GC_ASSERT(result > 0);\n  /* Exclude the one bit set past the end. */\n  result--;\n\n#    ifndef MARK_BIT_PER_OBJ\n  if (IS_UNCOLLECTABLE(hhdr->hb_obj_kind)) {\n    size_t lg = BYTES_TO_GRANULES(hhdr->hb_sz);\n\n    /*\n     * As mentioned in `GC_set_hdr_marks`, all the bits are set instead of\n     * every `n`-th, thus the result should be adjusted.\n     */\n    GC_ASSERT((unsigned)lg != 0 && result % lg == 0);\n    result /= (unsigned)lg;\n  }\n#    endif\n  return result;\n}\n#  endif /* !USE_MARK_BYTES */\n\nGC_API unsigned GC_CALL\nGC_count_set_marks_in_hblk(const void *p)\n{\n  return GC_n_set_marks(HDR(p));\n}\n\nSTATIC void GC_CALLBACK\nGC_print_block_descr(struct hblk *h, void *raw_ps)\n{\n  const hdr *hhdr = HDR(h);\n  size_t sz = hhdr->hb_sz;\n  struct Print_stats *ps = (struct Print_stats *)raw_ps;\n  size_t n_marks = (size_t)GC_n_set_marks(hhdr);\n  size_t n_objs = HBLK_OBJS(sz);\n\n#  ifndef PARALLEL_MARK\n  GC_ASSERT(hhdr->hb_n_marks == n_marks);\n#  endif\n#  if defined(CPPCHECK)\n  GC_noop1_ptr(h);\n#  endif\n  GC_ASSERT((n_objs > 0 ? n_objs : 1) >= n_marks);\n  GC_printf(\"%u,%u,%u,%u\\n\", hhdr->hb_obj_kind, (unsigned)sz,\n            (unsigned)n_marks, (unsigned)n_objs);\n  ps->number_of_blocks++;\n  ps->total_bytes += (sz + HBLKSIZE - 1) & ~(HBLKSIZE - 1); /*< round up */\n}\n\nvoid\nGC_print_block_list(void)\n{\n  struct Print_stats pstats;\n\n  GC_printf(\"kind(0=ptrfree/1=normal/2=unc.),\"\n            \"obj_sz,#marks_set,#objs_in_block\\n\");\n  BZERO(&pstats, sizeof(pstats));\n  GC_apply_to_all_blocks(GC_print_block_descr, &pstats);\n  GC_printf(\"blocks= %lu, total_bytes= %lu\\n\",\n            (unsigned long)pstats.number_of_blocks,\n            (unsigned long)pstats.total_bytes);\n  if (pstats.total_bytes + GC_large_free_bytes != GC_heapsize)\n    GC_err_printf(\"LOST SOME BLOCKS!! Total bytes should be: %lu\\n\",\n                  (unsigned long)(GC_heapsize - GC_large_free_bytes));\n}\n\nGC_API void GC_CALL\nGC_print_free_list(int kind, size_t lg)\n{\n  void *flh_next;\n  int n;\n\n  GC_ASSERT(kind < MAXOBJKINDS);\n  GC_ASSERT(lg <= MAXOBJGRANULES);\n  flh_next = GC_obj_kinds[kind].ok_freelist[lg];\n  for (n = 0; flh_next != NULL; n++) {\n    GC_printf(\"Free object in heap block %p [%d]: %p\\n\",\n              (void *)HBLKPTR(flh_next), n, flh_next);\n    flh_next = obj_link(flh_next);\n  }\n}\n#endif /* !NO_DEBUGGING */\n\n/*\n * Clear all `obj_link` pointers in the list of free objects `*flp`.\n * Clear `*flp`.  This must be done before dropping a list of free\n * `gcj`-style objects, since may otherwise end up with dangling\n * \"descriptor\" pointers.  It may help for other pointer-containing\n * objects.\n */\nSTATIC void\nGC_clear_fl_links(void **flp)\n{\n  void *next;\n\n  for (next = *flp; next != NULL; next = *flp) {\n    *flp = NULL;\n    flp = &obj_link(next);\n  }\n}\n\nGC_INNER void\nGC_start_reclaim(GC_bool report_if_found)\n{\n  int kind;\n\n  GC_ASSERT(I_HOLD_LOCK());\n#if defined(PARALLEL_MARK)\n  GC_ASSERT(0 == GC_fl_builder_count);\n#endif\n  /* Reset in-use counters.  `GC_reclaim_block` recomputes them. */\n  GC_composite_in_use = 0;\n  GC_atomic_in_use = 0;\n\n  /* Clear reclaim- and free-lists. */\n  for (kind = 0; kind < (int)GC_n_kinds; kind++) {\n    struct hblk **rlist = GC_obj_kinds[kind].ok_reclaim_list;\n    GC_bool should_clobber = GC_obj_kinds[kind].ok_descriptor != 0;\n\n    if (NULL == rlist) {\n      /* Means this object kind is not used. */\n      continue;\n    }\n\n    if (!report_if_found) {\n      void **fop;\n      void **lim = &GC_obj_kinds[kind].ok_freelist[MAXOBJGRANULES + 1];\n\n      for (fop = GC_obj_kinds[kind].ok_freelist;\n           ADDR_LT((ptr_t)fop, (ptr_t)lim); fop++) {\n        if (*fop != NULL) {\n          if (should_clobber) {\n            GC_clear_fl_links(fop);\n          } else {\n            *fop = NULL;\n          }\n        }\n      }\n    } else {\n      /* Free-list objects are marked, and it is safe to leave them. */\n    }\n    BZERO(rlist, (MAXOBJGRANULES + 1) * sizeof(void *));\n  }\n\n  /*\n   * Go through all heap blocks, and reclaim unmarked objects or enqueue\n   * the block for later processing.\n   */\n  GC_apply_to_all_blocks(GC_reclaim_block, NUMERIC_TO_VPTR(report_if_found));\n\n#ifdef EAGER_SWEEP\n  /*\n   * This is a very stupid thing to do.  We make it possible anyway.\n   */\n  GC_reclaim_all((GC_stop_func)0, FALSE);\n#elif defined(ENABLE_DISCLAIM)\n  /*\n   * However, make sure to clear reclaimable objects of kinds with\n   * unconditional marking enabled before we do any significant\n   * marking work.\n   */\n  GC_reclaim_unconditionally_marked();\n#endif\n#if defined(PARALLEL_MARK)\n  GC_ASSERT(0 == GC_fl_builder_count);\n#endif\n}\n\nGC_INNER void\nGC_continue_reclaim(size_t lg, int kind)\n{\n  struct hblk *hbp;\n  struct obj_kind *ok = &GC_obj_kinds[kind];\n  struct hblk **rlh = ok->ok_reclaim_list;\n  void **flh;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (NULL == rlh) {\n    /* No blocks of this kind. */\n    return;\n  }\n\n  flh = &ok->ok_freelist[lg];\n  for (rlh += lg; (hbp = *rlh) != NULL;) {\n    const hdr *hhdr = HDR(hbp);\n\n    *rlh = hhdr->hb_next;\n    GC_reclaim_small_nonempty_block(hbp, hhdr->hb_sz, FALSE);\n    if (*flh != NULL) {\n      /* The appropriate free list is nonempty. */\n      break;\n    }\n  }\n}\n\nGC_INNER GC_bool\nGC_reclaim_all(GC_stop_func stop_func, GC_bool ignore_old)\n{\n  size_t lg;\n  int kind;\n  const hdr *hhdr;\n  struct hblk *hbp;\n  struct hblk **rlp;\n  struct hblk **rlh;\n#ifndef NO_CLOCK\n  CLOCK_TYPE start_time = CLOCK_TYPE_INITIALIZER;\n\n  if (GC_print_stats == VERBOSE)\n    GET_TIME(start_time);\n#endif\n  GC_ASSERT(I_HOLD_LOCK());\n\n  for (kind = 0; kind < (int)GC_n_kinds; kind++) {\n    rlp = GC_obj_kinds[kind].ok_reclaim_list;\n    if (NULL == rlp)\n      continue;\n\n    for (lg = 1; lg <= MAXOBJGRANULES; lg++) {\n      for (rlh = rlp + lg; (hbp = *rlh) != NULL;) {\n        if (stop_func != (GC_stop_func)0 && (*stop_func)()) {\n          return FALSE;\n        }\n        hhdr = HDR(hbp);\n        *rlh = hhdr->hb_next;\n        if (!ignore_old || (word)hhdr->hb_last_reclaimed == GC_gc_no - 1) {\n          /*\n           * It is likely we will need it this time, too.  It has been\n           * touched recently, so this should not trigger paging.\n           */\n          GC_reclaim_small_nonempty_block(hbp, hhdr->hb_sz, FALSE);\n        }\n      }\n    }\n  }\n#ifndef NO_CLOCK\n  if (GC_print_stats == VERBOSE) {\n    CLOCK_TYPE done_time;\n\n    GET_TIME(done_time);\n    GC_verbose_log_printf(\"Disposing of reclaim lists took %lu ms %lu ns\\n\",\n                          MS_TIME_DIFF(done_time, start_time),\n                          NS_FRAC_TIME_DIFF(done_time, start_time));\n  }\n#endif\n  return TRUE;\n}\n\n#if !defined(EAGER_SWEEP) && defined(ENABLE_DISCLAIM)\n/*\n * We do an eager sweep on heap blocks where unconditional marking has\n * been enabled, so that any reclaimable objects have been reclaimed\n * before we start marking.  This is a simplified `GC_reclaim_all`\n * restricted to kinds where `ok_mark_unconditionally` is `TRUE`.\n */\nSTATIC void\nGC_reclaim_unconditionally_marked(void)\n{\n  int kind;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  for (kind = 0; kind < (int)GC_n_kinds; kind++) {\n    size_t lg;\n    struct obj_kind *ok = &GC_obj_kinds[kind];\n    struct hblk **rlp = ok->ok_reclaim_list;\n\n    if (NULL == rlp || !ok->ok_mark_unconditionally)\n      continue;\n\n    for (lg = 1; lg <= MAXOBJGRANULES; lg++) {\n      struct hblk **rlh = rlp + lg;\n      struct hblk *hbp;\n\n      while ((hbp = *rlh) != NULL) {\n        const hdr *hhdr = HDR(hbp);\n\n        *rlh = hhdr->hb_next;\n        GC_reclaim_small_nonempty_block(hbp, hhdr->hb_sz, FALSE);\n      }\n    }\n  }\n}\n#endif /* !EAGER_SWEEP && ENABLE_DISCLAIM */\n\nstruct enumerate_reachable_s {\n  GC_reachable_object_proc proc;\n  void *client_data;\n};\n\nSTATIC void GC_CALLBACK\nGC_do_enumerate_reachable_objects(struct hblk *hbp, void *ed_ptr)\n{\n  const hdr *hhdr = HDR(hbp);\n  ptr_t p, plim;\n  const struct enumerate_reachable_s *ped\n      = (struct enumerate_reachable_s *)ed_ptr;\n  size_t sz = hhdr->hb_sz;\n  size_t bit_no;\n\n  if (GC_block_empty(hhdr))\n    return;\n\n  p = hbp->hb_body;\n  if (sz > MAXOBJBYTES) {\n    /* The case of 1 big object. */\n    plim = p;\n  } else {\n    plim = p + HBLKSIZE - sz;\n  }\n  /* Go through all objects in the block. */\n  for (bit_no = 0; ADDR_GE(plim, p); bit_no += MARK_BIT_OFFSET(sz), p += sz) {\n    if (mark_bit_from_hdr(hhdr, bit_no)) {\n      ped->proc(p, sz, ped->client_data);\n    }\n  }\n}\n\nGC_API void GC_CALL\nGC_enumerate_reachable_objects_inner(GC_reachable_object_proc proc,\n                                     void *client_data)\n{\n  struct enumerate_reachable_s ed;\n\n  GC_ASSERT(I_HOLD_READER_LOCK());\n  ed.proc = proc;\n  ed.client_data = client_data;\n  GC_apply_to_all_blocks(GC_do_enumerate_reachable_objects, &ed);\n}\n\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1999-2000 by Hewlett-Packard Company.  All rights reserved.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n/*\n * Some simple primitives for allocation with explicit type information.\n * Simple objects are allocated such that they contain a `GC_descr` at the\n * end (in the last allocated word).  This descriptor may be a procedure\n * which then examines an extended descriptor passed as its environment.\n *\n * Arrays are treated as simple objects if they have sufficiently simple\n * structure.  Otherwise they are allocated from an array kind that supplies\n * a special mark procedure.  These arrays contain a pointer to a\n * `complex_descriptor` as their last \"pointer-sized\" word.\n * This is done because the environment field is too small, and the collector\n * must trace the `complex_descriptor`.\n *\n * Note that descriptors inside objects may appear cleared, if we encounter\n * a false reference to an object on a free list.  In the case of a simple\n * object, this is OK, since a zero descriptor corresponds to examining no\n * fields.  In the `complex_descriptor` case, we explicitly check for that\n * case.\n *\n * Note: major parts of this code have not been tested at all and are not\n * testable, since they are not accessible through the current interface.\n */\n\n#include \"gc/gc_typed.h\"\n\n/* Object kind for objects with indirect (possibly extended) descriptors. */\nSTATIC int GC_explicit_kind = 0;\n\n/*\n * Object kind for objects with complex descriptors and\n * `GC_array_mark_proc`.\n */\nSTATIC int GC_array_kind = 0;\n\n#define ED_INITIAL_SIZE 100\n\n/* Indices of the typed mark procedures. */\nSTATIC unsigned GC_typed_mark_proc_index = 0;\nSTATIC unsigned GC_array_mark_proc_index = 0;\n\nSTATIC void\nGC_push_typed_structures_proc(void)\n{\n  GC_PUSH_ALL_SYM(GC_ext_descriptors);\n}\n\n/*\n * Add a multi-word bitmap to `GC_ext_descriptors` arrays.\n * Returns starting index on success, -1 otherwise.\n */\nSTATIC GC_signed_word\nGC_add_ext_descriptor(const word *bm, size_t nbits)\n{\n  GC_signed_word result;\n  size_t i;\n  size_t nwords = divWORDSZ(nbits + CPP_WORDSZ - 1);\n\n  LOCK();\n  while (UNLIKELY(GC_avail_descr + nwords >= GC_ed_size)) {\n    typed_ext_descr_t *newExtD;\n    size_t new_size;\n    size_t ed_size = GC_ed_size;\n\n    if (0 == ed_size) {\n      GC_ASSERT(ADDR(&GC_ext_descriptors) % ALIGNMENT == 0);\n      GC_push_typed_structures = GC_push_typed_structures_proc;\n      UNLOCK();\n      new_size = ED_INITIAL_SIZE;\n    } else {\n      UNLOCK();\n      new_size = 2 * ed_size;\n      if (new_size > MAX_ENV)\n        return -1;\n    }\n    newExtD = (typed_ext_descr_t *)GC_malloc_atomic(\n        new_size * sizeof(typed_ext_descr_t));\n    if (NULL == newExtD)\n      return -1;\n    LOCK();\n    if (ed_size == GC_ed_size) {\n      if (GC_avail_descr != 0) {\n        BCOPY(GC_ext_descriptors, newExtD,\n              GC_avail_descr * sizeof(typed_ext_descr_t));\n      }\n      GC_ed_size = new_size;\n      GC_ext_descriptors = newExtD;\n    } else {\n      /* Another thread is already resized it in the meantime. */\n    }\n  }\n  result = (GC_signed_word)GC_avail_descr;\n  for (i = 0; i < nwords - 1; i++) {\n    GC_ext_descriptors[(size_t)result + i].ed_bitmap = bm[i];\n    GC_ext_descriptors[(size_t)result + i].ed_continued = TRUE;\n  }\n  /* Clear irrelevant (highest) bits for the last element. */\n  GC_ext_descriptors[(size_t)result + i].ed_bitmap\n      = bm[i] & (GC_WORD_MAX >> (nwords * CPP_WORDSZ - nbits));\n  GC_ext_descriptors[(size_t)result + i].ed_continued = FALSE;\n  GC_avail_descr += nwords;\n  GC_ASSERT(result >= 0);\n  UNLOCK();\n  return result;\n}\n\n/* Table of bitmap descriptors for `n` pointer-long all-pointer objects. */\nSTATIC GC_descr GC_bm_table[CPP_WORDSZ / 2] = { 0 };\n\n/*\n * Return a descriptor for the concatenation of 2 objects, each one is\n * `lpw` pointers long and described by descriptor `d`.  The result is\n * known to be short enough to fit into a bitmap descriptor.\n * `d` is a `GC_DS_LENGTH` or `GC_DS_BITMAP` descriptor.\n */\nSTATIC GC_descr\nGC_double_descr(GC_descr d, size_t lpw)\n{\n  GC_ASSERT(GC_bm_table[0] == GC_DS_BITMAP); /*< `bm` table is initialized */\n  if ((d & GC_DS_TAGS) == GC_DS_LENGTH) {\n    d = GC_bm_table[BYTES_TO_PTRS(d)];\n  }\n  d |= (d & ~(GC_descr)GC_DS_TAGS) >> lpw;\n  return d;\n}\n\nSTATIC mse *GC_CALLBACK GC_typed_mark_proc(word *addr, mse *mark_stack_top,\n                                           mse *mark_stack_limit, word env);\n\nSTATIC mse *GC_CALLBACK GC_array_mark_proc(word *addr, mse *mark_stack_top,\n                                           mse *mark_stack_limit, word env);\n\nSTATIC void\nGC_init_explicit_typing(void)\n{\n  unsigned i;\n\n  /*\n   * Set up object kind with simple indirect descriptor.\n   * Descriptor is in the last `word` of the object.\n   */\n  GC_typed_mark_proc_index = GC_new_proc_inner(GC_typed_mark_proc);\n  GC_explicit_kind = (int)GC_new_kind_inner(\n      GC_new_free_list_inner(),\n      (PTRS_TO_BYTES(GC_WORD_MAX) | GC_DS_PER_OBJECT), TRUE, TRUE);\n\n  /* Set up object kind with array descriptor. */\n  GC_array_mark_proc_index = GC_new_proc_inner(GC_array_mark_proc);\n  GC_array_kind = (int)GC_new_kind_inner(\n      GC_new_free_list_inner(), GC_MAKE_PROC(GC_array_mark_proc_index, 0),\n      FALSE, TRUE);\n\n  GC_bm_table[0] = GC_DS_BITMAP;\n  for (i = 1; i < CPP_WORDSZ / 2; i++) {\n    GC_bm_table[i] = (GC_WORD_MAX << (CPP_WORDSZ - i)) | GC_DS_BITMAP;\n  }\n}\n\nSTATIC mse *GC_CALLBACK\nGC_typed_mark_proc(word *addr, mse *mark_stack_top, mse *mark_stack_limit,\n                   word env)\n{\n  word bm;\n  ptr_t current_p = (ptr_t)addr;\n  ptr_t greatest_ha = (ptr_t)GC_greatest_plausible_heap_addr;\n  ptr_t least_ha = (ptr_t)GC_least_plausible_heap_addr;\n  DECLARE_HDR_CACHE;\n\n  /* The allocator lock is held by the collection initiating thread. */\n  GC_ASSERT(GC_get_parallel() || I_HOLD_LOCK());\n  bm = GC_ext_descriptors[env].ed_bitmap;\n\n  INIT_HDR_CACHE;\n  for (; bm != 0; bm >>= 1, current_p += sizeof(ptr_t)) {\n    if (bm & 1) {\n      ptr_t q;\n\n      LOAD_PTR_OR_CONTINUE(q, current_p);\n      FIXUP_POINTER(q);\n      if (ADDR_LT(least_ha, q) && ADDR_LT(q, greatest_ha)) {\n        PUSH_CONTENTS(q, mark_stack_top, mark_stack_limit, current_p);\n      }\n    }\n  }\n  if (GC_ext_descriptors[env].ed_continued) {\n    /*\n     * Push an entry with the rest of the descriptor back onto the stack.\n     * Thus we never do too much work at once.  Note that we also cannot\n     * overflow the mark stack unless we actually mark something.\n     */\n    mark_stack_top = GC_custom_push_proc(\n        GC_MAKE_PROC(GC_typed_mark_proc_index, env + 1),\n        (ptr_t *)addr + CPP_WORDSZ, mark_stack_top, mark_stack_limit);\n  }\n  return mark_stack_top;\n}\n\nGC_API GC_descr GC_CALL\nGC_make_descriptor(const GC_word *bm, size_t len)\n{\n  GC_signed_word last_set_bit = (GC_signed_word)len - 1;\n  GC_descr d;\n\n#if defined(AO_HAVE_load_acquire) && defined(AO_HAVE_store_release)\n  if (UNLIKELY(!AO_load_acquire(&GC_explicit_typing_initialized))) {\n    LOCK();\n    if (!GC_explicit_typing_initialized) {\n      GC_init_explicit_typing();\n      AO_store_release(&GC_explicit_typing_initialized, TRUE);\n    }\n    UNLOCK();\n  }\n#else\n  LOCK();\n  if (UNLIKELY(!GC_explicit_typing_initialized)) {\n    GC_init_explicit_typing();\n    GC_explicit_typing_initialized = TRUE;\n  }\n  UNLOCK();\n#endif\n\n  while (last_set_bit >= 0 && !GC_get_bit(bm, (word)last_set_bit))\n    last_set_bit--;\n  if (last_set_bit < 0) {\n    /* No pointers. */\n    return 0;\n  }\n\n#if ALIGNMENT == CPP_PTRSZ / 8\n  {\n    GC_signed_word i;\n\n    for (i = 0; i < last_set_bit; i++) {\n      if (!GC_get_bit(bm, (word)i))\n        break;\n    }\n    if (i == last_set_bit) {\n      /*\n       * The initial section contains all pointers; use the length\n       * descriptor.\n       */\n      return PTRS_TO_BYTES((word)last_set_bit + 1) | GC_DS_LENGTH;\n    }\n  }\n#endif\n  if (last_set_bit < BITMAP_BITS) {\n    GC_signed_word i;\n\n    /*\n     * Hopefully the common case.  Build the bitmap descriptor (with the\n     * bits reversed).\n     */\n    d = SIGNB;\n    for (i = last_set_bit - 1; i >= 0; i--) {\n      d >>= 1;\n      if (GC_get_bit(bm, (word)i))\n        d |= SIGNB;\n    }\n    d |= GC_DS_BITMAP;\n  } else {\n    GC_signed_word index = GC_add_ext_descriptor(bm, (size_t)last_set_bit + 1);\n\n    if (UNLIKELY(index < 0)) {\n      /* Out of memory: use a conservative approximation. */\n      return PTRS_TO_BYTES((word)last_set_bit + 1) | GC_DS_LENGTH;\n    }\n#ifdef LINT2\n    if ((word)index > MAX_ENV)\n      ABORT(\"GC_add_ext_descriptor() result cannot exceed MAX_ENV\");\n#endif\n    d = GC_MAKE_PROC(GC_typed_mark_proc_index, index);\n  }\n  return d;\n}\n\nstatic void\nset_obj_descr(ptr_t op, GC_descr d)\n{\n  size_t sz;\n\n  if (UNLIKELY(NULL == op))\n    return;\n  /*\n   * It is not safe to use `GC_size_map[]` here as the table might be\n   * updated asynchronously.\n   */\n  sz = GC_size(op);\n\n  GC_ASSERT((sz & (GC_GRANULE_BYTES - 1)) == 0 && sz > sizeof(GC_descr));\n#ifdef AO_HAVE_store_release\n  AO_store_release((volatile AO_t *)&op[sz - sizeof(GC_descr)], d);\n#else\n  *(GC_descr *)&op[sz - sizeof(GC_descr)] = d;\n#endif\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_malloc_explicitly_typed(size_t lb, GC_descr d)\n{\n  ptr_t op;\n\n  GC_ASSERT(GC_explicit_typing_initialized);\n  if (UNLIKELY(lb < sizeof(ptr_t) - sizeof(GC_descr) + 1)) {\n    /* Ensure the descriptor does not occupy the first pointer place. */\n    lb = sizeof(ptr_t) - sizeof(GC_descr) + 1;\n  }\n  op = (ptr_t)GC_malloc_kind(SIZET_SAT_ADD(lb, sizeof(GC_descr) - EXTRA_BYTES),\n                             GC_explicit_kind);\n  set_obj_descr(op, d);\n  return op;\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_malloc_explicitly_typed_ignore_off_page(size_t lb, GC_descr d)\n{\n  ptr_t op;\n\n  if (lb < HBLKSIZE - sizeof(GC_descr))\n    return GC_malloc_explicitly_typed(lb, d);\n\n  GC_ASSERT(GC_explicit_typing_initialized);\n  /*\n   * Note that ignore-off-page objects with the requested size of\n   * at least `HBLKSIZE` do not have `EXTRA_BYTES` added by\n   * `GC_generic_malloc_aligned()`.\n   */\n  op = (ptr_t)GC_clear_stack(\n      GC_generic_malloc_aligned(SIZET_SAT_ADD(lb, sizeof(GC_descr)),\n                                GC_explicit_kind, IGNORE_OFF_PAGE, 0));\n  set_obj_descr(op, d);\n  return op;\n}\n\n/*\n * Array descriptors.  `GC_array_mark_proc` understands these.\n * We may eventually need to add provisions for headers and trailers.\n * Hence we provide for tree structured descriptors, though we do not\n * really use them currently.\n */\n\n/* This type describes simple array. */\nstruct LeafDescriptor {\n  word ld_tag;\n#define LEAF_TAG 1\n  /* Bytes per element; nonzero, multiple of `ALIGNMENT`. */\n  size_t ld_size;\n  /* Number of elements. */\n  size_t ld_nelements;\n  /* A simple length, bitmap, or procedure descriptor. */\n  GC_descr ld_descriptor;\n};\n\nstruct ComplexArrayDescriptor {\n  word ad_tag;\n#define ARRAY_TAG 2\n  size_t ad_nelements;\n  union ComplexDescriptor *ad_element_descr;\n};\n\nstruct SequenceDescriptor {\n  word sd_tag;\n#define SEQUENCE_TAG 3\n  union ComplexDescriptor *sd_first;\n  union ComplexDescriptor *sd_second;\n};\n\ntypedef union ComplexDescriptor {\n  struct LeafDescriptor ld;\n  struct ComplexArrayDescriptor ad;\n  struct SequenceDescriptor sd;\n} complex_descriptor;\n\nSTATIC complex_descriptor *\nGC_make_leaf_descriptor(size_t size, size_t nelements, GC_descr d)\n{\n  complex_descriptor *result\n      = (complex_descriptor *)GC_malloc_atomic(sizeof(struct LeafDescriptor));\n\n  GC_ASSERT(size != 0);\n  if (UNLIKELY(NULL == result))\n    return NULL;\n\n  result->ld.ld_tag = LEAF_TAG;\n  result->ld.ld_size = size;\n  result->ld.ld_nelements = nelements;\n  result->ld.ld_descriptor = d;\n  return result;\n}\n\nSTATIC complex_descriptor *\nGC_make_sequence_descriptor(complex_descriptor *first,\n                            complex_descriptor *second)\n{\n  /*\n   * Note: for a reason, the sanitizer runtime complains of insufficient\n   * space for `complex_descriptor` if the pointer type of `result` variable\n   * is changed to.\n   */\n  struct SequenceDescriptor *result = (struct SequenceDescriptor *)GC_malloc(\n      sizeof(struct SequenceDescriptor));\n\n  if (UNLIKELY(NULL == result))\n    return NULL;\n\n  /*\n   * Cannot result in overly conservative marking, since tags are very\n   * small integers.  Probably faster than maintaining type information.\n   */\n  result->sd_tag = SEQUENCE_TAG;\n  result->sd_first = first;\n  result->sd_second = second;\n  GC_dirty(result);\n  REACHABLE_AFTER_DIRTY(first);\n  REACHABLE_AFTER_DIRTY(second);\n  return (complex_descriptor *)result;\n}\n\n#define NO_MEM (-1)\n#define SIMPLE 0\n#define LEAF 1\n#define COMPLEX 2\n\n/*\n * Build a descriptor for an array with `nelements` elements, each of\n * which can be described by a simple descriptor `d`.\n * We try to optimize some common cases.  If the result is `COMPLEX`,\n * a `complex_descriptor *` value is returned in `*pcomplex_d`.\n * If the result is `LEAF`, then a `LeafDescriptor` value is built in the\n * structure pointed to by `pleaf`.  The tag in the `*pleaf` structure\n * is not set.  If the result is `SIMPLE`, then a `GC_descr` value is\n * returned in `*psimple_d`.  If the result is `NO_MEM`, then we failed\n * to allocate the descriptor.  The implementation assumes `GC_DS_LENGTH`\n * is 0.  `*pleaf`, `*pcomplex_d` and `*psimple_d` may be used as\n * temporaries during the construction.\n */\nSTATIC int\nGC_make_array_descriptor(size_t nelements, size_t size, GC_descr d,\n                         GC_descr *psimple_d, complex_descriptor **pcomplex_d,\n                         struct LeafDescriptor *pleaf)\n{\n  /*\n   * For larger arrays, we try to combine descriptors of adjacent\n   * descriptors to speed up marking, and to reduce the amount of space\n   * needed on the mark stack.\n   */\n#define OPT_THRESHOLD 50\n\n  GC_ASSERT(size != 0);\n  if ((d & GC_DS_TAGS) == GC_DS_LENGTH) {\n    if (d == (GC_descr)size) {\n      /* Note: no overflow is guaranteed by caller. */\n      *psimple_d = nelements * d;\n      return SIMPLE;\n    } else if (0 == d) {\n      *psimple_d = 0;\n      return SIMPLE;\n    }\n  }\n\n  if (nelements <= OPT_THRESHOLD) {\n    if (nelements <= 1) {\n      *psimple_d = nelements == 1 ? d : 0;\n      return SIMPLE;\n    }\n  } else if (size <= BITMAP_BITS / 2 && (d & GC_DS_TAGS) != GC_DS_PROC\n             && (size & (sizeof(ptr_t) - 1)) == 0) {\n    complex_descriptor *one_element, *beginning;\n    int result = GC_make_array_descriptor(\n        nelements / 2, 2 * size, GC_double_descr(d, BYTES_TO_PTRS(size)),\n        psimple_d, pcomplex_d, pleaf);\n\n    if ((nelements & 1) == 0 || UNLIKELY(NO_MEM == result))\n      return result;\n\n    one_element = GC_make_leaf_descriptor(size, 1, d);\n    if (UNLIKELY(NULL == one_element))\n      return NO_MEM;\n\n    if (COMPLEX == result) {\n      beginning = *pcomplex_d;\n    } else {\n      beginning\n          = SIMPLE == result\n                ? GC_make_leaf_descriptor(size, 1, *psimple_d)\n                : GC_make_leaf_descriptor(pleaf->ld_size, pleaf->ld_nelements,\n                                          pleaf->ld_descriptor);\n      if (UNLIKELY(NULL == beginning))\n        return NO_MEM;\n    }\n    *pcomplex_d = GC_make_sequence_descriptor(beginning, one_element);\n    if (UNLIKELY(NULL == *pcomplex_d))\n      return NO_MEM;\n\n    return COMPLEX;\n  }\n\n  pleaf->ld_size = size;\n  pleaf->ld_nelements = nelements;\n  pleaf->ld_descriptor = d;\n  return LEAF;\n}\n\nstruct GC_calloc_typed_descr_s {\n  complex_descriptor *complex_d; /*< the first field, the only pointer */\n  struct LeafDescriptor leaf;\n  GC_descr simple_d;\n  word alloc_lb;             /*< of `size_t` type actually */\n  GC_signed_word descr_type; /*< of `int` type actually */\n};\n\nGC_API int GC_CALL\nGC_calloc_prepare_explicitly_typed(struct GC_calloc_typed_descr_s *pctd,\n                                   size_t ctd_sz, size_t n, size_t lb,\n                                   GC_descr d)\n{\n  GC_STATIC_ASSERT(sizeof(struct GC_calloc_typed_descr_opaque_s)\n                   == sizeof(struct GC_calloc_typed_descr_s));\n  GC_ASSERT(GC_explicit_typing_initialized);\n  GC_ASSERT(sizeof(struct GC_calloc_typed_descr_s) == ctd_sz);\n  (void)ctd_sz; /*< unused currently */\n  if (UNLIKELY(0 == lb || 0 == n))\n    lb = n = 1;\n  if (UNLIKELY((lb | n) > GC_SQRT_SIZE_MAX) /*< fast initial check */\n      && n > GC_SIZE_MAX / lb) {\n    /* `n * lb` overflows. */\n    pctd->alloc_lb = GC_SIZE_MAX;\n    pctd->descr_type = NO_MEM;\n    /* The rest of the fields are unset. */\n    return 0; /*< failure */\n  }\n\n  pctd->descr_type = GC_make_array_descriptor(n, lb, d, &pctd->simple_d,\n                                              &pctd->complex_d, &pctd->leaf);\n  switch (pctd->descr_type) {\n  case NO_MEM:\n  case SIMPLE:\n    pctd->alloc_lb = (word)lb * n;\n    break;\n  case LEAF:\n    pctd->alloc_lb = SIZET_SAT_ADD(\n        lb * n, (BYTES_TO_PTRS_ROUNDUP(sizeof(struct LeafDescriptor)) + 1)\n                        * sizeof(ptr_t)\n                    - EXTRA_BYTES);\n    break;\n  case COMPLEX:\n    pctd->alloc_lb = SIZET_SAT_ADD(lb * n, sizeof(ptr_t) - EXTRA_BYTES);\n    break;\n  }\n  return 1; /*< success */\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_calloc_do_explicitly_typed(const struct GC_calloc_typed_descr_s *pctd,\n                              size_t ctd_sz)\n{\n  void *op;\n  size_t lpw_m1;\n\n  GC_ASSERT(sizeof(struct GC_calloc_typed_descr_s) == ctd_sz);\n  (void)ctd_sz; /*< unused currently */\n  switch (pctd->descr_type) {\n  case NO_MEM:\n    return (*GC_get_oom_fn())((size_t)pctd->alloc_lb);\n  case SIMPLE:\n    return GC_malloc_explicitly_typed((size_t)pctd->alloc_lb, pctd->simple_d);\n  case LEAF:\n  case COMPLEX:\n    break;\n  default:\n    ABORT_RET(\"Bad descriptor type\");\n    return NULL;\n  }\n  op = GC_malloc_kind((size_t)pctd->alloc_lb, GC_array_kind);\n  if (UNLIKELY(NULL == op))\n    return NULL;\n\n  lpw_m1 = BYTES_TO_PTRS(GC_size(op)) - 1;\n  if (pctd->descr_type == LEAF) {\n    /* Set up the descriptor inside the object itself. */\n    struct LeafDescriptor *lp\n        = (struct LeafDescriptor *)((ptr_t *)op + lpw_m1\n                                    - BYTES_TO_PTRS_ROUNDUP(\n                                        sizeof(struct LeafDescriptor)));\n\n    lp->ld_tag = LEAF_TAG;\n    lp->ld_size = pctd->leaf.ld_size;\n    lp->ld_nelements = pctd->leaf.ld_nelements;\n    lp->ld_descriptor = pctd->leaf.ld_descriptor;\n    /*\n     * Hold the allocator lock (in the reader mode which should be enough)\n     * while writing the descriptor `word` to the object to ensure that\n     * the descriptor contents are seen by `GC_array_mark_proc` as expected.\n     */\n\n    /*\n     * TODO: It should be possible to replace locking with the atomic\n     * operations (with the release barrier here) but, in this case,\n     * avoiding the acquire barrier in `GC_array_mark_proc` seems to\n     * be tricky as `GC_mark_some` might be invoked with the world running.\n     */\n    READER_LOCK();\n    ((struct LeafDescriptor **)op)[lpw_m1] = lp;\n    READER_UNLOCK_RELEASE();\n  } else {\n#ifndef GC_NO_FINALIZATION\n    READER_LOCK();\n    ((complex_descriptor **)op)[lpw_m1] = pctd->complex_d;\n    READER_UNLOCK_RELEASE();\n\n    GC_dirty((ptr_t *)op + lpw_m1);\n    REACHABLE_AFTER_DIRTY(pctd->complex_d);\n\n    /*\n     * Make sure the descriptor is cleared once there is any danger\n     * it may have been collected.\n     */\n    if (UNLIKELY(\n            GC_general_register_disappearing_link((void **)op + lpw_m1, op)\n            == GC_NO_MEMORY))\n#endif\n    {\n      /* Could not register it due to lack of memory.  Punt. */\n      return (*GC_get_oom_fn())((size_t)pctd->alloc_lb);\n    }\n  }\n  return op;\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_calloc_explicitly_typed(size_t n, size_t lb, GC_descr d)\n{\n  struct GC_calloc_typed_descr_s ctd;\n\n  (void)GC_calloc_prepare_explicitly_typed(&ctd, sizeof(ctd), n, lb, d);\n  return GC_calloc_do_explicitly_typed(&ctd, sizeof(ctd));\n}\n\n/*\n * Return the size of the object described by `complex_d`.\n * It would be faster to store this directly, or to compute it as part\n * of `GC_push_complex_descriptor`, but hopefully it does not matter.\n */\nSTATIC size_t\nGC_descr_obj_size(complex_descriptor *complex_d)\n{\n  switch (complex_d->ad.ad_tag) {\n  case LEAF_TAG:\n    return complex_d->ld.ld_nelements * complex_d->ld.ld_size;\n  case ARRAY_TAG:\n    return complex_d->ad.ad_nelements\n           * GC_descr_obj_size(complex_d->ad.ad_element_descr);\n  case SEQUENCE_TAG:\n    return GC_descr_obj_size(complex_d->sd.sd_first)\n           + GC_descr_obj_size(complex_d->sd.sd_second);\n  default:\n    ABORT_RET(\"Bad complex descriptor\");\n    return 0;\n  }\n}\n\n/*\n * Push descriptors for the object with the complex descriptor onto\n * the mark stack.  Return `NULL` if the mark stack overflowed.\n */\nSTATIC mse *\nGC_push_complex_descriptor(ptr_t current, complex_descriptor *complex_d,\n                           mse *msp, mse *msl)\n{\n  size_t i, nelements;\n  size_t sz;\n  GC_descr d;\n  complex_descriptor *element_descr;\n\n  switch (complex_d->ad.ad_tag) {\n  case LEAF_TAG:\n    d = complex_d->ld.ld_descriptor;\n    nelements = complex_d->ld.ld_nelements;\n    sz = complex_d->ld.ld_size;\n\n    if (UNLIKELY(msl - msp <= (GC_signed_word)nelements))\n      return NULL;\n    GC_ASSERT(sz != 0);\n    for (i = 0; i < nelements; i++) {\n      msp++;\n      msp->mse_start = current;\n      msp->mse_descr = d;\n      current += sz;\n    }\n    break;\n  case ARRAY_TAG:\n    element_descr = complex_d->ad.ad_element_descr;\n    nelements = complex_d->ad.ad_nelements;\n    sz = GC_descr_obj_size(element_descr);\n    GC_ASSERT(sz != 0 || 0 == nelements);\n    for (i = 0; i < nelements; i++) {\n      msp = GC_push_complex_descriptor(current, element_descr, msp, msl);\n      if (UNLIKELY(NULL == msp))\n        return NULL;\n      current += sz;\n    }\n    break;\n  case SEQUENCE_TAG:\n    sz = GC_descr_obj_size(complex_d->sd.sd_first);\n    msp = GC_push_complex_descriptor(current, complex_d->sd.sd_first, msp,\n                                     msl);\n    if (UNLIKELY(NULL == msp))\n      return NULL;\n    GC_ASSERT(sz != 0);\n    current += sz;\n    msp = GC_push_complex_descriptor(current, complex_d->sd.sd_second, msp,\n                                     msl);\n    break;\n  default:\n    ABORT(\"Bad complex descriptor\");\n  }\n  return msp;\n}\n\nGC_ATTR_NO_SANITIZE_THREAD\nstatic complex_descriptor *\nget_complex_descr(ptr_t *p, size_t lpw)\n{\n  return (complex_descriptor *)p[lpw - 1];\n}\n\n/* Used by `GC_calloc_do_explicitly_typed()` via `GC_array_kind`. */\nSTATIC mse *GC_CALLBACK\nGC_array_mark_proc(word *addr, mse *mark_stack_top, mse *mark_stack_limit,\n                   word env)\n{\n  size_t sz = HDR(addr)->hb_sz;\n  size_t lpw = BYTES_TO_PTRS(sz);\n  complex_descriptor *complex_d = get_complex_descr((ptr_t *)addr, lpw);\n  mse *orig_mark_stack_top = mark_stack_top;\n  mse *new_mark_stack_top;\n\n  UNUSED_ARG(env);\n  if (NULL == complex_d) {\n    /* Found a reference to a free-list entry.  Ignore it. */\n    return orig_mark_stack_top;\n  }\n  /*\n   * In-use counts were already updated when array descriptor was pushed.\n   * Here we only replace it by subobject descriptors, so no update is\n   * necessary.\n   */\n  new_mark_stack_top = GC_push_complex_descriptor(\n      (ptr_t)addr, complex_d, mark_stack_top, mark_stack_limit - 1);\n  if (NULL == new_mark_stack_top) {\n    /* Explicitly instruct Clang Static Analyzer that pointer is non-`NULL`. */\n    if (NULL == mark_stack_top) {\n      ABORT(\"Bad mark_stack_top\");\n    }\n\n    /*\n     * Does not fit.  Conservatively push the whole array as a unit and\n     * request a mark stack expansion.  This cannot cause a mark stack\n     * overflow, since it replaces the original array entry.\n     */\n#ifdef PARALLEL_MARK\n    /* We might be using a `local_mark_stack` in the parallel collection. */\n    if (GC_mark_stack + GC_mark_stack_size == mark_stack_limit)\n#endif\n    {\n      GC_mark_stack_too_small = TRUE;\n    }\n    new_mark_stack_top = orig_mark_stack_top + 1;\n    new_mark_stack_top->mse_start = (ptr_t)addr;\n    new_mark_stack_top->mse_descr = sz | GC_DS_LENGTH;\n  } else {\n    /* Push descriptor itself. */\n    new_mark_stack_top++;\n    new_mark_stack_top->mse_start = (ptr_t)((ptr_t *)addr + lpw - 1);\n    new_mark_stack_top->mse_descr = sizeof(ptr_t) | GC_DS_LENGTH;\n  }\n  return new_mark_stack_top;\n}\n\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#include <limits.h>\n#include <stdarg.h>\n\n#if defined(SOLARIS) && defined(THREADS)\n#  include <sys/syscall.h>\n#endif\n\n#if defined(UNIX_LIKE) || defined(CYGWIN32) || defined(SYMBIAN) \\\n    || (defined(CONSOLE_LOG) && defined(MSWIN32))\n#  include <fcntl.h>\n#  include <sys/stat.h>\n#endif\n\n#if defined(CONSOLE_LOG) && defined(MSWIN32) && !defined(__GNUC__)\n#  include <io.h>\n#endif\n\n#ifdef NONSTOP\n#  include <floss.h>\n#endif\n\n#ifdef THREADS\n#  if defined(SN_TARGET_PSP2)\nGC_INNER WapiMutex GC_allocate_ml_PSP2 = { 0, NULL };\n#  elif defined(GC_DEFN_ALLOCATE_ML) && !defined(USE_RWLOCK) \\\n      || defined(SN_TARGET_PS3)\n#    include <pthread.h>\nGC_INNER pthread_mutex_t GC_allocate_ml;\n#  else\n/*\n * For other platforms with threads, the allocator lock and, possibly,\n * `GC_lock_holder` are defined in the thread support code.\n */\n#  endif\n#endif /* THREADS */\n\n#ifdef DYNAMIC_LOADING\n/*\n * We need to register the main data segment.  Returns `TRUE` unless\n * this is done implicitly as part of dynamic library registration.\n */\n#  define GC_REGISTER_MAIN_STATIC_DATA() GC_register_main_static_data()\n#elif defined(GC_DONT_REGISTER_MAIN_STATIC_DATA)\n#  define GC_REGISTER_MAIN_STATIC_DATA() FALSE\n#else\n/*\n * Do not unnecessarily call `GC_register_main_static_data()` in case\n * `dyn_load.c` file is not linked in.\n */\n#  define GC_REGISTER_MAIN_STATIC_DATA() TRUE\n#endif\n\n#ifdef NEED_CANCEL_DISABLE_COUNT\n__thread unsigned char GC_cancel_disable_count = 0;\n#endif\n\nstruct _GC_arrays GC_arrays /* `= { 0 }` */;\n\nGC_INNER unsigned GC_n_mark_procs = GC_RESERVED_MARK_PROCS;\n\nGC_INNER unsigned GC_n_kinds = GC_N_KINDS_INITIAL_VALUE;\n\nptr_t GC_stackbottom = 0;\n\n#if defined(E2K) && defined(THREADS) || defined(IA64)\nGC_INNER ptr_t GC_register_stackbottom = NULL;\n#endif\n\nint GC_dont_gc = FALSE;\n\nint GC_dont_precollect = FALSE;\n\nGC_bool GC_quiet = 0; /*< used also in `msvc_dbg.c` file */\n\n#if !defined(NO_CLOCK) || !defined(SMALL_CONFIG)\nGC_INNER int GC_print_stats = 0;\n#endif\n\n#ifdef MAKE_BACK_GRAPH\n#  ifdef GC_PRINT_BACK_HEIGHT\nGC_INNER GC_bool GC_print_back_height = TRUE;\n#  else\nGC_INNER GC_bool GC_print_back_height = FALSE;\n#  endif\n#endif\n\n#ifndef NO_DEBUGGING\n#  ifdef GC_DUMP_REGULARLY\nGC_INNER GC_bool GC_dump_regularly = TRUE;\n#  else\nGC_INNER GC_bool GC_dump_regularly = FALSE;\n#  endif\n#  ifndef NO_CLOCK\n/* The time that the collector was initialized at. */\nSTATIC CLOCK_TYPE GC_init_time = CLOCK_TYPE_INITIALIZER;\n#  endif\n#endif /* !NO_DEBUGGING */\n\n#ifdef KEEP_BACK_PTRS\nGC_INNER long GC_backtraces = 0;\n#endif\n\n#ifdef FIND_LEAK\nint GC_find_leak = 1;\n#else\nint GC_find_leak = 0;\n#endif\n\n#if !defined(NO_FIND_LEAK) && !defined(SHORT_DBG_HDRS)\n#  ifdef GC_FINDLEAK_DELAY_FREE\nGC_INNER GC_bool GC_findleak_delay_free = TRUE;\n#  else\nGC_INNER GC_bool GC_findleak_delay_free = FALSE;\n#  endif\n#endif /* !NO_FIND_LEAK && !SHORT_DBG_HDRS */\n\n#ifdef ALL_INTERIOR_POINTERS\nint GC_all_interior_pointers = 1;\n#else\nint GC_all_interior_pointers = 0;\n#endif\n\n#ifdef FINALIZE_ON_DEMAND\nint GC_finalize_on_demand = 1;\n#else\nint GC_finalize_on_demand = 0;\n#endif\n\n#ifdef JAVA_FINALIZATION\nint GC_java_finalization = 1;\n#else\nint GC_java_finalization = 0;\n#endif\n\n/* All accesses to it should be synchronized to avoid data race. */\nGC_finalizer_notifier_proc GC_finalizer_notifier\n    = (GC_finalizer_notifier_proc)0;\n\n#ifdef GC_FORCE_UNMAP_ON_GCOLLECT\nGC_INNER GC_bool GC_force_unmap_on_gcollect = TRUE;\n#else\nGC_INNER GC_bool GC_force_unmap_on_gcollect = FALSE;\n#endif\n\n#ifndef GC_LARGE_ALLOC_WARN_INTERVAL\n#  define GC_LARGE_ALLOC_WARN_INTERVAL 5\n#endif\n\n#ifndef NO_BLACK_LISTING\nGC_INNER long GC_large_alloc_warn_interval = GC_LARGE_ALLOC_WARN_INTERVAL;\n#endif\n\nSTATIC void *GC_CALLBACK\nGC_default_oom_fn(size_t bytes_requested)\n{\n  UNUSED_ARG(bytes_requested);\n  return NULL;\n}\n\n/* All accesses to it should be synchronized to avoid data race. */\nGC_oom_func GC_oom_fn = GC_default_oom_fn;\n\n#ifdef CAN_HANDLE_FORK\n#  ifdef HANDLE_FORK\nGC_INNER int GC_handle_fork = 1;\n#  else\nGC_INNER int GC_handle_fork = FALSE;\n#  endif\n\n#elif !defined(HAVE_NO_FORK)\nGC_API void GC_CALL\nGC_atfork_prepare(void)\n{\n#  ifdef THREADS\n  ABORT(\"fork() handling unsupported\");\n#  endif\n}\n\nGC_API void GC_CALL\nGC_atfork_parent(void)\n{\n  /* Empty. */\n}\n\nGC_API void GC_CALL\nGC_atfork_child(void)\n{\n  /* Empty. */\n}\n#endif /* !CAN_HANDLE_FORK && !HAVE_NO_FORK */\n\nGC_API void GC_CALL\nGC_set_handle_fork(int value)\n{\n#ifdef CAN_HANDLE_FORK\n  if (!GC_is_initialized) {\n    /* Map all negative values except for -1 to a positive one. */\n    GC_handle_fork = value >= -1 ? value : 1;\n  }\n#elif defined(THREADS) || (defined(DARWIN) && defined(MPROTECT_VDB))\n  if (!GC_is_initialized && value) {\n#  ifndef SMALL_CONFIG\n    /* Initialize `GC_manual_vdb` and `GC_stderr`. */\n    GC_init();\n#    ifndef THREADS\n    if (GC_manual_vdb)\n      return;\n#    endif\n#  endif\n    ABORT(\"fork() handling unsupported\");\n  }\n#else\n  /* No at-fork handler is needed in the single-threaded mode. */\n  UNUSED_ARG(value);\n#endif\n}\n\n/*\n * Set things up so that `GC_size_map[i] >= granules(i)`, but not too\n * much bigger and so that `GC_size_map` contains relatively few\n * distinct entries.  This was originally stolen from Russ Atkinson's\n * Cedar quantization algorithm (but we precompute it).\n */\nSTATIC void\nGC_init_size_map(void)\n{\n  size_t i = 1;\n\n  /* Map size 0 to something bigger; this avoids problems at lower levels. */\n  GC_size_map[0] = 1;\n\n  for (; i <= GRANULES_TO_BYTES(GC_TINY_FREELISTS - 1) - EXTRA_BYTES; i++) {\n    GC_size_map[i] = ALLOC_REQUEST_GRANS(i);\n#ifndef _MSC_VER\n    /* Seems to tickle bug in VC++ 2008 for x86_64. */\n    GC_ASSERT(GC_size_map[i] < GC_TINY_FREELISTS);\n#endif\n  }\n  /* We leave the rest of the array to be filled in on demand. */\n}\n\n/*\n * The following is a gross hack to deal with a problem that can occur\n * on machines that are sloppy about stack frame sizes, notably SPARC.\n * Bogus pointers may be written to the stack and not cleared for\n * a LONG time, because they always fall into holes in stack frames\n * that are not written.  We partially address this by clearing\n * sections of the stack whenever we get control.\n */\n\n#ifndef SMALL_CLEAR_SIZE\n/* Clear this many words of the stack every time. */\n#  define SMALL_CLEAR_SIZE 256\n#endif\n\n#if defined(ALWAYS_SMALL_CLEAR_STACK) || defined(STACK_NOT_SCANNED)\nGC_API void *GC_CALL\nGC_clear_stack(void *arg)\n{\n#  ifndef STACK_NOT_SCANNED\n  volatile ptr_t dummy[SMALL_CLEAR_SIZE];\n\n  BZERO(CAST_AWAY_VOLATILE_PVOID(dummy), sizeof(dummy));\n#  endif\n  return arg;\n}\n#else\n\n#  ifdef THREADS\n/* Clear this much sometimes. */\n#    define BIG_CLEAR_SIZE 2048\n#  else\n#    define DEGRADE_RATE 50\n\nSTATIC word GC_bytes_allocd_at_reset = 0;\n\n/* `GC_gc_no` value when we last did this. */\nSTATIC word GC_stack_last_cleared = 0;\n#  endif\n\n#  if defined(__APPLE_CC__) && !GC_CLANG_PREREQ(6, 0)\n#    define CLEARSTACK_LIMIT_MODIFIER volatile /*< to workaround some bug */\n#  else\n#    define CLEARSTACK_LIMIT_MODIFIER /*< empty */\n#  endif\n\nEXTERN_C_BEGIN\nvoid *GC_clear_stack_inner(void *, CLEARSTACK_LIMIT_MODIFIER ptr_t);\nEXTERN_C_END\n\n#  ifndef ASM_CLEAR_CODE\n/*\n * Clear the stack up to about `limit`.  Return `arg`.  This function is\n * not `static` because it could also be erroneously defined in `.S` file,\n * so this error would be caught by the linker.\n */\nvoid *\nGC_clear_stack_inner(void *arg, CLEARSTACK_LIMIT_MODIFIER ptr_t limit)\n{\n#    define CLEAR_SIZE 213 /*< granularity */\n  volatile ptr_t dummy[CLEAR_SIZE];\n\n  BZERO(CAST_AWAY_VOLATILE_PVOID(dummy), sizeof(dummy));\n  if (HOTTER_THAN((/* no volatile */ ptr_t)limit, GC_approx_sp())) {\n    (void)GC_clear_stack_inner(arg, limit);\n  }\n  /*\n   * Make sure the recursive call is not a tail call, and the `bzero` call\n   * is not recognized as dead code.\n   */\n#    if defined(CPPCHECK)\n  GC_noop1(ADDR(dummy[0]));\n#    else\n  GC_noop1(COVERT_DATAFLOW(ADDR(dummy)));\n#    endif\n  return arg;\n}\n#  endif /* !ASM_CLEAR_CODE */\n\n#  ifdef THREADS\n/* Used to occasionally clear a bigger chunk. */\n/* TODO: Should be more random than it is... */\nstatic unsigned\nnext_random_no(void)\n{\n#    ifdef AO_HAVE_fetch_and_add1\n  static volatile AO_t random_no;\n\n  return (unsigned)AO_fetch_and_add1(&random_no) % 13;\n#    else\n  static unsigned random_no = 0;\n\n  return (random_no++) % 13;\n#    endif\n}\n#  endif /* THREADS */\n\nGC_API void *GC_CALL\nGC_clear_stack(void *arg)\n{\n  /* Note: this is hotter than the actual stack pointer. */\n  ptr_t sp = GC_approx_sp();\n#  ifdef THREADS\n  volatile ptr_t dummy[SMALL_CLEAR_SIZE];\n#  endif\n\n  /*\n   * Extra bytes we clear every time.  This clears our own activation\n   * record, and should cause more frequent clearing near the cold end\n   * of the stack, a good thing.\n   */\n#  define SLOP 400\n\n  /*\n   * We make `GC_high_water` this much hotter than we really saw it,\n   * to cover for the GC noise above our current frame.\n   */\n#  define GC_SLOP 4000\n\n  /*\n   * We restart the clearing process after this many bytes of allocation.\n   * Otherwise very heavily recursive programs with sparse stacks may\n   * result in heaps that grow almost without bounds.  As the heap gets\n   * larger, collection frequency decreases, thus clearing frequency\n   * would decrease, thus more junk remains accessible, thus the heap\n   * gets larger...\n   */\n#  define CLEAR_THRESHOLD 100000\n\n#  ifdef THREADS\n  if (next_random_no() == 0) {\n    ptr_t limit = sp;\n\n    MAKE_HOTTER(limit, BIG_CLEAR_SIZE * sizeof(ptr_t));\n    /*\n     * Make it sufficiently aligned for assembly implementations\n     * of `GC_clear_stack_inner`.\n     */\n    limit = PTR_ALIGN_DOWN(limit, 0x10);\n    return GC_clear_stack_inner(arg, limit);\n  }\n  BZERO(CAST_AWAY_VOLATILE_PVOID(dummy), sizeof(dummy));\n#  else\n  if (GC_gc_no != GC_stack_last_cleared) {\n    /* Start things over, so we clear the entire stack again. */\n    if (UNLIKELY(NULL == GC_high_water))\n      GC_high_water = (ptr_t)GC_stackbottom;\n    GC_min_sp = GC_high_water;\n    GC_stack_last_cleared = GC_gc_no;\n    GC_bytes_allocd_at_reset = GC_bytes_allocd;\n  }\n  /* Adjust `GC_high_water`. */\n  GC_ASSERT(GC_high_water != NULL);\n  MAKE_COOLER(GC_high_water, PTRS_TO_BYTES(DEGRADE_RATE) + GC_SLOP);\n  if (HOTTER_THAN(sp, GC_high_water))\n    GC_high_water = sp;\n  MAKE_HOTTER(GC_high_water, GC_SLOP);\n  {\n    ptr_t limit = GC_min_sp;\n\n    MAKE_HOTTER(limit, SLOP);\n    if (HOTTER_THAN(limit, sp)) {\n      limit = PTR_ALIGN_DOWN(limit, 0x10);\n      GC_min_sp = sp;\n      return GC_clear_stack_inner(arg, limit);\n    }\n  }\n  if (GC_bytes_allocd - GC_bytes_allocd_at_reset > CLEAR_THRESHOLD) {\n    /* Restart clearing process, but limit how much clearing we do. */\n    GC_min_sp = sp;\n    MAKE_HOTTER(GC_min_sp, CLEAR_THRESHOLD / 4);\n    if (HOTTER_THAN(GC_min_sp, GC_high_water))\n      GC_min_sp = GC_high_water;\n    GC_bytes_allocd_at_reset = GC_bytes_allocd;\n  }\n#  endif\n  return arg;\n}\n\n#endif /* !ALWAYS_SMALL_CLEAR_STACK && !STACK_NOT_SCANNED */\n\nGC_API void *GC_CALL\nGC_base(void *p)\n{\n  ptr_t r = (ptr_t)p;\n  struct hblk *h;\n  bottom_index *bi;\n  hdr *hhdr;\n  ptr_t limit;\n  size_t sz;\n\n  if (UNLIKELY(!GC_is_initialized))\n    return NULL;\n  h = HBLKPTR(r);\n  GET_BI(r, bi);\n  hhdr = HDR_FROM_BI(bi, r);\n  if (NULL == hhdr)\n    return NULL;\n\n  /*\n   * If it is a pointer to the middle of a large object, then move it\n   * to the beginning.\n   */\n  if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {\n    h = GC_find_starting_hblk(h, &hhdr);\n    r = (ptr_t)h;\n  }\n  if (HBLK_IS_FREE(hhdr))\n    return NULL;\n\n  /* Make sure `r` points to the beginning of the object. */\n  r = PTR_ALIGN_DOWN(r, sizeof(ptr_t));\n\n  sz = hhdr->hb_sz;\n  r -= HBLKDISPL(r) % sz;\n  limit = r + sz;\n  if ((ADDR_LT((ptr_t)(h + 1), limit) && sz <= HBLKSIZE)\n      || ADDR_GE((ptr_t)p, limit))\n    return NULL;\n\n  return r;\n}\n\nGC_API int GC_CALL\nGC_is_heap_ptr(const void *p)\n{\n  bottom_index *bi;\n\n  GC_ASSERT(GC_is_initialized);\n  GET_BI(p, bi);\n  return HDR_FROM_BI(bi, p) != 0;\n}\n\nGC_API size_t GC_CALL\nGC_size(const void *p)\n{\n  const hdr *hhdr;\n\n  /* Accept `NULL` for compatibility with `malloc_usable_size()`. */\n  if (UNLIKELY(NULL == p))\n    return 0;\n\n  hhdr = HDR(p);\n  return hhdr->hb_sz;\n}\n\n/*\n * These getters remain unsynchronized for compatibility (since some clients\n * could call some of them from a GC callback holding the allocator lock).\n */\n\nGC_API size_t GC_CALL\nGC_get_heap_size(void)\n{\n  /*\n   * Ignore the memory space returned to OS (i.e. count only the space\n   * owned by the garbage collector).\n   */\n  return (size_t)(GC_heapsize - GC_unmapped_bytes);\n}\n\nGC_API size_t GC_CALL\nGC_get_obtained_from_os_bytes(void)\n{\n  return (size_t)GC_our_mem_bytes;\n}\n\nGC_API size_t GC_CALL\nGC_get_free_bytes(void)\n{\n  /* Ignore the memory space returned to OS. */\n  return (size_t)(GC_large_free_bytes - GC_unmapped_bytes);\n}\n\nGC_API size_t GC_CALL\nGC_get_unmapped_bytes(void)\n{\n  return (size_t)GC_unmapped_bytes;\n}\n\nGC_API size_t GC_CALL\nGC_get_bytes_since_gc(void)\n{\n  return (size_t)GC_bytes_allocd;\n}\n\nGC_API size_t GC_CALL\nGC_get_total_bytes(void)\n{\n  return (size_t)(GC_bytes_allocd + GC_bytes_allocd_before_gc);\n}\n\n#ifndef GC_GET_HEAP_USAGE_NOT_NEEDED\n\nGC_API size_t GC_CALL\nGC_get_size_map_at(int i)\n{\n  if ((unsigned)i > MAXOBJBYTES)\n    return GC_SIZE_MAX;\n  return GRANULES_TO_BYTES(GC_size_map[i]);\n}\n\nGC_API void GC_CALL\nGC_get_heap_usage_safe(GC_word *pheap_size, GC_word *pfree_bytes,\n                       GC_word *punmapped_bytes, GC_word *pbytes_since_gc,\n                       GC_word *ptotal_bytes)\n{\n  READER_LOCK();\n  if (pheap_size != NULL)\n    *pheap_size = GC_heapsize - GC_unmapped_bytes;\n  if (pfree_bytes != NULL)\n    *pfree_bytes = GC_large_free_bytes - GC_unmapped_bytes;\n  if (punmapped_bytes != NULL)\n    *punmapped_bytes = GC_unmapped_bytes;\n  if (pbytes_since_gc != NULL)\n    *pbytes_since_gc = GC_bytes_allocd;\n  if (ptotal_bytes != NULL)\n    *ptotal_bytes = GC_bytes_allocd + GC_bytes_allocd_before_gc;\n  READER_UNLOCK();\n}\n\n/* Fill in GC statistics provided the destination is of enough size. */\nstatic void\nfill_prof_stats(struct GC_prof_stats_s *pstats)\n{\n  pstats->heapsize_full = GC_heapsize;\n  pstats->free_bytes_full = GC_large_free_bytes;\n  pstats->unmapped_bytes = GC_unmapped_bytes;\n  pstats->bytes_allocd_since_gc = GC_bytes_allocd;\n  pstats->allocd_bytes_before_gc = GC_bytes_allocd_before_gc;\n  pstats->non_gc_bytes = GC_non_gc_bytes;\n  pstats->gc_no = GC_gc_no; /*< could be -1 */\n#  ifdef PARALLEL_MARK\n  pstats->markers_m1 = (word)((GC_signed_word)GC_markers_m1);\n#  else\n  /* A single marker. */\n  pstats->markers_m1 = 0;\n#  endif\n  pstats->bytes_reclaimed_since_gc\n      = GC_bytes_found > 0 ? (word)GC_bytes_found : 0;\n  pstats->reclaimed_bytes_before_gc = GC_reclaimed_bytes_before_gc;\n  pstats->expl_freed_bytes_since_gc = GC_bytes_freed; /*< since gc-7.7 */\n  pstats->obtained_from_os_bytes = GC_our_mem_bytes;  /*< since gc-8.2 */\n}\n\n#  include <string.h> /*< for `memset()` */\n\nGC_API size_t GC_CALL\nGC_get_prof_stats(struct GC_prof_stats_s *pstats, size_t stats_sz)\n{\n  struct GC_prof_stats_s stats;\n\n  READER_LOCK();\n  fill_prof_stats(stats_sz >= sizeof(stats) ? pstats : &stats);\n  READER_UNLOCK();\n\n  if (stats_sz == sizeof(stats)) {\n    return sizeof(stats);\n  } else if (stats_sz > sizeof(stats)) {\n    /* Fill in the remaining part with -1. */\n    memset((char *)pstats + sizeof(stats), 0xff, stats_sz - sizeof(stats));\n    return sizeof(stats);\n  } else {\n    if (LIKELY(stats_sz > 0))\n      BCOPY(&stats, pstats, stats_sz);\n    return stats_sz;\n  }\n}\n\n#  ifdef THREADS\nGC_API size_t GC_CALL\nGC_get_prof_stats_unsafe(struct GC_prof_stats_s *pstats, size_t stats_sz)\n{\n  struct GC_prof_stats_s stats;\n\n  if (stats_sz >= sizeof(stats)) {\n    fill_prof_stats(pstats);\n    if (stats_sz > sizeof(stats))\n      memset((char *)pstats + sizeof(stats), 0xff, stats_sz - sizeof(stats));\n    return sizeof(stats);\n  } else {\n    if (LIKELY(stats_sz > 0)) {\n      fill_prof_stats(&stats);\n      BCOPY(&stats, pstats, stats_sz);\n    }\n    return stats_sz;\n  }\n}\n#  endif /* THREADS */\n\n#endif /* !GC_GET_HEAP_USAGE_NOT_NEEDED */\n\n#if defined(THREADS) && !defined(SIGNAL_BASED_STOP_WORLD)\n/* The collector does not use signals to suspend and restart threads. */\n\nGC_API void GC_CALL\nGC_set_suspend_signal(int sig)\n{\n  UNUSED_ARG(sig);\n}\n\nGC_API void GC_CALL\nGC_set_thr_restart_signal(int sig)\n{\n  UNUSED_ARG(sig);\n}\n\nGC_API int GC_CALL\nGC_get_suspend_signal(void)\n{\n  return -1;\n}\n\nGC_API int GC_CALL\nGC_get_thr_restart_signal(void)\n{\n  return -1;\n}\n#endif /* THREADS && !SIGNAL_BASED_STOP_WORLD */\n\n#if !defined(_MAX_PATH) && defined(ANY_MSWIN)\n#  define _MAX_PATH MAX_PATH\n#endif\n\n#ifdef GC_READ_ENV_FILE\n/* This works for Win32/WinCE for now.  Really useful only for WinCE. */\n\n#  ifndef GC_ENVFILE_MAXLEN\n#    define GC_ENVFILE_MAXLEN 0x4000\n#  endif\n\n#  define GC_ENV_FILE_EXT \".gc.env\"\n\n/* The routine initializes `GC_envfile_content` from the `.gc.env` file. */\nSTATIC void\nGC_envfile_init(void)\n{\n#  ifdef ANY_MSWIN\n  HANDLE hFile;\n  char *content;\n  size_t ofs, len;\n  DWORD nBytesRead;\n  TCHAR path[_MAX_PATH + 0x10]; /*< buffer for file path with extension */\n  size_t bytes_to_get;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  len = (size_t)GetModuleFileName(NULL /* `hModule` */, path, _MAX_PATH + 1);\n  /* If `GetModuleFileName()` failed, then len is 0. */\n  if (len > 4 && path[len - 4] == (TCHAR)'.') {\n    /* Strip the executable file extension. */\n    len -= 4;\n  }\n  BCOPY(TEXT(GC_ENV_FILE_EXT), &path[len], sizeof(TEXT(GC_ENV_FILE_EXT)));\n  hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,\n                     NULL /* `lpSecurityAttributes` */, OPEN_EXISTING,\n                     FILE_ATTRIBUTE_NORMAL, NULL /* `hTemplateFile` */);\n  if (hFile == INVALID_HANDLE_VALUE) {\n    /* The file is absent or the operation failed. */\n    return;\n  }\n  len = (size_t)GetFileSize(hFile, NULL);\n  if (len <= 1 || len >= GC_ENVFILE_MAXLEN) {\n    CloseHandle(hFile);\n    /* Invalid file length - ignoring the file content. */\n    return;\n  }\n  /*\n   * At this execution point, `GC_setpagesize()` and `GC_init_win32()`\n   * must already be called (for `GET_MEM()` to work correctly).\n   */\n  GC_ASSERT(GC_page_size != 0);\n  bytes_to_get = ROUNDUP_PAGESIZE_IF_MMAP(len + 1);\n  content = GC_os_get_mem(bytes_to_get);\n  if (content == NULL) {\n    CloseHandle(hFile);\n    /* An allocation failure. */\n    return;\n  }\n  ofs = 0;\n  nBytesRead = (DWORD)-1L;\n  /* Last `ReadFile()` call should clear `nBytesRead` on success. */\n  while (ReadFile(hFile, content + ofs, (DWORD)(len - ofs + 1), &nBytesRead,\n                  NULL /* `lpOverlapped` */)\n         && nBytesRead != 0) {\n    if ((ofs += (size_t)nBytesRead) > len)\n      break;\n  }\n  CloseHandle(hFile);\n  if (ofs != len || nBytesRead != 0) {\n    /* TODO: Recycle content. */\n    /* Read operation has failed - ignoring the file content. */\n    return;\n  }\n  content[ofs] = '\\0';\n  while (ofs-- > 0) {\n    if (content[ofs] == '\\r' || content[ofs] == '\\n')\n      content[ofs] = '\\0';\n  }\n  GC_ASSERT(NULL == GC_envfile_content);\n  GC_envfile_length = len + 1;\n  GC_envfile_content = content;\n#  endif\n}\n\nGC_INNER char *\nGC_envfile_getenv(const char *name)\n{\n  char *p;\n  const char *end_of_content;\n  size_t namelen;\n\n#  ifndef NO_GETENV\n  /* Try the standard `getenv()` first. */\n  p = getenv(name);\n  if (p != NULL)\n    return *p != '\\0' ? p : NULL;\n#  endif\n  p = GC_envfile_content;\n  if (NULL == p) {\n    /* The `.gc.env` file is absent (or empty). */\n    return NULL;\n  }\n  namelen = strlen(name);\n  if (0 == namelen) {\n    /* A sanity check. */\n    return NULL;\n  }\n  for (end_of_content = p + GC_envfile_length;\n       ADDR_LT((ptr_t)p, (ptr_t)end_of_content); p += strlen(p) + 1) {\n    if (strncmp(p, name, namelen) == 0 && *(p += namelen) == '=') {\n      /* The match is found; skip \"=\". */\n      p++;\n      return *p != '\\0' ? p : NULL;\n    }\n    /* If not matching then skip to the next line. */\n  }\n  GC_ASSERT(p == end_of_content);\n  /* No match is found. */\n  return NULL;\n}\n#endif /* GC_READ_ENV_FILE */\n\nGC_API int GC_CALL\nGC_is_init_called(void)\n{\n  return (int)GC_is_initialized;\n}\n\n#if defined(GC_WIN32_THREADS) \\\n    && ((defined(MSWIN32) && !defined(CONSOLE_LOG)) || defined(MSWINCE))\nGC_INNER CRITICAL_SECTION GC_write_cs;\n#endif\n\n#ifndef DONT_USE_ATEXIT\nSTATIC void\nGC_exit_check(void)\n{\n  if (GC_find_leak && !GC_skip_collect_atexit) {\n#  ifdef THREADS\n    /*\n     * Check that the thread executing at-exit functions is the same as\n     * the one performed the GC initialization, otherwise the latter\n     * thread might already be dead but still registered and this, as\n     * a consequence, might cause a signal delivery fail when suspending\n     * the threads on platforms that do not guarantee `ESRCH` returned\n     * if the signal is not delivered.  It should also prevent\n     * \"Collecting from unknown thread\" abort in `GC_push_all_stacks()`.\n     */\n    if (!GC_is_main_thread() || !GC_thread_is_registered())\n      return;\n#  endif\n    GC_gcollect();\n  }\n}\n#endif /* !DONT_USE_ATEXIT */\n\n#if defined(UNIX_LIKE) && !defined(NO_DEBUGGING)\nstatic void\nlooping_handler(int sig)\n{\n  GC_err_printf(\"Caught signal %d: looping in handler\\n\", sig);\n  for (;;) {\n    /* Empty. */\n  }\n}\n\nstatic GC_bool installed_looping_handler = FALSE;\n\nstatic void\nmaybe_install_looping_handler(void)\n{\n  /*\n   * Install looping handler before the write fault handler,\n   * so we handle write faults correctly.\n   */\n  if (!installed_looping_handler && GETENV(\"GC_LOOP_ON_ABORT\") != NULL) {\n    GC_set_and_save_fault_handler(looping_handler);\n    installed_looping_handler = TRUE;\n  }\n}\n\n#else /* !UNIX_LIKE */\n#  define maybe_install_looping_handler()\n#endif\n\n#define GC_DEFAULT_STDERR_FD 2\n#ifdef KOS\n#  define GC_DEFAULT_STDOUT_FD GC_DEFAULT_STDERR_FD\n#else\n#  define GC_DEFAULT_STDOUT_FD 1\n#endif\n\n#if !defined(OS2) && !defined(GC_ANDROID_LOG) && !defined(NN_PLATFORM_CTR) \\\n    && !defined(NINTENDO_SWITCH)                                           \\\n    && (!defined(MSWIN32) || defined(CONSOLE_LOG)) && !defined(MSWINCE)\nSTATIC int GC_stdout = GC_DEFAULT_STDOUT_FD;\nSTATIC int GC_stderr = GC_DEFAULT_STDERR_FD;\nSTATIC int GC_log = GC_DEFAULT_STDERR_FD;\n\n#  ifndef MSWIN32\nGC_API void GC_CALL\nGC_set_log_fd(int fd)\n{\n  GC_log = fd;\n}\n#  endif\n#endif\n\n#ifdef MSGBOX_ON_ERROR\nSTATIC void\nGC_win32_MessageBoxA(const char *msg, const char *caption, unsigned flags)\n{\n#  ifndef DONT_USE_USER32_DLL\n  /* Use static binding to `user32.dll` file. */\n  (void)MessageBoxA(NULL, msg, caption, flags);\n#  else\n  /* This simplifies linking - resolve `MessageBoxA()` at run-time. */\n  HINSTANCE hU32 = LoadLibrary(TEXT(\"user32.dll\"));\n  if (hU32) {\n    FARPROC pfn = GetProcAddress(hU32, \"MessageBoxA\");\n    if (pfn)\n      (void)(*(int(WINAPI *)(HWND, LPCSTR, LPCSTR, UINT))(GC_funcptr_uint)pfn)(\n          NULL /* `hWnd` */, msg, caption, flags);\n    (void)FreeLibrary(hU32);\n  }\n#  endif\n}\n#endif /* MSGBOX_ON_ERROR */\n\n#if defined(THREADS) && defined(UNIX_LIKE) && !defined(NO_GETCONTEXT)\nstatic void\ncallee_saves_pushed_dummy_fn(ptr_t data, void *context)\n{\n  UNUSED_ARG(data);\n  UNUSED_ARG(context);\n}\n#endif\n\n#ifdef MANUAL_VDB\nstatic GC_bool manual_vdb_allowed = TRUE;\n#else\nstatic GC_bool manual_vdb_allowed = FALSE;\n#endif\n\nGC_API void GC_CALL\nGC_set_manual_vdb_allowed(int value)\n{\n  manual_vdb_allowed = (GC_bool)value;\n}\n\nGC_API int GC_CALL\nGC_get_manual_vdb_allowed(void)\n{\n  return (int)manual_vdb_allowed;\n}\n\nGC_API unsigned GC_CALL\nGC_get_supported_vdbs(void)\n{\n#ifdef GC_DISABLE_INCREMENTAL\n  return GC_VDB_NONE;\n#else\n#  if defined(CPPCHECK)\n  /* Workaround a warning about redundant `| 0`. */\n  volatile unsigned zero = 0;\n#  endif\n  return\n#  if defined(CPPCHECK)\n      zero\n#  else\n      0\n#  endif\n#  ifndef NO_MANUAL_VDB\n      | GC_VDB_MANUAL\n#  endif\n#  ifdef DEFAULT_VDB\n      | GC_VDB_DEFAULT\n#  endif\n#  ifdef MPROTECT_VDB\n      | GC_VDB_MPROTECT\n#  endif\n#  ifdef GWW_VDB\n      | GC_VDB_GWW\n#  endif\n#  ifdef PROC_VDB\n      | GC_VDB_PROC\n#  endif\n#  ifdef SOFT_VDB\n      | GC_VDB_SOFT\n#  endif\n      ;\n#endif\n}\n\n#ifndef GC_DISABLE_INCREMENTAL\nstatic void\nset_incremental_mode_on(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n#  ifndef NO_MANUAL_VDB\n  if (manual_vdb_allowed) {\n    GC_manual_vdb = TRUE;\n    GC_incremental = TRUE;\n  } else\n#  endif\n  /* else */ {\n    /*\n     * For `GWW_VDB` on Win32, this needs to happen before any heap memory\n     * is allocated.\n     */\n    GC_incremental = GC_dirty_init();\n  }\n}\n#endif /* !GC_DISABLE_INCREMENTAL */\n\nSTATIC word\nGC_parse_mem_size_arg(const char *str)\n{\n  word result;\n  char *endptr;\n  char ch;\n\n  if ('\\0' == *str)\n    return GC_WORD_MAX; /*< bad value */\n  result = (word)STRTOULL(str, &endptr, 10);\n  ch = *endptr;\n  if (ch != '\\0') {\n    if (*(endptr + 1) != '\\0')\n      return GC_WORD_MAX;\n    /* Allow \"k\", \"M\" or \"G\" suffix. */\n    switch (ch) {\n    case 'K':\n    case 'k':\n      result <<= 10;\n      break;\n#if CPP_WORDSZ >= 32\n    case 'M':\n    case 'm':\n      result <<= 20;\n      break;\n    case 'G':\n    case 'g':\n      result <<= 30;\n      break;\n#endif\n    default:\n      result = GC_WORD_MAX;\n    }\n  }\n  return result;\n}\n\n#define GC_LOG_STD_NAME \"gc.log\"\n\nGC_API void GC_CALL\nGC_init(void)\n{\n  word initial_heap_sz;\n  IF_CANCEL(int cancel_state;)\n\n  if (LIKELY(GC_is_initialized))\n    return;\n#ifdef REDIRECT_MALLOC\n  {\n    static GC_bool init_started = FALSE;\n\n    if (init_started)\n      ABORT(\"Redirected malloc() called during GC init\");\n    init_started = TRUE;\n  }\n#endif\n\n#if defined(GC_INITIAL_HEAP_SIZE) && !defined(CPPCHECK)\n  initial_heap_sz = GC_INITIAL_HEAP_SIZE;\n#else\n  initial_heap_sz = MINHINCR * HBLKSIZE;\n#endif\n\n  DISABLE_CANCEL(cancel_state);\n  /*\n   * Note that although we are nominally called with the allocator lock\n   * held, now it is only really acquired once a second thread is created.\n   * And the initialization code needs to run before then.  Thus we really\n   * do not hold any locks, and can safely initialize them here.\n   */\n#ifdef THREADS\n#  ifndef GC_ALWAYS_MULTITHREADED\n  GC_ASSERT(!GC_need_to_lock);\n#  endif\n  {\n#  if !defined(GC_BUILTIN_ATOMIC) && defined(HP_PA) \\\n      && (defined(USE_SPIN_LOCK) || defined(NEED_FAULT_HANDLER_LOCK))\n    AO_TS_t ts_init = AO_TS_INITIALIZER;\n\n    /* Arrays can only be initialized when declared. */\n#    ifdef USE_SPIN_LOCK\n    BCOPY(&ts_init, (/* no volatile */ void *)&GC_allocate_lock,\n          sizeof(GC_allocate_lock));\n#    endif\n#    ifdef NEED_FAULT_HANDLER_LOCK\n    BCOPY(&ts_init, (/* no volatile */ void *)&GC_fault_handler_lock,\n          sizeof(GC_fault_handler_lock));\n#    endif\n#  else\n#    ifdef USE_SPIN_LOCK\n    GC_allocate_lock = AO_TS_INITIALIZER;\n#    endif\n#    ifdef NEED_FAULT_HANDLER_LOCK\n    GC_fault_handler_lock = AO_TS_INITIALIZER;\n#    endif\n#  endif\n  }\n#  ifdef SN_TARGET_PS3\n  {\n    pthread_mutexattr_t mattr;\n\n    if (pthread_mutexattr_init(&mattr) != 0)\n      ABORT(\"pthread_mutexattr_init failed\");\n    if (pthread_mutex_init(&GC_allocate_ml, &mattr) != 0)\n      ABORT(\"pthread_mutex_init failed\");\n    (void)pthread_mutexattr_destroy(&mattr);\n  }\n#  endif\n#endif /* THREADS */\n#if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)\n#  ifndef SPIN_COUNT\n#    define SPIN_COUNT 4000\n#  endif\n#  ifdef USE_RWLOCK\n  /* TODO: Probably use `SRWLOCK_INIT` instead. */\n  InitializeSRWLock(&GC_allocate_ml);\n#  elif defined(MSWINRT_FLAVOR)\n  InitializeCriticalSectionAndSpinCount(&GC_allocate_ml, SPIN_COUNT);\n#  else\n  {\n#    ifndef MSWINCE\n    FARPROC pfn = 0;\n    HMODULE hK32 = GetModuleHandle(TEXT(\"kernel32.dll\"));\n    if (hK32)\n      pfn = GetProcAddress(hK32, \"InitializeCriticalSectionAndSpinCount\");\n    if (pfn) {\n      (*(BOOL(WINAPI *)(LPCRITICAL_SECTION, DWORD))(GC_funcptr_uint)pfn)(\n          &GC_allocate_ml, SPIN_COUNT);\n    } else\n#    endif /* !MSWINCE */\n      /* else */ InitializeCriticalSection(&GC_allocate_ml);\n  }\n#  endif\n#endif /* GC_WIN32_THREADS && !GC_PTHREADS */\n#if defined(GC_WIN32_THREADS) \\\n    && ((defined(MSWIN32) && !defined(CONSOLE_LOG)) || defined(MSWINCE))\n  InitializeCriticalSection(&GC_write_cs);\n#endif\n#if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED)\n  /* Just to set `GC_lock_holder`. */\n  LOCK();\n#endif\n#ifdef DYNAMIC_POINTER_MASK\n  if (0 == GC_pointer_mask)\n    GC_pointer_mask = GC_WORD_MAX;\n#endif\n  GC_setpagesize();\n#ifdef MSWIN32\n  GC_init_win32();\n#endif\n#ifdef GC_READ_ENV_FILE\n  GC_envfile_init();\n#endif\n#if !defined(NO_CLOCK) || !defined(SMALL_CONFIG)\n#  ifdef GC_PRINT_VERBOSE_STATS\n  /*\n   * This is useful for debugging and profiling on platforms with\n   * missing `getenv()` (like WinCE).\n   */\n  GC_print_stats = VERBOSE;\n#  else\n  if (GETENV(\"GC_PRINT_VERBOSE_STATS\") != NULL) {\n    GC_print_stats = VERBOSE;\n  } else if (GETENV(\"GC_PRINT_STATS\") != NULL) {\n    GC_print_stats = 1;\n  }\n#  endif\n#endif\n#if ((defined(UNIX_LIKE) && !defined(GC_ANDROID_LOG))                   \\\n     || (defined(CONSOLE_LOG) && defined(MSWIN32)) || defined(CYGWIN32) \\\n     || defined(SYMBIAN))                                               \\\n    && !defined(SMALL_CONFIG)\n  {\n    const char *fname = TRUSTED_STRING(GETENV(\"GC_LOG_FILE\"));\n#  ifdef GC_LOG_TO_FILE_ALWAYS\n    if (NULL == fname)\n      fname = GC_LOG_STD_NAME;\n#  else\n    if (fname != NULL)\n#  endif\n    {\n#  if defined(_MSC_VER)\n      int log_d = _open(fname, O_CREAT | O_WRONLY | O_APPEND);\n#  else\n      int log_d = open(fname, O_CREAT | O_WRONLY | O_APPEND, 0644);\n#  endif\n      if (log_d < 0) {\n        GC_err_printf(\"Failed to open %s as log file\\n\", fname);\n      } else {\n        const char *str;\n        GC_log = log_d;\n        str = GETENV(\"GC_ONLY_LOG_TO_FILE\");\n#  ifdef GC_ONLY_LOG_TO_FILE\n        /*\n         * The similar environment variable set to \"0\"\n         * overrides the effect of the macro defined.\n         */\n        if (str != NULL && str[0] == '0' && str[1] == '\\0')\n#  else\n        /*\n         * Otherwise setting the environment variable to anything other\n         * than \"0\" will prevent from redirecting `stdout` and `stderr`\n         * to the collector log file.\n         */\n        if (str == NULL || (str[0] == '0' && str[1] == '\\0'))\n#  endif\n        {\n          GC_stdout = log_d;\n          GC_stderr = log_d;\n        }\n      }\n    }\n  }\n#endif\n#if !defined(NO_DEBUGGING) && !defined(GC_DUMP_REGULARLY)\n  if (GETENV(\"GC_DUMP_REGULARLY\") != NULL) {\n    GC_dump_regularly = TRUE;\n  }\n#endif\n#ifdef KEEP_BACK_PTRS\n  {\n    const char *str = GETENV(\"GC_BACKTRACES\");\n\n    if (str != NULL) {\n      GC_backtraces = atol(str);\n      if (str[0] == '\\0')\n        GC_backtraces = 1;\n    }\n  }\n#endif\n#ifndef NO_FIND_LEAK\n  if (GETENV(\"GC_FIND_LEAK\") != NULL) {\n    GC_find_leak = 1;\n  }\n#  ifndef SHORT_DBG_HDRS\n  if (GETENV(\"GC_FINDLEAK_DELAY_FREE\") != NULL) {\n    GC_findleak_delay_free = TRUE;\n  }\n#  endif\n#endif\n  if (GETENV(\"GC_ALL_INTERIOR_POINTERS\") != NULL) {\n    GC_all_interior_pointers = 1;\n  }\n  if (GETENV(\"GC_DONT_GC\") != NULL) {\n#if defined(LINT2) \\\n    && !(defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED))\n    GC_disable();\n#else\n    GC_dont_gc = 1;\n#endif\n  }\n#if !defined(SMALL_CONFIG) && !defined(GC_PRINT_BACK_HEIGHT)\n  if (GETENV(\"GC_PRINT_BACK_HEIGHT\") != NULL) {\n#  ifdef MAKE_BACK_GRAPH\n    GC_print_back_height = TRUE;\n#  else\n    GC_err_printf(\"Back height is not available!\\n\");\n#  endif\n  }\n#endif\n  {\n    const char *str = GETENV(\"GC_TRACE\");\n\n    if (str != NULL) {\n#ifndef ENABLE_TRACE\n      WARN(\"Tracing not enabled: Ignoring GC_TRACE value\\n\", 0);\n#else\n      ptr_t p = MAKE_CPTR(STRTOULL(str, NULL, 16));\n\n      if (ADDR(p) < 0x1000)\n        WARN(\"Unlikely trace address: %p\\n\", p);\n      GC_trace_ptr = p;\n#endif\n    }\n  }\n#ifdef GC_COLLECT_AT_MALLOC\n  {\n    const char *str = GETENV(\"GC_COLLECT_AT_MALLOC\");\n\n    if (str != NULL) {\n      size_t min_lb = (size_t)STRTOULL(str, NULL, 10);\n\n      if (min_lb > 0)\n        GC_dbg_collect_at_malloc_min_lb = min_lb;\n    }\n  }\n#endif\n#if !defined(GC_DISABLE_INCREMENTAL) && !defined(NO_CLOCK)\n  {\n    const char *str = GETENV(\"GC_PAUSE_TIME_TARGET\");\n\n    if (str != NULL) {\n      long time_limit = atol(str);\n\n      if (time_limit > 0) {\n        GC_time_limit = (unsigned long)time_limit;\n      }\n    }\n  }\n#endif\n#ifndef SMALL_CONFIG\n  {\n    const char *str = GETENV(\"GC_FULL_FREQUENCY\");\n\n    if (str != NULL) {\n      int full_freq = atoi(str);\n\n      if (full_freq > 0)\n        GC_full_freq = full_freq;\n    }\n  }\n#endif\n#ifndef NO_BLACK_LISTING\n  {\n    char const *str = GETENV(\"GC_LARGE_ALLOC_WARN_INTERVAL\");\n\n    if (str != NULL) {\n      long interval = atol(str);\n\n      if (interval <= 0) {\n        WARN(\"GC_LARGE_ALLOC_WARN_INTERVAL environment variable has\"\n             \" bad value - ignoring\\n\",\n             0);\n      } else {\n        GC_large_alloc_warn_interval = interval;\n      }\n    }\n  }\n#endif\n  {\n    const char *str = GETENV(\"GC_FREE_SPACE_DIVISOR\");\n\n    if (str != NULL) {\n      int space_divisor = atoi(str);\n\n      if (space_divisor > 0)\n        GC_free_space_divisor = (unsigned)space_divisor;\n    }\n  }\n#ifdef USE_MUNMAP\n  {\n    const char *str = GETENV(\"GC_UNMAP_THRESHOLD\");\n\n    if (str != NULL) {\n      if (str[0] == '0' && str[1] == '\\0') {\n        /* \"0\" is used to disable unmapping. */\n        GC_unmap_threshold = 0;\n      } else {\n        int unmap_threshold = atoi(str);\n\n        if (unmap_threshold > 0)\n          GC_unmap_threshold = (unsigned)unmap_threshold;\n      }\n    }\n  }\n  {\n    const char *str = GETENV(\"GC_FORCE_UNMAP_ON_GCOLLECT\");\n\n    if (str != NULL) {\n      if (str[0] == '0' && str[1] == '\\0') {\n        /* \"0\" is used to turn off the mode. */\n        GC_force_unmap_on_gcollect = FALSE;\n      } else {\n        GC_force_unmap_on_gcollect = TRUE;\n      }\n    }\n  }\n  {\n    const char *str = GETENV(\"GC_USE_ENTIRE_HEAP\");\n\n    if (str != NULL) {\n      if (str[0] == '0' && str[1] == '\\0') {\n        /* \"0\" is used to turn off the mode. */\n        GC_use_entire_heap = FALSE;\n      } else {\n        GC_use_entire_heap = TRUE;\n      }\n    }\n  }\n#endif\n#if !defined(NO_DEBUGGING) && !defined(NO_CLOCK)\n  GET_TIME(GC_init_time);\n#endif\n  maybe_install_looping_handler();\n#if ALIGNMENT > GC_DS_TAGS\n  /* Adjust normal object descriptor for extra allocation. */\n  if (EXTRA_BYTES != 0)\n    GC_obj_kinds[NORMAL].ok_descriptor\n        = ((~(word)ALIGNMENT) + 1) | GC_DS_LENGTH;\n#endif\n  GC_exclude_static_roots_inner(beginGC_arrays, endGC_arrays);\n  GC_exclude_static_roots_inner(beginGC_obj_kinds, endGC_obj_kinds);\n#if defined(USE_PROC_FOR_LIBRARIES) && defined(LINUX) && defined(THREADS)\n  /*\n   * TODO: `USE_PROC_FOR_LIBRARIES` with LinuxThreads performs poorly!\n   * If thread stacks are cached, they tend to be scanned in entirety\n   * as part of the root set.  This will grow them to maximum size, and\n   * is generally not desirable.\n   */\n#endif\n#if !defined(THREADS) || !(defined(SN_TARGET_PS3) || defined(SN_TARGET_PSP2))\n  if (NULL == GC_stackbottom) {\n    GC_stackbottom = GC_get_main_stack_base();\n#  if (defined(LINUX) || defined(HPUX)) && defined(IA64)\n    GC_register_stackbottom = GC_get_register_stack_base();\n#  endif\n  } else {\n#  if (defined(LINUX) || defined(HPUX)) && defined(IA64)\n    if (NULL == GC_register_stackbottom) {\n      WARN(\"GC_register_stackbottom should be set with GC_stackbottom\\n\", 0);\n      /*\n       * The following may fail, since we may rely on alignment properties\n       * that may not hold with `GC_stackbottom` value set by client.\n       */\n      GC_register_stackbottom = GC_get_register_stack_base();\n    }\n#  endif\n  }\n#endif\n#if !defined(CPPCHECK)\n  GC_STATIC_ASSERT(sizeof(size_t) <= sizeof(ptrdiff_t));\n#  ifdef AO_HAVE_store\n  /*\n   * As of now, `hb_descr`, `mse_descr` and `hb_marks[i]` might be treated\n   * as variables of `word` type but might be accessed atomically.\n   */\n  GC_STATIC_ASSERT(sizeof(AO_t) == sizeof(word));\n#  endif\n  GC_STATIC_ASSERT(sizeof(ptrdiff_t) == sizeof(word));\n  GC_STATIC_ASSERT(sizeof(GC_signed_word) == sizeof(word));\n  GC_STATIC_ASSERT(sizeof(word) * 8 == CPP_WORDSZ);\n  GC_STATIC_ASSERT(sizeof(ptr_t) * 8 == CPP_PTRSZ);\n  GC_STATIC_ASSERT(sizeof(ptr_t) == sizeof(GC_uintptr_t));\n  GC_STATIC_ASSERT(sizeof(GC_oom_func) == sizeof(GC_funcptr_uint));\n#  ifdef FUNCPTR_IS_DATAPTR\n  GC_STATIC_ASSERT(sizeof(ptr_t) == sizeof(GC_funcptr_uint));\n#  endif\n  GC_STATIC_ASSERT((word)(-1) > (word)0); /*< `word` should be unsigned */\n  /*\n   * We no longer check for `(void *)-1 > NULL` since all pointers\n   * are explicitly cast to `word` in every less/greater comparison.\n   */\n  GC_STATIC_ASSERT((GC_signed_word)(-1) < (GC_signed_word)0);\n#endif\n  GC_STATIC_ASSERT(sizeof(struct hblk) == HBLKSIZE);\n#ifndef THREADS\n  GC_ASSERT(!HOTTER_THAN(GC_stackbottom, GC_approx_sp()));\n#endif\n  GC_init_headers();\n#ifdef SEARCH_FOR_DATA_START\n  /*\n   * For `MPROTECT_VDB`, the temporary fault handler should be installed\n   * first, before the write fault one in `GC_dirty_init`.\n   */\n  if (GC_REGISTER_MAIN_STATIC_DATA())\n    GC_init_linux_data_start();\n#endif\n#ifndef GC_DISABLE_INCREMENTAL\n  if (GC_incremental || GETENV(\"GC_ENABLE_INCREMENTAL\") != NULL) {\n    set_incremental_mode_on();\n    GC_ASSERT(0 == GC_bytes_allocd);\n  }\n#endif\n\n  /*\n   * Add the initial guess of root sets.  Do this first, since `sbrk(0)`\n   * might be used.\n   */\n  if (GC_REGISTER_MAIN_STATIC_DATA())\n    GC_register_data_segments();\n\n  GC_bl_init();\n  GC_mark_init();\n  {\n    const char *str = GETENV(\"GC_INITIAL_HEAP_SIZE\");\n\n    if (str != NULL) {\n      word value = GC_parse_mem_size_arg(str);\n\n      if (GC_WORD_MAX == value) {\n        WARN(\"Bad initial heap size %s - ignoring\\n\", str);\n      } else {\n        initial_heap_sz = value;\n      }\n    }\n  }\n  {\n    const char *str = GETENV(\"GC_MAXIMUM_HEAP_SIZE\");\n\n    if (str != NULL) {\n      word max_heap_sz = GC_parse_mem_size_arg(str);\n\n      if (max_heap_sz < initial_heap_sz || GC_WORD_MAX == max_heap_sz) {\n        WARN(\"Bad maximum heap size %s - ignoring\\n\", str);\n      } else {\n        if (0 == GC_max_retries)\n          GC_max_retries = 2;\n        GC_set_max_heap_size(max_heap_sz);\n      }\n    }\n  }\n  if (initial_heap_sz != 0) {\n    if (!GC_expand_hp_inner(divHBLKSZ(initial_heap_sz))) {\n      GC_err_printf(\"Can't start up: not enough memory\\n\");\n      EXIT();\n    } else {\n      GC_requested_heapsize += initial_heap_sz;\n    }\n  }\n  if (GC_all_interior_pointers)\n    GC_initialize_offsets();\n  GC_register_displacement_inner(0);\n#ifdef REDIR_MALLOC_AND_LINUXTHREADS\n  if (!GC_all_interior_pointers) {\n    /* TLS ABI uses \"pointer-sized\" offsets for `dtv`. */\n    GC_register_displacement_inner(sizeof(void *));\n  }\n#endif\n  GC_init_size_map();\n  GC_is_initialized = TRUE;\n#ifdef THREADS\n#  if defined(LINT2) \\\n      && !(defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED))\n  LOCK();\n  GC_thr_init();\n  UNLOCK();\n#  else\n  GC_thr_init();\n#  endif\n#endif\n  COND_DUMP;\n  /* Get black list set up and/or the incremental GC started. */\n  if (!GC_dont_precollect || GC_incremental) {\n#if defined(DYNAMIC_LOADING) && defined(DARWIN)\n    GC_ASSERT(0 == GC_bytes_allocd);\n#endif\n    GC_gcollect_inner();\n  }\n#if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED)\n  UNLOCK();\n#endif\n#if defined(THREADS) && defined(UNIX_LIKE) && !defined(NO_GETCONTEXT)\n  /* Ensure `getcontext_works` is set to avoid potential data race. */\n  if (GC_dont_gc || GC_dont_precollect)\n    GC_with_callee_saves_pushed(callee_saves_pushed_dummy_fn, NULL);\n#endif\n#ifndef DONT_USE_ATEXIT\n  if (GC_find_leak) {\n    /*\n     * This is to give us at least one chance to detect leaks.\n     * This may report some very benign leaks, but...\n     */\n    atexit(GC_exit_check);\n  }\n#endif\n  /*\n   * The rest of this again assumes we do not really hold the allocator\n   * lock.\n   */\n\n#ifdef THREADS\n  /* Initialize thread-local allocation. */\n  GC_init_parallel();\n#endif\n\n#if defined(DYNAMIC_LOADING) && defined(DARWIN)\n  /*\n   * This must be called *without* the allocator lock held and before\n   * any threads are created.\n   */\n  GC_init_dyld();\n#endif\n  RESTORE_CANCEL(cancel_state);\n  /*\n   * It is not safe to allocate any object till completion of `GC_init`\n   * (in particular by `GC_thr_init`), i.e. before `GC_init_dyld()` call\n   * and initialization of the incremental mode (if any).\n   */\n#if defined(GWW_VDB) && !defined(KEEP_BACK_PTRS)\n  GC_ASSERT(GC_bytes_allocd + GC_bytes_allocd_before_gc == 0);\n#endif\n}\n\nGC_API void GC_CALL\nGC_enable_incremental(void)\n{\n#if !defined(GC_DISABLE_INCREMENTAL) && !defined(KEEP_BACK_PTRS)\n  /*\n   * If we are keeping back pointers, the collector itself dirties all pages\n   * on which objects have been marked, making the incremental collection\n   * pointless.\n   */\n  if (!GC_find_leak_inner && NULL == GETENV(\"GC_DISABLE_INCREMENTAL\")) {\n    LOCK();\n    if (!GC_incremental) {\n      GC_setpagesize();\n      /* TODO: Should we skip enabling incremental if win32s? */\n\n      /* Install the looping handler before write fault handler! */\n      maybe_install_looping_handler();\n      if (!GC_is_initialized) {\n        /* Indicate the intention to turn it on. */\n        GC_incremental = TRUE;\n        UNLOCK();\n        GC_init();\n        LOCK();\n      } else {\n        set_incremental_mode_on();\n      }\n      /* Cannot easily do it if `GC_dont_gc`. */\n      if (GC_incremental && !GC_dont_gc) {\n        IF_CANCEL(int cancel_state;)\n\n        DISABLE_CANCEL(cancel_state);\n        if (GC_bytes_allocd > 0) {\n          /* There may be unmarked reachable objects. */\n          GC_gcollect_inner();\n        } else {\n          /*\n           * We are OK in assuming everything is clean since nothing can\n           * point to an unmarked object.\n           */\n#  ifdef CHECKSUMS\n          GC_read_dirty(FALSE);\n#  else\n          GC_read_dirty(TRUE);\n#  endif\n        }\n        RESTORE_CANCEL(cancel_state);\n      }\n    }\n    UNLOCK();\n    return;\n  }\n#endif\n  GC_init();\n}\n\nGC_API void GC_CALL\nGC_start_mark_threads(void)\n{\n#ifdef PARALLEL_MARK\n  IF_CANCEL(int cancel_state;)\n\n  DISABLE_CANCEL(cancel_state);\n  LOCK();\n  GC_start_mark_threads_inner();\n  UNLOCK();\n  RESTORE_CANCEL(cancel_state);\n#else\n  /* No action since parallel markers are disabled (or no POSIX `fork`). */\n  GC_ASSERT(I_DONT_HOLD_LOCK());\n#endif\n}\n\n#ifndef GC_NO_DEINIT\nGC_API void GC_CALL\nGC_deinit(void)\n{\n  /* Prevent duplicate resource close. */\n  if (!GC_is_initialized)\n    return;\n\n  BZERO(&GC_arrays, sizeof(GC_arrays)); /*< clears GC_is_initialized */\n  GC_gc_no = 0;\n  GC_dont_gc = FALSE;\n  GC_non_gc_bytes = 0;\n  GC_reset_obj_kinds();\n  GC_n_mark_procs = GC_RESERVED_MARK_PROCS;\n  GC_reset_freelist();\n#  ifdef CHECKSUMS\n  GC_reset_check_page();\n#  endif\n#  ifdef THREADS\n  GC_reset_threads();\n#  endif\n#  ifdef THREAD_LOCAL_ALLOC\n  GC_reset_thread_local_initialization();\n#  endif\n#  if defined(GC_WIN32_THREADS) && (defined(MSWIN32) || defined(MSWINCE))\n#    if !defined(CONSOLE_LOG) || defined(MSWINCE)\n  DeleteCriticalSection(&GC_write_cs);\n#    endif\n#    if !defined(GC_PTHREADS) && !defined(USE_RWLOCK)\n  DeleteCriticalSection(&GC_allocate_ml);\n#    endif\n#  endif\n}\n#endif\n\n#if (defined(MSWIN32) && !defined(CONSOLE_LOG)) || defined(MSWINCE)\n\nSTATIC HANDLE GC_log = 0;\n\n#  ifdef THREADS\n#    if defined(PARALLEL_MARK) && !defined(GC_ALWAYS_MULTITHREADED)\n#      define IF_NEED_TO_LOCK(x)            \\\n        if (GC_parallel || GC_need_to_lock) \\\n        x\n#    else\n#      define IF_NEED_TO_LOCK(x) \\\n        if (GC_need_to_lock)     \\\n        x\n#    endif\n#  else\n#    define IF_NEED_TO_LOCK(x)\n#  endif /* !THREADS */\n\n#  ifdef MSWINRT_FLAVOR\n#    include <windows.storage.h>\n\n/*\n * This API function is defined in platform `roapi.h` file, but we cannot\n * include it here since it does not compile in C.\n */\nDECLSPEC_IMPORT HRESULT WINAPI\nRoGetActivationFactory(HSTRING activatableClassId, REFIID iid, void **factory);\n\nstatic GC_bool\ngetWinRTLogPath(wchar_t *buf, size_t bufLen)\n{\n  static const GUID kIID_IApplicationDataStatics\n      = { 0x5612147B, 0xE843, 0x45E3, 0x94, 0xD8, 0x06,\n          0x16,       0x9E,   0x3C,   0x8E, 0x17 };\n  static const GUID kIID_IStorageItem\n      = { 0x4207A996, 0xCA2F, 0x42F7, 0xBD, 0xE8, 0x8B,\n          0x10,       0x45,   0x7A,   0x7F, 0x30 };\n  GC_bool result = FALSE;\n  HSTRING_HEADER appDataClassNameHeader;\n  HSTRING appDataClassName;\n  __x_ABI_CWindows_CStorage_CIApplicationDataStatics *appDataStatics = 0;\n\n  GC_ASSERT(bufLen > 0);\n  if (SUCCEEDED(WindowsCreateStringReference(\n          RuntimeClass_Windows_Storage_ApplicationData,\n          (sizeof(RuntimeClass_Windows_Storage_ApplicationData) - 1)\n              / sizeof(wchar_t),\n          &appDataClassNameHeader, &appDataClassName))\n      && SUCCEEDED(RoGetActivationFactory(\n          appDataClassName, &kIID_IApplicationDataStatics, &appDataStatics))) {\n    __x_ABI_CWindows_CStorage_CIApplicationData *appData = NULL;\n    __x_ABI_CWindows_CStorage_CIStorageFolder *tempFolder = NULL;\n    __x_ABI_CWindows_CStorage_CIStorageItem *tempFolderItem = NULL;\n    HSTRING tempPath = NULL;\n\n    if (SUCCEEDED(\n            appDataStatics->lpVtbl->get_Current(appDataStatics, &appData))\n        && SUCCEEDED(\n            appData->lpVtbl->get_TemporaryFolder(appData, &tempFolder))\n        && SUCCEEDED(tempFolder->lpVtbl->QueryInterface(\n            tempFolder, &kIID_IStorageItem, &tempFolderItem))\n        && SUCCEEDED(\n            tempFolderItem->lpVtbl->get_Path(tempFolderItem, &tempPath))) {\n      UINT32 tempPathLen;\n      const wchar_t *tempPathBuf\n          = WindowsGetStringRawBuffer(tempPath, &tempPathLen);\n\n      buf[0] = '\\0';\n      if (wcsncat_s(buf, bufLen, tempPathBuf, tempPathLen) == 0\n          && wcscat_s(buf, bufLen, L\"\\\\\") == 0\n          && wcscat_s(buf, bufLen, TEXT(GC_LOG_STD_NAME)) == 0)\n        result = TRUE;\n      WindowsDeleteString(tempPath);\n    }\n\n    if (tempFolderItem != NULL)\n      tempFolderItem->lpVtbl->Release(tempFolderItem);\n    if (tempFolder != NULL)\n      tempFolder->lpVtbl->Release(tempFolder);\n    if (appData != NULL)\n      appData->lpVtbl->Release(appData);\n    appDataStatics->lpVtbl->Release(appDataStatics);\n  }\n  return result;\n}\n#  endif /* MSWINRT_FLAVOR */\n\nSTATIC HANDLE\nGC_CreateLogFile(void)\n{\n  HANDLE hFile;\n#  ifdef MSWINRT_FLAVOR\n  TCHAR pathBuf[_MAX_PATH + 0x10]; /*< buffer for file path plus extension */\n\n  hFile = INVALID_HANDLE_VALUE;\n  if (getWinRTLogPath(pathBuf, _MAX_PATH + 1)) {\n    CREATEFILE2_EXTENDED_PARAMETERS extParams;\n\n    BZERO(&extParams, sizeof(extParams));\n    extParams.dwSize = sizeof(extParams);\n    extParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;\n    extParams.dwFileFlags\n        = GC_print_stats == VERBOSE ? 0 : FILE_FLAG_WRITE_THROUGH;\n    hFile = CreateFile2(pathBuf, GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS,\n                        &extParams);\n  }\n\n#  else\n  TCHAR *logPath;\n#    if defined(NO_GETENV_WIN32) && defined(CPPCHECK)\n#      define appendToFile FALSE\n#    else\n  BOOL appendToFile = FALSE;\n#    endif\n#    if !defined(NO_GETENV_WIN32) || !defined(OLD_WIN32_LOG_FILE)\n  TCHAR pathBuf[_MAX_PATH + 0x10]; /*< buffer for file path plus extension */\n\n  logPath = pathBuf;\n#    endif\n\n  /* Use `GetEnvironmentVariable` instead of `GETENV` for Unicode support. */\n#    ifndef NO_GETENV_WIN32\n  if (GetEnvironmentVariable(TEXT(\"GC_LOG_FILE\"), pathBuf, _MAX_PATH + 1) - 1U\n      < (DWORD)_MAX_PATH) {\n    appendToFile = TRUE;\n  } else\n#    endif\n  /* else */ {\n    /* Environment var not found or its value too long. */\n#    ifdef OLD_WIN32_LOG_FILE\n    logPath = TEXT(GC_LOG_STD_NAME);\n#    else\n    int len\n        = (int)GetModuleFileName(NULL /* `hModule` */, pathBuf, _MAX_PATH + 1);\n    /* If `GetModuleFileName()` has failed, then len is 0. */\n    if (len > 4 && pathBuf[len - 4] == (TCHAR)'.') {\n      /* Strip the executable file extension. */\n      len -= 4;\n    }\n    BCOPY(TEXT(\".\") TEXT(GC_LOG_STD_NAME), &pathBuf[len],\n          sizeof(TEXT(\".\") TEXT(GC_LOG_STD_NAME)));\n#    endif\n  }\n\n  hFile = CreateFile(logPath, GENERIC_WRITE, FILE_SHARE_READ,\n                     NULL /* `lpSecurityAttributes` */,\n                     appendToFile ? OPEN_ALWAYS : CREATE_ALWAYS,\n                     GC_print_stats == VERBOSE\n                         ? FILE_ATTRIBUTE_NORMAL\n                         :\n                         /* immediately flush writes unless very verbose */\n                         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,\n                     NULL /* `hTemplateFile` */);\n\n#    ifndef NO_GETENV_WIN32\n  if (appendToFile && hFile != INVALID_HANDLE_VALUE) {\n    LONG posHigh = 0;\n    /* Seek to the file end (ignoring any error). */\n    (void)SetFilePointer(hFile, 0, &posHigh, FILE_END);\n  }\n#    endif\n#    undef appendToFile\n#  endif\n  return hFile;\n}\n\nSTATIC int\nGC_write(const char *buf, size_t len)\n{\n  BOOL res;\n  DWORD written;\n#  if defined(THREADS) && defined(GC_ASSERTIONS)\n  /* This is to prevent infinite recursion at abort. */\n  static GC_bool inside_write = FALSE;\n\n  if (inside_write)\n    return -1;\n#  endif\n\n  if (0 == len)\n    return 0;\n  IF_NEED_TO_LOCK(EnterCriticalSection(&GC_write_cs));\n#  if defined(THREADS) && defined(GC_ASSERTIONS)\n  if (GC_write_disabled) {\n    inside_write = TRUE;\n    ABORT(\"Assertion failure: GC_write called with write_disabled\");\n  }\n#  endif\n  if (0 == GC_log) {\n    GC_log = GC_CreateLogFile();\n  }\n  if (GC_log == INVALID_HANDLE_VALUE) {\n    IF_NEED_TO_LOCK(LeaveCriticalSection(&GC_write_cs));\n#  ifdef NO_DEBUGGING\n    /*\n     * Ignore open log failure (e.g., it might be caused by read-only folder\n     * of the client application).\n     */\n    return 0;\n#  else\n    return -1;\n#  endif\n  }\n  res = WriteFile(GC_log, buf, (DWORD)len, &written, NULL);\n#  if defined(_MSC_VER) && defined(_DEBUG) && !defined(NO_CRT) \\\n      && !defined(NO_CRTDBGREPORT)\n#    ifdef MSWINCE\n  /* There is no `CrtDbgReport()` in WinCE. */\n  {\n    WCHAR wbuf[1024];\n\n    /* Always use Unicode variant of `OutputDebugString()`. */\n    wbuf[MultiByteToWideChar(CP_ACP, 0 /* `dwFlags` */, buf, len, wbuf,\n                             sizeof(wbuf) / sizeof(wbuf[0]) - 1)]\n        = 0;\n    OutputDebugStringW(wbuf);\n  }\n#    else\n  _CrtDbgReport(_CRT_WARN, NULL, 0, NULL, \"%.*s\", len, buf);\n#    endif\n#  endif\n  IF_NEED_TO_LOCK(LeaveCriticalSection(&GC_write_cs));\n  return res ? (int)written : -1;\n}\n\n/* TODO: This is pretty ugly... */\n#  define WRITE(f, buf, len) GC_write(buf, len)\n\n#elif defined(OS2)\nSTATIC FILE *GC_stdout = NULL;\nSTATIC FILE *GC_stderr = NULL;\nSTATIC FILE *GC_log = NULL;\n\n/* Initialize `GC_log` (and the friends) passed to `GC_write()`. */\nSTATIC void\nGC_set_files(void)\n{\n  if (GC_stdout == NULL) {\n    GC_stdout = stdout;\n  }\n  if (GC_stderr == NULL) {\n    GC_stderr = stderr;\n  }\n  if (GC_log == NULL) {\n    GC_log = stderr;\n  }\n}\n\nGC_INLINE int\nGC_write(FILE *f, const char *buf, size_t len)\n{\n  int res = fwrite(buf, 1, len, f);\n  fflush(f);\n  return res;\n}\n\n#  define WRITE(f, buf, len) (GC_set_files(), GC_write(f, buf, len))\n\n#elif defined(GC_ANDROID_LOG)\n\n#  include <android/log.h>\n\n#  ifndef GC_ANDROID_LOG_TAG\n#    define GC_ANDROID_LOG_TAG \"BDWGC\"\n#  endif\n\n#  define GC_stdout ANDROID_LOG_DEBUG\n#  define GC_stderr ANDROID_LOG_ERROR\n#  define GC_log GC_stdout\n\n#  define WRITE(level, buf, unused_len) \\\n    __android_log_write(level, GC_ANDROID_LOG_TAG, buf)\n\n#elif defined(NN_PLATFORM_CTR)\nint n3ds_log_write(const char *text, int length);\n#  define WRITE(level, buf, len) n3ds_log_write(buf, len)\n\n#elif defined(NINTENDO_SWITCH)\nint switch_log_write(const char *text, int length);\n#  define WRITE(level, buf, len) switch_log_write(buf, len)\n\n#else\n\n#  if !defined(ECOS) && !defined(NOSYS) && !defined(PLATFORM_WRITE) \\\n      && !defined(SN_TARGET_PSP2)\n#    include <errno.h>\n#  endif\n\nSTATIC int\nGC_write(int fd, const char *buf, size_t len)\n{\n#  if defined(ECOS) || defined(PLATFORM_WRITE) || defined(SN_TARGET_PSP2) \\\n      || defined(NOSYS)\n  UNUSED_ARG(fd);\n#    ifdef ECOS\n  /* FIXME: This seems to be defined nowhere at present. */\n  /* `_Jv_diag_write(buf, len);` */\n#    else\n  /* No writing. */\n#    endif\n  UNUSED_ARG(buf);\n  return (int)len;\n#  else\n  size_t bytes_written = 0;\n  IF_CANCEL(int cancel_state;)\n\n  DISABLE_CANCEL(cancel_state);\n  while (bytes_written < len) {\n    int result;\n\n#    if defined(SOLARIS) && defined(THREADS)\n    result = syscall(SYS_write, fd, buf + bytes_written, len - bytes_written);\n#    elif defined(_MSC_VER)\n    result = _write(fd, buf + bytes_written, (unsigned)(len - bytes_written));\n#    else\n    result = (int)write(fd, buf + bytes_written, len - bytes_written);\n#    endif\n    if (result < 0) {\n      if (EAGAIN == errno) {\n        /* Resource is temporarily unavailable. */\n        continue;\n      }\n      RESTORE_CANCEL(cancel_state);\n      return -1;\n    }\n#    ifdef LINT2\n    if ((unsigned)result > len - bytes_written)\n      ABORT(\"write() result cannot be bigger than requested length\");\n#    endif\n    bytes_written += (unsigned)result;\n  }\n  RESTORE_CANCEL(cancel_state);\n  return (int)bytes_written;\n#  endif\n}\n\n#  define WRITE(f, buf, len) GC_write(f, buf, len)\n#endif /* !MSWINCE && !OS2 && !GC_ANDROID_LOG */\n\n#ifndef GC_DISABLE_SNPRINTF\n#  define BUFSZ 1024\n\n#  if defined(DJGPP) || defined(__STRICT_ANSI__)\n/* `vsnprintf` is missing in DJGPP (v2.0.3). */\n#    define GC_VSNPRINTF(buf, bufsz, format, args) vsprintf(buf, format, args)\n#  elif defined(_MSC_VER)\n#    ifdef MSWINCE\n/* `_vsnprintf` is deprecated in WinCE. */\n#      define GC_VSNPRINTF StringCchVPrintfA\n#    else\n#      define GC_VSNPRINTF _vsnprintf\n#    endif\n#  else\n#    define GC_VSNPRINTF vsnprintf\n#  endif\n\n/*\n * A variant of `printf` that is unlikely to call `malloc`, and is thus\n * safer to call from the collector in case `malloc` has been bound to\n * `GC_malloc`.  Floating-point arguments and formats should be avoided,\n * since the conversion is more likely to allocate memory.\n * Assumes that no more than `BUFSZ - 1` characters are written at once.\n */\n#  define GC_PRINTF_FILLBUF(buf, format)                      \\\n    do {                                                      \\\n      va_list args;                                           \\\n      va_start(args, format);                                 \\\n      (buf)[sizeof(buf) - 1] = 0x15; /*< guard */             \\\n      (void)GC_VSNPRINTF(buf, sizeof(buf) - 1, format, args); \\\n      va_end(args);                                           \\\n      if ((buf)[sizeof(buf) - 1] != 0x15)                     \\\n        ABORT(\"GC_printf clobbered stack\");                   \\\n    } while (0)\n\n#  define DECL_BUF_AND_PRINTF_TO(buf, format) \\\n    char buf[BUFSZ + 1];                      \\\n    GC_PRINTF_FILLBUF(buf, format)\n#else\n/*\n * At most, when `vsnprintf()` is unavailable, we could only print the\n * format string as is, not handling the format specifiers (if any), thus\n * skipping the rest of the `printf` arguments.\n */\n#  define DECL_BUF_AND_PRINTF_TO(buf, format) const char *buf = (format)\n#endif /* GC_DISABLE_SNPRINTF */\n\nvoid\nGC_printf(const char *format, ...)\n{\n  if (!GC_quiet) {\n    DECL_BUF_AND_PRINTF_TO(buf, format);\n#ifdef NACL\n    (void)WRITE(GC_stdout, buf, strlen(buf));\n    /* Ignore errors silently. */\n#else\n    if (WRITE(GC_stdout, buf, strlen(buf)) < 0\n#  if defined(CYGWIN32) || (defined(CONSOLE_LOG) && defined(MSWIN32))\n        && GC_stdout != GC_DEFAULT_STDOUT_FD\n#  endif\n    ) {\n      ABORT(\"write to stdout failed\");\n    }\n#endif\n  }\n}\n\nvoid\nGC_err_printf(const char *format, ...)\n{\n  DECL_BUF_AND_PRINTF_TO(buf, format);\n  GC_err_puts(buf);\n}\n\nvoid\nGC_log_printf(const char *format, ...)\n{\n  DECL_BUF_AND_PRINTF_TO(buf, format);\n#ifdef NACL\n  (void)WRITE(GC_log, buf, strlen(buf));\n#else\n  if (WRITE(GC_log, buf, strlen(buf)) < 0\n#  if defined(CYGWIN32) || (defined(CONSOLE_LOG) && defined(MSWIN32))\n      && GC_log != GC_DEFAULT_STDERR_FD\n#  endif\n  ) {\n    ABORT(\"write to GC log failed\");\n  }\n#endif\n}\n\n#ifndef GC_ANDROID_LOG\n\n#  define GC_warn_printf GC_err_printf\n\n#else\n\nGC_INNER void\nGC_info_log_printf(const char *format, ...)\n{\n  DECL_BUF_AND_PRINTF_TO(buf, format);\n  (void)WRITE(ANDROID_LOG_INFO, buf, 0 /* unused */);\n}\n\nGC_INNER void\nGC_verbose_log_printf(const char *format, ...)\n{\n  DECL_BUF_AND_PRINTF_TO(buf, format);\n  /* Note: write errors are ignored. */\n  (void)WRITE(ANDROID_LOG_VERBOSE, buf, 0);\n}\n\nSTATIC void\nGC_warn_printf(const char *format, ...)\n{\n  DECL_BUF_AND_PRINTF_TO(buf, format);\n  (void)WRITE(ANDROID_LOG_WARN, buf, 0);\n}\n\n#endif /* GC_ANDROID_LOG */\n\nvoid\nGC_err_puts(const char *s)\n{\n  /* Note: write errors are ignored. */\n  (void)WRITE(GC_stderr, s, strlen(s));\n}\n\nSTATIC void GC_CALLBACK\nGC_default_warn_proc(const char *msg, GC_uintptr_t arg)\n{\n  /* TODO: Add assertion on argument to comply with `msg` (format). */\n  GC_warn_printf(msg, arg);\n}\n\nGC_INNER GC_warn_proc GC_current_warn_proc = GC_default_warn_proc;\n\nGC_API void GC_CALLBACK\nGC_ignore_warn_proc(const char *msg, GC_uintptr_t arg)\n{\n  if (GC_print_stats) {\n    /* Do not ignore warnings if stats printing is on. */\n    GC_default_warn_proc(msg, arg);\n  }\n}\n\nGC_API void GC_CALL\nGC_set_warn_proc(GC_warn_proc p)\n{\n  GC_ASSERT(NONNULL_ARG_NOT_NULL(p));\n  LOCK();\n  GC_current_warn_proc = p;\n  UNLOCK();\n}\n\nGC_API GC_warn_proc GC_CALL\nGC_get_warn_proc(void)\n{\n  GC_warn_proc result;\n\n  READER_LOCK();\n  result = GC_current_warn_proc;\n  READER_UNLOCK();\n  return result;\n}\n\n/*\n * Print (or display) a message before abnormal exit (including abort).\n * Invoked from `ABORT(msg)` macro (where `msg` is non-`NULL`) and from\n * `EXIT()` macro (`msg` is `NULL` in that case).\n */\nSTATIC void GC_CALLBACK\nGC_default_on_abort(const char *msg)\n{\n#if !defined(SMALL_CONFIG)\n#  ifndef DONT_USE_ATEXIT\n  /* Disable at-exit garbage collection. */\n  GC_skip_collect_atexit = TRUE;\n#  endif\n\n  if (msg != NULL) {\n#  ifdef MSGBOX_ON_ERROR\n    GC_win32_MessageBoxA(msg, \"Fatal error in GC\", MB_ICONERROR | MB_OK);\n    /* Also duplicate `msg` to the collector log file. */\n#  endif\n\n#  ifndef GC_ANDROID_LOG\n    /*\n     * Avoid calling `GC_err_printf()` here, as `GC_on_abort()` could\n     * be called from it.  Note 1: this is not an atomic output.\n     * Note 2: possible write errors are ignored.\n     */\n#    if defined(GC_WIN32_THREADS) && defined(GC_ASSERTIONS) \\\n        && ((defined(MSWIN32) && !defined(CONSOLE_LOG)) || defined(MSWINCE))\n    if (!GC_write_disabled)\n#    endif\n    {\n      if (WRITE(GC_stderr, msg, strlen(msg)) >= 0)\n        (void)WRITE(GC_stderr, \"\\n\", 1);\n    }\n#  else\n    __android_log_assert(\"*\" /* `cond` */, GC_ANDROID_LOG_TAG, \"%s\\n\", msg);\n#  endif\n#  if defined(HAIKU) && !defined(DONT_CALL_DEBUGGER)\n    /*\n     * This will cause the crash reason to appear in any debug reports\n     * generated (by the default system application crash dialog).\n     */\n    debugger(msg);\n#  endif\n  }\n\n#  if !defined(NO_DEBUGGING) && !defined(GC_ANDROID_LOG)\n  if (GETENV(\"GC_LOOP_ON_ABORT\") != NULL) {\n    /*\n     * In many cases it is easier to debug a running process.\n     * It is arguably nicer to sleep, but that makes it harder to look\n     * at the thread if the debugger does not know much about threads.\n     */\n    for (;;) {\n      /* Empty. */\n    }\n  }\n#  endif\n#else\n  UNUSED_ARG(msg);\n#endif\n}\n\n#ifndef SMALL_CONFIG\nGC_abort_func GC_on_abort = GC_default_on_abort;\n#endif\n\nGC_API void GC_CALL\nGC_set_abort_func(GC_abort_func fn)\n{\n  GC_ASSERT(NONNULL_ARG_NOT_NULL(fn));\n  LOCK();\n#ifndef SMALL_CONFIG\n  GC_on_abort = fn;\n#else\n  UNUSED_ARG(fn);\n#endif\n  UNLOCK();\n}\n\nGC_API GC_abort_func GC_CALL\nGC_get_abort_func(void)\n{\n  GC_abort_func fn;\n\n  READER_LOCK();\n#ifndef SMALL_CONFIG\n  fn = GC_on_abort;\n  GC_ASSERT(fn != 0);\n#else\n  fn = GC_default_on_abort;\n#endif\n  READER_UNLOCK();\n  return fn;\n}\n\n#if defined(NEED_SNPRINTF_SLDS) /* && GC_DISABLE_SNPRINTF */\nGC_INNER void\nGC_snprintf_s_ld_s(char *buf, size_t buf_sz, const char *prefix, long lv,\n                   const char *suffix)\n{\n  size_t len = strlen(prefix);\n\n  GC_ASSERT(buf_sz > 0);\n  /* Copy the prefix. */\n  if (UNLIKELY(len >= buf_sz))\n    len = buf_sz - 1;\n  BCOPY(prefix, buf, len);\n  buf += len;\n  buf_sz -= len;\n\n  /* Handle sign of the number. */\n  if (lv >= 0) {\n    lv = -lv;\n  } else if (LIKELY(buf_sz > 1)) {\n    *(buf++) = '-';\n    buf_sz--;\n  }\n\n  /* Convert the decimal number to string.  (A trivial implementation.) */\n  {\n    char num_buf[20];\n    size_t pos = sizeof(num_buf);\n\n    do {\n      long r = lv / 10;\n\n      if (UNLIKELY(0 == pos))\n        break; /*< overflow */\n      num_buf[--pos] = (char)(r * 10 - lv + '0');\n      lv = r;\n    } while (lv < 0);\n    len = sizeof(num_buf) - pos;\n    if (UNLIKELY(len >= buf_sz))\n      len = buf_sz - 1;\n    BCOPY(&num_buf[pos], buf, len);\n  }\n  buf += len;\n  buf_sz -= len;\n\n  /* Copy the suffix (if any). */\n  len = strlen(suffix);\n  if (len > 0) {\n    if (UNLIKELY(len >= buf_sz))\n      len = buf_sz - 1;\n    BCOPY(suffix, buf, len);\n    buf += len;\n  }\n  *buf = '\\0';\n}\n#endif /* NEED_SNPRINTF_SLDS */\n\nGC_API void GC_CALL\nGC_enable(void)\n{\n  LOCK();\n  /* Ensure no counter underflow. */\n  GC_ASSERT(GC_dont_gc != 0);\n  GC_dont_gc--;\n  if (!GC_dont_gc && GC_heapsize > GC_heapsize_on_gc_disable)\n    WARN(\"Heap grown by %\" WARN_PRIuPTR \" KiB while GC was disabled\\n\",\n         (GC_heapsize - GC_heapsize_on_gc_disable) >> 10);\n  UNLOCK();\n}\n\nGC_API void GC_CALL\nGC_disable(void)\n{\n  LOCK();\n  if (!GC_dont_gc)\n    GC_heapsize_on_gc_disable = GC_heapsize;\n  GC_dont_gc++;\n  UNLOCK();\n}\n\nGC_API int GC_CALL\nGC_is_disabled(void)\n{\n  return GC_dont_gc != 0;\n}\n\n/* Helper procedures for new kind creation. */\n\nGC_API void **GC_CALL\nGC_new_free_list_inner(void)\n{\n  void *result;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  result = GC_INTERNAL_MALLOC((MAXOBJGRANULES + 1) * sizeof(ptr_t), PTRFREE);\n  if (NULL == result)\n    ABORT(\"Failed to allocate free list for new kind\");\n  BZERO(result, (MAXOBJGRANULES + 1) * sizeof(ptr_t));\n  return (void **)result;\n}\n\nGC_API void **GC_CALL\nGC_new_free_list(void)\n{\n  void **result;\n\n  LOCK();\n  result = GC_new_free_list_inner();\n  UNLOCK();\n  return result;\n}\n\nGC_API unsigned GC_CALL\nGC_new_kind_inner(void **fl, GC_word descr, int adjust, int clear)\n{\n  unsigned result = GC_n_kinds;\n\n  GC_ASSERT(NONNULL_ARG_NOT_NULL(fl));\n  GC_ASSERT(!adjust || 1 == adjust);\n  /*\n   * If an object is not needed to be cleared (when moved to the free list),\n   * then its descriptor should be zero to denote a pointer-free object\n   * (and, as a consequence, the size of the object should not be added to\n   * the descriptor template).\n   */\n  GC_ASSERT(1 == clear || (0 == descr && !adjust && !clear));\n  if (result < MAXOBJKINDS) {\n    GC_ASSERT(result > 0);\n    GC_n_kinds++;\n    GC_obj_kinds[result].ok_freelist = fl;\n    GC_obj_kinds[result].ok_reclaim_list = 0;\n    GC_obj_kinds[result].ok_descriptor = descr;\n    GC_obj_kinds[result].ok_relocate_descr = (GC_bool)adjust;\n    GC_obj_kinds[result].ok_init = (GC_bool)clear;\n#ifdef ENABLE_DISCLAIM\n    GC_obj_kinds[result].ok_mark_unconditionally = FALSE;\n    GC_obj_kinds[result].ok_disclaim_proc = 0;\n#endif\n  } else {\n    ABORT(\"Too many kinds\");\n  }\n  return result;\n}\n\nGC_API unsigned GC_CALL\nGC_new_kind(void **fl, GC_word descr, int adjust, int clear)\n{\n  unsigned result;\n\n  LOCK();\n  result = GC_new_kind_inner(fl, descr, adjust, clear);\n  UNLOCK();\n  return result;\n}\n\nGC_API unsigned GC_CALL\nGC_new_proc_inner(GC_mark_proc proc)\n{\n  unsigned result = GC_n_mark_procs;\n\n  if (result < GC_MAX_MARK_PROCS) {\n    GC_n_mark_procs++;\n    GC_mark_procs[result] = proc;\n  } else {\n    ABORT(\"Too many mark procedures\");\n  }\n  return result;\n}\n\nGC_API unsigned GC_CALL\nGC_new_proc(GC_mark_proc proc)\n{\n  unsigned result;\n\n  LOCK();\n  result = GC_new_proc_inner(proc);\n  UNLOCK();\n  return result;\n}\n\nGC_API void *GC_CALL\nGC_call_with_alloc_lock(GC_fn_type fn, void *client_data)\n{\n  void *result;\n\n  LOCK();\n  result = fn(client_data);\n  UNLOCK();\n  return result;\n}\n\n#ifdef THREADS\nGC_API void GC_CALL\nGC_alloc_lock(void)\n{\n  LOCK();\n}\n\nGC_API void GC_CALL\nGC_alloc_unlock(void)\n{\n  UNLOCK();\n}\n\nGC_API void *GC_CALL\nGC_call_with_reader_lock(GC_fn_type fn, void *client_data, int release)\n{\n  void *result;\n\n  READER_LOCK();\n  result = fn(client_data);\n#  ifdef HAS_REAL_READER_LOCK\n  if (release) {\n    READER_UNLOCK_RELEASE();\n#    ifdef LINT2\n    GC_noop1((unsigned)release);\n#    endif\n    return result;\n  }\n#  else\n  UNUSED_ARG(release);\n#  endif\n  READER_UNLOCK();\n  return result;\n}\n#endif /* THREADS */\n\nGC_ATTR_NOINLINE\nGC_API void *GC_CALL\nGC_call_with_stack_base(GC_stack_base_func fn, void *arg)\n{\n  struct GC_stack_base base;\n  void *result;\n\n  STORE_APPROX_SP_TO(*(volatile ptr_t *)&base.mem_base);\n#ifdef IA64\n  base.reg_base = GC_save_regs_in_stack();\n  /*\n   * TODO: Unnecessarily flushes register stack, but that probably\n   * does not hurt.\n   */\n#elif defined(E2K)\n  {\n    unsigned long long sz_ull;\n\n    GET_PROCEDURE_STACK_SIZE_INNER(&sz_ull);\n    base.reg_base = NUMERIC_TO_VPTR(sz_ull);\n  }\n#endif\n  result = (*(GC_stack_base_func volatile *)&fn)(&base, arg);\n  /*\n   * Strongly discourage the compiler from treating the above as\n   * a tail call.\n   */\n  GC_noop1(COVERT_DATAFLOW(ADDR(&base)));\n  return result;\n}\n\n#ifndef THREADS\n\nGC_INNER ptr_t GC_blocked_sp = NULL;\n\n#  ifdef IA64\nSTATIC ptr_t GC_blocked_register_sp = NULL;\n#  endif\n\nGC_INNER struct GC_traced_stack_sect_s *GC_traced_stack_sect = NULL;\n\n/* This is nearly the same as in `pthread_support.c` file. */\nGC_ATTR_NOINLINE\nGC_API void *GC_CALL\nGC_call_with_gc_active(GC_fn_type fn, void *client_data)\n{\n  struct GC_traced_stack_sect_s stacksect;\n  GC_ASSERT(GC_is_initialized);\n\n  /*\n   * Adjust our stack bottom pointer (this could happen if\n   * `GC_get_main_stack_base()` is unimplemented or broken for\n   * the platform).  Note: `stacksect` variable is reused here.\n   */\n  STORE_APPROX_SP_TO(*(volatile ptr_t *)&stacksect.saved_stack_ptr);\n  if (HOTTER_THAN(GC_stackbottom, stacksect.saved_stack_ptr))\n    GC_stackbottom = stacksect.saved_stack_ptr;\n\n  if (GC_blocked_sp == NULL) {\n    /* We are not inside `GC_do_blocking()` - do nothing more. */\n    client_data = (*(GC_fn_type volatile *)&fn)(client_data);\n    /* Prevent treating the above as a tail call. */\n    GC_noop1(COVERT_DATAFLOW(ADDR(&stacksect)));\n    return client_data; /*< result */\n  }\n\n  /* Setup new \"stack section\". */\n  stacksect.saved_stack_ptr = GC_blocked_sp;\n#  ifdef IA64\n  /* This is the same as in `GC_call_with_stack_base()`. */\n  stacksect.backing_store_end = GC_save_regs_in_stack();\n  /* Unnecessarily flushes register stack, but that probably does not hurt. */\n  stacksect.saved_backing_store_ptr = GC_blocked_register_sp;\n#  endif\n  stacksect.prev = GC_traced_stack_sect;\n  GC_blocked_sp = NULL;\n  GC_traced_stack_sect = &stacksect;\n\n  client_data = (*(GC_fn_type volatile *)&fn)(client_data);\n  GC_ASSERT(GC_blocked_sp == NULL);\n  GC_ASSERT(GC_traced_stack_sect == &stacksect);\n\n#  if defined(CPPCHECK)\n  GC_noop1_ptr(GC_traced_stack_sect);\n  GC_noop1_ptr(GC_blocked_sp);\n#  endif\n  /* Restore original \"stack section\". */\n  GC_traced_stack_sect = stacksect.prev;\n#  ifdef IA64\n  GC_blocked_register_sp = stacksect.saved_backing_store_ptr;\n#  endif\n  GC_blocked_sp = stacksect.saved_stack_ptr;\n\n  return client_data; /*< result */\n}\n\n/* This is nearly the same as in `pthread_support.c` file. */\nSTATIC void\nGC_do_blocking_inner(ptr_t data, void *context)\n{\n  UNUSED_ARG(context);\n  GC_ASSERT(GC_is_initialized);\n  GC_ASSERT(GC_blocked_sp == NULL);\n#  ifdef SPARC\n  GC_blocked_sp = GC_save_regs_in_stack();\n#  else\n  GC_blocked_sp = GC_approx_sp();\n#    ifdef IA64\n  GC_blocked_register_sp = GC_save_regs_in_stack();\n#    endif\n#  endif\n\n  ((struct blocking_data *)data)->client_data /*< result */\n      = ((struct blocking_data *)data)\n            ->fn(((struct blocking_data *)data)->client_data);\n\n  GC_ASSERT(GC_blocked_sp != NULL);\n#  if defined(CPPCHECK)\n  GC_noop1_ptr(GC_blocked_sp);\n#  endif\n  GC_blocked_sp = NULL;\n}\n\nGC_API void GC_CALL\nGC_set_stackbottom(void *gc_thread_handle, const struct GC_stack_base *sb)\n{\n  GC_ASSERT(sb->mem_base != NULL);\n  GC_ASSERT(NULL == gc_thread_handle || &GC_stackbottom == gc_thread_handle);\n  GC_ASSERT(NULL == GC_blocked_sp\n            && NULL == GC_traced_stack_sect); /*< for now */\n  UNUSED_ARG(gc_thread_handle);\n\n  GC_stackbottom = (char *)sb->mem_base;\n#  ifdef IA64\n  GC_register_stackbottom = (ptr_t)sb->reg_base;\n#  endif\n}\n\nGC_API void *GC_CALL\nGC_get_my_stackbottom(struct GC_stack_base *sb)\n{\n  GC_ASSERT(GC_is_initialized);\n  sb->mem_base = GC_stackbottom;\n#  ifdef IA64\n  sb->reg_base = GC_register_stackbottom;\n#  elif defined(E2K)\n  sb->reg_base = NULL;\n#  endif\n  return &GC_stackbottom; /*< `gc_thread_handle` */\n}\n\n#endif /* !THREADS */\n\nGC_API void *GC_CALL\nGC_do_blocking(GC_fn_type fn, void *client_data)\n{\n  struct blocking_data my_data;\n\n  my_data.fn = fn;\n  my_data.client_data = client_data;\n  GC_with_callee_saves_pushed(GC_do_blocking_inner, (ptr_t)(&my_data));\n  return my_data.client_data; /*< result */\n}\n\n#if !defined(NO_DEBUGGING)\nGC_API void GC_CALL\nGC_dump(void)\n{\n  READER_LOCK();\n  GC_dump_named(NULL);\n  READER_UNLOCK();\n}\n\nGC_API void GC_CALL\nGC_dump_named(const char *name)\n{\n#  ifndef NO_CLOCK\n  CLOCK_TYPE current_time;\n\n  GET_TIME(current_time);\n#  endif\n  if (name != NULL) {\n    GC_printf(\"\\n***GC Dump %s\\n\", name);\n  } else {\n    GC_printf(\"\\n***GC Dump collection #%lu\\n\", (unsigned long)GC_gc_no);\n  }\n#  ifndef NO_CLOCK\n  /* Note that the time is wrapped in ~49 days if `sizeof(long) == 4`. */\n  GC_printf(\"Time since GC init: %lu ms\\n\",\n            MS_TIME_DIFF(current_time, GC_init_time));\n#  endif\n\n  GC_printf(\"\\n***Static roots:\\n\");\n  GC_print_static_roots();\n  GC_printf(\"\\n***Heap sections:\\n\");\n  GC_print_heap_sects();\n  GC_printf(\"\\n***Free blocks:\\n\");\n  GC_print_hblkfreelist();\n  GC_printf(\"\\n***Blocks in use:\\n\");\n  GC_print_block_list();\n#  ifndef GC_NO_FINALIZATION\n  GC_dump_finalization();\n#  endif\n}\n#endif /* !NO_DEBUGGING */\n\nGC_API GC_word GC_CALL\nGC_get_memory_use(void)\n{\n  word bytes;\n\n  READER_LOCK();\n  GC_ASSERT(GC_heapsize >= GC_large_free_bytes);\n  bytes = GC_heapsize - GC_large_free_bytes;\n  READER_UNLOCK();\n  return bytes;\n}\n\n/* Getter functions for the public read-only variables. */\n\nGC_API GC_word GC_CALL\nGC_get_gc_no(void)\n{\n  return GC_gc_no;\n}\n\n#ifndef PARALLEL_MARK\nGC_API void GC_CALL\nGC_set_markers_count(unsigned markers)\n{\n  UNUSED_ARG(markers);\n}\n#endif\n\nGC_API int GC_CALL\nGC_get_parallel(void)\n{\n#ifdef THREADS\n  return GC_parallel;\n#else\n  return 0;\n#endif\n}\n\n/*\n * Setter and getter functions for the public R/W function variables.\n * These functions are synchronized (like `GC_set_warn_proc()` and\n * `GC_get_warn_proc()`).\n */\n\nGC_API void GC_CALL\nGC_set_oom_fn(GC_oom_func fn)\n{\n  GC_ASSERT(NONNULL_ARG_NOT_NULL(fn));\n  LOCK();\n  GC_oom_fn = fn;\n  UNLOCK();\n}\n\nGC_API GC_oom_func GC_CALL\nGC_get_oom_fn(void)\n{\n  GC_oom_func fn;\n\n  READER_LOCK();\n  fn = GC_oom_fn;\n  READER_UNLOCK();\n  return fn;\n}\n\nGC_API void GC_CALL\nGC_set_on_heap_resize(GC_on_heap_resize_proc fn)\n{\n  /* `fn` may be 0 (means no event notifier). */\n  LOCK();\n  GC_on_heap_resize = fn;\n  UNLOCK();\n}\n\nGC_API GC_on_heap_resize_proc GC_CALL\nGC_get_on_heap_resize(void)\n{\n  GC_on_heap_resize_proc fn;\n\n  READER_LOCK();\n  fn = GC_on_heap_resize;\n  READER_UNLOCK();\n  return fn;\n}\n\nGC_API void GC_CALL\nGC_set_finalizer_notifier(GC_finalizer_notifier_proc fn)\n{\n  /* `fn` may be 0 (means no finalizer notifier). */\n  LOCK();\n  GC_finalizer_notifier = fn;\n  UNLOCK();\n}\n\nGC_API GC_finalizer_notifier_proc GC_CALL\nGC_get_finalizer_notifier(void)\n{\n  GC_finalizer_notifier_proc fn;\n\n  READER_LOCK();\n  fn = GC_finalizer_notifier;\n  READER_UNLOCK();\n  return fn;\n}\n\n/*\n * Setter and getter functions for the public numeric R/W variables.\n * It is safe to call these functions even before `GC_INIT()`.\n * These functions are unsynchronized and, if called after `GC_INIT()`,\n * should be typically invoked inside the context of\n * `GC_call_with_alloc_lock()` (or `GC_call_with_reader_lock()` in case\n * of the getters) to prevent data race (unless it is guaranteed the\n * collector is not multi-threaded at that execution point).\n */\n\nGC_API void GC_CALL\nGC_set_find_leak(int value)\n{\n  /* `value` is of boolean type. */\n#ifdef NO_FIND_LEAK\n  if (value)\n    ABORT(\"Find-leak mode is unsupported\");\n#else\n  GC_find_leak = value;\n#endif\n}\n\nGC_API int GC_CALL\nGC_get_find_leak(void)\n{\n  return GC_find_leak_inner;\n}\n\nGC_API void GC_CALL\nGC_set_all_interior_pointers(int value)\n{\n  GC_all_interior_pointers = value ? 1 : 0;\n  if (GC_is_initialized) {\n    /*\n     * It is not recommended to change `GC_all_interior_pointers` value\n     * after the collector is initialized but it seems it could work\n     * correctly even after switching the mode.\n     */\n    LOCK();\n    /* Note: this resets manual offsets as well. */\n    GC_initialize_offsets();\n#ifndef NO_BLACK_LISTING\n    if (!GC_all_interior_pointers)\n      GC_bl_init_no_interiors();\n#endif\n    UNLOCK();\n  }\n}\n\nGC_API int GC_CALL\nGC_get_all_interior_pointers(void)\n{\n  return GC_all_interior_pointers;\n}\n\nGC_API void GC_CALL\nGC_set_finalize_on_demand(int value)\n{\n  /* Note: -1 was used to retrieve old value in gc-7.2. */\n  GC_ASSERT(value != -1);\n  /* `value` is of boolean type. */\n  GC_finalize_on_demand = value;\n}\n\nGC_API int GC_CALL\nGC_get_finalize_on_demand(void)\n{\n  return GC_finalize_on_demand;\n}\n\nGC_API void GC_CALL\nGC_set_java_finalization(int value)\n{\n  /* Note: -1 was used to retrieve old value in gc-7.2. */\n  GC_ASSERT(value != -1);\n  /* `value` is of boolean type. */\n  GC_java_finalization = value;\n}\n\nGC_API int GC_CALL\nGC_get_java_finalization(void)\n{\n  return GC_java_finalization;\n}\n\nGC_API void GC_CALL\nGC_set_dont_expand(int value)\n{\n  /* Note: -1 was used to retrieve old value in gc-7.2. */\n  GC_ASSERT(value != -1);\n  /* `value` is of boolean type. */\n  GC_dont_expand = value;\n}\n\nGC_API int GC_CALL\nGC_get_dont_expand(void)\n{\n  return GC_dont_expand;\n}\n\nGC_API void GC_CALL\nGC_set_no_dls(int value)\n{\n  /* Note: -1 was used to retrieve old value in gc-7.2. */\n  GC_ASSERT(value != -1);\n  /* `value` is of boolean type. */\n  GC_no_dls = value;\n}\n\nGC_API int GC_CALL\nGC_get_no_dls(void)\n{\n  return GC_no_dls;\n}\n\nGC_API void GC_CALL\nGC_set_non_gc_bytes(GC_word value)\n{\n  GC_non_gc_bytes = value;\n}\n\nGC_API GC_word GC_CALL\nGC_get_non_gc_bytes(void)\n{\n  return GC_non_gc_bytes;\n}\n\nGC_API void GC_CALL\nGC_set_free_space_divisor(GC_word value)\n{\n  GC_ASSERT(value > 0);\n  GC_free_space_divisor = value;\n}\n\nGC_API GC_word GC_CALL\nGC_get_free_space_divisor(void)\n{\n  return GC_free_space_divisor;\n}\n\nGC_API void GC_CALL\nGC_set_max_retries(GC_word value)\n{\n  /* Note: -1 was used to retrieve old value in gc-7.2. */\n  GC_ASSERT((GC_signed_word)value != -1);\n  GC_max_retries = value;\n}\n\nGC_API GC_word GC_CALL\nGC_get_max_retries(void)\n{\n  return GC_max_retries;\n}\n\nGC_API void GC_CALL\nGC_set_dont_precollect(int value)\n{\n  /* Note: -1 was used to retrieve old value in gc-7.2. */\n  GC_ASSERT(value != -1);\n  /* `value` is of boolean type. */\n  GC_dont_precollect = value;\n}\n\nGC_API int GC_CALL\nGC_get_dont_precollect(void)\n{\n  return GC_dont_precollect;\n}\n\nGC_API void GC_CALL\nGC_set_full_freq(int value)\n{\n  GC_ASSERT(value >= 0);\n  GC_full_freq = value;\n}\n\nGC_API int GC_CALL\nGC_get_full_freq(void)\n{\n  return GC_full_freq;\n}\n\nGC_API void GC_CALL\nGC_set_time_limit(unsigned long value)\n{\n  /* Note: -1 was used to retrieve old value in gc-7.2. */\n  GC_ASSERT((long)value != -1L);\n  GC_time_limit = value;\n}\n\nGC_API unsigned long GC_CALL\nGC_get_time_limit(void)\n{\n  return GC_time_limit;\n}\n\nGC_API void GC_CALL\nGC_set_force_unmap_on_gcollect(int value)\n{\n  GC_force_unmap_on_gcollect = (GC_bool)value;\n}\n\nGC_API int GC_CALL\nGC_get_force_unmap_on_gcollect(void)\n{\n  return (int)GC_force_unmap_on_gcollect;\n}\n\nGC_API GC_OOM_ABORT_THROW_ATTRIBUTE void GC_CALL\nGC_abort_on_oom(void)\n{\n  GC_err_printf(\"Insufficient memory for the allocation\\n\");\n  EXIT();\n}\n\nGC_API size_t GC_CALL\nGC_get_hblk_size(void)\n{\n  return (size_t)HBLKSIZE;\n}\n\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999 by Hewlett-Packard Company.  All rights reserved.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#if (defined(MPROTECT_VDB) && !defined(MSWIN32) && !defined(MSWINCE)) \\\n    || (defined(SOLARIS) && defined(THREADS)) || defined(OPENBSD)\n#  include <signal.h>\n#endif\n\n#if defined(UNIX_LIKE) || defined(CYGWIN32) || defined(NACL) \\\n    || defined(SYMBIAN)\n#  include <fcntl.h>\n#endif\n\n#ifdef LINUX\n#  include <ctype.h>\n#endif\n\n/*\n * Blatantly OS-dependent routines, except for those that are related\n * to dynamic loading.\n */\n\n#ifdef IRIX5\n#  include <malloc.h> /*< for locking */\n#  include <sys/uio.h>\n#endif\n\n#if defined(MMAP_SUPPORTED) || defined(ADD_HEAP_GUARD_PAGES)\n#  if defined(USE_MUNMAP) && !defined(USE_MMAP) && !defined(CPPCHECK)\n#    error Invalid config: USE_MUNMAP requires USE_MMAP\n#  endif\n#  include <sys/mman.h>\n#  include <sys/stat.h>\n#endif\n\n#if defined(LINUX) && defined(SPECIFIC_MAIN_STACKBOTTOM)        \\\n    || defined(ADD_HEAP_GUARD_PAGES) || defined(MMAP_SUPPORTED) \\\n    || defined(NEED_PROC_MAPS)\n#  include <errno.h>\n#endif\n\n#if defined(DARWIN) && !defined(DYNAMIC_LOADING) \\\n    && !defined(GC_DONT_REGISTER_MAIN_STATIC_DATA)\n#  include <mach-o/getsect.h> /*< for `get_etext` and friends */\n#endif\n\n#ifdef DJGPP\n/*\n * Apparently necessary for djgpp 2.01.  May cause problems with\n * other versions.\n */\ntypedef long unsigned int caddr_t;\n#endif\n\n#ifdef NO_EXECUTE_PERMISSION\nSTATIC GC_bool GC_pages_executable = FALSE;\n#else\nSTATIC GC_bool GC_pages_executable = TRUE;\n#endif\n\n/* Note: it is undefined later on `GC_pages_executable` real use. */\n#define IGNORE_PAGES_EXECUTABLE 1\n\n#if ((defined(LINUX) && defined(SPECIFIC_MAIN_STACKBOTTOM)                  \\\n      || defined(NEED_PROC_MAPS) || defined(PROC_VDB) || defined(SOFT_VDB)) \\\n     && !defined(PROC_READ))                                                \\\n    || defined(CPPCHECK)\n/* Note: should probably call the real `read()`, if later is wrapped. */\n#  define PROC_READ read\n#endif\n\n#if defined(LINUX) && defined(SPECIFIC_MAIN_STACKBOTTOM) \\\n    || defined(NEED_PROC_MAPS)\n/*\n * Repeatedly perform a `read()` call until the buffer is filled up,\n * or we encounter EOF (end of file) or an error.\n */\nSTATIC ssize_t\nGC_repeat_read(int f, char *buf, size_t count)\n{\n  size_t num_read = 0;\n\n  ASSERT_CANCEL_DISABLED();\n  while (num_read < count) {\n    ssize_t result = PROC_READ(f, buf + num_read, count - num_read);\n\n    if (result < 0)\n      return result;\n    if (0 == result)\n      break;\n#  ifdef LINT2\n    if ((size_t)result > count - num_read)\n      ABORT(\"read() result cannot be bigger than requested length\");\n#  endif\n    num_read += (size_t)result;\n  }\n  return num_read;\n}\n#endif /* LINUX && SPECIFIC_MAIN_STACKBOTTOM || NEED_PROC_MAPS */\n\n#ifdef NEED_PROC_MAPS\n/*\n * We need to parse `/proc/self/maps` pseudo-file, either to find\n * dynamic libraries, and/or to find the register backing store\n * base (the IA-64 case).  Do it once here.\n */\n\n#  ifndef SINGLE_THREADED_PROCESS\n/*\n * Determine the length of a file by incrementally reading it into a buffer.\n * This would be silly to use it on a file supporting `lseek`, but Linux\n * `/proc` files usually do not.  As of Linux 4.15.0, `lseek(SEEK_END)` fails\n * for `/proc/self/maps` file.\n */\nSTATIC size_t\nGC_get_file_len(int f)\n{\n  size_t total = 0;\n#    define GET_FILE_LEN_BUF_SZ 500\n  char buf[GET_FILE_LEN_BUF_SZ];\n\n  ASSERT_CANCEL_DISABLED();\n  for (;;) {\n    ssize_t result = PROC_READ(f, buf, sizeof(buf));\n\n    if (result < 0) {\n      /* An error has occurred. */\n      return 0;\n    }\n    if (0 == result)\n      break;\n#    ifdef LINT2\n    if ((size_t)result >= GC_SIZE_MAX - total)\n      ABORT(\"Too big file is passed to GC_get_file_len\");\n#    endif\n    total += (size_t)result;\n  }\n  return total;\n}\n\nSTATIC size_t\nGC_get_maps_len(void)\n{\n  int f = open(\"/proc/self/maps\", O_RDONLY);\n  size_t result;\n\n  if (f < 0) {\n    /* Treat missing file as empty. */\n    return 0;\n  }\n  result = GC_get_file_len(f);\n  close(f);\n  return result;\n}\n#  endif /* !SINGLE_THREADED_PROCESS */\n\nGC_INNER const char *\nGC_get_maps(void)\n{\n  ssize_t result;\n  static char *maps_buf = NULL;\n  static size_t maps_buf_sz = 1;\n  size_t maps_size;\n#  ifndef SINGLE_THREADED_PROCESS\n  size_t old_maps_size = 0;\n#  endif\n\n  /* The buffer is essentially `static`, so there must be a single client. */\n  GC_ASSERT(I_HOLD_LOCK());\n\n  /*\n   * Note that in the presence of threads in the process (even if the\n   * collector itself is built single-threaded), the `maps` file can\n   * essentially shrink asynchronously and unexpectedly as threads\n   * that we already think of as dead release their stacks.\n   * And there is no easy way to read the entire file atomically.\n   * This is arguably a misfeature of the `/proc/self/maps` interface.\n   * Since we expect the file can grow asynchronously in rare cases,\n   * it should suffice to first determine the size (using `read()`),\n   * and then to reread the file.  If the size is inconsistent, then\n   * we have to retry.  This only matters with threads enabled, and\n   * if we use this to locate the data roots (not the default).\n   */\n\n#  ifndef SINGLE_THREADED_PROCESS\n  /* Determine the initial size of `/proc/self/maps` file. */\n  maps_size = GC_get_maps_len();\n  if (0 == maps_size)\n    ABORT(\"Cannot determine length of /proc/self/maps\");\n#  else\n  maps_size = 4000; /*< guess */\n#  endif\n\n  /*\n   * Read `/proc/self/maps` file, growing `maps_buf` as necessary.\n   * Note that we may not allocate conventionally, and thus cannot\n   * use `stdio` functionality.\n   */\n  do {\n    int f;\n\n    while (maps_size >= maps_buf_sz) {\n#  ifdef LINT2\n      /* Workaround passing tainted `maps_buf` to a tainted sink. */\n      GC_noop1_ptr(maps_buf);\n#  else\n      GC_scratch_recycle_no_gww(maps_buf, maps_buf_sz);\n#  endif\n      /* Grow only by powers of 2, since we leak \"too small\" buffers. */\n      while (maps_size >= maps_buf_sz)\n        maps_buf_sz *= 2;\n      maps_buf = GC_scratch_alloc(maps_buf_sz);\n      if (NULL == maps_buf)\n        ABORT_ARG1(\"Insufficient space for /proc/self/maps buffer\",\n                   \", %lu bytes requested\", (unsigned long)maps_buf_sz);\n#  ifndef SINGLE_THREADED_PROCESS\n      /*\n       * Recompute initial length, since we allocated.\n       * This can only happen a few times per program execution.\n       */\n      maps_size = GC_get_maps_len();\n      if (0 == maps_size)\n        ABORT(\"Cannot determine length of /proc/self/maps\");\n#  endif\n    }\n    GC_ASSERT(maps_buf_sz >= maps_size + 1);\n    f = open(\"/proc/self/maps\", O_RDONLY);\n    if (-1 == f)\n      ABORT_ARG1(\"Cannot open /proc/self/maps\", \": errno= %d\", errno);\n#  ifndef SINGLE_THREADED_PROCESS\n    old_maps_size = maps_size;\n#  endif\n    maps_size = 0;\n    do {\n      result = GC_repeat_read(f, maps_buf, maps_buf_sz - 1);\n      if (result < 0) {\n        ABORT_ARG1(\"Failed to read /proc/self/maps\", \": errno= %d\", errno);\n      }\n      maps_size += (size_t)result;\n    } while ((size_t)result == maps_buf_sz - 1);\n    close(f);\n    if (0 == maps_size)\n      ABORT(\"Empty /proc/self/maps\");\n#  ifndef SINGLE_THREADED_PROCESS\n    if (maps_size > old_maps_size) {\n      /* This might be caused by e.g. thread creation. */\n      WARN(\"Unexpected asynchronous /proc/self/maps growth\"\n           \" (to %\" WARN_PRIuPTR \" bytes)\\n\",\n           maps_size);\n    }\n#  endif\n  } while (maps_size >= maps_buf_sz\n#  ifndef SINGLE_THREADED_PROCESS\n           || maps_size < old_maps_size\n#  endif\n  );\n  maps_buf[maps_size] = '\\0';\n  return maps_buf;\n}\n\n/*\n * `GC_parse_map_entry` parses an entry from `/proc/self/maps` file so we\n * can locate all writable data segments that belong to shared libraries.\n * The format of one of these entries and the fields we care about\n * is as follows:\n * ```\n * XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537     name-of-mapping...\\n\n * ^^^^^^^^ ^^^^^^^^ ^^^^          ^^\n * *p_start *p_end   *p_prot       *p_maj_dev\n * ```\n *\n * Note that since about August 2003 kernels, the columns no longer have\n * fixed offsets on 64-bit kernels.  Hence we no longer rely on fixed\n * offsets anywhere, which is safer anyway.\n */\n\n#  if defined(DYNAMIC_LOADING) && defined(USE_PROC_FOR_LIBRARIES) \\\n      || defined(IA64) || defined(INCLUDE_LINUX_THREAD_DESCR)     \\\n      || (defined(CHECK_SOFT_VDB) && defined(MPROTECT_VDB))       \\\n      || defined(REDIR_MALLOC_AND_LINUXTHREADS)\nGC_INNER const char *\nGC_parse_map_entry(const char *maps_ptr, ptr_t *p_start, ptr_t *p_end,\n                   const char **p_prot, unsigned *p_maj_dev,\n                   const char **p_mapping_name)\n{\n  const unsigned char *start_start, *end_start, *maj_dev_start;\n  const unsigned char *p; /*< unsigned for `isspace`, `isxdigit` */\n\n  if (maps_ptr == NULL || *maps_ptr == '\\0') {\n    return NULL;\n  }\n\n  p = (const unsigned char *)maps_ptr;\n  while (isspace(*p))\n    ++p;\n  start_start = p;\n  GC_ASSERT(isxdigit(*start_start));\n  *p_start = (ptr_t)strtoul((const char *)start_start, (char **)&p, 16);\n  GC_ASSERT(*p == '-');\n\n  ++p;\n  end_start = p;\n  GC_ASSERT(isxdigit(*end_start));\n  *p_end = (ptr_t)strtoul((const char *)end_start, (char **)&p, 16);\n  GC_ASSERT(isspace(*p));\n\n  while (isspace(*p))\n    ++p;\n  GC_ASSERT(*p == 'r' || *p == '-');\n  *p_prot = (const char *)p;\n  /* Skip past protection field to offset field. */\n  while (!isspace(*p))\n    ++p;\n  while (isspace(*p))\n    p++;\n  GC_ASSERT(isxdigit(*p));\n  /* Skip past offset field, which we ignore. */\n  while (!isspace(*p))\n    ++p;\n  while (isspace(*p))\n    p++;\n  maj_dev_start = p;\n  GC_ASSERT(isxdigit(*maj_dev_start));\n  *p_maj_dev = strtoul((const char *)maj_dev_start, NULL, 16);\n\n  if (p_mapping_name != NULL) {\n    while (*p && *p != '\\n' && *p != '/' && *p != '[')\n      p++;\n    *p_mapping_name = (const char *)p;\n  }\n  while (*p && *p++ != '\\n') {\n    /* Empty. */\n  }\n  return (const char *)p;\n}\n#  endif /* REDIRECT_MALLOC || DYNAMIC_LOADING || IA64 || ... */\n\n#  if defined(IA64) || defined(INCLUDE_LINUX_THREAD_DESCR) \\\n      || (defined(CHECK_SOFT_VDB) && defined(MPROTECT_VDB))\nGC_INNER GC_bool\nGC_enclosing_writable_mapping(ptr_t addr, ptr_t *startp, ptr_t *endp)\n{\n  const char *prot;\n  ptr_t my_start, my_end;\n  const char *maps_ptr;\n  unsigned maj_dev;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  maps_ptr = GC_get_maps();\n  for (;;) {\n    maps_ptr = GC_parse_map_entry(maps_ptr, &my_start, &my_end, &prot,\n                                  &maj_dev, NULL);\n    if (NULL == maps_ptr)\n      break;\n\n    if (ADDR_INSIDE(addr, my_start, my_end)) {\n      if (prot[1] != 'w' || maj_dev != 0)\n        break;\n      *startp = my_start;\n      *endp = my_end;\n      return TRUE;\n    }\n  }\n  return FALSE;\n}\n#  endif /* IA64 || INCLUDE_LINUX_THREAD_DESCR */\n\n#  ifdef REDIR_MALLOC_AND_LINUXTHREADS\nGC_INNER GC_bool\nGC_text_mapping(const char *nm, ptr_t *startp, ptr_t *endp)\n{\n  size_t nm_len;\n  const char *prot, *map_path;\n  ptr_t my_start, my_end;\n  unsigned int maj_dev;\n  const char *maps_ptr;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  maps_ptr = GC_get_maps();\n  nm_len = strlen(nm);\n  for (;;) {\n    maps_ptr = GC_parse_map_entry(maps_ptr, &my_start, &my_end, &prot,\n                                  &maj_dev, &map_path);\n    if (NULL == maps_ptr)\n      break;\n\n    if (prot[0] == 'r' && prot[1] == '-' && prot[2] == 'x') {\n      const char *p = map_path;\n\n      /* Set `p` to point just past last slash, if any. */\n      while (*p != '\\0' && *p != '\\n' && *p != ' ' && *p != '\\t') {\n        ++p;\n      }\n      while (ADDR_GE((ptr_t)p, (ptr_t)map_path) && *p != '/') {\n        --p;\n      }\n      ++p;\n\n      if (strncmp(nm, p, nm_len) == 0) {\n        *startp = my_start;\n        *endp = my_end;\n        return TRUE;\n      }\n    }\n  }\n  return FALSE;\n}\n#  endif /* REDIR_MALLOC_AND_LINUXTHREADS */\n\n#  ifdef IA64\nstatic ptr_t\nbacking_store_base_from_proc(void)\n{\n  ptr_t my_start, my_end;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (!GC_enclosing_writable_mapping(GC_save_regs_in_stack(), &my_start,\n                                     &my_end)) {\n    GC_COND_LOG_PRINTF(\"Failed to find backing store base from /proc\\n\");\n    return 0;\n  }\n  return my_start;\n}\n#  endif\n\n#endif /* NEED_PROC_MAPS */\n\n#if defined(SEARCH_FOR_DATA_START)\n/*\n * The i686 case can be handled without a search.  The Alpha case used to\n * be handled differently as well, but the rules changed for recent Linux\n * versions.  This seems to be the easiest way to cover all versions.\n */\n\n#  if defined(LINUX) || defined(HURD)\n/*\n * Some Linux distributions arrange to define `__data_start`.\n * Some define `data_start` as a weak symbol.  The latter is technically\n * broken, since the user program may define `data_start`, in which\n * case we lose.  Nonetheless, we try both, preferring `__data_start`.\n * We assume gcc-compatible pragmas.\n */\nEXTERN_C_BEGIN\n#    pragma weak __data_start\n#    pragma weak data_start\nextern int __data_start[], data_start[];\nEXTERN_C_END\n#  elif defined(NETBSD)\nEXTERN_C_BEGIN\nextern char **environ;\nEXTERN_C_END\n#  endif\n\nptr_t GC_data_start = NULL;\n\nGC_INNER void\nGC_init_linux_data_start(void)\n{\n  ptr_t data_end = DATAEND;\n\n#  if (defined(LINUX) || defined(HURD)) && defined(USE_PROG_DATA_START)\n  /*\n   * Try the easy approaches first.  However, this may lead to wrong\n   * data start value if the collector code is put into a shared library\n   * (directly or indirectly) which is linked with `-Bsymbolic-functions`\n   * option.  Thus, the following is not used by default.\n   */\n  if (COVERT_DATAFLOW(ADDR(__data_start)) != 0) {\n    GC_data_start = (ptr_t)(__data_start);\n  } else {\n    GC_data_start = (ptr_t)(data_start);\n  }\n  if (COVERT_DATAFLOW(ADDR(GC_data_start)) != 0) {\n    if (ADDR_LT(data_end, GC_data_start))\n      ABORT_ARG2(\"Wrong __data_start/_end pair\", \": %p .. %p\",\n                 (void *)GC_data_start, (void *)data_end);\n    return;\n  }\n#    ifdef DEBUG_ADD_DEL_ROOTS\n  GC_log_printf(\"__data_start not provided\\n\");\n#    endif\n#  endif /* LINUX */\n\n  if (GC_no_dls) {\n    /*\n     * Not needed, avoids the `SIGSEGV` caused by `GC_find_limit` which\n     * complicates debugging.\n     */\n    GC_data_start = data_end; /*< set data root size to 0 */\n    return;\n  }\n\n#  ifdef NETBSD\n  /*\n   * This may need to be `environ`, without the underscore, for\n   * some versions.\n   */\n  GC_data_start = (ptr_t)GC_find_limit(&environ, FALSE);\n#  else\n  GC_data_start = (ptr_t)GC_find_limit(data_end, FALSE);\n#  endif\n}\n#endif /* SEARCH_FOR_DATA_START */\n\n#ifdef ECOS\nstatic void *\ntiny_sbrk(ptrdiff_t increment)\n{\n  /*\n   * TODO: This is a simple way of allocating memory which is compatible with\n   * ECOS early releases.  Later releases use a more sophisticated means of\n   * allocating memory than this simple static allocator, but this method is\n   * at least bound to work.\n   */\n  void *p = &GC_ecos_memory[GC_ecos_brk_idx];\n\n  GC_ASSERT(GC_ecos_brk_idx <= sizeof(GC_ecos_memory));\n  if ((size_t)increment > sizeof(GC_ecos_memory) - GC_ecos_brk_idx)\n    return NULL;\n  GC_ecos_brk_idx += (size_t)increment;\n  return p;\n}\n#  define sbrk tiny_sbrk\n#endif /* ECOS */\n\n#if defined(ADDRESS_SANITIZER)                         \\\n    && (defined(UNIX_LIKE) || defined(NEED_FIND_LIMIT) \\\n        || defined(MPROTECT_VDB))                      \\\n    && !defined(CUSTOM_ASAN_DEF_OPTIONS)\nEXTERN_C_BEGIN\nGC_API const char *__asan_default_options(void);\nEXTERN_C_END\n\n/*\n * To tell ASan to allow the collector to use its own `SIGBUS` and `SIGSEGV`\n * handlers.  The function is exported just to be visible to ASan library.\n */\nGC_API const char *\n__asan_default_options(void)\n{\n  return \"allow_user_segv_handler=1\";\n}\n#endif\n\n#ifdef OPENBSD\nstatic struct sigaction old_segv_act;\nSTATIC JMP_BUF GC_jmp_buf_openbsd;\n\nSTATIC void\nGC_fault_handler_openbsd(int sig)\n{\n  UNUSED_ARG(sig);\n  LONGJMP(GC_jmp_buf_openbsd, 1);\n}\n\nstatic volatile int firstpass;\n\n/*\n * Return first addressable location that is greater than `p` or return\n * `bound`.\n */\nSTATIC ptr_t\nGC_skip_hole_openbsd(ptr_t p, ptr_t bound)\n{\n  static volatile ptr_t result;\n  struct sigaction act;\n  size_t pgsz;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  pgsz = (size_t)sysconf(_SC_PAGESIZE);\n  GC_ASSERT(ADDR(bound) >= (word)pgsz);\n\n  act.sa_handler = GC_fault_handler_openbsd;\n  sigemptyset(&act.sa_mask);\n  act.sa_flags = SA_NODEFER | SA_RESTART;\n  /* `act.sa_restorer` is deprecated and should not be initialized. */\n  sigaction(SIGSEGV, &act, &old_segv_act);\n\n  firstpass = 1;\n  result = PTR_ALIGN_DOWN(p, pgsz);\n  if (SETJMP(GC_jmp_buf_openbsd) != 0 || firstpass) {\n    firstpass = 0;\n    if (ADDR_GE(result, bound - pgsz)) {\n      result = bound;\n    } else {\n      /*\n       * Notes: no overflow is expected; do not use compound assignment\n       * with `volatile`-qualified left operand.\n       */\n      result = result + pgsz;\n      GC_noop1((word)(unsigned char)(*result));\n    }\n  }\n\n  sigaction(SIGSEGV, &old_segv_act, 0);\n  return result;\n}\n#endif /* OPENBSD */\n\n#ifdef OS2\n\n#  include <stddef.h>\n\n#  if !defined(__IBMC__) && !defined(__WATCOMC__) /*< e.g. EMX */\n\nstruct exe_hdr {\n  unsigned short magic_number;\n  unsigned short padding[29];\n  long new_exe_offset;\n};\n\n#    define E_MAGIC(x) (x).magic_number\n#    define EMAGIC 0x5A4D\n#    define E_LFANEW(x) (x).new_exe_offset\n\nstruct e32_exe {\n  unsigned char magic_number[2];\n  unsigned char byte_order;\n  unsigned char word_order;\n  unsigned long exe_format_level;\n  unsigned short cpu;\n  unsigned short os;\n  unsigned long padding1[13];\n  unsigned long object_table_offset;\n  unsigned long object_count;\n  unsigned long padding2[31];\n};\n\n#    define E32_MAGIC1(x) (x).magic_number[0]\n#    define E32MAGIC1 'L'\n#    define E32_MAGIC2(x) (x).magic_number[1]\n#    define E32MAGIC2 'X'\n#    define E32_BORDER(x) (x).byte_order\n#    define E32LEBO 0\n#    define E32_WORDER(x) (x).word_order\n#    define E32LEWO 0\n#    define E32_CPU(x) (x).cpu\n#    define E32CPU286 1\n#    define E32_OBJTAB(x) (x).object_table_offset\n#    define E32_OBJCNT(x) (x).object_count\n\nstruct o32_obj {\n  unsigned long size;\n  unsigned long base;\n  unsigned long flags;\n  unsigned long pagemap;\n  unsigned long mapsize;\n  unsigned long reserved;\n};\n\n#    define O32_FLAGS(x) (x).flags\n#    define OBJREAD 0x0001L\n#    define OBJWRITE 0x0002L\n#    define OBJINVALID 0x0080L\n#    define O32_SIZE(x) (x).size\n#    define O32_BASE(x) (x).base\n\n#  else /* IBM's compiler */\n\n/* A kludge to get around what appears to be a header file bug. */\n#    ifndef WORD\n#      define WORD unsigned short\n#    endif\n#    ifndef DWORD\n#      define DWORD unsigned long\n#    endif\n\n#    define EXE386 1\n#    include <exe386.h>\n#    include <newexe.h>\n\n#  endif /* __IBMC__ */\n\n#  define INCL_DOSERRORS\n#  define INCL_DOSEXCEPTIONS\n#  define INCL_DOSFILEMGR\n#  define INCL_DOSMEMMGR\n#  define INCL_DOSMISC\n#  define INCL_DOSMODULEMGR\n#  define INCL_DOSPROCESS\n#  include <os2.h>\n\n#endif /* OS2 */\n\nGC_INNER size_t GC_page_size = 0;\n#ifdef REAL_PAGESIZE_NEEDED\nGC_INNER size_t GC_real_page_size = 0;\n#endif\n\n#ifdef SOFT_VDB\nSTATIC unsigned GC_log_pagesize = 0;\n#endif\n\n#ifdef ANY_MSWIN\n\n#  ifndef VER_PLATFORM_WIN32_CE\n#    define VER_PLATFORM_WIN32_CE 3\n#  endif\n\n#  if defined(MSWINCE) && defined(THREADS)\nGC_INNER GC_bool GC_dont_query_stack_min = FALSE;\n#  endif\n\nGC_INNER SYSTEM_INFO GC_sysinfo;\n\n#  ifndef CYGWIN32\n#    define is_writable(prot)                               \\\n      ((prot) == PAGE_READWRITE || (prot) == PAGE_WRITECOPY \\\n       || (prot) == PAGE_EXECUTE_READWRITE                  \\\n       || (prot) == PAGE_EXECUTE_WRITECOPY)\n/*\n * Return the number of bytes that are writable starting at `p`.\n * The pointer `p` is assumed to be page-aligned.  If `base` is not `NULL`,\n * then `*base` becomes the beginning of the allocation region containing `p`.\n */\nSTATIC word\nGC_get_writable_length(ptr_t p, ptr_t *base)\n{\n  MEMORY_BASIC_INFORMATION buf;\n  word result;\n  word protect;\n\n  result = VirtualQuery(p, &buf, sizeof(buf));\n  if (result != sizeof(buf))\n    ABORT(\"Weird VirtualQuery result\");\n  if (base != 0)\n    *base = (ptr_t)(buf.AllocationBase);\n  protect = buf.Protect & ~(word)(PAGE_GUARD | PAGE_NOCACHE);\n  if (!is_writable(protect) || buf.State != MEM_COMMIT)\n    return 0;\n  return buf.RegionSize;\n}\n\nGC_API int GC_CALL\nGC_get_stack_base(struct GC_stack_base *sb)\n{\n  /*\n   * Note: this function should not acquire the allocator lock as it is\n   * used by `GC_DllMain`.\n   */\n  ptr_t trunc_sp;\n  word size;\n\n  /*\n   * Set page size if it is not ready (so client can use this function even\n   * before the collector is initialized).\n   */\n  if (!GC_page_size)\n    GC_setpagesize();\n\n  trunc_sp = PTR_ALIGN_DOWN(GC_approx_sp(), GC_page_size);\n  /*\n   * FIXME: This will not work if called from a deeply recursive\n   * client code (and the committed stack space has grown).\n   */\n  size = GC_get_writable_length(trunc_sp, 0);\n  GC_ASSERT(size != 0);\n  sb->mem_base = trunc_sp + size;\n  return GC_SUCCESS;\n}\n#  else /* CYGWIN32 */\nGC_API int GC_CALL\nGC_get_stack_base(struct GC_stack_base *sb)\n{\n  /*\n   * An alternate variant for Cygwin (adapted from Dave Korn's gcc version\n   * of boehm-gc).\n   */\n#    ifdef X86_64\n  sb->mem_base = ((NT_TIB *)NtCurrentTeb())->StackBase;\n#    else\n  void *_tlsbase;\n\n  __asm__(\"movl %%fs:4, %0\" : \"=r\"(_tlsbase));\n  sb->mem_base = _tlsbase;\n#    endif\n  return GC_SUCCESS;\n}\n#  endif /* CYGWIN32 */\n#  define HAVE_GET_STACK_BASE\n\n#elif defined(OS2)\n\nstatic int\nos2_getpagesize(void)\n{\n  ULONG result[1];\n\n  if (DosQuerySysInfo(QSV_PAGE_SIZE, QSV_PAGE_SIZE, (void *)result,\n                      sizeof(ULONG))\n      != NO_ERROR) {\n    WARN(\"DosQuerySysInfo failed\\n\", 0);\n    result[0] = 4096;\n  }\n  return (int)result[0];\n}\n\n#endif /* !ANY_MSWIN && OS2 */\n\nGC_INNER void\nGC_setpagesize(void)\n{\n#ifdef ANY_MSWIN\n  GetSystemInfo(&GC_sysinfo);\n#  ifdef ALT_PAGESIZE_USED\n  /*\n   * Allocations made with `mmap()` are aligned to the allocation\n   * granularity, which (at least on Win64) is not the same as the\n   * page size.  Probably we could distinguish the allocation\n   * granularity from the actual page size, but in practice there\n   * is no good reason to make allocations smaller than\n   * `dwAllocationGranularity`, so we just use it instead of the\n   * actual page size here (as Cygwin itself does in many cases).\n   */\n  GC_page_size = (size_t)GC_sysinfo.dwAllocationGranularity;\n#    ifdef REAL_PAGESIZE_NEEDED\n  GC_real_page_size = (size_t)GC_sysinfo.dwPageSize;\n  GC_ASSERT(GC_page_size >= GC_real_page_size);\n#    endif\n#  else\n  GC_page_size = (size_t)GC_sysinfo.dwPageSize;\n#  endif\n#  if defined(MSWINCE) && !defined(_WIN32_WCE_EMULATION)\n  {\n    OSVERSIONINFO verInfo;\n\n    /* Check the current WinCE version. */\n    verInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\n    if (!GetVersionEx(&verInfo))\n      ABORT(\"GetVersionEx failed\");\n    if (verInfo.dwPlatformId == VER_PLATFORM_WIN32_CE\n        && verInfo.dwMajorVersion < 6) {\n      /*\n       * Only the first 32 MB of address space belongs to the\n       * current process (unless WinCE 6.0+ or emulation).\n       */\n      GC_sysinfo.lpMaximumApplicationAddress = (LPVOID)((word)32 << 20);\n#    ifdef THREADS\n      /*\n       * On some old WinCE versions, it is observed that\n       * `VirtualQuery()` calls do not work properly when used to\n       * get thread current stack committed minimum.\n       */\n      if (verInfo.dwMajorVersion < 5)\n        GC_dont_query_stack_min = TRUE;\n#    endif\n    }\n  }\n#  endif\n#else\n#  ifdef ALT_PAGESIZE_USED\n#    ifdef REAL_PAGESIZE_NEEDED\n  GC_real_page_size = (size_t)GETPAGESIZE();\n#    endif\n  /* It is acceptable to fake it. */\n  GC_page_size = HBLKSIZE;\n#  else\n  GC_page_size = (size_t)GETPAGESIZE();\n#    if !defined(CPPCHECK)\n  if (0 == GC_page_size)\n    ABORT(\"getpagesize failed\");\n#    endif\n#  endif\n#endif /* !ANY_MSWIN */\n#ifdef SOFT_VDB\n  {\n    size_t pgsize;\n    unsigned log_pgsize = 0;\n\n#  if !defined(CPPCHECK)\n    if (((GC_page_size - 1) & GC_page_size) != 0) {\n      /* Not a power of two. */\n      ABORT(\"Invalid page size\");\n    }\n#  endif\n    for (pgsize = GC_page_size; pgsize > 1; pgsize >>= 1)\n      log_pgsize++;\n    GC_log_pagesize = log_pgsize;\n  }\n#endif\n}\n\n#ifdef EMBOX\n#  include <kernel/thread/thread_stack.h>\n#  include <pthread.h>\n\nGC_API int GC_CALL\nGC_get_stack_base(struct GC_stack_base *sb)\n{\n  pthread_t self = pthread_self();\n  void *stack_addr = thread_stack_get(self);\n\n  /* TODO: Use `pthread_getattr_np`, `pthread_attr_getstack` alternatively. */\n#  ifdef STACK_GROWS_UP\n  sb->mem_base = stack_addr;\n#  else\n  sb->mem_base = (ptr_t)stack_addr + thread_stack_get_size(self);\n#  endif\n  return GC_SUCCESS;\n}\n#  define HAVE_GET_STACK_BASE\n#endif /* EMBOX */\n\n#ifdef OS2\nGC_API int GC_CALL\nGC_get_stack_base(struct GC_stack_base *sb)\n{\n  PTIB ptib; /*< thread information block */\n  PPIB ppib;\n\n  if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {\n    WARN(\"DosGetInfoBlocks failed\\n\", 0);\n    return GC_UNIMPLEMENTED;\n  }\n  sb->mem_base = ptib->tib_pstacklimit;\n  return GC_SUCCESS;\n}\n#  define HAVE_GET_STACK_BASE\n#endif /* OS2 */\n\n#ifdef SERENITY\n#  include <serenity.h>\n\nGC_API int GC_CALL\nGC_get_stack_base(struct GC_stack_base *sb)\n{\n  uintptr_t base;\n  size_t size;\n\n  if (get_stack_bounds(&base, &size) < 0) {\n    WARN(\"get_stack_bounds failed\\n\", 0);\n    return GC_UNIMPLEMENTED;\n  }\n  sb->mem_base = base + size;\n  return GC_SUCCESS;\n}\n#  define HAVE_GET_STACK_BASE\n#endif /* SERENITY */\n\n#if defined(NEED_FIND_LIMIT)                                 \\\n    || (defined(UNIX_LIKE) && !defined(NO_DEBUGGING))        \\\n    || (defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS)) \\\n    || (defined(WRAP_MARK_SOME) && defined(NO_SEH_AVAILABLE))\n\n#  include <signal.h>\n\n#  ifdef USE_SEGV_SIGACT\n#    ifndef OPENBSD\nstatic struct sigaction old_segv_act;\n#    endif\n#    ifdef USE_BUS_SIGACT\nstatic struct sigaction old_bus_act;\n#    endif\n#  else\nstatic GC_fault_handler_t old_segv_hand;\n#    ifdef HAVE_SIGBUS\nstatic GC_fault_handler_t old_bus_hand;\n#    endif\n#  endif /* !USE_SEGV_SIGACT */\n\nGC_INNER void\nGC_set_and_save_fault_handler(GC_fault_handler_t h)\n{\n#  ifdef USE_SEGV_SIGACT\n  struct sigaction act;\n\n  act.sa_handler = h;\n#    ifdef SIGACTION_FLAGS_NODEFER_HACK\n  /* Was necessary for Solaris 2.3 and very temporary NetBSD bugs. */\n  act.sa_flags = SA_RESTART | SA_NODEFER;\n#    else\n  act.sa_flags = SA_RESTART;\n#    endif\n\n  (void)sigemptyset(&act.sa_mask);\n  /* `act.sa_restorer` is deprecated and should not be initialized. */\n#    if defined(IRIX5) && defined(THREADS)\n  /*\n   * Older versions have a bug related to retrieving and setting\n   * a handler at the same time.\n   */\n  (void)sigaction(SIGSEGV, 0, &old_segv_act);\n  (void)sigaction(SIGSEGV, &act, 0);\n#    else\n  (void)sigaction(SIGSEGV, &act, &old_segv_act);\n#      ifdef USE_BUS_SIGACT\n  /*\n   * `pthreads` library does not exist under Irix 5.x, so we do not have\n   * to worry of the multi-threaded case.\n   */\n  (void)sigaction(SIGBUS, &act, &old_bus_act);\n#      endif\n#    endif /* !IRIX5 || !THREADS */\n#  else\n  old_segv_hand = signal(SIGSEGV, h);\n#    ifdef HAVE_SIGBUS\n  old_bus_hand = signal(SIGBUS, h);\n#    endif\n#  endif /* !USE_SEGV_SIGACT */\n#  if defined(CPPCHECK) && defined(ADDRESS_SANITIZER)\n  GC_noop1((word)(GC_funcptr_uint)(&__asan_default_options));\n#  endif\n}\n#endif /* NEED_FIND_LIMIT || UNIX_LIKE || WRAP_MARK_SOME */\n\n#if defined(NEED_FIND_LIMIT)                                 \\\n    || (defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS)) \\\n    || (defined(WRAP_MARK_SOME) && defined(NO_SEH_AVAILABLE))\nGC_INNER JMP_BUF GC_jmp_buf;\n\nSTATIC void\nGC_fault_handler(int sig)\n{\n  UNUSED_ARG(sig);\n  LONGJMP(GC_jmp_buf, 1);\n}\n\nGC_INNER void\nGC_setup_temporary_fault_handler(void)\n{\n  /*\n   * Handler is process-wide, so this should only happen in one thread\n   * at a time.\n   */\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_set_and_save_fault_handler(GC_fault_handler);\n}\n\nGC_INNER void\nGC_reset_fault_handler(void)\n{\n#  ifdef USE_SEGV_SIGACT\n  (void)sigaction(SIGSEGV, &old_segv_act, 0);\n#    ifdef USE_BUS_SIGACT\n  (void)sigaction(SIGBUS, &old_bus_act, 0);\n#    endif\n#  else\n  (void)signal(SIGSEGV, old_segv_hand);\n#    ifdef HAVE_SIGBUS\n  (void)signal(SIGBUS, old_bus_hand);\n#    endif\n#  endif\n}\n#endif /* NEED_FIND_LIMIT || USE_PROC_FOR_LIBRARIES || WRAP_MARK_SOME */\n\n#if defined(NEED_FIND_LIMIT) \\\n    || (defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS))\n#  define MIN_PAGE_SIZE 256 /*< smallest conceivable page size, in bytes */\n\n/*\n * Return the first non-addressable location greater than `p` (if `up`)\n * or the smallest location `q` such that [`q`,`p`) is addressable (if\n * not `up`).  We assume that `p` (if `up`) or `p - 1` (if not `up`) is\n * addressable.\n */\nGC_ATTR_NO_SANITIZE_ADDR\nSTATIC ptr_t\nGC_find_limit_with_bound(ptr_t p, GC_bool up, ptr_t bound)\n{\n  /*\n   * This is safer if `static`, since otherwise it may not be preserved\n   * across the `longjmp`.  Can safely be `static` since it is only called\n   * with the allocator lock held.\n   */\n  static volatile ptr_t result;\n\n  GC_ASSERT(up ? ADDR(bound) >= MIN_PAGE_SIZE\n               : ADDR(bound) <= ~(word)MIN_PAGE_SIZE);\n  GC_ASSERT(I_HOLD_LOCK());\n  result = PTR_ALIGN_DOWN(p, MIN_PAGE_SIZE);\n  GC_setup_temporary_fault_handler();\n  if (SETJMP(GC_jmp_buf) == 0) {\n    for (;;) {\n      if (up) {\n        if (ADDR_GE(result, bound - MIN_PAGE_SIZE)) {\n          result = bound;\n          break;\n        }\n        /*\n         * Notes: no overflow is expected; do not use compound assignment\n         * with `volatile`-qualified left operand.\n         */\n        result = result + MIN_PAGE_SIZE;\n      } else {\n        if (ADDR_GE(bound + MIN_PAGE_SIZE, result)) {\n          /*\n           * This is to compensate further result increment (we do not\n           * modify `up` variable since it might be clobbered by `setjmp()`\n           * otherwise).\n           */\n          result = bound - MIN_PAGE_SIZE;\n          break;\n        }\n        /* See the notes for the case when `up` is `TRUE`. */\n        result = result - MIN_PAGE_SIZE;\n      }\n      GC_noop1((word)(unsigned char)(*result));\n    }\n  }\n  GC_reset_fault_handler();\n  return up ? result : result + MIN_PAGE_SIZE;\n}\n\nvoid *\nGC_find_limit(void *p, int up)\n{\n  ptr_t bound;\n\n#  ifdef CHERI_PURECAP\n  bound = (ptr_t)cheri_address_set(p, cheri_base_get(p)\n                                          + (up ? cheri_length_get(p) : 0));\n#  else\n  bound = up ? MAKE_CPTR(GC_WORD_MAX) : NULL;\n#  endif\n  return GC_find_limit_with_bound((ptr_t)p, (GC_bool)up, bound);\n}\n#endif /* NEED_FIND_LIMIT || USE_PROC_FOR_LIBRARIES */\n\n#if defined(HPUX) && defined(IA64)\n#  include <sys/param.h>\n#  include <sys/pstat.h>\n\nGC_INNER ptr_t\nGC_get_register_stack_base(void)\n{\n  struct pst_vm_status vm_status;\n\n  int i = 0;\n  while (pstat_getprocvm(&vm_status, sizeof(vm_status), 0, i++) == 1) {\n    if (vm_status.pst_type == PS_RSESTACK) {\n      return (ptr_t)vm_status.pst_vaddr;\n    }\n  }\n\n  /* Old way to get the register stack bottom. */\n  GC_ASSERT(GC_stackbottom != NULL);\n  return PTR_ALIGN_DOWN(GC_stackbottom - BACKING_STORE_DISPLACEMENT - 1,\n                        BACKING_STORE_ALIGNMENT);\n}\n#endif /* HPUX && IA64 */\n\n#if defined(LINUX) && defined(IA64)\n#  ifdef USE_LIBC_PRIVATES\nEXTERN_C_BEGIN\n#    pragma weak __libc_ia64_register_backing_store_base\nextern ptr_t __libc_ia64_register_backing_store_base;\nEXTERN_C_END\n#  endif\n\nGC_INNER ptr_t\nGC_get_register_stack_base(void)\n{\n  ptr_t result;\n\n  GC_ASSERT(I_HOLD_LOCK());\n#  ifdef USE_LIBC_PRIVATES\n  {\n    ptr_t *p_libc_ia64_register_backing_store_base\n        = &__libc_ia64_register_backing_store_base;\n\n#    ifdef CPPCHECK\n    /*\n     * Workaround a warning that the address of the global symbol\n     * (which is a weak one) cannot be null.\n     */\n    GC_noop1_ptr(&p_libc_ia64_register_backing_store_base);\n#    endif\n    if (p_libc_ia64_register_backing_store_base != NULL\n        && __libc_ia64_register_backing_store_base != NULL) {\n      /*\n       * `glibc` 2.2.4 has a bug such that for dynamically linked\n       * executables `__libc_ia64_register_backing_store_base` is\n       * defined but uninitialized during constructor calls.\n       * Hence we check for both nonzero address and value.\n       */\n      return __libc_ia64_register_backing_store_base;\n    }\n  }\n#  endif\n  result = backing_store_base_from_proc();\n  if (0 == result) {\n    /* This works better than a constant displacement heuristic. */\n    result = (ptr_t)GC_find_limit(GC_save_regs_in_stack(), FALSE);\n  }\n  return result;\n}\n#endif /* LINUX && IA64 */\n\n#ifdef SPECIFIC_MAIN_STACKBOTTOM\n\n#  ifdef HPUX\n#    include <sys/param.h>\n#    include <sys/pstat.h>\n\nstatic ptr_t\nos_main_stackbottom(void)\n{\n  struct pst_vm_status vm_status;\n  int i = 0;\n\n  while (pstat_getprocvm(&vm_status, sizeof(vm_status), 0, i++) == 1) {\n    if (vm_status.pst_type == PS_STACK)\n      return (ptr_t)vm_status.pst_vaddr;\n  }\n\n  /* Old way to get the stack bottom. */\n#    ifdef STACK_GROWS_UP\n  return (ptr_t)GC_find_limit(GC_approx_sp(), FALSE);\n#    else\n  return (ptr_t)GC_find_limit(GC_approx_sp(), TRUE /* `up` */);\n#    endif\n}\n\n#  elif defined(LINUX)\n#    include <sys/stat.h>\n\n/* Number of fields preceding `startstack` one in `/proc/self/stat` file. */\n#    define STAT_SKIP 27\n\n#    ifdef USE_LIBC_PRIVATES\nEXTERN_C_BEGIN\n#      pragma weak __libc_stack_end\nextern ptr_t __libc_stack_end;\nEXTERN_C_END\n#    endif\n\nstatic ptr_t\nos_main_stackbottom(void)\n{\n  /*\n   * We read the stack bottom value from `/proc/self/stat` file.\n   * We do this using direct I/O system calls in order to avoid\n   * calling `malloc` in case `REDIRECT_MALLOC` is defined.\n   */\n#    define STAT_BUF_SIZE 4096\n  unsigned char stat_buf[STAT_BUF_SIZE];\n  int f;\n  word addr;\n  ssize_t i, buf_offset = 0, len;\n\n  /*\n   * First try the easy way.  This should work for `glibc` 2.2.\n   * This fails in a prelinked (`prelink` command) executable\n   * since the correct value of `__libc_stack_end` never becomes\n   * visible to us.  The second test is a workaround for this.\n   */\n#    ifdef USE_LIBC_PRIVATES\n  ptr_t *p_libc_stack_end = &__libc_stack_end;\n\n#      ifdef CPPCHECK\n  GC_noop1_ptr(&p_libc_stack_end);\n#      endif\n  if (p_libc_stack_end != NULL && __libc_stack_end != NULL) {\n#      ifdef IA64\n    /*\n     * Some versions of `glibc` set the address 16 bytes too low\n     * while the initialization code is running.\n     */\n    if ((ADDR(__libc_stack_end) & 0xfff) + 0x10 < 0x1000) {\n      return __libc_stack_end + 0x10;\n    } else {\n      /* It is not safe to add 16 bytes.  Thus, fall back to using `/proc`. */\n    }\n#      elif defined(SPARC)\n    /*\n     * Older versions of `glibc` for 64-bit SPARC do not set this\n     * variable correctly, it gets set to either zero or one.\n     */\n    if (ADDR(__libc_stack_end) != 1)\n      return __libc_stack_end;\n#      else\n    return __libc_stack_end;\n#      endif\n  }\n#    endif\n\n  f = open(\"/proc/self/stat\", O_RDONLY);\n  if (-1 == f)\n    ABORT_ARG1(\"Could not open /proc/self/stat\", \": errno= %d\", errno);\n  len = GC_repeat_read(f, (char *)stat_buf, sizeof(stat_buf));\n  if (len < 0)\n    ABORT_ARG1(\"Failed to read /proc/self/stat\", \": errno= %d\", errno);\n  close(f);\n\n  /*\n   * Skip the required number of fields.  This number is hopefully constant\n   * across all Linux implementations.\n   */\n  for (i = 0; i < STAT_SKIP; ++i) {\n    while (buf_offset < len && isspace(stat_buf[buf_offset++])) {\n      /* Empty. */\n    }\n    while (buf_offset < len && !isspace(stat_buf[buf_offset++])) {\n      /* Empty. */\n    }\n  }\n  /* Skip spaces. */\n  while (buf_offset < len && isspace(stat_buf[buf_offset])) {\n    buf_offset++;\n  }\n  /* Find the end of the number and cut the buffer there. */\n  for (i = 0; buf_offset + i < len; i++) {\n    if (!isdigit(stat_buf[buf_offset + i]))\n      break;\n  }\n  if (buf_offset + i >= len)\n    ABORT(\"Could not parse /proc/self/stat\");\n  stat_buf[buf_offset + i] = '\\0';\n\n  addr = (word)STRTOULL((char *)stat_buf + buf_offset, NULL, 10);\n  if (addr < 0x100000 || addr % ALIGNMENT != 0)\n    ABORT_ARG1(\"Absurd stack bottom value\", \": 0x%lx\", (unsigned long)addr);\n  return MAKE_CPTR(addr);\n}\n\n#  elif defined(QNX)\nstatic ptr_t\nos_main_stackbottom(void)\n{\n  /*\n   * TODO: This approach is not very exact but it works for the tests,\n   * at least, unlike other available heuristics.\n   */\n  return (ptr_t)__builtin_frame_address(0);\n}\n\n#  elif defined(FREEBSD)\n#    include <sys/sysctl.h>\n\n/*\n * This uses an undocumented `sysctl` call, but at least one expert\n * believes it will stay.\n */\nstatic ptr_t\nos_main_stackbottom(void)\n{\n  int nm[2] = { CTL_KERN, KERN_USRSTACK };\n  ptr_t base;\n  size_t len = sizeof(ptr_t);\n  int r = sysctl(nm, 2, &base, &len, NULL, 0);\n\n  if (r != 0)\n    ABORT(\"Error getting main stack base\");\n  return base;\n}\n#  endif\n\n#endif /* SPECIFIC_MAIN_STACKBOTTOM */\n\n#if defined(ECOS) || defined(NOSYS)\nGC_INNER ptr_t\nGC_get_main_stack_base(void)\n{\n  return STACKBOTTOM;\n}\n#  define GET_MAIN_STACKBASE_SPECIAL\n\n#elif defined(SYMBIAN)\nEXTERN_C_BEGIN\nextern int GC_get_main_symbian_stack_base(void);\nEXTERN_C_END\n\nGC_INNER ptr_t\nGC_get_main_stack_base(void)\n{\n  return (ptr_t)GC_get_main_symbian_stack_base();\n}\n#  define GET_MAIN_STACKBASE_SPECIAL\n\n#elif defined(EMSCRIPTEN)\n#  include <emscripten/stack.h>\n\nGC_INNER ptr_t\nGC_get_main_stack_base(void)\n{\n  return (ptr_t)emscripten_stack_get_base();\n}\n#  define GET_MAIN_STACKBASE_SPECIAL\n\n#elif !defined(ANY_MSWIN) && !defined(EMBOX) && !defined(OS2)        \\\n    && !(defined(OPENBSD) && defined(THREADS)) && !defined(SERENITY) \\\n    && (!(defined(SOLARIS) && defined(THREADS)) || defined(_STRICT_STDC))\n\n#  if (defined(HAVE_PTHREAD_ATTR_GET_NP) || defined(HAVE_PTHREAD_GETATTR_NP)) \\\n      && (defined(THREADS) || defined(USE_GET_STACKBASE_FOR_MAIN))\n#    include <pthread.h>\n#    ifdef HAVE_PTHREAD_NP_H\n#      include <pthread_np.h> /*< for `pthread_attr_get_np()` */\n#    endif\n#  elif defined(DARWIN) && !defined(NO_PTHREAD_GET_STACKADDR_NP)\n/*\n * We could use `pthread_get_stackaddr_np` even in case of a single-threaded\n * collector build (there is no `-lpthread` option on Darwin).\n */\n#    include <pthread.h>\n#    undef STACKBOTTOM\n#    define STACKBOTTOM (ptr_t) pthread_get_stackaddr_np(pthread_self())\n#  endif\n\nGC_INNER ptr_t\nGC_get_main_stack_base(void)\n{\n  ptr_t result;\n#  if (defined(HAVE_PTHREAD_ATTR_GET_NP) || defined(HAVE_PTHREAD_GETATTR_NP)) \\\n      && (defined(USE_GET_STACKBASE_FOR_MAIN)                                 \\\n          || (defined(THREADS) && !defined(REDIRECT_MALLOC)))\n  pthread_attr_t attr;\n  void *stackaddr;\n  size_t size;\n\n#    ifdef HAVE_PTHREAD_ATTR_GET_NP\n  if (pthread_attr_init(&attr) == 0\n      && (pthread_attr_get_np(pthread_self(), &attr) == 0\n              ? TRUE\n              : (pthread_attr_destroy(&attr), FALSE)))\n#    else /* HAVE_PTHREAD_GETATTR_NP */\n  if (pthread_getattr_np(pthread_self(), &attr) == 0)\n#    endif\n  {\n    if (pthread_attr_getstack(&attr, &stackaddr, &size) == 0\n        && stackaddr != NULL) {\n      (void)pthread_attr_destroy(&attr);\n#    ifndef STACK_GROWS_UP\n      stackaddr = (char *)stackaddr + size;\n#    endif\n      return (ptr_t)stackaddr;\n    }\n    (void)pthread_attr_destroy(&attr);\n  }\n  WARN(\"pthread_getattr_np or pthread_attr_getstack failed\"\n       \" for main thread\\n\",\n       0);\n#  endif\n#  ifdef STACKBOTTOM\n  result = STACKBOTTOM;\n#  else\n#    ifdef HEURISTIC1\n#      define STACKBOTTOM_ALIGNMENT_M1 ((word)STACK_GRAN - 1)\n#      ifdef STACK_GROWS_UP\n  result = PTR_ALIGN_DOWN(GC_approx_sp(), STACKBOTTOM_ALIGNMENT_M1 + 1);\n#      else\n  result = PTR_ALIGN_UP(GC_approx_sp(), STACKBOTTOM_ALIGNMENT_M1 + 1);\n#      endif\n#    elif defined(SPECIFIC_MAIN_STACKBOTTOM)\n  result = os_main_stackbottom();\n#    elif defined(HEURISTIC2)\n  {\n    ptr_t sp = GC_approx_sp();\n\n#      ifdef STACK_GROWS_UP\n    result = (ptr_t)GC_find_limit(sp, FALSE);\n#      else\n    result = (ptr_t)GC_find_limit(sp, TRUE /* `up` */);\n#      endif\n#      if defined(HEURISTIC2_LIMIT) && !defined(CPPCHECK)\n    if (HOTTER_THAN(HEURISTIC2_LIMIT, result)\n        && HOTTER_THAN(sp, HEURISTIC2_LIMIT))\n      result = HEURISTIC2_LIMIT;\n#      endif\n  }\n#    elif defined(STACK_NOT_SCANNED) || defined(CPPCHECK)\n  result = NULL;\n#    else\n#      error None of HEURISTIC* and *STACKBOTTOM defined!\n#    endif\n#    if !defined(STACK_GROWS_UP) && !defined(CPPCHECK)\n  if (NULL == result)\n    result = MAKE_CPTR((GC_signed_word)(-sizeof(ptr_t)));\n#    endif\n#  endif\n#  if !defined(CPPCHECK)\n  GC_ASSERT(HOTTER_THAN(GC_approx_sp(), result));\n#  endif\n  return result;\n}\n#  define GET_MAIN_STACKBASE_SPECIAL\n#endif /* !ANY_MSWIN && !EMBOX && !OS2 && !SERENITY */\n\n#if (defined(HAVE_PTHREAD_ATTR_GET_NP) || defined(HAVE_PTHREAD_GETATTR_NP)) \\\n    && defined(THREADS) && !defined(HAVE_GET_STACK_BASE)\n#  include <pthread.h>\n#  ifdef HAVE_PTHREAD_NP_H\n#    include <pthread_np.h>\n#  endif\n\nGC_API int GC_CALL\nGC_get_stack_base(struct GC_stack_base *b)\n{\n  pthread_attr_t attr;\n  size_t size;\n\n#  ifdef HAVE_PTHREAD_ATTR_GET_NP\n  if (pthread_attr_init(&attr) != 0)\n    ABORT(\"pthread_attr_init failed\");\n  if (pthread_attr_get_np(pthread_self(), &attr) != 0) {\n    WARN(\"pthread_attr_get_np failed\\n\", 0);\n    (void)pthread_attr_destroy(&attr);\n    return GC_UNIMPLEMENTED;\n  }\n#  else /* HAVE_PTHREAD_GETATTR_NP */\n  if (pthread_getattr_np(pthread_self(), &attr) != 0) {\n    WARN(\"pthread_getattr_np failed\\n\", 0);\n    return GC_UNIMPLEMENTED;\n  }\n#  endif\n  if (pthread_attr_getstack(&attr, &b->mem_base, &size) != 0) {\n    ABORT(\"pthread_attr_getstack failed\");\n  }\n  (void)pthread_attr_destroy(&attr);\n#  ifndef STACK_GROWS_UP\n  b->mem_base = (char *)b->mem_base + size;\n#  endif\n#  ifdef IA64\n  /*\n   * We could try `backing_store_base_from_proc`, but that is safe only\n   * if no mappings are being asynchronously created.  Subtracting the size\n   * from the stack base does not work for at least the main thread.\n   */\n  LOCK();\n  {\n    IF_CANCEL(int cancel_state;)\n    ptr_t bsp;\n    ptr_t next_stack;\n\n    DISABLE_CANCEL(cancel_state);\n    bsp = GC_save_regs_in_stack();\n    next_stack = GC_greatest_stack_base_below(bsp);\n    if (NULL == next_stack) {\n      b->reg_base = GC_find_limit(bsp, FALSE);\n    } else {\n      /*\n       * Avoid walking backwards into preceding memory stack and\n       * growing it.\n       */\n      b->reg_base = GC_find_limit_with_bound(bsp, FALSE, next_stack);\n    }\n    RESTORE_CANCEL(cancel_state);\n  }\n  UNLOCK();\n#  elif defined(E2K)\n  b->reg_base = NULL;\n#  endif\n  return GC_SUCCESS;\n}\n#  define HAVE_GET_STACK_BASE\n#endif /* THREADS && (HAVE_PTHREAD_ATTR_GET_NP || HAVE_PTHREAD_GETATTR_NP) */\n\n#if defined(DARWIN) && defined(THREADS) \\\n    && !defined(NO_PTHREAD_GET_STACKADDR_NP)\n#  include <pthread.h>\n\nGC_API int GC_CALL\nGC_get_stack_base(struct GC_stack_base *b)\n{\n  /*\n   * `pthread_get_stackaddr_np()` should return stack bottom (highest\n   * stack address plus 1).\n   */\n  b->mem_base = pthread_get_stackaddr_np(pthread_self());\n  GC_ASSERT(HOTTER_THAN(GC_approx_sp(), (ptr_t)b->mem_base));\n  return GC_SUCCESS;\n}\n#  define HAVE_GET_STACK_BASE\n#endif /* DARWIN && THREADS && !NO_PTHREAD_GET_STACKADDR_NP */\n\n#if defined(OPENBSD) && defined(THREADS)\n#  include <pthread.h>\n#  include <pthread_np.h>\n#  include <sys/signal.h>\n\nGC_API int GC_CALL\nGC_get_stack_base(struct GC_stack_base *sb)\n{\n  stack_t stack;\n\n  /* Find the stack using `pthread_stackseg_np()`. */\n  if (pthread_stackseg_np(pthread_self(), &stack))\n    ABORT(\"pthread_stackseg_np(self) failed\");\n  sb->mem_base = stack.ss_sp;\n  return GC_SUCCESS;\n}\n#  define HAVE_GET_STACK_BASE\n#endif /* OPENBSD && THREADS */\n\n#if defined(SOLARIS) && defined(THREADS) && !defined(_STRICT_STDC)\n\n#  include <pthread.h>\n#  include <thread.h>\n\n/*\n * These variables are used to cache `ss_sp` value for the primordial\n * thread (it is better not to call `thr_stksegment()` twice for this\n * thread - see JDK bug #4352906).\n * Note: `stackbase_main_self` set to zero means `stackbase_main_ss_sp`\n * value is unset.\n */\nstatic pthread_t stackbase_main_self = 0;\nstatic void *stackbase_main_ss_sp = NULL;\n\n#  ifdef CAN_HANDLE_FORK\nGC_INNER void\nGC_stackbase_info_update_after_fork(void)\n{\n  if (stackbase_main_self == GC_parent_pthread_self) {\n    /* The primordial thread has forked the process. */\n    stackbase_main_self = pthread_self();\n  } else {\n    stackbase_main_self = 0;\n  }\n}\n#  endif\n\nGC_API int GC_CALL\nGC_get_stack_base(struct GC_stack_base *b)\n{\n  stack_t s;\n  pthread_t self = pthread_self();\n\n  if (self == stackbase_main_self) {\n    /*\n     * If the client calls `GC_get_stack_base()` from the main thread,\n     * then just return the cached value.\n     */\n    b->mem_base = stackbase_main_ss_sp;\n    GC_ASSERT(b->mem_base != NULL);\n    return GC_SUCCESS;\n  }\n\n  if (thr_stksegment(&s)) {\n    /*\n     * According to the manual, the only failure error code returned is\n     * `EAGAIN` meaning \"the information is not available due to the thread\n     * is not yet completely initialized or it is an internal thread\" - this\n     * should not happen here.\n     */\n    ABORT(\"thr_stksegment failed\");\n  }\n  /* `s.ss_sp` holds the pointer to the stack bottom. */\n  GC_ASSERT(HOTTER_THAN(GC_approx_sp(), (ptr_t)s.ss_sp));\n\n  if (!stackbase_main_self && thr_main() != 0) {\n    /*\n     * Cache the stack bottom pointer for the primordial thread\n     * (this is done during `GC_init`, so there is no race).\n     */\n    stackbase_main_ss_sp = s.ss_sp;\n    stackbase_main_self = self;\n  }\n\n  b->mem_base = s.ss_sp;\n  return GC_SUCCESS;\n}\n#  define HAVE_GET_STACK_BASE\n#endif /* SOLARIS && THREADS */\n\n#if defined(RTEMS) && defined(THREADS)\nGC_API int GC_CALL\nGC_get_stack_base(struct GC_stack_base *sb)\n{\n  sb->mem_base = rtems_get_stack_bottom();\n  return GC_SUCCESS;\n}\n#  define HAVE_GET_STACK_BASE\n#endif /* RTEMS && THREADS */\n\n#ifndef HAVE_GET_STACK_BASE\n\n#  ifdef NEED_FIND_LIMIT\nGC_API int GC_CALL\nGC_get_stack_base(struct GC_stack_base *b)\n{\n  IF_CANCEL(int cancel_state;)\n\n  /*\n   * Note: using the `GC_find_limit` variant is risky; in the IA-64 case,\n   * e.g., there is no guard page between the stack of one thread and the\n   * register backing store of the next; thus this is likely to identify way\n   * too large a \"stack\" and thus at least result in disastrous performance.\n   */\n  /* TODO: Implement better strategies here. */\n  LOCK();\n  /* TODO: `DISABLE_CANCEL` may be unnecessary? */\n  DISABLE_CANCEL(cancel_state);\n#    ifdef STACK_GROWS_UP\n  b->mem_base = GC_find_limit(GC_approx_sp(), FALSE);\n#    else\n  b->mem_base = GC_find_limit(GC_approx_sp(), TRUE /* `up` */);\n#    endif\n#    ifdef IA64\n  b->reg_base = GC_find_limit(GC_save_regs_in_stack(), FALSE);\n#    elif defined(E2K)\n  b->reg_base = NULL;\n#    endif\n  RESTORE_CANCEL(cancel_state);\n  UNLOCK();\n  return GC_SUCCESS;\n}\n#  else /* !NEED_FIND_LIMIT */\nGC_API int GC_CALL\nGC_get_stack_base(struct GC_stack_base *b)\n{\n#    if defined(GET_MAIN_STACKBASE_SPECIAL) && !defined(THREADS) \\\n        && !defined(IA64)\n  b->mem_base = GC_get_main_stack_base();\n  return GC_SUCCESS;\n#    else\n  UNUSED_ARG(b);\n  return GC_UNIMPLEMENTED;\n#    endif\n}\n#  endif\n\n#endif /* !HAVE_GET_STACK_BASE */\n\n#ifndef GET_MAIN_STACKBASE_SPECIAL\nGC_INNER ptr_t\nGC_get_main_stack_base(void)\n{\n  /* Default implementation. */\n  struct GC_stack_base sb;\n\n  if (GC_get_stack_base(&sb) != GC_SUCCESS)\n    ABORT(\"GC_get_stack_base failed\");\n  GC_ASSERT(HOTTER_THAN(GC_approx_sp(), (ptr_t)sb.mem_base));\n  return (ptr_t)sb.mem_base;\n}\n#endif /* !GET_MAIN_STACKBASE_SPECIAL */\n\n/*\n * Register static data segment(s) as roots.  If more data segments are\n * added later, then they need to be registered at that point (as we do\n * with SunOS dynamic loading), or `GC_mark_roots` needs to check for them.\n */\n\n#ifdef ANY_MSWIN\n\n#  if defined(GWW_VDB)\n#    ifndef MEM_WRITE_WATCH\n#      define MEM_WRITE_WATCH 0x200000\n#    endif\n#    ifndef WRITE_WATCH_FLAG_RESET\n#      define WRITE_WATCH_FLAG_RESET 1\n#    endif\n\n/*\n * Since we cannot easily check whether `ULONG_PTR` and `SIZE_T` are\n * defined in Win32 `basetsd.h` file, we define own `ULONG_PTR`.\n */\n#    define GC_ULONG_PTR word\n\ntypedef UINT(WINAPI *GetWriteWatch_type)(DWORD, PVOID,\n                                         GC_ULONG_PTR /* `SIZE_T` */, PVOID *,\n                                         GC_ULONG_PTR *, PULONG);\nstatic FARPROC GetWriteWatch_func;\nstatic DWORD GetWriteWatch_alloc_flag;\n\n#    define GC_GWW_AVAILABLE() (GetWriteWatch_func != 0)\n\nstatic void\ndetect_GetWriteWatch(void)\n{\n  static GC_bool done;\n  HMODULE hK32;\n  if (done)\n    return;\n\n#    if defined(MPROTECT_VDB)\n  {\n    char *str = GETENV(\"GC_USE_GETWRITEWATCH\");\n#      if defined(GC_PREFER_MPROTECT_VDB)\n    if (NULL == str || (*str == '0' && *(str + 1) == '\\0')) {\n      /*\n       * `GC_USE_GETWRITEWATCH` environment variable is unset or set to \"0\".\n       * Falling back to `MPROTECT_VDB` strategy.\n       */\n      done = TRUE;\n      /* This should work as if `GWW_VDB` macro is not defined. */\n      return;\n    }\n#      else\n    if (str != NULL && *str == '0' && *(str + 1) == '\\0') {\n      /*\n       * `GC_USE_GETWRITEWATCH` environment variable is set \"0\".\n       * Falling back to `MPROTECT_VDB` strategy.\n       */\n      done = TRUE;\n      return;\n    }\n#      endif\n  }\n#    endif\n\n#    if defined(MSWINRT_FLAVOR) && defined(FUNCPTR_IS_DATAPTR)\n  {\n    MEMORY_BASIC_INFORMATION memInfo;\n    SIZE_T result = VirtualQuery(CAST_THRU_UINTPTR(void *, GetProcAddress),\n                                 &memInfo, sizeof(memInfo));\n\n    if (result != sizeof(memInfo))\n      ABORT(\"Weird VirtualQuery result\");\n    hK32 = (HMODULE)memInfo.AllocationBase;\n  }\n#    else\n  hK32 = GetModuleHandle(TEXT(\"kernel32.dll\"));\n#    endif\n  if (hK32 != (HMODULE)0\n      && (GetWriteWatch_func = GetProcAddress(hK32, \"GetWriteWatch\")) != 0) {\n    void *page;\n\n    GC_ASSERT(GC_page_size != 0);\n    /*\n     * Also check whether `VirtualAlloc()` accepts `MEM_WRITE_WATCH`,\n     * as some versions of `kernel32.dll` library have one but not the other,\n     * making the feature completely broken.\n     */\n    page = VirtualAlloc(NULL, GC_page_size, MEM_WRITE_WATCH | MEM_RESERVE,\n                        PAGE_READWRITE);\n    if (page != NULL) {\n      PVOID pages[16];\n      GC_ULONG_PTR count = sizeof(pages) / sizeof(PVOID);\n      DWORD page_size;\n      /*\n       * Check that it actually works.  In spite of some documentation\n       * it actually seems to exist on Win2K.\n       * This test may be unnecessary, but...\n       */\n      if ((*(GetWriteWatch_type)(GC_funcptr_uint)GetWriteWatch_func)(\n              WRITE_WATCH_FLAG_RESET, page, GC_page_size, pages, &count,\n              &page_size)\n          != 0) {\n        /* `GetWriteWatch()` always fails. */\n        GetWriteWatch_func = 0;\n      } else {\n        GetWriteWatch_alloc_flag = MEM_WRITE_WATCH;\n      }\n      VirtualFree(page, 0 /* `dwSize` */, MEM_RELEASE);\n    } else {\n      /* `GetWriteWatch` will be useless. */\n      GetWriteWatch_func = 0;\n    }\n  }\n  done = TRUE;\n}\n\n#  else\n#    define GetWriteWatch_alloc_flag 0\n#  endif /* !GWW_VDB */\n\n#  ifdef MSWIN32\n/*\n * Unfortunately, we have to handle win32s very differently from Windows NT,\n * since `VirtualQuery()` has very different semantics.  In particular,\n * under win32s a `VirtualQuery()` call on an unmapped page returns\n * an invalid result.  Under Windows NT, `GC_register_data_segments()` is\n * a no-op and all real work is done by `GC_register_dynamic_libraries()`.\n * Under win32s, we cannot find the data segments associated with DLL files.\n * We register the main data segment here.\n */\n\nGC_INNER GC_bool GC_no_win32_dlls = FALSE;\n\nGC_INNER GC_bool GC_wnt = FALSE;\n\nGC_INNER void\nGC_init_win32(void)\n{\n#    if defined(_WIN64) || (defined(_MSC_VER) && _MSC_VER >= 1800)\n  /*\n   * MS Visual Studio 2013 deprecates `GetVersion`, but on the other hand\n   * it cannot be used to target pre-Win2K.\n   */\n  GC_wnt = TRUE;\n#    else\n  /*\n   * Set `GC_wnt`.  If we are running under win32s, assume that no DLL file\n   * will be loaded.  I doubt anyone still runs win32s, but...\n   */\n  DWORD v = GetVersion();\n\n  GC_wnt = !(v & (DWORD)0x80000000UL);\n  GC_no_win32_dlls |= ((!GC_wnt) && (v & 0xff) <= 3);\n#    endif\n#    ifdef USE_MUNMAP\n  if (GC_no_win32_dlls) {\n    /*\n     * Turn off unmapping for safety (since may not work well with\n     * `GlobalAlloc()`).\n     */\n    GC_unmap_threshold = 0;\n  }\n#    endif\n}\n\n/*\n * Return the smallest address `p` such that `VirtualQuery()` returns\n * correct results for all addresses between `p` and `start`.\n * Assumes `VirtualQuery()` returns correct information for `start`.\n */\nSTATIC ptr_t\nGC_least_described_address(ptr_t start)\n{\n  ptr_t limit = (ptr_t)GC_sysinfo.lpMinimumApplicationAddress;\n  ptr_t p = PTR_ALIGN_DOWN(start, GC_page_size);\n\n  GC_ASSERT(GC_page_size != 0);\n  for (;;) {\n    MEMORY_BASIC_INFORMATION buf;\n    size_t result;\n    ptr_t q;\n\n    if (UNLIKELY(ADDR(p) <= (word)GC_page_size))\n      break; /*< avoid underflow */\n    q = p - GC_page_size;\n    if (ADDR_LT(q, limit))\n      break;\n\n    result = VirtualQuery((LPVOID)q, &buf, sizeof(buf));\n    if (result != sizeof(buf) || 0 == buf.AllocationBase)\n      break;\n    p = (ptr_t)buf.AllocationBase;\n  }\n  return p;\n}\n\nSTATIC void\nGC_register_root_section(ptr_t static_root)\n{\n  ptr_t p, base, limit;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (!GC_no_win32_dlls)\n    return;\n\n  p = GC_least_described_address(static_root);\n  base = limit = p;\n  while (ADDR_LT(p, (ptr_t)GC_sysinfo.lpMaximumApplicationAddress)) {\n    MEMORY_BASIC_INFORMATION buf;\n    size_t result = VirtualQuery((LPVOID)p, &buf, sizeof(buf));\n\n    if (result != sizeof(buf) || 0 == buf.AllocationBase\n        || GC_is_heap_base(buf.AllocationBase))\n      break;\n    if (ADDR(p) > GC_WORD_MAX - buf.RegionSize) {\n      /* Avoid overflow. */\n      break;\n    }\n    if (buf.State == MEM_COMMIT && is_writable(buf.Protect)) {\n      if (p != limit) {\n        if (base != limit)\n          GC_add_roots_inner(base, limit, FALSE);\n        base = p;\n      }\n      limit = p + buf.RegionSize;\n    }\n    p += buf.RegionSize;\n  }\n  if (base != limit)\n    GC_add_roots_inner(base, limit, FALSE);\n}\n#  endif /* MSWIN32 */\n\n#  if defined(USE_WINALLOC) && !defined(REDIRECT_MALLOC)\n/*\n * We maintain a linked list of `AllocationBase` values (that we know)\n * correspond to `malloc` heap sections.  Currently this is only called\n * during a collection.  But there is some hope that for long-running\n * programs we will eventually see most heap sections.\n *\n * In the long run, it would be more reliable to occasionally walk\n * the `malloc` heap with `HeapWalk()` on the default heap.\n * But that apparently works only for NT-based Windows.\n */\n\n/* Note: initialized to approximate largest root size. */\n#    define GC_INITIAL_MAX_ROOT_SIZE 100000\nSTATIC size_t GC_max_root_size = GC_INITIAL_MAX_ROOT_SIZE;\n\n/* In the long run, a better data structure would also be nice... */\nSTATIC struct GC_malloc_heap_list {\n  void *allocation_base;\n  struct GC_malloc_heap_list *next;\n} *GC_malloc_heap_l = NULL;\n\n/*\n * Is `p` the base of one of the `malloc` heap sections we already\n * know about?\n */\nSTATIC GC_bool\nGC_is_malloc_heap_base(const void *p)\n{\n  struct GC_malloc_heap_list *q;\n\n  for (q = GC_malloc_heap_l; q != NULL; q = q->next) {\n    if (q->allocation_base == p)\n      return TRUE;\n  }\n  return FALSE;\n}\n\nSTATIC void *\nGC_get_allocation_base(void *p)\n{\n  MEMORY_BASIC_INFORMATION buf;\n  size_t result = VirtualQuery(p, &buf, sizeof(buf));\n\n  if (result != sizeof(buf)) {\n    ABORT(\"Weird VirtualQuery result\");\n  }\n  return buf.AllocationBase;\n}\n\nGC_INNER void\nGC_add_current_malloc_heap(void)\n{\n  struct GC_malloc_heap_list *new_l = (struct GC_malloc_heap_list *)malloc(\n      sizeof(struct GC_malloc_heap_list));\n  void *candidate;\n\n  if (NULL == new_l)\n    return;\n  /* Explicitly set to suppress \"maybe-uninitialized\" gcc warning. */\n  new_l->allocation_base = NULL;\n\n  candidate = GC_get_allocation_base(new_l);\n  if (GC_is_malloc_heap_base(candidate)) {\n    /* Try a little harder to find `malloc` heap. */\n    size_t req_size = 10000;\n\n    do {\n      void *p = malloc(req_size);\n\n      if (NULL == p) {\n        free(new_l);\n        return;\n      }\n      candidate = GC_get_allocation_base(p);\n      free(p);\n      req_size *= 2;\n    } while (GC_is_malloc_heap_base(candidate)\n             && req_size < GC_max_root_size / 10 && req_size < 500000);\n    if (GC_is_malloc_heap_base(candidate)) {\n      free(new_l);\n      return;\n    }\n  }\n  GC_COND_LOG_PRINTF(\"Found new system malloc AllocationBase at %p\\n\",\n                     candidate);\n  new_l->allocation_base = candidate;\n  new_l->next = GC_malloc_heap_l;\n  GC_malloc_heap_l = new_l;\n}\n\n#    ifndef GC_NO_DEINIT\n/*\n * Free all the linked list nodes.  Could be invoked at process exit\n * to avoid memory leak complains of a dynamic code analysis tool.\n */\nSTATIC void\nGC_free_malloc_heap_list(void)\n{\n  struct GC_malloc_heap_list *q = GC_malloc_heap_l;\n\n  GC_malloc_heap_l = NULL;\n  GC_max_root_size = GC_INITIAL_MAX_ROOT_SIZE;\n  while (q != NULL) {\n    struct GC_malloc_heap_list *next = q->next;\n\n    free(q);\n    q = next;\n  }\n}\n#    endif\n#  endif /* USE_WINALLOC && !REDIRECT_MALLOC */\n\nGC_INNER GC_bool\nGC_is_heap_base(const void *p)\n{\n  size_t i;\n\n#  if defined(USE_WINALLOC) && !defined(REDIRECT_MALLOC)\n  if (GC_root_size > GC_max_root_size)\n    GC_max_root_size = GC_root_size;\n  if (GC_is_malloc_heap_base(p))\n    return TRUE;\n#  endif\n  for (i = 0; i < GC_n_heap_bases; i++) {\n    if (GC_heap_bases[i] == p)\n      return TRUE;\n  }\n  return FALSE;\n}\n\nGC_INNER void\nGC_register_data_segments(void)\n{\n#  ifdef MSWIN32\n  /* Note: any other GC global variable would fit too. */\n  GC_register_root_section((ptr_t)&GC_pages_executable);\n#  endif\n}\n\n#endif /* ANY_MSWIN */\n\n#ifdef DATASTART_USES_XGETDATASTART\n#  ifdef CHERI_PURECAP\n#    include <link.h>\n\n/*\n * The CheriBSD LLVM compiler declares `etext`, `edata` and `end` as\n * typeless variables.  If the collector library is statically linked\n * with the executable, these capabilities are compiled with the\n * read-only permissions and bounds that span the `.data` and `.bss`\n * sections.  If the collector is compiled as a shared library, these\n * symbols are compiled with zero bounds and cannot be dereferenced;\n * instead, the read-only capability returned by the loader is used.\n */\n\nstruct scan_bounds_s {\n  word start_addr;\n  word end_addr;\n  ptr_t ld_cap;\n};\n\nstatic int\nld_cap_search(struct dl_phdr_info *info, size_t size, void *cd)\n{\n  struct scan_bounds_s *region = (struct scan_bounds_s *)cd;\n  ptr_t load_ptr = (ptr_t)info->dlpi_addr;\n\n  UNUSED_ARG(size);\n  if (!SPANNING_CAPABILITY(load_ptr, region->start_addr, region->end_addr))\n    return 0;\n\n  region->ld_cap = (ptr_t)cheri_bounds_set(\n      cheri_address_set(load_ptr, region->start_addr),\n      region->end_addr - region->start_addr);\n  return 1; /*< stop */\n}\n\nstatic ptr_t\nderive_cap_from_ldr(ptr_t range_start, ptr_t range_end)\n{\n  word scan_start = ADDR(range_start);\n  word scan_end = ADDR(range_end);\n  struct scan_bounds_s region;\n\n  /* If symbols already span the required range, return one of them. */\n  if (SPANNING_CAPABILITY(range_start, scan_start, scan_end))\n    return range_start;\n  if (SPANNING_CAPABILITY(range_end, scan_start, scan_end))\n    return range_end;\n\n  /*\n   * Fall-back option: derive `.data` plus `.bss` end pointer from the\n   * read-only capability provided by loader.\n   */\n  region.start_addr = scan_start;\n  region.end_addr = scan_end;\n  region.ld_cap = NULL; /*< prevent a compiler warning */\n  if (!dl_iterate_phdr(ld_cap_search, &region))\n    ABORT(\"Cannot find static roots for capability system\");\n  GC_ASSERT(region.ld_cap != NULL);\n  return region.ld_cap;\n}\n#  endif /* CHERI_PURECAP */\n\nGC_INNER ptr_t\nGC_SysVGetDataStart(size_t max_page_size, ptr_t etext_ptr)\n{\n  volatile ptr_t result;\n\n  GC_ASSERT(max_page_size % ALIGNMENT == 0);\n  result = PTR_ALIGN_UP(etext_ptr, ALIGNMENT);\n#  ifdef CHERI_PURECAP\n  result = derive_cap_from_ldr(result, DATAEND);\n#  endif\n\n  GC_setup_temporary_fault_handler();\n  if (SETJMP(GC_jmp_buf) == 0) {\n    /*\n     * Note that this is not equivalent to just adding `max_page_size` to\n     * `etext_ptr` because the latter is not guaranteed to be multiple of\n     * the page size.\n     */\n    ptr_t next_page = PTR_ALIGN_UP(result, max_page_size);\n\n#  ifdef FREEBSD\n    /*\n     * It is unclear whether this should be identical to the below, or\n     * whether it should apply to non-x86 architectures.  For now we\n     * do not assume that there is always an empty page after `etext`.\n     * But in some cases there actually seems to be slightly more.\n     * It also deals with holes between read-only and writable data.\n     *\n     * Try reading at the address.  This should happen before there is\n     * another thread.\n     */\n    for (; ADDR_LT(next_page, DATAEND); next_page += max_page_size) {\n      GC_noop1((word)(*(volatile unsigned char *)next_page));\n    }\n#  else\n    result = next_page + (ADDR(result) & ((word)max_page_size - 1));\n    /* Try writing to the address. */\n    {\n#    ifdef AO_HAVE_fetch_and_add\n      volatile AO_t zero = 0;\n\n      (void)AO_fetch_and_add((volatile AO_t *)result, zero);\n#    else\n      /* Fall back to non-atomic fetch-and-store. */\n      char v = *result;\n\n#      ifdef CPPCHECK\n      GC_noop1_ptr(&v);\n#      endif\n      *result = v;\n#    endif\n    }\n#  endif\n    GC_reset_fault_handler();\n  } else {\n    GC_reset_fault_handler();\n    /*\n     * We got here via a `longjmp`.  The address is not readable.\n     * This is known to happen under Solaris 2.4 with gcc, which places\n     * string constants in the `text` segment, but after `etext`.\n     * Use plan B.  Note that we now know there is a gap between `text`\n     * and `data` segments, so plan A brought us something.\n     */\n#  ifdef CHERI_PURECAP\n    result = (ptr_t)GC_find_limit(cheri_address_set(result, ADDR(DATAEND)),\n                                  FALSE);\n#  else\n    result = (ptr_t)GC_find_limit(DATAEND, FALSE);\n#  endif\n  }\n  return (ptr_t)CAST_AWAY_VOLATILE_PVOID(result);\n}\n#endif /* DATASTART_USES_XGETDATASTART */\n\n#if defined(OS2)\nGC_INNER void\nGC_register_data_segments(void)\n{\n  PTIB ptib;\n  PPIB ppib;\n  HMODULE module_handle;\n#  define PBUFSIZ 512\n  UCHAR path[PBUFSIZ];\n  FILE *myexefile;\n  struct exe_hdr hdrdos; /*< MSDOS header */\n  struct e32_exe hdr386; /*< real header for my executable */\n  struct o32_obj seg;    /*< current segment */\n  int nsegs;\n\n#  if defined(CPPCHECK)\n  hdrdos.padding[0] = 0; /*< to prevent \"field unused\" warnings */\n  hdr386.exe_format_level = 0;\n  hdr386.os = 0;\n  hdr386.padding1[0] = 0;\n  hdr386.padding2[0] = 0;\n  seg.pagemap = 0;\n  seg.mapsize = 0;\n  seg.reserved = 0;\n#  endif\n  if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {\n    ABORT(\"DosGetInfoBlocks failed\");\n  }\n  module_handle = ppib->pib_hmte;\n  if (DosQueryModuleName(module_handle, PBUFSIZ, path) != NO_ERROR) {\n    ABORT(\"DosQueryModuleName failed\");\n  }\n  myexefile = fopen(path, \"rb\");\n  if (myexefile == 0) {\n    ABORT_ARG1(\"Failed to open executable\", \": %s\", path);\n  }\n  if (fread((char *)&hdrdos, 1, sizeof(hdrdos), myexefile) < sizeof(hdrdos)) {\n    ABORT_ARG1(\"Could not read MSDOS header\", \" from: %s\", path);\n  }\n  if (E_MAGIC(hdrdos) != EMAGIC) {\n    ABORT_ARG1(\"Bad DOS magic number\", \" in file: %s\", path);\n  }\n  if (fseek(myexefile, E_LFANEW(hdrdos), SEEK_SET) != 0) {\n    ABORT_ARG1(\"Bad DOS magic number\", \" in file: %s\", path);\n  }\n  if (fread((char *)&hdr386, 1, sizeof(hdr386), myexefile) < sizeof(hdr386)) {\n    ABORT_ARG1(\"Could not read OS/2 header\", \" from: %s\", path);\n  }\n  if (E32_MAGIC1(hdr386) != E32MAGIC1 || E32_MAGIC2(hdr386) != E32MAGIC2) {\n    ABORT_ARG1(\"Bad OS/2 magic number\", \" in file: %s\", path);\n  }\n  if (E32_BORDER(hdr386) != E32LEBO || E32_WORDER(hdr386) != E32LEWO) {\n    ABORT_ARG1(\"Bad byte order in executable\", \" file: %s\", path);\n  }\n  if (E32_CPU(hdr386) == E32CPU286) {\n    ABORT_ARG1(\"GC cannot handle 80286 executables\", \": %s\", path);\n  }\n  if (fseek(myexefile, E_LFANEW(hdrdos) + E32_OBJTAB(hdr386), SEEK_SET) != 0) {\n    ABORT_ARG1(\"Seek to object table failed\", \" in file: %s\", path);\n  }\n  for (nsegs = E32_OBJCNT(hdr386); nsegs > 0; nsegs--) {\n    int flags;\n    if (fread((char *)&seg, 1, sizeof(seg), myexefile) < sizeof(seg)) {\n      ABORT_ARG1(\"Could not read obj table entry\", \" from file: %s\", path);\n    }\n    flags = O32_FLAGS(seg);\n    if (!(flags & OBJWRITE))\n      continue;\n    if (!(flags & OBJREAD))\n      continue;\n    if (flags & OBJINVALID) {\n      GC_err_printf(\"Object with invalid pages?\\n\");\n      continue;\n    }\n    GC_add_roots_inner((ptr_t)O32_BASE(seg),\n                       (ptr_t)(O32_BASE(seg) + O32_SIZE(seg)), FALSE);\n  }\n  (void)fclose(myexefile);\n}\n\n#elif defined(OPENBSD)\nGC_INNER void\nGC_register_data_segments(void)\n{\n  /*\n   * Depending on arch alignment, there can be multiple holes between\n   * `DATASTART` and `DATAEND`.  Scan in `DATASTART` .. `DATAEND` and\n   * register each region.\n   */\n  ptr_t region_start = DATASTART;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (ADDR(region_start) - 1U >= ADDR(DATAEND))\n    ABORT_ARG2(\"Wrong DATASTART/END pair\", \": %p .. %p\", (void *)region_start,\n               (void *)DATAEND);\n  for (;;) {\n    ptr_t region_end = GC_find_limit_with_bound(region_start, TRUE, DATAEND);\n\n    GC_add_roots_inner(region_start, region_end, FALSE);\n    if (ADDR_GE(region_end, DATAEND))\n      break;\n    region_start = GC_skip_hole_openbsd(region_end, DATAEND);\n  }\n}\n\n#elif !defined(ANY_MSWIN)\nGC_INNER void\nGC_register_data_segments(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n#  if !defined(DYNAMIC_LOADING) && defined(GC_DONT_REGISTER_MAIN_STATIC_DATA)\n  /*\n   * Avoid even referencing `DATASTART` and `DATAEND` as they are\n   * unnecessary and cause linker errors when bitcode is enabled.\n   * `GC_register_data_segments` is not called anyway.\n   */\n#  elif defined(DYNAMIC_LOADING) && (defined(DARWIN) || defined(HAIKU))\n  /* No-op.  `GC_register_main_static_data()` always returns `FALSE`. */\n#  elif defined(REDIRECT_MALLOC) && defined(SOLARIS) && defined(THREADS)\n  /*\n   * As of Solaris 2.3, the Solaris threads implementation allocates\n   * the data structure for the initial thread with `sbrk` at the\n   * process startup.  It needs to be scanned, so that we do not lose\n   * some `malloc`-allocated data structures hanging from it.\n   * We are on thin ice here...\n   */\n  GC_ASSERT(DATASTART);\n  {\n    ptr_t p = (ptr_t)sbrk(0);\n\n    if (ADDR_LT(DATASTART, p))\n      GC_add_roots_inner(DATASTART, p, FALSE);\n  }\n#  else\n  /*\n   * Note: subtract one is to also check for `NULL` without a compiler\n   * warning.\n   */\n  if (ADDR(DATASTART) - 1U >= ADDR(DATAEND)) {\n    ABORT_ARG2(\"Wrong DATASTART/END pair\", \": %p .. %p\", (void *)DATASTART,\n               (void *)DATAEND);\n  }\n  GC_add_roots_inner(DATASTART, DATAEND, FALSE);\n#    ifdef GC_HAVE_DATAREGION2\n  if (ADDR(DATASTART2) - 1U >= ADDR(DATAEND2))\n    ABORT_ARG2(\"Wrong DATASTART/END2 pair\", \": %p .. %p\", (void *)DATASTART2,\n               (void *)DATAEND2);\n  GC_add_roots_inner(DATASTART2, DATAEND2, FALSE);\n#    endif\n#  endif\n  /*\n   * Dynamic libraries are added at every collection, since they\n   * may change.\n   */\n}\n#endif /* !ANY_MSWIN && !OPENBSD && !OS2 */\n\n/* Auxiliary routines for obtaining memory from OS. */\n\n#ifdef NEED_UNIX_GET_MEM\n\n#  define SBRK_ARG_T ptrdiff_t\n\n#  if defined(MMAP_SUPPORTED)\n\n#    ifdef USE_MMAP_FIXED\n/*\n * Seems to yield better performance on Solaris 2, but can be unreliable\n * if something is already mapped at the address.\n */\n#      define GC_MMAP_FLAGS MAP_FIXED | MAP_PRIVATE\n#    else\n#      define GC_MMAP_FLAGS MAP_PRIVATE\n#    endif\n\n#    ifdef USE_MMAP_ANON\n#      define zero_fd -1\n#      if defined(MAP_ANONYMOUS) && !defined(CPPCHECK)\n#        define OPT_MAP_ANON MAP_ANONYMOUS\n#      else\n#        define OPT_MAP_ANON MAP_ANON\n#      endif\n#    else\nstatic int zero_fd = -1;\n#      define OPT_MAP_ANON 0\n#    endif\n\n#    ifndef MSWIN_XBOX1\n#      if defined(SYMBIAN) && !defined(USE_MMAP_ANON)\nEXTERN_C_BEGIN\nextern char *GC_get_private_path_and_zero_file(void);\nEXTERN_C_END\n#      endif\n\nSTATIC void *\nGC_unix_mmap_get_mem(size_t bytes)\n{\n  void *result;\n  static word last_addr = HEAP_START;\n\n#      ifndef USE_MMAP_ANON\n  static GC_bool initialized = FALSE;\n\n  if (UNLIKELY(!initialized)) {\n#        ifdef SYMBIAN\n    char *path = GC_get_private_path_and_zero_file();\n    if (path != NULL) {\n      zero_fd = open(path, O_RDWR | O_CREAT, 0644);\n      free(path);\n    }\n#        else\n    zero_fd = open(\"/dev/zero\", O_RDONLY);\n#        endif\n    if (zero_fd == -1)\n      ABORT(\"Could not open /dev/zero\");\n    if (fcntl(zero_fd, F_SETFD, FD_CLOEXEC) == -1)\n      WARN(\"Could not set FD_CLOEXEC for /dev/zero\\n\", 0);\n\n    initialized = TRUE;\n  }\n#      endif\n\n  GC_ASSERT(GC_page_size != 0);\n  if (bytes & (GC_page_size - 1))\n    ABORT(\"Bad GET_MEM arg\");\n  /*\n   * Note: it is essential for CHERI to have only address part in\n   * `last_addr` without metadata (thus the variable is of `word` type\n   * intentionally), otherwise `mmap()` fails setting `errno` to `EPROT`.\n   */\n  result\n      = mmap(MAKE_CPTR(last_addr), bytes,\n             (PROT_READ | PROT_WRITE) | (GC_pages_executable ? PROT_EXEC : 0),\n             GC_MMAP_FLAGS | OPT_MAP_ANON, zero_fd, 0 /* `offset` */);\n#      undef IGNORE_PAGES_EXECUTABLE\n\n  if (UNLIKELY(MAP_FAILED == result)) {\n    if (HEAP_START == last_addr && GC_pages_executable\n        && (EACCES == errno || EPERM == errno))\n      ABORT(\"Cannot allocate executable pages\");\n    return NULL;\n  }\n#      ifdef LINUX\n  GC_ASSERT(ADDR(result) <= ~(word)(GC_page_size - 1) - bytes);\n  /* The following `PTR_ALIGN_UP()` cannot overflow. */\n#      else\n  if (UNLIKELY(ADDR(result) > ~(word)(GC_page_size - 1) - bytes)) {\n    /*\n     * Oops.  We got the end of the address space.  This is not usable\n     * by arbitrary C code, since one-past-end pointers do not work,\n     * so we discard it and try again.  Leave the last page mapped,\n     * so we cannot repeat.\n     */\n    (void)munmap(result, ~(GC_page_size - 1) - (size_t)ADDR(result));\n    return GC_unix_mmap_get_mem(bytes);\n  }\n#      endif\n  if ((ADDR(result) % HBLKSIZE) != 0)\n    ABORT(\"Memory returned by mmap is not aligned to HBLKSIZE\");\n  last_addr = ADDR(result) + bytes;\n  GC_ASSERT((last_addr & (GC_page_size - 1)) == 0);\n  return result;\n}\n#    endif /* !MSWIN_XBOX1 */\n\n#  endif /* MMAP_SUPPORTED */\n\n#  if defined(USE_MMAP)\n\nGC_INNER void *\nGC_unix_get_mem(size_t bytes)\n{\n  return GC_unix_mmap_get_mem(bytes);\n}\n\n#  else /* !USE_MMAP */\n\nSTATIC void *\nGC_unix_sbrk_get_mem(size_t bytes)\n{\n  void *result;\n\n#    ifdef IRIX5\n  /*\n   * Bare `sbrk()` is not thread-safe.  Play by `malloc` rules.\n   * The equivalent may be needed on other systems as well.\n   */\n  __LOCK_MALLOC();\n#    endif\n  {\n    ptr_t cur_brk = (ptr_t)sbrk(0);\n    SBRK_ARG_T lsbs = ADDR(cur_brk) & (GC_page_size - 1);\n\n    GC_ASSERT(GC_page_size != 0);\n    if (UNLIKELY((SBRK_ARG_T)bytes < 0)) {\n      /* Value of `bytes` is too big. */\n      result = NULL;\n      goto out;\n    }\n    if (lsbs != 0) {\n      if ((ptr_t)sbrk((SBRK_ARG_T)GC_page_size - lsbs) == (ptr_t)(-1)) {\n        result = NULL;\n        goto out;\n      }\n    }\n#    ifdef ADD_HEAP_GUARD_PAGES\n    /*\n     * This is useful for catching severe memory overwrite problems\n     * that span heap sections.  It should not otherwise be turned on.\n     */\n    {\n      ptr_t guard = (ptr_t)sbrk((SBRK_ARG_T)GC_page_size);\n      if (mprotect(guard, GC_page_size, PROT_NONE) != 0)\n        ABORT(\"ADD_HEAP_GUARD_PAGES: mprotect failed\");\n    }\n#    endif\n    result = sbrk((SBRK_ARG_T)bytes);\n    if (UNLIKELY(ADDR(result) == GC_WORD_MAX))\n      result = NULL;\n  }\nout:\n#    ifdef IRIX5\n  __UNLOCK_MALLOC();\n#    endif\n  return result;\n}\n\nGC_INNER void *\nGC_unix_get_mem(size_t bytes)\n{\n#    if defined(MMAP_SUPPORTED)\n  /* By default, we try both `sbrk` and `mmap`, in that order. */\n  static GC_bool sbrk_failed = FALSE;\n  void *result = NULL;\n\n  if (GC_pages_executable) {\n    /*\n     * If the allocated memory should have the execute permission,\n     * then `sbrk()` cannot be used.\n     */\n    return GC_unix_mmap_get_mem(bytes);\n  }\n  if (!sbrk_failed)\n    result = GC_unix_sbrk_get_mem(bytes);\n  if (NULL == result) {\n    sbrk_failed = TRUE;\n    result = GC_unix_mmap_get_mem(bytes);\n    if (NULL == result) {\n      /* Try `sbrk()` again, in case `sbrk` memory became available. */\n      result = GC_unix_sbrk_get_mem(bytes);\n    }\n  }\n  return result;\n#    else /* !MMAP_SUPPORTED */\n  return GC_unix_sbrk_get_mem(bytes);\n#    endif\n}\n\n#  endif /* !USE_MMAP */\n\n#endif /* NEED_UNIX_GET_MEM */\n\n#if defined(OS2)\nGC_INNER void *\nGC_get_mem(size_t bytes)\n{\n  void *result = NULL;\n  int retry;\n\n  GC_ASSERT(GC_page_size != 0);\n  bytes = SIZET_SAT_ADD(bytes, GC_page_size);\n  for (retry = 0;; retry++) {\n    if (DosAllocMem(&result, bytes,\n                    (PAG_READ | PAG_WRITE | PAG_COMMIT)\n                        | (GC_pages_executable ? PAG_EXECUTE : 0))\n            == NO_ERROR\n        && LIKELY(result != NULL))\n      break;\n    /*\n     * TODO: Unclear the purpose of the retry.  (Probably, if `DosAllocMem`\n     * returns memory at address zero, then just retry once.)\n     */\n    if (retry >= 1)\n      return NULL;\n  }\n  return HBLKPTR((ptr_t)result + GC_page_size - 1);\n}\n\n#elif defined(MSWIN_XBOX1)\nGC_INNER void *\nGC_get_mem(size_t bytes)\n{\n  if (UNLIKELY(0 == bytes))\n    return NULL;\n  return VirtualAlloc(NULL, bytes, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);\n}\n\n#elif defined(MSWINCE)\nGC_INNER void *\nGC_get_mem(size_t bytes)\n{\n  void *result = NULL; /*< initialized to prevent a compiler warning */\n  size_t i;\n\n  GC_ASSERT(GC_page_size != 0);\n  bytes = ROUNDUP_PAGESIZE(bytes);\n\n  /* Try to find reserved, uncommitted pages. */\n  for (i = 0; i < GC_n_heap_bases; i++) {\n    if (((word)(-(GC_signed_word)GC_heap_lengths[i])\n         & (GC_sysinfo.dwAllocationGranularity - 1))\n        >= bytes) {\n      result = GC_heap_bases[i] + GC_heap_lengths[i];\n      break;\n    }\n  }\n\n  if (i == GC_n_heap_bases) {\n    /* Reserve more pages. */\n    size_t res_bytes\n        = SIZET_SAT_ADD(bytes, (size_t)GC_sysinfo.dwAllocationGranularity - 1)\n          & ~((size_t)GC_sysinfo.dwAllocationGranularity - 1);\n    /*\n     * If we ever support `MPROTECT_VDB` here, we will probably need\n     * to ensure that `res_bytes` is greater (strictly) than `bytes`,\n     * so that `VirtualProtect()` never spans regions.  It seems to be\n     * fine for a `VirtualFree()` argument to span regions, so we\n     * should be OK for now.\n     */\n    result = VirtualAlloc(NULL, res_bytes, MEM_RESERVE | MEM_TOP_DOWN,\n                          GC_pages_executable ? PAGE_EXECUTE_READWRITE\n                                              : PAGE_READWRITE);\n    if (HBLKDISPL(result) != 0) {\n      /*\n       * If I read the documentation correctly, this can only happen\n       * if `HBLKSIZE` is greater than 64 KB or not a power of 2.\n       */\n      ABORT(\"Bad VirtualAlloc result\");\n    }\n    if (GC_n_heap_bases >= MAX_HEAP_SECTS)\n      ABORT(\"Too many heap sections\");\n    if (UNLIKELY(NULL == result))\n      return NULL;\n    GC_heap_bases[GC_n_heap_bases] = (ptr_t)result;\n    GC_heap_lengths[GC_n_heap_bases] = 0;\n    GC_n_heap_bases++;\n  }\n\n  /* Commit pages. */\n  result = VirtualAlloc(result, bytes, MEM_COMMIT,\n                        GC_pages_executable ? PAGE_EXECUTE_READWRITE\n                                            : PAGE_READWRITE);\n#  undef IGNORE_PAGES_EXECUTABLE\n\n  if (HBLKDISPL(result) != 0)\n    ABORT(\"Bad VirtualAlloc result\");\n  if (LIKELY(result != NULL))\n    GC_heap_lengths[i] += bytes;\n  return result;\n}\n\n#elif defined(CYGWIN32) || defined(MSWIN32)\n#  ifdef USE_GLOBAL_ALLOC\n#    define GLOBAL_ALLOC_TEST 1\n#  else\n#    define GLOBAL_ALLOC_TEST GC_no_win32_dlls\n#  endif\n\n#  if (defined(GC_USE_MEM_TOP_DOWN) && defined(USE_WINALLOC)) \\\n      || defined(CPPCHECK)\n/*\n * Use `GC_USE_MEM_TOP_DOWN` for better 64-bit testing.\n * Otherwise all addresses tend to end up in the first 4 GB, hiding bugs.\n */\nDWORD GC_mem_top_down = MEM_TOP_DOWN;\n#  else\n#    define GC_mem_top_down 0\n#  endif /* !GC_USE_MEM_TOP_DOWN */\n\nGC_INNER void *\nGC_get_mem(size_t bytes)\n{\n  void *result;\n\n#  ifndef USE_WINALLOC\n  result = GC_unix_get_mem(bytes);\n#  else\n#    if defined(MSWIN32) && !defined(MSWINRT_FLAVOR)\n  if (GLOBAL_ALLOC_TEST) {\n    /*\n     * `VirtualAlloc()` does not like `PAGE_EXECUTE_READWRITE`.\n     * There are also unconfirmed rumors of other problems, so we\n     * dodge the issue.\n     */\n    result = GlobalAlloc(0, SIZET_SAT_ADD(bytes, HBLKSIZE));\n    /* Align it at `HBLKSIZE` boundary (`NULL` value remains unchanged). */\n    result = PTR_ALIGN_UP((ptr_t)result, HBLKSIZE);\n  } else\n#    endif\n  /* else */ {\n    /*\n     * `VirtualProtect()` only works on regions returned by a single\n     * `VirtualAlloc()` call.  Thus we allocate one extra page, which will\n     * prevent merging of blocks in separate regions, and eliminate any\n     * temptation to call `VirtualProtect()` on a range spanning regions.\n     * This wastes a small amount of memory, and risks increased\n     * fragmentation.  But better alternatives would require effort.\n     */\n#    ifdef MPROTECT_VDB\n    /*\n     * We cannot check for `GC_incremental` here (because\n     * `GC_enable_incremental()` might be called some time later after\n     * the collector initialization).\n     */\n#      ifdef GWW_VDB\n#        define VIRTUAL_ALLOC_PAD (GC_GWW_AVAILABLE() ? 0 : 1)\n#      else\n#        define VIRTUAL_ALLOC_PAD 1\n#      endif\n#    else\n#      define VIRTUAL_ALLOC_PAD 0\n#    endif\n    /*\n     * Pass `MEM_WRITE_WATCH` only if `GetWriteWatch`-based VDB is\n     * enabled and `GetWriteWatch()` is available.  Otherwise we waste\n     * resources or possibly cause `VirtualAlloc()` to fail (observed\n     * in Windows 2000 SP2).\n     */\n    result = VirtualAlloc(\n        NULL, SIZET_SAT_ADD(bytes, VIRTUAL_ALLOC_PAD),\n        MEM_COMMIT | MEM_RESERVE | GetWriteWatch_alloc_flag | GC_mem_top_down,\n        GC_pages_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE);\n#    undef IGNORE_PAGES_EXECUTABLE\n  }\n#  endif\n  if (HBLKDISPL(result) != 0)\n    ABORT(\"Bad VirtualAlloc result\");\n  if (GC_n_heap_bases >= MAX_HEAP_SECTS)\n    ABORT(\"Too many heap sections\");\n  if (LIKELY(result != NULL))\n    GC_heap_bases[GC_n_heap_bases++] = (ptr_t)result;\n  return result;\n}\n#endif /* CYGWIN32 || MSWIN32 */\n\n#if (defined(ANY_MSWIN) || defined(MSWIN_XBOX1)) && !defined(GC_NO_DEINIT)\nGC_API void GC_CALL\nGC_win32_free_heap(void)\n{\n#  if defined(USE_WINALLOC) && !defined(REDIRECT_MALLOC)\n  GC_free_malloc_heap_list();\n#  endif\n#  if defined(CYGWIN32) || defined(MSWIN32)\n#    ifndef MSWINRT_FLAVOR\n#      ifdef MSWIN32\n  if (GLOBAL_ALLOC_TEST)\n#      endif\n  {\n    while (GC_n_heap_bases > 0) {\n      GC_n_heap_bases--;\n#      ifdef CYGWIN32\n      /* FIXME: Is it OK to use non-GC `free()` here? */\n#      else\n      GlobalFree(GC_heap_bases[GC_n_heap_bases]);\n#      endif\n      GC_heap_bases[GC_n_heap_bases] = 0;\n    }\n    return;\n  }\n#    endif /* !MSWINRT_FLAVOR */\n#    ifndef CYGWIN32\n  /* Avoiding `VirtualAlloc` leak. */\n  while (GC_n_heap_bases > 0) {\n    VirtualFree(GC_heap_bases[--GC_n_heap_bases], 0, MEM_RELEASE);\n    GC_heap_bases[GC_n_heap_bases] = 0;\n  }\n#    endif\n#  endif\n}\n#endif\n\n#if (defined(USE_MUNMAP) || defined(MPROTECT_VDB)) && !defined(USE_WINALLOC)\n#  define ABORT_ON_REMAP_FAIL(C_msg_prefix, start_addr, len)             \\\n    ABORT_ARG3(C_msg_prefix \" failed\", \" at %p (length %lu), errno= %d\", \\\n               (void *)(start_addr), (unsigned long)(len), errno)\n#endif\n\n#ifdef USE_MUNMAP\n\n#  if !defined(NN_PLATFORM_CTR) && !defined(MSWIN32) && !defined(MSWINCE) \\\n      && !defined(MSWIN_XBOX1)\n#    ifdef SN_TARGET_PS3\n#      include <sys/memory.h>\n#    else\n#      include <sys/mman.h>\n#    endif\n#    include <sys/stat.h>\n#  endif\n\n/*\n * Compute a page-aligned starting address for the memory unmap\n * operation on a block of size `bytes` starting at `start`.\n * Return `NULL` if the block is too small to make this feasible.\n */\nSTATIC ptr_t\nGC_unmap_start(ptr_t start, size_t bytes)\n{\n  ptr_t result;\n\n  GC_ASSERT(GC_page_size != 0);\n  result = PTR_ALIGN_UP(start, GC_page_size);\n  if (ADDR_LT(start + bytes, result + GC_page_size))\n    return NULL;\n\n  return result;\n}\n\n/*\n * We assume that `GC_remap` is called on exactly the same range as\n * the previous call to `GC_unmap`.  It is safe to consistently round\n * the endpoints in both places.\n */\n\nstatic void\nblock_unmap_inner(ptr_t start_addr, size_t len)\n{\n  if (0 == start_addr)\n    return;\n\n#  ifdef USE_WINALLOC\n  /*\n   * Under Win32/WinCE we commit (map) and decommit (unmap) memory\n   * using `VirtualAlloc()` and `VirtualFree()`.  These functions\n   * work on individual allocations of virtual memory, made\n   * previously using `VirtualAlloc()` with the `MEM_RESERVE` flag.\n   * The ranges we need to (de)commit may span several of these\n   * allocations; therefore we use `VirtualQuery()` to check\n   * allocation lengths, and split up the range as necessary.\n   */\n  while (len != 0) {\n    MEMORY_BASIC_INFORMATION mem_info;\n    word free_len;\n\n    if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))\n        != sizeof(mem_info))\n      ABORT(\"Weird VirtualQuery result\");\n    free_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;\n    if (!VirtualFree(start_addr, free_len, MEM_DECOMMIT))\n      ABORT(\"VirtualFree failed\");\n    GC_unmapped_bytes += free_len;\n    start_addr += free_len;\n    len -= free_len;\n  }\n#  else\n  if (len != 0) {\n#    ifdef SN_TARGET_PS3\n    ps3_free_mem(start_addr, len);\n#    elif defined(AIX) || defined(COSMO) || defined(CYGWIN32) \\\n        || defined(HPUX)                                      \\\n        || (defined(LINUX) && !defined(PREFER_MMAP_PROT_NONE))\n    /*\n     * On AIX, `mmap(PROT_NONE)` fails with `ENOMEM` unless the\n     * environment variable `XPG_SUS_ENV` is set to `ON`.\n     * On Cygwin, calling `mmap()` with the new protection flags on\n     * an existing memory map with `MAP_FIXED` is broken.\n     * However, calling `mprotect()` on the given address range\n     * with `PROT_NONE` seems to work fine.  On Linux, low `RLIMIT_AS`\n     * value may lead to `mmap()` failure.\n     */\n#      if (defined(COSMO) || defined(LINUX)) \\\n          && !defined(FORCE_MPROTECT_BEFORE_MADVISE)\n    /* On Linux, at least, `madvise()` should be sufficient. */\n#      else\n    if (mprotect(start_addr, len, PROT_NONE))\n      ABORT_ON_REMAP_FAIL(\"unmap: mprotect\", start_addr, len);\n#      endif\n#      if !defined(CYGWIN32)\n    /*\n     * On Linux (and some other platforms probably), `mprotect(PROT_NONE)`\n     * is just disabling access to the pages but not returning them to OS.\n     */\n    if (madvise(start_addr, len, MADV_DONTNEED) == -1)\n      ABORT_ON_REMAP_FAIL(\"unmap: madvise\", start_addr, len);\n#      endif\n#    else\n    /*\n     * We immediately remap it to prevent an intervening `mmap()` from\n     * accidentally grabbing the same address space.\n     */\n    void *result = mmap(start_addr, len, PROT_NONE,\n                        MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON, zero_fd,\n                        0 /* `offset` */);\n\n    if (UNLIKELY(MAP_FAILED == result))\n      ABORT_ON_REMAP_FAIL(\"unmap: mmap\", start_addr, len);\n    if (result != start_addr)\n      ABORT(\"unmap: mmap() result differs from start_addr\");\n#      if defined(CPPCHECK) || defined(LINT2)\n    /* Explicitly store the resource handle to a global variable. */\n    GC_noop1_ptr(result);\n#      endif\n#    endif\n    GC_unmapped_bytes += len;\n  }\n#  endif\n}\n\n/* Compute end address for an unmap operation on the indicated block. */\nGC_INLINE ptr_t\nGC_unmap_end(ptr_t start, size_t bytes)\n{\n  return (ptr_t)HBLK_PAGE_ALIGNED(start + bytes);\n}\n\nGC_INNER void\nGC_unmap(ptr_t start, size_t bytes)\n{\n  ptr_t start_addr = GC_unmap_start(start, bytes);\n  ptr_t end_addr = GC_unmap_end(start, bytes);\n\n  block_unmap_inner(start_addr, (size_t)(end_addr - start_addr));\n}\n\nGC_INNER void\nGC_remap(ptr_t start, size_t bytes)\n{\n  ptr_t start_addr = GC_unmap_start(start, bytes);\n  ptr_t end_addr = GC_unmap_end(start, bytes);\n  word len = (word)(end_addr - start_addr);\n  if (0 == start_addr) {\n    return;\n  }\n\n  /* FIXME: Handle out-of-memory correctly (at least for Win32). */\n#  ifdef USE_WINALLOC\n  while (len != 0) {\n    MEMORY_BASIC_INFORMATION mem_info;\n    word alloc_len;\n    ptr_t result;\n\n    if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))\n        != sizeof(mem_info))\n      ABORT(\"Weird VirtualQuery result\");\n    alloc_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;\n    result = (ptr_t)VirtualAlloc(start_addr, alloc_len, MEM_COMMIT,\n                                 GC_pages_executable ? PAGE_EXECUTE_READWRITE\n                                                     : PAGE_READWRITE);\n    if (result != start_addr) {\n      if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY\n          || GetLastError() == ERROR_OUTOFMEMORY) {\n        ABORT(\"Not enough memory to process remapping\");\n      } else {\n        ABORT(\"VirtualAlloc remapping failed\");\n      }\n    }\n#    ifdef LINT2\n    GC_noop1_ptr(result);\n#    endif\n    GC_ASSERT(GC_unmapped_bytes >= alloc_len);\n    GC_unmapped_bytes -= alloc_len;\n    start_addr += alloc_len;\n    len -= alloc_len;\n  }\n#    undef IGNORE_PAGES_EXECUTABLE\n#  else\n  /* It was already remapped with `PROT_NONE`. */\n  {\n#    if !defined(SN_TARGET_PS3) && !defined(FORCE_MPROTECT_BEFORE_MADVISE) \\\n        && (defined(LINUX) && !defined(PREFER_MMAP_PROT_NONE)              \\\n            || defined(COSMO))\n    /* Nothing to unprotect as `madvise()` is just a hint. */\n#    elif defined(COSMO) || defined(NACL) || defined(NETBSD)\n    /*\n     * NaCl does not expose `mprotect`, but `mmap` should work fine.\n     * In case of NetBSD, `mprotect` fails (unlike `mmap`) even without\n     * `PROT_EXEC` if PaX `MPROTECT` feature is enabled.\n     */\n    void *result = mmap(\n        start_addr, len,\n        (PROT_READ | PROT_WRITE) | (GC_pages_executable ? PROT_EXEC : 0),\n        MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON, zero_fd, 0 /* `offset` */);\n    if (UNLIKELY(MAP_FAILED == result))\n      ABORT_ON_REMAP_FAIL(\"remap: mmap\", start_addr, len);\n    if (result != start_addr)\n      ABORT(\"remap: mmap() result differs from start_addr\");\n#      if defined(CPPCHECK) || defined(LINT2)\n    GC_noop1_ptr(result);\n#      endif\n#      undef IGNORE_PAGES_EXECUTABLE\n#    else\n    if (mprotect(start_addr, len,\n                 (PROT_READ | PROT_WRITE)\n                     | (GC_pages_executable ? PROT_EXEC : 0)))\n      ABORT_ON_REMAP_FAIL(\"remap: mprotect\", start_addr, len);\n#      undef IGNORE_PAGES_EXECUTABLE\n#    endif /* !NACL */\n  }\n  GC_ASSERT(GC_unmapped_bytes >= len);\n  GC_unmapped_bytes -= len;\n#  endif\n}\n\nGC_INNER void\nGC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2, size_t bytes2)\n{\n  ptr_t start1_addr = GC_unmap_start(start1, bytes1);\n  ptr_t end1_addr = GC_unmap_end(start1, bytes1);\n  ptr_t start2_addr = GC_unmap_start(start2, bytes2);\n  ptr_t start_addr = end1_addr;\n  ptr_t end_addr = start2_addr;\n\n  GC_ASSERT(start1 + bytes1 == start2);\n  if (0 == start1_addr)\n    start_addr = GC_unmap_start(start1, bytes1 + bytes2);\n  if (0 == start2_addr)\n    end_addr = GC_unmap_end(start1, bytes1 + bytes2);\n  block_unmap_inner(start_addr, (size_t)(end_addr - start_addr));\n}\n\n#endif /* USE_MUNMAP */\n\n/*\n * Routine for pushing any additional roots.  In the multi-threaded\n * environment, this is also responsible for marking from thread stacks.\n */\n#ifndef THREADS\n\n#  if defined(EMSCRIPTEN) && defined(EMSCRIPTEN_ASYNCIFY)\n#    include <emscripten.h>\n\nstatic void\nscan_regs_cb(void *begin, void *finish)\n{\n  GC_push_all_stack((ptr_t)begin, (ptr_t)finish);\n}\n\nSTATIC void GC_CALLBACK\nGC_default_push_other_roots(void)\n{\n  /* Note: this needs `-sASYNCIFY` linker flag. */\n  emscripten_scan_registers(scan_regs_cb);\n}\n\n#  else\n#    define GC_default_push_other_roots 0\n#  endif\n\n#else /* THREADS */\n\n#  if defined(SN_TARGET_PS3)\nSTATIC void GC_CALLBACK\nGC_default_push_other_roots(void)\n{\n  ABORT(\"GC_default_push_other_roots is not implemented\");\n}\n\nGC_INNER void\nGC_push_thread_structures(void)\n{\n  ABORT(\"GC_push_thread_structures is not implemented\");\n}\n\n#  else /* GC_PTHREADS, etc. */\nSTATIC void GC_CALLBACK\nGC_default_push_other_roots(void)\n{\n  GC_push_all_stacks();\n}\n#  endif\n\n#endif /* THREADS */\n\nGC_push_other_roots_proc GC_push_other_roots = GC_default_push_other_roots;\n\nGC_API void GC_CALL\nGC_set_push_other_roots(GC_push_other_roots_proc fn)\n{\n  GC_push_other_roots = fn;\n}\n\nGC_API GC_push_other_roots_proc GC_CALL\nGC_get_push_other_roots(void)\n{\n  return GC_push_other_roots;\n}\n\n#if defined(SOFT_VDB) && !defined(NO_SOFT_VDB_LINUX_VER_RUNTIME_CHECK) \\\n    || (defined(GLIBC_2_19_TSX_BUG) && defined(GC_PTHREADS_PARAMARK))\nGC_INNER int\nGC_parse_version(int *pminor, const char *pverstr)\n{\n  char *endp;\n  unsigned long value = strtoul(pverstr, &endp, 10);\n  int major = (int)value;\n\n  if (major < 0 || (char *)pverstr == endp || (unsigned)major != value) {\n    /* Parse error. */\n    return -1;\n  }\n  if (*endp != '.') {\n    /* No minor part. */\n    *pminor = -1;\n  } else {\n    value = strtoul(endp + 1, &endp, 10);\n    *pminor = (int)value;\n    if (*pminor < 0 || (unsigned)(*pminor) != value) {\n      return -1;\n    }\n  }\n  return major;\n}\n#endif\n\n/*\n * Routines for accessing dirty bits on virtual pages.  There are 6 ways to\n * maintain this information, as of now:\n *\n *   - `DEFAULT_VDB`: A simple dummy implementation that treats every page\n *     as possibly dirty.  This makes incremental collection useless, but\n *     the implementation is still correct.\n *\n *   - `MANUAL_VDB`: Stacks and static data are always considered dirty.\n *     Heap pages are considered dirty if `GC_dirty(p)` has been called on\n *     some `p` pointing to somewhere inside an object on that page.\n *     A `GC_dirty()` call on a large object directly dirties only a single\n *     page, but for the manual VDB we are careful to treat an object with\n *     a dirty page as completely dirty.  In order to avoid races, an object\n *     must be marked dirty after it is written, and a reference to the\n *     object must be kept on a stack or in a register in the interim.\n *     With threads enabled, an object directly reachable from the stack at\n *     the time of a collection is treated as dirty.  In the single-threaded\n *     mode, it suffices to ensure that no collection can take place between\n *     the pointer assignment and the `GC_dirty()` call.\n *\n *   - `PROC_VDB`: Use the `/proc` facility for reading dirty bits.\n *     Only works under some SVR4 variants.  Even then, it may be too slow\n *     to be entirely satisfactory.  Requires reading dirty bits for entire\n *     address space.  Implementations tend to assume that the client is\n *     a (slow) debugger.\n *\n *   - `SOFT_VDB`: Use the `/proc` facility for reading soft-dirty PTEs\n *     (page table entries).  Works on Linux 3.18+ if the kernel is\n *     properly configured.  The proposed implementation iterates over\n *     `GC_heap_sects` and `GC_static_roots` examining the soft-dirty bit\n *     of the `word` elements in `/proc/self/pagemap` file corresponding to\n *     the pages of the sections; finally all soft-dirty bits of the process\n *     are cleared (by writing some special value to `/proc/self/clear_refs`\n *     file).  In case the soft-dirty bit is not supported by the kernel,\n *     `MPROTECT_VDB` may be defined as a fall back strategy.\n *\n *   - `MPROTECT_VDB`: Protect pages and then catch the faults to keep\n *     track of dirtied pages.  The implementation (and implementability)\n *     is highly system-dependent.  This usually fails when system calls\n *     write to a protected page.  We prevent the `read` system call from\n *     doing so.  It is the clients responsibility to make sure that other\n *     system calls are similarly protected or write only to the stack.\n *\n *   - `GWW_VDB`: Use the Win32 `GetWriteWatch` function, if available, to\n *     read dirty bits.  In case it is not available (because we are\n *     running on Windows 95, Windows 2000 or earlier), `MPROTECT_VDB` may\n *     be defined as a fall back strategy.\n */\n\n#if (defined(CHECKSUMS) && defined(GWW_VDB)) || defined(PROC_VDB)\n/* Add all pages in `pht2` to `pht1`. */\nSTATIC void\nGC_or_pages(page_hash_table pht1, const word *pht2)\n{\n  size_t i;\n\n  for (i = 0; i < PHT_SIZE; i++)\n    pht1[i] |= pht2[i];\n}\n#endif /* CHECKSUMS && GWW_VDB || PROC_VDB */\n\n#ifdef GWW_VDB\n\n/*\n * Note: this is still susceptible to overflow, if there are very large\n * allocations, and everything is dirty.\n */\n#  define GC_GWW_BUF_LEN (MAXHINCR * HBLKSIZE / 4096 /* x86 page size */)\nstatic PVOID gww_buf[GC_GWW_BUF_LEN];\n\n#  ifndef MPROTECT_VDB\n#    define GC_gww_dirty_init GC_dirty_init\n#  endif\n\nGC_INNER GC_bool\nGC_gww_dirty_init(void)\n{\n  /* No assumption about the allocator lock. */\n  detect_GetWriteWatch();\n  return GC_GWW_AVAILABLE();\n}\n\nGC_INLINE void\nGC_gww_read_dirty(GC_bool output_unneeded)\n{\n  size_t i;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (!output_unneeded)\n    BZERO(GC_grungy_pages, sizeof(GC_grungy_pages));\n\n  for (i = 0; i < GC_n_heap_sects; ++i) {\n    GC_ULONG_PTR count;\n\n    do {\n      PVOID *pages = gww_buf;\n      DWORD page_size;\n\n      count = GC_GWW_BUF_LEN;\n      /*\n       * `GetWriteWatch()` is documented as returning nonzero when\n       * it fails, but the documentation does not explicitly say why\n       * it would fail or what its behavior will be if it fails.\n       * It does appear to fail, at least on recent Win2K instances,\n       * if the underlying memory was not allocated with the appropriate\n       * flag.  This is common if `GC_enable_incremental` is called\n       * shortly after the collector initialization.  To avoid modifying\n       * the interface, we silently work around such a failure, it only\n       * affects the initial (small) heap allocation.  If there are\n       * more dirty pages than will fit in the buffer, this is not\n       * treated as a failure; we must check the page count in the\n       * loop condition.  Since each partial call will reset the\n       * status of some pages, this should eventually terminate even\n       * in the overflow case.\n       */\n      if ((*(GetWriteWatch_type)(GC_funcptr_uint)GetWriteWatch_func)(\n              WRITE_WATCH_FLAG_RESET, GC_heap_sects[i].hs_start,\n              GC_heap_sects[i].hs_bytes, pages, &count, &page_size)\n          != 0) {\n        static int warn_count = 0;\n        static const struct hblk *last_warned = NULL;\n        struct hblk *start = (struct hblk *)GC_heap_sects[i].hs_start;\n        size_t nblocks = divHBLKSZ(GC_heap_sects[i].hs_bytes);\n\n        if (i != 0 && last_warned != start && warn_count++ < 5) {\n          last_warned = start;\n          WARN(\"GC_gww_read_dirty unexpectedly failed at %p:\"\n               \" Falling back to marking all pages dirty\\n\",\n               start);\n        }\n        if (!output_unneeded) {\n          size_t j;\n\n          for (j = 0; j < nblocks; ++j) {\n            size_t index = PHT_HASH(start + j);\n\n            set_pht_entry_from_index(GC_grungy_pages, index);\n          }\n        }\n        /* Done with this section. */\n        count = 1;\n      } else if (!output_unneeded) { /*< succeeded */\n        const PVOID *pages_end = pages + count;\n\n        while (pages != pages_end) {\n          struct hblk *h = (struct hblk *)(*pages++);\n          ptr_t h_end = (ptr_t)h + page_size;\n\n          do {\n            set_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h));\n            h++;\n          } while (ADDR_LT((ptr_t)h, h_end));\n        }\n      }\n    } while (count == GC_GWW_BUF_LEN);\n    /*\n     * FIXME: It is unclear from Microsoft's documentation if this loop\n     * is useful.  We suspect the call just fails if the buffer fills up.\n     * But that should still be handled correctly.\n     */\n  }\n\n#  ifdef CHECKSUMS\n  GC_ASSERT(!output_unneeded);\n  GC_or_pages(GC_written_pages, GC_grungy_pages);\n#  endif\n}\n\n#elif defined(SOFT_VDB)\nstatic int clear_refs_fd = -1;\n#  define GC_GWW_AVAILABLE() (clear_refs_fd != -1)\n#else\n#  define GC_GWW_AVAILABLE() FALSE\n#endif /* !GWW_VDB && !SOFT_VDB */\n\n#ifdef DEFAULT_VDB\n/*\n * The client asserts that unallocated pages in the heap are never\n * written.\n */\n\nGC_INNER GC_bool\nGC_dirty_init(void)\n{\n  GC_VERBOSE_LOG_PRINTF(\"Initializing DEFAULT_VDB...\\n\");\n  /* `GC_dirty_pages` and `GC_grungy_pages` are already cleared. */\n  return TRUE;\n}\n#endif /* DEFAULT_VDB */\n\n#if !defined(NO_MANUAL_VDB) || defined(MPROTECT_VDB)\n#  if !defined(THREADS) || defined(HAVE_LOCKFREE_AO_OR)\n#    ifdef MPROTECT_VDB\n#      define async_set_pht_entry_from_index(db, index) \\\n        set_pht_entry_from_index_concurrent_volatile(db, index)\n#    else\n#      define async_set_pht_entry_from_index(db, index) \\\n        set_pht_entry_from_index_concurrent(db, index)\n#    endif\n#  elif defined(NEED_FAULT_HANDLER_LOCK)\n/*\n * We need to lock around the bitmap update (in the write fault\n * handler or `GC_dirty`) in order to avoid the risk of losing a bit.\n * We do this with a test-and-set spin lock if possible.\n */\nstatic void\nasync_set_pht_entry_from_index(volatile page_hash_table db, size_t index)\n{\n  GC_acquire_dirty_lock();\n  set_pht_entry_from_index(db, index);\n  GC_release_dirty_lock();\n}\n#  else /* THREADS && !NEED_FAULT_HANDLER_LOCK */\n#    error No test_and_set operation: Introduces a race.\n#  endif\n#endif /* !NO_MANUAL_VDB || MPROTECT_VDB */\n\n#ifdef MPROTECT_VDB\n/*\n * This implementation maintains dirty bits itself by catching write\n * faults and keeping track of them.  We assume nobody else catches\n * `SIGBUS` or `SIGSEGV`.  We assume no write faults occur in system\n * calls.  This means that clients must ensure that system calls do\n * not write to the write-protected heap.  Probably the best way to\n * do this is to ensure that system calls write at most to\n * pointer-free objects in the heap, and do even that only if we are\n * on a platform on which those are not protected (or the collector\n * is built with `DONT_PROTECT_PTRFREE` defined).  We assume the page\n * size is a multiple of `HBLKSIZE`.\n */\n\n#  ifdef DARWIN\n/* `#define BROKEN_EXCEPTION_HANDLING` */\n\n/*\n * Using `vm_protect` (a `mach` `syscall`) over `mprotect` (a BSD `syscall`)\n * seems to decrease the likelihood of some of the problems described below.\n */\n#    include <mach/vm_map.h>\nSTATIC mach_port_t GC_task_self = 0;\n#    define PROTECT_INNER(addr, len, allow_write, C_msg_prefix)            \\\n      if (vm_protect(GC_task_self, (vm_address_t)(addr), (vm_size_t)(len), \\\n                     FALSE,                                                \\\n                     VM_PROT_READ | ((allow_write) ? VM_PROT_WRITE : 0)    \\\n                         | (GC_pages_executable ? VM_PROT_EXECUTE : 0))    \\\n          == KERN_SUCCESS) {                                               \\\n      } else                                                               \\\n        ABORT(C_msg_prefix \"vm_protect() failed\")\n\n#  elif !defined(USE_WINALLOC)\n#    include <sys/mman.h>\n#    if !defined(AIX) && !defined(CYGWIN32) && !defined(HAIKU)\n#      include <sys/syscall.h>\n#    endif\n\n#    define PROTECT_INNER(addr, len, allow_write, C_msg_prefix)           \\\n      if (mprotect((caddr_t)(addr), (size_t)(len),                        \\\n                   PROT_READ | ((allow_write) ? PROT_WRITE : 0)           \\\n                       | (GC_pages_executable ? PROT_EXEC : 0))           \\\n          >= 0) {                                                         \\\n      } else if (GC_pages_executable) {                                   \\\n        ABORT_ON_REMAP_FAIL(C_msg_prefix \"mprotect vdb executable pages\", \\\n                            addr, len);                                   \\\n      } else                                                              \\\n        ABORT_ON_REMAP_FAIL(C_msg_prefix \"mprotect vdb\", addr, len)\n#    undef IGNORE_PAGES_EXECUTABLE\n\n#  else /* USE_WINALLOC */\nstatic DWORD protect_junk;\n#    define PROTECT_INNER(addr, len, allow_write, C_msg_prefix)             \\\n      if (VirtualProtect(addr, len,                                         \\\n                         GC_pages_executable                                \\\n                             ? ((allow_write) ? PAGE_EXECUTE_READWRITE      \\\n                                              : PAGE_EXECUTE_READ)          \\\n                         : (allow_write) ? PAGE_READWRITE                   \\\n                                         : PAGE_READONLY,                   \\\n                         &protect_junk)) {                                  \\\n      } else                                                                \\\n        ABORT_ARG1(C_msg_prefix \"VirtualProtect failed\", \": errcode= 0x%X\", \\\n                   (unsigned)GetLastError())\n#  endif /* USE_WINALLOC */\n\n#  define PROTECT(addr, len) PROTECT_INNER(addr, len, FALSE, \"\")\n#  define UNPROTECT(addr, len) PROTECT_INNER(addr, len, TRUE, \"un-\")\n\n#  if defined(MSWIN32)\ntypedef LPTOP_LEVEL_EXCEPTION_FILTER SIG_HNDLR_PTR;\n#    undef SIG_DFL\n#    define SIG_DFL ((LPTOP_LEVEL_EXCEPTION_FILTER)(~(GC_funcptr_uint)0))\n#  elif defined(MSWINCE)\ntypedef LONG(WINAPI *SIG_HNDLR_PTR)(struct _EXCEPTION_POINTERS *);\n#    undef SIG_DFL\n#    define SIG_DFL ((SIG_HNDLR_PTR)(~(GC_funcptr_uint)0))\n#  elif defined(DARWIN)\n#    ifdef BROKEN_EXCEPTION_HANDLING\ntypedef void (*SIG_HNDLR_PTR)();\n#    endif\n#  else\ntypedef void (*SIG_HNDLR_PTR)(int, siginfo_t *, void *);\ntypedef void (*PLAIN_HNDLR_PTR)(int);\n#  endif /* !DARWIN && !MSWIN32 && !MSWINCE */\n\n#  ifndef DARWIN\n/* Also old `MSWIN32` `ACCESS_VIOLATION` filter. */\nSTATIC SIG_HNDLR_PTR GC_old_segv_handler = 0;\n#    ifdef USE_BUS_SIGACT\nSTATIC SIG_HNDLR_PTR GC_old_bus_handler = 0;\nSTATIC GC_bool GC_old_bus_handler_used_si = FALSE;\n#    endif\n#    if !defined(MSWIN32) && !defined(MSWINCE)\nSTATIC GC_bool GC_old_segv_handler_used_si = FALSE;\n#    endif\n#  endif /* !DARWIN */\n\n#  ifdef THREADS\n/*\n * This function is used only by the fault handler.  Potential data\n * race between this function and `GC_install_header`, `GC_remove_header`\n * should not be harmful because the added or removed header should be\n * already unprotected.\n */\nGC_ATTR_NO_SANITIZE_THREAD\nstatic GC_bool\nis_header_found_async(const void *p)\n{\n#    ifdef HASH_TL\n  hdr *result;\n\n  GET_HDR(p, result);\n  return result != NULL;\n#    else\n  return HDR_INNER(p) != NULL;\n#    endif\n}\n#  else\n#    define is_header_found_async(p) (HDR(p) != NULL)\n#  endif /* !THREADS */\n\n#  ifndef DARWIN\n\n#    if !defined(MSWIN32) && !defined(MSWINCE)\n#      include <errno.h>\n#      ifdef USE_BUS_SIGACT\n#        define SIG_OK (sig == SIGBUS || sig == SIGSEGV)\n#      else\n/* Catch `SIGSEGV` but ignore `SIGBUS`. */\n#        define SIG_OK (sig == SIGSEGV)\n#      endif\n#      if defined(FREEBSD) || defined(OPENBSD)\n#        ifndef SEGV_ACCERR\n#          define SEGV_ACCERR 2\n#        endif\n#        if defined(AARCH64) || defined(ARM32) || defined(MIPS) \\\n            || (__FreeBSD__ >= 7 || defined(OPENBSD))\n#          define CODE_OK (si->si_code == SEGV_ACCERR)\n#        elif defined(POWERPC)\n/* Pretend that we are AIM. */\n#          define AIM\n#          include <machine/trap.h>\n#          define CODE_OK \\\n            (si->si_code == EXC_DSI || si->si_code == SEGV_ACCERR)\n#        else\n#          define CODE_OK \\\n            (si->si_code == BUS_PAGE_FAULT || si->si_code == SEGV_ACCERR)\n#        endif\n#      elif defined(OSF1)\n#        define CODE_OK (si->si_code == 2) /*< experimentally determined */\n#      elif defined(IRIX5)\n#        define CODE_OK (si->si_code == EACCES)\n#      elif defined(AIX) || defined(COSMO) || defined(CYGWIN32) \\\n          || defined(HAIKU) || defined(HURD) || defined(LINUX)  \\\n          || defined(NETBSD)\n/*\n * Linux/i686: Empirically `c.trapno == 14`, but is that useful?\n * Should probably consider alignment issues on other architectures.\n */\n#        define CODE_OK TRUE\n#      elif defined(HPUX)\n#        define CODE_OK                                                 \\\n          (si->si_code == SEGV_ACCERR || si->si_code == BUS_ADRERR      \\\n           || si->si_code == BUS_UNKNOWN || si->si_code == SEGV_UNKNOWN \\\n           || si->si_code == BUS_OBJERR)\n#      elif defined(SUNOS5SIGS)\n#        define CODE_OK (si->si_code == SEGV_ACCERR)\n#      endif\n#      ifndef NO_GETCONTEXT\n#        include <ucontext.h>\n#      endif\nSTATIC void\nGC_write_fault_handler(int sig, siginfo_t *si, void *raw_sc)\n#    else /* MSWIN32 || MSWINCE */\n#      define SIG_OK \\\n        (exc_info->ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION)\n#      define CODE_OK                                       \\\n        (exc_info->ExceptionRecord->ExceptionInformation[0] \\\n         == 1) /*< write fault */\nSTATIC LONG WINAPI\nGC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info)\n#    endif\n{\n#    if !defined(MSWIN32) && !defined(MSWINCE)\n  char *addr = (char *)si->si_addr;\n#    else\n  char *addr = (char *)exc_info->ExceptionRecord->ExceptionInformation[1];\n#    endif\n\n  if (SIG_OK && CODE_OK) {\n    struct hblk *h = HBLK_PAGE_ALIGNED(addr);\n    GC_bool in_allocd_block;\n    size_t i;\n\n    GC_ASSERT(GC_page_size != 0);\n#    ifdef CHECKSUMS\n    GC_record_fault(h);\n#    endif\n#    ifdef SUNOS5SIGS\n    /* Address is only within the correct physical page. */\n    in_allocd_block = FALSE;\n    for (i = 0; i < divHBLKSZ(GC_page_size); i++) {\n      if (is_header_found_async(&h[i])) {\n        in_allocd_block = TRUE;\n        break;\n      }\n    }\n#    else\n    in_allocd_block = is_header_found_async(addr);\n#    endif\n    if (!in_allocd_block) {\n      /*\n       * FIXME: We should make sure that we invoke the old handler with the\n       * appropriate calling sequence, which often depends on `SA_SIGINFO`.\n       */\n\n      /* Heap blocks now begin and end on page boundaries. */\n      SIG_HNDLR_PTR old_handler;\n\n#    if defined(MSWIN32) || defined(MSWINCE)\n      old_handler = GC_old_segv_handler;\n#    else\n      GC_bool used_si;\n\n#      ifdef USE_BUS_SIGACT\n      if (sig == SIGBUS) {\n        old_handler = GC_old_bus_handler;\n        used_si = GC_old_bus_handler_used_si;\n      } else\n#      endif\n      /* else */ {\n        old_handler = GC_old_segv_handler;\n        used_si = GC_old_segv_handler_used_si;\n      }\n#    endif\n\n      if ((GC_funcptr_uint)old_handler == (GC_funcptr_uint)SIG_DFL) {\n#    if !defined(MSWIN32) && !defined(MSWINCE)\n        ABORT_ARG1(\"Unexpected segmentation fault outside heap\", \" at %p\",\n                   (void *)addr);\n#    else\n        return EXCEPTION_CONTINUE_SEARCH;\n#    endif\n      } else {\n        /*\n         * FIXME: This code should probably check if the old signal handler\n         * used the traditional style and if so, call it using that style.\n         */\n#    if defined(MSWIN32) || defined(MSWINCE)\n        return (*old_handler)(exc_info);\n#    else\n        if (used_si)\n          ((SIG_HNDLR_PTR)old_handler)(sig, si, raw_sc);\n        else\n          /* FIXME: Should pass nonstandard arguments as well. */\n          ((PLAIN_HNDLR_PTR)(GC_funcptr_uint)old_handler)(sig);\n        return;\n#    endif\n      }\n    }\n    UNPROTECT(h, GC_page_size);\n    /*\n     * We need to make sure that no collection occurs between the\n     * `UNPROTECT()` call and the setting of the dirty bit.\n     * Otherwise a write by a third thread might go unnoticed.\n     * Reversing the order is just as bad, since we would end up\n     * unprotecting a page in a collection cycle during which it is not\n     * marked.  Currently we do this by disabling the thread stopping\n     * signals while this handler is running.  An alternative might be\n     * to record the fact that we are about to unprotect, or have just\n     * unprotected a page in the collector's thread structure, and then\n     * to have the thread stopping code set the dirty flag, if necessary.\n     */\n    for (i = 0; i < divHBLKSZ(GC_page_size); i++) {\n      size_t index = PHT_HASH(h + i);\n\n      async_set_pht_entry_from_index(GC_dirty_pages, index);\n    }\n    /*\n     * The `write()` may not take place before dirty bits are read.\n     * But then we will fault again...\n     */\n#    if defined(MSWIN32) || defined(MSWINCE)\n    return EXCEPTION_CONTINUE_EXECUTION;\n#    else\n    return;\n#    endif\n  }\n#    if defined(MSWIN32) || defined(MSWINCE)\n  return EXCEPTION_CONTINUE_SEARCH;\n#    else\n  ABORT_ARG1(\"Unexpected bus error or segmentation fault\", \" at %p\",\n             (void *)addr);\n#    endif\n}\n\n#    if defined(GC_WIN32_THREADS) && !defined(CYGWIN32)\nGC_INNER void\nGC_set_write_fault_handler(void)\n{\n  SetUnhandledExceptionFilter(GC_write_fault_handler);\n}\n#    endif\n\n#    ifdef SOFT_VDB\nstatic GC_bool soft_dirty_init(void);\n#    endif\n\nGC_INNER GC_bool\nGC_dirty_init(void)\n{\n#    if !defined(MSWIN32) && !defined(MSWINCE)\n  struct sigaction act, oldact;\n#    endif\n\n  GC_ASSERT(I_HOLD_LOCK());\n#    ifdef COUNT_PROTECTED_REGIONS\n  GC_ASSERT(GC_page_size != 0);\n  if ((GC_signed_word)(GC_heapsize / (word)GC_page_size)\n      >= ((GC_signed_word)GC_UNMAPPED_REGIONS_SOFT_LIMIT\n          - GC_num_unmapped_regions)\n             * 2) {\n    GC_COND_LOG_PRINTF(\"Cannot turn on GC incremental mode\"\n                       \" as heap contains too many pages\\n\");\n    return FALSE;\n  }\n#    endif\n#    if !defined(MSWIN32) && !defined(MSWINCE)\n  act.sa_flags = SA_RESTART | SA_SIGINFO;\n  act.sa_sigaction = GC_write_fault_handler;\n  (void)sigemptyset(&act.sa_mask);\n#      ifdef SIGNAL_BASED_STOP_WORLD\n  /*\n   * Arrange to postpone the signal while we are in a write fault handler.\n   * This effectively makes the handler atomic w.r.t. stopping the world\n   * for the collection.\n   */\n  (void)sigaddset(&act.sa_mask, GC_get_suspend_signal());\n#      endif\n#    endif /* !MSWIN32 */\n  GC_VERBOSE_LOG_PRINTF(\n      \"Initializing mprotect virtual dirty bit implementation\\n\");\n  if (GC_page_size % HBLKSIZE != 0) {\n    ABORT(\"Page size not multiple of HBLKSIZE\");\n  }\n#    ifdef GWW_VDB\n  if (GC_gww_dirty_init()) {\n    GC_COND_LOG_PRINTF(\"Using GetWriteWatch()\\n\");\n    return TRUE;\n  }\n#    elif defined(SOFT_VDB)\n#      ifdef CHECK_SOFT_VDB\n  if (!soft_dirty_init())\n    ABORT(\"Soft-dirty bit support is missing\");\n#      else\n  if (soft_dirty_init()) {\n    GC_COND_LOG_PRINTF(\"Using soft-dirty bit feature\\n\");\n    return TRUE;\n  }\n#      endif\n#    endif\n#    ifdef MSWIN32\n  GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler);\n  if (GC_old_segv_handler != NULL) {\n    GC_COND_LOG_PRINTF(\"Replaced other UnhandledExceptionFilter\\n\");\n  } else {\n    GC_old_segv_handler = SIG_DFL;\n  }\n#    elif defined(MSWINCE)\n  {\n    /* `MPROTECT_VDB` is unsupported for WinCE at present. */\n    /* FIXME: Implement (if possible). */\n  }\n#    else\n  /* `act.sa_restorer` is deprecated and should not be initialized. */\n#      if defined(IRIX5) && defined(THREADS)\n  sigaction(SIGSEGV, 0, &oldact);\n  sigaction(SIGSEGV, &act, 0);\n#      else\n  {\n    int res = sigaction(SIGSEGV, &act, &oldact);\n    if (res != 0)\n      ABORT(\"Sigaction failed\");\n  }\n#      endif\n  if (oldact.sa_flags & SA_SIGINFO) {\n    GC_old_segv_handler = oldact.sa_sigaction;\n    GC_old_segv_handler_used_si = TRUE;\n  } else {\n    GC_old_segv_handler = (SIG_HNDLR_PTR)(GC_funcptr_uint)oldact.sa_handler;\n    GC_old_segv_handler_used_si = FALSE;\n  }\n  if ((GC_funcptr_uint)GC_old_segv_handler == (GC_funcptr_uint)SIG_IGN) {\n    WARN(\"Previously ignored segmentation violation!?\\n\", 0);\n    GC_old_segv_handler = (SIG_HNDLR_PTR)(GC_funcptr_uint)SIG_DFL;\n  }\n  if ((GC_funcptr_uint)GC_old_segv_handler != (GC_funcptr_uint)SIG_DFL) {\n    GC_VERBOSE_LOG_PRINTF(\"Replaced other SIGSEGV handler\\n\");\n  }\n#      ifdef USE_BUS_SIGACT\n  sigaction(SIGBUS, &act, &oldact);\n  if ((oldact.sa_flags & SA_SIGINFO) != 0) {\n    GC_old_bus_handler = oldact.sa_sigaction;\n    GC_old_bus_handler_used_si = TRUE;\n  } else {\n    GC_old_bus_handler = (SIG_HNDLR_PTR)(GC_funcptr_uint)oldact.sa_handler;\n  }\n  if ((GC_funcptr_uint)GC_old_bus_handler == (GC_funcptr_uint)SIG_IGN) {\n    WARN(\"Previously ignored bus error!?\\n\", 0);\n    GC_old_bus_handler = (SIG_HNDLR_PTR)(GC_funcptr_uint)SIG_DFL;\n  } else if ((GC_funcptr_uint)GC_old_bus_handler != (GC_funcptr_uint)SIG_DFL) {\n    GC_VERBOSE_LOG_PRINTF(\"Replaced other SIGBUS handler\\n\");\n  }\n#      endif\n#    endif /* !MSWIN32 && !MSWINCE */\n#    if defined(CPPCHECK) && defined(ADDRESS_SANITIZER)\n  GC_noop1((word)(GC_funcptr_uint)(&__asan_default_options));\n#    endif\n  return TRUE;\n}\n#  endif /* !DARWIN */\n\nSTATIC void\nGC_protect_heap(void)\n{\n  size_t i;\n\n  GC_ASSERT(GC_page_size != 0);\n  for (i = 0; i < GC_n_heap_sects; i++) {\n    ptr_t start = GC_heap_sects[i].hs_start;\n    size_t len = GC_heap_sects[i].hs_bytes;\n    struct hblk *current;\n    struct hblk *current_start; /*< start of block to be protected */\n    ptr_t limit;\n\n    GC_ASSERT((ADDR(start) & (GC_page_size - 1)) == 0);\n    GC_ASSERT((len & (GC_page_size - 1)) == 0);\n#  ifndef DONT_PROTECT_PTRFREE\n    /*\n     * We avoid protecting pointer-free objects unless the page size\n     * differs from `HBLKSIZE`.\n     */\n    if (GC_page_size != HBLKSIZE) {\n      PROTECT(start, len);\n      continue;\n    }\n#  endif\n\n    current_start = (struct hblk *)start;\n    limit = start + len;\n    for (current = current_start;;) {\n      size_t nblocks = 0;\n      GC_bool is_ptrfree = TRUE;\n\n      if (ADDR_LT((ptr_t)current, limit)) {\n        hdr *hhdr;\n\n        GET_HDR(current, hhdr);\n        if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {\n          /*\n           * This can happen only if we are at the beginning of a heap\n           * segment, and a block spans heap segments.  We will handle\n           * that block as part of the preceding segment.\n           */\n          GC_ASSERT(current_start == current);\n\n          current_start = ++current;\n          continue;\n        }\n        if (HBLK_IS_FREE(hhdr)) {\n          GC_ASSERT(modHBLKSZ(hhdr->hb_sz) == 0);\n          nblocks = divHBLKSZ(hhdr->hb_sz);\n        } else {\n          nblocks = OBJ_SZ_TO_BLOCKS(hhdr->hb_sz);\n          is_ptrfree = IS_PTRFREE(hhdr);\n        }\n      }\n      if (is_ptrfree) {\n        if (ADDR_LT((ptr_t)current_start, (ptr_t)current)) {\n#  ifdef DONT_PROTECT_PTRFREE\n          ptr_t cur_aligned = PTR_ALIGN_UP((ptr_t)current, GC_page_size);\n\n          current_start = HBLK_PAGE_ALIGNED(current_start);\n          /*\n           * Adjacent free blocks might be protected too because\n           * of the alignment by the page size.\n           */\n          PROTECT(current_start, cur_aligned - (ptr_t)current_start);\n#  else\n          PROTECT(current_start, (ptr_t)current - (ptr_t)current_start);\n#  endif\n        }\n        if (ADDR_GE((ptr_t)current, limit))\n          break;\n      }\n      current += nblocks;\n      if (is_ptrfree)\n        current_start = current;\n    }\n  }\n}\n\n#  if defined(CAN_HANDLE_FORK) && defined(DARWIN) && defined(THREADS) \\\n      || defined(COUNT_PROTECTED_REGIONS)\n/* Remove protection for the entire heap not updating `GC_dirty_pages`. */\nSTATIC void\nGC_unprotect_all_heap(void)\n{\n  size_t i;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_auto_incremental);\n  for (i = 0; i < GC_n_heap_sects; i++) {\n    UNPROTECT(GC_heap_sects[i].hs_start, GC_heap_sects[i].hs_bytes);\n  }\n}\n#  endif\n\n#  ifdef COUNT_PROTECTED_REGIONS\nGC_INNER void\nGC_handle_protected_regions_limit(void)\n{\n  GC_ASSERT(GC_page_size != 0);\n  /*\n   * To prevent exceeding the limit of `vm.max_map_count`, the most\n   * trivial (though highly restrictive) way is to turn off the\n   * incremental collection mode (based on `mprotect`) once the number\n   * of pages in the heap reaches that limit.\n   */\n  if (GC_auto_incremental && !GC_GWW_AVAILABLE()\n      && (GC_signed_word)(GC_heapsize / (word)GC_page_size)\n             >= ((GC_signed_word)GC_UNMAPPED_REGIONS_SOFT_LIMIT\n                 - GC_num_unmapped_regions)\n                    * 2) {\n    GC_unprotect_all_heap();\n#    ifdef DARWIN\n    GC_task_self = 0;\n#    endif\n    GC_incremental = FALSE;\n    WARN(\"GC incremental mode is turned off\"\n         \" to prevent hitting VM maps limit\\n\",\n         0);\n  }\n}\n#  endif /* COUNT_PROTECTED_REGIONS */\n\n#endif /* MPROTECT_VDB */\n\n#if !defined(THREADS) && (defined(PROC_VDB) || defined(SOFT_VDB))\nstatic pid_t saved_proc_pid; /*< `pid` used to compose `/proc` file names */\n#endif\n\n#ifdef PROC_VDB\n/*\n * This implementation assumes the Solaris new structured `/proc`\n * pseudo-file-system from which we can read page modified bits.\n * This facility is far from optimal (e.g. we would like to get the\n * info for only some of the address space), but it avoids intercepting\n * system calls.\n */\n\n#  include <errno.h>\n#  include <sys/signal.h>\n#  include <sys/stat.h>\n#  include <sys/syscall.h>\n\n#  ifdef GC_NO_SYS_FAULT_H\n/* This exists only to check `PROC_VDB` code compilation (on Linux). */\n#    define PG_MODIFIED 1\nstruct prpageheader {\n  long dummy[2]; /*< `pr_tstamp` */\n  long pr_nmap;\n  long pr_npage;\n};\nstruct prasmap {\n  GC_uintptr_t pr_vaddr;\n  size_t pr_npage;\n  char dummy1[64 + 8]; /*< `pr_mapname`, `pr_offset` */\n  int pr_mflags;\n  int pr_pagesize;\n  int dummy2[2]; /*< `pr_shmid`, `pr_filler` */\n};\n#  else\n/* Use the new structured `/proc` definitions. */\n#    include <procfs.h>\n#  endif\n\n#  define INITIAL_BUF_SZ 8192\nSTATIC size_t GC_proc_buf_size = INITIAL_BUF_SZ;\nSTATIC char *GC_proc_buf = NULL;\nSTATIC int GC_proc_fd = -1;\n\nstatic GC_bool\nproc_dirty_open_files(void)\n{\n  char buf[6 + 20 + 9 + 1];\n  pid_t pid = getpid();\n\n  GC_snprintf_s_ld_s(buf, sizeof(buf), \"/proc/\", (long)pid, \"/pagedata\");\n  GC_proc_fd = open(buf, O_RDONLY);\n  if (-1 == GC_proc_fd) {\n    WARN(\"/proc open failed; cannot enable GC incremental mode\\n\", 0);\n    return FALSE;\n  }\n  if (syscall(SYS_fcntl, GC_proc_fd, F_SETFD, FD_CLOEXEC) == -1)\n    WARN(\"Could not set FD_CLOEXEC for /proc\\n\", 0);\n#  ifndef THREADS\n  /* Updated on success only. */\n  saved_proc_pid = pid;\n#  endif\n  return TRUE;\n}\n\n#  ifdef CAN_HANDLE_FORK\nGC_INNER void\nGC_dirty_update_child(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  if (-1 == GC_proc_fd) {\n    /* The GC incremental mode is off. */\n    return;\n  }\n  close(GC_proc_fd);\n  if (!proc_dirty_open_files()) {\n    /* Should be safe to turn it off. */\n    GC_incremental = FALSE;\n  }\n}\n#  endif /* CAN_HANDLE_FORK */\n\nGC_INNER GC_bool\nGC_dirty_init(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  if (GC_bytes_allocd != 0 || GC_bytes_allocd_before_gc != 0) {\n    memset(GC_written_pages, 0xff, sizeof(page_hash_table));\n    GC_VERBOSE_LOG_PRINTF(\n        \"Allocated %lu bytes: all pages may have been written\\n\",\n        (unsigned long)(GC_bytes_allocd + GC_bytes_allocd_before_gc));\n  }\n  if (!proc_dirty_open_files())\n    return FALSE;\n  GC_proc_buf = GC_scratch_alloc(GC_proc_buf_size);\n  if (GC_proc_buf == NULL)\n    ABORT(\"Insufficient space for /proc read\");\n  return TRUE;\n}\n\nGC_INLINE void\nGC_proc_read_dirty(GC_bool output_unneeded)\n{\n  size_t i, nmaps;\n  ssize_t pagedata_len;\n  char *bufp = GC_proc_buf;\n\n  GC_ASSERT(I_HOLD_LOCK());\n#  ifndef THREADS\n  /*\n   * If the current `pid` differs from the saved one, then we are in\n   * the forked (child) process, the current `/proc` file should be\n   * closed, the new one should be opened with the updated path.\n   * Note, this is not needed for the multi-threaded case because\n   * `fork_child_proc()` reopens the file right after `fork()` call.\n   */\n  if (getpid() != saved_proc_pid\n      && (-1 == GC_proc_fd /*< no need to retry */\n          || (close(GC_proc_fd), !proc_dirty_open_files()))) {\n    /* Failed to reopen the file.  Punt! */\n    if (!output_unneeded)\n      memset(GC_grungy_pages, 0xff, sizeof(page_hash_table));\n    memset(GC_written_pages, 0xff, sizeof(page_hash_table));\n    return;\n  }\n#  endif\n\n  for (;;) {\n    char *new_buf;\n    size_t new_size;\n\n    pagedata_len = PROC_READ(GC_proc_fd, bufp, GC_proc_buf_size);\n    if (LIKELY(pagedata_len != -1))\n      break;\n    if (errno != E2BIG) {\n      WARN(\"read /proc failed, errno= %\" WARN_PRIdPTR \"\\n\",\n           (GC_signed_word)errno);\n      /* Punt. */\n      if (!output_unneeded)\n        memset(GC_grungy_pages, 0xff, sizeof(page_hash_table));\n      memset(GC_written_pages, 0xff, sizeof(page_hash_table));\n      return;\n    }\n    /* Retry with larger buffer. */\n    new_size = 2 * GC_proc_buf_size;\n    /*\n     * Alternatively, we could use `fstat()` to determine the required\n     * buffer size.\n     */\n#  ifdef DEBUG_DIRTY_BITS\n    GC_log_printf(\"Growing proc buf to %lu bytes at collection #%lu\\n\",\n                  (unsigned long)new_size, (unsigned long)GC_gc_no + 1);\n#  endif\n    new_buf = GC_scratch_alloc(new_size);\n    if (new_buf != NULL) {\n      GC_scratch_recycle_no_gww(bufp, GC_proc_buf_size);\n      GC_proc_buf = bufp = new_buf;\n      GC_proc_buf_size = new_size;\n    }\n  }\n  GC_ASSERT((size_t)pagedata_len <= GC_proc_buf_size);\n\n  /* Copy dirty bits into `GC_grungy_pages`. */\n  BZERO(GC_grungy_pages, sizeof(GC_grungy_pages));\n  nmaps = (size_t)(((struct prpageheader *)bufp)->pr_nmap);\n#  ifdef DEBUG_DIRTY_BITS\n  GC_log_printf(\"Proc VDB read: pr_nmap= %u, pr_npage= %ld\\n\", (unsigned)nmaps,\n                ((struct prpageheader *)bufp)->pr_npage);\n#  endif\n#  if defined(GC_NO_SYS_FAULT_H) && defined(CPPCHECK)\n  GC_noop1(((struct prpageheader *)bufp)->dummy[0]);\n#  endif\n  bufp += sizeof(struct prpageheader);\n  for (i = 0; i < nmaps; i++) {\n    struct prasmap *map = (struct prasmap *)bufp;\n    ptr_t vaddr, limit;\n    unsigned long npages = 0;\n    unsigned pagesize;\n\n    bufp += sizeof(struct prasmap);\n    /* Ensure no buffer overrun. */\n    if (bufp - GC_proc_buf < pagedata_len)\n      npages = (unsigned long)map->pr_npage;\n    if (bufp - GC_proc_buf > pagedata_len - (ssize_t)npages)\n      ABORT(\"Wrong pr_nmap or pr_npage read from /proc\");\n\n    vaddr = (ptr_t)map->pr_vaddr;\n    pagesize = (unsigned)map->pr_pagesize;\n#  if defined(GC_NO_SYS_FAULT_H) && defined(CPPCHECK)\n    GC_noop1(map->dummy1[0] + map->dummy2[0]);\n#  endif\n#  ifdef DEBUG_DIRTY_BITS\n    GC_log_printf(\"pr_vaddr= %p, npage= %lu, mflags= 0x%x, pagesize= 0x%x\\n\",\n                  (void *)vaddr, npages, map->pr_mflags, pagesize);\n#  endif\n    if (0 == pagesize || ((pagesize - 1) & pagesize) != 0)\n      ABORT(\"Wrong pagesize read from /proc\");\n\n    limit = vaddr + pagesize * npages;\n    for (; ADDR_LT(vaddr, limit); vaddr += pagesize) {\n      if ((*bufp++) & PG_MODIFIED) {\n        struct hblk *h;\n        ptr_t next_vaddr = vaddr + pagesize;\n\n#  ifdef DEBUG_DIRTY_BITS\n        GC_log_printf(\"dirty page at: %p\\n\", (void *)vaddr);\n#  endif\n        for (h = (struct hblk *)vaddr; ADDR_LT((ptr_t)h, next_vaddr); h++) {\n          size_t index = PHT_HASH(h);\n\n          set_pht_entry_from_index(GC_grungy_pages, index);\n        }\n      }\n    }\n    /*\n     * According to the new structured `pagedata` file format, an 8-byte\n     * alignment is enforced (preceding the next `struct prasmap`)\n     * regardless of the pointer size.\n     */\n    bufp = PTR_ALIGN_UP(bufp, 8);\n  }\n#  ifdef DEBUG_DIRTY_BITS\n  GC_log_printf(\"Proc VDB read done\\n\");\n#  endif\n\n  /* Update `GC_written_pages` (even if `output_unneeded`). */\n  GC_or_pages(GC_written_pages, GC_grungy_pages);\n}\n\n#endif /* PROC_VDB */\n\n#ifdef SOFT_VDB\n#  ifndef VDB_BUF_SZ\n#    define VDB_BUF_SZ 16384\n#  endif\n\nstatic int\nopen_proc_fd(pid_t pid, const char *slash_filename, int mode)\n{\n  int f;\n  char buf[6 + 20 + 11 + 1];\n\n  GC_snprintf_s_ld_s(buf, sizeof(buf), \"/proc/\", (long)pid, slash_filename);\n  f = open(buf, mode);\n  if (-1 == f) {\n    WARN(\"/proc/self%s open failed; cannot enable GC incremental mode\\n\",\n         slash_filename);\n  } else if (fcntl(f, F_SETFD, FD_CLOEXEC) == -1) {\n    WARN(\"Could not set FD_CLOEXEC for /proc\\n\", 0);\n  }\n  return f;\n}\n\n#  include <stdint.h> /*< for `uint64_t` */\n\ntypedef uint64_t pagemap_elem_t;\n\nstatic pagemap_elem_t *soft_vdb_buf;\nstatic int pagemap_fd;\n\nstatic GC_bool\nsoft_dirty_open_files(void)\n{\n  pid_t pid = getpid();\n\n  clear_refs_fd = open_proc_fd(pid, \"/clear_refs\", O_WRONLY);\n  if (-1 == clear_refs_fd)\n    return FALSE;\n  pagemap_fd = open_proc_fd(pid, \"/pagemap\", O_RDONLY);\n  if (-1 == pagemap_fd) {\n    close(clear_refs_fd);\n    clear_refs_fd = -1;\n    return FALSE;\n  }\n#  ifndef THREADS\n  /* Updated on success only. */\n  saved_proc_pid = pid;\n#  endif\n  return TRUE;\n}\n\n#  ifdef CAN_HANDLE_FORK\nGC_INNER void\nGC_dirty_update_child(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  if (-1 == clear_refs_fd) {\n    /* The GC incremental mode is off. */\n    return;\n  }\n  close(clear_refs_fd);\n  close(pagemap_fd);\n  if (!soft_dirty_open_files())\n    GC_incremental = FALSE;\n}\n#  endif /* CAN_HANDLE_FORK */\n\n/* Clear soft-dirty bits from the task's PTEs. */\nstatic void\nclear_soft_dirty_bits(void)\n{\n  ssize_t res = write(clear_refs_fd, \"4\\n\", 2);\n\n  if (res != 2)\n    ABORT_ARG1(\"Failed to write to /proc/self/clear_refs\", \": errno= %d\",\n               res < 0 ? errno : 0);\n}\n\n/* The bit 55 of the 64-bit `qword` of `pagemap` file is the soft-dirty one. */\n#  define PM_SOFTDIRTY_MASK ((pagemap_elem_t)1 << 55)\n\nstatic GC_bool\ndetect_soft_dirty_supported(ptr_t vaddr)\n{\n  off_t fpos;\n  pagemap_elem_t buf[1];\n\n  GC_ASSERT(GC_log_pagesize != 0);\n  /* Make it dirty. */\n  *vaddr = 1;\n  fpos = (off_t)((ADDR(vaddr) >> GC_log_pagesize) * sizeof(pagemap_elem_t));\n\n  for (;;) {\n    /* Read the relevant PTE from the `pagemap` file. */\n    if (lseek(pagemap_fd, fpos, SEEK_SET) == (off_t)(-1))\n      return FALSE;\n    if (PROC_READ(pagemap_fd, buf, sizeof(buf)) != (int)sizeof(buf))\n      return FALSE;\n\n    /* Is the soft-dirty bit unset? */\n    if ((buf[0] & PM_SOFTDIRTY_MASK) == 0)\n      return FALSE;\n\n    if (0 == *vaddr)\n      break;\n    /*\n     * Retry to check that writing to `clear_refs` works as expected.\n     * This malfunction of the soft-dirty bits implementation is\n     * observed on some Linux kernels on Power9 (e.g. in Fedora 36).\n     */\n    clear_soft_dirty_bits();\n    *vaddr = 0;\n  }\n  return TRUE; /*< success */\n}\n\n#  ifndef NO_SOFT_VDB_LINUX_VER_RUNTIME_CHECK\n#    include <string.h> /*< for strcmp() */\n#    include <sys/utsname.h>\n\n/* Ensure the linux (kernel) major/minor version is as given or higher. */\nstatic GC_bool\nensure_min_linux_ver(int major, int minor)\n{\n  struct utsname info;\n  int actual_major;\n  int actual_minor = -1;\n\n  if (uname(&info) == -1) {\n    /* `uname()` has failed, should not happen actually. */\n    return FALSE;\n  }\n  if (strcmp(info.sysname, \"Linux\")) {\n    WARN(\"Cannot ensure Linux version as running on other OS: %s\\n\",\n         info.sysname);\n    return FALSE;\n  }\n  actual_major = GC_parse_version(&actual_minor, info.release);\n  return actual_major > major\n         || (actual_major == major && actual_minor >= minor);\n}\n#  endif\n\n#  ifdef MPROTECT_VDB\nstatic GC_bool\nsoft_dirty_init(void)\n#  else\nGC_INNER GC_bool\nGC_dirty_init(void)\n#  endif\n{\n#  if defined(MPROTECT_VDB) && !defined(CHECK_SOFT_VDB)\n  char *str = GETENV(\"GC_USE_GETWRITEWATCH\");\n#    ifdef GC_PREFER_MPROTECT_VDB\n  if (NULL == str || (*str == '0' && *(str + 1) == '\\0')) {\n    /* The environment variable is unset or set to \"0\". */\n    return FALSE;\n  }\n#    else\n  if (str != NULL && *str == '0' && *(str + 1) == '\\0') {\n    /* The environment variable is set \"0\". */\n    return FALSE;\n  }\n#    endif\n#  endif\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(NULL == soft_vdb_buf);\n#  ifndef NO_SOFT_VDB_LINUX_VER_RUNTIME_CHECK\n  if (!ensure_min_linux_ver(3, 18)) {\n    GC_COND_LOG_PRINTF(\n        \"Running on old kernel lacking correct soft-dirty bit support\\n\");\n    return FALSE;\n  }\n#  endif\n  if (!soft_dirty_open_files())\n    return FALSE;\n  soft_vdb_buf = (pagemap_elem_t *)GC_scratch_alloc(VDB_BUF_SZ);\n  if (NULL == soft_vdb_buf)\n    ABORT(\"Insufficient space for /proc pagemap buffer\");\n  if (!detect_soft_dirty_supported((ptr_t)soft_vdb_buf)) {\n    GC_COND_LOG_PRINTF(\"Soft-dirty bit is not supported by kernel\\n\");\n    /* Release the resources. */\n    GC_scratch_recycle_no_gww(soft_vdb_buf, VDB_BUF_SZ);\n    soft_vdb_buf = NULL;\n    close(clear_refs_fd);\n    clear_refs_fd = -1;\n    close(pagemap_fd);\n    return FALSE;\n  }\n  return TRUE;\n}\n\nstatic off_t pagemap_buf_fpos; /*< valid only if `pagemap_buf_len > 0` */\n\nstatic size_t pagemap_buf_len;\n\n/*\n * Read bytes from `/proc/self/pagemap` file at given file position.\n * `len` is the maximum number of bytes to read; `*pres` is the amount\n * of bytes actually read (always bigger than 0 but never exceeds `len`);\n * `next_fpos_hint` is the file position of the next bytes block to read\n * ahead if possible (0 means no information provided).\n */\nstatic const pagemap_elem_t *\npagemap_buffered_read(size_t *pres, off_t fpos, size_t len,\n                      off_t next_fpos_hint)\n{\n  ssize_t res;\n  size_t ofs;\n\n  GC_ASSERT(GC_page_size != 0);\n  GC_ASSERT(len > 0);\n  if (pagemap_buf_fpos <= fpos\n      && fpos < pagemap_buf_fpos + (off_t)pagemap_buf_len) {\n    /* The requested data is already in the buffer. */\n    ofs = (size_t)(fpos - pagemap_buf_fpos);\n    res = (ssize_t)(pagemap_buf_fpos + pagemap_buf_len - fpos);\n  } else {\n    off_t aligned_pos = fpos\n                        & ~(off_t)(GC_page_size < VDB_BUF_SZ ? GC_page_size - 1\n                                                             : VDB_BUF_SZ - 1);\n\n    for (;;) {\n      size_t count;\n\n      if ((0 == pagemap_buf_len\n           || pagemap_buf_fpos + (off_t)pagemap_buf_len != aligned_pos)\n          && lseek(pagemap_fd, aligned_pos, SEEK_SET) == (off_t)(-1))\n        ABORT_ARG2(\"Failed to lseek /proc/self/pagemap\",\n                   \": offset= %lu, errno= %d\", (unsigned long)fpos, errno);\n\n      /* How much to read at once? */\n      ofs = (size_t)(fpos - aligned_pos);\n      GC_ASSERT(ofs < VDB_BUF_SZ);\n      if (next_fpos_hint > aligned_pos\n          && next_fpos_hint - aligned_pos < VDB_BUF_SZ) {\n        count = VDB_BUF_SZ;\n      } else {\n        count = len + ofs;\n        if (count > VDB_BUF_SZ)\n          count = VDB_BUF_SZ;\n      }\n\n      GC_ASSERT(count % sizeof(pagemap_elem_t) == 0);\n      res = PROC_READ(pagemap_fd, soft_vdb_buf, count);\n      if (res > (ssize_t)ofs)\n        break;\n      if (res <= 0)\n        ABORT_ARG1(\"Failed to read /proc/self/pagemap\", \": errno= %d\",\n                   res < 0 ? errno : 0);\n      /* Retry (once) w/o page-alignment. */\n      aligned_pos = fpos;\n    }\n\n    /* Save the buffer (file window) position and size. */\n    pagemap_buf_fpos = aligned_pos;\n    pagemap_buf_len = (size_t)res;\n    res -= (ssize_t)ofs;\n  }\n\n  GC_ASSERT(ofs % sizeof(pagemap_elem_t) == 0);\n  *pres = (size_t)res < len ? (size_t)res : len;\n  return &soft_vdb_buf[ofs / sizeof(pagemap_elem_t)];\n}\n\nstatic void\nsoft_set_grungy_pages(ptr_t start, ptr_t limit, ptr_t next_start_hint,\n                      GC_bool is_static_root)\n{\n  ptr_t vaddr = (ptr_t)HBLK_PAGE_ALIGNED(start);\n  off_t next_fpos_hint = (off_t)((ADDR(next_start_hint) >> GC_log_pagesize)\n                                 * sizeof(pagemap_elem_t));\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(modHBLKSZ(ADDR(start)) == 0);\n  GC_ASSERT(GC_log_pagesize != 0);\n  while (ADDR_LT(vaddr, limit)) {\n    size_t res;\n    ptr_t limit_buf;\n    word vlen_p = ADDR(limit) - ADDR(vaddr) + GC_page_size - 1;\n    const pagemap_elem_t *bufp = pagemap_buffered_read(\n        &res,\n        (off_t)((ADDR(vaddr) >> GC_log_pagesize) * sizeof(pagemap_elem_t)),\n        (size_t)((vlen_p >> GC_log_pagesize) * sizeof(pagemap_elem_t)),\n        next_fpos_hint);\n\n    if (res % sizeof(pagemap_elem_t) != 0) {\n      /* Punt. */\n      memset(GC_grungy_pages, 0xff, sizeof(page_hash_table));\n      WARN(\"Incomplete read of pagemap, not multiple of entry size\\n\", 0);\n      break;\n    }\n\n    limit_buf = vaddr + ((res / sizeof(pagemap_elem_t)) << GC_log_pagesize);\n    for (; ADDR_LT(vaddr, limit_buf); vaddr += GC_page_size, bufp++) {\n      if ((*bufp & PM_SOFTDIRTY_MASK) != 0) {\n        struct hblk *h;\n        ptr_t next_vaddr = vaddr + GC_page_size;\n\n        if (UNLIKELY(ADDR_LT(limit, next_vaddr))) {\n          next_vaddr = limit;\n        }\n\n        /*\n         * If the bit is set, the respective PTE was written to\n         * since clearing the soft-dirty bits.\n         */\n#  ifdef DEBUG_DIRTY_BITS\n        if (is_static_root)\n          GC_log_printf(\"static root dirty page at: %p\\n\", (void *)vaddr);\n#  endif\n        h = (struct hblk *)vaddr;\n        if (UNLIKELY(ADDR_LT(vaddr, start))) {\n          h = (struct hblk *)start;\n        }\n        for (; ADDR_LT((ptr_t)h, next_vaddr); h++) {\n          size_t index = PHT_HASH(h);\n\n          /*\n           * Filter out the blocks without pointers.  It might worth for\n           * the case when the heap is large enough for the hash collisions\n           * to occur frequently.  Thus, off by default.\n           */\n#  if defined(FILTER_PTRFREE_HBLKS_IN_SOFT_VDB) || defined(CHECKSUMS) \\\n      || defined(DEBUG_DIRTY_BITS)\n          if (!is_static_root) {\n            hdr *hhdr;\n\n#    ifdef CHECKSUMS\n            set_pht_entry_from_index(GC_written_pages, index);\n#    endif\n            GET_HDR(h, hhdr);\n            if (NULL == hhdr)\n              continue;\n\n            (void)GC_find_starting_hblk(h, &hhdr);\n            if (HBLK_IS_FREE(hhdr) || IS_PTRFREE(hhdr))\n              continue;\n#    ifdef DEBUG_DIRTY_BITS\n            GC_log_printf(\"dirty page (hblk) at: %p\\n\", (void *)h);\n#    endif\n          }\n#  else\n          UNUSED_ARG(is_static_root);\n#  endif\n          set_pht_entry_from_index(GC_grungy_pages, index);\n        }\n      } else {\n#  if defined(CHECK_SOFT_VDB) /* `&& defined(MPROTECT_VDB)` */\n        /*\n         * Ensure that each clean page according to the soft-dirty VDB is\n         * also identified such by the `mprotect`-based one.\n         */\n        if (!is_static_root\n            && get_pht_entry_from_index(GC_dirty_pages, PHT_HASH(vaddr))) {\n          ptr_t my_start, my_end; /*< the values are not used */\n\n          /*\n           * There could be a hash collision, thus we need to verify the\n           * page is clean using slow `GC_get_maps()`.\n           */\n          if (GC_enclosing_writable_mapping(vaddr, &my_start, &my_end)) {\n            ABORT(\"Inconsistent soft-dirty against mprotect dirty bits\");\n          }\n        }\n#  endif\n      }\n    }\n    /* Read the next portion of `pagemap` file if incomplete. */\n  }\n}\n\nGC_INLINE void\nGC_soft_read_dirty(GC_bool output_unneeded)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n#  ifndef THREADS\n  /* Similar as for `GC_proc_read_dirty`. */\n  if (getpid() != saved_proc_pid\n      && (-1 == clear_refs_fd /*< no need to retry */\n          || (close(clear_refs_fd), close(pagemap_fd),\n              !soft_dirty_open_files()))) {\n    /* Failed to reopen the files. */\n    if (!output_unneeded) {\n      /* Punt. */\n      memset(GC_grungy_pages, 0xff, sizeof(page_hash_table));\n#    ifdef CHECKSUMS\n      memset(GC_written_pages, 0xff, sizeof(page_hash_table));\n#    endif\n    }\n    return;\n  }\n#  endif\n\n  if (!output_unneeded) {\n    size_t i;\n\n    BZERO(GC_grungy_pages, sizeof(GC_grungy_pages));\n    pagemap_buf_len = 0; /*< invalidate `soft_vdb_buf` */\n\n    for (i = 0; i < GC_n_heap_sects; ++i) {\n      ptr_t start = GC_heap_sects[i].hs_start;\n\n      soft_set_grungy_pages(\n          start, start + GC_heap_sects[i].hs_bytes,\n          i + 1 < GC_n_heap_sects ? GC_heap_sects[i + 1].hs_start : NULL,\n          FALSE);\n    }\n\n#  ifndef NO_VDB_FOR_STATIC_ROOTS\n    for (i = 0; i < n_root_sets; ++i) {\n      soft_set_grungy_pages(\n          (ptr_t)HBLKPTR(GC_static_roots[i].r_start), GC_static_roots[i].r_end,\n          i + 1 < n_root_sets ? GC_static_roots[i + 1].r_start : NULL, TRUE);\n    }\n#  endif\n  }\n\n  clear_soft_dirty_bits();\n}\n#endif /* SOFT_VDB */\n\n#ifndef NO_MANUAL_VDB\nGC_INNER GC_bool GC_manual_vdb = FALSE;\n\nvoid\nGC_dirty_inner(const void *p)\n{\n  size_t index = PHT_HASH(p);\n\n#  if defined(MPROTECT_VDB)\n  /*\n   * Do not update `GC_dirty_pages` if it should be followed by the\n   * page unprotection.\n   */\n  GC_ASSERT(GC_manual_vdb);\n#  endif\n  async_set_pht_entry_from_index(GC_dirty_pages, index);\n}\n#endif /* !NO_MANUAL_VDB */\n\n#ifndef GC_DISABLE_INCREMENTAL\nGC_INNER void\nGC_read_dirty(GC_bool output_unneeded)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n#  ifdef DEBUG_DIRTY_BITS\n  GC_log_printf(\"read dirty begin\\n\");\n#  endif\n  if (GC_manual_vdb\n#  if defined(MPROTECT_VDB)\n      || !GC_GWW_AVAILABLE()\n#  endif\n  ) {\n    if (!output_unneeded)\n      BCOPY(CAST_AWAY_VOLATILE_PVOID(GC_dirty_pages), GC_grungy_pages,\n            sizeof(GC_dirty_pages));\n    BZERO(CAST_AWAY_VOLATILE_PVOID(GC_dirty_pages), sizeof(GC_dirty_pages));\n#  ifdef MPROTECT_VDB\n    if (!GC_manual_vdb)\n      GC_protect_heap();\n#  endif\n    return;\n  }\n\n#  ifdef GWW_VDB\n  GC_gww_read_dirty(output_unneeded);\n#  elif defined(PROC_VDB)\n  GC_proc_read_dirty(output_unneeded);\n#  elif defined(SOFT_VDB)\n  GC_soft_read_dirty(output_unneeded);\n#  endif\n#  if defined(CHECK_SOFT_VDB) /* `&& defined(MPROTECT_VDB)` */\n  BZERO(CAST_AWAY_VOLATILE_PVOID(GC_dirty_pages), sizeof(GC_dirty_pages));\n  GC_protect_heap();\n#  endif\n}\n\n#  if !defined(NO_VDB_FOR_STATIC_ROOTS) && !defined(PROC_VDB)\nGC_INNER GC_bool\nGC_is_vdb_for_static_roots(void)\n{\n  if (GC_manual_vdb)\n    return FALSE;\n#    if defined(MPROTECT_VDB)\n  /* Currently used only in conjunction with `SOFT_VDB`. */\n  return GC_GWW_AVAILABLE();\n#    else\n#      ifndef LINT2\n  GC_ASSERT(GC_incremental);\n#      endif\n  return TRUE;\n#    endif\n}\n#  endif\n\nGC_INNER GC_bool\nGC_page_was_dirty(struct hblk *h)\n{\n  size_t index;\n\n#  ifdef DEFAULT_VDB\n  if (!GC_manual_vdb)\n    return TRUE;\n#  elif defined(PROC_VDB)\n  /* Unless manual VDB is on, the bitmap covers all process memory. */\n  if (GC_manual_vdb)\n#  endif\n  {\n    if (NULL == HDR(h))\n      return TRUE;\n  }\n  index = PHT_HASH(h);\n  return get_pht_entry_from_index(GC_grungy_pages, index);\n}\n\n#  if defined(CHECKSUMS) || defined(PROC_VDB)\nGC_INNER GC_bool\nGC_page_was_ever_dirty(struct hblk *h)\n{\n#    if defined(GWW_VDB) || defined(PROC_VDB) || defined(SOFT_VDB)\n  size_t index;\n\n#      ifdef MPROTECT_VDB\n  if (!GC_GWW_AVAILABLE())\n    return TRUE;\n#      endif\n#      if defined(PROC_VDB)\n  if (GC_manual_vdb)\n#      endif\n  {\n    if (NULL == HDR(h))\n      return TRUE;\n  }\n  index = PHT_HASH(h);\n  return get_pht_entry_from_index(GC_written_pages, index);\n#    else\n  /* TODO: Implement for `MANUAL_VDB` case. */\n  UNUSED_ARG(h);\n  return TRUE;\n#    endif\n}\n#  endif /* CHECKSUMS || PROC_VDB */\n\nGC_INNER void\nGC_remove_protection(struct hblk *h, size_t nblocks, GC_bool is_ptrfree)\n{\n#  ifdef MPROTECT_VDB\n  struct hblk *current;\n  struct hblk *h_trunc; /*< truncated to page boundary */\n  ptr_t h_end;          /*< page boundary following the block end */\n#  endif\n\n#  ifndef PARALLEL_MARK\n  GC_ASSERT(I_HOLD_LOCK());\n#  endif\n#  ifdef MPROTECT_VDB\n  /*\n   * Note it is not allowed to call `GC_printf` (and the friends)\n   * in this function, see Win32 `GC_stop_world` for the details.\n   */\n#    ifdef DONT_PROTECT_PTRFREE\n  if (is_ptrfree)\n    return;\n#    endif\n  if (!GC_auto_incremental || GC_GWW_AVAILABLE())\n    return;\n  GC_ASSERT(GC_page_size != 0);\n  h_trunc = HBLK_PAGE_ALIGNED(h);\n  h_end = PTR_ALIGN_UP((ptr_t)(h + nblocks), GC_page_size);\n  /*\n   * Note that we cannot examine `GC_dirty_pages` to check whether the\n   * page at `h_trunc` has already been marked dirty as there could be\n   * a hash collision.\n   */\n  for (current = h_trunc; ADDR_LT((ptr_t)current, h_end); ++current) {\n    size_t index = PHT_HASH(current);\n\n#    ifndef DONT_PROTECT_PTRFREE\n    if (!is_ptrfree\n        || !ADDR_INSIDE((ptr_t)current, (ptr_t)h, (ptr_t)(h + nblocks)))\n#    endif\n    {\n      async_set_pht_entry_from_index(GC_dirty_pages, index);\n    }\n  }\n  UNPROTECT(h_trunc, h_end - (ptr_t)h_trunc);\n#  else\n  /* Ignore write hints.  They do not help us here. */\n  UNUSED_ARG(h);\n  UNUSED_ARG(nblocks);\n  UNUSED_ARG(is_ptrfree);\n#  endif\n}\n#endif /* !GC_DISABLE_INCREMENTAL */\n\n#if defined(MPROTECT_VDB) && defined(DARWIN)\n/*\n * The following sources were used as a \"reference\" for this exception\n * handling code:\n *   - Apple's mach/xnu documentation;\n *   - Timothy J. Wood's \"Mach Exception Handlers 101\" post to the omnigroup's\n *     macosx-dev list;\n *   - macosx-nat.c from Apple's GDB source code.\n */\n\n/*\n * The bug that caused all this trouble should now be fixed.\n * This should eventually be removed if all goes well.\n */\n\n#  include <mach/exception.h>\n#  include <mach/mach.h>\n#  include <mach/mach_error.h>\n#  include <mach/task.h>\n\nEXTERN_C_BEGIN\n\n/*\n * Some of the following prototypes are missing in any header, although\n * they are documented.  Some are in platform `mach/exc.h` file.\n */\nextern boolean_t exc_server(mach_msg_header_t *, mach_msg_header_t *);\n\nextern kern_return_t exception_raise(mach_port_t, mach_port_t, mach_port_t,\n                                     exception_type_t, exception_data_t,\n                                     mach_msg_type_number_t);\n\nextern kern_return_t exception_raise_state(\n    mach_port_t, mach_port_t, mach_port_t, exception_type_t, exception_data_t,\n    mach_msg_type_number_t, thread_state_flavor_t *, thread_state_t,\n    mach_msg_type_number_t, thread_state_t, mach_msg_type_number_t *);\n\nextern kern_return_t exception_raise_state_identity(\n    mach_port_t, mach_port_t, mach_port_t, exception_type_t, exception_data_t,\n    mach_msg_type_number_t, thread_state_flavor_t *, thread_state_t,\n    mach_msg_type_number_t, thread_state_t, mach_msg_type_number_t *);\n\nGC_API_OSCALL kern_return_t catch_exception_raise(\n    mach_port_t exception_port, mach_port_t thread, mach_port_t task,\n    exception_type_t exception, exception_data_t code,\n    mach_msg_type_number_t code_count);\n\nGC_API_OSCALL kern_return_t catch_exception_raise_state(\n    mach_port_name_t exception_port, int exception, exception_data_t code,\n    mach_msg_type_number_t codeCnt, int flavor, thread_state_t old_state,\n    int old_stateCnt, thread_state_t new_state, int new_stateCnt);\n\nGC_API_OSCALL kern_return_t catch_exception_raise_state_identity(\n    mach_port_name_t exception_port, mach_port_t thread, mach_port_t task,\n    int exception, exception_data_t code, mach_msg_type_number_t codeCnt,\n    int flavor, thread_state_t old_state, int old_stateCnt,\n    thread_state_t new_state, int new_stateCnt);\n\nEXTERN_C_END\n\n/* These should never be called, but just in case... */\nGC_API_OSCALL kern_return_t\ncatch_exception_raise_state(mach_port_name_t exception_port, int exception,\n                            exception_data_t code,\n                            mach_msg_type_number_t codeCnt, int flavor,\n                            thread_state_t old_state, int old_stateCnt,\n                            thread_state_t new_state, int new_stateCnt)\n{\n  UNUSED_ARG(exception_port);\n  UNUSED_ARG(exception);\n  UNUSED_ARG(code);\n  UNUSED_ARG(codeCnt);\n  UNUSED_ARG(flavor);\n  UNUSED_ARG(old_state);\n  UNUSED_ARG(old_stateCnt);\n  UNUSED_ARG(new_state);\n  UNUSED_ARG(new_stateCnt);\n  ABORT_RET(\"Unexpected catch_exception_raise_state invocation\");\n  return KERN_INVALID_ARGUMENT;\n}\n\nGC_API_OSCALL kern_return_t\ncatch_exception_raise_state_identity(\n    mach_port_name_t exception_port, mach_port_t thread, mach_port_t task,\n    int exception, exception_data_t code, mach_msg_type_number_t codeCnt,\n    int flavor, thread_state_t old_state, int old_stateCnt,\n    thread_state_t new_state, int new_stateCnt)\n{\n  UNUSED_ARG(exception_port);\n  UNUSED_ARG(thread);\n  UNUSED_ARG(task);\n  UNUSED_ARG(exception);\n  UNUSED_ARG(code);\n  UNUSED_ARG(codeCnt);\n  UNUSED_ARG(flavor);\n  UNUSED_ARG(old_state);\n  UNUSED_ARG(old_stateCnt);\n  UNUSED_ARG(new_state);\n  UNUSED_ARG(new_stateCnt);\n  ABORT_RET(\"Unexpected catch_exception_raise_state_identity invocation\");\n  return KERN_INVALID_ARGUMENT;\n}\n\n#  define MAX_EXCEPTION_PORTS 16\n\nstatic struct {\n  mach_msg_type_number_t count;\n  exception_mask_t masks[MAX_EXCEPTION_PORTS];\n  exception_handler_t ports[MAX_EXCEPTION_PORTS];\n  exception_behavior_t behaviors[MAX_EXCEPTION_PORTS];\n  thread_state_flavor_t flavors[MAX_EXCEPTION_PORTS];\n} GC_old_exc_ports;\n\nSTATIC struct ports_s {\n  void (*volatile os_callback[3])(void);\n  mach_port_t exception;\n#  if defined(THREADS)\n  mach_port_t reply;\n#  endif\n} GC_ports = { { /*< this is to prevent stripping these routines as dead */\n                 (void (*)(void))catch_exception_raise,\n                 (void (*)(void))catch_exception_raise_state,\n                 (void (*)(void))catch_exception_raise_state_identity },\n#  ifdef THREADS\n               0 /* `exception` */,\n#  endif\n               0 };\n\ntypedef struct {\n  mach_msg_header_t head;\n} GC_msg_t;\n\ntypedef enum {\n  GC_MP_NORMAL,\n  GC_MP_DISCARDING,\n  GC_MP_STOPPED\n} GC_mprotect_state_t;\n\n#  ifdef THREADS\n/*\n * FIXME: 1 and 2 seem to be safe to use in the `msgh_id` field, but it\n * is not documented.  Use the source and see if they should be OK.\n */\n#    define ID_STOP 1\n#    define ID_RESUME 2\n\n/* This value is only used on the reply port. */\n#    define ID_ACK 3\n\nSTATIC GC_mprotect_state_t GC_mprotect_state = GC_MP_NORMAL;\n\n/* The following should *only* be called when the world is stopped. */\nSTATIC void\nGC_mprotect_thread_notify(mach_msg_id_t id)\n{\n  struct buf_s {\n    GC_msg_t msg;\n    mach_msg_trailer_t trailer;\n  } buf;\n  mach_msg_return_t r;\n\n  /* remote, local */\n  buf.msg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);\n  buf.msg.head.msgh_size = sizeof(buf.msg);\n  buf.msg.head.msgh_remote_port = GC_ports.exception;\n  buf.msg.head.msgh_local_port = MACH_PORT_NULL;\n  buf.msg.head.msgh_id = id;\n\n  r = mach_msg(&buf.msg.head, MACH_SEND_MSG | MACH_RCV_MSG | MACH_RCV_LARGE,\n               sizeof(buf.msg), sizeof(buf), GC_ports.reply,\n               MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);\n  if (r != MACH_MSG_SUCCESS)\n    ABORT(\"mach_msg failed in GC_mprotect_thread_notify\");\n  if (buf.msg.head.msgh_id != ID_ACK)\n    ABORT(\"Invalid ack in GC_mprotect_thread_notify\");\n}\n\n/* Should only be called by the `mprotect` thread. */\nSTATIC void\nGC_mprotect_thread_reply(void)\n{\n  GC_msg_t msg;\n  mach_msg_return_t r;\n\n  /* remote, local */\n  msg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);\n  msg.head.msgh_size = sizeof(msg);\n  msg.head.msgh_remote_port = GC_ports.reply;\n  msg.head.msgh_local_port = MACH_PORT_NULL;\n  msg.head.msgh_id = ID_ACK;\n\n  r = mach_msg(&msg.head, MACH_SEND_MSG, sizeof(msg), 0, MACH_PORT_NULL,\n               MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);\n  if (r != MACH_MSG_SUCCESS)\n    ABORT(\"mach_msg failed in GC_mprotect_thread_reply\");\n}\n\nGC_INNER void\nGC_mprotect_stop(void)\n{\n  GC_mprotect_thread_notify(ID_STOP);\n}\n\nGC_INNER void\nGC_mprotect_resume(void)\n{\n  GC_mprotect_thread_notify(ID_RESUME);\n}\n\n#    ifdef CAN_HANDLE_FORK\nGC_INNER void\nGC_dirty_update_child(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  if (0 == GC_task_self) {\n    /* The GC incremental mode is off. */\n    return;\n  }\n\n  GC_ASSERT(GC_mprotect_state == GC_MP_NORMAL);\n  GC_task_self = mach_task_self(); /*< needed by `UNPROTECT()` */\n  GC_unprotect_all_heap();\n\n  /* Restore the old task exception ports. */\n  /* TODO: Should we do it in `fork_prepare_proc`/`fork_parent_proc`? */\n  if (GC_old_exc_ports.count > 0) {\n    /* TODO: Should we check `GC_old_exc_ports.count <= 1`? */\n    if (task_set_exception_ports(\n            GC_task_self, GC_old_exc_ports.masks[0], GC_old_exc_ports.ports[0],\n            GC_old_exc_ports.behaviors[0], GC_old_exc_ports.flavors[0])\n        != KERN_SUCCESS)\n      ABORT(\"task_set_exception_ports failed (in child)\");\n  }\n\n  /* TODO: Re-enable incremental mode in child. */\n  GC_task_self = 0;\n  GC_incremental = FALSE;\n}\n#    endif /* CAN_HANDLE_FORK */\n\n#  else\n/* The compiler should optimize away any `GC_mprotect_state` computations. */\n#    define GC_mprotect_state GC_MP_NORMAL\n#  endif /* !THREADS */\n\nstruct mp_reply_s {\n  mach_msg_header_t head;\n  char data[256];\n};\n\nstruct mp_msg_s {\n  mach_msg_header_t head;\n  mach_msg_body_t msgh_body;\n  char data[1024];\n};\n\nSTATIC void *\nGC_mprotect_thread(void *arg)\n{\n  mach_msg_return_t r;\n  /*\n   * These two structures contain some private kernel data.  We do not need\n   * to access any of it so we do not bother defining a proper structure.\n   * The correct definitions are in the `xnu` source code.\n   */\n  struct mp_reply_s reply;\n  struct mp_msg_s msg;\n  mach_msg_id_t id;\n\n  if (ADDR(arg) == GC_WORD_MAX)\n    return 0; /*< to prevent a compiler warning */\n#  if defined(CPPCHECK)\n  reply.data[0] = 0; /*< to prevent \"field unused\" warnings */\n  msg.data[0] = 0;\n#  endif\n\n#  if defined(HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID)\n  (void)pthread_setname_np(\"GC-mprotect\");\n#  endif\n#  if defined(THREADS) && !defined(GC_NO_THREADS_DISCOVERY)\n  GC_darwin_register_self_mach_handler();\n#  endif\n\n  for (;;) {\n    r = mach_msg(\n        &msg.head,\n        MACH_RCV_MSG | MACH_RCV_LARGE\n            | (GC_mprotect_state == GC_MP_DISCARDING ? MACH_RCV_TIMEOUT : 0),\n        0, sizeof(msg), GC_ports.exception,\n        GC_mprotect_state == GC_MP_DISCARDING ? 0 : MACH_MSG_TIMEOUT_NONE,\n        MACH_PORT_NULL);\n    id = r == MACH_MSG_SUCCESS ? msg.head.msgh_id : -1;\n\n#  if defined(THREADS)\n    if (GC_mprotect_state == GC_MP_DISCARDING) {\n      if (r == MACH_RCV_TIMED_OUT) {\n        GC_mprotect_state = GC_MP_STOPPED;\n        GC_mprotect_thread_reply();\n        continue;\n      }\n      if (r == MACH_MSG_SUCCESS && (id == ID_STOP || id == ID_RESUME))\n        ABORT(\"Out of order mprotect thread request\");\n    }\n#  endif /* THREADS */\n\n    if (r != MACH_MSG_SUCCESS) {\n      ABORT_ARG2(\"mach_msg failed\", \": errcode= %d (%s)\", (int)r,\n                 mach_error_string(r));\n    }\n\n    switch (id) {\n#  if defined(THREADS)\n    case ID_STOP:\n      if (GC_mprotect_state != GC_MP_NORMAL)\n        ABORT(\"Called mprotect_stop when state wasn't normal\");\n      GC_mprotect_state = GC_MP_DISCARDING;\n      break;\n    case ID_RESUME:\n      if (GC_mprotect_state != GC_MP_STOPPED)\n        ABORT(\"Called mprotect_resume when state wasn't stopped\");\n      GC_mprotect_state = GC_MP_NORMAL;\n      GC_mprotect_thread_reply();\n      break;\n#  endif /* THREADS */\n    default:\n      /* Handle the message (it calls `catch_exception_raise`). */\n      if (!exc_server(&msg.head, &reply.head))\n        ABORT(\"exc_server failed\");\n      /* Send the reply. */\n      r = mach_msg(&reply.head, MACH_SEND_MSG, reply.head.msgh_size, 0,\n                   MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);\n      if (r != MACH_MSG_SUCCESS) {\n        /*\n         * This will fail if the thread dies, but the thread should\n         * not die...\n         */\n#  ifdef BROKEN_EXCEPTION_HANDLING\n        GC_err_printf(\"mach_msg failed with %d %s while sending \"\n                      \"exc reply\\n\",\n                      (int)r, mach_error_string(r));\n#  else\n        ABORT(\"mach_msg failed while sending exception reply\");\n#  endif\n      }\n    }\n  }\n}\n\n/*\n * All this `SIGBUS` code should not be necessary.  All protection\n * faults should be going through the `mach` exception handler.\n * However, it seems a `SIGBUS` is occasionally sent for some unknown\n * reason; even more odd, it seems to be meaningless and safe to ignore.\n */\n#  ifdef BROKEN_EXCEPTION_HANDLING\n\n/*\n * Updates to this are not atomic, but the `SIGBUS` signals seem pretty rare.\n * Even if this does not get updated property, it is not really a problem.\n */\nSTATIC int GC_sigbus_count = 0;\n\nSTATIC void\nGC_darwin_sigbus(int num, siginfo_t *sip, void *context)\n{\n  if (num != SIGBUS)\n    ABORT(\"Got a non-sigbus signal in the sigbus handler\");\n\n  /*\n   * Ugh... some seem safe to ignore, but too many in a row probably means\n   * trouble.  `GC_sigbus_count` is reset for each `mach` exception that\n   * is handled.\n   */\n  if (GC_sigbus_count >= 8)\n    ABORT(\"Got many SIGBUS signals in a row!\");\n  GC_sigbus_count++;\n  WARN(\"Ignoring SIGBUS\\n\", 0);\n}\n#  endif /* BROKEN_EXCEPTION_HANDLING */\n\nGC_INNER GC_bool\nGC_dirty_init(void)\n{\n  kern_return_t r;\n  mach_port_t me;\n  pthread_t thread;\n  pthread_attr_t attr;\n  exception_mask_t mask;\n\n  GC_ASSERT(I_HOLD_LOCK());\n#  if defined(CAN_HANDLE_FORK) && !defined(THREADS)\n  if (GC_handle_fork) {\n    /*\n     * To both support GC incremental mode and GC functions usage in\n     * the forked child process, `pthread_atfork` should be used to\n     * install handlers that switch off `GC_incremental` in the child\n     * gracefully (unprotecting all pages and clearing\n     * `GC_mach_handler_thread`).  For now, we just disable incremental\n     * mode if `fork()` handling is requested by the client.\n     */\n    WARN(\"Can't turn on GC incremental mode as fork()\"\n         \" handling requested\\n\",\n         0);\n    return FALSE;\n  }\n#  endif\n\n  GC_VERBOSE_LOG_PRINTF(\"Initializing mach/darwin mprotect\"\n                        \" virtual dirty bit implementation\\n\");\n#  ifdef BROKEN_EXCEPTION_HANDLING\n  WARN(\"Enabling workarounds for various darwin exception handling bugs\\n\", 0);\n#  endif\n  if (GC_page_size % HBLKSIZE != 0) {\n    ABORT(\"Page size not multiple of HBLKSIZE\");\n  }\n\n  GC_task_self = me = mach_task_self();\n  GC_ASSERT(me != 0);\n\n  r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.exception);\n  /* TODO: Call `WARN()` and return `FALSE` in case of a failure. */\n  if (r != KERN_SUCCESS)\n    ABORT(\"mach_port_allocate failed (exception port)\");\n\n  r = mach_port_insert_right(me, GC_ports.exception, GC_ports.exception,\n                             MACH_MSG_TYPE_MAKE_SEND);\n  if (r != KERN_SUCCESS)\n    ABORT(\"mach_port_insert_right failed (exception port)\");\n\n#  if defined(THREADS)\n  r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.reply);\n  if (r != KERN_SUCCESS)\n    ABORT(\"mach_port_allocate failed (reply port)\");\n#  endif\n\n  /* The exceptions we want to catch. */\n  mask = EXC_MASK_BAD_ACCESS;\n  r = task_get_exception_ports(me, mask, GC_old_exc_ports.masks,\n                               &GC_old_exc_ports.count, GC_old_exc_ports.ports,\n                               GC_old_exc_ports.behaviors,\n                               GC_old_exc_ports.flavors);\n  if (r != KERN_SUCCESS)\n    ABORT(\"task_get_exception_ports failed\");\n\n  r = task_set_exception_ports(me, mask, GC_ports.exception, EXCEPTION_DEFAULT,\n                               GC_MACH_THREAD_STATE);\n  if (r != KERN_SUCCESS)\n    ABORT(\"task_set_exception_ports failed\");\n\n  if (pthread_attr_init(&attr) != 0)\n    ABORT(\"pthread_attr_init failed\");\n  if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)\n    ABORT(\"pthread_attr_setdetachedstate failed\");\n  /* This will call the real `pthreads` routine, not our wrapper. */\n  if (GC_inner_pthread_create(&thread, &attr, GC_mprotect_thread, NULL) != 0)\n    ABORT(\"pthread_create failed\");\n  (void)pthread_attr_destroy(&attr);\n\n  /* Setup the handler for ignoring the meaningless `SIGBUS` signals. */\n#  ifdef BROKEN_EXCEPTION_HANDLING\n  {\n    struct sigaction sa, oldsa;\n    sa.sa_handler = (SIG_HNDLR_PTR)GC_darwin_sigbus;\n    sigemptyset(&sa.sa_mask);\n    sa.sa_flags = SA_RESTART | SA_SIGINFO;\n    /* `sa.sa_restorer` is deprecated and should not be initialized. */\n    if (sigaction(SIGBUS, &sa, &oldsa) < 0)\n      ABORT(\"sigaction failed\");\n    if ((GC_funcptr_uint)oldsa.sa_handler != (GC_funcptr_uint)SIG_DFL) {\n      GC_VERBOSE_LOG_PRINTF(\"Replaced other SIGBUS handler\\n\");\n    }\n  }\n#  endif /* BROKEN_EXCEPTION_HANDLING */\n#  if defined(CPPCHECK)\n  GC_noop1((word)(GC_funcptr_uint)GC_ports.os_callback[0]);\n#  endif\n  return TRUE;\n}\n\n/*\n * The source code for Apple's GDB was used as a reference for the\n * exception forwarding code.  This code is similar to be GDB code only\n * because there is only one way to do it.\n */\nSTATIC kern_return_t\nGC_forward_exception(mach_port_t thread, mach_port_t task,\n                     exception_type_t exception, exception_data_t data,\n                     mach_msg_type_number_t data_count)\n{\n  size_t i;\n  kern_return_t r;\n  mach_port_t port;\n  exception_behavior_t behavior;\n  thread_state_flavor_t flavor;\n\n  thread_state_data_t thread_state;\n  mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;\n\n  for (i = 0; i < (size_t)GC_old_exc_ports.count; i++) {\n    if ((GC_old_exc_ports.masks[i] & ((exception_mask_t)1 << exception)) != 0)\n      break;\n  }\n  if (i == (size_t)GC_old_exc_ports.count)\n    ABORT(\"No handler for exception!\");\n\n  port = GC_old_exc_ports.ports[i];\n  behavior = GC_old_exc_ports.behaviors[i];\n  flavor = GC_old_exc_ports.flavors[i];\n\n  if (behavior == EXCEPTION_STATE || behavior == EXCEPTION_STATE_IDENTITY) {\n    r = thread_get_state(thread, flavor, thread_state, &thread_state_count);\n    if (r != KERN_SUCCESS)\n      ABORT(\"thread_get_state failed in forward_exception\");\n  }\n\n  switch (behavior) {\n  case EXCEPTION_STATE:\n    r = exception_raise_state(port, thread, task, exception, data, data_count,\n                              &flavor, thread_state, thread_state_count,\n                              thread_state, &thread_state_count);\n    break;\n  case EXCEPTION_STATE_IDENTITY:\n    r = exception_raise_state_identity(\n        port, thread, task, exception, data, data_count, &flavor, thread_state,\n        thread_state_count, thread_state, &thread_state_count);\n    break;\n  /* `case EXCEPTION_DEFAULT:` - the default signal handlers. */\n  default:\n    /* The user-supplied signal handlers. */\n    r = exception_raise(port, thread, task, exception, data, data_count);\n  }\n\n  if (behavior == EXCEPTION_STATE || behavior == EXCEPTION_STATE_IDENTITY) {\n    r = thread_set_state(thread, flavor, thread_state, thread_state_count);\n    if (r != KERN_SUCCESS)\n      ABORT(\"thread_set_state failed in forward_exception\");\n  }\n  return r;\n}\n\n#  define FWD() GC_forward_exception(thread, task, exception, code, code_count)\n\n#  ifdef ARM32\n#    define DARWIN_EXC_STATE ARM_EXCEPTION_STATE\n#    define DARWIN_EXC_STATE_COUNT ARM_EXCEPTION_STATE_COUNT\n#    define DARWIN_EXC_STATE_T arm_exception_state_t\n#    define DARWIN_EXC_STATE_DAR THREAD_FLD_NAME(far)\n#  elif defined(AARCH64)\n#    define DARWIN_EXC_STATE ARM_EXCEPTION_STATE64\n#    define DARWIN_EXC_STATE_COUNT ARM_EXCEPTION_STATE64_COUNT\n#    define DARWIN_EXC_STATE_T arm_exception_state64_t\n#    define DARWIN_EXC_STATE_DAR THREAD_FLD_NAME(far)\n#  elif defined(POWERPC)\n#    if CPP_WORDSZ == 32\n#      define DARWIN_EXC_STATE PPC_EXCEPTION_STATE\n#      define DARWIN_EXC_STATE_COUNT PPC_EXCEPTION_STATE_COUNT\n#      define DARWIN_EXC_STATE_T ppc_exception_state_t\n#    else\n#      define DARWIN_EXC_STATE PPC_EXCEPTION_STATE64\n#      define DARWIN_EXC_STATE_COUNT PPC_EXCEPTION_STATE64_COUNT\n#      define DARWIN_EXC_STATE_T ppc_exception_state64_t\n#    endif\n#    define DARWIN_EXC_STATE_DAR THREAD_FLD_NAME(dar)\n#  elif defined(I386) || defined(X86_64)\n#    if CPP_WORDSZ == 32\n#      if defined(i386_EXCEPTION_STATE_COUNT) \\\n          && !defined(x86_EXCEPTION_STATE32_COUNT)\n/* Use old naming convention for i686. */\n#        define DARWIN_EXC_STATE i386_EXCEPTION_STATE\n#        define DARWIN_EXC_STATE_COUNT i386_EXCEPTION_STATE_COUNT\n#        define DARWIN_EXC_STATE_T i386_exception_state_t\n#      else\n#        define DARWIN_EXC_STATE x86_EXCEPTION_STATE32\n#        define DARWIN_EXC_STATE_COUNT x86_EXCEPTION_STATE32_COUNT\n#        define DARWIN_EXC_STATE_T x86_exception_state32_t\n#      endif\n#    else\n#      define DARWIN_EXC_STATE x86_EXCEPTION_STATE64\n#      define DARWIN_EXC_STATE_COUNT x86_EXCEPTION_STATE64_COUNT\n#      define DARWIN_EXC_STATE_T x86_exception_state64_t\n#    endif\n#    define DARWIN_EXC_STATE_DAR THREAD_FLD_NAME(faultvaddr)\n#  elif !defined(CPPCHECK)\n#    error FIXME for non-arm/ppc/x86 darwin\n#  endif\n\n/*\n * This violates the namespace rules but there is not anything that can\n * be done about it.  The exception handling stuff is hard-coded to\n * call this.  `catch_exception_raise`, `catch_exception_raise_state`\n * and `catch_exception_raise_state_identity` are called from OS.\n */\nGC_API_OSCALL kern_return_t\ncatch_exception_raise(mach_port_t exception_port, mach_port_t thread,\n                      mach_port_t task, exception_type_t exception,\n                      exception_data_t code, mach_msg_type_number_t code_count)\n{\n  kern_return_t r;\n  char *addr;\n  thread_state_flavor_t flavor = DARWIN_EXC_STATE;\n  mach_msg_type_number_t exc_state_count = DARWIN_EXC_STATE_COUNT;\n  DARWIN_EXC_STATE_T exc_state;\n\n  UNUSED_ARG(exception_port);\n  UNUSED_ARG(task);\n  if (exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) {\n#  ifdef DEBUG_EXCEPTION_HANDLING\n    /* We are not interested in, pass it on to the old handler. */\n    GC_log_printf(\"Exception: 0x%x Code: 0x%x 0x%x in catch...\\n\", exception,\n                  code_count > 0 ? code[0] : -1,\n                  code_count > 1 ? code[1] : -1);\n#  else\n    UNUSED_ARG(code_count);\n#  endif\n    return FWD();\n  }\n\n  r = thread_get_state(thread, flavor, (natural_t *)&exc_state,\n                       &exc_state_count);\n  if (r != KERN_SUCCESS) {\n    /*\n     * The thread is supposed to be suspended while the exception\n     * handler is called.  This should not fail.\n     */\n#  ifdef BROKEN_EXCEPTION_HANDLING\n    GC_err_printf(\"thread_get_state failed in catch_exception_raise\\n\");\n    return KERN_SUCCESS;\n#  else\n    ABORT(\"thread_get_state failed in catch_exception_raise\");\n#  endif\n  }\n\n  /* This is the address that caused the fault. */\n  addr = (char *)exc_state.DARWIN_EXC_STATE_DAR;\n  if (!is_header_found_async(addr)) {\n    /*\n     * Ugh... just like the `SIGBUS` problem above, it seems we get\n     * a bogus `KERN_PROTECTION_FAILURE` every once and a while.\n     * We wait till we get a bunch in a row before doing anything\n     * about it.  If a \"real\" fault ever occurs, it will just keep\n     * faulting over and over, and we will hit the limit pretty quickly.\n     */\n#  ifdef BROKEN_EXCEPTION_HANDLING\n    static const char *last_fault;\n    static int last_fault_count;\n\n    if (addr != last_fault) {\n      last_fault = addr;\n      last_fault_count = 0;\n    }\n    if (++last_fault_count < 32) {\n      if (last_fault_count == 1)\n        WARN(\"Ignoring KERN_PROTECTION_FAILURE at %p\\n\", addr);\n      return KERN_SUCCESS;\n    }\n\n    GC_err_printf(\"Unexpected KERN_PROTECTION_FAILURE at %p; aborting...\\n\",\n                  (void *)addr);\n    /*\n     * Cannot pass it along to the signal handler because that is ignoring\n     * `SIGBUS` signals.  We also should not call `ABORT()` here as signals\n     * do not always work too well from the exception handler.\n     */\n    EXIT();\n#  else\n    /*\n     * Pass it along to the next exception handler (which should call\n     * `SIGBUS`/`SIGSEGV`).\n     */\n    return FWD();\n#  endif /* !BROKEN_EXCEPTION_HANDLING */\n  }\n\n#  ifdef BROKEN_EXCEPTION_HANDLING\n  /* Reset the number of consecutive `SIGBUS` signals. */\n  GC_sigbus_count = 0;\n#  endif\n\n  GC_ASSERT(GC_page_size != 0);\n  if (GC_mprotect_state == GC_MP_NORMAL) {\n    /* The common case. */\n    struct hblk *h = HBLK_PAGE_ALIGNED(addr);\n    size_t i;\n\n#  ifdef CHECKSUMS\n    GC_record_fault(h);\n#  endif\n    UNPROTECT(h, GC_page_size);\n    for (i = 0; i < divHBLKSZ(GC_page_size); i++) {\n      size_t index = PHT_HASH(h + i);\n\n      async_set_pht_entry_from_index(GC_dirty_pages, index);\n    }\n  } else if (GC_mprotect_state == GC_MP_DISCARDING) {\n    /*\n     * Lie to the thread for now.  No sense `UNPROTECT`'ing the memory\n     * when we are just going to `PROTECT()` it again later.\n     * The thread will just fault again once it resumes.\n     */\n  } else {\n    /* Should not happen, I do not think. */\n    GC_err_printf(\"KERN_PROTECTION_FAILURE while world is stopped\\n\");\n    return FWD();\n  }\n  return KERN_SUCCESS;\n}\n#  undef FWD\n\n#  ifndef NO_DESC_CATCH_EXCEPTION_RAISE\n/*\n * These symbols should have `REFERENCED_DYNAMICALLY` (0x10) bit set to\n * let strip know they are not to be stripped.\n */\n__asm__(\".desc _catch_exception_raise, 0x10\");\n__asm__(\".desc _catch_exception_raise_state, 0x10\");\n__asm__(\".desc _catch_exception_raise_state_identity, 0x10\");\n#  endif\n\n#endif /* DARWIN && MPROTECT_VDB */\n\nGC_API int GC_CALL\nGC_incremental_protection_needs(void)\n{\n  GC_ASSERT(GC_is_initialized);\n#ifdef MPROTECT_VDB\n#  if defined(GWW_VDB) || (defined(SOFT_VDB) && !defined(CHECK_SOFT_VDB))\n  /* Only if the incremental mode is already switched on. */\n  if (GC_GWW_AVAILABLE())\n    return GC_PROTECTS_NONE;\n#  endif\n#  ifndef DONT_PROTECT_PTRFREE\n  if (GC_page_size != HBLKSIZE)\n    return GC_PROTECTS_POINTER_HEAP | GC_PROTECTS_PTRFREE_HEAP;\n#  endif\n  return GC_PROTECTS_POINTER_HEAP;\n#else\n  return GC_PROTECTS_NONE;\n#endif\n}\n\nGC_API unsigned GC_CALL\nGC_get_actual_vdb(void)\n{\n#ifndef GC_DISABLE_INCREMENTAL\n  if (GC_incremental) {\n#  ifndef NO_MANUAL_VDB\n    if (GC_manual_vdb)\n      return GC_VDB_MANUAL;\n#  endif\n#  ifdef MPROTECT_VDB\n#    ifdef GWW_VDB\n    if (GC_GWW_AVAILABLE())\n      return GC_VDB_GWW;\n#    endif\n#    ifdef SOFT_VDB\n    if (GC_GWW_AVAILABLE())\n      return GC_VDB_SOFT;\n#    endif\n    return GC_VDB_MPROTECT;\n#  elif defined(GWW_VDB)\n    return GC_VDB_GWW;\n#  elif defined(SOFT_VDB)\n    return GC_VDB_SOFT;\n#  elif defined(PROC_VDB)\n    return GC_VDB_PROC;\n#  else /* DEFAULT_VDB */\n    return GC_VDB_DEFAULT;\n#  endif\n  }\n#endif\n  return GC_VDB_NONE;\n}\n\n#ifdef ECOS\n/* Undo `sbrk()` redirection. */\n#  undef sbrk\n#endif\n\nGC_API void GC_CALL\nGC_set_pages_executable(int value)\n{\n  GC_ASSERT(!GC_is_initialized);\n  /*\n   * Even if `IGNORE_PAGES_EXECUTABLE` macro is defined,\n   * `GC_pages_executable` is touched here to prevent a compiler warning.\n   */\n  GC_pages_executable = (GC_bool)(value != 0);\n}\n\nGC_API int GC_CALL\nGC_get_pages_executable(void)\n{\n  /*\n   * `GC_get_pages_executable` is defined after all the places\n   * where `GC_get_pages_executable` is undefined.\n   */\n#ifdef IGNORE_PAGES_EXECUTABLE\n  /* Always allocate executable memory. */\n  return 1;\n#else\n  return (int)GC_pages_executable;\n#endif\n}\n\n/*\n * Call stack save code for debugging.  Should probably be in\n * `mach_dep.c` file, but that requires reorganization.\n */\n#ifdef NEED_CALLINFO\n\n/*\n * I suspect the following works for most Un*x i686 variants, so long as\n * the frame pointer is explicitly stored.  In the case of gcc, the client\n * code should not be compiled with `-fomit-frame-pointer` option.\n */\n#  if defined(I386) && defined(LINUX) && defined(SAVE_CALL_CHAIN)\nstruct frame {\n  struct frame *fr_savfp;\n  long fr_savpc;\n#    if NARGS > 0\n  /* All the arguments go here. */\n  long fr_arg[NARGS];\n#    endif\n};\n#  endif\n\n#  if defined(SPARC)\n#    if defined(LINUX)\n#      if defined(SAVE_CALL_CHAIN)\nstruct frame {\n  long fr_local[8];\n  long fr_arg[6];\n  struct frame *fr_savfp;\n  long fr_savpc;\n#        ifndef __arch64__\n  char *fr_stret;\n#        endif\n  long fr_argd[6];\n  long fr_argx[0];\n};\n#      endif\n#    elif defined(DRSNX)\n#      include <sys/sparc/frame.h>\n#    elif defined(OPENBSD)\n#      include <frame.h>\n#    elif defined(FREEBSD) || defined(NETBSD)\n#      include <machine/frame.h>\n#    else\n#      include <sys/frame.h>\n#    endif\n#    if NARGS > 6\n#      error We only know how to get the first 6 arguments\n#    endif\n#  endif /* SPARC */\n\n/*\n * Fill in the `pc` and `argument` information for up to `NFRAMES` of\n * my callers.  Ignore my frame and my callers frame.\n */\n\n#  if defined(GC_HAVE_BUILTIN_BACKTRACE)\n#    ifdef _MSC_VER\nEXTERN_C_BEGIN\nint backtrace(void *addresses[], int count);\nchar **backtrace_symbols(void *const addresses[], int count);\nEXTERN_C_END\n#    else\n#      include <execinfo.h>\n#    endif\n#  endif /* GC_HAVE_BUILTIN_BACKTRACE */\n\n#  ifdef SAVE_CALL_CHAIN\n\n#    if NARGS == 0 && NFRAMES % 2 == 0 /*< no padding */ \\\n        && defined(GC_HAVE_BUILTIN_BACKTRACE)\n\n#      ifdef REDIRECT_MALLOC\n/*\n * Deal with possible `malloc()` calls in `backtrace()` by omitting\n * the infinitely recursing backtrace.\n */\nSTATIC GC_bool GC_in_save_callers = FALSE;\n\n#        if defined(THREADS) && defined(DBG_HDRS_ALL)\n\nGC_INNER void\nGC_save_callers_no_unlock(struct callinfo info[NFRAMES])\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  info[0].ci_pc\n      = CAST_THRU_UINTPTR(GC_return_addr_t, GC_save_callers_no_unlock);\n  BZERO(&info[1], sizeof(void *) * (NFRAMES - 1));\n}\n#        endif\n#      endif /* REDIRECT_MALLOC */\n\nGC_INNER void\nGC_save_callers(struct callinfo info[NFRAMES])\n{\n  void *tmp_info[NFRAMES + 1];\n  int npcs, i;\n\n  /*\n   * `backtrace()` may call `dl_iterate_phdr` which is also used by\n   * `GC_register_dynamic_libraries()`, and `dl_iterate_phdr` is not\n   * guaranteed to be reentrant.\n   */\n  GC_ASSERT(I_HOLD_LOCK());\n\n  GC_STATIC_ASSERT(sizeof(struct callinfo) == sizeof(void *));\n#      ifdef REDIRECT_MALLOC\n  if (GC_in_save_callers) {\n    info[0].ci_pc = CAST_THRU_UINTPTR(GC_return_addr_t, GC_save_callers);\n    BZERO(&info[1], sizeof(void *) * (NFRAMES - 1));\n    return;\n  }\n  GC_in_save_callers = TRUE;\n  /* `backtrace()` might call a redirected `malloc`. */\n  UNLOCK();\n  npcs = backtrace((void **)tmp_info, NFRAMES + 1);\n  LOCK();\n#      else\n  npcs = backtrace((void **)tmp_info, NFRAMES + 1);\n#      endif\n  /*\n   * We retrieve `NFRAMES + 1` `pc` values, but discard the first one,\n   * since it points to our own frame.\n   */\n  i = 0;\n  if (npcs > 1) {\n    i = npcs - 1;\n    BCOPY(&tmp_info[1], info, (unsigned)i * sizeof(void *));\n  }\n  BZERO(&info[i], sizeof(void *) * (unsigned)(NFRAMES - i));\n#      ifdef REDIRECT_MALLOC\n  GC_in_save_callers = FALSE;\n#      endif\n}\n\n#    elif defined(I386) || defined(SPARC)\n\n#      if defined(ANY_BSD) && defined(SPARC)\n#        define FR_SAVFP fr_fp\n#        define FR_SAVPC fr_pc\n#      else\n#        define FR_SAVFP fr_savfp\n#        define FR_SAVPC fr_savpc\n#      endif\n\n#      if defined(SPARC) && (defined(__arch64__) || defined(__sparcv9))\n#        define BIAS 2047\n#      else\n#        define BIAS 0\n#      endif\n\nGC_INNER void\nGC_save_callers(struct callinfo info[NFRAMES])\n{\n  struct frame *frame;\n  struct frame *fp;\n  int nframes = 0;\n#      ifdef I386\n  /* We assume this is turned on only with gcc as the compiler. */\n  asm(\"movl %%ebp,%0\" : \"=r\"(frame));\n  fp = frame;\n#      else /* SPARC */\n  frame = (struct frame *)GC_save_regs_in_stack();\n  fp = (struct frame *)((ptr_t)frame->FR_SAVFP + BIAS);\n#      endif\n\n  for (; !HOTTER_THAN((ptr_t)fp, (ptr_t)frame)\n#      ifndef THREADS\n         && !HOTTER_THAN(GC_stackbottom, (ptr_t)fp)\n#      elif defined(STACK_GROWS_UP)\n         && fp != NULL\n#      endif\n         && nframes < NFRAMES;\n       fp = (struct frame *)((ptr_t)fp->FR_SAVFP + BIAS), nframes++) {\n#      if NARGS > 0\n    int i;\n#      endif\n\n    info[nframes].ci_pc = (GC_return_addr_t)fp->FR_SAVPC;\n#      if NARGS > 0\n    for (i = 0; i < NARGS; i++) {\n      info[nframes].ci_arg[i] = GC_HIDE_NZ_POINTER(MAKE_CPTR(fp->fr_arg[i]));\n    }\n#      endif\n  }\n  if (nframes < NFRAMES)\n    info[nframes].ci_pc = 0;\n}\n\n#    endif /* !GC_HAVE_BUILTIN_BACKTRACE */\n\n#  endif /* SAVE_CALL_CHAIN */\n\nGC_INNER void\nGC_print_callers(struct callinfo info[NFRAMES])\n{\n  int i, reent_cnt;\n#  if defined(AO_HAVE_fetch_and_add1) && defined(AO_HAVE_fetch_and_sub1)\n  static volatile AO_t reentry_count = 0;\n\n  /*\n   * Note: alternatively, if available, we may use a thread-local storage,\n   * thus, enabling concurrent usage of `GC_print_callers()`;\n   * but practically this has little sense because printing is done into\n   * a single output stream.\n   */\n  GC_ASSERT(I_DONT_HOLD_LOCK());\n  reent_cnt = (int)(GC_signed_word)AO_fetch_and_add1(&reentry_count);\n#  else\n  static int reentry_count = 0;\n\n  /* Note: this could use a different lock. */\n  LOCK();\n  reent_cnt = reentry_count++;\n  UNLOCK();\n#  endif\n#  if NFRAMES == 1\n  GC_err_printf(\"\\tCaller at allocation:\\n\");\n#  else\n  GC_err_printf(\"\\tCall chain at allocation:\\n\");\n#  endif\n  for (i = 0; i < NFRAMES; i++) {\n#  if defined(LINUX) && !defined(SMALL_CONFIG)\n    GC_bool stop = FALSE;\n#  endif\n\n    if (0 == info[i].ci_pc)\n      break;\n#  if NARGS > 0\n    {\n      int j;\n\n      GC_err_printf(\"\\t\\targs: \");\n      for (j = 0; j < NARGS; j++) {\n        void *p = GC_REVEAL_NZ_POINTER(info[i].ci_arg[j]);\n\n        if (j != 0)\n          GC_err_printf(\", \");\n        GC_err_printf(\"%ld (%p)\", (long)(GC_signed_word)ADDR(p), p);\n      }\n      GC_err_printf(\"\\n\");\n    }\n#  endif\n    if (reent_cnt > 0) {\n      /*\n       * We were called either concurrently or during an allocation\n       * by `backtrace_symbols()` called from `GC_print_callers`; punt.\n       */\n      GC_err_printf(\"\\t\\t##PC##= 0x%lx\\n\", (unsigned long)ADDR(info[i].ci_pc));\n      continue;\n    }\n\n    {\n      char buf[40];\n      char *name;\n#  if defined(GC_HAVE_BUILTIN_BACKTRACE) \\\n      && !defined(GC_BACKTRACE_SYMBOLS_BROKEN) && defined(FUNCPTR_IS_DATAPTR)\n      char **sym_name = backtrace_symbols((void **)&info[i].ci_pc, 1);\n      if (sym_name != NULL) {\n        name = sym_name[0];\n      } else\n#  endif\n      /* else */ {\n        (void)snprintf(buf, sizeof(buf), \"##PC##= 0x%lx\",\n                       (unsigned long)ADDR(info[i].ci_pc));\n        buf[sizeof(buf) - 1] = '\\0';\n        name = buf;\n      }\n#  if defined(LINUX) && !defined(SMALL_CONFIG)\n      /* Try for a line number. */\n      do {\n        FILE *pipe;\n#    define EXE_SZ 100\n        static char exe_name[EXE_SZ];\n#    define CMD_SZ 200\n        char cmd_buf[CMD_SZ];\n#    define RESULT_SZ 200\n        static char result_buf[RESULT_SZ];\n        size_t result_len;\n        const char *old_preload;\n#    define PRELOAD_SZ 200\n        char preload_buf[PRELOAD_SZ];\n        static GC_bool found_exe_name = FALSE;\n        static GC_bool will_fail = FALSE;\n\n        /*\n         * Try to get it via a hairy and expensive scheme.\n         * First we get the name of the executable.\n         */\n        if (will_fail)\n          break;\n        if (!found_exe_name) {\n          int ret_code = readlink(\"/proc/self/exe\", exe_name, EXE_SZ);\n\n          if (ret_code < 0 || ret_code >= EXE_SZ || exe_name[0] != '/') {\n            /* Do not try again. */\n            will_fail = TRUE;\n            break;\n          }\n          exe_name[ret_code] = '\\0';\n          found_exe_name = TRUE;\n        }\n        /*\n         * Then we use `popen()` to start `addr2line -e <exe> <addr>`.\n         * There are faster ways to do this, but hopefully this is\n         * not time critical.\n         */\n        (void)snprintf(cmd_buf, sizeof(cmd_buf),\n                       \"/usr/bin/addr2line -f -e %s 0x%lx\", exe_name,\n                       (unsigned long)ADDR(info[i].ci_pc));\n        cmd_buf[sizeof(cmd_buf) - 1] = '\\0';\n        old_preload = GETENV(\"LD_PRELOAD\");\n        if (old_preload != NULL) {\n          size_t old_len = strlen(old_preload);\n          if (old_len >= PRELOAD_SZ) {\n            will_fail = TRUE;\n            break;\n          }\n          BCOPY(old_preload, preload_buf, old_len + 1);\n          unsetenv(\"LD_PRELOAD\");\n        }\n        pipe = popen(cmd_buf, \"r\");\n        if (old_preload != NULL\n            && setenv(\"LD_PRELOAD\", preload_buf, 0 /* `overwrite` */) == -1) {\n          WARN(\"Failed to reset LD_PRELOAD\\n\", 0);\n        }\n        if (NULL == pipe) {\n          will_fail = TRUE;\n          break;\n        }\n        result_len = fread(result_buf, 1, RESULT_SZ - 1, pipe);\n        (void)pclose(pipe);\n        if (0 == result_len) {\n          will_fail = TRUE;\n          break;\n        }\n        if (result_buf[result_len - 1] == '\\n')\n          --result_len;\n        result_buf[result_len] = 0;\n        if (result_buf[0] == '?'\n            || (result_buf[result_len - 2] == ':'\n                && result_buf[result_len - 1] == '0'))\n          break;\n        /* Get rid of embedded newline, if any.  Test for \"main\". */\n        {\n          char *nl = strchr(result_buf, '\\n');\n          if (nl != NULL && ADDR_LT(nl, result_buf + result_len)) {\n            *nl = ':';\n          }\n          if (strncmp(result_buf, \"main\",\n                      nl != NULL\n                          ? (size_t)(ADDR(nl) /*< CPPCHECK */\n                                     - COVERT_DATAFLOW(ADDR(result_buf)))\n                          : result_len)\n              == 0) {\n            stop = TRUE;\n          }\n        }\n        if (result_len < RESULT_SZ - 25) {\n          /* Add address in the hex format. */\n          (void)snprintf(&result_buf[result_len],\n                         sizeof(result_buf) - result_len, \" [0x%lx]\",\n                         (unsigned long)ADDR(info[i].ci_pc));\n          result_buf[sizeof(result_buf) - 1] = '\\0';\n        }\n#    if defined(CPPCHECK)\n        GC_noop1((unsigned char)name[0]);\n        /* The value of name computed previously is discarded. */\n#    endif\n        name = result_buf;\n      } while (0);\n#  endif /* LINUX */\n      GC_err_printf(\"\\t\\t%s\\n\", name);\n#  if defined(GC_HAVE_BUILTIN_BACKTRACE) \\\n      && !defined(GC_BACKTRACE_SYMBOLS_BROKEN) && defined(FUNCPTR_IS_DATAPTR)\n      if (sym_name != NULL) {\n        /* May call `GC_free()`, `GC_debug_free()`; that is OK. */\n        free(sym_name);\n      }\n#  endif\n    }\n#  if defined(LINUX) && !defined(SMALL_CONFIG)\n    if (stop)\n      break;\n#  endif\n  }\n#  if defined(AO_HAVE_fetch_and_add1) && defined(AO_HAVE_fetch_and_sub1)\n  (void)AO_fetch_and_sub1(&reentry_count);\n#  else\n  LOCK();\n  --reentry_count;\n  UNLOCK();\n#  endif\n}\n\n#endif /* NEED_CALLINFO */\n\n#if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)\n/*\n * Dump `/proc/self/maps` file to `GC_stderr`, to enable looking up names\n * for addresses in `FIND_LEAK` output.\n */\nvoid\nGC_print_address_map(void)\n{\n  const char *maps_ptr;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  maps_ptr = GC_get_maps();\n  GC_err_printf(\"---------- Begin address map ----------\\n\");\n  GC_err_puts(maps_ptr);\n  GC_err_printf(\"---------- End address map ----------\\n\");\n}\n#endif /* LINUX && ELF */\n\n/*\n * Copyright (c) 2000-2005 by Hewlett-Packard Company.  All rights reserved.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#if defined(THREAD_LOCAL_ALLOC)\n\n#  if !defined(THREADS) && !defined(CPPCHECK)\n#    error Invalid config - THREAD_LOCAL_ALLOC requires GC_THREADS\n#  endif\n\n/*\n * Copyright (c) 2000-2005 by Hewlett-Packard Company.  All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * Included indirectly from a thread-library-specific file.\n * This is the interface for thread-local allocation, whose implementation\n * is mostly thread-library-independent.  Here we describe only the interface\n * that needs to be known and invoked from the thread support layer;\n * the actual implementation also exports `GC_malloc` and friends, which are\n * declared in `gc.h` file.\n */\n\n#ifndef GC_THREAD_LOCAL_ALLOC_H\n#define GC_THREAD_LOCAL_ALLOC_H\n\n\n#ifdef THREAD_LOCAL_ALLOC\n\n#  if defined(USE_HPUX_TLS)\n#    error USE_HPUX_TLS macro was replaced by USE_COMPILER_TLS\n#  endif\n\n#  include <stdlib.h>\n\nEXTERN_C_BEGIN\n\n#  if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_WIN32_SPECIFIC)    \\\n      && !defined(USE_WIN32_COMPILER_TLS) && !defined(USE_COMPILER_TLS) \\\n      && !defined(USE_CUSTOM_SPECIFIC)\n#    if defined(GC_WIN32_THREADS)\n#      if defined(CYGWIN32) && GC_GNUC_PREREQ(4, 0)\n#        if defined(__clang__)\n/* As of Cygwin clang-3.5.2, thread-local storage is unsupported. */\n#          define USE_PTHREAD_SPECIFIC\n#        else\n#          define USE_COMPILER_TLS\n#        endif\n#      elif defined(__GNUC__) || defined(MSWINCE)\n#        define USE_WIN32_SPECIFIC\n#      else\n#        define USE_WIN32_COMPILER_TLS\n#      endif /* !GNU */\n\n#    elif defined(HOST_ANDROID)\n#      if defined(ARM32) \\\n          && (GC_GNUC_PREREQ(4, 6) || GC_CLANG_PREREQ_FULL(3, 8, 256229))\n#        define USE_COMPILER_TLS\n#      elif !defined(__clang__) && !defined(ARM32)\n/* TODO: Support clang/arm64. */\n#        define USE_COMPILER_TLS\n#      else\n#        define USE_PTHREAD_SPECIFIC\n#      endif\n\n#    elif defined(LINUX) && GC_GNUC_PREREQ(3, 3) /* `&& !HOST_ANDROID` */\n#      if defined(ARM32) || defined(AVR32)\n/* TODO: Change to USE_COMPILER_TLS on Linux/arm. */\n#        define USE_PTHREAD_SPECIFIC\n#      elif defined(AARCH64) && defined(__clang__) && !GC_CLANG_PREREQ(8, 0)\n/* To avoid \"R_AARCH64_ABS64 used with TLS symbol\" linker warnings. */\n#        define USE_PTHREAD_SPECIFIC\n#      else\n#        define USE_COMPILER_TLS\n#      endif\n\n#    elif (defined(COSMO) || defined(FREEBSD)                                 \\\n           || (defined(NETBSD) && __NetBSD_Version__ >= 600000000 /* 6.0 */)) \\\n        && (GC_GNUC_PREREQ(4, 4) || GC_CLANG_PREREQ(3, 9))\n#      define USE_COMPILER_TLS\n\n#    elif defined(HPUX)\n#      ifdef __GNUC__\n/* Empirically, as of gcc-3.3, USE_COMPILER_TLS does not work. */\n#        define USE_PTHREAD_SPECIFIC\n#      else\n#        define USE_COMPILER_TLS\n#      endif\n\n#    elif defined(IRIX5) || defined(OPENBSD) || defined(SOLARIS) \\\n        || defined(NINTENDO_SWITCH) || defined(NN_PLATFORM_CTR)\n/* Use our own. */\n#      define USE_CUSTOM_SPECIFIC\n\n#    else\n#      define USE_PTHREAD_SPECIFIC\n#    endif\n#  endif /* !USE_x_SPECIFIC */\n\n#  ifndef THREAD_FREELISTS_KINDS\n#    ifdef ENABLE_DISCLAIM\n#      define THREAD_FREELISTS_KINDS (NORMAL + 2)\n#    else\n#      define THREAD_FREELISTS_KINDS (NORMAL + 1)\n#    endif\n#  endif /* !THREAD_FREELISTS_KINDS */\n\n/*\n * The first `GC_TINY_FREELISTS` free lists correspond to the first\n * `GC_TINY_FREELISTS` multiples of `GC_GRANULE_BYTES`, i.e. we keep\n * separate free lists for each multiple of `GC_GRANULE_BYTES` up to\n * `(GC_TINY_FREELISTS-1) * GC_GRANULE_BYTES`.  After that they may be\n * spread out further.\n */\n\n/*\n * This should be used for the `tlfs` field in the structure pointed to\n * by a `GC_thread` entity.  Free lists contain either a pointer or\n * a small count reflecting the number of granules allocated at that size:\n *   - zero means thread-local allocation in use, free list is empty;\n *   - greater than zero but not greater than `DIRECT_GRANULES` means\n *     using global allocation, too few objects of this size have been\n *     allocated by this thread;\n *   - greater than `DIRECT_GRANULES` but less than `HBLKSIZE` means\n *     transition to local allocation, equivalent to zero;\n *   - not less than `HBLKSIZE` means pointer to nonempty free list.\n */\n\nstruct thread_local_freelists {\n  /* Note: preserve `*_freelists` names for some clients. */\n  void *_freelists[THREAD_FREELISTS_KINDS][GC_TINY_FREELISTS];\n#  define ptrfree_freelists _freelists[PTRFREE]\n#  define normal_freelists _freelists[NORMAL]\n#  ifdef GC_GCJ_SUPPORT\n  void *gcj_freelists[GC_TINY_FREELISTS];\n  /* A value used for `gcj_freelists[-1]`; allocation is erroneous. */\n#    define ERROR_FL GC_WORD_MAX\n#  endif\n\n  /* Do not use local free lists for up to this much allocation. */\n#  define DIRECT_GRANULES (HBLKSIZE / GC_GRANULE_BYTES)\n};\ntypedef struct thread_local_freelists *GC_tlfs;\n\n#  if defined(USE_PTHREAD_SPECIFIC)\n#    define GC_getspecific pthread_getspecific\n#    define GC_setspecific pthread_setspecific\n#    define GC_key_create pthread_key_create\n/*\n * Explicitly delete the value to stop the TLS (thread-local storage)\n * destructor from being called repeatedly.\n */\n#    define GC_remove_specific(key) (void)pthread_setspecific(key, NULL)\n#    define GC_remove_specific_after_fork(key, t) \\\n      (void)0 /*< no action needed */\ntypedef pthread_key_t GC_key_t;\n#  elif defined(USE_COMPILER_TLS) || defined(USE_WIN32_COMPILER_TLS)\n#    define GC_getspecific(x) (x)\n#    define GC_setspecific(key, v) ((key) = (v), 0)\n#    define GC_key_create(key, d) 0\n/* Just to clear the pointer to `tlfs`. */\n#    define GC_remove_specific(key) (void)GC_setspecific(key, NULL)\n#    define GC_remove_specific_after_fork(key, t) (void)0\ntypedef void *GC_key_t;\n#  elif defined(USE_WIN32_SPECIFIC)\n#    define GC_getspecific TlsGetValue\n/* Note: we assume that zero means success, Win32 API does the opposite. */\n#    define GC_setspecific(key, v) !TlsSetValue(key, v)\n#    ifndef TLS_OUT_OF_INDEXES\n/* This is currently missing in WinCE. */\n#      define TLS_OUT_OF_INDEXES (DWORD)0xFFFFFFFF\n#    endif\n#    define GC_key_create(key, d) \\\n      ((d) != 0 || (*(key) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? -1 : 0)\n/* TODO: Is `TlsFree` needed on process exit/detach? */\n#    define GC_remove_specific(key) (void)GC_setspecific(key, NULL)\n#    define GC_remove_specific_after_fork(key, t) (void)0\ntypedef DWORD GC_key_t;\n#  elif defined(USE_CUSTOM_SPECIFIC)\nEXTERN_C_END\n/*\n * Copyright (c) 2000 by Hewlett-Packard Company.  All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * This is a reimplementation of a subset of the\n * `pthread_getspecific`/`pthread_setspecific` interface.  This appears\n * to outperform the standard LinuxThreads one by a significant margin.\n * The major restriction is that each thread may only make a single\n * `pthread_setspecific()` call on a single key.  (The current data\n * structure does not really require that.  This restriction should be\n * easily removable.)  We do not currently support the destruction\n * functions, though that could be done.  We also currently assume that\n * only one `pthread_setspecific()` call can be executed at a time,\n * though that assumption would be easy to remove by adding a lock.\n */\n\n#ifndef GC_SPECIFIC_H\n#define GC_SPECIFIC_H\n\n#if !defined(GC_THREAD_LOCAL_ALLOC_H)\n#  error specific.h should be included from thread_local_alloc.h\n#endif\n\n#include <errno.h>\n\nEXTERN_C_BEGIN\n\n/*\n * Called during key creation or by `GC_setspecific()`.  For the GC we\n * already hold the allocator lock.  Currently allocated objects leak\n * on thread exit.  It is hard to avoid, but OK if we allocate garbage\n * collected memory.\n */\n#define MALLOC_CLEAR(n) GC_INTERNAL_MALLOC(n, NORMAL)\n\n#define TS_CACHE_SIZE 1024\n#define TS_CACHE_HASH(n) ((((n) >> 8) ^ (n)) & (TS_CACHE_SIZE - 1))\n\n#define TS_HASH_SIZE 1024\n#define TS_HASH(p) ((unsigned)((ADDR(p) >> 8) ^ ADDR(p)) & (TS_HASH_SIZE - 1))\n\n#ifdef GC_ASSERTIONS\n/*\n * Thread-local storage is not guaranteed to be scanned by the collector.\n * We hide values stored in \"specific\" entries for a test purpose.\n */\ntypedef GC_hidden_pointer ts_entry_value_t;\n#  define TS_HIDE_VALUE(p) GC_HIDE_NZ_POINTER(p)\n#  define TS_REVEAL_PTR(p) GC_REVEAL_NZ_POINTER(p)\n#else\ntypedef void *ts_entry_value_t;\n#  define TS_HIDE_VALUE(p) (p)\n#  define TS_REVEAL_PTR(p) (p)\n#endif\n\n/*\n * An entry describing a thread-specific value for a given thread.\n * All such accessible structures preserve the invariant that if\n * either thread is a valid `pthreads` id or `qtid` is a valid\n * \"quick thread identifier\" for a thread, then value holds the\n * corresponding thread specific value.  This invariant must be\n * preserved at all times, since asynchronous reads are allowed.\n */\ntypedef struct thread_specific_entry {\n  volatile AO_t qtid; /*< a \"quick thread identifier\", only for cache */\n  ts_entry_value_t value;\n  struct thread_specific_entry *next;\n  pthread_t thread;\n} tse;\n\n/*\n * We represent each thread-specific datum as two tables.  The first is\n * a cache, indexed by a \"quick thread identifier\".  The latter one is\n * an easy-to-compute value, which is guaranteed to determine the thread,\n * though a thread may correspond to more than one value.  We typically\n * use the address of a page in the stack.  The second is a hash table,\n * indexed by `pthread_self()`.  It is used only as a backup.\n */\n\n/*\n * Return the \"quick thread identifier\".  The default variant.\n * Assumes the page size, or at least thread stack separation, is at\n * least 4 KB.  Must be defined so that it never returns 0.  (Page zero\n * cannot really be part of any stack, since that would make 0 a valid\n * stack pointer.)\n */\n#define ts_quick_thread_id() ((size_t)(ADDR(GC_approx_sp()) >> 12))\n\n#define INVALID_QTID ((size_t)0)\n#define INVALID_THREADID ((pthread_t)0)\n\ntypedef struct thread_specific_data {\n  tse *volatile cache[TS_CACHE_SIZE]; /*< a faster index to the hash table */\n  tse *hash[TS_HASH_SIZE];\n  pthread_mutex_t lock;\n} tsd;\n\ntypedef tsd *GC_key_t;\n\n#define GC_key_create(key, d) GC_key_create_inner(key)\nGC_INNER int GC_key_create_inner(tsd **key_ptr);\n\n/*\n * Set the thread-local value associated with `key`.\n * Should not be used to overwrite a previously set value.\n */\nGC_INNER int GC_setspecific(tsd *key, void *value);\n\n/* This function is called on thread exit. */\n#define GC_remove_specific(key) \\\n  GC_remove_specific_after_fork(key, pthread_self())\n\n/*\n * Remove thread-specific data for a given thread.  This function is called\n * at `fork` from the child process for all threads except for the survived\n * one.\n */\nGC_INNER void GC_remove_specific_after_fork(tsd *key, pthread_t t);\n\n#ifdef CAN_HANDLE_FORK\n/*\n * Update thread-specific data for the survived thread of the child process.\n * Should be called once after removing thread-specific data for other\n * threads.\n */\nGC_INNER void GC_update_specific_after_fork(tsd *key);\n#endif\n\n/*\n * An internal variant of `GC_getspecific` that assumes a cache miss.\n * Note that even the slow path does not lock.\n */\nGC_INNER void *GC_slow_getspecific(tsd *key, size_t qtid,\n                                   tse *volatile *entry_ptr);\n\nGC_INLINE void *\nGC_getspecific(tsd *key)\n{\n  size_t qtid = ts_quick_thread_id();\n  tse *volatile *entry_ptr = &key->cache[TS_CACHE_HASH(qtid)];\n  const tse *entry = *entry_ptr; /*< must be loaded only once */\n\n  GC_ASSERT(qtid != INVALID_QTID);\n  if (LIKELY(entry->qtid == qtid)) {\n    GC_ASSERT(entry->thread == pthread_self());\n    return TS_REVEAL_PTR(entry->value);\n  }\n\n  return GC_slow_getspecific(key, qtid, entry_ptr);\n}\n\nEXTERN_C_END\n\n#endif /* GC_SPECIFIC_H */\n\nEXTERN_C_BEGIN\n#  else\n#    error implement me\n#  endif\n\n/*\n * Each thread structure must be initialized.  This call must be made from\n * the new thread.  Caller should hold the allocator lock.\n */\nGC_INNER void GC_init_thread_local(GC_tlfs p);\n\n/*\n * Called when a thread is unregistered, or exits.  Caller should hold\n * the allocator lock.\n */\nGC_INNER void GC_destroy_thread_local(GC_tlfs p);\n\n/*\n * The thread support layer must arrange to mark thread-local free lists\n * explicitly, since the link field is often invisible to the marker.\n * It knows how to find all threads; we take care of an individual thread\n * free-list structure.\n */\nGC_INNER void GC_mark_thread_local_fls_for(GC_tlfs p);\n\n#  ifdef GC_ASSERTIONS\nGC_bool GC_is_thread_tsd_valid(void *tsd);\nvoid GC_check_tls_for(GC_tlfs p);\n#    if defined(USE_CUSTOM_SPECIFIC)\nvoid GC_check_tsd_marks(tsd *key);\n#    endif\n#  endif /* GC_ASSERTIONS */\n\n#  ifndef GC_ATTR_TLS_FAST\n#    define GC_ATTR_TLS_FAST /*< empty */\n#  endif\n\n/*\n * This is set up by `GC_init_thread_local()`.  No need for cleanup\n * on thread exit.  But the thread support layer makes sure that\n * `GC_thread_key` is traced, if necessary.\n */\nextern\n#  if defined(USE_COMPILER_TLS)\n    __thread GC_ATTR_TLS_FAST\n#  elif defined(USE_WIN32_COMPILER_TLS)\n    __declspec(thread) GC_ATTR_TLS_FAST\n#  endif\n        GC_key_t GC_thread_key;\n\nEXTERN_C_END\n\n#endif /* THREAD_LOCAL_ALLOC */\n\n#endif /* GC_THREAD_LOCAL_ALLOC_H */\n\n\n#  if defined(USE_COMPILER_TLS)\n__thread GC_ATTR_TLS_FAST\n#  elif defined(USE_WIN32_COMPILER_TLS)\n__declspec(thread) GC_ATTR_TLS_FAST\n#  endif\n    GC_key_t GC_thread_key;\n\nstatic GC_bool keys_initialized;\n\n#  ifndef GC_NO_DEINIT\nGC_INNER void\nGC_reset_thread_local_initialization(void)\n{\n  keys_initialized = FALSE;\n  /* TODO: Dispose resources associated with `GC_thread_key`. */\n}\n#  endif\n\n/*\n * Return a single nonempty free list `fl` to the global one pointed to\n * by `gfl`.\n */\nstatic void\nreturn_single_freelist(void *fl, void **gfl)\n{\n  if (NULL == *gfl) {\n    *gfl = fl;\n  } else {\n    void *q = fl;\n    void **qptr;\n\n    GC_ASSERT(GC_size(fl) == GC_size(*gfl));\n    /* Concatenate. */\n    do {\n      qptr = &obj_link(q);\n      q = *qptr;\n    } while (ADDR(q) >= HBLKSIZE);\n    GC_ASSERT(NULL == q);\n    *qptr = *gfl;\n    *gfl = fl;\n  }\n}\n\n/*\n * Recover the contents of the free-list array `fl` into the global one\n * `gfl`.\n */\nstatic void\nreturn_freelists(void **fl, void **gfl)\n{\n  int i;\n\n  for (i = 1; i < GC_TINY_FREELISTS; ++i) {\n    if (ADDR(fl[i]) >= HBLKSIZE) {\n      return_single_freelist(fl[i], &gfl[i]);\n    }\n    /*\n     * Clear `fl[i]`, since the thread structure may hang around.\n     * Do it in a way that is likely to trap if we access it.\n     */\n    fl[i] = (ptr_t)NUMERIC_TO_VPTR(HBLKSIZE);\n  }\n  /* The 0 granule free list really contains 1 granule objects. */\n  if (ADDR(fl[0]) >= HBLKSIZE\n#  ifdef GC_GCJ_SUPPORT\n      && ADDR(fl[0]) != ERROR_FL\n#  endif\n  ) {\n    return_single_freelist(fl[0], &gfl[1]);\n  }\n}\n\n#  ifdef USE_PTHREAD_SPECIFIC\n/*\n * Re-set the TLS value on thread cleanup to allow thread-local allocations\n * to happen in the TLS destructors.  `GC_unregister_my_thread()` (and\n * similar routines) will finally set the `GC_thread_key` to `NULL`\n * preventing this destructor from being called repeatedly.\n */\nstatic void\nreset_thread_key(void *v)\n{\n  pthread_setspecific(GC_thread_key, v);\n}\n#  else\n#    define reset_thread_key 0\n#  endif\n\nGC_INNER void\nGC_init_thread_local(GC_tlfs p)\n{\n  int kind, j, res;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (UNLIKELY(!keys_initialized)) {\n#  ifdef USE_CUSTOM_SPECIFIC\n    /* Ensure proper alignment of a \"pushed\" GC symbol. */\n    GC_ASSERT(ADDR(&GC_thread_key) % ALIGNMENT == 0);\n#  endif\n    res = GC_key_create(&GC_thread_key, reset_thread_key);\n    if (COVERT_DATAFLOW(res) != 0) {\n      ABORT(\"Failed to create key for local allocator\");\n    }\n    keys_initialized = TRUE;\n  }\n  res = GC_setspecific(GC_thread_key, p);\n  if (COVERT_DATAFLOW(res) != 0) {\n    ABORT(\"Failed to set thread specific allocation pointers\");\n  }\n  for (j = 0; j < GC_TINY_FREELISTS; ++j) {\n    for (kind = 0; kind < THREAD_FREELISTS_KINDS; ++kind) {\n      p->_freelists[kind][j] = NUMERIC_TO_VPTR(1);\n    }\n#  ifdef GC_GCJ_SUPPORT\n    p->gcj_freelists[j] = NUMERIC_TO_VPTR(1);\n#  endif\n  }\n  /*\n   * The zero-sized free list is handled like the regular free list, to\n   * ensure that the explicit deallocation works.  However, an allocation\n   * of a `gcj` object with the zero size is always an error.\n   */\n#  ifdef GC_GCJ_SUPPORT\n  p->gcj_freelists[0] = MAKE_CPTR(ERROR_FL);\n#  endif\n}\n\nGC_INNER void\nGC_destroy_thread_local(GC_tlfs p)\n{\n  int kind;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_getspecific(GC_thread_key) == p);\n  /* We currently only do this from the thread itself. */\n  GC_STATIC_ASSERT(THREAD_FREELISTS_KINDS <= MAXOBJKINDS);\n  for (kind = 0; kind < THREAD_FREELISTS_KINDS; ++kind) {\n    if (kind == (int)GC_n_kinds) {\n      /* The kind is not created. */\n      break;\n    }\n    return_freelists(p->_freelists[kind], GC_obj_kinds[kind].ok_freelist);\n  }\n#  ifdef GC_GCJ_SUPPORT\n  return_freelists(p->gcj_freelists, (void **)GC_gcjobjfreelist);\n#  endif\n}\n\nSTATIC void *\nGC_get_tlfs(void)\n{\n#  if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_WIN32_SPECIFIC)\n  GC_key_t k = GC_thread_key;\n\n  if (UNLIKELY(0 == k)) {\n    /*\n     * We have not yet run `GC_init_parallel()`.  That means we also\n     * are not locking, so `GC_malloc_kind_global()` is fairly cheap.\n     */\n    return NULL;\n  }\n  return GC_getspecific(k);\n#  else\n  if (UNLIKELY(!keys_initialized))\n    return NULL;\n\n  return GC_getspecific(GC_thread_key);\n#  endif\n}\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_malloc_kind(size_t lb, int kind)\n{\n  size_t lg;\n  void *tsd;\n  void *result;\n\n#  if MAXOBJKINDS > THREAD_FREELISTS_KINDS\n  if (UNLIKELY(kind >= THREAD_FREELISTS_KINDS))\n    return GC_malloc_kind_global(lb, kind);\n#  endif\n  tsd = GC_get_tlfs();\n  if (UNLIKELY(NULL == tsd))\n    return GC_malloc_kind_global(lb, kind);\n\n  GC_ASSERT(GC_is_initialized);\n  GC_ASSERT(GC_is_thread_tsd_valid(tsd));\n  lg = ALLOC_REQUEST_GRANS(lb);\n#  if defined(CPPCHECK)\n#    define MALLOC_KIND_PTRFREE_INIT (void *)1\n#  else\n#    define MALLOC_KIND_PTRFREE_INIT NULL\n#  endif\n  GC_FAST_MALLOC_GRANS(result, lg, ((GC_tlfs)tsd)->_freelists[kind],\n                       DIRECT_GRANULES, kind, GC_malloc_kind_global(lb, kind),\n                       (void)(kind == PTRFREE ? MALLOC_KIND_PTRFREE_INIT\n                                              : (obj_link(result) = 0)));\n#  ifdef LOG_ALLOCS\n  GC_log_printf(\"GC_malloc_kind(%lu, %d) returned %p, recent GC #%lu\\n\",\n                (unsigned long)lb, kind, result, (unsigned long)GC_gc_no);\n#  endif\n  return result;\n}\n\n#  ifdef GC_GCJ_SUPPORT\n\n\n\n\nGC_API GC_ATTR_MALLOC void *GC_CALL\nGC_gcj_malloc(size_t lb, const void *vtable_ptr)\n{\n  void *result;\n  void **tiny_fl;\n  size_t lg;\n\n  /*\n   * Unlike the other thread-local allocation calls, we assume that the\n   * collector has been explicitly initialized.\n   */\n  GC_ASSERT(GC_gcjobjfreelist != NULL);\n#    if defined(USE_PTHREAD_SPECIFIC) || defined(USE_WIN32_SPECIFIC)\n  GC_ASSERT(keys_initialized);\n#    else\n  GC_ASSERT(GC_thread_key != 0);\n#    endif\n\n  /*\n   * `gcj`-style allocation without locks is extremely tricky.\n   * The fundamental issue is that we may end up marking a free list,\n   * which has free-list links instead of \"vtable\" pointers.\n   * That is usually OK, since the next object on the free list will be\n   * cleared, and will thus be interpreted as containing a zero descriptor.\n   * That is fine if the object has not yet been initialized.  But there\n   * are interesting potential races.  In the case of incremental\n   * collection, this seems hopeless, since the marker may run\n   * asynchronously, and may pick up the pointer to the next free-list\n   * entry (which it thinks is a \"vtable\" pointer), get suspended for\n   * a while, and then see an allocated object instead of the \"vtable\".\n   * This may be avoidable with either a handshake with the collector or,\n   * probably more easily, by moving the free list links to the second\n   * \"pointer-sized\" word of each object.  The latter is not a universal\n   * win, since on architecture like Itanium, nonzero offsets are not\n   * necessarily free.  And there may be cache fill order issues.\n   * For now, we punt with the incremental collection.  This probably means\n   * that the incremental collection should be enabled before we create\n   * a second thread.\n   */\n  if (UNLIKELY(GC_incremental))\n    return GC_core_gcj_malloc(lb, vtable_ptr, 0 /* `flags` */);\n\n  tiny_fl = ((GC_tlfs)GC_getspecific(GC_thread_key))->gcj_freelists;\n  lg = ALLOC_REQUEST_GRANS(lb);\n\n  /*\n   * The provided `default_expr` below forces the initialization of the\n   * \"vtable\" pointer.  This is necessary to ensure some very subtle\n   * properties required if a garbage collection is run in the middle of\n   * such an allocation.  Here we implicitly also assume atomicity for the\n   * free list and method pointer assignments.  We must update the free list\n   * before we store the pointer.  Otherwise a collection at this point\n   * would see a corrupted free list.  A real memory barrier is not needed,\n   * since the action of stopping this thread will cause prior writes\n   * to complete.  We assert that any concurrent marker will stop us.\n   * Thus it is impossible for a mark procedure to see the allocation of the\n   * next object, but to see this object still containing a free-list pointer.\n   * Otherwise the marker, by misinterpreting the free-list link as a \"vtable\"\n   * pointer, might find a random \"mark descriptor\" in the next object.\n   */\n  GC_FAST_MALLOC_GRANS(\n      result, lg, tiny_fl, DIRECT_GRANULES, GC_gcj_kind,\n      GC_core_gcj_malloc(lb, vtable_ptr, 0 /* `flags` */), do {\n        AO_compiler_barrier();\n        *(const void **)result = vtable_ptr;\n      } while (0));\n  return result;\n}\n\n#  endif /* GC_GCJ_SUPPORT */\n\nGC_INNER void\nGC_mark_thread_local_fls_for(GC_tlfs p)\n{\n  ptr_t q;\n  int kind, j;\n\n  for (j = 0; j < GC_TINY_FREELISTS; ++j) {\n    for (kind = 0; kind < THREAD_FREELISTS_KINDS; ++kind) {\n      /*\n       * Load the pointer atomically as it might be updated concurrently\n       * by `GC_FAST_MALLOC_GRANS()`.\n       */\n      q = GC_cptr_load((volatile ptr_t *)&p->_freelists[kind][j]);\n      if (ADDR(q) > HBLKSIZE)\n        GC_set_fl_marks(q);\n    }\n#  ifdef GC_GCJ_SUPPORT\n    if (LIKELY(j > 0)) {\n      q = GC_cptr_load((volatile ptr_t *)&p->gcj_freelists[j]);\n      if (ADDR(q) > HBLKSIZE)\n        GC_set_fl_marks(q);\n    }\n#  endif\n  }\n}\n\n#  if defined(GC_ASSERTIONS)\n/* Check that all thread-local free-lists in `p` are completely marked. */\nvoid\nGC_check_tls_for(GC_tlfs p)\n{\n  int kind, j;\n\n  for (j = 1; j < GC_TINY_FREELISTS; ++j) {\n    for (kind = 0; kind < THREAD_FREELISTS_KINDS; ++kind) {\n      GC_check_fl_marks(&p->_freelists[kind][j]);\n    }\n#    ifdef GC_GCJ_SUPPORT\n    GC_check_fl_marks(&p->gcj_freelists[j]);\n#    endif\n  }\n}\n#  endif\n\n#endif /* THREAD_LOCAL_ALLOC */\n\n\n/* Most platform-specific files go here... */\n/*\n * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.\n * Copyright (c) 2000-2010 by Hewlett-Packard Development Company.\n * All rights reserved.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.\n * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.\n * All rights reserved.\n * Copyright (c) 2009-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/* Private declarations for thread support. */\n\n#ifndef GC_PTHREAD_SUPPORT_H\n#define GC_PTHREAD_SUPPORT_H\n\n\n#ifdef THREADS\n\n#  if defined(GC_PTHREADS) || defined(GC_PTHREADS_PARAMARK)\n#    include <pthread.h>\n#  endif\n\n#  ifdef DARWIN\n#    include <mach/mach.h>\n#    include <mach/thread_act.h>\n#  endif\n\n#  ifdef THREAD_LOCAL_ALLOC\n#  endif\n\n#  ifdef THREAD_SANITIZER\n#  endif\n\nEXTERN_C_BEGIN\n\n#  ifdef WOW64_THREAD_CONTEXT_WORKAROUND\n#    if defined(__WATCOMC__) && defined(GC_WIN32_THREADS)\n/*\n * Open Watcom (as of v2 2024-11-02 Build) does not define `NT_TIB`\n * in the platform `winnt.h` file.\n */\nstruct GC_NT_TIB_s {\n  /* `EXCEPTION_REGISTRATION_RECORD *` */ void *ExceptionList; /*< unused */\n  PVOID StackBase;\n  PVOID StackLimit;\n  /* The remaining fields are unused. */\n};\ntypedef struct GC_NT_TIB_s GC_NT_TIB;\n#    else\n#      define GC_NT_TIB NT_TIB\n#    endif\n#  endif\n\nstruct GC_StackContext_Rep {\n#  if defined(THREAD_SANITIZER) && defined(SIGNAL_BASED_STOP_WORLD)\n  /*\n   * A dummy field to avoid TSan false positive about the race\n   * between `GC_has_other_debug_info` and `GC_suspend_handler_inner`\n   * (the latter one sets `stack_ptr`).\n   */\n  char dummy[sizeof(oh)];\n#  endif\n\n  /*\n   * Cold end of the stack (except for main thread on non-Windows).\n   * On Windows: 0 means entry invalid; not `in_use` implies `stack_end`\n   * is zero.\n   */\n#  if !defined(GC_NO_THREADS_DISCOVERY) && defined(GC_WIN32_THREADS)\n  volatile\n#  endif\n      ptr_t stack_end;\n\n  /* Valid only in some platform-specific states. */\n  ptr_t stack_ptr;\n\n#  ifdef GC_WIN32_THREADS\n#    define ADDR_LIMIT ((ptr_t)GC_WORD_MAX)\n  /*\n   * Last known minimum (hottest) address in stack or `ADDR_LIMIT`\n   * if unset.\n   */\n  ptr_t last_stack_min;\n#    ifdef I386\n  /*\n   * The cold end of the stack saved by `GC_record_stack_base` (never\n   * modified by `GC_set_stackbottom()`); used for the old way of the\n   * coroutines support.\n   */\n  ptr_t initial_stack_base;\n#    endif\n#  elif defined(DARWIN) && !defined(DARWIN_DONT_PARSE_STACK)\n  /*\n   * Result of `GC_FindTopOfStack(0)`; valid only if the thread is blocked;\n   * non-`NULL` value means already set.\n   */\n  ptr_t topOfStack;\n#  endif\n\n#  if defined(E2K) || defined(IA64)\n  ptr_t backing_store_end;\n  ptr_t backing_store_ptr;\n#  endif\n\n#  ifdef GC_WIN32_THREADS\n  /* For now, alt-stack is not implemented for Win32. */\n#  else\n  /* The start of the alt-stack if there is one, `NULL` otherwise. */\n  ptr_t altstack;\n\n  /* Same for the \"normal\" stack (set by `GC_register_altstack`). */\n  ptr_t normstack;\n\n  /* The size of the alt-stack if exists. */\n  size_t altstack_size;\n\n  size_t normstack_size;\n#  endif\n\n#  ifdef E2K\n  /* The current offset in the procedure stack. */\n  size_t ps_ofs;\n#  endif\n\n#  ifndef GC_NO_FINALIZATION\n  unsigned char finalizer_nested;\n\n  /*\n   * Used by `GC_check_finalizer_nested()` to minimize the level of recursion\n   * when a client finalizer allocates memory.  Initially it is zero and\n   * `finalizer_nested` is zero.\n   */\n  unsigned short finalizer_skipped;\n#  endif\n\n  /*\n   * Points to the \"frame\" data held in stack by the innermost\n   * `GC_call_with_gc_active()` of this stack (thread); may be `NULL`.\n   */\n  struct GC_traced_stack_sect_s *traced_stack_sect;\n};\ntypedef struct GC_StackContext_Rep *GC_stack_context_t;\n\n#  ifdef GC_WIN32_THREADS\ntypedef DWORD thread_id_t;\n#    define thread_id_self() GetCurrentThreadId()\n#    define THREAD_ID_EQUAL(id1, id2) ((id1) == (id2))\n/*\n * Convert a platform-specific thread `id` (of `thread_id_t` type) to some\n * pointer identifying the thread.  This is used mostly for a debugging\n * purpose when printing thread id.\n */\n#    define THREAD_ID_TO_VPTR(id) CAST_THRU_UINTPTR(void *, id)\n#  else\ntypedef pthread_t thread_id_t;\n#    define thread_id_self() pthread_self()\n#    define THREAD_ID_EQUAL(id1, id2) THREAD_EQUAL(id1, id2)\n#    define THREAD_ID_TO_VPTR(id) PTHREAD_TO_VPTR(id)\n#  endif\n\nstruct GC_Thread_Rep {\n  union {\n#  if !defined(GC_NO_THREADS_DISCOVERY) && defined(GC_WIN32_THREADS)\n    /*\n     * Updated without a lock.  We assert that each unused entry has\n     * invalid `id` of zero and zero `stack_end`.\n     * Used only if `GC_win32_dll_threads`.\n     */\n    volatile AO_t in_use;\n\n    /*\n     * The same but of the type that matches the first argument of\n     * `InterlockedExchange()`; `volatile` is omitted because the\n     * ancient version of the function prototype lacked the qualifier.\n     */\n    LONG long_in_use;\n#  endif\n\n    /*\n     * Hash table link without `GC_win32_dll_threads`.  More recently\n     * allocated threads with a given `pthreads` id come first.\n     * (All but the first are guaranteed to be dead, but we may not yet\n     * have registered the join.)\n     */\n    struct GC_Thread_Rep *next;\n  } tm; /*< table_management */\n\n  GC_stack_context_t crtn;\n\n  thread_id_t id; /*< hash table key */\n#  ifdef DARWIN\n  mach_port_t mach_thread;\n#  elif defined(GC_WIN32_THREADS) && defined(GC_PTHREADS)\n  pthread_t pthread_id;\n#  elif defined(USE_TKILL_ON_ANDROID)\n  pid_t kernel_id;\n#  endif\n\n#  ifdef MSWINCE\n  /*\n   * According to MSDN docs for WinCE targets:\n   *   - `DuplicateHandle()` is not applicable to thread handles;\n   *   - the value returned by `GetCurrentThreadId()` could be used as\n   *     a \"real\" thread handle (for `SuspendThread()`, `ResumeThread()`\n   *     and `GetThreadContext()`).\n   */\n#    define THREAD_HANDLE(p) ((HANDLE)(word)(p)->id)\n#  elif defined(GC_WIN32_THREADS)\n  HANDLE handle;\n#    define THREAD_HANDLE(p) ((p)->handle)\n#  endif /* GC_WIN32_THREADS && !MSWINCE */\n\n  /* Note: this is protected by the allocator lock. */\n  unsigned char flags;\n\n  /* Thread has exited (`pthreads` only). */\n#  define FINISHED 0x1\n#  ifndef GC_PTHREADS\n#    define KNOWN_FINISHED(p) FALSE\n#  else\n#    define KNOWN_FINISHED(p) (((p)->flags & FINISHED) != 0)\n  /*\n   * Thread is treated as detached.  Thread may really be detached,\n   * or it may have been explicitly registered, in which case we can\n   * deallocate its `GC_Thread_Rep` entity once it unregisters itself,\n   * since it may not return a pointer to the collector heap.\n   */\n#    define DETACHED 0x2\n#  endif\n#  if (defined(GC_HAVE_PTHREAD_EXIT) || !defined(GC_NO_PTHREAD_CANCEL)) \\\n      && defined(GC_PTHREADS)\n  /* Collections are disabled while the thread is exiting. */\n#    define DISABLED_GC 0x10\n#  endif\n  /*\n   * Thread is in the do-blocking state.  If the flag is set, the thread\n   * has stored its stack pointer value and will acquire the allocator lock\n   * before any pointer manipulation.  Thus, it does not need a signal sent\n   * to stop it.\n   */\n#  define DO_BLOCKING 0x20\n#  ifdef GC_WIN32_THREADS\n  /* Thread is suspended by `SuspendThread()`. */\n#    define IS_SUSPENDED 0x40\n#  endif\n\n#  ifdef SIGNAL_BASED_STOP_WORLD\n  /*\n   * The value of `GC_stop_count` when the thread last successfully\n   * handled a suspend signal.\n   */\n  volatile AO_t last_stop_count;\n#    ifdef GC_ENABLE_SUSPEND_THREAD\n  /*\n   * Note: an odd value means thread was suspended externally;\n   * incremented on every call of `GC_suspend_thread()` and\n   * `GC_resume_thread()`; updated with the allocator lock held, but\n   * could be read from a signal handler.\n   */\n  volatile AO_t ext_suspend_cnt;\n#    endif\n#  endif\n\n#  ifdef GC_PTHREADS\n  /*\n   * The value returned from the thread.  Used only to avoid premature\n   * reclamation of any data it might reference.  This is unfortunately\n   * also the reason we need to intercept join and detach.\n   */\n  void *status;\n#  endif\n\n#  ifdef THREAD_LOCAL_ALLOC\n  struct thread_local_freelists tlfs GC_ATTR_PTRT_ALIGNED;\n#  endif\n\n#  ifdef NACL\n  /*\n   * Grab `NACL_GC_REG_STORAGE_SIZE` pointers off the stack when going\n   * into a `syscall()`.  20 is more than we need, but it is\n   * an overestimate in case the instrumented function uses any\n   * callee-saved registers, they may be pushed to the stack much\n   * earlier.  Also, on x86_64 `push` puts 8 bytes on the stack even\n   * though our pointers have 4 bytes in length.\n   */\n#    ifdef ARM32\n  /* Space for `r4` ... `r8`, `r10`, ... `r12`, `r14`. */\n#      define NACL_GC_REG_STORAGE_SIZE 9\n#    else\n#      define NACL_GC_REG_STORAGE_SIZE 20\n#    endif\n  ptr_t reg_storage[NACL_GC_REG_STORAGE_SIZE];\n#  elif defined(PLATFORM_HAVE_GC_REG_STORAGE_SIZE)\n  word registers[PLATFORM_GC_REG_STORAGE_SIZE]; /*< used externally */\n#  endif\n\n#  if defined(WOW64_THREAD_CONTEXT_WORKAROUND) && defined(MSWINRT_FLAVOR)\n  GC_NT_TIB *tib;\n#  endif\n\n#  ifdef RETRY_GET_THREAD_CONTEXT /* `&& GC_WIN32_THREADS` */\n  ptr_t context_sp;\n\n  /*\n   * Populated as part of `GC_suspend()` as resume/suspend loop may be\n   * needed for `GetThreadContext()` to succeed.\n   */\n  word context_regs[PUSHED_REGS_COUNT];\n#  endif\n};\ntypedef struct GC_Thread_Rep *GC_thread;\n\n#  if defined(GC_PTHREADS) || defined(GC_PTHREADS_PARAMARK)\n/* Convert an opaque `pthread_t` value to a pointer identifying the thread. */\n#    if defined(GC_WIN32_THREADS) && !defined(CYGWIN32)                  \\\n        && (defined(GC_WIN32_PTHREADS) || defined(GC_PTHREADS_PARAMARK)) \\\n        && !defined(__WINPTHREADS_VERSION_MAJOR)\n/*\n * Using documented internal details of pthreads-win32 library.\n * `pthread_t` is a structure.\n */\n#      define PTHREAD_TO_VPTR(id) ((void *)(id).p)\n#    else\n#      define PTHREAD_TO_VPTR(id) CAST_THRU_UINTPTR(void *, id)\n#    endif\n#  endif\n\n#  ifndef THREAD_TABLE_SZ\n/* Note: this is a power of 2 (for speed). */\n#    define THREAD_TABLE_SZ 256\n#  endif\n\n#  ifdef GC_WIN32_THREADS\n#    define THREAD_TABLE_INDEX(id) /*< `id` is of `DWORD` type */ \\\n      (int)((((id) >> 8) ^ (id)) % THREAD_TABLE_SZ)\n#  elif CPP_WORDSZ > 32\n#    define THREAD_TABLE_INDEX(id)                                          \\\n      (int)(((((NUMERIC_THREAD_ID(id) >> 8) ^ NUMERIC_THREAD_ID(id)) >> 16) \\\n             ^ ((NUMERIC_THREAD_ID(id) >> 8) ^ NUMERIC_THREAD_ID(id)))      \\\n            % THREAD_TABLE_SZ)\n#  else\n#    define THREAD_TABLE_INDEX(id)                                        \\\n      (int)(((NUMERIC_THREAD_ID(id) >> 16) ^ (NUMERIC_THREAD_ID(id) >> 8) \\\n             ^ NUMERIC_THREAD_ID(id))                                     \\\n            % THREAD_TABLE_SZ)\n#  endif\n\n/*\n * The set (hash table) of all known threads.  We intercept thread\n * creation and join/detach.  Protected by the allocator lock.\n * Not used if `GC_win32_dll_threads`.\n */\nGC_EXTERN GC_thread GC_threads[THREAD_TABLE_SZ];\n\n#  ifndef MAX_MARKERS\n#    define MAX_MARKERS 16\n#  endif\n\n#  ifdef STACKPTR_CORRECTOR_AVAILABLE\nGC_EXTERN GC_sp_corrector_proc GC_sp_corrector;\n#  endif\n\nGC_EXTERN GC_on_thread_event_proc GC_on_thread_event;\n\n#  ifdef GC_WIN32_THREADS\n\n#    ifdef GC_NO_THREADS_DISCOVERY\n#      define GC_win32_dll_threads FALSE\n#    elif defined(GC_DISCOVER_TASK_THREADS)\n#      define GC_win32_dll_threads TRUE\n#    else\n/*\n * `GC_win32_dll_threads` must be set (if needed) at the application\n * initialization time, i.e. before any collector or thread calls.\n * We make it a \"dynamic\" option only to avoid multiple library versions.\n */\nGC_EXTERN GC_bool GC_win32_dll_threads;\n#    endif\n\n#    ifdef PARALLEL_MARK\nGC_EXTERN int GC_available_markers_m1;\n\n/*\n * The desired amount of marker threads (including the initiating one).\n * Note: the default value (0) means the number of markers should be\n * selected automatically.\n */\nGC_EXTERN unsigned GC_required_markers_cnt;\n\n/* The cold end of the stack for markers. */\nGC_EXTERN ptr_t GC_marker_sp[MAX_MARKERS - 1];\n\n/*\n * Last known minimum (hottest) address in stack (or `ADDR_LIMIT` if\n * unset) for markers.\n */\nGC_EXTERN ptr_t GC_marker_last_stack_min[MAX_MARKERS - 1];\n\n#      ifndef GC_PTHREADS_PARAMARK\n/*\n * A table mapping the helper thread id to the mark helper index\n * (linear search is used since the mapping contains only a few entries).\n */\nGC_EXTERN thread_id_t GC_marker_Id[MAX_MARKERS - 1];\n#      endif\n\n#      if !defined(HAVE_PTHREAD_SETNAME_NP_WITH_TID) && !defined(MSWINCE)\nGC_INNER void GC_init_win32_thread_naming(HMODULE hK32);\n#      endif\n#      ifdef GC_PTHREADS_PARAMARK\nGC_INNER void *GC_mark_thread(void *);\n#      elif defined(MSWINCE)\nGC_INNER DWORD WINAPI GC_mark_thread(LPVOID);\n#      else\nGC_INNER unsigned __stdcall GC_mark_thread(void *);\n#      endif\n#    endif /* PARALLEL_MARK */\n\n/*\n * Add a thread to `GC_threads`.  We assume it was not already there.\n * Note: the `id` field should be set by the caller.\n */\nGC_INNER GC_thread GC_new_thread(thread_id_t);\n\nGC_INNER void GC_record_stack_base(GC_stack_context_t crtn,\n                                   const struct GC_stack_base *sb);\n\n/*\n * This may be called from `DllMain`, and hence operates under unusual\n * constraints.  In particular, it must be lock-free if\n * `GC_win32_dll_threads`.  Always called from the thread being added.\n * If not `GC_win32_dll_threads`, then we already hold the allocator\n * lock except possibly during single-threaded startup code.\n * Does not initialize thread-local free lists.\n */\nGC_INNER GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb,\n                                               thread_id_t self_id);\n\n#    ifdef GC_PTHREADS\nGC_INNER void GC_win32_cache_self_pthread(thread_id_t);\n#    else\n/*\n * Delete a thread from `GC_threads`.  We assume it is there.\n * (The code intentionally traps if it was not.)  It is also safe to delete\n * the main thread.  If `GC_win32_dll_threads`, it should be called only\n * from the thread being deleted (except for `DLL_PROCESS_DETACH` case).\n * If a thread has been joined, but we have not yet been notified, then\n * there may be more than one thread in the table with the same thread\n * id - this is OK because we delete a specific one.\n */\nGC_INNER void GC_delete_thread(GC_thread);\n#    endif\n\n#    ifdef CAN_HANDLE_FORK\n/* Prepare for a process fork if requested. */\nGC_INNER void GC_setup_atfork(void);\n#    endif\n\n#    if !defined(DONT_USE_ATEXIT) || !defined(GC_NO_THREADS_DISCOVERY)\nGC_EXTERN thread_id_t GC_main_thread_id;\n#    endif\n\n#    ifndef GC_NO_THREADS_DISCOVERY\n/*\n * Search in `dll_thread_table` and return the `GC_thread[]` entity\n * corresponding to the given thread `id`.\n * May be called without a lock, but should be called in contexts in\n * those the requested thread cannot be asynchronously deleted, e.g.\n * from the thread itself.\n */\nGC_INNER GC_thread GC_win32_dll_lookup_thread(thread_id_t id);\n#    endif\n\n#    ifdef MPROTECT_VDB\n/*\n * Make sure given thread descriptor is not protected by the VDB\n * implementation.  Used to prevent write faults when the world is\n * (partially) stopped, since it may have been stopped with a system\n * lock held, and that lock may be required for fault handling.\n */\nGC_INNER void GC_win32_unprotect_thread(GC_thread);\n#    else\n#      define GC_win32_unprotect_thread(t) (void)(t)\n#    endif /* !MPROTECT_VDB */\n\n#  else\n#    define GC_win32_dll_threads FALSE\n#  endif /* !GC_WIN32_THREADS */\n\n#  ifdef GC_PTHREADS\n#    ifdef GC_WIN32_THREADS\n/*\n * Return a `GC_thread` corresponding to a given `pthread_t`, or\n * `NULL` if it is not there.  We assume that this is only called for\n * `pthreads` ids that have not yet terminated or are still joinable,\n * and cannot be terminated concurrently.\n */\nGC_INNER GC_thread GC_lookup_by_pthread(pthread_t);\n#    else\n#      define GC_lookup_by_pthread(t) GC_lookup_thread(t)\n#    endif\n#  endif /* GC_PTHREADS */\n\n/*\n * Return a `GC_thread` corresponding to a given thread `id`, or\n * `NULL` if it is not there.  Caller holds the allocator lock in the\n * reader mode, at least, or otherwise inhibits updates.  If there is more\n * than one thread with the given `id`, we return the most recent one.\n */\nGC_INNER GC_thread GC_lookup_thread(thread_id_t id);\n\n#  define GC_self_thread_inner() GC_lookup_thread(thread_id_self())\n\n/*\n * Wait until an in-progress collection has finished.\n * We hold the allocator lock and repeatedly release it in order to wait.\n * If `wait_for_all`, then we exit with the allocator lock held and\n * no collection is in progress; otherwise we just wait for the current\n * collection to finish.\n */\nGC_INNER void GC_wait_for_gc_completion(GC_bool wait_for_all);\n\n#  ifdef NACL\nGC_INNER void GC_nacl_initialize_gc_thread(GC_thread);\nGC_INNER void GC_nacl_shutdown_gc_thread(void);\n#  endif\n\n#  if defined(PTHREAD_STOP_WORLD_IMPL)            \\\n          && !defined(NO_SIGNALS_UNBLOCK_IN_MAIN) \\\n      || defined(GC_EXPLICIT_SIGNALS_UNBLOCK)\n/*\n * Some targets (e.g., Solaris) might require this to be called when\n * doing thread registering from the thread destructor.\n */\nGC_INNER void GC_unblock_gc_signals(void);\n#  endif\n\n#  if defined(GC_ENABLE_SUSPEND_THREAD) && defined(SIGNAL_BASED_STOP_WORLD)\nGC_INNER void GC_suspend_self_inner(GC_thread me, size_t suspend_cnt);\n\n/*\n * A wrapper over `GC_suspend_self_inner()`.  Similar to\n * `GC_do_blocking_inner()` but assuming the allocator lock is held and\n * `fn` is `GC_suspend_self_inner`.\n */\nGC_INNER void GC_suspend_self_blocked(ptr_t thread_me, void *context);\n#  endif\n\n#  if defined(GC_PTHREADS) && !defined(PLATFORM_THREADS) \\\n      && !defined(SN_TARGET_PSP2)\n\n#    ifdef GC_PTHREAD_START_STANDALONE\n#      define GC_INNER_PTHRSTART /*< empty */\n#    else\n#      define GC_INNER_PTHRSTART GC_INNER\n#    endif\n\nGC_INNER_PTHRSTART void *GC_CALLBACK\nGC_pthread_start_inner(struct GC_stack_base *sb, void *arg);\n\n/*\n * Called from `GC_pthread_start_inner()`.  Defined in `pthread_support.c`\n * file to minimize the number of files included from `pthread_start.c` file\n * (because `sem_t` and `sem_post()` are not used in that file directly).\n */\nGC_INNER_PTHRSTART GC_thread\nGC_start_rtn_prepare_thread(void *(**pstart)(void *), void **pstart_arg,\n                            struct GC_stack_base *sb, void *arg);\n\n/*\n * Called at thread exit.  Never called for main thread.  That is OK,\n * since it results in at most a tiny one-time leak.  And LinuxThreads\n * implementation does not reclaim the primordial (main) thread resources\n * or id anyway.\n */\nGC_INNER_PTHRSTART void GC_thread_exit_proc(void *);\n#  endif /* GC_PTHREADS */\n\n#  ifdef DARWIN\n#    ifndef DARWIN_DONT_PARSE_STACK\nGC_INNER ptr_t GC_FindTopOfStack(unsigned long);\n#    endif\n#    if defined(PARALLEL_MARK) && !defined(GC_NO_THREADS_DISCOVERY)\n/* Note: this is used only by `GC_suspend_thread_list()`. */\nGC_INNER GC_bool GC_is_mach_marker(thread_act_t);\n#    endif\n#  endif /* DARWIN */\n\n#  ifdef PTHREAD_STOP_WORLD_IMPL\nGC_INNER void GC_stop_init(void);\n#  endif\n\nEXTERN_C_END\n\n#endif /* THREADS */\n\n#endif /* GC_PTHREAD_SUPPORT_H */\n\n\n/* This probably needs more porting work to ppc64. */\n\n#if defined(DARWIN) && defined(THREADS)\n\n#  include <mach/machine.h>\n#  include <sys/sysctl.h>\n\n#  if defined(ARM32) && defined(ARM_THREAD_STATE32)\n#    include <CoreFoundation/CoreFoundation.h>\n#  endif\n\n/*\n * From \"Inside Mac OS X - Mach-O Runtime Architecture\" published by Apple:\n *   - Page 49: The space beneath the stack pointer, where a new stack frame\n *     would normally be allocated, is called the red zone.  This area as\n *     shown in Figure 3-2 may be used for any purpose as long as a new stack\n *     frame does not need to be added to the stack.\n *   - Page 50: If a leaf procedure's red zone usage would exceed 224 bytes,\n *     then it must set up a stack frame just like routines that call other\n *     routines.\n */\n#  ifdef POWERPC\n#    if CPP_WORDSZ == 32\n#      define PPC_RED_ZONE_SIZE 224\n#    elif CPP_WORDSZ == 64\n#      define PPC_RED_ZONE_SIZE 320\n#    endif\n#  endif\n\n#  ifndef DARWIN_DONT_PARSE_STACK\n\ntypedef struct StackFrame {\n  unsigned long savedSP;\n  unsigned long savedCR;\n  unsigned long savedLR;\n  /* `unsigned long reserved[2];` */\n  /* `unsigned long savedRTOC;` */\n} StackFrame;\n\nGC_INNER ptr_t\nGC_FindTopOfStack(unsigned long stack_start)\n{\n  StackFrame *frame = (StackFrame *)MAKE_CPTR(stack_start);\n\n  if (NULL == frame) {\n#    ifdef POWERPC\n#      if CPP_WORDSZ == 32\n    __asm__ __volatile__(\"lwz %0,0(r1)\" : \"=r\"(frame));\n#      else\n    __asm__ __volatile__(\"ld %0,0(r1)\" : \"=r\"(frame));\n#      endif\n#    elif defined(ARM32)\n    volatile ptr_t sp_reg;\n\n    __asm__ __volatile__(\"mov %0, r7\\n\" : \"=r\"(sp_reg));\n    frame = (/* no volatile */ StackFrame *)sp_reg;\n#    elif defined(AARCH64)\n    volatile ptr_t sp_reg;\n\n    __asm__ __volatile__(\"mov %0, x29\\n\" : \"=r\"(sp_reg));\n    frame = (/* no volatile */ StackFrame *)sp_reg;\n#    else\n#      if defined(CPPCHECK)\n    GC_noop1_ptr(&frame);\n#      endif\n    ABORT(\"GC_FindTopOfStack(0) is not implemented\");\n#    endif\n  }\n\n#    ifdef DEBUG_THREADS_EXTRA\n  GC_log_printf(\"FindTopOfStack start at sp= %p\\n\", (void *)frame);\n#    endif\n  while (frame->savedSP != 0) { /*< stop if no more stack frames */\n    unsigned long maskedLR;\n\n#    ifdef CPPCHECK\n    GC_noop1(frame->savedCR);\n#    endif\n    frame = (StackFrame *)MAKE_CPTR(frame->savedSP);\n\n    /*\n     * We do these next two checks after going to the next frame because\n     * the `savedLR` for the first stack frame in the loop is not set up\n     * on purpose, so we should not check it.\n     */\n    maskedLR = frame->savedLR & ~0x3UL;\n    if (0 == maskedLR || ~0x3UL == maskedLR) {\n      /* The next `savedLR` is bogus, stop. */\n      break;\n    }\n  }\n#    ifdef DEBUG_THREADS_EXTRA\n  GC_log_printf(\"FindTopOfStack finish at sp= %p\\n\", (void *)frame);\n#    endif\n  return (ptr_t)frame;\n}\n\n#  endif /* !DARWIN_DONT_PARSE_STACK */\n\n/*\n * `GC_query_task_threads` controls whether to obtain the list of the\n * threads from the kernel or to use `GC_threads` table.\n */\n#  ifdef GC_NO_THREADS_DISCOVERY\n#    define GC_query_task_threads FALSE\n#  elif defined(GC_DISCOVER_TASK_THREADS)\n#    define GC_query_task_threads TRUE\n#  else\nSTATIC GC_bool GC_query_task_threads = FALSE;\n#  endif /* !GC_NO_THREADS_DISCOVERY */\n\nGC_API void GC_CALL\nGC_use_threads_discovery(void)\n{\n#  ifdef GC_NO_THREADS_DISCOVERY\n  ABORT(\"Darwin task-threads-based stop and push unsupported\");\n#  else\n#    ifndef GC_ALWAYS_MULTITHREADED\n  GC_ASSERT(!GC_need_to_lock);\n#    endif\n#    ifndef GC_DISCOVER_TASK_THREADS\n  GC_query_task_threads = TRUE;\n#    endif\n  GC_init();\n#  endif\n}\n\n#  ifndef kCFCoreFoundationVersionNumber_iOS_8_0\n#    define kCFCoreFoundationVersionNumber_iOS_8_0 1140.1\n#  endif\n\n#  define THREAD_ACT_TO_VPTR(t) THREAD_ID_TO_VPTR(t)\n#  define MACH_PORT_TO_VPTR(t) THREAD_ID_TO_VPTR(t)\n\n/*\n * Evaluates the stack range for a given thread.  Returns the lower bound\n * and sets `*phi` to the upper one.  Sets `*pfound_me` to `TRUE` if this\n * is the current thread, otherwise the value is not changed.\n */\nSTATIC ptr_t\nGC_stack_range_for(ptr_t *phi, thread_act_t thread, GC_thread p,\n                   mach_port_t my_thread, ptr_t *paltstack_lo,\n                   ptr_t *paltstack_hi, GC_bool *pfound_me)\n{\n#  ifdef DARWIN_DONT_PARSE_STACK\n  GC_stack_context_t crtn;\n#  endif\n  ptr_t lo;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (thread == my_thread) {\n    GC_ASSERT(NULL == p || (p->flags & DO_BLOCKING) == 0);\n    lo = GC_approx_sp();\n#  ifndef DARWIN_DONT_PARSE_STACK\n    *phi = GC_FindTopOfStack(0);\n#  endif\n    *pfound_me = TRUE;\n  } else if (p != NULL && (p->flags & DO_BLOCKING) != 0) {\n    lo = p->crtn->stack_ptr;\n#  ifndef DARWIN_DONT_PARSE_STACK\n    *phi = p->crtn->topOfStack;\n#  endif\n\n  } else {\n    /*\n     * `MACHINE_THREAD_STATE_COUNT` does not seem to be defined everywhere.\n     * Hence we use our own variant.  Alternatively, we could use\n     * `THREAD_STATE_MAX` (but seems to be not optimal).\n     */\n    kern_return_t kern_result;\n    GC_THREAD_STATE_T state;\n\n#  if defined(ARM32) && defined(ARM_THREAD_STATE32)\n    /*\n     * Use `ARM_UNIFIED_THREAD_STATE` on iOS8+ 32-bit targets and on\n     * 64-bit H/W (iOS7+ 32-bit mode).\n     */\n    size_t size;\n    static cpu_type_t cputype = 0;\n\n    if (cputype == 0) {\n      sysctlbyname(\"hw.cputype\", &cputype, &size, NULL, 0);\n    }\n    if (cputype == CPU_TYPE_ARM64\n        || kCFCoreFoundationVersionNumber\n               >= kCFCoreFoundationVersionNumber_iOS_8_0) {\n      arm_unified_thread_state_t unified_state;\n      mach_msg_type_number_t unified_thread_state_count\n          = ARM_UNIFIED_THREAD_STATE_COUNT;\n#    if defined(CPPCHECK)\n#      define GC_ARM_UNIFIED_THREAD_STATE 1\n#    else\n#      define GC_ARM_UNIFIED_THREAD_STATE ARM_UNIFIED_THREAD_STATE\n#    endif\n      kern_result = thread_get_state(thread, GC_ARM_UNIFIED_THREAD_STATE,\n                                     (natural_t *)&unified_state,\n                                     &unified_thread_state_count);\n#    if !defined(CPPCHECK)\n      if (unified_state.ash.flavor != ARM_THREAD_STATE32) {\n        ABORT(\"unified_state flavor should be ARM_THREAD_STATE32\");\n      }\n#    endif\n      state = unified_state;\n    } else\n#  endif\n    /* else */ {\n      mach_msg_type_number_t thread_state_count = GC_MACH_THREAD_STATE_COUNT;\n\n      /* Get the thread state (registers, etc.). */\n      do {\n        kern_result\n            = thread_get_state(thread, GC_MACH_THREAD_STATE,\n                               (natural_t *)&state, &thread_state_count);\n      } while (kern_result == KERN_ABORTED);\n    }\n#  ifdef DEBUG_THREADS\n    GC_log_printf(\"thread_get_state returns %d\\n\", kern_result);\n#  endif\n    if (kern_result != KERN_SUCCESS)\n      ABORT(\"thread_get_state failed\");\n\n#  if defined(I386)\n    lo = (ptr_t)state.THREAD_FLD(esp);\n#    ifndef DARWIN_DONT_PARSE_STACK\n    *phi = GC_FindTopOfStack(state.THREAD_FLD(esp));\n#    endif\n    GC_push_one(state.THREAD_FLD(eax));\n    GC_push_one(state.THREAD_FLD(ebx));\n    GC_push_one(state.THREAD_FLD(ecx));\n    GC_push_one(state.THREAD_FLD(edx));\n    GC_push_one(state.THREAD_FLD(edi));\n    GC_push_one(state.THREAD_FLD(esi));\n    GC_push_one(state.THREAD_FLD(ebp));\n\n#  elif defined(X86_64)\n    lo = (ptr_t)state.THREAD_FLD(rsp);\n#    ifndef DARWIN_DONT_PARSE_STACK\n    *phi = GC_FindTopOfStack(state.THREAD_FLD(rsp));\n#    endif\n    GC_push_one(state.THREAD_FLD(rax));\n    GC_push_one(state.THREAD_FLD(rbx));\n    GC_push_one(state.THREAD_FLD(rcx));\n    GC_push_one(state.THREAD_FLD(rdx));\n    GC_push_one(state.THREAD_FLD(rdi));\n    GC_push_one(state.THREAD_FLD(rsi));\n    GC_push_one(state.THREAD_FLD(rbp));\n    /* `rsp` is skipped. */\n    GC_push_one(state.THREAD_FLD(r8));\n    GC_push_one(state.THREAD_FLD(r9));\n    GC_push_one(state.THREAD_FLD(r10));\n    GC_push_one(state.THREAD_FLD(r11));\n    GC_push_one(state.THREAD_FLD(r12));\n    GC_push_one(state.THREAD_FLD(r13));\n    GC_push_one(state.THREAD_FLD(r14));\n    GC_push_one(state.THREAD_FLD(r15));\n\n#  elif defined(POWERPC)\n    lo = (ptr_t)(state.THREAD_FLD(r1) - PPC_RED_ZONE_SIZE);\n#    ifndef DARWIN_DONT_PARSE_STACK\n    *phi = GC_FindTopOfStack(state.THREAD_FLD(r1));\n#    endif\n    GC_push_one(state.THREAD_FLD(r0));\n    /* `r1` is skipped. */\n    GC_push_one(state.THREAD_FLD(r2));\n    GC_push_one(state.THREAD_FLD(r3));\n    GC_push_one(state.THREAD_FLD(r4));\n    GC_push_one(state.THREAD_FLD(r5));\n    GC_push_one(state.THREAD_FLD(r6));\n    GC_push_one(state.THREAD_FLD(r7));\n    GC_push_one(state.THREAD_FLD(r8));\n    GC_push_one(state.THREAD_FLD(r9));\n    GC_push_one(state.THREAD_FLD(r10));\n    GC_push_one(state.THREAD_FLD(r11));\n    GC_push_one(state.THREAD_FLD(r12));\n    GC_push_one(state.THREAD_FLD(r13));\n    GC_push_one(state.THREAD_FLD(r14));\n    GC_push_one(state.THREAD_FLD(r15));\n    GC_push_one(state.THREAD_FLD(r16));\n    GC_push_one(state.THREAD_FLD(r17));\n    GC_push_one(state.THREAD_FLD(r18));\n    GC_push_one(state.THREAD_FLD(r19));\n    GC_push_one(state.THREAD_FLD(r20));\n    GC_push_one(state.THREAD_FLD(r21));\n    GC_push_one(state.THREAD_FLD(r22));\n    GC_push_one(state.THREAD_FLD(r23));\n    GC_push_one(state.THREAD_FLD(r24));\n    GC_push_one(state.THREAD_FLD(r25));\n    GC_push_one(state.THREAD_FLD(r26));\n    GC_push_one(state.THREAD_FLD(r27));\n    GC_push_one(state.THREAD_FLD(r28));\n    GC_push_one(state.THREAD_FLD(r29));\n    GC_push_one(state.THREAD_FLD(r30));\n    GC_push_one(state.THREAD_FLD(r31));\n\n#  elif defined(ARM32)\n    lo = (ptr_t)state.THREAD_FLD(sp);\n#    ifndef DARWIN_DONT_PARSE_STACK\n    *phi = GC_FindTopOfStack(state.THREAD_FLD(r[7])); /*< `fp` */\n#    endif\n    {\n      int j;\n      for (j = 0; j < 7; j++)\n        GC_push_one(state.THREAD_FLD(r[j]));\n      /* Skip `r7` (because iOS uses it as a frame pointer). */\n      j++;\n      for (; j <= 12; j++)\n        GC_push_one(state.THREAD_FLD(r[j]));\n    }\n    /* `cpsr`, `pc` and `sp` are skipped. */\n    GC_push_one(state.THREAD_FLD(lr));\n\n#  elif defined(AARCH64)\n    lo = (ptr_t)state.THREAD_FLD(sp);\n#    ifndef DARWIN_DONT_PARSE_STACK\n    *phi = GC_FindTopOfStack(state.THREAD_FLD(fp));\n#    endif\n    {\n      int j;\n      for (j = 0; j <= 28; j++) {\n        GC_push_one(state.THREAD_FLD(x[j]));\n      }\n    }\n    /* `cpsr`, `fp`, `pc` and `sp` are skipped. */\n    GC_push_one(state.THREAD_FLD(lr));\n\n#  elif defined(CPPCHECK)\n    lo = NULL;\n#  else\n#    error FIXME for non-arm/ppc/x86 architectures\n#  endif\n  }\n\n#  ifndef DARWIN_DONT_PARSE_STACK\n  /* TODO: Determine `p` and handle `altstack` if `!DARWIN_DONT_PARSE_STACK` */\n  UNUSED_ARG(paltstack_hi);\n#  else\n  /*\n   * `p` is guaranteed to be non-`NULL` regardless of\n   * `GC_query_task_threads`.\n   */\n#    ifdef CPPCHECK\n  if (NULL == p)\n    ABORT(\"Bad GC_stack_range_for call\");\n#    endif\n  crtn = p->crtn;\n  *phi = crtn->stack_end;\n  if (crtn->altstack != NULL && ADDR_GE(lo, crtn->altstack)\n      && ADDR_GE(crtn->altstack + crtn->altstack_size, lo)) {\n    *paltstack_lo = lo;\n    *paltstack_hi = crtn->altstack + crtn->altstack_size;\n    lo = crtn->normstack;\n    *phi = lo + crtn->normstack_size;\n  } else\n#  endif\n  /* else */ {\n    *paltstack_lo = NULL;\n  }\n#  if defined(STACKPTR_CORRECTOR_AVAILABLE) && defined(DARWIN_DONT_PARSE_STACK)\n  if (GC_sp_corrector != 0)\n    GC_sp_corrector((void **)&lo, THREAD_ID_TO_VPTR(p->id));\n#  endif\n#  ifdef DEBUG_THREADS\n  GC_log_printf(\"Darwin: Stack for thread %p is [%p,%p)\\n\",\n                THREAD_ACT_TO_VPTR(thread), (void *)lo, (void *)*phi);\n#  endif\n  return lo;\n}\n\nGC_INNER void\nGC_push_all_stacks(void)\n{\n  ptr_t hi, altstack_lo, altstack_hi;\n  task_t my_task = current_task();\n  mach_port_t my_thread = mach_thread_self();\n  GC_bool found_me = FALSE;\n  int nthreads = 0;\n  word total_size = 0;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_thr_initialized);\n\n#  ifndef DARWIN_DONT_PARSE_STACK\n  if (GC_query_task_threads) {\n    int i;\n    kern_return_t kern_result;\n    thread_act_array_t act_list;\n    mach_msg_type_number_t listcount;\n\n    /* Obtain the list of the threads from the kernel. */\n    kern_result = task_threads(my_task, &act_list, &listcount);\n    if (kern_result != KERN_SUCCESS)\n      ABORT(\"task_threads failed\");\n\n    for (i = 0; i < (int)listcount; i++) {\n      thread_act_t thread = act_list[i];\n      ptr_t lo = GC_stack_range_for(&hi, thread, NULL, my_thread, &altstack_lo,\n                                    &altstack_hi, &found_me);\n\n      if (lo) {\n        GC_ASSERT(ADDR_GE(hi, lo));\n        total_size += hi - lo;\n        GC_push_all_stack(lo, hi);\n      }\n      /* TODO: Handle `altstack`. */\n      nthreads++;\n      mach_port_deallocate(my_task, thread);\n    }\n\n    vm_deallocate(my_task, (vm_address_t)act_list,\n                  sizeof(thread_t) * listcount);\n  } else\n#  endif /* !DARWIN_DONT_PARSE_STACK */\n  /* else */ {\n    int i;\n\n    for (i = 0; i < THREAD_TABLE_SZ; i++) {\n      GC_thread p;\n\n      for (p = GC_threads[i]; p != NULL; p = p->tm.next) {\n        GC_ASSERT(THREAD_TABLE_INDEX(p->id) == i);\n        if (!KNOWN_FINISHED(p)) {\n          thread_act_t thread = (thread_act_t)(p->mach_thread);\n          ptr_t lo = GC_stack_range_for(&hi, thread, p, my_thread,\n                                        &altstack_lo, &altstack_hi, &found_me);\n\n          if (lo) {\n            GC_ASSERT(ADDR_GE(hi, lo));\n            total_size += hi - lo;\n            GC_push_all_stack_sections(lo, hi, p->crtn->traced_stack_sect);\n          }\n          if (altstack_lo) {\n            total_size += altstack_hi - altstack_lo;\n            GC_push_all_stack(altstack_lo, altstack_hi);\n          }\n          nthreads++;\n        }\n      }\n    }\n  }\n\n  mach_port_deallocate(my_task, my_thread);\n  GC_VERBOSE_LOG_PRINTF(\"Pushed %d thread stacks\\n\", nthreads);\n  if (!found_me && !GC_in_thread_creation)\n    ABORT(\"Collecting from unknown thread\");\n  GC_total_stacksize = total_size;\n}\n\n#  ifndef GC_NO_THREADS_DISCOVERY\n\n#    ifdef MPROTECT_VDB\nSTATIC mach_port_t GC_mach_handler_thread = 0;\nSTATIC GC_bool GC_use_mach_handler_thread = FALSE;\n\nGC_INNER void\nGC_darwin_register_self_mach_handler(void)\n{\n  GC_mach_handler_thread = mach_thread_self();\n  GC_use_mach_handler_thread = TRUE;\n}\n#    endif /* MPROTECT_VDB */\n\n#    ifndef GC_MAX_MACH_THREADS\n#      define GC_MAX_MACH_THREADS THREAD_TABLE_SZ\n#    endif\n\nstruct GC_mach_thread {\n  thread_act_t thread;\n  GC_bool suspended;\n};\n\nSTATIC struct GC_mach_thread GC_mach_threads[GC_MAX_MACH_THREADS]\n    = { { 0, FALSE } };\n\nSTATIC int GC_mach_threads_count = 0;\n/* FIXME: It is better to implement `GC_mach_threads` as a hash set. */\n\n/*\n * Return `TRUE` if there is a thread in `act_list` that was not\n * in `old_list`.\n */\nSTATIC GC_bool\nGC_suspend_thread_list(thread_act_array_t act_list, int count,\n                       thread_act_array_t old_list, int old_count,\n                       task_t my_task, mach_port_t my_thread)\n{\n  int i;\n  int j = -1;\n  GC_bool changed = FALSE;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  for (i = 0; i < count; i++) {\n    thread_act_t thread = act_list[i];\n    GC_bool found;\n    kern_return_t kern_result;\n\n    if (thread == my_thread\n#    ifdef MPROTECT_VDB\n        || (GC_mach_handler_thread == thread && GC_use_mach_handler_thread)\n#    endif\n#    ifdef PARALLEL_MARK\n        || GC_is_mach_marker(thread) /*< ignore the parallel markers */\n#    endif\n    ) {\n      /*\n       * Do not add our one, parallel marker and the handler threads;\n       * consider it as found (e.g., it was processed earlier).\n       */\n      mach_port_deallocate(my_task, thread);\n      continue;\n    }\n\n    /* Find the current thread in the old list. */\n    found = FALSE;\n    {\n      /* The previous found thread index. */\n      int last_found = j;\n\n      /* Search for the thread starting from the last found one first. */\n      while (++j < old_count)\n        if (old_list[j] == thread) {\n          found = TRUE;\n          break;\n        }\n      if (!found) {\n        /* If not found, search in the rest (beginning) of the list. */\n        for (j = 0; j < last_found; j++)\n          if (old_list[j] == thread) {\n            found = TRUE;\n            break;\n          }\n      }\n    }\n\n    if (found) {\n      /* It is already in the list, skip processing, release `mach` port. */\n      mach_port_deallocate(my_task, thread);\n      continue;\n    }\n\n    /* Add it to the `GC_mach_threads` list. */\n    if (GC_mach_threads_count == GC_MAX_MACH_THREADS)\n      ABORT(\"Too many threads\");\n    GC_mach_threads[GC_mach_threads_count].thread = thread;\n    /* The default is \"not suspended\". */\n    GC_mach_threads[GC_mach_threads_count].suspended = FALSE;\n    changed = TRUE;\n\n#    ifdef DEBUG_THREADS\n    GC_log_printf(\"Suspending %p\\n\", THREAD_ACT_TO_VPTR(thread));\n#    endif\n    /*\n     * Unconditionally suspend the thread.  It will do no harm if it is\n     * already suspended by the client logic.\n     */\n    GC_acquire_dirty_lock();\n    do {\n      kern_result = thread_suspend(thread);\n    } while (kern_result == KERN_ABORTED);\n    GC_release_dirty_lock();\n    if (kern_result != KERN_SUCCESS) {\n      /*\n       * The thread may have quit since the `thread_threads()` call we\n       * mark as already suspended so it is not dealt with anymore later.\n       */\n      GC_mach_threads[GC_mach_threads_count].suspended = FALSE;\n    } else {\n      /* Mark the thread as suspended and require resume. */\n      GC_mach_threads[GC_mach_threads_count].suspended = TRUE;\n      if (GC_on_thread_event)\n        GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED,\n                           THREAD_ACT_TO_VPTR(thread));\n    }\n    GC_mach_threads_count++;\n  }\n  return changed;\n}\n\n#  endif /* !GC_NO_THREADS_DISCOVERY */\n\nGC_INNER void\nGC_stop_world(void)\n{\n  task_t my_task = current_task();\n  mach_port_t my_thread = mach_thread_self();\n  kern_return_t kern_result;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_thr_initialized);\n#  ifdef DEBUG_THREADS\n  GC_log_printf(\"Stopping the world from thread %p\\n\",\n                MACH_PORT_TO_VPTR(my_thread));\n#  endif\n#  ifdef PARALLEL_MARK\n  if (GC_parallel) {\n    GC_acquire_mark_lock();\n    /* We should have previously waited for it to become zero. */\n    GC_ASSERT(GC_fl_builder_count == 0);\n  }\n#  endif /* PARALLEL_MARK */\n\n  if (GC_query_task_threads) {\n#  ifndef GC_NO_THREADS_DISCOVERY\n    GC_bool changed;\n    thread_act_array_t act_list, prev_list;\n    mach_msg_type_number_t listcount, prevcount;\n\n    /*\n     * Clear out the `mach` threads list table.  We do not need to really\n     * clear `GC_mach_threads[]` as it is used only in the range from 0 to\n     * `GC_mach_threads_count - 1`, inclusive.\n     */\n    GC_mach_threads_count = 0;\n\n    /*\n     * Loop stopping threads until you have gone over the whole list twice\n     * without a new one appearing.  `thread_create()` will not return (and\n     * thus the thread stop) until the new thread exists, so there is\n     * no window whereby you could stop a thread, recognize it is stopped,\n     * but then have a new thread it created before stopping shows up later.\n     */\n    changed = TRUE;\n    prev_list = NULL;\n    prevcount = 0;\n    do {\n      kern_result = task_threads(my_task, &act_list, &listcount);\n\n      if (kern_result == KERN_SUCCESS) {\n        changed = GC_suspend_thread_list(act_list, listcount, prev_list,\n                                         prevcount, my_task, my_thread);\n\n        if (prev_list != NULL) {\n          /*\n           * Thread ports are not deallocated by list, unused ports\n           * deallocated in `GC_suspend_thread_list`, used ones - kept\n           * in `GC_mach_threads` till `GC_start_world` as otherwise thread\n           * object change can occur and `GC_start_world` will not find the\n           * thread to resume which will cause application to hang.\n           */\n          vm_deallocate(my_task, (vm_address_t)prev_list,\n                        sizeof(thread_t) * prevcount);\n        }\n\n        /* Repeat while having changes. */\n        prev_list = act_list;\n        prevcount = listcount;\n      }\n    } while (changed);\n\n    GC_ASSERT(prev_list != 0);\n    /* The thread ports are not deallocated by list, see above. */\n    vm_deallocate(my_task, (vm_address_t)act_list,\n                  sizeof(thread_t) * listcount);\n#  endif /* !GC_NO_THREADS_DISCOVERY */\n\n  } else {\n    unsigned i;\n\n    for (i = 0; i < THREAD_TABLE_SZ; i++) {\n      GC_thread p;\n\n      for (p = GC_threads[i]; p != NULL; p = p->tm.next) {\n        if ((p->flags & (FINISHED | DO_BLOCKING)) == 0\n            && p->mach_thread != my_thread) {\n          GC_acquire_dirty_lock();\n          do {\n            kern_result = thread_suspend(p->mach_thread);\n          } while (kern_result == KERN_ABORTED);\n          GC_release_dirty_lock();\n          if (kern_result != KERN_SUCCESS)\n            ABORT(\"thread_suspend failed\");\n          if (GC_on_thread_event)\n            GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED,\n                               MACH_PORT_TO_VPTR(p->mach_thread));\n        }\n      }\n    }\n  }\n\n#  ifdef MPROTECT_VDB\n  if (GC_auto_incremental) {\n    GC_mprotect_stop();\n  }\n#  endif\n#  ifdef PARALLEL_MARK\n  if (GC_parallel)\n    GC_release_mark_lock();\n#  endif\n\n#  ifdef DEBUG_THREADS\n  GC_log_printf(\"World stopped from %p\\n\", MACH_PORT_TO_VPTR(my_thread));\n#  endif\n  mach_port_deallocate(my_task, my_thread);\n}\n\nGC_INLINE void\nGC_thread_resume(thread_act_t thread)\n{\n  kern_return_t kern_result;\n#  if defined(DEBUG_THREADS) || defined(GC_ASSERTIONS)\n  struct thread_basic_info info;\n  mach_msg_type_number_t outCount = THREAD_BASIC_INFO_COUNT;\n\n#    ifdef CPPCHECK\n  info.run_state = 0;\n#    endif\n  kern_result = thread_info(thread, THREAD_BASIC_INFO, (thread_info_t)&info,\n                            &outCount);\n  if (kern_result != KERN_SUCCESS)\n    ABORT(\"thread_info failed\");\n#  endif\n  GC_ASSERT(I_HOLD_LOCK());\n#  ifdef DEBUG_THREADS\n  GC_log_printf(\"Resuming thread %p with state %d\\n\",\n                THREAD_ACT_TO_VPTR(thread), info.run_state);\n#  endif\n  /* Resume the thread. */\n  kern_result = thread_resume(thread);\n  if (kern_result != KERN_SUCCESS) {\n    WARN(\"thread_resume(%p) failed: mach port invalid\\n\", thread);\n  } else if (GC_on_thread_event) {\n    GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED,\n                       THREAD_ACT_TO_VPTR(thread));\n  }\n}\n\nGC_INNER void\nGC_start_world(void)\n{\n  task_t my_task = current_task();\n\n  /* The allocator lock is held continuously since the world stopped. */\n  GC_ASSERT(I_HOLD_LOCK());\n#  ifdef DEBUG_THREADS\n  GC_log_printf(\"World starting\\n\");\n#  endif\n#  ifdef MPROTECT_VDB\n  if (GC_auto_incremental) {\n    GC_mprotect_resume();\n  }\n#  endif\n\n  if (GC_query_task_threads) {\n#  ifndef GC_NO_THREADS_DISCOVERY\n    int i, j;\n    kern_return_t kern_result;\n    thread_act_array_t act_list;\n    mach_msg_type_number_t listcount;\n\n    kern_result = task_threads(my_task, &act_list, &listcount);\n    if (kern_result != KERN_SUCCESS)\n      ABORT(\"task_threads failed\");\n\n    j = (int)listcount;\n    for (i = 0; i < GC_mach_threads_count; i++) {\n      thread_act_t thread = GC_mach_threads[i].thread;\n\n      if (GC_mach_threads[i].suspended) {\n        /*\n         * The thread index found during the previous iteration\n         * (reaching `listcount` value means no thread found yet).\n         */\n        int last_found = j;\n\n        /* Search for the thread starting from the last found one first. */\n        while (++j < (int)listcount) {\n          if (act_list[j] == thread)\n            break;\n        }\n        if (j >= (int)listcount) {\n          /* If not found, search in the rest (beginning) of the list. */\n          for (j = 0; j < last_found; j++) {\n            if (act_list[j] == thread)\n              break;\n          }\n        }\n        if (j != last_found) {\n          /* The thread is alive, resume it. */\n          GC_thread_resume(thread);\n        }\n      } else {\n        /*\n         * This thread has failed to be suspended by `GC_stop_world`,\n         * no action is needed.\n         */\n#    ifdef DEBUG_THREADS\n        GC_log_printf(\"Not resuming thread %p as it is not suspended\\n\",\n                      THREAD_ACT_TO_VPTR(thread));\n#    endif\n      }\n      mach_port_deallocate(my_task, thread);\n    }\n\n    for (i = 0; i < (int)listcount; i++)\n      mach_port_deallocate(my_task, act_list[i]);\n    vm_deallocate(my_task, (vm_address_t)act_list,\n                  sizeof(thread_t) * listcount);\n#  endif /* !GC_NO_THREADS_DISCOVERY */\n\n  } else {\n    int i;\n    mach_port_t my_thread = mach_thread_self();\n\n    for (i = 0; i < THREAD_TABLE_SZ; i++) {\n      GC_thread p;\n\n      for (p = GC_threads[i]; p != NULL; p = p->tm.next) {\n        if ((p->flags & (FINISHED | DO_BLOCKING)) == 0\n            && p->mach_thread != my_thread)\n          GC_thread_resume(p->mach_thread);\n      }\n    }\n\n    mach_port_deallocate(my_task, my_thread);\n  }\n\n#  ifdef DEBUG_THREADS\n  GC_log_printf(\"World started\\n\");\n#  endif\n}\n\n#endif /* DARWIN && THREADS */\n\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1997 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2009-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n/*\n * This is incredibly OS specific code for tracking down data sections in\n * dynamic libraries.  There appears to be no way of doing this quickly\n * without groveling through undocumented data structures.  We would argue\n * that this is a bug in the design of the `dlopen` interface.  This code\n * may break in future OS releases.  If this matters to you, do not hesitate\n * to let your vendor know...\n *\n * None of this is safe with `dlclose` and incremental collection.\n * But, then not much of anything is safe in the presence of `dlclose`.\n */\n\n/*\n * BTL: avoid circular redefinition of `dlopen` if `SOLARIS` and `THREADS`\n * are both defined.\n */\n#undef GC_MUST_RESTORE_REDEFINED_DLOPEN\n#if defined(GC_PTHREADS) && !defined(GC_NO_DLOPEN) \\\n    && !defined(GC_NO_THREAD_REDIRECTS) && !defined(GC_USE_LD_WRAP)\n/*\n * To support threads in Solaris, `gc.h` file interposes on `dlopen` by\n * defining `dlopen` to be `GC_dlopen`.  `GC_FirstDLOpenedLinkMap()` needs\n * to use the real system `dlopen()`, thus we first undo `dlopen` definition\n * by `gc.h` file and restore it at the end of the current file.\n */\n#  undef dlopen\n#  define GC_MUST_RESTORE_REDEFINED_DLOPEN\n#endif /* !GC_NO_DLOPEN */\n\n#if defined(SOLARISDL) && defined(THREADS) && !defined(SOLARIS) \\\n    && !defined(CPPCHECK)\n#  error Fix mutual exclusion with dlopen\n#endif\n\n/*\n * A user-supplied routine (custom filter) that might be called to\n * determine whether a DSO really needs to be scanned by the collector.\n * Zero means no filter installed.  May be unused on some platforms.\n */\n/* FIXME: Add filter support for more platforms. */\nSTATIC GC_has_static_roots_func GC_has_static_roots = 0;\n\n#ifdef ANY_MSWIN\n/*\n * We traverse the entire address space and register all segments that\n * could possibly have been written to.\n */\nSTATIC void\nGC_cond_add_roots(ptr_t base, ptr_t limit)\n{\n#  ifdef THREADS\n  ptr_t curr_base = base;\n  ptr_t next_stack_lo, next_stack_hi;\n#  else\n  ptr_t stack_top;\n#  endif\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (base == limit)\n    return;\n#  ifdef THREADS\n  for (;;) {\n    GC_get_next_stack(curr_base, limit, &next_stack_lo, &next_stack_hi);\n    if (ADDR_GE(next_stack_lo, limit))\n      break;\n    if (ADDR_LT(curr_base, next_stack_lo))\n      GC_add_roots_inner(curr_base, next_stack_lo, TRUE);\n    curr_base = next_stack_hi;\n  }\n  if (ADDR_LT(curr_base, limit))\n    GC_add_roots_inner(curr_base, limit, TRUE);\n#  else\n  stack_top\n      = PTR_ALIGN_DOWN(GC_approx_sp(), GC_sysinfo.dwAllocationGranularity);\n  if (ADDR_LT(stack_top, limit) && ADDR_LT(base, GC_stackbottom)) {\n    /* Part of the stack; ignore it. */\n    return;\n  }\n  GC_add_roots_inner(base, limit, TRUE);\n#  endif\n}\n\n#  ifdef DYNAMIC_LOADING\nGC_INNER GC_bool\nGC_register_main_static_data(void)\n{\n#    if defined(MSWINCE) || defined(CYGWIN32)\n  return FALSE;\n#    else\n  return GC_no_win32_dlls;\n#    endif\n}\n#    define HAVE_REGISTER_MAIN_STATIC_DATA\n#  endif /* DYNAMIC_LOADING */\n\n#  ifdef DEBUG_VIRTUALQUERY\nvoid\nGC_dump_meminfo(MEMORY_BASIC_INFORMATION *buf)\n{\n  GC_printf(\"BaseAddress= 0x%lx, AllocationBase= 0x%lx,\"\n            \" RegionSize= 0x%lx(%lu)\\n\",\n            buf->BaseAddress, buf->AllocationBase, buf->RegionSize,\n            buf->RegionSize);\n  GC_printf(\"\\tAllocationProtect= 0x%lx, State= 0x%lx, Protect= 0x%lx, \"\n            \"Type= 0x%lx\\n\",\n            buf->AllocationProtect, buf->State, buf->Protect, buf->Type);\n}\n#  endif /* DEBUG_VIRTUALQUERY */\n\n#  if defined(MSWINCE) || defined(CYGWIN32)\n/* FIXME: Should we really need to scan `MEM_PRIVATE` sections? */\n/*\n * For now, we do not add `MEM_PRIVATE` sections to the data roots for\n * WinCE because otherwise `SIGSEGV` fault sometimes happens to occur\n * in `GC_mark_from()` (and, even if we use `WRAP_MARK_SOME`, WinCE\n * prints a \"Data Abort\" message to the debugging console).\n * To workaround that, use `-D GC_REGISTER_MEM_PRIVATE`.\n */\n#    define GC_wnt TRUE\n#  endif\n\nGC_INNER void\nGC_register_dynamic_libraries(void)\n{\n  ptr_t p, base, limit;\n\n  GC_ASSERT(I_HOLD_LOCK());\n#  ifdef MSWIN32\n  if (GC_no_win32_dlls)\n    return;\n#  endif\n  p = (ptr_t)GC_sysinfo.lpMinimumApplicationAddress;\n  base = limit = p;\n  while (ADDR_LT(p, (ptr_t)GC_sysinfo.lpMaximumApplicationAddress)) {\n    MEMORY_BASIC_INFORMATION buf;\n    size_t result = VirtualQuery((LPVOID)p, &buf, sizeof(buf));\n\n#  ifdef MSWINCE\n    if (0 == result) {\n      if (ADDR(p) > GC_WORD_MAX - GC_sysinfo.dwAllocationGranularity) {\n        /* An overflow. */\n        break;\n      }\n      /* Page is free; advance to the next possible allocation base. */\n      p = PTR_ALIGN_UP(p + 1, GC_sysinfo.dwAllocationGranularity);\n    } else\n#  endif\n    /* else */ {\n      DWORD protect;\n\n      if (result != sizeof(buf))\n        ABORT(\"Weird VirtualQuery result\");\n      if (ADDR(p) > GC_WORD_MAX - buf.RegionSize) {\n        /* An overflow. */\n        break;\n      }\n\n      protect = buf.Protect;\n      if (buf.State == MEM_COMMIT\n          && (protect == PAGE_EXECUTE_READWRITE\n              || protect == PAGE_EXECUTE_WRITECOPY || protect == PAGE_READWRITE\n              || protect == PAGE_WRITECOPY)\n          && (buf.Type == MEM_IMAGE\n#  ifdef GC_REGISTER_MEM_PRIVATE\n              || (protect == PAGE_READWRITE && buf.Type == MEM_PRIVATE)\n#  else\n              /*\n               * There is some evidence that we cannot always ignore\n               * `MEM_PRIVATE` sections under Windows ME and predecessors.\n               * Hence we now also check for that case.\n               */\n              || (!GC_wnt && buf.Type == MEM_PRIVATE)\n#  endif\n                  )\n          && !GC_is_heap_base(buf.AllocationBase)) {\n#  ifdef DEBUG_VIRTUALQUERY\n        GC_dump_meminfo(&buf);\n#  endif\n        if (p != limit) {\n          GC_cond_add_roots(base, limit);\n          base = p;\n        }\n        limit = p + buf.RegionSize;\n      }\n      p += buf.RegionSize;\n    }\n  }\n  GC_cond_add_roots(base, limit);\n}\n\n#elif defined(DYNAMIC_LOADING) /* `&& !ANY_MSWIN` */\n\n#  if !(defined(CPPCHECK) || defined(AIX) || defined(DARWIN) || defined(DGUX) \\\n        || defined(IRIX5) || defined(HAIKU) || defined(HPUX) || defined(HURD) \\\n        || defined(NACL) || defined(OSF1) || defined(SCO_ELF)                 \\\n        || defined(SERENITY) || defined(SOLARISDL)                            \\\n        || ((defined(ANY_BSD) || defined(LINUX)) && defined(__ELF__))         \\\n        || (defined(OPENBSD) && defined(M68K)))\n#    error Finding data segments of dynamic libraries is unsupported on target\n#  endif\n\n#  if defined(DARWIN) && !defined(USE_DYLD_TO_BIND) \\\n      && !defined(NO_DYLD_BIND_FULLY_IMAGE)\n#    include <dlfcn.h>\n#  endif\n\n#  ifdef SOLARISDL\n#    include <dlfcn.h>\n#    include <link.h>\n#    include <sys/elf.h>\n#  endif\n\n#  if defined(NETBSD)\n#    include <dlfcn.h>\n#    include <machine/elf_machdep.h>\n#    include <sys/param.h>\n#    define ELFSIZE ARCH_ELFSIZE\n#  endif\n\n#  if defined(OPENBSD)\n#    include <sys/param.h>\n#    if (OpenBSD >= 200519) && !defined(HAVE_DL_ITERATE_PHDR)\n#      define HAVE_DL_ITERATE_PHDR\n#    endif\n#  endif /* OPENBSD */\n\n#  if defined(DGUX) || defined(HURD) || defined(NACL) || defined(SCO_ELF) \\\n      || defined(SERENITY)                                                \\\n      || ((defined(ANY_BSD) || defined(LINUX)) && defined(__ELF__))\n#    include <stddef.h>\n#    if !defined(OPENBSD) && !defined(HOST_ANDROID)\n/*\n * OpenBSD does not have platform `elf.h` file; include `link.h` file below\n * is sufficient.  Exclude this on Android because platform `linker.h` file\n * below includes its own variant.\n */\n#      include <elf.h>\n#    endif\n#    ifdef HOST_ANDROID\n/*\n * If you do not need the \"dynamic loading\" feature, you may build the\n * collector with `-D IGNORE_DYNAMIC_LOADING`.\n */\n#      ifdef BIONIC_ELFDATA_REDEF_BUG\n/*\n * Workaround a problem in Bionic (as of Android 4.2) which has mismatching\n * `ELF_DATA` definitions in platform `sys/exec_elf.h` and `asm/elf.h` files\n * included from `linker.h` file (similar to `EM_ALPHA`).\n */\n#        include <asm/elf.h>\n#        include <linux/elf-em.h>\n#        undef ELF_DATA\n#        undef EM_ALPHA\n#      endif\n#      include <link.h>\n#    endif /* HOST_ANDROID */\n#    if ((defined(HOST_ANDROID) && !defined(GC_DONT_DEFINE_LINK_MAP) \\\n          && !(__ANDROID_API__ >= 21))                               \\\n         || defined(SERENITY))                                       \\\n        && !defined(USE_PROC_FOR_LIBRARIES)\n/*\n * `link_map` and `r_debug` are defined in `link.h` file of NDK r10+.\n * `bionic/linker/linker.h` file defines them too but the header itself\n * is a C++ one starting from Android 4.3.\n */\nstruct link_map {\n  uintptr_t l_addr;\n  char *l_name;\n  uintptr_t l_ld;\n  struct link_map *l_next;\n  struct link_map *l_prev;\n};\nstruct r_debug {\n  int32_t r_version;\n  struct link_map *r_map;\n  /* `void (*r_brk)(void);` */\n  /* `int32_t r_state;` */\n  /* `uintptr_t r_ldbase;` */\n};\n#      define LINK_MAP_R_DEBUG_DEFINED\n#    endif /* __ANDROID_API__ >= 21 || SERENITY */\n#    ifndef HOST_ANDROID\n/*\n * Workaround missing `extern \"C\"` around `_DYNAMIC` symbol in platform\n * `link.h` file of some Linux hosts.\n */\nEXTERN_C_BEGIN\n#      include <link.h>\nEXTERN_C_END\n#    endif /* !HOST_ANDROID */\n#  endif\n\n/*\n * Newer versions of GNU/Linux define this macro.  We define it similarly\n * for all ELF systems that do not.\n */\n#  ifndef ElfW\n#    if defined(FREEBSD)\n#      if __ELF_WORD_SIZE == 32\n#        define ElfW(type) Elf32_##type\n#      else\n#        define ElfW(type) Elf64_##type\n#      endif\n#    elif defined(NETBSD) || defined(OPENBSD)\n#      if ELFSIZE == 32\n#        define ElfW(type) Elf32_##type\n#      elif ELFSIZE == 64\n#        define ElfW(type) Elf64_##type\n#      else\n#        error Missing ELFSIZE define\n#      endif\n#    else\n#      if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32\n#        define ElfW(type) Elf32_##type\n#      else\n#        define ElfW(type) Elf64_##type\n#      endif\n#    endif\n#  endif\n\n#  if defined(DGUX) || defined(HURD) || defined(NACL) || defined(SCO_ELF) \\\n      || defined(SERENITY)                                                \\\n      || ((defined(ANY_BSD) || defined(LINUX)) && defined(__ELF__))\n\n#    ifdef USE_PROC_FOR_LIBRARIES\n\n#      include <fcntl.h>\n#      include <string.h>\n#      include <sys/stat.h>\n\n#      define MAPS_BUF_SIZE (32 * 1024)\n\n/*\n * Sort an array of `HeapSects` elements by `hs_start` value.\n * Unfortunately, at least some versions of Linux, `qsort` end up calling\n * `malloc` by way of `sysconf`, and hence cannot be used in the collector.\n * Hence we roll our own.  Should be reasonably fast if the array is\n * already mostly sorted, as we expect it to be.\n */\nstatic void\nsort_heap_sects(struct HeapSect *base, size_t number_of_elements)\n{\n  GC_signed_word n = (GC_signed_word)number_of_elements;\n  GC_signed_word nsorted = 1;\n\n  while (nsorted < n) {\n    GC_signed_word i;\n\n    while (nsorted < n\n           && ADDR_LT(base[nsorted - 1].hs_start, base[nsorted].hs_start)) {\n      ++nsorted;\n    }\n    if (nsorted == n)\n      break;\n    GC_ASSERT(ADDR_LT(base[nsorted].hs_start, base[nsorted - 1].hs_start));\n    for (i = nsorted - 1;\n         i >= 0 && ADDR_LT(base[i + 1].hs_start, base[i].hs_start); --i) {\n      struct HeapSect tmp = base[i];\n\n      base[i] = base[i + 1];\n      base[i + 1] = tmp;\n    }\n    GC_ASSERT(ADDR_LT(base[nsorted - 1].hs_start, base[nsorted].hs_start));\n    ++nsorted;\n  }\n}\n\nSTATIC void\nGC_register_map_entries(const char *maps)\n{\n  const char *prot, *path;\n  ptr_t my_start, my_end;\n  ptr_t least_ha, greatest_ha;\n  unsigned maj_dev;\n  unsigned i;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  sort_heap_sects(GC_our_memory, GC_n_memory);\n  least_ha = GC_our_memory[0].hs_start;\n  greatest_ha = GC_our_memory[GC_n_memory - 1].hs_start\n                + GC_our_memory[GC_n_memory - 1].hs_bytes;\n\n  for (;;) {\n    maps\n        = GC_parse_map_entry(maps, &my_start, &my_end, &prot, &maj_dev, &path);\n    if (NULL == maps)\n      break;\n\n    if (prot[1] == 'w') {\n      /*\n       * This is a writable mapping.  Add it to the root set unless\n       * it is already otherwise accounted for.\n       */\n#      ifndef THREADS\n      if (ADDR_GE(GC_stackbottom, my_start)\n          && ADDR_GE(my_end, GC_stackbottom)) {\n        /* Stack mapping; discard it. */\n        continue;\n      }\n#      endif\n#      if defined(E2K) && defined(__ptr64__)\n      /* TODO: Avoid hard-coded addresses. */\n      if (ADDR(my_start) == 0xc2fffffff000UL\n          && ADDR(my_end) == 0xc30000000000UL && path[0] == '\\n') {\n        /* Discard some special mapping. */\n        continue;\n      }\n#      endif\n      if (path[0] == '[' && strncmp(path + 1, \"heap]\", 5) != 0) {\n        /* Discard a pseudo-file path except for \"[heap]\". */\n        continue;\n      }\n\n#      ifdef THREADS\n      /*\n       * This may fail, since a thread may already be unregistered, but\n       * its thread stack may still be there.  That can fail because the\n       * stack may disappear while we are marking.  Thus the marker is,\n       * and has to be prepared to recover from segmentation faults.\n       */\n\n      if (GC_segment_is_thread_stack(my_start, my_end)) {\n        continue;\n        /*\n         * FIXME: NPTL squirrels away pointers in pieces of the stack\n         * segment that we do not scan.  We work around this by treating\n         * anything allocated by `libpthread` as uncollectible, as we do\n         * in some other cases.  A specifically identified problem is that\n         * thread stacks contain pointers to dynamic thread vectors, that\n         * may be reused due to thread caching.  They may not be marked\n         * if the thread is still live.  This specific instance should be\n         * addressed by `INCLUDE_LINUX_THREAD_DESCR`, but that does not\n         * quite seem to suffice.  We currently trace entire thread stacks,\n         * if they are are currently cached but unused.  This is very\n         * suboptimal for performance reasons.\n         */\n      }\n#      endif\n      /* We no longer exclude the main data segment. */\n      if (ADDR_GE(least_ha, my_end) || ADDR_GE(my_start, greatest_ha)) {\n        /* The easy case; just trace the entire segment. */\n        GC_add_roots_inner(my_start, my_end, TRUE);\n        continue;\n      }\n      /* Add sections that do not belong to us. */\n      i = 0;\n      while (ADDR_LT(GC_our_memory[i].hs_start + GC_our_memory[i].hs_bytes,\n                     my_start)) {\n        ++i;\n      }\n      GC_ASSERT(i < GC_n_memory);\n      if (ADDR_GE(my_start, GC_our_memory[i].hs_start)) {\n        my_start = GC_our_memory[i].hs_start + GC_our_memory[i].hs_bytes;\n        ++i;\n      }\n      for (; i < GC_n_memory && ADDR_LT(my_start, my_end)\n             && ADDR_LT(GC_our_memory[i].hs_start, my_end);\n           ++i) {\n        if (ADDR_LT(my_start, GC_our_memory[i].hs_start))\n          GC_add_roots_inner(my_start, GC_our_memory[i].hs_start, TRUE);\n        my_start = GC_our_memory[i].hs_start + GC_our_memory[i].hs_bytes;\n      }\n      if (ADDR_LT(my_start, my_end))\n        GC_add_roots_inner(my_start, my_end, TRUE);\n    } else if (prot[0] == '-' && prot[1] == '-' && prot[2] == '-') {\n      /*\n       * Even roots added statically might disappear partially\n       * (e.g. the roots added by `INCLUDE_LINUX_THREAD_DESCR`).\n       */\n      GC_remove_roots_subregion(my_start, my_end);\n    }\n  }\n}\n\nGC_INNER void\nGC_register_dynamic_libraries(void)\n{\n  GC_register_map_entries(GC_get_maps());\n}\n\nGC_INNER GC_bool\nGC_register_main_static_data(void)\n{\n  /* We now take care of the main data segment ourselves. */\n  return FALSE;\n}\n#      define HAVE_REGISTER_MAIN_STATIC_DATA\n\n#    else /* !USE_PROC_FOR_LIBRARIES */\n\n/*\n * The following is the preferred way to walk dynamic libraries for\n * `glibc` 2.2.4+.  Unfortunately, it does not work for older versions.\n */\n\n#      if GC_GLIBC_PREREQ(2, 3) || defined(HOST_ANDROID)\n/* Are others OK here, too? */\n#        ifndef HAVE_DL_ITERATE_PHDR\n#          define HAVE_DL_ITERATE_PHDR\n#        endif\n#        ifdef HOST_ANDROID\n/* Android headers might have no such definition for some targets. */\nEXTERN_C_BEGIN\nextern int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *),\n                           void *data);\nEXTERN_C_END\n#        endif\n#      endif /* __GLIBC__ >= 2 || HOST_ANDROID */\n\n#      if defined(__DragonFly__) || defined(__FreeBSD_kernel__) \\\n          || (defined(FREEBSD) && __FreeBSD__ >= 7)\n/*\n * On the FreeBSD system, any target system at major version 7 shall have\n * `dl_iterate_phdr`; therefore, we need not make it weak as below.\n */\n#        ifndef HAVE_DL_ITERATE_PHDR\n#          define HAVE_DL_ITERATE_PHDR\n#        endif\n#        define DL_ITERATE_PHDR_STRONG\n#      elif defined(HAVE_DL_ITERATE_PHDR)\n/*\n * We have the header files for a `glibc` that includes `dl_iterate_phdr`.\n * It may still not be available in the library on the target system.\n * Thus we also treat it as a weak symbol.\n */\nEXTERN_C_BEGIN\n#        pragma weak dl_iterate_phdr\nEXTERN_C_END\n#      endif\n\n#      ifdef HAVE_DL_ITERATE_PHDR\n\n#        ifdef PT_GNU_RELRO\n/*\n * Instead of registering `PT_LOAD` sections directly, we keep them\n * in a temporary list, and filter them by excluding `PT_GNU_RELRO`\n * segments.  Processing `PT_GNU_RELRO` sections with\n * `GC_exclude_static_roots` instead would be superficially cleaner.\n * But it runs into trouble if a client registers an overlapping segment,\n * which unfortunately seems quite possible.\n */\n\n#          define MAX_LOAD_SEGS MAX_ROOT_SETS\n\nstatic struct load_segment {\n  ptr_t start;\n  ptr_t end;\n  /*\n   * The room for the second segment if we remove a `PT_GNU_RELRO` segment\n   * from the middle.\n   */\n  ptr_t start2;\n  ptr_t end2;\n} load_segs[MAX_LOAD_SEGS];\n\nstatic int n_load_segs;\nstatic GC_bool load_segs_overflow;\n#        endif /* PT_GNU_RELRO */\n\nSTATIC int\nGC_register_dynlib_callback(struct dl_phdr_info *info, size_t size, void *ptr)\n{\n  const ElfW(Phdr) * p;\n  ptr_t load_ptr, my_start, my_end;\n  int i;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  /* Make sure `dl_phdr_info` structure is at least as big as we need. */\n  if (size\n      < offsetof(struct dl_phdr_info, dlpi_phnum) + sizeof(info->dlpi_phnum))\n    return 1; /*< stop */\n\n  load_ptr = (ptr_t)info->dlpi_addr;\n  p = info->dlpi_phdr;\n  for (i = 0; i < (int)info->dlpi_phnum; i++, p++) {\n    if (p->p_type == PT_LOAD) {\n      GC_has_static_roots_func callback = GC_has_static_roots;\n      if ((p->p_flags & PF_W) == 0)\n        continue;\n\n#        ifdef CHERI_PURECAP\n      my_start = load_ptr + p->p_vaddr;\n#        else\n      /*\n       * Prevent \"applying nonzero offset to null pointer\" compiler warning\n       * as `load_ptr` could be `NULL`.\n       */\n      my_start = (ptr_t)((GC_uintptr_t)load_ptr + p->p_vaddr);\n#        endif\n      my_end = my_start + p->p_memsz;\n#        ifdef CHERI_PURECAP\n      my_start = PTR_ALIGN_UP(my_start, ALIGNMENT);\n      my_end = PTR_ALIGN_DOWN(my_end, ALIGNMENT);\n      if (!SPANNING_CAPABILITY(load_ptr, ADDR(my_start), ADDR(my_end)))\n        continue;\n      my_start = cheri_bounds_set(my_start, (word)(my_end - my_start));\n#        endif\n\n      if (callback != 0 && !callback(info->dlpi_name, my_start, p->p_memsz))\n        continue;\n#        ifdef PT_GNU_RELRO\n#          if CPP_PTRSZ >= 64 && !defined(CHERI_PURECAP)\n      /*\n       * TODO: `GC_push_all` eventually does the correct rounding to the\n       * next multiple of `ALIGNMENT`, so, most probably, we should remove\n       * the corresponding assertion check in `GC_add_roots_inner` along\n       * with this code line.  `my_start` value may require aligning.\n       */\n      my_start = PTR_ALIGN_DOWN(my_start, ALIGNMENT);\n#          endif\n      if (n_load_segs >= MAX_LOAD_SEGS) {\n        if (!load_segs_overflow) {\n          WARN(\"Too many PT_LOAD segments;\"\n               \" registering as roots directly...\\n\",\n               0);\n          load_segs_overflow = TRUE;\n        }\n        GC_add_roots_inner(my_start, my_end, TRUE);\n      } else {\n        load_segs[n_load_segs].start = my_start;\n        load_segs[n_load_segs].end = my_end;\n        load_segs[n_load_segs].start2 = NULL;\n        load_segs[n_load_segs].end2 = NULL;\n        ++n_load_segs;\n      }\n#        else\n      GC_add_roots_inner(my_start, my_end, TRUE);\n#        endif /* !PT_GNU_RELRO */\n    }\n  }\n\n#        ifdef PT_GNU_RELRO\n  p = info->dlpi_phdr;\n  for (i = 0; i < (int)info->dlpi_phnum; i++, p++) {\n    if (p->p_type == PT_GNU_RELRO) {\n      /*\n       * This entry is known to be constant and will eventually be\n       * remapped as read-only.  However, the address range covered\n       * by this entry is typically a subset of a previously\n       * encountered `PT_LOAD` segment, so we need to exclude it.\n       */\n      int j;\n\n#          ifdef CHERI_PURECAP\n      my_start = load_ptr + p->p_vaddr;\n#          else\n      my_start = (ptr_t)((GC_uintptr_t)load_ptr + p->p_vaddr);\n#          endif\n      my_end = my_start + p->p_memsz;\n      for (j = n_load_segs; --j >= 0;) {\n        if (ADDR_INSIDE(my_start, load_segs[j].start, load_segs[j].end)) {\n          if (load_segs[j].start2 != NULL) {\n            WARN(\"More than one GNU_RELRO segment per load one\\n\", 0);\n          } else {\n            GC_ASSERT(\n                ADDR_GE(PTR_ALIGN_UP(load_segs[j].end, GC_page_size), my_end));\n            /* Remove it from the existing load segment. */\n            load_segs[j].end2 = load_segs[j].end;\n            load_segs[j].end = my_start;\n            load_segs[j].start2 = my_end;\n            /*\n             * Note that `start2` may be greater than `end2` because of\n             * `p->p_memsz` value is multiple of page size.\n             */\n          }\n          break;\n        }\n        if (0 == j && 0 == GC_has_static_roots)\n          WARN(\"Failed to find PT_GNU_RELRO segment\"\n               \" inside PT_LOAD region\\n\",\n               0);\n        /*\n         * No warning reported in case of the callback is present because\n         * most likely the segment has been excluded.\n         */\n      }\n    }\n  }\n#        endif\n\n  /* Signal that we were called. */\n  *(int *)ptr = 1;\n  return 0;\n}\n\nGC_INNER GC_bool\nGC_register_main_static_data(void)\n{\n#        if defined(DL_ITERATE_PHDR_STRONG) && !defined(CPPCHECK)\n  /*\n   * If `dl_iterate_phdr` is not a weak symbol, then do not test against\n   * zero (otherwise a compiler might issue a warning).\n   */\n  return FALSE;\n#        else\n  return 0 == COVERT_DATAFLOW(ADDR(dl_iterate_phdr));\n#        endif\n}\n#        define HAVE_REGISTER_MAIN_STATIC_DATA\n\n/*\n * Return `TRUE` if we succeed; return `FALSE` if `dl_iterate_phdr` was\n * not there.\n */\nSTATIC GC_bool\nGC_register_dynamic_libraries_dl_iterate_phdr(void)\n{\n  int did_something;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (GC_register_main_static_data())\n    return FALSE;\n\n#        ifdef PT_GNU_RELRO\n  {\n    static GC_bool excluded_segs = FALSE;\n    n_load_segs = 0;\n    load_segs_overflow = FALSE;\n    if (UNLIKELY(!excluded_segs)) {\n      GC_exclude_static_roots_inner((ptr_t)load_segs,\n                                    (ptr_t)load_segs + sizeof(load_segs));\n      excluded_segs = TRUE;\n    }\n  }\n#        endif\n\n  did_something = 0;\n  dl_iterate_phdr(GC_register_dynlib_callback, &did_something);\n  if (did_something) {\n#        ifdef PT_GNU_RELRO\n    int i;\n\n    for (i = 0; i < n_load_segs; ++i) {\n      if (ADDR_LT(load_segs[i].start, load_segs[i].end))\n        GC_add_roots_inner(load_segs[i].start, load_segs[i].end, TRUE);\n      if (ADDR_LT(load_segs[i].start2, load_segs[i].end2))\n        GC_add_roots_inner(load_segs[i].start2, load_segs[i].end2, TRUE);\n    }\n#        endif\n  } else {\n    ptr_t datastart, dataend;\n#        ifdef DATASTART_USES_XGETDATASTART\n    static ptr_t datastart_cached = MAKE_CPTR(GC_WORD_MAX);\n\n    /* Evaluate `DATASTART` only once. */\n    if (ADDR(datastart_cached) == GC_WORD_MAX) {\n      datastart_cached = DATASTART;\n    }\n    datastart = datastart_cached;\n#        else\n    datastart = DATASTART;\n#        endif\n#        ifdef DATAEND_IS_FUNC\n    {\n      static ptr_t dataend_cached = 0;\n      /* Evaluate `DATAEND` only once. */\n      if (dataend_cached == 0) {\n        dataend_cached = DATAEND;\n      }\n      dataend = dataend_cached;\n    }\n#        else\n    dataend = DATAEND;\n#        endif\n    if (NULL == *(char *volatile *)&datastart || ADDR_LT(dataend, datastart))\n      ABORT_ARG2(\"Wrong DATASTART/END pair\", \": %p .. %p\", (void *)datastart,\n                 (void *)dataend);\n\n    /*\n     * `dl_iterate_phdr` may forget the static data segment in\n     * statically linked executables.\n     */\n    GC_add_roots_inner(datastart, dataend, TRUE);\n#        ifdef GC_HAVE_DATAREGION2\n    /* Subtract one to check also for `NULL` without a compiler warning. */\n    if (ADDR(DATASTART2) - 1U >= ADDR(DATAEND2)) {\n      ABORT_ARG2(\"Wrong DATASTART/END2 pair\", \": %p .. %p\", (void *)DATASTART2,\n                 (void *)DATAEND2);\n    }\n    GC_add_roots_inner(DATASTART2, DATAEND2, TRUE);\n#        endif\n  }\n  return TRUE;\n}\n\n#      else /* !HAVE_DL_ITERATE_PHDR */\n\n#        if defined(NETBSD) || defined(OPENBSD)\n#          include <sys/exec_elf.h>\n/* For compatibility with 1.4.x. */\n#          ifndef DT_DEBUG\n#            define DT_DEBUG 21\n#          endif\n#          ifndef PT_LOAD\n#            define PT_LOAD 1\n#          endif\n#          ifndef PF_W\n#            define PF_W 2\n#          endif\n#        elif !defined(HOST_ANDROID)\n#          include <elf.h>\n#        endif\n\n#        ifndef HOST_ANDROID\n#          include <link.h>\n#        endif\n\n#      endif /* !HAVE_DL_ITERATE_PHDR */\n\n#    endif /* !USE_PROC_FOR_LIBRARIES */\n\n#  endif /* DGUX || HURD || NACL || (ANY_BSD || LINUX) && __ELF__ */\n\n#  if (defined(DGUX) || defined(HURD) || defined(NACL) || defined(SCO_ELF) \\\n       || defined(SERENITY) || defined(SOLARISDL)                          \\\n       || ((defined(ANY_BSD) || defined(LINUX)) && defined(__ELF__)))      \\\n      && !defined(USE_PROC_FOR_LIBRARIES)\n\n/* Dynamic loading code for Linux, Solaris or similar OS running ELF. */\n\n/*\n * This does not necessarily work in all cases, e.g. with preloaded\n * dynamic libraries.\n */\n\nEXTERN_C_BEGIN\n#    if defined(__GNUC__) && !defined(SOLARISDL)\n#      pragma weak _DYNAMIC\n#    endif\nextern ElfW(Dyn) _DYNAMIC[];\nEXTERN_C_END\n\nSTATIC struct link_map *\nGC_FirstDLOpenedLinkMap(void)\n{\n  static struct link_map *cachedResult = NULL;\n\n#    ifdef SUNOS53_SHARED_LIB\n  /*\n   * BTL: Avoid the Solaris 5.3 `ld.so` bug that `_DYNAMIC` is not being\n   * setup properly in dynamically linked library file.  This means we\n   * have to use its value in the set of original object files loaded at\n   * the program startup.\n   */\n  static ElfW(Dyn) *dynStructureAddr = NULL;\n\n  if (NULL == dynStructureAddr) {\n    void *startupSyms = dlopen(NULL, RTLD_LAZY);\n\n    dynStructureAddr = (ElfW(Dyn) *)dlsym(startupSyms, \"_DYNAMIC\");\n    /* Note: `dlclose()` is not called intentionally. */\n    if (NULL == dynStructureAddr) {\n      /* `_DYNAMIC` symbol is not resolved. */\n      return NULL;\n    }\n  }\n#    else\n  if (0 == COVERT_DATAFLOW(ADDR(_DYNAMIC))) {\n    /* `_DYNAMIC` symbol is not resolved. */\n    return NULL;\n  }\n#    endif\n\n  if (NULL == cachedResult) {\n#    if defined(NETBSD) && defined(RTLD_DI_LINKMAP)\n#      if defined(CPPCHECK)\n#        define GC_RTLD_DI_LINKMAP 2\n#      else\n#        define GC_RTLD_DI_LINKMAP RTLD_DI_LINKMAP\n#      endif\n    struct link_map *lm = NULL;\n\n    if (!dlinfo(RTLD_SELF, GC_RTLD_DI_LINKMAP, &lm) && lm != NULL) {\n      /*\n       * Now `lm` points `link_map` object of the collector.\n       * Since it might not be the first dynamically linked object,\n       * try to find it (object next to the main object).\n       */\n      while (lm->l_prev != NULL) {\n        lm = lm->l_prev;\n      }\n      cachedResult = lm->l_next;\n    }\n#    else\n    ElfW(Dyn) * dp;\n    int tag;\n\n    for (dp = _DYNAMIC; (tag = dp->d_tag) != 0; dp++) {\n      if (tag == DT_DEBUG) {\n        const struct r_debug *rd\n            = CAST_THRU_UINTPTR(struct r_debug *, dp->d_un.d_ptr);\n\n        /* `d_ptr` could be `NULL` if libs are linked statically. */\n        if (rd != NULL) {\n          const struct link_map *lm = rd->r_map;\n\n#      if defined(CPPCHECK) && defined(LINK_MAP_R_DEBUG_DEFINED)\n          GC_noop1((word)rd->r_version);\n#      endif\n          if (lm != NULL) {\n            cachedResult = lm->l_next;\n            /* Might be `NULL`. */\n          }\n        }\n        break;\n      }\n    }\n#    endif\n  }\n  return cachedResult;\n}\n\nGC_INNER void\nGC_register_dynamic_libraries(void)\n{\n  struct link_map *lm;\n\n  GC_ASSERT(I_HOLD_LOCK());\n#    ifdef HAVE_DL_ITERATE_PHDR\n  if (GC_register_dynamic_libraries_dl_iterate_phdr()) {\n    return;\n  }\n#    endif\n  for (lm = GC_FirstDLOpenedLinkMap(); lm != NULL; lm = lm->l_next) {\n    const ElfW(Ehdr) * e;\n    const ElfW(Phdr) * p;\n    ptr_t load_ptr = (ptr_t)lm->l_addr;\n    size_t i;\n\n#    ifdef HOST_ANDROID\n    if (NULL == load_ptr)\n      continue;\n#    endif\n    e = (ElfW(Ehdr) *)load_ptr;\n    p = (ElfW(Phdr) *)(load_ptr + e->e_phoff);\n#    ifdef LINT2\n    /* Workaround tainted e->e_phnum usage as a loop boundary. */\n    GC_noop1_ptr((/* no const */ void *)&e->e_phnum);\n#    endif\n    for (i = 0; i < (size_t)e->e_phnum; i++, p++) {\n      ptr_t start;\n\n      switch (p->p_type) {\n      case PT_LOAD:\n        if ((p->p_flags & PF_W) == 0)\n          break;\n        start = load_ptr + p->p_vaddr;\n        GC_add_roots_inner(start, start + p->p_memsz, TRUE);\n        break;\n      default:\n        break;\n      }\n    }\n#    if defined(CPPCHECK) && defined(LINK_MAP_R_DEBUG_DEFINED)\n    GC_noop1_ptr(lm->l_name);\n    GC_noop1((word)lm->l_ld);\n    GC_noop1_ptr(lm->l_prev);\n#    endif\n  }\n}\n\n#  endif /* (SOLARISDL || LINUX && __ELF__) && !USE_PROC_FOR_LIBRARIES */\n\n#  if defined(USE_PROC_FOR_LIBRARIES) && !defined(LINUX) || defined(IRIX5)\n\n#    include <elf.h>\n#    include <errno.h>\n#    include <fcntl.h>\n#    include <sys/procfs.h>\n#    include <sys/stat.h>\n\n/* This is included only for the following test. */\n#    include <signal.h>\n#    ifndef _sigargs\n#      define IRIX6\n#    endif\n\nGC_INNER void\nGC_register_dynamic_libraries(void)\n{\n  /*\n   * We use `/proc` to track down all parts of the address space that\n   * are mapped by the process, and throw out regions we know we should\n   * not worry about.  This may also work under other SVR4 variants.\n   */\n  static int fd = -1;\n  static prmap_t *addr_map = 0;\n  /* Number of records currently in `addr_map`. */\n  static int current_sz = 0;\n  char buf[6 + 20 + 1];\n  /* Required size of `addr_map`. */\n  int needed_sz = 0;\n  int i;\n  long flags;\n  ptr_t start;\n  ptr_t limit;\n  word heap_start = HEAP_START;\n  word heap_end = heap_start;\n#    ifdef SOLARISDL\n#      define MA_PHYS 0\n#    endif\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (fd < 0) {\n    GC_snprintf_s_ld_s(buf, sizeof(buf), \"/proc/\", (long)getpid(), \"\");\n    fd = open(buf, O_RDONLY);\n    if (fd < 0) {\n      ABORT(\"/proc open failed\");\n    }\n  }\n  if (ioctl(fd, PIOCNMAP, &needed_sz) < 0) {\n    ABORT_ARG2(\"/proc PIOCNMAP ioctl failed\", \": fd= %d, errno= %d\", fd,\n               errno);\n  }\n  if (needed_sz >= current_sz) {\n    GC_scratch_recycle_no_gww(addr_map, (size_t)current_sz * sizeof(prmap_t));\n    /* Expansion, plus room for record 0. */\n    current_sz = needed_sz * 2 + 1;\n    addr_map\n        = (prmap_t *)GC_scratch_alloc((size_t)current_sz * sizeof(prmap_t));\n    if (NULL == addr_map)\n      ABORT(\"Insufficient memory for address map\");\n  }\n  if (ioctl(fd, PIOCMAP, addr_map) < 0) {\n    ABORT_ARG3(\"/proc PIOCMAP ioctl failed\",\n               \": errcode= %d, needed_sz= %d, addr_map= %p\", errno, needed_sz,\n               (void *)addr_map);\n  }\n  if (GC_n_heap_sects > 0) {\n    heap_end = ADDR(GC_heap_sects[GC_n_heap_sects - 1].hs_start)\n               + GC_heap_sects[GC_n_heap_sects - 1].hs_bytes;\n    if (heap_end < GC_scratch_last_end_addr)\n      heap_end = GC_scratch_last_end_addr;\n  }\n  for (i = 0; i < needed_sz; i++) {\n    flags = addr_map[i].pr_mflags;\n    if ((flags & (MA_BREAK | MA_STACK | MA_PHYS | MA_FETCHOP | MA_NOTCACHED))\n        != 0)\n      goto irrelevant;\n    if ((flags & (MA_READ | MA_WRITE)) != (MA_READ | MA_WRITE))\n      goto irrelevant;\n    /*\n     * The latter test is empirically useless in very old Irix versions.\n     * Other than the main data and stack segments, everything appears\n     * to be mapped readable, writable, executable, and shared(!!).\n     * Probably this makes no sense.\n     */\n    start = (ptr_t)addr_map[i].pr_vaddr;\n    if (GC_roots_present(start)\n        || (ADDR(start) >= heap_start && ADDR(start) < heap_end))\n      goto irrelevant;\n\n    limit = start + addr_map[i].pr_size;\n    /*\n     * The following seemed to be necessary for very old versions of Irix,\n     * but it has been reported to discard relevant segments under Irix 6.5.\n     */\n#    ifndef IRIX6\n    if (addr_map[i].pr_off == 0 && strncmp(start, ELFMAG, 4) == 0) {\n      /*\n       * Discard text segments, i.e. zero-offset mappings against\n       * executable files that appear to have ELF headers.\n       */\n      caddr_t arg;\n      int obj;\n#      define MAP_IRR_SZ 10\n      /* Known irrelevant map entries. */\n      static ptr_t map_irr[MAP_IRR_SZ];\n      static int n_irr = 0;\n      struct stat buf;\n      int j;\n\n      for (j = 0; j < n_irr; j++) {\n        if (map_irr[j] == start)\n          goto irrelevant;\n      }\n      arg = (caddr_t)start;\n      obj = ioctl(fd, PIOCOPENM, &arg);\n      if (obj >= 0) {\n        fstat(obj, &buf);\n        close(obj);\n        if ((buf.st_mode & 0111) != 0) {\n          if (n_irr < MAP_IRR_SZ) {\n            map_irr[n_irr++] = start;\n          }\n          goto irrelevant;\n        }\n      }\n    }\n#    endif /* !IRIX6 */\n    GC_add_roots_inner(start, limit, TRUE);\n  irrelevant:;\n  }\n  /*\n   * Do not keep cached descriptor, for now.  Some kernels do not like us\n   * to keep a `/proc` file descriptor around during `kill -9`.  Otherwise,\n   * it should also require `FD_CLOEXEC` and proper handling at process fork\n   * (i.e. close the file descriptor because of the `pid` change).\n   */\n  if (close(fd) < 0)\n    ABORT(\"Couldn't close /proc file\");\n  fd = -1;\n}\n\n#  endif /* USE_PROC_FOR_LIBRARIES && !LINUX || IRIX5 */\n\n#  ifdef AIX\n#    include <alloca.h>\n#    include <sys/errno.h>\n#    include <sys/ldr.h>\n\nGC_INNER void\nGC_register_dynamic_libraries(void)\n{\n  int ldibuflen = 8192;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  for (;;) {\n    int len;\n    struct ld_info *ldi;\n#    if defined(CPPCHECK)\n    char ldibuf[ldibuflen];\n#    else\n    char *ldibuf = alloca(ldibuflen);\n#    endif\n\n    len = loadquery(L_GETINFO, ldibuf, ldibuflen);\n    if (len < 0) {\n      if (errno != ENOMEM) {\n        ABORT(\"loadquery failed\");\n      }\n      ldibuflen *= 2;\n      continue;\n    }\n\n    ldi = (struct ld_info *)ldibuf;\n    for (;;) {\n      len = ldi->ldinfo_next;\n      GC_add_roots_inner((ptr_t)ldi->ldinfo_dataorg,\n                         (ptr_t)ldi->ldinfo_dataorg + ldi->ldinfo_datasize,\n                         TRUE);\n      if (0 == len)\n        break;\n      ldi = (struct ld_info *)((ptr_t)ldi + len);\n    }\n    break;\n  }\n}\n#  endif /* AIX */\n\n#  ifdef DARWIN\n\n/* `__private_extern__` hack required for gcc-3.3 and earlier. */\n#    ifndef __private_extern__\n#      define __private_extern__ extern\n#      include <mach-o/dyld.h>\n#      undef __private_extern__\n#    else\n#      include <mach-o/dyld.h>\n#    endif\n\n#    if CPP_WORDSZ == 64\n#      define GC_MACH_HEADER mach_header_64\n#    else\n#      define GC_MACH_HEADER mach_header\n#    endif\n\n#    ifdef MISSING_MACH_O_GETSECT_H\nEXTERN_C_BEGIN\nextern uint8_t *getsectiondata(const struct GC_MACH_HEADER *, const char *seg,\n                               const char *sect, unsigned long *psz);\nEXTERN_C_END\n#    else\n#      include <mach-o/getsect.h>\n#    endif\n\n/* Writable sections generally available on Darwin. */\nSTATIC const struct dyld_sections_s {\n  const char *seg;\n  const char *sect;\n} GC_dyld_sections[]\n    = { { SEG_DATA, SECT_DATA },\n        /* Used by FSF gcc, but not by OS X system tools, so far. */\n        { SEG_DATA, \"__static_data\" },\n        { SEG_DATA, SECT_BSS },\n        { SEG_DATA, SECT_COMMON },\n        /*\n         * FSF gcc - zero-sized object sections for targets supporting\n         * section anchors.\n         */\n        { SEG_DATA, \"__zobj_data\" },\n        { SEG_DATA, \"__zobj_bss\" } };\n\n/*\n * Additional writable sections: gcc on Darwin constructs aligned sections\n * \"on demand\", where the alignment size is embedded in the section name.\n * Furthermore, there are distinctions between sections containing private\n * vs. public symbols.  It also constructs sections specifically for\n * zero-sized objects, when the target supports section anchors.\n */\nSTATIC const char *const GC_dyld_bss_prefixes[]\n    = { \"__bss\", \"__pu_bss\", \"__zo_bss\", \"__zo_pu_bss\" };\n\n/*\n * Currently, `mach-o` will allow up to the max of `2**15` alignment\n * in an object file.\n */\n#    ifndef L2_MAX_OFILE_ALIGNMENT\n#      define L2_MAX_OFILE_ALIGNMENT 15\n#    endif\n\nSTATIC const char *\nGC_dyld_name_for_hdr(const struct GC_MACH_HEADER *phdr)\n{\n  unsigned long i, count = _dyld_image_count();\n\n  for (i = 0; i < count; i++) {\n    if ((const struct GC_MACH_HEADER *)_dyld_get_image_header(i) == phdr)\n      return _dyld_get_image_name(i);\n  }\n  /* TODO: Probably `ABORT()` in this case? */\n  return NULL; /*< not found */\n}\n\n/*\n * `getsectbynamefromheader` is deprecated (first time in macOS 13.0),\n * `getsectiondata` (introduced in macOS 10.7) is used instead, if exists.\n * Define `USE_GETSECTBYNAME` macro to use the deprecated symbol, if needed.\n */\n#    if !defined(USE_GETSECTBYNAME)       \\\n        && (MAC_OS_X_VERSION_MIN_REQUIRED \\\n            < 1070 /* `MAC_OS_X_VERSION_10_7` */)\n#      define USE_GETSECTBYNAME\n#    endif\n\nstatic void\ndyld_section_add_del(const struct GC_MACH_HEADER *phdr, intptr_t slide,\n                     const char *dlpi_name, GC_has_static_roots_func callback,\n                     const char *seg, const char *secnam, GC_bool is_add)\n{\n  ptr_t start, finish;\n  unsigned long sec_size;\n#    ifdef USE_GETSECTBYNAME\n#      if CPP_WORDSZ == 64\n  const struct section_64 *sec = getsectbynamefromheader_64(phdr, seg, secnam);\n#      else\n  const struct section *sec = getsectbynamefromheader(phdr, seg, secnam);\n#      endif\n\n  if (NULL == sec)\n    return;\n  sec_size = sec->size;\n  start = (ptr_t)slide + sec->addr;\n#    else\n\n  UNUSED_ARG(slide);\n  sec_size = 0;\n  start = (ptr_t)getsectiondata(phdr, seg, secnam, &sec_size);\n  if (NULL == start)\n    return;\n#    endif\n  if (sec_size < sizeof(ptr_t))\n    return;\n  finish = start + sec_size;\n  if (is_add) {\n    LOCK();\n    /* The user callback is invoked holding the allocator lock. */\n    if (UNLIKELY(callback != 0)\n        && !callback(dlpi_name, start, (size_t)sec_size)) {\n      UNLOCK();\n      return; /*< skip section */\n    }\n    GC_add_roots_inner(start, finish, FALSE);\n    UNLOCK();\n  } else {\n    GC_remove_roots(start, finish);\n  }\n#    ifdef DARWIN_DEBUG\n  GC_log_printf(\"%s section __DATA,%s at %p-%p (%lu bytes) from image %s\\n\",\n                is_add ? \"Added\" : \"Removed\", secnam, (void *)start,\n                (void *)finish, sec_size, dlpi_name);\n#    endif\n}\n\nstatic void\ndyld_image_add_del(const struct GC_MACH_HEADER *phdr, intptr_t slide,\n                   GC_has_static_roots_func callback, GC_bool is_add)\n{\n  unsigned i, j;\n  const char *dlpi_name;\n\n  GC_ASSERT(I_DONT_HOLD_LOCK());\n#    ifndef DARWIN_DEBUG\n  if (0 == callback) {\n    dlpi_name = NULL;\n  } else\n#    endif\n  /* else */ {\n    dlpi_name = GC_dyld_name_for_hdr(phdr);\n  }\n  for (i = 0; i < sizeof(GC_dyld_sections) / sizeof(GC_dyld_sections[0]);\n       i++) {\n    dyld_section_add_del(phdr, slide, dlpi_name, callback,\n                         GC_dyld_sections[i].seg, GC_dyld_sections[i].sect,\n                         is_add);\n  }\n\n  /* Sections constructed on demand. */\n  for (j = 0; j < sizeof(GC_dyld_bss_prefixes) / sizeof(char *); j++) {\n    /* Our manufactured aligned BSS sections. */\n    for (i = 0; i <= L2_MAX_OFILE_ALIGNMENT; i++) {\n      char secnam[11 + 20 + 1];\n\n      GC_snprintf_s_ld_s(secnam, sizeof(secnam), GC_dyld_bss_prefixes[j],\n                         (long)i, \"\");\n      dyld_section_add_del(phdr, slide, dlpi_name, 0 /* `callback` */,\n                           SEG_DATA, secnam, is_add);\n    }\n  }\n\n#    if defined(DARWIN_DEBUG) && !defined(NO_DEBUGGING)\n  READER_LOCK();\n  GC_print_static_roots();\n  READER_UNLOCK();\n#    endif\n}\n\nSTATIC void\nGC_dyld_image_add(const struct GC_MACH_HEADER *phdr, intptr_t slide)\n{\n  if (!GC_no_dls)\n    dyld_image_add_del(phdr, slide, GC_has_static_roots, TRUE);\n}\n\nSTATIC void\nGC_dyld_image_remove(const struct GC_MACH_HEADER *phdr, intptr_t slide)\n{\n  dyld_image_add_del(phdr, slide, 0 /* `callback` */, FALSE);\n}\n\nGC_INNER void\nGC_register_dynamic_libraries(void)\n{\n  /*\n   * Currently does nothing.  The callbacks are setup by `GC_init_dyld()`.\n   * The `dyld` library takes it from there.\n   */\n}\n\n/*\n * The `_dyld_*` functions have an internal lock, so none of them can\n * be called while the world is stopped without the risk of a deadlock.\n * Because of this we must setup callbacks before we ever stop the world.\n * This should be called before any thread is created and without the\n * allocator lock held.\n */\n\n/*\n * `_dyld_bind_fully_image_containing_address` is deprecated, so use\n * `dlopen(NULL, RTLD_NOW)` instead; define `USE_DYLD_TO_BIND` macro\n * to override this, if needed.\n */\n\nGC_INNER void\nGC_init_dyld(void)\n{\n  static GC_bool initialized = FALSE;\n\n  GC_ASSERT(I_DONT_HOLD_LOCK());\n  if (initialized)\n    return;\n\n#    ifdef DARWIN_DEBUG\n  GC_log_printf(\"Registering dyld callbacks...\\n\");\n#    endif\n\n  /*\n   * From Apple's documentation:\n   * When you call `_dyld_register_func_for_add_image`, the dynamic linker\n   * runtime calls the specified callback (func) once for each of the images\n   * that is currently loaded into the program.  When a new image is added to\n   * the program, your callback is invoked again with the `mach_header` for\n   * the new image, and the virtual memory slide amount of the new image.\n   *\n   * This *will* properly register already linked libraries and libraries\n   * linked in the future.\n   */\n\n  /*\n   * `struct mach_header_64` has the same fields as `struct mach_header`\n   * except for the reserved one at the end, so these casts are OK.\n   */\n  _dyld_register_func_for_add_image(\n      (void (*)(const struct mach_header *, intptr_t))GC_dyld_image_add);\n  _dyld_register_func_for_remove_image(\n      (void (*)(const struct mach_header *, intptr_t))GC_dyld_image_remove);\n\n  /* Set this early to avoid reentrancy issues. */\n  initialized = TRUE;\n\n#    ifndef NO_DYLD_BIND_FULLY_IMAGE\n  if (GC_no_dls) {\n    /* Skip main data segment registration. */\n    return;\n  }\n\n  /*\n   * When the environment variable is set, the dynamic linker binds\n   * all undefined symbols the application needs at launch time.\n   * This includes function symbols that are normally bound lazily at\n   * the time of their first invocation.\n   */\n  if (GETENV(\"DYLD_BIND_AT_LAUNCH\") != NULL) {\n    return;\n  }\n  /* Else we should bind manually. */\n#      ifdef DARWIN_DEBUG\n  GC_log_printf(\"Forcing full bind of GC code...\\n\");\n#      endif\n#      ifndef USE_DYLD_TO_BIND\n  {\n    void *dl_handle = dlopen(NULL, RTLD_NOW);\n\n    if (!dl_handle) {\n      ABORT(\"dlopen failed (to bind fully image)\");\n    }\n    /* Note that the handle is never closed. */\n#        if defined(CPPCHECK) || defined(LINT2)\n    GC_noop1_ptr(dl_handle);\n#        endif\n  }\n#      else\n  /* Note: `_dyld_bind_fully_image_containing_address` is deprecated. */\n  if (!_dyld_bind_fully_image_containing_address((unsigned long *)GC_malloc))\n    ABORT(\"_dyld_bind_fully_image_containing_address failed\");\n#      endif\n#    endif\n}\n\nGC_INNER GC_bool\nGC_register_main_static_data(void)\n{\n  /* Already done through `dyld` callbacks. */\n  return FALSE;\n}\n#    define HAVE_REGISTER_MAIN_STATIC_DATA\n\n#  endif /* DARWIN */\n\n#  if defined(HAIKU)\n#    include <kernel/image.h>\n\nGC_INNER void\nGC_register_dynamic_libraries(void)\n{\n  image_info info;\n  int32 cookie = 0;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) {\n    ptr_t data = (ptr_t)info.data;\n\n    GC_add_roots_inner(data, data + info.data_size, TRUE);\n  }\n}\n\nGC_INNER GC_bool\nGC_register_main_static_data(void)\n{\n  /*\n   * On Haiku, the main application binary is also a \"shared image\" and will\n   * be reported in an `image_info` same as for dynamically-loaded libraries.\n   */\n  return FALSE;\n}\n#    define HAVE_REGISTER_MAIN_STATIC_DATA\n#  endif /* HAIKU */\n\n#  ifdef HPUX\n#    include <dl.h>\n#    include <errno.h>\n\nEXTERN_C_BEGIN\nextern char *sys_errlist[];\nextern int sys_nerr;\nEXTERN_C_END\n\nGC_INNER void\nGC_register_dynamic_libraries(void)\n{\n  /* Ordinal position in shared library search list. */\n  int index = 1;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  /* For each dynamic library loaded. */\n  for (;;) {\n    /* Shared library info, see platform `dl.h` file. */\n    struct shl_descriptor *shl_desc;\n    /* Get info about next shared library. */\n    int status = shl_get(index, &shl_desc);\n\n    /* Check if this is the end of the list or if some error occurred. */\n    if (status != 0) {\n#    ifdef THREADS\n      /*\n       * I have seen `errno` values of 0.  The man page is not clear as\n       * to whether `errno` should get set when -1 is returned.\n       */\n      break;\n#    else\n      if (errno == EINVAL) {\n        /* Moved past end of shared library list.  Finish. */\n        break;\n      } else {\n        ABORT_ARG3(\"shl_get failed\", \": status= %d, errcode= %d (%s)\", status,\n                   errno, errno < sys_nerr ? sys_errlist[errno] : \"\");\n      }\n#    endif\n    }\n\n#    ifdef DL_VERBOSE\n    GC_log_printf(\"---Shared library---\\n\");\n    GC_log_printf(\"filename= \\\"%s\\\"\\n\", shl_desc->filename);\n    GC_log_printf(\"index= %d\\n\", index);\n    GC_log_printf(\"handle= %08x\\n\", (unsigned long)shl_desc->handle);\n    GC_log_printf(\"text seg.start= %08x\\n\", shl_desc->tstart);\n    GC_log_printf(\"text seg.end= %08x\\n\", shl_desc->tend);\n    GC_log_printf(\"data seg.start= %08x\\n\", shl_desc->dstart);\n    GC_log_printf(\"data seg.end= %08x\\n\", shl_desc->dend);\n    GC_log_printf(\"ref.count= %lu\\n\", shl_desc->ref_count);\n#    endif\n\n    /*\n     * Register shared library's data segment as a garbage collection\n     * root.\n     */\n    GC_add_roots_inner((char *)shl_desc->dstart, (char *)shl_desc->dend, TRUE);\n\n    index++;\n  }\n}\n#  endif /* HPUX */\n\n#  ifdef OSF1\n#    include <loader.h>\n\nEXTERN_C_BEGIN\nextern char *sys_errlist[];\nextern int sys_nerr, errno;\nEXTERN_C_END\n\nGC_INNER void\nGC_register_dynamic_libraries(void)\n{\n  ldr_module_t moduleid = LDR_NULL_MODULE;\n  ldr_process_t mypid;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  /* Obtain id of this process. */\n  mypid = ldr_my_process();\n\n  /* For each module. */\n  for (;;) {\n    ldr_module_info_t moduleinfo;\n    size_t modulereturnsize;\n    ldr_region_t region;\n    ldr_region_info_t regioninfo;\n    size_t regionreturnsize;\n    /* Get the next (first) module. */\n    int status = ldr_next_module(mypid, &moduleid);\n\n    if (moduleid == LDR_NULL_MODULE) {\n      /* No more modules. */\n      break;\n    }\n\n    /*\n     * Check status *after* checking `moduleid` because of a bug\n     * in the non-shared `ldr_next_module` stub.\n     */\n    if (status != 0) {\n      ABORT_ARG3(\"ldr_next_module failed\", \": status= %d, errcode= %d (%s)\",\n                 status, errno, errno < sys_nerr ? sys_errlist[errno] : \"\");\n    }\n\n    /* Get the module information. */\n    status = ldr_inq_module(mypid, moduleid, &moduleinfo, sizeof(moduleinfo),\n                            &modulereturnsize);\n    if (status != 0)\n      ABORT(\"ldr_inq_module failed\");\n\n    /* Is module for the main program (i.e. nonshared portion)? */\n    if ((moduleinfo.lmi_flags & LDR_MAIN) != 0) {\n      /* Skip the main module. */\n      continue;\n    }\n\n#    ifdef DL_VERBOSE\n    GC_log_printf(\"---Module---\\n\");\n    GC_log_printf(\"Module ID: %ld\\n\", moduleinfo.lmi_modid);\n    GC_log_printf(\"Count of regions: %d\\n\", moduleinfo.lmi_nregion);\n    GC_log_printf(\"Flags for module: %016lx\\n\", moduleinfo.lmi_flags);\n    GC_log_printf(\"Module pathname: \\\"%s\\\"\\n\", moduleinfo.lmi_name);\n#    endif\n\n    /* For each region in this module. */\n    for (region = 0; region < moduleinfo.lmi_nregion; region++) {\n      /* Get the region information. */\n      status = ldr_inq_region(mypid, moduleid, region, &regioninfo,\n                              sizeof(regioninfo), &regionreturnsize);\n      if (status != 0)\n        ABORT(\"ldr_inq_region failed\");\n\n      /* Only process writable (data) regions. */\n      if ((regioninfo.lri_prot & LDR_W) == 0)\n        continue;\n\n#    ifdef DL_VERBOSE\n      GC_log_printf(\"--- Region ---\\n\");\n      GC_log_printf(\"Region number: %ld\\n\", regioninfo.lri_region_no);\n      GC_log_printf(\"Protection flags: %016x\\n\", regioninfo.lri_prot);\n      GC_log_printf(\"Virtual address: %p\\n\", regioninfo.lri_vaddr);\n      GC_log_printf(\"Mapped address: %p\\n\", regioninfo.lri_mapaddr);\n      GC_log_printf(\"Region size: %ld\\n\", regioninfo.lri_size);\n      GC_log_printf(\"Region name: \\\"%s\\\"\\n\", regioninfo.lri_name);\n#    endif\n\n      /* Register region as a garbage collection root. */\n      GC_add_roots_inner((char *)regioninfo.lri_mapaddr,\n                         (char *)regioninfo.lri_mapaddr + regioninfo.lri_size,\n                         TRUE);\n    }\n  }\n}\n#  endif /* OSF1 */\n\n#endif /* DYNAMIC_LOADING */\n\n#ifdef GC_MUST_RESTORE_REDEFINED_DLOPEN\n#  define dlopen GC_dlopen\n#endif\n\n#if !defined(HAVE_REGISTER_MAIN_STATIC_DATA) && defined(DYNAMIC_LOADING)\nGC_INNER GC_bool\nGC_register_main_static_data(void)\n{\n  return TRUE;\n}\n#endif /* HAVE_REGISTER_MAIN_STATIC_DATA */\n\nGC_API void GC_CALL\nGC_register_has_static_roots_callback(GC_has_static_roots_func callback)\n{\n  GC_has_static_roots = callback;\n}\n\n/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1997 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 2000 by Hewlett-Packard Company.  All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n/*\n * This is located in this file (rather than in `dyn_load.c` file) to\n * avoid having to link against `libdl` library if the client does not\n * call `dlopen()`.  Of course, this is meaningless if the collector is\n * in a dynamic library.\n */\n#if defined(GC_PTHREADS) && !defined(GC_NO_DLOPEN)\n\n#  undef GC_MUST_RESTORE_REDEFINED_DLOPEN\n#  if defined(dlopen) && !defined(GC_USE_LD_WRAP)\n/*\n * To support various threads packages, `gc.h` file interposes on `dlopen`\n * by defining the latter to be `GC_dlopen`, which is implemented below.\n * However, `GC_dlopen()` itself uses the real system `dlopen()`, thus\n * we first remove `dlopen` definition by `gc.h` file and restore it later,\n * after `GC_dlopen()` definition.\n */\n#    undef dlopen\n#    define GC_MUST_RESTORE_REDEFINED_DLOPEN\n#  endif\n\n/*\n * Make sure we are not in the middle of a collection, and make sure we\n * do not start any.  This is invoked prior to a `dlopen` call to avoid\n * synchronization issues.  We cannot just acquire the allocator lock,\n * since startup code in `dlopen` may try to allocate.  This solution\n * risks heap growth (or, even, heap overflow) in the presence of many\n * `dlopen` calls in either a multi-threaded environment, or if the\n * library initialization code allocates substantial amounts of garbage\n * collected memory.\n */\n#  ifndef USE_PROC_FOR_LIBRARIES\nstatic void\ndisable_gc_for_dlopen(void)\n{\n  LOCK();\n  while (GC_incremental && GC_collection_in_progress()) {\n    GC_collect_a_little_inner(1000);\n  }\n  ++GC_dont_gc;\n  UNLOCK();\n}\n#  endif\n\n/*\n * Redefine `dlopen` to guarantee mutual exclusion with\n * `GC_register_dynamic_libraries()`.  Should probably happen for\n * other operating systems, too.\n */\n\n/* This is similar to `WRAP_FUNC`/`REAL_FUNC` in `pthread_support.c` file. */\n#  ifdef GC_USE_LD_WRAP\n#    define WRAP_DLFUNC(f) __wrap_##f\n#    define REAL_DLFUNC(f) __real_##f\nvoid *REAL_DLFUNC(dlopen)(const char *, int);\n#  else\n#    define WRAP_DLFUNC(f) GC_##f\n#    define REAL_DLFUNC(f) f\n#  endif\n\n#  define GC_wrap_dlopen WRAP_DLFUNC(dlopen)\nGC_API void *\nGC_wrap_dlopen(const char *path, int mode)\n{\n  void *result;\n\n#  ifndef USE_PROC_FOR_LIBRARIES\n  /*\n   * Disable collections.  This solution risks heap growth (or, even,\n   * heap overflow) but there seems no better solutions.\n   */\n  disable_gc_for_dlopen();\n#  endif\n  result = REAL_DLFUNC(dlopen)(path, mode);\n#  ifndef USE_PROC_FOR_LIBRARIES\n  /* This undoes `disable_gc_for_dlopen()`. */\n  GC_enable();\n#  endif\n  return result;\n}\n#  undef GC_wrap_dlopen\n\n/*\n * Define `GC_` function as an alias for the plain one, which will be\n * intercepted.  This allows files that include `gc.h` file, and hence\n * generate references to the `GC_` symbol, to see the right symbol.\n */\n#  ifdef GC_USE_LD_WRAP\n\nGC_API void *\nGC_dlopen(const char *path, int mode)\n{\n  return dlopen(path, mode);\n}\n#  endif /* GC_USE_LD_WRAP */\n\n#  ifdef GC_MUST_RESTORE_REDEFINED_DLOPEN\n#    define dlopen GC_dlopen\n#  endif\n\n#endif /* GC_PTHREADS && !GC_NO_DLOPEN */\n\n#if !defined(PLATFORM_MACH_DEP)\n/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#if !defined(PLATFORM_MACH_DEP) && !defined(SN_TARGET_PSP2)\n\n#  if defined(IA64) && !defined(THREADS)\nGC_INNER ptr_t GC_save_regs_ret_val = NULL;\n#  endif\n\n#  if defined(UNIX_LIKE) && !defined(STACK_NOT_SCANNED)\n#    include <signal.h>\n#    ifndef NO_GETCONTEXT\n#      if defined(DARWIN)                  \\\n          && (MAC_OS_X_VERSION_MAX_ALLOWED \\\n              >= 1060 /* `MAC_OS_X_VERSION_10_6` */)\n#        include <sys/ucontext.h>\n#      else\n#        include <ucontext.h>\n#      endif /* !DARWIN */\n#      ifdef GETCONTEXT_FPU_EXCMASK_BUG\n#        include <fenv.h>\n#      endif\n#    endif /* !NO_GETCONTEXT */\n#  endif\n\nGC_ATTR_NOINLINE GC_ATTR_NO_SANITIZE_ADDR GC_INNER void\nGC_with_callee_saves_pushed(GC_with_callee_saves_func fn, ptr_t arg)\n{\n  volatile int dummy;\n  volatile ptr_t context = 0;\n#  if defined(EMSCRIPTEN) || defined(HAVE_BUILTIN_UNWIND_INIT)               \\\n      || defined(STACK_NOT_SCANNED) || (defined(NO_CRT) && defined(MSWIN32)) \\\n      || !defined(NO_UNDERSCORE_SETJMP)\n#    define volatile_arg arg\n#  else\n  /*\n   * Note: `volatile` to avoid \"arg might be clobbered by setjmp\" warning\n   * produced by some compilers.\n   */\n  volatile ptr_t volatile_arg = arg;\n#  endif\n\n#  if defined(EMSCRIPTEN) || defined(STACK_NOT_SCANNED)\n  /* No-op, \"registers\" are pushed in `GC_push_other_roots()`. */\n#  else\n#    if defined(UNIX_LIKE) && !defined(NO_GETCONTEXT)\n  /*\n   * Older versions of Darwin seem to lack `getcontext()`.\n   * Linux on ARM and MIPS often does not provide a real `getcontext()`.\n   */\n\n  /* The variable is set to -1 (means broken) or 1 (means it works). */\n  static signed char getcontext_works = 0;\n  ucontext_t ctxt;\n#      ifdef GETCONTEXT_FPU_EXCMASK_BUG\n  /*\n   * Workaround a bug (clearing the FPU exception mask) in `getcontext`\n   * on Linux/x86_64.\n   */\n#        ifdef X86_64\n  /*\n   * We manipulate FPU control word here just not to force the client\n   * application to use `-lm` linker option.\n   */\n  unsigned short old_fcw;\n\n#          if defined(CPPCHECK)\n  GC_noop1_ptr(&old_fcw);\n#          endif\n  __asm__ __volatile__(\"fstcw %0\" : \"=m\"(*&old_fcw));\n#        else\n  int except_mask = fegetexcept();\n#        endif\n#      endif\n\n  if (getcontext_works >= 0) {\n    if (getcontext(&ctxt) < 0) {\n      WARN(\"getcontext failed:\"\n           \" using another register retrieval method...\\n\",\n           0);\n      /*\n       * `getcontext()` is broken, do not try again.\n       * E.g., to workaround a bug in Docker `ubuntu_32bit`.\n       */\n    } else {\n      context = (ptr_t)&ctxt;\n    }\n    if (UNLIKELY(0 == getcontext_works))\n      getcontext_works = context != NULL ? 1 : -1;\n  }\n#      ifdef GETCONTEXT_FPU_EXCMASK_BUG\n#        ifdef X86_64\n  __asm__ __volatile__(\"fldcw %0\" : : \"m\"(*&old_fcw));\n  {\n    unsigned mxcsr;\n    /* And now correct the exception mask in SSE `mxcsr`. */\n    __asm__ __volatile__(\"stmxcsr %0\" : \"=m\"(*&mxcsr));\n    mxcsr = (mxcsr & ~(FE_ALL_EXCEPT << 7)) | ((old_fcw & FE_ALL_EXCEPT) << 7);\n    __asm__ __volatile__(\"ldmxcsr %0\" : : \"m\"(*&mxcsr));\n  }\n#        else /* !X86_64 */\n  if (feenableexcept(except_mask) < 0)\n    ABORT(\"feenableexcept failed\");\n#        endif\n#      endif /* GETCONTEXT_FPU_EXCMASK_BUG */\n#      if defined(IA64) || defined(SPARC)\n  /*\n   * On a register-window machine, we need to save register contents on\n   * the stack for this to work.  This may already be subsumed by the\n   * `getcontext()` call.\n   */\n#        if defined(IA64) && !defined(THREADS)\n  GC_save_regs_ret_val =\n#        endif\n      GC_save_regs_in_stack();\n#      endif\n  if (NULL == context) /*< `getcontext` failed */\n#    endif /* !NO_GETCONTEXT */\n  {\n#    if defined(HAVE_BUILTIN_UNWIND_INIT)\n    /*\n     * This was suggested as the way to force callee-save registers and\n     * register windows onto the stack.\n     */\n    __builtin_unwind_init();\n#    elif defined(NO_CRT) && defined(MSWIN32)\n    CONTEXT ctx;\n\n    RtlCaptureContext(&ctx);\n#    else\n    /* Generic code. */\n    jmp_buf regs;\n\n    /*\n     * `setjmp()` does not always clear all of the buffer.\n     * That tends to preserve garbage.  Clear it.\n     */\n    BZERO(regs, sizeof(regs));\n#      ifdef NO_UNDERSCORE_SETJMP\n    (void)setjmp(regs);\n#      else\n    /*\n     * We do not want to mess with signals.  According to the SUSv3\n     * (Single UNIX Specification v3), `setjmp` may or may not save\n     * signal mask.  `_setjmp` will not, but is less portable.\n     */\n    (void)_setjmp(regs);\n#      endif\n#    endif\n  }\n#  endif\n  /*\n   * TODO: `context` here is sometimes just zero.  At the moment, the\n   * callees do not really need it.  Cast `fn` to a `volatile` type\n   * to prevent call inlining.\n   */\n  (*(GC_with_callee_saves_func volatile *)&fn)(\n      volatile_arg, CAST_AWAY_VOLATILE_PVOID(context));\n  /*\n   * Strongly discourage the compiler from treating the above as a tail-call,\n   * since that would pop the register contents before we get a chance to\n   * look at them.\n   */\n  GC_noop1(COVERT_DATAFLOW(ADDR(&dummy)));\n#  undef volatile_arg\n}\n\n#endif /* !PLATFORM_MACH_DEP && !SN_TARGET_PSP2 */\n\n#endif\n#if !defined(PLATFORM_STOP_WORLD)\n/*\n * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.\n * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.\n * All rights reserved.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#ifdef PTHREAD_STOP_WORLD_IMPL\n\n#  ifdef NACL\n#    include <sys/time.h>\n#  else\n#    include <errno.h>\n#    include <semaphore.h>\n#    include <signal.h>\n#    include <time.h>\n#  endif /* !NACL */\n\n#  ifdef E2K\n#    include <alloca.h>\n#  endif\n\nGC_INLINE void\nGC_usleep(unsigned us)\n{\n#  if defined(LINT2) || defined(THREAD_SANITIZER)\n  /*\n   * Workaround \"waiting while holding a lock\" static analyzer warning.\n   * Workaround a rare hang in `usleep()` trying to acquire TSan Lock.\n   */\n  while (us-- > 0) {\n    /* Sleep for a moment, pretending it takes 1us. */\n    sched_yield();\n  }\n#  elif defined(CPPCHECK) /* `|| _POSIX_C_SOURCE >= 199309L` */\n  struct timespec ts;\n\n  ts.tv_sec = 0;\n  ts.tv_nsec = (unsigned32)us * 1000;\n  /* This requires `_POSIX_TIMERS` feature. */\n  (void)nanosleep(&ts, NULL);\n#  else\n  usleep(us);\n#  endif\n}\n\n#  ifdef NACL\n\nSTATIC int GC_nacl_num_gc_threads = 0;\nSTATIC volatile int GC_nacl_park_threads_now = 0;\nSTATIC volatile pthread_t GC_nacl_thread_parker = -1;\n\nSTATIC __thread int GC_nacl_thread_idx = -1;\n\n/* TODO: Use `GC_get_tlfs()` instead. */\nSTATIC __thread GC_thread GC_nacl_gc_thread_self = NULL;\n\nvolatile int GC_nacl_thread_parked[MAX_NACL_GC_THREADS];\nint GC_nacl_thread_used[MAX_NACL_GC_THREADS];\n\n#  else /* !NACL */\n\n#    if (!defined(AO_HAVE_load_acquire) || !defined(AO_HAVE_store_release)) \\\n        && !defined(CPPCHECK)\n#      error AO_load_acquire and/or AO_store_release are missing;\n#      error please define AO_REQUIRE_CAS manually\n#    endif\n\n#    ifdef DEBUG_THREADS\n/* It is safe to call original `pthread_sigmask()` here. */\n#      undef pthread_sigmask\n\n#      ifndef NSIG\n#        ifdef CPPCHECK\n#          define NSIG 32\n#        elif defined(MAXSIG)\n#          define NSIG (MAXSIG + 1)\n#        elif defined(_NSIG)\n#          define NSIG _NSIG\n#        elif defined(__SIGRTMAX)\n#          define NSIG (__SIGRTMAX + 1)\n#        else\n#          error define NSIG\n#        endif\n#      endif\n\nvoid\nGC_print_sig_mask(void)\n{\n  sigset_t blocked;\n  int i;\n\n  if (pthread_sigmask(SIG_BLOCK, NULL, &blocked) != 0)\n    ABORT(\"pthread_sigmask failed\");\n  for (i = 1; i < NSIG; i++) {\n    if (sigismember(&blocked, i))\n      GC_printf(\"Signal blocked: %d\\n\", i);\n  }\n}\n#    endif /* DEBUG_THREADS */\n\n/*\n * Remove the signals that we want to allow in thread stopping handler\n * from a set.\n */\nSTATIC void\nGC_remove_allowed_signals(sigset_t *set)\n{\n  if (sigdelset(set, SIGINT) != 0 || sigdelset(set, SIGQUIT) != 0\n      || sigdelset(set, SIGABRT) != 0 || sigdelset(set, SIGTERM) != 0) {\n    ABORT(\"sigdelset failed\");\n  }\n\n#    ifdef MPROTECT_VDB\n  /*\n   * The handlers write to the thread structure, which is in the heap,\n   * and hence can trigger a protection fault.\n   */\n  if (sigdelset(set, SIGSEGV) != 0\n#      ifdef HAVE_SIGBUS\n      || sigdelset(set, SIGBUS) != 0\n#      endif\n  ) {\n    ABORT(\"sigdelset failed\");\n  }\n#    endif\n}\n\nstatic sigset_t suspend_handler_mask;\n\n#    define THREAD_RESTARTED 0x1\n\n/*\n * Incremented (to the nearest even value) at the beginning of\n * `GC_stop_world()` (or when a thread is requested to be suspended by\n * `GC_suspend_thread`) and once more (to an odd value) at the\n * beginning of `GC_start_world`.  The lowest bit is `THREAD_RESTARTED`\n * one which, if set, means it is safe for threads to restart, i.e.\n * they will see another suspend signal before they are expected to\n * stop (unless they have stopped voluntarily).\n */\nSTATIC volatile AO_t GC_stop_count = 0;\n\nSTATIC GC_bool GC_retry_signals = FALSE;\n\n/*\n * We use signals to stop threads during GC.\n *\n * Suspended threads wait in signal handler for `SIG_THR_RESTART`.\n * That is more portable than semaphores or condition variables.\n * (We do use `sem_post()` from a signal handler, but that should be\n * portable.)\n *\n * The thread suspension signal `SIG_SUSPEND` is now defined in `gc_priv.h`\n * file.  Note that we cannot just stop a thread; we need it to save its\n * stack pointers and acknowledge.\n */\n#    ifndef SIG_THR_RESTART\n#      if defined(SUSPEND_HANDLER_NO_CONTEXT) || defined(GC_REUSE_SIG_SUSPEND)\n/* Reuse the suspend signal. */\n#        define SIG_THR_RESTART SIG_SUSPEND\n#      elif defined(HPUX) || defined(NETBSD) || defined(OSF1) \\\n          || defined(GC_USESIGRT_SIGNALS)\n#        if defined(_SIGRTMIN) && !defined(CPPCHECK)\n#          define SIG_THR_RESTART (_SIGRTMIN + 5)\n#        else\n#          define SIG_THR_RESTART (SIGRTMIN + 5)\n#        endif\n#      elif defined(FREEBSD) && defined(__GLIBC__)\n#        define SIG_THR_RESTART (32 + 5)\n#      elif defined(FREEBSD) || defined(HURD) || defined(RTEMS)\n#        define SIG_THR_RESTART SIGUSR2\n#      else\n#        define SIG_THR_RESTART SIGXCPU\n#      endif\n#    endif /* !SIG_THR_RESTART */\n\n#    define SIGNAL_UNSET (-1)\n\n/*\n * Since `SIG_SUSPEND` and/or `SIG_THR_RESTART` could represent\n * a non-constant expression (e.g., in case of `SIGRTMIN`), actual\n * signal numbers are determined by `GC_stop_init()` unless manually\n * set (before the collector initialization).  Might be set to the\n * same signal number.\n */\nSTATIC int GC_sig_suspend = SIGNAL_UNSET;\nSTATIC int GC_sig_thr_restart = SIGNAL_UNSET;\n\nGC_API void GC_CALL\nGC_set_suspend_signal(int sig)\n{\n  if (GC_is_initialized)\n    return;\n\n  GC_sig_suspend = sig;\n}\n\nGC_API void GC_CALL\nGC_set_thr_restart_signal(int sig)\n{\n  if (GC_is_initialized)\n    return;\n\n  GC_sig_thr_restart = sig;\n}\n\nGC_API int GC_CALL\nGC_get_suspend_signal(void)\n{\n  return GC_sig_suspend != SIGNAL_UNSET ? GC_sig_suspend : SIG_SUSPEND;\n}\n\nGC_API int GC_CALL\nGC_get_thr_restart_signal(void)\n{\n  return GC_sig_thr_restart != SIGNAL_UNSET ? GC_sig_thr_restart\n                                            : SIG_THR_RESTART;\n}\n\n#    ifdef BASE_ATOMIC_OPS_EMULATED\n/*\n * The AO primitives emulated with locks cannot be used inside signal\n * handlers as this could cause a deadlock or a double lock.\n * The following \"async\" macro definitions are correct only for\n * an uniprocessor case and are provided for a test purpose.\n */\n#      define ao_load_acquire_async(p) (*(p))\n#      define ao_load_async(p) ao_load_acquire_async(p)\n#      define ao_store_release_async(p, v) (void)(*(p) = (v))\n#      define ao_cptr_store_async(p, v) (void)(*(p) = (v))\n#    else\n#      define ao_load_acquire_async(p) AO_load_acquire(p)\n#      define ao_load_async(p) AO_load(p)\n#      define ao_store_release_async(p, v) AO_store_release(p, v)\n#      define ao_cptr_store_async(p, v) GC_cptr_store(p, v)\n#    endif /* !BASE_ATOMIC_OPS_EMULATED */\n\n/* Note: this is also used to acknowledge restart. */\nSTATIC sem_t GC_suspend_ack_sem;\n\nSTATIC void GC_suspend_handler_inner(ptr_t dummy, void *context);\n\n#    ifdef SUSPEND_HANDLER_NO_CONTEXT\nSTATIC void\nGC_suspend_handler(int sig)\n#    else\nSTATIC void\nGC_suspend_sigaction(int sig, siginfo_t *info, void *context)\n#    endif\n{\n  int old_errno = errno;\n\n  if (sig != GC_sig_suspend) {\n#    ifdef FREEBSD\n    /* Workaround \"deferred signal handling\" bug in FreeBSD 9.2. */\n    if (0 == sig)\n      return;\n#    endif\n    ABORT(\"Bad signal in suspend_handler\");\n  }\n\n#    ifdef SUSPEND_HANDLER_NO_CONTEXT\n  /* A quick check if the signal is called to restart the world. */\n  if ((ao_load_async(&GC_stop_count) & THREAD_RESTARTED) != 0)\n    return;\n  GC_with_callee_saves_pushed(GC_suspend_handler_inner, NULL);\n#    else\n  UNUSED_ARG(info);\n  /*\n   * We believe that in this case the full context is already in the\n   * signal handler frame.\n   */\n  GC_suspend_handler_inner(NULL, context);\n#    endif\n  errno = old_errno;\n}\n\n/*\n * The lookup here is safe, since this is done on behalf of a thread which\n * holds the allocator lock in order to stop the world.  Thus concurrent\n * modification of the data structure is impossible.  Unfortunately, we\n * have to instruct TSan that the lookup is safe.\n */\n#    ifdef THREAD_SANITIZER\n/*\n * Almost same as `GC_self_thread_inner()` except for the `no_sanitize`\n * attribute added and the result is never `NULL`.\n */\nGC_ATTR_NO_SANITIZE_THREAD\nstatic GC_thread\nGC_lookup_self_thread_async(void)\n{\n  thread_id_t self_id = thread_id_self();\n  GC_thread p = GC_threads[THREAD_TABLE_INDEX(self_id)];\n\n  for (;; p = p->tm.next) {\n    if (THREAD_EQUAL(p->id, self_id))\n      break;\n  }\n  return p;\n}\n#    else\n#      define GC_lookup_self_thread_async() GC_self_thread_inner()\n#    endif\n\nGC_INLINE void\nGC_store_stack_ptr(GC_stack_context_t crtn)\n{\n  /*\n   * There is no data race between the suspend handler (storing\n   * `stack_ptr`) and `GC_push_all_stacks` (fetching `stack_ptr`)\n   * because `GC_push_all_stacks` is executed after `GC_stop_world`\n   * exits and the latter runs `sem_wait()` repeatedly waiting for all\n   * the suspended threads to call `sem_post()`.  Nonetheless,\n   * `stack_ptr` is stored (here) and fetched (by `GC_push_all_stacks`)\n   * using the atomic primitives to avoid the related TSan warning.\n   */\n#    ifdef SPARC\n  ao_cptr_store_async(&crtn->stack_ptr, GC_save_regs_in_stack());\n  /* TODO: Registers saving already done by `GC_with_callee_saves_pushed`. */\n#    else\n#      ifdef IA64\n  crtn->backing_store_ptr = GC_save_regs_in_stack();\n#      endif\n  ao_cptr_store_async(&crtn->stack_ptr, GC_approx_sp());\n#    endif\n}\n\nSTATIC void\nGC_suspend_handler_inner(ptr_t dummy, void *context)\n{\n  GC_thread me;\n  GC_stack_context_t crtn;\n#    ifdef E2K\n  ptr_t bs_lo;\n  size_t stack_size;\n#    endif\n  IF_CANCEL(int cancel_state;)\n#    ifdef GC_ENABLE_SUSPEND_THREAD\n  AO_t suspend_cnt;\n#    endif\n  AO_t my_stop_count = ao_load_acquire_async(&GC_stop_count);\n  /*\n   * After the barrier, this thread should see the actual content of\n   * `GC_threads`.\n   */\n\n  UNUSED_ARG(dummy);\n  UNUSED_ARG(context);\n  if ((my_stop_count & THREAD_RESTARTED) != 0) {\n    /* Restarting the world. */\n    return;\n  }\n\n  /*\n   * `pthread_setcancelstate()` is not defined to be async-signal-safe.\n   * But the `glibc` version appears to be defined, in the absence of\n   * asynchronous cancellation.  And since this signal handler to block\n   * on `sigsuspend`, which is both async-signal-safe and\n   * a cancellation point, there seems to be no obvious way out of it.\n   * In fact, it looks like an async-signal-safe cancellation point\n   * is inherently a problem, unless there is some way to disable\n   * cancellation in the handler.\n   */\n  DISABLE_CANCEL(cancel_state);\n\n#    ifdef DEBUG_THREADS\n  GC_log_printf(\"Suspending %p\\n\", PTHREAD_TO_VPTR(pthread_self()));\n#    endif\n  me = GC_lookup_self_thread_async();\n  if (NULL == me) return; // __v_, make the sanitizers and -cstrict happy\n  if ((me->last_stop_count & ~(word)THREAD_RESTARTED) == my_stop_count) {\n    /* Duplicate signal.  OK if we are retrying. */\n    if (!GC_retry_signals) {\n      WARN(\"Duplicate suspend signal in thread %p\\n\", pthread_self());\n    }\n    RESTORE_CANCEL(cancel_state);\n    return;\n  }\n  crtn = me->crtn;\n  GC_store_stack_ptr(crtn);\n#    ifdef E2K\n  GC_ASSERT(NULL == crtn->backing_store_end);\n  GET_PROCEDURE_STACK_LOCAL(crtn->ps_ofs, &bs_lo, &stack_size);\n  crtn->backing_store_end = bs_lo;\n  crtn->backing_store_ptr = bs_lo + stack_size;\n#    endif\n#    ifdef GC_ENABLE_SUSPEND_THREAD\n  suspend_cnt = ao_load_async(&me->ext_suspend_cnt);\n#    endif\n\n  /*\n   * Tell the thread that wants to stop the world that this thread has\n   * been stopped.  Note that `sem_post()` is the only async-signal-safe\n   * primitive in LinuxThreads.\n   */\n  sem_post(&GC_suspend_ack_sem);\n  ao_store_release_async(&me->last_stop_count, my_stop_count);\n\n  /*\n   * Wait until that thread tells us to restart by sending this thread\n   * a `GC_sig_thr_restart` signal (should be masked at this point thus\n   * there is no race).  We do not continue until we receive that signal,\n   * but we do not take that as authoritative.  (We may be accidentally\n   * restarted by one of the user signals we do not block.)\n   * After we receive the signal, we use a primitive and an expensive\n   * mechanism to wait until it is really safe to proceed.\n   */\n  do {\n    sigsuspend(&suspend_handler_mask);\n    /* Iterate while not restarting the world or thread is suspended. */\n  } while (ao_load_acquire_async(&GC_stop_count) == my_stop_count\n#    ifdef GC_ENABLE_SUSPEND_THREAD\n           || ((suspend_cnt & 1) != 0\n               && ao_load_async(&me->ext_suspend_cnt) == suspend_cnt)\n#    endif\n  );\n\n#    ifdef DEBUG_THREADS\n  GC_log_printf(\"Resuming %p\\n\", PTHREAD_TO_VPTR(pthread_self()));\n#    endif\n#    ifdef E2K\n  GC_ASSERT(crtn->backing_store_end == bs_lo);\n  crtn->backing_store_ptr = NULL;\n  crtn->backing_store_end = NULL;\n#    endif\n\n#    ifndef GC_NETBSD_THREADS_WORKAROUND\n  if (GC_retry_signals || GC_sig_suspend == GC_sig_thr_restart)\n#    endif\n  {\n    /*\n     * If the `SIG_THR_RESTART` signal loss is possible (though it should\n     * be less likely than losing the `SIG_SUSPEND` signal as we do not\n     * do much between the first `sem_post` and `sigsuspend` calls), more\n     * handshaking is provided to work around it.\n     */\n    sem_post(&GC_suspend_ack_sem);\n    /* Set the flag that the thread has been restarted. */\n    if (GC_retry_signals)\n      ao_store_release_async(&me->last_stop_count,\n                             my_stop_count | THREAD_RESTARTED);\n  }\n  RESTORE_CANCEL(cancel_state);\n}\n\nstatic void\nsuspend_restart_barrier(int n_live_threads)\n{\n  int i;\n\n  for (i = 0; i < n_live_threads; i++) {\n    while (sem_wait(&GC_suspend_ack_sem) == -1) {\n      /*\n       * On Linux, `sem_wait()` is documented to always return zero.\n       * But the documentation appears to be incorrect.\n       * `EINTR` seems to happen with some versions of gdb.\n       */\n      if (errno != EINTR)\n        ABORT(\"sem_wait failed\");\n    }\n  }\n#    ifdef GC_ASSERTIONS\n  sem_getvalue(&GC_suspend_ack_sem, &i);\n  GC_ASSERT(0 == i);\n#    endif\n}\n\n#    define WAIT_UNIT 3000 /* us */\n\nstatic int\nresend_lost_signals(int n_live_threads, int (*suspend_restart_all)(void))\n{\n#    define RESEND_SIGNALS_LIMIT 150\n#    define RETRY_INTERVAL 100000 /* us */\n\n  if (n_live_threads > 0) {\n    unsigned long wait_usecs = 0; /*< total wait since retry */\n    int retry = 0;\n    int prev_sent = 0;\n\n    for (;;) {\n      int ack_count;\n\n      sem_getvalue(&GC_suspend_ack_sem, &ack_count);\n      if (ack_count == n_live_threads)\n        break;\n      if (wait_usecs > RETRY_INTERVAL) {\n        int newly_sent = suspend_restart_all();\n\n        if (newly_sent != prev_sent) {\n          /* Restart the counter. */\n          retry = 0;\n        } else if (++retry >= RESEND_SIGNALS_LIMIT) {\n          /* No progress. */\n          ABORT_ARG1(\"Signals delivery fails constantly\", \" at GC #%lu\",\n                     (unsigned long)GC_gc_no);\n        }\n\n        GC_COND_LOG_PRINTF(\"Resent %d signals after timeout, retry: %d\\n\",\n                           newly_sent, retry);\n        sem_getvalue(&GC_suspend_ack_sem, &ack_count);\n        if (newly_sent < n_live_threads - ack_count) {\n          WARN(\"Lost some threads while stopping or starting world?!\\n\", 0);\n          n_live_threads = ack_count + newly_sent;\n        }\n        prev_sent = newly_sent;\n        wait_usecs = 0;\n      }\n      GC_usleep(WAIT_UNIT);\n      wait_usecs += WAIT_UNIT;\n    }\n  }\n  return n_live_threads;\n}\n\n#    ifdef HAVE_CLOCK_GETTIME\n#      define TS_NSEC_ADD(ts, ns)                                     \\\n        (ts.tv_nsec += (ns),                                          \\\n         (void)(ts.tv_nsec >= 1000000L * 1000                         \\\n                    ? (ts.tv_nsec -= 1000000L * 1000, ts.tv_sec++, 0) \\\n                    : 0))\n#    endif\n\nstatic void\nresend_lost_signals_retry(int n_live_threads, int (*suspend_restart_all)(void))\n{\n#    if defined(HAVE_CLOCK_GETTIME) && !defined(DONT_TIMEDWAIT_ACK_SEM)\n#      define TIMEOUT_BEFORE_RESEND 10000 /* us */\n  struct timespec ts;\n\n  if (n_live_threads > 0 && clock_gettime(CLOCK_REALTIME, &ts) == 0) {\n    int i;\n\n    TS_NSEC_ADD(ts, TIMEOUT_BEFORE_RESEND * (unsigned32)1000);\n    /*\n     * First, try to wait for the semaphore with some timeout.\n     * On failure, fall back to `WAIT_UNIT` pause and resend of the signal.\n     */\n    for (i = 0; i < n_live_threads; i++) {\n      if (sem_timedwait(&GC_suspend_ack_sem, &ts) == -1)\n        break; /*< wait timed out or any other error */\n    }\n    /* Update the count of threads to wait the acknowledge from. */\n    n_live_threads -= i;\n  }\n#    endif\n  n_live_threads = resend_lost_signals(n_live_threads, suspend_restart_all);\n  suspend_restart_barrier(n_live_threads);\n}\n\nSTATIC void\nGC_restart_handler(int sig)\n{\n#    ifdef DEBUG_THREADS\n  /* Preserve `errno` value. */\n  int old_errno = errno;\n#    endif\n\n  if (sig != GC_sig_thr_restart) {\n    ABORT(\"Bad signal in restart handler\");\n  }\n\n  /*\n   * Note: even if we do not do anything useful here, it would still\n   * be necessary to have a signal handler, rather than ignoring the\n   * signals, otherwise the signals will not be delivered at all, and\n   * will thus not interrupt the `sigsuspend()` above.\n   */\n#    ifdef DEBUG_THREADS\n  GC_log_printf(\"In GC_restart_handler for %p\\n\",\n                PTHREAD_TO_VPTR(pthread_self()));\n  errno = old_errno;\n#    endif\n}\n\n#    ifdef USE_TKILL_ON_ANDROID\nEXTERN_C_BEGIN\nextern int tkill(pid_t tid, int sig); /*< from platform `sys/linux-unistd.h` */\nEXTERN_C_END\n#      define THREAD_SYSTEM_ID(t) (t)->kernel_id\n#    else\n#      define THREAD_SYSTEM_ID(t) (t)->id\n#    endif\n\n#    ifndef RETRY_TKILL_EAGAIN_LIMIT\n#      define RETRY_TKILL_EAGAIN_LIMIT 16\n#    endif\n\nstatic int\nraise_signal(GC_thread p, int sig)\n{\n  int res;\n#    ifdef RETRY_TKILL_ON_EAGAIN\n  int retry;\n#    endif\n#    if defined(SIMULATE_LOST_SIGNALS) && !defined(GC_ENABLE_SUSPEND_THREAD)\n#      ifndef LOST_SIGNALS_RATIO\n#        define LOST_SIGNALS_RATIO 25\n#      endif\n  /* Note: race is OK, it is for test purpose only. */\n  static int signal_cnt;\n\n  if (GC_retry_signals && (++signal_cnt) % LOST_SIGNALS_RATIO == 0) {\n    /* Simulate the signal is sent but lost. */\n    return 0;\n  }\n#    endif\n#    ifdef RETRY_TKILL_ON_EAGAIN\n  for (retry = 0;; retry++)\n#    endif\n  {\n#    ifdef USE_TKILL_ON_ANDROID\n    int old_errno = errno;\n\n    res = tkill(THREAD_SYSTEM_ID(p), sig);\n    if (res < 0) {\n      res = errno;\n      errno = old_errno;\n    }\n#    else\n    res = pthread_kill(THREAD_SYSTEM_ID(p), sig);\n#    endif\n#    ifdef RETRY_TKILL_ON_EAGAIN\n    if (res != EAGAIN || retry >= RETRY_TKILL_EAGAIN_LIMIT)\n      break;\n    /* A temporal overflow of the real-time signal queue. */\n    GC_usleep(WAIT_UNIT);\n#    endif\n  }\n  return res;\n}\n\n#    ifdef GC_ENABLE_SUSPEND_THREAD\n#      include <sys/time.h>\n\n/* This is to get the prototypes as `extern \"C\"`. */\n\n\n\nSTATIC void\nGC_brief_async_signal_safe_sleep(void)\n{\n  struct timeval tv;\n  tv.tv_sec = 0;\n#      if defined(GC_TIME_LIMIT) && !defined(CPPCHECK)\n  tv.tv_usec = 1000 * GC_TIME_LIMIT / 2;\n#      else\n  tv.tv_usec = 1000 * 15 / 2;\n#      endif\n  (void)select(0, 0, 0, 0, &tv);\n}\n\nGC_INNER void\nGC_suspend_self_inner(GC_thread me, size_t suspend_cnt)\n{\n  IF_CANCEL(int cancel_state;)\n\n  GC_ASSERT((suspend_cnt & 1) != 0);\n  DISABLE_CANCEL(cancel_state);\n#      ifdef DEBUG_THREADS\n  GC_log_printf(\"Suspend self: %p\\n\", THREAD_ID_TO_VPTR(me->id));\n#      endif\n  while (ao_load_acquire_async(&me->ext_suspend_cnt) == suspend_cnt) {\n    /* TODO: Use `sigsuspend()` even for self-suspended threads. */\n    GC_brief_async_signal_safe_sleep();\n  }\n#      ifdef DEBUG_THREADS\n  GC_log_printf(\"Resume self: %p\\n\", THREAD_ID_TO_VPTR(me->id));\n#      endif\n  RESTORE_CANCEL(cancel_state);\n}\n\nGC_API void GC_CALL\nGC_suspend_thread(GC_SUSPEND_THREAD_ID thread)\n{\n  GC_thread t;\n  AO_t next_stop_count;\n  AO_t suspend_cnt;\n  IF_CANCEL(int cancel_state;)\n\n  LOCK();\n  t = GC_lookup_by_pthread((pthread_t)thread);\n  if (NULL == t) {\n    UNLOCK();\n    return;\n  }\n  suspend_cnt = t->ext_suspend_cnt;\n  if ((suspend_cnt & 1) != 0) /*< already suspended? */ {\n    GC_ASSERT(!THREAD_EQUAL((pthread_t)thread, pthread_self()));\n    UNLOCK();\n    return;\n  }\n  if ((t->flags & (FINISHED | DO_BLOCKING)) != 0) {\n    t->ext_suspend_cnt = suspend_cnt | 1; /*< suspend */\n    /* Terminated but not joined yet, or in do-blocking state. */\n    UNLOCK();\n    return;\n  }\n\n  if (THREAD_EQUAL((pthread_t)thread, pthread_self())) {\n    t->ext_suspend_cnt = suspend_cnt | 1;\n    GC_with_callee_saves_pushed(GC_suspend_self_blocked, (ptr_t)t);\n    UNLOCK();\n    return;\n  }\n\n  /* `GC_suspend_thread()` is not a cancellation point. */\n  DISABLE_CANCEL(cancel_state);\n#      ifdef PARALLEL_MARK\n  /*\n   * Ensure we do not suspend a thread while it is rebuilding a free list,\n   * otherwise such a deadlock is possible:\n   *   - thread 1 is blocked in `GC_wait_for_reclaim` holding the allocator\n   *     lock;\n   *   - thread 2 is suspended in `GC_reclaim_generic` invoked from\n   *     `GC_generic_malloc_many` (with `GC_fl_builder_count` greater than\n   *     zero);\n   *   - thread 3 is blocked acquiring the allocator lock in\n   *     `GC_resume_thread`.\n   */\n  if (GC_parallel)\n    GC_wait_for_reclaim();\n#      endif\n\n  if (GC_manual_vdb) {\n    /* See the relevant comment in `GC_stop_world()`. */\n    GC_acquire_dirty_lock();\n  }\n  /*\n   * Else do not acquire the dirty lock as the write fault handler\n   * might be trying to acquire it too, and the suspend handler\n   * execution is deferred until the write fault handler completes.\n   */\n\n  next_stop_count = GC_stop_count + THREAD_RESTARTED;\n  GC_ASSERT((next_stop_count & THREAD_RESTARTED) == 0);\n  AO_store(&GC_stop_count, next_stop_count);\n\n  /* Set the flag making the change visible to the signal handler. */\n  AO_store_release(&t->ext_suspend_cnt, suspend_cnt | 1);\n\n  /* TODO: Support `GC_retry_signals` (not needed for TSan). */\n  switch (raise_signal(t, GC_sig_suspend)) {\n  /* `ESRCH` cannot happen as terminated threads are handled above. */\n  case 0:\n    break;\n  default:\n    ABORT(\"pthread_kill failed\");\n  }\n\n  /*\n   * Wait for the thread to complete threads table lookup and\n   * `stack_ptr` assignment.\n   */\n  GC_ASSERT(GC_thr_initialized);\n  suspend_restart_barrier(1);\n  if (GC_manual_vdb)\n    GC_release_dirty_lock();\n  AO_store(&GC_stop_count, next_stop_count | THREAD_RESTARTED);\n\n  RESTORE_CANCEL(cancel_state);\n  UNLOCK();\n}\n\nGC_API void GC_CALL\nGC_resume_thread(GC_SUSPEND_THREAD_ID thread)\n{\n  GC_thread t;\n\n  LOCK();\n  t = GC_lookup_by_pthread((pthread_t)thread);\n  if (t != NULL) {\n    AO_t suspend_cnt = t->ext_suspend_cnt;\n\n    if ((suspend_cnt & 1) != 0) { /*< is suspended? */\n      GC_ASSERT((GC_stop_count & THREAD_RESTARTED) != 0);\n      /* Mark the thread as not suspended - it will be resumed shortly. */\n      AO_store(&t->ext_suspend_cnt, suspend_cnt + 1);\n\n      if ((t->flags & (FINISHED | DO_BLOCKING)) == 0) {\n        int result = raise_signal(t, GC_sig_thr_restart);\n\n        /* TODO: Support signal resending on `GC_retry_signals`. */\n        if (result != 0)\n          ABORT_ARG1(\"pthread_kill failed in GC_resume_thread\",\n                     \": errcode= %d\", result);\n#      ifndef GC_NETBSD_THREADS_WORKAROUND\n        if (GC_retry_signals || GC_sig_suspend == GC_sig_thr_restart)\n#      endif\n        {\n          IF_CANCEL(int cancel_state;)\n\n          DISABLE_CANCEL(cancel_state);\n          suspend_restart_barrier(1);\n          RESTORE_CANCEL(cancel_state);\n        }\n      }\n    }\n  }\n  UNLOCK();\n}\n\nGC_API int GC_CALL\nGC_is_thread_suspended(GC_SUSPEND_THREAD_ID thread)\n{\n  GC_thread t;\n  int is_suspended = 0;\n\n  READER_LOCK();\n  t = GC_lookup_by_pthread((pthread_t)thread);\n  if (t != NULL && (t->ext_suspend_cnt & 1) != 0)\n    is_suspended = (int)TRUE;\n  READER_UNLOCK();\n  return is_suspended;\n}\n#    endif /* GC_ENABLE_SUSPEND_THREAD */\n\n#    undef ao_cptr_store_async\n#    undef ao_load_acquire_async\n#    undef ao_load_async\n#    undef ao_store_release_async\n#  endif /* !NACL */\n\nGC_INNER void\nGC_push_all_stacks(void)\n{\n  GC_bool found_me = FALSE;\n  size_t nthreads = 0;\n  int i;\n  GC_thread p;\n  ptr_t lo; /*< stack top (`sp`) */\n  ptr_t hi; /*< bottom */\n#  if defined(E2K) || defined(IA64)\n  /* We also need to scan the register backing store. */\n  ptr_t bs_lo, bs_hi;\n#  endif\n  struct GC_traced_stack_sect_s *traced_stack_sect;\n  pthread_t self = pthread_self();\n  word total_size = 0;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_thr_initialized);\n#  ifdef DEBUG_THREADS\n  GC_log_printf(\"Pushing stacks from thread %p\\n\", PTHREAD_TO_VPTR(self));\n#  endif\n  for (i = 0; i < THREAD_TABLE_SZ; i++) {\n    for (p = GC_threads[i]; p != NULL; p = p->tm.next) {\n#  if defined(E2K) || defined(IA64)\n      GC_bool is_self = FALSE;\n#  endif\n      GC_stack_context_t crtn = p->crtn;\n\n      GC_ASSERT(THREAD_TABLE_INDEX(p->id) == i);\n      if (KNOWN_FINISHED(p))\n        continue;\n      ++nthreads;\n      traced_stack_sect = crtn->traced_stack_sect;\n      if (THREAD_EQUAL(p->id, self)) {\n        GC_ASSERT((p->flags & DO_BLOCKING) == 0);\n#  ifdef SPARC\n        lo = GC_save_regs_in_stack();\n#  else\n        lo = GC_approx_sp();\n#    ifdef IA64\n        bs_hi = GC_save_regs_in_stack();\n#    elif defined(E2K)\n        {\n          size_t stack_size;\n\n          GC_ASSERT(NULL == crtn->backing_store_end);\n          GET_PROCEDURE_STACK_LOCAL(crtn->ps_ofs, &bs_lo, &stack_size);\n          bs_hi = bs_lo + stack_size;\n        }\n#    endif\n#  endif\n        found_me = TRUE;\n#  if defined(E2K) || defined(IA64)\n        is_self = TRUE;\n#  endif\n      } else {\n        lo = GC_cptr_load(&crtn->stack_ptr);\n#  ifdef IA64\n        bs_hi = crtn->backing_store_ptr;\n#  elif defined(E2K)\n        bs_lo = crtn->backing_store_end;\n        bs_hi = crtn->backing_store_ptr;\n#  endif\n        if (traced_stack_sect != NULL\n            && traced_stack_sect->saved_stack_ptr == lo) {\n          /*\n           * If the thread has never been stopped since the recent\n           * `GC_call_with_gc_active` invocation, then skip the top\n           * \"stack section\" as `stack_ptr` already points to.\n           */\n          traced_stack_sect = traced_stack_sect->prev;\n        }\n      }\n      hi = crtn->stack_end;\n#  ifdef IA64\n      bs_lo = crtn->backing_store_end;\n#  endif\n#  ifdef DEBUG_THREADS\n#    ifdef STACK_GROWS_UP\n      GC_log_printf(\"Stack for thread %p is (%p,%p]\\n\",\n                    THREAD_ID_TO_VPTR(p->id), (void *)hi, (void *)lo);\n#    else\n      GC_log_printf(\"Stack for thread %p is [%p,%p)\\n\",\n                    THREAD_ID_TO_VPTR(p->id), (void *)lo, (void *)hi);\n#    endif\n#  endif\n      if (NULL == lo)\n        ABORT(\"GC_push_all_stacks: sp not set!\");\n      if (crtn->altstack != NULL && ADDR_GE(lo, crtn->altstack)\n          && ADDR_GE(crtn->altstack + crtn->altstack_size, lo)) {\n#  ifdef STACK_GROWS_UP\n        hi = crtn->altstack;\n#  else\n        hi = crtn->altstack + crtn->altstack_size;\n#  endif\n        /* FIXME: Need to scan the normal stack too, but how? */\n      }\n#  ifdef STACKPTR_CORRECTOR_AVAILABLE\n      if (GC_sp_corrector != 0)\n        GC_sp_corrector((void **)&lo, THREAD_ID_TO_VPTR(p->id));\n#  endif\n      GC_push_all_stack_sections(lo, hi, traced_stack_sect);\n#  ifdef STACK_GROWS_UP\n      total_size += lo - hi;\n#  else\n      total_size += hi - lo; /*< `lo` is not greater than `hi` */\n#  endif\n#  ifdef NACL\n      /* Push `reg_storage` as roots, this will cover the reg context. */\n      GC_push_all_stack((ptr_t)p->reg_storage,\n                        (ptr_t)(p->reg_storage + NACL_GC_REG_STORAGE_SIZE));\n      total_size += NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t);\n#  endif\n#  ifdef E2K\n      if ((GC_stop_count & THREAD_RESTARTED) != 0\n#    ifdef GC_ENABLE_SUSPEND_THREAD\n          && (p->ext_suspend_cnt & 1) == 0\n#    endif\n          && !is_self && (p->flags & DO_BLOCKING) == 0) {\n        /* Procedure stack buffer has already been freed. */\n        continue;\n      }\n#  endif\n#  if defined(E2K) || defined(IA64)\n#    ifdef DEBUG_THREADS\n      GC_log_printf(\"Reg stack for thread %p is [%p,%p)\\n\",\n                    THREAD_ID_TO_VPTR(p->id), (void *)bs_lo, (void *)bs_hi);\n#    endif\n      GC_ASSERT(bs_lo != NULL && bs_hi != NULL);\n      /*\n       * FIXME: This (if `is_self`) may add an unbounded number of entries,\n       * and hence overflow the mark stack, which is bad.\n       */\n#    ifdef IA64\n      GC_push_all_register_sections(bs_lo, bs_hi, is_self, traced_stack_sect);\n#    else\n      if (is_self) {\n        GC_push_all_eager(bs_lo, bs_hi);\n      } else {\n        GC_push_all_stack(bs_lo, bs_hi);\n      }\n#    endif\n      total_size += bs_hi - bs_lo; /*< `bs_lo` is not greater than `bs_hi` */\n#  endif\n    }\n  }\n  GC_VERBOSE_LOG_PRINTF(\"Pushed %d thread stacks\\n\", (int)nthreads);\n  if (!found_me && !GC_in_thread_creation)\n    ABORT(\"Collecting from unknown thread\");\n  GC_total_stacksize = total_size;\n}\n\n#  ifdef DEBUG_THREADS\n/*\n * There seems to be a very rare thread stopping problem.\n * To help us debug that, we save the ids of the stopping thread.\n */\npthread_t GC_stopping_thread;\nint GC_stopping_pid = 0;\n#  endif\n\n/*\n * Suspend all threads that might still be running.  Return the number\n * of suspend signals that were sent.\n */\nSTATIC int\nGC_suspend_all(void)\n{\n  int n_live_threads = 0;\n  int i;\n#  ifndef NACL\n  GC_thread p;\n  pthread_t self = pthread_self();\n  int result;\n\n  GC_ASSERT((GC_stop_count & THREAD_RESTARTED) == 0);\n  GC_ASSERT(I_HOLD_LOCK());\n  for (i = 0; i < THREAD_TABLE_SZ; i++) {\n    for (p = GC_threads[i]; p != NULL; p = p->tm.next) {\n      if (!THREAD_EQUAL(p->id, self)) {\n        if ((p->flags & (FINISHED | DO_BLOCKING)) != 0)\n          continue;\n#    ifdef GC_ENABLE_SUSPEND_THREAD\n        if ((p->ext_suspend_cnt & 1) != 0)\n          continue;\n#    endif\n        if (AO_load(&p->last_stop_count) == GC_stop_count) {\n          /* Matters only if `GC_retry_signals`. */\n          continue;\n        }\n        n_live_threads++;\n#    ifdef DEBUG_THREADS\n        GC_log_printf(\"Sending suspend signal to %p\\n\",\n                      THREAD_ID_TO_VPTR(p->id));\n#    endif\n\n        /*\n         * The synchronization between `GC_dirty` (based on test-and-set)\n         * and the signal-based thread suspension is performed in\n         * `GC_stop_world()` because `GC_release_dirty_lock()` cannot be\n         * called before acknowledging that the thread is really suspended.\n         */\n        result = raise_signal(p, GC_sig_suspend);\n        switch (result) {\n        case ESRCH:\n          /* Not really there anymore.  Possible? */\n          n_live_threads--;\n          break;\n        case 0:\n          if (GC_on_thread_event) {\n            /* Note: thread id might be truncated. */\n            GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED,\n                               THREAD_ID_TO_VPTR(THREAD_SYSTEM_ID(p)));\n          }\n          break;\n        default:\n          ABORT_ARG1(\"pthread_kill failed at suspend\", \": errcode= %d\",\n                     result);\n        }\n      }\n    }\n  }\n\n#  else /* NACL */\n#    ifndef NACL_PARK_WAIT_USEC\n#      define NACL_PARK_WAIT_USEC 100 /* us */\n#    endif\n  unsigned long num_sleeps = 0;\n\n  GC_ASSERT(I_HOLD_LOCK());\n#    ifdef DEBUG_THREADS\n  GC_log_printf(\"pthread_stop_world: number of threads: %d\\n\",\n                GC_nacl_num_gc_threads - 1);\n#    endif\n  GC_nacl_thread_parker = pthread_self();\n  GC_nacl_park_threads_now = 1;\n\n  if (GC_manual_vdb)\n    GC_acquire_dirty_lock();\n  for (;;) {\n    int num_threads_parked = 0;\n    int num_used = 0;\n\n    /* Check the \"parked\" flag for each thread the collector knows about. */\n    for (i = 0; i < MAX_NACL_GC_THREADS && num_used < GC_nacl_num_gc_threads;\n         i++) {\n      if (GC_nacl_thread_used[i] == 1) {\n        num_used++;\n        if (GC_nacl_thread_parked[i] == 1) {\n          num_threads_parked++;\n          if (GC_on_thread_event)\n            GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED, NUMERIC_TO_VPTR(i));\n        }\n      }\n    }\n    /* Note: -1 for the current thread. */\n    if (num_threads_parked >= GC_nacl_num_gc_threads - 1)\n      break;\n#    ifdef DEBUG_THREADS\n    GC_log_printf(\"Sleep waiting for %d threads to park...\\n\",\n                  GC_nacl_num_gc_threads - num_threads_parked - 1);\n#    endif\n    GC_usleep(NACL_PARK_WAIT_USEC);\n    if (++num_sleeps > (1000 * 1000) / NACL_PARK_WAIT_USEC) {\n      WARN(\"GC appears stalled waiting for %\" WARN_PRIdPTR\n           \" threads to park...\\n\",\n           GC_nacl_num_gc_threads - num_threads_parked - 1);\n      num_sleeps = 0;\n    }\n  }\n  if (GC_manual_vdb)\n    GC_release_dirty_lock();\n#  endif /* NACL */\n  return n_live_threads;\n}\n\nGC_INNER void\nGC_stop_world(void)\n{\n#  ifndef NACL\n  int n_live_threads;\n#  endif\n  GC_ASSERT(I_HOLD_LOCK());\n  /*\n   * Make sure all free list construction has stopped before we start.\n   * No new construction can start, since it is required to acquire and\n   * release the allocator lock before start.\n   */\n\n  GC_ASSERT(GC_thr_initialized);\n#  ifdef DEBUG_THREADS\n  GC_stopping_thread = pthread_self();\n  GC_stopping_pid = getpid();\n  GC_log_printf(\"Stopping the world from %p\\n\",\n                PTHREAD_TO_VPTR(GC_stopping_thread));\n#  endif\n#  ifdef PARALLEL_MARK\n  if (GC_parallel) {\n    GC_acquire_mark_lock();\n    GC_ASSERT(GC_fl_builder_count == 0);\n    /* We should have previously waited for it to become zero. */\n  }\n#  endif /* PARALLEL_MARK */\n\n#  ifdef NACL\n  (void)GC_suspend_all();\n#  else\n  /* Note: only concurrent reads are possible. */\n  AO_store(&GC_stop_count, GC_stop_count + THREAD_RESTARTED);\n  if (GC_manual_vdb) {\n    GC_acquire_dirty_lock();\n    /*\n     * The write fault handler cannot be called if `GC_manual_vdb` (thus\n     * double-locking should not occur in `async_set_pht_entry_from_index`\n     * based on test-and-set).\n     */\n  }\n  n_live_threads = GC_suspend_all();\n  if (GC_retry_signals) {\n    resend_lost_signals_retry(n_live_threads, GC_suspend_all);\n  } else {\n    suspend_restart_barrier(n_live_threads);\n  }\n  if (GC_manual_vdb) {\n    /* Note: cannot be done in `GC_suspend_all`. */\n    GC_release_dirty_lock();\n  }\n#  endif\n\n#  ifdef PARALLEL_MARK\n  if (GC_parallel)\n    GC_release_mark_lock();\n#  endif\n#  ifdef DEBUG_THREADS\n  GC_log_printf(\"World stopped from %p\\n\", PTHREAD_TO_VPTR(pthread_self()));\n  GC_stopping_thread = 0;\n#  endif\n}\n\n#  ifdef NACL\n#    if defined(__x86_64__)\n#      define NACL_STORE_REGS()                                 \\\n        do {                                                    \\\n          __asm__ __volatile__(\"push %rbx\");                    \\\n          __asm__ __volatile__(\"push %rbp\");                    \\\n          __asm__ __volatile__(\"push %r12\");                    \\\n          __asm__ __volatile__(\"push %r13\");                    \\\n          __asm__ __volatile__(\"push %r14\");                    \\\n          __asm__ __volatile__(\"push %r15\");                    \\\n          __asm__ __volatile__(                                 \\\n              \"mov %%esp, %0\"                                   \\\n              : \"=m\"(GC_nacl_gc_thread_self->crtn->stack_ptr)); \\\n          BCOPY(GC_nacl_gc_thread_self->crtn->stack_ptr,        \\\n                GC_nacl_gc_thread_self->reg_storage,            \\\n                NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));      \\\n          __asm__ __volatile__(\"naclasp $48, %r15\");            \\\n        } while (0)\n#    elif defined(__i386__)\n#      define NACL_STORE_REGS()                                 \\\n        do {                                                    \\\n          __asm__ __volatile__(\"push %ebx\");                    \\\n          __asm__ __volatile__(\"push %ebp\");                    \\\n          __asm__ __volatile__(\"push %esi\");                    \\\n          __asm__ __volatile__(\"push %edi\");                    \\\n          __asm__ __volatile__(                                 \\\n              \"mov %%esp, %0\"                                   \\\n              : \"=m\"(GC_nacl_gc_thread_self->crtn->stack_ptr)); \\\n          BCOPY(GC_nacl_gc_thread_self->crtn->stack_ptr,        \\\n                GC_nacl_gc_thread_self->reg_storage,            \\\n                NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));      \\\n          __asm__ __volatile__(\"add $16, %esp\");                \\\n        } while (0)\n#    elif defined(__arm__)\n#      define NACL_STORE_REGS()                                 \\\n        do {                                                    \\\n          __asm__ __volatile__(\"push {r4-r8,r10-r12,lr}\");      \\\n          __asm__ __volatile__(                                 \\\n              \"mov r0, %0\"                                      \\\n              :                                                 \\\n              : \"r\"(&GC_nacl_gc_thread_self->crtn->stack_ptr)); \\\n          __asm__ __volatile__(\"bic r0, r0, #0xc0000000\");      \\\n          __asm__ __volatile__(\"str sp, [r0]\");                 \\\n          BCOPY(GC_nacl_gc_thread_self->crtn->stack_ptr,        \\\n                GC_nacl_gc_thread_self->reg_storage,            \\\n                NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));      \\\n          __asm__ __volatile__(\"add sp, sp, #40\");              \\\n          __asm__ __volatile__(\"bic sp, sp, #0xc0000000\");      \\\n        } while (0)\n#    else\n#      error TODO Please port NACL_STORE_REGS\n#    endif\n\nGC_API_OSCALL void\nnacl_pre_syscall_hook(void)\n{\n  if (GC_nacl_thread_idx != -1) {\n    NACL_STORE_REGS();\n    GC_nacl_gc_thread_self->crtn->stack_ptr = GC_approx_sp();\n    GC_nacl_thread_parked[GC_nacl_thread_idx] = 1;\n  }\n}\n\nGC_API_OSCALL void\n__nacl_suspend_thread_if_needed(void)\n{\n  if (!GC_nacl_park_threads_now)\n    return;\n\n  /* Do not try to park the thread parker. */\n  if (GC_nacl_thread_parker == pthread_self())\n    return;\n\n  /*\n   * This can happen when a thread is created outside of the collector\n   * system (`wthread` mostly).\n   */\n  if (GC_nacl_thread_idx < 0)\n    return;\n\n  /*\n   * If it was already \"parked\", we are returning from a `syscall`,\n   * so do not bother storing registers again, the collector has a set of.\n   */\n  if (!GC_nacl_thread_parked[GC_nacl_thread_idx]) {\n    NACL_STORE_REGS();\n    GC_nacl_gc_thread_self->crtn->stack_ptr = GC_approx_sp();\n  }\n  GC_nacl_thread_parked[GC_nacl_thread_idx] = 1;\n  while (GC_nacl_park_threads_now) {\n    /* Just spin. */\n  }\n  GC_nacl_thread_parked[GC_nacl_thread_idx] = 0;\n\n  /* Clear out the `reg_storage` for the next suspend. */\n  BZERO(GC_nacl_gc_thread_self->reg_storage,\n        NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));\n}\n\nGC_API_OSCALL void\nnacl_post_syscall_hook(void)\n{\n  /*\n   * Calling `__nacl_suspend_thread_if_needed` right away should guarantee\n   * we do not mutate the collector set.\n   */\n  __nacl_suspend_thread_if_needed();\n  if (GC_nacl_thread_idx != -1) {\n    GC_nacl_thread_parked[GC_nacl_thread_idx] = 0;\n  }\n}\n\nSTATIC GC_bool GC_nacl_thread_parking_inited = FALSE;\nSTATIC pthread_mutex_t GC_nacl_thread_alloc_lock = PTHREAD_MUTEX_INITIALIZER;\n\nstruct nacl_irt_blockhook {\n  int (*register_block_hooks)(void (*pre)(void), void (*post)(void));\n};\n\nEXTERN_C_BEGIN\nextern size_t nacl_interface_query(const char *interface_ident, void *table,\n                                   size_t tablesize);\nEXTERN_C_END\n\nGC_INNER void\nGC_nacl_initialize_gc_thread(GC_thread me)\n{\n  int i;\n  static struct nacl_irt_blockhook gc_hook;\n\n  GC_ASSERT(NULL == GC_nacl_gc_thread_self);\n  GC_nacl_gc_thread_self = me;\n  pthread_mutex_lock(&GC_nacl_thread_alloc_lock);\n  if (UNLIKELY(!GC_nacl_thread_parking_inited)) {\n    BZERO(GC_nacl_thread_parked, sizeof(GC_nacl_thread_parked));\n    BZERO(GC_nacl_thread_used, sizeof(GC_nacl_thread_used));\n    /*\n     * TODO: Replace with the public \"register hook\" function when\n     * available from `glibc`.\n     */\n    nacl_interface_query(\"nacl-irt-blockhook-0.1\", &gc_hook, sizeof(gc_hook));\n    gc_hook.register_block_hooks(nacl_pre_syscall_hook,\n                                 nacl_post_syscall_hook);\n    GC_nacl_thread_parking_inited = TRUE;\n  }\n  GC_ASSERT(GC_nacl_num_gc_threads <= MAX_NACL_GC_THREADS);\n  for (i = 0; i < MAX_NACL_GC_THREADS; i++) {\n    if (GC_nacl_thread_used[i] == 0) {\n      GC_nacl_thread_used[i] = 1;\n      GC_nacl_thread_idx = i;\n      GC_nacl_num_gc_threads++;\n      break;\n    }\n  }\n  pthread_mutex_unlock(&GC_nacl_thread_alloc_lock);\n}\n\nGC_INNER void\nGC_nacl_shutdown_gc_thread(void)\n{\n  GC_ASSERT(GC_nacl_gc_thread_self != NULL);\n  pthread_mutex_lock(&GC_nacl_thread_alloc_lock);\n  GC_ASSERT(GC_nacl_thread_idx >= 0);\n  GC_ASSERT(GC_nacl_thread_idx < MAX_NACL_GC_THREADS);\n  GC_ASSERT(GC_nacl_thread_used[GC_nacl_thread_idx] != 0);\n  GC_nacl_thread_used[GC_nacl_thread_idx] = 0;\n  GC_nacl_thread_idx = -1;\n  GC_nacl_num_gc_threads--;\n  pthread_mutex_unlock(&GC_nacl_thread_alloc_lock);\n  GC_nacl_gc_thread_self = NULL;\n}\n\n#  else /* !NACL */\n\nstatic GC_bool in_resend_restart_signals;\n\n/*\n * Restart all threads that were suspended by the collector.\n * Return the number of restart signals that were sent.\n */\nSTATIC int\nGC_restart_all(void)\n{\n  int n_live_threads = 0;\n  int i;\n  pthread_t self = pthread_self();\n  GC_thread p;\n  int result;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT((GC_stop_count & THREAD_RESTARTED) != 0);\n  for (i = 0; i < THREAD_TABLE_SZ; i++) {\n    for (p = GC_threads[i]; p != NULL; p = p->tm.next) {\n      if (!THREAD_EQUAL(p->id, self)) {\n        if ((p->flags & (FINISHED | DO_BLOCKING)) != 0)\n          continue;\n#    ifdef GC_ENABLE_SUSPEND_THREAD\n        if ((p->ext_suspend_cnt & 1) != 0)\n          continue;\n#    endif\n        if (GC_retry_signals\n            && AO_load(&p->last_stop_count) == GC_stop_count) {\n          /* The thread has been restarted. */\n          if (!in_resend_restart_signals) {\n            /*\n             * Some user signal (which we do not block, e.g. `SIGQUIT`)\n             * has already restarted the thread, but nonetheless we need to\n             * count the latter in `n_live_threads`, so that to decrement\n             * the semaphore's value proper amount of times.  (We are also\n             * sending the restart signal to the thread, it is not needed\n             * actually but does not hurt.)\n             */\n          } else {\n            continue;\n            /*\n             * FIXME: Still, an extremely low chance exists that the user\n             * signal restarts the thread after the restart signal has been\n             * lost (causing `sem_timedwait()` to fail) while retrying,\n             * causing finally a mismatch between `GC_suspend_ack_sem` and\n             * `n_live_threads`.\n             */\n          }\n        }\n        n_live_threads++;\n#    ifdef DEBUG_THREADS\n        GC_log_printf(\"Sending restart signal to %p\\n\",\n                      THREAD_ID_TO_VPTR(p->id));\n#    endif\n        result = raise_signal(p, GC_sig_thr_restart);\n        switch (result) {\n        case ESRCH:\n          /* Not really there anymore.  Possible? */\n          n_live_threads--;\n          break;\n        case 0:\n          if (GC_on_thread_event)\n            GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED,\n                               THREAD_ID_TO_VPTR(THREAD_SYSTEM_ID(p)));\n          break;\n        default:\n          ABORT_ARG1(\"pthread_kill failed at resume\", \": errcode= %d\", result);\n        }\n      }\n    }\n  }\n  return n_live_threads;\n}\n#  endif /* !NACL */\n\nGC_INNER void\nGC_start_world(void)\n{\n#  ifndef NACL\n  int n_live_threads;\n\n  /* The allocator lock is held continuously since the world stopped. */\n  GC_ASSERT(I_HOLD_LOCK());\n\n#    ifdef DEBUG_THREADS\n  GC_log_printf(\"World starting\\n\");\n#    endif\n  /*\n   * Note: the updated value should now be visible to the signal handler\n   * (note that `pthread_kill` is not on the list of functions that\n   * synchronize memory).\n   */\n  AO_store_release(&GC_stop_count, GC_stop_count + THREAD_RESTARTED);\n\n  GC_ASSERT(!in_resend_restart_signals);\n  n_live_threads = GC_restart_all();\n  if (GC_retry_signals) {\n    in_resend_restart_signals = TRUE;\n    resend_lost_signals_retry(n_live_threads, GC_restart_all);\n    in_resend_restart_signals = FALSE;\n  } else {\n#    ifndef GC_NETBSD_THREADS_WORKAROUND\n    if (GC_sig_suspend == GC_sig_thr_restart)\n#    endif\n    {\n      suspend_restart_barrier(n_live_threads);\n    }\n  }\n#    ifdef DEBUG_THREADS\n  GC_log_printf(\"World started\\n\");\n#    endif\n#  else /* NACL */\n#    ifdef DEBUG_THREADS\n  GC_log_printf(\"World starting...\\n\");\n#    endif\n  GC_nacl_park_threads_now = 0;\n  if (GC_on_thread_event) {\n    GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, NULL);\n    /* TODO: Send event for every unsuspended thread. */\n  }\n#  endif\n}\n\nGC_INNER void\nGC_stop_init(void)\n{\n#  ifndef NACL\n  struct sigaction act;\n  char *str;\n\n  if (SIGNAL_UNSET == GC_sig_suspend)\n    GC_sig_suspend = SIG_SUSPEND;\n  if (SIGNAL_UNSET == GC_sig_thr_restart)\n    GC_sig_thr_restart = SIG_THR_RESTART;\n\n  if (sem_init(&GC_suspend_ack_sem, GC_SEM_INIT_PSHARED, 0) == -1)\n    ABORT(\"sem_init failed\");\n  GC_stop_count = THREAD_RESTARTED; /*< i.e. the world is not stopped */\n\n  if (sigfillset(&act.sa_mask) != 0) {\n    ABORT(\"sigfillset failed\");\n  }\n#    ifdef RTEMS\n  if (sigprocmask(SIG_UNBLOCK, &act.sa_mask, NULL) != 0) {\n    ABORT(\"sigprocmask failed\");\n  }\n#    endif\n  GC_remove_allowed_signals(&act.sa_mask);\n  /*\n   * `GC_sig_thr_restart` is set in the resulting mask.\n   * It is unmasked by the handler when necessary.\n   */\n\n#    ifdef SA_RESTART\n  act.sa_flags = SA_RESTART;\n#    else\n  act.sa_flags = 0;\n#    endif\n#    ifdef SUSPEND_HANDLER_NO_CONTEXT\n  act.sa_handler = GC_suspend_handler;\n#    else\n  act.sa_flags |= SA_SIGINFO;\n  act.sa_sigaction = GC_suspend_sigaction;\n#    endif\n  /* `act.sa_restorer` is deprecated and should not be initialized. */\n  if (sigaction(GC_sig_suspend, &act, NULL) != 0) {\n    ABORT(\"Cannot set SIG_SUSPEND handler\");\n  }\n\n  if (GC_sig_suspend != GC_sig_thr_restart) {\n#    ifndef SUSPEND_HANDLER_NO_CONTEXT\n    act.sa_flags &= ~SA_SIGINFO;\n#    endif\n    act.sa_handler = GC_restart_handler;\n    if (sigaction(GC_sig_thr_restart, &act, NULL) != 0)\n      ABORT(\"Cannot set SIG_THR_RESTART handler\");\n  } else {\n    GC_COND_LOG_PRINTF(\"Using same signal for suspend and restart\\n\");\n  }\n\n  /* Initialize `suspend_handler_mask` (excluding `GC_sig_thr_restart`). */\n  if (sigfillset(&suspend_handler_mask) != 0)\n    ABORT(\"sigfillset failed\");\n  GC_remove_allowed_signals(&suspend_handler_mask);\n  if (sigdelset(&suspend_handler_mask, GC_sig_thr_restart) != 0)\n    ABORT(\"sigdelset failed\");\n\n#    ifndef NO_RETRY_SIGNALS\n  /*\n   * Any platform could lose signals, so let's be conservative and\n   * always enable signals retry logic.\n   */\n  GC_retry_signals = TRUE;\n#    endif\n  /* Override the default value of `GC_retry_signals`. */\n  str = GETENV(\"GC_RETRY_SIGNALS\");\n  if (str != NULL) {\n    /* Do not retry if the environment variable is set to \"0\". */\n    GC_retry_signals = *str != '0' || *(str + 1) != '\\0';\n  }\n  if (GC_retry_signals) {\n    GC_COND_LOG_PRINTF(\n        \"Will retry suspend and restart signals if necessary\\n\");\n  }\n#    ifndef NO_SIGNALS_UNBLOCK_IN_MAIN\n  /* Explicitly unblock the signals once before new threads creation. */\n  GC_unblock_gc_signals();\n#    endif\n#  endif /* !NACL */\n}\n\n#endif /* PTHREAD_STOP_WORLD_IMPL */\n\n#endif\n/*\n * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.\n * Copyright (c) 2000-2008 by Hewlett-Packard Company.  All rights reserved.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n/*\n * Support code originally for LinuxThreads, the `clone`-based kernel\n * thread package for Linux which is included in `libc6`.\n *\n * This code no doubt makes some assumptions beyond what is guaranteed by\n * the `pthreads` standard, though it now does very little of that.\n * It now also supports NPTL, and many other POSIX thread implementations.\n * We are trying to merge all flavors of `pthreads` support code into this\n * file.\n */\n\n#ifdef THREADS\n\n#  ifdef GC_PTHREADS\n#    if defined(DARWIN) \\\n        || (defined(GC_WIN32_THREADS) && defined(EMULATE_PTHREAD_SEMAPHORE))\n/*\n * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.\n * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.\n * All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n#ifndef GC_DARWIN_SEMAPHORE_H\n#define GC_DARWIN_SEMAPHORE_H\n\n\n/*\n * This is a very simple semaphore implementation based on `pthreads`.\n * It is not async-signal safe.  But this is not a problem because\n * signals are not used to suspend threads on the target.\n */\n\n#if !defined(DARWIN) && !defined(GC_WIN32_THREADS) || !defined(GC_PTHREADS)\n#  error darwin_semaphore.h included for improper target\n#endif\n\n#include <errno.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct {\n  pthread_mutex_t mutex;\n  pthread_cond_t cond;\n  int value;\n} sem_t;\n\nGC_INLINE int\nsem_init(sem_t *sem, int pshared, int value)\n{\n  int err;\n\n  if (UNLIKELY(pshared != 0)) {\n    errno = EPERM; /*< unsupported */\n    return -1;\n  }\n  sem->value = value;\n  err = pthread_mutex_init(&sem->mutex, NULL);\n  if (UNLIKELY(err != 0)) {\n    errno = err;\n    return -1;\n  }\n  err = pthread_cond_init(&sem->cond, NULL);\n  if (UNLIKELY(err != 0)) {\n    (void)pthread_mutex_destroy(&sem->mutex);\n    errno = err;\n    return -1;\n  }\n  return 0;\n}\n\nGC_INLINE int\nsem_post(sem_t *sem)\n{\n  int err = pthread_mutex_lock(&sem->mutex);\n\n  if (UNLIKELY(err != 0)) {\n    errno = err;\n    return -1;\n  }\n  sem->value++;\n  err = pthread_cond_signal(&sem->cond);\n  if (UNLIKELY(err != 0)) {\n    (void)pthread_mutex_unlock(&sem->mutex);\n    errno = err;\n    return -1;\n  }\n  err = pthread_mutex_unlock(&sem->mutex);\n  if (UNLIKELY(err != 0)) {\n    errno = err;\n    return -1;\n  }\n  return 0;\n}\n\nGC_INLINE int\nsem_wait(sem_t *sem)\n{\n  int err = pthread_mutex_lock(&sem->mutex);\n\n  if (UNLIKELY(err != 0)) {\n    errno = err;\n    return -1;\n  }\n  while (0 == sem->value) {\n    err = pthread_cond_wait(&sem->cond, &sem->mutex);\n    if (UNLIKELY(err != 0)) {\n      (void)pthread_mutex_unlock(&sem->mutex);\n      errno = err;\n      return -1;\n    }\n  }\n  sem->value--;\n  err = pthread_mutex_unlock(&sem->mutex);\n  if (UNLIKELY(err != 0)) {\n    errno = err;\n    return -1;\n  }\n  return 0;\n}\n\nGC_INLINE int\nsem_destroy(sem_t *sem)\n{\n  int err = pthread_cond_destroy(&sem->cond);\n\n  if (UNLIKELY(err != 0)) {\n    errno = err;\n    return -1;\n  }\n  err = pthread_mutex_destroy(&sem->mutex);\n  if (UNLIKELY(err != 0)) {\n    errno = err;\n    return -1;\n  }\n  return 0;\n}\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#endif\n\n#    elif !defined(PLATFORM_THREADS) && !defined(SN_TARGET_PSP2)\n#      include <semaphore.h>\n#    endif\n#    include <errno.h>\n#  endif /* GC_PTHREADS */\n\n#  if !defined(GC_WIN32_THREADS)\n#    include <sched.h>\n#    include <time.h>\n#    if !defined(PLATFORM_THREADS) && !defined(SN_TARGET_PSP2)\n#      ifndef RTEMS\n#        include <sys/mman.h>\n#      endif\n#      include <fcntl.h>\n#      include <sys/stat.h>\n#      include <sys/time.h>\n#    endif\n#    if defined(GC_EXPLICIT_SIGNALS_UNBLOCK) \\\n        || !defined(GC_NO_PTHREAD_SIGMASK)   \\\n        || (defined(GC_PTHREADS_PARAMARK)    \\\n            && !defined(NO_MARKER_SPECIAL_SIGMASK))\n#      include <signal.h>\n#    endif\n#  endif /* !GC_WIN32_THREADS */\n\n#  ifdef E2K\n#    include <alloca.h>\n#  endif\n\n#  if defined(DARWIN) || defined(ANY_BSD)\n#    if defined(NETBSD) || defined(OPENBSD)\n#      include <sys/param.h>\n#    endif\n#    include <sys/sysctl.h>\n#  elif defined(DGUX)\n#    include <sys/_int_psem.h>\n#    include <sys/dg_sys_info.h>\n/* Note: `sem_t` is `uint` in DG/UX. */\ntypedef unsigned int sem_t;\n#  endif\n\n#  if defined(GC_PTHREADS) && !defined(PLATFORM_THREADS) \\\n      && !defined(SN_TARGET_PSP2)\n/* Undefine macros used to redirect `pthreads` primitives. */\n#    undef pthread_create\n#    ifndef GC_NO_PTHREAD_SIGMASK\n#      undef pthread_sigmask\n#    endif\n#    ifndef GC_NO_PTHREAD_CANCEL\n#      undef pthread_cancel\n#    endif\n#    ifdef GC_HAVE_PTHREAD_EXIT\n#      undef pthread_exit\n#    endif\n#    undef pthread_join\n#    undef pthread_detach\n#    if defined(OSF1) && defined(_PTHREAD_USE_MANGLED_NAMES_) \\\n        && !defined(_PTHREAD_USE_PTDNAM_)\n/* Restore the original mangled names on Tru64 UNIX. */\n#      define pthread_create __pthread_create\n#      define pthread_join __pthread_join\n#      define pthread_detach __pthread_detach\n#      ifndef GC_NO_PTHREAD_CANCEL\n#        define pthread_cancel __pthread_cancel\n#      endif\n#      ifdef GC_HAVE_PTHREAD_EXIT\n#        define pthread_exit __pthread_exit\n#      endif\n#    endif\n#  endif /* GC_PTHREADS */\n\n#  if !defined(GC_WIN32_THREADS) && !defined(PLATFORM_THREADS) \\\n      && !defined(SN_TARGET_PSP2)\n/* TODO: Enable `GC_USE_DLOPEN_WRAP` for Cygwin? */\n\n#    ifdef GC_USE_LD_WRAP\n#      define WRAP_FUNC(f) __wrap_##f\n#      define REAL_FUNC(f) __real_##f\nint REAL_FUNC(pthread_create)(pthread_t *,\n                              GC_PTHREAD_CREATE_CONST pthread_attr_t *,\n                              void *(*start_routine)(void *), void *);\nint REAL_FUNC(pthread_join)(pthread_t, void **);\nint REAL_FUNC(pthread_detach)(pthread_t);\n#      ifndef GC_NO_PTHREAD_SIGMASK\nint REAL_FUNC(pthread_sigmask)(int, const sigset_t *, sigset_t *);\n#      endif\n#      ifndef GC_NO_PTHREAD_CANCEL\nint REAL_FUNC(pthread_cancel)(pthread_t);\n#      endif\n#      ifdef GC_HAVE_PTHREAD_EXIT\nvoid REAL_FUNC(pthread_exit)(void *) GC_PTHREAD_EXIT_ATTRIBUTE;\n#      endif\n#    elif defined(GC_USE_DLOPEN_WRAP)\n#      include <dlfcn.h>\n#      define WRAP_FUNC(f) f\n#      define REAL_FUNC(f) GC_real_##f\n/*\n * We define both `GC_<fn>` and plain `fn` to be the wrapped function.\n * In that way plain calls work, as do calls from files that include\n * `gc.h` file which redefines `fn` to `GC_<fn>`.\n */\n/* FIXME: Needs work for `DARWIN` and True64 (`OSF1`). */\ntypedef int (*GC_pthread_create_t)(pthread_t *,\n                                   GC_PTHREAD_CREATE_CONST pthread_attr_t *,\n                                   void *(*)(void *), void *);\nstatic GC_pthread_create_t REAL_FUNC(pthread_create);\n#      ifndef GC_NO_PTHREAD_SIGMASK\ntypedef int (*GC_pthread_sigmask_t)(int, const sigset_t *, sigset_t *);\nstatic GC_pthread_sigmask_t REAL_FUNC(pthread_sigmask);\n#      endif\ntypedef int (*GC_pthread_join_t)(pthread_t, void **);\nstatic GC_pthread_join_t REAL_FUNC(pthread_join);\ntypedef int (*GC_pthread_detach_t)(pthread_t);\nstatic GC_pthread_detach_t REAL_FUNC(pthread_detach);\n#      ifndef GC_NO_PTHREAD_CANCEL\ntypedef int (*GC_pthread_cancel_t)(pthread_t);\nstatic GC_pthread_cancel_t REAL_FUNC(pthread_cancel);\n#      endif\n#      ifdef GC_HAVE_PTHREAD_EXIT\ntypedef void (*GC_pthread_exit_t)(void *) GC_PTHREAD_EXIT_ATTRIBUTE;\nstatic GC_pthread_exit_t REAL_FUNC(pthread_exit);\n#      endif\n#    else\n#      define WRAP_FUNC(f) GC_##f\n#      ifdef DGUX\n#        define REAL_FUNC(f) __d10_##f\n#      else\n#        define REAL_FUNC(f) f\n#      endif\n#    endif /* !GC_USE_LD_WRAP && !GC_USE_DLOPEN_WRAP */\n\n/*\n * Define `GC_` functions as aliases for the plain ones, which will\n * be intercepted.  This allows files that include `gc.h` file, and\n * hence generate references to the `GC_` symbols, to see the right ones.\n */\n#    if defined(GC_USE_LD_WRAP) || defined(GC_USE_DLOPEN_WRAP)\n\nGC_API int\nGC_pthread_create(pthread_t *t, GC_PTHREAD_CREATE_CONST pthread_attr_t *a,\n                  void *(*fn)(void *), void *arg)\n{\n  return pthread_create(t, a, fn, arg);\n}\n\n#      ifndef GC_NO_PTHREAD_SIGMASK\nGC_API int\nGC_pthread_sigmask(int how, const sigset_t *mask, sigset_t *old)\n{\n  return pthread_sigmask(how, mask, old);\n}\n#      endif /* !GC_NO_PTHREAD_SIGMASK */\n\nGC_API int\nGC_pthread_join(pthread_t t, void **res)\n{\n  return pthread_join(t, res);\n}\n\nGC_API int\nGC_pthread_detach(pthread_t t)\n{\n  return pthread_detach(t);\n}\n\n#      ifndef GC_NO_PTHREAD_CANCEL\nGC_API int\nGC_pthread_cancel(pthread_t t)\n{\n  return pthread_cancel(t);\n}\n#      endif /* !GC_NO_PTHREAD_CANCEL */\n\n#      ifdef GC_HAVE_PTHREAD_EXIT\nGC_API GC_PTHREAD_EXIT_ATTRIBUTE void\nGC_pthread_exit(void *retval)\n{\n  pthread_exit(retval);\n}\n#      endif\n#    endif /* GC_USE_LD_WRAP || GC_USE_DLOPEN_WRAP */\n\n#    ifdef GC_USE_DLOPEN_WRAP\n/*\n * Resolve a symbol with name `n` from the dynamic library (given by\n * handle `h`) and cast it to the given functional type `fn`.\n */\n#      define TYPED_DLSYM(fn, h, n) CAST_THRU_UINTPTR(fn, dlsym(h, n))\n\nSTATIC void\nGC_init_real_syms(void)\n{\n  void *dl_handle;\n\n  GC_ASSERT(!GC_syms_wrap_initialized);\n#      ifdef RTLD_NEXT\n  dl_handle = RTLD_NEXT;\n#      else\n  dl_handle = dlopen(\"libpthread.so.0\", RTLD_LAZY);\n  if (NULL == dl_handle) {\n    /* Retry without \".0\" suffix. */\n    dl_handle = dlopen(\"libpthread.so\", RTLD_LAZY);\n    if (NULL == dl_handle)\n      ABORT(\"Couldn't open libpthread\");\n  }\n#      endif\n  REAL_FUNC(pthread_create)\n      = TYPED_DLSYM(GC_pthread_create_t, dl_handle, \"pthread_create\");\n#      ifdef RTLD_NEXT\n  if (REAL_FUNC(pthread_create) == 0)\n    ABORT(\"pthread_create not found\"\n          \" (probably -lgc is specified after -lpthread)\");\n#      endif\n#      ifndef GC_NO_PTHREAD_SIGMASK\n  REAL_FUNC(pthread_sigmask)\n      = TYPED_DLSYM(GC_pthread_sigmask_t, dl_handle, \"pthread_sigmask\");\n#      endif\n  REAL_FUNC(pthread_join)\n      = TYPED_DLSYM(GC_pthread_join_t, dl_handle, \"pthread_join\");\n  REAL_FUNC(pthread_detach)\n      = TYPED_DLSYM(GC_pthread_detach_t, dl_handle, \"pthread_detach\");\n#      ifndef GC_NO_PTHREAD_CANCEL\n  REAL_FUNC(pthread_cancel)\n      = TYPED_DLSYM(GC_pthread_cancel_t, dl_handle, \"pthread_cancel\");\n#      endif\n#      ifdef GC_HAVE_PTHREAD_EXIT\n  REAL_FUNC(pthread_exit)\n      = TYPED_DLSYM(GC_pthread_exit_t, dl_handle, \"pthread_exit\");\n#      endif\n  GC_syms_wrap_initialized = TRUE;\n}\n\n#      define INIT_REAL_SYMS()                  \\\n        if (LIKELY(GC_syms_wrap_initialized)) { \\\n        } else                                  \\\n          GC_init_real_syms()\n#    else\n#      define INIT_REAL_SYMS() (void)0\n#    endif /* !GC_USE_DLOPEN_WRAP */\n\n#  else\n#    define WRAP_FUNC(f) GC_##f\n#    define REAL_FUNC(f) f\n#    define INIT_REAL_SYMS() (void)0\n#  endif /* GC_WIN32_THREADS */\n\n#  if defined(MPROTECT_VDB) && defined(DARWIN)\nGC_INNER int\nGC_inner_pthread_create(pthread_t *t,\n                        GC_PTHREAD_CREATE_CONST pthread_attr_t *a,\n                        void *(*fn)(void *), void *arg)\n{\n  INIT_REAL_SYMS();\n  return REAL_FUNC(pthread_create)(t, a, fn, arg);\n}\n#  endif\n\n#  ifdef THREAD_LOCAL_ALLOC\n\nGC_INNER void\nGC_mark_thread_local_free_lists(void)\n{\n  int i;\n  GC_thread p;\n\n  for (i = 0; i < THREAD_TABLE_SZ; ++i) {\n    for (p = GC_threads[i]; p != NULL; p = p->tm.next) {\n      if (!KNOWN_FINISHED(p))\n        GC_mark_thread_local_fls_for(&p->tlfs);\n    }\n  }\n}\n\n#    if defined(GC_ASSERTIONS)\n/*\n * Check that all thread-local free-lists are completely marked.\n * Also check that thread-specific-data structures are marked.\n */\nvoid\nGC_check_tls(void)\n{\n  int i;\n  GC_thread p;\n\n  for (i = 0; i < THREAD_TABLE_SZ; ++i) {\n    for (p = GC_threads[i]; p != NULL; p = p->tm.next) {\n      if (!KNOWN_FINISHED(p))\n        GC_check_tls_for(&p->tlfs);\n    }\n  }\n#      if defined(USE_CUSTOM_SPECIFIC)\n  if (GC_thread_key != 0)\n    GC_check_tsd_marks(GC_thread_key);\n#      endif\n}\n#    endif\n\n#  endif /* THREAD_LOCAL_ALLOC */\n\n#  ifdef GC_WIN32_THREADS\n/*\n * A macro for functions and variables that should be accessible\n * from `win32_threads.c` file but otherwise could be `static`.\n */\n#    define GC_INNER_WIN32THREAD GC_INNER\n#  else\n#    define GC_INNER_WIN32THREAD STATIC\n#  endif\n\n#  ifdef PARALLEL_MARK\n\n#    if defined(GC_WIN32_THREADS) || defined(USE_PROC_FOR_LIBRARIES) \\\n        || (defined(IA64)                                            \\\n            && (defined(HAVE_PTHREAD_ATTR_GET_NP)                    \\\n                || defined(HAVE_PTHREAD_GETATTR_NP)))\nGC_INNER_WIN32THREAD ptr_t GC_marker_sp[MAX_MARKERS - 1] = { 0 };\n#    endif /* GC_WIN32_THREADS || USE_PROC_FOR_LIBRARIES */\n\n#    if defined(IA64) && defined(USE_PROC_FOR_LIBRARIES)\nstatic ptr_t marker_bsp[MAX_MARKERS - 1] = { 0 };\n#    endif\n\n#    if defined(DARWIN) && !defined(GC_NO_THREADS_DISCOVERY)\nstatic mach_port_t marker_mach_threads[MAX_MARKERS - 1] = { 0 };\n\nGC_INNER GC_bool\nGC_is_mach_marker(thread_act_t thread)\n{\n  int i;\n  for (i = 0; i < GC_markers_m1; i++) {\n    if (marker_mach_threads[i] == thread)\n      return TRUE;\n  }\n  return FALSE;\n}\n#    endif /* DARWIN && !GC_NO_THREADS_DISCOVERY */\n\n#    ifdef HAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG\n/* For NetBSD. */\nstatic void\nset_marker_thread_name(unsigned id)\n{\n  int err = pthread_setname_np(pthread_self(), \"GC-marker-%zu\",\n                               NUMERIC_TO_VPTR(id));\n  if (UNLIKELY(err != 0))\n    WARN(\"pthread_setname_np failed, errno= %\" WARN_PRIdPTR \"\\n\",\n         (GC_signed_word)err);\n}\n\n#    elif defined(HAVE_PTHREAD_SETNAME_NP_WITH_TID)     \\\n        || defined(HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID) \\\n        || defined(HAVE_PTHREAD_SET_NAME_NP)\n#      ifdef HAVE_PTHREAD_SET_NAME_NP\n#        include <pthread_np.h>\n#      endif\nstatic void\nset_marker_thread_name(unsigned id)\n{\n  /*\n   * Note: a smaller size of the buffer may result in\n   * \"output may be truncated\" compiler warning.\n   */\n  char name_buf[10 + 20 + 1];\n\n  GC_snprintf_s_ld_s(name_buf, sizeof(name_buf), \"GC-marker-\", (long)id, \"\");\n#      ifdef HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID\n  /* The iOS or OS X case. */\n  (void)pthread_setname_np(name_buf);\n#      elif defined(HAVE_PTHREAD_SET_NAME_NP)\n  /* The OpenBSD case. */\n  pthread_set_name_np(pthread_self(), name_buf);\n#      else\n  /* The case of Linux, Solaris, etc. */\n  GC_ASSERT(strlen(name_buf) < 16);\n  /* `pthread_setname_np()` may fail for longer names. */\n  if (UNLIKELY(pthread_setname_np(pthread_self(), name_buf) != 0))\n    WARN(\"pthread_setname_np failed\\n\", 0);\n#      endif\n}\n\n#    elif defined(GC_WIN32_THREADS) && !defined(MSWINCE)\n/*\n * A pointer to `SetThreadDescription()` which is available since Windows 10.\n * The function prototype is in the platform `processthreadsapi.h` file.\n */\nstatic FARPROC setThreadDescription_fn;\n\nGC_INNER void\nGC_init_win32_thread_naming(HMODULE hK32)\n{\n  if (hK32)\n    setThreadDescription_fn = GetProcAddress(hK32, \"SetThreadDescription\");\n}\n\nstatic void\nset_marker_thread_name(unsigned id)\n{\n  WCHAR name_buf[16];\n  int len = sizeof(L\"GC-marker-\") / sizeof(WCHAR) - 1;\n  HRESULT hr;\n\n  if (!setThreadDescription_fn) {\n    /* `SetThreadDescription()` is missing. */\n    return;\n  }\n\n  /* Compose the name manually as `swprintf` may be unavailable. */\n  BCOPY(L\"GC-marker-\", name_buf, len * sizeof(WCHAR));\n  if (id >= 10)\n    name_buf[len++] = (WCHAR)('0' + (id / 10) % 10);\n  name_buf[len] = (WCHAR)('0' + id % 10);\n  name_buf[len + 1] = 0;\n\n  /*\n   * Invoke `SetThreadDescription()`.  Cast the function pointer to\n   * `GC_funcptr_uint` first to avoid \"incompatible function types\"\n   * compiler warning.\n   */\n  hr = (*(HRESULT(WINAPI *)(HANDLE, const WCHAR *))(\n      GC_funcptr_uint)setThreadDescription_fn)(GetCurrentThread(), name_buf);\n  if (hr < 0)\n    WARN(\"SetThreadDescription failed\\n\", 0);\n}\n#    else\n#      define set_marker_thread_name(id) (void)(id)\n#    endif\n\nGC_INNER_WIN32THREAD\n#    ifdef GC_PTHREADS_PARAMARK\nvoid *\nGC_mark_thread(void *id)\n#    elif defined(MSWINCE)\nDWORD WINAPI\nGC_mark_thread(LPVOID id)\n#    else\nunsigned __stdcall GC_mark_thread(void *id)\n#    endif\n{\n  word my_mark_no = 0;\n  word id_n = (word)(GC_uintptr_t)id;\n  IF_CANCEL(int cancel_state;)\n\n  if (id_n == GC_WORD_MAX)\n    return 0; /*< to prevent a compiler warning */\n\n  /*\n   * Mark threads are not cancellable; they should be invisible to\n   * client.\n   */\n  DISABLE_CANCEL(cancel_state);\n\n  set_marker_thread_name((unsigned)id_n);\n#    if defined(GC_WIN32_THREADS) || defined(USE_PROC_FOR_LIBRARIES) \\\n        || (defined(IA64)                                            \\\n            && (defined(HAVE_PTHREAD_ATTR_GET_NP)                    \\\n                || defined(HAVE_PTHREAD_GETATTR_NP)))\n  GC_marker_sp[id_n] = GC_approx_sp();\n#    endif\n#    if defined(IA64) && defined(USE_PROC_FOR_LIBRARIES)\n  marker_bsp[id_n] = GC_save_regs_in_stack();\n#    endif\n#    if defined(DARWIN) && !defined(GC_NO_THREADS_DISCOVERY)\n  marker_mach_threads[id_n] = mach_thread_self();\n#    endif\n#    if !defined(GC_PTHREADS_PARAMARK)\n  GC_marker_Id[id_n] = thread_id_self();\n#    endif\n\n  /* Inform `GC_start_mark_threads` about completion of marker data init. */\n  GC_acquire_mark_lock();\n  /* Note: the count variable may have a negative value. */\n  if (0 == --GC_fl_builder_count)\n    GC_notify_all_builder();\n\n  /*\n   * `GC_mark_no` is passed only to allow `GC_help_marker` to\n   * terminate promptly.  This is important if it were called from the\n   * signal handler or from the allocator lock acquisition code.\n   * On Linux, it is not safe to call it from a signal handler, since\n   * it uses mutex and condition variables.  Since it is called only\n   * here, the argument is unnecessary.\n   */\n  for (;; ++my_mark_no) {\n    if (my_mark_no - GC_mark_no > (word)2) {\n      /* Resynchronize if we get far off, e.g. because `GC_mark_no` wrapped. */\n      my_mark_no = GC_mark_no;\n    }\n#    ifdef DEBUG_THREADS\n    GC_log_printf(\"Starting helper for mark number %lu (thread %u)\\n\",\n                  (unsigned long)my_mark_no, (unsigned)id_n);\n#    endif\n    GC_help_marker(my_mark_no);\n  }\n}\n\nGC_INNER_WIN32THREAD int GC_available_markers_m1 = 0;\n\n#  endif /* PARALLEL_MARK */\n\n#  ifdef GC_PTHREADS_PARAMARK\n\n#    ifdef GLIBC_2_1_MUTEX_HACK\n/*\n * Ugly workaround for a Linux threads bug in the final versions\n * of `glibc` 2.1.  `pthread_mutex_trylock` sets the mutex owner\n * field even when it fails to acquire the mutex.  This causes\n * `pthread_cond_wait` to die.  Should not be needed for `glibc` 2.2.\n * According to the man page, we should use\n * `PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP`, but that is not actually\n * defined.\n */\nstatic pthread_mutex_t mark_mutex\n    = { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, { 0, 0 } };\n#    else\nstatic pthread_mutex_t mark_mutex = PTHREAD_MUTEX_INITIALIZER;\n#    endif\n\n#    ifdef CAN_HANDLE_FORK\n/* Note: this is initialized by `GC_start_mark_threads_inner()`. */\nstatic pthread_cond_t mark_cv;\n#    else\nstatic pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER;\n#    endif\n\nGC_INNER void\nGC_start_mark_threads_inner(void)\n{\n  int i;\n  pthread_attr_t attr;\n#    ifndef NO_MARKER_SPECIAL_SIGMASK\n  sigset_t set, oldset;\n#    endif\n\n  GC_ASSERT(I_HOLD_LOCK());\n  ASSERT_CANCEL_DISABLED();\n  if (GC_available_markers_m1 <= 0 || GC_parallel) {\n    /* Skip if parallel markers disabled or already started. */\n    return;\n  }\n  GC_wait_for_gc_completion(TRUE);\n\n#    ifdef CAN_HANDLE_FORK\n  /*\n   * Initialize `mark_cv` (for the first time), or cleanup its value\n   * after forking in the child process.  All the marker threads in the\n   * parent process were blocked on this variable at process fork, so\n   * `pthread_cond_wait()` malfunction (hang) is possible in the child\n   * process without such a cleanup.\n   */\n\n  /*\n   * TODO: This is not portable, it is better to shortly unblock all\n   * marker threads in the parent process at `fork`.\n   */\n  {\n    pthread_cond_t mark_cv_local = PTHREAD_COND_INITIALIZER;\n    BCOPY(&mark_cv_local, &mark_cv, sizeof(mark_cv));\n  }\n#    endif\n\n  GC_ASSERT(0 == GC_fl_builder_count);\n  INIT_REAL_SYMS(); /*< for `pthread_create` */\n\n  if (pthread_attr_init(&attr) != 0)\n    ABORT(\"pthread_attr_init failed\");\n  if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)\n    ABORT(\"pthread_attr_setdetachstate failed\");\n\n#    ifdef DEFAULT_STACK_MAYBE_SMALL\n  /*\n   * The default stack size is usually too small: increase it.\n   * Otherwise marker threads may run out of space.\n   */\n  {\n    size_t old_size;\n\n    if (pthread_attr_getstacksize(&attr, &old_size) != 0)\n      ABORT(\"pthread_attr_getstacksize failed\");\n    if (old_size < MIN_STACK_SIZE && old_size != 0 /* stack size is known */) {\n      if (pthread_attr_setstacksize(&attr, MIN_STACK_SIZE) != 0)\n        ABORT(\"pthread_attr_setstacksize failed\");\n    }\n  }\n#    endif /* DEFAULT_STACK_MAYBE_SMALL */\n\n#    ifndef NO_MARKER_SPECIAL_SIGMASK\n  /*\n   * Apply special signal mask to GC marker threads, and do not drop\n   * user-defined signals by the marker threads.\n   */\n  if (sigfillset(&set) != 0)\n    ABORT(\"sigfillset failed\");\n\n#      ifdef SIGNAL_BASED_STOP_WORLD\n  /* These are used by GC to stop and restart the world. */\n  if (sigdelset(&set, GC_get_suspend_signal()) != 0\n      || sigdelset(&set, GC_get_thr_restart_signal()) != 0)\n    ABORT(\"sigdelset failed\");\n#      endif\n\n  if (UNLIKELY(REAL_FUNC(pthread_sigmask)(SIG_BLOCK, &set, &oldset) != 0)) {\n    WARN(\"pthread_sigmask set failed, no markers started\\n\", 0);\n    GC_markers_m1 = 0;\n    (void)pthread_attr_destroy(&attr);\n    return;\n  }\n#    endif /* !NO_MARKER_SPECIAL_SIGMASK */\n\n  /* To have proper `GC_parallel` value in `GC_help_marker()`. */\n  GC_markers_m1 = GC_available_markers_m1;\n\n  for (i = 0; i < GC_available_markers_m1; ++i) {\n    pthread_t new_thread;\n\n#    ifdef GC_WIN32_THREADS\n    GC_marker_last_stack_min[i] = ADDR_LIMIT;\n#    endif\n    if (UNLIKELY(REAL_FUNC(pthread_create)(&new_thread, &attr, GC_mark_thread,\n                                           NUMERIC_TO_VPTR(i))\n                 != 0)) {\n      WARN(\"Marker thread %\" WARN_PRIdPTR \" creation failed\\n\",\n           (GC_signed_word)i);\n      /* Do not try to create other marker threads. */\n      GC_markers_m1 = i;\n      break;\n    }\n  }\n\n#    ifndef NO_MARKER_SPECIAL_SIGMASK\n  /* Restore previous signal mask. */\n  if (UNLIKELY(REAL_FUNC(pthread_sigmask)(SIG_SETMASK, &oldset, NULL) != 0)) {\n    WARN(\"pthread_sigmask restore failed\\n\", 0);\n  }\n#    endif\n\n  (void)pthread_attr_destroy(&attr);\n  GC_wait_for_markers_init();\n  GC_COND_LOG_PRINTF(\"Started %d mark helper threads\\n\", GC_markers_m1);\n}\n\n#  endif /* GC_PTHREADS_PARAMARK */\n\nGC_INNER GC_thread GC_threads[THREAD_TABLE_SZ] = { 0 };\n\n/*\n * It may not be safe to allocate when we register the first thread.\n * Note that `next` and `status` fields are unused, but there might be\n * some other fields (`crtn`) to be pushed.\n */\nstatic struct GC_StackContext_Rep first_crtn;\nstatic struct GC_Thread_Rep first_thread;\n\n#  ifndef GC_NO_DEINIT\nGC_INNER void\nGC_reset_threads(void)\n{\n  BZERO(GC_threads, sizeof(GC_threads));\n  BZERO(&first_crtn, sizeof(first_crtn));\n  BZERO(&first_thread, sizeof(first_thread));\n}\n#  endif\n\n/*\n * A place to retain a pointer to an allocated object while a thread\n * registration is ongoing.  Protected by the allocator lock.\n */\nstatic GC_stack_context_t saved_crtn = NULL;\n\nGC_INNER void\nGC_push_thread_structures(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n#  if !defined(GC_NO_THREADS_DISCOVERY) && defined(GC_WIN32_THREADS)\n  if (GC_win32_dll_threads) {\n    /*\n     * Unlike the other threads implementations, the thread table here\n     * contains no pointers to the collectible heap (note also that\n     * `GC_PTHREADS` is incompatible with `DllMain`-based thread\n     * registration).  Thus we have no private structures we need to\n     * preserve.\n     */\n  } else\n#  endif\n  /* else */ {\n    GC_push_all(&GC_threads, (ptr_t)(&GC_threads) + sizeof(GC_threads));\n    GC_ASSERT(NULL == first_thread.tm.next);\n#  ifdef GC_PTHREADS\n    GC_ASSERT(NULL == first_thread.status);\n#  endif\n    GC_PUSH_ALL_SYM(first_thread.crtn);\n    GC_PUSH_ALL_SYM(saved_crtn);\n  }\n#  if defined(THREAD_LOCAL_ALLOC) && defined(USE_CUSTOM_SPECIFIC)\n  GC_PUSH_ALL_SYM(GC_thread_key);\n#  endif\n}\n\n#  if defined(MPROTECT_VDB) && defined(GC_WIN32_THREADS)\nGC_INNER void\nGC_win32_unprotect_thread(GC_thread t)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  if (!GC_win32_dll_threads && GC_auto_incremental) {\n    GC_stack_context_t crtn = t->crtn;\n\n    if (crtn != &first_crtn) {\n      GC_ASSERT(SMALL_OBJ(GC_size(crtn)));\n      GC_remove_protection(HBLKPTR(crtn), 1, FALSE);\n    }\n    if (t != &first_thread) {\n      GC_ASSERT(SMALL_OBJ(GC_size(t)));\n      GC_remove_protection(HBLKPTR(t), 1, FALSE);\n    }\n  }\n}\n#  endif /* MPROTECT_VDB && GC_WIN32_THREADS */\n\n#  ifdef DEBUG_THREADS\nSTATIC int\nGC_count_threads(void)\n{\n  int i;\n  int count = 0;\n\n#    if !defined(GC_NO_THREADS_DISCOVERY) && defined(GC_WIN32_THREADS)\n  if (GC_win32_dll_threads)\n    return -1; /*< not implemented */\n#    endif\n  GC_ASSERT(I_HOLD_READER_LOCK());\n  for (i = 0; i < THREAD_TABLE_SZ; ++i) {\n    GC_thread p;\n\n    for (p = GC_threads[i]; p != NULL; p = p->tm.next) {\n      if (!KNOWN_FINISHED(p))\n        ++count;\n    }\n  }\n  return count;\n}\n#  endif /* DEBUG_THREADS */\n\nGC_INNER_WIN32THREAD GC_thread\nGC_new_thread(thread_id_t self_id)\n{\n  int hv = THREAD_TABLE_INDEX(self_id);\n  GC_thread result;\n\n  GC_ASSERT(I_HOLD_LOCK());\n#  ifdef DEBUG_THREADS\n  GC_log_printf(\"Creating thread %p\\n\", THREAD_ID_TO_VPTR(self_id));\n  for (result = GC_threads[hv]; result != NULL; result = result->tm.next)\n    if (!THREAD_ID_EQUAL(result->id, self_id)) {\n      GC_log_printf(\"Hash collision at GC_threads[%d]\\n\", hv);\n      break;\n    }\n#  endif\n  if (UNLIKELY(NULL == first_thread.crtn)) {\n    result = &first_thread;\n    first_thread.crtn = &first_crtn;\n    GC_ASSERT(NULL == GC_threads[hv]);\n#  if defined(CPPCHECK) && defined(THREAD_SANITIZER) \\\n      && defined(SIGNAL_BASED_STOP_WORLD)\n    GC_noop1((unsigned char)first_crtn.dummy[0]);\n#  endif\n  } else {\n    GC_stack_context_t crtn;\n\n    GC_ASSERT(!GC_win32_dll_threads);\n    GC_ASSERT(!GC_in_thread_creation);\n    GC_in_thread_creation = TRUE; /*< OK to collect from unknown thread */\n    crtn = (GC_stack_context_t)GC_INTERNAL_MALLOC(\n        sizeof(struct GC_StackContext_Rep), NORMAL);\n\n    /*\n     * The current stack is not scanned until the thread is registered,\n     * thus `crtn` pointer is to be retained in the global data roots for\n     * a while (and pushed explicitly if a collection occurs here).\n     */\n    GC_ASSERT(NULL == saved_crtn);\n    saved_crtn = crtn;\n    result\n        = (GC_thread)GC_INTERNAL_MALLOC(sizeof(struct GC_Thread_Rep), NORMAL);\n    /* No more collections till thread is registered. */\n    saved_crtn = NULL;\n    GC_in_thread_creation = FALSE;\n    if (NULL == crtn || NULL == result)\n      ABORT(\"Failed to allocate memory for thread registering\");\n    result->crtn = crtn;\n  }\n  /* The `id` field is not set here. */\n#  ifdef USE_TKILL_ON_ANDROID\n  result->kernel_id = gettid();\n#  endif\n  result->tm.next = GC_threads[hv];\n  GC_threads[hv] = result;\n#  ifdef NACL\n  GC_nacl_initialize_gc_thread(result);\n#  endif\n  GC_ASSERT(0 == result->flags);\n  if (LIKELY(result != &first_thread))\n    GC_dirty(result);\n  return result;\n}\n\nGC_INNER_WIN32THREAD void\nGC_delete_thread(GC_thread t)\n{\n#  if !defined(GC_NO_THREADS_DISCOVERY) && defined(GC_WIN32_THREADS)\n  if (GC_win32_dll_threads) {\n    HANDLE handle = t->handle;\n\n    GC_cptr_store_release(&t->handle, NULL);\n    CloseHandle(handle);\n    /*\n     * This is intended to be lock-free.  It is either called synchronously\n     * from the thread being deleted, or by the joining thread.  In this\n     * branch asynchronous changes to `*t` are possible.  Note that it is\n     * not allowed to call `GC_printf` (and the friends) here, see\n     * `GC_stop_world()` in `win32_threads.c` file for the information.\n     */\n    t->crtn->stack_end = NULL;\n    t->id = 0;\n    /* The thread is not suspended. */\n    t->flags = 0;\n#    ifdef RETRY_GET_THREAD_CONTEXT\n    t->context_sp = NULL;\n#    endif\n    AO_store_release(&t->tm.in_use, FALSE);\n  } else\n#  endif\n  /* else */ {\n    thread_id_t id = t->id;\n    int hv = THREAD_TABLE_INDEX(id);\n    GC_thread p;\n    GC_thread prev = NULL;\n\n    GC_ASSERT(I_HOLD_LOCK());\n#  if defined(DEBUG_THREADS) && !defined(MSWINCE) \\\n      && (!defined(MSWIN32) || defined(CONSOLE_LOG))\n    GC_log_printf(\"Deleting thread %p, n_threads= %d\\n\", THREAD_ID_TO_VPTR(id),\n                  GC_count_threads());\n#  endif\n#  if defined(GC_WIN32_THREADS) && !defined(MSWINCE)\n    CloseHandle(t->handle);\n#  endif\n    for (p = GC_threads[hv]; p != t; p = p->tm.next) {\n      prev = p;\n    }\n    if (NULL == prev) {\n      GC_threads[hv] = p->tm.next;\n    } else {\n      GC_ASSERT(prev != &first_thread);\n      prev->tm.next = p->tm.next;\n      GC_dirty(prev);\n    }\n    if (LIKELY(p != &first_thread)) {\n#  ifdef DARWIN\n      mach_port_deallocate(mach_task_self(), p->mach_thread);\n#  endif\n      GC_ASSERT(p->crtn != &first_crtn);\n      GC_INTERNAL_FREE(p->crtn);\n      GC_INTERNAL_FREE(p);\n    }\n  }\n}\n\nGC_INNER GC_thread\nGC_lookup_thread(thread_id_t id)\n{\n  GC_thread p;\n\n#  if !defined(GC_NO_THREADS_DISCOVERY) && defined(GC_WIN32_THREADS)\n  if (GC_win32_dll_threads)\n    return GC_win32_dll_lookup_thread(id);\n#  endif\n  for (p = GC_threads[THREAD_TABLE_INDEX(id)]; p != NULL; p = p->tm.next) {\n    if (LIKELY(THREAD_ID_EQUAL(p->id, id)))\n      break;\n  }\n  return p;\n}\n\n/*\n * Same as `GC_self_thread_inner()` but acquires the allocator lock (in\n * the reader mode).\n */\nSTATIC GC_thread\nGC_self_thread(void)\n{\n  GC_thread p;\n\n  READER_LOCK();\n  p = GC_self_thread_inner();\n  READER_UNLOCK();\n  return p;\n}\n\n#  ifndef GC_NO_FINALIZATION\nGC_INNER void\nGC_reset_finalizer_nested(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_thread me;\n  me = GC_self_thread_inner();\n  if (NULL == me) return; // __v_, make the sanitizers and -cstrict happy\n  me->crtn->finalizer_nested = 0;\n}\n\nGC_INNER unsigned char *\nGC_check_finalizer_nested(void)\n{\n  GC_thread me;\n  GC_stack_context_t crtn;\n  unsigned nesting_level;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  me = GC_self_thread_inner();\n#    if defined(INCLUDE_LINUX_THREAD_DESCR) && defined(REDIRECT_MALLOC)\n  /*\n   * As noted in `GC_pthread_start`, an allocation may happen in\n   * `GC_get_stack_base`, causing `GC_notify_or_invoke_finalizers`\n   * to be called before the thread gets registered.\n   */\n  if (UNLIKELY(NULL == me))\n    return NULL;\n#    endif\n  if (NULL == me) return NULL; // __v_, make the sanitizers and -cstrict happy\n  crtn = me->crtn;\n  nesting_level = crtn->finalizer_nested;\n  if (nesting_level) {\n    /*\n     * We are inside another `GC_invoke_finalizers()`.  Skip some\n     * implicitly-called `GC_invoke_finalizers()` depending on the\n     * nesting (recursion) level.\n     */\n    if ((unsigned)(++crtn->finalizer_skipped) < (1U << nesting_level))\n      return NULL;\n    crtn->finalizer_skipped = 0;\n  }\n  crtn->finalizer_nested = (unsigned char)(nesting_level + 1);\n  return &crtn->finalizer_nested;\n}\n#  endif /* !GC_NO_FINALIZATION */\n\n#  define ADDR_INSIDE_OBJ(p, obj) \\\n    ADDR_INSIDE(p, (ptr_t)(&(obj)), (ptr_t)(&(obj)) + sizeof(obj))\n\n#  if defined(GC_ASSERTIONS) && defined(THREAD_LOCAL_ALLOC)\n/* This is called from thread-local `GC_malloc()`. */\nGC_bool\nGC_is_thread_tsd_valid(void *tsd)\n{\n  GC_thread me = GC_self_thread();\n\n  return ADDR_INSIDE_OBJ((ptr_t)tsd, me->tlfs);\n}\n#  endif /* GC_ASSERTIONS && THREAD_LOCAL_ALLOC */\n\nGC_API int GC_CALL\nGC_thread_is_registered(void)\n{\n  /* TODO: Use `GC_get_tlfs()` instead. */\n  GC_thread me = GC_self_thread();\n\n  return me != NULL && !KNOWN_FINISHED(me);\n}\n\nGC_API void GC_CALL\nGC_register_altstack(void *normstack, size_t normstack_size, void *altstack,\n                     size_t altstack_size)\n{\n#  ifdef GC_WIN32_THREADS\n  /* TODO: Implement. */\n  UNUSED_ARG(normstack);\n  UNUSED_ARG(normstack_size);\n  UNUSED_ARG(altstack);\n  UNUSED_ARG(altstack_size);\n#  else\n  GC_thread me;\n  GC_stack_context_t crtn;\n\n  READER_LOCK();\n  me = GC_self_thread_inner();\n  if (UNLIKELY(NULL == me)) {\n    /* We are called before `GC_thr_init()`. */\n    me = &first_thread;\n  }\n  crtn = me->crtn;\n  crtn->normstack = (ptr_t)normstack;\n  crtn->normstack_size = normstack_size;\n  crtn->altstack = (ptr_t)altstack;\n  crtn->altstack_size = altstack_size;\n  READER_UNLOCK_RELEASE();\n#  endif\n}\n\n#  ifdef USE_PROC_FOR_LIBRARIES\nGC_INNER GC_bool\nGC_segment_is_thread_stack(ptr_t lo, ptr_t hi)\n{\n  int i;\n  GC_thread p;\n\n  GC_ASSERT(I_HOLD_READER_LOCK());\n#    ifdef PARALLEL_MARK\n  for (i = 0; i < GC_markers_m1; ++i) {\n    if (ADDR_LT(lo, GC_marker_sp[i]) && ADDR_LT(GC_marker_sp[i], hi))\n      return TRUE;\n#      ifdef IA64\n    if (ADDR_LT(lo, marker_bsp[i]) && ADDR_LT(marker_bsp[i], hi))\n      return TRUE;\n#      endif\n  }\n#    endif\n  for (i = 0; i < THREAD_TABLE_SZ; i++) {\n    for (p = GC_threads[i]; p != NULL; p = p->tm.next) {\n      ptr_t stack_end = p->crtn->stack_end;\n\n      if (stack_end != NULL) {\n#    ifdef STACK_GROWS_UP\n        if (ADDR_INSIDE(stack_end, lo, hi))\n          return TRUE;\n#    else\n        if (ADDR_LT(lo, stack_end) && ADDR_GE(hi, stack_end))\n          return TRUE;\n#    endif\n      }\n    }\n  }\n  return FALSE;\n}\n#  endif /* USE_PROC_FOR_LIBRARIES */\n\n#  if (defined(HAVE_PTHREAD_ATTR_GET_NP) || defined(HAVE_PTHREAD_GETATTR_NP)) \\\n      && defined(IA64)\nGC_INNER ptr_t\nGC_greatest_stack_base_below(ptr_t bound)\n{\n  int i;\n  GC_thread p;\n  ptr_t result = NULL;\n\n  GC_ASSERT(I_HOLD_READER_LOCK());\n#    ifdef PARALLEL_MARK\n  for (i = 0; i < GC_markers_m1; ++i) {\n    if (ADDR_LT(result, GC_marker_sp[i]) && ADDR_LT(GC_marker_sp[i], bound))\n      result = GC_marker_sp[i];\n  }\n#    endif\n  for (i = 0; i < THREAD_TABLE_SZ; i++) {\n    for (p = GC_threads[i]; p != NULL; p = p->tm.next) {\n      ptr_t stack_end = p->crtn->stack_end;\n\n      if (ADDR_LT(result, stack_end) && ADDR_LT(stack_end, bound))\n        result = stack_end;\n    }\n  }\n  return result;\n}\n#  endif /* IA64 */\n\n#  ifndef STAT_READ\n/*\n * Note: if `read()` is wrapped, this may need to be redefined to call\n * the real one.\n */\n#    define STAT_READ read\n#  endif\n\n#  ifdef HPUX\n#    define GC_get_nprocs() pthread_num_processors_np()\n\n#  elif defined(AIX) || defined(COSMO) || defined(HAIKU)         \\\n      || defined(HOST_ANDROID) || defined(HURD) || defined(NACL) \\\n      || defined(OSF1) || defined(SOLARIS)\nGC_INLINE int\nGC_get_nprocs(void)\n{\n  int nprocs = (int)sysconf(_SC_NPROCESSORS_ONLN);\n  /* Note: ignore any error silently. */\n  return nprocs > 0 ? nprocs : 1;\n}\n\n#  elif defined(IRIX5)\nGC_INLINE int\nGC_get_nprocs(void)\n{\n  int nprocs = (int)sysconf(_SC_NPROC_ONLN);\n  /* Note: ignore any error silently. */\n  return nprocs > 0 ? nprocs : 1;\n}\n\n#  elif defined(LINUX)\n/* Return the number of processors. */\nSTATIC int\nGC_get_nprocs(void)\n{\n  /*\n   * Should be just `return sysconf(_SC_NPROCESSORS_ONLN)` but that\n   * appears to be buggy in many cases.  We look for lines \"cpu<N>\" in\n   * `/proc/stat` pseudo-file.  No need to read the entire `/proc/stat`\n   * pseudo-file to get maximum \"cpu<N>\" such as:\n   *   - the requested lines are located at the beginning of the file;\n   *   - the lines with \"cpu<N>\" where `N` is greater than `MAX_MARKERS`\n   *     are not needed.\n   */\n#    define PROC_STAT_BUF_SZ ((1 + MAX_MARKERS) * 100)\n  char stat_buf[PROC_STAT_BUF_SZ + 1]; /*< the size should be enough */\n  int f;\n  int result, i, len;\n\n  f = open(\"/proc/stat\", O_RDONLY);\n  if (f < 0) {\n    WARN(\"Could not open /proc/stat\\n\", 0);\n    /* Assume an uniprocessor. */\n    return 1;\n  }\n  len = STAT_READ(f, stat_buf, sizeof(stat_buf) - 1);\n  /* Unlikely that we need to retry because of an incomplete read here. */\n  if (len < 0) {\n    WARN(\"Failed to read /proc/stat, errno= %\" WARN_PRIdPTR \"\\n\",\n         (GC_signed_word)errno);\n    close(f);\n    return 1;\n  }\n  /* Avoid potential buffer overrun by `atoi()`. */\n  stat_buf[len] = '\\0';\n\n  close(f);\n\n  /*\n   * Some old kernels only have a single \"cpu nnnn ...\" entry in\n   * `/proc/stat` pseudo-file.  We identify those as uniprocessors.\n   */\n  result = 1;\n\n  for (i = 0; i < len - 4; ++i) {\n    if (stat_buf[i] == '\\n' && stat_buf[i + 1] == 'c' && stat_buf[i + 2] == 'p'\n        && stat_buf[i + 3] == 'u') {\n      int cpu_no = atoi(&stat_buf[i + 4]);\n      if (cpu_no >= result)\n        result = cpu_no + 1;\n    }\n  }\n  return result;\n}\n\n#  elif defined(DGUX)\n/*\n * Return the number of processors, or a non-positive value if the number\n * cannot be determined.\n */\nSTATIC int\nGC_get_nprocs(void)\n{\n  int numCpus;\n  struct dg_sys_info_pm_info pm_sysinfo;\n  int status = 0;\n\n  status = dg_sys_info((long int *)&pm_sysinfo, DG_SYS_INFO_PM_INFO_TYPE,\n                       DG_SYS_INFO_PM_CURRENT_VERSION);\n  if (status < 0) {\n    /* Set -1 for an error. */\n    numCpus = -1;\n  } else {\n    /* Active CPUs. */\n    numCpus = pm_sysinfo.idle_vp_count;\n  }\n  return numCpus;\n}\n\n#  elif defined(ANY_BSD) || defined(DARWIN)\nSTATIC int\nGC_get_nprocs(void)\n{\n  int mib[] = { CTL_HW, HW_NCPU };\n  int res;\n  size_t len = sizeof(res);\n\n  sysctl(mib, sizeof(mib) / sizeof(int), &res, &len, NULL, 0);\n  return res;\n}\n\n#  else\n/* E.g., RTEMS. */\n/* TODO: Implement. */\n#    define GC_get_nprocs() 1\n#  endif\n\n#  if defined(LINUX) && defined(ARM32)\n/*\n * Some buggy Linux/arm kernels show only non-sleeping CPUs in\n * `/proc/stat` pseudo-file (and in `/proc/cpuinfo` pseudo-file), so\n * another data system source is tried first.  Returns a non-positive\n * value on error.\n */\nSTATIC int\nGC_get_nprocs_present(void)\n{\n  char stat_buf[16];\n  int f;\n  int len;\n\n  f = open(\"/sys/devices/system/cpu/present\", O_RDONLY);\n  if (f < 0) {\n    /* Cannot open the file. */\n    return -1;\n  }\n\n  len = STAT_READ(f, stat_buf, sizeof(stat_buf));\n  close(f);\n\n  /*\n   * Recognized file format: \"0\\n\" or \"0-<max_cpu_num>\\n\".\n   * The file might probably contain a comma-separated list\n   * but we do not need to handle it (just silently ignore).\n   */\n  if (len < 2 || stat_buf[0] != '0' || stat_buf[len - 1] != '\\n') {\n    /* A read error or an unrecognized content. */\n    return 0;\n  } else if (len == 2) {\n    /* An uniprocessor. */\n    return 1;\n  } else if (stat_buf[1] != '-') {\n    /* An unrecognized content. */\n    return 0;\n  }\n\n  /* Terminate the string. */\n  stat_buf[len - 1] = '\\0';\n\n  /* Skip \"0-\" and parse `max_cpu_num`. */\n  return atoi(&stat_buf[2]) + 1;\n}\n#  endif /* LINUX && ARM32 */\n\n#  if defined(CAN_HANDLE_FORK) && defined(THREAD_SANITIZER)\n\n/*\n * Workaround for TSan which does not notice that the allocator lock\n * is acquired in `fork_prepare_proc()`.\n */\nGC_ATTR_NO_SANITIZE_THREAD\nstatic GC_bool\ncollection_in_progress(void)\n{\n  return GC_mark_state != MS_NONE;\n}\n#  else\n#    define collection_in_progress() GC_collection_in_progress()\n#  endif\n\nGC_INNER void\nGC_wait_for_gc_completion(GC_bool wait_for_all)\n{\n#  if !defined(THREAD_SANITIZER) || !defined(CAN_CALL_ATFORK)\n  /*\n   * `GC_lock_holder` is accessed with the allocator lock held, so\n   * there is no data race actually (unlike what is reported by TSan).\n   */\n  GC_ASSERT(I_HOLD_LOCK());\n#  endif\n  ASSERT_CANCEL_DISABLED();\n#  ifdef GC_DISABLE_INCREMENTAL\n  (void)wait_for_all;\n#  else\n  if (GC_incremental && collection_in_progress()) {\n    word old_gc_no = GC_gc_no;\n\n    /*\n     * Make sure that no part of our stack is still on the mark stack,\n     * since it is about to be unmapped.\n     */\n#    ifdef LINT2\n    /*\n     * Note: do not transform this `if`-`do`-`while` construction into\n     * a single while statement because it might cause some static code\n     * analyzers to report a false positive (FP) code defect about\n     * missing unlock after lock.\n     */\n#    endif\n    do {\n      GC_ASSERT(!GC_in_thread_creation);\n      GC_in_thread_creation = TRUE;\n      GC_collect_a_little_inner(1);\n      GC_in_thread_creation = FALSE;\n\n      UNLOCK();\n#    ifdef GC_WIN32_THREADS\n      Sleep(0);\n#    else\n      sched_yield();\n#    endif\n      LOCK();\n    } while (GC_incremental && collection_in_progress()\n             && (wait_for_all || old_gc_no == GC_gc_no));\n  }\n#  endif\n}\n\n#  if defined(GC_ASSERTIONS) && defined(GC_PTHREADS_PARAMARK)\nSTATIC unsigned long GC_mark_lock_holder = NO_THREAD;\n#  endif\n\n#  ifdef CAN_HANDLE_FORK\n\n/*\n * Procedures called before and after a process fork.  The goal here is\n * to make it safe to call `GC_malloc()` in the forked child process.\n * It is unclear that is attainable, since the Single UNIX Specification\n * seems to imply that one should only call async-signal-safe functions,\n * and we probably cannot quite guarantee that.  But we give it our best\n * shot.  (That same specification also implies that it is not safe to\n * call the system `malloc` between `fork` and `exec`.  Thus we are doing\n * no worse than it.)\n */\n\nIF_CANCEL(static int fork_cancel_state;) /*< protected by the allocator lock */\n\n#    ifdef PARALLEL_MARK\n#      ifdef THREAD_SANITIZER\n#        if defined(GC_ASSERTIONS) && defined(CAN_CALL_ATFORK)\nSTATIC void GC_generic_lock(pthread_mutex_t *);\n#        endif\nGC_ATTR_NO_SANITIZE_THREAD\nstatic void wait_for_reclaim_atfork(void);\n#      else\n#        define wait_for_reclaim_atfork() GC_wait_for_reclaim()\n#      endif\n#    endif /* PARALLEL_MARK */\n\n/*\n * Prevent TSan false positive (FP) about the race during items removal\n * from `GC_threads`.  (The race cannot happen since only one thread\n * survives in the child process.)\n */\n#    ifdef CAN_CALL_ATFORK\nGC_ATTR_NO_SANITIZE_THREAD\n#    endif\nstatic void\nstore_to_threads_table(int hv, GC_thread me)\n{\n  GC_threads[hv] = me;\n}\n\n/*\n * Remove all entries from the `GC_threads` table, except the one for\n * the current thread.  Also update thread identifiers stored in the\n * table for the current thread.  We need to do this in the child process\n * after a `fork()`, since only the current thread survives in the child\n * process.\n */\nSTATIC void\nGC_remove_all_threads_but_me(void)\n{\n  int hv;\n  GC_thread me = NULL;\n#    ifndef GC_WIN32_THREADS\n#      define pthread_id id\n#    endif\n\n  for (hv = 0; hv < THREAD_TABLE_SZ; ++hv) {\n    GC_thread p, next;\n\n    for (p = GC_threads[hv]; p != NULL; p = next) {\n      next = p->tm.next;\n      if (THREAD_EQUAL(p->pthread_id, GC_parent_pthread_self) && me == NULL) {\n        /* Ignore dead threads with the same id. */\n        me = p;\n        p->tm.next = NULL;\n      } else {\n#    ifdef THREAD_LOCAL_ALLOC\n        if (!KNOWN_FINISHED(p)) {\n          /*\n           * Cannot call `GC_destroy_thread_local` here.  The free\n           * lists may be in an inconsistent state (as thread `p` may\n           * be updating one of the lists by `GC_generic_malloc_many()`\n           * or `GC_FAST_MALLOC_GRANS()` when `fork()` is invoked).\n           * This should not be a problem because the lost elements\n           * of the free lists will be collected during GC.\n           */\n          GC_remove_specific_after_fork(GC_thread_key, p->pthread_id);\n        }\n#    endif\n        /*\n         * TODO: To avoid TSan hang (when updating `GC_bytes_freed`),\n         * we just skip explicit freeing of `GC_threads` entries.\n         */\n#    if !defined(THREAD_SANITIZER) || !defined(CAN_CALL_ATFORK)\n        if (p != &first_thread) {\n          /* TODO: Should call `mach_port_deallocate`? */\n          GC_ASSERT(p->crtn != &first_crtn);\n          GC_INTERNAL_FREE(p->crtn);\n          GC_INTERNAL_FREE(p);\n        }\n#    endif\n      }\n    }\n    store_to_threads_table(hv, NULL);\n  }\n\n#    if defined(CPPCHECK) || defined(LINT2)\n  if (NULL == me)\n    ABORT(\"Current thread is not found after fork\");\n#    else\n  GC_ASSERT(me != NULL);\n#    endif\n  /*\n   * Update `pthreads` id as it is not guaranteed to be the same between\n   * this (child) process and the parent one.\n   */\n  me->pthread_id = pthread_self();\n#    ifdef GC_WIN32_THREADS\n  /*\n   * Update Win32 thread id and handle.  They differ from that in the\n   * parent process.\n   */\n  me->id = thread_id_self();\n#      ifndef MSWINCE\n  if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),\n                       GetCurrentProcess(), (HANDLE *)&me->handle,\n                       0 /* `dwDesiredAccess` */, FALSE /* `bInheritHandle` */,\n                       DUPLICATE_SAME_ACCESS))\n    ABORT(\"DuplicateHandle failed\");\n#      endif\n#    endif\n#    ifdef DARWIN\n  /*\n   * Update thread id after process fork (it is OK to call\n   * `GC_destroy_thread_local()` and `GC_free_inner()` before update).\n   */\n  me->mach_thread = mach_thread_self();\n#    endif\n#    ifdef USE_TKILL_ON_ANDROID\n  me->kernel_id = gettid();\n#    endif\n\n  /* Put `me` back to `GC_threads`. */\n  store_to_threads_table(THREAD_TABLE_INDEX(me->id), me);\n\n#    ifdef THREAD_LOCAL_ALLOC\n#      ifdef USE_CUSTOM_SPECIFIC\n  GC_update_specific_after_fork(GC_thread_key);\n#      else\n  /*\n   * Some TLS implementations (e.g., in Cygwin) might be not `fork`-friendly,\n   * so we re-assign thread-local pointer to `tlfs` for safety instead of the\n   * assertion check (again, it is OK to call `GC_destroy_thread_local()` and\n   * `GC_free_inner()` before).\n   */\n  {\n    int res = GC_setspecific(GC_thread_key, &me->tlfs);\n\n    if (COVERT_DATAFLOW(res) != 0)\n      ABORT(\"GC_setspecific failed (in child)\");\n  }\n#      endif\n#    endif\n#    undef pthread_id\n}\n\n/* Called before a `fork()`. */\n#    if defined(GC_ASSERTIONS) && defined(CAN_CALL_ATFORK)\n/* `GC_lock_holder` is updated safely (no data race actually). */\nGC_ATTR_NO_SANITIZE_THREAD\n#    endif\nstatic void\nfork_prepare_proc(void)\n{\n#    if defined(GC_EXPLICIT_SIGNALS_UNBLOCK) && defined(CAN_CALL_ATFORK)\n  /*\n   * The signals might be blocked by `fork()` implementation when the\n   * at-fork prepare handler is invoked.\n   */\n  if (GC_handle_fork == 1)\n    GC_unblock_gc_signals();\n#    endif\n\n  /*\n   * Acquire all relevant locks, so that after releasing the locks the child\n   * process will see a consistent state in which monitor invariants hold.\n   * Unfortunately, we cannot acquire `libc` locks we might need, and there\n   * seems to be no guarantee that `libc` must install a suitable `fork`\n   * handler.  Wait for an ongoing collection to finish, since we cannot\n   * finish it in the (one remaining thread in) the child process.\n   */\n\n  LOCK();\n  DISABLE_CANCEL(fork_cancel_state);\n  GC_parent_pthread_self = pthread_self();\n  /* The following waits may include cancellation points. */\n#    ifdef PARALLEL_MARK\n  if (GC_parallel)\n    wait_for_reclaim_atfork();\n#    endif\n  GC_wait_for_gc_completion(TRUE);\n#    ifdef PARALLEL_MARK\n  if (GC_parallel) {\n#      if defined(THREAD_SANITIZER) && defined(GC_ASSERTIONS) \\\n          && defined(CAN_CALL_ATFORK)\n    /*\n     * Prevent TSan false positive (FP) about the data race when updating\n     * `GC_mark_lock_holder`.\n     */\n    GC_generic_lock(&mark_mutex);\n#      else\n    GC_acquire_mark_lock();\n#      endif\n  }\n#    endif\n  GC_acquire_dirty_lock();\n}\n\n/*\n * Called in the parent process after a `fork()` (even if the latter\n * has failed).\n */\n#    if defined(GC_ASSERTIONS) && defined(CAN_CALL_ATFORK)\nGC_ATTR_NO_SANITIZE_THREAD\n#    endif\nstatic void\nfork_parent_proc(void)\n{\n  GC_release_dirty_lock();\n#    ifdef PARALLEL_MARK\n  if (GC_parallel) {\n#      if defined(THREAD_SANITIZER) && defined(GC_ASSERTIONS) \\\n          && defined(CAN_CALL_ATFORK)\n    /* To match that in `fork_prepare_proc`. */\n    (void)pthread_mutex_unlock(&mark_mutex);\n#      else\n    GC_release_mark_lock();\n#      endif\n  }\n#    endif\n  RESTORE_CANCEL(fork_cancel_state);\n#    ifdef GC_ASSERTIONS\n  BZERO(&GC_parent_pthread_self, sizeof(pthread_t));\n#    endif\n  UNLOCK();\n}\n\n/* Called in the child process after a `fork()`. */\n#    if defined(GC_ASSERTIONS) && defined(CAN_CALL_ATFORK)\nGC_ATTR_NO_SANITIZE_THREAD\n#    endif\nstatic void\nfork_child_proc(void)\n{\n#    ifdef GC_ASSERTIONS\n  /*\n   * Update `GC_lock_holder` as value of `thread_id_self()` might differ\n   * from that of the parent process.\n   */\n  SET_LOCK_HOLDER();\n#    endif\n  GC_release_dirty_lock();\n#    ifndef GC_DISABLE_INCREMENTAL\n  GC_dirty_update_child();\n#    endif\n#    ifdef PARALLEL_MARK\n  if (GC_parallel) {\n#      ifdef GC_WIN32_THREADS\n    GC_release_mark_lock();\n#      else\n#        if !defined(GC_ASSERTIONS) \\\n            || (defined(THREAD_SANITIZER) && defined(CAN_CALL_ATFORK))\n    /* Do not change `GC_mark_lock_holder`. */\n#        else\n    GC_mark_lock_holder = NO_THREAD;\n#        endif\n    /*\n     * The unlock operation may fail on some targets, just ignore\n     * the error silently.\n     */\n    (void)pthread_mutex_unlock(&mark_mutex);\n    /*\n     * Reinitialize the mark lock.  The reason is the same as for\n     * `GC_allocate_ml` below.\n     */\n    (void)pthread_mutex_destroy(&mark_mutex);\n    /* TODO: `GLIBC_2_19_TSX_BUG` has no effect. */\n    if (pthread_mutex_init(&mark_mutex, NULL) != 0)\n      ABORT(\"mark_mutex re-init failed in child\");\n#      endif\n    /*\n     * Turn off parallel marking in the child process, since we are probably\n     * just going to exec, and we would have to restart mark threads.\n     */\n    GC_parallel = FALSE;\n  }\n#      ifdef THREAD_SANITIZER\n  /* TSan does not support threads creation in the child process. */\n  GC_available_markers_m1 = 0;\n#      endif\n#    endif\n  /* Clean up the thread table, so that just our thread is left. */\n  GC_remove_all_threads_but_me();\n  GC_stackbase_info_update_after_fork();\n  RESTORE_CANCEL(fork_cancel_state);\n#    ifdef GC_ASSERTIONS\n  BZERO(&GC_parent_pthread_self, sizeof(pthread_t));\n#    endif\n  UNLOCK();\n  /*\n   * Even though after a `fork()` the child process only inherits the\n   * single thread that called the `fork()`, if another thread in the\n   * parent process was attempting to lock the mutex while being held\n   * in `fork_child_prepare()`, the mutex will be left in\n   * an inconsistent state in the child process after the `UNLOCK()`.\n   * This is the case, at least, in Mac OS X and leads to an unusable\n   * collector in the child process which will block when attempting\n   * to perform any GC operation that acquires the allocator lock.\n   */\n#    if defined(USE_PTHREAD_LOCKS) && !defined(GC_WIN32_THREADS)\n  GC_ASSERT(I_DONT_HOLD_LOCK());\n  /*\n   * Reinitialize the mutex.  It should be safe since we are running\n   * this in the child process which only inherits a single thread.\n   * `pthread_mutex_destroy()` and `pthread_rwlock_destroy()` may\n   * return `EBUSY`, which makes no sense, but that is the reason for\n   * the need of the reinitialization.\n   * Note: excluded for Cygwin as does not seem to be needed.\n   */\n#      ifdef USE_RWLOCK\n  (void)pthread_rwlock_destroy(&GC_allocate_ml);\n#        ifdef DARWIN\n  /* A workaround for `pthread_rwlock_init()` fail with `EBUSY`. */\n  {\n    pthread_rwlock_t rwlock_local = PTHREAD_RWLOCK_INITIALIZER;\n    BCOPY(&rwlock_local, &GC_allocate_ml, sizeof(GC_allocate_ml));\n  }\n#        else\n  if (pthread_rwlock_init(&GC_allocate_ml, NULL) != 0)\n    ABORT(\"pthread_rwlock_init failed (in child)\");\n#        endif\n#      else\n  (void)pthread_mutex_destroy(&GC_allocate_ml);\n  /*\n   * TODO: Probably some targets (e.g. with `GLIBC_2_19_TSX_BUG`) might\n   * need the default mutex attribute to be passed instead of `NULL`.\n   */\n  if (pthread_mutex_init(&GC_allocate_ml, NULL) != 0)\n    ABORT(\"pthread_mutex_init failed (in child)\");\n#      endif\n#    endif\n}\n\n/*\n * Routines for `fork()` handling by client (no-op if `pthread_atfork`\n * works).\n */\n\nGC_API void GC_CALL\nGC_atfork_prepare(void)\n{\n  if (UNLIKELY(!GC_is_initialized))\n    GC_init();\n  if (GC_handle_fork <= 0)\n    fork_prepare_proc();\n}\n\nGC_API void GC_CALL\nGC_atfork_parent(void)\n{\n  if (GC_handle_fork <= 0)\n    fork_parent_proc();\n}\n\nGC_API void GC_CALL\nGC_atfork_child(void)\n{\n  if (GC_handle_fork <= 0)\n    fork_child_proc();\n}\n\nGC_INNER_WIN32THREAD void\nGC_setup_atfork(void)\n{\n  if (GC_handle_fork) {\n#    ifdef CAN_CALL_ATFORK\n    if (pthread_atfork(fork_prepare_proc, fork_parent_proc, fork_child_proc)\n        == 0) {\n      /* Handlers successfully registered. */\n      GC_handle_fork = 1;\n    } else\n#    endif\n    /* else */ {\n      if (GC_handle_fork != -1)\n        ABORT(\"pthread_atfork failed\");\n    }\n  }\n}\n\n#  endif /* CAN_HANDLE_FORK */\n\n#  ifdef INCLUDE_LINUX_THREAD_DESCR\n__thread int GC_dummy_thread_local;\n#  endif\n\n#  ifdef PARALLEL_MARK\n#    ifndef GC_WIN32_THREADS\nstatic void setup_mark_lock(void);\n#    endif\n\nGC_INNER_WIN32THREAD unsigned GC_required_markers_cnt = 0;\n\nGC_API void GC_CALL\nGC_set_markers_count(unsigned markers)\n{\n  GC_required_markers_cnt = markers < MAX_MARKERS ? markers : MAX_MARKERS;\n}\n#  endif /* PARALLEL_MARK */\n\nGC_INNER GC_bool GC_in_thread_creation = FALSE;\n\nGC_INNER_WIN32THREAD void\nGC_record_stack_base(GC_stack_context_t crtn, const struct GC_stack_base *sb)\n{\n#  if !defined(DARWIN) && !defined(GC_WIN32_THREADS)\n  crtn->stack_ptr = (ptr_t)sb->mem_base;\n#  endif\n  if ((crtn->stack_end = (ptr_t)sb->mem_base) == NULL)\n    ABORT(\"Bad stack base in GC_register_my_thread\");\n#  ifdef E2K\n  crtn->ps_ofs = (size_t)(GC_uintptr_t)sb->reg_base;\n#  elif defined(IA64)\n  crtn->backing_store_end = (ptr_t)sb->reg_base;\n#  elif defined(I386) && defined(GC_WIN32_THREADS)\n  crtn->initial_stack_base = (ptr_t)sb->mem_base;\n#  endif\n}\n\n#  if !defined(GC_NO_THREADS_DISCOVERY) && defined(GC_WIN32_THREADS) \\\n      || !defined(DONT_USE_ATEXIT)\nGC_INNER_WIN32THREAD thread_id_t GC_main_thread_id;\n#  endif\n\n#  ifndef DONT_USE_ATEXIT\nGC_INNER GC_bool\nGC_is_main_thread(void)\n{\n  GC_ASSERT(GC_thr_initialized);\n  return THREAD_ID_EQUAL(GC_main_thread_id, thread_id_self());\n}\n#  endif /* !DONT_USE_ATEXIT */\n\n#  ifndef GC_WIN32_THREADS\n\nSTATIC GC_thread\nGC_register_my_thread_inner(const struct GC_stack_base *sb,\n                            thread_id_t self_id)\n{\n  GC_thread me;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  me = GC_new_thread(self_id);\n  me->id = self_id;\n#    ifdef DARWIN\n  me->mach_thread = mach_thread_self();\n#    endif\n  GC_record_stack_base(me->crtn, sb);\n  return me;\n}\n\n/*\n * Number of processors.  We may not have access to all of them, but\n * this is as good a guess as any...\n */\nSTATIC int GC_nprocs = 1;\n\nGC_INNER void\nGC_thr_init(void)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(!GC_thr_initialized);\n  GC_ASSERT(ADDR(&GC_threads) % ALIGNMENT == 0);\n#    ifdef GC_ASSERTIONS\n  GC_thr_initialized = TRUE;\n#    endif\n#    ifdef CAN_HANDLE_FORK\n  GC_setup_atfork();\n#    endif\n\n#    ifdef INCLUDE_LINUX_THREAD_DESCR\n  /*\n   * Explicitly register the region including the address of a thread-local\n   * variable.  This should include thread locals for the main thread,\n   * except for those allocated in response to `dlopen()` calls.\n   */\n  {\n    ptr_t thread_local_addr = (ptr_t)(&GC_dummy_thread_local);\n    ptr_t main_thread_start, main_thread_end;\n    if (!GC_enclosing_writable_mapping(thread_local_addr, &main_thread_start,\n                                       &main_thread_end)) {\n      ABORT(\"Failed to find TLS mapping for the primordial thread\");\n    } else {\n      /* `main_thread_start` and `main_thread_end` are initialized. */\n      GC_add_roots_inner(main_thread_start, main_thread_end, FALSE);\n    }\n  }\n#    endif\n\n  /* Set `GC_nprocs` and `GC_available_markers_m1` variables. */\n  {\n    const char *nprocs_string = GETENV(\"GC_NPROCS\");\n    GC_nprocs = -1;\n    if (nprocs_string != NULL)\n      GC_nprocs = atoi(nprocs_string);\n  }\n  if (GC_nprocs <= 0\n#    if defined(LINUX) && defined(ARM32)\n      /* Workaround for some Linux/arm kernels. */\n      && (GC_nprocs = GC_get_nprocs_present()) <= 1\n#    endif\n  ) {\n    GC_nprocs = GC_get_nprocs();\n  }\n  if (GC_nprocs <= 0) {\n    WARN(\"GC_get_nprocs() returned %\" WARN_PRIdPTR \"\\n\",\n         (GC_signed_word)GC_nprocs);\n    /* Assume a dual-core CPU. */\n    GC_nprocs = 2;\n#    ifdef PARALLEL_MARK\n    /* But use only one marker. */\n    GC_available_markers_m1 = 0;\n#    endif\n  } else {\n#    ifdef PARALLEL_MARK\n    {\n      const char *markers_string = GETENV(\"GC_MARKERS\");\n      int markers = GC_required_markers_cnt;\n\n      if (markers_string != NULL) {\n        markers = atoi(markers_string);\n        if (markers <= 0 || markers > MAX_MARKERS) {\n          WARN(\"Too big or invalid number of mark threads: %\" WARN_PRIdPTR\n               \"; using maximum threads\\n\",\n               (GC_signed_word)markers);\n          markers = MAX_MARKERS;\n        }\n      } else if (0 == markers) {\n        /*\n         * Unless the client sets the desired number of parallel markers,\n         * it is determined based on the number of CPU cores.\n         */\n        markers = GC_nprocs;\n#      if defined(GC_MIN_MARKERS) && !defined(CPPCHECK)\n        /* This is primarily for targets without `getenv()`. */\n        if (markers < GC_MIN_MARKERS)\n          markers = GC_MIN_MARKERS;\n#      endif\n        if (markers > MAX_MARKERS) {\n          /* Silently limit the amount of markers. */\n          markers = MAX_MARKERS;\n        }\n      }\n      GC_available_markers_m1 = markers - 1;\n    }\n#    endif\n  }\n  GC_COND_LOG_PRINTF(\"Number of processors: %d\\n\", GC_nprocs);\n\n#    if defined(BASE_ATOMIC_OPS_EMULATED) && defined(SIGNAL_BASED_STOP_WORLD)\n  /*\n   * Ensure the process is running on just one CPU core.  This is needed\n   * because the AO primitives emulated with locks cannot be used inside\n   * signal handlers.\n   */\n  {\n    cpu_set_t mask;\n    int cpu_set_cnt = 0;\n    int cpu_lowest_set = 0;\n#      ifdef RANDOM_ONE_CPU_CORE\n    int cpu_highest_set = 0;\n#      endif\n    /* Ensure at least 2 cores. */\n    int i = GC_nprocs > 1 ? GC_nprocs : 2;\n\n    if (sched_getaffinity(0 /* current process */, sizeof(mask), &mask) == -1)\n      ABORT_ARG1(\"sched_getaffinity failed\", \": errno= %d\", errno);\n    while (i-- > 0)\n      if (CPU_ISSET(i, &mask)) {\n#      ifdef RANDOM_ONE_CPU_CORE\n        if (i + 1 != cpu_lowest_set)\n          cpu_highest_set = i;\n#      endif\n        cpu_lowest_set = i;\n        cpu_set_cnt++;\n      }\n    if (0 == cpu_set_cnt)\n      ABORT(\"sched_getaffinity returned empty mask\");\n    if (cpu_set_cnt > 1) {\n#      ifdef RANDOM_ONE_CPU_CORE\n      if (cpu_lowest_set < cpu_highest_set) {\n        /* Pseudo-randomly adjust the bit to set among valid ones. */\n        cpu_lowest_set\n            += (unsigned)getpid() % (cpu_highest_set - cpu_lowest_set + 1);\n      }\n#      endif\n      CPU_ZERO(&mask);\n      /* Select just one CPU. */\n      CPU_SET(cpu_lowest_set, &mask);\n      if (sched_setaffinity(0, sizeof(mask), &mask) == -1)\n        ABORT_ARG1(\"sched_setaffinity failed\", \": errno= %d\", errno);\n      WARN(\"CPU affinity mask is set to %p\\n\", (word)1 << cpu_lowest_set);\n    }\n  }\n#    endif /* BASE_ATOMIC_OPS_EMULATED */\n\n#    ifndef DARWIN\n  GC_stop_init();\n#    endif\n\n#    ifdef PARALLEL_MARK\n  if (GC_available_markers_m1 <= 0) {\n    /* Disable parallel marking. */\n    GC_parallel = FALSE;\n    GC_COND_LOG_PRINTF(\"Single marker thread, turning off parallel marking\\n\");\n  } else {\n    setup_mark_lock();\n  }\n#    endif\n\n  /* Add the initial thread, so we can stop it. */\n  {\n    struct GC_stack_base sb;\n    GC_thread me;\n    thread_id_t self_id = thread_id_self();\n\n    sb.mem_base = GC_stackbottom;\n    GC_ASSERT(sb.mem_base != NULL);\n#    if defined(E2K) || defined(IA64)\n    sb.reg_base = GC_register_stackbottom;\n#    endif\n    GC_ASSERT(NULL == GC_self_thread_inner());\n    me = GC_register_my_thread_inner(&sb, self_id);\n#    ifndef DONT_USE_ATEXIT\n    GC_main_thread_id = self_id;\n#    endif\n    me->flags = DETACHED;\n  }\n}\n\n#  endif /* !GC_WIN32_THREADS */\n\nGC_INNER void\nGC_init_parallel(void)\n{\n#  ifdef THREAD_LOCAL_ALLOC\n  GC_thread me;\n\n  GC_ASSERT(GC_is_initialized);\n  LOCK();\n  me = GC_self_thread_inner();\n  GC_init_thread_local(&me->tlfs);\n  UNLOCK();\n#  endif\n#  if !defined(GC_NO_THREADS_DISCOVERY) && defined(GC_WIN32_THREADS)\n  if (GC_win32_dll_threads) {\n    /*\n     * Cannot intercept thread creation.  Hence we do not know if other\n     * threads exist.  However, client is not allowed to create other threads\n     * before collector initialization.  Thus it is OK not to lock before\n     * this.\n     */\n    set_need_to_lock();\n  }\n#  endif\n}\n\n#  if !defined(GC_NO_PTHREAD_SIGMASK) && defined(GC_PTHREADS)\n#    define GC_wrap_pthread_sigmask WRAP_FUNC(pthread_sigmask)\nGC_API int\nGC_wrap_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)\n{\n#    ifdef GC_WIN32_THREADS\n  /*\n   * `pthreads-win32` library does not support `sigmask`.\n   * So, nothing is required here...\n   */\n#    else\n  sigset_t fudged_set;\n\n  INIT_REAL_SYMS();\n  if (LIKELY(set != NULL) && (how == SIG_BLOCK || how == SIG_SETMASK)) {\n    int sig_suspend = GC_get_suspend_signal();\n\n    fudged_set = *set;\n    GC_ASSERT(sig_suspend >= 0);\n    if (sigdelset(&fudged_set, sig_suspend) != 0)\n      ABORT(\"sigdelset failed\");\n    set = &fudged_set;\n  }\n#    endif\n  return REAL_FUNC(pthread_sigmask)(how, set, oset);\n}\n#    undef GC_wrap_pthread_sigmask\n#  endif /* !GC_NO_PTHREAD_SIGMASK */\n\n/*\n * Wrapper for functions that are likely to block for an appreciable\n * length of time.\n */\n\n#  ifdef E2K\n/*\n * Cannot be defined as a function because the stack-allocated buffer\n * (pointed to by `bs_lo`) should be preserved till completion of\n * `GC_do_blocking_inner` (or `GC_suspend_self_blocked`).\n */\n#    define do_blocking_enter(pTopOfStackUnset, me)                   \\\n      do {                                                            \\\n        ptr_t bs_lo;                                                  \\\n        size_t stack_size;                                            \\\n        GC_stack_context_t crtn = (me)->crtn;                         \\\n                                                                      \\\n        *(pTopOfStackUnset) = FALSE;                                  \\\n        crtn->stack_ptr = GC_approx_sp();                             \\\n        GC_ASSERT(NULL == crtn->backing_store_end);                   \\\n        GET_PROCEDURE_STACK_LOCAL(crtn->ps_ofs, &bs_lo, &stack_size); \\\n        crtn->backing_store_end = bs_lo;                              \\\n        crtn->backing_store_ptr = bs_lo + stack_size;                 \\\n        (me)->flags |= DO_BLOCKING;                                   \\\n      } while (0)\n\n#  else /* !E2K */\nstatic void\ndo_blocking_enter(GC_bool *pTopOfStackUnset, GC_thread me)\n{\n#    if defined(SPARC) || defined(IA64)\n  ptr_t bs_hi = GC_save_regs_in_stack();\n  /* TODO: Registers saving already done by `GC_with_callee_saves_pushed`. */\n#    endif\n  GC_stack_context_t crtn = me->crtn;\n\n  GC_ASSERT(I_HOLD_READER_LOCK());\n  GC_ASSERT((me->flags & DO_BLOCKING) == 0);\n  *pTopOfStackUnset = FALSE;\n#    ifdef SPARC\n  crtn->stack_ptr = bs_hi;\n#    else\n  crtn->stack_ptr = GC_approx_sp();\n#    endif\n#    if defined(DARWIN) && !defined(DARWIN_DONT_PARSE_STACK)\n  if (NULL == crtn->topOfStack) {\n    /*\n     * `GC_do_blocking_inner` is not called recursively, so `topOfStack`\n     * should be computed now.\n     */\n    *pTopOfStackUnset = TRUE;\n    crtn->topOfStack = GC_FindTopOfStack(0);\n  }\n#    endif\n#    ifdef IA64\n  crtn->backing_store_ptr = bs_hi;\n#    endif\n  me->flags |= DO_BLOCKING;\n  /* Save context here if we want to support precise stack marking. */\n}\n#  endif /* !E2K */\n\nstatic void\ndo_blocking_leave(GC_thread me, GC_bool topOfStackUnset)\n{\n  GC_ASSERT(I_HOLD_READER_LOCK());\n  me->flags &= (unsigned char)~DO_BLOCKING;\n#  ifdef E2K\n  {\n    GC_stack_context_t crtn = me->crtn;\n\n    GC_ASSERT(crtn->backing_store_end != NULL);\n    crtn->backing_store_ptr = NULL;\n    crtn->backing_store_end = NULL;\n  }\n#  endif\n#  if defined(DARWIN) && !defined(DARWIN_DONT_PARSE_STACK)\n  if (topOfStackUnset) {\n    /* Make it unset again. */\n    me->crtn->topOfStack = NULL;\n  }\n#  else\n  (void)topOfStackUnset;\n#  endif\n}\n\nGC_INNER void\nGC_do_blocking_inner(ptr_t data, void *context)\n{\n  GC_thread me;\n  GC_bool topOfStackUnset;\n\n  UNUSED_ARG(context);\n  READER_LOCK();\n  me = GC_self_thread_inner();\n  do_blocking_enter(&topOfStackUnset, me);\n  READER_UNLOCK_RELEASE();\n\n  ((struct blocking_data *)data)->client_data /*< result */\n      = ((struct blocking_data *)data)\n            ->fn(((struct blocking_data *)data)->client_data);\n\n  /* This will block if the world is stopped. */\n  READER_LOCK();\n\n#  ifdef LINT2\n  {\n#    ifdef GC_ASSERTIONS\n    GC_thread saved_me = me;\n#    endif\n\n    /*\n     * The pointer to the GC thread descriptor should not be changed while\n     * the thread is registered but a static analysis tool might complain\n     * that this pointer value (obtained in the first locked section) is\n     * unreliable in the second locked section.\n     */\n    me = GC_self_thread_inner();\n    GC_ASSERT(me == saved_me);\n  }\n#  endif\n#  if defined(GC_ENABLE_SUSPEND_THREAD) && defined(SIGNAL_BASED_STOP_WORLD)\n  /*\n   * Note: this code cannot be moved into `do_blocking_leave()` otherwise\n   * there could be a static analysis tool warning (false positive) about\n   * unlock without a matching lock.\n   */\n  while (UNLIKELY((me->ext_suspend_cnt & 1) != 0)) {\n    /* Read suspend counter (number) before unlocking. */\n    size_t suspend_cnt = me->ext_suspend_cnt;\n\n    READER_UNLOCK_RELEASE();\n    GC_suspend_self_inner(me, suspend_cnt);\n    READER_LOCK();\n  }\n#  endif\n  do_blocking_leave(me, topOfStackUnset);\n  READER_UNLOCK_RELEASE();\n}\n\n#  if defined(GC_ENABLE_SUSPEND_THREAD) && defined(SIGNAL_BASED_STOP_WORLD)\nGC_INNER void\nGC_suspend_self_blocked(ptr_t thread_me, void *context)\n{\n  GC_thread me = (GC_thread)thread_me;\n  GC_bool topOfStackUnset;\n\n  UNUSED_ARG(context);\n\n  /*\n   * The caller holds the allocator lock in the exclusive mode, thus\n   * we require and restore it to the same mode upon return from the\n   * function.\n   */\n  GC_ASSERT(I_HOLD_LOCK());\n\n  do_blocking_enter(&topOfStackUnset, me);\n  while ((me->ext_suspend_cnt & 1) != 0) {\n    size_t suspend_cnt = me->ext_suspend_cnt;\n\n    UNLOCK();\n    GC_suspend_self_inner(me, suspend_cnt);\n    LOCK();\n  }\n  do_blocking_leave(me, topOfStackUnset);\n}\n#  endif /* GC_ENABLE_SUSPEND_THREAD */\n\nGC_API void GC_CALL\nGC_set_stackbottom(void *gc_thread_handle, const struct GC_stack_base *sb)\n{\n  GC_thread t = (GC_thread)gc_thread_handle;\n  GC_stack_context_t crtn;\n\n  GC_ASSERT(sb->mem_base != NULL);\n  if (UNLIKELY(!GC_is_initialized)) {\n    GC_ASSERT(NULL == t);\n    /* Alter the stack bottom of the primordial thread. */\n    GC_stackbottom = (char *)sb->mem_base;\n#  if defined(E2K) || defined(IA64)\n    GC_register_stackbottom = (ptr_t)sb->reg_base;\n#  endif\n    return;\n  }\n\n  GC_ASSERT(I_HOLD_READER_LOCK());\n  if (NULL == t) {\n    /* The current thread. */\n    t = GC_self_thread_inner();\n  }\n  GC_ASSERT(!KNOWN_FINISHED(t));\n  crtn = t->crtn;\n  GC_ASSERT((t->flags & DO_BLOCKING) == 0\n            && NULL == crtn->traced_stack_sect); /*< for now */\n\n  crtn->stack_end = (ptr_t)sb->mem_base;\n#  ifdef E2K\n  crtn->ps_ofs = (size_t)(GC_uintptr_t)sb->reg_base;\n#  elif defined(IA64)\n  crtn->backing_store_end = (ptr_t)sb->reg_base;\n#  endif\n#  ifdef GC_WIN32_THREADS\n  /* Reset the known minimum (hottest address in the stack). */\n  crtn->last_stack_min = ADDR_LIMIT;\n#  endif\n}\n\nGC_API void *GC_CALL\nGC_get_my_stackbottom(struct GC_stack_base *sb)\n{\n  GC_thread me;\n  GC_stack_context_t crtn;\n\n  READER_LOCK();\n  me = GC_self_thread_inner();\n  /* The thread is assumed to be registered. */\n  crtn = me->crtn;\n  sb->mem_base = crtn->stack_end;\n#  ifdef E2K\n  /* Store the offset in the procedure stack, not address. */\n  sb->reg_base = NUMERIC_TO_VPTR(crtn->ps_ofs);\n#  elif defined(IA64)\n  sb->reg_base = crtn->backing_store_end;\n#  endif\n  READER_UNLOCK();\n  return me; /*< `gc_thread_handle` */\n}\n\nGC_ATTR_NOINLINE\nGC_API void *GC_CALL\nGC_call_with_gc_active(GC_fn_type fn, void *client_data)\n{\n  struct GC_traced_stack_sect_s stacksect;\n  GC_thread me;\n  GC_stack_context_t crtn;\n  ptr_t stack_end;\n#  ifdef E2K\n  ptr_t saved_bs_ptr, saved_bs_end;\n  size_t saved_ps_ofs;\n#  endif\n\n  /* This will block if the world is stopped. */\n  READER_LOCK();\n\n  me = GC_self_thread_inner();\n  crtn = me->crtn;\n\n  /*\n   * Adjust our stack bottom value (this could happen unless\n   * `GC_get_stack_base()` was used which returned `GC_SUCCESS`).\n   */\n  stack_end = crtn->stack_end; /*< read of a `volatile` field */\n  GC_ASSERT(stack_end != NULL);\n  STORE_APPROX_SP_TO(*(volatile ptr_t *)&stacksect.saved_stack_ptr);\n  if (HOTTER_THAN(stack_end, stacksect.saved_stack_ptr)) {\n    crtn->stack_end = stacksect.saved_stack_ptr;\n#  if defined(I386) && defined(GC_WIN32_THREADS)\n    crtn->initial_stack_base = stacksect.saved_stack_ptr;\n#  endif\n  }\n\n  if ((me->flags & DO_BLOCKING) == 0) {\n    /* We are not inside `GC_do_blocking()` - do nothing more. */\n    READER_UNLOCK_RELEASE();\n    /* Cast `fn` to a `volatile` type to prevent its call inlining. */\n    client_data = (*(GC_fn_type volatile *)&fn)(client_data);\n    /* Prevent treating the above as a tail call. */\n    GC_noop1(COVERT_DATAFLOW(ADDR(&stacksect)));\n    return client_data; /*< result */\n  }\n\n#  if defined(GC_ENABLE_SUSPEND_THREAD) && defined(SIGNAL_BASED_STOP_WORLD)\n  while (UNLIKELY((me->ext_suspend_cnt & 1) != 0)) {\n    size_t suspend_cnt = me->ext_suspend_cnt;\n\n    READER_UNLOCK_RELEASE();\n    GC_suspend_self_inner(me, suspend_cnt);\n    READER_LOCK();\n    GC_ASSERT(me->crtn == crtn);\n  }\n#  endif\n\n  /* Setup new \"stack section\". */\n  stacksect.saved_stack_ptr = crtn->stack_ptr;\n#  ifdef E2K\n  GC_ASSERT(crtn->backing_store_end != NULL);\n  {\n    unsigned long long sz_ull;\n\n    GET_PROCEDURE_STACK_SIZE_INNER(&sz_ull);\n    saved_ps_ofs = crtn->ps_ofs;\n    GC_ASSERT(saved_ps_ofs <= (size_t)sz_ull);\n    crtn->ps_ofs = (size_t)sz_ull;\n  }\n  saved_bs_end = crtn->backing_store_end;\n  saved_bs_ptr = crtn->backing_store_ptr;\n  crtn->backing_store_ptr = NULL;\n  crtn->backing_store_end = NULL;\n#  elif defined(IA64)\n  /* This is the same as in `GC_call_with_stack_base()`. */\n  stacksect.backing_store_end = GC_save_regs_in_stack();\n  /*\n   * Unnecessarily flushes the register stack, but that probably does\n   * not hurt.\n   */\n  stacksect.saved_backing_store_ptr = crtn->backing_store_ptr;\n#  endif\n  stacksect.prev = crtn->traced_stack_sect;\n  me->flags &= (unsigned char)~DO_BLOCKING;\n  crtn->traced_stack_sect = &stacksect;\n\n  READER_UNLOCK_RELEASE();\n  client_data = (*(GC_fn_type volatile *)&fn)(client_data);\n  GC_ASSERT((me->flags & DO_BLOCKING) == 0);\n\n  /* Restore original \"stack section\". */\n  READER_LOCK();\n  GC_ASSERT(me->crtn == crtn);\n  GC_ASSERT(crtn->traced_stack_sect == &stacksect);\n#  ifdef CPPCHECK\n  GC_noop1_ptr(crtn->traced_stack_sect);\n#  endif\n  crtn->traced_stack_sect = stacksect.prev;\n#  ifdef E2K\n  GC_ASSERT(NULL == crtn->backing_store_end);\n  crtn->backing_store_end = saved_bs_end;\n  crtn->backing_store_ptr = saved_bs_ptr;\n  crtn->ps_ofs = saved_ps_ofs;\n#  elif defined(IA64)\n  crtn->backing_store_ptr = stacksect.saved_backing_store_ptr;\n#  endif\n  me->flags |= DO_BLOCKING;\n  crtn->stack_ptr = stacksect.saved_stack_ptr;\n  READER_UNLOCK_RELEASE();\n  return client_data; /*< result */\n}\n\nSTATIC void\nGC_unregister_my_thread_inner(GC_thread me)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n#  ifdef DEBUG_THREADS\n  GC_log_printf(\"Unregistering thread %p, gc_thread= %p, n_threads= %d\\n\",\n                THREAD_ID_TO_VPTR(me->id), (void *)me, GC_count_threads());\n#  endif\n  GC_ASSERT(!KNOWN_FINISHED(me));\n#  if defined(THREAD_LOCAL_ALLOC)\n  GC_destroy_thread_local(&me->tlfs);\n#  endif\n#  ifdef NACL\n  GC_nacl_shutdown_gc_thread();\n#  endif\n#  ifdef GC_PTHREADS\n#    if defined(GC_HAVE_PTHREAD_EXIT) || !defined(GC_NO_PTHREAD_CANCEL)\n  /*\n   * Handle `DISABLED_GC` flag which is set by the intercepted\n   * `pthread_cancel()` or `pthread_exit()`.\n   */\n  if ((me->flags & DISABLED_GC) != 0) {\n    GC_dont_gc--;\n  }\n#    endif\n  if ((me->flags & DETACHED) == 0) {\n    me->flags |= FINISHED;\n  } else\n#  endif\n  /* else */ {\n    GC_delete_thread(me);\n  }\n#  if defined(THREAD_LOCAL_ALLOC)\n  /*\n   * It is required to call `GC_remove_specific()` defined in\n   * `specific.c` file.\n   */\n  GC_remove_specific(GC_thread_key);\n#  endif\n}\n\nGC_API int GC_CALL\nGC_unregister_my_thread(void)\n{\n  GC_thread me;\n  IF_CANCEL(int cancel_state;)\n\n  /*\n   * Client should not unregister the thread explicitly\n   * if it is registered by `DllMain`, except for the main thread.\n   */\n#  if !defined(GC_NO_THREADS_DISCOVERY) && defined(GC_WIN32_THREADS)\n  GC_ASSERT(!GC_win32_dll_threads\n            || THREAD_ID_EQUAL(GC_main_thread_id, thread_id_self()));\n#  endif\n\n  LOCK();\n  DISABLE_CANCEL(cancel_state);\n  /*\n   * Wait for any collection that may be marking from our stack to complete\n   * before we remove this thread.\n   */\n  GC_wait_for_gc_completion(FALSE);\n  me = GC_self_thread_inner();\n  GC_ASSERT(THREAD_ID_EQUAL(me->id, thread_id_self()));\n  GC_unregister_my_thread_inner(me);\n  RESTORE_CANCEL(cancel_state);\n  UNLOCK();\n  return GC_SUCCESS;\n}\n\n#  if !defined(GC_NO_PTHREAD_CANCEL) && defined(GC_PTHREADS)\n/*\n * We should deal with the fact that apparently on Solaris and, probably,\n * on some Linux we cannot collect while a thread is exiting, since\n * signals are not handled properly.  This currently gives rise to deadlocks.\n * The only workaround seen is to intercept `pthread_cancel()` and\n * `pthread_exit()`, and disable the collections until the thread exit\n * handler is called.  That is ugly, because we risk growing the heap\n * unnecessarily.  But it seems that we do not really have an option in that\n * the process is not in a fully functional state while a thread is exiting.\n */\n#    define GC_wrap_pthread_cancel WRAP_FUNC(pthread_cancel)\nGC_API int\nGC_wrap_pthread_cancel(pthread_t thread)\n{\n#    ifdef CANCEL_SAFE\n  GC_thread t;\n#    endif\n\n  INIT_REAL_SYMS();\n#    ifdef CANCEL_SAFE\n  LOCK();\n  t = GC_lookup_by_pthread(thread);\n  /*\n   * We test `DISABLED_GC` because `pthread_exit` could be called at\n   * the same time.  (If `t` is `NULL`, then `pthread_cancel()` should\n   * return `ESRCH`.)\n   */\n  if (t != NULL && (t->flags & DISABLED_GC) == 0) {\n    t->flags |= DISABLED_GC;\n    GC_dont_gc++;\n  }\n  UNLOCK();\n#    endif\n  return REAL_FUNC(pthread_cancel)(thread);\n}\n#    undef GC_wrap_pthread_cancel\n#  endif /* !GC_NO_PTHREAD_CANCEL */\n\n#  ifdef GC_HAVE_PTHREAD_EXIT\n#    define GC_wrap_pthread_exit WRAP_FUNC(pthread_exit)\nGC_API GC_PTHREAD_EXIT_ATTRIBUTE void\nGC_wrap_pthread_exit(void *retval)\n{\n  GC_thread me;\n\n  INIT_REAL_SYMS();\n  LOCK();\n  me = GC_self_thread_inner();\n  /*\n   * We test `DISABLED_GC` because someone else could call `pthread_cancel()`\n   * at the same time.\n   */\n  if (me != NULL && (me->flags & DISABLED_GC) == 0) {\n    me->flags |= DISABLED_GC;\n    GC_dont_gc++;\n  }\n  UNLOCK();\n\n  REAL_FUNC(pthread_exit)(retval);\n}\n#    undef GC_wrap_pthread_exit\n#  endif /* GC_HAVE_PTHREAD_EXIT */\n\nGC_API void GC_CALL\nGC_allow_register_threads(void)\n{\n  /*\n   * Check the collector is initialized and the current thread is\n   * registered.\n   */\n  GC_ASSERT(GC_self_thread() != NULL);\n\n  /* Initialize symbols while still single-threaded. */\n  INIT_REAL_SYMS();\n\n  GC_init_lib_bounds();\n  GC_start_mark_threads();\n  set_need_to_lock();\n}\n\n#  if defined(PTHREAD_STOP_WORLD_IMPL)            \\\n          && !defined(NO_SIGNALS_UNBLOCK_IN_MAIN) \\\n      || defined(GC_EXPLICIT_SIGNALS_UNBLOCK)\nGC_INNER void\nGC_unblock_gc_signals(void)\n{\n  sigset_t set;\n\n  /* This is for `pthread_sigmask`. */\n  INIT_REAL_SYMS();\n\n  sigemptyset(&set);\n  sigaddset(&set, GC_get_suspend_signal());\n  sigaddset(&set, GC_get_thr_restart_signal());\n  if (REAL_FUNC(pthread_sigmask)(SIG_UNBLOCK, &set, NULL) != 0)\n    ABORT(\"pthread_sigmask failed\");\n}\n#  endif /* PTHREAD_STOP_WORLD_IMPL || GC_EXPLICIT_SIGNALS_UNBLOCK */\n\nGC_API int GC_CALL\nGC_register_my_thread(const struct GC_stack_base *sb)\n{\n  GC_thread me;\n\n  if (!GC_need_to_lock)\n    ABORT(\"Threads explicit registering is not previously enabled\");\n\n  /* We lock here, since we want to wait for an ongoing GC. */\n  LOCK();\n  me = GC_self_thread_inner();\n  if (LIKELY(NULL == me)) {\n    me = GC_register_my_thread_inner(sb, thread_id_self());\n#  ifdef GC_PTHREADS\n#    ifdef CPPCHECK\n    GC_noop1(me->flags);\n#    endif\n    /*\n     * Treat as detached, since we do not need to worry about pointer\n     * results.\n     */\n    me->flags |= DETACHED;\n#  else\n    (void)me;\n#  endif\n  } else {\n#  ifdef GC_PTHREADS\n    if (KNOWN_FINISHED(me)) {\n      /*\n       * This code is executed when a thread is registered from the destructor\n       * of the client thread key.\n       */\n#    ifdef NACL\n      GC_nacl_initialize_gc_thread(me);\n#    endif\n#    ifdef DARWIN\n      /*\n       * Reinitialize `mach_thread` to avoid `thread_suspend()` fail\n       * with `MACH_SEND_INVALID_DEST` error.\n       */\n      me->mach_thread = mach_thread_self();\n#    endif\n      GC_record_stack_base(me->crtn, sb);\n      me->flags &= (unsigned char)~FINISHED; /*< but not `DETACHED` */\n    } else\n#  endif\n    /* else */ {\n      UNLOCK();\n      return GC_DUPLICATE;\n    }\n  }\n\n#  ifdef THREAD_LOCAL_ALLOC\n  GC_init_thread_local(&me->tlfs);\n#  endif\n#  ifdef GC_EXPLICIT_SIGNALS_UNBLOCK\n  /*\n   * Since this could be executed from a thread destructor,\n   * our signals might already be blocked.\n   */\n  GC_unblock_gc_signals();\n#  endif\n#  if defined(GC_ENABLE_SUSPEND_THREAD) && defined(SIGNAL_BASED_STOP_WORLD)\n  if (UNLIKELY((me->ext_suspend_cnt & 1) != 0)) {\n    GC_with_callee_saves_pushed(GC_suspend_self_blocked, (ptr_t)me);\n  }\n#  endif\n  UNLOCK();\n  return GC_SUCCESS;\n}\n\n#  if defined(GC_PTHREADS) && !defined(PLATFORM_THREADS) \\\n      && !defined(SN_TARGET_PSP2)\n\nGC_INNER_PTHRSTART void\nGC_thread_exit_proc(void *arg)\n{\n  GC_thread me = (GC_thread)arg;\n  IF_CANCEL(int cancel_state;)\n\n#    ifdef DEBUG_THREADS\n  GC_log_printf(\"Called GC_thread_exit_proc on %p, gc_thread= %p\\n\",\n                THREAD_ID_TO_VPTR(me->id), (void *)me);\n#    endif\n  LOCK();\n  DISABLE_CANCEL(cancel_state);\n  GC_wait_for_gc_completion(FALSE);\n  GC_unregister_my_thread_inner(me);\n  RESTORE_CANCEL(cancel_state);\n  UNLOCK();\n}\n\n#    define GC_wrap_pthread_join WRAP_FUNC(pthread_join)\nGC_API int\nGC_wrap_pthread_join(pthread_t thread, void **retval)\n{\n  int result;\n  GC_thread t;\n\n  INIT_REAL_SYMS();\n#    ifdef DEBUG_THREADS\n  GC_log_printf(\"thread %p is joining thread %p\\n\",\n                PTHREAD_TO_VPTR(pthread_self()), PTHREAD_TO_VPTR(thread));\n#    endif\n\n  /* After the join, thread id may have been recycled. */\n  READER_LOCK();\n  t = (GC_thread)COVERT_DATAFLOW_P(GC_lookup_by_pthread(thread));\n  /*\n   * This is guaranteed to be the intended one, since the thread id\n   * cannot have been recycled by `pthreads`.\n   */\n  READER_UNLOCK();\n\n  result = REAL_FUNC(pthread_join)(thread, retval);\n#    ifdef FREEBSD\n  /*\n   * On FreeBSD, the wrapped `pthread_join()` sometimes returns (what\n   * appears to be) a spurious `EINTR` which caused the test and real code\n   * to fail gratuitously.  Having looked at system `pthreads` library\n   * source code, I see how such return code value may be generated:\n   * in one path of the code, `pthread_join()` just returns the `errno`\n   * setting of the thread being joined - this does not match the POSIX\n   * specification or the local man pages.  Thus, I have taken the liberty\n   * to catch this one spurious return value.\n   */\n  if (UNLIKELY(result == EINTR))\n    result = 0;\n#    endif\n\n  if (LIKELY(0 == result)) {\n    LOCK();\n    /*\n     * Here the `pthread_id` may have been recycled.  Delete the thread from\n     *`GC_threads` (unless it has been registered again from the destructor\n     * of the client thread key).\n     */\n    if (KNOWN_FINISHED(t)) {\n      GC_delete_thread(t);\n    }\n    UNLOCK();\n  }\n\n#    ifdef DEBUG_THREADS\n  GC_log_printf(\"thread %p join with thread %p %s\\n\",\n                PTHREAD_TO_VPTR(pthread_self()), PTHREAD_TO_VPTR(thread),\n                result != 0 ? \"failed\" : \"succeeded\");\n#    endif\n  return result;\n}\n#    undef GC_wrap_pthread_join\n\n#    define GC_wrap_pthread_detach WRAP_FUNC(pthread_detach)\nGC_API int\nGC_wrap_pthread_detach(pthread_t thread)\n{\n  int result;\n  GC_thread t;\n\n  INIT_REAL_SYMS();\n  READER_LOCK();\n  t = (GC_thread)COVERT_DATAFLOW_P(GC_lookup_by_pthread(thread));\n  READER_UNLOCK();\n  result = REAL_FUNC(pthread_detach)(thread);\n  if (LIKELY(0 == result)) {\n    LOCK();\n    /* Here the `pthread_id` may have been recycled. */\n    if (KNOWN_FINISHED(t)) {\n      GC_delete_thread(t);\n    } else {\n      t->flags |= DETACHED;\n    }\n    UNLOCK();\n  }\n  return result;\n}\n#    undef GC_wrap_pthread_detach\n\nstruct start_info {\n  void *(*start_routine)(void *);\n  void *arg;\n  /*\n   * Note: a value of 1 means the thread is in our thread table, but\n   * the parent process has not noticed it yet.\n   */\n  sem_t registered;\n  unsigned char flags;\n};\n\nGC_INNER_PTHRSTART GC_thread\nGC_start_rtn_prepare_thread(void *(**pstart)(void *), void **pstart_arg,\n                            struct GC_stack_base *sb, void *arg)\n{\n  struct start_info *psi = (struct start_info *)arg;\n  thread_id_t self_id = thread_id_self();\n  GC_thread me;\n\n#    ifdef DEBUG_THREADS\n  GC_log_printf(\"Starting thread %p, sp= %p\\n\",\n                PTHREAD_TO_VPTR(pthread_self()), (void *)GC_approx_sp());\n#    endif\n  /*\n   * If a collection occurs before the thread is registered, that collection\n   * will ignore this thread.  That is fine, since it will block trying to\n   * acquire the allocator lock, and will not yet hold interesting pointers.\n   */\n  LOCK();\n  /*\n   * We register the thread here instead of in the parent process, so that\n   * we do not need to hold the allocator lock during `pthread_create()`\n   * call.\n   */\n  me = GC_register_my_thread_inner(sb, self_id);\n  GC_ASSERT(me != &first_thread);\n  me->flags = psi->flags;\n#    ifdef GC_WIN32_THREADS\n  GC_win32_cache_self_pthread(self_id);\n#    endif\n#    ifdef THREAD_LOCAL_ALLOC\n  GC_init_thread_local(&me->tlfs);\n#    endif\n  UNLOCK();\n\n  *pstart = psi->start_routine;\n  *pstart_arg = psi->arg;\n#    if defined(DEBUG_THREADS) && defined(FUNCPTR_IS_DATAPTR)\n  GC_log_printf(\"start_routine= %p\\n\", CAST_THRU_UINTPTR(void *, *pstart));\n#    endif\n  sem_post(&psi->registered);\n  /* This was the last action on `*psi`; OK to deallocate. */\n  return me;\n}\n\nSTATIC void *\nGC_pthread_start(void *arg)\n{\n#    ifdef INCLUDE_LINUX_THREAD_DESCR\n  struct GC_stack_base sb;\n\n#      ifdef REDIRECT_MALLOC\n  /*\n   * `GC_get_stack_base()` may call `pthread_getattr_np()`, which\n   * can unfortunately call `realloc()`, which may allocate from\n   * an unregistered thread.  This is unpleasant, since it might\n   * force heap growth (or, even, heap overflow).\n   */\n  GC_disable();\n#      endif\n  if (GC_get_stack_base(&sb) != GC_SUCCESS)\n    ABORT(\"Failed to get thread stack base\");\n#      ifdef REDIRECT_MALLOC\n  GC_enable();\n#      endif\n  return GC_pthread_start_inner(&sb, arg);\n#    else\n  return GC_call_with_stack_base(GC_pthread_start_inner, arg);\n#    endif\n}\n\n#    define GC_wrap_pthread_create WRAP_FUNC(pthread_create)\nGC_API int\nGC_wrap_pthread_create(pthread_t *new_thread,\n                       GC_PTHREAD_CREATE_CONST pthread_attr_t *attr,\n                       void *(*start_routine)(void *), void *arg)\n{\n  int result;\n  struct start_info si;\n\n  GC_ASSERT(I_DONT_HOLD_LOCK());\n  INIT_REAL_SYMS();\n  if (UNLIKELY(!GC_is_initialized))\n    GC_init();\n  GC_ASSERT(GC_thr_initialized);\n\n  GC_init_lib_bounds();\n  if (sem_init(&si.registered, GC_SEM_INIT_PSHARED, 0) == -1)\n    ABORT(\"sem_init failed\");\n  si.flags = 0;\n  si.start_routine = start_routine;\n  si.arg = arg;\n\n  /*\n   * We resist the temptation to muck with the stack size here, even if the\n   * default is unreasonably small.  That is the client's responsibility.\n   */\n#    ifdef GC_ASSERTIONS\n  {\n    size_t stack_size = 0;\n    if (NULL != attr) {\n      if (pthread_attr_getstacksize(attr, &stack_size) != 0)\n        ABORT(\"pthread_attr_getstacksize failed\");\n    }\n    if (0 == stack_size) {\n      pthread_attr_t my_attr;\n\n      if (pthread_attr_init(&my_attr) != 0)\n        ABORT(\"pthread_attr_init failed\");\n      if (pthread_attr_getstacksize(&my_attr, &stack_size) != 0)\n        ABORT(\"pthread_attr_getstacksize failed\");\n      (void)pthread_attr_destroy(&my_attr);\n    }\n    /*\n     * On Solaris 10 and on Win32 with `winpthreads` library, with the\n     * default `attr` initialization, `stack_size` remains 0; fudge it.\n     */\n    if (UNLIKELY(0 == stack_size)) {\n#      if !defined(SOLARIS) && !defined(GC_WIN32_PTHREADS)\n      WARN(\"Failed to get stack size for assertion checking\\n\", 0);\n#      endif\n      stack_size = 1000000;\n    }\n    GC_ASSERT(stack_size >= 65536);\n    /*\n     * Our threads may need to do some work for the GC.\n     * Ridiculously small threads will not work, and they\n     * probably would not work anyway.\n     */\n  }\n#    endif\n\n  if (attr != NULL) {\n    int detachstate;\n\n    if (pthread_attr_getdetachstate(attr, &detachstate) != 0)\n      ABORT(\"pthread_attr_getdetachstate failed\");\n    if (PTHREAD_CREATE_DETACHED == detachstate)\n      si.flags |= DETACHED;\n  }\n\n#    ifdef PARALLEL_MARK\n  if (!GC_parallel && UNLIKELY(GC_available_markers_m1 > 0))\n    GC_start_mark_threads();\n#    endif\n#    ifdef DEBUG_THREADS\n  GC_log_printf(\"About to start new thread from thread %p\\n\",\n                PTHREAD_TO_VPTR(pthread_self()));\n#    endif\n  set_need_to_lock();\n  result = REAL_FUNC(pthread_create)(new_thread, attr, GC_pthread_start, &si);\n\n  /*\n   * Wait until child has been added to the thread table.\n   * This also ensures that we hold onto the stack-allocated `si`\n   * until the child is done with it.\n   */\n  if (LIKELY(0 == result)) {\n    IF_CANCEL(int cancel_state;)\n\n    /* `pthread_create()` is not a cancellation point. */\n    DISABLE_CANCEL(cancel_state);\n\n    while (sem_wait(&si.registered) == -1) {\n#    ifdef HAIKU\n      /* To workaround some bug in Haiku semaphores. */\n      if (EACCES == errno)\n        continue;\n#    endif\n      if (errno != EINTR)\n        ABORT(\"sem_wait failed\");\n    }\n    RESTORE_CANCEL(cancel_state);\n  }\n  sem_destroy(&si.registered);\n  return result;\n}\n#    undef GC_wrap_pthread_create\n\n#  endif /* GC_PTHREADS && !PLATFORM_THREADS && !SN_TARGET_PSP2 */\n\n#  if ((defined(GC_PTHREADS_PARAMARK) || defined(USE_PTHREAD_LOCKS)) \\\n       && !defined(NO_PTHREAD_TRYLOCK))                              \\\n      || defined(USE_SPIN_LOCK)\n/*\n * Spend a few cycles in a way that cannot introduce contention with\n * other threads.\n */\n#    define GC_PAUSE_SPIN_CYCLES 10\nSTATIC void\nGC_pause(void)\n{\n  int i;\n\n  for (i = 0; i < GC_PAUSE_SPIN_CYCLES; ++i) {\n    /* Something that is unlikely to be optimized away. */\n#    if defined(AO_HAVE_compiler_barrier) && !defined(BASE_ATOMIC_OPS_EMULATED)\n    AO_compiler_barrier();\n#    else\n    GC_noop1(i);\n#    endif\n  }\n}\n#  endif /* USE_SPIN_LOCK || !NO_PTHREAD_TRYLOCK */\n\n#  ifndef SPIN_MAX\n/* Maximum number of calls to `GC_pause()` before give up. */\n#    define SPIN_MAX 128\n#  endif\n\n#  if (!defined(USE_SPIN_LOCK) && !defined(NO_PTHREAD_TRYLOCK) \\\n       && defined(USE_PTHREAD_LOCKS))                          \\\n      || defined(GC_PTHREADS_PARAMARK)\n/*\n * If we do not want to use the below spinlock implementation, either\n * because we do not have a `GC_test_and_set` implementation, or because\n * we do not want to risk sleeping, we can still try spinning\n * on `pthread_mutex_trylock` for a while.  This appears to be very\n * beneficial in many cases.\n * I suspect that under high contention this is nearly always better\n * than the spin lock.  But it is a bit slower on a uniprocessor.\n * Hence we still default to the spin lock.  This is also used to\n * acquire the mark lock for the parallel marker.\n *\n * Here we use a strict exponential back-off scheme.  I do not know\n * whether that is better or worse than the above.  We eventually\n * yield by calling `pthread_mutex_lock()`; it never makes sense to\n * explicitly sleep.\n */\n\n#    ifdef LOCK_STATS\n/* Note that `LOCK_STATS` requires `AO_HAVE_test_and_set`. */\nvolatile AO_t GC_spin_count = 0;\nvolatile AO_t GC_block_count = 0;\nvolatile AO_t GC_unlocked_count = 0;\n#    endif\n\nSTATIC void\nGC_generic_lock(pthread_mutex_t *lock)\n{\n#    ifndef NO_PTHREAD_TRYLOCK\n  unsigned pause_length = 1;\n  unsigned i;\n\n  if (LIKELY(0 == pthread_mutex_trylock(lock))) {\n#      ifdef LOCK_STATS\n    (void)AO_fetch_and_add1(&GC_unlocked_count);\n#      endif\n    return;\n  }\n  for (; pause_length <= (unsigned)SPIN_MAX; pause_length <<= 1) {\n    for (i = 0; i < pause_length; ++i) {\n      GC_pause();\n    }\n    switch (pthread_mutex_trylock(lock)) {\n    case 0:\n#      ifdef LOCK_STATS\n      (void)AO_fetch_and_add1(&GC_spin_count);\n#      endif\n      return;\n    case EBUSY:\n      break;\n    default:\n      ABORT(\"Unexpected error from pthread_mutex_trylock\");\n    }\n  }\n#    endif /* !NO_PTHREAD_TRYLOCK */\n#    ifdef LOCK_STATS\n  (void)AO_fetch_and_add1(&GC_block_count);\n#    endif\n  pthread_mutex_lock(lock);\n}\n#  endif /* !USE_SPIN_LOCK || ... */\n\n#  if defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS)\nGC_INNER volatile unsigned char GC_collecting = FALSE;\n\n#    if defined(AO_HAVE_char_load) && !defined(BASE_ATOMIC_OPS_EMULATED)\n#      define is_collecting() ((GC_bool)AO_char_load(&GC_collecting))\n#    else\n/*\n * `GC_collecting` is a hint, a potential data race between `GC_lock()`\n * and `ENTER_GC()`/`EXIT_GC()` is OK to ignore.\n */\n#      define is_collecting() ((GC_bool)GC_collecting)\n#    endif\n#  endif /* GC_PTHREADS && !GC_WIN32_THREADS */\n\n#  ifdef GC_ASSERTIONS\nGC_INNER unsigned long GC_lock_holder = NO_THREAD;\n#  endif\n\n#  if defined(USE_SPIN_LOCK)\n/*\n * Reasonably fast spin locks.  Basically the same implementation as\n * in STL `alloc.h` file.  This is not really the right way to do this\n * but until the POSIX scheduling mess gets straightened out...\n */\n\n/* Spin cycles if we suspect we are running on an uniprocessor. */\n#    define low_spin_max 30\n\n/* Spin cycles for a multiprocessor. */\n#    define high_spin_max SPIN_MAX\n\nstatic volatile AO_t spin_max = low_spin_max;\n\n/*\n * A potential data race between threads invoking `GC_lock` which reads\n * and updates `spin_max` and `last_spins` could be ignored because these\n * variables are hints only.\n */\nstatic volatile AO_t last_spins = 0;\n\nGC_INNER void\nGC_lock(void)\n{\n  AO_t my_spin_max, my_last_spins_half;\n  size_t i;\n\n  if (LIKELY(AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_CLEAR))\n    return;\n\n  my_spin_max = AO_load(&spin_max);\n  my_last_spins_half = AO_load(&last_spins) / 2;\n  for (i = 0; i < my_spin_max; i++) {\n    if (is_collecting() || GC_nprocs == 1)\n      goto yield;\n    if (i < my_last_spins_half) {\n      GC_pause();\n      continue;\n    }\n    if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_CLEAR) {\n      /*\n       * Got it, spinning worked!  Thus we are probably not being\n       * scheduled against the other process with which we were\n       * contending.  Thus it makes sense to spin longer the next time.\n       */\n      AO_store(&last_spins, i);\n      AO_store(&spin_max, high_spin_max);\n      return;\n    }\n  }\n  /* We are probably being scheduled against the other process.  Sleep. */\n  AO_store(&spin_max, low_spin_max);\nyield:\n  for (i = 0;; ++i) {\n    if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_CLEAR) {\n      return;\n    }\n\n    /*\n     * Under Linux, very short sleeps tend to wait until the current time\n     * quantum expires.  On old Linux kernels, `nanosleep()` (<= 2 ms) just\n     * spins.  (Under Linux 2.4, this happens only for real-time processes.)\n     * We want to minimize both behaviors here.\n     */\n#    define SLEEP_THRESHOLD 12\n\n    if (i < SLEEP_THRESHOLD) {\n      sched_yield();\n    } else {\n      struct timespec ts;\n\n      /*\n       * Do not wait for more than about 15 ms, even under extreme\n       * contention.\n       */\n      if (i > 24)\n        i = 24;\n\n      ts.tv_sec = 0;\n      ts.tv_nsec = (unsigned32)1 << i;\n      nanosleep(&ts, 0);\n    }\n  }\n}\n\n#  elif defined(USE_PTHREAD_LOCKS)\n#    ifdef USE_RWLOCK\nGC_INNER pthread_rwlock_t GC_allocate_ml = PTHREAD_RWLOCK_INITIALIZER;\n#    else\nGC_INNER pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;\n#    endif\n\n#    ifndef NO_PTHREAD_TRYLOCK\nGC_INNER void\nGC_lock(void)\n{\n  if (1 == GC_nprocs || is_collecting()) {\n    pthread_mutex_lock(&GC_allocate_ml);\n  } else {\n    GC_generic_lock(&GC_allocate_ml);\n  }\n}\n#    elif defined(GC_ASSERTIONS)\nGC_INNER void\nGC_lock(void)\n{\n#      ifdef USE_RWLOCK\n  (void)pthread_rwlock_wrlock(&GC_allocate_ml); /*< exclusive */\n#      else\n  pthread_mutex_lock(&GC_allocate_ml);\n#      endif\n}\n#    endif /* NO_PTHREAD_TRYLOCK && GC_ASSERTIONS */\n\n#  endif /* !USE_SPIN_LOCK && USE_PTHREAD_LOCKS */\n\n#  ifdef GC_PTHREADS_PARAMARK\n\n#    if defined(GC_ASSERTIONS) && defined(GC_WIN32_THREADS) \\\n        && !defined(USE_PTHREAD_LOCKS)\n/* Note: result is not guaranteed to be unique. */\n#      define NUMERIC_THREAD_ID(id) ((unsigned long)ADDR(PTHREAD_TO_VPTR(id)))\n#    endif\n\n#    ifdef GC_ASSERTIONS\n#      define SET_MARK_LOCK_HOLDER \\\n        (void)(GC_mark_lock_holder = NUMERIC_THREAD_ID(pthread_self()))\n#      define UNSET_MARK_LOCK_HOLDER                       \\\n        do {                                               \\\n          GC_ASSERT(GC_mark_lock_holder                    \\\n                    == NUMERIC_THREAD_ID(pthread_self())); \\\n          GC_mark_lock_holder = NO_THREAD;                 \\\n        } while (0)\n#    else\n#      define SET_MARK_LOCK_HOLDER (void)0\n#      define UNSET_MARK_LOCK_HOLDER (void)0\n#    endif /* !GC_ASSERTIONS */\n\nstatic pthread_cond_t builder_cv = PTHREAD_COND_INITIALIZER;\n\n#    ifndef GC_WIN32_THREADS\nstatic void\nsetup_mark_lock(void)\n{\n#      ifdef GLIBC_2_19_TSX_BUG\n  pthread_mutexattr_t mattr;\n  int glibc_minor = -1;\n  int glibc_major = GC_parse_version(&glibc_minor, gnu_get_libc_version());\n\n  if (glibc_major > 2 || (glibc_major == 2 && glibc_minor >= 19)) {\n    /* TODO: Disable this workaround for `glibc` with fixed TSX. */\n    /* This disables lock elision to workaround a bug in `glibc` 2.19+. */\n    if (pthread_mutexattr_init(&mattr) != 0)\n      ABORT(\"pthread_mutexattr_init failed\");\n    if (pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_NORMAL) != 0)\n      ABORT(\"pthread_mutexattr_settype failed\");\n    if (pthread_mutex_init(&mark_mutex, &mattr) != 0)\n      ABORT(\"pthread_mutex_init failed\");\n    (void)pthread_mutexattr_destroy(&mattr);\n  }\n#      endif\n}\n#    endif /* !GC_WIN32_THREADS */\n\nGC_INNER void\nGC_acquire_mark_lock(void)\n{\n#    if defined(NUMERIC_THREAD_ID_UNIQUE) && !defined(THREAD_SANITIZER)\n  GC_ASSERT(GC_mark_lock_holder != NUMERIC_THREAD_ID(pthread_self()));\n#    endif\n  GC_generic_lock(&mark_mutex);\n  SET_MARK_LOCK_HOLDER;\n}\n\nGC_INNER void\nGC_release_mark_lock(void)\n{\n  UNSET_MARK_LOCK_HOLDER;\n  if (pthread_mutex_unlock(&mark_mutex) != 0)\n    ABORT(\"pthread_mutex_unlock failed\");\n}\n\n/*\n * Collector must wait for free-list builders for 2 reasons:\n *   - Mark bits may still be getting examined without lock;\n *   - Partial free lists referenced only by locals may not be scanned\n *     correctly, e.g. if they contain \"pointer-free\" objects, since the\n *     free-list link may be ignored.\n */\nSTATIC void\nGC_wait_builder(void)\n{\n  ASSERT_CANCEL_DISABLED();\n  UNSET_MARK_LOCK_HOLDER;\n  if (pthread_cond_wait(&builder_cv, &mark_mutex) != 0)\n    ABORT(\"pthread_cond_wait failed\");\n  GC_ASSERT(GC_mark_lock_holder == NO_THREAD);\n  SET_MARK_LOCK_HOLDER;\n}\n\nGC_INNER void\nGC_wait_for_reclaim(void)\n{\n  GC_acquire_mark_lock();\n  while (GC_fl_builder_count > 0) {\n    GC_wait_builder();\n  }\n  GC_release_mark_lock();\n}\n\n#    if defined(CAN_HANDLE_FORK) && defined(THREAD_SANITIZER)\n/*\n * Identical to `GC_wait_for_reclaim()` but with the `no_sanitize`\n * attribute as a workaround for TSan which does not notice that the\n * allocator lock is acquired in `fork_prepare_proc()`.\n */\nGC_ATTR_NO_SANITIZE_THREAD\nstatic void\nwait_for_reclaim_atfork(void)\n{\n  GC_acquire_mark_lock();\n  while (GC_fl_builder_count > 0)\n    GC_wait_builder();\n  GC_release_mark_lock();\n}\n#    endif /* CAN_HANDLE_FORK && THREAD_SANITIZER */\n\nGC_INNER void\nGC_notify_all_builder(void)\n{\n  GC_ASSERT(GC_mark_lock_holder == NUMERIC_THREAD_ID(pthread_self()));\n  if (pthread_cond_broadcast(&builder_cv) != 0)\n    ABORT(\"pthread_cond_broadcast failed\");\n}\n\nGC_INNER void\nGC_wait_marker(void)\n{\n  ASSERT_CANCEL_DISABLED();\n  GC_ASSERT(GC_parallel);\n  UNSET_MARK_LOCK_HOLDER;\n  if (pthread_cond_wait(&mark_cv, &mark_mutex) != 0)\n    ABORT(\"pthread_cond_wait failed\");\n  GC_ASSERT(GC_mark_lock_holder == NO_THREAD);\n  SET_MARK_LOCK_HOLDER;\n}\n\nGC_INNER void\nGC_notify_all_marker(void)\n{\n  GC_ASSERT(GC_parallel);\n  if (pthread_cond_broadcast(&mark_cv) != 0)\n    ABORT(\"pthread_cond_broadcast failed\");\n}\n\n#  endif /* GC_PTHREADS_PARAMARK */\n\nGC_INNER GC_on_thread_event_proc GC_on_thread_event = 0;\n\nGC_API void GC_CALL\nGC_set_on_thread_event(GC_on_thread_event_proc fn)\n{\n  /* Note: `fn` may be 0 (means no event notifier). */\n  LOCK();\n  GC_on_thread_event = fn;\n  UNLOCK();\n}\n\nGC_API GC_on_thread_event_proc GC_CALL\nGC_get_on_thread_event(void)\n{\n  GC_on_thread_event_proc fn;\n\n  READER_LOCK();\n  fn = GC_on_thread_event;\n  READER_UNLOCK();\n  return fn;\n}\n\n#  ifdef STACKPTR_CORRECTOR_AVAILABLE\nGC_INNER GC_sp_corrector_proc GC_sp_corrector = 0;\n#  endif\n\nGC_API void GC_CALL\nGC_set_sp_corrector(GC_sp_corrector_proc fn)\n{\n#  ifdef STACKPTR_CORRECTOR_AVAILABLE\n  LOCK();\n  GC_sp_corrector = fn;\n  UNLOCK();\n#  else\n  UNUSED_ARG(fn);\n#  endif\n}\n\nGC_API GC_sp_corrector_proc GC_CALL\nGC_get_sp_corrector(void)\n{\n#  ifdef STACKPTR_CORRECTOR_AVAILABLE\n  GC_sp_corrector_proc fn;\n\n  READER_LOCK();\n  fn = GC_sp_corrector;\n  READER_UNLOCK();\n  return fn;\n#  else\n  return 0; /*< unsupported */\n#  endif\n}\n\n#  ifdef PTHREAD_REGISTER_CANCEL_WEAK_STUBS\n/* Workaround \"undefined reference\" linkage errors on some targets. */\nEXTERN_C_BEGIN\nextern void __pthread_register_cancel(void) __attribute__((__weak__));\nextern void __pthread_unregister_cancel(void) __attribute__((__weak__));\nEXTERN_C_END\n\nvoid\n__pthread_register_cancel(void)\n{\n}\nvoid\n__pthread_unregister_cancel(void)\n{\n}\n#  endif\n\n#  undef do_blocking_enter\n\n#endif /* THREADS */\n\n/*\n * Copyright (c) 2000 by Hewlett-Packard Company.  All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * To determine type of `tsd` implementation; includes `private/specific.h`\n * file if needed.\n */\n\n#if defined(USE_CUSTOM_SPECIFIC)\n\n/*\n * A thread-specific data entry which will never appear valid to a reader.\n * Used to fill in empty cache entries to avoid a check for 0.\n */\nstatic const tse invalid_tse = { INVALID_QTID, 0, 0, INVALID_THREADID };\n\nGC_INNER int\nGC_key_create_inner(tsd **key_ptr)\n{\n  int i;\n  int ret;\n  tsd *result;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  /* A quick alignment check, since we need atomic stores. */\n  GC_ASSERT(ADDR(&invalid_tse.next) % ALIGNMENT == 0);\n  result = (tsd *)MALLOC_CLEAR(sizeof(tsd));\n  if (NULL == result)\n    return ENOMEM;\n  ret = pthread_mutex_init(&result->lock, NULL);\n  if (ret != 0)\n    return ret;\n\n  for (i = 0; i < TS_CACHE_SIZE; ++i) {\n    result->cache[i] = (tse *)GC_CAST_AWAY_CONST_PVOID(&invalid_tse);\n  }\n#  ifdef GC_ASSERTIONS\n  for (i = 0; i < TS_HASH_SIZE; ++i) {\n    GC_ASSERT(NULL == result->hash[i]);\n  }\n#  endif\n  *key_ptr = result;\n  return 0;\n}\n\nGC_INNER int\nGC_setspecific(tsd *key, void *value)\n{\n  pthread_t self = pthread_self();\n  unsigned hash_val = TS_HASH(self);\n  volatile tse *entry;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(self != INVALID_THREADID);\n  /* Disable garbage collection during `GC_malloc`. */\n  GC_dont_gc++;\n  entry = (volatile tse *)MALLOC_CLEAR(sizeof(tse));\n  GC_dont_gc--;\n  if (UNLIKELY(NULL == entry))\n    return ENOMEM;\n\n  pthread_mutex_lock(&key->lock);\n  entry->next = key->hash[hash_val];\n#  ifdef GC_ASSERTIONS\n  {\n    tse *p;\n\n    /* Ensure no existing entry. */\n    for (p = entry->next; p != NULL; p = p->next) {\n      GC_ASSERT(!THREAD_EQUAL(p->thread, self));\n    }\n  }\n#  endif\n  entry->thread = self;\n  entry->value = TS_HIDE_VALUE(value);\n  GC_ASSERT(entry->qtid == INVALID_QTID);\n  /*\n   * There can only be one writer at a time, but this needs to be atomic\n   * with respect to concurrent readers.\n   */\n  GC_cptr_store_release((volatile ptr_t *)&key->hash[hash_val],\n                        (ptr_t)CAST_AWAY_VOLATILE_PVOID(entry));\n  GC_dirty(CAST_AWAY_VOLATILE_PVOID(entry));\n  GC_dirty(key->hash + hash_val);\n  if (pthread_mutex_unlock(&key->lock) != 0)\n    ABORT(\"pthread_mutex_unlock failed (setspecific)\");\n  return 0;\n}\n\nGC_INNER void\nGC_remove_specific_after_fork(tsd *key, pthread_t t)\n{\n  unsigned hash_val = TS_HASH(t);\n  tse *entry;\n  tse *prev = NULL;\n\n#  ifdef CAN_HANDLE_FORK\n  /*\n   * Both `GC_setspecific` and `GC_remove_specific` should be called with\n   * the allocator lock held to ensure the consistency of the hash table\n   * in the forked child process.\n   */\n  GC_ASSERT(I_HOLD_LOCK());\n#  endif\n  pthread_mutex_lock(&key->lock);\n  for (entry = key->hash[hash_val];\n       entry != NULL && !THREAD_EQUAL(entry->thread, t); entry = entry->next) {\n    prev = entry;\n  }\n  /*\n   * Invalidate `qtid` field, since `qtid` values may be reused, and\n   * a later cache lookup could otherwise find this `entry`.\n   */\n  if (entry != NULL) {\n    entry->qtid = INVALID_QTID;\n    if (NULL == prev) {\n      key->hash[hash_val] = entry->next;\n      GC_dirty(key->hash + hash_val);\n    } else {\n      prev->next = entry->next;\n      GC_dirty(prev);\n    }\n    /*\n     * Atomic! Concurrent accesses still work.  They must, since readers\n     * do not lock.  We should not need a `volatile` access here, since\n     * both this and the preceding write should become visible no later\n     * than the `pthread_mutex_unlock()` call.\n     */\n  }\n  /*\n   * If we wanted to deallocate the entry, we would first have to clear\n   * any cache entries pointing to it.  That probably requires additional\n   * synchronization, since we cannot prevent a concurrent cache lookup,\n   * which should still be examining deallocated memory.  This can only\n   * happen if the concurrent access is from another thread, and hence\n   * has missed the cache, but still...\n   */\n#  ifdef LINT2\n  GC_noop1_ptr(entry);\n#  endif\n\n  /*\n   * With GC, we are done, since the pointers from the cache will be\n   * overwritten, all local pointers to the entries will be dropped,\n   * and the entry will then be reclaimed.\n   */\n  if (pthread_mutex_unlock(&key->lock) != 0)\n    ABORT(\"pthread_mutex_unlock failed (remove_specific after fork)\");\n}\n\n#  ifdef CAN_HANDLE_FORK\nGC_INNER void\nGC_update_specific_after_fork(tsd *key)\n{\n  unsigned hash_val = TS_HASH(GC_parent_pthread_self);\n  tse *entry;\n\n  GC_ASSERT(I_HOLD_LOCK());\n#    ifdef LINT2\n  pthread_mutex_lock(&key->lock);\n#    endif\n  entry = key->hash[hash_val];\n  if (LIKELY(entry != NULL)) {\n    GC_ASSERT(THREAD_EQUAL(entry->thread, GC_parent_pthread_self));\n    GC_ASSERT(NULL == entry->next);\n    /* Remove the `entry` from the table. */\n    key->hash[hash_val] = NULL;\n    entry->thread = pthread_self();\n    /* Then put the `entry` back to the table (based on new hash value). */\n    key->hash[TS_HASH(entry->thread)] = entry;\n  }\n#    ifdef LINT2\n  (void)pthread_mutex_unlock(&key->lock);\n#    endif\n}\n#  endif\n\nGC_INNER void *\nGC_slow_getspecific(tsd *key, size_t qtid, tse *volatile *cache_ptr)\n{\n  pthread_t self = pthread_self();\n  tse *entry = key->hash[TS_HASH(self)];\n\n  GC_ASSERT(qtid != INVALID_QTID);\n  while (entry != NULL && !THREAD_EQUAL(entry->thread, self)) {\n    entry = entry->next;\n  }\n  if (entry == NULL)\n    return NULL;\n  /*\n   * Set the cache `entry`.  It is safe to do this asynchronously.\n   * Either value is safe, though may produce spurious misses.\n   * We are replacing one `qtid` with another one for the same thread.\n   */\n  AO_store(&entry->qtid, qtid);\n\n  GC_cptr_store((volatile ptr_t *)cache_ptr, (ptr_t)entry);\n  return TS_REVEAL_PTR(entry->value);\n}\n\n#  ifdef GC_ASSERTIONS\n/*\n * Check that that all elements of the data structure associated with\n * `key` are marked.\n */\nvoid\nGC_check_tsd_marks(tsd *key)\n{\n  int i;\n  tse *p;\n\n  if (!GC_is_marked(GC_base(key))) {\n    ABORT(\"Unmarked thread-specific-data table\");\n  }\n  for (i = 0; i < TS_HASH_SIZE; ++i) {\n    for (p = key->hash[i]; p != NULL; p = p->next) {\n      if (!GC_is_marked(GC_base(p))) {\n        ABORT_ARG1(\"Unmarked thread-specific-data entry\", \" at %p\", (void *)p);\n      }\n    }\n  }\n  for (i = 0; i < TS_CACHE_SIZE; ++i) {\n    p = key->cache[i];\n    if (p != &invalid_tse && !GC_is_marked(GC_base(p))) {\n      ABORT_ARG1(\"Unmarked cached thread-specific-data entry\", \" at %p\",\n                 (void *)p);\n    }\n  }\n}\n#  endif /* GC_ASSERTIONS */\n\n#endif /* USE_CUSTOM_SPECIFIC */\n\n/*\n * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.\n * Copyright (c) 2000-2008 by Hewlett-Packard Development Company.\n * All rights reserved.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n\n#if defined(GC_WIN32_THREADS)\n\n/* The allocator lock definition. */\n#  ifndef USE_PTHREAD_LOCKS\n#    ifdef USE_RWLOCK\nGC_INNER SRWLOCK GC_allocate_ml;\n#    else\nGC_INNER CRITICAL_SECTION GC_allocate_ml;\n#    endif\n#  endif /* !USE_PTHREAD_LOCKS */\n\n#  undef CreateThread\n#  undef ExitThread\n#  undef _beginthreadex\n#  undef _endthreadex\n\n#  if !defined(GC_PTHREADS) && !defined(MSWINCE)\n#    include <errno.h>\n#    include <process.h> /*< for `_beginthreadex`, `_endthreadex` */\n#  endif\n\nstatic ptr_t copy_ptr_regs(word *regs, const CONTEXT *pcontext);\n\n#  ifndef GC_NO_THREADS_DISCOVERY\n/*\n * This code operates in two distinct modes, depending on the setting\n * of `GC_win32_dll_threads`.  If `GC_win32_dll_threads`, then all\n * threads in the process are implicitly registered with the collector\n * by `DllMain()`.  No explicit registration is required, and attempts\n * at explicit registration are ignored.  This mode is very different\n * from the POSIX operation of the collector.  In this mode access to\n * the thread table is lock-free.  Hence there is a static limit on the\n * number of threads.\n */\n\n/*\n * `GC_DISCOVER_TASK_THREADS` should be used if `DllMain`-based thread\n * registration is required but it is impossible to call\n * `GC_use_threads_discovery()` before other GC routines.\n */\n\n#    ifndef GC_DISCOVER_TASK_THREADS\nGC_INNER GC_bool GC_win32_dll_threads = FALSE;\n#    endif\n#  else\n/*\n * If not `GC_win32_dll_threads` (or the collector is built without `GC_DLL`\n * macro defined), things operate in a way that is very similar to POSIX\n * platforms, and new threads must be registered with the collector,\n * e.g. by using preprocessor-based interception of the thread primitives.\n * In this case, we use a real data structure for the thread table.\n * Note that there is no equivalent of linker-based call interception,\n * since we do not have ELF-like facilities.  The Windows analog appears\n * to be \"API hooking\", which really seems to be a standard way to do minor\n * binary rewriting (?).  I would prefer not to have the basic collector\n * rely on such facilities, but an optional package that intercepts thread\n * calls this way would probably be nice.\n */\n#    undef MAX_THREADS\n/* `dll_thread_table[]` is always empty. */\n#    define MAX_THREADS 1\n#  endif /* GC_NO_THREADS_DISCOVERY */\n\n/*\n * We have two variants of the thread table.  Which one we use depends\n * on whether `GC_win32_dll_threads` is set.  Note that before the\n * initialization, we do not add any entries to either table, even\n * if `DllMain()` is called.  The main thread will be added on the\n * collector initialization.\n */\n\nGC_API void GC_CALL\nGC_use_threads_discovery(void)\n{\n#  ifdef GC_NO_THREADS_DISCOVERY\n  /*\n   * `GC_use_threads_discovery()` is currently incompatible with\n   * `pthreads` and WinCE.  It might be possible to get `DllMain`-based\n   * thread registration to work with Cygwin, but if you try it then\n   * you are on your own.\n   */\n  ABORT(\"GC DllMain-based thread registration unsupported\");\n#  else\n  /* Turn on `GC_win32_dll_threads`. */\n  GC_ASSERT(!GC_is_initialized);\n  /*\n   * Note that `GC_use_threads_discovery()` is expected to be called by\n   * the client application (not from `DllMain()`) at start-up.\n   */\n#    ifndef GC_DISCOVER_TASK_THREADS\n  GC_win32_dll_threads = TRUE;\n#    endif\n  GC_init();\n#    ifdef CPPCHECK\n  GC_noop1((word)(GC_funcptr_uint)(&GC_DllMain));\n#    endif\n#  endif\n}\n\n#  ifndef GC_NO_THREADS_DISCOVERY\n/*\n * We track thread attachments while the world is supposed to be stopped.\n * Unfortunately, we cannot stop them from starting, since blocking in\n * `DllMain` seems to cause the world to deadlock.  Thus, we have to\n * recover if we notice this in the middle of marking.\n */\nSTATIC volatile AO_t GC_attached_thread = FALSE;\n\n/*\n * We assume that `volatile` implies memory ordering, at least among\n * `volatile` variables.  This code should consistently use `libatomic_ops`\n * package or gcc atomic intrinsics.\n */\nSTATIC volatile GC_bool GC_please_stop = FALSE;\n#  elif defined(GC_ASSERTIONS)\nSTATIC GC_bool GC_please_stop = FALSE;\n#  endif /* GC_NO_THREADS_DISCOVERY && GC_ASSERTIONS */\n\n#  if defined(WRAP_MARK_SOME) && !defined(GC_PTHREADS)\nGC_INNER GC_bool\nGC_started_thread_while_stopped(void)\n{\n#    ifndef GC_NO_THREADS_DISCOVERY\n  if (GC_win32_dll_threads) {\n#      ifdef AO_HAVE_compare_and_swap_release\n    if (AO_compare_and_swap_release(&GC_attached_thread, TRUE,\n                                    FALSE /* stored */))\n      return TRUE;\n#      else\n    /* Prior heap reads need to complete earlier. */\n    AO_nop_full();\n\n    if (AO_load(&GC_attached_thread)) {\n      AO_store(&GC_attached_thread, FALSE);\n      return TRUE;\n    }\n#      endif\n  }\n#    endif\n  return FALSE;\n}\n#  endif /* WRAP_MARK_SOME */\n\n/*\n * The thread table used if `GC_win32_dll_threads`.  This is a fixed-size\n * array.  Since we use runtime conditionals, both variants are always\n * defined.\n */\n#  ifndef MAX_THREADS\n#    define MAX_THREADS 512\n#  endif\n\n/*\n * Things may get quite slow for large numbers of threads,\n * since we look them up with the sequential search.\n */\nstatic volatile struct GC_Thread_Rep dll_thread_table[MAX_THREADS];\n#  ifndef GC_NO_THREADS_DISCOVERY\nstatic struct GC_StackContext_Rep dll_crtn_table[MAX_THREADS];\n#  endif\n\nGC_INNER GC_thread\nGC_register_my_thread_inner(const struct GC_stack_base *sb,\n                            thread_id_t self_id)\n{\n  GC_thread me;\n\n#  ifdef GC_NO_THREADS_DISCOVERY\n  GC_ASSERT(I_HOLD_LOCK());\n#  endif\n  /*\n   * The following should be a no-op according to the Win32 documentation.\n   * There is an empirical evidence that it is not.\n   */\n#  if defined(MPROTECT_VDB) && !defined(CYGWIN32)\n  if (GC_auto_incremental\n#    ifdef GWW_VDB\n      && !GC_gww_dirty_init()\n#    endif\n  )\n    GC_set_write_fault_handler();\n#  endif\n\n#  ifndef GC_NO_THREADS_DISCOVERY\n  if (GC_win32_dll_threads) {\n    int i;\n    /*\n     * It appears to be unsafe to acquire a lock here, since this code\n     * is apparently not preemptible on some systems.  (This is based on\n     * complaints, not on Microsoft's official documentation, which says\n     * this should perform \"only simple initialization tasks\".)\n     * Hence we make it does with a nonblocking synchronization.\n     * It has been claimed that `DllMain` is really only executed with\n     * a particular system lock held, and thus careful use of locking\n     * around code that does not call back into the system libraries might\n     * be OK.  (But this has not been tested across all Win32 versions.)\n     */\n    for (i = 0;\n         InterlockedExchange(&dll_thread_table[i].tm.long_in_use, 1) != 0;\n         i++) {\n      /*\n       * Compare-and-swap would make this cleaner, but that is not\n       * supported before Windows 98 and NT 4.0.  In Windows 2000,\n       * `InterlockedExchange` is supposed to be replaced by\n       * `InterlockedExchangePointer`, but that is not really what\n       * is needed here.\n       */\n\n      /*\n       * FIXME: We should eventually declare Windows 95 dead and use\n       * AO primitives here.\n       */\n      if (i == MAX_THREADS - 1)\n        ABORT(\"Too many threads\");\n    }\n    /*\n     * Update `GC_max_thread_index` if necessary.  The following is safe,\n     * and unlike `CompareExchange`-based solutions seems to work on all\n     * Windows 95 and later platforms.  Note that `GC_max_thread_index`\n     * may be temporarily out of bounds, so readers have to compensate.\n     */\n    while (i > GC_max_thread_index) {\n      InterlockedIncrement((LONG *)&GC_max_thread_index);\n      /* Cast away `volatile` for older versions of Win32 headers. */\n    }\n    if (UNLIKELY(GC_max_thread_index >= MAX_THREADS)) {\n      /*\n       * We overshot due to simultaneous increments.\n       * Setting it to `MAX_THREADS - 1` is always safe.\n       */\n      GC_max_thread_index = MAX_THREADS - 1;\n    }\n    me = (GC_thread)(dll_thread_table + i);\n    me->crtn = &dll_crtn_table[i];\n  } else\n#  endif\n  /* else */ {\n    /* Not using `DllMain`. */\n    me = GC_new_thread(self_id);\n  }\n#  ifdef GC_PTHREADS\n  me->pthread_id = pthread_self();\n#  endif\n#  ifndef MSWINCE\n  /* `GetCurrentThread()` returns a pseudohandle (a constant value). */\n  if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),\n                       GetCurrentProcess(), (HANDLE *)&me->handle,\n                       0 /* `dwDesiredAccess` */, FALSE /* `bInheritHandle` */,\n                       DUPLICATE_SAME_ACCESS)) {\n    ABORT_ARG1(\"DuplicateHandle failed\", \": errcode= 0x%X\",\n               (unsigned)GetLastError());\n  }\n#  endif\n#  if defined(WOW64_THREAD_CONTEXT_WORKAROUND) && defined(MSWINRT_FLAVOR)\n  /*\n   * Lookup TIB value via a call to `NtCurrentTeb()` on thread registration\n   * rather than calling `GetThreadSelectorEntry()` which is not available\n   * on UWP.\n   */\n  me->tib = (GC_NT_TIB *)NtCurrentTeb();\n#  endif\n  me->crtn->last_stack_min = ADDR_LIMIT;\n  GC_record_stack_base(me->crtn, sb);\n  /*\n   * Up until this point, `GC_push_all_stacks` considers this thread\n   * invalid.  And, up until this point, the entry is viewed by\n   * `GC_win32_dll_lookup_thread` as reserved but invalid.\n   */\n  ((volatile struct GC_Thread_Rep *)me)->id = self_id;\n#  ifndef GC_NO_THREADS_DISCOVERY\n  if (GC_win32_dll_threads) {\n    if (GC_please_stop) {\n      AO_store(&GC_attached_thread, TRUE);\n      AO_nop_full(); /*< later updates must become visible after this */\n    }\n    /*\n     * We would like to wait here, but cannot, since waiting in `DllMain()`\n     * provokes deadlocks.  Thus we force marking to be restarted instead.\n     */\n  } else\n#  endif\n  /* else */ {\n    /*\n     * `GC_please_stop` is `FALSE`, otherwise both we and the thread-stopping\n     * code would be holding the allocator lock.\n     */\n    GC_ASSERT(!GC_please_stop);\n  }\n  return me;\n}\n\n/*\n * `GC_max_thread_index` may temporarily be larger than `MAX_THREADS`.\n * To avoid subscript errors, we check it on access.\n */\nGC_INLINE LONG\nGC_get_max_thread_index(void)\n{\n  LONG my_max = GC_max_thread_index;\n  if (UNLIKELY(my_max >= MAX_THREADS))\n    return MAX_THREADS - 1;\n  return my_max;\n}\n\n#  ifndef GC_NO_THREADS_DISCOVERY\nGC_INNER GC_thread\nGC_win32_dll_lookup_thread(thread_id_t id)\n{\n  int i;\n  LONG my_max = GC_get_max_thread_index();\n\n  GC_ASSERT(GC_win32_dll_threads);\n  for (i = 0; i <= my_max; i++) {\n    if (AO_load_acquire(&dll_thread_table[i].tm.in_use)\n        && dll_thread_table[i].id == id) {\n      /*\n       * Must still be in use, since nobody else can store our\n       * thread `id`.\n       */\n      break;\n    }\n  }\n  return i <= my_max ? (GC_thread)(dll_thread_table + i) : NULL;\n}\n#  endif /* !GC_NO_THREADS_DISCOVERY */\n\n#  ifdef GC_PTHREADS\n/*\n * A quick-and-dirty cache of the mapping between `pthread_t` and\n * Win32 thread id.\n */\n#    define PTHREAD_MAP_SIZE 512\nthread_id_t GC_pthread_map_cache[PTHREAD_MAP_SIZE] = { 0 };\n/* It appears `pthread_t` is really a pointer type... */\n#    define PTHREAD_MAP_INDEX(pthread_id) \\\n      ((NUMERIC_THREAD_ID(pthread_id) >> 5) % PTHREAD_MAP_SIZE)\n#    define SET_PTHREAD_MAP_CACHE(pthread_id, win32_id) \\\n      (void)(GC_pthread_map_cache[PTHREAD_MAP_INDEX(pthread_id)] = (win32_id))\n#    define GET_PTHREAD_MAP_CACHE(pthread_id) \\\n      GC_pthread_map_cache[PTHREAD_MAP_INDEX(pthread_id)]\n\nGC_INNER void\nGC_win32_cache_self_pthread(thread_id_t self_id)\n{\n  pthread_t self = pthread_self();\n\n  GC_ASSERT(I_HOLD_LOCK());\n  SET_PTHREAD_MAP_CACHE(self, self_id);\n}\n\nGC_INNER GC_thread\nGC_lookup_by_pthread(pthread_t thread)\n{\n  /*\n   * TODO: Search in `dll_thread_table` instead when `DllMain`-based thread\n   * registration is made compatible with `pthreads` (and turned on).\n   */\n  thread_id_t id;\n  GC_thread p;\n  int hv;\n\n  GC_ASSERT(I_HOLD_READER_LOCK());\n  id = GET_PTHREAD_MAP_CACHE(thread);\n  /* We first try the cache. */\n  for (p = GC_threads[THREAD_TABLE_INDEX(id)]; p != NULL; p = p->tm.next) {\n    if (LIKELY(THREAD_EQUAL(p->pthread_id, thread)))\n      return p;\n  }\n\n  /* If that fails, we use a very slow approach. */\n  for (hv = 0; hv < THREAD_TABLE_SZ; ++hv) {\n    for (p = GC_threads[hv]; p != NULL; p = p->tm.next) {\n      if (THREAD_EQUAL(p->pthread_id, thread))\n        return p;\n    }\n  }\n  return NULL;\n}\n#  endif /* GC_PTHREADS */\n\n#  ifdef WOW64_THREAD_CONTEXT_WORKAROUND\n#    ifndef CONTEXT_EXCEPTION_ACTIVE\n#      define CONTEXT_EXCEPTION_ACTIVE 0x08000000\n#      define CONTEXT_EXCEPTION_REQUEST 0x40000000\n#      define CONTEXT_EXCEPTION_REPORTING 0x80000000\n#    endif\n/* Is 32-bit code running on Win64? */\nstatic GC_bool isWow64;\n#    define GET_THREAD_CONTEXT_FLAGS                                \\\n      (isWow64 ? CONTEXT_INTEGER | CONTEXT_CONTROL                  \\\n                     | CONTEXT_EXCEPTION_REQUEST | CONTEXT_SEGMENTS \\\n               : CONTEXT_INTEGER | CONTEXT_CONTROL)\n#  elif defined(I386) || defined(XMM_CANT_STORE_PTRS)\n#    define GET_THREAD_CONTEXT_FLAGS (CONTEXT_INTEGER | CONTEXT_CONTROL)\n#  else\n#    define GET_THREAD_CONTEXT_FLAGS \\\n      (CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_FLOATING_POINT)\n#  endif /* !WOW64_THREAD_CONTEXT_WORKAROUND && !I386 */\n\n/* Suspend the given thread, if it is still active. */\nSTATIC void\nGC_suspend(GC_thread t)\n{\n#  ifndef MSWINCE\n  DWORD exitCode;\n#    ifdef RETRY_GET_THREAD_CONTEXT\n  int retry_cnt;\n#      define MAX_SUSPEND_THREAD_RETRIES (1000 * 1000)\n#    endif\n#  endif\n\n  GC_ASSERT(I_HOLD_LOCK());\n#  ifndef GC_NO_THREADS_DISCOVERY\n  if (NULL == GC_cptr_load_acquire(&t->handle))\n    return;\n#  endif\n#  if defined(DEBUG_THREADS) && !defined(MSWINCE) \\\n      && (!defined(MSWIN32) || defined(CONSOLE_LOG))\n  GC_log_printf(\"Suspending 0x%x\\n\", (int)t->id);\n#  endif\n  GC_win32_unprotect_thread(t);\n  GC_acquire_dirty_lock();\n\n#  ifdef MSWINCE\n  /* `SuspendThread()` will fail if thread is running kernel code. */\n  while (SuspendThread(THREAD_HANDLE(t)) == (DWORD)-1) {\n    GC_release_dirty_lock();\n    Sleep(10); /*< in millis */\n    GC_acquire_dirty_lock();\n  }\n#  elif defined(RETRY_GET_THREAD_CONTEXT)\n  for (retry_cnt = 0;;) {\n    /*\n     * Apparently the Windows 95 `GetOpenFileName()` creates a thread\n     * that does not properly get cleaned up, and `SuspendThread()` on\n     * its descriptor may provoke a crash.  This reduces the probability\n     * of that event, though it still appears there is a race here.\n     */\n    if (GetExitCodeThread(t->handle, &exitCode) && exitCode != STILL_ACTIVE) {\n      GC_release_dirty_lock();\n#    ifdef GC_PTHREADS\n      /* Prevent stack from being pushed. */\n      t->crtn->stack_end = NULL;\n#    else\n      /*\n       * This breaks `pthread_join` on Cygwin, which is guaranteed to\n       * only see user threads.\n       */\n      GC_delete_thread(t);\n#    endif\n      return;\n    }\n\n    if (SuspendThread(t->handle) != (DWORD)-1) {\n      CONTEXT context;\n\n      /*\n       * Calls to `GetThreadContext()` may fail.  Work around this by\n       * putting access in suspend/resume loop to advance thread past\n       * problematic areas where suspend fails.  Capture the `context`\n       * in per-thread structure at the suspend time rather than at\n       * retrieving the `context` during the push logic.\n       */\n      context.ContextFlags = GET_THREAD_CONTEXT_FLAGS;\n      if (GetThreadContext(t->handle, &context)) {\n        /*\n         * TODO: WoW64 extra workaround: if `CONTEXT_EXCEPTION_ACTIVE`\n         * then `Sleep(1)` and retry.\n         */\n        t->context_sp = copy_ptr_regs(t->context_regs, &context);\n        /* Success; the context pointer registers are saved. */\n        break;\n      }\n\n      /* Resume the thread, try to suspend it in a better location. */\n      if (ResumeThread(t->handle) == (DWORD)-1) {\n#    ifndef GC_NO_THREADS_DISCOVERY\n        if (NULL == GC_cptr_load_acquire(&t->handle)) {\n          /*\n           * It might be the scenario like this:\n           *   1. `GC_suspend` calls `SuspendThread` on a valid handle;\n           *   2. Within the `SuspendThread` call a context switch\n           *      occurs to `DllMain` (before the thread has actually\n           *      been suspended);\n           *   3. `DllMain` sets `t->handle` to `NULL`, but does not\n           *      yet close the handle;\n           *   4. A context switch occurs returning to `SuspendThread`\n           *      which completes on the handle that was originally\n           *      passed into it;\n           *   5. Then `ResumeThread` attempts to run on `t->handle`\n           *      which is now `NULL`.\n           */\n          GC_release_dirty_lock();\n          /*\n           * FIXME: The thread seems to be suspended forever (causing\n           * a resource leak).\n           */\n          WARN(\"ResumeThread failed (async CloseHandle by DllMain)\\n\", 0);\n          return;\n        }\n#    endif\n        ABORT(\"ResumeThread failed in suspend loop\");\n      }\n    } else {\n#    ifndef GC_NO_THREADS_DISCOVERY\n      if (NULL == GC_cptr_load_acquire(&t->handle)) {\n        /* The thread handle is closed asynchronously by `GC_DllMain`. */\n        GC_release_dirty_lock();\n        return;\n      }\n#    endif\n    }\n    if (retry_cnt > 1) {\n      GC_release_dirty_lock();\n      Sleep(0); /*< yield */\n#    ifndef GC_NO_THREADS_DISCOVERY\n      if (NULL == GC_cptr_load_acquire(&t->handle))\n        return;\n#    endif\n      GC_acquire_dirty_lock();\n    }\n    if (++retry_cnt >= MAX_SUSPEND_THREAD_RETRIES) {\n      /* Something must be wrong. */\n      ABORT(\"SuspendThread loop failed\");\n    }\n  }\n#  else\n  if (GetExitCodeThread(t->handle, &exitCode) && exitCode != STILL_ACTIVE) {\n    GC_release_dirty_lock();\n#    ifdef GC_PTHREADS\n    /* Prevent stack from being pushed. */\n    t->crtn->stack_end = NULL;\n#    else\n    GC_delete_thread(t);\n#    endif\n    return;\n  }\n  if (SuspendThread(t->handle) == (DWORD)-1) {\n#    ifndef GC_NO_THREADS_DISCOVERY\n    if (NULL == GC_cptr_load_acquire(&t->handle)) {\n      GC_release_dirty_lock();\n      return;\n    }\n#    endif\n    ABORT(\"SuspendThread failed\");\n  }\n#  endif\n  t->flags |= IS_SUSPENDED;\n  GC_release_dirty_lock();\n  if (GC_on_thread_event)\n    GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED, THREAD_HANDLE(t));\n}\n\n#  if defined(GC_ASSERTIONS) \\\n      && ((defined(MSWIN32) && !defined(CONSOLE_LOG)) || defined(MSWINCE))\nGC_INNER GC_bool GC_write_disabled = FALSE;\n#  endif\n\nGC_INNER void\nGC_stop_world(void)\n{\n  thread_id_t self_id = GetCurrentThreadId();\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_thr_initialized);\n\n  /* This code is the same as in `pthread_stop_world.c` file. */\n#  ifdef PARALLEL_MARK\n  if (GC_parallel) {\n    GC_acquire_mark_lock();\n    /* We should have previously waited for the count to become zero. */\n    GC_ASSERT(0 == GC_fl_builder_count);\n  }\n#  endif /* PARALLEL_MARK */\n\n#  if !defined(GC_NO_THREADS_DISCOVERY) || defined(GC_ASSERTIONS)\n  GC_please_stop = TRUE;\n#  endif\n#  if (defined(MSWIN32) && !defined(CONSOLE_LOG)) || defined(MSWINCE)\n  GC_ASSERT(!GC_write_disabled);\n  EnterCriticalSection(&GC_write_cs);\n  /*\n   * It is not allowed to call `GC_printf()` (and friends) here down to\n   * `LeaveCriticalSection` (same applies recursively to `GC_suspend`,\n   * `GC_delete_thread`, `GC_get_max_thread_index`, `GC_size` and\n   * `GC_remove_protection`).\n   */\n#    ifdef GC_ASSERTIONS\n  GC_write_disabled = TRUE;\n#    endif\n#  endif\n#  ifndef GC_NO_THREADS_DISCOVERY\n  if (GC_win32_dll_threads) {\n    int i;\n    int my_max;\n\n    /*\n     * Any threads being created during this loop will end up setting\n     * `GC_attached_thread` when they start.  This will force marking\n     * to restart.  This is not ideal, but hopefully correct.\n     */\n    AO_store(&GC_attached_thread, FALSE);\n    my_max = (int)GC_get_max_thread_index();\n    for (i = 0; i <= my_max; i++) {\n      GC_thread p = (GC_thread)(dll_thread_table + i);\n\n      if (p->crtn->stack_end != NULL && (p->flags & DO_BLOCKING) == 0\n          && p->id != self_id) {\n        GC_suspend(p);\n      }\n    }\n  } else\n#  endif\n  /* else */ {\n    GC_thread p;\n    int i;\n\n    for (i = 0; i < THREAD_TABLE_SZ; i++) {\n      for (p = GC_threads[i]; p != NULL; p = p->tm.next)\n        if (p->crtn->stack_end != NULL && p->id != self_id\n            && (p->flags & (FINISHED | DO_BLOCKING)) == 0)\n          GC_suspend(p);\n    }\n  }\n#  if (defined(MSWIN32) && !defined(CONSOLE_LOG)) || defined(MSWINCE)\n#    ifdef GC_ASSERTIONS\n  GC_write_disabled = FALSE;\n#    endif\n  LeaveCriticalSection(&GC_write_cs);\n#  endif\n#  ifdef PARALLEL_MARK\n  if (GC_parallel)\n    GC_release_mark_lock();\n#  endif\n}\n\nGC_INNER void\nGC_start_world(void)\n{\n#  ifdef GC_ASSERTIONS\n  thread_id_t self_id = GetCurrentThreadId();\n#  endif\n\n  GC_ASSERT(I_HOLD_LOCK());\n#  ifndef GC_NO_THREADS_DISCOVERY\n  if (GC_win32_dll_threads) {\n    LONG my_max = GC_get_max_thread_index();\n    int i;\n\n    for (i = 0; i <= my_max; i++) {\n      GC_thread p = (GC_thread)(dll_thread_table + i);\n\n      if ((p->flags & IS_SUSPENDED) != 0) {\n#    ifdef DEBUG_THREADS\n        GC_log_printf(\"Resuming 0x%x\\n\", (int)p->id);\n#    endif\n        GC_ASSERT(p->id != self_id);\n        GC_ASSERT(*(ptr_t *)CAST_AWAY_VOLATILE_PVOID(&p->crtn->stack_end)\n                  != NULL);\n        if (ResumeThread(p->handle) == (DWORD)-1) {\n          if (NULL == GC_cptr_load_acquire(&p->handle)) {\n            /* FIXME: See the same issue in `GC_suspend`. */\n            WARN(\"ResumeThread failed (async CloseHandle by DllMain)\\n\", 0);\n          } else {\n            ABORT(\"ResumeThread failed\");\n          }\n        }\n        p->flags &= (unsigned char)~IS_SUSPENDED;\n        if (GC_on_thread_event)\n          GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, p->handle);\n      } else {\n        /* The thread is unregistered or not suspended. */\n      }\n    }\n  } else\n#  endif\n  /* else */ {\n    GC_thread p;\n    int i;\n\n    for (i = 0; i < THREAD_TABLE_SZ; i++) {\n      for (p = GC_threads[i]; p != NULL; p = p->tm.next) {\n        if ((p->flags & IS_SUSPENDED) != 0) {\n#  ifdef DEBUG_THREADS\n          GC_log_printf(\"Resuming 0x%x\\n\", (int)p->id);\n#  endif\n          GC_ASSERT(p->id != self_id && *(ptr_t *)&p->crtn->stack_end != NULL);\n          if (ResumeThread(THREAD_HANDLE(p)) == (DWORD)-1)\n            ABORT(\"ResumeThread failed\");\n          GC_win32_unprotect_thread(p);\n          p->flags &= (unsigned char)~IS_SUSPENDED;\n          if (GC_on_thread_event)\n            GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, THREAD_HANDLE(p));\n        } else {\n#  ifdef DEBUG_THREADS\n          GC_log_printf(\"Not resuming thread 0x%x as it is not suspended\\n\",\n                        (int)p->id);\n#  endif\n        }\n      }\n    }\n  }\n#  if !defined(GC_NO_THREADS_DISCOVERY) || defined(GC_ASSERTIONS)\n  GC_please_stop = FALSE;\n#  endif\n}\n\n#  ifdef MSWINCE\n/*\n * The `VirtualQuery()` calls below will not work properly on some old\n * WinCE versions, but since each stack is restricted to an aligned\n * 64 KiB region of virtual memory we can just take the next lowest\n * multiple of 64 KiB.  The result of this macro must not be used as\n * its argument later and must not be used as the lower bound for `sp`\n * check (since the stack may be bigger than 64 KiB).\n */\n#    define GC_wince_evaluate_stack_min(s) \\\n      (ptr_t)(((word)(s) - (word)1) & ~(word)0xFFFF)\n#  elif defined(GC_ASSERTIONS)\n#    define GC_dont_query_stack_min FALSE\n#  endif\n\n/*\n * A cache holding the results of the recent `VirtualQuery()` call.\n * Protected by the allocator lock.\n */\nstatic ptr_t last_address = 0;\nstatic MEMORY_BASIC_INFORMATION last_info;\n\n/*\n * Probe stack memory region (starting at `s`) to find out its lowest\n * address (i.e. stack top).  `s` must be a mapped address inside the\n * region, *not* the first unmapped address.\n */\nSTATIC ptr_t\nGC_get_stack_min(ptr_t s)\n{\n  ptr_t bottom;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (s != last_address) {\n    VirtualQuery(s, &last_info, sizeof(last_info));\n    last_address = s;\n  }\n  do {\n    bottom = (ptr_t)last_info.BaseAddress;\n    VirtualQuery(bottom - 1, &last_info, sizeof(last_info));\n    last_address = bottom - 1;\n  } while ((last_info.Protect & PAGE_READWRITE)\n           && !(last_info.Protect & PAGE_GUARD));\n  return bottom;\n}\n\n/*\n * Return `TRUE` if the page at `s` has protections appropriate for\n * a stack page.\n */\nstatic GC_bool\nmay_be_in_stack(ptr_t s)\n{\n  GC_ASSERT(I_HOLD_LOCK());\n  if (s != last_address) {\n    VirtualQuery(s, &last_info, sizeof(last_info));\n    last_address = s;\n  }\n  return (last_info.Protect & PAGE_READWRITE) != 0\n         && (last_info.Protect & PAGE_GUARD) == 0;\n}\n\n/*\n * Copy all registers that might point into the heap.  Frame pointer\n * registers are included in case client code was compiled with the\n * \"omit frame pointer\" optimization.  The context register values are\n * stored to `regs` argument which is expected to be of `PUSHED_REGS_COUNT`\n * length exactly.  Returns the context stack pointer value.\n */\nstatic ptr_t\ncopy_ptr_regs(word *regs, const CONTEXT *pcontext)\n{\n  ptr_t sp;\n  int cnt = 0;\n#  define context (*pcontext)\n#  define PUSH1(reg) (regs[cnt++] = (word)pcontext->reg)\n#  define PUSH2(r1, r2) (PUSH1(r1), PUSH1(r2))\n#  define PUSH4(r1, r2, r3, r4) (PUSH2(r1, r2), PUSH2(r3, r4))\n#  define PUSH8_LH(r1, r2, r3, r4)            \\\n    (PUSH4(r1.Low, r1.High, r2.Low, r2.High), \\\n     PUSH4(r3.Low, r3.High, r4.Low, r4.High))\n#  if defined(I386)\n#    ifdef WOW64_THREAD_CONTEXT_WORKAROUND\n  /*\n   * Notes: these should be the first \"pushed\" registers, exactly in this\n   * order, see the WoW64 logic in `GC_push_stack_for()`; these registers\n   * do not contain pointers.\n   */\n  PUSH2(ContextFlags, SegFs);\n#    endif\n  PUSH4(Edi, Esi, Ebx, Edx), PUSH2(Ecx, Eax), PUSH1(Ebp);\n  sp = (ptr_t)context.Esp;\n#  elif defined(X86_64)\n  PUSH4(Rax, Rcx, Rdx, Rbx);\n  PUSH2(Rbp, Rsi);\n  PUSH1(Rdi);\n  PUSH4(R8, R9, R10, R11);\n  PUSH4(R12, R13, R14, R15);\n#    ifndef XMM_CANT_STORE_PTRS\n  PUSH8_LH(Xmm0, Xmm1, Xmm2, Xmm3);\n  PUSH8_LH(Xmm4, Xmm5, Xmm6, Xmm7);\n  PUSH8_LH(Xmm8, Xmm9, Xmm10, Xmm11);\n  PUSH8_LH(Xmm12, Xmm13, Xmm14, Xmm15);\n#    endif\n  sp = (ptr_t)context.Rsp;\n#  elif defined(ARM32)\n  PUSH4(R0, R1, R2, R3), PUSH4(R4, R5, R6, R7), PUSH4(R8, R9, R10, R11);\n  PUSH1(R12);\n  sp = (ptr_t)context.Sp;\n#  elif defined(AARCH64)\n  PUSH4(X0, X1, X2, X3), PUSH4(X4, X5, X6, X7), PUSH4(X8, X9, X10, X11);\n  PUSH4(X12, X13, X14, X15), PUSH4(X16, X17, X18, X19),\n      PUSH4(X20, X21, X22, X23);\n  PUSH4(X24, X25, X26, X27), PUSH1(X28);\n  PUSH1(Lr);\n  sp = (ptr_t)context.Sp;\n#  elif defined(SHx)\n  PUSH4(R0, R1, R2, R3), PUSH4(R4, R5, R6, R7), PUSH4(R8, R9, R10, R11);\n  PUSH2(R12, R13), PUSH1(R14);\n  sp = (ptr_t)context.R15;\n#  elif defined(MIPS)\n  PUSH4(IntAt, IntV0, IntV1, IntA0), PUSH4(IntA1, IntA2, IntA3, IntT0);\n  PUSH4(IntT1, IntT2, IntT3, IntT4), PUSH4(IntT5, IntT6, IntT7, IntS0);\n  PUSH4(IntS1, IntS2, IntS3, IntS4), PUSH4(IntS5, IntS6, IntS7, IntT8);\n  PUSH4(IntT9, IntK0, IntK1, IntS8);\n  sp = (ptr_t)context.IntSp;\n#  elif defined(PPC)\n  PUSH4(Gpr0, Gpr3, Gpr4, Gpr5), PUSH4(Gpr6, Gpr7, Gpr8, Gpr9);\n  PUSH4(Gpr10, Gpr11, Gpr12, Gpr14), PUSH4(Gpr15, Gpr16, Gpr17, Gpr18);\n  PUSH4(Gpr19, Gpr20, Gpr21, Gpr22), PUSH4(Gpr23, Gpr24, Gpr25, Gpr26);\n  PUSH4(Gpr27, Gpr28, Gpr29, Gpr30), PUSH1(Gpr31);\n  sp = (ptr_t)context.Gpr1;\n#  elif defined(ALPHA)\n  PUSH4(IntV0, IntT0, IntT1, IntT2), PUSH4(IntT3, IntT4, IntT5, IntT6);\n  PUSH4(IntT7, IntS0, IntS1, IntS2), PUSH4(IntS3, IntS4, IntS5, IntFp);\n  PUSH4(IntA0, IntA1, IntA2, IntA3), PUSH4(IntA4, IntA5, IntT8, IntT9);\n  PUSH4(IntT10, IntT11, IntT12, IntAt);\n  sp = (ptr_t)context.IntSp;\n#  elif defined(CPPCHECK)\n  GC_noop1_ptr(regs);\n  sp = (ptr_t)(word)cnt; /*< to workaround \"cnt not used\" false positive */\n#  else\n#    error Architecture is not supported\n#  endif\n#  undef context\n#  undef PUSH1\n#  undef PUSH2\n#  undef PUSH4\n#  undef PUSH8_LH\n  GC_ASSERT(cnt == PUSHED_REGS_COUNT);\n  return sp;\n}\n\nSTATIC word\nGC_push_stack_for(GC_thread thread, thread_id_t self_id, GC_bool *pfound_me)\n{\n  GC_bool is_self = FALSE;\n  ptr_t sp, stack_min;\n  GC_stack_context_t crtn = thread->crtn;\n  ptr_t stack_end = crtn->stack_end;\n  struct GC_traced_stack_sect_s *traced_stack_sect = crtn->traced_stack_sect;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  if (UNLIKELY(NULL == stack_end))\n    return 0;\n\n  if (thread->id == self_id) {\n    GC_ASSERT((thread->flags & DO_BLOCKING) == 0);\n    sp = GC_approx_sp();\n    is_self = TRUE;\n    *pfound_me = TRUE;\n  } else if ((thread->flags & DO_BLOCKING) != 0) {\n    /* Use saved `sp` value for blocked threads. */\n    sp = crtn->stack_ptr;\n  } else {\n#  ifdef RETRY_GET_THREAD_CONTEXT\n    /*\n     * We cache context when suspending the thread since it may require\n     * looping.\n     */\n    word *regs = thread->context_regs;\n\n    if ((thread->flags & IS_SUSPENDED) != 0) {\n      sp = thread->context_sp;\n    } else\n#  else\n    word regs[PUSHED_REGS_COUNT];\n#  endif\n\n    /* else */ {\n      CONTEXT context;\n\n      /* For unblocked threads call `GetThreadContext()`. */\n      context.ContextFlags = GET_THREAD_CONTEXT_FLAGS;\n      if (GetThreadContext(THREAD_HANDLE(thread), &context)) {\n        sp = copy_ptr_regs(regs, &context);\n      } else {\n#  ifndef GC_NO_THREADS_DISCOVERY\n        if (NULL == GC_cptr_load_acquire(&thread->handle))\n          return 0;\n#  endif\n#  ifdef RETRY_GET_THREAD_CONTEXT\n        /* At least, try to use the stale context if saved. */\n        sp = thread->context_sp;\n        if (NULL == sp) {\n          /*\n           * Skip the current thread; anyway its stack will be pushed\n           * when the world is stopped.\n           */\n          return 0;\n        }\n#  else\n        /* This is to avoid \"might be uninitialized\" compiler warning. */\n        *(volatile ptr_t *)&sp = NULL;\n        ABORT(\"GetThreadContext failed\");\n#  endif\n      }\n    }\n#  ifdef THREAD_LOCAL_ALLOC\n    GC_ASSERT((thread->flags & IS_SUSPENDED) != 0 || !GC_world_stopped);\n#  endif\n\n#  ifndef WOW64_THREAD_CONTEXT_WORKAROUND\n    GC_push_many_regs(regs, PUSHED_REGS_COUNT);\n#  else\n    GC_push_many_regs(regs + 2, PUSHED_REGS_COUNT - 2);\n    /* Skip `ContextFlags` and `SegFs`. */\n\n    /* WoW64 workaround. */\n    if (isWow64) {\n      DWORD ContextFlags = (DWORD)regs[0];\n\n      if ((ContextFlags & CONTEXT_EXCEPTION_REPORTING) != 0\n          && (ContextFlags\n              & (CONTEXT_EXCEPTION_ACTIVE\n                 /* `| CONTEXT_SERVICE_ACTIVE` */))\n                 != 0) {\n        GC_NT_TIB *tib;\n\n#    ifdef MSWINRT_FLAVOR\n        tib = thread->tib;\n#    else\n        WORD SegFs = (WORD)regs[1];\n        LDT_ENTRY selector;\n\n        if (!GetThreadSelectorEntry(THREAD_HANDLE(thread), SegFs, &selector))\n          ABORT(\"GetThreadSelectorEntry failed\");\n        tib = (GC_NT_TIB *)(selector.BaseLow\n                            | (selector.HighWord.Bits.BaseMid << 16)\n                            | (selector.HighWord.Bits.BaseHi << 24));\n#    endif\n#    ifdef DEBUG_THREADS\n        GC_log_printf(\"TIB stack limit/base: %p .. %p\\n\",\n                      (void *)tib->StackLimit, (void *)tib->StackBase);\n#    endif\n        GC_ASSERT(!HOTTER_THAN((ptr_t)tib->StackBase, stack_end));\n        if (stack_end != crtn->initial_stack_base\n            /* We are in a coroutine (old-style way of the support). */\n            && (ADDR(stack_end) <= (word)tib->StackLimit\n                || (word)tib->StackBase < ADDR(stack_end))) {\n          /* The coroutine stack is not within TIB stack. */\n          WARN(\"GetThreadContext might return stale register values\"\n               \" including ESP= %p\\n\",\n               sp);\n          /*\n           * TODO: Because of WoW64 bug, there is no guarantee that `sp`\n           * really points to the stack top but, for now, we do our best\n           * as the TIB stack limit/base cannot be used while we are\n           * inside a coroutine.\n           */\n        } else {\n          /*\n           * `GetThreadContext()` might return stale register values,\n           * so we scan the entire stack region (down to the stack limit).\n           * There is no 100% guarantee that all the registers are pushed\n           * but we do our best (the proper solution would be to fix it\n           * inside Windows).\n           */\n          sp = (ptr_t)tib->StackLimit;\n        }\n      } /* else */\n#    ifdef DEBUG_THREADS\n      else {\n        static GC_bool logged;\n        if (!logged && (ContextFlags & CONTEXT_EXCEPTION_REPORTING) == 0) {\n          GC_log_printf(\"CONTEXT_EXCEPTION_REQUEST not supported\\n\");\n          logged = TRUE;\n        }\n      }\n#    endif\n    }\n#  endif /* WOW64_THREAD_CONTEXT_WORKAROUND */\n  }\n#  if defined(STACKPTR_CORRECTOR_AVAILABLE) && defined(GC_PTHREADS)\n  if (GC_sp_corrector != 0)\n    GC_sp_corrector((void **)&sp, PTHREAD_TO_VPTR(thread->pthread_id));\n#  endif\n\n  /*\n   * Set `stack_min` to the lowest address in the thread stack, or to\n   * an address in the thread stack not bigger than `sp`, taking advantage\n   * of the old value to avoid slow traversals of large stacks.\n   */\n  if (crtn->last_stack_min == ADDR_LIMIT) {\n#  ifdef MSWINCE\n    if (GC_dont_query_stack_min) {\n      stack_min = GC_wince_evaluate_stack_min(\n          traced_stack_sect != NULL ? (ptr_t)traced_stack_sect : stack_end);\n      /* Keep `last_stack_min` value unmodified. */\n    } else\n#  endif\n    /* else */ {\n      stack_min = GC_get_stack_min(\n          traced_stack_sect != NULL ? (ptr_t)traced_stack_sect : stack_end);\n      GC_win32_unprotect_thread(thread);\n      crtn->last_stack_min = stack_min;\n    }\n  } else {\n    /*\n     * First, adjust the latest known minimum stack address if we are\n     * inside `GC_call_with_gc_active`.\n     */\n    if (traced_stack_sect != NULL\n        && ADDR_LT((ptr_t)traced_stack_sect, crtn->last_stack_min)) {\n      GC_win32_unprotect_thread(thread);\n      crtn->last_stack_min = (ptr_t)traced_stack_sect;\n    }\n\n    if (ADDR_INSIDE(sp, crtn->last_stack_min, stack_end)) {\n      stack_min = sp;\n    } else {\n      /* In the current thread it is always safe to use `sp` value. */\n      if (may_be_in_stack(is_self && ADDR_LT(sp, crtn->last_stack_min)\n                              ? sp\n                              : crtn->last_stack_min)) {\n        stack_min = (ptr_t)last_info.BaseAddress;\n        /* Do not probe rest of the stack if `sp` is correct. */\n        if (!ADDR_INSIDE(sp, stack_min, stack_end))\n          stack_min = GC_get_stack_min(crtn->last_stack_min);\n      } else {\n        /* Stack shrunk?  Is this possible? */\n        stack_min = GC_get_stack_min(stack_end);\n      }\n      GC_win32_unprotect_thread(thread);\n      crtn->last_stack_min = stack_min;\n    }\n  }\n\n  GC_ASSERT(GC_dont_query_stack_min || stack_min == GC_get_stack_min(stack_end)\n            || (ADDR_GE(sp, stack_min) && ADDR_LT(stack_min, stack_end)\n                && ADDR_LT(GC_get_stack_min(stack_end), stack_min)));\n\n  if (ADDR_INSIDE(sp, stack_min, stack_end)) {\n#  ifdef DEBUG_THREADS\n    GC_log_printf(\"Pushing stack for 0x%x from sp %p to %p from 0x%x\\n\",\n                  (int)thread->id, (void *)sp, (void *)stack_end,\n                  (int)self_id);\n#  endif\n    GC_push_all_stack_sections(sp, stack_end, traced_stack_sect);\n  } else {\n    /*\n     * If not the current thread, then it is possible for `sp` to point to\n     * the guarded (untouched yet) page just below the current `stack_min`\n     * of the thread.\n     */\n    if (is_self || ADDR_GE(sp, stack_end)\n        || ADDR_LT(sp + GC_page_size, stack_min))\n      WARN(\"Thread stack pointer %p out of range, pushing everything\\n\", sp);\n#  ifdef DEBUG_THREADS\n    GC_log_printf(\"Pushing stack for 0x%x from (min) %p to %p from 0x%x\\n\",\n                  (int)thread->id, (void *)stack_min, (void *)stack_end,\n                  (int)self_id);\n#  endif\n    /* Push everything - ignore \"traced stack section\" data. */\n    GC_push_all_stack(stack_min, stack_end);\n  }\n  /* Note: stack grows down. */\n  return stack_end - sp;\n}\n\nGC_INNER void\nGC_push_all_stacks(void)\n{\n  thread_id_t self_id = GetCurrentThreadId();\n  GC_bool found_me = FALSE;\n#  ifndef SMALL_CONFIG\n  unsigned nthreads = 0;\n#  endif\n  word total_size = 0;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(GC_thr_initialized);\n#  ifndef GC_NO_THREADS_DISCOVERY\n  if (GC_win32_dll_threads) {\n    int i;\n    LONG my_max = GC_get_max_thread_index();\n\n    for (i = 0; i <= my_max; i++) {\n      GC_thread p = (GC_thread)(dll_thread_table + i);\n\n      if (p->tm.in_use) {\n#    ifndef SMALL_CONFIG\n        ++nthreads;\n#    endif\n        total_size += GC_push_stack_for(p, self_id, &found_me);\n      }\n    }\n  } else\n#  endif\n  /* else */ {\n    int i;\n    for (i = 0; i < THREAD_TABLE_SZ; i++) {\n      GC_thread p;\n\n      for (p = GC_threads[i]; p != NULL; p = p->tm.next) {\n        GC_ASSERT(THREAD_TABLE_INDEX(p->id) == i);\n        if (!KNOWN_FINISHED(p)) {\n#  ifndef SMALL_CONFIG\n          ++nthreads;\n#  endif\n          total_size += GC_push_stack_for(p, self_id, &found_me);\n        }\n      }\n    }\n  }\n#  ifndef SMALL_CONFIG\n  GC_VERBOSE_LOG_PRINTF(\n      \"Pushed %d thread stacks%s\\n\", nthreads,\n      GC_win32_dll_threads ? \" based on DllMain thread tracking\" : \"\");\n#  endif\n  if (!found_me && !GC_in_thread_creation)\n    ABORT(\"Collecting from unknown thread\");\n  GC_total_stacksize = total_size;\n}\n\n#  ifdef PARALLEL_MARK\nGC_INNER ptr_t GC_marker_last_stack_min[MAX_MARKERS - 1] = { 0 };\n#  endif\n\nGC_INNER void\nGC_get_next_stack(ptr_t start, ptr_t limit, ptr_t *plo, ptr_t *phi)\n{\n  int i;\n  /* Least in-range stack base. */\n  ptr_t current_min = ADDR_LIMIT;\n  /*\n   * Address of `last_stack_min` field for thread corresponding to\n   * `current_min`.\n   */\n  ptr_t *plast_stack_min = NULL;\n  /*\n   * Either `NULL` or points to the thread's hash table entry\n   * containing `*plast_stack_min`.\n   */\n  GC_thread thread = NULL;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  /* First set `current_min`, ignoring `limit`. */\n  if (GC_win32_dll_threads) {\n    LONG my_max = GC_get_max_thread_index();\n\n    for (i = 0; i <= my_max; i++) {\n      ptr_t stack_end = (ptr_t)dll_thread_table[i].crtn->stack_end;\n\n      if (ADDR_LT(start, stack_end) && ADDR_LT(stack_end, current_min)) {\n        /* Update address of `last_stack_min`. */\n        plast_stack_min = &dll_thread_table[i].crtn->last_stack_min;\n        current_min = stack_end;\n#  ifdef CPPCHECK\n        /* To avoid a warning that thread is always null. */\n        thread = (GC_thread)&dll_thread_table[i];\n#  endif\n      }\n    }\n  } else {\n    for (i = 0; i < THREAD_TABLE_SZ; i++) {\n      GC_thread p;\n\n      for (p = GC_threads[i]; p != NULL; p = p->tm.next) {\n        GC_stack_context_t crtn = p->crtn;\n        /* Note: the following is read of a `volatile` field. */\n        ptr_t stack_end = crtn->stack_end;\n\n        if (ADDR_LT(start, stack_end) && ADDR_LT(stack_end, current_min)) {\n          /* Update value of `*plast_stack_min`. */\n          plast_stack_min = &crtn->last_stack_min;\n          /* Remember current thread to unprotect. */\n          thread = p;\n          current_min = stack_end;\n        }\n      }\n    }\n#  ifdef PARALLEL_MARK\n    for (i = 0; i < GC_markers_m1; ++i) {\n      ptr_t s = GC_marker_sp[i];\n\n#    ifdef IA64\n      /* FIXME: Not implemented. */\n#    endif\n      if (ADDR_LT(start, s) && ADDR_LT(s, current_min)) {\n        GC_ASSERT(GC_marker_last_stack_min[i] != NULL);\n        plast_stack_min = &GC_marker_last_stack_min[i];\n        current_min = s;\n        /* Not a thread's hash table entry. */\n        thread = NULL;\n      }\n    }\n#  endif\n  }\n\n  *phi = current_min;\n  if (current_min == ADDR_LIMIT) {\n    *plo = ADDR_LIMIT;\n    return;\n  }\n\n  GC_ASSERT(ADDR_LT(start, current_min) && plast_stack_min != NULL);\n#  ifdef MSWINCE\n  if (GC_dont_query_stack_min) {\n    *plo = GC_wince_evaluate_stack_min(current_min);\n    /* Keep `last_stack_min` value unmodified. */\n    return;\n  }\n#  endif\n\n  if (ADDR_LT(limit, current_min) && !may_be_in_stack(limit)) {\n    /*\n     * Skip the rest since the memory region at `limit` address is not\n     * a stack (so the lowest address of the found stack would be above\n     * the `limit` value anyway).\n     */\n    *plo = ADDR_LIMIT;\n    return;\n  }\n\n  /*\n   * Get the minimum address of the found stack by probing its memory\n   * region starting from the recent known minimum (if set).\n   */\n  if (*plast_stack_min == ADDR_LIMIT || !may_be_in_stack(*plast_stack_min)) {\n    /* Unsafe to start from `last_stack_min` value. */\n    *plo = GC_get_stack_min(current_min);\n  } else {\n    /* Use the recent value to optimize search for minimum address. */\n    *plo = GC_get_stack_min(*plast_stack_min);\n  }\n\n  /* Remember current `stack_min` value. */\n  if (thread != NULL)\n    GC_win32_unprotect_thread(thread);\n  *plast_stack_min = *plo;\n}\n\n#  if defined(PARALLEL_MARK) && !defined(GC_PTHREADS_PARAMARK)\n\n#    ifndef MARK_THREAD_STACK_SIZE\n/* The default size of the marker's thread stack. */\n#      define MARK_THREAD_STACK_SIZE 0\n#    endif\n\n/* Events with manual reset (one for each mark helper). */\nSTATIC HANDLE GC_marker_cv[MAX_MARKERS - 1] = { 0 };\n\nGC_INNER thread_id_t GC_marker_Id[MAX_MARKERS - 1] = { 0 };\n\n/*\n * `mark_mutex_event`, `builder_cv`, `mark_cv` are initialized in\n * `GC_thr_init()`.\n */\n\n/* Note: this event should be with auto-reset. */\nstatic HANDLE mark_mutex_event = (HANDLE)0;\n\n/* Note: these events are with manual reset. */\nstatic HANDLE builder_cv = (HANDLE)0;\nstatic HANDLE mark_cv = (HANDLE)0;\n\nGC_INNER void\nGC_start_mark_threads_inner(void)\n{\n  int i;\n\n  GC_ASSERT(I_HOLD_LOCK());\n  ASSERT_CANCEL_DISABLED();\n  if (GC_available_markers_m1 <= 0 || GC_parallel)\n    return;\n  GC_wait_for_gc_completion(TRUE);\n\n  GC_ASSERT(0 == GC_fl_builder_count);\n  /*\n   * Initialize `GC_marker_cv[]` fully before starting the first helper\n   * thread.\n   */\n  GC_markers_m1 = GC_available_markers_m1;\n  for (i = 0; i < GC_markers_m1; ++i) {\n    if ((GC_marker_cv[i]\n         = CreateEvent(NULL /* `attrs` */, TRUE /* `isManualReset` */,\n                       FALSE /* `initialState` */, NULL /* `name` (A/W) */))\n        == (HANDLE)0)\n      ABORT(\"CreateEvent failed\");\n  }\n\n  for (i = 0; i < GC_markers_m1; ++i) {\n#    if defined(MSWINCE) || defined(MSWIN_XBOX1)\n    HANDLE handle;\n    DWORD thread_id;\n\n    GC_marker_last_stack_min[i] = ADDR_LIMIT;\n    /* There is no `_beginthreadex()` in WinCE. */\n    handle = CreateThread(NULL /* `lpsa` */,\n                          MARK_THREAD_STACK_SIZE /* ignored */, GC_mark_thread,\n                          NUMERIC_TO_VPTR(i), 0 /* `fdwCreate` */, &thread_id);\n    if (UNLIKELY(NULL == handle)) {\n      WARN(\"Marker thread %\" WARN_PRIdPTR \" creation failed\\n\",\n           (GC_signed_word)i);\n      /*\n       * The most probable failure reason is \"not enough memory\".\n       * Do not try to create other marker threads.\n       */\n      break;\n    }\n    /* It is safe to detach the thread. */\n    CloseHandle(handle);\n#    else\n    GC_uintptr_t handle;\n    unsigned thread_id;\n\n    GC_marker_last_stack_min[i] = ADDR_LIMIT;\n    handle = _beginthreadex(NULL /* `security_attr` */, MARK_THREAD_STACK_SIZE,\n                            GC_mark_thread, NUMERIC_TO_VPTR(i),\n                            0 /* `flags` */, &thread_id);\n    if (UNLIKELY(!handle || handle == ~(GC_uintptr_t)0)) {\n      WARN(\"Marker thread %\" WARN_PRIdPTR \" creation failed\\n\",\n           (GC_signed_word)i);\n      /* Do not try to create other marker threads. */\n      break;\n    } else {\n      /* We may detach the thread (if `handle` is of `HANDLE` type). */\n      /* `CloseHandle((HANDLE)handle);` */\n    }\n#    endif\n  }\n\n  /* Adjust `GC_markers_m1` (and free unused resources) if failed. */\n  while (GC_markers_m1 > i) {\n    GC_markers_m1--;\n    CloseHandle(GC_marker_cv[GC_markers_m1]);\n  }\n  GC_wait_for_markers_init();\n  GC_COND_LOG_PRINTF(\"Started %d mark helper threads\\n\", GC_markers_m1);\n  if (UNLIKELY(0 == i)) {\n    CloseHandle(mark_cv);\n    CloseHandle(builder_cv);\n    CloseHandle(mark_mutex_event);\n  }\n}\n\n#    ifdef GC_ASSERTIONS\nSTATIC unsigned long GC_mark_lock_holder = NO_THREAD;\n#      define SET_MARK_LOCK_HOLDER \\\n        (void)(GC_mark_lock_holder = GetCurrentThreadId())\n#      define UNSET_MARK_LOCK_HOLDER                              \\\n        do {                                                      \\\n          GC_ASSERT(GC_mark_lock_holder == GetCurrentThreadId()); \\\n          GC_mark_lock_holder = NO_THREAD;                        \\\n        } while (0)\n#    else\n#      define SET_MARK_LOCK_HOLDER (void)0\n#      define UNSET_MARK_LOCK_HOLDER (void)0\n#    endif /* !GC_ASSERTIONS */\n\n/*\n * Allowed values for `GC_mark_mutex_state`.\n * `MARK_MUTEX_LOCKED` means \"locked but no other waiters\";\n * `MARK_MUTEX_WAITERS_EXIST` means \"locked and waiters may exist\".\n */\n#    define MARK_MUTEX_UNLOCKED 0\n#    define MARK_MUTEX_LOCKED 1\n#    define MARK_MUTEX_WAITERS_EXIST (-1)\n\n/* The mutex state.  Accessed using `InterlockedExchange()`. */\nSTATIC /* `volatile` */ LONG GC_mark_mutex_state = MARK_MUTEX_UNLOCKED;\n\n#    ifdef LOCK_STATS\nvolatile AO_t GC_block_count = 0;\nvolatile AO_t GC_unlocked_count = 0;\n#    endif\n\nGC_INNER void\nGC_acquire_mark_lock(void)\n{\n  GC_ASSERT(GC_mark_lock_holder != GetCurrentThreadId());\n  if (UNLIKELY(InterlockedExchange(&GC_mark_mutex_state, MARK_MUTEX_LOCKED)\n               != 0)) {\n#    ifdef LOCK_STATS\n    (void)AO_fetch_and_add1(&GC_block_count);\n#    endif\n    /* Repeatedly reset the state and wait until we acquire the mark lock. */\n    while (InterlockedExchange(&GC_mark_mutex_state, MARK_MUTEX_WAITERS_EXIST)\n           != 0) {\n      if (WaitForSingleObject(mark_mutex_event, INFINITE) == WAIT_FAILED)\n        ABORT(\"WaitForSingleObject failed\");\n    }\n  }\n#    ifdef LOCK_STATS\n  else {\n    (void)AO_fetch_and_add1(&GC_unlocked_count);\n  }\n#    endif\n\n  GC_ASSERT(GC_mark_lock_holder == NO_THREAD);\n  SET_MARK_LOCK_HOLDER;\n}\n\nGC_INNER void\nGC_release_mark_lock(void)\n{\n  UNSET_MARK_LOCK_HOLDER;\n  if (UNLIKELY(InterlockedExchange(&GC_mark_mutex_state, MARK_MUTEX_UNLOCKED)\n               < 0)) {\n    /* Wake a waiter. */\n    if (!SetEvent(mark_mutex_event))\n      ABORT(\"SetEvent failed\");\n  }\n}\n\n/*\n * In `GC_wait_for_reclaim()`/`GC_notify_all_builder()` we emulate\n * `pthread_cond_wait()`/`pthread_cond_broadcast()` primitives with\n * Win32 API event object (working in the \"manual reset\" mode).\n * This works here because `GC_notify_all_builder()` is always called\n * holding the mark lock and the checked condition\n * (`GC_fl_builder_count` is zero) is the only one for which\n * broadcasting on `builder_cv` is performed.\n */\n\nGC_INNER void\nGC_wait_for_reclaim(void)\n{\n  GC_ASSERT(builder_cv != 0);\n  for (;;) {\n    GC_acquire_mark_lock();\n    if (0 == GC_fl_builder_count)\n      break;\n    if (!ResetEvent(builder_cv))\n      ABORT(\"ResetEvent failed\");\n    GC_release_mark_lock();\n    if (WaitForSingleObject(builder_cv, INFINITE) == WAIT_FAILED)\n      ABORT(\"WaitForSingleObject failed\");\n  }\n  GC_release_mark_lock();\n}\n\nGC_INNER void\nGC_notify_all_builder(void)\n{\n  GC_ASSERT(GC_mark_lock_holder == GetCurrentThreadId());\n  GC_ASSERT(builder_cv != 0);\n  GC_ASSERT(0 == GC_fl_builder_count);\n  if (!SetEvent(builder_cv))\n    ABORT(\"SetEvent failed\");\n}\n\n/* `mark_cv` is used (for waiting) by a non-helper thread. */\n\nGC_INNER void\nGC_wait_marker(void)\n{\n  HANDLE event = mark_cv;\n  thread_id_t self_id = GetCurrentThreadId();\n  int i = GC_markers_m1;\n\n  while (i-- > 0) {\n    if (GC_marker_Id[i] == self_id) {\n      event = GC_marker_cv[i];\n      break;\n    }\n  }\n\n  if (!ResetEvent(event))\n    ABORT(\"ResetEvent failed\");\n  GC_release_mark_lock();\n  if (WaitForSingleObject(event, INFINITE) == WAIT_FAILED)\n    ABORT(\"WaitForSingleObject failed\");\n  GC_acquire_mark_lock();\n}\n\nGC_INNER void\nGC_notify_all_marker(void)\n{\n  thread_id_t self_id = GetCurrentThreadId();\n  int i = GC_markers_m1;\n\n  while (i-- > 0) {\n    /* Notify every marker ignoring self (for efficiency). */\n    if (!SetEvent(GC_marker_Id[i] != self_id ? GC_marker_cv[i] : mark_cv))\n      ABORT(\"SetEvent failed\");\n  }\n}\n\n#  endif /* PARALLEL_MARK && !GC_PTHREADS_PARAMARK */\n\n/*\n * We have no `DllMain` to take care of new threads.  Thus, we must properly\n * intercept thread creation.\n */\n\nstruct win32_start_info {\n  LPTHREAD_START_ROUTINE start_routine;\n  LPVOID arg;\n};\n\nSTATIC void *GC_CALLBACK\nGC_win32_start_inner(struct GC_stack_base *sb, void *arg)\n{\n  void *ret;\n  LPTHREAD_START_ROUTINE start_routine\n      = ((struct win32_start_info *)arg)->start_routine;\n  LPVOID start_arg = ((struct win32_start_info *)arg)->arg;\n\n  GC_ASSERT(!GC_win32_dll_threads);\n  /* This waits for an in-progress garbage collection. */\n  GC_register_my_thread(sb);\n#  ifdef DEBUG_THREADS\n  GC_log_printf(\"thread 0x%lx starting...\\n\", (long)GetCurrentThreadId());\n#  endif\n  GC_free(arg);\n\n  /*\n   * Clear the thread entry even if we exit with an exception.\n   * This is probably pointless, since an uncaught exception is\n   * supposed to result in the process being killed.\n   */\n#  ifndef NO_SEH_AVAILABLE\n  ret = NULL; /*< to avoid \"might be uninitialized\" compiler warning */\n  __try\n#  endif\n  {\n    ret = NUMERIC_TO_VPTR(start_routine(start_arg));\n  }\n#  ifndef NO_SEH_AVAILABLE\n  __finally\n#  endif\n  {\n    (void)GC_unregister_my_thread();\n  }\n\n#  ifdef DEBUG_THREADS\n  GC_log_printf(\"thread 0x%lx returned from start routine\\n\",\n                (long)GetCurrentThreadId());\n#  endif\n#  if defined(CPPCHECK)\n  GC_noop1_ptr(sb);\n#  endif\n  return ret;\n}\n\nSTATIC DWORD WINAPI\nGC_win32_start(LPVOID arg)\n{\n  return (DWORD)(GC_uintptr_t)GC_call_with_stack_base(GC_win32_start_inner,\n                                                      arg);\n}\n\nGC_API HANDLE WINAPI\nGC_CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,\n                GC_WIN32_SIZE_T dwStackSize,\n                LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter,\n                DWORD dwCreationFlags, LPDWORD lpThreadId)\n{\n  /*\n   * Make sure the collector is initialized (i.e. main thread is attached,\n   * TLS is initialized).  This is redundant when `GC_win32_dll_threads`\n   * is set by `GC_use_threads_discovery()`.\n   */\n  if (UNLIKELY(!GC_is_initialized))\n    GC_init();\n  GC_ASSERT(GC_thr_initialized);\n\n#  ifdef DEBUG_THREADS\n  GC_log_printf(\"About to create a thread from 0x%lx\\n\",\n                (long)GetCurrentThreadId());\n#  endif\n  if (GC_win32_dll_threads) {\n    return CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress,\n                        lpParameter, dwCreationFlags, lpThreadId);\n  } else {\n    /* Note: this is handed off to and deallocated by child thread. */\n    struct win32_start_info *psi\n        = (struct win32_start_info *)GC_malloc_uncollectable(\n            sizeof(struct win32_start_info));\n    HANDLE thread_h;\n\n    if (UNLIKELY(NULL == psi)) {\n      SetLastError(ERROR_NOT_ENOUGH_MEMORY);\n      return NULL;\n    }\n\n    /* Set up the thread arguments. */\n    psi->start_routine = lpStartAddress;\n    psi->arg = lpParameter;\n    GC_dirty(psi);\n    REACHABLE_AFTER_DIRTY(lpParameter);\n\n#  ifdef PARALLEL_MARK\n    if (!GC_parallel && UNLIKELY(GC_available_markers_m1 > 0))\n      GC_start_mark_threads();\n#  endif\n    set_need_to_lock();\n    thread_h = CreateThread(lpThreadAttributes, dwStackSize, GC_win32_start,\n                            psi, dwCreationFlags, lpThreadId);\n    if (UNLIKELY(0 == thread_h))\n      GC_free(psi);\n    return thread_h;\n  }\n}\n\nGC_API DECLSPEC_NORETURN void WINAPI\nGC_ExitThread(DWORD dwExitCode)\n{\n  if (!GC_win32_dll_threads)\n    (void)GC_unregister_my_thread();\n  ExitThread(dwExitCode);\n}\n\n#  if defined(MSWIN32) && !defined(NO_CRT)\nGC_API GC_uintptr_t GC_CALL\nGC_beginthreadex(void *security, unsigned stack_size,\n                 unsigned(__stdcall *start_address)(void *), void *arglist,\n                 unsigned initflag, unsigned *thrdaddr)\n{\n  if (UNLIKELY(!GC_is_initialized))\n    GC_init();\n  GC_ASSERT(GC_thr_initialized);\n#    ifdef DEBUG_THREADS\n  GC_log_printf(\"About to create a thread from 0x%lx\\n\",\n                (long)GetCurrentThreadId());\n#    endif\n\n  if (GC_win32_dll_threads) {\n    return _beginthreadex(security, stack_size, start_address, arglist,\n                          initflag, thrdaddr);\n  } else {\n    GC_uintptr_t thread_h;\n    /* Note: this is handed off to and deallocated by child thread. */\n    struct win32_start_info *psi\n        = (struct win32_start_info *)GC_malloc_uncollectable(\n            sizeof(struct win32_start_info));\n\n    if (UNLIKELY(NULL == psi)) {\n      /*\n       * MSDN docs say `_beginthreadex()` returns 0 on error and sets\n       * `errno` to either `EAGAIN` (too many threads) or `EINVAL` (the\n       * argument is invalid or the stack size is incorrect), so we set\n       * `errno` to `EAGAIN` on \"not enough memory\".\n       */\n      errno = EAGAIN;\n      return 0;\n    }\n\n    /* Set up the thread arguments. */\n    psi->start_routine = (LPTHREAD_START_ROUTINE)start_address;\n    psi->arg = arglist;\n    GC_dirty(psi);\n    REACHABLE_AFTER_DIRTY(arglist);\n\n#    ifdef PARALLEL_MARK\n    if (!GC_parallel && UNLIKELY(GC_available_markers_m1 > 0))\n      GC_start_mark_threads();\n#    endif\n    set_need_to_lock();\n    thread_h = _beginthreadex(security, stack_size,\n                              (unsigned(__stdcall *)(void *))GC_win32_start,\n                              psi, initflag, thrdaddr);\n    if (UNLIKELY(0 == thread_h))\n      GC_free(psi);\n    return thread_h;\n  }\n}\n\nGC_API void GC_CALL\nGC_endthreadex(unsigned retval)\n{\n  if (!GC_win32_dll_threads)\n    (void)GC_unregister_my_thread();\n  _endthreadex(retval);\n}\n#  endif /* MSWIN32 && !NO_CRT */\n\n#  ifdef GC_WINMAIN_REDIRECT\n/* This might be useful on WinCE.  Should not be used with `GC_DLL`. */\n\n#    if defined(MSWINCE) && defined(UNDER_CE)\n#      define WINMAIN_LPTSTR LPWSTR\n#    else\n#      define WINMAIN_LPTSTR LPSTR\n#    endif\n\n/* This is defined in `gc.h` file. */\n#    undef WinMain\n\n/* Defined outside the collector by an application. */\nint WINAPI GC_WinMain(HINSTANCE, HINSTANCE, WINMAIN_LPTSTR, int);\n\ntypedef struct {\n  HINSTANCE hInstance;\n  HINSTANCE hPrevInstance;\n  WINMAIN_LPTSTR lpCmdLine;\n  int nShowCmd;\n} main_thread_args;\n\nstatic DWORD WINAPI\nmain_thread_start(LPVOID arg)\n{\n  main_thread_args *main_args = (main_thread_args *)arg;\n  return (DWORD)GC_WinMain(main_args->hInstance, main_args->hPrevInstance,\n                           main_args->lpCmdLine, main_args->nShowCmd);\n}\n\nSTATIC void *GC_CALLBACK\nGC_waitForSingleObjectInfinite(void *handle)\n{\n  return NUMERIC_TO_VPTR(WaitForSingleObject((HANDLE)handle, INFINITE));\n}\n\n#    ifndef WINMAIN_THREAD_STACK_SIZE\n/* The default size of the `WinMain`'s thread stack. */\n#      define WINMAIN_THREAD_STACK_SIZE 0\n#    endif\n\nint WINAPI\nWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, WINMAIN_LPTSTR lpCmdLine,\n        int nShowCmd)\n{\n  DWORD exit_code = 1;\n\n  main_thread_args args = { hInstance, hPrevInstance, lpCmdLine, nShowCmd };\n  HANDLE thread_h;\n  DWORD thread_id;\n\n  /* Initialize everything. */\n  GC_INIT();\n\n  /* Start the main thread. */\n  thread_h = GC_CreateThread(\n      NULL /* `lpsa` */, WINMAIN_THREAD_STACK_SIZE /* ignored on WinCE */,\n      main_thread_start, &args, 0 /* `fdwCreate` */, &thread_id);\n  if (NULL == thread_h)\n    ABORT(\"GC_CreateThread(main_thread) failed\");\n\n  if ((DWORD)(GC_uintptr_t)GC_do_blocking(GC_waitForSingleObjectInfinite,\n                                          (void *)thread_h)\n      == WAIT_FAILED)\n    ABORT(\"WaitForSingleObject(main_thread) failed\");\n  GetExitCodeThread(thread_h, &exit_code);\n  CloseHandle(thread_h);\n\n#    if defined(MSWINCE) && !defined(GC_NO_DEINIT)\n  GC_deinit();\n#    endif\n  return (int)exit_code;\n}\n\n#  endif /* GC_WINMAIN_REDIRECT */\n\n#  ifdef WOW64_THREAD_CONTEXT_WORKAROUND\n#    ifdef MSWINRT_FLAVOR\n/* Available on WinRT but we have to declare it manually. */\n__declspec(dllimport) HMODULE WINAPI GetModuleHandleW(LPCWSTR);\n#    endif\n\nstatic GC_bool\nis_wow64_process(HMODULE hK32)\n{\n  BOOL is_wow64;\n#    ifdef MSWINRT_FLAVOR\n  /* Try to use `IsWow64Process2()` as it handles different WoW64 cases. */\n  HMODULE hWow64 = GetModuleHandleW(L\"api-ms-win-core-wow64-l1-1-1.dll\");\n\n  UNUSED_ARG(hK32);\n  if (hWow64) {\n    FARPROC pfn2 = GetProcAddress(hWow64, \"IsWow64Process2\");\n    USHORT process_machine, native_machine;\n\n    if (pfn2\n        && (*(BOOL(WINAPI *)(HANDLE, USHORT *, USHORT *))(GC_funcptr_uint)\n                pfn2)(GetCurrentProcess(), &process_machine, &native_machine))\n      return process_machine != native_machine;\n  }\n  if (IsWow64Process(GetCurrentProcess(), &is_wow64))\n    return (GC_bool)is_wow64;\n#    else\n  if (hK32) {\n    FARPROC pfn = GetProcAddress(hK32, \"IsWow64Process\");\n\n    if (pfn\n        && (*(BOOL(WINAPI *)(HANDLE, BOOL *))(GC_funcptr_uint)pfn)(\n            GetCurrentProcess(), &is_wow64))\n      return (GC_bool)is_wow64;\n  }\n#    endif\n  /* `IsWow64Process()` failed. */\n  return FALSE;\n}\n#  endif /* WOW64_THREAD_CONTEXT_WORKAROUND */\n\nGC_INNER void\nGC_thr_init(void)\n{\n  struct GC_stack_base sb;\n  thread_id_t self_id = GetCurrentThreadId();\n#  if (!defined(HAVE_PTHREAD_SETNAME_NP_WITH_TID) && !defined(MSWINCE) \\\n       && defined(PARALLEL_MARK))                                      \\\n      || defined(WOW64_THREAD_CONTEXT_WORKAROUND)\n  HMODULE hK32;\n#    if defined(MSWINRT_FLAVOR) && defined(FUNCPTR_IS_DATAPTR)\n  MEMORY_BASIC_INFORMATION memInfo;\n\n  if (VirtualQuery(CAST_THRU_UINTPTR(void *, GetProcAddress), &memInfo,\n                   sizeof(memInfo))\n      != sizeof(memInfo))\n    ABORT(\"Weird VirtualQuery result\");\n  hK32 = (HMODULE)memInfo.AllocationBase;\n#    else\n  hK32 = GetModuleHandle(TEXT(\"kernel32.dll\"));\n#    endif\n#  endif\n\n  GC_ASSERT(I_HOLD_LOCK());\n  GC_ASSERT(!GC_thr_initialized);\n  GC_ASSERT(ADDR(&GC_threads) % ALIGNMENT == 0);\n#  ifdef GC_ASSERTIONS\n  GC_thr_initialized = TRUE;\n#  endif\n#  if !defined(DONT_USE_ATEXIT) || !defined(GC_NO_THREADS_DISCOVERY)\n  GC_main_thread_id = self_id;\n#  endif\n#  ifdef CAN_HANDLE_FORK\n  GC_setup_atfork();\n#  endif\n#  ifdef WOW64_THREAD_CONTEXT_WORKAROUND\n  /* Set `isWow64` flag. */\n  isWow64 = is_wow64_process(hK32);\n#  endif\n  /* Add the initial thread, so we can stop it. */\n  sb.mem_base = GC_stackbottom;\n  GC_ASSERT(sb.mem_base != NULL);\n#  ifdef IA64\n  sb.reg_base = GC_register_stackbottom;\n#  endif\n\n#  if defined(PARALLEL_MARK)\n  {\n    const char *markers_string = GETENV(\"GC_MARKERS\");\n    int markers = GC_required_markers_cnt;\n\n    if (markers_string != NULL) {\n      markers = atoi(markers_string);\n      if (markers <= 0 || markers > MAX_MARKERS) {\n        WARN(\"Too big or invalid number of mark threads: %\" WARN_PRIdPTR\n             \"; using maximum threads\\n\",\n             (GC_signed_word)markers);\n        markers = MAX_MARKERS;\n      }\n    } else if (0 == markers) {\n      /*\n       * Unless the client sets the desired number of parallel markers,\n       * it is determined based on the number of CPU cores.\n       */\n#    ifdef MSWINCE\n      /*\n       * There is no `GetProcessAffinityMask()` in WinCE.\n       * `GC_sysinfo` is already initialized.\n       */\n      markers = (int)GC_sysinfo.dwNumberOfProcessors;\n#    else\n#      ifdef _WIN64\n      DWORD_PTR procMask = 0;\n      DWORD_PTR sysMask;\n#      else\n      DWORD procMask = 0;\n      DWORD sysMask;\n#      endif\n      int ncpu = 0;\n      if (\n#      ifdef __cplusplus\n          GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask)\n#      else\n          /*\n           * Cast the mask arguments to `void *` for compatibility with\n           * some old SDKs.\n           */\n          GetProcessAffinityMask(GetCurrentProcess(), (void *)&procMask,\n                                 (void *)&sysMask)\n#      endif\n          && procMask) {\n        do {\n          ncpu++;\n        } while ((procMask &= procMask - 1) != 0);\n      }\n      markers = ncpu;\n#    endif\n#    if defined(GC_MIN_MARKERS) && !defined(CPPCHECK)\n      /* This is primarily for testing on systems without `getenv()`. */\n      if (markers < GC_MIN_MARKERS)\n        markers = GC_MIN_MARKERS;\n#    endif\n      if (markers > MAX_MARKERS) {\n        /* Silently limit the amount of markers. */\n        markers = MAX_MARKERS;\n      }\n    }\n    GC_available_markers_m1 = markers - 1;\n  }\n\n  /* Check whether parallel mode could be enabled. */\n  if (GC_win32_dll_threads || GC_available_markers_m1 <= 0) {\n    /* Disable parallel marking. */\n    GC_parallel = FALSE;\n    GC_COND_LOG_PRINTF(\"Single marker thread, turning off parallel marking\\n\");\n  } else {\n#    ifndef GC_PTHREADS_PARAMARK\n    /* Initialize Win32 event objects for parallel marking. */\n    mark_mutex_event\n        = CreateEvent(NULL /* `attrs` */, FALSE /* `isManualReset` */,\n                      FALSE /* `initialState` */, NULL /* `name` */);\n    builder_cv = CreateEvent(NULL /* `attrs` */, TRUE /* `isManualReset` */,\n                             FALSE /* `initialState` */, NULL /* `name` */);\n    mark_cv = CreateEvent(NULL /* `attrs` */, TRUE /* `isManualReset` */,\n                          FALSE /* `initialState` */, NULL /* `name` */);\n    if (mark_mutex_event == (HANDLE)0 || builder_cv == (HANDLE)0\n        || mark_cv == (HANDLE)0)\n      ABORT(\"CreateEvent failed\");\n#    endif\n#    if !defined(HAVE_PTHREAD_SETNAME_NP_WITH_TID) && !defined(MSWINCE)\n    GC_init_win32_thread_naming(hK32);\n#    endif\n  }\n#  endif /* PARALLEL_MARK */\n\n  GC_register_my_thread_inner(&sb, self_id);\n}\n\n#  ifndef GC_NO_THREADS_DISCOVERY\n/*\n * We avoid acquiring locks here, since this does not seem to be preemptible.\n * This may run with an uninitialized collector, in which case we do not\n * do much.  This implies that no threads other than the main one should be\n * created with an uninitialized collector.  (The alternative of initializing\n * the collector here seems dangerous, since `DllMain` is limited in what it\n * can do.)\n */\n\n#    ifdef GC_INSIDE_DLL\n/* Export only if needed by client. */\nGC_API\n#    else\n#      define GC_DllMain DllMain\n#    endif\nBOOL WINAPI\nGC_DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved)\n{\n  thread_id_t self_id;\n\n  UNUSED_ARG(inst);\n  UNUSED_ARG(reserved);\n  /*\n   * Note that `GC_use_threads_discovery` should be called by the client\n   * application at start-up to activate automatic thread registration\n   * (it is the default collector behavior); to always have automatic\n   * thread registration turned on, the collector should be compiled with\n   * `-D GC_DISCOVER_TASK_THREADS` option.\n   */\n  if (!GC_win32_dll_threads && GC_is_initialized)\n    return TRUE;\n\n  switch (reason) {\n  case DLL_THREAD_ATTACH:\n    /* This is invoked for threads other than main one. */\n#    ifdef PARALLEL_MARK\n    /* Do not register marker threads. */\n    if (GC_parallel) {\n      /*\n       * We could reach here only if the collector is not initialized.\n       * Because `GC_thr_init()` sets `GC_parallel` to `FALSE`.\n       */\n      break;\n    }\n#    endif\n    /* FALLTHRU */\n  case DLL_PROCESS_ATTACH:\n    /* This may run with the collector uninitialized. */\n    self_id = GetCurrentThreadId();\n    if (GC_is_initialized && GC_main_thread_id != self_id) {\n      struct GC_stack_base sb;\n      /* Do not lock here. */\n#    ifdef GC_ASSERTIONS\n      int sb_result =\n#    endif\n          GC_get_stack_base(&sb);\n      GC_ASSERT(sb_result == GC_SUCCESS);\n      GC_register_my_thread_inner(&sb, self_id);\n    } else {\n      /* We already did it during `GC_thr_init()`, called by `GC_init()`. */\n    }\n    break;\n\n  case DLL_THREAD_DETACH:\n    /* We are hopefully running in the context of the exiting thread. */\n    if (GC_win32_dll_threads) {\n      GC_thread t = GC_win32_dll_lookup_thread(GetCurrentThreadId());\n\n      if (LIKELY(t != NULL))\n        GC_delete_thread(t);\n    }\n    break;\n\n  case DLL_PROCESS_DETACH:\n    if (GC_win32_dll_threads) {\n      int i;\n      int my_max = (int)GC_get_max_thread_index();\n\n      for (i = 0; i <= my_max; ++i) {\n        if (AO_load(&dll_thread_table[i].tm.in_use))\n          GC_delete_thread((GC_thread)&dll_thread_table[i]);\n      }\n#    ifndef GC_NO_DEINIT\n      GC_deinit();\n#    endif\n    }\n    break;\n  }\n  return TRUE;\n}\n#  endif /* !GC_NO_THREADS_DISCOVERY */\n\n#  ifndef GC_NO_THREAD_REDIRECTS\n/* Restore thread calls redirection. */\n#    define CreateThread GC_CreateThread\n#    define ExitThread GC_ExitThread\n#    undef _beginthreadex\n#    define _beginthreadex GC_beginthreadex\n#    undef _endthreadex\n#    define _endthreadex GC_endthreadex\n#  endif /* !GC_NO_THREAD_REDIRECTS */\n\n#endif /* GC_WIN32_THREADS */\n\n\n#ifndef GC_PTHREAD_START_STANDALONE\n/*\n * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.\n * Copyright (c) 2000-2010 by Hewlett-Packard Development Company.\n * All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * We want to make sure that `GC_thread_exit_proc()` is unconditionally\n * invoked, even if the client is not compiled with `-fexceptions` option,\n * but the collector is.  The workaround is to put `GC_pthread_start_inner()`\n * in its own file (this one), and undefine `__EXCEPTIONS` in the gcc case\n * at the top of the file.\n * FIXME: It is still unclear whether this will actually cause the\n * `exit` handler to be invoked last when `thread_exit` is called (and\n * if `-fexceptions` option is used).\n */\n\n#if !defined(DONT_UNDEF_EXCEPTIONS) && defined(__GNUC__) && defined(__linux__)\n/*\n * We undefine `__EXCEPTIONS` to avoid using gcc `__cleanup__` attribute.\n * The current NPTL implementation of `pthread_cleanup_push` uses\n * `__cleanup__` attribute when `__EXCEPTIONS` is defined (`-fexceptions`\n * option is given).  The stack unwinding and cleanup with `__cleanup__`\n * attribute work correctly when everything is compiled with `-fexceptions`\n * option, but it is not the requirement for this library clients to use\n * `-fexceptions` option everywhere.  With `__EXCEPTIONS` undefined, the\n * cleanup routines are registered with `__pthread_register_cancel` thus\n * should work anyway.\n */\n#  undef __EXCEPTIONS\n#endif\n\n\n#if defined(GC_PTHREADS) && !defined(PLATFORM_THREADS) \\\n    && !defined(SN_TARGET_PSP2)\n\n/* Invoked from `GC_pthread_start()`. */\nGC_INNER_PTHRSTART void *GC_CALLBACK\nGC_pthread_start_inner(struct GC_stack_base *sb, void *arg)\n{\n  void *(*start)(void *);\n  void *start_arg;\n  void *result;\n  volatile GC_thread me\n      = GC_start_rtn_prepare_thread(&start, &start_arg, sb, arg);\n\n#  ifndef NACL\n  pthread_cleanup_push(GC_thread_exit_proc, (/* no volatile */ void *)me);\n#  endif\n  result = (*start)(start_arg);\n#  if defined(DEBUG_THREADS) && !defined(GC_PTHREAD_START_STANDALONE)\n  GC_log_printf(\"Finishing thread %p\\n\", PTHREAD_TO_VPTR(pthread_self()));\n#  endif\n  me->status = result;\n  /* Note: we cannot use `GC_dirty()` instead. */\n  GC_end_stubborn_change(me);\n\n  /*\n   * Cleanup acquires the allocator lock, ensuring that we cannot exit\n   * while a collection that thinks we are alive is trying to stop us.\n   */\n#  ifdef NACL\n  GC_thread_exit_proc((/* no volatile */ void *)me);\n#  else\n  pthread_cleanup_pop(1);\n#  endif\n  return result;\n}\n\n#endif /* GC_PTHREADS */\n\n#endif\n\n/*\n * Restore `pthreads` calls redirection (if altered in `pthread_stop_world.c`\n * or `pthread_support.c` file).  This is only useful if directly included\n * from client code (instead of linking with `gc.o` file).\n */\n#if !defined(GC_NO_THREAD_REDIRECTS) && defined(GC_PTHREADS)\n#  define GC_PTHREAD_REDIRECTS_ONLY\n#  include \"gc/gc_pthread_redirects.h\"\n#endif\n\n/* Note: the files from `extra` folder are not included. */\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/cord.h",
    "content": "/*\n * Copyright (c) 1993-1994 by Xerox Corporation.  All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * Cords are immutable character strings.  A number of operations on long\n * cords are much more efficient than their counterpart in platform\n * `strings.h` file.  In particular, concatenation takes constant time\n * independent of the length of the arguments.  (Cords are represented as\n * trees, with internal nodes representing concatenation and leaves\n * consisting of either C strings or a functional description of the string.)\n *\n * The following are reasonable applications of cords.  They would perform\n * unacceptably if C strings were used:\n *   - A compiler that produces assembly language output by repeatedly\n *     concatenating instructions onto a cord representing the output file;\n *   - A text editor that converts the input file to a cord, and then\n *     performs editing operations by producing a new cord representing the\n *     file after each character change (and keeping the old ones in an edit\n *     history).\n *\n * For optimal performance, cords should be built by concatenating short\n * sections.  This interface is designed for maximum compatibility with\n * C strings.  ASCII NUL characters may be embedded in cords using\n * `CORD_from_fn`.  This is handled correctly, but `CORD_to_char_star` will\n * produce a string with embedded NUL characters when given such a cord.\n *\n * This interface is fairly big, largely for performance reasons.\n * The most basic constants, functions and types:\n *\n *   - `CORD` - the type of a cord;\n *   - `CORD_EMPTY` - empty cord;\n *   - `CORD_len(cord)` - length of a cord;\n *   - `CORD_cat(cord1, cord2)` - concatenation of two cords;\n *   - `CORD_substr(cord, start, len)` - substring (or subcord);\n *   - `CORD_pos i; CORD_FOR(i, cord) { ... CORD_pos_fetch(i) ... }` - examine\n *     each character in a cord (`CORD_pos_fetch(i)` is the `char`);\n *   - `CORD_fetch(i)` - retrieve `i`'th character (slowly);\n *   - `CORD_cmp(cord1, cord2)` - compare two cords;\n *   - `CORD_from_file(FILE *f)` - turn a read-only file into a cord;\n *   - `CORD_to_char_star(cord)` - convert to C string (non-`NULL` C constant\n *     strings are cords);\n *   - `CORD_printf(CORD format, ...)` and friends - cord's variant of\n *     `printf` (use \"%r\" for cords).\n */\n\n#ifndef CORD_H\n#define CORD_H\n\n#include <stddef.h>\n#include <stdio.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if defined(GC_DLL) && !defined(CORD_NOT_DLL) && !defined(CORD_API)\n/* Same as for `GC_API` in `gc_config_macros.h` file. */\n#  ifdef CORD_BUILD\n#    if defined(__MINGW32__) && !defined(__cplusplus) || defined(__CEGCC__)\n#      define CORD_API __declspec(dllexport)\n#    elif defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \\\n        || defined(__CYGWIN__) || defined(__MINGW32__)                   \\\n        || defined(__WATCOMC__)\n#      define CORD_API extern __declspec(dllexport)\n#    elif defined(__GNUC__) && !defined(GC_NO_VISIBILITY) \\\n        && (__GNUC__ >= 4 || defined(GC_VISIBILITY_HIDDEN_SET))\n/* Only matters if used in conjunction with `-fvisibility=hidden` option. */\n#      define CORD_API extern __attribute__((__visibility__(\"default\")))\n#    endif\n#  else /* !CORD_BUILD */\n#    if defined(__BORLANDC__) || defined(__CEGCC__) || defined(__CYGWIN__) \\\n        || defined(__DMC__) || defined(_MSC_VER)\n#      define CORD_API __declspec(dllimport)\n#    elif defined(__MINGW32__) || defined(__WATCOMC__)\n#      define CORD_API extern __declspec(dllimport)\n#    endif\n#  endif\n#endif /* GC_DLL */\n\n#ifndef CORD_API\n#  define CORD_API extern\n#endif\n\n/**\n * Cords have type `const char *`.  This is cheating quite a bit, and not\n * 100% portable.  But it means that nonempty character string constants\n * may be used as cords directly, provided the string is never modified in\n * place.  The empty cord is represented by, and can be written as, `NULL`.\n */\ntypedef const char *CORD;\n\n/** An empty cord is always represented as nil. */\n#define CORD_EMPTY 0\n\n/** Is a nonempty cord represented as a C string? */\n#define CORD_IS_STRING(s) (*(s) != '\\0')\n\n/**\n * Concatenate two cords.  If the arguments are C strings, they may not\n * be subsequently altered.\n */\nCORD_API CORD CORD_cat(CORD, CORD);\n\n/**\n * Concatenate a cord and a C string with known length.  Except for the\n * empty string case, this is a special case of `CORD_cat`.  Since the\n * length is known, it can be faster.  The string `y` is shared with\n * the resulting cord.  Hence it should not be altered by the caller.\n */\nCORD_API CORD CORD_cat_char_star(CORD /* `x` */, const char * /* `y` */,\n                                 size_t /* `y_len` */);\n\n/** Compute the length of a cord. */\nCORD_API size_t CORD_len(CORD);\n\n/** Cords may be represented by functions defining the `i`-th character. */\ntypedef char (*CORD_fn)(size_t /* `i` */, void * /* `client_data` */);\n\n/** Turn a functional description into a cord. */\nCORD_API CORD CORD_from_fn(CORD_fn, void * /* `client_data` */,\n                           size_t /* `len` */);\n\n/**\n * Return the substring (subcord really) of `x` with length at most `n`,\n * starting at position `i`.  (The initial character has position zero.)\n */\nCORD_API CORD CORD_substr(CORD, size_t /* `i` */, size_t /* `n` */);\n\n/**\n * Return the argument, but rebalanced to allow more efficient\n * character retrieval, substring operations, and comparisons.\n * This is useful only for cords that were built using repeated\n * concatenation.  Guarantees log time access to the result, unless\n * the argument was obtained through a large number of repeated\n * substring operations or the embedded functional descriptions take\n * longer to evaluate.  May reallocate significant parts of the cord.\n * The argument is not modified; only the result is balanced.\n */\nCORD_API CORD CORD_balance(CORD);\n\n/*\n * The following traverse a cord by applying a function to each\n * character.  This is occasionally appropriate, especially where\n * speed is crucial.  But, since C does not have nested functions,\n * clients of this sort of traversal are clumsy to write.  Consider\n * the functions that operate on cord positions instead.\n */\n\n/** Function to iteratively apply to individual characters in cord. */\ntypedef int (*CORD_iter_fn)(char, void * /* `client_data` */);\n\n/**\n * Function to apply to substrings of a cord.  Each substring is\n * a C character string, not a general cord.\n */\ntypedef int (*CORD_batched_iter_fn)(const char *, void * /* `client_data` */);\n\n#define CORD_NO_FN ((CORD_batched_iter_fn)0)\n\n/**\n * Apply `f1` to each character in the cord, in ascending order, starting at\n * position `i`.  If `f2` is not `CORD_NO_FN`, then multiple calls to `f1`\n * may be replaced by a single call to `f2`.  The latter is provided only\n * to allow some optimization by the client.  This terminates when the right\n * end of this string is reached, or when `f1` or `f2` return a nonzero value.\n * In the latter case this function returns a nonzero value; otherwise\n * it returns 0.  The specified value of `i` must be less than `CORD_len(x)`.\n */\nCORD_API int CORD_iter5(CORD, size_t /* `i` */, CORD_iter_fn /* `f1` */,\n                        CORD_batched_iter_fn /* `f2` */,\n                        void * /* `client_data` */);\n\n/** A simpler variant of `CORD_iter5` that starts at 0, and without `f2`. */\nCORD_API int CORD_iter(CORD, CORD_iter_fn /* `f1` */,\n                       void * /* `client_data` */);\n#define CORD_iter(x, f1, cd) CORD_iter5(x, 0, f1, CORD_NO_FN, cd)\n\n/**\n * Similar to `CORD_iter5`, but end-to-beginning.  No provisions for\n * `CORD_batched_iter_fn`.\n */\nCORD_API int CORD_riter4(CORD, size_t /* `i` */, CORD_iter_fn /* `f1` */,\n                         void * /* `client_data` */);\n\n/** A simpler variant of `CORD_riter4` that starts at the end. */\nCORD_API int CORD_riter(CORD, CORD_iter_fn /* `f1` */,\n                        void * /* `client_data` */);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n/*\n * Functions that operate on cord positions.  The easy way to traverse cords.\n * A cord position is logically a pair consisting of a cord and an index\n * into that cord.  But it is much faster to retrieve a character based on\n * a position than on an index.  Unfortunately, positions are big (order of\n * a few 100 bytes), so allocate them with caution.  Things in `cord_pos.h`\n * file should be treated as opaque, except as described below.  Also, note\n * that `CORD_pos_fetch`, `CORD_next` and `CORD_prev` have both macro and\n * function definitions.  The former may evaluate their argument more than\n * once.\n */\n#include \"cord_pos.h\"\n\n/*\n * Visible definitions from above:\n *   - `typedef <OPAQUE_but_fairly_big> CORD_pos[1]`;\n *   - `CORD CORD_pos_to_cord(CORD_pos p)` - extract the cord from\n *     a position;\n *   - `size_t CORD_pos_to_index(CORD_pos p)` - extract the current index\n *     from a position;\n *   - `char CORD_pos_fetch(CORD_pos p)` - fetch the character located at\n *     the given position;\n *   - `void CORD_set_pos(CORD_pos p, CORD x, size_t i)` - initialize the\n *     position to refer to the given cord and index;\n *   - `void CORD_next(CORD_pos p)` - advance the position to the next\n *     character;\n *   - `void CORD_prev(CORD_pos p)` - move the position to the preceding\n *     character;\n *   - `int CORD_pos_valid(CORD_pos p)` - check whether the position is\n *     valid, i.e. inside the cord.\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define CORD_FOR(pos, cord) \\\n  for (CORD_set_pos(pos, cord, 0); CORD_pos_valid(pos); CORD_next(pos))\n\n/**\n * An out-of-memory handler to call.  Zero value means do nothing special,\n * just abort.  Use of the setter and getter is preferred over the direct\n * access to the global variable.\n */\ntypedef void (*CORD_oom_fn_t)(void);\nCORD_API void CORD_set_oom_fn(CORD_oom_fn_t);\nCORD_API CORD_oom_fn_t CORD_get_oom_fn(void);\n#ifndef CORD_DONT_DECLARE_OOM_FN\nCORD_API CORD_oom_fn_t CORD_oom_fn;\n#endif\n#ifdef CORD_BUILD\n/* no export */ void CORD__call_oom_fn(void);\n#endif\n\n/**\n * Dump the representation of `x` to `stdout` in an implementation\n * defined manner.  Intended for debugging only.\n */\nCORD_API void CORD_dump(CORD /* `x` */);\n\n/*\n * The following could easily be implemented by the client.  They are\n * provided by the cord library for convenience.\n */\n\n/** Concatenate a character to the end of a cord. */\nCORD_API CORD CORD_cat_char(CORD, char);\n\n/** Concatenate `n` cords. */\nCORD_API CORD CORD_catn(int /* `n` */, /* `CORD` */...);\n\n/** Return the character in `CORD_substr(x, i, 1)`. */\nCORD_API char CORD_fetch(CORD /* `x` */, size_t /* `i` */);\n\n/**\n * Return a negative value, zero, or a positive value, depending on\n * whether `x < y`, `x == y`, or `x > y`, respectively.\n */\nCORD_API int CORD_cmp(CORD /* `x` */, CORD /* `y` */);\n\n/**\n * A generalization that takes both starting positions for the comparison,\n * and a limit on the number of characters to be compared.\n */\nCORD_API int CORD_ncmp(CORD /* `x` */, size_t /* `x_start` */, CORD /* `y` */,\n                       size_t /* `y_start` */, size_t /* `len` */);\n\n/**\n * Find the first occurrence of `s` in `x` at position `start` or later.\n * Return the position of the first character of `s` in `x`, or\n * `CORD_NOT_FOUND` if there is none.\n */\nCORD_API size_t CORD_str(CORD /* `x` */, size_t /* `start` */, CORD /* `s` */);\n\n/**\n * Return a cord consisting of `i` copies of `c`.  Dangerous in\n * conjunction with `CORD_to_char_star`.  `c` could be a NUL character.\n * The resulting representation takes constant space, independent of `i`.\n */\nCORD_API CORD CORD_chars(char /* `c` */, size_t /* `i` */);\n\n#define CORD_nul(i) CORD_chars('\\0', i)\n\n/**\n * Turn a file `f` into cord.  The file must be seekable.  Its contents\n * must remain constant.  The file may be accessed as an immediate\n * result of this call and/or as a result of subsequent accesses to\n * the cord.  Short files are likely to be immediately read, but\n * long files are likely to be read on demand, possibly relying on\n * `stdio` for buffering.  We must have exclusive access to the\n * descriptor `f`, i.e. we may read it at any time, and expect the file\n * pointer to be where we left it.  Normally this should be invoked as\n * `CORD_from_file(fopen(...))`.  The latter (`CORD_from_file`)\n * arranges to close the file descriptor when it is no longer needed\n * (e.g. when the result becomes inaccessible).  The file `f` must be\n * such that `ftell` reflects the actual character position in the\n * file, i.e. the number of characters that can be or were read with\n * `fread`.  On UNIX systems this is always true.  On Windows systems,\n * `f` must be opened in binary mode.\n */\nCORD_API CORD CORD_from_file(FILE * /* `f` */);\n\n/**\n * Equivalent to `CORD_from_file`, except that the entire file will be\n * read and the file pointer will be closed immediately.  The binary mode\n * restriction of `CORD_from_file` does not apply.\n */\nCORD_API CORD CORD_from_file_eager(FILE *);\n\n/**\n * Equivalent to `CORD_from_file`, except that the file will be read on\n * demand.  The binary mode restriction applies.\n */\nCORD_API CORD CORD_from_file_lazy(FILE *);\n\n/**\n * Turn a cord into a C string.  The result shares no structure with `x`,\n * and is thus modifiable.\n */\nCORD_API char *CORD_to_char_star(CORD /* `x` */);\n\n/**\n * Turn a C string into a `CORD`.  The C string is copied, and so may\n * subsequently be modified.\n */\nCORD_API CORD CORD_from_char_star(const char *);\n\n/**\n * Identical to `CORD_from_char_star`, but the result may share structure\n * with the argument and is thus not modifiable.\n */\nCORD_API const char *CORD_to_const_char_star(CORD);\n\n/**\n * Write a cord to a file, starting at the current position.\n * No trailing NUL characters and newlines are added.  Returns `EOF`\n * if a write error occurs, 1 otherwise.\n */\nCORD_API int CORD_put(CORD, FILE *);\n\n/** \"Not found\" result for `CORD_chr()` and `CORD_rchr()`. */\n#define CORD_NOT_FOUND ((size_t)(-1))\n\n/**\n * A vague analog of `strchr`.  Returns the position (an integer, not\n * a pointer) of the first occurrence of `char` `c` inside `x` at\n * position `i` or later.  The value `i` must be less than `CORD_len(x)`.\n */\nCORD_API size_t CORD_chr(CORD /* `x` */, size_t /* `i` */, int /* `c` */);\n\n/**\n * A vague analog of `strrchr`.  Returns index of the last occurrence\n * of `char` `c` inside `x` at position `i` or earlier.  The value `i` must\n * be less than `CORD_len(x)`.\n */\nCORD_API size_t CORD_rchr(CORD /* `x` */, size_t /* `i` */, int /* `c` */);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#ifndef CORD_NO_IO\n\n#  include <stdarg.h>\n\n#  ifdef __cplusplus\nextern \"C\" {\n#  endif\n\n/**\n * The following ones provide functionality similar to the ANSI C functions\n * with corresponding names, but with the following additions and changes:\n *   1. A \"%r\" conversion specification specifies a `CORD` argument.\n *      Field width, precision, etc. have the same semantics as for \"%s\".\n *      (Note that \"%c\", \"%C\", and \"%S\" were already taken.)\n *   2. The format string is represented as a `CORD`.\n *   3. `CORD_sprintf` and `CORD_vsprintf` assign the result through\n *      the 1st argument.  Unlike their ANSI C variants, there is no need\n *      to guess the correct buffer size.\n *   4. Most of the conversions are implemented through the native\n *      `vsprintf`.  Hence they are usually no faster, and idiosyncrasies\n *      of the native `printf` are preserved.  However, `CORD` arguments\n *      to `CORD_sprintf`, `CORD_vsprintf` are *not* copied; the result\n *      shares the original structure.  This may make them very efficient\n *      in some unusual applications.  The format string is copied.\n *\n * The functions return the number of characters generated or -1 on error.\n * This complies with the ANSI standard, but is inconsistent with some\n * older implementations of `sprintf`.\n */\nCORD_API int CORD_sprintf(CORD * /* `out` */, CORD /* `format` */, ...);\nCORD_API int CORD_vsprintf(CORD * /* `out` */, CORD /* `format` */, va_list);\nCORD_API int CORD_fprintf(FILE *, CORD /* `format` */, ...);\nCORD_API int CORD_vfprintf(FILE *, CORD /* `format` */, va_list);\nCORD_API int CORD_printf(CORD /* `format` */, ...);\nCORD_API int CORD_vprintf(CORD /* `format` */, va_list);\n\n#  ifdef __cplusplus\n} /* extern \"C\" */\n#  endif\n\n#endif /* CORD_NO_IO */\n\n#endif /* CORD_H */\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/cord_pos.h",
    "content": "/*\n * Copyright (c) 1993-1994 by Xerox Corporation.  All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/* This should never be included directly; included only from `cord.h` file. */\n#if !defined(CORD_POSITION_H) && defined(CORD_H)\n#  define CORD_POSITION_H\n\n#  ifdef __cplusplus\nextern \"C\" {\n#  endif\n\n/*\n * The representation of `CORD_position`.  This is private to the\n * implementation, but the size is known to clients.  Also the implementation\n * of some exported macros relies on it.  Do not use anything defined here\n * and not in `cord.h` file.\n */\n\n/**\n * The maximum depth of a balanced cord plus one.  We do not let cords get\n * deeper than this maximum.\n */\n#  define CORD_MAX_DEPTH 48\n\nstruct CORD_pe {\n  CORD pe_cord;\n  size_t pe_start_pos;\n};\n\n/**\n * A structure describing an entry on the path from the root to current\n * position.\n */\ntypedef struct CORD_Pos {\n  size_t cur_pos;\n\n  int path_len;\n\n  /* `path_len` is `CORD_POS_INVALID` if and only if position is invalid. */\n#  define CORD_POS_INVALID 0x55555555\n\n  /*\n   * Current leaf, if it is a string.  If the current leaf is a function,\n   * then this may point to `function_buf` containing the next few characters.\n   * Always points to a valid string containing the current character\n   * unless `cur_end` is zero.\n   */\n  const char *cur_leaf;\n\n  /* Start position of `cur_leaf`. */\n  size_t cur_start;\n\n  /* Ending position of `cur_leaf`; zero if `cur_leaf` is invalid. */\n  size_t cur_end;\n\n  /*\n   * `path[path_len]` is the leaf corresponding to `cur_pos`;\n   * `path[0].pe_cord` is the cord we point to.\n   */\n  struct CORD_pe path[CORD_MAX_DEPTH + 1];\n\n#  define CORD_FUNCTION_BUF_SZ 8\n\n  /* Space for next few chars from function node. */\n  char function_buf[CORD_FUNCTION_BUF_SZ];\n} CORD_pos[1];\n\n/** Extract the cord from a position. */\nCORD_API CORD CORD_pos_to_cord(CORD_pos);\n\n/** Extract the current index from a position. */\nCORD_API size_t CORD_pos_to_index(CORD_pos);\n\n/** Fetch the character located at the given position. */\nCORD_API char CORD_pos_fetch(CORD_pos);\n\n/**\n * Initialize the position to refer to the given cord and `index`.\n * Note that this is the most expensive function on positions.\n */\nCORD_API void CORD_set_pos(CORD_pos, CORD, size_t /* `index` */);\n\n/**\n * Advance the position to the next character.  `p` must be initialized\n * and valid.  Invalidates `p` if past end.\n */\nCORD_API void CORD_next(CORD_pos /* `p` */);\n\n/**\n * Move the position to the preceding character.  `p` must be initialized\n * and valid.  Invalidates `p` if past beginning.\n */\nCORD_API void CORD_prev(CORD_pos /* `p` */);\n\n/** Is the position valid, i.e. inside the cord? */\nCORD_API int CORD_pos_valid(CORD_pos);\n\nCORD_API char CORD__pos_fetch(CORD_pos);\nCORD_API void CORD__next(CORD_pos);\nCORD_API void CORD__prev(CORD_pos);\n\n#  define CORD_pos_fetch(p)                                                   \\\n    ((p)[0].cur_end != 0 ? (p)[0].cur_leaf[(p)[0].cur_pos - (p)[0].cur_start] \\\n                         : CORD__pos_fetch(p))\n\n#  define CORD_next(p)                                      \\\n    ((p)[0].cur_pos + 1 < (p)[0].cur_end ? (p)[0].cur_pos++ \\\n                                         : (CORD__next(p), 0U))\n\n#  define CORD_prev(p)                                        \\\n    ((p)[0].cur_end != 0 && (p)[0].cur_pos > (p)[0].cur_start \\\n         ? (p)[0].cur_pos--                                   \\\n         : (CORD__prev(p), 0U))\n\n#  define CORD_pos_to_index(p) ((p)[0].cur_pos)\n\n#  define CORD_pos_to_cord(p) ((p)[0].path[0].pe_cord)\n\n#  define CORD_pos_valid(p) ((p)[0].path_len != CORD_POS_INVALID)\n\n/* Some grubby stuff for performance-critical friends. */\n\n/** Number of characters in cache.  A non-positive value means none. */\n#  define CORD_pos_chars_left(p) ((long)(p)[0].cur_end - (long)(p)[0].cur_pos)\n\n/**\n * Advance position by `n` characters; `n` should be positive and less\n * than `CORD_pos_chars_left(p)`.\n */\n#  define CORD_pos_advance(p, n) \\\n    ((p)[0].cur_pos += (n) - (size_t)1, CORD_next(p))\n\n/** Address of the current character in cache. */\n#  define CORD_pos_cur_char_addr(p) \\\n    ((p)[0].cur_leaf + ((p)[0].cur_pos - (p)[0].cur_start))\n\n#  ifdef __cplusplus\n} /* extern \"C\" */\n#  endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/ec.h",
    "content": "/*\n * Copyright (c) 1993-1994 by Xerox Corporation.  All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n#ifndef EC_H\n#define EC_H\n\n#ifndef CORD_H\n#  include \"cord.h\"\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * Extensible cords are strings that may be destructively appended to.\n * They allow fast construction of cords from characters that are being\n * read from a stream.\n *\n * A client might look like:\n * ```\n *   CORD_ec x;\n *   CORD result;\n *   char c;\n *   FILE *f;\n *\n *   CORD_ec_init(x);\n *   while (...) {\n *       c = getc(f);\n *       ...\n *       CORD_ec_append(x, c);\n *   }\n *   result = CORD_balance(CORD_ec_to_cord(x));\n * ```\n *\n * If a C string is desired as the final result, the call to `CORD_balance`\n * may be replaced by a call to `CORD_to_char_star`.\n */\n\n#ifndef CORD_BUFSZ\n#  define CORD_BUFSZ 128\n#endif\n\n/**\n * This structure represents the concatenation of `ec_cord` with\n * `ec_buf[0 .. ec_bufptr - ec_buf - 1]`.\n */\ntypedef struct CORD_ec_struct {\n  CORD ec_cord;\n  char *ec_bufptr;\n  char ec_buf[CORD_BUFSZ + 1];\n} CORD_ec[1];\n\n/** Flush the buffer part of the extended cord into extensible cord. */\nCORD_API void CORD_ec_flush_buf(CORD_ec);\n\n/** Convert an extensible cord to a cord. */\n#define CORD_ec_to_cord(x) (CORD_ec_flush_buf(x), (x)[0].ec_cord)\n\n/** Initialize an extensible cord. */\n#define CORD_ec_init(x) \\\n  ((x)[0].ec_cord = 0, (void)((x)[0].ec_bufptr = (x)[0].ec_buf))\n\n/** Append a character to an extensible cord. */\n#define CORD_ec_append(x, c)                             \\\n  ((void)((x)[0].ec_bufptr == (x)[0].ec_buf + CORD_BUFSZ \\\n              ? (CORD_ec_flush_buf(x), 0)                \\\n              : 0),                                      \\\n   (void)(*(x)[0].ec_bufptr++ = (c)))\n\n/**\n * Append a cord to an extensible cord.  Structure remains shared with\n * the original.\n */\nCORD_API void CORD_ec_append_cord(CORD_ec, CORD);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#endif /* EC_H */\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/gc.h",
    "content": "/*\n * Copyright (c) 1988-1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1999 by Hewlett-Packard Company.  All rights reserved.\n * Copyright (c) 2007 Free Software Foundation, Inc.\n * Copyright (c) 2000-2011 by Hewlett-Packard Development Company.\n * Copyright (c) 2009-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * Note that this defines a large number of tuning hooks, which can\n * safely be ignored in nearly all cases.  For normal use it suffices\n * to call only `GC_MALLOC` and, perhaps, `GC_REALLOC`.\n * For better performance, also look at `GC_MALLOC_ATOMIC`, and\n * `GC_enable_incremental`.  If you need an action to be performed\n * immediately before an object is collected, look at `GC_register_finalizer`.\n * Everything else is best ignored unless you encounter performance\n * problems.\n */\n\n#ifndef GC_H\n#define GC_H\n\n/* Help debug mixed up preprocessor symbols. */\n#if defined(WIN64) && !defined(_WIN64) && defined(_MSC_VER)\n#  pragma message(\"Warning: Expecting _WIN64 for x64 targets!\")\n#endif\n\n/*\n * Define version numbers here to allow test on build machine for\n * cross-builds.  Note that this defines the header version number,\n * which may or may not match that of the dynamic library.\n * `GC_get_version()` can be used to obtain the latter.\n */\n#include \"gc_version.h\"\n\n#include \"gc_config_macros.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef void *GC_PTR; /*< preserved only for backward compatibility */\n\n/**\n * Define public `word` and `signed_word` to be unsigned and signed types\n * of the size same as of `size_t`, `ptrdiff_t`, and of the address part\n * of data pointers (like `char *` and `void *`).\n */\ntypedef GC_UNSIGNEDWORD GC_word;\ntypedef GC_SIGNEDWORD GC_signed_word;\n#undef GC_SIGNEDWORD\n#undef GC_UNSIGNEDWORD\n\n#if (defined(_UINTPTR_T) || defined(_UINTPTR_T_DECLARED) \\\n     || defined(_UINTPTR_T_DEFINED))                     \\\n    && !defined(__CYGWIN__) && !defined(__MSYS__)\n/* Note: Cygwin and MSYS2 might provide `__uintptr_t` but not `uintptr_t`. */\ntypedef uintptr_t GC_uintptr_t;\n#else\ntypedef GC_word GC_uintptr_t;\n#endif\n\n/**\n * Is first pointer has a smaller address than the second one?\n * The arguments should be of the same pointer type, e.g. of `char *` type.\n * Ancient compilers might treat a pointer as a signed value, thus we\n * need a cast to unsigned `word` of each compared pointer.\n */\n#if defined(__GNUC__) && !defined(__CHERI_PURE_CAPABILITY__)\n#  define GC_ADDR_LT(p, q) ((p) < (q))\n#else\n#  define GC_ADDR_LT(p, q) \\\n    ((GC_word)(GC_uintptr_t)(p) < (GC_word)(GC_uintptr_t)(q))\n#endif\n\n/**\n * Get the collector library version.  The returned value is a constant\n * in the form:\n * `((version_major << 16) | (version_minor << 8) | version_micro)`.\n */\nGC_API GC_VERSION_VAL_T GC_CALL GC_get_version(void);\n\n/*\n * Public read-only variables.  The supplied getter functions are\n * preferred for new client code.\n */\n\n/**\n * Counter incremented once per collection.  Includes empty collections\n * at startup.  `GC_get_gc_no()` is unsynchronized, so it requires\n * `GC_call_with_reader_lock()` to avoid data race on multiprocessors.\n */\nGC_API GC_ATTR_DEPRECATED GC_word GC_gc_no;\nGC_API GC_word GC_CALL GC_get_gc_no(void);\n\n#ifdef GC_THREADS\n/**\n * GC is parallelized for performance on multiprocessors.\n * Set to a nonzero value when client calls `GC_start_mark_threads()`\n * directly or starts the first non-main thread, provided the\n * collector is built with `PARALLEL_MARK` macro defined, and either\n * `GC_MARKERS` (or `GC_NPROCS`) environment variable is set to a value\n * bigger than 1, or multiple cores (processors) are available, or\n * the client calls `GC_set_markers_count()` before the collector\n * initialization.  After setting, `GC_parallel` value is equal to the\n * number of marker threads minus one (i.e. the number of existing\n * parallel marker threads excluding the initiating one).\n */\nGC_API GC_ATTR_DEPRECATED int GC_parallel;\n#endif\n\n/** Return value of `GC_parallel`.  Does not acquire the allocator lock. */\nGC_API int GC_CALL GC_get_parallel(void);\n\n/**\n * Set the number of marker threads (including the initiating one)\n * to the desired value at start-up.  Zero value means the collector\n * is to decide.  If the correct nonzero value is passed, then\n * `GC_parallel` will be set to the value minus one later.  Has no effect\n * if called after the collector initialization.  Does not itself cause\n * creation of the marker threads.  Does not use any synchronization.\n */\nGC_API void GC_CALL GC_set_markers_count(unsigned);\n\n/*\n * Public R/W variables.  The supplied setter and getter functions are\n * preferred for new client code.\n */\n\n/**\n * When there is insufficient memory to satisfy an allocation request,\n * we return `(*GC_oom_fn)(size)`.  If it returns, it must return either\n * `NULL` or a valid pointer to a previously allocated heap object.\n * By default, this just returns `NULL`.  If it points to a function which\n * never returns `NULL`, probably by aborting the program instead, then\n * invocations of `GC_MALLOC()` and friends (that are additionally marked\n * as \"never returning NULL unless GC_oom_fn returns NULL\") do not need to\n * be followed by code that checks for the `NULL` result.\n * `GC_oom_fn` must not be 0.  Both the setter and the getter acquire\n * the allocator lock (in the reader mode in case of the getter) to\n * avoid data race.\n */\ntypedef void *(GC_CALLBACK *GC_oom_func)(size_t /* `bytes_requested` */);\nGC_API GC_ATTR_DEPRECATED GC_oom_func GC_oom_fn;\nGC_API void GC_CALL GC_set_oom_fn(GC_oom_func) GC_ATTR_NONNULL(1);\nGC_API GC_oom_func GC_CALL GC_get_oom_fn(void);\n\n/**\n * Invoked when the heap grows or shrinks.  Called with the world\n * stopped (and the allocator lock held).  May be 0.  Both the setter\n * and the getter acquire the allocator lock (in the reader mode in\n * case of the getter).\n */\ntypedef void(GC_CALLBACK *GC_on_heap_resize_proc)(GC_word /* new_size */);\nGC_API GC_ATTR_DEPRECATED GC_on_heap_resize_proc GC_on_heap_resize;\nGC_API void GC_CALL GC_set_on_heap_resize(GC_on_heap_resize_proc);\nGC_API GC_on_heap_resize_proc GC_CALL GC_get_on_heap_resize(void);\n\ntypedef enum {\n  GC_EVENT_START, /*< start collection */\n  GC_EVENT_MARK_START,\n  GC_EVENT_MARK_END,\n  GC_EVENT_RECLAIM_START,\n  GC_EVENT_RECLAIM_END,\n  GC_EVENT_END,              /*< end collection */\n  GC_EVENT_PRE_STOP_WORLD,   /*< begin stopping world */\n  GC_EVENT_POST_STOP_WORLD,  /*< end stopping world */\n  GC_EVENT_PRE_START_WORLD,  /*< begin restarting world */\n  GC_EVENT_POST_START_WORLD, /*< end restarting world */\n  GC_EVENT_THREAD_SUSPENDED,\n  GC_EVENT_THREAD_UNSUSPENDED\n} GC_EventType;\n\n/**\n * Invoked to indicate progress through the collection process.\n * Not used for thread suspend/resume notifications.  Called with the\n * allocator lock held (or, even, the world stopped).  May be 0 (means\n * no notifier).  Both the setter and the getter acquire the allocator\n * lock (in the reader mode in case of the getter).\n */\ntypedef void(GC_CALLBACK *GC_on_collection_event_proc)(GC_EventType);\nGC_API void GC_CALL GC_set_on_collection_event(GC_on_collection_event_proc);\nGC_API GC_on_collection_event_proc GC_CALL GC_get_on_collection_event(void);\n\n#ifdef GC_THREADS\n/**\n * Invoked when a thread is suspended or resumed during collection.\n * Called with the allocator lock held (and the world stopped partially).\n * May be 0 (means no notifier).  Both the setter and the getter acquire\n * the allocator lock (in the reader mode in case of the getter).\n */\ntypedef void(GC_CALLBACK *GC_on_thread_event_proc)(GC_EventType,\n                                                   void * /* `thread_id` */);\nGC_API void GC_CALL GC_set_on_thread_event(GC_on_thread_event_proc);\nGC_API GC_on_thread_event_proc GC_CALL GC_get_on_thread_event(void);\n#endif\n\n/**\n * Turn on the find-leak mode (do not actually garbage collect, but\n * simply report inaccessible memory that was not deallocated with\n * `GC_FREE()`).  Initial value is determined by `FIND_LEAK` macro.\n * The value should not typically be modified after the collector\n * initialization (and, thus, it does not use or need synchronization).\n * The mode is supported only if the library has been compiled without\n * `NO_FIND_LEAK` macro defined.\n */\nGC_API GC_ATTR_DEPRECATED int GC_find_leak;\nGC_API void GC_CALL GC_set_find_leak(int);\nGC_API int GC_CALL GC_get_find_leak(void);\n\n/**\n * Arrange for pointers to object interiors to be recognized as valid.\n * Typically should not be changed after the collector initialization\n * (in case of calling it after the collector is initialized, the\n * setter acquires the allocator lock).  Must be only 0 or 1.\n * The initial value depends on whether the collector is built with\n * `ALL_INTERIOR_POINTERS` macro defined or not.  This also affects,\n * unless `GC_get_dont_add_byte_at_end()` returns a nonzero value,\n * whether the object sizes are increased by at least a byte to allow\n * \"off-the-end\" pointer recognition (but the size is not increased\n * for uncollectible objects as well as for ignore-off-page objects of\n * at least heap block size).\n */\nGC_API GC_ATTR_DEPRECATED int GC_all_interior_pointers;\nGC_API void GC_CALL GC_set_all_interior_pointers(int);\nGC_API int GC_CALL GC_get_all_interior_pointers(void);\n\n/**\n * If nonzero, finalizers will only be run in response to an explicit\n * `GC_invoke_finalizers()` call.  The default is determined by whether\n * the `FINALIZE_ON_DEMAND` macro is defined when the collector is built.\n * The setter and the getter are unsynchronized.\n */\nGC_API GC_ATTR_DEPRECATED int GC_finalize_on_demand;\nGC_API void GC_CALL GC_set_finalize_on_demand(int);\nGC_API int GC_CALL GC_get_finalize_on_demand(void);\n\n/**\n * Mark objects reachable from finalizable objects in a separate post-pass.\n * This makes it a bit safer to use non-topologically-ordered finalization.\n * Default value is determined by `JAVA_FINALIZATION` macro.\n * Enables `GC_register_finalizer_unreachable()` to work correctly.\n * The setter and the getter are unsynchronized.\n */\nGC_API GC_ATTR_DEPRECATED int GC_java_finalization;\nGC_API void GC_CALL GC_set_java_finalization(int);\nGC_API int GC_CALL GC_get_java_finalization(void);\n\n/**\n * Invoked by the collector when there are objects to be finalized.\n * Invoked at most once per collection cycle.  Never invoked unless\n * `GC_finalize_on_demand` is set.  Typically this will notify\n * a finalization thread, which will call `GC_invoke_finalizers()` in\n * response.  May be 0 (means no notifier).  Both the setter and the getter\n * acquire the allocator lock (in the reader mode in case of the getter).\n */\ntypedef void(GC_CALLBACK *GC_finalizer_notifier_proc)(void);\nGC_API GC_ATTR_DEPRECATED GC_finalizer_notifier_proc GC_finalizer_notifier;\nGC_API void GC_CALL GC_set_finalizer_notifier(GC_finalizer_notifier_proc);\nGC_API GC_finalizer_notifier_proc GC_CALL GC_get_finalizer_notifier(void);\n\n/**\n * The functions called to report pointer checking errors.  Called without\n * the allocator lock held.  The default behavior is to fail with the\n * appropriate message which includes the pointers.  The functions\n * (variables) must not be 0.  Both the setters and the getters are\n * unsynchronized.\n */\ntypedef void(GC_CALLBACK *GC_valid_ptr_print_proc_t)(void *);\ntypedef void(GC_CALLBACK *GC_same_obj_print_proc_t)(void * /* `p` */,\n                                                    void * /* `q` */);\nGC_API GC_ATTR_DEPRECATED GC_same_obj_print_proc_t GC_same_obj_print_proc;\nGC_API GC_ATTR_DEPRECATED GC_valid_ptr_print_proc_t\n    GC_is_valid_displacement_print_proc;\nGC_API GC_ATTR_DEPRECATED GC_valid_ptr_print_proc_t GC_is_visible_print_proc;\nGC_API void GC_CALL GC_set_same_obj_print_proc(GC_same_obj_print_proc_t)\n    GC_ATTR_NONNULL(1);\nGC_API GC_same_obj_print_proc_t GC_CALL GC_get_same_obj_print_proc(void);\nGC_API void\n    GC_CALL GC_set_is_valid_displacement_print_proc(GC_valid_ptr_print_proc_t)\n        GC_ATTR_NONNULL(1);\nGC_API GC_valid_ptr_print_proc_t GC_CALL\nGC_get_is_valid_displacement_print_proc(void);\nGC_API void GC_CALL GC_set_is_visible_print_proc(GC_valid_ptr_print_proc_t)\n    GC_ATTR_NONNULL(1);\nGC_API GC_valid_ptr_print_proc_t GC_CALL GC_get_is_visible_print_proc(void);\n\n/*\n * A flag indicating \"do not collect\" mode.  This overrides explicit\n * `GC_gcollect()` calls as well.  Used as a counter, so that nested\n * enabling and disabling work correctly.  Should normally be updated\n * with `GC_enable()` and `GC_disable()` calls.  Direct assignment to\n * `GC_dont_gc` variable is deprecated.  To check whether collections\n * are disabled, `GC_is_disabled()` is preferred for new code.\n */\nGC_API\n#ifndef GC_DONT_GC\nGC_ATTR_DEPRECATED\n#endif\nint GC_dont_gc;\n\n/**\n * Do not expand the heap unless explicitly requested or forced to.\n * The setter and the getter are unsynchronized.\n */\nGC_API GC_ATTR_DEPRECATED int GC_dont_expand;\nGC_API void GC_CALL GC_set_dont_expand(int);\nGC_API int GC_CALL GC_get_dont_expand(void);\n\n/**\n * Causes the non-incremental collector to use the entire heap before\n * collecting.  This sometimes results in more large-block fragmentation,\n * since very large blocks will tend to get broken up during each\n * collection cycle.  It is likely to result in a larger working set, but\n * lower collection frequencies, and hence fewer instructions executed in\n * the collector.\n */\nGC_API GC_ATTR_DEPRECATED int GC_use_entire_heap;\n\n/**\n * Number of partial collections between full collections.  Matters only\n * if `GC_is_incremental_mode()`.  Full collections are also triggered\n * if the collector detects a substantial increase in the number of the\n * in-use heap blocks.  Values in the tens are now perfectly reasonable.\n * The setter and the getter are unsynchronized, so\n * `GC_call_with_alloc_lock()` (`GC_call_with_reader_lock()` in case\n * of the getter) is required to avoid data race (if the value is\n * modified after the collector is put into the multi-threaded mode).\n */\nGC_API GC_ATTR_DEPRECATED int GC_full_freq;\nGC_API void GC_CALL GC_set_full_freq(int);\nGC_API int GC_CALL GC_get_full_freq(void);\n\n/**\n * Bytes not considered candidates for collection.  Used only to control\n * scheduling of collections.  Updated by `GC_malloc_uncollectable()` and\n * `GC_free()`.  Wizards only.  The setter and the getter are unsynchronized,\n * so `GC_call_with_alloc_lock()` (`GC_call_with_reader_lock()` in case of\n * the getter) is required to avoid data race (if the value is modified\n * after the collector is put into the multi-threaded mode).\n */\nGC_API GC_ATTR_DEPRECATED GC_word GC_non_gc_bytes;\nGC_API void GC_CALL GC_set_non_gc_bytes(GC_word);\nGC_API GC_word GC_CALL GC_get_non_gc_bytes(void);\n\n/**\n * Do not register dynamic library data segments automatically.\n * Also, if set by the collector itself (during a collection), this\n * means that such a registration is not supported.  Wizards only.\n * Should be set only if the client explicitly registers all roots.\n * (In some environments like Microsoft Windows and Apple's Darwin,\n * this may also prevent registration of the main data segment as a part\n * of the root set.)  The setter and the getter are unsynchronized.\n */\nGC_API GC_ATTR_DEPRECATED int GC_no_dls;\nGC_API void GC_CALL GC_set_no_dls(int);\nGC_API int GC_CALL GC_get_no_dls(void);\n\n/**\n * We try to make sure that we allocate at least\n * `N / GC_free_space_divisor` bytes between collections, where `N` is\n * twice the number of traced bytes, plus the number of untraced bytes\n * (i.e. bytes in the \"atomic\" objects), plus a rough estimate of the\n * root set size.  `N` approximates GC tracing work per collection.\n * The initial value is given by `GC_FREE_SPACE_DIVISOR` macro.\n * Increasing its value will use less space but more collection time.\n * Decreasing it will appreciably decrease total collection time at the\n * expense of space.  The setter and the getter are unsynchronized, so\n * `GC_call_with_alloc_lock()` (`GC_call_with_reader_lock()` in case of\n * the getter) is required to avoid data race (if the value is modified\n * after the collector is put into the multi-threaded mode).\n * In GC v7.1 and before, the setter returned the old value.\n */\nGC_API GC_ATTR_DEPRECATED GC_word GC_free_space_divisor;\nGC_API void GC_CALL GC_set_free_space_divisor(GC_word);\nGC_API GC_word GC_CALL GC_get_free_space_divisor(void);\n\n/**\n * The maximum number of collections attempted before reporting out of\n * memory after heap expansion fails.  Initially 0.  The setter and\n * getter are unsynchronized, so `GC_call_with_alloc_lock()`\n * (`GC_call_with_reader_lock()` in case of the getter) is required to\n * avoid data race (if the value is modified after the collector is put\n * into the multi-threaded mode).\n */\nGC_API GC_ATTR_DEPRECATED GC_word GC_max_retries;\nGC_API void GC_CALL GC_set_max_retries(GC_word);\nGC_API GC_word GC_CALL GC_get_max_retries(void);\n\n/**\n * The cold end (bottom) of user stack.  May be set in the client prior\n * to calling any `GC_` routines.  This avoids some overhead, and\n * potentially some signals that can confuse debuggers.  Otherwise the\n * collector attempts to set it automatically.  For multi-threaded\n * code, this is the cold end of the stack for the primordial thread.\n * For multi-threaded code, altering `GC_stackbottom` value directly\n * after the collector initialization has no effect.  Portable clients\n * should use `GC_set_stackbottom()`, `GC_get_stack_base()`,\n * `GC_call_with_gc_active()` and `GC_register_my_thread()` instead.\n */\nGC_API GC_ATTR_DEPRECATED char *GC_stackbottom;\n\n/**\n * Do not collect as part of the collector initialization.  Should be\n * set only if the client wants a chance to manually initialize the\n * root set before the first collection.  Interferes with black-listing.\n * Wizards only.  The setter and the getter are unsynchronized (and no\n * external locking is needed since the value is accessed at the collector\n * initialization only).\n */\nGC_API GC_ATTR_DEPRECATED int GC_dont_precollect;\nGC_API void GC_CALL GC_set_dont_precollect(int);\nGC_API int GC_CALL GC_get_dont_precollect(void);\n\n/**\n * If incremental collection is enabled, we try to terminate collections\n * after this many milliseconds (plus the amount of nanoseconds as given in\n * the latest `GC_set_time_limit_tv()` call, if any).  Not a hard time bound.\n * Setting this variable to `GC_TIME_UNLIMITED` essentially disables\n * incremental collection (i.e. disables the \"pause time exceeded\" tests)\n * while leaving generational collection enabled.  The setter and the\n * getter are unsynchronized, so `GC_call_with_alloc_lock()`\n * (`GC_call_with_reader_lock()` in case of the getter) is required to\n * avoid data race (if the value is modified after the collector is put\n * into the multi-threaded mode).  The setter does not update the value\n * of the nanosecond part of the time limit (it is zero unless ever set\n * by `GC_set_time_limit_tv()` call).\n */\nGC_API GC_ATTR_DEPRECATED unsigned long GC_time_limit;\n#define GC_TIME_UNLIMITED 999999\nGC_API void GC_CALL GC_set_time_limit(unsigned long);\nGC_API unsigned long GC_CALL GC_get_time_limit(void);\n\n/** A portable type definition of time with a nanosecond precision. */\nstruct GC_timeval_s {\n  unsigned long tv_ms;   /*< time in milliseconds */\n  unsigned long tv_nsec; /*< nanoseconds fraction (less than 1000000) */\n};\n\n/* Public procedures */\n\n/**\n * Set/get the time limit of the incremental collections.  This is\n * similar to `GC_set_time_limit` and `GC_get_time_limit` but the time\n * is provided with the nanosecond precision.  The value of `tv_nsec`\n * part should be less than a million.  If the value of `tv_ms` part is\n * `GC_TIME_UNLIMITED`, then `tv_nsec` part is ignored.  Initially, the\n * value of `tv_nsec` part of the time limit is zero.  The functions do\n * not use any synchronization.  Defined only if the library has been\n * compiled without `NO_CLOCK` macro defined.\n */\nGC_API void GC_CALL GC_set_time_limit_tv(struct GC_timeval_s);\nGC_API struct GC_timeval_s GC_CALL GC_get_time_limit_tv(void);\n\n/**\n * Set/get the minimum value of the ratio of allocated bytes since\n * garbage collection to the amount of finalizers created since that\n * collection (so value is greater than\n * `GC_bytes_allocd / (GC_fo_entries - last_fo_entries)`) which\n * triggers the collection instead heap expansion.  The value has no\n * effect in the collector incremental mode.  The default value is\n * 10000 unless `GC_ALLOCD_BYTES_PER_FINALIZER` macro with a custom value\n * is defined to build the collector.  The default value might be not the\n * right choice for clients where e.g. most objects have a finalizer.\n * Zero value effectively disables taking amount of finalizers in the\n * decision whether to collect or not.  The functions do not use any\n * synchronization.\n */\nGC_API void GC_CALL GC_set_allocd_bytes_per_finalizer(GC_word);\nGC_API GC_word GC_CALL GC_get_allocd_bytes_per_finalizer(void);\n\n/**\n * Tell the collector to start various performance measurements.\n * Only the total time taken by full collections and the average time\n * spent in the world-stopped collections are calculated, as of now.\n * And, currently, there is no way to stop the measurements.\n * The function does not use any synchronization.  Defined only if the\n * library has been compiled without `NO_CLOCK` macro defined.\n */\nGC_API void GC_CALL GC_start_performance_measurement(void);\n\n/**\n * Get the total time of all full collections since the start of the\n * performance measurements.  Includes time spent in the supplementary\n * actions like blacklists promotion, marks clearing, free lists\n * reconstruction and objects finalization.  The measurement unit is a\n * millisecond.  Note that the returned value wraps around on overflow.\n * The function does not use any synchronization.  Defined only if the\n * library has been compiled without `NO_CLOCK` macro defined.\n */\nGC_API unsigned long GC_CALL GC_get_full_gc_total_time(void);\n\n/**\n * Same as `GC_get_full_gc_total_time` but takes into account all mark\n * phases with the world stopped and nothing else.\n */\nGC_API unsigned long GC_CALL GC_get_stopped_mark_total_time(void);\n\n/**\n * Get the average time spent in all mark phases with the world stopped.\n * The average value is computed since the start of the performance\n * measurements (or right since the collector initialization if the\n * collector logging is enabled).  The result is in nanoseconds.\n * The function acquires the allocator lock (in the reader mode) to avoid\n * data race.  Defined only if the library has been compiled without\n * `NO_CLOCK` macro defined.\n */\nGC_API unsigned long GC_CALL GC_get_avg_stopped_mark_time_ns(void);\n\n/**\n * Set whether the garbage collector will allocate executable memory\n * pages or not.  A nonzero argument instructs the collector to\n * allocate memory with the executable flag on.  Must be called before\n * the collector is initialized.  May have no effect on some platforms.\n * The default value is controlled by `NO_EXECUTE_PERMISSION` macro (if\n * present then the flag is off).  Portable clients should have\n * `GC_set_pages_executable(1)` call (before `GC_INIT()` one) provided\n * they are going to execute code on any of the GC-allocated memory objects.\n */\nGC_API void GC_CALL GC_set_pages_executable(int);\n\n/**\n * Returns nonzero value if the garbage collector is set to the\n * allocate-executable-memory mode.  The mode could be changed by\n * `GC_set_pages_executable` (before `GC_INIT()` call) unless the former\n * has no effect on the platform.  Does not use or need synchronization.\n */\nGC_API int GC_CALL GC_get_pages_executable(void);\n\n/**\n * The setter and the getter of the minimum value returned by the internal\n * `min_bytes_allocd()`.  The value should not be zero; the default value\n * is one.  Not synchronized.\n */\nGC_API void GC_CALL GC_set_min_bytes_allocd(size_t);\nGC_API size_t GC_CALL GC_get_min_bytes_allocd(void);\n\n/**\n * Set/get the size in pages of units operated by `GC_collect_a_little()`.\n * The value should not be zero.  Not synchronized.\n */\nGC_API void GC_CALL GC_set_rate(int);\nGC_API int GC_CALL GC_get_rate(void);\n\n/**\n * Set/get the maximum number of prior attempts at the world-stop marking.\n * Not synchronized.\n */\nGC_API void GC_CALL GC_set_max_prior_attempts(int);\nGC_API int GC_CALL GC_get_max_prior_attempts(void);\n\n/**\n * Control whether to disable algorithm deciding if a collection should\n * be started when we allocated enough to amortize the collection.\n * Both the setter and the getter acquire the allocator lock (in the reader\n * mode in case of the getter) to avoid data race.\n */\nGC_API void GC_CALL GC_set_disable_automatic_collection(int);\nGC_API int GC_CALL GC_get_disable_automatic_collection(void);\n\n/**\n * Overrides the default handle-fork mode.  A nonzero value means GC\n * should install proper `pthread_atfork` handlers.  Has effect only\n * if called before the collector initialization.  Clients should call\n * `GC_set_handle_fork()` with nonzero argument if going to use `fork`\n * with the GC functions called in the child process.  (Note that such\n * client and at-fork handler activities are not fully POSIX-compliant.)\n * `GC_set_handle_fork()` instructs `GC_init` to setup GC fork handlers\n * using `pthread_atfork()`, the latter might fail (or, even, absent on\n * some targets) causing `abort` at the collector initialization.\n * Issues with missing (or failed) `pthread_atfork()` could be avoided\n * by invocation of `GC_set_handle_fork(-1)` at application start-up and\n * surrounding each `fork()` with the relevant\n * `GC_atfork_prepare`/`GC_atfork_parent`/`GC_atfork_child` calls.\n */\nGC_API void GC_CALL GC_set_handle_fork(int);\n\n/**\n * Routines to handle POSIX `fork()` manually (no-op if handled\n * automatically).  `GC_atfork_prepare()` should be called immediately\n * before `fork()`; `GC_atfork_parent()` should be invoked just after\n * `fork` in the branch that corresponds to parent process (i.e.,\n * `fork` result is nonzero); `GC_atfork_child()` is to be called\n * immediately in the child branch (i.e., `fork` result is 0).\n * Note that `GC_atfork_child()` call should, of course, precede\n * `GC_start_mark_threads()` call, if any.\n */\nGC_API void GC_CALL GC_atfork_prepare(void);\nGC_API void GC_CALL GC_atfork_parent(void);\nGC_API void GC_CALL GC_atfork_child(void);\n\n/**\n * Initialize the collector.  Portable clients should call `GC_INIT()`\n * from the program's `main()` instead.\n */\nGC_API void GC_CALL GC_init(void);\n\n/**\n * Return 1 (true) if the collector is initialized (or, at least, the\n * initialization is in progress), 0 otherwise.\n */\nGC_API int GC_CALL GC_is_init_called(void);\n\n/**\n * Perform the collector shutdown.  (E.g. dispose critical sections on\n * Windows target.)  A duplicate invocation is a no-op.  In case of Windows,\n * typically, the client should also call `GC_win32_free_heap()` before this\n * function call.\n * TODO: The collector reinitialization after shutdown might work in certain\n * configurations, but not tested.\n */\nGC_API void GC_CALL GC_deinit(void);\n\n/**\n * General-purpose allocation functions, with roughly `malloc` calling\n * conventions.  The atomic variants promise that no relevant pointers\n * are contained in the object.  The non-atomic variants guarantee that\n * the new object is cleared.  `GC_malloc_uncollectable()` allocates\n * an object that is scanned for pointers to collectible objects, but\n * is not itself collectible.  The object is scanned even if it does\n * not appear to be reachable.  `GC_malloc_uncollectable()` and `GC_free()`\n * called on the resulting object implicitly update `GC_non_gc_bytes`\n * appropriately.  All these functions (`GC_malloc`, `GC_malloc_atomic`,\n * `GC_strdup`, `GC_strndup`, `GC_malloc_uncollectable`) are guaranteed\n * never to return `NULL` unless `GC_oom_fn()` returns `NULL`.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_malloc(size_t /* `size_in_bytes` */);\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_malloc_atomic(size_t /* `size_in_bytes` */);\nGC_API GC_ATTR_MALLOC char *GC_CALL GC_strdup(const char *);\nGC_API GC_ATTR_MALLOC char *GC_CALL GC_strndup(const char *, size_t)\n    GC_ATTR_NONNULL(1);\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_malloc_uncollectable(size_t /* `size_in_bytes` */);\n\n/**\n * The allocation function which guarantees the requested alignment of\n * the allocated memory object.  The `align` argument should be nonzero\n * and a power of two.  It is guaranteed never to return `NULL` unless\n * `GC_oom_fn()` returns `NULL`.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(2) void *GC_CALL\n    GC_memalign(size_t /* `align` */, size_t /* `lb` */);\n\n/**\n * A function similar to `GC_memalign` but existing largely for\n * redirection in the find-leak mode.  The `align` argument should be\n * nonzero and a power of two, but additionally the argument is\n * required to be not less than size of a pointer.  Note that the\n * function does not change value of `*memptr` in case of failure\n * (i.e. when the result is nonzero).  It is guaranteed never to return\n * `NULL` unless `GC_oom_fn()` returns `NULL`.\n */\nGC_API int GC_CALL GC_posix_memalign(void ** /* `memptr` */,\n                                     size_t /* `align` */, size_t /* `lb` */)\n    GC_ATTR_NONNULL(1);\n\n#ifndef GC_NO_VALLOC\n/**\n * The allocation functions that guarantee the memory page alignment of\n * the returned object.  Exist largely for redirection in the find-leak\n * mode.  All these functions (`GC_pvalloc`, `GC_valloc`) are guaranteed\n * never to return `NULL` unless `GC_oom_fn()` returns `NULL`.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_valloc(size_t /* `lb` */);\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_pvalloc(size_t /* `lb` */);\n#endif\n\n/**\n * Explicitly deallocate an object.  Dangerous if used incorrectly.\n * Requires a pointer to the base of an object.  An object should not\n * be enabled for finalization (and it should not contain registered\n * disappearing links of any kind) when it is explicitly deallocated.\n * `GC_free(0)` is a no-op, as required by ANSI C for `free()`.\n */\nGC_API void GC_CALL GC_free(void *);\nGC_API void GC_CALL GC_debug_free(void *);\n\n/**\n * A symbol to be intercepted by heap profilers so that they can\n * accurately track allocations.  Programs such as Valgrind `massif`\n * and KDE heaptrack do tracking of allocated objects by overriding\n * common allocator methods (e.g. `malloc` and `free`).  However,\n * because the collector does not work by calling standard allocation\n * methods on objects that were reclaimed, we need a way to tell the\n * profiler that an object has been freed.  This function is not\n * intended to be called by the client, it should be used for the\n * interception purpose only.  The collector calls this function\n * internally whenever an object is freed.  Defined only if the library\n * has been compiled with `VALGRIND_TRACKING` macro defined.\n */\nGC_API void GC_CALLBACK GC_free_profiler_hook(void *);\n\n#if (defined(GC_CAN_SAVE_CALL_STACKS) || defined(GC_ADD_CALLER)) \\\n    && !defined(GC_RETURN_ADDR_T_DEFINED)\n/*\n * A type to hold a function return address (pointer).  Never used for\n * calling a function.\n */\n#  if defined(__GNUC__)\n/*\n * Defined as a data (object) pointer type to avoid the compiler complain\n * that ISO C forbids conversion between object and function pointer types.\n */\ntypedef void *GC_return_addr_t;\n#  else\ntypedef void (*GC_return_addr_t)(void);\n#  endif\n#  define GC_RETURN_ADDR_T_DEFINED\n#endif /* GC_CAN_SAVE_CALL_STACKS || GC_ADD_CALLER */\n\n#ifdef GC_ADD_CALLER\n#  define GC_EXTRAS GC_RETURN_ADDR, __FILE__, __LINE__\n#  define GC_EXTRA_PARAMS GC_return_addr_t ra, const char *s, int i\n#else\n#  define GC_EXTRAS __FILE__, __LINE__\n#  define GC_EXTRA_PARAMS const char *s, int i\n#endif\n\n/*\n * The \"stubborn\" objects allocation is not supported anymore.\n * Exists only for the backward compatibility.\n */\n#define GC_MALLOC_STUBBORN(sz) GC_MALLOC(sz)\n#define GC_NEW_STUBBORN(t) GC_NEW(t)\n#define GC_CHANGE_STUBBORN(p) GC_change_stubborn(p)\nGC_API GC_ATTR_DEPRECATED void GC_CALL GC_change_stubborn(const void *);\nGC_API GC_ATTR_DEPRECATED void GC_CALL GC_debug_change_stubborn(const void *);\nGC_API GC_ATTR_ALLOC_SIZE(1) GC_ATTR_DEPRECATED void *GC_CALL\n    GC_malloc_stubborn(size_t);\nGC_API GC_ATTR_ALLOC_SIZE(1) GC_ATTR_DEPRECATED void *GC_CALL\n    GC_debug_malloc_stubborn(size_t, GC_EXTRA_PARAMS);\n\n/**\n * Inform the collector that the object has been changed.\n * Only non-`NULL` pointer stores into the object are considered to be\n * changes.  Matters only if the incremental collection is enabled in\n * the manual VDB (virtual dirty bits) mode; otherwise the function\n * does nothing.  Should be followed typically by `GC_reachable_here()`\n * called for each of the stored pointers.\n */\nGC_API void GC_CALL GC_end_stubborn_change(const void *) GC_ATTR_NONNULL(1);\nGC_API void GC_CALL GC_debug_end_stubborn_change(const void *)\n    GC_ATTR_NONNULL(1);\n\n/**\n * Return a pointer to the base (lowest address) of an object given\n * a pointer to a location within the object.  I.e., map an interior\n * pointer to the corresponding base pointer.  Note that with debugging\n * allocation, this returns a pointer to the actual base of the object,\n * i.e. the debug information, not to the base of the user object.\n * Return `NULL` if `displaced_pointer` does not point to within\n * a valid object.  Note that a deallocated object in the garbage\n * collected heap may be considered valid, even if it has been\n * deallocated with `GC_free()`.\n */\nGC_API void *GC_CALL GC_base(void * /* `displaced_pointer` */);\n\n/**\n * Return 1 (true) if the argument points to somewhere in the garbage\n * collected heap, 0 otherwise.  Primary use is as a fast alternative to\n * `GC_base()` to check whether the given object is allocated by the\n * collector or not.  It is assumed that the collector is already initialized.\n */\nGC_API int GC_CALL GC_is_heap_ptr(const void *);\n\n/**\n * Given a pointer to the base of an object, return its size in bytes.\n * (For small objects this also happens to work from interior pointers,\n * but that should not be relied upon.)  The returned size may be slightly\n * larger than what was originally requested.  The argument may be `NULL`\n * (causing 0 to be returned).\n */\nGC_API size_t GC_CALL GC_size(const void * /* `obj` */);\n\n/**\n * For compatibility with C library.  This is occasionally faster than\n * a `malloc` followed by a `bcopy`.  But if you rely on that, either\n * here or with the standard C library, your code is broken.\n * Probably, it should not have been invented, but now we are stuck.\n * The resulting object has the same kind as the original one.\n * It is an error to have changes enabled for the original object.\n * It does not change the content of the object from its beginning to\n * the minimum of old size and `new_size_in_bytes`; the content above in\n * case of object size growth is initialized to zero (not guaranteed for\n * atomic object type).  The function follows ANSI conventions for `NULL`\n * `old_object` (i.e., equivalent to `GC_malloc` regardless of\n * `new_size_in_bytes`).  If `new_size_in_bytes` is zero (and\n * `old_object` is non-`NULL`), then the call is equivalent to\n * `GC_free` (and `NULL` is returned).  If `old_object` is non-`NULL`,\n * it must have been returned by an earlier call to `GC_realloc`,\n * `GC_malloc` or friends.  In case of the allocation failure, the\n * memory pointed by `old_object` is untouched (and not freed).  If the\n * returned pointer is not the same as `old_object` and both of them\n * are non-`NULL`, then `old_object` is freed.  Returns either `NULL`\n * (in case of the allocation failure or zero `new_size_in_bytes`) or\n * pointer to the allocated memory.  For a nonzero `new_size_in_bytes`,\n * the function (including its debug variant) is guaranteed never to\n * return `NULL` unless `GC_oom_fn()` returns `NULL`.\n */\nGC_API void *GC_CALL GC_realloc(void * /* `old_object` */,\n                                size_t /* `new_size_in_bytes` */)\n    /* `realloc` attribute */ GC_ATTR_ALLOC_SIZE(2);\nGC_API void *GC_CALL GC_debug_realloc(void * /* `old_object` */,\n                                      size_t /* `new_size_in_bytes` */,\n                                      GC_EXTRA_PARAMS)\n    /* `realloc` attribute */ GC_ATTR_ALLOC_SIZE(2);\n\n/**\n * Increase the heap size explicitly.  The performed increase is at\n * least `number_of_bytes`.  Does the collector initialization as well\n * (if not yet).  Returns 0 on failure, 1 on success.\n */\nGC_API int GC_CALL GC_expand_hp(size_t /* `number_of_bytes` */);\n\n/**\n * Limit the heap size to `n` bytes.  Useful when you are debugging,\n * especially on systems that do not handle running out of memory well.\n * A zero `n` means the heap is unbounded; this is the default.\n * This setter function is unsynchronized (so it might require\n * `GC_call_with_alloc_lock` to avoid data race).\n */\nGC_API void GC_CALL GC_set_max_heap_size(GC_word /* `n` */);\n\n/**\n * Inform the collector that a certain section of statically allocated\n * memory contains no pointers to garbage-collected memory.  Thus it does\n * not need to be scanned.  This is sometimes important if the application\n * maps large read/write files into the address space, which could be\n * mistaken for dynamic library data segments on some systems.\n * Both section start (`low_address`) and end (`high_address_plus_1`)\n * are not needed to be pointer-aligned.\n */\nGC_API void GC_CALL GC_exclude_static_roots(\n    void * /* `low_address` */, void * /* `high_address_plus_1` */);\n\n/**\n * Clear the number of entries in the exclusion table.  Wizards only.\n * Should be called typically with the allocator lock held, but no\n * assertion about it by design.\n */\nGC_API void GC_CALL GC_clear_exclusion_table(void);\n\n/** Clear the set of root segments.  Wizards only. */\nGC_API void GC_CALL GC_clear_roots(void);\n\n/**\n * Add a root segment.  Wizards only.  May merge adjacent or overlapping\n * segments if appropriate.  Both segment start (`low_address`) and\n * end (`high_address_plus_1`) are not needed to be pointer-aligned.\n * `low_address` must not be greater than `high_address_plus_1`.\n */\nGC_API void GC_CALL GC_add_roots(void * /* `low_address` */,\n                                 void * /* `high_address_plus_1` */);\n\n/** Remove root segments located fully in the region.  Wizards only. */\nGC_API void GC_CALL GC_remove_roots(void * /* `low_address` */,\n                                    void * /* `high_address_plus_1` */);\n\n/**\n * Add a displacement to the set of those considered valid by the\n * collector.  `GC_register_displacement(offset)` means that if `p` was\n * returned by `GC_malloc()`, then `(char *)p + offset` will be\n * considered to be a valid pointer to `p`.  `offset` must be less than\n * the size of a heap block.  (All pointers to the interior of objects\n * from the stack are considered valid in any case.  This applies to\n * heap objects and static data.)  Preferably, this should be called\n * before any other GC procedures.  Calling it later adds to the\n * probability of excess memory retention.  This is a no-op if the\n * collector has recognition of arbitrary interior pointers enabled,\n * which is the default (assuming the collector is built with\n * `ALL_INTERIOR_POINTERS` macro defined).  The debugging variant should\n * be used if any debugging allocation is being done.\n */\nGC_API void GC_CALL GC_register_displacement(size_t /* `offset` */);\nGC_API void GC_CALL GC_debug_register_displacement(size_t /* `offset` */);\n\n/** Explicitly trigger a full, world-stop collection. */\nGC_API void GC_CALL GC_gcollect(void);\n\n/**\n * Same as above but ignores the default `stop_func` setting and tries\n * to unmap as much memory as possible (regardless of the corresponding\n * switch setting).  The recommended usage: on receiving a system\n * low-memory event; before retrying a system call failed because of\n * the system is running out of resources.\n */\nGC_API void GC_CALL GC_gcollect_and_unmap(void);\n\n/**\n * Trigger a full world-stopped collection.  Abort the collection if\n * and when `stop_func()` returns a nonzero value.  `stop_func()` will\n * be called frequently, and should be reasonably fast.\n * (`stop_func()` is called with the allocator lock held and the world\n * might be stopped; it is not allowed for `stop_func()` to manipulate\n * pointers to the garbage-collected heap or call most of GC functions.)\n * This works even if no virtual dirty bits, and hence incremental\n * collection is not available for the architecture.  Collections can\n * be aborted faster than normal pause times for incremental collection;\n * however, aborted collections do no useful work; the next collection\n * needs to start from the beginning.  `stop_func` must not be 0.\n * `GC_try_to_collect()` returns 0 if the collection was aborted (or the\n * collections are disabled), 1 if it succeeded.\n */\ntypedef int(GC_CALLBACK *GC_stop_func)(void);\nGC_API int GC_CALL GC_try_to_collect(GC_stop_func /* `stop_func` */)\n    GC_ATTR_NONNULL(1);\n\n/**\n * Set/get the default `stop_func`.  The latter is used by `GC_gcollect()`\n * and by implicitly triggered collections (except for the case when\n * handling out of memory).  Must not be 0.  Both the setter and the getter\n * acquire the allocator lock (in the reader mode in case of the getter)\n * to avoid data race.\n */\nGC_API void GC_CALL GC_set_stop_func(GC_stop_func /* `stop_func` */)\n    GC_ATTR_NONNULL(1);\nGC_API GC_stop_func GC_CALL GC_get_stop_func(void);\n\n/**\n * Return the number of bytes in the heap.  Excludes collector private\n * data structures; excludes the unmapped memory (returned to the OS).\n * Includes empty blocks and fragmentation loss.  Includes some pages\n * that were allocated but never written.  This is an unsynchronized\n * getter, so it should be called typically with the allocator lock\n * held, at least in the reader mode, to avoid data race on\n * multiprocessors (the alternative way is to use `GC_get_prof_stats`\n * or `GC_get_heap_usage_safe` API calls instead).\n * This getter remains lock-free (unsynchronized) for compatibility\n * reason since some existing clients call it from a GC callback\n * holding the allocator lock.  (This API function and the following\n * four ones below were made thread-safe in GC v7.2alpha1 and\n * reverted back in v7.2alpha7 for the reason described.)\n */\nGC_API size_t GC_CALL GC_get_heap_size(void);\n\n/**\n * Return a lower bound on the number of free bytes in the heap\n * (excluding the unmapped memory space).  This is an unsynchronized\n * getter (see `GC_get_heap_size` comment regarding thread-safety).\n */\nGC_API size_t GC_CALL GC_get_free_bytes(void);\n\n/**\n * Return the size (in bytes) of the unmapped memory (which is returned\n * to the OS but could be remapped back by the collector later unless\n * the OS runs out of system/virtual memory).  This is an unsynchronized\n * getter (see `GC_get_heap_size` comment regarding thread-safety).\n */\nGC_API size_t GC_CALL GC_get_unmapped_bytes(void);\n\n/**\n * Return the number of bytes allocated since the last collection.\n * This is an unsynchronized getter (see `GC_get_heap_size` comment\n * regarding thread-safety).\n */\nGC_API size_t GC_CALL GC_get_bytes_since_gc(void);\n\n/**\n * Return the number of explicitly deallocated bytes of memory since\n * the recent collection.  This is an unsynchronized getter.\n */\nGC_API size_t GC_CALL GC_get_expl_freed_bytes_since_gc(void);\n\n/**\n * Return the total number of bytes allocated in this process.\n * Never decreases, except due to wrapping.  This is an unsynchronized\n * getter (see `GC_get_heap_size` comment regarding thread-safety).\n */\nGC_API size_t GC_CALL GC_get_total_bytes(void);\n\n/**\n * Return the total number of bytes obtained from OS.  Includes the\n * unmapped memory.  Never decreases.  It is an unsynchronized getter.\n */\nGC_API size_t GC_CALL GC_get_obtained_from_os_bytes(void);\n\n/**\n * Return the heap usage information.  This is a thread-safe (atomic)\n * alternative for the five above getters.   (This function acquires\n * the allocator lock in the reader mode, thus preventing data race and\n * returning the consistent result.)  Passing `NULL` pointer is allowed\n * for any argument.  Returned (filled in) values are of `GC_word` type.\n */\nGC_API void GC_CALL GC_get_heap_usage_safe(GC_word * /* `pheap_size` */,\n                                           GC_word * /* `pfree_bytes` */,\n                                           GC_word * /* `punmapped_bytes` */,\n                                           GC_word * /* `pbytes_since_gc` */,\n                                           GC_word * /* `ptotal_bytes` */);\n\n/**\n * Structure used to query the GC statistics (profiling information).\n * More fields could be added in the future.  To preserve compatibility\n * new fields should be added only to the end, and no deprecated fields\n * should be removed from.\n */\nstruct GC_prof_stats_s {\n  /**\n   * Heap size in bytes (including the area unmapped to OS).\n   * Same as value of `GC_get_heap_size() + GC_get_unmapped_bytes()`.\n   */\n  GC_word heapsize_full;\n\n  /**\n   * Total bytes contained in free and unmapped blocks.\n   * Same as result of `GC_get_free_bytes() + GC_get_unmapped_bytes()`.\n   */\n  GC_word free_bytes_full;\n\n  /**\n   * Amount of memory unmapped to OS.  Same as the value returned by\n   * `GC_get_unmapped_bytes()`.\n   */\n  GC_word unmapped_bytes;\n\n  /**\n   * Number of bytes allocated since the recent collection.\n   * Same as the value returned by `GC_get_bytes_since_gc()`.\n   */\n  GC_word bytes_allocd_since_gc;\n\n  /**\n   * Number of bytes allocated before the recent garbage collection.\n   * The value may wrap.  Same as the result of\n   * `GC_get_total_bytes() - GC_get_bytes_since_gc()`.\n   */\n  GC_word allocd_bytes_before_gc;\n\n  /**\n   * Number of bytes not considered candidates for garbage collection.\n   * Same as the value returned by `GC_get_non_gc_bytes()`.\n   */\n  GC_word non_gc_bytes;\n\n  /**\n   * Garbage collection cycle number.  The value may wrap.  Same as the\n   * value returned by `GC_get_gc_no()`.\n   */\n  GC_word gc_no;\n\n  /**\n   * Number of marker threads (excluding the initiating one).  Same as\n   * the value returned by `GC_get_parallel()` (or 0 if the collector\n   * is single-threaded).\n   */\n  GC_word markers_m1;\n\n  /**\n   * Approximate number of reclaimed bytes after the recent garbage\n   * collection.\n   */\n  GC_word bytes_reclaimed_since_gc;\n\n  /**\n   * Approximate number of bytes reclaimed before the recent garbage\n   * collection.  The value may wrap.\n   */\n  GC_word reclaimed_bytes_before_gc;\n\n  /**\n   * Number of bytes freed explicitly since the recent garbage collection.\n   * Same as the value returned by `GC_get_expl_freed_bytes_since_gc()`.\n   */\n  GC_word expl_freed_bytes_since_gc;\n\n  /** Total amount of memory obtained from OS, in bytes. */\n  GC_word obtained_from_os_bytes;\n};\n\n/**\n * Atomically get the collector statistics (various global counters).\n * Clients should pass the size of the buffer (of `GC_prof_stats_s` type)\n * to fill in the values - this is for interoperability between different\n * collector versions: an old client could have fewer fields, and vice\n * versa, client could use newer `gc.h` file (with more entries declared\n * in the structure) than that of the linked collector library; in the\n * latter case, unsupported (unknown) fields are filled in with -1 (`~0`).\n * Return the size (in bytes) of the filled in part of the structure\n * (excluding all unknown fields, if any).\n */\nGC_API size_t GC_CALL GC_get_prof_stats(struct GC_prof_stats_s *,\n                                        size_t /* `stats_sz` */);\n#ifdef GC_THREADS\n/**\n * Same as `GC_get_prof_stats` but unsynchronized (i.e., not holding\n * the allocator lock).  Clients should call it using\n * `GC_call_with_reader_lock()` to avoid data race on multiprocessors.\n */\nGC_API size_t GC_CALL GC_get_prof_stats_unsafe(struct GC_prof_stats_s *,\n                                               size_t /* `stats_sz` */);\n#endif\n\n/**\n * Get the element value (converted to bytes) at a given index of\n * `GC_size_map` table which provides requested-to-actual allocation size\n * mapping.  Assumes the collector is initialized.  Returns -1 (`~0`) if\n * the index is out of `GC_size_map` table bounds.  Does not use\n * synchronization, thus clients should call it using\n * `GC_call_with_reader_lock()` typically to avoid data race on\n * multiprocessors.\n */\nGC_API size_t GC_CALL GC_get_size_map_at(int i);\n\n/**\n * Return the total memory use (in bytes) by all allocated blocks.\n * The result is equal to `GC_get_heap_size() - GC_get_free_bytes()`.\n * Acquires the allocator lock in the reader mode.\n */\nGC_API GC_word GC_CALL GC_get_memory_use(void);\n\n/**\n * Disable garbage collection.  Even `GC_gcollect()` calls will be\n * ineffective.\n */\nGC_API void GC_CALL GC_disable(void);\n\n/**\n * Return 1 (true) if the garbage collection is disabled (i.e., the\n * value of `GC_dont_gc` is nonzero), 0 otherwise.  Does not acquire\n * the allocator lock.\n */\nGC_API int GC_CALL GC_is_disabled(void);\n\n/**\n * Try to re-enable garbage collection.  `GC_disable()` and `GC_enable()`\n * calls could be nested.  Garbage collection is enabled if the number of\n * calls to both functions is equal.\n */\nGC_API void GC_CALL GC_enable(void);\n\n/**\n * Select whether to use the manual VDB (virtual dirty bits) mode for\n * the incremental collection.  Has no effect if called after enabling\n * the incremental collection.  The default value is off unless the\n * collector is compiled with `MANUAL_VDB` macro defined.  The manual\n * VDB mode should be used only if the client has the appropriate\n * `GC_END_STUBBORN_CHANGE()` and `GC_reachable_here()` (or,\n * alternatively, `GC_PTR_STORE_AND_DIRTY()`) calls (to ensure proper\n * write barriers).  The setter and the getter are not synchronized.\n */\nGC_API void GC_CALL GC_set_manual_vdb_allowed(int);\nGC_API int GC_CALL GC_get_manual_vdb_allowed(void);\n\n/*\n * The constants to represent available VDB (virtual dirty bits)\n * techniques.\n */\n\n/** Means the incremental mode is unsupported. */\n#define GC_VDB_NONE 0\n\n#define GC_VDB_MPROTECT 0x1\n\n/** Means `GC_set_manual_vdb_allowed(1)` has effect. */\n#define GC_VDB_MANUAL 0x2\n\n/** Means no other technique is usable. */\n#define GC_VDB_DEFAULT 0x4\n\n#define GC_VDB_GWW 0x8\n\n#define GC_VDB_PROC 0x20\n#define GC_VDB_SOFT 0x40\n\n/**\n * Get the list of available VDB (virtual dirty bits) techniques.\n * The returned value is a constant one, either `GC_VDB_NONE`, or one\n * or more of the above `GC_VDB_` constants, or'ed together.  May be\n * called before the collector is initialized.\n */\nGC_API unsigned GC_CALL GC_get_supported_vdbs(void);\n\n/**\n * Enable incremental/generational collection.  Not advisable unless\n * dirty bits are available or most heap objects are pointer-free\n * (atomic) or immutable.  Do not use in the find-leak mode.\n * Ignored if `GC_dont_gc` is nonzero.  Only the generational piece of\n * this is functional if `GC_time_limit` is set to `GC_TIME_UNLIMITED`.\n * Causes thread-local variant of `GC_gcj_malloc()` to revert to locked\n * allocation.  Must be called before any such `GC_gcj_malloc()` calls.\n * For best performance, should be called as early as possible.\n * On some platforms, calling it later may have adverse effects.\n * Safe to call before the collector initialization; it performs the\n * latter if not done yet.\n */\nGC_API void GC_CALL GC_enable_incremental(void);\n\n/**\n * Return 1 (true) if the incremental mode is on, 0 otherwise.\n * Does not acquire the allocator lock.\n */\nGC_API int GC_CALL GC_is_incremental_mode(void);\n\n/**\n * An extended variant of `GC_is_incremental_mode()` to return one of\n * `GC_VDB_` constants designating which VDB (virtual dirty bits)\n * technique is used exactly.  Does not acquire the allocator lock.\n */\nGC_API unsigned GC_CALL GC_get_actual_vdb(void);\n\n/** May protect non-atomic objects. */\n#define GC_PROTECTS_POINTER_HEAP 1\n\n#define GC_PROTECTS_PTRFREE_HEAP 2\n\n/* Protects static data.  But this is currently never. */\n#define GC_PROTECTS_STATIC_DATA 4\n\n/* Deprecated.  It is probably impractical to protect stacks. */\n#define GC_PROTECTS_STACK 8\n\n#define GC_PROTECTS_NONE 0\n\n/**\n * Does incremental mode write-protect pages?  Returns zero or\n * more of the above `GC_PROTECTS_` constants, or'ed together.\n * The collector is assumed to be initialized before this call.\n * The result is not affected by `GC_set_manual_vdb_allowed()`.\n * Call of `GC_enable_incremental()` may change the result to\n * `GC_PROTECTS_NONE` if some implementation is chosen at\n * runtime not needing to write-protect the pages.\n */\nGC_API int GC_CALL GC_incremental_protection_needs(void);\n\n/**\n * Force start of incremental collection.  Acquires the allocator lock.\n * No-op unless the incremental mode is on.\n */\nGC_API void GC_CALL GC_start_incremental_collection(void);\n\n/**\n * Perform some garbage collection work, if appropriate.\n * Return 0 if there is no more work to be done (including the\n * case when garbage collection is not appropriate).\n * Typically performs an amount of work corresponding roughly\n * to marking from one page.  May do more work if further\n * progress requires it, e.g. if incremental collection is\n * disabled.  It is reasonable to call this in a wait loop\n * until it returns 0.  If the garbage collection is disabled\n * but the incremental collection is already ongoing, then\n * perform marking anyway but not stopping the world (and\n * without the reclaim phase).\n */\nGC_API int GC_CALL GC_collect_a_little(void);\n\n/**\n * Allocate an object of size `lb` bytes.  The client guarantees that\n * as long as the object is live, it will be referenced by a pointer\n * that points to somewhere within the first GC heap block (`hblk`) of\n * the object.  (This should normally be declared `volatile` to prevent\n * the compiler from invalidating this assertion.)  This function is\n * only useful if a large array is being allocated.  It reduces the\n * chance of accidentally retaining such an array as a result of\n * scanning an integer that happens to be an address inside the array.\n * (Actually, it reduces the chance of the allocator not finding space\n * for such an array, since it will try hard to avoid introducing such\n * a false reference.)  On a SunOS 4.x or Windows system this is\n * recommended for arrays likely to be larger than 100 KB or so.\n * For other systems, or if the collector is not configured to\n * recognize all interior pointers, the threshold is normally much\n * higher.  These functions are guaranteed never to return `NULL`\n * unless `GC_oom_fn()` returns `NULL`.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_malloc_ignore_off_page(size_t /* `lb` */);\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_malloc_atomic_ignore_off_page(size_t /* `lb` */);\n\n/**\n * Allocate `lb` bytes of pointer-free, untraced, uncollectible data.\n * This is normally roughly equivalent to the system `malloc`.  But it\n * may be useful if `malloc` is redefined.  The function (including its\n * debug variant) is guaranteed never to return `NULL` unless\n * `GC_oom_fn()` returns `NULL`.  Defined only if the library has been\n * compiled with `GC_ATOMIC_UNCOLLECTABLE` macro defined.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_malloc_atomic_uncollectable(size_t /* `size_in_bytes` */);\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_debug_malloc_atomic_uncollectable(size_t, GC_EXTRA_PARAMS);\n\n/**\n * Debugging (annotated) allocation.  `GC_gcollect()` will check\n * objects allocated in this way for overwrites, etc.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_debug_malloc(size_t /* `size_in_bytes` */, GC_EXTRA_PARAMS);\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_debug_malloc_atomic(size_t /* `size_in_bytes` */, GC_EXTRA_PARAMS);\nGC_API GC_ATTR_MALLOC char *GC_CALL GC_debug_strdup(const char *,\n                                                    GC_EXTRA_PARAMS);\nGC_API GC_ATTR_MALLOC char *GC_CALL GC_debug_strndup(const char *, size_t,\n                                                     GC_EXTRA_PARAMS)\n    GC_ATTR_NONNULL(1);\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_debug_malloc_uncollectable(size_t /* `size_in_bytes` */,\n                                  GC_EXTRA_PARAMS);\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_debug_malloc_ignore_off_page(size_t /* `size_in_bytes` */,\n                                    GC_EXTRA_PARAMS);\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_debug_malloc_atomic_ignore_off_page(size_t /* `size_in_bytes` */,\n                                           GC_EXTRA_PARAMS);\n\n/**\n * The functions that allocate objects with debug information (like the\n * above), but just fill in dummy file and line number information.\n * Thus they can serve as drop-in `malloc`/`realloc` replacements.\n * This can be useful for two reasons:\n *   1. It allows the collector to be built with `DBG_HDRS_ALL` macro\n *      defined even if some allocation calls come from 3rd-party\n *      libraries that cannot be recompiled.\n *   2. On some platforms, the file and line information is redundant,\n *      since it can be reconstructed from a stack trace.  On such\n *      platforms it may be more convenient not to recompile, e.g. for\n *      leak detection.  This can be accomplished by instructing the\n *      linker to replace `malloc`/`realloc` with these.\n *\n * Note that these functions (for a nonzero new size in case of\n * `realloc`) are guaranteed never to return `NULL` unless\n * `GC_oom_fn()` returns `NULL`.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_debug_malloc_replacement(size_t /* `size_in_bytes` */);\nGC_API /* `realloc` attribute */ GC_ATTR_ALLOC_SIZE(2) void *GC_CALL\n    GC_debug_realloc_replacement(void * /* `obj` */,\n                                 size_t /* `size_in_bytes` */);\n\n#ifdef __cplusplus\n#  define GC_CAST_AWAY_CONST_PVOID(p) \\\n    reinterpret_cast</* no const */ void *>(reinterpret_cast<GC_uintptr_t>(p))\n#else\n#  define GC_CAST_AWAY_CONST_PVOID(p) \\\n    ((/* no const */ void *)(GC_uintptr_t)(p))\n#endif\n\n/**\n * Convenient macros for disappearing links registration working both\n * for debug and non-debug allocated objects, and accepting interior\n * pointers to object.\n */\n#define GC_GENERAL_REGISTER_DISAPPEARING_LINK_SAFE(link, obj) \\\n  GC_general_register_disappearing_link(                      \\\n      link, GC_base(GC_CAST_AWAY_CONST_PVOID(obj)))\n#define GC_REGISTER_LONG_LINK_SAFE(link, obj) \\\n  GC_register_long_link(link, GC_base(GC_CAST_AWAY_CONST_PVOID(obj)))\n\n/*\n * Convenient macros over debug and non-debug allocation functions.\n * All these macros (`GC_MALLOC`, `GC_REALLOC`, `GC_MALLOC_ATOMIC`,\n * `GC_STRDUP`, `GC_STRNDUP`, `GC_MALLOC_ATOMIC_UNCOLLECTABLE`,\n * `GC_MALLOC_UNCOLLECTABLE`, `GC_MALLOC_IGNORE_OFF_PAGE`,\n * `GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE`) are guaranteed never to return\n * `NULL` (for a nonzero new size in case of `GC_REALLOC`) unless\n * `GC_oom_fn()` returns `NULL`.\n */\n#ifdef GC_DEBUG_REPLACEMENT\n#  define GC_MALLOC(sz) GC_debug_malloc_replacement(sz)\n#  define GC_REALLOC(old, sz) GC_debug_realloc_replacement(old, sz)\n#elif defined(GC_DEBUG)\n#  define GC_MALLOC(sz) GC_debug_malloc(sz, GC_EXTRAS)\n#  define GC_REALLOC(old, sz) GC_debug_realloc(old, sz, GC_EXTRAS)\n#else\n#  define GC_MALLOC(sz) GC_malloc(sz)\n#  define GC_REALLOC(old, sz) GC_realloc(old, sz)\n#endif /* !GC_DEBUG_REPLACEMENT && !GC_DEBUG */\n#ifdef GC_DEBUG\n#  define GC_MALLOC_ATOMIC(sz) GC_debug_malloc_atomic(sz, GC_EXTRAS)\n#  define GC_STRDUP(s) GC_debug_strdup(s, GC_EXTRAS)\n#  define GC_STRNDUP(s, sz) GC_debug_strndup(s, sz, GC_EXTRAS)\n#  define GC_MALLOC_ATOMIC_UNCOLLECTABLE(sz) \\\n    GC_debug_malloc_atomic_uncollectable(sz, GC_EXTRAS)\n#  define GC_MALLOC_UNCOLLECTABLE(sz) \\\n    GC_debug_malloc_uncollectable(sz, GC_EXTRAS)\n#  define GC_MALLOC_IGNORE_OFF_PAGE(sz) \\\n    GC_debug_malloc_ignore_off_page(sz, GC_EXTRAS)\n#  define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \\\n    GC_debug_malloc_atomic_ignore_off_page(sz, GC_EXTRAS)\n#else\n#  define GC_MALLOC_ATOMIC(sz) GC_malloc_atomic(sz)\n#  define GC_STRDUP(s) GC_strdup(s)\n#  define GC_STRNDUP(s, sz) GC_strndup(s, sz)\n#  define GC_MALLOC_ATOMIC_UNCOLLECTABLE(sz) GC_malloc_atomic_uncollectable(sz)\n#  define GC_MALLOC_UNCOLLECTABLE(sz) GC_malloc_uncollectable(sz)\n#  define GC_MALLOC_IGNORE_OFF_PAGE(sz) GC_malloc_ignore_off_page(sz)\n#  define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \\\n    GC_malloc_atomic_ignore_off_page(sz)\n#endif /* !GC_DEBUG */\n\n#ifdef GC_DEBUG\n#  define GC_FREE(p) GC_debug_free(p)\n#  define GC_REGISTER_FINALIZER(p, f, d, of, od) \\\n    GC_debug_register_finalizer(p, f, d, of, od)\n#  define GC_REGISTER_FINALIZER_IGNORE_SELF(p, f, d, of, od) \\\n    GC_debug_register_finalizer_ignore_self(p, f, d, of, od)\n#  define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \\\n    GC_debug_register_finalizer_no_order(p, f, d, of, od)\n#  define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \\\n    GC_debug_register_finalizer_unreachable(p, f, d, of, od)\n#  define GC_TOGGLEREF_ADD(p, is_strong) GC_debug_toggleref_add(p, is_strong)\n#  define GC_END_STUBBORN_CHANGE(p) GC_debug_end_stubborn_change(p)\n#  define GC_PTR_STORE_AND_DIRTY(p, q) GC_debug_ptr_store_and_dirty(p, q)\n#  define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \\\n    GC_GENERAL_REGISTER_DISAPPEARING_LINK_SAFE(link, obj)\n#  define GC_REGISTER_LONG_LINK(link, obj) \\\n    GC_REGISTER_LONG_LINK_SAFE(link, obj)\n#  define GC_REGISTER_DISPLACEMENT(n) GC_debug_register_displacement(n)\n#else\n#  define GC_FREE(p) GC_free(p)\n#  define GC_REGISTER_FINALIZER(p, f, d, of, od) \\\n    GC_register_finalizer(p, f, d, of, od)\n#  define GC_REGISTER_FINALIZER_IGNORE_SELF(p, f, d, of, od) \\\n    GC_register_finalizer_ignore_self(p, f, d, of, od)\n#  define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \\\n    GC_register_finalizer_no_order(p, f, d, of, od)\n#  define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \\\n    GC_register_finalizer_unreachable(p, f, d, of, od)\n#  define GC_TOGGLEREF_ADD(p, is_strong) GC_toggleref_add(p, is_strong)\n#  define GC_END_STUBBORN_CHANGE(p) GC_end_stubborn_change(p)\n#  define GC_PTR_STORE_AND_DIRTY(p, q) GC_ptr_store_and_dirty(p, q)\n#  define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \\\n    GC_general_register_disappearing_link(link, obj)\n#  define GC_REGISTER_LONG_LINK(link, obj) GC_register_long_link(link, obj)\n#  define GC_REGISTER_DISPLACEMENT(n) GC_register_displacement(n)\n#endif /* !GC_DEBUG */\n\n/**\n * Convenient macros for object allocation in C++ style.  The use of\n * them also reduces the chance for a misspecified size argument.\n * But, note, that they may expand to something syntactically incorrect\n * if the argument is a complicated type expression.  Note also, unlike\n * C++ new operator, these ones may return `NULL` (in case of out of\n * memory); however these macros are guaranteed never to return `NULL`\n * unless `GC_oom_fn()` returns `NULL`.\n */\n#define GC_NEW(t) ((t *)GC_MALLOC(sizeof(t)))\n#define GC_NEW_ATOMIC(t) ((t *)GC_MALLOC_ATOMIC(sizeof(t)))\n#define GC_NEW_UNCOLLECTABLE(t) ((t *)GC_MALLOC_UNCOLLECTABLE(sizeof(t)))\n\n#ifdef GC_REQUIRE_WCSDUP\n/**\n * Same as `GC_strdup` but for a `wchar_t` string.  Might be\n * unavailable on some targets (or not needed).  `wchar_t` type should\n * be defined in the platform `stddef.h` file.  The function (including\n * its debug variant) is guaranteed never to return `NULL` unless\n * `GC_oom_fn()` returns `NULL`.\n */\nGC_API GC_ATTR_MALLOC wchar_t *GC_CALL GC_wcsdup(const wchar_t *)\n    GC_ATTR_NONNULL(1);\nGC_API GC_ATTR_MALLOC wchar_t *GC_CALL GC_debug_wcsdup(const wchar_t *,\n                                                       GC_EXTRA_PARAMS)\n    GC_ATTR_NONNULL(1);\n#  ifdef GC_DEBUG\n#    define GC_WCSDUP(s) GC_debug_wcsdup(s, GC_EXTRAS)\n#  else\n#    define GC_WCSDUP(s) GC_wcsdup(s)\n#  endif\n#endif /* GC_REQUIRE_WCSDUP */\n\n/*\n * The finalization.  Some of these primitives are grossly unsafe.\n * The idea is to make them both cheap, and sufficient to build\n * a safer layer, closer to Modula-3, Java, or PCedar finalization.\n * The interface represents my conclusions from a long discussion\n * with Alan Demers, Dan Greene, Carl Hauser, Barry Hayes,\n * Christian Jacobi, and Russ Atkinson.  It is not perfect, and\n * probably nobody else agrees with it.\n */\n\ntypedef void(GC_CALLBACK *GC_finalization_proc)(void * /* `obj` */,\n                                                void * /* `client_data` */);\n\n/**\n * When `obj` is no longer accessible, invoke `(*fn)(obj, cd)`.  If `a`\n * and `b` are inaccessible, and `a` points to `b` (after disappearing\n * links have been made to disappear), then only `a` will be finalized.\n * (If this does not create any new pointers to `b`, then `b` will be\n * finalized after the next collection.)  Any finalizable object that\n * is reachable from itself by following one or more pointers will not\n * be finalized (or collected).  Thus cycles involving finalizable\n * objects should be avoided, or broken by disappearing links.  All but\n * the last finalizer registered for an object is ignored.  No-op in\n * the find-leak mode.  Finalization may be removed by passing 0 as\n * `fn`.  Finalizers are implicitly unregistered when they are enqueued\n * for finalization (i.e. become ready to be finalized).  The old\n * finalizer and client data are stored in `*ofn` and `*ocd`,\n * respectively.  (`ofn` and/or `ocd` may be `NULL`.  The allocator\n * lock is held while `*ofn` and `*ocd` are updated.  In case of error\n * (no memory to register new finalizer), `*ofn` and `*ocd` remain\n * unchanged.)  `fn` is never invoked on an accessible object, provided\n * hidden pointers are converted to real pointers only if the allocator\n * lock is held, at least in the reader mode, and such conversions are\n * not performed by finalization routines.\n * If `GC_register_finalizer()` is aborted as a result of a signal,\n * then the object may be left with no finalization, even if neither\n * the old nor new finalizer were `NULL`.  `obj` should be the starting\n * address of an object allocated by `GC_malloc` or friends. `obj` may\n * also be `NULL` or point to something outside the collector heap (in\n * this case, `fn` is ignored, `*ofn` and `*ocd` are set to `NULL`).\n * Note that any garbage collectible object referenced by `cd` will be\n * considered accessible until the finalizer is invoked.\n */\nGC_API void GC_CALL GC_register_finalizer(void * /* `obj` */,\n                                          GC_finalization_proc /* `fn` */,\n                                          void * /* `cd` */,\n                                          GC_finalization_proc * /* `ofn` */,\n                                          void ** /* `ocd` */)\n    GC_ATTR_NONNULL(1);\nGC_API void GC_CALL GC_debug_register_finalizer(\n    void * /* `obj` */, GC_finalization_proc /* `fn` */, void * /* `cd` */,\n    GC_finalization_proc * /* `ofn` */, void ** /* `ocd` */)\n    GC_ATTR_NONNULL(1);\n\n/**\n * Another variant of `GC_register_finalizer` but ignoring self-cycles,\n * i.e. pointers from a finalizable object to itself.  There is\n * a stylistic argument that this is wrong, but it is unavoidable for\n * C++, since the compiler may silently introduce these.  It is also\n * benign in that specific case.  And it helps if finalizable objects\n * are split to avoid cycles.  Note that `cd` will still be viewed as\n * accessible, even if it refers to the object itself.\n */\nGC_API void GC_CALL GC_register_finalizer_ignore_self(\n    void * /* `obj` */, GC_finalization_proc /* `fn` */, void * /* `cd` */,\n    GC_finalization_proc * /* `ofn` */, void ** /* `ocd` */)\n    GC_ATTR_NONNULL(1);\nGC_API void GC_CALL GC_debug_register_finalizer_ignore_self(\n    void * /* `obj` */, GC_finalization_proc /* `fn` */, void * /* `cd` */,\n    GC_finalization_proc * /* `ofn` */, void ** /* `ocd` */)\n    GC_ATTR_NONNULL(1);\n\n/**\n * Another variant of `GC_register_finalizer` which ignores all cycles.\n * It should probably only be used by Java implementations.  Note that\n * `cd` will still be viewed as accessible, even if it refers to the\n * object itself.\n */\nGC_API void GC_CALL GC_register_finalizer_no_order(\n    void * /* `obj` */, GC_finalization_proc /* `fn` */, void * /* `cd` */,\n    GC_finalization_proc * /* `ofn` */, void ** /* `ocd` */)\n    GC_ATTR_NONNULL(1);\nGC_API void GC_CALL GC_debug_register_finalizer_no_order(\n    void * /* `obj` */, GC_finalization_proc /* `fn` */, void * /* `cd` */,\n    GC_finalization_proc * /* `ofn` */, void ** /* `ocd` */)\n    GC_ATTR_NONNULL(1);\n\n/**\n * This is a special finalizer that is useful when an object's finalizer\n * must be run when the object is known to be no longer reachable, not even\n * from other finalizable objects.  It behaves like \"normal\" finalization,\n * except that the finalizer is not run while the object is reachable from\n * other objects specifying unordered finalization.  Effectively it allows\n * an object referenced, possibly indirectly, from an unordered finalizable\n * object to override the unordered finalization request.  This can be used\n * in combination with `GC_register_finalizer_no_order` so as to release\n * resources that must not be released while an object can still be brought\n * back to life by other finalizers.  Only works if `GC_java_finalization`\n * is set.  Probably only of interest when implementing a language that\n * requires unordered finalization (e.g. Java, C#).\n */\nGC_API void GC_CALL GC_register_finalizer_unreachable(\n    void * /* `obj` */, GC_finalization_proc /* `fn` */, void * /* `cd` */,\n    GC_finalization_proc * /* `ofn` */, void ** /* `ocd` */)\n    GC_ATTR_NONNULL(1);\nGC_API void GC_CALL GC_debug_register_finalizer_unreachable(\n    void * /* `obj` */, GC_finalization_proc /* `fn` */, void * /* `cd` */,\n    GC_finalization_proc * /* `ofn` */, void ** /* `ocd` */)\n    GC_ATTR_NONNULL(1);\n\n/** A constant indicating a failure due to lack of memory. */\n#define GC_NO_MEMORY 2\n\n/**\n * This routine may be used to break cycles between finalizable objects,\n * thus causing cyclic finalizable objects to be finalized in\n * the correct order.  The standard use involves calling\n * `GC_register_disappearing_link(&p)`, where `p` is a pointer that is\n * not followed by finalization code, and should not be considered in\n * determining finalization order.  `link` should point to a field of\n * a heap-allocated object.  `*link` will be cleared when the object is\n * found to be inaccessible.  This happens before any finalization code\n * is invoked, and before any decisions about finalization order are\n * made.  This is useful in telling the finalizer that some pointers\n * are not essential for proper finalization.  This may avoid\n * finalization cycles.  Note that the object may be resurrected by\n * another finalizer, and thus the clearing of `*link` may be visible\n * to non-finalization code.  There is an argument that an arbitrary\n * action should be allowed here, instead of just clearing a pointer.\n * But this causes problems if that action alters, or examines\n * connectivity.  Returns `GC_DUPLICATE` if given `link` was already\n * registered, `GC_SUCCESS` if registration succeeded, `GC_NO_MEMORY`\n * if it failed for lack of memory (and `GC_oom_fn` did not handle the\n * problem).  Only exists for backward compatibility, use\n * `GC_general_register_disappearing_link()` instead.\n */\nGC_API int GC_CALL GC_register_disappearing_link(void ** /* `link` */)\n    GC_ATTR_NONNULL(1);\n\n/**\n * A slight generalization of `GC_register_disappearing_link`.\n * `*link` is cleared when `obj` first becomes inaccessible.  This can be\n * used to implement weak pointers easily and safely.  Typically `link`\n * will point to a location (in a GC-allocated object or not) holding\n * a disguised pointer to `obj`.  (A pointer inside an \"atomic\" object\n * is effectively disguised.)  In this way, weak pointers are broken\n * before any object reachable from them gets finalized.  Each `link`\n * may be registered only with one `obj` value, i.e. all objects but\n * the last one (`link` registered with) are ignored.  `link` must be\n * non-`NULL` (and be properly aligned).  `obj` must be a pointer to\n * the beginning of an object allocated by `GC_malloc` or friends.\n * A link disappears when it is unregistered manually, or when `*link`\n * is cleared, or when the object containing this `link` is garbage\n * collected.  It is unsafe to explicitly deallocate the object\n * containing `link`.  Explicit deallocation of `obj` may or may not\n * cause `link` to eventually be cleared.  No-op in the find-leak mode.\n * This function can be used to implement certain types of weak pointers.\n * Note, however, this generally requires that the allocator lock is held,\n * at least in the reader mode (e.g. using `GC_call_with_reader_lock()`),\n * when the disguised pointer is accessed.  Otherwise a strong pointer\n * could be recreated between the time the collector decides to reclaim\n * the object and the link is cleared.  Returns `GC_SUCCESS` if\n * registration succeeded (a new link is registered), `GC_DUPLICATE` if\n * `link` was already registered (with some object), `GC_NO_MEMORY` if\n * registration failed for lack of memory (and `GC_oom_fn` did not handle\n * the problem), `GC_UNIMPLEMENTED` if `GC_find_leak` is true.\n */\nGC_API int GC_CALL GC_general_register_disappearing_link(\n    void ** /* `link` */, const void * /* `obj` */) GC_ATTR_NONNULL(1)\n    GC_ATTR_NONNULL(2);\n\n/**\n * Moves a `link` previously registered via\n * `GC_general_register_disappearing_link` (or\n * `GC_register_disappearing_link`).  Does not change the target object\n * of the weak reference.  Does not change `*new_link` content.  May be\n * called with `new_link` equal to `link` (to check whether `link` has\n * been registered).  Returns `GC_SUCCESS` on success, `GC_DUPLICATE`\n * if there is already another disappearing link at the new location\n * (never returned if `new_link` is equal to `link`), `GC_NOT_FOUND`\n * if no `link` is registered at the original location.\n */\nGC_API int GC_CALL GC_move_disappearing_link(void ** /* `link` */,\n                                             void ** /* `new_link` */)\n    GC_ATTR_NONNULL(2);\n\n/**\n * Undoes a registration by either `GC_register_disappearing_link()` or\n * `GC_general_register_disappearing_link()`.  Returns 0 if `link` was\n * not actually registered (otherwise returns 1).\n */\nGC_API int GC_CALL GC_unregister_disappearing_link(void ** /* `link` */);\n\n/**\n * Similar to `GC_general_register_disappearing_link` but `*link` only\n * gets cleared when `obj` becomes truly inaccessible.  An object becomes\n * truly inaccessible when it can no longer be resurrected from its\n * finalizer (e.g. by assigning itself to a pointer traceable from root).\n * This can be used to implement \"long\" weak pointers easily and safely.\n */\nGC_API int GC_CALL GC_register_long_link(void ** /* `link` */,\n                                         const void * /* `obj` */)\n    GC_ATTR_NONNULL(1) GC_ATTR_NONNULL(2);\n\n/**\n * Similar to `GC_move_disappearing_link` but for a `link` previously\n * registered via `GC_register_long_link`.\n */\nGC_API int GC_CALL GC_move_long_link(void ** /* `link` */,\n                                     void ** /* `new_link` */)\n    GC_ATTR_NONNULL(2);\n\n/**\n * Similar to `GC_unregister_disappearing_link` but for `link`\n * registration done by `GC_register_long_link()`.\n */\nGC_API int GC_CALL GC_unregister_long_link(void ** /* `link` */);\n\n/*\n * Support of \"toggle-refs\" style of external memory management without\n * hooking up to the host retain/release machinery.  The idea of\n * \"toggle-refs\" is that an external reference to an object is kept and\n * it can be either a strong or weak reference; a weak reference is\n * used when the external peer has no interest in the object, and\n * a strong otherwise.\n */\n\ntypedef enum {\n  GC_TOGGLE_REF_DROP,\n  GC_TOGGLE_REF_STRONG,\n  GC_TOGGLE_REF_WEAK\n} GC_ToggleRefStatus;\n\n/**\n * The callback is to decide (return) the new state of a given object.\n * Invoked by the collector for all objects registered for \"toggle-refs\"\n * processing.  Invoked with the allocator lock held but the world is\n * running.\n */\ntypedef GC_ToggleRefStatus(GC_CALLBACK *GC_toggleref_func)(void * /* `obj` */);\n\n/**\n * Set (register) a callback that decides the state of a given object (by,\n * probably, inspecting its native state).  The argument may be 0 (means\n * no callback).  Both the setter and the getter acquire the allocator lock\n * (in the reader mode in case of the getter).\n */\nGC_API void GC_CALL GC_set_toggleref_func(GC_toggleref_func);\nGC_API GC_toggleref_func GC_CALL GC_get_toggleref_func(void);\n\n/**\n * Register a given object for \"toggle-refs\" processing.  It will be\n * stored internally and the \"toggle-refs\" callback will be invoked on\n * the object until the callback returns `GC_TOGGLE_REF_DROP` or the\n * object is collected.  If `is_strong`, then the object is registered\n * with a strong ref, a weak one otherwise.  `obj` should be the starting\n * address of an object allocated by `GC_malloc` (`GC_debug_malloc`)\n * or friends.  Returns `GC_SUCCESS` if registration succeeded (or no\n * callback is registered yet), `GC_NO_MEMORY` if it failed for a lack\n * of memory reason.\n */\nGC_API int GC_CALL GC_toggleref_add(void * /* `obj` */, int /* `is_strong` */)\n    GC_ATTR_NONNULL(1);\nGC_API int GC_CALL GC_debug_toggleref_add(void * /* `obj` */,\n                                          int /* `is_strong` */)\n    GC_ATTR_NONNULL(1);\n\n/**\n * Finalizer callback support.  Invoked by the collector (with the allocator\n * lock held) for each unreachable object enqueued for finalization.\n * Zero means no callback.  The setter and the getter acquire the allocator\n * lock too (in the reader mode in case of the getter).\n */\ntypedef void(GC_CALLBACK *GC_await_finalize_proc)(void * /* `obj` */);\nGC_API void GC_CALL GC_set_await_finalize_proc(GC_await_finalize_proc);\nGC_API GC_await_finalize_proc GC_CALL GC_get_await_finalize_proc(void);\n\n/**\n * Returns a nonzero value (true) if `GC_invoke_finalizers()` has\n * something to do.  (Useful if finalizers can only be called from some\n * kind of \"safe state\" and getting into that safe state is expensive.)\n * Does not use any synchronization.\n */\nGC_API int GC_CALL GC_should_invoke_finalizers(void);\n\n/**\n * Set maximum amount of finalizers to run during a single invocation\n * of `GC_invoke_finalizers()`.  Zero means no limit.  Both the setter\n * and the getter acquire the allocator lock (in the reader mode in\n * case of the getter).  Note that invocation of `GC_finalize_all()`\n * resets the maximum amount value.\n */\nGC_API void GC_CALL GC_set_interrupt_finalizers(unsigned);\nGC_API unsigned GC_CALL GC_get_interrupt_finalizers(void);\n\n/**\n * Run finalizers for all objects that are ready to be finalized.\n * Return the number of finalizers that were run.  Normally this is\n * also called implicitly during some allocations.\n * If `GC_finalize_on_demand` is nonzero, it must be called explicitly.\n */\nGC_API int GC_CALL GC_invoke_finalizers(void);\n\n/*\n * Explicitly tell the collector that an object is reachable\n * at a particular program point.  This prevents the argument\n * pointer from being optimized away, even it is otherwise no\n * longer needed.  It should have no visible effect in the\n * absence of finalizers or disappearing links.  But it may be\n * needed to prevent finalizers from running while the\n * associated external resource is still in use.\n * The function is sometimes called to keep some object alive.\n */\n#if defined(__GNUC__) && !defined(__INTEL_COMPILER) \\\n    && !(defined(__APPLE__) && defined(__arm__) && defined(__TINYC__))\n/* TCC (as of v0.9.28rc) does not support asm on macOS/arm. */\n#  if defined(__CHERI_PURE_CAPABILITY__) || defined(__TINYC__)\n#    define GC_reachable_here(ptr) \\\n      __asm__ __volatile__(\" \" : : \"g\"(ptr) : \"memory\")\n#  elif defined(__e2k__)\n#    define GC_reachable_here(ptr) \\\n      __asm__ __volatile__(\" \" : : \"r\"(ptr) : \"memory\")\n#  else\n#    define GC_reachable_here(ptr) \\\n      __asm__ __volatile__(\" \" : : \"X\"(ptr) : \"memory\")\n#  endif\n#elif defined(LINT2)\n/* The definition is similar to that of `COVERT_DATAFLOW()`. */\n#  define GC_reachable_here(ptr) GC_noop1(~(GC_word)(ptr) ^ (~(GC_word)0))\n#else\n#  define GC_reachable_here(ptr) GC_noop1_ptr(GC_CAST_AWAY_CONST_PVOID(ptr))\n#endif\n\n/**\n * Make the argument of `GC_word` type appear live to compiler.\n * This could be used to prevent certain compiler false positive (FP)\n * warnings and misoptimizations.  Should be robust against the whole\n * program analysis.\n */\nGC_API void GC_CALL GC_noop1(GC_word);\n\n/** Same as `GC_noop1()` but for a pointer. */\nGC_API void GC_CALL GC_noop1_ptr(volatile void *);\n\n/**\n * `GC_set_warn_proc` can be used to redirect or filter warning messages.\n * `p` may not be a `NULL` pointer.  `msg` is a `printf` format string\n * (`arg` must match the format).  Both the setter and the getter acquire\n * the allocator lock (in the reader mode in case of the getter) to avoid\n * data race.  In GC v7.1 and before: the setter returned the value of\n * old `warn_proc`.  In GC v8.2.x and before: `msg` pointer type had\n * no `const` qualifier.\n */\ntypedef void(GC_CALLBACK *GC_warn_proc)(const char * /* `msg` */,\n                                        GC_uintptr_t /* `arg` */);\nGC_API void GC_CALL GC_set_warn_proc(GC_warn_proc /* `p` */)\n    GC_ATTR_NONNULL(1);\nGC_API GC_warn_proc GC_CALL GC_get_warn_proc(void);\n\n/**\n * `GC_ignore_warn_proc` may be used as an argument for `GC_set_warn_proc()`\n * to suppress all warnings (unless statistics printing is turned on).\n * This is recommended for production code (release).\n */\nGC_API void GC_CALLBACK GC_ignore_warn_proc(const char *, GC_uintptr_t);\n\n/**\n * Change file descriptor of the collector log.  Unavailable on some\n * targets.\n */\nGC_API void GC_CALL GC_set_log_fd(int);\n\n/**\n * This is invoked on the collector fatal aborts (just before\n * OS-dependent `abort()` or `exit(1)` is called).  Must be non-`NULL`.\n * The default one outputs `msg` to the platform `stderr` provided\n * `msg` is non-`NULL`.  `msg` is `NULL` if invoked before `exit(1)`\n * otherwise `msg` is non-`NULL` (i.e., if invoked before `abort`).\n * Both the setter and the getter acquire the allocator lock (in the reader\n * mode in case of the getter).  The setter does not change `GC_abort_func`\n * if the library has been compiled with `SMALL_CONFIG` macro defined.\n */\ntypedef void(GC_CALLBACK *GC_abort_func)(const char * /* `msg` */);\nGC_API void GC_CALL GC_set_abort_func(GC_abort_func) GC_ATTR_NONNULL(1);\nGC_API GC_abort_func GC_CALL GC_get_abort_func(void);\n\n/*\n * Clients should define `GC_EXIT_LACKS_NORETURN` macro if the platform\n * `exit()` does not have a `noreturn` attribute.\n */\n#ifdef GC_EXIT_LACKS_NORETURN\n#  define GC_OOM_ABORT_THROW_ATTRIBUTE /*< empty */\n#else\n#  define GC_OOM_ABORT_THROW_ATTRIBUTE GC_ATTR_NORETURN\n#endif\n\n/** A portable way to abort the application because of not enough memory. */\nGC_API GC_OOM_ABORT_THROW_ATTRIBUTE void GC_CALL GC_abort_on_oom(void);\n\n/*\n * The following is intended to be used by a higher level (e.g.\n * Java-like) finalization facility.  It is expected that finalization\n * code will arrange for hidden pointers to disappear.  Otherwise,\n * objects can be accessed after they have been collected.  Should not\n * be used in the find-leak mode.\n * Note that putting pointers in atomic objects or in non-pointer slots\n * of \"typed\" objects is equivalent to disguising them in this way, and\n * may have other advantages.  Note also that some code relies on that\n * the least significant bit of the argument (including for `NULL`) is\n * inverted by these primitives.\n * Important: converting a hidden pointer to a real pointer requires\n * verifying that the object still exists; this should involve\n * acquiring the allocator lock, at least in the reader mode, to avoid\n * a race with the collector (e.g., one thread might fetch hidden link\n * value, while another thread might collect the relevant object and\n * reuse the free space for another object).\n */\ntypedef GC_uintptr_t GC_hidden_pointer;\n#define GC_HIDE_POINTER(p) (~(GC_hidden_pointer)(p))\n#define GC_REVEAL_POINTER(p) ((void *)GC_HIDE_POINTER(p))\n\n#if defined(I_HIDE_POINTERS) || defined(GC_I_HIDE_POINTERS)\n/*\n * This exists only for compatibility (the GC-prefixed symbols are\n * preferred for new code).\n */\n#  define HIDE_POINTER(p) GC_HIDE_POINTER(p)\n#  define REVEAL_POINTER(p) GC_REVEAL_POINTER(p)\n#endif\n\n/*\n * A slightly modified variant of `GC_HIDE_POINTER` which guarantees\n * not to \"hide\" `NULL` (i.e. passing zero argument gives zero result).\n * This might be useful in conjunction with `GC_register_disappearing_link`.\n * Note that unlike `GC_HIDE_POINTER`, inversion of the least significant\n * bit of the argument is not guaranteed.\n */\n#if defined(__CHERI_PURE_CAPABILITY__)\n#  define GC_HIDE_NZ_POINTER(p) ((GC_hidden_pointer)(-(intptr_t)(p)))\n#else\n#  define GC_HIDE_NZ_POINTER(p) ((GC_hidden_pointer)(-(GC_signed_word)(p)))\n#endif\n#define GC_REVEAL_NZ_POINTER(p) ((void *)GC_HIDE_NZ_POINTER(p))\n\n/*\n * The routines to acquire/release the GC (allocator) lock.\n * The lock is not reentrant.  `GC_alloc_unlock()` should not be called\n * unless the allocator lock is acquired by the current thread.\n */\n#ifdef GC_THREADS\nGC_API void GC_CALL GC_alloc_lock(void);\nGC_API void GC_CALL GC_alloc_unlock(void);\n#else\n/* No need for real locking if the client is single-threaded. */\n#  define GC_alloc_lock() (void)0\n#  define GC_alloc_unlock() (void)0\n#endif /* !GC_THREADS */\n\ntypedef void *(GC_CALLBACK *GC_fn_type)(void * /* `client_data` */);\n\n/**\n * Execute given function with the allocator lock held (in the exclusive\n * mode).\n */\nGC_API void *GC_CALL GC_call_with_alloc_lock(GC_fn_type /* `fn` */,\n                                             void * /* `client_data` */)\n    GC_ATTR_NONNULL(1);\n\n/*\n * Execute given function with the allocator lock held in the reader\n * (shared) mode.  The 3rd argument (`release`), if nonzero, indicates\n * that `fn` might write some data that should be made visible to the\n * thread which acquires the allocator lock in the exclusive mode later.\n */\n#ifdef GC_THREADS\nGC_API void *GC_CALL GC_call_with_reader_lock(GC_fn_type /* `fn` */,\n                                              void * /* `client_data` */,\n                                              int /* `release` */)\n    GC_ATTR_NONNULL(1);\n#else\n#  define GC_call_with_reader_lock(fn, cd, r) ((void)(r), (fn)(cd))\n#endif\n\n/*\n * These routines are intended to explicitly notify the collector\n * of new threads.  Often this is unnecessary because thread creation\n * is implicitly intercepted by the collector, using header-file defines,\n * or linker-based interception.  In the long run, the intent is to\n * always make redundant registration safe.  In the short run, this is\n * being implemented a platform at a time.  The interface is complicated\n * by the fact that we probably will not ever be able to automatically\n * determine the stack bottom for thread stacks on all platforms.\n */\n\n/**\n * Structure representing the bottom (cold end) of a thread stack.\n * On most platforms this contains just a single address.\n */\nstruct GC_stack_base {\n  /* The bottom of the general-purpose stack. */\n  void *mem_base;\n#if defined(__e2k__) || defined(__ia64) || defined(__ia64__) \\\n    || defined(_M_IA64)\n  /* The bottom of the register stack. */\n  void *reg_base;\n#endif\n};\n\ntypedef void *(GC_CALLBACK *GC_stack_base_func)(\n    struct GC_stack_base * /* `sb` */, void * /* `arg` */);\n\n/**\n * Call a function with a stack base structure corresponding to somewhere in\n * the `GC_call_with_stack_base` frame.  This often can be used to provide\n * a sufficiently accurate stack bottom.  And we implement it everywhere.\n */\nGC_API void *GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */,\n                                             void * /* arg */)\n    GC_ATTR_NONNULL(1);\n\n#define GC_SUCCESS 0\n\n/** Means was already registered. */\n#define GC_DUPLICATE 1\n\n/* Deprecated.  No thread support in the collector. */\n#define GC_NO_THREADS 2\n\n/** Not yet implemented on this platform. */\n#define GC_UNIMPLEMENTED 3\n\n/** Requested `link` not found (returned by `GC_move_disappearing_link()`). */\n#define GC_NOT_FOUND 4\n\n/**\n * Start the parallel marker threads, if available.  Useful, e.g.,\n * after POSIX `fork` in a child process (provided not followed by\n * `exec()`) or in single-threaded clients (provided it is OK for the\n * client to perform marking in parallel).  Acquires the allocator lock\n * to avoid a race.\n */\nGC_API void GC_CALL GC_start_mark_threads(void);\n\n#if defined(GC_DARWIN_THREADS) || defined(GC_WIN32_THREADS)\n/**\n * Use implicit thread registration and processing (via Win32 `DllMain`\n * or Darwin `task_threads`).  Deprecated.  Must be called before\n * `GC_INIT()` and other GC routines (or, at least, before going\n * multi-threaded).  Performs the collector initialization.  Should be\n * avoided if `GC_pthread_create`, `GC_beginthreadex` (or `GC_CreateThread`),\n * or `GC_register_my_thread` could be used instead.  Disables parallelized\n * garbage collection on Win32.\n */\nGC_API void GC_CALL GC_use_threads_discovery(void);\n#endif\n\n#ifdef GC_THREADS\n/**\n * Suggest the collector to use the specific signal to suspend threads.\n * Has no effect after the collector initialization and on non-POSIX systems.\n */\nGC_API void GC_CALL GC_set_suspend_signal(int);\n\n/**\n * Return the signal number (which is a constant after the collector\n * initialization) used by the collector to suspend threads on POSIX systems.\n * Return -1 otherwise.\n */\nGC_API int GC_CALL GC_get_suspend_signal(void);\n\n/**\n * Suggest the collector to use the specific signal to resume threads.\n * Has no effect after the collector initialization and on non-POSIX systems.\n * The same signal might be used for threads suspension and restart.\n */\nGC_API void GC_CALL GC_set_thr_restart_signal(int);\n\n/**\n * Return the signal number (which is a constant after the collector\n * initialization) used by the collector to restart (resume) threads on\n * POSIX systems.  Return -1 otherwise.\n */\nGC_API int GC_CALL GC_get_thr_restart_signal(void);\n\n/**\n * Explicitly enable `GC_register_my_thread()` invocation.\n * Done implicitly if a GC thread-creation function is called\n * (or implicit thread registration is activated, or the collector is\n * compiled with `GC_ALWAYS_MULTITHREADED` macro defined).  Otherwise,\n * it must be called from the main (or any previously registered)\n * thread between the collector initialization and the first explicit\n * registering of a thread (it should be called as late as possible).\n * Includes a `GC_start_mark_threads()` call.\n */\nGC_API void GC_CALL GC_allow_register_threads(void);\n\n/**\n * Register the current thread, with the indicated stack bottom, as\n * a new thread whose stack(s) should be traced by the collector.\n * If it is not implicitly called by the collector, this must be called\n * before a thread can allocate garbage-collected memory, or assign\n * pointers to the garbage-collected heap.  Once registered, a thread\n * will be stopped during garbage collections.  This call must be\n * previously enabled (see `GC_allow_register_threads`).  This should\n * never be called from the main thread, where it is always done\n * implicitly.  This is normally done implicitly if `GC_` functions are\n * called to create the thread, e.g. by include `gc.h` file (which\n * redefines some system functions) before calling the system thread\n * creation function.  Nonetheless, thread cleanup routines (e.g.,\n * `pthreads` key destructor) typically require manual thread\n * registering (and unregistering) if pointers to GC-allocated objects\n * are manipulated inside.  It is also always done implicitly on some\n * platforms if `GC_use_threads_discovery()` is called at start-up.\n * Except for the latter case, the explicit call is normally required\n * for threads created by third-party libraries.  A manually registered\n * thread requires manual unregistering.  Returns `GC_SUCCESS` on\n * success, `GC_DUPLICATE` if already registered.\n */\nGC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *)\n    GC_ATTR_NONNULL(1);\n\n/**\n * Return 1 (true) if the calling (current) thread is registered with the\n * garbage collector, 0 otherwise.  Acquires the allocator lock in the\n * reader mode.  If the thread is finished (e.g. running in a destructor\n * and not registered manually again), then it is considered as not\n * registered.\n */\nGC_API int GC_CALL GC_thread_is_registered(void);\n\n/**\n * Notify the collector about the stack and the alt-stack of the current\n * thread.  `normstack` and `normstack_size` are used to determine the\n * \"normal\" stack boundaries when a thread is suspended while it is on\n * an alt-stack.  Acquires the allocator lock in the reader mode.\n */\nGC_API void GC_CALL GC_register_altstack(void * /* `normstack` */,\n                                         size_t /* `normstack_size` */,\n                                         void * /* `altstack` */,\n                                         size_t /* `altstack_size` */);\n\n/**\n * Unregister the current thread.  Only an explicitly registered thread\n * (i.e. for which `GC_register_my_thread()` returns `GC_SUCCESS`)\n * is allowed (and required) to call this function.  (As a special\n * exception, it is also allowed to once unregister the main thread.)\n * The thread may no longer allocate garbage-collected memory or\n * manipulate pointers to the garbage-collected heap after making this\n * call.  Specifically, if it wants to return or otherwise communicate\n * a pointer to the garbage-collected heap to another thread, it must\n * do this before calling `GC_unregister_my_thread`, most probably by\n * saving it in a global data structure.  Must not be called inside\n * a GC callback function (except for `GC_call_with_stack_base()` one).\n * Always returns `GC_SUCCESS`.\n */\nGC_API int GC_CALL GC_unregister_my_thread(void);\n\n/** Stop/start the world explicitly.  Not recommended for general use. */\nGC_API void GC_CALL GC_stop_world_external(void);\nGC_API void GC_CALL GC_start_world_external(void);\n\n/**\n * Provide a verifier/modifier of the stack pointer when pushing the\n * thread stacks.  This might be useful for a crude integration\n * with certain coroutine implementations.  `*sp_ptr` is the captured\n * stack pointer of the suspended thread with `pthread_id` (the latter\n * is actually of `pthread_t` type).  The functionality is unsupported\n * on some targets (the getter always returns 0 in such a case).\n * Both the setter and the getter acquire the allocator lock (in the reader\n * mode in case of the getter).  The client function (if provided) is called\n * with the allocator lock held and, might be, with the world stopped.\n */\ntypedef void(GC_CALLBACK *GC_sp_corrector_proc)(void ** /* `sp_ptr` */,\n                                                void * /* `pthread_id` */);\nGC_API void GC_CALL GC_set_sp_corrector(GC_sp_corrector_proc);\nGC_API GC_sp_corrector_proc GC_CALL GC_get_sp_corrector(void);\n#endif /* GC_THREADS */\n\n/**\n * Wrapper for functions that are likely to block (or, at least, do not\n * allocate garbage-collected memory and/or manipulate pointers to the\n * garbage-collected heap) for an appreciable length of time.\n * While `fn` is running, the collector is said to be in the \"inactive\"\n * state for the current thread (this means that the thread is not\n * suspended and the thread's stack frames \"belonging\" to the functions\n * in the \"inactive\" state are not scanned during garbage collections).\n * It is assumed that the collector is already initialized and the\n * current thread is registered.  It is allowed for `fn` to call\n * `GC_call_with_gc_active()` (even recursively), thus temporarily\n * toggling the collector's state back to \"active\".  The latter\n * technique might be used to make stack scanning more precise (i.e.\n * scan only stack frames of functions that allocate garbage-collected\n * memory and/or manipulate pointers to the garbage-collected heap).\n * Acquires the allocator lock in the reader mode (but `fn` is called\n * not holding it).\n */\nGC_API void *GC_CALL GC_do_blocking(GC_fn_type /* `fn` */,\n                                    void * /* `client_data` */)\n    GC_ATTR_NONNULL(1);\n\n/**\n * Call a function switching to the \"active\" state of the collector for\n * the current thread (i.e. the user function is temporarily back\n * allowed to call any GC function and/or manipulate pointers to the\n * garbage-collected heap).  `GC_call_with_gc_active()` has the\n * functionality opposite to `GC_do_blocking()` one.  It is assumed\n * that the collector is already initialized and the current thread is\n * registered.  `fn` may toggle the collector thread's state\n * temporarily to \"inactive\" one by using `GC_do_blocking()`.\n * `GC_call_with_gc_active()` often can be used to provide\n * a sufficiently accurate stack bottom.  Acquires the allocator lock\n * in the reader mode (but `fn` is called not holding it).\n */\nGC_API void *GC_CALL GC_call_with_gc_active(GC_fn_type /* `fn` */,\n                                            void * /* `client_data` */)\n    GC_ATTR_NONNULL(1);\n\n/**\n * Attempt to fill in the `GC_stack_base` structure with the stack\n * bottom for this thread.  This appears to be required to implement\n * anything like the JNI (Java Native Interface) `AttachCurrentThread`\n * in an environment in which new threads are not automatically registered\n * with the collector.  It is also unfortunately hard to implement well\n * on many platforms.  Returns `GC_SUCCESS` or `GC_UNIMPLEMENTED`.\n * Acquires the allocator lock on some platforms.\n */\nGC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *)\n    GC_ATTR_NONNULL(1);\n\n/**\n * Fill in the GC_stack_base structure with the cold end (bottom) of\n * the stack of the current thread (or coroutine).\n * Unlike `GC_get_stack_base`, it retrieves the value stored in the\n * collector (which is initially set by the collector upon the thread\n * is started or registered manually but it could be later updated by\n * client using `GC_set_stackbottom`).  Returns the GC-internal\n * non-`NULL` handle of the thread which could be passed to\n * `GC_set_stackbottom()` later.  It is assumed that the collector is\n * already initialized and the thread is registered.  Acquires the\n * allocator lock in the reader mode.\n */\nGC_API void *GC_CALL GC_get_my_stackbottom(struct GC_stack_base *)\n    GC_ATTR_NONNULL(1);\n\n/**\n * Set the cool end of the user (coroutine) stack of the specified thread.\n * The GC thread handle (`gc_thread_handle`) is either the one returned by\n * `GC_get_my_stackbottom()` or `NULL` (the latter designates the current\n * thread).  The caller should hold the allocator lock (e.g. using\n * `GC_call_with_reader_lock()` with `release` argument set to 1), the\n * reader mode should be enough typically, at least for the collector\n * itself (the client is responsible to avoid data race between this and\n * `GC_get_my_stackbottom` functions if the client acquires the allocator\n * lock in the reader mode).  Also, the function could be used for setting\n * `GC_stackbottom` value (the bottom of the primordial thread) before the\n * collector is initialized (the allocator lock is not needed to be\n * acquired at all in this case).\n */\nGC_API void GC_CALL GC_set_stackbottom(void * /* `gc_thread_handle` */,\n                                       const struct GC_stack_base *)\n    GC_ATTR_NONNULL(2);\n\n/*\n * The following routines are primarily intended for use with a preprocessor\n * which inserts calls to check C pointer arithmetic.  They indicate failure\n * by invoking the corresponding print procedure (`GC_same_obj_print_proc`,\n * `GC_is_valid_displacement_print_proc` or `GC_is_visible_print_proc`).\n */\n\n/**\n * Checked pointer pre- and post-increment operations.  Note that the second\n * argument (`how_much`) is in units of bytes, not multiples of the object\n * size.  This should either be invoked from a macro, or the call should be\n * automatically generated.\n */\nGC_API void *GC_CALL GC_pre_incr(void **, ptrdiff_t /* `how_much` */)\n    GC_ATTR_NONNULL(1);\nGC_API void *GC_CALL GC_post_incr(void **, ptrdiff_t /* `how_much` */)\n    GC_ATTR_NONNULL(1);\n\n/**\n * Check that `p` and `q` point to the same object.\n * `GC_same_obj_print_proc` is called (fail by default) if they do not.\n * Succeeds, as well, if neither `p` nor `q` points to the heap.\n * (May succeed also if both `p` and `q` point to between heap objects.)\n * Returns the first argument (`p`).  (The returned value may be hard to\n * use due to typing issues.  But if we had a suitable preprocessor...)\n * We assume this is somewhat performance critical (it should not be\n * called by production code, of course, but it can easily make even\n * debugging intolerably slow).\n */\nGC_API void *GC_CALL GC_same_obj(void * /* `p` */, void * /* `q` */);\n\n/**\n * Check that `p` is visible to the collector as a possibly pointer\n * containing location.  If it is not, call `GC_is_visible_print_proc`\n * (fail by default).  Always returns the argument (`p`).\n * May erroneously succeed in hard cases.  The function is intended for\n * debugging use with untyped allocations.  (The idea is that it should\n * be possible, though slow, to add such a call to all indirect pointer\n * stores.)  Currently almost useless for the multi-threaded worlds.\n */\nGC_API void *GC_CALL GC_is_visible(void * /* p */);\n\n/**\n * Check that if `p` is a pointer to a heap page, then it points to\n * a valid displacement within a heap object.  If it is not, invoke\n * `GC_is_valid_displacement_print_proc` (fail by default).\n * Always returns the argument (`p`).  Uninteresting in the\n * all-interior-pointers mode.  Note that we do not acquire the\n * allocator lock, since nothing relevant about the header should\n * change while we have a valid object pointer to the block.\n */\nGC_API void *GC_CALL GC_is_valid_displacement(void * /* `p` */);\n\n/**\n * Explicitly dump the collector state.  This is most often called from\n * the debugger, or by setting the `GC_DUMP_REGULARLY` environment\n * variable, but it may be useful to call it from client code during\n * debugging.  The current collection number is printed in the header\n * of the dump.  Acquires the allocator lock in the reader mode to\n * avoid data race.  Defined only if the library has been compiled\n * without `NO_DEBUGGING` macro defined.\n */\nGC_API void GC_CALL GC_dump(void);\n\n/**\n * The same as `GC_dump` but allows to specify the name of dump and\n * does not acquire the allocator lock.  If `name` is non-`NULL`, it is\n * printed to help identifying individual dumps.  Otherwise the current\n * collection number is used as the name.  Defined only if the library\n * has been compiled without `NO_DEBUGGING` macro defined.\n */\nGC_API void GC_CALL GC_dump_named(const char * /* `name` */);\n\n/**\n * Dump information about each block of every GC memory section.\n * Defined only if the library has been compiled without `NO_DEBUGGING`\n * macro defined.\n */\nGC_API void GC_CALL GC_dump_regions(void);\n\n/**\n * Dump information about every registered disappearing link and\n * finalizable object.  Defined only if the library has been compiled\n * without `NO_DEBUGGING` macro defined.\n */\nGC_API void GC_CALL GC_dump_finalization(void);\n\ntypedef enum {\n  GC_HEAP_SECTION_TYPE_FREE,\n  GC_HEAP_SECTION_TYPE_PADDING,\n  GC_HEAP_SECTION_TYPE_USED,\n  GC_HEAP_SECTION_TYPE_UNMAPPED,\n  GC_HEAP_SECTION_TYPE_FORWARDING,\n  GC_HEAP_SECTION_TYPE_WHOLE_SECT\n} GC_heap_section_type;\n\ntypedef void(GC_CALLBACK *GC_heap_section_proc)(\n    void * /* `start` */, void * /* `finish` */,\n    GC_heap_section_type /* `type` */, void * /* `client_data` */);\n\n/**\n * Apply `fn` to each heap section and each heap block inside.\n * Similar to `GC_apply_to_all_blocks()`.  Assumes the allocator lock\n * is held at least in the reader mode, but no assertion about it\n * by design.  Defined only if the library has been compiled without\n * `NO_DEBUGGING` macro defined.\n */\nGC_API void GC_CALL GC_foreach_heap_section_inner(GC_heap_section_proc fn,\n                                                  void *client_data)\n    GC_ATTR_NONNULL(1);\n\n/*\n * Safer, but slow, pointer addition.  Probably useful mainly with\n * a preprocessor.  Useful only for heap pointers.  Only the macros\n * without trailing digits are meant to be used by clients.  These are\n * designed to model the available C pointer arithmetic expressions.\n * Even then, these are probably more useful as documentation than as\n * a part of the API.  Note that `GC_PTR_ADD()` evaluates the first\n * argument more than once.\n */\n#if defined(GC_DEBUG) && (defined(__GNUC__) || defined(__clang__))\n#  define GC_PTR_ADD3(x, n, type_of_result) \\\n    ((type_of_result)GC_same_obj((x) + (n), (x)))\n#  define GC_PRE_INCR3(x, n, type_of_result) \\\n    ((type_of_result)GC_pre_incr((void **)&(x), (n) * sizeof(*(x))))\n#  define GC_POST_INCR3(x, n, type_of_result) \\\n    ((type_of_result)GC_post_incr((void **)&(x), (n) * sizeof(*(x))))\n#  define GC_PTR_ADD(x, n) GC_PTR_ADD3(x, n, __typeof__(x))\n#  define GC_PRE_INCR(x, n) GC_PRE_INCR3(x, n, __typeof__(x))\n#  define GC_POST_INCR(x) GC_POST_INCR3(x, 1, __typeof__(x))\n#  define GC_POST_DECR(x) GC_POST_INCR3(x, -1, __typeof__(x))\n#else /* !GC_DEBUG || !__GNUC__ */\n/*\n * We cannot do this right without `typeof`, which ANSI decided was not\n * sufficiently useful.  Without it we resort to the non-debug variant.\n */\n/* TODO: This should eventually support C++0x `decltype`. */\n#  define GC_PTR_ADD(x, n) ((x) + (n))\n#  define GC_PRE_INCR(x, n) ((x) += (n))\n#  define GC_POST_INCR(x) ((x)++)\n#  define GC_POST_DECR(x) ((x)--)\n#endif /* !GC_DEBUG || !__GNUC__ */\n\n/* Safer assignment of a pointer to a non-stack location. */\n#ifdef GC_DEBUG\n#  define GC_PTR_STORE(p, q)              \\\n    (*(void **)GC_is_visible((void *)(p)) \\\n     = GC_is_valid_displacement((void *)(q)))\n#else\n#  define GC_PTR_STORE(p, q) (*(void **)(p) = (void *)(q))\n#endif\n\n/*\n * `GC_PTR_STORE_AND_DIRTY(p, q)` is equivalent to `GC_PTR_STORE(p, q)`\n * followed by `GC_END_STUBBORN_CHANGE(p)` and `GC_reachable_here(q)`\n * (assuming `p` and `q` do not have side effects).\n */\nGC_API void GC_CALL GC_ptr_store_and_dirty(void * /* `p` */,\n                                           const void * /* `q` */);\nGC_API void GC_CALL GC_debug_ptr_store_and_dirty(void * /* `p` */,\n                                                 const void * /* `q` */);\n\n#ifdef GC_PTHREADS\n/*\n * For `pthreads` support, we generally need to intercept a number of\n * thread library calls.  We do that here by macro defining them.\n */\n#  ifdef __cplusplus\n} /* extern \"C\" */\n#  endif\n#  include \"gc_pthread_redirects.h\"\n#  ifdef __cplusplus\nextern \"C\" {\n#  endif\n#endif\n\n/**\n * This returns a list of objects with the link pointer located at the\n * beginning of each object.  The use of such list can greatly reduce\n * lock contention problems, since the allocator lock can be acquired\n * and released many fewer times.  Note that there is no \"atomic\"\n * variant of this function, as otherwise the links would not be seen\n * by the collector.  If the argument (`lb`) is zero, then it is\n * treated as 1.  The function is guaranteed never to return `NULL`\n * unless `GC_oom_fn()` returns `NULL`.\n */\nGC_API GC_ATTR_MALLOC void *GC_CALL GC_malloc_many(size_t /* `lb` */);\n\n/* Retrieve the next element in the list returned by `GC_malloc_many()`. */\n#define GC_NEXT(p) (*(void **)(p))\n\n/**\n * A filter function to control the scanning of dynamic libraries.\n * If implemented, called by the collector before registering a dynamic\n * library (discovered by the collector) section as a static data root\n * (called only as a last reason not to register).  The filename\n * (`dlpi_name`) of the library, the address and the length of the\n * memory region (section) are passed.  This routine should return\n * a nonzero value if that region should be scanned.  Always called\n * with the allocator lock held.  Depending on the platform, might be\n * called with the world stopped.\n */\ntypedef int(GC_CALLBACK *GC_has_static_roots_func)(\n    const char * /* `dlpi_name` */, void * /* `section_start` */,\n    size_t /* `section_size` */);\n\n/**\n * Register a new callback (a user-supplied filter) to control the\n * scanning of dynamic libraries.  Replaces any previously registered\n * callback.  May be 0 (means no filtering).  May be unused on some\n * platforms (if the filtering is unimplemented or inappropriate).\n */\nGC_API void\n    GC_CALL GC_register_has_static_roots_callback(GC_has_static_roots_func);\n\n#if !defined(CPPCHECK) && !defined(GC_WINDOWS_H_INCLUDED) && defined(WINAPI)\n/* Platform `windows.h` file is included before `gc.h` file. */\n#  define GC_WINDOWS_H_INCLUDED\n#endif\n\n#if defined(GC_WIN32_THREADS)                      \\\n    && (!defined(GC_PTHREADS) || defined(GC_BUILD) \\\n        || defined(GC_WINDOWS_H_INCLUDED))\n/*\n * Note: for Cygwin and pthreads-win32, this is skipped unless platform\n * `windows.h` file is included before `gc.h` file.\n */\n\n#  if (!defined(GC_NO_THREAD_DECLS) || defined(GC_BUILD)) \\\n      && !defined(GC_DONT_INCL_WINDOWS_H)\n\n/*\n * Including platform `windows.h` file in an `extern \"C\"` context\n * no longer works.\n */\n#    ifdef __cplusplus\n}\n#    endif\n\n#    if !defined(_WIN32_WCE) && !defined(__CEGCC__)\n#      include <process.h> /* for `_beginthreadex`, `_endthreadex` */\n#    endif\n\n#    if defined(GC_BUILD) || !defined(GC_DONT_INCLUDE_WINDOWS_H)\n#      include <windows.h>\n#      define GC_WINDOWS_H_INCLUDED\n#    endif\n\n#    ifdef __cplusplus\nextern \"C\" {\n#    endif\n\n#    ifdef GC_UNDERSCORE_STDCALL\n/*\n * Explicitly prefix exported/imported WINAPI (`__stdcall`) symbols\n * with \"_\" (underscore).  Might be useful if MinGW/x86 is used.\n */\n#      define GC_CreateThread _GC_CreateThread\n#      define GC_ExitThread _GC_ExitThread\n#    endif\n\n#    ifndef DECLSPEC_NORETURN\n/* Typically defined in platform `winnt.h` file. */\n#      ifdef GC_WINDOWS_H_INCLUDED\n#        define DECLSPEC_NORETURN /*< empty */\n#      else\n#        define DECLSPEC_NORETURN GC_ATTR_NORETURN\n#      endif\n#    endif\n\n#    ifdef _WIN64\n#      define GC_WIN32_SIZE_T GC_uintptr_t\n#    elif defined(GC_WINDOWS_H_INCLUDED)\n#      define GC_WIN32_SIZE_T DWORD\n#    else\n#      define GC_WIN32_SIZE_T unsigned long\n#    endif\n\n#    ifdef GC_INSIDE_DLL\n/* Export GC `DllMain()` to be invoked from the client `DllMain`. */\n#      ifdef GC_UNDERSCORE_STDCALL\n#        define GC_DllMain _GC_DllMain\n#      endif\n#      ifdef GC_WINDOWS_H_INCLUDED\nGC_API BOOL WINAPI GC_DllMain(HINSTANCE /* `inst` */, ULONG /* `reason` */,\n                              LPVOID /* `reserved` */);\n#      else\nGC_API int __stdcall GC_DllMain(void *, unsigned long, void *);\n#      endif\n#    endif /* GC_INSIDE_DLL */\n\n/*\n * All threads must be created using `GC_CreateThread` or\n * `GC_beginthreadex`, or must explicitly call `GC_register_my_thread`\n * (and call `GC_unregister_my_thread` before thread termination), so\n * that they will be recorded in the thread table.  For backward\n * compatibility, it is possible to build the collector with `GC_DLL`\n * macro defined, and to call `GC_use_threads_discovery()`.\n * This implicitly registers all created threads, but appears to be\n * less robust.  Currently the collector expects all threads to fall\n * through and terminate normally, or call `GC_endthreadex` or\n * `GC_ExitThread`, so that the thread is properly unregistered.\n */\n#    ifdef GC_WINDOWS_H_INCLUDED\nGC_API HANDLE WINAPI GC_CreateThread(\n    LPSECURITY_ATTRIBUTES /* `lpThreadAttributes` */,\n    GC_WIN32_SIZE_T /* `dwStackSize` */,\n    LPTHREAD_START_ROUTINE /* `lpStartAddress` */, LPVOID /* `lpParameter` */,\n    DWORD /* `dwCreationFlags` */, LPDWORD /* `lpThreadId` */);\n\nGC_API DECLSPEC_NORETURN void WINAPI GC_ExitThread(DWORD /* `dwExitCode` */);\n#    else\nstruct _SECURITY_ATTRIBUTES;\nGC_API void *__stdcall GC_CreateThread(struct _SECURITY_ATTRIBUTES *,\n                                       GC_WIN32_SIZE_T,\n                                       unsigned long(__stdcall *)(void *),\n                                       void *, unsigned long, unsigned long *);\nGC_API DECLSPEC_NORETURN void __stdcall GC_ExitThread(unsigned long);\n#    endif\n\n#    if !defined(_WIN32_WCE) && !defined(__CEGCC__)\nGC_API GC_uintptr_t GC_CALL GC_beginthreadex(void * /* `security` */,\n                                             unsigned /* `stack_size` */,\n                                             unsigned(__stdcall *)(void *),\n                                             void * /* `arglist` */,\n                                             unsigned /* `initflag` */,\n                                             unsigned * /* `thrdaddr` */);\n\n/*\n * Note: `_endthreadex()` is not currently marked as `noreturn` in VC++\n * and MinGW headers, so we do not mark it neither.\n */\nGC_API void GC_CALL GC_endthreadex(unsigned /* `retval` */);\n#    endif /* !_WIN32_WCE */\n\n#  endif /* !GC_NO_THREAD_DECLS */\n\n#  ifdef GC_WINMAIN_REDIRECT\n/*\n * The collector provides the real `WinMain()`, which starts a new thread\n * to call `GC_WinMain()` after initializing the collector.\n */\n#    define WinMain GC_WinMain\n#  endif\n\n/* For compatibility only. */\n#  define GC_use_DllMain GC_use_threads_discovery\n\n#  ifndef GC_NO_THREAD_REDIRECTS\n#    define CreateThread GC_CreateThread\n#    define ExitThread GC_ExitThread\n#    undef _beginthreadex\n#    define _beginthreadex GC_beginthreadex\n#    undef _endthreadex\n#    define _endthreadex GC_endthreadex\n/* `#define _beginthread { \"Use _beginthreadex instead of _beginthread\" }` */\n#  endif /* !GC_NO_THREAD_REDIRECTS */\n\n#endif /* GC_WIN32_THREADS */\n\n/**\n * The setter and the getter for switching \"unmap as much as possible\"\n * mode on(1) and off(0).  Has no effect unless unmapping is turned on.\n * Initial value is controlled by `GC_FORCE_UNMAP_ON_GCOLLECT` macro.\n * The setter and the getter are unsynchronized.\n */\nGC_API void GC_CALL GC_set_force_unmap_on_gcollect(int);\nGC_API int GC_CALL GC_get_force_unmap_on_gcollect(void);\n\n/*\n * Fully portable code should call `GC_INIT()` from the main program\n * before making any other `GC_` calls.  On most platforms this is\n * a no-op and the collector self-initializes.  But a number of\n * platforms make that too hard.  A `GC_INIT()` call is required if the\n * collector is built with `THREAD_LOCAL_ALLOC` macro defined and the\n * initial allocation call is not to `GC_malloc` or `GC_malloc_atomic`.\n */\n\n#if defined(__CYGWIN32__) || defined(__CYGWIN__)\n/*\n * Similarly gnu-win32 DLLs need explicit initialization from the\n * main program, as does AIX.\n */\n#  ifdef __x86_64__\n/* Cygwin/x86_64 does not add leading underscore to symbols anymore. */\nextern int __data_start__[], __data_end__[];\nextern int __bss_start__[], __bss_end__[];\n#    define GC_DATASTART                                         \\\n      (GC_ADDR_LT((char *)__data_start__, (char *)__bss_start__) \\\n           ? (void *)__data_start__                              \\\n           : (void *)__bss_start__)\n#    define GC_DATAEND                                       \\\n      (GC_ADDR_LT((char *)__bss_end__, (char *)__data_end__) \\\n           ? (void *)__data_end__                            \\\n           : (void *)__bss_end__)\n#  else\nextern int _data_start__[], _data_end__[], _bss_start__[], _bss_end__[];\n#    define GC_DATASTART                                       \\\n      (GC_ADDR_LT((char *)_data_start__, (char *)_bss_start__) \\\n           ? (void *)_data_start__                             \\\n           : (void *)_bss_start__)\n#    define GC_DATAEND                                     \\\n      (GC_ADDR_LT((char *)_bss_end__, (char *)_data_end__) \\\n           ? (void *)_data_end__                           \\\n           : (void *)_bss_end__)\n#  endif /* !__x86_64__ */\n/*\n * This is required at least if the collector is in a DLL; and does not\n * hurt.\n */\n#  define GC_INIT_CONF_ROOTS                \\\n    GC_add_roots(GC_DATASTART, GC_DATAEND); \\\n    GC_gcollect() /*< for black-listing */\n#elif defined(_AIX)\nextern int _data[], _end[];\n#  define GC_DATASTART ((void *)_data)\n#  define GC_DATAEND ((void *)_end)\n#  define GC_INIT_CONF_ROOTS GC_add_roots(GC_DATASTART, GC_DATAEND)\n#elif (defined(HOST_ANDROID) || defined(__ANDROID__)) \\\n    && defined(IGNORE_DYNAMIC_LOADING)\n/*\n * This is ugly but seems the only way to register data roots of the\n * client shared library if the GC dynamic loading support is off.\n */\n#  pragma weak __dso_handle\nextern int __dso_handle[];\nGC_API void *GC_CALL GC_find_limit(void * /* `start` */, int /* `up` */);\n#  define GC_INIT_CONF_ROOTS                                               \\\n    (void)(__dso_handle != 0                                               \\\n               ? (GC_add_roots(__dso_handle,                               \\\n                               GC_find_limit(__dso_handle, 1 /* `up` */)), \\\n                  0)                                                       \\\n               : 0)\n#else\n#  define GC_INIT_CONF_ROOTS (void)0\n#endif\n\n#ifdef GC_DONT_EXPAND\n/* Set `GC_dont_expand` to true at start-up. */\n#  define GC_INIT_CONF_DONT_EXPAND GC_set_dont_expand(1)\n#else\n#  define GC_INIT_CONF_DONT_EXPAND (void)0\n#endif\n\n#ifdef GC_FORCE_UNMAP_ON_GCOLLECT\n/* Turn on \"unmap as much as possible on explicit GC\" mode at start-up. */\n#  define GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT \\\n    GC_set_force_unmap_on_gcollect(1)\n#else\n#  define GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT (void)0\n#endif\n\n#ifdef GC_DONT_GC\n/*\n * This is for debugging only (useful if environment variables are\n * unsupported); cannot call `GC_disable()` as goes before the\n * collector initialization.\n */\n#  define GC_INIT_CONF_MAX_RETRIES (void)(GC_dont_gc = 1)\n#elif defined(GC_MAX_RETRIES) && !defined(CPPCHECK)\n/* Set `GC_max_retries` to the desired value at start-up. */\n#  define GC_INIT_CONF_MAX_RETRIES GC_set_max_retries(GC_MAX_RETRIES)\n#else\n#  define GC_INIT_CONF_MAX_RETRIES (void)0\n#endif\n\n#if defined(GC_ALLOCD_BYTES_PER_FINALIZER) && !defined(CPPCHECK)\n/* Set `GC_allocd_bytes_per_finalizer` to the desired value at start-up. */\n#  define GC_INIT_CONF_ALLOCD_BYTES_PER_FINALIZER \\\n    GC_set_allocd_bytes_per_finalizer(GC_ALLOCD_BYTES_PER_FINALIZER)\n#else\n#  define GC_INIT_CONF_ALLOCD_BYTES_PER_FINALIZER (void)0\n#endif\n\n#if defined(GC_FREE_SPACE_DIVISOR) && !defined(CPPCHECK)\n/* Set `GC_free_space_divisor` to the desired value at start-up. */\n#  define GC_INIT_CONF_FREE_SPACE_DIVISOR \\\n    GC_set_free_space_divisor(GC_FREE_SPACE_DIVISOR)\n#else\n#  define GC_INIT_CONF_FREE_SPACE_DIVISOR (void)0\n#endif\n\n#if defined(GC_FULL_FREQ) && !defined(CPPCHECK)\n/* Set `GC_full_freq` to the desired value at start-up. */\n#  define GC_INIT_CONF_FULL_FREQ GC_set_full_freq(GC_FULL_FREQ)\n#else\n#  define GC_INIT_CONF_FULL_FREQ (void)0\n#endif\n\n#if defined(GC_TIME_LIMIT) && !defined(CPPCHECK)\n/* Set `GC_time_limit` (in ms) to the desired value at start-up. */\n#  define GC_INIT_CONF_TIME_LIMIT GC_set_time_limit(GC_TIME_LIMIT)\n#else\n#  define GC_INIT_CONF_TIME_LIMIT (void)0\n#endif\n\n#if defined(GC_MARKERS) && defined(GC_THREADS) && !defined(CPPCHECK)\n/*\n * Set the number of marker threads (including the initiating one) to\n * the desired value at start-up.\n */\n#  define GC_INIT_CONF_MARKERS GC_set_markers_count(GC_MARKERS)\n#else\n#  define GC_INIT_CONF_MARKERS (void)0\n#endif\n\n#if defined(GC_SIG_SUSPEND) && defined(GC_THREADS) && !defined(CPPCHECK)\n#  define GC_INIT_CONF_SUSPEND_SIGNAL GC_set_suspend_signal(GC_SIG_SUSPEND)\n#else\n#  define GC_INIT_CONF_SUSPEND_SIGNAL (void)0\n#endif\n\n#if defined(GC_SIG_THR_RESTART) && defined(GC_THREADS) && !defined(CPPCHECK)\n#  define GC_INIT_CONF_THR_RESTART_SIGNAL \\\n    GC_set_thr_restart_signal(GC_SIG_THR_RESTART)\n#else\n#  define GC_INIT_CONF_THR_RESTART_SIGNAL (void)0\n#endif\n\n#if defined(GC_MAXIMUM_HEAP_SIZE) && !defined(CPPCHECK)\n/*\n * Limit the heap size to the desired value (useful for debugging).\n * The limit could be overridden either at the program start-up by\n * the similar environment variable or anytime later by the corresponding\n * API function call.\n */\n#  define GC_INIT_CONF_MAXIMUM_HEAP_SIZE \\\n    GC_set_max_heap_size(GC_MAXIMUM_HEAP_SIZE)\n#else\n#  define GC_INIT_CONF_MAXIMUM_HEAP_SIZE (void)0\n#endif\n\n#ifdef GC_IGNORE_WARN\n/* Turn off all warnings at start-up (after the collector initialization). */\n#  define GC_INIT_CONF_IGNORE_WARN GC_set_warn_proc(GC_ignore_warn_proc)\n#else\n#  define GC_INIT_CONF_IGNORE_WARN (void)0\n#endif\n\n#if defined(GC_INITIAL_HEAP_SIZE) && !defined(CPPCHECK)\n/* Set heap size to the desired value at start-up. */\n#  define GC_INIT_CONF_INITIAL_HEAP_SIZE                                  \\\n    {                                                                     \\\n      size_t heap_size = GC_get_heap_size();                              \\\n      if (heap_size < (size_t)(GC_INITIAL_HEAP_SIZE))                     \\\n        (void)GC_expand_hp(((size_t)(GC_INITIAL_HEAP_SIZE)) - heap_size); \\\n    }\n#else\n#  define GC_INIT_CONF_INITIAL_HEAP_SIZE (void)0\n#endif\n\n/**\n * Portable clients should call this at the program start-up.\n * More over, some platforms require this call to be done strictly from\n * the primordial thread.  Multiple invocations are harmless.\n */\n#define GC_INIT()                                     \\\n  {                                                   \\\n    GC_INIT_CONF_DONT_EXPAND; /*< pre-init */         \\\n    GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT;             \\\n    GC_INIT_CONF_MAX_RETRIES;                         \\\n    GC_INIT_CONF_ALLOCD_BYTES_PER_FINALIZER;          \\\n    GC_INIT_CONF_FREE_SPACE_DIVISOR;                  \\\n    GC_INIT_CONF_FULL_FREQ;                           \\\n    GC_INIT_CONF_TIME_LIMIT;                          \\\n    GC_INIT_CONF_MARKERS;                             \\\n    GC_INIT_CONF_SUSPEND_SIGNAL;                      \\\n    GC_INIT_CONF_THR_RESTART_SIGNAL;                  \\\n    GC_INIT_CONF_MAXIMUM_HEAP_SIZE;                   \\\n    GC_init();          /*< real GC initialization */ \\\n    GC_INIT_CONF_ROOTS; /*< post-init */              \\\n    GC_INIT_CONF_IGNORE_WARN;                         \\\n    GC_INIT_CONF_INITIAL_HEAP_SIZE;                   \\\n  }\n\n/**\n * win32s may not free all resources on process exit.\n * This explicitly deallocates the heap.  Defined only for Windows.\n */\nGC_API void GC_CALL GC_win32_free_heap(void);\n\n#if defined(__SYMBIAN32__)\nGC_API void GC_CALL GC_init_global_static_roots(void);\n#endif\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#endif /* GC_H */\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/gc_allocator.h",
    "content": "/*\n * Copyright (c) 1996-1997 Silicon Graphics Computer Systems, Inc.\n * Copyright (c) 2002 Hewlett-Packard Company\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * This implements standard-conforming allocators that interact with\n * the garbage collector.  `gc_allocator<T>` allocates garbage-collectible\n * objects of type `T`.  `traceable_allocator<T>` allocates objects that\n * are not themselves garbage-collected ones, but are scanned by the\n * collector for pointers to collectible objects.  `traceable_allocator<T>`\n * should be used for explicitly managed STL containers that may point to\n * collectible objects.\n *\n * This code was derived from an earlier version of the GNU C++ standard\n * library, which itself was derived from the SGI STL implementation.\n *\n * Ignore-off-page allocator: George T. Talbot\n */\n\n#ifndef GC_ALLOCATOR_H\n#define GC_ALLOCATOR_H\n\n#include \"gc.h\"\n\n#include <new> // for placement `new` and `bad_alloc`\n\n#ifdef GC_NAMESPACE_ALLOCATOR\nnamespace boehmgc\n{\n#endif\n\n#if !defined(GC_NO_MEMBER_TEMPLATES) && defined(_MSC_VER) && _MSC_VER <= 1200\n// MSVC++ 6.0 do not support member templates.\n#  define GC_NO_MEMBER_TEMPLATES\n#endif\n\n#if defined(GC_NEW_ABORTS_ON_OOM) || defined(_LIBCPP_NO_EXCEPTIONS)\n#  define GC_ALLOCATOR_THROW_OR_ABORT() GC_abort_on_oom()\n#else\n#  define GC_ALLOCATOR_THROW_OR_ABORT() throw std::bad_alloc()\n#endif\n\n#if __cplusplus >= 201103L\n#  define GC_ALCTR_PTRDIFF_T std::ptrdiff_t\n#  define GC_ALCTR_SIZE_T std::size_t\n#else\n#  define GC_ALCTR_PTRDIFF_T ptrdiff_t\n#  define GC_ALCTR_SIZE_T size_t\n#endif\n\n// First some helpers to allow us to dispatch on whether or not a type\n// is known to be pointer-free.  These are private, except that the client\n// may invoke the `GC_DECLARE_PTRFREE` macro.\n\nstruct GC_true_type {\n};\nstruct GC_false_type {\n};\n\ntemplate <class GC_tp> struct GC_type_traits {\n  GC_false_type GC_is_ptr_free;\n};\n\n#define GC_DECLARE_PTRFREE(T)            \\\n  template <> struct GC_type_traits<T> { \\\n    GC_true_type GC_is_ptr_free;         \\\n  }\n\nGC_DECLARE_PTRFREE(char);\nGC_DECLARE_PTRFREE(signed char);\nGC_DECLARE_PTRFREE(unsigned char);\nGC_DECLARE_PTRFREE(signed short);\nGC_DECLARE_PTRFREE(unsigned short);\nGC_DECLARE_PTRFREE(signed int);\nGC_DECLARE_PTRFREE(unsigned int);\nGC_DECLARE_PTRFREE(signed long);\nGC_DECLARE_PTRFREE(unsigned long);\nGC_DECLARE_PTRFREE(float);\nGC_DECLARE_PTRFREE(double);\nGC_DECLARE_PTRFREE(long double);\n// The client may want to add others.\n\n// In the following `GC_Tp` is `GC_true_type` if we are allocating\n// a pointer-free object.\ntemplate <class GC_Tp>\ninline void *\nGC_selective_alloc(GC_ALCTR_SIZE_T n, GC_Tp, bool ignore_off_page)\n{\n  void *obj = ignore_off_page ? GC_MALLOC_IGNORE_OFF_PAGE(n) : GC_MALLOC(n);\n  if (0 == obj)\n    GC_ALLOCATOR_THROW_OR_ABORT();\n  return obj;\n}\n\n#if !defined(__WATCOMC__)\n// Note: template-id not supported in this context by Watcom compiler.\ntemplate <>\ninline void *\nGC_selective_alloc<GC_true_type>(GC_ALCTR_SIZE_T n, GC_true_type,\n                                 bool ignore_off_page)\n{\n  void *obj = ignore_off_page ? GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(n)\n                              : GC_MALLOC_ATOMIC(n);\n  if (0 == obj)\n    GC_ALLOCATOR_THROW_OR_ABORT();\n  return obj;\n}\n#endif\n\n// Now the public `gc_allocator<T>` class.\ntemplate <class GC_Tp> class gc_allocator\n{\npublic:\n  typedef GC_ALCTR_SIZE_T size_type;\n  typedef GC_ALCTR_PTRDIFF_T difference_type;\n  typedef GC_Tp *pointer;\n  typedef const GC_Tp *const_pointer;\n  typedef GC_Tp &reference;\n  typedef const GC_Tp &const_reference;\n  typedef GC_Tp value_type;\n\n  template <class GC_Tp1> struct rebind {\n    typedef gc_allocator<GC_Tp1> other;\n  };\n\n  GC_CONSTEXPR\n  gc_allocator() GC_NOEXCEPT\n  {\n    // Empty.\n  }\n\n  GC_CONSTEXPR\n  gc_allocator(const gc_allocator &) GC_NOEXCEPT\n  {\n    // Empty.\n  }\n\n#ifndef GC_NO_MEMBER_TEMPLATES\n  template <class GC_Tp1>\n  GC_ATTR_EXPLICIT GC_CONSTEXPR\n  gc_allocator(const gc_allocator<GC_Tp1> &) GC_NOEXCEPT\n  {\n  }\n#endif\n\n  GC_CONSTEXPR ~gc_allocator() GC_NOEXCEPT {}\n\n  GC_CONSTEXPR pointer\n  address(reference GC_x) const\n  {\n    return &GC_x;\n  }\n\n  GC_CONSTEXPR const_pointer\n  address(const_reference GC_x) const\n  {\n    return &GC_x;\n  }\n\n  // `GC_n` is permitted to be 0.  The C++ standard says nothing about what\n  // the return value is when `GC_n` is zero.\n  GC_CONSTEXPR GC_Tp *\n  allocate(size_type GC_n, const void * = 0)\n  {\n    GC_type_traits<GC_Tp> traits;\n    return static_cast<GC_Tp *>(GC_selective_alloc(\n        GC_n * sizeof(GC_Tp), traits.GC_is_ptr_free, false));\n  }\n\n  GC_CONSTEXPR void\n  deallocate(pointer __p, size_type /* `GC_n` */) GC_NOEXCEPT\n  {\n    GC_FREE(__p);\n  }\n\n  GC_CONSTEXPR size_type\n  max_size() const GC_NOEXCEPT\n  {\n    return static_cast<GC_ALCTR_SIZE_T>(-1) / sizeof(GC_Tp);\n  }\n\n  GC_CONSTEXPR void\n  construct(pointer __p, const GC_Tp &__val)\n  {\n    new (__p) GC_Tp(__val);\n  }\n\n  GC_CONSTEXPR void\n  destroy(pointer __p)\n  {\n    __p->~GC_Tp();\n  }\n};\n\ntemplate <> class gc_allocator<void>\n{\npublic:\n  typedef GC_ALCTR_SIZE_T size_type;\n  typedef GC_ALCTR_PTRDIFF_T difference_type;\n  typedef void *pointer;\n  typedef const void *const_pointer;\n  typedef void value_type;\n\n  template <class GC_Tp1> struct rebind {\n    typedef gc_allocator<GC_Tp1> other;\n  };\n};\n\ntemplate <class GC_T1, class GC_T2>\nGC_CONSTEXPR inline bool\noperator==(const gc_allocator<GC_T1> &,\n           const gc_allocator<GC_T2> &) GC_NOEXCEPT\n{\n  return true;\n}\n\ntemplate <class GC_T1, class GC_T2>\nGC_CONSTEXPR inline bool\noperator!=(const gc_allocator<GC_T1> &,\n           const gc_allocator<GC_T2> &) GC_NOEXCEPT\n{\n  return false;\n}\n\n// Now the public `gc_allocator_ignore_off_page<T>` class.\ntemplate <class GC_Tp> class gc_allocator_ignore_off_page\n{\npublic:\n  typedef GC_ALCTR_SIZE_T size_type;\n  typedef GC_ALCTR_PTRDIFF_T difference_type;\n  typedef GC_Tp *pointer;\n  typedef const GC_Tp *const_pointer;\n  typedef GC_Tp &reference;\n  typedef const GC_Tp &const_reference;\n  typedef GC_Tp value_type;\n\n  template <class GC_Tp1> struct rebind {\n    typedef gc_allocator_ignore_off_page<GC_Tp1> other;\n  };\n\n  GC_CONSTEXPR\n  gc_allocator_ignore_off_page() GC_NOEXCEPT\n  {\n    // Empty.\n  }\n\n  GC_CONSTEXPR\n  gc_allocator_ignore_off_page(const gc_allocator_ignore_off_page &)\n      GC_NOEXCEPT\n  {\n    // Empty.\n  }\n\n#ifndef GC_NO_MEMBER_TEMPLATES\n  template <class GC_Tp1>\n  GC_ATTR_EXPLICIT GC_CONSTEXPR\n  gc_allocator_ignore_off_page(const gc_allocator_ignore_off_page<GC_Tp1> &)\n      GC_NOEXCEPT\n  {\n  }\n#endif\n\n  GC_CONSTEXPR ~gc_allocator_ignore_off_page() GC_NOEXCEPT {}\n\n  GC_CONSTEXPR pointer\n  address(reference GC_x) const\n  {\n    return &GC_x;\n  }\n\n  GC_CONSTEXPR const_pointer\n  address(const_reference GC_x) const\n  {\n    return &GC_x;\n  }\n\n  // `GC_n` is permitted to be 0.  The C++ standard says nothing about what\n  // the return value is when `GC_n` is zero.\n  GC_CONSTEXPR GC_Tp *\n  allocate(size_type GC_n, const void * = 0)\n  {\n    GC_type_traits<GC_Tp> traits;\n    return static_cast<GC_Tp *>(\n        GC_selective_alloc(GC_n * sizeof(GC_Tp), traits.GC_is_ptr_free, true));\n  }\n\n  GC_CONSTEXPR void\n  deallocate(pointer __p, size_type /* `GC_n` */) GC_NOEXCEPT\n  {\n    GC_FREE(__p);\n  }\n\n  GC_CONSTEXPR size_type\n  max_size() const GC_NOEXCEPT\n  {\n    return static_cast<GC_ALCTR_SIZE_T>(-1) / sizeof(GC_Tp);\n  }\n\n  GC_CONSTEXPR void\n  construct(pointer __p, const GC_Tp &__val)\n  {\n    new (__p) GC_Tp(__val);\n  }\n\n  GC_CONSTEXPR void\n  destroy(pointer __p)\n  {\n    __p->~GC_Tp();\n  }\n};\n\ntemplate <> class gc_allocator_ignore_off_page<void>\n{\npublic:\n  typedef GC_ALCTR_SIZE_T size_type;\n  typedef GC_ALCTR_PTRDIFF_T difference_type;\n  typedef void *pointer;\n  typedef const void *const_pointer;\n  typedef void value_type;\n\n  template <class GC_Tp1> struct rebind {\n    typedef gc_allocator_ignore_off_page<GC_Tp1> other;\n  };\n};\n\ntemplate <class GC_T1, class GC_T2>\nGC_CONSTEXPR inline bool\noperator==(const gc_allocator_ignore_off_page<GC_T1> &,\n           const gc_allocator_ignore_off_page<GC_T2> &) GC_NOEXCEPT\n{\n  return true;\n}\n\ntemplate <class GC_T1, class GC_T2>\nGC_CONSTEXPR inline bool\noperator!=(const gc_allocator_ignore_off_page<GC_T1> &,\n           const gc_allocator_ignore_off_page<GC_T2> &) GC_NOEXCEPT\n{\n  return false;\n}\n\n// And the public `traceable_allocator<T>` class.\n\n// Note that we currently do not specialize the pointer-free case,\n// since a pointer-free traceable container does not make that much sense,\n// though it could become an issue due to abstraction boundaries.\n\ntemplate <class GC_Tp> class traceable_allocator\n{\npublic:\n  typedef GC_ALCTR_SIZE_T size_type;\n  typedef GC_ALCTR_PTRDIFF_T difference_type;\n  typedef GC_Tp *pointer;\n  typedef const GC_Tp *const_pointer;\n  typedef GC_Tp &reference;\n  typedef const GC_Tp &const_reference;\n  typedef GC_Tp value_type;\n\n  template <class GC_Tp1> struct rebind {\n    typedef traceable_allocator<GC_Tp1> other;\n  };\n\n  GC_CONSTEXPR\n  traceable_allocator() GC_NOEXCEPT\n  {\n    // Empty.\n  }\n\n  GC_CONSTEXPR\n  traceable_allocator(const traceable_allocator &) GC_NOEXCEPT\n  {\n    // Empty.\n  }\n\n#ifndef GC_NO_MEMBER_TEMPLATES\n  template <class GC_Tp1>\n  GC_ATTR_EXPLICIT GC_CONSTEXPR\n  traceable_allocator(const traceable_allocator<GC_Tp1> &) GC_NOEXCEPT\n  {\n  }\n#endif\n\n  GC_CONSTEXPR ~traceable_allocator() GC_NOEXCEPT {}\n\n  GC_CONSTEXPR pointer\n  address(reference GC_x) const\n  {\n    return &GC_x;\n  }\n\n  GC_CONSTEXPR const_pointer\n  address(const_reference GC_x) const\n  {\n    return &GC_x;\n  }\n\n  // `GC_n` is permitted to be 0.  The C++ standard says nothing about what\n  // the return value is when `GC_n` is zero.\n  GC_CONSTEXPR GC_Tp *\n  allocate(size_type GC_n, const void * = 0)\n  {\n    void *obj = GC_MALLOC_UNCOLLECTABLE(GC_n * sizeof(GC_Tp));\n    if (0 == obj)\n      GC_ALLOCATOR_THROW_OR_ABORT();\n    return static_cast<GC_Tp *>(obj);\n  }\n\n  GC_CONSTEXPR void\n  deallocate(pointer __p, size_type /* `GC_n` */) GC_NOEXCEPT\n  {\n    GC_FREE(__p);\n  }\n\n  GC_CONSTEXPR size_type\n  max_size() const GC_NOEXCEPT\n  {\n    return static_cast<GC_ALCTR_SIZE_T>(-1) / sizeof(GC_Tp);\n  }\n\n  GC_CONSTEXPR void\n  construct(pointer __p, const GC_Tp &__val)\n  {\n    new (__p) GC_Tp(__val);\n  }\n\n  GC_CONSTEXPR void\n  destroy(pointer __p)\n  {\n    __p->~GC_Tp();\n  }\n};\n\ntemplate <> class traceable_allocator<void>\n{\npublic:\n  typedef GC_ALCTR_SIZE_T size_type;\n  typedef GC_ALCTR_PTRDIFF_T difference_type;\n  typedef void *pointer;\n  typedef const void *const_pointer;\n  typedef void value_type;\n\n  template <class GC_Tp1> struct rebind {\n    typedef traceable_allocator<GC_Tp1> other;\n  };\n};\n\ntemplate <class GC_T1, class GC_T2>\nGC_CONSTEXPR inline bool\noperator==(const traceable_allocator<GC_T1> &,\n           const traceable_allocator<GC_T2> &) GC_NOEXCEPT\n{\n  return true;\n}\n\ntemplate <class GC_T1, class GC_T2>\nGC_CONSTEXPR inline bool\noperator!=(const traceable_allocator<GC_T1> &,\n           const traceable_allocator<GC_T2> &) GC_NOEXCEPT\n{\n  return false;\n}\n\n#undef GC_ALCTR_PTRDIFF_T\n#undef GC_ALCTR_SIZE_T\n\n#ifdef GC_NAMESPACE_ALLOCATOR\n}\n#endif\n\n#endif /* GC_ALLOCATOR_H */\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/gc_backptr.h",
    "content": "/*\n * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.\n * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.\n * All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * This is a simple API to implement pointer back tracing, i.e.\n * to answer questions such as \"who is pointing to this\" or\n * \"why is this object being retained by the collector\".\n * Most of these calls yield useful information on only after\n * a garbage collection.  Usually the client will first force\n * a full collection and then gather information, preferably\n * before much intervening allocation.\n * The implementation of the interface is only about 99.9999%\n * correct.  It is intended to be good enough for profiling,\n * but is not intended to be used with production code.\n * Results are likely to be much more useful if all allocation\n * is accomplished through the debugging allocators.\n */\n\n/* The implementation idea is due to A. Demers. */\n\n#ifndef GC_BACKPTR_H\n#define GC_BACKPTR_H\n\n#ifndef GC_H\n#  include \"gc.h\"\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef enum {\n  /** No reference info available. */\n  GC_UNREFERENCED,\n  /** `dest` is not allocated with a debug allocation routine. */\n  GC_NO_SPACE,\n  /** Referenced directly by root `*base_p`. */\n  GC_REFD_FROM_ROOT,\n  /** Referenced from a register, i.e. a root without an address. */\n  GC_REFD_FROM_REG,\n  /** Referenced from another heap object. */\n  GC_REFD_FROM_HEAP,\n  /** Finalizable and hence accessible. */\n  GC_FINALIZER_REFD\n} GC_ref_kind;\n\n/**\n * Store information about the source object referencing `dest` in\n * `*base_p` and `*offset_p`.  If multiple objects or roots point to\n * `dest`, then the one reported will be the last one used by the\n * garbage collector to trace the object.  If the source is root, then\n * `*base_p` is the address and `*offset_p` is zero.  If the source is\n * a heap object, then `*base_p` is non-`NULL` and `*offset_p` is the\n * offset.  `dest` can be any address within a heap object.\n * The allocator lock is not acquired by design (despite of the\n * possibility of a race); anyway the function should not be used in\n * production code.\n */\nGC_API GC_ref_kind GC_CALL GC_get_back_ptr_info(void * /* `dest` */,\n                                                void ** /* `base_p` */,\n                                                size_t * /* `offset_p` */)\n    GC_ATTR_NONNULL(1);\n\n/**\n * Generate a random heap address.  The resulting address is\n * in the heap, but not necessarily inside a valid object.\n * The caller should hold the allocator lock.\n */\nGC_API void *GC_CALL GC_generate_random_heap_address(void);\n\n/**\n * Generate a random address inside a valid marked heap object.\n * The caller should hold the allocator lock.\n */\nGC_API void *GC_CALL GC_generate_random_valid_address(void);\n\n/**\n * Force a garbage collection and generate a backtrace from a random\n * heap address.  This uses the collector logging mechanism (`GC_printf`)\n * to produce output.  It can often be called from a debugger.\n */\nGC_API void GC_CALL GC_generate_random_backtrace(void);\n\n/**\n * Print a backtrace from a specific address.  The client should call\n * `GC_gcollect()` right before the invocation.  Used e.g. by\n * `GC_generate_random_backtrace()`.\n */\nGC_API void GC_CALL GC_print_backtrace(void *) GC_ATTR_NONNULL(1);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#endif /* GC_BACKPTR_H */\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/gc_config_macros.h",
    "content": "/*\n * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.\n * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.\n * All rights reserved.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * This should never be included directly; it is included only from\n * `gc.h` file.  We separate it only to make `gc.h` file more suitable\n * as documentation.\n */\n#if defined(GC_H)\n\n/* Convenient internal macro to test version of gcc. */\n#  if defined(__GNUC__) && defined(__GNUC_MINOR__)\n#    define GC_GNUC_PREREQ(major, minor) \\\n      ((__GNUC__ << 8) + __GNUC_MINOR__ >= ((major) << 8) + (minor))\n#  else\n#    define GC_GNUC_PREREQ(major, minor) 0 /*< false */\n#  endif\n\n/*\n * A macro to define integer types of a pointer size.  There seems to\n * be no way to do this even semi-portably.  The following is probably\n * no better/worse than almost anything else.\n * The ANSI standard suggests that `size_t` and `ptrdiff_t` might be\n * better choices.  But those had incorrect definitions on some older\n * systems; notably `typedef int size_t` is wrong.\n */\n#  ifdef _WIN64\n#    if defined(__int64) && !defined(CPPCHECK)\n#      define GC_SIGNEDWORD __int64\n#    else\n#      define GC_SIGNEDWORD long long\n#    endif\n#  else\n#    define GC_SIGNEDWORD long\n#  endif\n#  define GC_UNSIGNEDWORD unsigned GC_SIGNEDWORD\n\n/* Size of a pointer in bytes. */\n#  if defined(__SIZEOF_POINTER__)\n#    define GC_SIZEOF_PTR __SIZEOF_POINTER__\n#  elif defined(__LP64__) || defined(_LP64) || defined(_WIN64)               \\\n      || defined(__alpha__) || defined(__arch64__) || defined(__powerpc64__) \\\n      || defined(__s390x__) || defined(__sparcv9)                            \\\n      || (defined(__x86_64__) && !defined(__ILP32__))\n#    define GC_SIZEOF_PTR 8\n#  else\n#    define GC_SIZEOF_PTR 4\n#  endif\n\n/*\n * The return type of `GC_get_version()`.  A 32-bit unsigned integer\n * or longer.\n */\n#  define GC_VERSION_VAL_T unsigned\n\n/*\n * Some tests for old macros.  These violate our namespace rules and\n * are deprecated.  Use the `GC_` names instead.\n */\n#  if defined(SOLARIS_THREADS) || defined(_SOLARIS_THREADS) \\\n      || defined(_SOLARIS_PTHREADS) || defined(GC_SOLARIS_PTHREADS)\n/*\n * We no longer support old style Solaris threads.\n * `GC_SOLARIS_THREADS` now means `pthreads`.\n */\n#    ifndef GC_SOLARIS_THREADS\n#      define GC_SOLARIS_THREADS\n#    endif\n#  endif\n#  if defined(IRIX_THREADS)\n#    define GC_IRIX_THREADS\n#  endif\n#  if defined(DGUX_THREADS) && !defined(GC_DGUX386_THREADS)\n#    define GC_DGUX386_THREADS\n#  endif\n#  if defined(AIX_THREADS)\n#    define GC_AIX_THREADS\n#  endif\n#  if defined(HPUX_THREADS)\n#    define GC_HPUX_THREADS\n#  endif\n#  if defined(OSF1_THREADS)\n#    define GC_OSF1_THREADS\n#  endif\n#  if defined(LINUX_THREADS)\n#    define GC_LINUX_THREADS\n#  endif\n#  if defined(WIN32_THREADS)\n#    define GC_WIN32_THREADS\n#  endif\n#  if defined(RTEMS_THREADS)\n#    define GC_RTEMS_PTHREADS\n#  endif\n#  if defined(USE_LD_WRAP)\n#    define GC_USE_LD_WRAP\n#  endif\n\n#  if defined(GC_WIN32_PTHREADS) && !defined(GC_WIN32_THREADS)\n/* Using pthreads-win32 library (or other Win32 implementation). */\n#    define GC_WIN32_THREADS\n#  endif\n\n#  if defined(GC_AIX_THREADS) || defined(GC_DARWIN_THREADS)         \\\n      || defined(GC_DGUX386_THREADS) || defined(GC_FREEBSD_THREADS) \\\n      || defined(GC_HPUX_THREADS) || defined(GC_IRIX_THREADS)       \\\n      || defined(GC_LINUX_THREADS) || defined(GC_NETBSD_THREADS)    \\\n      || defined(GC_OPENBSD_THREADS) || defined(GC_OSF1_THREADS)    \\\n      || defined(GC_SOLARIS_THREADS) || defined(GC_WIN32_THREADS)   \\\n      || defined(GC_RTEMS_PTHREADS)\n#    ifndef GC_THREADS\n#      define GC_THREADS\n#    endif\n#  elif defined(GC_THREADS)\n#    if defined(__linux__) || defined(__native_client__)\n#      define GC_LINUX_THREADS\n#    elif defined(__OpenBSD__)\n#      define GC_OPENBSD_THREADS\n#    elif defined(_PA_RISC1_1) || defined(_PA_RISC2_0) || defined(hppa) \\\n        || defined(__HPPA) || (defined(__ia64) && defined(_HPUX_SOURCE))\n#      define GC_HPUX_THREADS\n#    elif defined(__HAIKU__)\n#      define GC_HAIKU_THREADS\n#    elif (defined(__DragonFly__) || defined(__FreeBSD_kernel__) \\\n           || defined(__FreeBSD__))                              \\\n        && !defined(GC_NO_FREEBSD)\n#      define GC_FREEBSD_THREADS\n#    elif defined(__NetBSD__)\n#      define GC_NETBSD_THREADS\n#    elif defined(__alpha) || defined(__alpha__) /*< not Linux, not xBSD */\n#      define GC_OSF1_THREADS\n#    elif (defined(mips) || defined(__mips) || defined(_mips))        \\\n        && !(defined(nec_ews) || defined(_nec_ews) || defined(ultrix) \\\n             || defined(__ultrix))\n#      define GC_IRIX_THREADS\n#    elif defined(__sparc) /* `&& !defined(__linux__)` */              \\\n        || ((defined(sun) || defined(__sun))                           \\\n            && (defined(i386) || defined(__i386__) || defined(__amd64) \\\n                || defined(__amd64__)))\n#      define GC_SOLARIS_THREADS\n#    elif defined(__APPLE__) && defined(__MACH__)\n#      define GC_DARWIN_THREADS\n#    endif\n#    if defined(DGUX) && (defined(i386) || defined(__i386__))\n#      define GC_DGUX386_THREADS\n#    endif\n#    if defined(_AIX)\n#      define GC_AIX_THREADS\n#    endif\n#    if (defined(_WIN32) || defined(_MSC_VER) || defined(__BORLANDC__) \\\n         || defined(__CYGWIN32__) || defined(__CYGWIN__)               \\\n         || defined(__CEGCC__) || defined(_WIN32_WCE)                  \\\n         || defined(__MINGW32__))                                      \\\n        && !defined(GC_WIN32_THREADS)\n/* Either POSIX or native Win32 threads. */\n#      define GC_WIN32_THREADS\n#    endif\n#    if defined(__rtems__) && (defined(i386) || defined(__i386__))\n#      define GC_RTEMS_PTHREADS\n#    endif\n#  endif /* GC_THREADS */\n\n#  undef GC_PTHREADS\n#  if (!defined(GC_WIN32_THREADS) || defined(GC_WIN32_PTHREADS) \\\n       || defined(__CYGWIN32__) || defined(__CYGWIN__))         \\\n      && defined(GC_THREADS) && !defined(NN_PLATFORM_CTR)       \\\n      && !defined(NN_BUILD_TARGET_PLATFORM_NX)\n/* POSIX threads (`pthreads`). */\n#    define GC_PTHREADS\n#  endif\n\n#  if !defined(_PTHREADS) && defined(GC_NETBSD_THREADS)\n#    define _PTHREADS\n#  endif\n\n#  if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)\n#    define _POSIX4A_DRAFT10_SOURCE 1\n#  endif\n\n#  if !defined(_REENTRANT) && defined(GC_PTHREADS) \\\n      && !defined(GC_WIN32_THREADS)\n/*\n * Better late than never.  This fails if system headers that depend\n * on this were previously included.\n */\n#    define _REENTRANT 1\n#  endif\n\n#  if defined(__clang__) && defined(__CYGWIN__) && defined(GC_THREADS) \\\n      && defined(__LP64__)\n/*\n * Workaround \"__stdcall__ ignored for this target\" clang warning.\n * Note: `__stdcall` is defined implicitly based on `__stdcall__`.\n */\n#    define __stdcall__ /*< empty */\n#  endif\n\n#  define __GC\n#  if !defined(_WIN32_WCE) || defined(__GNUC__)\n#    include <stddef.h>\n#    if defined(__MINGW32__) && !defined(_WIN32_WCE) \\\n        || defined(__CHERI_PURE_CAPABILITY__)\n#      include <stdint.h>\n/*\n * We mention `uintptr_t`.  Perhaps this should be included in pure\n * MS environments as well.\n */\n#    endif\n#  else\n/* Yet more kludges for WinCE. */\n#    include <stdlib.h> /*< for `size_t` */\n#    ifndef _PTRDIFF_T_DEFINED\n/* `ptrdiff_t` is not defined. */\n#      define _PTRDIFF_T_DEFINED\ntypedef long ptrdiff_t;\n#    endif\n#  endif /* _WIN32_WCE */\n\n#  if !defined(GC_NOT_DLL) && !defined(GC_DLL)  \\\n      && ((defined(_DLL) && !defined(__GNUC__)) \\\n          || (defined(DLL_EXPORT) && defined(GC_BUILD)))\n#    define GC_DLL\n#  endif\n\n#  if defined(GC_DLL) && !defined(GC_API)\n\n#    if defined(__CEGCC__)\n#      if defined(GC_BUILD)\n#        define GC_API __declspec(dllexport)\n#      else\n#        define GC_API __declspec(dllimport)\n#      endif\n\n#    elif defined(__MINGW32__)\n#      if defined(__cplusplus) && defined(GC_BUILD)\n#        define GC_API extern __declspec(dllexport)\n#      elif defined(GC_BUILD) || defined(__MINGW32_DELAY_LOAD__)\n#        define GC_API __declspec(dllexport)\n#      else\n#        define GC_API extern __declspec(dllimport)\n#      endif\n\n#    elif defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \\\n        || defined(__CYGWIN__)\n#      ifdef GC_BUILD\n#        define GC_API extern __declspec(dllexport)\n#      else\n#        define GC_API __declspec(dllimport)\n#      endif\n\n#    elif defined(__WATCOMC__)\n#      ifdef GC_BUILD\n#        define GC_API extern __declspec(dllexport)\n#      else\n#        define GC_API extern __declspec(dllimport)\n#      endif\n\n#    elif defined(__SYMBIAN32__)\n#      ifdef GC_BUILD\n#        define GC_API extern EXPORT_C\n#      else\n#        define GC_API extern IMPORT_C\n#      endif\n\n#    elif defined(__GNUC__)\n/* Only matters if used in conjunction with `-fvisibility=hidden` option. */\n#      if defined(GC_BUILD) && !defined(GC_NO_VISIBILITY) \\\n          && (GC_GNUC_PREREQ(4, 0) || defined(GC_VISIBILITY_HIDDEN_SET))\n#        define GC_API extern __attribute__((__visibility__(\"default\")))\n#      endif\n#    endif\n#  endif /* GC_DLL */\n\n#  ifndef GC_API\n#    define GC_API extern\n#  endif\n\n#  ifndef GC_CALL\n#    define GC_CALL\n#  endif\n\n#  ifndef GC_CALLBACK\n#    define GC_CALLBACK GC_CALL\n#  endif\n\n#  ifndef GC_ATTR_MALLOC\n/*\n * `malloc` attribute should be used for all `malloc`-like functions\n * (to tell the compiler that a function may be treated as if any\n * non-`NULL` pointer it returns cannot alias any other pointer valid\n * when the function returns).  If the client code violates this rule\n * by using custom `GC_oom_func`, then the client should define\n * `GC_OOM_FUNC_RETURNS_ALIAS` macro.\n */\n#    ifdef GC_OOM_FUNC_RETURNS_ALIAS\n#      define GC_ATTR_MALLOC /*< empty */\n#    elif GC_GNUC_PREREQ(3, 1)\n#      define GC_ATTR_MALLOC __attribute__((__malloc__))\n#    elif defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(__EDG__)\n#      define GC_ATTR_MALLOC \\\n        __declspec(allocator) __declspec(noalias) __declspec(restrict)\n#    elif defined(_MSC_VER) && _MSC_VER >= 1400\n#      define GC_ATTR_MALLOC __declspec(noalias) __declspec(restrict)\n#    else\n#      define GC_ATTR_MALLOC\n#    endif\n#  endif\n\n#  ifndef GC_ATTR_ALLOC_SIZE\n/* `alloc_size` attribute improves `__builtin_object_size` correctness. */\n#    undef GC_ATTR_CALLOC_SIZE\n#    ifdef __clang__\n#      if __has_attribute(__alloc_size__)\n#        define GC_ATTR_ALLOC_SIZE(argnum) \\\n          __attribute__((__alloc_size__(argnum)))\n#        define GC_ATTR_CALLOC_SIZE(n, s) __attribute__((__alloc_size__(n, s)))\n#      else\n#        define GC_ATTR_ALLOC_SIZE(argnum) /*< empty */\n#      endif\n#    elif GC_GNUC_PREREQ(4, 3) && !defined(__ICC)\n#      define GC_ATTR_ALLOC_SIZE(argnum) \\\n        __attribute__((__alloc_size__(argnum)))\n#      define GC_ATTR_CALLOC_SIZE(n, s) __attribute__((__alloc_size__(n, s)))\n#    else\n#      define GC_ATTR_ALLOC_SIZE(argnum) /*< empty */\n#    endif\n#  endif\n\n#  ifndef GC_ATTR_CALLOC_SIZE\n#    define GC_ATTR_CALLOC_SIZE(n, s) /*< empty */\n#  endif\n\n#  ifndef GC_ATTR_NONNULL\n#    if GC_GNUC_PREREQ(4, 0)\n#      define GC_ATTR_NONNULL(argnum) __attribute__((__nonnull__(argnum)))\n#    else\n#      define GC_ATTR_NONNULL(argnum) /*< empty */\n#    endif\n#  endif\n\n#  ifndef GC_ATTR_CONST\n#    if GC_GNUC_PREREQ(4, 0)\n#      define GC_ATTR_CONST __attribute__((__const__))\n#    else\n#      define GC_ATTR_CONST /*< empty */\n#    endif\n#  endif\n\n#  ifndef GC_ATTR_DEPRECATED\n#    ifdef GC_BUILD\n#      undef GC_ATTR_DEPRECATED\n#      define GC_ATTR_DEPRECATED /*< empty */\n#    elif GC_GNUC_PREREQ(4, 0)\n#      define GC_ATTR_DEPRECATED __attribute__((__deprecated__))\n#    elif defined(_MSC_VER) && _MSC_VER >= 1200\n#      define GC_ATTR_DEPRECATED __declspec(deprecated)\n#    else\n#      define GC_ATTR_DEPRECATED /*< empty */\n#    endif\n#  endif\n\n#  ifndef GC_ATTR_NORETURN\n#    if GC_GNUC_PREREQ(2, 7)\n#      define GC_ATTR_NORETURN __attribute__((__noreturn__))\n#    elif defined(_MSC_VER) && _MSC_VER >= 1310 /*< VS 2003+ */\n#      define GC_ATTR_NORETURN __declspec(noreturn)\n#    elif defined(__NORETURN) /*< used in Solaris */\n#      define GC_ATTR_NORETURN __NORETURN\n#    else\n#      define GC_ATTR_NORETURN /*< empty */\n#    endif\n#  endif\n\n#  if defined(__sgi) && !defined(__GNUC__) && _COMPILER_VERSION >= 720\n#    define GC_ADD_CALLER\n#    define GC_RETURN_ADDR ((GC_return_addr_t)__return_address)\n#  endif\n\n#  if defined(__linux__) || defined(__GLIBC__)\n#    if !defined(__native_client__)\n#      include <features.h>\n#    endif\n#    if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \\\n        && !defined(__ia64__) && !defined(GC_MISSING_EXECINFO_H)  \\\n        && !defined(GC_HAVE_BUILTIN_BACKTRACE)\n#      define GC_HAVE_BUILTIN_BACKTRACE\n#    endif\n#    if defined(__i386__) || defined(__amd64__) || defined(__x86_64__)\n#      define GC_CAN_SAVE_CALL_STACKS\n#    endif\n#  endif /* GLIBC */\n\n#  if defined(_MSC_VER) && (_MSC_VER >= 1200 /* v12.0+ (MSVC 6.0+) */) \\\n      && !defined(_M_ARM) && !defined(_M_ARM64) && !defined(_AMD64_)   \\\n      && !defined(_M_X64) && !defined(_WIN32_WCE)                      \\\n      && !defined(GC_HAVE_NO_BUILTIN_BACKTRACE)                        \\\n      && !defined(GC_HAVE_BUILTIN_BACKTRACE)\n#    define GC_HAVE_BUILTIN_BACKTRACE\n#  endif\n\n#  if defined(GC_HAVE_BUILTIN_BACKTRACE) && !defined(GC_CAN_SAVE_CALL_STACKS) \\\n      || defined(__sparc)\n#    define GC_CAN_SAVE_CALL_STACKS\n#  endif\n\n/*\n * If we are on a platform on which we cannot save call stacks, but\n * gcc is normally used, we go ahead and define `GC_ADD_CALLER` macro.\n * We make this decision independent of whether gcc is actually being\n * used, in order to keep the interface consistent, and allow mixing\n * of compilers.\n * This may also be desirable if it is possible but expensive to\n * retrieve the call chain.\n */\n#  if (defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) \\\n       || defined(__FreeBSD_kernel__) || defined(__HAIKU__)                 \\\n       || defined(__NetBSD__) || defined(__OpenBSD__)                       \\\n       || defined(HOST_ANDROID) || defined(__ANDROID__))                    \\\n      && !defined(GC_CAN_SAVE_CALL_STACKS)\n#    define GC_ADD_CALLER\n#    if GC_GNUC_PREREQ(2, 95)\n/*\n * gcc knows how to retrieve return address, but we do not know how to\n * generate call stacks.\n */\n#      define GC_RETURN_ADDR ((GC_return_addr_t)__builtin_return_address(0))\n#      if GC_GNUC_PREREQ(4, 0)                                     \\\n          && (defined(__i386__) || defined(__amd64__)              \\\n              || defined(__x86_64__) /* and probably others... */) \\\n          && !defined(GC_NO_RETURN_ADDR_PARENT)\n#        define GC_HAVE_RETURN_ADDR_PARENT\n#        define GC_RETURN_ADDR_PARENT                       \\\n          ((GC_return_addr_t)__builtin_extract_return_addr( \\\n              __builtin_return_address(1)))\n/*\n * Note: a compiler might complain that calling `__builtin_return_address`\n * with a nonzero argument is unsafe.\n */\n#      endif\n#    else\n/* Just pass 0 for gcc compatibility. */\n#      define GC_RETURN_ADDR ((GC_return_addr_t)0)\n#    endif\n#  endif /* !GC_CAN_SAVE_CALL_STACKS */\n\n#  ifdef GC_PTHREADS\n\n#    if (defined(GC_DARWIN_THREADS) || defined(GC_WIN32_PTHREADS)     \\\n         || defined(__native_client__) || defined(GC_RTEMS_PTHREADS)) \\\n        && !defined(GC_NO_DLOPEN)\n/* Either there is no `dlopen()` or we do not need to intercept it. */\n#      define GC_NO_DLOPEN\n#    endif\n\n#    if (defined(GC_DARWIN_THREADS) || defined(GC_WIN32_PTHREADS) \\\n         || defined(__native_client__))                           \\\n        && !defined(GC_NO_PTHREAD_SIGMASK)\n/* Either there is no `pthread_sigmask()` or no need to intercept it. */\n#      define GC_NO_PTHREAD_SIGMASK\n#    endif\n\n#    if defined(__native_client__)\n/*\n * At present, NaCl `pthread_create()` prototype does not have\n * `const` for its `attr` argument; also, NaCl `pthread_exit()` one\n * does not have `noreturn` attribute.\n */\n#      ifndef GC_PTHREAD_CREATE_CONST\n#        define GC_PTHREAD_CREATE_CONST /*< empty */\n#      endif\n#      ifndef GC_HAVE_PTHREAD_EXIT\n#        define GC_HAVE_PTHREAD_EXIT\n#        define GC_PTHREAD_EXIT_ATTRIBUTE /*< empty */\n#      endif\n#    endif\n\n#    if !defined(GC_HAVE_PTHREAD_EXIT)                           \\\n        && ((defined(GC_LINUX_THREADS) && !defined(HOST_ANDROID) \\\n             && !defined(__ANDROID__))                           \\\n            || defined(GC_SOLARIS_THREADS) || defined(__COSMOPOLITAN__))\n/* Intercept `pthread_exit()` where available and needed. */\n#      define GC_HAVE_PTHREAD_EXIT\n#      define GC_PTHREAD_EXIT_ATTRIBUTE GC_ATTR_NORETURN\n#    endif\n\n#    if (!defined(GC_HAVE_PTHREAD_EXIT) || defined(__native_client__)) \\\n        && !defined(GC_NO_PTHREAD_CANCEL)\n/* Either there is no `pthread_cancel()` or no need to intercept it. */\n#      define GC_NO_PTHREAD_CANCEL\n#    endif\n\n#  endif /* GC_PTHREADS */\n\n#  ifdef __cplusplus\n\n#    ifndef GC_ATTR_EXPLICIT\n#      if __cplusplus >= 201103L && !defined(__clang__) \\\n          || _MSVC_LANG >= 201103L || defined(CPPCHECK)\n#        define GC_ATTR_EXPLICIT explicit\n#      else\n#        define GC_ATTR_EXPLICIT /*< empty */\n#      endif\n#    endif\n\n#    ifndef GC_NOEXCEPT\n#      if defined(__DMC__)                                  \\\n          || (defined(__BORLANDC__)                         \\\n              && (defined(_RWSTD_NO_EXCEPTIONS)             \\\n                  || defined(_RWSTD_NO_EX_SPEC)))           \\\n          || (defined(_MSC_VER) && defined(_HAS_EXCEPTIONS) \\\n              && !_HAS_EXCEPTIONS)                          \\\n          || (defined(__WATCOMC__) && !defined(_CPPUNWIND))\n#        define GC_NOEXCEPT /*< empty */\n#        ifndef GC_NEW_ABORTS_ON_OOM\n#          define GC_NEW_ABORTS_ON_OOM\n#        endif\n#      elif __cplusplus >= 201103L || _MSVC_LANG >= 201103L\n#        define GC_NOEXCEPT noexcept\n#      else\n#        define GC_NOEXCEPT throw()\n#      endif\n#    endif\n\n#    ifndef GC_CONSTEXPR\n#      if __cplusplus >= 202002L\n#        define GC_CONSTEXPR constexpr\n#      else\n#        define GC_CONSTEXPR /*< empty */\n#      endif\n#    endif\n\n#  endif /* __cplusplus */\n\n#endif\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/gc_disclaim.h",
    "content": "/*\n * Copyright (c) 2007-2011 by Hewlett-Packard Company. All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n#ifndef GC_DISCLAIM_H\n#define GC_DISCLAIM_H\n\n#include \"gc.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * This API is defined only if the library has been suitably compiled\n * (i.e. with `ENABLE_DISCLAIM` macro defined).\n */\n\n/**\n * Prepare the object kind used by `GC_finalized_malloc`.  Call it from\n * your initialization code or, at least, at some point before using\n * finalized allocations.  The function is thread-safe.\n */\nGC_API void GC_CALL GC_init_finalized_malloc(void);\n\n/** Type of a disclaim callback.  Called with the allocator lock held. */\ntypedef int(GC_CALLBACK *GC_disclaim_proc)(void * /* `obj` */);\n\n/**\n * Register `proc` to be called on each object (of given `kind`) ready\n * to be reclaimed.  If `proc()` returns a nonzero value, the\n * collector will not reclaim the object on this collection cycle\n * (`proc()` should not try to resurrect the object otherwise); objects\n * reachable from `proc()` (including the referred closure object) will\n * be protected from collection if `mark_from_all` is nonzero, but at\n * the expense that long chains of objects will take many cycles to\n * reclaim.  Any call to `GC_free()` deallocates the object (pointed by\n * the argument) without inquiring `proc()`.  Acquires the allocator lock.\n * No-op in the find-leak mode.\n */\nGC_API void GC_CALL GC_register_disclaim_proc(int /* `kind` */,\n                                              GC_disclaim_proc /* `proc` */,\n                                              int /* `mark_from_all` */);\n\n/** The finalizer closure used by `GC_finalized_malloc`. */\nstruct GC_finalizer_closure {\n  GC_finalization_proc proc;\n  void *cd;\n};\n\n/**\n * Allocate an object which is to be finalized by the given closure.\n * This uses a dedicated object kind with a disclaim procedure, and\n * is more efficient than `GC_register_finalizer` and friends.\n * `GC_init_finalized_malloc` must be called before using this.\n * The collector will reclaim the object during this collection cycle\n * (thus, `fc->proc()` should not try to resurrect the object).\n * The other objects reachable from `fc->proc()` (including the closure\n * object in case it is a heap-allocated one) will be protected from\n * collection.  Note that `GC_size()` (applied to such allocated object)\n * returns a value slightly bigger than the specified allocation size,\n * and that `GC_base()` result points to a \"pointer-sized\" word prior\n * to the start of the allocated object.\n * The disclaim procedure is not invoked in the find-leak mode.\n * There is no debugging variant of this allocation function.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_finalized_malloc(size_t /* `size` */,\n                        const struct GC_finalizer_closure * /* `fc` */)\n        GC_ATTR_NONNULL(2);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/gc_gcj.h",
    "content": "/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.\n * Copyright 1996-1999 by Silicon Graphics.  All rights reserved.\n * Copyright 1999 by Hewlett-Packard Company.  All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * This file assumes the collector has been compiled with `GC_GCJ_SUPPORT`\n * macro defined.\n */\n\n/*\n * We allocate objects whose first element contains a pointer to a structure\n * describing the object type.  This structure contains a garbage collector\n * mark descriptor at offset `GC_GCJ_MARK_DESCR_OFFSET`.\n * Alternatively, the objects may be marked by the mark procedure passed\n * to `GC_init_gcj_malloc_mp()`.\n */\n\n#ifndef GC_GCJ_H\n#define GC_GCJ_H\n\n#ifndef GC_H\n#  include \"gc.h\"\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * The offset of the garbage collector mark descriptor inside the\n * structure describing the object type (\"vtable\").  `gcj` keeps the\n * mark descriptor as the second \"pointer-sized\" word of \"vtable\".\n * Probably this needs to be adjusted for other clients.  It is assumed\n * that this offset is not smaller than the size of a pointer (the\n * assumption allows objects on the free list to be marked normally).\n */\n#ifndef GC_GCJ_MARK_DESCR_OFFSET\n#  define GC_GCJ_MARK_DESCR_OFFSET GC_SIZEOF_PTR\n#endif\n\n/**\n * This function must be called before the `gcj` allocators are invoked.\n * `mp_index` and `mp` are the index and mark procedure (see `gc_mark.h`\n * file), respectively, for the allocated objects.  `mp` will be used to\n * build the descriptor for objects allocated through the debugging\n * interface; it will be invoked on all such objects with an `env` value\n * of 1.  The client may choose to use the same mark procedure (`mp`) for\n * some of its generated mark descriptors.  In that case, it should use\n * a different `env` value to detect the presence or absence of the debug\n * header.  `mp` is really of type `GC_mark_proc`, as defined in `gc_mark.h`\n * file; we do not want to include that here for namespace pollution reasons.\n * Passing in `mp_index` here instead of having `GC_init_gcj_malloc()`\n * internally call `GC_new_proc()` is quite ugly, but in typical usage\n * scenarios a compiler also has to know about `mp_index`, so generating it\n * dynamically is not acceptable.  The `mp_index` will typically be\n * an integer less than `RESERVED_MARK_PROCS`, so that it does not collide\n * with indices allocated by `GC_new_proc()`.  If the application needs\n * no other reserved indices, zero (`GC_GCJ_RESERVED_MARK_PROC_INDEX` in\n * `gc_mark.h` file) is an obvious choice.  Deprecated, portable clients\n * should include `gc_mark.h` file and use `GC_init_gcj_malloc_mp()` instead.\n */\nGC_API GC_ATTR_DEPRECATED void GC_CALL GC_init_gcj_malloc(int /* `mp_index` */,\n                                                          void * /* `mp` */);\n\n/**\n * Allocate an object, clear it, and store the pointer to the type\n * structure (\"vtable\" in `gcj`).  This adds a byte at the end of the\n * object if `GC_malloc()` would.  In case of out of memory,\n * `GC_oom_fn()` is called and its result is returned.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_gcj_malloc(size_t /* `lb` */, const void * /* `vtable_ptr` */);\n\n/**\n * Similar to `GC_gcj_malloc`, but add the debug info.  This is allocated\n * with `GC_gcj_debug_kind`.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_debug_gcj_malloc(size_t /* `lb` */, const void * /* `vtable_ptr` */,\n                        GC_EXTRA_PARAMS);\n\n/**\n * Similar to `GC_gcj_malloc`, but assumes that a pointer to near the\n * beginning (i.e. within the first heap block) of the allocated object\n * is always maintained.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_gcj_malloc_ignore_off_page(size_t /* `lb` */,\n                                  const void * /* `vtable_ptr` */);\n\n/**\n * The kind numbers of normal and debug `gcj` objects.  Useful only for\n * debug support, we hope.\n */\nGC_API int GC_gcj_kind;\nGC_API int GC_gcj_debug_kind;\n\n#ifdef GC_DEBUG\n#  define GC_GCJ_MALLOC(s, d) GC_debug_gcj_malloc(s, d, GC_EXTRAS)\n#  define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s, d) GC_GCJ_MALLOC(s, d)\n#else\n#  define GC_GCJ_MALLOC(s, d) GC_gcj_malloc(s, d)\n#  define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s, d) \\\n    GC_gcj_malloc_ignore_off_page(s, d)\n#endif\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#endif /* GC_GCJ_H */\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/gc_inline.h",
    "content": "/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 2005 Hewlett-Packard Development Company, L.P.\n * Copyright (c) 2008-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n#ifndef GC_INLINE_H\n#define GC_INLINE_H\n\n/*\n * *Warning*: Note that for these routines, it is the client`s responsibility\n * to add the extra byte at the end to deal with one-past-the-end pointers.\n * In the standard collector configuration, the collector assumes that such\n * a byte has been added, and hence does not trace the last \"pointer-sized\"\n * word in the resulting object.  This is not an issue if\n * `GC_get_all_interior_pointers()` returns zero or if\n * `GC_get_dont_add_byte_at_end()` returns 1.  This interface is most useful\n * for compilers that generate C code.  It is also used internally for\n * thread-local allocation.  A manual use is hereby discouraged.\n * Multi-threaded clients should include `atomic_ops.h` file (or similar)\n * before this header.  There is no debugging variant of this allocation API.\n */\n\n#include \"gc.h\"\n#include \"gc_tiny_fl.h\"\n\n#if GC_GNUC_PREREQ(3, 0) || defined(__clang__)\n/* Equivalent to `(expr)`, but predict that usually `expr == outcome`. */\n#  define GC_EXPECT(expr, outcome) __builtin_expect(expr, outcome)\n#else\n#  define GC_EXPECT(expr, outcome) (expr)\n#endif\n\n#ifndef GC_ASSERT\n#  ifdef NDEBUG\n#    define GC_ASSERT(expr) (void)0\n#  else\n#    include <assert.h>\n#    define GC_ASSERT(expr) assert(expr)\n#  endif\n#endif\n\n#ifndef GC_PREFETCH_FOR_WRITE\n#  if (GC_GNUC_PREREQ(3, 0) || defined(__clang__)) \\\n      && !defined(GC_NO_PREFETCH_FOR_WRITE)\n#    define GC_PREFETCH_FOR_WRITE(x) __builtin_prefetch((x), 1 /* write */)\n#  elif defined(_MSC_VER) && !defined(GC_NO_PREFETCH_FOR_WRITE)         \\\n      && (defined(_M_IX86) || defined(_M_X64)) && !defined(_CHPE_ONLY_) \\\n      && (_MSC_VER >= 1900 /* VS 2015+ */)\n#    include <intrin.h>\n#    define GC_PREFETCH_FOR_WRITE(x) _m_prefetchw(x)\n/* TODO: Support also `_M_ARM` (`__prefetchw`). */\n#  else\n#    define GC_PREFETCH_FOR_WRITE(x) (void)0\n#  endif\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Object kinds (exposed to public). */\n#define GC_I_PTRFREE 0\n#define GC_I_NORMAL 1\n\n/**\n * Determine if the collector has been configured not to pad the\n * allocated objects even in the all-interior-pointers mode.\n * Meaningful only if `GC_get_all_interior_pointers()` returns 1.\n */\nGC_API int GC_CALL GC_get_dont_add_byte_at_end(void);\n\n/**\n * Return a list of one or more objects of the indicated size, linked\n * through the first pointer in each object.  This has the advantage\n * that it acquires the allocator lock only once, and may greatly\n * reduce time wasted contending for the allocator lock.  Typical usage\n * would be in a thread that requires many items of the same size.\n * It would keep its own free list in a thread-local storage, and call\n * `GC_malloc_many()` or friends to replenish it.  (We do not round up\n * object sizes, since a call indicates the intention to consume many\n * objects of exactly this size.)  We assume that the size is nonzero\n * and a multiple of `GC_GRANULE_BYTES`, and that the size already\n * includes the value returned by `GC_get_all_interior_pointers()`\n * (unless `GC_get_dont_add_byte_at_end()` returns a nonzero value).\n * We return the free-list by assigning it to `*result`, since it is\n * not safe to return a linked list of pointer-free objects, since the\n * collector would not retain the entire list if it were invoked just\n * as we were returning; the client must make sure that `*result` is\n * traced even if objects are pointer-free.  Note also that the client\n * should usually clear the link field.\n */\nGC_API void GC_CALL GC_generic_malloc_many(size_t /* `lb_adjusted` */,\n                                           int /* `kind` */,\n                                           void ** /* `result` */);\n\n/**\n * A generalized variant of `GC_malloc` and `GC_malloc_atomic`.\n * Uses appropriately the thread-local (if available) or the global\n * free-list of the specified `kind`.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_malloc_kind(size_t /* `lb` */, int /* `kind` */);\n\n#ifdef GC_THREADS\n/* Same as `GC_malloc_kind` but uses only the global free-list. */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_malloc_kind_global(size_t /* `lb` */, int /* `kind` */);\n#else\n#  define GC_malloc_kind_global GC_malloc_kind\n#endif\n\n/*\n * An internal macro to update the free-list pointer atomically\n * (if the AO primitives are available) to avoid race with the marker.\n */\n#if !defined(GC_THREADS) || !defined(AO_HAVE_store)\n#  define GC_FAST_M_AO_STORE(my_fl, next) (void)(*(my_fl) = (next))\n#elif defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ > __SIZEOF_SIZE_T__)\n/*\n * Directly use the gcc atomic intrinsic as the size of a pointer is\n * bigger than that of `AO_t`.\n */\n#  define GC_FAST_M_AO_STORE(my_fl, next) \\\n    __atomic_store_n(my_fl, next, __ATOMIC_RELAXED)\n#else\n#  define GC_FAST_M_AO_STORE(my_fl, next) \\\n    AO_store((volatile AO_t *)(my_fl), (size_t)(next))\n#endif\n\n/**\n * The ultimately general inline allocation macro.  Allocate an object\n * of size `lg` (in granules), putting the resulting pointer in `result`.\n * `tiny_fl` is a \"tiny\" free-list array, which will be used first,\n * if the size is appropriate.  If `lg` argument is too large, then we\n * allocate with `default_expr` instead.  If we need to refill the free\n * list, we use `GC_generic_malloc_many()` with the indicated kind `k`.\n * `tiny_fl` should be an array of `GC_TINY_FREELISTS` `void` pointers.\n * If `num_direct` is nonzero, and the individual free-list pointers are\n * initialized to `(void *)1`, then we allocate `num_direct` granules\n * directly using `GC_generic_malloc_many()` before putting multiple\n * objects into the `tiny_fl` entry.  If `num_direct` is zero, then the\n * free lists may also be initialized to `NULL`.  Note that we use the\n * zeroth free list to hold objects of 1 granule in size that are used to\n * satisfy size 0 allocation requests.  We rely on much of this hopefully\n * getting optimized away in the case of `num_direct` is 0.  Particularly,\n * if `lg` argument is constant, this should generate a small amount of code.\n */\n#define GC_FAST_MALLOC_GRANS(result, lg, tiny_fl, num_direct, k,         \\\n                             default_expr, init)                         \\\n  do {                                                                   \\\n    if (GC_EXPECT((lg) >= GC_TINY_FREELISTS, 0)) {                       \\\n      result = (default_expr);                                           \\\n    } else {                                                             \\\n      void **my_fl = (tiny_fl) + (lg);                                   \\\n      void *my_entry = *my_fl;                                           \\\n      void *next;                                                        \\\n                                                                         \\\n      for (;;) {                                                         \\\n        if (GC_EXPECT((GC_word)(GC_uintptr_t)my_entry                    \\\n                          > (num_direct) + GC_TINY_FREELISTS + 1,        \\\n                      1)) {                                              \\\n          next = *(void **)(my_entry);                                   \\\n          result = my_entry;                                             \\\n          GC_FAST_M_AO_STORE(my_fl, next);                               \\\n          init;                                                          \\\n          GC_PREFETCH_FOR_WRITE(next);                                   \\\n          if ((k) != GC_I_PTRFREE) {                                     \\\n            GC_end_stubborn_change(my_fl);                               \\\n            GC_reachable_here(next);                                     \\\n          }                                                              \\\n          GC_ASSERT(GC_size(result) >= GC_RAW_BYTES_FROM_INDEX(lg));     \\\n          GC_ASSERT((k) == GC_I_PTRFREE                                  \\\n                    || 0 /* `NULL` */ == ((void **)result)[1]);          \\\n          break;                                                         \\\n        }                                                                \\\n        /* Entry contains counter or `NULL`. */                          \\\n        if ((GC_signed_word)(GC_uintptr_t)my_entry                       \\\n                    - (GC_signed_word)(num_direct)                       \\\n                <= 0 /*< `(GC_uintptr_t)my_entry <= num_direct` */       \\\n            && my_entry != 0 /* NULL */) {                               \\\n          /* Small counter value, not `NULL`. */                         \\\n          GC_FAST_M_AO_STORE(my_fl, (char *)my_entry + (lg) + 1);        \\\n          result = (default_expr);                                       \\\n          break;                                                         \\\n        } else {                                                         \\\n          /* Large counter or `NULL`. */                                 \\\n          size_t lb_adj = GC_RAW_BYTES_FROM_INDEX(0 == (lg) ? 1 : (lg)); \\\n                                                                         \\\n          GC_generic_malloc_many(lb_adj, k, my_fl);                      \\\n          my_entry = *my_fl;                                             \\\n          if (0 /* `NULL` */ == my_entry) {                              \\\n            result = (*GC_get_oom_fn())(lb_adj);                         \\\n            break;                                                       \\\n          }                                                              \\\n        }                                                                \\\n      }                                                                  \\\n    }                                                                    \\\n  } while (0)\n\n/**\n * Allocate `n` \"pointer-sized\" words.  The allocation size is rounded\n * up to a granule size.  The pointer is stored to `result`.\n * Should not be used unless `GC_get_all_interior_pointers()` returns zero\n * or if `GC_get_dont_add_byte_at_end()` returns 1.  Does not acquire\n * the allocator lock.  The caller is responsible for supplying\n * a cleared `tiny_fl` free-list array.  For single-threaded applications,\n * this may be a global array.\n */\n#define GC_MALLOC_WORDS_KIND(result, n, tiny_fl, k, init)                \\\n  do {                                                                   \\\n    size_t lg = GC_PTRS_TO_WHOLE_GRANULES(n);                            \\\n                                                                         \\\n    GC_FAST_MALLOC_GRANS(result, lg, tiny_fl, 0 /* `num_direct` */, k,   \\\n                         GC_malloc_kind(GC_RAW_BYTES_FROM_INDEX(lg), k), \\\n                         init);                                          \\\n  } while (0)\n\n#define GC_MALLOC_WORDS(result, n, tiny_fl)             \\\n  GC_MALLOC_WORDS_KIND(result, n, tiny_fl, GC_I_NORMAL, \\\n                       (void)(*(void **)(result) = 0 /* `NULL` */))\n\n#define GC_MALLOC_ATOMIC_WORDS(result, n, tiny_fl) \\\n  GC_MALLOC_WORDS_KIND(result, n, tiny_fl, GC_I_PTRFREE, (void)0)\n\n/** Allocate a two-pointer initialized object. */\n#define GC_CONS(result, first, second, tiny_fl)                     \\\n  do {                                                              \\\n    void *l = (void *)(first);                                      \\\n    void *r = (void *)(second);                                     \\\n    GC_MALLOC_WORDS_KIND(result, 2, tiny_fl, GC_I_NORMAL, (void)0); \\\n    if ((result) != 0 /* `NULL` */) {                               \\\n      *(void **)(result) = l;                                       \\\n      GC_ptr_store_and_dirty((void **)(result) + 1, r);             \\\n      GC_reachable_here(l);                                         \\\n    }                                                               \\\n  } while (0)\n\n/**\n * Print address of each object in the free list for the given `kind`\n * and size `lg` (in granules).  The caller should hold the allocator\n * lock at least in the reader mode.  Defined only if the library has\n * been compiled without `NO_DEBUGGING` macro defined.\n */\nGC_API void GC_CALL GC_print_free_list(int /* `kind` */, size_t /* `lg` */);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#endif /* !GC_INLINE_H */\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/gc_mark.h",
    "content": "/*\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 2001 by Hewlett-Packard Company. All rights reserved.\n * Copyright (c) 2009-2025 Ivan Maidanski\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * This contains interfaces to the garbage collector marker that are likely\n * to be useful to clients that provide detailed heap layout information\n * to the collector.  This interface should not be used by normal C or C++\n * clients.  It will be useful to runtimes for other languages.\n *\n * This is an experts-only interface!  There are many ways to break the\n * collector in subtle ways by using this functionality.\n */\n#ifndef GC_MARK_H\n#define GC_MARK_H\n\n#ifndef GC_H\n#  include \"gc.h\"\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define GC_PROC_BYTES 100\n\n#if defined(GC_BUILD) || defined(NOT_GCBUILD)\nstruct GC_ms_entry;\nstruct GC_hblk_s;\n#else\nstruct GC_ms_entry {\n  void *opaque;\n};\nstruct GC_hblk_s {\n  void *opaque;\n};\n#endif\n\n/**\n * A client-supplied mark procedure.  Returns new mark stack pointer.\n * Primary effect should be to push new entries on the mark stack.\n * Mark stack pointer values are passed and returned explicitly.\n * Global variables describing mark stack are not necessarily valid.\n * (This usually saves a few cycles by keeping things in registers.)\n * Assumed to scan about `GC_PROC_BYTES` on average.  If it needs to do\n * much more work than that, it should do it in smaller pieces by\n * pushing itself back on the mark stack.  Note that it should always\n * do some work (defined as \"marking some objects\") before pushing more\n * than one entry on the mark stack.  This is required to ensure\n * termination in the event of mark stack overflows.  This procedure is\n * always called with at least one empty entry on the mark stack.\n * Currently we require that mark procedures look for pointers in\n * a subset of the places the conservative marker would.  It must be safe\n * to invoke the normal mark procedure instead.\n *\n * *Warning*: Such a mark procedure may be invoked on an unused object\n * residing on a free list.  Such objects are cleared, except for a\n * free-list link field (which is located at the beginning of each\n * object).  Thus mark procedures may not count on the presence of a\n * type descriptor, and must handle this case correctly somehow.  Also,\n * a mark procedure should be prepared to be executed concurrently from\n * the marker threads (the latter ones are created only if the client\n * has called `GC_start_mark_threads()` or started a user thread\n * previously).  For the compatibility reason, `addr` is a pointer to\n * `GC_word`, but it should be treated as a pointer to `void` pointer.\n */\ntypedef struct GC_ms_entry *(GC_CALLBACK *GC_mark_proc)(\n    GC_word * /* `addr` */, struct GC_ms_entry * /* `mark_stack_top` */,\n    struct GC_ms_entry * /* `mark_stack_limit` */, GC_word /* `env` */);\n\n#define GC_LOG_MAX_MARK_PROCS 6\n#define GC_MAX_MARK_PROCS (1 << GC_LOG_MAX_MARK_PROCS)\n\n/*\n * In a few cases it is necessary to assign statically known indices to\n * certain mark procedures.  Thus we reserve a few for well known clients.\n * (This is necessary if mark descriptors are compiler generated.)\n */\n#define GC_RESERVED_MARK_PROCS 8\n#define GC_GCJ_RESERVED_MARK_PROC_INDEX 0\n\n/*\n * Object descriptors on mark stack or in objects.  Low-order two bits are\n * tags distinguishing among the following 4 possibilities for the rest\n * (high-order) bits.\n */\n#define GC_DS_TAG_BITS 2\n#define GC_DS_TAGS ((1U << GC_DS_TAG_BITS) - 1)\n\n/**\n * The entire descriptor is a length in bytes that must be a multiple of 4.\n */\n#define GC_DS_LENGTH 0\n\n/**\n * The high-order bits are describing pointer fields.  The most\n * significant bit is set if the first \"pointer-sized\" word is a pointer.\n * (This unconventional ordering sometimes makes the marker slightly faster.)\n * Zeros indicate definite non-pointers; ones indicate possible pointers.\n * *Note*: only usable if pointers are aligned on the size of a pointer (thus,\n * extra care should be taken by client on cris and m68k architectures).\n */\n#define GC_DS_BITMAP 1\n\n/**\n * The objects referenced by this object can be pushed on the mark stack by\n * invoking `PROC(descr)`.  `ENV(descr)` is passed as the last argument.\n */\n#define GC_DS_PROC 2\n\n/**\n * The real descriptor is at the byte displacement from the beginning\n * of the object given by `descr & ~GC_DS_TAGS`.  If the descriptor is\n * negative, the real descriptor is at\n * `*<object_start> - (descr & ~GC_DS_TAGS) - GC_INDIR_PER_OBJ_BIAS`.\n * The latter alternative can be used if each object contains a type\n * descriptor at the beginning of the object.  Note that in the\n * multi-threaded environments per-object descriptors must be located\n * in either the first two or last two \"pointer-sized\" words of the\n * object, since only those are guaranteed to be cleared while the\n * allocator lock is held.\n */\n#define GC_DS_PER_OBJECT 3\n\n#define GC_INDIR_PER_OBJ_BIAS 0x10\n\n#define GC_MAKE_PROC(proc_index, env)                                      \\\n  ((((((GC_word)(env)) << GC_LOG_MAX_MARK_PROCS) | (unsigned)(proc_index)) \\\n    << GC_DS_TAG_BITS)                                                     \\\n   | (GC_word)GC_DS_PROC)\n\n/**\n * Bounds on the heap.  Guaranteed to be valid.  Likely to include future\n * heap expansion.  Hence the bounded range usually includes not-yet-mapped\n * memory, or might overlap with other data roots.  The address of any heap\n * object is larger than `GC_least_plausible_heap_addr` and less than\n * `GC_greatest_plausible_heap_addr`.\n */\nGC_API void *GC_least_plausible_heap_addr;\nGC_API void *GC_greatest_plausible_heap_addr;\n\n/**\n * Specify the pointer address mask.  Works only if the collector is\n * built with `DYNAMIC_POINTER_MASK` macro defined.  These primitives\n * are normally needed only to support systems that use high-order\n * pointer tags.  The setter is expected to be called, if needed,\n * before the collector initialization or, at least, before the first\n * object is allocated.  Both the setter and the getter are unsynchronized.\n */\nGC_API void GC_CALL GC_set_pointer_mask(GC_word);\nGC_API GC_word GC_CALL GC_get_pointer_mask(void);\n\n/**\n * Similar to `GC_set_pointer_mask`/`GC_get_pointer_mask` but for the\n * pointer address shift.  The value should be less than the size of\n * `GC_word`, in bits.  Applied after the mask.\n */\nGC_API void GC_CALL GC_set_pointer_shift(unsigned);\nGC_API unsigned GC_CALL GC_get_pointer_shift(void);\n\n/**\n * Handle nested references in a custom mark procedure.\n * Check if `obj` is a valid object.  If so, ensure that it is marked.\n * If it was not previously marked, push its contents onto the mark\n * stack for future scanning.  The object will then be scanned using\n * its mark descriptor.  Returns the new mark stack pointer.\n * Handles mark stack overflows correctly.  Since this marks first, it\n * makes progress even if there are mark stack overflows.\n * `src` is the address of the pointer to `obj`, which is used only\n * for back pointer-based heap debugging.\n * It is strongly recommended that most objects be handled without mark\n * procedures, e.g. with bitmap descriptors, and that mark procedures\n * be reserved for the exceptional cases.  That will ensure that\n * performance of this call is not extremely performance critical.\n * (Otherwise we would need to inline `GC_mark_and_push` completely,\n * which would tie the client code to a fixed collector version.)\n * Note that mark procedures should explicitly call `FIXUP_POINTER()`\n * if required.\n */\nGC_API struct GC_ms_entry *GC_CALL GC_mark_and_push(\n    void * /* `obj` */, struct GC_ms_entry * /* `mark_stack_top` */,\n    struct GC_ms_entry * /* `mark_stack_limit` */, void ** /* `src` */);\n\n#define GC_MARK_AND_PUSH(obj, msp, lim, src)                       \\\n  (GC_ADDR_LT((char *)GC_least_plausible_heap_addr, (char *)(obj)) \\\n           && GC_ADDR_LT((char *)(obj),                            \\\n                         (char *)GC_greatest_plausible_heap_addr)  \\\n       ? GC_mark_and_push(obj, msp, lim, src)                      \\\n       : (msp))\n\nGC_API void GC_CALL GC_push_proc(GC_word /* `descr` */, void * /* `obj` */);\n\nGC_API struct GC_ms_entry *GC_CALL\nGC_custom_push_proc(GC_word /* `descr` */, void * /* `obj` */,\n                    struct GC_ms_entry * /* `mark_stack_top` */,\n                    struct GC_ms_entry * /* `mark_stack_limit` */);\n\nGC_API struct GC_ms_entry *GC_CALL\nGC_custom_push_range(void * /* `bottom` */, void * /* `top` */,\n                     struct GC_ms_entry * /* `mark_stack_top` */,\n                     struct GC_ms_entry * /* `mark_stack_limit` */);\n\n/**\n * The size of the header added to objects allocated through the `GC_debug_`\n * routines.  Defined as a function so that client mark procedures do not\n * need to be recompiled for the collector library version changes.\n */\nGC_API GC_ATTR_CONST size_t GC_CALL GC_get_debug_header_size(void);\n#define GC_USR_PTR_FROM_BASE(p) \\\n  ((void *)((char *)(p) + GC_get_debug_header_size()))\n\n/*\n * The same as `GC_get_debug_header_size()` but defined as a variable.\n * Exists only for the backward compatibility.  Some compilers do not\n * accept `const` together with `deprecated` or `dllimport` attributes,\n * so the symbol is exported as a non-constant one.\n */\nGC_API GC_ATTR_DEPRECATED\n#ifdef GC_BUILD\n    const\n#endif\n        size_t GC_debug_header_size;\n\n/**\n * Return the heap block size.  Each heap block is devoted to a single size\n * and kind of object.\n */\nGC_API GC_ATTR_CONST size_t GC_CALL GC_get_hblk_size(void);\n\ntypedef void(GC_CALLBACK *GC_walk_hblk_fn)(struct GC_hblk_s *,\n                                           void * /* `client_data` */);\n\n/**\n * Apply `fn` to each allocated heap block.  It is the responsibility\n * of the caller to avoid data race during the function execution\n * (e.g. by acquiring the allocator lock at least in the reader mode).\n */\nGC_API void GC_CALL GC_apply_to_all_blocks(GC_walk_hblk_fn,\n                                           void * /* `client_data` */)\n    GC_ATTR_NONNULL(1);\n\n/* Same as `GC_walk_hblk_fn` but with index of the free list. */\ntypedef void(GC_CALLBACK *GC_walk_free_blk_fn)(struct GC_hblk_s *,\n                                               int /* `index` */,\n                                               void * /* `client_data` */);\n\n/**\n * Apply `fn` to each completely empty heap block.  It is the responsibility\n * of the caller to avoid data race during the function execution (e.g. by\n * acquiring the allocator lock at least in the reader mode).\n */\nGC_API void GC_CALL GC_iterate_free_hblks(GC_walk_free_blk_fn,\n                                          void * /* `client_data` */)\n    GC_ATTR_NONNULL(1);\n\n/**\n * If there are likely to be false references to a block starting at\n * `h` of the indicated length (`len`), then return the next plausible\n * starting location for `h` that might avoid these false references.\n * (In other words: Is the block starting at `h` of size `len` bytes\n * black-listed?  If so, then return the address of the next plausible\n * `r` such that (`r`,`len`) might not be black-listed.  Note that\n * pointer `r` may not actually be in the heap, we guarantee only that\n * every smaller value of `r` after `h` is also black-listed.)\n * Otherwise `NULL` is returned.  Assumes the allocator lock is held at\n * least in the reader mode, but no assertion about it by design.\n */\nGC_API struct GC_hblk_s *GC_CALL\nGC_is_black_listed(struct GC_hblk_s * /* `h` */, size_t /* `len` */);\n\n/**\n * Return the number of set mark bits for the heap block where object `p`\n * is located.  Defined only if the library has been compiled without\n * `NO_DEBUGGING` macro defined.\n */\nGC_API unsigned GC_CALL GC_count_set_marks_in_hblk(const void * /* `p` */);\n\n/*\n * And some routines to support creation of new \"kinds\", e.g. with custom\n * mark procedures, by language runtimes.  The `_inner` variants assume\n * the caller holds the allocator lock.\n */\n\n/** Return a new free-list array. */\nGC_API void **GC_CALL GC_new_free_list(void);\nGC_API void **GC_CALL GC_new_free_list_inner(void);\n\n/**\n * Return a new kind, as specified.  The last two parameters must be zero\n * or one.\n */\nGC_API unsigned GC_CALL GC_new_kind(void ** /* `free_list` */,\n                                    GC_word /* `mark_descriptor_template` */,\n                                    int /* `add_size_to_descriptor` */,\n                                    int /* `clear_new_objects` */)\n    GC_ATTR_NONNULL(1);\nGC_API unsigned GC_CALL GC_new_kind_inner(\n    void ** /* `free_list` */, GC_word /* `mark_descriptor_template` */,\n    int /* `add_size_to_descriptor` */, int /* `clear_new_objects` */)\n    GC_ATTR_NONNULL(1);\n\n/**\n * Return a new mark procedure identifier, suitable for use as the first\n * argument in `GC_MAKE_PROC()`.\n */\nGC_API unsigned GC_CALL GC_new_proc(GC_mark_proc);\nGC_API unsigned GC_CALL GC_new_proc_inner(GC_mark_proc);\n\n/**\n * Similar to `GC_init_gcj_malloc()` described in `gc_gcj.h` file but with\n * the proper types of the arguments and an additional runtime checking.\n * `GC_GCJ_MARK_DESCR_OFFSET` should be passed to `descr_offset` argument.\n * Defined only if the library has been compiled with `GC_GCJ_SUPPORT`\n * macro defined.\n */\nGC_API void GC_CALL GC_init_gcj_malloc_mp(unsigned /* `mp_index` */,\n                                          GC_mark_proc /* `mp` */,\n                                          size_t /* `descr_offset` */);\n\n/**\n * Allocate an object of a given `kind`.  By default, there are only\n * a few kinds: composite (pointerful), atomic, uncollectible, etc.\n * We claim it is possible for clever client code that understands the\n * collector internals to add more, e.g. to communicate object layout\n * information to the collector.  Note that in the multi-threaded\n * contexts, this is usually unsafe for kinds that have the descriptor\n * in the object itself, since there is otherwise a window in which\n * the descriptor is not correct.  Even in the single-threaded case,\n * we need to be sure that cleared objects on a free list do not cause\n * a GC crash if they are accidentally traced.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_generic_malloc(size_t /* `lb` */, int /* `kind` */);\n\n/**\n * Same as `GC_generic_malloc()`, but pointers to past the first heap block\n * of the resulting object are ignored.  We avoid holding the allocator lock\n * while we clear the memory.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_generic_malloc_ignore_off_page(size_t /* `lb` */, int /* `kind` */);\n\n/**\n * A generalized variant of `GC_malloc_uncollectable()` and\n * `GC_malloc_atomic_uncollectable()`.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_generic_malloc_uncollectable(size_t /* `lb` */, int /* `kind` */);\n\n/**\n * Same as `GC_generic_malloc()`, but primary for allocating an object\n * of the same kind as an existing one (`kind` obtained by\n * `GC_get_kind_and_size()`).  Not suitable for `gcj` and typed-`malloc`\n * kinds.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_generic_or_special_malloc(size_t /* `size` */, int /* `kind` */);\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_debug_generic_or_special_malloc(size_t /* `size` */, int /* `kind` */,\n                                       GC_EXTRA_PARAMS);\n\n#ifdef GC_DEBUG\n#  define GC_GENERIC_OR_SPECIAL_MALLOC(sz, k) \\\n    GC_debug_generic_or_special_malloc(sz, k, GC_EXTRAS)\n#else\n#  define GC_GENERIC_OR_SPECIAL_MALLOC(sz, k) \\\n    GC_generic_or_special_malloc(sz, k)\n#endif /* !GC_DEBUG */\n\n/**\n * Similar to `GC_size` but returns object kind.  The size is returned too\n * if `psize` is not `NULL`.  The object pointer should be non-`NULL`.\n */\nGC_API int GC_CALL GC_get_kind_and_size(const void *, size_t * /* `psize` */)\n    GC_ATTR_NONNULL(1);\n\n/**\n * A procedure which produces a human-readable description of the\n * \"type\" of object `p` into the buffer `out_buf` of length\n * `GC_TYPE_DESCR_LEN`.  This is used by the debug support when\n * printing objects.  These functions should be as robust as possible,\n * though we do avoid invoking them on objects on the global free list.\n */\ntypedef void(GC_CALLBACK *GC_describe_type_fn)(void * /* `p` */,\n                                               char * /* `out_buf` */);\n#define GC_TYPE_DESCR_LEN 40\n\n/**\n * Register a `describe_type` function to be used when printing objects\n * of a particular `kind`.\n */\nGC_API void GC_CALL GC_register_describe_type_fn(int /* `kind` */,\n                                                 GC_describe_type_fn);\n\n/**\n * Clear some of the inaccessible part of the stack.  Returns its argument,\n * so it can be used in a tail call position, hence clearing another frame.\n * The argument may be `NULL`.\n */\nGC_API void *GC_CALL GC_clear_stack(void *);\n\n/**\n * Set/get the client notifier on collections.  The client-supplied procedure\n * is called at the start of every full collection (called with the allocator\n * lock held).  May be 0.  This is a really tricky interface to use correctly.\n * Unless you really understand the collector internals, the callback should\n * not, directly or indirectly, make any `GC_` or potentially blocking calls.\n * In particular, it is not safe to allocate memory using the collector from\n * within the callback procedure.  Both the setter and the getter acquire the\n * allocator lock (in the reader mode in case of the getter).\n */\ntypedef void(GC_CALLBACK *GC_start_callback_proc)(void);\nGC_API void GC_CALL GC_set_start_callback(GC_start_callback_proc);\nGC_API GC_start_callback_proc GC_CALL GC_get_start_callback(void);\n\n/**\n * Slow/general mark bit manipulation.  The caller should hold the\n * allocator lock.  The argument should be the real address of an object\n * (i.e. the address of the debug header if there is one).\n */\nGC_API void GC_CALL GC_clear_mark_bit(const void *) GC_ATTR_NONNULL(1);\nGC_API void GC_CALL GC_set_mark_bit(const void *) GC_ATTR_NONNULL(1);\n\n/**\n * Get the mark bit.  Returns 1 (true) or 0.  The caller should hold the\n * allocator lock at least in the reader mode.  The argument should be\n * the real address of an object (i.e. the address of the debug header\n * if there is one).\n */\nGC_API int GC_CALL GC_is_marked(const void *) GC_ATTR_NONNULL(1);\n\n/**\n * Push everything in the given range onto the mark stack.  `bottom` is\n * the first location to be scanned; `top` is one past the last location\n * to be scanned.  Should only be used if there is no possibility of mark\n * stack overflow.\n */\nGC_API void GC_CALL GC_push_all(void * /* `bottom` */, void * /* `top` */);\n\n/**\n * Similar to `GC_push_all` but treats all interior pointers as valid and\n * scans the entire region immediately (not just schedules it for scanning),\n * in case the contents change.\n */\nGC_API void GC_CALL GC_push_all_eager(void * /* `bottom` */,\n                                      void * /* `top` */);\n\n/**\n * Similar to `GC_push_all` but processes either all or only dirty pages\n * depending on `all` argument.\n */\nGC_API void GC_CALL GC_push_conditional(void * /* `bottom` */,\n                                        void * /* `top` */,\n                                        int /* `bool` `all` */);\n\nGC_API void GC_CALL GC_push_finalizer_structures(void);\n\n/**\n * Set/get the client push-other-roots procedure.  A client-supplied\n * procedure should also call the original one.  Note that both the setter\n * and the getter require some external synchronization to avoid data race.\n */\ntypedef void(GC_CALLBACK *GC_push_other_roots_proc)(void);\nGC_API void GC_CALL GC_set_push_other_roots(GC_push_other_roots_proc);\nGC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void);\n\n/**\n * Walk the GC heap visiting all reachable objects.  Assume the caller\n * holds the allocator lock at least in the reader mode.  Object base\n * pointer, object size and client custom data are passed to the callback\n * (holding the allocator lock in the same mode as the caller does).\n */\ntypedef void(GC_CALLBACK *GC_reachable_object_proc)(\n    void * /* `obj` */, size_t /* `bytes` */, void * /* `client_data` */);\nGC_API void GC_CALL GC_enumerate_reachable_objects_inner(\n    GC_reachable_object_proc, void * /* `client_data` */) GC_ATTR_NONNULL(1);\n\n/**\n * Is the given address in one of the temporary static root sections?\n * Acquires the allocator lock in the reader mode.  For the debugging\n * purpose only.\n */\nGC_API int GC_CALL GC_is_tmp_root(void *);\n\nGC_API void GC_CALL GC_print_trace(GC_word /* `gc_no` */);\nGC_API void GC_CALL GC_print_trace_inner(GC_word /* `gc_no` */);\n\n/**\n * Set the client for when mark stack is empty.  A client can use this\n * callback to process (un)marked objects and push additional work onto\n * the stack.  Useful for implementing ephemerons.  Both the setter and\n * the getter acquire the allocator lock (in the reader mode in case of\n * the getter).\n */\ntypedef struct GC_ms_entry *(GC_CALLBACK *GC_on_mark_stack_empty_proc)(\n    struct GC_ms_entry * /* `mark_stack_top` */,\n    struct GC_ms_entry * /* `mark_stack_limit` */);\nGC_API void GC_CALL GC_set_on_mark_stack_empty(GC_on_mark_stack_empty_proc);\nGC_API GC_on_mark_stack_empty_proc GC_CALL GC_get_on_mark_stack_empty(void);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#endif /* GC_MARK_H */\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/gc_pthread_redirects.h",
    "content": "/*\n * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.\n * Copyright (c) 2000-2010 by Hewlett-Packard Development Company.\n * All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * The collector `pthreads` support normally needs to intercept a number\n * of thread calls.  We arrange to do that here, if appropriate.\n */\n\n#ifndef GC_PTHREAD_REDIRECTS_H\n#define GC_PTHREAD_REDIRECTS_H\n\n/*\n * Included from `gc.h` file only.  Included only if `GC_PTHREADS` macro\n * is defined.\n */\n#if defined(GC_H) && defined(GC_PTHREADS)\n\n/*\n * We need to intercept calls to many of the threads' primitives, so\n * that we can locate thread stacks and stop the world.\n *\n * Note also that the collector cannot always see thread-specific data.\n * Such data should generally consist of pointers to uncollectible\n * objects (allocated with `GC_malloc_uncollectable`, not the system\n * `malloc`), which are deallocated using the destructor facility in\n * `pthread_key_create()`.  Alternatively, keep a redundant pointer\n * to thread-specific data on the thread stack.\n */\n\n#  ifndef GC_PTHREAD_REDIRECTS_ONLY\n\n#    include <pthread.h>\n#    ifndef GC_NO_DLOPEN\n#      include <dlfcn.h>\n#    endif\n#    ifndef GC_NO_PTHREAD_SIGMASK\n/* This is needed anyway for proper redirection. */\n#      include <signal.h>\n#    endif\n\n#    ifdef __cplusplus\nextern \"C\" {\n#    endif\n\n#    ifndef GC_SUSPEND_THREAD_ID\n#      define GC_SUSPEND_THREAD_ID pthread_t\n#    endif\n\n#    ifndef GC_NO_DLOPEN\nGC_API void *GC_dlopen(const char * /* `path` */, int /* `mode` */);\n#    endif\n\n#    ifndef GC_NO_PTHREAD_SIGMASK\n#      if defined(GC_PTHREAD_SIGMASK_NEEDED) || defined(__COSMOPOLITAN__) \\\n          || defined(GC_HAVE_PTHREAD_SIGMASK) || defined(_BSD_SOURCE)     \\\n          || defined(_GNU_SOURCE) || defined(_NETBSD_SOURCE)              \\\n          || (_POSIX_C_SOURCE >= 199506L) || (_XOPEN_SOURCE >= 500)       \\\n          || (__POSIX_VISIBLE >= 199506) /*< xBSD internal macro */\n\nGC_API int GC_pthread_sigmask(int /* `how` */, const sigset_t *,\n                              sigset_t * /* `oset` */);\n#      else\n#        define GC_NO_PTHREAD_SIGMASK\n#      endif\n#    endif /* !GC_NO_PTHREAD_SIGMASK */\n\n#    ifndef GC_PTHREAD_CREATE_CONST\n/* This is used for `pthread_create()` only. */\n#      define GC_PTHREAD_CREATE_CONST const\n#    endif\n\nGC_API int GC_pthread_create(pthread_t *,\n                             GC_PTHREAD_CREATE_CONST pthread_attr_t *,\n                             void *(*)(void *), void * /* `arg` */);\nGC_API int GC_pthread_join(pthread_t, void ** /* `retval` */);\nGC_API int GC_pthread_detach(pthread_t);\n\n#    ifndef GC_NO_PTHREAD_CANCEL\nGC_API int GC_pthread_cancel(pthread_t);\n#    endif\n\n#    if defined(GC_HAVE_PTHREAD_EXIT) && !defined(GC_PTHREAD_EXIT_DECLARED)\n#      define GC_PTHREAD_EXIT_DECLARED\nGC_API void GC_pthread_exit(void *) GC_PTHREAD_EXIT_ATTRIBUTE;\n#    endif\n\n#    ifdef __cplusplus\n} /* extern \"C\" */\n#    endif\n\n#  endif /* !GC_PTHREAD_REDIRECTS_ONLY */\n\n#  if !defined(GC_NO_THREAD_REDIRECTS) && !defined(GC_USE_LD_WRAP)\n/*\n * Unless the compiler supports `#pragma extern_prefix`, the Tru64 UNIX\n * platform `pthread.h` file redefines some POSIX thread functions to use\n * mangled names.  Anyway, it is safe to `#undef` them before redefining.\n */\n#    undef pthread_create\n#    undef pthread_join\n#    undef pthread_detach\n#    define pthread_create GC_pthread_create\n#    define pthread_join GC_pthread_join\n#    define pthread_detach GC_pthread_detach\n\n#    ifndef GC_NO_PTHREAD_SIGMASK\n#      undef pthread_sigmask\n#      define pthread_sigmask GC_pthread_sigmask\n#    endif\n#    ifndef GC_NO_DLOPEN\n#      undef dlopen\n#      define dlopen GC_dlopen\n#    endif\n#    ifndef GC_NO_PTHREAD_CANCEL\n#      undef pthread_cancel\n#      define pthread_cancel GC_pthread_cancel\n#    endif\n#    ifdef GC_HAVE_PTHREAD_EXIT\n#      undef pthread_exit\n#      define pthread_exit GC_pthread_exit\n#    endif\n#  endif /* !GC_NO_THREAD_REDIRECTS */\n\n#endif /* GC_PTHREADS */\n\n#endif /* GC_PTHREAD_REDIRECTS_H */\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/gc_tiny_fl.h",
    "content": "/*\n * Copyright (c) 1999-2005 Hewlett-Packard Development Company, L.P.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n#ifndef GC_TINY_FL_H\n#define GC_TINY_FL_H\n\n/*\n * Constants and data structures for \"tiny\" free lists.\n * These are used for thread-local allocation and inlined allocators.\n * Each global free list also essentially starts with one of these.\n * However, global free lists are known to the collector.\n * \"Tiny\" free lists are basically private to the client.\n * Their contents are viewed as \"in use\" and marked accordingly by the\n * core of the collector.  Note that inlined code might know about the\n * layout of these and the constants involved.  Thus any change here\n * may invalidate clients, and such changes should be avoided.\n * Hence we keep this as simple as possible.\n */\n\n/*\n * We always set `GC_GRANULE_BYTES` to twice the length of a pointer.\n * This means that all allocation requests are rounded up to the next\n * multiple of 16 on 64-bit architectures or 8 on 32-bit architectures.\n * This appears to be a reasonable compromise between fragmentation\n * overhead and space usage for mark bits (usually mark bytes).\n * On many 64-bit architectures some memory references require 16-byte\n * alignment, making this necessary anyway.  For a few 32-bit\n * architectures (e.g. i686), we may also need 16-byte alignment for\n * certain memory references.  But currently that does not seem to be\n * the default for all conventional `malloc` implementations, so we\n * ignore that problem.\n * It would always be safe, and often useful, to be able to allocate\n * very small objects with smaller alignment.  But that would cost us\n * mark bit space, so we no longer do so.\n * `GC_GRANULE_BYTES` should not be overridden in any instances of the\n * collector library that may be shared between applications, since it\n * affects the ABI (application binary interface) to the library.\n */\n#if defined(CPPCHECK) && GC_GRANULE_BYTES == 1\n#  undef GC_GRANULE_BYTES\n#endif\n#ifdef GC_GRANULE_BYTES\n#  define GC_GRANULE_PTRS (GC_GRANULE_BYTES / GC_SIZEOF_PTR)\n#else\n#  define GC_GRANULE_PTRS 2 /*< in pointers */\n#  define GC_GRANULE_BYTES (GC_GRANULE_PTRS * GC_SIZEOF_PTR)\n#endif /* !GC_GRANULE_BYTES */\n\n/** Convert size in pointers to that in granules. */\n#define GC_PTRS_TO_GRANULES(n) ((n) / GC_GRANULE_PTRS)\n\n/**\n * Convert size in pointers to that in granules, but rounding up the\n * result.\n */\n#define GC_PTRS_TO_WHOLE_GRANULES(n) \\\n  GC_PTRS_TO_GRANULES((n) + GC_GRANULE_PTRS - 1)\n\n/*\n * A \"tiny\" free-list header contains `GC_TINY_FREELISTS` pointers to\n * singly-linked lists of objects of different sizes, the `i`-th one\n * containing objects of `i` granules in size.  Note that there is\n * a list of size zero objects.\n */\n#ifndef GC_TINY_FREELISTS\n#  if GC_GRANULE_BYTES >= 16\n#    define GC_TINY_FREELISTS 25\n#  else\n#    define GC_TINY_FREELISTS 33 /*< up to and including 256 bytes */\n#  endif\n#endif /* !GC_TINY_FREELISTS */\n\n/*\n * The `i`-th free list corresponds to size `i * GC_GRANULE_BYTES`.\n * Internally to the collector, the index `i` can be computed with\n * `ALLOC_REQUEST_GRANS()`.  The latter also depends on the values\n * returned by `GC_get_dont_add_byte_at_end()` and\n * `GC_get_all_interior_pointers()`.\n */\n\n/**\n * Convert a free-list index to the actual size of objects on that list,\n * including extra space we added.  Not an inverse of the above.\n */\n#define GC_RAW_BYTES_FROM_INDEX(i) (GC_GRANULE_BYTES * (i))\n\n/* Deprecated.  Use `GC_GRANULE_PTRS` instead. */\n#undef GC_GRANULE_WORDS\n#define GC_GRANULE_WORDS GC_GRANULE_PTRS\n\n/* Deprecated.  Use `GC_PTRS_TO_GRANULES()` instead. */\n#define GC_WORDS_TO_GRANULES(n) GC_PTRS_TO_GRANULES(n)\n\n/* Deprecated. */\n#define GC_WORDS_TO_WHOLE_GRANULES(n) GC_PTRS_TO_WHOLE_GRANULES(n)\n\n#endif /* GC_TINY_FL_H */\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/gc_typed.h",
    "content": "/*\n * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers\n * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.\n * Copyright 1996 Silicon Graphics.  All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * Some simple primitives for allocation with explicit type information.\n * Facilities for dynamic type inference may be added later.\n * Should be used only for extremely performance critical applications,\n * or if conservative collector leakage is otherwise a problem (unlikely).\n * Note that this is implemented completely separately from the rest\n * of the collector, and is not linked in unless referenced.\n * This does not currently support `GC_DEBUG` in any interesting way.\n *\n * Note for cris and m68k architectures (and for bcc and wcc compilers):\n * this API expects all pointers in the type (`T`) are aligned by the size\n * of a pointer (which might differ from `ALIGNMENT`).\n */\n\n#ifndef GC_TYPED_H\n#define GC_TYPED_H\n\n#ifndef GC_H\n#  include \"gc.h\"\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** The size of `GC_word` (not a pointer) type in bits. */\n#define GC_WORDSZ (8 * sizeof(GC_word))\n\n/** The size of a type `t` in pointers.  The value is rounded down. */\n#define GC_SIZEOF_IN_PTRS(t) (sizeof(t) / sizeof(void *))\n\n/** The offset of a field in pointers. */\n#define GC_OFFSETOF_IN_PTRS(t, f) (offsetof(t, f) / sizeof(void *))\n\n/**\n * The bitmap type.  The least significant bit of the first `GC_word` is one\n * if the first \"pointer-sized\" word in the object may be a pointer.\n */\ntypedef GC_word *GC_bitmap;\n\n/**\n * The number of elements (of `GC_word` type) of a bitmap array to\n * create for a given type `t`.  The bitmap is intended to be passed to\n * `GC_make_descriptor()`.\n */\n#define GC_BITMAP_SIZE(t) ((GC_SIZEOF_IN_PTRS(t) + GC_WORDSZ - 1) / GC_WORDSZ)\n\n/**\n * The setter and getter of the bitmap.  The `bm` argument should be of\n * `GC_bitmap` type; `i` argument should be of some `unsigned` type and\n * should not have side effects.\n */\n#define GC_set_bit(bm, i) \\\n  ((bm)[(i) / GC_WORDSZ] |= (GC_word)1 << ((i) % GC_WORDSZ))\n#define GC_get_bit(bm, i) (((bm)[(i) / GC_WORDSZ] >> ((i) % GC_WORDSZ)) & 1)\n\ntypedef GC_word GC_descr;\n\n/**\n * Return a type descriptor for the object whose layout is described\n * by the first argument.  The least significant bit of the first\n * `GC_word` is one if the first \"pointer-sized\" word in the object may\n * be a pointer.  The second argument (`number_of_bits_in_bitmap`)\n * specifies the number of meaningful bits in the bitmap.\n * The actual object may be larger (but not smaller); any additional\n * \"pointer-sized\" words in the object are assumed not to contain\n * pointers.  Returns a conservative approximation in the (unlikely)\n * case of insufficient memory to build the descriptor.  Calls to\n * `GC_make_descriptor()` may consume some amount of a finite resource.\n * This is intended to be called once per a type, not once per an\n * allocation.\n *\n * It is possible to generate a descriptor for a client type `T` with\n * aligned pointer fields `f1`, `f2`, ... as follows:\n * ```\n *   GC_descr t_descr;\n *   {\n *     GC_word bm[GC_BITMAP_SIZE(T)] = { 0 };\n *     GC_set_bit(bm, GC_OFFSETOF_IN_PTRS(T, f1));\n *     GC_set_bit(bm, GC_OFFSETOF_IN_PTRS(T, f2));\n *     ...\n *     t_descr = GC_make_descriptor(bm, GC_SIZEOF_IN_PTRS(T));\n *   }\n * ```\n */\nGC_API GC_descr GC_CALL\nGC_make_descriptor(const GC_word * /* `GC_bitmap` `bm` */,\n                   size_t /* `number_of_bits_in_bitmap` */);\n\n/**\n * Allocate an object whose layout is described by `d`.  The size\n * (`size_in_bytes`) may *not* be less than the number of meaningful\n * bits in the bitmap of `d` multiplied by the size of a pointer.\n * The returned object is cleared.  The returned object may *not* be\n * passed to `GC_realloc()`.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_malloc_explicitly_typed(size_t /* `size_in_bytes` */,\n                               GC_descr /* `d` */);\n\n/** The ignore-off-page variant of `GC_malloc_explicitly_typed()`. */\nGC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL\n    GC_malloc_explicitly_typed_ignore_off_page(size_t /* `size_in_bytes` */,\n                                               GC_descr /* `d` */);\n\n/**\n * Allocate an array of `nelements` elements, each of the given size\n * (`element_size_in_bytes`), and with the given descriptor (`d`).\n * The element size must be a multiple of the byte alignment required\n * for pointers.  (E.g. on a 32-bit machine with 16-bit aligned\n * pointers, `element_size_in_bytes` must be a multiple of 2.)\n * The element size may *not* be less than the number of meaningful\n * bits in the bitmap of `d` multiplied by the size of a pointer.\n * The returned object is cleared.\n */\nGC_API GC_ATTR_MALLOC GC_ATTR_CALLOC_SIZE(1, 2) void *GC_CALL\n    GC_calloc_explicitly_typed(size_t /* `nelements` */,\n                               size_t /* `element_size_in_bytes` */,\n                               GC_descr /* d */);\n\n#define GC_CALLOC_TYPED_DESCR_PTRS 1\n#define GC_CALLOC_TYPED_DESCR_WORDS 8 /*< includes space for pointers */\n\n#ifdef GC_BUILD\nstruct GC_calloc_typed_descr_s;\n#  define GC_calloc_typed_descr_s GC_calloc_typed_descr_opaque_s\n#endif\n\nstruct GC_calloc_typed_descr_s {\n  GC_uintptr_t opaque_p[GC_CALLOC_TYPED_DESCR_PTRS];\n  GC_word opaque[GC_CALLOC_TYPED_DESCR_WORDS - GC_CALLOC_TYPED_DESCR_PTRS];\n};\n#undef GC_calloc_typed_descr_s\n\n/**\n * This is same as `GC_calloc_explicitly_typed` but more optimal in\n * terms of the performance and memory usage if the client needs to\n * allocate multiple typed object arrays with the same layout and\n * number of elements.  The client should call it to be prepared for\n * the subsequent allocations by `GC_calloc_do_explicitly_typed()`, one\n * or many.  The result of the preparation is stored to `*pctd`, even\n * in case of a failure.  The prepared structure could be just dropped\n * when no longer needed.  Returns 0 on failure, 1 on success; the\n * result could be ignored (as it is also stored to `*pctd` and checked\n * later by `GC_calloc_do_explicitly_typed()`).\n */\nGC_API int GC_CALL GC_calloc_prepare_explicitly_typed(\n    struct GC_calloc_typed_descr_s * /* `pctd` */, size_t /* `sizeof_ctd` */,\n    size_t /* `nelements` */, size_t /* `element_size_in_bytes` */, GC_descr);\n\n/** The actual object allocation for the prepared description. */\nGC_API GC_ATTR_MALLOC void *GC_CALL GC_calloc_do_explicitly_typed(\n    const struct GC_calloc_typed_descr_s * /* `pctd` */,\n    size_t /* `sizeof_ctd` */);\n\n#ifdef GC_DEBUG\n#  define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) ((void)(d), GC_MALLOC(bytes))\n#  define GC_MALLOC_EXPLICITLY_TYPED_IGNORE_OFF_PAGE(bytes, d) \\\n    GC_MALLOC_EXPLICITLY_TYPED(bytes, d)\n#  define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \\\n    ((void)(d), GC_MALLOC((n) * (bytes)))\n#else\n#  define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) \\\n    GC_malloc_explicitly_typed(bytes, d)\n#  define GC_MALLOC_EXPLICITLY_TYPED_IGNORE_OFF_PAGE(bytes, d) \\\n    GC_malloc_explicitly_typed_ignore_off_page(bytes, d)\n#  define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \\\n    GC_calloc_explicitly_typed(n, bytes, d)\n#endif\n\n/* Deprecated.  Use `GC_SIZEOF_IN_PTRS()` instead. */\n#define GC_WORD_LEN(t) GC_SIZEOF_IN_PTRS(t)\n\n/* Deprecated.  Use `GC_OFFSETOF_IN_PTRS()` instead. */\n#define GC_WORD_OFFSET(t, f) GC_OFFSETOF_IN_PTRS(t, f)\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#endif /* GC_TYPED_H */\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/gc_version.h",
    "content": "/*\n * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.\n * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.\n * All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n/*\n * This should never be included directly; it is included only from\n * `gc.h` file.\n */\n#if defined(GC_H)\n\n/*\n * The policy regarding version numbers: development code has odd\n * `minor` number (and `micro` part is 0); when development is finished\n * and a release is prepared, `minor` number is incremented (keeping\n * `micro` number still zero), whenever a defect is fixed a new release\n * is prepared incrementing `micro` part to odd value (the most stable\n * release has the biggest `micro` number).\n */\n\n/*\n * The version here should match that in files `CMakeLists.txt`,\n * `build.zig.zon` and `configure.ac`.  Eventually this one may become\n * unnecessary.  For now we need it to keep the old-style build process\n * working.\n */\n#  define GC_TMP_VERSION_MAJOR 8\n#  define GC_TMP_VERSION_MINOR 3\n#  define GC_TMP_VERSION_MICRO 0 /*< 8.3.0 */\n\n#  ifdef GC_VERSION_MAJOR\n#    if GC_TMP_VERSION_MAJOR != GC_VERSION_MAJOR    \\\n        || GC_TMP_VERSION_MINOR != GC_VERSION_MINOR \\\n        || GC_TMP_VERSION_MICRO != GC_VERSION_MICRO\n#   error Inconsistent version info.  Check README.md, include/gc_version.h and configure.ac.\n#    endif\n#  else\n#    define GC_VERSION_MAJOR GC_TMP_VERSION_MAJOR\n#    define GC_VERSION_MINOR GC_TMP_VERSION_MINOR\n#    define GC_VERSION_MICRO GC_TMP_VERSION_MICRO\n#  endif /* !GC_VERSION_MAJOR */\n\n#endif\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/javaxfc.h",
    "content": "/*\n * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.\n * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.\n * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.\n * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.\n * All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n#ifndef GC_JAVAXFC_H\n#define GC_JAVAXFC_H\n\n#ifndef GC_H\n#  include \"gc.h\"\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Invoke all remaining finalizers that have not yet been run.  (Since the\n * notifier is not called, this should be called from a separate thread.)\n * This function is needed for strict compliance with the Java standard,\n * which can make the runtime guarantee that all finalizers are run.\n * This is problematic for several reasons:\n *   1. It means that finalizers, and all methods called by them, must be\n *      prepared to deal with objects that have been finalized in spite of\n *      the fact that they are still referenced by statically allocated\n *      pointer variables (i.e. finalizers run at this point must be\n *      prepared to deal with a mostly broken world);\n *   2. The Java standard implies we have to keep running finalizers until\n *      there are no more left, thus it may mean that we get stuck in\n *      an infinite loop running finalizers that create new finalizable\n *      objects, though that is probably unlikely.\n * Thus this is not recommended for general use.\n * Acquires the allocator lock (to enqueue all finalizers).\n */\nGC_API void GC_CALL GC_finalize_all(void);\n\n#ifdef GC_THREADS\n/**\n * External thread suspension support.  No thread suspension count\n * (so a thread which has been suspended numerous times will be resumed\n * with the very first call to `GC_resume_thread()`).  Acquires the\n * allocator lock.  Thread should be registered in the collector.\n * Unimplemented on some platforms.  Not recommended for general use.\n */\n#  ifndef GC_SUSPEND_THREAD_ID\n#    define GC_SUSPEND_THREAD_ID void *\n#  endif\nGC_API void GC_CALL GC_suspend_thread(GC_SUSPEND_THREAD_ID);\nGC_API void GC_CALL GC_resume_thread(GC_SUSPEND_THREAD_ID);\n\n/**\n * Is the given thread suspended externally?  The result is either\n * 1 (true) or 0.  Acquires the allocator lock in the reader mode.\n * Note: returns 0 (false) if the thread is not registered in the collector.\n * Unimplemented on some platforms (same as `GC_suspend_thread()`).\n */\nGC_API int GC_CALL GC_is_thread_suspended(GC_SUSPEND_THREAD_ID);\n#endif /* GC_THREADS */\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#endif /* GC_JAVAXFC_H */\n"
  },
  {
    "path": "thirdparty/libgc/include/gc/leak_detector.h",
    "content": "/*\n * Copyright (c) 2000-2011 by Hewlett-Packard Development Company.\n * All rights reserved.\n *\n * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED\n * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n *\n * Permission is hereby granted to use or copy this program\n * for any purpose, provided the above notices are retained on all copies.\n * Permission to modify the code and to distribute modified code is granted,\n * provided the above notices are retained, and a notice that the code was\n * modified is included with the above copyright notice.\n */\n\n#ifndef GC_LEAK_DETECTOR_H\n#define GC_LEAK_DETECTOR_H\n\n/*\n * Include this header file (e.g., via gcc `--include` option) to turn\n * the collector into a leak detector.\n */\n\n#ifndef GC_DEBUG\n#  define GC_DEBUG\n#endif\n#include \"gc.h\"\n\n#ifndef GC_DONT_INCLUDE_STDLIB\n/*\n * We ensure the platform `stdlib.h` and `string.h` files are included\n * before redirecting `malloc` and the accompanying functions.\n */\n#  include <stdlib.h>\n#  include <string.h>\n#endif\n\n#undef malloc\n#define malloc(n) GC_MALLOC(n)\n#undef calloc\n#define calloc(m, n) GC_MALLOC((m) * (n))\n#undef free\n#define free(p) GC_FREE(p)\n#undef realloc\n#define realloc(p, n) GC_REALLOC(p, n)\n#undef reallocarray\n#define reallocarray(p, m, n) GC_REALLOC(p, (m) * (n))\n\n#undef strdup\n#define strdup(s) GC_STRDUP(s)\n#undef strndup\n#define strndup(s, n) GC_STRNDUP(s, n)\n\n#ifdef GC_REQUIRE_WCSDUP\n/*\n * The collector should be built with `GC_REQUIRE_WCSDUP` macro defined\n * as well to redirect `wcsdup`.\n */\n#  include <wchar.h>\n#  undef wcsdup\n#  define wcsdup(s) GC_WCSDUP(s)\n#endif\n\n/*\n * The following routines for the aligned objects allocation\n * (`aligned_alloc`, `valloc`, etc.) do not have their debugging\n * counterparts.  Note that `free()` called for such objects may output\n * a warning that the pointer has no debugging info.\n */\n\n#undef aligned_alloc\n#define aligned_alloc(a, n) GC_memalign(a, n) /*< identical to `memalign` */\n#undef memalign\n#define memalign(a, n) GC_memalign(a, n)\n#undef posix_memalign\n#define posix_memalign(p, a, n) GC_posix_memalign(p, a, n)\n\n/* These are defined in the C23 standard. */\n#undef free_sized\n#define free_sized(p, n) (free(p), (void)(n))\n#undef free_aligned_sized\n#define free_aligned_sized(p, a, n) \\\n  (GC_free(p) /* non-debug */, (void)(a), (void)(n))\n\n#undef cfree /*< obsolete */\n#if defined(sun) || defined(__sun)\n#  define cfree(p, m, n) ((void)(m), (void)(n), free(p))\n#else\n#  define cfree(p) free(p)\n#endif\n\n#undef _aligned_malloc\n#define _aligned_malloc(n, a) GC_memalign(a, n) /*< reverse args order */\n#undef _aligned_free\n#define _aligned_free(p) GC_free(p) /*< non-debug */\n\n#ifndef GC_NO_VALLOC\n#  undef valloc\n#  define valloc(n) GC_valloc(n)\n#  undef pvalloc\n#  define pvalloc(n) GC_pvalloc(n) /*< obsolete */\n#endif\n\n#undef malloc_usable_size /*< available in `glibc` */\n#define malloc_usable_size(p) GC_size(p)\n#undef malloc_size /*< available in Darwin */\n#define malloc_size(p) GC_size(p)\n#undef _msize /*< available in Windows CRT */\n#define _msize(p) GC_size(p)\n\n#ifndef CHECK_LEAKS\n/**\n * Note 1: `CHECK_LEAKS` does not have `GC_` prefix (preserved for\n * backward compatibility).\n * Note 2: `GC_gcollect()` is also called automatically in the\n * find-leak mode at program exit.\n */\n#  define CHECK_LEAKS() GC_gcollect()\n#endif\n\n#endif /* GC_LEAK_DETECTOR_H */\n"
  },
  {
    "path": "thirdparty/libgc/include/gc.h",
    "content": "/* This file is installed for backward compatibility. */\n#include \"gc/gc.h\"\n\n#ifndef _MSC_VER\n__attribute__ ((weak)) GC_API void GC_CALL GC_noop1_ptr(volatile void *p) {\n   GC_noop1((u64)p);\n}\n#endif\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/README.md",
    "content": "The files in this directory stem from [Project Everest](https://project-everest.github.io/) and are distributed under the Apache 2.0 license.\n\nThis is a formally verified implementation of Curve25519-based handshakes. The C code is automatically derived from the (verified) [original implementation](https://github.com/project-everest/hacl-star/tree/master/code/curve25519) in the [F* language](https://github.com/fstarlang/fstar) by [KreMLin](https://github.com/fstarlang/kremlin). In addition to the improved safety and security of the implementation, it is also significantly faster than the default implementation of Curve25519 in mbedTLS.\n\nThe caveat is that not all platforms are supported, although the version in `everest/library/legacy` should work on most systems. The main issue is that some platforms do not provide a 128-bit integer type and KreMLin therefore has to use additional (also verified) code to simulate them, resulting in less of a performance gain overall. Explicitly supported platforms are currently `x86` and `x86_64` using gcc or clang, and Visual C (2010 and later).\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/include/everest/Hacl_Curve25519.h",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>\n * KreMLin invocation: /mnt/e/everest/verify/kremlin/krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -fbuiltin-uint128 -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -I /mnt/e/everest/verify/hacl-star/code/lib/kremlin -I /mnt/e/everest/verify/kremlin/kremlib/compat -I /mnt/e/everest/verify/hacl-star/specs -I /mnt/e/everest/verify/hacl-star/specs/old -I . -ccopt -march=native -verbose -ldopt -flto -tmpdir x25519-c -I ../bignum -bundle Hacl.Curve25519=* -minimal -add-include \"kremlib.h\" -skip-compilation x25519-c/out.krml -o x25519-c/Hacl_Curve25519.c\n * F* version: 059db0c8\n * KreMLin version: 916c37ac\n */\n\n\n\n#ifndef __Hacl_Curve25519_H\n#define __Hacl_Curve25519_H\n\n\n#include \"kremlib.h\"\n\nvoid Hacl_Curve25519_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint);\n\n#define __Hacl_Curve25519_H_DEFINED\n#endif\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/include/everest/everest.h",
    "content": "/*\n *  Interface to code from Project Everest\n *\n *  Copyright 2016-2018 INRIA and Microsoft Corporation\n *  SPDX-License-Identifier: Apache-2.0\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n *  not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *  http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *  This file is part of Mbed TLS (https://tls.mbed.org).\n */\n\n#ifndef MBEDTLS_EVEREST_H\n#define MBEDTLS_EVEREST_H\n\n#include \"everest/x25519.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Defines the source of the imported EC key.\n */\ntypedef enum\n{\n    MBEDTLS_EVEREST_ECDH_OURS,   /**< Our key. */\n    MBEDTLS_EVEREST_ECDH_THEIRS, /**< The key of the peer. */\n} mbedtls_everest_ecdh_side;\n\ntypedef struct {\n    mbedtls_x25519_context ctx;\n} mbedtls_ecdh_context_everest;\n\n\n/**\n * \\brief           This function sets up the ECDH context with the information\n *                  given.\n *\n *                  This function should be called after mbedtls_ecdh_init() but\n *                  before mbedtls_ecdh_make_params(). There is no need to call\n *                  this function before mbedtls_ecdh_read_params().\n *\n *                  This is the first function used by a TLS server for ECDHE\n *                  ciphersuites.\n *\n * \\param ctx       The ECDH context to set up.\n * \\param grp_id    The group id of the group to set up the context for.\n *\n * \\return          \\c 0 on success.\n */\nint mbedtls_everest_setup( mbedtls_ecdh_context_everest *ctx, int grp_id );\n\n/**\n * \\brief           This function frees a context.\n *\n * \\param ctx       The context to free.\n */\nvoid mbedtls_everest_free( mbedtls_ecdh_context_everest *ctx );\n\n/**\n * \\brief           This function generates a public key and a TLS\n *                  ServerKeyExchange payload.\n *\n *                  This is the second function used by a TLS server for ECDHE\n *                  ciphersuites. (It is called after mbedtls_ecdh_setup().)\n *\n * \\note            This function assumes that the ECP group (grp) of the\n *                  \\p ctx context has already been properly set,\n *                  for example, using mbedtls_ecp_group_load().\n *\n * \\see             ecp.h\n *\n * \\param ctx       The ECDH context.\n * \\param olen      The number of characters written.\n * \\param buf       The destination buffer.\n * \\param blen      The length of the destination buffer.\n * \\param f_rng     The RNG function.\n * \\param p_rng     The RNG context.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n */\nint mbedtls_everest_make_params( mbedtls_ecdh_context_everest *ctx, size_t *olen,\n                                 unsigned char *buf, size_t blen,\n                                 int( *f_rng )( void *, unsigned char *, size_t ),\n                                 void *p_rng );\n\n/**\n * \\brief           This function parses and processes a TLS ServerKeyExchange\n *                  payload.\n *\n *                  This is the first function used by a TLS client for ECDHE\n *                  ciphersuites.\n *\n * \\see             ecp.h\n *\n * \\param ctx       The ECDH context.\n * \\param buf       The pointer to the start of the input buffer.\n * \\param end       The address for one Byte past the end of the buffer.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n *\n */\nint mbedtls_everest_read_params( mbedtls_ecdh_context_everest *ctx,\n                                 const unsigned char **buf, const unsigned char *end );\n\n/**\n * \\brief           This function parses and processes a TLS ServerKeyExchange\n *                  payload.\n *\n *                  This is the first function used by a TLS client for ECDHE\n *                  ciphersuites.\n *\n * \\see             ecp.h\n *\n * \\param ctx       The ECDH context.\n * \\param buf       The pointer to the start of the input buffer.\n * \\param end       The address for one Byte past the end of the buffer.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n *\n */\nint mbedtls_everest_read_params( mbedtls_ecdh_context_everest *ctx,\n                                 const unsigned char **buf, const unsigned char *end );\n\n/**\n * \\brief           This function sets up an ECDH context from an EC key.\n *\n *                  It is used by clients and servers in place of the\n *                  ServerKeyEchange for static ECDH, and imports ECDH\n *                  parameters from the EC key information of a certificate.\n *\n * \\see             ecp.h\n *\n * \\param ctx       The ECDH context to set up.\n * \\param key       The EC key to use.\n * \\param side      Defines the source of the key: 1: Our key, or\n *                  0: The key of the peer.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n *\n */\nint mbedtls_everest_get_params( mbedtls_ecdh_context_everest *ctx, const mbedtls_ecp_keypair *key,\n                                mbedtls_everest_ecdh_side side );\n\n/**\n * \\brief           This function generates a public key and a TLS\n *                  ClientKeyExchange payload.\n *\n *                  This is the second function used by a TLS client for ECDH(E)\n *                  ciphersuites.\n *\n * \\see             ecp.h\n *\n * \\param ctx       The ECDH context.\n * \\param olen      The number of Bytes written.\n * \\param buf       The destination buffer.\n * \\param blen      The size of the destination buffer.\n * \\param f_rng     The RNG function.\n * \\param p_rng     The RNG context.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n */\nint mbedtls_everest_make_public( mbedtls_ecdh_context_everest *ctx, size_t *olen,\n                                 unsigned char *buf, size_t blen,\n                                 int( *f_rng )( void *, unsigned char *, size_t ),\n                                 void *p_rng );\n\n/**\n * \\brief       This function parses and processes a TLS ClientKeyExchange\n *              payload.\n *\n *              This is the third function used by a TLS server for ECDH(E)\n *              ciphersuites. (It is called after mbedtls_ecdh_setup() and\n *              mbedtls_ecdh_make_params().)\n *\n * \\see         ecp.h\n *\n * \\param ctx   The ECDH context.\n * \\param buf   The start of the input buffer.\n * \\param blen  The length of the input buffer.\n *\n * \\return      \\c 0 on success.\n * \\return      An \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n */\nint mbedtls_everest_read_public( mbedtls_ecdh_context_everest *ctx,\n                                 const unsigned char *buf, size_t blen );\n\n/**\n * \\brief           This function derives and exports the shared secret.\n *\n *                  This is the last function used by both TLS client\n *                  and servers.\n *\n * \\note            If \\p f_rng is not NULL, it is used to implement\n *                  countermeasures against side-channel attacks.\n *                  For more information, see mbedtls_ecp_mul().\n *\n * \\see             ecp.h\n *\n * \\param ctx       The ECDH context.\n * \\param olen      The number of Bytes written.\n * \\param buf       The destination buffer.\n * \\param blen      The length of the destination buffer.\n * \\param f_rng     The RNG function.\n * \\param p_rng     The RNG context.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n */\nint mbedtls_everest_calc_secret( mbedtls_ecdh_context_everest *ctx, size_t *olen,\n                                 unsigned char *buf, size_t blen,\n                                 int( *f_rng )( void *, unsigned char *, size_t ),\n                                 void *p_rng );\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_EVEREST_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/include/everest/kremlib/FStar_UInt128.h",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>\n * KreMLin invocation: ../krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrB9w -minimal -fparentheses -fcurly-braces -fno-shadow -header copyright-header.txt -minimal -tmpdir dist/uint128 -skip-compilation -extract-uints -add-include <inttypes.h> -add-include <stdbool.h> -add-include \"kremlin/internal/types.h\" -bundle FStar.UInt128=* extracted/prims.krml extracted/FStar_Pervasives_Native.krml extracted/FStar_Pervasives.krml extracted/FStar_Mul.krml extracted/FStar_Squash.krml extracted/FStar_Classical.krml extracted/FStar_StrongExcludedMiddle.krml extracted/FStar_FunctionalExtensionality.krml extracted/FStar_List_Tot_Base.krml extracted/FStar_List_Tot_Properties.krml extracted/FStar_List_Tot.krml extracted/FStar_Seq_Base.krml extracted/FStar_Seq_Properties.krml extracted/FStar_Seq.krml extracted/FStar_Math_Lib.krml extracted/FStar_Math_Lemmas.krml extracted/FStar_BitVector.krml extracted/FStar_UInt.krml extracted/FStar_UInt32.krml extracted/FStar_Int.krml extracted/FStar_Int16.krml extracted/FStar_Preorder.krml extracted/FStar_Ghost.krml extracted/FStar_ErasedLogic.krml extracted/FStar_UInt64.krml extracted/FStar_Set.krml extracted/FStar_PropositionalExtensionality.krml extracted/FStar_PredicateExtensionality.krml extracted/FStar_TSet.krml extracted/FStar_Monotonic_Heap.krml extracted/FStar_Heap.krml extracted/FStar_Map.krml extracted/FStar_Monotonic_HyperHeap.krml extracted/FStar_Monotonic_HyperStack.krml extracted/FStar_HyperStack.krml extracted/FStar_Monotonic_Witnessed.krml extracted/FStar_HyperStack_ST.krml extracted/FStar_HyperStack_All.krml extracted/FStar_Date.krml extracted/FStar_Universe.krml extracted/FStar_GSet.krml extracted/FStar_ModifiesGen.krml extracted/LowStar_Monotonic_Buffer.krml extracted/LowStar_Buffer.krml extracted/Spec_Loops.krml extracted/LowStar_BufferOps.krml extracted/C_Loops.krml extracted/FStar_UInt8.krml extracted/FStar_Kremlin_Endianness.krml extracted/FStar_UInt63.krml extracted/FStar_Exn.krml extracted/FStar_ST.krml extracted/FStar_All.krml extracted/FStar_Dyn.krml extracted/FStar_Int63.krml extracted/FStar_Int64.krml extracted/FStar_Int32.krml extracted/FStar_Int8.krml extracted/FStar_UInt16.krml extracted/FStar_Int_Cast.krml extracted/FStar_UInt128.krml extracted/C_Endianness.krml extracted/FStar_List.krml extracted/FStar_Float.krml extracted/FStar_IO.krml extracted/C.krml extracted/FStar_Char.krml extracted/FStar_String.krml extracted/LowStar_Modifies.krml extracted/C_String.krml extracted/FStar_Bytes.krml extracted/FStar_HyperStack_IO.krml extracted/C_Failure.krml extracted/TestLib.krml extracted/FStar_Int_Cast_Full.krml\n * F* version: 059db0c8\n * KreMLin version: 916c37ac\n */\n\n\n\n#ifndef __FStar_UInt128_H\n#define __FStar_UInt128_H\n\n\n#include <inttypes.h>\n#include <stdbool.h>\n#include \"kremlin/internal/types.h\"\n\nuint64_t FStar_UInt128___proj__Mkuint128__item__low(FStar_UInt128_uint128 projectee);\n\nuint64_t FStar_UInt128___proj__Mkuint128__item__high(FStar_UInt128_uint128 projectee);\n\ntypedef FStar_UInt128_uint128 FStar_UInt128_t;\n\nFStar_UInt128_uint128 FStar_UInt128_add(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nFStar_UInt128_uint128\nFStar_UInt128_add_underspec(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nFStar_UInt128_uint128 FStar_UInt128_add_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nFStar_UInt128_uint128 FStar_UInt128_sub(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nFStar_UInt128_uint128\nFStar_UInt128_sub_underspec(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nFStar_UInt128_uint128 FStar_UInt128_sub_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nFStar_UInt128_uint128 FStar_UInt128_logand(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nFStar_UInt128_uint128 FStar_UInt128_logxor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nFStar_UInt128_uint128 FStar_UInt128_logor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nFStar_UInt128_uint128 FStar_UInt128_lognot(FStar_UInt128_uint128 a);\n\nFStar_UInt128_uint128 FStar_UInt128_shift_left(FStar_UInt128_uint128 a, uint32_t s);\n\nFStar_UInt128_uint128 FStar_UInt128_shift_right(FStar_UInt128_uint128 a, uint32_t s);\n\nbool FStar_UInt128_eq(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nbool FStar_UInt128_gt(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nbool FStar_UInt128_lt(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nbool FStar_UInt128_gte(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nbool FStar_UInt128_lte(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nFStar_UInt128_uint128 FStar_UInt128_eq_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nFStar_UInt128_uint128 FStar_UInt128_gte_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);\n\nFStar_UInt128_uint128 FStar_UInt128_uint64_to_uint128(uint64_t a);\n\nuint64_t FStar_UInt128_uint128_to_uint64(FStar_UInt128_uint128 a);\n\nextern FStar_UInt128_uint128\n(*FStar_UInt128_op_Plus_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nextern FStar_UInt128_uint128\n(*FStar_UInt128_op_Plus_Question_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nextern FStar_UInt128_uint128\n(*FStar_UInt128_op_Plus_Percent_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nextern FStar_UInt128_uint128\n(*FStar_UInt128_op_Subtraction_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nextern FStar_UInt128_uint128\n(*FStar_UInt128_op_Subtraction_Question_Hat)(\n  FStar_UInt128_uint128 x0,\n  FStar_UInt128_uint128 x1\n);\n\nextern FStar_UInt128_uint128\n(*FStar_UInt128_op_Subtraction_Percent_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nextern FStar_UInt128_uint128\n(*FStar_UInt128_op_Amp_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nextern FStar_UInt128_uint128\n(*FStar_UInt128_op_Hat_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nextern FStar_UInt128_uint128\n(*FStar_UInt128_op_Bar_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nextern FStar_UInt128_uint128\n(*FStar_UInt128_op_Less_Less_Hat)(FStar_UInt128_uint128 x0, uint32_t x1);\n\nextern FStar_UInt128_uint128\n(*FStar_UInt128_op_Greater_Greater_Hat)(FStar_UInt128_uint128 x0, uint32_t x1);\n\nextern bool (*FStar_UInt128_op_Equals_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nextern bool\n(*FStar_UInt128_op_Greater_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nextern bool (*FStar_UInt128_op_Less_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nextern bool\n(*FStar_UInt128_op_Greater_Equals_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nextern bool\n(*FStar_UInt128_op_Less_Equals_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nFStar_UInt128_uint128 FStar_UInt128_mul32(uint64_t x, uint32_t y);\n\nFStar_UInt128_uint128 FStar_UInt128_mul_wide(uint64_t x, uint64_t y);\n\n#define __FStar_UInt128_H_DEFINED\n#endif\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/include/everest/kremlib/FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8.h",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>\n * KreMLin invocation: ../krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrB9w -minimal -fparentheses -fcurly-braces -fno-shadow -header copyright-header.txt -minimal -tmpdir dist/minimal -skip-compilation -extract-uints -add-include <inttypes.h> -add-include <stdbool.h> -add-include \"kremlin/internal/compat.h\" -add-include \"kremlin/internal/types.h\" -bundle FStar.UInt64+FStar.UInt32+FStar.UInt16+FStar.UInt8=* extracted/prims.krml extracted/FStar_Pervasives_Native.krml extracted/FStar_Pervasives.krml extracted/FStar_Mul.krml extracted/FStar_Squash.krml extracted/FStar_Classical.krml extracted/FStar_StrongExcludedMiddle.krml extracted/FStar_FunctionalExtensionality.krml extracted/FStar_List_Tot_Base.krml extracted/FStar_List_Tot_Properties.krml extracted/FStar_List_Tot.krml extracted/FStar_Seq_Base.krml extracted/FStar_Seq_Properties.krml extracted/FStar_Seq.krml extracted/FStar_Math_Lib.krml extracted/FStar_Math_Lemmas.krml extracted/FStar_BitVector.krml extracted/FStar_UInt.krml extracted/FStar_UInt32.krml extracted/FStar_Int.krml extracted/FStar_Int16.krml extracted/FStar_Preorder.krml extracted/FStar_Ghost.krml extracted/FStar_ErasedLogic.krml extracted/FStar_UInt64.krml extracted/FStar_Set.krml extracted/FStar_PropositionalExtensionality.krml extracted/FStar_PredicateExtensionality.krml extracted/FStar_TSet.krml extracted/FStar_Monotonic_Heap.krml extracted/FStar_Heap.krml extracted/FStar_Map.krml extracted/FStar_Monotonic_HyperHeap.krml extracted/FStar_Monotonic_HyperStack.krml extracted/FStar_HyperStack.krml extracted/FStar_Monotonic_Witnessed.krml extracted/FStar_HyperStack_ST.krml extracted/FStar_HyperStack_All.krml extracted/FStar_Date.krml extracted/FStar_Universe.krml extracted/FStar_GSet.krml extracted/FStar_ModifiesGen.krml extracted/LowStar_Monotonic_Buffer.krml extracted/LowStar_Buffer.krml extracted/Spec_Loops.krml extracted/LowStar_BufferOps.krml extracted/C_Loops.krml extracted/FStar_UInt8.krml extracted/FStar_Kremlin_Endianness.krml extracted/FStar_UInt63.krml extracted/FStar_Exn.krml extracted/FStar_ST.krml extracted/FStar_All.krml extracted/FStar_Dyn.krml extracted/FStar_Int63.krml extracted/FStar_Int64.krml extracted/FStar_Int32.krml extracted/FStar_Int8.krml extracted/FStar_UInt16.krml extracted/FStar_Int_Cast.krml extracted/FStar_UInt128.krml extracted/C_Endianness.krml extracted/FStar_List.krml extracted/FStar_Float.krml extracted/FStar_IO.krml extracted/C.krml extracted/FStar_Char.krml extracted/FStar_String.krml extracted/LowStar_Modifies.krml extracted/C_String.krml extracted/FStar_Bytes.krml extracted/FStar_HyperStack_IO.krml extracted/C_Failure.krml extracted/TestLib.krml extracted/FStar_Int_Cast_Full.krml\n * F* version: 059db0c8\n * KreMLin version: 916c37ac\n */\n\n\n\n#ifndef __FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8_H\n#define __FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8_H\n\n\n#include <inttypes.h>\n#include <stdbool.h>\n#include \"kremlin/internal/compat.h\"\n#include \"kremlin/internal/types.h\"\n\nextern Prims_int FStar_UInt64_n;\n\nextern Prims_int FStar_UInt64_v(uint64_t x0);\n\nextern uint64_t FStar_UInt64_uint_to_t(Prims_int x0);\n\nextern uint64_t FStar_UInt64_add(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_add_underspec(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_add_mod(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_sub(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_sub_underspec(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_sub_mod(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_mul(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_mul_underspec(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_mul_mod(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_mul_div(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_div(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_rem(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_logand(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_logxor(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_logor(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_lognot(uint64_t x0);\n\nextern uint64_t FStar_UInt64_shift_right(uint64_t x0, uint32_t x1);\n\nextern uint64_t FStar_UInt64_shift_left(uint64_t x0, uint32_t x1);\n\nextern bool FStar_UInt64_eq(uint64_t x0, uint64_t x1);\n\nextern bool FStar_UInt64_gt(uint64_t x0, uint64_t x1);\n\nextern bool FStar_UInt64_gte(uint64_t x0, uint64_t x1);\n\nextern bool FStar_UInt64_lt(uint64_t x0, uint64_t x1);\n\nextern bool FStar_UInt64_lte(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_minus(uint64_t x0);\n\nextern uint32_t FStar_UInt64_n_minus_one;\n\nuint64_t FStar_UInt64_eq_mask(uint64_t a, uint64_t b);\n\nuint64_t FStar_UInt64_gte_mask(uint64_t a, uint64_t b);\n\nextern Prims_string FStar_UInt64_to_string(uint64_t x0);\n\nextern uint64_t FStar_UInt64_of_string(Prims_string x0);\n\nextern Prims_int FStar_UInt32_n;\n\nextern Prims_int FStar_UInt32_v(uint32_t x0);\n\nextern uint32_t FStar_UInt32_uint_to_t(Prims_int x0);\n\nextern uint32_t FStar_UInt32_add(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_add_underspec(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_add_mod(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_sub(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_sub_underspec(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_sub_mod(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_mul(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_mul_underspec(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_mul_mod(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_mul_div(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_div(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_rem(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_logand(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_logxor(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_logor(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_lognot(uint32_t x0);\n\nextern uint32_t FStar_UInt32_shift_right(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_shift_left(uint32_t x0, uint32_t x1);\n\nextern bool FStar_UInt32_eq(uint32_t x0, uint32_t x1);\n\nextern bool FStar_UInt32_gt(uint32_t x0, uint32_t x1);\n\nextern bool FStar_UInt32_gte(uint32_t x0, uint32_t x1);\n\nextern bool FStar_UInt32_lt(uint32_t x0, uint32_t x1);\n\nextern bool FStar_UInt32_lte(uint32_t x0, uint32_t x1);\n\nextern uint32_t FStar_UInt32_minus(uint32_t x0);\n\nextern uint32_t FStar_UInt32_n_minus_one;\n\nuint32_t FStar_UInt32_eq_mask(uint32_t a, uint32_t b);\n\nuint32_t FStar_UInt32_gte_mask(uint32_t a, uint32_t b);\n\nextern Prims_string FStar_UInt32_to_string(uint32_t x0);\n\nextern uint32_t FStar_UInt32_of_string(Prims_string x0);\n\nextern Prims_int FStar_UInt16_n;\n\nextern Prims_int FStar_UInt16_v(uint16_t x0);\n\nextern uint16_t FStar_UInt16_uint_to_t(Prims_int x0);\n\nextern uint16_t FStar_UInt16_add(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_add_underspec(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_add_mod(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_sub(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_sub_underspec(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_sub_mod(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_mul(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_mul_underspec(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_mul_mod(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_mul_div(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_div(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_rem(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_logand(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_logxor(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_logor(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_lognot(uint16_t x0);\n\nextern uint16_t FStar_UInt16_shift_right(uint16_t x0, uint32_t x1);\n\nextern uint16_t FStar_UInt16_shift_left(uint16_t x0, uint32_t x1);\n\nextern bool FStar_UInt16_eq(uint16_t x0, uint16_t x1);\n\nextern bool FStar_UInt16_gt(uint16_t x0, uint16_t x1);\n\nextern bool FStar_UInt16_gte(uint16_t x0, uint16_t x1);\n\nextern bool FStar_UInt16_lt(uint16_t x0, uint16_t x1);\n\nextern bool FStar_UInt16_lte(uint16_t x0, uint16_t x1);\n\nextern uint16_t FStar_UInt16_minus(uint16_t x0);\n\nextern uint32_t FStar_UInt16_n_minus_one;\n\nuint16_t FStar_UInt16_eq_mask(uint16_t a, uint16_t b);\n\nuint16_t FStar_UInt16_gte_mask(uint16_t a, uint16_t b);\n\nextern Prims_string FStar_UInt16_to_string(uint16_t x0);\n\nextern uint16_t FStar_UInt16_of_string(Prims_string x0);\n\nextern Prims_int FStar_UInt8_n;\n\nextern Prims_int FStar_UInt8_v(uint8_t x0);\n\nextern uint8_t FStar_UInt8_uint_to_t(Prims_int x0);\n\nextern uint8_t FStar_UInt8_add(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_add_underspec(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_add_mod(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_sub(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_sub_underspec(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_sub_mod(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_mul(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_mul_underspec(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_mul_mod(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_mul_div(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_div(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_rem(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_logand(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_logxor(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_logor(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_lognot(uint8_t x0);\n\nextern uint8_t FStar_UInt8_shift_right(uint8_t x0, uint32_t x1);\n\nextern uint8_t FStar_UInt8_shift_left(uint8_t x0, uint32_t x1);\n\nextern bool FStar_UInt8_eq(uint8_t x0, uint8_t x1);\n\nextern bool FStar_UInt8_gt(uint8_t x0, uint8_t x1);\n\nextern bool FStar_UInt8_gte(uint8_t x0, uint8_t x1);\n\nextern bool FStar_UInt8_lt(uint8_t x0, uint8_t x1);\n\nextern bool FStar_UInt8_lte(uint8_t x0, uint8_t x1);\n\nextern uint8_t FStar_UInt8_minus(uint8_t x0);\n\nextern uint32_t FStar_UInt8_n_minus_one;\n\nuint8_t FStar_UInt8_eq_mask(uint8_t a, uint8_t b);\n\nuint8_t FStar_UInt8_gte_mask(uint8_t a, uint8_t b);\n\nextern Prims_string FStar_UInt8_to_string(uint8_t x0);\n\nextern uint8_t FStar_UInt8_of_string(Prims_string x0);\n\ntypedef uint8_t FStar_UInt8_byte;\n\n#define __FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8_H_DEFINED\n#endif\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/include/everest/kremlib.h",
    "content": "/*\n *  Copyright 2016-2018 INRIA and Microsoft Corporation\n *\n *  SPDX-License-Identifier: Apache-2.0\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n *  not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *  http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *  This file is part of Mbed TLS (https://tls.mbed.org) and\n *  originated from Project Everest (https://project-everest.github.io/)\n */\n\n#ifndef __KREMLIB_H\n#define __KREMLIB_H\n\n#include \"kremlin/internal/target.h\"\n#include \"kremlin/internal/types.h\"\n#include \"kremlin/c_endianness.h\"\n\n#endif     /* __KREMLIB_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/include/everest/kremlin/c_endianness.h",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n#ifndef __KREMLIN_ENDIAN_H\n#define __KREMLIN_ENDIAN_H\n\n#include <string.h>\n#include <inttypes.h>\n\n#include \"kremlin/internal/callconv.h\"\n\n/******************************************************************************/\n/* Implementing C.fst (part 2: endian-ness macros)                            */\n/******************************************************************************/\n\n/* ... for Linux */\n#if defined(__linux__) || defined(__CYGWIN__)\n#  include <endian.h>\n\n/* ... for OSX */\n#elif defined(__APPLE__)\n#  include <libkern/OSByteOrder.h>\n#  define htole64(x) OSSwapHostToLittleInt64(x)\n#  define le64toh(x) OSSwapLittleToHostInt64(x)\n#  define htobe64(x) OSSwapHostToBigInt64(x)\n#  define be64toh(x) OSSwapBigToHostInt64(x)\n\n#  define htole16(x) OSSwapHostToLittleInt16(x)\n#  define le16toh(x) OSSwapLittleToHostInt16(x)\n#  define htobe16(x) OSSwapHostToBigInt16(x)\n#  define be16toh(x) OSSwapBigToHostInt16(x)\n\n#  define htole32(x) OSSwapHostToLittleInt32(x)\n#  define le32toh(x) OSSwapLittleToHostInt32(x)\n#  define htobe32(x) OSSwapHostToBigInt32(x)\n#  define be32toh(x) OSSwapBigToHostInt32(x)\n\n/* ... for Solaris */\n#elif defined(__sun__)\n#  include <sys/byteorder.h>\n#  define htole64(x) LE_64(x)\n#  define le64toh(x) LE_64(x)\n#  define htobe64(x) BE_64(x)\n#  define be64toh(x) BE_64(x)\n\n#  define htole16(x) LE_16(x)\n#  define le16toh(x) LE_16(x)\n#  define htobe16(x) BE_16(x)\n#  define be16toh(x) BE_16(x)\n\n#  define htole32(x) LE_32(x)\n#  define le32toh(x) LE_32(x)\n#  define htobe32(x) BE_32(x)\n#  define be32toh(x) BE_32(x)\n\n/* ... for the BSDs */\n#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)\n#  include <sys/endian.h>\n#elif defined(__OpenBSD__)\n#  include <endian.h>\n\n/* ... for Windows (MSVC)... not targeting XBOX 360! */\n#elif defined(_MSC_VER)\n\n#  include <stdlib.h>\n#  define htobe16(x) _byteswap_ushort(x)\n#  define htole16(x) (x)\n#  define be16toh(x) _byteswap_ushort(x)\n#  define le16toh(x) (x)\n\n#  define htobe32(x) _byteswap_ulong(x)\n#  define htole32(x) (x)\n#  define be32toh(x) _byteswap_ulong(x)\n#  define le32toh(x) (x)\n\n#  define htobe64(x) _byteswap_uint64(x)\n#  define htole64(x) (x)\n#  define be64toh(x) _byteswap_uint64(x)\n#  define le64toh(x) (x)\n\n/* ... for Windows (GCC-like, e.g. mingw or clang) */\n#elif (defined(_WIN32) || defined(_WIN64)) &&                                  \\\n    (defined(__GNUC__) || defined(__clang__))\n\n#  define htobe16(x) __builtin_bswap16(x)\n#  define htole16(x) (x)\n#  define be16toh(x) __builtin_bswap16(x)\n#  define le16toh(x) (x)\n\n#  define htobe32(x) __builtin_bswap32(x)\n#  define htole32(x) (x)\n#  define be32toh(x) __builtin_bswap32(x)\n#  define le32toh(x) (x)\n\n#  define htobe64(x) __builtin_bswap64(x)\n#  define htole64(x) (x)\n#  define be64toh(x) __builtin_bswap64(x)\n#  define le64toh(x) (x)\n\n/* ... generic big-endian fallback code */\n#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n\n/* byte swapping code inspired by:\n * https://github.com/rweather/arduinolibs/blob/master/libraries/Crypto/utility/EndianUtil.h\n * */\n\n#  define htobe32(x) (x)\n#  define be32toh(x) (x)\n#  define htole32(x)                                                           \\\n    (__extension__({                                                           \\\n      uint32_t _temp = (x);                                                    \\\n      ((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) |             \\\n          ((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000);          \\\n    }))\n#  define le32toh(x) (htole32((x)))\n\n#  define htobe64(x) (x)\n#  define be64toh(x) (x)\n#  define htole64(x)                                                           \\\n    (__extension__({                                                           \\\n      uint64_t __temp = (x);                                                   \\\n      uint32_t __low = htobe32((uint32_t)__temp);                              \\\n      uint32_t __high = htobe32((uint32_t)(__temp >> 32));                     \\\n      (((uint64_t)__low) << 32) | __high;                                      \\\n    }))\n#  define le64toh(x) (htole64((x)))\n\n/* ... generic little-endian fallback code */\n#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__\n\n#  define htole32(x) (x)\n#  define le32toh(x) (x)\n#  define htobe32(x)                                                           \\\n    (__extension__({                                                           \\\n      uint32_t _temp = (x);                                                    \\\n      ((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) |             \\\n          ((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000);          \\\n    }))\n#  define be32toh(x) (htobe32((x)))\n\n#  define htole64(x) (x)\n#  define le64toh(x) (x)\n#  define htobe64(x)                                                           \\\n    (__extension__({                                                           \\\n      uint64_t __temp = (x);                                                   \\\n      uint32_t __low = htobe32((uint32_t)__temp);                              \\\n      uint32_t __high = htobe32((uint32_t)(__temp >> 32));                     \\\n      (((uint64_t)__low) << 32) | __high;                                      \\\n    }))\n#  define be64toh(x) (htobe64((x)))\n\n/* ... couldn't determine endian-ness of the target platform */\n#else\n#  error \"Please define __BYTE_ORDER__!\"\n\n#endif /* defined(__linux__) || ... */\n\n/* Loads and stores. These avoid undefined behavior due to unaligned memory\n * accesses, via memcpy. */\n\ninline static uint16_t load16(uint8_t *b) {\n  uint16_t x;\n  memcpy(&x, b, 2);\n  return x;\n}\n\ninline static uint32_t load32(uint8_t *b) {\n  uint32_t x;\n  memcpy(&x, b, 4);\n  return x;\n}\n\ninline static uint64_t load64(uint8_t *b) {\n  uint64_t x;\n  memcpy(&x, b, 8);\n  return x;\n}\n\ninline static void store16(uint8_t *b, uint16_t i) {\n  memcpy(b, &i, 2);\n}\n\ninline static void store32(uint8_t *b, uint32_t i) {\n  memcpy(b, &i, 4);\n}\n\ninline static void store64(uint8_t *b, uint64_t i) {\n  memcpy(b, &i, 8);\n}\n\n#define load16_le(b) (le16toh(load16(b)))\n#define store16_le(b, i) (store16(b, htole16(i)))\n#define load16_be(b) (be16toh(load16(b)))\n#define store16_be(b, i) (store16(b, htobe16(i)))\n\n#define load32_le(b) (le32toh(load32(b)))\n#define store32_le(b, i) (store32(b, htole32(i)))\n#define load32_be(b) (be32toh(load32(b)))\n#define store32_be(b, i) (store32(b, htobe32(i)))\n\n#define load64_le(b) (le64toh(load64(b)))\n#define store64_le(b, i) (store64(b, htole64(i)))\n#define load64_be(b) (be64toh(load64(b)))\n#define store64_be(b, i) (store64(b, htobe64(i)))\n\n#endif\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/include/everest/kremlin/internal/builtin.h",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n#ifndef __KREMLIN_BUILTIN_H\n#define __KREMLIN_BUILTIN_H\n\n/* For alloca, when using KreMLin's -falloca */\n#if (defined(_WIN32) || defined(_WIN64))\n#  include <malloc.h>\n#endif\n\n/* If some globals need to be initialized before the main, then kremlin will\n * generate and try to link last a function with this type: */\nvoid kremlinit_globals(void);\n\n#endif\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/include/everest/kremlin/internal/callconv.h",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n#ifndef __KREMLIN_CALLCONV_H\n#define __KREMLIN_CALLCONV_H\n\n/******************************************************************************/\n/* Some macros to ease compatibility                                          */\n/******************************************************************************/\n\n/* We want to generate __cdecl safely without worrying about it being undefined.\n * When using MSVC, these are always defined. When using MinGW, these are\n * defined too. They have no meaning for other platforms, so we define them to\n * be empty macros in other situations. */\n#ifndef _MSC_VER\n#ifndef __cdecl\n#define __cdecl\n#endif\n#ifndef __stdcall\n#define __stdcall\n#endif\n#ifndef __fastcall\n#define __fastcall\n#endif\n#endif\n\n/* Since KreMLin emits the inline keyword unconditionally, we follow the\n * guidelines at https://gcc.gnu.org/onlinedocs/gcc/Inline.html and make this\n * __inline__ to ensure the code compiles with -std=c90 and earlier. */\n#if defined(__GNUC__)\n#  define inline __inline__\n#elif defined(_MSC_VER)\n#  define inline __inline\n#endif\n\n/* GCC-specific attribute syntax; everyone else gets the standard C inline\n * attribute. */\n#ifdef __GNU_C__\n#  ifndef __clang__\n#    define force_inline inline __attribute__((always_inline))\n#  else\n#    define force_inline inline\n#  endif\n#else\n#  define force_inline inline\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/include/everest/kremlin/internal/compat.h",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n#ifndef KRML_COMPAT_H\n#define KRML_COMPAT_H\n\n#include <inttypes.h>\n\n/* A series of macros that define C implementations of types that are not Low*,\n * to facilitate porting programs to Low*. */\n\ntypedef const char *Prims_string;\n\ntypedef struct {\n  uint32_t length;\n  const char *data;\n} FStar_Bytes_bytes;\n\ntypedef int32_t Prims_pos, Prims_nat, Prims_nonzero, Prims_int,\n    krml_checked_int_t;\n\n#define RETURN_OR(x)                                                           \\\n  do {                                                                         \\\n    int64_t __ret = x;                                                         \\\n    if (__ret < INT32_MIN || INT32_MAX < __ret) {                              \\\n      KRML_HOST_PRINTF(                                                        \\\n          \"Prims.{int,nat,pos} integer overflow at %s:%d\\n\", __FILE__,         \\\n          __LINE__);                                                           \\\n      KRML_HOST_EXIT(252);                                                     \\\n    }                                                                          \\\n    return (int32_t)__ret;                                                     \\\n  } while (0)\n\n#endif\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/include/everest/kremlin/internal/debug.h",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n#ifndef __KREMLIN_DEBUG_H\n#define __KREMLIN_DEBUG_H\n\n#include <inttypes.h>\n\n#include \"kremlin/internal/target.h\"\n\n/******************************************************************************/\n/* Debugging helpers - intended only for KreMLin developers                   */\n/******************************************************************************/\n\n/* In support of \"-wasm -d force-c\": we might need this function to be\n * forward-declared, because the dependency on WasmSupport appears very late,\n * after SimplifyWasm, and sadly, after the topological order has been done. */\nvoid WasmSupport_check_buffer_size(uint32_t s);\n\n/* A series of GCC atrocities to trace function calls (kremlin's [-d c-calls]\n * option). Useful when trying to debug, say, Wasm, to compare traces. */\n/* clang-format off */\n#ifdef __GNUC__\n#define KRML_FORMAT(X) _Generic((X),                                           \\\n  uint8_t : \"0x%08\" PRIx8,                                                     \\\n  uint16_t: \"0x%08\" PRIx16,                                                    \\\n  uint32_t: \"0x%08\" PRIx32,                                                    \\\n  uint64_t: \"0x%08\" PRIx64,                                                    \\\n  int8_t  : \"0x%08\" PRIx8,                                                     \\\n  int16_t : \"0x%08\" PRIx16,                                                    \\\n  int32_t : \"0x%08\" PRIx32,                                                    \\\n  int64_t : \"0x%08\" PRIx64,                                                    \\\n  default : \"%s\")\n\n#define KRML_FORMAT_ARG(X) _Generic((X),                                       \\\n  uint8_t : X,                                                                 \\\n  uint16_t: X,                                                                 \\\n  uint32_t: X,                                                                 \\\n  uint64_t: X,                                                                 \\\n  int8_t  : X,                                                                 \\\n  int16_t : X,                                                                 \\\n  int32_t : X,                                                                 \\\n  int64_t : X,                                                                 \\\n  default : \"unknown\")\n/* clang-format on */\n\n#  define KRML_DEBUG_RETURN(X)                                                 \\\n    ({                                                                         \\\n      __auto_type _ret = (X);                                                  \\\n      KRML_HOST_PRINTF(\"returning: \");                                         \\\n      KRML_HOST_PRINTF(KRML_FORMAT(_ret), KRML_FORMAT_ARG(_ret));              \\\n      KRML_HOST_PRINTF(\" \\n\");                                                 \\\n      _ret;                                                                    \\\n    })\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/include/everest/kremlin/internal/target.h",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n#ifndef __KREMLIN_TARGET_H\n#define __KREMLIN_TARGET_H\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdbool.h>\n#include <inttypes.h>\n#include <limits.h>\n\n#include \"kremlin/internal/callconv.h\"\n\n/******************************************************************************/\n/* Macros that KreMLin will generate.                                         */\n/******************************************************************************/\n\n/* For \"bare\" targets that do not have a C stdlib, the user might want to use\n * [-add-early-include '\"mydefinitions.h\"'] and override these. */\n#ifndef KRML_HOST_PRINTF\n#  define KRML_HOST_PRINTF printf\n#endif\n\n#if (                                                                          \\\n    (defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) &&             \\\n    (!(defined KRML_HOST_EPRINTF)))\n#  define KRML_HOST_EPRINTF(...) fprintf(stderr, __VA_ARGS__)\n#endif\n\n#ifndef KRML_HOST_EXIT\n#  define KRML_HOST_EXIT exit\n#endif\n\n#ifndef KRML_HOST_MALLOC\n#  define KRML_HOST_MALLOC malloc\n#endif\n\n#ifndef KRML_HOST_CALLOC\n#  define KRML_HOST_CALLOC calloc\n#endif\n\n#ifndef KRML_HOST_FREE\n#  define KRML_HOST_FREE free\n#endif\n\n#ifndef KRML_HOST_TIME\n\n#  include <time.h>\n\n/* Prims_nat not yet in scope */\ninline static int32_t krml_time() {\n  return (int32_t)time(NULL);\n}\n\n#  define KRML_HOST_TIME krml_time\n#endif\n\n/* In statement position, exiting is easy. */\n#define KRML_EXIT                                                              \\\n  do {                                                                         \\\n    KRML_HOST_PRINTF(\"Unimplemented function at %s:%d\\n\", __FILE__, __LINE__); \\\n    KRML_HOST_EXIT(254);                                                       \\\n  } while (0)\n\n/* In expression position, use the comma-operator and a malloc to return an\n * expression of the right size. KreMLin passes t as the parameter to the macro.\n */\n#define KRML_EABORT(t, msg)                                                    \\\n  (KRML_HOST_PRINTF(\"KreMLin abort at %s:%d\\n%s\\n\", __FILE__, __LINE__, msg),  \\\n   KRML_HOST_EXIT(255), *((t *)KRML_HOST_MALLOC(sizeof(t))))\n\n/* In FStar.Buffer.fst, the size of arrays is uint32_t, but it's a number of\n * *elements*. Do an ugly, run-time check (some of which KreMLin can eliminate).\n */\n\n#ifdef __GNUC__\n#  define _KRML_CHECK_SIZE_PRAGMA                                              \\\n    _Pragma(\"GCC diagnostic ignored \\\"-Wtype-limits\\\"\")\n#else\n#  define _KRML_CHECK_SIZE_PRAGMA\n#endif\n\n#define KRML_CHECK_SIZE(size_elt, sz)                                          \\\n  do {                                                                         \\\n    _KRML_CHECK_SIZE_PRAGMA                                                    \\\n    if (((size_t)(sz)) > ((size_t)(SIZE_MAX / (size_elt)))) {                  \\\n      KRML_HOST_PRINTF(                                                        \\\n          \"Maximum allocatable size exceeded, aborting before overflow at \"    \\\n          \"%s:%d\\n\",                                                           \\\n          __FILE__, __LINE__);                                                 \\\n      KRML_HOST_EXIT(253);                                                     \\\n    }                                                                          \\\n  } while (0)\n\n#if defined(_MSC_VER) && _MSC_VER < 1900\n#  define KRML_HOST_SNPRINTF(buf, sz, fmt, arg) _snprintf_s(buf, sz, _TRUNCATE, fmt, arg)\n#else\n#  define KRML_HOST_SNPRINTF(buf, sz, fmt, arg) snprintf(buf, sz, fmt, arg)\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/include/everest/kremlin/internal/types.h",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n#ifndef KRML_TYPES_H\n#define KRML_TYPES_H\n\n#include <inttypes.h>\n#include <stdio.h>\n#include <stdlib.h>\n\n/* Types which are either abstract, meaning that have to be implemented in C, or\n * which are models, meaning that they are swapped out at compile-time for\n * hand-written C types (in which case they're marked as noextract). */\n\ntypedef uint64_t FStar_UInt64_t, FStar_UInt64_t_;\ntypedef int64_t FStar_Int64_t, FStar_Int64_t_;\ntypedef uint32_t FStar_UInt32_t, FStar_UInt32_t_;\ntypedef int32_t FStar_Int32_t, FStar_Int32_t_;\ntypedef uint16_t FStar_UInt16_t, FStar_UInt16_t_;\ntypedef int16_t FStar_Int16_t, FStar_Int16_t_;\ntypedef uint8_t FStar_UInt8_t, FStar_UInt8_t_;\ntypedef int8_t FStar_Int8_t, FStar_Int8_t_;\n\n/* Only useful when building Kremlib, because it's in the dependency graph of\n * FStar.Int.Cast. */\ntypedef uint64_t FStar_UInt63_t, FStar_UInt63_t_;\ntypedef int64_t FStar_Int63_t, FStar_Int63_t_;\n\ntypedef double FStar_Float_float;\ntypedef uint32_t FStar_Char_char;\ntypedef FILE *FStar_IO_fd_read, *FStar_IO_fd_write;\n\ntypedef void *FStar_Dyn_dyn;\n\ntypedef const char *C_String_t, *C_String_t_;\n\ntypedef int exit_code;\ntypedef FILE *channel;\n\ntypedef unsigned long long TestLib_cycles;\n\ntypedef uint64_t FStar_Date_dateTime, FStar_Date_timeSpan;\n\n/* The uint128 type is a special case since we offer several implementations of\n * it, depending on the compiler and whether the user wants the verified\n * implementation or not. */\n#if !defined(KRML_VERIFIED_UINT128) && defined(_MSC_VER) && defined(_M_X64)\n#  include <emmintrin.h>\ntypedef __m128i FStar_UInt128_uint128;\n#elif !defined(KRML_VERIFIED_UINT128) && !defined(_MSC_VER)\ntypedef unsigned __int128 FStar_UInt128_uint128;\n#else\ntypedef struct FStar_UInt128_uint128_s {\n  uint64_t low;\n  uint64_t high;\n} FStar_UInt128_uint128;\n#endif\n\ntypedef FStar_UInt128_uint128 FStar_UInt128_t, FStar_UInt128_t_, uint128_t;\n\n#endif\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/include/everest/kremlin/internal/wasmsupport.h",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n/* This file is automatically included when compiling with -wasm -d force-c */\n#define WasmSupport_check_buffer_size(X)\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/include/everest/vs2013/Hacl_Curve25519.h",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>\n * KreMLin invocation: /mnt/e/everest/verify/kremlin/krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -I /mnt/e/everest/verify/hacl-star/code/lib/kremlin -I /mnt/e/everest/verify/kremlin/kremlib/compat -I /mnt/e/everest/verify/hacl-star/specs -I /mnt/e/everest/verify/hacl-star/specs/old -I . -ccopt -march=native -verbose -ldopt -flto -tmpdir x25519-c -I ../bignum -bundle Hacl.Curve25519=* -minimal -add-include \"kremlib.h\" -skip-compilation x25519-c/out.krml -o x25519-c/Hacl_Curve25519.c\n * F* version: 059db0c8\n * KreMLin version: 916c37ac\n */\n\n\n\n#ifndef __Hacl_Curve25519_H\n#define __Hacl_Curve25519_H\n\n\n#include \"kremlib.h\"\n\nvoid Hacl_Curve25519_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint);\n\n#define __Hacl_Curve25519_H_DEFINED\n#endif\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/include/everest/x25519.h",
    "content": "/*\n *  ECDH with curve-optimized implementation multiplexing\n *\n *  Copyright 2016-2018 INRIA and Microsoft Corporation\n *  SPDX-License-Identifier: Apache-2.0\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n *  not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *  http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *  This file is part of Mbed TLS (https://tls.mbed.org)\n */\n\n#ifndef MBEDTLS_X25519_H\n#define MBEDTLS_X25519_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define MBEDTLS_ECP_TLS_CURVE25519 0x1d\n#define MBEDTLS_X25519_KEY_SIZE_BYTES 32\n\n/**\n * Defines the source of the imported EC key.\n */\ntypedef enum\n{\n    MBEDTLS_X25519_ECDH_OURS,   /**< Our key. */\n    MBEDTLS_X25519_ECDH_THEIRS, /**< The key of the peer. */\n} mbedtls_x25519_ecdh_side;\n\n/**\n * \\brief           The x25519 context structure.\n */\ntypedef struct\n{\n  unsigned char our_secret[MBEDTLS_X25519_KEY_SIZE_BYTES];\n  unsigned char peer_point[MBEDTLS_X25519_KEY_SIZE_BYTES];\n} mbedtls_x25519_context;\n\n/**\n * \\brief           This function initializes an x25519 context.\n *\n * \\param ctx       The x25519 context to initialize.\n */\nvoid mbedtls_x25519_init( mbedtls_x25519_context *ctx );\n\n/**\n * \\brief           This function frees a context.\n *\n * \\param ctx       The context to free.\n */\nvoid mbedtls_x25519_free( mbedtls_x25519_context *ctx );\n\n/**\n * \\brief           This function generates a public key and a TLS\n *                  ServerKeyExchange payload.\n *\n *                  This is the first function used by a TLS server for x25519.\n *\n *\n * \\param ctx       The x25519 context.\n * \\param olen      The number of characters written.\n * \\param buf       The destination buffer.\n * \\param blen      The length of the destination buffer.\n * \\param f_rng     The RNG function.\n * \\param p_rng     The RNG context.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n */\nint mbedtls_x25519_make_params( mbedtls_x25519_context *ctx, size_t *olen,\n                        unsigned char *buf, size_t blen,\n                        int( *f_rng )(void *, unsigned char *, size_t),\n                        void *p_rng );\n\n/**\n * \\brief           This function parses and processes a TLS ServerKeyExchange\n *                  payload.\n *\n *\n * \\param ctx       The x25519 context.\n * \\param buf       The pointer to the start of the input buffer.\n * \\param end       The address for one Byte past the end of the buffer.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n *\n */\nint mbedtls_x25519_read_params( mbedtls_x25519_context *ctx,\n                        const unsigned char **buf, const unsigned char *end );\n\n/**\n * \\brief           This function sets up an x25519 context from an EC key.\n *\n *                  It is used by clients and servers in place of the\n *                  ServerKeyEchange for static ECDH, and imports ECDH\n *                  parameters from the EC key information of a certificate.\n *\n * \\see             ecp.h\n *\n * \\param ctx       The x25519 context to set up.\n * \\param key       The EC key to use.\n * \\param side      Defines the source of the key: 1: Our key, or\n *                  0: The key of the peer.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n *\n */\nint mbedtls_x25519_get_params( mbedtls_x25519_context *ctx, const mbedtls_ecp_keypair *key,\n                               mbedtls_x25519_ecdh_side side );\n\n/**\n * \\brief           This function derives and exports the shared secret.\n *\n *                  This is the last function used by both TLS client\n *                  and servers.\n *\n *\n * \\param ctx       The x25519 context.\n * \\param olen      The number of Bytes written.\n * \\param buf       The destination buffer.\n * \\param blen      The length of the destination buffer.\n * \\param f_rng     The RNG function.\n * \\param p_rng     The RNG context.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n */\nint mbedtls_x25519_calc_secret( mbedtls_x25519_context *ctx, size_t *olen,\n                        unsigned char *buf, size_t blen,\n                        int( *f_rng )(void *, unsigned char *, size_t),\n                        void *p_rng );\n\n/**\n * \\brief           This function generates a public key and a TLS\n *                  ClientKeyExchange payload.\n *\n *                  This is the second function used by a TLS client for x25519.\n *\n * \\see             ecp.h\n *\n * \\param ctx       The x25519 context.\n * \\param olen      The number of Bytes written.\n * \\param buf       The destination buffer.\n * \\param blen      The size of the destination buffer.\n * \\param f_rng     The RNG function.\n * \\param p_rng     The RNG context.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n */\nint mbedtls_x25519_make_public( mbedtls_x25519_context *ctx, size_t *olen,\n                        unsigned char *buf, size_t blen,\n                        int( *f_rng )(void *, unsigned char *, size_t),\n                        void *p_rng );\n\n/**\n * \\brief       This function parses and processes a TLS ClientKeyExchange\n *              payload.\n *\n *              This is the second function used by a TLS server for x25519.\n *\n * \\see         ecp.h\n *\n * \\param ctx   The x25519 context.\n * \\param buf   The start of the input buffer.\n * \\param blen  The length of the input buffer.\n *\n * \\return      \\c 0 on success.\n * \\return      An \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n */\nint mbedtls_x25519_read_public( mbedtls_x25519_context *ctx,\n                        const unsigned char *buf, size_t blen );\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* x25519.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/library/Hacl_Curve25519.c",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>\n * KreMLin invocation: /mnt/e/everest/verify/kremlin/krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -fbuiltin-uint128 -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -I /mnt/e/everest/verify/hacl-star/code/lib/kremlin -I /mnt/e/everest/verify/kremlin/kremlib/compat -I /mnt/e/everest/verify/hacl-star/specs -I /mnt/e/everest/verify/hacl-star/specs/old -I . -ccopt -march=native -verbose -ldopt -flto -tmpdir x25519-c -I ../bignum -bundle Hacl.Curve25519=* -minimal -add-include \"kremlib.h\" -skip-compilation x25519-c/out.krml -o x25519-c/Hacl_Curve25519.c\n * F* version: 059db0c8\n * KreMLin version: 916c37ac\n */\n\n\n#include \"Hacl_Curve25519.h\"\n\nextern uint64_t FStar_UInt64_eq_mask(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_gte_mask(uint64_t x0, uint64_t x1);\n\nextern uint128_t FStar_UInt128_add(uint128_t x0, uint128_t x1);\n\nextern uint128_t FStar_UInt128_add_mod(uint128_t x0, uint128_t x1);\n\nextern uint128_t FStar_UInt128_logand(uint128_t x0, uint128_t x1);\n\nextern uint128_t FStar_UInt128_shift_right(uint128_t x0, uint32_t x1);\n\nextern uint128_t FStar_UInt128_uint64_to_uint128(uint64_t x0);\n\nextern uint64_t FStar_UInt128_uint128_to_uint64(uint128_t x0);\n\nextern uint128_t FStar_UInt128_mul_wide(uint64_t x0, uint64_t x1);\n\nstatic void Hacl_Bignum_Modulo_carry_top(uint64_t *b)\n{\n  uint64_t b4 = b[4U];\n  uint64_t b0 = b[0U];\n  uint64_t b4_ = b4 & (uint64_t)0x7ffffffffffffU;\n  uint64_t b0_ = b0 + (uint64_t)19U * (b4 >> (uint32_t)51U);\n  b[4U] = b4_;\n  b[0U] = b0_;\n}\n\ninline static void Hacl_Bignum_Fproduct_copy_from_wide_(uint64_t *output, uint128_t *input)\n{\n  uint32_t i;\n  for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U)\n  {\n    uint128_t xi = input[i];\n    output[i] = (uint64_t)xi;\n  }\n}\n\ninline static void\nHacl_Bignum_Fproduct_sum_scalar_multiplication_(uint128_t *output, uint64_t *input, uint64_t s)\n{\n  uint32_t i;\n  for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U)\n  {\n    uint128_t xi = output[i];\n    uint64_t yi = input[i];\n    output[i] = xi + (uint128_t)yi * s;\n  }\n}\n\ninline static void Hacl_Bignum_Fproduct_carry_wide_(uint128_t *tmp)\n{\n  uint32_t i;\n  for (i = (uint32_t)0U; i < (uint32_t)4U; i = i + (uint32_t)1U)\n  {\n    uint32_t ctr = i;\n    uint128_t tctr = tmp[ctr];\n    uint128_t tctrp1 = tmp[ctr + (uint32_t)1U];\n    uint64_t r0 = (uint64_t)tctr & (uint64_t)0x7ffffffffffffU;\n    uint128_t c = tctr >> (uint32_t)51U;\n    tmp[ctr] = (uint128_t)r0;\n    tmp[ctr + (uint32_t)1U] = tctrp1 + c;\n  }\n}\n\ninline static void Hacl_Bignum_Fmul_shift_reduce(uint64_t *output)\n{\n  uint64_t tmp = output[4U];\n  uint64_t b0;\n  {\n    uint32_t i;\n    for (i = (uint32_t)0U; i < (uint32_t)4U; i = i + (uint32_t)1U)\n    {\n      uint32_t ctr = (uint32_t)5U - i - (uint32_t)1U;\n      uint64_t z = output[ctr - (uint32_t)1U];\n      output[ctr] = z;\n    }\n  }\n  output[0U] = tmp;\n  b0 = output[0U];\n  output[0U] = (uint64_t)19U * b0;\n}\n\nstatic void\nHacl_Bignum_Fmul_mul_shift_reduce_(uint128_t *output, uint64_t *input, uint64_t *input2)\n{\n  uint32_t i;\n  uint64_t input2i;\n  {\n    uint32_t i0;\n    for (i0 = (uint32_t)0U; i0 < (uint32_t)4U; i0 = i0 + (uint32_t)1U)\n    {\n      uint64_t input2i0 = input2[i0];\n      Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i0);\n      Hacl_Bignum_Fmul_shift_reduce(input);\n    }\n  }\n  i = (uint32_t)4U;\n  input2i = input2[i];\n  Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i);\n}\n\ninline static void Hacl_Bignum_Fmul_fmul(uint64_t *output, uint64_t *input, uint64_t *input2)\n{\n  uint64_t tmp[5U] = { 0U };\n  memcpy(tmp, input, (uint32_t)5U * sizeof input[0U]);\n  KRML_CHECK_SIZE(sizeof (uint128_t), (uint32_t)5U);\n  {\n    uint128_t t[5U];\n    {\n      uint32_t _i;\n      for (_i = 0U; _i < (uint32_t)5U; ++_i)\n        t[_i] = (uint128_t)(uint64_t)0U;\n    }\n    {\n      uint128_t b4;\n      uint128_t b0;\n      uint128_t b4_;\n      uint128_t b0_;\n      uint64_t i0;\n      uint64_t i1;\n      uint64_t i0_;\n      uint64_t i1_;\n      Hacl_Bignum_Fmul_mul_shift_reduce_(t, tmp, input2);\n      Hacl_Bignum_Fproduct_carry_wide_(t);\n      b4 = t[4U];\n      b0 = t[0U];\n      b4_ = b4 & (uint128_t)(uint64_t)0x7ffffffffffffU;\n      b0_ = b0 + (uint128_t)(uint64_t)19U * (uint64_t)(b4 >> (uint32_t)51U);\n      t[4U] = b4_;\n      t[0U] = b0_;\n      Hacl_Bignum_Fproduct_copy_from_wide_(output, t);\n      i0 = output[0U];\n      i1 = output[1U];\n      i0_ = i0 & (uint64_t)0x7ffffffffffffU;\n      i1_ = i1 + (i0 >> (uint32_t)51U);\n      output[0U] = i0_;\n      output[1U] = i1_;\n    }\n  }\n}\n\ninline static void Hacl_Bignum_Fsquare_fsquare__(uint128_t *tmp, uint64_t *output)\n{\n  uint64_t r0 = output[0U];\n  uint64_t r1 = output[1U];\n  uint64_t r2 = output[2U];\n  uint64_t r3 = output[3U];\n  uint64_t r4 = output[4U];\n  uint64_t d0 = r0 * (uint64_t)2U;\n  uint64_t d1 = r1 * (uint64_t)2U;\n  uint64_t d2 = r2 * (uint64_t)2U * (uint64_t)19U;\n  uint64_t d419 = r4 * (uint64_t)19U;\n  uint64_t d4 = d419 * (uint64_t)2U;\n  uint128_t s0 = (uint128_t)r0 * r0 + (uint128_t)d4 * r1 + (uint128_t)d2 * r3;\n  uint128_t s1 = (uint128_t)d0 * r1 + (uint128_t)d4 * r2 + (uint128_t)(r3 * (uint64_t)19U) * r3;\n  uint128_t s2 = (uint128_t)d0 * r2 + (uint128_t)r1 * r1 + (uint128_t)d4 * r3;\n  uint128_t s3 = (uint128_t)d0 * r3 + (uint128_t)d1 * r2 + (uint128_t)r4 * d419;\n  uint128_t s4 = (uint128_t)d0 * r4 + (uint128_t)d1 * r3 + (uint128_t)r2 * r2;\n  tmp[0U] = s0;\n  tmp[1U] = s1;\n  tmp[2U] = s2;\n  tmp[3U] = s3;\n  tmp[4U] = s4;\n}\n\ninline static void Hacl_Bignum_Fsquare_fsquare_(uint128_t *tmp, uint64_t *output)\n{\n  uint128_t b4;\n  uint128_t b0;\n  uint128_t b4_;\n  uint128_t b0_;\n  uint64_t i0;\n  uint64_t i1;\n  uint64_t i0_;\n  uint64_t i1_;\n  Hacl_Bignum_Fsquare_fsquare__(tmp, output);\n  Hacl_Bignum_Fproduct_carry_wide_(tmp);\n  b4 = tmp[4U];\n  b0 = tmp[0U];\n  b4_ = b4 & (uint128_t)(uint64_t)0x7ffffffffffffU;\n  b0_ = b0 + (uint128_t)(uint64_t)19U * (uint64_t)(b4 >> (uint32_t)51U);\n  tmp[4U] = b4_;\n  tmp[0U] = b0_;\n  Hacl_Bignum_Fproduct_copy_from_wide_(output, tmp);\n  i0 = output[0U];\n  i1 = output[1U];\n  i0_ = i0 & (uint64_t)0x7ffffffffffffU;\n  i1_ = i1 + (i0 >> (uint32_t)51U);\n  output[0U] = i0_;\n  output[1U] = i1_;\n}\n\nstatic void\nHacl_Bignum_Fsquare_fsquare_times_(uint64_t *input, uint128_t *tmp, uint32_t count1)\n{\n  uint32_t i;\n  Hacl_Bignum_Fsquare_fsquare_(tmp, input);\n  for (i = (uint32_t)1U; i < count1; i = i + (uint32_t)1U)\n    Hacl_Bignum_Fsquare_fsquare_(tmp, input);\n}\n\ninline static void\nHacl_Bignum_Fsquare_fsquare_times(uint64_t *output, uint64_t *input, uint32_t count1)\n{\n  KRML_CHECK_SIZE(sizeof (uint128_t), (uint32_t)5U);\n  {\n    uint128_t t[5U];\n    {\n      uint32_t _i;\n      for (_i = 0U; _i < (uint32_t)5U; ++_i)\n        t[_i] = (uint128_t)(uint64_t)0U;\n    }\n    memcpy(output, input, (uint32_t)5U * sizeof input[0U]);\n    Hacl_Bignum_Fsquare_fsquare_times_(output, t, count1);\n  }\n}\n\ninline static void Hacl_Bignum_Fsquare_fsquare_times_inplace(uint64_t *output, uint32_t count1)\n{\n  KRML_CHECK_SIZE(sizeof (uint128_t), (uint32_t)5U);\n  {\n    uint128_t t[5U];\n    {\n      uint32_t _i;\n      for (_i = 0U; _i < (uint32_t)5U; ++_i)\n        t[_i] = (uint128_t)(uint64_t)0U;\n    }\n    Hacl_Bignum_Fsquare_fsquare_times_(output, t, count1);\n  }\n}\n\ninline static void Hacl_Bignum_Crecip_crecip(uint64_t *out, uint64_t *z)\n{\n  uint64_t buf[20U] = { 0U };\n  uint64_t *a0 = buf;\n  uint64_t *t00 = buf + (uint32_t)5U;\n  uint64_t *b0 = buf + (uint32_t)10U;\n  uint64_t *t01;\n  uint64_t *b1;\n  uint64_t *c0;\n  uint64_t *a;\n  uint64_t *t0;\n  uint64_t *b;\n  uint64_t *c;\n  Hacl_Bignum_Fsquare_fsquare_times(a0, z, (uint32_t)1U);\n  Hacl_Bignum_Fsquare_fsquare_times(t00, a0, (uint32_t)2U);\n  Hacl_Bignum_Fmul_fmul(b0, t00, z);\n  Hacl_Bignum_Fmul_fmul(a0, b0, a0);\n  Hacl_Bignum_Fsquare_fsquare_times(t00, a0, (uint32_t)1U);\n  Hacl_Bignum_Fmul_fmul(b0, t00, b0);\n  Hacl_Bignum_Fsquare_fsquare_times(t00, b0, (uint32_t)5U);\n  t01 = buf + (uint32_t)5U;\n  b1 = buf + (uint32_t)10U;\n  c0 = buf + (uint32_t)15U;\n  Hacl_Bignum_Fmul_fmul(b1, t01, b1);\n  Hacl_Bignum_Fsquare_fsquare_times(t01, b1, (uint32_t)10U);\n  Hacl_Bignum_Fmul_fmul(c0, t01, b1);\n  Hacl_Bignum_Fsquare_fsquare_times(t01, c0, (uint32_t)20U);\n  Hacl_Bignum_Fmul_fmul(t01, t01, c0);\n  Hacl_Bignum_Fsquare_fsquare_times_inplace(t01, (uint32_t)10U);\n  Hacl_Bignum_Fmul_fmul(b1, t01, b1);\n  Hacl_Bignum_Fsquare_fsquare_times(t01, b1, (uint32_t)50U);\n  a = buf;\n  t0 = buf + (uint32_t)5U;\n  b = buf + (uint32_t)10U;\n  c = buf + (uint32_t)15U;\n  Hacl_Bignum_Fmul_fmul(c, t0, b);\n  Hacl_Bignum_Fsquare_fsquare_times(t0, c, (uint32_t)100U);\n  Hacl_Bignum_Fmul_fmul(t0, t0, c);\n  Hacl_Bignum_Fsquare_fsquare_times_inplace(t0, (uint32_t)50U);\n  Hacl_Bignum_Fmul_fmul(t0, t0, b);\n  Hacl_Bignum_Fsquare_fsquare_times_inplace(t0, (uint32_t)5U);\n  Hacl_Bignum_Fmul_fmul(out, t0, a);\n}\n\ninline static void Hacl_Bignum_fsum(uint64_t *a, uint64_t *b)\n{\n  uint32_t i;\n  for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U)\n  {\n    uint64_t xi = a[i];\n    uint64_t yi = b[i];\n    a[i] = xi + yi;\n  }\n}\n\ninline static void Hacl_Bignum_fdifference(uint64_t *a, uint64_t *b)\n{\n  uint64_t tmp[5U] = { 0U };\n  uint64_t b0;\n  uint64_t b1;\n  uint64_t b2;\n  uint64_t b3;\n  uint64_t b4;\n  memcpy(tmp, b, (uint32_t)5U * sizeof b[0U]);\n  b0 = tmp[0U];\n  b1 = tmp[1U];\n  b2 = tmp[2U];\n  b3 = tmp[3U];\n  b4 = tmp[4U];\n  tmp[0U] = b0 + (uint64_t)0x3fffffffffff68U;\n  tmp[1U] = b1 + (uint64_t)0x3ffffffffffff8U;\n  tmp[2U] = b2 + (uint64_t)0x3ffffffffffff8U;\n  tmp[3U] = b3 + (uint64_t)0x3ffffffffffff8U;\n  tmp[4U] = b4 + (uint64_t)0x3ffffffffffff8U;\n  {\n    uint32_t i;\n    for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U)\n    {\n      uint64_t xi = a[i];\n      uint64_t yi = tmp[i];\n      a[i] = yi - xi;\n    }\n  }\n}\n\ninline static void Hacl_Bignum_fscalar(uint64_t *output, uint64_t *b, uint64_t s)\n{\n  KRML_CHECK_SIZE(sizeof (uint128_t), (uint32_t)5U);\n  {\n    uint128_t tmp[5U];\n    {\n      uint32_t _i;\n      for (_i = 0U; _i < (uint32_t)5U; ++_i)\n        tmp[_i] = (uint128_t)(uint64_t)0U;\n    }\n    {\n      uint128_t b4;\n      uint128_t b0;\n      uint128_t b4_;\n      uint128_t b0_;\n      {\n        uint32_t i;\n        for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U)\n        {\n          uint64_t xi = b[i];\n          tmp[i] = (uint128_t)xi * s;\n        }\n      }\n      Hacl_Bignum_Fproduct_carry_wide_(tmp);\n      b4 = tmp[4U];\n      b0 = tmp[0U];\n      b4_ = b4 & (uint128_t)(uint64_t)0x7ffffffffffffU;\n      b0_ = b0 + (uint128_t)(uint64_t)19U * (uint64_t)(b4 >> (uint32_t)51U);\n      tmp[4U] = b4_;\n      tmp[0U] = b0_;\n      Hacl_Bignum_Fproduct_copy_from_wide_(output, tmp);\n    }\n  }\n}\n\ninline static void Hacl_Bignum_fmul(uint64_t *output, uint64_t *a, uint64_t *b)\n{\n  Hacl_Bignum_Fmul_fmul(output, a, b);\n}\n\ninline static void Hacl_Bignum_crecip(uint64_t *output, uint64_t *input)\n{\n  Hacl_Bignum_Crecip_crecip(output, input);\n}\n\nstatic void\nHacl_EC_Point_swap_conditional_step(uint64_t *a, uint64_t *b, uint64_t swap1, uint32_t ctr)\n{\n  uint32_t i = ctr - (uint32_t)1U;\n  uint64_t ai = a[i];\n  uint64_t bi = b[i];\n  uint64_t x = swap1 & (ai ^ bi);\n  uint64_t ai1 = ai ^ x;\n  uint64_t bi1 = bi ^ x;\n  a[i] = ai1;\n  b[i] = bi1;\n}\n\nstatic void\nHacl_EC_Point_swap_conditional_(uint64_t *a, uint64_t *b, uint64_t swap1, uint32_t ctr)\n{\n  if (!(ctr == (uint32_t)0U))\n  {\n    uint32_t i;\n    Hacl_EC_Point_swap_conditional_step(a, b, swap1, ctr);\n    i = ctr - (uint32_t)1U;\n    Hacl_EC_Point_swap_conditional_(a, b, swap1, i);\n  }\n}\n\nstatic void Hacl_EC_Point_swap_conditional(uint64_t *a, uint64_t *b, uint64_t iswap)\n{\n  uint64_t swap1 = (uint64_t)0U - iswap;\n  Hacl_EC_Point_swap_conditional_(a, b, swap1, (uint32_t)5U);\n  Hacl_EC_Point_swap_conditional_(a + (uint32_t)5U, b + (uint32_t)5U, swap1, (uint32_t)5U);\n}\n\nstatic void Hacl_EC_Point_copy(uint64_t *output, uint64_t *input)\n{\n  memcpy(output, input, (uint32_t)5U * sizeof input[0U]);\n  memcpy(output + (uint32_t)5U,\n    input + (uint32_t)5U,\n    (uint32_t)5U * sizeof (input + (uint32_t)5U)[0U]);\n}\n\nstatic void Hacl_EC_Format_fexpand(uint64_t *output, uint8_t *input)\n{\n  uint64_t i0 = load64_le(input);\n  uint8_t *x00 = input + (uint32_t)6U;\n  uint64_t i1 = load64_le(x00);\n  uint8_t *x01 = input + (uint32_t)12U;\n  uint64_t i2 = load64_le(x01);\n  uint8_t *x02 = input + (uint32_t)19U;\n  uint64_t i3 = load64_le(x02);\n  uint8_t *x0 = input + (uint32_t)24U;\n  uint64_t i4 = load64_le(x0);\n  uint64_t output0 = i0 & (uint64_t)0x7ffffffffffffU;\n  uint64_t output1 = i1 >> (uint32_t)3U & (uint64_t)0x7ffffffffffffU;\n  uint64_t output2 = i2 >> (uint32_t)6U & (uint64_t)0x7ffffffffffffU;\n  uint64_t output3 = i3 >> (uint32_t)1U & (uint64_t)0x7ffffffffffffU;\n  uint64_t output4 = i4 >> (uint32_t)12U & (uint64_t)0x7ffffffffffffU;\n  output[0U] = output0;\n  output[1U] = output1;\n  output[2U] = output2;\n  output[3U] = output3;\n  output[4U] = output4;\n}\n\nstatic void Hacl_EC_Format_fcontract_first_carry_pass(uint64_t *input)\n{\n  uint64_t t0 = input[0U];\n  uint64_t t1 = input[1U];\n  uint64_t t2 = input[2U];\n  uint64_t t3 = input[3U];\n  uint64_t t4 = input[4U];\n  uint64_t t1_ = t1 + (t0 >> (uint32_t)51U);\n  uint64_t t0_ = t0 & (uint64_t)0x7ffffffffffffU;\n  uint64_t t2_ = t2 + (t1_ >> (uint32_t)51U);\n  uint64_t t1__ = t1_ & (uint64_t)0x7ffffffffffffU;\n  uint64_t t3_ = t3 + (t2_ >> (uint32_t)51U);\n  uint64_t t2__ = t2_ & (uint64_t)0x7ffffffffffffU;\n  uint64_t t4_ = t4 + (t3_ >> (uint32_t)51U);\n  uint64_t t3__ = t3_ & (uint64_t)0x7ffffffffffffU;\n  input[0U] = t0_;\n  input[1U] = t1__;\n  input[2U] = t2__;\n  input[3U] = t3__;\n  input[4U] = t4_;\n}\n\nstatic void Hacl_EC_Format_fcontract_first_carry_full(uint64_t *input)\n{\n  Hacl_EC_Format_fcontract_first_carry_pass(input);\n  Hacl_Bignum_Modulo_carry_top(input);\n}\n\nstatic void Hacl_EC_Format_fcontract_second_carry_pass(uint64_t *input)\n{\n  uint64_t t0 = input[0U];\n  uint64_t t1 = input[1U];\n  uint64_t t2 = input[2U];\n  uint64_t t3 = input[3U];\n  uint64_t t4 = input[4U];\n  uint64_t t1_ = t1 + (t0 >> (uint32_t)51U);\n  uint64_t t0_ = t0 & (uint64_t)0x7ffffffffffffU;\n  uint64_t t2_ = t2 + (t1_ >> (uint32_t)51U);\n  uint64_t t1__ = t1_ & (uint64_t)0x7ffffffffffffU;\n  uint64_t t3_ = t3 + (t2_ >> (uint32_t)51U);\n  uint64_t t2__ = t2_ & (uint64_t)0x7ffffffffffffU;\n  uint64_t t4_ = t4 + (t3_ >> (uint32_t)51U);\n  uint64_t t3__ = t3_ & (uint64_t)0x7ffffffffffffU;\n  input[0U] = t0_;\n  input[1U] = t1__;\n  input[2U] = t2__;\n  input[3U] = t3__;\n  input[4U] = t4_;\n}\n\nstatic void Hacl_EC_Format_fcontract_second_carry_full(uint64_t *input)\n{\n  uint64_t i0;\n  uint64_t i1;\n  uint64_t i0_;\n  uint64_t i1_;\n  Hacl_EC_Format_fcontract_second_carry_pass(input);\n  Hacl_Bignum_Modulo_carry_top(input);\n  i0 = input[0U];\n  i1 = input[1U];\n  i0_ = i0 & (uint64_t)0x7ffffffffffffU;\n  i1_ = i1 + (i0 >> (uint32_t)51U);\n  input[0U] = i0_;\n  input[1U] = i1_;\n}\n\nstatic void Hacl_EC_Format_fcontract_trim(uint64_t *input)\n{\n  uint64_t a0 = input[0U];\n  uint64_t a1 = input[1U];\n  uint64_t a2 = input[2U];\n  uint64_t a3 = input[3U];\n  uint64_t a4 = input[4U];\n  uint64_t mask0 = FStar_UInt64_gte_mask(a0, (uint64_t)0x7ffffffffffedU);\n  uint64_t mask1 = FStar_UInt64_eq_mask(a1, (uint64_t)0x7ffffffffffffU);\n  uint64_t mask2 = FStar_UInt64_eq_mask(a2, (uint64_t)0x7ffffffffffffU);\n  uint64_t mask3 = FStar_UInt64_eq_mask(a3, (uint64_t)0x7ffffffffffffU);\n  uint64_t mask4 = FStar_UInt64_eq_mask(a4, (uint64_t)0x7ffffffffffffU);\n  uint64_t mask = (((mask0 & mask1) & mask2) & mask3) & mask4;\n  uint64_t a0_ = a0 - ((uint64_t)0x7ffffffffffedU & mask);\n  uint64_t a1_ = a1 - ((uint64_t)0x7ffffffffffffU & mask);\n  uint64_t a2_ = a2 - ((uint64_t)0x7ffffffffffffU & mask);\n  uint64_t a3_ = a3 - ((uint64_t)0x7ffffffffffffU & mask);\n  uint64_t a4_ = a4 - ((uint64_t)0x7ffffffffffffU & mask);\n  input[0U] = a0_;\n  input[1U] = a1_;\n  input[2U] = a2_;\n  input[3U] = a3_;\n  input[4U] = a4_;\n}\n\nstatic void Hacl_EC_Format_fcontract_store(uint8_t *output, uint64_t *input)\n{\n  uint64_t t0 = input[0U];\n  uint64_t t1 = input[1U];\n  uint64_t t2 = input[2U];\n  uint64_t t3 = input[3U];\n  uint64_t t4 = input[4U];\n  uint64_t o0 = t1 << (uint32_t)51U | t0;\n  uint64_t o1 = t2 << (uint32_t)38U | t1 >> (uint32_t)13U;\n  uint64_t o2 = t3 << (uint32_t)25U | t2 >> (uint32_t)26U;\n  uint64_t o3 = t4 << (uint32_t)12U | t3 >> (uint32_t)39U;\n  uint8_t *b0 = output;\n  uint8_t *b1 = output + (uint32_t)8U;\n  uint8_t *b2 = output + (uint32_t)16U;\n  uint8_t *b3 = output + (uint32_t)24U;\n  store64_le(b0, o0);\n  store64_le(b1, o1);\n  store64_le(b2, o2);\n  store64_le(b3, o3);\n}\n\nstatic void Hacl_EC_Format_fcontract(uint8_t *output, uint64_t *input)\n{\n  Hacl_EC_Format_fcontract_first_carry_full(input);\n  Hacl_EC_Format_fcontract_second_carry_full(input);\n  Hacl_EC_Format_fcontract_trim(input);\n  Hacl_EC_Format_fcontract_store(output, input);\n}\n\nstatic void Hacl_EC_Format_scalar_of_point(uint8_t *scalar, uint64_t *point)\n{\n  uint64_t *x = point;\n  uint64_t *z = point + (uint32_t)5U;\n  uint64_t buf[10U] = { 0U };\n  uint64_t *zmone = buf;\n  uint64_t *sc = buf + (uint32_t)5U;\n  Hacl_Bignum_crecip(zmone, z);\n  Hacl_Bignum_fmul(sc, x, zmone);\n  Hacl_EC_Format_fcontract(scalar, sc);\n}\n\nstatic void\nHacl_EC_AddAndDouble_fmonty(\n  uint64_t *pp,\n  uint64_t *ppq,\n  uint64_t *p,\n  uint64_t *pq,\n  uint64_t *qmqp\n)\n{\n  uint64_t *qx = qmqp;\n  uint64_t *x2 = pp;\n  uint64_t *z2 = pp + (uint32_t)5U;\n  uint64_t *x3 = ppq;\n  uint64_t *z3 = ppq + (uint32_t)5U;\n  uint64_t *x = p;\n  uint64_t *z = p + (uint32_t)5U;\n  uint64_t *xprime = pq;\n  uint64_t *zprime = pq + (uint32_t)5U;\n  uint64_t buf[40U] = { 0U };\n  uint64_t *origx = buf;\n  uint64_t *origxprime0 = buf + (uint32_t)5U;\n  uint64_t *xxprime0 = buf + (uint32_t)25U;\n  uint64_t *zzprime0 = buf + (uint32_t)30U;\n  uint64_t *origxprime;\n  uint64_t *xx0;\n  uint64_t *zz0;\n  uint64_t *xxprime;\n  uint64_t *zzprime;\n  uint64_t *zzzprime;\n  uint64_t *zzz;\n  uint64_t *xx;\n  uint64_t *zz;\n  uint64_t scalar;\n  memcpy(origx, x, (uint32_t)5U * sizeof x[0U]);\n  Hacl_Bignum_fsum(x, z);\n  Hacl_Bignum_fdifference(z, origx);\n  memcpy(origxprime0, xprime, (uint32_t)5U * sizeof xprime[0U]);\n  Hacl_Bignum_fsum(xprime, zprime);\n  Hacl_Bignum_fdifference(zprime, origxprime0);\n  Hacl_Bignum_fmul(xxprime0, xprime, z);\n  Hacl_Bignum_fmul(zzprime0, x, zprime);\n  origxprime = buf + (uint32_t)5U;\n  xx0 = buf + (uint32_t)15U;\n  zz0 = buf + (uint32_t)20U;\n  xxprime = buf + (uint32_t)25U;\n  zzprime = buf + (uint32_t)30U;\n  zzzprime = buf + (uint32_t)35U;\n  memcpy(origxprime, xxprime, (uint32_t)5U * sizeof xxprime[0U]);\n  Hacl_Bignum_fsum(xxprime, zzprime);\n  Hacl_Bignum_fdifference(zzprime, origxprime);\n  Hacl_Bignum_Fsquare_fsquare_times(x3, xxprime, (uint32_t)1U);\n  Hacl_Bignum_Fsquare_fsquare_times(zzzprime, zzprime, (uint32_t)1U);\n  Hacl_Bignum_fmul(z3, zzzprime, qx);\n  Hacl_Bignum_Fsquare_fsquare_times(xx0, x, (uint32_t)1U);\n  Hacl_Bignum_Fsquare_fsquare_times(zz0, z, (uint32_t)1U);\n  zzz = buf + (uint32_t)10U;\n  xx = buf + (uint32_t)15U;\n  zz = buf + (uint32_t)20U;\n  Hacl_Bignum_fmul(x2, xx, zz);\n  Hacl_Bignum_fdifference(zz, xx);\n  scalar = (uint64_t)121665U;\n  Hacl_Bignum_fscalar(zzz, zz, scalar);\n  Hacl_Bignum_fsum(zzz, xx);\n  Hacl_Bignum_fmul(z2, zzz, zz);\n}\n\nstatic void\nHacl_EC_Ladder_SmallLoop_cmult_small_loop_step(\n  uint64_t *nq,\n  uint64_t *nqpq,\n  uint64_t *nq2,\n  uint64_t *nqpq2,\n  uint64_t *q,\n  uint8_t byt\n)\n{\n  uint64_t bit0 = (uint64_t)(byt >> (uint32_t)7U);\n  uint64_t bit;\n  Hacl_EC_Point_swap_conditional(nq, nqpq, bit0);\n  Hacl_EC_AddAndDouble_fmonty(nq2, nqpq2, nq, nqpq, q);\n  bit = (uint64_t)(byt >> (uint32_t)7U);\n  Hacl_EC_Point_swap_conditional(nq2, nqpq2, bit);\n}\n\nstatic void\nHacl_EC_Ladder_SmallLoop_cmult_small_loop_double_step(\n  uint64_t *nq,\n  uint64_t *nqpq,\n  uint64_t *nq2,\n  uint64_t *nqpq2,\n  uint64_t *q,\n  uint8_t byt\n)\n{\n  uint8_t byt1;\n  Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step(nq, nqpq, nq2, nqpq2, q, byt);\n  byt1 = byt << (uint32_t)1U;\n  Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step(nq2, nqpq2, nq, nqpq, q, byt1);\n}\n\nstatic void\nHacl_EC_Ladder_SmallLoop_cmult_small_loop(\n  uint64_t *nq,\n  uint64_t *nqpq,\n  uint64_t *nq2,\n  uint64_t *nqpq2,\n  uint64_t *q,\n  uint8_t byt,\n  uint32_t i\n)\n{\n  if (!(i == (uint32_t)0U))\n  {\n    uint32_t i_ = i - (uint32_t)1U;\n    uint8_t byt_;\n    Hacl_EC_Ladder_SmallLoop_cmult_small_loop_double_step(nq, nqpq, nq2, nqpq2, q, byt);\n    byt_ = byt << (uint32_t)2U;\n    Hacl_EC_Ladder_SmallLoop_cmult_small_loop(nq, nqpq, nq2, nqpq2, q, byt_, i_);\n  }\n}\n\nstatic void\nHacl_EC_Ladder_BigLoop_cmult_big_loop(\n  uint8_t *n1,\n  uint64_t *nq,\n  uint64_t *nqpq,\n  uint64_t *nq2,\n  uint64_t *nqpq2,\n  uint64_t *q,\n  uint32_t i\n)\n{\n  if (!(i == (uint32_t)0U))\n  {\n    uint32_t i1 = i - (uint32_t)1U;\n    uint8_t byte = n1[i1];\n    Hacl_EC_Ladder_SmallLoop_cmult_small_loop(nq, nqpq, nq2, nqpq2, q, byte, (uint32_t)4U);\n    Hacl_EC_Ladder_BigLoop_cmult_big_loop(n1, nq, nqpq, nq2, nqpq2, q, i1);\n  }\n}\n\nstatic void Hacl_EC_Ladder_cmult(uint64_t *result, uint8_t *n1, uint64_t *q)\n{\n  uint64_t point_buf[40U] = { 0U };\n  uint64_t *nq = point_buf;\n  uint64_t *nqpq = point_buf + (uint32_t)10U;\n  uint64_t *nq2 = point_buf + (uint32_t)20U;\n  uint64_t *nqpq2 = point_buf + (uint32_t)30U;\n  Hacl_EC_Point_copy(nqpq, q);\n  nq[0U] = (uint64_t)1U;\n  Hacl_EC_Ladder_BigLoop_cmult_big_loop(n1, nq, nqpq, nq2, nqpq2, q, (uint32_t)32U);\n  Hacl_EC_Point_copy(result, nq);\n}\n\nvoid Hacl_Curve25519_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint)\n{\n  uint64_t buf0[10U] = { 0U };\n  uint64_t *x0 = buf0;\n  uint64_t *z = buf0 + (uint32_t)5U;\n  uint64_t *q;\n  Hacl_EC_Format_fexpand(x0, basepoint);\n  z[0U] = (uint64_t)1U;\n  q = buf0;\n  {\n    uint8_t e[32U] = { 0U };\n    uint8_t e0;\n    uint8_t e31;\n    uint8_t e01;\n    uint8_t e311;\n    uint8_t e312;\n    uint8_t *scalar;\n    memcpy(e, secret, (uint32_t)32U * sizeof secret[0U]);\n    e0 = e[0U];\n    e31 = e[31U];\n    e01 = e0 & (uint8_t)248U;\n    e311 = e31 & (uint8_t)127U;\n    e312 = e311 | (uint8_t)64U;\n    e[0U] = e01;\n    e[31U] = e312;\n    scalar = e;\n    {\n      uint64_t buf[15U] = { 0U };\n      uint64_t *nq = buf;\n      uint64_t *x = nq;\n      x[0U] = (uint64_t)1U;\n      Hacl_EC_Ladder_cmult(nq, scalar, q);\n      Hacl_EC_Format_scalar_of_point(mypublic, nq);\n    }\n  }\n}\n\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/library/Hacl_Curve25519_joined.c",
    "content": "/*\n *  Interface to code from Project Everest\n *\n *  Copyright 2016-2018 INRIA and Microsoft Corporation\n *  SPDX-License-Identifier: Apache-2.0\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n *  not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *  http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *  This file is part of Mbed TLS (https://tls.mbed.org)\n */\n#ifndef _BSD_SOURCE\n/* Required to get htole64() from gcc/glibc's endian.h (older systems)\n * when we compile with -std=c99 */\n#define _BSD_SOURCE\n#endif\n#ifndef _DEFAULT_SOURCE\n/* (modern version of _BSD_SOURCE) */\n#define _DEFAULT_SOURCE\n#endif\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)\n\n#if defined(__SIZEOF_INT128__) && (__SIZEOF_INT128__ == 16)\n#define MBEDTLS_HAVE_INT128\n#endif\n\n#if defined(MBEDTLS_HAVE_INT128)\n#include \"Hacl_Curve25519.c\"\n#else\n#define KRML_VERIFIED_UINT128\n#include \"kremlib/FStar_UInt128_extracted.c\"\n#include \"legacy/Hacl_Curve25519.c\"\n#endif\n\n#include \"kremlib/FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8.c\"\n\n#endif /* defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) */\n\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/library/everest.c",
    "content": "/*\n *  Interface to code from Project Everest\n *\n *  Copyright 2016-2018 INRIA and Microsoft Corporation\n *  SPDX-License-Identifier: Apache-2.0\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n *  not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *  http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *  This file is part of Mbed TLS (https://tls.mbed.org).\n */\n\n#include \"common.h\"\n\n#include <string.h>\n\n#include \"mbedtls/ecdh.h\"\n\n#include \"everest/x25519.h\"\n#include \"everest/everest.h\"\n\n#include \"mbedtls/platform.h\"\n\n#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)\n\nint mbedtls_everest_setup( mbedtls_ecdh_context_everest *ctx, int grp_id )\n{\n    if( grp_id != MBEDTLS_ECP_DP_CURVE25519 )\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    mbedtls_x25519_init( &ctx->ctx );\n    return 0;\n}\n\nvoid mbedtls_everest_free( mbedtls_ecdh_context_everest *ctx )\n{\n    mbedtls_x25519_free( &ctx->ctx );\n}\n\nint mbedtls_everest_make_params( mbedtls_ecdh_context_everest *ctx, size_t *olen,\n                                 unsigned char *buf, size_t blen,\n                                 int( *f_rng )( void *, unsigned char *, size_t ),\n                                 void *p_rng )\n{\n    mbedtls_x25519_context *x25519_ctx = &ctx->ctx;\n    return mbedtls_x25519_make_params( x25519_ctx, olen, buf, blen, f_rng, p_rng );\n}\n\nint mbedtls_everest_read_params( mbedtls_ecdh_context_everest *ctx,\n                                 const unsigned char **buf,\n                                 const unsigned char *end )\n{\n    mbedtls_x25519_context *x25519_ctx = &ctx->ctx;\n    return mbedtls_x25519_read_params( x25519_ctx, buf, end );\n}\n\nint mbedtls_everest_get_params( mbedtls_ecdh_context_everest *ctx,\n                                const mbedtls_ecp_keypair *key,\n                                mbedtls_everest_ecdh_side side )\n{\n    mbedtls_x25519_context *x25519_ctx = &ctx->ctx;\n    mbedtls_x25519_ecdh_side s = side == MBEDTLS_EVEREST_ECDH_OURS ?\n                                            MBEDTLS_X25519_ECDH_OURS :\n                                            MBEDTLS_X25519_ECDH_THEIRS;\n    return mbedtls_x25519_get_params( x25519_ctx, key, s );\n}\n\nint mbedtls_everest_make_public( mbedtls_ecdh_context_everest *ctx, size_t *olen,\n                                 unsigned char *buf, size_t blen,\n                                 int( *f_rng )( void *, unsigned char *, size_t ),\n                                 void *p_rng )\n{\n    mbedtls_x25519_context *x25519_ctx = &ctx->ctx;\n    return mbedtls_x25519_make_public( x25519_ctx, olen, buf, blen, f_rng, p_rng );\n}\n\nint mbedtls_everest_read_public( mbedtls_ecdh_context_everest *ctx,\n                                 const unsigned char *buf, size_t blen )\n{\n    mbedtls_x25519_context *x25519_ctx = &ctx->ctx;\n    return mbedtls_x25519_read_public ( x25519_ctx, buf, blen );\n}\n\nint mbedtls_everest_calc_secret( mbedtls_ecdh_context_everest *ctx, size_t *olen,\n                                 unsigned char *buf, size_t blen,\n                                 int( *f_rng )( void *, unsigned char *, size_t ),\n                                 void *p_rng )\n{\n    mbedtls_x25519_context *x25519_ctx = &ctx->ctx;\n    return mbedtls_x25519_calc_secret( x25519_ctx, olen, buf, blen, f_rng, p_rng );\n}\n\n#endif /* MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED */\n\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/library/kremlib/FStar_UInt128_extracted.c",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>\n * KreMLin invocation: ../krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrB9w -minimal -fparentheses -fcurly-braces -fno-shadow -header copyright-header.txt -minimal -tmpdir extracted -warn-error +9+11 -skip-compilation -extract-uints -add-include <inttypes.h> -add-include \"kremlib.h\" -add-include \"kremlin/internal/compat.h\" extracted/prims.krml extracted/FStar_Pervasives_Native.krml extracted/FStar_Pervasives.krml extracted/FStar_Mul.krml extracted/FStar_Squash.krml extracted/FStar_Classical.krml extracted/FStar_StrongExcludedMiddle.krml extracted/FStar_FunctionalExtensionality.krml extracted/FStar_List_Tot_Base.krml extracted/FStar_List_Tot_Properties.krml extracted/FStar_List_Tot.krml extracted/FStar_Seq_Base.krml extracted/FStar_Seq_Properties.krml extracted/FStar_Seq.krml extracted/FStar_Math_Lib.krml extracted/FStar_Math_Lemmas.krml extracted/FStar_BitVector.krml extracted/FStar_UInt.krml extracted/FStar_UInt32.krml extracted/FStar_Int.krml extracted/FStar_Int16.krml extracted/FStar_Preorder.krml extracted/FStar_Ghost.krml extracted/FStar_ErasedLogic.krml extracted/FStar_UInt64.krml extracted/FStar_Set.krml extracted/FStar_PropositionalExtensionality.krml extracted/FStar_PredicateExtensionality.krml extracted/FStar_TSet.krml extracted/FStar_Monotonic_Heap.krml extracted/FStar_Heap.krml extracted/FStar_Map.krml extracted/FStar_Monotonic_HyperHeap.krml extracted/FStar_Monotonic_HyperStack.krml extracted/FStar_HyperStack.krml extracted/FStar_Monotonic_Witnessed.krml extracted/FStar_HyperStack_ST.krml extracted/FStar_HyperStack_All.krml extracted/FStar_Date.krml extracted/FStar_Universe.krml extracted/FStar_GSet.krml extracted/FStar_ModifiesGen.krml extracted/LowStar_Monotonic_Buffer.krml extracted/LowStar_Buffer.krml extracted/Spec_Loops.krml extracted/LowStar_BufferOps.krml extracted/C_Loops.krml extracted/FStar_UInt8.krml extracted/FStar_Kremlin_Endianness.krml extracted/FStar_UInt63.krml extracted/FStar_Exn.krml extracted/FStar_ST.krml extracted/FStar_All.krml extracted/FStar_Dyn.krml extracted/FStar_Int63.krml extracted/FStar_Int64.krml extracted/FStar_Int32.krml extracted/FStar_Int8.krml extracted/FStar_UInt16.krml extracted/FStar_Int_Cast.krml extracted/FStar_UInt128.krml extracted/C_Endianness.krml extracted/FStar_List.krml extracted/FStar_Float.krml extracted/FStar_IO.krml extracted/C.krml extracted/FStar_Char.krml extracted/FStar_String.krml extracted/LowStar_Modifies.krml extracted/C_String.krml extracted/FStar_Bytes.krml extracted/FStar_HyperStack_IO.krml extracted/C_Failure.krml extracted/TestLib.krml extracted/FStar_Int_Cast_Full.krml\n * F* version: 059db0c8\n * KreMLin version: 916c37ac\n */\n\n\n#include \"FStar_UInt128.h\"\n#include \"kremlin/c_endianness.h\"\n#include \"FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8.h\"\n\nuint64_t FStar_UInt128___proj__Mkuint128__item__low(FStar_UInt128_uint128 projectee)\n{\n  return projectee.low;\n}\n\nuint64_t FStar_UInt128___proj__Mkuint128__item__high(FStar_UInt128_uint128 projectee)\n{\n  return projectee.high;\n}\n\nstatic uint64_t FStar_UInt128_constant_time_carry(uint64_t a, uint64_t b)\n{\n  return (a ^ ((a ^ b) | ((a - b) ^ b))) >> (uint32_t)63U;\n}\n\nstatic uint64_t FStar_UInt128_carry(uint64_t a, uint64_t b)\n{\n  return FStar_UInt128_constant_time_carry(a, b);\n}\n\nFStar_UInt128_uint128 FStar_UInt128_add(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  FStar_UInt128_uint128\n  flat = { a.low + b.low, a.high + b.high + FStar_UInt128_carry(a.low + b.low, b.low) };\n  return flat;\n}\n\nFStar_UInt128_uint128\nFStar_UInt128_add_underspec(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  FStar_UInt128_uint128\n  flat = { a.low + b.low, a.high + b.high + FStar_UInt128_carry(a.low + b.low, b.low) };\n  return flat;\n}\n\nFStar_UInt128_uint128 FStar_UInt128_add_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  FStar_UInt128_uint128\n  flat = { a.low + b.low, a.high + b.high + FStar_UInt128_carry(a.low + b.low, b.low) };\n  return flat;\n}\n\nFStar_UInt128_uint128 FStar_UInt128_sub(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  FStar_UInt128_uint128\n  flat = { a.low - b.low, a.high - b.high - FStar_UInt128_carry(a.low, a.low - b.low) };\n  return flat;\n}\n\nFStar_UInt128_uint128\nFStar_UInt128_sub_underspec(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  FStar_UInt128_uint128\n  flat = { a.low - b.low, a.high - b.high - FStar_UInt128_carry(a.low, a.low - b.low) };\n  return flat;\n}\n\nstatic FStar_UInt128_uint128\nFStar_UInt128_sub_mod_impl(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  FStar_UInt128_uint128\n  flat = { a.low - b.low, a.high - b.high - FStar_UInt128_carry(a.low, a.low - b.low) };\n  return flat;\n}\n\nFStar_UInt128_uint128 FStar_UInt128_sub_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  return FStar_UInt128_sub_mod_impl(a, b);\n}\n\nFStar_UInt128_uint128 FStar_UInt128_logand(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  FStar_UInt128_uint128 flat = { a.low & b.low, a.high & b.high };\n  return flat;\n}\n\nFStar_UInt128_uint128 FStar_UInt128_logxor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  FStar_UInt128_uint128 flat = { a.low ^ b.low, a.high ^ b.high };\n  return flat;\n}\n\nFStar_UInt128_uint128 FStar_UInt128_logor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  FStar_UInt128_uint128 flat = { a.low | b.low, a.high | b.high };\n  return flat;\n}\n\nFStar_UInt128_uint128 FStar_UInt128_lognot(FStar_UInt128_uint128 a)\n{\n  FStar_UInt128_uint128 flat = { ~a.low, ~a.high };\n  return flat;\n}\n\nstatic uint32_t FStar_UInt128_u32_64 = (uint32_t)64U;\n\nstatic uint64_t FStar_UInt128_add_u64_shift_left(uint64_t hi, uint64_t lo, uint32_t s)\n{\n  return (hi << s) + (lo >> (FStar_UInt128_u32_64 - s));\n}\n\nstatic uint64_t FStar_UInt128_add_u64_shift_left_respec(uint64_t hi, uint64_t lo, uint32_t s)\n{\n  return FStar_UInt128_add_u64_shift_left(hi, lo, s);\n}\n\nstatic FStar_UInt128_uint128\nFStar_UInt128_shift_left_small(FStar_UInt128_uint128 a, uint32_t s)\n{\n  if (s == (uint32_t)0U)\n  {\n    return a;\n  }\n  else\n  {\n    FStar_UInt128_uint128\n    flat = { a.low << s, FStar_UInt128_add_u64_shift_left_respec(a.high, a.low, s) };\n    return flat;\n  }\n}\n\nstatic FStar_UInt128_uint128\nFStar_UInt128_shift_left_large(FStar_UInt128_uint128 a, uint32_t s)\n{\n  FStar_UInt128_uint128 flat = { (uint64_t)0U, a.low << (s - FStar_UInt128_u32_64) };\n  return flat;\n}\n\nFStar_UInt128_uint128 FStar_UInt128_shift_left(FStar_UInt128_uint128 a, uint32_t s)\n{\n  if (s < FStar_UInt128_u32_64)\n  {\n    return FStar_UInt128_shift_left_small(a, s);\n  }\n  else\n  {\n    return FStar_UInt128_shift_left_large(a, s);\n  }\n}\n\nstatic uint64_t FStar_UInt128_add_u64_shift_right(uint64_t hi, uint64_t lo, uint32_t s)\n{\n  return (lo >> s) + (hi << (FStar_UInt128_u32_64 - s));\n}\n\nstatic uint64_t FStar_UInt128_add_u64_shift_right_respec(uint64_t hi, uint64_t lo, uint32_t s)\n{\n  return FStar_UInt128_add_u64_shift_right(hi, lo, s);\n}\n\nstatic FStar_UInt128_uint128\nFStar_UInt128_shift_right_small(FStar_UInt128_uint128 a, uint32_t s)\n{\n  if (s == (uint32_t)0U)\n  {\n    return a;\n  }\n  else\n  {\n    FStar_UInt128_uint128\n    flat = { FStar_UInt128_add_u64_shift_right_respec(a.high, a.low, s), a.high >> s };\n    return flat;\n  }\n}\n\nstatic FStar_UInt128_uint128\nFStar_UInt128_shift_right_large(FStar_UInt128_uint128 a, uint32_t s)\n{\n  FStar_UInt128_uint128 flat = { a.high >> (s - FStar_UInt128_u32_64), (uint64_t)0U };\n  return flat;\n}\n\nFStar_UInt128_uint128 FStar_UInt128_shift_right(FStar_UInt128_uint128 a, uint32_t s)\n{\n  if (s < FStar_UInt128_u32_64)\n  {\n    return FStar_UInt128_shift_right_small(a, s);\n  }\n  else\n  {\n    return FStar_UInt128_shift_right_large(a, s);\n  }\n}\n\nbool FStar_UInt128_eq(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  return a.low == b.low && a.high == b.high;\n}\n\nbool FStar_UInt128_gt(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  return a.high > b.high || (a.high == b.high && a.low > b.low);\n}\n\nbool FStar_UInt128_lt(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  return a.high < b.high || (a.high == b.high && a.low < b.low);\n}\n\nbool FStar_UInt128_gte(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  return a.high > b.high || (a.high == b.high && a.low >= b.low);\n}\n\nbool FStar_UInt128_lte(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  return a.high < b.high || (a.high == b.high && a.low <= b.low);\n}\n\nFStar_UInt128_uint128 FStar_UInt128_eq_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  FStar_UInt128_uint128\n  flat =\n    {\n      FStar_UInt64_eq_mask(a.low,\n        b.low)\n      & FStar_UInt64_eq_mask(a.high, b.high),\n      FStar_UInt64_eq_mask(a.low,\n        b.low)\n      & FStar_UInt64_eq_mask(a.high, b.high)\n    };\n  return flat;\n}\n\nFStar_UInt128_uint128 FStar_UInt128_gte_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)\n{\n  FStar_UInt128_uint128\n  flat =\n    {\n      (FStar_UInt64_gte_mask(a.high, b.high) & ~FStar_UInt64_eq_mask(a.high, b.high))\n      | (FStar_UInt64_eq_mask(a.high, b.high) & FStar_UInt64_gte_mask(a.low, b.low)),\n      (FStar_UInt64_gte_mask(a.high, b.high) & ~FStar_UInt64_eq_mask(a.high, b.high))\n      | (FStar_UInt64_eq_mask(a.high, b.high) & FStar_UInt64_gte_mask(a.low, b.low))\n    };\n  return flat;\n}\n\nFStar_UInt128_uint128 FStar_UInt128_uint64_to_uint128(uint64_t a)\n{\n  FStar_UInt128_uint128 flat = { a, (uint64_t)0U };\n  return flat;\n}\n\nuint64_t FStar_UInt128_uint128_to_uint64(FStar_UInt128_uint128 a)\n{\n  return a.low;\n}\n\nFStar_UInt128_uint128\n(*FStar_UInt128_op_Plus_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) =\n  FStar_UInt128_add;\n\nFStar_UInt128_uint128\n(*FStar_UInt128_op_Plus_Question_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) =\n  FStar_UInt128_add_underspec;\n\nFStar_UInt128_uint128\n(*FStar_UInt128_op_Plus_Percent_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) =\n  FStar_UInt128_add_mod;\n\nFStar_UInt128_uint128\n(*FStar_UInt128_op_Subtraction_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) =\n  FStar_UInt128_sub;\n\nFStar_UInt128_uint128\n(*FStar_UInt128_op_Subtraction_Question_Hat)(\n  FStar_UInt128_uint128 x0,\n  FStar_UInt128_uint128 x1\n) = FStar_UInt128_sub_underspec;\n\nFStar_UInt128_uint128\n(*FStar_UInt128_op_Subtraction_Percent_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) =\n  FStar_UInt128_sub_mod;\n\nFStar_UInt128_uint128\n(*FStar_UInt128_op_Amp_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) =\n  FStar_UInt128_logand;\n\nFStar_UInt128_uint128\n(*FStar_UInt128_op_Hat_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) =\n  FStar_UInt128_logxor;\n\nFStar_UInt128_uint128\n(*FStar_UInt128_op_Bar_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) =\n  FStar_UInt128_logor;\n\nFStar_UInt128_uint128\n(*FStar_UInt128_op_Less_Less_Hat)(FStar_UInt128_uint128 x0, uint32_t x1) =\n  FStar_UInt128_shift_left;\n\nFStar_UInt128_uint128\n(*FStar_UInt128_op_Greater_Greater_Hat)(FStar_UInt128_uint128 x0, uint32_t x1) =\n  FStar_UInt128_shift_right;\n\nbool\n(*FStar_UInt128_op_Equals_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) =\n  FStar_UInt128_eq;\n\nbool\n(*FStar_UInt128_op_Greater_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) =\n  FStar_UInt128_gt;\n\nbool\n(*FStar_UInt128_op_Less_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) =\n  FStar_UInt128_lt;\n\nbool\n(*FStar_UInt128_op_Greater_Equals_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) =\n  FStar_UInt128_gte;\n\nbool\n(*FStar_UInt128_op_Less_Equals_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) =\n  FStar_UInt128_lte;\n\nstatic uint64_t FStar_UInt128_u64_mod_32(uint64_t a)\n{\n  return a & (uint64_t)0xffffffffU;\n}\n\nstatic uint32_t FStar_UInt128_u32_32 = (uint32_t)32U;\n\nstatic uint64_t FStar_UInt128_u32_combine(uint64_t hi, uint64_t lo)\n{\n  return lo + (hi << FStar_UInt128_u32_32);\n}\n\nFStar_UInt128_uint128 FStar_UInt128_mul32(uint64_t x, uint32_t y)\n{\n  FStar_UInt128_uint128\n  flat =\n    {\n      FStar_UInt128_u32_combine((x >> FStar_UInt128_u32_32)\n        * (uint64_t)y\n        + (FStar_UInt128_u64_mod_32(x) * (uint64_t)y >> FStar_UInt128_u32_32),\n        FStar_UInt128_u64_mod_32(FStar_UInt128_u64_mod_32(x) * (uint64_t)y)),\n      ((x >> FStar_UInt128_u32_32)\n      * (uint64_t)y\n      + (FStar_UInt128_u64_mod_32(x) * (uint64_t)y >> FStar_UInt128_u32_32))\n      >> FStar_UInt128_u32_32\n    };\n  return flat;\n}\n\ntypedef struct K___uint64_t_uint64_t_uint64_t_uint64_t_s\n{\n  uint64_t fst;\n  uint64_t snd;\n  uint64_t thd;\n  uint64_t f3;\n}\nK___uint64_t_uint64_t_uint64_t_uint64_t;\n\nstatic K___uint64_t_uint64_t_uint64_t_uint64_t\nFStar_UInt128_mul_wide_impl_t_(uint64_t x, uint64_t y)\n{\n  K___uint64_t_uint64_t_uint64_t_uint64_t\n  flat =\n    {\n      FStar_UInt128_u64_mod_32(x),\n      FStar_UInt128_u64_mod_32(FStar_UInt128_u64_mod_32(x) * FStar_UInt128_u64_mod_32(y)),\n      x\n      >> FStar_UInt128_u32_32,\n      (x >> FStar_UInt128_u32_32)\n      * FStar_UInt128_u64_mod_32(y)\n      + (FStar_UInt128_u64_mod_32(x) * FStar_UInt128_u64_mod_32(y) >> FStar_UInt128_u32_32)\n    };\n  return flat;\n}\n\nstatic uint64_t FStar_UInt128_u32_combine_(uint64_t hi, uint64_t lo)\n{\n  return lo + (hi << FStar_UInt128_u32_32);\n}\n\nstatic FStar_UInt128_uint128 FStar_UInt128_mul_wide_impl(uint64_t x, uint64_t y)\n{\n  K___uint64_t_uint64_t_uint64_t_uint64_t scrut = FStar_UInt128_mul_wide_impl_t_(x, y);\n  uint64_t u1 = scrut.fst;\n  uint64_t w3 = scrut.snd;\n  uint64_t x_ = scrut.thd;\n  uint64_t t_ = scrut.f3;\n  FStar_UInt128_uint128\n  flat =\n    {\n      FStar_UInt128_u32_combine_(u1 * (y >> FStar_UInt128_u32_32) + FStar_UInt128_u64_mod_32(t_),\n        w3),\n      x_\n      * (y >> FStar_UInt128_u32_32)\n      + (t_ >> FStar_UInt128_u32_32)\n      + ((u1 * (y >> FStar_UInt128_u32_32) + FStar_UInt128_u64_mod_32(t_)) >> FStar_UInt128_u32_32)\n    };\n  return flat;\n}\n\nFStar_UInt128_uint128 FStar_UInt128_mul_wide(uint64_t x, uint64_t y)\n{\n  return FStar_UInt128_mul_wide_impl(x, y);\n}\n\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/library/kremlib/FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8.c",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>\n * KreMLin invocation: ../krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrB9w -minimal -fparentheses -fcurly-braces -fno-shadow -header copyright-header.txt -minimal -tmpdir dist/minimal -skip-compilation -extract-uints -add-include <inttypes.h> -add-include <stdbool.h> -add-include \"kremlin/internal/compat.h\" -add-include \"kremlin/internal/types.h\" -bundle FStar.UInt64+FStar.UInt32+FStar.UInt16+FStar.UInt8=* extracted/prims.krml extracted/FStar_Pervasives_Native.krml extracted/FStar_Pervasives.krml extracted/FStar_Mul.krml extracted/FStar_Squash.krml extracted/FStar_Classical.krml extracted/FStar_StrongExcludedMiddle.krml extracted/FStar_FunctionalExtensionality.krml extracted/FStar_List_Tot_Base.krml extracted/FStar_List_Tot_Properties.krml extracted/FStar_List_Tot.krml extracted/FStar_Seq_Base.krml extracted/FStar_Seq_Properties.krml extracted/FStar_Seq.krml extracted/FStar_Math_Lib.krml extracted/FStar_Math_Lemmas.krml extracted/FStar_BitVector.krml extracted/FStar_UInt.krml extracted/FStar_UInt32.krml extracted/FStar_Int.krml extracted/FStar_Int16.krml extracted/FStar_Preorder.krml extracted/FStar_Ghost.krml extracted/FStar_ErasedLogic.krml extracted/FStar_UInt64.krml extracted/FStar_Set.krml extracted/FStar_PropositionalExtensionality.krml extracted/FStar_PredicateExtensionality.krml extracted/FStar_TSet.krml extracted/FStar_Monotonic_Heap.krml extracted/FStar_Heap.krml extracted/FStar_Map.krml extracted/FStar_Monotonic_HyperHeap.krml extracted/FStar_Monotonic_HyperStack.krml extracted/FStar_HyperStack.krml extracted/FStar_Monotonic_Witnessed.krml extracted/FStar_HyperStack_ST.krml extracted/FStar_HyperStack_All.krml extracted/FStar_Date.krml extracted/FStar_Universe.krml extracted/FStar_GSet.krml extracted/FStar_ModifiesGen.krml extracted/LowStar_Monotonic_Buffer.krml extracted/LowStar_Buffer.krml extracted/Spec_Loops.krml extracted/LowStar_BufferOps.krml extracted/C_Loops.krml extracted/FStar_UInt8.krml extracted/FStar_Kremlin_Endianness.krml extracted/FStar_UInt63.krml extracted/FStar_Exn.krml extracted/FStar_ST.krml extracted/FStar_All.krml extracted/FStar_Dyn.krml extracted/FStar_Int63.krml extracted/FStar_Int64.krml extracted/FStar_Int32.krml extracted/FStar_Int8.krml extracted/FStar_UInt16.krml extracted/FStar_Int_Cast.krml extracted/FStar_UInt128.krml extracted/C_Endianness.krml extracted/FStar_List.krml extracted/FStar_Float.krml extracted/FStar_IO.krml extracted/C.krml extracted/FStar_Char.krml extracted/FStar_String.krml extracted/LowStar_Modifies.krml extracted/C_String.krml extracted/FStar_Bytes.krml extracted/FStar_HyperStack_IO.krml extracted/C_Failure.krml extracted/TestLib.krml extracted/FStar_Int_Cast_Full.krml\n * F* version: 059db0c8\n * KreMLin version: 916c37ac\n */\n\n\n#include \"FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8.h\"\n\nuint64_t FStar_UInt64_eq_mask(uint64_t a, uint64_t b)\n{\n  uint64_t x = a ^ b;\n  uint64_t minus_x = ~x + (uint64_t)1U;\n  uint64_t x_or_minus_x = x | minus_x;\n  uint64_t xnx = x_or_minus_x >> (uint32_t)63U;\n  return xnx - (uint64_t)1U;\n}\n\nuint64_t FStar_UInt64_gte_mask(uint64_t a, uint64_t b)\n{\n  uint64_t x = a;\n  uint64_t y = b;\n  uint64_t x_xor_y = x ^ y;\n  uint64_t x_sub_y = x - y;\n  uint64_t x_sub_y_xor_y = x_sub_y ^ y;\n  uint64_t q = x_xor_y | x_sub_y_xor_y;\n  uint64_t x_xor_q = x ^ q;\n  uint64_t x_xor_q_ = x_xor_q >> (uint32_t)63U;\n  return x_xor_q_ - (uint64_t)1U;\n}\n\nuint32_t FStar_UInt32_eq_mask(uint32_t a, uint32_t b)\n{\n  uint32_t x = a ^ b;\n  uint32_t minus_x = ~x + (uint32_t)1U;\n  uint32_t x_or_minus_x = x | minus_x;\n  uint32_t xnx = x_or_minus_x >> (uint32_t)31U;\n  return xnx - (uint32_t)1U;\n}\n\nuint32_t FStar_UInt32_gte_mask(uint32_t a, uint32_t b)\n{\n  uint32_t x = a;\n  uint32_t y = b;\n  uint32_t x_xor_y = x ^ y;\n  uint32_t x_sub_y = x - y;\n  uint32_t x_sub_y_xor_y = x_sub_y ^ y;\n  uint32_t q = x_xor_y | x_sub_y_xor_y;\n  uint32_t x_xor_q = x ^ q;\n  uint32_t x_xor_q_ = x_xor_q >> (uint32_t)31U;\n  return x_xor_q_ - (uint32_t)1U;\n}\n\nuint16_t FStar_UInt16_eq_mask(uint16_t a, uint16_t b)\n{\n  uint16_t x = a ^ b;\n  uint16_t minus_x = ~x + (uint16_t)1U;\n  uint16_t x_or_minus_x = x | minus_x;\n  uint16_t xnx = x_or_minus_x >> (uint32_t)15U;\n  return xnx - (uint16_t)1U;\n}\n\nuint16_t FStar_UInt16_gte_mask(uint16_t a, uint16_t b)\n{\n  uint16_t x = a;\n  uint16_t y = b;\n  uint16_t x_xor_y = x ^ y;\n  uint16_t x_sub_y = x - y;\n  uint16_t x_sub_y_xor_y = x_sub_y ^ y;\n  uint16_t q = x_xor_y | x_sub_y_xor_y;\n  uint16_t x_xor_q = x ^ q;\n  uint16_t x_xor_q_ = x_xor_q >> (uint32_t)15U;\n  return x_xor_q_ - (uint16_t)1U;\n}\n\nuint8_t FStar_UInt8_eq_mask(uint8_t a, uint8_t b)\n{\n  uint8_t x = a ^ b;\n  uint8_t minus_x = ~x + (uint8_t)1U;\n  uint8_t x_or_minus_x = x | minus_x;\n  uint8_t xnx = x_or_minus_x >> (uint32_t)7U;\n  return xnx - (uint8_t)1U;\n}\n\nuint8_t FStar_UInt8_gte_mask(uint8_t a, uint8_t b)\n{\n  uint8_t x = a;\n  uint8_t y = b;\n  uint8_t x_xor_y = x ^ y;\n  uint8_t x_sub_y = x - y;\n  uint8_t x_sub_y_xor_y = x_sub_y ^ y;\n  uint8_t q = x_xor_y | x_sub_y_xor_y;\n  uint8_t x_xor_q = x ^ q;\n  uint8_t x_xor_q_ = x_xor_q >> (uint32_t)7U;\n  return x_xor_q_ - (uint8_t)1U;\n}\n\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/library/legacy/Hacl_Curve25519.c",
    "content": "/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.\n   Licensed under the Apache 2.0 License. */\n\n/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>\n * KreMLin invocation: /mnt/e/everest/verify/kremlin/krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -I /mnt/e/everest/verify/hacl-star/code/lib/kremlin -I /mnt/e/everest/verify/kremlin/kremlib/compat -I /mnt/e/everest/verify/hacl-star/specs -I /mnt/e/everest/verify/hacl-star/specs/old -I . -ccopt -march=native -verbose -ldopt -flto -tmpdir x25519-c -I ../bignum -bundle Hacl.Curve25519=* -minimal -add-include \"kremlib.h\" -skip-compilation x25519-c/out.krml -o x25519-c/Hacl_Curve25519.c\n * F* version: 059db0c8\n * KreMLin version: 916c37ac\n */\n\n\n#include \"Hacl_Curve25519.h\"\n\nextern uint64_t FStar_UInt64_eq_mask(uint64_t x0, uint64_t x1);\n\nextern uint64_t FStar_UInt64_gte_mask(uint64_t x0, uint64_t x1);\n\nextern FStar_UInt128_uint128\nFStar_UInt128_add(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nextern FStar_UInt128_uint128\nFStar_UInt128_add_mod(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nextern FStar_UInt128_uint128\nFStar_UInt128_logand(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1);\n\nextern FStar_UInt128_uint128 FStar_UInt128_shift_right(FStar_UInt128_uint128 x0, uint32_t x1);\n\nextern FStar_UInt128_uint128 FStar_UInt128_uint64_to_uint128(uint64_t x0);\n\nextern uint64_t FStar_UInt128_uint128_to_uint64(FStar_UInt128_uint128 x0);\n\nextern FStar_UInt128_uint128 FStar_UInt128_mul_wide(uint64_t x0, uint64_t x1);\n\nstatic void Hacl_Bignum_Modulo_carry_top(uint64_t *b)\n{\n  uint64_t b4 = b[4U];\n  uint64_t b0 = b[0U];\n  uint64_t b4_ = b4 & (uint64_t)0x7ffffffffffffU;\n  uint64_t b0_ = b0 + (uint64_t)19U * (b4 >> (uint32_t)51U);\n  b[4U] = b4_;\n  b[0U] = b0_;\n}\n\ninline static void\nHacl_Bignum_Fproduct_copy_from_wide_(uint64_t *output, FStar_UInt128_uint128 *input)\n{\n  uint32_t i;\n  for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U)\n  {\n    FStar_UInt128_uint128 xi = input[i];\n    output[i] = FStar_UInt128_uint128_to_uint64(xi);\n  }\n}\n\ninline static void\nHacl_Bignum_Fproduct_sum_scalar_multiplication_(\n  FStar_UInt128_uint128 *output,\n  uint64_t *input,\n  uint64_t s\n)\n{\n  uint32_t i;\n  for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U)\n  {\n    FStar_UInt128_uint128 xi = output[i];\n    uint64_t yi = input[i];\n    output[i] = FStar_UInt128_add_mod(xi, FStar_UInt128_mul_wide(yi, s));\n  }\n}\n\ninline static void Hacl_Bignum_Fproduct_carry_wide_(FStar_UInt128_uint128 *tmp)\n{\n  uint32_t i;\n  for (i = (uint32_t)0U; i < (uint32_t)4U; i = i + (uint32_t)1U)\n  {\n    uint32_t ctr = i;\n    FStar_UInt128_uint128 tctr = tmp[ctr];\n    FStar_UInt128_uint128 tctrp1 = tmp[ctr + (uint32_t)1U];\n    uint64_t r0 = FStar_UInt128_uint128_to_uint64(tctr) & (uint64_t)0x7ffffffffffffU;\n    FStar_UInt128_uint128 c = FStar_UInt128_shift_right(tctr, (uint32_t)51U);\n    tmp[ctr] = FStar_UInt128_uint64_to_uint128(r0);\n    tmp[ctr + (uint32_t)1U] = FStar_UInt128_add(tctrp1, c);\n  }\n}\n\ninline static void Hacl_Bignum_Fmul_shift_reduce(uint64_t *output)\n{\n  uint64_t tmp = output[4U];\n  uint64_t b0;\n  {\n    uint32_t i;\n    for (i = (uint32_t)0U; i < (uint32_t)4U; i = i + (uint32_t)1U)\n    {\n      uint32_t ctr = (uint32_t)5U - i - (uint32_t)1U;\n      uint64_t z = output[ctr - (uint32_t)1U];\n      output[ctr] = z;\n    }\n  }\n  output[0U] = tmp;\n  b0 = output[0U];\n  output[0U] = (uint64_t)19U * b0;\n}\n\nstatic void\nHacl_Bignum_Fmul_mul_shift_reduce_(\n  FStar_UInt128_uint128 *output,\n  uint64_t *input,\n  uint64_t *input2\n)\n{\n  uint32_t i;\n  uint64_t input2i;\n  {\n    uint32_t i0;\n    for (i0 = (uint32_t)0U; i0 < (uint32_t)4U; i0 = i0 + (uint32_t)1U)\n    {\n      uint64_t input2i0 = input2[i0];\n      Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i0);\n      Hacl_Bignum_Fmul_shift_reduce(input);\n    }\n  }\n  i = (uint32_t)4U;\n  input2i = input2[i];\n  Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i);\n}\n\ninline static void Hacl_Bignum_Fmul_fmul(uint64_t *output, uint64_t *input, uint64_t *input2)\n{\n  uint64_t tmp[5U] = { 0U };\n  memcpy(tmp, input, (uint32_t)5U * sizeof input[0U]);\n  KRML_CHECK_SIZE(sizeof (FStar_UInt128_uint128), (uint32_t)5U);\n  {\n    FStar_UInt128_uint128 t[5U];\n    {\n      uint32_t _i;\n      for (_i = 0U; _i < (uint32_t)5U; ++_i)\n        t[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U);\n    }\n    {\n      FStar_UInt128_uint128 b4;\n      FStar_UInt128_uint128 b0;\n      FStar_UInt128_uint128 b4_;\n      FStar_UInt128_uint128 b0_;\n      uint64_t i0;\n      uint64_t i1;\n      uint64_t i0_;\n      uint64_t i1_;\n      Hacl_Bignum_Fmul_mul_shift_reduce_(t, tmp, input2);\n      Hacl_Bignum_Fproduct_carry_wide_(t);\n      b4 = t[4U];\n      b0 = t[0U];\n      b4_ = FStar_UInt128_logand(b4, FStar_UInt128_uint64_to_uint128((uint64_t)0x7ffffffffffffU));\n      b0_ =\n        FStar_UInt128_add(b0,\n          FStar_UInt128_mul_wide((uint64_t)19U,\n            FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(b4, (uint32_t)51U))));\n      t[4U] = b4_;\n      t[0U] = b0_;\n      Hacl_Bignum_Fproduct_copy_from_wide_(output, t);\n      i0 = output[0U];\n      i1 = output[1U];\n      i0_ = i0 & (uint64_t)0x7ffffffffffffU;\n      i1_ = i1 + (i0 >> (uint32_t)51U);\n      output[0U] = i0_;\n      output[1U] = i1_;\n    }\n  }\n}\n\ninline static void Hacl_Bignum_Fsquare_fsquare__(FStar_UInt128_uint128 *tmp, uint64_t *output)\n{\n  uint64_t r0 = output[0U];\n  uint64_t r1 = output[1U];\n  uint64_t r2 = output[2U];\n  uint64_t r3 = output[3U];\n  uint64_t r4 = output[4U];\n  uint64_t d0 = r0 * (uint64_t)2U;\n  uint64_t d1 = r1 * (uint64_t)2U;\n  uint64_t d2 = r2 * (uint64_t)2U * (uint64_t)19U;\n  uint64_t d419 = r4 * (uint64_t)19U;\n  uint64_t d4 = d419 * (uint64_t)2U;\n  FStar_UInt128_uint128\n  s0 =\n    FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(r0, r0),\n        FStar_UInt128_mul_wide(d4, r1)),\n      FStar_UInt128_mul_wide(d2, r3));\n  FStar_UInt128_uint128\n  s1 =\n    FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r1),\n        FStar_UInt128_mul_wide(d4, r2)),\n      FStar_UInt128_mul_wide(r3 * (uint64_t)19U, r3));\n  FStar_UInt128_uint128\n  s2 =\n    FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r2),\n        FStar_UInt128_mul_wide(r1, r1)),\n      FStar_UInt128_mul_wide(d4, r3));\n  FStar_UInt128_uint128\n  s3 =\n    FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r3),\n        FStar_UInt128_mul_wide(d1, r2)),\n      FStar_UInt128_mul_wide(r4, d419));\n  FStar_UInt128_uint128\n  s4 =\n    FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r4),\n        FStar_UInt128_mul_wide(d1, r3)),\n      FStar_UInt128_mul_wide(r2, r2));\n  tmp[0U] = s0;\n  tmp[1U] = s1;\n  tmp[2U] = s2;\n  tmp[3U] = s3;\n  tmp[4U] = s4;\n}\n\ninline static void Hacl_Bignum_Fsquare_fsquare_(FStar_UInt128_uint128 *tmp, uint64_t *output)\n{\n  FStar_UInt128_uint128 b4;\n  FStar_UInt128_uint128 b0;\n  FStar_UInt128_uint128 b4_;\n  FStar_UInt128_uint128 b0_;\n  uint64_t i0;\n  uint64_t i1;\n  uint64_t i0_;\n  uint64_t i1_;\n  Hacl_Bignum_Fsquare_fsquare__(tmp, output);\n  Hacl_Bignum_Fproduct_carry_wide_(tmp);\n  b4 = tmp[4U];\n  b0 = tmp[0U];\n  b4_ = FStar_UInt128_logand(b4, FStar_UInt128_uint64_to_uint128((uint64_t)0x7ffffffffffffU));\n  b0_ =\n    FStar_UInt128_add(b0,\n      FStar_UInt128_mul_wide((uint64_t)19U,\n        FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(b4, (uint32_t)51U))));\n  tmp[4U] = b4_;\n  tmp[0U] = b0_;\n  Hacl_Bignum_Fproduct_copy_from_wide_(output, tmp);\n  i0 = output[0U];\n  i1 = output[1U];\n  i0_ = i0 & (uint64_t)0x7ffffffffffffU;\n  i1_ = i1 + (i0 >> (uint32_t)51U);\n  output[0U] = i0_;\n  output[1U] = i1_;\n}\n\nstatic void\nHacl_Bignum_Fsquare_fsquare_times_(\n  uint64_t *input,\n  FStar_UInt128_uint128 *tmp,\n  uint32_t count1\n)\n{\n  uint32_t i;\n  Hacl_Bignum_Fsquare_fsquare_(tmp, input);\n  for (i = (uint32_t)1U; i < count1; i = i + (uint32_t)1U)\n    Hacl_Bignum_Fsquare_fsquare_(tmp, input);\n}\n\ninline static void\nHacl_Bignum_Fsquare_fsquare_times(uint64_t *output, uint64_t *input, uint32_t count1)\n{\n  KRML_CHECK_SIZE(sizeof (FStar_UInt128_uint128), (uint32_t)5U);\n  {\n    FStar_UInt128_uint128 t[5U];\n    {\n      uint32_t _i;\n      for (_i = 0U; _i < (uint32_t)5U; ++_i)\n        t[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U);\n    }\n    memcpy(output, input, (uint32_t)5U * sizeof input[0U]);\n    Hacl_Bignum_Fsquare_fsquare_times_(output, t, count1);\n  }\n}\n\ninline static void Hacl_Bignum_Fsquare_fsquare_times_inplace(uint64_t *output, uint32_t count1)\n{\n  KRML_CHECK_SIZE(sizeof (FStar_UInt128_uint128), (uint32_t)5U);\n  {\n    FStar_UInt128_uint128 t[5U];\n    {\n      uint32_t _i;\n      for (_i = 0U; _i < (uint32_t)5U; ++_i)\n        t[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U);\n    }\n    Hacl_Bignum_Fsquare_fsquare_times_(output, t, count1);\n  }\n}\n\ninline static void Hacl_Bignum_Crecip_crecip(uint64_t *out, uint64_t *z)\n{\n  uint64_t buf[20U] = { 0U };\n  uint64_t *a0 = buf;\n  uint64_t *t00 = buf + (uint32_t)5U;\n  uint64_t *b0 = buf + (uint32_t)10U;\n  uint64_t *t01;\n  uint64_t *b1;\n  uint64_t *c0;\n  uint64_t *a;\n  uint64_t *t0;\n  uint64_t *b;\n  uint64_t *c;\n  Hacl_Bignum_Fsquare_fsquare_times(a0, z, (uint32_t)1U);\n  Hacl_Bignum_Fsquare_fsquare_times(t00, a0, (uint32_t)2U);\n  Hacl_Bignum_Fmul_fmul(b0, t00, z);\n  Hacl_Bignum_Fmul_fmul(a0, b0, a0);\n  Hacl_Bignum_Fsquare_fsquare_times(t00, a0, (uint32_t)1U);\n  Hacl_Bignum_Fmul_fmul(b0, t00, b0);\n  Hacl_Bignum_Fsquare_fsquare_times(t00, b0, (uint32_t)5U);\n  t01 = buf + (uint32_t)5U;\n  b1 = buf + (uint32_t)10U;\n  c0 = buf + (uint32_t)15U;\n  Hacl_Bignum_Fmul_fmul(b1, t01, b1);\n  Hacl_Bignum_Fsquare_fsquare_times(t01, b1, (uint32_t)10U);\n  Hacl_Bignum_Fmul_fmul(c0, t01, b1);\n  Hacl_Bignum_Fsquare_fsquare_times(t01, c0, (uint32_t)20U);\n  Hacl_Bignum_Fmul_fmul(t01, t01, c0);\n  Hacl_Bignum_Fsquare_fsquare_times_inplace(t01, (uint32_t)10U);\n  Hacl_Bignum_Fmul_fmul(b1, t01, b1);\n  Hacl_Bignum_Fsquare_fsquare_times(t01, b1, (uint32_t)50U);\n  a = buf;\n  t0 = buf + (uint32_t)5U;\n  b = buf + (uint32_t)10U;\n  c = buf + (uint32_t)15U;\n  Hacl_Bignum_Fmul_fmul(c, t0, b);\n  Hacl_Bignum_Fsquare_fsquare_times(t0, c, (uint32_t)100U);\n  Hacl_Bignum_Fmul_fmul(t0, t0, c);\n  Hacl_Bignum_Fsquare_fsquare_times_inplace(t0, (uint32_t)50U);\n  Hacl_Bignum_Fmul_fmul(t0, t0, b);\n  Hacl_Bignum_Fsquare_fsquare_times_inplace(t0, (uint32_t)5U);\n  Hacl_Bignum_Fmul_fmul(out, t0, a);\n}\n\ninline static void Hacl_Bignum_fsum(uint64_t *a, uint64_t *b)\n{\n  uint32_t i;\n  for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U)\n  {\n    uint64_t xi = a[i];\n    uint64_t yi = b[i];\n    a[i] = xi + yi;\n  }\n}\n\ninline static void Hacl_Bignum_fdifference(uint64_t *a, uint64_t *b)\n{\n  uint64_t tmp[5U] = { 0U };\n  uint64_t b0;\n  uint64_t b1;\n  uint64_t b2;\n  uint64_t b3;\n  uint64_t b4;\n  memcpy(tmp, b, (uint32_t)5U * sizeof b[0U]);\n  b0 = tmp[0U];\n  b1 = tmp[1U];\n  b2 = tmp[2U];\n  b3 = tmp[3U];\n  b4 = tmp[4U];\n  tmp[0U] = b0 + (uint64_t)0x3fffffffffff68U;\n  tmp[1U] = b1 + (uint64_t)0x3ffffffffffff8U;\n  tmp[2U] = b2 + (uint64_t)0x3ffffffffffff8U;\n  tmp[3U] = b3 + (uint64_t)0x3ffffffffffff8U;\n  tmp[4U] = b4 + (uint64_t)0x3ffffffffffff8U;\n  {\n    uint32_t i;\n    for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U)\n    {\n      uint64_t xi = a[i];\n      uint64_t yi = tmp[i];\n      a[i] = yi - xi;\n    }\n  }\n}\n\ninline static void Hacl_Bignum_fscalar(uint64_t *output, uint64_t *b, uint64_t s)\n{\n  KRML_CHECK_SIZE(sizeof (FStar_UInt128_uint128), (uint32_t)5U);\n  {\n    FStar_UInt128_uint128 tmp[5U];\n    {\n      uint32_t _i;\n      for (_i = 0U; _i < (uint32_t)5U; ++_i)\n        tmp[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U);\n    }\n    {\n      FStar_UInt128_uint128 b4;\n      FStar_UInt128_uint128 b0;\n      FStar_UInt128_uint128 b4_;\n      FStar_UInt128_uint128 b0_;\n      {\n        uint32_t i;\n        for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U)\n        {\n          uint64_t xi = b[i];\n          tmp[i] = FStar_UInt128_mul_wide(xi, s);\n        }\n      }\n      Hacl_Bignum_Fproduct_carry_wide_(tmp);\n      b4 = tmp[4U];\n      b0 = tmp[0U];\n      b4_ = FStar_UInt128_logand(b4, FStar_UInt128_uint64_to_uint128((uint64_t)0x7ffffffffffffU));\n      b0_ =\n        FStar_UInt128_add(b0,\n          FStar_UInt128_mul_wide((uint64_t)19U,\n            FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(b4, (uint32_t)51U))));\n      tmp[4U] = b4_;\n      tmp[0U] = b0_;\n      Hacl_Bignum_Fproduct_copy_from_wide_(output, tmp);\n    }\n  }\n}\n\ninline static void Hacl_Bignum_fmul(uint64_t *output, uint64_t *a, uint64_t *b)\n{\n  Hacl_Bignum_Fmul_fmul(output, a, b);\n}\n\ninline static void Hacl_Bignum_crecip(uint64_t *output, uint64_t *input)\n{\n  Hacl_Bignum_Crecip_crecip(output, input);\n}\n\nstatic void\nHacl_EC_Point_swap_conditional_step(uint64_t *a, uint64_t *b, uint64_t swap1, uint32_t ctr)\n{\n  uint32_t i = ctr - (uint32_t)1U;\n  uint64_t ai = a[i];\n  uint64_t bi = b[i];\n  uint64_t x = swap1 & (ai ^ bi);\n  uint64_t ai1 = ai ^ x;\n  uint64_t bi1 = bi ^ x;\n  a[i] = ai1;\n  b[i] = bi1;\n}\n\nstatic void\nHacl_EC_Point_swap_conditional_(uint64_t *a, uint64_t *b, uint64_t swap1, uint32_t ctr)\n{\n  if (!(ctr == (uint32_t)0U))\n  {\n    uint32_t i;\n    Hacl_EC_Point_swap_conditional_step(a, b, swap1, ctr);\n    i = ctr - (uint32_t)1U;\n    Hacl_EC_Point_swap_conditional_(a, b, swap1, i);\n  }\n}\n\nstatic void Hacl_EC_Point_swap_conditional(uint64_t *a, uint64_t *b, uint64_t iswap)\n{\n  uint64_t swap1 = (uint64_t)0U - iswap;\n  Hacl_EC_Point_swap_conditional_(a, b, swap1, (uint32_t)5U);\n  Hacl_EC_Point_swap_conditional_(a + (uint32_t)5U, b + (uint32_t)5U, swap1, (uint32_t)5U);\n}\n\nstatic void Hacl_EC_Point_copy(uint64_t *output, uint64_t *input)\n{\n  memcpy(output, input, (uint32_t)5U * sizeof input[0U]);\n  memcpy(output + (uint32_t)5U,\n    input + (uint32_t)5U,\n    (uint32_t)5U * sizeof (input + (uint32_t)5U)[0U]);\n}\n\nstatic void Hacl_EC_Format_fexpand(uint64_t *output, uint8_t *input)\n{\n  uint64_t i0 = load64_le(input);\n  uint8_t *x00 = input + (uint32_t)6U;\n  uint64_t i1 = load64_le(x00);\n  uint8_t *x01 = input + (uint32_t)12U;\n  uint64_t i2 = load64_le(x01);\n  uint8_t *x02 = input + (uint32_t)19U;\n  uint64_t i3 = load64_le(x02);\n  uint8_t *x0 = input + (uint32_t)24U;\n  uint64_t i4 = load64_le(x0);\n  uint64_t output0 = i0 & (uint64_t)0x7ffffffffffffU;\n  uint64_t output1 = i1 >> (uint32_t)3U & (uint64_t)0x7ffffffffffffU;\n  uint64_t output2 = i2 >> (uint32_t)6U & (uint64_t)0x7ffffffffffffU;\n  uint64_t output3 = i3 >> (uint32_t)1U & (uint64_t)0x7ffffffffffffU;\n  uint64_t output4 = i4 >> (uint32_t)12U & (uint64_t)0x7ffffffffffffU;\n  output[0U] = output0;\n  output[1U] = output1;\n  output[2U] = output2;\n  output[3U] = output3;\n  output[4U] = output4;\n}\n\nstatic void Hacl_EC_Format_fcontract_first_carry_pass(uint64_t *input)\n{\n  uint64_t t0 = input[0U];\n  uint64_t t1 = input[1U];\n  uint64_t t2 = input[2U];\n  uint64_t t3 = input[3U];\n  uint64_t t4 = input[4U];\n  uint64_t t1_ = t1 + (t0 >> (uint32_t)51U);\n  uint64_t t0_ = t0 & (uint64_t)0x7ffffffffffffU;\n  uint64_t t2_ = t2 + (t1_ >> (uint32_t)51U);\n  uint64_t t1__ = t1_ & (uint64_t)0x7ffffffffffffU;\n  uint64_t t3_ = t3 + (t2_ >> (uint32_t)51U);\n  uint64_t t2__ = t2_ & (uint64_t)0x7ffffffffffffU;\n  uint64_t t4_ = t4 + (t3_ >> (uint32_t)51U);\n  uint64_t t3__ = t3_ & (uint64_t)0x7ffffffffffffU;\n  input[0U] = t0_;\n  input[1U] = t1__;\n  input[2U] = t2__;\n  input[3U] = t3__;\n  input[4U] = t4_;\n}\n\nstatic void Hacl_EC_Format_fcontract_first_carry_full(uint64_t *input)\n{\n  Hacl_EC_Format_fcontract_first_carry_pass(input);\n  Hacl_Bignum_Modulo_carry_top(input);\n}\n\nstatic void Hacl_EC_Format_fcontract_second_carry_pass(uint64_t *input)\n{\n  uint64_t t0 = input[0U];\n  uint64_t t1 = input[1U];\n  uint64_t t2 = input[2U];\n  uint64_t t3 = input[3U];\n  uint64_t t4 = input[4U];\n  uint64_t t1_ = t1 + (t0 >> (uint32_t)51U);\n  uint64_t t0_ = t0 & (uint64_t)0x7ffffffffffffU;\n  uint64_t t2_ = t2 + (t1_ >> (uint32_t)51U);\n  uint64_t t1__ = t1_ & (uint64_t)0x7ffffffffffffU;\n  uint64_t t3_ = t3 + (t2_ >> (uint32_t)51U);\n  uint64_t t2__ = t2_ & (uint64_t)0x7ffffffffffffU;\n  uint64_t t4_ = t4 + (t3_ >> (uint32_t)51U);\n  uint64_t t3__ = t3_ & (uint64_t)0x7ffffffffffffU;\n  input[0U] = t0_;\n  input[1U] = t1__;\n  input[2U] = t2__;\n  input[3U] = t3__;\n  input[4U] = t4_;\n}\n\nstatic void Hacl_EC_Format_fcontract_second_carry_full(uint64_t *input)\n{\n  uint64_t i0;\n  uint64_t i1;\n  uint64_t i0_;\n  uint64_t i1_;\n  Hacl_EC_Format_fcontract_second_carry_pass(input);\n  Hacl_Bignum_Modulo_carry_top(input);\n  i0 = input[0U];\n  i1 = input[1U];\n  i0_ = i0 & (uint64_t)0x7ffffffffffffU;\n  i1_ = i1 + (i0 >> (uint32_t)51U);\n  input[0U] = i0_;\n  input[1U] = i1_;\n}\n\nstatic void Hacl_EC_Format_fcontract_trim(uint64_t *input)\n{\n  uint64_t a0 = input[0U];\n  uint64_t a1 = input[1U];\n  uint64_t a2 = input[2U];\n  uint64_t a3 = input[3U];\n  uint64_t a4 = input[4U];\n  uint64_t mask0 = FStar_UInt64_gte_mask(a0, (uint64_t)0x7ffffffffffedU);\n  uint64_t mask1 = FStar_UInt64_eq_mask(a1, (uint64_t)0x7ffffffffffffU);\n  uint64_t mask2 = FStar_UInt64_eq_mask(a2, (uint64_t)0x7ffffffffffffU);\n  uint64_t mask3 = FStar_UInt64_eq_mask(a3, (uint64_t)0x7ffffffffffffU);\n  uint64_t mask4 = FStar_UInt64_eq_mask(a4, (uint64_t)0x7ffffffffffffU);\n  uint64_t mask = (((mask0 & mask1) & mask2) & mask3) & mask4;\n  uint64_t a0_ = a0 - ((uint64_t)0x7ffffffffffedU & mask);\n  uint64_t a1_ = a1 - ((uint64_t)0x7ffffffffffffU & mask);\n  uint64_t a2_ = a2 - ((uint64_t)0x7ffffffffffffU & mask);\n  uint64_t a3_ = a3 - ((uint64_t)0x7ffffffffffffU & mask);\n  uint64_t a4_ = a4 - ((uint64_t)0x7ffffffffffffU & mask);\n  input[0U] = a0_;\n  input[1U] = a1_;\n  input[2U] = a2_;\n  input[3U] = a3_;\n  input[4U] = a4_;\n}\n\nstatic void Hacl_EC_Format_fcontract_store(uint8_t *output, uint64_t *input)\n{\n  uint64_t t0 = input[0U];\n  uint64_t t1 = input[1U];\n  uint64_t t2 = input[2U];\n  uint64_t t3 = input[3U];\n  uint64_t t4 = input[4U];\n  uint64_t o0 = t1 << (uint32_t)51U | t0;\n  uint64_t o1 = t2 << (uint32_t)38U | t1 >> (uint32_t)13U;\n  uint64_t o2 = t3 << (uint32_t)25U | t2 >> (uint32_t)26U;\n  uint64_t o3 = t4 << (uint32_t)12U | t3 >> (uint32_t)39U;\n  uint8_t *b0 = output;\n  uint8_t *b1 = output + (uint32_t)8U;\n  uint8_t *b2 = output + (uint32_t)16U;\n  uint8_t *b3 = output + (uint32_t)24U;\n  store64_le(b0, o0);\n  store64_le(b1, o1);\n  store64_le(b2, o2);\n  store64_le(b3, o3);\n}\n\nstatic void Hacl_EC_Format_fcontract(uint8_t *output, uint64_t *input)\n{\n  Hacl_EC_Format_fcontract_first_carry_full(input);\n  Hacl_EC_Format_fcontract_second_carry_full(input);\n  Hacl_EC_Format_fcontract_trim(input);\n  Hacl_EC_Format_fcontract_store(output, input);\n}\n\nstatic void Hacl_EC_Format_scalar_of_point(uint8_t *scalar, uint64_t *point)\n{\n  uint64_t *x = point;\n  uint64_t *z = point + (uint32_t)5U;\n  uint64_t buf[10U] = { 0U };\n  uint64_t *zmone = buf;\n  uint64_t *sc = buf + (uint32_t)5U;\n  Hacl_Bignum_crecip(zmone, z);\n  Hacl_Bignum_fmul(sc, x, zmone);\n  Hacl_EC_Format_fcontract(scalar, sc);\n}\n\nstatic void\nHacl_EC_AddAndDouble_fmonty(\n  uint64_t *pp,\n  uint64_t *ppq,\n  uint64_t *p,\n  uint64_t *pq,\n  uint64_t *qmqp\n)\n{\n  uint64_t *qx = qmqp;\n  uint64_t *x2 = pp;\n  uint64_t *z2 = pp + (uint32_t)5U;\n  uint64_t *x3 = ppq;\n  uint64_t *z3 = ppq + (uint32_t)5U;\n  uint64_t *x = p;\n  uint64_t *z = p + (uint32_t)5U;\n  uint64_t *xprime = pq;\n  uint64_t *zprime = pq + (uint32_t)5U;\n  uint64_t buf[40U] = { 0U };\n  uint64_t *origx = buf;\n  uint64_t *origxprime0 = buf + (uint32_t)5U;\n  uint64_t *xxprime0 = buf + (uint32_t)25U;\n  uint64_t *zzprime0 = buf + (uint32_t)30U;\n  uint64_t *origxprime;\n  uint64_t *xx0;\n  uint64_t *zz0;\n  uint64_t *xxprime;\n  uint64_t *zzprime;\n  uint64_t *zzzprime;\n  uint64_t *zzz;\n  uint64_t *xx;\n  uint64_t *zz;\n  uint64_t scalar;\n  memcpy(origx, x, (uint32_t)5U * sizeof x[0U]);\n  Hacl_Bignum_fsum(x, z);\n  Hacl_Bignum_fdifference(z, origx);\n  memcpy(origxprime0, xprime, (uint32_t)5U * sizeof xprime[0U]);\n  Hacl_Bignum_fsum(xprime, zprime);\n  Hacl_Bignum_fdifference(zprime, origxprime0);\n  Hacl_Bignum_fmul(xxprime0, xprime, z);\n  Hacl_Bignum_fmul(zzprime0, x, zprime);\n  origxprime = buf + (uint32_t)5U;\n  xx0 = buf + (uint32_t)15U;\n  zz0 = buf + (uint32_t)20U;\n  xxprime = buf + (uint32_t)25U;\n  zzprime = buf + (uint32_t)30U;\n  zzzprime = buf + (uint32_t)35U;\n  memcpy(origxprime, xxprime, (uint32_t)5U * sizeof xxprime[0U]);\n  Hacl_Bignum_fsum(xxprime, zzprime);\n  Hacl_Bignum_fdifference(zzprime, origxprime);\n  Hacl_Bignum_Fsquare_fsquare_times(x3, xxprime, (uint32_t)1U);\n  Hacl_Bignum_Fsquare_fsquare_times(zzzprime, zzprime, (uint32_t)1U);\n  Hacl_Bignum_fmul(z3, zzzprime, qx);\n  Hacl_Bignum_Fsquare_fsquare_times(xx0, x, (uint32_t)1U);\n  Hacl_Bignum_Fsquare_fsquare_times(zz0, z, (uint32_t)1U);\n  zzz = buf + (uint32_t)10U;\n  xx = buf + (uint32_t)15U;\n  zz = buf + (uint32_t)20U;\n  Hacl_Bignum_fmul(x2, xx, zz);\n  Hacl_Bignum_fdifference(zz, xx);\n  scalar = (uint64_t)121665U;\n  Hacl_Bignum_fscalar(zzz, zz, scalar);\n  Hacl_Bignum_fsum(zzz, xx);\n  Hacl_Bignum_fmul(z2, zzz, zz);\n}\n\nstatic void\nHacl_EC_Ladder_SmallLoop_cmult_small_loop_step(\n  uint64_t *nq,\n  uint64_t *nqpq,\n  uint64_t *nq2,\n  uint64_t *nqpq2,\n  uint64_t *q,\n  uint8_t byt\n)\n{\n  uint64_t bit0 = (uint64_t)(byt >> (uint32_t)7U);\n  uint64_t bit;\n  Hacl_EC_Point_swap_conditional(nq, nqpq, bit0);\n  Hacl_EC_AddAndDouble_fmonty(nq2, nqpq2, nq, nqpq, q);\n  bit = (uint64_t)(byt >> (uint32_t)7U);\n  Hacl_EC_Point_swap_conditional(nq2, nqpq2, bit);\n}\n\nstatic void\nHacl_EC_Ladder_SmallLoop_cmult_small_loop_double_step(\n  uint64_t *nq,\n  uint64_t *nqpq,\n  uint64_t *nq2,\n  uint64_t *nqpq2,\n  uint64_t *q,\n  uint8_t byt\n)\n{\n  uint8_t byt1;\n  Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step(nq, nqpq, nq2, nqpq2, q, byt);\n  byt1 = byt << (uint32_t)1U;\n  Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step(nq2, nqpq2, nq, nqpq, q, byt1);\n}\n\nstatic void\nHacl_EC_Ladder_SmallLoop_cmult_small_loop(\n  uint64_t *nq,\n  uint64_t *nqpq,\n  uint64_t *nq2,\n  uint64_t *nqpq2,\n  uint64_t *q,\n  uint8_t byt,\n  uint32_t i\n)\n{\n  if (!(i == (uint32_t)0U))\n  {\n    uint32_t i_ = i - (uint32_t)1U;\n    uint8_t byt_;\n    Hacl_EC_Ladder_SmallLoop_cmult_small_loop_double_step(nq, nqpq, nq2, nqpq2, q, byt);\n    byt_ = byt << (uint32_t)2U;\n    Hacl_EC_Ladder_SmallLoop_cmult_small_loop(nq, nqpq, nq2, nqpq2, q, byt_, i_);\n  }\n}\n\nstatic void\nHacl_EC_Ladder_BigLoop_cmult_big_loop(\n  uint8_t *n1,\n  uint64_t *nq,\n  uint64_t *nqpq,\n  uint64_t *nq2,\n  uint64_t *nqpq2,\n  uint64_t *q,\n  uint32_t i\n)\n{\n  if (!(i == (uint32_t)0U))\n  {\n    uint32_t i1 = i - (uint32_t)1U;\n    uint8_t byte = n1[i1];\n    Hacl_EC_Ladder_SmallLoop_cmult_small_loop(nq, nqpq, nq2, nqpq2, q, byte, (uint32_t)4U);\n    Hacl_EC_Ladder_BigLoop_cmult_big_loop(n1, nq, nqpq, nq2, nqpq2, q, i1);\n  }\n}\n\nstatic void Hacl_EC_Ladder_cmult(uint64_t *result, uint8_t *n1, uint64_t *q)\n{\n  uint64_t point_buf[40U] = { 0U };\n  uint64_t *nq = point_buf;\n  uint64_t *nqpq = point_buf + (uint32_t)10U;\n  uint64_t *nq2 = point_buf + (uint32_t)20U;\n  uint64_t *nqpq2 = point_buf + (uint32_t)30U;\n  Hacl_EC_Point_copy(nqpq, q);\n  nq[0U] = (uint64_t)1U;\n  Hacl_EC_Ladder_BigLoop_cmult_big_loop(n1, nq, nqpq, nq2, nqpq2, q, (uint32_t)32U);\n  Hacl_EC_Point_copy(result, nq);\n}\n\nvoid Hacl_Curve25519_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint)\n{\n  uint64_t buf0[10U] = { 0U };\n  uint64_t *x0 = buf0;\n  uint64_t *z = buf0 + (uint32_t)5U;\n  uint64_t *q;\n  Hacl_EC_Format_fexpand(x0, basepoint);\n  z[0U] = (uint64_t)1U;\n  q = buf0;\n  {\n    uint8_t e[32U] = { 0U };\n    uint8_t e0;\n    uint8_t e31;\n    uint8_t e01;\n    uint8_t e311;\n    uint8_t e312;\n    uint8_t *scalar;\n    memcpy(e, secret, (uint32_t)32U * sizeof secret[0U]);\n    e0 = e[0U];\n    e31 = e[31U];\n    e01 = e0 & (uint8_t)248U;\n    e311 = e31 & (uint8_t)127U;\n    e312 = e311 | (uint8_t)64U;\n    e[0U] = e01;\n    e[31U] = e312;\n    scalar = e;\n    {\n      uint64_t buf[15U] = { 0U };\n      uint64_t *nq = buf;\n      uint64_t *x = nq;\n      x[0U] = (uint64_t)1U;\n      Hacl_EC_Ladder_cmult(nq, scalar, q);\n      Hacl_EC_Format_scalar_of_point(mypublic, nq);\n    }\n  }\n}\n\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/everest/library/x25519.c",
    "content": "/*\n *  ECDH with curve-optimized implementation multiplexing\n *\n *  Copyright 2016-2018 INRIA and Microsoft Corporation\n *  SPDX-License-Identifier: Apache-2.0\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n *  not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *  http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *  This file is part of Mbed TLS (https://tls.mbed.org)\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_ECDH_C) && defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)\n\n#include <mbedtls/ecdh.h>\n\n#if !(defined(__SIZEOF_INT128__) && (__SIZEOF_INT128__ == 16))\n#define KRML_VERIFIED_UINT128\n#endif\n\n#include <Hacl_Curve25519.h>\n#include <mbedtls/platform_util.h>\n\n#include \"x25519.h\"\n\n#include <string.h>\n\n/*\n * Initialize context\n */\nvoid mbedtls_x25519_init( mbedtls_x25519_context *ctx )\n{\n    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x25519_context ) );\n}\n\n/*\n * Free context\n */\nvoid mbedtls_x25519_free( mbedtls_x25519_context *ctx )\n{\n    if( ctx == NULL )\n        return;\n\n    mbedtls_platform_zeroize( ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES );\n    mbedtls_platform_zeroize( ctx->peer_point, MBEDTLS_X25519_KEY_SIZE_BYTES );\n}\n\nint mbedtls_x25519_make_params( mbedtls_x25519_context *ctx, size_t *olen,\n                        unsigned char *buf, size_t blen,\n                        int( *f_rng )(void *, unsigned char *, size_t),\n                        void *p_rng )\n{\n    int ret = 0;\n\n    uint8_t base[MBEDTLS_X25519_KEY_SIZE_BYTES] = {0};\n\n    if( ( ret = f_rng( p_rng, ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES ) ) != 0 )\n        return ret;\n\n    *olen = MBEDTLS_X25519_KEY_SIZE_BYTES + 4;\n    if( blen < *olen )\n        return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );\n\n    *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;\n    *buf++ = MBEDTLS_ECP_TLS_CURVE25519 >> 8;\n    *buf++ = MBEDTLS_ECP_TLS_CURVE25519 & 0xFF;\n    *buf++ = MBEDTLS_X25519_KEY_SIZE_BYTES;\n\n    base[0] = 9;\n    Hacl_Curve25519_crypto_scalarmult( buf, ctx->our_secret, base );\n\n    base[0] = 0;\n    if( memcmp( buf, base, MBEDTLS_X25519_KEY_SIZE_BYTES) == 0 )\n        return MBEDTLS_ERR_ECP_RANDOM_FAILED;\n\n    return( 0 );\n}\n\nint mbedtls_x25519_read_params( mbedtls_x25519_context *ctx,\n                        const unsigned char **buf, const unsigned char *end )\n{\n    if( end - *buf < MBEDTLS_X25519_KEY_SIZE_BYTES + 1 )\n        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );\n\n    if( ( *(*buf)++ != MBEDTLS_X25519_KEY_SIZE_BYTES ) )\n        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );\n\n    memcpy( ctx->peer_point, *buf, MBEDTLS_X25519_KEY_SIZE_BYTES );\n    *buf += MBEDTLS_X25519_KEY_SIZE_BYTES;\n    return( 0 );\n}\n\nint mbedtls_x25519_get_params( mbedtls_x25519_context *ctx, const mbedtls_ecp_keypair *key,\n                               mbedtls_x25519_ecdh_side side )\n{\n    size_t olen = 0;\n\n    switch( side ) {\n    case MBEDTLS_X25519_ECDH_THEIRS:\n        return mbedtls_ecp_point_write_binary( &key->grp, &key->Q, MBEDTLS_ECP_PF_COMPRESSED, &olen, ctx->peer_point, MBEDTLS_X25519_KEY_SIZE_BYTES );\n    case MBEDTLS_X25519_ECDH_OURS:\n        return mbedtls_mpi_write_binary_le( &key->d, ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES );\n    default:\n        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );\n    }\n}\n\nint mbedtls_x25519_calc_secret( mbedtls_x25519_context *ctx, size_t *olen,\n                        unsigned char *buf, size_t blen,\n                        int( *f_rng )(void *, unsigned char *, size_t),\n                        void *p_rng )\n{\n    /* f_rng and p_rng are not used here because this implementation does not\n       need blinding since it has constant trace. */\n    (( void )f_rng);\n    (( void )p_rng);\n\n    *olen = MBEDTLS_X25519_KEY_SIZE_BYTES;\n\n    if( blen < *olen )\n        return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );\n\n    Hacl_Curve25519_crypto_scalarmult( buf, ctx->our_secret, ctx->peer_point);\n\n    /* Wipe the DH secret and don't let the peer chose a small subgroup point */\n    mbedtls_platform_zeroize( ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES );\n\n    if( memcmp( buf, ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES) == 0 )\n        return MBEDTLS_ERR_ECP_RANDOM_FAILED;\n\n    return( 0 );\n}\n\nint mbedtls_x25519_make_public( mbedtls_x25519_context *ctx, size_t *olen,\n                        unsigned char *buf, size_t blen,\n                        int( *f_rng )(void *, unsigned char *, size_t),\n                        void *p_rng )\n{\n    int ret = 0;\n    unsigned char base[MBEDTLS_X25519_KEY_SIZE_BYTES] = { 0 };\n\n    if( ctx == NULL )\n        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );\n\n    if( ( ret = f_rng( p_rng, ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES ) ) != 0 )\n        return ret;\n\n    *olen = MBEDTLS_X25519_KEY_SIZE_BYTES + 1;\n    if( blen < *olen )\n        return(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL);\n    *buf++ = MBEDTLS_X25519_KEY_SIZE_BYTES;\n\n    base[0] = 9;\n    Hacl_Curve25519_crypto_scalarmult( buf, ctx->our_secret, base );\n\n    base[0] = 0;\n    if( memcmp( buf, base, MBEDTLS_X25519_KEY_SIZE_BYTES ) == 0 )\n        return MBEDTLS_ERR_ECP_RANDOM_FAILED;\n\n    return( ret );\n}\n\nint mbedtls_x25519_read_public( mbedtls_x25519_context *ctx,\n                        const unsigned char *buf, size_t blen )\n{\n    if( blen < MBEDTLS_X25519_KEY_SIZE_BYTES + 1 )\n        return(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL);\n    if( (*buf++ != MBEDTLS_X25519_KEY_SIZE_BYTES) )\n        return(MBEDTLS_ERR_ECP_BAD_INPUT_DATA);\n    memcpy( ctx->peer_point, buf, MBEDTLS_X25519_KEY_SIZE_BYTES );\n    return( 0 );\n}\n\n\n#endif /* MBEDTLS_ECDH_C && MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED */\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/p256-m/README.md",
    "content": "The files within the `p256-m/` subdirectory originate from the [p256-m GitHub repository](https://github.com/mpg/p256-m). They are distributed here under a dual Apache-2.0 OR GPL-2.0-or-later license. They are authored by Manuel Pégourié-Gonnard. p256-m is a minimalistic implementation of ECDH and ECDSA on NIST P-256, especially suited to constrained 32-bit environments. Mbed TLS documentation for integrating drivers uses p256-m as an example of a software accelerator, and describes how it can be integrated alongside Mbed TLS. It should be noted that p256-m files in the Mbed TLS repo will not be updated regularly, so they may not have fixes and improvements present in the upstream project.\n\nThe files `p256-m.c`, `p256-m.h` and `README.md` have been taken from the `p256-m` repository.\nIt should be noted that p256-m deliberately does not supply its own cryptographically secure RNG function. As a result, the PSA RNG is used, with `p256_generate_random()` wrapping `psa_generate_random()`.\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/p256-m/p256-m/README.md",
    "content": "*This is the original README for the p256-m repository. Please note that as\nonly a subset of p256-m's files are present in Mbed TLS, this README may refer\nto files that are not present/relevant here.*\n\np256-m is a minimalistic implementation of ECDH and ECDSA on NIST P-256,\nespecially suited to constrained 32-bit environments. It's written in standard\nC, with optional bits of assembly for Arm Cortex-M and Cortex-A CPUs.\n\nIts design is guided by the following goals in this order:\n\n1. correctness & security;\n2. low code size & RAM usage;\n3. runtime performance.\n\nMost cryptographic implementations care more about speed than footprint, and\nsome might even risk weakening security for more speed. p256-m was written\nbecause I wanted to see what happened when reversing the usual emphasis.\n\nThe result is a full implementation of ECDH and ECDSA in **less than 3KiB of\ncode**, using **less than 768 bytes of RAM**, with comparable performance\nto existing implementations (see below) - in less than 700 LOC.\n\n_Contents of this Readme:_\n\n- [Correctness](#correctness)\n- [Security](#security)\n- [Code size](#code-size)\n- [RAM usage](#ram-usage)\n- [Runtime performance](#runtime-performance)\n- [Comparison with other implementations](#comparison-with-other-implementations)\n- [Design overview](#design-overview)\n- [Notes about other curves](#notes-about-other-curves)\n- [Notes about other platforms](#notes-about-other-platforms)\n\n## Correctness\n\n**API design:**\n\n- The API is minimal: only 4 public functions.\n- Each public function fully validates its inputs and returns specific errors.\n- The API uses arrays of octets for all input and output.\n\n**Testing:**\n\n- p256-m is validated against multiple test vectors from various RFCs and\n  NIST.\n- In addition, crafted inputs are used for negative testing and to reach\n  corner cases.\n- Two test suites are provided: one for closed-box testing (using only the\n  public API), one for open-box testing (for unit-testing internal functions,\nand reaching more error cases by exploiting knowledge of how the RNG is used).\n- The resulting branch coverage is maximal: closed-box testing reaches all\n  branches except four; three of them are reached by open-box testing using a\nrigged RNG; the last branch could only be reached by computing a discrete log\non P-256... See `coverage.sh`.\n- Testing also uses dynamic analysis: valgrind, ASan, MemSan, UBSan.\n\n**Code quality:**\n\n- The code is standard C99; it builds without warnings with `clang\n  -Weverything` and `gcc -Wall -Wextra -pedantic`.\n- The code is small and well documented, including internal APIs: with the\n  header file, it's less than 700 lines of code, and more lines of comments\nthan of code.\n- However it _has not been reviewed_ independently so far, as this is a\n  personal project.\n\n**Short Weierstrass pitfalls:**\n\nIts has been [pointed out](https://safecurves.cr.yp.to/) that the NIST curves,\nand indeed all Short Weierstrass curves, have a number of pitfalls including\nrisk for the implementation to:\n\n- \"produce incorrect results for some rare curve points\" - this is avoided by\n  carefully checking the validity domain of formulas used throughout the code;\n- \"leak secret data when the input isn't a curve point\" - this is avoided by\n  validating that points lie on the curve every time a point is deserialized.\n\n## Security\n\nIn addition to the above correctness claims, p256-m has the following\nproperties:\n\n- it has no branch depending (even indirectly) on secret data;\n- it has no memory access depending (even indirectly) on secret data.\n\nThese properties are checked using valgrind and MemSan with the ideas\nbehind [ctgrind](https://github.com/agl/ctgrind), see `consttime.sh`.\n\nIn addition to avoiding branches and memory accesses depending on secret data,\np256-m also avoid instructions (or library functions) whose execution time\ndepends on the value of operands on cores of interest. Namely, it never uses\ninteger division, and for multiplication by default it only uses 16x16->32 bit\nunsigned multiplication. On cores which have a constant-time 32x32->64 bit\nunsigned multiplication instruction, the symbol `MUL64_IS_CONSTANT_TIME` can\nbe defined by the user at compile-time to take advantage of it in order to\nimprove performance and code size. (On Cortex-M and Cortex-A cores wtih GCC or\nClang this is not necessary, since inline assembly is used instead.)\n\nAs a result, p256-m should be secure against the following classes of attackers:\n\n1. attackers who can only manipulate the input and observe the output;\n2. attackers who can also measure the total computation time of the operation;\n3. attackers who can also observe and manipulate micro-architectural features\n   such as the cache or branch predictor with arbitrary precision.\n\nHowever, p256-m makes no attempt to protect against:\n\n4. passive physical attackers who can record traces of physical emissions\n   (power, EM, sound) of the CPU while it manipulates secrets;\n5. active physical attackers who can also inject faults in the computation.\n\n(Note: p256-m should actually be secure against SPA, by virtue of being fully\nconstant-flow, but is not expected to resist any other physical attack.)\n\n**Warning:** p256-m requires an externally-provided RNG function. If that\nfunction is not cryptographically secure, then neither is p256-m's key\ngeneration or ECDSA signature generation.\n\n_Note:_ p256-m also follows best practices such as securely erasing secret\ndata on the stack before returning.\n\n## Code size\n\nCompiled with\n[ARM-GCC 9](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads),\nwith `-mthumb -Os`, here are samples of code sizes reached on selected cores:\n\n- Cortex-M0: 2988 bytes\n- Cortex-M4: 2900 bytes\n- Cortex-A7: 2924 bytes\n\nClang was also tried but tends to generate larger code (by about 10%). For\ndetails, see `sizes.sh`.\n\n**What's included:**\n\n- Full input validation and (de)serialisation of input/outputs to/from bytes.\n- Cleaning up secret values from the stack before returning from a function.\n- The code has no dependency on libc functions or the toolchain's runtime\n  library (such as helpers for long multiply); this can be checked for the\nArm-GCC toolchain with the `deps.sh` script.\n\n**What's excluded:**\n\n- A secure RNG function needs to be provided externally, see\n  `p256_generate_random()` in `p256-m.h`.\n\n## RAM usage\n\np256-m doesn't use any dynamic memory (on the heap), only the stack. Here's\nhow much stack is used by each of its 4 public functions on selected cores:\n\n| Function                  | Cortex-M0 | Cortex-M4 | Cortex-A7 |\n| ------------------------- | --------: | --------: | --------: |\n| `p256_gen_keypair`        |       608 |       564 |       564 |\n| `p256_ecdh_shared_secret` |       640 |       596 |       596 |\n| `p256_ecdsa_sign`         |       664 |       604 |       604 |\n| `p256_ecdsa_verify`       |       752 |       700 |       700 |\n\nFor details, see `stack.sh`, `wcs.py` and `libc.msu` (the above figures assume\nthat the externally-provided RNG function uses at most 384 bytes of stack).\n\n## Runtime performance\n\nHere are the timings of each public function in milliseconds measured on\nplatforms based on a selection of cores:\n\n- Cortex-M0 at  48 MHz: STM32F091 board running Mbed OS 6\n- Cortex-M4 at 100 MHz: STM32F411 board running Mbed OS 6\n- Cortex-A7 at 900 MHz: Raspberry Pi 2B running Raspbian Buster\n\n| Function                  | Cortex-M0 | Cortex-M4 | Cortex-A7 |\n| ------------------------- | --------: | --------: | --------: |\n| `p256_gen_keypair`        |       921 |       145 |        11 |\n| `p256_ecdh_shared_secret` |       922 |       144 |        11 |\n| `p256_ecdsa_sign`         |       990 |       155 |        12 |\n| `p256_ecdsa_verify`       |      1976 |       309 |        24 |\n| Sum of the above          |      4809 |       753 |        59 |\n\nThe sum of these operations corresponds to a TLS handshake using ECDHE-ECDSA\nwith mutual authentication based on raw public keys or directly-trusted\ncertificates (otherwise, add one 'verify' for each link in the peer's\ncertificate chain).\n\n_Note_: the above figures where obtained by compiling with GCC, which is able\nto use inline assembly. Without that inline assembly (22 lines for Cortex-M0,\n1 line for Cortex-M4), the code would be roughly 2 times slower on those\nplatforms. (The effect is much less important on the Cortex-A7 core.)\n\nFor details, see `bench.sh`, `benchmark.c` and `on-target-benchmark/`.\n\n## Comparison with other implementations\n\nThe most relevant/convenient implementation for comparisons is\n[TinyCrypt](https://github.com/intel/tinycrypt), as it's also a standalone\nimplementation of ECDH and ECDSA on P-256 only, that also targets constrained\ndevices. Other implementations tend to implement many curves and build on a\nshared bignum/MPI module (possibly also supporting RSA), which makes fair\ncomparisons less convenient.\n\nThe scripts used for TinyCrypt measurements are available in [this\nbranch](https://github.com/mpg/tinycrypt/tree/measurements), based on version\n0.2.8.\n\n**Code size**\n\n| Core      | p256-m | TinyCrypt |\n| --------- | -----: | --------: |\n| Cortex-M0 |   2988 |      6134 |\n| Cortex-M4 |   2900 |      5934 |\n| Cortex-A7 |   2924 |      5934 |\n\n**RAM usage**\n\nTinyCrypto also uses no heap, only the stack. Here's the RAM used by each\noperation on a Cortex-M0 core:\n\n| operation          | p256-m | TinyCrypt |\n| ------------------ | -----: | --------: |\n| key generation     |    608 |       824 |\n| ECDH shared secret |    640 |       728 |\n| ECDSA sign         |    664 |       880 |\n| ECDSA verify       |    752 |       824 |\n\nOn a Cortex-M4 or Cortex-A7 core (identical numbers):\n\n| operation          | p256-m | TinyCrypt |\n| ------------------ | -----: | --------: |\n| key generation     |    564 |       796 |\n| ECDH shared secret |    596 |       700 |\n| ECDSA sign         |    604 |       844 |\n| ECDSA verify       |    700 |       808 |\n\n**Runtime performance**\n\nHere are the timings of each operation in milliseconds measured on\nplatforms based on a selection of cores:\n\n_Cortex-M0_ at  48 MHz: STM32F091 board running Mbed OS 6\n\n| Operation          | p256-m | TinyCrypt |\n| ------------------ | -----: | --------: |\n| Key generation     |    921 |       979 |\n| ECDH shared secret |    922 |       975 |\n| ECDSA sign         |    990 |      1009 |\n| ECDSA verify       |   1976 |      1130 |\n| Sum of those 4     |   4809 |      4093 |\n\n_Cortex-M4_ at 100 MHz: STM32F411 board running Mbed OS 6\n\n| Operation          | p256-m | TinyCrypt |\n| ------------------ | -----: | --------: |\n| Key generation     |    145 |       178 |\n| ECDH shared secret |    144 |       177 |\n| ECDSA sign         |    155 |       188 |\n| ECDSA verify       |    309 |       210 |\n| Sum of those 4     |    753 |       753 |\n\n_Cortex-A7_ at 900 MHz: Raspberry Pi 2B running Raspbian Buster\n\n| Operation          | p256-m | TinyCrypt |\n| ------------------ | -----: | --------: |\n| Key generation     |     11 |        13 |\n| ECDH shared secret |     11 |        13 |\n| ECDSA sign         |     12 |        14 |\n| ECDSA verify       |     24 |        15 |\n| Sum of those 4     |     59 |        55 |\n\n_64-bit Intel_ (i7-6500U at 2.50GHz) laptop running Ubuntu 20.04\n\nNote: results in microseconds (previous benchmarks in milliseconds)\n\n| Operation          | p256-m | TinyCrypt |\n| ------------------ | -----: | --------: |\n| Key generation     |   1060 |      1627 |\n| ECDH shared secret |   1060 |      1611 |\n| ECDSA sign         |   1136 |      1712 |\n| ECDSA verify       |   2279 |      1888 |\n| Sum of those 4     |   5535 |      6838 |\n\n**Other differences**\n\n- While p256-m fully validates all inputs, Tinycrypt's ECDH shared secret\n  function doesn't include validation of the peer's public key, which should be\ndone separately by the user for static ECDH (there are attacks [when users\nforget](https://link.springer.com/chapter/10.1007/978-3-319-24174-6_21)).\n- The two implementations have slightly different security characteristics:\n  p256-m is fully constant-time from the ground up so should be more robust\nthan TinyCrypt against powerful local attackers (such as an untrusted OS\nattacking a secure enclave); on the other hand TinyCrypt includes coordinate\nrandomisation which protects against some passive physical attacks (such as\nDPA, see Table 3, column C9 of [this\npaper](https://www.esat.kuleuven.be/cosic/publications/article-2293.pdf#page=12)),\nwhich p256-m completely ignores.\n- TinyCrypt's code looks like it could easily be expanded to support other\n  curves, while p256-m has much more hard-coded to minimize code size (see\n\"Notes about other curves\" below).\n- TinyCrypt uses a specialised routine for reduction modulo the curve prime,\n  exploiting its structure as a Solinas prime, which should be faster than the\ngeneric Montgomery reduction used by p256-m, but other factors appear to\ncompensate for that.\n- TinyCrypt uses Co-Z Jacobian formulas for point operation, which should be\n  faster (though a bit larger) than the mixed affine-Jacobian formulas\nused by p256-m, but again other factors appear to compensate for that.\n- p256-m uses bits of inline assembly for 64-bit multiplication on the\n  platforms used for benchmarking, while TinyCrypt uses only C (and the\ncompiler's runtime library).\n- TinyCrypt uses a specialised routine based on Shamir's trick for\n  ECDSA verification, which gives much better performance than the generic\ncode that p256-m uses in order to minimize code size.\n\n## Design overview\n\nThe implementation is contained in a single file to keep most functions static\nand allow for more optimisations. It is organized in multiple layers:\n\n- Fixed-width multi-precision arithmetic\n- Fixed-width modular arithmetic\n- Operations on curve points\n- Operations with scalars\n- The public API\n\n**Multi-precision arithmetic.**\n\nLarge integers are represented as arrays of `uint32_t` limbs. When carries may\noccur, casts to `uint64_t` are used to nudge the compiler towards using the\nCPU's carry flag. When overflow may occur, functions return a carry flag.\n\nThis layer contains optional assembly for Cortex-M and Cortex-A cores, for the\ninternal `u32_muladd64()` function, as well as two pure C versions of this\nfunction, depending on whether `MUL64_IS_CONSTANT_TIME`.\n\nThis layer's API consists of:\n\n- addition, subtraction;\n- multiply-and-add, shift by one limb (for Montgomery multiplication);\n- conditional assignment, assignment of a small value;\n- comparison of two values for equality, comparison to 0 for equality;\n- (de)serialization as big-endian arrays of bytes.\n\n**Modular arithmetic.**\n\nAll modular operations are done in the Montgomery domain, that is x is\nrepresented by `x * 2^256 mod m`; integers need to be converted to that domain\nbefore computations, and back from it afterwards. Montgomery constants\nassociated to the curve's p and n are pre-computed and stored in static\nstructures.\n\nModular inversion is computed using Fermat's little theorem to get\nconstant-time behaviour with respect to the value being inverted.\n\nThis layer's API consists of:\n\n- the curve's constants p and n (and associated Montgomery constants);\n- modular addition, subtraction, multiplication, and inversion;\n- assignment of a small value;\n- conversion to/from Montgomery domain;\n- (de)serialization to/from bytes with integrated range checking and\n  Montgomery domain conversion.\n\n**Operations on curve points.**\n\nCurve points are represented using either affine or Jacobian coordinates;\naffine coordinates are extended to represent 0 as (0,0). Individual\ncoordinates are always in the Montgomery domain.\n\nNot all formulas associated with affine or Jacobian coordinates are complete;\ngreat care is taken to document and satisfy each function's pre-conditions.\n\nThis layer's API consists of:\n\n- curve constants: b from the equation, the base point's coordinates;\n- point validity check (on the curve and not 0);\n- Jacobian to affine coordinate conversion;\n- point doubling in Jacobian coordinates (complete formulas);\n- point addition in mixed affine-Jacobian coordinates (P not in {0, Q, -Q});\n- point addition-or-doubling in affine coordinates (leaky version, only used\n  for ECDSA verify where all data is public);\n- (de)serialization to/from bytes with integrated validity checking\n\n**Scalar operations.**\n\nThe crucial function here is scalar multiplication. It uses a signed binary\nladder, which is a variant of the good old double-and-add algorithm where an\naddition/subtraction is performed at each step. Again, care is taken to make\nsure the pre-conditions for the addition formulas are always satisfied. The\nsigned binary ladder only works if the scalar is odd; this is ensured by\nnegating both the scalar (mod n) and the input point if necessary.\n\nThis layer's API consists of:\n\n- scalar multiplication\n- de-serialization from bytes with integrated range checking\n- generation of a scalar and its associated public key\n\n**Public API.**\n\nThis layer builds on the others, but unlike them, all inputs and outputs are\nbyte arrays. Key generation and ECDH shared secret computation are thin\nwrappers around internal functions, just taking care of format conversions and\nerrors. The ECDSA functions have more non-trivial logic.\n\nThis layer's API consists of:\n\n- key-pair generation\n- ECDH shared secret computation\n- ECDSA signature creation\n- ECDSA signature verification\n\n**Testing.**\n\nA self-contained, straightforward, pure-Python implementation was first\nproduced as a warm-up and to help check intermediate values. Test vectors from\nvarious sources are embedded and used to validate the implementation.\n\nThis implementation, `p256.py`, is used by a second Python script,\n`gen-test-data.py`, to generate additional data for both positive and negative\ntesting, available from a C header file, that is then used by the closed-box\nand open-box test programs.\n\np256-m can be compiled with extra instrumentation to mark secret data and\nallow either valgrind or MemSan to check that no branch or memory access\ndepends on it (even indirectly). Macros are defined for this purpose near the\ntop of the file.\n\n**Tested platforms.**\n\nThere are 4 versions of the internal function `u32_muladd64`: two assembly\nversions, for Cortex-M/A cores with or without the DSP extension, and two\npure-C versions, depending on whether `MUL64_IS_CONSTANT_TIME`.\n\nTests are run on the following platforms:\n\n- `make` on x64 tests the pure-C version without `MUL64_IS_CONSTANT_TIME`\n  (with Clang).\n- `./consttime.sh` on x64 tests both pure-C versions (with Clang).\n- `make` on Arm v7-A (Raspberry Pi 2) tests the Arm-DSP assembly version (with\n  Clang).\n- `on-target-*box` on boards based on Cortex-M0 and M4 cores test both\n  assembly versions (with GCC).\n\nIn addition:\n\n- `sizes.sh` builds the code for three Arm cores with GCC and Clang.\n- `deps.sh` checks for external dependencies with GCC.\n\n## Notes about other curves\n\nIt should be clear that minimal code size can only be reached by specializing\nthe implementation to the curve at hand. Here's a list of things in the\nimplementation that are specific to the NIST P-256 curve, and how the\nimplementation could be changed to expand to other curves, layer by layer (see\n\"Design Overview\" above).\n\n**Fixed-width multi-precision arithmetic:**\n\n- The number of limbs is hard-coded to 8. For other 256-bit curves, nothing to\n  change. For a curve of another size, hard-code to another value. For multiple\ncurves of various sizes, add a parameter to each function specifying the\nnumber of limbs; when declaring arrays, always use the maximum number of\nlimbs.\n\n**Fixed-width modular arithmetic:**\n\n- The values of the curve's constant p and n, and their associated Montgomery\n  constants, are hard-coded. For another curve, just hard-code the new constants.\nFor multiple other curves, define all the constants, and from this layer's API\nonly keep the functions that already accept a `mod` parameter (that is, remove\nconvenience functions `m256_xxx_p()`).\n- The number of limbs is again hard-coded to 8. See above, but it order to\n  support multiple sizes there is no need to add a new parameter to functions\nin this layer: the existing `mod` parameter can include the number of limbs as\nwell.\n\n**Operations on curve points:**\n\n- The values of the curve's constants b (constant term from the equation) and\n  gx, gy (coordinates of the base point) are hard-coded. For another curve,\n  hard-code the other values. For multiple curves, define each curve's value and\nadd a \"curve id\" parameter to all functions in this layer.\n- The value of the curve's constant a is implicitly hard-coded to `-3` by using\n  a standard optimisation to save one multiplication in the first step of\n`point_double()`. For curves that don't have a == -3, replace that with the\nnormal computation.\n- The fact that b != 0 in the curve equation is used indirectly, to ensure\n  that (0, 0) is not a point on the curve and re-use that value to represent\nthe point 0. As far as I know, all Short Weierstrass curves standardized so\nfar have b != 0.\n- The shape of the curve is assumed to be Short Weierstrass. For other curve\n  shapes (Montgomery, (twisted) Edwards), this layer would probably look very\ndifferent (both implementation and API).\n\n**Scalar operations:**\n\n- If multiple curves are to be supported, all function in this layer need to\n  gain a new \"curve id\" parameter.\n- This layer assumes that the bit size of the curve's order n is the same as\n  that of the modulus p. This is true of most curves standardized so far, the\nonly exception being secp224k1. If that curve were to be supported, the\nrepresentation of `n` and scalars would need adapting to allow for an extra\nlimb.\n- The bit size of the curve's order is hard-coded in `scalar_mult()`. For\n  multiple curves, this should be deduced from the \"curve id\" parameter.\n- The `scalar_mult()` function exploits the fact that the second least\n  significant bit of the curve's order n is set in order to avoid a special\ncase. For curve orders that don't meet this criterion, we can just handle that\nspecial case (multiplication by +-2) separately (always compute that and\nconditionally assign it to the result).\n- The shape of the curve is again assumed to be Short Weierstrass. For other curve\n  shapes (Montgomery, (twisted) Edwards), this layer would probably have a\nvery different implementation.\n\n**Public API:**\n\n- For multiple curves, all functions in this layer would need to gain a \"curve\n  id\" parameter and handle variable-sized input/output.\n- The shape of the curve is again assumed to be Short Weierstrass. For other curve\n  shapes (Montgomery, (twisted) Edwards), the ECDH API would probably look\nquite similar (with differences in the size of public keys), but the ECDSA API\nwouldn't apply and an EdDSA API would look pretty different.\n\n## Notes about other platforms\n\nWhile p256-m is standard C99, it is written with constrained 32-bit platforms\nin mind and makes a few assumptions about the platform:\n\n- The types `uint8_t`, `uint16_t`, `uint32_t` and `uint64_t` exist.\n- 32-bit unsigned addition and subtraction with carry are constant time.\n- 16x16->32-bit unsigned multiplication is available and constant time.\n\nAlso, on platforms on which 64-bit addition and subtraction with carry, or\neven 64x64->128-bit multiplication, are available, p256-m makes no use of\nthem, though they could significantly improve performance.\n\nThis could be improved by replacing uses of arrays of `uint32_t` with a\ndefined type throughout the internal APIs, and then on 64-bit platforms define\nthat type to be an array of `uint64_t` instead, and making the obvious\nadaptations in the multi-precision arithmetic layer.\n\nFinally, the optional assembly code (which boosts performance by a factor 2 on\ntested Cortex-M CPUs, while slightly reducing code size and stack usage) is\ncurrently only available with compilers that support GCC's extended asm\nsyntax (which includes GCC and Clang).\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/p256-m/p256-m/p256-m.c",
    "content": "/*\n * Implementation of curve P-256 (ECDH and ECDSA)\n *\n * Copyright The Mbed TLS Contributors\n * Author: Manuel Pégourié-Gonnard.\n * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"p256-m.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"psa/crypto.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#if defined (MBEDTLS_PSA_P256M_DRIVER_ENABLED)\n\n/*\n * Zeroize memory - this should not be optimized away\n */\n#define zeroize mbedtls_platform_zeroize\n\n/*\n * Helpers to test constant-time behaviour with valgrind or MemSan.\n *\n * CT_POISON() is used for secret data. It marks the memory area as\n * uninitialised, so that any branch or pointer dereference that depends on it\n * (even indirectly) triggers a warning.\n * CT_UNPOISON() is used for public data; it marks the area as initialised.\n *\n * These are macros in order to avoid interfering with origin tracking.\n */\n#if defined(CT_MEMSAN)\n\n#include <sanitizer/msan_interface.h>\n#define CT_POISON   __msan_allocated_memory\n// void __msan_allocated_memory(const volatile void* data, size_t size);\n#define CT_UNPOISON __msan_unpoison\n// void __msan_unpoison(const volatile void *a, size_t size);\n\n#elif defined(CT_VALGRIND)\n\n#include <valgrind/memcheck.h>\n#define CT_POISON   VALGRIND_MAKE_MEM_UNDEFINED\n// VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr,_qzz_len)\n#define CT_UNPOISON VALGRIND_MAKE_MEM_DEFINED\n// VALGRIND_MAKE_MEM_DEFINED(_qzz_addr,_qzz_len)\n\n#else\n#define CT_POISON(p, sz)\n#define CT_UNPOISON(p, sz)\n#endif\n\n/**********************************************************************\n *\n * Operations on fixed-width unsigned integers\n *\n * Represented using 32-bit limbs, least significant limb first.\n * That is: x = x[0] + 2^32 x[1] + ... + 2^224 x[7] for 256-bit.\n *\n **********************************************************************/\n\n/*\n * 256-bit set to 32-bit value\n *\n * in: x in [0, 2^32)\n * out: z = x\n */\nstatic void u256_set32(uint32_t z[8], uint32_t x)\n{\n    z[0] = x;\n    for (unsigned i = 1; i < 8; i++) {\n        z[i] = 0;\n    }\n}\n\n/*\n * 256-bit addition\n *\n * in: x, y in [0, 2^256)\n * out: z = (x + y) mod 2^256\n *      c = (x + y) div 2^256\n * That is, z + c * 2^256 = x + y\n *\n * Note: as a memory area, z must be either equal to x or y, or not overlap.\n */\nstatic uint32_t u256_add(uint32_t z[8],\n                         const uint32_t x[8], const uint32_t y[8])\n{\n    uint32_t carry = 0;\n\n    for (unsigned i = 0; i < 8; i++) {\n        uint64_t sum = (uint64_t) carry + x[i] + y[i];\n        z[i] = (uint32_t) sum;\n        carry = (uint32_t) (sum >> 32);\n    }\n\n    return carry;\n}\n\n/*\n * 256-bit subtraction\n *\n * in: x, y in [0, 2^256)\n * out: z = (x - y) mod 2^256\n *      c = 0 if x >=y, 1 otherwise\n * That is, z = c * 2^256 + x - y\n *\n * Note: as a memory area, z must be either equal to x or y, or not overlap.\n */\nstatic uint32_t u256_sub(uint32_t z[8],\n                         const uint32_t x[8], const uint32_t y[8])\n{\n    uint32_t carry = 0;\n\n    for (unsigned i = 0; i < 8; i++) {\n        uint64_t diff = (uint64_t) x[i] - y[i] - carry;\n        z[i] = (uint32_t) diff;\n        carry = -(uint32_t) (diff >> 32);\n    }\n\n    return carry;\n}\n\n/*\n * 256-bit conditional assignment\n *\n * in: x in [0, 2^256)\n *     c in [0, 1]\n * out: z = x if c == 1, z unchanged otherwise\n *\n * Note: as a memory area, z must be either equal to x, or not overlap.\n */\nstatic void u256_cmov(uint32_t z[8], const uint32_t x[8], uint32_t c)\n{\n    const uint32_t x_mask = -c;\n    for (unsigned i = 0; i < 8; i++) {\n        z[i] = (z[i] & ~x_mask) | (x[i] & x_mask);\n    }\n}\n\n/*\n * 256-bit compare for equality\n *\n * in: x in [0, 2^256)\n *     y in [0, 2^256)\n * out: 0 if x == y, unspecified non-zero otherwise\n */\nstatic uint32_t u256_diff(const uint32_t x[8], const uint32_t y[8])\n{\n    uint32_t diff = 0;\n    for (unsigned i = 0; i < 8; i++) {\n        diff |= x[i] ^ y[i];\n    }\n    return diff;\n}\n\n/*\n * 256-bit compare to zero\n *\n * in: x in [0, 2^256)\n * out: 0 if x == 0, unspecified non-zero otherwise\n */\nstatic uint32_t u256_diff0(const uint32_t x[8])\n{\n    uint32_t diff = 0;\n    for (unsigned i = 0; i < 8; i++) {\n        diff |= x[i];\n    }\n    return diff;\n}\n\n/*\n * 32 x 32 -> 64-bit multiply-and-accumulate\n *\n * in: x, y, z, t in [0, 2^32)\n * out: x * y + z + t in [0, 2^64)\n *\n * Note: this computation cannot overflow.\n *\n * Note: this function has two pure-C implementations (depending on whether\n * MUL64_IS_CONSTANT_TIME), and possibly optimised asm implementations.\n * Start with the potential asm definitions, and use the C definition only if\n * we no have no asm for the current toolchain & CPU.\n */\nstatic uint64_t u32_muladd64(uint32_t x, uint32_t y, uint32_t z, uint32_t t);\n\n/* This macro is used to mark whether an asm implentation is found */\n#undef MULADD64_ASM\n/* This macro is used to mark whether the implementation has a small\n * code size (ie, it can be inlined even in an unrolled loop) */\n#undef MULADD64_SMALL\n\n/*\n * Currently assembly optimisations are only supported with GCC/Clang for\n * Arm's Cortex-A and Cortex-M lines of CPUs, which start with the v6-M and\n * v7-M architectures. __ARM_ARCH_PROFILE is not defined for v6 and earlier.\n * Thumb and 32-bit assembly is supported; aarch64 is not supported.\n */\n#if defined(__GNUC__) &&\\\n    defined(__ARM_ARCH) && __ARM_ARCH >= 6 && defined(__ARM_ARCH_PROFILE) && \\\n    ( __ARM_ARCH_PROFILE == 77 || __ARM_ARCH_PROFILE == 65 ) /* 'M' or 'A' */ && \\\n    !defined(__aarch64__)\n\n/*\n * This set of CPUs is conveniently partitioned as follows:\n *\n * 1. Cores that have the DSP extension, which includes a 1-cycle UMAAL\n *    instruction: M4, M7, M33, all A-class cores.\n * 2. Cores that don't have the DSP extension, and also lack a constant-time\n *    64-bit multiplication instruction:\n *    - M0, M0+, M23: 32-bit multiplication only;\n *    - M3: 64-bit multiplication is not constant-time.\n */\n#if defined(__ARM_FEATURE_DSP)\n\nstatic uint64_t u32_muladd64(uint32_t x, uint32_t y, uint32_t z, uint32_t t)\n{\n    __asm__(\n        /* UMAAL <RdLo>, <RdHi>, <Rn>, <Rm> */\n        \"umaal   %[z], %[t], %[x], %[y]\"\n        : [z] \"+l\" (z), [t] \"+l\" (t)\n        : [x] \"l\" (x), [y] \"l\" (y)\n    );\n    return ((uint64_t) t << 32) | z;\n}\n#define MULADD64_ASM\n#define MULADD64_SMALL\n\n#else /* __ARM_FEATURE_DSP */\n\n/*\n * This implementation only uses 16x16->32 bit multiplication.\n *\n * It decomposes the multiplicands as:\n *      x = xh:xl = 2^16 * xh + xl\n *      y = yh:yl = 2^16 * yh + yl\n * and computes their product as:\n *      x*y = xl*yl + 2**16 (xh*yl + yl*yh) + 2**32 xh*yh\n * then adds z and t to the result.\n */\nstatic uint64_t u32_muladd64(uint32_t x, uint32_t y, uint32_t z, uint32_t t)\n{\n    /* First compute x*y, using 3 temporary registers */\n    uint32_t tmp1, tmp2, tmp3;\n    __asm__(\n        \".syntax unified\\n\\t\"\n        /* start by splitting the inputs into halves */\n        \"lsrs    %[u], %[x], #16\\n\\t\"\n        \"lsrs    %[v], %[y], #16\\n\\t\"\n        \"uxth    %[x], %[x]\\n\\t\"\n        \"uxth    %[y], %[y]\\n\\t\"\n        /* now we have %[x], %[y], %[u], %[v] = xl, yl, xh, yh */\n        /* let's compute the 4 products we can form with those */\n        \"movs    %[w], %[v]\\n\\t\"\n        \"muls    %[w], %[u]\\n\\t\"\n        \"muls    %[v], %[x]\\n\\t\"\n        \"muls    %[x], %[y]\\n\\t\"\n        \"muls    %[y], %[u]\\n\\t\"\n        /* now we have %[x], %[y], %[v], %[w] = xl*yl, xh*yl, xl*yh, xh*yh */\n        /* let's split and add the first middle product */\n        \"lsls    %[u], %[y], #16\\n\\t\"\n        \"lsrs    %[y], %[y], #16\\n\\t\"\n        \"adds    %[x], %[u]\\n\\t\"\n        \"adcs    %[y], %[w]\\n\\t\"\n        /* let's finish with the second middle product */\n        \"lsls    %[u], %[v], #16\\n\\t\"\n        \"lsrs    %[v], %[v], #16\\n\\t\"\n        \"adds    %[x], %[u]\\n\\t\"\n        \"adcs    %[y], %[v]\\n\\t\"\n        : [x] \"+l\" (x), [y] \"+l\" (y),\n          [u] \"=&l\" (tmp1), [v] \"=&l\" (tmp2), [w] \"=&l\" (tmp3)\n        : /* no read-only inputs */\n        : \"cc\"\n    );\n    (void) tmp1;\n    (void) tmp2;\n    (void) tmp3;\n\n    /* Add z and t, using one temporary register */\n    __asm__(\n        \".syntax unified\\n\\t\"\n        \"movs    %[u], #0\\n\\t\"\n        \"adds    %[x], %[z]\\n\\t\"\n        \"adcs    %[y], %[u]\\n\\t\"\n        \"adds    %[x], %[t]\\n\\t\"\n        \"adcs    %[y], %[u]\\n\\t\"\n        : [x] \"+l\" (x), [y] \"+l\" (y), [u] \"=&l\" (tmp1)\n        : [z] \"l\" (z), [t] \"l\" (t)\n        : \"cc\"\n    );\n    (void) tmp1;\n\n    return ((uint64_t) y << 32) | x;\n}\n#define MULADD64_ASM\n\n#endif /* __ARM_FEATURE_DSP */\n\n#endif /* GCC/Clang with Cortex-M/A CPU */\n\n#if !defined(MULADD64_ASM)\n#if defined(MUL64_IS_CONSTANT_TIME)\nstatic uint64_t u32_muladd64(uint32_t x, uint32_t y, uint32_t z, uint32_t t)\n{\n    return (uint64_t) x * y + z + t;\n}\n#define MULADD64_SMALL\n#else\nstatic uint64_t u32_muladd64(uint32_t x, uint32_t y, uint32_t z, uint32_t t)\n{\n    /* x = xl + 2**16 xh, y = yl + 2**16 yh */\n    const uint16_t xl = (uint16_t) x;\n    const uint16_t yl = (uint16_t) y;\n    const uint16_t xh = x >> 16;\n    const uint16_t yh = y >> 16;\n\n    /* x*y = xl*yl + 2**16 (xh*yl + yl*yh) + 2**32 xh*yh\n     *     = lo    + 2**16 (m1    + m2   ) + 2**32 hi    */\n    const uint32_t lo = (uint32_t) xl * yl;\n    const uint32_t m1 = (uint32_t) xh * yl;\n    const uint32_t m2 = (uint32_t) xl * yh;\n    const uint32_t hi = (uint32_t) xh * yh;\n\n    uint64_t acc = lo + ((uint64_t) (hi + (m1 >> 16) + (m2 >> 16)) << 32);\n    acc += m1 << 16;\n    acc += m2 << 16;\n    acc += z;\n    acc += t;\n\n    return acc;\n}\n#endif /* MUL64_IS_CONSTANT_TIME */\n#endif /* MULADD64_ASM */\n\n/*\n * 288 + 32 x 256 -> 288-bit multiply and add\n *\n * in: x in [0, 2^32)\n *     y in [0, 2^256)\n *     z in [0, 2^288)\n * out: z_out = z_in + x * y mod 2^288\n *      c     = z_in + x * y div 2^288\n * That is, z_out + c * 2^288 = z_in + x * y\n *\n * Note: as a memory area, z must be either equal to y, or not overlap.\n *\n * This is a helper for Montgomery multiplication.\n */\nstatic uint32_t u288_muladd(uint32_t z[9], uint32_t x, const uint32_t y[8])\n{\n    uint32_t carry = 0;\n\n#define U288_MULADD_STEP(i) \\\n    do { \\\n        uint64_t prod = u32_muladd64(x, y[i], z[i], carry); \\\n        z[i] = (uint32_t) prod; \\\n        carry = (uint32_t) (prod >> 32); \\\n    } while( 0 )\n\n#if defined(MULADD64_SMALL)\n    U288_MULADD_STEP(0);\n    U288_MULADD_STEP(1);\n    U288_MULADD_STEP(2);\n    U288_MULADD_STEP(3);\n    U288_MULADD_STEP(4);\n    U288_MULADD_STEP(5);\n    U288_MULADD_STEP(6);\n    U288_MULADD_STEP(7);\n#else\n    for (unsigned i = 0; i < 8; i++) {\n        U288_MULADD_STEP(i);\n    }\n#endif\n\n    uint64_t sum = (uint64_t) z[8] + carry;\n    z[8] = (uint32_t) sum;\n    carry = (uint32_t) (sum >> 32);\n\n    return carry;\n}\n\n/*\n * 288-bit in-place right shift by 32 bits\n *\n * in: z in [0, 2^288)\n *     c in [0, 2^32)\n * out: z_out = z_in div 2^32 + c * 2^256\n *            = (z_in + c * 2^288) div 2^32\n *\n * This is a helper for Montgomery multiplication.\n */\nstatic void u288_rshift32(uint32_t z[9], uint32_t c)\n{\n    for (unsigned i = 0; i < 8; i++) {\n        z[i] = z[i + 1];\n    }\n    z[8] = c;\n}\n\n/*\n * 256-bit import from big-endian bytes\n *\n * in: p = p0, ..., p31\n * out: z = p0 * 2^248 + p1 * 2^240 + ... + p30 * 2^8 + p31\n */\nstatic void u256_from_bytes(uint32_t z[8], const uint8_t p[32])\n{\n    for (unsigned i = 0; i < 8; i++) {\n        unsigned j = 4 * (7 - i);\n        z[i] = ((uint32_t) p[j + 0] << 24) |\n               ((uint32_t) p[j + 1] << 16) |\n               ((uint32_t) p[j + 2] <<  8) |\n               ((uint32_t) p[j + 3] <<  0);\n    }\n}\n\n/*\n * 256-bit export to big-endian bytes\n *\n * in: z in [0, 2^256)\n * out: p = p0, ..., p31 such that\n *      z = p0 * 2^248 + p1 * 2^240 + ... + p30 * 2^8 + p31\n */\nstatic void u256_to_bytes(uint8_t p[32], const uint32_t z[8])\n{\n    for (unsigned i = 0; i < 8; i++) {\n        unsigned j = 4 * (7 - i);\n        p[j + 0] = (uint8_t) (z[i] >> 24);\n        p[j + 1] = (uint8_t) (z[i] >> 16);\n        p[j + 2] = (uint8_t) (z[i] >>  8);\n        p[j + 3] = (uint8_t) (z[i] >>  0);\n    }\n}\n\n/**********************************************************************\n *\n * Operations modulo a 256-bit prime m\n *\n * These are done in the Montgomery domain, that is x is represented by\n *  x * 2^256 mod m\n * Numbers need to be converted to that domain before computations,\n * and back from it afterwards.\n *\n * Inversion is computed using Fermat's little theorem.\n *\n * Assumptions on m:\n * - Montgomery operations require that m is odd.\n * - Fermat's little theorem require it to be a prime.\n * - m256_inv() further requires that m % 2^32 >= 2.\n * - m256_inv() also assumes that the value of m is not a secret.\n *\n * In practice operations are done modulo the curve's p and n,\n * both of which satisfy those assumptions.\n *\n **********************************************************************/\n\n/*\n * Data associated to a modulus for Montgomery operations.\n *\n * m in [0, 2^256) - the modulus itself, must be odd\n * R2 = 2^512 mod m\n * ni = -m^-1 mod 2^32\n */\ntypedef struct {\n    uint32_t m[8];\n    uint32_t R2[8];\n    uint32_t ni;\n}\nm256_mod;\n\n/*\n * Data for Montgomery operations modulo the curve's p\n */\nstatic const m256_mod p256_p = {\n    {   /* the curve's p */\n        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,\n        0x00000000, 0x00000000, 0x00000001, 0xFFFFFFFF,\n    },\n    {   /* 2^512 mod p */\n        0x00000003, 0x00000000, 0xffffffff, 0xfffffffb,\n        0xfffffffe, 0xffffffff, 0xfffffffd, 0x00000004,\n    },\n    0x00000001, /* -p^-1 mod 2^32 */\n};\n\n/*\n * Data for Montgomery operations modulo the curve's n\n */\nstatic const m256_mod p256_n = {\n    {   /* the curve's n */\n        0xFC632551, 0xF3B9CAC2, 0xA7179E84, 0xBCE6FAAD,\n        0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,\n    },\n    {   /* 2^512 mod n */\n        0xbe79eea2, 0x83244c95, 0x49bd6fa6, 0x4699799c,\n        0x2b6bec59, 0x2845b239, 0xf3d95620, 0x66e12d94,\n    },\n    0xee00bc4f, /* -n^-1 mod 2^32 */\n};\n\n/*\n * Modular addition\n *\n * in: x, y in [0, m)\n *     mod must point to a valid m256_mod structure\n * out: z = (x + y) mod m, in [0, m)\n *\n * Note: as a memory area, z must be either equal to x or y, or not overlap.\n */\nstatic void m256_add(uint32_t z[8],\n                     const uint32_t x[8], const uint32_t y[8],\n                     const m256_mod *mod)\n{\n    uint32_t r[8];\n    uint32_t carry_add = u256_add(z, x, y);\n    uint32_t carry_sub = u256_sub(r, z, mod->m);\n    /* Need to subract m if:\n     *      x+y >= 2^256 > m (that is, carry_add == 1)\n     *   OR z >= m (that is, carry_sub == 0) */\n    uint32_t use_sub = carry_add | (1 - carry_sub);\n    u256_cmov(z, r, use_sub);\n}\n\n/*\n * Modular addition mod p\n *\n * in: x, y in [0, p)\n * out: z = (x + y) mod p, in [0, p)\n *\n * Note: as a memory area, z must be either equal to x or y, or not overlap.\n */\nstatic void m256_add_p(uint32_t z[8],\n                       const uint32_t x[8], const uint32_t y[8])\n{\n    m256_add(z, x, y, &p256_p);\n}\n\n/*\n * Modular subtraction\n *\n * in: x, y in [0, m)\n *     mod must point to a valid m256_mod structure\n * out: z = (x - y) mod m, in [0, m)\n *\n * Note: as a memory area, z must be either equal to x or y, or not overlap.\n */\nstatic void m256_sub(uint32_t z[8],\n                     const uint32_t x[8], const uint32_t y[8],\n                     const m256_mod *mod)\n{\n    uint32_t r[8];\n    uint32_t carry = u256_sub(z, x, y);\n    (void) u256_add(r, z, mod->m);\n    /* Need to add m if and only if x < y, that is carry == 1.\n     * In that case z is in [2^256 - m + 1, 2^256 - 1], so the\n     * addition will have a carry as well, which cancels out. */\n    u256_cmov(z, r, carry);\n}\n\n/*\n * Modular subtraction mod p\n *\n * in: x, y in [0, p)\n * out: z = (x + y) mod p, in [0, p)\n *\n * Note: as a memory area, z must be either equal to x or y, or not overlap.\n */\nstatic void m256_sub_p(uint32_t z[8],\n                       const uint32_t x[8], const uint32_t y[8])\n{\n    m256_sub(z, x, y, &p256_p);\n}\n\n/*\n * Montgomery modular multiplication\n *\n * in: x, y in [0, m)\n *     mod must point to a valid m256_mod structure\n * out: z = (x * y) / 2^256 mod m, in [0, m)\n *\n * Note: as a memory area, z may overlap with x or y.\n */\nstatic void m256_mul(uint32_t z[8],\n                     const uint32_t x[8], const uint32_t y[8],\n                     const m256_mod *mod)\n{\n    /*\n     * Algorithm 14.36 in Handbook of Applied Cryptography with:\n     * b = 2^32, n = 8, R = 2^256\n     */\n    uint32_t m_prime = mod->ni;\n    uint32_t a[9];\n\n    for (unsigned i = 0; i < 9; i++) {\n        a[i] = 0;\n    }\n\n    for (unsigned i = 0; i < 8; i++) {\n        /* the \"mod 2^32\" is implicit from the type */\n        uint32_t u = (a[0] + x[i] * y[0]) * m_prime;\n\n        /* a = (a + x[i] * y + u * m) div b */\n        uint32_t c = u288_muladd(a, x[i], y);\n        c += u288_muladd(a, u, mod->m);\n        u288_rshift32(a, c);\n    }\n\n    /* a = a > m ? a - m : a */\n    uint32_t carry_add = a[8];  // 0 or 1 since a < 2m, see HAC Note 14.37\n    uint32_t carry_sub = u256_sub(z, a, mod->m);\n    uint32_t use_sub = carry_add | (1 - carry_sub);     // see m256_add()\n    u256_cmov(z, a, 1 - use_sub);\n}\n\n/*\n * Montgomery modular multiplication modulo p.\n *\n * in: x, y in [0, p)\n * out: z = (x * y) / 2^256 mod p, in [0, p)\n *\n * Note: as a memory area, z may overlap with x or y.\n */\nstatic void m256_mul_p(uint32_t z[8],\n                       const uint32_t x[8], const uint32_t y[8])\n{\n    m256_mul(z, x, y, &p256_p);\n}\n\n/*\n * In-place conversion to Montgomery form\n *\n * in: z in [0, m)\n *     mod must point to a valid m256_mod structure\n * out: z_out = z_in * 2^256 mod m, in [0, m)\n */\nstatic void m256_prep(uint32_t z[8], const m256_mod *mod)\n{\n    m256_mul(z, z, mod->R2, mod);\n}\n\n/*\n * In-place conversion from Montgomery form\n *\n * in: z in [0, m)\n *     mod must point to a valid m256_mod structure\n * out: z_out = z_in / 2^256 mod m, in [0, m)\n * That is, z_in was z_actual * 2^256 mod m, and z_out is z_actual\n */\nstatic void m256_done(uint32_t z[8], const m256_mod *mod)\n{\n    uint32_t one[8];\n    u256_set32(one, 1);\n    m256_mul(z, z, one, mod);\n}\n\n/*\n * Set to 32-bit value\n *\n * in: x in [0, 2^32)\n *     mod must point to a valid m256_mod structure\n * out: z = x * 2^256 mod m, in [0, m)\n * That is, z is set to the image of x in the Montgomery domain.\n */\nstatic void m256_set32(uint32_t z[8], uint32_t x, const m256_mod *mod)\n{\n    u256_set32(z, x);\n    m256_prep(z, mod);\n}\n\n/*\n * Modular inversion in Montgomery form\n *\n * in: x in [0, m)\n *     mod must point to a valid m256_mod structure\n *     such that mod->m % 2^32 >= 2, assumed to be public.\n * out: z = x^-1 * 2^512 mod m if x != 0,\n *      z = 0 if x == 0\n * That is, if x = x_actual    * 2^256 mod m, then\n *             z = x_actual^-1 * 2^256 mod m\n *\n * Note: as a memory area, z may overlap with x.\n */\nstatic void m256_inv(uint32_t z[8], const uint32_t x[8],\n                     const m256_mod *mod)\n{\n    /*\n     * Use Fermat's little theorem to compute x^-1 as x^(m-2).\n     *\n     * Take advantage of the fact that both p's and n's least significant limb\n     * is at least 2 to perform the subtraction on the flight (no carry).\n     *\n     * Use plain right-to-left binary exponentiation;\n     * branches are OK as the exponent is not a secret.\n     */\n    uint32_t bitval[8];\n    u256_cmov(bitval, x, 1);    /* copy x before writing to z */\n\n    m256_set32(z, 1, mod);\n\n    unsigned i = 0;\n    uint32_t limb = mod->m[i] - 2;\n    while (1) {\n        for (unsigned j = 0; j < 32; j++) {\n            if ((limb & 1) != 0) {\n                m256_mul(z, z, bitval, mod);\n            }\n            m256_mul(bitval, bitval, bitval, mod);\n            limb >>= 1;\n        }\n\n        if (i == 7)\n            break;\n\n        i++;\n        limb = mod->m[i];\n    }\n}\n\n/*\n * Import modular integer from bytes to Montgomery domain\n *\n * in: p = p0, ..., p32\n *     mod must point to a valid m256_mod structure\n * out: z = (p0 * 2^248 + ... + p31) * 2^256 mod m, in [0, m)\n *      return 0 if the number was already in [0, m), or -1.\n *      z may be incorrect and must be discared when -1 is returned.\n */\nstatic int m256_from_bytes(uint32_t z[8],\n                           const uint8_t p[32], const m256_mod *mod)\n{\n    u256_from_bytes(z, p);\n\n    uint32_t t[8];\n    uint32_t lt_m = u256_sub(t, z, mod->m);\n    if (lt_m != 1)\n        return -1;\n\n    m256_prep(z, mod);\n    return 0;\n}\n\n/*\n * Export modular integer from Montgomery domain to bytes\n *\n * in: z in [0, 2^256)\n *     mod must point to a valid m256_mod structure\n * out: p = p0, ..., p31 such that\n *      z = (p0 * 2^248 + ... + p31) * 2^256 mod m\n */\nstatic void m256_to_bytes(uint8_t p[32],\n                          const uint32_t z[8], const m256_mod *mod)\n{\n    uint32_t zi[8];\n    u256_cmov(zi, z, 1);\n    m256_done(zi, mod);\n\n    u256_to_bytes(p, zi);\n}\n\n/**********************************************************************\n *\n * Operations on curve points\n *\n * Points are represented in two coordinates system:\n *  - affine (x, y) - extended to represent 0 (see below)\n *  - jacobian (x:y:z)\n * In either case, coordinates are integers modulo p256_p and\n * are always represented in the Montgomery domain.\n *\n * For background on jacobian coordinates, see for example [GECC] 3.2.2:\n * - conversions go (x, y) -> (x:y:1) and (x:y:z) -> (x/z^2, y/z^3)\n * - the curve equation becomes y^2 = x^3 - 3 x z^4 + b z^6\n * - 0 (aka the origin aka point at infinity) is (x:y:0) with y^2 = x^3.\n * - point negation goes -(x:y:z) = (x:-y:z)\n *\n * Normally 0 (the point at infinity) can't be represented in affine\n * coordinates. However we extend affine coordinates with the convention that\n * (0, 0) (which is normally not a point on the curve) is interpreted as 0.\n *\n * References:\n * - [GECC]: Guide to Elliptic Curve Cryptography; Hankerson, Menezes,\n *   Vanstone; Springer, 2004.\n * - [CMO98]: Efficient Elliptic Curve Exponentiation Using Mixed Coordinates;\n *   Cohen, Miyaji, Ono; Springer, ASIACRYPT 1998.\n *   https://link.springer.com/content/pdf/10.1007/3-540-49649-1_6.pdf\n * - [RCB15]: Complete addition formulas for prime order elliptic curves;\n *   Renes, Costello, Batina; IACR e-print 2015-1060.\n *   https://eprint.iacr.org/2015/1060.pdf\n *\n **********************************************************************/\n\n/*\n * The curve's b parameter in the Short Weierstrass equation\n *  y^2 = x^3 - 3*x + b\n * Compared to the standard, this is converted to the Montgomery domain.\n */\nstatic const uint32_t p256_b[8] = { /* b * 2^256 mod p */\n    0x29c4bddf, 0xd89cdf62, 0x78843090, 0xacf005cd,\n    0xf7212ed6, 0xe5a220ab, 0x04874834, 0xdc30061d,\n};\n\n/*\n * The curve's conventional base point G.\n * Compared to the standard, coordinates converted to the Montgomery domain.\n */\nstatic const uint32_t p256_gx[8] = { /* G_x * 2^256 mod p */\n    0x18a9143c, 0x79e730d4, 0x5fedb601, 0x75ba95fc,\n    0x77622510, 0x79fb732b, 0xa53755c6, 0x18905f76,\n};\nstatic const uint32_t p256_gy[8] = { /* G_y * 2^256 mod p */\n    0xce95560a, 0xddf25357, 0xba19e45c, 0x8b4ab8e4,\n    0xdd21f325, 0xd2e88688, 0x25885d85, 0x8571ff18,\n};\n\n/*\n * Point-on-curve check - do the coordinates satisfy the curve's equation?\n *\n * in: x, y in [0, p)   (Montgomery domain)\n * out: 0 if the point lies on the curve and is not 0,\n *      unspecified non-zero otherwise\n */\nstatic uint32_t point_check(const uint32_t x[8], const uint32_t y[8])\n{\n    uint32_t lhs[8], rhs[8];\n\n    /* lhs = y^2 */\n    m256_mul_p(lhs, y, y);\n\n    /* rhs = x^3 - 3x + b */\n    m256_mul_p(rhs, x,   x);      /* x^2 */\n    m256_mul_p(rhs, rhs, x);      /* x^3 */\n    for (unsigned i = 0; i < 3; i++)\n        m256_sub_p(rhs, rhs, x);  /* x^3 - 3x */\n    m256_add_p(rhs, rhs, p256_b); /* x^3 - 3x + b */\n\n    return u256_diff(lhs, rhs);\n}\n\n/*\n * In-place jacobian to affine coordinate conversion\n *\n * in: (x:y:z) must be on the curve (coordinates in Montegomery domain)\n * out: x_out = x_in / z_in^2   (Montgomery domain)\n *      y_out = y_in / z_in^3   (Montgomery domain)\n *      z_out unspecified, must be disregarded\n *\n * Note: if z is 0 (that is, the input point is 0), x_out = y_out = 0.\n */\nstatic void point_to_affine(uint32_t x[8], uint32_t y[8], uint32_t z[8])\n{\n    uint32_t t[8];\n\n    m256_inv(z, z, &p256_p);    /* z = z^-1 */\n\n    m256_mul_p(t, z, z);        /* t = z^-2 */\n    m256_mul_p(x, x, t);        /* x = x * z^-2 */\n\n    m256_mul_p(t, t, z);        /* t = z^-3 */\n    m256_mul_p(y, y, t);        /* y = y * z^-3 */\n}\n\n/*\n * In-place point doubling in jacobian coordinates (Montgomery domain)\n *\n * in: P_in = (x:y:z), must be on the curve\n * out: (x:y:z) = P_out = 2 * P_in\n */\nstatic void point_double(uint32_t x[8], uint32_t y[8], uint32_t z[8])\n{\n    /*\n     * This is formula 6 from [CMO98], cited as complete in [RCB15] (table 1).\n     * Notations as in the paper, except u added and t ommited (it's x3).\n     */\n    uint32_t m[8], s[8], u[8];\n\n    /* m = 3 * x^2 + a * z^4 = 3 * (x + z^2) * (x - z^2) */\n    m256_mul_p(s, z, z);\n    m256_add_p(m, x, s);\n    m256_sub_p(u, x, s);\n    m256_mul_p(s, m, u);\n    m256_add_p(m, s, s);\n    m256_add_p(m, m, s);\n\n    /* s = 4 * x * y^2 */\n    m256_mul_p(u, y, y);\n    m256_add_p(u, u, u); /* u = 2 * y^2 (used below) */\n    m256_mul_p(s, x, u);\n    m256_add_p(s, s, s);\n\n    /* u = 8 * y^4 (not named in the paper, first term of y3) */\n    m256_mul_p(u, u, u);\n    m256_add_p(u, u, u);\n\n    /* x3 = t = m^2 - 2 * s */\n    m256_mul_p(x, m, m);\n    m256_sub_p(x, x, s);\n    m256_sub_p(x, x, s);\n\n    /* z3 = 2 * y * z */\n    m256_mul_p(z, y, z);\n    m256_add_p(z, z, z);\n\n    /* y3 = -u + m * (s - t) */\n    m256_sub_p(y, s, x);\n    m256_mul_p(y, y, m);\n    m256_sub_p(y, y, u);\n}\n\n/*\n * In-place point addition in jacobian-affine coordinates (Montgomery domain)\n *\n * in: P_in = (x1:y1:z1), must be on the curve and not 0\n *     Q = (x2, y2), must be on the curve and not P_in or -P_in or 0\n * out: P_out = (x1:y1:z1) = P_in + Q\n */\nstatic void point_add(uint32_t x1[8], uint32_t y1[8], uint32_t z1[8],\n                      const uint32_t x2[8], const uint32_t y2[8])\n{\n    /*\n     * This is formula 5 from [CMO98], with z2 == 1 substituted. We use\n     * intermediates with neutral names, and names from the paper in comments.\n     */\n    uint32_t t1[8], t2[8], t3[8];\n\n    /* u1 = x1 and s1 = y1 (no computations) */\n\n    /* t1 = u2 = x2 z1^2 */\n    m256_mul_p(t1, z1, z1);\n    m256_mul_p(t2, t1, z1);\n    m256_mul_p(t1, t1, x2);\n\n    /* t2 = s2 = y2 z1^3 */\n    m256_mul_p(t2, t2, y2);\n\n    /* t1 = h = u2 - u1 */\n    m256_sub_p(t1, t1, x1); /* t1 = x2 * z1^2 - x1 */\n\n    /* t2 = r = s2 - s1 */\n    m256_sub_p(t2, t2, y1);\n\n    /* z3 = z1 * h */\n    m256_mul_p(z1, z1, t1);\n\n    /* t1 = h^3 */\n    m256_mul_p(t3, t1, t1);\n    m256_mul_p(t1, t3, t1);\n\n    /* t3 = x1 * h^2 */\n    m256_mul_p(t3, t3, x1);\n\n    /* x3 = r^2 - 2 * x1 * h^2 - h^3 */\n    m256_mul_p(x1, t2, t2);\n    m256_sub_p(x1, x1, t3);\n    m256_sub_p(x1, x1, t3);\n    m256_sub_p(x1, x1, t1);\n\n    /* y3 = r * (x1 * h^2 - x3) - y1 h^3 */\n    m256_sub_p(t3, t3, x1);\n    m256_mul_p(t3, t3, t2);\n    m256_mul_p(t1, t1, y1);\n    m256_sub_p(y1, t3, t1);\n}\n\n/*\n * Point addition or doubling (affine to jacobian, Montgomery domain)\n *\n * in: P = (x1, y1) - must be on the curve and not 0\n *     Q = (x2, y2) - must be on the curve and not 0\n * out: (x3, y3) = R = P + Q\n *\n * Note: unlike point_add(), this function works if P = +- Q;\n * however it leaks information on its input through timing,\n * branches taken and memory access patterns (if observable).\n */\nstatic void point_add_or_double_leaky(\n                        uint32_t x3[8], uint32_t y3[8],\n                        const uint32_t x1[8], const uint32_t y1[8],\n                        const uint32_t x2[8], const uint32_t y2[8])\n{\n\n    uint32_t z3[8];\n    u256_cmov(x3, x1, 1);\n    u256_cmov(y3, y1, 1);\n    m256_set32(z3, 1, &p256_p);\n\n    if (u256_diff(x1, x2) != 0) {\n        // P != +- Q -> generic addition\n        point_add(x3, y3, z3, x2, y2);\n        point_to_affine(x3, y3, z3);\n    }\n    else if (u256_diff(y1, y2) == 0) {\n        // P == Q -> double\n        point_double(x3, y3, z3);\n        point_to_affine(x3, y3, z3);\n    } else {\n        // P == -Q -> zero\n        m256_set32(x3, 0, &p256_p);\n        m256_set32(y3, 0, &p256_p);\n    }\n}\n\n/*\n * Import curve point from bytes\n *\n * in: p = (x, y) concatenated, fixed-width 256-bit big-endian integers\n * out: x, y in Mongomery domain\n *      return 0 if x and y are both in [0, p)\n *                  and (x, y) is on the curve and not 0\n *             unspecified non-zero otherwise.\n *      x and y are unspecified and must be discarded if returning non-zero.\n */\nstatic int point_from_bytes(uint32_t x[8], uint32_t y[8], const uint8_t p[64])\n{\n    int ret;\n\n    ret = m256_from_bytes(x, p, &p256_p);\n    if (ret != 0)\n        return ret;\n\n    ret = m256_from_bytes(y, p + 32, &p256_p);\n    if (ret != 0)\n        return ret;\n\n    return (int) point_check(x, y);\n}\n\n/*\n * Export curve point to bytes\n *\n * in: x, y affine coordinates of a point (Montgomery domain)\n *     must be on the curve and not 0\n * out: p = (x, y) concatenated, fixed-width 256-bit big-endian integers\n */\nstatic void point_to_bytes(uint8_t p[64],\n                           const uint32_t x[8], const uint32_t y[8])\n{\n    m256_to_bytes(p,        x, &p256_p);\n    m256_to_bytes(p + 32,   y, &p256_p);\n}\n\n/**********************************************************************\n *\n * Scalar multiplication and other scalar-related operations\n *\n **********************************************************************/\n\n/*\n * Scalar multiplication\n *\n * in: P = (px, py), affine (Montgomery), must be on the curve and not 0\n *     s in [1, n-1]\n * out: R = s * P = (rx, ry), affine coordinates (Montgomery).\n *\n * Note: as memory areas, none of the parameters may overlap.\n */\nstatic void scalar_mult(uint32_t rx[8], uint32_t ry[8],\n                        const uint32_t px[8], const uint32_t py[8],\n                        const uint32_t s[8])\n{\n    /*\n     * We use a signed binary ladder, see for example slides 10-14 of\n     * http://ecc2015.math.u-bordeaux1.fr/documents/hamburg.pdf but with\n     * implicit recoding, and a different loop initialisation to avoid feeding\n     * 0 to our addition formulas, as they don't support it.\n     */\n    uint32_t s_odd[8], py_neg[8], py_use[8], rz[8];\n\n    /*\n     * Make s odd by replacing it with n - s if necessary.\n     *\n     * If s was odd, we'll have s_odd = s, and define P' = P.\n     * Otherwise, we'll have s_odd = n - s and define P' = -P.\n     *\n     * Either way, we can compute s * P as s_odd * P'.\n     */\n    u256_sub(s_odd, p256_n.m, s); /* no carry, result still in [1, n-1] */\n    uint32_t negate = ~s[0] & 1;\n    u256_cmov(s_odd, s, 1 - negate);\n\n    /* Compute py_neg = - py mod p (that's the y coordinate of -P) */\n    u256_set32(py_use, 0);\n    m256_sub_p(py_neg, py_use, py);\n\n    /* Initialize R = P' = (x:(-1)^negate * y:1) */\n    u256_cmov(rx, px, 1);\n    u256_cmov(ry, py, 1);\n    m256_set32(rz, 1, &p256_p);\n    u256_cmov(ry, py_neg, negate);\n\n    /*\n     * For any odd number s_odd = b255 ... b1 1, we have\n     *      s_odd = 2^255 + 2^254 sbit(b255) + ... + 2 sbit(b2) + sbit(b1)\n     * writing\n     *      sbit(b) = 2 * b - 1 = b ? 1 : -1\n     *\n     * Use that to compute s_odd * P' by repeating R = 2 * R +- P':\n     *      s_odd * P' = 2 * ( ... (2 * P' + sbit(b255) P') ... ) + sbit(b1) P'\n     *\n     * The loop invariant is that when beginning an iteration we have\n     *      R = s_i P'\n     * with\n     *      s_i = 2^(255-i) + 2^(254-i) sbit(b_255) + ...\n     * where the sum has 256 - i terms.\n     *\n     * When updating R we need to make sure the input to point_add() is\n     * neither 0 not +-P'. Since that input is 2 s_i P', it is sufficient to\n     * see that 1 < 2 s_i < n-1. The lower bound is obvious since s_i is a\n     * positive integer, and for the upper bound we distinguish three cases.\n     *\n     * If i > 1, then s_i < 2^254, so 2 s_i < 2^255 < n-1.\n     * Otherwise, i == 1 and we have 2 s_i = s_odd - sbit(b1).\n     *      If s_odd <= n-4, then 2 s_1 <= n-3.\n     *      Otherwise, s_odd = n-2, and for this curve's value of n,\n     *      we have b1 == 1, so sbit(b1) = 1 and 2 s_1 <= n-3.\n     */\n    for (unsigned i = 255; i > 0; i--) {\n        uint32_t bit = (s_odd[i / 32] >> i % 32) & 1;\n\n        /* set (px, py_use) = sbit(bit) P' = sbit(bit) * (-1)^negate P */\n        u256_cmov(py_use, py, bit ^ negate);\n        u256_cmov(py_use, py_neg, (1 - bit) ^ negate);\n\n        /* Update R = 2 * R +- P' */\n        point_double(rx, ry, rz);\n        point_add(rx, ry, rz, px, py_use);\n    }\n\n    point_to_affine(rx, ry, rz);\n}\n\n/*\n * Scalar import from big-endian bytes\n *\n * in: p = p0, ..., p31\n * out: s = p0 * 2^248 + p1 * 2^240 + ... + p30 * 2^8 + p31\n *      return 0 if s in [1, n-1],\n *            -1 otherwise.\n */\nstatic int scalar_from_bytes(uint32_t s[8], const uint8_t p[32])\n{\n    u256_from_bytes(s, p);\n\n    uint32_t r[8];\n    uint32_t lt_n = u256_sub(r, s, p256_n.m);\n\n    u256_set32(r, 1);\n    uint32_t lt_1 = u256_sub(r, s, r);\n\n    if (lt_n && !lt_1)\n        return 0;\n\n    return -1;\n}\n\n/* Using RNG functions from Mbed TLS as p256-m does not come with a\n * cryptographically secure RNG function.\n */\nint p256_generate_random(uint8_t *output, unsigned output_size)\n{\n    int ret;\n    ret = psa_generate_random(output, output_size);\n\n    if (ret != 0){\n        return P256_RANDOM_FAILED;\n    }\n    return P256_SUCCESS;\n}\n\n/*\n * Scalar generation, with public key\n *\n * out: sbytes the big-endian bytes representation of the scalar\n *      s its u256 representation\n *      x, y the affine coordinates of s * G (Montgomery domain)\n *      return 0 if OK, -1 on failure\n *      sbytes, s, x, y must be discarded when returning non-zero.\n */\nstatic int scalar_gen_with_pub(uint8_t sbytes[32], uint32_t s[8],\n                               uint32_t x[8], uint32_t y[8])\n{\n    /* generate a random valid scalar */\n    int ret;\n    unsigned nb_tried = 0;\n    do {\n        if (nb_tried++ >= 4)\n            return -1;\n\n        ret = p256_generate_random(sbytes, 32);\n        CT_POISON(sbytes, 32);\n        if (ret != 0)\n            return -1;\n\n        ret = scalar_from_bytes(s, sbytes);\n        CT_UNPOISON(&ret, sizeof ret);\n    }\n    while (ret != 0);\n\n    /* compute and ouput the associated public key */\n    scalar_mult(x, y, p256_gx, p256_gy, s);\n\n    /* the associated public key is not a secret */\n    CT_UNPOISON(x, 32);\n    CT_UNPOISON(y, 32);\n\n    return 0;\n}\n\n/*\n * ECDH/ECDSA generate pair\n */\nint p256_gen_keypair(uint8_t priv[32], uint8_t pub[64])\n{\n    uint32_t s[8], x[8], y[8];\n    int ret = scalar_gen_with_pub(priv, s, x, y);\n    zeroize(s, sizeof s);\n    if (ret != 0)\n        return P256_RANDOM_FAILED;\n\n    point_to_bytes(pub, x, y);\n    return 0;\n}\n\n/**********************************************************************\n *\n * ECDH\n *\n **********************************************************************/\n\n/*\n * ECDH compute shared secret\n */\nint p256_ecdh_shared_secret(uint8_t secret[32],\n                            const uint8_t priv[32], const uint8_t peer[64])\n{\n    CT_POISON(priv, 32);\n\n    uint32_t s[8], px[8], py[8], x[8], y[8];\n    int ret;\n\n    ret = scalar_from_bytes(s, priv);\n    CT_UNPOISON(&ret, sizeof ret);\n    if (ret != 0) {\n        ret = P256_INVALID_PRIVKEY;\n        goto cleanup;\n    }\n\n    ret = point_from_bytes(px, py, peer);\n    if (ret != 0) {\n        ret = P256_INVALID_PUBKEY;\n        goto cleanup;\n    }\n\n    scalar_mult(x, y, px, py, s);\n\n    m256_to_bytes(secret, x, &p256_p);\n    CT_UNPOISON(secret, 32);\n\ncleanup:\n    zeroize(s, sizeof s);\n    return ret;\n}\n\n/**********************************************************************\n *\n * ECDSA\n *\n * Reference:\n * [SEC1] SEC 1: Elliptic Curve Cryptography, Certicom research, 2009.\n *        http://www.secg.org/sec1-v2.pdf\n **********************************************************************/\n\n/*\n * Reduction mod n of a small number\n *\n * in: x in [0, 2^256)\n * out: x_out = x_in mod n in [0, n)\n */\nstatic void ecdsa_m256_mod_n(uint32_t x[8])\n{\n    uint32_t t[8];\n    uint32_t c = u256_sub(t, x, p256_n.m);\n    u256_cmov(x, t, 1 - c);\n}\n\n/*\n * Import integer mod n (Montgomery domain) from hash\n *\n * in: h = h0, ..., h_hlen\n *     hlen the length of h in bytes\n * out: z = (h0 * 2^l-8 + ... + h_l) * 2^256 mod n\n *      with l = min(32, hlen)\n *\n * Note: in [SEC1] this is step 5 of 4.1.3 (sign) or step 3 or 4.1.4 (verify),\n * with obvious simplications since n's bit-length is a multiple of 8.\n */\nstatic void ecdsa_m256_from_hash(uint32_t z[8],\n                                 const uint8_t *h, size_t hlen)\n{\n    /* convert from h (big-endian) */\n    /* hlen is public data so it's OK to branch on it */\n    if (hlen < 32) {\n        uint8_t p[32];\n        for (unsigned i = 0; i < 32; i++)\n            p[i] = 0;\n        for (unsigned i = 0; i < hlen; i++)\n            p[32 - hlen + i] = h[i];\n        u256_from_bytes(z, p);\n    } else {\n        u256_from_bytes(z, h);\n    }\n\n    /* ensure the result is in [0, n) */\n    ecdsa_m256_mod_n(z);\n\n    /* map to Montgomery domain */\n    m256_prep(z, &p256_n);\n}\n\n/*\n * ECDSA sign\n */\nint p256_ecdsa_sign(uint8_t sig[64], const uint8_t priv[32],\n                    const uint8_t *hash, size_t hlen)\n{\n    CT_POISON(priv, 32);\n\n    /*\n     * Steps and notations from [SEC1] 4.1.3\n     *\n     * Instead of retrying on r == 0 or s == 0, just abort,\n     * as those events have negligible probability.\n     */\n    int ret;\n\n    /* Temporary buffers - the first two are mostly stable, so have names */\n    uint32_t xr[8], k[8], t3[8], t4[8];\n\n    /* 1. Set ephemeral keypair */\n    uint8_t *kb = (uint8_t *) t4;\n    /* kb will be erased by re-using t4 for dU - if we exit before that, we\n     * haven't read the private key yet so we kb isn't sensitive yet */\n    ret = scalar_gen_with_pub(kb, k, xr, t3);   /* xr = x_coord(k * G) */\n    if (ret != 0)\n        return P256_RANDOM_FAILED;\n    m256_prep(k, &p256_n);\n\n    /* 2. Convert xr to an integer */\n    m256_done(xr, &p256_p);\n\n    /* 3. Reduce xr mod n (extra: output it while at it) */\n    ecdsa_m256_mod_n(xr);    /* xr = int(xr) mod n */\n\n    /* xr is public data so it's OK to use a branch */\n    if (u256_diff0(xr) == 0)\n        return P256_RANDOM_FAILED;\n\n    u256_to_bytes(sig, xr);\n\n    m256_prep(xr, &p256_n);\n\n    /* 4. Skipped - we take the hash as an input, not the message */\n\n    /* 5. Derive an integer from the hash */\n    ecdsa_m256_from_hash(t3, hash, hlen);   /* t3 = e */\n\n    /* 6. Compute s = k^-1 * (e + r * dU) */\n\n    /* Note: dU will be erased by re-using t4 for the value of s (public) */\n    ret = scalar_from_bytes(t4, priv);   /* t4 = dU (integer domain) */\n    CT_UNPOISON(&ret, sizeof ret); /* Result of input validation */\n    if (ret != 0)\n        return P256_INVALID_PRIVKEY;\n    m256_prep(t4, &p256_n);         /* t4 = dU (Montgomery domain) */\n\n    m256_inv(k, k, &p256_n);        /* k^-1 */\n    m256_mul(t4, xr, t4, &p256_n);  /* t4 = r * dU */\n    m256_add(t4, t3, t4, &p256_n);  /* t4 = e + r * dU */\n    m256_mul(t4, k, t4, &p256_n);   /* t4 = s = k^-1 * (e + r * dU) */\n    zeroize(k, sizeof k);\n\n    /* 7. Output s (r already outputed at step 3) */\n    CT_UNPOISON(t4, 32);\n    if (u256_diff0(t4) == 0) {\n        /* undo early output of r */\n        u256_to_bytes(sig, t4);\n        return P256_RANDOM_FAILED;\n    }\n    m256_to_bytes(sig + 32, t4, &p256_n);\n\n    return P256_SUCCESS;\n}\n\n/*\n * ECDSA verify\n */\nint p256_ecdsa_verify(const uint8_t sig[64], const uint8_t pub[64],\n                      const uint8_t *hash, size_t hlen)\n{\n    /*\n     * Steps and notations from [SEC1] 4.1.3\n     *\n     * Note: we're using public data only, so branches are OK\n     */\n    int ret;\n\n    /* 1. Validate range of r and s : [1, n-1] */\n    uint32_t r[8], s[8];\n    ret = scalar_from_bytes(r, sig);\n    if (ret != 0)\n        return P256_INVALID_SIGNATURE;\n    ret = scalar_from_bytes(s, sig + 32);\n    if (ret != 0)\n        return P256_INVALID_SIGNATURE;\n\n    /* 2. Skipped - we take the hash as an input, not the message */\n\n    /* 3. Derive an integer from the hash */\n    uint32_t e[8];\n    ecdsa_m256_from_hash(e, hash, hlen);\n\n    /* 4. Compute u1 = e * s^-1 and u2 = r * s^-1 */\n    uint32_t u1[8], u2[8];\n    m256_prep(s, &p256_n);           /* s in Montgomery domain */\n    m256_inv(s, s, &p256_n);         /* s = s^-1 mod n */\n    m256_mul(u1, e, s, &p256_n);     /* u1 = e * s^-1 mod n */\n    m256_done(u1, &p256_n);          /* u1 out of Montgomery domain */\n\n    u256_cmov(u2, r, 1);\n    m256_prep(u2, &p256_n);          /* r in Montgomery domain */\n    m256_mul(u2, u2, s, &p256_n);    /* u2 = r * s^-1 mod n */\n    m256_done(u2, &p256_n);          /* u2 out of Montgomery domain */\n\n    /* 5. Compute R (and re-use (u1, u2) to store its coordinates */\n    uint32_t px[8], py[8];\n    ret = point_from_bytes(px, py, pub);\n    if (ret != 0)\n        return P256_INVALID_PUBKEY;\n\n    scalar_mult(e, s, px, py, u2);      /* (e, s) = R2 = u2 * Qu */\n\n    if (u256_diff0(u1) == 0) {\n        /* u1 out of range for scalar_mult() - just skip it */\n        u256_cmov(u1, e, 1);\n        /* we don't care about the y coordinate */\n    } else {\n        scalar_mult(px, py, p256_gx, p256_gy, u1); /* (px, py) = R1 = u1 * G */\n\n        /* (u1, u2) = R = R1 + R2 */\n        point_add_or_double_leaky(u1, u2, px, py, e, s);\n        /* No need to check if R == 0 here: if that's the case, it will be\n         * caught when comparating rx (which will be 0) to r (which isn't). */\n    }\n\n    /* 6. Convert xR to an integer */\n    m256_done(u1, &p256_p);\n\n    /* 7. Reduce xR mod n */\n    ecdsa_m256_mod_n(u1);\n\n    /* 8. Compare xR mod n to r */\n    uint32_t diff = u256_diff(u1, r);\n    if (diff == 0)\n        return P256_SUCCESS;\n\n    return P256_INVALID_SIGNATURE;\n}\n\n/**********************************************************************\n *\n * Key management utilities\n *\n **********************************************************************/\n\nint p256_validate_pubkey(const uint8_t pub[64])\n{\n    uint32_t x[8], y[8];\n    int ret = point_from_bytes(x, y, pub);\n\n    return ret == 0 ? P256_SUCCESS : P256_INVALID_PUBKEY;\n}\n\nint p256_validate_privkey(const uint8_t priv[32])\n{\n    uint32_t s[8];\n    int ret = scalar_from_bytes(s, priv);\n    zeroize(s, sizeof(s));\n\n    return ret == 0 ? P256_SUCCESS : P256_INVALID_PRIVKEY;\n}\n\nint p256_public_from_private(uint8_t pub[64], const uint8_t priv[32])\n{\n    int ret;\n    uint32_t s[8];\n\n    ret = scalar_from_bytes(s, priv);\n    if (ret != 0)\n        return P256_INVALID_PRIVKEY;\n\n    /* compute and ouput the associated public key */\n    uint32_t x[8], y[8];\n    scalar_mult(x, y, p256_gx, p256_gy, s);\n\n    /* the associated public key is not a secret, the scalar was */\n    CT_UNPOISON(x, 32);\n    CT_UNPOISON(y, 32);\n    zeroize(s, sizeof(s));\n\n    point_to_bytes(pub, x, y);\n    return P256_SUCCESS;\n}\n\n#endif\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/p256-m/p256-m/p256-m.h",
    "content": "/*\n * Interface of curve P-256 (ECDH and ECDSA)\n *\n * Copyright The Mbed TLS Contributors\n * Author: Manuel Pégourié-Gonnard.\n * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef P256_M_H\n#define P256_M_H\n\n#include <stdint.h>\n#include <stddef.h>\n\n/* Status codes */\n#define P256_SUCCESS            0\n#define P256_RANDOM_FAILED      -1\n#define P256_INVALID_PUBKEY     -2\n#define P256_INVALID_PRIVKEY    -3\n#define P256_INVALID_SIGNATURE  -4\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * RNG function - must be provided externally and be cryptographically secure.\n *\n * in: output - must point to a writable buffer of at least output_size bytes.\n *     output_size - the number of random bytes to write to output.\n * out: output is filled with output_size random bytes.\n *      return 0 on success, non-zero on errors.\n */\nextern int p256_generate_random(uint8_t * output, unsigned output_size);\n\n/*\n * ECDH/ECDSA generate key pair\n *\n * [in] draws from p256_generate_random()\n * [out] priv: on success, holds the private key, as a big-endian integer\n * [out] pub: on success, holds the public key, as two big-endian integers\n *\n * return:  P256_SUCCESS on success\n *          P256_RANDOM_FAILED on failure\n */\nint p256_gen_keypair(uint8_t priv[32], uint8_t pub[64]);\n\n/*\n * ECDH compute shared secret\n *\n * [out] secret: on success, holds the shared secret, as a big-endian integer\n * [in] priv: our private key as a big-endian integer\n * [in] pub: the peer's public key, as two big-endian integers\n *\n * return:  P256_SUCCESS on success\n *          P256_INVALID_PRIVKEY if priv is invalid\n *          P256_INVALID_PUBKEY if pub is invalid\n */\nint p256_ecdh_shared_secret(uint8_t secret[32],\n                            const uint8_t priv[32], const uint8_t pub[64]);\n\n/*\n * ECDSA sign\n *\n * [in] draws from p256_generate_random()\n * [out] sig: on success, holds the signature, as two big-endian integers\n * [in] priv: our private key as a big-endian integer\n * [in] hash: the hash of the message to be signed\n * [in] hlen: the size of hash in bytes\n *\n * return:  P256_SUCCESS on success\n *          P256_RANDOM_FAILED on failure\n *          P256_INVALID_PRIVKEY if priv is invalid\n */\nint p256_ecdsa_sign(uint8_t sig[64], const uint8_t priv[32],\n                    const uint8_t *hash, size_t hlen);\n\n/*\n * ECDSA verify\n *\n * [in] sig: the signature to be verified, as two big-endian integers\n * [in] pub: the associated public key, as two big-endian integers\n * [in] hash: the hash of the message that was signed\n * [in] hlen: the size of hash in bytes\n *\n * return:  P256_SUCCESS on success - the signature was verified as valid\n *          P256_INVALID_PUBKEY if pub is invalid\n *          P256_INVALID_SIGNATURE if the signature was found to be invalid\n */\nint p256_ecdsa_verify(const uint8_t sig[64], const uint8_t pub[64],\n                      const uint8_t *hash, size_t hlen);\n\n/*\n * Public key validation\n *\n * Note: you never need to call this function, as all other functions always\n * validate their input; however it's availabe if you want to validate the key\n * without performing an operation.\n *\n * [in] pub: the public key, as two big-endian integers\n *\n * return:  P256_SUCCESS if the key is valid\n *          P256_INVALID_PUBKEY if pub is invalid\n */\nint p256_validate_pubkey(const uint8_t pub[64]);\n\n/*\n * Private key validation\n *\n * Note: you never need to call this function, as all other functions always\n * validate their input; however it's availabe if you want to validate the key\n * without performing an operation.\n *\n * [in] priv: the private key, as a big-endian integer\n *\n * return:  P256_SUCCESS if the key is valid\n *          P256_INVALID_PRIVKEY if priv is invalid\n */\nint p256_validate_privkey(const uint8_t priv[32]);\n\n/*\n * Compute public key from private key\n *\n * [out] pub: the associated public key, as two big-endian integers\n * [in] priv: the private key, as a big-endian integer\n *\n * return:  P256_SUCCESS on success\n *          P256_INVALID_PRIVKEY if priv is invalid\n */\nint p256_public_from_private(uint8_t pub[64], const uint8_t priv[32]);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* P256_M_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/p256-m/p256-m_driver_entrypoints.c",
    "content": "/*\n *  Driver entry points for p256-m\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"mbedtls/platform.h\"\n#include \"p256-m_driver_entrypoints.h\"\n#include \"p256-m/p256-m.h\"\n#include \"psa/crypto.h\"\n#include <stddef.h>\n#include <string.h>\n#include \"psa_crypto_driver_wrappers_no_static.h\"\n\n#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)\n\n/* INFORMATION ON PSA KEY EXPORT FORMATS:\n *\n * PSA exports SECP256R1 keys in two formats:\n * 1. Keypair format: 32 byte string which is just the private key (public key\n *                    can be calculated from the private key)\n * 2. Public Key format: A leading byte 0x04 (indicating uncompressed format),\n *                       followed by the 64 byte public key. This results in a\n *                       total of 65 bytes.\n *\n * p256-m's internal format for private keys matches PSA. Its format for public\n * keys is only 64 bytes: the same as PSA but without the leading byte (0x04).\n * Hence, when passing public keys from PSA to p256-m, the leading byte is\n * removed.\n *\n * Shared secret and signature have the same format between PSA and p256-m.\n */\n#define PSA_PUBKEY_SIZE         65\n#define PSA_PUBKEY_HEADER_BYTE  0x04\n#define P256_PUBKEY_SIZE        64\n#define PRIVKEY_SIZE            32\n#define SHARED_SECRET_SIZE      32\n#define SIGNATURE_SIZE          64\n\n#define CURVE_BITS              256\n\n/* Convert between p256-m and PSA error codes */\nstatic psa_status_t p256_to_psa_error(int ret)\n{\n    switch (ret) {\n        case P256_SUCCESS:\n            return PSA_SUCCESS;\n        case P256_INVALID_PUBKEY:\n        case P256_INVALID_PRIVKEY:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case P256_INVALID_SIGNATURE:\n            return PSA_ERROR_INVALID_SIGNATURE;\n        case P256_RANDOM_FAILED:\n        default:\n            return PSA_ERROR_GENERIC_ERROR;\n    }\n}\n\npsa_status_t p256_transparent_import_key(const psa_key_attributes_t *attributes,\n                             const uint8_t *data,\n                             size_t data_length,\n                             uint8_t *key_buffer,\n                             size_t key_buffer_size,\n                             size_t *key_buffer_length,\n                             size_t *bits)\n{\n    /* Check the key size */\n    if (*bits != 0 && *bits != CURVE_BITS) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    /* Validate the key (and its type and size) */\n    psa_key_type_t type = psa_get_key_type(attributes);\n    if (type == PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)) {\n        if (data_length != PSA_PUBKEY_SIZE) {\n            return *bits == 0 ? PSA_ERROR_NOT_SUPPORTED : PSA_ERROR_INVALID_ARGUMENT;\n        }\n        /* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */\n        if (p256_validate_pubkey(data + 1) != P256_SUCCESS) {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n    } else if (type == PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)) {\n        if (data_length != PRIVKEY_SIZE) {\n            return *bits == 0 ? PSA_ERROR_NOT_SUPPORTED : PSA_ERROR_INVALID_ARGUMENT;\n        }\n        if (p256_validate_privkey(data) != P256_SUCCESS) {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n    } else {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n    *bits = CURVE_BITS;\n\n    /* We only support the export format for input, so just copy. */\n    if (key_buffer_size < data_length) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n    memcpy(key_buffer, data, data_length);\n    *key_buffer_length = data_length;\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t p256_transparent_export_public_key(const psa_key_attributes_t *attributes,\n                                    const uint8_t *key_buffer,\n                                    size_t key_buffer_size,\n                                    uint8_t *data,\n                                    size_t data_size,\n                                    size_t *data_length)\n{\n    /* Is this the right curve? */\n    size_t bits = psa_get_key_bits(attributes);\n    psa_key_type_t type = psa_get_key_type(attributes);\n    if (bits != CURVE_BITS || type != PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    /* Validate sizes, as p256-m expects fixed-size buffers */\n    if (key_buffer_size != PRIVKEY_SIZE) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n    if (data_size < PSA_PUBKEY_SIZE) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n\n    /* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */\n    data[0] = PSA_PUBKEY_HEADER_BYTE;\n    int ret = p256_public_from_private(data + 1, key_buffer);\n    if (ret == P256_SUCCESS) {\n        *data_length = PSA_PUBKEY_SIZE;\n    }\n\n    return p256_to_psa_error(ret);\n}\n\npsa_status_t p256_transparent_generate_key(\n    const psa_key_attributes_t *attributes,\n    uint8_t *key_buffer,\n    size_t key_buffer_size,\n    size_t *key_buffer_length)\n{\n    /* We don't use this argument, but the specification mandates the signature\n     * of driver entry-points. (void) used to avoid compiler warning. */\n    (void) attributes;\n\n    /* Validate sizes, as p256-m expects fixed-size buffers */\n    if (key_buffer_size != PRIVKEY_SIZE) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n\n    /*\n     *  p256-m's keypair generation function outputs both public and private\n     *  keys. Allocate a buffer to which the public key will be written. The\n     *  private key will be written to key_buffer, which is passed to this\n     *  function as an argument. */\n    uint8_t public_key_buffer[P256_PUBKEY_SIZE];\n\n    int ret = p256_gen_keypair(key_buffer, public_key_buffer);\n    if (ret == P256_SUCCESS) {\n        *key_buffer_length = PRIVKEY_SIZE;\n    }\n\n    return p256_to_psa_error(ret);\n}\n\npsa_status_t p256_transparent_key_agreement(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *peer_key,\n    size_t peer_key_length,\n    uint8_t *shared_secret,\n    size_t shared_secret_size,\n    size_t *shared_secret_length)\n{\n    /* We don't use these arguments, but the specification mandates the\n     * sginature of driver entry-points. (void) used to avoid compiler\n     * warning. */\n    (void) attributes;\n    (void) alg;\n\n    /* Validate sizes, as p256-m expects fixed-size buffers */\n    if (key_buffer_size != PRIVKEY_SIZE || peer_key_length != PSA_PUBKEY_SIZE) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n    if (shared_secret_size < SHARED_SECRET_SIZE) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n\n    /* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */\n    const uint8_t *peer_key_p256m = peer_key + 1;\n    int ret = p256_ecdh_shared_secret(shared_secret, key_buffer, peer_key_p256m);\n    if (ret == P256_SUCCESS) {\n        *shared_secret_length = SHARED_SECRET_SIZE;\n    }\n\n    return p256_to_psa_error(ret);\n}\n\npsa_status_t p256_transparent_sign_hash(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *hash,\n    size_t hash_length,\n    uint8_t *signature,\n    size_t signature_size,\n    size_t *signature_length)\n{\n    /* We don't use these arguments, but the specification mandates the\n     * sginature of driver entry-points. (void) used to avoid compiler\n     * warning. */\n    (void) attributes;\n    (void) alg;\n\n    /* Validate sizes, as p256-m expects fixed-size buffers */\n    if (key_buffer_size != PRIVKEY_SIZE) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n    if (signature_size < SIGNATURE_SIZE) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n\n    int ret = p256_ecdsa_sign(signature, key_buffer, hash, hash_length);\n    if (ret == P256_SUCCESS) {\n        *signature_length = SIGNATURE_SIZE;\n    }\n\n    return p256_to_psa_error(ret);\n}\n\n/*  This function expects the key buffer to contain a PSA public key,\n *  as exported by psa_export_public_key() */\nstatic psa_status_t p256_verify_hash_with_public_key(\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    const uint8_t *hash,\n    size_t hash_length,\n    const uint8_t *signature,\n    size_t signature_length)\n{\n    /* Validate sizes, as p256-m expects fixed-size buffers */\n    if (key_buffer_size != PSA_PUBKEY_SIZE || *key_buffer != PSA_PUBKEY_HEADER_BYTE) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n    if (signature_length != SIGNATURE_SIZE) {\n        return PSA_ERROR_INVALID_SIGNATURE;\n    }\n\n    /* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */\n    const uint8_t *public_key_p256m = key_buffer + 1;\n    int ret = p256_ecdsa_verify(signature, public_key_p256m, hash, hash_length);\n\n    return p256_to_psa_error(ret);\n}\n\npsa_status_t p256_transparent_verify_hash(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *hash,\n    size_t hash_length,\n    const uint8_t *signature,\n    size_t signature_length)\n{\n    /* We don't use this argument, but the specification mandates the signature\n     * of driver entry-points. (void) used to avoid compiler warning. */\n    (void) alg;\n\n    psa_status_t status;\n    uint8_t public_key_buffer[PSA_PUBKEY_SIZE];\n    size_t public_key_buffer_size = PSA_PUBKEY_SIZE;\n\n    size_t public_key_length = PSA_PUBKEY_SIZE;\n    /* As p256-m doesn't require dynamic allocation, we want to avoid it in\n     * the entrypoint functions as well. psa_driver_wrapper_export_public_key()\n     * requires size_t*, so we use a pointer to a stack variable. */\n    size_t *public_key_length_ptr = &public_key_length;\n\n    /* The contents of key_buffer may either be the 32 byte private key\n     * (keypair format), or 0x04 followed by the 64 byte public key (public\n     * key format). To ensure the key is in the latter format, the public key\n     * is exported. */\n    status = psa_driver_wrapper_export_public_key(\n        attributes,\n        key_buffer,\n        key_buffer_size,\n        public_key_buffer,\n        public_key_buffer_size,\n        public_key_length_ptr);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = p256_verify_hash_with_public_key(\n        public_key_buffer,\n        public_key_buffer_size,\n        hash,\n        hash_length,\n        signature,\n        signature_length);\n\nexit:\n    return status;\n}\n\n#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */\n"
  },
  {
    "path": "thirdparty/mbedtls/3rdparty/p256-m/p256-m_driver_entrypoints.h",
    "content": "/*\n *   Driver entry points for p256-m\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef P256M_DRIVER_ENTRYPOINTS_H\n#define P256M_DRIVER_ENTRYPOINTS_H\n\n#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)\n#ifndef PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT\n#define PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */\n\n#include \"psa/crypto_types.h\"\n\n/** Import SECP256R1 key.\n *\n * \\param[in]  attributes           The attributes of the key to use for the\n *                                  operation.\n * \\param[in]  data                 The raw key material. For private keys\n *                                  this must be a big-endian integer of 32\n *                                  bytes; for public key this must be an\n *                                  uncompressed ECPoint (65 bytes).\n * \\param[in]  data_length          The size of the raw key material.\n * \\param[out] key_buffer           The buffer to contain the key data in\n *                                  output format upon successful return.\n * \\param[in]  key_buffer_size      Size of the \\p key_buffer buffer in bytes.\n * \\param[out] key_buffer_length    The length of the data written in \\p\n *                                  key_buffer in bytes.\n * \\param[out] bits                 The bitsize of the key.\n *\n * \\retval  #PSA_SUCCESS\n *          Success. Keypair generated and stored in buffer.\n * \\retval  #PSA_ERROR_NOT_SUPPORTED\n *          The input is not supported by this driver (not SECP256R1).\n * \\retval  #PSA_ERROR_INVALID_ARGUMENT\n *          The input is invalid.\n * \\retval  #PSA_ERROR_BUFFER_TOO_SMALL\n *          \\p key_buffer_size is too small.\n */\npsa_status_t p256_transparent_import_key(const psa_key_attributes_t *attributes,\n                             const uint8_t *data,\n                             size_t data_length,\n                             uint8_t *key_buffer,\n                             size_t key_buffer_size,\n                             size_t *key_buffer_length,\n                             size_t *bits);\n\n/** Export SECP256R1 public key, from the private key.\n *\n * \\param[in]  attributes           The attributes of the key to use for the\n *                                  operation.\n * \\param[in]  key_buffer           The private key in the export format.\n * \\param[in]  key_buffer_size      The size of the private key in bytes.\n * \\param[out] data                 The buffer to contain the public key in\n *                                  the export format upon successful return.\n * \\param[in]  data_size            The size of the \\p data buffer in bytes.\n * \\param[out] data_length          The length written to \\p data in bytes.\n *\n * \\retval  #PSA_SUCCESS\n *          Success. Keypair generated and stored in buffer.\n * \\retval  #PSA_ERROR_NOT_SUPPORTED\n *          The input is not supported by this driver (not SECP256R1).\n * \\retval  #PSA_ERROR_INVALID_ARGUMENT\n *          The input is invalid.\n * \\retval  #PSA_ERROR_BUFFER_TOO_SMALL\n *          \\p key_buffer_size is too small.\n */\npsa_status_t p256_transparent_export_public_key(const psa_key_attributes_t *attributes,\n                                    const uint8_t *key_buffer,\n                                    size_t key_buffer_size,\n                                    uint8_t *data,\n                                    size_t data_size,\n                                    size_t *data_length);\n\n/** Generate SECP256R1 ECC Key Pair.\n *  Interface function which calls the p256-m key generation function and\n *  places it in the key buffer provided by the caller (Mbed TLS) in the\n *  correct format. For a SECP256R1 curve this is the 32 bit private key.\n *\n * \\param[in]  attributes           The attributes of the key to use for the\n *                                  operation.\n * \\param[out]  key_buffer          The buffer to contain the key data in\n *                                  output format upon successful return.\n * \\param[in]   key_buffer_size     Size of the \\p key_buffer buffer in bytes.\n * \\param[out]  key_buffer_length   The length of the data written in \\p\n *                                  key_buffer in bytes.\n *\n * \\retval  #PSA_SUCCESS\n *          Success. Keypair generated and stored in buffer.\n * \\retval  #PSA_ERROR_BUFFER_TOO_SMALL\n *          \\p key_buffer_size is too small.\n * \\retval  #PSA_ERROR_GENERIC_ERROR\n *          The internal RNG failed.\n */\npsa_status_t p256_transparent_generate_key(\n    const psa_key_attributes_t *attributes,\n    uint8_t *key_buffer,\n    size_t key_buffer_size,\n    size_t *key_buffer_length);\n\n/** Perform raw key agreement using p256-m's ECDH implementation\n * \\param[in]  attributes           The attributes of the key to use for the\n *                                  operation.\n * \\param[in]  key_buffer           The buffer containing the private key\n *                                  in the format specified by PSA.\n * \\param[in]  key_buffer_size      Size of the \\p key_buffer buffer in bytes.\n * \\param[in]  alg                  A key agreement algorithm that is\n *                                  compatible with the type of the key.\n * \\param[in]  peer_key             The buffer containing the peer's public\n *                                  key in format specified by PSA.\n * \\param[in]  peer_key_length      Size of the \\p peer_key buffer in\n *                                  bytes.\n * \\param[out] shared_secret        The buffer to which the shared secret\n *                                  is to be written.\n * \\param[in]  shared_secret_size   Size of the \\p shared_secret buffer in\n *                                  bytes.\n * \\param[out] shared_secret_length On success, the number of bytes that\n *                                  make up the returned shared secret.\n * \\retval  #PSA_SUCCESS\n *          Success. Shared secret successfully calculated.\n * \\retval  #PSA_ERROR_INVALID_ARGUMENT\n *          The input is invalid.\n * \\retval  #PSA_ERROR_BUFFER_TOO_SMALL\n *          \\p shared_secret_size is too small.\n */\npsa_status_t p256_transparent_key_agreement(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *peer_key,\n    size_t peer_key_length,\n    uint8_t *shared_secret,\n    size_t shared_secret_size,\n    size_t *shared_secret_length);\n\n/** Sign an already-calculated hash with a private key using p256-m's ECDSA\n *  implementation\n * \\param[in]  attributes           The attributes of the key to use for the\n *                                  operation.\n * \\param[in]  key_buffer           The buffer containing the private key\n *                                  in the format specified by PSA.\n * \\param[in]  key_buffer_size      Size of the \\p key_buffer buffer in bytes.\n * \\param[in]  alg                  A signature algorithm that is compatible\n *                                  with the type of the key.\n * \\param[in]  hash                 The hash to sign.\n * \\param[in]  hash_length          Size of the \\p hash buffer in bytes.\n * \\param[out] signature            Buffer where signature is to be written.\n * \\param[in]  signature_size       Size of the \\p signature buffer in bytes.\n * \\param[out] signature_length     On success, the number of bytes\n *                                  that make up the returned signature value.\n *\n * \\retval  #PSA_SUCCESS\n *          Success. Hash was signed successfully.\n * \\retval  #PSA_ERROR_INVALID_ARGUMENT\n *          The input is invalid.\n * \\retval  #PSA_ERROR_BUFFER_TOO_SMALL\n *          \\p signature_size is too small.\n * \\retval  #PSA_ERROR_GENERIC_ERROR\n *          The internal RNG failed.\n */\npsa_status_t p256_transparent_sign_hash(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *hash,\n    size_t hash_length,\n    uint8_t *signature,\n    size_t signature_size,\n    size_t *signature_length);\n\n/** Verify the signature of a hash using a SECP256R1 public key using p256-m's\n *  ECDSA implementation.\n *\n * \\note p256-m expects a 64 byte public key, but the contents of the key\n         buffer may be the 32 byte keypair representation or the 65 byte\n         public key representation. As a result, this function calls\n         psa_driver_wrapper_export_public_key() to ensure the public key\n         can be passed to p256-m.\n *\n * \\param[in]  attributes       The attributes of the key to use for the\n *                              operation.\n *\n * \\param[in]  key_buffer       The buffer containing the key\n *                              in the format specified by PSA.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[in]  alg              A signature algorithm that is compatible with\n *                              the type of the key.\n * \\param[in]  hash             The hash whose signature is to be\n *                              verified.\n * \\param[in]  hash_length      Size of the \\p hash buffer in bytes.\n * \\param[in]  signature        Buffer containing the signature to verify.\n * \\param[in]  signature_length Size of the \\p signature buffer in bytes.\n *\n * \\retval  #PSA_SUCCESS\n *          The signature is valid.\n * \\retval  #PSA_ERROR_INVALID_SIGNATURE\n *          The calculation was performed successfully, but the passed\n *          signature is not a valid signature.\n * \\retval  #PSA_ERROR_INVALID_ARGUMENT\n *          The input is invalid.\n */\npsa_status_t p256_transparent_verify_hash(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *hash,\n    size_t hash_length,\n    const uint8_t *signature,\n    size_t signature_length);\n\n#endif /* P256M_DRIVER_ENTRYPOINTS_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/LICENSE",
    "content": "Mbed TLS files are provided under a dual [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html)\nOR [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) license.\nThis means that users may choose which of these licenses they take the code\nunder.\n\nThe full text of each of these licenses is given below.\n\n\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n\n===============================================================================\n\n\n                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.,\n 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n                            NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License along\n    with this program; if not, write to the Free Software Foundation, Inc.,\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  <signature of Ty Coon>, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.\n"
  },
  {
    "path": "thirdparty/mbedtls/README.md",
    "content": "README for Mbed TLS\n===================\n\nMbed TLS is a C library that implements cryptographic primitives (including the [PSA Cryptography API](#psa-cryptography-api)), X.509 certificate manipulation and the SSL/TLS and DTLS protocols. Its small code footprint makes it suitable for embedded systems.\n\nConfiguration\n-------------\n\nMbed TLS should build out of the box on most systems. Some platform specific options are available in the fully documented configuration file `include/mbedtls/mbedtls_config.h`, which is also the place where features can be selected. This file can be edited manually, or in a more programmatic way using the Python 3 script `scripts/config.py` (use `--help` for usage instructions).\n\nCompiler options can be set using conventional environment variables such as `CC` and `CFLAGS` when using the Make and CMake build system (see below).\n\nWe provide some non-standard configurations focused on specific use cases in the `configs/` directory. You can read more about those in `configs/README.txt`\n\nDocumentation\n-------------\n\nThe main Mbed TLS documentation is available via [ReadTheDocs](https://mbed-tls.readthedocs.io/).\n\nDocumentation for the PSA Cryptography API is available [on GitHub](https://arm-software.github.io/psa-api/crypto/).\n\nTo generate a local copy of the library documentation in HTML format, tailored to your compile-time configuration:\n\n1. Make sure that [Doxygen](http://www.doxygen.nl/) is installed.\n1. Run `make apidoc`.\n1. Browse `apidoc/index.html` or `apidoc/modules.html`.\n\nFor other sources of documentation, see the [SUPPORT](SUPPORT.md) document.\n\nCompiling\n---------\n\nThere are currently three active build systems used within Mbed TLS releases:\n\n-   GNU Make\n-   CMake\n-   Microsoft Visual Studio\n\nThe main systems used for development are CMake and GNU Make. Those systems are always complete and up-to-date. The others should reflect all changes present in the CMake and Make build system, although features may not be ported there automatically.\n\nThe Make and CMake build systems create three libraries: libmbedcrypto, libmbedx509, and libmbedtls. Note that libmbedtls depends on libmbedx509 and libmbedcrypto, and libmbedx509 depends on libmbedcrypto. As a result, some linkers will expect flags to be in a specific order, for example the GNU linker wants `-lmbedtls -lmbedx509 -lmbedcrypto`.\n\n### Tool versions\n\nYou need the following tools to build the library with the provided makefiles:\n\n* GNU Make 3.82 or a build tool that CMake supports.\n* A C99 toolchain (compiler, linker, archiver). We actively test with GCC 5.4, Clang 3.8, Arm Compiler 6, IAR 8 and Visual Studio 2017. More recent versions should work. Slightly older versions may work.\n* Python 3.8 to generate the test code. Python is also needed to integrate PSA drivers and to build the development branch (see next section).\n* Perl to run the tests, and to generate some source files in the development branch.\n* CMake 3.10.2 or later (if using CMake).\n* Microsoft Visual Studio 2017 or later (if using Visual Studio).\n* Doxygen 1.8.11 or later (if building the documentation; slightly older versions should work).\n\n### Git usage\n\nThe `development` branch and the `mbedtls-3.6` long-term support branch of Mbed TLS use a [Git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules#_cloning_submodules) ([framework](https://github.com/Mbed-TLS/mbedtls-framework)). This is not needed to merely compile the library at a release tag. This is not needed to consume a release archive (zip or tar).\n\n### Generated source files in the development branch\n\nThe source code of Mbed TLS includes some files that are automatically generated by scripts and whose content depends only on the Mbed TLS source, not on the platform or on the library configuration. These files are not included in the development branch of Mbed TLS, but the generated files are included in official releases. This section explains how to generate the missing files in the development branch.\n\nThe following tools are required:\n\n* Perl, for some library source files and for Visual Studio build files.\n* Python 3.8 and some Python packages, for some library source files, sample programs and test data. To install the necessary packages, run:\n    ```\n    python3 -m pip install --user -r scripts/basic.requirements.txt\n    ```\n    Depending on your Python installation, you may need to invoke `python` instead of `python3`. To install the packages system-wide, omit the `--user` option.\n* A C compiler for the host platform, for some test data.\n\nThe scripts that generate the configuration-independent files will look for a host C compiler in the following places (in order of preference):\n\n1. The `HOSTCC` environment variable. This can be used if `CC` is pointing to a cross-compiler.\n2. The `CC` environment variable.\n3. An executable called `cc` in the current path.\n\nNote: If you have multiple toolchains installed, it is recommended to set `CC` or `HOSTCC` to the intended host compiler before generating the files.\n\nAny of the following methods are available to generate the configuration-independent files:\n\n* If not cross-compiling, running `make` with any target, or just `make`, will automatically generate required files.\n* On non-Windows systems, when not cross-compiling, CMake will generate the required files automatically.\n* Run `make generated_files` to generate all the configuration-independent files.\n* On Unix/POSIX systems, run `tests/scripts/check-generated-files.sh -u` to generate all the configuration-independent files.\n* On Windows, run `scripts\\make_generated_files.bat` to generate all the configuration-independent files.\n\n### Make\n\nWe require GNU Make. To build the library and the sample programs, GNU Make and a C compiler are sufficient. Some of the more advanced build targets require some Unix/Linux tools.\n\nWe intentionally only use a minimum of functionality in the makefiles in order to keep them as simple and independent of different toolchains as possible, to allow users to more easily move between different platforms. Users who need more features are recommended to use CMake.\n\nIn order to build from the source code using GNU Make, just enter at the command line:\n\n    make\n\nIn order to run the tests, enter:\n\n    make check\n\nThe tests need Python to be built and Perl to be run. If you don't have one of them installed, you can skip building the tests with:\n\n    make no_test\n\nYou'll still be able to run a much smaller set of tests with:\n\n    programs/test/selftest\n\nIn order to build for a Windows platform, you should use `WINDOWS_BUILD=1` if the target is Windows but the build environment is Unix-like (for instance when cross-compiling, or compiling from an MSYS shell), and `WINDOWS=1` if the build environment is a Windows shell (for instance using mingw32-make) (in that case some targets will not be available).\n\nSetting the variable `SHARED` in your environment will build shared libraries in addition to the static libraries. Setting `DEBUG` gives you a debug build. You can override `CFLAGS` and `LDFLAGS` by setting them in your environment or on the make command line; compiler warning options may be overridden separately using `WARNING_CFLAGS`. Some directory-specific options (for example, `-I` directives) are still preserved.\n\nPlease note that setting `CFLAGS` overrides its default value of `-O2` and setting `WARNING_CFLAGS` overrides its default value (starting with `-Wall -Wextra`), so if you just want to add some warning options to the default ones, you can do so by setting `CFLAGS=-O2 -Werror` for example. Setting `WARNING_CFLAGS` is useful when you want to get rid of its default content (for example because your compiler doesn't accept `-Wall` as an option). Directory-specific options cannot be overridden from the command line.\n\nDepending on your platform, you might run into some issues. Please check the Makefiles in `library/`, `programs/` and `tests/` for options to manually add or remove for specific platforms. You can also check [the Mbed TLS Knowledge Base](https://mbed-tls.readthedocs.io/en/latest/kb/) for articles on your platform or issue.\n\nIn case you find that you need to do something else as well, please let us know what, so we can add it to the [Mbed TLS Knowledge Base](https://mbed-tls.readthedocs.io/en/latest/kb/).\n\n### CMake\n\nIn order to build the source using CMake in a separate directory (recommended), just enter at the command line:\n\n    mkdir /path/to/build_dir && cd /path/to/build_dir\n    cmake /path/to/mbedtls_source\n    cmake --build .\n\nIn order to run the tests, enter:\n\n    ctest\n\nThe test suites need Python to be built and Perl to be executed. If you don't have one of these installed, you'll want to disable the test suites with:\n\n    cmake -DENABLE_TESTING=Off /path/to/mbedtls_source\n\nIf you disabled the test suites, but kept the programs enabled, you can still run a much smaller set of tests with:\n\n    programs/test/selftest\n\nTo configure CMake for building shared libraries, use:\n\n    cmake -DUSE_SHARED_MBEDTLS_LIBRARY=On /path/to/mbedtls_source\n\nThere are many different build modes available within the CMake buildsystem. Most of them are available for gcc and clang, though some are compiler-specific:\n\n-   `Release`. This generates the default code without any unnecessary information in the binary files.\n-   `Debug`. This generates debug information and disables optimization of the code.\n-   `Coverage`. This generates code coverage information in addition to debug information.\n-   `ASan`. This instruments the code with AddressSanitizer to check for memory errors. (This includes LeakSanitizer, with recent version of gcc and clang.) (With recent version of clang, this mode also instruments the code with UndefinedSanitizer to check for undefined behaviour.)\n-   `ASanDbg`. Same as ASan but slower, with debug information and better stack traces.\n-   `MemSan`. This instruments the code with MemorySanitizer to check for uninitialised memory reads. Experimental, needs recent clang on Linux/x86\\_64.\n-   `MemSanDbg`. Same as MemSan but slower, with debug information, better stack traces and origin tracking.\n-   `Check`. This activates the compiler warnings that depend on optimization and treats all warnings as errors.\n\nSwitching build modes in CMake is simple. For debug mode, enter at the command line:\n\n    cmake -D CMAKE_BUILD_TYPE=Debug /path/to/mbedtls_source\n\nTo list other available CMake options, use:\n\n    cmake -LH\n\nNote that, with CMake, you can't adjust the compiler or its flags after the\ninitial invocation of cmake. This means that `CC=your_cc make` and `make\nCC=your_cc` will *not* work (similarly with `CFLAGS` and other variables).\nThese variables need to be adjusted when invoking cmake for the first time,\nfor example:\n\n    CC=your_cc cmake /path/to/mbedtls_source\n\nIf you already invoked cmake and want to change those settings, you need to\nremove the build directory and create it again.\n\nNote that it is possible to build in-place; this will however overwrite the\nprovided Makefiles (see `scripts/tmp_ignore_makefiles.sh` if you want to\nprevent `git status` from showing them as modified). In order to do so, from\nthe Mbed TLS source directory, use:\n\n    cmake .\n    make\n\nIf you want to change `CC` or `CFLAGS` afterwards, you will need to remove the\nCMake cache. This can be done with the following command using GNU find:\n\n    find . -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} +\n\nYou can now make the desired change:\n\n    CC=your_cc cmake .\n    make\n\nRegarding variables, also note that if you set CFLAGS when invoking cmake,\nyour value of CFLAGS doesn't override the content provided by cmake (depending\non the build mode as seen above), it's merely prepended to it.\n\n#### Consuming Mbed TLS\n\nMbed TLS provides a package config file for consumption as a dependency in other\nCMake projects. You can include Mbed TLS's CMake targets yourself with:\n\n    find_package(MbedTLS)\n\nIf prompted, set `MbedTLS_DIR` to `${YOUR_MBEDTLS_INSTALL_DIR}/cmake`. This\ncreates the following targets:\n\n- `MbedTLS::mbedcrypto` (Crypto library)\n- `MbedTLS::mbedtls` (TLS library)\n- `MbedTLS::mbedx509` (X509 library)\n\nYou can then use these directly through `target_link_libraries()`:\n\n    add_executable(xyz)\n\n    target_link_libraries(xyz\n        PUBLIC MbedTLS::mbedtls\n               MbedTLS::mbedcrypto\n               MbedTLS::mbedx509)\n\nThis will link the Mbed TLS libraries to your library or application, and add\nits include directories to your target (transitively, in the case of `PUBLIC` or\n`INTERFACE` link libraries).\n\n#### Mbed TLS as a subproject\n\nMbed TLS supports being built as a CMake subproject. One can\nuse `add_subdirectory()` from a parent CMake project to include Mbed TLS as a\nsubproject.\n\n### Microsoft Visual Studio\n\nThe build files for Microsoft Visual Studio are generated for Visual Studio 2017.\n\nThe solution file `mbedTLS.sln` contains all the basic projects needed to build the library and all the programs. The files in tests are not generated and compiled, as these need Python and perl environments as well. However, the selftest program in `programs/test/` is still available.\n\nIn the development branch of Mbed TLS, the Visual Studio solution files need to be generated first as described in [“Generated source files in the development branch”](#generated-source-files-in-the-development-branch).\n\nExample programs\n----------------\n\nWe've included example programs for a lot of different features and uses in [`programs/`](programs/README.md).\nPlease note that the goal of these sample programs is to demonstrate specific features of the library, and the code may need to be adapted to build a real-world application.\n\nTests\n-----\n\nMbed TLS includes an elaborate test suite in `tests/` that initially requires Python to generate the tests files (e.g. `test\\_suite\\_mpi.c`). These files are generated from a `function file` (e.g. `suites/test\\_suite\\_mpi.function`) and a `data file` (e.g. `suites/test\\_suite\\_mpi.data`). The `function file` contains the test functions. The `data file` contains the test cases, specified as parameters that will be passed to the test function.\n\nFor machines with a Unix shell and OpenSSL (and optionally GnuTLS) installed, additional test scripts are available:\n\n-   `tests/ssl-opt.sh` runs integration tests for various TLS options (renegotiation, resumption, etc.) and tests interoperability of these options with other implementations.\n-   `tests/compat.sh` tests interoperability of every ciphersuite with other implementations.\n-   `tests/scripts/test-ref-configs.pl` test builds in various reduced configurations.\n-   `tests/scripts/depends.py` test builds in configurations with a single curve, key exchange, hash, cipher, or pkalg on.\n-   `tests/scripts/all.sh` runs a combination of the above tests, plus some more, with various build options (such as ASan, full `mbedtls_config.h`, etc).\n\nInstead of manually installing the required versions of all tools required for testing, it is possible to use the Docker images from our CI systems, as explained in [our testing infrastructure repository](https://github.com/Mbed-TLS/mbedtls-test/blob/main/README.md#quick-start).\n\nPorting Mbed TLS\n----------------\n\nMbed TLS can be ported to many different architectures, OS's and platforms. Before starting a port, you may find the following Knowledge Base articles useful:\n\n-   [Porting Mbed TLS to a new environment or OS](https://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS/)\n-   [What external dependencies does Mbed TLS rely on?](https://mbed-tls.readthedocs.io/en/latest/kb/development/what-external-dependencies-does-mbedtls-rely-on/)\n-   [How do I configure Mbed TLS](https://mbed-tls.readthedocs.io/en/latest/kb/compiling-and-building/how-do-i-configure-mbedtls/)\n\nMbed TLS is mostly written in portable C99; however, it has a few platform requirements that go beyond the standard, but are met by most modern architectures:\n\n- Bytes must be 8 bits.\n- All-bits-zero must be a valid representation of a null pointer.\n- Signed integers must be represented using two's complement.\n- `int` and `size_t` must be at least 32 bits wide.\n- The types `uint8_t`, `uint16_t`, `uint32_t` and their signed equivalents must be available.\n- Mixed-endian platforms are not supported.\n- SIZE_MAX must be at least as big as INT_MAX and UINT_MAX.\n\nPSA cryptography API\n--------------------\n\n### PSA API\n\nArm's [Platform Security Architecture (PSA)](https://developer.arm.com/architectures/security-architectures/platform-security-architecture) is a holistic set of threat models, security analyses, hardware and firmware architecture specifications, and an open source firmware reference implementation. PSA provides a recipe, based on industry best practice, that allows security to be consistently designed in, at both a hardware and firmware level.\n\nThe [PSA cryptography API](https://arm-software.github.io/psa-api/crypto/) provides access to a set of cryptographic primitives. It has a dual purpose. First, it can be used in a PSA-compliant platform to build services, such as secure boot, secure storage and secure communication. Second, it can also be used independently of other PSA components on any platform.\n\nThe design goals of the PSA cryptography API include:\n\n* The API distinguishes caller memory from internal memory, which allows the library to be implemented in an isolated space for additional security. Library calls can be implemented as direct function calls if isolation is not desired, and as remote procedure calls if isolation is desired.\n* The structure of internal data is hidden to the application, which allows substituting alternative implementations at build time or run time, for example, in order to take advantage of hardware accelerators.\n* All access to the keys happens through key identifiers, which allows support for external cryptoprocessors that is transparent to applications.\n* The interface to algorithms is generic, favoring algorithm agility.\n* The interface is designed to be easy to use and hard to accidentally misuse.\n\nArm welcomes feedback on the design of the API. If you think something could be improved, please open an issue on our Github repository. Alternatively, if you prefer to provide your feedback privately, please email us at [`mbed-crypto@arm.com`](mailto:mbed-crypto@arm.com). All feedback received by email is treated confidentially.\n\n### PSA implementation in Mbed TLS\n\nMbed TLS includes an implementation of the PSA Cryptography API. It covers most, but not all algorithms.\n\nThe X.509 and TLS code can use PSA cryptography for most operations. To enable this support, activate the compilation option `MBEDTLS_USE_PSA_CRYPTO` in `mbedtls_config.h`. Note that TLS 1.3 uses PSA cryptography for most operations regardless of this option. See `docs/use-psa-crypto.md` for details.\n\n### PSA drivers\n\nMbed TLS supports drivers for cryptographic accelerators, secure elements and random generators. This is work in progress. Please note that the driver interfaces are not fully stable yet and may change without notice. We intend to preserve backward compatibility for application code (using the PSA Crypto API), but the code of the drivers may have to change in future minor releases of Mbed TLS.\n\nPlease see the [PSA driver example and guide](docs/psa-driver-example-and-guide.md) for information on writing a driver.\n\nWhen using drivers, you will generally want to enable two compilation options (see the reference manual for more information):\n\n* `MBEDTLS_USE_PSA_CRYPTO` is necessary so that the X.509 and TLS code calls the PSA drivers rather than the built-in software implementation.\n* `MBEDTLS_PSA_CRYPTO_CONFIG` allows you to enable PSA cryptographic mechanisms without including the code of the corresponding software implementation. This is not yet supported for all mechanisms.\n\nLicense\n-------\n\nUnless specifically indicated otherwise in a file, Mbed TLS files are provided under a dual [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) OR [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) license. See the [LICENSE](LICENSE) file for the full text of these licenses, and [the 'License and Copyright' section in the contributing guidelines](CONTRIBUTING.md#License-and-Copyright) for more information.\n\n### Third-party code included in Mbed TLS\n\nThis project contains code from other projects. This code is located within the `3rdparty/` directory. The original license text is included within project subdirectories, where it differs from the normal Mbed TLS license, and/or in source files. The projects are listed below:\n\n* `3rdparty/everest/`: Files stem from [Project Everest](https://project-everest.github.io/) and are distributed under the Apache 2.0 license.\n* `3rdparty/p256-m/p256-m/`: Files have been taken from the [p256-m](https://github.com/mpg/p256-m) repository. The code in the original repository is distributed under the Apache 2.0 license. It is distributed in Mbed TLS under a dual Apache-2.0 OR GPL-2.0-or-later license with permission from the author.\n\nContributing\n------------\n\nWe gratefully accept bug reports and contributions from the community. Please see the [contributing guidelines](CONTRIBUTING.md) for details on how to do this.\n\nContact\n-------\n\n* To report a security vulnerability in Mbed TLS, please email <mbed-tls-security@lists.trustedfirmware.org>. For more information, see [`SECURITY.md`](SECURITY.md).\n* To report a bug or request a feature in Mbed TLS, please [file an issue on GitHub](https://github.com/Mbed-TLS/mbedtls/issues/new/choose).\n* Please see [`SUPPORT.md`](SUPPORT.md) for other channels for discussion and support about Mbed TLS.\n"
  },
  {
    "path": "thirdparty/mbedtls/fix.md",
    "content": "To update this, change the version/branch in `thirdparty/mbedtls/update.vsh`,\nthen run `./v thirdparty/mbedtls/update.vsh` .\n\nThe patch containing the local changes, that needs to be applied is in:\n`thirdparty/mbedtls/mbedtls.patch` . It may need changes for the new version too.\n\nBTW, you can generate a new patch by `diff -ur mbedtls.orig mbedtls > mbedtls.patch`\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/aes.h",
    "content": "/**\n * \\file aes.h\n *\n * \\brief   This file contains AES definitions and functions.\n *\n *          The Advanced Encryption Standard (AES) specifies a FIPS-approved\n *          cryptographic algorithm that can be used to protect electronic\n *          data.\n *\n *          The AES algorithm is a symmetric block cipher that can\n *          encrypt and decrypt information. For more information, see\n *          <em>FIPS Publication 197: Advanced Encryption Standard</em> and\n *          <em>ISO/IEC 18033-2:2006: Information technology -- Security\n *          techniques -- Encryption algorithms -- Part 2: Asymmetric\n *          ciphers</em>.\n *\n *          The AES-XTS block mode is standardized by NIST SP 800-38E\n *          <https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38e.pdf>\n *          and described in detail by IEEE P1619\n *          <https://ieeexplore.ieee.org/servlet/opac?punumber=4375278>.\n */\n\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_AES_H\n#define MBEDTLS_AES_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n/* padlock.c and aesni.c rely on these values! */\n#define MBEDTLS_AES_ENCRYPT     1 /**< AES encryption. */\n#define MBEDTLS_AES_DECRYPT     0 /**< AES decryption. */\n\n/* Error codes in range 0x0020-0x0022 */\n/** Invalid key length. */\n#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH                -0x0020\n/** Invalid data input length. */\n#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH              -0x0022\n\n/* Error codes in range 0x0021-0x0025 */\n/** Invalid input data. */\n#define MBEDTLS_ERR_AES_BAD_INPUT_DATA                    -0x0021\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_AES_ALT)\n// Regular implementation\n//\n\n/**\n * \\brief The AES context-type definition.\n */\ntypedef struct mbedtls_aes_context {\n    int MBEDTLS_PRIVATE(nr);                     /*!< The number of rounds. */\n    size_t MBEDTLS_PRIVATE(rk_offset);           /*!< The offset in array elements to AES\n                                                    round keys in the buffer. */\n#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) && !defined(MBEDTLS_PADLOCK_C)\n    uint32_t MBEDTLS_PRIVATE(buf)[44];           /*!< Aligned data buffer to hold\n                                                    10 round keys for 128-bit case. */\n#else\n    uint32_t MBEDTLS_PRIVATE(buf)[68];           /*!< Unaligned data buffer. This buffer can\n                                                    hold 32 extra Bytes, which can be used for\n                                                    one of the following purposes:\n                                                    <ul><li>Alignment if VIA padlock is\n                                                    used.</li>\n                                                    <li>Simplifying key expansion in the 256-bit\n                                                    case by generating an extra round key.\n                                                    </li></ul> */\n#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH && !MBEDTLS_PADLOCK_C */\n}\nmbedtls_aes_context;\n\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n/**\n * \\brief The AES XTS context-type definition.\n */\ntypedef struct mbedtls_aes_xts_context {\n    mbedtls_aes_context MBEDTLS_PRIVATE(crypt); /*!< The AES context to use for AES block\n                                                   encryption or decryption. */\n    mbedtls_aes_context MBEDTLS_PRIVATE(tweak); /*!< The AES context used for tweak\n                                                   computation. */\n} mbedtls_aes_xts_context;\n#endif /* MBEDTLS_CIPHER_MODE_XTS */\n\n#else  /* MBEDTLS_AES_ALT */\n#include \"aes_alt.h\"\n#endif /* MBEDTLS_AES_ALT */\n\n/**\n * \\brief          This function initializes the specified AES context.\n *\n *                 It must be the first API called before using\n *                 the context.\n *\n * \\param ctx      The AES context to initialize. This must not be \\c NULL.\n */\nvoid mbedtls_aes_init(mbedtls_aes_context *ctx);\n\n/**\n * \\brief          This function releases and clears the specified AES context.\n *\n * \\param ctx      The AES context to clear.\n *                 If this is \\c NULL, this function does nothing.\n *                 Otherwise, the context must have been at least initialized.\n */\nvoid mbedtls_aes_free(mbedtls_aes_context *ctx);\n\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n/**\n * \\brief          This function initializes the specified AES XTS context.\n *\n *                 It must be the first API called before using\n *                 the context.\n *\n * \\param ctx      The AES XTS context to initialize. This must not be \\c NULL.\n */\nvoid mbedtls_aes_xts_init(mbedtls_aes_xts_context *ctx);\n\n/**\n * \\brief          This function releases and clears the specified AES XTS context.\n *\n * \\param ctx      The AES XTS context to clear.\n *                 If this is \\c NULL, this function does nothing.\n *                 Otherwise, the context must have been at least initialized.\n */\nvoid mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx);\n#endif /* MBEDTLS_CIPHER_MODE_XTS */\n\n/**\n * \\brief          This function sets the encryption key.\n *\n * \\param ctx      The AES context to which the key should be bound.\n *                 It must be initialized.\n * \\param key      The encryption key.\n *                 This must be a readable buffer of size \\p keybits bits.\n * \\param keybits  The size of data passed in bits. Valid options are:\n *                 <ul><li>128 bits</li>\n *                 <li>192 bits</li>\n *                 <li>256 bits</li></ul>\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,\n                           unsigned int keybits);\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n/**\n * \\brief          This function sets the decryption key.\n *\n * \\param ctx      The AES context to which the key should be bound.\n *                 It must be initialized.\n * \\param key      The decryption key.\n *                 This must be a readable buffer of size \\p keybits bits.\n * \\param keybits  The size of data passed. Valid options are:\n *                 <ul><li>128 bits</li>\n *                 <li>192 bits</li>\n *                 <li>256 bits</li></ul>\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,\n                           unsigned int keybits);\n#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */\n\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n/**\n * \\brief          This function prepares an XTS context for encryption and\n *                 sets the encryption key.\n *\n * \\param ctx      The AES XTS context to which the key should be bound.\n *                 It must be initialized.\n * \\param key      The encryption key. This is comprised of the XTS key1\n *                 concatenated with the XTS key2.\n *                 This must be a readable buffer of size \\p keybits bits.\n * \\param keybits  The size of \\p key passed in bits. Valid options are:\n *                 <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>\n *                 <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context *ctx,\n                               const unsigned char *key,\n                               unsigned int keybits);\n\n/**\n * \\brief          This function prepares an XTS context for decryption and\n *                 sets the decryption key.\n *\n * \\param ctx      The AES XTS context to which the key should be bound.\n *                 It must be initialized.\n * \\param key      The decryption key. This is comprised of the XTS key1\n *                 concatenated with the XTS key2.\n *                 This must be a readable buffer of size \\p keybits bits.\n * \\param keybits  The size of \\p key passed in bits. Valid options are:\n *                 <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>\n *                 <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context *ctx,\n                               const unsigned char *key,\n                               unsigned int keybits);\n#endif /* MBEDTLS_CIPHER_MODE_XTS */\n\n/**\n * \\brief          This function performs an AES single-block encryption or\n *                 decryption operation.\n *\n *                 It performs the operation defined in the \\p mode parameter\n *                 (encrypt or decrypt), on the input data buffer defined in\n *                 the \\p input parameter.\n *\n *                 mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or\n *                 mbedtls_aes_setkey_dec() must be called before the first\n *                 call to this API with the same context.\n *\n * \\param ctx      The AES context to use for encryption or decryption.\n *                 It must be initialized and bound to a key.\n * \\param mode     The AES operation: #MBEDTLS_AES_ENCRYPT or\n *                 #MBEDTLS_AES_DECRYPT.\n * \\param input    The buffer holding the input data.\n *                 It must be readable and at least \\c 16 Bytes long.\n * \\param output   The buffer where the output data will be written.\n *                 It must be writeable and at least \\c 16 Bytes long.\n\n * \\return         \\c 0 on success.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx,\n                          int mode,\n                          const unsigned char input[16],\n                          unsigned char output[16]);\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n/**\n * \\brief  This function performs an AES-CBC encryption or decryption operation\n *         on full blocks.\n *\n *         It performs the operation defined in the \\p mode\n *         parameter (encrypt/decrypt), on the input data buffer defined in\n *         the \\p input parameter.\n *\n *         It can be called as many times as needed, until all the input\n *         data is processed. mbedtls_aes_init(), and either\n *         mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called\n *         before the first call to this API with the same context.\n *\n * \\note   This function operates on full blocks, that is, the input size\n *         must be a multiple of the AES block size of \\c 16 Bytes.\n *\n * \\note   Upon exit, the content of the IV is updated so that you can\n *         call the same function again on the next\n *         block(s) of data and get the same result as if it was\n *         encrypted in one call. This allows a \"streaming\" usage.\n *         If you need to retain the contents of the IV, you should\n *         either save it manually or use the cipher module instead.\n *\n *\n * \\param ctx      The AES context to use for encryption or decryption.\n *                 It must be initialized and bound to a key.\n * \\param mode     The AES operation: #MBEDTLS_AES_ENCRYPT or\n *                 #MBEDTLS_AES_DECRYPT.\n * \\param length   The length of the input data in Bytes. This must be a\n *                 multiple of the block size (\\c 16 Bytes).\n * \\param iv       Initialization vector (updated after use).\n *                 It must be a readable and writeable buffer of \\c 16 Bytes.\n * \\param input    The buffer holding the input data.\n *                 It must be readable and of size \\p length Bytes.\n * \\param output   The buffer holding the output data.\n *                 It must be writeable and of size \\p length Bytes.\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH\n *                 on failure.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx,\n                          int mode,\n                          size_t length,\n                          unsigned char iv[16],\n                          const unsigned char *input,\n                          unsigned char *output);\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n/**\n * \\brief      This function performs an AES-XTS encryption or decryption\n *             operation for an entire XTS data unit.\n *\n *             AES-XTS encrypts or decrypts blocks based on their location as\n *             defined by a data unit number. The data unit number must be\n *             provided by \\p data_unit.\n *\n *             NIST SP 800-38E limits the maximum size of a data unit to 2^20\n *             AES blocks. If the data unit is larger than this, this function\n *             returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH.\n *\n * \\param ctx          The AES XTS context to use for AES XTS operations.\n *                     It must be initialized and bound to a key.\n * \\param mode         The AES operation: #MBEDTLS_AES_ENCRYPT or\n *                     #MBEDTLS_AES_DECRYPT.\n * \\param length       The length of a data unit in Bytes. This can be any\n *                     length between 16 bytes and 2^24 bytes inclusive\n *                     (between 1 and 2^20 block cipher blocks).\n * \\param data_unit    The address of the data unit encoded as an array of 16\n *                     bytes in little-endian format. For disk encryption, this\n *                     is typically the index of the block device sector that\n *                     contains the data.\n * \\param input        The buffer holding the input data (which is an entire\n *                     data unit). This function reads \\p length Bytes from \\p\n *                     input.\n * \\param output       The buffer holding the output data (which is an entire\n *                     data unit). This function writes \\p length Bytes to \\p\n *                     output.\n *\n * \\return             \\c 0 on success.\n * \\return             #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \\p length is\n *                     smaller than an AES block in size (16 Bytes) or if \\p\n *                     length is larger than 2^20 blocks (16 MiB).\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx,\n                          int mode,\n                          size_t length,\n                          const unsigned char data_unit[16],\n                          const unsigned char *input,\n                          unsigned char *output);\n#endif /* MBEDTLS_CIPHER_MODE_XTS */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n/**\n * \\brief This function performs an AES-CFB128 encryption or decryption\n *        operation.\n *\n *        It performs the operation defined in the \\p mode\n *        parameter (encrypt or decrypt), on the input data buffer\n *        defined in the \\p input parameter.\n *\n *        For CFB, you must set up the context with mbedtls_aes_setkey_enc(),\n *        regardless of whether you are performing an encryption or decryption\n *        operation, that is, regardless of the \\p mode parameter. This is\n *        because CFB mode uses the same key schedule for encryption and\n *        decryption.\n *\n * \\note  Upon exit, the content of the IV is updated so that you can\n *        call the same function again on the next\n *        block(s) of data and get the same result as if it was\n *        encrypted in one call. This allows a \"streaming\" usage.\n *        If you need to retain the contents of the\n *        IV, you must either save it manually or use the cipher\n *        module instead.\n *\n *\n * \\param ctx      The AES context to use for encryption or decryption.\n *                 It must be initialized and bound to a key.\n * \\param mode     The AES operation: #MBEDTLS_AES_ENCRYPT or\n *                 #MBEDTLS_AES_DECRYPT.\n * \\param length   The length of the input data in Bytes.\n * \\param iv_off   The offset in IV (updated after use).\n *                 It must point to a valid \\c size_t.\n * \\param iv       The initialization vector (updated after use).\n *                 It must be a readable and writeable buffer of \\c 16 Bytes.\n * \\param input    The buffer holding the input data.\n *                 It must be readable and of size \\p length Bytes.\n * \\param output   The buffer holding the output data.\n *                 It must be writeable and of size \\p length Bytes.\n *\n * \\return         \\c 0 on success.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_aes_crypt_cfb128(mbedtls_aes_context *ctx,\n                             int mode,\n                             size_t length,\n                             size_t *iv_off,\n                             unsigned char iv[16],\n                             const unsigned char *input,\n                             unsigned char *output);\n\n/**\n * \\brief This function performs an AES-CFB8 encryption or decryption\n *        operation.\n *\n *        It performs the operation defined in the \\p mode\n *        parameter (encrypt/decrypt), on the input data buffer defined\n *        in the \\p input parameter.\n *\n *        Due to the nature of CFB, you must use the same key schedule for\n *        both encryption and decryption operations. Therefore, you must\n *        use the context initialized with mbedtls_aes_setkey_enc() for\n *        both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT.\n *\n * \\note  Upon exit, the content of the IV is updated so that you can\n *        call the same function again on the next\n *        block(s) of data and get the same result as if it was\n *        encrypted in one call. This allows a \"streaming\" usage.\n *        If you need to retain the contents of the\n *        IV, you should either save it manually or use the cipher\n *        module instead.\n *\n *\n * \\param ctx      The AES context to use for encryption or decryption.\n *                 It must be initialized and bound to a key.\n * \\param mode     The AES operation: #MBEDTLS_AES_ENCRYPT or\n *                 #MBEDTLS_AES_DECRYPT\n * \\param length   The length of the input data.\n * \\param iv       The initialization vector (updated after use).\n *                 It must be a readable and writeable buffer of \\c 16 Bytes.\n * \\param input    The buffer holding the input data.\n *                 It must be readable and of size \\p length Bytes.\n * \\param output   The buffer holding the output data.\n *                 It must be writeable and of size \\p length Bytes.\n *\n * \\return         \\c 0 on success.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_aes_crypt_cfb8(mbedtls_aes_context *ctx,\n                           int mode,\n                           size_t length,\n                           unsigned char iv[16],\n                           const unsigned char *input,\n                           unsigned char *output);\n#endif /*MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n/**\n * \\brief       This function performs an AES-OFB (Output Feedback Mode)\n *              encryption or decryption operation.\n *\n *              For OFB, you must set up the context with\n *              mbedtls_aes_setkey_enc(), regardless of whether you are\n *              performing an encryption or decryption operation. This is\n *              because OFB mode uses the same key schedule for encryption and\n *              decryption.\n *\n *              The OFB operation is identical for encryption or decryption,\n *              therefore no operation mode needs to be specified.\n *\n * \\note        Upon exit, the content of iv, the Initialisation Vector, is\n *              updated so that you can call the same function again on the next\n *              block(s) of data and get the same result as if it was encrypted\n *              in one call. This allows a \"streaming\" usage, by initialising\n *              iv_off to 0 before the first call, and preserving its value\n *              between calls.\n *\n *              For non-streaming use, the iv should be initialised on each call\n *              to a unique value, and iv_off set to 0 on each call.\n *\n *              If you need to retain the contents of the initialisation vector,\n *              you must either save it manually or use the cipher module\n *              instead.\n *\n * \\warning     For the OFB mode, the initialisation vector must be unique\n *              every encryption operation. Reuse of an initialisation vector\n *              will compromise security.\n *\n * \\param ctx      The AES context to use for encryption or decryption.\n *                 It must be initialized and bound to a key.\n * \\param length   The length of the input data.\n * \\param iv_off   The offset in IV (updated after use).\n *                 It must point to a valid \\c size_t.\n * \\param iv       The initialization vector (updated after use).\n *                 It must be a readable and writeable buffer of \\c 16 Bytes.\n * \\param input    The buffer holding the input data.\n *                 It must be readable and of size \\p length Bytes.\n * \\param output   The buffer holding the output data.\n *                 It must be writeable and of size \\p length Bytes.\n *\n * \\return         \\c 0 on success.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_aes_crypt_ofb(mbedtls_aes_context *ctx,\n                          size_t length,\n                          size_t *iv_off,\n                          unsigned char iv[16],\n                          const unsigned char *input,\n                          unsigned char *output);\n\n#endif /* MBEDTLS_CIPHER_MODE_OFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n/**\n * \\brief      This function performs an AES-CTR encryption or decryption\n *             operation.\n *\n *             Due to the nature of CTR, you must use the same key schedule\n *             for both encryption and decryption operations. Therefore, you\n *             must use the context initialized with mbedtls_aes_setkey_enc()\n *             for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT.\n *\n * \\warning    You must never reuse a nonce value with the same key. Doing so\n *             would void the encryption for the two messages encrypted with\n *             the same nonce and key.\n *\n *             There are two common strategies for managing nonces with CTR:\n *\n *             1. You can handle everything as a single message processed over\n *             successive calls to this function. In that case, you want to\n *             set \\p nonce_counter and \\p nc_off to 0 for the first call, and\n *             then preserve the values of \\p nonce_counter, \\p nc_off and \\p\n *             stream_block across calls to this function as they will be\n *             updated by this function.\n *\n *             With this strategy, you must not encrypt more than 2**128\n *             blocks of data with the same key.\n *\n *             2. You can encrypt separate messages by dividing the \\p\n *             nonce_counter buffer in two areas: the first one used for a\n *             per-message nonce, handled by yourself, and the second one\n *             updated by this function internally.\n *\n *             For example, you might reserve the first 12 bytes for the\n *             per-message nonce, and the last 4 bytes for internal use. In that\n *             case, before calling this function on a new message you need to\n *             set the first 12 bytes of \\p nonce_counter to your chosen nonce\n *             value, the last 4 to 0, and \\p nc_off to 0 (which will cause \\p\n *             stream_block to be ignored). That way, you can encrypt at most\n *             2**96 messages of up to 2**32 blocks each with the same key.\n *\n *             The per-message nonce (or information sufficient to reconstruct\n *             it) needs to be communicated with the ciphertext and must be unique.\n *             The recommended way to ensure uniqueness is to use a message\n *             counter. An alternative is to generate random nonces, but this\n *             limits the number of messages that can be securely encrypted:\n *             for example, with 96-bit random nonces, you should not encrypt\n *             more than 2**32 messages with the same key.\n *\n *             Note that for both strategies, sizes are measured in blocks and\n *             that an AES block is 16 bytes.\n *\n * \\warning    Upon return, \\p stream_block contains sensitive data. Its\n *             content must not be written to insecure storage and should be\n *             securely discarded as soon as it's no longer needed.\n *\n * \\param ctx              The AES context to use for encryption or decryption.\n *                         It must be initialized and bound to a key.\n * \\param length           The length of the input data.\n * \\param nc_off           The offset in the current \\p stream_block, for\n *                         resuming within the current cipher stream. The\n *                         offset pointer should be 0 at the start of a stream.\n *                         It must point to a valid \\c size_t.\n * \\param nonce_counter    The 128-bit nonce and counter.\n *                         It must be a readable-writeable buffer of \\c 16 Bytes.\n * \\param stream_block     The saved stream block for resuming. This is\n *                         overwritten by the function.\n *                         It must be a readable-writeable buffer of \\c 16 Bytes.\n * \\param input            The buffer holding the input data.\n *                         It must be readable and of size \\p length Bytes.\n * \\param output           The buffer holding the output data.\n *                         It must be writeable and of size \\p length Bytes.\n *\n * \\return                 \\c 0 on success.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx,\n                          size_t length,\n                          size_t *nc_off,\n                          unsigned char nonce_counter[16],\n                          unsigned char stream_block[16],\n                          const unsigned char *input,\n                          unsigned char *output);\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n/**\n * \\brief           Internal AES block encryption function. This is only\n *                  exposed to allow overriding it using\n *                  \\c MBEDTLS_AES_ENCRYPT_ALT.\n *\n * \\param ctx       The AES context to use for encryption.\n * \\param input     The plaintext block.\n * \\param output    The output (ciphertext) block.\n *\n * \\return          \\c 0 on success.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx,\n                                 const unsigned char input[16],\n                                 unsigned char output[16]);\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n/**\n * \\brief           Internal AES block decryption function. This is only\n *                  exposed to allow overriding it using see\n *                  \\c MBEDTLS_AES_DECRYPT_ALT.\n *\n * \\param ctx       The AES context to use for decryption.\n * \\param input     The ciphertext block.\n * \\param output    The output (plaintext) block.\n *\n * \\return          \\c 0 on success.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx,\n                                 const unsigned char input[16],\n                                 unsigned char output[16]);\n#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */\n\n#if defined(MBEDTLS_SELF_TEST)\n/**\n * \\brief          Checkup routine.\n *\n * \\return         \\c 0 on success.\n * \\return         \\c 1 on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_aes_self_test(int verbose);\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* aes.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/aria.h",
    "content": "/**\n * \\file aria.h\n *\n * \\brief ARIA block cipher\n *\n *        The ARIA algorithm is a symmetric block cipher that can encrypt and\n *        decrypt information. It is defined by the Korean Agency for\n *        Technology and Standards (KATS) in <em>KS X 1213:2004</em> (in\n *        Korean, but see http://210.104.33.10/ARIA/index-e.html in English)\n *        and also described by the IETF in <em>RFC 5794</em>.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_ARIA_H\n#define MBEDTLS_ARIA_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"mbedtls/platform_util.h\"\n\n#define MBEDTLS_ARIA_ENCRYPT     1 /**< ARIA encryption. */\n#define MBEDTLS_ARIA_DECRYPT     0 /**< ARIA decryption. */\n\n#define MBEDTLS_ARIA_BLOCKSIZE   16 /**< ARIA block size in bytes. */\n#define MBEDTLS_ARIA_MAX_ROUNDS  16 /**< Maximum number of rounds in ARIA. */\n#define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */\n\n/** Bad input data. */\n#define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C\n\n/** Invalid data input length. */\n#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_ARIA_ALT)\n// Regular implementation\n//\n\n/**\n * \\brief The ARIA context-type definition.\n */\ntypedef struct mbedtls_aria_context {\n    unsigned char MBEDTLS_PRIVATE(nr);           /*!< The number of rounds (12, 14 or 16) */\n    /*! The ARIA round keys. */\n    uint32_t MBEDTLS_PRIVATE(rk)[MBEDTLS_ARIA_MAX_ROUNDS + 1][MBEDTLS_ARIA_BLOCKSIZE / 4];\n}\nmbedtls_aria_context;\n\n#else  /* MBEDTLS_ARIA_ALT */\n#include \"aria_alt.h\"\n#endif /* MBEDTLS_ARIA_ALT */\n\n/**\n * \\brief          This function initializes the specified ARIA context.\n *\n *                 It must be the first API called before using\n *                 the context.\n *\n * \\param ctx      The ARIA context to initialize. This must not be \\c NULL.\n */\nvoid mbedtls_aria_init(mbedtls_aria_context *ctx);\n\n/**\n * \\brief          This function releases and clears the specified ARIA context.\n *\n * \\param ctx      The ARIA context to clear. This may be \\c NULL, in which\n *                 case this function returns immediately. If it is not \\c NULL,\n *                 it must point to an initialized ARIA context.\n */\nvoid mbedtls_aria_free(mbedtls_aria_context *ctx);\n\n/**\n * \\brief          This function sets the encryption key.\n *\n * \\param ctx      The ARIA context to which the key should be bound.\n *                 This must be initialized.\n * \\param key      The encryption key. This must be a readable buffer\n *                 of size \\p keybits Bits.\n * \\param keybits  The size of \\p key in Bits. Valid options are:\n *                 <ul><li>128 bits</li>\n *                 <li>192 bits</li>\n *                 <li>256 bits</li></ul>\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx,\n                            const unsigned char *key,\n                            unsigned int keybits);\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n/**\n * \\brief          This function sets the decryption key.\n *\n * \\param ctx      The ARIA context to which the key should be bound.\n *                 This must be initialized.\n * \\param key      The decryption key. This must be a readable buffer\n *                 of size \\p keybits Bits.\n * \\param keybits  The size of data passed. Valid options are:\n *                 <ul><li>128 bits</li>\n *                 <li>192 bits</li>\n *                 <li>256 bits</li></ul>\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_aria_setkey_dec(mbedtls_aria_context *ctx,\n                            const unsigned char *key,\n                            unsigned int keybits);\n#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */\n\n/**\n * \\brief          This function performs an ARIA single-block encryption or\n *                 decryption operation.\n *\n *                 It performs encryption or decryption (depending on whether\n *                 the key was set for encryption on decryption) on the input\n *                 data buffer defined in the \\p input parameter.\n *\n *                 mbedtls_aria_init(), and either mbedtls_aria_setkey_enc() or\n *                 mbedtls_aria_setkey_dec() must be called before the first\n *                 call to this API with the same context.\n *\n * \\param ctx      The ARIA context to use for encryption or decryption.\n *                 This must be initialized and bound to a key.\n * \\param input    The 16-Byte buffer holding the input data.\n * \\param output   The 16-Byte buffer holding the output data.\n\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_aria_crypt_ecb(mbedtls_aria_context *ctx,\n                           const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE],\n                           unsigned char output[MBEDTLS_ARIA_BLOCKSIZE]);\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n/**\n * \\brief  This function performs an ARIA-CBC encryption or decryption operation\n *         on full blocks.\n *\n *         It performs the operation defined in the \\p mode\n *         parameter (encrypt/decrypt), on the input data buffer defined in\n *         the \\p input parameter.\n *\n *         It can be called as many times as needed, until all the input\n *         data is processed. mbedtls_aria_init(), and either\n *         mbedtls_aria_setkey_enc() or mbedtls_aria_setkey_dec() must be called\n *         before the first call to this API with the same context.\n *\n * \\note   This function operates on aligned blocks, that is, the input size\n *         must be a multiple of the ARIA block size of 16 Bytes.\n *\n * \\note   Upon exit, the content of the IV is updated so that you can\n *         call the same function again on the next\n *         block(s) of data and get the same result as if it was\n *         encrypted in one call. This allows a \"streaming\" usage.\n *         If you need to retain the contents of the IV, you should\n *         either save it manually or use the cipher module instead.\n *\n *\n * \\param ctx      The ARIA context to use for encryption or decryption.\n *                 This must be initialized and bound to a key.\n * \\param mode     The mode of operation. This must be either\n *                 #MBEDTLS_ARIA_ENCRYPT for encryption, or\n *                 #MBEDTLS_ARIA_DECRYPT for decryption.\n * \\param length   The length of the input data in Bytes. This must be a\n *                 multiple of the block size (16 Bytes).\n * \\param iv       Initialization vector (updated after use).\n *                 This must be a readable buffer of size 16 Bytes.\n * \\param input    The buffer holding the input data. This must\n *                 be a readable buffer of length \\p length Bytes.\n * \\param output   The buffer holding the output data. This must\n *                 be a writable buffer of length \\p length Bytes.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_aria_crypt_cbc(mbedtls_aria_context *ctx,\n                           int mode,\n                           size_t length,\n                           unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE],\n                           const unsigned char *input,\n                           unsigned char *output);\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n/**\n * \\brief This function performs an ARIA-CFB128 encryption or decryption\n *        operation.\n *\n *        It performs the operation defined in the \\p mode\n *        parameter (encrypt or decrypt), on the input data buffer\n *        defined in the \\p input parameter.\n *\n *        For CFB, you must set up the context with mbedtls_aria_setkey_enc(),\n *        regardless of whether you are performing an encryption or decryption\n *        operation, that is, regardless of the \\p mode parameter. This is\n *        because CFB mode uses the same key schedule for encryption and\n *        decryption.\n *\n * \\note  Upon exit, the content of the IV is updated so that you can\n *        call the same function again on the next\n *        block(s) of data and get the same result as if it was\n *        encrypted in one call. This allows a \"streaming\" usage.\n *        If you need to retain the contents of the\n *        IV, you must either save it manually or use the cipher\n *        module instead.\n *\n *\n * \\param ctx      The ARIA context to use for encryption or decryption.\n *                 This must be initialized and bound to a key.\n * \\param mode     The mode of operation. This must be either\n *                 #MBEDTLS_ARIA_ENCRYPT for encryption, or\n *                 #MBEDTLS_ARIA_DECRYPT for decryption.\n * \\param length   The length of the input data \\p input in Bytes.\n * \\param iv_off   The offset in IV (updated after use).\n *                 This must not be larger than 15.\n * \\param iv       The initialization vector (updated after use).\n *                 This must be a readable buffer of size 16 Bytes.\n * \\param input    The buffer holding the input data. This must\n *                 be a readable buffer of length \\p length Bytes.\n * \\param output   The buffer holding the output data. This must\n *                 be a writable buffer of length \\p length Bytes.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_aria_crypt_cfb128(mbedtls_aria_context *ctx,\n                              int mode,\n                              size_t length,\n                              size_t *iv_off,\n                              unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE],\n                              const unsigned char *input,\n                              unsigned char *output);\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n/**\n * \\brief      This function performs an ARIA-CTR encryption or decryption\n *             operation.\n *\n *             Due to the nature of CTR, you must use the same key schedule\n *             for both encryption and decryption operations. Therefore, you\n *             must use the context initialized with mbedtls_aria_setkey_enc()\n *             for both #MBEDTLS_ARIA_ENCRYPT and #MBEDTLS_ARIA_DECRYPT.\n *\n * \\warning    You must never reuse a nonce value with the same key. Doing so\n *             would void the encryption for the two messages encrypted with\n *             the same nonce and key.\n *\n *             There are two common strategies for managing nonces with CTR:\n *\n *             1. You can handle everything as a single message processed over\n *             successive calls to this function. In that case, you want to\n *             set \\p nonce_counter and \\p nc_off to 0 for the first call, and\n *             then preserve the values of \\p nonce_counter, \\p nc_off and \\p\n *             stream_block across calls to this function as they will be\n *             updated by this function.\n *\n *             With this strategy, you must not encrypt more than 2**128\n *             blocks of data with the same key.\n *\n *             2. You can encrypt separate messages by dividing the \\p\n *             nonce_counter buffer in two areas: the first one used for a\n *             per-message nonce, handled by yourself, and the second one\n *             updated by this function internally.\n *\n *             For example, you might reserve the first 12 bytes for the\n *             per-message nonce, and the last 4 bytes for internal use. In that\n *             case, before calling this function on a new message you need to\n *             set the first 12 bytes of \\p nonce_counter to your chosen nonce\n *             value, the last 4 to 0, and \\p nc_off to 0 (which will cause \\p\n *             stream_block to be ignored). That way, you can encrypt at most\n *             2**96 messages of up to 2**32 blocks each with the same key.\n *\n *             The per-message nonce (or information sufficient to reconstruct\n *             it) needs to be communicated with the ciphertext and must be unique.\n *             The recommended way to ensure uniqueness is to use a message\n *             counter. An alternative is to generate random nonces, but this\n *             limits the number of messages that can be securely encrypted:\n *             for example, with 96-bit random nonces, you should not encrypt\n *             more than 2**32 messages with the same key.\n *\n *             Note that for both strategies, sizes are measured in blocks and\n *             that an ARIA block is 16 bytes.\n *\n * \\warning    Upon return, \\p stream_block contains sensitive data. Its\n *             content must not be written to insecure storage and should be\n *             securely discarded as soon as it's no longer needed.\n *\n * \\param ctx              The ARIA context to use for encryption or decryption.\n *                         This must be initialized and bound to a key.\n * \\param length           The length of the input data \\p input in Bytes.\n * \\param nc_off           The offset in Bytes in the current \\p stream_block,\n *                         for resuming within the current cipher stream. The\n *                         offset pointer should be \\c 0 at the start of a\n *                         stream. This must not be larger than \\c 15 Bytes.\n * \\param nonce_counter    The 128-bit nonce and counter. This must point to\n *                         a read/write buffer of length \\c 16 bytes.\n * \\param stream_block     The saved stream block for resuming. This must\n *                         point to a read/write buffer of length \\c 16 bytes.\n *                         This is overwritten by the function.\n * \\param input            The buffer holding the input data. This must\n *                         be a readable buffer of length \\p length Bytes.\n * \\param output           The buffer holding the output data. This must\n *                         be a writable buffer of length \\p length Bytes.\n *\n * \\return                 \\c 0 on success.\n * \\return                 A negative error code on failure.\n */\nint mbedtls_aria_crypt_ctr(mbedtls_aria_context *ctx,\n                           size_t length,\n                           size_t *nc_off,\n                           unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE],\n                           unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE],\n                           const unsigned char *input,\n                           unsigned char *output);\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n#if defined(MBEDTLS_SELF_TEST)\n/**\n * \\brief          Checkup routine.\n *\n * \\return         \\c 0 on success, or \\c 1 on failure.\n */\nint mbedtls_aria_self_test(int verbose);\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* aria.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/asn1.h",
    "content": "/**\n * \\file asn1.h\n *\n * \\brief Generic ASN.1 parsing\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_ASN1_H\n#define MBEDTLS_ASN1_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include <stddef.h>\n\n#if defined(MBEDTLS_BIGNUM_C)\n#include \"mbedtls/bignum.h\"\n#endif\n\n/**\n * \\addtogroup asn1_module\n * \\{\n */\n\n/**\n * \\name ASN1 Error codes\n * These error codes are combined with other error codes for\n * higher error granularity.\n * e.g. X.509 and PKCS #7 error codes\n * ASN1 is a standard to specify data structures.\n * \\{\n */\n/** Out of data when parsing an ASN1 data structure. */\n#define MBEDTLS_ERR_ASN1_OUT_OF_DATA                      -0x0060\n/** ASN1 tag was of an unexpected value. */\n#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG                   -0x0062\n/** Error when trying to determine the length or invalid length. */\n#define MBEDTLS_ERR_ASN1_INVALID_LENGTH                   -0x0064\n/** Actual length differs from expected length. */\n#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH                  -0x0066\n/** Data is invalid. */\n#define MBEDTLS_ERR_ASN1_INVALID_DATA                     -0x0068\n/** Memory allocation failed */\n#define MBEDTLS_ERR_ASN1_ALLOC_FAILED                     -0x006A\n/** Buffer too small when writing ASN.1 data structure. */\n#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL                    -0x006C\n\n/** \\} name ASN1 Error codes */\n\n/**\n * \\name DER constants\n * These constants comply with the DER encoded ASN.1 type tags.\n * DER encoding uses hexadecimal representation.\n * An example DER sequence is:\\n\n * - 0x02 -- tag indicating INTEGER\n * - 0x01 -- length in octets\n * - 0x05 -- value\n * Such sequences are typically read into \\c ::mbedtls_x509_buf.\n * \\{\n */\n#define MBEDTLS_ASN1_BOOLEAN                 0x01\n#define MBEDTLS_ASN1_INTEGER                 0x02\n#define MBEDTLS_ASN1_BIT_STRING              0x03\n#define MBEDTLS_ASN1_OCTET_STRING            0x04\n#define MBEDTLS_ASN1_NULL                    0x05\n#define MBEDTLS_ASN1_OID                     0x06\n#define MBEDTLS_ASN1_ENUMERATED              0x0A\n#define MBEDTLS_ASN1_UTF8_STRING             0x0C\n#define MBEDTLS_ASN1_SEQUENCE                0x10\n#define MBEDTLS_ASN1_SET                     0x11\n#define MBEDTLS_ASN1_PRINTABLE_STRING        0x13\n#define MBEDTLS_ASN1_T61_STRING              0x14\n#define MBEDTLS_ASN1_IA5_STRING              0x16\n#define MBEDTLS_ASN1_UTC_TIME                0x17\n#define MBEDTLS_ASN1_GENERALIZED_TIME        0x18\n#define MBEDTLS_ASN1_UNIVERSAL_STRING        0x1C\n#define MBEDTLS_ASN1_BMP_STRING              0x1E\n#define MBEDTLS_ASN1_PRIMITIVE               0x00\n#define MBEDTLS_ASN1_CONSTRUCTED             0x20\n#define MBEDTLS_ASN1_CONTEXT_SPECIFIC        0x80\n\n/* Slightly smaller way to check if tag is a string tag\n * compared to canonical implementation. */\n#define MBEDTLS_ASN1_IS_STRING_TAG(tag)                                \\\n    ((unsigned int) (tag) < 32u && (                                   \\\n         ((1u << (tag)) & ((1u << MBEDTLS_ASN1_BMP_STRING)       |     \\\n                           (1u << MBEDTLS_ASN1_UTF8_STRING)      |     \\\n                           (1u << MBEDTLS_ASN1_T61_STRING)       |     \\\n                           (1u << MBEDTLS_ASN1_IA5_STRING)       |     \\\n                           (1u << MBEDTLS_ASN1_UNIVERSAL_STRING) |     \\\n                           (1u << MBEDTLS_ASN1_PRINTABLE_STRING))) != 0))\n\n/*\n * Bit masks for each of the components of an ASN.1 tag as specified in\n * ITU X.690 (08/2015), section 8.1 \"General rules for encoding\",\n * paragraph 8.1.2.2:\n *\n * Bit  8     7   6   5          1\n *     +-------+-----+------------+\n *     | Class | P/C | Tag number |\n *     +-------+-----+------------+\n */\n#define MBEDTLS_ASN1_TAG_CLASS_MASK          0xC0\n#define MBEDTLS_ASN1_TAG_PC_MASK             0x20\n#define MBEDTLS_ASN1_TAG_VALUE_MASK          0x1F\n\n/** \\} name DER constants */\n\n/** Returns the size of the binary string, without the trailing \\\\0 */\n#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1)\n\n/**\n * Compares an mbedtls_asn1_buf structure to a reference OID.\n *\n * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a\n * 'unsigned char *oid' here!\n */\n#define MBEDTLS_OID_CMP(oid_str, oid_buf)                                   \\\n    ((MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len) ||                \\\n     memcmp((oid_str), (oid_buf)->p, (oid_buf)->len) != 0)\n\n#define MBEDTLS_OID_CMP_RAW(oid_str, oid_buf, oid_buf_len)              \\\n    ((MBEDTLS_OID_SIZE(oid_str) != (oid_buf_len)) ||             \\\n     memcmp((oid_str), (oid_buf), (oid_buf_len)) != 0)\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\name Functions to parse ASN.1 data structures\n * \\{\n */\n\n/**\n * Type-length-value structure that allows for ASN1 using DER.\n */\ntypedef struct mbedtls_asn1_buf {\n    int tag;                /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */\n    size_t len;             /**< ASN1 length, in octets. */\n    unsigned char *p;       /**< ASN1 data, e.g. in ASCII. */\n}\nmbedtls_asn1_buf;\n\n/**\n * Container for ASN1 bit strings.\n */\ntypedef struct mbedtls_asn1_bitstring {\n    size_t len;                 /**< ASN1 length, in octets. */\n    unsigned char unused_bits;  /**< Number of unused bits at the end of the string */\n    unsigned char *p;           /**< Raw ASN1 data for the bit string */\n}\nmbedtls_asn1_bitstring;\n\n/**\n * Container for a sequence of ASN.1 items\n */\ntypedef struct mbedtls_asn1_sequence {\n    mbedtls_asn1_buf buf;                   /**< Buffer containing the given ASN.1 item. */\n\n    /** The next entry in the sequence.\n     *\n     * The details of memory management for sequences are not documented and\n     * may change in future versions. Set this field to \\p NULL when\n     * initializing a structure, and do not modify it except via Mbed TLS\n     * library functions.\n     */\n    struct mbedtls_asn1_sequence *next;\n}\nmbedtls_asn1_sequence;\n\n/**\n * Container for a sequence or list of 'named' ASN.1 data items\n */\ntypedef struct mbedtls_asn1_named_data {\n    mbedtls_asn1_buf oid;                   /**< The object identifier. */\n    mbedtls_asn1_buf val;                   /**< The named value. */\n\n    /** The next entry in the sequence.\n     *\n     * The details of memory management for named data sequences are not\n     * documented and may change in future versions. Set this field to \\p NULL\n     * when initializing a structure, and do not modify it except via Mbed TLS\n     * library functions.\n     */\n    struct mbedtls_asn1_named_data *next;\n\n    /** Merge next item into the current one?\n     *\n     * This field exists for the sake of Mbed TLS's X.509 certificate parsing\n     * code and may change in future versions of the library.\n     */\n    unsigned char MBEDTLS_PRIVATE(next_merged);\n}\nmbedtls_asn1_named_data;\n\n#if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \\\n    defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)\n/**\n * \\brief       Get the length of an ASN.1 element.\n *              Updates the pointer to immediately behind the length.\n *\n * \\param p     On entry, \\c *p points to the first byte of the length,\n *              i.e. immediately after the tag.\n *              On successful completion, \\c *p points to the first byte\n *              after the length, i.e. the first byte of the content.\n *              On error, the value of \\c *p is undefined.\n * \\param end   End of data.\n * \\param len   On successful completion, \\c *len contains the length\n *              read from the ASN.1 input.\n *\n * \\return      0 if successful.\n * \\return      #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element\n *              would end beyond \\p end.\n * \\return      #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable.\n */\nint mbedtls_asn1_get_len(unsigned char **p,\n                         const unsigned char *end,\n                         size_t *len);\n\n/**\n * \\brief       Get the tag and length of the element.\n *              Check for the requested tag.\n *              Updates the pointer to immediately behind the tag and length.\n *\n * \\param p     On entry, \\c *p points to the start of the ASN.1 element.\n *              On successful completion, \\c *p points to the first byte\n *              after the length, i.e. the first byte of the content.\n *              On error, the value of \\c *p is undefined.\n * \\param end   End of data.\n * \\param len   On successful completion, \\c *len contains the length\n *              read from the ASN.1 input.\n * \\param tag   The expected tag.\n *\n * \\return      0 if successful.\n * \\return      #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the data does not start\n *              with the requested tag.\n * \\return      #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element\n *              would end beyond \\p end.\n * \\return      #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable.\n */\nint mbedtls_asn1_get_tag(unsigned char **p,\n                         const unsigned char *end,\n                         size_t *len, int tag);\n#endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */\n\n#if defined(MBEDTLS_ASN1_PARSE_C)\n/**\n * \\brief       Retrieve a boolean ASN.1 tag and its value.\n *              Updates the pointer to immediately behind the full tag.\n *\n * \\param p     On entry, \\c *p points to the start of the ASN.1 element.\n *              On successful completion, \\c *p points to the first byte\n *              beyond the ASN.1 element.\n *              On error, the value of \\c *p is undefined.\n * \\param end   End of data.\n * \\param val   On success, the parsed value (\\c 0 or \\c 1).\n *\n * \\return      0 if successful.\n * \\return      An ASN.1 error code if the input does not start with\n *              a valid ASN.1 BOOLEAN.\n */\nint mbedtls_asn1_get_bool(unsigned char **p,\n                          const unsigned char *end,\n                          int *val);\n\n/**\n * \\brief       Retrieve an integer ASN.1 tag and its value.\n *              Updates the pointer to immediately behind the full tag.\n *\n * \\param p     On entry, \\c *p points to the start of the ASN.1 element.\n *              On successful completion, \\c *p points to the first byte\n *              beyond the ASN.1 element.\n *              On error, the value of \\c *p is undefined.\n * \\param end   End of data.\n * \\param val   On success, the parsed value.\n *\n * \\return      0 if successful.\n * \\return      An ASN.1 error code if the input does not start with\n *              a valid ASN.1 INTEGER.\n * \\return      #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does\n *              not fit in an \\c int.\n */\nint mbedtls_asn1_get_int(unsigned char **p,\n                         const unsigned char *end,\n                         int *val);\n\n/**\n * \\brief       Retrieve an enumerated ASN.1 tag and its value.\n *              Updates the pointer to immediately behind the full tag.\n *\n * \\param p     On entry, \\c *p points to the start of the ASN.1 element.\n *              On successful completion, \\c *p points to the first byte\n *              beyond the ASN.1 element.\n *              On error, the value of \\c *p is undefined.\n * \\param end   End of data.\n * \\param val   On success, the parsed value.\n *\n * \\return      0 if successful.\n * \\return      An ASN.1 error code if the input does not start with\n *              a valid ASN.1 ENUMERATED.\n * \\return      #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does\n *              not fit in an \\c int.\n */\nint mbedtls_asn1_get_enum(unsigned char **p,\n                          const unsigned char *end,\n                          int *val);\n\n/**\n * \\brief       Retrieve a bitstring ASN.1 tag and its value.\n *              Updates the pointer to immediately behind the full tag.\n *\n * \\param p     On entry, \\c *p points to the start of the ASN.1 element.\n *              On successful completion, \\c *p is equal to \\p end.\n *              On error, the value of \\c *p is undefined.\n * \\param end   End of data.\n * \\param bs    On success, ::mbedtls_asn1_bitstring information about\n *              the parsed value.\n *\n * \\return      0 if successful.\n * \\return      #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains\n *              extra data after a valid BIT STRING.\n * \\return      An ASN.1 error code if the input does not start with\n *              a valid ASN.1 BIT STRING.\n */\nint mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end,\n                               mbedtls_asn1_bitstring *bs);\n\n/**\n * \\brief       Retrieve a bitstring ASN.1 tag without unused bits and its\n *              value.\n *              Updates the pointer to the beginning of the bit/octet string.\n *\n * \\param p     On entry, \\c *p points to the start of the ASN.1 element.\n *              On successful completion, \\c *p points to the first byte\n *              of the content of the BIT STRING.\n *              On error, the value of \\c *p is undefined.\n * \\param end   End of data.\n * \\param len   On success, \\c *len is the length of the content in bytes.\n *\n * \\return      0 if successful.\n * \\return      #MBEDTLS_ERR_ASN1_INVALID_DATA if the input starts with\n *              a valid BIT STRING with a nonzero number of unused bits.\n * \\return      An ASN.1 error code if the input does not start with\n *              a valid ASN.1 BIT STRING.\n */\nint mbedtls_asn1_get_bitstring_null(unsigned char **p,\n                                    const unsigned char *end,\n                                    size_t *len);\n\n/**\n * \\brief       Parses and splits an ASN.1 \"SEQUENCE OF <tag>\".\n *              Updates the pointer to immediately behind the full sequence tag.\n *\n * This function allocates memory for the sequence elements. You can free\n * the allocated memory with mbedtls_asn1_sequence_free().\n *\n * \\note        On error, this function may return a partial list in \\p cur.\n *              You must set `cur->next = NULL` before calling this function!\n *              Otherwise it is impossible to distinguish a previously non-null\n *              pointer from a pointer to an object allocated by this function.\n *\n * \\note        If the sequence is empty, this function does not modify\n *              \\c *cur. If the sequence is valid and non-empty, this\n *              function sets `cur->buf.tag` to \\p tag. This allows\n *              callers to distinguish between an empty sequence and\n *              a one-element sequence.\n *\n * \\param p     On entry, \\c *p points to the start of the ASN.1 element.\n *              On successful completion, \\c *p is equal to \\p end.\n *              On error, the value of \\c *p is undefined.\n * \\param end   End of data.\n * \\param cur   A ::mbedtls_asn1_sequence which this function fills.\n *              When this function returns, \\c *cur is the head of a linked\n *              list. Each node in this list is allocated with\n *              mbedtls_calloc() apart from \\p cur itself, and should\n *              therefore be freed with mbedtls_free().\n *              The list describes the content of the sequence.\n *              The head of the list (i.e. \\c *cur itself) describes the\n *              first element, `*cur->next` describes the second element, etc.\n *              For each element, `buf.tag == tag`, `buf.len` is the length\n *              of the content of the content of the element, and `buf.p`\n *              points to the first byte of the content (i.e. immediately\n *              past the length of the element).\n *              Note that list elements may be allocated even on error.\n * \\param tag   Each element of the sequence must have this tag.\n *\n * \\return      0 if successful.\n * \\return      #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains\n *              extra data after a valid SEQUENCE OF \\p tag.\n * \\return      #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts with\n *              an ASN.1 SEQUENCE in which an element has a tag that\n *              is different from \\p tag.\n * \\return      #MBEDTLS_ERR_ASN1_ALLOC_FAILED if a memory allocation failed.\n * \\return      An ASN.1 error code if the input does not start with\n *              a valid ASN.1 SEQUENCE.\n */\nint mbedtls_asn1_get_sequence_of(unsigned char **p,\n                                 const unsigned char *end,\n                                 mbedtls_asn1_sequence *cur,\n                                 int tag);\n/**\n * \\brief          Free a heap-allocated linked list presentation of\n *                 an ASN.1 sequence, including the first element.\n *\n * There are two common ways to manage the memory used for the representation\n * of a parsed ASN.1 sequence:\n * - Allocate a head node `mbedtls_asn1_sequence *head` with mbedtls_calloc().\n *   Pass this node as the `cur` argument to mbedtls_asn1_get_sequence_of().\n *   When you have finished processing the sequence,\n *   call mbedtls_asn1_sequence_free() on `head`.\n * - Allocate a head node `mbedtls_asn1_sequence *head` in any manner,\n *   for example on the stack. Make sure that `head->next == NULL`.\n *   Pass `head` as the `cur` argument to mbedtls_asn1_get_sequence_of().\n *   When you have finished processing the sequence,\n *   call mbedtls_asn1_sequence_free() on `head->cur`,\n *   then free `head` itself in the appropriate manner.\n *\n * \\param seq      The address of the first sequence component. This may\n *                 be \\c NULL, in which case this functions returns\n *                 immediately.\n */\nvoid mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq);\n\n/**\n * \\brief                Traverse an ASN.1 SEQUENCE container and\n *                       call a callback for each entry.\n *\n * This function checks that the input is a SEQUENCE of elements that\n * each have a \"must\" tag, and calls a callback function on the elements\n * that have a \"may\" tag.\n *\n * For example, to validate that the input is a SEQUENCE of `tag1` and call\n * `cb` on each element, use\n * ```\n * mbedtls_asn1_traverse_sequence_of(&p, end, 0xff, tag1, 0, 0, cb, ctx);\n * ```\n *\n * To validate that the input is a SEQUENCE of ANY and call `cb` on\n * each element, use\n * ```\n * mbedtls_asn1_traverse_sequence_of(&p, end, 0, 0, 0, 0, cb, ctx);\n * ```\n *\n * To validate that the input is a SEQUENCE of CHOICE {NULL, OCTET STRING}\n * and call `cb` on each element that is an OCTET STRING, use\n * ```\n * mbedtls_asn1_traverse_sequence_of(&p, end, 0xfe, 0x04, 0xff, 0x04, cb, ctx);\n * ```\n *\n * The callback is called on the elements with a \"may\" tag from left to\n * right. If the input is not a valid SEQUENCE of elements with a \"must\" tag,\n * the callback is called on the elements up to the leftmost point where\n * the input is invalid.\n *\n * \\warning              This function is still experimental and may change\n *                       at any time.\n *\n * \\param p              The address of the pointer to the beginning of\n *                       the ASN.1 SEQUENCE header. This is updated to\n *                       point to the end of the ASN.1 SEQUENCE container\n *                       on a successful invocation.\n * \\param end            The end of the ASN.1 SEQUENCE container.\n * \\param tag_must_mask  A mask to be applied to the ASN.1 tags found within\n *                       the SEQUENCE before comparing to \\p tag_must_val.\n * \\param tag_must_val   The required value of each ASN.1 tag found in the\n *                       SEQUENCE, after masking with \\p tag_must_mask.\n *                       Mismatching tags lead to an error.\n *                       For example, a value of \\c 0 for both \\p tag_must_mask\n *                       and \\p tag_must_val means that every tag is allowed,\n *                       while a value of \\c 0xFF for \\p tag_must_mask means\n *                       that \\p tag_must_val is the only allowed tag.\n * \\param tag_may_mask   A mask to be applied to the ASN.1 tags found within\n *                       the SEQUENCE before comparing to \\p tag_may_val.\n * \\param tag_may_val    The desired value of each ASN.1 tag found in the\n *                       SEQUENCE, after masking with \\p tag_may_mask.\n *                       Mismatching tags will be silently ignored.\n *                       For example, a value of \\c 0 for \\p tag_may_mask and\n *                       \\p tag_may_val means that any tag will be considered,\n *                       while a value of \\c 0xFF for \\p tag_may_mask means\n *                       that all tags with value different from \\p tag_may_val\n *                       will be ignored.\n * \\param cb             The callback to trigger for each component\n *                       in the ASN.1 SEQUENCE that matches \\p tag_may_val.\n *                       The callback function is called with the following\n *                       parameters:\n *                       - \\p ctx.\n *                       - The tag of the current element.\n *                       - A pointer to the start of the current element's\n *                         content inside the input.\n *                       - The length of the content of the current element.\n *                       If the callback returns a non-zero value,\n *                       the function stops immediately,\n *                       forwarding the callback's return value.\n * \\param ctx            The context to be passed to the callback \\p cb.\n *\n * \\return               \\c 0 if successful the entire ASN.1 SEQUENCE\n *                       was traversed without parsing or callback errors.\n * \\return               #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input\n *                       contains extra data after a valid SEQUENCE\n *                       of elements with an accepted tag.\n * \\return               #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts\n *                       with an ASN.1 SEQUENCE in which an element has a tag\n *                       that is not accepted.\n * \\return               An ASN.1 error code if the input does not start with\n *                       a valid ASN.1 SEQUENCE.\n * \\return               A non-zero error code forwarded from the callback\n *                       \\p cb in case the latter returns a non-zero value.\n */\nint mbedtls_asn1_traverse_sequence_of(\n    unsigned char **p,\n    const unsigned char *end,\n    unsigned char tag_must_mask, unsigned char tag_must_val,\n    unsigned char tag_may_mask, unsigned char tag_may_val,\n    int (*cb)(void *ctx, int tag,\n              unsigned char *start, size_t len),\n    void *ctx);\n\n#if defined(MBEDTLS_BIGNUM_C)\n/**\n * \\brief       Retrieve an integer ASN.1 tag and its value.\n *              Updates the pointer to immediately behind the full tag.\n *\n * \\param p     On entry, \\c *p points to the start of the ASN.1 element.\n *              On successful completion, \\c *p points to the first byte\n *              beyond the ASN.1 element.\n *              On error, the value of \\c *p is undefined.\n * \\param end   End of data.\n * \\param X     On success, the parsed value.\n *\n * \\return      0 if successful.\n * \\return      An ASN.1 error code if the input does not start with\n *              a valid ASN.1 INTEGER.\n * \\return      #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does\n *              not fit in an \\c int.\n * \\return      An MPI error code if the parsed value is too large.\n */\nint mbedtls_asn1_get_mpi(unsigned char **p,\n                         const unsigned char *end,\n                         mbedtls_mpi *X);\n#endif /* MBEDTLS_BIGNUM_C */\n\n/**\n * \\brief       Retrieve an AlgorithmIdentifier ASN.1 sequence.\n *              Updates the pointer to immediately behind the full\n *              AlgorithmIdentifier.\n *\n * \\param p     On entry, \\c *p points to the start of the ASN.1 element.\n *              On successful completion, \\c *p points to the first byte\n *              beyond the AlgorithmIdentifier element.\n *              On error, the value of \\c *p is undefined.\n * \\param end   End of data.\n * \\param alg   The buffer to receive the OID.\n * \\param params The buffer to receive the parameters.\n *              This is zeroized if there are no parameters.\n *\n * \\return      0 if successful or a specific ASN.1 or MPI error code.\n */\nint mbedtls_asn1_get_alg(unsigned char **p,\n                         const unsigned char *end,\n                         mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params);\n\n/**\n * \\brief       Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no\n *              params.\n *              Updates the pointer to immediately behind the full\n *              AlgorithmIdentifier.\n *\n * \\param p     On entry, \\c *p points to the start of the ASN.1 element.\n *              On successful completion, \\c *p points to the first byte\n *              beyond the AlgorithmIdentifier element.\n *              On error, the value of \\c *p is undefined.\n * \\param end   End of data.\n * \\param alg   The buffer to receive the OID.\n *\n * \\return      0 if successful or a specific ASN.1 or MPI error code.\n */\nint mbedtls_asn1_get_alg_null(unsigned char **p,\n                              const unsigned char *end,\n                              mbedtls_asn1_buf *alg);\n\n/**\n * \\brief       Find a specific named_data entry in a sequence or list based on\n *              the OID.\n *\n * \\param list  The list to seek through\n * \\param oid   The OID to look for\n * \\param len   Size of the OID\n *\n * \\return      NULL if not found, or a pointer to the existing entry.\n */\nconst mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list,\n                                                            const char *oid, size_t len);\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n/**\n * \\brief       Free a mbedtls_asn1_named_data entry\n *\n * \\deprecated  This function is deprecated and will be removed in a\n *              future version of the library.\n *              Please use mbedtls_asn1_free_named_data_list()\n *              or mbedtls_asn1_free_named_data_list_shallow().\n *\n * \\param entry The named data entry to free.\n *              This function calls mbedtls_free() on\n *              `entry->oid.p` and `entry->val.p`.\n */\nvoid MBEDTLS_DEPRECATED mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *entry);\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n\n/**\n * \\brief       Free all entries in a mbedtls_asn1_named_data list.\n *\n * \\param head  Pointer to the head of the list of named data entries to free.\n *              This function calls mbedtls_free() on\n *              `entry->oid.p` and `entry->val.p` and then on `entry`\n *              for each list entry, and sets \\c *head to \\c NULL.\n */\nvoid mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head);\n\n/**\n * \\brief       Free all shallow entries in a mbedtls_asn1_named_data list,\n *              but do not free internal pointer targets.\n *\n * \\param name  Head of the list of named data entries to free.\n *              This function calls mbedtls_free() on each list element.\n */\nvoid mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name);\n\n/** \\} name Functions to parse ASN.1 data structures */\n/** \\} addtogroup asn1_module */\n\n#endif /* MBEDTLS_ASN1_PARSE_C */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* asn1.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/asn1write.h",
    "content": "/**\n * \\file asn1write.h\n *\n * \\brief ASN.1 buffer writing functionality\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_ASN1_WRITE_H\n#define MBEDTLS_ASN1_WRITE_H\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/asn1.h\"\n\n#define MBEDTLS_ASN1_CHK_ADD(g, f)                      \\\n    do                                                  \\\n    {                                                   \\\n        if ((ret = (f)) < 0)                         \\\n        return ret;                              \\\n        else                                            \\\n        (g) += ret;                                 \\\n    } while (0)\n\n#define MBEDTLS_ASN1_CHK_CLEANUP_ADD(g, f)                      \\\n    do                                                  \\\n    {                                                   \\\n        if ((ret = (f)) < 0)                         \\\n        goto cleanup;                              \\\n        else                                            \\\n        (g) += ret;                                 \\\n    } while (0)\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if defined(MBEDTLS_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C) || \\\n    defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)\n/**\n * \\brief           Write a length field in ASN.1 format.\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param len       The length value to write.\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative \\c MBEDTLS_ERR_ASN1_XXX error code on failure.\n */\nint mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start,\n                           size_t len);\n/**\n * \\brief           Write an ASN.1 tag in ASN.1 format.\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param tag       The tag to write.\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative \\c MBEDTLS_ERR_ASN1_XXX error code on failure.\n */\nint mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start,\n                           unsigned char tag);\n#endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA*/\n\n#if defined(MBEDTLS_ASN1_WRITE_C)\n/**\n * \\brief           Write raw buffer data.\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param buf       The data buffer to write.\n * \\param size      The length of the data buffer.\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative \\c MBEDTLS_ERR_ASN1_XXX error code on failure.\n */\nint mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start,\n                                  const unsigned char *buf, size_t size);\n\n#if defined(MBEDTLS_BIGNUM_C)\n/**\n * \\brief           Write an arbitrary-precision number (#MBEDTLS_ASN1_INTEGER)\n *                  in ASN.1 format.\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param X         The MPI to write.\n *                  It must be non-negative.\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative \\c MBEDTLS_ERR_ASN1_XXX error code on failure.\n */\nint mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start,\n                           const mbedtls_mpi *X);\n#endif /* MBEDTLS_BIGNUM_C */\n\n/**\n * \\brief           Write a NULL tag (#MBEDTLS_ASN1_NULL) with zero data\n *                  in ASN.1 format.\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative \\c MBEDTLS_ERR_ASN1_XXX error code on failure.\n */\nint mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start);\n\n/**\n * \\brief           Write an OID tag (#MBEDTLS_ASN1_OID) and data\n *                  in ASN.1 format.\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param oid       The OID to write.\n * \\param oid_len   The length of the OID.\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative \\c MBEDTLS_ERR_ASN1_XXX error code on failure.\n */\nint mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start,\n                           const char *oid, size_t oid_len);\n\n/**\n * \\brief           Write an AlgorithmIdentifier sequence in ASN.1 format.\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param oid       The OID of the algorithm to write.\n * \\param oid_len   The length of the algorithm's OID.\n * \\param par_len   The length of the parameters, which must be already written.\n *                  If 0, NULL parameters are added\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative \\c MBEDTLS_ERR_ASN1_XXX error code on failure.\n */\nint mbedtls_asn1_write_algorithm_identifier(unsigned char **p,\n                                            const unsigned char *start,\n                                            const char *oid, size_t oid_len,\n                                            size_t par_len);\n\n/**\n * \\brief           Write an AlgorithmIdentifier sequence in ASN.1 format.\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param oid       The OID of the algorithm to write.\n * \\param oid_len   The length of the algorithm's OID.\n * \\param par_len   The length of the parameters, which must be already written.\n * \\param has_par   If there are any parameters. If 0, par_len must be 0. If 1\n *                  and \\p par_len is 0, NULL parameters are added.\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative \\c MBEDTLS_ERR_ASN1_XXX error code on failure.\n */\nint mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p,\n                                                const unsigned char *start,\n                                                const char *oid, size_t oid_len,\n                                                size_t par_len, int has_par);\n\n/**\n * \\brief           Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value\n *                  in ASN.1 format.\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param boolean   The boolean value to write, either \\c 0 or \\c 1.\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative \\c MBEDTLS_ERR_ASN1_XXX error code on failure.\n */\nint mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start,\n                            int boolean);\n\n/**\n * \\brief           Write an int tag (#MBEDTLS_ASN1_INTEGER) and value\n *                  in ASN.1 format.\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param val       The integer value to write.\n *                  It must be non-negative.\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative \\c MBEDTLS_ERR_ASN1_XXX error code on failure.\n */\nint mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val);\n\n/**\n * \\brief           Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value\n *                  in ASN.1 format.\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param val       The integer value to write.\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative \\c MBEDTLS_ERR_ASN1_XXX error code on failure.\n */\nint mbedtls_asn1_write_enum(unsigned char **p, const unsigned char *start, int val);\n\n/**\n * \\brief           Write a string in ASN.1 format using a specific\n *                  string encoding tag.\n\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param tag       The string encoding tag to write, e.g.\n *                  #MBEDTLS_ASN1_UTF8_STRING.\n * \\param text      The string to write.\n * \\param text_len  The length of \\p text in bytes (which might\n *                  be strictly larger than the number of characters).\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *start,\n                                     int tag, const char *text,\n                                     size_t text_len);\n\n/**\n * \\brief           Write a string in ASN.1 format using the PrintableString\n *                  string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING).\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param text      The string to write.\n * \\param text_len  The length of \\p text in bytes (which might\n *                  be strictly larger than the number of characters).\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_asn1_write_printable_string(unsigned char **p,\n                                        const unsigned char *start,\n                                        const char *text, size_t text_len);\n\n/**\n * \\brief           Write a UTF8 string in ASN.1 format using the UTF8String\n *                  string encoding tag (#MBEDTLS_ASN1_UTF8_STRING).\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param text      The string to write.\n * \\param text_len  The length of \\p text in bytes (which might\n *                  be strictly larger than the number of characters).\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start,\n                                   const char *text, size_t text_len);\n\n/**\n * \\brief           Write a string in ASN.1 format using the IA5String\n *                  string encoding tag (#MBEDTLS_ASN1_IA5_STRING).\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param text      The string to write.\n * \\param text_len  The length of \\p text in bytes (which might\n *                  be strictly larger than the number of characters).\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_asn1_write_ia5_string(unsigned char **p, const unsigned char *start,\n                                  const char *text, size_t text_len);\n\n/**\n * \\brief           Write a bitstring tag (#MBEDTLS_ASN1_BIT_STRING) and\n *                  value in ASN.1 format.\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param buf       The bitstring to write.\n * \\param bits      The total number of bits in the bitstring.\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start,\n                                 const unsigned char *buf, size_t bits);\n\n/**\n * \\brief           This function writes a named bitstring tag\n *                  (#MBEDTLS_ASN1_BIT_STRING) and value in ASN.1 format.\n *\n *                  As stated in RFC 5280 Appendix B, trailing zeroes are\n *                  omitted when encoding named bitstrings in DER.\n *\n * \\note            This function works backwards within the data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer which is used for bounds-checking.\n * \\param buf       The bitstring to write.\n * \\param bits      The total number of bits in the bitstring.\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_asn1_write_named_bitstring(unsigned char **p,\n                                       const unsigned char *start,\n                                       const unsigned char *buf,\n                                       size_t bits);\n\n/**\n * \\brief           Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING)\n *                  and value in ASN.1 format.\n *\n * \\note            This function works backwards in data buffer.\n *\n * \\param p         The reference to the current position pointer.\n * \\param start     The start of the buffer, for bounds-checking.\n * \\param buf       The buffer holding the data to write.\n * \\param size      The length of the data buffer \\p buf.\n *\n * \\return          The number of bytes written to \\p p on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start,\n                                    const unsigned char *buf, size_t size);\n\n/**\n * \\brief           Create or find a specific named_data entry for writing in a\n *                  sequence or list based on the OID. If not already in there,\n *                  a new entry is added to the head of the list.\n *                  Warning: Destructive behaviour for the val data!\n *\n * \\param list      The pointer to the location of the head of the list to seek\n *                  through (will be updated in case of a new entry).\n * \\param oid       The OID to look for.\n * \\param oid_len   The size of the OID.\n * \\param val       The associated data to store. If this is \\c NULL,\n *                  no data is copied to the new or existing buffer.\n * \\param val_len   The minimum length of the data buffer needed.\n *                  If this is 0, do not allocate a buffer for the associated\n *                  data.\n *                  If the OID was already present, enlarge, shrink or free\n *                  the existing buffer to fit \\p val_len.\n *\n * \\return          A pointer to the new / existing entry on success.\n * \\return          \\c NULL if there was a memory allocation error.\n */\nmbedtls_asn1_named_data *mbedtls_asn1_store_named_data(mbedtls_asn1_named_data **list,\n                                                       const char *oid, size_t oid_len,\n                                                       const unsigned char *val,\n                                                       size_t val_len);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_ASN1_WRITE_C */\n\n#endif /* MBEDTLS_ASN1_WRITE_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/base64.h",
    "content": "/**\n * \\file base64.h\n *\n * \\brief RFC 1521 base64 encoding/decoding\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_BASE64_H\n#define MBEDTLS_BASE64_H\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n\n/** Output buffer too small. */\n#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL               -0x002A\n/** Invalid character in input. */\n#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER              -0x002C\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief          Encode a buffer into base64 format\n *\n * \\param dst      destination buffer\n * \\param dlen     size of the destination buffer\n * \\param olen     number of bytes written\n * \\param src      source buffer\n * \\param slen     amount of data to be encoded\n *\n * \\return         0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL.\n *                 *olen is always updated to reflect the amount\n *                 of data that has (or would have) been written.\n *                 If that length cannot be represented, then no data is\n *                 written to the buffer and *olen is set to the maximum\n *                 length representable as a size_t.\n *\n * \\note           Call this function with dlen = 0 to obtain the\n *                 required buffer size in *olen\n */\nint mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen,\n                          const unsigned char *src, size_t slen);\n\n/**\n * \\brief          Decode a base64-formatted buffer\n *\n * \\param dst      destination buffer (can be NULL for checking size)\n * \\param dlen     size of the destination buffer\n * \\param olen     number of bytes written\n * \\param src      source buffer\n * \\param slen     amount of data to be decoded\n *\n * \\return         0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or\n *                 MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is\n *                 not correct. *olen is always updated to reflect the amount\n *                 of data that has (or would have) been written.\n *\n * \\note           Call this function with *dst = NULL or dlen = 0 to obtain\n *                 the required buffer size in *olen\n */\nint mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen,\n                          const unsigned char *src, size_t slen);\n\n#if defined(MBEDTLS_SELF_TEST)\n/**\n * \\brief          Checkup routine\n *\n * \\return         0 if successful, or 1 if the test failed\n */\nint mbedtls_base64_self_test(int verbose);\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* base64.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/bignum.h",
    "content": "/**\n * \\file bignum.h\n *\n * \\brief Multi-precision integer library\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_BIGNUM_H\n#define MBEDTLS_BIGNUM_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n#if defined(MBEDTLS_FS_IO)\n#include <stdio.h>\n#endif\n\n/** An error occurred while reading from or writing to a file. */\n#define MBEDTLS_ERR_MPI_FILE_IO_ERROR                     -0x0002\n/** Bad input parameters to function. */\n#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA                    -0x0004\n/** There is an invalid character in the digit string. */\n#define MBEDTLS_ERR_MPI_INVALID_CHARACTER                 -0x0006\n/** The buffer is too small to write to. */\n#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL                  -0x0008\n/** The input arguments are negative or result in illegal output. */\n#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE                    -0x000A\n/** The input argument for division is zero, which is not allowed. */\n#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO                  -0x000C\n/** The input arguments are not acceptable. */\n#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE                    -0x000E\n/** Memory allocation failed. */\n#define MBEDTLS_ERR_MPI_ALLOC_FAILED                      -0x0010\n\n#define MBEDTLS_MPI_CHK(f)       \\\n    do                           \\\n    {                            \\\n        if ((ret = (f)) != 0) \\\n        goto cleanup;        \\\n    } while (0)\n\n/*\n * Maximum size MPIs are allowed to grow to in number of limbs.\n */\n#define MBEDTLS_MPI_MAX_LIMBS                             10000\n\n#if !defined(MBEDTLS_MPI_WINDOW_SIZE)\n/*\n * Maximum window size used for modular exponentiation. Default: 3\n * Minimum value: 1. Maximum value: 6.\n *\n * Result is an array of ( 2 ** MBEDTLS_MPI_WINDOW_SIZE ) MPIs used\n * for the sliding window calculation. (So 8 by default)\n *\n * Reduction in size, reduces speed.\n */\n#define MBEDTLS_MPI_WINDOW_SIZE                           3        /**< Maximum window size used. */\n#endif /* !MBEDTLS_MPI_WINDOW_SIZE */\n\n#if !defined(MBEDTLS_MPI_MAX_SIZE)\n/*\n * Maximum size of MPIs allowed in bits and bytes for user-MPIs.\n * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits )\n *\n * Note: Calculations can temporarily result in larger MPIs. So the number\n * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher.\n */\n#define MBEDTLS_MPI_MAX_SIZE                              1024     /**< Maximum number of bytes for usable MPIs. */\n#endif /* !MBEDTLS_MPI_MAX_SIZE */\n\n#define MBEDTLS_MPI_MAX_BITS                              (8 * MBEDTLS_MPI_MAX_SIZE)      /**< Maximum number of bits for usable MPIs. */\n\n/*\n * When reading from files with mbedtls_mpi_read_file() and writing to files with\n * mbedtls_mpi_write_file() the buffer should have space\n * for a (short) label, the MPI (in the provided radix), the newline\n * characters and the '\\0'.\n *\n * By default we assume at least a 10 char label, a minimum radix of 10\n * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars).\n * Autosized at compile time for at least a 10 char label, a minimum radix\n * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size.\n *\n * This used to be statically sized to 1250 for a maximum of 4096 bit\n * numbers (1234 decimal chars).\n *\n * Calculate using the formula:\n *  MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) +\n *                                LabelSize + 6\n */\n#define MBEDTLS_MPI_MAX_BITS_SCALE100          (100 * MBEDTLS_MPI_MAX_BITS)\n#define MBEDTLS_LN_2_DIV_LN_10_SCALE100                 332\n#define MBEDTLS_MPI_RW_BUFFER_SIZE             (((MBEDTLS_MPI_MAX_BITS_SCALE100 + \\\n                                                  MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / \\\n                                                 MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6)\n\n/*\n * Define the base integer type, architecture-wise.\n *\n * 32 or 64-bit integer types can be forced regardless of the underlying\n * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64\n * respectively and undefining MBEDTLS_HAVE_ASM.\n *\n * Double-width integers (e.g. 128-bit in 64-bit architectures) can be\n * disabled by defining MBEDTLS_NO_UDBL_DIVISION.\n */\n#if !defined(MBEDTLS_HAVE_INT32)\n    #if defined(_MSC_VER) && defined(_M_AMD64)\n/* Always choose 64-bit when using MSC */\n        #if !defined(MBEDTLS_HAVE_INT64)\n            #define MBEDTLS_HAVE_INT64\n        #endif /* !MBEDTLS_HAVE_INT64 */\ntypedef  int64_t mbedtls_mpi_sint;\ntypedef uint64_t mbedtls_mpi_uint;\n#define MBEDTLS_MPI_UINT_MAX                UINT64_MAX\n    #elif defined(__GNUC__) && (                         \\\n    defined(__amd64__) || defined(__x86_64__)     || \\\n    defined(__ppc64__) || defined(__powerpc64__)  || \\\n    defined(__ia64__)  || defined(__alpha__)      || \\\n    (defined(__sparc__) && defined(__arch64__)) || \\\n    defined(__s390x__) || defined(__mips64)       || \\\n    defined(__aarch64__))\n        #if !defined(MBEDTLS_HAVE_INT64)\n            #define MBEDTLS_HAVE_INT64\n        #endif /* MBEDTLS_HAVE_INT64 */\ntypedef  int64_t mbedtls_mpi_sint;\ntypedef uint64_t mbedtls_mpi_uint;\n#define MBEDTLS_MPI_UINT_MAX                UINT64_MAX\n        #if !defined(MBEDTLS_NO_UDBL_DIVISION)\n/* mbedtls_t_udbl defined as 128-bit unsigned int */\ntypedef unsigned int mbedtls_t_udbl __attribute__((mode(TI)));\n            #define MBEDTLS_HAVE_UDBL\n        #endif /* !MBEDTLS_NO_UDBL_DIVISION */\n    #elif defined(__ARMCC_VERSION) && defined(__aarch64__)\n/*\n * __ARMCC_VERSION is defined for both armcc and armclang and\n * __aarch64__ is only defined by armclang when compiling 64-bit code\n */\n        #if !defined(MBEDTLS_HAVE_INT64)\n            #define MBEDTLS_HAVE_INT64\n        #endif /* !MBEDTLS_HAVE_INT64 */\ntypedef  int64_t mbedtls_mpi_sint;\ntypedef uint64_t mbedtls_mpi_uint;\n#define MBEDTLS_MPI_UINT_MAX                UINT64_MAX\n        #if !defined(MBEDTLS_NO_UDBL_DIVISION)\n/* mbedtls_t_udbl defined as 128-bit unsigned int */\ntypedef __uint128_t mbedtls_t_udbl;\n            #define MBEDTLS_HAVE_UDBL\n        #endif /* !MBEDTLS_NO_UDBL_DIVISION */\n    #elif defined(MBEDTLS_HAVE_INT64)\n/* Force 64-bit integers with unknown compiler */\ntypedef  int64_t mbedtls_mpi_sint;\ntypedef uint64_t mbedtls_mpi_uint;\n#define MBEDTLS_MPI_UINT_MAX                UINT64_MAX\n    #endif\n#endif /* !MBEDTLS_HAVE_INT32 */\n\n#if !defined(MBEDTLS_HAVE_INT64)\n/* Default to 32-bit compilation */\n    #if !defined(MBEDTLS_HAVE_INT32)\n        #define MBEDTLS_HAVE_INT32\n    #endif /* !MBEDTLS_HAVE_INT32 */\ntypedef  int32_t mbedtls_mpi_sint;\ntypedef uint32_t mbedtls_mpi_uint;\n#define MBEDTLS_MPI_UINT_MAX                UINT32_MAX\n    #if !defined(MBEDTLS_NO_UDBL_DIVISION)\ntypedef uint64_t mbedtls_t_udbl;\n        #define MBEDTLS_HAVE_UDBL\n    #endif /* !MBEDTLS_NO_UDBL_DIVISION */\n#endif /* !MBEDTLS_HAVE_INT64 */\n\n/*\n * Sanity check that exactly one of MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 is defined,\n * so that code elsewhere doesn't have to check.\n */\n#if (!(defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64))) || \\\n    (defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64))\n#error \"Only 32-bit or 64-bit limbs are supported in bignum\"\n#endif\n\n/** \\typedef mbedtls_mpi_uint\n * \\brief The type of machine digits in a bignum, called _limbs_.\n *\n * This is always an unsigned integer type with no padding bits. The size\n * is platform-dependent.\n */\n\n/** \\typedef mbedtls_mpi_sint\n * \\brief The signed type corresponding to #mbedtls_mpi_uint.\n *\n * This is always an signed integer type with no padding bits. The size\n * is platform-dependent.\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief          MPI structure\n */\ntypedef struct mbedtls_mpi {\n    /** Pointer to limbs.\n     *\n     * This may be \\c NULL if \\c n is 0.\n     */\n    mbedtls_mpi_uint *MBEDTLS_PRIVATE(p);\n\n    /** Sign: -1 if the mpi is negative, 1 otherwise.\n     *\n     * The number 0 must be represented with `s = +1`. Although many library\n     * functions treat all-limbs-zero as equivalent to a valid representation\n     * of 0 regardless of the sign bit, there are exceptions, so bignum\n     * functions and external callers must always set \\c s to +1 for the\n     * number zero.\n     *\n     * Note that this implies that calloc() or `... = {0}` does not create\n     * a valid MPI representation. You must call mbedtls_mpi_init().\n     */\n    signed short MBEDTLS_PRIVATE(s);\n\n    /** Total number of limbs in \\c p.  */\n    unsigned short MBEDTLS_PRIVATE(n);\n    /* Make sure that MBEDTLS_MPI_MAX_LIMBS fits in n.\n     * Use the same limit value on all platforms so that we don't have to\n     * think about different behavior on the rare platforms where\n     * unsigned short can store values larger than the minimum required by\n     * the C language, which is 65535.\n     */\n#if MBEDTLS_MPI_MAX_LIMBS > 65535\n#error \"MBEDTLS_MPI_MAX_LIMBS > 65535 is not supported\"\n#endif\n}\nmbedtls_mpi;\n\n/**\n * \\brief           Initialize an MPI context.\n *\n *                  This makes the MPI ready to be set or freed,\n *                  but does not define a value for the MPI.\n *\n * \\param X         The MPI context to initialize. This must not be \\c NULL.\n */\nvoid mbedtls_mpi_init(mbedtls_mpi *X);\n\n/**\n * \\brief          This function frees the components of an MPI context.\n *\n * \\param X        The MPI context to be cleared. This may be \\c NULL,\n *                 in which case this function is a no-op. If it is\n *                 not \\c NULL, it must point to an initialized MPI.\n */\nvoid mbedtls_mpi_free(mbedtls_mpi *X);\n\n/**\n * \\brief          Enlarge an MPI to the specified number of limbs.\n *\n * \\note           This function does nothing if the MPI is\n *                 already large enough.\n *\n * \\param X        The MPI to grow. It must be initialized.\n * \\param nblimbs  The target number of limbs.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.\n * \\return         Another negative error code on other kinds of failure.\n */\nint mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs);\n\n/**\n * \\brief          This function resizes an MPI downwards, keeping at least the\n *                 specified number of limbs.\n *\n *                 If \\c X is smaller than \\c nblimbs, it is resized up\n *                 instead.\n *\n * \\param X        The MPI to shrink. This must point to an initialized MPI.\n * \\param nblimbs  The minimum number of limbs to keep.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed\n *                 (this can only happen when resizing up).\n * \\return         Another negative error code on other kinds of failure.\n */\nint mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs);\n\n/**\n * \\brief          Make a copy of an MPI.\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n * \\param Y        The source MPI. This must point to an initialized MPI.\n *\n * \\note           The limb-buffer in the destination MPI is enlarged\n *                 if necessary to hold the value in the source MPI.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.\n * \\return         Another negative error code on other kinds of failure.\n */\nint mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y);\n\n/**\n * \\brief          Swap the contents of two MPIs.\n *\n * \\param X        The first MPI. It must be initialized.\n * \\param Y        The second MPI. It must be initialized.\n */\nvoid mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y);\n\n/**\n * \\brief          Perform a safe conditional copy of MPI which doesn't\n *                 reveal whether the condition was true or not.\n *\n * \\param X        The MPI to conditionally assign to. This must point\n *                 to an initialized MPI.\n * \\param Y        The MPI to be assigned from. This must point to an\n *                 initialized MPI.\n * \\param assign   The condition deciding whether to perform the\n *                 assignment or not. Must be either 0 or 1:\n *                 * \\c 1: Perform the assignment `X = Y`.\n *                 * \\c 0: Keep the original value of \\p X.\n *\n * \\note           This function is equivalent to\n *                      `if( assign ) mbedtls_mpi_copy( X, Y );`\n *                 except that it avoids leaking any information about whether\n *                 the assignment was done or not (the above code may leak\n *                 information through branch prediction and/or memory access\n *                 patterns analysis).\n *\n * \\warning        If \\p assign is neither 0 nor 1, the result of this function\n *                 is indeterminate, and the resulting value in \\p X might be\n *                 neither its original value nor the value in \\p Y.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.\n * \\return         Another negative error code on other kinds of failure.\n */\nint mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign);\n\n/**\n * \\brief          Perform a safe conditional swap which doesn't\n *                 reveal whether the condition was true or not.\n *\n * \\param X        The first MPI. This must be initialized.\n * \\param Y        The second MPI. This must be initialized.\n * \\param swap     The condition deciding whether to perform\n *                 the swap or not. Must be either 0 or 1:\n *                 * \\c 1: Swap the values of \\p X and \\p Y.\n *                 * \\c 0: Keep the original values of \\p X and \\p Y.\n *\n * \\note           This function is equivalent to\n *                      if( swap ) mbedtls_mpi_swap( X, Y );\n *                 except that it avoids leaking any information about whether\n *                 the swap was done or not (the above code may leak\n *                 information through branch prediction and/or memory access\n *                 patterns analysis).\n *\n * \\warning        If \\p swap is neither 0 nor 1, the result of this function\n *                 is indeterminate, and both \\p X and \\p Y might end up with\n *                 values different to either of the original ones.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.\n * \\return         Another negative error code on other kinds of failure.\n *\n */\nint mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap);\n\n/**\n * \\brief          Store integer value in MPI.\n *\n * \\param X        The MPI to set. This must be initialized.\n * \\param z        The value to use.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.\n * \\return         Another negative error code on other kinds of failure.\n */\nint mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z);\n\n/**\n * \\brief          Get a specific bit from an MPI.\n *\n * \\param X        The MPI to query. This must be initialized.\n * \\param pos      Zero-based index of the bit to query.\n *\n * \\return         \\c 0 or \\c 1 on success, depending on whether bit \\c pos\n *                 of \\c X is unset or set.\n * \\return         A negative error code on failure.\n */\nint mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos);\n\n/**\n * \\brief          Modify a specific bit in an MPI.\n *\n * \\note           This function will grow the target MPI if necessary to set a\n *                 bit to \\c 1 in a not yet existing limb. It will not grow if\n *                 the bit should be set to \\c 0.\n *\n * \\param X        The MPI to modify. This must be initialized.\n * \\param pos      Zero-based index of the bit to modify.\n * \\param val      The desired value of bit \\c pos: \\c 0 or \\c 1.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.\n * \\return         Another negative error code on other kinds of failure.\n */\nint mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val);\n\n/**\n * \\brief          Return the number of bits of value \\c 0 before the\n *                 least significant bit of value \\c 1.\n *\n * \\note           This is the same as the zero-based index of\n *                 the least significant bit of value \\c 1.\n *\n * \\param X        The MPI to query.\n *\n * \\return         The number of bits of value \\c 0 before the least significant\n *                 bit of value \\c 1 in \\p X.\n */\nsize_t mbedtls_mpi_lsb(const mbedtls_mpi *X);\n\n/**\n * \\brief          Return the number of bits up to and including the most\n *                 significant bit of value \\c 1.\n *\n * * \\note         This is same as the one-based index of the most\n *                 significant bit of value \\c 1.\n *\n * \\param X        The MPI to query. This must point to an initialized MPI.\n *\n * \\return         The number of bits up to and including the most\n *                 significant bit of value \\c 1.\n */\nsize_t mbedtls_mpi_bitlen(const mbedtls_mpi *X);\n\n/**\n * \\brief          Return the total size of an MPI value in bytes.\n *\n * \\param X        The MPI to use. This must point to an initialized MPI.\n *\n * \\note           The value returned by this function may be less than\n *                 the number of bytes used to store \\p X internally.\n *                 This happens if and only if there are trailing bytes\n *                 of value zero.\n *\n * \\return         The least number of bytes capable of storing\n *                 the absolute value of \\p X.\n */\nsize_t mbedtls_mpi_size(const mbedtls_mpi *X);\n\n/**\n * \\brief          Import an MPI from an ASCII string.\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n * \\param radix    The numeric base of the input string.\n * \\param s        Null-terminated string buffer.\n *\n * \\return         \\c 0 if successful.\n * \\return         A negative error code on failure.\n */\nint mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s);\n\n/**\n * \\brief          Export an MPI to an ASCII string.\n *\n * \\param X        The source MPI. This must point to an initialized MPI.\n * \\param radix    The numeric base of the output string.\n * \\param buf      The buffer to write the string to. This must be writable\n *                 buffer of length \\p buflen Bytes.\n * \\param buflen   The available size in Bytes of \\p buf.\n * \\param olen     The address at which to store the length of the string\n *                 written, including the  final \\c NULL byte. This must\n *                 not be \\c NULL.\n *\n * \\note           You can call this function with `buflen == 0` to obtain the\n *                 minimum required buffer size in `*olen`.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the target buffer \\p buf\n *                 is too small to hold the value of \\p X in the desired base.\n *                 In this case, `*olen` is nonetheless updated to contain the\n *                 size of \\p buf required for a successful call.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,\n                             char *buf, size_t buflen, size_t *olen);\n\n#if defined(MBEDTLS_FS_IO)\n/**\n * \\brief          Read an MPI from a line in an opened file.\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n * \\param radix    The numeric base of the string representation used\n *                 in the source line.\n * \\param fin      The input file handle to use. This must not be \\c NULL.\n *\n * \\note           On success, this function advances the file stream\n *                 to the end of the current line or to EOF.\n *\n *                 The function returns \\c 0 on an empty line.\n *\n *                 Leading whitespaces are ignored, as is a\n *                 '0x' prefix for radix \\c 16.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the file read buffer\n *                 is too small.\n * \\return         Another negative error code on failure.\n */\nint mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin);\n\n/**\n * \\brief          Export an MPI into an opened file.\n *\n * \\param p        A string prefix to emit prior to the MPI data.\n *                 For example, this might be a label, or \"0x\" when\n *                 printing in base \\c 16. This may be \\c NULL if no prefix\n *                 is needed.\n * \\param X        The source MPI. This must point to an initialized MPI.\n * \\param radix    The numeric base to be used in the emitted string.\n * \\param fout     The output file handle. This may be \\c NULL, in which case\n *                 the output is written to \\c stdout.\n *\n * \\return         \\c 0 if successful.\n * \\return         A negative error code on failure.\n */\nint mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X,\n                           int radix, FILE *fout);\n#endif /* MBEDTLS_FS_IO */\n\n/**\n * \\brief          Import an MPI from unsigned big endian binary data.\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n * \\param buf      The input buffer. This must be a readable buffer of length\n *                 \\p buflen Bytes.\n * \\param buflen   The length of the input buffer \\p buf in Bytes.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf,\n                            size_t buflen);\n\n/**\n * \\brief          Import X from unsigned binary data, little endian\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n * \\param buf      The input buffer. This must be a readable buffer of length\n *                 \\p buflen Bytes.\n * \\param buflen   The length of the input buffer \\p buf in Bytes.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_read_binary_le(mbedtls_mpi *X,\n                               const unsigned char *buf, size_t buflen);\n\n/**\n * \\brief          Export X into unsigned binary data, big endian.\n *                 Always fills the whole buffer, which will start with zeros\n *                 if the number is smaller.\n *\n * \\param X        The source MPI. This must point to an initialized MPI.\n * \\param buf      The output buffer. This must be a writable buffer of length\n *                 \\p buflen Bytes.\n * \\param buflen   The size of the output buffer \\p buf in Bytes.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \\p buf isn't\n *                 large enough to hold the value of \\p X.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_write_binary(const mbedtls_mpi *X, unsigned char *buf,\n                             size_t buflen);\n\n/**\n * \\brief          Export X into unsigned binary data, little endian.\n *                 Always fills the whole buffer, which will end with zeros\n *                 if the number is smaller.\n *\n * \\param X        The source MPI. This must point to an initialized MPI.\n * \\param buf      The output buffer. This must be a writable buffer of length\n *                 \\p buflen Bytes.\n * \\param buflen   The size of the output buffer \\p buf in Bytes.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \\p buf isn't\n *                 large enough to hold the value of \\p X.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,\n                                unsigned char *buf, size_t buflen);\n\n/**\n * \\brief          Perform a left-shift on an MPI: X <<= count\n *\n * \\param X        The MPI to shift. This must point to an initialized MPI.\n *                 The MPI pointed by \\p X may be resized to fit\n *                 the resulting number.\n * \\param count    The number of bits to shift by.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count);\n\n/**\n * \\brief          Perform a right-shift on an MPI: X >>= count\n *\n * \\param X        The MPI to shift. This must point to an initialized MPI.\n * \\param count    The number of bits to shift by.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count);\n\n/**\n * \\brief          Compare the absolute values of two MPIs.\n *\n * \\param X        The left-hand MPI. This must point to an initialized MPI.\n * \\param Y        The right-hand MPI. This must point to an initialized MPI.\n *\n * \\return         \\c 1 if `|X|` is greater than `|Y|`.\n * \\return         \\c -1 if `|X|` is lesser than `|Y|`.\n * \\return         \\c 0 if `|X|` is equal to `|Y|`.\n */\nint mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y);\n\n/**\n * \\brief          Compare two MPIs.\n *\n * \\param X        The left-hand MPI. This must point to an initialized MPI.\n * \\param Y        The right-hand MPI. This must point to an initialized MPI.\n *\n * \\return         \\c 1 if \\p X is greater than \\p Y.\n * \\return         \\c -1 if \\p X is lesser than \\p Y.\n * \\return         \\c 0 if \\p X is equal to \\p Y.\n */\nint mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y);\n\n/**\n * \\brief          Check if an MPI is less than the other in constant time.\n *\n * \\param X        The left-hand MPI. This must point to an initialized MPI\n *                 with the same allocated length as Y.\n * \\param Y        The right-hand MPI. This must point to an initialized MPI\n *                 with the same allocated length as X.\n * \\param ret      The result of the comparison:\n *                 \\c 1 if \\p X is less than \\p Y.\n *                 \\c 0 if \\p X is greater than or equal to \\p Y.\n *\n * \\return         0 on success.\n * \\return         MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the allocated length of\n *                 the two input MPIs is not the same.\n */\nint mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X, const mbedtls_mpi *Y,\n                          unsigned *ret);\n\n/**\n * \\brief          Compare an MPI with an integer.\n *\n * \\param X        The left-hand MPI. This must point to an initialized MPI.\n * \\param z        The integer value to compare \\p X to.\n *\n * \\return         \\c 1 if \\p X is greater than \\p z.\n * \\return         \\c -1 if \\p X is lesser than \\p z.\n * \\return         \\c 0 if \\p X is equal to \\p z.\n */\nint mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z);\n\n/**\n * \\brief          Perform an unsigned addition of MPIs: X = |A| + |B|\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n * \\param A        The first summand. This must point to an initialized MPI.\n * \\param B        The second summand. This must point to an initialized MPI.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A,\n                        const mbedtls_mpi *B);\n\n/**\n * \\brief          Perform an unsigned subtraction of MPIs: X = |A| - |B|\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n * \\param A        The minuend. This must point to an initialized MPI.\n * \\param B        The subtrahend. This must point to an initialized MPI.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \\p B is greater than \\p A.\n * \\return         Another negative error code on different kinds of failure.\n *\n */\nint mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A,\n                        const mbedtls_mpi *B);\n\n/**\n * \\brief          Perform a signed addition of MPIs: X = A + B\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n * \\param A        The first summand. This must point to an initialized MPI.\n * \\param B        The second summand. This must point to an initialized MPI.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A,\n                        const mbedtls_mpi *B);\n\n/**\n * \\brief          Perform a signed subtraction of MPIs: X = A - B\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n * \\param A        The minuend. This must point to an initialized MPI.\n * \\param B        The subtrahend. This must point to an initialized MPI.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A,\n                        const mbedtls_mpi *B);\n\n/**\n * \\brief          Perform a signed addition of an MPI and an integer: X = A + b\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n * \\param A        The first summand. This must point to an initialized MPI.\n * \\param b        The second summand.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A,\n                        mbedtls_mpi_sint b);\n\n/**\n * \\brief          Perform a signed subtraction of an MPI and an integer:\n *                 X = A - b\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n * \\param A        The minuend. This must point to an initialized MPI.\n * \\param b        The subtrahend.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A,\n                        mbedtls_mpi_sint b);\n\n/**\n * \\brief          Perform a multiplication of two MPIs: X = A * B\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n * \\param A        The first factor. This must point to an initialized MPI.\n * \\param B        The second factor. This must point to an initialized MPI.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         Another negative error code on different kinds of failure.\n *\n */\nint mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A,\n                        const mbedtls_mpi *B);\n\n/**\n * \\brief          Perform a multiplication of an MPI with an unsigned integer:\n *                 X = A * b\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n * \\param A        The first factor. This must point to an initialized MPI.\n * \\param b        The second factor.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         Another negative error code on different kinds of failure.\n *\n */\nint mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A,\n                        mbedtls_mpi_uint b);\n\n/**\n * \\brief          Perform a division with remainder of two MPIs:\n *                 A = Q * B + R\n *\n * \\param Q        The destination MPI for the quotient.\n *                 This may be \\c NULL if the value of the\n *                 quotient is not needed. This must not alias A or B.\n * \\param R        The destination MPI for the remainder value.\n *                 This may be \\c NULL if the value of the\n *                 remainder is not needed. This must not alias A or B.\n * \\param A        The dividend. This must point to an initialized MPI.\n * \\param B        The divisor. This must point to an initialized MPI.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.\n * \\return         #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \\p B equals zero.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,\n                        const mbedtls_mpi *B);\n\n/**\n * \\brief          Perform a division with remainder of an MPI by an integer:\n *                 A = Q * b + R\n *\n * \\param Q        The destination MPI for the quotient.\n *                 This may be \\c NULL if the value of the\n *                 quotient is not needed.  This must not alias A.\n * \\param R        The destination MPI for the remainder value.\n *                 This may be \\c NULL if the value of the\n *                 remainder is not needed.  This must not alias A.\n * \\param A        The dividend. This must point to an initialized MPi.\n * \\param b        The divisor.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.\n * \\return         #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \\p b equals zero.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,\n                        mbedtls_mpi_sint b);\n\n/**\n * \\brief          Perform a modular reduction. R = A mod B\n *\n * \\param R        The destination MPI for the residue value.\n *                 This must point to an initialized MPI.\n * \\param A        The MPI to compute the residue of.\n *                 This must point to an initialized MPI.\n * \\param B        The base of the modular reduction.\n *                 This must point to an initialized MPI.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \\p B equals zero.\n * \\return         #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \\p B is negative.\n * \\return         Another negative error code on different kinds of failure.\n *\n */\nint mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A,\n                        const mbedtls_mpi *B);\n\n/**\n * \\brief          Perform a modular reduction with respect to an integer.\n *                 r = A mod b\n *\n * \\param r        The address at which to store the residue.\n *                 This must not be \\c NULL.\n * \\param A        The MPI to compute the residue of.\n *                 This must point to an initialized MPi.\n * \\param b        The integer base of the modular reduction.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \\p b equals zero.\n * \\return         #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \\p b is negative.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A,\n                        mbedtls_mpi_sint b);\n\n/**\n * \\brief          Perform a modular exponentiation: X = A^E mod N\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n *                 This must not alias E or N.\n * \\param A        The base of the exponentiation.\n *                 This must point to an initialized MPI.\n * \\param E        The exponent MPI. This must point to an initialized MPI.\n * \\param N        The base for the modular reduction. This must point to an\n *                 initialized MPI.\n * \\param prec_RR  A helper MPI depending solely on \\p N which can be used to\n *                 speed-up multiple modular exponentiations for the same value\n *                 of \\p N. This may be \\c NULL. If it is not \\c NULL, it must\n *                 point to an initialized MPI. If it hasn't been used after\n *                 the call to mbedtls_mpi_init(), this function will compute\n *                 the helper value and store it in \\p prec_RR for reuse on\n *                 subsequent calls to this function. Otherwise, the function\n *                 will assume that \\p prec_RR holds the helper value set by a\n *                 previous call to mbedtls_mpi_exp_mod(), and reuse it.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \\c N is negative or\n *                 even, or if \\c E is negative.\n * \\return         Another negative error code on different kinds of failures.\n *\n */\nint mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,\n                        const mbedtls_mpi *E, const mbedtls_mpi *N,\n                        mbedtls_mpi *prec_RR);\n\n/**\n * \\brief          Fill an MPI with a number of random bytes.\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n * \\param size     The number of random bytes to generate.\n * \\param f_rng    The RNG function to use. This must not be \\c NULL.\n * \\param p_rng    The RNG parameter to be passed to \\p f_rng. This may be\n *                 \\c NULL if \\p f_rng doesn't need a context argument.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         Another negative error code on failure.\n *\n * \\note           The bytes obtained from the RNG are interpreted\n *                 as a big-endian representation of an MPI; this can\n *                 be relevant in applications like deterministic ECDSA.\n */\nint mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,\n                            mbedtls_f_rng_t *f_rng,\n                            void *p_rng);\n\n/** Generate a random number uniformly in a range.\n *\n * This function generates a random number between \\p min inclusive and\n * \\p N exclusive.\n *\n * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)\n * when the RNG is a suitably parametrized instance of HMAC_DRBG\n * and \\p min is \\c 1.\n *\n * \\note           There are `N - min` possible outputs. The lower bound\n *                 \\p min can be reached, but the upper bound \\p N cannot.\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n * \\param min      The minimum value to return.\n *                 It must be nonnegative.\n * \\param N        The upper bound of the range, exclusive.\n *                 In other words, this is one plus the maximum value to return.\n *                 \\p N must be strictly larger than \\p min.\n * \\param f_rng    The RNG function to use. This must not be \\c NULL.\n * \\param p_rng    The RNG parameter to be passed to \\p f_rng.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \\p min or \\p N is invalid\n *                 or if they are incompatible.\n * \\return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was\n *                 unable to find a suitable value within a limited number\n *                 of attempts. This has a negligible probability if \\p N\n *                 is significantly larger than \\p min, which is the case\n *                 for all usual cryptographic applications.\n * \\return         Another negative error code on failure.\n */\nint mbedtls_mpi_random(mbedtls_mpi *X,\n                       mbedtls_mpi_sint min,\n                       const mbedtls_mpi *N,\n                       mbedtls_f_rng_t *f_rng,\n                       void *p_rng);\n\n/**\n * \\brief          Compute the greatest common divisor: G = gcd(A, B)\n *\n * \\param G        The destination MPI. This must point to an initialized MPI.\n *                 This will always be positive or 0.\n * \\param A        The first operand. This must point to an initialized MPI.\n * \\param B        The second operand. This must point to an initialized MPI.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         Another negative error code on different kinds of failure.\n */\nint mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A,\n                    const mbedtls_mpi *B);\n\n/**\n * \\brief          Compute the modular inverse: X = A^-1 mod N\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n *                 The value returned on success will be between [1, N-1].\n * \\param A        The MPI to calculate the modular inverse of. This must point\n *                 to an initialized MPI. This value can be negative, in which\n *                 case a positive answer will still be returned in \\p X.\n * \\param N        The base of the modular inversion. This must point to an\n *                 initialized MPI and be greater than one.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \\p N is less than\n *                 or equal to one.\n * \\return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \\p A has no modular\n *                 inverse with respect to \\p N.\n */\nint mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A,\n                        const mbedtls_mpi *N);\n\n/**\n * \\brief          Miller-Rabin primality test.\n *\n * \\warning        If \\p X is potentially generated by an adversary, for example\n *                 when validating cryptographic parameters that you didn't\n *                 generate yourself and that are supposed to be prime, then\n *                 \\p rounds should be at least the half of the security\n *                 strength of the cryptographic algorithm. On the other hand,\n *                 if \\p X is chosen uniformly or non-adversarially (as is the\n *                 case when mbedtls_mpi_gen_prime calls this function), then\n *                 \\p rounds can be much lower.\n *\n * \\param X        The MPI to check for primality.\n *                 This must point to an initialized MPI.\n * \\param rounds   The number of bases to perform the Miller-Rabin primality\n *                 test for. The probability of returning 0 on a composite is\n *                 at most 2<sup>-2*\\p rounds </sup>.\n * \\param f_rng    The RNG function to use. This must not be \\c NULL.\n * \\param p_rng    The RNG parameter to be passed to \\p f_rng.\n *                 This may be \\c NULL if \\p f_rng doesn't use\n *                 a context parameter.\n *\n * \\return         \\c 0 if successful, i.e. \\p X is probably prime.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \\p X is not prime.\n * \\return         Another negative error code on other kinds of failure.\n */\nint mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,\n                             mbedtls_f_rng_t *f_rng,\n                             void *p_rng);\n/**\n * \\brief Flags for mbedtls_mpi_gen_prime()\n *\n * Each of these flags is a constraint on the result X returned by\n * mbedtls_mpi_gen_prime().\n */\ntypedef enum {\n    MBEDTLS_MPI_GEN_PRIME_FLAG_DH =      0x0001, /**< (X-1)/2 is prime too */\n    MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR = 0x0002, /**< lower error rate from 2<sup>-80</sup> to 2<sup>-128</sup> */\n} mbedtls_mpi_gen_prime_flag_t;\n\n/**\n * \\brief          Generate a prime number.\n *\n * \\param X        The destination MPI to store the generated prime in.\n *                 This must point to an initialized MPi.\n * \\param nbits    The required size of the destination MPI in bits.\n *                 This must be between \\c 3 and #MBEDTLS_MPI_MAX_BITS.\n * \\param flags    A mask of flags of type #mbedtls_mpi_gen_prime_flag_t.\n * \\param f_rng    The RNG function to use. This must not be \\c NULL.\n * \\param p_rng    The RNG parameter to be passed to \\p f_rng.\n *                 This may be \\c NULL if \\p f_rng doesn't use\n *                 a context parameter.\n *\n * \\return         \\c 0 if successful, in which case \\p X holds a\n *                 probably prime number.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if `nbits` is not between\n *                 \\c 3 and #MBEDTLS_MPI_MAX_BITS.\n */\nint mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,\n                          mbedtls_f_rng_t *f_rng,\n                          void *p_rng);\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/**\n * \\brief          Checkup routine\n *\n * \\return         0 if successful, or 1 if the test failed\n */\nint mbedtls_mpi_self_test(int verbose);\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* bignum.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/block_cipher.h",
    "content": "/**\n * \\file block_cipher.h\n *\n * \\brief Internal abstraction layer.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_BLOCK_CIPHER_H\n#define MBEDTLS_BLOCK_CIPHER_H\n\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#if defined(MBEDTLS_AES_C)\n#include \"mbedtls/aes.h\"\n#endif\n#if defined(MBEDTLS_ARIA_C)\n#include \"mbedtls/aria.h\"\n#endif\n#if defined(MBEDTLS_CAMELLIA_C)\n#include \"mbedtls/camellia.h\"\n#endif\n\n#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)\n#include \"psa/crypto_types.h\"\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef enum {\n    MBEDTLS_BLOCK_CIPHER_ID_NONE = 0,  /**< Unset. */\n    MBEDTLS_BLOCK_CIPHER_ID_AES,       /**< The AES cipher. */\n    MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA,  /**< The Camellia cipher. */\n    MBEDTLS_BLOCK_CIPHER_ID_ARIA,      /**< The Aria cipher. */\n} mbedtls_block_cipher_id_t;\n\n/**\n * Used internally to indicate whether a context uses legacy or PSA.\n *\n * Internal use only.\n */\ntypedef enum {\n    MBEDTLS_BLOCK_CIPHER_ENGINE_LEGACY = 0,\n    MBEDTLS_BLOCK_CIPHER_ENGINE_PSA,\n} mbedtls_block_cipher_engine_t;\n\ntypedef struct {\n    mbedtls_block_cipher_id_t MBEDTLS_PRIVATE(id);\n#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)\n    mbedtls_block_cipher_engine_t MBEDTLS_PRIVATE(engine);\n    mbedtls_svc_key_id_t MBEDTLS_PRIVATE(psa_key_id);\n#endif\n    union {\n        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */\n#if defined(MBEDTLS_AES_C)\n        mbedtls_aes_context MBEDTLS_PRIVATE(aes);\n#endif\n#if defined(MBEDTLS_ARIA_C)\n        mbedtls_aria_context MBEDTLS_PRIVATE(aria);\n#endif\n#if defined(MBEDTLS_CAMELLIA_C)\n        mbedtls_camellia_context MBEDTLS_PRIVATE(camellia);\n#endif\n    } MBEDTLS_PRIVATE(ctx);\n} mbedtls_block_cipher_context_t;\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_BLOCK_CIPHER_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/build_info.h",
    "content": "/**\n * \\file mbedtls/build_info.h\n *\n * \\brief Build-time configuration info\n *\n *  Include this file if you need to depend on the\n *  configuration options defined in mbedtls_config.h or MBEDTLS_CONFIG_FILE\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_BUILD_INFO_H\n#define MBEDTLS_BUILD_INFO_H\n\n/*\n * This set of compile-time defines can be used to determine the version number\n * of the Mbed TLS library used. Run-time variables for the same can be found in\n * version.h\n */\n\n/**\n * The version number x.y.z is split into three parts.\n * Major, Minor, Patchlevel\n */\n#define MBEDTLS_VERSION_MAJOR  3\n#define MBEDTLS_VERSION_MINOR  6\n#define MBEDTLS_VERSION_PATCH  5\n\n/**\n * The single version number has the following structure:\n *    MMNNPP00\n *    Major version | Minor version | Patch version\n */\n#define MBEDTLS_VERSION_NUMBER         0x03060500\n#define MBEDTLS_VERSION_STRING         \"3.6.5\"\n#define MBEDTLS_VERSION_STRING_FULL    \"Mbed TLS 3.6.5\"\n\n/* Macros for build-time platform detection */\n\n#if !defined(MBEDTLS_ARCH_IS_ARM64) && \\\n    (defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC))\n#define MBEDTLS_ARCH_IS_ARM64\n#endif\n\n#if !defined(MBEDTLS_ARCH_IS_ARM32) && \\\n    (defined(__arm__) || defined(_M_ARM) || \\\n    defined(_M_ARMT) || defined(__thumb__) || defined(__thumb2__))\n#define MBEDTLS_ARCH_IS_ARM32\n#endif\n\n#if !defined(MBEDTLS_ARCH_IS_X64) && \\\n    (defined(__amd64__) || defined(__x86_64__) || \\\n    ((defined(_M_X64) || defined(_M_AMD64)) && !defined(_M_ARM64EC)))\n#define MBEDTLS_ARCH_IS_X64\n#endif\n\n#if !defined(MBEDTLS_ARCH_IS_X86) && \\\n    (defined(__i386__) || defined(_X86_) || \\\n    (defined(_M_IX86) && !defined(_M_I86)))\n#define MBEDTLS_ARCH_IS_X86\n#endif\n\n#if !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \\\n    (defined(_M_ARM64) || defined(_M_ARM64EC))\n#define MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64\n#endif\n\n/* This is defined if the architecture is Armv8-A, or higher */\n#if !defined(MBEDTLS_ARCH_IS_ARMV8_A)\n#if defined(__ARM_ARCH) && defined(__ARM_ARCH_PROFILE)\n#if (__ARM_ARCH >= 8) && (__ARM_ARCH_PROFILE == 'A')\n/* GCC, clang, armclang and IAR */\n#define MBEDTLS_ARCH_IS_ARMV8_A\n#endif\n#elif defined(__ARM_ARCH_8A)\n/* Alternative defined by clang */\n#define MBEDTLS_ARCH_IS_ARMV8_A\n#elif defined(_M_ARM64) || defined(_M_ARM64EC)\n/* MSVC ARM64 is at least Armv8.0-A */\n#define MBEDTLS_ARCH_IS_ARMV8_A\n#endif\n#endif\n\n#if defined(__GNUC__) && !defined(__ARMCC_VERSION) && !defined(__clang__) \\\n    && !defined(__llvm__) && !defined(__INTEL_COMPILER)\n/* Defined if the compiler really is gcc and not clang, etc */\n#define MBEDTLS_COMPILER_IS_GCC\n#define MBEDTLS_GCC_VERSION \\\n    (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)\n#endif\n\n#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)\n#define _CRT_SECURE_NO_DEPRECATE 1\n#endif\n\n/* Define `inline` on some non-C99-compliant compilers. */\n#if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && \\\n    !defined(inline) && !defined(__cplusplus)\n#define inline __inline\n#endif\n\n#if defined(MBEDTLS_CONFIG_FILES_READ)\n#error \"Something went wrong: MBEDTLS_CONFIG_FILES_READ defined before reading the config files!\"\n#endif\n#if defined(MBEDTLS_CONFIG_IS_FINALIZED)\n#error \"Something went wrong: MBEDTLS_CONFIG_IS_FINALIZED defined before reading the config files!\"\n#endif\n\n/* X.509, TLS and non-PSA crypto configuration */\n#if !defined(MBEDTLS_CONFIG_FILE)\n#include \"mbedtls/mbedtls_config.h\"\n#else\n#include MBEDTLS_CONFIG_FILE\n#endif\n\n#if defined(MBEDTLS_CONFIG_VERSION) && ( \\\n    MBEDTLS_CONFIG_VERSION < 0x03000000 || \\\n                             MBEDTLS_CONFIG_VERSION > MBEDTLS_VERSION_NUMBER)\n#error \"Invalid config version, defined value of MBEDTLS_CONFIG_VERSION is unsupported\"\n#endif\n\n/* Target and application specific configurations\n *\n * Allow user to override any previous default.\n *\n */\n#if defined(MBEDTLS_USER_CONFIG_FILE)\n#include MBEDTLS_USER_CONFIG_FILE\n#endif\n\n/* PSA crypto configuration */\n#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)\n#if defined(MBEDTLS_PSA_CRYPTO_CONFIG_FILE)\n#include MBEDTLS_PSA_CRYPTO_CONFIG_FILE\n#else\n#include \"psa/crypto_config.h\"\n#endif\n#if defined(MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE)\n#include MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE\n#endif\n#endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */\n\n/* Indicate that all configuration files have been read.\n * It is now time to adjust the configuration (follow through on dependencies,\n * make PSA and legacy crypto consistent, etc.).\n */\n#define MBEDTLS_CONFIG_FILES_READ\n\n/* Auto-enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY if\n * MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH and MBEDTLS_CTR_DRBG_C defined\n * to ensure a 128-bit key size in CTR_DRBG.\n */\n#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) && defined(MBEDTLS_CTR_DRBG_C)\n#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY\n#endif\n\n/* Auto-enable MBEDTLS_MD_C if needed by a module that didn't require it\n * in a previous release, to ensure backwards compatibility.\n */\n#if defined(MBEDTLS_PKCS5_C)\n#define MBEDTLS_MD_C\n#endif\n\n/* PSA crypto specific configuration options\n * - If config_psa.h reads a configuration option in preprocessor directive,\n *   this symbol should be set before its inclusion. (e.g. MBEDTLS_MD_C)\n * - If config_psa.h writes a configuration option in conditional directive,\n *   this symbol should be consulted after its inclusion.\n *   (e.g. MBEDTLS_MD_LIGHT)\n */\n#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) /* PSA_WANT_xxx influences MBEDTLS_xxx */ || \\\n    defined(MBEDTLS_PSA_CRYPTO_C) /* MBEDTLS_xxx influences PSA_WANT_xxx */ || \\\n    defined(MBEDTLS_PSA_CRYPTO_CLIENT) /* The same as the previous, but with separation only */\n#include \"mbedtls/config_psa.h\"\n#endif\n\n#include \"mbedtls/config_adjust_legacy_crypto.h\"\n\n#include \"mbedtls/config_adjust_x509.h\"\n\n#include \"mbedtls/config_adjust_ssl.h\"\n\n/* Indicate that all configuration symbols are set,\n * even the ones that are calculated programmatically.\n * It is now safe to query the configuration (to check it, to size buffers,\n * etc.).\n */\n#define MBEDTLS_CONFIG_IS_FINALIZED\n\n#include \"mbedtls/check_config.h\"\n\n#endif /* MBEDTLS_BUILD_INFO_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/camellia.h",
    "content": "/**\n * \\file camellia.h\n *\n * \\brief Camellia block cipher\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_CAMELLIA_H\n#define MBEDTLS_CAMELLIA_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"mbedtls/platform_util.h\"\n\n#define MBEDTLS_CAMELLIA_ENCRYPT     1\n#define MBEDTLS_CAMELLIA_DECRYPT     0\n\n/** Bad input data. */\n#define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024\n\n/** Invalid data input length. */\n#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_CAMELLIA_ALT)\n// Regular implementation\n//\n\n/**\n * \\brief          CAMELLIA context structure\n */\ntypedef struct mbedtls_camellia_context {\n    int MBEDTLS_PRIVATE(nr);                     /*!<  number of rounds  */\n    uint32_t MBEDTLS_PRIVATE(rk)[68];            /*!<  CAMELLIA round keys    */\n}\nmbedtls_camellia_context;\n\n#else  /* MBEDTLS_CAMELLIA_ALT */\n#include \"camellia_alt.h\"\n#endif /* MBEDTLS_CAMELLIA_ALT */\n\n/**\n * \\brief          Initialize a CAMELLIA context.\n *\n * \\param ctx      The CAMELLIA context to be initialized.\n *                 This must not be \\c NULL.\n */\nvoid mbedtls_camellia_init(mbedtls_camellia_context *ctx);\n\n/**\n * \\brief          Clear a CAMELLIA context.\n *\n * \\param ctx      The CAMELLIA context to be cleared. This may be \\c NULL,\n *                 in which case this function returns immediately. If it is not\n *                 \\c NULL, it must be initialized.\n */\nvoid mbedtls_camellia_free(mbedtls_camellia_context *ctx);\n\n/**\n * \\brief          Perform a CAMELLIA key schedule operation for encryption.\n *\n * \\param ctx      The CAMELLIA context to use. This must be initialized.\n * \\param key      The encryption key to use. This must be a readable buffer\n *                 of size \\p keybits Bits.\n * \\param keybits  The length of \\p key in Bits. This must be either \\c 128,\n *                 \\c 192 or \\c 256.\n *\n * \\return         \\c 0 if successful.\n * \\return         A negative error code on failure.\n */\nint mbedtls_camellia_setkey_enc(mbedtls_camellia_context *ctx,\n                                const unsigned char *key,\n                                unsigned int keybits);\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n/**\n * \\brief          Perform a CAMELLIA key schedule operation for decryption.\n *\n * \\param ctx      The CAMELLIA context to use. This must be initialized.\n * \\param key      The decryption key. This must be a readable buffer\n *                 of size \\p keybits Bits.\n * \\param keybits  The length of \\p key in Bits. This must be either \\c 128,\n *                 \\c 192 or \\c 256.\n *\n * \\return         \\c 0 if successful.\n * \\return         A negative error code on failure.\n */\nint mbedtls_camellia_setkey_dec(mbedtls_camellia_context *ctx,\n                                const unsigned char *key,\n                                unsigned int keybits);\n#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */\n\n/**\n * \\brief          Perform a CAMELLIA-ECB block encryption/decryption operation.\n *\n * \\param ctx      The CAMELLIA context to use. This must be initialized\n *                 and bound to a key.\n * \\param mode     The mode of operation. This must be either\n *                 #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.\n * \\param input    The input block. This must be a readable buffer\n *                 of size \\c 16 Bytes.\n * \\param output   The output block. This must be a writable buffer\n *                 of size \\c 16 Bytes.\n *\n * \\return         \\c 0 if successful.\n * \\return         A negative error code on failure.\n */\nint mbedtls_camellia_crypt_ecb(mbedtls_camellia_context *ctx,\n                               int mode,\n                               const unsigned char input[16],\n                               unsigned char output[16]);\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n/**\n * \\brief          Perform a CAMELLIA-CBC buffer encryption/decryption operation.\n *\n * \\note           Upon exit, the content of the IV is updated so that you can\n *                 call the function same function again on the following\n *                 block(s) of data and get the same result as if it was\n *                 encrypted in one call. This allows a \"streaming\" usage.\n *                 If on the other hand you need to retain the contents of the\n *                 IV, you should either save it manually or use the cipher\n *                 module instead.\n *\n * \\param ctx      The CAMELLIA context to use. This must be initialized\n *                 and bound to a key.\n * \\param mode     The mode of operation. This must be either\n *                 #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.\n * \\param length   The length in Bytes of the input data \\p input.\n *                 This must be a multiple of \\c 16 Bytes.\n * \\param iv       The initialization vector. This must be a read/write buffer\n *                 of length \\c 16 Bytes. It is updated to allow streaming\n *                 use as explained above.\n * \\param input    The buffer holding the input data. This must point to a\n *                 readable buffer of length \\p length Bytes.\n * \\param output   The buffer holding the output data. This must point to a\n *                 writable buffer of length \\p length Bytes.\n *\n * \\return         \\c 0 if successful.\n * \\return         A negative error code on failure.\n */\nint mbedtls_camellia_crypt_cbc(mbedtls_camellia_context *ctx,\n                               int mode,\n                               size_t length,\n                               unsigned char iv[16],\n                               const unsigned char *input,\n                               unsigned char *output);\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n/**\n * \\brief          Perform a CAMELLIA-CFB128 buffer encryption/decryption\n *                 operation.\n *\n * \\note           Due to the nature of CFB mode, you should use the same\n *                 key for both encryption and decryption. In particular, calls\n *                 to this function should be preceded by a key-schedule via\n *                 mbedtls_camellia_setkey_enc() regardless of whether \\p mode\n *                 is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.\n *\n * \\note           Upon exit, the content of the IV is updated so that you can\n *                 call the function same function again on the following\n *                 block(s) of data and get the same result as if it was\n *                 encrypted in one call. This allows a \"streaming\" usage.\n *                 If on the other hand you need to retain the contents of the\n *                 IV, you should either save it manually or use the cipher\n *                 module instead.\n *\n * \\param ctx      The CAMELLIA context to use. This must be initialized\n *                 and bound to a key.\n * \\param mode     The mode of operation. This must be either\n *                 #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.\n * \\param length   The length of the input data \\p input. Any value is allowed.\n * \\param iv_off   The current offset in the IV. This must be smaller\n *                 than \\c 16 Bytes. It is updated after this call to allow\n *                 the aforementioned streaming usage.\n * \\param iv       The initialization vector. This must be a read/write buffer\n *                 of length \\c 16 Bytes. It is updated after this call to\n *                 allow the aforementioned streaming usage.\n * \\param input    The buffer holding the input data. This must be a readable\n *                 buffer of size \\p length Bytes.\n * \\param output   The buffer to hold the output data. This must be a writable\n *                 buffer of length \\p length Bytes.\n *\n * \\return         \\c 0 if successful.\n * \\return         A negative error code on failure.\n */\nint mbedtls_camellia_crypt_cfb128(mbedtls_camellia_context *ctx,\n                                  int mode,\n                                  size_t length,\n                                  size_t *iv_off,\n                                  unsigned char iv[16],\n                                  const unsigned char *input,\n                                  unsigned char *output);\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n/**\n * \\brief      Perform a CAMELLIA-CTR buffer encryption/decryption operation.\n *\n * *note       Due to the nature of CTR mode, you should use the same\n *             key for both encryption and decryption. In particular, calls\n *             to this function should be preceded by a key-schedule via\n *             mbedtls_camellia_setkey_enc() regardless of whether the mode\n *             is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.\n *\n * \\warning    You must never reuse a nonce value with the same key. Doing so\n *             would void the encryption for the two messages encrypted with\n *             the same nonce and key.\n *\n *             There are two common strategies for managing nonces with CTR:\n *\n *             1. You can handle everything as a single message processed over\n *             successive calls to this function. In that case, you want to\n *             set \\p nonce_counter and \\p nc_off to 0 for the first call, and\n *             then preserve the values of \\p nonce_counter, \\p nc_off and \\p\n *             stream_block across calls to this function as they will be\n *             updated by this function.\n *\n *             With this strategy, you must not encrypt more than 2**128\n *             blocks of data with the same key.\n *\n *             2. You can encrypt separate messages by dividing the \\p\n *             nonce_counter buffer in two areas: the first one used for a\n *             per-message nonce, handled by yourself, and the second one\n *             updated by this function internally.\n *\n *             For example, you might reserve the first \\c 12 Bytes for the\n *             per-message nonce, and the last \\c 4 Bytes for internal use.\n *             In that case, before calling this function on a new message you\n *             need to set the first \\c 12 Bytes of \\p nonce_counter to your\n *             chosen nonce value, the last four to \\c 0, and \\p nc_off to \\c 0\n *             (which will cause \\p stream_block to be ignored). That way, you\n *             can encrypt at most \\c 2**96 messages of up to \\c 2**32 blocks\n *             each  with the same key.\n *\n *             The per-message nonce (or information sufficient to reconstruct\n *             it) needs to be communicated with the ciphertext and must be\n *             unique. The recommended way to ensure uniqueness is to use a\n *             message counter. An alternative is to generate random nonces,\n *             but this limits the number of messages that can be securely\n *             encrypted: for example, with 96-bit random nonces, you should\n *             not encrypt more than 2**32 messages with the same key.\n *\n *             Note that for both strategies, sizes are measured in blocks and\n *             that a CAMELLIA block is \\c 16 Bytes.\n *\n * \\warning    Upon return, \\p stream_block contains sensitive data. Its\n *             content must not be written to insecure storage and should be\n *             securely discarded as soon as it's no longer needed.\n *\n * \\param ctx           The CAMELLIA context to use. This must be initialized\n *                      and bound to a key.\n * \\param length        The length of the input data \\p input in Bytes.\n *                      Any value is allowed.\n * \\param nc_off        The offset in the current \\p stream_block (for resuming\n *                      within current cipher stream). The offset pointer to\n *                      should be \\c 0 at the start of a stream. It is updated\n *                      at the end of this call.\n * \\param nonce_counter The 128-bit nonce and counter. This must be a read/write\n *                      buffer of length \\c 16 Bytes.\n * \\param stream_block  The saved stream-block for resuming. This must be a\n *                      read/write buffer of length \\c 16 Bytes.\n * \\param input         The input data stream. This must be a readable buffer of\n *                      size \\p length Bytes.\n * \\param output        The output data stream. This must be a writable buffer\n *                      of size \\p length Bytes.\n *\n * \\return              \\c 0 if successful.\n * \\return              A negative error code on failure.\n */\nint mbedtls_camellia_crypt_ctr(mbedtls_camellia_context *ctx,\n                               size_t length,\n                               size_t *nc_off,\n                               unsigned char nonce_counter[16],\n                               unsigned char stream_block[16],\n                               const unsigned char *input,\n                               unsigned char *output);\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/**\n * \\brief          Checkup routine\n *\n * \\return         0 if successful, or 1 if the test failed\n */\nint mbedtls_camellia_self_test(int verbose);\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* camellia.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/ccm.h",
    "content": "/**\n * \\file ccm.h\n *\n * \\brief This file provides an API for the CCM authenticated encryption\n *        mode for block ciphers.\n *\n * CCM combines Counter mode encryption with CBC-MAC authentication\n * for 128-bit block ciphers.\n *\n * Input to CCM includes the following elements:\n * <ul><li>Payload - data that is both authenticated and encrypted.</li>\n * <li>Associated data (Adata) - data that is authenticated but not\n * encrypted, For example, a header.</li>\n * <li>Nonce - A unique value that is assigned to the payload and the\n * associated data.</li></ul>\n *\n * Definition of CCM:\n * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf\n * RFC 3610 \"Counter with CBC-MAC (CCM)\"\n *\n * Related:\n * RFC 5116 \"An Interface and Algorithms for Authenticated Encryption\"\n *\n * Definition of CCM*:\n * IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks\n * Integer representation is fixed most-significant-octet-first order and\n * the representation of octets is most-significant-bit-first order. This is\n * consistent with RFC 3610.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CCM_H\n#define MBEDTLS_CCM_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/cipher.h\"\n\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n#include \"mbedtls/block_cipher.h\"\n#endif\n\n#define MBEDTLS_CCM_DECRYPT       0\n#define MBEDTLS_CCM_ENCRYPT       1\n#define MBEDTLS_CCM_STAR_DECRYPT  2\n#define MBEDTLS_CCM_STAR_ENCRYPT  3\n\n/** Bad input parameters to the function. */\n#define MBEDTLS_ERR_CCM_BAD_INPUT       -0x000D\n/** Authenticated decryption failed. */\n#define MBEDTLS_ERR_CCM_AUTH_FAILED     -0x000F\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_CCM_ALT)\n// Regular implementation\n//\n\n/**\n * \\brief    The CCM context-type definition. The CCM context is passed\n *           to the APIs called.\n */\ntypedef struct mbedtls_ccm_context {\n    unsigned char MBEDTLS_PRIVATE(y)[16];    /*!< The Y working buffer */\n    unsigned char MBEDTLS_PRIVATE(ctr)[16];  /*!< The counter buffer */\n    size_t MBEDTLS_PRIVATE(plaintext_len);   /*!< Total plaintext length */\n    size_t MBEDTLS_PRIVATE(add_len);         /*!< Total authentication data length */\n    size_t MBEDTLS_PRIVATE(tag_len);         /*!< Total tag length */\n    size_t MBEDTLS_PRIVATE(processed);       /*!< Track how many bytes of input data\n                                                  were processed (chunked input).\n                                                  Used independently for both auth data\n                                                  and plaintext/ciphertext.\n                                                  This variable is set to zero after\n                                                  auth data input is finished. */\n    unsigned int MBEDTLS_PRIVATE(q);         /*!< The Q working value */\n    unsigned int MBEDTLS_PRIVATE(mode);      /*!< The operation to perform:\n                                              #MBEDTLS_CCM_ENCRYPT or\n                                              #MBEDTLS_CCM_DECRYPT or\n                                              #MBEDTLS_CCM_STAR_ENCRYPT or\n                                              #MBEDTLS_CCM_STAR_DECRYPT. */\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n    mbedtls_block_cipher_context_t MBEDTLS_PRIVATE(block_cipher_ctx);    /*!< The cipher context used. */\n#else\n    mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx);    /*!< The cipher context used. */\n#endif\n    int MBEDTLS_PRIVATE(state);              /*!< Working value holding context's\n                                                  state. Used for chunked data input */\n}\nmbedtls_ccm_context;\n\n#else  /* MBEDTLS_CCM_ALT */\n#include \"ccm_alt.h\"\n#endif /* MBEDTLS_CCM_ALT */\n\n/**\n * \\brief           This function initializes the specified CCM context,\n *                  to make references valid, and prepare the context\n *                  for mbedtls_ccm_setkey() or mbedtls_ccm_free().\n *\n * \\param ctx       The CCM context to initialize. This must not be \\c NULL.\n */\nvoid mbedtls_ccm_init(mbedtls_ccm_context *ctx);\n\n/**\n * \\brief           This function initializes the CCM context set in the\n *                  \\p ctx parameter and sets the encryption key.\n *\n * \\param ctx       The CCM context to initialize. This must be an initialized\n *                  context.\n * \\param cipher    The 128-bit block cipher to use.\n * \\param key       The encryption key. This must not be \\c NULL.\n * \\param keybits   The key size in bits. This must be acceptable by the cipher.\n *\n * \\return          \\c 0 on success.\n * \\return          A CCM or cipher-specific error code on failure.\n */\nint mbedtls_ccm_setkey(mbedtls_ccm_context *ctx,\n                       mbedtls_cipher_id_t cipher,\n                       const unsigned char *key,\n                       unsigned int keybits);\n\n/**\n * \\brief   This function releases and clears the specified CCM context\n *          and underlying cipher sub-context.\n *\n * \\param ctx       The CCM context to clear. If this is \\c NULL, the function\n *                  has no effect. Otherwise, this must be initialized.\n */\nvoid mbedtls_ccm_free(mbedtls_ccm_context *ctx);\n\n/**\n * \\brief           This function encrypts a buffer using CCM.\n *\n * \\note            The tag is written to a separate buffer. To concatenate\n *                  the \\p tag with the \\p output, as done in <em>RFC-3610:\n *                  Counter with CBC-MAC (CCM)</em>, use\n *                  \\p tag = \\p output + \\p length, and make sure that the\n *                  output buffer is at least \\p length + \\p tag_len wide.\n *\n * \\param ctx       The CCM context to use for encryption. This must be\n *                  initialized and bound to a key.\n * \\param length    The length of the input data in Bytes.\n * \\param iv        The initialization vector (nonce). This must be a readable\n *                  buffer of at least \\p iv_len Bytes.\n * \\param iv_len    The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,\n *                  or 13. The length L of the message length field is\n *                  15 - \\p iv_len.\n * \\param ad        The additional data field. If \\p ad_len is greater than\n *                  zero, \\p ad must be a readable buffer of at least that\n *                  length.\n * \\param ad_len    The length of additional data in Bytes.\n *                  This must be less than `2^16 - 2^8`.\n * \\param input     The buffer holding the input data. If \\p length is greater\n *                  than zero, \\p input must be a readable buffer of at least\n *                  that length.\n * \\param output    The buffer holding the output data. If \\p length is greater\n *                  than zero, \\p output must be a writable buffer of at least\n *                  that length.\n * \\param tag       The buffer holding the authentication field. This must be a\n *                  writable buffer of at least \\p tag_len Bytes.\n * \\param tag_len   The length of the authentication field to generate in Bytes:\n *                  4, 6, 8, 10, 12, 14 or 16.\n *\n * \\return          \\c 0 on success.\n * \\return          A CCM or cipher-specific error code on failure.\n */\nint mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length,\n                                const unsigned char *iv, size_t iv_len,\n                                const unsigned char *ad, size_t ad_len,\n                                const unsigned char *input, unsigned char *output,\n                                unsigned char *tag, size_t tag_len);\n\n/**\n * \\brief           This function encrypts a buffer using CCM*.\n *\n * \\note            The tag is written to a separate buffer. To concatenate\n *                  the \\p tag with the \\p output, as done in <em>RFC-3610:\n *                  Counter with CBC-MAC (CCM)</em>, use\n *                  \\p tag = \\p output + \\p length, and make sure that the\n *                  output buffer is at least \\p length + \\p tag_len wide.\n *\n * \\note            When using this function in a variable tag length context,\n *                  the tag length has to be encoded into the \\p iv passed to\n *                  this function.\n *\n * \\param ctx       The CCM context to use for encryption. This must be\n *                  initialized and bound to a key.\n * \\param length    The length of the input data in Bytes.\n *                  For tag length = 0, input length is ignored.\n * \\param iv        The initialization vector (nonce). This must be a readable\n *                  buffer of at least \\p iv_len Bytes.\n * \\param iv_len    The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,\n *                  or 13. The length L of the message length field is\n *                  15 - \\p iv_len.\n * \\param ad        The additional data field. This must be a readable buffer of\n *                  at least \\p ad_len Bytes.\n * \\param ad_len    The length of additional data in Bytes.\n *                  This must be less than 2^16 - 2^8.\n * \\param input     The buffer holding the input data. If \\p length is greater\n *                  than zero, \\p input must be a readable buffer of at least\n *                  that length.\n * \\param output    The buffer holding the output data. If \\p length is greater\n *                  than zero, \\p output must be a writable buffer of at least\n *                  that length.\n * \\param tag       The buffer holding the authentication field. This must be a\n *                  writable buffer of at least \\p tag_len Bytes.\n * \\param tag_len   The length of the authentication field to generate in Bytes:\n *                  0, 4, 6, 8, 10, 12, 14 or 16.\n *\n * \\warning         Passing \\c 0 as \\p tag_len means that the message is no\n *                  longer authenticated.\n *\n * \\return          \\c 0 on success.\n * \\return          A CCM or cipher-specific error code on failure.\n */\nint mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length,\n                                     const unsigned char *iv, size_t iv_len,\n                                     const unsigned char *ad, size_t ad_len,\n                                     const unsigned char *input, unsigned char *output,\n                                     unsigned char *tag, size_t tag_len);\n\n/**\n * \\brief           This function performs a CCM authenticated decryption of a\n *                  buffer.\n *\n * \\param ctx       The CCM context to use for decryption. This must be\n *                  initialized and bound to a key.\n * \\param length    The length of the input data in Bytes.\n * \\param iv        The initialization vector (nonce). This must be a readable\n *                  buffer of at least \\p iv_len Bytes.\n * \\param iv_len    The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,\n *                  or 13. The length L of the message length field is\n *                  15 - \\p iv_len.\n * \\param ad        The additional data field. This must be a readable buffer\n *                  of at least that \\p ad_len Bytes..\n * \\param ad_len    The length of additional data in Bytes.\n *                  This must be less than 2^16 - 2^8.\n * \\param input     The buffer holding the input data. If \\p length is greater\n *                  than zero, \\p input must be a readable buffer of at least\n *                  that length.\n * \\param output    The buffer holding the output data. If \\p length is greater\n *                  than zero, \\p output must be a writable buffer of at least\n *                  that length.\n * \\param tag       The buffer holding the authentication field. This must be a\n *                  readable buffer of at least \\p tag_len Bytes.\n * \\param tag_len   The length of the authentication field to generate in Bytes:\n *                  4, 6, 8, 10, 12, 14 or 16.\n *\n * \\return          \\c 0 on success. This indicates that the message is authentic.\n * \\return          #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match.\n * \\return          A cipher-specific error code on calculation failure.\n */\nint mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length,\n                             const unsigned char *iv, size_t iv_len,\n                             const unsigned char *ad, size_t ad_len,\n                             const unsigned char *input, unsigned char *output,\n                             const unsigned char *tag, size_t tag_len);\n\n/**\n * \\brief           This function performs a CCM* authenticated decryption of a\n *                  buffer.\n *\n * \\note            When using this function in a variable tag length context,\n *                  the tag length has to be decoded from \\p iv and passed to\n *                  this function as \\p tag_len. (\\p tag needs to be adjusted\n *                  accordingly.)\n *\n * \\param ctx       The CCM context to use for decryption. This must be\n *                  initialized and bound to a key.\n * \\param length    The length of the input data in Bytes.\n *                  For tag length = 0, input length is ignored.\n * \\param iv        The initialization vector (nonce). This must be a readable\n *                  buffer of at least \\p iv_len Bytes.\n * \\param iv_len    The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,\n *                  or 13. The length L of the message length field is\n *                  15 - \\p iv_len.\n * \\param ad        The additional data field. This must be a readable buffer of\n *                  at least that \\p ad_len Bytes.\n * \\param ad_len    The length of additional data in Bytes.\n *                  This must be less than 2^16 - 2^8.\n * \\param input     The buffer holding the input data. If \\p length is greater\n *                  than zero, \\p input must be a readable buffer of at least\n *                  that length.\n * \\param output    The buffer holding the output data. If \\p length is greater\n *                  than zero, \\p output must be a writable buffer of at least\n *                  that length.\n * \\param tag       The buffer holding the authentication field. This must be a\n *                  readable buffer of at least \\p tag_len Bytes.\n * \\param tag_len   The length of the authentication field in Bytes.\n *                  0, 4, 6, 8, 10, 12, 14 or 16.\n *\n * \\warning         Passing \\c 0 as \\p tag_len means that the message is nos\n *                  longer authenticated.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match.\n * \\return          A cipher-specific error code on calculation failure.\n */\nint mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length,\n                                  const unsigned char *iv, size_t iv_len,\n                                  const unsigned char *ad, size_t ad_len,\n                                  const unsigned char *input, unsigned char *output,\n                                  const unsigned char *tag, size_t tag_len);\n\n/**\n * \\brief           This function starts a CCM encryption or decryption\n *                  operation.\n *\n *                  This function and mbedtls_ccm_set_lengths() must be called\n *                  before calling mbedtls_ccm_update_ad() or\n *                  mbedtls_ccm_update(). This function can be called before\n *                  or after mbedtls_ccm_set_lengths().\n *\n * \\note            This function is not implemented in Mbed TLS yet.\n *\n * \\param ctx       The CCM context. This must be initialized.\n * \\param mode      The operation to perform: #MBEDTLS_CCM_ENCRYPT or\n *                  #MBEDTLS_CCM_DECRYPT or #MBEDTLS_CCM_STAR_ENCRYPT or\n *                  #MBEDTLS_CCM_STAR_DECRYPT.\n * \\param iv        The initialization vector. This must be a readable buffer\n *                  of at least \\p iv_len Bytes.\n * \\param iv_len    The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,\n *                  or 13. The length L of the message length field is\n *                  15 - \\p iv_len.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_CCM_BAD_INPUT on failure:\n *                  \\p ctx is in an invalid state,\n *                  \\p mode is invalid,\n *                  \\p iv_len is invalid (lower than \\c 7 or greater than\n *                  \\c 13).\n */\nint mbedtls_ccm_starts(mbedtls_ccm_context *ctx,\n                       int mode,\n                       const unsigned char *iv,\n                       size_t iv_len);\n\n/**\n * \\brief           This function declares the lengths of the message\n *                  and additional data for a CCM encryption or decryption\n *                  operation.\n *\n *                  This function and mbedtls_ccm_starts() must be called\n *                  before calling mbedtls_ccm_update_ad() or\n *                  mbedtls_ccm_update(). This function can be called before\n *                  or after mbedtls_ccm_starts().\n *\n * \\note            This function is not implemented in Mbed TLS yet.\n *\n * \\param ctx       The CCM context. This must be initialized.\n * \\param total_ad_len   The total length of additional data in bytes.\n *                       This must be less than `2^16 - 2^8`.\n * \\param plaintext_len  The length in bytes of the plaintext to encrypt or\n *                       result of the decryption (thus not encompassing the\n *                       additional data that are not encrypted).\n * \\param tag_len   The length of the tag to generate in Bytes:\n *                  4, 6, 8, 10, 12, 14 or 16.\n *                  For CCM*, zero is also valid.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_CCM_BAD_INPUT on failure:\n *                  \\p ctx is in an invalid state,\n *                  \\p total_ad_len is greater than \\c 0xFF00.\n */\nint mbedtls_ccm_set_lengths(mbedtls_ccm_context *ctx,\n                            size_t total_ad_len,\n                            size_t plaintext_len,\n                            size_t tag_len);\n\n/**\n * \\brief           This function feeds an input buffer as associated data\n *                  (authenticated but not encrypted data) in a CCM\n *                  encryption or decryption operation.\n *\n *                  You may call this function zero, one or more times\n *                  to pass successive parts of the additional data. The\n *                  lengths \\p ad_len of the data parts should eventually add\n *                  up exactly to the total length of additional data\n *                  \\c total_ad_len passed to mbedtls_ccm_set_lengths(). You\n *                  may not call this function after calling\n *                  mbedtls_ccm_update().\n *\n * \\note            This function is not implemented in Mbed TLS yet.\n *\n * \\param ctx       The CCM context. This must have been started with\n *                  mbedtls_ccm_starts(), the lengths of the message and\n *                  additional data must have been declared with\n *                  mbedtls_ccm_set_lengths() and this must not have yet\n *                  received any input with mbedtls_ccm_update().\n * \\param ad        The buffer holding the additional data, or \\c NULL\n *                  if \\p ad_len is \\c 0.\n * \\param ad_len    The length of the additional data. If \\c 0,\n *                  \\p ad may be \\c NULL.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_CCM_BAD_INPUT on failure:\n *                  \\p ctx is in an invalid state,\n *                  total input length too long.\n */\nint mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx,\n                          const unsigned char *ad,\n                          size_t ad_len);\n\n/**\n * \\brief           This function feeds an input buffer into an ongoing CCM\n *                  encryption or decryption operation.\n *\n *                  You may call this function zero, one or more times\n *                  to pass successive parts of the input: the plaintext to\n *                  encrypt, or the ciphertext (not including the tag) to\n *                  decrypt. After the last part of the input, call\n *                  mbedtls_ccm_finish(). The lengths \\p input_len of the\n *                  data parts should eventually add up exactly to the\n *                  plaintext length \\c plaintext_len passed to\n *                  mbedtls_ccm_set_lengths().\n *\n *                  This function may produce output in one of the following\n *                  ways:\n *                  - Immediate output: the output length is always equal\n *                    to the input length.\n *                  - Buffered output: except for the last part of input data,\n *                    the output consists of a whole number of 16-byte blocks.\n *                    If the total input length so far (not including\n *                    associated data) is 16 \\* *B* + *A* with *A* < 16 then\n *                    the total output length is 16 \\* *B*.\n *                    For the last part of input data, the output length is\n *                    equal to the input length plus the number of bytes (*A*)\n *                    buffered in the previous call to the function (if any).\n *                    The function uses the plaintext length\n *                    \\c plaintext_len passed to mbedtls_ccm_set_lengths()\n *                    to detect the last part of input data.\n *\n *                  In particular:\n *                  - It is always correct to call this function with\n *                    \\p output_size >= \\p input_len + 15.\n *                  - If \\p input_len is a multiple of 16 for all the calls\n *                    to this function during an operation (not necessary for\n *                    the last one) then it is correct to use \\p output_size\n *                    =\\p input_len.\n *\n * \\note            This function is not implemented in Mbed TLS yet.\n *\n * \\param ctx           The CCM context. This must have been started with\n *                      mbedtls_ccm_starts() and the lengths of the message and\n *                      additional data must have been declared with\n *                      mbedtls_ccm_set_lengths().\n * \\param input         The buffer holding the input data. If \\p input_len\n *                      is greater than zero, this must be a readable buffer\n *                      of at least \\p input_len bytes.\n * \\param input_len     The length of the input data in bytes.\n * \\param output        The buffer for the output data. If \\p output_size\n *                      is greater than zero, this must be a writable buffer of\n *                      at least \\p output_size bytes.\n * \\param output_size   The size of the output buffer in bytes.\n *                      See the function description regarding the output size.\n * \\param output_len    On success, \\p *output_len contains the actual\n *                      length of the output written in \\p output.\n *                      On failure, the content of \\p *output_len is\n *                      unspecified.\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_CCM_BAD_INPUT on failure:\n *                 \\p ctx is in an invalid state,\n *                 total input length too long,\n *                 or \\p output_size too small.\n */\nint mbedtls_ccm_update(mbedtls_ccm_context *ctx,\n                       const unsigned char *input, size_t input_len,\n                       unsigned char *output, size_t output_size,\n                       size_t *output_len);\n\n/**\n * \\brief           This function finishes the CCM operation and generates\n *                  the authentication tag.\n *\n *                  It wraps up the CCM stream, and generates the\n *                  tag. The tag can have a maximum length of 16 Bytes.\n *\n * \\note            This function is not implemented in Mbed TLS yet.\n *\n * \\param ctx       The CCM context. This must have been started with\n *                  mbedtls_ccm_starts() and the lengths of the message and\n *                  additional data must have been declared with\n *                  mbedtls_ccm_set_lengths().\n * \\param tag       The buffer for holding the tag. If \\p tag_len is greater\n *                  than zero, this must be a writable buffer of at least \\p\n *                  tag_len Bytes.\n * \\param tag_len   The length of the tag. Must match the tag length passed to\n *                  mbedtls_ccm_set_lengths() function.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_CCM_BAD_INPUT on failure:\n *                  \\p ctx is in an invalid state,\n *                  invalid value of \\p tag_len,\n *                  the total amount of additional data passed to\n *                  mbedtls_ccm_update_ad() was lower than the total length of\n *                  additional data \\c total_ad_len passed to\n *                  mbedtls_ccm_set_lengths(),\n *                  the total amount of input data passed to\n *                  mbedtls_ccm_update() was lower than the plaintext length\n *                  \\c plaintext_len passed to mbedtls_ccm_set_lengths().\n */\nint mbedtls_ccm_finish(mbedtls_ccm_context *ctx,\n                       unsigned char *tag, size_t tag_len);\n\n#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES)\n/**\n * \\brief          The CCM checkup routine.\n *\n * \\return         \\c 0 on success.\n * \\return         \\c 1 on failure.\n */\nint mbedtls_ccm_self_test(int verbose);\n#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_CCM_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/chacha20.h",
    "content": "/**\n * \\file chacha20.h\n *\n * \\brief   This file contains ChaCha20 definitions and functions.\n *\n *          ChaCha20 is a stream cipher that can encrypt and decrypt\n *          information. ChaCha was created by Daniel Bernstein as a variant of\n *          its Salsa cipher https://cr.yp.to/chacha/chacha-20080128.pdf\n *          ChaCha20 is the variant with 20 rounds, that was also standardized\n *          in RFC 7539.\n *\n * \\author Daniel King <damaki.gh@gmail.com>\n */\n\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CHACHA20_H\n#define MBEDTLS_CHACHA20_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include <stdint.h>\n#include <stddef.h>\n\n/** Invalid input parameter(s). */\n#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA         -0x0051\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_CHACHA20_ALT)\n\ntypedef struct mbedtls_chacha20_context {\n    uint32_t MBEDTLS_PRIVATE(state)[16];          /*! The state (before round operations). */\n    uint8_t  MBEDTLS_PRIVATE(keystream8)[64];     /*! Leftover keystream bytes. */\n    size_t MBEDTLS_PRIVATE(keystream_bytes_used); /*! Number of keystream bytes already used. */\n}\nmbedtls_chacha20_context;\n\n#else  /* MBEDTLS_CHACHA20_ALT */\n#include \"chacha20_alt.h\"\n#endif /* MBEDTLS_CHACHA20_ALT */\n\n/**\n * \\brief           This function initializes the specified ChaCha20 context.\n *\n *                  It must be the first API called before using\n *                  the context.\n *\n *                  It is usually followed by calls to\n *                  \\c mbedtls_chacha20_setkey() and\n *                  \\c mbedtls_chacha20_starts(), then one or more calls to\n *                  to \\c mbedtls_chacha20_update(), and finally to\n *                  \\c mbedtls_chacha20_free().\n *\n * \\param ctx       The ChaCha20 context to initialize.\n *                  This must not be \\c NULL.\n */\nvoid mbedtls_chacha20_init(mbedtls_chacha20_context *ctx);\n\n/**\n * \\brief           This function releases and clears the specified\n *                  ChaCha20 context.\n *\n * \\param ctx       The ChaCha20 context to clear. This may be \\c NULL,\n *                  in which case this function is a no-op. If it is not\n *                  \\c NULL, it must point to an initialized context.\n *\n */\nvoid mbedtls_chacha20_free(mbedtls_chacha20_context *ctx);\n\n/**\n * \\brief           This function sets the encryption/decryption key.\n *\n * \\note            After using this function, you must also call\n *                  \\c mbedtls_chacha20_starts() to set a nonce before you\n *                  start encrypting/decrypting data with\n *                  \\c mbedtls_chacha_update().\n *\n * \\param ctx       The ChaCha20 context to which the key should be bound.\n *                  It must be initialized.\n * \\param key       The encryption/decryption key. This must be \\c 32 Bytes\n *                  in length.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL.\n */\nint mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,\n                            const unsigned char key[32]);\n\n/**\n * \\brief           This function sets the nonce and initial counter value.\n *\n * \\note            A ChaCha20 context can be re-used with the same key by\n *                  calling this function to change the nonce.\n *\n * \\warning         You must never use the same nonce twice with the same key.\n *                  This would void any confidentiality guarantees for the\n *                  messages encrypted with the same nonce and key.\n *\n * \\param ctx       The ChaCha20 context to which the nonce should be bound.\n *                  It must be initialized and bound to a key.\n * \\param nonce     The nonce. This must be \\c 12 Bytes in size.\n * \\param counter   The initial counter value. This is usually \\c 0.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is\n *                  NULL.\n */\nint mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,\n                            const unsigned char nonce[12],\n                            uint32_t counter);\n\n/**\n * \\brief           This function encrypts or decrypts data.\n *\n *                  Since ChaCha20 is a stream cipher, the same operation is\n *                  used for encrypting and decrypting data.\n *\n * \\note            The \\p input and \\p output pointers must either be equal or\n *                  point to non-overlapping buffers.\n *\n * \\note            \\c mbedtls_chacha20_setkey() and\n *                  \\c mbedtls_chacha20_starts() must be called at least once\n *                  to setup the context before this function can be called.\n *\n * \\note            This function can be called multiple times in a row in\n *                  order to encrypt of decrypt data piecewise with the same\n *                  key and nonce.\n *\n * \\param ctx       The ChaCha20 context to use for encryption or decryption.\n *                  It must be initialized and bound to a key and nonce.\n * \\param size      The length of the input data in Bytes.\n * \\param input     The buffer holding the input data.\n *                  This pointer can be \\c NULL if `size == 0`.\n * \\param output    The buffer holding the output data.\n *                  This must be able to hold \\p size Bytes.\n *                  This pointer can be \\c NULL if `size == 0`.\n *\n * \\return          \\c 0 on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,\n                            size_t size,\n                            const unsigned char *input,\n                            unsigned char *output);\n\n/**\n * \\brief           This function encrypts or decrypts data with ChaCha20 and\n *                  the given key and nonce.\n *\n *                  Since ChaCha20 is a stream cipher, the same operation is\n *                  used for encrypting and decrypting data.\n *\n * \\warning         You must never use the same (key, nonce) pair more than\n *                  once. This would void any confidentiality guarantees for\n *                  the messages encrypted with the same nonce and key.\n *\n * \\note            The \\p input and \\p output pointers must either be equal or\n *                  point to non-overlapping buffers.\n *\n * \\param key       The encryption/decryption key.\n *                  This must be \\c 32 Bytes in length.\n * \\param nonce     The nonce. This must be \\c 12 Bytes in size.\n * \\param counter   The initial counter value. This is usually \\c 0.\n * \\param size      The length of the input data in Bytes.\n * \\param input     The buffer holding the input data.\n *                  This pointer can be \\c NULL if `size == 0`.\n * \\param output    The buffer holding the output data.\n *                  This must be able to hold \\p size Bytes.\n *                  This pointer can be \\c NULL if `size == 0`.\n *\n * \\return          \\c 0 on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_chacha20_crypt(const unsigned char key[32],\n                           const unsigned char nonce[12],\n                           uint32_t counter,\n                           size_t size,\n                           const unsigned char *input,\n                           unsigned char *output);\n\n#if defined(MBEDTLS_SELF_TEST)\n/**\n * \\brief           The ChaCha20 checkup routine.\n *\n * \\return          \\c 0 on success.\n * \\return          \\c 1 on failure.\n */\nint mbedtls_chacha20_self_test(int verbose);\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_CHACHA20_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/chachapoly.h",
    "content": "/**\n * \\file chachapoly.h\n *\n * \\brief   This file contains the AEAD-ChaCha20-Poly1305 definitions and\n *          functions.\n *\n *          ChaCha20-Poly1305 is an algorithm for Authenticated Encryption\n *          with Associated Data (AEAD) that can be used to encrypt and\n *          authenticate data. It is based on ChaCha20 and Poly1305 by Daniel\n *          Bernstein and was standardized in RFC 7539.\n *\n * \\author Daniel King <damaki.gh@gmail.com>\n */\n\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CHACHAPOLY_H\n#define MBEDTLS_CHACHAPOLY_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n/* for shared error codes */\n#include \"mbedtls/poly1305.h\"\n\n/** The requested operation is not permitted in the current state. */\n#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE            -0x0054\n/** Authenticated decryption failed: data was not authentic. */\n#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED          -0x0056\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef enum {\n    MBEDTLS_CHACHAPOLY_ENCRYPT,     /**< The mode value for performing encryption. */\n    MBEDTLS_CHACHAPOLY_DECRYPT      /**< The mode value for performing decryption. */\n}\nmbedtls_chachapoly_mode_t;\n\n#if !defined(MBEDTLS_CHACHAPOLY_ALT)\n\n#include \"mbedtls/chacha20.h\"\n\ntypedef struct mbedtls_chachapoly_context {\n    mbedtls_chacha20_context MBEDTLS_PRIVATE(chacha20_ctx);  /**< The ChaCha20 context. */\n    mbedtls_poly1305_context MBEDTLS_PRIVATE(poly1305_ctx);  /**< The Poly1305 context. */\n    uint64_t MBEDTLS_PRIVATE(aad_len);                       /**< The length (bytes) of the Additional Authenticated Data. */\n    uint64_t MBEDTLS_PRIVATE(ciphertext_len);                /**< The length (bytes) of the ciphertext. */\n    int MBEDTLS_PRIVATE(state);                              /**< The current state of the context. */\n    mbedtls_chachapoly_mode_t MBEDTLS_PRIVATE(mode);         /**< Cipher mode (encrypt or decrypt). */\n}\nmbedtls_chachapoly_context;\n\n#else /* !MBEDTLS_CHACHAPOLY_ALT */\n#include \"chachapoly_alt.h\"\n#endif /* !MBEDTLS_CHACHAPOLY_ALT */\n\n/**\n * \\brief           This function initializes the specified ChaCha20-Poly1305 context.\n *\n *                  It must be the first API called before using\n *                  the context. It must be followed by a call to\n *                  \\c mbedtls_chachapoly_setkey() before any operation can be\n *                  done, and to \\c mbedtls_chachapoly_free() once all\n *                  operations with that context have been finished.\n *\n *                  In order to encrypt or decrypt full messages at once, for\n *                  each message you should make a single call to\n *                  \\c mbedtls_chachapoly_crypt_and_tag() or\n *                  \\c mbedtls_chachapoly_auth_decrypt().\n *\n *                  In order to encrypt messages piecewise, for each\n *                  message you should make a call to\n *                  \\c mbedtls_chachapoly_starts(), then 0 or more calls to\n *                  \\c mbedtls_chachapoly_update_aad(), then 0 or more calls to\n *                  \\c mbedtls_chachapoly_update(), then one call to\n *                  \\c mbedtls_chachapoly_finish().\n *\n * \\warning         Decryption with the piecewise API is discouraged! Always\n *                  use \\c mbedtls_chachapoly_auth_decrypt() when possible!\n *\n *                  If however this is not possible because the data is too\n *                  large to fit in memory, you need to:\n *\n *                  - call \\c mbedtls_chachapoly_starts() and (if needed)\n *                  \\c mbedtls_chachapoly_update_aad() as above,\n *                  - call \\c mbedtls_chachapoly_update() multiple times and\n *                  ensure its output (the plaintext) is NOT used in any other\n *                  way than placing it in temporary storage at this point,\n *                  - call \\c mbedtls_chachapoly_finish() to compute the\n *                  authentication tag and compared it in constant time to the\n *                  tag received with the ciphertext.\n *\n *                  If the tags are not equal, you must immediately discard\n *                  all previous outputs of \\c mbedtls_chachapoly_update(),\n *                  otherwise you can now safely use the plaintext.\n *\n * \\param ctx       The ChachaPoly context to initialize. Must not be \\c NULL.\n */\nvoid mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx);\n\n/**\n * \\brief           This function releases and clears the specified\n *                  ChaCha20-Poly1305 context.\n *\n * \\param ctx       The ChachaPoly context to clear. This may be \\c NULL, in which\n *                  case this function is a no-op.\n */\nvoid mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx);\n\n/**\n * \\brief           This function sets the ChaCha20-Poly1305\n *                  symmetric encryption key.\n *\n * \\param ctx       The ChaCha20-Poly1305 context to which the key should be\n *                  bound. This must be initialized.\n * \\param key       The \\c 256 Bit (\\c 32 Bytes) key.\n *\n * \\return          \\c 0 on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,\n                              const unsigned char key[32]);\n\n/**\n * \\brief           This function starts a ChaCha20-Poly1305 encryption or\n *                  decryption operation.\n *\n * \\warning         You must never use the same nonce twice with the same key.\n *                  This would void any confidentiality and authenticity\n *                  guarantees for the messages encrypted with the same nonce\n *                  and key.\n *\n * \\note            If the context is being used for AAD only (no data to\n *                  encrypt or decrypt) then \\p mode can be set to any value.\n *\n * \\warning         Decryption with the piecewise API is discouraged, see the\n *                  warning on \\c mbedtls_chachapoly_init().\n *\n * \\param ctx       The ChaCha20-Poly1305 context. This must be initialized\n *                  and bound to a key.\n * \\param nonce     The nonce/IV to use for the message.\n *                  This must be a readable buffer of length \\c 12 Bytes.\n * \\param mode      The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or\n *                  #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning).\n *\n * \\return          \\c 0 on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,\n                              const unsigned char nonce[12],\n                              mbedtls_chachapoly_mode_t mode);\n\n/**\n * \\brief           This function feeds additional data to be authenticated\n *                  into an ongoing ChaCha20-Poly1305 operation.\n *\n *                  The Additional Authenticated Data (AAD), also called\n *                  Associated Data (AD) is only authenticated but not\n *                  encrypted nor included in the encrypted output. It is\n *                  usually transmitted separately from the ciphertext or\n *                  computed locally by each party.\n *\n * \\note            This function is called before data is encrypted/decrypted.\n *                  I.e. call this function to process the AAD before calling\n *                  \\c mbedtls_chachapoly_update().\n *\n *                  You may call this function multiple times to process\n *                  an arbitrary amount of AAD. It is permitted to call\n *                  this function 0 times, if no AAD is used.\n *\n *                  This function cannot be called any more if data has\n *                  been processed by \\c mbedtls_chachapoly_update(),\n *                  or if the context has been finished.\n *\n * \\warning         Decryption with the piecewise API is discouraged, see the\n *                  warning on \\c mbedtls_chachapoly_init().\n *\n * \\param ctx       The ChaCha20-Poly1305 context. This must be initialized\n *                  and bound to a key.\n * \\param aad_len   The length in Bytes of the AAD. The length has no\n *                  restrictions.\n * \\param aad       Buffer containing the AAD.\n *                  This pointer can be \\c NULL if `aad_len == 0`.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA\n *                  if \\p ctx or \\p aad are NULL.\n * \\return          #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE\n *                  if the operations has not been started or has been\n *                  finished, or if the AAD has been finished.\n */\nint mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx,\n                                  const unsigned char *aad,\n                                  size_t aad_len);\n\n/**\n * \\brief           Thus function feeds data to be encrypted or decrypted\n *                  into an on-going ChaCha20-Poly1305\n *                  operation.\n *\n *                  The direction (encryption or decryption) depends on the\n *                  mode that was given when calling\n *                  \\c mbedtls_chachapoly_starts().\n *\n *                  You may call this function multiple times to process\n *                  an arbitrary amount of data. It is permitted to call\n *                  this function 0 times, if no data is to be encrypted\n *                  or decrypted.\n *\n * \\warning         Decryption with the piecewise API is discouraged, see the\n *                  warning on \\c mbedtls_chachapoly_init().\n *\n * \\param ctx       The ChaCha20-Poly1305 context to use. This must be initialized.\n * \\param len       The length (in bytes) of the data to encrypt or decrypt.\n * \\param input     The buffer containing the data to encrypt or decrypt.\n *                  This pointer can be \\c NULL if `len == 0`.\n * \\param output    The buffer to where the encrypted or decrypted data is\n *                  written. This must be able to hold \\p len bytes.\n *                  This pointer can be \\c NULL if `len == 0`.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE\n *                  if the operation has not been started or has been\n *                  finished.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,\n                              size_t len,\n                              const unsigned char *input,\n                              unsigned char *output);\n\n/**\n * \\brief           This function finished the ChaCha20-Poly1305 operation and\n *                  generates the MAC (authentication tag).\n *\n * \\param ctx       The ChaCha20-Poly1305 context to use. This must be initialized.\n * \\param mac       The buffer to where the 128-bit (16 bytes) MAC is written.\n *\n * \\warning         Decryption with the piecewise API is discouraged, see the\n *                  warning on \\c mbedtls_chachapoly_init().\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE\n *                  if the operation has not been started or has been\n *                  finished.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,\n                              unsigned char mac[16]);\n\n/**\n * \\brief           This function performs a complete ChaCha20-Poly1305\n *                  authenticated encryption with the previously-set key.\n *\n * \\note            Before using this function, you must set the key with\n *                  \\c mbedtls_chachapoly_setkey().\n *\n * \\warning         You must never use the same nonce twice with the same key.\n *                  This would void any confidentiality and authenticity\n *                  guarantees for the messages encrypted with the same nonce\n *                  and key.\n *\n * \\param ctx       The ChaCha20-Poly1305 context to use (holds the key).\n *                  This must be initialized.\n * \\param length    The length (in bytes) of the data to encrypt or decrypt.\n * \\param nonce     The 96-bit (12 bytes) nonce/IV to use.\n * \\param aad       The buffer containing the additional authenticated\n *                  data (AAD). This pointer can be \\c NULL if `aad_len == 0`.\n * \\param aad_len   The length (in bytes) of the AAD data to process.\n * \\param input     The buffer containing the data to encrypt or decrypt.\n *                  This pointer can be \\c NULL if `ilen == 0`.\n * \\param output    The buffer to where the encrypted or decrypted data\n *                  is written. This pointer can be \\c NULL if `ilen == 0`.\n * \\param tag       The buffer to where the computed 128-bit (16 bytes) MAC\n *                  is written. This must not be \\c NULL.\n *\n * \\return          \\c 0 on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx,\n                                       size_t length,\n                                       const unsigned char nonce[12],\n                                       const unsigned char *aad,\n                                       size_t aad_len,\n                                       const unsigned char *input,\n                                       unsigned char *output,\n                                       unsigned char tag[16]);\n\n/**\n * \\brief           This function performs a complete ChaCha20-Poly1305\n *                  authenticated decryption with the previously-set key.\n *\n * \\note            Before using this function, you must set the key with\n *                  \\c mbedtls_chachapoly_setkey().\n *\n * \\param ctx       The ChaCha20-Poly1305 context to use (holds the key).\n * \\param length    The length (in Bytes) of the data to decrypt.\n * \\param nonce     The \\c 96 Bit (\\c 12 bytes) nonce/IV to use.\n * \\param aad       The buffer containing the additional authenticated data (AAD).\n *                  This pointer can be \\c NULL if `aad_len == 0`.\n * \\param aad_len   The length (in bytes) of the AAD data to process.\n * \\param tag       The buffer holding the authentication tag.\n *                  This must be a readable buffer of length \\c 16 Bytes.\n * \\param input     The buffer containing the data to decrypt.\n *                  This pointer can be \\c NULL if `ilen == 0`.\n * \\param output    The buffer to where the decrypted data is written.\n *                  This pointer can be \\c NULL if `ilen == 0`.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED\n *                  if the data was not authentic.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,\n                                    size_t length,\n                                    const unsigned char nonce[12],\n                                    const unsigned char *aad,\n                                    size_t aad_len,\n                                    const unsigned char tag[16],\n                                    const unsigned char *input,\n                                    unsigned char *output);\n\n#if defined(MBEDTLS_SELF_TEST)\n/**\n * \\brief           The ChaCha20-Poly1305 checkup routine.\n *\n * \\return          \\c 0 on success.\n * \\return          \\c 1 on failure.\n */\nint mbedtls_chachapoly_self_test(int verbose);\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_CHACHAPOLY_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/check_config.h",
    "content": "/**\n * \\file check_config.h\n *\n * \\brief Consistency checks for configuration options\n *\n * This is an internal header. Do not include it directly.\n *\n * This header is included automatically by all public Mbed TLS headers\n * (via mbedtls/build_info.h). Do not include it directly in a configuration\n * file such as mbedtls/mbedtls_config.h or #MBEDTLS_USER_CONFIG_FILE!\n * It would run at the wrong time due to missing derived symbols.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CHECK_CONFIG_H\n#define MBEDTLS_CHECK_CONFIG_H\n\n/* *INDENT-OFF* */\n\n#if !defined(MBEDTLS_CONFIG_IS_FINALIZED)\n#warning \"Do not include mbedtls/check_config.h manually! \" \\\n         \"This may cause spurious errors. \" \\\n         \"It is included automatically at the right point since Mbed TLS 3.0.\"\n#endif /* !MBEDTLS_CONFIG_IS_FINALIZED */\n\n/*\n * We assume CHAR_BIT is 8 in many places. In practice, this is true on our\n * target platforms, so not an issue, but let's just be extra sure.\n */\n#include <limits.h>\n#if CHAR_BIT != 8\n#error \"Mbed TLS requires a platform with 8-bit chars\"\n#endif\n\n#include <stdint.h>\n\n#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900)\n#if !defined(MBEDTLS_PLATFORM_C)\n#error \"MBEDTLS_PLATFORM_C is required on Windows\"\n#endif\n/* See auto-enabling SNPRINTF_ALT and VSNPRINTF_ALT\n * in * config_adjust_legacy_crypto.h */\n#endif /* _MINGW32__ || (_MSC_VER && (_MSC_VER <= 1900)) */\n\n#if defined(TARGET_LIKE_MBED) && defined(MBEDTLS_NET_C)\n#error \"The NET module is not available for mbed OS - please use the network functions provided by Mbed OS\"\n#endif\n\n#if defined(MBEDTLS_DEPRECATED_WARNING) && \\\n    !defined(__GNUC__) && !defined(__clang__)\n#error \"MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang\"\n#endif\n\n#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME)\n#error \"MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense\"\n#endif\n\n/* Limitations on ECC key types acceleration: if we have any of `PUBLIC_KEY`,\n * `KEY_PAIR_BASIC`, `KEY_PAIR_IMPORT`, `KEY_PAIR_EXPORT` then we must have\n * all 4 of them.\n */\n#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) || \\\n    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \\\n    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \\\n    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) || \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT)\n#error \"Unsupported partial support for ECC key type acceleration, see docs/driver-only-builds.md\"\n#endif /* not all of public, basic, import, export */\n#endif /* one of public, basic, import, export */\n\n/* Limitations on ECC curves acceleration: partial curve acceleration is only\n * supported with crypto excluding PK, X.509 or TLS.\n * Note: no need to check X.509 as it depends on PK. */\n#if defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256) || \\\n    defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384) || \\\n    defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512) || \\\n    defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255) || \\\n    defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448) || \\\n    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192) || \\\n    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224) || \\\n    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256) || \\\n    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192) || \\\n    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224) || \\\n    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) || \\\n    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384) || \\\n    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521)\n#if defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES)\n#if defined(MBEDTLS_PK_C) || \\\n    defined(MBEDTLS_SSL_TLS_C)\n#error \"Unsupported partial support for ECC curves acceleration, see docs/driver-only-builds.md\"\n#endif /* modules beyond what's supported */\n#endif /* not all curves accelerated */\n#endif /* some curve accelerated */\n\n#if defined(MBEDTLS_CTR_DRBG_C) && !(defined(MBEDTLS_AES_C) || \\\n    (defined(MBEDTLS_PSA_CRYPTO_CLIENT) && defined(PSA_WANT_KEY_TYPE_AES) && \\\n    defined(PSA_WANT_ALG_ECB_NO_PADDING)))\n#error \"MBEDTLS_CTR_DRBG_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C)\n#error \"MBEDTLS_DHM_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_CMAC_C) && \\\n    ( !defined(MBEDTLS_CIPHER_C ) || ( !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) ) )\n#error \"MBEDTLS_CMAC_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_NIST_KW_C) && \\\n    ( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) )\n#error \"MBEDTLS_NIST_KW_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) && defined(MBEDTLS_PSA_CRYPTO_CONFIG)\n#if defined(PSA_WANT_ALG_CBC_NO_PADDING)\n#error \"MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_ALG_CBC_NO_PADDING cannot be defined simultaneously\"\n#endif\n#if defined(PSA_WANT_ALG_CBC_PKCS7)\n#error \"MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_ALG_CBC_PKCS7 cannot be defined simultaneously\"\n#endif\n#if defined(PSA_WANT_ALG_ECB_NO_PADDING)\n#error \"MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_ALG_ECB_NO_PADDING cannot be defined simultaneously\"\n#endif\n#if defined(PSA_WANT_KEY_TYPE_DES)\n#error \"MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_KEY_TYPE_DES cannot be defined simultaneously\"\n#endif\n#endif\n\n#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n#error \"MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_CIPHER_MODE_CBC cannot be defined simultaneously\"\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n#error \"MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_CIPHER_MODE_XTS cannot be defined simultaneously\"\n#endif\n#if defined(MBEDTLS_DES_C)\n#error \"MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_DES_C cannot be defined simultaneously\"\n#endif\n#if defined(MBEDTLS_NIST_KW_C)\n#error \"MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_NIST_KW_C cannot be defined simultaneously\"\n#endif\n#endif\n\n#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C)\n#error \"MBEDTLS_ECDH_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_ECDSA_C) &&            \\\n    ( !defined(MBEDTLS_ECP_C) ||           \\\n      !( defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \\\n         defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \\\n         defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \\\n         defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \\\n         defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \\\n         defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \\\n         defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \\\n         defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || \\\n         defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) ||   \\\n         defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) ||   \\\n         defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) ) || \\\n      !defined(MBEDTLS_ASN1_PARSE_C) ||    \\\n      !defined(MBEDTLS_ASN1_WRITE_C) )\n#error \"MBEDTLS_ECDSA_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_USE_PSA_CRYPTO)\n#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) && !defined(MBEDTLS_ASN1_WRITE_C)\n#error \"MBEDTLS_PK_C with MBEDTLS_USE_PSA_CRYPTO needs MBEDTLS_ASN1_WRITE_C for ECDSA signature\"\n#endif\n#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) && !defined(MBEDTLS_ASN1_PARSE_C)\n#error \"MBEDTLS_PK_C with MBEDTLS_USE_PSA_CRYPTO needs MBEDTLS_ASN1_PARSE_C for ECDSA verification\"\n#endif\n#endif /* MBEDTLS_PK_C && MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_ECJPAKE_C) && \\\n    !defined(MBEDTLS_ECP_C)\n#error \"MBEDTLS_ECJPAKE_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)           && \\\n    ( defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \\\n      defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)     || \\\n      defined(MBEDTLS_ECDSA_SIGN_ALT)          || \\\n      defined(MBEDTLS_ECDSA_VERIFY_ALT)        || \\\n      defined(MBEDTLS_ECDSA_GENKEY_ALT)        || \\\n      defined(MBEDTLS_ECP_INTERNAL_ALT)        || \\\n      defined(MBEDTLS_ECP_ALT) )\n#error \"MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative ECP implementation\"\n#endif\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)           && \\\n    !defined(MBEDTLS_ECP_C)\n#error \"MBEDTLS_ECP_RESTARTABLE defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C)\n#error \"MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_ECP_LIGHT) && ( !defined(MBEDTLS_BIGNUM_C) || (    \\\n    !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) &&                  \\\n    !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) &&                  \\\n    !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) &&                  \\\n    !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) &&                  \\\n    !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) &&                  \\\n    !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)   &&                  \\\n    !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)   &&                  \\\n    !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)   &&                  \\\n    !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) &&                  \\\n    !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) &&                  \\\n    !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) &&                  \\\n    !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) &&                 \\\n    !defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) ) )\n#error \"MBEDTLS_ECP_C defined (or a subset enabled), but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_ENTROPY_C) && \\\n    !(defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_MD_CAN_SHA256))\n#error \"MBEDTLS_ENTROPY_C defined, but not all prerequisites\"\n#endif\n#if defined(MBEDTLS_ENTROPY_C) && \\\n    defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64)\n#error \"MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high\"\n#endif\n#if defined(MBEDTLS_ENTROPY_C) &&                                            \\\n    (defined(MBEDTLS_ENTROPY_FORCE_SHA256) || !defined(MBEDTLS_MD_CAN_SHA512)) \\\n    && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32)\n#error \"MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high\"\n#endif\n#if defined(MBEDTLS_ENTROPY_C) && \\\n    defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_MD_CAN_SHA256)\n#error \"MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites\"\n#endif\n\n#if defined(__has_feature)\n#if __has_feature(memory_sanitizer)\n#define MBEDTLS_HAS_MEMSAN // #undef at the end of this paragraph\n#endif\n#endif\n#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) &&  !defined(MBEDTLS_HAS_MEMSAN)\n#error \"MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer\"\n#endif\n// skip this check for now because V test-self need a `fsanitizer`\n//#if defined(MBEDTLS_HAS_MEMSAN) && defined(MBEDTLS_HAVE_ASM)\n//#error \"MemorySanitizer does not support assembly implementation\"\n//#endif\n#undef MBEDTLS_HAS_MEMSAN // temporary macro defined above\n\n#if defined(MBEDTLS_CCM_C) && \\\n    !(defined(MBEDTLS_CCM_GCM_CAN_AES) || defined(MBEDTLS_CCM_GCM_CAN_ARIA) || \\\n    defined(MBEDTLS_CCM_GCM_CAN_CAMELLIA))\n#error \"MBEDTLS_CCM_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_GCM_C) && \\\n    !(defined(MBEDTLS_CCM_GCM_CAN_AES) || defined(MBEDTLS_CCM_GCM_CAN_ARIA) || \\\n    defined(MBEDTLS_CCM_GCM_CAN_CAMELLIA))\n#error \"MBEDTLS_GCM_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_CHACHA20_C)\n#error \"MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_POLY1305_C)\n#error \"MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT)\n#error \"MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT)\n#error \"MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT)\n#error \"MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT)\n#error \"MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT)\n#error \"MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT)\n#error \"MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT)\n#error \"MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT)\n#error \"MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_ECP_NO_FALLBACK) && !defined(MBEDTLS_ECP_INTERNAL_ALT)\n#error \"MBEDTLS_ECP_NO_FALLBACK defined, but no alternative implementation enabled\"\n#endif\n\n#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C)\n#error \"MBEDTLS_HKDF_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C)\n#error \"MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) &&                 \\\n    ( !defined(MBEDTLS_CAN_ECDH) ||                                       \\\n      !defined(MBEDTLS_PK_CAN_ECDSA_SIGN) ||                                \\\n      !defined(MBEDTLS_X509_CRT_PARSE_C) )\n#error \"MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) &&                 \\\n    ( !defined(MBEDTLS_CAN_ECDH) || !defined(MBEDTLS_RSA_C) ||          \\\n      !defined(MBEDTLS_X509_CRT_PARSE_C) )\n#error \"MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C)\n#error \"MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) &&                     \\\n    !defined(MBEDTLS_CAN_ECDH)\n#error \"MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) &&                   \\\n    ( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) ||           \\\n      !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) )\n#error \"MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) &&                 \\\n    ( !defined(MBEDTLS_CAN_ECDH) || !defined(MBEDTLS_RSA_C) ||          \\\n      !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) )\n#error \"MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) &&                \\\n    ( !defined(MBEDTLS_CAN_ECDH) ||                                       \\\n      !defined(MBEDTLS_PK_CAN_ECDSA_SIGN) ||                                \\\n      !defined(MBEDTLS_X509_CRT_PARSE_C) )\n#error \"MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) &&                   \\\n    ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \\\n      !defined(MBEDTLS_PKCS1_V15) )\n#error \"MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) &&                       \\\n    ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \\\n      !defined(MBEDTLS_PKCS1_V15) )\n#error \"MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) &&    \\\n    ( !defined(PSA_WANT_ALG_JPAKE) ||                   \\\n      !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \\\n      !defined(PSA_WANT_ECC_SECP_R1_256) )\n#error \"MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites\"\n#endif\n#else /* MBEDTLS_USE_PSA_CRYPTO */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) &&    \\\n    ( !defined(MBEDTLS_ECJPAKE_C) ||                    \\\n      !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) )\n#error \"MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites\"\n#endif\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n/* Use of EC J-PAKE in TLS requires SHA-256. */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) &&                    \\\n    !defined(MBEDTLS_MD_CAN_SHA256)\n#error \"MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) &&        \\\n    !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) &&            \\\n    !defined(MBEDTLS_MD_CAN_SHA256) &&                        \\\n    !defined(MBEDTLS_MD_CAN_SHA512) &&                        \\\n    !defined(MBEDTLS_MD_CAN_SHA1)\n#error \"!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE requires SHA-512, SHA-256 or SHA-1\".\n#endif\n\n#if defined(MBEDTLS_MD_C) && \\\n    !defined(MBEDTLS_MD_CAN_MD5) && \\\n    !defined(MBEDTLS_MD_CAN_RIPEMD160) && \\\n    !defined(MBEDTLS_MD_CAN_SHA1) && \\\n    !defined(MBEDTLS_MD_CAN_SHA224) && \\\n    !defined(MBEDTLS_MD_CAN_SHA256) && \\\n    !defined(MBEDTLS_MD_CAN_SHA384) && \\\n    !defined(MBEDTLS_MD_CAN_SHA512) && \\\n    !defined(MBEDTLS_MD_CAN_SHA3_224) && \\\n    !defined(MBEDTLS_MD_CAN_SHA3_256) && \\\n    !defined(MBEDTLS_MD_CAN_SHA3_384) && \\\n    !defined(MBEDTLS_MD_CAN_SHA3_512)\n#error \"MBEDTLS_MD_C defined, but no hash algorithm\"\n#endif\n\n#if defined(MBEDTLS_LMS_C) &&                                          \\\n    ! ( defined(MBEDTLS_PSA_CRYPTO_CLIENT) && defined(PSA_WANT_ALG_SHA_256) )\n#error \"MBEDTLS_LMS_C requires MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256\"\n#endif\n\n#if defined(MBEDTLS_LMS_PRIVATE) &&                                    \\\n    ( !defined(MBEDTLS_LMS_C) )\n#error \"MBEDTLS_LMS_PRIVATE requires MBEDTLS_LMS_C\"\n#endif\n\n#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) &&                          \\\n    ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) )\n#error \"MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)\n#error \"MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)\n#error \"MBEDTLS_MEMORY_DEBUG defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C)\n#error \"MBEDTLS_PEM_PARSE_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C)\n#error \"MBEDTLS_PEM_WRITE_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PK_C) && \\\n    !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n#error \"MBEDTLS_PK_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PK_PARSE_C) && \\\n    (!defined(MBEDTLS_ASN1_PARSE_C) || \\\n     !defined(MBEDTLS_OID_C)        || \\\n     !defined(MBEDTLS_PK_C))\n#error \"MBEDTLS_PK_PARSE_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PK_WRITE_C) && \\\n    (!defined(MBEDTLS_ASN1_WRITE_C) || \\\n     !defined(MBEDTLS_OID_C)        || \\\n     !defined(MBEDTLS_PK_C))\n#error \"MBEDTLS_PK_WRITE_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C)\n#error \"MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C)\n#error \"MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\\\n    ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\\\n        defined(MBEDTLS_PLATFORM_EXIT_ALT) )\n#error \"MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_SETBUF_ALT) && !defined(MBEDTLS_PLATFORM_C)\n#error \"MBEDTLS_PLATFORM_SETBUF_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_SETBUF_MACRO) && !defined(MBEDTLS_PLATFORM_C)\n#error \"MBEDTLS_PLATFORM_SETBUF_MACRO defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_SETBUF_MACRO) &&\\\n    ( defined(MBEDTLS_PLATFORM_STD_SETBUF) ||\\\n        defined(MBEDTLS_PLATFORM_SETBUF_ALT) )\n#error \"MBEDTLS_PLATFORM_SETBUF_MACRO and MBEDTLS_PLATFORM_STD_SETBUF/MBEDTLS_PLATFORM_SETBUF_ALT cannot be defined simultaneously\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\\\n    ( !defined(MBEDTLS_PLATFORM_C) ||\\\n        !defined(MBEDTLS_HAVE_TIME) )\n#error \"MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\\\n    ( !defined(MBEDTLS_PLATFORM_C) ||\\\n        !defined(MBEDTLS_HAVE_TIME) )\n#error \"MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO) &&\\\n    ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_HAVE_TIME) )\n#error \"MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_MS_TIME_ALT)   && \\\n    ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_HAVE_TIME) )\n#error \"MBEDTLS_PLATFORM_MS_TIME_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\\\n    ( !defined(MBEDTLS_PLATFORM_C) ||\\\n        !defined(MBEDTLS_HAVE_TIME) )\n#error \"MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\\\n    ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\\\n        defined(MBEDTLS_PLATFORM_TIME_ALT) )\n#error \"MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\\\n    ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\\\n        defined(MBEDTLS_PLATFORM_TIME_ALT) )\n#error \"MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C)\n#error \"MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C)\n#error \"MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\\\n    ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\\\n        defined(MBEDTLS_PLATFORM_FPRINTF_ALT) )\n#error \"MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\\\n    ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) )\n#error \"MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\\\n    defined(MBEDTLS_PLATFORM_STD_FREE)\n#error \"MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO)\n#error \"MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\\\n    ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) )\n#error \"MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\\\n    defined(MBEDTLS_PLATFORM_STD_CALLOC)\n#error \"MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO)\n#error \"MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C)\n#error \"MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C)\n#error \"MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C)\n#error \"MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\\\n    ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\\\n        defined(MBEDTLS_PLATFORM_PRINTF_ALT) )\n#error \"MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C)\n#error \"MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C)\n#error \"MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\\\n    ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\\\n        defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) )\n#error \"MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C)\n#error \"MBEDTLS_PLATFORM_VSNPRINTF_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C)\n#error \"MBEDTLS_PLATFORM_VSNPRINTF_MACRO defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) &&\\\n    ( defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) ||\\\n        defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) )\n#error \"MBEDTLS_PLATFORM_VSNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_VSNPRINTF/MBEDTLS_PLATFORM_VSNPRINTF_ALT cannot be defined simultaneously\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\\\n    !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS)\n#error \"MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY)\n#error \"MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY)\n#error \"MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\\\n    !defined(MBEDTLS_PLATFORM_EXIT_ALT)\n#error \"MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_STD_TIME) &&\\\n    ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\\\n        !defined(MBEDTLS_HAVE_TIME) )\n#error \"MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\\\n    !defined(MBEDTLS_PLATFORM_FPRINTF_ALT)\n#error \"MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\\\n    !defined(MBEDTLS_PLATFORM_PRINTF_ALT)\n#error \"MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\\\n    !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)\n#error \"MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\\\n    ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) )\n#error \"MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\\\n    !defined(MBEDTLS_ENTROPY_NV_SEED)\n#error \"MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\\\n    !defined(MBEDTLS_PLATFORM_NV_SEED_ALT)\n#error \"MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\\\n    !defined(MBEDTLS_PLATFORM_NV_SEED_ALT)\n#error \"MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\\\n    ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\\\n      defined(MBEDTLS_PLATFORM_NV_SEED_ALT) )\n#error \"MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\\\n    ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\\\n      defined(MBEDTLS_PLATFORM_NV_SEED_ALT) )\n#error \"MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously\"\n#endif\n\n#if defined(MBEDTLS_PSA_CRYPTO_C) &&                                    \\\n    !( ( ( defined(MBEDTLS_CTR_DRBG_C) || defined(MBEDTLS_HMAC_DRBG_C) ) && \\\n         defined(MBEDTLS_ENTROPY_C) ) ||                                \\\n       defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) )\n#error \"MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites (missing RNG)\"\n#endif\n\n#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_HAVE_SOFT_BLOCK_MODE) && \\\n    defined(PSA_HAVE_SOFT_BLOCK_CIPHER) && !defined(MBEDTLS_CIPHER_C)\n#error \"MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PSA_CRYPTO_SPM) && !defined(MBEDTLS_PSA_CRYPTO_C)\n#error \"MBEDTLS_PSA_CRYPTO_SPM defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C) &&    \\\n    ! ( defined(MBEDTLS_PSA_CRYPTO_C) && \\\n        defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) )\n#error \"MBEDTLS_PSA_CRYPTO_SE_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n#if defined(MBEDTLS_DEPRECATED_REMOVED)\n#error \"MBEDTLS_PSA_CRYPTO_SE_C is deprecated and will be removed in a future version of Mbed TLS\"\n#elif defined(MBEDTLS_DEPRECATED_WARNING)\n#warning \"MBEDTLS_PSA_CRYPTO_SE_C is deprecated and will be removed in a future version of Mbed TLS\"\n#endif\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) &&            \\\n    ! defined(MBEDTLS_PSA_CRYPTO_C)\n#error \"MBEDTLS_PSA_CRYPTO_STORAGE_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PSA_INJECT_ENTROPY) &&      \\\n    !( defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \\\n       defined(MBEDTLS_ENTROPY_NV_SEED) )\n#error \"MBEDTLS_PSA_INJECT_ENTROPY defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_PSA_INJECT_ENTROPY) &&              \\\n    !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)\n#error \"MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources\"\n#endif\n\n#if defined(MBEDTLS_PSA_INJECT_ENTROPY) &&              \\\n    defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)\n#error \"MBEDTLS_PSA_INJECT_ENTROPY is not compatible with MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG\"\n#endif\n\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) &&           \\\n    defined(MBEDTLS_PSA_STATIC_KEY_SLOTS)\n#error \"MBEDTLS_PSA_KEY_STORE_DYNAMIC and MBEDTLS_PSA_STATIC_KEY_SLOTS cannot be defined simultaneously\"\n#endif\n\n#if defined(MBEDTLS_PSA_ITS_FILE_C) && \\\n    !defined(MBEDTLS_FS_IO)\n#error \"MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) ||         \\\n    !defined(MBEDTLS_OID_C) )\n#error \"MBEDTLS_RSA_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) &&         \\\n    !defined(MBEDTLS_PKCS1_V15) )\n#error \"MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled\"\n#endif\n\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) &&                        \\\n    ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) )\n#error \"MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) && \\\n    defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)\n#error \"Must only define one of MBEDTLS_SHA512_USE_A64_CRYPTO_*\"\n#endif\n\n#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \\\n    defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)\n#if !defined(MBEDTLS_SHA512_C)\n#error \"MBEDTLS_SHA512_USE_A64_CRYPTO_* defined without MBEDTLS_SHA512_C\"\n#endif\n#if defined(MBEDTLS_SHA512_ALT) || defined(MBEDTLS_SHA512_PROCESS_ALT)\n#error \"MBEDTLS_SHA512_*ALT can't be used with MBEDTLS_SHA512_USE_A64_CRYPTO_*\"\n#endif\n\n#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */\n\n#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) && !defined(__aarch64__)\n#error \"MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY defined on non-Aarch64 system\"\n#endif\n\n#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) && \\\n    defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)\n#error \"Must only define one of MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*\"\n#endif\n\n#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \\\n    defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)\n#if !defined(MBEDTLS_SHA256_C)\n#error \"MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_* defined without MBEDTLS_SHA256_C\"\n#endif\n#if defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA256_PROCESS_ALT)\n#error \"MBEDTLS_SHA256_*ALT can't be used with MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*\"\n#endif\n\n#endif\n\n#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) && !defined(MBEDTLS_ARCH_IS_ARMV8_A)\n#error \"MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY defined on non-Armv8-A system\"\n#endif\n\n/* TLS 1.3 requires separate HKDF parts from PSA,\n * and at least one ciphersuite, so at least SHA-256 or SHA-384\n * from PSA to use with HKDF.\n *\n * Note: for dependencies common with TLS 1.2 (running handshake hash),\n * see MBEDTLS_SSL_TLS_C. */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \\\n    !(defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \\\n      defined(PSA_WANT_ALG_HKDF_EXTRACT) && \\\n      defined(PSA_WANT_ALG_HKDF_EXPAND) && \\\n      (defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_384)))\n#error \"MBEDTLS_SSL_PROTO_TLS1_3 defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n#if !( (defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)) && \\\n       defined(MBEDTLS_X509_CRT_PARSE_C) && \\\n       ( defined(MBEDTLS_PK_CAN_ECDSA_SIGN) || defined(MBEDTLS_PKCS1_V21) ) )\n#error \"MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED defined, but not all prerequisites\"\n#endif\n#endif\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)\n#if !( defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) )\n#error \"MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED defined, but not all prerequisites\"\n#endif\n#endif\n\n/*\n * The current implementation of TLS 1.3 requires MBEDTLS_SSL_KEEP_PEER_CERTIFICATE.\n */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n#error \"MBEDTLS_SSL_PROTO_TLS1_3 defined without MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\"\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2) &&                                    \\\n    !(defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) ||                          \\\n      defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                      \\\n      defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                    \\\n      defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                  \\\n      defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                     \\\n      defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) ||                   \\\n      defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) ||                          \\\n      defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) ||                      \\\n      defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) ||                      \\\n      defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||                    \\\n      defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) )\n#error \"One or more versions of the TLS protocol are enabled \" \\\n        \"but no key exchange methods defined with MBEDTLS_KEY_EXCHANGE_xxxx\"\n#endif\n\n#if defined(MBEDTLS_SSL_EARLY_DATA) && \\\n    ( !defined(MBEDTLS_SSL_SESSION_TICKETS) || \\\n      ( !defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) && \\\n        !defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) ) )\n#error \"MBEDTLS_SSL_EARLY_DATA  defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) && \\\n    defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE) &&                      \\\n        ((MBEDTLS_SSL_MAX_EARLY_DATA_SIZE < 0) ||                    \\\n         (MBEDTLS_SSL_MAX_EARLY_DATA_SIZE > UINT32_MAX))\n#error \"MBEDTLS_SSL_MAX_EARLY_DATA_SIZE must be in the range(0..UINT32_MAX)\"\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)     && \\\n    !defined(MBEDTLS_SSL_PROTO_TLS1_2)\n#error \"MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C)\n#error \"MBEDTLS_SSL_CLI_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && !defined(MBEDTLS_X509_CRT_PARSE_C)\n#error \"MBEDTLS_SSL_ASYNC_PRIVATE defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_TLS_C) && !(defined(MBEDTLS_CIPHER_C) || \\\n    defined(MBEDTLS_USE_PSA_CRYPTO))\n#error \"MBEDTLS_SSL_TLS_C defined, but not all prerequisites\"\n#endif\n\n/* TLS 1.2 and 1.3 require SHA-256 or SHA-384 (running handshake hash) */\n#if defined(MBEDTLS_SSL_TLS_C)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#if !(defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_384))\n#error \"MBEDTLS_SSL_TLS_C defined, but not all prerequisites\"\n#endif\n#else /* MBEDTLS_USE_PSA_CRYPTO */\n#if !defined(MBEDTLS_MD_C) || \\\n    !(defined(MBEDTLS_MD_CAN_SHA256) || defined(MBEDTLS_MD_CAN_SHA384))\n#error \"MBEDTLS_SSL_TLS_C defined, but not all prerequisites\"\n#endif\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#endif /* MBEDTLS_SSL_TLS_C */\n\n#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C)\n#error \"MBEDTLS_SSL_SRV_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_TLS_C) && \\\n    !( defined(MBEDTLS_SSL_PROTO_TLS1_2) || defined(MBEDTLS_SSL_PROTO_TLS1_3) )\n#error \"MBEDTLS_SSL_TLS_C defined, but no protocols are active\"\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS)\n#error \"MBEDTLS_SSL_DTLS_HELLO_VERIFY  defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \\\n    !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)\n#error \"MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE  defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) &&                              \\\n    ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) )\n#error \"MBEDTLS_SSL_DTLS_ANTI_REPLAY  defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) &&                              \\\n    ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) )\n#error \"MBEDTLS_SSL_DTLS_CONNECTION_ID  defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)            &&                 \\\n    defined(MBEDTLS_SSL_CID_IN_LEN_MAX) &&                 \\\n    MBEDTLS_SSL_CID_IN_LEN_MAX > 255\n#error \"MBEDTLS_SSL_CID_IN_LEN_MAX too large (max 255)\"\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)            &&                  \\\n    defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) &&                 \\\n    MBEDTLS_SSL_CID_OUT_LEN_MAX > 255\n#error \"MBEDTLS_SSL_CID_OUT_LEN_MAX too large (max 255)\"\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT)     &&                 \\\n    !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n#error \"MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) && MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT != 0\n#if defined(MBEDTLS_DEPRECATED_REMOVED)\n#error \"MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT is deprecated and will be removed in a future version of Mbed TLS\"\n#elif defined(MBEDTLS_DEPRECATED_WARNING)\n#warning \"MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT is deprecated and will be removed in a future version of Mbed TLS\"\n#endif\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT && MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT != 0 */\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) &&   \\\n    !defined(MBEDTLS_SSL_PROTO_TLS1_2)\n#error \"MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \\\n    !defined(MBEDTLS_SSL_PROTO_TLS1_2)\n#error \"MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION) && \\\n    !defined(MBEDTLS_SSL_PROTO_TLS1_2)\n#error \"MBEDTLS_SSL_RENEGOTIATION defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_TICKET_C) && ( !defined(MBEDTLS_CIPHER_C) && \\\n                                       !defined(MBEDTLS_USE_PSA_CRYPTO) )\n#error \"MBEDTLS_SSL_TICKET_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_TICKET_C) && \\\n    !( defined(MBEDTLS_SSL_HAVE_CCM) || defined(MBEDTLS_SSL_HAVE_GCM) || \\\n    defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) )\n#error \"MBEDTLS_SSL_TICKET_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH) && \\\n    MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH >= 256\n#error \"MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH must be less than 256\"\n#endif\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \\\n        !defined(MBEDTLS_X509_CRT_PARSE_C)\n#error \"MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_THREADING_PTHREAD)\n#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL)\n#error \"MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites\"\n#endif\n#define MBEDTLS_THREADING_IMPL // undef at the end of this paragraph\n#endif\n#if defined(MBEDTLS_THREADING_ALT)\n#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL)\n#error \"MBEDTLS_THREADING_ALT defined, but not all prerequisites\"\n#endif\n#define MBEDTLS_THREADING_IMPL // undef at the end of this paragraph\n#endif\n#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL)\n#error \"MBEDTLS_THREADING_C defined, single threading implementation required\"\n#endif\n#undef MBEDTLS_THREADING_IMPL // temporary macro defined above\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_CLIENT)\n#error \"MBEDTLS_USE_PSA_CRYPTO defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C)\n#error \"MBEDTLS_VERSION_FEATURES defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_X509_USE_C) && \\\n    (!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) ||   \\\n    !defined(MBEDTLS_PK_PARSE_C) ||                                 \\\n    ( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) )\n#error \"MBEDTLS_X509_USE_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_X509_CREATE_C) && \\\n    (!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) ||      \\\n    !defined(MBEDTLS_PK_PARSE_C) ||                                    \\\n    ( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) )\n#error \"MBEDTLS_X509_CREATE_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) )\n#error \"MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) )\n#error \"MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) )\n#error \"MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) )\n#error \"MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) )\n#error \"MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) && \\\n            ( !defined(MBEDTLS_X509_CRT_PARSE_C) )\n#error \"MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64)\n#error \"MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously\"\n#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */\n\n#if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \\\n    defined(MBEDTLS_HAVE_ASM)\n#error \"MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously\"\n#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP) && ( !defined(MBEDTLS_SSL_PROTO_DTLS) )\n#error \"MBEDTLS_SSL_DTLS_SRTP defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) && ( !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) )\n#error \"MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) && ( !defined(MBEDTLS_SSL_PROTO_TLS1_3) )\n#error \"MBEDTLS_SSL_RECORD_SIZE_LIMIT defined, but not all prerequisites\"\n#endif\n\n#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) && \\\n    !( defined(MBEDTLS_SSL_HAVE_CCM) || defined(MBEDTLS_SSL_HAVE_GCM) || \\\n    defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) )\n#error \"MBEDTLS_SSL_CONTEXT_SERIALIZATION defined, but not all prerequisites\"\n#endif\n\n/* Reject attempts to enable options that have been removed and that could\n * cause a build to succeed but with features removed. */\n\n#if defined(MBEDTLS_HAVEGE_C) //no-check-names\n#error \"MBEDTLS_HAVEGE_C was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/2599\"\n#endif\n\n#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) //no-check-names\n#error \"MBEDTLS_SSL_HW_RECORD_ACCEL was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031\"\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_SSL3) //no-check-names\n#error \"MBEDTLS_SSL_PROTO_SSL3 (SSL v3.0 support) was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031\"\n#endif\n\n#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) //no-check-names\n#error \"MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO (SSL v2 ClientHello support) was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031\"\n#endif\n\n#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) //no-check-names\n#error \"MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT (compatibility with the buggy implementation of truncated HMAC in Mbed TLS up to 2.7) was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031\"\n#endif\n\n#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) //no-check-names\n#error \"MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES was removed in Mbed TLS 3.0. See the ChangeLog entry if you really need SHA-1-signed certificates.\"\n#endif\n\n#if defined(MBEDTLS_ZLIB_SUPPORT) //no-check-names\n#error \"MBEDTLS_ZLIB_SUPPORT was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031\"\n#endif\n\n#if defined(MBEDTLS_CHECK_PARAMS) //no-check-names\n#error \"MBEDTLS_CHECK_PARAMS was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4313\"\n#endif\n\n#if defined(MBEDTLS_SSL_CID_PADDING_GRANULARITY) //no-check-names\n#error \"MBEDTLS_SSL_CID_PADDING_GRANULARITY was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4335\"\n#endif\n\n#if defined(MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY) //no-check-names\n#error \"MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4335\"\n#endif\n\n#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) //no-check-names\n#error \"MBEDTLS_SSL_TRUNCATED_HMAC was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4341\"\n#endif\n\n#if defined(MBEDTLS_PKCS7_C) && ( ( !defined(MBEDTLS_ASN1_PARSE_C) ) || \\\n    ( !defined(MBEDTLS_OID_C) ) || ( !defined(MBEDTLS_PK_PARSE_C) ) || \\\n    ( !defined(MBEDTLS_X509_CRT_PARSE_C) ) || \\\n    ( !defined(MBEDTLS_X509_CRL_PARSE_C) ) || \\\n    ( !defined(MBEDTLS_MD_C) ) )\n#error  \"MBEDTLS_PKCS7_C is defined, but not all prerequisites\"\n#endif\n\n/*\n * Avoid warning from -pedantic. This is a convenient place for this\n * workaround since this is included by every single file before the\n * #if defined(MBEDTLS_xxx_C) that results in empty translation units.\n */\ntypedef int mbedtls_iso_c_forbids_empty_translation_units;\n\n/* *INDENT-ON* */\n#endif /* MBEDTLS_CHECK_CONFIG_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/cipher.h",
    "content": "/**\n * \\file cipher.h\n *\n * \\brief This file contains an abstraction interface for use with the cipher\n * primitives provided by the library. It provides a common interface to all of\n * the available cipher operations.\n *\n * \\author Adriaan de Jong <dejong@fox-it.com>\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CIPHER_H\n#define MBEDTLS_CIPHER_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n#include \"mbedtls/platform_util.h\"\n\n#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C)\n#define MBEDTLS_CIPHER_MODE_AEAD\n#endif\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n#define MBEDTLS_CIPHER_MODE_WITH_PADDING\n#endif\n\n#if defined(MBEDTLS_CIPHER_NULL_CIPHER) || \\\n    defined(MBEDTLS_CHACHA20_C)\n#define MBEDTLS_CIPHER_MODE_STREAM\n#endif\n\n/** The selected feature is not available. */\n#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE  -0x6080\n/** Bad input parameters. */\n#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA       -0x6100\n/** Failed to allocate memory. */\n#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED         -0x6180\n/** Input data contains invalid padding and is rejected. */\n#define MBEDTLS_ERR_CIPHER_INVALID_PADDING      -0x6200\n/** Decryption of block requires a full block. */\n#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED  -0x6280\n/** Authentication failed (for AEAD modes). */\n#define MBEDTLS_ERR_CIPHER_AUTH_FAILED          -0x6300\n/** The context is invalid. For example, because it was freed. */\n#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT      -0x6380\n\n#define MBEDTLS_CIPHER_VARIABLE_IV_LEN     0x01    /**< Cipher accepts IVs of variable length. */\n#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN    0x02    /**< Cipher accepts keys of variable length. */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief     Supported cipher types.\n *\n * \\warning   DES/3DES are considered weak ciphers and their use\n *            constitutes a security risk. We recommend considering stronger\n *            ciphers instead.\n */\ntypedef enum {\n    MBEDTLS_CIPHER_ID_NONE = 0,  /**< Placeholder to mark the end of cipher ID lists. */\n    MBEDTLS_CIPHER_ID_NULL,      /**< The identity cipher, treated as a stream cipher. */\n    MBEDTLS_CIPHER_ID_AES,       /**< The AES cipher. */\n    MBEDTLS_CIPHER_ID_DES,       /**< The DES cipher. \\warning DES is considered weak. */\n    MBEDTLS_CIPHER_ID_3DES,      /**< The Triple DES cipher. \\warning 3DES is considered weak. */\n    MBEDTLS_CIPHER_ID_CAMELLIA,  /**< The Camellia cipher. */\n    MBEDTLS_CIPHER_ID_ARIA,      /**< The Aria cipher. */\n    MBEDTLS_CIPHER_ID_CHACHA20,  /**< The ChaCha20 cipher. */\n} mbedtls_cipher_id_t;\n\n/**\n * \\brief     Supported {cipher type, cipher mode} pairs.\n *\n * \\warning   DES/3DES are considered weak ciphers and their use\n *            constitutes a security risk. We recommend considering stronger\n *            ciphers instead.\n */\ntypedef enum {\n    MBEDTLS_CIPHER_NONE = 0,             /**< Placeholder to mark the end of cipher-pair lists. */\n    MBEDTLS_CIPHER_NULL,                 /**< The identity stream cipher. */\n    MBEDTLS_CIPHER_AES_128_ECB,          /**< AES cipher with 128-bit ECB mode. */\n    MBEDTLS_CIPHER_AES_192_ECB,          /**< AES cipher with 192-bit ECB mode. */\n    MBEDTLS_CIPHER_AES_256_ECB,          /**< AES cipher with 256-bit ECB mode. */\n    MBEDTLS_CIPHER_AES_128_CBC,          /**< AES cipher with 128-bit CBC mode. */\n    MBEDTLS_CIPHER_AES_192_CBC,          /**< AES cipher with 192-bit CBC mode. */\n    MBEDTLS_CIPHER_AES_256_CBC,          /**< AES cipher with 256-bit CBC mode. */\n    MBEDTLS_CIPHER_AES_128_CFB128,       /**< AES cipher with 128-bit CFB128 mode. */\n    MBEDTLS_CIPHER_AES_192_CFB128,       /**< AES cipher with 192-bit CFB128 mode. */\n    MBEDTLS_CIPHER_AES_256_CFB128,       /**< AES cipher with 256-bit CFB128 mode. */\n    MBEDTLS_CIPHER_AES_128_CTR,          /**< AES cipher with 128-bit CTR mode. */\n    MBEDTLS_CIPHER_AES_192_CTR,          /**< AES cipher with 192-bit CTR mode. */\n    MBEDTLS_CIPHER_AES_256_CTR,          /**< AES cipher with 256-bit CTR mode. */\n    MBEDTLS_CIPHER_AES_128_GCM,          /**< AES cipher with 128-bit GCM mode. */\n    MBEDTLS_CIPHER_AES_192_GCM,          /**< AES cipher with 192-bit GCM mode. */\n    MBEDTLS_CIPHER_AES_256_GCM,          /**< AES cipher with 256-bit GCM mode. */\n    MBEDTLS_CIPHER_CAMELLIA_128_ECB,     /**< Camellia cipher with 128-bit ECB mode. */\n    MBEDTLS_CIPHER_CAMELLIA_192_ECB,     /**< Camellia cipher with 192-bit ECB mode. */\n    MBEDTLS_CIPHER_CAMELLIA_256_ECB,     /**< Camellia cipher with 256-bit ECB mode. */\n    MBEDTLS_CIPHER_CAMELLIA_128_CBC,     /**< Camellia cipher with 128-bit CBC mode. */\n    MBEDTLS_CIPHER_CAMELLIA_192_CBC,     /**< Camellia cipher with 192-bit CBC mode. */\n    MBEDTLS_CIPHER_CAMELLIA_256_CBC,     /**< Camellia cipher with 256-bit CBC mode. */\n    MBEDTLS_CIPHER_CAMELLIA_128_CFB128,  /**< Camellia cipher with 128-bit CFB128 mode. */\n    MBEDTLS_CIPHER_CAMELLIA_192_CFB128,  /**< Camellia cipher with 192-bit CFB128 mode. */\n    MBEDTLS_CIPHER_CAMELLIA_256_CFB128,  /**< Camellia cipher with 256-bit CFB128 mode. */\n    MBEDTLS_CIPHER_CAMELLIA_128_CTR,     /**< Camellia cipher with 128-bit CTR mode. */\n    MBEDTLS_CIPHER_CAMELLIA_192_CTR,     /**< Camellia cipher with 192-bit CTR mode. */\n    MBEDTLS_CIPHER_CAMELLIA_256_CTR,     /**< Camellia cipher with 256-bit CTR mode. */\n    MBEDTLS_CIPHER_CAMELLIA_128_GCM,     /**< Camellia cipher with 128-bit GCM mode. */\n    MBEDTLS_CIPHER_CAMELLIA_192_GCM,     /**< Camellia cipher with 192-bit GCM mode. */\n    MBEDTLS_CIPHER_CAMELLIA_256_GCM,     /**< Camellia cipher with 256-bit GCM mode. */\n    MBEDTLS_CIPHER_DES_ECB,              /**< DES cipher with ECB mode. \\warning DES is considered weak. */\n    MBEDTLS_CIPHER_DES_CBC,              /**< DES cipher with CBC mode. \\warning DES is considered weak. */\n    MBEDTLS_CIPHER_DES_EDE_ECB,          /**< DES cipher with EDE ECB mode. \\warning 3DES is considered weak. */\n    MBEDTLS_CIPHER_DES_EDE_CBC,          /**< DES cipher with EDE CBC mode. \\warning 3DES is considered weak. */\n    MBEDTLS_CIPHER_DES_EDE3_ECB,         /**< DES cipher with EDE3 ECB mode. \\warning 3DES is considered weak. */\n    MBEDTLS_CIPHER_DES_EDE3_CBC,         /**< DES cipher with EDE3 CBC mode. \\warning 3DES is considered weak. */\n    MBEDTLS_CIPHER_AES_128_CCM,          /**< AES cipher with 128-bit CCM mode. */\n    MBEDTLS_CIPHER_AES_192_CCM,          /**< AES cipher with 192-bit CCM mode. */\n    MBEDTLS_CIPHER_AES_256_CCM,          /**< AES cipher with 256-bit CCM mode. */\n    MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, /**< AES cipher with 128-bit CCM_STAR_NO_TAG mode. */\n    MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, /**< AES cipher with 192-bit CCM_STAR_NO_TAG mode. */\n    MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, /**< AES cipher with 256-bit CCM_STAR_NO_TAG mode. */\n    MBEDTLS_CIPHER_CAMELLIA_128_CCM,     /**< Camellia cipher with 128-bit CCM mode. */\n    MBEDTLS_CIPHER_CAMELLIA_192_CCM,     /**< Camellia cipher with 192-bit CCM mode. */\n    MBEDTLS_CIPHER_CAMELLIA_256_CCM,     /**< Camellia cipher with 256-bit CCM mode. */\n    MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, /**< Camellia cipher with 128-bit CCM_STAR_NO_TAG mode. */\n    MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, /**< Camellia cipher with 192-bit CCM_STAR_NO_TAG mode. */\n    MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, /**< Camellia cipher with 256-bit CCM_STAR_NO_TAG mode. */\n    MBEDTLS_CIPHER_ARIA_128_ECB,         /**< Aria cipher with 128-bit key and ECB mode. */\n    MBEDTLS_CIPHER_ARIA_192_ECB,         /**< Aria cipher with 192-bit key and ECB mode. */\n    MBEDTLS_CIPHER_ARIA_256_ECB,         /**< Aria cipher with 256-bit key and ECB mode. */\n    MBEDTLS_CIPHER_ARIA_128_CBC,         /**< Aria cipher with 128-bit key and CBC mode. */\n    MBEDTLS_CIPHER_ARIA_192_CBC,         /**< Aria cipher with 192-bit key and CBC mode. */\n    MBEDTLS_CIPHER_ARIA_256_CBC,         /**< Aria cipher with 256-bit key and CBC mode. */\n    MBEDTLS_CIPHER_ARIA_128_CFB128,      /**< Aria cipher with 128-bit key and CFB-128 mode. */\n    MBEDTLS_CIPHER_ARIA_192_CFB128,      /**< Aria cipher with 192-bit key and CFB-128 mode. */\n    MBEDTLS_CIPHER_ARIA_256_CFB128,      /**< Aria cipher with 256-bit key and CFB-128 mode. */\n    MBEDTLS_CIPHER_ARIA_128_CTR,         /**< Aria cipher with 128-bit key and CTR mode. */\n    MBEDTLS_CIPHER_ARIA_192_CTR,         /**< Aria cipher with 192-bit key and CTR mode. */\n    MBEDTLS_CIPHER_ARIA_256_CTR,         /**< Aria cipher with 256-bit key and CTR mode. */\n    MBEDTLS_CIPHER_ARIA_128_GCM,         /**< Aria cipher with 128-bit key and GCM mode. */\n    MBEDTLS_CIPHER_ARIA_192_GCM,         /**< Aria cipher with 192-bit key and GCM mode. */\n    MBEDTLS_CIPHER_ARIA_256_GCM,         /**< Aria cipher with 256-bit key and GCM mode. */\n    MBEDTLS_CIPHER_ARIA_128_CCM,         /**< Aria cipher with 128-bit key and CCM mode. */\n    MBEDTLS_CIPHER_ARIA_192_CCM,         /**< Aria cipher with 192-bit key and CCM mode. */\n    MBEDTLS_CIPHER_ARIA_256_CCM,         /**< Aria cipher with 256-bit key and CCM mode. */\n    MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, /**< Aria cipher with 128-bit key and CCM_STAR_NO_TAG mode. */\n    MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, /**< Aria cipher with 192-bit key and CCM_STAR_NO_TAG mode. */\n    MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, /**< Aria cipher with 256-bit key and CCM_STAR_NO_TAG mode. */\n    MBEDTLS_CIPHER_AES_128_OFB,          /**< AES 128-bit cipher in OFB mode. */\n    MBEDTLS_CIPHER_AES_192_OFB,          /**< AES 192-bit cipher in OFB mode. */\n    MBEDTLS_CIPHER_AES_256_OFB,          /**< AES 256-bit cipher in OFB mode. */\n    MBEDTLS_CIPHER_AES_128_XTS,          /**< AES 128-bit cipher in XTS block mode. */\n    MBEDTLS_CIPHER_AES_256_XTS,          /**< AES 256-bit cipher in XTS block mode. */\n    MBEDTLS_CIPHER_CHACHA20,             /**< ChaCha20 stream cipher. */\n    MBEDTLS_CIPHER_CHACHA20_POLY1305,    /**< ChaCha20-Poly1305 AEAD cipher. */\n    MBEDTLS_CIPHER_AES_128_KW,           /**< AES cipher with 128-bit NIST KW mode. */\n    MBEDTLS_CIPHER_AES_192_KW,           /**< AES cipher with 192-bit NIST KW mode. */\n    MBEDTLS_CIPHER_AES_256_KW,           /**< AES cipher with 256-bit NIST KW mode. */\n    MBEDTLS_CIPHER_AES_128_KWP,          /**< AES cipher with 128-bit NIST KWP mode. */\n    MBEDTLS_CIPHER_AES_192_KWP,          /**< AES cipher with 192-bit NIST KWP mode. */\n    MBEDTLS_CIPHER_AES_256_KWP,          /**< AES cipher with 256-bit NIST KWP mode. */\n} mbedtls_cipher_type_t;\n\n/** Supported cipher modes. */\ntypedef enum {\n    MBEDTLS_MODE_NONE = 0,               /**< None.                        */\n    MBEDTLS_MODE_ECB,                    /**< The ECB cipher mode.         */\n    MBEDTLS_MODE_CBC,                    /**< The CBC cipher mode.         */\n    MBEDTLS_MODE_CFB,                    /**< The CFB cipher mode.         */\n    MBEDTLS_MODE_OFB,                    /**< The OFB cipher mode.         */\n    MBEDTLS_MODE_CTR,                    /**< The CTR cipher mode.         */\n    MBEDTLS_MODE_GCM,                    /**< The GCM cipher mode.         */\n    MBEDTLS_MODE_STREAM,                 /**< The stream cipher mode.      */\n    MBEDTLS_MODE_CCM,                    /**< The CCM cipher mode.         */\n    MBEDTLS_MODE_CCM_STAR_NO_TAG,        /**< The CCM*-no-tag cipher mode. */\n    MBEDTLS_MODE_XTS,                    /**< The XTS cipher mode.         */\n    MBEDTLS_MODE_CHACHAPOLY,             /**< The ChaCha-Poly cipher mode. */\n    MBEDTLS_MODE_KW,                     /**< The SP800-38F KW mode */\n    MBEDTLS_MODE_KWP,                    /**< The SP800-38F KWP mode */\n} mbedtls_cipher_mode_t;\n\n/** Supported cipher padding types. */\ntypedef enum {\n    MBEDTLS_PADDING_PKCS7 = 0,     /**< PKCS7 padding (default).        */\n    MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding.         */\n    MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding.             */\n    MBEDTLS_PADDING_ZEROS,         /**< Zero padding (not reversible). */\n    MBEDTLS_PADDING_NONE,          /**< Never pad (full blocks only).   */\n} mbedtls_cipher_padding_t;\n\n/** Type of operation. */\ntypedef enum {\n    MBEDTLS_OPERATION_NONE = -1,\n    MBEDTLS_DECRYPT = 0,\n    MBEDTLS_ENCRYPT,\n} mbedtls_operation_t;\n\nenum {\n    /** Undefined key length. */\n    MBEDTLS_KEY_LENGTH_NONE = 0,\n    /** Key length, in bits (including parity), for DES keys. \\warning DES is considered weak. */\n    MBEDTLS_KEY_LENGTH_DES  = 64,\n    /** Key length in bits, including parity, for DES in two-key EDE. \\warning 3DES is considered weak. */\n    MBEDTLS_KEY_LENGTH_DES_EDE = 128,\n    /** Key length in bits, including parity, for DES in three-key EDE. \\warning 3DES is considered weak. */\n    MBEDTLS_KEY_LENGTH_DES_EDE3 = 192,\n};\n\n/** Maximum length of any IV, in Bytes. */\n/* This should ideally be derived automatically from list of ciphers.\n * This should be kept in sync with MBEDTLS_SSL_MAX_IV_LENGTH defined\n * in library/ssl_misc.h. */\n#define MBEDTLS_MAX_IV_LENGTH      16\n\n/** Maximum block size of any cipher, in Bytes. */\n/* This should ideally be derived automatically from list of ciphers.\n * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined\n * in library/ssl_misc.h. */\n#define MBEDTLS_MAX_BLOCK_LENGTH   16\n\n/** Maximum key length, in Bytes. */\n/* This should ideally be derived automatically from list of ciphers.\n * For now, only check whether XTS is enabled which uses 64 Byte keys,\n * and use 32 Bytes as an upper bound for the maximum key length otherwise.\n * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined\n * in library/ssl_misc.h, which however deliberately ignores the case of XTS\n * since the latter isn't used in SSL/TLS. */\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n#define MBEDTLS_MAX_KEY_LENGTH     64\n#else\n#define MBEDTLS_MAX_KEY_LENGTH     32\n#endif /* MBEDTLS_CIPHER_MODE_XTS */\n\n/**\n * Base cipher information (opaque struct).\n */\ntypedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t;\n\n/**\n * CMAC context (opaque struct).\n */\ntypedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t;\n\n/**\n * Cipher information. Allows calling cipher functions\n * in a generic way.\n *\n * \\note        The library does not support custom cipher info structures,\n *              only built-in structures returned by the functions\n *              mbedtls_cipher_info_from_string(),\n *              mbedtls_cipher_info_from_type(),\n *              mbedtls_cipher_info_from_values(),\n *              mbedtls_cipher_info_from_psa().\n *\n * \\note        Some fields store a value that has been right-shifted to save\n *              code-size, so should not be used directly. The accessor\n *              functions adjust for this and return the \"natural\" value.\n */\ntypedef struct mbedtls_cipher_info_t {\n    /** Name of the cipher. */\n    const char *MBEDTLS_PRIVATE(name);\n\n    /** The block size, in bytes. */\n    unsigned int MBEDTLS_PRIVATE(block_size) : 5;\n\n    /** IV or nonce size, in bytes (right shifted by #MBEDTLS_IV_SIZE_SHIFT).\n     * For ciphers that accept variable IV sizes,\n     * this is the recommended size.\n     */\n    unsigned int MBEDTLS_PRIVATE(iv_size) : 3;\n\n    /** The cipher key length, in bits (right shifted by #MBEDTLS_KEY_BITLEN_SHIFT).\n     * This is the default length for variable sized ciphers.\n     * Includes parity bits for ciphers like DES.\n     */\n    unsigned int MBEDTLS_PRIVATE(key_bitlen) : 4;\n\n    /** The cipher mode (as per mbedtls_cipher_mode_t).\n     * For example, MBEDTLS_MODE_CBC.\n     */\n    unsigned int MBEDTLS_PRIVATE(mode) : 4;\n\n    /** Full cipher identifier (as per mbedtls_cipher_type_t).\n     * For example, MBEDTLS_CIPHER_AES_256_CBC.\n     *\n     * This could be 7 bits, but 8 bits retains byte alignment for the\n     * next field, which reduces code size to access that field.\n     */\n    unsigned int MBEDTLS_PRIVATE(type) : 8;\n\n    /** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and\n     *  MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the\n     *  cipher supports variable IV or variable key sizes, respectively.\n     */\n    unsigned int MBEDTLS_PRIVATE(flags) : 2;\n\n    /** Index to LUT for base cipher information and functions. */\n    unsigned int MBEDTLS_PRIVATE(base_idx) : 5;\n\n} mbedtls_cipher_info_t;\n\n/* For internal use only.\n * These are used to more compactly represent the fields above. */\n#define MBEDTLS_KEY_BITLEN_SHIFT  6\n#define MBEDTLS_IV_SIZE_SHIFT     2\n/**\n * Generic cipher context.\n */\ntypedef struct mbedtls_cipher_context_t {\n    /** Information about the associated cipher. */\n    const mbedtls_cipher_info_t *MBEDTLS_PRIVATE(cipher_info);\n\n    /** Key length to use. */\n    int MBEDTLS_PRIVATE(key_bitlen);\n\n    /** Operation that the key of the context has been\n     * initialized for.\n     */\n    mbedtls_operation_t MBEDTLS_PRIVATE(operation);\n\n#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)\n    /** Padding functions to use, if relevant for\n     * the specific cipher mode.\n     */\n    void(*MBEDTLS_PRIVATE(add_padding))(unsigned char *output, size_t olen,\n                                        size_t data_len);\n    /* Report invalid-padding condition through the output parameter\n     * invalid_padding. To minimize changes in Mbed TLS 3.6, where this\n     * declaration is in a public header, use the public type size_t\n     * rather than the internal type mbedtls_ct_condition_t. */\n    int(*MBEDTLS_PRIVATE(get_padding))(unsigned char *input, size_t ilen,\n                                       size_t *data_len,\n                                       size_t *invalid_padding);\n#endif\n\n    /** Buffer for input that has not been processed yet. */\n    unsigned char MBEDTLS_PRIVATE(unprocessed_data)[MBEDTLS_MAX_BLOCK_LENGTH];\n\n    /** Number of Bytes that have not been processed yet. */\n    size_t MBEDTLS_PRIVATE(unprocessed_len);\n\n    /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number\n     * for XTS-mode. */\n    unsigned char MBEDTLS_PRIVATE(iv)[MBEDTLS_MAX_IV_LENGTH];\n\n    /** IV size in Bytes, for ciphers with variable-length IVs. */\n    size_t MBEDTLS_PRIVATE(iv_size);\n\n    /** The cipher-specific context. */\n    void *MBEDTLS_PRIVATE(cipher_ctx);\n\n#if defined(MBEDTLS_CMAC_C)\n    /** CMAC-specific context. */\n    mbedtls_cmac_context_t *MBEDTLS_PRIVATE(cmac_ctx);\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    /** Indicates whether the cipher operations should be performed\n     *  by Mbed TLS' own crypto library or an external implementation\n     *  of the PSA Crypto API.\n     *  This is unset if the cipher context was established through\n     *  mbedtls_cipher_setup(), and set if it was established through\n     *  mbedtls_cipher_setup_psa().\n     */\n    unsigned char MBEDTLS_PRIVATE(psa_enabled);\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\n} mbedtls_cipher_context_t;\n\n/**\n * \\brief This function retrieves the list of ciphers supported\n *        by the generic cipher module.\n *\n *        For any cipher identifier in the returned list, you can\n *        obtain the corresponding generic cipher information structure\n *        via mbedtls_cipher_info_from_type(), which can then be used\n *        to prepare a cipher context via mbedtls_cipher_setup().\n *\n *\n * \\return      A statically-allocated array of cipher identifiers\n *              of type cipher_type_t. The last entry is zero.\n */\nconst int *mbedtls_cipher_list(void);\n\n/**\n * \\brief               This function retrieves the cipher-information\n *                      structure associated with the given cipher name.\n *\n * \\param cipher_name   Name of the cipher to search for. This must not be\n *                      \\c NULL.\n *\n * \\return              The cipher information structure associated with the\n *                      given \\p cipher_name.\n * \\return              \\c NULL if the associated cipher information is not found.\n */\nconst mbedtls_cipher_info_t *mbedtls_cipher_info_from_string(const char *cipher_name);\n\n/**\n * \\brief               This function retrieves the cipher-information\n *                      structure associated with the given cipher type.\n *\n * \\param cipher_type   Type of the cipher to search for.\n *\n * \\return              The cipher information structure associated with the\n *                      given \\p cipher_type.\n * \\return              \\c NULL if the associated cipher information is not found.\n */\nconst mbedtls_cipher_info_t *mbedtls_cipher_info_from_type(const mbedtls_cipher_type_t cipher_type);\n\n/**\n * \\brief               This function retrieves the cipher-information\n *                      structure associated with the given cipher ID,\n *                      key size and mode.\n *\n * \\param cipher_id     The ID of the cipher to search for. For example,\n *                      #MBEDTLS_CIPHER_ID_AES.\n * \\param key_bitlen    The length of the key in bits.\n * \\param mode          The cipher mode. For example, #MBEDTLS_MODE_CBC.\n *\n * \\return              The cipher information structure associated with the\n *                      given \\p cipher_id.\n * \\return              \\c NULL if the associated cipher information is not found.\n */\nconst mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(const mbedtls_cipher_id_t cipher_id,\n                                                             int key_bitlen,\n                                                             const mbedtls_cipher_mode_t mode);\n\n/**\n * \\brief               Retrieve the identifier for a cipher info structure.\n *\n * \\param[in] info      The cipher info structure to query.\n *                      This may be \\c NULL.\n *\n * \\return              The full cipher identifier (\\c MBEDTLS_CIPHER_xxx).\n * \\return              #MBEDTLS_CIPHER_NONE if \\p info is \\c NULL.\n */\nstatic inline mbedtls_cipher_type_t mbedtls_cipher_info_get_type(\n    const mbedtls_cipher_info_t *info)\n{\n    if (info == NULL) {\n        return MBEDTLS_CIPHER_NONE;\n    } else {\n        return (mbedtls_cipher_type_t) info->MBEDTLS_PRIVATE(type);\n    }\n}\n\n/**\n * \\brief               Retrieve the operation mode for a cipher info structure.\n *\n * \\param[in] info      The cipher info structure to query.\n *                      This may be \\c NULL.\n *\n * \\return              The cipher mode (\\c MBEDTLS_MODE_xxx).\n * \\return              #MBEDTLS_MODE_NONE if \\p info is \\c NULL.\n */\nstatic inline mbedtls_cipher_mode_t mbedtls_cipher_info_get_mode(\n    const mbedtls_cipher_info_t *info)\n{\n    if (info == NULL) {\n        return MBEDTLS_MODE_NONE;\n    } else {\n        return (mbedtls_cipher_mode_t) info->MBEDTLS_PRIVATE(mode);\n    }\n}\n\n/**\n * \\brief               Retrieve the key size for a cipher info structure.\n *\n * \\param[in] info      The cipher info structure to query.\n *                      This may be \\c NULL.\n *\n * \\return              The key length in bits.\n *                      For variable-sized ciphers, this is the default length.\n *                      For DES, this includes the parity bits.\n * \\return              \\c 0 if \\p info is \\c NULL.\n */\nstatic inline size_t mbedtls_cipher_info_get_key_bitlen(\n    const mbedtls_cipher_info_t *info)\n{\n    if (info == NULL) {\n        return 0;\n    } else {\n        return ((size_t) info->MBEDTLS_PRIVATE(key_bitlen)) << MBEDTLS_KEY_BITLEN_SHIFT;\n    }\n}\n\n/**\n * \\brief               Retrieve the human-readable name for a\n *                      cipher info structure.\n *\n * \\param[in] info      The cipher info structure to query.\n *                      This may be \\c NULL.\n *\n * \\return              The cipher name, which is a human readable string,\n *                      with static storage duration.\n * \\return              \\c NULL if \\p info is \\c NULL.\n */\nstatic inline const char *mbedtls_cipher_info_get_name(\n    const mbedtls_cipher_info_t *info)\n{\n    if (info == NULL) {\n        return NULL;\n    } else {\n        return info->MBEDTLS_PRIVATE(name);\n    }\n}\n\n/**\n * \\brief       This function returns the size of the IV or nonce\n *              for the cipher info structure, in bytes.\n *\n * \\param info  The cipher info structure. This may be \\c NULL.\n *\n * \\return      The recommended IV size.\n * \\return      \\c 0 for ciphers not using an IV or a nonce.\n * \\return      \\c 0 if \\p info is \\c NULL.\n */\nstatic inline size_t mbedtls_cipher_info_get_iv_size(\n    const mbedtls_cipher_info_t *info)\n{\n    if (info == NULL) {\n        return 0;\n    }\n\n    return ((size_t) info->MBEDTLS_PRIVATE(iv_size)) << MBEDTLS_IV_SIZE_SHIFT;\n}\n\n/**\n * \\brief        This function returns the block size of the given\n *               cipher info structure in bytes.\n *\n * \\param info   The cipher info structure. This may be \\c NULL.\n *\n * \\return       The block size of the cipher.\n * \\return       \\c 1 if the cipher is a stream cipher.\n * \\return       \\c 0 if \\p info is \\c NULL.\n */\nstatic inline size_t mbedtls_cipher_info_get_block_size(\n    const mbedtls_cipher_info_t *info)\n{\n    if (info == NULL) {\n        return 0;\n    }\n\n    return (size_t) (info->MBEDTLS_PRIVATE(block_size));\n}\n\n/**\n * \\brief        This function returns a non-zero value if the key length for\n *               the given cipher is variable.\n *\n * \\param info   The cipher info structure. This may be \\c NULL.\n *\n * \\return       Non-zero if the key length is variable, \\c 0 otherwise.\n * \\return       \\c 0 if the given pointer is \\c NULL.\n */\nstatic inline int mbedtls_cipher_info_has_variable_key_bitlen(\n    const mbedtls_cipher_info_t *info)\n{\n    if (info == NULL) {\n        return 0;\n    }\n\n    return info->MBEDTLS_PRIVATE(flags) & MBEDTLS_CIPHER_VARIABLE_KEY_LEN;\n}\n\n/**\n * \\brief        This function returns a non-zero value if the IV size for\n *               the given cipher is variable.\n *\n * \\param info   The cipher info structure. This may be \\c NULL.\n *\n * \\return       Non-zero if the IV size is variable, \\c 0 otherwise.\n * \\return       \\c 0 if the given pointer is \\c NULL.\n */\nstatic inline int mbedtls_cipher_info_has_variable_iv_size(\n    const mbedtls_cipher_info_t *info)\n{\n    if (info == NULL) {\n        return 0;\n    }\n\n    return info->MBEDTLS_PRIVATE(flags) & MBEDTLS_CIPHER_VARIABLE_IV_LEN;\n}\n\n/**\n * \\brief               This function initializes a \\p ctx as NONE.\n *\n * \\param ctx           The context to be initialized. This must not be \\c NULL.\n */\nvoid mbedtls_cipher_init(mbedtls_cipher_context_t *ctx);\n\n/**\n * \\brief               This function frees and clears the cipher-specific\n *                      context of \\p ctx. Freeing \\p ctx itself remains the\n *                      responsibility of the caller.\n *\n * \\param ctx           The context to be freed. If this is \\c NULL, the\n *                      function has no effect, otherwise this must point to an\n *                      initialized context.\n */\nvoid mbedtls_cipher_free(mbedtls_cipher_context_t *ctx);\n\n\n/**\n * \\brief               This function prepares a cipher context for\n *                      use with the given cipher primitive.\n *\n * \\note                After calling this function, you should call\n *                      mbedtls_cipher_setkey() and, if the mode uses padding,\n *                      mbedtls_cipher_set_padding_mode(), then for each\n *                      message to encrypt or decrypt with this key, either:\n *                      - mbedtls_cipher_crypt() for one-shot processing with\n *                      non-AEAD modes;\n *                      - mbedtls_cipher_auth_encrypt_ext() or\n *                      mbedtls_cipher_auth_decrypt_ext() for one-shot\n *                      processing with AEAD modes or NIST_KW;\n *                      - for multi-part processing, see the documentation of\n *                      mbedtls_cipher_reset().\n *\n * \\param ctx           The context to prepare. This must be initialized by\n *                      a call to mbedtls_cipher_init() first.\n * \\param cipher_info   The cipher to use.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on\n *                      parameter-verification failure.\n * \\return              #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the\n *                      cipher-specific context fails.\n */\nint mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx,\n                         const mbedtls_cipher_info_t *cipher_info);\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n/**\n * \\brief               This function initializes a cipher context for\n *                      PSA-based use with the given cipher primitive.\n *\n * \\deprecated          This function is deprecated and will be removed in a\n *                      future version of the library.\n *                      Please use psa_aead_xxx() / psa_cipher_xxx() directly\n *                      instead.\n *\n * \\note                See #MBEDTLS_USE_PSA_CRYPTO for information on PSA.\n *\n * \\param ctx           The context to initialize. May not be \\c NULL.\n * \\param cipher_info   The cipher to use.\n * \\param taglen        For AEAD ciphers, the length in bytes of the\n *                      authentication tag to use. Subsequent uses of\n *                      mbedtls_cipher_auth_encrypt_ext() or\n *                      mbedtls_cipher_auth_decrypt_ext() must provide\n *                      the same tag length.\n *                      For non-AEAD ciphers, the value must be \\c 0.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on\n *                      parameter-verification failure.\n * \\return              #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the\n *                      cipher-specific context fails.\n */\nint MBEDTLS_DEPRECATED mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx,\n                                                const mbedtls_cipher_info_t *cipher_info,\n                                                size_t taglen);\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n/**\n * \\brief        This function returns the block size of the given cipher\n *               in bytes.\n *\n * \\param ctx    The context of the cipher.\n *\n * \\return       The block size of the underlying cipher.\n * \\return       \\c 1 if the cipher is a stream cipher.\n * \\return       \\c 0 if \\p ctx has not been initialized.\n */\nstatic inline unsigned int mbedtls_cipher_get_block_size(\n    const mbedtls_cipher_context_t *ctx)\n{\n    if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) {\n        return 0;\n    }\n\n    return (unsigned int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(block_size);\n}\n\n/**\n * \\brief        This function returns the mode of operation for\n *               the cipher. For example, MBEDTLS_MODE_CBC.\n *\n * \\param ctx    The context of the cipher. This must be initialized.\n *\n * \\return       The mode of operation.\n * \\return       #MBEDTLS_MODE_NONE if \\p ctx has not been initialized.\n */\nstatic inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode(\n    const mbedtls_cipher_context_t *ctx)\n{\n    if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) {\n        return MBEDTLS_MODE_NONE;\n    }\n\n    return (mbedtls_cipher_mode_t) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(mode);\n}\n\n/**\n * \\brief       This function returns the size of the IV or nonce\n *              of the cipher, in Bytes.\n *\n * \\param ctx   The context of the cipher. This must be initialized.\n *\n * \\return      The recommended IV size if no IV has been set.\n * \\return      \\c 0 for ciphers not using an IV or a nonce.\n * \\return      The actual size if an IV has been set.\n */\nstatic inline int mbedtls_cipher_get_iv_size(\n    const mbedtls_cipher_context_t *ctx)\n{\n    if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) {\n        return 0;\n    }\n\n    if (ctx->MBEDTLS_PRIVATE(iv_size) != 0) {\n        return (int) ctx->MBEDTLS_PRIVATE(iv_size);\n    }\n\n    return (int) (((int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(iv_size)) <<\n                  MBEDTLS_IV_SIZE_SHIFT);\n}\n\n/**\n * \\brief               This function returns the type of the given cipher.\n *\n * \\param ctx           The context of the cipher. This must be initialized.\n *\n * \\return              The type of the cipher.\n * \\return              #MBEDTLS_CIPHER_NONE if \\p ctx has not been initialized.\n */\nstatic inline mbedtls_cipher_type_t mbedtls_cipher_get_type(\n    const mbedtls_cipher_context_t *ctx)\n{\n    if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) {\n        return MBEDTLS_CIPHER_NONE;\n    }\n\n    return (mbedtls_cipher_type_t) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(type);\n}\n\n/**\n * \\brief               This function returns the name of the given cipher\n *                      as a string.\n *\n * \\param ctx           The context of the cipher. This must be initialized.\n *\n * \\return              The name of the cipher.\n * \\return              NULL if \\p ctx has not been not initialized.\n */\nstatic inline const char *mbedtls_cipher_get_name(\n    const mbedtls_cipher_context_t *ctx)\n{\n    if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) {\n        return 0;\n    }\n\n    return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(name);\n}\n\n/**\n * \\brief               This function returns the key length of the cipher.\n *\n * \\param ctx           The context of the cipher. This must be initialized.\n *\n * \\return              The key length of the cipher in bits.\n * \\return              #MBEDTLS_KEY_LENGTH_NONE if \\p ctx has not been\n *                      initialized.\n */\nstatic inline int mbedtls_cipher_get_key_bitlen(\n    const mbedtls_cipher_context_t *ctx)\n{\n    if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) {\n        return MBEDTLS_KEY_LENGTH_NONE;\n    }\n\n    return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(key_bitlen) <<\n           MBEDTLS_KEY_BITLEN_SHIFT;\n}\n\n/**\n * \\brief          This function returns the operation of the given cipher.\n *\n * \\param ctx      The context of the cipher. This must be initialized.\n *\n * \\return         The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT.\n * \\return         #MBEDTLS_OPERATION_NONE if \\p ctx has not been initialized.\n */\nstatic inline mbedtls_operation_t mbedtls_cipher_get_operation(\n    const mbedtls_cipher_context_t *ctx)\n{\n    if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) {\n        return MBEDTLS_OPERATION_NONE;\n    }\n\n    return ctx->MBEDTLS_PRIVATE(operation);\n}\n\n/**\n * \\brief               This function sets the key to use with the given context.\n *\n * \\param ctx           The generic cipher context. This must be initialized and\n *                      bound to a cipher information structure.\n * \\param key           The key to use. This must be a readable buffer of at\n *                      least \\p key_bitlen Bits.\n * \\param key_bitlen    The key length to use, in Bits.\n * \\param operation     The operation that the key will be used for:\n *                      #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on\n *                      parameter-verification failure.\n * \\return              A cipher-specific error code on failure.\n */\nint mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx,\n                          const unsigned char *key,\n                          int key_bitlen,\n                          const mbedtls_operation_t operation);\n\n#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)\n/**\n * \\brief               This function sets the padding mode, for cipher modes\n *                      that use padding.\n *\n *\n * \\param ctx           The generic cipher context. This must be initialized and\n *                      bound to a cipher information structure.\n * \\param mode          The padding mode.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE\n *                      if the selected padding mode is not supported.\n * \\return              #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode\n *                      does not support padding.\n */\nint mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx,\n                                    mbedtls_cipher_padding_t mode);\n#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */\n\n/**\n * \\brief           This function sets the initialization vector (IV)\n *                  or nonce.\n *\n * \\note            Some ciphers do not use IVs nor nonce. For these\n *                  ciphers, this function has no effect.\n *\n * \\note            For #MBEDTLS_CIPHER_CHACHA20, the nonce length must\n *                  be 12, and the initial counter value is 0.\n *\n * \\note            For #MBEDTLS_CIPHER_CHACHA20_POLY1305, the nonce length\n *                  must be 12.\n *\n * \\param ctx       The generic cipher context. This must be initialized and\n *                  bound to a cipher information structure.\n * \\param iv        The IV to use, or NONCE_COUNTER for CTR-mode ciphers. This\n *                  must be a readable buffer of at least \\p iv_len Bytes.\n * \\param iv_len    The IV length for ciphers with variable-size IV.\n *                  This parameter is discarded by ciphers with fixed-size IV.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on\n *                  parameter-verification failure.\n */\nint mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx,\n                          const unsigned char *iv,\n                          size_t iv_len);\n\n/**\n * \\brief         This function resets the cipher state.\n *\n * \\note          With non-AEAD ciphers, the order of calls for each message\n *                is as follows:\n *                1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce;\n *                2. mbedtls_cipher_reset();\n *                3. mbedtls_cipher_update() zero, one or more times;\n *                4. mbedtls_cipher_finish_padded() (recommended for decryption\n *                   if the mode uses padding) or mbedtls_cipher_finish().\n *                .\n *                This sequence can be repeated to encrypt or decrypt multiple\n *                messages with the same key.\n *\n * \\note          With AEAD ciphers, the order of calls for each message\n *                is as follows:\n *                1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce;\n *                2. mbedtls_cipher_reset();\n *                3. mbedtls_cipher_update_ad();\n *                4. mbedtls_cipher_update() zero, one or more times;\n *                5. mbedtls_cipher_finish() (or mbedtls_cipher_finish_padded());\n *                6. mbedtls_cipher_check_tag() (for decryption) or\n *                   mbedtls_cipher_write_tag() (for encryption).\n *                .\n *                This sequence can be repeated to encrypt or decrypt multiple\n *                messages with the same key.\n *\n * \\param ctx     The generic cipher context. This must be bound to a key.\n *\n * \\return        \\c 0 on success.\n * \\return        #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on\n *                parameter-verification failure.\n */\nint mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx);\n\n#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)\n/**\n * \\brief               This function adds additional data for AEAD ciphers.\n *                      Currently supported with GCM and ChaCha20+Poly1305.\n *\n * \\param ctx           The generic cipher context. This must be initialized.\n * \\param ad            The additional data to use. This must be a readable\n *                      buffer of at least \\p ad_len Bytes.\n * \\param ad_len        The length of \\p ad in Bytes.\n *\n * \\return              \\c 0 on success.\n * \\return              A specific error code on failure.\n */\nint mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx,\n                             const unsigned char *ad, size_t ad_len);\n#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */\n\n/**\n * \\brief               The generic cipher update function. It encrypts or\n *                      decrypts using the given cipher context. Writes as\n *                      many block-sized blocks of data as possible to output.\n *                      Any data that cannot be written immediately is either\n *                      added to the next block, or flushed when\n *                      mbedtls_cipher_finish() or mbedtls_cipher_finish_padded()\n *                      is called.\n *                      Exception: For MBEDTLS_MODE_ECB, expects a single block\n *                      in size. For example, 16 Bytes for AES.\n *\n * \\param ctx           The generic cipher context. This must be initialized and\n *                      bound to a key.\n * \\param input         The buffer holding the input data. This must be a\n *                      readable buffer of at least \\p ilen Bytes.\n * \\param ilen          The length of the input data.\n * \\param output        The buffer for the output data. This must be able to\n *                      hold at least `ilen + block_size`. This must not be the\n *                      same buffer as \\p input.\n * \\param olen          The length of the output data, to be updated with the\n *                      actual number of Bytes written. This must not be\n *                      \\c NULL.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on\n *                      parameter-verification failure.\n * \\return              #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an\n *                      unsupported mode for a cipher.\n * \\return              A cipher-specific error code on failure.\n */\nint mbedtls_cipher_update(mbedtls_cipher_context_t *ctx,\n                          const unsigned char *input,\n                          size_t ilen, unsigned char *output,\n                          size_t *olen);\n\n/**\n * \\brief               The generic cipher finalization function. If data still\n *                      needs to be flushed from an incomplete block, the data\n *                      contained in it is padded to the size of\n *                      the last block, and written to the \\p output buffer.\n *\n * \\warning             This function reports invalid padding through an error\n *                      code. Adversaries may be able to decrypt encrypted\n *                      data if they can submit chosen ciphertexts and\n *                      detect whether it has valid padding or not,\n *                      either through direct observation or through a side\n *                      channel such as timing. This is known as a\n *                      padding oracle attack.\n *                      Therefore applications that call this function for\n *                      decryption with a cipher that involves padding\n *                      should take care around error handling. Preferably,\n *                      such applications should use\n *                      mbedtls_cipher_finish_padded() instead of this function.\n *\n * \\param ctx           The generic cipher context. This must be initialized and\n *                      bound to a key.\n * \\param output        The buffer to write data to. This needs to be a writable\n *                      buffer of at least block_size Bytes.\n * \\param olen          The length of the data written to the \\p output buffer.\n *                      This may not be \\c NULL.\n *                      Note that when decrypting in a mode with padding,\n *                      the actual output length is sensitive and may be\n *                      used to mount a padding oracle attack (see warning\n *                      above), although less efficiently than through\n *                      the invalid-padding condition.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on\n *                      parameter-verification failure.\n * \\return              #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption\n *                      expecting a full block but not receiving one.\n * \\return              #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding\n *                      while decrypting. Note that invalid-padding errors\n *                      should be handled carefully; see the warning above.\n * \\return              A cipher-specific error code on failure.\n */\nint mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx,\n                          unsigned char *output, size_t *olen);\n\n/**\n * \\brief               The generic cipher finalization function. If data still\n *                      needs to be flushed from an incomplete block, the data\n *                      contained in it is padded to the size of\n *                      the last block, and written to the \\p output buffer.\n *\n * \\note                This function is similar to mbedtls_cipher_finish().\n *                      The only difference is that it reports invalid padding\n *                      decryption differently, through the \\p invalid_padding\n *                      parameter rather than an error code.\n *                      For encryption, and in modes without padding (including\n *                      all authenticated modes), this function is identical\n *                      to mbedtls_cipher_finish().\n *\n * \\param[in,out] ctx   The generic cipher context. This must be initialized and\n *                      bound to a key.\n * \\param[out] output   The buffer to write data to. This needs to be a writable\n *                      buffer of at least block_size Bytes.\n * \\param[out] olen     The length of the data written to the \\p output buffer.\n *                      This may not be \\c NULL.\n *                      Note that when decrypting in a mode with padding,\n *                      the actual output length is sensitive and may be\n *                      used to mount a padding oracle attack (see warning\n *                      on mbedtls_cipher_finish()).\n * \\param[out] invalid_padding\n *                      If this function returns \\c 0 on decryption,\n *                      \\p *invalid_padding is \\c 0 if the ciphertext was\n *                      valid, and all-bits-one if the ciphertext had invalid\n *                      padding.\n *                      On encryption, or in a mode without padding (including\n *                      all authenticated modes), \\p *invalid_padding is \\c 0\n *                      on success.\n *                      The value in \\p *invalid_padding is unspecified if\n *                      this function returns a nonzero status.\n *\n * \\return              \\c 0 on success.\n *                      Also \\c 0 for decryption with invalid padding.\n * \\return              #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on\n *                      parameter-verification failure.\n * \\return              #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption\n *                      expecting a full block but not receiving one.\n * \\return              A cipher-specific error code on failure.\n */\nint mbedtls_cipher_finish_padded(mbedtls_cipher_context_t *ctx,\n                                 unsigned char *output, size_t *olen,\n                                 size_t *invalid_padding);\n\n#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)\n/**\n * \\brief               This function writes a tag for AEAD ciphers.\n *                      Currently supported with GCM and ChaCha20+Poly1305.\n *                      This must be called after mbedtls_cipher_finish()\n *                      or mbedtls_cipher_finish_padded().\n *\n * \\param ctx           The generic cipher context. This must be initialized,\n *                      bound to a key, and have just completed a cipher\n *                      operation through mbedtls_cipher_finish() the tag for\n *                      which should be written.\n * \\param tag           The buffer to write the tag to. This must be a writable\n *                      buffer of at least \\p tag_len Bytes.\n * \\param tag_len       The length of the tag to write.\n *\n * \\return              \\c 0 on success.\n * \\return              A specific error code on failure.\n */\nint mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx,\n                             unsigned char *tag, size_t tag_len);\n\n/**\n * \\brief               This function checks the tag for AEAD ciphers.\n *                      Currently supported with GCM and ChaCha20+Poly1305.\n *                      This must be called after mbedtls_cipher_finish()\n *                      or mbedtls_cipher_finish_padded().\n *\n * \\param ctx           The generic cipher context. This must be initialized.\n * \\param tag           The buffer holding the tag. This must be a readable\n *                      buffer of at least \\p tag_len Bytes.\n * \\param tag_len       The length of the tag to check.\n *\n * \\return              \\c 0 on success.\n * \\return              A specific error code on failure.\n */\nint mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx,\n                             const unsigned char *tag, size_t tag_len);\n#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */\n\n/**\n * \\brief               The generic all-in-one encryption/decryption function,\n *                      for all ciphers except AEAD constructs.\n *\n * \\param ctx           The generic cipher context. This must be initialized.\n * \\param iv            The IV to use, or NONCE_COUNTER for CTR-mode ciphers.\n *                      This must be a readable buffer of at least \\p iv_len\n *                      Bytes.\n * \\param iv_len        The IV length for ciphers with variable-size IV.\n *                      This parameter is discarded by ciphers with fixed-size\n *                      IV.\n * \\param input         The buffer holding the input data. This must be a\n *                      readable buffer of at least \\p ilen Bytes.\n * \\param ilen          The length of the input data in Bytes.\n * \\param output        The buffer for the output data. This must be able to\n *                      hold at least `ilen + block_size`. This must not be the\n *                      same buffer as \\p input.\n * \\param olen          The length of the output data, to be updated with the\n *                      actual number of Bytes written. This must not be\n *                      \\c NULL.\n *\n * \\note                Some ciphers do not use IVs nor nonce. For these\n *                      ciphers, use \\p iv = NULL and \\p iv_len = 0.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on\n *                      parameter-verification failure.\n * \\return              #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption\n *                      expecting a full block but not receiving one.\n * \\return              #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding\n *                      while decrypting.\n * \\return              A cipher-specific error code on failure.\n */\nint mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx,\n                         const unsigned char *iv, size_t iv_len,\n                         const unsigned char *input, size_t ilen,\n                         unsigned char *output, size_t *olen);\n\n#if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C)\n/**\n * \\brief               The authenticated encryption (AEAD/NIST_KW) function.\n *\n * \\note                For AEAD modes, the tag will be appended to the\n *                      ciphertext, as recommended by RFC 5116.\n *                      (NIST_KW doesn't have a separate tag.)\n *\n * \\param ctx           The generic cipher context. This must be initialized and\n *                      bound to a key, with an AEAD algorithm or NIST_KW.\n * \\param iv            The nonce to use. This must be a readable buffer of\n *                      at least \\p iv_len Bytes and may be \\c NULL if \\p\n *                      iv_len is \\c 0.\n * \\param iv_len        The length of the nonce. For AEAD ciphers, this must\n *                      satisfy the constraints imposed by the cipher used.\n *                      For NIST_KW, this must be \\c 0.\n * \\param ad            The additional data to authenticate. This must be a\n *                      readable buffer of at least \\p ad_len Bytes, and may\n *                      be \\c NULL is \\p ad_len is \\c 0.\n * \\param ad_len        The length of \\p ad. For NIST_KW, this must be \\c 0.\n * \\param input         The buffer holding the input data. This must be a\n *                      readable buffer of at least \\p ilen Bytes, and may be\n *                      \\c NULL if \\p ilen is \\c 0.\n * \\param ilen          The length of the input data.\n * \\param output        The buffer for the output data. This must be a\n *                      writable buffer of at least \\p output_len Bytes, and\n *                      must not be \\c NULL.\n * \\param output_len    The length of the \\p output buffer in Bytes. For AEAD\n *                      ciphers, this must be at least \\p ilen + \\p tag_len.\n *                      For NIST_KW, this must be at least \\p ilen + 8\n *                      (rounded up to a multiple of 8 if KWP is used);\n *                      \\p ilen + 15 is always a safe value.\n * \\param olen          This will be filled with the actual number of Bytes\n *                      written to the \\p output buffer. This must point to a\n *                      writable object of type \\c size_t.\n * \\param tag_len       The desired length of the authentication tag. For AEAD\n *                      ciphers, this must match the constraints imposed by\n *                      the cipher used, and in particular must not be \\c 0.\n *                      For NIST_KW, this must be \\c 0.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on\n *                      parameter-verification failure.\n * \\return              A cipher-specific error code on failure.\n */\nint mbedtls_cipher_auth_encrypt_ext(mbedtls_cipher_context_t *ctx,\n                                    const unsigned char *iv, size_t iv_len,\n                                    const unsigned char *ad, size_t ad_len,\n                                    const unsigned char *input, size_t ilen,\n                                    unsigned char *output, size_t output_len,\n                                    size_t *olen, size_t tag_len);\n\n/**\n * \\brief               The authenticated encryption (AEAD/NIST_KW) function.\n *\n * \\note                If the data is not authentic, then the output buffer\n *                      is zeroed out to prevent the unauthentic plaintext being\n *                      used, making this interface safer.\n *\n * \\note                For AEAD modes, the tag must be appended to the\n *                      ciphertext, as recommended by RFC 5116.\n *                      (NIST_KW doesn't have a separate tag.)\n *\n * \\param ctx           The generic cipher context. This must be initialized and\n *                      bound to a key, with an AEAD algorithm or NIST_KW.\n * \\param iv            The nonce to use. This must be a readable buffer of\n *                      at least \\p iv_len Bytes and may be \\c NULL if \\p\n *                      iv_len is \\c 0.\n * \\param iv_len        The length of the nonce. For AEAD ciphers, this must\n *                      satisfy the constraints imposed by the cipher used.\n *                      For NIST_KW, this must be \\c 0.\n * \\param ad            The additional data to authenticate. This must be a\n *                      readable buffer of at least \\p ad_len Bytes, and may\n *                      be \\c NULL is \\p ad_len is \\c 0.\n * \\param ad_len        The length of \\p ad. For NIST_KW, this must be \\c 0.\n * \\param input         The buffer holding the input data. This must be a\n *                      readable buffer of at least \\p ilen Bytes, and may be\n *                      \\c NULL if \\p ilen is \\c 0.\n * \\param ilen          The length of the input data. For AEAD ciphers this\n *                      must be at least \\p tag_len. For NIST_KW this must be\n *                      at least \\c 8.\n * \\param output        The buffer for the output data. This must be a\n *                      writable buffer of at least \\p output_len Bytes, and\n *                      may be \\c NULL if \\p output_len is \\c 0.\n * \\param output_len    The length of the \\p output buffer in Bytes. For AEAD\n *                      ciphers, this must be at least \\p ilen - \\p tag_len.\n *                      For NIST_KW, this must be at least \\p ilen - 8.\n * \\param olen          This will be filled with the actual number of Bytes\n *                      written to the \\p output buffer. This must point to a\n *                      writable object of type \\c size_t.\n * \\param tag_len       The actual length of the authentication tag. For AEAD\n *                      ciphers, this must match the constraints imposed by\n *                      the cipher used, and in particular must not be \\c 0.\n *                      For NIST_KW, this must be \\c 0.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on\n *                      parameter-verification failure.\n * \\return              #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic.\n * \\return              A cipher-specific error code on failure.\n */\nint mbedtls_cipher_auth_decrypt_ext(mbedtls_cipher_context_t *ctx,\n                                    const unsigned char *iv, size_t iv_len,\n                                    const unsigned char *ad, size_t ad_len,\n                                    const unsigned char *input, size_t ilen,\n                                    unsigned char *output, size_t output_len,\n                                    size_t *olen, size_t tag_len);\n#endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_CIPHER_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/cmac.h",
    "content": "/**\n * \\file cmac.h\n *\n * \\brief This file contains CMAC definitions and functions.\n *\n * The Cipher-based Message Authentication Code (CMAC) Mode for\n * Authentication is defined in <em>RFC-4493: The AES-CMAC Algorithm</em>.\n * It is supported with AES and DES.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CMAC_H\n#define MBEDTLS_CMAC_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/cipher.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define MBEDTLS_AES_BLOCK_SIZE          16\n#define MBEDTLS_DES3_BLOCK_SIZE         8\n\n/* We don't support Camellia or ARIA in this module */\n#if defined(MBEDTLS_AES_C)\n#define MBEDTLS_CMAC_MAX_BLOCK_SIZE      16  /**< The longest block used by CMAC is that of AES. */\n#else\n#define MBEDTLS_CMAC_MAX_BLOCK_SIZE      8   /**< The longest block used by CMAC is that of 3DES. */\n#endif\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n/** The longest block supported by the cipher module.\n *\n * \\deprecated\n * For the maximum block size of a cipher supported by the CMAC module,\n * use #MBEDTLS_CMAC_MAX_BLOCK_SIZE.\n * For the maximum block size of a cipher supported by the cipher module,\n * use #MBEDTLS_MAX_BLOCK_LENGTH.\n */\n/* Before Mbed TLS 3.5, this was the maximum block size supported by the CMAC\n * module, so it didn't take Camellia or ARIA into account. Since the name\n * of the macro doesn't even convey \"CMAC\", this was misleading. Now the size\n * is sufficient for any cipher, but the name is defined in cmac.h for\n * backward compatibility. */\n#define MBEDTLS_CIPHER_BLKSIZE_MAX MBEDTLS_MAX_BLOCK_LENGTH\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n\n#if !defined(MBEDTLS_CMAC_ALT)\n\n/**\n * The CMAC context structure.\n */\nstruct mbedtls_cmac_context_t {\n    /** The internal state of the CMAC algorithm.  */\n    unsigned char       MBEDTLS_PRIVATE(state)[MBEDTLS_CMAC_MAX_BLOCK_SIZE];\n\n    /** Unprocessed data - either data that was not block aligned and is still\n     *  pending processing, or the final block. */\n    unsigned char       MBEDTLS_PRIVATE(unprocessed_block)[MBEDTLS_CMAC_MAX_BLOCK_SIZE];\n\n    /** The length of data pending processing. */\n    size_t              MBEDTLS_PRIVATE(unprocessed_len);\n};\n\n#else  /* !MBEDTLS_CMAC_ALT */\n#include \"cmac_alt.h\"\n#endif /* !MBEDTLS_CMAC_ALT */\n\n/**\n * \\brief               This function starts a new CMAC computation\n *                      by setting the CMAC key, and preparing to authenticate\n *                      the input data.\n *                      It must be called with an initialized cipher context.\n *\n *                      Once this function has completed, data can be supplied\n *                      to the CMAC computation by calling\n *                      mbedtls_cipher_cmac_update().\n *\n *                      To start a CMAC computation using the same key as a previous\n *                      CMAC computation, use mbedtls_cipher_cmac_finish().\n *\n * \\note                When the CMAC implementation is supplied by an alternate\n *                      implementation (through #MBEDTLS_CMAC_ALT), some ciphers\n *                      may not be supported by that implementation, and thus\n *                      return an error. Alternate implementations must support\n *                      AES-128 and AES-256, and may support AES-192 and 3DES.\n *\n * \\param ctx           The cipher context used for the CMAC operation, initialized\n *                      as one of the following types: MBEDTLS_CIPHER_AES_128_ECB,\n *                      MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_CIPHER_AES_256_ECB,\n *                      or MBEDTLS_CIPHER_DES_EDE3_ECB.\n * \\param key           The CMAC key.\n * \\param keybits       The length of the CMAC key in bits.\n *                      Must be supported by the cipher.\n *\n * \\return              \\c 0 on success.\n * \\return              A cipher-specific error code on failure.\n */\nint mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx,\n                               const unsigned char *key, size_t keybits);\n\n/**\n * \\brief               This function feeds an input buffer into an ongoing CMAC\n *                      computation.\n *\n *                      The CMAC computation must have previously been started\n *                      by calling mbedtls_cipher_cmac_starts() or\n *                      mbedtls_cipher_cmac_reset().\n *\n *                      Call this function as many times as needed to input the\n *                      data to be authenticated.\n *                      Once all of the required data has been input,\n *                      call mbedtls_cipher_cmac_finish() to obtain the result\n *                      of the CMAC operation.\n *\n * \\param ctx           The cipher context used for the CMAC operation.\n * \\param input         The buffer holding the input data.\n * \\param ilen          The length of the input data.\n *\n * \\return             \\c 0 on success.\n * \\return             #MBEDTLS_ERR_MD_BAD_INPUT_DATA\n *                     if parameter verification fails.\n */\nint mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx,\n                               const unsigned char *input, size_t ilen);\n\n/**\n * \\brief               This function finishes an ongoing CMAC operation, and\n *                      writes the result to the output buffer.\n *\n *                      It should be followed either by\n *                      mbedtls_cipher_cmac_reset(), which starts another CMAC\n *                      operation with the same key, or mbedtls_cipher_free(),\n *                      which clears the cipher context.\n *\n * \\param ctx           The cipher context used for the CMAC operation.\n * \\param output        The output buffer for the CMAC checksum result.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_MD_BAD_INPUT_DATA\n *                      if parameter verification fails.\n */\nint mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx,\n                               unsigned char *output);\n\n/**\n * \\brief               This function starts a new CMAC operation with the same\n *                      key as the previous one.\n *\n *                      It should be called after finishing the previous CMAC\n *                      operation with mbedtls_cipher_cmac_finish().\n *                      After calling this function,\n *                      call mbedtls_cipher_cmac_update() to supply the new\n *                      CMAC operation with data.\n *\n * \\param ctx           The cipher context used for the CMAC operation.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_MD_BAD_INPUT_DATA\n *                      if parameter verification fails.\n */\nint mbedtls_cipher_cmac_reset(mbedtls_cipher_context_t *ctx);\n\n/**\n * \\brief               This function calculates the full generic CMAC\n *                      on the input buffer with the provided key.\n *\n *                      The function allocates the context, performs the\n *                      calculation, and frees the context.\n *\n *                      The CMAC result is calculated as\n *                      output = generic CMAC(cmac key, input buffer).\n *\n * \\note                When the CMAC implementation is supplied by an alternate\n *                      implementation (through #MBEDTLS_CMAC_ALT), some ciphers\n *                      may not be supported by that implementation, and thus\n *                      return an error. Alternate implementations must support\n *                      AES-128 and AES-256, and may support AES-192 and 3DES.\n *\n * \\param cipher_info   The cipher information.\n * \\param key           The CMAC key.\n * \\param keylen        The length of the CMAC key in bits.\n * \\param input         The buffer holding the input data.\n * \\param ilen          The length of the input data.\n * \\param output        The buffer for the generic CMAC result.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_MD_BAD_INPUT_DATA\n *                      if parameter verification fails.\n */\nint mbedtls_cipher_cmac(const mbedtls_cipher_info_t *cipher_info,\n                        const unsigned char *key, size_t keylen,\n                        const unsigned char *input, size_t ilen,\n                        unsigned char *output);\n\n#if defined(MBEDTLS_AES_C)\n/**\n * \\brief           This function implements the AES-CMAC-PRF-128 pseudorandom\n *                  function, as defined in\n *                  <em>RFC-4615: The Advanced Encryption Standard-Cipher-based\n *                  Message Authentication Code-Pseudo-Random Function-128\n *                  (AES-CMAC-PRF-128) Algorithm for the Internet Key\n *                  Exchange Protocol (IKE).</em>\n *\n * \\param key       The key to use.\n * \\param key_len   The key length in Bytes.\n * \\param input     The buffer holding the input data.\n * \\param in_len    The length of the input data in Bytes.\n * \\param output    The buffer holding the generated 16 Bytes of\n *                  pseudorandom output.\n *\n * \\return          \\c 0 on success.\n */\nint mbedtls_aes_cmac_prf_128(const unsigned char *key, size_t key_len,\n                             const unsigned char *input, size_t in_len,\n                             unsigned char output[16]);\n#endif /* MBEDTLS_AES_C */\n\n#if defined(MBEDTLS_SELF_TEST) && (defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C))\n/**\n * \\brief          The CMAC checkup routine.\n *\n * \\note           In case the CMAC routines are provided by an alternative\n *                 implementation (i.e. #MBEDTLS_CMAC_ALT is defined), the\n *                 checkup routine will succeed even if the implementation does\n *                 not support the less widely used AES-192 or 3DES primitives.\n *                 The self-test requires at least AES-128 and AES-256 to be\n *                 supported by the underlying implementation.\n *\n * \\return         \\c 0 on success.\n * \\return         \\c 1 on failure.\n */\nint mbedtls_cmac_self_test(int verbose);\n#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_CMAC_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/compat-2.x.h",
    "content": "/**\n * \\file compat-2.x.h\n *\n * \\brief Compatibility definitions\n *\n * \\deprecated Use the new names directly instead\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#if defined(MBEDTLS_DEPRECATED_WARNING)\n#warning \"Including compat-2.x.h is deprecated\"\n#endif\n\n#ifndef MBEDTLS_COMPAT2X_H\n#define MBEDTLS_COMPAT2X_H\n\n/*\n * Macros for renamed functions\n */\n#define mbedtls_ctr_drbg_update_ret   mbedtls_ctr_drbg_update\n#define mbedtls_hmac_drbg_update_ret  mbedtls_hmac_drbg_update\n#define mbedtls_md5_starts_ret        mbedtls_md5_starts\n#define mbedtls_md5_update_ret        mbedtls_md5_update\n#define mbedtls_md5_finish_ret        mbedtls_md5_finish\n#define mbedtls_md5_ret               mbedtls_md5\n#define mbedtls_ripemd160_starts_ret  mbedtls_ripemd160_starts\n#define mbedtls_ripemd160_update_ret  mbedtls_ripemd160_update\n#define mbedtls_ripemd160_finish_ret  mbedtls_ripemd160_finish\n#define mbedtls_ripemd160_ret         mbedtls_ripemd160\n#define mbedtls_sha1_starts_ret       mbedtls_sha1_starts\n#define mbedtls_sha1_update_ret       mbedtls_sha1_update\n#define mbedtls_sha1_finish_ret       mbedtls_sha1_finish\n#define mbedtls_sha1_ret              mbedtls_sha1\n#define mbedtls_sha256_starts_ret     mbedtls_sha256_starts\n#define mbedtls_sha256_update_ret     mbedtls_sha256_update\n#define mbedtls_sha256_finish_ret     mbedtls_sha256_finish\n#define mbedtls_sha256_ret            mbedtls_sha256\n#define mbedtls_sha512_starts_ret     mbedtls_sha512_starts\n#define mbedtls_sha512_update_ret     mbedtls_sha512_update\n#define mbedtls_sha512_finish_ret     mbedtls_sha512_finish\n#define mbedtls_sha512_ret            mbedtls_sha512\n\n#endif /* MBEDTLS_COMPAT2X_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/config_adjust_legacy_crypto.h",
    "content": "/**\n * \\file mbedtls/config_adjust_legacy_crypto.h\n * \\brief Adjust legacy configuration configuration\n *\n * This is an internal header. Do not include it directly.\n *\n * Automatically enable certain dependencies. Generally, MBEDTLS_xxx\n * configurations need to be explicitly enabled by the user: enabling\n * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a\n * compilation error. However, we do automatically enable certain options\n * in some circumstances. One case is if MBEDTLS_xxx_B is an internal option\n * used to identify parts of a module that are used by other module, and we\n * don't want to make the symbol MBEDTLS_xxx_B part of the public API.\n * Another case is if A didn't depend on B in earlier versions, and we\n * want to use B in A but we need to preserve backward compatibility with\n * configurations that explicitly activate MBEDTLS_xxx_A but not\n * MBEDTLS_xxx_B.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H\n#define MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H\n\n#if !defined(MBEDTLS_CONFIG_FILES_READ)\n#error \"Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, \" \\\n    \"up to and including runtime errors such as buffer overflows. \" \\\n    \"If you're trying to fix a complaint from check_config.h, just remove \" \\\n    \"it from your configuration file: since Mbed TLS 3.0, it is included \" \\\n    \"automatically at the right point.\"\n#endif /* */\n\n/* Ideally, we'd set those as defaults in mbedtls_config.h, but\n * putting an #ifdef _WIN32 in mbedtls_config.h would confuse config.py.\n *\n * So, adjust it here.\n * Not related to crypto, but this is the bottom of the stack. */\n#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900)\n#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \\\n    !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO)\n#define MBEDTLS_PLATFORM_SNPRINTF_ALT\n#endif\n#if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \\\n    !defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO)\n#define MBEDTLS_PLATFORM_VSNPRINTF_ALT\n#endif\n#endif /* _MINGW32__ || (_MSC_VER && (_MSC_VER <= 1900)) */\n\n/* If MBEDTLS_PSA_CRYPTO_C is defined, make sure MBEDTLS_PSA_CRYPTO_CLIENT\n * is defined as well to include all PSA code.\n */\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n#define MBEDTLS_PSA_CRYPTO_CLIENT\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n\n/* Auto-enable CIPHER_C when any of the unauthenticated ciphers is builtin\n * in PSA. */\n#if defined(MBEDTLS_PSA_CRYPTO_C) && \\\n    (defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC))\n#define MBEDTLS_CIPHER_C\n#endif\n\n/* Auto-enable MBEDTLS_MD_LIGHT based on MBEDTLS_MD_C.\n * This allows checking for MD_LIGHT rather than MD_LIGHT || MD_C.\n */\n#if defined(MBEDTLS_MD_C)\n#define MBEDTLS_MD_LIGHT\n#endif\n\n/* Auto-enable MBEDTLS_MD_LIGHT if needed by a module that didn't require it\n * in a previous release, to ensure backwards compatibility.\n */\n#if defined(MBEDTLS_ECJPAKE_C) || \\\n    defined(MBEDTLS_PEM_PARSE_C) || \\\n    defined(MBEDTLS_ENTROPY_C) || \\\n    defined(MBEDTLS_PK_C) || \\\n    defined(MBEDTLS_PKCS12_C) || \\\n    defined(MBEDTLS_RSA_C) || \\\n    defined(MBEDTLS_SSL_TLS_C) || \\\n    defined(MBEDTLS_X509_USE_C) || \\\n    defined(MBEDTLS_X509_CREATE_C)\n#define MBEDTLS_MD_LIGHT\n#endif\n\n#if defined(MBEDTLS_MD_LIGHT)\n/*\n * - MBEDTLS_MD_CAN_xxx is defined if the md module can perform xxx.\n * - MBEDTLS_MD_xxx_VIA_PSA is defined if the md module may perform xxx via PSA\n *   (see below).\n * - MBEDTLS_MD_SOME_PSA is defined if at least one algorithm may be performed\n *   via PSA (see below).\n * - MBEDTLS_MD_SOME_LEGACY is defined if at least one algorithm may be performed\n *   via a direct legacy call (see below).\n *\n * The md module performs an algorithm via PSA if there is a PSA hash\n * accelerator and the PSA driver subsytem is initialized at the time the\n * operation is started, and makes a direct legacy call otherwise.\n */\n\n/* PSA accelerated implementations */\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n\n#if defined(MBEDTLS_PSA_ACCEL_ALG_MD5)\n#define MBEDTLS_MD_CAN_MD5\n#define MBEDTLS_MD_MD5_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1)\n#define MBEDTLS_MD_CAN_SHA1\n#define MBEDTLS_MD_SHA1_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224)\n#define MBEDTLS_MD_CAN_SHA224\n#define MBEDTLS_MD_SHA224_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)\n#define MBEDTLS_MD_CAN_SHA256\n#define MBEDTLS_MD_SHA256_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384)\n#define MBEDTLS_MD_CAN_SHA384\n#define MBEDTLS_MD_SHA384_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512)\n#define MBEDTLS_MD_CAN_SHA512\n#define MBEDTLS_MD_SHA512_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160)\n#define MBEDTLS_MD_CAN_RIPEMD160\n#define MBEDTLS_MD_RIPEMD160_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_224)\n#define MBEDTLS_MD_CAN_SHA3_224\n#define MBEDTLS_MD_SHA3_224_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_256)\n#define MBEDTLS_MD_CAN_SHA3_256\n#define MBEDTLS_MD_SHA3_256_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_384)\n#define MBEDTLS_MD_CAN_SHA3_384\n#define MBEDTLS_MD_SHA3_384_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_512)\n#define MBEDTLS_MD_CAN_SHA3_512\n#define MBEDTLS_MD_SHA3_512_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n\n#elif defined(MBEDTLS_PSA_CRYPTO_CLIENT)\n\n#if defined(PSA_WANT_ALG_MD5)\n#define MBEDTLS_MD_CAN_MD5\n#define MBEDTLS_MD_MD5_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(PSA_WANT_ALG_SHA_1)\n#define MBEDTLS_MD_CAN_SHA1\n#define MBEDTLS_MD_SHA1_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(PSA_WANT_ALG_SHA_224)\n#define MBEDTLS_MD_CAN_SHA224\n#define MBEDTLS_MD_SHA224_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(PSA_WANT_ALG_SHA_256)\n#define MBEDTLS_MD_CAN_SHA256\n#define MBEDTLS_MD_SHA256_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(PSA_WANT_ALG_SHA_384)\n#define MBEDTLS_MD_CAN_SHA384\n#define MBEDTLS_MD_SHA384_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(PSA_WANT_ALG_SHA_512)\n#define MBEDTLS_MD_CAN_SHA512\n#define MBEDTLS_MD_SHA512_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(PSA_WANT_ALG_RIPEMD160)\n#define MBEDTLS_MD_CAN_RIPEMD160\n#define MBEDTLS_MD_RIPEMD160_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(PSA_WANT_ALG_SHA3_224)\n#define MBEDTLS_MD_CAN_SHA3_224\n#define MBEDTLS_MD_SHA3_224_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(PSA_WANT_ALG_SHA3_256)\n#define MBEDTLS_MD_CAN_SHA3_256\n#define MBEDTLS_MD_SHA3_256_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(PSA_WANT_ALG_SHA3_384)\n#define MBEDTLS_MD_CAN_SHA3_384\n#define MBEDTLS_MD_SHA3_384_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n#if defined(PSA_WANT_ALG_SHA3_512)\n#define MBEDTLS_MD_CAN_SHA3_512\n#define MBEDTLS_MD_SHA3_512_VIA_PSA\n#define MBEDTLS_MD_SOME_PSA\n#endif\n\n#endif /* !MBEDTLS_PSA_CRYPTO_CLIENT && !MBEDTLS_PSA_CRYPTO_C */\n\n/* Built-in implementations */\n#if defined(MBEDTLS_MD5_C)\n#define MBEDTLS_MD_CAN_MD5\n#define MBEDTLS_MD_SOME_LEGACY\n#endif\n#if defined(MBEDTLS_SHA1_C)\n#define MBEDTLS_MD_CAN_SHA1\n#define MBEDTLS_MD_SOME_LEGACY\n#endif\n#if defined(MBEDTLS_SHA224_C)\n#define MBEDTLS_MD_CAN_SHA224\n#define MBEDTLS_MD_SOME_LEGACY\n#endif\n#if defined(MBEDTLS_SHA256_C)\n#define MBEDTLS_MD_CAN_SHA256\n#define MBEDTLS_MD_SOME_LEGACY\n#endif\n#if defined(MBEDTLS_SHA384_C)\n#define MBEDTLS_MD_CAN_SHA384\n#define MBEDTLS_MD_SOME_LEGACY\n#endif\n#if defined(MBEDTLS_SHA512_C)\n#define MBEDTLS_MD_CAN_SHA512\n#define MBEDTLS_MD_SOME_LEGACY\n#endif\n#if defined(MBEDTLS_SHA3_C)\n#define MBEDTLS_MD_CAN_SHA3_224\n#define MBEDTLS_MD_CAN_SHA3_256\n#define MBEDTLS_MD_CAN_SHA3_384\n#define MBEDTLS_MD_CAN_SHA3_512\n#define MBEDTLS_MD_SOME_LEGACY\n#endif\n#if defined(MBEDTLS_RIPEMD160_C)\n#define MBEDTLS_MD_CAN_RIPEMD160\n#define MBEDTLS_MD_SOME_LEGACY\n#endif\n\n#endif /* MBEDTLS_MD_LIGHT */\n\n/* BLOCK_CIPHER module can dispatch to PSA when:\n * - PSA is enabled and drivers have been initialized\n * - desired key type is supported on the PSA side\n * If the above conditions are not met, but the legacy support is enabled, then\n * BLOCK_CIPHER will dynamically fallback to it.\n *\n * In case BLOCK_CIPHER is defined (see below) the following symbols/helpers\n * can be used to define its capabilities:\n * - MBEDTLS_BLOCK_CIPHER_SOME_PSA: there is at least 1 key type between AES,\n *   ARIA and Camellia which is supported through a driver;\n * - MBEDTLS_BLOCK_CIPHER_xxx_VIA_PSA: xxx key type is supported through a\n *   driver;\n * - MBEDTLS_BLOCK_CIPHER_xxx_VIA_LEGACY: xxx key type is supported through\n *   a legacy module (i.e. MBEDTLS_xxx_C)\n */\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES)\n#define MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA\n#define MBEDTLS_BLOCK_CIPHER_SOME_PSA\n#endif\n#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA)\n#define MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA\n#define MBEDTLS_BLOCK_CIPHER_SOME_PSA\n#endif\n#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA)\n#define MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA\n#define MBEDTLS_BLOCK_CIPHER_SOME_PSA\n#endif\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n\n#if defined(MBEDTLS_AES_C)\n#define MBEDTLS_BLOCK_CIPHER_AES_VIA_LEGACY\n#endif\n#if defined(MBEDTLS_ARIA_C)\n#define MBEDTLS_BLOCK_CIPHER_ARIA_VIA_LEGACY\n#endif\n#if defined(MBEDTLS_CAMELLIA_C)\n#define MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_LEGACY\n#endif\n\n/* Helpers to state that BLOCK_CIPHER module supports AES, ARIA and/or Camellia\n * block ciphers via either PSA or legacy. */\n#if defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA) || \\\n    defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_LEGACY)\n#define MBEDTLS_BLOCK_CIPHER_CAN_AES\n#endif\n#if defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA) || \\\n    defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_LEGACY)\n#define MBEDTLS_BLOCK_CIPHER_CAN_ARIA\n#endif\n#if defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA) || \\\n    defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_LEGACY)\n#define MBEDTLS_BLOCK_CIPHER_CAN_CAMELLIA\n#endif\n\n/* GCM_C and CCM_C can either depend on (in order of preference) BLOCK_CIPHER_C\n * or CIPHER_C. The former is auto-enabled when:\n * - CIPHER_C is not defined, which is also the legacy solution;\n * - BLOCK_CIPHER_SOME_PSA because in this case BLOCK_CIPHER can take advantage\n *   of the driver's acceleration.\n */\n#if (defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)) && \\\n    (!defined(MBEDTLS_CIPHER_C) || defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA))\n#define MBEDTLS_BLOCK_CIPHER_C\n#endif\n\n/* Helpers for GCM/CCM capabilities */\n#if (defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_AES_C)) || \\\n    (defined(MBEDTLS_BLOCK_CIPHER_C) && defined(MBEDTLS_BLOCK_CIPHER_CAN_AES))\n#define MBEDTLS_CCM_GCM_CAN_AES\n#endif\n\n#if (defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_ARIA_C)) || \\\n    (defined(MBEDTLS_BLOCK_CIPHER_C) && defined(MBEDTLS_BLOCK_CIPHER_CAN_ARIA))\n#define MBEDTLS_CCM_GCM_CAN_ARIA\n#endif\n\n#if (defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_CAMELLIA_C)) || \\\n    (defined(MBEDTLS_BLOCK_CIPHER_C) && defined(MBEDTLS_BLOCK_CIPHER_CAN_CAMELLIA))\n#define MBEDTLS_CCM_GCM_CAN_CAMELLIA\n#endif\n\n/* MBEDTLS_ECP_LIGHT is auto-enabled by the following symbols:\n * - MBEDTLS_ECP_C because now it consists of MBEDTLS_ECP_LIGHT plus functions\n *   for curve arithmetic. As a consequence if MBEDTLS_ECP_C is required for\n *   some reason, then MBEDTLS_ECP_LIGHT should be enabled as well.\n * - MBEDTLS_PK_PARSE_EC_EXTENDED and MBEDTLS_PK_PARSE_EC_COMPRESSED because\n *   these features are not supported in PSA so the only way to have them is\n *   to enable the built-in solution.\n *   Both of them are temporary dependencies:\n *   - PK_PARSE_EC_EXTENDED will be removed after #7779 and #7789\n *   - support for compressed points should also be added to PSA, but in this\n *     case there is no associated issue to track it yet.\n * - PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE because Weierstrass key derivation\n *   still depends on ECP_LIGHT.\n * - PK_C + USE_PSA + PSA_WANT_ALG_ECDSA is a temporary dependency which will\n *   be fixed by #7453.\n */\n#if defined(MBEDTLS_ECP_C) || \\\n    defined(MBEDTLS_PK_PARSE_EC_EXTENDED) || \\\n    defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE)\n#define MBEDTLS_ECP_LIGHT\n#endif\n\n/* Backward compatibility: after #8740 the RSA module offers functions to parse\n * and write RSA private/public keys without relying on the PK one. Of course\n * this needs ASN1 support to do so, so we enable it here. */\n#if defined(MBEDTLS_RSA_C)\n#define MBEDTLS_ASN1_PARSE_C\n#define MBEDTLS_ASN1_WRITE_C\n#endif\n\n/* MBEDTLS_PK_PARSE_EC_COMPRESSED is introduced in Mbed TLS version 3.5, while\n * in previous version compressed points were automatically supported as long\n * as PK_PARSE_C and ECP_C were enabled. As a consequence, for backward\n * compatibility, we auto-enable PK_PARSE_EC_COMPRESSED when these conditions\n * are met. */\n#if defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_ECP_C)\n#define MBEDTLS_PK_PARSE_EC_COMPRESSED\n#endif\n\n/* Helper symbol to state that there is support for ECDH, either through\n * library implementation (ECDH_C) or through PSA. */\n#if (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_ECDH)) || \\\n    (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECDH_C))\n#define MBEDTLS_CAN_ECDH\n#endif\n\n/* PK module can achieve ECDSA functionalities by means of either software\n * implementations (ECDSA_C) or through a PSA driver. The following defines\n * are meant to list these capabilities in a general way which abstracts how\n * they are implemented under the hood. */\n#if !defined(MBEDTLS_USE_PSA_CRYPTO)\n#if defined(MBEDTLS_ECDSA_C)\n#define MBEDTLS_PK_CAN_ECDSA_SIGN\n#define MBEDTLS_PK_CAN_ECDSA_VERIFY\n#endif /* MBEDTLS_ECDSA_C */\n#else /* MBEDTLS_USE_PSA_CRYPTO */\n#if defined(PSA_WANT_ALG_ECDSA)\n#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC)\n#define MBEDTLS_PK_CAN_ECDSA_SIGN\n#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC */\n#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)\n#define MBEDTLS_PK_CAN_ECDSA_VERIFY\n#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */\n#endif /* PSA_WANT_ALG_ECDSA */\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) || defined(MBEDTLS_PK_CAN_ECDSA_SIGN)\n#define MBEDTLS_PK_CAN_ECDSA_SOME\n#endif\n\n/* Helpers to state that each key is supported either on the builtin or PSA side. */\n#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_521)\n#define MBEDTLS_ECP_HAVE_SECP521R1\n#endif\n#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)\n#define MBEDTLS_ECP_HAVE_BP512R1\n#endif\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_448)\n#define MBEDTLS_ECP_HAVE_CURVE448\n#endif\n#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)\n#define MBEDTLS_ECP_HAVE_BP384R1\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_384)\n#define MBEDTLS_ECP_HAVE_SECP384R1\n#endif\n#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)\n#define MBEDTLS_ECP_HAVE_BP256R1\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_256)\n#define MBEDTLS_ECP_HAVE_SECP256K1\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_256)\n#define MBEDTLS_ECP_HAVE_SECP256R1\n#endif\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_255)\n#define MBEDTLS_ECP_HAVE_CURVE25519\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_224)\n#define MBEDTLS_ECP_HAVE_SECP224K1\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_224)\n#define MBEDTLS_ECP_HAVE_SECP224R1\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_192)\n#define MBEDTLS_ECP_HAVE_SECP192K1\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_192)\n#define MBEDTLS_ECP_HAVE_SECP192R1\n#endif\n\n/* Helper symbol to state that the PK module has support for EC keys. This\n * can either be provided through the legacy ECP solution or through the\n * PSA friendly MBEDTLS_PK_USE_PSA_EC_DATA (see pk.h for its description). */\n#if defined(MBEDTLS_ECP_C) || \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY))\n#define MBEDTLS_PK_HAVE_ECC_KEYS\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_ECP_C */\n\n/* Historically pkparse did not check the CBC padding when decrypting\n * a key. This was a bug, which is now fixed. As a consequence, pkparse\n * now needs PKCS7 padding support, but existing configurations might not\n * enable it, so we enable it here. */\n#if defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_CIPHER_MODE_CBC)\n#define MBEDTLS_CIPHER_PADDING_PKCS7\n#endif\n\n/* Backwards compatibility for some macros which were renamed to reflect that\n * they are related to Armv8, not aarch64. */\n#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) && \\\n    !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)\n#define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT\n#endif\n#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) && !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)\n#define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY\n#endif\n\n/* psa_util file features some ECDSA conversion functions, to convert between\n * legacy's ASN.1 DER format and PSA's raw one. */\n#if (defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \\\n    (defined(PSA_WANT_ALG_ECDSA) || defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)))\n#define MBEDTLS_PSA_UTIL_HAVE_ECDSA\n#endif\n\n/* Some internal helpers to determine which keys are available. */\n#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_AES_C)) || \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_AES))\n#define MBEDTLS_SSL_HAVE_AES\n#endif\n#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ARIA_C)) || \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ARIA))\n#define MBEDTLS_SSL_HAVE_ARIA\n#endif\n#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CAMELLIA_C)) || \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_CAMELLIA))\n#define MBEDTLS_SSL_HAVE_CAMELLIA\n#endif\n\n/* Some internal helpers to determine which operation modes are available. */\n#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CIPHER_MODE_CBC)) || \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CBC_NO_PADDING))\n#define MBEDTLS_SSL_HAVE_CBC\n#endif\n\n#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_GCM_C)) || \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM))\n#define MBEDTLS_SSL_HAVE_GCM\n#endif\n\n#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CCM_C)) || \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM))\n#define MBEDTLS_SSL_HAVE_CCM\n#endif\n\n#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CHACHAPOLY_C)) || \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CHACHA20_POLY1305))\n#define MBEDTLS_SSL_HAVE_CHACHAPOLY\n#endif\n\n#if defined(MBEDTLS_SSL_HAVE_GCM) || defined(MBEDTLS_SSL_HAVE_CCM) || \\\n    defined(MBEDTLS_SSL_HAVE_CHACHAPOLY)\n#define MBEDTLS_SSL_HAVE_AEAD\n#endif\n\n#endif /* MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/config_adjust_legacy_from_psa.h",
    "content": "/**\n * \\file mbedtls/config_adjust_legacy_from_psa.h\n * \\brief Adjust PSA configuration: activate legacy implementations\n *\n * This is an internal header. Do not include it directly.\n *\n * When MBEDTLS_PSA_CRYPTO_CONFIG is enabled, activate legacy implementations\n * of cryptographic mechanisms as needed to fulfill the needs of the PSA\n * configuration. Generally speaking, we activate a legacy mechanism if\n * it's needed for a requested PSA mechanism and there is no PSA driver\n * for it.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H\n#define MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H\n\n#if !defined(MBEDTLS_CONFIG_FILES_READ)\n#error \"Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, \" \\\n    \"up to and including runtime errors such as buffer overflows. \" \\\n    \"If you're trying to fix a complaint from check_config.h, just remove \" \\\n    \"it from your configuration file: since Mbed TLS 3.0, it is included \" \\\n    \"automatically at the right point.\"\n#endif /* */\n\n/* Define appropriate ACCEL macros for the p256-m driver.\n * In the future, those should be generated from the drivers JSON description.\n */\n#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)\n#define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256\n#define MBEDTLS_PSA_ACCEL_ALG_ECDSA\n#define MBEDTLS_PSA_ACCEL_ALG_ECDH\n#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY\n#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC\n#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT\n#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT\n#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE\n#endif\n\n/*\n * ECC: support for a feature is controlled by a triplet or a pair:\n * (curve, key_type public/basic, alg) or (curve, key_type_<action>).\n *\n * A triplet/pair is accelerated if all of is components are accelerated;\n * otherwise each component needs to be built in.\n *\n * We proceed in two passes:\n * 1. Check if acceleration is complete for curves, key types, algs.\n * 2. Then enable built-ins for each thing that's either not accelerated of\n * doesn't have complete acceleration of the other triplet/pair components.\n *\n * Note: this needs psa/crypto_adjust_keypair_types.h to have been included\n * already, so that we know the full set of key types that are requested.\n */\n\n/* ECC: curves: is acceleration complete? */\n#if (defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) && \\\n    !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256)) || \\\n    (defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) && \\\n    !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384)) || \\\n    (defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) && \\\n    !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512)) || \\\n    (defined(PSA_WANT_ECC_SECP_R1_192) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192)) || \\\n    (defined(PSA_WANT_ECC_SECP_R1_224) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224)) || \\\n    (defined(PSA_WANT_ECC_SECP_R1_256) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256)) || \\\n    (defined(PSA_WANT_ECC_SECP_R1_384) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384)) || \\\n    (defined(PSA_WANT_ECC_SECP_R1_521) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521)) || \\\n    (defined(PSA_WANT_ECC_SECP_K1_192) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192)) || \\\n    (defined(PSA_WANT_ECC_SECP_K1_256) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256))\n#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES\n#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_WEIERSTRASS_CURVES\n#endif\n\n#if (defined(PSA_WANT_ECC_MONTGOMERY_255) && !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255)) || \\\n    (defined(PSA_WANT_ECC_MONTGOMERY_448) && !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448))\n#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES\n#endif\n\n/* ECC: algs: is acceleration complete? */\n#if (defined(PSA_WANT_ALG_ECDH) && !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH)) || \\\n    (defined(PSA_WANT_ALG_ECDSA) && !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA)) || \\\n    (defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \\\n    !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA)) || \\\n    (defined(PSA_WANT_ALG_JPAKE) && !defined(MBEDTLS_PSA_ACCEL_ALG_JPAKE))\n#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS\n#endif\n\n/* ECC: key types: is acceleration complete? */\n#if (defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)) || \\\n    (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC))\n#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC\n#endif\n\n/* Special case: we don't support cooked key derivation in drivers yet */\n#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE)\n#undef MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE\n#endif\n\n/* Note: the condition about key derivation is always true as DERIVE can't be\n * accelerated yet */\n#if (defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)) || \\\n    (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC)) || \\\n    (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) && \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT)) || \\\n    (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) && \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT)) || \\\n    (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) && \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE)) || \\\n    (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) && \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE))\n#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES\n#endif\n\n/* ECC: curves: enable built-ins as needed.\n *\n * We need the curve built-in:\n * - if it's not accelerated, or\n * - if there's a key type with missing acceleration, or\n * - if there's a alg with missing acceleration.\n */\n#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)\n#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1\n#define MBEDTLS_ECP_DP_BP256R1_ENABLED\n#endif /* missing accel */\n#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_256 */\n\n#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)\n#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1\n#define MBEDTLS_ECP_DP_BP384R1_ENABLED\n#endif /* missing accel */\n#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_384 */\n\n#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)\n#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1\n#define MBEDTLS_ECP_DP_BP512R1_ENABLED\n#endif /* missing accel */\n#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_512 */\n\n#if defined(PSA_WANT_ECC_MONTGOMERY_255)\n#if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1\n#define MBEDTLS_ECP_DP_CURVE25519_ENABLED\n#endif /* missing accel */\n#endif /* PSA_WANT_ECC_MONTGOMERY_255 */\n\n#if defined(PSA_WANT_ECC_MONTGOMERY_448)\n#if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1\n#define MBEDTLS_ECP_DP_CURVE448_ENABLED\n#endif /* missing accel */\n#endif /* PSA_WANT_ECC_MONTGOMERY_448 */\n\n#if defined(PSA_WANT_ECC_SECP_R1_192)\n#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1\n#define MBEDTLS_ECP_DP_SECP192R1_ENABLED\n#endif /* missing accel */\n#endif /* PSA_WANT_ECC_SECP_R1_192 */\n\n#if defined(PSA_WANT_ECC_SECP_R1_224)\n#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1\n#define MBEDTLS_ECP_DP_SECP224R1_ENABLED\n#endif /* missing accel */\n#endif /* PSA_WANT_ECC_SECP_R1_224 */\n\n#if defined(PSA_WANT_ECC_SECP_R1_256)\n#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1\n#define MBEDTLS_ECP_DP_SECP256R1_ENABLED\n#endif /* missing accel */\n#endif /* PSA_WANT_ECC_SECP_R1_256 */\n\n#if defined(PSA_WANT_ECC_SECP_R1_384)\n#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1\n#define MBEDTLS_ECP_DP_SECP384R1_ENABLED\n#endif /* missing accel */\n#endif /* PSA_WANT_ECC_SECP_R1_384 */\n\n#if defined(PSA_WANT_ECC_SECP_R1_521)\n#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1\n#define MBEDTLS_ECP_DP_SECP521R1_ENABLED\n#endif /* missing accel */\n#endif /* PSA_WANT_ECC_SECP_R1_521 */\n\n#if defined(PSA_WANT_ECC_SECP_K1_192)\n#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1\n#define MBEDTLS_ECP_DP_SECP192K1_ENABLED\n#endif /* missing accel */\n#endif /* PSA_WANT_ECC_SECP_K1_192 */\n\n#if defined(PSA_WANT_ECC_SECP_K1_256)\n#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1\n#define MBEDTLS_ECP_DP_SECP256K1_ENABLED\n#endif /* missing accel */\n#endif /* PSA_WANT_ECC_SECP_K1_256 */\n\n/* ECC: algs: enable built-ins as needed.\n *\n * We need the alg built-in:\n * - if it's not accelerated, or\n * - if there's a relevant curve (see below) with missing acceleration, or\n * - if there's a key type among (public, basic) with missing acceleration.\n *\n * Relevant curves are:\n * - all curves for ECDH\n * - Weierstrass curves for (deterministic) ECDSA\n * - secp256r1 for EC J-PAKE\n */\n#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_WEIERSTRASS_CURVES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC)\n#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1\n#define MBEDTLS_ECDSA_DETERMINISTIC\n#define MBEDTLS_HMAC_DRBG_C\n#define MBEDTLS_MD_C\n#define MBEDTLS_ECDSA_C\n#define MBEDTLS_ECP_C\n#define MBEDTLS_BIGNUM_C\n#define MBEDTLS_ASN1_PARSE_C\n#define MBEDTLS_ASN1_WRITE_C\n#endif /* missing accel */\n#endif /* PSA_WANT_ALG_DETERMINISTIC_ECDSA */\n\n#if defined(PSA_WANT_ALG_ECDH)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC)\n#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1\n#define MBEDTLS_ECDH_C\n#define MBEDTLS_ECP_C\n#define MBEDTLS_BIGNUM_C\n#endif /* missing accel */\n#endif /* PSA_WANT_ALG_ECDH */\n\n#if defined(PSA_WANT_ALG_ECDSA)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_WEIERSTRASS_CURVES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC)\n#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1\n#define MBEDTLS_ECDSA_C\n#define MBEDTLS_ECP_C\n#define MBEDTLS_BIGNUM_C\n#define MBEDTLS_ASN1_PARSE_C\n#define MBEDTLS_ASN1_WRITE_C\n#endif /* missing accel */\n#endif /* PSA_WANT_ALG_ECDSA */\n\n#if defined(PSA_WANT_ALG_JPAKE)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_JPAKE) || \\\n    !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC)\n#define MBEDTLS_PSA_BUILTIN_PAKE 1\n#define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1\n#define MBEDTLS_ECP_DP_SECP256R1_ENABLED\n#define MBEDTLS_BIGNUM_C\n#define MBEDTLS_ECP_C\n#define MBEDTLS_ECJPAKE_C\n#endif /* missing accel */\n#endif /* PSA_WANT_ALG_JPAKE */\n\n/* ECC: key types: enable built-ins as needed.\n *\n * We need the key type built-in:\n * - if it's not accelerated, or\n * - if there's a curve with missing acceleration, or\n * - only for public/basic: if there's an alg with missing acceleration.\n */\n#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1\n#endif /* missing accel */\n#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */\n\n#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC 1\n#endif /* missing accel */\n#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC */\n\n#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1\n#endif /* missing accel */\n#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT */\n\n#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1\n#endif /* missing accel */\n#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT */\n\n#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1\n#endif /* missing accel */\n#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE */\n\n/* Note: the condition is always true as DERIVE can't be accelerated yet */\n#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || \\\n    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1\n#endif /* missing accel */\n#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE */\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE)\n#define MBEDTLS_ECP_LIGHT\n#define MBEDTLS_BIGNUM_C\n#endif\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE)\n#define MBEDTLS_ECP_C\n#define MBEDTLS_BIGNUM_C\n#endif\n\n/* End of ECC section */\n\n/*\n * DH key types follow the same pattern used above for EC keys. They are defined\n * by a triplet (group, key_type, alg). A triplet is accelerated if all its\n * component are accelerated, otherwise each component needs to be builtin.\n */\n\n/* DH: groups: is acceleration complete? */\n#if (defined(PSA_WANT_DH_RFC7919_2048) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_2048)) || \\\n    (defined(PSA_WANT_DH_RFC7919_3072) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_3072)) || \\\n    (defined(PSA_WANT_DH_RFC7919_4096) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_4096)) || \\\n    (defined(PSA_WANT_DH_RFC7919_6144) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_6144)) || \\\n    (defined(PSA_WANT_DH_RFC7919_8192) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_8192))\n#define MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS\n#endif\n\n/* DH: algs: is acceleration complete? */\n#if defined(PSA_WANT_ALG_FFDH) && !defined(MBEDTLS_PSA_ACCEL_ALG_FFDH)\n#define MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS\n#endif\n\n/* DH: key types: is acceleration complete? */\n#if (defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) && \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY)) || \\\n    (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) && \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC)) || \\\n    (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) && \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT)) || \\\n    (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) && \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT)) || \\\n    (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) && \\\n    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE))\n#define MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES\n#endif\n\n#if defined(PSA_WANT_DH_RFC7919_2048)\n#if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_2048) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES)\n#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 1\n#endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */\n#endif /* PSA_WANT_DH_RFC7919_2048 */\n\n#if defined(PSA_WANT_DH_RFC7919_3072)\n#if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_3072) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES)\n#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 1\n#endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */\n#endif /* PSA_WANT_DH_RFC7919_3072 */\n\n#if defined(PSA_WANT_DH_RFC7919_4096)\n#if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_4096) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES)\n#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 1\n#endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */\n#endif /* PSA_WANT_DH_RFC7919_4096 */\n\n#if defined(PSA_WANT_DH_RFC7919_6144)\n#if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_6144) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES)\n#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 1\n#endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */\n#endif /* PSA_WANT_DH_RFC7919_6144 */\n\n#if defined(PSA_WANT_DH_RFC7919_8192)\n#if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_8192) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES)\n#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 1\n#endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */\n#endif /* PSA_WANT_DH_RFC7919_8192 */\n\n#if defined(PSA_WANT_ALG_FFDH)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_FFDH) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES)\n#define MBEDTLS_PSA_BUILTIN_ALG_FFDH 1\n#define MBEDTLS_BIGNUM_C\n#endif /* !MBEDTLS_PSA_ACCEL_ALG_FFDH */\n#endif /* PSA_WANT_ALG_FFDH */\n\n#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT 1\n#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT */\n#endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT */\n\n#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT 1\n#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT */\n#endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT */\n\n#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE 1\n#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE */\n#endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE */\n\n#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_BASIC 1\n#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC */\n#endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC */\n\n#if defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \\\n    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY 1\n#define MBEDTLS_BIGNUM_C\n#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY */\n#endif /* PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY */\n\n/* End of DH section */\n\n#if defined(PSA_WANT_ALG_HKDF)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF)\n/*\n * The PSA implementation has its own implementation of HKDF, separate from\n * hkdf.c. No need to enable MBEDTLS_HKDF_C here.\n */\n#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1\n#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF */\n#endif /* PSA_WANT_ALG_HKDF */\n\n#if defined(PSA_WANT_ALG_HKDF_EXTRACT)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT)\n/*\n * The PSA implementation has its own implementation of HKDF, separate from\n * hkdf.c. No need to enable MBEDTLS_HKDF_C here.\n */\n#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1\n#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT */\n#endif /* PSA_WANT_ALG_HKDF_EXTRACT */\n\n#if defined(PSA_WANT_ALG_HKDF_EXPAND)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND)\n/*\n * The PSA implementation has its own implementation of HKDF, separate from\n * hkdf.c. No need to enable MBEDTLS_HKDF_C here.\n */\n#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1\n#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND */\n#endif /* PSA_WANT_ALG_HKDF_EXPAND */\n\n#if defined(PSA_WANT_ALG_HMAC)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC)\n#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1\n#endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */\n#endif /* PSA_WANT_ALG_HMAC */\n\n#if defined(PSA_WANT_ALG_MD5) && !defined(MBEDTLS_PSA_ACCEL_ALG_MD5)\n#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1\n#define MBEDTLS_MD5_C\n#endif\n\n#if defined(PSA_WANT_ALG_RIPEMD160) && !defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160)\n#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1\n#define MBEDTLS_RIPEMD160_C\n#endif\n\n#if defined(PSA_WANT_ALG_RSA_OAEP)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP)\n#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1\n#define MBEDTLS_RSA_C\n#define MBEDTLS_BIGNUM_C\n#define MBEDTLS_OID_C\n#define MBEDTLS_PKCS1_V21\n#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP */\n#endif /* PSA_WANT_ALG_RSA_OAEP */\n\n#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT)\n#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1\n#define MBEDTLS_RSA_C\n#define MBEDTLS_BIGNUM_C\n#define MBEDTLS_OID_C\n#define MBEDTLS_PKCS1_V15\n#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT */\n#endif /* PSA_WANT_ALG_RSA_PKCS1V15_CRYPT */\n\n#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN)\n#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1\n#define MBEDTLS_RSA_C\n#define MBEDTLS_BIGNUM_C\n#define MBEDTLS_OID_C\n#define MBEDTLS_PKCS1_V15\n#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN */\n#endif /* PSA_WANT_ALG_RSA_PKCS1V15_SIGN */\n\n#if defined(PSA_WANT_ALG_RSA_PSS)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS)\n#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1\n#define MBEDTLS_RSA_C\n#define MBEDTLS_BIGNUM_C\n#define MBEDTLS_OID_C\n#define MBEDTLS_PKCS1_V21\n#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PSS */\n#endif /* PSA_WANT_ALG_RSA_PSS */\n\n#if defined(PSA_WANT_ALG_SHA_1) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1)\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1\n#define MBEDTLS_SHA1_C\n#endif\n\n#if defined(PSA_WANT_ALG_SHA_224) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224)\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1\n#define MBEDTLS_SHA224_C\n#endif\n\n#if defined(PSA_WANT_ALG_SHA_256) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1\n#define MBEDTLS_SHA256_C\n#endif\n\n#if defined(PSA_WANT_ALG_SHA_384) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384)\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1\n#define MBEDTLS_SHA384_C\n#endif\n\n#if defined(PSA_WANT_ALG_SHA_512) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512)\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1\n#define MBEDTLS_SHA512_C\n#endif\n\n#if defined(PSA_WANT_ALG_SHA3_224) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_224)\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_224 1\n#define MBEDTLS_SHA3_C\n#endif\n\n#if defined(PSA_WANT_ALG_SHA3_256) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_256)\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_256 1\n#define MBEDTLS_SHA3_C\n#endif\n\n#if defined(PSA_WANT_ALG_SHA3_384) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_384)\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_384 1\n#define MBEDTLS_SHA3_C\n#endif\n\n#if defined(PSA_WANT_ALG_SHA3_512) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_512)\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_512 1\n#define MBEDTLS_SHA3_C\n#endif\n\n#if defined(PSA_WANT_ALG_PBKDF2_HMAC)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC)\n#define MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC 1\n#define PSA_HAVE_SOFT_PBKDF2_HMAC 1\n#endif /* !MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */\n#endif /* PSA_WANT_ALG_PBKDF2_HMAC */\n\n#if defined(PSA_WANT_ALG_TLS12_PRF)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF)\n#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1\n#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF */\n#endif /* PSA_WANT_ALG_TLS12_PRF */\n\n#if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS)\n#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1\n#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS */\n#endif /* PSA_WANT_ALG_TLS12_PSK_TO_MS */\n\n#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS)\n#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1\n#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS */\n#endif /* PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS */\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1\n#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT */\n#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT */\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1\n#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT */\n#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT */\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1\n#define MBEDTLS_GENPRIME\n#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE */\n#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE */\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_BASIC 1\n#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC */\n#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1\n#define MBEDTLS_RSA_C\n#define MBEDTLS_BIGNUM_C\n#define MBEDTLS_OID_C\n#define MBEDTLS_ASN1_PARSE_C\n#define MBEDTLS_ASN1_WRITE_C\n#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY */\n#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */\n\n/* If any of the block modes are requested that don't have an\n * associated HW assist, define PSA_HAVE_SOFT_BLOCK_MODE for checking\n * in the block cipher key types. */\n#if (defined(PSA_WANT_ALG_CTR) && !defined(MBEDTLS_PSA_ACCEL_ALG_CTR)) || \\\n    (defined(PSA_WANT_ALG_CFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_CFB)) || \\\n    (defined(PSA_WANT_ALG_OFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_OFB)) || \\\n    (defined(PSA_WANT_ALG_ECB_NO_PADDING) && !defined(MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING)) || \\\n    (defined(PSA_WANT_ALG_CBC_NO_PADDING) && !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING)) || \\\n    (defined(PSA_WANT_ALG_CBC_PKCS7) && !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7)) || \\\n    (defined(PSA_WANT_ALG_CMAC) && !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC))\n#define PSA_HAVE_SOFT_BLOCK_MODE 1\n#endif\n\n#if defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128)\n#define MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 1\n#define PSA_HAVE_SOFT_PBKDF2_CMAC 1\n#endif /* !MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128 */\n#endif /* PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 */\n\n#if defined(PSA_WANT_KEY_TYPE_AES)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES)\n#define PSA_HAVE_SOFT_KEY_TYPE_AES 1\n#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_AES */\n#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \\\n    defined(PSA_HAVE_SOFT_BLOCK_MODE)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1\n#define MBEDTLS_AES_C\n#endif /* PSA_HAVE_SOFT_KEY_TYPE_AES || PSA_HAVE_SOFT_BLOCK_MODE */\n#endif /* PSA_WANT_KEY_TYPE_AES */\n\n#if defined(PSA_WANT_KEY_TYPE_ARIA)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA)\n#define PSA_HAVE_SOFT_KEY_TYPE_ARIA 1\n#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA */\n#if defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \\\n    defined(PSA_HAVE_SOFT_BLOCK_MODE)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1\n#define MBEDTLS_ARIA_C\n#endif /* PSA_HAVE_SOFT_KEY_TYPE_ARIA || PSA_HAVE_SOFT_BLOCK_MODE */\n#endif /* PSA_WANT_KEY_TYPE_ARIA */\n\n#if defined(PSA_WANT_KEY_TYPE_CAMELLIA)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA)\n#define PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA 1\n#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA */\n#if defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) || \\\n    defined(PSA_HAVE_SOFT_BLOCK_MODE)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1\n#define MBEDTLS_CAMELLIA_C\n#endif /* PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA || PSA_HAVE_SOFT_BLOCK_MODE */\n#endif /* PSA_WANT_KEY_TYPE_CAMELLIA */\n\n#if defined(PSA_WANT_KEY_TYPE_DES)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DES)\n#define PSA_HAVE_SOFT_KEY_TYPE_DES 1\n#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DES */\n#if defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \\\n    defined(PSA_HAVE_SOFT_BLOCK_MODE)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1\n#define MBEDTLS_DES_C\n#endif /*PSA_HAVE_SOFT_KEY_TYPE_DES || PSA_HAVE_SOFT_BLOCK_MODE */\n#endif /* PSA_WANT_KEY_TYPE_DES */\n\n#if defined(PSA_WANT_ALG_STREAM_CIPHER)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_STREAM_CIPHER)\n#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1\n#endif /* MBEDTLS_PSA_ACCEL_ALG_STREAM_CIPHER */\n#endif /* PSA_WANT_ALG_STREAM_CIPHER */\n\n#if defined(PSA_WANT_KEY_TYPE_CHACHA20)\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1\n#define MBEDTLS_CHACHA20_C\n#endif /*!MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20 */\n#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */\n\n/* If any of the software block ciphers are selected, define\n * PSA_HAVE_SOFT_BLOCK_CIPHER, which can be used in any of these\n * situations. */\n#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \\\n    defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \\\n    defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \\\n    defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA)\n#define PSA_HAVE_SOFT_BLOCK_CIPHER 1\n#endif\n\n#if defined(PSA_WANT_ALG_CMAC)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC) || \\\n    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)\n#define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1\n#define MBEDTLS_CMAC_C\n#endif /* !MBEDTLS_PSA_ACCEL_ALG_CMAC */\n#endif /* PSA_WANT_ALG_CMAC */\n\n#if defined(PSA_HAVE_SOFT_PBKDF2_HMAC) || \\\n    defined(PSA_HAVE_SOFT_PBKDF2_CMAC)\n#define PSA_HAVE_SOFT_PBKDF2 1\n#endif /* PSA_HAVE_SOFT_PBKDF2_HMAC || PSA_HAVE_SOFT_PBKDF2_CMAC */\n\n#if defined(PSA_WANT_ALG_CTR)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_CTR) || \\\n    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)\n#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1\n#define MBEDTLS_CIPHER_MODE_CTR\n#endif\n#endif /* PSA_WANT_ALG_CTR */\n\n#if defined(PSA_WANT_ALG_CFB)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_CFB) || \\\n    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)\n#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1\n#define MBEDTLS_CIPHER_MODE_CFB\n#endif\n#endif /* PSA_WANT_ALG_CFB */\n\n#if defined(PSA_WANT_ALG_OFB)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_OFB) || \\\n    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)\n#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1\n#define MBEDTLS_CIPHER_MODE_OFB\n#endif\n#endif /* PSA_WANT_ALG_OFB */\n\n#if defined(PSA_WANT_ALG_ECB_NO_PADDING) &&     \\\n    !defined(MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING)\n#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1\n#endif\n\n#if defined(PSA_WANT_ALG_CBC_NO_PADDING)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING) || \\\n    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)\n#define MBEDTLS_CIPHER_MODE_CBC\n#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1\n#endif\n#endif /* PSA_WANT_ALG_CBC_NO_PADDING */\n\n#if defined(PSA_WANT_ALG_CBC_PKCS7)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7) || \\\n    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)\n#define MBEDTLS_CIPHER_MODE_CBC\n#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1\n#define MBEDTLS_CIPHER_PADDING_PKCS7\n#endif\n#endif /* PSA_WANT_ALG_CBC_PKCS7 */\n\n#if defined(PSA_WANT_ALG_CCM)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_CCM) || \\\n    defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \\\n    defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \\\n    defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA)\n#define MBEDTLS_PSA_BUILTIN_ALG_CCM 1\n#define MBEDTLS_CCM_C\n#endif\n#endif /* PSA_WANT_ALG_CCM */\n\n#if defined(PSA_WANT_ALG_CCM_STAR_NO_TAG)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_CCM_STAR_NO_TAG) || \\\n    defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \\\n    defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \\\n    defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA)\n#define MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG 1\n#define MBEDTLS_CCM_C\n#endif\n#endif /* PSA_WANT_ALG_CCM_STAR_NO_TAG */\n\n#if defined(PSA_WANT_ALG_GCM)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_GCM) || \\\n    defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \\\n    defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \\\n    defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA)\n#define MBEDTLS_PSA_BUILTIN_ALG_GCM 1\n#define MBEDTLS_GCM_C\n#endif\n#endif /* PSA_WANT_ALG_GCM */\n\n#if defined(PSA_WANT_ALG_CHACHA20_POLY1305)\n#if !defined(MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305)\n#if defined(PSA_WANT_KEY_TYPE_CHACHA20)\n#define MBEDTLS_CHACHAPOLY_C\n#define MBEDTLS_CHACHA20_C\n#define MBEDTLS_POLY1305_C\n#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1\n#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */\n#endif /* !MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305 */\n#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */\n\n#endif /* MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/config_adjust_psa_from_legacy.h",
    "content": "/**\n * \\file mbedtls/config_adjust_psa_from_legacy.h\n * \\brief Adjust PSA configuration: construct PSA configuration from legacy\n *\n * This is an internal header. Do not include it directly.\n *\n * When MBEDTLS_PSA_CRYPTO_CONFIG is disabled, we automatically enable\n * cryptographic mechanisms through the PSA interface when the corresponding\n * legacy mechanism is enabled. In many cases, this just enables the PSA\n * wrapper code around the legacy implementation, but we also do this for\n * some mechanisms where PSA has its own independent implementation so\n * that high-level modules that can use either cryptographic API have the\n * same feature set in both cases.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H\n#define MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H\n\n#if !defined(MBEDTLS_CONFIG_FILES_READ)\n#error \"Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, \" \\\n    \"up to and including runtime errors such as buffer overflows. \" \\\n    \"If you're trying to fix a complaint from check_config.h, just remove \" \\\n    \"it from your configuration file: since Mbed TLS 3.0, it is included \" \\\n    \"automatically at the right point.\"\n#endif /* */\n\n/*\n * Ensure PSA_WANT_* defines are setup properly if MBEDTLS_PSA_CRYPTO_CONFIG\n * is not defined\n */\n\n#if defined(MBEDTLS_CCM_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_CCM 1\n#define PSA_WANT_ALG_CCM 1\n#if defined(MBEDTLS_CIPHER_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG 1\n#define PSA_WANT_ALG_CCM_STAR_NO_TAG 1\n#endif /* MBEDTLS_CIPHER_C */\n#endif /* MBEDTLS_CCM_C */\n\n#if defined(MBEDTLS_CMAC_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1\n#define PSA_WANT_ALG_CMAC 1\n#endif /* MBEDTLS_CMAC_C */\n\n#if defined(MBEDTLS_ECDH_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1\n#define PSA_WANT_ALG_ECDH 1\n#endif /* MBEDTLS_ECDH_C */\n\n#if defined(MBEDTLS_ECDSA_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1\n#define PSA_WANT_ALG_ECDSA 1\n#define PSA_WANT_ALG_ECDSA_ANY 1\n\n// Only add in DETERMINISTIC support if ECDSA is also enabled\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC)\n#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1\n#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1\n#endif /* MBEDTLS_ECDSA_DETERMINISTIC */\n\n#endif /* MBEDTLS_ECDSA_C */\n\n#if defined(MBEDTLS_ECP_C)\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1\n/* Normally we wouldn't enable this because it's not implemented in ecp.c,\n * but since it used to be available any time ECP_C was enabled, let's enable\n * it anyway for the sake of backwards compatibility */\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1\n/* See comment for PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE above. */\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1\n#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1\n#endif /* MBEDTLS_ECP_C */\n\n#if defined(MBEDTLS_DHM_C)\n#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1\n#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1\n#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1\n#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE 1\n#define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY 1\n#define PSA_WANT_ALG_FFDH 1\n#define PSA_WANT_DH_RFC7919_2048 1\n#define PSA_WANT_DH_RFC7919_3072 1\n#define PSA_WANT_DH_RFC7919_4096 1\n#define PSA_WANT_DH_RFC7919_6144 1\n#define PSA_WANT_DH_RFC7919_8192 1\n#define MBEDTLS_PSA_BUILTIN_ALG_FFDH 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_BASIC 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY 1\n#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 1\n#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 1\n#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 1\n#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 1\n#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 1\n#endif /* MBEDTLS_DHM_C */\n\n#if defined(MBEDTLS_GCM_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_GCM 1\n#define PSA_WANT_ALG_GCM 1\n#endif /* MBEDTLS_GCM_C */\n\n/* Enable PSA HKDF algorithm if mbedtls HKDF is supported.\n * PSA HKDF EXTRACT and PSA HKDF EXPAND have minimal cost when\n * PSA HKDF is enabled, so enable both algorithms together\n * with PSA HKDF. */\n#if defined(MBEDTLS_HKDF_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1\n#define PSA_WANT_ALG_HMAC 1\n#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1\n#define PSA_WANT_ALG_HKDF 1\n#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1\n#define PSA_WANT_ALG_HKDF_EXTRACT 1\n#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1\n#define PSA_WANT_ALG_HKDF_EXPAND 1\n#endif /* MBEDTLS_HKDF_C */\n\n#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1\n#define PSA_WANT_ALG_HMAC 1\n#define PSA_WANT_KEY_TYPE_HMAC 1\n\n#if defined(MBEDTLS_MD_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1\n#define PSA_WANT_ALG_TLS12_PRF 1\n#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1\n#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1\n#endif /* MBEDTLS_MD_C */\n\n#if defined(MBEDTLS_MD5_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1\n#define PSA_WANT_ALG_MD5 1\n#endif\n\n#if defined(MBEDTLS_ECJPAKE_C)\n#define MBEDTLS_PSA_BUILTIN_PAKE 1\n#define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1\n#define PSA_WANT_ALG_JPAKE 1\n#endif\n\n#if defined(MBEDTLS_RIPEMD160_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1\n#define PSA_WANT_ALG_RIPEMD160 1\n#endif\n\n#if defined(MBEDTLS_RSA_C)\n#if defined(MBEDTLS_PKCS1_V15)\n#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1\n#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1\n#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1\n#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1\n#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW 1\n#endif /* MBEDTLS_PKCS1_V15 */\n#if defined(MBEDTLS_PKCS1_V21)\n#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1\n#define PSA_WANT_ALG_RSA_OAEP 1\n#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1\n#define PSA_WANT_ALG_RSA_PSS 1\n#endif /* MBEDTLS_PKCS1_V21 */\n#if defined(MBEDTLS_GENPRIME)\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1\n#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1\n#endif /* MBEDTLS_GENPRIME */\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_BASIC 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1\n#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1\n#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1\n#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1\n#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1\n#endif /* MBEDTLS_RSA_C */\n\n#if defined(MBEDTLS_SHA1_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1\n#define PSA_WANT_ALG_SHA_1 1\n#endif\n\n#if defined(MBEDTLS_SHA224_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1\n#define PSA_WANT_ALG_SHA_224 1\n#endif\n\n#if defined(MBEDTLS_SHA256_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1\n#define PSA_WANT_ALG_SHA_256 1\n#endif\n\n#if defined(MBEDTLS_SHA384_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1\n#define PSA_WANT_ALG_SHA_384 1\n#endif\n\n#if defined(MBEDTLS_SHA512_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1\n#define PSA_WANT_ALG_SHA_512 1\n#endif\n\n#if defined(MBEDTLS_SHA3_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_224 1\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_256 1\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_384 1\n#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_512 1\n#define PSA_WANT_ALG_SHA3_224 1\n#define PSA_WANT_ALG_SHA3_256 1\n#define PSA_WANT_ALG_SHA3_384 1\n#define PSA_WANT_ALG_SHA3_512 1\n#endif\n\n#if defined(MBEDTLS_AES_C)\n#define PSA_WANT_KEY_TYPE_AES 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1\n#endif\n\n#if defined(MBEDTLS_ARIA_C)\n#define PSA_WANT_KEY_TYPE_ARIA 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1\n#endif\n\n#if defined(MBEDTLS_CAMELLIA_C)\n#define PSA_WANT_KEY_TYPE_CAMELLIA 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1\n#endif\n\n#if defined(MBEDTLS_DES_C)\n#define PSA_WANT_KEY_TYPE_DES 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1\n#endif\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)\n#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1\n#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1\n#endif\n\n#if defined(MBEDTLS_CHACHA20_C)\n#define PSA_WANT_KEY_TYPE_CHACHA20 1\n#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1\n/* ALG_STREAM_CIPHER requires CIPHER_C in order to be supported in PSA */\n#if defined(MBEDTLS_CIPHER_C)\n#define PSA_WANT_ALG_STREAM_CIPHER 1\n#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1\n#endif\n#if defined(MBEDTLS_CHACHAPOLY_C)\n#define PSA_WANT_ALG_CHACHA20_POLY1305 1\n#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1\n#endif\n#endif\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1\n#define PSA_WANT_ALG_CBC_NO_PADDING 1\n#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)\n#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1\n#define PSA_WANT_ALG_CBC_PKCS7 1\n#endif\n#endif\n\n#if (defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) || \\\n    defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C)) && \\\n    defined(MBEDTLS_CIPHER_C)\n#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1\n#define PSA_WANT_ALG_ECB_NO_PADDING 1\n#endif\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1\n#define PSA_WANT_ALG_CFB 1\n#endif\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1\n#define PSA_WANT_ALG_CTR 1\n#endif\n\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1\n#define PSA_WANT_ALG_OFB 1\n#endif\n\n#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)\n#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1\n#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1\n#endif\n\n#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)\n#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1\n#define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1\n#endif\n\n#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)\n#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1\n#define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1\n#endif\n\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1\n#define PSA_WANT_ECC_MONTGOMERY_255 1\n#endif\n\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1\n#define PSA_WANT_ECC_MONTGOMERY_448 1\n#endif\n\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\n#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1\n#define PSA_WANT_ECC_SECP_R1_192 1\n#endif\n\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)\n#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1\n#define PSA_WANT_ECC_SECP_R1_224 1\n#endif\n\n#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)\n#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1\n#define PSA_WANT_ECC_SECP_R1_256 1\n#endif\n\n#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\n#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1\n#define PSA_WANT_ECC_SECP_R1_384 1\n#endif\n\n#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)\n#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1\n#define PSA_WANT_ECC_SECP_R1_521 1\n#endif\n\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)\n#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1\n#define PSA_WANT_ECC_SECP_K1_192 1\n#endif\n\n/* SECP224K1 is buggy via the PSA API (https://github.com/Mbed-TLS/mbedtls/issues/3541) */\n#if 0 && defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)\n#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1\n#define PSA_WANT_ECC_SECP_K1_224 1\n#endif\n\n#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1\n#define PSA_WANT_ECC_SECP_K1_256 1\n#endif\n\n#endif /* MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/config_adjust_psa_superset_legacy.h",
    "content": "/**\n * \\file mbedtls/config_adjust_psa_superset_legacy.h\n * \\brief Adjust PSA configuration: automatic enablement from legacy\n *\n * This is an internal header. Do not include it directly.\n *\n * To simplify some edge cases, we automatically enable certain cryptographic\n * mechanisms in the PSA API if they are enabled in the legacy API. The general\n * idea is that if legacy module M uses mechanism A internally, and A has\n * both a legacy and a PSA implementation, we enable A through PSA whenever\n * it's enabled through legacy. This facilitates the transition to PSA\n * implementations of A for users of M.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H\n#define MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H\n\n#if !defined(MBEDTLS_CONFIG_FILES_READ)\n#error \"Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, \" \\\n    \"up to and including runtime errors such as buffer overflows. \" \\\n    \"If you're trying to fix a complaint from check_config.h, just remove \" \\\n    \"it from your configuration file: since Mbed TLS 3.0, it is included \" \\\n    \"automatically at the right point.\"\n#endif /* */\n\n/****************************************************************/\n/* Hashes that are built in are also enabled in PSA.\n * This simplifies dependency declarations especially\n * for modules that obey MBEDTLS_USE_PSA_CRYPTO. */\n/****************************************************************/\n\n#if defined(MBEDTLS_MD5_C)\n#define PSA_WANT_ALG_MD5 1\n#endif\n\n#if defined(MBEDTLS_RIPEMD160_C)\n#define PSA_WANT_ALG_RIPEMD160 1\n#endif\n\n#if defined(MBEDTLS_SHA1_C)\n#define PSA_WANT_ALG_SHA_1 1\n#endif\n\n#if defined(MBEDTLS_SHA224_C)\n#define PSA_WANT_ALG_SHA_224 1\n#endif\n\n#if defined(MBEDTLS_SHA256_C)\n#define PSA_WANT_ALG_SHA_256 1\n#endif\n\n#if defined(MBEDTLS_SHA384_C)\n#define PSA_WANT_ALG_SHA_384 1\n#endif\n\n#if defined(MBEDTLS_SHA512_C)\n#define PSA_WANT_ALG_SHA_512 1\n#endif\n\n#if defined(MBEDTLS_SHA3_C)\n#define PSA_WANT_ALG_SHA3_224 1\n#define PSA_WANT_ALG_SHA3_256 1\n#define PSA_WANT_ALG_SHA3_384 1\n#define PSA_WANT_ALG_SHA3_512 1\n#endif\n\n/* Ensure that the PSA's supported curves (PSA_WANT_ECC_xxx) are always a\n * superset of the builtin ones (MBEDTLS_ECP_DP_xxx). */\n#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)\n#if !defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)\n#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1\n#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_256 */\n#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)\n#if !defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)\n#define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1\n#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_384 */\n#endif /*MBEDTLS_ECP_DP_BP384R1_ENABLED  */\n\n#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)\n#if !defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)\n#define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1\n#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_512 */\n#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n#if !defined(PSA_WANT_ECC_MONTGOMERY_255)\n#define PSA_WANT_ECC_MONTGOMERY_255 1\n#endif /* PSA_WANT_ECC_MONTGOMERY_255 */\n#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n#if !defined(PSA_WANT_ECC_MONTGOMERY_448)\n#define PSA_WANT_ECC_MONTGOMERY_448 1\n#endif /* PSA_WANT_ECC_MONTGOMERY_448 */\n#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\n#if !defined(PSA_WANT_ECC_SECP_R1_192)\n#define PSA_WANT_ECC_SECP_R1_192 1\n#endif /* PSA_WANT_ECC_SECP_R1_192 */\n#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)\n#if !defined(PSA_WANT_ECC_SECP_R1_224)\n#define PSA_WANT_ECC_SECP_R1_224 1\n#endif /* PSA_WANT_ECC_SECP_R1_224 */\n#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)\n#if !defined(PSA_WANT_ECC_SECP_R1_256)\n#define PSA_WANT_ECC_SECP_R1_256 1\n#endif /* PSA_WANT_ECC_SECP_R1_256 */\n#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\n#if !defined(PSA_WANT_ECC_SECP_R1_384)\n#define PSA_WANT_ECC_SECP_R1_384 1\n#endif /* PSA_WANT_ECC_SECP_R1_384 */\n#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)\n#if !defined(PSA_WANT_ECC_SECP_R1_521)\n#define PSA_WANT_ECC_SECP_R1_521 1\n#endif /* PSA_WANT_ECC_SECP_R1_521 */\n#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)\n#if !defined(PSA_WANT_ECC_SECP_K1_192)\n#define PSA_WANT_ECC_SECP_K1_192 1\n#endif /* PSA_WANT_ECC_SECP_K1_192 */\n#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n#if !defined(PSA_WANT_ECC_SECP_K1_256)\n#define PSA_WANT_ECC_SECP_K1_256 1\n#endif /* PSA_WANT_ECC_SECP_K1_256 */\n#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */\n\n#endif /* MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/config_adjust_ssl.h",
    "content": "/**\n * \\file mbedtls/config_adjust_ssl.h\n * \\brief Adjust TLS configuration\n *\n * This is an internal header. Do not include it directly.\n *\n * Automatically enable certain dependencies. Generally, MBEDTLS_xxx\n * configurations need to be explicitly enabled by the user: enabling\n * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a\n * compilation error. However, we do automatically enable certain options\n * in some circumstances. One case is if MBEDTLS_xxx_B is an internal option\n * used to identify parts of a module that are used by other module, and we\n * don't want to make the symbol MBEDTLS_xxx_B part of the public API.\n * Another case is if A didn't depend on B in earlier versions, and we\n * want to use B in A but we need to preserve backward compatibility with\n * configurations that explicitly activate MBEDTLS_xxx_A but not\n * MBEDTLS_xxx_B.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CONFIG_ADJUST_SSL_H\n#define MBEDTLS_CONFIG_ADJUST_SSL_H\n\n#if !defined(MBEDTLS_CONFIG_FILES_READ)\n#error \"Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, \" \\\n    \"up to and including runtime errors such as buffer overflows. \" \\\n    \"If you're trying to fix a complaint from check_config.h, just remove \" \\\n    \"it from your configuration file: since Mbed TLS 3.0, it is included \" \\\n    \"automatically at the right point.\"\n#endif /* */\n\n/* The following blocks make it easier to disable all of TLS,\n * or of TLS 1.2 or 1.3 or DTLS, without having to manually disable all\n * key exchanges, options and extensions related to them. */\n\n#if !defined(MBEDTLS_SSL_TLS_C)\n#undef MBEDTLS_SSL_CLI_C\n#undef MBEDTLS_SSL_SRV_C\n#undef MBEDTLS_SSL_PROTO_TLS1_3\n#undef MBEDTLS_SSL_PROTO_TLS1_2\n#undef MBEDTLS_SSL_PROTO_DTLS\n#endif\n\n#if !(defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS))\n#undef MBEDTLS_SSL_TICKET_C\n#endif\n\n#if !defined(MBEDTLS_SSL_PROTO_DTLS)\n#undef MBEDTLS_SSL_DTLS_ANTI_REPLAY\n#undef MBEDTLS_SSL_DTLS_CONNECTION_ID\n#undef MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT\n#undef MBEDTLS_SSL_DTLS_HELLO_VERIFY\n#undef MBEDTLS_SSL_DTLS_SRTP\n#undef MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE\n#endif\n\n#if !defined(MBEDTLS_SSL_PROTO_TLS1_2)\n#undef MBEDTLS_SSL_ENCRYPT_THEN_MAC\n#undef MBEDTLS_SSL_EXTENDED_MASTER_SECRET\n#undef MBEDTLS_SSL_RENEGOTIATION\n#undef MBEDTLS_KEY_EXCHANGE_RSA_ENABLED\n#undef MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED\n#undef MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED\n#undef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED\n#undef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED\n#undef MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED\n#undef MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED\n#undef MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED\n#undef MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED\n#undef MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED\n#undef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED\n#endif\n\n#if !defined(MBEDTLS_SSL_PROTO_TLS1_3)\n#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED\n#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED\n#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED\n#undef MBEDTLS_SSL_EARLY_DATA\n#undef MBEDTLS_SSL_RECORD_SIZE_LIMIT\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \\\n    (defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED))\n#define MBEDTLS_SSL_TLS1_2_SOME_ECC\n#endif\n\n#endif /* MBEDTLS_CONFIG_ADJUST_SSL_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/config_adjust_x509.h",
    "content": "/**\n * \\file mbedtls/config_adjust_x509.h\n * \\brief Adjust X.509 configuration\n *\n * This is an internal header. Do not include it directly.\n *\n * Automatically enable certain dependencies. Generally, MBEDTLS_xxx\n * configurations need to be explicitly enabled by the user: enabling\n * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a\n * compilation error. However, we do automatically enable certain options\n * in some circumstances. One case is if MBEDTLS_xxx_B is an internal option\n * used to identify parts of a module that are used by other module, and we\n * don't want to make the symbol MBEDTLS_xxx_B part of the public API.\n * Another case is if A didn't depend on B in earlier versions, and we\n * want to use B in A but we need to preserve backward compatibility with\n * configurations that explicitly activate MBEDTLS_xxx_A but not\n * MBEDTLS_xxx_B.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CONFIG_ADJUST_X509_H\n#define MBEDTLS_CONFIG_ADJUST_X509_H\n\n#if !defined(MBEDTLS_CONFIG_FILES_READ)\n#error \"Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, \" \\\n    \"up to and including runtime errors such as buffer overflows. \" \\\n    \"If you're trying to fix a complaint from check_config.h, just remove \" \\\n    \"it from your configuration file: since Mbed TLS 3.0, it is included \" \\\n    \"automatically at the right point.\"\n#endif /* */\n\n#endif /* MBEDTLS_CONFIG_ADJUST_X509_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/config_psa.h",
    "content": "/**\n * \\file mbedtls/config_psa.h\n * \\brief PSA crypto configuration options (set of defines)\n *\n *  This set of compile-time options takes settings defined in\n *  include/mbedtls/mbedtls_config.h and include/psa/crypto_config.h and uses\n *  those definitions to define symbols used in the library code.\n *\n *  Users and integrators should not edit this file, please edit\n *  include/mbedtls/mbedtls_config.h for MBEDTLS_XXX settings or\n *  include/psa/crypto_config.h for PSA_WANT_XXX settings.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CONFIG_PSA_H\n#define MBEDTLS_CONFIG_PSA_H\n\n#include \"psa/crypto_legacy.h\"\n\n#include \"psa/crypto_adjust_config_synonyms.h\"\n\n#include \"psa/crypto_adjust_config_dependencies.h\"\n\n#include \"mbedtls/config_adjust_psa_superset_legacy.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)\n\n/* Require built-in implementations based on PSA requirements */\n\n/* We need this to have a complete list of requirements\n * before we deduce what built-ins are required. */\n#include \"psa/crypto_adjust_config_key_pair_types.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n/* If we are implementing PSA crypto ourselves, then we want to enable the\n * required built-ins. Otherwise, PSA features will be provided by the server. */\n#include \"mbedtls/config_adjust_legacy_from_psa.h\"\n#endif\n\n#else /* MBEDTLS_PSA_CRYPTO_CONFIG */\n\n/* Infer PSA requirements from Mbed TLS capabilities */\n\n#include \"mbedtls/config_adjust_psa_from_legacy.h\"\n\n/* Hopefully the file above will have enabled keypair symbols in a consistent\n * way, but including this here fixes them if that wasn't the case. */\n#include \"psa/crypto_adjust_config_key_pair_types.h\"\n\n#endif /* MBEDTLS_PSA_CRYPTO_CONFIG */\n\n#if defined(PSA_WANT_ALG_JPAKE)\n#define PSA_WANT_ALG_SOME_PAKE 1\n#endif\n\n#include \"psa/crypto_adjust_auto_enabled.h\"\n\n#endif /* MBEDTLS_CONFIG_PSA_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/constant_time.h",
    "content": "/**\n *  Constant-time functions\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CONSTANT_TIME_H\n#define MBEDTLS_CONSTANT_TIME_H\n\n#include <stddef.h>\n\n/** Constant-time buffer comparison without branches.\n *\n * This is equivalent to the standard memcmp function, but is likely to be\n * compiled to code using bitwise operations rather than a branch, such that\n * the time taken is constant w.r.t. the data pointed to by \\p a and \\p b,\n * and w.r.t. whether \\p a and \\p b are equal or not. It is not constant-time\n * w.r.t. \\p n .\n *\n * This function can be used to write constant-time code by replacing branches\n * with bit operations using masks.\n *\n * \\param a     Pointer to the first buffer, containing at least \\p n bytes. May not be NULL.\n * \\param b     Pointer to the second buffer, containing at least \\p n bytes. May not be NULL.\n * \\param n     The number of bytes to compare.\n *\n * \\return      Zero if the contents of the two buffers are the same,\n *              otherwise non-zero.\n */\nint mbedtls_ct_memcmp(const void *a,\n                      const void *b,\n                      size_t n);\n\n#endif /* MBEDTLS_CONSTANT_TIME_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/ctr_drbg.h",
    "content": "/**\n * \\file ctr_drbg.h\n *\n * \\brief    This file contains definitions and functions for the\n *           CTR_DRBG pseudorandom generator.\n *\n * CTR_DRBG is a standardized way of building a PRNG from a block-cipher\n * in counter mode operation, as defined in <em>NIST SP 800-90A:\n * Recommendation for Random Number Generation Using Deterministic Random\n * Bit Generators</em>.\n *\n * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128\n * (if \\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time)\n * as the underlying block cipher, with a derivation function.\n *\n * The security strength as defined in NIST SP 800-90A is\n * 128 bits when AES-128 is used (\\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled)\n * and 256 bits otherwise, provided that #MBEDTLS_CTR_DRBG_ENTROPY_LEN is\n * kept at its default value (and not overridden in mbedtls_config.h) and that the\n * DRBG instance is set up with default parameters.\n * See the documentation of mbedtls_ctr_drbg_seed() for more\n * information.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CTR_DRBG_H\n#define MBEDTLS_CTR_DRBG_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n/* The CTR_DRBG implementation can either directly call the low-level AES\n * module (gated by MBEDTLS_AES_C) or call the PSA API to perform AES\n * operations. Calling the AES module directly is the default, both for\n * maximum backward compatibility and because it's a bit more efficient\n * (less glue code).\n *\n * When MBEDTLS_AES_C is disabled, the CTR_DRBG module calls PSA crypto and\n * thus benefits from the PSA AES accelerator driver.\n * It is technically possible to enable MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO\n * to use PSA even when MBEDTLS_AES_C is enabled, but there is very little\n * reason to do so other than testing purposes and this is not officially\n * supported.\n */\n#if !defined(MBEDTLS_AES_C)\n#define MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO\n#endif\n\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n#include \"psa/crypto.h\"\n#else\n#include \"mbedtls/aes.h\"\n#endif\n\n#include \"entropy.h\"\n\n#if defined(MBEDTLS_THREADING_C)\n#include \"mbedtls/threading.h\"\n#endif\n\n/** The entropy source failed. */\n#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED        -0x0034\n/** The requested random buffer length is too big. */\n#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG              -0x0036\n/** The input (entropy + additional data) is too large. */\n#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG                -0x0038\n/** Read or write error in file. */\n#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR                -0x003A\n\n#define MBEDTLS_CTR_DRBG_BLOCKSIZE          16 /**< The block size used by the cipher. */\n\n#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)\n#define MBEDTLS_CTR_DRBG_KEYSIZE            16\n/**< The key size in bytes used by the cipher.\n *\n * Compile-time choice: 16 bytes (128 bits)\n * because #MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled.\n */\n#else\n#define MBEDTLS_CTR_DRBG_KEYSIZE            32\n/**< The key size in bytes used by the cipher.\n *\n * Compile-time choice: 32 bytes (256 bits)\n * because \\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled.\n */\n#endif\n\n#define MBEDTLS_CTR_DRBG_KEYBITS            (MBEDTLS_CTR_DRBG_KEYSIZE * 8)   /**< The key size for the DRBG operation, in bits. */\n#define MBEDTLS_CTR_DRBG_SEEDLEN            (MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE)   /**< The seed length, calculated as (counter + AES key). */\n\n/**\n * \\name SECTION: Module settings\n *\n * The configuration options you can set for this module are in this section.\n * Either change them in mbedtls_config.h or define them using the compiler command\n * line.\n * \\{\n */\n\n/** \\def MBEDTLS_CTR_DRBG_ENTROPY_LEN\n *\n * \\brief The amount of entropy used per seed by default, in bytes.\n */\n#if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN)\n#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)\n/** This is 48 bytes because the entropy module uses SHA-512.\n */\n#define MBEDTLS_CTR_DRBG_ENTROPY_LEN        48\n\n#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */\n\n/** This is 32 bytes because the entropy module uses SHA-256.\n */\n#if !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)\n/** \\warning To achieve a 256-bit security strength, you must pass a nonce\n *           to mbedtls_ctr_drbg_seed().\n */\n#endif /* !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) */\n#define MBEDTLS_CTR_DRBG_ENTROPY_LEN        32\n#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */\n#endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */\n\n#if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL)\n#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL    10000\n/**< The interval before reseed is performed by default. */\n#endif\n\n#if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT)\n#define MBEDTLS_CTR_DRBG_MAX_INPUT          256\n/**< The maximum number of additional input Bytes. */\n#endif\n\n#if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST)\n#define MBEDTLS_CTR_DRBG_MAX_REQUEST        1024\n/**< The maximum number of requested Bytes per call. */\n#endif\n\n#if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT)\n#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT     384\n/**< The maximum size of seed or reseed buffer in bytes. */\n#endif\n\n/** \\} name SECTION: Module settings */\n\n#define MBEDTLS_CTR_DRBG_PR_OFF             0\n/**< Prediction resistance is disabled. */\n#define MBEDTLS_CTR_DRBG_PR_ON              1\n/**< Prediction resistance is enabled. */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2\n/** The default length of the nonce read from the entropy source.\n *\n * This is \\c 0 because a single read from the entropy source is sufficient\n * to include a nonce.\n * See the documentation of mbedtls_ctr_drbg_seed() for more information.\n */\n#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN 0\n#else\n/** The default length of the nonce read from the entropy source.\n *\n * This is half of the default entropy length because a single read from\n * the entropy source does not provide enough material to form a nonce.\n * See the documentation of mbedtls_ctr_drbg_seed() for more information.\n */\n#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN (MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1) / 2\n#endif\n\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\ntypedef struct mbedtls_ctr_drbg_psa_context {\n    mbedtls_svc_key_id_t key_id;\n    psa_cipher_operation_t operation;\n} mbedtls_ctr_drbg_psa_context;\n#endif\n\n/**\n * \\brief          The CTR_DRBG context structure.\n */\ntypedef struct mbedtls_ctr_drbg_context {\n    unsigned char MBEDTLS_PRIVATE(counter)[16];  /*!< The counter (V). */\n    int MBEDTLS_PRIVATE(reseed_counter);         /*!< The reseed counter.\n                                                  * This is the number of requests that have\n                                                  * been made since the last (re)seeding,\n                                                  * minus one.\n                                                  * Before the initial seeding, this field\n                                                  * contains the amount of entropy in bytes\n                                                  * to use as a nonce for the initial seeding,\n                                                  * or -1 if no nonce length has been explicitly\n                                                  * set (see mbedtls_ctr_drbg_set_nonce_len()).\n                                                  */\n    int MBEDTLS_PRIVATE(prediction_resistance);  /*!< This determines whether prediction\n                                                    resistance is enabled, that is\n                                                    whether to systematically reseed before\n                                                    each random generation. */\n    size_t MBEDTLS_PRIVATE(entropy_len);         /*!< The amount of entropy grabbed on each\n                                                    seed or reseed operation, in bytes. */\n    int MBEDTLS_PRIVATE(reseed_interval);        /*!< The reseed interval.\n                                                  * This is the maximum number of requests\n                                                  * that can be made between reseedings. */\n\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n    mbedtls_ctr_drbg_psa_context MBEDTLS_PRIVATE(psa_ctx); /*!< The PSA context. */\n#else\n    mbedtls_aes_context MBEDTLS_PRIVATE(aes_ctx);        /*!< The AES context. */\n#endif\n\n    /*\n     * Callbacks (Entropy)\n     */\n    int(*MBEDTLS_PRIVATE(f_entropy))(void *, unsigned char *, size_t);\n    /*!< The entropy callback function. */\n\n    void *MBEDTLS_PRIVATE(p_entropy);            /*!< The context for the entropy function. */\n\n#if defined(MBEDTLS_THREADING_C)\n    /* Invariant: the mutex is initialized if and only if f_entropy != NULL.\n     * This means that the mutex is initialized during the initial seeding\n     * in mbedtls_ctr_drbg_seed() and freed in mbedtls_ctr_drbg_free().\n     *\n     * Note that this invariant may change without notice. Do not rely on it\n     * and do not access the mutex directly in application code.\n     */\n    mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex);\n#endif\n}\nmbedtls_ctr_drbg_context;\n\n/**\n * \\brief               This function initializes the CTR_DRBG context,\n *                      and prepares it for mbedtls_ctr_drbg_seed()\n *                      or mbedtls_ctr_drbg_free().\n *\n * \\note                The reseed interval is\n *                      #MBEDTLS_CTR_DRBG_RESEED_INTERVAL by default.\n *                      You can override it by calling\n *                      mbedtls_ctr_drbg_set_reseed_interval().\n *\n * \\param ctx           The CTR_DRBG context to initialize.\n */\nvoid mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx);\n\n/**\n * \\brief               This function seeds and sets up the CTR_DRBG\n *                      entropy source for future reseeds.\n *\n * A typical choice for the \\p f_entropy and \\p p_entropy parameters is\n * to use the entropy module:\n * - \\p f_entropy is mbedtls_entropy_func();\n * - \\p p_entropy is an instance of ::mbedtls_entropy_context initialized\n *   with mbedtls_entropy_init() (which registers the platform's default\n *   entropy sources).\n *\n * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default.\n * You can override it by calling mbedtls_ctr_drbg_set_entropy_len().\n *\n * The entropy nonce length is:\n * - \\c 0 if the entropy length is at least 3/2 times the entropy length,\n *   which guarantees that the security strength is the maximum permitted\n *   by the key size and entropy length according to NIST SP 800-90A §10.2.1;\n * - Half the entropy length otherwise.\n * You can override it by calling mbedtls_ctr_drbg_set_nonce_len().\n * With the default entropy length, the entropy nonce length is\n * #MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN.\n *\n * You can provide a nonce and personalization string in addition to the\n * entropy source, to make this instantiation as unique as possible.\n * See SP 800-90A §8.6.7 for more details about nonces.\n *\n * The _seed_material_ value passed to the derivation function in\n * the CTR_DRBG Instantiate Process described in NIST SP 800-90A §10.2.1.3.2\n * is the concatenation of the following strings:\n * - A string obtained by calling \\p f_entropy function for the entropy\n *   length.\n */\n#if MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN == 0\n/**\n * - If mbedtls_ctr_drbg_set_nonce_len() has been called, a string\n *   obtained by calling \\p f_entropy function for the specified length.\n */\n#else\n/**\n * - A string obtained by calling \\p f_entropy function for the entropy nonce\n *   length. If the entropy nonce length is \\c 0, this function does not\n *   make a second call to \\p f_entropy.\n */\n#endif\n#if defined(MBEDTLS_THREADING_C)\n/**\n * \\note                When Mbed TLS is built with threading support,\n *                      after this function returns successfully,\n *                      it is safe to call mbedtls_ctr_drbg_random()\n *                      from multiple threads. Other operations, including\n *                      reseeding, are not thread-safe.\n */\n#endif /* MBEDTLS_THREADING_C */\n/**\n * - The \\p custom string.\n *\n * \\note                To achieve the nominal security strength permitted\n *                      by CTR_DRBG, the entropy length must be:\n *                      - at least 16 bytes for a 128-bit strength\n *                      (maximum achievable strength when using AES-128);\n *                      - at least 32 bytes for a 256-bit strength\n *                      (maximum achievable strength when using AES-256).\n *\n *                      In addition, if you do not pass a nonce in \\p custom,\n *                      the sum of the entropy length\n *                      and the entropy nonce length must be:\n *                      - at least 24 bytes for a 128-bit strength\n *                      (maximum achievable strength when using AES-128);\n *                      - at least 48 bytes for a 256-bit strength\n *                      (maximum achievable strength when using AES-256).\n *\n * \\param ctx           The CTR_DRBG context to seed.\n *                      It must have been initialized with\n *                      mbedtls_ctr_drbg_init().\n *                      After a successful call to mbedtls_ctr_drbg_seed(),\n *                      you may not call mbedtls_ctr_drbg_seed() again on\n *                      the same context unless you call\n *                      mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init()\n *                      again first.\n *                      After a failed call to mbedtls_ctr_drbg_seed(),\n *                      you must call mbedtls_ctr_drbg_free().\n * \\param f_entropy     The entropy callback, taking as arguments the\n *                      \\p p_entropy context, the buffer to fill, and the\n *                      length of the buffer.\n *                      \\p f_entropy is always called with a buffer size\n *                      less than or equal to the entropy length.\n * \\param p_entropy     The entropy context to pass to \\p f_entropy.\n * \\param custom        The personalization string.\n *                      This can be \\c NULL, in which case the personalization\n *                      string is empty regardless of the value of \\p len.\n * \\param len           The length of the personalization string.\n *                      This must be at most\n *                      #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT\n *                      - #MBEDTLS_CTR_DRBG_ENTROPY_LEN.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure.\n */\nint mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,\n                          int (*f_entropy)(void *, unsigned char *, size_t),\n                          void *p_entropy,\n                          const unsigned char *custom,\n                          size_t len);\n\n/**\n * \\brief               This function resets CTR_DRBG context to the state immediately\n *                      after initial call of mbedtls_ctr_drbg_init().\n *\n * \\param ctx           The CTR_DRBG context to clear.\n */\nvoid mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx);\n\n/**\n * \\brief               This function turns prediction resistance on or off.\n *                      The default value is off.\n *\n * \\note                If enabled, entropy is gathered at the beginning of\n *                      every call to mbedtls_ctr_drbg_random_with_add()\n *                      or mbedtls_ctr_drbg_random().\n *                      Only use this if your entropy source has sufficient\n *                      throughput.\n *\n * \\param ctx           The CTR_DRBG context.\n * \\param resistance    #MBEDTLS_CTR_DRBG_PR_ON or #MBEDTLS_CTR_DRBG_PR_OFF.\n */\nvoid mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,\n                                                int resistance);\n\n/**\n * \\brief               This function sets the amount of entropy grabbed on each\n *                      seed or reseed.\n *\n * The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN.\n *\n * \\note                The security strength of CTR_DRBG is bounded by the\n *                      entropy length. Thus:\n *                      - When using AES-256\n *                        (\\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled,\n *                        which is the default),\n *                        \\p len must be at least 32 (in bytes)\n *                        to achieve a 256-bit strength.\n *                      - When using AES-128\n *                        (\\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled)\n *                        \\p len must be at least 16 (in bytes)\n *                        to achieve a 128-bit strength.\n *\n * \\param ctx           The CTR_DRBG context.\n * \\param len           The amount of entropy to grab, in bytes.\n *                      This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT\n *                      and at most the maximum length accepted by the\n *                      entropy function that is set in the context.\n */\nvoid mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx,\n                                      size_t len);\n\n/**\n * \\brief               This function sets the amount of entropy grabbed\n *                      as a nonce for the initial seeding.\n *\n * Call this function before calling mbedtls_ctr_drbg_seed() to read\n * a nonce from the entropy source during the initial seeding.\n *\n * \\param ctx           The CTR_DRBG context.\n * \\param len           The amount of entropy to grab for the nonce, in bytes.\n *                      This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT\n *                      and at most the maximum length accepted by the\n *                      entropy function that is set in the context.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if \\p len is\n *                      more than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.\n * \\return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED\n *                      if the initial seeding has already taken place.\n */\nint mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx,\n                                   size_t len);\n\n/**\n * \\brief               This function sets the reseed interval.\n *\n * The reseed interval is the number of calls to mbedtls_ctr_drbg_random()\n * or mbedtls_ctr_drbg_random_with_add() after which the entropy function\n * is called again.\n *\n * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL.\n *\n * \\param ctx           The CTR_DRBG context.\n * \\param interval      The reseed interval.\n */\nvoid mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx,\n                                          int interval);\n\n/**\n * \\brief               This function reseeds the CTR_DRBG context, that is\n *                      extracts data from the entropy source.\n *\n * \\note                This function is not thread-safe. It is not safe\n *                      to call this function if another thread might be\n *                      concurrently obtaining random numbers from the same\n *                      context or updating or reseeding the same context.\n *\n * \\param ctx           The CTR_DRBG context.\n * \\param additional    Additional data to add to the state. Can be \\c NULL.\n * \\param len           The length of the additional data.\n *                      This must be less than\n *                      #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \\c entropy_len\n *                      where \\c entropy_len is the entropy length\n *                      configured for the context.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure.\n */\nint mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,\n                            const unsigned char *additional, size_t len);\n\n/**\n * \\brief              This function updates the state of the CTR_DRBG context.\n *\n * \\note                This function is not thread-safe. It is not safe\n *                      to call this function if another thread might be\n *                      concurrently obtaining random numbers from the same\n *                      context or updating or reseeding the same context.\n *\n * \\param ctx          The CTR_DRBG context.\n * \\param additional   The data to update the state with. This must not be\n *                     \\c NULL unless \\p add_len is \\c 0.\n * \\param add_len      Length of \\p additional in bytes. This must be at\n *                     most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.\n *\n * \\return             \\c 0 on success.\n * \\return             #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if\n *                     \\p add_len is more than\n *                     #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.\n * \\return             An error from the underlying AES cipher on failure.\n */\nint mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,\n                            const unsigned char *additional,\n                            size_t add_len);\n\n/**\n * \\brief   This function updates a CTR_DRBG instance with additional\n *          data and uses it to generate random data.\n *\n * This function automatically reseeds if the reseed counter is exceeded\n * or prediction resistance is enabled.\n *\n * \\note                This function is not thread-safe. It is not safe\n *                      to call this function if another thread might be\n *                      concurrently obtaining random numbers from the same\n *                      context or updating or reseeding the same context.\n *\n * \\param p_rng         The CTR_DRBG context. This must be a pointer to a\n *                      #mbedtls_ctr_drbg_context structure.\n * \\param output        The buffer to fill.\n * \\param output_len    The length of the buffer in bytes.\n * \\param additional    Additional data to update. Can be \\c NULL, in which\n *                      case the additional data is empty regardless of\n *                      the value of \\p add_len.\n * \\param add_len       The length of the additional data\n *                      if \\p additional is not \\c NULL.\n *                      This must be less than #MBEDTLS_CTR_DRBG_MAX_INPUT\n *                      and less than\n *                      #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \\c entropy_len\n *                      where \\c entropy_len is the entropy length\n *                      configured for the context.\n *\n * \\return    \\c 0 on success.\n * \\return    #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or\n *            #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure.\n */\nint mbedtls_ctr_drbg_random_with_add(void *p_rng,\n                                     unsigned char *output, size_t output_len,\n                                     const unsigned char *additional, size_t add_len);\n\n/**\n * \\brief   This function uses CTR_DRBG to generate random data.\n *\n * This function automatically reseeds if the reseed counter is exceeded\n * or prediction resistance is enabled.\n */\n#if defined(MBEDTLS_THREADING_C)\n/**\n * \\note                When Mbed TLS is built with threading support,\n *                      it is safe to call mbedtls_ctr_drbg_random()\n *                      from multiple threads. Other operations, including\n *                      reseeding, are not thread-safe.\n */\n#endif /* MBEDTLS_THREADING_C */\n/**\n * \\param p_rng         The CTR_DRBG context. This must be a pointer to a\n *                      #mbedtls_ctr_drbg_context structure.\n * \\param output        The buffer to fill.\n * \\param output_len    The length of the buffer in bytes.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or\n *                      #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure.\n */\nint mbedtls_ctr_drbg_random(void *p_rng,\n                            unsigned char *output, size_t output_len);\n\n#if defined(MBEDTLS_FS_IO)\n/**\n * \\brief               This function writes a seed file.\n *\n * \\param ctx           The CTR_DRBG context.\n * \\param path          The name of the file.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error.\n * \\return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on reseed\n *                      failure.\n */\nint mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx, const char *path);\n\n/**\n * \\brief               This function reads and updates a seed file. The seed\n *                      is added to this instance.\n *\n * \\param ctx           The CTR_DRBG context.\n * \\param path          The name of the file.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error.\n * \\return              #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on\n *                      reseed failure.\n * \\return              #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if the existing\n *                      seed file is too large.\n */\nint mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx, const char *path);\n#endif /* MBEDTLS_FS_IO */\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/**\n * \\brief               The CTR_DRBG checkup routine.\n *\n * \\return              \\c 0 on success.\n * \\return              \\c 1 on failure.\n */\nint mbedtls_ctr_drbg_self_test(int verbose);\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* ctr_drbg.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/debug.h",
    "content": "/**\n * \\file debug.h\n *\n * \\brief Functions for controlling and providing debug output from the library.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_DEBUG_H\n#define MBEDTLS_DEBUG_H\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/ssl.h\"\n\n#if defined(MBEDTLS_ECP_C)\n#include \"mbedtls/ecp.h\"\n#endif\n\n#if defined(MBEDTLS_DEBUG_C)\n\n#define MBEDTLS_DEBUG_STRIP_PARENS(...)   __VA_ARGS__\n\n#define MBEDTLS_SSL_DEBUG_MSG(level, args)                    \\\n    mbedtls_debug_print_msg(ssl, level, __FILE__, __LINE__,    \\\n                            MBEDTLS_DEBUG_STRIP_PARENS args)\n\n#define MBEDTLS_SSL_DEBUG_RET(level, text, ret)                \\\n    mbedtls_debug_print_ret(ssl, level, __FILE__, __LINE__, text, ret)\n\n#define MBEDTLS_SSL_DEBUG_BUF(level, text, buf, len)           \\\n    mbedtls_debug_print_buf(ssl, level, __FILE__, __LINE__, text, buf, len)\n\n#if defined(MBEDTLS_BIGNUM_C)\n#define MBEDTLS_SSL_DEBUG_MPI(level, text, X)                  \\\n    mbedtls_debug_print_mpi(ssl, level, __FILE__, __LINE__, text, X)\n#endif\n\n#if defined(MBEDTLS_ECP_C)\n#define MBEDTLS_SSL_DEBUG_ECP(level, text, X)                  \\\n    mbedtls_debug_print_ecp(ssl, level, __FILE__, __LINE__, text, X)\n#endif\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\n#define MBEDTLS_SSL_DEBUG_CRT(level, text, crt)                \\\n    mbedtls_debug_print_crt(ssl, level, __FILE__, __LINE__, text, crt)\n#else\n#define MBEDTLS_SSL_DEBUG_CRT(level, text, crt)       do { } while (0)\n#endif /* MBEDTLS_X509_REMOVE_INFO */\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n#if defined(MBEDTLS_ECDH_C)\n#define MBEDTLS_SSL_DEBUG_ECDH(level, ecdh, attr)               \\\n    mbedtls_debug_printf_ecdh(ssl, level, __FILE__, __LINE__, ecdh, attr)\n#endif\n\n#else /* MBEDTLS_DEBUG_C */\n\n#define MBEDTLS_SSL_DEBUG_MSG(level, args)            do { } while (0)\n#define MBEDTLS_SSL_DEBUG_RET(level, text, ret)       do { } while (0)\n#define MBEDTLS_SSL_DEBUG_BUF(level, text, buf, len)  do { } while (0)\n#define MBEDTLS_SSL_DEBUG_MPI(level, text, X)         do { } while (0)\n#define MBEDTLS_SSL_DEBUG_ECP(level, text, X)         do { } while (0)\n#define MBEDTLS_SSL_DEBUG_CRT(level, text, crt)       do { } while (0)\n#define MBEDTLS_SSL_DEBUG_ECDH(level, ecdh, attr)     do { } while (0)\n\n#endif /* MBEDTLS_DEBUG_C */\n\n/**\n * \\def MBEDTLS_PRINTF_ATTRIBUTE\n *\n * Mark a function as having printf attributes, and thus enable checking\n * via -wFormat and other flags. This does nothing on builds with compilers\n * that do not support the format attribute\n *\n * Module:  library/debug.c\n * Caller:\n *\n * This module provides debugging functions.\n */\n#if defined(__has_attribute)\n#if __has_attribute(format)\n#if defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 1\n#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check)    \\\n    __attribute__((__format__(gnu_printf, string_index, first_to_check)))\n#else /* defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 1 */\n#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check)    \\\n    __attribute__((format(printf, string_index, first_to_check)))\n#endif\n#else /* __has_attribute(format) */\n#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check)\n#endif /* __has_attribute(format) */\n#else /* defined(__has_attribute) */\n#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check)\n#endif\n\n/**\n * \\def MBEDTLS_PRINTF_SIZET\n *\n * MBEDTLS_PRINTF_xxx: Due to issues with older window compilers\n * and MinGW we need to define the printf specifier for size_t\n * and long long per platform.\n *\n * Module:  library/debug.c\n * Caller:\n *\n * This module provides debugging functions.\n */\n#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1900)\n   #include <inttypes.h>\n   #define MBEDTLS_PRINTF_SIZET     PRIuPTR\n   #define MBEDTLS_PRINTF_LONGLONG  \"I64d\"\n#else \\\n    /* defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1900) */\n   #define MBEDTLS_PRINTF_SIZET     \"zu\"\n   #define MBEDTLS_PRINTF_LONGLONG  \"lld\"\n#endif \\\n    /* defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1900) */\n\n#if !defined(MBEDTLS_PRINTF_MS_TIME)\n#include <inttypes.h>\n#if !defined(PRId64)\n#define MBEDTLS_PRINTF_MS_TIME MBEDTLS_PRINTF_LONGLONG\n#else\n#define MBEDTLS_PRINTF_MS_TIME PRId64\n#endif\n#endif /* MBEDTLS_PRINTF_MS_TIME */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief   Set the threshold error level to handle globally all debug output.\n *          Debug messages that have a level over the threshold value are\n *          discarded.\n *          (Default value: 0 = No debug )\n *\n * \\param threshold     threshold level of messages to filter on. Messages at a\n *                      higher level will be discarded.\n *                          - Debug levels\n *                              - 0 No debug\n *                              - 1 Error\n *                              - 2 State change\n *                              - 3 Informational\n *                              - 4 Verbose\n */\nvoid mbedtls_debug_set_threshold(int threshold);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_DEBUG_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/des.h",
    "content": "/**\n * \\file des.h\n *\n * \\brief DES block cipher\n *\n * \\warning   DES/3DES are considered weak ciphers and their use constitutes a\n *            security risk. We recommend considering stronger ciphers\n *            instead.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n *\n */\n#ifndef MBEDTLS_DES_H\n#define MBEDTLS_DES_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n#define MBEDTLS_DES_ENCRYPT     1\n#define MBEDTLS_DES_DECRYPT     0\n\n/** The data input has an invalid length. */\n#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH              -0x0032\n\n#define MBEDTLS_DES_KEY_SIZE    8\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_DES_ALT)\n// Regular implementation\n//\n\n/**\n * \\brief          DES context structure\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\ntypedef struct mbedtls_des_context {\n    uint32_t MBEDTLS_PRIVATE(sk)[32];            /*!<  DES subkeys       */\n}\nmbedtls_des_context;\n\n/**\n * \\brief          Triple-DES context structure\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\ntypedef struct mbedtls_des3_context {\n    uint32_t MBEDTLS_PRIVATE(sk)[96];            /*!<  3DES subkeys      */\n}\nmbedtls_des3_context;\n\n#else  /* MBEDTLS_DES_ALT */\n#include \"des_alt.h\"\n#endif /* MBEDTLS_DES_ALT */\n\n/**\n * \\brief          Initialize DES context\n *\n * \\param ctx      DES context to be initialized\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nvoid mbedtls_des_init(mbedtls_des_context *ctx);\n\n/**\n * \\brief          Clear DES context\n *\n * \\param ctx      DES context to be cleared\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nvoid mbedtls_des_free(mbedtls_des_context *ctx);\n\n/**\n * \\brief          Initialize Triple-DES context\n *\n * \\param ctx      DES3 context to be initialized\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nvoid mbedtls_des3_init(mbedtls_des3_context *ctx);\n\n/**\n * \\brief          Clear Triple-DES context\n *\n * \\param ctx      DES3 context to be cleared\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nvoid mbedtls_des3_free(mbedtls_des3_context *ctx);\n\n/**\n * \\brief          Set key parity on the given key to odd.\n *\n *                 DES keys are 56 bits long, but each byte is padded with\n *                 a parity bit to allow verification.\n *\n * \\param key      8-byte secret key\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nvoid mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE]);\n\n/**\n * \\brief          Check that key parity on the given key is odd.\n *\n *                 DES keys are 56 bits long, but each byte is padded with\n *                 a parity bit to allow verification.\n *\n * \\param key      8-byte secret key\n *\n * \\return         0 is parity was ok, 1 if parity was not correct.\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_des_key_check_key_parity(const unsigned char key[MBEDTLS_DES_KEY_SIZE]);\n\n/**\n * \\brief          Check that key is not a weak or semi-weak DES key\n *\n * \\param key      8-byte secret key\n *\n * \\return         0 if no weak key was found, 1 if a weak key was identified.\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_des_key_check_weak(const unsigned char key[MBEDTLS_DES_KEY_SIZE]);\n\n/**\n * \\brief          DES key schedule (56-bit, encryption)\n *\n * \\param ctx      DES context to be initialized\n * \\param key      8-byte secret key\n *\n * \\return         0\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_des_setkey_enc(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE]);\n\n/**\n * \\brief          DES key schedule (56-bit, decryption)\n *\n * \\param ctx      DES context to be initialized\n * \\param key      8-byte secret key\n *\n * \\return         0\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_des_setkey_dec(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE]);\n\n/**\n * \\brief          Triple-DES key schedule (112-bit, encryption)\n *\n * \\param ctx      3DES context to be initialized\n * \\param key      16-byte secret key\n *\n * \\return         0\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_des3_set2key_enc(mbedtls_des3_context *ctx,\n                             const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]);\n\n/**\n * \\brief          Triple-DES key schedule (112-bit, decryption)\n *\n * \\param ctx      3DES context to be initialized\n * \\param key      16-byte secret key\n *\n * \\return         0\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_des3_set2key_dec(mbedtls_des3_context *ctx,\n                             const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]);\n\n/**\n * \\brief          Triple-DES key schedule (168-bit, encryption)\n *\n * \\param ctx      3DES context to be initialized\n * \\param key      24-byte secret key\n *\n * \\return         0\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_des3_set3key_enc(mbedtls_des3_context *ctx,\n                             const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]);\n\n/**\n * \\brief          Triple-DES key schedule (168-bit, decryption)\n *\n * \\param ctx      3DES context to be initialized\n * \\param key      24-byte secret key\n *\n * \\return         0\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_des3_set3key_dec(mbedtls_des3_context *ctx,\n                             const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]);\n\n/**\n * \\brief          DES-ECB block encryption/decryption\n *\n * \\param ctx      DES context\n * \\param input    64-bit input block\n * \\param output   64-bit output block\n *\n * \\return         0 if successful\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_des_crypt_ecb(mbedtls_des_context *ctx,\n                          const unsigned char input[8],\n                          unsigned char output[8]);\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n/**\n * \\brief          DES-CBC buffer encryption/decryption\n *\n * \\note           Upon exit, the content of the IV is updated so that you can\n *                 call the function same function again on the following\n *                 block(s) of data and get the same result as if it was\n *                 encrypted in one call. This allows a \"streaming\" usage.\n *                 If on the other hand you need to retain the contents of the\n *                 IV, you should either save it manually or use the cipher\n *                 module instead.\n *\n * \\param ctx      DES context\n * \\param mode     MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT\n * \\param length   length of the input data\n * \\param iv       initialization vector (updated after use)\n * \\param input    buffer holding the input data\n * \\param output   buffer holding the output data\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_des_crypt_cbc(mbedtls_des_context *ctx,\n                          int mode,\n                          size_t length,\n                          unsigned char iv[8],\n                          const unsigned char *input,\n                          unsigned char *output);\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n/**\n * \\brief          3DES-ECB block encryption/decryption\n *\n * \\param ctx      3DES context\n * \\param input    64-bit input block\n * \\param output   64-bit output block\n *\n * \\return         0 if successful\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_des3_crypt_ecb(mbedtls_des3_context *ctx,\n                           const unsigned char input[8],\n                           unsigned char output[8]);\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n/**\n * \\brief          3DES-CBC buffer encryption/decryption\n *\n * \\note           Upon exit, the content of the IV is updated so that you can\n *                 call the function same function again on the following\n *                 block(s) of data and get the same result as if it was\n *                 encrypted in one call. This allows a \"streaming\" usage.\n *                 If on the other hand you need to retain the contents of the\n *                 IV, you should either save it manually or use the cipher\n *                 module instead.\n *\n * \\param ctx      3DES context\n * \\param mode     MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT\n * \\param length   length of the input data\n * \\param iv       initialization vector (updated after use)\n * \\param input    buffer holding the input data\n * \\param output   buffer holding the output data\n *\n * \\return         0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx,\n                           int mode,\n                           size_t length,\n                           unsigned char iv[8],\n                           const unsigned char *input,\n                           unsigned char *output);\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n/**\n * \\brief          Internal function for key expansion.\n *                 (Only exposed to allow overriding it,\n *                 see MBEDTLS_DES_SETKEY_ALT)\n *\n * \\param SK       Round keys\n * \\param key      Base key\n *\n * \\warning        DES/3DES are considered weak ciphers and their use constitutes a\n *                 security risk. We recommend considering stronger ciphers\n *                 instead.\n */\nvoid mbedtls_des_setkey(uint32_t SK[32],\n                        const unsigned char key[MBEDTLS_DES_KEY_SIZE]);\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/**\n * \\brief          Checkup routine\n *\n * \\return         0 if successful, or 1 if the test failed\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_des_self_test(int verbose);\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* des.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/dhm.h",
    "content": "/**\n * \\file dhm.h\n *\n * \\brief   This file contains Diffie-Hellman-Merkle (DHM) key exchange\n *          definitions and functions.\n *\n * Diffie-Hellman-Merkle (DHM) key exchange is defined in\n * <em>RFC-2631: Diffie-Hellman Key Agreement Method</em> and\n * <em>Public-Key Cryptography Standards (PKCS) #3: Diffie\n * Hellman Key Agreement Standard</em>.\n *\n * <em>RFC-3526: More Modular Exponential (MODP) Diffie-Hellman groups for\n * Internet Key Exchange (IKE)</em> defines a number of standardized\n * Diffie-Hellman groups for IKE.\n *\n * <em>RFC-5114: Additional Diffie-Hellman Groups for Use with IETF\n * Standards</em> defines a number of standardized Diffie-Hellman\n * groups that can be used.\n *\n * \\warning  The security of the DHM key exchange relies on the proper choice\n *           of prime modulus - optimally, it should be a safe prime. The usage\n *           of non-safe primes both decreases the difficulty of the underlying\n *           discrete logarithm problem and can lead to small subgroup attacks\n *           leaking private exponent bits when invalid public keys are used\n *           and not detected. This is especially relevant if the same DHM\n *           parameters are reused for multiple key exchanges as in static DHM,\n *           while the criticality of small-subgroup attacks is lower for\n *           ephemeral DHM.\n *\n * \\warning  For performance reasons, the code does neither perform primality\n *           nor safe primality tests, nor the expensive checks for invalid\n *           subgroups. Moreover, even if these were performed, non-standardized\n *           primes cannot be trusted because of the possibility of backdoors\n *           that can't be effectively checked for.\n *\n * \\warning  Diffie-Hellman-Merkle is therefore a security risk when not using\n *           standardized primes generated using a trustworthy (\"nothing up\n *           my sleeve\") method, such as the RFC 3526 / 7919 primes. In the TLS\n *           protocol, DH parameters need to be negotiated, so using the default\n *           primes systematically is not always an option. If possible, use\n *           Elliptic Curve Diffie-Hellman (ECDH), which has better performance,\n *           and for which the TLS protocol mandates the use of standard\n *           parameters.\n *\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_DHM_H\n#define MBEDTLS_DHM_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n#include \"mbedtls/bignum.h\"\n\n/*\n * DHM Error codes\n */\n/** Bad input parameters. */\n#define MBEDTLS_ERR_DHM_BAD_INPUT_DATA                    -0x3080\n/** Reading of the DHM parameters failed. */\n#define MBEDTLS_ERR_DHM_READ_PARAMS_FAILED                -0x3100\n/** Making of the DHM parameters failed. */\n#define MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED                -0x3180\n/** Reading of the public values failed. */\n#define MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED                -0x3200\n/** Making of the public value failed. */\n#define MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED                -0x3280\n/** Calculation of the DHM secret failed. */\n#define MBEDTLS_ERR_DHM_CALC_SECRET_FAILED                -0x3300\n/** The ASN.1 data is not formatted correctly. */\n#define MBEDTLS_ERR_DHM_INVALID_FORMAT                    -0x3380\n/** Allocation of memory failed. */\n#define MBEDTLS_ERR_DHM_ALLOC_FAILED                      -0x3400\n/** Read or write of file failed. */\n#define MBEDTLS_ERR_DHM_FILE_IO_ERROR                     -0x3480\n/** Setting the modulus and generator failed. */\n#define MBEDTLS_ERR_DHM_SET_GROUP_FAILED                  -0x3580\n\n/** Which parameter to access in mbedtls_dhm_get_value(). */\ntypedef enum {\n    MBEDTLS_DHM_PARAM_P,  /*!<  The prime modulus. */\n    MBEDTLS_DHM_PARAM_G,  /*!<  The generator. */\n    MBEDTLS_DHM_PARAM_X,  /*!<  Our secret value. */\n    MBEDTLS_DHM_PARAM_GX, /*!<  Our public key = \\c G^X mod \\c P. */\n    MBEDTLS_DHM_PARAM_GY, /*!<  The public key of the peer = \\c G^Y mod \\c P. */\n    MBEDTLS_DHM_PARAM_K,  /*!<  The shared secret = \\c G^(XY) mod \\c P. */\n} mbedtls_dhm_parameter;\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_DHM_ALT)\n\n/**\n * \\brief          The DHM context structure.\n */\ntypedef struct mbedtls_dhm_context {\n    mbedtls_mpi MBEDTLS_PRIVATE(P);      /*!<  The prime modulus. */\n    mbedtls_mpi MBEDTLS_PRIVATE(G);      /*!<  The generator. */\n    mbedtls_mpi MBEDTLS_PRIVATE(X);      /*!<  Our secret value. */\n    mbedtls_mpi MBEDTLS_PRIVATE(GX);     /*!<  Our public key = \\c G^X mod \\c P. */\n    mbedtls_mpi MBEDTLS_PRIVATE(GY);     /*!<  The public key of the peer = \\c G^Y mod \\c P. */\n    mbedtls_mpi MBEDTLS_PRIVATE(K);      /*!<  The shared secret = \\c G^(XY) mod \\c P. */\n    mbedtls_mpi MBEDTLS_PRIVATE(RP);     /*!<  The cached value = \\c R^2 mod \\c P. */\n    mbedtls_mpi MBEDTLS_PRIVATE(Vi);     /*!<  The blinding value. */\n    mbedtls_mpi MBEDTLS_PRIVATE(Vf);     /*!<  The unblinding value. */\n    mbedtls_mpi MBEDTLS_PRIVATE(pX);     /*!<  The previous \\c X. */\n}\nmbedtls_dhm_context;\n\n#else /* MBEDTLS_DHM_ALT */\n#include \"dhm_alt.h\"\n#endif /* MBEDTLS_DHM_ALT */\n\n/**\n * \\brief          This function initializes the DHM context.\n *\n * \\param ctx      The DHM context to initialize.\n */\nvoid mbedtls_dhm_init(mbedtls_dhm_context *ctx);\n\n/**\n * \\brief          This function parses the DHM parameters in a\n *                 TLS ServerKeyExchange handshake message\n *                 (DHM modulus, generator, and public key).\n *\n * \\note           In a TLS handshake, this is the how the client\n *                 sets up its DHM context from the server's public\n *                 DHM key material.\n *\n * \\param ctx      The DHM context to use. This must be initialized.\n * \\param p        On input, *p must be the start of the input buffer.\n *                 On output, *p is updated to point to the end of the data\n *                 that has been read. On success, this is the first byte\n *                 past the end of the ServerKeyExchange parameters.\n *                 On error, this is the point at which an error has been\n *                 detected, which is usually not useful except to debug\n *                 failures.\n * \\param end      The end of the input buffer.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_DHM_XXX error code on failure.\n */\nint mbedtls_dhm_read_params(mbedtls_dhm_context *ctx,\n                            unsigned char **p,\n                            const unsigned char *end);\n\n/**\n * \\brief          This function generates a DHM key pair and exports its\n *                 public part together with the DHM parameters in the format\n *                 used in a TLS ServerKeyExchange handshake message.\n *\n * \\note           This function assumes that the DHM parameters \\c ctx->P\n *                 and \\c ctx->G have already been properly set. For that, use\n *                 mbedtls_dhm_set_group() below in conjunction with\n *                 mbedtls_mpi_read_binary() and mbedtls_mpi_read_string().\n *\n * \\note           In a TLS handshake, this is the how the server generates\n *                 and exports its DHM key material.\n *\n * \\param ctx      The DHM context to use. This must be initialized\n *                 and have the DHM parameters set. It may or may not\n *                 already have imported the peer's public key.\n * \\param x_size   The private key size in Bytes.\n * \\param olen     The address at which to store the number of Bytes\n *                 written on success. This must not be \\c NULL.\n * \\param output   The destination buffer. This must be a writable buffer of\n *                 sufficient size to hold the reduced binary presentation of\n *                 the modulus, the generator and the public key, each wrapped\n *                 with a 2-byte length field. It is the responsibility of the\n *                 caller to ensure that enough space is available. Refer to\n *                 mbedtls_mpi_size() to computing the byte-size of an MPI.\n * \\param f_rng    The RNG function. Must not be \\c NULL.\n * \\param p_rng    The RNG context to be passed to \\p f_rng. This may be\n *                 \\c NULL if \\p f_rng doesn't need a context parameter.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_DHM_XXX error code on failure.\n */\nint mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size,\n                            unsigned char *output, size_t *olen,\n                            mbedtls_f_rng_t *f_rng,\n                            void *p_rng);\n\n/**\n * \\brief          This function sets the prime modulus and generator.\n *\n * \\note           This function can be used to set \\c ctx->P, \\c ctx->G\n *                 in preparation for mbedtls_dhm_make_params().\n *\n * \\param ctx      The DHM context to configure. This must be initialized.\n * \\param P        The MPI holding the DHM prime modulus. This must be\n *                 an initialized MPI.\n * \\param G        The MPI holding the DHM generator. This must be an\n *                 initialized MPI.\n *\n * \\return         \\c 0 if successful.\n * \\return         An \\c MBEDTLS_ERR_DHM_XXX error code on failure.\n */\nint mbedtls_dhm_set_group(mbedtls_dhm_context *ctx,\n                          const mbedtls_mpi *P,\n                          const mbedtls_mpi *G);\n\n/**\n * \\brief          This function imports the raw public value of the peer.\n *\n * \\note           In a TLS handshake, this is the how the server imports\n *                 the Client's public DHM key.\n *\n * \\param ctx      The DHM context to use. This must be initialized and have\n *                 its DHM parameters set, e.g. via mbedtls_dhm_set_group().\n *                 It may or may not already have generated its own private key.\n * \\param input    The input buffer containing the \\c G^Y value of the peer.\n *                 This must be a readable buffer of size \\p ilen Bytes.\n * \\param ilen     The size of the input buffer \\p input in Bytes.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_DHM_XXX error code on failure.\n */\nint mbedtls_dhm_read_public(mbedtls_dhm_context *ctx,\n                            const unsigned char *input, size_t ilen);\n\n/**\n * \\brief          This function creates a DHM key pair and exports\n *                 the raw public key in big-endian format.\n *\n * \\note           The destination buffer is always fully written\n *                 so as to contain a big-endian representation of G^X mod P.\n *                 If it is larger than \\c ctx->len, it is padded accordingly\n *                 with zero-bytes at the beginning.\n *\n * \\param ctx      The DHM context to use. This must be initialized and\n *                 have the DHM parameters set. It may or may not already\n *                 have imported the peer's public key.\n * \\param x_size   The private key size in Bytes.\n * \\param output   The destination buffer. This must be a writable buffer of\n *                 size \\p olen Bytes.\n * \\param olen     The length of the destination buffer. This must be at least\n *                 equal to `ctx->len` (the size of \\c P).\n * \\param f_rng    The RNG function. This must not be \\c NULL.\n * \\param p_rng    The RNG context to be passed to \\p f_rng. This may be \\c NULL\n *                 if \\p f_rng doesn't need a context argument.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_DHM_XXX error code on failure.\n */\nint mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size,\n                            unsigned char *output, size_t olen,\n                            mbedtls_f_rng_t *f_rng,\n                            void *p_rng);\n\n/**\n * \\brief          This function derives and exports the shared secret\n *                 \\c (G^Y)^X mod \\c P.\n *\n * \\note           If \\p f_rng is not \\c NULL, it is used to blind the input as\n *                 a countermeasure against timing attacks. Blinding is used\n *                 only if our private key \\c X is re-used, and not used\n *                 otherwise. We recommend always passing a non-NULL\n *                 \\p f_rng argument.\n *\n * \\param ctx           The DHM context to use. This must be initialized\n *                      and have its own private key generated and the peer's\n *                      public key imported.\n * \\param output        The buffer to write the generated shared key to. This\n *                      must be a writable buffer of size \\p output_size Bytes.\n * \\param output_size   The size of the destination buffer. This must be at\n *                      least the size of \\c ctx->len (the size of \\c P).\n * \\param olen          On exit, holds the actual number of Bytes written.\n * \\param f_rng         The RNG function. Must not be \\c NULL. Used for\n *                      blinding.\n * \\param p_rng         The RNG context to be passed to \\p f_rng. This may be\n *                      \\c NULL if \\p f_rng doesn't need a context parameter.\n *\n * \\return              \\c 0 on success.\n * \\return              An \\c MBEDTLS_ERR_DHM_XXX error code on failure.\n */\nint mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx,\n                            unsigned char *output, size_t output_size, size_t *olen,\n                            mbedtls_f_rng_t *f_rng,\n                            void *p_rng);\n\n/**\n * \\brief          This function returns the size of the prime modulus in bits.\n *\n * \\param ctx      The DHM context to query.\n *\n * \\return         The size of the prime modulus in bits,\n *                 i.e. the number n such that 2^(n-1) <= P < 2^n.\n */\nsize_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx);\n\n/**\n * \\brief          This function returns the size of the prime modulus in bytes.\n *\n * \\param ctx      The DHM context to query.\n *\n * \\return         The size of the prime modulus in bytes,\n *                 i.e. the number n such that 2^(8*(n-1)) <= P < 2^(8*n).\n */\nsize_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx);\n\n/**\n * \\brief          This function copies a parameter of a DHM key.\n *\n * \\param ctx      The DHM context to query.\n * \\param param    The parameter to copy.\n * \\param dest     The MPI object to copy the value into. It must be\n *                 initialized.\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_DHM_BAD_INPUT_DATA if \\p param is invalid.\n * \\return         An \\c MBEDTLS_ERR_MPI_XXX error code if the copy fails.\n */\nint mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx,\n                          mbedtls_dhm_parameter param,\n                          mbedtls_mpi *dest);\n\n/**\n * \\brief          This function frees and clears the components\n *                 of a DHM context.\n *\n * \\param ctx      The DHM context to free and clear. This may be \\c NULL,\n *                 in which case this function is a no-op. If it is not \\c NULL,\n *                 it must point to an initialized DHM context.\n */\nvoid mbedtls_dhm_free(mbedtls_dhm_context *ctx);\n\n#if defined(MBEDTLS_ASN1_PARSE_C)\n/**\n * \\brief             This function parses DHM parameters in PEM or DER format.\n *\n * \\param dhm         The DHM context to import the DHM parameters into.\n *                    This must be initialized.\n * \\param dhmin       The input buffer. This must be a readable buffer of\n *                    length \\p dhminlen Bytes.\n * \\param dhminlen    The size of the input buffer \\p dhmin, including the\n *                    terminating \\c NULL Byte for PEM data.\n *\n * \\return            \\c 0 on success.\n * \\return            An \\c MBEDTLS_ERR_DHM_XXX or \\c MBEDTLS_ERR_PEM_XXX error\n *                    code on failure.\n */\nint mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin,\n                          size_t dhminlen);\n\n#if defined(MBEDTLS_FS_IO)\n/**\n * \\brief          This function loads and parses DHM parameters from a file.\n *\n * \\param dhm      The DHM context to load the parameters to.\n *                 This must be initialized.\n * \\param path     The filename to read the DHM parameters from.\n *                 This must not be \\c NULL.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_DHM_XXX or \\c MBEDTLS_ERR_PEM_XXX\n *                 error code on failure.\n */\nint mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path);\n#endif /* MBEDTLS_FS_IO */\n#endif /* MBEDTLS_ASN1_PARSE_C */\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/**\n * \\brief          The DMH checkup routine.\n *\n * \\return         \\c 0 on success.\n * \\return         \\c 1 on failure.\n */\nint mbedtls_dhm_self_test(int verbose);\n\n#endif /* MBEDTLS_SELF_TEST */\n#ifdef __cplusplus\n}\n#endif\n\n/**\n * RFC 3526, RFC 5114 and RFC 7919 standardize a number of\n * Diffie-Hellman groups, some of which are included here\n * for use within the SSL/TLS module and the user's convenience\n * when configuring the Diffie-Hellman parameters by hand\n * through \\c mbedtls_ssl_conf_dh_param.\n *\n * The following lists the source of the above groups in the standards:\n * - RFC 5114 section 2.2:  2048-bit MODP Group with 224-bit Prime Order Subgroup\n * - RFC 3526 section 3:    2048-bit MODP Group\n * - RFC 3526 section 4:    3072-bit MODP Group\n * - RFC 3526 section 5:    4096-bit MODP Group\n * - RFC 7919 section A.1:  ffdhe2048\n * - RFC 7919 section A.2:  ffdhe3072\n * - RFC 7919 section A.3:  ffdhe4096\n * - RFC 7919 section A.4:  ffdhe6144\n * - RFC 7919 section A.5:  ffdhe8192\n *\n * The constants with suffix \"_p\" denote the chosen prime moduli, while\n * the constants with suffix \"_g\" denote the chosen generator\n * of the associated prime field.\n *\n * The constants further suffixed with \"_bin\" are provided in binary format,\n * while all other constants represent null-terminated strings holding the\n * hexadecimal presentation of the respective numbers.\n *\n * The primes from RFC 3526 and RFC 7919 have been generating by the following\n * trust-worthy procedure:\n * - Fix N in { 2048, 3072, 4096, 6144, 8192 } and consider the N-bit number\n *   the first and last 64 bits are all 1, and the remaining N - 128 bits of\n *   which are 0x7ff...ff.\n * - Add the smallest multiple of the first N - 129 bits of the binary expansion\n *   of pi (for RFC 5236) or e (for RFC 7919) to this intermediate bit-string\n *   such that the resulting integer is a safe-prime.\n * - The result is the respective RFC 3526 / 7919 prime, and the corresponding\n *   generator is always chosen to be 2 (which is a square for these prime,\n *   hence the corresponding subgroup has order (p-1)/2 and avoids leaking a\n *   bit in the private exponent).\n *\n */\n\n/*\n * Trustworthy DHM parameters in binary form\n */\n\n#define MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN {        \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \\\n        0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \\\n        0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \\\n        0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \\\n        0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \\\n        0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \\\n        0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \\\n        0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \\\n        0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \\\n        0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \\\n        0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \\\n        0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \\\n        0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \\\n        0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \\\n        0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \\\n        0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \\\n        0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \\\n        0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \\\n        0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \\\n        0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \\\n        0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \\\n        0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \\\n        0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \\\n        0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \\\n        0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \\\n        0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \\\n        0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \\\n        0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \\\n        0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \\\n        0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \\\n        0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }\n\n#define MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN { 0x02 }\n\n#define MBEDTLS_DHM_RFC3526_MODP_3072_P_BIN {       \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \\\n        0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \\\n        0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \\\n        0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \\\n        0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \\\n        0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \\\n        0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \\\n        0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \\\n        0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \\\n        0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \\\n        0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \\\n        0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \\\n        0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \\\n        0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \\\n        0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \\\n        0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \\\n        0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \\\n        0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \\\n        0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \\\n        0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \\\n        0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \\\n        0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \\\n        0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \\\n        0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \\\n        0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \\\n        0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \\\n        0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \\\n        0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \\\n        0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \\\n        0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \\\n        0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \\\n        0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \\\n        0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \\\n        0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \\\n        0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \\\n        0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \\\n        0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \\\n        0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \\\n        0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \\\n        0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \\\n        0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \\\n        0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \\\n        0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \\\n        0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \\\n        0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \\\n        0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \\\n        0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }\n\n#define MBEDTLS_DHM_RFC3526_MODP_3072_G_BIN { 0x02 }\n\n#define MBEDTLS_DHM_RFC3526_MODP_4096_P_BIN  {       \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  \\\n        0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,  \\\n        0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,  \\\n        0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,  \\\n        0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,  \\\n        0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,  \\\n        0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,  \\\n        0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,  \\\n        0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,  \\\n        0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,  \\\n        0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,  \\\n        0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,  \\\n        0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,  \\\n        0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,  \\\n        0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,  \\\n        0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,  \\\n        0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,  \\\n        0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,  \\\n        0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,  \\\n        0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,  \\\n        0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,  \\\n        0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,  \\\n        0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,  \\\n        0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,  \\\n        0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,  \\\n        0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,  \\\n        0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,  \\\n        0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,  \\\n        0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,  \\\n        0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,  \\\n        0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,  \\\n        0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,  \\\n        0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,  \\\n        0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,  \\\n        0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,  \\\n        0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,  \\\n        0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,  \\\n        0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,  \\\n        0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,  \\\n        0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,  \\\n        0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,  \\\n        0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,  \\\n        0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,  \\\n        0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,  \\\n        0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,  \\\n        0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,  \\\n        0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,  \\\n        0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,  \\\n        0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,  \\\n        0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,  \\\n        0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,  \\\n        0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,  \\\n        0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,  \\\n        0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,  \\\n        0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,  \\\n        0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,  \\\n        0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,  \\\n        0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,  \\\n        0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,  \\\n        0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,  \\\n        0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,  \\\n        0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,  \\\n        0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,  \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }\n\n#define MBEDTLS_DHM_RFC3526_MODP_4096_G_BIN { 0x02 }\n\n#define MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN {        \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \\\n        0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \\\n        0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \\\n        0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \\\n        0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \\\n        0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \\\n        0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \\\n        0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \\\n        0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \\\n        0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \\\n        0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \\\n        0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \\\n        0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \\\n        0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \\\n        0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \\\n        0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \\\n        0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \\\n        0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \\\n        0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \\\n        0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \\\n        0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \\\n        0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \\\n        0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \\\n        0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \\\n        0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \\\n        0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \\\n        0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \\\n        0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \\\n        0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \\\n        0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \\\n        0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }\n\n#define MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN { 0x02 }\n\n#define MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN { \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \\\n        0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \\\n        0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \\\n        0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \\\n        0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \\\n        0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \\\n        0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \\\n        0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \\\n        0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \\\n        0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \\\n        0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \\\n        0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \\\n        0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \\\n        0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \\\n        0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \\\n        0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \\\n        0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \\\n        0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \\\n        0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \\\n        0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \\\n        0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \\\n        0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \\\n        0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \\\n        0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \\\n        0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \\\n        0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \\\n        0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \\\n        0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \\\n        0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \\\n        0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \\\n        0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \\\n        0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \\\n        0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \\\n        0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \\\n        0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \\\n        0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \\\n        0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \\\n        0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \\\n        0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \\\n        0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \\\n        0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \\\n        0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \\\n        0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \\\n        0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \\\n        0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \\\n        0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \\\n        0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37, \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }\n\n#define MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN { 0x02 }\n\n#define MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN {        \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \\\n        0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \\\n        0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \\\n        0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \\\n        0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \\\n        0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \\\n        0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \\\n        0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \\\n        0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \\\n        0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \\\n        0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \\\n        0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \\\n        0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \\\n        0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \\\n        0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \\\n        0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \\\n        0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \\\n        0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \\\n        0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \\\n        0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \\\n        0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \\\n        0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \\\n        0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \\\n        0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \\\n        0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \\\n        0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \\\n        0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \\\n        0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \\\n        0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \\\n        0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \\\n        0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \\\n        0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \\\n        0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \\\n        0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \\\n        0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \\\n        0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \\\n        0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \\\n        0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \\\n        0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \\\n        0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \\\n        0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \\\n        0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \\\n        0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \\\n        0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \\\n        0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \\\n        0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \\\n        0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \\\n        0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \\\n        0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \\\n        0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \\\n        0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \\\n        0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \\\n        0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \\\n        0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \\\n        0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \\\n        0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \\\n        0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \\\n        0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \\\n        0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \\\n        0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \\\n        0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \\\n        0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \\\n        0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A, \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }\n\n#define MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN { 0x02 }\n\n#define MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN {        \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \\\n        0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \\\n        0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \\\n        0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \\\n        0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \\\n        0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \\\n        0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \\\n        0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \\\n        0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \\\n        0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \\\n        0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \\\n        0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \\\n        0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \\\n        0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \\\n        0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \\\n        0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \\\n        0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \\\n        0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \\\n        0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \\\n        0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \\\n        0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \\\n        0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \\\n        0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \\\n        0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \\\n        0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \\\n        0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \\\n        0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \\\n        0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \\\n        0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \\\n        0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \\\n        0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \\\n        0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \\\n        0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \\\n        0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \\\n        0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \\\n        0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \\\n        0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \\\n        0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \\\n        0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \\\n        0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \\\n        0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \\\n        0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \\\n        0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \\\n        0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \\\n        0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \\\n        0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \\\n        0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \\\n        0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \\\n        0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \\\n        0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \\\n        0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \\\n        0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \\\n        0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \\\n        0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \\\n        0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \\\n        0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \\\n        0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \\\n        0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \\\n        0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \\\n        0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \\\n        0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \\\n        0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \\\n        0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \\\n        0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \\\n        0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \\\n        0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \\\n        0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \\\n        0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \\\n        0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \\\n        0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \\\n        0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \\\n        0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \\\n        0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \\\n        0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \\\n        0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \\\n        0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \\\n        0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \\\n        0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \\\n        0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \\\n        0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \\\n        0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \\\n        0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \\\n        0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \\\n        0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \\\n        0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \\\n        0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \\\n        0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \\\n        0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \\\n        0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \\\n        0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \\\n        0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \\\n        0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \\\n        0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \\\n        0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \\\n        0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65, \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }\n\n#define MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN { 0x02 }\n\n#define MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN {        \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \\\n        0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \\\n        0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \\\n        0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \\\n        0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \\\n        0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \\\n        0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \\\n        0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \\\n        0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \\\n        0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \\\n        0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \\\n        0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \\\n        0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \\\n        0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \\\n        0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \\\n        0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \\\n        0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \\\n        0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \\\n        0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \\\n        0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \\\n        0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \\\n        0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \\\n        0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \\\n        0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \\\n        0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \\\n        0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \\\n        0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \\\n        0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \\\n        0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \\\n        0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \\\n        0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \\\n        0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \\\n        0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \\\n        0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \\\n        0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \\\n        0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \\\n        0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \\\n        0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \\\n        0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \\\n        0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \\\n        0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \\\n        0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \\\n        0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \\\n        0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \\\n        0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \\\n        0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \\\n        0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \\\n        0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \\\n        0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \\\n        0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \\\n        0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \\\n        0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \\\n        0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \\\n        0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \\\n        0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \\\n        0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \\\n        0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \\\n        0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \\\n        0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \\\n        0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \\\n        0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \\\n        0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \\\n        0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \\\n        0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \\\n        0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \\\n        0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \\\n        0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \\\n        0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \\\n        0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \\\n        0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \\\n        0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \\\n        0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \\\n        0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \\\n        0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \\\n        0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \\\n        0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \\\n        0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \\\n        0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \\\n        0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \\\n        0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \\\n        0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \\\n        0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \\\n        0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \\\n        0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \\\n        0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \\\n        0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \\\n        0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \\\n        0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \\\n        0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \\\n        0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \\\n        0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \\\n        0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \\\n        0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \\\n        0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \\\n        0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA, \\\n        0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38, \\\n        0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, \\\n        0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43, \\\n        0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E, \\\n        0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, \\\n        0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29, \\\n        0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65, \\\n        0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, \\\n        0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4, \\\n        0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82, \\\n        0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, \\\n        0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51, \\\n        0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22, \\\n        0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, \\\n        0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE, \\\n        0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C, \\\n        0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, \\\n        0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B, \\\n        0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9, \\\n        0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, \\\n        0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31, \\\n        0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57, \\\n        0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, \\\n        0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E, \\\n        0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30, \\\n        0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, \\\n        0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE, \\\n        0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D, \\\n        0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, \\\n        0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E, \\\n        0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C, \\\n        0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, \\\n        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }\n\n#define MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN { 0x02 }\n\n#endif /* dhm.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/ecdh.h",
    "content": "/**\n * \\file ecdh.h\n *\n * \\brief This file contains ECDH definitions and functions.\n *\n * The Elliptic Curve Diffie-Hellman (ECDH) protocol is an anonymous\n * key agreement protocol allowing two parties to establish a shared\n * secret over an insecure channel. Each party must have an\n * elliptic-curve public–private key pair.\n *\n * For more information, see <em>NIST SP 800-56A Rev. 2: Recommendation for\n * Pair-Wise Key Establishment Schemes Using Discrete Logarithm\n * Cryptography</em>.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_ECDH_H\n#define MBEDTLS_ECDH_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/ecp.h\"\n\n/*\n * Mbed TLS supports two formats for ECDH contexts (#mbedtls_ecdh_context\n * defined in `ecdh.h`). For most applications, the choice of format makes\n * no difference, since all library functions can work with either format,\n * except that the new format is incompatible with MBEDTLS_ECP_RESTARTABLE.\n\n * The new format used when this option is disabled is smaller\n * (56 bytes on a 32-bit platform). In future versions of the library, it\n * will support alternative implementations of ECDH operations.\n * The new format is incompatible with applications that access\n * context fields directly and with restartable ECP operations.\n */\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n#define MBEDTLS_ECDH_LEGACY_CONTEXT\n#else\n#undef MBEDTLS_ECDH_LEGACY_CONTEXT\n#endif\n\n#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)\n#undef MBEDTLS_ECDH_LEGACY_CONTEXT\n#include \"everest/everest.h\"\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Defines the source of the imported EC key.\n */\ntypedef enum {\n    MBEDTLS_ECDH_OURS,   /**< Our key. */\n    MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */\n} mbedtls_ecdh_side;\n\n#if !defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n/**\n * Defines the ECDH implementation used.\n *\n * Later versions of the library may add new variants, therefore users should\n * not make any assumptions about them.\n */\ntypedef enum {\n    MBEDTLS_ECDH_VARIANT_NONE = 0,   /*!< Implementation not defined. */\n    MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0,/*!< The default Mbed TLS implementation */\n#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)\n    MBEDTLS_ECDH_VARIANT_EVEREST     /*!< Everest implementation */\n#endif\n} mbedtls_ecdh_variant;\n\n/**\n * The context used by the default ECDH implementation.\n *\n * Later versions might change the structure of this context, therefore users\n * should not make any assumptions about the structure of\n * mbedtls_ecdh_context_mbed.\n */\ntypedef struct mbedtls_ecdh_context_mbed {\n    mbedtls_ecp_group MBEDTLS_PRIVATE(grp);   /*!< The elliptic curve used. */\n    mbedtls_mpi MBEDTLS_PRIVATE(d);           /*!< The private key. */\n    mbedtls_ecp_point MBEDTLS_PRIVATE(Q);     /*!< The public key. */\n    mbedtls_ecp_point MBEDTLS_PRIVATE(Qp);    /*!< The value of the public key of the peer. */\n    mbedtls_mpi MBEDTLS_PRIVATE(z);           /*!< The shared secret. */\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(rs); /*!< The restart context for EC computations. */\n#endif\n} mbedtls_ecdh_context_mbed;\n#endif\n\n/**\n *\n * \\warning         Performing multiple operations concurrently on the same\n *                  ECDSA context is not supported; objects of this type\n *                  should not be shared between multiple threads.\n * \\brief           The ECDH context structure.\n */\ntypedef struct mbedtls_ecdh_context {\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n    mbedtls_ecp_group MBEDTLS_PRIVATE(grp);   /*!< The elliptic curve used. */\n    mbedtls_mpi MBEDTLS_PRIVATE(d);           /*!< The private key. */\n    mbedtls_ecp_point MBEDTLS_PRIVATE(Q);     /*!< The public key. */\n    mbedtls_ecp_point MBEDTLS_PRIVATE(Qp);    /*!< The value of the public key of the peer. */\n    mbedtls_mpi MBEDTLS_PRIVATE(z);           /*!< The shared secret. */\n    int MBEDTLS_PRIVATE(point_format);        /*!< The format of point export in TLS messages. */\n    mbedtls_ecp_point MBEDTLS_PRIVATE(Vi);    /*!< The blinding value. */\n    mbedtls_ecp_point MBEDTLS_PRIVATE(Vf);    /*!< The unblinding value. */\n    mbedtls_mpi MBEDTLS_PRIVATE(_d);          /*!< The previous \\p d. */\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    int MBEDTLS_PRIVATE(restart_enabled);        /*!< The flag for restartable mode. */\n    mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(rs); /*!< The restart context for EC computations. */\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n#else\n    uint8_t MBEDTLS_PRIVATE(point_format);       /*!< The format of point export in TLS messages\n                                                    as defined in RFC 4492. */\n    mbedtls_ecp_group_id MBEDTLS_PRIVATE(grp_id);/*!< The elliptic curve used. */\n    mbedtls_ecdh_variant MBEDTLS_PRIVATE(var);   /*!< The ECDH implementation/structure used. */\n    union {\n        mbedtls_ecdh_context_mbed   MBEDTLS_PRIVATE(mbed_ecdh);\n#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)\n        mbedtls_ecdh_context_everest MBEDTLS_PRIVATE(everest_ecdh);\n#endif\n    } MBEDTLS_PRIVATE(ctx);                      /*!< Implementation-specific context. The\n                                                    context in use is specified by the \\c var\n                                                    field. */\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    uint8_t MBEDTLS_PRIVATE(restart_enabled);    /*!< The flag for restartable mode. Functions of\n                                                    an alternative implementation not supporting\n                                                    restartable mode must return\n                                                    MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error\n                                                    if this flag is set. */\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */\n}\nmbedtls_ecdh_context;\n\n/**\n * \\brief          Return the ECP group for provided context.\n *\n * \\note           To access group specific fields, users should use\n *                 `mbedtls_ecp_curve_info_from_grp_id` or\n *                 `mbedtls_ecp_group_load` on the extracted `group_id`.\n *\n * \\param ctx      The ECDH context to parse. This must not be \\c NULL.\n *\n * \\return         The \\c mbedtls_ecp_group_id of the context.\n */\nmbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx);\n\n/**\n * \\brief          Check whether a given group can be used for ECDH.\n *\n * \\param gid      The ECP group ID to check.\n *\n * \\return         \\c 1 if the group can be used, \\c 0 otherwise\n */\nint mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid);\n\n/**\n * \\brief           This function generates an ECDH keypair on an elliptic\n *                  curve.\n *\n *                  This function performs the first of two core computations\n *                  implemented during the ECDH key exchange. The second core\n *                  computation is performed by mbedtls_ecdh_compute_shared().\n *\n * \\see             ecp.h\n *\n * \\param grp       The ECP group to use. This must be initialized and have\n *                  domain parameters loaded, for example through\n *                  mbedtls_ecp_load() or mbedtls_ecp_tls_read_group().\n * \\param d         The destination MPI (private key).\n *                  This must be initialized.\n * \\param Q         The destination point (public key).\n *                  This must be initialized.\n * \\param f_rng     The RNG function to use. This must not be \\c NULL.\n * \\param p_rng     The RNG context to be passed to \\p f_rng. This may be\n *                  \\c NULL in case \\p f_rng doesn't need a context argument.\n *\n * \\return          \\c 0 on success.\n * \\return          Another \\c MBEDTLS_ERR_ECP_XXX or\n *                  \\c MBEDTLS_MPI_XXX error code on failure.\n */\nint mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,\n                            mbedtls_f_rng_t *f_rng,\n                            void *p_rng);\n\n/**\n * \\brief           This function computes the shared secret.\n *\n *                  This function performs the second of two core computations\n *                  implemented during the ECDH key exchange. The first core\n *                  computation is performed by mbedtls_ecdh_gen_public().\n *\n * \\see             ecp.h\n *\n * \\note            If \\p f_rng is not NULL, it is used to implement\n *                  countermeasures against side-channel attacks.\n *                  For more information, see mbedtls_ecp_mul().\n *\n * \\param grp       The ECP group to use. This must be initialized and have\n *                  domain parameters loaded, for example through\n *                  mbedtls_ecp_load() or mbedtls_ecp_tls_read_group().\n * \\param z         The destination MPI (shared secret).\n *                  This must be initialized.\n * \\param Q         The public key from another party.\n *                  This must be initialized.\n * \\param d         Our secret exponent (private key).\n *                  This must be initialized.\n * \\param f_rng     The RNG function to use. This must not be \\c NULL.\n * \\param p_rng     The RNG context to be passed to \\p f_rng. This may be\n *                  \\c NULL if \\p f_rng is \\c NULL or doesn't need a\n *                  context argument.\n *\n * \\return          \\c 0 on success.\n * \\return          Another \\c MBEDTLS_ERR_ECP_XXX or\n *                  \\c MBEDTLS_MPI_XXX error code on failure.\n */\nint mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z,\n                                const mbedtls_ecp_point *Q, const mbedtls_mpi *d,\n                                mbedtls_f_rng_t *f_rng,\n                                void *p_rng);\n\n/**\n * \\brief           This function initializes an ECDH context.\n *\n * \\param ctx       The ECDH context to initialize. This must not be \\c NULL.\n */\nvoid mbedtls_ecdh_init(mbedtls_ecdh_context *ctx);\n\n/**\n * \\brief           This function sets up the ECDH context with the information\n *                  given.\n *\n *                  This function should be called after mbedtls_ecdh_init() but\n *                  before mbedtls_ecdh_make_params(). There is no need to call\n *                  this function before mbedtls_ecdh_read_params().\n *\n *                  This is the first function used by a TLS server for ECDHE\n *                  ciphersuites.\n *\n * \\param ctx       The ECDH context to set up. This must be initialized.\n * \\param grp_id    The group id of the group to set up the context for.\n *\n * \\return          \\c 0 on success.\n */\nint mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx,\n                       mbedtls_ecp_group_id grp_id);\n\n/**\n * \\brief           This function frees a context.\n *\n * \\param ctx       The context to free. This may be \\c NULL, in which\n *                  case this function does nothing. If it is not \\c NULL,\n *                  it must point to an initialized ECDH context.\n */\nvoid mbedtls_ecdh_free(mbedtls_ecdh_context *ctx);\n\n/**\n * \\brief           This function generates an EC key pair and exports its\n *                  in the format used in a TLS ServerKeyExchange handshake\n *                  message.\n *\n *                  This is the second function used by a TLS server for ECDHE\n *                  ciphersuites. (It is called after mbedtls_ecdh_setup().)\n *\n * \\see             ecp.h\n *\n * \\param ctx       The ECDH context to use. This must be initialized\n *                  and bound to a group, for example via mbedtls_ecdh_setup().\n * \\param olen      The address at which to store the number of Bytes written.\n * \\param buf       The destination buffer. This must be a writable buffer of\n *                  length \\p blen Bytes.\n * \\param blen      The length of the destination buffer \\p buf in Bytes.\n * \\param f_rng     The RNG function to use. This must not be \\c NULL.\n * \\param p_rng     The RNG context to be passed to \\p f_rng. This may be\n *                  \\c NULL in case \\p f_rng doesn't need a context argument.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of\n *                  operations was reached: see \\c mbedtls_ecp_set_max_ops().\n * \\return          Another \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n */\nint mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen,\n                             unsigned char *buf, size_t blen,\n                             mbedtls_f_rng_t *f_rng,\n                             void *p_rng);\n\n/**\n * \\brief           This function parses the ECDHE parameters in a\n *                  TLS ServerKeyExchange handshake message.\n *\n * \\note            In a TLS handshake, this is the how the client\n *                  sets up its ECDHE context from the server's public\n *                  ECDHE key material.\n *\n * \\see             ecp.h\n *\n * \\param ctx       The ECDHE context to use. This must be initialized.\n * \\param buf       On input, \\c *buf must be the start of the input buffer.\n *                  On output, \\c *buf is updated to point to the end of the\n *                  data that has been read. On success, this is the first byte\n *                  past the end of the ServerKeyExchange parameters.\n *                  On error, this is the point at which an error has been\n *                  detected, which is usually not useful except to debug\n *                  failures.\n * \\param end       The end of the input buffer.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n *\n */\nint mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,\n                             const unsigned char **buf,\n                             const unsigned char *end);\n\n/**\n * \\brief           This function sets up an ECDH context from an EC key.\n *\n *                  It is used by clients and servers in place of the\n *                  ServerKeyExchange for static ECDH, and imports ECDH\n *                  parameters from the EC key information of a certificate.\n *\n * \\see             ecp.h\n *\n * \\param ctx       The ECDH context to set up. This must be initialized.\n * \\param key       The EC key to use. This must be initialized.\n * \\param side      Defines the source of the key. Possible values are:\n *                  - #MBEDTLS_ECDH_OURS: The key is ours.\n *                  - #MBEDTLS_ECDH_THEIRS: The key is that of the peer.\n *\n * \\return          \\c 0 on success.\n * \\return          Another \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n *\n */\nint mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx,\n                            const mbedtls_ecp_keypair *key,\n                            mbedtls_ecdh_side side);\n\n/**\n * \\brief           This function generates a public key and exports it\n *                  as a TLS ClientKeyExchange payload.\n *\n *                  This is the second function used by a TLS client for ECDH(E)\n *                  ciphersuites.\n *\n * \\see             ecp.h\n *\n * \\param ctx       The ECDH context to use. This must be initialized\n *                  and bound to a group, the latter usually by\n *                  mbedtls_ecdh_read_params().\n * \\param olen      The address at which to store the number of Bytes written.\n *                  This must not be \\c NULL.\n * \\param buf       The destination buffer. This must be a writable buffer\n *                  of length \\p blen Bytes.\n * \\param blen      The size of the destination buffer \\p buf in Bytes.\n * \\param f_rng     The RNG function to use. This must not be \\c NULL.\n * \\param p_rng     The RNG context to be passed to \\p f_rng. This may be\n *                  \\c NULL in case \\p f_rng doesn't need a context argument.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of\n *                  operations was reached: see \\c mbedtls_ecp_set_max_ops().\n * \\return          Another \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n */\nint mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen,\n                             unsigned char *buf, size_t blen,\n                             mbedtls_f_rng_t *f_rng,\n                             void *p_rng);\n\n/**\n * \\brief       This function parses and processes the ECDHE payload of a\n *              TLS ClientKeyExchange message.\n *\n *              This is the third function used by a TLS server for ECDH(E)\n *              ciphersuites. (It is called after mbedtls_ecdh_setup() and\n *              mbedtls_ecdh_make_params().)\n *\n * \\see         ecp.h\n *\n * \\param ctx   The ECDH context to use. This must be initialized\n *              and bound to a group, for example via mbedtls_ecdh_setup().\n * \\param buf   The pointer to the ClientKeyExchange payload. This must\n *              be a readable buffer of length \\p blen Bytes.\n * \\param blen  The length of the input buffer \\p buf in Bytes.\n *\n * \\return      \\c 0 on success.\n * \\return      An \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n */\nint mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx,\n                             const unsigned char *buf, size_t blen);\n\n/**\n * \\brief           This function derives and exports the shared secret.\n *\n *                  This is the last function used by both TLS client\n *                  and servers.\n *\n * \\note            If \\p f_rng is not NULL, it is used to implement\n *                  countermeasures against side-channel attacks.\n *                  For more information, see mbedtls_ecp_mul().\n *\n * \\see             ecp.h\n\n * \\param ctx       The ECDH context to use. This must be initialized\n *                  and have its own private key generated and the peer's\n *                  public key imported.\n * \\param olen      The address at which to store the total number of\n *                  Bytes written on success. This must not be \\c NULL.\n * \\param buf       The buffer to write the generated shared key to. This\n *                  must be a writable buffer of size \\p blen Bytes.\n * \\param blen      The length of the destination buffer \\p buf in Bytes.\n * \\param f_rng     The RNG function to use. This must not be \\c NULL.\n * \\param p_rng     The RNG context. This may be \\c NULL if \\p f_rng\n *                  doesn't need a context argument.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of\n *                  operations was reached: see \\c mbedtls_ecp_set_max_ops().\n * \\return          Another \\c MBEDTLS_ERR_ECP_XXX error code on failure.\n */\nint mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen,\n                             unsigned char *buf, size_t blen,\n                             mbedtls_f_rng_t *f_rng,\n                             void *p_rng);\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n/**\n * \\brief           This function enables restartable EC computations for this\n *                  context.  (Default: disabled.)\n *\n * \\see             \\c mbedtls_ecp_set_max_ops()\n *\n * \\note            It is not possible to safely disable restartable\n *                  computations once enabled, except by free-ing the context,\n *                  which cancels possible in-progress operations.\n *\n * \\param ctx       The ECDH context to use. This must be initialized.\n */\nvoid mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx);\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* ecdh.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/ecdsa.h",
    "content": "/**\n * \\file ecdsa.h\n *\n * \\brief This file contains ECDSA definitions and functions.\n *\n * The Elliptic Curve Digital Signature Algorithm (ECDSA) is defined in\n * <em>Standards for Efficient Cryptography Group (SECG):\n * SEC1 Elliptic Curve Cryptography</em>.\n * The use of ECDSA for TLS is defined in <em>RFC-4492: Elliptic Curve\n * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS)</em>.\n *\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_ECDSA_H\n#define MBEDTLS_ECDSA_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/ecp.h\"\n#include \"mbedtls/md.h\"\n\n/**\n * \\brief           Maximum ECDSA signature size for a given curve bit size\n *\n * \\param bits      Curve size in bits\n * \\return          Maximum signature size in bytes\n *\n * \\note            This macro returns a compile-time constant if its argument\n *                  is one. It may evaluate its argument multiple times.\n */\n/*\n *     Ecdsa-Sig-Value ::= SEQUENCE {\n *         r       INTEGER,\n *         s       INTEGER\n *     }\n *\n * For each of r and s, the value (V) may include an extra initial \"0\" bit.\n */\n#define MBEDTLS_ECDSA_MAX_SIG_LEN(bits)                               \\\n    (/*T,L of SEQUENCE*/ ((bits) >= 61 * 8 ? 3 : 2) +              \\\n     /*T,L of r,s*/ 2 * (((bits) >= 127 * 8 ? 3 : 2) +     \\\n                         /*V of r,s*/ ((bits) + 8) / 8))\n\n/** The maximal size of an ECDSA signature in Bytes. */\n#define MBEDTLS_ECDSA_MAX_LEN  MBEDTLS_ECDSA_MAX_SIG_LEN(MBEDTLS_ECP_MAX_BITS)\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief           The ECDSA context structure.\n *\n * \\warning         Performing multiple operations concurrently on the same\n *                  ECDSA context is not supported; objects of this type\n *                  should not be shared between multiple threads.\n *\n * \\note            pk_wrap module assumes that \"ecdsa_context\" is identical\n *                  to \"ecp_keypair\" (see for example structure\n *                  \"mbedtls_eckey_info\" where ECDSA sign/verify functions\n *                  are used also for EC key)\n */\ntypedef mbedtls_ecp_keypair mbedtls_ecdsa_context;\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n\n/**\n * \\brief           Internal restart context for ecdsa_verify()\n *\n * \\note            Opaque struct, defined in ecdsa.c\n */\ntypedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx;\n\n/**\n * \\brief           Internal restart context for ecdsa_sign()\n *\n * \\note            Opaque struct, defined in ecdsa.c\n */\ntypedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx;\n\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC)\n/**\n * \\brief           Internal restart context for ecdsa_sign_det()\n *\n * \\note            Opaque struct, defined in ecdsa.c\n */\ntypedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx;\n#endif\n\n/**\n * \\brief           General context for resuming ECDSA operations\n */\ntypedef struct {\n    mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(ecp);        /*!<  base context for ECP restart and\n                                                            shared administrative info    */\n    mbedtls_ecdsa_restart_ver_ctx *MBEDTLS_PRIVATE(ver); /*!<  ecdsa_verify() sub-context    */\n    mbedtls_ecdsa_restart_sig_ctx *MBEDTLS_PRIVATE(sig); /*!<  ecdsa_sign() sub-context      */\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC)\n    mbedtls_ecdsa_restart_det_ctx *MBEDTLS_PRIVATE(det); /*!<  ecdsa_sign_det() sub-context  */\n#endif\n} mbedtls_ecdsa_restart_ctx;\n\n#else /* MBEDTLS_ECP_RESTARTABLE */\n\n/* Now we can declare functions that take a pointer to that */\ntypedef void mbedtls_ecdsa_restart_ctx;\n\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n/**\n * \\brief          This function checks whether a given group can be used\n *                 for ECDSA.\n *\n * \\param gid      The ECP group ID to check.\n *\n * \\return         \\c 1 if the group can be used, \\c 0 otherwise\n */\nint mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid);\n\n/**\n * \\brief           This function computes the ECDSA signature of a\n *                  previously-hashed message.\n *\n * \\note            The deterministic version implemented in\n *                  mbedtls_ecdsa_sign_det_ext() is usually preferred.\n *\n * \\note            If the bitlength of the message hash is larger than the\n *                  bitlength of the group order, then the hash is truncated\n *                  as defined in <em>Standards for Efficient Cryptography Group\n *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section\n *                  4.1.3, step 5.\n *\n * \\see             ecp.h\n *\n * \\param grp       The context for the elliptic curve to use.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param r         The MPI context in which to store the first part\n *                  the signature. This must be initialized.\n * \\param s         The MPI context in which to store the second part\n *                  the signature. This must be initialized.\n * \\param d         The private signing key. This must be initialized.\n * \\param buf       The content to be signed. This is usually the hash of\n *                  the original data to be signed. This must be a readable\n *                  buffer of length \\p blen Bytes. It may be \\c NULL if\n *                  \\p blen is zero.\n * \\param blen      The length of \\p buf in Bytes.\n * \\param f_rng     The RNG function, used both to generate the ECDSA nonce\n *                  and for blinding. This must not be \\c NULL.\n * \\param p_rng     The RNG context to be passed to \\p f_rng. This may be\n *                  \\c NULL if \\p f_rng doesn't need a context parameter.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX\n *                  or \\c MBEDTLS_MPI_XXX error code on failure.\n */\nint mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,\n                       const mbedtls_mpi *d, const unsigned char *buf, size_t blen,\n                       mbedtls_f_rng_t *f_rng, void *p_rng);\n\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC)\n/**\n * \\brief           This function computes the ECDSA signature of a\n *                  previously-hashed message, deterministic version.\n *\n *                  For more information, see <em>RFC-6979: Deterministic\n *                  Usage of the Digital Signature Algorithm (DSA) and Elliptic\n *                  Curve Digital Signature Algorithm (ECDSA)</em>.\n *\n * \\note            If the bitlength of the message hash is larger than the\n *                  bitlength of the group order, then the hash is truncated as\n *                  defined in <em>Standards for Efficient Cryptography Group\n *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section\n *                  4.1.3, step 5.\n *\n * \\see             ecp.h\n *\n * \\param grp           The context for the elliptic curve to use.\n *                      This must be initialized and have group parameters\n *                      set, for example through mbedtls_ecp_group_load().\n * \\param r             The MPI context in which to store the first part\n *                      the signature. This must be initialized.\n * \\param s             The MPI context in which to store the second part\n *                      the signature. This must be initialized.\n * \\param d             The private signing key. This must be initialized\n *                      and setup, for example through mbedtls_ecp_gen_privkey().\n * \\param buf           The hashed content to be signed. This must be a readable\n *                      buffer of length \\p blen Bytes. It may be \\c NULL if\n *                      \\p blen is zero.\n * \\param blen          The length of \\p buf in Bytes.\n * \\param md_alg        The hash algorithm used to hash the original data.\n * \\param f_rng_blind   The RNG function used for blinding. This must not be\n *                      \\c NULL.\n * \\param p_rng_blind   The RNG context to be passed to \\p f_rng_blind. This\n *                      may be \\c NULL if \\p f_rng_blind doesn't need a context\n *                      parameter.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX or \\c MBEDTLS_MPI_XXX\n *                  error code on failure.\n */\nint mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r,\n                               mbedtls_mpi *s, const mbedtls_mpi *d,\n                               const unsigned char *buf, size_t blen,\n                               mbedtls_md_type_t md_alg,\n                               mbedtls_f_rng_t *f_rng_blind,\n                               void *p_rng_blind);\n#endif /* MBEDTLS_ECDSA_DETERMINISTIC */\n\n#if !defined(MBEDTLS_ECDSA_SIGN_ALT)\n/**\n * \\brief               This function computes the ECDSA signature of a\n *                      previously-hashed message, in a restartable way.\n *\n * \\note                The deterministic version implemented in\n *                      mbedtls_ecdsa_sign_det_restartable() is usually\n *                      preferred.\n *\n * \\note                This function is like \\c mbedtls_ecdsa_sign() but\n *                      it can return early and restart according to the\n *                      limit set with \\c mbedtls_ecp_set_max_ops() to\n *                      reduce blocking.\n *\n * \\note                If the bitlength of the message hash is larger\n *                      than the bitlength of the group order, then the\n *                      hash is truncated as defined in <em>Standards for\n *                      Efficient Cryptography Group (SECG): SEC1 Elliptic\n *                      Curve Cryptography</em>, section 4.1.3, step 5.\n *\n * \\see                 ecp.h\n *\n * \\param grp           The context for the elliptic curve to use.\n *                      This must be initialized and have group parameters\n *                      set, for example through mbedtls_ecp_group_load().\n * \\param r             The MPI context in which to store the first part\n *                      the signature. This must be initialized.\n * \\param s             The MPI context in which to store the second part\n *                      the signature. This must be initialized.\n * \\param d             The private signing key. This must be initialized\n *                      and setup, for example through\n *                      mbedtls_ecp_gen_privkey().\n * \\param buf           The hashed content to be signed. This must be a readable\n *                      buffer of length \\p blen Bytes. It may be \\c NULL if\n *                      \\p blen is zero.\n * \\param blen          The length of \\p buf in Bytes.\n * \\param f_rng         The RNG function used to generate the ECDSA nonce.\n *                      This must not be \\c NULL.\n * \\param p_rng         The RNG context to be passed to \\p f_rng. This may be\n *                      \\c NULL if \\p f_rng doesn't need a context parameter.\n * \\param f_rng_blind   The RNG function used for blinding. This must not be\n *                      \\c NULL.\n * \\param p_rng_blind   The RNG context to be passed to \\p f_rng. This may be\n *                      \\c NULL if \\p f_rng doesn't need a context parameter.\n * \\param rs_ctx        The restart context to use. This may be \\c NULL\n *                      to disable restarting. If it is not \\c NULL, it\n *                      must point to an initialized restart context.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of\n *                      operations was reached: see \\c\n *                      mbedtls_ecp_set_max_ops().\n * \\return              Another \\c MBEDTLS_ERR_ECP_XXX, \\c\n *                      MBEDTLS_ERR_MPI_XXX or \\c MBEDTLS_ERR_ASN1_XXX\n *                      error code on failure.\n */\nint mbedtls_ecdsa_sign_restartable(\n    mbedtls_ecp_group *grp,\n    mbedtls_mpi *r, mbedtls_mpi *s,\n    const mbedtls_mpi *d,\n    const unsigned char *buf, size_t blen,\n    mbedtls_f_rng_t *f_rng,\n    void *p_rng,\n    mbedtls_f_rng_t *f_rng_blind,\n    void *p_rng_blind,\n    mbedtls_ecdsa_restart_ctx *rs_ctx);\n\n#endif /* !MBEDTLS_ECDSA_SIGN_ALT */\n\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC)\n\n/**\n * \\brief               This function computes the ECDSA signature of a\n *                      previously-hashed message, in a restartable way.\n *\n * \\note                This function is like \\c\n *                      mbedtls_ecdsa_sign_det_ext() but it can return\n *                      early and restart according to the limit set with\n *                      \\c mbedtls_ecp_set_max_ops() to reduce blocking.\n *\n * \\note                If the bitlength of the message hash is larger\n *                      than the bitlength of the group order, then the\n *                      hash is truncated as defined in <em>Standards for\n *                      Efficient Cryptography Group (SECG): SEC1 Elliptic\n *                      Curve Cryptography</em>, section 4.1.3, step 5.\n *\n * \\see                 ecp.h\n *\n * \\param grp           The context for the elliptic curve to use.\n *                      This must be initialized and have group parameters\n *                      set, for example through mbedtls_ecp_group_load().\n * \\param r             The MPI context in which to store the first part\n *                      the signature. This must be initialized.\n * \\param s             The MPI context in which to store the second part\n *                      the signature. This must be initialized.\n * \\param d             The private signing key. This must be initialized\n *                      and setup, for example through\n *                      mbedtls_ecp_gen_privkey().\n * \\param buf           The hashed content to be signed. This must be a readable\n *                      buffer of length \\p blen Bytes. It may be \\c NULL if\n *                      \\p blen is zero.\n * \\param blen          The length of \\p buf in Bytes.\n * \\param md_alg        The hash algorithm used to hash the original data.\n * \\param f_rng_blind   The RNG function used for blinding. This must not be\n *                      \\c NULL.\n * \\param p_rng_blind   The RNG context to be passed to \\p f_rng_blind. This may be\n *                      \\c NULL if \\p f_rng_blind doesn't need a context parameter.\n * \\param rs_ctx        The restart context to use. This may be \\c NULL\n *                      to disable restarting. If it is not \\c NULL, it\n *                      must point to an initialized restart context.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of\n *                      operations was reached: see \\c\n *                      mbedtls_ecp_set_max_ops().\n * \\return              Another \\c MBEDTLS_ERR_ECP_XXX, \\c\n *                      MBEDTLS_ERR_MPI_XXX or \\c MBEDTLS_ERR_ASN1_XXX\n *                      error code on failure.\n */\nint mbedtls_ecdsa_sign_det_restartable(\n    mbedtls_ecp_group *grp,\n    mbedtls_mpi *r, mbedtls_mpi *s,\n    const mbedtls_mpi *d, const unsigned char *buf, size_t blen,\n    mbedtls_md_type_t md_alg,\n    mbedtls_f_rng_t *f_rng_blind,\n    void *p_rng_blind,\n    mbedtls_ecdsa_restart_ctx *rs_ctx);\n\n#endif /* MBEDTLS_ECDSA_DETERMINISTIC */\n\n/**\n * \\brief           This function verifies the ECDSA signature of a\n *                  previously-hashed message.\n *\n * \\note            If the bitlength of the message hash is larger than the\n *                  bitlength of the group order, then the hash is truncated as\n *                  defined in <em>Standards for Efficient Cryptography Group\n *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section\n *                  4.1.4, step 3.\n *\n * \\see             ecp.h\n *\n * \\param grp       The ECP group to use.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param buf       The hashed content that was signed. This must be a readable\n *                  buffer of length \\p blen Bytes. It may be \\c NULL if\n *                  \\p blen is zero.\n * \\param blen      The length of \\p buf in Bytes.\n * \\param Q         The public key to use for verification. This must be\n *                  initialized and setup.\n * \\param r         The first integer of the signature.\n *                  This must be initialized.\n * \\param s         The second integer of the signature.\n *                  This must be initialized.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX or \\c MBEDTLS_MPI_XXX\n *                  error code on failure.\n */\nint mbedtls_ecdsa_verify(mbedtls_ecp_group *grp,\n                         const unsigned char *buf, size_t blen,\n                         const mbedtls_ecp_point *Q, const mbedtls_mpi *r,\n                         const mbedtls_mpi *s);\n\n#if !defined(MBEDTLS_ECDSA_VERIFY_ALT)\n/**\n * \\brief           This function verifies the ECDSA signature of a\n *                  previously-hashed message, in a restartable manner\n *\n * \\note            If the bitlength of the message hash is larger than the\n *                  bitlength of the group order, then the hash is truncated as\n *                  defined in <em>Standards for Efficient Cryptography Group\n *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section\n *                  4.1.4, step 3.\n *\n * \\see             ecp.h\n *\n * \\param grp       The ECP group to use.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param buf       The hashed content that was signed. This must be a readable\n *                  buffer of length \\p blen Bytes. It may be \\c NULL if\n *                  \\p blen is zero.\n * \\param blen      The length of \\p buf in Bytes.\n * \\param Q         The public key to use for verification. This must be\n *                  initialized and setup.\n * \\param r         The first integer of the signature.\n *                  This must be initialized.\n * \\param s         The second integer of the signature.\n *                  This must be initialized.\n * \\param rs_ctx    The restart context to use. This may be \\c NULL to disable\n *                  restarting. If it is not \\c NULL, it must point to an\n *                  initialized restart context.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of\n *                  operations was reached: see \\c mbedtls_ecp_set_max_ops().\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX or \\c MBEDTLS_MPI_XXX\n *                  error code on failure.\n */\nint mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp,\n                                     const unsigned char *buf, size_t blen,\n                                     const mbedtls_ecp_point *Q,\n                                     const mbedtls_mpi *r,\n                                     const mbedtls_mpi *s,\n                                     mbedtls_ecdsa_restart_ctx *rs_ctx);\n\n#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */\n\n/**\n * \\brief           This function computes the ECDSA signature and writes it\n *                  to a buffer, serialized as defined in <em>RFC-4492:\n *                  Elliptic Curve Cryptography (ECC) Cipher Suites for\n *                  Transport Layer Security (TLS)</em>.\n *\n * \\warning         It is not thread-safe to use the same context in\n *                  multiple threads.\n *\n * \\note            The deterministic version is used if\n *                  #MBEDTLS_ECDSA_DETERMINISTIC is defined. For more\n *                  information, see <em>RFC-6979: Deterministic Usage\n *                  of the Digital Signature Algorithm (DSA) and Elliptic\n *                  Curve Digital Signature Algorithm (ECDSA)</em>.\n *\n * \\note            If the bitlength of the message hash is larger than the\n *                  bitlength of the group order, then the hash is truncated as\n *                  defined in <em>Standards for Efficient Cryptography Group\n *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section\n *                  4.1.3, step 5.\n *\n * \\see             ecp.h\n *\n * \\param ctx       The ECDSA context to use. This must be initialized\n *                  and have a group and private key bound to it, for example\n *                  via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair().\n * \\param md_alg    The message digest that was used to hash the message.\n * \\param hash      The message hash to be signed. This must be a readable\n *                  buffer of length \\p hlen Bytes.\n * \\param hlen      The length of the hash \\p hash in Bytes.\n * \\param sig       The buffer to which to write the signature. This must be a\n *                  writable buffer of length at least twice as large as the\n *                  size of the curve used, plus 9. For example, 73 Bytes if\n *                  a 256-bit curve is used. A buffer length of\n *                  #MBEDTLS_ECDSA_MAX_LEN is always safe.\n * \\param sig_size  The size of the \\p sig buffer in bytes.\n * \\param slen      The address at which to store the actual length of\n *                  the signature written. Must not be \\c NULL.\n * \\param f_rng     The RNG function. This is used for blinding.\n *                  If #MBEDTLS_ECDSA_DETERMINISTIC is unset, this is also\n *                  used to generate the ECDSA nonce.\n *                  This must not be \\c NULL.\n * \\param p_rng     The RNG context to be passed to \\p f_rng. This may be\n *                  \\c NULL if \\p f_rng is \\c NULL or doesn't use a context.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX, \\c MBEDTLS_ERR_MPI_XXX or\n *                  \\c MBEDTLS_ERR_ASN1_XXX error code on failure.\n */\nint mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx,\n                                  mbedtls_md_type_t md_alg,\n                                  const unsigned char *hash, size_t hlen,\n                                  unsigned char *sig, size_t sig_size, size_t *slen,\n                                  mbedtls_f_rng_t *f_rng,\n                                  void *p_rng);\n\n/**\n * \\brief           This function computes the ECDSA signature and writes it\n *                  to a buffer, in a restartable way.\n *\n * \\see             \\c mbedtls_ecdsa_write_signature()\n *\n * \\note            This function is like \\c mbedtls_ecdsa_write_signature()\n *                  but it can return early and restart according to the limit\n *                  set with \\c mbedtls_ecp_set_max_ops() to reduce blocking.\n *\n * \\param ctx       The ECDSA context to use. This must be initialized\n *                  and have a group and private key bound to it, for example\n *                  via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair().\n * \\param md_alg    The message digest that was used to hash the message.\n * \\param hash      The message hash to be signed. This must be a readable\n *                  buffer of length \\p hlen Bytes.\n * \\param hlen      The length of the hash \\p hash in Bytes.\n * \\param sig       The buffer to which to write the signature. This must be a\n *                  writable buffer of length at least twice as large as the\n *                  size of the curve used, plus 9. For example, 73 Bytes if\n *                  a 256-bit curve is used. A buffer length of\n *                  #MBEDTLS_ECDSA_MAX_LEN is always safe.\n * \\param sig_size  The size of the \\p sig buffer in bytes.\n * \\param slen      The address at which to store the actual length of\n *                  the signature written. Must not be \\c NULL.\n * \\param f_rng     The RNG function. This is used for blinding.\n *                  If #MBEDTLS_ECDSA_DETERMINISTIC is unset, this is also\n *                  used to generate the ECDSA nonce.\n *                  This must not be \\c NULL.\n * \\param p_rng     The RNG context to be passed to \\p f_rng. This may be\n *                  \\c NULL if \\p f_rng is \\c NULL or doesn't use a context.\n * \\param rs_ctx    The restart context to use. This may be \\c NULL to disable\n *                  restarting. If it is not \\c NULL, it must point to an\n *                  initialized restart context.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of\n *                  operations was reached: see \\c mbedtls_ecp_set_max_ops().\n * \\return          Another \\c MBEDTLS_ERR_ECP_XXX, \\c MBEDTLS_ERR_MPI_XXX or\n *                  \\c MBEDTLS_ERR_ASN1_XXX error code on failure.\n */\nint mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx,\n                                              mbedtls_md_type_t md_alg,\n                                              const unsigned char *hash, size_t hlen,\n                                              unsigned char *sig, size_t sig_size, size_t *slen,\n                                              mbedtls_f_rng_t *f_rng,\n                                              void *p_rng,\n                                              mbedtls_ecdsa_restart_ctx *rs_ctx);\n\n/**\n * \\brief           This function reads and verifies an ECDSA signature.\n *\n * \\note            If the bitlength of the message hash is larger than the\n *                  bitlength of the group order, then the hash is truncated as\n *                  defined in <em>Standards for Efficient Cryptography Group\n *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section\n *                  4.1.4, step 3.\n *\n * \\see             ecp.h\n *\n * \\param ctx       The ECDSA context to use. This must be initialized\n *                  and have a group and public key bound to it.\n * \\param hash      The message hash that was signed. This must be a readable\n *                  buffer of length \\p hlen Bytes.\n * \\param hlen      The size of the hash \\p hash.\n * \\param sig       The signature to read and verify. This must be a readable\n *                  buffer of length \\p slen Bytes.\n * \\param slen      The size of \\p sig in Bytes.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid.\n * \\return          #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid\n *                  signature in \\p sig, but its length is less than \\p siglen.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX or \\c MBEDTLS_ERR_MPI_XXX\n *                  error code on failure for any other reason.\n */\nint mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx,\n                                 const unsigned char *hash, size_t hlen,\n                                 const unsigned char *sig, size_t slen);\n\n/**\n * \\brief           This function reads and verifies an ECDSA signature,\n *                  in a restartable way.\n *\n * \\see             \\c mbedtls_ecdsa_read_signature()\n *\n * \\note            This function is like \\c mbedtls_ecdsa_read_signature()\n *                  but it can return early and restart according to the limit\n *                  set with \\c mbedtls_ecp_set_max_ops() to reduce blocking.\n *\n * \\param ctx       The ECDSA context to use. This must be initialized\n *                  and have a group and public key bound to it.\n * \\param hash      The message hash that was signed. This must be a readable\n *                  buffer of length \\p hlen Bytes.\n * \\param hlen      The size of the hash \\p hash.\n * \\param sig       The signature to read and verify. This must be a readable\n *                  buffer of length \\p slen Bytes.\n * \\param slen      The size of \\p sig in Bytes.\n * \\param rs_ctx    The restart context to use. This may be \\c NULL to disable\n *                  restarting. If it is not \\c NULL, it must point to an\n *                  initialized restart context.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid.\n * \\return          #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid\n *                  signature in \\p sig, but its length is less than \\p siglen.\n * \\return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of\n *                  operations was reached: see \\c mbedtls_ecp_set_max_ops().\n * \\return          Another \\c MBEDTLS_ERR_ECP_XXX or \\c MBEDTLS_ERR_MPI_XXX\n *                  error code on failure for any other reason.\n */\nint mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx,\n                                             const unsigned char *hash, size_t hlen,\n                                             const unsigned char *sig, size_t slen,\n                                             mbedtls_ecdsa_restart_ctx *rs_ctx);\n\n/**\n * \\brief          This function generates an ECDSA keypair on the given curve.\n *\n * \\see            ecp.h\n *\n * \\param ctx      The ECDSA context to store the keypair in.\n *                 This must be initialized.\n * \\param gid      The elliptic curve to use. One of the various\n *                 \\c MBEDTLS_ECP_DP_XXX macros depending on configuration.\n * \\param f_rng    The RNG function to use. This must not be \\c NULL.\n * \\param p_rng    The RNG context to be passed to \\p f_rng. This may be\n *                 \\c NULL if \\p f_rng doesn't need a context argument.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_ECP_XXX code on failure.\n */\nint mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,\n                         mbedtls_f_rng_t *f_rng, void *p_rng);\n\n/**\n * \\brief           This function sets up an ECDSA context from an EC key pair.\n *\n * \\see             ecp.h\n *\n * \\param ctx       The ECDSA context to setup. This must be initialized.\n * \\param key       The EC key to use. This must be initialized and hold\n *                  a private-public key pair or a public key. In the former\n *                  case, the ECDSA context may be used for signature creation\n *                  and verification after this call. In the latter case, it\n *                  may be used for signature verification.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX code on failure.\n */\nint mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx,\n                               const mbedtls_ecp_keypair *key);\n\n/**\n * \\brief           This function initializes an ECDSA context.\n *\n * \\param ctx       The ECDSA context to initialize.\n *                  This must not be \\c NULL.\n */\nvoid mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx);\n\n/**\n * \\brief           This function frees an ECDSA context.\n *\n * \\param ctx       The ECDSA context to free. This may be \\c NULL,\n *                  in which case this function does nothing. If it\n *                  is not \\c NULL, it must be initialized.\n */\nvoid mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx);\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n/**\n * \\brief           Initialize a restart context.\n *\n * \\param ctx       The restart context to initialize.\n *                  This must not be \\c NULL.\n */\nvoid mbedtls_ecdsa_restart_init(mbedtls_ecdsa_restart_ctx *ctx);\n\n/**\n * \\brief           Free the components of a restart context.\n *\n * \\param ctx       The restart context to free. This may be \\c NULL,\n *                  in which case this function does nothing. If it\n *                  is not \\c NULL, it must be initialized.\n */\nvoid mbedtls_ecdsa_restart_free(mbedtls_ecdsa_restart_ctx *ctx);\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* ecdsa.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/ecjpake.h",
    "content": "/**\n * \\file ecjpake.h\n *\n * \\brief Elliptic curve J-PAKE\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_ECJPAKE_H\n#define MBEDTLS_ECJPAKE_H\n#include \"mbedtls/private_access.h\"\n\n/*\n * J-PAKE is a password-authenticated key exchange that allows deriving a\n * strong shared secret from a (potentially low entropy) pre-shared\n * passphrase, with forward secrecy and mutual authentication.\n * https://en.wikipedia.org/wiki/Password_Authenticated_Key_Exchange_by_Juggling\n *\n * This file implements the Elliptic Curve variant of J-PAKE,\n * as defined in Chapter 7.4 of the Thread v1.0 Specification,\n * available to members of the Thread Group http://threadgroup.org/\n *\n * As the J-PAKE algorithm is inherently symmetric, so is our API.\n * Each party needs to send its first round message, in any order, to the\n * other party, then each sends its second round message, in any order.\n * The payloads are serialized in a way suitable for use in TLS, but could\n * also be use outside TLS.\n */\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/ecp.h\"\n#include \"mbedtls/md.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Roles in the EC J-PAKE exchange\n */\ntypedef enum {\n    MBEDTLS_ECJPAKE_CLIENT = 0,         /**< Client                         */\n    MBEDTLS_ECJPAKE_SERVER,             /**< Server                         */\n    MBEDTLS_ECJPAKE_NONE,               /**< Undefined                      */\n} mbedtls_ecjpake_role;\n\n#if !defined(MBEDTLS_ECJPAKE_ALT)\n/**\n * EC J-PAKE context structure.\n *\n * J-PAKE is a symmetric protocol, except for the identifiers used in\n * Zero-Knowledge Proofs, and the serialization of the second message\n * (KeyExchange) as defined by the Thread spec.\n *\n * In order to benefit from this symmetry, we choose a different naming\n * convention from the Thread v1.0 spec. Correspondence is indicated in the\n * description as a pair C: client name, S: server name\n */\ntypedef struct mbedtls_ecjpake_context {\n    mbedtls_md_type_t MBEDTLS_PRIVATE(md_type);          /**< Hash to use                    */\n    mbedtls_ecp_group MBEDTLS_PRIVATE(grp);              /**< Elliptic curve                 */\n    mbedtls_ecjpake_role MBEDTLS_PRIVATE(role);          /**< Are we client or server?       */\n    int MBEDTLS_PRIVATE(point_format);                   /**< Format for point export        */\n\n    mbedtls_ecp_point MBEDTLS_PRIVATE(Xm1);              /**< My public key 1   C: X1, S: X3 */\n    mbedtls_ecp_point MBEDTLS_PRIVATE(Xm2);              /**< My public key 2   C: X2, S: X4 */\n    mbedtls_ecp_point MBEDTLS_PRIVATE(Xp1);              /**< Peer public key 1 C: X3, S: X1 */\n    mbedtls_ecp_point MBEDTLS_PRIVATE(Xp2);              /**< Peer public key 2 C: X4, S: X2 */\n    mbedtls_ecp_point MBEDTLS_PRIVATE(Xp);               /**< Peer public key   C: Xs, S: Xc */\n\n    mbedtls_mpi MBEDTLS_PRIVATE(xm1);                    /**< My private key 1  C: x1, S: x3 */\n    mbedtls_mpi MBEDTLS_PRIVATE(xm2);                    /**< My private key 2  C: x2, S: x4 */\n\n    mbedtls_mpi MBEDTLS_PRIVATE(s);                      /**< Pre-shared secret (passphrase) */\n} mbedtls_ecjpake_context;\n\n#else  /* MBEDTLS_ECJPAKE_ALT */\n#include \"ecjpake_alt.h\"\n#endif /* MBEDTLS_ECJPAKE_ALT */\n\n/**\n * \\brief           Initialize an ECJPAKE context.\n *\n * \\param ctx       The ECJPAKE context to initialize.\n *                  This must not be \\c NULL.\n */\nvoid mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx);\n\n/**\n * \\brief           Set up an ECJPAKE context for use.\n *\n * \\note            Currently the only values for hash/curve allowed by the\n *                  standard are #MBEDTLS_MD_SHA256/#MBEDTLS_ECP_DP_SECP256R1.\n *\n * \\param ctx       The ECJPAKE context to set up. This must be initialized.\n * \\param role      The role of the caller. This must be either\n *                  #MBEDTLS_ECJPAKE_CLIENT or #MBEDTLS_ECJPAKE_SERVER.\n * \\param hash      The identifier of the hash function to use,\n *                  for example #MBEDTLS_MD_SHA256.\n * \\param curve     The identifier of the elliptic curve to use,\n *                  for example #MBEDTLS_ECP_DP_SECP256R1.\n * \\param secret    The pre-shared secret (passphrase). This must be\n *                  a readable not empty buffer of length \\p len Bytes. It need\n *                  only be valid for the duration of this call.\n * \\param len       The length of the pre-shared secret \\p secret.\n *\n * \\return          \\c 0 if successful.\n * \\return          A negative error code on failure.\n */\nint mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,\n                          mbedtls_ecjpake_role role,\n                          mbedtls_md_type_t hash,\n                          mbedtls_ecp_group_id curve,\n                          const unsigned char *secret,\n                          size_t len);\n\n/**\n * \\brief               Set the point format for future reads and writes.\n *\n * \\param ctx           The ECJPAKE context to configure.\n * \\param point_format  The point format to use:\n *                      #MBEDTLS_ECP_PF_UNCOMPRESSED (default)\n *                      or #MBEDTLS_ECP_PF_COMPRESSED.\n *\n * \\return              \\c 0 if successful.\n * \\return              #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \\p point_format\n *                      is invalid.\n */\nint mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,\n                                     int point_format);\n\n/**\n * \\brief           Check if an ECJPAKE context is ready for use.\n *\n * \\param ctx       The ECJPAKE context to check. This must be\n *                  initialized.\n *\n * \\return          \\c 0 if the context is ready for use.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise.\n */\nint mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx);\n\n/**\n * \\brief           Generate and write the first round message\n *                  (TLS: contents of the Client/ServerHello extension,\n *                  excluding extension type and length bytes).\n *\n * \\param ctx       The ECJPAKE context to use. This must be\n *                  initialized and set up.\n * \\param buf       The buffer to write the contents to. This must be a\n *                  writable buffer of length \\p len Bytes.\n * \\param len       The length of \\p buf in Bytes.\n * \\param olen      The address at which to store the total number\n *                  of Bytes written to \\p buf. This must not be \\c NULL.\n * \\param f_rng     The RNG function to use. This must not be \\c NULL.\n * \\param p_rng     The RNG parameter to be passed to \\p f_rng. This\n *                  may be \\c NULL if \\p f_rng doesn't use a context.\n *\n * \\return          \\c 0 if successful.\n * \\return          A negative error code on failure.\n */\nint mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,\n                                    unsigned char *buf, size_t len, size_t *olen,\n                                    mbedtls_f_rng_t *f_rng,\n                                    void *p_rng);\n\n/**\n * \\brief           Read and process the first round message\n *                  (TLS: contents of the Client/ServerHello extension,\n *                  excluding extension type and length bytes).\n *\n * \\param ctx       The ECJPAKE context to use. This must be initialized\n *                  and set up.\n * \\param buf       The buffer holding the first round message. This must\n *                  be a readable buffer of length \\p len Bytes.\n * \\param len       The length in Bytes of \\p buf.\n *\n * \\return          \\c 0 if successful.\n * \\return          A negative error code on failure.\n */\nint mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,\n                                   const unsigned char *buf,\n                                   size_t len);\n\n/**\n * \\brief           Generate and write the second round message\n *                  (TLS: contents of the Client/ServerKeyExchange).\n *\n * \\param ctx       The ECJPAKE context to use. This must be initialized,\n *                  set up, and already have performed round one.\n * \\param buf       The buffer to write the round two contents to.\n *                  This must be a writable buffer of length \\p len Bytes.\n * \\param len       The size of \\p buf in Bytes.\n * \\param olen      The address at which to store the total number of Bytes\n *                  written to \\p buf. This must not be \\c NULL.\n * \\param f_rng     The RNG function to use. This must not be \\c NULL.\n * \\param p_rng     The RNG parameter to be passed to \\p f_rng. This\n *                  may be \\c NULL if \\p f_rng doesn't use a context.\n *\n * \\return          \\c 0 if successful.\n * \\return          A negative error code on failure.\n */\nint mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,\n                                    unsigned char *buf, size_t len, size_t *olen,\n                                    mbedtls_f_rng_t *f_rng,\n                                    void *p_rng);\n\n/**\n * \\brief           Read and process the second round message\n *                  (TLS: contents of the Client/ServerKeyExchange).\n *\n * \\param ctx       The ECJPAKE context to use. This must be initialized\n *                  and set up and already have performed round one.\n * \\param buf       The buffer holding the second round message. This must\n *                  be a readable buffer of length \\p len Bytes.\n * \\param len       The length in Bytes of \\p buf.\n *\n * \\return          \\c 0 if successful.\n * \\return          A negative error code on failure.\n */\nint mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,\n                                   const unsigned char *buf,\n                                   size_t len);\n\n/**\n * \\brief           Derive the shared secret\n *                  (TLS: Pre-Master Secret).\n *\n * \\param ctx       The ECJPAKE context to use. This must be initialized,\n *                  set up and have performed both round one and two.\n * \\param buf       The buffer to write the derived secret to. This must\n *                  be a writable buffer of length \\p len Bytes.\n * \\param len       The length of \\p buf in Bytes.\n * \\param olen      The address at which to store the total number of Bytes\n *                  written to \\p buf. This must not be \\c NULL.\n * \\param f_rng     The RNG function to use. This must not be \\c NULL.\n * \\param p_rng     The RNG parameter to be passed to \\p f_rng. This\n *                  may be \\c NULL if \\p f_rng doesn't use a context.\n *\n * \\return          \\c 0 if successful.\n * \\return          A negative error code on failure.\n */\nint mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,\n                                  unsigned char *buf, size_t len, size_t *olen,\n                                  mbedtls_f_rng_t *f_rng,\n                                  void *p_rng);\n\n/**\n * \\brief           Write the shared key material to be passed to a Key\n *                  Derivation Function as described in RFC8236.\n *\n * \\param ctx       The ECJPAKE context to use. This must be initialized,\n *                  set up and have performed both round one and two.\n * \\param buf       The buffer to write the derived secret to. This must\n *                  be a writable buffer of length \\p len Bytes.\n * \\param len       The length of \\p buf in Bytes.\n * \\param olen      The address at which to store the total number of bytes\n *                  written to \\p buf. This must not be \\c NULL.\n * \\param f_rng     The RNG function to use. This must not be \\c NULL.\n * \\param p_rng     The RNG parameter to be passed to \\p f_rng. This\n *                  may be \\c NULL if \\p f_rng doesn't use a context.\n *\n * \\return          \\c 0 if successful.\n * \\return          A negative error code on failure.\n */\nint mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx,\n                                     unsigned char *buf, size_t len, size_t *olen,\n                                     mbedtls_f_rng_t *f_rng,\n                                     void *p_rng);\n\n/**\n * \\brief           This clears an ECJPAKE context and frees any\n *                  embedded data structure.\n *\n * \\param ctx       The ECJPAKE context to free. This may be \\c NULL,\n *                  in which case this function does nothing. If it is not\n *                  \\c NULL, it must point to an initialized ECJPAKE context.\n */\nvoid mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx);\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/**\n * \\brief          Checkup routine\n *\n * \\return         0 if successful, or 1 if a test failed\n */\nint mbedtls_ecjpake_self_test(int verbose);\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n\n#endif /* ecjpake.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/ecp.h",
    "content": "/**\n * \\file ecp.h\n *\n * \\brief This file provides an API for Elliptic Curves over GF(P) (ECP).\n *\n * The use of ECP in cryptography and TLS is defined in\n * <em>Standards for Efficient Cryptography Group (SECG): SEC1\n * Elliptic Curve Cryptography</em> and\n * <em>RFC-4492: Elliptic Curve Cryptography (ECC) Cipher Suites\n * for Transport Layer Security (TLS)</em>.\n *\n * <em>RFC-2409: The Internet Key Exchange (IKE)</em> defines ECP\n * group types.\n *\n */\n\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_ECP_H\n#define MBEDTLS_ECP_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include \"mbedtls/bignum.h\"\n\n/*\n * ECP error codes\n */\n/** Bad input parameters to function. */\n#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA                    -0x4F80\n/** The buffer is too small to write to. */\n#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL                  -0x4F00\n/** The requested feature is not available, for example, the requested curve is not supported. */\n#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE               -0x4E80\n/** The signature is not valid. */\n#define MBEDTLS_ERR_ECP_VERIFY_FAILED                     -0x4E00\n/** Memory allocation failed. */\n#define MBEDTLS_ERR_ECP_ALLOC_FAILED                      -0x4D80\n/** Generation of random value, such as ephemeral key, failed. */\n#define MBEDTLS_ERR_ECP_RANDOM_FAILED                     -0x4D00\n/** Invalid private or public key. */\n#define MBEDTLS_ERR_ECP_INVALID_KEY                       -0x4C80\n/** The buffer contains a valid signature followed by more data. */\n#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH                  -0x4C00\n/** Operation in progress, call again with the same parameters to continue. */\n#define MBEDTLS_ERR_ECP_IN_PROGRESS                       -0x4B00\n\n/* Flags indicating whether to include code that is specific to certain\n * types of curves. These flags are for internal library use only. */\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \\\n    defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \\\n    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \\\n    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \\\n    defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \\\n    defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \\\n    defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \\\n    defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \\\n    defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \\\n    defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \\\n    defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n#define MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED\n#endif\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \\\n    defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n#define MBEDTLS_ECP_MONTGOMERY_ENABLED\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Domain-parameter identifiers: curve, subgroup, and generator.\n *\n * \\note Only curves over prime fields are supported.\n *\n * \\warning This library does not support validation of arbitrary domain\n * parameters. Therefore, only standardized domain parameters from trusted\n * sources should be used. See mbedtls_ecp_group_load().\n */\n/* Note: when adding a new curve:\n * - Add it at the end of this enum, otherwise you'll break the ABI by\n *   changing the numerical value for existing curves.\n * - Increment MBEDTLS_ECP_DP_MAX below if needed.\n * - Update the calculation of MBEDTLS_ECP_MAX_BITS below.\n * - Add the corresponding MBEDTLS_ECP_DP_xxx_ENABLED macro definition to\n *   mbedtls_config.h.\n * - List the curve as a dependency of MBEDTLS_ECP_C and\n *   MBEDTLS_ECDSA_C if supported in check_config.h.\n * - Add the curve to the appropriate curve type macro\n *   MBEDTLS_ECP_yyy_ENABLED above.\n * - Add the necessary definitions to ecp_curves.c.\n * - Add the curve to the ecp_supported_curves array in ecp.c.\n * - Add the curve to applicable profiles in x509_crt.c.\n * - Add the curve to applicable presets in ssl_tls.c.\n */\ntypedef enum {\n    MBEDTLS_ECP_DP_NONE = 0,       /*!< Curve not defined. */\n    MBEDTLS_ECP_DP_SECP192R1,      /*!< Domain parameters for the 192-bit curve defined by FIPS 186-4 and SEC1. */\n    MBEDTLS_ECP_DP_SECP224R1,      /*!< Domain parameters for the 224-bit curve defined by FIPS 186-4 and SEC1. */\n    MBEDTLS_ECP_DP_SECP256R1,      /*!< Domain parameters for the 256-bit curve defined by FIPS 186-4 and SEC1. */\n    MBEDTLS_ECP_DP_SECP384R1,      /*!< Domain parameters for the 384-bit curve defined by FIPS 186-4 and SEC1. */\n    MBEDTLS_ECP_DP_SECP521R1,      /*!< Domain parameters for the 521-bit curve defined by FIPS 186-4 and SEC1. */\n    MBEDTLS_ECP_DP_BP256R1,        /*!< Domain parameters for 256-bit Brainpool curve. */\n    MBEDTLS_ECP_DP_BP384R1,        /*!< Domain parameters for 384-bit Brainpool curve. */\n    MBEDTLS_ECP_DP_BP512R1,        /*!< Domain parameters for 512-bit Brainpool curve. */\n    MBEDTLS_ECP_DP_CURVE25519,     /*!< Domain parameters for Curve25519. */\n    MBEDTLS_ECP_DP_SECP192K1,      /*!< Domain parameters for 192-bit \"Koblitz\" curve. */\n    MBEDTLS_ECP_DP_SECP224K1,      /*!< Domain parameters for 224-bit \"Koblitz\" curve. */\n    MBEDTLS_ECP_DP_SECP256K1,      /*!< Domain parameters for 256-bit \"Koblitz\" curve. */\n    MBEDTLS_ECP_DP_CURVE448,       /*!< Domain parameters for Curve448. */\n} mbedtls_ecp_group_id;\n\n/**\n * The number of supported curves, plus one for #MBEDTLS_ECP_DP_NONE.\n */\n#define MBEDTLS_ECP_DP_MAX     14\n\n/*\n * Curve types\n */\ntypedef enum {\n    MBEDTLS_ECP_TYPE_NONE = 0,\n    MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS,    /* y^2 = x^3 + a x + b      */\n    MBEDTLS_ECP_TYPE_MONTGOMERY,           /* y^2 = x^3 + a x^2 + x    */\n} mbedtls_ecp_curve_type;\n\n/**\n * Curve information, for use by other modules.\n *\n * The fields of this structure are part of the public API and can be\n * accessed directly by applications. Future versions of the library may\n * add extra fields or reorder existing fields.\n */\ntypedef struct mbedtls_ecp_curve_info {\n    mbedtls_ecp_group_id grp_id;    /*!< An internal identifier. */\n    uint16_t tls_id;                /*!< The TLS NamedCurve identifier. */\n    uint16_t bit_size;              /*!< The curve size in bits. */\n    const char *name;               /*!< A human-friendly name. */\n} mbedtls_ecp_curve_info;\n\n/**\n * \\brief           The ECP point structure, in Jacobian coordinates.\n *\n * \\note            All functions expect and return points satisfying\n *                  the following condition: <code>Z == 0</code> or\n *                  <code>Z == 1</code>. Other values of \\p Z are\n *                  used only by internal functions.\n *                  The point is zero, or \"at infinity\", if <code>Z == 0</code>.\n *                  Otherwise, \\p X and \\p Y are its standard (affine)\n *                  coordinates.\n */\ntypedef struct mbedtls_ecp_point {\n    mbedtls_mpi MBEDTLS_PRIVATE(X);          /*!< The X coordinate of the ECP point. */\n    mbedtls_mpi MBEDTLS_PRIVATE(Y);          /*!< The Y coordinate of the ECP point. */\n    mbedtls_mpi MBEDTLS_PRIVATE(Z);          /*!< The Z coordinate of the ECP point. */\n}\nmbedtls_ecp_point;\n\n#if !defined(MBEDTLS_ECP_ALT)\n/*\n * default Mbed TLS elliptic curve arithmetic implementation\n *\n * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an\n * alternative implementation for the whole module and it will replace this\n * one.)\n */\n\n/**\n * \\brief           The ECP group structure.\n *\n * We consider two types of curve equations:\n * <ul><li>Short Weierstrass: <code>y^2 = x^3 + A x + B mod P</code>\n * (SEC1 + RFC-4492)</li>\n * <li>Montgomery: <code>y^2 = x^3 + A x^2 + x mod P</code> (Curve25519,\n * Curve448)</li></ul>\n * In both cases, the generator (\\p G) for a prime-order subgroup is fixed.\n *\n * For Short Weierstrass, this subgroup is the whole curve, and its\n * cardinality is denoted by \\p N. Our code requires that \\p N is an\n * odd prime as mbedtls_ecp_mul() requires an odd number, and\n * mbedtls_ecdsa_sign() requires that it is prime for blinding purposes.\n *\n * The default implementation only initializes \\p A without setting it to the\n * authentic value for curves with <code>A = -3</code>(SECP256R1, etc), in which\n * case you need to load \\p A by yourself when using domain parameters directly,\n * for example:\n * \\code\n * mbedtls_mpi_init(&A);\n * mbedtls_ecp_group_init(&grp);\n * CHECK_RETURN(mbedtls_ecp_group_load(&grp, grp_id));\n * if (mbedtls_ecp_group_a_is_minus_3(&grp)) {\n *     CHECK_RETURN(mbedtls_mpi_sub_int(&A, &grp.P, 3));\n * } else {\n *     CHECK_RETURN(mbedtls_mpi_copy(&A, &grp.A));\n * }\n *\n * do_something_with_a(&A);\n *\n * cleanup:\n * mbedtls_mpi_free(&A);\n * mbedtls_ecp_group_free(&grp);\n * \\endcode\n *\n * For Montgomery curves, we do not store \\p A, but <code>(A + 2) / 4</code>,\n * which is the quantity used in the formulas. Additionally, \\p nbits is\n * not the size of \\p N but the required size for private keys.\n *\n * If \\p modp is NULL, reduction modulo \\p P is done using a generic algorithm.\n * Otherwise, \\p modp must point to a function that takes an \\p mbedtls_mpi in the\n * range of <code>0..2^(2*pbits)-1</code>, and transforms it in-place to an integer\n * which is congruent mod \\p P to the given MPI, and is close enough to \\p pbits\n * in size, so that it may be efficiently brought in the 0..P-1 range by a few\n * additions or subtractions. Therefore, it is only an approximate modular\n * reduction. It must return 0 on success and non-zero on failure.\n *\n * \\note        Alternative implementations of the ECP module must obey the\n *              following constraints.\n *              * Group IDs must be distinct: if two group structures have\n *                the same ID, then they must be identical.\n *              * The fields \\c id, \\c P, \\c A, \\c B, \\c G, \\c N,\n *                \\c pbits and \\c nbits must have the same type and semantics\n *                as in the built-in implementation.\n *                They must be available for reading, but direct modification\n *                of these fields does not need to be supported.\n *                They do not need to be at the same offset in the structure.\n */\ntypedef struct mbedtls_ecp_group {\n    mbedtls_ecp_group_id id;    /*!< An internal group identifier. */\n    mbedtls_mpi P;              /*!< The prime modulus of the base field. */\n    mbedtls_mpi A;              /*!< For Short Weierstrass: \\p A in the equation. Note that\n                                     \\p A is not set to the authentic value in some cases.\n                                     Refer to detailed description of ::mbedtls_ecp_group if\n                                     using domain parameters in the structure.\n                                     For Montgomery curves: <code>(A + 2) / 4</code>. */\n    mbedtls_mpi B;              /*!< For Short Weierstrass: \\p B in the equation.\n                                     For Montgomery curves: unused. */\n    mbedtls_ecp_point G;        /*!< The generator of the subgroup used. */\n    mbedtls_mpi N;              /*!< The order of \\p G. */\n    size_t pbits;               /*!< The number of bits in \\p P.*/\n    size_t nbits;               /*!< For Short Weierstrass: The number of bits in \\p P.\n                                     For Montgomery curves: the number of bits in the\n                                     private keys. */\n    /* End of public fields */\n\n    unsigned int MBEDTLS_PRIVATE(h);             /*!< \\internal 1 if the constants are static. */\n    int(*MBEDTLS_PRIVATE(modp))(mbedtls_mpi *);  /*!< The function for fast pseudo-reduction\n                                                    mod \\p P (see above).*/\n    int(*MBEDTLS_PRIVATE(t_pre))(mbedtls_ecp_point *, void *);   /*!< Unused. */\n    int(*MBEDTLS_PRIVATE(t_post))(mbedtls_ecp_point *, void *);  /*!< Unused. */\n    void *MBEDTLS_PRIVATE(t_data);               /*!< Unused. */\n    mbedtls_ecp_point *MBEDTLS_PRIVATE(T);       /*!< Pre-computed points for ecp_mul_comb(). */\n    size_t MBEDTLS_PRIVATE(T_size);              /*!< The number of dynamic allocated pre-computed points. */\n}\nmbedtls_ecp_group;\n\n/**\n * \\name SECTION: Module settings\n *\n * The configuration options you can set for this module are in this section.\n * Either change them in mbedtls_config.h, or define them using the compiler command line.\n * \\{\n */\n\n#if !defined(MBEDTLS_ECP_WINDOW_SIZE)\n/*\n * Maximum \"window\" size used for point multiplication.\n * Default: a point where higher memory usage yields diminishing performance\n *          returns.\n * Minimum value: 2. Maximum value: 7.\n *\n * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )\n * points used for point multiplication. This value is directly tied to EC\n * peak memory usage, so decreasing it by one should roughly cut memory usage\n * by two (if large curves are in use).\n *\n * Reduction in size may reduce speed, but larger curves are impacted first.\n * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1):\n *      w-size:     6       5       4       3       2\n *      521       145     141     135     120      97\n *      384       214     209     198     177     146\n *      256       320     320     303     262     226\n *      224       475     475     453     398     342\n *      192       640     640     633     587     476\n */\n#define MBEDTLS_ECP_WINDOW_SIZE    4   /**< The maximum window size used. */\n#endif /* MBEDTLS_ECP_WINDOW_SIZE */\n\n#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM)\n/*\n * Trade code size for speed on fixed-point multiplication.\n *\n * This speeds up repeated multiplication of the generator (that is, the\n * multiplication in ECDSA signatures, and half of the multiplications in\n * ECDSA verification and ECDHE) by a factor roughly 3 to 4.\n *\n * For each n-bit Short Weierstrass curve that is enabled, this adds 4n bytes\n * of code size if n < 384 and 8n otherwise.\n *\n * Change this value to 0 to reduce code size.\n */\n#define MBEDTLS_ECP_FIXED_POINT_OPTIM  1   /**< Enable fixed-point speed-up. */\n#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */\n\n/** \\} name SECTION: Module settings */\n\n#else  /* MBEDTLS_ECP_ALT */\n#include \"ecp_alt.h\"\n#endif /* MBEDTLS_ECP_ALT */\n\n/**\n * The maximum size of the groups, that is, of \\c N and \\c P.\n */\n#if !defined(MBEDTLS_ECP_LIGHT)\n/* Dummy definition to help code that has optional ECP support and\n * defines an MBEDTLS_ECP_MAX_BYTES-sized array unconditionally. */\n#define MBEDTLS_ECP_MAX_BITS 1\n/* Note: the curves must be listed in DECREASING size! */\n#elif defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)\n#define MBEDTLS_ECP_MAX_BITS 521\n#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)\n#define MBEDTLS_ECP_MAX_BITS 512\n#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n#define MBEDTLS_ECP_MAX_BITS 448\n#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)\n#define MBEDTLS_ECP_MAX_BITS 384\n#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\n#define MBEDTLS_ECP_MAX_BITS 384\n#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)\n#define MBEDTLS_ECP_MAX_BITS 256\n#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n#define MBEDTLS_ECP_MAX_BITS 256\n#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)\n#define MBEDTLS_ECP_MAX_BITS 256\n#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n#define MBEDTLS_ECP_MAX_BITS 255\n#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)\n#define MBEDTLS_ECP_MAX_BITS 225 // n is slightly above 2^224\n#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)\n#define MBEDTLS_ECP_MAX_BITS 224\n#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)\n#define MBEDTLS_ECP_MAX_BITS 192\n#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\n#define MBEDTLS_ECP_MAX_BITS 192\n#else /* !MBEDTLS_ECP_LIGHT */\n#error \"Missing definition of MBEDTLS_ECP_MAX_BITS\"\n#endif /* !MBEDTLS_ECP_LIGHT */\n\n#define MBEDTLS_ECP_MAX_BYTES    ((MBEDTLS_ECP_MAX_BITS + 7) / 8)\n#define MBEDTLS_ECP_MAX_PT_LEN   (2 * MBEDTLS_ECP_MAX_BYTES + 1)\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n\n/**\n * \\brief           Internal restart context for multiplication\n *\n * \\note            Opaque struct\n */\ntypedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx;\n\n/**\n * \\brief           Internal restart context for ecp_muladd()\n *\n * \\note            Opaque struct\n */\ntypedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx;\n\n/**\n * \\brief           General context for resuming ECC operations\n */\ntypedef struct {\n    unsigned MBEDTLS_PRIVATE(ops_done);                  /*!<  current ops count             */\n    unsigned MBEDTLS_PRIVATE(depth);                     /*!<  call depth (0 = top-level)    */\n    mbedtls_ecp_restart_mul_ctx *MBEDTLS_PRIVATE(rsm);   /*!<  ecp_mul_comb() sub-context    */\n    mbedtls_ecp_restart_muladd_ctx *MBEDTLS_PRIVATE(ma); /*!<  ecp_muladd() sub-context      */\n} mbedtls_ecp_restart_ctx;\n\n/*\n * Operation counts for restartable functions\n */\n#define MBEDTLS_ECP_OPS_CHK   3 /*!< basic ops count for ecp_check_pubkey()  */\n#define MBEDTLS_ECP_OPS_DBL   8 /*!< basic ops count for ecp_double_jac()    */\n#define MBEDTLS_ECP_OPS_ADD  11 /*!< basic ops count for see ecp_add_mixed() */\n#define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv()  */\n\n/**\n * \\brief           Internal; for restartable functions in other modules.\n *                  Check and update basic ops budget.\n *\n * \\param grp       Group structure\n * \\param rs_ctx    Restart context\n * \\param ops       Number of basic ops to do\n *\n * \\return          \\c 0 if doing \\p ops basic ops is still allowed,\n * \\return          #MBEDTLS_ERR_ECP_IN_PROGRESS otherwise.\n */\nint mbedtls_ecp_check_budget(const mbedtls_ecp_group *grp,\n                             mbedtls_ecp_restart_ctx *rs_ctx,\n                             unsigned ops);\n\n/* Utility macro for checking and updating ops budget */\n#define MBEDTLS_ECP_BUDGET(ops)   \\\n    MBEDTLS_MPI_CHK(mbedtls_ecp_check_budget(grp, rs_ctx, \\\n                                             (unsigned) (ops)));\n\n#else /* MBEDTLS_ECP_RESTARTABLE */\n\n#define MBEDTLS_ECP_BUDGET(ops)     /* no-op; for compatibility */\n\n/* We want to declare restartable versions of existing functions anyway */\ntypedef void mbedtls_ecp_restart_ctx;\n\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n/**\n * \\brief    The ECP key-pair structure.\n *\n * A generic key-pair that may be used for ECDSA and fixed ECDH, for example.\n *\n * \\note    Members are deliberately in the same order as in the\n *          ::mbedtls_ecdsa_context structure.\n */\ntypedef struct mbedtls_ecp_keypair {\n    mbedtls_ecp_group MBEDTLS_PRIVATE(grp);      /*!<  Elliptic curve and base point     */\n    mbedtls_mpi MBEDTLS_PRIVATE(d);              /*!<  our secret value                  */\n    mbedtls_ecp_point MBEDTLS_PRIVATE(Q);        /*!<  our public value                  */\n}\nmbedtls_ecp_keypair;\n\n/**\n * The uncompressed point format for Short Weierstrass curves\n * (MBEDTLS_ECP_DP_SECP_XXX and MBEDTLS_ECP_DP_BP_XXX).\n */\n#define MBEDTLS_ECP_PF_UNCOMPRESSED    0\n/**\n * The compressed point format for Short Weierstrass curves\n * (MBEDTLS_ECP_DP_SECP_XXX and MBEDTLS_ECP_DP_BP_XXX).\n *\n * \\warning     While this format is supported for all concerned curves for\n *              writing, when it comes to parsing, it is not supported for all\n *              curves. Specifically, parsing compressed points on\n *              MBEDTLS_ECP_DP_SECP224R1 and MBEDTLS_ECP_DP_SECP224K1 is not\n *              supported.\n */\n#define MBEDTLS_ECP_PF_COMPRESSED      1\n\n/*\n * Some other constants from RFC 4492\n */\n#define MBEDTLS_ECP_TLS_NAMED_CURVE    3   /**< The named_curve of ECCurveType. */\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n/**\n * \\brief           Set the maximum number of basic operations done in a row.\n *\n *                  If more operations are needed to complete a computation,\n *                  #MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the\n *                  function performing the computation. It is then the\n *                  caller's responsibility to either call again with the same\n *                  parameters until it returns 0 or an error code; or to free\n *                  the restart context if the operation is to be aborted.\n *\n *                  It is strictly required that all input parameters and the\n *                  restart context be the same on successive calls for the\n *                  same operation, but output parameters need not be the\n *                  same; they must not be used until the function finally\n *                  returns 0.\n *\n *                  This only applies to functions whose documentation\n *                  mentions they may return #MBEDTLS_ERR_ECP_IN_PROGRESS (or\n *                  #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS for functions in the\n *                  SSL module). For functions that accept a \"restart context\"\n *                  argument, passing NULL disables restart and makes the\n *                  function equivalent to the function with the same name\n *                  with \\c _restartable removed. For functions in the ECDH\n *                  module, restart is disabled unless the function accepts\n *                  an \"ECDH context\" argument and\n *                  mbedtls_ecdh_enable_restart() was previously called on\n *                  that context. For function in the SSL module, restart is\n *                  only enabled for specific sides and key exchanges\n *                  (currently only for clients and ECDHE-ECDSA).\n *\n * \\warning         Using the PSA interruptible interfaces with keys in local\n *                  storage and no accelerator driver will also call this\n *                  function to set the values specified via those interfaces,\n *                  overwriting values previously set. Care should be taken if\n *                  mixing these two interfaces.\n *\n * \\param max_ops   Maximum number of basic operations done in a row.\n *                  Default: 0 (unlimited).\n *                  Lower (non-zero) values mean ECC functions will block for\n *                  a lesser maximum amount of time.\n *\n * \\note            A \"basic operation\" is defined as a rough equivalent of a\n *                  multiplication in GF(p) for the NIST P-256 curve.\n *                  As an indication, with default settings, a scalar\n *                  multiplication (full run of \\c mbedtls_ecp_mul()) is:\n *                  - about 3300 basic operations for P-256\n *                  - about 9400 basic operations for P-384\n *\n * \\note            Very low values are not always respected: sometimes\n *                  functions need to block for a minimum number of\n *                  operations, and will do so even if max_ops is set to a\n *                  lower value.  That minimum depends on the curve size, and\n *                  can be made lower by decreasing the value of\n *                  \\c MBEDTLS_ECP_WINDOW_SIZE.  As an indication, here is the\n *                  lowest effective value for various curves and values of\n *                  that parameter (w for short):\n *                          w=6     w=5     w=4     w=3     w=2\n *                  P-256   208     208     160     136     124\n *                  P-384   682     416     320     272     248\n *                  P-521  1364     832     640     544     496\n *\n * \\note            This setting is currently ignored by Curve25519.\n */\nvoid mbedtls_ecp_set_max_ops(unsigned max_ops);\n\n/**\n * \\brief           Check if restart is enabled (max_ops != 0)\n *\n * \\return          \\c 0 if \\c max_ops == 0 (restart disabled)\n * \\return          \\c 1 otherwise (restart enabled)\n */\nint mbedtls_ecp_restart_is_enabled(void);\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n/*\n * Get the type of a curve\n */\nmbedtls_ecp_curve_type mbedtls_ecp_get_type(const mbedtls_ecp_group *grp);\n\n/**\n * \\brief           This function retrieves the information defined in\n *                  mbedtls_ecp_curve_info() for all supported curves.\n *\n * \\note            This function returns information about all curves\n *                  supported by the library. Some curves may not be\n *                  supported for all algorithms. Call mbedtls_ecdh_can_do()\n *                  or mbedtls_ecdsa_can_do() to check if a curve is\n *                  supported for ECDH or ECDSA.\n *\n * \\return          A statically allocated array. The last entry is 0.\n */\nconst mbedtls_ecp_curve_info *mbedtls_ecp_curve_list(void);\n\n/**\n * \\brief           This function retrieves the list of internal group\n *                  identifiers of all supported curves in the order of\n *                  preference.\n *\n * \\note            This function returns information about all curves\n *                  supported by the library. Some curves may not be\n *                  supported for all algorithms. Call mbedtls_ecdh_can_do()\n *                  or mbedtls_ecdsa_can_do() to check if a curve is\n *                  supported for ECDH or ECDSA.\n *\n * \\return          A statically allocated array,\n *                  terminated with MBEDTLS_ECP_DP_NONE.\n */\nconst mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list(void);\n\n/**\n * \\brief           This function retrieves curve information from an internal\n *                  group identifier.\n *\n * \\param grp_id    An \\c MBEDTLS_ECP_DP_XXX value.\n *\n * \\return          The associated curve information on success.\n * \\return          NULL on failure.\n */\nconst mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id(mbedtls_ecp_group_id grp_id);\n\n/**\n * \\brief           This function retrieves curve information from a TLS\n *                  NamedCurve value.\n *\n * \\param tls_id    An \\c MBEDTLS_ECP_DP_XXX value.\n *\n * \\return          The associated curve information on success.\n * \\return          NULL on failure.\n */\nconst mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id(uint16_t tls_id);\n\n/**\n * \\brief           This function retrieves curve information from a\n *                  human-readable name.\n *\n * \\param name      The human-readable name.\n *\n * \\return          The associated curve information on success.\n * \\return          NULL on failure.\n */\nconst mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name(const char *name);\n\n/**\n * \\brief           This function initializes a point as zero.\n *\n * \\param pt        The point to initialize.\n */\nvoid mbedtls_ecp_point_init(mbedtls_ecp_point *pt);\n\n/**\n * \\brief           This function initializes an ECP group context\n *                  without loading any domain parameters.\n *\n * \\note            After this function is called, domain parameters\n *                  for various ECP groups can be loaded through the\n *                  mbedtls_ecp_group_load() or mbedtls_ecp_tls_read_group()\n *                  functions.\n */\nvoid mbedtls_ecp_group_init(mbedtls_ecp_group *grp);\n\n/**\n * \\brief           This function initializes a key pair as an invalid one.\n *\n * \\param key       The key pair to initialize.\n */\nvoid mbedtls_ecp_keypair_init(mbedtls_ecp_keypair *key);\n\n/**\n * \\brief           This function frees the components of a point.\n *\n * \\param pt        The point to free.\n */\nvoid mbedtls_ecp_point_free(mbedtls_ecp_point *pt);\n\n/**\n * \\brief           This function frees the components of an ECP group.\n *\n * \\param grp       The group to free. This may be \\c NULL, in which\n *                  case this function returns immediately. If it is not\n *                  \\c NULL, it must point to an initialized ECP group.\n */\nvoid mbedtls_ecp_group_free(mbedtls_ecp_group *grp);\n\n/**\n * \\brief           This function frees the components of a key pair.\n *\n * \\param key       The key pair to free. This may be \\c NULL, in which\n *                  case this function returns immediately. If it is not\n *                  \\c NULL, it must point to an initialized ECP key pair.\n */\nvoid mbedtls_ecp_keypair_free(mbedtls_ecp_keypair *key);\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n/**\n * \\brief           Initialize a restart context.\n *\n * \\param ctx       The restart context to initialize. This must\n *                  not be \\c NULL.\n */\nvoid mbedtls_ecp_restart_init(mbedtls_ecp_restart_ctx *ctx);\n\n/**\n * \\brief           Free the components of a restart context.\n *\n * \\param ctx       The restart context to free. This may be \\c NULL, in which\n *                  case this function returns immediately. If it is not\n *                  \\c NULL, it must point to an initialized restart context.\n */\nvoid mbedtls_ecp_restart_free(mbedtls_ecp_restart_ctx *ctx);\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n/**\n * \\brief           This function copies the contents of point \\p Q into\n *                  point \\p P.\n *\n * \\param P         The destination point. This must be initialized.\n * \\param Q         The source point. This must be initialized.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.\n * \\return          Another negative error code for other kinds of failure.\n */\nint mbedtls_ecp_copy(mbedtls_ecp_point *P, const mbedtls_ecp_point *Q);\n\n/**\n * \\brief           This function copies the contents of group \\p src into\n *                  group \\p dst.\n *\n * \\param dst       The destination group. This must be initialized.\n * \\param src       The source group. This must be initialized.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_group_copy(mbedtls_ecp_group *dst,\n                           const mbedtls_ecp_group *src);\n\n/**\n * \\brief           This function sets a point to the point at infinity.\n *\n * \\param pt        The point to set. This must be initialized.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_set_zero(mbedtls_ecp_point *pt);\n\n/**\n * \\brief           This function checks if a point is the point at infinity.\n *\n * \\param pt        The point to test. This must be initialized.\n *\n * \\return          \\c 1 if the point is zero.\n * \\return          \\c 0 if the point is non-zero.\n * \\return          A negative error code on failure.\n */\nint mbedtls_ecp_is_zero(mbedtls_ecp_point *pt);\n\n/**\n * \\brief           This function compares two points.\n *\n * \\note            This assumes that the points are normalized. Otherwise,\n *                  they may compare as \"not equal\" even if they are.\n *\n * \\param P         The first point to compare. This must be initialized.\n * \\param Q         The second point to compare. This must be initialized.\n *\n * \\return          \\c 0 if the points are equal.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the points are not equal.\n */\nint mbedtls_ecp_point_cmp(const mbedtls_ecp_point *P,\n                          const mbedtls_ecp_point *Q);\n\n/**\n * \\brief           This function imports a non-zero point from two ASCII\n *                  strings.\n *\n * \\param P         The destination point. This must be initialized.\n * \\param radix     The numeric base of the input.\n * \\param x         The first affine coordinate, as a null-terminated string.\n * \\param y         The second affine coordinate, as a null-terminated string.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_MPI_XXX error code on failure.\n */\nint mbedtls_ecp_point_read_string(mbedtls_ecp_point *P, int radix,\n                                  const char *x, const char *y);\n\n/**\n * \\brief           This function exports a point into unsigned binary data.\n *\n * \\param grp       The group to which the point should belong.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param P         The point to export. This must be initialized.\n * \\param format    The point format. This must be either\n *                  #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED.\n *                  (For groups without these formats, this parameter is\n *                  ignored. But it still has to be either of the above\n *                  values.)\n * \\param olen      The address at which to store the length of\n *                  the output in Bytes. This must not be \\c NULL.\n * \\param buf       The output buffer. This must be a writable buffer\n *                  of length \\p buflen Bytes.\n * \\param buflen    The length of the output buffer \\p buf in Bytes.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer\n *                  is too small to hold the point.\n * \\return          #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format\n *                  or the export for the given group is not implemented.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_point_write_binary(const mbedtls_ecp_group *grp,\n                                   const mbedtls_ecp_point *P,\n                                   int format, size_t *olen,\n                                   unsigned char *buf, size_t buflen);\n\n/**\n * \\brief           This function imports a point from unsigned binary data.\n *\n * \\note            This function does not check that the point actually\n *                  belongs to the given group, see mbedtls_ecp_check_pubkey()\n *                  for that.\n *\n * \\note            For compressed points, see #MBEDTLS_ECP_PF_COMPRESSED for\n *                  limitations.\n *\n * \\param grp       The group to which the point should belong.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param P         The destination context to import the point to.\n *                  This must be initialized.\n * \\param buf       The input buffer. This must be a readable buffer\n *                  of length \\p ilen Bytes.\n * \\param ilen      The length of the input buffer \\p buf in Bytes.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid.\n * \\return          #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.\n * \\return          #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the import for the\n *                  given group is not implemented.\n */\nint mbedtls_ecp_point_read_binary(const mbedtls_ecp_group *grp,\n                                  mbedtls_ecp_point *P,\n                                  const unsigned char *buf, size_t ilen);\n\n/**\n * \\brief           This function imports a point from a TLS ECPoint record.\n *\n * \\note            On function return, \\p *buf is updated to point immediately\n *                  after the ECPoint record.\n *\n * \\param grp       The ECP group to use.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param pt        The destination point.\n * \\param buf       The address of the pointer to the start of the input buffer.\n * \\param len       The length of the buffer.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_MPI_XXX error code on initialization\n *                  failure.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid.\n */\nint mbedtls_ecp_tls_read_point(const mbedtls_ecp_group *grp,\n                               mbedtls_ecp_point *pt,\n                               const unsigned char **buf, size_t len);\n\n/**\n * \\brief           This function exports a point as a TLS ECPoint record\n *                  defined in RFC 4492, Section 5.4.\n *\n * \\param grp       The ECP group to use.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param pt        The point to be exported. This must be initialized.\n * \\param format    The point format to use. This must be either\n *                  #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED.\n * \\param olen      The address at which to store the length in Bytes\n *                  of the data written.\n * \\param buf       The target buffer. This must be a writable buffer of\n *                  length \\p blen Bytes.\n * \\param blen      The length of the target buffer \\p buf in Bytes.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid.\n * \\return          #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the target buffer\n *                  is too small to hold the exported point.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_tls_write_point(const mbedtls_ecp_group *grp,\n                                const mbedtls_ecp_point *pt,\n                                int format, size_t *olen,\n                                unsigned char *buf, size_t blen);\n\n/**\n * \\brief           This function sets up an ECP group context\n *                  from a standardized set of domain parameters.\n *\n * \\note            The index should be a value of the NamedCurve enum,\n *                  as defined in <em>RFC-4492: Elliptic Curve Cryptography\n *                  (ECC) Cipher Suites for Transport Layer Security (TLS)</em>,\n *                  usually in the form of an \\c MBEDTLS_ECP_DP_XXX macro.\n *\n * \\param grp       The group context to setup. This must be initialized.\n * \\param id        The identifier of the domain parameter set to load.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \\p id doesn't\n *                  correspond to a known group.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id);\n\n/**\n * \\brief           This function sets up an ECP group context from a TLS\n *                  ECParameters record as defined in RFC 4492, Section 5.4.\n *\n * \\note            The read pointer \\p buf is updated to point right after\n *                  the ECParameters record on exit.\n *\n * \\param grp       The group context to setup. This must be initialized.\n * \\param buf       The address of the pointer to the start of the input buffer.\n * \\param len       The length of the input buffer \\c *buf in Bytes.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid.\n * \\return          #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not\n *                  recognized.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_tls_read_group(mbedtls_ecp_group *grp,\n                               const unsigned char **buf, size_t len);\n\n/**\n * \\brief           This function extracts an elliptic curve group ID from a\n *                  TLS ECParameters record as defined in RFC 4492, Section 5.4.\n *\n * \\note            The read pointer \\p buf is updated to point right after\n *                  the ECParameters record on exit.\n *\n * \\param grp       The address at which to store the group id.\n *                  This must not be \\c NULL.\n * \\param buf       The address of the pointer to the start of the input buffer.\n * \\param len       The length of the input buffer \\c *buf in Bytes.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid.\n * \\return          #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not\n *                  recognized.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_tls_read_group_id(mbedtls_ecp_group_id *grp,\n                                  const unsigned char **buf,\n                                  size_t len);\n/**\n * \\brief           This function exports an elliptic curve as a TLS\n *                  ECParameters record as defined in RFC 4492, Section 5.4.\n *\n * \\param grp       The ECP group to be exported.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param olen      The address at which to store the number of Bytes written.\n *                  This must not be \\c NULL.\n * \\param buf       The buffer to write to. This must be a writable buffer\n *                  of length \\p blen Bytes.\n * \\param blen      The length of the output buffer \\p buf in Bytes.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output\n *                  buffer is too small to hold the exported group.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_tls_write_group(const mbedtls_ecp_group *grp,\n                                size_t *olen,\n                                unsigned char *buf, size_t blen);\n\n/**\n * \\brief           This function performs a scalar multiplication of a point\n *                  by an integer: \\p R = \\p m * \\p P.\n *\n *                  It is not thread-safe to use same group in multiple threads.\n *\n * \\note            To prevent timing attacks, this function\n *                  executes the exact same sequence of base-field\n *                  operations for any valid \\p m. It avoids any if-branch or\n *                  array index depending on the value of \\p m. It also uses\n *                  \\p f_rng to randomize some intermediate results.\n *\n * \\param grp       The ECP group to use.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param R         The point in which to store the result of the calculation.\n *                  This must be initialized.\n * \\param m         The integer by which to multiply. This must be initialized.\n * \\param P         The point to multiply. This must be initialized.\n * \\param f_rng     The RNG function. This must not be \\c NULL.\n * \\param p_rng     The RNG context to be passed to \\p f_rng. This may be \\c\n *                  NULL if \\p f_rng doesn't need a context.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_INVALID_KEY if \\p m is not a valid private\n *                  key, or \\p P is not a valid public key.\n * \\return          #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_mul(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n                    const mbedtls_mpi *m, const mbedtls_ecp_point *P,\n                    mbedtls_f_rng_t *f_rng, void *p_rng);\n\n/**\n * \\brief           This function performs multiplication of a point by\n *                  an integer: \\p R = \\p m * \\p P in a restartable way.\n *\n * \\see             mbedtls_ecp_mul()\n *\n * \\note            This function does the same as \\c mbedtls_ecp_mul(), but\n *                  it can return early and restart according to the limit set\n *                  with \\c mbedtls_ecp_set_max_ops() to reduce blocking.\n *\n * \\param grp       The ECP group to use.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param R         The point in which to store the result of the calculation.\n *                  This must be initialized.\n * \\param m         The integer by which to multiply. This must be initialized.\n * \\param P         The point to multiply. This must be initialized.\n * \\param f_rng     The RNG function. This must not be \\c NULL.\n * \\param p_rng     The RNG context to be passed to \\p f_rng. This may be \\c\n *                  NULL if \\p f_rng doesn't need a context.\n * \\param rs_ctx    The restart context (NULL disables restart).\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_INVALID_KEY if \\p m is not a valid private\n *                  key, or \\p P is not a valid public key.\n * \\return          #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.\n * \\return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of\n *                  operations was reached: see \\c mbedtls_ecp_set_max_ops().\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_mul_restartable(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n                                const mbedtls_mpi *m, const mbedtls_ecp_point *P,\n                                mbedtls_f_rng_t *f_rng, void *p_rng,\n                                mbedtls_ecp_restart_ctx *rs_ctx);\n\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n/**\n * \\brief           This function checks if domain parameter A of the curve is\n *                  \\c -3.\n *\n * \\note            This function is only defined for short Weierstrass curves.\n *                  It may not be included in builds without any short\n *                  Weierstrass curve.\n *\n * \\param grp       The ECP group to use.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n *\n * \\return          \\c 1 if <code>A = -3</code>.\n * \\return          \\c 0 Otherwise.\n */\nstatic inline int mbedtls_ecp_group_a_is_minus_3(const mbedtls_ecp_group *grp)\n{\n    return grp->A.MBEDTLS_PRIVATE(p) == NULL;\n}\n\n/**\n * \\brief           This function performs multiplication and addition of two\n *                  points by integers: \\p R = \\p m * \\p P + \\p n * \\p Q\n *\n *                  It is not thread-safe to use same group in multiple threads.\n *\n * \\note            In contrast to mbedtls_ecp_mul(), this function does not\n *                  guarantee a constant execution flow and timing.\n *\n * \\note            This function is only defined for short Weierstrass curves.\n *                  It may not be included in builds without any short\n *                  Weierstrass curve.\n *\n * \\param grp       The ECP group to use.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param R         The point in which to store the result of the calculation.\n *                  This must be initialized.\n * \\param m         The integer by which to multiply \\p P.\n *                  This must be initialized.\n * \\param P         The point to multiply by \\p m. This must be initialized.\n * \\param n         The integer by which to multiply \\p Q.\n *                  This must be initialized.\n * \\param Q         The point to be multiplied by \\p n.\n *                  This must be initialized.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_INVALID_KEY if \\p m or \\p n are not\n *                  valid private keys, or \\p P or \\p Q are not valid public\n *                  keys.\n * \\return          #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.\n * \\return          #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \\p grp does not\n *                  designate a short Weierstrass curve.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_muladd(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n                       const mbedtls_mpi *m, const mbedtls_ecp_point *P,\n                       const mbedtls_mpi *n, const mbedtls_ecp_point *Q);\n\n/**\n * \\brief           This function performs multiplication and addition of two\n *                  points by integers: \\p R = \\p m * \\p P + \\p n * \\p Q in a\n *                  restartable way.\n *\n * \\see             \\c mbedtls_ecp_muladd()\n *\n * \\note            This function works the same as \\c mbedtls_ecp_muladd(),\n *                  but it can return early and restart according to the limit\n *                  set with \\c mbedtls_ecp_set_max_ops() to reduce blocking.\n *\n * \\note            This function is only defined for short Weierstrass curves.\n *                  It may not be included in builds without any short\n *                  Weierstrass curve.\n *\n * \\param grp       The ECP group to use.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param R         The point in which to store the result of the calculation.\n *                  This must be initialized.\n * \\param m         The integer by which to multiply \\p P.\n *                  This must be initialized.\n * \\param P         The point to multiply by \\p m. This must be initialized.\n * \\param n         The integer by which to multiply \\p Q.\n *                  This must be initialized.\n * \\param Q         The point to be multiplied by \\p n.\n *                  This must be initialized.\n * \\param rs_ctx    The restart context (NULL disables restart).\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_INVALID_KEY if \\p m or \\p n are not\n *                  valid private keys, or \\p P or \\p Q are not valid public\n *                  keys.\n * \\return          #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.\n * \\return          #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \\p grp does not\n *                  designate a short Weierstrass curve.\n * \\return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of\n *                  operations was reached: see \\c mbedtls_ecp_set_max_ops().\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_muladd_restartable(\n    mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n    const mbedtls_mpi *m, const mbedtls_ecp_point *P,\n    const mbedtls_mpi *n, const mbedtls_ecp_point *Q,\n    mbedtls_ecp_restart_ctx *rs_ctx);\n#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */\n\n/**\n * \\brief           This function checks that a point is a valid public key\n *                  on this curve.\n *\n *                  It only checks that the point is non-zero, has\n *                  valid coordinates and lies on the curve. It does not verify\n *                  that it is indeed a multiple of \\c G. This additional\n *                  check is computationally more expensive, is not required\n *                  by standards, and should not be necessary if the group\n *                  used has a small cofactor. In particular, it is useless for\n *                  the NIST groups which all have a cofactor of 1.\n *\n * \\note            This function uses bare components rather than an\n *                  ::mbedtls_ecp_keypair structure, to ease use with other\n *                  structures, such as ::mbedtls_ecdh_context or\n *                  ::mbedtls_ecdsa_context.\n *\n * \\param grp       The ECP group the point should belong to.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param pt        The point to check. This must be initialized.\n *\n * \\return          \\c 0 if the point is a valid public key.\n * \\return          #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not\n *                  a valid public key for the given curve.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_check_pubkey(const mbedtls_ecp_group *grp,\n                             const mbedtls_ecp_point *pt);\n\n/**\n * \\brief           This function checks that an \\c mbedtls_mpi is a\n *                  valid private key for this curve.\n *\n * \\note            This function uses bare components rather than an\n *                  ::mbedtls_ecp_keypair structure to ease use with other\n *                  structures, such as ::mbedtls_ecdh_context or\n *                  ::mbedtls_ecdsa_context.\n *\n * \\param grp       The ECP group the private key should belong to.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param d         The integer to check. This must be initialized.\n *\n * \\return          \\c 0 if the point is a valid private key.\n * \\return          #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not a valid\n *                  private key for the given curve.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_check_privkey(const mbedtls_ecp_group *grp,\n                              const mbedtls_mpi *d);\n\n/**\n * \\brief           This function generates a private key.\n *\n * \\param grp       The ECP group to generate a private key for.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param d         The destination MPI (secret part). This must be initialized.\n * \\param f_rng     The RNG function. This must not be \\c NULL.\n * \\param p_rng     The RNG parameter to be passed to \\p f_rng. This may be\n *                  \\c NULL if \\p f_rng doesn't need a context argument.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX or \\c MBEDTLS_MPI_XXX error code\n *                  on failure.\n */\nint mbedtls_ecp_gen_privkey(const mbedtls_ecp_group *grp,\n                            mbedtls_mpi *d,\n                            mbedtls_f_rng_t *f_rng,\n                            void *p_rng);\n\n/**\n * \\brief           This function generates a keypair with a configurable base\n *                  point.\n *\n * \\note            This function uses bare components rather than an\n *                  ::mbedtls_ecp_keypair structure to ease use with other\n *                  structures, such as ::mbedtls_ecdh_context or\n *                  ::mbedtls_ecdsa_context.\n *\n * \\param grp       The ECP group to generate a key pair for.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param G         The base point to use. This must be initialized\n *                  and belong to \\p grp. It replaces the default base\n *                  point \\c grp->G used by mbedtls_ecp_gen_keypair().\n * \\param d         The destination MPI (secret part).\n *                  This must be initialized.\n * \\param Q         The destination point (public part).\n *                  This must be initialized.\n * \\param f_rng     The RNG function. This must not be \\c NULL.\n * \\param p_rng     The RNG context to be passed to \\p f_rng. This may\n *                  be \\c NULL if \\p f_rng doesn't need a context argument.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX or \\c MBEDTLS_MPI_XXX error code\n *                  on failure.\n */\nint mbedtls_ecp_gen_keypair_base(mbedtls_ecp_group *grp,\n                                 const mbedtls_ecp_point *G,\n                                 mbedtls_mpi *d, mbedtls_ecp_point *Q,\n                                 mbedtls_f_rng_t *f_rng,\n                                 void *p_rng);\n\n/**\n * \\brief           This function generates an ECP keypair.\n *\n * \\note            This function uses bare components rather than an\n *                  ::mbedtls_ecp_keypair structure to ease use with other\n *                  structures, such as ::mbedtls_ecdh_context or\n *                  ::mbedtls_ecdsa_context.\n *\n * \\param grp       The ECP group to generate a key pair for.\n *                  This must be initialized and have group parameters\n *                  set, for example through mbedtls_ecp_group_load().\n * \\param d         The destination MPI (secret part).\n *                  This must be initialized.\n * \\param Q         The destination point (public part).\n *                  This must be initialized.\n * \\param f_rng     The RNG function. This must not be \\c NULL.\n * \\param p_rng     The RNG context to be passed to \\p f_rng. This may\n *                  be \\c NULL if \\p f_rng doesn't need a context argument.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX or \\c MBEDTLS_MPI_XXX error code\n *                  on failure.\n */\nint mbedtls_ecp_gen_keypair(mbedtls_ecp_group *grp, mbedtls_mpi *d,\n                            mbedtls_ecp_point *Q,\n                            mbedtls_f_rng_t *f_rng,\n                            void *p_rng);\n\n/**\n * \\brief           This function generates an ECP key.\n *\n * \\param grp_id    The ECP group identifier.\n * \\param key       The destination key. This must be initialized.\n * \\param f_rng     The RNG function to use. This must not be \\c NULL.\n * \\param p_rng     The RNG context to be passed to \\p f_rng. This may\n *                  be \\c NULL if \\p f_rng doesn't need a context argument.\n *\n * \\return          \\c 0 on success.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX or \\c MBEDTLS_MPI_XXX error code\n *                  on failure.\n */\nint mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,\n                        mbedtls_f_rng_t *f_rng,\n                        void *p_rng);\n\n/** \\brief          Set the public key in a key pair object.\n *\n * \\note            This function does not check that the point actually\n *                  belongs to the given group. Call mbedtls_ecp_check_pubkey()\n *                  on \\p Q before calling this function to check that.\n *\n * \\note            This function does not check that the public key matches\n *                  the private key that is already in \\p key, if any.\n *                  To check the consistency of the resulting key pair object,\n *                  call mbedtls_ecp_check_pub_priv() after setting both\n *                  the public key and the private key.\n *\n * \\param grp_id    The ECP group identifier.\n * \\param key       The key pair object. It must be initialized.\n *                  If its group has already been set, it must match \\p grp_id.\n *                  If its group has not been set, it will be set to \\p grp_id.\n *                  If the public key has already been set, it is overwritten.\n * \\param Q         The public key to copy. This must be a point on the\n *                  curve indicated by \\p grp_id.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \\p key does not\n *                  match \\p grp_id.\n * \\return          #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for\n *                  the group is not implemented.\n * \\return          #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_set_public_key(mbedtls_ecp_group_id grp_id,\n                               mbedtls_ecp_keypair *key,\n                               const mbedtls_ecp_point *Q);\n\n/**\n * \\brief           This function reads an elliptic curve private key.\n *\n * \\note            This function does not set the public key in the\n *                  key pair object. Without a public key, the key pair object\n *                  cannot be used with operations that require the public key.\n *                  Call mbedtls_ecp_keypair_calc_public() to set the public\n *                  key from the private key. Alternatively, you can call\n *                  mbedtls_ecp_set_public_key() to set the public key part,\n *                  and then optionally mbedtls_ecp_check_pub_priv() to check\n *                  that the private and public parts are consistent.\n *\n * \\note            If a public key has already been set in the key pair\n *                  object, this function does not check that it is consistent\n *                  with the private key. Call mbedtls_ecp_check_pub_priv()\n *                  after setting both the public key and the private key\n *                  to make that check.\n *\n * \\param grp_id    The ECP group identifier.\n * \\param key       The destination key.\n * \\param buf       The buffer containing the binary representation of the\n *                  key. (Big endian integer for Weierstrass curves, byte\n *                  string for Montgomery curves.)\n * \\param buflen    The length of the buffer in bytes.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_INVALID_KEY error if the key is\n *                  invalid.\n * \\return          #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.\n * \\return          #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for\n *                  the group is not implemented.\n * \\return          Another negative error code on different kinds of failure.\n */\nint mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,\n                         const unsigned char *buf, size_t buflen);\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n/**\n * \\brief           This function exports an elliptic curve private key.\n *\n * \\deprecated      Note that although this function accepts an output\n *                  buffer that is smaller or larger than the key, most key\n *                  import interfaces require the output to have exactly\n *                  key's nominal length. It is generally simplest to\n *                  pass the key's nominal length as \\c buflen, after\n *                  checking that the output buffer is large enough.\n *                  See the description of the \\p buflen parameter for\n *                  how to calculate the nominal length.\n *                  To avoid this difficulty, use mbedtls_ecp_write_key_ext()\n *                  instead.\n *                  mbedtls_ecp_write_key() is deprecated and will be\n *                  removed in a future version of the library.\n *\n * \\note            If the private key was not set in \\p key,\n *                  the output is unspecified. Future versions\n *                  may return an error in that case.\n *\n * \\param key       The private key.\n * \\param buf       The output buffer for containing the binary representation\n *                  of the key.\n *                  For Weierstrass curves, this is the big-endian\n *                  representation, padded with null bytes at the beginning\n *                  to reach \\p buflen bytes.\n *                  For Montgomery curves, this is the standard byte string\n *                  representation (which is little-endian), padded with\n *                  null bytes at the end to reach \\p buflen bytes.\n * \\param buflen    The total length of the buffer in bytes.\n *                  The length of the output is\n *                  (`grp->nbits` + 7) / 8 bytes\n *                  where `grp->nbits` is the private key size in bits.\n *                  For Weierstrass keys, if the output buffer is smaller,\n *                  leading zeros are trimmed to fit if possible. For\n *                  Montgomery keys, the output buffer must always be large\n *                  enough for the nominal length.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL or\n *                  #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the \\p key\n *                  representation is larger than the available space in \\p buf.\n * \\return          Another negative error code on different kinds of failure.\n */\nint MBEDTLS_DEPRECATED mbedtls_ecp_write_key(mbedtls_ecp_keypair *key,\n                                             unsigned char *buf, size_t buflen);\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n\n/**\n * \\brief           This function exports an elliptic curve private key.\n *\n * \\param key       The private key.\n * \\param olen      On success, the length of the private key.\n *                  This is always (`grp->nbits` + 7) / 8 bytes\n *                  where `grp->nbits` is the private key size in bits.\n * \\param buf       The output buffer for containing the binary representation\n *                  of the key.\n * \\param buflen    The total length of the buffer in bytes.\n *                  #MBEDTLS_ECP_MAX_BYTES is always sufficient.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the \\p key\n *                  representation is larger than the available space in \\p buf.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if no private key is\n *                  set in \\p key.\n * \\return          Another negative error code on different kinds of failure.\n */\nint mbedtls_ecp_write_key_ext(const mbedtls_ecp_keypair *key,\n                              size_t *olen, unsigned char *buf, size_t buflen);\n\n/**\n * \\brief           This function exports an elliptic curve public key.\n *\n * \\note            If the public key was not set in \\p key,\n *                  the output is unspecified. Future versions\n *                  may return an error in that case.\n *\n * \\param key       The public key.\n * \\param format    The point format. This must be either\n *                  #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED.\n *                  (For groups without these formats, this parameter is\n *                  ignored. But it still has to be either of the above\n *                  values.)\n * \\param olen      The address at which to store the length of\n *                  the output in Bytes. This must not be \\c NULL.\n * \\param buf       The output buffer. This must be a writable buffer\n *                  of length \\p buflen Bytes.\n * \\param buflen    The length of the output buffer \\p buf in Bytes.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer\n *                  is too small to hold the point.\n * \\return          #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format\n *                  or the export for the given group is not implemented.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_write_public_key(const mbedtls_ecp_keypair *key,\n                                 int format, size_t *olen,\n                                 unsigned char *buf, size_t buflen);\n\n/**\n * \\brief           This function checks that the keypair objects\n *                  \\p pub and \\p prv have the same group and the\n *                  same public point, and that the private key in\n *                  \\p prv is consistent with the public key.\n *\n * \\param pub       The keypair structure holding the public key. This\n *                  must be initialized. If it contains a private key, that\n *                  part is ignored.\n * \\param prv       The keypair structure holding the full keypair.\n *                  This must be initialized.\n * \\param f_rng     The RNG function. This must not be \\c NULL.\n * \\param p_rng     The RNG context to be passed to \\p f_rng. This may be \\c\n *                  NULL if \\p f_rng doesn't need a context.\n *\n * \\return          \\c 0 on success, meaning that the keys are valid and match.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX or an \\c MBEDTLS_ERR_MPI_XXX\n *                  error code on calculation failure.\n */\nint mbedtls_ecp_check_pub_priv(\n    const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv,\n    mbedtls_f_rng_t *f_rng, void *p_rng);\n\n/** \\brief          Calculate the public key from a private key in a key pair.\n *\n * \\param key       A keypair structure. It must have a private key set.\n *                  If the public key is set, it will be overwritten.\n * \\param f_rng     The RNG function. This must not be \\c NULL.\n * \\param p_rng     The RNG context to be passed to \\p f_rng. This may be \\c\n *                  NULL if \\p f_rng doesn't need a context.\n *\n * \\return          \\c 0 on success. The key pair object can be used for\n *                  operations that require the public key.\n * \\return          An \\c MBEDTLS_ERR_ECP_XXX or an \\c MBEDTLS_ERR_MPI_XXX\n *                  error code on calculation failure.\n */\nint mbedtls_ecp_keypair_calc_public(\n    mbedtls_ecp_keypair *key,\n    mbedtls_f_rng_t *f_rng, void *p_rng);\n\n/** \\brief          Query the group that a key pair belongs to.\n *\n * \\param key       The key pair to query.\n *\n * \\return          The group ID for the group registered in the key pair\n *                  object.\n *                  This is \\c MBEDTLS_ECP_DP_NONE if no group has been set\n *                  in the key pair object.\n */\nmbedtls_ecp_group_id mbedtls_ecp_keypair_get_group_id(\n    const mbedtls_ecp_keypair *key);\n\n/**\n * \\brief           This function exports generic key-pair parameters.\n *\n *                  Each of the output parameters can be a null pointer\n *                  if you do not need that parameter.\n *\n * \\note            If the private key or the public key was not set in \\p key,\n *                  the corresponding output is unspecified. Future versions\n *                  may return an error in that case.\n *\n * \\param key       The key pair to export from.\n * \\param grp       Slot for exported ECP group.\n *                  It must either be null or point to an initialized ECP group.\n * \\param d         Slot for the exported secret value.\n *                  It must either be null or point to an initialized mpi.\n * \\param Q         Slot for the exported public value.\n *                  It must either be null or point to an initialized ECP point.\n *\n * \\return          \\c 0 on success,\n * \\return          #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.\n * \\return          #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if key id doesn't\n *                  correspond to a known group.\n * \\return          Another negative error code on other kinds of failure.\n */\nint mbedtls_ecp_export(const mbedtls_ecp_keypair *key, mbedtls_ecp_group *grp,\n                       mbedtls_mpi *d, mbedtls_ecp_point *Q);\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/**\n * \\brief          The ECP checkup routine.\n *\n * \\return         \\c 0 on success.\n * \\return         \\c 1 on failure.\n */\nint mbedtls_ecp_self_test(int verbose);\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* ecp.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/entropy.h",
    "content": "/**\n * \\file entropy.h\n *\n * \\brief Entropy accumulator implementation\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_ENTROPY_H\n#define MBEDTLS_ENTROPY_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n\n#include \"md.h\"\n\n#if (defined(MBEDTLS_MD_CAN_SHA512) || defined(PSA_WANT_ALG_SHA_512)) && \\\n    !defined(MBEDTLS_ENTROPY_FORCE_SHA256)\n#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR\n#define MBEDTLS_ENTROPY_MD  MBEDTLS_MD_SHA512\n#define MBEDTLS_ENTROPY_BLOCK_SIZE      64      /**< Block size of entropy accumulator (SHA-512) */\n#else\n#if (defined(MBEDTLS_MD_CAN_SHA256) || defined(PSA_WANT_ALG_SHA_256))\n#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR\n#define MBEDTLS_ENTROPY_MD  MBEDTLS_MD_SHA256\n#define MBEDTLS_ENTROPY_BLOCK_SIZE      32      /**< Block size of entropy accumulator (SHA-256) */\n#endif\n#endif\n\n#if defined(MBEDTLS_THREADING_C)\n#include \"mbedtls/threading.h\"\n#endif\n\n\n/** Critical entropy source failure. */\n#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED                 -0x003C\n/** No more sources can be added. */\n#define MBEDTLS_ERR_ENTROPY_MAX_SOURCES                   -0x003E\n/** No sources have been added to poll. */\n#define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED            -0x0040\n/** No strong sources have been added to poll. */\n#define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE              -0x003D\n/** Read/write error in file. */\n#define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR                 -0x003F\n\n/**\n * \\name SECTION: Module settings\n *\n * The configuration options you can set for this module are in this section.\n * Either change them in mbedtls_config.h or define them on the compiler command line.\n * \\{\n */\n\n#if !defined(MBEDTLS_ENTROPY_MAX_SOURCES)\n#define MBEDTLS_ENTROPY_MAX_SOURCES     20      /**< Maximum number of sources supported */\n#endif\n\n#if !defined(MBEDTLS_ENTROPY_MAX_GATHER)\n#define MBEDTLS_ENTROPY_MAX_GATHER      128     /**< Maximum amount requested from entropy sources */\n#endif\n\n/** \\} name SECTION: Module settings */\n\n#define MBEDTLS_ENTROPY_MAX_SEED_SIZE   1024    /**< Maximum size of seed we read from seed file */\n#define MBEDTLS_ENTROPY_SOURCE_MANUAL   MBEDTLS_ENTROPY_MAX_SOURCES\n\n#define MBEDTLS_ENTROPY_SOURCE_STRONG   1       /**< Entropy source is strong   */\n#define MBEDTLS_ENTROPY_SOURCE_WEAK     0       /**< Entropy source is weak     */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief           Entropy poll callback pointer\n *\n * \\param data      Callback-specific data pointer\n * \\param output    Data to fill\n * \\param len       Maximum size to provide\n * \\param olen      The actual amount of bytes put into the buffer (Can be 0)\n *\n * \\return          0 if no critical failures occurred,\n *                  MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise\n */\ntypedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len,\n                                            size_t *olen);\n\n/**\n * \\brief           Entropy source state\n */\ntypedef struct mbedtls_entropy_source_state {\n    mbedtls_entropy_f_source_ptr    MBEDTLS_PRIVATE(f_source);   /**< The entropy source callback */\n    void *MBEDTLS_PRIVATE(p_source);             /**< The callback data pointer */\n    size_t          MBEDTLS_PRIVATE(size);       /**< Amount received in bytes */\n    size_t          MBEDTLS_PRIVATE(threshold);  /**< Minimum bytes required before release */\n    int             MBEDTLS_PRIVATE(strong);     /**< Is the source strong? */\n}\nmbedtls_entropy_source_state;\n\n/**\n * \\brief           Entropy context structure\n */\ntypedef struct mbedtls_entropy_context {\n    mbedtls_md_context_t  MBEDTLS_PRIVATE(accumulator);\n    int MBEDTLS_PRIVATE(accumulator_started); /* 0 after init.\n                                               * 1 after the first update.\n                                               * -1 after free. */\n    int             MBEDTLS_PRIVATE(source_count); /* Number of entries used in source. */\n    mbedtls_entropy_source_state    MBEDTLS_PRIVATE(source)[MBEDTLS_ENTROPY_MAX_SOURCES];\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex);    /*!< mutex                  */\n#endif\n#if defined(MBEDTLS_ENTROPY_NV_SEED)\n    int MBEDTLS_PRIVATE(initial_entropy_run);\n#endif\n}\nmbedtls_entropy_context;\n\n#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)\n/**\n * \\brief           Platform-specific entropy poll callback\n */\nint mbedtls_platform_entropy_poll(void *data,\n                                  unsigned char *output, size_t len, size_t *olen);\n#endif\n\n/**\n * \\brief           Initialize the context\n *\n * \\param ctx       Entropy context to initialize\n */\nvoid mbedtls_entropy_init(mbedtls_entropy_context *ctx);\n\n/**\n * \\brief           Free the data in the context\n *\n * \\param ctx       Entropy context to free\n */\nvoid mbedtls_entropy_free(mbedtls_entropy_context *ctx);\n\n/**\n * \\brief           Adds an entropy source to poll\n *                  (Thread-safe if MBEDTLS_THREADING_C is enabled)\n *\n * \\param ctx       Entropy context\n * \\param f_source  Entropy function\n * \\param p_source  Function data\n * \\param threshold Minimum required from source before entropy is released\n *                  ( with mbedtls_entropy_func() ) (in bytes)\n * \\param strong    MBEDTLS_ENTROPY_SOURCE_STRONG or\n *                  MBEDTLS_ENTROPY_SOURCE_WEAK.\n *                  At least one strong source needs to be added.\n *                  Weaker sources (such as the cycle counter) can be used as\n *                  a complement.\n *\n * \\return          0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES\n */\nint mbedtls_entropy_add_source(mbedtls_entropy_context *ctx,\n                               mbedtls_entropy_f_source_ptr f_source, void *p_source,\n                               size_t threshold, int strong);\n\n/**\n * \\brief           Trigger an extra gather poll for the accumulator\n *                  (Thread-safe if MBEDTLS_THREADING_C is enabled)\n *\n * \\param ctx       Entropy context\n *\n * \\return          0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED\n */\nint mbedtls_entropy_gather(mbedtls_entropy_context *ctx);\n\n/**\n * \\brief           Retrieve entropy from the accumulator\n *                  (Maximum length: MBEDTLS_ENTROPY_BLOCK_SIZE)\n *                  (Thread-safe if MBEDTLS_THREADING_C is enabled)\n *\n * \\param data      Entropy context\n * \\param output    Buffer to fill\n * \\param len       Number of bytes desired, must be at most MBEDTLS_ENTROPY_BLOCK_SIZE\n *\n * \\return          0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED\n */\nint mbedtls_entropy_func(void *data, unsigned char *output, size_t len);\n\n/**\n * \\brief           Add data to the accumulator manually\n *                  (Thread-safe if MBEDTLS_THREADING_C is enabled)\n *\n * \\param ctx       Entropy context\n * \\param data      Data to add\n * \\param len       Length of data\n *\n * \\return          0 if successful\n */\nint mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx,\n                                  const unsigned char *data, size_t len);\n\n#if defined(MBEDTLS_ENTROPY_NV_SEED)\n/**\n * \\brief           Trigger an update of the seed file in NV by using the\n *                  current entropy pool.\n *\n * \\param ctx       Entropy context\n *\n * \\return          0 if successful\n */\nint mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx);\n#endif /* MBEDTLS_ENTROPY_NV_SEED */\n\n#if defined(MBEDTLS_FS_IO)\n/**\n * \\brief               Write a seed file\n *\n * \\param ctx           Entropy context\n * \\param path          Name of the file\n *\n * \\return              0 if successful,\n *                      MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or\n *                      MBEDTLS_ERR_ENTROPY_SOURCE_FAILED\n */\nint mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *path);\n\n/**\n * \\brief               Read and update a seed file. Seed is added to this\n *                      instance. No more than MBEDTLS_ENTROPY_MAX_SEED_SIZE bytes are\n *                      read from the seed file. The rest is ignored.\n *\n * \\param ctx           Entropy context\n * \\param path          Name of the file\n *\n * \\return              0 if successful,\n *                      MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error,\n *                      MBEDTLS_ERR_ENTROPY_SOURCE_FAILED\n */\nint mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *path);\n#endif /* MBEDTLS_FS_IO */\n\n#if defined(MBEDTLS_SELF_TEST)\n/**\n * \\brief          Checkup routine\n *\n *                 This module self-test also calls the entropy self-test,\n *                 mbedtls_entropy_source_self_test();\n *\n * \\return         0 if successful, or 1 if a test failed\n */\nint mbedtls_entropy_self_test(int verbose);\n\n#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)\n/**\n * \\brief          Checkup routine\n *\n *                 Verifies the integrity of the hardware entropy source\n *                 provided by the function 'mbedtls_hardware_poll()'.\n *\n *                 Note this is the only hardware entropy source that is known\n *                 at link time, and other entropy sources configured\n *                 dynamically at runtime by the function\n *                 mbedtls_entropy_add_source() will not be tested.\n *\n * \\return         0 if successful, or 1 if a test failed\n */\nint mbedtls_entropy_source_self_test(int verbose);\n#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* entropy.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/error.h",
    "content": "/**\n * \\file error.h\n *\n * \\brief Error to string translation\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_ERROR_H\n#define MBEDTLS_ERROR_H\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n\n/**\n * Error code layout.\n *\n * Currently we try to keep all error codes within the negative space of 16\n * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In\n * addition we'd like to give two layers of information on the error if\n * possible.\n *\n * For that purpose the error codes are segmented in the following manner:\n *\n * 16 bit error code bit-segmentation\n *\n * 1 bit  - Unused (sign bit)\n * 3 bits - High level module ID\n * 5 bits - Module-dependent error code\n * 7 bits - Low level module errors\n *\n * For historical reasons, low-level error codes are divided in even and odd,\n * even codes were assigned first, and -1 is reserved for other errors.\n *\n * Low-level module errors (0x0002-0x007E, 0x0001-0x007F)\n *\n * Module   Nr  Codes assigned\n * ERROR     2  0x006E          0x0001\n * MPI       7  0x0002-0x0010\n * GCM       3  0x0012-0x0016   0x0013-0x0013\n * THREADING 3  0x001A-0x001E\n * AES       5  0x0020-0x0022   0x0021-0x0025\n * CAMELLIA  3  0x0024-0x0026   0x0027-0x0027\n * BASE64    2  0x002A-0x002C\n * OID       1  0x002E-0x002E   0x000B-0x000B\n * PADLOCK   1  0x0030-0x0030\n * DES       2  0x0032-0x0032   0x0033-0x0033\n * CTR_DBRG  4  0x0034-0x003A\n * ENTROPY   3  0x003C-0x0040   0x003D-0x003F\n * NET      13  0x0042-0x0052   0x0043-0x0049\n * ARIA      4  0x0058-0x005E\n * ASN1      7  0x0060-0x006C\n * CMAC      1  0x007A-0x007A\n * PBKDF2    1  0x007C-0x007C\n * HMAC_DRBG 4                  0x0003-0x0009\n * CCM       3                  0x000D-0x0011\n * MD5       1                  0x002F-0x002F\n * RIPEMD160 1                  0x0031-0x0031\n * SHA1      1                  0x0035-0x0035 0x0073-0x0073\n * SHA256    1                  0x0037-0x0037 0x0074-0x0074\n * SHA512    1                  0x0039-0x0039 0x0075-0x0075\n * SHA-3     1                  0x0076-0x0076\n * CHACHA20  3                  0x0051-0x0055\n * POLY1305  3                  0x0057-0x005B\n * CHACHAPOLY 2 0x0054-0x0056\n * PLATFORM  2  0x0070-0x0072\n * LMS       5  0x0011-0x0019\n *\n * High-level module nr (3 bits - 0x0...-0x7...)\n * Name      ID  Nr of Errors\n * PEM       1   9\n * PKCS#12   1   4 (Started from top)\n * X509      2   20\n * PKCS5     2   4 (Started from top)\n * DHM       3   11\n * PK        3   15 (Started from top)\n * RSA       4   11\n * ECP       4   10 (Started from top)\n * MD        5   5\n * HKDF      5   1 (Started from top)\n * PKCS7     5   12 (Started from 0x5300)\n * SSL       5   3 (Started from 0x5F00)\n * CIPHER    6   8 (Started from 0x6080)\n * SSL       6   22 (Started from top, plus 0x6000)\n * SSL       7   20 (Started from 0x7000, gaps at\n *                   0x7380, 0x7900-0x7980, 0x7A80-0x7E80)\n *\n * Module dependent error code (5 bits 0x.00.-0x.F8.)\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** Generic error */\n#define MBEDTLS_ERR_ERROR_GENERIC_ERROR       -0x0001\n/** This is a bug in the library */\n#define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E\n\n/** Hardware accelerator failed */\n#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED     -0x0070\n/** The requested feature is not supported by the platform */\n#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072\n\n/**\n * \\brief Combines a high-level and low-level error code together.\n *\n *        Wrapper macro for mbedtls_error_add(). See that function for\n *        more details.\n */\n#define MBEDTLS_ERROR_ADD(high, low) \\\n    mbedtls_error_add(high, low, __FILE__, __LINE__)\n\n#if defined(MBEDTLS_TEST_HOOKS)\n/**\n * \\brief Testing hook called before adding/combining two error codes together.\n *        Only used when invasive testing is enabled via MBEDTLS_TEST_HOOKS.\n */\nextern void (*mbedtls_test_hook_error_add)(int, int, const char *, int);\n#endif\n\n/**\n * \\brief Combines a high-level and low-level error code together.\n *\n *        This function can be called directly however it is usually\n *        called via the #MBEDTLS_ERROR_ADD macro.\n *\n *        While a value of zero is not a negative error code, it is still an\n *        error code (that denotes success) and can be combined with both a\n *        negative error code or another value of zero.\n *\n * \\note  When invasive testing is enabled via #MBEDTLS_TEST_HOOKS, also try to\n *        call \\link mbedtls_test_hook_error_add \\endlink.\n *\n * \\param high      high-level error code. See error.h for more details.\n * \\param low       low-level error code. See error.h for more details.\n * \\param file      file where this error code addition occurred.\n * \\param line      line where this error code addition occurred.\n */\nstatic inline int mbedtls_error_add(int high, int low,\n                                    const char *file, int line)\n{\n#if defined(MBEDTLS_TEST_HOOKS)\n    if (*mbedtls_test_hook_error_add != NULL) {\n        (*mbedtls_test_hook_error_add)(high, low, file, line);\n    }\n#endif\n    (void) file;\n    (void) line;\n\n    return high + low;\n}\n\n/**\n * \\brief Translate an Mbed TLS error code into a string representation.\n *        The result is truncated if necessary and always includes a\n *        terminating null byte.\n *\n * \\param errnum    error code\n * \\param buffer    buffer to place representation in\n * \\param buflen    length of the buffer\n */\nvoid mbedtls_strerror(int errnum, char *buffer, size_t buflen);\n\n/**\n * \\brief Translate the high-level part of an Mbed TLS error code into a string\n *        representation.\n *\n * This function returns a const pointer to an un-modifiable string. The caller\n * must not try to modify the string. It is intended to be used mostly for\n * logging purposes.\n *\n * \\param error_code    error code\n *\n * \\return The string representation of the error code, or \\c NULL if the error\n *         code is unknown.\n */\nconst char *mbedtls_high_level_strerr(int error_code);\n\n/**\n * \\brief Translate the low-level part of an Mbed TLS error code into a string\n *        representation.\n *\n * This function returns a const pointer to an un-modifiable string. The caller\n * must not try to modify the string. It is intended to be used mostly for\n * logging purposes.\n *\n * \\param error_code    error code\n *\n * \\return The string representation of the error code, or \\c NULL if the error\n *         code is unknown.\n */\nconst char *mbedtls_low_level_strerr(int error_code);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* error.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/gcm.h",
    "content": "/**\n * \\file gcm.h\n *\n * \\brief This file contains GCM definitions and functions.\n *\n * The Galois/Counter Mode (GCM) for 128-bit block ciphers is defined\n * in <em>D. McGrew, J. Viega, The Galois/Counter Mode of Operation\n * (GCM), Natl. Inst. Stand. Technol.</em>\n *\n * For more information on GCM, see <em>NIST SP 800-38D: Recommendation for\n * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC</em>.\n *\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_GCM_H\n#define MBEDTLS_GCM_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/cipher.h\"\n\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n#include \"mbedtls/block_cipher.h\"\n#endif\n\n#include <stdint.h>\n\n#define MBEDTLS_GCM_ENCRYPT     1\n#define MBEDTLS_GCM_DECRYPT     0\n\n/** Authenticated decryption failed. */\n#define MBEDTLS_ERR_GCM_AUTH_FAILED                       -0x0012\n/** Bad input parameters to function. */\n#define MBEDTLS_ERR_GCM_BAD_INPUT                         -0x0014\n/** An output buffer is too small. */\n#define MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL                  -0x0016\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_GCM_ALT)\n\n#if defined(MBEDTLS_GCM_LARGE_TABLE)\n#define MBEDTLS_GCM_HTABLE_SIZE 256\n#else\n#define MBEDTLS_GCM_HTABLE_SIZE 16\n#endif\n\n/**\n * \\brief          The GCM context structure.\n */\ntypedef struct mbedtls_gcm_context {\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n    mbedtls_block_cipher_context_t MBEDTLS_PRIVATE(block_cipher_ctx);  /*!< The cipher context used. */\n#else\n    mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx);    /*!< The cipher context used. */\n#endif\n    uint64_t MBEDTLS_PRIVATE(H)[MBEDTLS_GCM_HTABLE_SIZE][2]; /*!< Precalculated HTable. */\n    uint64_t MBEDTLS_PRIVATE(len);                           /*!< The total length of the encrypted data. */\n    uint64_t MBEDTLS_PRIVATE(add_len);                       /*!< The total length of the additional data. */\n    unsigned char MBEDTLS_PRIVATE(base_ectr)[16];            /*!< The first ECTR for tag. */\n    unsigned char MBEDTLS_PRIVATE(y)[16];                    /*!< The Y working value. */\n    unsigned char MBEDTLS_PRIVATE(buf)[16];                  /*!< The buf working value. */\n    unsigned char MBEDTLS_PRIVATE(mode);                     /*!< The operation to perform:\n                                                              #MBEDTLS_GCM_ENCRYPT or\n                                                              #MBEDTLS_GCM_DECRYPT. */\n    unsigned char MBEDTLS_PRIVATE(acceleration);             /*!< The acceleration to use. */\n}\nmbedtls_gcm_context;\n\n#else  /* !MBEDTLS_GCM_ALT */\n#include \"gcm_alt.h\"\n#endif /* !MBEDTLS_GCM_ALT */\n\n/**\n * \\brief           This function initializes the specified GCM context,\n *                  to make references valid, and prepares the context\n *                  for mbedtls_gcm_setkey() or mbedtls_gcm_free().\n *\n *                  The function does not bind the GCM context to a particular\n *                  cipher, nor set the key. For this purpose, use\n *                  mbedtls_gcm_setkey().\n *\n * \\param ctx       The GCM context to initialize. This must not be \\c NULL.\n */\nvoid mbedtls_gcm_init(mbedtls_gcm_context *ctx);\n\n/**\n * \\brief           This function associates a GCM context with a\n *                  cipher algorithm and a key.\n *\n * \\param ctx       The GCM context. This must be initialized.\n * \\param cipher    The 128-bit block cipher to use.\n * \\param key       The encryption key. This must be a readable buffer of at\n *                  least \\p keybits bits.\n * \\param keybits   The key size in bits. Valid options are:\n *                  <ul><li>128 bits</li>\n *                  <li>192 bits</li>\n *                  <li>256 bits</li></ul>\n *\n * \\return          \\c 0 on success.\n * \\return          A cipher-specific error code on failure.\n */\nint mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,\n                       mbedtls_cipher_id_t cipher,\n                       const unsigned char *key,\n                       unsigned int keybits);\n\n/**\n * \\brief           This function performs GCM encryption or decryption of a buffer.\n *\n * \\note            The output buffer \\p output can be the same as the input\n *                  buffer \\p input. If \\p output is greater than \\p input, they\n *                  cannot overlap.\n *\n * \\warning         When this function performs a decryption, it outputs the\n *                  authentication tag and does not verify that the data is\n *                  authentic. You should use this function to perform encryption\n *                  only. For decryption, use mbedtls_gcm_auth_decrypt() instead.\n *\n * \\param ctx       The GCM context to use for encryption or decryption. This\n *                  must be initialized.\n * \\param mode      The operation to perform:\n *                  - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption.\n *                    The ciphertext is written to \\p output and the\n *                    authentication tag is written to \\p tag.\n *                  - #MBEDTLS_GCM_DECRYPT to perform decryption.\n *                    The plaintext is written to \\p output and the\n *                    authentication tag is written to \\p tag.\n *                    Note that this mode is not recommended, because it does\n *                    not verify the authenticity of the data. For this reason,\n *                    you should use mbedtls_gcm_auth_decrypt() instead of\n *                    calling this function in decryption mode.\n * \\param length    The length of the input data, which is equal to the length\n *                  of the output data.\n * \\param iv        The initialization vector. This must be a readable buffer of\n *                  at least \\p iv_len Bytes.\n * \\param iv_len    The length of the IV.\n * \\param add       The buffer holding the additional data. This must be of at\n *                  least that size in Bytes.\n * \\param add_len   The length of the additional data.\n * \\param input     The buffer holding the input data. If \\p length is greater\n *                  than zero, this must be a readable buffer of at least that\n *                  size in Bytes.\n * \\param output    The buffer for holding the output data. If \\p length is greater\n *                  than zero, this must be a writable buffer of at least that\n *                  size in Bytes.\n * \\param tag_len   The length of the tag to generate.\n * \\param tag       The buffer for holding the tag. This must be a writable\n *                  buffer of at least \\p tag_len Bytes.\n *\n * \\return          \\c 0 if the encryption or decryption was performed\n *                  successfully. Note that in #MBEDTLS_GCM_DECRYPT mode,\n *                  this does not indicate that the data is authentic.\n * \\return          #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are\n *                  not valid or a cipher-specific error code if the encryption\n *                  or decryption failed.\n */\nint mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,\n                              int mode,\n                              size_t length,\n                              const unsigned char *iv,\n                              size_t iv_len,\n                              const unsigned char *add,\n                              size_t add_len,\n                              const unsigned char *input,\n                              unsigned char *output,\n                              size_t tag_len,\n                              unsigned char *tag);\n\n/**\n * \\brief           This function performs a GCM authenticated decryption of a\n *                  buffer.\n *\n * \\note            The output buffer \\p output can be the same as the input\n *                  buffer \\p input. If \\p output is greater than \\p input, they\n *                  cannot overlap. Implementations which require\n *                  MBEDTLS_GCM_ALT to be enabled may not provide support for\n *                  overlapping buffers.\n *\n * \\param ctx       The GCM context. This must be initialized.\n * \\param length    The length of the ciphertext to decrypt, which is also\n *                  the length of the decrypted plaintext.\n * \\param iv        The initialization vector. This must be a readable buffer\n *                  of at least \\p iv_len Bytes.\n * \\param iv_len    The length of the IV.\n * \\param add       The buffer holding the additional data. This must be of at\n *                  least that size in Bytes.\n * \\param add_len   The length of the additional data.\n * \\param tag       The buffer holding the tag to verify. This must be a\n *                  readable buffer of at least \\p tag_len Bytes.\n * \\param tag_len   The length of the tag to verify.\n * \\param input     The buffer holding the ciphertext. If \\p length is greater\n *                  than zero, this must be a readable buffer of at least that\n *                  size.\n * \\param output    The buffer for holding the decrypted plaintext. If \\p length\n *                  is greater than zero, this must be a writable buffer of at\n *                  least that size.\n *\n * \\return          \\c 0 if successful and authenticated.\n * \\return          #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.\n * \\return          #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are\n *                  not valid or a cipher-specific error code if the decryption\n *                  failed.\n */\nint mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,\n                             size_t length,\n                             const unsigned char *iv,\n                             size_t iv_len,\n                             const unsigned char *add,\n                             size_t add_len,\n                             const unsigned char *tag,\n                             size_t tag_len,\n                             const unsigned char *input,\n                             unsigned char *output);\n\n/**\n * \\brief           This function starts a GCM encryption or decryption\n *                  operation.\n *\n * \\param ctx       The GCM context. This must be initialized.\n * \\param mode      The operation to perform: #MBEDTLS_GCM_ENCRYPT or\n *                  #MBEDTLS_GCM_DECRYPT.\n * \\param iv        The initialization vector. This must be a readable buffer of\n *                  at least \\p iv_len Bytes.\n * \\param iv_len    The length of the IV.\n *\n * \\return          \\c 0 on success.\n */\nint mbedtls_gcm_starts(mbedtls_gcm_context *ctx,\n                       int mode,\n                       const unsigned char *iv,\n                       size_t iv_len);\n\n/**\n * \\brief           This function feeds an input buffer as associated data\n *                  (authenticated but not encrypted data) in a GCM\n *                  encryption or decryption operation.\n *\n *                  Call this function after mbedtls_gcm_starts() to pass\n *                  the associated data. If the associated data is empty,\n *                  you do not need to call this function. You may not\n *                  call this function after calling mbedtls_cipher_update().\n *\n * \\param ctx       The GCM context. This must have been started with\n *                  mbedtls_gcm_starts() and must not have yet received\n *                  any input with mbedtls_gcm_update().\n * \\param add       The buffer holding the additional data, or \\c NULL\n *                  if \\p add_len is \\c 0.\n * \\param add_len   The length of the additional data. If \\c 0,\n *                  \\p add may be \\c NULL.\n *\n * \\return          \\c 0 on success.\n */\nint mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,\n                          const unsigned char *add,\n                          size_t add_len);\n\n/**\n * \\brief           This function feeds an input buffer into an ongoing GCM\n *                  encryption or decryption operation.\n *\n *                  You may call this function zero, one or more times\n *                  to pass successive parts of the input: the plaintext to\n *                  encrypt, or the ciphertext (not including the tag) to\n *                  decrypt. After the last part of the input, call\n *                  mbedtls_gcm_finish().\n *\n *                  This function may produce output in one of the following\n *                  ways:\n *                  - Immediate output: the output length is always equal\n *                    to the input length.\n *                  - Buffered output: the output consists of a whole number\n *                    of 16-byte blocks. If the total input length so far\n *                    (not including associated data) is 16 \\* *B* + *A*\n *                    with *A* < 16 then the total output length is 16 \\* *B*.\n *\n *                  In particular:\n *                  - It is always correct to call this function with\n *                    \\p output_size >= \\p input_length + 15.\n *                  - If \\p input_length is a multiple of 16 for all the calls\n *                    to this function during an operation, then it is\n *                    correct to use \\p output_size = \\p input_length.\n *\n * \\note            The output buffer \\p output can be the same as the input\n *                  buffer \\p input. If \\p output is greater than \\p input, they\n *                  cannot overlap. Implementations which require\n *                  MBEDTLS_GCM_ALT to be enabled may not provide support for\n *                  overlapping buffers.\n *\n * \\param ctx           The GCM context. This must be initialized.\n * \\param input         The buffer holding the input data. If \\p input_length\n *                      is greater than zero, this must be a readable buffer\n *                      of at least \\p input_length bytes.\n * \\param input_length  The length of the input data in bytes.\n * \\param output        The buffer for the output data. If \\p output_size\n *                      is greater than zero, this must be a writable buffer of\n *                      of at least \\p output_size bytes.\n * \\param output_size   The size of the output buffer in bytes.\n *                      See the function description regarding the output size.\n * \\param output_length On success, \\p *output_length contains the actual\n *                      length of the output written in \\p output.\n *                      On failure, the content of \\p *output_length is\n *                      unspecified.\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_GCM_BAD_INPUT on failure:\n *                 total input length too long,\n *                 unsupported input/output buffer overlap detected,\n *                 or \\p output_size too small.\n */\nint mbedtls_gcm_update(mbedtls_gcm_context *ctx,\n                       const unsigned char *input, size_t input_length,\n                       unsigned char *output, size_t output_size,\n                       size_t *output_length);\n\n/**\n * \\brief           This function finishes the GCM operation and generates\n *                  the authentication tag.\n *\n *                  It wraps up the GCM stream, and generates the\n *                  tag. The tag can have a maximum length of 16 Bytes.\n *\n * \\param ctx       The GCM context. This must be initialized.\n * \\param tag       The buffer for holding the tag. This must be a writable\n *                  buffer of at least \\p tag_len Bytes.\n * \\param tag_len   The length of the tag to generate. This must be at least\n *                  four.\n * \\param output    The buffer for the final output.\n *                  If \\p output_size is nonzero, this must be a writable\n *                  buffer of at least \\p output_size bytes.\n * \\param output_size  The size of the \\p output buffer in bytes.\n *                  This must be large enough for the output that\n *                  mbedtls_gcm_update() has not produced. In particular:\n *                  - If mbedtls_gcm_update() produces immediate output,\n *                    or if the total input size is a multiple of \\c 16,\n *                    then mbedtls_gcm_finish() never produces any output,\n *                    so \\p output_size can be \\c 0.\n *                  - \\p output_size never needs to be more than \\c 15.\n * \\param output_length On success, \\p *output_length contains the actual\n *                      length of the output written in \\p output.\n *                      On failure, the content of \\p *output_length is\n *                      unspecified.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_GCM_BAD_INPUT on failure:\n *                  invalid value of \\p tag_len,\n *                  or \\p output_size too small.\n */\nint mbedtls_gcm_finish(mbedtls_gcm_context *ctx,\n                       unsigned char *output, size_t output_size,\n                       size_t *output_length,\n                       unsigned char *tag, size_t tag_len);\n\n/**\n * \\brief           This function clears a GCM context and the underlying\n *                  cipher sub-context.\n *\n * \\param ctx       The GCM context to clear. If this is \\c NULL, the call has\n *                  no effect. Otherwise, this must be initialized.\n */\nvoid mbedtls_gcm_free(mbedtls_gcm_context *ctx);\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/**\n * \\brief          The GCM checkup routine.\n *\n * \\return         \\c 0 on success.\n * \\return         \\c 1 on failure.\n */\nint mbedtls_gcm_self_test(int verbose);\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n\n#endif /* gcm.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/hkdf.h",
    "content": "/**\n * \\file hkdf.h\n *\n * \\brief   This file contains the HKDF interface.\n *\n *          The HMAC-based Extract-and-Expand Key Derivation Function (HKDF) is\n *          specified by RFC 5869.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_HKDF_H\n#define MBEDTLS_HKDF_H\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/md.h\"\n\n/**\n *  \\name HKDF Error codes\n *  \\{\n */\n/** Bad input parameters to function. */\n#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA  -0x5F80\n/** \\} name */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n *  \\brief  This is the HMAC-based Extract-and-Expand Key Derivation Function\n *          (HKDF).\n *\n *  \\param  md        A hash function; md.size denotes the length of the hash\n *                    function output in bytes.\n *  \\param  salt      An optional salt value (a non-secret random value);\n *                    if the salt is not provided, a string of all zeros of\n *                    md.size length is used as the salt.\n *  \\param  salt_len  The length in bytes of the optional \\p salt.\n *  \\param  ikm       The input keying material.\n *  \\param  ikm_len   The length in bytes of \\p ikm.\n *  \\param  info      An optional context and application specific information\n *                    string. This can be a zero-length string.\n *  \\param  info_len  The length of \\p info in bytes.\n *  \\param  okm       The output keying material of \\p okm_len bytes.\n *  \\param  okm_len   The length of the output keying material in bytes. This\n *                    must be less than or equal to 255 * md.size bytes.\n *\n *  \\return 0 on success.\n *  \\return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid.\n *  \\return An MBEDTLS_ERR_MD_* error for errors returned from the underlying\n *          MD layer.\n */\nint mbedtls_hkdf(const mbedtls_md_info_t *md, const unsigned char *salt,\n                 size_t salt_len, const unsigned char *ikm, size_t ikm_len,\n                 const unsigned char *info, size_t info_len,\n                 unsigned char *okm, size_t okm_len);\n\n/**\n *  \\brief  Take the input keying material \\p ikm and extract from it a\n *          fixed-length pseudorandom key \\p prk.\n *\n *  \\warning    This function should only be used if the security of it has been\n *              studied and established in that particular context (eg. TLS 1.3\n *              key schedule). For standard HKDF security guarantees use\n *              \\c mbedtls_hkdf instead.\n *\n *  \\param       md        A hash function; md.size denotes the length of the\n *                         hash function output in bytes.\n *  \\param       salt      An optional salt value (a non-secret random value);\n *                         if the salt is not provided, a string of all zeros\n *                         of md.size length is used as the salt.\n *  \\param       salt_len  The length in bytes of the optional \\p salt.\n *  \\param       ikm       The input keying material.\n *  \\param       ikm_len   The length in bytes of \\p ikm.\n *  \\param[out]  prk       A pseudorandom key of at least md.size bytes.\n *\n *  \\return 0 on success.\n *  \\return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid.\n *  \\return An MBEDTLS_ERR_MD_* error for errors returned from the underlying\n *          MD layer.\n */\nint mbedtls_hkdf_extract(const mbedtls_md_info_t *md,\n                         const unsigned char *salt, size_t salt_len,\n                         const unsigned char *ikm, size_t ikm_len,\n                         unsigned char *prk);\n\n/**\n *  \\brief  Expand the supplied \\p prk into several additional pseudorandom\n *          keys, which is the output of the HKDF.\n *\n *  \\warning    This function should only be used if the security of it has been\n *              studied and established in that particular context (eg. TLS 1.3\n *              key schedule). For standard HKDF security guarantees use\n *              \\c mbedtls_hkdf instead.\n *\n *  \\param  md        A hash function; md.size denotes the length of the hash\n *                    function output in bytes.\n *  \\param  prk       A pseudorandom key of at least md.size bytes. \\p prk is\n *                    usually the output from the HKDF extract step.\n *  \\param  prk_len   The length in bytes of \\p prk.\n *  \\param  info      An optional context and application specific information\n *                    string. This can be a zero-length string.\n *  \\param  info_len  The length of \\p info in bytes.\n *  \\param  okm       The output keying material of \\p okm_len bytes.\n *  \\param  okm_len   The length of the output keying material in bytes. This\n *                    must be less than or equal to 255 * md.size bytes.\n *\n *  \\return 0 on success.\n *  \\return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid.\n *  \\return An MBEDTLS_ERR_MD_* error for errors returned from the underlying\n *          MD layer.\n */\nint mbedtls_hkdf_expand(const mbedtls_md_info_t *md, const unsigned char *prk,\n                        size_t prk_len, const unsigned char *info,\n                        size_t info_len, unsigned char *okm, size_t okm_len);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* hkdf.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/hmac_drbg.h",
    "content": "/**\n * \\file hmac_drbg.h\n *\n * \\brief The HMAC_DRBG pseudorandom generator.\n *\n * This module implements the HMAC_DRBG pseudorandom generator described\n * in <em>NIST SP 800-90A: Recommendation for Random Number Generation Using\n * Deterministic Random Bit Generators</em>.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_HMAC_DRBG_H\n#define MBEDTLS_HMAC_DRBG_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/md.h\"\n\n#if defined(MBEDTLS_THREADING_C)\n#include \"mbedtls/threading.h\"\n#endif\n\n/*\n * Error codes\n */\n/** Too many random requested in single call. */\n#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG              -0x0003\n/** Input too large (Entropy + additional). */\n#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG                -0x0005\n/** Read/write error in file. */\n#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR                -0x0007\n/** The entropy source failed. */\n#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED        -0x0009\n\n/**\n * \\name SECTION: Module settings\n *\n * The configuration options you can set for this module are in this section.\n * Either change them in mbedtls_config.h or define them on the compiler command line.\n * \\{\n */\n\n#if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL)\n#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL   10000   /**< Interval before reseed is performed by default */\n#endif\n\n#if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT)\n#define MBEDTLS_HMAC_DRBG_MAX_INPUT         256     /**< Maximum number of additional input bytes */\n#endif\n\n#if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST)\n#define MBEDTLS_HMAC_DRBG_MAX_REQUEST       1024    /**< Maximum number of requested bytes per call */\n#endif\n\n#if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT)\n#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT    384     /**< Maximum size of (re)seed buffer */\n#endif\n\n/** \\} name SECTION: Module settings */\n\n#define MBEDTLS_HMAC_DRBG_PR_OFF   0   /**< No prediction resistance       */\n#define MBEDTLS_HMAC_DRBG_PR_ON    1   /**< Prediction resistance enabled  */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * HMAC_DRBG context.\n */\ntypedef struct mbedtls_hmac_drbg_context {\n    /* Working state: the key K is not stored explicitly,\n     * but is implied by the HMAC context */\n    mbedtls_md_context_t MBEDTLS_PRIVATE(md_ctx);                    /*!< HMAC context (inc. K)  */\n    unsigned char MBEDTLS_PRIVATE(V)[MBEDTLS_MD_MAX_SIZE];  /*!< V in the spec          */\n    int MBEDTLS_PRIVATE(reseed_counter);                     /*!< reseed counter         */\n\n    /* Administrative state */\n    size_t MBEDTLS_PRIVATE(entropy_len);         /*!< entropy bytes grabbed on each (re)seed */\n    int MBEDTLS_PRIVATE(prediction_resistance);  /*!< enable prediction resistance (Automatic\n                                                    reseed before every random generation) */\n    int MBEDTLS_PRIVATE(reseed_interval);        /*!< reseed interval   */\n\n    /* Callbacks */\n    int(*MBEDTLS_PRIVATE(f_entropy))(void *, unsigned char *, size_t);  /*!< entropy function */\n    void *MBEDTLS_PRIVATE(p_entropy);            /*!< context for the entropy function        */\n\n#if defined(MBEDTLS_THREADING_C)\n    /* Invariant: the mutex is initialized if and only if\n     * md_ctx->md_info != NULL. This means that the mutex is initialized\n     * during the initial seeding in mbedtls_hmac_drbg_seed() or\n     * mbedtls_hmac_drbg_seed_buf() and freed in mbedtls_ctr_drbg_free().\n     *\n     * Note that this invariant may change without notice. Do not rely on it\n     * and do not access the mutex directly in application code.\n     */\n    mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex);\n#endif\n} mbedtls_hmac_drbg_context;\n\n/**\n * \\brief               HMAC_DRBG context initialization.\n *\n * This function makes the context ready for mbedtls_hmac_drbg_seed(),\n * mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free().\n *\n * \\note                The reseed interval is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL\n *                      by default. Override this value by calling\n *                      mbedtls_hmac_drbg_set_reseed_interval().\n *\n * \\param ctx           HMAC_DRBG context to be initialized.\n */\nvoid mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx);\n\n/**\n * \\brief               HMAC_DRBG initial seeding.\n *\n * Set the initial seed and set up the entropy source for future reseeds.\n *\n * A typical choice for the \\p f_entropy and \\p p_entropy parameters is\n * to use the entropy module:\n * - \\p f_entropy is mbedtls_entropy_func();\n * - \\p p_entropy is an instance of ::mbedtls_entropy_context initialized\n *   with mbedtls_entropy_init() (which registers the platform's default\n *   entropy sources).\n *\n * You can provide a personalization string in addition to the\n * entropy source, to make this instantiation as unique as possible.\n *\n * \\note                By default, the security strength as defined by NIST is:\n *                      - 128 bits if \\p md_info is SHA-1;\n *                      - 192 bits if \\p md_info is SHA-224;\n *                      - 256 bits if \\p md_info is SHA-256, SHA-384 or SHA-512.\n *                      Note that SHA-256 is just as efficient as SHA-224.\n *                      The security strength can be reduced if a smaller\n *                      entropy length is set with\n *                      mbedtls_hmac_drbg_set_entropy_len().\n *\n * \\note                The default entropy length is the security strength\n *                      (converted from bits to bytes). You can override\n *                      it by calling mbedtls_hmac_drbg_set_entropy_len().\n *\n * \\note                During the initial seeding, this function calls\n *                      the entropy source to obtain a nonce\n *                      whose length is half the entropy length.\n */\n#if defined(MBEDTLS_THREADING_C)\n/**\n * \\note                When Mbed TLS is built with threading support,\n *                      after this function returns successfully,\n *                      it is safe to call mbedtls_hmac_drbg_random()\n *                      from multiple threads. Other operations, including\n *                      reseeding, are not thread-safe.\n */\n#endif /* MBEDTLS_THREADING_C */\n/**\n * \\param ctx           HMAC_DRBG context to be seeded.\n * \\param md_info       MD algorithm to use for HMAC_DRBG.\n * \\param f_entropy     The entropy callback, taking as arguments the\n *                      \\p p_entropy context, the buffer to fill, and the\n *                      length of the buffer.\n *                      \\p f_entropy is always called with a length that is\n *                      less than or equal to the entropy length.\n * \\param p_entropy     The entropy context to pass to \\p f_entropy.\n * \\param custom        The personalization string.\n *                      This can be \\c NULL, in which case the personalization\n *                      string is empty regardless of the value of \\p len.\n * \\param len           The length of the personalization string.\n *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT\n *                      and also at most\n *                      #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \\c entropy_len * 3 / 2\n *                      where \\c entropy_len is the entropy length\n *                      described above.\n *\n * \\return              \\c 0 if successful.\n * \\return              #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \\p md_info is\n *                      invalid.\n * \\return              #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough\n *                      memory to allocate context data.\n * \\return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED\n *                      if the call to \\p f_entropy failed.\n */\nint mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context *ctx,\n                           const mbedtls_md_info_t *md_info,\n                           int (*f_entropy)(void *, unsigned char *, size_t),\n                           void *p_entropy,\n                           const unsigned char *custom,\n                           size_t len);\n\n/**\n * \\brief               Initialisation of simplified HMAC_DRBG (never reseeds).\n *\n * This function is meant for use in algorithms that need a pseudorandom\n * input such as deterministic ECDSA.\n */\n#if defined(MBEDTLS_THREADING_C)\n/**\n * \\note                When Mbed TLS is built with threading support,\n *                      after this function returns successfully,\n *                      it is safe to call mbedtls_hmac_drbg_random()\n *                      from multiple threads. Other operations, including\n *                      reseeding, are not thread-safe.\n */\n#endif /* MBEDTLS_THREADING_C */\n/**\n * \\param ctx           HMAC_DRBG context to be initialised.\n * \\param md_info       MD algorithm to use for HMAC_DRBG.\n * \\param data          Concatenation of the initial entropy string and\n *                      the additional data.\n * \\param data_len      Length of \\p data in bytes.\n *\n * \\return              \\c 0 if successful. or\n * \\return              #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \\p md_info is\n *                      invalid.\n * \\return              #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough\n *                      memory to allocate context data.\n */\nint mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context *ctx,\n                               const mbedtls_md_info_t *md_info,\n                               const unsigned char *data, size_t data_len);\n\n/**\n * \\brief               This function turns prediction resistance on or off.\n *                      The default value is off.\n *\n * \\note                If enabled, entropy is gathered at the beginning of\n *                      every call to mbedtls_hmac_drbg_random_with_add()\n *                      or mbedtls_hmac_drbg_random().\n *                      Only use this if your entropy source has sufficient\n *                      throughput.\n *\n * \\param ctx           The HMAC_DRBG context.\n * \\param resistance    #MBEDTLS_HMAC_DRBG_PR_ON or #MBEDTLS_HMAC_DRBG_PR_OFF.\n */\nvoid mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context *ctx,\n                                                 int resistance);\n\n/**\n * \\brief               This function sets the amount of entropy grabbed on each\n *                      seed or reseed.\n *\n * See the documentation of mbedtls_hmac_drbg_seed() for the default value.\n *\n * \\param ctx           The HMAC_DRBG context.\n * \\param len           The amount of entropy to grab, in bytes.\n */\nvoid mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context *ctx,\n                                       size_t len);\n\n/**\n * \\brief               Set the reseed interval.\n *\n * The reseed interval is the number of calls to mbedtls_hmac_drbg_random()\n * or mbedtls_hmac_drbg_random_with_add() after which the entropy function\n * is called again.\n *\n * The default value is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL.\n *\n * \\param ctx           The HMAC_DRBG context.\n * \\param interval      The reseed interval.\n */\nvoid mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context *ctx,\n                                           int interval);\n\n/**\n * \\brief               This function updates the state of the HMAC_DRBG context.\n *\n * \\note                This function is not thread-safe. It is not safe\n *                      to call this function if another thread might be\n *                      concurrently obtaining random numbers from the same\n *                      context or updating or reseeding the same context.\n *\n * \\param ctx           The HMAC_DRBG context.\n * \\param additional    The data to update the state with.\n *                      If this is \\c NULL, there is no additional data.\n * \\param add_len       Length of \\p additional in bytes.\n *                      Unused if \\p additional is \\c NULL.\n *\n * \\return              \\c 0 on success, or an error from the underlying\n *                      hash calculation.\n */\nint mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx,\n                             const unsigned char *additional, size_t add_len);\n\n/**\n * \\brief               This function reseeds the HMAC_DRBG context, that is\n *                      extracts data from the entropy source.\n *\n * \\note                This function is not thread-safe. It is not safe\n *                      to call this function if another thread might be\n *                      concurrently obtaining random numbers from the same\n *                      context or updating or reseeding the same context.\n *\n * \\param ctx           The HMAC_DRBG context.\n * \\param additional    Additional data to add to the state.\n *                      If this is \\c NULL, there is no additional data\n *                      and \\p len should be \\c 0.\n * \\param len           The length of the additional data.\n *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT\n *                      and also at most\n *                      #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \\c entropy_len\n *                      where \\c entropy_len is the entropy length\n *                      (see mbedtls_hmac_drbg_set_entropy_len()).\n *\n * \\return              \\c 0 if successful.\n * \\return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED\n *                      if a call to the entropy function failed.\n */\nint mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context *ctx,\n                             const unsigned char *additional, size_t len);\n\n/**\n * \\brief   This function updates an HMAC_DRBG instance with additional\n *          data and uses it to generate random data.\n *\n * This function automatically reseeds if the reseed counter is exceeded\n * or prediction resistance is enabled.\n *\n * \\note                This function is not thread-safe. It is not safe\n *                      to call this function if another thread might be\n *                      concurrently obtaining random numbers from the same\n *                      context or updating or reseeding the same context.\n *\n * \\param p_rng         The HMAC_DRBG context. This must be a pointer to a\n *                      #mbedtls_hmac_drbg_context structure.\n * \\param output        The buffer to fill.\n * \\param output_len    The length of the buffer in bytes.\n *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST.\n * \\param additional    Additional data to update with.\n *                      If this is \\c NULL, there is no additional data\n *                      and \\p add_len should be \\c 0.\n * \\param add_len       The length of the additional data.\n *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT.\n *\n * \\return              \\c 0 if successful.\n * \\return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED\n *                      if a call to the entropy source failed.\n * \\return              #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if\n *                      \\p output_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST.\n * \\return              #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if\n *                      \\p add_len > #MBEDTLS_HMAC_DRBG_MAX_INPUT.\n */\nint mbedtls_hmac_drbg_random_with_add(void *p_rng,\n                                      unsigned char *output, size_t output_len,\n                                      const unsigned char *additional,\n                                      size_t add_len);\n\n/**\n * \\brief   This function uses HMAC_DRBG to generate random data.\n *\n * This function automatically reseeds if the reseed counter is exceeded\n * or prediction resistance is enabled.\n */\n#if defined(MBEDTLS_THREADING_C)\n/**\n * \\note                When Mbed TLS is built with threading support,\n *                      it is safe to call mbedtls_ctr_drbg_random()\n *                      from multiple threads. Other operations, including\n *                      reseeding, are not thread-safe.\n */\n#endif /* MBEDTLS_THREADING_C */\n/**\n * \\param p_rng         The HMAC_DRBG context. This must be a pointer to a\n *                      #mbedtls_hmac_drbg_context structure.\n * \\param output        The buffer to fill.\n * \\param out_len       The length of the buffer in bytes.\n *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST.\n *\n * \\return              \\c 0 if successful.\n * \\return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED\n *                      if a call to the entropy source failed.\n * \\return              #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if\n *                      \\p out_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST.\n */\nint mbedtls_hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len);\n\n/**\n * \\brief               This function resets HMAC_DRBG context to the state immediately\n *                      after initial call of mbedtls_hmac_drbg_init().\n *\n * \\param ctx           The HMAC_DRBG context to free.\n */\nvoid mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context *ctx);\n\n#if defined(MBEDTLS_FS_IO)\n/**\n * \\brief               This function writes a seed file.\n *\n * \\param ctx           The HMAC_DRBG context.\n * \\param path          The name of the file.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error.\n * \\return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on reseed\n *                      failure.\n */\nint mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path);\n\n/**\n * \\brief               This function reads and updates a seed file. The seed\n *                      is added to this instance.\n *\n * \\param ctx           The HMAC_DRBG context.\n * \\param path          The name of the file.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error.\n * \\return              #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on\n *                      reseed failure.\n * \\return              #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if the existing\n *                      seed file is too large.\n */\nint mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path);\n#endif /* MBEDTLS_FS_IO */\n\n\n#if defined(MBEDTLS_SELF_TEST)\n/**\n * \\brief               The HMAC_DRBG Checkup routine.\n *\n * \\return              \\c 0 if successful.\n * \\return              \\c 1 if the test failed.\n */\nint mbedtls_hmac_drbg_self_test(int verbose);\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* hmac_drbg.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/lms.h",
    "content": "/**\n * \\file lms.h\n *\n * \\brief This file provides an API for the LMS post-quantum-safe stateful-hash\n          public-key signature scheme as defined in RFC8554 and NIST.SP.200-208.\n *        This implementation currently only supports a single parameter set\n *        MBEDTLS_LMS_SHA256_M32_H10 in order to reduce complexity. This is one\n *        of the signature schemes recommended by the IETF draft SUIT standard\n *        for IOT firmware upgrades (RFC9019).\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_LMS_H\n#define MBEDTLS_LMS_H\n\n#include <stdint.h>\n#include <stddef.h>\n\n#include \"mbedtls/private_access.h\"\n#include \"mbedtls/build_info.h\"\n\n#define MBEDTLS_ERR_LMS_BAD_INPUT_DATA   -0x0011 /**< Bad data has been input to an LMS function */\n#define MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS -0x0013 /**< Specified LMS key has utilised all of its private keys */\n#define MBEDTLS_ERR_LMS_VERIFY_FAILED    -0x0015 /**< LMS signature verification failed */\n#define MBEDTLS_ERR_LMS_ALLOC_FAILED     -0x0017 /**< LMS failed to allocate space for a private key */\n#define MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL -0x0019 /**< Input/output buffer is too small to contain requited data */\n\n/* Currently only defined for SHA256, 32 is the max hash output size */\n#define MBEDTLS_LMOTS_N_HASH_LEN_MAX           (32u)\n#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX    (34u)\n#define MBEDTLS_LMOTS_N_HASH_LEN(type)         ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 32u : 0)\n#define MBEDTLS_LMOTS_I_KEY_ID_LEN             (16u)\n#define MBEDTLS_LMOTS_Q_LEAF_ID_LEN            (4u)\n#define MBEDTLS_LMOTS_TYPE_LEN                 (4u)\n#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type)  ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 34u : 0)\n#define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) (MBEDTLS_LMOTS_N_HASH_LEN(type))\n\n#define MBEDTLS_LMOTS_SIG_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \\\n                                     MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) + \\\n                                     (MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) * \\\n                                      MBEDTLS_LMOTS_N_HASH_LEN(type)))\n\n\n#define MBEDTLS_LMS_TYPE_LEN            (4)\n#define MBEDTLS_LMS_H_TREE_HEIGHT(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 10u : 0)\n\n/* The length of a hash output, Currently only implemented for SHA256.\n * Max is 32 bytes.\n */\n#define MBEDTLS_LMS_M_NODE_BYTES(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 32 : 0)\n#define MBEDTLS_LMS_M_NODE_BYTES_MAX 32\n\n#define MBEDTLS_LMS_SIG_LEN(type, otstype) (MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \\\n                                            MBEDTLS_LMOTS_SIG_LEN(otstype) + \\\n                                            MBEDTLS_LMS_TYPE_LEN + \\\n                                            (MBEDTLS_LMS_H_TREE_HEIGHT(type) * \\\n                                             MBEDTLS_LMS_M_NODE_BYTES(type)))\n\n#define MBEDTLS_LMS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMS_TYPE_LEN + \\\n                                          MBEDTLS_LMOTS_TYPE_LEN + \\\n                                          MBEDTLS_LMOTS_I_KEY_ID_LEN + \\\n                                          MBEDTLS_LMS_M_NODE_BYTES(type))\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** The Identifier of the LMS parameter set, as per\n * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml\n * We are only implementing a subset of the types, particularly H10, for the sake of simplicity.\n */\ntypedef enum {\n    MBEDTLS_LMS_SHA256_M32_H10 = 0x6,\n} mbedtls_lms_algorithm_type_t;\n\n/** The Identifier of the LMOTS parameter set, as per\n *  https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml.\n *  We are only implementing a subset of the types, particularly N32_W8, for the sake of simplicity.\n */\ntypedef enum {\n    MBEDTLS_LMOTS_SHA256_N32_W8 = 4\n} mbedtls_lmots_algorithm_type_t;\n\n/** LMOTS parameters structure.\n *\n * This contains the metadata associated with an LMOTS key, detailing the\n * algorithm type, the key ID, and the leaf identifier should be key be part of\n * a LMS key.\n */\ntypedef struct {\n    unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key\n                                                                                    identifier. */\n    unsigned char MBEDTLS_PRIVATE(q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN]); /*!< Which\n                                                                                      leaf of the LMS key this is.\n                                                                                      0 if the key is not part of an LMS key. */\n    mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LM-OTS key type identifier as\n                                                               per IANA. Only SHA256_N32_W8 is\n                                                               currently supported. */\n} mbedtls_lmots_parameters_t;\n\n/** LMOTS public context structure.\n *\n * A LMOTS public key is a hash output, and the applicable parameter set.\n *\n * The context must be initialized before it is used. A public key must either\n * be imported or generated from a private context.\n *\n * \\dot\n * digraph lmots_public_t {\n *   UNINITIALIZED -> INIT [label=\"init\"];\n *   HAVE_PUBLIC_KEY -> INIT [label=\"free\"];\n *   INIT -> HAVE_PUBLIC_KEY [label=\"import_public_key\"];\n *   INIT -> HAVE_PUBLIC_KEY [label=\"calculate_public_key from private key\"];\n *   HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label=\"export_public_key\"];\n * }\n * \\enddot\n */\ntypedef struct {\n    mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params);\n    unsigned char MBEDTLS_PRIVATE(public_key)[MBEDTLS_LMOTS_N_HASH_LEN_MAX];\n    unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key.\n                                                       Boolean values only. */\n} mbedtls_lmots_public_t;\n\n#if defined(MBEDTLS_LMS_PRIVATE)\n/** LMOTS private context structure.\n *\n * A LMOTS private key is one hash output for each of digit of the digest +\n * checksum, and the applicable parameter set.\n *\n * The context must be initialized before it is used. A public key must either\n * be imported or generated from a private context.\n *\n * \\dot\n * digraph lmots_public_t {\n *   UNINITIALIZED -> INIT [label=\"init\"];\n *   HAVE_PRIVATE_KEY -> INIT [label=\"free\"];\n *   INIT -> HAVE_PRIVATE_KEY [label=\"generate_private_key\"];\n *   HAVE_PRIVATE_KEY -> INIT [label=\"sign\"];\n * }\n * \\enddot\n */\ntypedef struct {\n    mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params);\n    unsigned char MBEDTLS_PRIVATE(private_key)[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][\n        MBEDTLS_LMOTS_N_HASH_LEN_MAX];\n    unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key.\n                                                        Boolean values only. */\n} mbedtls_lmots_private_t;\n#endif /* defined(MBEDTLS_LMS_PRIVATE) */\n\n\n/** LMS parameters structure.\n *\n * This contains the metadata associated with an LMS key, detailing the\n * algorithm type, the type of the underlying OTS algorithm, and the key ID.\n */\ntypedef struct {\n    unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key\n                                                                                    identifier. */\n    mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(otstype); /*!< The LM-OTS key type identifier as\n                                                                per IANA. Only SHA256_N32_W8 is\n                                                                currently supported. */\n    mbedtls_lms_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LMS key type identifier as per\n                                                             IANA. Only SHA256_M32_H10 is currently\n                                                             supported. */\n} mbedtls_lms_parameters_t;\n\n/** LMS public context structure.\n *\n * A LMS public key is the hash output that is the root of the Merkle tree, and\n * the applicable parameter set\n *\n * The context must be initialized before it is used. A public key must either\n * be imported or generated from a private context.\n *\n * \\dot\n * digraph lms_public_t {\n *   UNINITIALIZED -> INIT [label=\"init\"];\n *   HAVE_PUBLIC_KEY -> INIT [label=\"free\"];\n *   INIT -> HAVE_PUBLIC_KEY [label=\"import_public_key\"];\n *   INIT -> HAVE_PUBLIC_KEY [label=\"calculate_public_key from private key\"];\n *   HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label=\"export_public_key\"];\n * }\n * \\enddot\n */\ntypedef struct {\n    mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params);\n    unsigned char MBEDTLS_PRIVATE(T_1_pub_key)[MBEDTLS_LMS_M_NODE_BYTES_MAX]; /*!< The public key, in\n                                                                                 the form of the Merkle tree root node. */\n    unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key.\n                                                       Boolean values only. */\n} mbedtls_lms_public_t;\n\n\n#if defined(MBEDTLS_LMS_PRIVATE)\n/** LMS private context structure.\n *\n * A LMS private key is a set of LMOTS private keys, an index to the next usable\n * key, and the applicable parameter set.\n *\n * The context must be initialized before it is used. A public key must either\n * be imported or generated from a private context.\n *\n * \\dot\n * digraph lms_public_t {\n *   UNINITIALIZED -> INIT [label=\"init\"];\n *   HAVE_PRIVATE_KEY -> INIT [label=\"free\"];\n *   INIT -> HAVE_PRIVATE_KEY [label=\"generate_private_key\"];\n * }\n * \\enddot\n */\ntypedef struct {\n    mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params);\n    uint32_t MBEDTLS_PRIVATE(q_next_usable_key); /*!< The index of the next OTS key that has not\n                                                      been used. */\n    mbedtls_lmots_private_t *MBEDTLS_PRIVATE(ots_private_keys); /*!< The private key material. One OTS key\n                                                                   for each leaf node in the Merkle tree. NULL\n                                                                   when have_private_key is 0 and non-NULL otherwise.\n                                                                   is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type) in length. */\n    mbedtls_lmots_public_t *MBEDTLS_PRIVATE(ots_public_keys); /*!< The OTS key public keys, used to\n                                                                   build the Merkle tree. NULL\n                                                                   when have_private_key is 0 and\n                                                                   non-NULL otherwise.\n                                                                   Is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type)\n                                                                   in length. */\n    unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key.\n                                                        Boolean values only. */\n} mbedtls_lms_private_t;\n#endif /* defined(MBEDTLS_LMS_PRIVATE) */\n\n/**\n * \\brief                    This function initializes an LMS public context\n *\n * \\param ctx                The uninitialized LMS context that will then be\n *                           initialized.\n */\nvoid mbedtls_lms_public_init(mbedtls_lms_public_t *ctx);\n\n/**\n * \\brief                    This function uninitializes an LMS public context\n *\n * \\param ctx                The initialized LMS context that will then be\n *                           uninitialized.\n */\nvoid mbedtls_lms_public_free(mbedtls_lms_public_t *ctx);\n\n/**\n * \\brief                    This function imports an LMS public key into a\n *                           public LMS context.\n *\n * \\note                     Before this function is called, the context must\n *                           have been initialized.\n *\n * \\note                     See IETF RFC8554 for details of the encoding of\n *                           this public key.\n *\n * \\param ctx                The initialized LMS context store the key in.\n * \\param key                The buffer from which the key will be read.\n *                           #MBEDTLS_LMS_PUBLIC_KEY_LEN bytes will be read from\n *                           this.\n * \\param key_size           The size of the key being imported.\n *\n * \\return         \\c 0 on success.\n * \\return         A non-zero error code on failure.\n */\nint mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx,\n                                  const unsigned char *key, size_t key_size);\n\n/**\n * \\brief                    This function exports an LMS public key from a\n *                           LMS public context that already contains a public\n *                           key.\n *\n * \\note                     Before this function is called, the context must\n *                           have been initialized and the context must contain\n *                           a public key.\n *\n * \\note                     See IETF RFC8554 for details of the encoding of\n *                           this public key.\n *\n * \\param ctx                The initialized LMS public context that contains\n *                           the public key.\n * \\param key                The buffer into which the key will be output. Must\n *                           be at least #MBEDTLS_LMS_PUBLIC_KEY_LEN in size.\n * \\param key_size           The size of the key buffer.\n * \\param key_len            If not NULL, will be written with the size of the\n *                           key.\n *\n * \\return         \\c 0 on success.\n * \\return         A non-zero error code on failure.\n */\nint mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx,\n                                  unsigned char *key, size_t key_size,\n                                  size_t *key_len);\n\n/**\n * \\brief                    This function verifies a LMS signature, using a\n *                           LMS context that contains a public key.\n *\n * \\note                     Before this function is called, the context must\n *                           have been initialized and must contain a public key\n *                           (either by import or generation).\n *\n * \\param ctx                The initialized LMS public context from which the\n *                           public key will be read.\n * \\param msg                The buffer from which the message will be read.\n * \\param msg_size           The size of the message that will be read.\n * \\param sig                The buf from which the signature will be read.\n *                           #MBEDTLS_LMS_SIG_LEN bytes will be read from\n *                           this.\n * \\param sig_size           The size of the signature to be verified.\n *\n * \\return         \\c 0 on successful verification.\n * \\return         A non-zero error code on failure.\n */\nint mbedtls_lms_verify(const mbedtls_lms_public_t *ctx,\n                       const unsigned char *msg, size_t msg_size,\n                       const unsigned char *sig, size_t sig_size);\n\n#if defined(MBEDTLS_LMS_PRIVATE)\n/**\n * \\brief                    This function initializes an LMS private context\n *\n * \\param ctx                The uninitialized LMS private context that will\n *                           then be initialized. */\nvoid mbedtls_lms_private_init(mbedtls_lms_private_t *ctx);\n\n/**\n * \\brief                    This function uninitializes an LMS private context\n *\n * \\param ctx                The initialized LMS private context that will then\n *                           be uninitialized.\n */\nvoid mbedtls_lms_private_free(mbedtls_lms_private_t *ctx);\n\n/**\n * \\brief                    This function generates an LMS private key, and\n *                           stores in into an LMS private context.\n *\n * \\warning                  This function is **not intended for use in\n *                           production**, due to as-yet unsolved problems with\n *                           handling stateful keys. The API for this function\n *                           may change considerably in future versions.\n *\n * \\note                     The seed must have at least 256 bits of entropy.\n *\n * \\param ctx                The initialized LMOTS context to generate the key\n *                           into.\n * \\param type               The LMS parameter set identifier.\n * \\param otstype            The LMOTS parameter set identifier.\n * \\param f_rng              The RNG function to be used to generate the key ID.\n * \\param p_rng              The RNG context to be passed to f_rng\n * \\param seed               The seed used to deterministically generate the\n *                           key.\n * \\param seed_size          The length of the seed.\n *\n * \\return         \\c 0 on success.\n * \\return         A non-zero error code on failure.\n */\nint mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx,\n                                     mbedtls_lms_algorithm_type_t type,\n                                     mbedtls_lmots_algorithm_type_t otstype,\n                                     mbedtls_f_rng_t *f_rng,\n                                     void *p_rng, const unsigned char *seed,\n                                     size_t seed_size);\n\n/**\n * \\brief                    This function calculates an LMS public key from a\n *                           LMS context that already contains a private key.\n *\n * \\note                     Before this function is called, the context must\n *                           have been initialized and the context must contain\n *                           a private key.\n *\n * \\param ctx                The initialized LMS public context to calculate the key\n *                           from and store it into.\n *\n * \\param priv_ctx           The LMS private context to read the private key\n *                           from. This must have been initialized and contain a\n *                           private key.\n *\n * \\return         \\c 0 on success.\n * \\return         A non-zero error code on failure.\n */\nint mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx,\n                                     const mbedtls_lms_private_t *priv_ctx);\n\n/**\n * \\brief                    This function creates a LMS signature, using a\n *                           LMS context that contains unused private keys.\n *\n * \\warning                  This function is **not intended for use in\n *                           production**, due to as-yet unsolved problems with\n *                           handling stateful keys. The API for this function\n *                           may change considerably in future versions.\n *\n * \\note                     Before this function is called, the context must\n *                           have been initialized and must contain a private\n *                           key.\n *\n * \\note                     Each of the LMOTS private keys inside a LMS private\n *                           key can only be used once. If they are reused, then\n *                           attackers may be able to forge signatures with that\n *                           key. This is all handled transparently, but it is\n *                           important to not perform copy operations on LMS\n *                           contexts that contain private key material.\n *\n * \\param ctx                The initialized LMS private context from which the\n *                           private key will be read.\n * \\param f_rng              The RNG function to be used for signature\n *                           generation.\n * \\param p_rng              The RNG context to be passed to f_rng\n * \\param msg                The buffer from which the message will be read.\n * \\param msg_size           The size of the message that will be read.\n * \\param sig                The buf into which the signature will be stored.\n *                           Must be at least #MBEDTLS_LMS_SIG_LEN in size.\n * \\param sig_size           The size of the buffer the signature will be\n *                           written into.\n * \\param sig_len            If not NULL, will be written with the size of the\n *                           signature.\n *\n * \\return         \\c 0 on success.\n * \\return         A non-zero error code on failure.\n */\nint mbedtls_lms_sign(mbedtls_lms_private_t *ctx,\n                     mbedtls_f_rng_t *f_rng,\n                     void *p_rng, const unsigned char *msg,\n                     unsigned int msg_size, unsigned char *sig, size_t sig_size,\n                     size_t *sig_len);\n#endif /* defined(MBEDTLS_LMS_PRIVATE) */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_LMS_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/mbedtls_config.h",
    "content": "/**\n * \\file mbedtls_config.h\n *\n * \\brief Configuration options (set of defines)\n *\n *  This set of compile-time options may be used to enable\n *  or disable features selectively, and reduce the global\n *  memory footprint.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/**\n * This is an optional version symbol that enables compatibility handling of\n * config files.\n *\n * It is equal to the #MBEDTLS_VERSION_NUMBER of the Mbed TLS version that\n * introduced the config format we want to be compatible with.\n */\n//#define MBEDTLS_CONFIG_VERSION 0x03000000\n\n/**\n * \\name SECTION: System support\n *\n * This section sets system specific settings.\n * \\{\n */\n\n/**\n * \\def MBEDTLS_HAVE_ASM\n *\n * The compiler has support for asm().\n *\n * Requires support for asm() in compiler.\n *\n * Used in:\n *      library/aesni.h\n *      library/aria.c\n *      library/bn_mul.h\n *      library/constant_time.c\n *      library/padlock.h\n *\n * Required by:\n *      MBEDTLS_AESCE_C\n *      MBEDTLS_AESNI_C (on some platforms)\n *      MBEDTLS_PADLOCK_C\n *\n * Comment to disable the use of assembly code.\n */\n#define MBEDTLS_HAVE_ASM\n\n/**\n * \\def MBEDTLS_NO_UDBL_DIVISION\n *\n * The platform lacks support for double-width integer division (64-bit\n * division on a 32-bit platform, 128-bit division on a 64-bit platform).\n *\n * Used in:\n *      include/mbedtls/bignum.h\n *      library/bignum.c\n *\n * The bignum code uses double-width division to speed up some operations.\n * Double-width division is often implemented in software that needs to\n * be linked with the program. The presence of a double-width integer\n * type is usually detected automatically through preprocessor macros,\n * but the automatic detection cannot know whether the code needs to\n * and can be linked with an implementation of division for that type.\n * By default division is assumed to be usable if the type is present.\n * Uncomment this option to prevent the use of double-width division.\n *\n * Note that division for the native integer type is always required.\n * Furthermore, a 64-bit type is always required even on a 32-bit\n * platform, but it need not support multiplication or division. In some\n * cases it is also desirable to disable some double-width operations. For\n * example, if double-width division is implemented in software, disabling\n * it can reduce code size in some embedded targets.\n */\n//#define MBEDTLS_NO_UDBL_DIVISION\n\n/**\n * \\def MBEDTLS_NO_64BIT_MULTIPLICATION\n *\n * The platform lacks support for 32x32 -> 64-bit multiplication.\n *\n * Used in:\n *      library/poly1305.c\n *\n * Some parts of the library may use multiplication of two unsigned 32-bit\n * operands with a 64-bit result in order to speed up computations. On some\n * platforms, this is not available in hardware and has to be implemented in\n * software, usually in a library provided by the toolchain.\n *\n * Sometimes it is not desirable to have to link to that library. This option\n * removes the dependency of that library on platforms that lack a hardware\n * 64-bit multiplier by embedding a software implementation in Mbed TLS.\n *\n * Note that depending on the compiler, this may decrease performance compared\n * to using the library function provided by the toolchain.\n */\n//#define MBEDTLS_NO_64BIT_MULTIPLICATION\n\n/**\n * \\def MBEDTLS_HAVE_SSE2\n *\n * CPU supports SSE2 instruction set.\n *\n * Uncomment if the CPU supports SSE2 (IA-32 specific).\n */\n//#define MBEDTLS_HAVE_SSE2\n\n/**\n * \\def MBEDTLS_HAVE_TIME\n *\n * System has time.h and time().\n * The time does not need to be correct, only time differences are used,\n * by contrast with MBEDTLS_HAVE_TIME_DATE\n *\n * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT,\n * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and\n * MBEDTLS_PLATFORM_STD_TIME.\n *\n * Comment if your system does not support time functions.\n *\n * \\note If MBEDTLS_TIMING_C is set - to enable the semi-portable timing\n *       interface - timing.c will include time.h on suitable platforms\n *       regardless of the setting of MBEDTLS_HAVE_TIME, unless\n *       MBEDTLS_TIMING_ALT is used. See timing.c for more information.\n */\n#define MBEDTLS_HAVE_TIME\n\n/**\n * \\def MBEDTLS_HAVE_TIME_DATE\n *\n * System has time.h, time(), and an implementation for\n * mbedtls_platform_gmtime_r() (see below).\n * The time needs to be correct (not necessarily very accurate, but at least\n * the date should be correct). This is used to verify the validity period of\n * X.509 certificates.\n *\n * Comment if your system does not have a correct clock.\n *\n * \\note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that\n * behaves similarly to the gmtime_r() function from the C standard. Refer to\n * the documentation for mbedtls_platform_gmtime_r() for more information.\n *\n * \\note It is possible to configure an implementation for\n * mbedtls_platform_gmtime_r() at compile-time by using the macro\n * MBEDTLS_PLATFORM_GMTIME_R_ALT.\n */\n#define MBEDTLS_HAVE_TIME_DATE\n\n/**\n * \\def MBEDTLS_PLATFORM_MEMORY\n *\n * Enable the memory allocation layer.\n *\n * By default Mbed TLS uses the system-provided calloc() and free().\n * This allows different allocators (self-implemented or provided) to be\n * provided to the platform abstraction layer.\n *\n * Enabling #MBEDTLS_PLATFORM_MEMORY without the\n * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide\n * \"mbedtls_platform_set_calloc_free()\" allowing you to set an alternative calloc() and\n * free() function pointer at runtime.\n *\n * Enabling #MBEDTLS_PLATFORM_MEMORY and specifying\n * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the\n * alternate function at compile time.\n *\n * An overview of how the value of mbedtls_calloc is determined:\n *\n * - if !MBEDTLS_PLATFORM_MEMORY\n *     - mbedtls_calloc = calloc\n * - if MBEDTLS_PLATFORM_MEMORY\n *     - if (MBEDTLS_PLATFORM_CALLOC_MACRO && MBEDTLS_PLATFORM_FREE_MACRO):\n *         - mbedtls_calloc = MBEDTLS_PLATFORM_CALLOC_MACRO\n *     - if !(MBEDTLS_PLATFORM_CALLOC_MACRO && MBEDTLS_PLATFORM_FREE_MACRO):\n *         - Dynamic setup via mbedtls_platform_set_calloc_free is now possible with a default value MBEDTLS_PLATFORM_STD_CALLOC.\n *         - How is MBEDTLS_PLATFORM_STD_CALLOC handled?\n *         - if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS:\n *             - MBEDTLS_PLATFORM_STD_CALLOC is not set to anything;\n *             - MBEDTLS_PLATFORM_STD_MEM_HDR can be included if present;\n *         - if !MBEDTLS_PLATFORM_NO_STD_FUNCTIONS:\n *             - if MBEDTLS_PLATFORM_STD_CALLOC is present:\n *                 - User-defined MBEDTLS_PLATFORM_STD_CALLOC is respected;\n *             - if !MBEDTLS_PLATFORM_STD_CALLOC:\n *                 - MBEDTLS_PLATFORM_STD_CALLOC = calloc\n *\n *         - At this point the presence of MBEDTLS_PLATFORM_STD_CALLOC is checked.\n *         - if !MBEDTLS_PLATFORM_STD_CALLOC\n *             - MBEDTLS_PLATFORM_STD_CALLOC = uninitialized_calloc\n *\n *         - mbedtls_calloc = MBEDTLS_PLATFORM_STD_CALLOC.\n *\n * Defining MBEDTLS_PLATFORM_CALLOC_MACRO and #MBEDTLS_PLATFORM_STD_CALLOC at the same time is not possible.\n * MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_FREE_MACRO must both be defined or undefined at the same time.\n * #MBEDTLS_PLATFORM_STD_CALLOC and #MBEDTLS_PLATFORM_STD_FREE do not have to be defined at the same time, as, if they are used,\n * dynamic setup of these functions is possible. See the tree above to see how are they handled in all cases.\n * An uninitialized #MBEDTLS_PLATFORM_STD_CALLOC always fails, returning a null pointer.\n * An uninitialized #MBEDTLS_PLATFORM_STD_FREE does not do anything.\n *\n * Requires: MBEDTLS_PLATFORM_C\n *\n * Enable this layer to allow use of alternative memory allocators.\n */\n//#define MBEDTLS_PLATFORM_MEMORY\n\n/**\n * \\def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS\n *\n * Do not assign standard functions in the platform layer (e.g. calloc() to\n * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF)\n *\n * This makes sure there are no linking errors on platforms that do not support\n * these functions. You will HAVE to provide alternatives, either at runtime\n * via the platform_set_xxx() functions or at compile time by setting\n * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a\n * MBEDTLS_PLATFORM_XXX_MACRO.\n *\n * Requires: MBEDTLS_PLATFORM_C\n *\n * Uncomment to prevent default assignment of standard functions in the\n * platform layer.\n */\n//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS\n\n/**\n * \\def MBEDTLS_PLATFORM_EXIT_ALT\n *\n * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let Mbed TLS support the\n * function in the platform abstraction layer.\n *\n * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, Mbed TLS will\n * provide a function \"mbedtls_platform_set_printf()\" that allows you to set an\n * alternative printf function pointer.\n *\n * All these define require MBEDTLS_PLATFORM_C to be defined!\n *\n * \\note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows;\n * it will be enabled automatically by check_config.h\n *\n * \\warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as\n * MBEDTLS_PLATFORM_XXX_MACRO!\n *\n * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME\n *\n * Uncomment a macro to enable alternate implementation of specific base\n * platform function\n */\n//#define MBEDTLS_PLATFORM_SETBUF_ALT\n//#define MBEDTLS_PLATFORM_EXIT_ALT\n//#define MBEDTLS_PLATFORM_TIME_ALT\n//#define MBEDTLS_PLATFORM_FPRINTF_ALT\n//#define MBEDTLS_PLATFORM_PRINTF_ALT\n//#define MBEDTLS_PLATFORM_SNPRINTF_ALT\n//#define MBEDTLS_PLATFORM_VSNPRINTF_ALT\n//#define MBEDTLS_PLATFORM_NV_SEED_ALT\n//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT\n//#define MBEDTLS_PLATFORM_MS_TIME_ALT\n\n/**\n * Uncomment the macro to let Mbed TLS use your alternate implementation of\n * mbedtls_platform_gmtime_r(). This replaces the default implementation in\n * platform_util.c.\n *\n * gmtime() is not a thread-safe function as defined in the C standard. The\n * library will try to use safer implementations of this function, such as\n * gmtime_r() when available. However, if Mbed TLS cannot identify the target\n * system, the implementation of mbedtls_platform_gmtime_r() will default to\n * using the standard gmtime(). In this case, calls from the library to\n * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex\n * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the\n * library are also guarded with this mutex to avoid race conditions. However,\n * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will\n * unconditionally use the implementation for mbedtls_platform_gmtime_r()\n * supplied at compile time.\n */\n//#define MBEDTLS_PLATFORM_GMTIME_R_ALT\n\n/**\n * Uncomment the macro to let Mbed TLS use your alternate implementation of\n * mbedtls_platform_zeroize(), to wipe sensitive data in memory. This replaces\n * the default implementation in platform_util.c.\n *\n * By default, the library uses a system function such as memset_s()\n * (optional feature of C11), explicit_bzero() (BSD and compatible), or\n * SecureZeroMemory (Windows). If no such function is detected, the library\n * falls back to a plain C implementation. Compilers are technically\n * permitted to optimize this implementation out, meaning that the memory is\n * not actually wiped. The library tries to prevent that, but the C language\n * makes it impossible to guarantee that the memory will always be wiped.\n *\n * If your platform provides a guaranteed method to wipe memory which\n * `platform_util.c` does not detect, define this macro to the name of\n * a function that takes two arguments, a `void *` pointer and a length,\n * and wipes that many bytes starting at the specified address. For example,\n * if your platform has explicit_bzero() but `platform_util.c` does not\n * detect its presence, define `MBEDTLS_PLATFORM_ZEROIZE_ALT` to be\n * `explicit_bzero` to use that function as mbedtls_platform_zeroize().\n */\n//#define MBEDTLS_PLATFORM_ZEROIZE_ALT\n\n/**\n * \\def MBEDTLS_DEPRECATED_WARNING\n *\n * Mark deprecated functions and features so that they generate a warning if\n * used. Functionality deprecated in one version will usually be removed in the\n * next version. You can enable this to help you prepare the transition to a\n * new major version by making sure your code is not using this functionality.\n *\n * This only works with GCC and Clang. With other compilers, you may want to\n * use MBEDTLS_DEPRECATED_REMOVED\n *\n * Uncomment to get warnings on using deprecated functions and features.\n */\n//#define MBEDTLS_DEPRECATED_WARNING\n\n/**\n * \\def MBEDTLS_DEPRECATED_REMOVED\n *\n * Remove deprecated functions and features so that they generate an error if\n * used. Functionality deprecated in one version will usually be removed in the\n * next version. You can enable this to help you prepare the transition to a\n * new major version by making sure your code is not using this functionality.\n *\n * Uncomment to get errors on using deprecated functions and features.\n */\n//#define MBEDTLS_DEPRECATED_REMOVED\n\n/** \\} name SECTION: System support */\n\n/**\n * \\name SECTION: Mbed TLS feature support\n *\n * This section sets support for features that are or are not needed\n * within the modules that are enabled.\n * \\{\n */\n\n/**\n * \\def MBEDTLS_TIMING_ALT\n *\n * Uncomment to provide your own alternate implementation for\n * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay()\n *\n * Only works if you have MBEDTLS_TIMING_C enabled.\n *\n * You will need to provide a header \"timing_alt.h\" and an implementation at\n * compile time.\n */\n//#define MBEDTLS_TIMING_ALT\n\n/**\n * \\def MBEDTLS_AES_ALT\n *\n * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let Mbed TLS use your\n * alternate core implementation of a symmetric crypto, an arithmetic or hash\n * module (e.g. platform specific assembly optimized implementations). Keep\n * in mind that the function prototypes should remain the same.\n *\n * This replaces the whole module. If you only want to replace one of the\n * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags.\n *\n * Example: In case you uncomment MBEDTLS_AES_ALT, Mbed TLS will no longer\n * provide the \"struct mbedtls_aes_context\" definition and omit the base\n * function declarations and implementations. \"aes_alt.h\" will be included from\n * \"aes.h\" to include the new function definitions.\n *\n * Uncomment a macro to enable alternate implementation of the corresponding\n * module.\n *\n * \\warning   MD5, DES and SHA-1 are considered weak and their\n *            use constitutes a security risk. If possible, we recommend\n *            avoiding dependencies on them, and considering stronger message\n *            digests and ciphers instead.\n *\n */\n//#define MBEDTLS_AES_ALT\n//#define MBEDTLS_ARIA_ALT\n//#define MBEDTLS_CAMELLIA_ALT\n//#define MBEDTLS_CCM_ALT\n//#define MBEDTLS_CHACHA20_ALT\n//#define MBEDTLS_CHACHAPOLY_ALT\n//#define MBEDTLS_CMAC_ALT\n//#define MBEDTLS_DES_ALT\n//#define MBEDTLS_DHM_ALT\n//#define MBEDTLS_ECJPAKE_ALT\n//#define MBEDTLS_GCM_ALT\n//#define MBEDTLS_NIST_KW_ALT\n//#define MBEDTLS_MD5_ALT\n//#define MBEDTLS_POLY1305_ALT\n//#define MBEDTLS_RIPEMD160_ALT\n//#define MBEDTLS_RSA_ALT\n//#define MBEDTLS_SHA1_ALT\n//#define MBEDTLS_SHA256_ALT\n//#define MBEDTLS_SHA512_ALT\n\n/*\n * When replacing the elliptic curve module, please consider, that it is\n * implemented with two .c files:\n *      - ecp.c\n *      - ecp_curves.c\n * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT\n * macros as described above. The only difference is that you have to make sure\n * that you provide functionality for both .c files.\n */\n//#define MBEDTLS_ECP_ALT\n\n/**\n * \\def MBEDTLS_SHA256_PROCESS_ALT\n *\n * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let Mbed TLS use you\n * alternate core implementation of symmetric crypto or hash function. Keep in\n * mind that function prototypes should remain the same.\n *\n * This replaces only one function. The header file from Mbed TLS is still\n * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags.\n *\n * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, Mbed TLS will\n * no longer provide the mbedtls_sha1_process() function, but it will still provide\n * the other function (using your mbedtls_sha1_process() function) and the definition\n * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible\n * with this definition.\n *\n * \\note If you use the AES_xxx_ALT macros, then it is recommended to also set\n *       MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES\n *       tables.\n *\n * Uncomment a macro to enable alternate implementation of the corresponding\n * function.\n *\n * \\warning   MD5, DES and SHA-1 are considered weak and their use\n *            constitutes a security risk. If possible, we recommend avoiding\n *            dependencies on them, and considering stronger message digests\n *            and ciphers instead.\n *\n * \\warning   If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are\n *            enabled, then the deterministic ECDH signature functions pass the\n *            the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore\n *            alternative implementations should use the RNG only for generating\n *            the ephemeral key and nothing else. If this is not possible, then\n *            MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative\n *            implementation should be provided for mbedtls_ecdsa_sign_det_ext().\n *\n */\n//#define MBEDTLS_MD5_PROCESS_ALT\n//#define MBEDTLS_RIPEMD160_PROCESS_ALT\n//#define MBEDTLS_SHA1_PROCESS_ALT\n//#define MBEDTLS_SHA256_PROCESS_ALT\n//#define MBEDTLS_SHA512_PROCESS_ALT\n//#define MBEDTLS_DES_SETKEY_ALT\n//#define MBEDTLS_DES_CRYPT_ECB_ALT\n//#define MBEDTLS_DES3_CRYPT_ECB_ALT\n//#define MBEDTLS_AES_SETKEY_ENC_ALT\n//#define MBEDTLS_AES_SETKEY_DEC_ALT\n//#define MBEDTLS_AES_ENCRYPT_ALT\n//#define MBEDTLS_AES_DECRYPT_ALT\n//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT\n//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT\n//#define MBEDTLS_ECDSA_VERIFY_ALT\n//#define MBEDTLS_ECDSA_SIGN_ALT\n//#define MBEDTLS_ECDSA_GENKEY_ALT\n\n/**\n * \\def MBEDTLS_ECP_INTERNAL_ALT\n *\n * Expose a part of the internal interface of the Elliptic Curve Point module.\n *\n * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let Mbed TLS use your\n * alternative core implementation of elliptic curve arithmetic. Keep in mind\n * that function prototypes should remain the same.\n *\n * This partially replaces one function. The header file from Mbed TLS is still\n * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation\n * is still present and it is used for group structures not supported by the\n * alternative.\n *\n * The original implementation can in addition be removed by setting the\n * MBEDTLS_ECP_NO_FALLBACK option, in which case any function for which the\n * corresponding MBEDTLS_ECP__FUNCTION_NAME__ALT macro is defined will not be\n * able to fallback to curves not supported by the alternative implementation.\n *\n * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT\n * and implementing the following functions:\n *      unsigned char mbedtls_internal_ecp_grp_capable(\n *          const mbedtls_ecp_group *grp )\n *      int  mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp )\n *      void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp )\n * The mbedtls_internal_ecp_grp_capable function should return 1 if the\n * replacement functions implement arithmetic for the given group and 0\n * otherwise.\n * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are\n * called before and after each point operation and provide an opportunity to\n * implement optimized set up and tear down instructions.\n *\n * Example: In case you set MBEDTLS_ECP_INTERNAL_ALT and\n * MBEDTLS_ECP_DOUBLE_JAC_ALT, Mbed TLS will still provide the ecp_double_jac()\n * function, but will use your mbedtls_internal_ecp_double_jac() if the group\n * for the operation is supported by your implementation (i.e. your\n * mbedtls_internal_ecp_grp_capable() function returns 1 for this group). If the\n * group is not supported by your implementation, then the original Mbed TLS\n * implementation of ecp_double_jac() is used instead, unless this fallback\n * behaviour is disabled by setting MBEDTLS_ECP_NO_FALLBACK (in which case\n * ecp_double_jac() will return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE).\n *\n * The function prototypes and the definition of mbedtls_ecp_group and\n * mbedtls_ecp_point will not change based on MBEDTLS_ECP_INTERNAL_ALT, so your\n * implementation of mbedtls_internal_ecp__function_name__ must be compatible\n * with their definitions.\n *\n * Uncomment a macro to enable alternate implementation of the corresponding\n * function.\n */\n/* Required for all the functions in this section */\n//#define MBEDTLS_ECP_INTERNAL_ALT\n/* Turn off software fallback for curves not supported in hardware */\n//#define MBEDTLS_ECP_NO_FALLBACK\n/* Support for Weierstrass curves with Jacobi representation */\n//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT\n//#define MBEDTLS_ECP_ADD_MIXED_ALT\n//#define MBEDTLS_ECP_DOUBLE_JAC_ALT\n//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT\n//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT\n/* Support for curves with Montgomery arithmetic */\n//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT\n//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT\n//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT\n\n/**\n * \\def MBEDTLS_ENTROPY_HARDWARE_ALT\n *\n * Uncomment this macro to let Mbed TLS use your own implementation of a\n * hardware entropy collector.\n *\n * Your function must be called \\c mbedtls_hardware_poll(), have the same\n * prototype as declared in library/entropy_poll.h, and accept NULL as first\n * argument.\n *\n * Uncomment to use your own hardware entropy collector.\n */\n//#define MBEDTLS_ENTROPY_HARDWARE_ALT\n\n/**\n * \\def MBEDTLS_AES_ROM_TABLES\n *\n * Use precomputed AES tables stored in ROM.\n *\n * Uncomment this macro to use precomputed AES tables stored in ROM.\n * Comment this macro to generate AES tables in RAM at runtime.\n *\n * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb\n * (or ~2kb if \\c MBEDTLS_AES_FEWER_TABLES is used) and reduces the\n * initialization time before the first AES operation can be performed.\n * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \\c\n * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded\n * performance if ROM access is slower than RAM access.\n *\n * This option is independent of \\c MBEDTLS_AES_FEWER_TABLES.\n */\n//#define MBEDTLS_AES_ROM_TABLES\n\n/**\n * \\def MBEDTLS_AES_FEWER_TABLES\n *\n * Use less ROM/RAM for AES tables.\n *\n * Uncommenting this macro omits 75% of the AES tables from\n * ROM / RAM (depending on the value of \\c MBEDTLS_AES_ROM_TABLES)\n * by computing their values on the fly during operations\n * (the tables are entry-wise rotations of one another).\n *\n * Tradeoff: Uncommenting this reduces the RAM / ROM footprint\n * by ~6kb but at the cost of more arithmetic operations during\n * runtime. Specifically, one has to compare 4 accesses within\n * different tables to 4 accesses with additional arithmetic\n * operations within the same table. The performance gain/loss\n * depends on the system and memory details.\n *\n * This option is independent of \\c MBEDTLS_AES_ROM_TABLES.\n */\n//#define MBEDTLS_AES_FEWER_TABLES\n\n/**\n * \\def MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH\n *\n * Use only 128-bit keys in AES operations to save ROM.\n *\n * Uncomment this macro to remove support for AES operations that use 192-\n * or 256-bit keys.\n *\n * Uncommenting this macro reduces the size of AES code by ~300 bytes\n * on v8-M/Thumb2.\n *\n * Module:  library/aes.c\n *\n * Requires: MBEDTLS_AES_C\n */\n//#define MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH\n\n/*\n * Disable plain C implementation for AES.\n *\n * When the plain C implementation is enabled, and an implementation using a\n * special CPU feature (such as MBEDTLS_AESCE_C) is also enabled, runtime\n * detection will be used to select between them.\n *\n * If only one implementation is present, runtime detection will not be used.\n * This configuration will crash at runtime if running on a CPU without the\n * necessary features. It will not build unless at least one of MBEDTLS_AESCE_C\n * and/or MBEDTLS_AESNI_C is enabled & present in the build.\n */\n//#define MBEDTLS_AES_USE_HARDWARE_ONLY\n\n/**\n * \\def MBEDTLS_CAMELLIA_SMALL_MEMORY\n *\n * Use less ROM for the Camellia implementation (saves about 768 bytes).\n *\n * Uncomment this macro to use less memory for Camellia.\n */\n//#define MBEDTLS_CAMELLIA_SMALL_MEMORY\n\n/**\n * \\def MBEDTLS_CHECK_RETURN_WARNING\n *\n * If this macro is defined, emit a compile-time warning if application code\n * calls a function without checking its return value, but the return value\n * should generally be checked in portable applications.\n *\n * This is only supported on platforms where #MBEDTLS_CHECK_RETURN is\n * implemented. Otherwise this option has no effect.\n *\n * Uncomment to get warnings on using fallible functions without checking\n * their return value.\n *\n * \\note  This feature is a work in progress.\n *        Warnings will be added to more functions in the future.\n *\n * \\note  A few functions are considered critical, and ignoring the return\n *        value of these functions will trigger a warning even if this\n *        macro is not defined. To completely disable return value check\n *        warnings, define #MBEDTLS_CHECK_RETURN with an empty expansion.\n */\n//#define MBEDTLS_CHECK_RETURN_WARNING\n\n/**\n * \\def MBEDTLS_CIPHER_MODE_CBC\n *\n * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.\n */\n#define MBEDTLS_CIPHER_MODE_CBC\n\n/**\n * \\def MBEDTLS_CIPHER_MODE_CFB\n *\n * Enable Cipher Feedback mode (CFB) for symmetric ciphers.\n */\n#define MBEDTLS_CIPHER_MODE_CFB\n\n/**\n * \\def MBEDTLS_CIPHER_MODE_CTR\n *\n * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.\n */\n#define MBEDTLS_CIPHER_MODE_CTR\n\n/**\n * \\def MBEDTLS_CIPHER_MODE_OFB\n *\n * Enable Output Feedback mode (OFB) for symmetric ciphers.\n */\n#define MBEDTLS_CIPHER_MODE_OFB\n\n/**\n * \\def MBEDTLS_CIPHER_MODE_XTS\n *\n * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES.\n */\n#define MBEDTLS_CIPHER_MODE_XTS\n\n/**\n * \\def MBEDTLS_CIPHER_NULL_CIPHER\n *\n * Enable NULL cipher.\n * Warning: Only do so when you know what you are doing. This allows for\n * encryption or channels without any security!\n *\n * To enable the following ciphersuites:\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA\n *      MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA\n *      MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384\n *      MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256\n *      MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA\n *      MBEDTLS_TLS_RSA_WITH_NULL_SHA256\n *      MBEDTLS_TLS_RSA_WITH_NULL_SHA\n *      MBEDTLS_TLS_RSA_WITH_NULL_MD5\n *      MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384\n *      MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256\n *      MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA\n *      MBEDTLS_TLS_PSK_WITH_NULL_SHA384\n *      MBEDTLS_TLS_PSK_WITH_NULL_SHA256\n *      MBEDTLS_TLS_PSK_WITH_NULL_SHA\n *\n * Uncomment this macro to enable the NULL cipher and ciphersuites\n */\n//#define MBEDTLS_CIPHER_NULL_CIPHER\n\n/**\n * \\def MBEDTLS_CIPHER_PADDING_PKCS7\n *\n * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for\n * specific padding modes in the cipher layer with cipher modes that support\n * padding (e.g. CBC)\n *\n * If you disable all padding modes, only full blocks can be used with CBC.\n *\n * Enable padding modes in the cipher layer.\n */\n#define MBEDTLS_CIPHER_PADDING_PKCS7\n#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS\n#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN\n#define MBEDTLS_CIPHER_PADDING_ZEROS\n\n/** \\def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY\n *\n * Uncomment this macro to use a 128-bit key in the CTR_DRBG module.\n * Without this, CTR_DRBG uses a 256-bit key\n * unless \\c MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH is set.\n */\n//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY\n\n/**\n * Enable the verified implementations of ECDH primitives from Project Everest\n * (currently only Curve25519). This feature changes the layout of ECDH\n * contexts and therefore is a compatibility break for applications that access\n * fields of a mbedtls_ecdh_context structure directly. See also\n * MBEDTLS_ECDH_LEGACY_CONTEXT in include/mbedtls/ecdh.h.\n *\n * The Everest code is provided under the Apache 2.0 license only; therefore enabling this\n * option is not compatible with taking the library under the GPL v2.0-or-later license.\n */\n//#define MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED\n\n/**\n * \\def MBEDTLS_ECP_DP_SECP192R1_ENABLED\n *\n * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve\n * module.  By default all supported curves are enabled.\n *\n * Comment macros to disable the curve and functions for it\n */\n/* Short Weierstrass curves (supporting ECP, ECDH, ECDSA) */\n#define MBEDTLS_ECP_DP_SECP192R1_ENABLED\n#define MBEDTLS_ECP_DP_SECP224R1_ENABLED\n#define MBEDTLS_ECP_DP_SECP256R1_ENABLED\n#define MBEDTLS_ECP_DP_SECP384R1_ENABLED\n#define MBEDTLS_ECP_DP_SECP521R1_ENABLED\n#define MBEDTLS_ECP_DP_SECP192K1_ENABLED\n#define MBEDTLS_ECP_DP_SECP224K1_ENABLED\n#define MBEDTLS_ECP_DP_SECP256K1_ENABLED\n#define MBEDTLS_ECP_DP_BP256R1_ENABLED\n#define MBEDTLS_ECP_DP_BP384R1_ENABLED\n#define MBEDTLS_ECP_DP_BP512R1_ENABLED\n/* Montgomery curves (supporting ECP) */\n#define MBEDTLS_ECP_DP_CURVE25519_ENABLED\n#define MBEDTLS_ECP_DP_CURVE448_ENABLED\n\n/**\n * \\def MBEDTLS_ECP_NIST_OPTIM\n *\n * Enable specific 'modulo p' routines for each NIST prime.\n * Depending on the prime and architecture, makes operations 4 to 8 times\n * faster on the corresponding curve.\n *\n * Comment this macro to disable NIST curves optimisation.\n */\n#define MBEDTLS_ECP_NIST_OPTIM\n\n/**\n * \\def MBEDTLS_ECP_RESTARTABLE\n *\n * Enable \"non-blocking\" ECC operations that can return early and be resumed.\n *\n * This allows various functions to pause by returning\n * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module,\n * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in\n * order to further progress and eventually complete their operation. This is\n * controlled through mbedtls_ecp_set_max_ops() which limits the maximum\n * number of ECC operations a function may perform before pausing; see\n * mbedtls_ecp_set_max_ops() for more information.\n *\n * This is useful in non-threaded environments if you want to avoid blocking\n * for too long on ECC (and, hence, X.509 or SSL/TLS) operations.\n *\n * This option:\n * - Adds xxx_restartable() variants of existing operations in the\n *   following modules, with corresponding restart context types:\n *   - ECP (for Short Weierstrass curves only): scalar multiplication (mul),\n *     linear combination (muladd);\n *   - ECDSA: signature generation & verification;\n *   - PK: signature generation & verification;\n *   - X509: certificate chain verification.\n * - Adds mbedtls_ecdh_enable_restart() in the ECDH module.\n * - Changes the behaviour of TLS 1.2 clients (not servers) when using the\n *   ECDHE-ECDSA key exchange (not other key exchanges) to make all ECC\n *   computations restartable:\n *   - ECDH operations from the key exchange, only for Short Weierstrass\n *     curves, only when MBEDTLS_USE_PSA_CRYPTO is not enabled.\n *   - verification of the server's key exchange signature;\n *   - verification of the server's certificate chain;\n *   - generation of the client's signature if client authentication is used,\n *     with an ECC key/certificate.\n *\n * \\note  In the cases above, the usual SSL/TLS functions, such as\n *        mbedtls_ssl_handshake(), can now return\n *        MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS.\n *\n * \\note  When this option and MBEDTLS_USE_PSA_CRYPTO are both enabled,\n *        restartable operations in PK, X.509 and TLS (see above) are not\n *        using PSA. On the other hand, ECDH computations in TLS are using\n *        PSA, and are not restartable. These are temporary limitations that\n *        should be lifted in the future.\n *\n * \\note  This option only works with the default software implementation of\n *        elliptic curve functionality. It is incompatible with\n *        MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT, MBEDTLS_ECDSA_XXX_ALT.\n *\n * Requires: MBEDTLS_ECP_C\n *\n * Uncomment this macro to enable restartable ECC computations.\n */\n//#define MBEDTLS_ECP_RESTARTABLE\n\n/**\n * Uncomment to enable using new bignum code in the ECC modules.\n *\n * \\warning This is currently experimental, incomplete and therefore should not\n * be used in production.\n */\n//#define MBEDTLS_ECP_WITH_MPI_UINT\n\n/**\n * \\def MBEDTLS_ECDSA_DETERMINISTIC\n *\n * Enable deterministic ECDSA (RFC 6979).\n * Standard ECDSA is \"fragile\" in the sense that lack of entropy when signing\n * may result in a compromise of the long-term signing key. This is avoided by\n * the deterministic variant.\n *\n * Requires: MBEDTLS_HMAC_DRBG_C, MBEDTLS_ECDSA_C\n *\n * Comment this macro to disable deterministic ECDSA.\n */\n#define MBEDTLS_ECDSA_DETERMINISTIC\n\n/**\n * \\def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED\n *\n * Enable the PSK based ciphersuite modes in SSL / TLS.\n *\n * This enables the following ciphersuites (if other requisites are\n * enabled as well):\n *      MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256\n */\n#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED\n\n/**\n * \\def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED\n *\n * Enable the DHE-PSK based ciphersuite modes in SSL / TLS.\n *\n * Requires: MBEDTLS_DHM_C\n *\n * This enables the following ciphersuites (if other requisites are\n * enabled as well):\n *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256\n *\n * \\warning    Using DHE constitutes a security risk as it\n *             is not possible to validate custom DH parameters.\n *             If possible, it is recommended users should consider\n *             preferring other methods of key exchange.\n *             See dhm.h for more details.\n *\n */\n#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED\n\n/**\n * \\def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED\n *\n * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS.\n *\n * Requires: MBEDTLS_ECDH_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDH)\n *\n * This enables the following ciphersuites (if other requisites are\n * enabled as well):\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256\n */\n#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED\n\n/**\n * \\def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED\n *\n * Enable the RSA-PSK based ciphersuite modes in SSL / TLS.\n *\n * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,\n *           MBEDTLS_X509_CRT_PARSE_C\n *\n * This enables the following ciphersuites (if other requisites are\n * enabled as well):\n *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256\n */\n#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED\n\n/**\n * \\def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED\n *\n * Enable the RSA-only based ciphersuite modes in SSL / TLS.\n *\n * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,\n *           MBEDTLS_X509_CRT_PARSE_C\n *\n * This enables the following ciphersuites (if other requisites are\n * enabled as well):\n *      MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256\n *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256\n *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA\n *      MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256\n *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA\n */\n#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED\n\n/**\n * \\def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED\n *\n * Enable the DHE-RSA based ciphersuite modes in SSL / TLS.\n *\n * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,\n *           MBEDTLS_X509_CRT_PARSE_C\n *\n * This enables the following ciphersuites (if other requisites are\n * enabled as well):\n *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256\n *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256\n *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA\n *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256\n *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA\n *\n * \\warning    Using DHE constitutes a security risk as it\n *             is not possible to validate custom DH parameters.\n *             If possible, it is recommended users should consider\n *             preferring other methods of key exchange.\n *             See dhm.h for more details.\n *\n */\n#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED\n\n/**\n * \\def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED\n *\n * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS.\n *\n * Requires: MBEDTLS_ECDH_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDH)\n *           MBEDTLS_RSA_C\n *           MBEDTLS_PKCS1_V15\n *           MBEDTLS_X509_CRT_PARSE_C\n *\n * This enables the following ciphersuites (if other requisites are\n * enabled as well):\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256\n */\n#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED\n\n/**\n * \\def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED\n *\n * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS.\n *\n * Requires: MBEDTLS_ECDH_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDH)\n *           MBEDTLS_ECDSA_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDSA)\n *           MBEDTLS_X509_CRT_PARSE_C\n *\n * This enables the following ciphersuites (if other requisites are\n * enabled as well):\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256\n */\n#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED\n\n/**\n * \\def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED\n *\n * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS.\n *\n * Requires: MBEDTLS_ECDH_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDH)\n *           MBEDTLS_ECDSA_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDSA)\n *           MBEDTLS_X509_CRT_PARSE_C\n *\n * This enables the following ciphersuites (if other requisites are\n * enabled as well):\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384\n */\n#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED\n\n/**\n * \\def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED\n *\n * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS.\n *\n * Requires: MBEDTLS_ECDH_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDH)\n *           MBEDTLS_RSA_C\n *           MBEDTLS_X509_CRT_PARSE_C\n *\n * This enables the following ciphersuites (if other requisites are\n * enabled as well):\n *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384\n */\n#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED\n\n/**\n * \\def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED\n *\n * Enable the ECJPAKE based ciphersuite modes in SSL / TLS.\n *\n * \\warning This is currently experimental. EC J-PAKE support is based on the\n * Thread v1.0.0 specification; incompatible changes to the specification\n * might still happen. For this reason, this is disabled by default.\n *\n * Requires: MBEDTLS_ECJPAKE_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_JPAKE)\n *           SHA-256 (via MBEDTLS_SHA256_C or a PSA driver)\n *           MBEDTLS_ECP_DP_SECP256R1_ENABLED\n *\n * \\warning If SHA-256 is provided only by a PSA driver, you must call\n * psa_crypto_init() before the first handshake (even if\n * MBEDTLS_USE_PSA_CRYPTO is disabled).\n *\n * This enables the following ciphersuites (if other requisites are\n * enabled as well):\n *      MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8\n */\n//#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED\n\n/**\n * \\def MBEDTLS_PK_PARSE_EC_EXTENDED\n *\n * Enhance support for reading EC keys using variants of SEC1 not allowed by\n * RFC 5915 and RFC 5480.\n *\n * Currently this means parsing the SpecifiedECDomain choice of EC\n * parameters (only known groups are supported, not arbitrary domains, to\n * avoid validation issues).\n *\n * Disable if you only need to support RFC 5915 + 5480 key formats.\n */\n#define MBEDTLS_PK_PARSE_EC_EXTENDED\n\n/**\n * \\def MBEDTLS_PK_PARSE_EC_COMPRESSED\n *\n * Enable the support for parsing public keys of type Short Weierstrass\n * (MBEDTLS_ECP_DP_SECP_XXX and MBEDTLS_ECP_DP_BP_XXX) which are using the\n * compressed point format. This parsing is done through ECP module's functions.\n *\n * \\note As explained in the description of MBEDTLS_ECP_PF_COMPRESSED (in ecp.h)\n *       the only unsupported curves are MBEDTLS_ECP_DP_SECP224R1 and\n *       MBEDTLS_ECP_DP_SECP224K1.\n */\n#define MBEDTLS_PK_PARSE_EC_COMPRESSED\n\n/**\n * \\def MBEDTLS_ERROR_STRERROR_DUMMY\n *\n * Enable a dummy error function to make use of mbedtls_strerror() in\n * third party libraries easier when MBEDTLS_ERROR_C is disabled\n * (no effect when MBEDTLS_ERROR_C is enabled).\n *\n * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're\n * not using mbedtls_strerror() or error_strerror() in your application.\n *\n * Disable if you run into name conflicts and want to really remove the\n * mbedtls_strerror()\n */\n#define MBEDTLS_ERROR_STRERROR_DUMMY\n\n/**\n * \\def MBEDTLS_GENPRIME\n *\n * Enable the prime-number generation code.\n *\n * Requires: MBEDTLS_BIGNUM_C\n */\n#define MBEDTLS_GENPRIME\n\n/**\n * \\def MBEDTLS_FS_IO\n *\n * Enable functions that use the filesystem.\n */\n#define MBEDTLS_FS_IO\n\n/**\n * \\def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES\n *\n * Do not add default entropy sources in mbedtls_entropy_init().\n *\n * This is useful to have more control over the added entropy sources in an\n * application.\n *\n * Uncomment this macro to prevent loading of default entropy functions.\n */\n//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES\n\n/**\n * \\def MBEDTLS_NO_PLATFORM_ENTROPY\n *\n * Do not use built-in platform entropy functions.\n * This is useful if your platform does not support\n * standards like the /dev/urandom or Windows CryptoAPI.\n *\n * Uncomment this macro to disable the built-in platform entropy functions.\n */\n//#define MBEDTLS_NO_PLATFORM_ENTROPY\n\n/**\n * \\def MBEDTLS_ENTROPY_FORCE_SHA256\n *\n * Force the entropy accumulator to use a SHA-256 accumulator instead of the\n * default SHA-512 based one (if both are available).\n *\n * Requires: MBEDTLS_SHA256_C\n *\n * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option\n * if you have performance concerns.\n *\n * This option is only useful if both MBEDTLS_SHA256_C and\n * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used.\n */\n//#define MBEDTLS_ENTROPY_FORCE_SHA256\n\n/**\n * \\def MBEDTLS_ENTROPY_NV_SEED\n *\n * Enable the non-volatile (NV) seed file-based entropy source.\n * (Also enables the NV seed read/write functions in the platform layer)\n *\n * This is crucial (if not required) on systems that do not have a\n * cryptographic entropy source (in hardware or kernel) available.\n *\n * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C\n *\n * \\note The read/write functions that are used by the entropy source are\n *       determined in the platform layer, and can be modified at runtime and/or\n *       compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used.\n *\n * \\note If you use the default implementation functions that read a seedfile\n *       with regular fopen(), please make sure you make a seedfile with the\n *       proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at\n *       least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from\n *       and written to or you will get an entropy source error! The default\n *       implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE\n *       bytes from the file.\n *\n * \\note The entropy collector will write to the seed file before entropy is\n *       given to an external source, to update it.\n */\n//#define MBEDTLS_ENTROPY_NV_SEED\n\n/* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER\n *\n * Enable key identifiers that encode a key owner identifier.\n *\n * The owner of a key is identified by a value of type ::mbedtls_key_owner_id_t\n * which is currently hard-coded to be int32_t.\n *\n * Note that this option is meant for internal use only and may be removed\n * without notice.\n */\n//#define MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER\n\n/**\n * \\def MBEDTLS_MEMORY_DEBUG\n *\n * Enable debugging of buffer allocator memory issues. Automatically prints\n * (to stderr) all (fatal) messages on memory allocation issues. Enables\n * function for 'debug output' of allocated memory.\n *\n * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C\n *\n * Uncomment this macro to let the buffer allocator print out error messages.\n */\n//#define MBEDTLS_MEMORY_DEBUG\n\n/**\n * \\def MBEDTLS_MEMORY_BACKTRACE\n *\n * Include backtrace information with each allocated block.\n *\n * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C\n *           GLIBC-compatible backtrace() and backtrace_symbols() support\n *\n * Uncomment this macro to include backtrace information\n */\n//#define MBEDTLS_MEMORY_BACKTRACE\n\n/**\n * \\def MBEDTLS_PK_RSA_ALT_SUPPORT\n *\n * Support external private RSA keys (eg from a HSM) in the PK layer.\n *\n * Comment this macro to disable support for external private RSA keys.\n */\n#define MBEDTLS_PK_RSA_ALT_SUPPORT\n\n/**\n * \\def MBEDTLS_PKCS1_V15\n *\n * Enable support for PKCS#1 v1.5 encoding.\n *\n * Requires: MBEDTLS_RSA_C\n *\n * This enables support for PKCS#1 v1.5 operations.\n */\n#define MBEDTLS_PKCS1_V15\n\n/**\n * \\def MBEDTLS_PKCS1_V21\n *\n * Enable support for PKCS#1 v2.1 encoding.\n *\n * Requires: MBEDTLS_RSA_C\n *\n * \\warning If using a hash that is only provided by PSA drivers, you must\n * call psa_crypto_init() before doing any PKCS#1 v2.1 operation.\n *\n * This enables support for RSAES-OAEP and RSASSA-PSS operations.\n */\n#define MBEDTLS_PKCS1_V21\n\n/** \\def MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS\n *\n * Enable support for platform built-in keys. If you enable this feature,\n * you must implement the function mbedtls_psa_platform_get_builtin_key().\n * See the documentation of that function for more information.\n *\n * Built-in keys are typically derived from a hardware unique key or\n * stored in a secure element.\n *\n * Requires: MBEDTLS_PSA_CRYPTO_C.\n *\n * \\warning This interface is experimental and may change or be removed\n * without notice.\n */\n//#define MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS\n\n/** \\def MBEDTLS_PSA_CRYPTO_CLIENT\n *\n * Enable support for PSA crypto client.\n *\n * \\note This option allows to include the code necessary for a PSA\n *       crypto client when the PSA crypto implementation is not included in\n *       the library (MBEDTLS_PSA_CRYPTO_C disabled). The code included is the\n *       code to set and get PSA key attributes.\n *       The development of PSA drivers partially relying on the library to\n *       fulfill the hardware gaps is another possible usage of this option.\n *\n * \\warning This interface is experimental and may change or be removed\n * without notice.\n */\n//#define MBEDTLS_PSA_CRYPTO_CLIENT\n\n/** \\def MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG\n *\n * Make the PSA Crypto module use an external random generator provided\n * by a driver, instead of Mbed TLS's entropy and DRBG modules.\n *\n * \\note This random generator must deliver random numbers with cryptographic\n *       quality and high performance. It must supply unpredictable numbers\n *       with a uniform distribution. The implementation of this function\n *       is responsible for ensuring that the random generator is seeded\n *       with sufficient entropy. If you have a hardware TRNG which is slow\n *       or delivers non-uniform output, declare it as an entropy source\n *       with mbedtls_entropy_add_source() instead of enabling this option.\n *\n * If you enable this option, you must configure the type\n * ::mbedtls_psa_external_random_context_t in psa/crypto_platform.h\n * and define a function called mbedtls_psa_external_get_random()\n * with the following prototype:\n * ```\n * psa_status_t mbedtls_psa_external_get_random(\n *     mbedtls_psa_external_random_context_t *context,\n *     uint8_t *output, size_t output_size, size_t *output_length);\n * );\n * ```\n * The \\c context value is initialized to 0 before the first call.\n * The function must fill the \\c output buffer with \\c output_size bytes\n * of random data and set \\c *output_length to \\c output_size.\n *\n * Requires: MBEDTLS_PSA_CRYPTO_C\n *\n * \\warning If you enable this option, code that uses the PSA cryptography\n *          interface will not use any of the entropy sources set up for\n *          the entropy module, nor the NV seed that MBEDTLS_ENTROPY_NV_SEED\n *          enables.\n *\n * \\note This option is experimental and may be removed without notice.\n */\n//#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG\n\n/**\n * \\def MBEDTLS_PSA_CRYPTO_SPM\n *\n * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is built for SPM (Secure\n * Partition Manager) integration which separates the code into two parts: a\n * NSPE (Non-Secure Process Environment) and an SPE (Secure Process\n * Environment).\n *\n * If you enable this option, your build environment must include a header\n * file `\"crypto_spe.h\"` (either in the `psa` subdirectory of the Mbed TLS\n * header files, or in another directory on the compiler's include search\n * path). Alternatively, your platform may customize the header\n * `psa/crypto_platform.h`, in which case it can skip or replace the\n * inclusion of `\"crypto_spe.h\"`.\n *\n * Module:  library/psa_crypto.c\n * Requires: MBEDTLS_PSA_CRYPTO_C\n *\n */\n//#define MBEDTLS_PSA_CRYPTO_SPM\n\n/**\n * \\def MBEDTLS_PSA_KEY_STORE_DYNAMIC\n *\n * Dynamically resize the PSA key store to accommodate any number of\n * volatile keys (until the heap memory is exhausted).\n *\n * If this option is disabled, the key store has a fixed size\n * #MBEDTLS_PSA_KEY_SLOT_COUNT for volatile keys and loaded persistent keys\n * together.\n *\n * This option has no effect when #MBEDTLS_PSA_CRYPTO_C is disabled.\n *\n * Module:  library/psa_crypto.c\n * Requires: MBEDTLS_PSA_CRYPTO_C\n */\n#define MBEDTLS_PSA_KEY_STORE_DYNAMIC\n\n/**\n * Uncomment to enable p256-m. This is an alternative implementation of\n * key generation, ECDH and (randomized) ECDSA on the curve SECP256R1.\n * Compared to the default implementation:\n *\n * - p256-m has a much smaller code size and RAM footprint.\n * - p256-m is only available via the PSA API. This includes the pk module\n *   when #MBEDTLS_USE_PSA_CRYPTO is enabled.\n * - p256-m does not support deterministic ECDSA, EC-JPAKE, custom protocols\n *   over the core arithmetic, or deterministic derivation of keys.\n *\n * We recommend enabling this option if your application uses the PSA API\n * and the only elliptic curve support it needs is ECDH and ECDSA over\n * SECP256R1.\n *\n * If you enable this option, you do not need to enable any ECC-related\n * MBEDTLS_xxx option. You do need to separately request support for the\n * cryptographic mechanisms through the PSA API:\n * - #MBEDTLS_PSA_CRYPTO_C and #MBEDTLS_PSA_CRYPTO_CONFIG for PSA-based\n *   configuration;\n * - #MBEDTLS_USE_PSA_CRYPTO if you want to use p256-m from PK, X.509 or TLS;\n * - #PSA_WANT_ECC_SECP_R1_256;\n * - #PSA_WANT_ALG_ECDH and/or #PSA_WANT_ALG_ECDSA as needed;\n * - #PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY, #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC,\n *   #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT,\n *   #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT and/or\n *   #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE as needed.\n *\n * \\note To benefit from the smaller code size of p256-m, make sure that you\n *       do not enable any ECC-related option not supported by p256-m: this\n *       would cause the built-in ECC implementation to be built as well, in\n *       order to provide the required option.\n *       Make sure #PSA_WANT_ALG_DETERMINISTIC_ECDSA, #PSA_WANT_ALG_JPAKE and\n *       #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE, and curves other than\n *       SECP256R1 are disabled as they are not supported by this driver.\n *       Also, avoid defining #MBEDTLS_PK_PARSE_EC_COMPRESSED or\n *       #MBEDTLS_PK_PARSE_EC_EXTENDED as those currently require a subset of\n *       the built-in ECC implementation, see docs/driver-only-builds.md.\n */\n//#define MBEDTLS_PSA_P256M_DRIVER_ENABLED\n\n/**\n * \\def MBEDTLS_PSA_INJECT_ENTROPY\n *\n * Enable support for entropy injection at first boot. This feature is\n * required on systems that do not have a built-in entropy source (TRNG).\n * This feature is currently not supported on systems that have a built-in\n * entropy source.\n *\n * Requires: MBEDTLS_PSA_CRYPTO_STORAGE_C, MBEDTLS_ENTROPY_NV_SEED\n *\n */\n//#define MBEDTLS_PSA_INJECT_ENTROPY\n\n/**\n * \\def MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS\n *\n * Assume all buffers passed to PSA functions are owned exclusively by the\n * PSA function and are not stored in shared memory.\n *\n * This option may be enabled if all buffers passed to any PSA function reside\n * in memory that is accessible only to the PSA function during its execution.\n *\n * This option MUST be disabled whenever buffer arguments are in memory shared\n * with an untrusted party, for example where arguments to PSA calls are passed\n * across a trust boundary.\n *\n * \\note Enabling this option reduces memory usage and code size.\n *\n * \\note Enabling this option causes overlap of input and output buffers\n *       not to be supported by PSA functions.\n */\n//#define MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS\n\n/**\n * \\def MBEDTLS_RSA_NO_CRT\n *\n * Do not use the Chinese Remainder Theorem\n * for the RSA private operation.\n *\n * Uncomment this macro to disable the use of CRT in RSA.\n *\n */\n//#define MBEDTLS_RSA_NO_CRT\n\n/**\n * \\def MBEDTLS_SELF_TEST\n *\n * Enable the checkup functions (*_self_test).\n */\n#define MBEDTLS_SELF_TEST\n\n/**\n * \\def MBEDTLS_SHA256_SMALLER\n *\n * Enable an implementation of SHA-256 that has lower ROM footprint but also\n * lower performance.\n *\n * The default implementation is meant to be a reasonable compromise between\n * performance and size. This version optimizes more aggressively for size at\n * the expense of performance. Eg on Cortex-M4 it reduces the size of\n * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about\n * 30%.\n *\n * Uncomment to enable the smaller implementation of SHA256.\n */\n//#define MBEDTLS_SHA256_SMALLER\n\n/**\n * \\def MBEDTLS_SHA512_SMALLER\n *\n * Enable an implementation of SHA-512 that has lower ROM footprint but also\n * lower performance.\n *\n * Uncomment to enable the smaller implementation of SHA512.\n */\n//#define MBEDTLS_SHA512_SMALLER\n\n/**\n * \\def MBEDTLS_SSL_ALL_ALERT_MESSAGES\n *\n * Enable sending of alert messages in case of encountered errors as per RFC.\n * If you choose not to send the alert messages, Mbed TLS can still communicate\n * with other servers, only debugging of failures is harder.\n *\n * The advantage of not sending alert messages, is that no information is given\n * about reasons for failures thus preventing adversaries of gaining intel.\n *\n * Enable sending of all alert messages\n */\n#define MBEDTLS_SSL_ALL_ALERT_MESSAGES\n\n/**\n * \\def MBEDTLS_SSL_DTLS_CONNECTION_ID\n *\n * Enable support for the DTLS Connection ID (CID) extension,\n * which allows to identify DTLS connections across changes\n * in the underlying transport. The CID functionality is described\n * in RFC 9146.\n *\n * Setting this option enables the SSL APIs `mbedtls_ssl_set_cid()`,\n * mbedtls_ssl_get_own_cid()`, `mbedtls_ssl_get_peer_cid()` and\n * `mbedtls_ssl_conf_cid()`. See the corresponding documentation for\n * more information.\n *\n * The maximum lengths of outgoing and incoming CIDs can be configured\n * through the options\n * - MBEDTLS_SSL_CID_OUT_LEN_MAX\n * - MBEDTLS_SSL_CID_IN_LEN_MAX.\n *\n * Requires: MBEDTLS_SSL_PROTO_DTLS\n *\n * Uncomment to enable the Connection ID extension.\n */\n#define MBEDTLS_SSL_DTLS_CONNECTION_ID\n\n\n/**\n * \\def MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT\n *\n * Defines whether RFC 9146 (default) or the legacy version\n * (version draft-ietf-tls-dtls-connection-id-05,\n * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05)\n * is used.\n *\n * Set the value to 0 for the standard version, and\n * 1 for the legacy draft version.\n *\n * \\deprecated Support for the legacy version of the DTLS\n *             Connection ID feature is deprecated. Please\n *             switch to the standardized version defined\n *             in RFC 9146 enabled by utilizing\n *             MBEDTLS_SSL_DTLS_CONNECTION_ID without use\n *             of MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT.\n *\n * Requires: MBEDTLS_SSL_DTLS_CONNECTION_ID\n */\n#define MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT 0\n\n/**\n * \\def MBEDTLS_SSL_ASYNC_PRIVATE\n *\n * Enable asynchronous external private key operations in SSL. This allows\n * you to configure an SSL connection to call an external cryptographic\n * module to perform private key operations instead of performing the\n * operation inside the library.\n *\n * Requires: MBEDTLS_X509_CRT_PARSE_C\n */\n//#define MBEDTLS_SSL_ASYNC_PRIVATE\n\n/** \\def MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME\n *\n * In TLS clients, when a client authenticates a server through its\n * certificate, the client normally checks three things:\n * - the certificate chain must be valid;\n * - the chain must start from a trusted CA;\n * - the certificate must cover the server name that is expected by the client.\n *\n * Omitting any of these checks is generally insecure, and can allow a\n * malicious server to impersonate a legitimate server.\n *\n * The third check may be safely skipped in some unusual scenarios,\n * such as networks where eavesdropping is a risk but not active attacks,\n * or a private PKI where the client equally trusts all servers that are\n * accredited by the root CA.\n *\n * You should call mbedtls_ssl_set_hostname() with the expected server name\n * before starting a TLS handshake on a client (unless the client is\n * set up to only use PSK-based authentication, which does not rely on the\n * host name). This configuration option controls what happens if a TLS client\n * is configured with the authentication mode #MBEDTLS_SSL_VERIFY_REQUIRED\n * (default), certificate authentication is enabled and the client does not\n * call mbedtls_ssl_set_hostname():\n *\n * - If this option is unset (default), the connection attempt is aborted\n *   with the error #MBEDTLS_ERR_SSL_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME.\n * - If this option is set, the TLS library does not check the server name\n *   that the certificate is valid for. This is the historical behavior\n *   of Mbed TLS, but may be insecure as explained above.\n *\n * Enable this option for strict backward compatibility if you have\n * determined that it is secure in the scenario where you are using\n * Mbed TLS.\n *\n * \\deprecated This option exists only for backward compatibility and will\n *             be removed in the next major version of Mbed TLS.\n *\n */\n//#define MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME\n\n/**\n * \\def MBEDTLS_SSL_CONTEXT_SERIALIZATION\n *\n * Enable serialization of the TLS context structures, through use of the\n * functions mbedtls_ssl_context_save() and mbedtls_ssl_context_load().\n *\n * This pair of functions allows one side of a connection to serialize the\n * context associated with the connection, then free or re-use that context\n * while the serialized state is persisted elsewhere, and finally deserialize\n * that state to a live context for resuming read/write operations on the\n * connection. From a protocol perspective, the state of the connection is\n * unaffected, in particular this is entirely transparent to the peer.\n *\n * Note: this is distinct from TLS session resumption, which is part of the\n * protocol and fully visible by the peer. TLS session resumption enables\n * establishing new connections associated to a saved session with shorter,\n * lighter handshakes, while context serialization is a local optimization in\n * handling a single, potentially long-lived connection.\n *\n * Enabling these APIs makes some SSL structures larger, as 64 extra bytes are\n * saved after the handshake to allow for more efficient serialization, so if\n * you don't need this feature you'll save RAM by disabling it.\n *\n * Requires: MBEDTLS_GCM_C or MBEDTLS_CCM_C or MBEDTLS_CHACHAPOLY_C\n *\n * Comment to disable the context serialization APIs.\n */\n#define MBEDTLS_SSL_CONTEXT_SERIALIZATION\n\n/**\n * \\def MBEDTLS_SSL_DEBUG_ALL\n *\n * Enable the debug messages in SSL module for all issues.\n * Debug messages have been disabled in some places to prevent timing\n * attacks due to (unbalanced) debugging function calls.\n *\n * If you need all error reporting you should enable this during debugging,\n * but remove this for production servers that should log as well.\n *\n * Uncomment this macro to report all debug messages on errors introducing\n * a timing side-channel.\n *\n */\n//#define MBEDTLS_SSL_DEBUG_ALL\n\n/** \\def MBEDTLS_SSL_ENCRYPT_THEN_MAC\n *\n * Enable support for Encrypt-then-MAC, RFC 7366.\n *\n * This allows peers that both support it to use a more robust protection for\n * ciphersuites using CBC, providing deep resistance against timing attacks\n * on the padding or underlying cipher.\n *\n * This only affects CBC ciphersuites, and is useless if none is defined.\n *\n * Requires: MBEDTLS_SSL_PROTO_TLS1_2\n *\n * Comment this macro to disable support for Encrypt-then-MAC\n */\n#define MBEDTLS_SSL_ENCRYPT_THEN_MAC\n\n/** \\def MBEDTLS_SSL_EXTENDED_MASTER_SECRET\n *\n * Enable support for RFC 7627: Session Hash and Extended Master Secret\n * Extension.\n *\n * This was introduced as \"the proper fix\" to the Triple Handshake family of\n * attacks, but it is recommended to always use it (even if you disable\n * renegotiation), since it actually fixes a more fundamental issue in the\n * original SSL/TLS design, and has implications beyond Triple Handshake.\n *\n * Requires: MBEDTLS_SSL_PROTO_TLS1_2\n *\n * Comment this macro to disable support for Extended Master Secret.\n */\n#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET\n\n/**\n * \\def MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n *\n * This option controls the availability of the API mbedtls_ssl_get_peer_cert()\n * giving access to the peer's certificate after completion of the handshake.\n *\n * Unless you need mbedtls_ssl_peer_cert() in your application, it is\n * recommended to disable this option for reduced RAM usage.\n *\n * \\note If this option is disabled, mbedtls_ssl_get_peer_cert() is still\n *       defined, but always returns \\c NULL.\n *\n * \\note This option has no influence on the protection against the\n *       triple handshake attack. Even if it is disabled, Mbed TLS will\n *       still ensure that certificates do not change during renegotiation,\n *       for example by keeping a hash of the peer's certificate.\n *\n * \\note This option is required if MBEDTLS_SSL_PROTO_TLS1_3 is set.\n *\n * Comment this macro to disable storing the peer's certificate\n * after the handshake.\n */\n#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n\n/**\n * \\def MBEDTLS_SSL_KEYING_MATERIAL_EXPORT\n *\n * When this option is enabled, the client and server can extract additional\n * shared symmetric keys after an SSL handshake using the function\n * mbedtls_ssl_export_keying_material().\n *\n * The process for deriving the keys is specified in RFC 5705 for TLS 1.2 and\n * in RFC 8446, Section 7.5, for TLS 1.3.\n *\n * Comment this macro to disable mbedtls_ssl_export_keying_material().\n */\n#define MBEDTLS_SSL_KEYING_MATERIAL_EXPORT\n\n/**\n * \\def MBEDTLS_SSL_RENEGOTIATION\n *\n * Enable support for TLS renegotiation.\n *\n * The two main uses of renegotiation are (1) refresh keys on long-lived\n * connections and (2) client authentication after the initial handshake.\n * If you don't need renegotiation, it's probably better to disable it, since\n * it has been associated with security issues in the past and is easy to\n * misuse/misunderstand.\n *\n * Requires: MBEDTLS_SSL_PROTO_TLS1_2\n *\n * Comment this to disable support for renegotiation.\n *\n * \\note   Even if this option is disabled, both client and server are aware\n *         of the Renegotiation Indication Extension (RFC 5746) used to\n *         prevent the SSL renegotiation attack (see RFC 5746 Sect. 1).\n *         (See \\c mbedtls_ssl_conf_legacy_renegotiation for the\n *          configuration of this extension).\n *\n */\n#define MBEDTLS_SSL_RENEGOTIATION\n\n/**\n * \\def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH\n *\n * Enable support for RFC 6066 max_fragment_length extension in SSL.\n *\n * Comment this macro to disable support for the max_fragment_length extension\n */\n#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH\n\n/**\n * \\def MBEDTLS_SSL_RECORD_SIZE_LIMIT\n *\n * Enable support for RFC 8449 record_size_limit extension in SSL (TLS 1.3 only).\n *\n * Requires: MBEDTLS_SSL_PROTO_TLS1_3\n *\n * Uncomment this macro to enable support for the record_size_limit extension\n */\n//#define MBEDTLS_SSL_RECORD_SIZE_LIMIT\n\n/**\n * \\def MBEDTLS_SSL_PROTO_TLS1_2\n *\n * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled).\n *\n * Requires: Without MBEDTLS_USE_PSA_CRYPTO: MBEDTLS_MD_C and\n *              (MBEDTLS_SHA256_C or MBEDTLS_SHA384_C or\n *               SHA-256 or SHA-512 provided by a PSA driver)\n *           With MBEDTLS_USE_PSA_CRYPTO:\n *              PSA_WANT_ALG_SHA_256 or PSA_WANT_ALG_SHA_384\n *\n * \\warning If building with MBEDTLS_USE_PSA_CRYPTO, or if the hash(es) used\n * are only provided by PSA drivers, you must call psa_crypto_init() before\n * doing any TLS operations.\n *\n * Comment this macro to disable support for TLS 1.2 / DTLS 1.2\n */\n#define MBEDTLS_SSL_PROTO_TLS1_2\n\n/**\n * \\def MBEDTLS_SSL_PROTO_TLS1_3\n *\n * Enable support for TLS 1.3.\n *\n * \\note See docs/architecture/tls13-support.md for a description of the TLS\n *       1.3 support that this option enables.\n *\n * Requires: MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n * Requires: MBEDTLS_PSA_CRYPTO_C\n *\n * \\note TLS 1.3 uses PSA crypto for cryptographic operations that are\n *       directly performed by TLS 1.3 code. As a consequence, when TLS 1.3\n *       is enabled, a TLS handshake may call psa_crypto_init(), even\n *       if it ends up negotiating a different TLS version.\n *\n * \\note Cryptographic operations performed indirectly via another module\n *       (X.509, PK) or by code shared with TLS 1.2 (record protection,\n *       running handshake hash) only use PSA crypto if\n *       #MBEDTLS_USE_PSA_CRYPTO is enabled.\n *\n * \\note In multithreaded applications, you must also enable\n *       #MBEDTLS_THREADING_C, even if individual TLS contexts are not\n *       shared between threads, unless only one thread ever calls\n *       TLS functions.\n *\n * Uncomment this macro to enable the support for TLS 1.3.\n */\n#define MBEDTLS_SSL_PROTO_TLS1_3\n\n/**\n * \\def MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE\n *\n * Enable TLS 1.3 middlebox compatibility mode.\n *\n * As specified in Section D.4 of RFC 8446, TLS 1.3 offers a compatibility\n * mode to make a TLS 1.3 connection more likely to pass through middle boxes\n * expecting TLS 1.2 traffic.\n *\n * Turning on the compatibility mode comes at the cost of a few added bytes\n * on the wire, but it doesn't affect compatibility with TLS 1.3 implementations\n * that don't use it. Therefore, unless transmission bandwidth is critical and\n * you know that middlebox compatibility issues won't occur, it is therefore\n * recommended to set this option.\n *\n * Comment to disable compatibility mode for TLS 1.3. If\n * MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not have any\n * effect on the build.\n *\n */\n#define MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE\n\n/**\n * \\def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED\n *\n * Enable TLS 1.3 PSK key exchange mode.\n *\n * Comment to disable support for the PSK key exchange mode in TLS 1.3. If\n * MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not have any\n * effect on the build.\n *\n */\n#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED\n\n/**\n * \\def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED\n *\n * Enable TLS 1.3 ephemeral key exchange mode.\n *\n * Requires: PSA_WANT_ALG_ECDH or PSA_WANT_ALG_FFDH\n *           MBEDTLS_X509_CRT_PARSE_C\n *           and at least one of:\n *               MBEDTLS_ECDSA_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDSA)\n *               MBEDTLS_PKCS1_V21\n *\n * Comment to disable support for the ephemeral key exchange mode in TLS 1.3.\n * If MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not have any\n * effect on the build.\n *\n */\n#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED\n\n/**\n * \\def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED\n *\n * Enable TLS 1.3 PSK ephemeral key exchange mode.\n *\n * Requires: PSA_WANT_ALG_ECDH or PSA_WANT_ALG_FFDH\n *\n * Comment to disable support for the PSK ephemeral key exchange mode in\n * TLS 1.3. If MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not\n * have any effect on the build.\n *\n */\n#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED\n\n/**\n * \\def MBEDTLS_SSL_EARLY_DATA\n *\n * Enable support for RFC 8446 TLS 1.3 early data.\n *\n * Requires: MBEDTLS_SSL_SESSION_TICKETS and either\n *           MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED or\n *           MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED\n *\n * Comment this to disable support for early data. If MBEDTLS_SSL_PROTO_TLS1_3\n * is not enabled, this option does not have any effect on the build.\n *\n * \\note The maximum amount of early data can be set with\n *       MBEDTLS_SSL_MAX_EARLY_DATA_SIZE.\n *\n */\n//#define MBEDTLS_SSL_EARLY_DATA\n\n/**\n * \\def MBEDTLS_SSL_PROTO_DTLS\n *\n * Enable support for DTLS (all available versions).\n *\n * Enable this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2.\n *\n * Requires: MBEDTLS_SSL_PROTO_TLS1_2\n *\n * Comment this macro to disable support for DTLS\n */\n#define MBEDTLS_SSL_PROTO_DTLS\n\n/**\n * \\def MBEDTLS_SSL_ALPN\n *\n * Enable support for RFC 7301 Application Layer Protocol Negotiation.\n *\n * Comment this macro to disable support for ALPN.\n */\n#define MBEDTLS_SSL_ALPN\n\n/**\n * \\def MBEDTLS_SSL_DTLS_ANTI_REPLAY\n *\n * Enable support for the anti-replay mechanism in DTLS.\n *\n * Requires: MBEDTLS_SSL_TLS_C\n *           MBEDTLS_SSL_PROTO_DTLS\n *\n * \\warning Disabling this is often a security risk!\n * See mbedtls_ssl_conf_dtls_anti_replay() for details.\n *\n * Comment this to disable anti-replay in DTLS.\n */\n#define MBEDTLS_SSL_DTLS_ANTI_REPLAY\n\n/**\n * \\def MBEDTLS_SSL_DTLS_HELLO_VERIFY\n *\n * Enable support for HelloVerifyRequest on DTLS servers.\n *\n * This feature is highly recommended to prevent DTLS servers being used as\n * amplifiers in DoS attacks against other hosts. It should always be enabled\n * unless you know for sure amplification cannot be a problem in the\n * environment in which your server operates.\n *\n * \\warning Disabling this can be a security risk! (see above)\n *\n * Requires: MBEDTLS_SSL_PROTO_DTLS\n *\n * Comment this to disable support for HelloVerifyRequest.\n */\n#define MBEDTLS_SSL_DTLS_HELLO_VERIFY\n\n/**\n * \\def MBEDTLS_SSL_DTLS_SRTP\n *\n * Enable support for negotiation of DTLS-SRTP (RFC 5764)\n * through the use_srtp extension.\n *\n * \\note This feature provides the minimum functionality required\n * to negotiate the use of DTLS-SRTP and to allow the derivation of\n * the associated SRTP packet protection key material.\n * In particular, the SRTP packet protection itself, as well as the\n * demultiplexing of RTP and DTLS packets at the datagram layer\n * (see Section 5 of RFC 5764), are not handled by this feature.\n * Instead, after successful completion of a handshake negotiating\n * the use of DTLS-SRTP, the extended key exporter API\n * mbedtls_ssl_conf_export_keys_cb() should be used to implement\n * the key exporter described in Section 4.2 of RFC 5764 and RFC 5705\n * (this is implemented in the SSL example programs).\n * The resulting key should then be passed to an SRTP stack.\n *\n * Setting this option enables the runtime API\n * mbedtls_ssl_conf_dtls_srtp_protection_profiles()\n * through which the supported DTLS-SRTP protection\n * profiles can be configured. You must call this API at\n * runtime if you wish to negotiate the use of DTLS-SRTP.\n *\n * Requires: MBEDTLS_SSL_PROTO_DTLS\n *\n * Uncomment this to enable support for use_srtp extension.\n */\n//#define MBEDTLS_SSL_DTLS_SRTP\n\n/**\n * \\def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE\n *\n * Enable server-side support for clients that reconnect from the same port.\n *\n * Some clients unexpectedly close the connection and try to reconnect using the\n * same source port. This needs special support from the server to handle the\n * new connection securely, as described in section 4.2.8 of RFC 6347. This\n * flag enables that support.\n *\n * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY\n *\n * Comment this to disable support for clients reusing the source port.\n */\n#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE\n\n/**\n * \\def MBEDTLS_SSL_SESSION_TICKETS\n *\n * Enable support for RFC 5077 session tickets in SSL.\n * Client-side, provides full support for session tickets (maintenance of a\n * session store remains the responsibility of the application, though).\n * Server-side, you also need to provide callbacks for writing and parsing\n * tickets, including authenticated encryption and key management. Example\n * callbacks are provided by MBEDTLS_SSL_TICKET_C.\n *\n * Comment this macro to disable support for SSL session tickets\n */\n#define MBEDTLS_SSL_SESSION_TICKETS\n\n/**\n * \\def MBEDTLS_SSL_SERVER_NAME_INDICATION\n *\n * Enable support for RFC 6066 server name indication (SNI) in SSL.\n *\n * Requires: MBEDTLS_X509_CRT_PARSE_C\n *\n * Comment this macro to disable support for server name indication in SSL\n */\n#define MBEDTLS_SSL_SERVER_NAME_INDICATION\n\n/**\n * \\def MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH\n *\n * When this option is enabled, the SSL buffer will be resized automatically\n * based on the negotiated maximum fragment length in each direction.\n *\n * Requires: MBEDTLS_SSL_MAX_FRAGMENT_LENGTH\n */\n//#define MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH\n\n/**\n * \\def MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN\n *\n * Enable testing of the constant-flow nature of some sensitive functions with\n * clang's MemorySanitizer. This causes some existing tests to also test\n * this non-functional property of the code under test.\n *\n * This setting requires compiling with clang -fsanitize=memory. The test\n * suites can then be run normally.\n *\n * \\warning This macro is only used for extended testing; it is not considered\n * part of the library's API, so it may change or disappear at any time.\n *\n * Uncomment to enable testing of the constant-flow nature of selected code.\n */\n//#define MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN\n\n/**\n * \\def MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND\n *\n * Enable testing of the constant-flow nature of some sensitive functions with\n * valgrind's memcheck tool. This causes some existing tests to also test\n * this non-functional property of the code under test.\n *\n * This setting requires valgrind headers for building, and is only useful for\n * testing if the tests suites are run with valgrind's memcheck. This can be\n * done for an individual test suite with 'valgrind ./test_suite_xxx', or when\n * using CMake, this can be done for all test suites with 'make memcheck'.\n *\n * \\warning This macro is only used for extended testing; it is not considered\n * part of the library's API, so it may change or disappear at any time.\n *\n * Uncomment to enable testing of the constant-flow nature of selected code.\n */\n//#define MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND\n\n/**\n * \\def MBEDTLS_TEST_HOOKS\n *\n * Enable features for invasive testing such as introspection functions and\n * hooks for fault injection. This enables additional unit tests.\n *\n * Merely enabling this feature should not change the behavior of the product.\n * It only adds new code, and new branching points where the default behavior\n * is the same as when this feature is disabled.\n * However, this feature increases the attack surface: there is an added\n * risk of vulnerabilities, and more gadgets that can make exploits easier.\n * Therefore this feature must never be enabled in production.\n *\n * See `docs/architecture/testing/mbed-crypto-invasive-testing.md` for more\n * information.\n *\n * Uncomment to enable invasive tests.\n */\n//#define MBEDTLS_TEST_HOOKS\n\n/**\n * \\def MBEDTLS_THREADING_ALT\n *\n * Provide your own alternate implementation of threading primitives\n * for mutexes. If you enable this option:\n *\n * - Provide a header file `\"threading_alt.h\"`, defining the\n *   type `mbedtls_threading_mutex_t` of mutex objects.\n *\n * - Call the function mbedtls_threading_set_alt() in your application\n *   before calling any other library function (in particular before\n *   calling psa_crypto_init(), performing an asymmetric cryptography\n *   operation, or starting a TLS connection).\n *\n * See mbedtls/threading.h for more details, especially the documentation\n * of mbedtls_threading_set_alt().\n *\n * Requires: MBEDTLS_THREADING_C\n *\n * Uncomment this to allow your own alternate threading implementation.\n */\n//#define MBEDTLS_THREADING_ALT\n\n/**\n * \\def MBEDTLS_THREADING_PTHREAD\n *\n * Enable the pthread wrapper layer for the threading layer.\n *\n * Requires: MBEDTLS_THREADING_C\n *\n * Uncomment this to enable pthread mutexes.\n */\n//#define MBEDTLS_THREADING_PTHREAD\n\n/**\n * \\def MBEDTLS_USE_PSA_CRYPTO\n *\n * Make the X.509 and TLS libraries use PSA for cryptographic operations as\n * much as possible, and enable new APIs for using keys handled by PSA Crypto.\n *\n * \\note Development of this option is currently in progress, and parts of Mbed\n * TLS's X.509 and TLS modules are not ported to PSA yet. However, these parts\n * will still continue to work as usual, so enabling this option should not\n * break backwards compatibility.\n *\n * \\warning If you enable this option, you need to call `psa_crypto_init()`\n * before calling any function from the SSL/TLS, X.509 or PK modules, except\n * for the various mbedtls_xxx_init() functions which can be called at any time.\n *\n * \\warning In multithreaded applications, you must also enable\n * #MBEDTLS_THREADING_C, unless only one thread ever calls PSA functions\n * (`psa_xxx()`), including indirect calls through SSL/TLS, X.509 or PK.\n *\n * \\note An important and desirable effect of this option is that it allows\n * PK, X.509 and TLS to take advantage of PSA drivers. For example, enabling\n * this option is what allows use of drivers for ECDSA, ECDH and EC J-PAKE in\n * those modules. However, note that even with this option disabled, some code\n * in PK, X.509, TLS or the crypto library might still use PSA drivers, if it\n * can determine it's safe to do so; currently that's the case for hashes.\n *\n * \\note See docs/use-psa-crypto.md for a complete description this option.\n *\n * Requires: MBEDTLS_PSA_CRYPTO_C.\n *\n * Uncomment this to enable internal use of PSA Crypto and new associated APIs.\n */\n//#define MBEDTLS_USE_PSA_CRYPTO\n\n/**\n * \\def MBEDTLS_PSA_CRYPTO_CONFIG\n *\n * This setting allows support for cryptographic mechanisms through the PSA\n * API to be configured separately from support through the mbedtls API.\n *\n * When this option is disabled, the PSA API exposes the cryptographic\n * mechanisms that can be implemented on top of the `mbedtls_xxx` API\n * configured with `MBEDTLS_XXX` symbols.\n *\n * When this option is enabled, the PSA API exposes the cryptographic\n * mechanisms requested by the `PSA_WANT_XXX` symbols defined in\n * include/psa/crypto_config.h. The corresponding `MBEDTLS_XXX` settings are\n * automatically enabled if required (i.e. if no PSA driver provides the\n * mechanism). You may still freely enable additional `MBEDTLS_XXX` symbols\n * in mbedtls_config.h.\n *\n * If the symbol #MBEDTLS_PSA_CRYPTO_CONFIG_FILE is defined, it specifies\n * an alternative header to include instead of include/psa/crypto_config.h.\n *\n * \\warning This option is experimental, in that the set of `PSA_WANT_XXX`\n *          symbols is not completely finalized yet, and the configuration\n *          tooling is not ideally adapted to having two separate configuration\n *          files.\n *          Future minor releases of Mbed TLS may make minor changes to those\n *          symbols, but we will endeavor to provide a transition path.\n *          Nonetheless, this option is considered mature enough to use in\n *          production, as long as you accept that you may need to make\n *          minor changes to psa/crypto_config.h when upgrading Mbed TLS.\n */\n//#define MBEDTLS_PSA_CRYPTO_CONFIG\n\n/**\n * \\def MBEDTLS_VERSION_FEATURES\n *\n * Allow run-time checking of compile-time enabled features. Thus allowing users\n * to check at run-time if the library is for instance compiled with threading\n * support via mbedtls_version_check_feature().\n *\n * Requires: MBEDTLS_VERSION_C\n *\n * Comment this to disable run-time checking and save ROM space\n */\n#define MBEDTLS_VERSION_FEATURES\n\n/**\n * \\def MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK\n *\n * If set, this enables the X.509 API `mbedtls_x509_crt_verify_with_ca_cb()`\n * and the SSL API `mbedtls_ssl_conf_ca_cb()` which allow users to configure\n * the set of trusted certificates through a callback instead of a linked\n * list.\n *\n * This is useful for example in environments where a large number of trusted\n * certificates is present and storing them in a linked list isn't efficient\n * enough, or when the set of trusted certificates changes frequently.\n *\n * See the documentation of `mbedtls_x509_crt_verify_with_ca_cb()` and\n * `mbedtls_ssl_conf_ca_cb()` for more information.\n *\n * Requires: MBEDTLS_X509_CRT_PARSE_C\n *\n * Uncomment to enable trusted certificate callbacks.\n */\n//#define MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK\n\n/**\n * \\def MBEDTLS_X509_REMOVE_INFO\n *\n * Disable mbedtls_x509_*_info() and related APIs.\n *\n * Uncomment to omit mbedtls_x509_*_info(), as well as mbedtls_debug_print_crt()\n * and other functions/constants only used by these functions, thus reducing\n * the code footprint by several KB.\n */\n//#define MBEDTLS_X509_REMOVE_INFO\n\n/**\n * \\def MBEDTLS_X509_RSASSA_PSS_SUPPORT\n *\n * Enable parsing and verification of X.509 certificates, CRLs and CSRS\n * signed with RSASSA-PSS (aka PKCS#1 v2.1).\n *\n * Requires: MBEDTLS_PKCS1_V21\n *\n * Comment this macro to disallow using RSASSA-PSS in certificates.\n */\n#define MBEDTLS_X509_RSASSA_PSS_SUPPORT\n/** \\} name SECTION: Mbed TLS feature support */\n\n/**\n * \\name SECTION: Mbed TLS modules\n *\n * This section enables or disables entire modules in Mbed TLS\n * \\{\n */\n\n/**\n * \\def MBEDTLS_AESNI_C\n *\n * Enable AES-NI support on x86-64 or x86-32.\n *\n * \\note AESNI is only supported with certain compilers and target options:\n * - Visual Studio: supported\n * - GCC, x86-64, target not explicitly supporting AESNI:\n *   requires MBEDTLS_HAVE_ASM.\n * - GCC, x86-32, target not explicitly supporting AESNI:\n *   not supported.\n * - GCC, x86-64 or x86-32, target supporting AESNI: supported.\n *   For this assembly-less implementation, you must currently compile\n *   `library/aesni.c` and `library/aes.c` with machine options to enable\n *   SSE2 and AESNI instructions: `gcc -msse2 -maes -mpclmul` or\n *   `clang -maes -mpclmul`.\n * - Non-x86 targets: this option is silently ignored.\n * - Other compilers: this option is silently ignored.\n *\n * \\note\n * Above, \"GCC\" includes compatible compilers such as Clang.\n * The limitations on target support are likely to be relaxed in the future.\n *\n * Module:  library/aesni.c\n * Caller:  library/aes.c\n *\n * Requires: MBEDTLS_HAVE_ASM (on some platforms, see note)\n *\n * This modules adds support for the AES-NI instructions on x86.\n */\n#define MBEDTLS_AESNI_C\n\n/**\n * \\def MBEDTLS_AESCE_C\n *\n * Enable AES cryptographic extension support on Armv8.\n *\n * Module:  library/aesce.c\n * Caller:  library/aes.c\n *\n * Requires: MBEDTLS_AES_C\n *\n * \\warning Runtime detection only works on Linux. For non-Linux operating\n *          system, Armv8-A Cryptographic Extensions must be supported by\n *          the CPU when this option is enabled.\n *\n * \\note    Minimum compiler versions for this feature when targeting aarch64\n *          are Clang 4.0; armclang 6.6; GCC 6.0; or MSVC 2019 version 16.11.2.\n *          Minimum compiler versions for this feature when targeting 32-bit\n *          Arm or Thumb are Clang 11.0; armclang 6.20; or GCC 6.0.\n *\n * \\note \\c CFLAGS must be set to a minimum of \\c -march=armv8-a+crypto for\n * armclang <= 6.9\n *\n * This module adds support for the AES Armv8-A Cryptographic Extensions on Armv8 systems.\n */\n#define MBEDTLS_AESCE_C\n\n/**\n * \\def MBEDTLS_AES_C\n *\n * Enable the AES block cipher.\n *\n * Module:  library/aes.c\n * Caller:  library/cipher.c\n *          library/pem.c\n *          library/ctr_drbg.c\n *\n * This module enables the following ciphersuites (if other requisites are\n * enabled as well):\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256\n *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA\n *      MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384\n *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384\n *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA\n *      MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256\n *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256\n *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA\n *\n * PEM_PARSE uses AES for decrypting encrypted keys.\n */\n#define MBEDTLS_AES_C\n\n/**\n * \\def MBEDTLS_ASN1_PARSE_C\n *\n * Enable the generic ASN1 parser.\n *\n * Module:  library/asn1.c\n * Caller:  library/x509.c\n *          library/dhm.c\n *          library/pkcs12.c\n *          library/pkcs5.c\n *          library/pkparse.c\n */\n#define MBEDTLS_ASN1_PARSE_C\n\n/**\n * \\def MBEDTLS_ASN1_WRITE_C\n *\n * Enable the generic ASN1 writer.\n *\n * Module:  library/asn1write.c\n * Caller:  library/ecdsa.c\n *          library/pkwrite.c\n *          library/x509_create.c\n *          library/x509write_crt.c\n *          library/x509write_csr.c\n */\n#define MBEDTLS_ASN1_WRITE_C\n\n/**\n * \\def MBEDTLS_BASE64_C\n *\n * Enable the Base64 module.\n *\n * Module:  library/base64.c\n * Caller:  library/pem.c\n *\n * This module is required for PEM support (required by X.509).\n */\n#define MBEDTLS_BASE64_C\n\n/**\n * \\def MBEDTLS_BLOCK_CIPHER_NO_DECRYPT\n *\n * Remove decryption operation for AES, ARIA and Camellia block cipher.\n *\n * \\note  This feature is incompatible with insecure block cipher,\n *        MBEDTLS_DES_C, and cipher modes which always require decryption\n *        operation, MBEDTLS_CIPHER_MODE_CBC, MBEDTLS_CIPHER_MODE_XTS and\n *        MBEDTLS_NIST_KW_C. When #MBEDTLS_PSA_CRYPTO_CONFIG is enabled,\n *        this feature is incompatible with following supported PSA equivalence,\n *        PSA_WANT_ALG_ECB_NO_PADDING, PSA_WANT_ALG_CBC_NO_PADDING,\n *        PSA_WANT_ALG_CBC_PKCS7 and PSA_WANT_KEY_TYPE_DES.\n *\n * Module:  library/aes.c\n *          library/aesce.c\n *          library/aesni.c\n *          library/aria.c\n *          library/camellia.c\n *          library/cipher.c\n */\n//#define MBEDTLS_BLOCK_CIPHER_NO_DECRYPT\n\n/**\n * \\def MBEDTLS_BIGNUM_C\n *\n * Enable the multi-precision integer library.\n *\n * Module:  library/bignum.c\n *          library/bignum_core.c\n *          library/bignum_mod.c\n *          library/bignum_mod_raw.c\n * Caller:  library/dhm.c\n *          library/ecp.c\n *          library/ecdsa.c\n *          library/rsa.c\n *          library/rsa_alt_helpers.c\n *          library/ssl_tls.c\n *\n * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support.\n */\n#define MBEDTLS_BIGNUM_C\n\n/**\n * \\def MBEDTLS_CAMELLIA_C\n *\n * Enable the Camellia block cipher.\n *\n * Module:  library/camellia.c\n * Caller:  library/cipher.c\n *\n * This module enables the following ciphersuites (if other requisites are\n * enabled as well):\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256\n *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256\n *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256\n *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA\n *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256\n *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256\n *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA\n *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256\n *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA\n *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256\n *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384\n *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384\n *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256\n *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256\n */\n#define MBEDTLS_CAMELLIA_C\n\n/**\n * \\def MBEDTLS_ARIA_C\n *\n * Enable the ARIA block cipher.\n *\n * Module:  library/aria.c\n * Caller:  library/cipher.c\n *\n * This module enables the following ciphersuites (if other requisites are\n * enabled as well):\n *\n *      MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256\n *      MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384\n *      MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256\n *      MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384\n *      MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384\n *      MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256\n *      MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384\n *      MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256\n *      MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256\n *      MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384\n *      MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256\n *      MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384\n *      MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256\n *      MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384\n *      MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256\n *      MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384\n *      MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256\n *      MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384\n *      MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256\n *      MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384\n *      MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256\n *      MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256\n *      MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384\n */\n#define MBEDTLS_ARIA_C\n\n/**\n * \\def MBEDTLS_CCM_C\n *\n * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher.\n *\n * Module:  library/ccm.c\n *\n * Requires: MBEDTLS_CIPHER_C, MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or\n *                             MBEDTLS_ARIA_C\n *\n * This module enables the AES-CCM ciphersuites, if other requisites are\n * enabled as well.\n */\n#define MBEDTLS_CCM_C\n\n/**\n * \\def MBEDTLS_CHACHA20_C\n *\n * Enable the ChaCha20 stream cipher.\n *\n * Module:  library/chacha20.c\n */\n#define MBEDTLS_CHACHA20_C\n\n/**\n * \\def MBEDTLS_CHACHAPOLY_C\n *\n * Enable the ChaCha20-Poly1305 AEAD algorithm.\n *\n * Module:  library/chachapoly.c\n *\n * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C\n */\n#define MBEDTLS_CHACHAPOLY_C\n\n/**\n * \\def MBEDTLS_CIPHER_C\n *\n * Enable the generic cipher layer.\n *\n * Module:  library/cipher.c\n * Caller:  library/ccm.c\n *          library/cmac.c\n *          library/gcm.c\n *          library/nist_kw.c\n *          library/pkcs12.c\n *          library/pkcs5.c\n *          library/psa_crypto_aead.c\n *          library/psa_crypto_mac.c\n *          library/ssl_ciphersuites.c\n *          library/ssl_msg.c\n *          library/ssl_ticket.c (unless MBEDTLS_USE_PSA_CRYPTO is enabled)\n * Auto-enabled by: MBEDTLS_PSA_CRYPTO_C depending on which ciphers are enabled\n *                  (see the documentation of that option for details).\n *\n * Uncomment to enable generic cipher wrappers.\n */\n#define MBEDTLS_CIPHER_C\n\n/**\n * \\def MBEDTLS_CMAC_C\n *\n * Enable the CMAC (Cipher-based Message Authentication Code) mode for block\n * ciphers.\n *\n * \\note When #MBEDTLS_CMAC_ALT is active, meaning that the underlying\n *       implementation of the CMAC algorithm is provided by an alternate\n *       implementation, that alternate implementation may opt to not support\n *       AES-192 or 3DES as underlying block ciphers for the CMAC operation.\n *\n * Module:  library/cmac.c\n *\n * Requires: MBEDTLS_CIPHER_C, MBEDTLS_AES_C or MBEDTLS_DES_C\n *\n */\n#define MBEDTLS_CMAC_C\n\n/**\n * \\def MBEDTLS_CTR_DRBG_C\n *\n * Enable the CTR_DRBG AES-based random generator.\n * The CTR_DRBG generator uses AES-256 by default.\n * To use AES-128 instead, enable \\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above.\n *\n * AES support can either be achieved through builtin (MBEDTLS_AES_C) or PSA.\n * Builtin is the default option when MBEDTLS_AES_C is defined otherwise PSA\n * is used.\n *\n * \\warning When using PSA, the user should call `psa_crypto_init()` before\n *          using any CTR_DRBG operation (except `mbedtls_ctr_drbg_init()`).\n *\n * \\note AES-128 will be used if \\c MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH is set.\n *\n * \\note To achieve a 256-bit security strength with CTR_DRBG,\n *       you must use AES-256 *and* use sufficient entropy.\n *       See ctr_drbg.h for more details.\n *\n * Module:  library/ctr_drbg.c\n * Caller:\n *\n * Requires: MBEDTLS_AES_C or\n *           (PSA_WANT_KEY_TYPE_AES and PSA_WANT_ALG_ECB_NO_PADDING and\n *            MBEDTLS_PSA_CRYPTO_C)\n *\n * This module provides the CTR_DRBG AES random number generator.\n */\n#define MBEDTLS_CTR_DRBG_C\n\n/**\n * \\def MBEDTLS_DEBUG_C\n *\n * Enable the debug functions.\n *\n * Module:  library/debug.c\n * Caller:  library/ssl_msg.c\n *          library/ssl_tls.c\n *          library/ssl_tls12_*.c\n *          library/ssl_tls13_*.c\n *\n * This module provides debugging functions.\n */\n#define MBEDTLS_DEBUG_C\n\n/**\n * \\def MBEDTLS_DES_C\n *\n * Enable the DES block cipher.\n *\n * Module:  library/des.c\n * Caller:  library/pem.c\n *          library/cipher.c\n *\n * PEM_PARSE uses DES/3DES for decrypting encrypted keys.\n *\n * \\warning   DES/3DES are considered weak ciphers and their use constitutes a\n *            security risk. We recommend considering stronger ciphers instead.\n */\n#define MBEDTLS_DES_C\n\n/**\n * \\def MBEDTLS_DHM_C\n *\n * Enable the Diffie-Hellman-Merkle module.\n *\n * Module:  library/dhm.c\n * Caller:  library/ssl_tls.c\n *          library/ssl*_client.c\n *          library/ssl*_server.c\n *\n * This module is used by the following key exchanges:\n *      DHE-RSA, DHE-PSK\n *\n * \\warning    Using DHE constitutes a security risk as it\n *             is not possible to validate custom DH parameters.\n *             If possible, it is recommended users should consider\n *             preferring other methods of key exchange.\n *             See dhm.h for more details.\n *\n */\n#define MBEDTLS_DHM_C\n\n/**\n * \\def MBEDTLS_ECDH_C\n *\n * Enable the elliptic curve Diffie-Hellman library.\n *\n * Module:  library/ecdh.c\n * Caller:  library/psa_crypto.c\n *          library/ssl_tls.c\n *          library/ssl*_client.c\n *          library/ssl*_server.c\n *\n * This module is used by the following key exchanges:\n *      ECDHE-ECDSA, ECDHE-RSA, DHE-PSK\n *\n * Requires: MBEDTLS_ECP_C\n */\n#define MBEDTLS_ECDH_C\n\n/**\n * \\def MBEDTLS_ECDSA_C\n *\n * Enable the elliptic curve DSA library.\n *\n * Module:  library/ecdsa.c\n * Caller:\n *\n * This module is used by the following key exchanges:\n *      ECDHE-ECDSA\n *\n * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C,\n *           and at least one MBEDTLS_ECP_DP_XXX_ENABLED for a\n *           short Weierstrass curve.\n */\n#define MBEDTLS_ECDSA_C\n\n/**\n * \\def MBEDTLS_ECJPAKE_C\n *\n * Enable the elliptic curve J-PAKE library.\n *\n * \\note EC J-PAKE support is based on the Thread v1.0.0 specification.\n *       It has not been reviewed for compliance with newer standards such as\n *       Thread v1.1 or RFC 8236.\n *\n * Module:  library/ecjpake.c\n * Caller:\n *\n * This module is used by the following key exchanges:\n *      ECJPAKE\n *\n * Requires: MBEDTLS_ECP_C and either MBEDTLS_MD_C or MBEDTLS_PSA_CRYPTO_C\n *\n * \\warning If using a hash that is only provided by PSA drivers, you must\n * call psa_crypto_init() before doing any EC J-PAKE operations.\n */\n#define MBEDTLS_ECJPAKE_C\n\n/**\n * \\def MBEDTLS_ECP_C\n *\n * Enable the elliptic curve over GF(p) library.\n *\n * Module:  library/ecp.c\n * Caller:  library/ecdh.c\n *          library/ecdsa.c\n *          library/ecjpake.c\n *\n * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED\n */\n#define MBEDTLS_ECP_C\n\n/**\n * \\def MBEDTLS_ENTROPY_C\n *\n * Enable the platform-specific entropy code.\n *\n * Module:  library/entropy.c\n * Caller:\n *\n * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C\n *\n * This module provides a generic entropy pool\n */\n#define MBEDTLS_ENTROPY_C\n\n/**\n * \\def MBEDTLS_ERROR_C\n *\n * Enable error code to error string conversion.\n *\n * Module:  library/error.c\n * Caller:\n *\n * This module enables mbedtls_strerror().\n */\n#define MBEDTLS_ERROR_C\n\n/**\n * \\def MBEDTLS_GCM_C\n *\n * Enable the Galois/Counter Mode (GCM).\n *\n * Module:  library/gcm.c\n *\n * Requires: MBEDTLS_CIPHER_C, MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or\n *                             MBEDTLS_ARIA_C\n *\n * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other\n * requisites are enabled as well.\n */\n#define MBEDTLS_GCM_C\n\n/**\n * \\def MBEDTLS_GCM_LARGE_TABLE\n *\n * Enable large pre-computed tables for  Galois/Counter Mode (GCM).\n * Can significantly increase throughput on systems without GCM hardware\n * acceleration (e.g., AESNI, AESCE).\n *\n * The mbedtls_gcm_context size will increase by 3840 bytes.\n * The code size will increase by roughly 344 bytes.\n *\n * Module:  library/gcm.c\n *\n * Requires: MBEDTLS_GCM_C\n */\n//#define MBEDTLS_GCM_LARGE_TABLE\n\n/**\n * \\def MBEDTLS_HKDF_C\n *\n * Enable the HKDF algorithm (RFC 5869).\n *\n * Module:  library/hkdf.c\n * Caller:\n *\n * Requires: MBEDTLS_MD_C\n *\n * This module adds support for the Hashed Message Authentication Code\n * (HMAC)-based key derivation function (HKDF).\n */\n#define MBEDTLS_HKDF_C\n\n/**\n * \\def MBEDTLS_HMAC_DRBG_C\n *\n * Enable the HMAC_DRBG random generator.\n *\n * Module:  library/hmac_drbg.c\n * Caller:\n *\n * Requires: MBEDTLS_MD_C\n *\n * Uncomment to enable the HMAC_DRBG random number generator.\n */\n#define MBEDTLS_HMAC_DRBG_C\n\n/**\n * \\def MBEDTLS_LMS_C\n *\n * Enable the LMS stateful-hash asymmetric signature algorithm.\n *\n * Module:  library/lms.c\n * Caller:\n *\n * Requires: MBEDTLS_PSA_CRYPTO_C\n *\n * Uncomment to enable the LMS verification algorithm and public key operations.\n */\n#define MBEDTLS_LMS_C\n\n/**\n * \\def MBEDTLS_LMS_PRIVATE\n *\n * Enable LMS private-key operations and signing code. Functions enabled by this\n * option are experimental, and should not be used in production.\n *\n * Requires: MBEDTLS_LMS_C\n *\n * Uncomment to enable the LMS signature algorithm and private key operations.\n */\n//#define MBEDTLS_LMS_PRIVATE\n\n/**\n * \\def MBEDTLS_NIST_KW_C\n *\n * Enable the Key Wrapping mode for 128-bit block ciphers,\n * as defined in NIST SP 800-38F. Only KW and KWP modes\n * are supported. At the moment, only AES is approved by NIST.\n *\n * Module:  library/nist_kw.c\n *\n * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C\n */\n#define MBEDTLS_NIST_KW_C\n\n/**\n * \\def MBEDTLS_MD_C\n *\n * Enable the generic layer for message digest (hashing) and HMAC.\n *\n * Requires: one of: MBEDTLS_MD5_C, MBEDTLS_RIPEMD160_C, MBEDTLS_SHA1_C,\n *                   MBEDTLS_SHA224_C, MBEDTLS_SHA256_C, MBEDTLS_SHA384_C,\n *                   MBEDTLS_SHA512_C, or MBEDTLS_PSA_CRYPTO_C with at least\n *                   one hash.\n * Module:  library/md.c\n * Caller:  library/constant_time.c\n *          library/ecdsa.c\n *          library/ecjpake.c\n *          library/hkdf.c\n *          library/hmac_drbg.c\n *          library/pk.c\n *          library/pkcs5.c\n *          library/pkcs12.c\n *          library/psa_crypto_ecp.c\n *          library/psa_crypto_rsa.c\n *          library/rsa.c\n *          library/ssl_cookie.c\n *          library/ssl_msg.c\n *          library/ssl_tls.c\n *          library/x509.c\n *          library/x509_crt.c\n *          library/x509write_crt.c\n *          library/x509write_csr.c\n *\n * Uncomment to enable generic message digest wrappers.\n */\n#define MBEDTLS_MD_C\n\n/**\n * \\def MBEDTLS_MD5_C\n *\n * Enable the MD5 hash algorithm.\n *\n * Module:  library/md5.c\n * Caller:  library/md.c\n *          library/pem.c\n *          library/ssl_tls.c\n *\n * This module is required for TLS 1.2 depending on the handshake parameters.\n * Further, it is used for checking MD5-signed certificates, and for PBKDF1\n * when decrypting PEM-encoded encrypted keys.\n *\n * \\warning   MD5 is considered a weak message digest and its use constitutes a\n *            security risk. If possible, we recommend avoiding dependencies on\n *            it, and considering stronger message digests instead.\n *\n */\n#define MBEDTLS_MD5_C\n\n/**\n * \\def MBEDTLS_MEMORY_BUFFER_ALLOC_C\n *\n * Enable the buffer allocator implementation that makes use of a (stack)\n * based buffer to 'allocate' dynamic memory. (replaces calloc() and free()\n * calls)\n *\n * Module:  library/memory_buffer_alloc.c\n *\n * Requires: MBEDTLS_PLATFORM_C\n *           MBEDTLS_PLATFORM_MEMORY (to use it within Mbed TLS)\n *\n * Enable this module to enable the buffer memory allocator.\n */\n//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C\n\n/**\n * \\def MBEDTLS_NET_C\n *\n * Enable the TCP and UDP over IPv6/IPv4 networking routines.\n *\n * \\note This module only works on POSIX/Unix (including Linux, BSD and OS X)\n * and Windows. For other platforms, you'll want to disable it, and write your\n * own networking callbacks to be passed to \\c mbedtls_ssl_set_bio().\n *\n * \\note See also our Knowledge Base article about porting to a new\n * environment:\n * https://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS\n *\n * Module:  library/net_sockets.c\n *\n * This module provides networking routines.\n */\n#define MBEDTLS_NET_C\n\n/**\n * \\def MBEDTLS_OID_C\n *\n * Enable the OID database.\n *\n * Module:  library/oid.c\n * Caller:  library/asn1write.c\n *          library/pkcs5.c\n *          library/pkparse.c\n *          library/pkwrite.c\n *          library/rsa.c\n *          library/x509.c\n *          library/x509_create.c\n *          library/x509_crl.c\n *          library/x509_crt.c\n *          library/x509_csr.c\n *          library/x509write_crt.c\n *          library/x509write_csr.c\n *\n * This modules translates between OIDs and internal values.\n */\n#define MBEDTLS_OID_C\n\n/**\n * \\def MBEDTLS_PADLOCK_C\n *\n * Enable VIA Padlock support on x86.\n *\n * Module:  library/padlock.c\n * Caller:  library/aes.c\n *\n * Requires: MBEDTLS_HAVE_ASM\n *\n * This modules adds support for the VIA PadLock on x86.\n */\n#define MBEDTLS_PADLOCK_C\n\n/**\n * \\def MBEDTLS_PEM_PARSE_C\n *\n * Enable PEM decoding / parsing.\n *\n * Module:  library/pem.c\n * Caller:  library/dhm.c\n *          library/pkparse.c\n *          library/x509_crl.c\n *          library/x509_crt.c\n *          library/x509_csr.c\n *\n * Requires: MBEDTLS_BASE64_C\n *           optionally MBEDTLS_MD5_C, or PSA Crypto with MD5 (see below)\n *\n * \\warning When parsing password-protected files, if MD5 is provided only by\n * a PSA driver, you must call psa_crypto_init() before the first file.\n *\n * This modules adds support for decoding / parsing PEM files.\n */\n#define MBEDTLS_PEM_PARSE_C\n\n/**\n * \\def MBEDTLS_PEM_WRITE_C\n *\n * Enable PEM encoding / writing.\n *\n * Module:  library/pem.c\n * Caller:  library/pkwrite.c\n *          library/x509write_crt.c\n *          library/x509write_csr.c\n *\n * Requires: MBEDTLS_BASE64_C\n *\n * This modules adds support for encoding / writing PEM files.\n */\n#define MBEDTLS_PEM_WRITE_C\n\n/**\n * \\def MBEDTLS_PK_C\n *\n * Enable the generic public (asymmetric) key layer.\n *\n * Module:  library/pk.c\n * Caller:  library/psa_crypto_rsa.c\n *          library/ssl_tls.c\n *          library/ssl*_client.c\n *          library/ssl*_server.c\n *          library/x509.c\n *\n * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C or MBEDTLS_ECP_C\n *\n * Uncomment to enable generic public key wrappers.\n */\n#define MBEDTLS_PK_C\n\n/**\n * \\def MBEDTLS_PK_PARSE_C\n *\n * Enable the generic public (asymmetric) key parser.\n *\n * Module:  library/pkparse.c\n * Caller:  library/x509_crt.c\n *          library/x509_csr.c\n *\n * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_OID_C, MBEDTLS_PK_C\n *\n * Uncomment to enable generic public key parse functions.\n */\n#define MBEDTLS_PK_PARSE_C\n\n/**\n * \\def MBEDTLS_PK_WRITE_C\n *\n * Enable the generic public (asymmetric) key writer.\n *\n * Module:  library/pkwrite.c\n * Caller:  library/x509write.c\n *\n * Requires: MBEDTLS_ASN1_WRITE_C, MBEDTLS_OID_C, MBEDTLS_PK_C\n *\n * Uncomment to enable generic public key write functions.\n */\n#define MBEDTLS_PK_WRITE_C\n\n/**\n * \\def MBEDTLS_PKCS5_C\n *\n * Enable PKCS#5 functions.\n *\n * Module:  library/pkcs5.c\n *\n * Auto-enables: MBEDTLS_MD_C\n *\n * \\warning If using a hash that is only provided by PSA drivers, you must\n * call psa_crypto_init() before doing any PKCS5 operations.\n *\n * This module adds support for the PKCS#5 functions.\n */\n#define MBEDTLS_PKCS5_C\n\n/**\n * \\def MBEDTLS_PKCS7_C\n *\n * Enable PKCS #7 core for using PKCS #7-formatted signatures.\n * RFC Link - https://tools.ietf.org/html/rfc2315\n *\n * Module:  library/pkcs7.c\n *\n * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_OID_C, MBEDTLS_PK_PARSE_C,\n *           MBEDTLS_X509_CRT_PARSE_C MBEDTLS_X509_CRL_PARSE_C,\n *           MBEDTLS_BIGNUM_C, MBEDTLS_MD_C\n *\n * This module is required for the PKCS #7 parsing modules.\n */\n#define MBEDTLS_PKCS7_C\n\n/**\n * \\def MBEDTLS_PKCS12_C\n *\n * Enable PKCS#12 PBE functions.\n * Adds algorithms for parsing PKCS#8 encrypted private keys\n *\n * Module:  library/pkcs12.c\n * Caller:  library/pkparse.c\n *\n * Requires: MBEDTLS_ASN1_PARSE_C and either MBEDTLS_MD_C or\n *           MBEDTLS_PSA_CRYPTO_C.\n *\n * \\warning If using a hash that is only provided by PSA drivers, you must\n * call psa_crypto_init() before doing any PKCS12 operations.\n *\n * This module enables PKCS#12 functions.\n */\n#define MBEDTLS_PKCS12_C\n\n/**\n * \\def MBEDTLS_PLATFORM_C\n *\n * Enable the platform abstraction layer that allows you to re-assign\n * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit().\n *\n * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT\n * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned\n * above to be specified at runtime or compile time respectively.\n *\n * \\note This abstraction layer must be enabled on Windows (including MSYS2)\n * as other modules rely on it for a fixed snprintf implementation.\n *\n * Module:  library/platform.c\n * Caller:  Most other .c files\n *\n * This module enables abstraction of common (libc) functions.\n */\n#define MBEDTLS_PLATFORM_C\n\n/**\n * \\def MBEDTLS_POLY1305_C\n *\n * Enable the Poly1305 MAC algorithm.\n *\n * Module:  library/poly1305.c\n * Caller:  library/chachapoly.c\n */\n#define MBEDTLS_POLY1305_C\n\n/**\n * \\def MBEDTLS_PSA_CRYPTO_C\n *\n * Enable the Platform Security Architecture (PSA) cryptography API.\n *\n * \\note In multithreaded applications, you must enable #MBEDTLS_THREADING_C,\n *       unless only one thread ever calls `psa_xxx()` functions.\n *       That includes indirect calls, such as:\n *       - performing a TLS handshake if support for TLS 1.3 is enabled;\n *       - using a TLS 1.3 connection;\n *       - indirect calls from PK, X.509 or SSL functions when\n *         #MBEDTLS_USE_PSA_CRYPTO is enabled;\n *       - indirect calls to calculate a hash when #MBEDTLS_MD_C is disabled;\n *       - any other call to a function that requires calling psa_crypto_init()\n *         beforehand.\n *\n * Module:  library/psa_crypto.c\n *\n * Requires: either MBEDTLS_CTR_DRBG_C and MBEDTLS_ENTROPY_C,\n *           or MBEDTLS_HMAC_DRBG_C and MBEDTLS_ENTROPY_C,\n *           or MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG.\n * Auto-enables: MBEDTLS_CIPHER_C if any unauthenticated (ie, non-AEAD) cipher\n *               is enabled in PSA (unless it's fully accelerated, see\n *               docs/driver-only-builds.md about that).\n */\n#define MBEDTLS_PSA_CRYPTO_C\n\n/**\n * \\def MBEDTLS_PSA_CRYPTO_SE_C\n *\n * Enable dynamic secure element support in the Platform Security Architecture\n * cryptography API.\n *\n * \\deprecated This feature is deprecated. Please switch to the PSA driver\n *             interface.\n *\n * \\warning    This feature is not thread-safe, and should not be used in a\n *             multi-threaded environment.\n *\n * Module:  library/psa_crypto_se.c\n *\n * Requires: MBEDTLS_PSA_CRYPTO_C, MBEDTLS_PSA_CRYPTO_STORAGE_C\n *\n */\n//#define MBEDTLS_PSA_CRYPTO_SE_C\n\n/**\n * \\def MBEDTLS_PSA_CRYPTO_STORAGE_C\n *\n * Enable the Platform Security Architecture persistent key storage.\n *\n * Module:  library/psa_crypto_storage.c\n *\n * Requires: MBEDTLS_PSA_CRYPTO_C,\n *           either MBEDTLS_PSA_ITS_FILE_C or a native implementation of\n *           the PSA ITS interface\n */\n#define MBEDTLS_PSA_CRYPTO_STORAGE_C\n\n/**\n * \\def MBEDTLS_PSA_ITS_FILE_C\n *\n * Enable the emulation of the Platform Security Architecture\n * Internal Trusted Storage (PSA ITS) over files.\n *\n * Module:  library/psa_its_file.c\n *\n * Requires: MBEDTLS_FS_IO\n */\n#define MBEDTLS_PSA_ITS_FILE_C\n\n/**\n * \\def MBEDTLS_PSA_STATIC_KEY_SLOTS\n *\n * Statically preallocate memory to store keys' material in PSA instead\n * of allocating it dynamically when required. This allows builds without a\n * heap, if none of the enabled cryptographic implementations or other features\n * require it.\n * This feature affects both volatile and persistent keys which means that\n * it's not possible to persistently store a key which is larger than\n * #MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE.\n *\n * \\note This feature comes with a (potentially) higher RAM usage since:\n *       - All the key slots are allocated no matter if they are used or not.\n *       - Each key buffer's length is #MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE bytes.\n *\n * Requires: MBEDTLS_PSA_CRYPTO_C\n *\n */\n//#define MBEDTLS_PSA_STATIC_KEY_SLOTS\n\n/**\n * \\def MBEDTLS_RIPEMD160_C\n *\n * Enable the RIPEMD-160 hash algorithm.\n *\n * Module:  library/ripemd160.c\n * Caller:  library/md.c\n *\n */\n#define MBEDTLS_RIPEMD160_C\n\n/**\n * \\def MBEDTLS_RSA_C\n *\n * Enable the RSA public-key cryptosystem.\n *\n * Module:  library/rsa.c\n *          library/rsa_alt_helpers.c\n * Caller:  library/pk.c\n *          library/psa_crypto.c\n *          library/ssl_tls.c\n *          library/ssl*_client.c\n *          library/ssl*_server.c\n *\n * This module is used by the following key exchanges:\n *      RSA, DHE-RSA, ECDHE-RSA, RSA-PSK\n *\n * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C\n */\n#define MBEDTLS_RSA_C\n\n/**\n * \\def MBEDTLS_SHA1_C\n *\n * Enable the SHA1 cryptographic hash algorithm.\n *\n * Module:  library/sha1.c\n * Caller:  library/md.c\n *          library/psa_crypto_hash.c\n *\n * This module is required for TLS 1.2 depending on the handshake parameters,\n * and for SHA1-signed certificates.\n *\n * \\warning   SHA-1 is considered a weak message digest and its use constitutes\n *            a security risk. If possible, we recommend avoiding dependencies\n *            on it, and considering stronger message digests instead.\n *\n */\n#define MBEDTLS_SHA1_C\n\n/**\n * \\def MBEDTLS_SHA224_C\n *\n * Enable the SHA-224 cryptographic hash algorithm.\n *\n * Module:  library/sha256.c\n * Caller:  library/md.c\n *          library/ssl_cookie.c\n *\n * This module adds support for SHA-224.\n */\n#define MBEDTLS_SHA224_C\n\n/**\n * \\def MBEDTLS_SHA256_C\n *\n * Enable the SHA-256 cryptographic hash algorithm.\n *\n * Module:  library/sha256.c\n * Caller:  library/entropy.c\n *          library/md.c\n *          library/ssl_tls.c\n *          library/ssl*_client.c\n *          library/ssl*_server.c\n *\n * This module adds support for SHA-256.\n * This module is required for the SSL/TLS 1.2 PRF function.\n */\n#define MBEDTLS_SHA256_C\n\n/**\n * \\def MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT\n *\n * Enable acceleration of the SHA-256 and SHA-224 cryptographic hash algorithms\n * with the ARMv8 cryptographic extensions if they are available at runtime.\n * If not, the library will fall back to the C implementation.\n *\n * \\note If MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT is defined when building\n * for a non-Armv8-A build it will be silently ignored.\n *\n * \\note    Minimum compiler versions for this feature are Clang 4.0,\n * armclang 6.6 or GCC 6.0.\n *\n * \\note \\c CFLAGS must be set to a minimum of \\c -march=armv8-a+crypto for\n * armclang <= 6.9\n *\n * \\note This was previously known as MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT.\n * That name is deprecated, but may still be used as an alternative form for this\n * option.\n *\n * \\warning MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT cannot be defined at the\n * same time as MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY.\n *\n * Requires: MBEDTLS_SHA256_C.\n *\n * Module:  library/sha256.c\n *\n * Uncomment to have the library check for the Armv8-A SHA-256 crypto extensions\n * and use them if available.\n */\n//#define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT\n\n/**\n * \\def MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT\n *\n * \\deprecated This is now known as MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT.\n * This name is now deprecated, but may still be used as an alternative form for\n * this option.\n */\n//#define MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT\n\n/**\n * \\def MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY\n *\n * Enable acceleration of the SHA-256 and SHA-224 cryptographic hash algorithms\n * with the ARMv8 cryptographic extensions, which must be available at runtime\n * or else an illegal instruction fault will occur.\n *\n * \\note This allows builds with a smaller code size than with\n * MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT\n *\n * \\note    Minimum compiler versions for this feature are Clang 4.0,\n * armclang 6.6 or GCC 6.0.\n *\n * \\note \\c CFLAGS must be set to a minimum of \\c -march=armv8-a+crypto for\n * armclang <= 6.9\n *\n * \\note This was previously known as MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY.\n * That name is deprecated, but may still be used as an alternative form for this\n * option.\n *\n * \\warning MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY cannot be defined at the same\n * time as MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT.\n *\n * Requires: MBEDTLS_SHA256_C.\n *\n * Module:  library/sha256.c\n *\n * Uncomment to have the library use the Armv8-A SHA-256 crypto extensions\n * unconditionally.\n */\n//#define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY\n\n/**\n * \\def MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY\n *\n * \\deprecated This is now known as MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY.\n * This name is now deprecated, but may still be used as an alternative form for\n * this option.\n */\n//#define MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY\n\n/**\n * \\def MBEDTLS_SHA384_C\n *\n * Enable the SHA-384 cryptographic hash algorithm.\n *\n * Module:  library/sha512.c\n * Caller:  library/md.c\n *          library/psa_crypto_hash.c\n *          library/ssl_tls.c\n *          library/ssl*_client.c\n *          library/ssl*_server.c\n *\n * Comment to disable SHA-384\n */\n#define MBEDTLS_SHA384_C\n\n/**\n * \\def MBEDTLS_SHA512_C\n *\n * Enable SHA-512 cryptographic hash algorithms.\n *\n * Module:  library/sha512.c\n * Caller:  library/entropy.c\n *          library/md.c\n *          library/ssl_tls.c\n *          library/ssl_cookie.c\n *\n * This module adds support for SHA-512.\n */\n#define MBEDTLS_SHA512_C\n\n/**\n * \\def MBEDTLS_SHA3_C\n *\n * Enable the SHA3 cryptographic hash algorithm.\n *\n * Module:  library/sha3.c\n *\n * This module adds support for SHA3.\n */\n#define MBEDTLS_SHA3_C\n\n/**\n * \\def MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT\n *\n * Enable acceleration of the SHA-512 and SHA-384 cryptographic hash algorithms\n * with the ARMv8 cryptographic extensions if they are available at runtime.\n * If not, the library will fall back to the C implementation.\n *\n * \\note If MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT is defined when building\n * for a non-Aarch64 build it will be silently ignored.\n *\n * \\note    Minimum compiler versions for this feature are Clang 7.0,\n * armclang 6.9 or GCC 8.0.\n *\n * \\note \\c CFLAGS must be set to a minimum of \\c -march=armv8.2-a+sha3 for\n * armclang 6.9\n *\n * \\warning MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT cannot be defined at the\n * same time as MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY.\n *\n * Requires: MBEDTLS_SHA512_C.\n *\n * Module:  library/sha512.c\n *\n * Uncomment to have the library check for the A64 SHA-512 crypto extensions\n * and use them if available.\n */\n//#define MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT\n\n/**\n * \\def MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY\n *\n * Enable acceleration of the SHA-512 and SHA-384 cryptographic hash algorithms\n * with the ARMv8 cryptographic extensions, which must be available at runtime\n * or else an illegal instruction fault will occur.\n *\n * \\note This allows builds with a smaller code size than with\n * MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT\n *\n * \\note    Minimum compiler versions for this feature are Clang 7.0,\n * armclang 6.9 or GCC 8.0.\n *\n * \\note \\c CFLAGS must be set to a minimum of \\c -march=armv8.2-a+sha3 for\n * armclang 6.9\n *\n * \\warning MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY cannot be defined at the same\n * time as MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT.\n *\n * Requires: MBEDTLS_SHA512_C.\n *\n * Module:  library/sha512.c\n *\n * Uncomment to have the library use the A64 SHA-512 crypto extensions\n * unconditionally.\n */\n//#define MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY\n\n/**\n * \\def MBEDTLS_SSL_CACHE_C\n *\n * Enable simple SSL cache implementation.\n *\n * Module:  library/ssl_cache.c\n * Caller:\n *\n * Requires: MBEDTLS_SSL_CACHE_C\n */\n#define MBEDTLS_SSL_CACHE_C\n\n/**\n * \\def MBEDTLS_SSL_COOKIE_C\n *\n * Enable basic implementation of DTLS cookies for hello verification.\n *\n * Module:  library/ssl_cookie.c\n * Caller:\n */\n#define MBEDTLS_SSL_COOKIE_C\n\n/**\n * \\def MBEDTLS_SSL_TICKET_C\n *\n * Enable an implementation of TLS server-side callbacks for session tickets.\n *\n * Module:  library/ssl_ticket.c\n * Caller:\n *\n * Requires: (MBEDTLS_CIPHER_C || MBEDTLS_USE_PSA_CRYPTO) &&\n *           (MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C)\n */\n#define MBEDTLS_SSL_TICKET_C\n\n/**\n * \\def MBEDTLS_SSL_CLI_C\n *\n * Enable the SSL/TLS client code.\n *\n * Module:  library/ssl*_client.c\n * Caller:\n *\n * Requires: MBEDTLS_SSL_TLS_C\n *\n * This module is required for SSL/TLS client support.\n */\n#define MBEDTLS_SSL_CLI_C\n\n/**\n * \\def MBEDTLS_SSL_SRV_C\n *\n * Enable the SSL/TLS server code.\n *\n * Module:  library/ssl*_server.c\n * Caller:\n *\n * Requires: MBEDTLS_SSL_TLS_C\n *\n * This module is required for SSL/TLS server support.\n */\n#define MBEDTLS_SSL_SRV_C\n\n/**\n * \\def MBEDTLS_SSL_TLS_C\n *\n * Enable the generic SSL/TLS code.\n *\n * Module:  library/ssl_tls.c\n * Caller:  library/ssl*_client.c\n *          library/ssl*_server.c\n *\n * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C\n *           and at least one of the MBEDTLS_SSL_PROTO_XXX defines\n *\n * This module is required for SSL/TLS.\n */\n#define MBEDTLS_SSL_TLS_C\n\n/**\n * \\def MBEDTLS_THREADING_C\n *\n * Enable the threading abstraction layer.\n *\n * Traditionally, Mbed TLS assumes it is used in a non-threaded environment or\n * that contexts are not shared between threads. If you do intend to use contexts\n * between threads, you will need to enable this layer to prevent race\n * conditions.\n *\n * The PSA subsystem has an implicit shared context. Therefore, you must\n * enable this option if more than one thread may use any part of\n * Mbed TLS that is implemented on top of the PSA subsystem.\n *\n * You must enable this option in multithreaded applications where more than\n * one thread performs any of the following operations:\n *\n * - Any call to a PSA function (`psa_xxx()`).\n * - Any call to a TLS, X.509 or PK function (`mbedtls_ssl_xxx()`,\n *   `mbedtls_x509_xxx()`, `mbedtls_pkcs7_xxx()`, `mbedtls_pk_xxx()`)\n *   if `MBEDTLS_USE_PSA_CRYPTO` is enabled (regardless of whether individual\n *   TLS, X.509 or PK contexts are shared between threads).\n * - A TLS 1.3 connection, regardless of the compile-time configuration.\n * - Any library feature that calculates a hash, if `MBEDTLS_MD_C` is disabled.\n *   As an exception, algorithm-specific low-level modules do not require\n *   threading protection unless the contexts are shared between threads.\n * - Any library feature that performs symmetric encryption or decryption,\n *   if `MBEDTLS_CIPHER_C` is disabled.\n *   As an exception, algorithm-specific low-level modules do not require\n *   threading protection unless the contexts are shared between threads.\n * - Any use of a cryptographic context if the same context is used in\n *   multiple threads.\n * - Any call to a function where the documentation specifies that\n *   psa_crypto_init() must be called prior to that function.\n *\n * See also our Knowledge Base article about threading:\n * https://mbed-tls.readthedocs.io/en/latest/kb/development/thread-safety-and-multi-threading\n *\n * Module:  library/threading.c\n *\n * This allows different threading implementations (self-implemented or\n * provided).\n *\n * You will have to enable either MBEDTLS_THREADING_ALT or\n * MBEDTLS_THREADING_PTHREAD.\n *\n * Enable this layer to allow use of mutexes within Mbed TLS\n */\n//#define MBEDTLS_THREADING_C\n\n/**\n * \\def MBEDTLS_TIMING_C\n *\n * Enable the semi-portable timing interface.\n *\n * \\note The provided implementation only works on POSIX/Unix (including Linux,\n * BSD and OS X) and Windows. On other platforms, you can either disable that\n * module and provide your own implementations of the callbacks needed by\n * \\c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide\n * your own implementation of the whole module by setting\n * \\c MBEDTLS_TIMING_ALT in the current file.\n *\n * \\note The timing module will include time.h on suitable platforms\n *       regardless of the setting of MBEDTLS_HAVE_TIME, unless\n *       MBEDTLS_TIMING_ALT is used. See timing.c for more information.\n *\n * \\note See also our Knowledge Base article about porting to a new\n * environment:\n * https://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS\n *\n * Module:  library/timing.c\n */\n#define MBEDTLS_TIMING_C\n\n/**\n * \\def MBEDTLS_VERSION_C\n *\n * Enable run-time version information.\n *\n * Module:  library/version.c\n *\n * This module provides run-time version information.\n */\n#define MBEDTLS_VERSION_C\n\n/**\n * \\def MBEDTLS_X509_USE_C\n *\n * Enable X.509 core for using certificates.\n *\n * Module:  library/x509.c\n * Caller:  library/x509_crl.c\n *          library/x509_crt.c\n *          library/x509_csr.c\n *\n * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_PARSE_C,\n *           (MBEDTLS_MD_C or MBEDTLS_USE_PSA_CRYPTO)\n *\n * \\warning If building with MBEDTLS_USE_PSA_CRYPTO, you must call\n * psa_crypto_init() before doing any X.509 operation.\n *\n * This module is required for the X.509 parsing modules.\n */\n#define MBEDTLS_X509_USE_C\n\n/**\n * \\def MBEDTLS_X509_CRT_PARSE_C\n *\n * Enable X.509 certificate parsing.\n *\n * Module:  library/x509_crt.c\n * Caller:  library/ssl_tls.c\n *          library/ssl*_client.c\n *          library/ssl*_server.c\n *\n * Requires: MBEDTLS_X509_USE_C\n *\n * This module is required for X.509 certificate parsing.\n */\n#define MBEDTLS_X509_CRT_PARSE_C\n\n/**\n * \\def MBEDTLS_X509_CRL_PARSE_C\n *\n * Enable X.509 CRL parsing.\n *\n * Module:  library/x509_crl.c\n * Caller:  library/x509_crt.c\n *\n * Requires: MBEDTLS_X509_USE_C\n *\n * This module is required for X.509 CRL parsing.\n */\n#define MBEDTLS_X509_CRL_PARSE_C\n\n/**\n * \\def MBEDTLS_X509_CSR_PARSE_C\n *\n * Enable X.509 Certificate Signing Request (CSR) parsing.\n *\n * Module:  library/x509_csr.c\n * Caller:  library/x509_crt_write.c\n *\n * Requires: MBEDTLS_X509_USE_C\n *\n * This module is used for reading X.509 certificate request.\n */\n#define MBEDTLS_X509_CSR_PARSE_C\n\n/**\n * \\def MBEDTLS_X509_CREATE_C\n *\n * Enable X.509 core for creating certificates.\n *\n * Module:  library/x509_create.c\n *\n * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_PARSE_C,\n *           (MBEDTLS_MD_C or MBEDTLS_USE_PSA_CRYPTO)\n *\n * \\warning If building with MBEDTLS_USE_PSA_CRYPTO, you must call\n * psa_crypto_init() before doing any X.509 create operation.\n *\n * This module is the basis for creating X.509 certificates and CSRs.\n */\n#define MBEDTLS_X509_CREATE_C\n\n/**\n * \\def MBEDTLS_X509_CRT_WRITE_C\n *\n * Enable creating X.509 certificates.\n *\n * Module:  library/x509_crt_write.c\n *\n * Requires: MBEDTLS_X509_CREATE_C\n *\n * This module is required for X.509 certificate creation.\n */\n#define MBEDTLS_X509_CRT_WRITE_C\n\n/**\n * \\def MBEDTLS_X509_CSR_WRITE_C\n *\n * Enable creating X.509 Certificate Signing Requests (CSR).\n *\n * Module:  library/x509_csr_write.c\n *\n * Requires: MBEDTLS_X509_CREATE_C\n *\n * This module is required for X.509 certificate request writing.\n */\n#define MBEDTLS_X509_CSR_WRITE_C\n\n/** \\} name SECTION: Mbed TLS modules */\n\n/**\n * \\name SECTION: General configuration options\n *\n * This section contains Mbed TLS build settings that are not associated\n * with a particular module.\n *\n * \\{\n */\n\n/**\n * \\def MBEDTLS_CONFIG_FILE\n *\n * If defined, this is a header which will be included instead of\n * `\"mbedtls/mbedtls_config.h\"`.\n * This header file specifies the compile-time configuration of Mbed TLS.\n * Unlike other configuration options, this one must be defined on the\n * compiler command line: a definition in `mbedtls_config.h` would have\n * no effect.\n *\n * This macro is expanded after an <tt>\\#include</tt> directive. This is a popular but\n * non-standard feature of the C language, so this feature is only available\n * with compilers that perform macro expansion on an <tt>\\#include</tt> line.\n *\n * The value of this symbol is typically a path in double quotes, either\n * absolute or relative to a directory on the include search path.\n */\n//#define MBEDTLS_CONFIG_FILE \"mbedtls/mbedtls_config.h\"\n\n/**\n * \\def MBEDTLS_USER_CONFIG_FILE\n *\n * If defined, this is a header which will be included after\n * `\"mbedtls/mbedtls_config.h\"` or #MBEDTLS_CONFIG_FILE.\n * This allows you to modify the default configuration, including the ability\n * to undefine options that are enabled by default.\n *\n * This macro is expanded after an <tt>\\#include</tt> directive. This is a popular but\n * non-standard feature of the C language, so this feature is only available\n * with compilers that perform macro expansion on an <tt>\\#include</tt> line.\n *\n * The value of this symbol is typically a path in double quotes, either\n * absolute or relative to a directory on the include search path.\n */\n//#define MBEDTLS_USER_CONFIG_FILE \"/dev/null\"\n\n/**\n * \\def MBEDTLS_PSA_CRYPTO_CONFIG_FILE\n *\n * If defined, this is a header which will be included instead of\n * `\"psa/crypto_config.h\"`.\n * This header file specifies which cryptographic mechanisms are available\n * through the PSA API when #MBEDTLS_PSA_CRYPTO_CONFIG is enabled, and\n * is not used when #MBEDTLS_PSA_CRYPTO_CONFIG is disabled.\n *\n * This macro is expanded after an <tt>\\#include</tt> directive. This is a popular but\n * non-standard feature of the C language, so this feature is only available\n * with compilers that perform macro expansion on an <tt>\\#include</tt> line.\n *\n * The value of this symbol is typically a path in double quotes, either\n * absolute or relative to a directory on the include search path.\n */\n//#define MBEDTLS_PSA_CRYPTO_CONFIG_FILE \"psa/crypto_config.h\"\n\n/**\n * \\def MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE\n *\n * If defined, this is a header which will be included after\n * `\"psa/crypto_config.h\"` or #MBEDTLS_PSA_CRYPTO_CONFIG_FILE.\n * This allows you to modify the default configuration, including the ability\n * to undefine options that are enabled by default.\n *\n * This macro is expanded after an <tt>\\#include</tt> directive. This is a popular but\n * non-standard feature of the C language, so this feature is only available\n * with compilers that perform macro expansion on an <tt>\\#include</tt> line.\n *\n * The value of this symbol is typically a path in double quotes, either\n * absolute or relative to a directory on the include search path.\n */\n//#define MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE \"/dev/null\"\n\n/**\n * \\def MBEDTLS_PSA_CRYPTO_PLATFORM_FILE\n *\n * If defined, this is a header which will be included instead of\n * `\"psa/crypto_platform.h\"`. This file should declare the same identifiers\n * as the one in Mbed TLS, but with definitions adapted to the platform on\n * which the library code will run.\n *\n * \\note The required content of this header can vary from one version of\n *       Mbed TLS to the next. Integrators who provide an alternative file\n *       should review the changes in the original file whenever they\n *       upgrade Mbed TLS.\n *\n * This macro is expanded after an <tt>\\#include</tt> directive. This is a popular but\n * non-standard feature of the C language, so this feature is only available\n * with compilers that perform macro expansion on an <tt>\\#include</tt> line.\n *\n * The value of this symbol is typically a path in double quotes, either\n * absolute or relative to a directory on the include search path.\n */\n//#define MBEDTLS_PSA_CRYPTO_PLATFORM_FILE \"psa/crypto_platform_alt.h\"\n\n/**\n * \\def MBEDTLS_PSA_CRYPTO_STRUCT_FILE\n *\n * If defined, this is a header which will be included instead of\n * `\"psa/crypto_struct.h\"`. This file should declare the same identifiers\n * as the one in Mbed TLS, but with definitions adapted to the environment\n * in which the library code will run. The typical use for this feature\n * is to provide alternative type definitions on the client side in\n * client-server integrations of PSA crypto, where operation structures\n * contain handles instead of cryptographic data.\n *\n * \\note The required content of this header can vary from one version of\n *       Mbed TLS to the next. Integrators who provide an alternative file\n *       should review the changes in the original file whenever they\n *       upgrade Mbed TLS.\n *\n * This macro is expanded after an <tt>\\#include</tt> directive. This is a popular but\n * non-standard feature of the C language, so this feature is only available\n * with compilers that perform macro expansion on an <tt>\\#include</tt> line.\n *\n * The value of this symbol is typically a path in double quotes, either\n * absolute or relative to a directory on the include search path.\n */\n//#define MBEDTLS_PSA_CRYPTO_STRUCT_FILE \"psa/crypto_struct_alt.h\"\n\n/** \\} name SECTION: General configuration options */\n\n/**\n * \\name SECTION: Module configuration options\n *\n * This section allows for the setting of module specific sizes and\n * configuration options. The default values are already present in the\n * relevant header files and should suffice for the regular use cases.\n *\n * Our advice is to enable options and change their values here\n * only if you have a good reason and know the consequences.\n * \\{\n */\n/* The Doxygen documentation here is used when a user comments out a\n * setting and runs doxygen themselves. On the other hand, when we typeset\n * the full documentation including disabled settings, the documentation\n * in specific modules' header files is used if present. When editing this\n * file, make sure that each option is documented in exactly one place,\n * plus optionally a same-line Doxygen comment here if there is a Doxygen\n * comment in the specific module. */\n\n/* MPI / BIGNUM options */\n//#define MBEDTLS_MPI_WINDOW_SIZE            2 /**< Maximum window size used. */\n//#define MBEDTLS_MPI_MAX_SIZE            1024 /**< Maximum number of bytes for usable MPIs. */\n\n/* CTR_DRBG options */\n//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN               48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */\n//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL        10000 /**< Interval before reseed is performed by default */\n//#define MBEDTLS_CTR_DRBG_MAX_INPUT                256 /**< Maximum number of additional input bytes */\n//#define MBEDTLS_CTR_DRBG_MAX_REQUEST             1024 /**< Maximum number of requested bytes per call */\n//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT           384 /**< Maximum size of (re)seed buffer */\n\n/* HMAC_DRBG options */\n//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL   10000 /**< Interval before reseed is performed by default */\n//#define MBEDTLS_HMAC_DRBG_MAX_INPUT           256 /**< Maximum number of additional input bytes */\n//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST        1024 /**< Maximum number of requested bytes per call */\n//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT      384 /**< Maximum size of (re)seed buffer */\n\n/* ECP options */\n//#define MBEDTLS_ECP_WINDOW_SIZE            4 /**< Maximum window size used */\n//#define MBEDTLS_ECP_FIXED_POINT_OPTIM      1 /**< Enable fixed-point speed-up */\n\n/* Entropy options */\n//#define MBEDTLS_ENTROPY_MAX_SOURCES                20 /**< Maximum number of sources supported */\n//#define MBEDTLS_ENTROPY_MAX_GATHER                128 /**< Maximum amount requested from entropy sources */\n//#define MBEDTLS_ENTROPY_MIN_HARDWARE               32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */\n\n/* Memory buffer allocator options */\n//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE      4 /**< Align on multiples of this value */\n\n/* Platform options */\n//#define MBEDTLS_PLATFORM_STD_MEM_HDR   <stdlib.h> /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */\n\n/** \\def MBEDTLS_PLATFORM_STD_CALLOC\n *\n * Default allocator to use, can be undefined.\n * It must initialize the allocated buffer memory to zeroes.\n * The size of the buffer is the product of the two parameters.\n * The calloc function returns either a null pointer or a pointer to the allocated space.\n * If the product is 0, the function may either return NULL or a valid pointer to an array of size 0 which is a valid input to the deallocation function.\n * An uninitialized #MBEDTLS_PLATFORM_STD_CALLOC always fails, returning a null pointer.\n * See the description of #MBEDTLS_PLATFORM_MEMORY for more details.\n * The corresponding deallocation function is #MBEDTLS_PLATFORM_STD_FREE.\n */\n//#define MBEDTLS_PLATFORM_STD_CALLOC        calloc\n\n/** \\def MBEDTLS_PLATFORM_STD_FREE\n *\n * Default free to use, can be undefined.\n * NULL is a valid parameter, and the function must do nothing.\n * A non-null parameter will always be a pointer previously returned by #MBEDTLS_PLATFORM_STD_CALLOC and not yet freed.\n * An uninitialized #MBEDTLS_PLATFORM_STD_FREE does not do anything.\n * See the description of #MBEDTLS_PLATFORM_MEMORY for more details (same principles as for MBEDTLS_PLATFORM_STD_CALLOC apply).\n */\n//#define MBEDTLS_PLATFORM_STD_FREE            free\n//#define MBEDTLS_PLATFORM_STD_SETBUF      setbuf /**< Default setbuf to use, can be undefined */\n//#define MBEDTLS_PLATFORM_STD_EXIT            exit /**< Default exit to use, can be undefined */\n//#define MBEDTLS_PLATFORM_STD_TIME            time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */\n//#define MBEDTLS_PLATFORM_STD_FPRINTF      fprintf /**< Default fprintf to use, can be undefined */\n//#define MBEDTLS_PLATFORM_STD_PRINTF        printf /**< Default printf to use, can be undefined */\n/* Note: your snprintf must correctly zero-terminate the buffer! */\n//#define MBEDTLS_PLATFORM_STD_SNPRINTF    snprintf /**< Default snprintf to use, can be undefined */\n//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS       0 /**< Default exit value to use, can be undefined */\n//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE       1 /**< Default exit value to use, can be undefined */\n//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ   mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */\n//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE  mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */\n//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE  \"seedfile\" /**< Seed file to read/write with default implementation */\n\n/* To use the following function macros, MBEDTLS_PLATFORM_C must be enabled. */\n/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */\n//#define MBEDTLS_PLATFORM_CALLOC_MACRO        calloc /**< Default allocator macro to use, can be undefined. See MBEDTLS_PLATFORM_STD_CALLOC for requirements. */\n//#define MBEDTLS_PLATFORM_FREE_MACRO            free /**< Default free macro to use, can be undefined. See MBEDTLS_PLATFORM_STD_FREE for requirements. */\n//#define MBEDTLS_PLATFORM_EXIT_MACRO            exit /**< Default exit macro to use, can be undefined */\n//#define MBEDTLS_PLATFORM_SETBUF_MACRO      setbuf /**< Default setbuf macro to use, can be undefined */\n//#define MBEDTLS_PLATFORM_TIME_MACRO            time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */\n//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO       time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */\n//#define MBEDTLS_PLATFORM_FPRINTF_MACRO      fprintf /**< Default fprintf macro to use, can be undefined */\n//#define MBEDTLS_PLATFORM_PRINTF_MACRO        printf /**< Default printf macro to use, can be undefined */\n/* Note: your snprintf must correctly zero-terminate the buffer! */\n//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO    snprintf /**< Default snprintf macro to use, can be undefined */\n//#define MBEDTLS_PLATFORM_VSNPRINTF_MACRO    vsnprintf /**< Default vsnprintf macro to use, can be undefined */\n//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO   mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */\n//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO  mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */\n//#define MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO   int64_t //#define MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO   int64_t /**< Default milliseconds time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled. It must be signed, and at least 64 bits. If it is changed from the default, MBEDTLS_PRINTF_MS_TIME must be updated to match.*/\n//#define MBEDTLS_PRINTF_MS_TIME    PRId64 /**< Default fmt for printf. That's avoid compiler warning if mbedtls_ms_time_t is redefined */\n\n/** \\def MBEDTLS_CHECK_RETURN\n *\n * This macro is used at the beginning of the declaration of a function\n * to indicate that its return value should be checked. It should\n * instruct the compiler to emit a warning or an error if the function\n * is called without checking its return value.\n *\n * There is a default implementation for popular compilers in platform_util.h.\n * You can override the default implementation by defining your own here.\n *\n * If the implementation here is empty, this will effectively disable the\n * checking of functions' return values.\n */\n//#define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__))\n\n/** \\def MBEDTLS_IGNORE_RETURN\n *\n * This macro requires one argument, which should be a C function call.\n * If that function call would cause a #MBEDTLS_CHECK_RETURN warning, this\n * warning is suppressed.\n */\n//#define MBEDTLS_IGNORE_RETURN( result ) ((void) !(result))\n\n/* PSA options */\n/**\n * Use HMAC_DRBG with the specified hash algorithm for HMAC_DRBG for the\n * PSA crypto subsystem.\n *\n * If this option is unset, the library chooses a hash (currently between\n * #MBEDTLS_MD_SHA512 and #MBEDTLS_MD_SHA256) based on availability and\n * unspecified heuristics.\n *\n * \\note The PSA crypto subsystem uses the first available mechanism amongst\n *       the following:\n *       - #MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG if enabled;\n *       - Entropy from #MBEDTLS_ENTROPY_C plus CTR_DRBG with AES\n *         if #MBEDTLS_CTR_DRBG_C is enabled;\n *       - Entropy from #MBEDTLS_ENTROPY_C plus HMAC_DRBG.\n *\n *       A future version may reevaluate the prioritization of DRBG mechanisms.\n */\n//#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256\n\n/** \\def MBEDTLS_PSA_KEY_SLOT_COUNT\n *\n * When #MBEDTLS_PSA_KEY_STORE_DYNAMIC is disabled,\n * the maximum amount of PSA keys simultaneously in memory. This counts all\n * volatile keys, plus loaded persistent keys.\n *\n * When #MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled,\n * the maximum number of loaded persistent keys.\n *\n * Currently, persistent keys do not need to be loaded all the time while\n * a multipart operation is in progress, only while the operation is being\n * set up. This may change in future versions of the library.\n *\n * Currently, the library traverses of the whole table on each access to a\n * persistent key. Therefore large values may cause poor performance.\n *\n * This option has no effect when #MBEDTLS_PSA_CRYPTO_C is disabled.\n */\n//#define MBEDTLS_PSA_KEY_SLOT_COUNT 32\n\n/**\n * \\def MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE\n *\n * Define the size (in bytes) of each static key buffer when\n * #MBEDTLS_PSA_STATIC_KEY_SLOTS is set. If not\n * explicitly defined then it's automatically guessed from available PSA keys\n * enabled in the build through PSA_WANT_xxx symbols.\n * If required by the application this parameter can be set to higher values\n * in order to store larger objects (ex: raw keys), but please note that this\n * will increase RAM usage.\n */\n//#define MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE       256\n\n/* RSA OPTIONS */\n//#define MBEDTLS_RSA_GEN_KEY_MIN_BITS            1024 /**<  Minimum RSA key size that can be generated in bits (Minimum possible value is 128 bits) */\n\n/* SSL Cache options */\n//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT       86400 /**< 1 day  */\n//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES      50 /**< Maximum entries in cache */\n\n/* SSL options */\n\n/** \\def MBEDTLS_SSL_IN_CONTENT_LEN\n *\n * Maximum length (in bytes) of incoming plaintext fragments.\n *\n * This determines the size of the incoming TLS I/O buffer in such a way\n * that it is capable of holding the specified amount of plaintext data,\n * regardless of the protection mechanism used.\n *\n * \\note When using a value less than the default of 16KB on the client, it is\n *       recommended to use the Maximum Fragment Length (MFL) extension to\n *       inform the server about this limitation. On the server, there\n *       is no supported, standardized way of informing the client about\n *       restriction on the maximum size of incoming messages, and unless\n *       the limitation has been communicated by other means, it is recommended\n *       to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN\n *       while keeping the default value of 16KB for the incoming buffer.\n *\n * Uncomment to set the maximum plaintext size of the incoming I/O buffer.\n */\n//#define MBEDTLS_SSL_IN_CONTENT_LEN              16384\n\n/** \\def MBEDTLS_SSL_CID_IN_LEN_MAX\n *\n * The maximum length of CIDs used for incoming DTLS messages.\n *\n */\n//#define MBEDTLS_SSL_CID_IN_LEN_MAX 32\n\n/** \\def MBEDTLS_SSL_CID_OUT_LEN_MAX\n *\n * The maximum length of CIDs used for outgoing DTLS messages.\n *\n */\n//#define MBEDTLS_SSL_CID_OUT_LEN_MAX 32\n\n/** \\def MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY\n *\n * This option controls the use of record plaintext padding\n * in TLS 1.3 and when using the Connection ID extension in DTLS 1.2.\n *\n * The padding will always be chosen so that the length of the\n * padded plaintext is a multiple of the value of this option.\n *\n * Note: A value of \\c 1 means that no padding will be used\n *       for outgoing records.\n *\n * Note: On systems lacking division instructions,\n *       a power of two should be preferred.\n */\n//#define MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 16\n\n/** \\def MBEDTLS_SSL_OUT_CONTENT_LEN\n *\n * Maximum length (in bytes) of outgoing plaintext fragments.\n *\n * This determines the size of the outgoing TLS I/O buffer in such a way\n * that it is capable of holding the specified amount of plaintext data,\n * regardless of the protection mechanism used.\n *\n * It is possible to save RAM by setting a smaller outward buffer, while keeping\n * the default inward 16384 byte buffer to conform to the TLS specification.\n *\n * The minimum required outward buffer size is determined by the handshake\n * protocol's usage. Handshaking will fail if the outward buffer is too small.\n * The specific size requirement depends on the configured ciphers and any\n * certificate data which is sent during the handshake.\n *\n * Uncomment to set the maximum plaintext size of the outgoing I/O buffer.\n */\n//#define MBEDTLS_SSL_OUT_CONTENT_LEN             16384\n\n/** \\def MBEDTLS_SSL_DTLS_MAX_BUFFERING\n *\n * Maximum number of heap-allocated bytes for the purpose of\n * DTLS handshake message reassembly and future message buffering.\n *\n * This should be at least 9/8 * MBEDTLS_SSL_IN_CONTENT_LEN\n * to account for a reassembled handshake message of maximum size,\n * together with its reassembly bitmap.\n *\n * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default)\n * should be sufficient for all practical situations as it allows\n * to reassembly a large handshake message (such as a certificate)\n * while buffering multiple smaller handshake messages.\n *\n */\n//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING             32768\n\n//#define MBEDTLS_PSK_MAX_LEN               32 /**< Max size of TLS pre-shared keys, in bytes (default 256 or 384 bits) */\n//#define MBEDTLS_SSL_COOKIE_TIMEOUT        60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */\n\n/**\n * Complete list of ciphersuites to use, in order of preference.\n *\n * \\warning No dependency checking is done on that field! This option can only\n * be used to restrict the set of available ciphersuites. It is your\n * responsibility to make sure the needed modules are active.\n *\n * Use this to save a few hundred bytes of ROM (default ordering of all\n * available ciphersuites) and a few to a few hundred bytes of RAM.\n *\n * The value below is only an example, not the default.\n */\n//#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\n\n/**\n * \\def MBEDTLS_SSL_MAX_EARLY_DATA_SIZE\n *\n * The default maximum amount of 0-RTT data. See the documentation of\n * \\c mbedtls_ssl_conf_max_early_data_size() for more information.\n *\n * It must be positive and smaller than UINT32_MAX.\n *\n * If MBEDTLS_SSL_EARLY_DATA is not defined, this default value does not\n * have any impact on the build.\n */\n//#define MBEDTLS_SSL_MAX_EARLY_DATA_SIZE        1024\n\n/**\n * \\def MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE\n *\n * Maximum allowed ticket age difference in milliseconds tolerated between\n * server and client. Default value is 6000. This is not used in TLS 1.2.\n *\n * - The client ticket age is the time difference between the time when the\n *   client proposes to the server to use the ticket and the time the client\n *   received the ticket from the server.\n * - The server ticket age is the time difference between the time when the\n *   server receives a proposition from the client to use the ticket and the\n *   time when the ticket was created by the server.\n *\n * The ages might be different due to the client and server clocks not running\n * at the same pace. The typical accuracy of an RTC crystal is ±100 to ±20 parts\n * per million (360 to 72 milliseconds per hour). Default tolerance window is\n * 6s, thus in the worst case clients and servers must sync up their system time\n * every 6000/360/2~=8 hours.\n *\n * See section 8.3 of the TLS 1.3 specification(RFC 8446) for more information.\n */\n//#define MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE 6000\n\n/**\n * \\def MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH\n *\n * Size in bytes of a ticket nonce. This is not used in TLS 1.2.\n *\n * This must be less than 256.\n */\n//#define MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH 32\n\n/**\n * \\def MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS\n *\n * Default number of NewSessionTicket messages to be sent by a TLS 1.3 server\n * after handshake completion. This is not used in TLS 1.2 and relevant only if\n * the MBEDTLS_SSL_SESSION_TICKETS option is enabled.\n *\n */\n//#define MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS 1\n\n/* X509 options */\n//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA   8   /**< Maximum number of intermediate CAs in a verification chain. */\n//#define MBEDTLS_X509_MAX_FILE_PATH_LEN     512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\\0'). */\n\n/** \\} name SECTION: Module configuration options */\n\n\n#if defined(__TINYC__)\n#undef MBEDTLS_HAVE_ASM\n#undef MBEDTLS_AESNI_C\n#undef MBEDTLS_PADLOCK_C\n#else // __TINYC__\n#define MBEDTLS_HAVE_ASM\n#define MBEDTLS_AESNI_C\n#define MBEDTLS_PADLOCK_C\n#endif // __TINYC__\n\n#if ( defined(__linux__) || defined(__FreeBSD__) ) || defined (__OpenBSD__)\n#define MBEDTLS_THREADING_PTHREAD\n#define MBEDTLS_THREADING_C\n#else\n#undef MBEDTLS_THREADING_PTHREAD\n#undef MBEDTLS_THREADING_C\n#endif\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/md.h",
    "content": "/**\n * \\file md.h\n *\n * \\brief   This file contains the generic functions for message-digest\n *          (hashing) and HMAC.\n *\n * \\author Adriaan de Jong <dejong@fox-it.com>\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_MD_H\n#define MBEDTLS_MD_H\n#include \"mbedtls/private_access.h\"\n\n#include <stddef.h>\n\n#include \"mbedtls/build_info.h\"\n#include \"mbedtls/platform_util.h\"\n\n/** The selected feature is not available. */\n#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE                -0x5080\n/** Bad input parameters to function. */\n#define MBEDTLS_ERR_MD_BAD_INPUT_DATA                     -0x5100\n/** Failed to allocate memory. */\n#define MBEDTLS_ERR_MD_ALLOC_FAILED                       -0x5180\n/** Opening or reading of file failed. */\n#define MBEDTLS_ERR_MD_FILE_IO_ERROR                      -0x5200\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief     Supported message digests.\n *\n * \\warning   MD5 and SHA-1 are considered weak message digests and\n *            their use constitutes a security risk. We recommend considering\n *            stronger message digests instead.\n *\n */\n/* Note: these are aligned with the definitions of PSA_ALG_ macros for hashes,\n * in order to enable an efficient implementation of conversion functions.\n * This is tested by md_to_from_psa() in test_suite_md. */\ntypedef enum {\n    MBEDTLS_MD_NONE=0,    /**< None. */\n    MBEDTLS_MD_MD5=0x03,       /**< The MD5 message digest. */\n    MBEDTLS_MD_RIPEMD160=0x04, /**< The RIPEMD-160 message digest. */\n    MBEDTLS_MD_SHA1=0x05,      /**< The SHA-1 message digest. */\n    MBEDTLS_MD_SHA224=0x08,    /**< The SHA-224 message digest. */\n    MBEDTLS_MD_SHA256=0x09,    /**< The SHA-256 message digest. */\n    MBEDTLS_MD_SHA384=0x0a,    /**< The SHA-384 message digest. */\n    MBEDTLS_MD_SHA512=0x0b,    /**< The SHA-512 message digest. */\n    MBEDTLS_MD_SHA3_224=0x10,  /**< The SHA3-224 message digest. */\n    MBEDTLS_MD_SHA3_256=0x11,  /**< The SHA3-256 message digest. */\n    MBEDTLS_MD_SHA3_384=0x12,  /**< The SHA3-384 message digest. */\n    MBEDTLS_MD_SHA3_512=0x13,  /**< The SHA3-512 message digest. */\n} mbedtls_md_type_t;\n\n/* Note: this should always be >= PSA_HASH_MAX_SIZE\n * in all builds with both CRYPTO_C and MD_LIGHT.\n *\n * This is to make things easier for modules such as TLS that may define a\n * buffer size using MD_MAX_SIZE in a part of the code that's common to PSA\n * and legacy, then assume the buffer's size is PSA_HASH_MAX_SIZE in another\n * part of the code based on PSA.\n */\n#if defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_MD_CAN_SHA3_512)\n#define MBEDTLS_MD_MAX_SIZE         64  /* longest known is SHA512 */\n#elif defined(MBEDTLS_MD_CAN_SHA384) || defined(MBEDTLS_MD_CAN_SHA3_384)\n#define MBEDTLS_MD_MAX_SIZE         48  /* longest known is SHA384 */\n#elif defined(MBEDTLS_MD_CAN_SHA256) || defined(MBEDTLS_MD_CAN_SHA3_256)\n#define MBEDTLS_MD_MAX_SIZE         32  /* longest known is SHA256 */\n#elif defined(MBEDTLS_MD_CAN_SHA224) || defined(MBEDTLS_MD_CAN_SHA3_224)\n#define MBEDTLS_MD_MAX_SIZE         28  /* longest known is SHA224 */\n#else\n#define MBEDTLS_MD_MAX_SIZE         20  /* longest known is SHA1 or RIPE MD-160\n                                           or smaller (MD5 and earlier) */\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA3_224)\n#define MBEDTLS_MD_MAX_BLOCK_SIZE         144 /* the longest known is SHA3-224 */\n#elif defined(MBEDTLS_MD_CAN_SHA3_256)\n#define MBEDTLS_MD_MAX_BLOCK_SIZE         136\n#elif defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_MD_CAN_SHA384)\n#define MBEDTLS_MD_MAX_BLOCK_SIZE         128\n#elif defined(MBEDTLS_MD_CAN_SHA3_384)\n#define MBEDTLS_MD_MAX_BLOCK_SIZE         104\n#elif defined(MBEDTLS_MD_CAN_SHA3_512)\n#define MBEDTLS_MD_MAX_BLOCK_SIZE         72\n#else\n#define MBEDTLS_MD_MAX_BLOCK_SIZE         64\n#endif\n\n/**\n * Opaque struct.\n *\n * Constructed using either #mbedtls_md_info_from_string or\n * #mbedtls_md_info_from_type.\n *\n * Fields can be accessed with #mbedtls_md_get_size,\n * #mbedtls_md_get_type and #mbedtls_md_get_name.\n */\n/* Defined internally in library/md_wrap.h. */\ntypedef struct mbedtls_md_info_t mbedtls_md_info_t;\n\n/**\n * Used internally to indicate whether a context uses legacy or PSA.\n *\n * Internal use only.\n */\ntypedef enum {\n    MBEDTLS_MD_ENGINE_LEGACY = 0,\n    MBEDTLS_MD_ENGINE_PSA,\n} mbedtls_md_engine_t;\n\n/**\n * The generic message-digest context.\n */\ntypedef struct mbedtls_md_context_t {\n    /** Information about the associated message digest. */\n    const mbedtls_md_info_t *MBEDTLS_PRIVATE(md_info);\n\n#if defined(MBEDTLS_MD_SOME_PSA)\n    /** Are hash operations dispatched to PSA or legacy? */\n    mbedtls_md_engine_t MBEDTLS_PRIVATE(engine);\n#endif\n\n    /** The digest-specific context (legacy) or the PSA operation. */\n    void *MBEDTLS_PRIVATE(md_ctx);\n\n#if defined(MBEDTLS_MD_C)\n    /** The HMAC part of the context. */\n    void *MBEDTLS_PRIVATE(hmac_ctx);\n#endif\n} mbedtls_md_context_t;\n\n/**\n * \\brief           This function returns the message-digest information\n *                  associated with the given digest type.\n *\n * \\param md_type   The type of digest to search for.\n *\n * \\return          The message-digest information associated with \\p md_type.\n * \\return          NULL if the associated message-digest information is not found.\n */\nconst mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type);\n\n/**\n * \\brief           This function initializes a message-digest context without\n *                  binding it to a particular message-digest algorithm.\n *\n *                  This function should always be called first. It prepares the\n *                  context for mbedtls_md_setup() for binding it to a\n *                  message-digest algorithm.\n */\nvoid mbedtls_md_init(mbedtls_md_context_t *ctx);\n\n/**\n * \\brief           This function clears the internal structure of \\p ctx and\n *                  frees any embedded internal structure, but does not free\n *                  \\p ctx itself.\n *\n *                  If you have called mbedtls_md_setup() on \\p ctx, you must\n *                  call mbedtls_md_free() when you are no longer using the\n *                  context.\n *                  Calling this function if you have previously\n *                  called mbedtls_md_init() and nothing else is optional.\n *                  You must not call this function if you have not called\n *                  mbedtls_md_init().\n */\nvoid mbedtls_md_free(mbedtls_md_context_t *ctx);\n\n\n/**\n * \\brief           This function selects the message digest algorithm to use,\n *                  and allocates internal structures.\n *\n *                  It should be called after mbedtls_md_init() or\n *                  mbedtls_md_free(). Makes it necessary to call\n *                  mbedtls_md_free() later.\n *\n * \\param ctx       The context to set up.\n * \\param md_info   The information structure of the message-digest algorithm\n *                  to use.\n * \\param hmac      Defines if HMAC is used. 0: HMAC is not used (saves some memory),\n *                  or non-zero: HMAC is used with this context.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification\n *                  failure.\n * \\return          #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac);\n\n/**\n * \\brief           This function clones the state of a message-digest\n *                  context.\n *\n * \\note            You must call mbedtls_md_setup() on \\c dst before calling\n *                  this function.\n *\n * \\note            The two contexts must have the same type,\n *                  for example, both are SHA-256.\n *\n * \\warning         This function clones the message-digest state, not the\n *                  HMAC state.\n *\n * \\param dst       The destination context.\n * \\param src       The context to be cloned.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure.\n * \\return          #MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE if both contexts are\n *                  not using the same engine. This can be avoided by moving\n *                  the call to psa_crypto_init() before the first call to\n *                  mbedtls_md_setup().\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_md_clone(mbedtls_md_context_t *dst,\n                     const mbedtls_md_context_t *src);\n\n/**\n * \\brief           This function extracts the message-digest size from the\n *                  message-digest information structure.\n *\n * \\param md_info   The information structure of the message-digest algorithm\n *                  to use.\n *\n * \\return          The size of the message-digest output in Bytes.\n */\nunsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info);\n\n/**\n * \\brief           This function gives the message-digest size associated to\n *                  message-digest type.\n *\n * \\param md_type   The message-digest type.\n *\n * \\return          The size of the message-digest output in Bytes,\n *                  or 0 if the message-digest type is not known.\n */\nstatic inline unsigned char mbedtls_md_get_size_from_type(mbedtls_md_type_t md_type)\n{\n    return mbedtls_md_get_size(mbedtls_md_info_from_type(md_type));\n}\n\n/**\n * \\brief           This function extracts the message-digest type from the\n *                  message-digest information structure.\n *\n * \\param md_info   The information structure of the message-digest algorithm\n *                  to use.\n *\n * \\return          The type of the message digest.\n */\nmbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info);\n\n/**\n * \\brief           This function starts a message-digest computation.\n *\n *                  You must call this function after setting up the context\n *                  with mbedtls_md_setup(), and before passing data with\n *                  mbedtls_md_update().\n *\n * \\param ctx       The generic message-digest context.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification\n *                  failure.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_md_starts(mbedtls_md_context_t *ctx);\n\n/**\n * \\brief           This function feeds an input buffer into an ongoing\n *                  message-digest computation.\n *\n *                  You must call mbedtls_md_starts() before calling this\n *                  function. You may call this function multiple times.\n *                  Afterwards, call mbedtls_md_finish().\n *\n * \\param ctx       The generic message-digest context.\n * \\param input     The buffer holding the input data.\n * \\param ilen      The length of the input data.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification\n *                  failure.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen);\n\n/**\n * \\brief           This function finishes the digest operation,\n *                  and writes the result to the output buffer.\n *\n *                  Call this function after a call to mbedtls_md_starts(),\n *                  followed by any number of calls to mbedtls_md_update().\n *                  Afterwards, you may either clear the context with\n *                  mbedtls_md_free(), or call mbedtls_md_starts() to reuse\n *                  the context for another digest operation with the same\n *                  algorithm.\n *\n * \\param ctx       The generic message-digest context.\n * \\param output    The buffer for the generic message-digest checksum result.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification\n *                  failure.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_md_finish(mbedtls_md_context_t *ctx, unsigned char *output);\n\n/**\n * \\brief          This function calculates the message-digest of a buffer,\n *                 with respect to a configurable message-digest algorithm\n *                 in a single call.\n *\n *                 The result is calculated as\n *                 Output = message_digest(input buffer).\n *\n * \\param md_info  The information structure of the message-digest algorithm\n *                 to use.\n * \\param input    The buffer holding the data.\n * \\param ilen     The length of the input data.\n * \\param output   The generic message-digest checksum result.\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification\n *                 failure.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_md(const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,\n               unsigned char *output);\n\n/**\n * \\brief           This function returns the list of digests supported by the\n *                  generic digest module.\n *\n * \\note            The list starts with the strongest available hashes.\n *\n * \\return          A statically allocated array of digests. Each element\n *                  in the returned list is an integer belonging to the\n *                  message-digest enumeration #mbedtls_md_type_t.\n *                  The last entry is 0.\n */\nconst int *mbedtls_md_list(void);\n\n/**\n * \\brief           This function returns the message-digest information\n *                  associated with the given digest name.\n *\n * \\param md_name   The name of the digest to search for.\n *\n * \\return          The message-digest information associated with \\p md_name.\n * \\return          NULL if the associated message-digest information is not found.\n */\nconst mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name);\n\n/**\n * \\brief           This function returns the name of the message digest for\n *                  the message-digest information structure given.\n *\n * \\param md_info   The information structure of the message-digest algorithm\n *                  to use.\n *\n * \\return          The name of the message digest.\n */\nconst char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info);\n\n/**\n * \\brief           This function returns the message-digest information\n *                  from the given context.\n *\n * \\param ctx       The context from which to extract the information.\n *                  This must be initialized (or \\c NULL).\n *\n * \\return          The message-digest information associated with \\p ctx.\n * \\return          \\c NULL if \\p ctx is \\c NULL.\n */\nconst mbedtls_md_info_t *mbedtls_md_info_from_ctx(\n    const mbedtls_md_context_t *ctx);\n\n#if defined(MBEDTLS_FS_IO)\n/**\n * \\brief          This function calculates the message-digest checksum\n *                 result of the contents of the provided file.\n *\n *                 The result is calculated as\n *                 Output = message_digest(file contents).\n *\n * \\param md_info  The information structure of the message-digest algorithm\n *                 to use.\n * \\param path     The input file name.\n * \\param output   The generic message-digest checksum result.\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_MD_FILE_IO_ERROR on an I/O error accessing\n *                 the file pointed by \\p path.\n * \\return         #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \\p md_info was NULL.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_md_file(const mbedtls_md_info_t *md_info, const char *path,\n                    unsigned char *output);\n#endif /* MBEDTLS_FS_IO */\n\n/**\n * \\brief           This function sets the HMAC key and prepares to\n *                  authenticate a new message.\n *\n *                  Call this function after mbedtls_md_setup(), to use\n *                  the MD context for an HMAC calculation, then call\n *                  mbedtls_md_hmac_update() to provide the input data, and\n *                  mbedtls_md_hmac_finish() to get the HMAC value.\n *\n * \\param ctx       The message digest context containing an embedded HMAC\n *                  context.\n * \\param key       The HMAC secret key.\n * \\param keylen    The length of the HMAC key in Bytes.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification\n *                  failure.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_md_hmac_starts(mbedtls_md_context_t *ctx, const unsigned char *key,\n                           size_t keylen);\n\n/**\n * \\brief           This function feeds an input buffer into an ongoing HMAC\n *                  computation.\n *\n *                  Call mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset()\n *                  before calling this function.\n *                  You may call this function multiple times to pass the\n *                  input piecewise.\n *                  Afterwards, call mbedtls_md_hmac_finish().\n *\n * \\param ctx       The message digest context containing an embedded HMAC\n *                  context.\n * \\param input     The buffer holding the input data.\n * \\param ilen      The length of the input data.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification\n *                  failure.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_md_hmac_update(mbedtls_md_context_t *ctx, const unsigned char *input,\n                           size_t ilen);\n\n/**\n * \\brief           This function finishes the HMAC operation, and writes\n *                  the result to the output buffer.\n *\n *                  Call this function after mbedtls_md_hmac_starts() and\n *                  mbedtls_md_hmac_update() to get the HMAC value. Afterwards\n *                  you may either call mbedtls_md_free() to clear the context,\n *                  or call mbedtls_md_hmac_reset() to reuse the context with\n *                  the same HMAC key.\n *\n * \\param ctx       The message digest context containing an embedded HMAC\n *                  context.\n * \\param output    The generic HMAC checksum result.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification\n *                  failure.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_md_hmac_finish(mbedtls_md_context_t *ctx, unsigned char *output);\n\n/**\n * \\brief           This function prepares to authenticate a new message with\n *                  the same key as the previous HMAC operation.\n *\n *                  You may call this function after mbedtls_md_hmac_finish().\n *                  Afterwards call mbedtls_md_hmac_update() to pass the new\n *                  input.\n *\n * \\param ctx       The message digest context containing an embedded HMAC\n *                  context.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification\n *                  failure.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_md_hmac_reset(mbedtls_md_context_t *ctx);\n\n/**\n * \\brief          This function calculates the full generic HMAC\n *                 on the input buffer with the provided key.\n *\n *                 The function allocates the context, performs the\n *                 calculation, and frees the context.\n *\n *                 The HMAC result is calculated as\n *                 output = generic HMAC(hmac key, input buffer).\n *\n * \\param md_info  The information structure of the message-digest algorithm\n *                 to use.\n * \\param key      The HMAC secret key.\n * \\param keylen   The length of the HMAC secret key in Bytes.\n * \\param input    The buffer holding the input data.\n * \\param ilen     The length of the input data.\n * \\param output   The generic HMAC result.\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification\n *                 failure.\n */\nMBEDTLS_CHECK_RETURN_TYPICAL\nint mbedtls_md_hmac(const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen,\n                    const unsigned char *input, size_t ilen,\n                    unsigned char *output);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_MD_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/md5.h",
    "content": "/**\n * \\file md5.h\n *\n * \\brief MD5 message digest algorithm (hash function)\n *\n * \\warning   MD5 is considered a weak message digest and its use constitutes a\n *            security risk. We recommend considering stronger message\n *            digests instead.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_MD5_H\n#define MBEDTLS_MD5_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_MD5_ALT)\n// Regular implementation\n//\n\n/**\n * \\brief          MD5 context structure\n *\n * \\warning        MD5 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n */\ntypedef struct mbedtls_md5_context {\n    uint32_t MBEDTLS_PRIVATE(total)[2];          /*!< number of bytes processed  */\n    uint32_t MBEDTLS_PRIVATE(state)[4];          /*!< intermediate digest state  */\n    unsigned char MBEDTLS_PRIVATE(buffer)[64];   /*!< data block being processed */\n}\nmbedtls_md5_context;\n\n#else  /* MBEDTLS_MD5_ALT */\n#include \"md5_alt.h\"\n#endif /* MBEDTLS_MD5_ALT */\n\n/**\n * \\brief          Initialize MD5 context\n *\n * \\param ctx      MD5 context to be initialized\n *\n * \\warning        MD5 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n */\nvoid mbedtls_md5_init(mbedtls_md5_context *ctx);\n\n/**\n * \\brief          Clear MD5 context\n *\n * \\param ctx      MD5 context to be cleared\n *\n * \\warning        MD5 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n */\nvoid mbedtls_md5_free(mbedtls_md5_context *ctx);\n\n/**\n * \\brief          Clone (the state of) an MD5 context\n *\n * \\param dst      The destination context\n * \\param src      The context to be cloned\n *\n * \\warning        MD5 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n */\nvoid mbedtls_md5_clone(mbedtls_md5_context *dst,\n                       const mbedtls_md5_context *src);\n\n/**\n * \\brief          MD5 context setup\n *\n * \\param ctx      context to be initialized\n *\n * \\return         0 if successful\n *\n * \\warning        MD5 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n */\nint mbedtls_md5_starts(mbedtls_md5_context *ctx);\n\n/**\n * \\brief          MD5 process buffer\n *\n * \\param ctx      MD5 context\n * \\param input    buffer holding the data\n * \\param ilen     length of the input data\n *\n * \\return         0 if successful\n *\n * \\warning        MD5 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n */\nint mbedtls_md5_update(mbedtls_md5_context *ctx,\n                       const unsigned char *input,\n                       size_t ilen);\n\n/**\n * \\brief          MD5 final digest\n *\n * \\param ctx      MD5 context\n * \\param output   MD5 checksum result\n *\n * \\return         0 if successful\n *\n * \\warning        MD5 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n */\nint mbedtls_md5_finish(mbedtls_md5_context *ctx,\n                       unsigned char output[16]);\n\n/**\n * \\brief          MD5 process data block (internal use only)\n *\n * \\param ctx      MD5 context\n * \\param data     buffer holding one block of data\n *\n * \\return         0 if successful\n *\n * \\warning        MD5 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n */\nint mbedtls_internal_md5_process(mbedtls_md5_context *ctx,\n                                 const unsigned char data[64]);\n\n/**\n * \\brief          Output = MD5( input buffer )\n *\n * \\param input    buffer holding the data\n * \\param ilen     length of the input data\n * \\param output   MD5 checksum result\n *\n * \\return         0 if successful\n *\n * \\warning        MD5 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n */\nint mbedtls_md5(const unsigned char *input,\n                size_t ilen,\n                unsigned char output[16]);\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/**\n * \\brief          Checkup routine\n *\n * \\return         0 if successful, or 1 if the test failed\n *\n * \\warning        MD5 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n */\nint mbedtls_md5_self_test(int verbose);\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* mbedtls_md5.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h",
    "content": "/**\n * \\file memory_buffer_alloc.h\n *\n * \\brief Buffer-based memory allocator\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_MEMORY_BUFFER_ALLOC_H\n#define MBEDTLS_MEMORY_BUFFER_ALLOC_H\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n\n/**\n * \\name SECTION: Module settings\n *\n * The configuration options you can set for this module are in this section.\n * Either change them in mbedtls_config.h or define them on the compiler command line.\n * \\{\n */\n\n#if !defined(MBEDTLS_MEMORY_ALIGN_MULTIPLE)\n#define MBEDTLS_MEMORY_ALIGN_MULTIPLE       4 /**< Align on multiples of this value */\n#endif\n\n/** \\} name SECTION: Module settings */\n\n#define MBEDTLS_MEMORY_VERIFY_NONE         0\n#define MBEDTLS_MEMORY_VERIFY_ALLOC        (1 << 0)\n#define MBEDTLS_MEMORY_VERIFY_FREE         (1 << 1)\n#define MBEDTLS_MEMORY_VERIFY_ALWAYS       (MBEDTLS_MEMORY_VERIFY_ALLOC | \\\n                                            MBEDTLS_MEMORY_VERIFY_FREE)\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief   Initialize use of stack-based memory allocator.\n *          The stack-based allocator does memory management inside the\n *          presented buffer and does not call calloc() and free().\n *          It sets the global mbedtls_calloc() and mbedtls_free() pointers\n *          to its own functions.\n *          (Provided mbedtls_calloc() and mbedtls_free() are thread-safe if\n *           MBEDTLS_THREADING_C is defined)\n *\n * \\note    This code is not optimized and provides a straight-forward\n *          implementation of a stack-based memory allocator.\n *\n * \\param buf   buffer to use as heap\n * \\param len   size of the buffer\n */\nvoid mbedtls_memory_buffer_alloc_init(unsigned char *buf, size_t len);\n\n/**\n * \\brief   Free the mutex for thread-safety and clear remaining memory\n */\nvoid mbedtls_memory_buffer_alloc_free(void);\n\n/**\n * \\brief   Determine when the allocator should automatically verify the state\n *          of the entire chain of headers / meta-data.\n *          (Default: MBEDTLS_MEMORY_VERIFY_NONE)\n *\n * \\param verify    One of MBEDTLS_MEMORY_VERIFY_NONE, MBEDTLS_MEMORY_VERIFY_ALLOC,\n *                  MBEDTLS_MEMORY_VERIFY_FREE or MBEDTLS_MEMORY_VERIFY_ALWAYS\n */\nvoid mbedtls_memory_buffer_set_verify(int verify);\n\n#if defined(MBEDTLS_MEMORY_DEBUG)\n/**\n * \\brief   Print out the status of the allocated memory (primarily for use\n *          after a program should have de-allocated all memory)\n *          Prints out a list of 'still allocated' blocks and their stack\n *          trace if MBEDTLS_MEMORY_BACKTRACE is defined.\n */\nvoid mbedtls_memory_buffer_alloc_status(void);\n\n/**\n * \\brief   Get the number of alloc/free so far.\n *\n * \\param alloc_count   Number of allocations.\n * \\param free_count    Number of frees.\n */\nvoid mbedtls_memory_buffer_alloc_count_get(size_t *alloc_count, size_t *free_count);\n\n/**\n * \\brief   Get the peak heap usage so far\n *\n * \\param max_used      Peak number of bytes in use or committed. This\n *                      includes bytes in allocated blocks too small to split\n *                      into smaller blocks but larger than the requested size.\n * \\param max_blocks    Peak number of blocks in use, including free and used\n */\nvoid mbedtls_memory_buffer_alloc_max_get(size_t *max_used, size_t *max_blocks);\n\n/**\n * \\brief   Reset peak statistics\n */\nvoid mbedtls_memory_buffer_alloc_max_reset(void);\n\n/**\n * \\brief   Get the current heap usage\n *\n * \\param cur_used      Current number of bytes in use or committed. This\n *                      includes bytes in allocated blocks too small to split\n *                      into smaller blocks but larger than the requested size.\n * \\param cur_blocks    Current number of blocks in use, including free and used\n */\nvoid mbedtls_memory_buffer_alloc_cur_get(size_t *cur_used, size_t *cur_blocks);\n#endif /* MBEDTLS_MEMORY_DEBUG */\n\n/**\n * \\brief   Verifies that all headers in the memory buffer are correct\n *          and contain sane values. Helps debug buffer-overflow errors.\n *\n *          Prints out first failure if MBEDTLS_MEMORY_DEBUG is defined.\n *          Prints out full header information if MBEDTLS_MEMORY_DEBUG\n *          is defined. (Includes stack trace information for each block if\n *          MBEDTLS_MEMORY_BACKTRACE is defined as well).\n *\n * \\return             0 if verified, 1 otherwise\n */\nint mbedtls_memory_buffer_alloc_verify(void);\n\n#if defined(MBEDTLS_SELF_TEST)\n/**\n * \\brief          Checkup routine\n *\n * \\return         0 if successful, or 1 if a test failed\n */\nint mbedtls_memory_buffer_alloc_self_test(int verbose);\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* memory_buffer_alloc.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/net_sockets.h",
    "content": "/**\n * \\file net_sockets.h\n *\n * \\brief   Network sockets abstraction layer to integrate Mbed TLS into a\n *          BSD-style sockets API.\n *\n *          The network sockets module provides an example integration of the\n *          Mbed TLS library into a BSD sockets implementation. The module is\n *          intended to be an example of how Mbed TLS can be integrated into a\n *          networking stack, as well as to be Mbed TLS's network integration\n *          for its supported platforms.\n *\n *          The module is intended only to be used with the Mbed TLS library and\n *          is not intended to be used by third party application software\n *          directly.\n *\n *          The supported platforms are as follows:\n *              * Microsoft Windows and Windows CE\n *              * POSIX/Unix platforms including Linux, OS X\n *\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_NET_SOCKETS_H\n#define MBEDTLS_NET_SOCKETS_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/ssl.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n/** Failed to open a socket. */\n#define MBEDTLS_ERR_NET_SOCKET_FAILED                     -0x0042\n/** The connection to the given server / port failed. */\n#define MBEDTLS_ERR_NET_CONNECT_FAILED                    -0x0044\n/** Binding of the socket failed. */\n#define MBEDTLS_ERR_NET_BIND_FAILED                       -0x0046\n/** Could not listen on the socket. */\n#define MBEDTLS_ERR_NET_LISTEN_FAILED                     -0x0048\n/** Could not accept the incoming connection. */\n#define MBEDTLS_ERR_NET_ACCEPT_FAILED                     -0x004A\n/** Reading information from the socket failed. */\n#define MBEDTLS_ERR_NET_RECV_FAILED                       -0x004C\n/** Sending information through the socket failed. */\n#define MBEDTLS_ERR_NET_SEND_FAILED                       -0x004E\n/** Connection was reset by peer. */\n#define MBEDTLS_ERR_NET_CONN_RESET                        -0x0050\n/** Failed to get an IP address for the given hostname. */\n#define MBEDTLS_ERR_NET_UNKNOWN_HOST                      -0x0052\n/** Buffer is too small to hold the data. */\n#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL                  -0x0043\n/** The context is invalid, eg because it was free()ed. */\n#define MBEDTLS_ERR_NET_INVALID_CONTEXT                   -0x0045\n/** Polling the net context failed. */\n#define MBEDTLS_ERR_NET_POLL_FAILED                       -0x0047\n/** Input invalid. */\n#define MBEDTLS_ERR_NET_BAD_INPUT_DATA                    -0x0049\n\n#define MBEDTLS_NET_LISTEN_BACKLOG         10 /**< The backlog that listen() should use. */\n\n#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */\n#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */\n\n#define MBEDTLS_NET_POLL_READ  1 /**< Used in \\c mbedtls_net_poll to check for pending data  */\n#define MBEDTLS_NET_POLL_WRITE 2 /**< Used in \\c mbedtls_net_poll to check if write possible */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Wrapper type for sockets.\n *\n * Currently backed by just a file descriptor, but might be more in the future\n * (eg two file descriptors for combined IPv4 + IPv6 support, or additional\n * structures for hand-made UDP demultiplexing).\n */\ntypedef struct mbedtls_net_context {\n    /** The underlying file descriptor.\n     *\n     * This field is only guaranteed to be present on POSIX/Unix-like platforms.\n     * On other platforms, it may have a different type, have a different\n     * meaning, or be absent altogether.\n     */\n    int fd;\n}\nmbedtls_net_context;\n\n/**\n * \\brief          Initialize a context\n *                 Just makes the context ready to be used or freed safely.\n *\n * \\param ctx      Context to initialize\n */\nvoid mbedtls_net_init(mbedtls_net_context *ctx);\n\n/**\n * \\brief          Initiate a connection with host:port in the given protocol\n *\n * \\param ctx      Socket to use\n * \\param host     Host to connect to\n * \\param port     Port to connect to\n * \\param proto    Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP\n *\n * \\return         0 if successful, or one of:\n *                      MBEDTLS_ERR_NET_SOCKET_FAILED,\n *                      MBEDTLS_ERR_NET_UNKNOWN_HOST,\n *                      MBEDTLS_ERR_NET_CONNECT_FAILED\n *\n * \\note           Sets the socket in connected mode even with UDP.\n */\nint mbedtls_net_connect(mbedtls_net_context *ctx, const char *host, const char *port, int proto);\n\n/**\n * \\brief          Create a receiving socket on bind_ip:port in the chosen\n *                 protocol. If bind_ip == NULL, all interfaces are bound.\n *\n * \\param ctx      Socket to use\n * \\param bind_ip  IP to bind to, can be NULL\n * \\param port     Port number to use\n * \\param proto    Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP\n *\n * \\return         0 if successful, or one of:\n *                      MBEDTLS_ERR_NET_SOCKET_FAILED,\n *                      MBEDTLS_ERR_NET_UNKNOWN_HOST,\n *                      MBEDTLS_ERR_NET_BIND_FAILED,\n *                      MBEDTLS_ERR_NET_LISTEN_FAILED\n *\n * \\note           Regardless of the protocol, opens the sockets and binds it.\n *                 In addition, make the socket listening if protocol is TCP.\n */\nint mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto);\n\n/**\n * \\brief           Accept a connection from a remote client\n *\n * \\param bind_ctx  Relevant socket\n * \\param client_ctx Will contain the connected client socket\n * \\param client_ip Will contain the client IP address, can be NULL\n * \\param buf_size  Size of the client_ip buffer\n * \\param cip_len   Will receive the size of the client IP written,\n *                  can be NULL if client_ip is null\n *\n * \\return          0 if successful, or\n *                  MBEDTLS_ERR_NET_SOCKET_FAILED,\n *                  MBEDTLS_ERR_NET_BIND_FAILED,\n *                  MBEDTLS_ERR_NET_ACCEPT_FAILED, or\n *                  MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small,\n *                  MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to\n *                  non-blocking and accept() would block.\n */\nint mbedtls_net_accept(mbedtls_net_context *bind_ctx,\n                       mbedtls_net_context *client_ctx,\n                       void *client_ip, size_t buf_size, size_t *cip_len);\n\n/**\n * \\brief          Check and wait for the context to be ready for read/write\n *\n * \\note           The current implementation of this function uses\n *                 select() and returns an error if the file descriptor\n *                 is \\c FD_SETSIZE or greater.\n *\n * \\param ctx      Socket to check\n * \\param rw       Bitflag composed of MBEDTLS_NET_POLL_READ and\n *                 MBEDTLS_NET_POLL_WRITE specifying the events\n *                 to wait for:\n *                 - If MBEDTLS_NET_POLL_READ is set, the function\n *                   will return as soon as the net context is available\n *                   for reading.\n *                 - If MBEDTLS_NET_POLL_WRITE is set, the function\n *                   will return as soon as the net context is available\n *                   for writing.\n * \\param timeout  Maximal amount of time to wait before returning,\n *                 in milliseconds. If \\c timeout is zero, the\n *                 function returns immediately. If \\c timeout is\n *                 -1u, the function blocks potentially indefinitely.\n *\n * \\return         Bitmask composed of MBEDTLS_NET_POLL_READ/WRITE\n *                 on success or timeout, or a negative return code otherwise.\n */\nint mbedtls_net_poll(mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout);\n\n/**\n * \\brief          Set the socket blocking\n *\n * \\param ctx      Socket to set\n *\n * \\return         0 if successful, or a non-zero error code\n */\nint mbedtls_net_set_block(mbedtls_net_context *ctx);\n\n/**\n * \\brief          Set the socket non-blocking\n *\n * \\param ctx      Socket to set\n *\n * \\return         0 if successful, or a non-zero error code\n */\nint mbedtls_net_set_nonblock(mbedtls_net_context *ctx);\n\n/**\n * \\brief          Portable usleep helper\n *\n * \\param usec     Amount of microseconds to sleep\n *\n * \\note           Real amount of time slept will not be less than\n *                 select()'s timeout granularity (typically, 10ms).\n */\nvoid mbedtls_net_usleep(unsigned long usec);\n\n/**\n * \\brief          Read at most 'len' characters. If no error occurs,\n *                 the actual amount read is returned.\n *\n * \\param ctx      Socket\n * \\param buf      The buffer to write to\n * \\param len      Maximum length of the buffer\n *\n * \\return         the number of bytes received,\n *                 or a non-zero error code; with a non-blocking socket,\n *                 MBEDTLS_ERR_SSL_WANT_READ indicates read() would block.\n */\nint mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len);\n\n/**\n * \\brief          Write at most 'len' characters. If no error occurs,\n *                 the actual amount written is returned.\n *\n * \\param ctx      Socket\n * \\param buf      The buffer to read from\n * \\param len      The length of the buffer\n *\n * \\return         the number of bytes sent,\n *                 or a non-zero error code; with a non-blocking socket,\n *                 MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block.\n */\nint mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len);\n\n/**\n * \\brief          Read at most 'len' characters, blocking for at most\n *                 'timeout' seconds. If no error occurs, the actual amount\n *                 read is returned.\n *\n * \\note           The current implementation of this function uses\n *                 select() and returns an error if the file descriptor\n *                 is \\c FD_SETSIZE or greater.\n *\n * \\param ctx      Socket\n * \\param buf      The buffer to write to\n * \\param len      Maximum length of the buffer\n * \\param timeout  Maximum number of milliseconds to wait for data\n *                 0 means no timeout (wait forever)\n *\n * \\return         The number of bytes received if successful.\n *                 MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out.\n *                 MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal.\n *                 Another negative error code (MBEDTLS_ERR_NET_xxx)\n *                 for other failures.\n *\n * \\note           This function will block (until data becomes available or\n *                 timeout is reached) even if the socket is set to\n *                 non-blocking. Handling timeouts with non-blocking reads\n *                 requires a different strategy.\n */\nint mbedtls_net_recv_timeout(void *ctx, unsigned char *buf, size_t len,\n                             uint32_t timeout);\n\n/**\n * \\brief          Closes down the connection and free associated data\n *\n * \\param ctx      The context to close\n *\n * \\note           This function frees and clears data associated with the\n *                 context but does not free the memory pointed to by \\p ctx.\n *                 This memory is the responsibility of the caller.\n */\nvoid mbedtls_net_close(mbedtls_net_context *ctx);\n\n/**\n * \\brief          Gracefully shutdown the connection and free associated data\n *\n * \\param ctx      The context to free\n *\n * \\note           This function frees and clears data associated with the\n *                 context but does not free the memory pointed to by \\p ctx.\n *                 This memory is the responsibility of the caller.\n */\nvoid mbedtls_net_free(mbedtls_net_context *ctx);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* net_sockets.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/nist_kw.h",
    "content": "/**\n * \\file nist_kw.h\n *\n * \\brief This file provides an API for key wrapping (KW) and key wrapping with\n *        padding (KWP) as defined in NIST SP 800-38F.\n *        https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf\n *\n *        Key wrapping specifies a deterministic authenticated-encryption mode\n *        of operation, according to <em>NIST SP 800-38F: Recommendation for\n *        Block Cipher Modes of Operation: Methods for Key Wrapping</em>. Its\n *        purpose is to protect cryptographic keys.\n *\n *        Its equivalent is RFC 3394 for KW, and RFC 5649 for KWP.\n *        https://tools.ietf.org/html/rfc3394\n *        https://tools.ietf.org/html/rfc5649\n *\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_NIST_KW_H\n#define MBEDTLS_NIST_KW_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/cipher.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef enum {\n    MBEDTLS_KW_MODE_KW = 0,\n    MBEDTLS_KW_MODE_KWP = 1\n} mbedtls_nist_kw_mode_t;\n\n#if !defined(MBEDTLS_NIST_KW_ALT)\n// Regular implementation\n//\n\n/**\n * \\brief    The key wrapping context-type definition. The key wrapping context is passed\n *           to the APIs called.\n *\n * \\note     The definition of this type may change in future library versions.\n *           Don't make any assumptions on this context!\n */\ntypedef struct {\n    mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx);    /*!< The cipher context used. */\n} mbedtls_nist_kw_context;\n\n#else  /* MBEDTLS_NIST_key wrapping_ALT */\n#include \"nist_kw_alt.h\"\n#endif /* MBEDTLS_NIST_KW_ALT */\n\n/**\n * \\brief           This function initializes the specified key wrapping context\n *                  to make references valid and prepare the context\n *                  for mbedtls_nist_kw_setkey() or mbedtls_nist_kw_free().\n *\n * \\param ctx       The key wrapping context to initialize.\n *\n */\nvoid mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx);\n\n/**\n * \\brief           This function initializes the key wrapping context set in the\n *                  \\p ctx parameter and sets the encryption key.\n *\n * \\param ctx       The key wrapping context.\n * \\param cipher    The 128-bit block cipher to use. Only AES is supported.\n * \\param key       The Key Encryption Key (KEK).\n * \\param keybits   The KEK size in bits. This must be acceptable by the cipher.\n * \\param is_wrap   Specify whether the operation within the context is wrapping or unwrapping\n *\n * \\return          \\c 0 on success.\n * \\return          \\c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for any invalid input.\n * \\return          \\c MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE for 128-bit block ciphers\n *                  which are not supported.\n * \\return          cipher-specific error code on failure of the underlying cipher.\n */\nint mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx,\n                           mbedtls_cipher_id_t cipher,\n                           const unsigned char *key,\n                           unsigned int keybits,\n                           const int is_wrap);\n\n/**\n * \\brief   This function releases and clears the specified key wrapping context\n *          and underlying cipher sub-context.\n *\n * \\param ctx       The key wrapping context to clear.\n */\nvoid mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx);\n\n/**\n * \\brief           This function encrypts a buffer using key wrapping.\n *\n * \\param ctx       The key wrapping context to use for encryption.\n * \\param mode      The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP)\n * \\param input     The buffer holding the input data.\n * \\param in_len    The length of the input data in Bytes.\n *                  The input uses units of 8 Bytes called semiblocks.\n *                  <ul><li>For KW mode: a multiple of 8 bytes between 16 and 2^57-8 inclusive. </li>\n *                  <li>For KWP mode: any length between 1 and 2^32-1 inclusive.</li></ul>\n * \\param[out] output    The buffer holding the output data.\n *                  <ul><li>For KW mode: Must be at least 8 bytes larger than \\p in_len.</li>\n *                  <li>For KWP mode: Must be at least 8 bytes larger rounded up to a multiple of\n *                  8 bytes for KWP (15 bytes at most).</li></ul>\n * \\param[out] out_len The number of bytes written to the output buffer. \\c 0 on failure.\n * \\param[in] out_size The capacity of the output buffer.\n *\n * \\return          \\c 0 on success.\n * \\return          \\c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length.\n * \\return          cipher-specific error code on failure of the underlying cipher.\n */\nint mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode,\n                         const unsigned char *input, size_t in_len,\n                         unsigned char *output, size_t *out_len, size_t out_size);\n\n/**\n * \\brief           This function decrypts a buffer using key wrapping.\n *\n * \\param ctx       The key wrapping context to use for decryption.\n * \\param mode      The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP)\n * \\param input     The buffer holding the input data.\n * \\param in_len    The length of the input data in Bytes.\n *                  The input uses units of 8 Bytes called semiblocks.\n *                  The input must be a multiple of semiblocks.\n *                  <ul><li>For KW mode: a multiple of 8 bytes between 24 and 2^57 inclusive. </li>\n *                  <li>For KWP mode: a multiple of 8 bytes between 16 and 2^32 inclusive.</li></ul>\n * \\param[out] output    The buffer holding the output data.\n *                  The output buffer's minimal length is 8 bytes shorter than \\p in_len.\n * \\param[out] out_len The number of bytes written to the output buffer. \\c 0 on failure.\n *                  For KWP mode, the length could be up to 15 bytes shorter than \\p in_len,\n *                  depending on how much padding was added to the data.\n * \\param[in] out_size The capacity of the output buffer.\n *\n * \\return          \\c 0 on success.\n * \\return          \\c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length.\n * \\return          \\c MBEDTLS_ERR_CIPHER_AUTH_FAILED for verification failure of the ciphertext.\n * \\return          cipher-specific error code on failure of the underlying cipher.\n */\nint mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode,\n                           const unsigned char *input, size_t in_len,\n                           unsigned char *output, size_t *out_len, size_t out_size);\n\n\n#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)\n/**\n * \\brief          The key wrapping checkup routine.\n *\n * \\return         \\c 0 on success.\n * \\return         \\c 1 on failure.\n */\nint mbedtls_nist_kw_self_test(int verbose);\n#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_NIST_KW_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/oid.h",
    "content": "/**\n * \\file oid.h\n *\n * \\brief Object Identifier (OID) database\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_OID_H\n#define MBEDTLS_OID_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/asn1.h\"\n#include \"mbedtls/pk.h\"\n\n#include <stddef.h>\n\n#if defined(MBEDTLS_CIPHER_C)\n#include \"mbedtls/cipher.h\"\n#endif\n\n#include \"mbedtls/md.h\"\n\n/** OID is not found. */\n#define MBEDTLS_ERR_OID_NOT_FOUND                         -0x002E\n/** output buffer is too small */\n#define MBEDTLS_ERR_OID_BUF_TOO_SMALL                     -0x000B\n\n/* This is for the benefit of X.509, but defined here in order to avoid\n * having a \"backwards\" include of x.509.h here */\n/*\n * X.509 extension types (internal, arbitrary values for bitsets)\n */\n#define MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER    (1 << 0)\n#define MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER      (1 << 1)\n#define MBEDTLS_OID_X509_EXT_KEY_USAGE                   (1 << 2)\n#define MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES        (1 << 3)\n#define MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS             (1 << 4)\n#define MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME            (1 << 5)\n#define MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME             (1 << 6)\n#define MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS     (1 << 7)\n#define MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS           (1 << 8)\n#define MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS            (1 << 9)\n#define MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS          (1 << 10)\n#define MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE          (1 << 11)\n#define MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS     (1 << 12)\n#define MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY          (1 << 13)\n#define MBEDTLS_OID_X509_EXT_FRESHEST_CRL                (1 << 14)\n#define MBEDTLS_OID_X509_EXT_NS_CERT_TYPE                (1 << 16)\n\n/*\n * Maximum number of OID components allowed\n */\n#define MBEDTLS_OID_MAX_COMPONENTS              128\n\n/*\n * Top level OID tuples\n */\n#define MBEDTLS_OID_ISO_MEMBER_BODIES           \"\\x2a\"          /* {iso(1) member-body(2)} */\n#define MBEDTLS_OID_ISO_IDENTIFIED_ORG          \"\\x2b\"          /* {iso(1) identified-organization(3)} */\n#define MBEDTLS_OID_ISO_CCITT_DS                \"\\x55\"          /* {joint-iso-ccitt(2) ds(5)} */\n#define MBEDTLS_OID_ISO_ITU_COUNTRY             \"\\x60\"          /* {joint-iso-itu-t(2) country(16)} */\n\n/*\n * ISO Member bodies OID parts\n */\n#define MBEDTLS_OID_COUNTRY_US                  \"\\x86\\x48\"      /* {us(840)} */\n#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY       \"\\x86\\xf7\\x0d\"  /* {rsadsi(113549)} */\n#define MBEDTLS_OID_RSA_COMPANY                 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \\\n        MBEDTLS_OID_ORG_RSA_DATA_SECURITY                                 /* {iso(1) member-body(2) us(840) rsadsi(113549)} */\n#define MBEDTLS_OID_ORG_ANSI_X9_62              \"\\xce\\x3d\" /* ansi-X9-62(10045) */\n#define MBEDTLS_OID_ANSI_X9_62                  MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \\\n        MBEDTLS_OID_ORG_ANSI_X9_62\n\n/*\n * ISO Identified organization OID parts\n */\n#define MBEDTLS_OID_ORG_DOD                     \"\\x06\"          /* {dod(6)} */\n#define MBEDTLS_OID_ORG_OIW                     \"\\x0e\"\n#define MBEDTLS_OID_OIW_SECSIG                  MBEDTLS_OID_ORG_OIW \"\\x03\"\n#define MBEDTLS_OID_OIW_SECSIG_ALG              MBEDTLS_OID_OIW_SECSIG \"\\x02\"\n#define MBEDTLS_OID_OIW_SECSIG_SHA1             MBEDTLS_OID_OIW_SECSIG_ALG \"\\x1a\"\n#define MBEDTLS_OID_ORG_THAWTE                  \"\\x65\"          /* thawte(101) */\n#define MBEDTLS_OID_THAWTE                      MBEDTLS_OID_ISO_IDENTIFIED_ORG \\\n        MBEDTLS_OID_ORG_THAWTE\n#define MBEDTLS_OID_ORG_CERTICOM                \"\\x81\\x04\"  /* certicom(132) */\n#define MBEDTLS_OID_CERTICOM                    MBEDTLS_OID_ISO_IDENTIFIED_ORG \\\n        MBEDTLS_OID_ORG_CERTICOM\n#define MBEDTLS_OID_ORG_TELETRUST               \"\\x24\" /* teletrust(36) */\n#define MBEDTLS_OID_TELETRUST                   MBEDTLS_OID_ISO_IDENTIFIED_ORG \\\n        MBEDTLS_OID_ORG_TELETRUST\n\n/*\n * ISO ITU OID parts\n */\n#define MBEDTLS_OID_ORGANIZATION                \"\\x01\"          /* {organization(1)} */\n#define MBEDTLS_OID_ISO_ITU_US_ORG              MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US \\\n        MBEDTLS_OID_ORGANIZATION                                                                                            /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */\n\n#define MBEDTLS_OID_ORG_GOV                     \"\\x65\"          /* {gov(101)} */\n#define MBEDTLS_OID_GOV                         MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */\n\n#define MBEDTLS_OID_ORG_NETSCAPE                \"\\x86\\xF8\\x42\"  /* {netscape(113730)} */\n#define MBEDTLS_OID_NETSCAPE                    MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */\n\n/* ISO arc for standard certificate and CRL extensions */\n#define MBEDTLS_OID_ID_CE                       MBEDTLS_OID_ISO_CCITT_DS \"\\x1D\" /**< id-ce OBJECT IDENTIFIER  ::=  {joint-iso-ccitt(2) ds(5) 29} */\n\n#define MBEDTLS_OID_NIST_ALG                    MBEDTLS_OID_GOV \"\\x03\\x04\" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */\n\n/**\n * Private Internet Extensions\n * { iso(1) identified-organization(3) dod(6) internet(1)\n *                      security(5) mechanisms(5) pkix(7) }\n */\n#define MBEDTLS_OID_INTERNET                    MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD \\\n    \"\\x01\"\n#define MBEDTLS_OID_PKIX                        MBEDTLS_OID_INTERNET \"\\x05\\x05\\x07\"\n\n/*\n * Arc for standard naming attributes\n */\n#define MBEDTLS_OID_AT                          MBEDTLS_OID_ISO_CCITT_DS \"\\x04\" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */\n#define MBEDTLS_OID_AT_CN                       MBEDTLS_OID_AT \"\\x03\" /**< id-at-commonName AttributeType:= {id-at 3} */\n#define MBEDTLS_OID_AT_SUR_NAME                 MBEDTLS_OID_AT \"\\x04\" /**< id-at-surName AttributeType:= {id-at 4} */\n#define MBEDTLS_OID_AT_SERIAL_NUMBER            MBEDTLS_OID_AT \"\\x05\" /**< id-at-serialNumber AttributeType:= {id-at 5} */\n#define MBEDTLS_OID_AT_COUNTRY                  MBEDTLS_OID_AT \"\\x06\" /**< id-at-countryName AttributeType:= {id-at 6} */\n#define MBEDTLS_OID_AT_LOCALITY                 MBEDTLS_OID_AT \"\\x07\" /**< id-at-locality AttributeType:= {id-at 7} */\n#define MBEDTLS_OID_AT_STATE                    MBEDTLS_OID_AT \"\\x08\" /**< id-at-state AttributeType:= {id-at 8} */\n#define MBEDTLS_OID_AT_ORGANIZATION             MBEDTLS_OID_AT \"\\x0A\" /**< id-at-organizationName AttributeType:= {id-at 10} */\n#define MBEDTLS_OID_AT_ORG_UNIT                 MBEDTLS_OID_AT \"\\x0B\" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */\n#define MBEDTLS_OID_AT_TITLE                    MBEDTLS_OID_AT \"\\x0C\" /**< id-at-title AttributeType:= {id-at 12} */\n#define MBEDTLS_OID_AT_POSTAL_ADDRESS           MBEDTLS_OID_AT \"\\x10\" /**< id-at-postalAddress AttributeType:= {id-at 16} */\n#define MBEDTLS_OID_AT_POSTAL_CODE              MBEDTLS_OID_AT \"\\x11\" /**< id-at-postalCode AttributeType:= {id-at 17} */\n#define MBEDTLS_OID_AT_GIVEN_NAME               MBEDTLS_OID_AT \"\\x2A\" /**< id-at-givenName AttributeType:= {id-at 42} */\n#define MBEDTLS_OID_AT_INITIALS                 MBEDTLS_OID_AT \"\\x2B\" /**< id-at-initials AttributeType:= {id-at 43} */\n#define MBEDTLS_OID_AT_GENERATION_QUALIFIER     MBEDTLS_OID_AT \"\\x2C\" /**< id-at-generationQualifier AttributeType:= {id-at 44} */\n#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER        MBEDTLS_OID_AT \"\\x2D\" /**< id-at-uniqueIdentifier AttributeType:= {id-at 45} */\n#define MBEDTLS_OID_AT_DN_QUALIFIER             MBEDTLS_OID_AT \"\\x2E\" /**< id-at-dnQualifier AttributeType:= {id-at 46} */\n#define MBEDTLS_OID_AT_PSEUDONYM                MBEDTLS_OID_AT \"\\x41\" /**< id-at-pseudonym AttributeType:= {id-at 65} */\n\n#define MBEDTLS_OID_UID                         \"\\x09\\x92\\x26\\x89\\x93\\xF2\\x2C\\x64\\x01\\x01\" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) uid(1)} */\n#define MBEDTLS_OID_DOMAIN_COMPONENT            \"\\x09\\x92\\x26\\x89\\x93\\xF2\\x2C\\x64\\x01\\x19\" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */\n\n/*\n * OIDs for standard certificate extensions\n */\n#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER    MBEDTLS_OID_ID_CE \"\\x23\" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 } */\n#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER      MBEDTLS_OID_ID_CE \"\\x0E\" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 14 } */\n#define MBEDTLS_OID_KEY_USAGE                   MBEDTLS_OID_ID_CE \"\\x0F\" /**< id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 } */\n#define MBEDTLS_OID_CERTIFICATE_POLICIES        MBEDTLS_OID_ID_CE \"\\x20\" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::=  { id-ce 32 } */\n#define MBEDTLS_OID_POLICY_MAPPINGS             MBEDTLS_OID_ID_CE \"\\x21\" /**< id-ce-policyMappings OBJECT IDENTIFIER ::=  { id-ce 33 } */\n#define MBEDTLS_OID_SUBJECT_ALT_NAME            MBEDTLS_OID_ID_CE \"\\x11\" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::=  { id-ce 17 } */\n#define MBEDTLS_OID_ISSUER_ALT_NAME             MBEDTLS_OID_ID_CE \"\\x12\" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::=  { id-ce 18 } */\n#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS     MBEDTLS_OID_ID_CE \"\\x09\" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::=  { id-ce 9 } */\n#define MBEDTLS_OID_BASIC_CONSTRAINTS           MBEDTLS_OID_ID_CE \"\\x13\" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::=  { id-ce 19 } */\n#define MBEDTLS_OID_NAME_CONSTRAINTS            MBEDTLS_OID_ID_CE \"\\x1E\" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::=  { id-ce 30 } */\n#define MBEDTLS_OID_POLICY_CONSTRAINTS          MBEDTLS_OID_ID_CE \"\\x24\" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::=  { id-ce 36 } */\n#define MBEDTLS_OID_EXTENDED_KEY_USAGE          MBEDTLS_OID_ID_CE \"\\x25\" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */\n#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS     MBEDTLS_OID_ID_CE \"\\x1F\" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::=  { id-ce 31 } */\n#define MBEDTLS_OID_INIHIBIT_ANYPOLICY          MBEDTLS_OID_ID_CE \"\\x36\" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::=  { id-ce 54 } */\n#define MBEDTLS_OID_FRESHEST_CRL                MBEDTLS_OID_ID_CE \"\\x2E\" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::=  { id-ce 46 } */\n\n/*\n * Certificate policies\n */\n#define MBEDTLS_OID_ANY_POLICY              MBEDTLS_OID_CERTIFICATE_POLICIES \"\\x00\" /**< anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } */\n\n/*\n * Netscape certificate extensions\n */\n#define MBEDTLS_OID_NS_CERT                 MBEDTLS_OID_NETSCAPE \"\\x01\"\n#define MBEDTLS_OID_NS_CERT_TYPE            MBEDTLS_OID_NS_CERT  \"\\x01\"\n#define MBEDTLS_OID_NS_BASE_URL             MBEDTLS_OID_NS_CERT  \"\\x02\"\n#define MBEDTLS_OID_NS_REVOCATION_URL       MBEDTLS_OID_NS_CERT  \"\\x03\"\n#define MBEDTLS_OID_NS_CA_REVOCATION_URL    MBEDTLS_OID_NS_CERT  \"\\x04\"\n#define MBEDTLS_OID_NS_RENEWAL_URL          MBEDTLS_OID_NS_CERT  \"\\x07\"\n#define MBEDTLS_OID_NS_CA_POLICY_URL        MBEDTLS_OID_NS_CERT  \"\\x08\"\n#define MBEDTLS_OID_NS_SSL_SERVER_NAME      MBEDTLS_OID_NS_CERT  \"\\x0C\"\n#define MBEDTLS_OID_NS_COMMENT              MBEDTLS_OID_NS_CERT  \"\\x0D\"\n#define MBEDTLS_OID_NS_DATA_TYPE            MBEDTLS_OID_NETSCAPE \"\\x02\"\n#define MBEDTLS_OID_NS_CERT_SEQUENCE        MBEDTLS_OID_NS_DATA_TYPE \"\\x05\"\n\n/*\n * OIDs for CRL extensions\n */\n#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD    MBEDTLS_OID_ID_CE \"\\x10\"\n#define MBEDTLS_OID_CRL_NUMBER                  MBEDTLS_OID_ID_CE \"\\x14\" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */\n\n/*\n * X.509 v3 Extended key usage OIDs\n */\n#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE      MBEDTLS_OID_EXTENDED_KEY_USAGE \"\\x00\" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */\n\n#define MBEDTLS_OID_KP                          MBEDTLS_OID_PKIX \"\\x03\" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */\n#define MBEDTLS_OID_SERVER_AUTH                 MBEDTLS_OID_KP \"\\x01\" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */\n#define MBEDTLS_OID_CLIENT_AUTH                 MBEDTLS_OID_KP \"\\x02\" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */\n#define MBEDTLS_OID_CODE_SIGNING                MBEDTLS_OID_KP \"\\x03\" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */\n#define MBEDTLS_OID_EMAIL_PROTECTION            MBEDTLS_OID_KP \"\\x04\" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */\n#define MBEDTLS_OID_TIME_STAMPING               MBEDTLS_OID_KP \"\\x08\" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */\n#define MBEDTLS_OID_OCSP_SIGNING                MBEDTLS_OID_KP \"\\x09\" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */\n\n/**\n * Wi-SUN Alliance Field Area Network\n * { iso(1) identified-organization(3) dod(6) internet(1)\n *                      private(4) enterprise(1) WiSUN(45605) FieldAreaNetwork(1) }\n */\n#define MBEDTLS_OID_WISUN_FAN                   MBEDTLS_OID_INTERNET \"\\x04\\x01\\x82\\xe4\\x25\\x01\"\n\n#define MBEDTLS_OID_ON                          MBEDTLS_OID_PKIX \"\\x08\" /**< id-on OBJECT IDENTIFIER ::= { id-pkix 8 } */\n#define MBEDTLS_OID_ON_HW_MODULE_NAME           MBEDTLS_OID_ON \"\\x04\" /**< id-on-hardwareModuleName OBJECT IDENTIFIER ::= { id-on 4 } */\n\n/*\n * PKCS definition OIDs\n */\n\n#define MBEDTLS_OID_PKCS                MBEDTLS_OID_RSA_COMPANY \"\\x01\" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */\n#define MBEDTLS_OID_PKCS1               MBEDTLS_OID_PKCS \"\\x01\" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */\n#define MBEDTLS_OID_PKCS5               MBEDTLS_OID_PKCS \"\\x05\" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */\n#define MBEDTLS_OID_PKCS7               MBEDTLS_OID_PKCS \"\\x07\" /**< pkcs-7 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 } */\n#define MBEDTLS_OID_PKCS9               MBEDTLS_OID_PKCS \"\\x09\" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */\n#define MBEDTLS_OID_PKCS12              MBEDTLS_OID_PKCS \"\\x0c\" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */\n\n/*\n * PKCS#1 OIDs\n */\n#define MBEDTLS_OID_PKCS1_RSA           MBEDTLS_OID_PKCS1 \"\\x01\" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */\n#define MBEDTLS_OID_PKCS1_MD5           MBEDTLS_OID_PKCS1 \"\\x04\" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */\n#define MBEDTLS_OID_PKCS1_SHA1          MBEDTLS_OID_PKCS1 \"\\x05\" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */\n#define MBEDTLS_OID_PKCS1_SHA224        MBEDTLS_OID_PKCS1 \"\\x0e\" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */\n#define MBEDTLS_OID_PKCS1_SHA256        MBEDTLS_OID_PKCS1 \"\\x0b\" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */\n#define MBEDTLS_OID_PKCS1_SHA384        MBEDTLS_OID_PKCS1 \"\\x0c\" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */\n#define MBEDTLS_OID_PKCS1_SHA512        MBEDTLS_OID_PKCS1 \"\\x0d\" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */\n\n#define MBEDTLS_OID_RSA_SHA_OBS         \"\\x2B\\x0E\\x03\\x02\\x1D\"\n\n#define MBEDTLS_OID_PKCS9_EMAIL         MBEDTLS_OID_PKCS9 \"\\x01\" /**< emailAddress AttributeType ::= { pkcs-9 1 } */\n\n/* RFC 4055 */\n#define MBEDTLS_OID_RSASSA_PSS          MBEDTLS_OID_PKCS1 \"\\x0a\" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */\n#define MBEDTLS_OID_MGF1                MBEDTLS_OID_PKCS1 \"\\x08\" /**< id-mgf1 ::= { pkcs-1 8 } */\n\n/*\n * Digest algorithms\n */\n#define MBEDTLS_OID_DIGEST_ALG_MD5              MBEDTLS_OID_RSA_COMPANY \"\\x02\\x05\" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */\n#define MBEDTLS_OID_DIGEST_ALG_SHA1             MBEDTLS_OID_ISO_IDENTIFIED_ORG \\\n        MBEDTLS_OID_OIW_SECSIG_SHA1                                                                        /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */\n#define MBEDTLS_OID_DIGEST_ALG_SHA224           MBEDTLS_OID_NIST_ALG \"\\x02\\x04\" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */\n#define MBEDTLS_OID_DIGEST_ALG_SHA256           MBEDTLS_OID_NIST_ALG \"\\x02\\x01\" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */\n\n#define MBEDTLS_OID_DIGEST_ALG_SHA384           MBEDTLS_OID_NIST_ALG \"\\x02\\x02\" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */\n\n#define MBEDTLS_OID_DIGEST_ALG_SHA512           MBEDTLS_OID_NIST_ALG \"\\x02\\x03\" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */\n\n#define MBEDTLS_OID_DIGEST_ALG_RIPEMD160        MBEDTLS_OID_TELETRUST \"\\x03\\x02\\x01\" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) identified-organization(3) teletrust(36) algorithm(3) hashAlgorithm(2) ripemd160(1) } */\n\n#define MBEDTLS_OID_DIGEST_ALG_SHA3_224         MBEDTLS_OID_NIST_ALG \"\\x02\\x07\" /**< id-sha3-224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-224(7) } */\n\n#define MBEDTLS_OID_DIGEST_ALG_SHA3_256         MBEDTLS_OID_NIST_ALG \"\\x02\\x08\" /**< id-sha3-256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-256(8) } */\n\n#define MBEDTLS_OID_DIGEST_ALG_SHA3_384         MBEDTLS_OID_NIST_ALG \"\\x02\\x09\" /**< id-sha3-384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-384(9) } */\n\n#define MBEDTLS_OID_DIGEST_ALG_SHA3_512         MBEDTLS_OID_NIST_ALG \"\\x02\\x0a\" /**< id-sha3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-512(10) } */\n\n\n#define MBEDTLS_OID_HMAC_SHA1                   MBEDTLS_OID_RSA_COMPANY \"\\x02\\x07\" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */\n\n#define MBEDTLS_OID_HMAC_SHA224                 MBEDTLS_OID_RSA_COMPANY \"\\x02\\x08\" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */\n\n#define MBEDTLS_OID_HMAC_SHA256                 MBEDTLS_OID_RSA_COMPANY \"\\x02\\x09\" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */\n\n#define MBEDTLS_OID_HMAC_SHA384                 MBEDTLS_OID_RSA_COMPANY \"\\x02\\x0A\" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */\n\n#define MBEDTLS_OID_HMAC_SHA512                 MBEDTLS_OID_RSA_COMPANY \"\\x02\\x0B\" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */\n\n#define MBEDTLS_OID_HMAC_SHA3_224               MBEDTLS_OID_NIST_ALG \"\\x02\\x0d\" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-224(13) } */\n\n#define MBEDTLS_OID_HMAC_SHA3_256               MBEDTLS_OID_NIST_ALG \"\\x02\\x0e\" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-256(14) } */\n\n#define MBEDTLS_OID_HMAC_SHA3_384               MBEDTLS_OID_NIST_ALG \"\\x02\\x0f\" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-384(15) } */\n\n#define MBEDTLS_OID_HMAC_SHA3_512               MBEDTLS_OID_NIST_ALG \"\\x02\\x10\" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-512(16) } */\n\n#define MBEDTLS_OID_HMAC_RIPEMD160              MBEDTLS_OID_INTERNET \"\\x05\\x05\\x08\\x01\\x04\" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= {iso(1) iso-identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ipsec(8) isakmpOakley(1) hmacRIPEMD160(4)} */\n\n/*\n * Encryption algorithms,\n * the following standardized object identifiers are specified at\n * https://datatracker.ietf.org/doc/html/rfc8018#appendix-C.\n */\n#define MBEDTLS_OID_DES_CBC                     MBEDTLS_OID_ISO_IDENTIFIED_ORG \\\n        MBEDTLS_OID_OIW_SECSIG_ALG \"\\x07\"                                                                        /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */\n#define MBEDTLS_OID_DES_EDE3_CBC                MBEDTLS_OID_RSA_COMPANY \"\\x03\\x07\" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */\n#define MBEDTLS_OID_AES                         MBEDTLS_OID_NIST_ALG \"\\x01\" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */\n#define MBEDTLS_OID_AES_128_CBC                 MBEDTLS_OID_AES \"\\x02\" /** aes128-cbc-pad OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) aes(1) aes128-CBC-PAD(2) } */\n#define MBEDTLS_OID_AES_192_CBC                 MBEDTLS_OID_AES \"\\x16\" /** aes192-cbc-pad OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) aes(1) aes192-CBC-PAD(22) } */\n#define MBEDTLS_OID_AES_256_CBC                 MBEDTLS_OID_AES \"\\x2a\" /** aes256-cbc-pad OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) aes(1) aes256-CBC-PAD(42) } */\n\n/*\n * Key Wrapping algorithms\n */\n/*\n * RFC 5649\n */\n#define MBEDTLS_OID_AES128_KW                   MBEDTLS_OID_AES \"\\x05\" /** id-aes128-wrap     OBJECT IDENTIFIER ::= { aes 5 } */\n#define MBEDTLS_OID_AES128_KWP                  MBEDTLS_OID_AES \"\\x08\" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */\n#define MBEDTLS_OID_AES192_KW                   MBEDTLS_OID_AES \"\\x19\" /** id-aes192-wrap     OBJECT IDENTIFIER ::= { aes 25 } */\n#define MBEDTLS_OID_AES192_KWP                  MBEDTLS_OID_AES \"\\x1c\" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */\n#define MBEDTLS_OID_AES256_KW                   MBEDTLS_OID_AES \"\\x2d\" /** id-aes256-wrap     OBJECT IDENTIFIER ::= { aes 45 } */\n#define MBEDTLS_OID_AES256_KWP                  MBEDTLS_OID_AES \"\\x30\" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */\n/*\n * PKCS#5 OIDs\n */\n#define MBEDTLS_OID_PKCS5_PBKDF2                MBEDTLS_OID_PKCS5 \"\\x0c\" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */\n#define MBEDTLS_OID_PKCS5_PBES2                 MBEDTLS_OID_PKCS5 \"\\x0d\" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */\n#define MBEDTLS_OID_PKCS5_PBMAC1                MBEDTLS_OID_PKCS5 \"\\x0e\" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */\n\n/*\n * PKCS#5 PBES1 algorithms\n */\n#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC       MBEDTLS_OID_PKCS5 \"\\x03\" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */\n#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC       MBEDTLS_OID_PKCS5 \"\\x06\" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */\n#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC      MBEDTLS_OID_PKCS5 \"\\x0a\" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */\n#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC      MBEDTLS_OID_PKCS5 \"\\x0b\" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */\n\n/*\n * PKCS#7 OIDs\n */\n#define MBEDTLS_OID_PKCS7_DATA                        MBEDTLS_OID_PKCS7 \"\\x01\" /**< Content type is Data OBJECT IDENTIFIER ::= {pkcs-7 1} */\n#define MBEDTLS_OID_PKCS7_SIGNED_DATA                 MBEDTLS_OID_PKCS7 \"\\x02\" /**< Content type is Signed Data OBJECT IDENTIFIER ::= {pkcs-7 2} */\n#define MBEDTLS_OID_PKCS7_ENVELOPED_DATA              MBEDTLS_OID_PKCS7 \"\\x03\" /**< Content type is Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 3} */\n#define MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA   MBEDTLS_OID_PKCS7 \"\\x04\" /**< Content type is Signed and Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 4} */\n#define MBEDTLS_OID_PKCS7_DIGESTED_DATA               MBEDTLS_OID_PKCS7 \"\\x05\" /**< Content type is Digested Data OBJECT IDENTIFIER ::= {pkcs-7 5} */\n#define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA              MBEDTLS_OID_PKCS7 \"\\x06\" /**< Content type is Encrypted Data OBJECT IDENTIFIER ::= {pkcs-7 6} */\n\n/*\n * PKCS#8 OIDs\n */\n#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ           MBEDTLS_OID_PKCS9 \"\\x0e\" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */\n\n/*\n * PKCS#12 PBE OIDs\n */\n#define MBEDTLS_OID_PKCS12_PBE                      MBEDTLS_OID_PKCS12 \"\\x01\" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */\n\n#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC    MBEDTLS_OID_PKCS12_PBE \"\\x03\" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */\n#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC    MBEDTLS_OID_PKCS12_PBE \"\\x04\" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */\n#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC     MBEDTLS_OID_PKCS12_PBE \"\\x05\" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */\n#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC      MBEDTLS_OID_PKCS12_PBE \"\\x06\" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */\n\n/*\n * EC key algorithms from RFC 5480\n */\n\n/* id-ecPublicKey OBJECT IDENTIFIER ::= {\n *       iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */\n#define MBEDTLS_OID_EC_ALG_UNRESTRICTED         MBEDTLS_OID_ANSI_X9_62 \"\\x02\\01\"\n\n/*   id-ecDH OBJECT IDENTIFIER ::= {\n *     iso(1) identified-organization(3) certicom(132)\n *     schemes(1) ecdh(12) } */\n#define MBEDTLS_OID_EC_ALG_ECDH                 MBEDTLS_OID_CERTICOM \"\\x01\\x0c\"\n\n/*\n * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2\n */\n\n/* secp192r1 OBJECT IDENTIFIER ::= {\n *   iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */\n#define MBEDTLS_OID_EC_GRP_SECP192R1        MBEDTLS_OID_ANSI_X9_62 \"\\x03\\x01\\x01\"\n\n/* secp224r1 OBJECT IDENTIFIER ::= {\n *   iso(1) identified-organization(3) certicom(132) curve(0) 33 } */\n#define MBEDTLS_OID_EC_GRP_SECP224R1        MBEDTLS_OID_CERTICOM \"\\x00\\x21\"\n\n/* secp256r1 OBJECT IDENTIFIER ::= {\n *   iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */\n#define MBEDTLS_OID_EC_GRP_SECP256R1        MBEDTLS_OID_ANSI_X9_62 \"\\x03\\x01\\x07\"\n\n/* secp384r1 OBJECT IDENTIFIER ::= {\n *   iso(1) identified-organization(3) certicom(132) curve(0) 34 } */\n#define MBEDTLS_OID_EC_GRP_SECP384R1        MBEDTLS_OID_CERTICOM \"\\x00\\x22\"\n\n/* secp521r1 OBJECT IDENTIFIER ::= {\n *   iso(1) identified-organization(3) certicom(132) curve(0) 35 } */\n#define MBEDTLS_OID_EC_GRP_SECP521R1        MBEDTLS_OID_CERTICOM \"\\x00\\x23\"\n\n/* secp192k1 OBJECT IDENTIFIER ::= {\n *   iso(1) identified-organization(3) certicom(132) curve(0) 31 } */\n#define MBEDTLS_OID_EC_GRP_SECP192K1        MBEDTLS_OID_CERTICOM \"\\x00\\x1f\"\n\n/* secp224k1 OBJECT IDENTIFIER ::= {\n *   iso(1) identified-organization(3) certicom(132) curve(0) 32 } */\n#define MBEDTLS_OID_EC_GRP_SECP224K1        MBEDTLS_OID_CERTICOM \"\\x00\\x20\"\n\n/* secp256k1 OBJECT IDENTIFIER ::= {\n *   iso(1) identified-organization(3) certicom(132) curve(0) 10 } */\n#define MBEDTLS_OID_EC_GRP_SECP256K1        MBEDTLS_OID_CERTICOM \"\\x00\\x0a\"\n\n/* RFC 5639 4.1\n * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1)\n * identified-organization(3) teletrust(36) algorithm(3) signature-\n * algorithm(3) ecSign(2) 8}\n * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1}\n * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */\n#define MBEDTLS_OID_EC_BRAINPOOL_V1         MBEDTLS_OID_TELETRUST \"\\x03\\x03\\x02\\x08\\x01\\x01\"\n\n/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */\n#define MBEDTLS_OID_EC_GRP_BP256R1          MBEDTLS_OID_EC_BRAINPOOL_V1 \"\\x07\"\n\n/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */\n#define MBEDTLS_OID_EC_GRP_BP384R1          MBEDTLS_OID_EC_BRAINPOOL_V1 \"\\x0B\"\n\n/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */\n#define MBEDTLS_OID_EC_GRP_BP512R1          MBEDTLS_OID_EC_BRAINPOOL_V1 \"\\x0D\"\n\n/*\n * SEC1 C.1\n *\n * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }\n * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)}\n */\n#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE   MBEDTLS_OID_ANSI_X9_62 \"\\x01\"\n#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD  MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE \"\\x01\"\n\n/*\n * ECDSA signature identifiers, from RFC 5480\n */\n#define MBEDTLS_OID_ANSI_X9_62_SIG          MBEDTLS_OID_ANSI_X9_62 \"\\x04\" /* signatures(4) */\n#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2     MBEDTLS_OID_ANSI_X9_62_SIG \"\\x03\" /* ecdsa-with-SHA2(3) */\n\n/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {\n *   iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */\n#define MBEDTLS_OID_ECDSA_SHA1              MBEDTLS_OID_ANSI_X9_62_SIG \"\\x01\"\n\n/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= {\n *   iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)\n *   ecdsa-with-SHA2(3) 1 } */\n#define MBEDTLS_OID_ECDSA_SHA224            MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 \"\\x01\"\n\n/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= {\n *   iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)\n *   ecdsa-with-SHA2(3) 2 } */\n#define MBEDTLS_OID_ECDSA_SHA256            MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 \"\\x02\"\n\n/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= {\n *   iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)\n *   ecdsa-with-SHA2(3) 3 } */\n#define MBEDTLS_OID_ECDSA_SHA384            MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 \"\\x03\"\n\n/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= {\n *   iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)\n *   ecdsa-with-SHA2(3) 4 } */\n#define MBEDTLS_OID_ECDSA_SHA512            MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 \"\\x04\"\n\n/*\n * EC key algorithms from RFC 8410\n */\n\n#define MBEDTLS_OID_X25519                  MBEDTLS_OID_THAWTE \"\\x6e\" /**< id-X25519    OBJECT IDENTIFIER ::= { 1 3 101 110 } */\n#define MBEDTLS_OID_X448                    MBEDTLS_OID_THAWTE \"\\x6f\" /**< id-X448      OBJECT IDENTIFIER ::= { 1 3 101 111 } */\n#define MBEDTLS_OID_ED25519                 MBEDTLS_OID_THAWTE \"\\x70\" /**< id-Ed25519   OBJECT IDENTIFIER ::= { 1 3 101 112 } */\n#define MBEDTLS_OID_ED448                   MBEDTLS_OID_THAWTE \"\\x71\" /**< id-Ed448     OBJECT IDENTIFIER ::= { 1 3 101 113 } */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief Base OID descriptor structure\n */\ntypedef struct mbedtls_oid_descriptor_t {\n    const char *MBEDTLS_PRIVATE(asn1);               /*!< OID ASN.1 representation       */\n    size_t MBEDTLS_PRIVATE(asn1_len);                /*!< length of asn1                 */\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\n    const char *MBEDTLS_PRIVATE(name);               /*!< official name (e.g. from RFC)  */\n    const char *MBEDTLS_PRIVATE(description);        /*!< human friendly description     */\n#endif\n} mbedtls_oid_descriptor_t;\n\n/**\n * \\brief           Translate an ASN.1 OID into its numeric representation\n *                  (e.g. \"\\x2A\\x86\\x48\\x86\\xF7\\x0D\" into \"1.2.840.113549\")\n *\n * \\param buf       buffer to put representation in\n * \\param size      size of the buffer\n * \\param oid       OID to translate\n *\n * \\return          Length of the string written (excluding final NULL) or\n *                  MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error\n */\nint mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid);\n\n/**\n * \\brief           Translate a string containing a dotted-decimal\n *                  representation of an ASN.1 OID into its encoded form\n *                  (e.g. \"1.2.840.113549\" into \"\\x2A\\x86\\x48\\x86\\xF7\\x0D\").\n *                  On success, this function allocates oid->buf from the\n *                  heap. It must be freed by the caller using mbedtls_free().\n *\n * \\param oid       #mbedtls_asn1_buf to populate with the DER-encoded OID\n * \\param oid_str   string representation of the OID to parse\n * \\param size      length of the OID string, not including any null terminator\n *\n * \\return          0 if successful\n * \\return          #MBEDTLS_ERR_ASN1_INVALID_DATA if \\p oid_str does not\n *                  represent a valid OID\n * \\return          #MBEDTLS_ERR_ASN1_ALLOC_FAILED if the function fails to\n *                  allocate oid->buf\n */\nint mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, const char *oid_str, size_t size);\n\n/**\n * \\brief          Translate an X.509 extension OID into local values\n *\n * \\param oid      OID to use\n * \\param ext_type place to store the extension type\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_x509_ext_type(const mbedtls_asn1_buf *oid, int *ext_type);\n\n/**\n * \\brief          Translate an X.509 attribute type OID into the short name\n *                 (e.g. the OID for an X520 Common Name into \"CN\")\n *\n * \\param oid      OID to use\n * \\param short_name    place to store the string pointer\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_attr_short_name(const mbedtls_asn1_buf *oid, const char **short_name);\n\n/**\n * \\brief          Translate PublicKeyAlgorithm OID into pk_type\n *\n * \\param oid      OID to use\n * \\param pk_alg   place to store public key algorithm\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_pk_alg(const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg);\n\n/**\n * \\brief          Translate pk_type into PublicKeyAlgorithm OID\n *\n * \\param pk_alg   Public key type to look for\n * \\param oid      place to store ASN.1 OID string pointer\n * \\param olen     length of the OID\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_oid_by_pk_alg(mbedtls_pk_type_t pk_alg,\n                                  const char **oid, size_t *olen);\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n/**\n * \\brief          Translate NamedCurve OID into an EC group identifier\n *\n * \\param oid      OID to use\n * \\param grp_id   place to store group id\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_ec_grp(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id);\n\n/**\n * \\brief          Translate EC group identifier into NamedCurve OID\n *\n * \\param grp_id   EC group identifier\n * \\param oid      place to store ASN.1 OID string pointer\n * \\param olen     length of the OID\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_oid_by_ec_grp(mbedtls_ecp_group_id grp_id,\n                                  const char **oid, size_t *olen);\n\n/**\n * \\brief          Translate AlgorithmIdentifier OID into an EC group identifier,\n *                 for curves that are directly encoded at this level\n *\n * \\param oid      OID to use\n * \\param grp_id   place to store group id\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_ec_grp_algid(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id);\n\n/**\n * \\brief          Translate EC group identifier into AlgorithmIdentifier OID,\n *                 for curves that are directly encoded at this level\n *\n * \\param grp_id   EC group identifier\n * \\param oid      place to store ASN.1 OID string pointer\n * \\param olen     length of the OID\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_oid_by_ec_grp_algid(mbedtls_ecp_group_id grp_id,\n                                        const char **oid, size_t *olen);\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n/**\n * \\brief          Translate SignatureAlgorithm OID into md_type and pk_type\n *\n * \\param oid      OID to use\n * \\param md_alg   place to store message digest algorithm\n * \\param pk_alg   place to store public key algorithm\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_sig_alg(const mbedtls_asn1_buf *oid,\n                            mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg);\n\n/**\n * \\brief          Translate SignatureAlgorithm OID into description\n *\n * \\param oid      OID to use\n * \\param desc     place to store string pointer\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_sig_alg_desc(const mbedtls_asn1_buf *oid, const char **desc);\n\n/**\n * \\brief          Translate md_type and pk_type into SignatureAlgorithm OID\n *\n * \\param md_alg   message digest algorithm\n * \\param pk_alg   public key algorithm\n * \\param oid      place to store ASN.1 OID string pointer\n * \\param olen     length of the OID\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_oid_by_sig_alg(mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,\n                                   const char **oid, size_t *olen);\n\n/**\n * \\brief          Translate hmac algorithm OID into md_type\n *\n * \\param oid      OID to use\n * \\param md_hmac  place to store message hmac algorithm\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_md_hmac(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac);\n\n/**\n * \\brief          Translate hash algorithm OID into md_type\n *\n * \\param oid      OID to use\n * \\param md_alg   place to store message digest algorithm\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_md_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg);\n\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\n/**\n * \\brief          Translate Extended Key Usage OID into description\n *\n * \\param oid      OID to use\n * \\param desc     place to store string pointer\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_extended_key_usage(const mbedtls_asn1_buf *oid, const char **desc);\n#endif\n\n/**\n * \\brief          Translate certificate policies OID into description\n *\n * \\param oid      OID to use\n * \\param desc     place to store string pointer\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_certificate_policies(const mbedtls_asn1_buf *oid, const char **desc);\n\n/**\n * \\brief          Translate md_type into hash algorithm OID\n *\n * \\param md_alg   message digest algorithm\n * \\param oid      place to store ASN.1 OID string pointer\n * \\param olen     length of the OID\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_oid_by_md(mbedtls_md_type_t md_alg, const char **oid, size_t *olen);\n\n#if defined(MBEDTLS_CIPHER_C)\n/**\n * \\brief          Translate encryption algorithm OID into cipher_type\n *\n * \\param oid           OID to use\n * \\param cipher_alg    place to store cipher algorithm\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_cipher_alg(const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg);\n\n#if defined(MBEDTLS_PKCS12_C)\n/**\n * \\brief          Translate PKCS#12 PBE algorithm OID into md_type and\n *                 cipher_type\n *\n * \\param oid           OID to use\n * \\param md_alg        place to store message digest algorithm\n * \\param cipher_alg    place to store cipher algorithm\n *\n * \\return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND\n */\nint mbedtls_oid_get_pkcs12_pbe_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg,\n                                   mbedtls_cipher_type_t *cipher_alg);\n#endif /* MBEDTLS_PKCS12_C */\n#endif /* MBEDTLS_CIPHER_C */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* oid.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/pem.h",
    "content": "/**\n * \\file pem.h\n *\n * \\brief Privacy Enhanced Mail (PEM) decoding\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_PEM_H\n#define MBEDTLS_PEM_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n\n/**\n * \\name PEM Error codes\n * These error codes are returned in case of errors reading the\n * PEM data.\n * \\{\n */\n/** No PEM header or footer found. */\n#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT          -0x1080\n/** PEM string is not as expected. */\n#define MBEDTLS_ERR_PEM_INVALID_DATA                      -0x1100\n/** Failed to allocate memory. */\n#define MBEDTLS_ERR_PEM_ALLOC_FAILED                      -0x1180\n/** RSA IV is not in hex-format. */\n#define MBEDTLS_ERR_PEM_INVALID_ENC_IV                    -0x1200\n/** Unsupported key encryption algorithm. */\n#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG                   -0x1280\n/** Private key password can't be empty. */\n#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED                 -0x1300\n/** Given private key password does not allow for correct decryption. */\n#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH                 -0x1380\n/** Unavailable feature, e.g. hashing/encryption combination. */\n#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE               -0x1400\n/** Bad input parameters to function. */\n#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA                    -0x1480\n/** \\} name PEM Error codes */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if defined(MBEDTLS_PEM_PARSE_C)\n/**\n * \\brief       PEM context structure\n */\ntypedef struct mbedtls_pem_context {\n    unsigned char *MBEDTLS_PRIVATE(buf);     /*!< buffer for decoded data             */\n    size_t MBEDTLS_PRIVATE(buflen);          /*!< length of the buffer                */\n    unsigned char *MBEDTLS_PRIVATE(info);    /*!< buffer for extra header information */\n}\nmbedtls_pem_context;\n\n/**\n * \\brief       PEM context setup\n *\n * \\param ctx   context to be initialized\n */\nvoid mbedtls_pem_init(mbedtls_pem_context *ctx);\n\n/**\n * \\brief       Read a buffer for PEM information and store the resulting\n *              data into the specified context buffers.\n *\n * \\param ctx       context to use\n * \\param header    header string to seek and expect\n * \\param footer    footer string to seek and expect\n * \\param data      source data to look in (must be nul-terminated)\n * \\param pwd       password for decryption (can be NULL)\n * \\param pwdlen    length of password\n * \\param use_len   destination for total length used from data buffer. It is\n *                  set after header is correctly read, so unless you get\n *                  MBEDTLS_ERR_PEM_BAD_INPUT_DATA or\n *                  MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is\n *                  the length to skip.\n *\n * \\note            Attempts to check password correctness by verifying if\n *                  the decrypted text starts with an ASN.1 sequence of\n *                  appropriate length\n *\n * \\note            \\c mbedtls_pem_free must be called on PEM context before\n *                  the PEM context can be reused in another call to\n *                  \\c mbedtls_pem_read_buffer\n *\n * \\return          0 on success, or a specific PEM error code\n */\nint mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer,\n                            const unsigned char *data,\n                            const unsigned char *pwd,\n                            size_t pwdlen, size_t *use_len);\n\n/**\n * \\brief       Get the pointer to the decoded binary data in a PEM context.\n *\n * \\param ctx       PEM context to access.\n * \\param buflen    On success, this will contain the length of the binary data.\n *                  This must be a valid (non-null) pointer.\n *\n * \\return          A pointer to the decoded binary data.\n *\n * \\note            The returned pointer remains valid only until \\p ctx is\n                    modified or freed.\n */\nstatic inline const unsigned char *mbedtls_pem_get_buffer(mbedtls_pem_context *ctx, size_t *buflen)\n{\n    *buflen = ctx->MBEDTLS_PRIVATE(buflen);\n    return ctx->MBEDTLS_PRIVATE(buf);\n}\n\n\n/**\n * \\brief       PEM context memory freeing\n *\n * \\param ctx   context to be freed\n */\nvoid mbedtls_pem_free(mbedtls_pem_context *ctx);\n#endif /* MBEDTLS_PEM_PARSE_C */\n\n#if defined(MBEDTLS_PEM_WRITE_C)\n/**\n * \\brief           Write a buffer of PEM information from a DER encoded\n *                  buffer.\n *\n * \\param header    The header string to write.\n * \\param footer    The footer string to write.\n * \\param der_data  The DER data to encode.\n * \\param der_len   The length of the DER data \\p der_data in Bytes.\n * \\param buf       The buffer to write to.\n * \\param buf_len   The length of the output buffer \\p buf in Bytes.\n * \\param olen      The address at which to store the total length written\n *                  or required (if \\p buf_len is not enough).\n *\n * \\note            You may pass \\c NULL for \\p buf and \\c 0 for \\p buf_len\n *                  to request the length of the resulting PEM buffer in\n *                  `*olen`.\n *\n * \\note            This function may be called with overlapping \\p der_data\n *                  and \\p buf buffers.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL if \\p buf isn't large\n *                  enough to hold the PEM buffer. In  this case, `*olen` holds\n *                  the required minimum size of \\p buf.\n * \\return          Another PEM or BASE64 error code on other kinds of failure.\n */\nint mbedtls_pem_write_buffer(const char *header, const char *footer,\n                             const unsigned char *der_data, size_t der_len,\n                             unsigned char *buf, size_t buf_len, size_t *olen);\n#endif /* MBEDTLS_PEM_WRITE_C */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* pem.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/pk.h",
    "content": "/**\n * \\file pk.h\n *\n * \\brief Public Key abstraction layer\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_PK_H\n#define MBEDTLS_PK_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/md.h\"\n\n#if defined(MBEDTLS_RSA_C)\n#include \"mbedtls/rsa.h\"\n#endif\n\n#if defined(MBEDTLS_ECP_C)\n#include \"mbedtls/ecp.h\"\n#endif\n\n#if defined(MBEDTLS_ECDSA_C)\n#include \"mbedtls/ecdsa.h\"\n#endif\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)\n#include \"psa/crypto.h\"\n#endif\n\n/** Memory allocation failed. */\n#define MBEDTLS_ERR_PK_ALLOC_FAILED        -0x3F80\n/** Type mismatch, eg attempt to encrypt with an ECDSA key */\n#define MBEDTLS_ERR_PK_TYPE_MISMATCH       -0x3F00\n/** Bad input parameters to function. */\n#define MBEDTLS_ERR_PK_BAD_INPUT_DATA      -0x3E80\n/** Read/write of file failed. */\n#define MBEDTLS_ERR_PK_FILE_IO_ERROR       -0x3E00\n/** Unsupported key version */\n#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80\n/** Invalid key tag or value. */\n#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT  -0x3D00\n/** Key algorithm is unsupported (only RSA and EC are supported). */\n#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG      -0x3C80\n/** Private key password can't be empty. */\n#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED   -0x3C00\n/** Given private key password does not allow for correct decryption. */\n#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH   -0x3B80\n/** The pubkey tag or value is invalid (only RSA and EC are supported). */\n#define MBEDTLS_ERR_PK_INVALID_PUBKEY      -0x3B00\n/** The algorithm tag or value is invalid. */\n#define MBEDTLS_ERR_PK_INVALID_ALG         -0x3A80\n/** Elliptic curve is unsupported (only NIST curves are supported). */\n#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00\n/** Unavailable feature, e.g. RSA disabled for RSA key. */\n#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980\n/** The buffer contains a valid signature followed by more data. */\n#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH    -0x3900\n/** The output buffer is too small. */\n#define MBEDTLS_ERR_PK_BUFFER_TOO_SMALL    -0x3880\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief          Public key types\n */\ntypedef enum {\n    MBEDTLS_PK_NONE=0,\n    MBEDTLS_PK_RSA,\n    MBEDTLS_PK_ECKEY,\n    MBEDTLS_PK_ECKEY_DH,\n    MBEDTLS_PK_ECDSA,\n    MBEDTLS_PK_RSA_ALT,\n    MBEDTLS_PK_RSASSA_PSS,\n    MBEDTLS_PK_OPAQUE,\n} mbedtls_pk_type_t;\n\n/**\n * \\brief           Options for RSASSA-PSS signature verification.\n *                  See \\c mbedtls_rsa_rsassa_pss_verify_ext()\n */\ntypedef struct mbedtls_pk_rsassa_pss_options {\n    /** The digest to use for MGF1 in PSS.\n     *\n     * \\note When #MBEDTLS_USE_PSA_CRYPTO is enabled and #MBEDTLS_RSA_C is\n     *       disabled, this must be equal to the \\c md_alg argument passed\n     *       to mbedtls_pk_verify_ext(). In a future version of the library,\n     *       this constraint may apply whenever #MBEDTLS_USE_PSA_CRYPTO is\n     *       enabled regardless of the status of #MBEDTLS_RSA_C.\n     */\n    mbedtls_md_type_t mgf1_hash_id;\n\n    /** The expected length of the salt, in bytes. This may be\n     * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length.\n     *\n     * \\note When #MBEDTLS_USE_PSA_CRYPTO is enabled, only\n     *       #MBEDTLS_RSA_SALT_LEN_ANY is valid. Any other value may be\n     *       ignored (allowing any salt length).\n     */\n    int expected_salt_len;\n\n} mbedtls_pk_rsassa_pss_options;\n\n/**\n * \\brief           Maximum size of a signature made by mbedtls_pk_sign().\n */\n/* We need to set MBEDTLS_PK_SIGNATURE_MAX_SIZE to the maximum signature\n * size among the supported signature types. Do it by starting at 0,\n * then incrementally increasing to be large enough for each supported\n * signature mechanism.\n *\n * The resulting value can be 0, for example if MBEDTLS_ECDH_C is enabled\n * (which allows the pk module to be included) but neither MBEDTLS_ECDSA_C\n * nor MBEDTLS_RSA_C nor any opaque signature mechanism (PSA or RSA_ALT).\n */\n#define MBEDTLS_PK_SIGNATURE_MAX_SIZE 0\n\n#if (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_RSA_ALT_SUPPORT)) && \\\n    MBEDTLS_MPI_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE\n/* For RSA, the signature can be as large as the bignum module allows.\n * For RSA_ALT, the signature size is not necessarily tied to what the\n * bignum module can do, but in the absence of any specific setting,\n * we use that (rsa_alt_sign_wrap in library/pk_wrap.h will check). */\n#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE\n#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE\n#endif\n\n#if defined(MBEDTLS_ECDSA_C) &&                                 \\\n    MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_PK_SIGNATURE_MAX_SIZE\n/* For ECDSA, the ecdsa module exports a constant for the maximum\n * signature size. */\n#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE\n#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#if PSA_SIGNATURE_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE\n/* PSA_SIGNATURE_MAX_SIZE is the maximum size of a signature made\n * through the PSA API in the PSA representation. */\n#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE\n#define MBEDTLS_PK_SIGNATURE_MAX_SIZE PSA_SIGNATURE_MAX_SIZE\n#endif\n\n#if PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 > MBEDTLS_PK_SIGNATURE_MAX_SIZE\n/* The Mbed TLS representation is different for ECDSA signatures:\n * PSA uses the raw concatenation of r and s,\n * whereas Mbed TLS uses the ASN.1 representation (SEQUENCE of two INTEGERs).\n * Add the overhead of ASN.1: up to (1+2) + 2 * (1+2+1) for the\n * types, lengths (represented by up to 2 bytes), and potential leading\n * zeros of the INTEGERs and the SEQUENCE. */\n#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE\n#define MBEDTLS_PK_SIGNATURE_MAX_SIZE (PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11)\n#endif\n#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */\n\n/* Internal helper to define which fields in the pk_context structure below\n * should be used for EC keys: legacy ecp_keypair or the raw (PSA friendly)\n * format. It should be noted that this only affects how data is stored, not\n * which functions are used for various operations. The overall picture looks\n * like this:\n * - if USE_PSA is not defined and ECP_C is defined then use ecp_keypair data\n *   structure and legacy functions\n * - if USE_PSA is defined and\n *     - if ECP_C then use ecp_keypair structure, convert data to a PSA friendly\n *       format and use PSA functions\n *     - if !ECP_C then use new raw data and PSA functions directly.\n *\n * The main reason for the \"intermediate\" (USE_PSA + ECP_C) above is that as long\n * as ECP_C is defined mbedtls_pk_ec() gives the user a read/write access to the\n * ecp_keypair structure inside the pk_context so they can modify it using\n * ECP functions which are not under PK module's control.\n */\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \\\n    !defined(MBEDTLS_ECP_C)\n#define MBEDTLS_PK_USE_PSA_EC_DATA\n#endif\n\n/**\n * \\brief           Types for interfacing with the debug module\n */\ntypedef enum {\n    MBEDTLS_PK_DEBUG_NONE = 0,\n    MBEDTLS_PK_DEBUG_MPI,\n    MBEDTLS_PK_DEBUG_ECP,\n    MBEDTLS_PK_DEBUG_PSA_EC,\n} mbedtls_pk_debug_type;\n\n/**\n * \\brief           Item to send to the debug module\n */\ntypedef struct mbedtls_pk_debug_item {\n    mbedtls_pk_debug_type MBEDTLS_PRIVATE(type);\n    const char *MBEDTLS_PRIVATE(name);\n    void *MBEDTLS_PRIVATE(value);\n} mbedtls_pk_debug_item;\n\n/** Maximum number of item send for debugging, plus 1 */\n#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3\n\n/**\n * \\brief           Public key information and operations\n *\n * \\note        The library does not support custom pk info structures,\n *              only built-in structures returned by\n *              mbedtls_cipher_info_from_type().\n */\ntypedef struct mbedtls_pk_info_t mbedtls_pk_info_t;\n\n#define MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN \\\n    PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)\n/**\n * \\brief           Public key container\n */\ntypedef struct mbedtls_pk_context {\n    const mbedtls_pk_info_t *MBEDTLS_PRIVATE(pk_info);    /**< Public key information         */\n    void *MBEDTLS_PRIVATE(pk_ctx);                        /**< Underlying public key context  */\n    /* The following field is used to store the ID of a private key in the\n     * following cases:\n     * - opaque key when MBEDTLS_USE_PSA_CRYPTO is defined\n     * - normal key when MBEDTLS_PK_USE_PSA_EC_DATA is defined. In this case:\n     *    - the pk_ctx above is not not used to store the private key anymore.\n     *      Actually that field not populated at all in this case because also\n     *      the public key will be stored in raw format as explained below\n     *    - this ID is used for all private key operations (ex: sign, check\n     *      key pair, key write, etc) using PSA functions\n     *\n     * Note: this private key storing solution only affects EC keys, not the\n     *       other ones. The latters still use the pk_ctx to store their own\n     *       context. */\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    mbedtls_svc_key_id_t MBEDTLS_PRIVATE(priv_id);      /**< Key ID for opaque keys */\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    /* The following fields are meant for storing the public key in raw format\n     * which is handy for:\n     * - easily importing it into the PSA context\n     * - reducing the ECP module dependencies in the PK one.\n     *\n     * When MBEDTLS_PK_USE_PSA_EC_DATA is enabled:\n     * - the pk_ctx above is not used anymore for storing the public key\n     *   inside the ecp_keypair structure\n     * - the following fields are used for all public key operations: signature\n     *   verify, key pair check and key write.\n     * - For a key pair, priv_id contains the private key. For a public key,\n     *   priv_id is null.\n     * Of course, when MBEDTLS_PK_USE_PSA_EC_DATA is not enabled, the legacy\n     * ecp_keypair structure is used for storing the public key and performing\n     * all the operations.\n     *\n     * Note: This new public key storing solution only works for EC keys, not\n     *       other ones. The latters still use pk_ctx to store their own\n     *       context.\n     */\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n    uint8_t MBEDTLS_PRIVATE(pub_raw)[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; /**< Raw public key   */\n    size_t MBEDTLS_PRIVATE(pub_raw_len);            /**< Valid bytes in \"pub_raw\" */\n    psa_ecc_family_t MBEDTLS_PRIVATE(ec_family);    /**< EC family of pk */\n    size_t MBEDTLS_PRIVATE(ec_bits);                /**< Curve's bits of pk */\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n} mbedtls_pk_context;\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n/**\n * \\brief           Context for resuming operations\n */\ntypedef struct {\n    const mbedtls_pk_info_t *MBEDTLS_PRIVATE(pk_info);    /**< Public key information         */\n    void *MBEDTLS_PRIVATE(rs_ctx);                        /**< Underlying restart context     */\n} mbedtls_pk_restart_ctx;\n#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n/* Now we can declare functions that take a pointer to that */\ntypedef void mbedtls_pk_restart_ctx;\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n\n#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)\n/**\n * \\brief           Types for RSA-alt abstraction\n */\ntypedef int (*mbedtls_pk_rsa_alt_decrypt_func)(void *ctx, size_t *olen,\n                                               const unsigned char *input, unsigned char *output,\n                                               size_t output_max_len);\ntypedef int (*mbedtls_pk_rsa_alt_sign_func)(void *ctx,\n                                            mbedtls_f_rng_t *f_rng,\n                                            void *p_rng,\n                                            mbedtls_md_type_t md_alg, unsigned int hashlen,\n                                            const unsigned char *hash, unsigned char *sig);\ntypedef size_t (*mbedtls_pk_rsa_alt_key_len_func)(void *ctx);\n#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */\n\n/**\n * \\brief           Return information associated with the given PK type\n *\n * \\param pk_type   PK type to search for.\n *\n * \\return          The PK info associated with the type or NULL if not found.\n */\nconst mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type);\n\n/**\n * \\brief           Initialize a #mbedtls_pk_context (as NONE).\n *\n * \\param ctx       The context to initialize.\n *                  This must not be \\c NULL.\n */\nvoid mbedtls_pk_init(mbedtls_pk_context *ctx);\n\n/**\n * \\brief           Free the components of a #mbedtls_pk_context.\n *\n * \\param ctx       The context to clear. It must have been initialized.\n *                  If this is \\c NULL, this function does nothing.\n *\n * \\note            For contexts that have been set up with\n *                  mbedtls_pk_setup_opaque(), this does not free the underlying\n *                  PSA key and you still need to call psa_destroy_key()\n *                  independently if you want to destroy that key.\n */\nvoid mbedtls_pk_free(mbedtls_pk_context *ctx);\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n/**\n * \\brief           Initialize a restart context\n *\n * \\param ctx       The context to initialize.\n *                  This must not be \\c NULL.\n */\nvoid mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx);\n\n/**\n * \\brief           Free the components of a restart context\n *\n * \\param ctx       The context to clear. It must have been initialized.\n *                  If this is \\c NULL, this function does nothing.\n */\nvoid mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx);\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n\n/**\n * \\brief           Initialize a PK context with the information given\n *                  and allocates the type-specific PK subcontext.\n *\n * \\param ctx       Context to initialize. It must not have been set\n *                  up yet (type #MBEDTLS_PK_NONE).\n * \\param info      Information to use\n *\n * \\return          0 on success,\n *                  MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input,\n *                  MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure.\n *\n * \\note            For contexts holding an RSA-alt key, use\n *                  \\c mbedtls_pk_setup_rsa_alt() instead.\n */\nint mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info);\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n/**\n * \\brief Initialize a PK context to wrap a PSA key.\n *\n * This function creates a PK context which wraps a PSA key. The PSA wrapped\n * key must be an EC or RSA key pair (DH is not suported in the PK module).\n *\n * Under the hood PSA functions will be used to perform the required\n * operations and, based on the key type, used algorithms will be:\n * * EC:\n *     * verify, verify_ext, sign, sign_ext: ECDSA.\n * * RSA:\n *     * sign, decrypt: use the primary algorithm in the wrapped PSA key;\n *     * sign_ext: RSA PSS if the pk_type is #MBEDTLS_PK_RSASSA_PSS, otherwise\n *       it falls back to the sign() case;\n *     * verify, verify_ext, encrypt: not supported.\n *\n * In order for the above operations to succeed, the policy of the wrapped PSA\n * key must allow the specified algorithm.\n *\n * Opaque PK contexts wrapping an EC keys also support \\c mbedtls_pk_check_pair(),\n * whereas RSA ones do not.\n *\n * \\warning The PSA wrapped key must remain valid as long as the wrapping PK\n *          context is in use, that is at least between the point this function\n *          is called and the point mbedtls_pk_free() is called on this context.\n *\n * \\param ctx The context to initialize. It must be empty (type NONE).\n * \\param key The PSA key to wrap, which must hold an ECC or RSA key pair.\n *\n * \\return    \\c 0 on success.\n * \\return    #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input (context already\n *            used, invalid key identifier).\n * \\return    #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an ECC or\n *            RSA key pair.\n * \\return    #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure.\n */\nint mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx,\n                            const mbedtls_svc_key_id_t key);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)\n/**\n * \\brief           Initialize an RSA-alt context\n *\n * \\param ctx       Context to initialize. It must not have been set\n *                  up yet (type #MBEDTLS_PK_NONE).\n * \\param key       RSA key pointer\n * \\param decrypt_func  Decryption function\n * \\param sign_func     Signing function\n * \\param key_len_func  Function returning key length in bytes\n *\n * \\return          0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the\n *                  context wasn't already initialized as RSA_ALT.\n *\n * \\note            This function replaces \\c mbedtls_pk_setup() for RSA-alt.\n */\nint mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key,\n                             mbedtls_pk_rsa_alt_decrypt_func decrypt_func,\n                             mbedtls_pk_rsa_alt_sign_func sign_func,\n                             mbedtls_pk_rsa_alt_key_len_func key_len_func);\n#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */\n\n/**\n * \\brief           Get the size in bits of the underlying key\n *\n * \\param ctx       The context to query. It must have been initialized.\n *\n * \\return          Key size in bits, or 0 on error\n */\nsize_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx);\n\n/**\n * \\brief           Get the length in bytes of the underlying key\n *\n * \\param ctx       The context to query. It must have been initialized.\n *\n * \\return          Key length in bytes, or 0 on error\n */\nstatic inline size_t mbedtls_pk_get_len(const mbedtls_pk_context *ctx)\n{\n    return (mbedtls_pk_get_bitlen(ctx) + 7) / 8;\n}\n\n/**\n * \\brief           Tell if a context can do the operation given by type\n *\n * \\param ctx       The context to query. It must have been initialized.\n * \\param type      The desired type.\n *\n * \\return          1 if the context can do operations on the given type.\n * \\return          0 if the context cannot do the operations on the given\n *                  type. This is always the case for a context that has\n *                  been initialized but not set up, or that has been\n *                  cleared with mbedtls_pk_free().\n */\nint mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type);\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n/**\n * \\brief           Tell if context can do the operation given by PSA algorithm\n *\n * \\param ctx       The context to query. It must have been initialized.\n * \\param alg       PSA algorithm to check against, the following are allowed:\n *                  PSA_ALG_RSA_PKCS1V15_SIGN(hash),\n *                  PSA_ALG_RSA_PSS(hash),\n *                  PSA_ALG_RSA_PKCS1V15_CRYPT,\n *                  PSA_ALG_ECDSA(hash),\n *                  PSA_ALG_ECDH, where hash is a specific hash.\n * \\param usage     PSA usage flag to check against, must be composed of:\n *                  PSA_KEY_USAGE_SIGN_HASH\n *                  PSA_KEY_USAGE_DECRYPT\n *                  PSA_KEY_USAGE_DERIVE.\n *                  Context key must match all passed usage flags.\n *\n * \\warning         Since the set of allowed algorithms and usage flags may be\n *                  expanded in the future, the return value \\c 0 should not\n *                  be taken in account for non-allowed algorithms and usage\n *                  flags.\n *\n * \\return          1 if the context can do operations on the given type.\n * \\return          0 if the context cannot do the operations on the given\n *                  type, for non-allowed algorithms and usage flags, or\n *                  for a context that has been initialized but not set up\n *                  or that has been cleared with mbedtls_pk_free().\n */\nint mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg,\n                          psa_key_usage_t usage);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)\n/**\n * \\brief           Determine valid PSA attributes that can be used to\n *                  import a key into PSA.\n *\n * The attributes determined by this function are suitable\n * for calling mbedtls_pk_import_into_psa() to create\n * a PSA key with the same key material.\n *\n * The typical flow of operations involving this function is\n * ```\n * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n * int ret = mbedtls_pk_get_psa_attributes(pk, &attributes);\n * if (ret != 0) ...; // error handling omitted\n * // Tweak attributes if desired\n * psa_key_id_t key_id = 0;\n * ret = mbedtls_pk_import_into_psa(pk, &attributes, &key_id);\n * if (ret != 0) ...; // error handling omitted\n * ```\n *\n * \\note            This function does not support RSA-alt contexts\n *                  (set up with mbedtls_pk_setup_rsa_alt()).\n *\n * \\param[in] pk    The PK context to use. It must have been set up.\n *                  It can either contain a key pair or just a public key.\n * \\param usage     A single `PSA_KEY_USAGE_xxx` flag among the following:\n *                  - #PSA_KEY_USAGE_DECRYPT: \\p pk must contain a\n *                    key pair. The output \\p attributes will contain a\n *                    key pair type, and the usage policy will allow\n *                    #PSA_KEY_USAGE_ENCRYPT as well as\n *                    #PSA_KEY_USAGE_DECRYPT.\n *                  - #PSA_KEY_USAGE_DERIVE: \\p pk must contain a\n *                    key pair. The output \\p attributes will contain a\n *                    key pair type.\n *                  - #PSA_KEY_USAGE_ENCRYPT: The output\n *                    \\p attributes will contain a public key type.\n *                  - #PSA_KEY_USAGE_SIGN_HASH: \\p pk must contain a\n *                    key pair. The output \\p attributes will contain a\n *                    key pair type, and the usage policy will allow\n *                    #PSA_KEY_USAGE_VERIFY_HASH as well as\n *                    #PSA_KEY_USAGE_SIGN_HASH.\n *                  - #PSA_KEY_USAGE_SIGN_MESSAGE: \\p pk must contain a\n *                    key pair. The output \\p attributes will contain a\n *                    key pair type, and the usage policy will allow\n *                    #PSA_KEY_USAGE_VERIFY_MESSAGE as well as\n *                    #PSA_KEY_USAGE_SIGN_MESSAGE.\n *                  - #PSA_KEY_USAGE_VERIFY_HASH: The output\n *                    \\p attributes will contain a public key type.\n *                  - #PSA_KEY_USAGE_VERIFY_MESSAGE: The output\n *                    \\p attributes will contain a public key type.\n * \\param[out] attributes\n *                  On success, valid attributes to import the key into PSA.\n *                  - The lifetime and key identifier are unchanged. If the\n *                    attribute structure was initialized or reset before\n *                    calling this function, this will result in a volatile\n *                    key. Call psa_set_key_identifier() before or after this\n *                    function if you wish to create a persistent key. Call\n *                    psa_set_key_lifetime() before or after this function if\n *                    you wish to import the key in a secure element.\n *                  - The key type and bit-size are determined by the contents\n *                    of the PK context. If the PK context contains a key\n *                    pair, the key type can be either a key pair type or\n *                    the corresponding public key type, depending on\n *                    \\p usage. If the PK context contains a public key,\n *                    the key type is a public key type.\n *                  - The key's policy is determined by the key type and\n *                    the \\p usage parameter. The usage always allows\n *                    \\p usage, exporting and copying the key, and\n *                    possibly other permissions as documented for the\n *                    \\p usage parameter.\n *                    The permitted algorithm policy is determined as follows\n *                    based on the #mbedtls_pk_type_t type of \\p pk,\n *                    the chosen \\p usage and other factors:\n *                      - #MBEDTLS_PK_RSA whose underlying\n *                        #mbedtls_rsa_context has the padding mode\n *                        #MBEDTLS_RSA_PKCS_V15:\n *                        #PSA_ALG_RSA_PKCS1V15_SIGN(#PSA_ALG_ANY_HASH)\n *                        if \\p usage is SIGN/VERIFY, and\n *                        #PSA_ALG_RSA_PKCS1V15_CRYPT\n *                        if \\p usage is ENCRYPT/DECRYPT.\n *                      - #MBEDTLS_PK_RSA whose underlying\n *                        #mbedtls_rsa_context has the padding mode\n *                        #MBEDTLS_RSA_PKCS_V21 and the digest type\n *                        corresponding to the PSA algorithm \\c hash:\n *                        #PSA_ALG_RSA_PSS_ANY_SALT(#PSA_ALG_ANY_HASH)\n *                        if \\p usage is SIGN/VERIFY, and\n *                        #PSA_ALG_RSA_OAEP(\\c hash)\n *                        if \\p usage is ENCRYPT/DECRYPT.\n *                      - #MBEDTLS_PK_RSA_ALT: not supported.\n *                      - #MBEDTLS_PK_ECDSA or #MBEDTLS_PK_ECKEY\n *                        if \\p usage is SIGN/VERIFY:\n *                        #PSA_ALG_DETERMINISTIC_ECDSA(#PSA_ALG_ANY_HASH)\n *                        if #MBEDTLS_ECDSA_DETERMINISTIC is enabled,\n *                        otherwise #PSA_ALG_ECDSA(#PSA_ALG_ANY_HASH).\n *                      - #MBEDTLS_PK_ECKEY_DH or #MBEDTLS_PK_ECKEY\n *                        if \\p usage is DERIVE:\n *                        #PSA_ALG_ECDH.\n *                      - #MBEDTLS_PK_OPAQUE: same as the primary algorithm\n *                        set for the underlying PSA key, except that\n *                        sign/decrypt flags are removed if the type is\n *                        set to a public key type.\n *                        The underlying key must allow \\p usage.\n *                        Note that the enrollment algorithm set with\n *                        psa_set_key_enrollment_algorithm() is not copied.\n *\n * \\return          0 on success.\n *                  #MBEDTLS_ERR_PK_TYPE_MISMATCH if \\p pk does not contain\n *                  a key of the type identified in \\p attributes.\n *                  Another error code on other failures.\n */\nint mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk,\n                                  psa_key_usage_t usage,\n                                  psa_key_attributes_t *attributes);\n\n/**\n * \\brief           Import a key into the PSA key store.\n *\n * This function is equivalent to calling psa_import_key()\n * with the key material from \\p pk.\n *\n * The typical way to use this function is:\n * -# Call mbedtls_pk_get_psa_attributes() to obtain\n *    attributes for the given key.\n * -# If desired, modify the attributes, for example:\n *     - To create a persistent key, call\n *       psa_set_key_identifier() and optionally\n *       psa_set_key_lifetime().\n *     - To import only the public part of a key pair:\n *\n *           psa_set_key_type(&attributes,\n *                            PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\n *                                psa_get_key_type(&attributes)));\n *     - Restrict the key usage if desired.\n * -# Call mbedtls_pk_import_into_psa().\n *\n * \\note            This function does not support RSA-alt contexts\n *                  (set up with mbedtls_pk_setup_rsa_alt()).\n *\n * \\param[in] pk    The PK context to use. It must have been set up.\n *                  It can either contain a key pair or just a public key.\n * \\param[in] attributes\n *                  The attributes to use for the new key. They must be\n *                  compatible with \\p pk. In particular, the key type\n *                  must match the content of \\p pk.\n *                  If \\p pk contains a key pair, the key type in\n *                  attributes can be either the key pair type or the\n *                  corresponding public key type (to import only the\n *                  public part).\n * \\param[out] key_id\n *                  On success, the identifier of the newly created key.\n *                  On error, this is #MBEDTLS_SVC_KEY_ID_INIT.\n *\n * \\return          0 on success.\n *                  #MBEDTLS_ERR_PK_TYPE_MISMATCH if \\p pk does not contain\n *                  a key of the type identified in \\p attributes.\n *                  Another error code on other failures.\n */\nint mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk,\n                               const psa_key_attributes_t *attributes,\n                               mbedtls_svc_key_id_t *key_id);\n\n/**\n * \\brief           Create a PK context starting from a key stored in PSA.\n *                  This key:\n *                  - must be exportable and\n *                  - must be an RSA or EC key pair or public key (FFDH is not supported in PK).\n *\n *                  The resulting PK object will be a transparent type:\n *                  - #MBEDTLS_PK_RSA for RSA keys or\n *                  - #MBEDTLS_PK_ECKEY for EC keys.\n *\n *                  Once this functions returns the PK object will be completely\n *                  independent from the original PSA key that it was generated\n *                  from.\n *                  Calling mbedtls_pk_sign(), mbedtls_pk_verify(),\n *                  mbedtls_pk_encrypt(), mbedtls_pk_decrypt() on the resulting\n *                  PK context will perform the corresponding algorithm for that\n *                  PK context type.\n *                  * For ECDSA, the choice of deterministic vs randomized will\n *                    be based on the compile-time setting #MBEDTLS_ECDSA_DETERMINISTIC.\n *                  * For an RSA key, the output PK context will allow both\n *                    encrypt/decrypt and sign/verify regardless of the original\n *                    key's policy.\n *                    The original key's policy determines the output key's padding\n *                    mode: PCKS1 v2.1 is set if the PSA key policy is OAEP or PSS,\n *                    otherwise PKCS1 v1.5 is set.\n *\n * \\param key_id    The key identifier of the key stored in PSA.\n * \\param pk        The PK context that will be filled. It must be initialized,\n *                  but not set up.\n *\n * \\return          0 on success.\n * \\return          #MBEDTLS_ERR_PK_BAD_INPUT_DATA in case the provided input\n *                  parameters are not correct.\n */\nint mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk);\n\n/**\n * \\brief           Create a PK context for the public key of a PSA key.\n *\n *                  The key must be an RSA or ECC key. It can be either a\n *                  public key or a key pair, and only the public key is copied.\n *                  The resulting PK object will be a transparent type:\n *                  - #MBEDTLS_PK_RSA for RSA keys or\n *                  - #MBEDTLS_PK_ECKEY for EC keys.\n *\n *                  Once this functions returns the PK object will be completely\n *                  independent from the original PSA key that it was generated\n *                  from.\n *                  Calling mbedtls_pk_verify() or\n *                  mbedtls_pk_encrypt() on the resulting\n *                  PK context will perform the corresponding algorithm for that\n *                  PK context type.\n *\n *                  For an RSA key, the output PK context will allow both\n *                  encrypt and verify regardless of the original key's policy.\n *                  The original key's policy determines the output key's padding\n *                  mode: PCKS1 v2.1 is set if the PSA key policy is OAEP or PSS,\n *                  otherwise PKCS1 v1.5 is set.\n *\n * \\param key_id    The key identifier of the key stored in PSA.\n * \\param pk        The PK context that will be filled. It must be initialized,\n *                  but not set up.\n *\n * \\return          0 on success.\n * \\return          MBEDTLS_ERR_PK_BAD_INPUT_DATA in case the provided input\n *                  parameters are not correct.\n */\nint mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk);\n#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */\n\n/**\n * \\brief           Verify signature (including padding if relevant).\n *\n * \\param ctx       The PK context to use. It must have been set up.\n * \\param md_alg    Hash algorithm used.\n *                  This can be #MBEDTLS_MD_NONE if the signature algorithm\n *                  does not rely on a hash algorithm (non-deterministic\n *                  ECDSA, RSA PKCS#1 v1.5).\n *                  For PKCS#1 v1.5, if \\p md_alg is #MBEDTLS_MD_NONE, then\n *                  \\p hash is the DigestInfo structure used by RFC 8017\n *                  &sect;9.2 steps 3&ndash;6. If \\p md_alg is a valid hash\n *                  algorithm then \\p hash is the digest itself, and this\n *                  function calculates the DigestInfo encoding internally.\n * \\param hash      Hash of the message to sign\n * \\param hash_len  Hash length\n * \\param sig       Signature to verify\n * \\param sig_len   Signature length\n *\n * \\note            For keys of type #MBEDTLS_PK_RSA, the signature algorithm is\n *                  either PKCS#1 v1.5 or PSS (accepting any salt length),\n *                  depending on the padding mode in the underlying RSA context.\n *                  For a pk object constructed by parsing, this is PKCS#1 v1.5\n *                  by default. Use mbedtls_pk_verify_ext() to explicitly select\n *                  a different algorithm.\n *\n * \\return          0 on success (signature is valid),\n *                  #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid\n *                  signature in \\p sig but its length is less than \\p sig_len,\n *                  or a specific error code.\n */\nint mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,\n                      const unsigned char *hash, size_t hash_len,\n                      const unsigned char *sig, size_t sig_len);\n\n/**\n * \\brief           Restartable version of \\c mbedtls_pk_verify()\n *\n * \\note            Performs the same job as \\c mbedtls_pk_verify(), but can\n *                  return early and restart according to the limit set with\n *                  \\c mbedtls_ecp_set_max_ops() to reduce blocking for ECC\n *                  operations. For RSA, same as \\c mbedtls_pk_verify().\n *\n * \\param ctx       The PK context to use. It must have been set up.\n * \\param md_alg    Hash algorithm used (see notes)\n * \\param hash      Hash of the message to sign\n * \\param hash_len  Hash length or 0 (see notes)\n * \\param sig       Signature to verify\n * \\param sig_len   Signature length\n * \\param rs_ctx    Restart context (NULL to disable restart)\n *\n * \\return          See \\c mbedtls_pk_verify(), or\n * \\return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of\n *                  operations was reached: see \\c mbedtls_ecp_set_max_ops().\n */\nint mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx,\n                                  mbedtls_md_type_t md_alg,\n                                  const unsigned char *hash, size_t hash_len,\n                                  const unsigned char *sig, size_t sig_len,\n                                  mbedtls_pk_restart_ctx *rs_ctx);\n\n/**\n * \\brief           Verify signature, with options.\n *                  (Includes verification of the padding depending on type.)\n *\n * \\param type      Signature type (inc. possible padding type) to verify\n * \\param options   Pointer to type-specific options, or NULL\n * \\param ctx       The PK context to use. It must have been set up.\n * \\param md_alg    Hash algorithm used (see notes)\n * \\param hash      Hash of the message to sign\n * \\param hash_len  Hash length or 0 (see notes)\n * \\param sig       Signature to verify\n * \\param sig_len   Signature length\n *\n * \\return          0 on success (signature is valid),\n *                  #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be\n *                  used for this type of signatures,\n *                  #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid\n *                  signature in \\p sig but its length is less than \\p sig_len,\n *                  or a specific error code.\n *\n * \\note            If hash_len is 0, then the length associated with md_alg\n *                  is used instead, or an error returned if it is invalid.\n *\n * \\note            md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0\n *\n * \\note            If type is MBEDTLS_PK_RSASSA_PSS, then options must point\n *                  to a mbedtls_pk_rsassa_pss_options structure,\n *                  otherwise it must be NULL. Note that if\n *                  #MBEDTLS_USE_PSA_CRYPTO is defined, the salt length is not\n *                  verified as PSA_ALG_RSA_PSS_ANY_SALT is used.\n */\nint mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options,\n                          mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,\n                          const unsigned char *hash, size_t hash_len,\n                          const unsigned char *sig, size_t sig_len);\n\n/**\n * \\brief           Make signature, including padding if relevant.\n *\n * \\param ctx       The PK context to use. It must have been set up\n *                  with a private key.\n * \\param md_alg    Hash algorithm used (see notes)\n * \\param hash      Hash of the message to sign\n * \\param hash_len  Hash length\n * \\param sig       Place to write the signature.\n *                  It must have enough room for the signature.\n *                  #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough.\n *                  You may use a smaller buffer if it is large enough\n *                  given the key type.\n * \\param sig_size  The size of the \\p sig buffer in bytes.\n * \\param sig_len   On successful return,\n *                  the number of bytes written to \\p sig.\n * \\param f_rng     RNG function, must not be \\c NULL.\n * \\param p_rng     RNG parameter\n *\n * \\note            For keys of type #MBEDTLS_PK_RSA, the signature algorithm is\n *                  either PKCS#1 v1.5 or PSS (using the largest possible salt\n *                  length up to the hash length), depending on the padding mode\n *                  in the underlying RSA context. For a pk object constructed\n *                  by parsing, this is PKCS#1 v1.5 by default. Use\n *                  mbedtls_pk_verify_ext() to explicitly select a different\n *                  algorithm.\n *\n * \\return          0 on success, or a specific error code.\n *\n * \\note            For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0.\n *                  For ECDSA, md_alg may never be MBEDTLS_MD_NONE.\n */\nint mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,\n                    const unsigned char *hash, size_t hash_len,\n                    unsigned char *sig, size_t sig_size, size_t *sig_len,\n                    mbedtls_f_rng_t *f_rng, void *p_rng);\n\n/**\n * \\brief           Make signature given a signature type.\n *\n * \\param pk_type   Signature type.\n * \\param ctx       The PK context to use. It must have been set up\n *                  with a private key.\n * \\param md_alg    Hash algorithm used (see notes)\n * \\param hash      Hash of the message to sign\n * \\param hash_len  Hash length\n * \\param sig       Place to write the signature.\n *                  It must have enough room for the signature.\n *                  #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough.\n *                  You may use a smaller buffer if it is large enough\n *                  given the key type.\n * \\param sig_size  The size of the \\p sig buffer in bytes.\n * \\param sig_len   On successful return,\n *                  the number of bytes written to \\p sig.\n * \\param f_rng     RNG function, must not be \\c NULL.\n * \\param p_rng     RNG parameter\n *\n * \\return          0 on success, or a specific error code.\n *\n * \\note            When \\p pk_type is #MBEDTLS_PK_RSASSA_PSS,\n *                  see #PSA_ALG_RSA_PSS for a description of PSS options used.\n *\n * \\note            For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0.\n *                  For ECDSA, md_alg may never be MBEDTLS_MD_NONE.\n *\n */\nint mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type,\n                        mbedtls_pk_context *ctx,\n                        mbedtls_md_type_t md_alg,\n                        const unsigned char *hash, size_t hash_len,\n                        unsigned char *sig, size_t sig_size, size_t *sig_len,\n                        mbedtls_f_rng_t *f_rng,\n                        void *p_rng);\n\n/**\n * \\brief           Restartable version of \\c mbedtls_pk_sign()\n *\n * \\note            Performs the same job as \\c mbedtls_pk_sign(), but can\n *                  return early and restart according to the limit set with\n *                  \\c mbedtls_ecp_set_max_ops() to reduce blocking for ECC\n *                  operations. For RSA, same as \\c mbedtls_pk_sign().\n *\n * \\param ctx       The PK context to use. It must have been set up\n *                  with a private key.\n * \\param md_alg    Hash algorithm used (see notes for mbedtls_pk_sign())\n * \\param hash      Hash of the message to sign\n * \\param hash_len  Hash length\n * \\param sig       Place to write the signature.\n *                  It must have enough room for the signature.\n *                  #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough.\n *                  You may use a smaller buffer if it is large enough\n *                  given the key type.\n * \\param sig_size  The size of the \\p sig buffer in bytes.\n * \\param sig_len   On successful return,\n *                  the number of bytes written to \\p sig.\n * \\param f_rng     RNG function, must not be \\c NULL.\n * \\param p_rng     RNG parameter\n * \\param rs_ctx    Restart context (NULL to disable restart)\n *\n * \\return          See \\c mbedtls_pk_sign().\n * \\return          #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of\n *                  operations was reached: see \\c mbedtls_ecp_set_max_ops().\n */\nint mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx,\n                                mbedtls_md_type_t md_alg,\n                                const unsigned char *hash, size_t hash_len,\n                                unsigned char *sig, size_t sig_size, size_t *sig_len,\n                                mbedtls_f_rng_t *f_rng, void *p_rng,\n                                mbedtls_pk_restart_ctx *rs_ctx);\n\n/**\n * \\brief           Decrypt message (including padding if relevant).\n *\n * \\param ctx       The PK context to use. It must have been set up\n *                  with a private key.\n * \\param input     Input to decrypt\n * \\param ilen      Input size\n * \\param output    Decrypted output\n * \\param olen      Decrypted message length\n * \\param osize     Size of the output buffer\n * \\param f_rng     RNG function, must not be \\c NULL.\n * \\param p_rng     RNG parameter\n *\n * \\note            For keys of type #MBEDTLS_PK_RSA, the signature algorithm is\n *                  either PKCS#1 v1.5 or OAEP, depending on the padding mode in\n *                  the underlying RSA context. For a pk object constructed by\n *                  parsing, this is PKCS#1 v1.5 by default.\n *\n * \\return          0 on success, or a specific error code.\n */\nint mbedtls_pk_decrypt(mbedtls_pk_context *ctx,\n                       const unsigned char *input, size_t ilen,\n                       unsigned char *output, size_t *olen, size_t osize,\n                       mbedtls_f_rng_t *f_rng, void *p_rng);\n\n/**\n * \\brief           Encrypt message (including padding if relevant).\n *\n * \\param ctx       The PK context to use. It must have been set up.\n * \\param input     Message to encrypt\n * \\param ilen      Message size\n * \\param output    Encrypted output\n * \\param olen      Encrypted output length\n * \\param osize     Size of the output buffer\n * \\param f_rng     RNG function, must not be \\c NULL.\n * \\param p_rng     RNG parameter\n *\n * \\note            For keys of type #MBEDTLS_PK_RSA, the signature algorithm is\n *                  either PKCS#1 v1.5 or OAEP, depending on the padding mode in\n *                  the underlying RSA context. For a pk object constructed by\n *                  parsing, this is PKCS#1 v1.5 by default.\n *\n * \\note            \\p f_rng is used for padding generation.\n *\n * \\return          0 on success, or a specific error code.\n */\nint mbedtls_pk_encrypt(mbedtls_pk_context *ctx,\n                       const unsigned char *input, size_t ilen,\n                       unsigned char *output, size_t *olen, size_t osize,\n                       mbedtls_f_rng_t *f_rng, void *p_rng);\n\n/**\n * \\brief           Check if a public-private pair of keys matches.\n *\n * \\param pub       Context holding a public key.\n * \\param prv       Context holding a private (and public) key.\n * \\param f_rng     RNG function, must not be \\c NULL.\n * \\param p_rng     RNG parameter\n *\n * \\return          \\c 0 on success (keys were checked and match each other).\n * \\return          #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not\n *                  be checked - in that case they may or may not match.\n * \\return          #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid.\n * \\return          Another non-zero value if the keys do not match.\n */\nint mbedtls_pk_check_pair(const mbedtls_pk_context *pub,\n                          const mbedtls_pk_context *prv,\n                          mbedtls_f_rng_t *f_rng,\n                          void *p_rng);\n\n/**\n * \\brief           Export debug information\n *\n * \\param ctx       The PK context to use. It must have been initialized.\n * \\param items     Place to write debug items\n *\n * \\return          0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA\n */\nint mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items);\n\n/**\n * \\brief           Access the type name\n *\n * \\param ctx       The PK context to use. It must have been initialized.\n *\n * \\return          Type name on success, or \"invalid PK\"\n */\nconst char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx);\n\n/**\n * \\brief           Get the key type\n *\n * \\param ctx       The PK context to use. It must have been initialized.\n *\n * \\return          Type on success.\n * \\return          #MBEDTLS_PK_NONE for a context that has not been set up.\n */\nmbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx);\n\n#if defined(MBEDTLS_RSA_C)\n/**\n * Quick access to an RSA context inside a PK context.\n *\n * \\warning This function can only be used when the type of the context, as\n * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_RSA.\n * Ensuring that is the caller's responsibility.\n * Alternatively, you can check whether this function returns NULL.\n *\n * \\return The internal RSA context held by the PK context, or NULL.\n */\nstatic inline mbedtls_rsa_context *mbedtls_pk_rsa(const mbedtls_pk_context pk)\n{\n    switch (mbedtls_pk_get_type(&pk)) {\n        case MBEDTLS_PK_RSA:\n            return (mbedtls_rsa_context *) (pk).MBEDTLS_PRIVATE(pk_ctx);\n        default:\n            return NULL;\n    }\n}\n#endif /* MBEDTLS_RSA_C */\n\n#if defined(MBEDTLS_ECP_C)\n/**\n * Quick access to an EC context inside a PK context.\n *\n * \\warning This function can only be used when the type of the context, as\n * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_ECKEY,\n * #MBEDTLS_PK_ECKEY_DH, or #MBEDTLS_PK_ECDSA.\n * Ensuring that is the caller's responsibility.\n * Alternatively, you can check whether this function returns NULL.\n *\n * \\return The internal EC context held by the PK context, or NULL.\n */\nstatic inline mbedtls_ecp_keypair *mbedtls_pk_ec(const mbedtls_pk_context pk)\n{\n    switch (mbedtls_pk_get_type(&pk)) {\n        case MBEDTLS_PK_ECKEY:\n        case MBEDTLS_PK_ECKEY_DH:\n        case MBEDTLS_PK_ECDSA:\n            return (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx);\n        default:\n            return NULL;\n    }\n}\n#endif /* MBEDTLS_ECP_C */\n\n#if defined(MBEDTLS_PK_PARSE_C)\n/** \\ingroup pk_module */\n/**\n * \\brief           Parse a private key in PEM or DER format\n *\n * \\note            If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                  subsystem must have been initialized by calling\n *                  psa_crypto_init() before calling this function.\n *\n * \\param ctx       The PK context to fill. It must have been initialized\n *                  but not set up.\n * \\param key       Input buffer to parse.\n *                  The buffer must contain the input exactly, with no\n *                  extra trailing material. For PEM, the buffer must\n *                  contain a null-terminated string.\n * \\param keylen    Size of \\b key in bytes.\n *                  For PEM data, this includes the terminating null byte,\n *                  so \\p keylen must be equal to `strlen(key) + 1`.\n * \\param pwd       Optional password for decryption.\n *                  Pass \\c NULL if expecting a non-encrypted key.\n *                  Pass a string of \\p pwdlen bytes if expecting an encrypted\n *                  key; a non-encrypted key will also be accepted.\n *                  The empty password is not supported.\n * \\param pwdlen    Size of the password in bytes.\n *                  Ignored if \\p pwd is \\c NULL.\n * \\param f_rng     RNG function, must not be \\c NULL. Used for blinding.\n * \\param p_rng     RNG parameter\n *\n * \\note            On entry, ctx must be empty, either freshly initialised\n *                  with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a\n *                  specific key type, check the result with mbedtls_pk_can_do().\n *\n * \\note            The key is also checked for correctness.\n *\n * \\return          0 if successful, or a specific PK or PEM error code\n */\nint mbedtls_pk_parse_key(mbedtls_pk_context *ctx,\n                         const unsigned char *key, size_t keylen,\n                         const unsigned char *pwd, size_t pwdlen,\n                         mbedtls_f_rng_t *f_rng, void *p_rng);\n\n/** \\ingroup pk_module */\n/**\n * \\brief           Parse a public key in PEM or DER format\n *\n * \\note            If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                  subsystem must have been initialized by calling\n *                  psa_crypto_init() before calling this function.\n *\n * \\param ctx       The PK context to fill. It must have been initialized\n *                  but not set up.\n * \\param key       Input buffer to parse.\n *                  The buffer must contain the input exactly, with no\n *                  extra trailing material. For PEM, the buffer must\n *                  contain a null-terminated string.\n * \\param keylen    Size of \\b key in bytes.\n *                  For PEM data, this includes the terminating null byte,\n *                  so \\p keylen must be equal to `strlen(key) + 1`.\n *\n * \\note            On entry, ctx must be empty, either freshly initialised\n *                  with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a\n *                  specific key type, check the result with mbedtls_pk_can_do().\n *\n * \\note            For compressed points, see #MBEDTLS_ECP_PF_COMPRESSED for\n *                  limitations.\n *\n * \\note            The key is also checked for correctness.\n *\n * \\return          0 if successful, or a specific PK or PEM error code\n */\nint mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,\n                                const unsigned char *key, size_t keylen);\n\n#if defined(MBEDTLS_FS_IO)\n/** \\ingroup pk_module */\n/**\n * \\brief           Load and parse a private key\n *\n * \\note            If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                  subsystem must have been initialized by calling\n *                  psa_crypto_init() before calling this function.\n *\n * \\param ctx       The PK context to fill. It must have been initialized\n *                  but not set up.\n * \\param path      filename to read the private key from\n * \\param password  Optional password to decrypt the file.\n *                  Pass \\c NULL if expecting a non-encrypted key.\n *                  Pass a null-terminated string if expecting an encrypted\n *                  key; a non-encrypted key will also be accepted.\n *                  The empty password is not supported.\n * \\param f_rng     RNG function, must not be \\c NULL. Used for blinding.\n * \\param p_rng     RNG parameter\n *\n * \\note            On entry, ctx must be empty, either freshly initialised\n *                  with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a\n *                  specific key type, check the result with mbedtls_pk_can_do().\n *\n * \\note            The key is also checked for correctness.\n *\n * \\return          0 if successful, or a specific PK or PEM error code\n */\nint mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx,\n                             const char *path, const char *password,\n                             mbedtls_f_rng_t *f_rng, void *p_rng);\n\n/** \\ingroup pk_module */\n/**\n * \\brief           Load and parse a public key\n *\n * \\param ctx       The PK context to fill. It must have been initialized\n *                  but not set up.\n * \\param path      filename to read the public key from\n *\n * \\note            On entry, ctx must be empty, either freshly initialised\n *                  with mbedtls_pk_init() or reset with mbedtls_pk_free(). If\n *                  you need a specific key type, check the result with\n *                  mbedtls_pk_can_do().\n *\n * \\note            The key is also checked for correctness.\n *\n * \\return          0 if successful, or a specific PK or PEM error code\n */\nint mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path);\n#endif /* MBEDTLS_FS_IO */\n#endif /* MBEDTLS_PK_PARSE_C */\n\n#if defined(MBEDTLS_PK_WRITE_C)\n/**\n * \\brief           Write a private key to a PKCS#1 or SEC1 DER structure\n *                  Note: data is written at the end of the buffer! Use the\n *                        return value to determine where you should start\n *                        using the buffer\n *\n * \\param ctx       PK context which must contain a valid private key.\n * \\param buf       buffer to write to\n * \\param size      size of the buffer\n *\n * \\return          length of data written if successful, or a specific\n *                  error code\n */\nint mbedtls_pk_write_key_der(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size);\n\n/**\n * \\brief           Write a public key to a SubjectPublicKeyInfo DER structure\n *                  Note: data is written at the end of the buffer! Use the\n *                        return value to determine where you should start\n *                        using the buffer\n *\n * \\param ctx       PK context which must contain a valid public or private key.\n * \\param buf       buffer to write to\n * \\param size      size of the buffer\n *\n * \\return          length of data written if successful, or a specific\n *                  error code\n */\nint mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size);\n\n#if defined(MBEDTLS_PEM_WRITE_C)\n/**\n * \\brief           Write a public key to a PEM string\n *\n * \\param ctx       PK context which must contain a valid public or private key.\n * \\param buf       Buffer to write to. The output includes a\n *                  terminating null byte.\n * \\param size      Size of the buffer in bytes.\n *\n * \\return          0 if successful, or a specific error code\n */\nint mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size);\n\n/**\n * \\brief           Write a private key to a PKCS#1 or SEC1 PEM string\n *\n * \\param ctx       PK context which must contain a valid private key.\n * \\param buf       Buffer to write to. The output includes a\n *                  terminating null byte.\n * \\param size      Size of the buffer in bytes.\n *\n * \\return          0 if successful, or a specific error code\n */\nint mbedtls_pk_write_key_pem(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size);\n#endif /* MBEDTLS_PEM_WRITE_C */\n#endif /* MBEDTLS_PK_WRITE_C */\n\n/*\n * WARNING: Low-level functions. You probably do not want to use these unless\n *          you are certain you do ;)\n */\n\n#if defined(MBEDTLS_PK_PARSE_C)\n/**\n * \\brief           Parse a SubjectPublicKeyInfo DER structure\n *\n * \\param p         the position in the ASN.1 data\n * \\param end       end of the buffer\n * \\param pk        The PK context to fill. It must have been initialized\n *                  but not set up.\n *\n * \\return          0 if successful, or a specific PK error code\n */\nint mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,\n                               mbedtls_pk_context *pk);\n#endif /* MBEDTLS_PK_PARSE_C */\n\n#if defined(MBEDTLS_PK_WRITE_C)\n/**\n * \\brief           Write a subjectPublicKey to ASN.1 data\n *                  Note: function works backwards in data buffer\n *\n * \\param p         reference to current position pointer\n * \\param start     start of the buffer (for bounds-checking)\n * \\param key       PK context which must contain a valid public or private key.\n *\n * \\return          the length written or a negative error code\n */\nint mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,\n                            const mbedtls_pk_context *key);\n#endif /* MBEDTLS_PK_WRITE_C */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_PK_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/pkcs12.h",
    "content": "/**\n * \\file pkcs12.h\n *\n * \\brief PKCS#12 Personal Information Exchange Syntax\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_PKCS12_H\n#define MBEDTLS_PKCS12_H\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/md.h\"\n#include \"mbedtls/cipher.h\"\n#include \"mbedtls/asn1.h\"\n\n#include <stddef.h>\n\n/** Bad input parameters to function. */\n#define MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA                 -0x1F80\n/** Feature not available, e.g. unsupported encryption scheme. */\n#define MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE            -0x1F00\n/** PBE ASN.1 data not as expected. */\n#define MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT             -0x1E80\n/** Given private key password does not allow for correct decryption. */\n#define MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH              -0x1E00\n\n#define MBEDTLS_PKCS12_DERIVE_KEY       1   /**< encryption/decryption key */\n#define MBEDTLS_PKCS12_DERIVE_IV        2   /**< initialization vector     */\n#define MBEDTLS_PKCS12_DERIVE_MAC_KEY   3   /**< integrity / MAC key       */\n\n#define MBEDTLS_PKCS12_PBE_DECRYPT      MBEDTLS_DECRYPT\n#define MBEDTLS_PKCS12_PBE_ENCRYPT      MBEDTLS_ENCRYPT\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C)\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n/**\n * \\brief            PKCS12 Password Based function (encryption / decryption)\n *                   for cipher-based and mbedtls_md-based PBE's\n *\n * \\note             When encrypting, #MBEDTLS_CIPHER_PADDING_PKCS7 must\n *                   be enabled at compile time.\n *\n * \\deprecated       This function is deprecated and will be removed in a\n *                   future version of the library.\n *                   Please use mbedtls_pkcs12_pbe_ext() instead.\n *\n * \\warning          When decrypting:\n *                   - if #MBEDTLS_CIPHER_PADDING_PKCS7 is enabled at compile\n *                     time, this function validates the CBC padding and returns\n *                     #MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH if the padding is\n *                     invalid. Note that this can help active adversaries\n *                     attempting to brute-forcing the password. Note also that\n *                     there is no guarantee that an invalid password will be\n *                     detected (the chances of a valid padding with a random\n *                     password are about 1/255).\n *                   - if #MBEDTLS_CIPHER_PADDING_PKCS7 is disabled at compile\n *                     time, this function does not validate the CBC padding.\n *\n * \\param pbe_params an ASN1 buffer containing the pkcs-12 PbeParams structure\n * \\param mode       either #MBEDTLS_PKCS12_PBE_ENCRYPT or\n *                   #MBEDTLS_PKCS12_PBE_DECRYPT\n * \\param cipher_type the cipher used\n * \\param md_type    the mbedtls_md used\n * \\param pwd        Latin1-encoded password used. This may only be \\c NULL when\n *                   \\p pwdlen is 0. No null terminator should be used.\n * \\param pwdlen     length of the password (may be 0)\n * \\param data       the input data\n * \\param len        data length\n * \\param output     Output buffer.\n *                   On success, it contains the encrypted or decrypted data,\n *                   possibly followed by the CBC padding.\n *                   On failure, the content is indeterminate.\n *                   For decryption, there must be enough room for \\p len\n *                   bytes.\n *                   For encryption, there must be enough room for\n *                   \\p len + 1 bytes, rounded up to the block size of\n *                   the block cipher identified by \\p pbe_params.\n *\n * \\return           0 if successful, or a MBEDTLS_ERR_XXX code\n */\nint MBEDTLS_DEPRECATED mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode,\n                                          mbedtls_cipher_type_t cipher_type,\n                                          mbedtls_md_type_t md_type,\n                                          const unsigned char *pwd,  size_t pwdlen,\n                                          const unsigned char *data, size_t len,\n                                          unsigned char *output);\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n\n#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)\n\n/**\n * \\brief            PKCS12 Password Based function (encryption / decryption)\n *                   for cipher-based and mbedtls_md-based PBE's\n *\n *\n * \\warning          When decrypting:\n *                   - This function validates the CBC padding and returns\n *                     #MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH if the padding is\n *                     invalid. Note that this can help active adversaries\n *                     attempting to brute-forcing the password. Note also that\n *                     there is no guarantee that an invalid password will be\n *                     detected (the chances of a valid padding with a random\n *                     password are about 1/255).\n *\n * \\param pbe_params an ASN1 buffer containing the pkcs-12 PbeParams structure\n * \\param mode       either #MBEDTLS_PKCS12_PBE_ENCRYPT or\n *                   #MBEDTLS_PKCS12_PBE_DECRYPT\n * \\param cipher_type the cipher used\n * \\param md_type    the mbedtls_md used\n * \\param pwd        Latin1-encoded password used. This may only be \\c NULL when\n *                   \\p pwdlen is 0. No null terminator should be used.\n * \\param pwdlen     length of the password (may be 0)\n * \\param data       the input data\n * \\param len        data length\n * \\param output     Output buffer.\n *                   On success, it contains the encrypted or decrypted data,\n *                   possibly followed by the CBC padding.\n *                   On failure, the content is indeterminate.\n *                   For decryption, there must be enough room for \\p len\n *                   bytes.\n *                   For encryption, there must be enough room for\n *                   \\p len + 1 bytes, rounded up to the block size of\n *                   the block cipher identified by \\p pbe_params.\n * \\param output_size size of output buffer.\n *                    This must be big enough to accommodate for output plus\n *                    padding data.\n * \\param output_len On success, length of actual data written to the output buffer.\n *\n * \\return           0 if successful, or a MBEDTLS_ERR_XXX code\n */\nint mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode,\n                           mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,\n                           const unsigned char *pwd,  size_t pwdlen,\n                           const unsigned char *data, size_t len,\n                           unsigned char *output, size_t output_size,\n                           size_t *output_len);\n\n#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */\n\n#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */\n\n/**\n * \\brief            The PKCS#12 derivation function uses a password and a salt\n *                   to produce pseudo-random bits for a particular \"purpose\".\n *\n *                   Depending on the given id, this function can produce an\n *                   encryption/decryption key, an initialization vector or an\n *                   integrity key.\n *\n * \\param data       buffer to store the derived data in\n * \\param datalen    length of buffer to fill\n * \\param pwd        The password to use. For compliance with PKCS#12 §B.1, this\n *                   should be a BMPString, i.e. a Unicode string where each\n *                   character is encoded as 2 bytes in big-endian order, with\n *                   no byte order mark and with a null terminator (i.e. the\n *                   last two bytes should be 0x00 0x00).\n * \\param pwdlen     length of the password (may be 0).\n * \\param salt       Salt buffer to use. This may only be \\c NULL when\n *                   \\p saltlen is 0.\n * \\param saltlen    length of the salt (may be zero)\n * \\param mbedtls_md mbedtls_md type to use during the derivation\n * \\param id         id that describes the purpose (can be\n *                   #MBEDTLS_PKCS12_DERIVE_KEY, #MBEDTLS_PKCS12_DERIVE_IV or\n *                   #MBEDTLS_PKCS12_DERIVE_MAC_KEY)\n * \\param iterations number of iterations\n *\n * \\return          0 if successful, or a MD, BIGNUM type error.\n */\nint mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen,\n                              const unsigned char *pwd, size_t pwdlen,\n                              const unsigned char *salt, size_t saltlen,\n                              mbedtls_md_type_t mbedtls_md, int id, int iterations);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* pkcs12.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/pkcs5.h",
    "content": "/**\n * \\file pkcs5.h\n *\n * \\brief PKCS#5 functions\n *\n * \\author Mathias Olsson <mathias@kompetensum.com>\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_PKCS5_H\n#define MBEDTLS_PKCS5_H\n\n#include \"mbedtls/build_info.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include \"mbedtls/asn1.h\"\n#include \"mbedtls/md.h\"\n#include \"mbedtls/cipher.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n/** Bad input parameters to function. */\n#define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA                  -0x2f80\n/** Unexpected ASN.1 data. */\n#define MBEDTLS_ERR_PKCS5_INVALID_FORMAT                  -0x2f00\n/** Requested encryption or digest alg not available. */\n#define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE             -0x2e80\n/** Given private key password does not allow for correct decryption. */\n#define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH               -0x2e00\n\n#define MBEDTLS_PKCS5_DECRYPT      MBEDTLS_DECRYPT\n#define MBEDTLS_PKCS5_ENCRYPT      MBEDTLS_ENCRYPT\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C)\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n/**\n * \\brief          PKCS#5 PBES2 function\n *\n * \\note           When encrypting, #MBEDTLS_CIPHER_PADDING_PKCS7 must\n *                 be enabled at compile time.\n *\n * \\deprecated     This function is deprecated and will be removed in a\n *                 future version of the library.\n *                 Please use mbedtls_pkcs5_pbes2_ext() instead.\n *\n * \\warning        When decrypting:\n *                 - if #MBEDTLS_CIPHER_PADDING_PKCS7 is enabled at compile\n *                   time, this function validates the CBC padding and returns\n *                   #MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH if the padding is\n *                   invalid. Note that this can help active adversaries\n *                   attempting to brute-forcing the password. Note also that\n *                   there is no guarantee that an invalid password will be\n *                   detected (the chances of a valid padding with a random\n *                   password are about 1/255).\n *                 - if #MBEDTLS_CIPHER_PADDING_PKCS7 is disabled at compile\n *                   time, this function does not validate the CBC padding.\n *\n * \\param pbe_params the ASN.1 algorithm parameters\n * \\param mode       either #MBEDTLS_PKCS5_DECRYPT or #MBEDTLS_PKCS5_ENCRYPT\n * \\param pwd        password to use when generating key\n * \\param pwdlen     length of password\n * \\param data       data to process\n * \\param datalen    length of data\n * \\param output     Output buffer.\n *                   On success, it contains the encrypted or decrypted data,\n *                   possibly followed by the CBC padding.\n *                   On failure, the content is indeterminate.\n *                   For decryption, there must be enough room for \\p datalen\n *                   bytes.\n *                   For encryption, there must be enough room for\n *                   \\p datalen + 1 bytes, rounded up to the block size of\n *                   the block cipher identified by \\p pbe_params.\n *\n * \\returns        0 on success, or a MBEDTLS_ERR_XXX code if verification fails.\n */\nint MBEDTLS_DEPRECATED mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,\n                                           const unsigned char *pwd,  size_t pwdlen,\n                                           const unsigned char *data, size_t datalen,\n                                           unsigned char *output);\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n\n#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)\n\n/**\n * \\brief          PKCS#5 PBES2 function\n *\n * \\warning        When decrypting:\n *                 - This function validates the CBC padding and returns\n *                   #MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH if the padding is\n *                   invalid. Note that this can help active adversaries\n *                   attempting to brute-forcing the password. Note also that\n *                   there is no guarantee that an invalid password will be\n *                   detected (the chances of a valid padding with a random\n *                   password are about 1/255).\n *\n * \\param pbe_params the ASN.1 algorithm parameters\n * \\param mode       either #MBEDTLS_PKCS5_DECRYPT or #MBEDTLS_PKCS5_ENCRYPT\n * \\param pwd        password to use when generating key\n * \\param pwdlen     length of password\n * \\param data       data to process\n * \\param datalen    length of data\n * \\param output     Output buffer.\n *                   On success, it contains the decrypted data.\n *                   On failure, the content is indetermidate.\n *                   For decryption, there must be enough room for \\p datalen\n *                   bytes.\n *                   For encryption, there must be enough room for\n *                   \\p datalen + 1 bytes, rounded up to the block size of\n *                   the block cipher identified by \\p pbe_params.\n * \\param output_size size of output buffer.\n *                    This must be big enough to accommodate for output plus\n *                    padding data.\n * \\param output_len On success, length of actual data written to the output buffer.\n *\n * \\returns        0 on success, or a MBEDTLS_ERR_XXX code if parsing or decryption fails.\n */\nint mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode,\n                            const unsigned char *pwd,  size_t pwdlen,\n                            const unsigned char *data, size_t datalen,\n                            unsigned char *output, size_t output_size,\n                            size_t *output_len);\n\n#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */\n\n#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C*/\n\n/**\n * \\brief          PKCS#5 PBKDF2 using HMAC without using the HMAC context\n *\n * \\param md_type  Hash algorithm used\n * \\param password Password to use when generating key\n * \\param plen     Length of password\n * \\param salt     Salt to use when generating key\n * \\param slen     Length of salt\n * \\param iteration_count       Iteration count\n * \\param key_length            Length of generated key in bytes\n * \\param output   Generated key. Must be at least as big as key_length\n *\n * \\returns        0 on success, or a MBEDTLS_ERR_XXX code if verification fails.\n */\nint mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_type,\n                                  const unsigned char *password,\n                                  size_t plen, const unsigned char *salt, size_t slen,\n                                  unsigned int iteration_count,\n                                  uint32_t key_length, unsigned char *output);\n\n#if defined(MBEDTLS_MD_C)\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n/**\n * \\brief          PKCS#5 PBKDF2 using HMAC\n *\n * \\deprecated     Superseded by mbedtls_pkcs5_pbkdf2_hmac_ext().\n *\n * \\param ctx      Generic HMAC context\n * \\param password Password to use when generating key\n * \\param plen     Length of password\n * \\param salt     Salt to use when generating key\n * \\param slen     Length of salt\n * \\param iteration_count       Iteration count\n * \\param key_length            Length of generated key in bytes\n * \\param output   Generated key. Must be at least as big as key_length\n *\n * \\returns        0 on success, or a MBEDTLS_ERR_XXX code if verification fails.\n */\nint MBEDTLS_DEPRECATED mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx,\n                                                 const unsigned char *password,\n                                                 size_t plen,\n                                                 const unsigned char *salt,\n                                                 size_t slen,\n                                                 unsigned int iteration_count,\n                                                 uint32_t key_length,\n                                                 unsigned char *output);\n#endif /* !MBEDTLS_DEPRECATED_REMOVED */\n#endif /* MBEDTLS_MD_C */\n#if defined(MBEDTLS_SELF_TEST)\n\n/**\n * \\brief          Checkup routine\n *\n * \\return         0 if successful, or 1 if the test failed\n */\nint mbedtls_pkcs5_self_test(int verbose);\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* pkcs5.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/pkcs7.h",
    "content": "/**\n * \\file pkcs7.h\n *\n * \\brief PKCS #7 generic defines and structures\n *  https://tools.ietf.org/html/rfc2315\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/**\n * Note: For the time being, this implementation of the PKCS #7 cryptographic\n * message syntax is a partial implementation of RFC 2315.\n * Differences include:\n *  - The RFC specifies 6 different content types. The only type currently\n *    supported in Mbed TLS is the signed-data content type.\n *  - The only supported PKCS #7 Signed Data syntax version is version 1\n *  - The RFC specifies support for BER. This implementation is limited to\n *    DER only.\n *  - The RFC specifies that multiple digest algorithms can be specified\n *    in the Signed Data type. Only one digest algorithm is supported in Mbed TLS.\n *  - The RFC specifies the Signed Data type can contain multiple X.509 or PKCS #6 extended\n *    certificates. In Mbed TLS, this list can only contain 0 or 1 certificates\n *    and they must be in X.509 format.\n *  - The RFC specifies the Signed Data type can contain\n *    certificate-revocation lists (CRLs). This implementation has no support\n *    for CRLs so it is assumed to be an empty list.\n *  - The RFC allows for SignerInfo structure to optionally contain\n *    unauthenticatedAttributes and authenticatedAttributes. In Mbed TLS it is\n *    assumed these fields are empty.\n *  - The RFC allows for the signed Data type to contain contentInfo. This\n *    implementation assumes the type is DATA and the content is empty.\n */\n\n#ifndef MBEDTLS_PKCS7_H\n#define MBEDTLS_PKCS7_H\n\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/asn1.h\"\n#include \"mbedtls/x509_crt.h\"\n\n/**\n * \\name PKCS #7 Module Error codes\n * \\{\n */\n#define MBEDTLS_ERR_PKCS7_INVALID_FORMAT                   -0x5300  /**< The format is invalid, e.g. different type expected. */\n#define MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE              -0x5380  /**< Unavailable feature, e.g. anything other than signed data. */\n#define MBEDTLS_ERR_PKCS7_INVALID_VERSION                  -0x5400  /**< The PKCS #7 version element is invalid or cannot be parsed. */\n#define MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO             -0x5480  /**< The PKCS #7 content info is invalid or cannot be parsed. */\n#define MBEDTLS_ERR_PKCS7_INVALID_ALG                      -0x5500  /**< The algorithm tag or value is invalid or cannot be parsed. */\n#define MBEDTLS_ERR_PKCS7_INVALID_CERT                     -0x5580  /**< The certificate tag or value is invalid or cannot be parsed. */\n#define MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE                -0x5600  /**< Error parsing the signature */\n#define MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO              -0x5680  /**< Error parsing the signer's info */\n#define MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA                   -0x5700  /**< Input invalid. */\n#define MBEDTLS_ERR_PKCS7_ALLOC_FAILED                     -0x5780  /**< Allocation of memory failed. */\n#define MBEDTLS_ERR_PKCS7_VERIFY_FAIL                      -0x5800  /**< Verification Failed */\n#define MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID                -0x5880  /**< The PKCS #7 date issued/expired dates are invalid */\n/* \\} name */\n\n/**\n * \\name PKCS #7 Supported Version\n * \\{\n */\n#define MBEDTLS_PKCS7_SUPPORTED_VERSION                           0x01\n/* \\} name */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Type-length-value structure that allows for ASN.1 using DER.\n */\ntypedef mbedtls_asn1_buf mbedtls_pkcs7_buf;\n\n/**\n * Container for ASN.1 named information objects.\n * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.).\n */\ntypedef mbedtls_asn1_named_data mbedtls_pkcs7_name;\n\n/**\n * Container for a sequence of ASN.1 items\n */\ntypedef mbedtls_asn1_sequence mbedtls_pkcs7_sequence;\n\n/**\n * PKCS #7 types\n */\ntypedef enum {\n    MBEDTLS_PKCS7_NONE=0,\n    MBEDTLS_PKCS7_DATA,\n    MBEDTLS_PKCS7_SIGNED_DATA,\n    MBEDTLS_PKCS7_ENVELOPED_DATA,\n    MBEDTLS_PKCS7_SIGNED_AND_ENVELOPED_DATA,\n    MBEDTLS_PKCS7_DIGESTED_DATA,\n    MBEDTLS_PKCS7_ENCRYPTED_DATA,\n}\nmbedtls_pkcs7_type;\n\n/**\n * Structure holding PKCS #7 signer info\n */\ntypedef struct mbedtls_pkcs7_signer_info {\n    int MBEDTLS_PRIVATE(version);\n    mbedtls_x509_buf MBEDTLS_PRIVATE(serial);\n    mbedtls_x509_name MBEDTLS_PRIVATE(issuer);\n    mbedtls_x509_buf MBEDTLS_PRIVATE(issuer_raw);\n    mbedtls_x509_buf MBEDTLS_PRIVATE(alg_identifier);\n    mbedtls_x509_buf MBEDTLS_PRIVATE(sig_alg_identifier);\n    mbedtls_x509_buf MBEDTLS_PRIVATE(sig);\n    struct mbedtls_pkcs7_signer_info *MBEDTLS_PRIVATE(next);\n}\nmbedtls_pkcs7_signer_info;\n\n/**\n * Structure holding the signed data section\n */\ntypedef struct mbedtls_pkcs7_signed_data {\n    int MBEDTLS_PRIVATE(version);\n    mbedtls_pkcs7_buf MBEDTLS_PRIVATE(digest_alg_identifiers);\n    int MBEDTLS_PRIVATE(no_of_certs);\n    mbedtls_x509_crt MBEDTLS_PRIVATE(certs);\n    int MBEDTLS_PRIVATE(no_of_crls);\n    mbedtls_x509_crl MBEDTLS_PRIVATE(crl);\n    int MBEDTLS_PRIVATE(no_of_signers);\n    mbedtls_pkcs7_signer_info MBEDTLS_PRIVATE(signers);\n}\nmbedtls_pkcs7_signed_data;\n\n/**\n * Structure holding PKCS #7 structure, only signed data for now\n */\ntypedef struct mbedtls_pkcs7 {\n    mbedtls_pkcs7_buf MBEDTLS_PRIVATE(raw);\n    mbedtls_pkcs7_signed_data MBEDTLS_PRIVATE(signed_data);\n}\nmbedtls_pkcs7;\n\n/**\n * \\brief          Initialize mbedtls_pkcs7 structure.\n *\n * \\param pkcs7    mbedtls_pkcs7 structure.\n */\nvoid mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7);\n\n/**\n * \\brief          Parse a single DER formatted PKCS #7 detached signature.\n *\n * \\param pkcs7    The mbedtls_pkcs7 structure to be filled by the parser.\n * \\param buf      The buffer holding only the DER encoded PKCS #7 content.\n * \\param buflen   The size in bytes of \\p buf. The size must be exactly the\n *                 length of the DER encoded PKCS #7 content.\n *\n * \\note           This function makes an internal copy of the PKCS #7 buffer\n *                 \\p buf. In particular, \\p buf may be destroyed or reused\n *                 after this call returns.\n * \\note           Signatures with internal data are not supported.\n *\n * \\return         The \\c mbedtls_pkcs7_type of \\p buf, if successful.\n * \\return         A negative error code on failure.\n */\nint mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf,\n                            const size_t buflen);\n\n/**\n * \\brief          Verification of PKCS #7 signature against a caller-supplied\n *                 certificate.\n *\n *                 For each signer in the PKCS structure, this function computes\n *                 a signature over the supplied data, using the supplied\n *                 certificate and the same digest algorithm as specified by the\n *                 signer. It then compares this signature against the\n *                 signer's signature; verification succeeds if any comparison\n *                 matches.\n *\n *                 This function does not use the certificates held within the\n *                 PKCS #7 structure itself, and does not check that the\n *                 certificate is signed by a trusted certification authority.\n *\n * \\param pkcs7    mbedtls_pkcs7 structure containing signature.\n * \\param cert     Certificate containing key to verify signature.\n * \\param data     Plain data on which signature has to be verified.\n * \\param datalen  Length of the data.\n *\n * \\note           This function internally calculates the hash on the supplied\n *                 plain data for signature verification.\n *\n * \\return         0 if the signature verifies, or a negative error code on failure.\n */\nint mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7,\n                                     const mbedtls_x509_crt *cert,\n                                     const unsigned char *data,\n                                     size_t datalen);\n\n/**\n * \\brief          Verification of PKCS #7 signature against a caller-supplied\n *                 certificate.\n *\n *                 For each signer in the PKCS structure, this function\n *                 validates a signature over the supplied hash, using the\n *                 supplied certificate and the same digest algorithm as\n *                 specified by the signer. Verification succeeds if any\n *                 signature is good.\n *\n *                 This function does not use the certificates held within the\n *                 PKCS #7 structure itself, and does not check that the\n *                 certificate is signed by a trusted certification authority.\n *\n * \\param pkcs7    PKCS #7 structure containing signature.\n * \\param cert     Certificate containing key to verify signature.\n * \\param hash     Hash of the plain data on which signature has to be verified.\n * \\param hashlen  Length of the hash.\n *\n * \\note           This function is different from mbedtls_pkcs7_signed_data_verify()\n *                 in that it is directly passed the hash of the data.\n *\n * \\return         0 if the signature verifies, or a negative error code on failure.\n */\nint mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7,\n                                     const mbedtls_x509_crt *cert,\n                                     const unsigned char *hash, size_t hashlen);\n\n/**\n * \\brief          Unallocate all PKCS #7 data and zeroize the memory.\n *                 It doesn't free \\p pkcs7 itself. This should be done by the caller.\n *\n * \\param pkcs7    mbedtls_pkcs7 structure to free.\n */\nvoid mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* pkcs7.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/platform.h",
    "content": "/**\n * \\file platform.h\n *\n * \\brief This file contains the definitions and functions of the\n *        Mbed TLS platform abstraction layer.\n *\n *        The platform abstraction layer removes the need for the library\n *        to directly link to standard C library functions or operating\n *        system services, making the library easier to port and embed.\n *        Application developers and users of the library can provide their own\n *        implementations of these functions, or implementations specific to\n *        their platform, which can be statically linked to the library or\n *        dynamically configured at runtime.\n *\n *        When all compilation options related to platform abstraction are\n *        disabled, this header just defines `mbedtls_xxx` function names\n *        as aliases to the standard `xxx` function.\n *\n *        Most modules in the library and example programs are expected to\n *        include this header.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_PLATFORM_H\n#define MBEDTLS_PLATFORM_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#if defined(MBEDTLS_HAVE_TIME)\n#include \"mbedtls/platform_time.h\"\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\name SECTION: Module settings\n *\n * The configuration options you can set for this module are in this section.\n * Either change them in mbedtls_config.h or define them on the compiler command line.\n * \\{\n */\n\n/* The older Microsoft Windows common runtime provides non-conforming\n * implementations of some standard library functions, including snprintf\n * and vsnprintf. This affects MSVC and MinGW builds.\n */\n#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900)\n#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF\n#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF\n#endif\n\n#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS)\n#include <stdio.h>\n#include <stdlib.h>\n#if defined(MBEDTLS_HAVE_TIME)\n#include <time.h>\n#endif\n#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF)\n#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF)\n#define MBEDTLS_PLATFORM_STD_SNPRINTF   mbedtls_platform_win32_snprintf /**< The default \\c snprintf function to use.  */\n#else\n#define MBEDTLS_PLATFORM_STD_SNPRINTF   snprintf /**< The default \\c snprintf function to use.  */\n#endif\n#endif\n#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF)\n#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF)\n#define MBEDTLS_PLATFORM_STD_VSNPRINTF   mbedtls_platform_win32_vsnprintf /**< The default \\c vsnprintf function to use.  */\n#else\n#define MBEDTLS_PLATFORM_STD_VSNPRINTF   vsnprintf /**< The default \\c vsnprintf function to use.  */\n#endif\n#endif\n#if !defined(MBEDTLS_PLATFORM_STD_PRINTF)\n#define MBEDTLS_PLATFORM_STD_PRINTF   printf /**< The default \\c printf function to use. */\n#endif\n#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF)\n#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< The default \\c fprintf function to use. */\n#endif\n#if !defined(MBEDTLS_PLATFORM_STD_CALLOC)\n#define MBEDTLS_PLATFORM_STD_CALLOC   calloc /**< The default \\c calloc function to use. */\n#endif\n#if !defined(MBEDTLS_PLATFORM_STD_FREE)\n#define MBEDTLS_PLATFORM_STD_FREE       free /**< The default \\c free function to use. */\n#endif\n#if !defined(MBEDTLS_PLATFORM_STD_SETBUF)\n#define MBEDTLS_PLATFORM_STD_SETBUF   setbuf /**< The default \\c setbuf function to use. */\n#endif\n#if !defined(MBEDTLS_PLATFORM_STD_EXIT)\n#define MBEDTLS_PLATFORM_STD_EXIT      exit /**< The default \\c exit function to use. */\n#endif\n#if !defined(MBEDTLS_PLATFORM_STD_TIME)\n#define MBEDTLS_PLATFORM_STD_TIME       time    /**< The default \\c time function to use. */\n#endif\n#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS)\n#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS  EXIT_SUCCESS /**< The default exit value to use. */\n#endif\n#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE)\n#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE  EXIT_FAILURE /**< The default exit value to use. */\n#endif\n#if defined(MBEDTLS_FS_IO)\n#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ)\n#define MBEDTLS_PLATFORM_STD_NV_SEED_READ   mbedtls_platform_std_nv_seed_read\n#endif\n#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE)\n#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE  mbedtls_platform_std_nv_seed_write\n#endif\n#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE)\n#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE   \"seedfile\"\n#endif\n#endif /* MBEDTLS_FS_IO */\n#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */\n#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR)\n#include MBEDTLS_PLATFORM_STD_MEM_HDR\n#endif\n#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */\n\n/* Enable certain documented defines only when generating doxygen to avoid\n * an \"unrecognized define\" error. */\n#if defined(__DOXYGEN__) && !defined(MBEDTLS_PLATFORM_STD_CALLOC)\n#define MBEDTLS_PLATFORM_STD_CALLOC\n#endif\n\n#if defined(__DOXYGEN__) && !defined(MBEDTLS_PLATFORM_STD_FREE)\n#define MBEDTLS_PLATFORM_STD_FREE\n#endif\n\n/** \\} name SECTION: Module settings */\n\n/*\n * The function pointers for calloc and free.\n * Please see MBEDTLS_PLATFORM_STD_CALLOC and MBEDTLS_PLATFORM_STD_FREE\n * in mbedtls_config.h for more information about behaviour and requirements.\n */\n#if defined(MBEDTLS_PLATFORM_MEMORY)\n#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \\\n    defined(MBEDTLS_PLATFORM_CALLOC_MACRO)\n#undef mbedtls_free\n#undef mbedtls_calloc\n#define mbedtls_free       MBEDTLS_PLATFORM_FREE_MACRO\n#define mbedtls_calloc     MBEDTLS_PLATFORM_CALLOC_MACRO\n#else\n/* For size_t */\n#include <stddef.h>\nextern void *mbedtls_calloc(size_t n, size_t size);\nextern void mbedtls_free(void *ptr);\n\n/**\n * \\brief               This function dynamically sets the memory-management\n *                      functions used by the library, during runtime.\n *\n * \\param calloc_func   The \\c calloc function implementation.\n * \\param free_func     The \\c free function implementation.\n *\n * \\return              \\c 0.\n */\nint mbedtls_platform_set_calloc_free(void *(*calloc_func)(size_t, size_t),\n                                     void (*free_func)(void *));\n#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */\n#else /* !MBEDTLS_PLATFORM_MEMORY */\n#undef mbedtls_free\n#undef mbedtls_calloc\n#define mbedtls_free       free\n#define mbedtls_calloc     calloc\n#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */\n\n/*\n * The function pointers for fprintf\n */\n#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT)\n/* We need FILE * */\n#include <stdio.h>\nextern int (*mbedtls_fprintf)(FILE *stream, const char *format, ...);\n\n/**\n * \\brief                This function dynamically configures the fprintf\n *                       function that is called when the\n *                       mbedtls_fprintf() function is invoked by the library.\n *\n * \\param fprintf_func   The \\c fprintf function implementation.\n *\n * \\return               \\c 0.\n */\nint mbedtls_platform_set_fprintf(int (*fprintf_func)(FILE *stream, const char *,\n                                                     ...));\n#else\n#undef mbedtls_fprintf\n#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO)\n#define mbedtls_fprintf    MBEDTLS_PLATFORM_FPRINTF_MACRO\n#else\n#define mbedtls_fprintf    fprintf\n#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */\n#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */\n\n/*\n * The function pointers for printf\n */\n#if defined(MBEDTLS_PLATFORM_PRINTF_ALT)\nextern int (*mbedtls_printf)(const char *format, ...);\n\n/**\n * \\brief               This function dynamically configures the snprintf\n *                      function that is called when the mbedtls_snprintf()\n *                      function is invoked by the library.\n *\n * \\param printf_func   The \\c printf function implementation.\n *\n * \\return              \\c 0 on success.\n */\nint mbedtls_platform_set_printf(int (*printf_func)(const char *, ...));\n#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */\n#undef mbedtls_printf\n#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO)\n#define mbedtls_printf     MBEDTLS_PLATFORM_PRINTF_MACRO\n#else\n#define mbedtls_printf     printf\n#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */\n#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */\n\n/*\n * The function pointers for snprintf\n *\n * The snprintf implementation should conform to C99:\n * - it *must* always correctly zero-terminate the buffer\n *   (except when n == 0, then it must leave the buffer untouched)\n * - however it is acceptable to return -1 instead of the required length when\n *   the destination buffer is too short.\n */\n#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF)\n/* For Windows (inc. MSYS2), we provide our own fixed implementation */\nint mbedtls_platform_win32_snprintf(char *s, size_t n, const char *fmt, ...);\n#endif\n\n#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)\nextern int (*mbedtls_snprintf)(char *s, size_t n, const char *format, ...);\n\n/**\n * \\brief                 This function allows configuring a custom\n *                        \\c snprintf function pointer.\n *\n * \\param snprintf_func   The \\c snprintf function implementation.\n *\n * \\return                \\c 0 on success.\n */\nint mbedtls_platform_set_snprintf(int (*snprintf_func)(char *s, size_t n,\n                                                       const char *format, ...));\n#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */\n#undef mbedtls_snprintf\n#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO)\n#define mbedtls_snprintf   MBEDTLS_PLATFORM_SNPRINTF_MACRO\n#else\n#define mbedtls_snprintf   MBEDTLS_PLATFORM_STD_SNPRINTF\n#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */\n#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */\n\n/*\n * The function pointers for vsnprintf\n *\n * The vsnprintf implementation should conform to C99:\n * - it *must* always correctly zero-terminate the buffer\n *   (except when n == 0, then it must leave the buffer untouched)\n * - however it is acceptable to return -1 instead of the required length when\n *   the destination buffer is too short.\n */\n#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF)\n#include <stdarg.h>\n/* For Older Windows (inc. MSYS2), we provide our own fixed implementation */\nint mbedtls_platform_win32_vsnprintf(char *s, size_t n, const char *fmt, va_list arg);\n#endif\n\n#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT)\n#include <stdarg.h>\nextern int (*mbedtls_vsnprintf)(char *s, size_t n, const char *format, va_list arg);\n\n/**\n * \\brief   Set your own snprintf function pointer\n *\n * \\param   vsnprintf_func   The \\c vsnprintf function implementation\n *\n * \\return  \\c 0\n */\nint mbedtls_platform_set_vsnprintf(int (*vsnprintf_func)(char *s, size_t n,\n                                                         const char *format, va_list arg));\n#else /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */\n#undef mbedtls_vsnprintf\n#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO)\n#define mbedtls_vsnprintf   MBEDTLS_PLATFORM_VSNPRINTF_MACRO\n#else\n#define mbedtls_vsnprintf   vsnprintf\n#endif /* MBEDTLS_PLATFORM_VSNPRINTF_MACRO */\n#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */\n\n/*\n * The function pointers for setbuf\n */\n#if defined(MBEDTLS_PLATFORM_SETBUF_ALT)\n#include <stdio.h>\n/**\n * \\brief                  Function pointer to call for `setbuf()` functionality\n *                         (changing the internal buffering on stdio calls).\n *\n * \\note                   The library calls this function to disable\n *                         buffering when reading or writing sensitive data,\n *                         to avoid having extra copies of sensitive data\n *                         remaining in stdio buffers after the file is\n *                         closed. If this is not a concern, for example if\n *                         your platform's stdio doesn't have any buffering,\n *                         you can set mbedtls_setbuf to a function that\n *                         does nothing.\n *\n *                         The library always calls this function with\n *                         `buf` equal to `NULL`.\n */\nextern void (*mbedtls_setbuf)(FILE *stream, char *buf);\n\n/**\n * \\brief                  Dynamically configure the function that is called\n *                         when the mbedtls_setbuf() function is called by the\n *                         library.\n *\n * \\param   setbuf_func   The \\c setbuf function implementation\n *\n * \\return                 \\c 0\n */\nint mbedtls_platform_set_setbuf(void (*setbuf_func)(\n                                    FILE *stream, char *buf));\n#else\n#undef mbedtls_setbuf\n#if defined(MBEDTLS_PLATFORM_SETBUF_MACRO)\n/**\n * \\brief                  Macro defining the function for the library to\n *                         call for `setbuf` functionality (changing the\n *                         internal buffering on stdio calls).\n *\n * \\note                   See extra comments on the mbedtls_setbuf() function\n *                         pointer above.\n *\n * \\return                 \\c 0 on success, negative on error.\n */\n#define mbedtls_setbuf    MBEDTLS_PLATFORM_SETBUF_MACRO\n#else\n#define mbedtls_setbuf    setbuf\n#endif /* MBEDTLS_PLATFORM_SETBUF_MACRO */\n#endif /* MBEDTLS_PLATFORM_SETBUF_ALT */\n\n/*\n * The function pointers for exit\n */\n#if defined(MBEDTLS_PLATFORM_EXIT_ALT)\nextern void (*mbedtls_exit)(int status);\n\n/**\n * \\brief             This function dynamically configures the exit\n *                    function that is called when the mbedtls_exit()\n *                    function is invoked by the library.\n *\n * \\param exit_func   The \\c exit function implementation.\n *\n * \\return            \\c 0 on success.\n */\nint mbedtls_platform_set_exit(void (*exit_func)(int status));\n#else\n#undef mbedtls_exit\n#if defined(MBEDTLS_PLATFORM_EXIT_MACRO)\n#define mbedtls_exit   MBEDTLS_PLATFORM_EXIT_MACRO\n#else\n#define mbedtls_exit   exit\n#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */\n#endif /* MBEDTLS_PLATFORM_EXIT_ALT */\n\n/*\n * The default exit values\n */\n#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS)\n#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS\n#else\n#define MBEDTLS_EXIT_SUCCESS 0\n#endif\n#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE)\n#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE\n#else\n#define MBEDTLS_EXIT_FAILURE 1\n#endif\n\n/*\n * The function pointers for reading from and writing a seed file to\n * Non-Volatile storage (NV) in a platform-independent way\n *\n * Only enabled when the NV seed entropy source is enabled\n */\n#if defined(MBEDTLS_ENTROPY_NV_SEED)\n#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO)\n/* Internal standard platform definitions */\nint mbedtls_platform_std_nv_seed_read(unsigned char *buf, size_t buf_len);\nint mbedtls_platform_std_nv_seed_write(unsigned char *buf, size_t buf_len);\n#endif\n\n#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT)\nextern int (*mbedtls_nv_seed_read)(unsigned char *buf, size_t buf_len);\nextern int (*mbedtls_nv_seed_write)(unsigned char *buf, size_t buf_len);\n\n/**\n * \\brief   This function allows configuring custom seed file writing and\n *          reading functions.\n *\n * \\param   nv_seed_read_func   The seed reading function implementation.\n * \\param   nv_seed_write_func  The seed writing function implementation.\n *\n * \\return  \\c 0 on success.\n */\nint mbedtls_platform_set_nv_seed(\n    int (*nv_seed_read_func)(unsigned char *buf, size_t buf_len),\n    int (*nv_seed_write_func)(unsigned char *buf, size_t buf_len)\n    );\n#else\n#undef mbedtls_nv_seed_read\n#undef mbedtls_nv_seed_write\n#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \\\n    defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO)\n#define mbedtls_nv_seed_read    MBEDTLS_PLATFORM_NV_SEED_READ_MACRO\n#define mbedtls_nv_seed_write   MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO\n#else\n#define mbedtls_nv_seed_read    mbedtls_platform_std_nv_seed_read\n#define mbedtls_nv_seed_write   mbedtls_platform_std_nv_seed_write\n#endif\n#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */\n#endif /* MBEDTLS_ENTROPY_NV_SEED */\n\n#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT)\n\n/**\n * \\brief   The platform context structure.\n *\n * \\note    This structure may be used to assist platform-specific\n *          setup or teardown operations.\n */\ntypedef struct mbedtls_platform_context {\n    char MBEDTLS_PRIVATE(dummy); /**< A placeholder member, as empty structs are not portable. */\n}\nmbedtls_platform_context;\n\n#else\n#include \"platform_alt.h\"\n#endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */\n\n/**\n * \\brief   This function performs any platform-specific initialization\n *          operations.\n *\n * \\note    This function should be called before any other library functions.\n *\n *          Its implementation is platform-specific, and unless\n *          platform-specific code is provided, it does nothing.\n *\n * \\note    The usage and necessity of this function is dependent on the platform.\n *\n * \\param   ctx     The platform context.\n *\n * \\return  \\c 0 on success.\n */\nint mbedtls_platform_setup(mbedtls_platform_context *ctx);\n/**\n * \\brief   This function performs any platform teardown operations.\n *\n * \\note    This function should be called after every other Mbed TLS module\n *          has been correctly freed using the appropriate free function.\n *\n *          Its implementation is platform-specific, and unless\n *          platform-specific code is provided, it does nothing.\n *\n * \\note    The usage and necessity of this function is dependent on the platform.\n *\n * \\param   ctx     The platform context.\n *\n */\nvoid mbedtls_platform_teardown(mbedtls_platform_context *ctx);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* platform.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/platform_time.h",
    "content": "/**\n * \\file platform_time.h\n *\n * \\brief Mbed TLS Platform time abstraction\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_PLATFORM_TIME_H\n#define MBEDTLS_PLATFORM_TIME_H\n\n#include \"mbedtls/build_info.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * The time_t datatype\n */\n#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO)\ntypedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t;\n#else\n/* For time_t */\n#include <time.h>\ntypedef time_t mbedtls_time_t;\n#endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */\n\n#if defined(MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO)\ntypedef MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO mbedtls_ms_time_t;\n#else\n#include <stdint.h>\n#include <inttypes.h>\ntypedef int64_t mbedtls_ms_time_t;\n#endif /* MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO */\n\n/**\n * \\brief   Get time in milliseconds.\n *\n * \\return Monotonically-increasing current time in milliseconds.\n *\n * \\note Define MBEDTLS_PLATFORM_MS_TIME_ALT to be able to provide an\n *       alternative implementation\n *\n * \\warning This function returns a monotonically-increasing time value from a\n *          start time that will differ from platform to platform, and possibly\n *          from run to run of the process.\n *\n */\nmbedtls_ms_time_t mbedtls_ms_time(void);\n\n/*\n * The function pointers for time\n */\n#if defined(MBEDTLS_PLATFORM_TIME_ALT)\nextern mbedtls_time_t (*mbedtls_time)(mbedtls_time_t *time);\n\n/**\n * \\brief   Set your own time function pointer\n *\n * \\param   time_func   the time function implementation\n *\n * \\return              0\n */\nint mbedtls_platform_set_time(mbedtls_time_t (*time_func)(mbedtls_time_t *time));\n#else\n#if defined(MBEDTLS_PLATFORM_TIME_MACRO)\n#define mbedtls_time    MBEDTLS_PLATFORM_TIME_MACRO\n#else\n#define mbedtls_time   time\n#endif /* MBEDTLS_PLATFORM_TIME_MACRO */\n#endif /* MBEDTLS_PLATFORM_TIME_ALT */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* platform_time.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/platform_util.h",
    "content": "/**\n * \\file platform_util.h\n *\n * \\brief Common and shared functions used by multiple modules in the Mbed TLS\n *        library.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_PLATFORM_UTIL_H\n#define MBEDTLS_PLATFORM_UTIL_H\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n#if defined(MBEDTLS_HAVE_TIME_DATE)\n#include \"mbedtls/platform_time.h\"\n#include <time.h>\n#endif /* MBEDTLS_HAVE_TIME_DATE */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Internal helper macros for deprecating API constants. */\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n#if defined(MBEDTLS_DEPRECATED_WARNING)\n#define MBEDTLS_DEPRECATED __attribute__((deprecated))\nMBEDTLS_DEPRECATED typedef char const *mbedtls_deprecated_string_constant_t;\n#define MBEDTLS_DEPRECATED_STRING_CONSTANT(VAL)       \\\n    ((mbedtls_deprecated_string_constant_t) (VAL))\nMBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t;\n#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(VAL)       \\\n    ((mbedtls_deprecated_numeric_constant_t) (VAL))\n#else /* MBEDTLS_DEPRECATED_WARNING */\n#define MBEDTLS_DEPRECATED\n#define MBEDTLS_DEPRECATED_STRING_CONSTANT(VAL) VAL\n#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(VAL) VAL\n#endif /* MBEDTLS_DEPRECATED_WARNING */\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n\n/* Implementation of the check-return facility.\n * See the user documentation in mbedtls_config.h.\n *\n * Do not use this macro directly to annotate function: instead,\n * use one of MBEDTLS_CHECK_RETURN_CRITICAL or MBEDTLS_CHECK_RETURN_TYPICAL\n * depending on how important it is to check the return value.\n */\n#if !defined(MBEDTLS_CHECK_RETURN)\n#if defined(__GNUC__)\n#define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__))\n#elif defined(_MSC_VER) && _MSC_VER >= 1700\n#include <sal.h>\n#define MBEDTLS_CHECK_RETURN _Check_return_\n#else\n#define MBEDTLS_CHECK_RETURN\n#endif\n#endif\n\n/** Critical-failure function\n *\n * This macro appearing at the beginning of the declaration of a function\n * indicates that its return value should be checked in all applications.\n * Omitting the check is very likely to indicate a bug in the application\n * and will result in a compile-time warning if #MBEDTLS_CHECK_RETURN\n * is implemented for the compiler in use.\n *\n * \\note  The use of this macro is a work in progress.\n *        This macro may be added to more functions in the future.\n *        Such an extension is not considered an API break, provided that\n *        there are near-unavoidable circumstances under which the function\n *        can fail. For example, signature/MAC/AEAD verification functions,\n *        and functions that require a random generator, are considered\n *        return-check-critical.\n */\n#define MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_CHECK_RETURN\n\n/** Ordinary-failure function\n *\n * This macro appearing at the beginning of the declaration of a function\n * indicates that its return value should be generally be checked in portable\n * applications. Omitting the check will result in a compile-time warning if\n * #MBEDTLS_CHECK_RETURN is implemented for the compiler in use and\n * #MBEDTLS_CHECK_RETURN_WARNING is enabled in the compile-time configuration.\n *\n * You can use #MBEDTLS_IGNORE_RETURN to explicitly ignore the return value\n * of a function that is annotated with #MBEDTLS_CHECK_RETURN.\n *\n * \\note  The use of this macro is a work in progress.\n *        This macro will be added to more functions in the future.\n *        Eventually this should appear before most functions returning\n *        an error code (as \\c int in the \\c mbedtls_xxx API or\n *        as ::psa_status_t in the \\c psa_xxx API).\n */\n#if defined(MBEDTLS_CHECK_RETURN_WARNING)\n#define MBEDTLS_CHECK_RETURN_TYPICAL MBEDTLS_CHECK_RETURN\n#else\n#define MBEDTLS_CHECK_RETURN_TYPICAL\n#endif\n\n/** Benign-failure function\n *\n * This macro appearing at the beginning of the declaration of a function\n * indicates that it is rarely useful to check its return value.\n *\n * This macro has an empty expansion. It exists for documentation purposes:\n * a #MBEDTLS_CHECK_RETURN_OPTIONAL annotation indicates that the function\n * has been analyzed for return-check usefulness, whereas the lack of\n * an annotation indicates that the function has not been analyzed and its\n * return-check usefulness is unknown.\n */\n#define MBEDTLS_CHECK_RETURN_OPTIONAL\n\n/** \\def MBEDTLS_IGNORE_RETURN\n *\n * Call this macro with one argument, a function call, to suppress a warning\n * from #MBEDTLS_CHECK_RETURN due to that function call.\n */\n#if !defined(MBEDTLS_IGNORE_RETURN)\n/* GCC doesn't silence the warning with just (void)(result).\n * (void)!(result) is known to work up at least up to GCC 10, as well\n * as with Clang and MSVC.\n *\n * https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Non_002dbugs.html\n * https://stackoverflow.com/questions/40576003/ignoring-warning-wunused-result\n * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425#c34\n */\n#define MBEDTLS_IGNORE_RETURN(result) ((void) !(result))\n#endif\n\n/* If the following macro is defined, the library is being built by the test\n * framework, and the framework is going to provide a replacement\n * mbedtls_platform_zeroize() using a preprocessor macro, so the function\n * declaration should be omitted.  */\n#if !defined(MBEDTLS_TEST_DEFINES_ZEROIZE) //no-check-names\n/**\n * \\brief       Securely zeroize a buffer\n *\n *              The function is meant to wipe the data contained in a buffer so\n *              that it can no longer be recovered even if the program memory\n *              is later compromised. Call this function on sensitive data\n *              stored on the stack before returning from a function, and on\n *              sensitive data stored on the heap before freeing the heap\n *              object.\n *\n *              It is extremely difficult to guarantee that calls to\n *              mbedtls_platform_zeroize() are not removed by aggressive\n *              compiler optimizations in a portable way. For this reason, Mbed\n *              TLS provides the configuration option\n *              MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure\n *              mbedtls_platform_zeroize() to use a suitable implementation for\n *              their platform and needs\n *\n * \\param buf   Buffer to be zeroized\n * \\param len   Length of the buffer in bytes\n *\n */\nvoid mbedtls_platform_zeroize(void *buf, size_t len);\n#endif\n\n/** \\brief              The type of custom random generator (RNG) callbacks.\n *\n *                      Many Mbed TLS functions take two parameters\n *                      `mbedtls_f_rng_t *f_rng, void *p_rng`. The\n *                      library will call \\c f_rng to generate\n *                      random values.\n *\n * \\note                This is typically one of the following:\n *                      - mbedtls_ctr_drbg_random() with \\c p_rng\n *                        pointing to a #mbedtls_ctr_drbg_context;\n *                      - mbedtls_hmac_drbg_random() with \\c p_rng\n *                        pointing to a #mbedtls_hmac_drbg_context;\n *                      - mbedtls_psa_get_random() with\n *                        `prng = MBEDTLS_PSA_RANDOM_STATE`.\n *\n * \\note                Generally, given a call\n *                      `mbedtls_foo(f_rng, p_rng, ....)`, the RNG callback\n *                      and the context only need to remain valid until\n *                      the call to `mbedtls_foo` returns. However, there\n *                      are a few exceptions where the callback is stored\n *                      in for future use. Check the documentation of\n *                      the calling function.\n *\n * \\warning             In a multithreaded environment, calling the\n *                      function should be thread-safe. The standard\n *                      functions provided by the library are thread-safe\n *                      when #MBEDTLS_THREADING_C is enabled.\n *\n * \\warning             This function must either provide as many\n *                      bytes as requested of **cryptographic quality**\n *                      random data, or return a negative error code.\n *\n * \\param p_rng         The \\c p_rng argument that was passed along \\c f_rng.\n *                      The library always passes \\c p_rng unchanged.\n *                      This is typically a pointer to the random generator\n *                      state, or \\c NULL if the custom random generator\n *                      doesn't need a context-specific state.\n * \\param[out] output   On success, this must be filled with \\p output_size\n *                      bytes of cryptographic-quality random data.\n * \\param output_size   The number of bytes to output.\n *\n * \\return              \\c 0 on success, or a negative error code on failure.\n *                      Library functions will generally propagate this\n *                      error code, so \\c MBEDTLS_ERR_xxx values are\n *                      recommended. #MBEDTLS_ERR_ENTROPY_SOURCE_FAILED is\n *                      typically sensible for RNG failures.\n */\ntypedef int mbedtls_f_rng_t(void *p_rng,\n                            unsigned char *output, size_t output_size);\n\n#if defined(MBEDTLS_HAVE_TIME_DATE)\n/**\n * \\brief      Platform-specific implementation of gmtime_r()\n *\n *             The function is a thread-safe abstraction that behaves\n *             similarly to the gmtime_r() function from Unix/POSIX.\n *\n *             Mbed TLS will try to identify the underlying platform and\n *             make use of an appropriate underlying implementation (e.g.\n *             gmtime_r() for POSIX and gmtime_s() for Windows). If this is\n *             not possible, then gmtime() will be used. In this case, calls\n *             from the library to gmtime() will be guarded by the mutex\n *             mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is\n *             enabled. It is recommended that calls from outside the library\n *             are also guarded by this mutex.\n *\n *             If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will\n *             unconditionally use the alternative implementation for\n *             mbedtls_platform_gmtime_r() supplied by the user at compile time.\n *\n * \\param tt     Pointer to an object containing time (in seconds) since the\n *               epoch to be converted\n * \\param tm_buf Pointer to an object where the results will be stored\n *\n * \\return      Pointer to an object of type struct tm on success, otherwise\n *              NULL\n */\nstruct tm *mbedtls_platform_gmtime_r(const mbedtls_time_t *tt,\n                                     struct tm *tm_buf);\n#endif /* MBEDTLS_HAVE_TIME_DATE */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_PLATFORM_UTIL_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/poly1305.h",
    "content": "/**\n * \\file poly1305.h\n *\n * \\brief   This file contains Poly1305 definitions and functions.\n *\n *          Poly1305 is a one-time message authenticator that can be used to\n *          authenticate messages. Poly1305-AES was created by Daniel\n *          Bernstein https://cr.yp.to/mac/poly1305-20050329.pdf The generic\n *          Poly1305 algorithm (not tied to AES) was also standardized in RFC\n *          7539.\n *\n * \\author Daniel King <damaki.gh@gmail.com>\n */\n\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_POLY1305_H\n#define MBEDTLS_POLY1305_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include <stdint.h>\n#include <stddef.h>\n\n/** Invalid input parameter(s). */\n#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA         -0x0057\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_POLY1305_ALT)\n\ntypedef struct mbedtls_poly1305_context {\n    uint32_t MBEDTLS_PRIVATE(r)[4];      /** The value for 'r' (low 128 bits of the key). */\n    uint32_t MBEDTLS_PRIVATE(s)[4];      /** The value for 's' (high 128 bits of the key). */\n    uint32_t MBEDTLS_PRIVATE(acc)[5];    /** The accumulator number. */\n    uint8_t MBEDTLS_PRIVATE(queue)[16];  /** The current partial block of data. */\n    size_t MBEDTLS_PRIVATE(queue_len);   /** The number of bytes stored in 'queue'. */\n}\nmbedtls_poly1305_context;\n\n#else  /* MBEDTLS_POLY1305_ALT */\n#include \"poly1305_alt.h\"\n#endif /* MBEDTLS_POLY1305_ALT */\n\n/**\n * \\brief           This function initializes the specified Poly1305 context.\n *\n *                  It must be the first API called before using\n *                  the context.\n *\n *                  It is usually followed by a call to\n *                  \\c mbedtls_poly1305_starts(), then one or more calls to\n *                  \\c mbedtls_poly1305_update(), then one call to\n *                  \\c mbedtls_poly1305_finish(), then finally\n *                  \\c mbedtls_poly1305_free().\n *\n * \\param ctx       The Poly1305 context to initialize. This must\n *                  not be \\c NULL.\n */\nvoid mbedtls_poly1305_init(mbedtls_poly1305_context *ctx);\n\n/**\n * \\brief           This function releases and clears the specified\n *                  Poly1305 context.\n *\n * \\param ctx       The Poly1305 context to clear. This may be \\c NULL, in which\n *                  case this function is a no-op. If it is not \\c NULL, it must\n *                  point to an initialized Poly1305 context.\n */\nvoid mbedtls_poly1305_free(mbedtls_poly1305_context *ctx);\n\n/**\n * \\brief           This function sets the one-time authentication key.\n *\n * \\warning         The key must be unique and unpredictable for each\n *                  invocation of Poly1305.\n *\n * \\param ctx       The Poly1305 context to which the key should be bound.\n *                  This must be initialized.\n * \\param key       The buffer containing the \\c 32 Byte (\\c 256 Bit) key.\n *\n * \\return          \\c 0 on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_poly1305_starts(mbedtls_poly1305_context *ctx,\n                            const unsigned char key[32]);\n\n/**\n * \\brief           This functions feeds an input buffer into an ongoing\n *                  Poly1305 computation.\n *\n *                  It is called between \\c mbedtls_cipher_poly1305_starts() and\n *                  \\c mbedtls_cipher_poly1305_finish().\n *                  It can be called repeatedly to process a stream of data.\n *\n * \\param ctx       The Poly1305 context to use for the Poly1305 operation.\n *                  This must be initialized and bound to a key.\n * \\param ilen      The length of the input data in Bytes.\n *                  Any value is accepted.\n * \\param input     The buffer holding the input data.\n *                  This pointer can be \\c NULL if `ilen == 0`.\n *\n * \\return          \\c 0 on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_poly1305_update(mbedtls_poly1305_context *ctx,\n                            const unsigned char *input,\n                            size_t ilen);\n\n/**\n * \\brief           This function generates the Poly1305 Message\n *                  Authentication Code (MAC).\n *\n * \\param ctx       The Poly1305 context to use for the Poly1305 operation.\n *                  This must be initialized and bound to a key.\n * \\param mac       The buffer to where the MAC is written. This must\n *                  be a writable buffer of length \\c 16 Bytes.\n *\n * \\return          \\c 0 on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_poly1305_finish(mbedtls_poly1305_context *ctx,\n                            unsigned char mac[16]);\n\n/**\n * \\brief           This function calculates the Poly1305 MAC of the input\n *                  buffer with the provided key.\n *\n * \\warning         The key must be unique and unpredictable for each\n *                  invocation of Poly1305.\n *\n * \\param key       The buffer containing the \\c 32 Byte (\\c 256 Bit) key.\n * \\param ilen      The length of the input data in Bytes.\n *                  Any value is accepted.\n * \\param input     The buffer holding the input data.\n *                  This pointer can be \\c NULL if `ilen == 0`.\n * \\param mac       The buffer to where the MAC is written. This must be\n *                  a writable buffer of length \\c 16 Bytes.\n *\n * \\return          \\c 0 on success.\n * \\return          A negative error code on failure.\n */\nint mbedtls_poly1305_mac(const unsigned char key[32],\n                         const unsigned char *input,\n                         size_t ilen,\n                         unsigned char mac[16]);\n\n#if defined(MBEDTLS_SELF_TEST)\n/**\n * \\brief           The Poly1305 checkup routine.\n *\n * \\return          \\c 0 on success.\n * \\return          \\c 1 on failure.\n */\nint mbedtls_poly1305_self_test(int verbose);\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_POLY1305_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/private_access.h",
    "content": "/**\n * \\file private_access.h\n *\n * \\brief Macro wrapper for struct's members.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_PRIVATE_ACCESS_H\n#define MBEDTLS_PRIVATE_ACCESS_H\n\n#ifndef MBEDTLS_ALLOW_PRIVATE_ACCESS\n#define MBEDTLS_PRIVATE(member) private_##member\n#else\n#define MBEDTLS_PRIVATE(member) member\n#endif\n\n#endif /* MBEDTLS_PRIVATE_ACCESS_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/psa_util.h",
    "content": "/**\n * \\file psa_util.h\n *\n * \\brief Utility functions for the use of the PSA Crypto library.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_PSA_UTIL_H\n#define MBEDTLS_PSA_UTIL_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"psa/crypto.h\"\n\n/* ASN1 defines used in the ECDSA conversion functions.\n * Note: intentionally not adding MBEDTLS_ASN1_[PARSE|WRITE]_C guards here\n * otherwise error codes would be unknown in test_suite_psa_crypto_util.data.*/\n#include <mbedtls/asn1write.h>\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)\n\n/** The random generator function for the PSA subsystem.\n *\n * This function is suitable as the `f_rng` random generator function\n * parameter of many `mbedtls_xxx` functions.\n *\n * The implementation of this function depends on the configuration of the\n * library.\n *\n * \\note This function may only be used if the PSA crypto subsystem is active.\n *       This means that you must call psa_crypto_init() before any call to\n *       this function, and you must not call this function after calling\n *       mbedtls_psa_crypto_free().\n *\n * \\param p_rng         This parameter is only kept for backward compatibility\n *                      reasons with legacy `f_rng` functions and it's ignored.\n *                      Set to #MBEDTLS_PSA_RANDOM_STATE or NULL.\n * \\param output        The buffer to fill. It must have room for\n *                      \\c output_size bytes.\n * \\param output_size   The number of bytes to write to \\p output.\n *                      This function may fail if \\p output_size is too\n *                      large. It is guaranteed to accept any output size\n *                      requested by Mbed TLS library functions. The\n *                      maximum request size depends on the library\n *                      configuration.\n *\n * \\return              \\c 0 on success.\n * \\return              An `MBEDTLS_ERR_ENTROPY_xxx`,\n *                      `MBEDTLS_ERR_PLATFORM_xxx,\n *                      `MBEDTLS_ERR_CTR_DRBG_xxx` or\n *                      `MBEDTLS_ERR_HMAC_DRBG_xxx` on error.\n */\nint mbedtls_psa_get_random(void *p_rng,\n                           unsigned char *output,\n                           size_t output_size);\n\n/** The random generator state for the PSA subsystem.\n *\n * This macro always expands to NULL because the `p_rng` parameter is unused\n * in mbedtls_psa_get_random(), but it's kept for interface's backward\n * compatibility.\n */\n#define MBEDTLS_PSA_RANDOM_STATE    NULL\n\n/** \\defgroup psa_tls_helpers TLS helper functions\n * @{\n */\n#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)\n#include <mbedtls/ecp.h>\n\n/** Convert an ECC curve identifier from the Mbed TLS encoding to PSA.\n *\n * \\param grpid         An Mbed TLS elliptic curve identifier\n *                      (`MBEDTLS_ECP_DP_xxx`).\n * \\param[out] bits     On success the bit size of the curve; 0 on failure.\n *\n * \\return              If the curve is supported in the PSA API, this function\n *                      returns the proper PSA curve identifier\n *                      (`PSA_ECC_FAMILY_xxx`). This holds even if the curve is\n *                      not supported by the ECP module.\n * \\return              \\c 0 if the curve is not supported in the PSA API.\n */\npsa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid,\n                                          size_t *bits);\n\n/** Convert an ECC curve identifier from the PSA encoding to Mbed TLS.\n *\n * \\param family        A PSA elliptic curve family identifier\n *                      (`PSA_ECC_FAMILY_xxx`).\n * \\param bits          The bit-length of a private key on \\p curve.\n *\n * \\return              If the curve is supported in the PSA API, this function\n *                      returns the corresponding Mbed TLS elliptic curve\n *                      identifier (`MBEDTLS_ECP_DP_xxx`).\n * \\return              #MBEDTLS_ECP_DP_NONE if the combination of \\c curve\n *                      and \\p bits is not supported.\n */\nmbedtls_ecp_group_id mbedtls_ecc_group_from_psa(psa_ecc_family_t family,\n                                                size_t bits);\n#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */\n\n/**\n * \\brief           This function returns the PSA algorithm identifier\n *                  associated with the given digest type.\n *\n * \\param md_type   The type of digest to search for. Must not be NONE.\n *\n * \\warning         If \\p md_type is \\c MBEDTLS_MD_NONE, this function will\n *                  not return \\c PSA_ALG_NONE, but an invalid algorithm.\n *\n * \\warning         This function does not check if the algorithm is\n *                  supported, it always returns the corresponding identifier.\n *\n * \\return          The PSA algorithm identifier associated with \\p md_type,\n *                  regardless of whether it is supported or not.\n */\nstatic inline psa_algorithm_t mbedtls_md_psa_alg_from_type(mbedtls_md_type_t md_type)\n{\n    return PSA_ALG_CATEGORY_HASH | (psa_algorithm_t) md_type;\n}\n\n/**\n * \\brief           This function returns the given digest type\n *                  associated with the PSA algorithm identifier.\n *\n * \\param psa_alg   The PSA algorithm identifier to search for.\n *\n * \\warning         This function does not check if the algorithm is\n *                  supported, it always returns the corresponding identifier.\n *\n * \\return          The MD type associated with \\p psa_alg,\n *                  regardless of whether it is supported or not.\n */\nstatic inline mbedtls_md_type_t mbedtls_md_type_from_psa_alg(psa_algorithm_t psa_alg)\n{\n    return (mbedtls_md_type_t) (psa_alg & PSA_ALG_HASH_MASK);\n}\n#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */\n\n#if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)\n\n/** Convert an ECDSA signature from raw format to DER ASN.1 format.\n *\n * \\param       bits        Size of each coordinate in bits.\n * \\param       raw         Buffer that contains the signature in raw format.\n * \\param       raw_len     Length of \\p raw in bytes. This must be\n *                          PSA_BITS_TO_BYTES(bits) bytes.\n * \\param[out]  der         Buffer that will be filled with the converted DER\n *                          output. It can overlap with raw buffer.\n * \\param       der_size    Size of \\p der in bytes. It is enough if \\p der_size\n *                          is at least the size of the actual output. (The size\n *                          of the output can vary depending on the presence of\n *                          leading zeros in the data.) You can use\n *                          #MBEDTLS_ECDSA_MAX_SIG_LEN(\\p bits) to determine a\n *                          size that is large enough for all signatures for a\n *                          given value of \\p bits.\n * \\param[out]  der_len     On success it contains the amount of valid data\n *                          (in bytes) written to \\p der. It's undefined\n *                          in case of failure.\n *\n * \\note                    The behavior is undefined if \\p der is null,\n *                          even if \\p der_size is 0.\n *\n * \\return                  0 if successful.\n * \\return                  #MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if \\p der_size\n *                          is too small or if \\p bits is larger than the\n *                          largest supported curve.\n * \\return                  #MBEDTLS_ERR_ASN1_INVALID_DATA if one of the\n *                          numbers in the signature is 0.\n */\nint mbedtls_ecdsa_raw_to_der(size_t bits, const unsigned char *raw, size_t raw_len,\n                             unsigned char *der, size_t der_size, size_t *der_len);\n\n/** Convert an ECDSA signature from DER ASN.1 format to raw format.\n *\n * \\param       bits        Size of each coordinate in bits.\n * \\param       der         Buffer that contains the signature in DER format.\n * \\param       der_len     Size of \\p der in bytes.\n * \\param[out]  raw         Buffer that will be filled with the converted raw\n *                          signature. It can overlap with der buffer.\n * \\param       raw_size    Size of \\p raw in bytes. Must be at least\n *                          2 * PSA_BITS_TO_BYTES(bits) bytes.\n * \\param[out]  raw_len     On success it is updated with the amount of valid\n *                          data (in bytes) written to \\p raw. It's undefined\n *                          in case of failure.\n *\n * \\return                  0 if successful.\n * \\return                  #MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if \\p raw_size\n *                          is too small or if \\p bits is larger than the\n *                          largest supported curve.\n * \\return                  #MBEDTLS_ERR_ASN1_INVALID_DATA if the data in\n *                          \\p der is inconsistent with \\p bits.\n * \\return                  An \\c MBEDTLS_ERR_ASN1_xxx error code if\n *                          \\p der is malformed.\n */\nint mbedtls_ecdsa_der_to_raw(size_t bits, const unsigned char *der, size_t der_len,\n                             unsigned char *raw, size_t raw_size, size_t *raw_len);\n\n#endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */\n\n/**@}*/\n\n#endif /* MBEDTLS_PSA_UTIL_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/ripemd160.h",
    "content": "/**\n * \\file ripemd160.h\n *\n * \\brief RIPE MD-160 message digest\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_RIPEMD160_H\n#define MBEDTLS_RIPEMD160_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_RIPEMD160_ALT)\n// Regular implementation\n//\n\n/**\n * \\brief          RIPEMD-160 context structure\n */\ntypedef struct mbedtls_ripemd160_context {\n    uint32_t MBEDTLS_PRIVATE(total)[2];          /*!< number of bytes processed  */\n    uint32_t MBEDTLS_PRIVATE(state)[5];          /*!< intermediate digest state  */\n    unsigned char MBEDTLS_PRIVATE(buffer)[64];   /*!< data block being processed */\n}\nmbedtls_ripemd160_context;\n\n#else  /* MBEDTLS_RIPEMD160_ALT */\n#include \"ripemd160_alt.h\"\n#endif /* MBEDTLS_RIPEMD160_ALT */\n\n/**\n * \\brief          Initialize RIPEMD-160 context\n *\n * \\param ctx      RIPEMD-160 context to be initialized\n */\nvoid mbedtls_ripemd160_init(mbedtls_ripemd160_context *ctx);\n\n/**\n * \\brief          Clear RIPEMD-160 context\n *\n * \\param ctx      RIPEMD-160 context to be cleared\n */\nvoid mbedtls_ripemd160_free(mbedtls_ripemd160_context *ctx);\n\n/**\n * \\brief          Clone (the state of) a RIPEMD-160 context\n *\n * \\param dst      The destination context\n * \\param src      The context to be cloned\n */\nvoid mbedtls_ripemd160_clone(mbedtls_ripemd160_context *dst,\n                             const mbedtls_ripemd160_context *src);\n\n/**\n * \\brief          RIPEMD-160 context setup\n *\n * \\param ctx      context to be initialized\n *\n * \\return         0 if successful\n */\nint mbedtls_ripemd160_starts(mbedtls_ripemd160_context *ctx);\n\n/**\n * \\brief          RIPEMD-160 process buffer\n *\n * \\param ctx      RIPEMD-160 context\n * \\param input    buffer holding the data\n * \\param ilen     length of the input data\n *\n * \\return         0 if successful\n */\nint mbedtls_ripemd160_update(mbedtls_ripemd160_context *ctx,\n                             const unsigned char *input,\n                             size_t ilen);\n\n/**\n * \\brief          RIPEMD-160 final digest\n *\n * \\param ctx      RIPEMD-160 context\n * \\param output   RIPEMD-160 checksum result\n *\n * \\return         0 if successful\n */\nint mbedtls_ripemd160_finish(mbedtls_ripemd160_context *ctx,\n                             unsigned char output[20]);\n\n/**\n * \\brief          RIPEMD-160 process data block (internal use only)\n *\n * \\param ctx      RIPEMD-160 context\n * \\param data     buffer holding one block of data\n *\n * \\return         0 if successful\n */\nint mbedtls_internal_ripemd160_process(mbedtls_ripemd160_context *ctx,\n                                       const unsigned char data[64]);\n\n/**\n * \\brief          Output = RIPEMD-160( input buffer )\n *\n * \\param input    buffer holding the data\n * \\param ilen     length of the input data\n * \\param output   RIPEMD-160 checksum result\n *\n * \\return         0 if successful\n */\nint mbedtls_ripemd160(const unsigned char *input,\n                      size_t ilen,\n                      unsigned char output[20]);\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/**\n * \\brief          Checkup routine\n *\n * \\return         0 if successful, or 1 if the test failed\n */\nint mbedtls_ripemd160_self_test(int verbose);\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* mbedtls_ripemd160.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/rsa.h",
    "content": "/**\n * \\file rsa.h\n *\n * \\brief This file provides an API for the RSA public-key cryptosystem.\n *\n * The RSA public-key cryptosystem is defined in <em>Public-Key\n * Cryptography Standards (PKCS) #1 v1.5: RSA Encryption</em>\n * and <em>Public-Key Cryptography Standards (PKCS) #1 v2.1:\n * RSA Cryptography Specifications</em>.\n *\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_RSA_H\n#define MBEDTLS_RSA_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/bignum.h\"\n#include \"mbedtls/md.h\"\n\n#if defined(MBEDTLS_THREADING_C)\n#include \"mbedtls/threading.h\"\n#endif\n\n/*\n * RSA Error codes\n */\n/** Bad input parameters to function. */\n#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA                    -0x4080\n/** Input data contains invalid padding and is rejected. */\n#define MBEDTLS_ERR_RSA_INVALID_PADDING                   -0x4100\n/** Something failed during generation of a key. */\n#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED                    -0x4180\n/** Key failed to pass the validity check of the library. */\n#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED                  -0x4200\n/** The public key operation failed. */\n#define MBEDTLS_ERR_RSA_PUBLIC_FAILED                     -0x4280\n/** The private key operation failed. */\n#define MBEDTLS_ERR_RSA_PRIVATE_FAILED                    -0x4300\n/** The PKCS#1 verification failed. */\n#define MBEDTLS_ERR_RSA_VERIFY_FAILED                     -0x4380\n/** The output buffer for decryption is not large enough. */\n#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE                  -0x4400\n/** The random generator failed to generate non-zeros. */\n#define MBEDTLS_ERR_RSA_RNG_FAILED                        -0x4480\n\n/*\n * RSA constants\n */\n\n#define MBEDTLS_RSA_PKCS_V15    0 /**< Use PKCS#1 v1.5 encoding. */\n#define MBEDTLS_RSA_PKCS_V21    1 /**< Use PKCS#1 v2.1 encoding. */\n\n#define MBEDTLS_RSA_SIGN        1 /**< Identifier for RSA signature operations. */\n#define MBEDTLS_RSA_CRYPT       2 /**< Identifier for RSA encryption and decryption operations. */\n\n#define MBEDTLS_RSA_SALT_LEN_ANY    -1\n\n/*\n * The above constants may be used even if the RSA module is compile out,\n * eg for alternative (PKCS#11) RSA implementations in the PK layers.\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_RSA_ALT)\n// Regular implementation\n//\n\n#if !defined(MBEDTLS_RSA_GEN_KEY_MIN_BITS)\n#define MBEDTLS_RSA_GEN_KEY_MIN_BITS 1024\n#elif MBEDTLS_RSA_GEN_KEY_MIN_BITS < 128\n#error \"MBEDTLS_RSA_GEN_KEY_MIN_BITS must be at least 128 bits\"\n#endif\n\n/**\n * \\brief   The RSA context structure.\n */\ntypedef struct mbedtls_rsa_context {\n    int MBEDTLS_PRIVATE(ver);                    /*!<  Reserved for internal purposes.\n                                                  *    Do not set this field in application\n                                                  *    code. Its meaning might change without\n                                                  *    notice. */\n    size_t MBEDTLS_PRIVATE(len);                 /*!<  The size of \\p N in Bytes. */\n\n    mbedtls_mpi MBEDTLS_PRIVATE(N);              /*!<  The public modulus. */\n    mbedtls_mpi MBEDTLS_PRIVATE(E);              /*!<  The public exponent. */\n\n    mbedtls_mpi MBEDTLS_PRIVATE(D);              /*!<  The private exponent. */\n    mbedtls_mpi MBEDTLS_PRIVATE(P);              /*!<  The first prime factor. */\n    mbedtls_mpi MBEDTLS_PRIVATE(Q);              /*!<  The second prime factor. */\n\n    mbedtls_mpi MBEDTLS_PRIVATE(DP);             /*!<  <code>D % (P - 1)</code>. */\n    mbedtls_mpi MBEDTLS_PRIVATE(DQ);             /*!<  <code>D % (Q - 1)</code>. */\n    mbedtls_mpi MBEDTLS_PRIVATE(QP);             /*!<  <code>1 / (Q % P)</code>. */\n\n    mbedtls_mpi MBEDTLS_PRIVATE(RN);             /*!<  cached <code>R^2 mod N</code>. */\n\n    mbedtls_mpi MBEDTLS_PRIVATE(RP);             /*!<  cached <code>R^2 mod P</code>. */\n    mbedtls_mpi MBEDTLS_PRIVATE(RQ);             /*!<  cached <code>R^2 mod Q</code>. */\n\n    mbedtls_mpi MBEDTLS_PRIVATE(Vi);             /*!<  The cached blinding value. */\n    mbedtls_mpi MBEDTLS_PRIVATE(Vf);             /*!<  The cached un-blinding value. */\n\n    int MBEDTLS_PRIVATE(padding);                /*!< Selects padding mode:\n                                                  #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and\n                                                  #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */\n    int MBEDTLS_PRIVATE(hash_id);                /*!< Hash identifier of mbedtls_md_type_t type,\n                                                    as specified in md.h for use in the MGF\n                                                    mask generating function used in the\n                                                    EME-OAEP and EMSA-PSS encodings. */\n#if defined(MBEDTLS_THREADING_C)\n    /* Invariant: the mutex is initialized iff ver != 0. */\n    mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex);    /*!<  Thread-safety mutex. */\n#endif\n}\nmbedtls_rsa_context;\n\n#else  /* MBEDTLS_RSA_ALT */\n#include \"rsa_alt.h\"\n#endif /* MBEDTLS_RSA_ALT */\n\n/**\n * \\brief          This function initializes an RSA context.\n *\n * \\note           This function initializes the padding and the hash\n *                 identifier to respectively #MBEDTLS_RSA_PKCS_V15 and\n *                 #MBEDTLS_MD_NONE. See mbedtls_rsa_set_padding() for more\n *                 information about those parameters.\n *\n * \\param ctx      The RSA context to initialize. This must not be \\c NULL.\n */\nvoid mbedtls_rsa_init(mbedtls_rsa_context *ctx);\n\n/**\n * \\brief          This function sets padding for an already initialized RSA\n *                 context.\n *\n * \\note           Set padding to #MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP\n *                 encryption scheme and the RSASSA-PSS signature scheme.\n *\n * \\note           The \\p hash_id parameter is ignored when using\n *                 #MBEDTLS_RSA_PKCS_V15 padding.\n *\n * \\note           The choice of padding mode is strictly enforced for private\n *                 key operations, since there might be security concerns in\n *                 mixing padding modes. For public key operations it is\n *                 a default value, which can be overridden by calling specific\n *                 \\c mbedtls_rsa_rsaes_xxx or \\c mbedtls_rsa_rsassa_xxx\n *                 functions.\n *\n * \\note           The hash selected in \\p hash_id is always used for OEAP\n *                 encryption. For PSS signatures, it is always used for\n *                 making signatures, but can be overridden for verifying them.\n *                 If set to #MBEDTLS_MD_NONE, it is always overridden.\n *\n * \\param ctx      The initialized RSA context to be configured.\n * \\param padding  The padding mode to use. This must be either\n *                 #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21.\n * \\param hash_id  The hash identifier for PSS or OAEP, if \\p padding is\n *                 #MBEDTLS_RSA_PKCS_V21. #MBEDTLS_MD_NONE is accepted by this\n *                 function but may be not suitable for some operations.\n *                 Ignored if \\p padding is #MBEDTLS_RSA_PKCS_V15.\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_RSA_INVALID_PADDING failure:\n *                 \\p padding or \\p hash_id is invalid.\n */\nint mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding,\n                            mbedtls_md_type_t hash_id);\n\n/**\n * \\brief          This function retrieves padding mode of initialized\n *                 RSA context.\n *\n * \\param ctx      The initialized RSA context.\n *\n * \\return         RSA padding mode.\n *\n */\nint mbedtls_rsa_get_padding_mode(const mbedtls_rsa_context *ctx);\n\n/**\n * \\brief          This function retrieves hash identifier of mbedtls_md_type_t\n *                 type.\n *\n * \\param ctx      The initialized RSA context.\n *\n * \\return         Hash identifier of mbedtls_md_type_t type.\n *\n */\nint mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx);\n\n/**\n * \\brief          This function imports a set of core parameters into an\n *                 RSA context.\n *\n * \\note           This function can be called multiple times for successive\n *                 imports, if the parameters are not simultaneously present.\n *\n *                 Any sequence of calls to this function should be followed\n *                 by a call to mbedtls_rsa_complete(), which checks and\n *                 completes the provided information to a ready-for-use\n *                 public or private RSA key.\n *\n * \\note           See mbedtls_rsa_complete() for more information on which\n *                 parameters are necessary to set up a private or public\n *                 RSA key.\n *\n * \\note           The imported parameters are copied and need not be preserved\n *                 for the lifetime of the RSA context being set up.\n *\n * \\param ctx      The initialized RSA context to store the parameters in.\n * \\param N        The RSA modulus. This may be \\c NULL.\n * \\param P        The first prime factor of \\p N. This may be \\c NULL.\n * \\param Q        The second prime factor of \\p N. This may be \\c NULL.\n * \\param D        The private exponent. This may be \\c NULL.\n * \\param E        The public exponent. This may be \\c NULL.\n *\n * \\return         \\c 0 on success.\n * \\return         A non-zero error code on failure.\n */\nint mbedtls_rsa_import(mbedtls_rsa_context *ctx,\n                       const mbedtls_mpi *N,\n                       const mbedtls_mpi *P, const mbedtls_mpi *Q,\n                       const mbedtls_mpi *D, const mbedtls_mpi *E);\n\n/**\n * \\brief          This function imports core RSA parameters, in raw big-endian\n *                 binary format, into an RSA context.\n *\n * \\note           This function can be called multiple times for successive\n *                 imports, if the parameters are not simultaneously present.\n *\n *                 Any sequence of calls to this function should be followed\n *                 by a call to mbedtls_rsa_complete(), which checks and\n *                 completes the provided information to a ready-for-use\n *                 public or private RSA key.\n *\n * \\note           See mbedtls_rsa_complete() for more information on which\n *                 parameters are necessary to set up a private or public\n *                 RSA key.\n *\n * \\note           The imported parameters are copied and need not be preserved\n *                 for the lifetime of the RSA context being set up.\n *\n * \\param ctx      The initialized RSA context to store the parameters in.\n * \\param N        The RSA modulus. This may be \\c NULL.\n * \\param N_len    The Byte length of \\p N; it is ignored if \\p N == NULL.\n * \\param P        The first prime factor of \\p N. This may be \\c NULL.\n * \\param P_len    The Byte length of \\p P; it is ignored if \\p P == NULL.\n * \\param Q        The second prime factor of \\p N. This may be \\c NULL.\n * \\param Q_len    The Byte length of \\p Q; it is ignored if \\p Q == NULL.\n * \\param D        The private exponent. This may be \\c NULL.\n * \\param D_len    The Byte length of \\p D; it is ignored if \\p D == NULL.\n * \\param E        The public exponent. This may be \\c NULL.\n * \\param E_len    The Byte length of \\p E; it is ignored if \\p E == NULL.\n *\n * \\return         \\c 0 on success.\n * \\return         A non-zero error code on failure.\n */\nint mbedtls_rsa_import_raw(mbedtls_rsa_context *ctx,\n                           unsigned char const *N, size_t N_len,\n                           unsigned char const *P, size_t P_len,\n                           unsigned char const *Q, size_t Q_len,\n                           unsigned char const *D, size_t D_len,\n                           unsigned char const *E, size_t E_len);\n\n/**\n * \\brief          This function completes an RSA context from\n *                 a set of imported core parameters.\n *\n *                 To setup an RSA public key, precisely \\c N and \\c E\n *                 must have been imported.\n *\n *                 To setup an RSA private key, sufficient information must\n *                 be present for the other parameters to be derivable.\n *\n *                 The default implementation supports the following:\n *                 <ul><li>Derive \\c P, \\c Q from \\c N, \\c D, \\c E.</li>\n *                 <li>Derive \\c N, \\c D from \\c P, \\c Q, \\c E.</li></ul>\n *                 Alternative implementations need not support these.\n *\n *                 If this function runs successfully, it guarantees that\n *                 the RSA context can be used for RSA operations without\n *                 the risk of failure or crash.\n *\n * \\warning        This function need not perform consistency checks\n *                 for the imported parameters. In particular, parameters that\n *                 are not needed by the implementation might be silently\n *                 discarded and left unchecked. To check the consistency\n *                 of the key material, see mbedtls_rsa_check_privkey().\n *\n * \\param ctx      The initialized RSA context holding imported parameters.\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the attempted derivations\n *                 failed.\n *\n */\nint mbedtls_rsa_complete(mbedtls_rsa_context *ctx);\n\n/**\n * \\brief          This function exports the core parameters of an RSA key.\n *\n *                 If this function runs successfully, the non-NULL buffers\n *                 pointed to by \\p N, \\p P, \\p Q, \\p D, and \\p E are fully\n *                 written, with additional unused space filled leading by\n *                 zero Bytes.\n *\n *                 Possible reasons for returning\n *                 #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:<ul>\n *                 <li>An alternative RSA implementation is in use, which\n *                 stores the key externally, and either cannot or should\n *                 not export it into RAM.</li>\n *                 <li>A SW or HW implementation might not support a certain\n *                 deduction. For example, \\p P, \\p Q from \\p N, \\p D,\n *                 and \\p E if the former are not part of the\n *                 implementation.</li></ul>\n *\n *                 If the function fails due to an unsupported operation,\n *                 the RSA context stays intact and remains usable.\n *\n * \\param ctx      The initialized RSA context.\n * \\param N        The MPI to hold the RSA modulus.\n *                 This may be \\c NULL if this field need not be exported.\n * \\param P        The MPI to hold the first prime factor of \\p N.\n *                 This may be \\c NULL if this field need not be exported.\n * \\param Q        The MPI to hold the second prime factor of \\p N.\n *                 This may be \\c NULL if this field need not be exported.\n * \\param D        The MPI to hold the private exponent.\n *                 This may be \\c NULL if this field need not be exported.\n * \\param E        The MPI to hold the public exponent.\n *                 This may be \\c NULL if this field need not be exported.\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the\n *                 requested parameters cannot be done due to missing\n *                 functionality or because of security policies.\n * \\return         A non-zero return code on any other failure.\n *\n */\nint mbedtls_rsa_export(const mbedtls_rsa_context *ctx,\n                       mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q,\n                       mbedtls_mpi *D, mbedtls_mpi *E);\n\n/**\n * \\brief          This function exports core parameters of an RSA key\n *                 in raw big-endian binary format.\n *\n *                 If this function runs successfully, the non-NULL buffers\n *                 pointed to by \\p N, \\p P, \\p Q, \\p D, and \\p E are fully\n *                 written, with additional unused space filled leading by\n *                 zero Bytes.\n *\n *                 Possible reasons for returning\n *                 #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:<ul>\n *                 <li>An alternative RSA implementation is in use, which\n *                 stores the key externally, and either cannot or should\n *                 not export it into RAM.</li>\n *                 <li>A SW or HW implementation might not support a certain\n *                 deduction. For example, \\p P, \\p Q from \\p N, \\p D,\n *                 and \\p E if the former are not part of the\n *                 implementation.</li></ul>\n *                 If the function fails due to an unsupported operation,\n *                 the RSA context stays intact and remains usable.\n *\n * \\note           The length parameters are ignored if the corresponding\n *                 buffer pointers are NULL.\n *\n * \\param ctx      The initialized RSA context.\n * \\param N        The Byte array to store the RSA modulus,\n *                 or \\c NULL if this field need not be exported.\n * \\param N_len    The size of the buffer for the modulus.\n * \\param P        The Byte array to hold the first prime factor of \\p N,\n *                 or \\c NULL if this field need not be exported.\n * \\param P_len    The size of the buffer for the first prime factor.\n * \\param Q        The Byte array to hold the second prime factor of \\p N,\n *                 or \\c NULL if this field need not be exported.\n * \\param Q_len    The size of the buffer for the second prime factor.\n * \\param D        The Byte array to hold the private exponent,\n *                 or \\c NULL if this field need not be exported.\n * \\param D_len    The size of the buffer for the private exponent.\n * \\param E        The Byte array to hold the public exponent,\n *                 or \\c NULL if this field need not be exported.\n * \\param E_len    The size of the buffer for the public exponent.\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the\n *                 requested parameters cannot be done due to missing\n *                 functionality or because of security policies.\n * \\return         A non-zero return code on any other failure.\n */\nint mbedtls_rsa_export_raw(const mbedtls_rsa_context *ctx,\n                           unsigned char *N, size_t N_len,\n                           unsigned char *P, size_t P_len,\n                           unsigned char *Q, size_t Q_len,\n                           unsigned char *D, size_t D_len,\n                           unsigned char *E, size_t E_len);\n\n/**\n * \\brief          This function exports CRT parameters of a private RSA key.\n *\n * \\note           Alternative RSA implementations not using CRT-parameters\n *                 internally can implement this function based on\n *                 mbedtls_rsa_deduce_opt().\n *\n * \\param ctx      The initialized RSA context.\n * \\param DP       The MPI to hold \\c D modulo `P-1`,\n *                 or \\c NULL if it need not be exported.\n * \\param DQ       The MPI to hold \\c D modulo `Q-1`,\n *                 or \\c NULL if it need not be exported.\n * \\param QP       The MPI to hold modular inverse of \\c Q modulo \\c P,\n *                 or \\c NULL if it need not be exported.\n *\n * \\return         \\c 0 on success.\n * \\return         A non-zero error code on failure.\n *\n */\nint mbedtls_rsa_export_crt(const mbedtls_rsa_context *ctx,\n                           mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP);\n\n/**\n * \\brief          This function retrieves the length of the RSA modulus in bits.\n *\n * \\param ctx      The initialized RSA context.\n *\n * \\return         The length of the RSA modulus in bits.\n *\n */\nsize_t mbedtls_rsa_get_bitlen(const mbedtls_rsa_context *ctx);\n\n/**\n * \\brief          This function retrieves the length of RSA modulus in Bytes.\n *\n * \\param ctx      The initialized RSA context.\n *\n * \\return         The length of the RSA modulus in Bytes.\n *\n */\nsize_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx);\n\n/**\n * \\brief          This function generates an RSA keypair.\n *\n * \\note           mbedtls_rsa_init() must be called before this function,\n *                 to set up the RSA context.\n *\n * \\param ctx      The initialized RSA context used to hold the key.\n * \\param f_rng    The RNG function to be used for key generation.\n *                 This is mandatory and must not be \\c NULL.\n * \\param p_rng    The RNG context to be passed to \\p f_rng.\n *                 This may be \\c NULL if \\p f_rng doesn't need a context.\n * \\param nbits    The size of the public key in bits.\n * \\param exponent The public exponent to use. For example, \\c 65537.\n *                 This must be odd and greater than \\c 1.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx,\n                        mbedtls_f_rng_t *f_rng,\n                        void *p_rng,\n                        unsigned int nbits, int exponent);\n\n/**\n * \\brief          This function checks if a context contains at least an RSA\n *                 public key.\n *\n *                 If the function runs successfully, it is guaranteed that\n *                 enough information is present to perform an RSA public key\n *                 operation using mbedtls_rsa_public().\n *\n * \\param ctx      The initialized RSA context to check.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n *\n */\nint mbedtls_rsa_check_pubkey(const mbedtls_rsa_context *ctx);\n\n/**\n * \\brief      This function checks if a context contains an RSA private key\n *             and perform basic consistency checks.\n *\n * \\note       The consistency checks performed by this function not only\n *             ensure that mbedtls_rsa_private() can be called successfully\n *             on the given context, but that the various parameters are\n *             mutually consistent with high probability, in the sense that\n *             mbedtls_rsa_public() and mbedtls_rsa_private() are inverses.\n *\n * \\warning    This function should catch accidental misconfigurations\n *             like swapping of parameters, but it cannot establish full\n *             trust in neither the quality nor the consistency of the key\n *             material that was used to setup the given RSA context:\n *             <ul><li>Consistency: Imported parameters that are irrelevant\n *             for the implementation might be silently dropped. If dropped,\n *             the current function does not have access to them,\n *             and therefore cannot check them. See mbedtls_rsa_complete().\n *             If you want to check the consistency of the entire\n *             content of a PKCS1-encoded RSA private key, for example, you\n *             should use mbedtls_rsa_validate_params() before setting\n *             up the RSA context.\n *             Additionally, if the implementation performs empirical checks,\n *             these checks substantiate but do not guarantee consistency.</li>\n *             <li>Quality: This function is not expected to perform\n *             extended quality assessments like checking that the prime\n *             factors are safe. Additionally, it is the responsibility of the\n *             user to ensure the trustworthiness of the source of his RSA\n *             parameters, which goes beyond what is effectively checkable\n *             by the library.</li></ul>\n *\n * \\param ctx  The initialized RSA context to check.\n *\n * \\return     \\c 0 on success.\n * \\return     An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_check_privkey(const mbedtls_rsa_context *ctx);\n\n/**\n * \\brief          This function checks a public-private RSA key pair.\n *\n *                 It checks each of the contexts, and makes sure they match.\n *\n * \\param pub      The initialized RSA context holding the public key.\n * \\param prv      The initialized RSA context holding the private key.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_check_pub_priv(const mbedtls_rsa_context *pub,\n                               const mbedtls_rsa_context *prv);\n\n/**\n * \\brief          This function performs an RSA public key operation.\n *\n * \\param ctx      The initialized RSA context to use.\n * \\param input    The input buffer. This must be a readable buffer\n *                 of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus.\n * \\param output   The output buffer. This must be a writable buffer\n *                 of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus.\n *\n * \\note           This function does not handle message padding.\n *\n * \\note           Make sure to set \\p input[0] = 0 or ensure that\n *                 input is smaller than \\c N.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_public(mbedtls_rsa_context *ctx,\n                       const unsigned char *input,\n                       unsigned char *output);\n\n/**\n * \\brief          This function performs an RSA private key operation.\n *\n * \\note           Blinding is used if and only if a PRNG is provided.\n *\n * \\note           If blinding is used, both the base of exponentiation\n *                 and the exponent are blinded, providing protection\n *                 against some side-channel attacks.\n *\n * \\warning        It is deprecated and a security risk to not provide\n *                 a PRNG here and thereby prevent the use of blinding.\n *                 Future versions of the library may enforce the presence\n *                 of a PRNG.\n *\n * \\param ctx      The initialized RSA context to use.\n * \\param f_rng    The RNG function, used for blinding. It is mandatory.\n * \\param p_rng    The RNG context to pass to \\p f_rng. This may be \\c NULL\n *                 if \\p f_rng doesn't need a context.\n * \\param input    The input buffer. This must be a readable buffer\n *                 of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus.\n * \\param output   The output buffer. This must be a writable buffer\n *                 of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n *\n */\nint mbedtls_rsa_private(mbedtls_rsa_context *ctx,\n                        mbedtls_f_rng_t *f_rng,\n                        void *p_rng,\n                        const unsigned char *input,\n                        unsigned char *output);\n\n/**\n * \\brief          This function adds the message padding, then performs an RSA\n *                 operation.\n *\n *                 It is the generic wrapper for performing a PKCS#1 encryption\n *                 operation.\n *\n * \\param ctx      The initialized RSA context to use.\n * \\param f_rng    The RNG to use. It is used for padding generation\n *                 and it is mandatory.\n * \\param p_rng    The RNG context to be passed to \\p f_rng. May be\n *                 \\c NULL if \\p f_rng doesn't need a context argument.\n * \\param ilen     The length of the plaintext in Bytes.\n * \\param input    The input data to encrypt. This must be a readable\n *                 buffer of size \\p ilen Bytes. It may be \\c NULL if\n *                 `ilen == 0`.\n * \\param output   The output buffer. This must be a writable buffer\n *                 of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_pkcs1_encrypt(mbedtls_rsa_context *ctx,\n                              mbedtls_f_rng_t *f_rng,\n                              void *p_rng,\n                              size_t ilen,\n                              const unsigned char *input,\n                              unsigned char *output);\n\n/**\n * \\brief          This function performs a PKCS#1 v1.5 encryption operation\n *                 (RSAES-PKCS1-v1_5-ENCRYPT).\n *\n * \\param ctx      The initialized RSA context to use.\n * \\param f_rng    The RNG function to use. It is mandatory and used for\n *                 padding generation.\n * \\param p_rng    The RNG context to be passed to \\p f_rng. This may\n *                 be \\c NULL if \\p f_rng doesn't need a context argument.\n * \\param ilen     The length of the plaintext in Bytes.\n * \\param input    The input data to encrypt. This must be a readable\n *                 buffer of size \\p ilen Bytes. It may be \\c NULL if\n *                 `ilen == 0`.\n * \\param output   The output buffer. This must be a writable buffer\n *                 of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx,\n                                        mbedtls_f_rng_t *f_rng,\n                                        void *p_rng,\n                                        size_t ilen,\n                                        const unsigned char *input,\n                                        unsigned char *output);\n\n/**\n * \\brief            This function performs a PKCS#1 v2.1 OAEP encryption\n *                   operation (RSAES-OAEP-ENCRYPT).\n *\n * \\note             The output buffer must be as large as the size\n *                   of ctx->N. For example, 128 Bytes if RSA-1024 is used.\n *\n * \\param ctx        The initialized RSA context to use.\n * \\param f_rng      The RNG function to use. This is needed for padding\n *                   generation and is mandatory.\n * \\param p_rng      The RNG context to be passed to \\p f_rng. This may\n *                   be \\c NULL if \\p f_rng doesn't need a context argument.\n * \\param label      The buffer holding the custom label to use.\n *                   This must be a readable buffer of length \\p label_len\n *                   Bytes. It may be \\c NULL if \\p label_len is \\c 0.\n * \\param label_len  The length of the label in Bytes.\n * \\param ilen       The length of the plaintext buffer \\p input in Bytes.\n * \\param input      The input data to encrypt. This must be a readable\n *                   buffer of size \\p ilen Bytes. It may be \\c NULL if\n *                   `ilen == 0`.\n * \\param output     The output buffer. This must be a writable buffer\n *                   of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                   for an 2048-bit RSA modulus.\n *\n * \\return           \\c 0 on success.\n * \\return           An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx,\n                                   mbedtls_f_rng_t *f_rng,\n                                   void *p_rng,\n                                   const unsigned char *label, size_t label_len,\n                                   size_t ilen,\n                                   const unsigned char *input,\n                                   unsigned char *output);\n\n/**\n * \\brief          This function performs an RSA operation, then removes the\n *                 message padding.\n *\n *                 It is the generic wrapper for performing a PKCS#1 decryption\n *                 operation.\n *\n * \\warning        When \\p ctx->padding is set to #MBEDTLS_RSA_PKCS_V15,\n *                 mbedtls_rsa_rsaes_pkcs1_v15_decrypt() is called, which is an\n *                 inherently dangerous function (CWE-242).\n *\n * \\note           The output buffer length \\c output_max_len should be\n *                 as large as the size \\p ctx->len of \\p ctx->N (for example,\n *                 128 Bytes if RSA-1024 is used) to be able to hold an\n *                 arbitrary decrypted message. If it is not large enough to\n *                 hold the decryption of the particular ciphertext provided,\n *                 the function returns \\c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE.\n *\n * \\param ctx      The initialized RSA context to use.\n * \\param f_rng    The RNG function. This is used for blinding and is\n *                 mandatory; see mbedtls_rsa_private() for more.\n * \\param p_rng    The RNG context to be passed to \\p f_rng. This may be\n *                 \\c NULL if \\p f_rng doesn't need a context.\n * \\param olen     The address at which to store the length of\n *                 the plaintext. This must not be \\c NULL.\n * \\param input    The ciphertext buffer. This must be a readable buffer\n *                 of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus.\n * \\param output   The buffer used to hold the plaintext. This must\n *                 be a writable buffer of length \\p output_max_len Bytes.\n * \\param output_max_len The length in Bytes of the output buffer \\p output.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx,\n                              mbedtls_f_rng_t *f_rng,\n                              void *p_rng,\n                              size_t *olen,\n                              const unsigned char *input,\n                              unsigned char *output,\n                              size_t output_max_len);\n\n/**\n * \\brief          This function performs a PKCS#1 v1.5 decryption\n *                 operation (RSAES-PKCS1-v1_5-DECRYPT).\n *\n * \\warning        This is an inherently dangerous function (CWE-242). Unless\n *                 it is used in a side channel free and safe way (eg.\n *                 implementing the TLS protocol as per 7.4.7.1 of RFC 5246),\n *                 the calling code is vulnerable.\n *\n * \\note           The output buffer length \\c output_max_len should be\n *                 as large as the size \\p ctx->len of \\p ctx->N, for example,\n *                 128 Bytes if RSA-1024 is used, to be able to hold an\n *                 arbitrary decrypted message. If it is not large enough to\n *                 hold the decryption of the particular ciphertext provided,\n *                 the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE.\n *\n * \\param ctx      The initialized RSA context to use.\n * \\param f_rng    The RNG function. This is used for blinding and is\n *                 mandatory; see mbedtls_rsa_private() for more.\n * \\param p_rng    The RNG context to be passed to \\p f_rng. This may be\n *                 \\c NULL if \\p f_rng doesn't need a context.\n * \\param olen     The address at which to store the length of\n *                 the plaintext. This must not be \\c NULL.\n * \\param input    The ciphertext buffer. This must be a readable buffer\n *                 of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus.\n * \\param output   The buffer used to hold the plaintext. This must\n *                 be a writable buffer of length \\p output_max_len Bytes.\n * \\param output_max_len The length in Bytes of the output buffer \\p output.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n *\n */\nint mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx,\n                                        mbedtls_f_rng_t *f_rng,\n                                        void *p_rng,\n                                        size_t *olen,\n                                        const unsigned char *input,\n                                        unsigned char *output,\n                                        size_t output_max_len);\n\n/**\n * \\brief            This function performs a PKCS#1 v2.1 OAEP decryption\n *                   operation (RSAES-OAEP-DECRYPT).\n *\n * \\note             The output buffer length \\c output_max_len should be\n *                   as large as the size \\p ctx->len of \\p ctx->N, for\n *                   example, 128 Bytes if RSA-1024 is used, to be able to\n *                   hold an arbitrary decrypted message. If it is not\n *                   large enough to hold the decryption of the particular\n *                   ciphertext provided, the function returns\n *                   #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE.\n *\n * \\param ctx        The initialized RSA context to use.\n * \\param f_rng      The RNG function. This is used for blinding and is\n *                   mandatory.\n * \\param p_rng      The RNG context to be passed to \\p f_rng. This may be\n *                   \\c NULL if \\p f_rng doesn't need a context.\n * \\param label      The buffer holding the custom label to use.\n *                   This must be a readable buffer of length \\p label_len\n *                   Bytes. It may be \\c NULL if \\p label_len is \\c 0.\n * \\param label_len  The length of the label in Bytes.\n * \\param olen       The address at which to store the length of\n *                   the plaintext. This must not be \\c NULL.\n * \\param input      The ciphertext buffer. This must be a readable buffer\n *                   of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                   for an 2048-bit RSA modulus.\n * \\param output     The buffer used to hold the plaintext. This must\n *                   be a writable buffer of length \\p output_max_len Bytes.\n * \\param output_max_len The length in Bytes of the output buffer \\p output.\n *\n * \\return         \\c 0 on success.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx,\n                                   mbedtls_f_rng_t *f_rng,\n                                   void *p_rng,\n                                   const unsigned char *label, size_t label_len,\n                                   size_t *olen,\n                                   const unsigned char *input,\n                                   unsigned char *output,\n                                   size_t output_max_len);\n\n/**\n * \\brief          This function performs a private RSA operation to sign\n *                 a message digest using PKCS#1.\n *\n *                 It is the generic wrapper for performing a PKCS#1\n *                 signature.\n *\n * \\note           The \\p sig buffer must be as large as the size\n *                 of \\p ctx->N. For example, 128 Bytes if RSA-1024 is used.\n *\n * \\note           For PKCS#1 v2.1 encoding, see comments on\n *                 mbedtls_rsa_rsassa_pss_sign() for details on\n *                 \\p md_alg and \\p hash_id.\n *\n * \\param ctx      The initialized RSA context to use.\n * \\param f_rng    The RNG function to use. This is mandatory and\n *                 must not be \\c NULL.\n * \\param p_rng    The RNG context to be passed to \\p f_rng. This may be \\c NULL\n *                 if \\p f_rng doesn't need a context argument.\n * \\param md_alg   The message-digest algorithm used to hash the original data.\n *                 Use #MBEDTLS_MD_NONE for signing raw data.\n * \\param hashlen  The length of the message digest or raw data in Bytes.\n *                 If \\p md_alg is not #MBEDTLS_MD_NONE, this must match the\n *                 output length of the corresponding hash algorithm.\n * \\param hash     The buffer holding the message digest or raw data.\n *                 This must be a readable buffer of at least \\p hashlen Bytes.\n * \\param sig      The buffer to hold the signature. This must be a writable\n *                 buffer of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus. A buffer length of\n *                 #MBEDTLS_MPI_MAX_SIZE is always safe.\n *\n * \\return         \\c 0 if the signing operation was successful.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_pkcs1_sign(mbedtls_rsa_context *ctx,\n                           mbedtls_f_rng_t *f_rng,\n                           void *p_rng,\n                           mbedtls_md_type_t md_alg,\n                           unsigned int hashlen,\n                           const unsigned char *hash,\n                           unsigned char *sig);\n\n/**\n * \\brief          This function performs a PKCS#1 v1.5 signature\n *                 operation (RSASSA-PKCS1-v1_5-SIGN).\n *\n * \\param ctx      The initialized RSA context to use.\n * \\param f_rng    The RNG function. This is used for blinding and is\n *                 mandatory; see mbedtls_rsa_private() for more.\n * \\param p_rng    The RNG context to be passed to \\p f_rng. This may be \\c NULL\n *                 if \\p f_rng doesn't need a context argument.\n * \\param md_alg   The message-digest algorithm used to hash the original data.\n *                 Use #MBEDTLS_MD_NONE for signing raw data.\n * \\param hashlen  The length of the message digest or raw data in Bytes.\n *                 If \\p md_alg is not #MBEDTLS_MD_NONE, this must match the\n *                 output length of the corresponding hash algorithm.\n * \\param hash     The buffer holding the message digest or raw data.\n *                 This must be a readable buffer of at least \\p hashlen Bytes.\n * \\param sig      The buffer to hold the signature. This must be a writable\n *                 buffer of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus. A buffer length of\n *                 #MBEDTLS_MPI_MAX_SIZE is always safe.\n *\n * \\return         \\c 0 if the signing operation was successful.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx,\n                                      mbedtls_f_rng_t *f_rng,\n                                      void *p_rng,\n                                      mbedtls_md_type_t md_alg,\n                                      unsigned int hashlen,\n                                      const unsigned char *hash,\n                                      unsigned char *sig);\n\n#if defined(MBEDTLS_PKCS1_V21)\n/**\n * \\brief          This function performs a PKCS#1 v2.1 PSS signature\n *                 operation (RSASSA-PSS-SIGN).\n *\n * \\note           The \\c hash_id set in \\p ctx by calling\n *                 mbedtls_rsa_set_padding() selects the hash used for the\n *                 encoding operation and for the mask generation function\n *                 (MGF1). For more details on the encoding operation and the\n *                 mask generation function, consult <em>RFC-3447: Public-Key\n *                 Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography\n *                 Specifications</em>.\n *\n * \\note           This function enforces that the provided salt length complies\n *                 with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 v2.2) §9.1.1\n *                 step 3. The constraint is that the hash length plus the salt\n *                 length plus 2 bytes must be at most the key length. If this\n *                 constraint is not met, this function returns\n *                 #MBEDTLS_ERR_RSA_BAD_INPUT_DATA.\n *\n * \\param ctx      The initialized RSA context to use.\n * \\param f_rng    The RNG function. It is mandatory and must not be \\c NULL.\n * \\param p_rng    The RNG context to be passed to \\p f_rng. This may be \\c NULL\n *                 if \\p f_rng doesn't need a context argument.\n * \\param md_alg   The message-digest algorithm used to hash the original data.\n *                 Use #MBEDTLS_MD_NONE for signing raw data.\n * \\param hashlen  The length of the message digest or raw data in Bytes.\n *                 If \\p md_alg is not #MBEDTLS_MD_NONE, this must match the\n *                 output length of the corresponding hash algorithm.\n * \\param hash     The buffer holding the message digest or raw data.\n *                 This must be a readable buffer of at least \\p hashlen Bytes.\n * \\param saltlen  The length of the salt that should be used.\n *                 If passed #MBEDTLS_RSA_SALT_LEN_ANY, the function will use\n *                 the largest possible salt length up to the hash length,\n *                 which is the largest permitted by some standards including\n *                 FIPS 186-4 §5.5.\n * \\param sig      The buffer to hold the signature. This must be a writable\n *                 buffer of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus. A buffer length of\n *                 #MBEDTLS_MPI_MAX_SIZE is always safe.\n *\n * \\return         \\c 0 if the signing operation was successful.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_rsassa_pss_sign_ext(mbedtls_rsa_context *ctx,\n                                    mbedtls_f_rng_t *f_rng,\n                                    void *p_rng,\n                                    mbedtls_md_type_t md_alg,\n                                    unsigned int hashlen,\n                                    const unsigned char *hash,\n                                    int saltlen,\n                                    unsigned char *sig);\n\n/**\n * \\brief          This function performs a PKCS#1 v2.1 PSS signature\n *                 operation (RSASSA-PSS-SIGN).\n *\n * \\note           The \\c hash_id set in \\p ctx by calling\n *                 mbedtls_rsa_set_padding() selects the hash used for the\n *                 encoding operation and for the mask generation function\n *                 (MGF1). For more details on the encoding operation and the\n *                 mask generation function, consult <em>RFC-3447: Public-Key\n *                 Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography\n *                 Specifications</em>.\n *\n * \\note           This function always uses the maximum possible salt size,\n *                 up to the length of the payload hash. This choice of salt\n *                 size complies with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1\n *                 v2.2) §9.1.1 step 3. Furthermore this function enforces a\n *                 minimum salt size which is the hash size minus 2 bytes. If\n *                 this minimum size is too large given the key size (the salt\n *                 size, plus the hash size, plus 2 bytes must be no more than\n *                 the key size in bytes), this function returns\n *                 #MBEDTLS_ERR_RSA_BAD_INPUT_DATA.\n *\n * \\param ctx      The initialized RSA context to use.\n * \\param f_rng    The RNG function. It is mandatory and must not be \\c NULL.\n * \\param p_rng    The RNG context to be passed to \\p f_rng. This may be \\c NULL\n *                 if \\p f_rng doesn't need a context argument.\n * \\param md_alg   The message-digest algorithm used to hash the original data.\n *                 Use #MBEDTLS_MD_NONE for signing raw data.\n * \\param hashlen  The length of the message digest or raw data in Bytes.\n *                 If \\p md_alg is not #MBEDTLS_MD_NONE, this must match the\n *                 output length of the corresponding hash algorithm.\n * \\param hash     The buffer holding the message digest or raw data.\n *                 This must be a readable buffer of at least \\p hashlen Bytes.\n * \\param sig      The buffer to hold the signature. This must be a writable\n *                 buffer of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus. A buffer length of\n *                 #MBEDTLS_MPI_MAX_SIZE is always safe.\n *\n * \\return         \\c 0 if the signing operation was successful.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,\n                                mbedtls_f_rng_t *f_rng,\n                                void *p_rng,\n                                mbedtls_md_type_t md_alg,\n                                unsigned int hashlen,\n                                const unsigned char *hash,\n                                unsigned char *sig);\n#endif /* MBEDTLS_PKCS1_V21 */\n\n/**\n * \\brief          This function performs a public RSA operation and checks\n *                 the message digest.\n *\n *                 This is the generic wrapper for performing a PKCS#1\n *                 verification.\n *\n * \\note           For PKCS#1 v2.1 encoding, see comments on\n *                 mbedtls_rsa_rsassa_pss_verify() about \\c md_alg and\n *                 \\c hash_id.\n *\n * \\param ctx      The initialized RSA public key context to use.\n * \\param md_alg   The message-digest algorithm used to hash the original data.\n *                 Use #MBEDTLS_MD_NONE for signing raw data.\n * \\param hashlen  The length of the message digest or raw data in Bytes.\n *                 If \\p md_alg is not #MBEDTLS_MD_NONE, this must match the\n *                 output length of the corresponding hash algorithm.\n * \\param hash     The buffer holding the message digest or raw data.\n *                 This must be a readable buffer of at least \\p hashlen Bytes.\n * \\param sig      The buffer holding the signature. This must be a readable\n *                 buffer of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus.\n *\n * \\return         \\c 0 if the verify operation was successful.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_pkcs1_verify(mbedtls_rsa_context *ctx,\n                             mbedtls_md_type_t md_alg,\n                             unsigned int hashlen,\n                             const unsigned char *hash,\n                             const unsigned char *sig);\n\n/**\n * \\brief          This function performs a PKCS#1 v1.5 verification\n *                 operation (RSASSA-PKCS1-v1_5-VERIFY).\n *\n * \\param ctx      The initialized RSA public key context to use.\n * \\param md_alg   The message-digest algorithm used to hash the original data.\n *                 Use #MBEDTLS_MD_NONE for signing raw data.\n * \\param hashlen  The length of the message digest or raw data in Bytes.\n *                 If \\p md_alg is not #MBEDTLS_MD_NONE, this must match the\n *                 output length of the corresponding hash algorithm.\n * \\param hash     The buffer holding the message digest or raw data.\n *                 This must be a readable buffer of at least \\p hashlen Bytes.\n * \\param sig      The buffer holding the signature. This must be a readable\n *                 buffer of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus.\n *\n * \\return         \\c 0 if the verify operation was successful.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx,\n                                        mbedtls_md_type_t md_alg,\n                                        unsigned int hashlen,\n                                        const unsigned char *hash,\n                                        const unsigned char *sig);\n\n/**\n * \\brief          This function performs a PKCS#1 v2.1 PSS verification\n *                 operation (RSASSA-PSS-VERIFY).\n *\n * \\note           The \\c hash_id set in \\p ctx by calling\n *                 mbedtls_rsa_set_padding() selects the hash used for the\n *                 encoding operation and for the mask generation function\n *                 (MGF1). For more details on the encoding operation and the\n *                 mask generation function, consult <em>RFC-3447: Public-Key\n *                 Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography\n *                 Specifications</em>. If the \\c hash_id set in \\p ctx by\n *                 mbedtls_rsa_set_padding() is #MBEDTLS_MD_NONE, the \\p md_alg\n *                 parameter is used.\n *\n * \\param ctx      The initialized RSA public key context to use.\n * \\param md_alg   The message-digest algorithm used to hash the original data.\n *                 Use #MBEDTLS_MD_NONE for signing raw data.\n * \\param hashlen  The length of the message digest or raw data in Bytes.\n *                 If \\p md_alg is not #MBEDTLS_MD_NONE, this must match the\n *                 output length of the corresponding hash algorithm.\n * \\param hash     The buffer holding the message digest or raw data.\n *                 This must be a readable buffer of at least \\p hashlen Bytes.\n * \\param sig      The buffer holding the signature. This must be a readable\n *                 buffer of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus.\n *\n * \\return         \\c 0 if the verify operation was successful.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context *ctx,\n                                  mbedtls_md_type_t md_alg,\n                                  unsigned int hashlen,\n                                  const unsigned char *hash,\n                                  const unsigned char *sig);\n\n/**\n * \\brief          This function performs a PKCS#1 v2.1 PSS verification\n *                 operation (RSASSA-PSS-VERIFY).\n *\n * \\note           The \\p sig buffer must be as large as the size\n *                 of \\p ctx->N. For example, 128 Bytes if RSA-1024 is used.\n *\n * \\note           The \\c hash_id set in \\p ctx by mbedtls_rsa_set_padding() is\n *                 ignored.\n *\n * \\param ctx      The initialized RSA public key context to use.\n * \\param md_alg   The message-digest algorithm used to hash the original data.\n *                 Use #MBEDTLS_MD_NONE for signing raw data.\n * \\param hashlen  The length of the message digest or raw data in Bytes.\n *                 If \\p md_alg is not #MBEDTLS_MD_NONE, this must match the\n *                 output length of the corresponding hash algorithm.\n * \\param hash     The buffer holding the message digest or raw data.\n *                 This must be a readable buffer of at least \\p hashlen Bytes.\n * \\param mgf1_hash_id      The message digest algorithm used for the\n *                          verification operation and the mask generation\n *                          function (MGF1). For more details on the encoding\n *                          operation and the mask generation function, consult\n *                          <em>RFC-3447: Public-Key Cryptography Standards\n *                          (PKCS) #1 v2.1: RSA Cryptography\n *                          Specifications</em>.\n * \\param expected_salt_len The length of the salt used in padding. Use\n *                          #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length.\n * \\param sig      The buffer holding the signature. This must be a readable\n *                 buffer of length \\c ctx->len Bytes. For example, \\c 256 Bytes\n *                 for an 2048-bit RSA modulus.\n *\n * \\return         \\c 0 if the verify operation was successful.\n * \\return         An \\c MBEDTLS_ERR_RSA_XXX error code on failure.\n */\nint mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx,\n                                      mbedtls_md_type_t md_alg,\n                                      unsigned int hashlen,\n                                      const unsigned char *hash,\n                                      mbedtls_md_type_t mgf1_hash_id,\n                                      int expected_salt_len,\n                                      const unsigned char *sig);\n\n/**\n * \\brief          This function copies the components of an RSA context.\n *\n * \\param dst      The destination context. This must be initialized.\n * \\param src      The source context. This must be initialized.\n *\n * \\return         \\c 0 on success.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure.\n */\nint mbedtls_rsa_copy(mbedtls_rsa_context *dst, const mbedtls_rsa_context *src);\n\n/**\n * \\brief          This function frees the components of an RSA key.\n *\n * \\param ctx      The RSA context to free. May be \\c NULL, in which case\n *                 this function is a no-op. If it is not \\c NULL, it must\n *                 point to an initialized RSA context.\n */\nvoid mbedtls_rsa_free(mbedtls_rsa_context *ctx);\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/**\n * \\brief          The RSA checkup routine.\n *\n * \\return         \\c 0 on success.\n * \\return         \\c 1 on failure.\n */\nint mbedtls_rsa_self_test(int verbose);\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* rsa.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/sha1.h",
    "content": "/**\n * \\file sha1.h\n *\n * \\brief This file contains SHA-1 definitions and functions.\n *\n * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in\n * <em>FIPS 180-4: Secure Hash Standard (SHS)</em>.\n *\n * \\warning   SHA-1 is considered a weak message digest and its use constitutes\n *            a security risk. We recommend considering stronger message\n *            digests instead.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_SHA1_H\n#define MBEDTLS_SHA1_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n/** SHA-1 input data was malformed. */\n#define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA                   -0x0073\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_SHA1_ALT)\n// Regular implementation\n//\n\n/**\n * \\brief          The SHA-1 context structure.\n *\n * \\warning        SHA-1 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n */\ntypedef struct mbedtls_sha1_context {\n    uint32_t MBEDTLS_PRIVATE(total)[2];          /*!< The number of Bytes processed.  */\n    uint32_t MBEDTLS_PRIVATE(state)[5];          /*!< The intermediate digest state.  */\n    unsigned char MBEDTLS_PRIVATE(buffer)[64];   /*!< The data block being processed. */\n}\nmbedtls_sha1_context;\n\n#else  /* MBEDTLS_SHA1_ALT */\n#include \"sha1_alt.h\"\n#endif /* MBEDTLS_SHA1_ALT */\n\n/**\n * \\brief          This function initializes a SHA-1 context.\n *\n * \\warning        SHA-1 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n * \\param ctx      The SHA-1 context to initialize.\n *                 This must not be \\c NULL.\n *\n */\nvoid mbedtls_sha1_init(mbedtls_sha1_context *ctx);\n\n/**\n * \\brief          This function clears a SHA-1 context.\n *\n * \\warning        SHA-1 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n * \\param ctx      The SHA-1 context to clear. This may be \\c NULL,\n *                 in which case this function does nothing. If it is\n *                 not \\c NULL, it must point to an initialized\n *                 SHA-1 context.\n *\n */\nvoid mbedtls_sha1_free(mbedtls_sha1_context *ctx);\n\n/**\n * \\brief          This function clones the state of a SHA-1 context.\n *\n * \\warning        SHA-1 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n * \\param dst      The SHA-1 context to clone to. This must be initialized.\n * \\param src      The SHA-1 context to clone from. This must be initialized.\n *\n */\nvoid mbedtls_sha1_clone(mbedtls_sha1_context *dst,\n                        const mbedtls_sha1_context *src);\n\n/**\n * \\brief          This function starts a SHA-1 checksum calculation.\n *\n * \\warning        SHA-1 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n * \\param ctx      The SHA-1 context to initialize. This must be initialized.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n *\n */\nint mbedtls_sha1_starts(mbedtls_sha1_context *ctx);\n\n/**\n * \\brief          This function feeds an input buffer into an ongoing SHA-1\n *                 checksum calculation.\n *\n * \\warning        SHA-1 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n * \\param ctx      The SHA-1 context. This must be initialized\n *                 and have a hash operation started.\n * \\param input    The buffer holding the input data.\n *                 This must be a readable buffer of length \\p ilen Bytes.\n * \\param ilen     The length of the input data \\p input in Bytes.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_sha1_update(mbedtls_sha1_context *ctx,\n                        const unsigned char *input,\n                        size_t ilen);\n\n/**\n * \\brief          This function finishes the SHA-1 operation, and writes\n *                 the result to the output buffer.\n *\n * \\warning        SHA-1 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n * \\param ctx      The SHA-1 context to use. This must be initialized and\n *                 have a hash operation started.\n * \\param output   The SHA-1 checksum result. This must be a writable\n *                 buffer of length \\c 20 Bytes.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_sha1_finish(mbedtls_sha1_context *ctx,\n                        unsigned char output[20]);\n\n/**\n * \\brief          SHA-1 process data block (internal use only).\n *\n * \\warning        SHA-1 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n * \\param ctx      The SHA-1 context to use. This must be initialized.\n * \\param data     The data block being processed. This must be a\n *                 readable buffer of length \\c 64 Bytes.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n *\n */\nint mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx,\n                                  const unsigned char data[64]);\n\n/**\n * \\brief          This function calculates the SHA-1 checksum of a buffer.\n *\n *                 The function allocates the context, performs the\n *                 calculation, and frees the context.\n *\n *                 The SHA-1 result is calculated as\n *                 output = SHA-1(input buffer).\n *\n * \\warning        SHA-1 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n * \\param input    The buffer holding the input data.\n *                 This must be a readable buffer of length \\p ilen Bytes.\n * \\param ilen     The length of the input data \\p input in Bytes.\n * \\param output   The SHA-1 checksum result.\n *                 This must be a writable buffer of length \\c 20 Bytes.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n *\n */\nint mbedtls_sha1(const unsigned char *input,\n                 size_t ilen,\n                 unsigned char output[20]);\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/**\n * \\brief          The SHA-1 checkup routine.\n *\n * \\warning        SHA-1 is considered a weak message digest and its use\n *                 constitutes a security risk. We recommend considering\n *                 stronger message digests instead.\n *\n * \\return         \\c 0 on success.\n * \\return         \\c 1 on failure.\n *\n */\nint mbedtls_sha1_self_test(int verbose);\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* mbedtls_sha1.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/sha256.h",
    "content": "/**\n * \\file sha256.h\n *\n * \\brief This file contains SHA-224 and SHA-256 definitions and functions.\n *\n * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic\n * hash functions are defined in <em>FIPS 180-4: Secure Hash Standard (SHS)</em>.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_SHA256_H\n#define MBEDTLS_SHA256_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n/** SHA-256 input data was malformed. */\n#define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA                 -0x0074\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_SHA256_ALT)\n// Regular implementation\n//\n\n/**\n * \\brief          The SHA-256 context structure.\n *\n *                 The structure is used both for SHA-256 and for SHA-224\n *                 checksum calculations. The choice between these two is\n *                 made in the call to mbedtls_sha256_starts().\n */\ntypedef struct mbedtls_sha256_context {\n    unsigned char MBEDTLS_PRIVATE(buffer)[64];   /*!< The data block being processed. */\n    uint32_t MBEDTLS_PRIVATE(total)[2];          /*!< The number of Bytes processed.  */\n    uint32_t MBEDTLS_PRIVATE(state)[8];          /*!< The intermediate digest state.  */\n#if defined(MBEDTLS_SHA224_C)\n    int MBEDTLS_PRIVATE(is224);                  /*!< Determines which function to use:\n                                                    0: Use SHA-256, or 1: Use SHA-224. */\n#endif\n}\nmbedtls_sha256_context;\n\n#else  /* MBEDTLS_SHA256_ALT */\n#include \"sha256_alt.h\"\n#endif /* MBEDTLS_SHA256_ALT */\n\n/**\n * \\brief          This function initializes a SHA-256 context.\n *\n * \\param ctx      The SHA-256 context to initialize. This must not be \\c NULL.\n */\nvoid mbedtls_sha256_init(mbedtls_sha256_context *ctx);\n\n/**\n * \\brief          This function clears a SHA-256 context.\n *\n * \\param ctx      The SHA-256 context to clear. This may be \\c NULL, in which\n *                 case this function returns immediately. If it is not \\c NULL,\n *                 it must point to an initialized SHA-256 context.\n */\nvoid mbedtls_sha256_free(mbedtls_sha256_context *ctx);\n\n/**\n * \\brief          This function clones the state of a SHA-256 context.\n *\n * \\param dst      The destination context. This must be initialized.\n * \\param src      The context to clone. This must be initialized.\n */\nvoid mbedtls_sha256_clone(mbedtls_sha256_context *dst,\n                          const mbedtls_sha256_context *src);\n\n/**\n * \\brief          This function starts a SHA-224 or SHA-256 checksum\n *                 calculation.\n *\n * \\param ctx      The context to use. This must be initialized.\n * \\param is224    This determines which function to use. This must be\n *                 either \\c 0 for SHA-256, or \\c 1 for SHA-224.\n *\n * \\note           is224 must be defined accordingly to the enabled\n *                 MBEDTLS_SHA224_C/MBEDTLS_SHA256_C symbols otherwise the\n *                 function will return #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224);\n\n/**\n * \\brief          This function feeds an input buffer into an ongoing\n *                 SHA-256 checksum calculation.\n *\n * \\param ctx      The SHA-256 context. This must be initialized\n *                 and have a hash operation started.\n * \\param input    The buffer holding the data. This must be a readable\n *                 buffer of length \\p ilen Bytes.\n * \\param ilen     The length of the input data in Bytes.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_sha256_update(mbedtls_sha256_context *ctx,\n                          const unsigned char *input,\n                          size_t ilen);\n\n/**\n * \\brief          This function finishes the SHA-256 operation, and writes\n *                 the result to the output buffer.\n *\n * \\param ctx      The SHA-256 context. This must be initialized\n *                 and have a hash operation started.\n * \\param output   The SHA-224 or SHA-256 checksum result.\n *                 This must be a writable buffer of length \\c 32 bytes\n *                 for SHA-256, \\c 28 bytes for SHA-224.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_sha256_finish(mbedtls_sha256_context *ctx,\n                          unsigned char *output);\n\n/**\n * \\brief          This function processes a single data block within\n *                 the ongoing SHA-256 computation. This function is for\n *                 internal use only.\n *\n * \\param ctx      The SHA-256 context. This must be initialized.\n * \\param data     The buffer holding one block of data. This must\n *                 be a readable buffer of length \\c 64 Bytes.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx,\n                                    const unsigned char data[64]);\n\n/**\n * \\brief          This function calculates the SHA-224 or SHA-256\n *                 checksum of a buffer.\n *\n *                 The function allocates the context, performs the\n *                 calculation, and frees the context.\n *\n *                 The SHA-256 result is calculated as\n *                 output = SHA-256(input buffer).\n *\n * \\param input    The buffer holding the data. This must be a readable\n *                 buffer of length \\p ilen Bytes.\n * \\param ilen     The length of the input data in Bytes.\n * \\param output   The SHA-224 or SHA-256 checksum result.\n *                 This must be a writable buffer of length \\c 32 bytes\n *                 for SHA-256, \\c 28 bytes for SHA-224.\n * \\param is224    Determines which function to use. This must be\n *                 either \\c 0 for SHA-256, or \\c 1 for SHA-224.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_sha256(const unsigned char *input,\n                   size_t ilen,\n                   unsigned char *output,\n                   int is224);\n\n#if defined(MBEDTLS_SELF_TEST)\n\n#if defined(MBEDTLS_SHA224_C)\n/**\n * \\brief          The SHA-224 checkup routine.\n *\n * \\return         \\c 0 on success.\n * \\return         \\c 1 on failure.\n */\nint mbedtls_sha224_self_test(int verbose);\n#endif /* MBEDTLS_SHA224_C */\n\n#if defined(MBEDTLS_SHA256_C)\n/**\n * \\brief          The SHA-256 checkup routine.\n *\n * \\return         \\c 0 on success.\n * \\return         \\c 1 on failure.\n */\nint mbedtls_sha256_self_test(int verbose);\n#endif /* MBEDTLS_SHA256_C */\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* mbedtls_sha256.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/sha3.h",
    "content": "/**\n * \\file sha3.h\n *\n * \\brief This file contains SHA-3 definitions and functions.\n *\n * The Secure Hash Algorithms cryptographic\n * hash functions are defined in <em>FIPS 202: SHA-3 Standard:\n * Permutation-Based Hash and Extendable-Output Functions </em>.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_SHA3_H\n#define MBEDTLS_SHA3_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** SHA-3 input data was malformed. */\n#define MBEDTLS_ERR_SHA3_BAD_INPUT_DATA                 -0x0076\n\n/**\n * SHA-3 family id.\n *\n * It identifies the family (SHA3-256, SHA3-512, etc.)\n */\n\ntypedef enum {\n    MBEDTLS_SHA3_NONE = 0, /*!< Operation not defined. */\n    MBEDTLS_SHA3_224, /*!< SHA3-224 */\n    MBEDTLS_SHA3_256, /*!< SHA3-256 */\n    MBEDTLS_SHA3_384, /*!< SHA3-384 */\n    MBEDTLS_SHA3_512, /*!< SHA3-512 */\n} mbedtls_sha3_id;\n\n/**\n * \\brief          The SHA-3 context structure.\n *\n *                 The structure is used SHA-3 checksum calculations.\n */\ntypedef struct {\n    uint64_t MBEDTLS_PRIVATE(state[25]);\n    uint32_t MBEDTLS_PRIVATE(index);\n    uint16_t MBEDTLS_PRIVATE(olen);\n    uint16_t MBEDTLS_PRIVATE(max_block_size);\n}\nmbedtls_sha3_context;\n\n/**\n * \\brief          This function initializes a SHA-3 context.\n *\n * \\param ctx      The SHA-3 context to initialize. This must not be \\c NULL.\n */\nvoid mbedtls_sha3_init(mbedtls_sha3_context *ctx);\n\n/**\n * \\brief          This function clears a SHA-3 context.\n *\n * \\param ctx      The SHA-3 context to clear. This may be \\c NULL, in which\n *                 case this function returns immediately. If it is not \\c NULL,\n *                 it must point to an initialized SHA-3 context.\n */\nvoid mbedtls_sha3_free(mbedtls_sha3_context *ctx);\n\n/**\n * \\brief          This function clones the state of a SHA-3 context.\n *\n * \\param dst      The destination context. This must be initialized.\n * \\param src      The context to clone. This must be initialized.\n */\nvoid mbedtls_sha3_clone(mbedtls_sha3_context *dst,\n                        const mbedtls_sha3_context *src);\n\n/**\n * \\brief          This function starts a SHA-3 checksum\n *                 calculation.\n *\n * \\param ctx      The context to use. This must be initialized.\n * \\param id       The id of the SHA-3 family.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id);\n\n/**\n * \\brief          This function feeds an input buffer into an ongoing\n *                 SHA-3 checksum calculation.\n *\n * \\param ctx      The SHA-3 context. This must be initialized\n *                 and have a hash operation started.\n * \\param input    The buffer holding the data. This must be a readable\n *                 buffer of length \\p ilen Bytes.\n * \\param ilen     The length of the input data in Bytes.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_sha3_update(mbedtls_sha3_context *ctx,\n                        const uint8_t *input,\n                        size_t ilen);\n\n/**\n * \\brief          This function finishes the SHA-3 operation, and writes\n *                 the result to the output buffer.\n *\n * \\param ctx      The SHA-3 context. This must be initialized\n *                 and have a hash operation started.\n * \\param output   The SHA-3 checksum result.\n *                 This must be a writable buffer of length \\c olen bytes.\n * \\param olen     Defines the length of output buffer (in bytes). For SHA-3 224, SHA-3 256,\n *                 SHA-3 384 and SHA-3 512 \\c olen must equal to 28, 32, 48 and 64,\n *                 respectively.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_sha3_finish(mbedtls_sha3_context *ctx,\n                        uint8_t *output, size_t olen);\n\n/**\n * \\brief          This function calculates the SHA-3\n *                 checksum of a buffer.\n *\n *                 The function allocates the context, performs the\n *                 calculation, and frees the context.\n *\n *                 The SHA-3 result is calculated as\n *                 output = SHA-3(id, input buffer, d).\n *\n * \\param id       The id of the SHA-3 family.\n * \\param input    The buffer holding the data. This must be a readable\n *                 buffer of length \\p ilen Bytes.\n * \\param ilen     The length of the input data in Bytes.\n * \\param output   The SHA-3 checksum result.\n *                 This must be a writable buffer of length \\c olen bytes.\n * \\param olen     Defines the length of output buffer (in bytes). For SHA-3 224, SHA-3 256,\n *                 SHA-3 384 and SHA-3 512 \\c olen must equal to 28, 32, 48 and 64,\n *                 respectively.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input,\n                 size_t ilen,\n                 uint8_t *output,\n                 size_t olen);\n\n#if defined(MBEDTLS_SELF_TEST)\n/**\n * \\brief          Checkup routine for the algorithms implemented\n *                 by this module: SHA3-224, SHA3-256, SHA3-384, SHA3-512.\n *\n * \\return         0 if successful, or 1 if the test failed.\n */\nint mbedtls_sha3_self_test(int verbose);\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* mbedtls_sha3.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/sha512.h",
    "content": "/**\n * \\file sha512.h\n * \\brief This file contains SHA-384 and SHA-512 definitions and functions.\n *\n * The Secure Hash Algorithms 384 and 512 (SHA-384 and SHA-512) cryptographic\n * hash functions are defined in <em>FIPS 180-4: Secure Hash Standard (SHS)</em>.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_SHA512_H\n#define MBEDTLS_SHA512_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n#include <stdint.h>\n\n/** SHA-512 input data was malformed. */\n#define MBEDTLS_ERR_SHA512_BAD_INPUT_DATA                 -0x0075\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_SHA512_ALT)\n// Regular implementation\n//\n\n/**\n * \\brief          The SHA-512 context structure.\n *\n *                 The structure is used both for SHA-384 and for SHA-512\n *                 checksum calculations. The choice between these two is\n *                 made in the call to mbedtls_sha512_starts().\n */\ntypedef struct mbedtls_sha512_context {\n    uint64_t MBEDTLS_PRIVATE(total)[2];          /*!< The number of Bytes processed. */\n    uint64_t MBEDTLS_PRIVATE(state)[8];          /*!< The intermediate digest state. */\n    unsigned char MBEDTLS_PRIVATE(buffer)[128];  /*!< The data block being processed. */\n#if defined(MBEDTLS_SHA384_C)\n    int MBEDTLS_PRIVATE(is384);                  /*!< Determines which function to use:\n                                                      0: Use SHA-512, or 1: Use SHA-384. */\n#endif\n}\nmbedtls_sha512_context;\n\n#else  /* MBEDTLS_SHA512_ALT */\n#include \"sha512_alt.h\"\n#endif /* MBEDTLS_SHA512_ALT */\n\n/**\n * \\brief          This function initializes a SHA-512 context.\n *\n * \\param ctx      The SHA-512 context to initialize. This must\n *                 not be \\c NULL.\n */\nvoid mbedtls_sha512_init(mbedtls_sha512_context *ctx);\n\n/**\n * \\brief          This function clears a SHA-512 context.\n *\n * \\param ctx      The SHA-512 context to clear. This may be \\c NULL,\n *                 in which case this function does nothing. If it\n *                 is not \\c NULL, it must point to an initialized\n *                 SHA-512 context.\n */\nvoid mbedtls_sha512_free(mbedtls_sha512_context *ctx);\n\n/**\n * \\brief          This function clones the state of a SHA-512 context.\n *\n * \\param dst      The destination context. This must be initialized.\n * \\param src      The context to clone. This must be initialized.\n */\nvoid mbedtls_sha512_clone(mbedtls_sha512_context *dst,\n                          const mbedtls_sha512_context *src);\n\n/**\n * \\brief          This function starts a SHA-384 or SHA-512 checksum\n *                 calculation.\n *\n * \\param ctx      The SHA-512 context to use. This must be initialized.\n * \\param is384    Determines which function to use. This must be\n *                 either \\c 0 for SHA-512, or \\c 1 for SHA-384.\n *\n * \\note           is384 must be defined accordingly to the enabled\n *                 MBEDTLS_SHA384_C/MBEDTLS_SHA512_C symbols otherwise the\n *                 function will return #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_sha512_starts(mbedtls_sha512_context *ctx, int is384);\n\n/**\n * \\brief          This function feeds an input buffer into an ongoing\n *                 SHA-512 checksum calculation.\n *\n * \\param ctx      The SHA-512 context. This must be initialized\n *                 and have a hash operation started.\n * \\param input    The buffer holding the input data. This must\n *                 be a readable buffer of length \\p ilen Bytes.\n * \\param ilen     The length of the input data in Bytes.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_sha512_update(mbedtls_sha512_context *ctx,\n                          const unsigned char *input,\n                          size_t ilen);\n\n/**\n * \\brief          This function finishes the SHA-512 operation, and writes\n *                 the result to the output buffer.\n *\n * \\param ctx      The SHA-512 context. This must be initialized\n *                 and have a hash operation started.\n * \\param output   The SHA-384 or SHA-512 checksum result.\n *                 This must be a writable buffer of length \\c 64 bytes\n *                 for SHA-512, \\c 48 bytes for SHA-384.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_sha512_finish(mbedtls_sha512_context *ctx,\n                          unsigned char *output);\n\n/**\n * \\brief          This function processes a single data block within\n *                 the ongoing SHA-512 computation.\n *                 This function is for internal use only.\n *\n * \\param ctx      The SHA-512 context. This must be initialized.\n * \\param data     The buffer holding one block of data. This\n *                 must be a readable buffer of length \\c 128 Bytes.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx,\n                                    const unsigned char data[128]);\n\n/**\n * \\brief          This function calculates the SHA-512 or SHA-384\n *                 checksum of a buffer.\n *\n *                 The function allocates the context, performs the\n *                 calculation, and frees the context.\n *\n *                 The SHA-512 result is calculated as\n *                 output = SHA-512(input buffer).\n *\n * \\param input    The buffer holding the input data. This must be\n *                 a readable buffer of length \\p ilen Bytes.\n * \\param ilen     The length of the input data in Bytes.\n * \\param output   The SHA-384 or SHA-512 checksum result.\n *                 This must be a writable buffer of length \\c 64 bytes\n *                 for SHA-512, \\c 48 bytes for SHA-384.\n * \\param is384    Determines which function to use. This must be either\n *                 \\c 0 for SHA-512, or \\c 1 for SHA-384.\n *\n * \\note           is384 must be defined accordingly with the supported\n *                 symbols in the config file. If:\n *                 - is384 is 0, but \\c MBEDTLS_SHA384_C is not defined, or\n *                 - is384 is 1, but \\c MBEDTLS_SHA512_C is not defined\n *                 then the function will return\n *                 #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\nint mbedtls_sha512(const unsigned char *input,\n                   size_t ilen,\n                   unsigned char *output,\n                   int is384);\n\n#if defined(MBEDTLS_SELF_TEST)\n\n#if defined(MBEDTLS_SHA384_C)\n/**\n * \\brief          The SHA-384 checkup routine.\n *\n * \\return         \\c 0 on success.\n * \\return         \\c 1 on failure.\n */\nint mbedtls_sha384_self_test(int verbose);\n#endif /* MBEDTLS_SHA384_C */\n\n#if defined(MBEDTLS_SHA512_C)\n/**\n * \\brief          The SHA-512 checkup routine.\n *\n * \\return         \\c 0 on success.\n * \\return         \\c 1 on failure.\n */\nint mbedtls_sha512_self_test(int verbose);\n#endif /* MBEDTLS_SHA512_C */\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* mbedtls_sha512.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/ssl.h",
    "content": "/**\n * \\file ssl.h\n *\n * \\brief SSL/TLS functions.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_SSL_H\n#define MBEDTLS_SSL_H\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/bignum.h\"\n#include \"mbedtls/ecp.h\"\n\n#include \"mbedtls/ssl_ciphersuites.h\"\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n#include \"mbedtls/x509_crt.h\"\n#include \"mbedtls/x509_crl.h\"\n#endif\n\n#if defined(MBEDTLS_DHM_C)\n#include \"mbedtls/dhm.h\"\n#endif\n\n#include \"mbedtls/md.h\"\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED)\n#include \"mbedtls/ecdh.h\"\n#endif\n\n#if defined(MBEDTLS_HAVE_TIME)\n#include \"mbedtls/platform_time.h\"\n#endif\n\n#include \"psa/crypto.h\"\n\n/*\n * SSL Error codes\n */\n/** A cryptographic operation is in progress. Try again later. */\n#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS                -0x7000\n/** The requested feature is not available. */\n#define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE               -0x7080\n/** Bad input parameters to function. */\n#define MBEDTLS_ERR_SSL_BAD_INPUT_DATA                    -0x7100\n/** Verification of the message MAC failed. */\n#define MBEDTLS_ERR_SSL_INVALID_MAC                       -0x7180\n/** An invalid SSL record was received. */\n#define MBEDTLS_ERR_SSL_INVALID_RECORD                    -0x7200\n/** The connection indicated an EOF. */\n#define MBEDTLS_ERR_SSL_CONN_EOF                          -0x7280\n/** A message could not be parsed due to a syntactic error. */\n#define MBEDTLS_ERR_SSL_DECODE_ERROR                      -0x7300\n/* Error space gap */\n/** No RNG was provided to the SSL module. */\n#define MBEDTLS_ERR_SSL_NO_RNG                            -0x7400\n/** No client certification received from the client, but required by the authentication mode. */\n#define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE             -0x7480\n/** Client received an extended server hello containing an unsupported extension */\n#define MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION             -0x7500\n/** No ALPN protocols supported that the client advertises */\n#define MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL           -0x7580\n/** The own private key or pre-shared key is not set, but needed. */\n#define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED              -0x7600\n/** No CA Chain is set, but required to operate. */\n#define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED                 -0x7680\n/** An unexpected message was received from our peer. */\n#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE                -0x7700\n/** A fatal alert message was received from our peer. */\n#define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE               -0x7780\n/** No server could be identified matching the client's SNI. */\n#define MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME                 -0x7800\n/** The peer notified us that the connection is going to be closed. */\n#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY                 -0x7880\n/* Error space gap */\n/* Error space gap */\n/** Processing of the Certificate handshake message failed. */\n#define MBEDTLS_ERR_SSL_BAD_CERTIFICATE                   -0x7A00\n/* Error space gap */\n/** A TLS 1.3 NewSessionTicket message has been received. */\n#define MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET       -0x7B00\n/** Not possible to read early data */\n#define MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA            -0x7B80\n/**\n * Early data has been received as part of an on-going handshake.\n * This error code can be returned only on server side if and only if early\n * data has been enabled by means of the mbedtls_ssl_conf_early_data() API.\n * This error code can then be returned by mbedtls_ssl_handshake(),\n * mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or mbedtls_ssl_write() if\n * early data has been received as part of the handshake sequence they\n * triggered. To read the early data, call mbedtls_ssl_read_early_data().\n */\n#define MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA               -0x7C00\n/** Not possible to write early data */\n#define MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA           -0x7C80\n/* Error space gap */\n/* Error space gap */\n/* Error space gap */\n/* Error space gap */\n/** Cache entry not found */\n#define MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND             -0x7E80\n/** Memory allocation failed */\n#define MBEDTLS_ERR_SSL_ALLOC_FAILED                      -0x7F00\n/** Hardware acceleration function returned with error */\n#define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED                   -0x7F80\n/** Hardware acceleration function skipped / left alone data */\n#define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH              -0x6F80\n/** Handshake protocol not within min/max boundaries */\n#define MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION              -0x6E80\n/** The handshake negotiation failed. */\n#define MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE                 -0x6E00\n/** Session ticket has expired. */\n#define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED            -0x6D80\n/** Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */\n#define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH                  -0x6D00\n/** Unknown identity received (eg, PSK identity) */\n#define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY                  -0x6C80\n/** Internal error (eg, unexpected failure in lower-level module) */\n#define MBEDTLS_ERR_SSL_INTERNAL_ERROR                    -0x6C00\n/** A counter would wrap (eg, too many messages exchanged). */\n#define MBEDTLS_ERR_SSL_COUNTER_WRAPPING                  -0x6B80\n/** Unexpected message at ServerHello in renegotiation. */\n#define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO       -0x6B00\n/** DTLS client must retry for hello verification */\n#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED             -0x6A80\n/** A buffer is too small to receive or write a message */\n#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL                  -0x6A00\n/* Error space gap */\n/** No data of requested type currently available on underlying transport. */\n#define MBEDTLS_ERR_SSL_WANT_READ                         -0x6900\n/** Connection requires a write call. */\n#define MBEDTLS_ERR_SSL_WANT_WRITE                        -0x6880\n/** The operation timed out. */\n#define MBEDTLS_ERR_SSL_TIMEOUT                           -0x6800\n/** The client initiated a reconnect from the same port. */\n#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT                  -0x6780\n/** Record header looks valid but is not expected. */\n#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD                 -0x6700\n/** The alert message received indicates a non-fatal error. */\n#define MBEDTLS_ERR_SSL_NON_FATAL                         -0x6680\n/** A field in a message was incorrect or inconsistent with other fields. */\n#define MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER                 -0x6600\n/** Internal-only message signaling that further message-processing should be done */\n#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING               -0x6580\n/** The asynchronous operation is not completed yet. */\n#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS                 -0x6500\n/** Internal-only message signaling that a message arrived early. */\n#define MBEDTLS_ERR_SSL_EARLY_MESSAGE                     -0x6480\n/* Error space gap */\n/* Error space gap */\n/* Error space gap */\n/* Error space gap */\n/* Error space gap */\n/* Error space gap */\n/* Error space gap */\n/* Error space gap */\n/** An encrypted DTLS-frame with an unexpected CID was received. */\n#define MBEDTLS_ERR_SSL_UNEXPECTED_CID                    -0x6000\n/** An operation failed due to an unexpected version or configuration. */\n#define MBEDTLS_ERR_SSL_VERSION_MISMATCH                  -0x5F00\n/** Invalid value in SSL config */\n#define MBEDTLS_ERR_SSL_BAD_CONFIG                        -0x5E80\n/* Error space gap */\n/** Attempt to verify a certificate without an expected hostname.\n * This is usually insecure.\n *\n * In TLS clients, when a client authenticates a server through its\n * certificate, the client normally checks three things:\n * - the certificate chain must be valid;\n * - the chain must start from a trusted CA;\n * - the certificate must cover the server name that is expected by the client.\n *\n * Omitting any of these checks is generally insecure, and can allow a\n * malicious server to impersonate a legitimate server.\n *\n * The third check may be safely skipped in some unusual scenarios,\n * such as networks where eavesdropping is a risk but not active attacks,\n * or a private PKI where the client equally trusts all servers that are\n * accredited by the root CA.\n *\n * You should call mbedtls_ssl_set_hostname() with the expected server name\n * before starting a TLS handshake on a client (unless the client is\n * set up to only use PSK-based authentication, which does not rely on the\n * host name). If you have determined that server name verification is not\n * required for security in your scenario, call mbedtls_ssl_set_hostname()\n * with \\p NULL as the server name.\n *\n * This error is raised if all of the following conditions are met:\n *\n * - A TLS client is configured with the authentication mode\n *   #MBEDTLS_SSL_VERIFY_REQUIRED (default).\n * - Certificate authentication is enabled.\n * - The client does not call mbedtls_ssl_set_hostname().\n * - The configuration option\n *   #MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME\n *   is not enabled.\n */\n#define MBEDTLS_ERR_SSL_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME  -0x5D80\n\n/*\n * Constants from RFC 8446 for TLS 1.3 PSK modes\n *\n * Those are used in the Pre-Shared Key Exchange Modes extension.\n * See Section 4.2.9 in RFC 8446.\n */\n#define MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE  0 /* Pure PSK-based exchange  */\n#define MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE 1 /* PSK+ECDHE-based exchange */\n\n/*\n * TLS 1.3 NamedGroup values\n *\n * From RF 8446\n *    enum {\n *         // Elliptic Curve Groups (ECDHE)\n *         secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),\n *         x25519(0x001D), x448(0x001E),\n *         // Finite Field Groups (DHE)\n *         ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),\n *         ffdhe6144(0x0103), ffdhe8192(0x0104),\n *         // Reserved Code Points\n *         ffdhe_private_use(0x01FC..0x01FF),\n *         ecdhe_private_use(0xFE00..0xFEFF),\n *         (0xFFFF)\n *     } NamedGroup;\n *\n */\n\n/* Elliptic Curve Groups (ECDHE) */\n#define MBEDTLS_SSL_IANA_TLS_GROUP_NONE               0\n#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1     0x0012\n#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1     0x0013\n#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1     0x0014\n#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1     0x0015\n#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1     0x0016\n#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1     0x0017\n#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1     0x0018\n#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1     0x0019\n#define MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1       0x001A\n#define MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1       0x001B\n#define MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1       0x001C\n#define MBEDTLS_SSL_IANA_TLS_GROUP_X25519        0x001D\n#define MBEDTLS_SSL_IANA_TLS_GROUP_X448          0x001E\n/* Finite Field Groups (DHE) */\n#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048     0x0100\n#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072     0x0101\n#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096     0x0102\n#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144     0x0103\n#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192     0x0104\n\n/*\n * TLS 1.3 Key Exchange Modes\n *\n * Mbed TLS internal identifiers for use with the SSL configuration API\n * mbedtls_ssl_conf_tls13_key_exchange_modes().\n */\n\n#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK            (1u << 0)   /*!< Pure-PSK TLS 1.3 key exchange,\n                                                                         *   encompassing both externally agreed PSKs\n                                                                         *   as well as resumption PSKs. */\n#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL      (1u << 1)   /*!< Pure-Ephemeral TLS 1.3 key exchanges,\n                                                                         *   including for example ECDHE and DHE\n                                                                         *   key exchanges. */\n#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL  (1u << 2)   /*!< PSK-Ephemeral TLS 1.3 key exchanges,\n                                                                         *   using both a PSK and an ephemeral\n                                                                         *   key exchange. */\n\n/* Convenience macros for sets of key exchanges. */\n#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL                         \\\n    (MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK              |            \\\n     MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL    |            \\\n     MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL)          /*!< All TLS 1.3 key exchanges           */\n#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL                     \\\n    (MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK              |            \\\n     MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL)      /*!< All PSK-based TLS 1.3 key exchanges */\n#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL               \\\n    (MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL        |            \\\n     MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL)      /*!< All ephemeral TLS 1.3 key exchanges */\n\n#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE   (0)\n\n/*\n * Various constants\n */\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n/* These are the high and low bytes of ProtocolVersion as defined by:\n * - RFC 5246: ProtocolVersion version = { 3, 3 };     // TLS v1.2\n * - RFC 8446: see section 4.2.1\n */\n#define MBEDTLS_SSL_MAJOR_VERSION_3             3\n#define MBEDTLS_SSL_MINOR_VERSION_3             3   /*!< TLS v1.2 */\n#define MBEDTLS_SSL_MINOR_VERSION_4             4   /*!< TLS v1.3 */\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n\n#define MBEDTLS_SSL_TRANSPORT_STREAM            0   /*!< TLS      */\n#define MBEDTLS_SSL_TRANSPORT_DATAGRAM          1   /*!< DTLS     */\n\n#define MBEDTLS_SSL_MAX_HOST_NAME_LEN           255 /*!< Maximum host name defined in RFC 1035 */\n#define MBEDTLS_SSL_MAX_ALPN_NAME_LEN           255 /*!< Maximum size in bytes of a protocol name in alpn ext., RFC 7301 */\n\n#define MBEDTLS_SSL_MAX_ALPN_LIST_LEN           65535 /*!< Maximum size in bytes of list in alpn ext., RFC 7301          */\n\n/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c\n * NONE must be zero so that memset()ing structure to zero works */\n#define MBEDTLS_SSL_MAX_FRAG_LEN_NONE           0   /*!< don't use this extension   */\n#define MBEDTLS_SSL_MAX_FRAG_LEN_512            1   /*!< MaxFragmentLength 2^9      */\n#define MBEDTLS_SSL_MAX_FRAG_LEN_1024           2   /*!< MaxFragmentLength 2^10     */\n#define MBEDTLS_SSL_MAX_FRAG_LEN_2048           3   /*!< MaxFragmentLength 2^11     */\n#define MBEDTLS_SSL_MAX_FRAG_LEN_4096           4   /*!< MaxFragmentLength 2^12     */\n#define MBEDTLS_SSL_MAX_FRAG_LEN_INVALID        5   /*!< first invalid value        */\n\n#define MBEDTLS_SSL_IS_CLIENT                   0\n#define MBEDTLS_SSL_IS_SERVER                   1\n\n#define MBEDTLS_SSL_EXTENDED_MS_DISABLED        0\n#define MBEDTLS_SSL_EXTENDED_MS_ENABLED         1\n\n#define MBEDTLS_SSL_CID_DISABLED                0\n#define MBEDTLS_SSL_CID_ENABLED                 1\n\n#define MBEDTLS_SSL_ETM_DISABLED                0\n#define MBEDTLS_SSL_ETM_ENABLED                 1\n\n#define MBEDTLS_SSL_COMPRESS_NULL               0\n\n#define MBEDTLS_SSL_VERIFY_NONE                 0\n#define MBEDTLS_SSL_VERIFY_OPTIONAL             1\n#define MBEDTLS_SSL_VERIFY_REQUIRED             2\n#define MBEDTLS_SSL_VERIFY_UNSET                3 /* Used only for sni_authmode */\n\n#define MBEDTLS_SSL_LEGACY_RENEGOTIATION        0\n#define MBEDTLS_SSL_SECURE_RENEGOTIATION        1\n\n#define MBEDTLS_SSL_RENEGOTIATION_DISABLED      0\n#define MBEDTLS_SSL_RENEGOTIATION_ENABLED       1\n\n#define MBEDTLS_SSL_ANTI_REPLAY_DISABLED        0\n#define MBEDTLS_SSL_ANTI_REPLAY_ENABLED         1\n\n#define MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED  -1\n#define MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT  16\n\n#define MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION     0\n#define MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION  1\n#define MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE      2\n\n#define MBEDTLS_SSL_TRUNC_HMAC_DISABLED         0\n#define MBEDTLS_SSL_TRUNC_HMAC_ENABLED          1\n#define MBEDTLS_SSL_TRUNCATED_HMAC_LEN          10  /* 80 bits, rfc 6066 section 7 */\n\n#define MBEDTLS_SSL_SESSION_TICKETS_DISABLED     0\n#define MBEDTLS_SSL_SESSION_TICKETS_ENABLED      1\n\n#define MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED  0\n#define MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED   1\n\n#define MBEDTLS_SSL_PRESET_DEFAULT              0\n#define MBEDTLS_SSL_PRESET_SUITEB               2\n\n#define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED       1\n#define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED      0\n\n#define MBEDTLS_SSL_EARLY_DATA_DISABLED        0\n#define MBEDTLS_SSL_EARLY_DATA_ENABLED         1\n\n#define MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED    0\n#define MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED      1\n\n#define MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT  1\n#define MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER  0\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)\n#if defined(PSA_WANT_ALG_SHA_384)\n#define MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN        48\n#elif defined(PSA_WANT_ALG_SHA_256)\n#define MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN        32\n#endif\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */\n/*\n * Default range for DTLS retransmission timer value, in milliseconds.\n * RFC 6347 4.2.4.1 says from 1 second to 60 seconds.\n */\n#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN    1000\n#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX   60000\n\n/*\n * Whether early data record should be discarded or not and how.\n *\n * The client has indicated early data and the server has rejected them.\n * The server has then to skip past early data by either:\n * - attempting to deprotect received records using the handshake traffic\n *   key, discarding records which fail deprotection (up to the configured\n *   max_early_data_size). Once a record is deprotected successfully,\n *   it is treated as the start of the client's second flight and the\n *   server proceeds as with an ordinary 1-RTT handshake.\n * - skipping all records with an external content type of\n *   \"application_data\" (indicating that they are encrypted), up to the\n *   configured max_early_data_size. This is the expected behavior if the\n *   server has sent an HelloRetryRequest message. The server ignores\n *   application data message before 2nd ClientHello.\n */\n#define MBEDTLS_SSL_EARLY_DATA_NO_DISCARD 0\n#define MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD 1\n#define MBEDTLS_SSL_EARLY_DATA_DISCARD 2\n\n/**\n * \\name SECTION: Module settings\n *\n * The configuration options you can set for this module are in this section.\n * Either change them in mbedtls_config.h or define them on the compiler command line.\n * \\{\n */\n\n/*\n * Maximum fragment length in bytes,\n * determines the size of each of the two internal I/O buffers.\n *\n * Note: the RFC defines the default size of SSL / TLS messages. If you\n * change the value here, other clients / servers may not be able to\n * communicate with you anymore. Only change this value if you control\n * both sides of the connection and have it reduced at both sides, or\n * if you're using the Max Fragment Length extension and you know all your\n * peers are using it too!\n */\n#if !defined(MBEDTLS_SSL_IN_CONTENT_LEN)\n#define MBEDTLS_SSL_IN_CONTENT_LEN 16384\n#endif\n\n#if !defined(MBEDTLS_SSL_OUT_CONTENT_LEN)\n#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384\n#endif\n\n/*\n * Maximum number of heap-allocated bytes for the purpose of\n * DTLS handshake message reassembly and future message buffering.\n */\n#if !defined(MBEDTLS_SSL_DTLS_MAX_BUFFERING)\n#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768\n#endif\n\n/*\n * Maximum length of CIDs for incoming and outgoing messages.\n */\n#if !defined(MBEDTLS_SSL_CID_IN_LEN_MAX)\n#define MBEDTLS_SSL_CID_IN_LEN_MAX          32\n#endif\n\n#if !defined(MBEDTLS_SSL_CID_OUT_LEN_MAX)\n#define MBEDTLS_SSL_CID_OUT_LEN_MAX         32\n#endif\n\n#if !defined(MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY)\n#define MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 16\n#endif\n\n#if !defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE)\n#define MBEDTLS_SSL_MAX_EARLY_DATA_SIZE        1024\n#endif\n\n#if !defined(MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE)\n#define MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE 6000\n#endif\n\n#if !defined(MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH)\n#define MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH 32\n#endif\n\n#if !defined(MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS)\n#define MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS 1\n#endif\n\n/** \\} name SECTION: Module settings */\n\n/*\n * Default to standard CID mode\n */\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \\\n    !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT)\n#define MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT 0\n#endif\n\n/*\n * Length of the verify data for secure renegotiation\n */\n#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12\n\n/*\n * Signaling ciphersuite values (SCSV)\n */\n#define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO    0xFF   /**< renegotiation info ext */\n\n/*\n * Supported Signature and Hash algorithms (For TLS 1.2)\n * RFC 5246 section 7.4.1.4.1\n */\n#define MBEDTLS_SSL_HASH_NONE                0\n#define MBEDTLS_SSL_HASH_MD5                 1\n#define MBEDTLS_SSL_HASH_SHA1                2\n#define MBEDTLS_SSL_HASH_SHA224              3\n#define MBEDTLS_SSL_HASH_SHA256              4\n#define MBEDTLS_SSL_HASH_SHA384              5\n#define MBEDTLS_SSL_HASH_SHA512              6\n\n#define MBEDTLS_SSL_SIG_ANON                 0\n#define MBEDTLS_SSL_SIG_RSA                  1\n#define MBEDTLS_SSL_SIG_ECDSA                3\n\n/*\n * TLS 1.3 signature algorithms\n * RFC 8446, Section 4.2.3\n */\n\n/* RSASSA-PKCS1-v1_5 algorithms */\n#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256 0x0401\n#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384 0x0501\n#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512 0x0601\n\n/* ECDSA algorithms */\n#define MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256 0x0403\n#define MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384 0x0503\n#define MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512 0x0603\n\n/* RSASSA-PSS algorithms with public key OID rsaEncryption */\n#define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256 0x0804\n#define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384 0x0805\n#define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512 0x0806\n\n/* EdDSA algorithms */\n#define MBEDTLS_TLS1_3_SIG_ED25519 0x0807\n#define MBEDTLS_TLS1_3_SIG_ED448 0x0808\n\n/* RSASSA-PSS algorithms with public key OID RSASSA-PSS  */\n#define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA256 0x0809\n#define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA384 0x080A\n#define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA512 0x080B\n\n/* LEGACY ALGORITHMS */\n#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA1 0x0201\n#define MBEDTLS_TLS1_3_SIG_ECDSA_SHA1     0x0203\n\n#define MBEDTLS_TLS1_3_SIG_NONE 0x0\n\n/*\n * Client Certificate Types\n * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5\n */\n#define MBEDTLS_SSL_CERT_TYPE_RSA_SIGN       1\n#define MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN    64\n\n/*\n * Message, alert and handshake types\n */\n#define MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC     20\n#define MBEDTLS_SSL_MSG_ALERT                  21\n#define MBEDTLS_SSL_MSG_HANDSHAKE              22\n#define MBEDTLS_SSL_MSG_APPLICATION_DATA       23\n#define MBEDTLS_SSL_MSG_CID                    25\n\n#define MBEDTLS_SSL_ALERT_LEVEL_WARNING         1\n#define MBEDTLS_SSL_ALERT_LEVEL_FATAL           2\n\n#define MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY           0  /* 0x00 */\n#define MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE    10  /* 0x0A */\n#define MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC        20  /* 0x14 */\n#define MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED     21  /* 0x15 */\n#define MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW       22  /* 0x16 */\n#define MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30  /* 0x1E */\n#define MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE     40  /* 0x28 */\n#define MBEDTLS_SSL_ALERT_MSG_NO_CERT               41  /* 0x29 */\n#define MBEDTLS_SSL_ALERT_MSG_BAD_CERT              42  /* 0x2A */\n#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT      43  /* 0x2B */\n#define MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED          44  /* 0x2C */\n#define MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED          45  /* 0x2D */\n#define MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN          46  /* 0x2E */\n#define MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER     47  /* 0x2F */\n#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA            48  /* 0x30 */\n#define MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED         49  /* 0x31 */\n#define MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR          50  /* 0x32 */\n#define MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR         51  /* 0x33 */\n#define MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION    60  /* 0x3C */\n#define MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION      70  /* 0x46 */\n#define MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71  /* 0x47 */\n#define MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR        80  /* 0x50 */\n#define MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86  /* 0x56 */\n#define MBEDTLS_SSL_ALERT_MSG_USER_CANCELED         90  /* 0x5A */\n#define MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION     100  /* 0x64 */\n#define MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION    109  /* 0x6d -- new in TLS 1.3 */\n#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT      110  /* 0x6E */\n#define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME    112  /* 0x70 */\n#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115  /* 0x73 */\n#define MBEDTLS_SSL_ALERT_MSG_CERT_REQUIRED        116  /* 0x74 */\n#define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */\n\n#define MBEDTLS_SSL_HS_HELLO_REQUEST            0\n#define MBEDTLS_SSL_HS_CLIENT_HELLO             1\n#define MBEDTLS_SSL_HS_SERVER_HELLO             2\n#define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST     3\n#define MBEDTLS_SSL_HS_NEW_SESSION_TICKET       4\n#define MBEDTLS_SSL_HS_END_OF_EARLY_DATA        5\n#define MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS     8\n#define MBEDTLS_SSL_HS_CERTIFICATE             11\n#define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE     12\n#define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST     13\n#define MBEDTLS_SSL_HS_SERVER_HELLO_DONE       14\n#define MBEDTLS_SSL_HS_CERTIFICATE_VERIFY      15\n#define MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE     16\n#define MBEDTLS_SSL_HS_FINISHED                20\n#define MBEDTLS_SSL_HS_MESSAGE_HASH           254\n\n/*\n * TLS extensions\n */\n#define MBEDTLS_TLS_EXT_SERVERNAME                   0\n#define MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME          0\n\n#define MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH          1\n\n#define MBEDTLS_TLS_EXT_TRUNCATED_HMAC               4\n#define MBEDTLS_TLS_EXT_STATUS_REQUEST               5 /* RFC 6066 TLS 1.2 and 1.3 */\n\n#define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES   10\n#define MBEDTLS_TLS_EXT_SUPPORTED_GROUPS            10 /* RFC 8422,7919 TLS 1.2 and 1.3 */\n#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS     11\n\n#define MBEDTLS_TLS_EXT_SIG_ALG                     13 /* RFC 8446 TLS 1.3 */\n#define MBEDTLS_TLS_EXT_USE_SRTP                    14\n#define MBEDTLS_TLS_EXT_HEARTBEAT                   15 /* RFC 6520 TLS 1.2 and 1.3 */\n#define MBEDTLS_TLS_EXT_ALPN                        16\n\n#define MBEDTLS_TLS_EXT_SCT                         18 /* RFC 6962 TLS 1.2 and 1.3 */\n#define MBEDTLS_TLS_EXT_CLI_CERT_TYPE               19 /* RFC 7250 TLS 1.2 and 1.3 */\n#define MBEDTLS_TLS_EXT_SERV_CERT_TYPE              20 /* RFC 7250 TLS 1.2 and 1.3 */\n#define MBEDTLS_TLS_EXT_PADDING                     21 /* RFC 7685 TLS 1.2 and 1.3 */\n#define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC            22 /* 0x16 */\n#define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET  0x0017 /* 23 */\n\n#define MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT           28 /* RFC 8449 (implemented for TLS 1.3 only) */\n\n#define MBEDTLS_TLS_EXT_SESSION_TICKET              35\n\n#define MBEDTLS_TLS_EXT_PRE_SHARED_KEY              41 /* RFC 8446 TLS 1.3 */\n#define MBEDTLS_TLS_EXT_EARLY_DATA                  42 /* RFC 8446 TLS 1.3 */\n#define MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS          43 /* RFC 8446 TLS 1.3 */\n#define MBEDTLS_TLS_EXT_COOKIE                      44 /* RFC 8446 TLS 1.3 */\n#define MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES      45 /* RFC 8446 TLS 1.3 */\n\n#define MBEDTLS_TLS_EXT_CERT_AUTH                   47 /* RFC 8446 TLS 1.3 */\n#define MBEDTLS_TLS_EXT_OID_FILTERS                 48 /* RFC 8446 TLS 1.3 */\n#define MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH         49 /* RFC 8446 TLS 1.3 */\n#define MBEDTLS_TLS_EXT_SIG_ALG_CERT                50 /* RFC 8446 TLS 1.3 */\n#define MBEDTLS_TLS_EXT_KEY_SHARE                   51 /* RFC 8446 TLS 1.3 */\n\n#if MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0\n#define MBEDTLS_TLS_EXT_CID                         54 /* RFC 9146 DTLS 1.2 CID */\n#else\n#define MBEDTLS_TLS_EXT_CID                        254 /* Pre-RFC 9146 DTLS 1.2 CID */\n#endif\n\n#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP               256 /* experimental */\n\n#define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO      0xFF01\n\n/*\n * Size defines\n */\n#if !defined(MBEDTLS_PSK_MAX_LEN)\n/*\n * If the library supports TLS 1.3 tickets and the cipher suite\n * TLS1-3-AES-256-GCM-SHA384, set the PSK maximum length to 48 instead of 32.\n * That way, the TLS 1.3 client and server are able to resume sessions where\n * the cipher suite is TLS1-3-AES-256-GCM-SHA384 (pre-shared keys are 48\n * bytes long in that case).\n */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \\\n    defined(MBEDTLS_SSL_SESSION_TICKETS) && \\\n    defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM) && \\\n    defined(MBEDTLS_MD_CAN_SHA384)\n#define MBEDTLS_PSK_MAX_LEN 48 /* 384 bits */\n#else\n#define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */\n#endif\n#endif /* !MBEDTLS_PSK_MAX_LEN */\n\n/* Dummy type used only for its size */\nunion mbedtls_ssl_premaster_secret {\n    unsigned char dummy; /* Make the union non-empty even with SSL disabled */\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)\n    unsigned char _pms_rsa[48];                         /* RFC 5246 8.1.1 */\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)\n    unsigned char _pms_dhm[MBEDTLS_MPI_MAX_SIZE];      /* RFC 5246 8.1.2 */\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)    || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)  || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)     || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)\n    unsigned char _pms_ecdh[MBEDTLS_ECP_MAX_BYTES];    /* RFC 4492 5.10 */\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)\n    unsigned char _pms_psk[4 + 2 * MBEDTLS_PSK_MAX_LEN];       /* RFC 4279 2 */\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)\n    unsigned char _pms_dhe_psk[4 + MBEDTLS_MPI_MAX_SIZE\n                               + MBEDTLS_PSK_MAX_LEN];         /* RFC 4279 3 */\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)\n    unsigned char _pms_rsa_psk[52 + MBEDTLS_PSK_MAX_LEN];      /* RFC 4279 4 */\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)\n    unsigned char _pms_ecdhe_psk[4 + MBEDTLS_ECP_MAX_BYTES\n                                 + MBEDTLS_PSK_MAX_LEN];       /* RFC 5489 2 */\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n    unsigned char _pms_ecjpake[32];     /* Thread spec: SHA-256 output */\n#endif\n};\n\n#define MBEDTLS_PREMASTER_SIZE     sizeof(union mbedtls_ssl_premaster_secret)\n\n#define MBEDTLS_TLS1_3_MD_MAX_SIZE         PSA_HASH_MAX_SIZE\n\n\n/* Length in number of bytes of the TLS sequence number */\n#define MBEDTLS_SSL_SEQUENCE_NUMBER_LEN 8\n\n/* Helper to state that client_random and server_random need to be stored\n * after the handshake is complete. This is required for context serialization\n * and for the keying material exporter in TLS 1.2. */\n#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) || \\\n    (defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) && defined(MBEDTLS_SSL_PROTO_TLS1_2))\n#define MBEDTLS_SSL_KEEP_RANDBYTES\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * SSL state machine\n */\ntypedef enum {\n    MBEDTLS_SSL_HELLO_REQUEST,\n    MBEDTLS_SSL_CLIENT_HELLO,\n    MBEDTLS_SSL_SERVER_HELLO,\n    MBEDTLS_SSL_SERVER_CERTIFICATE,\n    MBEDTLS_SSL_SERVER_KEY_EXCHANGE,\n    MBEDTLS_SSL_CERTIFICATE_REQUEST,\n    MBEDTLS_SSL_SERVER_HELLO_DONE,\n    MBEDTLS_SSL_CLIENT_CERTIFICATE,\n    MBEDTLS_SSL_CLIENT_KEY_EXCHANGE,\n    MBEDTLS_SSL_CERTIFICATE_VERIFY,\n    MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC,\n    MBEDTLS_SSL_CLIENT_FINISHED,\n    MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC,\n    MBEDTLS_SSL_SERVER_FINISHED,\n    MBEDTLS_SSL_FLUSH_BUFFERS,\n    MBEDTLS_SSL_HANDSHAKE_WRAPUP,\n    MBEDTLS_SSL_NEW_SESSION_TICKET,\n    MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT,\n    MBEDTLS_SSL_HELLO_RETRY_REQUEST,\n    MBEDTLS_SSL_ENCRYPTED_EXTENSIONS,\n    MBEDTLS_SSL_END_OF_EARLY_DATA,\n    MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY,\n    MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED,\n    MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO,\n    MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO,\n    MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO,\n    MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST,\n    MBEDTLS_SSL_HANDSHAKE_OVER,\n    MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET,\n    MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH,\n}\nmbedtls_ssl_states;\n\n/*\n * Early data status, client side only.\n */\n\n#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)\ntypedef enum {\n/*\n * See documentation of mbedtls_ssl_get_early_data_status().\n */\n    MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED,\n    MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED,\n    MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED,\n} mbedtls_ssl_early_data_status;\n#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */\n\n/**\n * \\brief          Callback type: send data on the network.\n *\n * \\note           That callback may be either blocking or non-blocking.\n *\n * \\param ctx      Context for the send callback (typically a file descriptor)\n * \\param buf      Buffer holding the data to send\n * \\param len      Length of the data to send\n *\n * \\return         The callback must return the number of bytes sent if any,\n *                 or a non-zero error code.\n *                 If performing non-blocking I/O, \\c MBEDTLS_ERR_SSL_WANT_WRITE\n *                 must be returned when the operation would block.\n *\n * \\note           The callback is allowed to send fewer bytes than requested.\n *                 It must always return the number of bytes actually sent.\n */\ntypedef int mbedtls_ssl_send_t(void *ctx,\n                               const unsigned char *buf,\n                               size_t len);\n\n/**\n * \\brief          Callback type: receive data from the network.\n *\n * \\note           That callback may be either blocking or non-blocking.\n *\n * \\param ctx      Context for the receive callback (typically a file\n *                 descriptor)\n * \\param buf      Buffer to write the received data to\n * \\param len      Length of the receive buffer\n *\n * \\returns        If data has been received, the positive number of bytes received.\n * \\returns        \\c 0 if the connection has been closed.\n * \\returns        If performing non-blocking I/O, \\c MBEDTLS_ERR_SSL_WANT_READ\n *                 must be returned when the operation would block.\n * \\returns        Another negative error code on other kinds of failures.\n *\n * \\note           The callback may receive fewer bytes than the length of the\n *                 buffer. It must always return the number of bytes actually\n *                 received and written to the buffer.\n */\ntypedef int mbedtls_ssl_recv_t(void *ctx,\n                               unsigned char *buf,\n                               size_t len);\n\n/**\n * \\brief          Callback type: receive data from the network, with timeout\n *\n * \\note           That callback must block until data is received, or the\n *                 timeout delay expires, or the operation is interrupted by a\n *                 signal.\n *\n * \\param ctx      Context for the receive callback (typically a file descriptor)\n * \\param buf      Buffer to write the received data to\n * \\param len      Length of the receive buffer\n * \\param timeout  Maximum number of milliseconds to wait for data\n *                 0 means no timeout (potentially waiting forever)\n *\n * \\return         The callback must return the number of bytes received,\n *                 or a non-zero error code:\n *                 \\c MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out,\n *                 \\c MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal.\n *\n * \\note           The callback may receive fewer bytes than the length of the\n *                 buffer. It must always return the number of bytes actually\n *                 received and written to the buffer.\n */\ntypedef int mbedtls_ssl_recv_timeout_t(void *ctx,\n                                       unsigned char *buf,\n                                       size_t len,\n                                       uint32_t timeout);\n/**\n * \\brief          Callback type: set a pair of timers/delays to watch\n *\n * \\param ctx      Context pointer\n * \\param int_ms   Intermediate delay in milliseconds\n * \\param fin_ms   Final delay in milliseconds\n *                 0 cancels the current timer.\n *\n * \\note           This callback must at least store the necessary information\n *                 for the associated \\c mbedtls_ssl_get_timer_t callback to\n *                 return correct information.\n *\n * \\note           If using an event-driven style of programming, an event must\n *                 be generated when the final delay is passed. The event must\n *                 cause a call to \\c mbedtls_ssl_handshake() with the proper\n *                 SSL context to be scheduled. Care must be taken to ensure\n *                 that at most one such call happens at a time.\n *\n * \\note           Only one timer at a time must be running. Calling this\n *                 function while a timer is running must cancel it. Cancelled\n *                 timers must not generate any event.\n */\ntypedef void mbedtls_ssl_set_timer_t(void *ctx,\n                                     uint32_t int_ms,\n                                     uint32_t fin_ms);\n\n/**\n * \\brief          Callback type: get status of timers/delays\n *\n * \\param ctx      Context pointer\n *\n * \\return         This callback must return:\n *                 -1 if cancelled (fin_ms == 0),\n *                  0 if none of the delays have passed,\n *                  1 if only the intermediate delay has passed,\n *                  2 if the final delay has passed.\n */\ntypedef int mbedtls_ssl_get_timer_t(void *ctx);\n\n/* Defined below */\ntypedef struct mbedtls_ssl_session mbedtls_ssl_session;\ntypedef struct mbedtls_ssl_context mbedtls_ssl_context;\ntypedef struct mbedtls_ssl_config  mbedtls_ssl_config;\n\n/* Defined in library/ssl_misc.h */\ntypedef struct mbedtls_ssl_transform mbedtls_ssl_transform;\ntypedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params;\ntypedef struct mbedtls_ssl_sig_hash_set_t mbedtls_ssl_sig_hash_set_t;\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\ntypedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert;\n#endif\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\ntypedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item;\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)\n#define MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_RESUMPTION                          \\\n    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK                        /* 1U << 0 */\n#define MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION                \\\n    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL              /* 1U << 2 */\n#define MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA                  (1U << 3)\n\n#define MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK                                    \\\n    (MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_RESUMPTION             |      \\\n     MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION   |      \\\n     MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA)\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */\n\n/**\n * \\brief          Callback type: server-side session cache getter\n *\n *                 The session cache is logically a key value store, with\n *                 keys being session IDs and values being instances of\n *                 mbedtls_ssl_session.\n *\n *                 This callback retrieves an entry in this key-value store.\n *\n * \\param data            The address of the session cache structure to query.\n * \\param session_id      The buffer holding the session ID to query.\n * \\param session_id_len  The length of \\p session_id in Bytes.\n * \\param session         The address of the session structure to populate.\n *                        It is initialized with mbdtls_ssl_session_init(),\n *                        and the callback must always leave it in a state\n *                        where it can safely be freed via\n *                        mbedtls_ssl_session_free() independent of the\n *                        return code of this function.\n *\n * \\return                \\c 0 on success\n * \\return                A non-zero return value on failure.\n *\n */\ntypedef int mbedtls_ssl_cache_get_t(void *data,\n                                    unsigned char const *session_id,\n                                    size_t session_id_len,\n                                    mbedtls_ssl_session *session);\n/**\n * \\brief          Callback type: server-side session cache setter\n *\n *                 The session cache is logically a key value store, with\n *                 keys being session IDs and values being instances of\n *                 mbedtls_ssl_session.\n *\n *                 This callback sets an entry in this key-value store.\n *\n * \\param data            The address of the session cache structure to modify.\n * \\param session_id      The buffer holding the session ID to query.\n * \\param session_id_len  The length of \\p session_id in Bytes.\n * \\param session         The address of the session to be stored in the\n *                        session cache.\n *\n * \\return                \\c 0 on success\n * \\return                A non-zero return value on failure.\n */\ntypedef int mbedtls_ssl_cache_set_t(void *data,\n                                    unsigned char const *session_id,\n                                    size_t session_id_len,\n                                    const mbedtls_ssl_session *session);\n\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n/**\n * \\brief           Callback type: start external signature operation.\n *\n *                  This callback is called during an SSL handshake to start\n *                  a signature decryption operation using an\n *                  external processor. The parameter \\p cert contains\n *                  the public key; it is up to the callback function to\n *                  determine how to access the associated private key.\n *\n *                  This function typically sends or enqueues a request, and\n *                  does not wait for the operation to complete. This allows\n *                  the handshake step to be non-blocking.\n *\n *                  The parameters \\p ssl and \\p cert are guaranteed to remain\n *                  valid throughout the handshake. On the other hand, this\n *                  function must save the contents of \\p hash if the value\n *                  is needed for later processing, because the \\p hash buffer\n *                  is no longer valid after this function returns.\n *\n *                  This function may call mbedtls_ssl_set_async_operation_data()\n *                  to store an operation context for later retrieval\n *                  by the resume or cancel callback.\n *\n * \\note            For RSA signatures, this function must produce output\n *                  that is consistent with PKCS#1 v1.5 in the same way as\n *                  mbedtls_rsa_pkcs1_sign(). Before the private key operation,\n *                  apply the padding steps described in RFC 8017, section 9.2\n *                  \"EMSA-PKCS1-v1_5\" as follows.\n *                  - If \\p md_alg is #MBEDTLS_MD_NONE, apply the PKCS#1 v1.5\n *                    encoding, treating \\p hash as the DigestInfo to be\n *                    padded. In other words, apply EMSA-PKCS1-v1_5 starting\n *                    from step 3, with `T = hash` and `tLen = hash_len`.\n *                  - If `md_alg != MBEDTLS_MD_NONE`, apply the PKCS#1 v1.5\n *                    encoding, treating \\p hash as the hash to be encoded and\n *                    padded. In other words, apply EMSA-PKCS1-v1_5 starting\n *                    from step 2, with `digestAlgorithm` obtained by calling\n *                    mbedtls_oid_get_oid_by_md() on \\p md_alg.\n *\n * \\note            For ECDSA signatures, the output format is the DER encoding\n *                  `Ecdsa-Sig-Value` defined in\n *                  [RFC 4492 section 5.4](https://tools.ietf.org/html/rfc4492#section-5.4).\n *\n * \\param ssl             The SSL connection instance. It should not be\n *                        modified other than via\n *                        mbedtls_ssl_set_async_operation_data().\n * \\param cert            Certificate containing the public key.\n *                        In simple cases, this is one of the pointers passed to\n *                        mbedtls_ssl_conf_own_cert() when configuring the SSL\n *                        connection. However, if other callbacks are used, this\n *                        property may not hold. For example, if an SNI callback\n *                        is registered with mbedtls_ssl_conf_sni(), then\n *                        this callback determines what certificate is used.\n * \\param md_alg          Hash algorithm.\n * \\param hash            Buffer containing the hash. This buffer is\n *                        no longer valid when the function returns.\n * \\param hash_len        Size of the \\c hash buffer in bytes.\n *\n * \\return          0 if the operation was started successfully and the SSL\n *                  stack should call the resume callback immediately.\n * \\return          #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation\n *                  was started successfully and the SSL stack should return\n *                  immediately without calling the resume callback yet.\n * \\return          #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external\n *                  processor does not support this key. The SSL stack will\n *                  use the private key object instead.\n * \\return          Any other error indicates a fatal failure and is\n *                  propagated up the call chain. The callback should\n *                  use \\c MBEDTLS_ERR_PK_xxx error codes, and <b>must not</b>\n *                  use \\c MBEDTLS_ERR_SSL_xxx error codes except as\n *                  directed in the documentation of this callback.\n */\ntypedef int mbedtls_ssl_async_sign_t(mbedtls_ssl_context *ssl,\n                                     mbedtls_x509_crt *cert,\n                                     mbedtls_md_type_t md_alg,\n                                     const unsigned char *hash,\n                                     size_t hash_len);\n\n/**\n * \\brief           Callback type: start external decryption operation.\n *\n *                  This callback is called during an SSL handshake to start\n *                  an RSA decryption operation using an\n *                  external processor. The parameter \\p cert contains\n *                  the public key; it is up to the callback function to\n *                  determine how to access the associated private key.\n *\n *                  This function typically sends or enqueues a request, and\n *                  does not wait for the operation to complete. This allows\n *                  the handshake step to be non-blocking.\n *\n *                  The parameters \\p ssl and \\p cert are guaranteed to remain\n *                  valid throughout the handshake. On the other hand, this\n *                  function must save the contents of \\p input if the value\n *                  is needed for later processing, because the \\p input buffer\n *                  is no longer valid after this function returns.\n *\n *                  This function may call mbedtls_ssl_set_async_operation_data()\n *                  to store an operation context for later retrieval\n *                  by the resume or cancel callback.\n *\n * \\warning         RSA decryption as used in TLS is subject to a potential\n *                  timing side channel attack first discovered by Bleichenbacher\n *                  in 1998. This attack can be remotely exploitable\n *                  in practice. To avoid this attack, you must ensure that\n *                  if the callback performs an RSA decryption, the time it\n *                  takes to execute and return the result does not depend\n *                  on whether the RSA decryption succeeded or reported\n *                  invalid padding.\n *\n * \\param ssl             The SSL connection instance. It should not be\n *                        modified other than via\n *                        mbedtls_ssl_set_async_operation_data().\n * \\param cert            Certificate containing the public key.\n *                        In simple cases, this is one of the pointers passed to\n *                        mbedtls_ssl_conf_own_cert() when configuring the SSL\n *                        connection. However, if other callbacks are used, this\n *                        property may not hold. For example, if an SNI callback\n *                        is registered with mbedtls_ssl_conf_sni(), then\n *                        this callback determines what certificate is used.\n * \\param input           Buffer containing the input ciphertext. This buffer\n *                        is no longer valid when the function returns.\n * \\param input_len       Size of the \\p input buffer in bytes.\n *\n * \\return          0 if the operation was started successfully and the SSL\n *                  stack should call the resume callback immediately.\n * \\return          #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation\n *                  was started successfully and the SSL stack should return\n *                  immediately without calling the resume callback yet.\n * \\return          #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external\n *                  processor does not support this key. The SSL stack will\n *                  use the private key object instead.\n * \\return          Any other error indicates a fatal failure and is\n *                  propagated up the call chain. The callback should\n *                  use \\c MBEDTLS_ERR_PK_xxx error codes, and <b>must not</b>\n *                  use \\c MBEDTLS_ERR_SSL_xxx error codes except as\n *                  directed in the documentation of this callback.\n */\ntypedef int mbedtls_ssl_async_decrypt_t(mbedtls_ssl_context *ssl,\n                                        mbedtls_x509_crt *cert,\n                                        const unsigned char *input,\n                                        size_t input_len);\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n/**\n * \\brief           Callback type: resume external operation.\n *\n *                  This callback is called during an SSL handshake to resume\n *                  an external operation started by the\n *                  ::mbedtls_ssl_async_sign_t or\n *                  ::mbedtls_ssl_async_decrypt_t callback.\n *\n *                  This function typically checks the status of a pending\n *                  request or causes the request queue to make progress, and\n *                  does not wait for the operation to complete. This allows\n *                  the handshake step to be non-blocking.\n *\n *                  This function may call mbedtls_ssl_get_async_operation_data()\n *                  to retrieve an operation context set by the start callback.\n *                  It may call mbedtls_ssl_set_async_operation_data() to modify\n *                  this context.\n *\n *                  Note that when this function returns a status other than\n *                  #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, it must free any\n *                  resources associated with the operation.\n *\n * \\param ssl             The SSL connection instance. It should not be\n *                        modified other than via\n *                        mbedtls_ssl_set_async_operation_data().\n * \\param output          Buffer containing the output (signature or decrypted\n *                        data) on success.\n * \\param output_len      On success, number of bytes written to \\p output.\n * \\param output_size     Size of the \\p output buffer in bytes.\n *\n * \\return          0 if output of the operation is available in the\n *                  \\p output buffer.\n * \\return          #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation\n *                  is still in progress. Subsequent requests for progress\n *                  on the SSL connection will call the resume callback\n *                  again.\n * \\return          Any other error means that the operation is aborted.\n *                  The SSL handshake is aborted. The callback should\n *                  use \\c MBEDTLS_ERR_PK_xxx error codes, and <b>must not</b>\n *                  use \\c MBEDTLS_ERR_SSL_xxx error codes except as\n *                  directed in the documentation of this callback.\n */\ntypedef int mbedtls_ssl_async_resume_t(mbedtls_ssl_context *ssl,\n                                       unsigned char *output,\n                                       size_t *output_len,\n                                       size_t output_size);\n\n/**\n * \\brief           Callback type: cancel external operation.\n *\n *                  This callback is called if an SSL connection is closed\n *                  while an asynchronous operation is in progress. Note that\n *                  this callback is not called if the\n *                  ::mbedtls_ssl_async_resume_t callback has run and has\n *                  returned a value other than\n *                  #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, since in that case\n *                  the asynchronous operation has already completed.\n *\n *                  This function may call mbedtls_ssl_get_async_operation_data()\n *                  to retrieve an operation context set by the start callback.\n *\n * \\param ssl             The SSL connection instance. It should not be\n *                        modified.\n */\ntypedef void mbedtls_ssl_async_cancel_t(mbedtls_ssl_context *ssl);\n#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) &&        \\\n    !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n#define MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN  48\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA256\n#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN  32\n#elif defined(MBEDTLS_MD_CAN_SHA384)\n#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA384\n#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN  48\n#elif defined(MBEDTLS_MD_CAN_SHA1)\n#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA1\n#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN  20\n#else\n/* This is already checked in check_config.h, but be sure. */\n#error \"Bad configuration - need SHA-1, SHA-256 or SHA-512 enabled to compute digest of peer CRT.\"\n#endif\n#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED &&\n          !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n\ntypedef struct {\n    unsigned char client_application_traffic_secret_N[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    unsigned char server_application_traffic_secret_N[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    unsigned char exporter_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    unsigned char resumption_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n} mbedtls_ssl_tls13_application_secrets;\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\n\n#define MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH             255\n#define MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH    4\n/*\n * For code readability use a typedef for DTLS-SRTP profiles\n *\n * Use_srtp extension protection profiles values as defined in\n * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml\n *\n * Reminder: if this list is expanded mbedtls_ssl_check_srtp_profile_value\n * must be updated too.\n */\n#define MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80     ((uint16_t) 0x0001)\n#define MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32     ((uint16_t) 0x0002)\n#define MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80          ((uint16_t) 0x0005)\n#define MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32          ((uint16_t) 0x0006)\n/* This one is not iana defined, but for code readability. */\n#define MBEDTLS_TLS_SRTP_UNSET                      ((uint16_t) 0x0000)\n\ntypedef uint16_t mbedtls_ssl_srtp_profile;\n\ntypedef struct mbedtls_dtls_srtp_info_t {\n    /*! The SRTP profile that was negotiated. */\n    mbedtls_ssl_srtp_profile MBEDTLS_PRIVATE(chosen_dtls_srtp_profile);\n    /*! The length of mki_value. */\n    uint16_t MBEDTLS_PRIVATE(mki_len);\n    /*! The mki_value used, with max size of 256 bytes. */\n    unsigned char MBEDTLS_PRIVATE(mki_value)[MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH];\n}\nmbedtls_dtls_srtp_info;\n\n#endif /* MBEDTLS_SSL_DTLS_SRTP */\n\n/** Human-friendly representation of the (D)TLS protocol version. */\ntypedef enum {\n    MBEDTLS_SSL_VERSION_UNKNOWN, /*!< Context not in use or version not yet negotiated. */\n    MBEDTLS_SSL_VERSION_TLS1_2 = 0x0303, /*!< (D)TLS 1.2 */\n    MBEDTLS_SSL_VERSION_TLS1_3 = 0x0304, /*!< (D)TLS 1.3 */\n} mbedtls_ssl_protocol_version;\n\n/*\n * This structure is used for storing current session data.\n *\n * Note: when changing this definition, we need to check and update:\n *  - in tests/suites/test_suite_ssl.function:\n *      ssl_populate_session() and ssl_serialize_session_save_load()\n *  - in library/ssl_tls.c:\n *      mbedtls_ssl_session_init() and mbedtls_ssl_session_free()\n *      mbedtls_ssl_session_save() and ssl_session_load()\n *      ssl_session_copy()\n */\nstruct mbedtls_ssl_session {\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n    unsigned char MBEDTLS_PRIVATE(mfl_code);     /*!< MaxFragmentLength negotiated by peer */\n#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */\n\n/*!< RecordSizeLimit received from the peer */\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n    uint16_t MBEDTLS_PRIVATE(record_size_limit);\n#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */\n\n    unsigned char MBEDTLS_PRIVATE(exported);\n    uint8_t MBEDTLS_PRIVATE(endpoint);          /*!< 0: client, 1: server */\n\n    /** TLS version negotiated in the session. Used if and when renegotiating\n     *  or resuming a session instead of the configured minor TLS version.\n     */\n    mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(tls_version);\n\n#if defined(MBEDTLS_HAVE_TIME)\n    mbedtls_time_t MBEDTLS_PRIVATE(start);       /*!< start time of current session */\n#endif\n    int MBEDTLS_PRIVATE(ciphersuite);            /*!< chosen ciphersuite */\n    size_t MBEDTLS_PRIVATE(id_len);              /*!< session id length  */\n    unsigned char MBEDTLS_PRIVATE(id)[32];       /*!< session identifier */\n    unsigned char MBEDTLS_PRIVATE(master)[48];   /*!< the master secret  */\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    mbedtls_x509_crt *MBEDTLS_PRIVATE(peer_cert);       /*!< peer X.509 cert chain */\n#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n    /*! The digest of the peer's end-CRT. This must be kept to detect CRT\n     *  changes during renegotiation, mitigating the triple handshake attack. */\n    unsigned char *MBEDTLS_PRIVATE(peer_cert_digest);\n    size_t MBEDTLS_PRIVATE(peer_cert_digest_len);\n    mbedtls_md_type_t MBEDTLS_PRIVATE(peer_cert_digest_type);\n#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n    uint32_t MBEDTLS_PRIVATE(verify_result);          /*!<  verification result     */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)\n    unsigned char *MBEDTLS_PRIVATE(ticket);      /*!< RFC 5077 session ticket */\n    size_t MBEDTLS_PRIVATE(ticket_len);          /*!< session ticket length   */\n    uint32_t MBEDTLS_PRIVATE(ticket_lifetime);   /*!< ticket lifetime hint    */\n#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) && \\\n    defined(MBEDTLS_HAVE_TIME)\n    /*! When a ticket is created by a TLS server as part of an established TLS\n     *  session, the ticket creation time may need to be saved for the ticket\n     *  module to be able to check the ticket age when the ticket is used.\n     *  That's the purpose of this field.\n     *  Before creating a new ticket, an Mbed TLS server set this field with\n     *  its current time in milliseconds. This time may then be saved in the\n     *  session ticket data by the session ticket writing function and\n     *  recovered by the ticket parsing function later when the ticket is used.\n     *  The ticket module may then use this time to compute the ticket age and\n     *  determine if it has expired or not.\n     *  The Mbed TLS implementations of the session ticket writing and parsing\n     *  functions save and retrieve the ticket creation time as part of the\n     *  session ticket data. The session ticket parsing function relies on\n     *  the mbedtls_ssl_session_get_ticket_creation_time() API to get the\n     *  ticket creation time from the session ticket data.\n     */\n    mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_creation_time);\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)\n    uint32_t MBEDTLS_PRIVATE(ticket_age_add);     /*!< Randomly generated value used to obscure the age of the ticket */\n    uint8_t MBEDTLS_PRIVATE(ticket_flags);        /*!< Ticket flags */\n    uint8_t MBEDTLS_PRIVATE(resumption_key_len);  /*!< resumption_key length */\n    unsigned char MBEDTLS_PRIVATE(resumption_key)[MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN];\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && defined(MBEDTLS_SSL_CLI_C)\n    char *MBEDTLS_PRIVATE(hostname);             /*!< host name binded with tickets */\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION && MBEDTLS_SSL_CLI_C */\n\n#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C)\n    char *ticket_alpn;                      /*!< ALPN negotiated in the session\n                                                 during which the ticket was generated. */\n#endif\n\n#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_CLI_C)\n    /*! Time in milliseconds when the last ticket was received. */\n    mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_reception_time);\n#endif\n#endif /*  MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    uint32_t MBEDTLS_PRIVATE(max_early_data_size);          /*!< maximum amount of early data in tickets */\n#endif\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n    int MBEDTLS_PRIVATE(encrypt_then_mac);       /*!< flag for EtM activation                */\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    mbedtls_ssl_tls13_application_secrets MBEDTLS_PRIVATE(app_secrets);\n#endif\n};\n\n/*\n * Identifiers for PRFs used in various versions of TLS.\n */\ntypedef enum {\n    MBEDTLS_SSL_TLS_PRF_NONE,\n    MBEDTLS_SSL_TLS_PRF_SHA384,\n    MBEDTLS_SSL_TLS_PRF_SHA256,\n    MBEDTLS_SSL_HKDF_EXPAND_SHA384,\n    MBEDTLS_SSL_HKDF_EXPAND_SHA256\n}\nmbedtls_tls_prf_types;\n\ntypedef enum {\n    MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET = 0,\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET,\n    MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET,\n    MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET,\n    MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET,\n    MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET,\n    MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET,\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n} mbedtls_ssl_key_export_type;\n\n/**\n * \\brief           Callback type: Export key alongside random values for\n *                                 session identification, and PRF for\n *                                 implementation of TLS key exporters.\n *\n * \\param p_expkey   Context for the callback.\n * \\param type       The type of the key that is being exported.\n * \\param secret     The address of the buffer holding the secret\n *                   that's being exporterd.\n * \\param secret_len The length of \\p secret in bytes.\n * \\param client_random The client random bytes.\n * \\param server_random The server random bytes.\n * \\param tls_prf_type The identifier for the PRF used in the handshake\n *                     to which the key belongs.\n */\ntypedef void mbedtls_ssl_export_keys_t(void *p_expkey,\n                                       mbedtls_ssl_key_export_type type,\n                                       const unsigned char *secret,\n                                       size_t secret_len,\n                                       const unsigned char client_random[32],\n                                       const unsigned char server_random[32],\n                                       mbedtls_tls_prf_types tls_prf_type);\n\n#if defined(MBEDTLS_SSL_SRV_C)\n/**\n * \\brief           Callback type: generic handshake callback\n *\n * \\note            Callbacks may use user_data funcs to set/get app user data.\n *                  See \\c mbedtls_ssl_get_user_data_p()\n *                      \\c mbedtls_ssl_get_user_data_n()\n *                      \\c mbedtls_ssl_conf_get_user_data_p()\n *                      \\c mbedtls_ssl_conf_get_user_data_n()\n *\n * \\param ssl       \\c mbedtls_ssl_context on which the callback is run\n *\n * \\return          The return value of the callback is 0 if successful,\n *                  or a specific MBEDTLS_ERR_XXX code, which will cause\n *                  the handshake to be aborted.\n */\ntypedef int (*mbedtls_ssl_hs_cb_t)(mbedtls_ssl_context *ssl);\n#endif\n\n/* A type for storing user data in a library structure.\n *\n * The representation of type may change in future versions of the library.\n * Only the behaviors guaranteed by documented accessor functions are\n * guaranteed to remain stable.\n */\ntypedef union {\n    uintptr_t n;                /* typically a handle to an associated object */\n    void *p;                    /* typically a pointer to extra data */\n} mbedtls_ssl_user_data_t;\n\n/**\n * SSL/TLS configuration to be shared between mbedtls_ssl_context structures.\n */\nstruct mbedtls_ssl_config {\n    /* Group items mostly by size. This helps to reduce memory wasted to\n     * padding. It also helps to keep smaller fields early in the structure,\n     * so that elements tend to be in the 128-element direct access window\n     * on Arm Thumb, which reduces the code size. */\n\n    mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(max_tls_version);  /*!< max. TLS version used */\n    mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(min_tls_version);  /*!< min. TLS version used */\n\n    /*\n     * Flags (could be bit-fields to save RAM, but separate bytes make\n     * the code smaller on architectures with an instruction for direct\n     * byte access).\n     */\n\n    uint8_t MBEDTLS_PRIVATE(endpoint);      /*!< 0: client, 1: server               */\n    uint8_t MBEDTLS_PRIVATE(transport);     /*!< 0: stream (TLS), 1: datagram (DTLS)    */\n    uint8_t MBEDTLS_PRIVATE(authmode);      /*!< MBEDTLS_SSL_VERIFY_XXX             */\n    /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE          */\n    uint8_t MBEDTLS_PRIVATE(allow_legacy_renegotiation); /*!< MBEDTLS_LEGACY_XXX   */\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n    uint8_t MBEDTLS_PRIVATE(mfl_code);      /*!< desired fragment length indicator\n                                                 (MBEDTLS_SSL_MAX_FRAG_LEN_XXX) */\n#endif\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n    uint8_t MBEDTLS_PRIVATE(encrypt_then_mac); /*!< negotiate encrypt-then-mac?    */\n#endif\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\n    uint8_t MBEDTLS_PRIVATE(extended_ms);   /*!< negotiate extended master secret?  */\n#endif\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\n    uint8_t MBEDTLS_PRIVATE(anti_replay);   /*!< detect and prevent replay?         */\n#endif\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    uint8_t MBEDTLS_PRIVATE(disable_renegotiation); /*!< disable renegotiation?     */\n#endif\n#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \\\n    defined(MBEDTLS_SSL_CLI_C)\n    /** Encodes two booleans, one stating whether TLS 1.2 session tickets are\n     *  enabled or not, the other one whether the handling of TLS 1.3\n     *  NewSessionTicket messages is enabled or not. They are respectively set\n     *  by mbedtls_ssl_conf_session_tickets() and\n     *  mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets().\n     */\n    uint8_t MBEDTLS_PRIVATE(session_tickets);   /*!< use session tickets? */\n#endif\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \\\n    defined(MBEDTLS_SSL_SRV_C) && \\\n    defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    uint16_t MBEDTLS_PRIVATE(new_session_tickets_count);   /*!< number of NewSessionTicket */\n#endif\n\n#if defined(MBEDTLS_SSL_SRV_C)\n    uint8_t MBEDTLS_PRIVATE(cert_req_ca_list);  /*!< enable sending CA list in\n                                                     Certificate Request messages? */\n    uint8_t MBEDTLS_PRIVATE(respect_cli_pref);  /*!< pick the ciphersuite according to\n                                                     the client's preferences rather\n                                                     than ours? */\n#endif\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    uint8_t MBEDTLS_PRIVATE(ignore_unexpected_cid); /*!< Should DTLS record with\n                                                     *   unexpected CID\n                                                     *   lead to failure? */\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\n    uint8_t MBEDTLS_PRIVATE(dtls_srtp_mki_support); /* support having mki_value\n                                                       in the use_srtp extension? */\n#endif\n\n    /*\n     * Pointers\n     */\n\n    /** Allowed ciphersuites for (D)TLS 1.2 (0-terminated)                  */\n    const int *MBEDTLS_PRIVATE(ciphersuite_list);\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    /** Allowed TLS 1.3 key exchange modes.                                 */\n    int MBEDTLS_PRIVATE(tls13_kex_modes);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n    /** Callback for printing debug output                                  */\n    void(*MBEDTLS_PRIVATE(f_dbg))(void *, int, const char *, int, const char *);\n    void *MBEDTLS_PRIVATE(p_dbg);                    /*!< context for the debug function     */\n\n    /** Callback for getting (pseudo-)random numbers                        */\n    int(*MBEDTLS_PRIVATE(f_rng))(void *, unsigned char *, size_t);\n    void *MBEDTLS_PRIVATE(p_rng);                    /*!< context for the RNG function       */\n\n    /** Callback to retrieve a session from the cache                       */\n    mbedtls_ssl_cache_get_t *MBEDTLS_PRIVATE(f_get_cache);\n    /** Callback to store a session into the cache                          */\n    mbedtls_ssl_cache_set_t *MBEDTLS_PRIVATE(f_set_cache);\n    void *MBEDTLS_PRIVATE(p_cache);                  /*!< context for cache callbacks        */\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    /** Callback for setting cert according to SNI extension                */\n    int(*MBEDTLS_PRIVATE(f_sni))(void *, mbedtls_ssl_context *, const unsigned char *, size_t);\n    void *MBEDTLS_PRIVATE(p_sni);                    /*!< context for SNI callback           */\n#endif\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n    /** Callback to customize X.509 certificate chain verification          */\n    int(*MBEDTLS_PRIVATE(f_vrfy))(void *, mbedtls_x509_crt *, int, uint32_t *);\n    void *MBEDTLS_PRIVATE(p_vrfy);                   /*!< context for X.509 verify calllback */\n#endif\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)\n#if defined(MBEDTLS_SSL_SRV_C)\n    /** Callback to retrieve PSK key from identity                          */\n    int(*MBEDTLS_PRIVATE(f_psk))(void *, mbedtls_ssl_context *, const unsigned char *, size_t);\n    void *MBEDTLS_PRIVATE(p_psk);                    /*!< context for PSK callback           */\n#endif\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)\n    /** Callback to create & write a cookie for ClientHello verification    */\n    int(*MBEDTLS_PRIVATE(f_cookie_write))(void *, unsigned char **, unsigned char *,\n                                          const unsigned char *, size_t);\n    /** Callback to verify validity of a ClientHello cookie                 */\n    int(*MBEDTLS_PRIVATE(f_cookie_check))(void *, const unsigned char *, size_t,\n                                          const unsigned char *, size_t);\n    void *MBEDTLS_PRIVATE(p_cookie);                 /*!< context for the cookie callbacks   */\n#endif\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C)\n    /** Callback to create & write a session ticket                         */\n    int(*MBEDTLS_PRIVATE(f_ticket_write))(void *, const mbedtls_ssl_session *,\n                                          unsigned char *, const unsigned char *, size_t *,\n                                          uint32_t *);\n    /** Callback to parse a session ticket into a session structure         */\n    int(*MBEDTLS_PRIVATE(f_ticket_parse))(void *, mbedtls_ssl_session *, unsigned char *, size_t);\n    void *MBEDTLS_PRIVATE(p_ticket);                 /*!< context for the ticket callbacks   */\n#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    size_t MBEDTLS_PRIVATE(cid_len); /*!< The length of CIDs for incoming DTLS records.      */\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n    const mbedtls_x509_crt_profile *MBEDTLS_PRIVATE(cert_profile); /*!< verification profile */\n    mbedtls_ssl_key_cert *MBEDTLS_PRIVATE(key_cert); /*!< own certificate/key pair(s)        */\n    mbedtls_x509_crt *MBEDTLS_PRIVATE(ca_chain);     /*!< trusted CAs                        */\n    mbedtls_x509_crl *MBEDTLS_PRIVATE(ca_crl);       /*!< trusted CAs CRLs                   */\n#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)\n    mbedtls_x509_crt_ca_cb_t MBEDTLS_PRIVATE(f_ca_cb);\n    void *MBEDTLS_PRIVATE(p_ca_cb);\n#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n    mbedtls_ssl_async_sign_t *MBEDTLS_PRIVATE(f_async_sign_start); /*!< start asynchronous signature operation */\n    mbedtls_ssl_async_decrypt_t *MBEDTLS_PRIVATE(f_async_decrypt_start); /*!< start asynchronous decryption operation */\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n    mbedtls_ssl_async_resume_t *MBEDTLS_PRIVATE(f_async_resume); /*!< resume asynchronous operation */\n    mbedtls_ssl_async_cancel_t *MBEDTLS_PRIVATE(f_async_cancel); /*!< cancel asynchronous operation */\n    void *MBEDTLS_PRIVATE(p_async_config_data); /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */\n#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n    const int *MBEDTLS_PRIVATE(sig_hashes);         /*!< allowed signature hashes           */\n#endif\n    const uint16_t *MBEDTLS_PRIVATE(sig_algs);      /*!< allowed signature algorithms       */\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    const mbedtls_ecp_group_id *MBEDTLS_PRIVATE(curve_list); /*!< allowed curves             */\n#endif\n\n    const uint16_t *MBEDTLS_PRIVATE(group_list);     /*!< allowed IANA NamedGroups */\n\n#if defined(MBEDTLS_DHM_C)\n    mbedtls_mpi MBEDTLS_PRIVATE(dhm_P);              /*!< prime modulus for DHM              */\n    mbedtls_mpi MBEDTLS_PRIVATE(dhm_G);              /*!< generator for DHM                  */\n#endif\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    mbedtls_svc_key_id_t MBEDTLS_PRIVATE(psk_opaque); /*!< PSA key slot holding opaque PSK. This field\n                                                       *   should only be set via\n                                                       *   mbedtls_ssl_conf_psk_opaque().\n                                                       *   If either no PSK or a raw PSK have been\n                                                       *   configured, this has value \\c 0.\n                                                       */\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    unsigned char *MBEDTLS_PRIVATE(psk);      /*!< The raw pre-shared key. This field should\n                                               *   only be set via mbedtls_ssl_conf_psk().\n                                               *   If either no PSK or an opaque PSK\n                                               *   have been configured, this has value NULL. */\n    size_t         MBEDTLS_PRIVATE(psk_len);  /*!< The length of the raw pre-shared key.\n                                               *   This field should only be set via\n                                               *   mbedtls_ssl_conf_psk().\n                                               *   Its value is non-zero if and only if\n                                               *   \\c psk is not \\c NULL. */\n\n    unsigned char *MBEDTLS_PRIVATE(psk_identity);    /*!< The PSK identity for PSK negotiation.\n                                                      *   This field should only be set via\n                                                      *   mbedtls_ssl_conf_psk().\n                                                      *   This is set if and only if either\n                                                      *   \\c psk or \\c psk_opaque are set. */\n    size_t         MBEDTLS_PRIVATE(psk_identity_len);/*!< The length of PSK identity.\n                                                      *   This field should only be set via\n                                                      *   mbedtls_ssl_conf_psk().\n                                                      *   Its value is non-zero if and only if\n                                                      *   \\c psk is not \\c NULL or \\c psk_opaque\n                                                      *   is not \\c 0. */\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    int MBEDTLS_PRIVATE(early_data_enabled);     /*!< Early data enablement:\n                                                  *   - MBEDTLS_SSL_EARLY_DATA_DISABLED,\n                                                  *   - MBEDTLS_SSL_EARLY_DATA_ENABLED */\n\n#if defined(MBEDTLS_SSL_SRV_C)\n    /* The maximum amount of 0-RTT data. RFC 8446 section 4.6.1 */\n    uint32_t MBEDTLS_PRIVATE(max_early_data_size);\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n#if defined(MBEDTLS_SSL_ALPN)\n    const char **MBEDTLS_PRIVATE(alpn_list);         /*!< ordered list of protocols          */\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\n    /*! ordered list of supported srtp profile */\n    const mbedtls_ssl_srtp_profile *MBEDTLS_PRIVATE(dtls_srtp_profile_list);\n    /*! number of supported profiles */\n    size_t MBEDTLS_PRIVATE(dtls_srtp_profile_list_len);\n#endif /* MBEDTLS_SSL_DTLS_SRTP */\n\n    /*\n     * Numerical settings (int)\n     */\n\n    uint32_t MBEDTLS_PRIVATE(read_timeout);          /*!< timeout for mbedtls_ssl_read (ms)  */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    uint32_t MBEDTLS_PRIVATE(hs_timeout_min);        /*!< initial value of the handshake\n                                                        retransmission timeout (ms)        */\n    uint32_t MBEDTLS_PRIVATE(hs_timeout_max);        /*!< maximum value of the handshake\n                                                        retransmission timeout (ms)        */\n#endif\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    int MBEDTLS_PRIVATE(renego_max_records);         /*!< grace period for renegotiation     */\n    unsigned char MBEDTLS_PRIVATE(renego_period)[8]; /*!< value of the record counters\n                                                        that triggers renegotiation        */\n#endif\n\n    unsigned int MBEDTLS_PRIVATE(badmac_limit);      /*!< limit of records with a bad MAC    */\n\n#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C)\n    unsigned int MBEDTLS_PRIVATE(dhm_min_bitlen);    /*!< min. bit length of the DHM prime   */\n#endif\n\n    /** User data pointer or handle.\n     *\n     * The library sets this to \\p 0 when creating a context and does not\n     * access it afterwards.\n     */\n    mbedtls_ssl_user_data_t MBEDTLS_PRIVATE(user_data);\n\n#if defined(MBEDTLS_SSL_SRV_C)\n    mbedtls_ssl_hs_cb_t MBEDTLS_PRIVATE(f_cert_cb);  /*!< certificate selection callback */\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)\n    const mbedtls_x509_crt *MBEDTLS_PRIVATE(dn_hints);/*!< acceptable client cert issuers    */\n#endif\n};\n\nstruct mbedtls_ssl_context {\n    const mbedtls_ssl_config *MBEDTLS_PRIVATE(conf); /*!< configuration information          */\n\n    /*\n     * Miscellaneous\n     */\n    int MBEDTLS_PRIVATE(state);                  /*!< SSL handshake: current state     */\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    int MBEDTLS_PRIVATE(renego_status);          /*!< Initial, in progress, pending?   */\n    int MBEDTLS_PRIVATE(renego_records_seen);    /*!< Records since renego request, or with DTLS,\n                                                    number of retransmissions of request if\n                                                    renego_max_records is < 0           */\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n\n    /**\n     * Maximum TLS version to be negotiated, then negotiated TLS version.\n     *\n     * It is initialized as the configured maximum TLS version to be\n     * negotiated by mbedtls_ssl_setup().\n     *\n     * When renegotiating or resuming a session, it is overwritten in the\n     * ClientHello writing preparation stage with the previously negotiated\n     * TLS version.\n     *\n     * On client side, it is updated to the TLS version selected by the server\n     * for the handshake when the ServerHello is received.\n     *\n     * On server side, it is updated to the TLS version the server selects for\n     * the handshake when the ClientHello is received.\n     */\n    mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(tls_version);\n\n#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)\n    /**\n     * State of the negotiation and transfer of early data. Reset to\n     * MBEDTLS_SSL_EARLY_DATA_STATE_IDLE when the context is reset.\n     */\n    int MBEDTLS_PRIVATE(early_data_state);\n#endif\n\n    /** Multipurpose field.\n     *\n     * - DTLS: records with a bad MAC received.\n     * - TLS: accumulated length of handshake fragments (up to \\c in_hslen).\n     *\n     * This field is multipurpose in order to preserve the ABI in the\n     * Mbed TLS 3.6 LTS branch. Until 3.6.2, it was only used in DTLS\n     * and called `badmac_seen`.\n     */\n    unsigned MBEDTLS_PRIVATE(badmac_seen_or_in_hsfraglen);\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n    /** Callback to customize X.509 certificate chain verification          */\n    int(*MBEDTLS_PRIVATE(f_vrfy))(void *, mbedtls_x509_crt *, int, uint32_t *);\n    void *MBEDTLS_PRIVATE(p_vrfy);                   /*!< context for X.509 verify callback */\n#endif\n\n    mbedtls_ssl_send_t *MBEDTLS_PRIVATE(f_send); /*!< Callback for network send */\n    mbedtls_ssl_recv_t *MBEDTLS_PRIVATE(f_recv); /*!< Callback for network receive */\n    mbedtls_ssl_recv_timeout_t *MBEDTLS_PRIVATE(f_recv_timeout);\n    /*!< Callback for network receive with timeout */\n\n    void *MBEDTLS_PRIVATE(p_bio);                /*!< context for I/O operations   */\n\n    /*\n     * Session layer\n     */\n    mbedtls_ssl_session *MBEDTLS_PRIVATE(session_in);            /*!<  current session data (in)   */\n    mbedtls_ssl_session *MBEDTLS_PRIVATE(session_out);           /*!<  current session data (out)  */\n    mbedtls_ssl_session *MBEDTLS_PRIVATE(session);               /*!<  negotiated session data     */\n    mbedtls_ssl_session *MBEDTLS_PRIVATE(session_negotiate);     /*!<  session data in negotiation */\n\n    mbedtls_ssl_handshake_params *MBEDTLS_PRIVATE(handshake);    /*!<  params required only during\n                                                                    the handshake process        */\n\n    /*\n     * Record layer transformations\n     */\n    mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_in);        /*!<  current transform params (in)\n                                                                  *    This is always a reference,\n                                                                  *    never an owning pointer.        */\n    mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_out);       /*!<  current transform params (out)\n                                                                  *    This is always a reference,\n                                                                  *    never an owning pointer.        */\n    mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform);           /*!<  negotiated transform params\n                                                                  *    This pointer owns the transform\n                                                                  *    it references.                  */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_negotiate); /*!<  transform params in negotiation\n                                                                  *    This pointer owns the transform\n                                                                  *    it references.                  */\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    /*! The application data transform in TLS 1.3.\n     *  This pointer owns the transform it references. */\n    mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_application);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n    /*\n     * Timers\n     */\n    void *MBEDTLS_PRIVATE(p_timer);              /*!< context for the timer callbacks */\n\n    mbedtls_ssl_set_timer_t *MBEDTLS_PRIVATE(f_set_timer);       /*!< set timer callback */\n    mbedtls_ssl_get_timer_t *MBEDTLS_PRIVATE(f_get_timer);       /*!< get timer callback */\n\n    /*\n     * Record layer (incoming data)\n     */\n    unsigned char *MBEDTLS_PRIVATE(in_buf);      /*!< input buffer                     */\n    unsigned char *MBEDTLS_PRIVATE(in_ctr);      /*!< 64-bit incoming message counter\n                                                    TLS: maintained by us\n                                                    DTLS: read from peer             */\n    unsigned char *MBEDTLS_PRIVATE(in_hdr);      /*!< start of record header           */\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    unsigned char *MBEDTLS_PRIVATE(in_cid);      /*!< The start of the CID;\n                                                  *   (the end is marked by in_len).   */\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n    unsigned char *MBEDTLS_PRIVATE(in_len);      /*!< two-bytes message length field   */\n    unsigned char *MBEDTLS_PRIVATE(in_iv);       /*!< ivlen-byte IV                    */\n    unsigned char *MBEDTLS_PRIVATE(in_msg);      /*!< message contents (in_iv+ivlen)   */\n    unsigned char *MBEDTLS_PRIVATE(in_offt);     /*!< read offset in application data  */\n\n    int MBEDTLS_PRIVATE(in_msgtype);             /*!< record header: message type      */\n    size_t MBEDTLS_PRIVATE(in_msglen);           /*!< record header: message length    */\n    size_t MBEDTLS_PRIVATE(in_left);             /*!< amount of data read so far       */\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n    size_t MBEDTLS_PRIVATE(in_buf_len);          /*!< length of input buffer           */\n#endif\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    uint16_t MBEDTLS_PRIVATE(in_epoch);          /*!< DTLS epoch for incoming records  */\n    size_t MBEDTLS_PRIVATE(next_record_offset);  /*!< offset of the next record in datagram\n                                                    (equal to in_left if none)       */\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\n    uint64_t MBEDTLS_PRIVATE(in_window_top);     /*!< last validated record seq_num    */\n    uint64_t MBEDTLS_PRIVATE(in_window);         /*!< bitmask for replay detection     */\n#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */\n\n    size_t MBEDTLS_PRIVATE(in_hslen);            /*!< current handshake message length,\n                                                    including the handshake header   */\n    int MBEDTLS_PRIVATE(nb_zero);                /*!< # of 0-length encrypted messages */\n\n    int MBEDTLS_PRIVATE(keep_current_message);   /*!< drop or reuse current message\n                                                    on next call to record layer? */\n\n    /* The following three variables indicate if and, if yes,\n     * what kind of alert is pending to be sent.\n     */\n    unsigned char MBEDTLS_PRIVATE(send_alert);   /*!< Determines if a fatal alert\n                                                    should be sent. Values:\n                                                    - \\c 0 , no alert is to be sent.\n                                                    - \\c 1 , alert is to be sent. */\n    unsigned char MBEDTLS_PRIVATE(alert_type);   /*!< Type of alert if send_alert\n                                                    != 0 */\n    int MBEDTLS_PRIVATE(alert_reason);           /*!< The error code to be returned\n                                                    to the user once the fatal alert\n                                                    has been sent. */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    uint8_t MBEDTLS_PRIVATE(disable_datagram_packing);  /*!< Disable packing multiple records\n                                                         *   within a single datagram.  */\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n#if defined(MBEDTLS_SSL_SRV_C)\n    /*\n     * One of:\n     * MBEDTLS_SSL_EARLY_DATA_NO_DISCARD\n     * MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD\n     * MBEDTLS_SSL_EARLY_DATA_DISCARD\n     */\n    uint8_t MBEDTLS_PRIVATE(discard_early_data_record);\n#endif\n    uint32_t MBEDTLS_PRIVATE(total_early_data_size); /*!< Number of received/written early data bytes */\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n    /*\n     * Record layer (outgoing data)\n     */\n    unsigned char *MBEDTLS_PRIVATE(out_buf);     /*!< output buffer                    */\n    unsigned char *MBEDTLS_PRIVATE(out_ctr);     /*!< 64-bit outgoing message counter  */\n    unsigned char *MBEDTLS_PRIVATE(out_hdr);     /*!< start of record header           */\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    unsigned char *MBEDTLS_PRIVATE(out_cid);     /*!< The start of the CID;\n                                                  *   (the end is marked by in_len).   */\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n    unsigned char *MBEDTLS_PRIVATE(out_len);     /*!< two-bytes message length field   */\n    unsigned char *MBEDTLS_PRIVATE(out_iv);      /*!< ivlen-byte IV                    */\n    unsigned char *MBEDTLS_PRIVATE(out_msg);     /*!< message contents (out_iv+ivlen)  */\n\n    int MBEDTLS_PRIVATE(out_msgtype);            /*!< record header: message type      */\n    size_t MBEDTLS_PRIVATE(out_msglen);          /*!< record header: message length    */\n    size_t MBEDTLS_PRIVATE(out_left);            /*!< amount of data not yet written   */\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n    size_t MBEDTLS_PRIVATE(out_buf_len);         /*!< length of output buffer          */\n#endif\n\n    unsigned char MBEDTLS_PRIVATE(cur_out_ctr)[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!<  Outgoing record sequence  number. */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    uint16_t MBEDTLS_PRIVATE(mtu);               /*!< path mtu, used to fragment outgoing messages */\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    /*\n     * User settings\n     */\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n    /** Expected peer CN for verification.\n     *\n     * Also used on clients for SNI,\n     * and for TLS 1.3 session resumption using tickets.\n     *\n     * The value of this field can be:\n     * - \\p NULL in a newly initialized or reset context.\n     * - A heap-allocated copy of the last value passed to\n     *   mbedtls_ssl_set_hostname(), if the last call had a non-null\n     *  \\p hostname argument.\n     * - A special value to indicate that mbedtls_ssl_set_hostname()\n     *   was called with \\p NULL (as opposed to never having been called).\n     *   See `mbedtls_ssl_get_hostname_pointer()` in `ssl_tls.c`.\n     *\n     * If this field contains the value \\p NULL and the configuration option\n     * #MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME\n     * is unset, on a TLS client, attempting to verify a server certificate\n     * results in the error\n     * #MBEDTLS_ERR_SSL_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME.\n     *\n     * If this field contains the special value described above, or if\n     * the value is \\p NULL and the configuration option\n     * #MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME\n     * is set, then the peer name verification is skipped, which may be\n     * insecure, especially on a client. Furthermore, on a client, the\n     * server_name extension is not sent, and the server name is ignored\n     * in TLS 1.3 session resumption using tickets.\n     */\n    char *MBEDTLS_PRIVATE(hostname);\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n#if defined(MBEDTLS_SSL_ALPN)\n    const char *MBEDTLS_PRIVATE(alpn_chosen);    /*!<  negotiated protocol                   */\n#endif /* MBEDTLS_SSL_ALPN */\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\n    /*\n     * use_srtp extension\n     */\n    mbedtls_dtls_srtp_info MBEDTLS_PRIVATE(dtls_srtp_info);\n#endif /* MBEDTLS_SSL_DTLS_SRTP */\n\n    /*\n     * Information for DTLS hello verify\n     */\n#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)\n    unsigned char  *MBEDTLS_PRIVATE(cli_id);         /*!<  transport-level ID of the client  */\n    size_t          MBEDTLS_PRIVATE(cli_id_len);     /*!<  length of cli_id                  */\n#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */\n\n    /*\n     * Secure renegotiation\n     */\n    /* needed to know when to send extension on server */\n    int MBEDTLS_PRIVATE(secure_renegotiation);           /*!<  does peer support legacy or\n                                                            secure renegotiation           */\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    size_t MBEDTLS_PRIVATE(verify_data_len);             /*!<  length of verify data stored   */\n    char MBEDTLS_PRIVATE(own_verify_data)[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!<  previous handshake verify data */\n    char MBEDTLS_PRIVATE(peer_verify_data)[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!<  previous handshake verify data */\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    /* CID configuration to use in subsequent handshakes. */\n\n    /*! The next incoming CID, chosen by the user and applying to\n     *  all subsequent handshakes. This may be different from the\n     *  CID currently used in case the user has re-configured the CID\n     *  after an initial handshake. */\n    unsigned char MBEDTLS_PRIVATE(own_cid)[MBEDTLS_SSL_CID_IN_LEN_MAX];\n    uint8_t MBEDTLS_PRIVATE(own_cid_len);   /*!< The length of \\c own_cid. */\n    uint8_t MBEDTLS_PRIVATE(negotiate_cid); /*!< This indicates whether the CID extension should\n                                             *   be negotiated in the next handshake or not.\n                                             *   Possible values are #MBEDTLS_SSL_CID_ENABLED\n                                             *   and #MBEDTLS_SSL_CID_DISABLED. */\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n    /** Callback to export key block and master secret                      */\n    mbedtls_ssl_export_keys_t *MBEDTLS_PRIVATE(f_export_keys);\n    void *MBEDTLS_PRIVATE(p_export_keys);            /*!< context for key export callback    */\n\n    /** User data pointer or handle.\n     *\n     * The library sets this to \\p 0 when creating a context and does not\n     * access it afterwards.\n     *\n     * \\warning Serializing and restoring an SSL context with\n     *          mbedtls_ssl_context_save() and mbedtls_ssl_context_load()\n     *          does not currently restore the user data.\n     */\n    mbedtls_ssl_user_data_t MBEDTLS_PRIVATE(user_data);\n};\n\n/**\n * \\brief               Return the name of the ciphersuite associated with the\n *                      given ID\n *\n * \\param ciphersuite_id SSL ciphersuite ID\n *\n * \\return              a string containing the ciphersuite name\n */\nconst char *mbedtls_ssl_get_ciphersuite_name(const int ciphersuite_id);\n\n/**\n * \\brief               Return the ID of the ciphersuite associated with the\n *                      given name\n *\n * \\param ciphersuite_name SSL ciphersuite name\n *\n * \\return              the ID with the ciphersuite or 0 if not found\n */\nint mbedtls_ssl_get_ciphersuite_id(const char *ciphersuite_name);\n\n/**\n * \\brief          Initialize an SSL context\n *                 Just makes the context ready for mbedtls_ssl_setup() or\n *                 mbedtls_ssl_free()\n *\n * \\param ssl      SSL context\n */\nvoid mbedtls_ssl_init(mbedtls_ssl_context *ssl);\n\n/**\n * \\brief          Set up an SSL context for use\n *\n * \\note           No copy of the configuration context is made, it can be\n *                 shared by many mbedtls_ssl_context structures.\n *\n * \\warning        The conf structure will be accessed during the session.\n *                 It must not be modified or freed as long as the session\n *                 is active.\n *\n * \\warning        This function must be called exactly once per context.\n *                 Calling mbedtls_ssl_setup again is not supported, even\n *                 if no session is active.\n *\n * \\warning        After setting up a client context, if certificate-based\n *                 authentication is enabled, you should call\n *                 mbedtls_ssl_set_hostname() to specifiy the expected\n *                 name of the server. Without this, in most scenarios,\n *                 the TLS connection is insecure. See\n *                 #MBEDTLS_ERR_SSL_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME\n *                 for more information.\n *\n * \\note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                 subsystem must have been initialized by calling\n *                 psa_crypto_init() before calling this function.\n *\n * \\param ssl      SSL context\n * \\param conf     SSL configuration to use\n *\n * \\return         0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED if\n *                 memory allocation failed\n */\nint mbedtls_ssl_setup(mbedtls_ssl_context *ssl,\n                      const mbedtls_ssl_config *conf);\n\n/**\n * \\brief          Reset an already initialized SSL context for re-use\n *                 while retaining application-set variables, function\n *                 pointers and data.\n *\n * \\param ssl      SSL context\n * \\return         0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED or\n                   MBEDTLS_ERR_SSL_HW_ACCEL_FAILED\n */\nint mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl);\n\n/**\n * \\brief          Set the current endpoint type\n *\n * \\param conf     SSL configuration\n * \\param endpoint must be MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER\n */\nvoid mbedtls_ssl_conf_endpoint(mbedtls_ssl_config *conf, int endpoint);\n\n/**\n * \\brief          Get the current endpoint type\n *\n * \\param conf     SSL configuration\n *\n * \\return         Endpoint type, either MBEDTLS_SSL_IS_CLIENT\n *                 or MBEDTLS_SSL_IS_SERVER\n */\nstatic inline int mbedtls_ssl_conf_get_endpoint(const mbedtls_ssl_config *conf)\n{\n    return conf->MBEDTLS_PRIVATE(endpoint);\n}\n\n/**\n * \\brief           Set the transport type (TLS or DTLS).\n *                  Default: TLS\n *\n * \\note            For DTLS, you must either provide a recv callback that\n *                  doesn't block, or one that handles timeouts, see\n *                  \\c mbedtls_ssl_set_bio(). You also need to provide timer\n *                  callbacks with \\c mbedtls_ssl_set_timer_cb().\n *\n * \\param conf      SSL configuration\n * \\param transport transport type:\n *                  MBEDTLS_SSL_TRANSPORT_STREAM for TLS,\n *                  MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS.\n */\nvoid mbedtls_ssl_conf_transport(mbedtls_ssl_config *conf, int transport);\n\n/**\n * \\brief          Set the certificate verification mode\n *                 Default: NONE on server, REQUIRED on client\n *\n * \\param conf     SSL configuration\n * \\param authmode can be:\n *\n *  MBEDTLS_SSL_VERIFY_NONE:      peer certificate is not checked\n *                        (default on server)\n *                        (insecure on client)\n *\n *  MBEDTLS_SSL_VERIFY_OPTIONAL:  peer certificate is checked, however the\n *                        handshake continues even if verification failed;\n *                        mbedtls_ssl_get_verify_result() can be called after the\n *                        handshake is complete.\n *\n *  MBEDTLS_SSL_VERIFY_REQUIRED:  peer *must* present a valid certificate,\n *                        handshake is aborted if verification failed.\n *                        (default on client)\n *\n * \\note On client, MBEDTLS_SSL_VERIFY_REQUIRED is the recommended mode.\n * With MBEDTLS_SSL_VERIFY_OPTIONAL, the user needs to call mbedtls_ssl_get_verify_result() at\n * the right time(s), which may not be obvious, while REQUIRED always perform\n * the verification as soon as possible. For example, REQUIRED was protecting\n * against the \"triple handshake\" attack even before it was found.\n */\nvoid mbedtls_ssl_conf_authmode(mbedtls_ssl_config *conf, int authmode);\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n/**\n * \\brief    Set the early data mode\n *           Default: disabled on server and client\n *\n * \\param conf   The SSL configuration to use.\n * \\param early_data_enabled can be:\n *\n *  MBEDTLS_SSL_EARLY_DATA_DISABLED:\n *  Early data functionality is disabled. This is the default on client and\n *  server.\n *\n *  MBEDTLS_SSL_EARLY_DATA_ENABLED:\n *  Early data functionality is enabled and may be negotiated in the handshake.\n *  Application using early data functionality needs to be aware that the\n *  security properties for early data (also refered to as 0-RTT data) are\n *  weaker than those for other kinds of TLS data. See the documentation of\n *  mbedtls_ssl_write_early_data() and mbedtls_ssl_read_early_data() for more\n *  information.\n *  When early data functionality is enabled on server and only in that case,\n *  the call to one of the APIs that trigger or resume an handshake sequence,\n *  namely mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(),\n *  mbedtls_ssl_read() or mbedtls_ssl_write() may return with the error code\n *  MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA indicating that some early data have\n *  been received. To read the early data, call mbedtls_ssl_read_early_data()\n *  before calling the original function again.\n */\nvoid mbedtls_ssl_conf_early_data(mbedtls_ssl_config *conf,\n                                 int early_data_enabled);\n\n#if defined(MBEDTLS_SSL_SRV_C)\n/**\n * \\brief Set the maximum amount of 0-RTT data in bytes\n *        Default:  #MBEDTLS_SSL_MAX_EARLY_DATA_SIZE\n *\n *        This function sets the value of the max_early_data_size\n *        field of the early data indication extension included in\n *        the NewSessionTicket messages that the server may send.\n *\n *        The value defines the maximum amount of 0-RTT data\n *        in bytes that a client will be allowed to send when using\n *        one of the tickets defined by the NewSessionTicket messages.\n *\n * \\note When resuming a session using a ticket, if the server receives more\n *       early data than allowed for the ticket, it terminates the connection.\n *       The maximum amount of 0-RTT data should thus be large enough\n *       to allow a minimum of early data to be exchanged.\n *\n * \\param[in] conf                  The SSL configuration to use.\n * \\param[in] max_early_data_size   The maximum amount of 0-RTT data.\n *\n * \\warning This interface DOES NOT influence/limit the amount of early data\n *          that can be received through previously created and issued tickets,\n *          which clients may have stored.\n */\nvoid mbedtls_ssl_conf_max_early_data_size(\n    mbedtls_ssl_config *conf, uint32_t max_early_data_size);\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n/**\n * \\brief          Set the verification callback (Optional).\n *\n *                 If set, the provided verify callback is called for each\n *                 certificate in the peer's CRT chain, including the trusted\n *                 root. For more information, please see the documentation of\n *                 \\c mbedtls_x509_crt_verify().\n *\n * \\note           For per context callbacks and contexts, please use\n *                 mbedtls_ssl_set_verify() instead.\n *\n * \\param conf     The SSL configuration to use.\n * \\param f_vrfy   The verification callback to use during CRT verification.\n * \\param p_vrfy   The opaque context to be passed to the callback.\n */\nvoid mbedtls_ssl_conf_verify(mbedtls_ssl_config *conf,\n                             int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),\n                             void *p_vrfy);\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n/**\n * \\brief          Set the random number generator callback\n *\n * \\note           The callback with its parameter must remain valid as\n *                 long as there is an SSL context that uses the\n *                 SSL configuration.\n *\n * \\param conf     SSL configuration\n * \\param f_rng    RNG function (mandatory)\n * \\param p_rng    RNG parameter\n */\nvoid mbedtls_ssl_conf_rng(mbedtls_ssl_config *conf,\n                          mbedtls_f_rng_t *f_rng,\n                          void *p_rng);\n\n/**\n * \\brief          Set the debug callback\n *\n *                 The callback has the following argument:\n *                 void *           opaque context for the callback\n *                 int              debug level\n *                 const char *     file name\n *                 int              line number\n *                 const char *     message\n *\n * \\param conf     SSL configuration\n * \\param f_dbg    debug function\n * \\param p_dbg    debug parameter\n */\nvoid mbedtls_ssl_conf_dbg(mbedtls_ssl_config *conf,\n                          void (*f_dbg)(void *, int, const char *, int, const char *),\n                          void  *p_dbg);\n\n/**\n * \\brief          Return the SSL configuration structure associated\n *                 with the given SSL context.\n *\n * \\note           The pointer returned by this function is guaranteed to\n *                 remain valid until the context is freed.\n *\n * \\param ssl      The SSL context to query.\n * \\return         Pointer to the SSL configuration associated with \\p ssl.\n */\nstatic inline const mbedtls_ssl_config *mbedtls_ssl_context_get_config(\n    const mbedtls_ssl_context *ssl)\n{\n    return ssl->MBEDTLS_PRIVATE(conf);\n}\n\n/**\n * \\brief          Set the underlying BIO callbacks for write, read and\n *                 read-with-timeout.\n *\n * \\param ssl      SSL context\n * \\param p_bio    parameter (context) shared by BIO callbacks\n * \\param f_send   write callback\n * \\param f_recv   read callback\n * \\param f_recv_timeout blocking read callback with timeout.\n *\n * \\note           One of f_recv or f_recv_timeout can be NULL, in which case\n *                 the other is used. If both are non-NULL, f_recv_timeout is\n *                 used and f_recv is ignored (as if it were NULL).\n *\n * \\note           The two most common use cases are:\n *                 - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL\n *                 - blocking I/O, f_recv == NULL, f_recv_timeout != NULL\n *\n * \\note           For DTLS, you need to provide either a non-NULL\n *                 f_recv_timeout callback, or a f_recv that doesn't block.\n *\n * \\note           See the documentations of \\c mbedtls_ssl_send_t,\n *                 \\c mbedtls_ssl_recv_t and \\c mbedtls_ssl_recv_timeout_t for\n *                 the conventions those callbacks must follow.\n *\n * \\note           On some platforms, net_sockets.c provides\n *                 \\c mbedtls_net_send(), \\c mbedtls_net_recv() and\n *                 \\c mbedtls_net_recv_timeout() that are suitable to be used\n *                 here.\n */\nvoid mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl,\n                         void *p_bio,\n                         mbedtls_ssl_send_t *f_send,\n                         mbedtls_ssl_recv_t *f_recv,\n                         mbedtls_ssl_recv_timeout_t *f_recv_timeout);\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n\n\n/**\n * \\brief             Configure the use of the Connection ID (CID)\n *                    extension in the next handshake.\n *\n *                    Reference: RFC 9146 (or draft-ietf-tls-dtls-connection-id-05\n *                    https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05\n *                    for legacy version)\n *\n *                    The DTLS CID extension allows the reliable association of\n *                    DTLS records to DTLS connections across changes in the\n *                    underlying transport (changed IP and Port metadata) by\n *                    adding explicit connection identifiers (CIDs) to the\n *                    headers of encrypted DTLS records. The desired CIDs are\n *                    configured by the application layer and are exchanged in\n *                    new `ClientHello` / `ServerHello` extensions during the\n *                    handshake, where each side indicates the CID it wants the\n *                    peer to use when writing encrypted messages. The CIDs are\n *                    put to use once records get encrypted: the stack discards\n *                    any incoming records that don't include the configured CID\n *                    in their header, and adds the peer's requested CID to the\n *                    headers of outgoing messages.\n *\n *                    This API enables or disables the use of the CID extension\n *                    in the next handshake and sets the value of the CID to\n *                    be used for incoming messages.\n *\n * \\param ssl         The SSL context to configure. This must be initialized.\n * \\param enable      This value determines whether the CID extension should\n *                    be used or not. Possible values are:\n *                    - MBEDTLS_SSL_CID_ENABLED to enable the use of the CID.\n *                    - MBEDTLS_SSL_CID_DISABLED (default) to disable the use\n *                      of the CID.\n * \\param own_cid     The address of the readable buffer holding the CID we want\n *                    the peer to use when sending encrypted messages to us.\n *                    This may be \\c NULL if \\p own_cid_len is \\c 0.\n *                    This parameter is unused if \\p enable is set to\n *                    MBEDTLS_SSL_CID_DISABLED.\n * \\param own_cid_len The length of \\p own_cid.\n *                    This parameter is unused if \\p enable is set to\n *                    MBEDTLS_SSL_CID_DISABLED.\n *\n * \\note              The value of \\p own_cid_len must match the value of the\n *                    \\c len parameter passed to mbedtls_ssl_conf_cid()\n *                    when configuring the ::mbedtls_ssl_config that \\p ssl\n *                    is bound to.\n *\n * \\note              This CID configuration applies to subsequent handshakes\n *                    performed on the SSL context \\p ssl, but does not trigger\n *                    one. You still have to call `mbedtls_ssl_handshake()`\n *                    (for the initial handshake) or `mbedtls_ssl_renegotiate()`\n *                    (for a renegotiation handshake) explicitly after a\n *                    successful call to this function to run the handshake.\n *\n * \\note              This call cannot guarantee that the use of the CID\n *                    will be successfully negotiated in the next handshake,\n *                    because the peer might not support it. Specifically:\n *                    - On the Client, enabling the use of the CID through\n *                      this call implies that the `ClientHello` in the next\n *                      handshake will include the CID extension, thereby\n *                      offering the use of the CID to the server. Only if\n *                      the `ServerHello` contains the CID extension, too,\n *                      the CID extension will actually be put to use.\n *                    - On the Server, enabling the use of the CID through\n *                      this call implies that the server will look for\n *                      the CID extension in a `ClientHello` from the client,\n *                      and, if present, reply with a CID extension in its\n *                      `ServerHello`.\n *\n * \\note              To check whether the use of the CID was negotiated\n *                    after the subsequent handshake has completed, please\n *                    use the API mbedtls_ssl_get_peer_cid().\n *\n * \\warning           If the use of the CID extension is enabled in this call\n *                    and the subsequent handshake negotiates its use, Mbed TLS\n *                    will silently drop every packet whose CID does not match\n *                    the CID configured in \\p own_cid. It is the responsibility\n *                    of the user to adapt the underlying transport to take care\n *                    of CID-based demultiplexing before handing datagrams to\n *                    Mbed TLS.\n *\n * \\return            \\c 0 on success. In this case, the CID configuration\n *                    applies to the next handshake.\n * \\return            A negative error code on failure.\n */\nint mbedtls_ssl_set_cid(mbedtls_ssl_context *ssl,\n                        int enable,\n                        unsigned char const *own_cid,\n                        size_t own_cid_len);\n\n/**\n * \\brief              Get information about our request for usage of the CID\n *                     extension in the current connection.\n *\n * \\param ssl          The SSL context to query.\n * \\param enabled      The address at which to store whether the CID extension\n *                     is requested to be used or not. If the CID is\n *                     requested, `*enabled` is set to\n *                     MBEDTLS_SSL_CID_ENABLED; otherwise, it is set to\n *                     MBEDTLS_SSL_CID_DISABLED.\n * \\param own_cid      The address of the buffer in which to store our own\n *                     CID (if the CID extension is requested). This may be\n *                     \\c NULL in case the value of our CID isn't needed. If\n *                     it is not \\c NULL, \\p own_cid_len must not be \\c NULL.\n * \\param own_cid_len  The address at which to store the size of our own CID\n *                     (if the CID extension is requested). This is also the\n *                     number of Bytes in \\p own_cid that have been written.\n *                     This may be \\c NULL in case the length of our own CID\n *                     isn't needed. If it is \\c NULL, \\p own_cid must be\n *                     \\c NULL, too.\n *\n *\\note                If we are requesting an empty CID this function sets\n *                     `*enabled` to #MBEDTLS_SSL_CID_DISABLED (the rationale\n *                     for this is that the resulting outcome is the\n *                     same as if the CID extensions wasn't requested).\n *\n * \\return            \\c 0 on success.\n * \\return            A negative error code on failure.\n */\nint mbedtls_ssl_get_own_cid(mbedtls_ssl_context *ssl,\n                            int *enabled,\n                            unsigned char own_cid[MBEDTLS_SSL_CID_IN_LEN_MAX],\n                            size_t *own_cid_len);\n\n/**\n * \\brief              Get information about the use of the CID extension\n *                     in the current connection.\n *\n * \\param ssl          The SSL context to query.\n * \\param enabled      The address at which to store whether the CID extension\n *                     is currently in use or not. If the CID is in use,\n *                     `*enabled` is set to MBEDTLS_SSL_CID_ENABLED;\n *                     otherwise, it is set to MBEDTLS_SSL_CID_DISABLED.\n * \\param peer_cid     The address of the buffer in which to store the CID\n *                     chosen by the peer (if the CID extension is used).\n *                     This may be \\c NULL in case the value of peer CID\n *                     isn't needed. If it is not \\c NULL, \\p peer_cid_len\n *                     must not be \\c NULL.\n * \\param peer_cid_len The address at which to store the size of the CID\n *                     chosen by the peer (if the CID extension is used).\n *                     This is also the number of Bytes in \\p peer_cid that\n *                     have been written.\n *                     This may be \\c NULL in case the length of the peer CID\n *                     isn't needed. If it is \\c NULL, \\p peer_cid must be\n *                     \\c NULL, too.\n *\n * \\note               This applies to the state of the CID negotiated in\n *                     the last complete handshake. If a handshake is in\n *                     progress, this function will attempt to complete\n *                     the handshake first.\n *\n * \\note               If CID extensions have been exchanged but both client\n *                     and server chose to use an empty CID, this function\n *                     sets `*enabled` to #MBEDTLS_SSL_CID_DISABLED\n *                     (the rationale for this is that the resulting\n *                     communication is the same as if the CID extensions\n *                     hadn't been used).\n *\n * \\return            \\c 0 on success.\n * \\return            A negative error code on failure.\n */\nint mbedtls_ssl_get_peer_cid(mbedtls_ssl_context *ssl,\n                             int *enabled,\n                             unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX],\n                             size_t *peer_cid_len);\n\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n/**\n * \\brief          Set the Maximum Transport Unit (MTU).\n *                 Special value: 0 means unset (no limit).\n *                 This represents the maximum size of a datagram payload\n *                 handled by the transport layer (usually UDP) as determined\n *                 by the network link and stack. In practice, this controls\n *                 the maximum size datagram the DTLS layer will pass to the\n *                 \\c f_send() callback set using \\c mbedtls_ssl_set_bio().\n *\n * \\note           The limit on datagram size is converted to a limit on\n *                 record payload by subtracting the current overhead of\n *                 encapsulation and encryption/authentication if any.\n *\n * \\note           This can be called at any point during the connection, for\n *                 example when a Path Maximum Transfer Unit (PMTU)\n *                 estimate becomes available from other sources,\n *                 such as lower (or higher) protocol layers.\n *\n * \\note           This setting only controls the size of the packets we send,\n *                 and does not restrict the size of the datagrams we're\n *                 willing to receive. Client-side, you can request the\n *                 server to use smaller records with \\c\n *                 mbedtls_ssl_conf_max_frag_len().\n *\n * \\note           If both a MTU and a maximum fragment length have been\n *                 configured (or negotiated with the peer), the resulting\n *                 lower limit on record payload (see first note) is used.\n *\n * \\note           This can only be used to decrease the maximum size\n *                 of datagrams (hence records, see first note) sent. It\n *                 cannot be used to increase the maximum size of records over\n *                 the limit set by #MBEDTLS_SSL_OUT_CONTENT_LEN.\n *\n * \\note           Values lower than the current record layer expansion will\n *                 result in an error when trying to send data.\n *\n * \\param ssl      SSL context\n * \\param mtu      Value of the path MTU in bytes\n */\nvoid mbedtls_ssl_set_mtu(mbedtls_ssl_context *ssl, uint16_t mtu);\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n/**\n * \\brief          Set a connection-specific verification callback (optional).\n *\n *                 If set, the provided verify callback is called for each\n *                 certificate in the peer's CRT chain, including the trusted\n *                 root. For more information, please see the documentation of\n *                 \\c mbedtls_x509_crt_verify().\n *\n * \\note           This call is analogous to mbedtls_ssl_conf_verify() but\n *                 binds the verification callback and context to an SSL context\n *                 as opposed to an SSL configuration.\n *                 If mbedtls_ssl_conf_verify() and mbedtls_ssl_set_verify()\n *                 are both used, mbedtls_ssl_set_verify() takes precedence.\n *\n * \\param ssl      The SSL context to use.\n * \\param f_vrfy   The verification callback to use during CRT verification.\n * \\param p_vrfy   The opaque context to be passed to the callback.\n */\nvoid mbedtls_ssl_set_verify(mbedtls_ssl_context *ssl,\n                            int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),\n                            void *p_vrfy);\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n/**\n * \\brief          Set the timeout period for mbedtls_ssl_read()\n *                 (Default: no timeout.)\n *\n * \\param conf     SSL configuration context\n * \\param timeout  Timeout value in milliseconds.\n *                 Use 0 for no timeout (default).\n *\n * \\note           With blocking I/O, this will only work if a non-NULL\n *                 \\c f_recv_timeout was set with \\c mbedtls_ssl_set_bio().\n *                 With non-blocking I/O, this will only work if timer\n *                 callbacks were set with \\c mbedtls_ssl_set_timer_cb().\n *\n * \\note           With non-blocking I/O, you may also skip this function\n *                 altogether and handle timeouts at the application layer.\n */\nvoid mbedtls_ssl_conf_read_timeout(mbedtls_ssl_config *conf, uint32_t timeout);\n\n/**\n * \\brief          Check whether a buffer contains a valid and authentic record\n *                 that has not been seen before. (DTLS only).\n *\n *                 This function does not change the user-visible state\n *                 of the SSL context. Its sole purpose is to provide\n *                 an indication of the legitimacy of an incoming record.\n *\n *                 This can be useful e.g. in distributed server environments\n *                 using the DTLS Connection ID feature, in which connections\n *                 might need to be passed between service instances on a change\n *                 of peer address, but where such disruptive operations should\n *                 only happen after the validity of incoming records has been\n *                 confirmed.\n *\n * \\param ssl      The SSL context to use.\n * \\param buf      The address of the buffer holding the record to be checked.\n *                 This must be a read/write buffer of length \\p buflen Bytes.\n * \\param buflen   The length of \\p buf in Bytes.\n *\n * \\note           This routine only checks whether the provided buffer begins\n *                 with a valid and authentic record that has not been seen\n *                 before, but does not check potential data following the\n *                 initial record. In particular, it is possible to pass DTLS\n *                 datagrams containing multiple records, in which case only\n *                 the first record is checked.\n *\n * \\note           This function modifies the input buffer \\p buf. If you need\n *                 to preserve the original record, you have to maintain a copy.\n *\n * \\return         \\c 0 if the record is valid and authentic and has not been\n *                 seen before.\n * \\return         MBEDTLS_ERR_SSL_INVALID_MAC if the check completed\n *                 successfully but the record was found to be not authentic.\n * \\return         MBEDTLS_ERR_SSL_INVALID_RECORD if the check completed\n *                 successfully but the record was found to be invalid for\n *                 a reason different from authenticity checking.\n * \\return         MBEDTLS_ERR_SSL_UNEXPECTED_RECORD if the check completed\n *                 successfully but the record was found to be unexpected\n *                 in the state of the SSL context, including replayed records.\n * \\return         Another negative error code on different kinds of failure.\n *                 In this case, the SSL context becomes unusable and needs\n *                 to be freed or reset before reuse.\n */\nint mbedtls_ssl_check_record(mbedtls_ssl_context const *ssl,\n                             unsigned char *buf,\n                             size_t buflen);\n\n/**\n * \\brief          Set the timer callbacks (Mandatory for DTLS.)\n *\n * \\param ssl      SSL context\n * \\param p_timer  parameter (context) shared by timer callbacks\n * \\param f_set_timer   set timer callback\n * \\param f_get_timer   get timer callback. Must return:\n *\n * \\note           See the documentation of \\c mbedtls_ssl_set_timer_t and\n *                 \\c mbedtls_ssl_get_timer_t for the conventions this pair of\n *                 callbacks must follow.\n *\n * \\note           On some platforms, timing.c provides\n *                 \\c mbedtls_timing_set_delay() and\n *                 \\c mbedtls_timing_get_delay() that are suitable for using\n *                 here, except if using an event-driven style.\n *\n * \\note           See also the \"DTLS tutorial\" article in our knowledge base.\n *                 https://mbed-tls.readthedocs.io/en/latest/kb/how-to/dtls-tutorial\n */\nvoid mbedtls_ssl_set_timer_cb(mbedtls_ssl_context *ssl,\n                              void *p_timer,\n                              mbedtls_ssl_set_timer_t *f_set_timer,\n                              mbedtls_ssl_get_timer_t *f_get_timer);\n\n#if defined(MBEDTLS_SSL_SRV_C)\n/**\n * \\brief           Set the certificate selection callback (server-side only).\n *\n *                  If set, the callback is always called for each handshake,\n *                  after `ClientHello` processing has finished.\n *\n * \\param conf      The SSL configuration to register the callback with.\n * \\param f_cert_cb The callback for selecting server certificate after\n *                  `ClientHello` processing has finished.\n */\nstatic inline void mbedtls_ssl_conf_cert_cb(mbedtls_ssl_config *conf,\n                                            mbedtls_ssl_hs_cb_t f_cert_cb)\n{\n    conf->MBEDTLS_PRIVATE(f_cert_cb) = f_cert_cb;\n}\n#endif /* MBEDTLS_SSL_SRV_C */\n\n/**\n * \\brief           Callback type: generate and write session ticket\n *\n * \\note            This describes what a callback implementation should do.\n *                  This callback should generate an encrypted and\n *                  authenticated ticket for the session and write it to the\n *                  output buffer. Here, ticket means the opaque ticket part\n *                  of the NewSessionTicket structure of RFC 5077.\n *\n * \\param p_ticket  Context for the callback\n * \\param session   SSL session to be written in the ticket\n * \\param start     Start of the output buffer\n * \\param end       End of the output buffer\n * \\param tlen      On exit, holds the length written\n * \\param lifetime  On exit, holds the lifetime of the ticket in seconds\n *\n * \\return          0 if successful, or\n *                  a specific MBEDTLS_ERR_XXX code.\n */\ntypedef int mbedtls_ssl_ticket_write_t(void *p_ticket,\n                                       const mbedtls_ssl_session *session,\n                                       unsigned char *start,\n                                       const unsigned char *end,\n                                       size_t *tlen,\n                                       uint32_t *lifetime);\n\n/**\n * \\brief           Callback type: parse and load session ticket\n *\n * \\note            This describes what a callback implementation should do.\n *                  This callback should parse a session ticket as generated\n *                  by the corresponding mbedtls_ssl_ticket_write_t function,\n *                  and, if the ticket is authentic and valid, load the\n *                  session.\n *\n * \\note            The implementation is allowed to modify the first len\n *                  bytes of the input buffer, eg to use it as a temporary\n *                  area for the decrypted ticket contents.\n *\n * \\param p_ticket  Context for the callback\n * \\param session   SSL session to be loaded\n * \\param buf       Start of the buffer containing the ticket\n * \\param len       Length of the ticket.\n *\n * \\return          0 if successful, or\n *                  MBEDTLS_ERR_SSL_INVALID_MAC if not authentic, or\n *                  MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED if expired, or\n *                  any other non-zero code for other failures.\n */\ntypedef int mbedtls_ssl_ticket_parse_t(void *p_ticket,\n                                       mbedtls_ssl_session *session,\n                                       unsigned char *buf,\n                                       size_t len);\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C)\n/**\n * \\brief           Configure SSL session ticket callbacks (server only).\n *                  (Default: none.)\n *\n * \\note            On server, session tickets are enabled by providing\n *                  non-NULL callbacks.\n *\n * \\note            On client, use \\c mbedtls_ssl_conf_session_tickets().\n *\n * \\param conf      SSL configuration context\n * \\param f_ticket_write    Callback for writing a ticket\n * \\param f_ticket_parse    Callback for parsing a ticket\n * \\param p_ticket          Context shared by the two callbacks\n */\nvoid mbedtls_ssl_conf_session_tickets_cb(mbedtls_ssl_config *conf,\n                                         mbedtls_ssl_ticket_write_t *f_ticket_write,\n                                         mbedtls_ssl_ticket_parse_t *f_ticket_parse,\n                                         void *p_ticket);\n\n#if defined(MBEDTLS_HAVE_TIME)\n/**\n * \\brief Get the creation time of a session ticket.\n *\n * \\note See the documentation of \\c ticket_creation_time for information about\n *       the intended usage of this function.\n *\n * \\param session  SSL session\n * \\param ticket_creation_time  On exit, holds the ticket creation time in\n *                              milliseconds.\n *\n * \\return         0 on success,\n *                 MBEDTLS_ERR_SSL_BAD_INPUT_DATA if an input is not valid.\n */\nstatic inline int mbedtls_ssl_session_get_ticket_creation_time(\n    mbedtls_ssl_session *session, mbedtls_ms_time_t *ticket_creation_time)\n{\n    if (session == NULL || ticket_creation_time == NULL ||\n        session->MBEDTLS_PRIVATE(endpoint) != MBEDTLS_SSL_IS_SERVER) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    *ticket_creation_time = session->MBEDTLS_PRIVATE(ticket_creation_time);\n\n    return 0;\n}\n#endif /* MBEDTLS_HAVE_TIME */\n#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */\n\n/**\n * \\brief          Get the session-id buffer.\n *\n * \\param session  SSL session.\n *\n * \\return         The address of the session-id buffer.\n */\nstatic inline unsigned const char (*mbedtls_ssl_session_get_id(const mbedtls_ssl_session *\n                                                               session))[32]\n{\n    return &session->MBEDTLS_PRIVATE(id);\n}\n\n/**\n * \\brief          Get the size of the session-id.\n *\n * \\param session  SSL session.\n *\n * \\return         size_t size of session-id buffer.\n */\nstatic inline size_t mbedtls_ssl_session_get_id_len(const mbedtls_ssl_session *session)\n{\n    return session->MBEDTLS_PRIVATE(id_len);\n}\n\n/**\n * \\brief          Get the ciphersuite-id.\n *\n * \\param session  SSL session.\n *\n * \\return         int represetation for ciphersuite.\n */\nstatic inline int mbedtls_ssl_session_get_ciphersuite_id(const mbedtls_ssl_session *session)\n{\n    return session->MBEDTLS_PRIVATE(ciphersuite);\n}\n\n/**\n * \\brief   Configure a key export callback.\n *          (Default: none.)\n *\n *          This API can be used for two purposes:\n *          - Debugging: Use this API to e.g. generate an NSSKeylog\n *            file and use it to inspect encrypted traffic in tools\n *            such as Wireshark.\n *          - Application-specific export: Use this API to implement\n *            key exporters, e.g. for EAP-TLS or DTLS-SRTP.\n *\n *\n * \\param ssl            The SSL context to which the export\n *                       callback should be attached.\n * \\param f_export_keys  The callback for the key export.\n * \\param p_export_keys  The opaque context pointer to be passed to the\n *                       callback \\p f_export_keys.\n */\nvoid mbedtls_ssl_set_export_keys_cb(mbedtls_ssl_context *ssl,\n                                    mbedtls_ssl_export_keys_t *f_export_keys,\n                                    void *p_export_keys);\n\n/** \\brief Set the user data in an SSL configuration to a pointer.\n *\n * You can retrieve this value later with mbedtls_ssl_conf_get_user_data_p().\n *\n * \\note The library stores \\c p without accessing it. It is the responsibility\n *       of the caller to ensure that the pointer remains valid.\n *\n * \\param conf           The SSL configuration context to modify.\n * \\param p              The new value of the user data.\n */\nstatic inline void mbedtls_ssl_conf_set_user_data_p(\n    mbedtls_ssl_config *conf,\n    void *p)\n{\n    conf->MBEDTLS_PRIVATE(user_data).p = p;\n}\n\n/** \\brief Set the user data in an SSL configuration to an integer.\n *\n * You can retrieve this value later with mbedtls_ssl_conf_get_user_data_n().\n *\n * \\param conf           The SSL configuration context to modify.\n * \\param n              The new value of the user data.\n */\nstatic inline void mbedtls_ssl_conf_set_user_data_n(\n    mbedtls_ssl_config *conf,\n    uintptr_t n)\n{\n    conf->MBEDTLS_PRIVATE(user_data).n = n;\n}\n\n/** \\brief Retrieve the user data in an SSL configuration as a pointer.\n *\n * This is the value last set with mbedtls_ssl_conf_set_user_data_p(), or\n * \\c NULL if mbedtls_ssl_conf_set_user_data_p() has not previously been\n * called. The value is undefined if mbedtls_ssl_conf_set_user_data_n() has\n * been called without a subsequent call to mbedtls_ssl_conf_set_user_data_p().\n *\n * \\param conf           The SSL configuration context to modify.\n * \\return               The current value of the user data.\n */\nstatic inline void *mbedtls_ssl_conf_get_user_data_p(\n    mbedtls_ssl_config *conf)\n{\n    return conf->MBEDTLS_PRIVATE(user_data).p;\n}\n\n/** \\brief Retrieve the user data in an SSL configuration as an integer.\n *\n * This is the value last set with mbedtls_ssl_conf_set_user_data_n(), or\n * \\c 0 if mbedtls_ssl_conf_set_user_data_n() has not previously been\n * called. The value is undefined if mbedtls_ssl_conf_set_user_data_p() has\n * been called without a subsequent call to mbedtls_ssl_conf_set_user_data_n().\n *\n * \\param conf           The SSL configuration context to modify.\n * \\return               The current value of the user data.\n */\nstatic inline uintptr_t mbedtls_ssl_conf_get_user_data_n(\n    mbedtls_ssl_config *conf)\n{\n    return conf->MBEDTLS_PRIVATE(user_data).n;\n}\n\n/** \\brief Set the user data in an SSL context to a pointer.\n *\n * You can retrieve this value later with mbedtls_ssl_get_user_data_p().\n *\n * \\note The library stores \\c p without accessing it. It is the responsibility\n *       of the caller to ensure that the pointer remains valid.\n *\n * \\param ssl            The SSL context to modify.\n * \\param p              The new value of the user data.\n */\nstatic inline void mbedtls_ssl_set_user_data_p(\n    mbedtls_ssl_context *ssl,\n    void *p)\n{\n    ssl->MBEDTLS_PRIVATE(user_data).p = p;\n}\n\n/** \\brief Set the user data in an SSL context to an integer.\n *\n * You can retrieve this value later with mbedtls_ssl_get_user_data_n().\n *\n * \\param ssl            The SSL context to modify.\n * \\param n              The new value of the user data.\n */\nstatic inline void mbedtls_ssl_set_user_data_n(\n    mbedtls_ssl_context *ssl,\n    uintptr_t n)\n{\n    ssl->MBEDTLS_PRIVATE(user_data).n = n;\n}\n\n/** \\brief Retrieve the user data in an SSL context as a pointer.\n *\n * This is the value last set with mbedtls_ssl_set_user_data_p(), or\n * \\c NULL if mbedtls_ssl_set_user_data_p() has not previously been\n * called. The value is undefined if mbedtls_ssl_set_user_data_n() has\n * been called without a subsequent call to mbedtls_ssl_set_user_data_p().\n *\n * \\param ssl            The SSL context to modify.\n * \\return               The current value of the user data.\n */\nstatic inline void *mbedtls_ssl_get_user_data_p(\n    mbedtls_ssl_context *ssl)\n{\n    return ssl->MBEDTLS_PRIVATE(user_data).p;\n}\n\n/** \\brief Retrieve the user data in an SSL context as an integer.\n *\n * This is the value last set with mbedtls_ssl_set_user_data_n(), or\n * \\c 0 if mbedtls_ssl_set_user_data_n() has not previously been\n * called. The value is undefined if mbedtls_ssl_set_user_data_p() has\n * been called without a subsequent call to mbedtls_ssl_set_user_data_n().\n *\n * \\param ssl            The SSL context to modify.\n * \\return               The current value of the user data.\n */\nstatic inline uintptr_t mbedtls_ssl_get_user_data_n(\n    mbedtls_ssl_context *ssl)\n{\n    return ssl->MBEDTLS_PRIVATE(user_data).n;\n}\n\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)\n/**\n * \\brief           Configure asynchronous private key operation callbacks.\n *\n * \\param conf              SSL configuration context\n * \\param f_async_sign      Callback to start a signature operation. See\n *                          the description of ::mbedtls_ssl_async_sign_t\n *                          for more information. This may be \\c NULL if the\n *                          external processor does not support any signature\n *                          operation; in this case the private key object\n *                          associated with the certificate will be used.\n * \\param f_async_decrypt   Callback to start a decryption operation. See\n *                          the description of ::mbedtls_ssl_async_decrypt_t\n *                          for more information. This may be \\c NULL if the\n *                          external processor does not support any decryption\n *                          operation; in this case the private key object\n *                          associated with the certificate will be used.\n * \\param f_async_resume    Callback to resume an asynchronous operation. See\n *                          the description of ::mbedtls_ssl_async_resume_t\n *                          for more information. This may not be \\c NULL unless\n *                          \\p f_async_sign and \\p f_async_decrypt are both\n *                          \\c NULL.\n * \\param f_async_cancel    Callback to cancel an asynchronous operation. See\n *                          the description of ::mbedtls_ssl_async_cancel_t\n *                          for more information. This may be \\c NULL if\n *                          no cleanup is needed.\n * \\param config_data       A pointer to configuration data which can be\n *                          retrieved with\n *                          mbedtls_ssl_conf_get_async_config_data(). The\n *                          library stores this value without dereferencing it.\n */\nvoid mbedtls_ssl_conf_async_private_cb(mbedtls_ssl_config *conf,\n                                       mbedtls_ssl_async_sign_t *f_async_sign,\n                                       mbedtls_ssl_async_decrypt_t *f_async_decrypt,\n                                       mbedtls_ssl_async_resume_t *f_async_resume,\n                                       mbedtls_ssl_async_cancel_t *f_async_cancel,\n                                       void *config_data);\n\n/**\n * \\brief           Retrieve the configuration data set by\n *                  mbedtls_ssl_conf_async_private_cb().\n *\n * \\param conf      SSL configuration context\n * \\return          The configuration data set by\n *                  mbedtls_ssl_conf_async_private_cb().\n */\nvoid *mbedtls_ssl_conf_get_async_config_data(const mbedtls_ssl_config *conf);\n\n/**\n * \\brief           Retrieve the asynchronous operation user context.\n *\n * \\note            This function may only be called while a handshake\n *                  is in progress.\n *\n * \\param ssl       The SSL context to access.\n *\n * \\return          The asynchronous operation user context that was last\n *                  set during the current handshake. If\n *                  mbedtls_ssl_set_async_operation_data() has not yet been\n *                  called during the current handshake, this function returns\n *                  \\c NULL.\n */\nvoid *mbedtls_ssl_get_async_operation_data(const mbedtls_ssl_context *ssl);\n\n/**\n * \\brief           Retrieve the asynchronous operation user context.\n *\n * \\note            This function may only be called while a handshake\n *                  is in progress.\n *\n * \\param ssl       The SSL context to access.\n * \\param ctx       The new value of the asynchronous operation user context.\n *                  Call mbedtls_ssl_get_async_operation_data() later during the\n *                  same handshake to retrieve this value.\n */\nvoid mbedtls_ssl_set_async_operation_data(mbedtls_ssl_context *ssl,\n                                          void *ctx);\n#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */\n\n/**\n * \\brief          Callback type: generate a cookie\n *\n * \\param ctx      Context for the callback\n * \\param p        Buffer to write to,\n *                 must be updated to point right after the cookie\n * \\param end      Pointer to one past the end of the output buffer\n * \\param info     Client ID info that was passed to\n *                 \\c mbedtls_ssl_set_client_transport_id()\n * \\param ilen     Length of info in bytes\n *\n * \\return         The callback must return 0 on success,\n *                 or a negative error code.\n */\ntypedef int mbedtls_ssl_cookie_write_t(void *ctx,\n                                       unsigned char **p, unsigned char *end,\n                                       const unsigned char *info, size_t ilen);\n\n/**\n * \\brief          Callback type: verify a cookie\n *\n * \\param ctx      Context for the callback\n * \\param cookie   Cookie to verify\n * \\param clen     Length of cookie\n * \\param info     Client ID info that was passed to\n *                 \\c mbedtls_ssl_set_client_transport_id()\n * \\param ilen     Length of info in bytes\n *\n * \\return         The callback must return 0 if cookie is valid,\n *                 or a negative error code.\n */\ntypedef int mbedtls_ssl_cookie_check_t(void *ctx,\n                                       const unsigned char *cookie, size_t clen,\n                                       const unsigned char *info, size_t ilen);\n\n#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)\n/**\n * \\brief           Register callbacks for DTLS cookies\n *                  (Server only. DTLS only.)\n *\n *                  Default: dummy callbacks that fail, in order to force you to\n *                  register working callbacks (and initialize their context).\n *\n *                  To disable HelloVerifyRequest, register NULL callbacks.\n *\n * \\warning         Disabling hello verification allows your server to be used\n *                  for amplification in DoS attacks against other hosts.\n *                  Only disable if you known this can't happen in your\n *                  particular environment.\n *\n * \\note            See comments on \\c mbedtls_ssl_handshake() about handling\n *                  the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected\n *                  on the first handshake attempt when this is enabled.\n *\n * \\note            This is also necessary to handle client reconnection from\n *                  the same port as described in RFC 6347 section 4.2.8 (only\n *                  the variant with cookies is supported currently). See\n *                  comments on \\c mbedtls_ssl_read() for details.\n *\n * \\param conf              SSL configuration\n * \\param f_cookie_write    Cookie write callback\n * \\param f_cookie_check    Cookie check callback\n * \\param p_cookie          Context for both callbacks\n */\nvoid mbedtls_ssl_conf_dtls_cookies(mbedtls_ssl_config *conf,\n                                   mbedtls_ssl_cookie_write_t *f_cookie_write,\n                                   mbedtls_ssl_cookie_check_t *f_cookie_check,\n                                   void *p_cookie);\n\n/**\n * \\brief          Set client's transport-level identification info.\n *                 (Server only. DTLS only.)\n *\n *                 This is usually the IP address (and port), but could be\n *                 anything identify the client depending on the underlying\n *                 network stack. Used for HelloVerifyRequest with DTLS.\n *                 This is *not* used to route the actual packets.\n *\n * \\param ssl      SSL context\n * \\param info     Transport-level info identifying the client (eg IP + port)\n * \\param ilen     Length of info in bytes\n *\n * \\note           An internal copy is made, so the info buffer can be reused.\n *\n * \\return         0 on success,\n *                 MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used on client,\n *                 MBEDTLS_ERR_SSL_ALLOC_FAILED if out of memory.\n */\nint mbedtls_ssl_set_client_transport_id(mbedtls_ssl_context *ssl,\n                                        const unsigned char *info,\n                                        size_t ilen);\n\n#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\n/**\n * \\brief          Enable or disable anti-replay protection for DTLS.\n *                 (DTLS only, no effect on TLS.)\n *                 Default: enabled.\n *\n * \\param conf     SSL configuration\n * \\param mode     MBEDTLS_SSL_ANTI_REPLAY_ENABLED or MBEDTLS_SSL_ANTI_REPLAY_DISABLED.\n *\n * \\warning        Disabling this is a security risk unless the application\n *                 protocol handles duplicated packets in a safe way. You\n *                 should not disable this without careful consideration.\n *                 However, if your application already detects duplicated\n *                 packets and needs information about them to adjust its\n *                 transmission strategy, then you'll want to disable this.\n */\nvoid mbedtls_ssl_conf_dtls_anti_replay(mbedtls_ssl_config *conf, char mode);\n#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */\n\n/**\n * \\brief          Set a limit on the number of records with a bad MAC\n *                 before terminating the connection.\n *                 (DTLS only, no effect on TLS.)\n *                 Default: 0 (disabled).\n *\n * \\param conf     SSL configuration\n * \\param limit    Limit, or 0 to disable.\n *\n * \\note           If the limit is N, then the connection is terminated when\n *                 the Nth non-authentic record is seen.\n *\n * \\note           Records with an invalid header are not counted, only the\n *                 ones going through the authentication-decryption phase.\n *\n * \\note           This is a security trade-off related to the fact that it's\n *                 often relatively easy for an active attacker to inject UDP\n *                 datagrams. On one hand, setting a low limit here makes it\n *                 easier for such an attacker to forcibly terminated a\n *                 connection. On the other hand, a high limit or no limit\n *                 might make us waste resources checking authentication on\n *                 many bogus packets.\n */\nvoid mbedtls_ssl_conf_dtls_badmac_limit(mbedtls_ssl_config *conf, unsigned limit);\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n\n/**\n * \\brief          Allow or disallow packing of multiple handshake records\n *                 within a single datagram.\n *\n * \\param ssl           The SSL context to configure.\n * \\param allow_packing This determines whether datagram packing may\n *                      be used or not. A value of \\c 0 means that every\n *                      record will be sent in a separate datagram; a\n *                      value of \\c 1 means that, if space permits,\n *                      multiple handshake messages (including CCS) belonging to\n *                      a single flight may be packed within a single datagram.\n *\n * \\note           This is enabled by default and should only be disabled\n *                 for test purposes, or if datagram packing causes\n *                 interoperability issues with peers that don't support it.\n *\n * \\note           Allowing datagram packing reduces the network load since\n *                 there's less overhead if multiple messages share the same\n *                 datagram. Also, it increases the handshake efficiency\n *                 since messages belonging to a single datagram will not\n *                 be reordered in transit, and so future message buffering\n *                 or flight retransmission (if no buffering is used) as\n *                 means to deal with reordering are needed less frequently.\n *\n * \\note           Application records are not affected by this option and\n *                 are currently always sent in separate datagrams.\n *\n */\nvoid mbedtls_ssl_set_datagram_packing(mbedtls_ssl_context *ssl,\n                                      unsigned allow_packing);\n\n/**\n * \\brief          Set retransmit timeout values for the DTLS handshake.\n *                 (DTLS only, no effect on TLS.)\n *\n * \\param conf     SSL configuration\n * \\param min      Initial timeout value in milliseconds.\n *                 Default: 1000 (1 second).\n * \\param max      Maximum timeout value in milliseconds.\n *                 Default: 60000 (60 seconds).\n *\n * \\note           Default values are from RFC 6347 section 4.2.4.1.\n *\n * \\note           The 'min' value should typically be slightly above the\n *                 expected round-trip time to your peer, plus whatever time\n *                 it takes for the peer to process the message. For example,\n *                 if your RTT is about 600ms and you peer needs up to 1s to\n *                 do the cryptographic operations in the handshake, then you\n *                 should set 'min' slightly above 1600. Lower values of 'min'\n *                 might cause spurious resends which waste network resources,\n *                 while larger value of 'min' will increase overall latency\n *                 on unreliable network links.\n *\n * \\note           The more unreliable your network connection is, the larger\n *                 your max / min ratio needs to be in order to achieve\n *                 reliable handshakes.\n *\n * \\note           Messages are retransmitted up to log2(ceil(max/min)) times.\n *                 For example, if min = 1s and max = 5s, the retransmit plan\n *                 goes: send ... 1s -> resend ... 2s -> resend ... 4s ->\n *                 resend ... 5s -> give up and return a timeout error.\n */\nvoid mbedtls_ssl_conf_handshake_timeout(mbedtls_ssl_config *conf, uint32_t min, uint32_t max);\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n#if defined(MBEDTLS_SSL_SRV_C)\n/**\n * \\brief          Set the session cache callbacks (server-side only)\n *                 If not set, no session resuming is done (except if session\n *                 tickets are enabled too).\n *\n *                 The session cache has the responsibility to check for stale\n *                 entries based on timeout. See RFC 5246 for recommendations.\n *\n *                 Warning: session.peer_cert is cleared by the SSL/TLS layer on\n *                 connection shutdown, so do not cache the pointer! Either set\n *                 it to NULL or make a full copy of the certificate.\n *\n *                 The get callback is called once during the initial handshake\n *                 to enable session resuming. The get function has the\n *                 following parameters: (void *parameter, mbedtls_ssl_session *session)\n *                 If a valid entry is found, it should fill the master of\n *                 the session object with the cached values and return 0,\n *                 return 1 otherwise. Optionally peer_cert can be set as well\n *                 if it is properly present in cache entry.\n *\n *                 The set callback is called once during the initial handshake\n *                 to enable session resuming after the entire handshake has\n *                 been finished. The set function has the following parameters:\n *                 (void *parameter, const mbedtls_ssl_session *session). The function\n *                 should create a cache entry for future retrieval based on\n *                 the data in the session structure and should keep in mind\n *                 that the mbedtls_ssl_session object presented (and all its referenced\n *                 data) is cleared by the SSL/TLS layer when the connection is\n *                 terminated. It is recommended to add metadata to determine if\n *                 an entry is still valid in the future. Return 0 if\n *                 successfully cached, return 1 otherwise.\n *\n * \\param conf           SSL configuration\n * \\param p_cache        parameter (context) for both callbacks\n * \\param f_get_cache    session get callback\n * \\param f_set_cache    session set callback\n */\nvoid mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf,\n                                    void *p_cache,\n                                    mbedtls_ssl_cache_get_t *f_get_cache,\n                                    mbedtls_ssl_cache_set_t *f_set_cache);\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_SSL_CLI_C)\n/**\n * \\brief          Load a session for session resumption.\n *\n *                 Sessions loaded through this call will be considered\n *                 for session resumption in the next handshake.\n *\n * \\note           Even if this call succeeds, it is not guaranteed that\n *                 the next handshake will indeed be shortened through the\n *                 use of session resumption: The server is always free\n *                 to reject any attempt for resumption and fall back to\n *                 a full handshake.\n *\n * \\note           This function can handle a variety of mechanisms for session\n *                 resumption: For TLS 1.2, both session ID-based resumption\n *                 and ticket-based resumption will be considered. For TLS 1.3,\n *                 sessions equate to tickets, and loading one session by\n *                 calling this function will lead to its corresponding ticket\n *                 being advertised as resumption PSK by the client. This\n *                 depends on session tickets being enabled (see\n *                 #MBEDTLS_SSL_SESSION_TICKETS configuration option) though.\n *                 If session tickets are disabled, a call to this function\n *                 with a TLS 1.3 session, will not have any effect on the next\n *                 handshake for the SSL context \\p ssl.\n *\n * \\param ssl      The SSL context representing the connection which should\n *                 be attempted to be setup using session resumption. This\n *                 must be initialized via mbedtls_ssl_init() and bound to\n *                 an SSL configuration via mbedtls_ssl_setup(), but\n *                 the handshake must not yet have been started.\n * \\param session  The session to be considered for session resumption.\n *                 This must be a session previously exported via\n *                 mbedtls_ssl_get_session(), and potentially serialized and\n *                 deserialized through mbedtls_ssl_session_save() and\n *                 mbedtls_ssl_session_load() in the meantime.\n *\n * \\return         \\c 0 if successful.\n * \\return         \\c MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if the session\n *                 could not be loaded because one session has already been\n *                 loaded. This error is non-fatal, and has no observable\n *                 effect on the SSL context or the session that was attempted\n *                 to be loaded.\n * \\return         Another negative error code on other kinds of failure.\n *\n * \\sa             mbedtls_ssl_get_session()\n * \\sa             mbedtls_ssl_session_load()\n */\nint mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session);\n#endif /* MBEDTLS_SSL_CLI_C */\n\n/**\n * \\brief          Load serialized session data into a session structure.\n *                 On client, this can be used for loading saved sessions\n *                 before resuming them with mbedtls_ssl_set_session().\n *                 On server, this can be used for alternative implementations\n *                 of session cache or session tickets.\n *\n * \\warning        If a peer certificate chain is associated with the session,\n *                 the serialized state will only contain the peer's\n *                 end-entity certificate and the result of the chain\n *                 verification (unless verification was disabled), but not\n *                 the rest of the chain.\n *\n * \\see            mbedtls_ssl_session_save()\n * \\see            mbedtls_ssl_set_session()\n *\n * \\param session  The session structure to be populated. It must have been\n *                 initialised with mbedtls_ssl_session_init() but not\n *                 populated yet.\n * \\param buf      The buffer holding the serialized session data. It must be a\n *                 readable buffer of at least \\p len bytes.\n * \\param len      The size of the serialized data in bytes.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed.\n * \\return         #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid.\n * \\return         #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data\n *                 was generated in a different version or configuration of\n *                 Mbed TLS.\n * \\return         Another negative value for other kinds of errors (for\n *                 example, unsupported features in the embedded certificate).\n */\nint mbedtls_ssl_session_load(mbedtls_ssl_session *session,\n                             const unsigned char *buf,\n                             size_t len);\n\n/**\n * \\brief          Save session structure as serialized data in a buffer.\n *                 On client, this can be used for saving session data,\n *                 potentially in non-volatile storage, for resuming later.\n *                 On server, this can be used for alternative implementations\n *                 of session cache or session tickets.\n *\n * \\see            mbedtls_ssl_session_load()\n *\n * \\param session  The session structure to be saved.\n * \\param buf      The buffer to write the serialized data to. It must be a\n *                 writeable buffer of at least \\p buf_len bytes, or may be \\c\n *                 NULL if \\p buf_len is \\c 0.\n * \\param buf_len  The number of bytes available for writing in \\p buf.\n * \\param olen     The size in bytes of the data that has been or would have\n *                 been written. It must point to a valid \\c size_t.\n *\n * \\note           \\p olen is updated to the correct value regardless of\n *                 whether \\p buf_len was large enough. This makes it possible\n *                 to determine the necessary size by calling this function\n *                 with \\p buf set to \\c NULL and \\p buf_len to \\c 0.\n *\n * \\note           For TLS 1.3 sessions, this feature is supported only if the\n *                 MBEDTLS_SSL_SESSION_TICKETS configuration option is enabled,\n *                 as in TLS 1.3 session resumption is possible only with\n *                 tickets.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \\p buf is too small.\n * \\return         #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if the\n *                 MBEDTLS_SSL_SESSION_TICKETS configuration option is disabled\n *                 and the session is a TLS 1.3 session.\n */\nint mbedtls_ssl_session_save(const mbedtls_ssl_session *session,\n                             unsigned char *buf,\n                             size_t buf_len,\n                             size_t *olen);\n\n/**\n * \\brief               Set the list of allowed ciphersuites and the preference\n *                      order. First in the list has the highest preference.\n *\n *                      For TLS 1.2, the notion of ciphersuite determines both\n *                      the key exchange mechanism and the suite of symmetric\n *                      algorithms to be used during and after the handshake.\n *\n *                      For TLS 1.3 (in development), the notion of ciphersuite\n *                      only determines the suite of symmetric algorithms to be\n *                      used during and after the handshake, while key exchange\n *                      mechanisms are configured separately.\n *\n *                      In Mbed TLS, ciphersuites for both TLS 1.2 and TLS 1.3\n *                      are configured via this function. For users of TLS 1.3,\n *                      there will be separate API for the configuration of key\n *                      exchange mechanisms.\n *\n *                      The list of ciphersuites passed to this function may\n *                      contain a mixture of TLS 1.2 and TLS 1.3 ciphersuite\n *                      identifiers. This is useful if negotiation of TLS 1.3\n *                      should be attempted, but a fallback to TLS 1.2 would\n *                      be tolerated.\n *\n * \\note                By default, the server chooses its preferred\n *                      ciphersuite among those that the client supports. If\n *                      mbedtls_ssl_conf_preference_order() is called to prefer\n *                      the client's preferences, the server instead chooses\n *                      the client's preferred ciphersuite among those that\n *                      the server supports.\n *\n * \\warning             The ciphersuites array \\p ciphersuites is not copied.\n *                      It must remain valid for the lifetime of the SSL\n *                      configuration \\p conf.\n *\n * \\param conf          The SSL configuration to modify.\n * \\param ciphersuites  A 0-terminated list of IANA identifiers of supported\n *                      ciphersuites, accessible through \\c MBEDTLS_TLS_XXX\n *                      and \\c MBEDTLS_TLS1_3_XXX macros defined in\n *                      ssl_ciphersuites.h.\n */\nvoid mbedtls_ssl_conf_ciphersuites(mbedtls_ssl_config *conf,\n                                   const int *ciphersuites);\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n/**\n * \\brief Set the supported key exchange modes for TLS 1.3 connections.\n *\n *        In contrast to TLS 1.2, the ciphersuite concept in TLS 1.3 does not\n *        include the choice of key exchange mechanism. It is therefore not\n *        covered by the API mbedtls_ssl_conf_ciphersuites(). See the\n *        documentation of mbedtls_ssl_conf_ciphersuites() for more\n *        information on the ciphersuite concept in TLS 1.2 and TLS 1.3.\n *\n *        The present function is specific to TLS 1.3 and allows users to\n *        configure the set of supported key exchange mechanisms in TLS 1.3.\n *\n * \\param conf       The SSL configuration the change should apply to.\n * \\param kex_modes  A bitwise combination of one or more of the following:\n *                   - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK\n *                     This flag enables pure-PSK key exchanges.\n *                   - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL\n *                     This flag enables combined PSK-ephemeral key exchanges.\n *                   - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL\n *                     This flag enables pure-ephemeral key exchanges.\n *                   For convenience, the following pre-defined macros are\n *                   available for combinations of the above:\n *                   - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL\n *                     Includes all of pure-PSK, PSK-ephemeral and pure-ephemeral.\n *                   - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL\n *                     Includes both pure-PSK and combined PSK-ephemeral\n *                     key exchanges, but excludes pure-ephemeral key exchanges.\n *                   - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL\n *                     Includes both pure-ephemeral and combined PSK-ephemeral\n *                     key exchanges.\n *\n * \\note  If a PSK-based key exchange mode shall be supported, applications\n *        must also use the APIs mbedtls_ssl_conf_psk() or\n *        mbedtls_ssl_conf_psk_cb() or mbedtls_ssl_conf_psk_opaque()\n *        to configure the PSKs to be used.\n *\n * \\note  If a pure-ephemeral key exchange mode shall be supported,\n *        server-side applications must also provide a certificate via\n *        mbedtls_ssl_conf_own_cert().\n *\n */\n\nvoid mbedtls_ssl_conf_tls13_key_exchange_modes(mbedtls_ssl_config *conf,\n                                               const int kex_modes);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n#define MBEDTLS_SSL_UNEXPECTED_CID_IGNORE 0\n#define MBEDTLS_SSL_UNEXPECTED_CID_FAIL   1\n/**\n * \\brief               Specify the length of Connection IDs for incoming\n *                      encrypted DTLS records, as well as the behaviour\n *                      on unexpected CIDs.\n *\n *                      By default, the CID length is set to \\c 0,\n *                      and unexpected CIDs are silently ignored.\n *\n * \\param conf          The SSL configuration to modify.\n * \\param len           The length in Bytes of the CID fields in encrypted\n *                      DTLS records using the CID mechanism. This must\n *                      not be larger than #MBEDTLS_SSL_CID_OUT_LEN_MAX.\n * \\param ignore_other_cids This determines the stack's behaviour when\n *                          receiving a record with an unexpected CID.\n *                          Possible values are:\n *                          - #MBEDTLS_SSL_UNEXPECTED_CID_IGNORE\n *                            In this case, the record is silently ignored.\n *                          - #MBEDTLS_SSL_UNEXPECTED_CID_FAIL\n *                            In this case, the stack fails with the specific\n *                            error code #MBEDTLS_ERR_SSL_UNEXPECTED_CID.\n *\n * \\note                The CID specification allows implementations to either\n *                      use a common length for all incoming connection IDs or\n *                      allow variable-length incoming IDs. Mbed TLS currently\n *                      requires a common length for all connections sharing the\n *                      same SSL configuration; this allows simpler parsing of\n *                      record headers.\n *\n * \\return              \\c 0 on success.\n * \\return              #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if \\p len\n *                      is too large.\n */\nint mbedtls_ssl_conf_cid(mbedtls_ssl_config *conf, size_t len,\n                         int ignore_other_cids);\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n/**\n * \\brief          Set the X.509 security profile used for verification\n *\n * \\note           The restrictions are enforced for all certificates in the\n *                 chain. However, signatures in the handshake are not covered\n *                 by this setting but by \\b mbedtls_ssl_conf_sig_hashes().\n *\n * \\param conf     SSL configuration\n * \\param profile  Profile to use\n */\nvoid mbedtls_ssl_conf_cert_profile(mbedtls_ssl_config *conf,\n                                   const mbedtls_x509_crt_profile *profile);\n\n/**\n * \\brief          Set the data required to verify peer certificate\n *\n * \\note           See \\c mbedtls_x509_crt_verify() for notes regarding the\n *                 parameters ca_chain (maps to trust_ca for that function)\n *                 and ca_crl.\n *\n * \\param conf     SSL configuration\n * \\param ca_chain trusted CA chain (meaning all fully trusted top-level CAs)\n * \\param ca_crl   trusted CA CRLs\n */\nvoid mbedtls_ssl_conf_ca_chain(mbedtls_ssl_config *conf,\n                               mbedtls_x509_crt *ca_chain,\n                               mbedtls_x509_crl *ca_crl);\n\n#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)\n/**\n * \\brief          Set DN hints sent to client in CertificateRequest message\n *\n * \\note           If not set, subject distinguished names (DNs) are taken\n *                 from \\c mbedtls_ssl_conf_ca_chain()\n *                 or \\c mbedtls_ssl_set_hs_ca_chain())\n *\n * \\param conf     SSL configuration\n * \\param crt      crt chain whose subject DNs are issuer DNs of client certs\n *                 from which the client should select client peer certificate.\n */\nstatic inline\nvoid mbedtls_ssl_conf_dn_hints(mbedtls_ssl_config *conf,\n                               const mbedtls_x509_crt *crt)\n{\n    conf->MBEDTLS_PRIVATE(dn_hints) = crt;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */\n\n#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)\n/**\n * \\brief          Set the trusted certificate callback.\n *\n *                 This API allows to register the set of trusted certificates\n *                 through a callback, instead of a linked list as configured\n *                 by mbedtls_ssl_conf_ca_chain().\n *\n *                 This is useful for example in contexts where a large number\n *                 of CAs are used, and the inefficiency of maintaining them\n *                 in a linked list cannot be tolerated. It is also useful when\n *                 the set of trusted CAs needs to be modified frequently.\n *\n *                 See the documentation of `mbedtls_x509_crt_ca_cb_t` for\n *                 more information.\n *\n * \\param conf     The SSL configuration to register the callback with.\n * \\param f_ca_cb  The trusted certificate callback to use when verifying\n *                 certificate chains.\n * \\param p_ca_cb  The context to be passed to \\p f_ca_cb (for example,\n *                 a reference to a trusted CA database).\n *\n * \\note           This API is incompatible with mbedtls_ssl_conf_ca_chain():\n *                 Any call to this function overwrites the values set through\n *                 earlier calls to mbedtls_ssl_conf_ca_chain() or\n *                 mbedtls_ssl_conf_ca_cb().\n *\n * \\note           This API is incompatible with CA indication in\n *                 CertificateRequest messages: A server-side SSL context which\n *                 is bound to an SSL configuration that uses a CA callback\n *                 configured via mbedtls_ssl_conf_ca_cb(), and which requires\n *                 client authentication, will send an empty CA list in the\n *                 corresponding CertificateRequest message.\n *\n * \\note           This API is incompatible with mbedtls_ssl_set_hs_ca_chain():\n *                 If an SSL context is bound to an SSL configuration which uses\n *                 CA callbacks configured via mbedtls_ssl_conf_ca_cb(), then\n *                 calls to mbedtls_ssl_set_hs_ca_chain() have no effect.\n *\n * \\note           The use of this API disables the use of restartable ECC\n *                 during X.509 CRT signature verification (but doesn't affect\n *                 other uses).\n *\n * \\warning        This API is incompatible with the use of CRLs. Any call to\n *                 mbedtls_ssl_conf_ca_cb() unsets CRLs configured through\n *                 earlier calls to mbedtls_ssl_conf_ca_chain().\n *\n * \\warning        In multi-threaded environments, the callback \\p f_ca_cb\n *                 must be thread-safe, and it is the user's responsibility\n *                 to guarantee this (for example through a mutex\n *                 contained in the callback context pointed to by \\p p_ca_cb).\n */\nvoid mbedtls_ssl_conf_ca_cb(mbedtls_ssl_config *conf,\n                            mbedtls_x509_crt_ca_cb_t f_ca_cb,\n                            void *p_ca_cb);\n#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */\n\n/**\n * \\brief          Set own certificate chain and private key\n *\n * \\note           own_cert should contain in order from the bottom up your\n *                 certificate chain. The top certificate (self-signed)\n *                 can be omitted.\n *\n * \\note           On server, this function can be called multiple times to\n *                 provision more than one cert/key pair (eg one ECDSA, one\n *                 RSA with SHA-256, one RSA with SHA-1). An adequate\n *                 certificate will be selected according to the client's\n *                 advertised capabilities. In case multiple certificates are\n *                 adequate, preference is given to the one set by the first\n *                 call to this function, then second, etc.\n *\n * \\note           On client, only the first call has any effect. That is,\n *                 only one client certificate can be provisioned. The\n *                 server's preferences in its CertificateRequest message will\n *                 be ignored and our only cert will be sent regardless of\n *                 whether it matches those preferences - the server can then\n *                 decide what it wants to do with it.\n *\n * \\note           The provided \\p pk_key needs to match the public key in the\n *                 first certificate in \\p own_cert, or all handshakes using\n *                 that certificate will fail. It is your responsibility\n *                 to ensure that; this function will not perform any check.\n *                 You may use mbedtls_pk_check_pair() in order to perform\n *                 this check yourself, but be aware that this function can\n *                 be computationally expensive on some key types.\n *\n * \\param conf     SSL configuration\n * \\param own_cert own public certificate chain\n * \\param pk_key   own private key\n *\n * \\return         0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED\n */\nint mbedtls_ssl_conf_own_cert(mbedtls_ssl_config *conf,\n                              mbedtls_x509_crt *own_cert,\n                              mbedtls_pk_context *pk_key);\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)\n/**\n * \\brief          Configure pre-shared keys (PSKs) and their\n *                 identities to be used in PSK-based ciphersuites.\n *\n *                 Only one PSK can be registered, through either\n *                 mbedtls_ssl_conf_psk() or mbedtls_ssl_conf_psk_opaque().\n *                 If you attempt to register more than one PSK, this function\n *                 fails, though this may change in future versions, which\n *                 may add support for multiple PSKs.\n *\n * \\note           This is mainly useful for clients. Servers will usually\n *                 want to use \\c mbedtls_ssl_conf_psk_cb() instead.\n *\n * \\note           A PSK set by \\c mbedtls_ssl_set_hs_psk() in the PSK callback\n *                 takes precedence over a PSK configured by this function.\n *\n * \\param conf     The SSL configuration to register the PSK with.\n * \\param psk      The pointer to the pre-shared key to use.\n * \\param psk_len  The length of the pre-shared key in bytes.\n * \\param psk_identity      The pointer to the pre-shared key identity.\n * \\param psk_identity_len  The length of the pre-shared key identity\n *                          in bytes.\n *\n * \\note           The PSK and its identity are copied internally and\n *                 hence need not be preserved by the caller for the lifetime\n *                 of the SSL configuration.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no more PSKs\n *                 can be configured. In this case, the old PSK(s) remain intact.\n * \\return         Another negative error code on other kinds of failure.\n */\nint mbedtls_ssl_conf_psk(mbedtls_ssl_config *conf,\n                         const unsigned char *psk, size_t psk_len,\n                         const unsigned char *psk_identity, size_t psk_identity_len);\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n/**\n * \\brief          Configure one or more opaque pre-shared keys (PSKs) and\n *                 their identities to be used in PSK-based ciphersuites.\n *\n *                 Only one PSK can be registered, through either\n *                 mbedtls_ssl_conf_psk() or mbedtls_ssl_conf_psk_opaque().\n *                 If you attempt to register more than one PSK, this function\n *                 fails, though this may change in future versions, which\n *                 may add support for multiple PSKs.\n *\n * \\note           This is mainly useful for clients. Servers will usually\n *                 want to use \\c mbedtls_ssl_conf_psk_cb() instead.\n *\n * \\note           An opaque PSK set by \\c mbedtls_ssl_set_hs_psk_opaque() in\n *                 the PSK callback takes precedence over an opaque PSK\n *                 configured by this function.\n *\n * \\param conf     The SSL configuration to register the PSK with.\n * \\param psk      The identifier of the key slot holding the PSK.\n *                 Until \\p conf is destroyed or this function is successfully\n *                 called again, the key slot \\p psk must be populated with a\n *                 key of type PSA_ALG_CATEGORY_KEY_DERIVATION whose policy\n *                 allows its use for the key derivation algorithm applied\n *                 in the handshake.\n * \\param psk_identity      The pointer to the pre-shared key identity.\n * \\param psk_identity_len  The length of the pre-shared key identity\n *                          in bytes.\n *\n * \\note           The PSK identity hint is copied internally and hence need\n *                 not be preserved by the caller for the lifetime of the\n *                 SSL configuration.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no more PSKs\n *                 can be configured. In this case, the old PSK(s) remain intact.\n * \\return         Another negative error code on other kinds of failure.\n */\nint mbedtls_ssl_conf_psk_opaque(mbedtls_ssl_config *conf,\n                                mbedtls_svc_key_id_t psk,\n                                const unsigned char *psk_identity,\n                                size_t psk_identity_len);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n/**\n * \\brief          Set the pre-shared Key (PSK) for the current handshake.\n *\n * \\note           This should only be called inside the PSK callback,\n *                 i.e. the function passed to \\c mbedtls_ssl_conf_psk_cb().\n *\n * \\note           A PSK set by this function takes precedence over a PSK\n *                 configured by \\c mbedtls_ssl_conf_psk().\n *\n * \\param ssl      The SSL context to configure a PSK for.\n * \\param psk      The pointer to the pre-shared key.\n * \\param psk_len  The length of the pre-shared key in bytes.\n *\n * \\return         \\c 0 if successful.\n * \\return         An \\c MBEDTLS_ERR_SSL_XXX error code on failure.\n */\nint mbedtls_ssl_set_hs_psk(mbedtls_ssl_context *ssl,\n                           const unsigned char *psk, size_t psk_len);\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n/**\n * \\brief          Set an opaque pre-shared Key (PSK) for the current handshake.\n *\n * \\note           This should only be called inside the PSK callback,\n *                 i.e. the function passed to \\c mbedtls_ssl_conf_psk_cb().\n *\n * \\note           An opaque PSK set by this function takes precedence over an\n *                 opaque PSK configured by \\c mbedtls_ssl_conf_psk_opaque().\n *\n * \\param ssl      The SSL context to configure a PSK for.\n * \\param psk      The identifier of the key slot holding the PSK.\n *                 For the duration of the current handshake, the key slot\n *                 must be populated with a key of type\n *                 PSA_ALG_CATEGORY_KEY_DERIVATION whose policy allows its\n *                 use for the key derivation algorithm\n *                 applied in the handshake.\n *\n * \\return         \\c 0 if successful.\n * \\return         An \\c MBEDTLS_ERR_SSL_XXX error code on failure.\n */\nint mbedtls_ssl_set_hs_psk_opaque(mbedtls_ssl_context *ssl,\n                                  mbedtls_svc_key_id_t psk);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_SSL_SRV_C)\n/**\n * \\brief          Set the PSK callback (server-side only).\n *\n *                 If set, the PSK callback is called for each\n *                 handshake where a PSK-based ciphersuite was negotiated.\n *                 The caller provides the identity received and wants to\n *                 receive the actual PSK data and length.\n *\n *                 The callback has the following parameters:\n *                 - \\c void*: The opaque pointer \\p p_psk.\n *                 - \\c mbedtls_ssl_context*: The SSL context to which\n *                                            the operation applies.\n *                 - \\c const unsigned char*: The PSK identity\n *                                            selected by the client.\n *                 - \\c size_t: The length of the PSK identity\n *                              selected by the client.\n *\n *                 If a valid PSK identity is found, the callback should use\n *                 \\c mbedtls_ssl_set_hs_psk() or\n *                 \\c mbedtls_ssl_set_hs_psk_opaque()\n *                 on the SSL context to set the correct PSK and return \\c 0.\n *                 Any other return value will result in a denied PSK identity.\n *\n * \\note           A dynamic PSK (i.e. set by the PSK callback) takes\n *                 precedence over a static PSK (i.e. set by\n *                 \\c mbedtls_ssl_conf_psk() or\n *                 \\c mbedtls_ssl_conf_psk_opaque()).\n *                 This means that if you set a PSK callback using this\n *                 function, you don't need to set a PSK using\n *                 \\c mbedtls_ssl_conf_psk() or\n *                 \\c mbedtls_ssl_conf_psk_opaque()).\n *\n * \\param conf     The SSL configuration to register the callback with.\n * \\param f_psk    The callback for selecting and setting the PSK based\n *                 in the PSK identity chosen by the client.\n * \\param p_psk    A pointer to an opaque structure to be passed to\n *                 the callback, for example a PSK store.\n */\nvoid mbedtls_ssl_conf_psk_cb(mbedtls_ssl_config *conf,\n                             int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *,\n                                          size_t),\n                             void *p_psk);\n#endif /* MBEDTLS_SSL_SRV_C */\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */\n\n#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)\n/**\n * \\brief          Set the Diffie-Hellman public P and G values\n *                 from big-endian binary presentations.\n *                 (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]_BIN)\n *\n * \\param conf     SSL configuration\n * \\param dhm_P    Diffie-Hellman-Merkle modulus in big-endian binary form\n * \\param P_len    Length of DHM modulus\n * \\param dhm_G    Diffie-Hellman-Merkle generator in big-endian binary form\n * \\param G_len    Length of DHM generator\n *\n * \\return         0 if successful\n */\nint mbedtls_ssl_conf_dh_param_bin(mbedtls_ssl_config *conf,\n                                  const unsigned char *dhm_P, size_t P_len,\n                                  const unsigned char *dhm_G,  size_t G_len);\n\n/**\n * \\brief          Set the Diffie-Hellman public P and G values,\n *                 read from existing context (server-side only)\n *\n * \\param conf     SSL configuration\n * \\param dhm_ctx  Diffie-Hellman-Merkle context\n *\n * \\return         0 if successful\n */\nint mbedtls_ssl_conf_dh_param_ctx(mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx);\n#endif /* MBEDTLS_DHM_C && defined(MBEDTLS_SSL_SRV_C) */\n\n#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C)\n/**\n * \\brief          Set the minimum length for Diffie-Hellman parameters.\n *                 (Client-side only.)\n *                 (Default: 1024 bits.)\n *\n * \\param conf     SSL configuration\n * \\param bitlen   Minimum bit length of the DHM prime\n */\nvoid mbedtls_ssl_conf_dhm_min_bitlen(mbedtls_ssl_config *conf,\n                                     unsigned int bitlen);\n#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */\n\n#if defined(MBEDTLS_ECP_C)\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n/**\n * \\brief          Set the allowed curves in order of preference.\n *\n *                 On server: this only affects selection of the ECDHE curve;\n *                 the curves used for ECDH and ECDSA are determined by the\n *                 list of available certificates instead.\n *\n *                 On client: this affects the list of curves offered for any\n *                 use. The server can override our preference order.\n *\n *                 Both sides: limits the set of curves accepted for use in\n *                 ECDHE and in the peer's end-entity certificate.\n *\n * \\deprecated     Superseded by mbedtls_ssl_conf_groups().\n *\n * \\note           This has no influence on which curves are allowed inside the\n *                 certificate chains, see \\c mbedtls_ssl_conf_cert_profile()\n *                 for that. For the end-entity certificate however, the key\n *                 will be accepted only if it is allowed both by this list\n *                 and by the cert profile.\n *\n * \\note           This list should be ordered by decreasing preference\n *                 (preferred curve first).\n *\n * \\note           The default list is the same set of curves that\n *                 #mbedtls_x509_crt_profile_default allows, plus\n *                 ECDHE-only curves selected according to the same criteria.\n *                 The order favors curves with the lowest resource usage.\n *\n * \\note           New minor versions of Mbed TLS may extend this list,\n *                 for example if new curves are added to the library.\n *                 New minor versions of Mbed TLS will not remove items\n *                 from this list unless serious security concerns require it.\n *                 New minor versions of Mbed TLS may change the order in\n *                 keeping with the general principle of favoring the lowest\n *                 resource usage.\n *\n * \\param conf     SSL configuration\n * \\param curves   Ordered list of allowed curves,\n *                 terminated by MBEDTLS_ECP_DP_NONE.\n */\nvoid MBEDTLS_DEPRECATED mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf,\n                                                const mbedtls_ecp_group_id *curves);\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n#endif /* MBEDTLS_ECP_C */\n\n/**\n * \\brief          Set the allowed groups in order of preference.\n *\n *                 On server: This only affects the choice of key agreement mechanism\n *\n *                 On client: this affects the list of groups offered for any\n *                 use. The server can override our preference order.\n *\n *                 Both sides: limits the set of groups accepted for use in\n *                 key sharing.\n *\n * \\note           This function replaces the deprecated mbedtls_ssl_conf_curves(),\n *                 which only allows ECP curves to be configured.\n *\n * \\note           The most recent invocation of either mbedtls_ssl_conf_curves()\n *                 or mbedtls_ssl_conf_groups() nullifies all previous invocations\n *                 of both.\n *\n * \\note           This list should be ordered by decreasing preference\n *                 (preferred group first).\n *\n * \\note           When this function is not called, a default list is used,\n *                 consisting of all supported curves at 255 bits and above,\n *                 and all supported finite fields at 2048 bits and above.\n *                 The order favors groups with the lowest resource usage.\n *\n * \\note           New minor versions of Mbed TLS will not remove items\n *                 from the default list unless serious security concerns require it.\n *                 New minor versions of Mbed TLS may change the order in\n *                 keeping with the general principle of favoring the lowest\n *                 resource usage.\n *\n * \\param conf     SSL configuration\n * \\param groups   List of allowed groups ordered by preference, terminated by 0.\n *                 Must contain valid IANA NamedGroup IDs (provided via either an integer\n *                 or using MBEDTLS_TLS1_3_NAMED_GROUP_XXX macros).\n */\nvoid mbedtls_ssl_conf_groups(mbedtls_ssl_config *conf,\n                             const uint16_t *groups);\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n#if !defined(MBEDTLS_DEPRECATED_REMOVED) && defined(MBEDTLS_SSL_PROTO_TLS1_2)\n/**\n * \\brief          Set the allowed hashes for signatures during the handshake.\n *\n * \\note           This only affects which hashes are offered and can be used\n *                 for signatures during the handshake. Hashes for message\n *                 authentication and the TLS PRF are controlled by the\n *                 ciphersuite, see \\c mbedtls_ssl_conf_ciphersuites(). Hashes\n *                 used for certificate signature are controlled by the\n *                 verification profile, see \\c mbedtls_ssl_conf_cert_profile().\n *\n * \\deprecated     Superseded by mbedtls_ssl_conf_sig_algs().\n *\n * \\note           This list should be ordered by decreasing preference\n *                 (preferred hash first).\n *\n * \\note           By default, all supported hashes whose length is at least\n *                 256 bits are allowed. This is the same set as the default\n *                 for certificate verification\n *                 (#mbedtls_x509_crt_profile_default).\n *                 The preference order is currently unspecified and may\n *                 change in future versions.\n *\n * \\note           New minor versions of Mbed TLS may extend this list,\n *                 for example if new curves are added to the library.\n *                 New minor versions of Mbed TLS will not remove items\n *                 from this list unless serious security concerns require it.\n *\n * \\param conf     SSL configuration\n * \\param hashes   Ordered list of allowed signature hashes,\n *                 terminated by \\c MBEDTLS_MD_NONE.\n */\nvoid MBEDTLS_DEPRECATED mbedtls_ssl_conf_sig_hashes(mbedtls_ssl_config *conf,\n                                                    const int *hashes);\n#endif /* !MBEDTLS_DEPRECATED_REMOVED && MBEDTLS_SSL_PROTO_TLS1_2 */\n\n/**\n * \\brief          Configure allowed signature algorithms for use in TLS\n *\n * \\param conf     The SSL configuration to use.\n * \\param sig_algs List of allowed IANA values for TLS 1.3 signature algorithms,\n *                 terminated by #MBEDTLS_TLS1_3_SIG_NONE. The list must remain\n *                 available throughout the lifetime of the conf object.\n *                 - For TLS 1.3, values of \\c MBEDTLS_TLS1_3_SIG_XXXX should be\n *                   used.\n *                 - For TLS 1.2, values should be given as\n *                   \"(HashAlgorithm << 8) | SignatureAlgorithm\".\n */\nvoid mbedtls_ssl_conf_sig_algs(mbedtls_ssl_config *conf,\n                               const uint16_t *sig_algs);\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n/**\n * \\brief          Set or reset the hostname to check against the received\n *                 peer certificate. On a client, this also sets the\n *                 ServerName TLS extension, if that extension is enabled.\n *                 On a TLS 1.3 client, this also sets the server name in\n *                 the session resumption ticket, if that feature is enabled.\n *\n * \\param ssl      SSL context\n * \\param hostname The server hostname. This may be \\c NULL to clear\n *                 the hostname.\n *\n * \\note           Maximum hostname length #MBEDTLS_SSL_MAX_HOST_NAME_LEN.\n *\n * \\note           If the hostname is \\c NULL on a client, then the server\n *                 is not authenticated: it only needs to have a valid\n *                 certificate, not a certificate matching its name.\n *                 Therefore you should always call this function on a client,\n *                 unless the connection is set up to only allow\n *                 pre-shared keys, or in scenarios where server\n *                 impersonation is not a concern. See the documentation of\n *                 #MBEDTLS_ERR_SSL_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME\n *                 for more details.\n *\n * \\return         0 if successful, #MBEDTLS_ERR_SSL_ALLOC_FAILED on\n *                 allocation failure, #MBEDTLS_ERR_SSL_BAD_INPUT_DATA on\n *                 too long input hostname.\n *\n *                 Hostname set to the one provided on success (cleared\n *                 when NULL). On allocation failure hostname is cleared.\n *                 On too long input failure, old hostname is unchanged.\n */\nint mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname);\n\n/**\n * \\brief          Get the hostname that checked against the received\n *                 server certificate. It is used to set the ServerName\n *                 TLS extension, too, if that extension is enabled.\n *                 (client-side only)\n *\n * \\param ssl      SSL context\n *\n * \\return         const pointer to the hostname value\n */\nstatic inline const char *mbedtls_ssl_get_hostname(mbedtls_ssl_context *ssl)\n{\n    return ssl->MBEDTLS_PRIVATE(hostname);\n}\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n/**\n * \\brief          Retrieve SNI extension value for the current handshake.\n *                 Available in \\c f_cert_cb of \\c mbedtls_ssl_conf_cert_cb(),\n *                 this is the same value passed to \\c f_sni callback of\n *                 \\c mbedtls_ssl_conf_sni() and may be used instead of\n *                 \\c mbedtls_ssl_conf_sni().\n *\n * \\param ssl      SSL context\n * \\param name_len pointer into which to store length of returned value.\n *                 0 if SNI extension is not present or not yet processed.\n *\n * \\return         const pointer to SNI extension value.\n *                 - value is valid only when called in \\c f_cert_cb\n *                   registered with \\c mbedtls_ssl_conf_cert_cb().\n *                 - value is NULL if SNI extension is not present.\n *                 - value is not '\\0'-terminated. Use \\c name_len for len.\n *                 - value must not be freed.\n */\nconst unsigned char *mbedtls_ssl_get_hs_sni(mbedtls_ssl_context *ssl,\n                                            size_t *name_len);\n\n/**\n * \\brief          Set own certificate and key for the current handshake\n *\n * \\note           Same as \\c mbedtls_ssl_conf_own_cert() but for use within\n *                 the SNI callback or the certificate selection callback.\n *\n * \\note           Passing null \\c own_cert clears the certificate list for\n *                 the current handshake.\n *\n * \\param ssl      SSL context\n * \\param own_cert own public certificate chain\n * \\param pk_key   own private key\n *\n * \\return         0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED\n */\nint mbedtls_ssl_set_hs_own_cert(mbedtls_ssl_context *ssl,\n                                mbedtls_x509_crt *own_cert,\n                                mbedtls_pk_context *pk_key);\n\n/**\n * \\brief          Set the data required to verify peer certificate for the\n *                 current handshake\n *\n * \\note           Same as \\c mbedtls_ssl_conf_ca_chain() but for use within\n *                 the SNI callback or the certificate selection callback.\n *\n * \\param ssl      SSL context\n * \\param ca_chain trusted CA chain (meaning all fully trusted top-level CAs)\n * \\param ca_crl   trusted CA CRLs\n */\nvoid mbedtls_ssl_set_hs_ca_chain(mbedtls_ssl_context *ssl,\n                                 mbedtls_x509_crt *ca_chain,\n                                 mbedtls_x509_crl *ca_crl);\n\n#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)\n/**\n * \\brief          Set DN hints sent to client in CertificateRequest message\n *\n * \\note           Same as \\c mbedtls_ssl_conf_dn_hints() but for use within\n *                 the SNI callback or the certificate selection callback.\n *\n * \\param ssl      SSL context\n * \\param crt      crt chain whose subject DNs are issuer DNs of client certs\n *                 from which the client should select client peer certificate.\n */\nvoid mbedtls_ssl_set_hs_dn_hints(mbedtls_ssl_context *ssl,\n                                 const mbedtls_x509_crt *crt);\n#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */\n\n/**\n * \\brief          Set authmode for the current handshake.\n *\n * \\note           Same as \\c mbedtls_ssl_conf_authmode() but for use within\n *                 the SNI callback or the certificate selection callback.\n *\n * \\param ssl      SSL context\n * \\param authmode MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL or\n *                 MBEDTLS_SSL_VERIFY_REQUIRED\n */\nvoid mbedtls_ssl_set_hs_authmode(mbedtls_ssl_context *ssl,\n                                 int authmode);\n\n/**\n * \\brief          Set server side ServerName TLS extension callback\n *                 (optional, server-side only).\n *\n *                 If set, the ServerName callback is called whenever the\n *                 server receives a ServerName TLS extension from the client\n *                 during a handshake. The ServerName callback has the\n *                 following parameters: (void *parameter, mbedtls_ssl_context *ssl,\n *                 const unsigned char *hostname, size_t len). If a suitable\n *                 certificate is found, the callback must set the\n *                 certificate(s) and key(s) to use with \\c\n *                 mbedtls_ssl_set_hs_own_cert() (can be called repeatedly),\n *                 and may optionally adjust the CA and associated CRL with \\c\n *                 mbedtls_ssl_set_hs_ca_chain() as well as the client\n *                 authentication mode with \\c mbedtls_ssl_set_hs_authmode(),\n *                 then must return 0. If no matching name is found, the\n *                 callback may return non-zero to abort the handshake.\n *\n * \\param conf     SSL configuration\n * \\param f_sni    verification function\n * \\param p_sni    verification parameter\n */\nvoid mbedtls_ssl_conf_sni(mbedtls_ssl_config *conf,\n                          int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *,\n                                       size_t),\n                          void *p_sni);\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n/**\n * \\brief          Set the EC J-PAKE password for current handshake.\n *\n * \\note           An internal copy is made, and destroyed as soon as the\n *                 handshake is completed, or when the SSL context is reset or\n *                 freed.\n *\n * \\note           The SSL context needs to be already set up. The right place\n *                 to call this function is between \\c mbedtls_ssl_setup() or\n *                 \\c mbedtls_ssl_reset() and \\c mbedtls_ssl_handshake().\n *                 Password cannot be empty (see RFC 8236).\n *\n * \\param ssl      SSL context\n * \\param pw       EC J-PAKE password (pre-shared secret). It cannot be empty\n * \\param pw_len   length of pw in bytes\n *\n * \\return         0 on success, or a negative error code.\n */\nint mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl,\n                                        const unsigned char *pw,\n                                        size_t pw_len);\n\n/**\n * \\brief          Set the EC J-PAKE opaque password for current handshake.\n *\n * \\note           The key must remain valid until the handshake is over.\n *\n * \\note           The SSL context needs to be already set up. The right place\n *                 to call this function is between \\c mbedtls_ssl_setup() or\n *                 \\c mbedtls_ssl_reset() and \\c mbedtls_ssl_handshake().\n *\n * \\param ssl      SSL context\n * \\param pwd      EC J-PAKE opaque password\n *\n * \\return         0 on success, or a negative error code.\n */\nint mbedtls_ssl_set_hs_ecjpake_password_opaque(mbedtls_ssl_context *ssl,\n                                               mbedtls_svc_key_id_t pwd);\n#endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_SSL_ALPN)\n/**\n * \\brief          Set the supported Application Layer Protocols.\n *\n * \\param conf     SSL configuration\n * \\param protos   Pointer to a NULL-terminated list of supported protocols,\n *                 in decreasing preference order. The pointer to the list is\n *                 recorded by the library for later reference as required, so\n *                 the lifetime of the table must be at least as long as the\n *                 lifetime of the SSL configuration structure.\n *\n * \\return         0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA.\n */\nint mbedtls_ssl_conf_alpn_protocols(mbedtls_ssl_config *conf, const char **protos);\n\n/**\n * \\brief          Get the name of the negotiated Application Layer Protocol.\n *                 This function should be called after the handshake is\n *                 completed.\n *\n * \\param ssl      SSL context\n *\n * \\return         Protocol name, or NULL if no protocol was negotiated.\n */\nconst char *mbedtls_ssl_get_alpn_protocol(const mbedtls_ssl_context *ssl);\n#endif /* MBEDTLS_SSL_ALPN */\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\n#if defined(MBEDTLS_DEBUG_C)\nstatic inline const char *mbedtls_ssl_get_srtp_profile_as_string(mbedtls_ssl_srtp_profile profile)\n{\n    switch (profile) {\n        case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80:\n            return \"MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80\";\n        case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32:\n            return \"MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32\";\n        case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80:\n            return \"MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80\";\n        case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32:\n            return \"MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32\";\n        default: break;\n    }\n    return \"\";\n}\n#endif /* MBEDTLS_DEBUG_C */\n/**\n * \\brief                   Manage support for mki(master key id) value\n *                          in use_srtp extension.\n *                          MKI is an optional part of SRTP used for key management\n *                          and re-keying. See RFC3711 section 3.1 for details.\n *                          The default value is\n *                          #MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED.\n *\n * \\param conf              The SSL configuration to manage mki support.\n * \\param support_mki_value Enable or disable mki usage. Values are\n *                          #MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED\n *                          or #MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED.\n */\nvoid mbedtls_ssl_conf_srtp_mki_value_supported(mbedtls_ssl_config *conf,\n                                               int support_mki_value);\n\n/**\n * \\brief                   Set the supported DTLS-SRTP protection profiles.\n *\n * \\param conf              SSL configuration\n * \\param profiles          Pointer to a List of MBEDTLS_TLS_SRTP_UNSET terminated\n *                          supported protection profiles\n *                          in decreasing preference order.\n *                          The pointer to the list is recorded by the library\n *                          for later reference as required, so the lifetime\n *                          of the table must be at least as long as the lifetime\n *                          of the SSL configuration structure.\n *                          The list must not hold more than\n *                          MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH elements\n *                          (excluding the terminating MBEDTLS_TLS_SRTP_UNSET).\n *\n * \\return                  0 on success\n * \\return                  #MBEDTLS_ERR_SSL_BAD_INPUT_DATA when the list of\n *                          protection profiles is incorrect.\n */\nint mbedtls_ssl_conf_dtls_srtp_protection_profiles\n    (mbedtls_ssl_config *conf,\n    const mbedtls_ssl_srtp_profile *profiles);\n\n/**\n * \\brief                  Set the mki_value for the current DTLS-SRTP session.\n *\n * \\param ssl              SSL context to use.\n * \\param mki_value        The MKI value to set.\n * \\param mki_len          The length of the MKI value.\n *\n * \\note                   This function is relevant on client side only.\n *                         The server discovers the mki value during handshake.\n *                         A mki value set on server side using this function\n *                         is ignored.\n *\n * \\return                 0 on success\n * \\return                 #MBEDTLS_ERR_SSL_BAD_INPUT_DATA\n * \\return                 #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE\n */\nint mbedtls_ssl_dtls_srtp_set_mki_value(mbedtls_ssl_context *ssl,\n                                        unsigned char *mki_value,\n                                        uint16_t mki_len);\n/**\n * \\brief                  Get the negotiated DTLS-SRTP information:\n *                         Protection profile and MKI value.\n *\n * \\warning                This function must be called after the handshake is\n *                         completed. The value returned by this function must\n *                         not be trusted or acted upon before the handshake completes.\n *\n * \\param ssl              The SSL context to query.\n * \\param dtls_srtp_info   The negotiated DTLS-SRTP information:\n *                         - Protection profile in use.\n *                         A direct mapping of the iana defined value for protection\n *                         profile on an uint16_t.\n                   http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml\n *                         #MBEDTLS_TLS_SRTP_UNSET if the use of SRTP was not negotiated\n *                         or peer's Hello packet was not parsed yet.\n *                         - mki size and value( if size is > 0 ).\n */\nvoid mbedtls_ssl_get_dtls_srtp_negotiation_result(const mbedtls_ssl_context *ssl,\n                                                  mbedtls_dtls_srtp_info *dtls_srtp_info);\n#endif /* MBEDTLS_SSL_DTLS_SRTP */\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n/**\n * \\brief          Set the maximum supported version sent from the client side\n *                 and/or accepted at the server side.\n *\n *                 See also the documentation of mbedtls_ssl_conf_min_version().\n *\n * \\note           This ignores ciphersuites from higher versions.\n *\n * \\note           This function is deprecated and has been replaced by\n *                 \\c mbedtls_ssl_conf_max_tls_version().\n *\n * \\param conf     SSL configuration\n * \\param major    Major version number (#MBEDTLS_SSL_MAJOR_VERSION_3)\n * \\param minor    Minor version number\n *                 (#MBEDTLS_SSL_MINOR_VERSION_3 for (D)TLS 1.2,\n *                 #MBEDTLS_SSL_MINOR_VERSION_4 for TLS 1.3)\n */\nvoid MBEDTLS_DEPRECATED mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major,\n                                                     int minor);\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n\n/**\n * \\brief          Set the maximum supported version sent from the client side\n *                 and/or accepted at the server side.\n *\n * \\note           After the handshake, you can call\n *                 mbedtls_ssl_get_version_number() to see what version was\n *                 negotiated.\n *\n * \\param conf         SSL configuration\n * \\param tls_version  TLS protocol version number (\\c mbedtls_ssl_protocol_version)\n *                     (#MBEDTLS_SSL_VERSION_UNKNOWN is not valid)\n */\nstatic inline void mbedtls_ssl_conf_max_tls_version(mbedtls_ssl_config *conf,\n                                                    mbedtls_ssl_protocol_version tls_version)\n{\n    conf->MBEDTLS_PRIVATE(max_tls_version) = tls_version;\n}\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n/**\n * \\brief          Set the minimum accepted SSL/TLS protocol version\n *\n * \\note           By default, all supported versions are accepted.\n *                 Future versions of the library may disable older\n *                 protocol versions by default if they become deprecated.\n *\n * \\note           The following versions are supported (if enabled at\n *                 compile time):\n *                 - (D)TLS 1.2: \\p major = #MBEDTLS_SSL_MAJOR_VERSION_3,\n *                   \\p minor = #MBEDTLS_SSL_MINOR_VERSION_3\n *                 - TLS 1.3: \\p major = #MBEDTLS_SSL_MAJOR_VERSION_3,\n *                   \\p minor = #MBEDTLS_SSL_MINOR_VERSION_4\n *\n *                 Note that the numbers in the constant names are the\n *                 TLS internal protocol numbers, and the minor versions\n *                 differ by one from the human-readable versions!\n *\n * \\note           Input outside of the SSL_MAX_XXXXX_VERSION and\n *                 SSL_MIN_XXXXX_VERSION range is ignored.\n *\n * \\note           After the handshake, you can call\n *                 mbedtls_ssl_get_version_number() to see what version was\n *                 negotiated.\n *\n * \\note           This function is deprecated and has been replaced by\n *                 \\c mbedtls_ssl_conf_min_tls_version().\n *\n * \\param conf     SSL configuration\n * \\param major    Major version number (#MBEDTLS_SSL_MAJOR_VERSION_3)\n * \\param minor    Minor version number\n *                 (#MBEDTLS_SSL_MINOR_VERSION_3 for (D)TLS 1.2,\n *                 #MBEDTLS_SSL_MINOR_VERSION_4 for TLS 1.3)\n */\nvoid MBEDTLS_DEPRECATED mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, int major,\n                                                     int minor);\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n\n/**\n * \\brief          Set the minimum supported version sent from the client side\n *                 and/or accepted at the server side.\n *\n * \\note           After the handshake, you can call\n *                 mbedtls_ssl_get_version_number() to see what version was\n *                 negotiated.\n *\n * \\param conf         SSL configuration\n * \\param tls_version  TLS protocol version number (\\c mbedtls_ssl_protocol_version)\n *                     (#MBEDTLS_SSL_VERSION_UNKNOWN is not valid)\n */\nstatic inline void mbedtls_ssl_conf_min_tls_version(mbedtls_ssl_config *conf,\n                                                    mbedtls_ssl_protocol_version tls_version)\n{\n    conf->MBEDTLS_PRIVATE(min_tls_version) = tls_version;\n}\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n/**\n * \\brief           Enable or disable Encrypt-then-MAC\n *                  (Default: MBEDTLS_SSL_ETM_ENABLED)\n *\n * \\note            This should always be enabled, it is a security\n *                  improvement, and should not cause any interoperability\n *                  issue (used only if the peer supports it too).\n *\n * \\param conf      SSL configuration\n * \\param etm       MBEDTLS_SSL_ETM_ENABLED or MBEDTLS_SSL_ETM_DISABLED\n */\nvoid mbedtls_ssl_conf_encrypt_then_mac(mbedtls_ssl_config *conf, char etm);\n#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */\n\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\n/**\n * \\brief           Enable or disable Extended Master Secret negotiation.\n *                  (Default: MBEDTLS_SSL_EXTENDED_MS_ENABLED)\n *\n * \\note            This should always be enabled, it is a security fix to the\n *                  protocol, and should not cause any interoperability issue\n *                  (used only if the peer supports it too).\n *\n * \\param conf      SSL configuration\n * \\param ems       MBEDTLS_SSL_EXTENDED_MS_ENABLED or MBEDTLS_SSL_EXTENDED_MS_DISABLED\n */\nvoid mbedtls_ssl_conf_extended_master_secret(mbedtls_ssl_config *conf, char ems);\n#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */\n\n#if defined(MBEDTLS_SSL_SRV_C)\n/**\n * \\brief          Whether to send a list of acceptable CAs in\n *                 CertificateRequest messages.\n *                 (Default: do send)\n *\n * \\param conf     SSL configuration\n * \\param cert_req_ca_list   MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED or\n *                          MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED\n */\nvoid mbedtls_ssl_conf_cert_req_ca_list(mbedtls_ssl_config *conf,\n                                       char cert_req_ca_list);\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n/**\n * \\brief          Set the maximum fragment length to emit and/or negotiate.\n *                 (Typical: the smaller of #MBEDTLS_SSL_IN_CONTENT_LEN and\n *                 #MBEDTLS_SSL_OUT_CONTENT_LEN, usually `2^14` bytes)\n *                 (Server: set maximum fragment length to emit,\n *                 usually negotiated by the client during handshake)\n *                 (Client: set maximum fragment length to emit *and*\n *                 negotiate with the server during handshake)\n *                 (Default: #MBEDTLS_SSL_MAX_FRAG_LEN_NONE)\n *\n * \\note           On the client side, the maximum fragment length extension\n *                 *will not* be used, unless the maximum fragment length has\n *                 been set via this function to a value different than\n *                 #MBEDTLS_SSL_MAX_FRAG_LEN_NONE.\n *\n * \\note           With TLS, this currently only affects ApplicationData (sent\n *                 with \\c mbedtls_ssl_read()), not handshake messages.\n *                 With DTLS, this affects both ApplicationData and handshake.\n *\n * \\note           Defragmentation of TLS handshake messages is supported\n *                 with some limitations. See the documentation of\n *                 mbedtls_ssl_handshake() for details.\n *\n * \\note           This sets the maximum length for a record's payload,\n *                 excluding record overhead that will be added to it, see\n *                 \\c mbedtls_ssl_get_record_expansion().\n *\n * \\note           For DTLS, it is also possible to set a limit for the total\n *                 size of datagrams passed to the transport layer, including\n *                 record overhead, see \\c mbedtls_ssl_set_mtu().\n *\n * \\param conf     SSL configuration\n * \\param mfl_code Code for maximum fragment length (allowed values:\n *                 MBEDTLS_SSL_MAX_FRAG_LEN_512,  MBEDTLS_SSL_MAX_FRAG_LEN_1024,\n *                 MBEDTLS_SSL_MAX_FRAG_LEN_2048, MBEDTLS_SSL_MAX_FRAG_LEN_4096)\n *\n * \\return         0 if successful or MBEDTLS_ERR_SSL_BAD_INPUT_DATA\n */\nint mbedtls_ssl_conf_max_frag_len(mbedtls_ssl_config *conf, unsigned char mfl_code);\n#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */\n\n#if defined(MBEDTLS_SSL_SRV_C)\n/**\n * \\brief          Pick the ciphersuites order according to the second parameter\n *                 in the SSL Server module (MBEDTLS_SSL_SRV_C).\n *                 (Default, if never called: MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER)\n *\n * \\param conf     SSL configuration\n * \\param order    Server or client (MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER\n *                                or MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT)\n */\nvoid mbedtls_ssl_conf_preference_order(mbedtls_ssl_config *conf, int order);\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)\n/**\n * \\brief          Enable / Disable TLS 1.2 session tickets (client only,\n *                 TLS 1.2 only). Enabled by default.\n *\n * \\note           On server, use \\c mbedtls_ssl_conf_session_tickets_cb().\n *\n * \\param conf     SSL configuration\n * \\param use_tickets   Enable or disable (#MBEDTLS_SSL_SESSION_TICKETS_ENABLED or\n *                                         #MBEDTLS_SSL_SESSION_TICKETS_DISABLED)\n */\nvoid mbedtls_ssl_conf_session_tickets(mbedtls_ssl_config *conf, int use_tickets);\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n/**\n * \\brief Enable / Disable handling of TLS 1.3 NewSessionTicket messages\n *        (client only, TLS 1.3 only).\n *\n *        The handling of TLS 1.3 NewSessionTicket messages is disabled by\n *        default.\n *\n *        In TLS 1.3, servers may send a NewSessionTicket message at any time,\n *        and may send multiple NewSessionTicket messages. By default, TLS 1.3\n *        clients ignore NewSessionTicket messages.\n *\n *        To support session tickets in TLS 1.3 clients, call this function\n *        with #MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED. When\n *        this is enabled, when a client receives a NewSessionTicket message,\n *        the next call to a message processing functions (notably\n *        mbedtls_ssl_handshake() and mbedtls_ssl_read()) will return\n *        #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET. The client should then\n *        call mbedtls_ssl_get_session() to retrieve the session ticket before\n *        calling the same message processing function again.\n *\n * \\param conf  SSL configuration\n * \\param signal_new_session_tickets Enable or disable\n *                                   (#MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED or\n *                                    #MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED)\n */\nvoid mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(\n    mbedtls_ssl_config *conf, int signal_new_session_tickets);\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \\\n    defined(MBEDTLS_SSL_SRV_C) && \\\n    defined(MBEDTLS_SSL_PROTO_TLS1_3)\n/**\n * \\brief   Number of NewSessionTicket messages for the server to send\n *          after handshake completion.\n *\n * \\note    The default value is\n *          \\c MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS.\n *\n * \\note    In case of a session resumption, this setting only partially apply.\n *          At most one ticket is sent in that case to just renew the pool of\n *          tickets of the client. The rationale is to avoid the number of\n *          tickets on the server to become rapidly out of control when the\n *          server has the same configuration for all its connection instances.\n *\n * \\param conf    SSL configuration\n * \\param num_tickets    Number of NewSessionTicket.\n *\n */\nvoid mbedtls_ssl_conf_new_session_tickets(mbedtls_ssl_config *conf,\n                                          uint16_t num_tickets);\n#endif /* MBEDTLS_SSL_SESSION_TICKETS &&\n          MBEDTLS_SSL_SRV_C &&\n          MBEDTLS_SSL_PROTO_TLS1_3*/\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n/**\n * \\brief          Enable / Disable renegotiation support for connection when\n *                 initiated by peer\n *                 (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED)\n *\n * \\warning        It is recommended to always disable renegotiation unless you\n *                 know you need it and you know what you're doing. In the\n *                 past, there have been several issues associated with\n *                 renegotiation or a poor understanding of its properties.\n *\n * \\note           Server-side, enabling renegotiation also makes the server\n *                 susceptible to a resource DoS by a malicious client.\n *\n * \\param conf    SSL configuration\n * \\param renegotiation     Enable or disable (MBEDTLS_SSL_RENEGOTIATION_ENABLED or\n *                                             MBEDTLS_SSL_RENEGOTIATION_DISABLED)\n */\nvoid mbedtls_ssl_conf_renegotiation(mbedtls_ssl_config *conf, int renegotiation);\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n\n/**\n * \\brief          Prevent or allow legacy renegotiation.\n *                 (Default: MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION)\n *\n *                 MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION allows connections to\n *                 be established even if the peer does not support\n *                 secure renegotiation, but does not allow renegotiation\n *                 to take place if not secure.\n *                 (Interoperable and secure option)\n *\n *                 MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations\n *                 with non-upgraded peers. Allowing legacy renegotiation\n *                 makes the connection vulnerable to specific man in the\n *                 middle attacks. (See RFC 5746)\n *                 (Most interoperable and least secure option)\n *\n *                 MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE breaks off connections\n *                 if peer does not support secure renegotiation. Results\n *                 in interoperability issues with non-upgraded peers\n *                 that do not support renegotiation altogether.\n *                 (Most secure option, interoperability issues)\n *\n * \\param conf     SSL configuration\n * \\param allow_legacy  Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION,\n *                                        SSL_ALLOW_LEGACY_RENEGOTIATION or\n *                                        MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE)\n */\nvoid mbedtls_ssl_conf_legacy_renegotiation(mbedtls_ssl_config *conf, int allow_legacy);\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n/**\n * \\brief          Enforce renegotiation requests.\n *                 (Default: enforced, max_records = 16)\n *\n *                 When we request a renegotiation, the peer can comply or\n *                 ignore the request. This function allows us to decide\n *                 whether to enforce our renegotiation requests by closing\n *                 the connection if the peer doesn't comply.\n *\n *                 However, records could already be in transit from the peer\n *                 when the request is emitted. In order to increase\n *                 reliability, we can accept a number of records before the\n *                 expected handshake records.\n *\n *                 The optimal value is highly dependent on the specific usage\n *                 scenario.\n *\n * \\note           With DTLS and server-initiated renegotiation, the\n *                 HelloRequest is retransmitted every time mbedtls_ssl_read() times\n *                 out or receives Application Data, until:\n *                 - max_records records have beens seen, if it is >= 0, or\n *                 - the number of retransmits that would happen during an\n *                 actual handshake has been reached.\n *                 Please remember the request might be lost a few times\n *                 if you consider setting max_records to a really low value.\n *\n * \\warning        On client, the grace period can only happen during\n *                 mbedtls_ssl_read(), as opposed to mbedtls_ssl_write() and mbedtls_ssl_renegotiate()\n *                 which always behave as if max_record was 0. The reason is,\n *                 if we receive application data from the server, we need a\n *                 place to write it, which only happens during mbedtls_ssl_read().\n *\n * \\param conf     SSL configuration\n * \\param max_records Use MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to\n *                 enforce renegotiation, or a non-negative value to enforce\n *                 it but allow for a grace period of max_records records.\n */\nvoid mbedtls_ssl_conf_renegotiation_enforced(mbedtls_ssl_config *conf, int max_records);\n\n/**\n * \\brief          Set record counter threshold for periodic renegotiation.\n *                 (Default: 2^48 - 1)\n *\n *                 Renegotiation is automatically triggered when a record\n *                 counter (outgoing or incoming) crosses the defined\n *                 threshold. The default value is meant to prevent the\n *                 connection from being closed when the counter is about to\n *                 reached its maximal value (it is not allowed to wrap).\n *\n *                 Lower values can be used to enforce policies such as \"keys\n *                 must be refreshed every N packets with cipher X\".\n *\n *                 The renegotiation period can be disabled by setting\n *                 conf->disable_renegotiation to\n *                 MBEDTLS_SSL_RENEGOTIATION_DISABLED.\n *\n * \\note           When the configured transport is\n *                 MBEDTLS_SSL_TRANSPORT_DATAGRAM the maximum renegotiation\n *                 period is 2^48 - 1, and for MBEDTLS_SSL_TRANSPORT_STREAM,\n *                 the maximum renegotiation period is 2^64 - 1.\n *\n * \\param conf     SSL configuration\n * \\param period   The threshold value: a big-endian 64-bit number.\n */\nvoid mbedtls_ssl_conf_renegotiation_period(mbedtls_ssl_config *conf,\n                                           const unsigned char period[8]);\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n\n/**\n * \\brief          Check if there is data already read from the\n *                 underlying transport but not yet processed.\n *\n * \\param ssl      SSL context\n *\n * \\return         0 if nothing's pending, 1 otherwise.\n *\n * \\note           This is different in purpose and behaviour from\n *                 \\c mbedtls_ssl_get_bytes_avail in that it considers\n *                 any kind of unprocessed data, not only unread\n *                 application data. If \\c mbedtls_ssl_get_bytes\n *                 returns a non-zero value, this function will\n *                 also signal pending data, but the converse does\n *                 not hold. For example, in DTLS there might be\n *                 further records waiting to be processed from\n *                 the current underlying transport's datagram.\n *\n * \\note           If this function returns 1 (data pending), this\n *                 does not imply that a subsequent call to\n *                 \\c mbedtls_ssl_read will provide any data;\n *                 e.g., the unprocessed data might turn out\n *                 to be an alert or a handshake message.\n *\n * \\note           This function is useful in the following situation:\n *                 If the SSL/TLS module successfully returns from an\n *                 operation - e.g. a handshake or an application record\n *                 read - and you're awaiting incoming data next, you\n *                 must not immediately idle on the underlying transport\n *                 to have data ready, but you need to check the value\n *                 of this function first. The reason is that the desired\n *                 data might already be read but not yet processed.\n *                 If, in contrast, a previous call to the SSL/TLS module\n *                 returned MBEDTLS_ERR_SSL_WANT_READ, it is not necessary\n *                 to call this function, as the latter error code entails\n *                 that all internal data has been processed.\n *\n */\nint mbedtls_ssl_check_pending(const mbedtls_ssl_context *ssl);\n\n/**\n * \\brief          Return the number of application data bytes\n *                 remaining to be read from the current record.\n *\n * \\param ssl      SSL context\n *\n * \\return         How many bytes are available in the application\n *                 data record read buffer.\n *\n * \\note           When working over a datagram transport, this is\n *                 useful to detect the current datagram's boundary\n *                 in case \\c mbedtls_ssl_read has written the maximal\n *                 amount of data fitting into the input buffer.\n *\n */\nsize_t mbedtls_ssl_get_bytes_avail(const mbedtls_ssl_context *ssl);\n\n/**\n * \\brief          Return the result of the certificate verification\n *\n * \\param ssl      The SSL context to use.\n *\n * \\return         \\c 0 if the certificate verification was successful.\n * \\return         \\c -1u if the result is not available. This may happen\n *                 e.g. if the handshake aborts early, or a verification\n *                 callback returned a fatal error.\n * \\return         A bitwise combination of \\c MBEDTLS_X509_BADCERT_XXX\n *                 and \\c MBEDTLS_X509_BADCRL_XXX failure flags; see x509.h.\n */\nuint32_t mbedtls_ssl_get_verify_result(const mbedtls_ssl_context *ssl);\n\n/**\n * \\brief          Return the id of the current ciphersuite\n *\n * \\param ssl      SSL context\n *\n * \\return         a ciphersuite id\n */\nint mbedtls_ssl_get_ciphersuite_id_from_ssl(const mbedtls_ssl_context *ssl);\n\n/**\n * \\brief          Return the name of the current ciphersuite\n *\n * \\param ssl      SSL context\n *\n * \\return         a string containing the ciphersuite name\n */\nconst char *mbedtls_ssl_get_ciphersuite(const mbedtls_ssl_context *ssl);\n\n\n/**\n * \\brief          Return the (D)TLS protocol version negotiated in the\n *                 given connection.\n *\n * \\note           If you call this function too early during the initial\n *                 handshake, before the two sides have agreed on a version,\n *                 this function returns #MBEDTLS_SSL_VERSION_UNKNOWN.\n *\n * \\param ssl      The SSL context to query.\n * \\return         The negotiated protocol version.\n */\nstatic inline mbedtls_ssl_protocol_version mbedtls_ssl_get_version_number(\n    const mbedtls_ssl_context *ssl)\n{\n    return ssl->MBEDTLS_PRIVATE(tls_version);\n}\n\n/**\n * \\brief          Return the current TLS version\n *\n * \\param ssl      SSL context\n *\n * \\return         a string containing the TLS version\n */\nconst char *mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl);\n\n/**\n * \\brief          Return the (maximum) number of bytes added by the record\n *                 layer: header + encryption/MAC overhead (inc. padding)\n *\n * \\param ssl      SSL context\n *\n * \\return         Current maximum record expansion in bytes\n */\nint mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl);\n\n/**\n * \\brief          Return the current maximum outgoing record payload in bytes.\n *\n * \\note           The logic to determine the maximum outgoing record payload is\n *                 version-specific. It takes into account various factors, such as\n *                 the mbedtls_config.h setting \\c MBEDTLS_SSL_OUT_CONTENT_LEN, extensions\n *                 such as the max fragment length or record size limit extension if\n *                 used, and for DTLS the path MTU as configured and current\n *                 record expansion.\n *\n * \\note           With DTLS, \\c mbedtls_ssl_write() will return an error if\n *                 called with a larger length value.\n *                 With TLS, \\c mbedtls_ssl_write() will fragment the input if\n *                 necessary and return the number of bytes written; it is up\n *                 to the caller to call \\c mbedtls_ssl_write() again in\n *                 order to send the remaining bytes if any.\n *\n * \\sa             mbedtls_ssl_get_max_out_record_payload()\n * \\sa             mbedtls_ssl_get_record_expansion()\n *\n * \\param ssl      SSL context\n *\n * \\return         Current maximum payload for an outgoing record,\n *                 or a negative error code.\n */\nint mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl);\n\n/**\n * \\brief          Return the current maximum incoming record payload in bytes.\n *\n * \\note           The logic to determine the maximum incoming record payload is\n *                 version-specific. It takes into account various factors, such as\n *                 the mbedtls_config.h setting \\c MBEDTLS_SSL_IN_CONTENT_LEN, extensions\n *                 such as the max fragment length extension or record size limit\n *                 extension if used, and the current record expansion.\n *\n * \\sa             mbedtls_ssl_set_mtu()\n * \\sa             mbedtls_ssl_get_max_in_record_payload()\n * \\sa             mbedtls_ssl_get_record_expansion()\n *\n * \\param ssl      SSL context\n *\n * \\return         Current maximum payload for an incoming record,\n *                 or a negative error code.\n */\nint mbedtls_ssl_get_max_in_record_payload(const mbedtls_ssl_context *ssl);\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n/**\n * \\brief          Return the peer certificate from the current connection.\n *\n * \\param  ssl     The SSL context to use. This must be initialized and setup.\n *\n * \\return         The current peer certificate, if available.\n *                 The returned certificate is owned by the SSL context and\n *                 is valid only until the next call to the SSL API.\n * \\return         \\c NULL if no peer certificate is available. This might\n *                 be because the chosen ciphersuite doesn't use CRTs\n *                 (PSK-based ciphersuites, for example), or because\n *                 #MBEDTLS_SSL_KEEP_PEER_CERTIFICATE has been disabled,\n *                 allowing the stack to free the peer's CRT to save memory.\n *\n * \\note           For one-time inspection of the peer's certificate during\n *                 the handshake, consider registering an X.509 CRT verification\n *                 callback through mbedtls_ssl_conf_verify() instead of calling\n *                 this function. Using mbedtls_ssl_conf_verify() also comes at\n *                 the benefit of allowing you to influence the verification\n *                 process, for example by masking expected and tolerated\n *                 verification failures.\n *\n * \\warning        You must not use the pointer returned by this function\n *                 after any further call to the SSL API, including\n *                 mbedtls_ssl_read() and mbedtls_ssl_write(); this is\n *                 because the pointer might change during renegotiation,\n *                 which happens transparently to the user.\n *                 If you want to use the certificate across API calls,\n *                 you must make a copy.\n */\nconst mbedtls_x509_crt *mbedtls_ssl_get_peer_cert(const mbedtls_ssl_context *ssl);\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n#if defined(MBEDTLS_SSL_CLI_C)\n/**\n * \\brief          Export a session in order to resume it later.\n *\n * \\param ssl      The SSL context representing the connection for which to\n *                 to export a session structure for later resumption.\n * \\param session  The target structure in which to store the exported session.\n *                 This must have been initialized with mbedtls_ssl_session_init()\n *                 but otherwise be unused.\n *\n * \\note           This function can handle a variety of mechanisms for session\n *                 resumption: For TLS 1.2, both session ID-based resumption and\n *                 ticket-based resumption will be considered. For TLS 1.3,\n *                 sessions equate to tickets, and if session tickets are\n *                 enabled (see #MBEDTLS_SSL_SESSION_TICKETS configuration\n *                 option), this function exports the last received ticket and\n *                 the exported session may be used to resume the TLS 1.3\n *                 session. If session tickets are disabled, exported sessions\n *                 cannot be used to resume a TLS 1.3 session.\n *\n * \\return         \\c 0 if successful. In this case, \\p session can be used for\n *                 session resumption by passing it to mbedtls_ssl_set_session(),\n *                 and serialized for storage via mbedtls_ssl_session_save().\n * \\return         Another negative error code on other kinds of failure.\n *\n * \\sa             mbedtls_ssl_set_session()\n * \\sa             mbedtls_ssl_session_save()\n */\nint mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl,\n                            mbedtls_ssl_session *session);\n#endif /* MBEDTLS_SSL_CLI_C */\n\n/**\n * \\brief          Perform the SSL handshake\n *\n * \\param ssl      SSL context\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE\n *                 if the handshake is incomplete and waiting for data to\n *                 be available for reading from or writing to the underlying\n *                 transport - in this case you must call this function again\n *                 when the underlying transport is ready for the operation.\n * \\return         #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous\n *                 operation is in progress (see\n *                 mbedtls_ssl_conf_async_private_cb()) - in this case you\n *                 must call this function again when the operation is ready.\n * \\return         #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic\n *                 operation is in progress (see mbedtls_ecp_set_max_ops()) -\n *                 in this case you must call this function again to complete\n *                 the handshake when you're done attending other tasks.\n * \\return         #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use\n *                 and the client did not demonstrate reachability yet - in\n *                 this case you must stop using the context (see below).\n * \\return         #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET if a TLS 1.3\n *                 NewSessionTicket message has been received. See the\n *                 documentation of mbedtls_ssl_read() for more information\n *                 about this error code.\n * \\return         #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as\n *                 defined in RFC 8446 (TLS 1.3 specification), has been\n *                 received as part of the handshake. This is server specific\n *                 and may occur only if the early data feature has been\n *                 enabled on server (see mbedtls_ssl_conf_early_data()\n *                 documentation). You must call mbedtls_ssl_read_early_data()\n *                 to read the early data before resuming the handshake.\n * \\return         Another SSL error code - in this case you must stop using\n *                 the context (see below).\n *\n * \\warning        If this function returns something other than\n *                 \\c 0,\n *                 #MBEDTLS_ERR_SSL_WANT_READ,\n *                 #MBEDTLS_ERR_SSL_WANT_WRITE,\n *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or\n *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or\n *                 #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or\n *                 #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA,\n *                 you must stop using the SSL context for reading or writing,\n *                 and either free it or call \\c mbedtls_ssl_session_reset()\n *                 on it before re-using it for a new connection; the current\n *                 connection must be closed.\n *\n * \\note           If DTLS is in use, then you may choose to handle\n *                 #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging\n *                 purposes, as it is an expected return value rather than an\n *                 actual error, but you still need to reset/free the context.\n *\n * \\note           Remarks regarding event-driven DTLS:\n *                 If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram\n *                 from the underlying transport layer is currently being processed,\n *                 and it is safe to idle until the timer or the underlying transport\n *                 signal a new event. This is not true for a successful handshake,\n *                 in which case the datagram of the underlying transport that is\n *                 currently being processed might or might not contain further\n *                 DTLS records.\n *\n * \\note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                 subsystem must have been initialized by calling\n *                 psa_crypto_init() before calling this function.\n *                 Otherwise, the handshake may call psa_crypto_init()\n *                 if a negotiation involving TLS 1.3 takes place (this may\n *                 be the case even if TLS 1.3 is offered but eventually\n *                 not selected).\n *\n * \\note           In TLS, reception of fragmented handshake messages is\n *                 supported with some limitations (those limitations do\n *                 not apply to DTLS, where defragmentation is fully\n *                 supported):\n *                 - On an Mbed TLS server that only accepts TLS 1.2,\n *                   the initial ClientHello message must not be fragmented.\n *                   A TLS 1.2 ClientHello may be fragmented if the server\n *                   also accepts TLS 1.3 connections (meaning\n *                   that #MBEDTLS_SSL_PROTO_TLS1_3 enabled, and the\n *                   accepted versions have not been restricted with\n *                   mbedtls_ssl_conf_max_tls_version() or the like).\n *                 - The first fragment of a handshake message must be\n *                   at least 4 bytes long.\n *                 - Non-handshake records must not be interleaved between\n *                   the fragments of a handshake message. (This is permitted\n *                   in TLS 1.2 but not in TLS 1.3, but Mbed TLS rejects it\n *                   even in TLS 1.2.)\n */\nint mbedtls_ssl_handshake(mbedtls_ssl_context *ssl);\n\n/**\n * \\brief          After calling mbedtls_ssl_handshake() to start the SSL\n *                 handshake you can call this function to check whether the\n *                 handshake is over for a given SSL context. This function\n *                 should be also used to determine when to stop calling\n *                 mbedtls_handshake_step() for that context.\n *\n * \\param ssl      SSL context\n *\n * \\return         \\c 1 if handshake is over, \\c 0 if it is still ongoing.\n */\nstatic inline int mbedtls_ssl_is_handshake_over(mbedtls_ssl_context *ssl)\n{\n    return ssl->MBEDTLS_PRIVATE(state) >= MBEDTLS_SSL_HANDSHAKE_OVER;\n}\n\n/**\n * \\brief          Perform a single step of the SSL handshake\n *\n * \\note           The state of the context (ssl->state) will be at\n *                 the next state after this function returns \\c 0. Do not\n *                 call this function if mbedtls_ssl_is_handshake_over()\n *                 returns \\c 1.\n *\n * \\warning        Whilst in the past you may have used direct access to the\n *                 context state (ssl->state) in order to ascertain when to\n *                 stop calling this function and although you can still do\n *                 so with something like ssl->MBEDTLS_PRIVATE(state) or by\n *                 defining MBEDTLS_ALLOW_PRIVATE_ACCESS, this is now\n *                 considered deprecated and could be broken in any future\n *                 release. If you still find you have good reason for such\n *                 direct access, then please do contact the team to explain\n *                 this (raise an issue or post to the mailing list), so that\n *                 we can add a solution to your problem that will be\n *                 guaranteed to work in the future.\n *\n * \\param ssl      SSL context\n *\n * \\return         See mbedtls_ssl_handshake().\n *\n * \\warning        If this function returns something other than \\c 0,\n *                 #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE,\n *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS,\n *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or\n *                 #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or\n *                 #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA, you must stop using\n *                 the SSL context for reading or writing, and either free it\n *                 or call \\c mbedtls_ssl_session_reset() on it before\n *                 re-using it for a new connection; the current connection\n *                 must be closed.\n */\nint mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl);\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n/**\n * \\brief          Initiate an SSL renegotiation on the running connection.\n *                 Client: perform the renegotiation right now.\n *                 Server: request renegotiation, which will be performed\n *                 during the next call to mbedtls_ssl_read() if honored by\n *                 client.\n *\n * \\param ssl      SSL context\n *\n * \\return         0 if successful, or any mbedtls_ssl_handshake() return\n *                 value except #MBEDTLS_ERR_SSL_CLIENT_RECONNECT that can't\n *                 happen during a renegotiation.\n *\n * \\warning        If this function returns something other than \\c 0,\n *                 #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE,\n *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or\n *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using\n *                 the SSL context for reading or writing, and either free it\n *                 or call \\c mbedtls_ssl_session_reset() on it before\n *                 re-using it for a new connection; the current connection\n *                 must be closed.\n *\n */\nint mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl);\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n\n/**\n * \\brief          Read at most 'len' application data bytes\n *\n * \\param ssl      SSL context\n * \\param buf      buffer that will hold the data\n * \\param len      maximum number of bytes to read\n *\n * \\return         The (positive) number of bytes read if successful.\n * \\return         \\c 0 if the read end of the underlying transport was closed\n *                 without sending a CloseNotify beforehand, which might happen\n *                 because of various reasons (internal error of an underlying\n *                 stack, non-conformant peer not sending a CloseNotify and\n *                 such) - in this case you must stop using the context\n *                 (see below).\n * \\return         #MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY if the underlying\n *                 transport is still functional, but the peer has\n *                 acknowledged to not send anything anymore.\n * \\return         #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE\n *                 if the handshake is incomplete and waiting for data to\n *                 be available for reading from or writing to the underlying\n *                 transport - in this case you must call this function again\n *                 when the underlying transport is ready for the operation.\n * \\return         #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous\n *                 operation is in progress (see\n *                 mbedtls_ssl_conf_async_private_cb()) - in this case you\n *                 must call this function again when the operation is ready.\n * \\return         #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic\n *                 operation is in progress (see mbedtls_ecp_set_max_ops()) -\n *                 in this case you must call this function again to complete\n *                 the handshake when you're done attending other tasks.\n * \\return         #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server\n *                 side of a DTLS connection and the client is initiating a\n *                 new connection using the same source port. See below.\n * \\return         #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET if a TLS 1.3\n *                 NewSessionTicket message has been received.\n *                 This error code is only returned on the client side. It is\n *                 only returned if handling of TLS 1.3 NewSessionTicket\n *                 messages has been enabled through\n *                 mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets().\n *                 This error code indicates that a TLS 1.3 NewSessionTicket\n *                 message has been received and parsed successfully by the\n *                 client. The ticket data can be retrieved from the SSL\n *                 context by calling mbedtls_ssl_get_session(). It remains\n *                 available until the next call to mbedtls_ssl_read().\n * \\return         #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as\n *                 defined in RFC 8446 (TLS 1.3 specification), has been\n *                 received as part of the handshake. This is server specific\n *                 and may occur only if the early data feature has been\n *                 enabled on server (see mbedtls_ssl_conf_early_data()\n *                 documentation). You must call mbedtls_ssl_read_early_data()\n *                 to read the early data before resuming the handshake.\n * \\return         Another SSL error code - in this case you must stop using\n *                 the context (see below).\n *\n * \\warning        If this function returns something other than\n *                 a positive value,\n *                 #MBEDTLS_ERR_SSL_WANT_READ,\n *                 #MBEDTLS_ERR_SSL_WANT_WRITE,\n *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS,\n *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS,\n *                 #MBEDTLS_ERR_SSL_CLIENT_RECONNECT or\n *                 #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or\n *                 #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA,\n *                 you must stop using the SSL context for reading or writing,\n *                 and either free it or call \\c mbedtls_ssl_session_reset()\n *                 on it before re-using it for a new connection; the current\n *                 connection must be closed.\n *\n * \\note           When this function returns #MBEDTLS_ERR_SSL_CLIENT_RECONNECT\n *                 (which can only happen server-side), it means that a client\n *                 is initiating a new connection using the same source port.\n *                 You can either treat that as a connection close and wait\n *                 for the client to resend a ClientHello, or directly\n *                 continue with \\c mbedtls_ssl_handshake() with the same\n *                 context (as it has been reset internally). Either way, you\n *                 must make sure this is seen by the application as a new\n *                 connection: application state, if any, should be reset, and\n *                 most importantly the identity of the client must be checked\n *                 again. WARNING: not validating the identity of the client\n *                 again, or not transmitting the new identity to the\n *                 application layer, would allow authentication bypass!\n *\n * \\note           Remarks regarding event-driven DTLS:\n *                 - If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram\n *                   from the underlying transport layer is currently being processed,\n *                   and it is safe to idle until the timer or the underlying transport\n *                   signal a new event.\n *                 - This function may return MBEDTLS_ERR_SSL_WANT_READ even if data was\n *                   initially available on the underlying transport, as this data may have\n *                   been only e.g. duplicated messages or a renegotiation request.\n *                   Therefore, you must be prepared to receive MBEDTLS_ERR_SSL_WANT_READ even\n *                   when reacting to an incoming-data event from the underlying transport.\n *                 - On success, the datagram of the underlying transport that is currently\n *                   being processed may contain further DTLS records. You should call\n *                   \\c mbedtls_ssl_check_pending to check for remaining records.\n *\n */\nint mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len);\n\n/**\n * \\brief          Try to write exactly 'len' application data bytes\n *\n * \\warning        This function will do partial writes in some cases. If the\n *                 return value is non-negative but less than length, the\n *                 function must be called again with updated arguments:\n *                 buf + ret, len - ret (if ret is the return value) until\n *                 it returns a value equal to the last 'len' argument.\n *\n * \\param ssl      SSL context\n * \\param buf      buffer holding the data\n * \\param len      how many bytes must be written\n *\n * \\return         The (non-negative) number of bytes actually written if\n *                 successful (may be less than \\p len).\n * \\return         #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE\n *                 if the handshake is incomplete and waiting for data to\n *                 be available for reading from or writing to the underlying\n *                 transport - in this case you must call this function again\n *                 when the underlying transport is ready for the operation.\n * \\return         #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous\n *                 operation is in progress (see\n *                 mbedtls_ssl_conf_async_private_cb()) - in this case you\n *                 must call this function again when the operation is ready.\n * \\return         #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic\n *                 operation is in progress (see mbedtls_ecp_set_max_ops()) -\n *                 in this case you must call this function again to complete\n *                 the handshake when you're done attending other tasks.\n * \\return         #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET if a TLS 1.3\n *                 NewSessionTicket message has been received. See the\n *                 documentation of mbedtls_ssl_read() for more information\n *                 about this error code.\n * \\return         #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as\n *                 defined in RFC 8446 (TLS 1.3 specification), has been\n *                 received as part of the handshake. This is server specific\n *                 and may occur only if the early data feature has been\n *                 enabled on server (see mbedtls_ssl_conf_early_data()\n *                 documentation). You must call mbedtls_ssl_read_early_data()\n *                 to read the early data before resuming the handshake.\n * \\return         Another SSL error code - in this case you must stop using\n *                 the context (see below).\n *\n * \\warning        If this function returns something other than\n *                 a non-negative value,\n *                 #MBEDTLS_ERR_SSL_WANT_READ,\n *                 #MBEDTLS_ERR_SSL_WANT_WRITE,\n *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS,\n *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or\n *                 #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or\n *                 #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA,\n *                 you must stop using the SSL context for reading or writing,\n *                 and either free it or call \\c mbedtls_ssl_session_reset()\n *                 on it before re-using it for a new connection; the current\n *                 connection must be closed.\n *\n * \\note           When this function returns #MBEDTLS_ERR_SSL_WANT_WRITE/READ,\n *                 it must be called later with the *same* arguments,\n *                 until it returns a value greater than or equal to 0. When\n *                 the function returns #MBEDTLS_ERR_SSL_WANT_WRITE there may be\n *                 some partial data in the output buffer, however this is not\n *                 yet sent.\n *\n * \\note           If the requested length is greater than the maximum\n *                 fragment length (either the built-in limit or the one set\n *                 or negotiated with the peer), then:\n *                 - with TLS, less bytes than requested are written.\n *                 - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned.\n *                 \\c mbedtls_ssl_get_max_out_record_payload() may be used to\n *                 query the active maximum fragment length.\n *\n * \\note           Attempting to write 0 bytes will result in an empty TLS\n *                 application record being sent.\n */\nint mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len);\n\n/**\n * \\brief           Send an alert message\n *\n * \\param ssl       SSL context\n * \\param level     The alert level of the message\n *                  (MBEDTLS_SSL_ALERT_LEVEL_WARNING or MBEDTLS_SSL_ALERT_LEVEL_FATAL)\n * \\param message   The alert message (SSL_ALERT_MSG_*)\n *\n * \\return          0 if successful, or a specific SSL error code.\n *\n * \\note           If this function returns something other than 0 or\n *                 MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using\n *                 the SSL context for reading or writing, and either free it or\n *                 call \\c mbedtls_ssl_session_reset() on it before re-using it\n *                 for a new connection; the current connection must be closed.\n */\nint mbedtls_ssl_send_alert_message(mbedtls_ssl_context *ssl,\n                                   unsigned char level,\n                                   unsigned char message);\n/**\n * \\brief          Notify the peer that the connection is being closed\n *\n * \\param ssl      SSL context\n *\n * \\return          0 if successful, or a specific SSL error code.\n *\n * \\note           If this function returns something other than 0 or\n *                 MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using\n *                 the SSL context for reading or writing, and either free it or\n *                 call \\c mbedtls_ssl_session_reset() on it before re-using it\n *                 for a new connection; the current connection must be closed.\n */\nint mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl);\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n\n#if defined(MBEDTLS_SSL_SRV_C)\n/**\n * \\brief          Read at most 'len' bytes of early data\n *\n * \\note           This API is server specific.\n *\n * \\warning        Early data is defined in the TLS 1.3 specification, RFC 8446.\n *                 IMPORTANT NOTE from section 2.3 of the specification:\n *\n *                 The security properties for 0-RTT data are weaker than\n *                 those for other kinds of TLS data. Specifically:\n *                 - This data is not forward secret, as it is encrypted\n *                   solely under keys derived using the offered PSK.\n *                 - There are no guarantees of non-replay between connections.\n *                   Protection against replay for ordinary TLS 1.3 1-RTT data\n *                   is provided via the server's Random value, but 0-RTT data\n *                   does not depend on the ServerHello and therefore has\n *                   weaker guarantees. This is especially relevant if the\n *                   data is authenticated either with TLS client\n *                   authentication or inside the application protocol. The\n *                   same warnings apply to any use of the\n *                   early_exporter_master_secret.\n *\n * \\warning        Mbed TLS does not implement any of the anti-replay defenses\n *                 defined in section 8 of the TLS 1.3 specification:\n *                 single-use of tickets or ClientHello recording within a\n *                 given time window.\n *\n * \\note           This function is used in conjunction with\n *                 mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(),\n *                 mbedtls_ssl_read() and mbedtls_ssl_write() to read early\n *                 data when these functions return\n *                 #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA.\n *\n * \\param ssl      SSL context, it must have been initialized and set up.\n * \\param buf      buffer that will hold the data\n * \\param len      maximum number of bytes to read\n *\n * \\return         The (positive) number of bytes read if successful.\n * \\return         #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid.\n * \\return         #MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA if it is not\n *                 possible to read early data for the SSL context \\p ssl. Note\n *                 that this function is intended to be called for an SSL\n *                 context \\p ssl only after a call to mbedtls_ssl_handshake(),\n *                 mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or\n *                 mbedtls_ssl_write() for \\p ssl that has returned\n *                 #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA.\n */\nint mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl,\n                                unsigned char *buf, size_t len);\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_SSL_CLI_C)\n/**\n * \\brief          Try to write exactly 'len' application data bytes while\n *                 performing the handshake (early data).\n *\n * \\warning        Early data is defined in the TLS 1.3 specification, RFC 8446.\n *                 IMPORTANT NOTE from section 2.3 of the specification:\n *\n *                 The security properties for 0-RTT data are weaker than\n *                 those for other kinds of TLS data. Specifically:\n *                 - This data is not forward secret, as it is encrypted\n *                   solely under keys derived using the offered PSK.\n *                 - There are no guarantees of non-replay between connections.\n *                   Protection against replay for ordinary TLS 1.3 1-RTT data\n *                   is provided via the server's Random value, but 0-RTT data\n *                   does not depend on the ServerHello and therefore has\n *                   weaker guarantees. This is especially relevant if the\n *                   data is authenticated either with TLS client\n *                   authentication or inside the application protocol. The\n *                   same warnings apply to any use of the\n *                   early_exporter_master_secret.\n *\n * \\note           This function behaves mainly as mbedtls_ssl_write(). The\n *                 specification of mbedtls_ssl_write() relevant to TLS 1.3\n *                 (thus not the parts specific to (D)TLS1.2) applies to this\n *                 function and the present documentation is mainly restricted\n *                 to the differences with mbedtls_ssl_write(). One noticeable\n *                 difference though is that mbedtls_ssl_write() aims to\n *                 complete the handshake before to write application data\n *                 while mbedtls_ssl_write_early() aims to drive the handshake\n *                 just past the point where it is not possible to send early\n *                 data anymore.\n *\n * \\param ssl      SSL context\n * \\param buf      buffer holding the data\n * \\param len      how many bytes must be written\n *\n * \\return         The (non-negative) number of bytes actually written if\n *                 successful (may be less than \\p len).\n *\n * \\return         One additional specific error code compared to\n *                 mbedtls_ssl_write():\n *                 #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA.\n *\n *                 #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA is returned when it\n *                 is not possible to write early data for the SSL context\n *                 \\p ssl.\n *\n *                 It may have been possible and it is not possible\n *                 anymore because the client received the server Finished\n *                 message, the server rejected early data or the maximum\n *                 number of allowed early data for the PSK in use has been\n *                 reached.\n *\n *                 It may never have been possible and will never be possible\n *                 for the SSL context \\p ssl because the use of early data\n *                 is disabled for that context or more generally the context\n *                 is not suitably configured to enable early data or the first\n *                 call to the function was done while the handshake was\n *                 already completed.\n *\n *                 It is not possible to write early data for the SSL context\n *                 \\p ssl and any subsequent call to this API will return this\n *                 error code. But this does not preclude for using it with\n *                 mbedtls_ssl_write(), mbedtls_ssl_read() or\n *                 mbedtls_ssl_handshake() and the handshake can be\n *                 completed by calling one of these APIs.\n *\n * \\note           This function may write early data only if the SSL context\n *                 has been configured for the handshake with a PSK for which\n *                 early data is allowed.\n *\n * \\note           To maximize the number of early data that can be written in\n *                 the course of the handshake, it is expected that this\n *                 function starts the handshake for the SSL context \\p ssl.\n *                 But this is not mandatory.\n *\n * \\note           This function does not provide any information on whether\n *                 the server has accepted or will accept early data or not.\n *                 When it returns a positive value, it just means that it\n *                 has written early data to the server. To know whether the\n *                 server has accepted early data or not, you should call\n *                 mbedtls_ssl_get_early_data_status() with the handshake\n *                 completed.\n */\nint mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl,\n                                 const unsigned char *buf, size_t len);\n\n/**\n * \\brief Get the status of the negotiation of the use of early data.\n *\n * \\param ssl      The SSL context to query\n *\n * \\return         #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called\n *                 from the server-side.\n *\n * \\return         #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called\n *                 prior to completion of the handshake.\n *\n * \\return         #MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED if the client\n *                 has not indicated the use of early data to the server.\n *\n * \\return         #MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED if the client has\n *                 indicated the use of early data and the server has accepted\n *                 it.\n *\n * \\return         #MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED if the client has\n *                 indicated the use of early data but the server has rejected\n *                 it. In this situation, the client may want to re-send the\n *                 early data it may have tried to send by calling\n *                 mbedtls_ssl_write_early_data() as ordinary post-handshake\n *                 application data by calling mbedtls_ssl_write().\n *\n */\nint mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl);\n#endif /* MBEDTLS_SSL_CLI_C */\n\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n/**\n * \\brief          Free referenced items in an SSL context and clear memory\n *\n * \\param ssl      SSL context\n */\nvoid mbedtls_ssl_free(mbedtls_ssl_context *ssl);\n\n#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)\n/**\n * \\brief          Save an active connection as serialized data in a buffer.\n *                 This allows the freeing or re-using of the SSL context\n *                 while still picking up the connection later in a way that\n *                 it entirely transparent to the peer.\n *\n * \\see            mbedtls_ssl_context_load()\n *\n * \\note           The serialized data only contains the data that is\n *                 necessary to resume the connection: negotiated protocol\n *                 options, session identifier, keys, etc.\n *                 Loading a saved SSL context does not restore settings and\n *                 state related to how the application accesses the context,\n *                 such as configured callback functions, user data, pending\n *                 incoming or outgoing data, etc.\n *\n * \\note           This feature is currently only available under certain\n *                 conditions, see the documentation of the return value\n *                 #MBEDTLS_ERR_SSL_BAD_INPUT_DATA for details.\n *\n * \\note           When this function succeeds, it calls\n *                 mbedtls_ssl_session_reset() on \\p ssl which as a result is\n *                 no longer associated with the connection that has been\n *                 serialized. This avoids creating copies of the connection\n *                 state. You're then free to either re-use the context\n *                 structure for a different connection, or call\n *                 mbedtls_ssl_free() on it. See the documentation of\n *                 mbedtls_ssl_session_reset() for more details.\n *\n * \\param ssl      The SSL context to save. On success, it is no longer\n *                 associated with the connection that has been serialized.\n * \\param buf      The buffer to write the serialized data to. It must be a\n *                 writeable buffer of at least \\p buf_len bytes, or may be \\c\n *                 NULL if \\p buf_len is \\c 0.\n * \\param buf_len  The number of bytes available for writing in \\p buf.\n * \\param olen     The size in bytes of the data that has been or would have\n *                 been written. It must point to a valid \\c size_t.\n *\n * \\note           \\p olen is updated to the correct value regardless of\n *                 whether \\p buf_len was large enough. This makes it possible\n *                 to determine the necessary size by calling this function\n *                 with \\p buf set to \\c NULL and \\p buf_len to \\c 0. However,\n *                 the value of \\p olen is only guaranteed to be correct when\n *                 the function returns #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL or\n *                 \\c 0. If the return value is different, then the value of\n *                 \\p olen is undefined.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \\p buf is too small.\n * \\return         #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed\n *                 while resetting the context.\n * \\return         #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handshake is in\n *                 progress, or there is pending data for reading or sending,\n *                 or the connection does not use DTLS 1.2 with an AEAD\n *                 ciphersuite, or renegotiation is enabled.\n */\nint mbedtls_ssl_context_save(mbedtls_ssl_context *ssl,\n                             unsigned char *buf,\n                             size_t buf_len,\n                             size_t *olen);\n\n/**\n * \\brief          Load serialized connection data to an SSL context.\n *\n * \\see            mbedtls_ssl_context_save()\n *\n * \\warning        The same serialized data must never be loaded into more\n *                 that one context. In order to ensure that, after\n *                 successfully loading serialized data to an SSL context, you\n *                 should immediately destroy or invalidate all copies of the\n *                 serialized data that was loaded. Loading the same data in\n *                 more than one context would cause severe security failures\n *                 including but not limited to loss of confidentiality.\n *\n * \\note           Before calling this function, the SSL context must be\n *                 prepared in one of the two following ways. The first way is\n *                 to take a context freshly initialised with\n *                 mbedtls_ssl_init() and call mbedtls_ssl_setup() on it with\n *                 the same ::mbedtls_ssl_config structure that was used in\n *                 the original connection. The second way is to\n *                 call mbedtls_ssl_session_reset() on a context that was\n *                 previously prepared as above but used in the meantime.\n *                 Either way, you must not use the context to perform a\n *                 handshake between calling mbedtls_ssl_setup() or\n *                 mbedtls_ssl_session_reset() and calling this function. You\n *                 may however call other setter functions in that time frame\n *                 as indicated in the note below.\n *\n * \\note           Before or after calling this function successfully, you\n *                 also need to configure some connection-specific callbacks\n *                 and settings before you can use the connection again\n *                 (unless they were already set before calling\n *                 mbedtls_ssl_session_reset() and the values are suitable for\n *                 the present connection). Specifically, you want to call\n *                 at least mbedtls_ssl_set_bio(),\n *                 mbedtls_ssl_set_timer_cb(), and\n *                 mbedtls_ssl_set_user_data_n() or\n *                 mbedtls_ssl_set_user_data_p() if they were set originally.\n *                 All other SSL setter functions\n *                 are not necessary to call, either because they're only used\n *                 in handshakes, or because the setting is already saved. You\n *                 might choose to call them anyway, for example in order to\n *                 share code between the cases of establishing a new\n *                 connection and the case of loading an already-established\n *                 connection.\n *\n * \\note           If you have new information about the path MTU, you want to\n *                 call mbedtls_ssl_set_mtu() after calling this function, as\n *                 otherwise this function would overwrite your\n *                 newly-configured value with the value that was active when\n *                 the context was saved.\n *\n * \\note           When this function returns an error code, it calls\n *                 mbedtls_ssl_free() on \\p ssl. In this case, you need to\n *                 prepare the context with the usual sequence starting with a\n *                 call to mbedtls_ssl_init() if you want to use it again.\n *\n * \\param ssl      The SSL context structure to be populated. It must have\n *                 been prepared as described in the note above.\n * \\param buf      The buffer holding the serialized connection data. It must\n *                 be a readable buffer of at least \\p len bytes.\n * \\param len      The size of the serialized data in bytes.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed.\n * \\return         #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data\n *                 comes from a different Mbed TLS version or build.\n * \\return         #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid.\n */\nint mbedtls_ssl_context_load(mbedtls_ssl_context *ssl,\n                             const unsigned char *buf,\n                             size_t len);\n#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */\n\n/**\n * \\brief          Initialize an SSL configuration context\n *                 Just makes the context ready for\n *                 mbedtls_ssl_config_defaults() or mbedtls_ssl_config_free().\n *\n * \\note           You need to call mbedtls_ssl_config_defaults() unless you\n *                 manually set all of the relevant fields yourself.\n *\n * \\param conf     SSL configuration context\n */\nvoid mbedtls_ssl_config_init(mbedtls_ssl_config *conf);\n\n/**\n * \\brief          Load reasonable default SSL configuration values.\n *                 (You need to call mbedtls_ssl_config_init() first.)\n *\n * \\param conf     SSL configuration context\n * \\param endpoint MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER\n * \\param transport MBEDTLS_SSL_TRANSPORT_STREAM for TLS, or\n *                  MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS\n * \\param preset   a MBEDTLS_SSL_PRESET_XXX value\n *\n * \\note           See \\c mbedtls_ssl_conf_transport() for notes on DTLS.\n *\n * \\return         0 if successful, or\n *                 MBEDTLS_ERR_XXX_ALLOC_FAILED on memory allocation error.\n */\nint mbedtls_ssl_config_defaults(mbedtls_ssl_config *conf,\n                                int endpoint, int transport, int preset);\n\n/**\n * \\brief          Free an SSL configuration context\n *\n * \\param conf     SSL configuration context\n */\nvoid mbedtls_ssl_config_free(mbedtls_ssl_config *conf);\n\n/**\n * \\brief          Initialize SSL session structure\n *\n * \\param session  SSL session\n */\nvoid mbedtls_ssl_session_init(mbedtls_ssl_session *session);\n\n/**\n * \\brief          Free referenced items in an SSL session including the\n *                 peer certificate and clear memory\n *\n * \\note           A session object can be freed even if the SSL context\n *                 that was used to retrieve the session is still in use.\n *\n * \\param session  SSL session\n */\nvoid mbedtls_ssl_session_free(mbedtls_ssl_session *session);\n\n/**\n * \\brief          TLS-PRF function for key derivation.\n *\n * \\param prf      The tls_prf type function type to be used.\n * \\param secret   Secret for the key derivation function.\n * \\param slen     Length of the secret.\n * \\param label    String label for the key derivation function,\n *                 terminated with null character.\n * \\param random   Random bytes.\n * \\param rlen     Length of the random bytes buffer.\n * \\param dstbuf   The buffer holding the derived key.\n * \\param dlen     Length of the output buffer.\n *\n * \\return         0 on success. An SSL specific error on failure.\n */\nint  mbedtls_ssl_tls_prf(const mbedtls_tls_prf_types prf,\n                         const unsigned char *secret, size_t slen,\n                         const char *label,\n                         const unsigned char *random, size_t rlen,\n                         unsigned char *dstbuf, size_t dlen);\n\n#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT)\n/* Maximum value for key_len in mbedtls_ssl_export_keying material. Depending on the TLS\n * version and the negotiated ciphersuite, larger keys could in principle be exported,\n * but for simplicity, we define one limit that works in all cases. TLS 1.3 with SHA256\n * has the strictest limit: 255 blocks of SHA256 output, or 8160 bytes. */\n#define MBEDTLS_SSL_EXPORT_MAX_KEY_LEN 8160\n\n/**\n * \\brief             TLS-Exporter to derive shared symmetric keys between server and client.\n *\n * \\param ssl         SSL context from which to export keys. Must have finished the handshake.\n * \\param out         Output buffer of length at least key_len bytes.\n * \\param key_len     Length of the key to generate in bytes, must be at most\n *                    MBEDTLS_SSL_EXPORT_MAX_KEY_LEN (8160).\n * \\param label       Label for which to generate the key of length label_len.\n * \\param label_len   Length of label in bytes. Must be at most 249 in TLS 1.3.\n * \\param context     Context of the key. Can be NULL if context_len or use_context is 0.\n * \\param context_len Length of context. Must be < 2^16 in TLS 1.2.\n * \\param use_context Indicates if a context should be used in deriving the key.\n *\n * \\note TLS 1.2 makes a distinction between a 0-length context and no context.\n *       This is why the use_context argument exists. TLS 1.3 does not make\n *       this distinction. If use_context is 0 and TLS 1.3 is used, context and\n *       context_len are ignored and a 0-length context is used.\n *\n * \\return            0 on success.\n * \\return            MBEDTLS_ERR_SSL_BAD_INPUT_DATA if the handshake is not yet completed.\n * \\return            An SSL-specific error on failure.\n */\nint mbedtls_ssl_export_keying_material(mbedtls_ssl_context *ssl,\n                                       uint8_t *out, const size_t key_len,\n                                       const char *label, const size_t label_len,\n                                       const unsigned char *context, const size_t context_len,\n                                       const int use_context);\n#endif\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* ssl.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/ssl_cache.h",
    "content": "/**\n * \\file ssl_cache.h\n *\n * \\brief SSL session cache implementation\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_SSL_CACHE_H\n#define MBEDTLS_SSL_CACHE_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/ssl.h\"\n\n#if defined(MBEDTLS_THREADING_C)\n#include \"mbedtls/threading.h\"\n#endif\n\n/**\n * \\name SECTION: Module settings\n *\n * The configuration options you can set for this module are in this section.\n * Either change them in mbedtls_config.h or define them on the compiler command line.\n * \\{\n */\n\n#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT)\n#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT       86400   /*!< 1 day  */\n#endif\n\n#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES)\n#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES      50   /*!< Maximum entries in cache */\n#endif\n\n/** \\} name SECTION: Module settings */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct mbedtls_ssl_cache_context mbedtls_ssl_cache_context;\ntypedef struct mbedtls_ssl_cache_entry mbedtls_ssl_cache_entry;\n\n/**\n * \\brief   This structure is used for storing cache entries\n */\nstruct mbedtls_ssl_cache_entry {\n#if defined(MBEDTLS_HAVE_TIME)\n    mbedtls_time_t MBEDTLS_PRIVATE(timestamp);           /*!< entry timestamp    */\n#endif\n\n    unsigned char MBEDTLS_PRIVATE(session_id)[32];       /*!< session ID         */\n    size_t MBEDTLS_PRIVATE(session_id_len);\n\n    unsigned char *MBEDTLS_PRIVATE(session);             /*!< serialized session */\n    size_t MBEDTLS_PRIVATE(session_len);\n\n    mbedtls_ssl_cache_entry *MBEDTLS_PRIVATE(next);      /*!< chain pointer      */\n};\n\n/**\n * \\brief Cache context\n */\nstruct mbedtls_ssl_cache_context {\n    mbedtls_ssl_cache_entry *MBEDTLS_PRIVATE(chain);     /*!< start of the chain     */\n    int MBEDTLS_PRIVATE(timeout);                /*!< cache entry timeout    */\n    int MBEDTLS_PRIVATE(max_entries);            /*!< maximum entries        */\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex);    /*!< mutex                  */\n#endif\n};\n\n/**\n * \\brief          Initialize an SSL cache context\n *\n * \\param cache    SSL cache context\n */\nvoid mbedtls_ssl_cache_init(mbedtls_ssl_cache_context *cache);\n\n/**\n * \\brief          Cache get callback implementation\n *                 (Thread-safe if MBEDTLS_THREADING_C is enabled)\n *\n * \\param data            The SSL cache context to use.\n * \\param session_id      The pointer to the buffer holding the session ID\n *                        for the session to load.\n * \\param session_id_len  The length of \\p session_id in bytes.\n * \\param session         The address at which to store the session\n *                        associated with \\p session_id, if present.\n *\n * \\return                \\c 0 on success.\n * \\return                #MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND if there is\n *                        no cache entry with specified session ID found, or\n *                        any other negative error code for other failures.\n */\nint mbedtls_ssl_cache_get(void *data,\n                          unsigned char const *session_id,\n                          size_t session_id_len,\n                          mbedtls_ssl_session *session);\n\n/**\n * \\brief          Cache set callback implementation\n *                 (Thread-safe if MBEDTLS_THREADING_C is enabled)\n *\n * \\param data            The SSL cache context to use.\n * \\param session_id      The pointer to the buffer holding the session ID\n *                        associated to \\p session.\n * \\param session_id_len  The length of \\p session_id in bytes.\n * \\param session         The session to store.\n *\n * \\return                \\c 0 on success.\n * \\return                A negative error code on failure.\n */\nint mbedtls_ssl_cache_set(void *data,\n                          unsigned char const *session_id,\n                          size_t session_id_len,\n                          const mbedtls_ssl_session *session);\n\n/**\n * \\brief          Remove the cache entry by the session ID\n *                 (Thread-safe if MBEDTLS_THREADING_C is enabled)\n *\n * \\param data            The SSL cache context to use.\n * \\param session_id      The pointer to the buffer holding the session ID\n *                        associated to session.\n * \\param session_id_len  The length of \\p session_id in bytes.\n *\n * \\return                \\c 0 on success. This indicates the cache entry for\n *                        the session with provided ID is removed or does not\n *                        exist.\n * \\return                A negative error code on failure.\n */\nint mbedtls_ssl_cache_remove(void *data,\n                             unsigned char const *session_id,\n                             size_t session_id_len);\n\n#if defined(MBEDTLS_HAVE_TIME)\n/**\n * \\brief          Set the cache timeout\n *                 (Default: MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT (1 day))\n *\n *                 A timeout of 0 indicates no timeout.\n *\n * \\param cache    SSL cache context\n * \\param timeout  cache entry timeout in seconds\n */\nvoid mbedtls_ssl_cache_set_timeout(mbedtls_ssl_cache_context *cache, int timeout);\n\n/**\n * \\brief          Get the cache timeout\n *\n *                 A timeout of 0 indicates no timeout.\n *\n * \\param cache    SSL cache context\n *\n * \\return         cache entry timeout in seconds\n */\nstatic inline int mbedtls_ssl_cache_get_timeout(mbedtls_ssl_cache_context *cache)\n{\n    return cache->MBEDTLS_PRIVATE(timeout);\n}\n#endif /* MBEDTLS_HAVE_TIME */\n\n/**\n * \\brief          Set the maximum number of cache entries\n *                 (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50))\n *\n * \\param cache    SSL cache context\n * \\param max      cache entry maximum\n */\nvoid mbedtls_ssl_cache_set_max_entries(mbedtls_ssl_cache_context *cache, int max);\n\n/**\n * \\brief          Free referenced items in a cache context and clear memory\n *\n * \\param cache    SSL cache context\n */\nvoid mbedtls_ssl_cache_free(mbedtls_ssl_cache_context *cache);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* ssl_cache.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h",
    "content": "/**\n * \\file ssl_ciphersuites.h\n *\n * \\brief SSL Ciphersuites for Mbed TLS\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_SSL_CIPHERSUITES_H\n#define MBEDTLS_SSL_CIPHERSUITES_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/pk.h\"\n#include \"mbedtls/cipher.h\"\n#include \"mbedtls/md.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * Supported ciphersuites (Official IANA names)\n */\n#define MBEDTLS_TLS_RSA_WITH_NULL_MD5                    0x01   /**< Weak! */\n#define MBEDTLS_TLS_RSA_WITH_NULL_SHA                    0x02   /**< Weak! */\n\n#define MBEDTLS_TLS_PSK_WITH_NULL_SHA                    0x2C   /**< Weak! */\n#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA                0x2D   /**< Weak! */\n#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA                0x2E   /**< Weak! */\n#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA             0x2F\n\n#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA         0x33\n#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA             0x35\n#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA         0x39\n\n#define MBEDTLS_TLS_RSA_WITH_NULL_SHA256                 0x3B   /**< Weak! */\n#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256          0x3C   /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256          0x3D   /**< TLS 1.2 */\n\n#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA        0x41\n#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA    0x45\n\n#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256      0x67   /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256      0x6B   /**< TLS 1.2 */\n\n#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA        0x84\n#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA    0x88\n\n#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA             0x8C\n#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA             0x8D\n\n#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA         0x90\n#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA         0x91\n\n#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA         0x94\n#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA         0x95\n\n#define MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256          0x9C   /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384          0x9D   /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256      0x9E   /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384      0x9F   /**< TLS 1.2 */\n\n#define MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256          0xA8   /**< TLS 1.2 */\n#define MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384          0xA9   /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256      0xAA   /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384      0xAB   /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256      0xAC   /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384      0xAD   /**< TLS 1.2 */\n\n#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256          0xAE\n#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384          0xAF\n#define MBEDTLS_TLS_PSK_WITH_NULL_SHA256                 0xB0   /**< Weak! */\n#define MBEDTLS_TLS_PSK_WITH_NULL_SHA384                 0xB1   /**< Weak! */\n\n#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256      0xB2\n#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384      0xB3\n#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256             0xB4   /**< Weak! */\n#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384             0xB5   /**< Weak! */\n\n#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256      0xB6\n#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384      0xB7\n#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256             0xB8   /**< Weak! */\n#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384             0xB9   /**< Weak! */\n\n#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256     0xBA   /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE   /**< TLS 1.2 */\n\n#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256     0xC0   /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4   /**< TLS 1.2 */\n\n#define MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA             0xC001 /**< Weak! */\n#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA      0xC004\n#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA      0xC005\n\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA            0xC006 /**< Weak! */\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA     0xC009\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA     0xC00A\n\n#define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA               0xC00B /**< Weak! */\n#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA        0xC00E\n#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA        0xC00F\n\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA              0xC010 /**< Weak! */\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA       0xC013\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA       0xC014\n\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256  0xC023 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384  0xC024 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256   0xC025 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384   0xC026 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256    0xC027 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384    0xC028 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256     0xC029 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384     0xC02A /**< TLS 1.2 */\n\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256  0xC02B /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384  0xC02C /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256   0xC02D /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384   0xC02E /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256    0xC02F /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384    0xC030 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256     0xC031 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384     0xC032 /**< TLS 1.2 */\n\n#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA       0xC035\n#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA       0xC036\n#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256    0xC037\n#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384    0xC038\n#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA              0xC039\n#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256           0xC03A\n#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384           0xC03B\n\n#define MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256         0xC03C /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384         0xC03D /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256     0xC044 /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384     0xC045 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC048 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC049 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256  0xC04A /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384  0xC04B /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256   0xC04C /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384   0xC04D /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256    0xC04E /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384    0xC04F /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256         0xC050 /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384         0xC051 /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256     0xC052 /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384     0xC053 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05C /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05D /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256  0xC05E /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384  0xC05F /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256   0xC060 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384   0xC061 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256    0xC062 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384    0xC063 /**< TLS 1.2 */\n#define MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256         0xC064 /**< TLS 1.2 */\n#define MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384         0xC065 /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256     0xC066 /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384     0xC067 /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256     0xC068 /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384     0xC069 /**< TLS 1.2 */\n#define MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256         0xC06A /**< TLS 1.2 */\n#define MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384         0xC06B /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256     0xC06C /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384     0xC06D /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256     0xC06E /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384     0xC06F /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256   0xC070 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384   0xC071 /**< TLS 1.2 */\n\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073\n#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256  0xC074\n#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384  0xC075\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256   0xC076\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384   0xC077\n#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256    0xC078\n#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384    0xC079\n\n#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256         0xC07A /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384         0xC07B /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256     0xC07C /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384     0xC07D /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256  0xC088 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384  0xC089 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256   0xC08A /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384   0xC08B /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256    0xC08C /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384    0xC08D /**< TLS 1.2 */\n\n#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256       0xC08E /**< TLS 1.2 */\n#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384       0xC08F /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256   0xC090 /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384   0xC091 /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256   0xC092 /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384   0xC093 /**< TLS 1.2 */\n\n#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256       0xC094\n#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384       0xC095\n#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256   0xC096\n#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384   0xC097\n#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256   0xC098\n#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384   0xC099\n#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A\n#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B\n\n#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM                0xC09C  /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM                0xC09D  /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM            0xC09E  /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM            0xC09F  /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8              0xC0A0  /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8              0xC0A1  /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8          0xC0A2  /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8          0xC0A3  /**< TLS 1.2 */\n#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM                0xC0A4  /**< TLS 1.2 */\n#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM                0xC0A5  /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM            0xC0A6  /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM            0xC0A7  /**< TLS 1.2 */\n#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8              0xC0A8  /**< TLS 1.2 */\n#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8              0xC0A9  /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8          0xC0AA  /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8          0xC0AB  /**< TLS 1.2 */\n/* The last two are named with PSK_DHE in the RFC, which looks like a typo */\n\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM        0xC0AC  /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM        0xC0AD  /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8      0xC0AE  /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8      0xC0AF  /**< TLS 1.2 */\n\n#define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8          0xC0FF  /**< experimental */\n\n/* RFC 7905 */\n#define MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256   0xCCA8 /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256     0xCCAA /**< TLS 1.2 */\n#define MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256         0xCCAB /**< TLS 1.2 */\n#define MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256   0xCCAC /**< TLS 1.2 */\n#define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256     0xCCAD /**< TLS 1.2 */\n#define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256     0xCCAE /**< TLS 1.2 */\n\n/* RFC 8446, Appendix B.4 */\n#define MBEDTLS_TLS1_3_AES_128_GCM_SHA256                     0x1301 /**< TLS 1.3 */\n#define MBEDTLS_TLS1_3_AES_256_GCM_SHA384                     0x1302 /**< TLS 1.3 */\n#define MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256               0x1303 /**< TLS 1.3 */\n#define MBEDTLS_TLS1_3_AES_128_CCM_SHA256                     0x1304 /**< TLS 1.3 */\n#define MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256                   0x1305 /**< TLS 1.3 */\n\n/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange.\n * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below\n */\ntypedef enum {\n    MBEDTLS_KEY_EXCHANGE_NONE = 0,\n    MBEDTLS_KEY_EXCHANGE_RSA,\n    MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n    MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n    MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n    MBEDTLS_KEY_EXCHANGE_PSK,\n    MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n    MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n    MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,\n    MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n    MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n    MBEDTLS_KEY_EXCHANGE_ECJPAKE,\n} mbedtls_key_exchange_type_t;\n\n/* Key exchanges using a certificate */\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)           || \\\n    defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)       || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)     || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)   || \\\n    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)       || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)      || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)\n#define MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED\n#endif\n\n/* Key exchanges in either TLS 1.2 or 1.3 which are using an ECDSA\n * signature */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \\\n    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n#define MBEDTLS_KEY_EXCHANGE_WITH_ECDSA_ANY_ENABLED\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) || \\\n    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n#define MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED\n#endif\n\n/* Key exchanges allowing client certificate requests.\n *\n * Note: that's almost the same as MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED\n * above, except RSA-PSK uses a server certificate but no client cert.\n *\n * Note: this difference is specific to TLS 1.2, as with TLS 1.3, things are\n * more symmetrical: client certs and server certs are either both allowed\n * (Ephemeral mode) or both disallowed (PSK and PKS-Ephemeral modes).\n */\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)           ||       \\\n    defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)       ||       \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)     ||       \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)   ||       \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)    ||       \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)\n#define MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED\n#endif\n\n/* Helper to state that certificate-based client authentication through ECDSA\n * is supported in TLS 1.2 */\n#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) && \\\n    defined(MBEDTLS_PK_CAN_ECDSA_SIGN) && defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)\n#define MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED\n#endif\n\n/* ECDSA required for certificates in either TLS 1.2 or 1.3 */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \\\n    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n#define MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED\n#endif\n\n/* Key exchanges involving server signature in ServerKeyExchange */\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)       || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)     || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)\n#define MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED\n#endif\n\n/* Key exchanges using ECDH */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)      || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)\n#define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED\n#endif\n\n/* Key exchanges that don't involve ephemeral keys */\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)           || \\\n    defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)           || \\\n    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)       || \\\n    defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED)\n#define MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED\n#endif\n\n/* Key exchanges that involve ephemeral keys */\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)       || \\\n    defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)       || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)     || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)     || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)   || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n#define MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED\n#endif\n\n/* Key exchanges using a PSK */\n#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)           || \\\n    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)       || \\\n    defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)       || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)\n#define MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED\n#endif\n\n/* Key exchanges using DHE */\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)       || \\\n    defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)\n#define MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED\n#endif\n\n/* Key exchanges using ECDHE */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)     || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)   || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)\n#define MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED\n#endif\n\n/* TLS 1.2 key exchanges using ECDH or ECDHE*/\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)\n#define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED\n#endif\n\n/* TLS 1.3 PSK key exchanges */\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) || \\\n    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)\n#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED\n#endif\n\n/* TLS 1.2 or 1.3 key exchanges with PSK */\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) || \\\n    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n#define MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED\n#endif\n\n/* TLS 1.3 ephemeral key exchanges */\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) || \\\n    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)\n#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED\n#endif\n\n/* TLS 1.3 key exchanges using ECDHE */\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) && \\\n    defined(PSA_WANT_ALG_ECDH)\n#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_ECDHE_ENABLED\n#endif\n\n/* TLS 1.2 or 1.3 key exchanges using ECDH or ECDHE */\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \\\n    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_ECDHE_ENABLED)\n#define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED\n#endif\n\n/* TLS 1.2 XXDH key exchanges: ECDH or ECDHE or FFDH */\n#if (defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED))\n#define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_1_2_ENABLED\n#endif\n\n/* The handshake params structure has a set of fields called xxdh_psa which are used:\n * - by TLS 1.2 with `USE_PSA` to do ECDH or ECDHE;\n * - by TLS 1.3 to do ECDHE or FFDHE.\n * The following macros can be used to guard their declaration and use.\n */\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) && \\\n    defined(MBEDTLS_USE_PSA_CRYPTO)\n#define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_1_2_ENABLED\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_1_2_ENABLED) || \\\n    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)\n#define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED\n#endif\n\ntypedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t;\n\n#define MBEDTLS_CIPHERSUITE_WEAK       0x01    /**< Weak ciphersuite flag  */\n#define MBEDTLS_CIPHERSUITE_SHORT_TAG  0x02    /**< Short authentication tag,\n                                                     eg for CCM_8 */\n#define MBEDTLS_CIPHERSUITE_NODTLS     0x04    /**< Can't be used with DTLS */\n\n/**\n * \\brief   This structure is used for storing ciphersuite information\n *\n * \\note    members are defined using integral types instead of enums\n *          in order to pack structure and reduce memory usage by internal\n *          \\c ciphersuite_definitions[]\n */\nstruct mbedtls_ssl_ciphersuite_t {\n    int MBEDTLS_PRIVATE(id);\n    const char *MBEDTLS_PRIVATE(name);\n\n    uint8_t MBEDTLS_PRIVATE(cipher);           /* mbedtls_cipher_type_t */\n    uint8_t MBEDTLS_PRIVATE(mac);              /* mbedtls_md_type_t */\n    uint8_t MBEDTLS_PRIVATE(key_exchange);     /* mbedtls_key_exchange_type_t */\n    uint8_t MBEDTLS_PRIVATE(flags);\n\n    uint16_t MBEDTLS_PRIVATE(min_tls_version); /* mbedtls_ssl_protocol_version */\n    uint16_t MBEDTLS_PRIVATE(max_tls_version); /* mbedtls_ssl_protocol_version */\n};\n\nconst int *mbedtls_ssl_list_ciphersuites(void);\n\nconst mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string(const char *ciphersuite_name);\nconst mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id(int ciphersuite_id);\n\nstatic inline const char *mbedtls_ssl_ciphersuite_get_name(const mbedtls_ssl_ciphersuite_t *info)\n{\n    return info->MBEDTLS_PRIVATE(name);\n}\n\nstatic inline int mbedtls_ssl_ciphersuite_get_id(const mbedtls_ssl_ciphersuite_t *info)\n{\n    return info->MBEDTLS_PRIVATE(id);\n}\n\nsize_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(const mbedtls_ssl_ciphersuite_t *info);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* ssl_ciphersuites.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/ssl_cookie.h",
    "content": "/**\n * \\file ssl_cookie.h\n *\n * \\brief DTLS cookie callbacks implementation\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_SSL_COOKIE_H\n#define MBEDTLS_SSL_COOKIE_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/ssl.h\"\n\n#if !defined(MBEDTLS_USE_PSA_CRYPTO)\n#if defined(MBEDTLS_THREADING_C)\n#include \"mbedtls/threading.h\"\n#endif\n#endif /* !MBEDTLS_USE_PSA_CRYPTO */\n\n/**\n * \\name SECTION: Module settings\n *\n * The configuration options you can set for this module are in this section.\n * Either change them in mbedtls_config.h or define them on the compiler command line.\n * \\{\n */\n#ifndef MBEDTLS_SSL_COOKIE_TIMEOUT\n#define MBEDTLS_SSL_COOKIE_TIMEOUT     60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */\n#endif\n\n/** \\} name SECTION: Module settings */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief          Context for the default cookie functions.\n */\ntypedef struct mbedtls_ssl_cookie_ctx {\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    mbedtls_svc_key_id_t    MBEDTLS_PRIVATE(psa_hmac_key);  /*!< key id for the HMAC portion   */\n    psa_algorithm_t         MBEDTLS_PRIVATE(psa_hmac_alg);  /*!< key algorithm for the HMAC portion   */\n#else\n    mbedtls_md_context_t    MBEDTLS_PRIVATE(hmac_ctx);   /*!< context for the HMAC portion   */\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#if !defined(MBEDTLS_HAVE_TIME)\n    unsigned long   MBEDTLS_PRIVATE(serial);     /*!< serial number for expiration   */\n#endif\n    unsigned long   MBEDTLS_PRIVATE(timeout);    /*!< timeout delay, in seconds if HAVE_TIME,\n                                                    or in number of tickets issued */\n\n#if !defined(MBEDTLS_USE_PSA_CRYPTO)\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex);\n#endif\n#endif /* !MBEDTLS_USE_PSA_CRYPTO */\n} mbedtls_ssl_cookie_ctx;\n\n/**\n * \\brief          Initialize cookie context\n */\nvoid mbedtls_ssl_cookie_init(mbedtls_ssl_cookie_ctx *ctx);\n\n/**\n * \\brief          Setup cookie context (generate keys)\n */\nint mbedtls_ssl_cookie_setup(mbedtls_ssl_cookie_ctx *ctx,\n                             mbedtls_f_rng_t *f_rng,\n                             void *p_rng);\n\n/**\n * \\brief          Set expiration delay for cookies\n *                 (Default MBEDTLS_SSL_COOKIE_TIMEOUT)\n *\n * \\param ctx      Cookie context\n * \\param delay    Delay, in seconds if HAVE_TIME, or in number of cookies\n *                 issued in the meantime.\n *                 0 to disable expiration (NOT recommended)\n */\nvoid mbedtls_ssl_cookie_set_timeout(mbedtls_ssl_cookie_ctx *ctx, unsigned long delay);\n\n/**\n * \\brief          Free cookie context\n */\nvoid mbedtls_ssl_cookie_free(mbedtls_ssl_cookie_ctx *ctx);\n\n/**\n * \\brief          Generate cookie, see \\c mbedtls_ssl_cookie_write_t\n */\nmbedtls_ssl_cookie_write_t mbedtls_ssl_cookie_write;\n\n/**\n * \\brief          Verify cookie, see \\c mbedtls_ssl_cookie_write_t\n */\nmbedtls_ssl_cookie_check_t mbedtls_ssl_cookie_check;\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* ssl_cookie.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/ssl_ticket.h",
    "content": "/**\n * \\file ssl_ticket.h\n *\n * \\brief TLS server ticket callbacks implementation\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_SSL_TICKET_H\n#define MBEDTLS_SSL_TICKET_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n/*\n * This implementation of the session ticket callbacks includes key\n * management, rotating the keys periodically in order to preserve forward\n * secrecy, when MBEDTLS_HAVE_TIME is defined.\n */\n\n#include \"mbedtls/ssl.h\"\n#include \"mbedtls/cipher.h\"\n\n#if defined(MBEDTLS_HAVE_TIME)\n#include \"mbedtls/platform_time.h\"\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"psa/crypto.h\"\n#endif\n\n#if defined(MBEDTLS_THREADING_C)\n#include \"mbedtls/threading.h\"\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define MBEDTLS_SSL_TICKET_MAX_KEY_BYTES 32          /*!< Max supported key length in bytes */\n#define MBEDTLS_SSL_TICKET_KEY_NAME_BYTES 4          /*!< key name length in bytes */\n\n/**\n * \\brief   Information for session ticket protection\n */\ntypedef struct mbedtls_ssl_ticket_key {\n    unsigned char MBEDTLS_PRIVATE(name)[MBEDTLS_SSL_TICKET_KEY_NAME_BYTES];\n    /*!< random key identifier              */\n#if defined(MBEDTLS_HAVE_TIME)\n    mbedtls_time_t MBEDTLS_PRIVATE(generation_time); /*!< key generation timestamp (seconds) */\n#endif\n    /*! Lifetime of the key in seconds. This is also the lifetime of the\n     *  tickets created under that key.\n     */\n    uint32_t MBEDTLS_PRIVATE(lifetime);\n#if !defined(MBEDTLS_USE_PSA_CRYPTO)\n    mbedtls_cipher_context_t MBEDTLS_PRIVATE(ctx);   /*!< context for auth enc/decryption    */\n#else\n    mbedtls_svc_key_id_t MBEDTLS_PRIVATE(key);       /*!< key used for auth enc/decryption   */\n    psa_algorithm_t MBEDTLS_PRIVATE(alg);            /*!< algorithm of auth enc/decryption   */\n    psa_key_type_t MBEDTLS_PRIVATE(key_type);        /*!< key type                           */\n    size_t MBEDTLS_PRIVATE(key_bits);                /*!< key length in bits                 */\n#endif\n}\nmbedtls_ssl_ticket_key;\n\n/**\n * \\brief   Context for session ticket handling functions\n */\ntypedef struct mbedtls_ssl_ticket_context {\n    mbedtls_ssl_ticket_key MBEDTLS_PRIVATE(keys)[2]; /*!< ticket protection keys             */\n    unsigned char MBEDTLS_PRIVATE(active);           /*!< index of the currently active key  */\n\n    uint32_t MBEDTLS_PRIVATE(ticket_lifetime);       /*!< lifetime of tickets in seconds     */\n\n    /** Callback for getting (pseudo-)random numbers                        */\n    int(*MBEDTLS_PRIVATE(f_rng))(void *, unsigned char *, size_t);\n    void *MBEDTLS_PRIVATE(p_rng);                    /*!< context for the RNG function       */\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex);\n#endif\n}\nmbedtls_ssl_ticket_context;\n\n/**\n * \\brief           Initialize a ticket context.\n *                  (Just make it ready for mbedtls_ssl_ticket_setup()\n *                  or mbedtls_ssl_ticket_free().)\n *\n * \\param ctx       Context to be initialized\n */\nvoid mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx);\n\n/**\n * \\brief           Prepare context to be actually used\n *\n * \\param ctx       Context to be set up\n * \\param f_rng     RNG callback function (mandatory)\n * \\param p_rng     RNG callback context.\n *                  Note that the RNG callback must remain valid\n *                  until the ticket context is freed.\n * \\param cipher    AEAD cipher to use for ticket protection.\n *                  Recommended value: MBEDTLS_CIPHER_AES_256_GCM.\n * \\param lifetime  Tickets lifetime in seconds\n *                  Recommended value: 86400 (one day).\n *\n * \\note            It is highly recommended to select a cipher that is at\n *                  least as strong as the strongest ciphersuite\n *                  supported. Usually that means a 256-bit key.\n *\n * \\note            It is recommended to pick a reasonable lifetime so as not\n *                  to negate the benefits of forward secrecy.\n *\n * \\note            The TLS 1.3 specification states that ticket lifetime must\n *                  be smaller than seven days. If ticket lifetime has been\n *                  set to a value greater than seven days in this module then\n *                  if the TLS 1.3 is configured to send tickets after the\n *                  handshake it will fail the connection when trying to send\n *                  the first ticket.\n *\n * \\return          0 if successful,\n *                  or a specific MBEDTLS_ERR_XXX error code\n */\nint mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx,\n                             mbedtls_f_rng_t *f_rng, void *p_rng,\n                             mbedtls_cipher_type_t cipher,\n                             uint32_t lifetime);\n\n/**\n * \\brief           Rotate session ticket encryption key to new specified key.\n *                  Provides for external control of session ticket encryption\n *                  key rotation, e.g. for synchronization between different\n *                  machines.  If this function is not used, or if not called\n *                  before ticket lifetime expires, then a new session ticket\n *                  encryption key is generated internally in order to avoid\n *                  unbounded session ticket encryption key lifetimes.\n *\n * \\param ctx       Context to be set up\n * \\param name      Session ticket encryption key name\n * \\param nlength   Session ticket encryption key name length in bytes\n * \\param k         Session ticket encryption key\n * \\param klength   Session ticket encryption key length in bytes\n * \\param lifetime  Tickets lifetime in seconds\n *                  Recommended value: 86400 (one day).\n *\n * \\note            \\c name and \\c k are recommended to be cryptographically\n *                  random data.\n *\n * \\note            \\c nlength must match sizeof( ctx->name )\n *\n * \\note            \\c klength must be sufficient for use by cipher specified\n *                  to \\c mbedtls_ssl_ticket_setup\n *\n * \\note            It is recommended to pick a reasonable lifetime so as not\n *                  to negate the benefits of forward secrecy.\n *\n * \\note            The TLS 1.3 specification states that ticket lifetime must\n *                  be smaller than seven days. If ticket lifetime has been\n *                  set to a value greater than seven days in this module then\n *                  if the TLS 1.3 is configured to send tickets after the\n *                  handshake it will fail the connection when trying to send\n *                  the first ticket.\n *\n * \\return          0 if successful,\n *                  or a specific MBEDTLS_ERR_XXX error code\n */\nint mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx,\n                              const unsigned char *name, size_t nlength,\n                              const unsigned char *k, size_t klength,\n                              uint32_t lifetime);\n\n/**\n * \\brief           Implementation of the ticket write callback\n *\n * \\note            See \\c mbedtls_ssl_ticket_write_t for description\n */\nmbedtls_ssl_ticket_write_t mbedtls_ssl_ticket_write;\n\n/**\n * \\brief           Implementation of the ticket parse callback\n *\n * \\note            See \\c mbedtls_ssl_ticket_parse_t for description\n */\nmbedtls_ssl_ticket_parse_t mbedtls_ssl_ticket_parse;\n\n/**\n * \\brief           Free a context's content and zeroize it.\n *\n * \\param ctx       Context to be cleaned up\n */\nvoid mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* ssl_ticket.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/threading.h",
    "content": "/**\n * \\file threading.h\n *\n * \\brief Threading abstraction layer\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_THREADING_H\n#define MBEDTLS_THREADING_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include <stdlib.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** Bad input parameters to function. */\n#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA              -0x001C\n/** Locking / unlocking / free failed with error code. */\n#define MBEDTLS_ERR_THREADING_MUTEX_ERROR                 -0x001E\n\n#if defined(MBEDTLS_THREADING_PTHREAD)\n#include <pthread.h>\ntypedef struct mbedtls_threading_mutex_t {\n    pthread_mutex_t MBEDTLS_PRIVATE(mutex);\n\n    /* WARNING - state should only be accessed when holding the mutex lock in\n     * framework/tests/src/threading_helpers.c, otherwise corruption can occur.\n     * state will be 0 after a failed init or a free, and nonzero after a\n     * successful init. This field is for testing only and thus not considered\n     * part of the public API of Mbed TLS and may change without notice.*/\n    char MBEDTLS_PRIVATE(state);\n\n} mbedtls_threading_mutex_t;\n#endif\n\n#if defined(MBEDTLS_THREADING_ALT)\n/* You should define the mbedtls_threading_mutex_t type in your header */\n#include \"threading_alt.h\"\n\n/**\n * \\brief           Set your alternate threading implementation function\n *                  pointers and initialize global mutexes. If used, this\n *                  function must be called once in the main thread before any\n *                  other Mbed TLS function is called, and\n *                  mbedtls_threading_free_alt() must be called once in the main\n *                  thread after all other Mbed TLS functions.\n *\n * \\warning         \\p mutex_init and \\p mutex_free don't return a status code.\n *                  If \\p mutex_init fails, it should leave the mutex in\n *                  a state such that \\p mutex_lock will reliably return\n *                  #MBEDTLS_ERR_THREADING_MUTEX_ERROR called on this mutex,\n *                  and \\p mutex_free will do nothing.\n *\n * \\param mutex_init    The init function implementation. <br>\n *                      The behavior is undefined if the mutex is already\n *                      initialized and has not been destroyed.\n *                      On platforms where mutex initialization can fail,\n *                      since this function does not return a status code,\n *                      it must leave the mutex object in a safe state where\n *                      subsequent function calls will not cause undefined\n *                      behavior: after a call to \\p mutex_init, the\n *                      function \\p mutex_lock must either succeed or\n *                      fail with a nonzero status code, and the function\n *                      \\p mutex_free must free any resources associated\n *                      with the mutex..\n * \\param mutex_free    The destroy function implementation. <br>\n *                      This function must free any resources associated\n *                      with the mutex object. <br>\n *                      This function must work reliably if \\p mutex_init\n *                      has been called on the mutex and \\p mutex_free\n *                      has not yet been called. <br>\n *                      The behavior is undefined if the mutex was not\n *                      initialized, if it has already been destroyed,\n *                      if it is currently locked, or if this function\n *                      is called concurrently from multiple threads.\n * \\param mutex_lock    The lock function implementation. <br>\n *                      This function must work reliably on any mutex\n *                      which is not currently locked and on which\n *                      \\p mutex_init has already been called but\n *                      \\p mutex_free has not been called yet. <br>\n *                      The behavior is undefined if the mutex was not\n *                      initialized, if it has already been destroyed, or if\n *                      it is currently locked by the calling thread.\n * \\param mutex_unlock  The unlock function implementation. <br>\n *                      The behavior is undefined if the mutex is not\n *                      currently locked by the calling thread.\n */\nvoid mbedtls_threading_set_alt(void (*mutex_init)(mbedtls_threading_mutex_t *),\n                               void (*mutex_free)(mbedtls_threading_mutex_t *),\n                               int (*mutex_lock)(mbedtls_threading_mutex_t *),\n                               int (*mutex_unlock)(mbedtls_threading_mutex_t *));\n\n/**\n * \\brief               Free global mutexes.\n */\nvoid mbedtls_threading_free_alt(void);\n#endif /* MBEDTLS_THREADING_ALT */\n\n#if defined(MBEDTLS_THREADING_C)\n/*\n * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock\n *\n * All these functions are expected to work or the result will be undefined.\n */\nextern void (*mbedtls_mutex_init)(mbedtls_threading_mutex_t *mutex);\nextern void (*mbedtls_mutex_free)(mbedtls_threading_mutex_t *mutex);\nextern int (*mbedtls_mutex_lock)(mbedtls_threading_mutex_t *mutex);\nextern int (*mbedtls_mutex_unlock)(mbedtls_threading_mutex_t *mutex);\n\n/*\n * Global mutexes\n */\n#if defined(MBEDTLS_FS_IO)\nextern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex;\n#endif\n\n#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)\n/* This mutex may or may not be used in the default definition of\n * mbedtls_platform_gmtime_r(), but in order to determine that,\n * we need to check POSIX features, hence modify _POSIX_C_SOURCE.\n * With the current approach, this declaration is orphaned, lacking\n * an accompanying definition, in case mbedtls_platform_gmtime_r()\n * doesn't need it, but that's not a problem. */\nextern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex;\n#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */\n\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n/*\n * A mutex used to make the PSA subsystem thread safe.\n *\n * key_slot_mutex protects the registered_readers and\n * state variable for all key slots in &global_data.key_slots.\n *\n * This mutex must be held when any read from or write to a state or\n * registered_readers field is performed, i.e. when calling functions:\n * psa_key_slot_state_transition(), psa_register_read(), psa_unregister_read(),\n * psa_key_slot_has_readers() and psa_wipe_key_slot(). */\nextern mbedtls_threading_mutex_t mbedtls_threading_key_slot_mutex;\n\n/*\n * A mutex used to make the non-rng PSA global_data struct members thread safe.\n *\n * This mutex must be held when reading or writing to any of the PSA global_data\n * structure members, other than the rng_state or rng struct. */\nextern mbedtls_threading_mutex_t mbedtls_threading_psa_globaldata_mutex;\n\n/*\n * A mutex used to make the PSA global_data rng data thread safe.\n *\n * This mutex must be held when reading or writing to the PSA\n * global_data rng_state or rng struct members. */\nextern mbedtls_threading_mutex_t mbedtls_threading_psa_rngdata_mutex;\n#endif\n\n#endif /* MBEDTLS_THREADING_C */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* threading.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/timing.h",
    "content": "/**\n * \\file timing.h\n *\n * \\brief Portable interface to timeouts and to the CPU cycle counter\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_TIMING_H\n#define MBEDTLS_TIMING_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include <stdint.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if !defined(MBEDTLS_TIMING_ALT)\n// Regular implementation\n//\n\n/**\n * \\brief          timer structure\n */\nstruct mbedtls_timing_hr_time {\n    uint64_t MBEDTLS_PRIVATE(opaque)[4];\n};\n\n/**\n * \\brief          Context for mbedtls_timing_set/get_delay()\n */\ntypedef struct mbedtls_timing_delay_context {\n    struct mbedtls_timing_hr_time   MBEDTLS_PRIVATE(timer);\n    uint32_t                        MBEDTLS_PRIVATE(int_ms);\n    uint32_t                        MBEDTLS_PRIVATE(fin_ms);\n} mbedtls_timing_delay_context;\n\n#else  /* MBEDTLS_TIMING_ALT */\n#include \"timing_alt.h\"\n#endif /* MBEDTLS_TIMING_ALT */\n\n/* Internal use */\nunsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset);\n\n/**\n * \\brief          Set a pair of delays to watch\n *                 (See \\c mbedtls_timing_get_delay().)\n *\n * \\param data     Pointer to timing data.\n *                 Must point to a valid \\c mbedtls_timing_delay_context struct.\n * \\param int_ms   First (intermediate) delay in milliseconds.\n *                 The effect if int_ms > fin_ms is unspecified.\n * \\param fin_ms   Second (final) delay in milliseconds.\n *                 Pass 0 to cancel the current delay.\n *\n * \\note           To set a single delay, either use \\c mbedtls_timing_set_timer\n *                 directly or use this function with int_ms == fin_ms.\n */\nvoid mbedtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms);\n\n/**\n * \\brief          Get the status of delays\n *                 (Memory helper: number of delays passed.)\n *\n * \\param data     Pointer to timing data\n *                 Must point to a valid \\c mbedtls_timing_delay_context struct.\n *\n * \\return         -1 if cancelled (fin_ms = 0),\n *                  0 if none of the delays are passed,\n *                  1 if only the intermediate delay is passed,\n *                  2 if the final delay is passed.\n */\nint mbedtls_timing_get_delay(void *data);\n\n/**\n * \\brief          Get the final timing delay\n *\n * \\param data     Pointer to timing data\n *                 Must point to a valid \\c mbedtls_timing_delay_context struct.\n *\n * \\return         Final timing delay in milliseconds.\n */\nuint32_t mbedtls_timing_get_final_delay(\n    const mbedtls_timing_delay_context *data);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* timing.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/version.h",
    "content": "/**\n * \\file version.h\n *\n * \\brief Run-time version information\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n * This set of run-time variables can be used to determine the version number of\n * the Mbed TLS library used. Compile-time version defines for the same can be\n * found in build_info.h\n */\n#ifndef MBEDTLS_VERSION_H\n#define MBEDTLS_VERSION_H\n\n#include \"mbedtls/build_info.h\"\n\n#if defined(MBEDTLS_VERSION_C)\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Get the version number.\n *\n * \\return          The constructed version number in the format\n *                  MMNNPP00 (Major, Minor, Patch).\n */\nunsigned int mbedtls_version_get_number(void);\n\n/**\n * Get the version string (\"x.y.z\").\n *\n * \\param string    The string that will receive the value.\n *                  (Should be at least 9 bytes in size)\n */\nvoid mbedtls_version_get_string(char *string);\n\n/**\n * Get the full version string (\"Mbed TLS x.y.z\").\n *\n * \\param string    The string that will receive the value. The Mbed TLS version\n *                  string will use 18 bytes AT MOST including a terminating\n *                  null byte.\n *                  (So the buffer should be at least 18 bytes to receive this\n *                  version string).\n */\nvoid mbedtls_version_get_string_full(char *string);\n\n/**\n * \\brief           Check if support for a feature was compiled into this\n *                  Mbed TLS binary. This allows you to see at runtime if the\n *                  library was for instance compiled with or without\n *                  Multi-threading support.\n *\n * \\note            only checks against defines in the sections \"System\n *                  support\", \"Mbed TLS modules\" and \"Mbed TLS feature\n *                  support\" in mbedtls_config.h\n *\n * \\param feature   The string for the define to check (e.g. \"MBEDTLS_AES_C\")\n *\n * \\return          0 if the feature is present,\n *                  -1 if the feature is not present and\n *                  -2 if support for feature checking as a whole was not\n *                  compiled in.\n */\nint mbedtls_version_check_feature(const char *feature);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_VERSION_C */\n\n#endif /* version.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/x509.h",
    "content": "/**\n * \\file x509.h\n *\n * \\brief X.509 generic defines and structures\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_X509_H\n#define MBEDTLS_X509_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/asn1.h\"\n#include \"mbedtls/pk.h\"\n\n#if defined(MBEDTLS_RSA_C)\n#include \"mbedtls/rsa.h\"\n#endif\n\n/**\n * \\addtogroup x509_module\n * \\{\n */\n\n#if !defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA)\n/**\n * Maximum number of intermediate CAs in a verification chain.\n * That is, maximum length of the chain, excluding the end-entity certificate\n * and the trusted root certificate.\n *\n * Set this to a low value to prevent an adversary from making you waste\n * resources verifying an overlong certificate chain.\n */\n#define MBEDTLS_X509_MAX_INTERMEDIATE_CA   8\n#endif\n\n/**\n * \\name X509 Error codes\n * \\{\n */\n/** Unavailable feature, e.g. RSA hashing/encryption combination. */\n#define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE              -0x2080\n/** Requested OID is unknown. */\n#define MBEDTLS_ERR_X509_UNKNOWN_OID                      -0x2100\n/** The CRT/CRL/CSR format is invalid, e.g. different type expected. */\n#define MBEDTLS_ERR_X509_INVALID_FORMAT                   -0x2180\n/** The CRT/CRL/CSR version element is invalid. */\n#define MBEDTLS_ERR_X509_INVALID_VERSION                  -0x2200\n/** The serial tag or value is invalid. */\n#define MBEDTLS_ERR_X509_INVALID_SERIAL                   -0x2280\n/** The algorithm tag or value is invalid. */\n#define MBEDTLS_ERR_X509_INVALID_ALG                      -0x2300\n/** The name tag or value is invalid. */\n#define MBEDTLS_ERR_X509_INVALID_NAME                     -0x2380\n/** The date tag or value is invalid. */\n#define MBEDTLS_ERR_X509_INVALID_DATE                     -0x2400\n/** The signature tag or value invalid. */\n#define MBEDTLS_ERR_X509_INVALID_SIGNATURE                -0x2480\n/** The extension tag or value is invalid. */\n#define MBEDTLS_ERR_X509_INVALID_EXTENSIONS               -0x2500\n/** CRT/CRL/CSR has an unsupported version number. */\n#define MBEDTLS_ERR_X509_UNKNOWN_VERSION                  -0x2580\n/** Signature algorithm (oid) is unsupported. */\n#define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG                  -0x2600\n/** Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid) */\n#define MBEDTLS_ERR_X509_SIG_MISMATCH                     -0x2680\n/** Certificate verification failed, e.g. CRL, CA or signature check failed. */\n#define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED               -0x2700\n/** Format not recognized as DER or PEM. */\n#define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT              -0x2780\n/** Input invalid. */\n#define MBEDTLS_ERR_X509_BAD_INPUT_DATA                   -0x2800\n/** Allocation of memory failed. */\n#define MBEDTLS_ERR_X509_ALLOC_FAILED                     -0x2880\n/** Read/write of file failed. */\n#define MBEDTLS_ERR_X509_FILE_IO_ERROR                    -0x2900\n/** Destination buffer is too small. */\n#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL                 -0x2980\n/** A fatal error occurred, eg the chain is too long or the vrfy callback failed. */\n#define MBEDTLS_ERR_X509_FATAL_ERROR                      -0x3000\n/** \\} name X509 Error codes */\n\n/**\n * \\name X509 Verify codes\n * \\{\n */\n/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */\n#define MBEDTLS_X509_BADCERT_EXPIRED             0x01  /**< The certificate validity has expired. */\n#define MBEDTLS_X509_BADCERT_REVOKED             0x02  /**< The certificate has been revoked (is on a CRL). */\n#define MBEDTLS_X509_BADCERT_CN_MISMATCH         0x04  /**< The certificate Common Name (CN) does not match with the expected CN. */\n#define MBEDTLS_X509_BADCERT_NOT_TRUSTED         0x08  /**< The certificate is not correctly signed by the trusted CA. */\n#define MBEDTLS_X509_BADCRL_NOT_TRUSTED          0x10  /**< The CRL is not correctly signed by the trusted CA. */\n#define MBEDTLS_X509_BADCRL_EXPIRED              0x20  /**< The CRL is expired. */\n#define MBEDTLS_X509_BADCERT_MISSING             0x40  /**< Certificate was missing. */\n#define MBEDTLS_X509_BADCERT_SKIP_VERIFY         0x80  /**< Certificate verification was skipped. */\n#define MBEDTLS_X509_BADCERT_OTHER             0x0100  /**< Other reason (can be used by verify callback) */\n#define MBEDTLS_X509_BADCERT_FUTURE            0x0200  /**< The certificate validity starts in the future. */\n#define MBEDTLS_X509_BADCRL_FUTURE             0x0400  /**< The CRL is from the future */\n#define MBEDTLS_X509_BADCERT_KEY_USAGE         0x0800  /**< Usage does not match the keyUsage extension. */\n#define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE     0x1000  /**< Usage does not match the extendedKeyUsage extension. */\n#define MBEDTLS_X509_BADCERT_NS_CERT_TYPE      0x2000  /**< Usage does not match the nsCertType extension. */\n#define MBEDTLS_X509_BADCERT_BAD_MD            0x4000  /**< The certificate is signed with an unacceptable hash. */\n#define MBEDTLS_X509_BADCERT_BAD_PK            0x8000  /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */\n#define MBEDTLS_X509_BADCERT_BAD_KEY         0x010000  /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */\n#define MBEDTLS_X509_BADCRL_BAD_MD           0x020000  /**< The CRL is signed with an unacceptable hash. */\n#define MBEDTLS_X509_BADCRL_BAD_PK           0x040000  /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */\n#define MBEDTLS_X509_BADCRL_BAD_KEY          0x080000  /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */\n\n/** \\} name X509 Verify codes */\n/** \\} addtogroup x509_module */\n\n/*\n * X.509 v3 Subject Alternative Name types.\n *      otherName                       [0]     OtherName,\n *      rfc822Name                      [1]     IA5String,\n *      dNSName                         [2]     IA5String,\n *      x400Address                     [3]     ORAddress,\n *      directoryName                   [4]     Name,\n *      ediPartyName                    [5]     EDIPartyName,\n *      uniformResourceIdentifier       [6]     IA5String,\n *      iPAddress                       [7]     OCTET STRING,\n *      registeredID                    [8]     OBJECT IDENTIFIER\n */\n#define MBEDTLS_X509_SAN_OTHER_NAME                      0\n#define MBEDTLS_X509_SAN_RFC822_NAME                     1\n#define MBEDTLS_X509_SAN_DNS_NAME                        2\n#define MBEDTLS_X509_SAN_X400_ADDRESS_NAME               3\n#define MBEDTLS_X509_SAN_DIRECTORY_NAME                  4\n#define MBEDTLS_X509_SAN_EDI_PARTY_NAME                  5\n#define MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER     6\n#define MBEDTLS_X509_SAN_IP_ADDRESS                      7\n#define MBEDTLS_X509_SAN_REGISTERED_ID                   8\n\n/*\n * X.509 v3 Key Usage Extension flags\n * Reminder: update mbedtls_x509_info_key_usage() when adding new flags.\n */\n#define MBEDTLS_X509_KU_DIGITAL_SIGNATURE            (0x80)  /* bit 0 */\n#define MBEDTLS_X509_KU_NON_REPUDIATION              (0x40)  /* bit 1 */\n#define MBEDTLS_X509_KU_KEY_ENCIPHERMENT             (0x20)  /* bit 2 */\n#define MBEDTLS_X509_KU_DATA_ENCIPHERMENT            (0x10)  /* bit 3 */\n#define MBEDTLS_X509_KU_KEY_AGREEMENT                (0x08)  /* bit 4 */\n#define MBEDTLS_X509_KU_KEY_CERT_SIGN                (0x04)  /* bit 5 */\n#define MBEDTLS_X509_KU_CRL_SIGN                     (0x02)  /* bit 6 */\n#define MBEDTLS_X509_KU_ENCIPHER_ONLY                (0x01)  /* bit 7 */\n#define MBEDTLS_X509_KU_DECIPHER_ONLY              (0x8000)  /* bit 8 */\n\n/*\n * Netscape certificate types\n * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html)\n */\n\n#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT         (0x80)  /* bit 0 */\n#define MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER         (0x40)  /* bit 1 */\n#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL              (0x20)  /* bit 2 */\n#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING     (0x10)  /* bit 3 */\n#define MBEDTLS_X509_NS_CERT_TYPE_RESERVED           (0x08)  /* bit 4 */\n#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CA             (0x04)  /* bit 5 */\n#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA           (0x02)  /* bit 6 */\n#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA  (0x01)  /* bit 7 */\n\n/*\n * X.509 extension types\n *\n * Comments refer to the status for using certificates. Status can be\n * different for writing certificates or reading CRLs or CSRs.\n *\n * Those are defined in oid.h as oid.c needs them in a data structure. Since\n * these were previously defined here, let's have aliases for compatibility.\n */\n#define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER\n#define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER   MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER\n#define MBEDTLS_X509_EXT_KEY_USAGE                MBEDTLS_OID_X509_EXT_KEY_USAGE\n#define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES     MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES\n#define MBEDTLS_X509_EXT_POLICY_MAPPINGS          MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS\n#define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME         MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME         /* Supported (DNS) */\n#define MBEDTLS_X509_EXT_ISSUER_ALT_NAME          MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME\n#define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS  MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS\n#define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS        MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS        /* Supported */\n#define MBEDTLS_X509_EXT_NAME_CONSTRAINTS         MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS\n#define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS       MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS\n#define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE       MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE\n#define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS  MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS\n#define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY       MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY\n#define MBEDTLS_X509_EXT_FRESHEST_CRL             MBEDTLS_OID_X509_EXT_FRESHEST_CRL\n#define MBEDTLS_X509_EXT_NS_CERT_TYPE             MBEDTLS_OID_X509_EXT_NS_CERT_TYPE\n\n/*\n * Storage format identifiers\n * Recognized formats: PEM and DER\n */\n#define MBEDTLS_X509_FORMAT_DER                 1\n#define MBEDTLS_X509_FORMAT_PEM                 2\n\n#define MBEDTLS_X509_MAX_DN_NAME_SIZE         256 /**< Maximum value size of a DN entry */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\addtogroup x509_module\n * \\{ */\n\n/**\n * \\name Structures for parsing X.509 certificates, CRLs and CSRs\n * \\{\n */\n\n/**\n * Type-length-value structure that allows for ASN1 using DER.\n */\ntypedef mbedtls_asn1_buf mbedtls_x509_buf;\n\n/**\n * Container for ASN1 bit strings.\n */\ntypedef mbedtls_asn1_bitstring mbedtls_x509_bitstring;\n\n/**\n * Container for ASN1 named information objects.\n * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.).\n */\ntypedef mbedtls_asn1_named_data mbedtls_x509_name;\n\n/**\n * Container for a sequence of ASN.1 items\n */\ntypedef mbedtls_asn1_sequence mbedtls_x509_sequence;\n\n/*\n * Container for the fields of the Authority Key Identifier object\n */\ntypedef struct mbedtls_x509_authority {\n    mbedtls_x509_buf keyIdentifier;\n    mbedtls_x509_sequence authorityCertIssuer;\n    mbedtls_x509_buf authorityCertSerialNumber;\n    mbedtls_x509_buf raw;\n}\nmbedtls_x509_authority;\n\n/** Container for date and time (precision in seconds). */\ntypedef struct mbedtls_x509_time {\n    int year, mon, day;         /**< Date. */\n    int hour, min, sec;         /**< Time. */\n}\nmbedtls_x509_time;\n\n/**\n * From RFC 5280 section 4.2.1.6:\n * OtherName ::= SEQUENCE {\n *      type-id    OBJECT IDENTIFIER,\n *      value      [0] EXPLICIT ANY DEFINED BY type-id }\n *\n * Future versions of the library may add new fields to this structure or\n * to its embedded union and structure.\n */\ntypedef struct mbedtls_x509_san_other_name {\n    /**\n     * The type_id is an OID as defined in RFC 5280.\n     * To check the value of the type id, you should use\n     * \\p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf.\n     */\n    mbedtls_x509_buf type_id;                   /**< The type id. */\n    union {\n        /**\n         * From RFC 4108 section 5:\n         * HardwareModuleName ::= SEQUENCE {\n         *                         hwType OBJECT IDENTIFIER,\n         *                         hwSerialNum OCTET STRING }\n         */\n        struct {\n            mbedtls_x509_buf oid;               /**< The object identifier. */\n            mbedtls_x509_buf val;               /**< The named value. */\n        }\n        hardware_module_name;\n    }\n    value;\n}\nmbedtls_x509_san_other_name;\n\n/**\n * A structure for holding the parsed Subject Alternative Name,\n * according to type.\n *\n * Future versions of the library may add new fields to this structure or\n * to its embedded union and structure.\n */\ntypedef struct mbedtls_x509_subject_alternative_name {\n    int type;                              /**< The SAN type, value of MBEDTLS_X509_SAN_XXX. */\n    union {\n        mbedtls_x509_san_other_name other_name;\n        mbedtls_x509_name directory_name;\n        mbedtls_x509_buf unstructured_name; /**< The buffer for the unstructured types. rfc822Name, dnsName and uniformResourceIdentifier are currently supported. */\n    }\n    san; /**< A union of the supported SAN types */\n}\nmbedtls_x509_subject_alternative_name;\n\ntypedef struct mbedtls_x509_san_list {\n    mbedtls_x509_subject_alternative_name node;\n    struct mbedtls_x509_san_list *next;\n}\nmbedtls_x509_san_list;\n\n/** \\} name Structures for parsing X.509 certificates, CRLs and CSRs */\n/** \\} addtogroup x509_module */\n\n/**\n * \\brief          Store the certificate DN in printable form into buf;\n *                 no more than size characters will be written.\n *\n * \\param buf      Buffer to write to\n * \\param size     Maximum size of buffer\n * \\param dn       The X509 name to represent\n *\n * \\return         The length of the string written (not including the\n *                 terminated nul byte), or a negative error code.\n */\nint mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn);\n\n/**\n * \\brief            Convert the certificate DN string \\p name into\n *                   a linked list of mbedtls_x509_name (equivalent to\n *                   mbedtls_asn1_named_data).\n *\n * \\note             This function allocates a linked list, and places the head\n *                   pointer in \\p head. This list must later be freed by a\n *                   call to mbedtls_asn1_free_named_data_list().\n *\n * \\param[out] head  Address in which to store the pointer to the head of the\n *                   allocated list of mbedtls_x509_name. Must point to NULL on\n *                   entry.\n * \\param[in] name   The string representation of a DN to convert\n *\n * \\return           0 on success, or a negative error code.\n */\nint mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name);\n\n/**\n * \\brief          Return the next relative DN in an X509 name.\n *\n * \\note           Intended use is to compare function result to dn->next\n *                 in order to detect boundaries of multi-valued RDNs.\n *\n * \\param dn       Current node in the X509 name\n *\n * \\return         Pointer to the first attribute-value pair of the\n *                 next RDN in sequence, or NULL if end is reached.\n */\nstatic inline mbedtls_x509_name *mbedtls_x509_dn_get_next(\n    mbedtls_x509_name *dn)\n{\n    while (dn->MBEDTLS_PRIVATE(next_merged) && dn->next != NULL) {\n        dn = dn->next;\n    }\n    return dn->next;\n}\n\n/**\n * \\brief          Store the certificate serial in printable form into buf;\n *                 no more than size characters will be written.\n *\n * \\param buf      Buffer to write to\n * \\param size     Maximum size of buffer\n * \\param serial   The X509 serial to represent\n *\n * \\return         The length of the string written (not including the\n *                 terminated nul byte), or a negative error code.\n */\nint mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial);\n\n/**\n * \\brief          Compare pair of mbedtls_x509_time.\n *\n * \\param t1       mbedtls_x509_time to compare\n * \\param t2       mbedtls_x509_time to compare\n *\n * \\return         < 0 if t1 is before t2\n *                   0 if t1 equals t2\n *                 > 0 if t1 is after t2\n */\nint mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, const mbedtls_x509_time *t2);\n\n#if defined(MBEDTLS_HAVE_TIME_DATE)\n/**\n * \\brief          Fill mbedtls_x509_time with provided mbedtls_time_t.\n *\n * \\param tt       mbedtls_time_t to convert\n * \\param now      mbedtls_x509_time to fill with converted mbedtls_time_t\n *\n * \\return         \\c 0 on success\n * \\return         A non-zero return value on failure.\n */\nint mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now);\n#endif /* MBEDTLS_HAVE_TIME_DATE */\n\n/**\n * \\brief          Check a given mbedtls_x509_time against the system time\n *                 and tell if it's in the past.\n *\n * \\note           Intended usage is \"if( is_past( valid_to ) ) ERROR\".\n *                 Hence the return value of 1 if on internal errors.\n *\n * \\param to       mbedtls_x509_time to check\n *\n * \\return         1 if the given time is in the past or an error occurred,\n *                 0 otherwise.\n */\nint mbedtls_x509_time_is_past(const mbedtls_x509_time *to);\n\n/**\n * \\brief          Check a given mbedtls_x509_time against the system time\n *                 and tell if it's in the future.\n *\n * \\note           Intended usage is \"if( is_future( valid_from ) ) ERROR\".\n *                 Hence the return value of 1 if on internal errors.\n *\n * \\param from     mbedtls_x509_time to check\n *\n * \\return         1 if the given time is in the future or an error occurred,\n *                 0 otherwise.\n */\nint mbedtls_x509_time_is_future(const mbedtls_x509_time *from);\n\n/**\n * \\brief          This function parses an item in the SubjectAlternativeNames\n *                 extension. Please note that this function might allocate\n *                 additional memory for a subject alternative name, thus\n *                 mbedtls_x509_free_subject_alt_name has to be called\n *                 to dispose of this additional memory afterwards.\n *\n * \\param san_buf  The buffer holding the raw data item of the subject\n *                 alternative name.\n * \\param san      The target structure to populate with the parsed presentation\n *                 of the subject alternative name encoded in \\p san_buf.\n *\n * \\note           Supported GeneralName types, as defined in RFC 5280:\n *                 \"rfc822Name\", \"dnsName\", \"directoryName\",\n *                 \"uniformResourceIdentifier\" and \"hardware_module_name\"\n *                 of type \"otherName\", as defined in RFC 4108.\n *\n * \\note           This function should be called on a single raw data of\n *                 subject alternative name. For example, after successful\n *                 certificate parsing, one must iterate on every item in the\n *                 \\c crt->subject_alt_names sequence, and pass it to\n *                 this function.\n *\n * \\warning        The target structure contains pointers to the raw data of the\n *                 parsed certificate, and its lifetime is restricted by the\n *                 lifetime of the certificate.\n *\n * \\return         \\c 0 on success\n * \\return         #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported\n *                 SAN type.\n * \\return         Another negative value for any other failure.\n */\nint mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,\n                                        mbedtls_x509_subject_alternative_name *san);\n/**\n * \\brief          Unallocate all data related to subject alternative name\n *\n * \\param san      SAN structure - extra memory owned by this structure will be freed\n */\nvoid mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san);\n\n/**\n * \\brief          This function parses a CN string as an IP address.\n *\n * \\param cn       The CN string to parse. CN string MUST be null-terminated.\n * \\param dst      The target buffer to populate with the binary IP address.\n *                 The buffer MUST be 16 bytes to save IPv6, and should be\n *                 4-byte aligned if the result will be used as struct in_addr.\n *                 e.g. uint32_t dst[4]\n *\n * \\note           \\p cn is parsed as an IPv6 address if string contains ':',\n *                 else \\p cn is parsed as an IPv4 address.\n *\n * \\return         Length of binary IP address; num bytes written to target.\n * \\return         \\c 0 on failure to parse CN string as an IP address.\n */\nsize_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst);\n\n#define MBEDTLS_X509_SAFE_SNPRINTF                          \\\n    do {                                                    \\\n        if (ret < 0 || (size_t) ret >= n)                  \\\n        return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;    \\\n                                                          \\\n        n -= (size_t) ret;                                  \\\n        p += (size_t) ret;                                  \\\n    } while (0)\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_X509_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/x509_crl.h",
    "content": "/**\n * \\file x509_crl.h\n *\n * \\brief X.509 certificate revocation list parsing\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_X509_CRL_H\n#define MBEDTLS_X509_CRL_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/x509.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\addtogroup x509_module\n * \\{ */\n\n/**\n * \\name Structures and functions for parsing CRLs\n * \\{\n */\n\n/**\n * Certificate revocation list entry.\n * Contains the CA-specific serial numbers and revocation dates.\n *\n * Some fields of this structure are publicly readable. Do not modify\n * them except via Mbed TLS library functions: the effect of modifying\n * those fields or the data that those fields points to is unspecified.\n */\ntypedef struct mbedtls_x509_crl_entry {\n    /** Direct access to the whole entry inside the containing buffer. */\n    mbedtls_x509_buf raw;\n    /** The serial number of the revoked certificate. */\n    mbedtls_x509_buf serial;\n    /** The revocation date of this entry. */\n    mbedtls_x509_time revocation_date;\n    /** Direct access to the list of CRL entry extensions\n     * (an ASN.1 constructed sequence).\n     *\n     * If there are no extensions, `entry_ext.len == 0` and\n     * `entry_ext.p == NULL`. */\n    mbedtls_x509_buf entry_ext;\n\n    /** Next element in the linked list of entries.\n     * \\p NULL indicates the end of the list.\n     * Do not modify this field directly. */\n    struct mbedtls_x509_crl_entry *next;\n}\nmbedtls_x509_crl_entry;\n\n/**\n * Certificate revocation list structure.\n * Every CRL may have multiple entries.\n */\ntypedef struct mbedtls_x509_crl {\n    mbedtls_x509_buf raw;           /**< The raw certificate data (DER). */\n    mbedtls_x509_buf tbs;           /**< The raw certificate body (DER). The part that is To Be Signed. */\n\n    int version;            /**< CRL version (1=v1, 2=v2) */\n    mbedtls_x509_buf sig_oid;       /**< CRL signature type identifier */\n\n    mbedtls_x509_buf issuer_raw;    /**< The raw issuer data (DER). */\n\n    mbedtls_x509_name issuer;       /**< The parsed issuer data (named information object). */\n\n    mbedtls_x509_time this_update;\n    mbedtls_x509_time next_update;\n\n    mbedtls_x509_crl_entry entry;   /**< The CRL entries containing the certificate revocation times for this CA. */\n\n    mbedtls_x509_buf crl_ext;\n\n    mbedtls_x509_buf MBEDTLS_PRIVATE(sig_oid2);\n    mbedtls_x509_buf MBEDTLS_PRIVATE(sig);\n    mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md);           /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */\n    mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk);           /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */\n    void *MBEDTLS_PRIVATE(sig_opts);             /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */\n\n    /** Next element in the linked list of CRL.\n     * \\p NULL indicates the end of the list.\n     * Do not modify this field directly. */\n    struct mbedtls_x509_crl *next;\n}\nmbedtls_x509_crl;\n\n/**\n * \\brief          Parse a DER-encoded CRL and append it to the chained list\n *\n * \\note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                 subsystem must have been initialized by calling\n *                 psa_crypto_init() before calling this function.\n *\n * \\param chain    points to the start of the chain\n * \\param buf      buffer holding the CRL data in DER format\n * \\param buflen   size of the buffer\n *                 (including the terminating null byte for PEM data)\n *\n * \\return         0 if successful, or a specific X509 or PEM error code\n */\nint mbedtls_x509_crl_parse_der(mbedtls_x509_crl *chain,\n                               const unsigned char *buf, size_t buflen);\n/**\n * \\brief          Parse one or more CRLs and append them to the chained list\n *\n * \\note           Multiple CRLs are accepted only if using PEM format\n *\n * \\note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                 subsystem must have been initialized by calling\n *                 psa_crypto_init() before calling this function.\n *\n * \\param chain    points to the start of the chain\n * \\param buf      buffer holding the CRL data in PEM or DER format\n * \\param buflen   size of the buffer\n *                 (including the terminating null byte for PEM data)\n *\n * \\return         0 if successful, or a specific X509 or PEM error code\n */\nint mbedtls_x509_crl_parse(mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen);\n\n#if defined(MBEDTLS_FS_IO)\n/**\n * \\brief          Load one or more CRLs and append them to the chained list\n *\n * \\note           Multiple CRLs are accepted only if using PEM format\n *\n * \\note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                 subsystem must have been initialized by calling\n *                 psa_crypto_init() before calling this function.\n *\n * \\param chain    points to the start of the chain\n * \\param path     filename to read the CRLs from (in PEM or DER encoding)\n *\n * \\return         0 if successful, or a specific X509 or PEM error code\n */\nint mbedtls_x509_crl_parse_file(mbedtls_x509_crl *chain, const char *path);\n#endif /* MBEDTLS_FS_IO */\n\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\n/**\n * \\brief          Returns an informational string about the CRL.\n *\n * \\param buf      Buffer to write to\n * \\param size     Maximum size of buffer\n * \\param prefix   A line prefix\n * \\param crl      The X509 CRL to represent\n *\n * \\return         The length of the string written (not including the\n *                 terminated nul byte), or a negative error code.\n */\nint mbedtls_x509_crl_info(char *buf, size_t size, const char *prefix,\n                          const mbedtls_x509_crl *crl);\n#endif /* !MBEDTLS_X509_REMOVE_INFO */\n\n/**\n * \\brief          Initialize a CRL (chain)\n *\n * \\param crl      CRL chain to initialize\n */\nvoid mbedtls_x509_crl_init(mbedtls_x509_crl *crl);\n\n/**\n * \\brief          Unallocate all CRL data\n *\n * \\param crl      CRL chain to free\n */\nvoid mbedtls_x509_crl_free(mbedtls_x509_crl *crl);\n\n/** \\} name Structures and functions for parsing CRLs */\n/** \\} addtogroup x509_module */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* mbedtls_x509_crl.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/x509_crt.h",
    "content": "/**\n * \\file x509_crt.h\n *\n * \\brief X.509 certificate parsing and writing\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_X509_CRT_H\n#define MBEDTLS_X509_CRT_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/x509.h\"\n#include \"mbedtls/x509_crl.h\"\n#include \"mbedtls/bignum.h\"\n\n/**\n * \\addtogroup x509_module\n * \\{\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\name Structures and functions for parsing and writing X.509 certificates\n * \\{\n */\n\n/**\n * Container for an X.509 certificate. The certificate may be chained.\n *\n * Some fields of this structure are publicly readable. Do not modify\n * them except via Mbed TLS library functions: the effect of modifying\n * those fields or the data that those fields points to is unspecified.\n */\ntypedef struct mbedtls_x509_crt {\n    int MBEDTLS_PRIVATE(own_buffer);                     /**< Indicates if \\c raw is owned\n                                                          *   by the structure or not.        */\n    mbedtls_x509_buf raw;               /**< The raw certificate data (DER). */\n    mbedtls_x509_buf tbs;               /**< The raw certificate body (DER). The part that is To Be Signed. */\n\n    int version;                /**< The X.509 version. (1=v1, 2=v2, 3=v3) */\n    mbedtls_x509_buf serial;            /**< Unique id for certificate issued by a specific CA. */\n    mbedtls_x509_buf sig_oid;           /**< Signature algorithm, e.g. sha1RSA */\n\n    mbedtls_x509_buf issuer_raw;        /**< The raw issuer data (DER). Used for quick comparison. */\n    mbedtls_x509_buf subject_raw;       /**< The raw subject data (DER). Used for quick comparison. */\n\n    mbedtls_x509_name issuer;           /**< The parsed issuer data (named information object). */\n    mbedtls_x509_name subject;          /**< The parsed subject data (named information object). */\n\n    mbedtls_x509_time valid_from;       /**< Start time of certificate validity. */\n    mbedtls_x509_time valid_to;         /**< End time of certificate validity. */\n\n    mbedtls_x509_buf pk_raw;\n    mbedtls_pk_context pk;              /**< Container for the public key context. */\n\n    mbedtls_x509_buf issuer_id;         /**< Optional X.509 v2/v3 issuer unique identifier. */\n    mbedtls_x509_buf subject_id;        /**< Optional X.509 v2/v3 subject unique identifier. */\n    mbedtls_x509_buf v3_ext;            /**< Optional X.509 v3 extensions.  */\n    mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension. These can be later parsed by mbedtls_x509_parse_subject_alt_name. */\n    mbedtls_x509_buf subject_key_id;    /**< Optional X.509 v3 extension subject key identifier. */\n    mbedtls_x509_authority authority_key_id;    /**< Optional X.509 v3 extension authority key identifier. */\n\n    mbedtls_x509_sequence certificate_policies; /**< Optional list of certificate policies (Only anyPolicy is printed and enforced, however the rest of the policies are still listed). */\n\n    int MBEDTLS_PRIVATE(ext_types);              /**< Bit string containing detected and parsed extensions */\n    int MBEDTLS_PRIVATE(ca_istrue);              /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */\n    int MBEDTLS_PRIVATE(max_pathlen);            /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */\n\n    unsigned int MBEDTLS_PRIVATE(key_usage);     /**< Optional key usage extension value: See the values in x509.h */\n\n    mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */\n\n    unsigned char MBEDTLS_PRIVATE(ns_cert_type); /**< Optional Netscape certificate type extension value: See the values in x509.h */\n\n    mbedtls_x509_buf MBEDTLS_PRIVATE(sig);               /**< Signature: hash of the tbs part signed with the private key. */\n    mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md);           /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */\n    mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk);           /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */\n    void *MBEDTLS_PRIVATE(sig_opts);             /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */\n\n    /** Next certificate in the linked list that constitutes the CA chain.\n     * \\p NULL indicates the end of the list.\n     * Do not modify this field directly. */\n    struct mbedtls_x509_crt *next;\n}\nmbedtls_x509_crt;\n\n/**\n * Build flag from an algorithm/curve identifier (pk, md, ecp)\n * Since 0 is always XXX_NONE, ignore it.\n */\n#define MBEDTLS_X509_ID_FLAG(id)   (1 << ((id) - 1))\n\n/**\n * Security profile for certificate verification.\n *\n * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG().\n *\n * The fields of this structure are part of the public API and can be\n * manipulated directly by applications. Future versions of the library may\n * add extra fields or reorder existing fields.\n *\n * You can create custom profiles by starting from a copy of\n * an existing profile, such as mbedtls_x509_crt_profile_default or\n * mbedtls_x509_ctr_profile_none and then tune it to your needs.\n *\n * For example to allow SHA-224 in addition to the default:\n *\n *  mbedtls_x509_crt_profile my_profile = mbedtls_x509_crt_profile_default;\n *  my_profile.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 );\n *\n * Or to allow only RSA-3072+ with SHA-256:\n *\n *  mbedtls_x509_crt_profile my_profile = mbedtls_x509_crt_profile_none;\n *  my_profile.allowed_mds = MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 );\n *  my_profile.allowed_pks = MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_RSA );\n *  my_profile.rsa_min_bitlen = 3072;\n */\ntypedef struct mbedtls_x509_crt_profile {\n    uint32_t allowed_mds;       /**< MDs for signatures         */\n    uint32_t allowed_pks;       /**< PK algs for public keys;\n                                 *   this applies to all certificates\n                                 *   in the provided chain.     */\n    uint32_t allowed_curves;    /**< Elliptic curves for ECDSA  */\n    uint32_t rsa_min_bitlen;    /**< Minimum size for RSA keys  */\n}\nmbedtls_x509_crt_profile;\n\n#define MBEDTLS_X509_CRT_VERSION_1              0\n#define MBEDTLS_X509_CRT_VERSION_2              1\n#define MBEDTLS_X509_CRT_VERSION_3              2\n\n#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 20\n#define MBEDTLS_X509_RFC5280_UTC_TIME_LEN   15\n\n#if !defined(MBEDTLS_X509_MAX_FILE_PATH_LEN)\n#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512\n#endif\n\n/* This macro unfolds to the concatenation of macro invocations\n * X509_CRT_ERROR_INFO( error code,\n *                             error code as string,\n *                             human readable description )\n * where X509_CRT_ERROR_INFO is defined by the user.\n * See x509_crt.c for an example of how to use this. */\n#define MBEDTLS_X509_CRT_ERROR_INFO_LIST                                  \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_EXPIRED,            \\\n                        \"MBEDTLS_X509_BADCERT_EXPIRED\",          \\\n                        \"The certificate validity has expired\") \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_REVOKED,            \\\n                        \"MBEDTLS_X509_BADCERT_REVOKED\",          \\\n                        \"The certificate has been revoked (is on a CRL)\") \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_CN_MISMATCH,                  \\\n                        \"MBEDTLS_X509_BADCERT_CN_MISMATCH\",                \\\n                        \"The certificate Common Name (CN) does not match with the expected CN\") \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_NOT_TRUSTED,                             \\\n                        \"MBEDTLS_X509_BADCERT_NOT_TRUSTED\",                           \\\n                        \"The certificate is not correctly signed by the trusted CA\") \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_NOT_TRUSTED,                      \\\n                        \"MBEDTLS_X509_BADCRL_NOT_TRUSTED\",                    \\\n                        \"The CRL is not correctly signed by the trusted CA\") \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_EXPIRED,    \\\n                        \"MBEDTLS_X509_BADCRL_EXPIRED\",  \\\n                        \"The CRL is expired\")          \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_MISSING,   \\\n                        \"MBEDTLS_X509_BADCERT_MISSING\", \\\n                        \"Certificate was missing\")     \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_SKIP_VERIFY,         \\\n                        \"MBEDTLS_X509_BADCERT_SKIP_VERIFY\",       \\\n                        \"Certificate verification was skipped\")  \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_OTHER,                          \\\n                        \"MBEDTLS_X509_BADCERT_OTHER\",                        \\\n                        \"Other reason (can be used by verify callback)\")    \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_FUTURE,                         \\\n                        \"MBEDTLS_X509_BADCERT_FUTURE\",                       \\\n                        \"The certificate validity starts in the future\")    \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_FUTURE,     \\\n                        \"MBEDTLS_X509_BADCRL_FUTURE\",   \\\n                        \"The CRL is from the future\")  \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_KEY_USAGE,                      \\\n                        \"MBEDTLS_X509_BADCERT_KEY_USAGE\",                    \\\n                        \"Usage does not match the keyUsage extension\")      \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_EXT_KEY_USAGE,                       \\\n                        \"MBEDTLS_X509_BADCERT_EXT_KEY_USAGE\",                     \\\n                        \"Usage does not match the extendedKeyUsage extension\")   \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_NS_CERT_TYPE,                        \\\n                        \"MBEDTLS_X509_BADCERT_NS_CERT_TYPE\",                      \\\n                        \"Usage does not match the nsCertType extension\")         \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_BAD_MD,                              \\\n                        \"MBEDTLS_X509_BADCERT_BAD_MD\",                            \\\n                        \"The certificate is signed with an unacceptable hash.\")  \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_BAD_PK,                                                  \\\n                        \"MBEDTLS_X509_BADCERT_BAD_PK\",                                                \\\n                        \"The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA).\")  \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_BAD_KEY,                                                            \\\n                        \"MBEDTLS_X509_BADCERT_BAD_KEY\",                                                          \\\n                        \"The certificate is signed with an unacceptable key (eg bad curve, RSA too short).\")    \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_BAD_MD,                          \\\n                        \"MBEDTLS_X509_BADCRL_BAD_MD\",                        \\\n                        \"The CRL is signed with an unacceptable hash.\")     \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_BAD_PK,                                            \\\n                        \"MBEDTLS_X509_BADCRL_BAD_PK\",                                          \\\n                        \"The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA).\")   \\\n    X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_BAD_KEY,                                                    \\\n                        \"MBEDTLS_X509_BADCRL_BAD_KEY\",                                                  \\\n                        \"The CRL is signed with an unacceptable key (eg bad curve, RSA too short).\")\n\n/**\n * Container for writing a certificate (CRT)\n */\ntypedef struct mbedtls_x509write_cert {\n    int MBEDTLS_PRIVATE(version);\n    unsigned char MBEDTLS_PRIVATE(serial)[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN];\n    size_t MBEDTLS_PRIVATE(serial_len);\n    mbedtls_pk_context *MBEDTLS_PRIVATE(subject_key);\n    mbedtls_pk_context *MBEDTLS_PRIVATE(issuer_key);\n    mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject);\n    mbedtls_asn1_named_data *MBEDTLS_PRIVATE(issuer);\n    mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg);\n    char MBEDTLS_PRIVATE(not_before)[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1];\n    char MBEDTLS_PRIVATE(not_after)[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1];\n    mbedtls_asn1_named_data *MBEDTLS_PRIVATE(extensions);\n}\nmbedtls_x509write_cert;\n\n/**\n * \\brief           Set Subject Alternative Name\n *\n * \\param ctx       Certificate context to use\n * \\param san_list  List of SAN values\n *\n * \\return          0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED\n *\n * \\note            \"dnsName\", \"uniformResourceIdentifier\", \"IP address\",\n *                  \"otherName\", and \"DirectoryName\", as defined in RFC 5280,\n *                  are supported.\n */\nint mbedtls_x509write_crt_set_subject_alternative_name(mbedtls_x509write_cert *ctx,\n                                                       const mbedtls_x509_san_list *san_list);\n\n/**\n * Item in a verification chain: cert and flags for it\n */\ntypedef struct {\n    mbedtls_x509_crt *MBEDTLS_PRIVATE(crt);\n    uint32_t MBEDTLS_PRIVATE(flags);\n} mbedtls_x509_crt_verify_chain_item;\n\n/**\n * Max size of verification chain: end-entity + intermediates + trusted root\n */\n#define MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE  (MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2)\n\n/**\n * Verification chain as built by \\c mbedtls_crt_verify_chain()\n */\ntypedef struct {\n    mbedtls_x509_crt_verify_chain_item MBEDTLS_PRIVATE(items)[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE];\n    unsigned MBEDTLS_PRIVATE(len);\n\n#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)\n    /* This stores the list of potential trusted signers obtained from\n     * the CA callback used for the CRT verification, if configured.\n     * We must track it somewhere because the callback passes its\n     * ownership to the caller. */\n    mbedtls_x509_crt *MBEDTLS_PRIVATE(trust_ca_cb_result);\n#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */\n} mbedtls_x509_crt_verify_chain;\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n\n/**\n * \\brief       Context for resuming X.509 verify operations\n */\ntypedef struct {\n    /* for check_signature() */\n    mbedtls_pk_restart_ctx MBEDTLS_PRIVATE(pk);\n\n    /* for find_parent_in() */\n    mbedtls_x509_crt *MBEDTLS_PRIVATE(parent); /* non-null iff parent_in in progress */\n    mbedtls_x509_crt *MBEDTLS_PRIVATE(fallback_parent);\n    int MBEDTLS_PRIVATE(fallback_signature_is_good);\n\n    /* for find_parent() */\n    int MBEDTLS_PRIVATE(parent_is_trusted); /* -1 if find_parent is not in progress */\n\n    /* for verify_chain() */\n    enum {\n        x509_crt_rs_none,\n        x509_crt_rs_find_parent,\n    } MBEDTLS_PRIVATE(in_progress);  /* none if no operation is in progress */\n    int MBEDTLS_PRIVATE(self_cnt);\n    mbedtls_x509_crt_verify_chain MBEDTLS_PRIVATE(ver_chain);\n\n} mbedtls_x509_crt_restart_ctx;\n\n#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n\n/* Now we can declare functions that take a pointer to that */\ntypedef void mbedtls_x509_crt_restart_ctx;\n\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n/**\n * Default security profile. Should provide a good balance between security\n * and compatibility with current deployments.\n *\n * This profile permits:\n * - SHA2 hashes with at least 256 bits: SHA-256, SHA-384, SHA-512.\n * - Elliptic curves with 255 bits and above except secp256k1.\n * - RSA with 2048 bits and above.\n *\n * New minor versions of Mbed TLS may extend this profile, for example if\n * new algorithms are added to the library. New minor versions of Mbed TLS will\n * not reduce this profile unless serious security concerns require it.\n */\nextern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default;\n\n/**\n * Expected next default profile. Recommended for new deployments.\n * Currently targets a 128-bit security level, except for allowing RSA-2048.\n * This profile may change at any time.\n */\nextern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next;\n\n/**\n * NSA Suite B profile.\n */\nextern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb;\n\n/**\n * Empty profile that allows nothing. Useful as a basis for constructing\n * custom profiles.\n */\nextern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none;\n\n/**\n * \\brief          Parse a single DER formatted certificate and add it\n *                 to the end of the provided chained list.\n *\n * \\note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                 subsystem must have been initialized by calling\n *                 psa_crypto_init() before calling this function.\n *\n * \\param chain    The pointer to the start of the CRT chain to attach to.\n *                 When parsing the first CRT in a chain, this should point\n *                 to an instance of ::mbedtls_x509_crt initialized through\n *                 mbedtls_x509_crt_init().\n * \\param buf      The buffer holding the DER encoded certificate.\n * \\param buflen   The size in Bytes of \\p buf.\n *\n * \\note           This function makes an internal copy of the CRT buffer\n *                 \\p buf. In particular, \\p buf may be destroyed or reused\n *                 after this call returns. To avoid duplicating the CRT\n *                 buffer (at the cost of stricter lifetime constraints),\n *                 use mbedtls_x509_crt_parse_der_nocopy() instead.\n *\n * \\return         \\c 0 if successful.\n * \\return         A negative error code on failure.\n */\nint mbedtls_x509_crt_parse_der(mbedtls_x509_crt *chain,\n                               const unsigned char *buf,\n                               size_t buflen);\n\n/**\n * \\brief          The type of certificate extension callbacks.\n *\n *                 Callbacks of this type are passed to and used by the\n *                 mbedtls_x509_crt_parse_der_with_ext_cb() routine when\n *                 it encounters either an unsupported extension or a\n *                 \"certificate policies\" extension containing any\n *                 unsupported certificate policies.\n *                 Future versions of the library may invoke the callback\n *                 in other cases, if and when the need arises.\n *\n * \\param p_ctx    An opaque context passed to the callback.\n * \\param crt      The certificate being parsed.\n * \\param oid      The OID of the extension.\n * \\param critical Whether the extension is critical.\n * \\param p        Pointer to the start of the extension value\n *                 (the content of the OCTET STRING).\n * \\param end      End of extension value.\n *\n * \\note           The callback must fail and return a negative error code\n *                 if it can not parse or does not support the extension.\n *                 When the callback fails to parse a critical extension\n *                 mbedtls_x509_crt_parse_der_with_ext_cb() also fails.\n *                 When the callback fails to parse a non critical extension\n *                 mbedtls_x509_crt_parse_der_with_ext_cb() simply skips\n *                 the extension and continues parsing.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\ntypedef int (*mbedtls_x509_crt_ext_cb_t)(void *p_ctx,\n                                         mbedtls_x509_crt const *crt,\n                                         mbedtls_x509_buf const *oid,\n                                         int critical,\n                                         const unsigned char *p,\n                                         const unsigned char *end);\n\n/**\n * \\brief            Parse a single DER formatted certificate and add it\n *                   to the end of the provided chained list.\n *\n * \\note             If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                   subsystem must have been initialized by calling\n *                   psa_crypto_init() before calling this function.\n *\n * \\param chain      The pointer to the start of the CRT chain to attach to.\n *                   When parsing the first CRT in a chain, this should point\n *                   to an instance of ::mbedtls_x509_crt initialized through\n *                   mbedtls_x509_crt_init().\n * \\param buf        The buffer holding the DER encoded certificate.\n * \\param buflen     The size in Bytes of \\p buf.\n * \\param make_copy  When not zero this function makes an internal copy of the\n *                   CRT buffer \\p buf. In particular, \\p buf may be destroyed\n *                   or reused after this call returns.\n *                   When zero this function avoids duplicating the CRT buffer\n *                   by taking temporary ownership thereof until the CRT\n *                   is destroyed (like mbedtls_x509_crt_parse_der_nocopy())\n * \\param cb         A callback invoked for every unsupported certificate\n *                   extension.\n * \\param p_ctx      An opaque context passed to the callback.\n *\n * \\note             This call is functionally equivalent to\n *                   mbedtls_x509_crt_parse_der(), and/or\n *                   mbedtls_x509_crt_parse_der_nocopy()\n *                   but it calls the callback with every unsupported\n *                   certificate extension and additionally the\n *                   \"certificate policies\" extension if it contains any\n *                   unsupported certificate policies.\n *                   The callback must return a negative error code if it\n *                   does not know how to handle such an extension.\n *                   When the callback fails to parse a critical extension\n *                   mbedtls_x509_crt_parse_der_with_ext_cb() also fails.\n *                   When the callback fails to parse a non critical extension\n *                   mbedtls_x509_crt_parse_der_with_ext_cb() simply skips\n *                   the extension and continues parsing.\n *                   Future versions of the library may invoke the callback\n *                   in other cases, if and when the need arises.\n *\n * \\return           \\c 0 if successful.\n * \\return           A negative error code on failure.\n */\nint mbedtls_x509_crt_parse_der_with_ext_cb(mbedtls_x509_crt *chain,\n                                           const unsigned char *buf,\n                                           size_t buflen,\n                                           int make_copy,\n                                           mbedtls_x509_crt_ext_cb_t cb,\n                                           void *p_ctx);\n\n/**\n * \\brief          Parse a single DER formatted certificate and add it\n *                 to the end of the provided chained list. This is a\n *                 variant of mbedtls_x509_crt_parse_der() which takes\n *                 temporary ownership of the CRT buffer until the CRT\n *                 is destroyed.\n *\n * \\note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                 subsystem must have been initialized by calling\n *                 psa_crypto_init() before calling this function.\n *\n * \\param chain    The pointer to the start of the CRT chain to attach to.\n *                 When parsing the first CRT in a chain, this should point\n *                 to an instance of ::mbedtls_x509_crt initialized through\n *                 mbedtls_x509_crt_init().\n * \\param buf      The address of the readable buffer holding the DER encoded\n *                 certificate to use. On success, this buffer must be\n *                 retained and not be changed for the lifetime of the\n *                 CRT chain \\p chain, that is, until \\p chain is destroyed\n *                 through a call to mbedtls_x509_crt_free().\n * \\param buflen   The size in Bytes of \\p buf.\n *\n * \\note           This call is functionally equivalent to\n *                 mbedtls_x509_crt_parse_der(), but it avoids creating a\n *                 copy of the input buffer at the cost of stronger lifetime\n *                 constraints. This is useful in constrained environments\n *                 where duplication of the CRT cannot be tolerated.\n *\n * \\return         \\c 0 if successful.\n * \\return         A negative error code on failure.\n */\nint mbedtls_x509_crt_parse_der_nocopy(mbedtls_x509_crt *chain,\n                                      const unsigned char *buf,\n                                      size_t buflen);\n\n/**\n * \\brief          Parse one DER-encoded or one or more concatenated PEM-encoded\n *                 certificates and add them to the chained list.\n *\n *                 For CRTs in PEM encoding, the function parses permissively:\n *                 if at least one certificate can be parsed, the function\n *                 returns the number of certificates for which parsing failed\n *                 (hence \\c 0 if all certificates were parsed successfully).\n *                 If no certificate could be parsed, the function returns\n *                 the first (negative) error encountered during parsing.\n *\n *                 PEM encoded certificates may be interleaved by other data\n *                 such as human readable descriptions of their content, as\n *                 long as the certificates are enclosed in the PEM specific\n *                 '-----{BEGIN/END} CERTIFICATE-----' delimiters.\n *\n * \\note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                 subsystem must have been initialized by calling\n *                 psa_crypto_init() before calling this function.\n *\n * \\param chain    The chain to which to add the parsed certificates.\n * \\param buf      The buffer holding the certificate data in PEM or DER format.\n *                 For certificates in PEM encoding, this may be a concatenation\n *                 of multiple certificates; for DER encoding, the buffer must\n *                 comprise exactly one certificate.\n * \\param buflen   The size of \\p buf, including the terminating \\c NULL byte\n *                 in case of PEM encoded data.\n *\n * \\return         \\c 0 if all certificates were parsed successfully.\n * \\return         The (positive) number of certificates that couldn't\n *                 be parsed if parsing was partly successful (see above).\n * \\return         A negative X509 or PEM error code otherwise.\n *\n */\nint mbedtls_x509_crt_parse(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen);\n\n#if defined(MBEDTLS_FS_IO)\n/**\n * \\brief          Load one or more certificates and add them\n *                 to the chained list. Parses permissively. If some\n *                 certificates can be parsed, the result is the number\n *                 of failed certificates it encountered. If none complete\n *                 correctly, the first error is returned.\n *\n * \\note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                 subsystem must have been initialized by calling\n *                 psa_crypto_init() before calling this function.\n *\n * \\param chain    points to the start of the chain\n * \\param path     filename to read the certificates from\n *\n * \\return         0 if all certificates parsed successfully, a positive number\n *                 if partly successful or a specific X509 or PEM error code\n */\nint mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path);\n\n/**\n * \\brief          Load one or more certificate files from a path and add them\n *                 to the chained list. Parses permissively. If some\n *                 certificates can be parsed, the result is the number\n *                 of failed certificates it encountered. If none complete\n *                 correctly, the first error is returned.\n *\n * \\param chain    points to the start of the chain\n * \\param path     directory / folder to read the certificate files from\n *\n * \\return         0 if all certificates parsed successfully, a positive number\n *                 if partly successful or a specific X509 or PEM error code\n */\nint mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path);\n\n#endif /* MBEDTLS_FS_IO */\n\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\n/**\n * \\brief          Returns an informational string about the\n *                 certificate.\n *\n * \\param buf      Buffer to write to\n * \\param size     Maximum size of buffer\n * \\param prefix   A line prefix\n * \\param crt      The X509 certificate to represent\n *\n * \\return         The length of the string written (not including the\n *                 terminated nul byte), or a negative error code.\n */\nint mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix,\n                          const mbedtls_x509_crt *crt);\n\n/**\n * \\brief          Returns an informational string about the\n *                 verification status of a certificate.\n *\n * \\param buf      Buffer to write to\n * \\param size     Maximum size of buffer\n * \\param prefix   A line prefix\n * \\param flags    Verification flags created by mbedtls_x509_crt_verify()\n *\n * \\return         The length of the string written (not including the\n *                 terminated nul byte), or a negative error code.\n */\nint mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix,\n                                 uint32_t flags);\n#endif /* !MBEDTLS_X509_REMOVE_INFO */\n\n/**\n * \\brief          Verify a chain of certificates.\n *\n *                 The verify callback is a user-supplied callback that\n *                 can clear / modify / add flags for a certificate. If set,\n *                 the verification callback is called for each\n *                 certificate in the chain (from the trust-ca down to the\n *                 presented crt). The parameters for the callback are:\n *                 (void *parameter, mbedtls_x509_crt *crt, int certificate_depth,\n *                 int *flags). With the flags representing current flags for\n *                 that specific certificate and the certificate depth from\n *                 the bottom (Peer cert depth = 0).\n *\n *                 All flags left after returning from the callback\n *                 are also returned to the application. The function should\n *                 return 0 for anything (including invalid certificates)\n *                 other than fatal error, as a non-zero return code\n *                 immediately aborts the verification process. For fatal\n *                 errors, a specific error code should be used (different\n *                 from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED which should not\n *                 be returned at this point), or MBEDTLS_ERR_X509_FATAL_ERROR\n *                 can be used if no better code is available.\n *\n * \\note           In case verification failed, the results can be displayed\n *                 using \\c mbedtls_x509_crt_verify_info()\n *\n * \\note           Same as \\c mbedtls_x509_crt_verify_with_profile() with the\n *                 default security profile.\n *\n * \\note           It is your responsibility to provide up-to-date CRLs for\n *                 all trusted CAs. If no CRL is provided for the CA that was\n *                 used to sign the certificate, CRL verification is skipped\n *                 silently, that is *without* setting any flag.\n *\n * \\note           The \\c trust_ca list can contain two types of certificates:\n *                 (1) those of trusted root CAs, so that certificates\n *                 chaining up to those CAs will be trusted, and (2)\n *                 self-signed end-entity certificates to be trusted (for\n *                 specific peers you know) - in that case, the self-signed\n *                 certificate doesn't need to have the CA bit set.\n *\n * \\param crt      The certificate chain to be verified.\n * \\param trust_ca The list of trusted CAs.\n * \\param ca_crl   The list of CRLs for trusted CAs.\n * \\param cn       The expected Common Name. This will be checked to be\n *                 present in the certificate's subjectAltNames extension or,\n *                 if this extension is absent, as a CN component in its\n *                 Subject name. DNS names and IP addresses are fully\n *                 supported, while the URI subtype is partially supported:\n *                 only exact matching, without any normalization procedures\n *                 described in 7.4 of RFC5280, will result in a positive\n *                 URI verification.\n *                 This may be \\c NULL if the CN need not be verified.\n * \\param flags    The address at which to store the result of the verification.\n *                 If the verification couldn't be completed, the flag value is\n *                 set to (uint32_t) -1.\n * \\param f_vrfy   The verification callback to use. See the documentation\n *                 of mbedtls_x509_crt_verify() for more information.\n * \\param p_vrfy   The context to be passed to \\p f_vrfy.\n *\n * \\return         \\c 0 if the chain is valid with respect to the\n *                 passed CN, CAs, CRLs and security profile.\n * \\return         #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the\n *                 certificate chain verification failed. In this case,\n *                 \\c *flags will have one or more\n *                 \\c MBEDTLS_X509_BADCERT_XXX or \\c MBEDTLS_X509_BADCRL_XXX\n *                 flags set.\n * \\return         Another negative error code in case of a fatal error\n *                 encountered during the verification process.\n */\nint mbedtls_x509_crt_verify(mbedtls_x509_crt *crt,\n                            mbedtls_x509_crt *trust_ca,\n                            mbedtls_x509_crl *ca_crl,\n                            const char *cn, uint32_t *flags,\n                            int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),\n                            void *p_vrfy);\n\n/**\n * \\brief          Verify a chain of certificates with respect to\n *                 a configurable security profile.\n *\n * \\note           Same as \\c mbedtls_x509_crt_verify(), but with explicit\n *                 security profile.\n *\n * \\note           The restrictions on keys (RSA minimum size, allowed curves\n *                 for ECDSA) apply to all certificates: trusted root,\n *                 intermediate CAs if any, and end entity certificate.\n *\n * \\param crt      The certificate chain to be verified.\n * \\param trust_ca The list of trusted CAs.\n * \\param ca_crl   The list of CRLs for trusted CAs.\n * \\param profile  The security profile to use for the verification.\n * \\param cn       The expected Common Name. This may be \\c NULL if the\n *                 CN need not be verified.\n * \\param flags    The address at which to store the result of the verification.\n *                 If the verification couldn't be completed, the flag value is\n *                 set to (uint32_t) -1.\n * \\param f_vrfy   The verification callback to use. See the documentation\n *                 of mbedtls_x509_crt_verify() for more information.\n * \\param p_vrfy   The context to be passed to \\p f_vrfy.\n *\n * \\return         \\c 0 if the chain is valid with respect to the\n *                 passed CN, CAs, CRLs and security profile.\n * \\return         #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the\n *                 certificate chain verification failed. In this case,\n *                 \\c *flags will have one or more\n *                 \\c MBEDTLS_X509_BADCERT_XXX or \\c MBEDTLS_X509_BADCRL_XXX\n *                 flags set.\n * \\return         Another negative error code in case of a fatal error\n *                 encountered during the verification process.\n */\nint mbedtls_x509_crt_verify_with_profile(mbedtls_x509_crt *crt,\n                                         mbedtls_x509_crt *trust_ca,\n                                         mbedtls_x509_crl *ca_crl,\n                                         const mbedtls_x509_crt_profile *profile,\n                                         const char *cn, uint32_t *flags,\n                                         int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),\n                                         void *p_vrfy);\n\n/**\n * \\brief          Restartable version of \\c mbedtls_crt_verify_with_profile()\n *\n * \\note           Performs the same job as \\c mbedtls_crt_verify_with_profile()\n *                 but can return early and restart according to the limit\n *                 set with \\c mbedtls_ecp_set_max_ops() to reduce blocking.\n *\n * \\param crt      The certificate chain to be verified.\n * \\param trust_ca The list of trusted CAs.\n * \\param ca_crl   The list of CRLs for trusted CAs.\n * \\param profile  The security profile to use for the verification.\n * \\param cn       The expected Common Name. This may be \\c NULL if the\n *                 CN need not be verified.\n * \\param flags    The address at which to store the result of the verification.\n *                 If the verification couldn't be completed, the flag value is\n *                 set to (uint32_t) -1.\n * \\param f_vrfy   The verification callback to use. See the documentation\n *                 of mbedtls_x509_crt_verify() for more information.\n * \\param p_vrfy   The context to be passed to \\p f_vrfy.\n * \\param rs_ctx   The restart context to use. This may be set to \\c NULL\n *                 to disable restartable ECC.\n *\n * \\return         See \\c mbedtls_crt_verify_with_profile(), or\n * \\return         #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of\n *                 operations was reached: see \\c mbedtls_ecp_set_max_ops().\n */\nint mbedtls_x509_crt_verify_restartable(mbedtls_x509_crt *crt,\n                                        mbedtls_x509_crt *trust_ca,\n                                        mbedtls_x509_crl *ca_crl,\n                                        const mbedtls_x509_crt_profile *profile,\n                                        const char *cn, uint32_t *flags,\n                                        int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),\n                                        void *p_vrfy,\n                                        mbedtls_x509_crt_restart_ctx *rs_ctx);\n\n/**\n * \\brief               The type of trusted certificate callbacks.\n *\n *                      Callbacks of this type are passed to and used by the CRT\n *                      verification routine mbedtls_x509_crt_verify_with_ca_cb()\n *                      when looking for trusted signers of a given certificate.\n *\n *                      On success, the callback returns a list of trusted\n *                      certificates to be considered as potential signers\n *                      for the input certificate.\n *\n * \\param p_ctx         An opaque context passed to the callback.\n * \\param child         The certificate for which to search a potential signer.\n *                      This will point to a readable certificate.\n * \\param candidate_cas The address at which to store the address of the first\n *                      entry in the generated linked list of candidate signers.\n *                      This will not be \\c NULL.\n *\n * \\note                The callback must only return a non-zero value on a\n *                      fatal error. If, in contrast, the search for a potential\n *                      signer completes without a single candidate, the\n *                      callback must return \\c 0 and set \\c *candidate_cas\n *                      to \\c NULL.\n *\n * \\return              \\c 0 on success. In this case, \\c *candidate_cas points\n *                      to a heap-allocated linked list of instances of\n *                      ::mbedtls_x509_crt, and ownership of this list is passed\n *                      to the caller.\n * \\return              A negative error code on failure.\n */\ntypedef int (*mbedtls_x509_crt_ca_cb_t)(void *p_ctx,\n                                        mbedtls_x509_crt const *child,\n                                        mbedtls_x509_crt **candidate_cas);\n\n#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)\n/**\n * \\brief          Version of \\c mbedtls_x509_crt_verify_with_profile() which\n *                 uses a callback to acquire the list of trusted CA\n *                 certificates.\n *\n * \\param crt      The certificate chain to be verified.\n * \\param f_ca_cb  The callback to be used to query for potential signers\n *                 of a given child certificate. See the documentation of\n *                 ::mbedtls_x509_crt_ca_cb_t for more information.\n * \\param p_ca_cb  The opaque context to be passed to \\p f_ca_cb.\n * \\param profile  The security profile for the verification.\n * \\param cn       The expected Common Name. This may be \\c NULL if the\n *                 CN need not be verified.\n * \\param flags    The address at which to store the result of the verification.\n *                 If the verification couldn't be completed, the flag value is\n *                 set to (uint32_t) -1.\n * \\param f_vrfy   The verification callback to use. See the documentation\n *                 of mbedtls_x509_crt_verify() for more information.\n * \\param p_vrfy   The context to be passed to \\p f_vrfy.\n *\n * \\return         See \\c mbedtls_crt_verify_with_profile().\n */\nint mbedtls_x509_crt_verify_with_ca_cb(mbedtls_x509_crt *crt,\n                                       mbedtls_x509_crt_ca_cb_t f_ca_cb,\n                                       void *p_ca_cb,\n                                       const mbedtls_x509_crt_profile *profile,\n                                       const char *cn, uint32_t *flags,\n                                       int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),\n                                       void *p_vrfy);\n\n#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */\n\n/**\n * \\brief          Check usage of certificate against keyUsage extension.\n *\n * \\param crt      Leaf certificate used.\n * \\param usage    Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT\n *                 before using the certificate to perform an RSA key\n *                 exchange).\n *\n * \\note           Except for decipherOnly and encipherOnly, a bit set in the\n *                 usage argument means this bit MUST be set in the\n *                 certificate. For decipherOnly and encipherOnly, it means\n *                 that bit MAY be set.\n *\n * \\return         0 is these uses of the certificate are allowed,\n *                 MBEDTLS_ERR_X509_BAD_INPUT_DATA if the keyUsage extension\n *                 is present but does not match the usage argument.\n *\n * \\note           You should only call this function on leaf certificates, on\n *                 (intermediate) CAs the keyUsage extension is automatically\n *                 checked by \\c mbedtls_x509_crt_verify().\n */\nint mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt,\n                                     unsigned int usage);\n\n/**\n * \\brief           Check usage of certificate against extendedKeyUsage.\n *\n * \\param crt       Leaf certificate used.\n * \\param usage_oid Intended usage (eg MBEDTLS_OID_SERVER_AUTH or\n *                  MBEDTLS_OID_CLIENT_AUTH).\n * \\param usage_len Length of usage_oid (eg given by MBEDTLS_OID_SIZE()).\n *\n * \\return          0 if this use of the certificate is allowed,\n *                  MBEDTLS_ERR_X509_BAD_INPUT_DATA if not.\n *\n * \\note            Usually only makes sense on leaf certificates.\n */\nint mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt *crt,\n                                              const char *usage_oid,\n                                              size_t usage_len);\n\n#if defined(MBEDTLS_X509_CRL_PARSE_C)\n/**\n * \\brief          Verify the certificate revocation status\n *\n * \\param crt      a certificate to be verified\n * \\param crl      the CRL to verify against\n *\n * \\return         1 if the certificate is revoked, 0 otherwise\n *\n */\nint mbedtls_x509_crt_is_revoked(const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl);\n#endif /* MBEDTLS_X509_CRL_PARSE_C */\n\n/**\n * \\brief          Initialize a certificate (chain)\n *\n * \\param crt      Certificate chain to initialize\n */\nvoid mbedtls_x509_crt_init(mbedtls_x509_crt *crt);\n\n/**\n * \\brief          Unallocate all certificate data\n *\n * \\param crt      Certificate chain to free\n */\nvoid mbedtls_x509_crt_free(mbedtls_x509_crt *crt);\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n/**\n * \\brief           Initialize a restart context\n */\nvoid mbedtls_x509_crt_restart_init(mbedtls_x509_crt_restart_ctx *ctx);\n\n/**\n * \\brief           Free the components of a restart context\n */\nvoid mbedtls_x509_crt_restart_free(mbedtls_x509_crt_restart_ctx *ctx);\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n/**\n * \\brief               Query certificate for given extension type\n *\n * \\param[in] ctx       Certificate context to be queried, must not be \\c NULL\n * \\param ext_type      Extension type being queried for, must be a valid\n *                      extension type. Must be one of the MBEDTLS_X509_EXT_XXX\n *                      values\n *\n * \\return              0 if the given extension type is not present,\n *                      non-zero otherwise\n */\nstatic inline int mbedtls_x509_crt_has_ext_type(const mbedtls_x509_crt *ctx,\n                                                int ext_type)\n{\n    return ctx->MBEDTLS_PRIVATE(ext_types) & ext_type;\n}\n\n/**\n * \\brief               Access the ca_istrue field\n *\n * \\param[in] crt       Certificate to be queried, must not be \\c NULL\n *\n * \\return              \\c 1 if this a CA certificate \\c 0 otherwise.\n * \\return              MBEDTLS_ERR_X509_INVALID_EXTENSIONS if the certificate does not contain\n *                      the Optional Basic Constraint extension.\n *\n */\nint mbedtls_x509_crt_get_ca_istrue(const mbedtls_x509_crt *crt);\n\n/** \\} name Structures and functions for parsing and writing X.509 certificates */\n\n#if defined(MBEDTLS_X509_CRT_WRITE_C)\n/**\n * \\brief           Initialize a CRT writing context\n *\n * \\param ctx       CRT context to initialize\n */\nvoid mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx);\n\n/**\n * \\brief           Set the version for a Certificate\n *                  Default: MBEDTLS_X509_CRT_VERSION_3\n *\n * \\param ctx       CRT context to use\n * \\param version   version to set (MBEDTLS_X509_CRT_VERSION_1, MBEDTLS_X509_CRT_VERSION_2 or\n *                                  MBEDTLS_X509_CRT_VERSION_3)\n */\nvoid mbedtls_x509write_crt_set_version(mbedtls_x509write_cert *ctx, int version);\n\n#if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n/**\n * \\brief           Set the serial number for a Certificate.\n *\n * \\deprecated      This function is deprecated and will be removed in a\n *                  future version of the library. Please use\n *                  mbedtls_x509write_crt_set_serial_raw() instead.\n *\n * \\note            Even though the MBEDTLS_BIGNUM_C guard looks redundant since\n *                  X509 depends on PK and PK depends on BIGNUM, this emphasizes\n *                  a direct dependency between X509 and BIGNUM which is going\n *                  to be deprecated in the future.\n *\n * \\param ctx       CRT context to use\n * \\param serial    serial number to set\n *\n * \\return          0 if successful\n */\nint MBEDTLS_DEPRECATED mbedtls_x509write_crt_set_serial(\n    mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial);\n#endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED\n\n/**\n * \\brief           Set the serial number for a Certificate.\n *\n * \\param ctx          CRT context to use\n * \\param serial       A raw array of bytes containing the serial number in big\n *                     endian format\n * \\param serial_len   Length of valid bytes (expressed in bytes) in \\p serial\n *                     input buffer\n *\n * \\return          0 if successful, or\n *                  MBEDTLS_ERR_X509_BAD_INPUT_DATA if the provided input buffer\n *                  is too big (longer than MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN)\n */\nint mbedtls_x509write_crt_set_serial_raw(mbedtls_x509write_cert *ctx,\n                                         unsigned char *serial, size_t serial_len);\n\n/**\n * \\brief           Set the validity period for a Certificate\n *                  Timestamps should be in string format for UTC timezone\n *                  i.e. \"YYYYMMDDhhmmss\"\n *                  e.g. \"20131231235959\" for December 31st 2013\n *                       at 23:59:59\n *\n * \\param ctx       CRT context to use\n * \\param not_before    not_before timestamp\n * \\param not_after     not_after timestamp\n *\n * \\return          0 if timestamp was parsed successfully, or\n *                  a specific error code\n */\nint mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx, const char *not_before,\n                                       const char *not_after);\n\n/**\n * \\brief           Set the issuer name for a Certificate\n *                  Issuer names should contain a comma-separated list\n *                  of OID types and values:\n *                  e.g. \"C=UK,O=ARM,CN=Mbed TLS CA\"\n *\n * \\param ctx           CRT context to use\n * \\param issuer_name   issuer name to set\n *\n * \\return          0 if issuer name was parsed successfully, or\n *                  a specific error code\n */\nint mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert *ctx,\n                                          const char *issuer_name);\n\n/**\n * \\brief           Set the subject name for a Certificate\n *                  Subject names should contain a comma-separated list\n *                  of OID types and values:\n *                  e.g. \"C=UK,O=ARM,CN=Mbed TLS Server 1\"\n *\n * \\param ctx           CRT context to use\n * \\param subject_name  subject name to set\n *\n * \\return          0 if subject name was parsed successfully, or\n *                  a specific error code\n */\nint mbedtls_x509write_crt_set_subject_name(mbedtls_x509write_cert *ctx,\n                                           const char *subject_name);\n\n/**\n * \\brief           Set the subject public key for the certificate\n *\n * \\param ctx       CRT context to use\n * \\param key       public key to include\n */\nvoid mbedtls_x509write_crt_set_subject_key(mbedtls_x509write_cert *ctx, mbedtls_pk_context *key);\n\n/**\n * \\brief           Set the issuer key used for signing the certificate\n *\n * \\param ctx       CRT context to use\n * \\param key       private key to sign with\n */\nvoid mbedtls_x509write_crt_set_issuer_key(mbedtls_x509write_cert *ctx, mbedtls_pk_context *key);\n\n/**\n * \\brief           Set the MD algorithm to use for the signature\n *                  (e.g. MBEDTLS_MD_SHA1)\n *\n * \\param ctx       CRT context to use\n * \\param md_alg    MD algorithm to use\n */\nvoid mbedtls_x509write_crt_set_md_alg(mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg);\n\n/**\n * \\brief           Generic function to add to or replace an extension in the\n *                  CRT\n *\n * \\param ctx       CRT context to use\n * \\param oid       OID of the extension\n * \\param oid_len   length of the OID\n * \\param critical  if the extension is critical (per the RFC's definition)\n * \\param val       value of the extension OCTET STRING\n * \\param val_len   length of the value data\n *\n * \\return          0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED\n */\nint mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert *ctx,\n                                        const char *oid, size_t oid_len,\n                                        int critical,\n                                        const unsigned char *val, size_t val_len);\n\n/**\n * \\brief           Set the basicConstraints extension for a CRT\n *\n * \\param ctx       CRT context to use\n * \\param is_ca     is this a CA certificate\n * \\param max_pathlen   maximum length of certificate chains below this\n *                      certificate (only for CA certificates, -1 is\n *                      unlimited)\n *\n * \\return          0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED\n */\nint mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert *ctx,\n                                                int is_ca, int max_pathlen);\n\n#if defined(MBEDTLS_MD_CAN_SHA1)\n/**\n * \\brief           Set the subjectKeyIdentifier extension for a CRT\n *                  Requires that mbedtls_x509write_crt_set_subject_key() has been\n *                  called before\n *\n * \\param ctx       CRT context to use\n *\n * \\return          0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED\n */\nint mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx);\n\n/**\n * \\brief           Set the authorityKeyIdentifier extension for a CRT\n *                  Requires that mbedtls_x509write_crt_set_issuer_key() has been\n *                  called before\n *\n * \\param ctx       CRT context to use\n *\n * \\return          0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED\n */\nint mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx);\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n\n/**\n * \\brief           Set the Key Usage Extension flags\n *                  (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN)\n *\n * \\param ctx       CRT context to use\n * \\param key_usage key usage flags to set\n *\n * \\return          0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED\n */\nint mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert *ctx,\n                                        unsigned int key_usage);\n\n/**\n * \\brief           Set the Extended Key Usage Extension\n *                  (e.g. MBEDTLS_OID_SERVER_AUTH)\n *\n * \\param ctx       CRT context to use\n * \\param exts      extended key usage extensions to set, a sequence of\n *                  MBEDTLS_ASN1_OID objects\n *\n * \\return          0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED\n */\nint mbedtls_x509write_crt_set_ext_key_usage(mbedtls_x509write_cert *ctx,\n                                            const mbedtls_asn1_sequence *exts);\n\n/**\n * \\brief           Set the Netscape Cert Type flags\n *                  (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL)\n *\n * \\param ctx           CRT context to use\n * \\param ns_cert_type  Netscape Cert Type flags to set\n *\n * \\return          0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED\n */\nint mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert *ctx,\n                                           unsigned char ns_cert_type);\n\n/**\n * \\brief           Free the contents of a CRT write context\n *\n * \\param ctx       CRT context to free\n */\nvoid mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx);\n\n/**\n * \\brief           Write a built up certificate to a X509 DER structure\n *                  Note: data is written at the end of the buffer! Use the\n *                        return value to determine where you should start\n *                        using the buffer\n *\n * \\param ctx       certificate to write away\n * \\param buf       buffer to write to\n * \\param size      size of the buffer\n * \\param f_rng     RNG function. This must not be \\c NULL.\n * \\param p_rng     RNG parameter\n *\n * \\return          length of data written if successful, or a specific\n *                  error code\n *\n * \\note            \\p f_rng is used for the signature operation.\n */\nint mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size,\n                              mbedtls_f_rng_t *f_rng,\n                              void *p_rng);\n\n#if defined(MBEDTLS_PEM_WRITE_C)\n/**\n * \\brief           Write a built up certificate to a X509 PEM string\n *\n * \\param ctx       certificate to write away\n * \\param buf       buffer to write to\n * \\param size      size of the buffer\n * \\param f_rng     RNG function. This must not be \\c NULL.\n * \\param p_rng     RNG parameter\n *\n * \\return          0 if successful, or a specific error code\n *\n * \\note            \\p f_rng is used for the signature operation.\n */\nint mbedtls_x509write_crt_pem(mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size,\n                              mbedtls_f_rng_t *f_rng,\n                              void *p_rng);\n#endif /* MBEDTLS_PEM_WRITE_C */\n#endif /* MBEDTLS_X509_CRT_WRITE_C */\n\n/** \\} addtogroup x509_module */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* mbedtls_x509_crt.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/mbedtls/x509_csr.h",
    "content": "/**\n * \\file x509_csr.h\n *\n * \\brief X.509 certificate signing request parsing and writing\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_X509_CSR_H\n#define MBEDTLS_X509_CSR_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/x509.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\addtogroup x509_module\n * \\{ */\n\n/**\n * \\name Structures and functions for X.509 Certificate Signing Requests (CSR)\n * \\{\n */\n\n/**\n * Certificate Signing Request (CSR) structure.\n *\n * Some fields of this structure are publicly readable. Do not modify\n * them except via Mbed TLS library functions: the effect of modifying\n * those fields or the data that those fields point to is unspecified.\n */\ntypedef struct mbedtls_x509_csr {\n    mbedtls_x509_buf raw;           /**< The raw CSR data (DER). */\n    mbedtls_x509_buf cri;           /**< The raw CertificateRequestInfo body (DER). */\n\n    int version;            /**< CSR version (1=v1). */\n\n    mbedtls_x509_buf  subject_raw;  /**< The raw subject data (DER). */\n    mbedtls_x509_name subject;      /**< The parsed subject data (named information object). */\n\n    mbedtls_pk_context pk;          /**< Container for the public key context. */\n\n    unsigned int key_usage;     /**< Optional key usage extension value: See the values in x509.h */\n    unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */\n    mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension. These can be later parsed by mbedtls_x509_parse_subject_alt_name. */\n\n    int MBEDTLS_PRIVATE(ext_types);              /**< Bit string containing detected and parsed extensions */\n\n    mbedtls_x509_buf sig_oid;\n    mbedtls_x509_buf MBEDTLS_PRIVATE(sig);\n    mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md);       /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */\n    mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk);       /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */\n    void *MBEDTLS_PRIVATE(sig_opts);         /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */\n}\nmbedtls_x509_csr;\n\n/**\n * Container for writing a CSR\n */\ntypedef struct mbedtls_x509write_csr {\n    mbedtls_pk_context *MBEDTLS_PRIVATE(key);\n    mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject);\n    mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg);\n    mbedtls_asn1_named_data *MBEDTLS_PRIVATE(extensions);\n}\nmbedtls_x509write_csr;\n\n#if defined(MBEDTLS_X509_CSR_PARSE_C)\n/**\n * \\brief          Load a Certificate Signing Request (CSR) in DER format\n *\n * \\note           Any unsupported requested extensions are silently\n *                 ignored, unless the critical flag is set, in which case\n *                 the CSR is rejected.\n *\n * \\note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                 subsystem must have been initialized by calling\n *                 psa_crypto_init() before calling this function.\n *\n * \\param csr      CSR context to fill\n * \\param buf      buffer holding the CRL data\n * \\param buflen   size of the buffer\n *\n * \\return         0 if successful, or a specific X509 error code\n */\nint mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,\n                               const unsigned char *buf, size_t buflen);\n\n/**\n * \\brief          The type of certificate extension callbacks.\n *\n *                 Callbacks of this type are passed to and used by the\n *                 mbedtls_x509_csr_parse_der_with_ext_cb() routine when\n *                 it encounters either an unsupported extension.\n *                 Future versions of the library may invoke the callback\n *                 in other cases, if and when the need arises.\n *\n * \\param p_ctx    An opaque context passed to the callback.\n * \\param csr      The CSR being parsed.\n * \\param oid      The OID of the extension.\n * \\param critical Whether the extension is critical.\n * \\param p        Pointer to the start of the extension value\n *                 (the content of the OCTET STRING).\n * \\param end      End of extension value.\n *\n * \\note           The callback must fail and return a negative error code\n *                 if it can not parse or does not support the extension.\n *                 When the callback fails to parse a critical extension\n *                 mbedtls_x509_csr_parse_der_with_ext_cb() also fails.\n *                 When the callback fails to parse a non critical extension\n *                 mbedtls_x509_csr_parse_der_with_ext_cb() simply skips\n *                 the extension and continues parsing.\n *\n * \\return         \\c 0 on success.\n * \\return         A negative error code on failure.\n */\ntypedef int (*mbedtls_x509_csr_ext_cb_t)(void *p_ctx,\n                                         mbedtls_x509_csr const *csr,\n                                         mbedtls_x509_buf const *oid,\n                                         int critical,\n                                         const unsigned char *p,\n                                         const unsigned char *end);\n\n/**\n * \\brief          Load a Certificate Signing Request (CSR) in DER format\n *\n * \\note           Any unsupported requested extensions are silently\n *                 ignored, unless the critical flag is set, in which case\n *                 the result of the callback function decides whether\n *                 CSR is rejected.\n *\n * \\note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                 subsystem must have been initialized by calling\n *                 psa_crypto_init() before calling this function.\n *\n * \\param csr      CSR context to fill\n * \\param buf      buffer holding the CRL data\n * \\param buflen   size of the buffer\n * \\param cb       A callback invoked for every unsupported certificate\n *                 extension.\n * \\param p_ctx    An opaque context passed to the callback.\n *\n * \\return         0 if successful, or a specific X509 error code\n */\nint mbedtls_x509_csr_parse_der_with_ext_cb(mbedtls_x509_csr *csr,\n                                           const unsigned char *buf, size_t buflen,\n                                           mbedtls_x509_csr_ext_cb_t cb,\n                                           void *p_ctx);\n\n/**\n * \\brief          Load a Certificate Signing Request (CSR), DER or PEM format\n *\n * \\note           See notes for \\c mbedtls_x509_csr_parse_der()\n *\n * \\note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto\n *                 subsystem must have been initialized by calling\n *                 psa_crypto_init() before calling this function.\n *\n * \\param csr      CSR context to fill\n * \\param buf      buffer holding the CRL data\n * \\param buflen   size of the buffer\n *                 (including the terminating null byte for PEM data)\n *\n * \\return         0 if successful, or a specific X509 or PEM error code\n */\nint mbedtls_x509_csr_parse(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen);\n\n#if defined(MBEDTLS_FS_IO)\n/**\n * \\brief          Load a Certificate Signing Request (CSR)\n *\n * \\note           See notes for \\c mbedtls_x509_csr_parse()\n *\n * \\param csr      CSR context to fill\n * \\param path     filename to read the CSR from\n *\n * \\return         0 if successful, or a specific X509 or PEM error code\n */\nint mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path);\n#endif /* MBEDTLS_FS_IO */\n\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\n/**\n * \\brief          Returns an informational string about the\n *                 CSR.\n *\n * \\param buf      Buffer to write to\n * \\param size     Maximum size of buffer\n * \\param prefix   A line prefix\n * \\param csr      The X509 CSR to represent\n *\n * \\return         The length of the string written (not including the\n *                 terminated nul byte), or a negative error code.\n */\nint mbedtls_x509_csr_info(char *buf, size_t size, const char *prefix,\n                          const mbedtls_x509_csr *csr);\n#endif /* !MBEDTLS_X509_REMOVE_INFO */\n\n/**\n * \\brief          Initialize a CSR\n *\n * \\param csr      CSR to initialize\n */\nvoid mbedtls_x509_csr_init(mbedtls_x509_csr *csr);\n\n/**\n * \\brief          Unallocate all CSR data\n *\n * \\param csr      CSR to free\n */\nvoid mbedtls_x509_csr_free(mbedtls_x509_csr *csr);\n#endif /* MBEDTLS_X509_CSR_PARSE_C */\n\n/** \\} name Structures and functions for X.509 Certificate Signing Requests (CSR) */\n\n#if defined(MBEDTLS_X509_CSR_WRITE_C)\n/**\n * \\brief           Initialize a CSR context\n *\n * \\param ctx       CSR context to initialize\n */\nvoid mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx);\n\n/**\n * \\brief           Set the subject name for a CSR\n *                  Subject names should contain a comma-separated list\n *                  of OID types and values:\n *                  e.g. \"C=UK,O=ARM,CN=Mbed TLS Server 1\"\n *\n * \\param ctx           CSR context to use\n * \\param subject_name  subject name to set\n *\n * \\return          0 if subject name was parsed successfully, or\n *                  a specific error code\n */\nint mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx,\n                                           const char *subject_name);\n\n/**\n * \\brief           Set the key for a CSR (public key will be included,\n *                  private key used to sign the CSR when writing it)\n *\n * \\param ctx       CSR context to use\n * \\param key       Asymmetric key to include\n */\nvoid mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, mbedtls_pk_context *key);\n\n/**\n * \\brief           Set the MD algorithm to use for the signature\n *                  (e.g. MBEDTLS_MD_SHA1)\n *\n * \\param ctx       CSR context to use\n * \\param md_alg    MD algorithm to use\n */\nvoid mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg);\n\n/**\n * \\brief           Set the Key Usage Extension flags\n *                  (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN)\n *\n * \\param ctx       CSR context to use\n * \\param key_usage key usage flags to set\n *\n * \\return          0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED\n *\n * \\note            The <code>decipherOnly</code> flag from the Key Usage\n *                  extension is represented by bit 8 (i.e.\n *                  <code>0x8000</code>), which cannot typically be represented\n *                  in an unsigned char. Therefore, the flag\n *                  <code>decipherOnly</code> (i.e.\n *                  #MBEDTLS_X509_KU_DECIPHER_ONLY) cannot be set using this\n *                  function.\n */\nint mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage);\n\n/**\n * \\brief           Set Subject Alternative Name\n *\n * \\param ctx       CSR context to use\n * \\param san_list  List of SAN values\n *\n * \\return          0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED\n *\n * \\note            Only \"dnsName\", \"uniformResourceIdentifier\" and \"otherName\",\n *                  as defined in RFC 5280, are supported.\n */\nint mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx,\n                                                       const mbedtls_x509_san_list *san_list);\n\n/**\n * \\brief           Set the Netscape Cert Type flags\n *                  (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL)\n *\n * \\param ctx           CSR context to use\n * \\param ns_cert_type  Netscape Cert Type flags to set\n *\n * \\return          0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED\n */\nint mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx,\n                                           unsigned char ns_cert_type);\n\n/**\n * \\brief           Generic function to add to or replace an extension in the\n *                  CSR\n *\n * \\param ctx       CSR context to use\n * \\param oid       OID of the extension\n * \\param oid_len   length of the OID\n * \\param critical  Set to 1 to mark the extension as critical, 0 otherwise.\n * \\param val       value of the extension OCTET STRING\n * \\param val_len   length of the value data\n *\n * \\return          0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED\n */\nint mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx,\n                                        const char *oid, size_t oid_len,\n                                        int critical,\n                                        const unsigned char *val, size_t val_len);\n\n/**\n * \\brief           Free the contents of a CSR context\n *\n * \\param ctx       CSR context to free\n */\nvoid mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx);\n\n/**\n * \\brief           Write a CSR (Certificate Signing Request) to a\n *                  DER structure\n *                  Note: data is written at the end of the buffer! Use the\n *                        return value to determine where you should start\n *                        using the buffer\n *\n * \\param ctx       CSR to write away\n * \\param buf       buffer to write to\n * \\param size      size of the buffer\n * \\param f_rng     RNG function. This must not be \\c NULL.\n * \\param p_rng     RNG parameter\n *\n * \\return          length of data written if successful, or a specific\n *                  error code\n *\n * \\note            \\p f_rng is used for the signature operation.\n */\nint mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,\n                              mbedtls_f_rng_t *f_rng,\n                              void *p_rng);\n\n#if defined(MBEDTLS_PEM_WRITE_C)\n/**\n * \\brief           Write a CSR (Certificate Signing Request) to a\n *                  PEM string\n *\n * \\param ctx       CSR to write away\n * \\param buf       buffer to write to\n * \\param size      size of the buffer\n * \\param f_rng     RNG function. This must not be \\c NULL.\n * \\param p_rng     RNG parameter\n *\n * \\return          0 if successful, or a specific error code\n *\n * \\note            \\p f_rng is used for the signature operation.\n */\nint mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,\n                              mbedtls_f_rng_t *f_rng,\n                              void *p_rng);\n#endif /* MBEDTLS_PEM_WRITE_C */\n#endif /* MBEDTLS_X509_CSR_WRITE_C */\n\n/** \\} addtogroup x509_module */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* mbedtls_x509_csr.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/build_info.h",
    "content": "/**\n * \\file psa/build_info.h\n *\n * \\brief Build-time PSA configuration info\n *\n *  Include this file if you need to depend on the\n *  configuration options defined in mbedtls_config.h or MBEDTLS_CONFIG_FILE\n *  in PSA cryptography core specific files.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_BUILD_INFO_H\n#define PSA_CRYPTO_BUILD_INFO_H\n\n#include \"mbedtls/build_info.h\"\n\n#endif /* PSA_CRYPTO_BUILD_INFO_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto.h",
    "content": "/**\n * \\file psa/crypto.h\n * \\brief Platform Security Architecture cryptography module\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_H\n#define PSA_CRYPTO_H\n\n#if defined(MBEDTLS_PSA_CRYPTO_PLATFORM_FILE)\n#include MBEDTLS_PSA_CRYPTO_PLATFORM_FILE\n#else\n#include \"crypto_platform.h\"\n#endif\n\n#include <stddef.h>\n\n#ifdef __DOXYGEN_ONLY__\n/* This __DOXYGEN_ONLY__ block contains mock definitions for things that\n * must be defined in the crypto_platform.h header. These mock definitions\n * are present in this file as a convenience to generate pretty-printed\n * documentation that includes those definitions. */\n\n/** \\defgroup platform Implementation-specific definitions\n * @{\n */\n\n/**@}*/\n#endif /* __DOXYGEN_ONLY__ */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* The file \"crypto_types.h\" declares types that encode errors,\n * algorithms, key types, policies, etc. */\n#include \"crypto_types.h\"\n\n/** \\defgroup version API version\n * @{\n */\n\n/**\n * The major version of this implementation of the PSA Crypto API\n */\n#define PSA_CRYPTO_API_VERSION_MAJOR 1\n\n/**\n * The minor version of this implementation of the PSA Crypto API\n */\n#define PSA_CRYPTO_API_VERSION_MINOR 0\n\n/**@}*/\n\n/* The file \"crypto_values.h\" declares macros to build and analyze values\n * of integral types defined in \"crypto_types.h\". */\n#include \"crypto_values.h\"\n\n/* The file \"crypto_sizes.h\" contains definitions for size calculation\n * macros whose definitions are implementation-specific. */\n#include \"crypto_sizes.h\"\n\n/* The file \"crypto_struct.h\" contains definitions for\n * implementation-specific structs that are declared above. */\n#if defined(MBEDTLS_PSA_CRYPTO_STRUCT_FILE)\n#include MBEDTLS_PSA_CRYPTO_STRUCT_FILE\n#else\n#include \"crypto_struct.h\"\n#endif\n\n/** \\defgroup initialization Library initialization\n * @{\n */\n\n/**\n * \\brief Library initialization.\n *\n * Applications must call this function before calling any other\n * function in this module.\n *\n * Applications may call this function more than once. Once a call\n * succeeds, subsequent calls are guaranteed to succeed.\n *\n * If the application calls other functions before calling psa_crypto_init(),\n * the behavior is undefined. Implementations are encouraged to either perform\n * the operation as if the library had been initialized or to return\n * #PSA_ERROR_BAD_STATE or some other applicable error. In particular,\n * implementations should not return a success status if the lack of\n * initialization may have security implications, for example due to improper\n * seeding of the random number generator.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n */\npsa_status_t psa_crypto_init(void);\n\n/**@}*/\n\n/** \\addtogroup attributes\n * @{\n */\n\n/** \\def PSA_KEY_ATTRIBUTES_INIT\n *\n * This macro returns a suitable initializer for a key attribute structure\n * of type #psa_key_attributes_t.\n */\n\n/** Return an initial value for a key attributes structure.\n */\nstatic psa_key_attributes_t psa_key_attributes_init(void);\n\n/** Declare a key as persistent and set its key identifier.\n *\n * If the attribute structure currently declares the key as volatile (which\n * is the default content of an attribute structure), this function sets\n * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT.\n *\n * This function does not access storage, it merely stores the given\n * value in the structure.\n * The persistent key will be written to storage when the attribute\n * structure is passed to a key creation function such as\n * psa_import_key(), psa_generate_key(), psa_generate_key_custom(),\n * psa_key_derivation_output_key(), psa_key_derivation_output_key_custom()\n * or psa_copy_key().\n *\n * This function may be declared as `static` (i.e. without external\n * linkage). This function may be provided as a function-like macro,\n * but in this case it must evaluate each of its arguments exactly once.\n *\n * \\param[out] attributes  The attribute structure to write to.\n * \\param key              The persistent identifier for the key.\n *                         This can be any value in the range from\n *                         #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX\n *                         inclusive.\n */\nstatic void psa_set_key_id(psa_key_attributes_t *attributes,\n                           mbedtls_svc_key_id_t key);\n\n#ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER\n/** Set the owner identifier of a key.\n *\n * When key identifiers encode key owner identifiers, psa_set_key_id() does\n * not allow to define in key attributes the owner of volatile keys as\n * psa_set_key_id() enforces the key to be persistent.\n *\n * This function allows to set in key attributes the owner identifier of a\n * key. It is intended to be used for volatile keys. For persistent keys,\n * it is recommended to use the PSA Cryptography API psa_set_key_id() to define\n * the owner of a key.\n *\n * \\param[out] attributes  The attribute structure to write to.\n * \\param owner            The key owner identifier.\n */\nstatic void mbedtls_set_key_owner_id(psa_key_attributes_t *attributes,\n                                     mbedtls_key_owner_id_t owner);\n#endif\n\n/** Set the location of a persistent key.\n *\n * To make a key persistent, you must give it a persistent key identifier\n * with psa_set_key_id(). By default, a key that has a persistent identifier\n * is stored in the default storage area identifier by\n * #PSA_KEY_LIFETIME_PERSISTENT. Call this function to choose a storage\n * area, or to explicitly declare the key as volatile.\n *\n * This function does not access storage, it merely stores the given\n * value in the structure.\n * The persistent key will be written to storage when the attribute\n * structure is passed to a key creation function such as\n * psa_import_key(), psa_generate_key(), psa_generate_key_custom(),\n * psa_key_derivation_output_key(), psa_key_derivation_output_key_custom()\n * or psa_copy_key().\n *\n * This function may be declared as `static` (i.e. without external\n * linkage). This function may be provided as a function-like macro,\n * but in this case it must evaluate each of its arguments exactly once.\n *\n * \\param[out] attributes       The attribute structure to write to.\n * \\param lifetime              The lifetime for the key.\n *                              If this is #PSA_KEY_LIFETIME_VOLATILE, the\n *                              key will be volatile, and the key identifier\n *                              attribute is reset to 0.\n */\nstatic void psa_set_key_lifetime(psa_key_attributes_t *attributes,\n                                 psa_key_lifetime_t lifetime);\n\n/** Retrieve the key identifier from key attributes.\n *\n * This function may be declared as `static` (i.e. without external\n * linkage). This function may be provided as a function-like macro,\n * but in this case it must evaluate its argument exactly once.\n *\n * \\param[in] attributes        The key attribute structure to query.\n *\n * \\return The persistent identifier stored in the attribute structure.\n *         This value is unspecified if the attribute structure declares\n *         the key as volatile.\n */\nstatic mbedtls_svc_key_id_t psa_get_key_id(\n    const psa_key_attributes_t *attributes);\n\n/** Retrieve the lifetime from key attributes.\n *\n * This function may be declared as `static` (i.e. without external\n * linkage). This function may be provided as a function-like macro,\n * but in this case it must evaluate its argument exactly once.\n *\n * \\param[in] attributes        The key attribute structure to query.\n *\n * \\return The lifetime value stored in the attribute structure.\n */\nstatic psa_key_lifetime_t psa_get_key_lifetime(\n    const psa_key_attributes_t *attributes);\n\n/** Declare usage flags for a key.\n *\n * Usage flags are part of a key's usage policy. They encode what\n * kind of operations are permitted on the key. For more details,\n * refer to the documentation of the type #psa_key_usage_t.\n *\n * This function overwrites any usage flags\n * previously set in \\p attributes.\n *\n * This function may be declared as `static` (i.e. without external\n * linkage). This function may be provided as a function-like macro,\n * but in this case it must evaluate each of its arguments exactly once.\n *\n * \\param[out] attributes       The attribute structure to write to.\n * \\param usage_flags           The usage flags to write.\n */\nstatic void psa_set_key_usage_flags(psa_key_attributes_t *attributes,\n                                    psa_key_usage_t usage_flags);\n\n/** Retrieve the usage flags from key attributes.\n *\n * This function may be declared as `static` (i.e. without external\n * linkage). This function may be provided as a function-like macro,\n * but in this case it must evaluate its argument exactly once.\n *\n * \\param[in] attributes        The key attribute structure to query.\n *\n * \\return The usage flags stored in the attribute structure.\n */\nstatic psa_key_usage_t psa_get_key_usage_flags(\n    const psa_key_attributes_t *attributes);\n\n/** Declare the permitted algorithm policy for a key.\n *\n * The permitted algorithm policy of a key encodes which algorithm or\n * algorithms are permitted to be used with this key. The following\n * algorithm policies are supported:\n * - 0 does not allow any cryptographic operation with the key. The key\n *   may be used for non-cryptographic actions such as exporting (if\n *   permitted by the usage flags).\n * - An algorithm value permits this particular algorithm.\n * - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified\n *   signature scheme with any hash algorithm.\n * - An algorithm built from #PSA_ALG_AT_LEAST_THIS_LENGTH_MAC allows\n *   any MAC algorithm from the same base class (e.g. CMAC) which\n *   generates/verifies a MAC length greater than or equal to the length\n *   encoded in the wildcard algorithm.\n * - An algorithm built from #PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG\n *   allows any AEAD algorithm from the same base class (e.g. CCM) which\n *   generates/verifies a tag length greater than or equal to the length\n *   encoded in the wildcard algorithm.\n *\n * This function overwrites any algorithm policy\n * previously set in \\p attributes.\n *\n * This function may be declared as `static` (i.e. without external\n * linkage). This function may be provided as a function-like macro,\n * but in this case it must evaluate each of its arguments exactly once.\n *\n * \\param[out] attributes       The attribute structure to write to.\n * \\param alg                   The permitted algorithm policy to write.\n */\nstatic void psa_set_key_algorithm(psa_key_attributes_t *attributes,\n                                  psa_algorithm_t alg);\n\n\n/** Retrieve the algorithm policy from key attributes.\n *\n * This function may be declared as `static` (i.e. without external\n * linkage). This function may be provided as a function-like macro,\n * but in this case it must evaluate its argument exactly once.\n *\n * \\param[in] attributes        The key attribute structure to query.\n *\n * \\return The algorithm stored in the attribute structure.\n */\nstatic psa_algorithm_t psa_get_key_algorithm(\n    const psa_key_attributes_t *attributes);\n\n/** Declare the type of a key.\n *\n * This function overwrites any key type\n * previously set in \\p attributes.\n *\n * This function may be declared as `static` (i.e. without external\n * linkage). This function may be provided as a function-like macro,\n * but in this case it must evaluate each of its arguments exactly once.\n *\n * \\param[out] attributes       The attribute structure to write to.\n * \\param type                  The key type to write.\n *                              If this is 0, the key type in \\p attributes\n *                              becomes unspecified.\n */\nstatic void psa_set_key_type(psa_key_attributes_t *attributes,\n                             psa_key_type_t type);\n\n\n/** Declare the size of a key.\n *\n * This function overwrites any key size previously set in \\p attributes.\n *\n * This function may be declared as `static` (i.e. without external\n * linkage). This function may be provided as a function-like macro,\n * but in this case it must evaluate each of its arguments exactly once.\n *\n * \\param[out] attributes       The attribute structure to write to.\n * \\param bits                  The key size in bits.\n *                              If this is 0, the key size in \\p attributes\n *                              becomes unspecified. Keys of size 0 are\n *                              not supported.\n */\nstatic void psa_set_key_bits(psa_key_attributes_t *attributes,\n                             size_t bits);\n\n/** Retrieve the key type from key attributes.\n *\n * This function may be declared as `static` (i.e. without external\n * linkage). This function may be provided as a function-like macro,\n * but in this case it must evaluate its argument exactly once.\n *\n * \\param[in] attributes        The key attribute structure to query.\n *\n * \\return The key type stored in the attribute structure.\n */\nstatic psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes);\n\n/** Retrieve the key size from key attributes.\n *\n * This function may be declared as `static` (i.e. without external\n * linkage). This function may be provided as a function-like macro,\n * but in this case it must evaluate its argument exactly once.\n *\n * \\param[in] attributes        The key attribute structure to query.\n *\n * \\return The key size stored in the attribute structure, in bits.\n */\nstatic size_t psa_get_key_bits(const psa_key_attributes_t *attributes);\n\n/** Retrieve the attributes of a key.\n *\n * This function first resets the attribute structure as with\n * psa_reset_key_attributes(). It then copies the attributes of\n * the given key into the given attribute structure.\n *\n * \\note This function may allocate memory or other resources.\n *       Once you have called this function on an attribute structure,\n *       you must call psa_reset_key_attributes() to free these resources.\n *\n * \\param[in] key               Identifier of the key to query.\n * \\param[in,out] attributes    On success, the attributes of the key.\n *                              On failure, equivalent to a\n *                              freshly-initialized structure.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key,\n                                    psa_key_attributes_t *attributes);\n\n/** Reset a key attribute structure to a freshly initialized state.\n *\n * You must initialize the attribute structure as described in the\n * documentation of the type #psa_key_attributes_t before calling this\n * function. Once the structure has been initialized, you may call this\n * function at any time.\n *\n * This function frees any auxiliary resources that the structure\n * may contain.\n *\n * \\param[in,out] attributes    The attribute structure to reset.\n */\nvoid psa_reset_key_attributes(psa_key_attributes_t *attributes);\n\n/**@}*/\n\n/** \\defgroup key_management Key management\n * @{\n */\n\n/** Remove non-essential copies of key material from memory.\n *\n * If the key identifier designates a volatile key, this functions does not do\n * anything and returns successfully.\n *\n * If the key identifier designates a persistent key, then this function will\n * free all resources associated with the key in volatile memory. The key\n * data in persistent storage is not affected and the key can still be used.\n *\n * \\param key Identifier of the key to purge.\n *\n * \\retval #PSA_SUCCESS\n *         The key material will have been removed from memory if it is not\n *         currently required.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p key is not a valid key identifier.\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_purge_key(mbedtls_svc_key_id_t key);\n\n/** Make a copy of a key.\n *\n * Copy key material from one location to another.\n *\n * This function is primarily useful to copy a key from one location\n * to another, since it populates a key using the material from\n * another key which may have a different lifetime.\n *\n * This function may be used to share a key with a different party,\n * subject to implementation-defined restrictions on key sharing.\n *\n * The policy on the source key must have the usage flag\n * #PSA_KEY_USAGE_COPY set.\n * This flag is sufficient to permit the copy if the key has the lifetime\n * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT.\n * Some secure elements do not provide a way to copy a key without\n * making it extractable from the secure element. If a key is located\n * in such a secure element, then the key must have both usage flags\n * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make\n * a copy of the key outside the secure element.\n *\n * The resulting key may only be used in a way that conforms to\n * both the policy of the original key and the policy specified in\n * the \\p attributes parameter:\n * - The usage flags on the resulting key are the bitwise-and of the\n *   usage flags on the source policy and the usage flags in \\p attributes.\n * - If both allow the same algorithm or wildcard-based\n *   algorithm policy, the resulting key has the same algorithm policy.\n * - If either of the policies allows an algorithm and the other policy\n *   allows a wildcard-based algorithm policy that includes this algorithm,\n *   the resulting key allows the same algorithm.\n * - If the policies do not allow any algorithm in common, this function\n *   fails with the status #PSA_ERROR_INVALID_ARGUMENT.\n *\n * The effect of this function on implementation-defined attributes is\n * implementation-defined.\n *\n * \\param source_key        The key to copy. It must allow the usage\n *                          #PSA_KEY_USAGE_COPY. If a private or secret key is\n *                          being copied outside of a secure element it must\n *                          also allow #PSA_KEY_USAGE_EXPORT.\n * \\param[in] attributes    The attributes for the new key.\n *                          They are used as follows:\n *                          - The key type and size may be 0. If either is\n *                            nonzero, it must match the corresponding\n *                            attribute of the source key.\n *                          - The key location (the lifetime and, for\n *                            persistent keys, the key identifier) is\n *                            used directly.\n *                          - The policy constraints (usage flags and\n *                            algorithm policy) are combined from\n *                            the source key and \\p attributes so that\n *                            both sets of restrictions apply, as\n *                            described in the documentation of this function.\n * \\param[out] target_key   On success, an identifier for the newly created\n *                          key. For persistent keys, this is the key\n *                          identifier defined in \\p attributes.\n *                          \\c 0 on failure.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_HANDLE\n *         \\p source_key is invalid.\n * \\retval #PSA_ERROR_ALREADY_EXISTS\n *         This is an attempt to create a persistent key, and there is\n *         already a persistent key with the given identifier.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The lifetime or identifier in \\p attributes are invalid, or\n *         the policy constraints on the source and specified in\n *         \\p attributes are incompatible, or\n *         \\p attributes specifies a key type or key size\n *         which does not match the attributes of the source key.\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The source key does not have the #PSA_KEY_USAGE_COPY usage flag, or\n *         the source key is not exportable and its lifetime does not\n *         allow copying it to the target's lifetime.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key,\n                          const psa_key_attributes_t *attributes,\n                          mbedtls_svc_key_id_t *target_key);\n\n\n/**\n * \\brief Destroy a key.\n *\n * This function destroys a key from both volatile\n * memory and, if applicable, non-volatile storage. Implementations shall\n * make a best effort to ensure that the key material cannot be recovered.\n *\n * This function also erases any metadata such as policies and frees\n * resources associated with the key.\n *\n * If a key is currently in use in a multipart operation, then destroying the\n * key will cause the multipart operation to fail.\n *\n * \\warning    We can only guarantee that the the key material will\n *             eventually be wiped from memory. With threading enabled\n *             and during concurrent execution, copies of the key material may\n *             still exist until all threads have finished using the key.\n *\n * \\param key  Identifier of the key to erase. If this is \\c 0, do nothing and\n *             return #PSA_SUCCESS.\n *\n * \\retval #PSA_SUCCESS\n *         \\p key was a valid identifier and the key material that it\n *         referred to has been erased. Alternatively, \\p key is \\c 0.\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The key cannot be erased because it is\n *         read-only, either due to a policy or due to physical restrictions.\n * \\retval #PSA_ERROR_INVALID_HANDLE\n *         \\p key is not a valid identifier nor \\c 0.\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE\n *         There was a failure in communication with the cryptoprocessor.\n *         The key material may still be present in the cryptoprocessor.\n * \\retval #PSA_ERROR_DATA_INVALID\n *         This error is typically a result of either storage corruption on a\n *         cleartext storage backend, or an attempt to read data that was\n *         written by an incompatible version of the library.\n * \\retval #PSA_ERROR_STORAGE_FAILURE\n *         The storage is corrupted. Implementations shall make a best effort\n *         to erase key material even in this stage, however applications\n *         should be aware that it may be impossible to guarantee that the\n *         key material is not recoverable in such cases.\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED\n *         An unexpected condition which is not a storage corruption or\n *         a communication failure occurred. The cryptoprocessor may have\n *         been compromised.\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_destroy_key(mbedtls_svc_key_id_t key);\n\n/**@}*/\n\n/** \\defgroup import_export Key import and export\n * @{\n */\n\n/**\n * \\brief Import a key in binary format.\n *\n * This function supports any output from psa_export_key(). Refer to the\n * documentation of psa_export_public_key() for the format of public keys\n * and to the documentation of psa_export_key() for the format for\n * other key types.\n *\n * The key data determines the key size. The attributes may optionally\n * specify a key size; in this case it must match the size determined\n * from the key data. A key size of 0 in \\p attributes indicates that\n * the key size is solely determined by the key data.\n *\n * Implementations must reject an attempt to import a key of size 0.\n *\n * This specification supports a single format for each key type.\n * Implementations may support other formats as long as the standard\n * format is supported. Implementations that support other formats\n * should ensure that the formats are clearly unambiguous so as to\n * minimize the risk that an invalid input is accidentally interpreted\n * according to a different format.\n *\n * \\param[in] attributes    The attributes for the new key.\n *                          The key size is always determined from the\n *                          \\p data buffer.\n *                          If the key size in \\p attributes is nonzero,\n *                          it must be equal to the size from \\p data.\n * \\param[out] key          On success, an identifier to the newly created key.\n *                          For persistent keys, this is the key identifier\n *                          defined in \\p attributes.\n *                          \\c 0 on failure.\n * \\param[in] data    Buffer containing the key data. The content of this\n *                    buffer is interpreted according to the type declared\n *                    in \\p attributes.\n *                    All implementations must support at least the format\n *                    described in the documentation\n *                    of psa_export_key() or psa_export_public_key() for\n *                    the chosen type. Implementations may allow other\n *                    formats, but should be conservative: implementations\n *                    should err on the side of rejecting content if it\n *                    may be erroneous (e.g. wrong type or truncated data).\n * \\param data_length Size of the \\p data buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n *         If the key is persistent, the key material and the key's metadata\n *         have been saved to persistent storage.\n * \\retval #PSA_ERROR_ALREADY_EXISTS\n *         This is an attempt to create a persistent key, and there is\n *         already a persistent key with the given identifier.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         The key type or key size is not supported, either by the\n *         implementation in general or in this particular persistent location.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The key attributes, as a whole, are invalid, or\n *         the key data is not correctly formatted, or\n *         the size in \\p attributes is nonzero and does not match the size\n *         of the key data.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_import_key(const psa_key_attributes_t *attributes,\n                            const uint8_t *data,\n                            size_t data_length,\n                            mbedtls_svc_key_id_t *key);\n\n\n\n/**\n * \\brief Export a key in binary format.\n *\n * The output of this function can be passed to psa_import_key() to\n * create an equivalent object.\n *\n * If the implementation of psa_import_key() supports other formats\n * beyond the format specified here, the output from psa_export_key()\n * must use the representation specified here, not the original\n * representation.\n *\n * For standard key types, the output format is as follows:\n *\n * - For symmetric keys (including MAC keys), the format is the\n *   raw bytes of the key.\n * - For DES, the key data consists of 8 bytes. The parity bits must be\n *   correct.\n * - For Triple-DES, the format is the concatenation of the\n *   two or three DES keys.\n * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format\n *   is the non-encrypted DER encoding of the representation defined by\n *   PKCS\\#1 (RFC 8017) as `RSAPrivateKey`, version 0.\n *   ```\n *   RSAPrivateKey ::= SEQUENCE {\n *       version             INTEGER,  -- must be 0\n *       modulus             INTEGER,  -- n\n *       publicExponent      INTEGER,  -- e\n *       privateExponent     INTEGER,  -- d\n *       prime1              INTEGER,  -- p\n *       prime2              INTEGER,  -- q\n *       exponent1           INTEGER,  -- d mod (p-1)\n *       exponent2           INTEGER,  -- d mod (q-1)\n *       coefficient         INTEGER,  -- (inverse of q) mod p\n *   }\n *   ```\n * - For elliptic curve key pairs (key types for which\n *   #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is\n *   a representation of the private value as a `ceiling(m/8)`-byte string\n *   where `m` is the bit size associated with the curve, i.e. the bit size\n *   of the order of the curve's coordinate field. This byte string is\n *   in little-endian order for Montgomery curves (curve types\n *   `PSA_ECC_FAMILY_CURVEXXX`), and in big-endian order for Weierstrass\n *   curves (curve types `PSA_ECC_FAMILY_SECTXXX`, `PSA_ECC_FAMILY_SECPXXX`\n *   and `PSA_ECC_FAMILY_BRAINPOOL_PXXX`).\n *   For Weierstrass curves, this is the content of the `privateKey` field of\n *   the `ECPrivateKey` format defined by RFC 5915.  For Montgomery curves,\n *   the format is defined by RFC 7748, and output is masked according to §5.\n *   For twisted Edwards curves, the private key is as defined by RFC 8032\n *   (a 32-byte string for Edwards25519, a 57-byte string for Edwards448).\n * - For Diffie-Hellman key exchange key pairs (key types for which\n *   #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the\n *   format is the representation of the private key `x` as a big-endian byte\n *   string. The length of the byte string is the private key size in bytes\n *   (leading zeroes are not stripped).\n * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is\n *   true), the format is the same as for psa_export_public_key().\n *\n * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set.\n *\n * \\param key               Identifier of the key to export. It must allow the\n *                          usage #PSA_KEY_USAGE_EXPORT, unless it is a public\n *                          key.\n * \\param[out] data         Buffer where the key data is to be written.\n * \\param data_size         Size of the \\p data buffer in bytes.\n * \\param[out] data_length  On success, the number of bytes\n *                          that make up the key data.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The key does not have the #PSA_KEY_USAGE_EXPORT flag.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p data buffer is too small. You can determine a\n *         sufficient buffer size by calling\n *         #PSA_EXPORT_KEY_OUTPUT_SIZE(\\c type, \\c bits)\n *         where \\c type is the key type\n *         and \\c bits is the key size in bits.\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_export_key(mbedtls_svc_key_id_t key,\n                            uint8_t *data,\n                            size_t data_size,\n                            size_t *data_length);\n\n/**\n * \\brief Export a public key or the public part of a key pair in binary format.\n *\n * The output of this function can be passed to psa_import_key() to\n * create an object that is equivalent to the public key.\n *\n * This specification supports a single format for each key type.\n * Implementations may support other formats as long as the standard\n * format is supported. Implementations that support other formats\n * should ensure that the formats are clearly unambiguous so as to\n * minimize the risk that an invalid input is accidentally interpreted\n * according to a different format.\n *\n * For standard key types, the output format is as follows:\n * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of\n *   the representation defined by RFC 3279 &sect;2.3.1 as `RSAPublicKey`.\n *   ```\n *   RSAPublicKey ::= SEQUENCE {\n *      modulus            INTEGER,    -- n\n *      publicExponent     INTEGER  }  -- e\n *   ```\n * - For elliptic curve keys on a twisted Edwards curve (key types for which\n *   #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true and #PSA_KEY_TYPE_ECC_GET_FAMILY\n *   returns #PSA_ECC_FAMILY_TWISTED_EDWARDS), the public key is as defined\n *   by RFC 8032\n *   (a 32-byte string for Edwards25519, a 57-byte string for Edwards448).\n * - For other elliptic curve public keys (key types for which\n *   #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed\n *   representation defined by SEC1 &sect;2.3.3 as the content of an ECPoint.\n *   Let `m` be the bit size associated with the curve, i.e. the bit size of\n *   `q` for a curve over `F_q`. The representation consists of:\n *      - The byte 0x04;\n *      - `x_P` as a `ceiling(m/8)`-byte string, big-endian;\n *      - `y_P` as a `ceiling(m/8)`-byte string, big-endian.\n * - For Diffie-Hellman key exchange public keys (key types for which\n *   #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true),\n *   the format is the representation of the public key `y = g^x mod p` as a\n *   big-endian byte string. The length of the byte string is the length of the\n *   base prime `p` in bytes.\n *\n * Exporting a public key object or the public part of a key pair is\n * always permitted, regardless of the key's usage flags.\n *\n * \\param key               Identifier of the key to export.\n * \\param[out] data         Buffer where the key data is to be written.\n * \\param data_size         Size of the \\p data buffer in bytes.\n * \\param[out] data_length  On success, the number of bytes\n *                          that make up the key data.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The key is neither a public key nor a key pair.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p data buffer is too small. You can determine a\n *         sufficient buffer size by calling\n *         #PSA_EXPORT_KEY_OUTPUT_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\\c type), \\c bits)\n *         where \\c type is the key type\n *         and \\c bits is the key size in bits.\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_export_public_key(mbedtls_svc_key_id_t key,\n                                   uint8_t *data,\n                                   size_t data_size,\n                                   size_t *data_length);\n\n\n\n/**@}*/\n\n/** \\defgroup hash Message digests\n * @{\n */\n\n/** Calculate the hash (digest) of a message.\n *\n * \\note To verify the hash of a message against an\n *       expected value, use psa_hash_compare() instead.\n *\n * \\param alg               The hash algorithm to compute (\\c PSA_ALG_XXX value\n *                          such that #PSA_ALG_IS_HASH(\\p alg) is true).\n * \\param[in] input         Buffer containing the message to hash.\n * \\param input_length      Size of the \\p input buffer in bytes.\n * \\param[out] hash         Buffer where the hash is to be written.\n * \\param hash_size         Size of the \\p hash buffer in bytes.\n * \\param[out] hash_length  On success, the number of bytes\n *                          that make up the hash value. This is always\n *                          #PSA_HASH_LENGTH(\\p alg).\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported or is not a hash algorithm.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         \\p hash_size is too small\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_hash_compute(psa_algorithm_t alg,\n                              const uint8_t *input,\n                              size_t input_length,\n                              uint8_t *hash,\n                              size_t hash_size,\n                              size_t *hash_length);\n\n/** Calculate the hash (digest) of a message and compare it with a\n * reference value.\n *\n * \\param alg               The hash algorithm to compute (\\c PSA_ALG_XXX value\n *                          such that #PSA_ALG_IS_HASH(\\p alg) is true).\n * \\param[in] input         Buffer containing the message to hash.\n * \\param input_length      Size of the \\p input buffer in bytes.\n * \\param[in] hash          Buffer containing the expected hash value.\n * \\param hash_length       Size of the \\p hash buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         The expected hash is identical to the actual hash of the input.\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The hash of the message was calculated successfully, but it\n *         differs from the expected hash.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported or is not a hash algorithm.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p input_length or \\p hash_length do not match the hash size for \\p alg\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_hash_compare(psa_algorithm_t alg,\n                              const uint8_t *input,\n                              size_t input_length,\n                              const uint8_t *hash,\n                              size_t hash_length);\n\n/** The type of the state data structure for multipart hash operations.\n *\n * Before calling any function on a hash operation object, the application must\n * initialize it by any of the following means:\n * - Set the structure to all-bits-zero, for example:\n *   \\code\n *   psa_hash_operation_t operation;\n *   memset(&operation, 0, sizeof(operation));\n *   \\endcode\n * - Initialize the structure to logical zero values, for example:\n *   \\code\n *   psa_hash_operation_t operation = {0};\n *   \\endcode\n * - Initialize the structure to the initializer #PSA_HASH_OPERATION_INIT,\n *   for example:\n *   \\code\n *   psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;\n *   \\endcode\n * - Assign the result of the function psa_hash_operation_init()\n *   to the structure, for example:\n *   \\code\n *   psa_hash_operation_t operation;\n *   operation = psa_hash_operation_init();\n *   \\endcode\n *\n * This is an implementation-defined \\c struct. Applications should not\n * make any assumptions about the content of this structure.\n * Implementation details can change in future versions without notice. */\ntypedef struct psa_hash_operation_s psa_hash_operation_t;\n\n/** \\def PSA_HASH_OPERATION_INIT\n *\n * This macro returns a suitable initializer for a hash operation object\n * of type #psa_hash_operation_t.\n */\n\n/** Return an initial value for a hash operation object.\n */\nstatic psa_hash_operation_t psa_hash_operation_init(void);\n\n/** Set up a multipart hash operation.\n *\n * The sequence of operations to calculate a hash (message digest)\n * is as follows:\n * -# Allocate an operation object which will be passed to all the functions\n *    listed here.\n * -# Initialize the operation object with one of the methods described in the\n *    documentation for #psa_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT.\n * -# Call psa_hash_setup() to specify the algorithm.\n * -# Call psa_hash_update() zero, one or more times, passing a fragment\n *    of the message each time. The hash that is calculated is the hash\n *    of the concatenation of these messages in order.\n * -# To calculate the hash, call psa_hash_finish().\n *    To compare the hash with an expected value, call psa_hash_verify().\n *\n * If an error occurs at any step after a call to psa_hash_setup(), the\n * operation will need to be reset by a call to psa_hash_abort(). The\n * application may call psa_hash_abort() at any time after the operation\n * has been initialized.\n *\n * After a successful call to psa_hash_setup(), the application must\n * eventually terminate the operation. The following events terminate an\n * operation:\n * - A successful call to psa_hash_finish() or psa_hash_verify().\n * - A call to psa_hash_abort().\n *\n * \\param[in,out] operation The operation object to set up. It must have\n *                          been initialized as per the documentation for\n *                          #psa_hash_operation_t and not yet in use.\n * \\param alg               The hash algorithm to compute (\\c PSA_ALG_XXX value\n *                          such that #PSA_ALG_IS_HASH(\\p alg) is true).\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not a supported hash algorithm.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p alg is not a hash algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be inactive), or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_hash_setup(psa_hash_operation_t *operation,\n                            psa_algorithm_t alg);\n\n/** Add a message fragment to a multipart hash operation.\n *\n * The application must call psa_hash_setup() before calling this function.\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_hash_abort().\n *\n * \\param[in,out] operation Active hash operation.\n * \\param[in] input         Buffer containing the message fragment to hash.\n * \\param input_length      Size of the \\p input buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active), or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_hash_update(psa_hash_operation_t *operation,\n                             const uint8_t *input,\n                             size_t input_length);\n\n/** Finish the calculation of the hash of a message.\n *\n * The application must call psa_hash_setup() before calling this function.\n * This function calculates the hash of the message formed by concatenating\n * the inputs passed to preceding calls to psa_hash_update().\n *\n * When this function returns successfully, the operation becomes inactive.\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_hash_abort().\n *\n * \\warning Applications should not call this function if they expect\n *          a specific value for the hash. Call psa_hash_verify() instead.\n *          Beware that comparing integrity or authenticity data such as\n *          hash values with a function such as \\c memcmp is risky\n *          because the time taken by the comparison may leak information\n *          about the hashed data which could allow an attacker to guess\n *          a valid hash and thereby bypass security controls.\n *\n * \\param[in,out] operation     Active hash operation.\n * \\param[out] hash             Buffer where the hash is to be written.\n * \\param hash_size             Size of the \\p hash buffer in bytes.\n * \\param[out] hash_length      On success, the number of bytes\n *                              that make up the hash value. This is always\n *                              #PSA_HASH_LENGTH(\\c alg) where \\c alg is the\n *                              hash algorithm that is calculated.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p hash buffer is too small. You can determine a\n *         sufficient buffer size by calling #PSA_HASH_LENGTH(\\c alg)\n *         where \\c alg is the hash algorithm that is calculated.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active), or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_hash_finish(psa_hash_operation_t *operation,\n                             uint8_t *hash,\n                             size_t hash_size,\n                             size_t *hash_length);\n\n/** Finish the calculation of the hash of a message and compare it with\n * an expected value.\n *\n * The application must call psa_hash_setup() before calling this function.\n * This function calculates the hash of the message formed by concatenating\n * the inputs passed to preceding calls to psa_hash_update(). It then\n * compares the calculated hash with the expected hash passed as a\n * parameter to this function.\n *\n * When this function returns successfully, the operation becomes inactive.\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_hash_abort().\n *\n * \\note Implementations shall make the best effort to ensure that the\n * comparison between the actual hash and the expected hash is performed\n * in constant time.\n *\n * \\param[in,out] operation     Active hash operation.\n * \\param[in] hash              Buffer containing the expected hash value.\n * \\param hash_length           Size of the \\p hash buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         The expected hash is identical to the actual hash of the message.\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The hash of the message was calculated successfully, but it\n *         differs from the expected hash.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active), or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_hash_verify(psa_hash_operation_t *operation,\n                             const uint8_t *hash,\n                             size_t hash_length);\n\n/** Abort a hash operation.\n *\n * Aborting an operation frees all associated resources except for the\n * \\p operation structure itself. Once aborted, the operation object\n * can be reused for another operation by calling\n * psa_hash_setup() again.\n *\n * You may call this function any time after the operation object has\n * been initialized by one of the methods described in #psa_hash_operation_t.\n *\n * In particular, calling psa_hash_abort() after the operation has been\n * terminated by a call to psa_hash_abort(), psa_hash_finish() or\n * psa_hash_verify() is safe and has no effect.\n *\n * \\param[in,out] operation     Initialized hash operation.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_hash_abort(psa_hash_operation_t *operation);\n\n/** Clone a hash operation.\n *\n * This function copies the state of an ongoing hash operation to\n * a new operation object. In other words, this function is equivalent\n * to calling psa_hash_setup() on \\p target_operation with the same\n * algorithm that \\p source_operation was set up for, then\n * psa_hash_update() on \\p target_operation with the same input that\n * that was passed to \\p source_operation. After this function returns, the\n * two objects are independent, i.e. subsequent calls involving one of\n * the objects do not affect the other object.\n *\n * \\param[in] source_operation      The active hash operation to clone.\n * \\param[in,out] target_operation  The operation object to set up.\n *                                  It must be initialized but not active.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The \\p source_operation state is not valid (it must be active), or\n *         the \\p target_operation state is not valid (it must be inactive), or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation,\n                            psa_hash_operation_t *target_operation);\n\n/**@}*/\n\n/** \\defgroup MAC Message authentication codes\n * @{\n */\n\n/** Calculate the MAC (message authentication code) of a message.\n *\n * \\note To verify the MAC of a message against an\n *       expected value, use psa_mac_verify() instead.\n *       Beware that comparing integrity or authenticity data such as\n *       MAC values with a function such as \\c memcmp is risky\n *       because the time taken by the comparison may leak information\n *       about the MAC value which could allow an attacker to guess\n *       a valid MAC and thereby bypass security controls.\n *\n * \\param key               Identifier of the key to use for the operation. It\n *                          must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE.\n * \\param alg               The MAC algorithm to compute (\\c PSA_ALG_XXX value\n *                          such that #PSA_ALG_IS_MAC(\\p alg) is true).\n * \\param[in] input         Buffer containing the input message.\n * \\param input_length      Size of the \\p input buffer in bytes.\n * \\param[out] mac          Buffer where the MAC value is to be written.\n * \\param mac_size          Size of the \\p mac buffer in bytes.\n * \\param[out] mac_length   On success, the number of bytes\n *                          that make up the MAC value.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p key is not compatible with \\p alg.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported or is not a MAC algorithm.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         \\p mac_size is too small\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE\n *         The key could not be retrieved from storage.\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_mac_compute(mbedtls_svc_key_id_t key,\n                             psa_algorithm_t alg,\n                             const uint8_t *input,\n                             size_t input_length,\n                             uint8_t *mac,\n                             size_t mac_size,\n                             size_t *mac_length);\n\n/** Calculate the MAC of a message and compare it with a reference value.\n *\n * \\param key               Identifier of the key to use for the operation. It\n *                          must allow the usage PSA_KEY_USAGE_VERIFY_MESSAGE.\n * \\param alg               The MAC algorithm to compute (\\c PSA_ALG_XXX value\n *                          such that #PSA_ALG_IS_MAC(\\p alg) is true).\n * \\param[in] input         Buffer containing the input message.\n * \\param input_length      Size of the \\p input buffer in bytes.\n * \\param[in] mac           Buffer containing the expected MAC value.\n * \\param mac_length        Size of the \\p mac buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         The expected MAC is identical to the actual MAC of the input.\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The MAC of the message was calculated successfully, but it\n *         differs from the expected value.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p key is not compatible with \\p alg.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported or is not a MAC algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE\n *         The key could not be retrieved from storage.\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_mac_verify(mbedtls_svc_key_id_t key,\n                            psa_algorithm_t alg,\n                            const uint8_t *input,\n                            size_t input_length,\n                            const uint8_t *mac,\n                            size_t mac_length);\n\n/** The type of the state data structure for multipart MAC operations.\n *\n * Before calling any function on a MAC operation object, the application must\n * initialize it by any of the following means:\n * - Set the structure to all-bits-zero, for example:\n *   \\code\n *   psa_mac_operation_t operation;\n *   memset(&operation, 0, sizeof(operation));\n *   \\endcode\n * - Initialize the structure to logical zero values, for example:\n *   \\code\n *   psa_mac_operation_t operation = {0};\n *   \\endcode\n * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT,\n *   for example:\n *   \\code\n *   psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;\n *   \\endcode\n * - Assign the result of the function psa_mac_operation_init()\n *   to the structure, for example:\n *   \\code\n *   psa_mac_operation_t operation;\n *   operation = psa_mac_operation_init();\n *   \\endcode\n *\n *\n * This is an implementation-defined \\c struct. Applications should not\n * make any assumptions about the content of this structure.\n * Implementation details can change in future versions without notice. */\ntypedef struct psa_mac_operation_s psa_mac_operation_t;\n\n/** \\def PSA_MAC_OPERATION_INIT\n *\n * This macro returns a suitable initializer for a MAC operation object of type\n * #psa_mac_operation_t.\n */\n\n/** Return an initial value for a MAC operation object.\n */\nstatic psa_mac_operation_t psa_mac_operation_init(void);\n\n/** Set up a multipart MAC calculation operation.\n *\n * This function sets up the calculation of the MAC\n * (message authentication code) of a byte string.\n * To verify the MAC of a message against an\n * expected value, use psa_mac_verify_setup() instead.\n *\n * The sequence of operations to calculate a MAC is as follows:\n * -# Allocate an operation object which will be passed to all the functions\n *    listed here.\n * -# Initialize the operation object with one of the methods described in the\n *    documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT.\n * -# Call psa_mac_sign_setup() to specify the algorithm and key.\n * -# Call psa_mac_update() zero, one or more times, passing a fragment\n *    of the message each time. The MAC that is calculated is the MAC\n *    of the concatenation of these messages in order.\n * -# At the end of the message, call psa_mac_sign_finish() to finish\n *    calculating the MAC value and retrieve it.\n *\n * If an error occurs at any step after a call to psa_mac_sign_setup(), the\n * operation will need to be reset by a call to psa_mac_abort(). The\n * application may call psa_mac_abort() at any time after the operation\n * has been initialized.\n *\n * After a successful call to psa_mac_sign_setup(), the application must\n * eventually terminate the operation through one of the following methods:\n * - A successful call to psa_mac_sign_finish().\n * - A call to psa_mac_abort().\n *\n * \\param[in,out] operation The operation object to set up. It must have\n *                          been initialized as per the documentation for\n *                          #psa_mac_operation_t and not yet in use.\n * \\param key               Identifier of the key to use for the operation. It\n *                          must remain valid until the operation terminates.\n *                          It must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE.\n * \\param alg               The MAC algorithm to compute (\\c PSA_ALG_XXX value\n *                          such that #PSA_ALG_IS_MAC(\\p alg) is true).\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p key is not compatible with \\p alg.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported or is not a MAC algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE\n *         The key could not be retrieved from storage.\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be inactive), or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation,\n                                mbedtls_svc_key_id_t key,\n                                psa_algorithm_t alg);\n\n/** Set up a multipart MAC verification operation.\n *\n * This function sets up the verification of the MAC\n * (message authentication code) of a byte string against an expected value.\n *\n * The sequence of operations to verify a MAC is as follows:\n * -# Allocate an operation object which will be passed to all the functions\n *    listed here.\n * -# Initialize the operation object with one of the methods described in the\n *    documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT.\n * -# Call psa_mac_verify_setup() to specify the algorithm and key.\n * -# Call psa_mac_update() zero, one or more times, passing a fragment\n *    of the message each time. The MAC that is calculated is the MAC\n *    of the concatenation of these messages in order.\n * -# At the end of the message, call psa_mac_verify_finish() to finish\n *    calculating the actual MAC of the message and verify it against\n *    the expected value.\n *\n * If an error occurs at any step after a call to psa_mac_verify_setup(), the\n * operation will need to be reset by a call to psa_mac_abort(). The\n * application may call psa_mac_abort() at any time after the operation\n * has been initialized.\n *\n * After a successful call to psa_mac_verify_setup(), the application must\n * eventually terminate the operation through one of the following methods:\n * - A successful call to psa_mac_verify_finish().\n * - A call to psa_mac_abort().\n *\n * \\param[in,out] operation The operation object to set up. It must have\n *                          been initialized as per the documentation for\n *                          #psa_mac_operation_t and not yet in use.\n * \\param key               Identifier of the key to use for the operation. It\n *                          must remain valid until the operation terminates.\n *                          It must allow the usage\n *                          PSA_KEY_USAGE_VERIFY_MESSAGE.\n * \\param alg               The MAC algorithm to compute (\\c PSA_ALG_XXX value\n *                          such that #PSA_ALG_IS_MAC(\\p alg) is true).\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\c key is not compatible with \\c alg.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\c alg is not supported or is not a MAC algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE\n *         The key could not be retrieved from storage.\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be inactive), or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation,\n                                  mbedtls_svc_key_id_t key,\n                                  psa_algorithm_t alg);\n\n/** Add a message fragment to a multipart MAC operation.\n *\n * The application must call psa_mac_sign_setup() or psa_mac_verify_setup()\n * before calling this function.\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_mac_abort().\n *\n * \\param[in,out] operation Active MAC operation.\n * \\param[in] input         Buffer containing the message fragment to add to\n *                          the MAC calculation.\n * \\param input_length      Size of the \\p input buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active), or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_mac_update(psa_mac_operation_t *operation,\n                            const uint8_t *input,\n                            size_t input_length);\n\n/** Finish the calculation of the MAC of a message.\n *\n * The application must call psa_mac_sign_setup() before calling this function.\n * This function calculates the MAC of the message formed by concatenating\n * the inputs passed to preceding calls to psa_mac_update().\n *\n * When this function returns successfully, the operation becomes inactive.\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_mac_abort().\n *\n * \\warning Applications should not call this function if they expect\n *          a specific value for the MAC. Call psa_mac_verify_finish() instead.\n *          Beware that comparing integrity or authenticity data such as\n *          MAC values with a function such as \\c memcmp is risky\n *          because the time taken by the comparison may leak information\n *          about the MAC value which could allow an attacker to guess\n *          a valid MAC and thereby bypass security controls.\n *\n * \\param[in,out] operation Active MAC operation.\n * \\param[out] mac          Buffer where the MAC value is to be written.\n * \\param mac_size          Size of the \\p mac buffer in bytes.\n * \\param[out] mac_length   On success, the number of bytes\n *                          that make up the MAC value. This is always\n *                          #PSA_MAC_LENGTH(\\c key_type, \\c key_bits, \\c alg)\n *                          where \\c key_type and \\c key_bits are the type and\n *                          bit-size respectively of the key and \\c alg is the\n *                          MAC algorithm that is calculated.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p mac buffer is too small. You can determine a\n *         sufficient buffer size by calling PSA_MAC_LENGTH().\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be an active mac sign\n *         operation), or the library has not been previously initialized\n *         by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation,\n                                 uint8_t *mac,\n                                 size_t mac_size,\n                                 size_t *mac_length);\n\n/** Finish the calculation of the MAC of a message and compare it with\n * an expected value.\n *\n * The application must call psa_mac_verify_setup() before calling this function.\n * This function calculates the MAC of the message formed by concatenating\n * the inputs passed to preceding calls to psa_mac_update(). It then\n * compares the calculated MAC with the expected MAC passed as a\n * parameter to this function.\n *\n * When this function returns successfully, the operation becomes inactive.\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_mac_abort().\n *\n * \\note Implementations shall make the best effort to ensure that the\n * comparison between the actual MAC and the expected MAC is performed\n * in constant time.\n *\n * \\param[in,out] operation Active MAC operation.\n * \\param[in] mac           Buffer containing the expected MAC value.\n * \\param mac_length        Size of the \\p mac buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         The expected MAC is identical to the actual MAC of the message.\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The MAC of the message was calculated successfully, but it\n *         differs from the expected MAC.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be an active mac verify\n *         operation), or the library has not been previously initialized\n *         by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation,\n                                   const uint8_t *mac,\n                                   size_t mac_length);\n\n/** Abort a MAC operation.\n *\n * Aborting an operation frees all associated resources except for the\n * \\p operation structure itself. Once aborted, the operation object\n * can be reused for another operation by calling\n * psa_mac_sign_setup() or psa_mac_verify_setup() again.\n *\n * You may call this function any time after the operation object has\n * been initialized by one of the methods described in #psa_mac_operation_t.\n *\n * In particular, calling psa_mac_abort() after the operation has been\n * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or\n * psa_mac_verify_finish() is safe and has no effect.\n *\n * \\param[in,out] operation Initialized MAC operation.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_mac_abort(psa_mac_operation_t *operation);\n\n/**@}*/\n\n/** \\defgroup cipher Symmetric ciphers\n * @{\n */\n\n/** Encrypt a message using a symmetric cipher.\n *\n * This function encrypts a message with a random IV (initialization\n * vector). Use the multipart operation interface with a\n * #psa_cipher_operation_t object to provide other forms of IV.\n *\n * \\param key                   Identifier of the key to use for the operation.\n *                              It must allow the usage #PSA_KEY_USAGE_ENCRYPT.\n * \\param alg                   The cipher algorithm to compute\n *                              (\\c PSA_ALG_XXX value such that\n *                              #PSA_ALG_IS_CIPHER(\\p alg) is true).\n * \\param[in] input             Buffer containing the message to encrypt.\n * \\param input_length          Size of the \\p input buffer in bytes.\n * \\param[out] output           Buffer where the output is to be written.\n *                              The output contains the IV followed by\n *                              the ciphertext proper.\n * \\param output_size           Size of the \\p output buffer in bytes.\n * \\param[out] output_length    On success, the number of bytes\n *                              that make up the output.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p key is not compatible with \\p alg.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported or is not a cipher algorithm.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key,\n                                psa_algorithm_t alg,\n                                const uint8_t *input,\n                                size_t input_length,\n                                uint8_t *output,\n                                size_t output_size,\n                                size_t *output_length);\n\n/** Decrypt a message using a symmetric cipher.\n *\n * This function decrypts a message encrypted with a symmetric cipher.\n *\n * \\param key                   Identifier of the key to use for the operation.\n *                              It must remain valid until the operation\n *                              terminates. It must allow the usage\n *                              #PSA_KEY_USAGE_DECRYPT.\n * \\param alg                   The cipher algorithm to compute\n *                              (\\c PSA_ALG_XXX value such that\n *                              #PSA_ALG_IS_CIPHER(\\p alg) is true).\n * \\param[in] input             Buffer containing the message to decrypt.\n *                              This consists of the IV followed by the\n *                              ciphertext proper.\n * \\param input_length          Size of the \\p input buffer in bytes.\n * \\param[out] output           Buffer where the plaintext is to be written.\n * \\param output_size           Size of the \\p output buffer in bytes.\n * \\param[out] output_length    On success, the number of bytes\n *                              that make up the output.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p key is not compatible with \\p alg.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported or is not a cipher algorithm.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key,\n                                psa_algorithm_t alg,\n                                const uint8_t *input,\n                                size_t input_length,\n                                uint8_t *output,\n                                size_t output_size,\n                                size_t *output_length);\n\n/** The type of the state data structure for multipart cipher operations.\n *\n * Before calling any function on a cipher operation object, the application\n * must initialize it by any of the following means:\n * - Set the structure to all-bits-zero, for example:\n *   \\code\n *   psa_cipher_operation_t operation;\n *   memset(&operation, 0, sizeof(operation));\n *   \\endcode\n * - Initialize the structure to logical zero values, for example:\n *   \\code\n *   psa_cipher_operation_t operation = {0};\n *   \\endcode\n * - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT,\n *   for example:\n *   \\code\n *   psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;\n *   \\endcode\n * - Assign the result of the function psa_cipher_operation_init()\n *   to the structure, for example:\n *   \\code\n *   psa_cipher_operation_t operation;\n *   operation = psa_cipher_operation_init();\n *   \\endcode\n *\n * This is an implementation-defined \\c struct. Applications should not\n * make any assumptions about the content of this structure.\n * Implementation details can change in future versions without notice. */\ntypedef struct psa_cipher_operation_s psa_cipher_operation_t;\n\n/** \\def PSA_CIPHER_OPERATION_INIT\n *\n * This macro returns a suitable initializer for a cipher operation object of\n * type #psa_cipher_operation_t.\n */\n\n/** Return an initial value for a cipher operation object.\n */\nstatic psa_cipher_operation_t psa_cipher_operation_init(void);\n\n/** Set the key for a multipart symmetric encryption operation.\n *\n * The sequence of operations to encrypt a message with a symmetric cipher\n * is as follows:\n * -# Allocate an operation object which will be passed to all the functions\n *    listed here.\n * -# Initialize the operation object with one of the methods described in the\n *    documentation for #psa_cipher_operation_t, e.g.\n *    #PSA_CIPHER_OPERATION_INIT.\n * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key.\n * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to\n *    generate or set the IV (initialization vector). You should use\n *    psa_cipher_generate_iv() unless the protocol you are implementing\n *    requires a specific IV value.\n * -# Call psa_cipher_update() zero, one or more times, passing a fragment\n *    of the message each time.\n * -# Call psa_cipher_finish().\n *\n * If an error occurs at any step after a call to psa_cipher_encrypt_setup(),\n * the operation will need to be reset by a call to psa_cipher_abort(). The\n * application may call psa_cipher_abort() at any time after the operation\n * has been initialized.\n *\n * After a successful call to psa_cipher_encrypt_setup(), the application must\n * eventually terminate the operation. The following events terminate an\n * operation:\n * - A successful call to psa_cipher_finish().\n * - A call to psa_cipher_abort().\n *\n * \\param[in,out] operation     The operation object to set up. It must have\n *                              been initialized as per the documentation for\n *                              #psa_cipher_operation_t and not yet in use.\n * \\param key                   Identifier of the key to use for the operation.\n *                              It must remain valid until the operation\n *                              terminates. It must allow the usage\n *                              #PSA_KEY_USAGE_ENCRYPT.\n * \\param alg                   The cipher algorithm to compute\n *                              (\\c PSA_ALG_XXX value such that\n *                              #PSA_ALG_IS_CIPHER(\\p alg) is true).\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p key is not compatible with \\p alg.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported or is not a cipher algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be inactive), or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,\n                                      mbedtls_svc_key_id_t key,\n                                      psa_algorithm_t alg);\n\n/** Set the key for a multipart symmetric decryption operation.\n *\n * The sequence of operations to decrypt a message with a symmetric cipher\n * is as follows:\n * -# Allocate an operation object which will be passed to all the functions\n *    listed here.\n * -# Initialize the operation object with one of the methods described in the\n *    documentation for #psa_cipher_operation_t, e.g.\n *    #PSA_CIPHER_OPERATION_INIT.\n * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key.\n * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the\n *    decryption. If the IV is prepended to the ciphertext, you can call\n *    psa_cipher_update() on a buffer containing the IV followed by the\n *    beginning of the message.\n * -# Call psa_cipher_update() zero, one or more times, passing a fragment\n *    of the message each time.\n * -# Call psa_cipher_finish().\n *\n * If an error occurs at any step after a call to psa_cipher_decrypt_setup(),\n * the operation will need to be reset by a call to psa_cipher_abort(). The\n * application may call psa_cipher_abort() at any time after the operation\n * has been initialized.\n *\n * After a successful call to psa_cipher_decrypt_setup(), the application must\n * eventually terminate the operation. The following events terminate an\n * operation:\n * - A successful call to psa_cipher_finish().\n * - A call to psa_cipher_abort().\n *\n * \\param[in,out] operation     The operation object to set up. It must have\n *                              been initialized as per the documentation for\n *                              #psa_cipher_operation_t and not yet in use.\n * \\param key                   Identifier of the key to use for the operation.\n *                              It must remain valid until the operation\n *                              terminates. It must allow the usage\n *                              #PSA_KEY_USAGE_DECRYPT.\n * \\param alg                   The cipher algorithm to compute\n *                              (\\c PSA_ALG_XXX value such that\n *                              #PSA_ALG_IS_CIPHER(\\p alg) is true).\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p key is not compatible with \\p alg.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported or is not a cipher algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be inactive), or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation,\n                                      mbedtls_svc_key_id_t key,\n                                      psa_algorithm_t alg);\n\n/** Generate an IV for a symmetric encryption operation.\n *\n * This function generates a random IV (initialization vector), nonce\n * or initial counter value for the encryption operation as appropriate\n * for the chosen algorithm, key type and key size.\n *\n * The application must call psa_cipher_encrypt_setup() before\n * calling this function.\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_cipher_abort().\n *\n * \\param[in,out] operation     Active cipher operation.\n * \\param[out] iv               Buffer where the generated IV is to be written.\n * \\param iv_size               Size of the \\p iv buffer in bytes.\n * \\param[out] iv_length        On success, the number of bytes of the\n *                              generated IV.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p iv buffer is too small.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active, with no IV set),\n *         or the library has not been previously initialized\n *         by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation,\n                                    uint8_t *iv,\n                                    size_t iv_size,\n                                    size_t *iv_length);\n\n/** Set the IV for a symmetric encryption or decryption operation.\n *\n * This function sets the IV (initialization vector), nonce\n * or initial counter value for the encryption or decryption operation.\n *\n * The application must call psa_cipher_encrypt_setup() before\n * calling this function.\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_cipher_abort().\n *\n * \\note When encrypting, applications should use psa_cipher_generate_iv()\n * instead of this function, unless implementing a protocol that requires\n * a non-random IV.\n *\n * \\param[in,out] operation     Active cipher operation.\n * \\param[in] iv                Buffer containing the IV to use.\n * \\param iv_length             Size of the IV in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The size of \\p iv is not acceptable for the chosen algorithm,\n *         or the chosen algorithm does not use an IV.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be an active cipher\n *         encrypt operation, with no IV set), or the library has not been\n *         previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation,\n                               const uint8_t *iv,\n                               size_t iv_length);\n\n/** Encrypt or decrypt a message fragment in an active cipher operation.\n *\n * Before calling this function, you must:\n * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup().\n *    The choice of setup function determines whether this function\n *    encrypts or decrypts its input.\n * 2. If the algorithm requires an IV, call psa_cipher_generate_iv()\n *    (recommended when encrypting) or psa_cipher_set_iv().\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_cipher_abort().\n *\n * \\param[in,out] operation     Active cipher operation.\n * \\param[in] input             Buffer containing the message fragment to\n *                              encrypt or decrypt.\n * \\param input_length          Size of the \\p input buffer in bytes.\n * \\param[out] output           Buffer where the output is to be written.\n * \\param output_size           Size of the \\p output buffer in bytes.\n * \\param[out] output_length    On success, the number of bytes\n *                              that make up the returned output.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p output buffer is too small.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active, with an IV set\n *         if required for the algorithm), or the library has not been\n *         previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_cipher_update(psa_cipher_operation_t *operation,\n                               const uint8_t *input,\n                               size_t input_length,\n                               uint8_t *output,\n                               size_t output_size,\n                               size_t *output_length);\n\n/** Finish encrypting or decrypting a message in a cipher operation.\n *\n * The application must call psa_cipher_encrypt_setup() or\n * psa_cipher_decrypt_setup() before calling this function. The choice\n * of setup function determines whether this function encrypts or\n * decrypts its input.\n *\n * This function finishes the encryption or decryption of the message\n * formed by concatenating the inputs passed to preceding calls to\n * psa_cipher_update().\n *\n * When this function returns successfully, the operation becomes inactive.\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_cipher_abort().\n *\n * \\param[in,out] operation     Active cipher operation.\n * \\param[out] output           Buffer where the output is to be written.\n * \\param output_size           Size of the \\p output buffer in bytes.\n * \\param[out] output_length    On success, the number of bytes\n *                              that make up the returned output.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The total input size passed to this operation is not valid for\n *         this particular algorithm. For example, the algorithm is a based\n *         on block cipher and requires a whole number of blocks, but the\n *         total input size is not a multiple of the block size.\n * \\retval #PSA_ERROR_INVALID_PADDING\n *         This is a decryption operation for an algorithm that includes\n *         padding, and the ciphertext does not contain valid padding.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p output buffer is too small.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active, with an IV set\n *         if required for the algorithm), or the library has not been\n *         previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_cipher_finish(psa_cipher_operation_t *operation,\n                               uint8_t *output,\n                               size_t output_size,\n                               size_t *output_length);\n\n/** Abort a cipher operation.\n *\n * Aborting an operation frees all associated resources except for the\n * \\p operation structure itself. Once aborted, the operation object\n * can be reused for another operation by calling\n * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again.\n *\n * You may call this function any time after the operation object has\n * been initialized as described in #psa_cipher_operation_t.\n *\n * In particular, calling psa_cipher_abort() after the operation has been\n * terminated by a call to psa_cipher_abort() or psa_cipher_finish()\n * is safe and has no effect.\n *\n * \\param[in,out] operation     Initialized cipher operation.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_cipher_abort(psa_cipher_operation_t *operation);\n\n/**@}*/\n\n/** \\defgroup aead Authenticated encryption with associated data (AEAD)\n * @{\n */\n\n/** Process an authenticated encryption operation.\n *\n * \\param key                     Identifier of the key to use for the\n *                                operation. It must allow the usage\n *                                #PSA_KEY_USAGE_ENCRYPT.\n * \\param alg                     The AEAD algorithm to compute\n *                                (\\c PSA_ALG_XXX value such that\n *                                #PSA_ALG_IS_AEAD(\\p alg) is true).\n * \\param[in] nonce               Nonce or IV to use.\n * \\param nonce_length            Size of the \\p nonce buffer in bytes.\n * \\param[in] additional_data     Additional data that will be authenticated\n *                                but not encrypted.\n * \\param additional_data_length  Size of \\p additional_data in bytes.\n * \\param[in] plaintext           Data that will be authenticated and\n *                                encrypted.\n * \\param plaintext_length        Size of \\p plaintext in bytes.\n * \\param[out] ciphertext         Output buffer for the authenticated and\n *                                encrypted data. The additional data is not\n *                                part of this output. For algorithms where the\n *                                encrypted data and the authentication tag\n *                                are defined as separate outputs, the\n *                                authentication tag is appended to the\n *                                encrypted data.\n * \\param ciphertext_size         Size of the \\p ciphertext buffer in bytes.\n *                                This must be appropriate for the selected\n *                                algorithm and key:\n *                                - A sufficient output size is\n *                                  #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\\c key_type,\n *                                  \\p alg, \\p plaintext_length) where\n *                                  \\c key_type is the type of \\p key.\n *                                - #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\\p\n *                                  plaintext_length) evaluates to the maximum\n *                                  ciphertext size of any supported AEAD\n *                                  encryption.\n * \\param[out] ciphertext_length  On success, the size of the output\n *                                in the \\p ciphertext buffer.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p key is not compatible with \\p alg.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported or is not an AEAD algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         \\p ciphertext_size is too small.\n *         #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\\c key_type, \\p alg,\n *         \\p plaintext_length) or\n *         #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\\p plaintext_length) can be used to\n *         determine the required buffer size.\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key,\n                              psa_algorithm_t alg,\n                              const uint8_t *nonce,\n                              size_t nonce_length,\n                              const uint8_t *additional_data,\n                              size_t additional_data_length,\n                              const uint8_t *plaintext,\n                              size_t plaintext_length,\n                              uint8_t *ciphertext,\n                              size_t ciphertext_size,\n                              size_t *ciphertext_length);\n\n/** Process an authenticated decryption operation.\n *\n * \\param key                     Identifier of the key to use for the\n *                                operation. It must allow the usage\n *                                #PSA_KEY_USAGE_DECRYPT.\n * \\param alg                     The AEAD algorithm to compute\n *                                (\\c PSA_ALG_XXX value such that\n *                                #PSA_ALG_IS_AEAD(\\p alg) is true).\n * \\param[in] nonce               Nonce or IV to use.\n * \\param nonce_length            Size of the \\p nonce buffer in bytes.\n * \\param[in] additional_data     Additional data that has been authenticated\n *                                but not encrypted.\n * \\param additional_data_length  Size of \\p additional_data in bytes.\n * \\param[in] ciphertext          Data that has been authenticated and\n *                                encrypted. For algorithms where the\n *                                encrypted data and the authentication tag\n *                                are defined as separate inputs, the buffer\n *                                must contain the encrypted data followed\n *                                by the authentication tag.\n * \\param ciphertext_length       Size of \\p ciphertext in bytes.\n * \\param[out] plaintext          Output buffer for the decrypted data.\n * \\param plaintext_size          Size of the \\p plaintext buffer in bytes.\n *                                This must be appropriate for the selected\n *                                algorithm and key:\n *                                - A sufficient output size is\n *                                  #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\\c key_type,\n *                                  \\p alg, \\p ciphertext_length) where\n *                                  \\c key_type is the type of \\p key.\n *                                - #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\\p\n *                                  ciphertext_length) evaluates to the maximum\n *                                  plaintext size of any supported AEAD\n *                                  decryption.\n * \\param[out] plaintext_length   On success, the size of the output\n *                                in the \\p plaintext buffer.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The ciphertext is not authentic.\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p key is not compatible with \\p alg.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported or is not an AEAD algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         \\p plaintext_size is too small.\n *         #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\\c key_type, \\p alg,\n *         \\p ciphertext_length) or\n *         #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\\p ciphertext_length) can be used\n *         to determine the required buffer size.\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key,\n                              psa_algorithm_t alg,\n                              const uint8_t *nonce,\n                              size_t nonce_length,\n                              const uint8_t *additional_data,\n                              size_t additional_data_length,\n                              const uint8_t *ciphertext,\n                              size_t ciphertext_length,\n                              uint8_t *plaintext,\n                              size_t plaintext_size,\n                              size_t *plaintext_length);\n\n/** The type of the state data structure for multipart AEAD operations.\n *\n * Before calling any function on an AEAD operation object, the application\n * must initialize it by any of the following means:\n * - Set the structure to all-bits-zero, for example:\n *   \\code\n *   psa_aead_operation_t operation;\n *   memset(&operation, 0, sizeof(operation));\n *   \\endcode\n * - Initialize the structure to logical zero values, for example:\n *   \\code\n *   psa_aead_operation_t operation = {0};\n *   \\endcode\n * - Initialize the structure to the initializer #PSA_AEAD_OPERATION_INIT,\n *   for example:\n *   \\code\n *   psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;\n *   \\endcode\n * - Assign the result of the function psa_aead_operation_init()\n *   to the structure, for example:\n *   \\code\n *   psa_aead_operation_t operation;\n *   operation = psa_aead_operation_init();\n *   \\endcode\n *\n * This is an implementation-defined \\c struct. Applications should not\n * make any assumptions about the content of this structure.\n * Implementation details can change in future versions without notice. */\ntypedef struct psa_aead_operation_s psa_aead_operation_t;\n\n/** \\def PSA_AEAD_OPERATION_INIT\n *\n * This macro returns a suitable initializer for an AEAD operation object of\n * type #psa_aead_operation_t.\n */\n\n/** Return an initial value for an AEAD operation object.\n */\nstatic psa_aead_operation_t psa_aead_operation_init(void);\n\n/** Set the key for a multipart authenticated encryption operation.\n *\n * The sequence of operations to encrypt a message with authentication\n * is as follows:\n * -# Allocate an operation object which will be passed to all the functions\n *    listed here.\n * -# Initialize the operation object with one of the methods described in the\n *    documentation for #psa_aead_operation_t, e.g.\n *    #PSA_AEAD_OPERATION_INIT.\n * -# Call psa_aead_encrypt_setup() to specify the algorithm and key.\n * -# If needed, call psa_aead_set_lengths() to specify the length of the\n *    inputs to the subsequent calls to psa_aead_update_ad() and\n *    psa_aead_update(). See the documentation of psa_aead_set_lengths()\n *    for details.\n * -# Call either psa_aead_generate_nonce() or psa_aead_set_nonce() to\n *    generate or set the nonce. You should use\n *    psa_aead_generate_nonce() unless the protocol you are implementing\n *    requires a specific nonce value.\n * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment\n *    of the non-encrypted additional authenticated data each time.\n * -# Call psa_aead_update() zero, one or more times, passing a fragment\n *    of the message to encrypt each time.\n * -# Call psa_aead_finish().\n *\n * If an error occurs at any step after a call to psa_aead_encrypt_setup(),\n * the operation will need to be reset by a call to psa_aead_abort(). The\n * application may call psa_aead_abort() at any time after the operation\n * has been initialized.\n *\n * After a successful call to psa_aead_encrypt_setup(), the application must\n * eventually terminate the operation. The following events terminate an\n * operation:\n * - A successful call to psa_aead_finish().\n * - A call to psa_aead_abort().\n *\n * \\param[in,out] operation     The operation object to set up. It must have\n *                              been initialized as per the documentation for\n *                              #psa_aead_operation_t and not yet in use.\n * \\param key                   Identifier of the key to use for the operation.\n *                              It must remain valid until the operation\n *                              terminates. It must allow the usage\n *                              #PSA_KEY_USAGE_ENCRYPT.\n * \\param alg                   The AEAD algorithm to compute\n *                              (\\c PSA_ALG_XXX value such that\n *                              #PSA_ALG_IS_AEAD(\\p alg) is true).\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be inactive), or\n *         the library has not been previously initialized by psa_crypto_init().\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p key is not compatible with \\p alg.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported or is not an AEAD algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation,\n                                    mbedtls_svc_key_id_t key,\n                                    psa_algorithm_t alg);\n\n/** Set the key for a multipart authenticated decryption operation.\n *\n * The sequence of operations to decrypt a message with authentication\n * is as follows:\n * -# Allocate an operation object which will be passed to all the functions\n *    listed here.\n * -# Initialize the operation object with one of the methods described in the\n *    documentation for #psa_aead_operation_t, e.g.\n *    #PSA_AEAD_OPERATION_INIT.\n * -# Call psa_aead_decrypt_setup() to specify the algorithm and key.\n * -# If needed, call psa_aead_set_lengths() to specify the length of the\n *    inputs to the subsequent calls to psa_aead_update_ad() and\n *    psa_aead_update(). See the documentation of psa_aead_set_lengths()\n *    for details.\n * -# Call psa_aead_set_nonce() with the nonce for the decryption.\n * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment\n *    of the non-encrypted additional authenticated data each time.\n * -# Call psa_aead_update() zero, one or more times, passing a fragment\n *    of the ciphertext to decrypt each time.\n * -# Call psa_aead_verify().\n *\n * If an error occurs at any step after a call to psa_aead_decrypt_setup(),\n * the operation will need to be reset by a call to psa_aead_abort(). The\n * application may call psa_aead_abort() at any time after the operation\n * has been initialized.\n *\n * After a successful call to psa_aead_decrypt_setup(), the application must\n * eventually terminate the operation. The following events terminate an\n * operation:\n * - A successful call to psa_aead_verify().\n * - A call to psa_aead_abort().\n *\n * \\param[in,out] operation     The operation object to set up. It must have\n *                              been initialized as per the documentation for\n *                              #psa_aead_operation_t and not yet in use.\n * \\param key                   Identifier of the key to use for the operation.\n *                              It must remain valid until the operation\n *                              terminates. It must allow the usage\n *                              #PSA_KEY_USAGE_DECRYPT.\n * \\param alg                   The AEAD algorithm to compute\n *                              (\\c PSA_ALG_XXX value such that\n *                              #PSA_ALG_IS_AEAD(\\p alg) is true).\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p key is not compatible with \\p alg.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported or is not an AEAD algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be inactive), or the\n *         library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation,\n                                    mbedtls_svc_key_id_t key,\n                                    psa_algorithm_t alg);\n\n/** Generate a random nonce for an authenticated encryption operation.\n *\n * This function generates a random nonce for the authenticated encryption\n * operation with an appropriate size for the chosen algorithm, key type\n * and key size.\n *\n * The application must call psa_aead_encrypt_setup() before\n * calling this function.\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_aead_abort().\n *\n * \\param[in,out] operation     Active AEAD operation.\n * \\param[out] nonce            Buffer where the generated nonce is to be\n *                              written.\n * \\param nonce_size            Size of the \\p nonce buffer in bytes.\n * \\param[out] nonce_length     On success, the number of bytes of the\n *                              generated nonce.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p nonce buffer is too small.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be an active aead encrypt\n *         operation, with no nonce set), or the library has not been\n *         previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation,\n                                     uint8_t *nonce,\n                                     size_t nonce_size,\n                                     size_t *nonce_length);\n\n/** Set the nonce for an authenticated encryption or decryption operation.\n *\n * This function sets the nonce for the authenticated\n * encryption or decryption operation.\n *\n * The application must call psa_aead_encrypt_setup() or\n * psa_aead_decrypt_setup() before calling this function.\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_aead_abort().\n *\n * \\note When encrypting, applications should use psa_aead_generate_nonce()\n * instead of this function, unless implementing a protocol that requires\n * a non-random IV.\n *\n * \\param[in,out] operation     Active AEAD operation.\n * \\param[in] nonce             Buffer containing the nonce to use.\n * \\param nonce_length          Size of the nonce in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The size of \\p nonce is not acceptable for the chosen algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active, with no nonce\n *         set), or the library has not been previously initialized\n *         by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation,\n                                const uint8_t *nonce,\n                                size_t nonce_length);\n\n/** Declare the lengths of the message and additional data for AEAD.\n *\n * The application must call this function before calling\n * psa_aead_update_ad() or psa_aead_update() if the algorithm for\n * the operation requires it. If the algorithm does not require it,\n * calling this function is optional, but if this function is called\n * then the implementation must enforce the lengths.\n *\n * You may call this function before or after setting the nonce with\n * psa_aead_set_nonce() or psa_aead_generate_nonce().\n *\n * - For #PSA_ALG_CCM, calling this function is required.\n * - For the other AEAD algorithms defined in this specification, calling\n *   this function is not required.\n * - For vendor-defined algorithm, refer to the vendor documentation.\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_aead_abort().\n *\n * \\param[in,out] operation     Active AEAD operation.\n * \\param ad_length             Size of the non-encrypted additional\n *                              authenticated data in bytes.\n * \\param plaintext_length      Size of the plaintext to encrypt in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         At least one of the lengths is not acceptable for the chosen\n *         algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active, and\n *         psa_aead_update_ad() and psa_aead_update() must not have been\n *         called yet), or the library has not been previously initialized\n *         by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation,\n                                  size_t ad_length,\n                                  size_t plaintext_length);\n\n/** Pass additional data to an active AEAD operation.\n *\n * Additional data is authenticated, but not encrypted.\n *\n * You may call this function multiple times to pass successive fragments\n * of the additional data. You may not call this function after passing\n * data to encrypt or decrypt with psa_aead_update().\n *\n * Before calling this function, you must:\n * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup().\n * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce().\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_aead_abort().\n *\n * \\warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS,\n *          there is no guarantee that the input is valid. Therefore, until\n *          you have called psa_aead_verify() and it has returned #PSA_SUCCESS,\n *          treat the input as untrusted and prepare to undo any action that\n *          depends on the input if psa_aead_verify() returns an error status.\n *\n * \\param[in,out] operation     Active AEAD operation.\n * \\param[in] input             Buffer containing the fragment of\n *                              additional data.\n * \\param input_length          Size of the \\p input buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The total input length overflows the additional data length that\n *         was previously specified with psa_aead_set_lengths().\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active, have a nonce\n *         set, have lengths set if required by the algorithm, and\n *         psa_aead_update() must not have been called yet), or the library\n *         has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_aead_update_ad(psa_aead_operation_t *operation,\n                                const uint8_t *input,\n                                size_t input_length);\n\n/** Encrypt or decrypt a message fragment in an active AEAD operation.\n *\n * Before calling this function, you must:\n * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup().\n *    The choice of setup function determines whether this function\n *    encrypts or decrypts its input.\n * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce().\n * 3. Call psa_aead_update_ad() to pass all the additional data.\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_aead_abort().\n *\n * \\warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS,\n *          there is no guarantee that the input is valid. Therefore, until\n *          you have called psa_aead_verify() and it has returned #PSA_SUCCESS:\n *          - Do not use the output in any way other than storing it in a\n *            confidential location. If you take any action that depends\n *            on the tentative decrypted data, this action will need to be\n *            undone if the input turns out not to be valid. Furthermore,\n *            if an adversary can observe that this action took place\n *            (for example through timing), they may be able to use this\n *            fact as an oracle to decrypt any message encrypted with the\n *            same key.\n *          - In particular, do not copy the output anywhere but to a\n *            memory or storage space that you have exclusive access to.\n *\n * This function does not require the input to be aligned to any\n * particular block boundary. If the implementation can only process\n * a whole block at a time, it must consume all the input provided, but\n * it may delay the end of the corresponding output until a subsequent\n * call to psa_aead_update(), psa_aead_finish() or psa_aead_verify()\n * provides sufficient input. The amount of data that can be delayed\n * in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE.\n *\n * \\param[in,out] operation     Active AEAD operation.\n * \\param[in] input             Buffer containing the message fragment to\n *                              encrypt or decrypt.\n * \\param input_length          Size of the \\p input buffer in bytes.\n * \\param[out] output           Buffer where the output is to be written.\n * \\param output_size           Size of the \\p output buffer in bytes.\n *                              This must be appropriate for the selected\n *                                algorithm and key:\n *                                - A sufficient output size is\n *                                  #PSA_AEAD_UPDATE_OUTPUT_SIZE(\\c key_type,\n *                                  \\c alg, \\p input_length) where\n *                                  \\c key_type is the type of key and \\c alg is\n *                                  the algorithm that were used to set up the\n *                                  operation.\n *                                - #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\\p\n *                                  input_length) evaluates to the maximum\n *                                  output size of any supported AEAD\n *                                  algorithm.\n * \\param[out] output_length    On success, the number of bytes\n *                              that make up the returned output.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p output buffer is too small.\n *         #PSA_AEAD_UPDATE_OUTPUT_SIZE(\\c key_type, \\c alg, \\p input_length) or\n *         #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\\p input_length) can be used to\n *         determine the required buffer size.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The total length of input to psa_aead_update_ad() so far is\n *         less than the additional data length that was previously\n *         specified with psa_aead_set_lengths(), or\n *         the total input length overflows the plaintext length that\n *         was previously specified with psa_aead_set_lengths().\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active, have a nonce\n *         set, and have lengths set if required by the algorithm), or the\n *         library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_aead_update(psa_aead_operation_t *operation,\n                             const uint8_t *input,\n                             size_t input_length,\n                             uint8_t *output,\n                             size_t output_size,\n                             size_t *output_length);\n\n/** Finish encrypting a message in an AEAD operation.\n *\n * The operation must have been set up with psa_aead_encrypt_setup().\n *\n * This function finishes the authentication of the additional data\n * formed by concatenating the inputs passed to preceding calls to\n * psa_aead_update_ad() with the plaintext formed by concatenating the\n * inputs passed to preceding calls to psa_aead_update().\n *\n * This function has two output buffers:\n * - \\p ciphertext contains trailing ciphertext that was buffered from\n *   preceding calls to psa_aead_update().\n * - \\p tag contains the authentication tag.\n *\n * When this function returns successfully, the operation becomes inactive.\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_aead_abort().\n *\n * \\param[in,out] operation     Active AEAD operation.\n * \\param[out] ciphertext       Buffer where the last part of the ciphertext\n *                              is to be written.\n * \\param ciphertext_size       Size of the \\p ciphertext buffer in bytes.\n *                              This must be appropriate for the selected\n *                              algorithm and key:\n *                              - A sufficient output size is\n *                                #PSA_AEAD_FINISH_OUTPUT_SIZE(\\c key_type,\n *                                \\c alg) where \\c key_type is the type of key\n *                                and \\c alg is the algorithm that were used to\n *                                set up the operation.\n *                              - #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE evaluates to\n *                                the maximum output size of any supported AEAD\n *                                algorithm.\n * \\param[out] ciphertext_length On success, the number of bytes of\n *                              returned ciphertext.\n * \\param[out] tag              Buffer where the authentication tag is\n *                              to be written.\n * \\param tag_size              Size of the \\p tag buffer in bytes.\n *                              This must be appropriate for the selected\n *                              algorithm and key:\n *                              - The exact tag size is #PSA_AEAD_TAG_LENGTH(\\c\n *                                key_type, \\c key_bits, \\c alg) where\n *                                \\c key_type and \\c key_bits are the type and\n *                                bit-size of the key, and \\c alg is the\n *                                algorithm that were used in the call to\n *                                psa_aead_encrypt_setup().\n *                              - #PSA_AEAD_TAG_MAX_SIZE evaluates to the\n *                                maximum tag size of any supported AEAD\n *                                algorithm.\n * \\param[out] tag_length       On success, the number of bytes\n *                              that make up the returned tag.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p ciphertext or \\p tag buffer is too small.\n *         #PSA_AEAD_FINISH_OUTPUT_SIZE(\\c key_type, \\c alg) or\n *         #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE can be used to determine the\n *         required \\p ciphertext buffer size. #PSA_AEAD_TAG_LENGTH(\\c key_type,\n *         \\c key_bits, \\c alg) or #PSA_AEAD_TAG_MAX_SIZE can be used to\n *         determine the required \\p tag buffer size.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The total length of input to psa_aead_update_ad() so far is\n *         less than the additional data length that was previously\n *         specified with psa_aead_set_lengths(), or\n *         the total length of input to psa_aead_update() so far is\n *         less than the plaintext length that was previously\n *         specified with psa_aead_set_lengths().\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be an active encryption\n *         operation with a nonce set), or the library has not been previously\n *         initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_aead_finish(psa_aead_operation_t *operation,\n                             uint8_t *ciphertext,\n                             size_t ciphertext_size,\n                             size_t *ciphertext_length,\n                             uint8_t *tag,\n                             size_t tag_size,\n                             size_t *tag_length);\n\n/** Finish authenticating and decrypting a message in an AEAD operation.\n *\n * The operation must have been set up with psa_aead_decrypt_setup().\n *\n * This function finishes the authenticated decryption of the message\n * components:\n *\n * -  The additional data consisting of the concatenation of the inputs\n *    passed to preceding calls to psa_aead_update_ad().\n * -  The ciphertext consisting of the concatenation of the inputs passed to\n *    preceding calls to psa_aead_update().\n * -  The tag passed to this function call.\n *\n * If the authentication tag is correct, this function outputs any remaining\n * plaintext and reports success. If the authentication tag is not correct,\n * this function returns #PSA_ERROR_INVALID_SIGNATURE.\n *\n * When this function returns successfully, the operation becomes inactive.\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_aead_abort().\n *\n * \\note Implementations shall make the best effort to ensure that the\n * comparison between the actual tag and the expected tag is performed\n * in constant time.\n *\n * \\param[in,out] operation     Active AEAD operation.\n * \\param[out] plaintext        Buffer where the last part of the plaintext\n *                              is to be written. This is the remaining data\n *                              from previous calls to psa_aead_update()\n *                              that could not be processed until the end\n *                              of the input.\n * \\param plaintext_size        Size of the \\p plaintext buffer in bytes.\n *                              This must be appropriate for the selected algorithm and key:\n *                              - A sufficient output size is\n *                                #PSA_AEAD_VERIFY_OUTPUT_SIZE(\\c key_type,\n *                                \\c alg) where \\c key_type is the type of key\n *                                and \\c alg is the algorithm that were used to\n *                                set up the operation.\n *                              - #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE evaluates to\n *                                the maximum output size of any supported AEAD\n *                                algorithm.\n * \\param[out] plaintext_length On success, the number of bytes of\n *                              returned plaintext.\n * \\param[in] tag               Buffer containing the authentication tag.\n * \\param tag_length            Size of the \\p tag buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The calculations were successful, but the authentication tag is\n *         not correct.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p plaintext buffer is too small.\n *         #PSA_AEAD_VERIFY_OUTPUT_SIZE(\\c key_type, \\c alg) or\n *         #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE can be used to determine the\n *         required buffer size.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The total length of input to psa_aead_update_ad() so far is\n *         less than the additional data length that was previously\n *         specified with psa_aead_set_lengths(), or\n *         the total length of input to psa_aead_update() so far is\n *         less than the plaintext length that was previously\n *         specified with psa_aead_set_lengths().\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be an active decryption\n *         operation with a nonce set), or the library has not been previously\n *         initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_aead_verify(psa_aead_operation_t *operation,\n                             uint8_t *plaintext,\n                             size_t plaintext_size,\n                             size_t *plaintext_length,\n                             const uint8_t *tag,\n                             size_t tag_length);\n\n/** Abort an AEAD operation.\n *\n * Aborting an operation frees all associated resources except for the\n * \\p operation structure itself. Once aborted, the operation object\n * can be reused for another operation by calling\n * psa_aead_encrypt_setup() or psa_aead_decrypt_setup() again.\n *\n * You may call this function any time after the operation object has\n * been initialized as described in #psa_aead_operation_t.\n *\n * In particular, calling psa_aead_abort() after the operation has been\n * terminated by a call to psa_aead_abort(), psa_aead_finish() or\n * psa_aead_verify() is safe and has no effect.\n *\n * \\param[in,out] operation     Initialized AEAD operation.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_aead_abort(psa_aead_operation_t *operation);\n\n/**@}*/\n\n/** \\defgroup asymmetric Asymmetric cryptography\n * @{\n */\n\n/**\n * \\brief Sign a message with a private key. For hash-and-sign algorithms,\n *        this includes the hashing step.\n *\n * \\note To perform a multi-part hash-and-sign signature algorithm, first use\n *       a multi-part hash operation and then pass the resulting hash to\n *       psa_sign_hash(). PSA_ALG_GET_HASH(\\p alg) can be used to determine the\n *       hash algorithm to use.\n *\n * \\param[in]  key              Identifier of the key to use for the operation.\n *                              It must be an asymmetric key pair. The key must\n *                              allow the usage #PSA_KEY_USAGE_SIGN_MESSAGE.\n * \\param[in]  alg              An asymmetric signature algorithm (PSA_ALG_XXX\n *                              value such that #PSA_ALG_IS_SIGN_MESSAGE(\\p alg)\n *                              is true), that is compatible with the type of\n *                              \\p key.\n * \\param[in]  input            The input message to sign.\n * \\param[in]  input_length     Size of the \\p input buffer in bytes.\n * \\param[out] signature        Buffer where the signature is to be written.\n * \\param[in]  signature_size   Size of the \\p signature buffer in bytes. This\n *                              must be appropriate for the selected\n *                              algorithm and key:\n *                              - The required signature size is\n *                                #PSA_SIGN_OUTPUT_SIZE(\\c key_type, \\c key_bits, \\p alg)\n *                                where \\c key_type and \\c key_bits are the type and\n *                                bit-size respectively of key.\n *                              - #PSA_SIGNATURE_MAX_SIZE evaluates to the\n *                                maximum signature size of any supported\n *                                signature algorithm.\n * \\param[out] signature_length On success, the number of bytes that make up\n *                              the returned signature value.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag,\n *         or it does not permit the requested algorithm.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p signature buffer is too small. You can\n *         determine a sufficient buffer size by calling\n *         #PSA_SIGN_OUTPUT_SIZE(\\c key_type, \\c key_bits, \\p alg)\n *         where \\c key_type and \\c key_bits are the type and bit-size\n *         respectively of \\p key.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_sign_message(mbedtls_svc_key_id_t key,\n                              psa_algorithm_t alg,\n                              const uint8_t *input,\n                              size_t input_length,\n                              uint8_t *signature,\n                              size_t signature_size,\n                              size_t *signature_length);\n\n/** \\brief Verify the signature of a message with a public key, using\n *         a hash-and-sign verification algorithm.\n *\n * \\note To perform a multi-part hash-and-sign signature verification\n *       algorithm, first use a multi-part hash operation to hash the message\n *       and then pass the resulting hash to psa_verify_hash().\n *       PSA_ALG_GET_HASH(\\p alg) can be used to determine the hash algorithm\n *       to use.\n *\n * \\param[in]  key              Identifier of the key to use for the operation.\n *                              It must be a public key or an asymmetric key\n *                              pair. The key must allow the usage\n *                              #PSA_KEY_USAGE_VERIFY_MESSAGE.\n * \\param[in]  alg              An asymmetric signature algorithm (PSA_ALG_XXX\n *                              value such that #PSA_ALG_IS_SIGN_MESSAGE(\\p alg)\n *                              is true), that is compatible with the type of\n *                              \\p key.\n * \\param[in]  input            The message whose signature is to be verified.\n * \\param[in]  input_length     Size of the \\p input buffer in bytes.\n * \\param[in] signature         Buffer containing the signature to verify.\n * \\param[in]  signature_length Size of the \\p signature buffer in bytes.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag,\n *         or it does not permit the requested algorithm.\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The calculation was performed successfully, but the passed signature\n *         is not a valid signature.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_verify_message(mbedtls_svc_key_id_t key,\n                                psa_algorithm_t alg,\n                                const uint8_t *input,\n                                size_t input_length,\n                                const uint8_t *signature,\n                                size_t signature_length);\n\n/**\n * \\brief Sign a hash or short message with a private key.\n *\n * Note that to perform a hash-and-sign signature algorithm, you must\n * first calculate the hash by calling psa_hash_setup(), psa_hash_update()\n * and psa_hash_finish(), or alternatively by calling psa_hash_compute().\n * Then pass the resulting hash as the \\p hash\n * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\\p alg)\n * to determine the hash algorithm to use.\n *\n * \\param key                   Identifier of the key to use for the operation.\n *                              It must be an asymmetric key pair. The key must\n *                              allow the usage #PSA_KEY_USAGE_SIGN_HASH.\n * \\param alg                   A signature algorithm (PSA_ALG_XXX\n *                              value such that #PSA_ALG_IS_SIGN_HASH(\\p alg)\n *                              is true), that is compatible with\n *                              the type of \\p key.\n * \\param[in] hash              The hash or message to sign.\n * \\param hash_length           Size of the \\p hash buffer in bytes.\n * \\param[out] signature        Buffer where the signature is to be written.\n * \\param signature_size        Size of the \\p signature buffer in bytes.\n * \\param[out] signature_length On success, the number of bytes\n *                              that make up the returned signature value.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p signature buffer is too small. You can\n *         determine a sufficient buffer size by calling\n *         #PSA_SIGN_OUTPUT_SIZE(\\c key_type, \\c key_bits, \\p alg)\n *         where \\c key_type and \\c key_bits are the type and bit-size\n *         respectively of \\p key.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_sign_hash(mbedtls_svc_key_id_t key,\n                           psa_algorithm_t alg,\n                           const uint8_t *hash,\n                           size_t hash_length,\n                           uint8_t *signature,\n                           size_t signature_size,\n                           size_t *signature_length);\n\n/**\n * \\brief Verify the signature of a hash or short message using a public key.\n *\n * Note that to perform a hash-and-sign signature algorithm, you must\n * first calculate the hash by calling psa_hash_setup(), psa_hash_update()\n * and psa_hash_finish(), or alternatively by calling psa_hash_compute().\n * Then pass the resulting hash as the \\p hash\n * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\\p alg)\n * to determine the hash algorithm to use.\n *\n * \\param key               Identifier of the key to use for the operation. It\n *                          must be a public key or an asymmetric key pair. The\n *                          key must allow the usage\n *                          #PSA_KEY_USAGE_VERIFY_HASH.\n * \\param alg               A signature algorithm (PSA_ALG_XXX\n *                          value such that #PSA_ALG_IS_SIGN_HASH(\\p alg)\n *                          is true), that is compatible with\n *                          the type of \\p key.\n * \\param[in] hash          The hash or message whose signature is to be\n *                          verified.\n * \\param hash_length       Size of the \\p hash buffer in bytes.\n * \\param[in] signature     Buffer containing the signature to verify.\n * \\param signature_length  Size of the \\p signature buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         The signature is valid.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The calculation was performed successfully, but the passed\n *         signature is not a valid signature.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_verify_hash(mbedtls_svc_key_id_t key,\n                             psa_algorithm_t alg,\n                             const uint8_t *hash,\n                             size_t hash_length,\n                             const uint8_t *signature,\n                             size_t signature_length);\n\n/**\n * \\brief Encrypt a short message with a public key.\n *\n * \\param key                   Identifier of the key to use for the operation.\n *                              It must be a public key or an asymmetric key\n *                              pair. It must allow the usage\n *                              #PSA_KEY_USAGE_ENCRYPT.\n * \\param alg                   An asymmetric encryption algorithm that is\n *                              compatible with the type of \\p key.\n * \\param[in] input             The message to encrypt.\n * \\param input_length          Size of the \\p input buffer in bytes.\n * \\param[in] salt              A salt or label, if supported by the\n *                              encryption algorithm.\n *                              If the algorithm does not support a\n *                              salt, pass \\c NULL.\n *                              If the algorithm supports an optional\n *                              salt and you do not want to pass a salt,\n *                              pass \\c NULL.\n *\n *                              - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is\n *                                supported.\n * \\param salt_length           Size of the \\p salt buffer in bytes.\n *                              If \\p salt is \\c NULL, pass 0.\n * \\param[out] output           Buffer where the encrypted message is to\n *                              be written.\n * \\param output_size           Size of the \\p output buffer in bytes.\n * \\param[out] output_length    On success, the number of bytes\n *                              that make up the returned output.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p output buffer is too small. You can\n *         determine a sufficient buffer size by calling\n *         #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\\c key_type, \\c key_bits, \\p alg)\n *         where \\c key_type and \\c key_bits are the type and bit-size\n *         respectively of \\p key.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key,\n                                    psa_algorithm_t alg,\n                                    const uint8_t *input,\n                                    size_t input_length,\n                                    const uint8_t *salt,\n                                    size_t salt_length,\n                                    uint8_t *output,\n                                    size_t output_size,\n                                    size_t *output_length);\n\n/**\n * \\brief Decrypt a short message with a private key.\n *\n * \\param key                   Identifier of the key to use for the operation.\n *                              It must be an asymmetric key pair. It must\n *                              allow the usage #PSA_KEY_USAGE_DECRYPT.\n * \\param alg                   An asymmetric encryption algorithm that is\n *                              compatible with the type of \\p key.\n * \\param[in] input             The message to decrypt.\n * \\param input_length          Size of the \\p input buffer in bytes.\n * \\param[in] salt              A salt or label, if supported by the\n *                              encryption algorithm.\n *                              If the algorithm does not support a\n *                              salt, pass \\c NULL.\n *                              If the algorithm supports an optional\n *                              salt and you do not want to pass a salt,\n *                              pass \\c NULL.\n *\n *                              - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is\n *                                supported.\n * \\param salt_length           Size of the \\p salt buffer in bytes.\n *                              If \\p salt is \\c NULL, pass 0.\n * \\param[out] output           Buffer where the decrypted message is to\n *                              be written.\n * \\param output_size           Size of the \\c output buffer in bytes.\n * \\param[out] output_length    On success, the number of bytes\n *                              that make up the returned output.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p output buffer is too small. You can\n *         determine a sufficient buffer size by calling\n *         #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\\c key_type, \\c key_bits, \\p alg)\n *         where \\c key_type and \\c key_bits are the type and bit-size\n *         respectively of \\p key.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n * \\retval #PSA_ERROR_INVALID_PADDING \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key,\n                                    psa_algorithm_t alg,\n                                    const uint8_t *input,\n                                    size_t input_length,\n                                    const uint8_t *salt,\n                                    size_t salt_length,\n                                    uint8_t *output,\n                                    size_t output_size,\n                                    size_t *output_length);\n\n/**@}*/\n\n/** \\defgroup key_derivation Key derivation and pseudorandom generation\n * @{\n */\n\n/** The type of the state data structure for key derivation operations.\n *\n * Before calling any function on a key derivation operation object, the\n * application must initialize it by any of the following means:\n * - Set the structure to all-bits-zero, for example:\n *   \\code\n *   psa_key_derivation_operation_t operation;\n *   memset(&operation, 0, sizeof(operation));\n *   \\endcode\n * - Initialize the structure to logical zero values, for example:\n *   \\code\n *   psa_key_derivation_operation_t operation = {0};\n *   \\endcode\n * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT,\n *   for example:\n *   \\code\n *   psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;\n *   \\endcode\n * - Assign the result of the function psa_key_derivation_operation_init()\n *   to the structure, for example:\n *   \\code\n *   psa_key_derivation_operation_t operation;\n *   operation = psa_key_derivation_operation_init();\n *   \\endcode\n *\n * This is an implementation-defined \\c struct. Applications should not\n * make any assumptions about the content of this structure.\n * Implementation details can change in future versions without notice.\n */\ntypedef struct psa_key_derivation_s psa_key_derivation_operation_t;\n\n/** \\def PSA_KEY_DERIVATION_OPERATION_INIT\n *\n * This macro returns a suitable initializer for a key derivation operation\n * object of type #psa_key_derivation_operation_t.\n */\n\n/** Return an initial value for a key derivation operation object.\n */\nstatic psa_key_derivation_operation_t psa_key_derivation_operation_init(void);\n\n/** Set up a key derivation operation.\n *\n * A key derivation algorithm takes some inputs and uses them to generate\n * a byte stream in a deterministic way.\n * This byte stream can be used to produce keys and other\n * cryptographic material.\n *\n * To derive a key:\n * -# Start with an initialized object of type #psa_key_derivation_operation_t.\n * -# Call psa_key_derivation_setup() to select the algorithm.\n * -# Provide the inputs for the key derivation by calling\n *    psa_key_derivation_input_bytes() or psa_key_derivation_input_key()\n *    as appropriate. Which inputs are needed, in what order, and whether\n *    they may be keys and if so of what type depends on the algorithm.\n * -# Optionally set the operation's maximum capacity with\n *    psa_key_derivation_set_capacity(). You may do this before, in the middle\n *    of or after providing inputs. For some algorithms, this step is mandatory\n *    because the output depends on the maximum capacity.\n * -# To derive a key, call psa_key_derivation_output_key() or\n *    psa_key_derivation_output_key_custom().\n *    To derive a byte string for a different purpose, call\n *    psa_key_derivation_output_bytes().\n *    Successive calls to these functions use successive output bytes\n *    calculated by the key derivation algorithm.\n * -# Clean up the key derivation operation object with\n *    psa_key_derivation_abort().\n *\n * If this function returns an error, the key derivation operation object is\n * not changed.\n *\n * If an error occurs at any step after a call to psa_key_derivation_setup(),\n * the operation will need to be reset by a call to psa_key_derivation_abort().\n *\n * Implementations must reject an attempt to derive a key of size 0.\n *\n * \\param[in,out] operation       The key derivation operation object\n *                                to set up. It must\n *                                have been initialized but not set up yet.\n * \\param alg                     The key derivation algorithm to compute\n *                                (\\c PSA_ALG_XXX value such that\n *                                #PSA_ALG_IS_KEY_DERIVATION(\\p alg) is true).\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\c alg is not a key derivation algorithm.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\c alg is not supported or is not a key derivation algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be inactive), or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_key_derivation_setup(\n    psa_key_derivation_operation_t *operation,\n    psa_algorithm_t alg);\n\n/** Retrieve the current capacity of a key derivation operation.\n *\n * The capacity of a key derivation is the maximum number of bytes that it can\n * return. When you get *N* bytes of output from a key derivation operation,\n * this reduces its capacity by *N*.\n *\n * \\param[in] operation     The operation to query.\n * \\param[out] capacity     On success, the capacity of the operation.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active), or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_key_derivation_get_capacity(\n    const psa_key_derivation_operation_t *operation,\n    size_t *capacity);\n\n/** Set the maximum capacity of a key derivation operation.\n *\n * The capacity of a key derivation operation is the maximum number of bytes\n * that the key derivation operation can return from this point onwards.\n *\n * \\param[in,out] operation The key derivation operation object to modify.\n * \\param capacity          The new capacity of the operation.\n *                          It must be less or equal to the operation's\n *                          current capacity.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p capacity is larger than the operation's current capacity.\n *         In this case, the operation object remains valid and its capacity\n *         remains unchanged.\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active), or the\n *         library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_key_derivation_set_capacity(\n    psa_key_derivation_operation_t *operation,\n    size_t capacity);\n\n/** Use the maximum possible capacity for a key derivation operation.\n *\n * Use this value as the capacity argument when setting up a key derivation\n * to indicate that the operation should have the maximum possible capacity.\n * The value of the maximum possible capacity depends on the key derivation\n * algorithm.\n */\n#define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t) (-1))\n\n/** Provide an input for key derivation or key agreement.\n *\n * Which inputs are required and in what order depends on the algorithm.\n * Refer to the documentation of each key derivation or key agreement\n * algorithm for information.\n *\n * This function passes direct inputs, which is usually correct for\n * non-secret inputs. To pass a secret input, which should be in a key\n * object, call psa_key_derivation_input_key() instead of this function.\n * Refer to the documentation of individual step types\n * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t)\n * for more information.\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_key_derivation_abort().\n *\n * \\param[in,out] operation       The key derivation operation object to use.\n *                                It must have been set up with\n *                                psa_key_derivation_setup() and must not\n *                                have produced any output yet.\n * \\param step                    Which step the input data is for.\n * \\param[in] data                Input data to use.\n * \\param data_length             Size of the \\p data buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\c step is not compatible with the operation's algorithm, or\n *         \\c step does not allow direct inputs.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid for this input \\p step, or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_key_derivation_input_bytes(\n    psa_key_derivation_operation_t *operation,\n    psa_key_derivation_step_t step,\n    const uint8_t *data,\n    size_t data_length);\n\n/** Provide a numeric input for key derivation or key agreement.\n *\n * Which inputs are required and in what order depends on the algorithm.\n * However, when an algorithm requires a particular order, numeric inputs\n * usually come first as they tend to be configuration parameters.\n * Refer to the documentation of each key derivation or key agreement\n * algorithm for information.\n *\n * This function is used for inputs which are fixed-size non-negative\n * integers.\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_key_derivation_abort().\n *\n * \\param[in,out] operation       The key derivation operation object to use.\n *                                It must have been set up with\n *                                psa_key_derivation_setup() and must not\n *                                have produced any output yet.\n * \\param step                    Which step the input data is for.\n * \\param[in] value               The value of the numeric input.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\c step is not compatible with the operation's algorithm, or\n *         \\c step does not allow numeric inputs.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid for this input \\p step, or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_key_derivation_input_integer(\n    psa_key_derivation_operation_t *operation,\n    psa_key_derivation_step_t step,\n    uint64_t value);\n\n/** Provide an input for key derivation in the form of a key.\n *\n * Which inputs are required and in what order depends on the algorithm.\n * Refer to the documentation of each key derivation or key agreement\n * algorithm for information.\n *\n * This function obtains input from a key object, which is usually correct for\n * secret inputs or for non-secret personalization strings kept in the key\n * store. To pass a non-secret parameter which is not in the key store,\n * call psa_key_derivation_input_bytes() instead of this function.\n * Refer to the documentation of individual step types\n * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t)\n * for more information.\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_key_derivation_abort().\n *\n * \\param[in,out] operation       The key derivation operation object to use.\n *                                It must have been set up with\n *                                psa_key_derivation_setup() and must not\n *                                have produced any output yet.\n * \\param step                    Which step the input data is for.\n * \\param key                     Identifier of the key. It must have an\n *                                appropriate type for step and must allow the\n *                                usage #PSA_KEY_USAGE_DERIVE or\n *                                #PSA_KEY_USAGE_VERIFY_DERIVATION (see note)\n *                                and the algorithm used by the operation.\n *\n * \\note Once all inputs steps are completed, the operations will allow:\n * - psa_key_derivation_output_bytes() if each input was either a direct input\n *   or  a key with #PSA_KEY_USAGE_DERIVE set;\n * - psa_key_derivation_output_key() or psa_key_derivation_output_key_custom()\n *   if the input for step\n *   #PSA_KEY_DERIVATION_INPUT_SECRET or #PSA_KEY_DERIVATION_INPUT_PASSWORD\n *   was from a key slot with #PSA_KEY_USAGE_DERIVE and each other input was\n *   either a direct input or a key with #PSA_KEY_USAGE_DERIVE set;\n * - psa_key_derivation_verify_bytes() if each input was either a direct input\n *   or  a key with #PSA_KEY_USAGE_VERIFY_DERIVATION set;\n * - psa_key_derivation_verify_key() under the same conditions as\n *   psa_key_derivation_verify_bytes().\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The key allows neither #PSA_KEY_USAGE_DERIVE nor\n *         #PSA_KEY_USAGE_VERIFY_DERIVATION, or it doesn't allow this\n *         algorithm.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\c step is not compatible with the operation's algorithm, or\n *         \\c step does not allow key inputs of the given type\n *         or does not allow key inputs at all.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid for this input \\p step, or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_key_derivation_input_key(\n    psa_key_derivation_operation_t *operation,\n    psa_key_derivation_step_t step,\n    mbedtls_svc_key_id_t key);\n\n/** Perform a key agreement and use the shared secret as input to a key\n * derivation.\n *\n * A key agreement algorithm takes two inputs: a private key \\p private_key\n * a public key \\p peer_key.\n * The result of this function is passed as input to a key derivation.\n * The output of this key derivation can be extracted by reading from the\n * resulting operation to produce keys and other cryptographic material.\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_key_derivation_abort().\n *\n * \\param[in,out] operation       The key derivation operation object to use.\n *                                It must have been set up with\n *                                psa_key_derivation_setup() with a\n *                                key agreement and derivation algorithm\n *                                \\c alg (\\c PSA_ALG_XXX value such that\n *                                #PSA_ALG_IS_KEY_AGREEMENT(\\c alg) is true\n *                                and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\\c alg)\n *                                is false).\n *                                The operation must be ready for an\n *                                input of the type given by \\p step.\n * \\param step                    Which step the input data is for.\n * \\param private_key             Identifier of the private key to use. It must\n *                                allow the usage #PSA_KEY_USAGE_DERIVE.\n * \\param[in] peer_key      Public key of the peer. The peer key must be in the\n *                          same format that psa_import_key() accepts for the\n *                          public key type corresponding to the type of\n *                          private_key. That is, this function performs the\n *                          equivalent of\n *                          #psa_import_key(...,\n *                          `peer_key`, `peer_key_length`) where\n *                          with key attributes indicating the public key\n *                          type corresponding to the type of `private_key`.\n *                          For example, for EC keys, this means that peer_key\n *                          is interpreted as a point on the curve that the\n *                          private key is on. The standard formats for public\n *                          keys are documented in the documentation of\n *                          psa_export_public_key().\n * \\param peer_key_length         Size of \\p peer_key in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\c private_key is not compatible with \\c alg,\n *         or \\p peer_key is not valid for \\c alg or not compatible with\n *         \\c private_key, or \\c step does not allow an input resulting\n *         from a key agreement.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\c alg is not supported or is not a key derivation algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid for this key agreement \\p step,\n *         or the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_key_derivation_key_agreement(\n    psa_key_derivation_operation_t *operation,\n    psa_key_derivation_step_t step,\n    mbedtls_svc_key_id_t private_key,\n    const uint8_t *peer_key,\n    size_t peer_key_length);\n\n/** Read some data from a key derivation operation.\n *\n * This function calculates output bytes from a key derivation algorithm and\n * return those bytes.\n * If you view the key derivation's output as a stream of bytes, this\n * function destructively reads the requested number of bytes from the\n * stream.\n * The operation's capacity decreases by the number of bytes read.\n *\n * If this function returns an error status other than\n * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error\n * state and must be aborted by calling psa_key_derivation_abort().\n *\n * \\param[in,out] operation The key derivation operation object to read from.\n * \\param[out] output       Buffer where the output will be written.\n * \\param output_length     Number of bytes to output.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         One of the inputs was a key whose policy didn't allow\n *         #PSA_KEY_USAGE_DERIVE.\n * \\retval #PSA_ERROR_INSUFFICIENT_DATA\n *                          The operation's capacity was less than\n *                          \\p output_length bytes. Note that in this case,\n *                          no output is written to the output buffer.\n *                          The operation's capacity is set to 0, thus\n *                          subsequent calls to this function will not\n *                          succeed, even with a smaller output buffer.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active and completed\n *         all required input steps), or the library has not been previously\n *         initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_key_derivation_output_bytes(\n    psa_key_derivation_operation_t *operation,\n    uint8_t *output,\n    size_t output_length);\n\n/** Derive a key from an ongoing key derivation operation.\n *\n * This function calculates output bytes from a key derivation algorithm\n * and uses those bytes to generate a key deterministically.\n * The key's location, usage policy, type and size are taken from\n * \\p attributes.\n *\n * If you view the key derivation's output as a stream of bytes, this\n * function destructively reads as many bytes as required from the\n * stream.\n * The operation's capacity decreases by the number of bytes read.\n *\n * If this function returns an error status other than\n * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error\n * state and must be aborted by calling psa_key_derivation_abort().\n *\n * How much output is produced and consumed from the operation, and how\n * the key is derived, depends on the key type and on the key size\n * (denoted \\c bits below):\n *\n * - For key types for which the key is an arbitrary sequence of bytes\n *   of a given size, this function is functionally equivalent to\n *   calling #psa_key_derivation_output_bytes\n *   and passing the resulting output to #psa_import_key.\n *   However, this function has a security benefit:\n *   if the implementation provides an isolation boundary then\n *   the key material is not exposed outside the isolation boundary.\n *   As a consequence, for these key types, this function always consumes\n *   exactly (\\c bits / 8) bytes from the operation.\n *   The following key types defined in this specification follow this scheme:\n *\n *     - #PSA_KEY_TYPE_AES;\n *     - #PSA_KEY_TYPE_ARIA;\n *     - #PSA_KEY_TYPE_CAMELLIA;\n *     - #PSA_KEY_TYPE_DERIVE;\n *     - #PSA_KEY_TYPE_HMAC;\n *     - #PSA_KEY_TYPE_PASSWORD_HASH.\n *\n * - For ECC keys on a Montgomery elliptic curve\n *   (#PSA_KEY_TYPE_ECC_KEY_PAIR(\\c curve) where \\c curve designates a\n *   Montgomery curve), this function always draws a byte string whose\n *   length is determined by the curve, and sets the mandatory bits\n *   accordingly. That is:\n *\n *     - Curve25519 (#PSA_ECC_FAMILY_MONTGOMERY, 255 bits): draw a 32-byte\n *       string and process it as specified in RFC 7748 &sect;5.\n *     - Curve448 (#PSA_ECC_FAMILY_MONTGOMERY, 448 bits): draw a 56-byte\n *       string and process it as specified in RFC 7748 &sect;5.\n *\n * - For key types for which the key is represented by a single sequence of\n *   \\c bits bits with constraints as to which bit sequences are acceptable,\n *   this function draws a byte string of length (\\c bits / 8) bytes rounded\n *   up to the nearest whole number of bytes. If the resulting byte string\n *   is acceptable, it becomes the key, otherwise the drawn bytes are discarded.\n *   This process is repeated until an acceptable byte string is drawn.\n *   The byte string drawn from the operation is interpreted as specified\n *   for the output produced by psa_export_key().\n *   The following key types defined in this specification follow this scheme:\n *\n *     - #PSA_KEY_TYPE_DES.\n *       Force-set the parity bits, but discard forbidden weak keys.\n *       For 2-key and 3-key triple-DES, the three keys are generated\n *       successively (for example, for 3-key triple-DES,\n *       if the first 8 bytes specify a weak key and the next 8 bytes do not,\n *       discard the first 8 bytes, use the next 8 bytes as the first key,\n *       and continue reading output from the operation to derive the other\n *       two keys).\n *     - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\\c group)\n *       where \\c group designates any Diffie-Hellman group) and\n *       ECC keys on a Weierstrass elliptic curve\n *       (#PSA_KEY_TYPE_ECC_KEY_PAIR(\\c curve) where \\c curve designates a\n *       Weierstrass curve).\n *       For these key types, interpret the byte string as integer\n *       in big-endian order. Discard it if it is not in the range\n *       [0, *N* - 2] where *N* is the boundary of the private key domain\n *       (the prime *p* for Diffie-Hellman, the subprime *q* for DSA,\n *       or the order of the curve's base point for ECC).\n *       Add 1 to the resulting integer and use this as the private key *x*.\n *       This method allows compliance to NIST standards, specifically\n *       the methods titled \"key-pair generation by testing candidates\"\n *       in NIST SP 800-56A &sect;5.6.1.1.4 for Diffie-Hellman,\n *       in FIPS 186-4 &sect;B.1.2 for DSA, and\n *       in NIST SP 800-56A &sect;5.6.1.2.2 or\n *       FIPS 186-4 &sect;B.4.2 for elliptic curve keys.\n *\n * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR,\n *   the way in which the operation output is consumed is\n *   implementation-defined.\n *\n * In all cases, the data that is read is discarded from the operation.\n * The operation's capacity is decreased by the number of bytes read.\n *\n * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET,\n * the input to that step must be provided with psa_key_derivation_input_key().\n * Future versions of this specification may include additional restrictions\n * on the derived key based on the attributes and strength of the secret key.\n *\n * \\note This function is equivalent to calling\n *       psa_key_derivation_output_key_custom()\n *       with the custom production parameters #PSA_CUSTOM_KEY_PARAMETERS_INIT\n *       and `custom_data_length == 0` (i.e. `custom_data` is empty).\n *\n * \\param[in] attributes    The attributes for the new key.\n *                          If the key type to be created is\n *                          #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in\n *                          the policy must be the same as in the current\n *                          operation.\n * \\param[in,out] operation The key derivation operation object to read from.\n * \\param[out] key          On success, an identifier for the newly created\n *                          key. For persistent keys, this is the key\n *                          identifier defined in \\p attributes.\n *                          \\c 0 on failure.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n *         If the key is persistent, the key material and the key's metadata\n *         have been saved to persistent storage.\n * \\retval #PSA_ERROR_ALREADY_EXISTS\n *         This is an attempt to create a persistent key, and there is\n *         already a persistent key with the given identifier.\n * \\retval #PSA_ERROR_INSUFFICIENT_DATA\n *         There was not enough data to create the desired key.\n *         Note that in this case, no output is written to the output buffer.\n *         The operation's capacity is set to 0, thus subsequent calls to\n *         this function will not succeed, even with a smaller output buffer.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         The key type or key size is not supported, either by the\n *         implementation in general or in this particular location.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The provided key attributes are not valid for the operation.\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The #PSA_KEY_DERIVATION_INPUT_SECRET or\n *         #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a\n *         key; or one of the inputs was a key whose policy didn't allow\n *         #PSA_KEY_USAGE_DERIVE.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active and completed\n *         all required input steps), or the library has not been previously\n *         initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_key_derivation_output_key(\n    const psa_key_attributes_t *attributes,\n    psa_key_derivation_operation_t *operation,\n    mbedtls_svc_key_id_t *key);\n\n/** Derive a key from an ongoing key derivation operation with custom\n *  production parameters.\n *\n * See the description of psa_key_derivation_out_key() for the operation of\n * this function with the default production parameters.\n * Mbed TLS currently does not currently support any non-default production\n * parameters.\n *\n * \\note This function is experimental and may change in future minor\n *       versions of Mbed TLS.\n *\n * \\param[in] attributes    The attributes for the new key.\n *                          If the key type to be created is\n *                          #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in\n *                          the policy must be the same as in the current\n *                          operation.\n * \\param[in,out] operation The key derivation operation object to read from.\n * \\param[in] custom        Customization parameters for the key generation.\n *                          When this is #PSA_CUSTOM_KEY_PARAMETERS_INIT\n *                          with \\p custom_data_length = 0,\n *                          this function is equivalent to\n *                          psa_key_derivation_output_key().\n * \\param[in] custom_data   Variable-length data associated with \\c custom.\n * \\param custom_data_length\n *                          Length of `custom_data` in bytes.\n * \\param[out] key          On success, an identifier for the newly created\n *                          key. For persistent keys, this is the key\n *                          identifier defined in \\p attributes.\n *                          \\c 0 on failure.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n *         If the key is persistent, the key material and the key's metadata\n *         have been saved to persistent storage.\n * \\retval #PSA_ERROR_ALREADY_EXISTS\n *         This is an attempt to create a persistent key, and there is\n *         already a persistent key with the given identifier.\n * \\retval #PSA_ERROR_INSUFFICIENT_DATA\n *         There was not enough data to create the desired key.\n *         Note that in this case, no output is written to the output buffer.\n *         The operation's capacity is set to 0, thus subsequent calls to\n *         this function will not succeed, even with a smaller output buffer.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         The key type or key size is not supported, either by the\n *         implementation in general or in this particular location.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The provided key attributes are not valid for the operation.\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The #PSA_KEY_DERIVATION_INPUT_SECRET or\n *         #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a\n *         key; or one of the inputs was a key whose policy didn't allow\n *         #PSA_KEY_USAGE_DERIVE.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active and completed\n *         all required input steps), or the library has not been previously\n *         initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_key_derivation_output_key_custom(\n    const psa_key_attributes_t *attributes,\n    psa_key_derivation_operation_t *operation,\n    const psa_custom_key_parameters_t *custom,\n    const uint8_t *custom_data,\n    size_t custom_data_length,\n    mbedtls_svc_key_id_t *key);\n\n#ifndef __cplusplus\n/* Omitted when compiling in C++, because one of the parameters is a\n * pointer to a struct with a flexible array member, and that is not\n * standard C++.\n * https://github.com/Mbed-TLS/mbedtls/issues/9020\n */\n/** Derive a key from an ongoing key derivation operation with custom\n *  production parameters.\n *\n * \\note\n * This is a deprecated variant of psa_key_derivation_output_key_custom().\n * It is equivalent except that the associated variable-length data\n * is passed in `params->data` instead of a separate parameter.\n * This function will be removed in a future version of Mbed TLS.\n *\n * \\param[in] attributes    The attributes for the new key.\n *                          If the key type to be created is\n *                          #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in\n *                          the policy must be the same as in the current\n *                          operation.\n * \\param[in,out] operation The key derivation operation object to read from.\n * \\param[in] params        Customization parameters for the key derivation.\n *                          When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT\n *                          with \\p params_data_length = 0,\n *                          this function is equivalent to\n *                          psa_key_derivation_output_key().\n *                          Mbed TLS currently only supports the default\n *                          production parameters, i.e.\n *                          #PSA_KEY_PRODUCTION_PARAMETERS_INIT,\n *                          for all key types.\n * \\param params_data_length\n *                          Length of `params->data` in bytes.\n * \\param[out] key          On success, an identifier for the newly created\n *                          key. For persistent keys, this is the key\n *                          identifier defined in \\p attributes.\n *                          \\c 0 on failure.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n *         If the key is persistent, the key material and the key's metadata\n *         have been saved to persistent storage.\n * \\retval #PSA_ERROR_ALREADY_EXISTS\n *         This is an attempt to create a persistent key, and there is\n *         already a persistent key with the given identifier.\n * \\retval #PSA_ERROR_INSUFFICIENT_DATA\n *         There was not enough data to create the desired key.\n *         Note that in this case, no output is written to the output buffer.\n *         The operation's capacity is set to 0, thus subsequent calls to\n *         this function will not succeed, even with a smaller output buffer.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         The key type or key size is not supported, either by the\n *         implementation in general or in this particular location.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The provided key attributes are not valid for the operation.\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The #PSA_KEY_DERIVATION_INPUT_SECRET or\n *         #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a\n *         key; or one of the inputs was a key whose policy didn't allow\n *         #PSA_KEY_USAGE_DERIVE.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active and completed\n *         all required input steps), or the library has not been previously\n *         initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_key_derivation_output_key_ext(\n    const psa_key_attributes_t *attributes,\n    psa_key_derivation_operation_t *operation,\n    const psa_key_production_parameters_t *params,\n    size_t params_data_length,\n    mbedtls_svc_key_id_t *key);\n#endif /* !__cplusplus */\n\n/** Compare output data from a key derivation operation to an expected value.\n *\n * This function calculates output bytes from a key derivation algorithm and\n * compares those bytes to an expected value in constant time.\n * If you view the key derivation's output as a stream of bytes, this\n * function destructively reads the expected number of bytes from the\n * stream before comparing them.\n * The operation's capacity decreases by the number of bytes read.\n *\n * This is functionally equivalent to the following code:\n * \\code\n * psa_key_derivation_output_bytes(operation, tmp, output_length);\n * if (memcmp(output, tmp, output_length) != 0)\n *     return PSA_ERROR_INVALID_SIGNATURE;\n * \\endcode\n * except (1) it works even if the key's policy does not allow outputting the\n * bytes, and (2) the comparison will be done in constant time.\n *\n * If this function returns an error status other than\n * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE,\n * the operation enters an error state and must be aborted by calling\n * psa_key_derivation_abort().\n *\n * \\param[in,out] operation The key derivation operation object to read from.\n * \\param[in] expected      Buffer containing the expected derivation output.\n * \\param expected_length   Length of the expected output; this is also the\n *                          number of bytes that will be read.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The output was read successfully, but it differs from the expected\n *         output.\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         One of the inputs was a key whose policy didn't allow\n *         #PSA_KEY_USAGE_VERIFY_DERIVATION.\n * \\retval #PSA_ERROR_INSUFFICIENT_DATA\n *                          The operation's capacity was less than\n *                          \\p output_length bytes. Note that in this case,\n *                          the operation's capacity is set to 0, thus\n *                          subsequent calls to this function will not\n *                          succeed, even with a smaller expected output.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active and completed\n *         all required input steps), or the library has not been previously\n *         initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_key_derivation_verify_bytes(\n    psa_key_derivation_operation_t *operation,\n    const uint8_t *expected,\n    size_t expected_length);\n\n/** Compare output data from a key derivation operation to an expected value\n * stored in a key object.\n *\n * This function calculates output bytes from a key derivation algorithm and\n * compares those bytes to an expected value, provided as key of type\n * #PSA_KEY_TYPE_PASSWORD_HASH.\n * If you view the key derivation's output as a stream of bytes, this\n * function destructively reads the number of bytes corresponding to the\n * length of the expected value from the stream before comparing them.\n * The operation's capacity decreases by the number of bytes read.\n *\n * This is functionally equivalent to exporting the key and calling\n * psa_key_derivation_verify_bytes() on the result, except that it\n * works even if the key cannot be exported.\n *\n * If this function returns an error status other than\n * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE,\n * the operation enters an error state and must be aborted by calling\n * psa_key_derivation_abort().\n *\n * \\param[in,out] operation The key derivation operation object to read from.\n * \\param[in] expected      A key of type #PSA_KEY_TYPE_PASSWORD_HASH\n *                          containing the expected output. Its policy must\n *                          include the #PSA_KEY_USAGE_VERIFY_DERIVATION flag\n *                          and the permitted algorithm must match the\n *                          operation. The value of this key was likely\n *                          computed by a previous call to\n *                          psa_key_derivation_output_key() or\n *                          psa_key_derivation_output_key_custom().\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The output was read successfully, but if differs from the expected\n *         output.\n * \\retval #PSA_ERROR_INVALID_HANDLE\n *         The key passed as the expected value does not exist.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The key passed as the expected value has an invalid type.\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The key passed as the expected value does not allow this usage or\n *         this algorithm; or one of the inputs was a key whose policy didn't\n *         allow #PSA_KEY_USAGE_VERIFY_DERIVATION.\n * \\retval #PSA_ERROR_INSUFFICIENT_DATA\n *                          The operation's capacity was less than\n *                          the length of the expected value. In this case,\n *                          the operation's capacity is set to 0, thus\n *                          subsequent calls to this function will not\n *                          succeed, even with a smaller expected output.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active and completed\n *         all required input steps), or the library has not been previously\n *         initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_key_derivation_verify_key(\n    psa_key_derivation_operation_t *operation,\n    psa_key_id_t expected);\n\n/** Abort a key derivation operation.\n *\n * Aborting an operation frees all associated resources except for the \\c\n * operation structure itself. Once aborted, the operation object can be reused\n * for another operation by calling psa_key_derivation_setup() again.\n *\n * This function may be called at any time after the operation\n * object has been initialized as described in #psa_key_derivation_operation_t.\n *\n * In particular, it is valid to call psa_key_derivation_abort() twice, or to\n * call psa_key_derivation_abort() on an operation that has not been set up.\n *\n * \\param[in,out] operation    The operation to abort.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_key_derivation_abort(\n    psa_key_derivation_operation_t *operation);\n\n/** Perform a key agreement and return the raw shared secret.\n *\n * \\warning The raw result of a key agreement algorithm such as finite-field\n * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should\n * not be used directly as key material. It should instead be passed as\n * input to a key derivation algorithm. To chain a key agreement with\n * a key derivation, use psa_key_derivation_key_agreement() and other\n * functions from the key derivation interface.\n *\n * \\param alg                     The key agreement algorithm to compute\n *                                (\\c PSA_ALG_XXX value such that\n *                                #PSA_ALG_IS_RAW_KEY_AGREEMENT(\\p alg)\n *                                is true).\n * \\param private_key             Identifier of the private key to use. It must\n *                                allow the usage #PSA_KEY_USAGE_DERIVE.\n * \\param[in] peer_key            Public key of the peer. It must be\n *                                in the same format that psa_import_key()\n *                                accepts. The standard formats for public\n *                                keys are documented in the documentation\n *                                of psa_export_public_key().\n * \\param peer_key_length         Size of \\p peer_key in bytes.\n * \\param[out] output             Buffer where the decrypted message is to\n *                                be written.\n * \\param output_size             Size of the \\c output buffer in bytes.\n * \\param[out] output_length      On success, the number of bytes\n *                                that make up the returned output.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p alg is not a key agreement algorithm, or\n *         \\p private_key is not compatible with \\p alg,\n *         or \\p peer_key is not valid for \\p alg or not compatible with\n *         \\p private_key.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         \\p output_size is too small\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not a supported key agreement algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_raw_key_agreement(psa_algorithm_t alg,\n                                   mbedtls_svc_key_id_t private_key,\n                                   const uint8_t *peer_key,\n                                   size_t peer_key_length,\n                                   uint8_t *output,\n                                   size_t output_size,\n                                   size_t *output_length);\n\n/**@}*/\n\n/** \\defgroup random Random generation\n * @{\n */\n\n/**\n * \\brief Generate random bytes.\n *\n * \\warning This function **can** fail! Callers MUST check the return status\n *          and MUST NOT use the content of the output buffer if the return\n *          status is not #PSA_SUCCESS.\n *\n * \\note    To generate a key, use psa_generate_key() instead.\n *\n * \\param[out] output       Output buffer for the generated data.\n * \\param output_size       Number of bytes to generate and output.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_generate_random(uint8_t *output,\n                                 size_t output_size);\n\n/**\n * \\brief Generate a key or key pair.\n *\n * The key is generated randomly.\n * Its location, usage policy, type and size are taken from \\p attributes.\n *\n * Implementations must reject an attempt to generate a key of size 0.\n *\n * The following type-specific considerations apply:\n * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR),\n *   the public exponent is 65537.\n *   The modulus is a product of two probabilistic primes\n *   between 2^{n-1} and 2^n where n is the bit size specified in the\n *   attributes.\n *\n * \\note This function is equivalent to calling psa_generate_key_custom()\n *       with the custom production parameters #PSA_CUSTOM_KEY_PARAMETERS_INIT\n *       and `custom_data_length == 0` (i.e. `custom_data` is empty).\n *\n * \\param[in] attributes    The attributes for the new key.\n * \\param[out] key          On success, an identifier for the newly created\n *                          key. For persistent keys, this is the key\n *                          identifier defined in \\p attributes.\n *                          \\c 0 on failure.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n *         If the key is persistent, the key material and the key's metadata\n *         have been saved to persistent storage.\n * \\retval #PSA_ERROR_ALREADY_EXISTS\n *         This is an attempt to create a persistent key, and there is\n *         already a persistent key with the given identifier.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_generate_key(const psa_key_attributes_t *attributes,\n                              mbedtls_svc_key_id_t *key);\n\n/**\n * \\brief Generate a key or key pair using custom production parameters.\n *\n * See the description of psa_generate_key() for the operation of this\n * function with the default production parameters. In addition, this function\n * supports the following production customizations, described in more detail\n * in the documentation of ::psa_custom_key_parameters_t:\n *\n * - RSA keys: generation with a custom public exponent.\n *\n * \\note This function is experimental and may change in future minor\n *       versions of Mbed TLS.\n *\n * \\param[in] attributes    The attributes for the new key.\n * \\param[in] custom        Customization parameters for the key generation.\n *                          When this is #PSA_CUSTOM_KEY_PARAMETERS_INIT\n *                          with \\p custom_data_length = 0,\n *                          this function is equivalent to\n *                          psa_generate_key().\n * \\param[in] custom_data   Variable-length data associated with \\c custom.\n * \\param custom_data_length\n *                          Length of `custom_data` in bytes.\n * \\param[out] key          On success, an identifier for the newly created\n *                          key. For persistent keys, this is the key\n *                          identifier defined in \\p attributes.\n *                          \\c 0 on failure.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n *         If the key is persistent, the key material and the key's metadata\n *         have been saved to persistent storage.\n * \\retval #PSA_ERROR_ALREADY_EXISTS\n *         This is an attempt to create a persistent key, and there is\n *         already a persistent key with the given identifier.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_generate_key_custom(const psa_key_attributes_t *attributes,\n                                     const psa_custom_key_parameters_t *custom,\n                                     const uint8_t *custom_data,\n                                     size_t custom_data_length,\n                                     mbedtls_svc_key_id_t *key);\n\n#ifndef __cplusplus\n/* Omitted when compiling in C++, because one of the parameters is a\n * pointer to a struct with a flexible array member, and that is not\n * standard C++.\n * https://github.com/Mbed-TLS/mbedtls/issues/9020\n */\n/**\n * \\brief Generate a key or key pair using custom production parameters.\n *\n * \\note\n * This is a deprecated variant of psa_key_derivation_output_key_custom().\n * It is equivalent except that the associated variable-length data\n * is passed in `params->data` instead of a separate parameter.\n * This function will be removed in a future version of Mbed TLS.\n *\n * \\param[in] attributes    The attributes for the new key.\n * \\param[in] params        Customization parameters for the key generation.\n *                          When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT\n *                          with \\p params_data_length = 0,\n *                          this function is equivalent to\n *                          psa_generate_key().\n * \\param params_data_length\n *                          Length of `params->data` in bytes.\n * \\param[out] key          On success, an identifier for the newly created\n *                          key. For persistent keys, this is the key\n *                          identifier defined in \\p attributes.\n *                          \\c 0 on failure.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n *         If the key is persistent, the key material and the key's metadata\n *         have been saved to persistent storage.\n * \\retval #PSA_ERROR_ALREADY_EXISTS\n *         This is an attempt to create a persistent key, and there is\n *         already a persistent key with the given identifier.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes,\n                                  const psa_key_production_parameters_t *params,\n                                  size_t params_data_length,\n                                  mbedtls_svc_key_id_t *key);\n#endif /* !__cplusplus */\n\n/**@}*/\n\n/** \\defgroup interruptible_hash Interruptible sign/verify hash\n * @{\n */\n\n/** The type of the state data structure for interruptible hash\n *  signing operations.\n *\n * Before calling any function on a sign hash operation object, the\n * application must initialize it by any of the following means:\n * - Set the structure to all-bits-zero, for example:\n *   \\code\n *   psa_sign_hash_interruptible_operation_t operation;\n *   memset(&operation, 0, sizeof(operation));\n *   \\endcode\n * - Initialize the structure to logical zero values, for example:\n *   \\code\n *   psa_sign_hash_interruptible_operation_t operation = {0};\n *   \\endcode\n * - Initialize the structure to the initializer\n *   #PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT, for example:\n *   \\code\n *   psa_sign_hash_interruptible_operation_t operation =\n *   PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT;\n *   \\endcode\n * - Assign the result of the function\n *   psa_sign_hash_interruptible_operation_init() to the structure, for\n *   example:\n *   \\code\n *   psa_sign_hash_interruptible_operation_t operation;\n *   operation = psa_sign_hash_interruptible_operation_init();\n *   \\endcode\n *\n * This is an implementation-defined \\c struct. Applications should not\n * make any assumptions about the content of this structure.\n * Implementation details can change in future versions without notice. */\ntypedef struct psa_sign_hash_interruptible_operation_s psa_sign_hash_interruptible_operation_t;\n\n/** The type of the state data structure for interruptible hash\n *  verification operations.\n *\n * Before calling any function on a sign hash operation object, the\n * application must initialize it by any of the following means:\n * - Set the structure to all-bits-zero, for example:\n *   \\code\n *   psa_verify_hash_interruptible_operation_t operation;\n *   memset(&operation, 0, sizeof(operation));\n *   \\endcode\n * - Initialize the structure to logical zero values, for example:\n *   \\code\n *   psa_verify_hash_interruptible_operation_t operation = {0};\n *   \\endcode\n * - Initialize the structure to the initializer\n *   #PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT, for example:\n *   \\code\n *   psa_verify_hash_interruptible_operation_t operation =\n *   PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT;\n *   \\endcode\n * - Assign the result of the function\n *   psa_verify_hash_interruptible_operation_init() to the structure, for\n *   example:\n *   \\code\n *   psa_verify_hash_interruptible_operation_t operation;\n *   operation = psa_verify_hash_interruptible_operation_init();\n *   \\endcode\n *\n * This is an implementation-defined \\c struct. Applications should not\n * make any assumptions about the content of this structure.\n * Implementation details can change in future versions without notice. */\ntypedef struct psa_verify_hash_interruptible_operation_s psa_verify_hash_interruptible_operation_t;\n\n/**\n * \\brief                       Set the maximum number of ops allowed to be\n *                              executed by an interruptible function in a\n *                              single call.\n *\n * \\warning                     This is a beta API, and thus subject to change\n *                              at any point. It is not bound by the usual\n *                              interface stability promises.\n *\n * \\note                        The time taken to execute a single op is\n *                              implementation specific and depends on\n *                              software, hardware, the algorithm, key type and\n *                              curve chosen. Even within a single operation,\n *                              successive ops can take differing amounts of\n *                              time. The only guarantee is that lower values\n *                              for \\p max_ops means functions will block for a\n *                              lesser maximum amount of time. The functions\n *                              \\c psa_sign_interruptible_get_num_ops() and\n *                              \\c psa_verify_interruptible_get_num_ops() are\n *                              provided to help with tuning this value.\n *\n * \\note                        This value defaults to\n *                              #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, which\n *                              means the whole operation will be done in one\n *                              go, regardless of the number of ops required.\n *\n * \\note                        If more ops are needed to complete a\n *                              computation, #PSA_OPERATION_INCOMPLETE will be\n *                              returned by the function performing the\n *                              computation. It is then the caller's\n *                              responsibility to either call again with the\n *                              same operation context until it returns 0 or an\n *                              error code; or to call the relevant abort\n *                              function if the answer is no longer required.\n *\n * \\note                        The interpretation of \\p max_ops is also\n *                              implementation defined. On a hard real time\n *                              system, this can indicate a hard deadline, as a\n *                              real-time system needs a guarantee of not\n *                              spending more than X time, however care must be\n *                              taken in such an implementation to avoid the\n *                              situation whereby calls just return, not being\n *                              able to do any actual work within the allotted\n *                              time.  On a non-real-time system, the\n *                              implementation can be more relaxed, but again\n *                              whether this number should be interpreted as as\n *                              hard or soft limit or even whether a less than\n *                              or equals as regards to ops executed in a\n *                              single call is implementation defined.\n *\n * \\note                        For keys in local storage when no accelerator\n *                              driver applies, please see also the\n *                              documentation for \\c mbedtls_ecp_set_max_ops(),\n *                              which is the internal implementation in these\n *                              cases.\n *\n * \\warning                     With implementations that interpret this number\n *                              as a hard limit, setting this number too small\n *                              may result in an infinite loop, whereby each\n *                              call results in immediate return with no ops\n *                              done (as there is not enough time to execute\n *                              any), and thus no result will ever be achieved.\n *\n * \\note                        This only applies to functions whose\n *                              documentation mentions they may return\n *                              #PSA_OPERATION_INCOMPLETE.\n *\n * \\param max_ops               The maximum number of ops to be executed in a\n *                              single call. This can be a number from 0 to\n *                              #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, where 0\n *                              is the least amount of work done per call.\n */\nvoid psa_interruptible_set_max_ops(uint32_t max_ops);\n\n/**\n * \\brief                       Get the maximum number of ops allowed to be\n *                              executed by an interruptible function in a\n *                              single call. This will return the last\n *                              value set by\n *                              \\c psa_interruptible_set_max_ops() or\n *                              #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED if\n *                              that function has never been called.\n *\n * \\warning                     This is a beta API, and thus subject to change\n *                              at any point. It is not bound by the usual\n *                              interface stability promises.\n *\n * \\return                      Maximum number of ops allowed to be\n *                              executed by an interruptible function in a\n *                              single call.\n */\nuint32_t psa_interruptible_get_max_ops(void);\n\n/**\n * \\brief                       Get the number of ops that a hash signing\n *                              operation has taken so far. If the operation\n *                              has completed, then this will represent the\n *                              number of ops required for the entire\n *                              operation. After initialization or calling\n *                              \\c psa_sign_hash_interruptible_abort() on\n *                              the operation, a value of 0 will be returned.\n *\n * \\note                        This interface is guaranteed re-entrant and\n *                              thus may be called from driver code.\n *\n * \\warning                     This is a beta API, and thus subject to change\n *                              at any point. It is not bound by the usual\n *                              interface stability promises.\n *\n *                              This is a helper provided to help you tune the\n *                              value passed to \\c\n *                              psa_interruptible_set_max_ops().\n *\n * \\param operation             The \\c psa_sign_hash_interruptible_operation_t\n *                              to use. This must be initialized first.\n *\n * \\return                      Number of ops that the operation has taken so\n *                              far.\n */\nuint32_t psa_sign_hash_get_num_ops(\n    const psa_sign_hash_interruptible_operation_t *operation);\n\n/**\n * \\brief                       Get the number of ops that a hash verification\n *                              operation has taken so far. If the operation\n *                              has completed, then this will represent the\n *                              number of ops required for the entire\n *                              operation. After initialization or calling \\c\n *                              psa_verify_hash_interruptible_abort() on the\n *                              operation, a value of 0 will be returned.\n *\n * \\warning                     This is a beta API, and thus subject to change\n *                              at any point. It is not bound by the usual\n *                              interface stability promises.\n *\n *                              This is a helper provided to help you tune the\n *                              value passed to \\c\n *                              psa_interruptible_set_max_ops().\n *\n * \\param operation             The \\c\n *                              psa_verify_hash_interruptible_operation_t to\n *                              use. This must be initialized first.\n *\n * \\return                      Number of ops that the operation has taken so\n *                              far.\n */\nuint32_t psa_verify_hash_get_num_ops(\n    const psa_verify_hash_interruptible_operation_t *operation);\n\n/**\n * \\brief                       Start signing a hash or short message with a\n *                              private key, in an interruptible manner.\n *\n * \\see                         \\c psa_sign_hash_complete()\n *\n * \\warning                     This is a beta API, and thus subject to change\n *                              at any point. It is not bound by the usual\n *                              interface stability promises.\n *\n * \\note                        This function combined with \\c\n *                              psa_sign_hash_complete() is equivalent to\n *                              \\c psa_sign_hash() but\n *                              \\c psa_sign_hash_complete() can return early and\n *                              resume according to the limit set with \\c\n *                              psa_interruptible_set_max_ops() to reduce the\n *                              maximum time spent in a function call.\n *\n * \\note                        Users should call \\c psa_sign_hash_complete()\n *                              repeatedly on the same context after a\n *                              successful call to this function until \\c\n *                              psa_sign_hash_complete() either returns 0 or an\n *                              error. \\c psa_sign_hash_complete() will return\n *                              #PSA_OPERATION_INCOMPLETE if there is more work\n *                              to do. Alternatively users can call\n *                              \\c psa_sign_hash_abort() at any point if they no\n *                              longer want the result.\n *\n * \\note                        If this function returns an error status, the\n *                              operation enters an error state and must be\n *                              aborted by calling \\c psa_sign_hash_abort().\n *\n * \\param[in, out] operation    The \\c psa_sign_hash_interruptible_operation_t\n *                              to use. This must be initialized first.\n *\n * \\param key                   Identifier of the key to use for the operation.\n *                              It must be an asymmetric key pair. The key must\n *                              allow the usage #PSA_KEY_USAGE_SIGN_HASH.\n * \\param alg                   A signature algorithm (\\c PSA_ALG_XXX\n *                              value such that #PSA_ALG_IS_SIGN_HASH(\\p alg)\n *                              is true), that is compatible with\n *                              the type of \\p key.\n * \\param[in] hash              The hash or message to sign.\n * \\param hash_length           Size of the \\p hash buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         The operation started successfully - call \\c psa_sign_hash_complete()\n *         with the same context to complete the operation\n *\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The key does not have the #PSA_KEY_USAGE_SIGN_HASH flag, or it does\n *         not permit the requested algorithm.\n * \\retval #PSA_ERROR_BAD_STATE\n *         An operation has previously been started on this context, and is\n *         still in progress.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_sign_hash_start(\n    psa_sign_hash_interruptible_operation_t *operation,\n    mbedtls_svc_key_id_t key, psa_algorithm_t alg,\n    const uint8_t *hash, size_t hash_length);\n\n/**\n * \\brief                       Continue and eventually complete the action of\n *                              signing a hash or short message with a private\n *                              key, in an interruptible manner.\n *\n * \\see                         \\c psa_sign_hash_start()\n *\n * \\warning                     This is a beta API, and thus subject to change\n *                              at any point. It is not bound by the usual\n *                              interface stability promises.\n *\n * \\note                        This function combined with \\c\n *                              psa_sign_hash_start() is equivalent to\n *                              \\c psa_sign_hash() but this function can return\n *                              early and resume according to the limit set with\n *                              \\c psa_interruptible_set_max_ops() to reduce the\n *                              maximum time spent in a function call.\n *\n * \\note                        Users should call this function on the same\n *                              operation object repeatedly until it either\n *                              returns 0 or an error. This function will return\n *                              #PSA_OPERATION_INCOMPLETE if there is more work\n *                              to do. Alternatively users can call\n *                              \\c psa_sign_hash_abort() at any point if they no\n *                              longer want the result.\n *\n * \\note                        When this function returns successfully, the\n *                              operation becomes inactive. If this function\n *                              returns an error status, the operation enters an\n *                              error state and must be aborted by calling\n *                              \\c psa_sign_hash_abort().\n *\n * \\param[in, out] operation    The \\c psa_sign_hash_interruptible_operation_t\n *                              to use. This must be initialized first, and have\n *                              had \\c psa_sign_hash_start() called with it\n *                              first.\n *\n * \\param[out] signature        Buffer where the signature is to be written.\n * \\param signature_size        Size of the \\p signature buffer in bytes. This\n *                              must be appropriate for the selected\n *                              algorithm and key:\n *                              - The required signature size is\n *                                #PSA_SIGN_OUTPUT_SIZE(\\c key_type, \\c\n *                                key_bits, \\c alg) where \\c key_type and \\c\n *                                key_bits are the type and bit-size\n *                                respectively of key.\n *                              - #PSA_SIGNATURE_MAX_SIZE evaluates to the\n *                                maximum signature size of any supported\n *                                signature algorithm.\n * \\param[out] signature_length On success, the number of bytes that make up\n *                              the returned signature value.\n *\n * \\retval #PSA_SUCCESS\n *         Operation completed successfully\n *\n * \\retval #PSA_OPERATION_INCOMPLETE\n *         Operation was interrupted due to the setting of \\c\n *         psa_interruptible_set_max_ops(). There is still work to be done.\n *         Call this function again with the same operation object.\n *\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p signature buffer is too small. You can\n *         determine a sufficient buffer size by calling\n *         #PSA_SIGN_OUTPUT_SIZE(\\c key_type, \\c key_bits, \\c alg)\n *         where \\c key_type and \\c key_bits are the type and bit-size\n *         respectively of \\c key.\n *\n * \\retval #PSA_ERROR_BAD_STATE\n *         An operation was not previously started on this context via\n *         \\c psa_sign_hash_start().\n *\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has either not been previously initialized by\n *         psa_crypto_init() or you did not previously call\n *         psa_sign_hash_start() with this operation object. It is\n *         implementation-dependent whether a failure to initialize results in\n *         this error code.\n */\npsa_status_t psa_sign_hash_complete(\n    psa_sign_hash_interruptible_operation_t *operation,\n    uint8_t *signature, size_t signature_size,\n    size_t *signature_length);\n\n/**\n * \\brief                       Abort a sign hash operation.\n *\n * \\warning                     This is a beta API, and thus subject to change\n *                              at any point. It is not bound by the usual\n *                              interface stability promises.\n *\n * \\note                        This function is the only function that clears\n *                              the number of ops completed as part of the\n *                              operation. Please ensure you copy this value via\n *                              \\c psa_sign_hash_get_num_ops() if required\n *                              before calling.\n *\n * \\note                        Aborting an operation frees all associated\n *                              resources except for the \\p operation structure\n *                              itself. Once aborted, the operation object can\n *                              be reused for another operation by calling \\c\n *                              psa_sign_hash_start() again.\n *\n * \\note                        You may call this function any time after the\n *                              operation object has been initialized. In\n *                              particular, calling \\c psa_sign_hash_abort()\n *                              after the operation has already been terminated\n *                              by a call to \\c psa_sign_hash_abort() or\n *                              psa_sign_hash_complete() is safe.\n *\n * \\param[in,out] operation     Initialized sign hash operation.\n *\n * \\retval #PSA_SUCCESS\n *         The operation was aborted successfully.\n *\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_sign_hash_abort(\n    psa_sign_hash_interruptible_operation_t *operation);\n\n/**\n * \\brief                       Start reading and verifying a hash or short\n *                              message, in an interruptible manner.\n *\n * \\see                         \\c psa_verify_hash_complete()\n *\n * \\warning                     This is a beta API, and thus subject to change\n *                              at any point. It is not bound by the usual\n *                              interface stability promises.\n *\n * \\note                        This function combined with \\c\n *                              psa_verify_hash_complete() is equivalent to\n *                              \\c psa_verify_hash() but \\c\n *                              psa_verify_hash_complete() can return early and\n *                              resume according to the limit set with \\c\n *                              psa_interruptible_set_max_ops() to reduce the\n *                              maximum time spent in a function.\n *\n * \\note                        Users should call \\c psa_verify_hash_complete()\n *                              repeatedly on the same operation object after a\n *                              successful call to this function until \\c\n *                              psa_verify_hash_complete() either returns 0 or\n *                              an error. \\c psa_verify_hash_complete() will\n *                              return #PSA_OPERATION_INCOMPLETE if there is\n *                              more work to do. Alternatively users can call\n *                              \\c psa_verify_hash_abort() at any point if they\n *                              no longer want the result.\n *\n * \\note                        If this function returns an error status, the\n *                              operation enters an error state and must be\n *                              aborted by calling \\c psa_verify_hash_abort().\n *\n * \\param[in, out] operation    The \\c psa_verify_hash_interruptible_operation_t\n *                              to use. This must be initialized first.\n *\n * \\param key                   Identifier of the key to use for the operation.\n *                              The key must allow the usage\n *                              #PSA_KEY_USAGE_VERIFY_HASH.\n * \\param alg                   A signature algorithm (\\c PSA_ALG_XXX\n *                              value such that #PSA_ALG_IS_SIGN_HASH(\\p alg)\n *                              is true), that is compatible with\n *                              the type of \\p key.\n * \\param[in] hash              The hash whose signature is to be verified.\n * \\param hash_length           Size of the \\p hash buffer in bytes.\n * \\param[in] signature         Buffer containing the signature to verify.\n * \\param signature_length      Size of the \\p signature buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         The operation started successfully - please call \\c\n *         psa_verify_hash_complete() with the same context to complete the\n *         operation.\n *\n * \\retval #PSA_ERROR_BAD_STATE\n *         Another operation has already been started on this context, and is\n *         still in progress.\n *\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The key does not have the #PSA_KEY_USAGE_VERIFY_HASH flag, or it does\n *         not permit the requested algorithm.\n *\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_verify_hash_start(\n    psa_verify_hash_interruptible_operation_t *operation,\n    mbedtls_svc_key_id_t key, psa_algorithm_t alg,\n    const uint8_t *hash, size_t hash_length,\n    const uint8_t *signature, size_t signature_length);\n\n/**\n * \\brief                       Continue and eventually complete the action of\n *                              reading and verifying a hash or short message\n *                              signed with a private key, in an interruptible\n *                              manner.\n *\n * \\see                         \\c psa_verify_hash_start()\n *\n * \\warning                     This is a beta API, and thus subject to change\n *                              at any point. It is not bound by the usual\n *                              interface stability promises.\n *\n * \\note                        This function combined with \\c\n *                              psa_verify_hash_start() is equivalent to\n *                              \\c psa_verify_hash() but this function can\n *                              return early and resume according to the limit\n *                              set with \\c psa_interruptible_set_max_ops() to\n *                              reduce the maximum time spent in a function\n *                              call.\n *\n * \\note                        Users should call this function on the same\n *                              operation object repeatedly until it either\n *                              returns 0 or an error. This function will return\n *                              #PSA_OPERATION_INCOMPLETE if there is more work\n *                              to do. Alternatively users can call\n *                              \\c psa_verify_hash_abort() at any point if they\n *                              no longer want the result.\n *\n * \\note                        When this function returns successfully, the\n *                              operation becomes inactive. If this function\n *                              returns an error status, the operation enters an\n *                              error state and must be aborted by calling\n *                              \\c psa_verify_hash_abort().\n *\n * \\param[in, out] operation    The \\c psa_verify_hash_interruptible_operation_t\n *                              to use. This must be initialized first, and have\n *                              had \\c psa_verify_hash_start() called with it\n *                              first.\n *\n * \\retval #PSA_SUCCESS\n *         Operation completed successfully, and the passed signature is valid.\n *\n * \\retval #PSA_OPERATION_INCOMPLETE\n *         Operation was interrupted due to the setting of \\c\n *         psa_interruptible_set_max_ops(). There is still work to be done.\n *         Call this function again with the same operation object.\n *\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The calculation was performed successfully, but the passed\n *         signature is not a valid signature.\n * \\retval #PSA_ERROR_BAD_STATE\n *         An operation was not previously started on this context via\n *         \\c psa_verify_hash_start().\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has either not been previously initialized by\n *         psa_crypto_init() or you did not previously call\n *         psa_verify_hash_start() on this object. It is\n *         implementation-dependent whether a failure to initialize results in\n *         this error code.\n */\npsa_status_t psa_verify_hash_complete(\n    psa_verify_hash_interruptible_operation_t *operation);\n\n/**\n * \\brief                     Abort a verify hash operation.\n *\n * \\warning                   This is a beta API, and thus subject to change at\n *                            any point. It is not bound by the usual interface\n *                            stability promises.\n *\n * \\note                      This function is the only function that clears the\n *                            number of ops completed as part of the operation.\n *                            Please ensure you copy this value via\n *                            \\c psa_verify_hash_get_num_ops() if required\n *                            before calling.\n *\n * \\note                      Aborting an operation frees all associated\n *                            resources except for the operation structure\n *                            itself. Once aborted, the operation object can be\n *                            reused for another operation by calling \\c\n *                            psa_verify_hash_start() again.\n *\n * \\note                      You may call this function any time after the\n *                            operation object has been initialized.\n *                            In particular, calling \\c psa_verify_hash_abort()\n *                            after the operation has already been terminated by\n *                            a call to \\c psa_verify_hash_abort() or\n *                            psa_verify_hash_complete() is safe.\n *\n * \\param[in,out] operation   Initialized verify hash operation.\n *\n * \\retval #PSA_SUCCESS\n *         The operation was aborted successfully.\n *\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_verify_hash_abort(\n    psa_verify_hash_interruptible_operation_t *operation);\n\n\n/**@}*/\n\n#ifdef __cplusplus\n}\n#endif\n\n/* The file \"crypto_extra.h\" contains vendor-specific definitions. This\n * can include vendor-defined algorithms, extra functions, etc. */\n#include \"crypto_extra.h\"\n\n#endif /* PSA_CRYPTO_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_adjust_auto_enabled.h",
    "content": "/**\n * \\file psa/crypto_adjust_auto_enabled.h\n * \\brief Adjust PSA configuration: enable always-on features\n *\n * This is an internal header. Do not include it directly.\n *\n * Always enable certain features which require a negligible amount of code\n * to implement, to avoid some edge cases in the configuration combinatorics.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_ADJUST_AUTO_ENABLED_H\n#define PSA_CRYPTO_ADJUST_AUTO_ENABLED_H\n\n#if !defined(MBEDTLS_CONFIG_FILES_READ)\n#error \"Do not include psa/crypto_adjust_*.h manually! This can lead to problems, \" \\\n    \"up to and including runtime errors such as buffer overflows. \" \\\n    \"If you're trying to fix a complaint from check_config.h, just remove \" \\\n    \"it from your configuration file: since Mbed TLS 3.0, it is included \" \\\n    \"automatically at the right point.\"\n#endif /* */\n\n#define PSA_WANT_KEY_TYPE_DERIVE 1\n#define PSA_WANT_KEY_TYPE_PASSWORD 1\n#define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1\n#define PSA_WANT_KEY_TYPE_RAW_DATA 1\n\n#endif /* PSA_CRYPTO_ADJUST_AUTO_ENABLED_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_adjust_config_dependencies.h",
    "content": "/**\n * \\file psa/crypto_adjust_config_dependencies.h\n * \\brief Adjust PSA configuration by resolving some dependencies.\n *\n * This is an internal header. Do not include it directly.\n *\n * See docs/proposed/psa-conditional-inclusion-c.md.\n * If the Mbed TLS implementation of a cryptographic mechanism A depends on a\n * cryptographic mechanism B then if the cryptographic mechanism A is enabled\n * and not accelerated enable B. Note that if A is enabled and accelerated, it\n * is not necessary to enable B for A support.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_ADJUST_CONFIG_DEPENDENCIES_H\n#define PSA_CRYPTO_ADJUST_CONFIG_DEPENDENCIES_H\n\n#if !defined(MBEDTLS_CONFIG_FILES_READ)\n#error \"Do not include psa/crypto_adjust_*.h manually! This can lead to problems, \" \\\n    \"up to and including runtime errors such as buffer overflows. \" \\\n    \"If you're trying to fix a complaint from check_config.h, just remove \" \\\n    \"it from your configuration file: since Mbed TLS 3.0, it is included \" \\\n    \"automatically at the right point.\"\n#endif /* */\n\n#if (defined(PSA_WANT_ALG_TLS12_PRF) && \\\n    !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF)) || \\\n    (defined(PSA_WANT_ALG_TLS12_PSK_TO_MS) && \\\n    !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS)) || \\\n    (defined(PSA_WANT_ALG_HKDF) && \\\n    !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF)) || \\\n    (defined(PSA_WANT_ALG_HKDF_EXTRACT) && \\\n    !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT)) || \\\n    (defined(PSA_WANT_ALG_HKDF_EXPAND) && \\\n    !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND)) || \\\n    (defined(PSA_WANT_ALG_PBKDF2_HMAC) && \\\n    !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC))\n#define PSA_WANT_ALG_HMAC 1\n#define PSA_WANT_KEY_TYPE_HMAC 1\n#endif\n\n#if (defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128) && \\\n    !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128))\n#define PSA_WANT_KEY_TYPE_AES 1\n#define PSA_WANT_ALG_CMAC 1\n#endif\n\n#endif /* PSA_CRYPTO_ADJUST_CONFIG_DEPENDENCIES_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_adjust_config_key_pair_types.h",
    "content": "/**\n * \\file psa/crypto_adjust_config_key_pair_types.h\n * \\brief Adjust PSA configuration for key pair types.\n *\n * This is an internal header. Do not include it directly.\n *\n * See docs/proposed/psa-conditional-inclusion-c.md.\n * - Support non-basic operations in a keypair type implicitly enables basic\n *   support for that keypair type.\n * - Support for a keypair type implicitly enables the corresponding public\n *   key type.\n * - Basic support for a keypair type implicilty enables import/export support\n *   for that keypair type. Warning: this is implementation-specific (mainly\n *   for the benefit of testing) and may change in the future!\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H\n#define PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H\n\n#if !defined(MBEDTLS_CONFIG_FILES_READ)\n#error \"Do not include psa/crypto_adjust_*.h manually! This can lead to problems, \" \\\n    \"up to and including runtime errors such as buffer overflows. \" \\\n    \"If you're trying to fix a complaint from check_config.h, just remove \" \\\n    \"it from your configuration file: since Mbed TLS 3.0, it is included \" \\\n    \"automatically at the right point.\"\n#endif /* */\n\n/*****************************************************************\n * ANYTHING -> BASIC\n ****************************************************************/\n\n#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \\\n    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \\\n    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \\\n    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1\n#endif\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \\\n    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \\\n    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) || \\\n    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE)\n#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1\n#endif\n\n#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \\\n    defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \\\n    defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) || \\\n    defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE)\n#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1\n#endif\n\n/*****************************************************************\n * BASIC -> corresponding PUBLIC\n ****************************************************************/\n\n#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC)\n#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1\n#endif\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)\n#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1\n#endif\n\n#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC)\n#define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY 1\n#endif\n\n/*****************************************************************\n * BASIC -> IMPORT+EXPORT\n *\n * (Implementation-specific, may change in the future.)\n ****************************************************************/\n\n/* Even though KEY_PAIR symbols' feature several level of support (BASIC, IMPORT,\n * EXPORT, GENERATE, DERIVE) we're not planning to have support only for BASIC\n * without IMPORT/EXPORT since these last 2 features are strongly used in tests.\n * In general it is allowed to include more feature than what is strictly\n * requested.\n * As a consequence IMPORT and EXPORT features will be automatically enabled\n * as soon as the BASIC one is. */\n#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC)\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1\n#endif\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)\n#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1\n#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1\n#endif\n\n#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC)\n#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1\n#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1\n#endif\n\n#endif /* PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_adjust_config_synonyms.h",
    "content": "/**\n * \\file psa/crypto_adjust_config_synonyms.h\n * \\brief Adjust PSA configuration: enable quasi-synonyms\n *\n * This is an internal header. Do not include it directly.\n *\n * When two features require almost the same code, we automatically enable\n * both when either one is requested, to reduce the combinatorics of\n * possible configurations.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H\n#define PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H\n\n#if !defined(MBEDTLS_CONFIG_FILES_READ)\n#error \"Do not include psa/crypto_adjust_*.h manually! This can lead to problems, \" \\\n    \"up to and including runtime errors such as buffer overflows. \" \\\n    \"If you're trying to fix a complaint from check_config.h, just remove \" \\\n    \"it from your configuration file: since Mbed TLS 3.0, it is included \" \\\n    \"automatically at the right point.\"\n#endif /* */\n\n/****************************************************************/\n/* De facto synonyms */\n/****************************************************************/\n\n#if defined(PSA_WANT_ALG_ECDSA_ANY) && !defined(PSA_WANT_ALG_ECDSA)\n#define PSA_WANT_ALG_ECDSA PSA_WANT_ALG_ECDSA_ANY\n#elif !defined(PSA_WANT_ALG_ECDSA_ANY) && defined(PSA_WANT_ALG_ECDSA)\n#define PSA_WANT_ALG_ECDSA_ANY PSA_WANT_ALG_ECDSA\n#endif\n\n#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN)\n#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW\n#elif !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN)\n#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW PSA_WANT_ALG_RSA_PKCS1V15_SIGN\n#endif\n\n#if defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && !defined(PSA_WANT_ALG_RSA_PSS)\n#define PSA_WANT_ALG_RSA_PSS PSA_WANT_ALG_RSA_PSS_ANY_SALT\n#elif !defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && defined(PSA_WANT_ALG_RSA_PSS)\n#define PSA_WANT_ALG_RSA_PSS_ANY_SALT PSA_WANT_ALG_RSA_PSS\n#endif\n\n#endif /* PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_builtin_composites.h",
    "content": "/*\n *  Context structure declaration of the Mbed TLS software-based PSA drivers\n *  called through the PSA Crypto driver dispatch layer.\n *  This file contains the context structures of those algorithms which need to\n *  rely on other algorithms, i.e. are 'composite' algorithms.\n *\n * \\note This file may not be included directly. Applications must\n * include psa/crypto.h.\n *\n * \\note This header and its content are not part of the Mbed TLS API and\n * applications must not depend on it. Its main purpose is to define the\n * multi-part state objects of the Mbed TLS software-based PSA drivers. The\n * definitions of these objects are then used by crypto_struct.h to define the\n * implementation-defined types of PSA multi-part state objects.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_BUILTIN_COMPOSITES_H\n#define PSA_CRYPTO_BUILTIN_COMPOSITES_H\n#include \"mbedtls/private_access.h\"\n\n#include <psa/crypto_driver_common.h>\n\n#include \"mbedtls/cmac.h\"\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)\n#include \"mbedtls/gcm.h\"\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)\n#include \"mbedtls/ccm.h\"\n#endif\n#include \"mbedtls/chachapoly.h\"\n\n/*\n * MAC multi-part operation definitions.\n */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)\n#define MBEDTLS_PSA_BUILTIN_MAC\n#endif\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST)\ntypedef struct {\n    /** The HMAC algorithm in use */\n    psa_algorithm_t MBEDTLS_PRIVATE(alg);\n    /** The hash context. */\n    struct psa_hash_operation_s hash_ctx;\n    /** The HMAC part of the context. */\n    uint8_t MBEDTLS_PRIVATE(opad)[PSA_HMAC_MAX_HASH_BLOCK_SIZE];\n} mbedtls_psa_hmac_operation_t;\n\n#define MBEDTLS_PSA_HMAC_OPERATION_INIT { 0, PSA_HASH_OPERATION_INIT, { 0 } }\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */\n\ntypedef struct {\n    psa_algorithm_t MBEDTLS_PRIVATE(alg);\n    union {\n        unsigned MBEDTLS_PRIVATE(dummy); /* Make the union non-empty even with no supported algorithms. */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST)\n        mbedtls_psa_hmac_operation_t MBEDTLS_PRIVATE(hmac);\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || defined(PSA_CRYPTO_DRIVER_TEST)\n        mbedtls_cipher_context_t MBEDTLS_PRIVATE(cmac);\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */\n    } MBEDTLS_PRIVATE(ctx);\n} mbedtls_psa_mac_operation_t;\n\n#define MBEDTLS_PSA_MAC_OPERATION_INIT { 0, { 0 } }\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)\n#define MBEDTLS_PSA_BUILTIN_AEAD  1\n#endif\n\n/* Context structure for the Mbed TLS AEAD implementation. */\ntypedef struct {\n    psa_algorithm_t MBEDTLS_PRIVATE(alg);\n    psa_key_type_t MBEDTLS_PRIVATE(key_type);\n\n    unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1;\n\n    uint8_t MBEDTLS_PRIVATE(tag_length);\n\n    union {\n        unsigned dummy; /* Enable easier initializing of the union. */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)\n        mbedtls_ccm_context MBEDTLS_PRIVATE(ccm);\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)\n        mbedtls_gcm_context MBEDTLS_PRIVATE(gcm);\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)\n        mbedtls_chachapoly_context MBEDTLS_PRIVATE(chachapoly);\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */\n\n    } ctx;\n\n} mbedtls_psa_aead_operation_t;\n\n#define MBEDTLS_PSA_AEAD_OPERATION_INIT { 0, 0, 0, 0, { 0 } }\n\n#include \"mbedtls/ecdsa.h\"\n\n/* Context structure for the Mbed TLS interruptible sign hash implementation. */\ntypedef struct {\n#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \\\n    defined(MBEDTLS_ECP_RESTARTABLE)\n    mbedtls_ecdsa_context *MBEDTLS_PRIVATE(ctx);\n    mbedtls_ecdsa_restart_ctx MBEDTLS_PRIVATE(restart_ctx);\n\n    uint32_t MBEDTLS_PRIVATE(num_ops);\n\n    size_t MBEDTLS_PRIVATE(coordinate_bytes);\n    psa_algorithm_t MBEDTLS_PRIVATE(alg);\n    mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg);\n    uint8_t MBEDTLS_PRIVATE(hash)[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];\n    size_t MBEDTLS_PRIVATE(hash_length);\n\n#else\n    /* Make the struct non-empty if algs not supported. */\n    unsigned MBEDTLS_PRIVATE(dummy);\n\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&\n        * defined( MBEDTLS_ECP_RESTARTABLE ) */\n} mbedtls_psa_sign_hash_interruptible_operation_t;\n\n#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \\\n    defined(MBEDTLS_ECP_RESTARTABLE)\n#define MBEDTLS_PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { { 0 }, { 0 }, 0, 0, 0, 0, 0, 0 }\n#else\n#define MBEDTLS_PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 }\n#endif\n\n/* Context structure for the Mbed TLS interruptible verify hash\n * implementation.*/\ntypedef struct {\n#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \\\n    defined(MBEDTLS_ECP_RESTARTABLE)\n\n    mbedtls_ecdsa_context *MBEDTLS_PRIVATE(ctx);\n    mbedtls_ecdsa_restart_ctx MBEDTLS_PRIVATE(restart_ctx);\n\n    uint32_t MBEDTLS_PRIVATE(num_ops);\n\n    uint8_t MBEDTLS_PRIVATE(hash)[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];\n    size_t MBEDTLS_PRIVATE(hash_length);\n\n    mbedtls_mpi MBEDTLS_PRIVATE(r);\n    mbedtls_mpi MBEDTLS_PRIVATE(s);\n\n#else\n    /* Make the struct non-empty if algs not supported. */\n    unsigned MBEDTLS_PRIVATE(dummy);\n\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&\n        * defined( MBEDTLS_ECP_RESTARTABLE ) */\n\n} mbedtls_psa_verify_hash_interruptible_operation_t;\n\n#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \\\n    defined(MBEDTLS_ECP_RESTARTABLE)\n#define MBEDTLS_VERIFY_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { { 0 }, { 0 }, 0, 0, 0, 0, { 0 }, \\\n        { 0 } }\n#else\n#define MBEDTLS_VERIFY_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 }\n#endif\n\n\n/* EC-JPAKE operation definitions */\n\n#include \"mbedtls/ecjpake.h\"\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)\n#define MBEDTLS_PSA_BUILTIN_PAKE  1\n#endif\n\n/* Note: the format for mbedtls_ecjpake_read/write function has an extra\n * length byte for each step, plus an extra 3 bytes for ECParameters in the\n * server's 2nd round. */\n#define MBEDTLS_PSA_JPAKE_BUFFER_SIZE ((3 + 1 + 65 + 1 + 65 + 1 + 32) * 2)\n\ntypedef struct {\n    psa_algorithm_t MBEDTLS_PRIVATE(alg);\n\n    uint8_t *MBEDTLS_PRIVATE(password);\n    size_t MBEDTLS_PRIVATE(password_len);\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)\n    mbedtls_ecjpake_role MBEDTLS_PRIVATE(role);\n    uint8_t MBEDTLS_PRIVATE(buffer[MBEDTLS_PSA_JPAKE_BUFFER_SIZE]);\n    size_t MBEDTLS_PRIVATE(buffer_length);\n    size_t MBEDTLS_PRIVATE(buffer_offset);\n#endif\n    /* Context structure for the Mbed TLS EC-JPAKE implementation. */\n    union {\n        unsigned int MBEDTLS_PRIVATE(dummy);\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)\n        mbedtls_ecjpake_context MBEDTLS_PRIVATE(jpake);\n#endif\n    } MBEDTLS_PRIVATE(ctx);\n\n} mbedtls_psa_pake_operation_t;\n\n#define MBEDTLS_PSA_PAKE_OPERATION_INIT { { 0 } }\n\n#endif /* PSA_CRYPTO_BUILTIN_COMPOSITES_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_builtin_key_derivation.h",
    "content": "/*\n *  Context structure declaration of the Mbed TLS software-based PSA drivers\n *  called through the PSA Crypto driver dispatch layer.\n *  This file contains the context structures of key derivation algorithms\n *  which need to rely on other algorithms.\n *\n * \\note This file may not be included directly. Applications must\n * include psa/crypto.h.\n *\n * \\note This header and its content are not part of the Mbed TLS API and\n * applications must not depend on it. Its main purpose is to define the\n * multi-part state objects of the Mbed TLS software-based PSA drivers. The\n * definitions of these objects are then used by crypto_struct.h to define the\n * implementation-defined types of PSA multi-part state objects.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H\n#define PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H\n#include \"mbedtls/private_access.h\"\n\n#include <psa/crypto_driver_common.h>\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)\ntypedef struct {\n    uint8_t *MBEDTLS_PRIVATE(info);\n    size_t MBEDTLS_PRIVATE(info_length);\n#if PSA_HASH_MAX_SIZE > 0xff\n#error \"PSA_HASH_MAX_SIZE does not fit in uint8_t\"\n#endif\n    uint8_t MBEDTLS_PRIVATE(offset_in_block);\n    uint8_t MBEDTLS_PRIVATE(block_number);\n    unsigned int MBEDTLS_PRIVATE(state) : 2;\n    unsigned int MBEDTLS_PRIVATE(info_set) : 1;\n    uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE];\n    uint8_t MBEDTLS_PRIVATE(prk)[PSA_HASH_MAX_SIZE];\n    struct psa_mac_operation_s MBEDTLS_PRIVATE(hmac);\n} psa_hkdf_key_derivation_t;\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF ||\n          MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT ||\n          MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)\ntypedef struct {\n    uint8_t MBEDTLS_PRIVATE(data)[PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE];\n} psa_tls12_ecjpake_to_pms_t;\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)\ntypedef enum {\n    PSA_TLS12_PRF_STATE_INIT,             /* no input provided */\n    PSA_TLS12_PRF_STATE_SEED_SET,         /* seed has been set */\n    PSA_TLS12_PRF_STATE_OTHER_KEY_SET,    /* other key has been set - optional */\n    PSA_TLS12_PRF_STATE_KEY_SET,          /* key has been set */\n    PSA_TLS12_PRF_STATE_LABEL_SET,        /* label has been set */\n    PSA_TLS12_PRF_STATE_OUTPUT            /* output has been started */\n} psa_tls12_prf_key_derivation_state_t;\n\ntypedef struct psa_tls12_prf_key_derivation_s {\n#if PSA_HASH_MAX_SIZE > 0xff\n#error \"PSA_HASH_MAX_SIZE does not fit in uint8_t\"\n#endif\n\n    /* Indicates how many bytes in the current HMAC block have\n     * not yet been read by the user. */\n    uint8_t MBEDTLS_PRIVATE(left_in_block);\n\n    /* The 1-based number of the block. */\n    uint8_t MBEDTLS_PRIVATE(block_number);\n\n    psa_tls12_prf_key_derivation_state_t MBEDTLS_PRIVATE(state);\n\n    uint8_t *MBEDTLS_PRIVATE(secret);\n    size_t MBEDTLS_PRIVATE(secret_length);\n    uint8_t *MBEDTLS_PRIVATE(seed);\n    size_t MBEDTLS_PRIVATE(seed_length);\n    uint8_t *MBEDTLS_PRIVATE(label);\n    size_t MBEDTLS_PRIVATE(label_length);\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)\n    uint8_t *MBEDTLS_PRIVATE(other_secret);\n    size_t MBEDTLS_PRIVATE(other_secret_length);\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */\n\n    uint8_t MBEDTLS_PRIVATE(Ai)[PSA_HASH_MAX_SIZE];\n\n    /* `HMAC_hash( prk, A( i ) + seed )` in the notation of RFC 5246, Sect. 5. */\n    uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE];\n} psa_tls12_prf_key_derivation_t;\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||\n        * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */\n#if defined(PSA_HAVE_SOFT_PBKDF2)\ntypedef enum {\n    PSA_PBKDF2_STATE_INIT,             /* no input provided */\n    PSA_PBKDF2_STATE_INPUT_COST_SET,   /* input cost has been set */\n    PSA_PBKDF2_STATE_SALT_SET,         /* salt has been set */\n    PSA_PBKDF2_STATE_PASSWORD_SET,     /* password has been set */\n    PSA_PBKDF2_STATE_OUTPUT            /* output has been started */\n} psa_pbkdf2_key_derivation_state_t;\n\ntypedef struct {\n    psa_pbkdf2_key_derivation_state_t MBEDTLS_PRIVATE(state);\n    uint64_t MBEDTLS_PRIVATE(input_cost);\n    uint8_t *MBEDTLS_PRIVATE(salt);\n    size_t MBEDTLS_PRIVATE(salt_length);\n    uint8_t MBEDTLS_PRIVATE(password)[PSA_HMAC_MAX_HASH_BLOCK_SIZE];\n    size_t MBEDTLS_PRIVATE(password_length);\n    uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE];\n    uint8_t MBEDTLS_PRIVATE(bytes_used);\n    uint32_t MBEDTLS_PRIVATE(block_number);\n} psa_pbkdf2_key_derivation_t;\n#endif /* PSA_HAVE_SOFT_PBKDF2 */\n\n#endif /* PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_builtin_primitives.h",
    "content": "/*\n *  Context structure declaration of the Mbed TLS software-based PSA drivers\n *  called through the PSA Crypto driver dispatch layer.\n *  This file contains the context structures of those algorithms which do not\n *  rely on other algorithms, i.e. are 'primitive' algorithms.\n *\n * \\note This file may not be included directly. Applications must\n * include psa/crypto.h.\n *\n * \\note This header and its content are not part of the Mbed TLS API and\n * applications must not depend on it. Its main purpose is to define the\n * multi-part state objects of the Mbed TLS software-based PSA drivers. The\n * definitions of these objects are then used by crypto_struct.h to define the\n * implementation-defined types of PSA multi-part state objects.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_BUILTIN_PRIMITIVES_H\n#define PSA_CRYPTO_BUILTIN_PRIMITIVES_H\n#include \"mbedtls/private_access.h\"\n\n#include <psa/crypto_driver_common.h>\n\n/*\n * Hash multi-part operation definitions.\n */\n\n#include \"mbedtls/md5.h\"\n#include \"mbedtls/ripemd160.h\"\n#include \"mbedtls/sha1.h\"\n#include \"mbedtls/sha256.h\"\n#include \"mbedtls/sha512.h\"\n#include \"mbedtls/sha3.h\"\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)\n#define MBEDTLS_PSA_BUILTIN_HASH\n#endif\n\ntypedef struct {\n    psa_algorithm_t MBEDTLS_PRIVATE(alg);\n    union {\n        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)\n        mbedtls_md5_context md5;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)\n        mbedtls_ripemd160_context ripemd160;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)\n        mbedtls_sha1_context sha1;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \\\n        defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)\n        mbedtls_sha256_context sha256;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) || \\\n        defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)\n        mbedtls_sha512_context sha512;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \\\n        defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \\\n        defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \\\n        defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)\n        mbedtls_sha3_context sha3;\n#endif\n    } MBEDTLS_PRIVATE(ctx);\n} mbedtls_psa_hash_operation_t;\n\n#define MBEDTLS_PSA_HASH_OPERATION_INIT { 0, { 0 } }\n\n/*\n * Cipher multi-part operation definitions.\n */\n\n#include \"mbedtls/cipher.h\"\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)\n#define MBEDTLS_PSA_BUILTIN_CIPHER  1\n#endif\n\ntypedef struct {\n    /* Context structure for the Mbed TLS cipher implementation. */\n    psa_algorithm_t MBEDTLS_PRIVATE(alg);\n    uint8_t MBEDTLS_PRIVATE(iv_length);\n    uint8_t MBEDTLS_PRIVATE(block_length);\n    union {\n        unsigned int MBEDTLS_PRIVATE(dummy);\n        mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher);\n    } MBEDTLS_PRIVATE(ctx);\n} mbedtls_psa_cipher_operation_t;\n\n#define MBEDTLS_PSA_CIPHER_OPERATION_INIT { 0, 0, 0, { 0 } }\n\n#endif /* PSA_CRYPTO_BUILTIN_PRIMITIVES_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_compat.h",
    "content": "/**\n * \\file psa/crypto_compat.h\n *\n * \\brief PSA cryptography module: Backward compatibility aliases\n *\n * This header declares alternative names for macro and functions.\n * New application code should not use these names.\n * These names may be removed in a future version of Mbed TLS.\n *\n * \\note This file may not be included directly. Applications must\n * include psa/crypto.h.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_COMPAT_H\n#define PSA_CRYPTO_COMPAT_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * To support both openless APIs and psa_open_key() temporarily, define\n * psa_key_handle_t to be equal to mbedtls_svc_key_id_t. Do not mark the\n * type and its utility macros and functions deprecated yet. This will be done\n * in a subsequent phase.\n */\ntypedef mbedtls_svc_key_id_t psa_key_handle_t;\n\n#define PSA_KEY_HANDLE_INIT MBEDTLS_SVC_KEY_ID_INIT\n\n/** Check whether a handle is null.\n *\n * \\param handle  Handle\n *\n * \\return Non-zero if the handle is null, zero otherwise.\n */\nstatic inline int psa_key_handle_is_null(psa_key_handle_t handle)\n{\n    return mbedtls_svc_key_id_is_null(handle);\n}\n\n/** Open a handle to an existing persistent key.\n *\n * Open a handle to a persistent key. A key is persistent if it was created\n * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key\n * always has a nonzero key identifier, set with psa_set_key_id() when\n * creating the key. Implementations may provide additional pre-provisioned\n * keys that can be opened with psa_open_key(). Such keys have an application\n * key identifier in the vendor range, as documented in the description of\n * #psa_key_id_t.\n *\n * The application must eventually close the handle with psa_close_key() or\n * psa_destroy_key() to release associated resources. If the application dies\n * without calling one of these functions, the implementation should perform\n * the equivalent of a call to psa_close_key().\n *\n * Some implementations permit an application to open the same key multiple\n * times. If this is successful, each call to psa_open_key() will return a\n * different key handle.\n *\n * \\note This API is not part of the PSA Cryptography API Release 1.0.0\n * specification. It was defined in the 1.0 Beta 3 version of the\n * specification but was removed in the 1.0.0 released version. This API is\n * kept for the time being to not break applications relying on it. It is not\n * deprecated yet but will be in the near future.\n *\n * \\note Applications that rely on opening a key multiple times will not be\n * portable to implementations that only permit a single key handle to be\n * opened. See also :ref:\\`key-handles\\`.\n *\n *\n * \\param key           The persistent identifier of the key.\n * \\param[out] handle   On success, a handle to the key.\n *\n * \\retval #PSA_SUCCESS\n *         Success. The application can now use the value of `*handle`\n *         to access the key.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY\n *         The implementation does not have sufficient resources to open the\n *         key. This can be due to reaching an implementation limit on the\n *         number of open keys, the number of open key handles, or available\n *         memory.\n * \\retval #PSA_ERROR_DOES_NOT_EXIST\n *         There is no persistent key with key identifier \\p key.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p key is not a valid persistent key identifier.\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The specified key exists, but the application does not have the\n *         permission to access it. Note that this specification does not\n *         define any way to create such a key, but it may be possible\n *         through implementation-specific means.\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_open_key(mbedtls_svc_key_id_t key,\n                          psa_key_handle_t *handle);\n\n/** Close a key handle.\n *\n * If the handle designates a volatile key, this will destroy the key material\n * and free all associated resources, just like psa_destroy_key().\n *\n * If this is the last open handle to a persistent key, then closing the handle\n * will free all resources associated with the key in volatile memory. The key\n * data in persistent storage is not affected and can be opened again later\n * with a call to psa_open_key().\n *\n * Closing the key handle makes the handle invalid, and the key handle\n * must not be used again by the application.\n *\n * \\note This API is not part of the PSA Cryptography API Release 1.0.0\n * specification. It was defined in the 1.0 Beta 3 version of the\n * specification but was removed in the 1.0.0 released version. This API is\n * kept for the time being to not break applications relying on it. It is not\n * deprecated yet but will be in the near future.\n *\n * \\note If the key handle was used to set up an active\n * :ref:\\`multipart operation <multipart-operations>\\`, then closing the\n * key handle can cause the multipart operation to fail. Applications should\n * maintain the key handle until after the multipart operation has finished.\n *\n * \\param handle        The key handle to close.\n *                      If this is \\c 0, do nothing and return \\c PSA_SUCCESS.\n *\n * \\retval #PSA_SUCCESS\n *         \\p handle was a valid handle or \\c 0. It is now closed.\n * \\retval #PSA_ERROR_INVALID_HANDLE\n *         \\p handle is not a valid handle nor \\c 0.\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_close_key(psa_key_handle_t handle);\n\n/** \\addtogroup attributes\n * @{\n */\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n/** Custom Diffie-Hellman group.\n *\n * Mbed TLS does not support custom DH groups.\n *\n * \\deprecated This value is not useful, so this macro will be removed in\n *             a future version of the library.\n */\n#define PSA_DH_FAMILY_CUSTOM                                            \\\n    ((psa_dh_family_t) MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(0x7e))\n\n/**\n * \\brief Set domain parameters for a key.\n *\n * \\deprecated  Mbed TLS no longer supports any domain parameters.\n *              This function only does the equivalent of\n *              psa_set_key_type() and will be removed in a future version\n *              of the library.\n *\n * \\param[in,out] attributes    Attribute structure where \\p type will be set.\n * \\param type                  Key type (a \\c PSA_KEY_TYPE_XXX value).\n * \\param[in] data              Ignored.\n * \\param data_length           Must be 0.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n */\nstatic inline psa_status_t MBEDTLS_DEPRECATED psa_set_key_domain_parameters(\n    psa_key_attributes_t *attributes,\n    psa_key_type_t type, const uint8_t *data, size_t data_length)\n{\n    (void) data;\n    if (data_length != 0) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n    psa_set_key_type(attributes, type);\n    return PSA_SUCCESS;\n}\n\n/**\n * \\brief Get domain parameters for a key.\n *\n * \\deprecated  Mbed TLS no longer supports any domain parameters.\n *              This function alwaya has an empty output and will be\n *              removed in a future version of the library.\n\n * \\param[in] attributes        Ignored.\n * \\param[out] data             Ignored.\n * \\param data_size             Ignored.\n * \\param[out] data_length      Set to 0.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n */\nstatic inline psa_status_t MBEDTLS_DEPRECATED psa_get_key_domain_parameters(\n    const psa_key_attributes_t *attributes,\n    uint8_t *data, size_t data_size, size_t *data_length)\n{\n    (void) attributes;\n    (void) data;\n    (void) data_size;\n    *data_length = 0;\n    return PSA_SUCCESS;\n}\n\n/** Safe output buffer size for psa_get_key_domain_parameters().\n *\n */\n#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits)      \\\n    MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(1u)\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n\n/**@}*/\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* PSA_CRYPTO_COMPAT_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_config.h",
    "content": "/**\n * \\file psa/crypto_config.h\n * \\brief PSA crypto configuration options (set of defines)\n *\n */\n#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)\n/**\n * When #MBEDTLS_PSA_CRYPTO_CONFIG is enabled in mbedtls_config.h,\n * this file determines which cryptographic mechanisms are enabled\n * through the PSA Cryptography API (\\c psa_xxx() functions).\n *\n * To enable a cryptographic mechanism, uncomment the definition of\n * the corresponding \\c PSA_WANT_xxx preprocessor symbol.\n * To disable a cryptographic mechanism, comment out the definition of\n * the corresponding \\c PSA_WANT_xxx preprocessor symbol.\n * The names of cryptographic mechanisms correspond to values\n * defined in psa/crypto_values.h, with the prefix \\c PSA_WANT_ instead\n * of \\c PSA_.\n *\n * Note that many cryptographic mechanisms involve two symbols: one for\n * the key type (\\c PSA_WANT_KEY_TYPE_xxx) and one for the algorithm\n * (\\c PSA_WANT_ALG_xxx). Mechanisms with additional parameters may involve\n * additional symbols.\n */\n#else\n/**\n * When \\c MBEDTLS_PSA_CRYPTO_CONFIG is disabled in mbedtls_config.h,\n * this file is not used, and cryptographic mechanisms are supported\n * through the PSA API if and only if they are supported through the\n * mbedtls_xxx API.\n */\n#endif\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_CONFIG_H\n#define PSA_CRYPTO_CONFIG_H\n\n#define PSA_WANT_ALG_CBC_NO_PADDING             1\n#define PSA_WANT_ALG_CBC_PKCS7                  1\n#define PSA_WANT_ALG_CCM                        1\n#define PSA_WANT_ALG_CCM_STAR_NO_TAG            1\n#define PSA_WANT_ALG_CMAC                       1\n#define PSA_WANT_ALG_CFB                        1\n#define PSA_WANT_ALG_CHACHA20_POLY1305          1\n#define PSA_WANT_ALG_CTR                        1\n#define PSA_WANT_ALG_DETERMINISTIC_ECDSA        1\n#define PSA_WANT_ALG_ECB_NO_PADDING             1\n#define PSA_WANT_ALG_ECDH                       1\n#define PSA_WANT_ALG_FFDH                       1\n#define PSA_WANT_ALG_ECDSA                      1\n#define PSA_WANT_ALG_JPAKE                      1\n#define PSA_WANT_ALG_GCM                        1\n#define PSA_WANT_ALG_HKDF                       1\n#define PSA_WANT_ALG_HKDF_EXTRACT               1\n#define PSA_WANT_ALG_HKDF_EXPAND                1\n#define PSA_WANT_ALG_HMAC                       1\n#define PSA_WANT_ALG_MD5                        1\n#define PSA_WANT_ALG_OFB                        1\n#define PSA_WANT_ALG_PBKDF2_HMAC                1\n#define PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128    1\n#define PSA_WANT_ALG_RIPEMD160                  1\n#define PSA_WANT_ALG_RSA_OAEP                   1\n#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT         1\n#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN          1\n#define PSA_WANT_ALG_RSA_PSS                    1\n#define PSA_WANT_ALG_SHA_1                      1\n#define PSA_WANT_ALG_SHA_224                    1\n#define PSA_WANT_ALG_SHA_256                    1\n#define PSA_WANT_ALG_SHA_384                    1\n#define PSA_WANT_ALG_SHA_512                    1\n#define PSA_WANT_ALG_SHA3_224                   1\n#define PSA_WANT_ALG_SHA3_256                   1\n#define PSA_WANT_ALG_SHA3_384                   1\n#define PSA_WANT_ALG_SHA3_512                   1\n#define PSA_WANT_ALG_STREAM_CIPHER              1\n#define PSA_WANT_ALG_TLS12_PRF                  1\n#define PSA_WANT_ALG_TLS12_PSK_TO_MS            1\n#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS       1\n\n#define PSA_WANT_ECC_BRAINPOOL_P_R1_256         1\n#define PSA_WANT_ECC_BRAINPOOL_P_R1_384         1\n#define PSA_WANT_ECC_BRAINPOOL_P_R1_512         1\n#define PSA_WANT_ECC_MONTGOMERY_255             1\n#define PSA_WANT_ECC_MONTGOMERY_448             1\n#define PSA_WANT_ECC_SECP_K1_192                1\n#define PSA_WANT_ECC_SECP_K1_256                1\n#define PSA_WANT_ECC_SECP_R1_192                1\n#define PSA_WANT_ECC_SECP_R1_224                1\n/* For secp256r1, consider enabling #MBEDTLS_PSA_P256M_DRIVER_ENABLED\n * (see the description in mbedtls/mbedtls_config.h for details). */\n#define PSA_WANT_ECC_SECP_R1_256                1\n#define PSA_WANT_ECC_SECP_R1_384                1\n#define PSA_WANT_ECC_SECP_R1_521                1\n\n#define PSA_WANT_DH_RFC7919_2048                1\n#define PSA_WANT_DH_RFC7919_3072                1\n#define PSA_WANT_DH_RFC7919_4096                1\n#define PSA_WANT_DH_RFC7919_6144                1\n#define PSA_WANT_DH_RFC7919_8192                1\n\n#define PSA_WANT_KEY_TYPE_DERIVE                1\n#define PSA_WANT_KEY_TYPE_PASSWORD              1\n#define PSA_WANT_KEY_TYPE_PASSWORD_HASH         1\n#define PSA_WANT_KEY_TYPE_HMAC                  1\n#define PSA_WANT_KEY_TYPE_AES                   1\n#define PSA_WANT_KEY_TYPE_ARIA                  1\n#define PSA_WANT_KEY_TYPE_CAMELLIA              1\n#define PSA_WANT_KEY_TYPE_CHACHA20              1\n#define PSA_WANT_KEY_TYPE_DES                   1\n//#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR          1 /* Deprecated */\n#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY        1\n#define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY         1\n#define PSA_WANT_KEY_TYPE_RAW_DATA              1\n//#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR          1 /* Deprecated */\n#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY        1\n\n/*\n * The following symbols extend and deprecate the legacy\n * PSA_WANT_KEY_TYPE_xxx_KEY_PAIR ones. They include the usage of that key in\n * the name's suffix. \"_USE\" is the most generic and it can be used to describe\n * a generic suport, whereas other ones add more features on top of that and\n * they are more specific.\n */\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC      1\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT   1\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT   1\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE   1\n\n#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC      1\n#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT   1\n#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT   1\n#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1\n//#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE   1 /* Not supported */\n\n#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC       1\n#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT    1\n#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT    1\n#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE  1\n//#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE    1 /* Not supported */\n\n#endif /* PSA_CRYPTO_CONFIG_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_driver_common.h",
    "content": "/**\n * \\file psa/crypto_driver_common.h\n * \\brief Definitions for all PSA crypto drivers\n *\n * This file contains common definitions shared by all PSA crypto drivers.\n * Do not include it directly: instead, include the header file(s) for\n * the type(s) of driver that you are implementing. For example, if\n * you are writing a dynamically registered driver for a secure element,\n * include `psa/crypto_se_driver.h`.\n *\n * This file is part of the PSA Crypto Driver Model, containing functions for\n * driver developers to implement to enable hardware to be called in a\n * standardized way by a PSA Cryptographic API implementation. The functions\n * comprising the driver model, which driver authors implement, are not\n * intended to be called by application developers.\n */\n\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef PSA_CRYPTO_DRIVER_COMMON_H\n#define PSA_CRYPTO_DRIVER_COMMON_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n/* Include type definitions (psa_status_t, psa_algorithm_t,\n * psa_key_type_t, etc.) and macros to build and analyze values\n * of these types. */\n#include \"crypto_types.h\"\n#include \"crypto_values.h\"\n/* Include size definitions which are used to size some arrays in operation\n * structures. */\n#include <psa/crypto_sizes.h>\n\n/** For encrypt-decrypt functions, whether the operation is an encryption\n * or a decryption. */\ntypedef enum {\n    PSA_CRYPTO_DRIVER_DECRYPT,\n    PSA_CRYPTO_DRIVER_ENCRYPT\n} psa_encrypt_or_decrypt_t;\n\n#endif /* PSA_CRYPTO_DRIVER_COMMON_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_driver_contexts_composites.h",
    "content": "/*\n *  Declaration of context structures for use with the PSA driver wrapper\n *  interface. This file contains the context structures for 'composite'\n *  operations, i.e. those operations which need to make use of other operations\n *  from the primitives (crypto_driver_contexts_primitives.h)\n *\n *  Warning: This file will be auto-generated in the future.\n *\n * \\note This file may not be included directly. Applications must\n * include psa/crypto.h.\n *\n * \\note This header and its content are not part of the Mbed TLS API and\n * applications must not depend on it. Its main purpose is to define the\n * multi-part state objects of the PSA drivers included in the cryptographic\n * library. The definitions of these objects are then used by crypto_struct.h\n * to define the implementation-defined types of PSA multi-part state objects.\n */\n/*  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H\n#define PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H\n\n#include \"psa/crypto_driver_common.h\"\n\n/* Include the context structure definitions for the Mbed TLS software drivers */\n#include \"psa/crypto_builtin_composites.h\"\n\n/* Include the context structure definitions for those drivers that were\n * declared during the autogeneration process. */\n\n#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)\n#include <libtestdriver1/include/psa/crypto.h>\n#endif\n\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \\\n    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)\ntypedef libtestdriver1_mbedtls_psa_mac_operation_t\n    mbedtls_transparent_test_driver_mac_operation_t;\ntypedef libtestdriver1_mbedtls_psa_mac_operation_t\n    mbedtls_opaque_test_driver_mac_operation_t;\n\n#define MBEDTLS_TRANSPARENT_TEST_DRIVER_MAC_OPERATION_INIT \\\n    LIBTESTDRIVER1_MBEDTLS_PSA_MAC_OPERATION_INIT\n#define MBEDTLS_OPAQUE_TEST_DRIVER_MAC_OPERATION_INIT \\\n    LIBTESTDRIVER1_MBEDTLS_PSA_MAC_OPERATION_INIT\n\n#else\ntypedef mbedtls_psa_mac_operation_t\n    mbedtls_transparent_test_driver_mac_operation_t;\ntypedef mbedtls_psa_mac_operation_t\n    mbedtls_opaque_test_driver_mac_operation_t;\n\n#define MBEDTLS_TRANSPARENT_TEST_DRIVER_MAC_OPERATION_INIT \\\n    MBEDTLS_PSA_MAC_OPERATION_INIT\n#define MBEDTLS_OPAQUE_TEST_DRIVER_MAC_OPERATION_INIT \\\n    MBEDTLS_PSA_MAC_OPERATION_INIT\n\n#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC */\n\n#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \\\n    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD)\ntypedef libtestdriver1_mbedtls_psa_aead_operation_t\n    mbedtls_transparent_test_driver_aead_operation_t;\n\n#define MBEDTLS_TRANSPARENT_TEST_DRIVER_AEAD_OPERATION_INIT \\\n    LIBTESTDRIVER1_MBEDTLS_PSA_AEAD_OPERATION_INIT\n#else\ntypedef mbedtls_psa_aead_operation_t\n    mbedtls_transparent_test_driver_aead_operation_t;\n\n#define MBEDTLS_TRANSPARENT_TEST_DRIVER_AEAD_OPERATION_INIT \\\n    MBEDTLS_PSA_AEAD_OPERATION_INIT\n\n#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD */\n\n#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \\\n    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_PAKE)\n\ntypedef libtestdriver1_mbedtls_psa_pake_operation_t\n    mbedtls_transparent_test_driver_pake_operation_t;\ntypedef libtestdriver1_mbedtls_psa_pake_operation_t\n    mbedtls_opaque_test_driver_pake_operation_t;\n\n#define MBEDTLS_TRANSPARENT_TEST_DRIVER_PAKE_OPERATION_INIT \\\n    LIBTESTDRIVER1_MBEDTLS_PSA_PAKE_OPERATION_INIT\n#define MBEDTLS_OPAQUE_TEST_DRIVER_PAKE_OPERATION_INIT \\\n    LIBTESTDRIVER1_MBEDTLS_PSA_PAKE_OPERATION_INIT\n\n#else\ntypedef mbedtls_psa_pake_operation_t\n    mbedtls_transparent_test_driver_pake_operation_t;\ntypedef mbedtls_psa_pake_operation_t\n    mbedtls_opaque_test_driver_pake_operation_t;\n\n#define MBEDTLS_TRANSPARENT_TEST_DRIVER_PAKE_OPERATION_INIT \\\n    MBEDTLS_PSA_PAKE_OPERATION_INIT\n#define MBEDTLS_OPAQUE_TEST_DRIVER_PAKE_OPERATION_INIT \\\n    MBEDTLS_PSA_PAKE_OPERATION_INIT\n\n#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_PAKE */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n\n/* Define the context to be used for an operation that is executed through the\n * PSA Driver wrapper layer as the union of all possible driver's contexts.\n *\n * The union members are the driver's context structures, and the member names\n * are formatted as `'drivername'_ctx`. This allows for procedural generation\n * of both this file and the content of psa_crypto_driver_wrappers.h */\n\ntypedef union {\n    unsigned dummy; /* Make sure this union is always non-empty */\n    mbedtls_psa_mac_operation_t mbedtls_ctx;\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n    mbedtls_transparent_test_driver_mac_operation_t transparent_test_driver_ctx;\n    mbedtls_opaque_test_driver_mac_operation_t opaque_test_driver_ctx;\n#endif\n} psa_driver_mac_context_t;\n\ntypedef union {\n    unsigned dummy; /* Make sure this union is always non-empty */\n    mbedtls_psa_aead_operation_t mbedtls_ctx;\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n    mbedtls_transparent_test_driver_aead_operation_t transparent_test_driver_ctx;\n#endif\n} psa_driver_aead_context_t;\n\ntypedef union {\n    unsigned dummy; /* Make sure this union is always non-empty */\n    mbedtls_psa_sign_hash_interruptible_operation_t mbedtls_ctx;\n} psa_driver_sign_hash_interruptible_context_t;\n\ntypedef union {\n    unsigned dummy; /* Make sure this union is always non-empty */\n    mbedtls_psa_verify_hash_interruptible_operation_t mbedtls_ctx;\n} psa_driver_verify_hash_interruptible_context_t;\n\ntypedef union {\n    unsigned dummy; /* Make sure this union is always non-empty */\n    mbedtls_psa_pake_operation_t mbedtls_ctx;\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n    mbedtls_transparent_test_driver_pake_operation_t transparent_test_driver_ctx;\n    mbedtls_opaque_test_driver_pake_operation_t opaque_test_driver_ctx;\n#endif\n} psa_driver_pake_context_t;\n\n#endif /* PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H */\n/* End of automatically generated file. */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_driver_contexts_key_derivation.h",
    "content": "/*\n *  Declaration of context structures for use with the PSA driver wrapper\n *  interface. This file contains the context structures for key derivation\n *  operations.\n *\n *  Warning: This file will be auto-generated in the future.\n *\n * \\note This file may not be included directly. Applications must\n * include psa/crypto.h.\n *\n * \\note This header and its content are not part of the Mbed TLS API and\n * applications must not depend on it. Its main purpose is to define the\n * multi-part state objects of the PSA drivers included in the cryptographic\n * library. The definitions of these objects are then used by crypto_struct.h\n * to define the implementation-defined types of PSA multi-part state objects.\n */\n/*  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H\n#define PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H\n\n#include \"psa/crypto_driver_common.h\"\n\n/* Include the context structure definitions for the Mbed TLS software drivers */\n#include \"psa/crypto_builtin_key_derivation.h\"\n\n/* Include the context structure definitions for those drivers that were\n * declared during the autogeneration process. */\n\ntypedef union {\n    unsigned dummy; /* Make sure this union is always non-empty */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)\n    psa_hkdf_key_derivation_t MBEDTLS_PRIVATE(hkdf);\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)\n    psa_tls12_prf_key_derivation_t MBEDTLS_PRIVATE(tls12_prf);\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)\n    psa_tls12_ecjpake_to_pms_t MBEDTLS_PRIVATE(tls12_ecjpake_to_pms);\n#endif\n#if defined(PSA_HAVE_SOFT_PBKDF2)\n    psa_pbkdf2_key_derivation_t MBEDTLS_PRIVATE(pbkdf2);\n#endif\n} psa_driver_key_derivation_context_t;\n\n#endif /* PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H */\n/* End of automatically generated file. */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_driver_contexts_primitives.h",
    "content": "/*\n *  Declaration of context structures for use with the PSA driver wrapper\n *  interface. This file contains the context structures for 'primitive'\n *  operations, i.e. those operations which do not rely on other contexts.\n *\n *  Warning: This file will be auto-generated in the future.\n *\n * \\note This file may not be included directly. Applications must\n * include psa/crypto.h.\n *\n * \\note This header and its content are not part of the Mbed TLS API and\n * applications must not depend on it. Its main purpose is to define the\n * multi-part state objects of the PSA drivers included in the cryptographic\n * library. The definitions of these objects are then used by crypto_struct.h\n * to define the implementation-defined types of PSA multi-part state objects.\n */\n/*  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H\n#define PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H\n\n#include \"psa/crypto_driver_common.h\"\n\n/* Include the context structure definitions for the Mbed TLS software drivers */\n#include \"psa/crypto_builtin_primitives.h\"\n\n/* Include the context structure definitions for those drivers that were\n * declared during the autogeneration process. */\n\n#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)\n#include <libtestdriver1/include/psa/crypto.h>\n#endif\n\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n\n#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \\\n    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)\ntypedef libtestdriver1_mbedtls_psa_cipher_operation_t\n    mbedtls_transparent_test_driver_cipher_operation_t;\n\n#define MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT \\\n    LIBTESTDRIVER1_MBEDTLS_PSA_CIPHER_OPERATION_INIT\n#else\ntypedef mbedtls_psa_cipher_operation_t\n    mbedtls_transparent_test_driver_cipher_operation_t;\n\n#define MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT \\\n    MBEDTLS_PSA_CIPHER_OPERATION_INIT\n#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 &&\n          LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER */\n\n#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \\\n    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)\ntypedef libtestdriver1_mbedtls_psa_hash_operation_t\n    mbedtls_transparent_test_driver_hash_operation_t;\n\n#define MBEDTLS_TRANSPARENT_TEST_DRIVER_HASH_OPERATION_INIT \\\n    LIBTESTDRIVER1_MBEDTLS_PSA_HASH_OPERATION_INIT\n#else\ntypedef mbedtls_psa_hash_operation_t\n    mbedtls_transparent_test_driver_hash_operation_t;\n\n#define MBEDTLS_TRANSPARENT_TEST_DRIVER_HASH_OPERATION_INIT \\\n    MBEDTLS_PSA_HASH_OPERATION_INIT\n#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 &&\n          LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH */\n\ntypedef struct {\n    unsigned int initialised : 1;\n    mbedtls_transparent_test_driver_cipher_operation_t ctx;\n} mbedtls_opaque_test_driver_cipher_operation_t;\n\n#define MBEDTLS_OPAQUE_TEST_DRIVER_CIPHER_OPERATION_INIT \\\n    { 0, MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT }\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n\n/* Define the context to be used for an operation that is executed through the\n * PSA Driver wrapper layer as the union of all possible driver's contexts.\n *\n * The union members are the driver's context structures, and the member names\n * are formatted as `'drivername'_ctx`. This allows for procedural generation\n * of both this file and the content of psa_crypto_driver_wrappers.h */\n\ntypedef union {\n    unsigned dummy; /* Make sure this union is always non-empty */\n    mbedtls_psa_hash_operation_t mbedtls_ctx;\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n    mbedtls_transparent_test_driver_hash_operation_t test_driver_ctx;\n#endif\n} psa_driver_hash_context_t;\n\ntypedef union {\n    unsigned dummy; /* Make sure this union is always non-empty */\n    mbedtls_psa_cipher_operation_t mbedtls_ctx;\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n    mbedtls_transparent_test_driver_cipher_operation_t transparent_test_driver_ctx;\n    mbedtls_opaque_test_driver_cipher_operation_t opaque_test_driver_ctx;\n#endif\n} psa_driver_cipher_context_t;\n\n#endif /* PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H */\n/* End of automatically generated file. */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_extra.h",
    "content": "/**\n * \\file psa/crypto_extra.h\n *\n * \\brief PSA cryptography module: Mbed TLS vendor extensions\n *\n * \\note This file may not be included directly. Applications must\n * include psa/crypto.h.\n *\n * This file is reserved for vendor-specific definitions.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_EXTRA_H\n#define PSA_CRYPTO_EXTRA_H\n#include \"mbedtls/private_access.h\"\n\n#include \"crypto_types.h\"\n#include \"crypto_compat.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* UID for secure storage seed */\n#define PSA_CRYPTO_ITS_RANDOM_SEED_UID 0xFFFFFF52\n\n/* See mbedtls_config.h for definition */\n#if !defined(MBEDTLS_PSA_KEY_SLOT_COUNT)\n#define MBEDTLS_PSA_KEY_SLOT_COUNT 32\n#endif\n\n/* If the size of static key slots is not explicitly defined by the user, then\n * set it to the maximum between PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE and\n * PSA_CIPHER_MAX_KEY_LENGTH.\n * See mbedtls_config.h for the definition. */\n#if !defined(MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE)\n#define MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE  \\\n    ((PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE > PSA_CIPHER_MAX_KEY_LENGTH) ? \\\n     PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE : PSA_CIPHER_MAX_KEY_LENGTH)\n#endif /* !MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE*/\n\n/** \\addtogroup attributes\n * @{\n */\n\n/** \\brief Declare the enrollment algorithm for a key.\n *\n * An operation on a key may indifferently use the algorithm set with\n * psa_set_key_algorithm() or with this function.\n *\n * \\param[out] attributes       The attribute structure to write to.\n * \\param alg2                  A second algorithm that the key may be used\n *                              for, in addition to the algorithm set with\n *                              psa_set_key_algorithm().\n *\n * \\warning Setting an enrollment algorithm is not recommended, because\n *          using the same key with different algorithms can allow some\n *          attacks based on arithmetic relations between different\n *          computations made with the same key, or can escalate harmless\n *          side channels into exploitable ones. Use this function only\n *          if it is necessary to support a protocol for which it has been\n *          verified that the usage of the key with multiple algorithms\n *          is safe.\n */\nstatic inline void psa_set_key_enrollment_algorithm(\n    psa_key_attributes_t *attributes,\n    psa_algorithm_t alg2)\n{\n    attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2) = alg2;\n}\n\n/** Retrieve the enrollment algorithm policy from key attributes.\n *\n * \\param[in] attributes        The key attribute structure to query.\n *\n * \\return The enrollment algorithm stored in the attribute structure.\n */\nstatic inline psa_algorithm_t psa_get_key_enrollment_algorithm(\n    const psa_key_attributes_t *attributes)\n{\n    return attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2);\n}\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n\n/** Retrieve the slot number where a key is stored.\n *\n * A slot number is only defined for keys that are stored in a secure\n * element.\n *\n * This information is only useful if the secure element is not entirely\n * managed through the PSA Cryptography API. It is up to the secure\n * element driver to decide how PSA slot numbers map to any other interface\n * that the secure element may have.\n *\n * \\param[in] attributes        The key attribute structure to query.\n * \\param[out] slot_number      On success, the slot number containing the key.\n *\n * \\retval #PSA_SUCCESS\n *         The key is located in a secure element, and \\p *slot_number\n *         indicates the slot number that contains it.\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The caller is not permitted to query the slot number.\n *         Mbed TLS currently does not return this error.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The key is not located in a secure element.\n */\npsa_status_t psa_get_key_slot_number(\n    const psa_key_attributes_t *attributes,\n    psa_key_slot_number_t *slot_number);\n\n/** Choose the slot number where a key is stored.\n *\n * This function declares a slot number in the specified attribute\n * structure.\n *\n * A slot number is only meaningful for keys that are stored in a secure\n * element. It is up to the secure element driver to decide how PSA slot\n * numbers map to any other interface that the secure element may have.\n *\n * \\note Setting a slot number in key attributes for a key creation can\n *       cause the following errors when creating the key:\n *       - #PSA_ERROR_NOT_SUPPORTED if the selected secure element does\n *         not support choosing a specific slot number.\n *       - #PSA_ERROR_NOT_PERMITTED if the caller is not permitted to\n *         choose slot numbers in general or to choose this specific slot.\n *       - #PSA_ERROR_INVALID_ARGUMENT if the chosen slot number is not\n *         valid in general or not valid for this specific key.\n *       - #PSA_ERROR_ALREADY_EXISTS if there is already a key in the\n *         selected slot.\n *\n * \\param[out] attributes       The attribute structure to write to.\n * \\param slot_number           The slot number to set.\n */\nstatic inline void psa_set_key_slot_number(\n    psa_key_attributes_t *attributes,\n    psa_key_slot_number_t slot_number)\n{\n    attributes->MBEDTLS_PRIVATE(has_slot_number) = 1;\n    attributes->MBEDTLS_PRIVATE(slot_number) = slot_number;\n}\n\n/** Remove the slot number attribute from a key attribute structure.\n *\n * This function undoes the action of psa_set_key_slot_number().\n *\n * \\param[out] attributes       The attribute structure to write to.\n */\nstatic inline void psa_clear_key_slot_number(\n    psa_key_attributes_t *attributes)\n{\n    attributes->MBEDTLS_PRIVATE(has_slot_number) = 0;\n}\n\n/** Register a key that is already present in a secure element.\n *\n * The key must be located in a secure element designated by the\n * lifetime field in \\p attributes, in the slot set with\n * psa_set_key_slot_number() in the attribute structure.\n * This function makes the key available through the key identifier\n * specified in \\p attributes.\n *\n * \\param[in] attributes        The attributes of the existing key.\n *                              - The lifetime must be a persistent lifetime\n *                                in a secure element. Volatile lifetimes are\n *                                not currently supported.\n *                              - The key identifier must be in the valid\n *                                range for persistent keys.\n *                              - The key type and size must be specified and\n *                                must be consistent with the key material\n *                                in the secure element.\n *\n * \\retval #PSA_SUCCESS\n *         The key was successfully registered.\n *         Note that depending on the design of the driver, this may or may\n *         not guarantee that a key actually exists in the designated slot\n *         and is compatible with the specified attributes.\n * \\retval #PSA_ERROR_ALREADY_EXISTS\n *         There is already a key with the identifier specified in\n *         \\p attributes.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         The secure element driver for the specified lifetime does not\n *         support registering a key.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The identifier in \\p attributes is invalid, namely the identifier is\n *         not in the user range, or\n *         \\p attributes specifies a lifetime which is not located\n *         in a secure element, or no slot number is specified in \\p attributes,\n *         or the specified slot number is not valid.\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The caller is not authorized to register the specified key slot.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t mbedtls_psa_register_se_key(\n    const psa_key_attributes_t *attributes);\n\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n/**@}*/\n\n/**\n * \\brief Library deinitialization.\n *\n * This function clears all data associated with the PSA layer,\n * including the whole key store.\n * This function is not thread safe, it wipes every key slot regardless of\n * state and reader count. It should only be called when no slot is in use.\n *\n * This is an Mbed TLS extension.\n */\nvoid mbedtls_psa_crypto_free(void);\n\n/** \\brief Statistics about\n * resource consumption related to the PSA keystore.\n *\n * \\note The content of this structure is not part of the stable API and ABI\n *       of Mbed TLS and may change arbitrarily from version to version.\n */\ntypedef struct mbedtls_psa_stats_s {\n    /** Number of slots containing key material for a volatile key. */\n    size_t MBEDTLS_PRIVATE(volatile_slots);\n    /** Number of slots containing key material for a key which is in\n     * internal persistent storage. */\n    size_t MBEDTLS_PRIVATE(persistent_slots);\n    /** Number of slots containing a reference to a key in a\n     * secure element. */\n    size_t MBEDTLS_PRIVATE(external_slots);\n    /** Number of slots which are occupied, but do not contain\n     * key material yet. */\n    size_t MBEDTLS_PRIVATE(half_filled_slots);\n    /** Number of slots that contain cache data. */\n    size_t MBEDTLS_PRIVATE(cache_slots);\n    /** Number of slots that are not used for anything. */\n    size_t MBEDTLS_PRIVATE(empty_slots);\n    /** Number of slots that are locked. */\n    size_t MBEDTLS_PRIVATE(locked_slots);\n    /** Largest key id value among open keys in internal persistent storage. */\n    psa_key_id_t MBEDTLS_PRIVATE(max_open_internal_key_id);\n    /** Largest key id value among open keys in secure elements. */\n    psa_key_id_t MBEDTLS_PRIVATE(max_open_external_key_id);\n} mbedtls_psa_stats_t;\n\n/** \\brief Get statistics about\n * resource consumption related to the PSA keystore.\n *\n * \\note When Mbed TLS is built as part of a service, with isolation\n *       between the application and the keystore, the service may or\n *       may not expose this function.\n */\nvoid mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats);\n\n/**\n * \\brief Inject an initial entropy seed for the random generator into\n *        secure storage.\n *\n * This function injects data to be used as a seed for the random generator\n * used by the PSA Crypto implementation. On devices that lack a trusted\n * entropy source (preferably a hardware random number generator),\n * the Mbed PSA Crypto implementation uses this value to seed its\n * random generator.\n *\n * On devices without a trusted entropy source, this function must be\n * called exactly once in the lifetime of the device. On devices with\n * a trusted entropy source, calling this function is optional.\n * In all cases, this function may only be called before calling any\n * other function in the PSA Crypto API, including psa_crypto_init().\n *\n * When this function returns successfully, it populates a file in\n * persistent storage. Once the file has been created, this function\n * can no longer succeed.\n *\n * If any error occurs, this function does not change the system state.\n * You can call this function again after correcting the reason for the\n * error if possible.\n *\n * \\warning This function **can** fail! Callers MUST check the return status.\n *\n * \\warning If you use this function, you should use it as part of a\n *          factory provisioning process. The value of the injected seed\n *          is critical to the security of the device. It must be\n *          *secret*, *unpredictable* and (statistically) *unique per device*.\n *          You should be generate it randomly using a cryptographically\n *          secure random generator seeded from trusted entropy sources.\n *          You should transmit it securely to the device and ensure\n *          that its value is not leaked or stored anywhere beyond the\n *          needs of transmitting it from the point of generation to\n *          the call of this function, and erase all copies of the value\n *          once this function returns.\n *\n * This is an Mbed TLS extension.\n *\n * \\note This function is only available on the following platforms:\n * * If the compile-time option MBEDTLS_PSA_INJECT_ENTROPY is enabled.\n *   Note that you must provide compatible implementations of\n *   mbedtls_nv_seed_read and mbedtls_nv_seed_write.\n * * In a client-server integration of PSA Cryptography, on the client side,\n *   if the server supports this feature.\n * \\param[in] seed          Buffer containing the seed value to inject.\n * \\param[in] seed_size     Size of the \\p seed buffer.\n *                          The size of the seed in bytes must be greater\n *                          or equal to both #MBEDTLS_ENTROPY_BLOCK_SIZE\n *                          and the value of \\c MBEDTLS_ENTROPY_MIN_PLATFORM\n *                          in `library/entropy_poll.h` in the Mbed TLS source\n *                          code.\n *                          It must be less or equal to\n *                          #MBEDTLS_ENTROPY_MAX_SEED_SIZE.\n *\n * \\retval #PSA_SUCCESS\n *         The seed value was injected successfully. The random generator\n *         of the PSA Crypto implementation is now ready for use.\n *         You may now call psa_crypto_init() and use the PSA Crypto\n *         implementation.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p seed_size is out of range.\n * \\retval #PSA_ERROR_STORAGE_FAILURE\n *         There was a failure reading or writing from storage.\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The library has already been initialized. It is no longer\n *         possible to call this function.\n */\npsa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed,\n                                        size_t seed_size);\n\n/** \\addtogroup crypto_types\n * @{\n */\n\n/** DSA public key.\n *\n * The import and export format is the\n * representation of the public key `y = g^x mod p` as a big-endian byte\n * string. The length of the byte string is the length of the base prime `p`\n * in bytes.\n */\n#define PSA_KEY_TYPE_DSA_PUBLIC_KEY                 ((psa_key_type_t) 0x4002)\n\n/** DSA key pair (private and public key).\n *\n * The import and export format is the\n * representation of the private key `x` as a big-endian byte string. The\n * length of the byte string is the private key size in bytes (leading zeroes\n * are not stripped).\n *\n * Deterministic DSA key derivation with psa_generate_derived_key follows\n * FIPS 186-4 &sect;B.1.2: interpret the byte string as integer\n * in big-endian order. Discard it if it is not in the range\n * [0, *N* - 2] where *N* is the boundary of the private key domain\n * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA,\n * or the order of the curve's base point for ECC).\n * Add 1 to the resulting integer and use this as the private key *x*.\n *\n */\n#define PSA_KEY_TYPE_DSA_KEY_PAIR                    ((psa_key_type_t) 0x7002)\n\n/** Whether a key type is a DSA key (pair or public-only). */\n#define PSA_KEY_TYPE_IS_DSA(type)                                       \\\n    (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY)\n\n#define PSA_ALG_DSA_BASE                        ((psa_algorithm_t) 0x06000400)\n/** DSA signature with hashing.\n *\n * This is the signature scheme defined by FIPS 186-4,\n * with a random per-message secret number (*k*).\n *\n * \\param hash_alg      A hash algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_HASH(\\p hash_alg) is true).\n *                      This includes #PSA_ALG_ANY_HASH\n *                      when specifying the algorithm in a usage policy.\n *\n * \\return              The corresponding DSA signature algorithm.\n * \\return              Unspecified if \\p hash_alg is not a supported\n *                      hash algorithm.\n */\n#define PSA_ALG_DSA(hash_alg)                             \\\n    (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))\n#define PSA_ALG_DETERMINISTIC_DSA_BASE          ((psa_algorithm_t) 0x06000500)\n#define PSA_ALG_DSA_DETERMINISTIC_FLAG PSA_ALG_ECDSA_DETERMINISTIC_FLAG\n/** Deterministic DSA signature with hashing.\n *\n * This is the deterministic variant defined by RFC 6979 of\n * the signature scheme defined by FIPS 186-4.\n *\n * \\param hash_alg      A hash algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_HASH(\\p hash_alg) is true).\n *                      This includes #PSA_ALG_ANY_HASH\n *                      when specifying the algorithm in a usage policy.\n *\n * \\return              The corresponding DSA signature algorithm.\n * \\return              Unspecified if \\p hash_alg is not a supported\n *                      hash algorithm.\n */\n#define PSA_ALG_DETERMINISTIC_DSA(hash_alg)                             \\\n    (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))\n#define PSA_ALG_IS_DSA(alg)                                             \\\n    (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) ==  \\\n     PSA_ALG_DSA_BASE)\n#define PSA_ALG_DSA_IS_DETERMINISTIC(alg)               \\\n    (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0)\n#define PSA_ALG_IS_DETERMINISTIC_DSA(alg)                       \\\n    (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg))\n#define PSA_ALG_IS_RANDOMIZED_DSA(alg)                          \\\n    (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg))\n\n\n/* We need to expand the sample definition of this macro from\n * the API definition. */\n#undef PSA_ALG_IS_VENDOR_HASH_AND_SIGN\n#define PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg)    \\\n    PSA_ALG_IS_DSA(alg)\n\n/**@}*/\n\n/** \\addtogroup attributes\n * @{\n */\n\n/** PAKE operation stages. */\n#define PSA_PAKE_OPERATION_STAGE_SETUP 0\n#define PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS 1\n#define PSA_PAKE_OPERATION_STAGE_COMPUTATION 2\n\n/**@}*/\n\n\n/** \\defgroup psa_external_rng External random generator\n * @{\n */\n\n#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)\n/** External random generator function, implemented by the platform.\n *\n * When the compile-time option #MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG is enabled,\n * this function replaces Mbed TLS's entropy and DRBG modules for all\n * random generation triggered via PSA crypto interfaces.\n *\n * \\note This random generator must deliver random numbers with cryptographic\n *       quality and high performance. It must supply unpredictable numbers\n *       with a uniform distribution. The implementation of this function\n *       is responsible for ensuring that the random generator is seeded\n *       with sufficient entropy. If you have a hardware TRNG which is slow\n *       or delivers non-uniform output, declare it as an entropy source\n *       with mbedtls_entropy_add_source() instead of enabling this option.\n *\n * \\param[in,out] context       Pointer to the random generator context.\n *                              This is all-bits-zero on the first call\n *                              and preserved between successive calls.\n * \\param[out] output           Output buffer. On success, this buffer\n *                              contains random data with a uniform\n *                              distribution.\n * \\param output_size           The size of the \\p output buffer in bytes.\n * \\param[out] output_length    On success, set this value to \\p output_size.\n *\n * \\retval #PSA_SUCCESS\n *         Success. The output buffer contains \\p output_size bytes of\n *         cryptographic-quality random data, and \\c *output_length is\n *         set to \\p output_size.\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY\n *         The random generator requires extra entropy and there is no\n *         way to obtain entropy under current environment conditions.\n *         This error should not happen under normal circumstances since\n *         this function is responsible for obtaining as much entropy as\n *         it needs. However implementations of this function may return\n *         #PSA_ERROR_INSUFFICIENT_ENTROPY if there is no way to obtain\n *         entropy without blocking indefinitely.\n * \\retval #PSA_ERROR_HARDWARE_FAILURE\n *         A failure of the random generator hardware that isn't covered\n *         by #PSA_ERROR_INSUFFICIENT_ENTROPY.\n */\npsa_status_t mbedtls_psa_external_get_random(\n    mbedtls_psa_external_random_context_t *context,\n    uint8_t *output, size_t output_size, size_t *output_length);\n#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */\n\n/**@}*/\n\n/** \\defgroup psa_builtin_keys Built-in keys\n * @{\n */\n\n/** The minimum value for a key identifier that is built into the\n * implementation.\n *\n * The range of key identifiers from #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN\n * to #MBEDTLS_PSA_KEY_ID_BUILTIN_MAX within the range from\n * #PSA_KEY_ID_VENDOR_MIN and #PSA_KEY_ID_VENDOR_MAX and must not intersect\n * with any other set of implementation-chosen key identifiers.\n *\n * This value is part of the library's API since changing it would invalidate\n * the values of built-in key identifiers in applications.\n */\n#define MBEDTLS_PSA_KEY_ID_BUILTIN_MIN          ((psa_key_id_t) 0x7fff0000)\n\n/** The maximum value for a key identifier that is built into the\n * implementation.\n *\n * See #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN for more information.\n */\n#define MBEDTLS_PSA_KEY_ID_BUILTIN_MAX          ((psa_key_id_t) 0x7fffefff)\n\n/** A slot number identifying a key in a driver.\n *\n * Values of this type are used to identify built-in keys.\n */\ntypedef uint64_t psa_drv_slot_number_t;\n\n#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)\n/** Test whether a key identifier belongs to the builtin key range.\n *\n * \\param key_id  Key identifier to test.\n *\n * \\retval 1\n *         The key identifier is a builtin key identifier.\n * \\retval 0\n *         The key identifier is not a builtin key identifier.\n */\nstatic inline int psa_key_id_is_builtin(psa_key_id_t key_id)\n{\n    return (key_id >= MBEDTLS_PSA_KEY_ID_BUILTIN_MIN) &&\n           (key_id <= MBEDTLS_PSA_KEY_ID_BUILTIN_MAX);\n}\n\n/** Platform function to obtain the location and slot number of a built-in key.\n *\n * An application-specific implementation of this function must be provided if\n * #MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS is enabled. This would typically be provided\n * as part of a platform's system image.\n *\n * #MBEDTLS_SVC_KEY_ID_GET_KEY_ID(\\p key_id) needs to be in the range from\n * #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN to #MBEDTLS_PSA_KEY_ID_BUILTIN_MAX.\n *\n * In a multi-application configuration\n * (\\c MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER is defined),\n * this function should check that #MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(\\p key_id)\n * is allowed to use the given key.\n *\n * \\param key_id                The key ID for which to retrieve the\n *                              location and slot attributes.\n * \\param[out] lifetime         On success, the lifetime associated with the key\n *                              corresponding to \\p key_id. Lifetime is a\n *                              combination of which driver contains the key,\n *                              and with what persistence level the key is\n *                              intended to be used. If the platform\n *                              implementation does not contain specific\n *                              information about the intended key persistence\n *                              level, the persistence level may be reported as\n *                              #PSA_KEY_PERSISTENCE_DEFAULT.\n * \\param[out] slot_number      On success, the slot number known to the driver\n *                              registered at the lifetime location reported\n *                              through \\p lifetime which corresponds to the\n *                              requested built-in key.\n *\n * \\retval #PSA_SUCCESS\n *         The requested key identifier designates a built-in key.\n *         In a multi-application configuration, the requested owner\n *         is allowed to access it.\n * \\retval #PSA_ERROR_DOES_NOT_EXIST\n *         The requested key identifier is not a built-in key which is known\n *         to this function. If a key exists in the key storage with this\n *         identifier, the data from the storage will be used.\n * \\return (any other error)\n *         Any other error is propagated to the function that requested the key.\n *         Common errors include:\n *         - #PSA_ERROR_NOT_PERMITTED: the key exists but the requested owner\n *           is not allowed to access it.\n */\npsa_status_t mbedtls_psa_platform_get_builtin_key(\n    mbedtls_svc_key_id_t key_id,\n    psa_key_lifetime_t *lifetime,\n    psa_drv_slot_number_t *slot_number);\n#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */\n\n/** @} */\n\n/** \\defgroup psa_crypto_client Functions defined by a client provider\n *\n * The functions in this group are meant to be implemented by providers of\n * the PSA Crypto client interface. They are provided by the library when\n * #MBEDTLS_PSA_CRYPTO_C is enabled.\n *\n * \\note All functions in this group are experimental, as using\n *       alternative client interface providers is experimental.\n *\n * @{\n */\n\n/** Check if PSA is capable of handling the specified hash algorithm.\n *\n * This means that PSA core was built with the corresponding PSA_WANT_ALG_xxx\n * set and that psa_crypto_init has already been called.\n *\n * \\note When using the built-in version of the PSA core (i.e.\n *       #MBEDTLS_PSA_CRYPTO_C is set), for now, this function only checks\n *       the state of the driver subsystem, not the algorithm.\n *       This might be improved in the future.\n *\n * \\param hash_alg  The hash algorithm.\n *\n * \\return 1 if the PSA can handle \\p hash_alg, 0 otherwise.\n */\nint psa_can_do_hash(psa_algorithm_t hash_alg);\n\n/**\n * Tell if PSA is ready for this cipher.\n *\n * \\note When using the built-in version of the PSA core (i.e.\n *       #MBEDTLS_PSA_CRYPTO_C is set), for now, this function only checks\n *       the state of the driver subsystem, not the key type and algorithm.\n *       This might be improved in the future.\n *\n * \\param key_type    The key type.\n * \\param cipher_alg  The cipher algorithm.\n *\n * \\return 1 if the PSA can handle \\p cipher_alg, 0 otherwise.\n */\nint psa_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t cipher_alg);\n\n/**@}*/\n\n/** \\addtogroup crypto_types\n * @{\n */\n\n#define PSA_ALG_CATEGORY_PAKE                   ((psa_algorithm_t) 0x0a000000)\n\n/** Whether the specified algorithm is a password-authenticated key exchange.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is a password-authenticated key exchange (PAKE)\n *         algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\p alg is not a supported\n *         algorithm identifier.\n */\n#define PSA_ALG_IS_PAKE(alg)                                        \\\n    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_PAKE)\n\n/** The Password-authenticated key exchange by juggling (J-PAKE) algorithm.\n *\n * This is J-PAKE as defined by RFC 8236, instantiated with the following\n * parameters:\n *\n * - The group can be either an elliptic curve or defined over a finite field.\n * - Schnorr NIZK proof as defined by RFC 8235 and using the same group as the\n *   J-PAKE algorithm.\n * - A cryptographic hash function.\n *\n * To select these parameters and set up the cipher suite, call these functions\n * in any order:\n *\n * \\code\n * psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_JPAKE);\n * psa_pake_cs_set_primitive(cipher_suite,\n *                           PSA_PAKE_PRIMITIVE(type, family, bits));\n * psa_pake_cs_set_hash(cipher_suite, hash);\n * \\endcode\n *\n * For more information on how to set a specific curve or field, refer to the\n * documentation of the individual \\c PSA_PAKE_PRIMITIVE_TYPE_XXX constants.\n *\n * After initializing a J-PAKE operation, call\n *\n * \\code\n * psa_pake_setup(operation, cipher_suite);\n * psa_pake_set_user(operation, ...);\n * psa_pake_set_peer(operation, ...);\n * psa_pake_set_password_key(operation, ...);\n * \\endcode\n *\n * The password is provided as a key. This can be the password text itself,\n * in an agreed character encoding, or some value derived from the password\n * as required by a higher level protocol.\n *\n * (The implementation converts the key material to a number as described in\n * Section 2.3.8 of _SEC 1: Elliptic Curve Cryptography_\n * (https://www.secg.org/sec1-v2.pdf), before reducing it modulo \\c q. Here\n * \\c q is order of the group defined by the primitive set in the cipher suite.\n * The \\c psa_pake_set_password_key() function returns an error if the result\n * of the reduction is 0.)\n *\n * The key exchange flow for J-PAKE is as follows:\n * -# To get the first round data that needs to be sent to the peer, call\n *    \\code\n *    // Get g1\n *    psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);\n *    // Get the ZKP public key for x1\n *    psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);\n *    // Get the ZKP proof for x1\n *    psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);\n *    // Get g2\n *    psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);\n *    // Get the ZKP public key for x2\n *    psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);\n *    // Get the ZKP proof for x2\n *    psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);\n *    \\endcode\n * -# To provide the first round data received from the peer to the operation,\n *    call\n *    \\code\n *    // Set g3\n *    psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);\n *    // Set the ZKP public key for x3\n *    psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);\n *    // Set the ZKP proof for x3\n *    psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);\n *    // Set g4\n *    psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);\n *    // Set the ZKP public key for x4\n *    psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);\n *    // Set the ZKP proof for x4\n *    psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);\n *    \\endcode\n * -# To get the second round data that needs to be sent to the peer, call\n *    \\code\n *    // Get A\n *    psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);\n *    // Get ZKP public key for x2*s\n *    psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);\n *    // Get ZKP proof for x2*s\n *    psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);\n *    \\endcode\n * -# To provide the second round data received from the peer to the operation,\n *    call\n *    \\code\n *    // Set B\n *    psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);\n *    // Set ZKP public key for x4*s\n *    psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);\n *    // Set ZKP proof for x4*s\n *    psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);\n *    \\endcode\n * -# To access the shared secret call\n *    \\code\n *    // Get Ka=Kb=K\n *    psa_pake_get_implicit_key()\n *    \\endcode\n *\n * For more information consult the documentation of the individual\n * \\c PSA_PAKE_STEP_XXX constants.\n *\n * At this point there is a cryptographic guarantee that only the authenticated\n * party who used the same password is able to compute the key. But there is no\n * guarantee that the peer is the party it claims to be and was able to do so.\n *\n * That is, the authentication is only implicit (the peer is not authenticated\n * at this point, and no action should be taken that assume that they are - like\n * for example accessing restricted files).\n *\n * To make the authentication explicit there are various methods, see Section 5\n * of RFC 8236 for two examples.\n *\n * \\note The JPAKE implementation has the following limitations:\n *       - The only supported primitive is ECC on the curve secp256r1, i.e.\n *         `PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC,\n *          PSA_ECC_FAMILY_SECP_R1, 256)`.\n *       - The only supported hash algorithm is SHA-256, i.e.\n *         `PSA_ALG_SHA_256`.\n *       - When using the built-in implementation, the user ID and the peer ID\n *         must be `\"client\"` (6-byte string) and `\"server\"` (6-byte string),\n *         or the other way round.\n *         Third-party drivers may or may not have this limitation.\n *\n */\n#define PSA_ALG_JPAKE                   ((psa_algorithm_t) 0x0a000100)\n\n/** @} */\n\n/** \\defgroup pake Password-authenticated key exchange (PAKE)\n *\n * This is a proposed PAKE interface for the PSA Crypto API. It is not part of\n * the official PSA Crypto API yet.\n *\n * \\note The content of this section is not part of the stable API and ABI\n *       of Mbed TLS and may change arbitrarily from version to version.\n *       Same holds for the corresponding macros #PSA_ALG_CATEGORY_PAKE and\n *       #PSA_ALG_JPAKE.\n * @{\n */\n\n/** \\brief Encoding of the application role of PAKE\n *\n * Encodes the application's role in the algorithm is being executed. For more\n * information see the documentation of individual \\c PSA_PAKE_ROLE_XXX\n * constants.\n */\ntypedef uint8_t psa_pake_role_t;\n\n/** Encoding of input and output indicators for PAKE.\n *\n * Some PAKE algorithms need to exchange more data than just a single key share.\n * This type is for encoding additional input and output data for such\n * algorithms.\n */\ntypedef uint8_t psa_pake_step_t;\n\n/** Encoding of the type of the PAKE's primitive.\n *\n * Values defined by this standard will never be in the range 0x80-0xff.\n * Vendors who define additional types must use an encoding in this range.\n *\n * For more information see the documentation of individual\n * \\c PSA_PAKE_PRIMITIVE_TYPE_XXX constants.\n */\ntypedef uint8_t psa_pake_primitive_type_t;\n\n/** \\brief Encoding of the family of the primitive associated with the PAKE.\n *\n * For more information see the documentation of individual\n * \\c PSA_PAKE_PRIMITIVE_TYPE_XXX constants.\n */\ntypedef uint8_t psa_pake_family_t;\n\n/** \\brief Encoding of the primitive associated with the PAKE.\n *\n * For more information see the documentation of the #PSA_PAKE_PRIMITIVE macro.\n */\ntypedef uint32_t psa_pake_primitive_t;\n\n/** A value to indicate no role in a PAKE algorithm.\n * This value can be used in a call to psa_pake_set_role() for symmetric PAKE\n * algorithms which do not assign roles.\n */\n#define PSA_PAKE_ROLE_NONE                  ((psa_pake_role_t) 0x00)\n\n/** The first peer in a balanced PAKE.\n *\n * Although balanced PAKE algorithms are symmetric, some of them needs an\n * ordering of peers for the transcript calculations. If the algorithm does not\n * need this, both #PSA_PAKE_ROLE_FIRST and #PSA_PAKE_ROLE_SECOND are\n * accepted.\n */\n#define PSA_PAKE_ROLE_FIRST                ((psa_pake_role_t) 0x01)\n\n/** The second peer in a balanced PAKE.\n *\n * Although balanced PAKE algorithms are symmetric, some of them needs an\n * ordering of peers for the transcript calculations. If the algorithm does not\n * need this, either #PSA_PAKE_ROLE_FIRST or #PSA_PAKE_ROLE_SECOND are\n * accepted.\n */\n#define PSA_PAKE_ROLE_SECOND                ((psa_pake_role_t) 0x02)\n\n/** The client in an augmented PAKE.\n *\n * Augmented PAKE algorithms need to differentiate between client and server.\n */\n#define PSA_PAKE_ROLE_CLIENT                ((psa_pake_role_t) 0x11)\n\n/** The server in an augmented PAKE.\n *\n * Augmented PAKE algorithms need to differentiate between client and server.\n */\n#define PSA_PAKE_ROLE_SERVER                ((psa_pake_role_t) 0x12)\n\n/** The PAKE primitive type indicating the use of elliptic curves.\n *\n * The values of the \\c family and \\c bits fields of the cipher suite identify a\n * specific elliptic curve, using the same mapping that is used for ECC\n * (::psa_ecc_family_t) keys.\n *\n * (Here \\c family means the value returned by psa_pake_cs_get_family() and\n * \\c bits means the value returned by psa_pake_cs_get_bits().)\n *\n * Input and output during the operation can involve group elements and scalar\n * values:\n * -# The format for group elements is the same as for public keys on the\n *  specific curve would be. For more information, consult the documentation of\n *  psa_export_public_key().\n * -# The format for scalars is the same as for private keys on the specific\n *  curve would be. For more information, consult the documentation of\n *  psa_export_key().\n */\n#define PSA_PAKE_PRIMITIVE_TYPE_ECC       ((psa_pake_primitive_type_t) 0x01)\n\n/** The PAKE primitive type indicating the use of Diffie-Hellman groups.\n *\n * The values of the \\c family and \\c bits fields of the cipher suite identify\n * a specific Diffie-Hellman group, using the same mapping that is used for\n * Diffie-Hellman (::psa_dh_family_t) keys.\n *\n * (Here \\c family means the value returned by psa_pake_cs_get_family() and\n * \\c bits means the value returned by psa_pake_cs_get_bits().)\n *\n * Input and output during the operation can involve group elements and scalar\n * values:\n * -# The format for group elements is the same as for public keys on the\n *  specific group would be. For more information, consult the documentation of\n *  psa_export_public_key().\n * -# The format for scalars is the same as for private keys on the specific\n *  group would be. For more information, consult the documentation of\n *  psa_export_key().\n */\n#define PSA_PAKE_PRIMITIVE_TYPE_DH       ((psa_pake_primitive_type_t) 0x02)\n\n/** Construct a PAKE primitive from type, family and bit-size.\n *\n * \\param pake_type     The type of the primitive\n *                      (value of type ::psa_pake_primitive_type_t).\n * \\param pake_family   The family of the primitive\n *                      (the type and interpretation of this parameter depends\n *                      on \\p pake_type, for more information consult the\n *                      documentation of individual ::psa_pake_primitive_type_t\n *                      constants).\n * \\param pake_bits     The bit-size of the primitive\n *                      (Value of type \\c size_t. The interpretation\n *                      of this parameter depends on \\p pake_family, for more\n *                      information consult the documentation of individual\n *                      ::psa_pake_primitive_type_t constants).\n *\n * \\return The constructed primitive value of type ::psa_pake_primitive_t.\n *         Return 0 if the requested primitive can't be encoded as\n *         ::psa_pake_primitive_t.\n */\n#define PSA_PAKE_PRIMITIVE(pake_type, pake_family, pake_bits) \\\n    ((pake_bits & 0xFFFF) != pake_bits) ? 0 :                 \\\n    ((psa_pake_primitive_t) (((pake_type) << 24 |             \\\n                              (pake_family) << 16) | (pake_bits)))\n\n/** The key share being sent to or received from the peer.\n *\n * The format for both input and output at this step is the same as for public\n * keys on the group determined by the primitive (::psa_pake_primitive_t) would\n * be.\n *\n * For more information on the format, consult the documentation of\n * psa_export_public_key().\n *\n * For information regarding how the group is determined, consult the\n * documentation #PSA_PAKE_PRIMITIVE.\n */\n#define PSA_PAKE_STEP_KEY_SHARE                 ((psa_pake_step_t) 0x01)\n\n/** A Schnorr NIZKP public key.\n *\n * This is the ephemeral public key in the Schnorr Non-Interactive\n * Zero-Knowledge Proof (the value denoted by the letter 'V' in RFC 8235).\n *\n * The format for both input and output at this step is the same as for public\n * keys on the group determined by the primitive (::psa_pake_primitive_t) would\n * be.\n *\n * For more information on the format, consult the documentation of\n * psa_export_public_key().\n *\n * For information regarding how the group is determined, consult the\n * documentation #PSA_PAKE_PRIMITIVE.\n */\n#define PSA_PAKE_STEP_ZK_PUBLIC                 ((psa_pake_step_t) 0x02)\n\n/** A Schnorr NIZKP proof.\n *\n * This is the proof in the Schnorr Non-Interactive Zero-Knowledge Proof (the\n * value denoted by the letter 'r' in RFC 8235).\n *\n * Both for input and output, the value at this step is an integer less than\n * the order of the group selected in the cipher suite. The format depends on\n * the group as well:\n *\n * - For Montgomery curves, the encoding is little endian.\n * - For everything else the encoding is big endian (see Section 2.3.8 of\n *   _SEC 1: Elliptic Curve Cryptography_ at https://www.secg.org/sec1-v2.pdf).\n *\n * In both cases leading zeroes are allowed as long as the length in bytes does\n * not exceed the byte length of the group order.\n *\n * For information regarding how the group is determined, consult the\n * documentation #PSA_PAKE_PRIMITIVE.\n */\n#define PSA_PAKE_STEP_ZK_PROOF                  ((psa_pake_step_t) 0x03)\n\n/**@}*/\n\n/** A sufficient output buffer size for psa_pake_output().\n *\n * If the size of the output buffer is at least this large, it is guaranteed\n * that psa_pake_output() will not fail due to an insufficient output buffer\n * size. The actual size of the output might be smaller in any given call.\n *\n * See also #PSA_PAKE_OUTPUT_MAX_SIZE\n *\n * \\param alg           A PAKE algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_PAKE(\\p alg) is true).\n * \\param primitive     A primitive of type ::psa_pake_primitive_t that is\n *                      compatible with algorithm \\p alg.\n * \\param output_step   A value of type ::psa_pake_step_t that is valid for the\n *                      algorithm \\p alg.\n * \\return              A sufficient output buffer size for the specified\n *                      PAKE algorithm, primitive, and output step. If the\n *                      PAKE algorithm, primitive, or output step is not\n *                      recognized, or the parameters are incompatible,\n *                      return 0.\n */\n#define PSA_PAKE_OUTPUT_SIZE(alg, primitive, output_step)               \\\n    (alg == PSA_ALG_JPAKE &&                                           \\\n     primitive == PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC,      \\\n                                     PSA_ECC_FAMILY_SECP_R1, 256) ?    \\\n     (                                                                 \\\n         output_step == PSA_PAKE_STEP_KEY_SHARE ? 65 :                   \\\n         output_step == PSA_PAKE_STEP_ZK_PUBLIC ? 65 :                   \\\n         32                                                              \\\n     ) :                                                               \\\n     0)\n\n/** A sufficient input buffer size for psa_pake_input().\n *\n * The value returned by this macro is guaranteed to be large enough for any\n * valid input to psa_pake_input() in an operation with the specified\n * parameters.\n *\n * See also #PSA_PAKE_INPUT_MAX_SIZE\n *\n * \\param alg           A PAKE algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_PAKE(\\p alg) is true).\n * \\param primitive     A primitive of type ::psa_pake_primitive_t that is\n *                      compatible with algorithm \\p alg.\n * \\param input_step    A value of type ::psa_pake_step_t that is valid for the\n *                      algorithm \\p alg.\n * \\return              A sufficient input buffer size for the specified\n *                      input, cipher suite and algorithm. If the cipher suite,\n *                      the input type or PAKE algorithm is not recognized, or\n *                      the parameters are incompatible, return 0.\n */\n#define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step)                 \\\n    (alg == PSA_ALG_JPAKE &&                                           \\\n     primitive == PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC,      \\\n                                     PSA_ECC_FAMILY_SECP_R1, 256) ?    \\\n     (                                                                 \\\n         input_step == PSA_PAKE_STEP_KEY_SHARE ? 65 :                    \\\n         input_step == PSA_PAKE_STEP_ZK_PUBLIC ? 65 :                    \\\n         32                                                              \\\n     ) :                                                               \\\n     0)\n\n/** Output buffer size for psa_pake_output() for any of the supported PAKE\n * algorithm and primitive suites and output step.\n *\n * This macro must expand to a compile-time constant integer.\n *\n * The value of this macro must be at least as large as the largest value\n * returned by PSA_PAKE_OUTPUT_SIZE()\n *\n * See also #PSA_PAKE_OUTPUT_SIZE(\\p alg, \\p primitive, \\p output_step).\n */\n#define PSA_PAKE_OUTPUT_MAX_SIZE 65\n\n/** Input buffer size for psa_pake_input() for any of the supported PAKE\n * algorithm and primitive suites and input step.\n *\n * This macro must expand to a compile-time constant integer.\n *\n * The value of this macro must be at least as large as the largest value\n * returned by PSA_PAKE_INPUT_SIZE()\n *\n * See also #PSA_PAKE_INPUT_SIZE(\\p alg, \\p primitive, \\p output_step).\n */\n#define PSA_PAKE_INPUT_MAX_SIZE 65\n\n/** Returns a suitable initializer for a PAKE cipher suite object of type\n * psa_pake_cipher_suite_t.\n */\n#define PSA_PAKE_CIPHER_SUITE_INIT { PSA_ALG_NONE, 0, 0, 0, PSA_ALG_NONE }\n\n/** Returns a suitable initializer for a PAKE operation object of type\n * psa_pake_operation_t.\n */\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n#define PSA_PAKE_OPERATION_INIT { 0 }\n#else\n#define PSA_PAKE_OPERATION_INIT { 0, PSA_ALG_NONE, 0, PSA_PAKE_OPERATION_STAGE_SETUP, \\\n                                  { 0 }, { { 0 } } }\n#endif\n\nstruct psa_pake_cipher_suite_s {\n    psa_algorithm_t algorithm;\n    psa_pake_primitive_type_t type;\n    psa_pake_family_t family;\n    uint16_t  bits;\n    psa_algorithm_t hash;\n};\n\nstruct psa_crypto_driver_pake_inputs_s {\n    uint8_t *MBEDTLS_PRIVATE(password);\n    size_t MBEDTLS_PRIVATE(password_len);\n    uint8_t *MBEDTLS_PRIVATE(user);\n    size_t MBEDTLS_PRIVATE(user_len);\n    uint8_t *MBEDTLS_PRIVATE(peer);\n    size_t MBEDTLS_PRIVATE(peer_len);\n    psa_key_attributes_t MBEDTLS_PRIVATE(attributes);\n    struct psa_pake_cipher_suite_s MBEDTLS_PRIVATE(cipher_suite);\n};\n\ntypedef enum psa_crypto_driver_pake_step {\n    PSA_JPAKE_STEP_INVALID        = 0,  /* Invalid step */\n    PSA_JPAKE_X1_STEP_KEY_SHARE   = 1,  /* Round 1: input/output key share (for ephemeral private key X1).*/\n    PSA_JPAKE_X1_STEP_ZK_PUBLIC   = 2,  /* Round 1: input/output Schnorr NIZKP public key for the X1 key */\n    PSA_JPAKE_X1_STEP_ZK_PROOF    = 3,  /* Round 1: input/output Schnorr NIZKP proof for the X1 key */\n    PSA_JPAKE_X2_STEP_KEY_SHARE   = 4,  /* Round 1: input/output key share (for ephemeral private key X2).*/\n    PSA_JPAKE_X2_STEP_ZK_PUBLIC   = 5,  /* Round 1: input/output Schnorr NIZKP public key for the X2 key */\n    PSA_JPAKE_X2_STEP_ZK_PROOF    = 6,  /* Round 1: input/output Schnorr NIZKP proof for the X2 key */\n    PSA_JPAKE_X2S_STEP_KEY_SHARE  = 7,  /* Round 2: output X2S key (our key) */\n    PSA_JPAKE_X2S_STEP_ZK_PUBLIC  = 8,  /* Round 2: output Schnorr NIZKP public key for the X2S key (our key) */\n    PSA_JPAKE_X2S_STEP_ZK_PROOF   = 9,  /* Round 2: output Schnorr NIZKP proof for the X2S key (our key) */\n    PSA_JPAKE_X4S_STEP_KEY_SHARE  = 10, /* Round 2: input X4S key (from peer) */\n    PSA_JPAKE_X4S_STEP_ZK_PUBLIC  = 11, /* Round 2: input Schnorr NIZKP public key for the X4S key (from peer) */\n    PSA_JPAKE_X4S_STEP_ZK_PROOF   = 12  /* Round 2: input Schnorr NIZKP proof for the X4S key (from peer) */\n} psa_crypto_driver_pake_step_t;\n\ntypedef enum psa_jpake_round {\n    PSA_JPAKE_FIRST = 0,\n    PSA_JPAKE_SECOND = 1,\n    PSA_JPAKE_FINISHED = 2\n} psa_jpake_round_t;\n\ntypedef enum psa_jpake_io_mode {\n    PSA_JPAKE_INPUT = 0,\n    PSA_JPAKE_OUTPUT = 1\n} psa_jpake_io_mode_t;\n\nstruct psa_jpake_computation_stage_s {\n    /* The J-PAKE round we are currently on */\n    psa_jpake_round_t MBEDTLS_PRIVATE(round);\n    /* The 'mode' we are currently in (inputting or outputting) */\n    psa_jpake_io_mode_t MBEDTLS_PRIVATE(io_mode);\n    /* The number of completed inputs so far this round */\n    uint8_t MBEDTLS_PRIVATE(inputs);\n    /* The number of completed outputs so far this round */\n    uint8_t MBEDTLS_PRIVATE(outputs);\n    /* The next expected step (KEY_SHARE, ZK_PUBLIC or ZK_PROOF) */\n    psa_pake_step_t MBEDTLS_PRIVATE(step);\n};\n\n#define PSA_JPAKE_EXPECTED_INPUTS(round) ((round) == PSA_JPAKE_FINISHED ? 0 : \\\n                                          ((round) == PSA_JPAKE_FIRST ? 2 : 1))\n#define PSA_JPAKE_EXPECTED_OUTPUTS(round) ((round) == PSA_JPAKE_FINISHED ? 0 : \\\n                                           ((round) == PSA_JPAKE_FIRST ? 2 : 1))\n\nstruct psa_pake_operation_s {\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n    mbedtls_psa_client_handle_t handle;\n#else\n    /** Unique ID indicating which driver got assigned to do the\n     * operation. Since driver contexts are driver-specific, swapping\n     * drivers halfway through the operation is not supported.\n     * ID values are auto-generated in psa_crypto_driver_wrappers.h\n     * ID value zero means the context is not valid or not assigned to\n     * any driver (i.e. none of the driver contexts are active). */\n    unsigned int MBEDTLS_PRIVATE(id);\n    /* Algorithm of the PAKE operation */\n    psa_algorithm_t MBEDTLS_PRIVATE(alg);\n    /* A primitive of type compatible with algorithm */\n    psa_pake_primitive_t MBEDTLS_PRIVATE(primitive);\n    /* Stage of the PAKE operation: waiting for the setup, collecting inputs\n     * or computing. */\n    uint8_t MBEDTLS_PRIVATE(stage);\n    /* Holds computation stage of the PAKE algorithms. */\n    union {\n        uint8_t MBEDTLS_PRIVATE(dummy);\n#if defined(PSA_WANT_ALG_JPAKE)\n        struct psa_jpake_computation_stage_s MBEDTLS_PRIVATE(jpake);\n#endif\n    } MBEDTLS_PRIVATE(computation_stage);\n    union {\n        psa_driver_pake_context_t MBEDTLS_PRIVATE(ctx);\n        struct psa_crypto_driver_pake_inputs_s MBEDTLS_PRIVATE(inputs);\n    } MBEDTLS_PRIVATE(data);\n#endif\n};\n\n/** \\addtogroup pake\n * @{\n */\n\n/** The type of the data structure for PAKE cipher suites.\n *\n * This is an implementation-defined \\c struct. Applications should not\n * make any assumptions about the content of this structure.\n * Implementation details can change in future versions without notice.\n */\ntypedef struct psa_pake_cipher_suite_s psa_pake_cipher_suite_t;\n\n/** Return an initial value for a PAKE cipher suite object.\n */\nstatic psa_pake_cipher_suite_t psa_pake_cipher_suite_init(void);\n\n/** Retrieve the PAKE algorithm from a PAKE cipher suite.\n *\n * \\param[in] cipher_suite     The cipher suite structure to query.\n *\n * \\return The PAKE algorithm stored in the cipher suite structure.\n */\nstatic psa_algorithm_t psa_pake_cs_get_algorithm(\n    const psa_pake_cipher_suite_t *cipher_suite);\n\n/** Declare the PAKE algorithm for the cipher suite.\n *\n * This function overwrites any PAKE algorithm\n * previously set in \\p cipher_suite.\n *\n * \\note For #PSA_ALG_JPAKE, the only supported hash algorithm is SHA-256.\n *\n * \\param[out] cipher_suite    The cipher suite structure to write to.\n * \\param algorithm            The PAKE algorithm to write.\n *                             (`PSA_ALG_XXX` values of type ::psa_algorithm_t\n *                             such that #PSA_ALG_IS_PAKE(\\c alg) is true.)\n *                             If this is 0, the PAKE algorithm in\n *                             \\p cipher_suite becomes unspecified.\n */\nstatic void psa_pake_cs_set_algorithm(psa_pake_cipher_suite_t *cipher_suite,\n                                      psa_algorithm_t algorithm);\n\n/** Retrieve the primitive from a PAKE cipher suite.\n *\n * \\param[in] cipher_suite     The cipher suite structure to query.\n *\n * \\return The primitive stored in the cipher suite structure.\n */\nstatic psa_pake_primitive_t psa_pake_cs_get_primitive(\n    const psa_pake_cipher_suite_t *cipher_suite);\n\n/** Declare the primitive for a PAKE cipher suite.\n *\n * This function overwrites any primitive previously set in \\p cipher_suite.\n *\n * \\note For #PSA_ALG_JPAKE, the only supported primitive is ECC on the curve\n *       secp256r1, i.e. `PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC,\n *       PSA_ECC_FAMILY_SECP_R1, 256)`.\n *\n * \\param[out] cipher_suite    The cipher suite structure to write to.\n * \\param primitive            The primitive to write. If this is 0, the\n *                             primitive type in \\p cipher_suite becomes\n *                             unspecified.\n */\nstatic void psa_pake_cs_set_primitive(psa_pake_cipher_suite_t *cipher_suite,\n                                      psa_pake_primitive_t primitive);\n\n/** Retrieve the PAKE family from a PAKE cipher suite.\n *\n * \\param[in] cipher_suite     The cipher suite structure to query.\n *\n * \\return The PAKE family stored in the cipher suite structure.\n */\nstatic psa_pake_family_t psa_pake_cs_get_family(\n    const psa_pake_cipher_suite_t *cipher_suite);\n\n/** Retrieve the PAKE primitive bit-size from a PAKE cipher suite.\n *\n * \\param[in] cipher_suite     The cipher suite structure to query.\n *\n * \\return The PAKE primitive bit-size stored in the cipher suite structure.\n */\nstatic uint16_t psa_pake_cs_get_bits(\n    const psa_pake_cipher_suite_t *cipher_suite);\n\n/** Retrieve the hash algorithm from a PAKE cipher suite.\n *\n * \\param[in] cipher_suite      The cipher suite structure to query.\n *\n * \\return The hash algorithm stored in the cipher suite structure. The return\n *         value is 0 if the PAKE is not parametrised by a hash algorithm or if\n *         the hash algorithm is not set.\n */\nstatic psa_algorithm_t psa_pake_cs_get_hash(\n    const psa_pake_cipher_suite_t *cipher_suite);\n\n/** Declare the hash algorithm for a PAKE cipher suite.\n *\n * This function overwrites any hash algorithm\n * previously set in \\p cipher_suite.\n *\n * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX`\n * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\\c alg) is true)\n * for more information.\n *\n * \\param[out] cipher_suite     The cipher suite structure to write to.\n * \\param hash                  The hash involved in the cipher suite.\n *                              (`PSA_ALG_XXX` values of type ::psa_algorithm_t\n *                              such that #PSA_ALG_IS_HASH(\\c alg) is true.)\n *                              If this is 0, the hash algorithm in\n *                              \\p cipher_suite becomes unspecified.\n */\nstatic void psa_pake_cs_set_hash(psa_pake_cipher_suite_t *cipher_suite,\n                                 psa_algorithm_t hash);\n\n/** The type of the state data structure for PAKE operations.\n *\n * Before calling any function on a PAKE operation object, the application\n * must initialize it by any of the following means:\n * - Set the structure to all-bits-zero, for example:\n *   \\code\n *   psa_pake_operation_t operation;\n *   memset(&operation, 0, sizeof(operation));\n *   \\endcode\n * - Initialize the structure to logical zero values, for example:\n *   \\code\n *   psa_pake_operation_t operation = {0};\n *   \\endcode\n * - Initialize the structure to the initializer #PSA_PAKE_OPERATION_INIT,\n *   for example:\n *   \\code\n *   psa_pake_operation_t operation = PSA_PAKE_OPERATION_INIT;\n *   \\endcode\n * - Assign the result of the function psa_pake_operation_init()\n *   to the structure, for example:\n *   \\code\n *   psa_pake_operation_t operation;\n *   operation = psa_pake_operation_init();\n *   \\endcode\n *\n * This is an implementation-defined \\c struct. Applications should not\n * make any assumptions about the content of this structure.\n * Implementation details can change in future versions without notice. */\ntypedef struct psa_pake_operation_s psa_pake_operation_t;\n\n/** The type of input values for PAKE operations. */\ntypedef struct psa_crypto_driver_pake_inputs_s psa_crypto_driver_pake_inputs_t;\n\n/** The type of computation stage for J-PAKE operations. */\ntypedef struct psa_jpake_computation_stage_s psa_jpake_computation_stage_t;\n\n/** Return an initial value for a PAKE operation object.\n */\nstatic psa_pake_operation_t psa_pake_operation_init(void);\n\n/** Get the length of the password in bytes from given inputs.\n *\n * \\param[in]  inputs           Operation inputs.\n * \\param[out] password_len     Password length.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BAD_STATE\n *         Password hasn't been set yet.\n */\npsa_status_t psa_crypto_driver_pake_get_password_len(\n    const psa_crypto_driver_pake_inputs_t *inputs,\n    size_t *password_len);\n\n/** Get the password from given inputs.\n *\n * \\param[in]  inputs           Operation inputs.\n * \\param[out] buffer           Return buffer for password.\n * \\param      buffer_size      Size of the return buffer in bytes.\n * \\param[out] buffer_length    Actual size of the password in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BAD_STATE\n *         Password hasn't been set yet.\n */\npsa_status_t psa_crypto_driver_pake_get_password(\n    const psa_crypto_driver_pake_inputs_t *inputs,\n    uint8_t *buffer, size_t buffer_size, size_t *buffer_length);\n\n/** Get the length of the user id in bytes from given inputs.\n *\n * \\param[in]  inputs           Operation inputs.\n * \\param[out] user_len         User id length.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BAD_STATE\n *         User id hasn't been set yet.\n */\npsa_status_t psa_crypto_driver_pake_get_user_len(\n    const psa_crypto_driver_pake_inputs_t *inputs,\n    size_t *user_len);\n\n/** Get the length of the peer id in bytes from given inputs.\n *\n * \\param[in]  inputs           Operation inputs.\n * \\param[out] peer_len         Peer id length.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BAD_STATE\n *         Peer id hasn't been set yet.\n */\npsa_status_t psa_crypto_driver_pake_get_peer_len(\n    const psa_crypto_driver_pake_inputs_t *inputs,\n    size_t *peer_len);\n\n/** Get the user id from given inputs.\n *\n * \\param[in]  inputs           Operation inputs.\n * \\param[out] user_id          User id.\n * \\param      user_id_size     Size of \\p user_id in bytes.\n * \\param[out] user_id_len      Size of the user id in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BAD_STATE\n *         User id hasn't been set yet.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p user_id is too small.\n */\npsa_status_t psa_crypto_driver_pake_get_user(\n    const psa_crypto_driver_pake_inputs_t *inputs,\n    uint8_t *user_id, size_t user_id_size, size_t *user_id_len);\n\n/** Get the peer id from given inputs.\n *\n * \\param[in]  inputs           Operation inputs.\n * \\param[out] peer_id          Peer id.\n * \\param      peer_id_size     Size of \\p peer_id in bytes.\n * \\param[out] peer_id_length   Size of the peer id in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BAD_STATE\n *         Peer id hasn't been set yet.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p peer_id is too small.\n */\npsa_status_t psa_crypto_driver_pake_get_peer(\n    const psa_crypto_driver_pake_inputs_t *inputs,\n    uint8_t *peer_id, size_t peer_id_size, size_t *peer_id_length);\n\n/** Get the cipher suite from given inputs.\n *\n * \\param[in]  inputs           Operation inputs.\n * \\param[out] cipher_suite     Return buffer for role.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BAD_STATE\n *         Cipher_suite hasn't been set yet.\n */\npsa_status_t psa_crypto_driver_pake_get_cipher_suite(\n    const psa_crypto_driver_pake_inputs_t *inputs,\n    psa_pake_cipher_suite_t *cipher_suite);\n\n/** Set the session information for a password-authenticated key exchange.\n *\n * The sequence of operations to set up a password-authenticated key exchange\n * is as follows:\n * -# Allocate an operation object which will be passed to all the functions\n *    listed here.\n * -# Initialize the operation object with one of the methods described in the\n *    documentation for #psa_pake_operation_t, e.g.\n *    #PSA_PAKE_OPERATION_INIT.\n * -# Call psa_pake_setup() to specify the cipher suite.\n * -# Call \\c psa_pake_set_xxx() functions on the operation to complete the\n *    setup. The exact sequence of \\c psa_pake_set_xxx() functions that needs\n *    to be called depends on the algorithm in use.\n *\n * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX`\n * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\\c alg) is true)\n * for more information.\n *\n * A typical sequence of calls to perform a password-authenticated key\n * exchange:\n * -# Call psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to get the\n *    key share that needs to be sent to the peer.\n * -# Call psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to provide\n *    the key share that was received from the peer.\n * -# Depending on the algorithm additional calls to psa_pake_output() and\n *    psa_pake_input() might be necessary.\n * -# Call psa_pake_get_implicit_key() for accessing the shared secret.\n *\n * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX`\n * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\\c alg) is true)\n * for more information.\n *\n * If an error occurs at any step after a call to psa_pake_setup(),\n * the operation will need to be reset by a call to psa_pake_abort(). The\n * application may call psa_pake_abort() at any time after the operation\n * has been initialized.\n *\n * After a successful call to psa_pake_setup(), the application must\n * eventually terminate the operation. The following events terminate an\n * operation:\n * - A call to psa_pake_abort().\n * - A successful call to psa_pake_get_implicit_key().\n *\n * \\param[in,out] operation     The operation object to set up. It must have\n *                              been initialized but not set up yet.\n * \\param[in] cipher_suite      The cipher suite to use. (A cipher suite fully\n *                              characterizes a PAKE algorithm and determines\n *                              the algorithm as well.)\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The algorithm in \\p cipher_suite is not a PAKE algorithm, or the\n *         PAKE primitive in \\p cipher_suite is not compatible with the\n *         PAKE algorithm, or the hash algorithm in \\p cipher_suite is invalid\n *         or not compatible with the PAKE algorithm and primitive.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         The algorithm in \\p cipher_suite is not a supported PAKE algorithm,\n *         or the PAKE primitive in \\p cipher_suite is not supported or not\n *         compatible with the PAKE algorithm, or the hash algorithm in\n *         \\p cipher_suite is not supported or not compatible with the PAKE\n *         algorithm and primitive.\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid, or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_pake_setup(psa_pake_operation_t *operation,\n                            const psa_pake_cipher_suite_t *cipher_suite);\n\n/** Set the password for a password-authenticated key exchange from key ID.\n *\n * Call this function when the password, or a value derived from the password,\n * is already present in the key store.\n *\n * \\param[in,out] operation     The operation object to set the password for. It\n *                              must have been set up by psa_pake_setup() and\n *                              not yet in use (neither psa_pake_output() nor\n *                              psa_pake_input() has been called yet). It must\n *                              be on operation for which the password hasn't\n *                              been set yet (psa_pake_set_password_key()\n *                              hasn't been called yet).\n * \\param password              Identifier of the key holding the password or a\n *                              value derived from the password (eg. by a\n *                              memory-hard function).  It must remain valid\n *                              until the operation terminates. It must be of\n *                              type #PSA_KEY_TYPE_PASSWORD or\n *                              #PSA_KEY_TYPE_PASSWORD_HASH. It has to allow\n *                              the usage #PSA_KEY_USAGE_DERIVE.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_HANDLE\n *         \\p password is not a valid key identifier.\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The key does not have the #PSA_KEY_USAGE_DERIVE flag, or it does not\n *         permit the \\p operation's algorithm.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The key type for \\p password is not #PSA_KEY_TYPE_PASSWORD or\n *         #PSA_KEY_TYPE_PASSWORD_HASH, or \\p password is not compatible with\n *         the \\p operation's cipher suite.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         The key type or key size of \\p password is not supported with the\n *         \\p operation's cipher suite.\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must have been set up.), or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation,\n                                       mbedtls_svc_key_id_t password);\n\n/** Set the user ID for a password-authenticated key exchange.\n *\n * Call this function to set the user ID. For PAKE algorithms that associate a\n * user identifier with each side of the session you need to call\n * psa_pake_set_peer() as well. For PAKE algorithms that associate a single\n * user identifier with the session, call psa_pake_set_user() only.\n *\n * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX`\n * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\\c alg) is true)\n * for more information.\n *\n * \\note When using the built-in implementation of #PSA_ALG_JPAKE, the user ID\n *       must be `\"client\"` (6-byte string) or `\"server\"` (6-byte string).\n *       Third-party drivers may or may not have this limitation.\n *\n * \\param[in,out] operation     The operation object to set the user ID for. It\n *                              must have been set up by psa_pake_setup() and\n *                              not yet in use (neither psa_pake_output() nor\n *                              psa_pake_input() has been called yet). It must\n *                              be on operation for which the user ID hasn't\n *                              been set (psa_pake_set_user() hasn't been\n *                              called yet).\n * \\param[in] user_id           The user ID to authenticate with.\n * \\param user_id_len           Size of the \\p user_id buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p user_id is not valid for the \\p operation's algorithm and cipher\n *         suite.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         The value of \\p user_id is not supported by the implementation.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid, or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_pake_set_user(psa_pake_operation_t *operation,\n                               const uint8_t *user_id,\n                               size_t user_id_len);\n\n/** Set the peer ID for a password-authenticated key exchange.\n *\n * Call this function in addition to psa_pake_set_user() for PAKE algorithms\n * that associate a user identifier with each side of the session. For PAKE\n * algorithms that associate a single user identifier with the session, call\n * psa_pake_set_user() only.\n *\n * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX`\n * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\\c alg) is true)\n * for more information.\n *\n * \\note When using the built-in implementation of #PSA_ALG_JPAKE, the peer ID\n *       must be `\"client\"` (6-byte string) or `\"server\"` (6-byte string).\n *       Third-party drivers may or may not have this limitation.\n *\n * \\param[in,out] operation     The operation object to set the peer ID for. It\n *                              must have been set up by psa_pake_setup() and\n *                              not yet in use (neither psa_pake_output() nor\n *                              psa_pake_input() has been called yet). It must\n *                              be on operation for which the peer ID hasn't\n *                              been set (psa_pake_set_peer() hasn't been\n *                              called yet).\n * \\param[in] peer_id           The peer's ID to authenticate.\n * \\param peer_id_len           Size of the \\p peer_id buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p peer_id is not valid for the \\p operation's algorithm and cipher\n *         suite.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         The algorithm doesn't associate a second identity with the session.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         Calling psa_pake_set_peer() is invalid with the \\p operation's\n *         algorithm, the operation state is not valid, or the library has not\n *         been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_pake_set_peer(psa_pake_operation_t *operation,\n                               const uint8_t *peer_id,\n                               size_t peer_id_len);\n\n/** Set the application role for a password-authenticated key exchange.\n *\n * Not all PAKE algorithms need to differentiate the communicating entities.\n * It is optional to call this function for PAKEs that don't require a role\n * to be specified. For such PAKEs the application role parameter is ignored,\n * or #PSA_PAKE_ROLE_NONE can be passed as \\c role.\n *\n * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX`\n * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\\c alg) is true)\n * for more information.\n *\n * \\param[in,out] operation     The operation object to specify the\n *                              application's role for. It must have been set up\n *                              by psa_pake_setup() and not yet in use (neither\n *                              psa_pake_output() nor psa_pake_input() has been\n *                              called yet). It must be on operation for which\n *                              the application's role hasn't been specified\n *                              (psa_pake_set_role() hasn't been called yet).\n * \\param role                  A value of type ::psa_pake_role_t indicating the\n *                              application's role in the PAKE the algorithm\n *                              that is being set up. For more information see\n *                              the documentation of \\c PSA_PAKE_ROLE_XXX\n *                              constants.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The \\p role is not a valid PAKE role in the \\p operation’s algorithm.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         The \\p role for this algorithm is not supported or is not valid.\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid, or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_pake_set_role(psa_pake_operation_t *operation,\n                               psa_pake_role_t role);\n\n/** Get output for a step of a password-authenticated key exchange.\n *\n * Depending on the algorithm being executed, you might need to call this\n * function several times or you might not need to call this at all.\n *\n * The exact sequence of calls to perform a password-authenticated key\n * exchange depends on the algorithm in use.  Refer to the documentation of\n * individual PAKE algorithm types (`PSA_ALG_XXX` values of type\n * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\\c alg) is true) for more\n * information.\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_pake_abort().\n *\n * \\param[in,out] operation    Active PAKE operation.\n * \\param step                 The step of the algorithm for which the output is\n *                             requested.\n * \\param[out] output          Buffer where the output is to be written in the\n *                             format appropriate for this \\p step. Refer to\n *                             the documentation of the individual\n *                             \\c PSA_PAKE_STEP_XXX constants for more\n *                             information.\n * \\param output_size          Size of the \\p output buffer in bytes. This must\n *                             be at least #PSA_PAKE_OUTPUT_SIZE(\\c alg, \\c\n *                             primitive, \\p output_step) where \\c alg and\n *                             \\p primitive are the PAKE algorithm and primitive\n *                             in the operation's cipher suite, and \\p step is\n *                             the output step.\n *\n * \\param[out] output_length   On success, the number of bytes of the returned\n *                             output.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p output buffer is too small.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p step is not compatible with the operation's algorithm.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p step is not supported with the operation's algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active, and fully set\n *         up, and this call must conform to the algorithm's requirements\n *         for ordering of input and output steps), or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_pake_output(psa_pake_operation_t *operation,\n                             psa_pake_step_t step,\n                             uint8_t *output,\n                             size_t output_size,\n                             size_t *output_length);\n\n/** Provide input for a step of a password-authenticated key exchange.\n *\n * Depending on the algorithm being executed, you might need to call this\n * function several times or you might not need to call this at all.\n *\n * The exact sequence of calls to perform a password-authenticated key\n * exchange depends on the algorithm in use.  Refer to the documentation of\n * individual PAKE algorithm types (`PSA_ALG_XXX` values of type\n * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\\c alg) is true) for more\n * information.\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling psa_pake_abort().\n *\n * \\param[in,out] operation    Active PAKE operation.\n * \\param step                 The step for which the input is provided.\n * \\param[in] input            Buffer containing the input in the format\n *                             appropriate for this \\p step. Refer to the\n *                             documentation of the individual\n *                             \\c PSA_PAKE_STEP_XXX constants for more\n *                             information.\n * \\param input_length         Size of the \\p input buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The verification fails for a #PSA_PAKE_STEP_ZK_PROOF input step.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p input_length is not compatible with the \\p operation’s algorithm,\n *         or the \\p input is not valid for the \\p operation's algorithm,\n *         cipher suite or \\p step.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p step p is not supported with the \\p operation's algorithm, or the\n *         \\p input is not supported for the \\p operation's algorithm, cipher\n *         suite or \\p step.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active, and fully set\n *         up, and this call must conform to the algorithm's requirements\n *         for ordering of input and output steps), or\n *         the library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_pake_input(psa_pake_operation_t *operation,\n                            psa_pake_step_t step,\n                            const uint8_t *input,\n                            size_t input_length);\n\n/** Get implicitly confirmed shared secret from a PAKE.\n *\n * At this point there is a cryptographic guarantee that only the authenticated\n * party who used the same password is able to compute the key. But there is no\n * guarantee that the peer is the party it claims to be and was able to do so.\n *\n * That is, the authentication is only implicit. Since the peer is not\n * authenticated yet, no action should be taken yet that assumes that the peer\n * is who it claims to be. For example, do not access restricted files on the\n * peer's behalf until an explicit authentication has succeeded.\n *\n * This function can be called after the key exchange phase of the operation\n * has completed. It imports the shared secret output of the PAKE into the\n * provided derivation operation. The input step\n * #PSA_KEY_DERIVATION_INPUT_SECRET is used when placing the shared key\n * material in the key derivation operation.\n *\n * The exact sequence of calls to perform a password-authenticated key\n * exchange depends on the algorithm in use.  Refer to the documentation of\n * individual PAKE algorithm types (`PSA_ALG_XXX` values of type\n * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\\c alg) is true) for more\n * information.\n *\n * When this function returns successfully, \\p operation becomes inactive.\n * If this function returns an error status, both \\p operation\n * and \\c key_derivation operations enter an error state and must be aborted by\n * calling psa_pake_abort() and psa_key_derivation_abort() respectively.\n *\n * \\param[in,out] operation    Active PAKE operation.\n * \\param[out] output          A key derivation operation that is ready\n *                             for an input step of type\n *                             #PSA_KEY_DERIVATION_INPUT_SECRET.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         #PSA_KEY_DERIVATION_INPUT_SECRET is not compatible with the\n *         algorithm in the \\p output key derivation operation.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         Input from a PAKE is not supported by the algorithm in the \\p output\n *         key derivation operation.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The PAKE operation state is not valid (it must be active, but beyond\n *         that validity is specific to the algorithm), or\n *         the library has not been previously initialized by psa_crypto_init(),\n *         or the state of \\p output is not valid for\n *         the #PSA_KEY_DERIVATION_INPUT_SECRET step. This can happen if the\n *         step is out of order or the application has done this step already\n *         and it may not be repeated.\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation,\n                                       psa_key_derivation_operation_t *output);\n\n/** Abort a PAKE operation.\n *\n * Aborting an operation frees all associated resources except for the \\c\n * operation structure itself. Once aborted, the operation object can be reused\n * for another operation by calling psa_pake_setup() again.\n *\n * This function may be called at any time after the operation\n * object has been initialized as described in #psa_pake_operation_t.\n *\n * In particular, calling psa_pake_abort() after the operation has been\n * terminated by a call to psa_pake_abort() or psa_pake_get_implicit_key()\n * is safe and has no effect.\n *\n * \\param[in,out] operation    The operation to abort.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t psa_pake_abort(psa_pake_operation_t *operation);\n\n/**@}*/\n\nstatic inline psa_algorithm_t psa_pake_cs_get_algorithm(\n    const psa_pake_cipher_suite_t *cipher_suite)\n{\n    return cipher_suite->algorithm;\n}\n\nstatic inline void psa_pake_cs_set_algorithm(\n    psa_pake_cipher_suite_t *cipher_suite,\n    psa_algorithm_t algorithm)\n{\n    if (!PSA_ALG_IS_PAKE(algorithm)) {\n        cipher_suite->algorithm = 0;\n    } else {\n        cipher_suite->algorithm = algorithm;\n    }\n}\n\nstatic inline psa_pake_primitive_t psa_pake_cs_get_primitive(\n    const psa_pake_cipher_suite_t *cipher_suite)\n{\n    return PSA_PAKE_PRIMITIVE(cipher_suite->type, cipher_suite->family,\n                              cipher_suite->bits);\n}\n\nstatic inline void psa_pake_cs_set_primitive(\n    psa_pake_cipher_suite_t *cipher_suite,\n    psa_pake_primitive_t primitive)\n{\n    cipher_suite->type = (psa_pake_primitive_type_t) (primitive >> 24);\n    cipher_suite->family = (psa_pake_family_t) (0xFF & (primitive >> 16));\n    cipher_suite->bits = (uint16_t) (0xFFFF & primitive);\n}\n\nstatic inline psa_pake_family_t psa_pake_cs_get_family(\n    const psa_pake_cipher_suite_t *cipher_suite)\n{\n    return cipher_suite->family;\n}\n\nstatic inline uint16_t psa_pake_cs_get_bits(\n    const psa_pake_cipher_suite_t *cipher_suite)\n{\n    return cipher_suite->bits;\n}\n\nstatic inline psa_algorithm_t psa_pake_cs_get_hash(\n    const psa_pake_cipher_suite_t *cipher_suite)\n{\n    return cipher_suite->hash;\n}\n\nstatic inline void psa_pake_cs_set_hash(psa_pake_cipher_suite_t *cipher_suite,\n                                        psa_algorithm_t hash)\n{\n    if (!PSA_ALG_IS_HASH(hash)) {\n        cipher_suite->hash = 0;\n    } else {\n        cipher_suite->hash = hash;\n    }\n}\n\nstatic inline struct psa_pake_cipher_suite_s psa_pake_cipher_suite_init(void)\n{\n    const struct psa_pake_cipher_suite_s v = PSA_PAKE_CIPHER_SUITE_INIT;\n    return v;\n}\n\nstatic inline struct psa_pake_operation_s psa_pake_operation_init(void)\n{\n    const struct psa_pake_operation_s v = PSA_PAKE_OPERATION_INIT;\n    return v;\n}\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* PSA_CRYPTO_EXTRA_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_legacy.h",
    "content": "/**\n * \\file psa/crypto_legacy.h\n *\n * \\brief Add temporary suppport for deprecated symbols before they are\n *        removed from the library.\n *\n * PSA_WANT_KEY_TYPE_xxx_KEY_PAIR and MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR\n * symbols are deprecated.\n * New symols add a suffix to that base name in order to clearly state what is\n * the expected use for the key (use, import, export, generate, derive).\n * Here we define some backward compatibility support for uses stil using\n * the legacy symbols.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_PSA_CRYPTO_LEGACY_H\n#define MBEDTLS_PSA_CRYPTO_LEGACY_H\n\n#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) //no-check-names\n#if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC)\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC      1\n#endif\n#if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT)\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT   1\n#endif\n#if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT)\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT   1\n#endif\n#if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE)\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1\n#endif\n#if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)\n#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE   1\n#endif\n#endif\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) //no-check-names\n#if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)\n#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC      1\n#endif\n#if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT)\n#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT   1\n#endif\n#if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT)\n#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT   1\n#endif\n#if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)\n#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1\n#endif\n#endif\n\n#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) //no-check-names\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC)\n#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC\n#endif\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT)\n#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT\n#endif\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT)\n#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT\n#endif\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE)\n#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE\n#endif\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE)\n#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE\n#endif\n#endif\n\n#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) //no-check-names\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC)\n#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC\n#endif\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT)\n#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT\n#endif\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT)\n#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT\n#endif\n#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE)\n#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE\n#endif\n#endif\n\n#endif /* MBEDTLS_PSA_CRYPTO_LEGACY_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_platform.h",
    "content": "/**\n * \\file psa/crypto_platform.h\n *\n * \\brief PSA cryptography module: Mbed TLS platform definitions\n *\n * \\note This file may not be included directly. Applications must\n * include psa/crypto.h.\n *\n * This file contains platform-dependent type definitions.\n *\n * In implementations with isolation between the application and the\n * cryptography module, implementers should take care to ensure that\n * the definitions that are exposed to applications match what the\n * module implements.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_PLATFORM_H\n#define PSA_CRYPTO_PLATFORM_H\n#include \"mbedtls/private_access.h\"\n\n/*\n * Include the build-time configuration information header. Here, we do not\n * include `\"mbedtls/build_info.h\"` directly but `\"psa/build_info.h\"`, which\n * is basically just an alias to it. This is to ease the maintenance of the\n * TF-PSA-Crypto repository which has a different build system and\n * configuration.\n */\n#include \"psa/build_info.h\"\n\n/* PSA requires several types which C99 provides in stdint.h. */\n#include <stdint.h>\n\n#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)\n\n/* Building for the PSA Crypto service on a PSA platform, a key owner is a PSA\n * partition identifier.\n *\n * The function psa_its_identifier_of_slot() in psa_crypto_storage.c that\n * translates a key identifier to a key storage file name assumes that\n * mbedtls_key_owner_id_t is a 32-bit integer. This function thus needs\n * reworking if mbedtls_key_owner_id_t is not defined as a 32-bit integer\n * here anymore.\n */\ntypedef int32_t mbedtls_key_owner_id_t;\n\n/** Compare two key owner identifiers.\n *\n * \\param id1 First key owner identifier.\n * \\param id2 Second key owner identifier.\n *\n * \\return Non-zero if the two key owner identifiers are equal, zero otherwise.\n */\nstatic inline int mbedtls_key_owner_id_equal(mbedtls_key_owner_id_t id1,\n                                             mbedtls_key_owner_id_t id2)\n{\n    return id1 == id2;\n}\n\n#endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */\n\n/*\n * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is being built for SPM\n * (Secure Partition Manager) integration which separates the code into two\n * parts: NSPE (Non-Secure Processing Environment) and SPE (Secure Processing\n * Environment). When building for the SPE, an additional header file should be\n * included.\n */\n#if defined(MBEDTLS_PSA_CRYPTO_SPM)\n#define PSA_CRYPTO_SECURE 1\n#include \"crypto_spe.h\"\n#endif // MBEDTLS_PSA_CRYPTO_SPM\n\n#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)\n/** The type of the context passed to mbedtls_psa_external_get_random().\n *\n * Mbed TLS initializes the context to all-bits-zero before calling\n * mbedtls_psa_external_get_random() for the first time.\n *\n * The definition of this type in the Mbed TLS source code is for\n * demonstration purposes. Implementers of mbedtls_psa_external_get_random()\n * are expected to replace it with a custom definition.\n */\ntypedef struct {\n    uintptr_t MBEDTLS_PRIVATE(opaque)[2];\n} mbedtls_psa_external_random_context_t;\n#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n/** The type of the client handle used in context structures\n *\n * When a client view of the multipart context structures is required,\n * this handle is used to keep a mapping with the service side of the\n * context which contains the actual data.\n */\ntypedef uint32_t mbedtls_psa_client_handle_t;\n#endif\n\n#endif /* PSA_CRYPTO_PLATFORM_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_se_driver.h",
    "content": "/**\n * \\file psa/crypto_se_driver.h\n * \\brief PSA external cryptoprocessor driver module\n *\n * This header declares types and function signatures for cryptography\n * drivers that access key material via opaque references.\n * This is meant for cryptoprocessors that have a separate key storage from the\n * space in which the PSA Crypto implementation runs, typically secure\n * elements (SEs).\n *\n * This file is part of the PSA Crypto Driver HAL (hardware abstraction layer),\n * containing functions for driver developers to implement to enable hardware\n * to be called in a standardized way by a PSA Cryptography API\n * implementation. The functions comprising the driver HAL, which driver\n * authors implement, are not intended to be called by application developers.\n */\n\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef PSA_CRYPTO_SE_DRIVER_H\n#define PSA_CRYPTO_SE_DRIVER_H\n#include \"mbedtls/private_access.h\"\n\n#include \"crypto_driver_common.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** \\defgroup se_init Secure element driver initialization\n */\n/**@{*/\n\n/** \\brief Driver context structure\n *\n * Driver functions receive a pointer to this structure.\n * Each registered driver has one instance of this structure.\n *\n * Implementations must include the fields specified here and\n * may include other fields.\n */\ntypedef struct {\n    /** A read-only pointer to the driver's persistent data.\n     *\n     * Drivers typically use this persistent data to keep track of\n     * which slot numbers are available. This is only a guideline:\n     * drivers may use the persistent data for any purpose, keeping\n     * in mind the restrictions on when the persistent data is saved\n     * to storage: the persistent data is only saved after calling\n     * certain functions that receive a writable pointer to the\n     * persistent data.\n     *\n     * The core allocates a memory buffer for the persistent data.\n     * The pointer is guaranteed to be suitably aligned for any data type,\n     * like a pointer returned by `malloc` (but the core can use any\n     * method to allocate the buffer, not necessarily `malloc`).\n     *\n     * The size of this buffer is in the \\c persistent_data_size field of\n     * this structure.\n     *\n     * Before the driver is initialized for the first time, the content of\n     * the persistent data is all-bits-zero. After a driver upgrade, if the\n     * size of the persistent data has increased, the original data is padded\n     * on the right with zeros; if the size has decreased, the original data\n     * is truncated to the new size.\n     *\n     * This pointer is to read-only data. Only a few driver functions are\n     * allowed to modify the persistent data. These functions receive a\n     * writable pointer. These functions are:\n     * - psa_drv_se_t::p_init\n     * - psa_drv_se_key_management_t::p_allocate\n     * - psa_drv_se_key_management_t::p_destroy\n     *\n     * The PSA Cryptography core saves the persistent data from one\n     * session to the next. It does this before returning from API functions\n     * that call a driver method that is allowed to modify the persistent\n     * data, specifically:\n     * - psa_crypto_init() causes a call to psa_drv_se_t::p_init, and may call\n     *   psa_drv_se_key_management_t::p_destroy to complete an action\n     *   that was interrupted by a power failure.\n     * - Key creation functions cause a call to\n     *   psa_drv_se_key_management_t::p_allocate, and may cause a call to\n     *   psa_drv_se_key_management_t::p_destroy in case an error occurs.\n     * - psa_destroy_key() causes a call to\n     *   psa_drv_se_key_management_t::p_destroy.\n     */\n    const void *const MBEDTLS_PRIVATE(persistent_data);\n\n    /** The size of \\c persistent_data in bytes.\n     *\n     * This is always equal to the value of the `persistent_data_size` field\n     * of the ::psa_drv_se_t structure when the driver is registered.\n     */\n    const size_t MBEDTLS_PRIVATE(persistent_data_size);\n\n    /** Driver transient data.\n     *\n     * The core initializes this value to 0 and does not read or modify it\n     * afterwards. The driver may store whatever it wants in this field.\n     */\n    uintptr_t MBEDTLS_PRIVATE(transient_data);\n} psa_drv_se_context_t;\n\n/** \\brief A driver initialization function.\n *\n * \\param[in,out] drv_context       The driver context structure.\n * \\param[in,out] persistent_data   A pointer to the persistent data\n *                                  that allows writing.\n * \\param location                  The location value for which this driver\n *                                  is registered. The driver will be invoked\n *                                  for all keys whose lifetime is in this\n *                                  location.\n *\n * \\retval #PSA_SUCCESS\n *         The driver is operational.\n *         The core will update the persistent data in storage.\n * \\return\n *         Any other return value prevents the driver from being used in\n *         this session.\n *         The core will NOT update the persistent data in storage.\n */\ntypedef psa_status_t (*psa_drv_se_init_t)(psa_drv_se_context_t *drv_context,\n                                          void *persistent_data,\n                                          psa_key_location_t location);\n\n#if defined(__DOXYGEN_ONLY__) || !defined(MBEDTLS_PSA_CRYPTO_SE_C)\n/* Mbed TLS with secure element support enabled defines this type in\n * crypto_types.h because it is also visible to applications through an\n * implementation-specific extension.\n * For the PSA Cryptography specification, this type is only visible\n * via crypto_se_driver.h. */\n/** An internal designation of a key slot between the core part of the\n * PSA Crypto implementation and the driver. The meaning of this value\n * is driver-dependent. */\ntypedef uint64_t psa_key_slot_number_t;\n#endif /* __DOXYGEN_ONLY__ || !MBEDTLS_PSA_CRYPTO_SE_C */\n\n/**@}*/\n\n/** \\defgroup se_mac Secure Element Message Authentication Codes\n * Generation and authentication of Message Authentication Codes (MACs) using\n * a secure element can be done either as a single function call (via the\n * `psa_drv_se_mac_generate_t` or `psa_drv_se_mac_verify_t` functions), or in\n * parts using the following sequence:\n * - `psa_drv_se_mac_setup_t`\n * - `psa_drv_se_mac_update_t`\n * - `psa_drv_se_mac_update_t`\n * - ...\n * - `psa_drv_se_mac_finish_t` or `psa_drv_se_mac_finish_verify_t`\n *\n * If a previously started secure element MAC operation needs to be terminated,\n * it should be done so by the `psa_drv_se_mac_abort_t`. Failure to do so may\n * result in allocated resources not being freed or in other undefined\n * behavior.\n */\n/**@{*/\n/** \\brief A function that starts a secure element  MAC operation for a PSA\n * Crypto Driver implementation\n *\n * \\param[in,out] drv_context   The driver context structure.\n * \\param[in,out] op_context    A structure that will contain the\n *                              hardware-specific MAC context\n * \\param[in] key_slot          The slot of the key to be used for the\n *                              operation\n * \\param[in] algorithm         The algorithm to be used to underly the MAC\n *                              operation\n *\n * \\retval  #PSA_SUCCESS\n *          Success.\n */\ntypedef psa_status_t (*psa_drv_se_mac_setup_t)(psa_drv_se_context_t *drv_context,\n                                               void *op_context,\n                                               psa_key_slot_number_t key_slot,\n                                               psa_algorithm_t algorithm);\n\n/** \\brief A function that continues a previously started secure element MAC\n * operation\n *\n * \\param[in,out] op_context    A hardware-specific structure for the\n *                              previously-established MAC operation to be\n *                              updated\n * \\param[in] p_input           A buffer containing the message to be appended\n *                              to the MAC operation\n * \\param[in] input_length      The size in bytes of the input message buffer\n */\ntypedef psa_status_t (*psa_drv_se_mac_update_t)(void *op_context,\n                                                const uint8_t *p_input,\n                                                size_t input_length);\n\n/** \\brief a function that completes a previously started secure element MAC\n * operation by returning the resulting MAC.\n *\n * \\param[in,out] op_context    A hardware-specific structure for the\n *                              previously started MAC operation to be\n *                              finished\n * \\param[out] p_mac            A buffer where the generated MAC will be\n *                              placed\n * \\param[in] mac_size          The size in bytes of the buffer that has been\n *                              allocated for the `output` buffer\n * \\param[out] p_mac_length     After completion, will contain the number of\n *                              bytes placed in the `p_mac` buffer\n *\n * \\retval  #PSA_SUCCESS\n *          Success.\n */\ntypedef psa_status_t (*psa_drv_se_mac_finish_t)(void *op_context,\n                                                uint8_t *p_mac,\n                                                size_t mac_size,\n                                                size_t *p_mac_length);\n\n/** \\brief A function that completes a previously started secure element MAC\n * operation by comparing the resulting MAC against a provided value\n *\n * \\param[in,out] op_context    A hardware-specific structure for the previously\n *                              started MAC operation to be finished\n * \\param[in] p_mac             The MAC value against which the resulting MAC\n *                              will be compared against\n * \\param[in] mac_length        The size in bytes of the value stored in `p_mac`\n *\n * \\retval #PSA_SUCCESS\n *         The operation completed successfully and the MACs matched each\n *         other\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The operation completed successfully, but the calculated MAC did\n *         not match the provided MAC\n */\ntypedef psa_status_t (*psa_drv_se_mac_finish_verify_t)(void *op_context,\n                                                       const uint8_t *p_mac,\n                                                       size_t mac_length);\n\n/** \\brief A function that aborts a previous started secure element MAC\n * operation\n *\n * \\param[in,out] op_context    A hardware-specific structure for the previously\n *                              started MAC operation to be aborted\n */\ntypedef psa_status_t (*psa_drv_se_mac_abort_t)(void *op_context);\n\n/** \\brief A function that performs a secure element MAC operation in one\n * command and returns the calculated MAC\n *\n * \\param[in,out] drv_context   The driver context structure.\n * \\param[in] p_input           A buffer containing the message to be MACed\n * \\param[in] input_length      The size in bytes of `p_input`\n * \\param[in] key_slot          The slot of the key to be used\n * \\param[in] alg               The algorithm to be used to underlie the MAC\n *                              operation\n * \\param[out] p_mac            A buffer where the generated MAC will be\n *                              placed\n * \\param[in] mac_size          The size in bytes of the `p_mac` buffer\n * \\param[out] p_mac_length     After completion, will contain the number of\n *                              bytes placed in the `output` buffer\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n */\ntypedef psa_status_t (*psa_drv_se_mac_generate_t)(psa_drv_se_context_t *drv_context,\n                                                  const uint8_t *p_input,\n                                                  size_t input_length,\n                                                  psa_key_slot_number_t key_slot,\n                                                  psa_algorithm_t alg,\n                                                  uint8_t *p_mac,\n                                                  size_t mac_size,\n                                                  size_t *p_mac_length);\n\n/** \\brief A function that performs a secure element MAC operation in one\n * command and compares the resulting MAC against a provided value\n *\n * \\param[in,out] drv_context       The driver context structure.\n * \\param[in] p_input       A buffer containing the message to be MACed\n * \\param[in] input_length  The size in bytes of `input`\n * \\param[in] key_slot      The slot of the key to be used\n * \\param[in] alg           The algorithm to be used to underlie the MAC\n *                          operation\n * \\param[in] p_mac         The MAC value against which the resulting MAC will\n *                          be compared against\n * \\param[in] mac_length   The size in bytes of `mac`\n *\n * \\retval #PSA_SUCCESS\n *         The operation completed successfully and the MACs matched each\n *         other\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The operation completed successfully, but the calculated MAC did\n *         not match the provided MAC\n */\ntypedef psa_status_t (*psa_drv_se_mac_verify_t)(psa_drv_se_context_t *drv_context,\n                                                const uint8_t *p_input,\n                                                size_t input_length,\n                                                psa_key_slot_number_t key_slot,\n                                                psa_algorithm_t alg,\n                                                const uint8_t *p_mac,\n                                                size_t mac_length);\n\n/** \\brief A struct containing all of the function pointers needed to\n * perform secure element MAC operations\n *\n * PSA Crypto API implementations should populate the table as appropriate\n * upon startup.\n *\n * If one of the functions is not implemented (such as\n * `psa_drv_se_mac_generate_t`), it should be set to NULL.\n *\n * Driver implementers should ensure that they implement all of the functions\n * that make sense for their hardware, and that they provide a full solution\n * (for example, if they support `p_setup`, they should also support\n * `p_update` and at least one of `p_finish` or `p_finish_verify`).\n *\n */\ntypedef struct {\n    /**The size in bytes of the hardware-specific secure element MAC context\n     * structure\n     */\n    size_t                    MBEDTLS_PRIVATE(context_size);\n    /** Function that performs a MAC setup operation\n     */\n    psa_drv_se_mac_setup_t          MBEDTLS_PRIVATE(p_setup);\n    /** Function that performs a MAC update operation\n     */\n    psa_drv_se_mac_update_t         MBEDTLS_PRIVATE(p_update);\n    /** Function that completes a MAC operation\n     */\n    psa_drv_se_mac_finish_t         MBEDTLS_PRIVATE(p_finish);\n    /** Function that completes a MAC operation with a verify check\n     */\n    psa_drv_se_mac_finish_verify_t  MBEDTLS_PRIVATE(p_finish_verify);\n    /** Function that aborts a previously started MAC operation\n     */\n    psa_drv_se_mac_abort_t          MBEDTLS_PRIVATE(p_abort);\n    /** Function that performs a MAC operation in one call\n     */\n    psa_drv_se_mac_generate_t       MBEDTLS_PRIVATE(p_mac);\n    /** Function that performs a MAC and verify operation in one call\n     */\n    psa_drv_se_mac_verify_t         MBEDTLS_PRIVATE(p_mac_verify);\n} psa_drv_se_mac_t;\n/**@}*/\n\n/** \\defgroup se_cipher Secure Element Symmetric Ciphers\n *\n * Encryption and Decryption using secure element keys in block modes other\n * than ECB must be done in multiple parts, using the following flow:\n * - `psa_drv_se_cipher_setup_t`\n * - `psa_drv_se_cipher_set_iv_t` (optional depending upon block mode)\n * - `psa_drv_se_cipher_update_t`\n * - `psa_drv_se_cipher_update_t`\n * - ...\n * - `psa_drv_se_cipher_finish_t`\n *\n * If a previously started secure element Cipher operation needs to be\n * terminated, it should be done so by the `psa_drv_se_cipher_abort_t`. Failure\n * to do so may result in allocated resources not being freed or in other\n * undefined behavior.\n *\n * In situations where a PSA Cryptographic API implementation is using a block\n * mode not-supported by the underlying hardware or driver, it can construct\n * the block mode itself, while calling the `psa_drv_se_cipher_ecb_t` function\n * for the cipher operations.\n */\n/**@{*/\n\n/** \\brief A function that provides the cipher setup function for a\n * secure element driver\n *\n * \\param[in,out] drv_context   The driver context structure.\n * \\param[in,out] op_context    A structure that will contain the\n *                              hardware-specific cipher context.\n * \\param[in] key_slot          The slot of the key to be used for the\n *                              operation\n * \\param[in] algorithm         The algorithm to be used in the cipher\n *                              operation\n * \\param[in] direction         Indicates whether the operation is an encrypt\n *                              or decrypt\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n */\ntypedef psa_status_t (*psa_drv_se_cipher_setup_t)(psa_drv_se_context_t *drv_context,\n                                                  void *op_context,\n                                                  psa_key_slot_number_t key_slot,\n                                                  psa_algorithm_t algorithm,\n                                                  psa_encrypt_or_decrypt_t direction);\n\n/** \\brief A function that sets the initialization vector (if\n * necessary) for a secure element cipher operation\n *\n * Rationale: The `psa_se_cipher_*` operation in the PSA Cryptographic API has\n * two IV functions: one to set the IV, and one to generate it internally. The\n * generate function is not necessary for the drivers to implement as the PSA\n * Crypto implementation can do the generation using its RNG features.\n *\n * \\param[in,out] op_context    A structure that contains the previously set up\n *                              hardware-specific cipher context\n * \\param[in] p_iv              A buffer containing the initialization vector\n * \\param[in] iv_length         The size (in bytes) of the `p_iv` buffer\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n */\ntypedef psa_status_t (*psa_drv_se_cipher_set_iv_t)(void *op_context,\n                                                   const uint8_t *p_iv,\n                                                   size_t iv_length);\n\n/** \\brief A function that continues a previously started secure element cipher\n * operation\n *\n * \\param[in,out] op_context        A hardware-specific structure for the\n *                                  previously started cipher operation\n * \\param[in] p_input               A buffer containing the data to be\n *                                  encrypted/decrypted\n * \\param[in] input_size            The size in bytes of the buffer pointed to\n *                                  by `p_input`\n * \\param[out] p_output             The caller-allocated buffer where the\n *                                  output will be placed\n * \\param[in] output_size           The allocated size in bytes of the\n *                                  `p_output` buffer\n * \\param[out] p_output_length      After completion, will contain the number\n *                                  of bytes placed in the `p_output` buffer\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n */\ntypedef psa_status_t (*psa_drv_se_cipher_update_t)(void *op_context,\n                                                   const uint8_t *p_input,\n                                                   size_t input_size,\n                                                   uint8_t *p_output,\n                                                   size_t output_size,\n                                                   size_t *p_output_length);\n\n/** \\brief A function that completes a previously started secure element cipher\n * operation\n *\n * \\param[in,out] op_context    A hardware-specific structure for the\n *                              previously started cipher operation\n * \\param[out] p_output         The caller-allocated buffer where the output\n *                              will be placed\n * \\param[in] output_size       The allocated size in bytes of the `p_output`\n *                              buffer\n * \\param[out] p_output_length  After completion, will contain the number of\n *                              bytes placed in the `p_output` buffer\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n */\ntypedef psa_status_t (*psa_drv_se_cipher_finish_t)(void *op_context,\n                                                   uint8_t *p_output,\n                                                   size_t output_size,\n                                                   size_t *p_output_length);\n\n/** \\brief A function that aborts a previously started secure element cipher\n * operation\n *\n * \\param[in,out] op_context    A hardware-specific structure for the\n *                              previously started cipher operation\n */\ntypedef psa_status_t (*psa_drv_se_cipher_abort_t)(void *op_context);\n\n/** \\brief A function that performs the ECB block mode for secure element\n * cipher operations\n *\n * Note: this function should only be used with implementations that do not\n * provide a needed higher-level operation.\n *\n * \\param[in,out] drv_context   The driver context structure.\n * \\param[in] key_slot          The slot of the key to be used for the operation\n * \\param[in] algorithm         The algorithm to be used in the cipher operation\n * \\param[in] direction         Indicates whether the operation is an encrypt or\n *                              decrypt\n * \\param[in] p_input           A buffer containing the data to be\n *                              encrypted/decrypted\n * \\param[in] input_size        The size in bytes of the buffer pointed to by\n *                              `p_input`\n * \\param[out] p_output         The caller-allocated buffer where the output\n *                              will be placed\n * \\param[in] output_size       The allocated size in bytes of the `p_output`\n *                              buffer\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n */\ntypedef psa_status_t (*psa_drv_se_cipher_ecb_t)(psa_drv_se_context_t *drv_context,\n                                                psa_key_slot_number_t key_slot,\n                                                psa_algorithm_t algorithm,\n                                                psa_encrypt_or_decrypt_t direction,\n                                                const uint8_t *p_input,\n                                                size_t input_size,\n                                                uint8_t *p_output,\n                                                size_t output_size);\n\n/**\n * \\brief A struct containing all of the function pointers needed to implement\n * cipher operations using secure elements.\n *\n * PSA Crypto API implementations should populate instances of the table as\n * appropriate upon startup or at build time.\n *\n * If one of the functions is not implemented (such as\n * `psa_drv_se_cipher_ecb_t`), it should be set to NULL.\n */\ntypedef struct {\n    /** The size in bytes of the hardware-specific secure element cipher\n     * context structure\n     */\n    size_t               MBEDTLS_PRIVATE(context_size);\n    /** Function that performs a cipher setup operation */\n    psa_drv_se_cipher_setup_t  MBEDTLS_PRIVATE(p_setup);\n    /** Function that sets a cipher IV (if necessary) */\n    psa_drv_se_cipher_set_iv_t MBEDTLS_PRIVATE(p_set_iv);\n    /** Function that performs a cipher update operation */\n    psa_drv_se_cipher_update_t MBEDTLS_PRIVATE(p_update);\n    /** Function that completes a cipher operation */\n    psa_drv_se_cipher_finish_t MBEDTLS_PRIVATE(p_finish);\n    /** Function that aborts a cipher operation */\n    psa_drv_se_cipher_abort_t  MBEDTLS_PRIVATE(p_abort);\n    /** Function that performs ECB mode for a cipher operation\n     * (Danger: ECB mode should not be used directly by clients of the PSA\n     * Crypto Client API)\n     */\n    psa_drv_se_cipher_ecb_t    MBEDTLS_PRIVATE(p_ecb);\n} psa_drv_se_cipher_t;\n\n/**@}*/\n\n/** \\defgroup se_asymmetric Secure Element Asymmetric Cryptography\n *\n * Since the amount of data that can (or should) be encrypted or signed using\n * asymmetric keys is limited by the key size, asymmetric key operations using\n * keys in a secure element must be done in single function calls.\n */\n/**@{*/\n\n/**\n * \\brief A function that signs a hash or short message with a private key in\n * a secure element\n *\n * \\param[in,out] drv_context       The driver context structure.\n * \\param[in] key_slot              Key slot of an asymmetric key pair\n * \\param[in] alg                   A signature algorithm that is compatible\n *                                  with the type of `key`\n * \\param[in] p_hash                The hash to sign\n * \\param[in] hash_length           Size of the `p_hash` buffer in bytes\n * \\param[out] p_signature          Buffer where the signature is to be written\n * \\param[in] signature_size        Size of the `p_signature` buffer in bytes\n * \\param[out] p_signature_length   On success, the number of bytes\n *                                  that make up the returned signature value\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n */\ntypedef psa_status_t (*psa_drv_se_asymmetric_sign_t)(psa_drv_se_context_t *drv_context,\n                                                     psa_key_slot_number_t key_slot,\n                                                     psa_algorithm_t alg,\n                                                     const uint8_t *p_hash,\n                                                     size_t hash_length,\n                                                     uint8_t *p_signature,\n                                                     size_t signature_size,\n                                                     size_t *p_signature_length);\n\n/**\n * \\brief A function that verifies the signature a hash or short message using\n * an asymmetric public key in a secure element\n *\n * \\param[in,out] drv_context   The driver context structure.\n * \\param[in] key_slot          Key slot of a public key or an asymmetric key\n *                              pair\n * \\param[in] alg               A signature algorithm that is compatible with\n *                              the type of `key`\n * \\param[in] p_hash            The hash whose signature is to be verified\n * \\param[in] hash_length       Size of the `p_hash` buffer in bytes\n * \\param[in] p_signature       Buffer containing the signature to verify\n * \\param[in] signature_length  Size of the `p_signature` buffer in bytes\n *\n * \\retval #PSA_SUCCESS\n *         The signature is valid.\n */\ntypedef psa_status_t (*psa_drv_se_asymmetric_verify_t)(psa_drv_se_context_t *drv_context,\n                                                       psa_key_slot_number_t key_slot,\n                                                       psa_algorithm_t alg,\n                                                       const uint8_t *p_hash,\n                                                       size_t hash_length,\n                                                       const uint8_t *p_signature,\n                                                       size_t signature_length);\n\n/**\n * \\brief A function that encrypts a short message with an asymmetric public\n * key in a secure element\n *\n * \\param[in,out] drv_context   The driver context structure.\n * \\param[in] key_slot          Key slot of a public key or an asymmetric key\n *                              pair\n * \\param[in] alg               An asymmetric encryption algorithm that is\n *                              compatible with the type of `key`\n * \\param[in] p_input           The message to encrypt\n * \\param[in] input_length      Size of the `p_input` buffer in bytes\n * \\param[in] p_salt            A salt or label, if supported by the\n *                              encryption algorithm\n *                              If the algorithm does not support a\n *                              salt, pass `NULL`.\n *                              If the algorithm supports an optional\n *                              salt and you do not want to pass a salt,\n *                              pass `NULL`.\n *                              For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is\n *                              supported.\n * \\param[in] salt_length       Size of the `p_salt` buffer in bytes\n *                              If `p_salt` is `NULL`, pass 0.\n * \\param[out] p_output         Buffer where the encrypted message is to\n *                              be written\n * \\param[in] output_size       Size of the `p_output` buffer in bytes\n * \\param[out] p_output_length  On success, the number of bytes that make up\n *                              the returned output\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n */\ntypedef psa_status_t (*psa_drv_se_asymmetric_encrypt_t)(psa_drv_se_context_t *drv_context,\n                                                        psa_key_slot_number_t key_slot,\n                                                        psa_algorithm_t alg,\n                                                        const uint8_t *p_input,\n                                                        size_t input_length,\n                                                        const uint8_t *p_salt,\n                                                        size_t salt_length,\n                                                        uint8_t *p_output,\n                                                        size_t output_size,\n                                                        size_t *p_output_length);\n\n/**\n * \\brief A function that decrypts a short message with an asymmetric private\n * key in a secure element.\n *\n * \\param[in,out] drv_context   The driver context structure.\n * \\param[in] key_slot          Key slot of an asymmetric key pair\n * \\param[in] alg               An asymmetric encryption algorithm that is\n *                              compatible with the type of `key`\n * \\param[in] p_input           The message to decrypt\n * \\param[in] input_length      Size of the `p_input` buffer in bytes\n * \\param[in] p_salt            A salt or label, if supported by the\n *                              encryption algorithm\n *                              If the algorithm does not support a\n *                              salt, pass `NULL`.\n *                              If the algorithm supports an optional\n *                              salt and you do not want to pass a salt,\n *                              pass `NULL`.\n *                              For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is\n *                              supported.\n * \\param[in] salt_length       Size of the `p_salt` buffer in bytes\n *                              If `p_salt` is `NULL`, pass 0.\n * \\param[out] p_output         Buffer where the decrypted message is to\n *                              be written\n * \\param[in] output_size       Size of the `p_output` buffer in bytes\n * \\param[out] p_output_length  On success, the number of bytes\n *                              that make up the returned output\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n */\ntypedef psa_status_t (*psa_drv_se_asymmetric_decrypt_t)(psa_drv_se_context_t *drv_context,\n                                                        psa_key_slot_number_t key_slot,\n                                                        psa_algorithm_t alg,\n                                                        const uint8_t *p_input,\n                                                        size_t input_length,\n                                                        const uint8_t *p_salt,\n                                                        size_t salt_length,\n                                                        uint8_t *p_output,\n                                                        size_t output_size,\n                                                        size_t *p_output_length);\n\n/**\n * \\brief A struct containing all of the function pointers needed to implement\n * asymmetric cryptographic operations using secure elements.\n *\n * PSA Crypto API implementations should populate instances of the table as\n * appropriate upon startup or at build time.\n *\n * If one of the functions is not implemented, it should be set to NULL.\n */\ntypedef struct {\n    /** Function that performs an asymmetric sign operation */\n    psa_drv_se_asymmetric_sign_t    MBEDTLS_PRIVATE(p_sign);\n    /** Function that performs an asymmetric verify operation */\n    psa_drv_se_asymmetric_verify_t  MBEDTLS_PRIVATE(p_verify);\n    /** Function that performs an asymmetric encrypt operation */\n    psa_drv_se_asymmetric_encrypt_t MBEDTLS_PRIVATE(p_encrypt);\n    /** Function that performs an asymmetric decrypt operation */\n    psa_drv_se_asymmetric_decrypt_t MBEDTLS_PRIVATE(p_decrypt);\n} psa_drv_se_asymmetric_t;\n\n/**@}*/\n\n/** \\defgroup se_aead Secure Element Authenticated Encryption with Additional Data\n * Authenticated Encryption with Additional Data (AEAD) operations with secure\n * elements must be done in one function call. While this creates a burden for\n * implementers as there must be sufficient space in memory for the entire\n * message, it prevents decrypted data from being made available before the\n * authentication operation is complete and the data is known to be authentic.\n */\n/**@{*/\n\n/** \\brief A function that performs a secure element authenticated encryption\n * operation\n *\n * \\param[in,out] drv_context           The driver context structure.\n * \\param[in] key_slot                  Slot containing the key to use.\n * \\param[in] algorithm                 The AEAD algorithm to compute\n *                                      (\\c PSA_ALG_XXX value such that\n *                                      #PSA_ALG_IS_AEAD(`alg`) is true)\n * \\param[in] p_nonce                   Nonce or IV to use\n * \\param[in] nonce_length              Size of the `p_nonce` buffer in bytes\n * \\param[in] p_additional_data         Additional data that will be\n *                                      authenticated but not encrypted\n * \\param[in] additional_data_length    Size of `p_additional_data` in bytes\n * \\param[in] p_plaintext               Data that will be authenticated and\n *                                      encrypted\n * \\param[in] plaintext_length          Size of `p_plaintext` in bytes\n * \\param[out] p_ciphertext             Output buffer for the authenticated and\n *                                      encrypted data. The additional data is\n *                                      not part of this output. For algorithms\n *                                      where the encrypted data and the\n *                                      authentication tag are defined as\n *                                      separate outputs, the authentication\n *                                      tag is appended to the encrypted data.\n * \\param[in] ciphertext_size           Size of the `p_ciphertext` buffer in\n *                                      bytes\n * \\param[out] p_ciphertext_length      On success, the size of the output in\n *                                      the `p_ciphertext` buffer\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n */\ntypedef psa_status_t (*psa_drv_se_aead_encrypt_t)(psa_drv_se_context_t *drv_context,\n                                                  psa_key_slot_number_t key_slot,\n                                                  psa_algorithm_t algorithm,\n                                                  const uint8_t *p_nonce,\n                                                  size_t nonce_length,\n                                                  const uint8_t *p_additional_data,\n                                                  size_t additional_data_length,\n                                                  const uint8_t *p_plaintext,\n                                                  size_t plaintext_length,\n                                                  uint8_t *p_ciphertext,\n                                                  size_t ciphertext_size,\n                                                  size_t *p_ciphertext_length);\n\n/** A function that performs a secure element authenticated decryption operation\n *\n * \\param[in,out] drv_context           The driver context structure.\n * \\param[in] key_slot                  Slot containing the key to use\n * \\param[in] algorithm                 The AEAD algorithm to compute\n *                                      (\\c PSA_ALG_XXX value such that\n *                                      #PSA_ALG_IS_AEAD(`alg`) is true)\n * \\param[in] p_nonce                   Nonce or IV to use\n * \\param[in] nonce_length              Size of the `p_nonce` buffer in bytes\n * \\param[in] p_additional_data         Additional data that has been\n *                                      authenticated but not encrypted\n * \\param[in] additional_data_length    Size of `p_additional_data` in bytes\n * \\param[in] p_ciphertext              Data that has been authenticated and\n *                                      encrypted.\n *                                      For algorithms where the encrypted data\n *                                      and the authentication tag are defined\n *                                      as separate inputs, the buffer must\n *                                      contain the encrypted data followed by\n *                                      the authentication tag.\n * \\param[in] ciphertext_length         Size of `p_ciphertext` in bytes\n * \\param[out] p_plaintext              Output buffer for the decrypted data\n * \\param[in] plaintext_size            Size of the `p_plaintext` buffer in\n *                                      bytes\n * \\param[out] p_plaintext_length       On success, the size of the output in\n *                                      the `p_plaintext` buffer\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n */\ntypedef psa_status_t (*psa_drv_se_aead_decrypt_t)(psa_drv_se_context_t *drv_context,\n                                                  psa_key_slot_number_t key_slot,\n                                                  psa_algorithm_t algorithm,\n                                                  const uint8_t *p_nonce,\n                                                  size_t nonce_length,\n                                                  const uint8_t *p_additional_data,\n                                                  size_t additional_data_length,\n                                                  const uint8_t *p_ciphertext,\n                                                  size_t ciphertext_length,\n                                                  uint8_t *p_plaintext,\n                                                  size_t plaintext_size,\n                                                  size_t *p_plaintext_length);\n\n/**\n * \\brief A struct containing all of the function pointers needed to implement\n * secure element Authenticated Encryption with Additional Data operations\n *\n * PSA Crypto API implementations should populate instances of the table as\n * appropriate upon startup.\n *\n * If one of the functions is not implemented, it should be set to NULL.\n */\ntypedef struct {\n    /** Function that performs the AEAD encrypt operation */\n    psa_drv_se_aead_encrypt_t MBEDTLS_PRIVATE(p_encrypt);\n    /** Function that performs the AEAD decrypt operation */\n    psa_drv_se_aead_decrypt_t MBEDTLS_PRIVATE(p_decrypt);\n} psa_drv_se_aead_t;\n/**@}*/\n\n/** \\defgroup se_key_management Secure Element Key Management\n * Currently, key management is limited to importing keys in the clear,\n * destroying keys, and exporting keys in the clear.\n * Whether a key may be exported is determined by the key policies in place\n * on the key slot.\n */\n/**@{*/\n\n/** An enumeration indicating how a key is created.\n */\ntypedef enum {\n    PSA_KEY_CREATION_IMPORT, /**< During psa_import_key() */\n    PSA_KEY_CREATION_GENERATE, /**< During psa_generate_key() */\n    PSA_KEY_CREATION_DERIVE, /**< During psa_key_derivation_output_key() */\n    PSA_KEY_CREATION_COPY, /**< During psa_copy_key() */\n\n#ifndef __DOXYGEN_ONLY__\n    /** A key is being registered with mbedtls_psa_register_se_key().\n     *\n     * The core only passes this value to\n     * psa_drv_se_key_management_t::p_validate_slot_number, not to\n     * psa_drv_se_key_management_t::p_allocate. The call to\n     * `p_validate_slot_number` is not followed by any other call to the\n     * driver: the key is considered successfully registered if the call to\n     * `p_validate_slot_number` succeeds, or if `p_validate_slot_number` is\n     * null.\n     *\n     * With this creation method, the driver must return #PSA_SUCCESS if\n     * the given attributes are compatible with the existing key in the slot,\n     * and #PSA_ERROR_DOES_NOT_EXIST if the driver can determine that there\n     * is no key with the specified slot number.\n     *\n     * This is an Mbed TLS extension.\n     */\n    PSA_KEY_CREATION_REGISTER,\n#endif\n} psa_key_creation_method_t;\n\n/** \\brief A function that allocates a slot for a key.\n *\n * To create a key in a specific slot in a secure element, the core\n * first calls this function to determine a valid slot number,\n * then calls a function to create the key material in that slot.\n * In nominal conditions (that is, if no error occurs),\n * the effect of a call to a key creation function in the PSA Cryptography\n * API with a lifetime that places the key in a secure element is the\n * following:\n * -# The core calls psa_drv_se_key_management_t::p_allocate\n *    (or in some implementations\n *    psa_drv_se_key_management_t::p_validate_slot_number). The driver\n *    selects (or validates) a suitable slot number given the key attributes\n *    and the state of the secure element.\n * -# The core calls a key creation function in the driver.\n *\n * The key creation functions in the PSA Cryptography API are:\n * - psa_import_key(), which causes\n *   a call to `p_allocate` with \\p method = #PSA_KEY_CREATION_IMPORT\n *   then a call to psa_drv_se_key_management_t::p_import.\n * - psa_generate_key(), which causes\n *   a call to `p_allocate` with \\p method = #PSA_KEY_CREATION_GENERATE\n *   then a call to psa_drv_se_key_management_t::p_import.\n * - psa_key_derivation_output_key(), which causes\n *   a call to `p_allocate` with \\p method = #PSA_KEY_CREATION_DERIVE\n *   then a call to psa_drv_se_key_derivation_t::p_derive.\n * - psa_copy_key(), which causes\n *   a call to `p_allocate` with \\p method = #PSA_KEY_CREATION_COPY\n *   then a call to psa_drv_se_key_management_t::p_export.\n *\n * In case of errors, other behaviors are possible.\n * - If the PSA Cryptography subsystem dies after the first step,\n *   for example because the device has lost power abruptly,\n *   the second step may never happen, or may happen after a reset\n *   and re-initialization. Alternatively, after a reset and\n *   re-initialization, the core may call\n *   psa_drv_se_key_management_t::p_destroy on the slot number that\n *   was allocated (or validated) instead of calling a key creation function.\n * - If an error occurs, the core may call\n *   psa_drv_se_key_management_t::p_destroy on the slot number that\n *   was allocated (or validated) instead of calling a key creation function.\n *\n * Errors and system resets also have an impact on the driver's persistent\n * data. If a reset happens before the overall key creation process is\n * completed (before or after the second step above), it is unspecified\n * whether the persistent data after the reset is identical to what it\n * was before or after the call to `p_allocate` (or `p_validate_slot_number`).\n *\n * \\param[in,out] drv_context       The driver context structure.\n * \\param[in,out] persistent_data   A pointer to the persistent data\n *                                  that allows writing.\n * \\param[in] attributes            Attributes of the key.\n * \\param method                    The way in which the key is being created.\n * \\param[out] key_slot             Slot where the key will be stored.\n *                                  This must be a valid slot for a key of the\n *                                  chosen type. It must be unoccupied.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n *         The core will record \\c *key_slot as the key slot where the key\n *         is stored and will update the persistent data in storage.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n */\ntypedef psa_status_t (*psa_drv_se_allocate_key_t)(\n    psa_drv_se_context_t *drv_context,\n    void *persistent_data,\n    const psa_key_attributes_t *attributes,\n    psa_key_creation_method_t method,\n    psa_key_slot_number_t *key_slot);\n\n/** \\brief A function that determines whether a slot number is valid\n * for a key.\n *\n * To create a key in a specific slot in a secure element, the core\n * first calls this function to validate the choice of slot number,\n * then calls a function to create the key material in that slot.\n * See the documentation of #psa_drv_se_allocate_key_t for more details.\n *\n * As of the PSA Cryptography API specification version 1.0, there is no way\n * for applications to trigger a call to this function. However some\n * implementations offer the capability to create or declare a key in\n * a specific slot via implementation-specific means, generally for the\n * sake of initial device provisioning or onboarding. Such a mechanism may\n * be added to a future version of the PSA Cryptography API specification.\n *\n * This function may update the driver's persistent data through\n * \\p persistent_data. The core will save the updated persistent data at the\n * end of the key creation process. See the description of\n * ::psa_drv_se_allocate_key_t for more information.\n *\n * \\param[in,out] drv_context   The driver context structure.\n * \\param[in,out] persistent_data   A pointer to the persistent data\n *                                  that allows writing.\n * \\param[in] attributes        Attributes of the key.\n * \\param method                The way in which the key is being created.\n * \\param[in] key_slot          Slot where the key is to be stored.\n *\n * \\retval #PSA_SUCCESS\n *         The given slot number is valid for a key with the given\n *         attributes.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The given slot number is not valid for a key with the\n *         given attributes. This includes the case where the slot\n *         number is not valid at all.\n * \\retval #PSA_ERROR_ALREADY_EXISTS\n *         There is already a key with the specified slot number.\n *         Drivers may choose to return this error from the key\n *         creation function instead.\n */\ntypedef psa_status_t (*psa_drv_se_validate_slot_number_t)(\n    psa_drv_se_context_t *drv_context,\n    void *persistent_data,\n    const psa_key_attributes_t *attributes,\n    psa_key_creation_method_t method,\n    psa_key_slot_number_t key_slot);\n\n/** \\brief A function that imports a key into a secure element in binary format\n *\n * This function can support any output from psa_export_key(). Refer to the\n * documentation of psa_export_key() for the format for each key type.\n *\n * \\param[in,out] drv_context   The driver context structure.\n * \\param key_slot              Slot where the key will be stored.\n *                              This must be a valid slot for a key of the\n *                              chosen type. It must be unoccupied.\n * \\param[in] attributes        The key attributes, including the lifetime,\n *                              the key type and the usage policy.\n *                              Drivers should not access the key size stored\n *                              in the attributes: it may not match the\n *                              data passed in \\p data.\n *                              Drivers can call psa_get_key_lifetime(),\n *                              psa_get_key_type(),\n *                              psa_get_key_usage_flags() and\n *                              psa_get_key_algorithm() to access this\n *                              information.\n * \\param[in] data              Buffer containing the key data.\n * \\param[in] data_length       Size of the \\p data buffer in bytes.\n * \\param[out] bits             On success, the key size in bits. The driver\n *                              must determine this value after parsing the\n *                              key according to the key type.\n *                              This value is not used if the function fails.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n */\ntypedef psa_status_t (*psa_drv_se_import_key_t)(\n    psa_drv_se_context_t *drv_context,\n    psa_key_slot_number_t key_slot,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *data,\n    size_t data_length,\n    size_t *bits);\n\n/**\n * \\brief A function that destroys a secure element key and restore the slot to\n * its default state\n *\n * This function destroys the content of the key from a secure element.\n * Implementations shall make a best effort to ensure that any previous content\n * of the slot is unrecoverable.\n *\n * This function returns the specified slot to its default state.\n *\n * \\param[in,out] drv_context       The driver context structure.\n * \\param[in,out] persistent_data   A pointer to the persistent data\n *                                  that allows writing.\n * \\param key_slot                  The key slot to erase.\n *\n * \\retval #PSA_SUCCESS\n *         The slot's content, if any, has been erased.\n */\ntypedef psa_status_t (*psa_drv_se_destroy_key_t)(\n    psa_drv_se_context_t *drv_context,\n    void *persistent_data,\n    psa_key_slot_number_t key_slot);\n\n/**\n * \\brief A function that exports a secure element key in binary format\n *\n * The output of this function can be passed to psa_import_key() to\n * create an equivalent object.\n *\n * If a key is created with `psa_import_key()` and then exported with\n * this function, it is not guaranteed that the resulting data is\n * identical: the implementation may choose a different representation\n * of the same key if the format permits it.\n *\n * This function should generate output in the same format that\n * `psa_export_key()` does. Refer to the\n * documentation of `psa_export_key()` for the format for each key type.\n *\n * \\param[in,out] drv_context   The driver context structure.\n * \\param[in] key               Slot whose content is to be exported. This must\n *                              be an occupied key slot.\n * \\param[out] p_data           Buffer where the key data is to be written.\n * \\param[in] data_size         Size of the `p_data` buffer in bytes.\n * \\param[out] p_data_length    On success, the number of bytes\n *                              that make up the key data.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_DOES_NOT_EXIST \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\ntypedef psa_status_t (*psa_drv_se_export_key_t)(psa_drv_se_context_t *drv_context,\n                                                psa_key_slot_number_t key,\n                                                uint8_t *p_data,\n                                                size_t data_size,\n                                                size_t *p_data_length);\n\n/**\n * \\brief A function that generates a symmetric or asymmetric key on a secure\n * element\n *\n * If the key type \\c type recorded in \\p attributes\n * is asymmetric (#PSA_KEY_TYPE_IS_ASYMMETRIC(\\c type) = 1),\n * the driver may export the public key at the time of generation,\n * in the format documented for psa_export_public_key() by writing it\n * to the \\p pubkey buffer.\n * This is optional, intended for secure elements that output the\n * public key at generation time and that cannot export the public key\n * later. Drivers that do not need this feature should leave\n * \\p *pubkey_length set to 0 and should\n * implement the psa_drv_key_management_t::p_export_public function.\n * Some implementations do not support this feature, in which case\n * \\p pubkey is \\c NULL and \\p pubkey_size is 0.\n *\n * \\param[in,out] drv_context   The driver context structure.\n * \\param key_slot              Slot where the key will be stored.\n *                              This must be a valid slot for a key of the\n *                              chosen type. It must be unoccupied.\n * \\param[in] attributes        The key attributes, including the lifetime,\n *                              the key type and size, and the usage policy.\n *                              Drivers can call psa_get_key_lifetime(),\n *                              psa_get_key_type(), psa_get_key_bits(),\n *                              psa_get_key_usage_flags() and\n *                              psa_get_key_algorithm() to access this\n *                              information.\n * \\param[out] pubkey           A buffer where the driver can write the\n *                              public key, when generating an asymmetric\n *                              key pair.\n *                              This is \\c NULL when generating a symmetric\n *                              key or if the core does not support\n *                              exporting the public key at generation time.\n * \\param pubkey_size           The size of the `pubkey` buffer in bytes.\n *                              This is 0 when generating a symmetric\n *                              key or if the core does not support\n *                              exporting the public key at generation time.\n * \\param[out] pubkey_length    On entry, this is always 0.\n *                              On success, the number of bytes written to\n *                              \\p pubkey. If this is 0 or unchanged on return,\n *                              the core will not read the \\p pubkey buffer,\n *                              and will instead call the driver's\n *                              psa_drv_key_management_t::p_export_public\n *                              function to export the public key when needed.\n */\ntypedef psa_status_t (*psa_drv_se_generate_key_t)(\n    psa_drv_se_context_t *drv_context,\n    psa_key_slot_number_t key_slot,\n    const psa_key_attributes_t *attributes,\n    uint8_t *pubkey, size_t pubkey_size, size_t *pubkey_length);\n\n/**\n * \\brief A struct containing all of the function pointers needed to for secure\n * element key management\n *\n * PSA Crypto API implementations should populate instances of the table as\n * appropriate upon startup or at build time.\n *\n * If one of the functions is not implemented, it should be set to NULL.\n */\ntypedef struct {\n    /** Function that allocates a slot for a key. */\n    psa_drv_se_allocate_key_t   MBEDTLS_PRIVATE(p_allocate);\n    /** Function that checks the validity of a slot for a key. */\n    psa_drv_se_validate_slot_number_t MBEDTLS_PRIVATE(p_validate_slot_number);\n    /** Function that performs a key import operation */\n    psa_drv_se_import_key_t     MBEDTLS_PRIVATE(p_import);\n    /** Function that performs a generation */\n    psa_drv_se_generate_key_t   MBEDTLS_PRIVATE(p_generate);\n    /** Function that performs a key destroy operation */\n    psa_drv_se_destroy_key_t    MBEDTLS_PRIVATE(p_destroy);\n    /** Function that performs a key export operation */\n    psa_drv_se_export_key_t     MBEDTLS_PRIVATE(p_export);\n    /** Function that performs a public key export operation */\n    psa_drv_se_export_key_t     MBEDTLS_PRIVATE(p_export_public);\n} psa_drv_se_key_management_t;\n\n/**@}*/\n\n/** \\defgroup driver_derivation Secure Element Key Derivation and Agreement\n * Key derivation is the process of generating new key material using an\n * existing key and additional parameters, iterating through a basic\n * cryptographic function, such as a hash.\n * Key agreement is a part of cryptographic protocols that allows two parties\n * to agree on the same key value, but starting from different original key\n * material.\n * The flows are similar, and the PSA Crypto Driver Model uses the same functions\n * for both of the flows.\n *\n * There are two different final functions for the flows,\n * `psa_drv_se_key_derivation_derive` and `psa_drv_se_key_derivation_export`.\n * `psa_drv_se_key_derivation_derive` is used when the key material should be\n * placed in a slot on the hardware and not exposed to the caller.\n * `psa_drv_se_key_derivation_export` is used when the key material should be\n * returned to the PSA Cryptographic API implementation.\n *\n * Different key derivation algorithms require a different number of inputs.\n * Instead of having an API that takes as input variable length arrays, which\n * can be problematic to manage on embedded platforms, the inputs are passed\n * to the driver via a function, `psa_drv_se_key_derivation_collateral`, that\n * is called multiple times with different `collateral_id`s. Thus, for a key\n * derivation algorithm that required 3 parameter inputs, the flow would look\n * something like:\n * ~~~~~~~~~~~~~{.c}\n * psa_drv_se_key_derivation_setup(kdf_algorithm, source_key, dest_key_size_bytes);\n * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_0,\n *                                      p_collateral_0,\n *                                      collateral_0_size);\n * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_1,\n *                                      p_collateral_1,\n *                                      collateral_1_size);\n * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_2,\n *                                      p_collateral_2,\n *                                      collateral_2_size);\n * psa_drv_se_key_derivation_derive();\n * ~~~~~~~~~~~~~\n *\n * key agreement example:\n * ~~~~~~~~~~~~~{.c}\n * psa_drv_se_key_derivation_setup(alg, source_key. dest_key_size_bytes);\n * psa_drv_se_key_derivation_collateral(DHE_PUBKEY, p_pubkey, pubkey_size);\n * psa_drv_se_key_derivation_export(p_session_key,\n *                                  session_key_size,\n *                                  &session_key_length);\n * ~~~~~~~~~~~~~\n */\n/**@{*/\n\n/** \\brief A function that Sets up a secure element key derivation operation by\n * specifying the algorithm and the source key sot\n *\n * \\param[in,out] drv_context   The driver context structure.\n * \\param[in,out] op_context    A hardware-specific structure containing any\n *                              context information for the implementation\n * \\param[in] kdf_alg           The algorithm to be used for the key derivation\n * \\param[in] source_key        The key to be used as the source material for\n *                              the key derivation\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n */\ntypedef psa_status_t (*psa_drv_se_key_derivation_setup_t)(psa_drv_se_context_t *drv_context,\n                                                          void *op_context,\n                                                          psa_algorithm_t kdf_alg,\n                                                          psa_key_slot_number_t source_key);\n\n/** \\brief A function that provides collateral (parameters) needed for a secure\n * element key derivation or key agreement operation\n *\n * Since many key derivation algorithms require multiple parameters, it is\n * expected that this function may be called multiple times for the same\n * operation, each with a different algorithm-specific `collateral_id`\n *\n * \\param[in,out] op_context    A hardware-specific structure containing any\n *                              context information for the implementation\n * \\param[in] collateral_id     An ID for the collateral being provided\n * \\param[in] p_collateral      A buffer containing the collateral data\n * \\param[in] collateral_size   The size in bytes of the collateral\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n */\ntypedef psa_status_t (*psa_drv_se_key_derivation_collateral_t)(void *op_context,\n                                                               uint32_t collateral_id,\n                                                               const uint8_t *p_collateral,\n                                                               size_t collateral_size);\n\n/** \\brief A function that performs the final secure element key derivation\n * step and place the generated key material in a slot\n *\n * \\param[in,out] op_context    A hardware-specific structure containing any\n *                              context information for the implementation\n * \\param[in] dest_key          The slot where the generated key material\n *                              should be placed\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n */\ntypedef psa_status_t (*psa_drv_se_key_derivation_derive_t)(void *op_context,\n                                                           psa_key_slot_number_t dest_key);\n\n/** \\brief A function that performs the final step of a secure element key\n * agreement and place the generated key material in a buffer\n *\n * \\param[out] p_output         Buffer in which to place the generated key\n *                              material\n * \\param[in] output_size       The size in bytes of `p_output`\n * \\param[out] p_output_length  Upon success, contains the number of bytes of\n *                              key material placed in `p_output`\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n */\ntypedef psa_status_t (*psa_drv_se_key_derivation_export_t)(void *op_context,\n                                                           uint8_t *p_output,\n                                                           size_t output_size,\n                                                           size_t *p_output_length);\n\n/**\n * \\brief A struct containing all of the function pointers needed to for secure\n * element key derivation and agreement\n *\n * PSA Crypto API implementations should populate instances of the table as\n * appropriate upon startup.\n *\n * If one of the functions is not implemented, it should be set to NULL.\n */\ntypedef struct {\n    /** The driver-specific size of the key derivation context */\n    size_t                           MBEDTLS_PRIVATE(context_size);\n    /** Function that performs a key derivation setup */\n    psa_drv_se_key_derivation_setup_t      MBEDTLS_PRIVATE(p_setup);\n    /** Function that sets key derivation collateral */\n    psa_drv_se_key_derivation_collateral_t MBEDTLS_PRIVATE(p_collateral);\n    /** Function that performs a final key derivation step */\n    psa_drv_se_key_derivation_derive_t     MBEDTLS_PRIVATE(p_derive);\n    /** Function that performs a final key derivation or agreement and\n     * exports the key */\n    psa_drv_se_key_derivation_export_t     MBEDTLS_PRIVATE(p_export);\n} psa_drv_se_key_derivation_t;\n\n/**@}*/\n\n/** \\defgroup se_registration Secure element driver registration\n */\n/**@{*/\n\n/** A structure containing pointers to all the entry points of a\n * secure element driver.\n *\n * Future versions of this specification may add extra substructures at\n * the end of this structure.\n */\ntypedef struct {\n    /** The version of the driver HAL that this driver implements.\n     * This is a protection against loading driver binaries built against\n     * a different version of this specification.\n     * Use #PSA_DRV_SE_HAL_VERSION.\n     */\n    uint32_t MBEDTLS_PRIVATE(hal_version);\n\n    /** The size of the driver's persistent data in bytes.\n     *\n     * This can be 0 if the driver does not need persistent data.\n     *\n     * See the documentation of psa_drv_se_context_t::persistent_data\n     * for more information about why and how a driver can use\n     * persistent data.\n     */\n    size_t MBEDTLS_PRIVATE(persistent_data_size);\n\n    /** The driver initialization function.\n     *\n     * This function is called once during the initialization of the\n     * PSA Cryptography subsystem, before any other function of the\n     * driver is called. If this function returns a failure status,\n     * the driver will be unusable, at least until the next system reset.\n     *\n     * If this field is \\c NULL, it is equivalent to a function that does\n     * nothing and returns #PSA_SUCCESS.\n     */\n    psa_drv_se_init_t MBEDTLS_PRIVATE(p_init);\n\n    const psa_drv_se_key_management_t *MBEDTLS_PRIVATE(key_management);\n    const psa_drv_se_mac_t *MBEDTLS_PRIVATE(mac);\n    const psa_drv_se_cipher_t *MBEDTLS_PRIVATE(cipher);\n    const psa_drv_se_aead_t *MBEDTLS_PRIVATE(aead);\n    const psa_drv_se_asymmetric_t *MBEDTLS_PRIVATE(asymmetric);\n    const psa_drv_se_key_derivation_t *MBEDTLS_PRIVATE(derivation);\n} psa_drv_se_t;\n\n/** The current version of the secure element driver HAL.\n */\n/* 0.0.0 patchlevel 5 */\n#define PSA_DRV_SE_HAL_VERSION 0x00000005\n\n/** Register an external cryptoprocessor (secure element) driver.\n *\n * This function is only intended to be used by driver code, not by\n * application code. In implementations with separation between the\n * PSA cryptography module and applications, this function should\n * only be available to callers that run in the same memory space as\n * the cryptography module, and should not be exposed to applications\n * running in a different memory space.\n *\n * This function may be called before psa_crypto_init(). It is\n * implementation-defined whether this function may be called\n * after psa_crypto_init().\n *\n * \\note Implementations store metadata about keys including the lifetime\n *       value, which contains the driver's location indicator. Therefore,\n *       from one instantiation of the PSA Cryptography\n *       library to the next one, if there is a key in storage with a certain\n *       lifetime value, you must always register the same driver (or an\n *       updated version that communicates with the same secure element)\n *       with the same location value.\n *\n * \\param location      The location value through which this driver will\n *                      be exposed to applications.\n *                      This driver will be used for all keys such that\n *                      `location == #PSA_KEY_LIFETIME_GET_LOCATION( lifetime )`.\n *                      The value #PSA_KEY_LOCATION_LOCAL_STORAGE is reserved\n *                      and may not be used for drivers. Implementations\n *                      may reserve other values.\n * \\param[in] methods   The method table of the driver. This structure must\n *                      remain valid for as long as the cryptography\n *                      module keeps running. It is typically a global\n *                      constant.\n *\n * \\return #PSA_SUCCESS\n *         The driver was successfully registered. Applications can now\n *         use \\p location to access keys through the methods passed to\n *         this function.\n * \\return #PSA_ERROR_BAD_STATE\n *         This function was called after the initialization of the\n *         cryptography module, and this implementation does not support\n *         driver registration at this stage.\n * \\return #PSA_ERROR_ALREADY_EXISTS\n *         There is already a registered driver for this value of \\p location.\n * \\return #PSA_ERROR_INVALID_ARGUMENT\n *         \\p location is a reserved value.\n * \\return #PSA_ERROR_NOT_SUPPORTED\n *         `methods->hal_version` is not supported by this implementation.\n * \\return #PSA_ERROR_INSUFFICIENT_MEMORY\n * \\return #PSA_ERROR_NOT_PERMITTED\n * \\return #PSA_ERROR_STORAGE_FAILURE\n * \\return #PSA_ERROR_DATA_CORRUPT\n */\npsa_status_t psa_register_se_driver(\n    psa_key_location_t location,\n    const psa_drv_se_t *methods);\n\n/**@}*/\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* PSA_CRYPTO_SE_DRIVER_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_sizes.h",
    "content": "/**\n * \\file psa/crypto_sizes.h\n *\n * \\brief PSA cryptography module: Mbed TLS buffer size macros\n *\n * \\note This file may not be included directly. Applications must\n * include psa/crypto.h.\n *\n * This file contains the definitions of macros that are useful to\n * compute buffer sizes. The signatures and semantics of these macros\n * are standardized, but the definitions are not, because they depend on\n * the available algorithms and, in some cases, on permitted tolerances\n * on buffer sizes.\n *\n * In implementations with isolation between the application and the\n * cryptography module, implementers should take care to ensure that\n * the definitions that are exposed to applications match what the\n * module implements.\n *\n * Macros that compute sizes whose values do not depend on the\n * implementation are in crypto.h.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_SIZES_H\n#define PSA_CRYPTO_SIZES_H\n\n/*\n * Include the build-time configuration information header. Here, we do not\n * include `\"mbedtls/build_info.h\"` directly but `\"psa/build_info.h\"`, which\n * is basically just an alias to it. This is to ease the maintenance of the\n * TF-PSA-Crypto repository which has a different build system and\n * configuration.\n */\n#include \"psa/build_info.h\"\n\n#define PSA_BITS_TO_BYTES(bits) (((bits) + 7u) / 8u)\n#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8u)\n#define PSA_MAX_OF_THREE(a, b, c) ((a) <= (b) ? (b) <= (c) ? \\\n                                   (c) : (b) : (a) <= (c) ? (c) : (a))\n\n#define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \\\n    (((length) + (block_size) - 1) / (block_size) * (block_size))\n\n/** The size of the output of psa_hash_finish(), in bytes.\n *\n * This is also the hash size that psa_hash_verify() expects.\n *\n * \\param alg   A hash algorithm (\\c PSA_ALG_XXX value such that\n *              #PSA_ALG_IS_HASH(\\p alg) is true), or an HMAC algorithm\n *              (#PSA_ALG_HMAC(\\c hash_alg) where \\c hash_alg is a\n *              hash algorithm).\n *\n * \\return The hash size for the specified hash algorithm.\n *         If the hash algorithm is not recognized, return 0.\n */\n#define PSA_HASH_LENGTH(alg)                                        \\\n    (                                                               \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16u :           \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20u :     \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20u :         \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28u :       \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32u :       \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48u :       \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64u :       \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28u :   \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32u :   \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28u :      \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32u :      \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48u :      \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64u :      \\\n        0u)\n\n/** The input block size of a hash algorithm, in bytes.\n *\n * Hash algorithms process their input data in blocks. Hash operations will\n * retain any partial blocks until they have enough input to fill the block or\n * until the operation is finished.\n * This affects the output from psa_hash_suspend().\n *\n * \\param alg   A hash algorithm (\\c PSA_ALG_XXX value such that\n *              PSA_ALG_IS_HASH(\\p alg) is true).\n *\n * \\return      The block size in bytes for the specified hash algorithm.\n *              If the hash algorithm is not recognized, return 0.\n *              An implementation can return either 0 or the correct size for a\n *              hash algorithm that it recognizes, but does not support.\n */\n#define PSA_HASH_BLOCK_LENGTH(alg)                                  \\\n    (                                                               \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 64u :           \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 64u :     \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 64u :         \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 64u :       \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 64u :       \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 128u :      \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 128u :      \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 128u :  \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 128u :  \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 144u :     \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 136u :     \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 104u :     \\\n        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 72u :      \\\n        0u)\n\n/** \\def PSA_HASH_MAX_SIZE\n *\n * Maximum size of a hash.\n *\n * This macro expands to a compile-time constant integer. This value\n * is the maximum size of a hash in bytes.\n */\n/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-224,\n * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for\n * HMAC-SHA3-512. */\n/* Note: PSA_HASH_MAX_SIZE should be kept in sync with MBEDTLS_MD_MAX_SIZE,\n * see the note on MBEDTLS_MD_MAX_SIZE for details. */\n#if defined(PSA_WANT_ALG_SHA3_224)\n#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 144u\n#elif defined(PSA_WANT_ALG_SHA3_256)\n#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 136u\n#elif defined(PSA_WANT_ALG_SHA_512)\n#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128u\n#elif defined(PSA_WANT_ALG_SHA_384)\n#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128u\n#elif defined(PSA_WANT_ALG_SHA3_384)\n#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 104u\n#elif defined(PSA_WANT_ALG_SHA3_512)\n#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 72u\n#elif defined(PSA_WANT_ALG_SHA_256)\n#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64u\n#elif defined(PSA_WANT_ALG_SHA_224)\n#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64u\n#else /* SHA-1 or smaller */\n#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64u\n#endif\n\n#if defined(PSA_WANT_ALG_SHA_512) || defined(PSA_WANT_ALG_SHA3_512)\n#define PSA_HASH_MAX_SIZE 64u\n#elif defined(PSA_WANT_ALG_SHA_384) || defined(PSA_WANT_ALG_SHA3_384)\n#define PSA_HASH_MAX_SIZE 48u\n#elif defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA3_256)\n#define PSA_HASH_MAX_SIZE 32u\n#elif defined(PSA_WANT_ALG_SHA_224) || defined(PSA_WANT_ALG_SHA3_224)\n#define PSA_HASH_MAX_SIZE 28u\n#else /* SHA-1 or smaller */\n#define PSA_HASH_MAX_SIZE 20u\n#endif\n\n/** \\def PSA_MAC_MAX_SIZE\n *\n * Maximum size of a MAC.\n *\n * This macro expands to a compile-time constant integer. This value\n * is the maximum size of a MAC in bytes.\n */\n/* All non-HMAC MACs have a maximum size that's smaller than the\n * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */\n/* Note that the encoding of truncated MAC algorithms limits this value\n * to 64 bytes.\n */\n#define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE\n\n/** The length of a tag for an AEAD algorithm, in bytes.\n *\n * This macro can be used to allocate a buffer of sufficient size to store the\n * tag output from psa_aead_finish().\n *\n * See also #PSA_AEAD_TAG_MAX_SIZE.\n *\n * \\param key_type            The type of the AEAD key.\n * \\param key_bits            The size of the AEAD key in bits.\n * \\param alg                 An AEAD algorithm\n *                            (\\c PSA_ALG_XXX value such that\n *                            #PSA_ALG_IS_AEAD(\\p alg) is true).\n *\n * \\return                    The tag length for the specified algorithm and key.\n *                            If the AEAD algorithm does not have an identified\n *                            tag that can be distinguished from the rest of\n *                            the ciphertext, return 0.\n *                            If the key type or AEAD algorithm is not\n *                            recognized, or the parameters are incompatible,\n *                            return 0.\n */\n#define PSA_AEAD_TAG_LENGTH(key_type, key_bits, alg)                        \\\n    (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ?                            \\\n     PSA_ALG_AEAD_GET_TAG_LENGTH(alg) :                                     \\\n     ((void) (key_bits), 0u))\n\n/** The maximum tag size for all supported AEAD algorithms, in bytes.\n *\n * See also #PSA_AEAD_TAG_LENGTH(\\p key_type, \\p key_bits, \\p alg).\n */\n#define PSA_AEAD_TAG_MAX_SIZE       16u\n\n/* The maximum size of an RSA key on this implementation, in bits.\n * This is a vendor-specific macro.\n *\n * Mbed TLS does not set a hard limit on the size of RSA keys: any key\n * whose parameters fit in a bignum is accepted. However large keys can\n * induce a large memory usage and long computation times. Unlike other\n * auxiliary macros in this file and in crypto.h, which reflect how the\n * library is configured, this macro defines how the library is\n * configured. This implementation refuses to import or generate an\n * RSA key whose size is larger than the value defined here.\n *\n * Note that an implementation may set different size limits for different\n * operations, and does not need to accept all key sizes up to the limit. */\n#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096u\n\n/* The minimum size of an RSA key on this implementation, in bits.\n * This is a vendor-specific macro.\n *\n * Limits RSA key generation to a minimum due to avoid accidental misuse.\n * This value cannot be less than 128 bits.\n */\n#if defined(MBEDTLS_RSA_GEN_KEY_MIN_BITS)\n#define PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS MBEDTLS_RSA_GEN_KEY_MIN_BITS\n#else\n#define PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS 1024\n#endif\n\n/* The maximum size of an DH key on this implementation, in bits.\n * This is a vendor-specific macro.*/\n#if defined(PSA_WANT_DH_RFC7919_8192)\n#define PSA_VENDOR_FFDH_MAX_KEY_BITS 8192u\n#elif defined(PSA_WANT_DH_RFC7919_6144)\n#define PSA_VENDOR_FFDH_MAX_KEY_BITS 6144u\n#elif defined(PSA_WANT_DH_RFC7919_4096)\n#define PSA_VENDOR_FFDH_MAX_KEY_BITS 4096u\n#elif defined(PSA_WANT_DH_RFC7919_3072)\n#define PSA_VENDOR_FFDH_MAX_KEY_BITS 3072u\n#elif defined(PSA_WANT_DH_RFC7919_2048)\n#define PSA_VENDOR_FFDH_MAX_KEY_BITS 2048u\n#else\n#define PSA_VENDOR_FFDH_MAX_KEY_BITS 0u\n#endif\n\n/* The maximum size of an ECC key on this implementation, in bits.\n * This is a vendor-specific macro. */\n#if defined(PSA_WANT_ECC_SECP_R1_521)\n#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521u\n#elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)\n#define PSA_VENDOR_ECC_MAX_CURVE_BITS 512u\n#elif defined(PSA_WANT_ECC_MONTGOMERY_448)\n#define PSA_VENDOR_ECC_MAX_CURVE_BITS 448u\n#elif defined(PSA_WANT_ECC_SECP_R1_384)\n#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384u\n#elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)\n#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384u\n#elif defined(PSA_WANT_ECC_SECP_R1_256)\n#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256u\n#elif defined(PSA_WANT_ECC_SECP_K1_256)\n#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256u\n#elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)\n#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256u\n#elif defined(PSA_WANT_ECC_MONTGOMERY_255)\n#define PSA_VENDOR_ECC_MAX_CURVE_BITS 255u\n#elif defined(PSA_WANT_ECC_SECP_R1_224)\n#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224u\n#elif defined(PSA_WANT_ECC_SECP_K1_224)\n#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224u\n#elif defined(PSA_WANT_ECC_SECP_R1_192)\n#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192u\n#elif defined(PSA_WANT_ECC_SECP_K1_192)\n#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192u\n#else\n#define PSA_VENDOR_ECC_MAX_CURVE_BITS 0u\n#endif\n\n/** This macro returns the maximum supported length of the PSK for the\n * TLS-1.2 PSK-to-MS key derivation\n * (#PSA_ALG_TLS12_PSK_TO_MS(\\c hash_alg)).\n *\n * The maximum supported length does not depend on the chosen hash algorithm.\n *\n * Quoting RFC 4279, Sect 5.3:\n * TLS implementations supporting these ciphersuites MUST support\n * arbitrary PSK identities up to 128 octets in length, and arbitrary\n * PSKs up to 64 octets in length.  Supporting longer identities and\n * keys is RECOMMENDED.\n *\n * Therefore, no implementation should define a value smaller than 64\n * for #PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE.\n */\n#define PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE 128u\n\n/* The expected size of input passed to psa_tls12_ecjpake_to_pms_input,\n * which is expected to work with P-256 curve only. */\n#define PSA_TLS12_ECJPAKE_TO_PMS_INPUT_SIZE 65u\n\n/* The size of a serialized K.X coordinate to be used in\n * psa_tls12_ecjpake_to_pms_input. This function only accepts the P-256\n * curve. */\n#define PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE 32u\n\n/* The maximum number of iterations for PBKDF2 on this implementation, in bits.\n * This is a vendor-specific macro. This can be configured if necessary */\n#define PSA_VENDOR_PBKDF2_MAX_ITERATIONS 0xffffffffU\n\n/** The maximum size of a block cipher. */\n#define PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE 16u\n\n/** The size of the output of psa_mac_sign_finish(), in bytes.\n *\n * This is also the MAC size that psa_mac_verify_finish() expects.\n *\n * \\warning This macro may evaluate its arguments multiple times or\n *          zero times, so you should not pass arguments that contain\n *          side effects.\n *\n * \\param key_type      The type of the MAC key.\n * \\param key_bits      The size of the MAC key in bits.\n * \\param alg           A MAC algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_MAC(\\p alg) is true).\n *\n * \\return              The MAC size for the specified algorithm with\n *                      the specified key parameters.\n * \\return              0 if the MAC algorithm is not recognized.\n * \\return              Either 0 or the correct size for a MAC algorithm that\n *                      the implementation recognizes, but does not support.\n * \\return              Unspecified if the key parameters are not consistent\n *                      with the algorithm.\n */\n#define PSA_MAC_LENGTH(key_type, key_bits, alg)                                   \\\n    ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) :        \\\n     PSA_ALG_IS_HMAC(alg) ? PSA_HASH_LENGTH(PSA_ALG_HMAC_GET_HASH(alg)) :         \\\n     PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \\\n     ((void) (key_type), (void) (key_bits), 0u))\n\n/** The maximum size of the output of psa_aead_encrypt(), in bytes.\n *\n * If the size of the ciphertext buffer is at least this large, it is\n * guaranteed that psa_aead_encrypt() will not fail due to an\n * insufficient buffer size. Depending on the algorithm, the actual size of\n * the ciphertext may be smaller.\n *\n * See also #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\\p plaintext_length).\n *\n * \\warning This macro may evaluate its arguments multiple times or\n *          zero times, so you should not pass arguments that contain\n *          side effects.\n *\n * \\param key_type            A symmetric key type that is\n *                            compatible with algorithm \\p alg.\n * \\param alg                 An AEAD algorithm\n *                            (\\c PSA_ALG_XXX value such that\n *                            #PSA_ALG_IS_AEAD(\\p alg) is true).\n * \\param plaintext_length    Size of the plaintext in bytes.\n *\n * \\return                    The AEAD ciphertext size for the specified\n *                            algorithm.\n *                            If the key type or AEAD algorithm is not\n *                            recognized, or the parameters are incompatible,\n *                            return 0.\n */\n#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg, plaintext_length) \\\n    (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ?                      \\\n     (plaintext_length) + PSA_ALG_AEAD_GET_TAG_LENGTH(alg) :          \\\n     0u)\n\n/** A sufficient output buffer size for psa_aead_encrypt(), for any of the\n *  supported key types and AEAD algorithms.\n *\n * If the size of the ciphertext buffer is at least this large, it is guaranteed\n * that psa_aead_encrypt() will not fail due to an insufficient buffer size.\n *\n * \\note This macro returns a compile-time constant if its arguments are\n *       compile-time constants.\n *\n * See also #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\\p key_type, \\p alg,\n * \\p plaintext_length).\n *\n * \\param plaintext_length    Size of the plaintext in bytes.\n *\n * \\return                    A sufficient output buffer size for any of the\n *                            supported key types and AEAD algorithms.\n *\n */\n#define PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(plaintext_length)          \\\n    ((plaintext_length) + PSA_AEAD_TAG_MAX_SIZE)\n\n\n/** The maximum size of the output of psa_aead_decrypt(), in bytes.\n *\n * If the size of the plaintext buffer is at least this large, it is\n * guaranteed that psa_aead_decrypt() will not fail due to an\n * insufficient buffer size. Depending on the algorithm, the actual size of\n * the plaintext may be smaller.\n *\n * See also #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\\p ciphertext_length).\n *\n * \\warning This macro may evaluate its arguments multiple times or\n *          zero times, so you should not pass arguments that contain\n *          side effects.\n *\n * \\param key_type            A symmetric key type that is\n *                            compatible with algorithm \\p alg.\n * \\param alg                 An AEAD algorithm\n *                            (\\c PSA_ALG_XXX value such that\n *                            #PSA_ALG_IS_AEAD(\\p alg) is true).\n * \\param ciphertext_length   Size of the plaintext in bytes.\n *\n * \\return                    The AEAD ciphertext size for the specified\n *                            algorithm.\n *                            If the key type or AEAD algorithm is not\n *                            recognized, or the parameters are incompatible,\n *                            return 0.\n */\n#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg, ciphertext_length) \\\n    (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 &&                      \\\n     (ciphertext_length) > PSA_ALG_AEAD_GET_TAG_LENGTH(alg) ?      \\\n     (ciphertext_length) - PSA_ALG_AEAD_GET_TAG_LENGTH(alg) :      \\\n     0u)\n\n/** A sufficient output buffer size for psa_aead_decrypt(), for any of the\n *  supported key types and AEAD algorithms.\n *\n * If the size of the plaintext buffer is at least this large, it is guaranteed\n * that psa_aead_decrypt() will not fail due to an insufficient buffer size.\n *\n * \\note This macro returns a compile-time constant if its arguments are\n *       compile-time constants.\n *\n * See also #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\\p key_type, \\p alg,\n * \\p ciphertext_length).\n *\n * \\param ciphertext_length   Size of the ciphertext in bytes.\n *\n * \\return                    A sufficient output buffer size for any of the\n *                            supported key types and AEAD algorithms.\n *\n */\n#define PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(ciphertext_length)     \\\n    (ciphertext_length)\n\n/** The default nonce size for an AEAD algorithm, in bytes.\n *\n * This macro can be used to allocate a buffer of sufficient size to\n * store the nonce output from #psa_aead_generate_nonce().\n *\n * See also #PSA_AEAD_NONCE_MAX_SIZE.\n *\n * \\note This is not the maximum size of nonce supported as input to\n *       #psa_aead_set_nonce(), #psa_aead_encrypt() or #psa_aead_decrypt(),\n *       just the default size that is generated by #psa_aead_generate_nonce().\n *\n * \\warning This macro may evaluate its arguments multiple times or\n *          zero times, so you should not pass arguments that contain\n *          side effects.\n *\n * \\param key_type  A symmetric key type that is compatible with\n *                  algorithm \\p alg.\n *\n * \\param alg       An AEAD algorithm (\\c PSA_ALG_XXX value such that\n *                  #PSA_ALG_IS_AEAD(\\p alg) is true).\n *\n * \\return The default nonce size for the specified key type and algorithm.\n *         If the key type or AEAD algorithm is not recognized,\n *         or the parameters are incompatible, return 0.\n */\n#define PSA_AEAD_NONCE_LENGTH(key_type, alg) \\\n    (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) == 16 ? \\\n     MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CCM) ? 13u : \\\n     MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_GCM) ? 12u : \\\n     0u : \\\n     (key_type) == PSA_KEY_TYPE_CHACHA20 && \\\n     MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CHACHA20_POLY1305) ? 12u : \\\n     0u)\n\n/** The maximum default nonce size among all supported pairs of key types and\n *  AEAD algorithms, in bytes.\n *\n * This is equal to or greater than any value that #PSA_AEAD_NONCE_LENGTH()\n * may return.\n *\n * \\note This is not the maximum size of nonce supported as input to\n *       #psa_aead_set_nonce(), #psa_aead_encrypt() or #psa_aead_decrypt(),\n *       just the largest size that may be generated by\n *       #psa_aead_generate_nonce().\n */\n#define PSA_AEAD_NONCE_MAX_SIZE 13u\n\n/** A sufficient output buffer size for psa_aead_update().\n *\n * If the size of the output buffer is at least this large, it is\n * guaranteed that psa_aead_update() will not fail due to an\n * insufficient buffer size. The actual size of the output may be smaller\n * in any given call.\n *\n * See also #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\\p input_length).\n *\n * \\warning This macro may evaluate its arguments multiple times or\n *          zero times, so you should not pass arguments that contain\n *          side effects.\n *\n * \\param key_type            A symmetric key type that is\n *                            compatible with algorithm \\p alg.\n * \\param alg                 An AEAD algorithm\n *                            (\\c PSA_ALG_XXX value such that\n *                            #PSA_ALG_IS_AEAD(\\p alg) is true).\n * \\param input_length        Size of the input in bytes.\n *\n * \\return                    A sufficient output buffer size for the specified\n *                            algorithm.\n *                            If the key type or AEAD algorithm is not\n *                            recognized, or the parameters are incompatible,\n *                            return 0.\n */\n/* For all the AEAD modes defined in this specification, it is possible\n * to emit output without delay. However, hardware may not always be\n * capable of this. So for modes based on a block cipher, allow the\n * implementation to delay the output until it has a full block. */\n#define PSA_AEAD_UPDATE_OUTPUT_SIZE(key_type, alg, input_length)                             \\\n    (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ?                                             \\\n     PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ?                                              \\\n     PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), (input_length)) : \\\n     (input_length) : \\\n     0u)\n\n/** A sufficient output buffer size for psa_aead_update(), for any of the\n *  supported key types and AEAD algorithms.\n *\n * If the size of the output buffer is at least this large, it is guaranteed\n * that psa_aead_update() will not fail due to an insufficient buffer size.\n *\n * See also #PSA_AEAD_UPDATE_OUTPUT_SIZE(\\p key_type, \\p alg, \\p input_length).\n *\n * \\param input_length      Size of the input in bytes.\n */\n#define PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(input_length)                           \\\n    (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, (input_length)))\n\n/** A sufficient ciphertext buffer size for psa_aead_finish().\n *\n * If the size of the ciphertext buffer is at least this large, it is\n * guaranteed that psa_aead_finish() will not fail due to an\n * insufficient ciphertext buffer size. The actual size of the output may\n * be smaller in any given call.\n *\n * See also #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE.\n *\n * \\param key_type            A symmetric key type that is\n                              compatible with algorithm \\p alg.\n * \\param alg                 An AEAD algorithm\n *                            (\\c PSA_ALG_XXX value such that\n *                            #PSA_ALG_IS_AEAD(\\p alg) is true).\n *\n * \\return                    A sufficient ciphertext buffer size for the\n *                            specified algorithm.\n *                            If the key type or AEAD algorithm is not\n *                            recognized, or the parameters are incompatible,\n *                            return 0.\n */\n#define PSA_AEAD_FINISH_OUTPUT_SIZE(key_type, alg) \\\n    (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 &&  \\\n     PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ?    \\\n     PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \\\n     0u)\n\n/** A sufficient ciphertext buffer size for psa_aead_finish(), for any of the\n *  supported key types and AEAD algorithms.\n *\n * See also #PSA_AEAD_FINISH_OUTPUT_SIZE(\\p key_type, \\p alg).\n */\n#define PSA_AEAD_FINISH_OUTPUT_MAX_SIZE     (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE)\n\n/** A sufficient plaintext buffer size for psa_aead_verify().\n *\n * If the size of the plaintext buffer is at least this large, it is\n * guaranteed that psa_aead_verify() will not fail due to an\n * insufficient plaintext buffer size. The actual size of the output may\n * be smaller in any given call.\n *\n * See also #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE.\n *\n * \\param key_type            A symmetric key type that is\n *                            compatible with algorithm \\p alg.\n * \\param alg                 An AEAD algorithm\n *                            (\\c PSA_ALG_XXX value such that\n *                            #PSA_ALG_IS_AEAD(\\p alg) is true).\n *\n * \\return                    A sufficient plaintext buffer size for the\n *                            specified algorithm.\n *                            If the key type or AEAD algorithm is not\n *                            recognized, or the parameters are incompatible,\n *                            return 0.\n */\n#define PSA_AEAD_VERIFY_OUTPUT_SIZE(key_type, alg) \\\n    (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 &&  \\\n     PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ?    \\\n     PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \\\n     0u)\n\n/** A sufficient plaintext buffer size for psa_aead_verify(), for any of the\n *  supported key types and AEAD algorithms.\n *\n * See also #PSA_AEAD_VERIFY_OUTPUT_SIZE(\\p key_type, \\p alg).\n */\n#define PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE     (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE)\n\n#define PSA_RSA_MINIMUM_PADDING_SIZE(alg)                         \\\n    (PSA_ALG_IS_RSA_OAEP(alg) ?                                   \\\n     2u * PSA_HASH_LENGTH(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1u :   \\\n     11u /*PKCS#1v1.5*/)\n\n/**\n * \\brief ECDSA signature size for a given curve bit size\n *\n * \\param curve_bits    Curve size in bits.\n * \\return              Signature size in bytes.\n *\n * \\note This macro returns a compile-time constant if its argument is one.\n */\n#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits)    \\\n    (PSA_BITS_TO_BYTES(curve_bits) * 2u)\n\n/** Sufficient signature buffer size for psa_sign_hash().\n *\n * This macro returns a sufficient buffer size for a signature using a key\n * of the specified type and size, with the specified algorithm.\n * Note that the actual size of the signature may be smaller\n * (some algorithms produce a variable-size signature).\n *\n * \\warning This function may call its arguments multiple times or\n *          zero times, so you should not pass arguments that contain\n *          side effects.\n *\n * \\param key_type  An asymmetric key type (this may indifferently be a\n *                  key pair type or a public key type).\n * \\param key_bits  The size of the key in bits.\n * \\param alg       The signature algorithm.\n *\n * \\return If the parameters are valid and supported, return\n *         a buffer size in bytes that guarantees that\n *         psa_sign_hash() will not fail with\n *         #PSA_ERROR_BUFFER_TOO_SMALL.\n *         If the parameters are a valid combination that is not supported,\n *         return either a sensible size or 0.\n *         If the parameters are not valid, the\n *         return value is unspecified.\n */\n#define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg)        \\\n    (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void) alg, PSA_BITS_TO_BYTES(key_bits)) : \\\n     PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \\\n     ((void) alg, 0u))\n\n#define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE     \\\n    PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)\n\n/** \\def PSA_SIGNATURE_MAX_SIZE\n *\n * Maximum size of an asymmetric signature.\n *\n * This macro expands to a compile-time constant integer. This value\n * is the maximum size of a signature in bytes.\n */\n#define PSA_SIGNATURE_MAX_SIZE      1\n\n#if (defined(PSA_WANT_ALG_ECDSA) || defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)) && \\\n    (PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE > PSA_SIGNATURE_MAX_SIZE)\n#undef PSA_SIGNATURE_MAX_SIZE\n#define PSA_SIGNATURE_MAX_SIZE      PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE\n#endif\n#if (defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) || defined(PSA_WANT_ALG_RSA_PSS)) && \\\n    (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_SIGNATURE_MAX_SIZE)\n#undef PSA_SIGNATURE_MAX_SIZE\n#define PSA_SIGNATURE_MAX_SIZE      PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS)\n#endif\n\n/** Sufficient output buffer size for psa_asymmetric_encrypt().\n *\n * This macro returns a sufficient buffer size for a ciphertext produced using\n * a key of the specified type and size, with the specified algorithm.\n * Note that the actual size of the ciphertext may be smaller, depending\n * on the algorithm.\n *\n * \\warning This function may call its arguments multiple times or\n *          zero times, so you should not pass arguments that contain\n *          side effects.\n *\n * \\param key_type  An asymmetric key type (this may indifferently be a\n *                  key pair type or a public key type).\n * \\param key_bits  The size of the key in bits.\n * \\param alg       The asymmetric encryption algorithm.\n *\n * \\return If the parameters are valid and supported, return\n *         a buffer size in bytes that guarantees that\n *         psa_asymmetric_encrypt() will not fail with\n *         #PSA_ERROR_BUFFER_TOO_SMALL.\n *         If the parameters are a valid combination that is not supported,\n *         return either a sensible size or 0.\n *         If the parameters are not valid, the\n *         return value is unspecified.\n */\n#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg)     \\\n    (PSA_KEY_TYPE_IS_RSA(key_type) ?                                    \\\n     ((void) alg, PSA_BITS_TO_BYTES(key_bits)) :                         \\\n     0u)\n\n/** A sufficient output buffer size for psa_asymmetric_encrypt(), for any\n *  supported asymmetric encryption.\n *\n * See also #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\\p key_type, \\p key_bits, \\p alg).\n */\n/* This macro assumes that RSA is the only supported asymmetric encryption. */\n#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_MAX_SIZE          \\\n    (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS))\n\n/** Sufficient output buffer size for psa_asymmetric_decrypt().\n *\n * This macro returns a sufficient buffer size for a plaintext produced using\n * a key of the specified type and size, with the specified algorithm.\n * Note that the actual size of the plaintext may be smaller, depending\n * on the algorithm.\n *\n * \\warning This function may call its arguments multiple times or\n *          zero times, so you should not pass arguments that contain\n *          side effects.\n *\n * \\param key_type  An asymmetric key type (this may indifferently be a\n *                  key pair type or a public key type).\n * \\param key_bits  The size of the key in bits.\n * \\param alg       The asymmetric encryption algorithm.\n *\n * \\return If the parameters are valid and supported, return\n *         a buffer size in bytes that guarantees that\n *         psa_asymmetric_decrypt() will not fail with\n *         #PSA_ERROR_BUFFER_TOO_SMALL.\n *         If the parameters are a valid combination that is not supported,\n *         return either a sensible size or 0.\n *         If the parameters are not valid, the\n *         return value is unspecified.\n */\n#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg)     \\\n    (PSA_KEY_TYPE_IS_RSA(key_type) ?                                    \\\n     PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) :  \\\n     0u)\n\n/** A sufficient output buffer size for psa_asymmetric_decrypt(), for any\n *  supported asymmetric decryption.\n *\n * This macro assumes that RSA is the only supported asymmetric encryption.\n *\n * See also #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\\p key_type, \\p key_bits, \\p alg).\n */\n#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE          \\\n    (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS))\n\n/* Maximum size of the ASN.1 encoding of an INTEGER with the specified\n * number of bits.\n *\n * This definition assumes that bits <= 2^19 - 9 so that the length field\n * is at most 3 bytes. The length of the encoding is the length of the\n * bit string padded to a whole number of bytes plus:\n * - 1 type byte;\n * - 1 to 3 length bytes;\n * - 0 to 1 bytes of leading 0 due to the sign bit.\n */\n#define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits)      \\\n    ((bits) / 8u + 5u)\n\n/* Maximum size of the export encoding of an RSA public key.\n * Assumes that the public exponent is less than 2^32.\n *\n * RSAPublicKey  ::=  SEQUENCE  {\n *    modulus            INTEGER,    -- n\n *    publicExponent     INTEGER  }  -- e\n *\n * - 4 bytes of SEQUENCE overhead;\n * - n : INTEGER;\n * - 7 bytes for the public exponent.\n */\n#define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits)        \\\n    (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11u)\n\n/* Maximum size of the export encoding of an RSA key pair.\n * Assumes that the public exponent is less than 2^32 and that the size\n * difference between the two primes is at most 1 bit.\n *\n * RSAPrivateKey ::= SEQUENCE {\n *     version           Version,  -- 0\n *     modulus           INTEGER,  -- N-bit\n *     publicExponent    INTEGER,  -- 32-bit\n *     privateExponent   INTEGER,  -- N-bit\n *     prime1            INTEGER,  -- N/2-bit\n *     prime2            INTEGER,  -- N/2-bit\n *     exponent1         INTEGER,  -- N/2-bit\n *     exponent2         INTEGER,  -- N/2-bit\n *     coefficient       INTEGER,  -- N/2-bit\n * }\n *\n * - 4 bytes of SEQUENCE overhead;\n * - 3 bytes of version;\n * - 7 half-size INTEGERs plus 2 full-size INTEGERs,\n *   overapproximated as 9 half-size INTEGERS;\n * - 7 bytes for the public exponent.\n */\n#define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits)   \\\n    (9u * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2u + 1u) + 14u)\n\n/* Maximum size of the export encoding of a DSA public key.\n *\n * SubjectPublicKeyInfo  ::=  SEQUENCE  {\n *      algorithm            AlgorithmIdentifier,\n *      subjectPublicKey     BIT STRING  } -- contains DSAPublicKey\n * AlgorithmIdentifier  ::=  SEQUENCE  {\n *      algorithm               OBJECT IDENTIFIER,\n *      parameters              Dss-Params  } -- SEQUENCE of 3 INTEGERs\n * DSAPublicKey  ::=  INTEGER -- public key, Y\n *\n * - 3 * 4 bytes of SEQUENCE overhead;\n * - 1 + 1 + 7 bytes of algorithm (DSA OID);\n * - 4 bytes of BIT STRING overhead;\n * - 3 full-size INTEGERs (p, g, y);\n * - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits).\n */\n#define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits)        \\\n    (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3u + 59u)\n\n/* Maximum size of the export encoding of a DSA key pair.\n *\n * DSAPrivateKey ::= SEQUENCE {\n *     version             Version,  -- 0\n *     prime               INTEGER,  -- p\n *     subprime            INTEGER,  -- q\n *     generator           INTEGER,  -- g\n *     public              INTEGER,  -- y\n *     private             INTEGER,  -- x\n * }\n *\n * - 4 bytes of SEQUENCE overhead;\n * - 3 bytes of version;\n * - 3 full-size INTEGERs (p, g, y);\n * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits).\n */\n#define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits)   \\\n    (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3u + 75u)\n\n/* Maximum size of the export encoding of an ECC public key.\n *\n * The representation of an ECC public key is:\n *      - The byte 0x04;\n *      - `x_P` as a `ceiling(m/8)`-byte string, big-endian;\n *      - `y_P` as a `ceiling(m/8)`-byte string, big-endian;\n *      - where m is the bit size associated with the curve.\n *\n * - 1 byte + 2 * point size.\n */\n#define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits)        \\\n    (2u * PSA_BITS_TO_BYTES(key_bits) + 1u)\n\n/* Maximum size of the export encoding of an ECC key pair.\n *\n * An ECC key pair is represented by the secret value.\n */\n#define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits)   \\\n    (PSA_BITS_TO_BYTES(key_bits))\n\n/* Maximum size of the export encoding of an DH key pair.\n *\n * An DH key pair is represented by the secret value.\n */\n#define PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(key_bits)   \\\n    (PSA_BITS_TO_BYTES(key_bits))\n\n/* Maximum size of the export encoding of an DH public key.\n */\n#define PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(key_bits)   \\\n    (PSA_BITS_TO_BYTES(key_bits))\n\n/** Sufficient output buffer size for psa_export_key() or\n * psa_export_public_key().\n *\n * This macro returns a compile-time constant if its arguments are\n * compile-time constants.\n *\n * \\warning This macro may evaluate its arguments multiple times or\n *          zero times, so you should not pass arguments that contain\n *          side effects.\n *\n * The following code illustrates how to allocate enough memory to export\n * a key by querying the key type and size at runtime.\n * \\code{c}\n * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n * psa_status_t status;\n * status = psa_get_key_attributes(key, &attributes);\n * if (status != PSA_SUCCESS) handle_error(...);\n * psa_key_type_t key_type = psa_get_key_type(&attributes);\n * size_t key_bits = psa_get_key_bits(&attributes);\n * size_t buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits);\n * psa_reset_key_attributes(&attributes);\n * uint8_t *buffer = malloc(buffer_size);\n * if (buffer == NULL) handle_error(...);\n * size_t buffer_length;\n * status = psa_export_key(key, buffer, buffer_size, &buffer_length);\n * if (status != PSA_SUCCESS) handle_error(...);\n * \\endcode\n *\n * \\param key_type  A supported key type.\n * \\param key_bits  The size of the key in bits.\n *\n * \\return If the parameters are valid and supported, return\n *         a buffer size in bytes that guarantees that\n *         psa_export_key() or psa_export_public_key() will not fail with\n *         #PSA_ERROR_BUFFER_TOO_SMALL.\n *         If the parameters are a valid combination that is not supported,\n *         return either a sensible size or 0.\n *         If the parameters are not valid, the return value is unspecified.\n */\n#define PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits)                                              \\\n    (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) :                         \\\n     PSA_KEY_TYPE_IS_DH(key_type) ? PSA_BITS_TO_BYTES(key_bits) :                                   \\\n     (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) :     \\\n     (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \\\n     (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) :     \\\n     (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \\\n     PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) :      \\\n     PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) :  \\\n     0u)\n\n/** Sufficient output buffer size for psa_export_public_key().\n *\n * This macro returns a compile-time constant if its arguments are\n * compile-time constants.\n *\n * \\warning This macro may evaluate its arguments multiple times or\n *          zero times, so you should not pass arguments that contain\n *          side effects.\n *\n * The following code illustrates how to allocate enough memory to export\n * a public key by querying the key type and size at runtime.\n * \\code{c}\n * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n * psa_status_t status;\n * status = psa_get_key_attributes(key, &attributes);\n * if (status != PSA_SUCCESS) handle_error(...);\n * psa_key_type_t key_type = psa_get_key_type(&attributes);\n * size_t key_bits = psa_get_key_bits(&attributes);\n * size_t buffer_size = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, key_bits);\n * psa_reset_key_attributes(&attributes);\n * uint8_t *buffer = malloc(buffer_size);\n * if (buffer == NULL) handle_error(...);\n * size_t buffer_length;\n * status = psa_export_public_key(key, buffer, buffer_size, &buffer_length);\n * if (status != PSA_SUCCESS) handle_error(...);\n * \\endcode\n *\n * \\param key_type      A public key or key pair key type.\n * \\param key_bits      The size of the key in bits.\n *\n * \\return              If the parameters are valid and supported, return\n *                      a buffer size in bytes that guarantees that\n *                      psa_export_public_key() will not fail with\n *                      #PSA_ERROR_BUFFER_TOO_SMALL.\n *                      If the parameters are a valid combination that is not\n *                      supported, return either a sensible size or 0.\n *                      If the parameters are not valid,\n *                      the return value is unspecified.\n *\n *                      If the parameters are valid and supported,\n *                      return the same result as\n *                      #PSA_EXPORT_KEY_OUTPUT_SIZE(\n *                          \\p #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\\p key_type),\n *                          \\p key_bits).\n */\n#define PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, key_bits)                           \\\n    (PSA_KEY_TYPE_IS_RSA(key_type) ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \\\n     PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \\\n     PSA_KEY_TYPE_IS_DH(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \\\n     0u)\n\n/** Sufficient buffer size for exporting any asymmetric key pair.\n *\n * This macro expands to a compile-time constant integer. This value is\n * a sufficient buffer size when calling psa_export_key() to export any\n * asymmetric key pair, regardless of the exact key type and key size.\n *\n * See also #PSA_EXPORT_KEY_OUTPUT_SIZE(\\p key_type, \\p key_bits).\n */\n#define PSA_EXPORT_KEY_PAIR_MAX_SIZE            1\n\n#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \\\n    (PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \\\n     PSA_EXPORT_KEY_PAIR_MAX_SIZE)\n#undef PSA_EXPORT_KEY_PAIR_MAX_SIZE\n#define PSA_EXPORT_KEY_PAIR_MAX_SIZE    \\\n    PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)\n#endif\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) && \\\n    (PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \\\n     PSA_EXPORT_KEY_PAIR_MAX_SIZE)\n#undef PSA_EXPORT_KEY_PAIR_MAX_SIZE\n#define PSA_EXPORT_KEY_PAIR_MAX_SIZE    \\\n    PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)\n#endif\n#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) && \\\n    (PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) > \\\n     PSA_EXPORT_KEY_PAIR_MAX_SIZE)\n#undef PSA_EXPORT_KEY_PAIR_MAX_SIZE\n#define PSA_EXPORT_KEY_PAIR_MAX_SIZE    \\\n    PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS)\n#endif\n\n/** Sufficient buffer size for exporting any asymmetric public key.\n *\n * This macro expands to a compile-time constant integer. This value is\n * a sufficient buffer size when calling psa_export_key() or\n * psa_export_public_key() to export any asymmetric public key,\n * regardless of the exact key type and key size.\n *\n * See also #PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(\\p key_type, \\p key_bits).\n */\n#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE            1\n\n#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \\\n    (PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \\\n     PSA_EXPORT_PUBLIC_KEY_MAX_SIZE)\n#undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE\n#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE    \\\n    PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)\n#endif\n#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) && \\\n    (PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \\\n     PSA_EXPORT_PUBLIC_KEY_MAX_SIZE)\n#undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE\n#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE    \\\n    PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)\n#endif\n#if defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) && \\\n    (PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) > \\\n     PSA_EXPORT_PUBLIC_KEY_MAX_SIZE)\n#undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE\n#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE    \\\n    PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS)\n#endif\n\n#define PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE \\\n    ((PSA_EXPORT_KEY_PAIR_MAX_SIZE > PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) ? \\\n     PSA_EXPORT_KEY_PAIR_MAX_SIZE : PSA_EXPORT_PUBLIC_KEY_MAX_SIZE)\n\n/** Sufficient output buffer size for psa_raw_key_agreement().\n *\n * This macro returns a compile-time constant if its arguments are\n * compile-time constants.\n *\n * \\warning This macro may evaluate its arguments multiple times or\n *          zero times, so you should not pass arguments that contain\n *          side effects.\n *\n * See also #PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE.\n *\n * \\param key_type      A supported key type.\n * \\param key_bits      The size of the key in bits.\n *\n * \\return              If the parameters are valid and supported, return\n *                      a buffer size in bytes that guarantees that\n *                      psa_raw_key_agreement() will not fail with\n *                      #PSA_ERROR_BUFFER_TOO_SMALL.\n *                      If the parameters are a valid combination that\n *                      is not supported, return either a sensible size or 0.\n *                      If the parameters are not valid,\n *                      the return value is unspecified.\n */\n#define PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(key_type, key_bits)   \\\n    ((PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) || \\\n      PSA_KEY_TYPE_IS_DH_KEY_PAIR(key_type)) ? PSA_BITS_TO_BYTES(key_bits) : 0u)\n\n/** Maximum size of the output from psa_raw_key_agreement().\n *\n * This macro expands to a compile-time constant integer. This value is the\n * maximum size of the output any raw key agreement algorithm, in bytes.\n *\n * See also #PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(\\p key_type, \\p key_bits).\n */\n#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE       1\n\n#if defined(PSA_WANT_ALG_ECDH) && \\\n    (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) > PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE)\n#undef PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE\n#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE    PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)\n#endif\n#if defined(PSA_WANT_ALG_FFDH) && \\\n    (PSA_BITS_TO_BYTES(PSA_VENDOR_FFDH_MAX_KEY_BITS) > PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE)\n#undef PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE\n#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE    PSA_BITS_TO_BYTES(PSA_VENDOR_FFDH_MAX_KEY_BITS)\n#endif\n\n/** Maximum key length for ciphers.\n *\n * Since there is no additional PSA_WANT_xxx symbol to specifiy the size of\n * the key once a cipher is enabled (as it happens for asymmetric keys for\n * example), the maximum key length is taken into account for each cipher.\n * The resulting value will be the maximum cipher's key length given depending\n * on which ciphers are enabled.\n *\n * Note: max value for AES used below would be doubled if XTS were enabled, but\n *       this mode is currently not supported in Mbed TLS implementation of PSA\n *       APIs.\n */\n#if (defined(PSA_WANT_KEY_TYPE_AES) || defined(PSA_WANT_KEY_TYPE_ARIA) || \\\n    defined(PSA_WANT_KEY_TYPE_CAMELLIA) || defined(PSA_WANT_KEY_TYPE_CHACHA20))\n#define PSA_CIPHER_MAX_KEY_LENGTH       32u\n#elif defined(PSA_WANT_KEY_TYPE_DES)\n#define PSA_CIPHER_MAX_KEY_LENGTH       24u\n#else\n#define PSA_CIPHER_MAX_KEY_LENGTH       0u\n#endif\n\n/** The default IV size for a cipher algorithm, in bytes.\n *\n * The IV that is generated as part of a call to #psa_cipher_encrypt() is always\n * the default IV length for the algorithm.\n *\n * This macro can be used to allocate a buffer of sufficient size to\n * store the IV output from #psa_cipher_generate_iv() when using\n * a multi-part cipher operation.\n *\n * See also #PSA_CIPHER_IV_MAX_SIZE.\n *\n * \\warning This macro may evaluate its arguments multiple times or\n *          zero times, so you should not pass arguments that contain\n *          side effects.\n *\n * \\param key_type  A symmetric key type that is compatible with algorithm \\p alg.\n *\n * \\param alg       A cipher algorithm (\\c PSA_ALG_XXX value such that #PSA_ALG_IS_CIPHER(\\p alg) is true).\n *\n * \\return The default IV size for the specified key type and algorithm.\n *         If the algorithm does not use an IV, return 0.\n *         If the key type or cipher algorithm is not recognized,\n *         or the parameters are incompatible, return 0.\n */\n#define PSA_CIPHER_IV_LENGTH(key_type, alg) \\\n    (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) > 1 && \\\n     ((alg) == PSA_ALG_CTR || \\\n      (alg) == PSA_ALG_CFB || \\\n      (alg) == PSA_ALG_OFB || \\\n      (alg) == PSA_ALG_XTS || \\\n      (alg) == PSA_ALG_CBC_NO_PADDING || \\\n      (alg) == PSA_ALG_CBC_PKCS7) ? PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \\\n     (key_type) == PSA_KEY_TYPE_CHACHA20 && \\\n     (alg) == PSA_ALG_STREAM_CIPHER ? 12u : \\\n     (alg) == PSA_ALG_CCM_STAR_NO_TAG ? 13u : \\\n     0u)\n\n/** The maximum IV size for all supported cipher algorithms, in bytes.\n *\n * See also #PSA_CIPHER_IV_LENGTH().\n */\n#define PSA_CIPHER_IV_MAX_SIZE 16u\n\n/** The maximum size of the output of psa_cipher_encrypt(), in bytes.\n *\n * If the size of the output buffer is at least this large, it is guaranteed\n * that psa_cipher_encrypt() will not fail due to an insufficient buffer size.\n * Depending on the algorithm, the actual size of the output might be smaller.\n *\n * See also #PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(\\p input_length).\n *\n * \\warning This macro may evaluate its arguments multiple times or\n *          zero times, so you should not pass arguments that contain\n *          side effects.\n *\n * \\param key_type      A symmetric key type that is compatible with algorithm\n *                      alg.\n * \\param alg           A cipher algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_CIPHER(\\p alg) is true).\n * \\param input_length  Size of the input in bytes.\n *\n * \\return              A sufficient output size for the specified key type and\n *                      algorithm. If the key type or cipher algorithm is not\n *                      recognized, or the parameters are incompatible,\n *                      return 0.\n */\n#define PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input_length)     \\\n    (alg == PSA_ALG_CBC_PKCS7 ?                                         \\\n     (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ?                    \\\n      PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \\\n                               (input_length) + 1u) +                   \\\n      PSA_CIPHER_IV_LENGTH((key_type), (alg)) : 0u) :                   \\\n     (PSA_ALG_IS_CIPHER(alg) ?                                          \\\n      (input_length) + PSA_CIPHER_IV_LENGTH((key_type), (alg)) :        \\\n      0u))\n\n/** A sufficient output buffer size for psa_cipher_encrypt(), for any of the\n *  supported key types and cipher algorithms.\n *\n * If the size of the output buffer is at least this large, it is guaranteed\n * that psa_cipher_encrypt() will not fail due to an insufficient buffer size.\n *\n * See also #PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(\\p key_type, \\p alg, \\p input_length).\n *\n * \\param input_length  Size of the input in bytes.\n *\n */\n#define PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(input_length)                \\\n    (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE,          \\\n                              (input_length) + 1u) +                    \\\n     PSA_CIPHER_IV_MAX_SIZE)\n\n/** The maximum size of the output of psa_cipher_decrypt(), in bytes.\n *\n * If the size of the output buffer is at least this large, it is guaranteed\n * that psa_cipher_decrypt() will not fail due to an insufficient buffer size.\n * Depending on the algorithm, the actual size of the output might be smaller.\n *\n * See also #PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(\\p input_length).\n *\n * \\param key_type      A symmetric key type that is compatible with algorithm\n *                      alg.\n * \\param alg           A cipher algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_CIPHER(\\p alg) is true).\n * \\param input_length  Size of the input in bytes.\n *\n * \\return              A sufficient output size for the specified key type and\n *                      algorithm. If the key type or cipher algorithm is not\n *                      recognized, or the parameters are incompatible,\n *                      return 0.\n */\n#define PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, input_length)     \\\n    (PSA_ALG_IS_CIPHER(alg) &&                                          \\\n     ((key_type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \\\n     (input_length) :                                                   \\\n     0u)\n\n/** A sufficient output buffer size for psa_cipher_decrypt(), for any of the\n *  supported key types and cipher algorithms.\n *\n * If the size of the output buffer is at least this large, it is guaranteed\n * that psa_cipher_decrypt() will not fail due to an insufficient buffer size.\n *\n * See also #PSA_CIPHER_DECRYPT_OUTPUT_SIZE(\\p key_type, \\p alg, \\p input_length).\n *\n * \\param input_length  Size of the input in bytes.\n */\n#define PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(input_length)    \\\n    (input_length)\n\n/** A sufficient output buffer size for psa_cipher_update().\n *\n * If the size of the output buffer is at least this large, it is guaranteed\n * that psa_cipher_update() will not fail due to an insufficient buffer size.\n * The actual size of the output might be smaller in any given call.\n *\n * See also #PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(\\p input_length).\n *\n * \\param key_type      A symmetric key type that is compatible with algorithm\n *                      alg.\n * \\param alg           A cipher algorithm (PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_CIPHER(\\p alg) is true).\n * \\param input_length  Size of the input in bytes.\n *\n * \\return              A sufficient output size for the specified key type and\n *                      algorithm. If the key type or cipher algorithm is not\n *                      recognized, or the parameters are incompatible, return 0.\n */\n#define PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, input_length)      \\\n    (PSA_ALG_IS_CIPHER(alg) ?                                           \\\n     (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ?                    \\\n      (((alg) == PSA_ALG_CBC_PKCS7      ||                              \\\n        (alg) == PSA_ALG_CBC_NO_PADDING ||                              \\\n        (alg) == PSA_ALG_ECB_NO_PADDING) ?                              \\\n       PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \\\n                                input_length) :                         \\\n       (input_length)) : 0u) :                                          \\\n     0u)\n\n/** A sufficient output buffer size for psa_cipher_update(), for any of the\n *  supported key types and cipher algorithms.\n *\n * If the size of the output buffer is at least this large, it is guaranteed\n * that psa_cipher_update() will not fail due to an insufficient buffer size.\n *\n * See also #PSA_CIPHER_UPDATE_OUTPUT_SIZE(\\p key_type, \\p alg, \\p input_length).\n *\n * \\param input_length  Size of the input in bytes.\n */\n#define PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(input_length)     \\\n    (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, input_length))\n\n/** A sufficient ciphertext buffer size for psa_cipher_finish().\n *\n * If the size of the ciphertext buffer is at least this large, it is\n * guaranteed that psa_cipher_finish() will not fail due to an insufficient\n * ciphertext buffer size. The actual size of the output might be smaller in\n * any given call.\n *\n * See also #PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE().\n *\n * \\param key_type      A symmetric key type that is compatible with algorithm\n *                      alg.\n * \\param alg           A cipher algorithm (PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_CIPHER(\\p alg) is true).\n * \\return              A sufficient output size for the specified key type and\n *                      algorithm. If the key type or cipher algorithm is not\n *                      recognized, or the parameters are incompatible, return 0.\n */\n#define PSA_CIPHER_FINISH_OUTPUT_SIZE(key_type, alg)    \\\n    (PSA_ALG_IS_CIPHER(alg) ?                           \\\n     (alg == PSA_ALG_CBC_PKCS7 ?                        \\\n      PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) :         \\\n      0u) :                                             \\\n     0u)\n\n/** A sufficient ciphertext buffer size for psa_cipher_finish(), for any of the\n *  supported key types and cipher algorithms.\n *\n * See also #PSA_CIPHER_FINISH_OUTPUT_SIZE(\\p key_type, \\p alg).\n */\n#define PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE           \\\n    (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE)\n\n#endif /* PSA_CRYPTO_SIZES_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_struct.h",
    "content": "/**\n * \\file psa/crypto_struct.h\n *\n * \\brief PSA cryptography module: Mbed TLS structured type implementations\n *\n * \\note This file may not be included directly. Applications must\n * include psa/crypto.h.\n *\n * This file contains the definitions of some data structures with\n * implementation-specific definitions.\n *\n * In implementations with isolation between the application and the\n * cryptography module, it is expected that the front-end and the back-end\n * would have different versions of this file.\n *\n * <h3>Design notes about multipart operation structures</h3>\n *\n * For multipart operations without driver delegation support, each multipart\n * operation structure contains a `psa_algorithm_t alg` field which indicates\n * which specific algorithm the structure is for. When the structure is not in\n * use, `alg` is 0. Most of the structure consists of a union which is\n * discriminated by `alg`.\n *\n * For multipart operations with driver delegation support, each multipart\n * operation structure contains an `unsigned int id` field indicating which\n * driver got assigned to do the operation. When the structure is not in use,\n * 'id' is 0. The structure contains also a driver context which is the union\n * of the contexts of all drivers able to handle the type of multipart\n * operation.\n *\n * Note that when `alg` or `id` is 0, the content of other fields is undefined.\n * In particular, it is not guaranteed that a freshly-initialized structure\n * is all-zero: we initialize structures to something like `{0, 0}`, which\n * is only guaranteed to initializes the first member of the union;\n * GCC and Clang initialize the whole structure to 0 (at the time of writing),\n * but MSVC and CompCert don't.\n *\n * In Mbed TLS, multipart operation structures live independently from\n * the key. This allows Mbed TLS to free the key objects when destroying\n * a key slot. If a multipart operation needs to remember the key after\n * the setup function returns, the operation structure needs to contain a\n * copy of the key.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_STRUCT_H\n#define PSA_CRYPTO_STRUCT_H\n#include \"mbedtls/private_access.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * Include the build-time configuration information header. Here, we do not\n * include `\"mbedtls/build_info.h\"` directly but `\"psa/build_info.h\"`, which\n * is basically just an alias to it. This is to ease the maintenance of the\n * TF-PSA-Crypto repository which has a different build system and\n * configuration.\n */\n#include \"psa/build_info.h\"\n\n/* Include the context definition for the compiled-in drivers for the primitive\n * algorithms. */\n#include \"psa/crypto_driver_contexts_primitives.h\"\n\nstruct psa_hash_operation_s {\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n    mbedtls_psa_client_handle_t handle;\n#else\n    /** Unique ID indicating which driver got assigned to do the\n     * operation. Since driver contexts are driver-specific, swapping\n     * drivers halfway through the operation is not supported.\n     * ID values are auto-generated in psa_driver_wrappers.h.\n     * ID value zero means the context is not valid or not assigned to\n     * any driver (i.e. the driver context is not active, in use). */\n    unsigned int MBEDTLS_PRIVATE(id);\n    psa_driver_hash_context_t MBEDTLS_PRIVATE(ctx);\n#endif\n};\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n#define PSA_HASH_OPERATION_INIT { 0 }\n#else\n#define PSA_HASH_OPERATION_INIT { 0, { 0 } }\n#endif\nstatic inline struct psa_hash_operation_s psa_hash_operation_init(void)\n{\n    const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT;\n    return v;\n}\n\nstruct psa_cipher_operation_s {\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n    mbedtls_psa_client_handle_t handle;\n#else\n    /** Unique ID indicating which driver got assigned to do the\n     * operation. Since driver contexts are driver-specific, swapping\n     * drivers halfway through the operation is not supported.\n     * ID values are auto-generated in psa_crypto_driver_wrappers.h\n     * ID value zero means the context is not valid or not assigned to\n     * any driver (i.e. none of the driver contexts are active). */\n    unsigned int MBEDTLS_PRIVATE(id);\n\n    unsigned int MBEDTLS_PRIVATE(iv_required) : 1;\n    unsigned int MBEDTLS_PRIVATE(iv_set) : 1;\n\n    uint8_t MBEDTLS_PRIVATE(default_iv_length);\n\n    psa_driver_cipher_context_t MBEDTLS_PRIVATE(ctx);\n#endif\n};\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n#define PSA_CIPHER_OPERATION_INIT { 0 }\n#else\n#define PSA_CIPHER_OPERATION_INIT { 0, 0, 0, 0, { 0 } }\n#endif\nstatic inline struct psa_cipher_operation_s psa_cipher_operation_init(void)\n{\n    const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT;\n    return v;\n}\n\n/* Include the context definition for the compiled-in drivers for the composite\n * algorithms. */\n#include \"psa/crypto_driver_contexts_composites.h\"\n\nstruct psa_mac_operation_s {\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n    mbedtls_psa_client_handle_t handle;\n#else\n    /** Unique ID indicating which driver got assigned to do the\n     * operation. Since driver contexts are driver-specific, swapping\n     * drivers halfway through the operation is not supported.\n     * ID values are auto-generated in psa_driver_wrappers.h\n     * ID value zero means the context is not valid or not assigned to\n     * any driver (i.e. none of the driver contexts are active). */\n    unsigned int MBEDTLS_PRIVATE(id);\n    uint8_t MBEDTLS_PRIVATE(mac_size);\n    unsigned int MBEDTLS_PRIVATE(is_sign) : 1;\n    psa_driver_mac_context_t MBEDTLS_PRIVATE(ctx);\n#endif\n};\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n#define PSA_MAC_OPERATION_INIT { 0 }\n#else\n#define PSA_MAC_OPERATION_INIT { 0, 0, 0, { 0 } }\n#endif\nstatic inline struct psa_mac_operation_s psa_mac_operation_init(void)\n{\n    const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT;\n    return v;\n}\n\nstruct psa_aead_operation_s {\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n    mbedtls_psa_client_handle_t handle;\n#else\n    /** Unique ID indicating which driver got assigned to do the\n     * operation. Since driver contexts are driver-specific, swapping\n     * drivers halfway through the operation is not supported.\n     * ID values are auto-generated in psa_crypto_driver_wrappers.h\n     * ID value zero means the context is not valid or not assigned to\n     * any driver (i.e. none of the driver contexts are active). */\n    unsigned int MBEDTLS_PRIVATE(id);\n\n    psa_algorithm_t MBEDTLS_PRIVATE(alg);\n    psa_key_type_t MBEDTLS_PRIVATE(key_type);\n\n    size_t MBEDTLS_PRIVATE(ad_remaining);\n    size_t MBEDTLS_PRIVATE(body_remaining);\n\n    unsigned int MBEDTLS_PRIVATE(nonce_set) : 1;\n    unsigned int MBEDTLS_PRIVATE(lengths_set) : 1;\n    unsigned int MBEDTLS_PRIVATE(ad_started) : 1;\n    unsigned int MBEDTLS_PRIVATE(body_started) : 1;\n    unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1;\n\n    psa_driver_aead_context_t MBEDTLS_PRIVATE(ctx);\n#endif\n};\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n#define PSA_AEAD_OPERATION_INIT { 0 }\n#else\n#define PSA_AEAD_OPERATION_INIT { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0 } }\n#endif\nstatic inline struct psa_aead_operation_s psa_aead_operation_init(void)\n{\n    const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT;\n    return v;\n}\n\n/* Include the context definition for the compiled-in drivers for the key\n * derivation algorithms. */\n#include \"psa/crypto_driver_contexts_key_derivation.h\"\n\nstruct psa_key_derivation_s {\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n    mbedtls_psa_client_handle_t handle;\n#else\n    psa_algorithm_t MBEDTLS_PRIVATE(alg);\n    unsigned int MBEDTLS_PRIVATE(can_output_key) : 1;\n    size_t MBEDTLS_PRIVATE(capacity);\n    psa_driver_key_derivation_context_t MBEDTLS_PRIVATE(ctx);\n#endif\n};\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n#define PSA_KEY_DERIVATION_OPERATION_INIT { 0 }\n#else\n/* This only zeroes out the first byte in the union, the rest is unspecified. */\n#define PSA_KEY_DERIVATION_OPERATION_INIT { 0, 0, 0, { 0 } }\n#endif\nstatic inline struct psa_key_derivation_s psa_key_derivation_operation_init(\n    void)\n{\n    const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT;\n    return v;\n}\n\nstruct psa_custom_key_parameters_s {\n    /* Future versions may add other fields in this structure. */\n    uint32_t flags;\n};\n\n/** The default production parameters for key generation or key derivation.\n *\n * Calling psa_generate_key_custom() or psa_key_derivation_output_key_custom()\n * with `custom=PSA_CUSTOM_KEY_PARAMETERS_INIT` and `custom_data_length=0` is\n * equivalent to calling psa_generate_key() or psa_key_derivation_output_key()\n * respectively.\n */\n#define PSA_CUSTOM_KEY_PARAMETERS_INIT { 0 }\n\n#ifndef __cplusplus\n/* Omitted when compiling in C++, because one of the parameters is a\n * pointer to a struct with a flexible array member, and that is not\n * standard C++.\n * https://github.com/Mbed-TLS/mbedtls/issues/9020\n */\n/* This is a deprecated variant of `struct psa_custom_key_parameters_s`.\n * It has exactly the same layout, plus an extra field which is a flexible\n * array member. Thus a `const struct psa_key_production_parameters_s *`\n * can be passed to any function that reads a\n * `const struct psa_custom_key_parameters_s *`.\n */\nstruct psa_key_production_parameters_s {\n    uint32_t flags;\n    uint8_t data[];\n};\n\n/** The default production parameters for key generation or key derivation.\n *\n * Calling psa_generate_key_ext() or psa_key_derivation_output_key_ext()\n * with `params=PSA_KEY_PRODUCTION_PARAMETERS_INIT` and\n * `params_data_length == 0` is equivalent to\n * calling psa_generate_key() or psa_key_derivation_output_key()\n * respectively.\n */\n#define PSA_KEY_PRODUCTION_PARAMETERS_INIT { 0 }\n#endif /* !__cplusplus */\n\nstruct psa_key_policy_s {\n    psa_key_usage_t MBEDTLS_PRIVATE(usage);\n    psa_algorithm_t MBEDTLS_PRIVATE(alg);\n    psa_algorithm_t MBEDTLS_PRIVATE(alg2);\n};\ntypedef struct psa_key_policy_s psa_key_policy_t;\n\n#define PSA_KEY_POLICY_INIT { 0, 0, 0 }\nstatic inline struct psa_key_policy_s psa_key_policy_init(void)\n{\n    const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT;\n    return v;\n}\n\n/* The type used internally for key sizes.\n * Public interfaces use size_t, but internally we use a smaller type. */\ntypedef uint16_t psa_key_bits_t;\n/* The maximum value of the type used to represent bit-sizes.\n * This is used to mark an invalid key size. */\n#define PSA_KEY_BITS_TOO_LARGE          ((psa_key_bits_t) -1)\n/* The maximum size of a key in bits.\n * Currently defined as the maximum that can be represented, rounded down\n * to a whole number of bytes.\n * This is an uncast value so that it can be used in preprocessor\n * conditionals. */\n#define PSA_MAX_KEY_BITS 0xfff8\n\nstruct psa_key_attributes_s {\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    psa_key_slot_number_t MBEDTLS_PRIVATE(slot_number);\n    int MBEDTLS_PRIVATE(has_slot_number);\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n    psa_key_type_t MBEDTLS_PRIVATE(type);\n    psa_key_bits_t MBEDTLS_PRIVATE(bits);\n    psa_key_lifetime_t MBEDTLS_PRIVATE(lifetime);\n    psa_key_policy_t MBEDTLS_PRIVATE(policy);\n    /* This type has a different layout in the client view wrt the\n     * service view of the key id, i.e. in service view usually is\n     * expected to have MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined\n     * thus adding an owner field to the standard psa_key_id_t. For\n     * implementations with client/service separation, this means the\n     * object will be marshalled through a transport channel and\n     * interpreted differently at each side of the transport. Placing\n     * it at the end of structures allows to interpret the structure\n     * at the client without reorganizing the memory layout of the\n     * struct\n     */\n    mbedtls_svc_key_id_t MBEDTLS_PRIVATE(id);\n};\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n#define PSA_KEY_ATTRIBUTES_MAYBE_SLOT_NUMBER 0, 0,\n#else\n#define PSA_KEY_ATTRIBUTES_MAYBE_SLOT_NUMBER\n#endif\n#define PSA_KEY_ATTRIBUTES_INIT { PSA_KEY_ATTRIBUTES_MAYBE_SLOT_NUMBER \\\n                                      PSA_KEY_TYPE_NONE, 0,            \\\n                                      PSA_KEY_LIFETIME_VOLATILE,       \\\n                                      PSA_KEY_POLICY_INIT,             \\\n                                      MBEDTLS_SVC_KEY_ID_INIT }\n\nstatic inline struct psa_key_attributes_s psa_key_attributes_init(void)\n{\n    const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT;\n    return v;\n}\n\nstatic inline void psa_set_key_id(psa_key_attributes_t *attributes,\n                                  mbedtls_svc_key_id_t key)\n{\n    psa_key_lifetime_t lifetime = attributes->MBEDTLS_PRIVATE(lifetime);\n\n    attributes->MBEDTLS_PRIVATE(id) = key;\n\n    if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) {\n        attributes->MBEDTLS_PRIVATE(lifetime) =\n            PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(\n                PSA_KEY_LIFETIME_PERSISTENT,\n                PSA_KEY_LIFETIME_GET_LOCATION(lifetime));\n    }\n}\n\nstatic inline mbedtls_svc_key_id_t psa_get_key_id(\n    const psa_key_attributes_t *attributes)\n{\n    return attributes->MBEDTLS_PRIVATE(id);\n}\n\n#ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER\nstatic inline void mbedtls_set_key_owner_id(psa_key_attributes_t *attributes,\n                                            mbedtls_key_owner_id_t owner)\n{\n    attributes->MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(owner) = owner;\n}\n#endif\n\nstatic inline void psa_set_key_lifetime(psa_key_attributes_t *attributes,\n                                        psa_key_lifetime_t lifetime)\n{\n    attributes->MBEDTLS_PRIVATE(lifetime) = lifetime;\n    if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) {\n#ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER\n        attributes->MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(key_id) = 0;\n#else\n        attributes->MBEDTLS_PRIVATE(id) = 0;\n#endif\n    }\n}\n\nstatic inline psa_key_lifetime_t psa_get_key_lifetime(\n    const psa_key_attributes_t *attributes)\n{\n    return attributes->MBEDTLS_PRIVATE(lifetime);\n}\n\nstatic inline void psa_extend_key_usage_flags(psa_key_usage_t *usage_flags)\n{\n    if (*usage_flags & PSA_KEY_USAGE_SIGN_HASH) {\n        *usage_flags |= PSA_KEY_USAGE_SIGN_MESSAGE;\n    }\n\n    if (*usage_flags & PSA_KEY_USAGE_VERIFY_HASH) {\n        *usage_flags |= PSA_KEY_USAGE_VERIFY_MESSAGE;\n    }\n}\n\nstatic inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes,\n                                           psa_key_usage_t usage_flags)\n{\n    psa_extend_key_usage_flags(&usage_flags);\n    attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage) = usage_flags;\n}\n\nstatic inline psa_key_usage_t psa_get_key_usage_flags(\n    const psa_key_attributes_t *attributes)\n{\n    return attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage);\n}\n\nstatic inline void psa_set_key_algorithm(psa_key_attributes_t *attributes,\n                                         psa_algorithm_t alg)\n{\n    attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg) = alg;\n}\n\nstatic inline psa_algorithm_t psa_get_key_algorithm(\n    const psa_key_attributes_t *attributes)\n{\n    return attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg);\n}\n\nstatic inline void psa_set_key_type(psa_key_attributes_t *attributes,\n                                    psa_key_type_t type)\n{\n    attributes->MBEDTLS_PRIVATE(type) = type;\n}\n\nstatic inline psa_key_type_t psa_get_key_type(\n    const psa_key_attributes_t *attributes)\n{\n    return attributes->MBEDTLS_PRIVATE(type);\n}\n\nstatic inline void psa_set_key_bits(psa_key_attributes_t *attributes,\n                                    size_t bits)\n{\n    if (bits > PSA_MAX_KEY_BITS) {\n        attributes->MBEDTLS_PRIVATE(bits) = PSA_KEY_BITS_TOO_LARGE;\n    } else {\n        attributes->MBEDTLS_PRIVATE(bits) = (psa_key_bits_t) bits;\n    }\n}\n\nstatic inline size_t psa_get_key_bits(\n    const psa_key_attributes_t *attributes)\n{\n    return attributes->MBEDTLS_PRIVATE(bits);\n}\n\n/**\n * \\brief The context for PSA interruptible hash signing.\n */\nstruct psa_sign_hash_interruptible_operation_s {\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n    mbedtls_psa_client_handle_t handle;\n#else\n    /** Unique ID indicating which driver got assigned to do the\n     * operation. Since driver contexts are driver-specific, swapping\n     * drivers halfway through the operation is not supported.\n     * ID values are auto-generated in psa_crypto_driver_wrappers.h\n     * ID value zero means the context is not valid or not assigned to\n     * any driver (i.e. none of the driver contexts are active). */\n    unsigned int MBEDTLS_PRIVATE(id);\n\n    psa_driver_sign_hash_interruptible_context_t MBEDTLS_PRIVATE(ctx);\n\n    unsigned int MBEDTLS_PRIVATE(error_occurred) : 1;\n\n    uint32_t MBEDTLS_PRIVATE(num_ops);\n#endif\n};\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n#define PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 }\n#else\n#define PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0, { 0 }, 0, 0 }\n#endif\n\nstatic inline struct psa_sign_hash_interruptible_operation_s\npsa_sign_hash_interruptible_operation_init(void)\n{\n    const struct psa_sign_hash_interruptible_operation_s v =\n        PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT;\n\n    return v;\n}\n\n/**\n * \\brief The context for PSA interruptible hash verification.\n */\nstruct psa_verify_hash_interruptible_operation_s {\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n    mbedtls_psa_client_handle_t handle;\n#else\n    /** Unique ID indicating which driver got assigned to do the\n     * operation. Since driver contexts are driver-specific, swapping\n     * drivers halfway through the operation is not supported.\n     * ID values are auto-generated in psa_crypto_driver_wrappers.h\n     * ID value zero means the context is not valid or not assigned to\n     * any driver (i.e. none of the driver contexts are active). */\n    unsigned int MBEDTLS_PRIVATE(id);\n\n    psa_driver_verify_hash_interruptible_context_t MBEDTLS_PRIVATE(ctx);\n\n    unsigned int MBEDTLS_PRIVATE(error_occurred) : 1;\n\n    uint32_t MBEDTLS_PRIVATE(num_ops);\n#endif\n};\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)\n#define PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 }\n#else\n#define PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT { 0, { 0 }, 0, 0 }\n#endif\n\nstatic inline struct psa_verify_hash_interruptible_operation_s\npsa_verify_hash_interruptible_operation_init(void)\n{\n    const struct psa_verify_hash_interruptible_operation_s v =\n        PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT;\n\n    return v;\n}\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* PSA_CRYPTO_STRUCT_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_types.h",
    "content": "/**\n * \\file psa/crypto_types.h\n *\n * \\brief PSA cryptography module: type aliases.\n *\n * \\note This file may not be included directly. Applications must\n * include psa/crypto.h. Drivers must include the appropriate driver\n * header file.\n *\n * This file contains portable definitions of integral types for properties\n * of cryptographic keys, designations of cryptographic algorithms, and\n * error codes returned by the library.\n *\n * This header file does not declare any function.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_TYPES_H\n#define PSA_CRYPTO_TYPES_H\n\n/*\n * Include the build-time configuration information header. Here, we do not\n * include `\"mbedtls/build_info.h\"` directly but `\"psa/build_info.h\"`, which\n * is basically just an alias to it. This is to ease the maintenance of the\n * TF-PSA-Crypto repository which has a different build system and\n * configuration.\n */\n#include \"psa/build_info.h\"\n\n/* Define the MBEDTLS_PRIVATE macro. */\n#include \"mbedtls/private_access.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_PLATFORM_FILE)\n#include MBEDTLS_PSA_CRYPTO_PLATFORM_FILE\n#else\n#include \"crypto_platform.h\"\n#endif\n\n#include <stdint.h>\n\n/** \\defgroup error Error codes\n * @{\n */\n\n/**\n * \\brief Function return status.\n *\n * This is either #PSA_SUCCESS (which is zero), indicating success,\n * or a small negative value indicating that an error occurred. Errors are\n * encoded as one of the \\c PSA_ERROR_xxx values defined here. */\n/* If #PSA_SUCCESS is already defined, it means that #psa_status_t\n * is also defined in an external header, so prevent its multiple\n * definition.\n */\n#ifndef PSA_SUCCESS\ntypedef int32_t psa_status_t;\n#endif\n\n/**@}*/\n\n/** \\defgroup crypto_types Key and algorithm types\n * @{\n */\n\n/** \\brief Encoding of a key type.\n *\n * Values of this type are generally constructed by macros called\n * `PSA_KEY_TYPE_xxx`.\n *\n * \\note Values of this type are encoded in the persistent key store.\n *       Any changes to existing values will require bumping the storage\n *       format version and providing a translation when reading the old\n *       format.\n */\ntypedef uint16_t psa_key_type_t;\n\n/** The type of PSA elliptic curve family identifiers.\n *\n * Values of this type are generally constructed by macros called\n * `PSA_ECC_FAMILY_xxx`.\n *\n * The curve identifier is required to create an ECC key using the\n * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY()\n * macros.\n *\n * Values defined by this standard will never be in the range 0x80-0xff.\n * Vendors who define additional families must use an encoding in this range.\n *\n * \\note Values of this type are encoded in the persistent key store.\n *       Any changes to existing values will require bumping the storage\n *       format version and providing a translation when reading the old\n *       format.\n */\ntypedef uint8_t psa_ecc_family_t;\n\n/** The type of PSA Diffie-Hellman group family identifiers.\n *\n * Values of this type are generally constructed by macros called\n * `PSA_DH_FAMILY_xxx`.\n *\n * The group identifier is required to create a Diffie-Hellman key using the\n * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY()\n * macros.\n *\n * Values defined by this standard will never be in the range 0x80-0xff.\n * Vendors who define additional families must use an encoding in this range.\n *\n * \\note Values of this type are encoded in the persistent key store.\n *       Any changes to existing values will require bumping the storage\n *       format version and providing a translation when reading the old\n *       format.\n */\ntypedef uint8_t psa_dh_family_t;\n\n/** \\brief Encoding of a cryptographic algorithm.\n *\n * Values of this type are generally constructed by macros called\n * `PSA_ALG_xxx`.\n *\n * For algorithms that can be applied to multiple key types, this type\n * does not encode the key type. For example, for symmetric ciphers\n * based on a block cipher, #psa_algorithm_t encodes the block cipher\n * mode and the padding mode while the block cipher itself is encoded\n * via #psa_key_type_t.\n *\n * \\note Values of this type are encoded in the persistent key store.\n *       Any changes to existing values will require bumping the storage\n *       format version and providing a translation when reading the old\n *       format.\n */\ntypedef uint32_t psa_algorithm_t;\n\n/**@}*/\n\n/** \\defgroup key_lifetimes Key lifetimes\n * @{\n */\n\n/** Encoding of key lifetimes.\n *\n * The lifetime of a key indicates where it is stored and what system actions\n * may create and destroy it.\n *\n * Lifetime values have the following structure:\n * - Bits 0-7 (#PSA_KEY_LIFETIME_GET_PERSISTENCE(\\c lifetime)):\n *   persistence level. This value indicates what device management\n *   actions can cause it to be destroyed. In particular, it indicates\n *   whether the key is _volatile_ or _persistent_.\n *   See ::psa_key_persistence_t for more information.\n * - Bits 8-31 (#PSA_KEY_LIFETIME_GET_LOCATION(\\c lifetime)):\n *   location indicator. This value indicates which part of the system\n *   has access to the key material and can perform operations using the key.\n *   See ::psa_key_location_t for more information.\n *\n * Volatile keys are automatically destroyed when the application instance\n * terminates or on a power reset of the device. Persistent keys are\n * preserved until the application explicitly destroys them or until an\n * integration-specific device management event occurs (for example,\n * a factory reset).\n *\n * Persistent keys have a key identifier of type #mbedtls_svc_key_id_t.\n * This identifier remains valid throughout the lifetime of the key,\n * even if the application instance that created the key terminates.\n * The application can call psa_open_key() to open a persistent key that\n * it created previously.\n *\n * The default lifetime of a key is #PSA_KEY_LIFETIME_VOLATILE. The lifetime\n * #PSA_KEY_LIFETIME_PERSISTENT is supported if persistent storage is\n * available. Other lifetime values may be supported depending on the\n * library configuration.\n *\n * Values of this type are generally constructed by macros called\n * `PSA_KEY_LIFETIME_xxx`.\n *\n * \\note Values of this type are encoded in the persistent key store.\n *       Any changes to existing values will require bumping the storage\n *       format version and providing a translation when reading the old\n *       format.\n */\ntypedef uint32_t psa_key_lifetime_t;\n\n/** Encoding of key persistence levels.\n *\n * What distinguishes different persistence levels is what device management\n * events may cause keys to be destroyed. _Volatile_ keys are destroyed\n * by a power reset. Persistent keys may be destroyed by events such as\n * a transfer of ownership or a factory reset. What management events\n * actually affect persistent keys at different levels is outside the\n * scope of the PSA Cryptography specification.\n *\n * The PSA Cryptography specification defines the following values of\n * persistence levels:\n * - \\c 0 = #PSA_KEY_PERSISTENCE_VOLATILE: volatile key.\n *   A volatile key is automatically destroyed by the implementation when\n *   the application instance terminates. In particular, a volatile key\n *   is automatically destroyed on a power reset of the device.\n * - \\c 1 = #PSA_KEY_PERSISTENCE_DEFAULT:\n *   persistent key with a default lifetime.\n * - \\c 2-254: currently not supported by Mbed TLS.\n * - \\c 255 = #PSA_KEY_PERSISTENCE_READ_ONLY:\n *   read-only or write-once key.\n *   A key with this persistence level cannot be destroyed.\n *   Mbed TLS does not currently offer a way to create such keys, but\n *   integrations of Mbed TLS can use it for built-in keys that the\n *   application cannot modify (for example, a hardware unique key (HUK)).\n *\n * \\note Key persistence levels are 8-bit values. Key management\n *       interfaces operate on lifetimes (type ::psa_key_lifetime_t) which\n *       encode the persistence as the lower 8 bits of a 32-bit value.\n *\n * \\note Values of this type are encoded in the persistent key store.\n *       Any changes to existing values will require bumping the storage\n *       format version and providing a translation when reading the old\n *       format.\n */\ntypedef uint8_t psa_key_persistence_t;\n\n/** Encoding of key location indicators.\n *\n * If an integration of Mbed TLS can make calls to external\n * cryptoprocessors such as secure elements, the location of a key\n * indicates which secure element performs the operations on the key.\n * Depending on the design of the secure element, the key\n * material may be stored either in the secure element, or\n * in wrapped (encrypted) form alongside the key metadata in the\n * primary local storage.\n *\n * The PSA Cryptography API specification defines the following values of\n * location indicators:\n * - \\c 0: primary local storage.\n *   This location is always available.\n *   The primary local storage is typically the same storage area that\n *   contains the key metadata.\n * - \\c 1: primary secure element.\n *   Integrations of Mbed TLS should support this value if there is a secure\n *   element attached to the operating environment.\n *   As a guideline, secure elements may provide higher resistance against\n *   side channel and physical attacks than the primary local storage, but may\n *   have restrictions on supported key types, sizes, policies and operations\n *   and may have different performance characteristics.\n * - \\c 2-0x7fffff: other locations defined by a PSA specification.\n *   The PSA Cryptography API does not currently assign any meaning to these\n *   locations, but future versions of that specification or other PSA\n *   specifications may do so.\n * - \\c 0x800000-0xffffff: vendor-defined locations.\n *   No PSA specification will assign a meaning to locations in this range.\n *\n * \\note Key location indicators are 24-bit values. Key management\n *       interfaces operate on lifetimes (type ::psa_key_lifetime_t) which\n *       encode the location as the upper 24 bits of a 32-bit value.\n *\n * \\note Values of this type are encoded in the persistent key store.\n *       Any changes to existing values will require bumping the storage\n *       format version and providing a translation when reading the old\n *       format.\n */\ntypedef uint32_t psa_key_location_t;\n\n/** Encoding of identifiers of persistent keys.\n *\n * - Applications may freely choose key identifiers in the range\n *   #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX.\n * - The implementation may define additional key identifiers in the range\n *   #PSA_KEY_ID_VENDOR_MIN to #PSA_KEY_ID_VENDOR_MAX.\n * - 0 is reserved as an invalid key identifier.\n * - Key identifiers outside these ranges are reserved for future use.\n *\n * \\note Values of this type are encoded in the persistent key store.\n *       Any changes to how values are allocated must require careful\n *       consideration to allow backward compatibility.\n */\ntypedef uint32_t psa_key_id_t;\n\n/** Encoding of key identifiers as seen inside the PSA Crypto implementation.\n *\n * When PSA Crypto is built as a library inside an application, this type\n * is identical to #psa_key_id_t. When PSA Crypto is built as a service\n * that can store keys on behalf of multiple clients, this type\n * encodes the #psa_key_id_t value seen by each client application as\n * well as extra information that identifies the client that owns\n * the key.\n *\n * \\note Values of this type are encoded in the persistent key store.\n *       Any changes to existing values will require bumping the storage\n *       format version and providing a translation when reading the old\n *       format.\n */\n#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)\ntypedef psa_key_id_t mbedtls_svc_key_id_t;\n\n#else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */\n/* Implementation-specific: The Mbed TLS library can be built as\n * part of a multi-client service that exposes the PSA Cryptography API in each\n * client and encodes the client identity in the key identifier argument of\n * functions such as psa_open_key().\n */\ntypedef struct {\n    psa_key_id_t MBEDTLS_PRIVATE(key_id);\n    mbedtls_key_owner_id_t MBEDTLS_PRIVATE(owner);\n} mbedtls_svc_key_id_t;\n\n#endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */\n\n/**@}*/\n\n/** \\defgroup policy Key policies\n * @{\n */\n\n/** \\brief Encoding of permitted usage on a key.\n *\n * Values of this type are generally constructed as bitwise-ors of macros\n * called `PSA_KEY_USAGE_xxx`.\n *\n * \\note Values of this type are encoded in the persistent key store.\n *       Any changes to existing values will require bumping the storage\n *       format version and providing a translation when reading the old\n *       format.\n */\ntypedef uint32_t psa_key_usage_t;\n\n/**@}*/\n\n/** \\defgroup attributes Key attributes\n * @{\n */\n\n/** The type of a structure containing key attributes.\n *\n * This is an opaque structure that can represent the metadata of a key\n * object. Metadata that can be stored in attributes includes:\n * - The location of the key in storage, indicated by its key identifier\n *   and its lifetime.\n * - The key's policy, comprising usage flags and a specification of\n *   the permitted algorithm(s).\n * - Information about the key itself: the key type and its size.\n * - Additional implementation-defined attributes.\n *\n * The actual key material is not considered an attribute of a key.\n * Key attributes do not contain information that is generally considered\n * highly confidential.\n *\n * An attribute structure works like a simple data structure where each function\n * `psa_set_key_xxx` sets a field and the corresponding function\n * `psa_get_key_xxx` retrieves the value of the corresponding field.\n * However, a future version of the library  may report values that are\n * equivalent to the original one, but have a different encoding. Invalid\n * values may be mapped to different, also invalid values.\n *\n * An attribute structure may contain references to auxiliary resources,\n * for example pointers to allocated memory or indirect references to\n * pre-calculated values. In order to free such resources, the application\n * must call psa_reset_key_attributes(). As an exception, calling\n * psa_reset_key_attributes() on an attribute structure is optional if\n * the structure has only been modified by the following functions\n * since it was initialized or last reset with psa_reset_key_attributes():\n * - psa_set_key_id()\n * - psa_set_key_lifetime()\n * - psa_set_key_type()\n * - psa_set_key_bits()\n * - psa_set_key_usage_flags()\n * - psa_set_key_algorithm()\n *\n * Before calling any function on a key attribute structure, the application\n * must initialize it by any of the following means:\n * - Set the structure to all-bits-zero, for example:\n *   \\code\n *   psa_key_attributes_t attributes;\n *   memset(&attributes, 0, sizeof(attributes));\n *   \\endcode\n * - Initialize the structure to logical zero values, for example:\n *   \\code\n *   psa_key_attributes_t attributes = {0};\n *   \\endcode\n * - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT,\n *   for example:\n *   \\code\n *   psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n *   \\endcode\n * - Assign the result of the function psa_key_attributes_init()\n *   to the structure, for example:\n *   \\code\n *   psa_key_attributes_t attributes;\n *   attributes = psa_key_attributes_init();\n *   \\endcode\n *\n * A freshly initialized attribute structure contains the following\n * values:\n *\n * - lifetime: #PSA_KEY_LIFETIME_VOLATILE.\n * - key identifier: 0 (which is not a valid key identifier).\n * - type: \\c 0 (meaning that the type is unspecified).\n * - key size: \\c 0 (meaning that the size is unspecified).\n * - usage flags: \\c 0 (which allows no usage except exporting a public key).\n * - algorithm: \\c 0 (which allows no cryptographic usage, but allows\n *   exporting).\n *\n * A typical sequence to create a key is as follows:\n * -# Create and initialize an attribute structure.\n * -# If the key is persistent, call psa_set_key_id().\n *    Also call psa_set_key_lifetime() to place the key in a non-default\n *    location.\n * -# Set the key policy with psa_set_key_usage_flags() and\n *    psa_set_key_algorithm().\n * -# Set the key type with psa_set_key_type().\n *    Skip this step if copying an existing key with psa_copy_key().\n * -# When generating a random key with psa_generate_key() or deriving a key\n *    with psa_key_derivation_output_key(), set the desired key size with\n *    psa_set_key_bits().\n * -# Call a key creation function: psa_import_key(), psa_generate_key(),\n *    psa_key_derivation_output_key() or psa_copy_key(). This function reads\n *    the attribute structure, creates a key with these attributes, and\n *    outputs a key identifier to the newly created key.\n * -# The attribute structure is now no longer necessary.\n *    You may call psa_reset_key_attributes(), although this is optional\n *    with the workflow presented here because the attributes currently\n *    defined in this specification do not require any additional resources\n *    beyond the structure itself.\n *\n * A typical sequence to query a key's attributes is as follows:\n * -# Call psa_get_key_attributes().\n * -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that\n *    you are interested in.\n * -# Call psa_reset_key_attributes() to free any resources that may be\n *    used by the attribute structure.\n *\n * Once a key has been created, it is impossible to change its attributes.\n */\ntypedef struct psa_key_attributes_s psa_key_attributes_t;\n\n\n#ifndef __DOXYGEN_ONLY__\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n/* Mbed TLS defines this type in crypto_types.h because it is also\n * visible to applications through an implementation-specific extension.\n * For the PSA Cryptography specification, this type is only visible\n * via crypto_se_driver.h. */\ntypedef uint64_t psa_key_slot_number_t;\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n#endif /* !__DOXYGEN_ONLY__ */\n\n/**@}*/\n\n/** \\defgroup derivation Key derivation\n * @{\n */\n\n/** \\brief Encoding of the step of a key derivation.\n *\n * Values of this type are generally constructed by macros called\n * `PSA_KEY_DERIVATION_INPUT_xxx`.\n */\ntypedef uint16_t psa_key_derivation_step_t;\n\n/** \\brief Custom parameters for key generation or key derivation.\n *\n * This is a structure type with at least the following field:\n *\n * - \\c flags: an unsigned integer type. 0 for the default production parameters.\n *\n * Functions that take such a structure as input also take an associated\n * input buffer \\c custom_data of length \\c custom_data_length.\n *\n * The interpretation of this structure and the associated \\c custom_data\n * parameter depend on the type of the created key.\n *\n * - #PSA_KEY_TYPE_RSA_KEY_PAIR:\n *     - \\c flags: must be 0.\n *     - \\c custom_data: the public exponent, in little-endian order.\n *       This must be an odd integer and must not be 1.\n *       Implementations must support 65537, should support 3 and may\n *       support other values.\n *       When not using a driver, Mbed TLS supports values up to \\c INT_MAX.\n *       If this is empty, the default value 65537 is used.\n * - Other key types: reserved for future use. \\c flags must be 0.\n */\ntypedef struct psa_custom_key_parameters_s psa_custom_key_parameters_t;\n\n/** \\brief Custom parameters for key generation or key derivation.\n *\n * This is a structure type with at least the following fields:\n *\n * - \\c flags: an unsigned integer type. 0 for the default production parameters.\n * - \\c data: a flexible array of bytes.\n *\n * The interpretation of this structure depend on the type of the\n * created key.\n *\n * - #PSA_KEY_TYPE_RSA_KEY_PAIR:\n *     - \\c flags: must be 0.\n *     - \\c data: the public exponent, in little-endian order.\n *       This must be an odd integer and must not be 1.\n *       Implementations must support 65537, should support 3 and may\n *       support other values.\n *       When not using a driver, Mbed TLS supports values up to \\c INT_MAX.\n *       If this is empty or if the custom production parameters are omitted\n *       altogether, the default value 65537 is used.\n * - Other key types: reserved for future use. \\c flags must be 0.\n *\n */\ntypedef struct psa_key_production_parameters_s psa_key_production_parameters_t;\n\n/**@}*/\n\n#endif /* PSA_CRYPTO_TYPES_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/include/psa/crypto_values.h",
    "content": "/**\n * \\file psa/crypto_values.h\n *\n * \\brief PSA cryptography module: macros to build and analyze integer values.\n *\n * \\note This file may not be included directly. Applications must\n * include psa/crypto.h. Drivers must include the appropriate driver\n * header file.\n *\n * This file contains portable definitions of macros to build and analyze\n * values of integral types that encode properties of cryptographic keys,\n * designations of cryptographic algorithms, and error codes returned by\n * the library.\n *\n * Note that many of the constants defined in this file are embedded in\n * the persistent key store, as part of key metadata (including usage\n * policies). As a consequence, they must not be changed (unless the storage\n * format version changes).\n *\n * This header file only defines preprocessor macros.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_VALUES_H\n#define PSA_CRYPTO_VALUES_H\n#include \"mbedtls/private_access.h\"\n\n/** \\defgroup error Error codes\n * @{\n */\n\n/* PSA error codes */\n\n/* Error codes are standardized across PSA domains (framework, crypto, storage,\n * etc.). Do not change the values in this section or even the expansions\n * of each macro: it must be possible to `#include` both this header\n * and some other PSA component's headers in the same C source,\n * which will lead to duplicate definitions of the `PSA_SUCCESS` and\n * `PSA_ERROR_xxx` macros, which is ok if and only if the macros expand\n * to the same sequence of tokens.\n *\n * If you must add a new\n * value, check with the Arm PSA framework group to pick one that other\n * domains aren't already using. */\n\n/* Tell uncrustify not to touch the constant definitions, otherwise\n * it might change the spacing to something that is not PSA-compliant\n * (e.g. adding a space after casts).\n *\n * *INDENT-OFF*\n */\n\n/** The action was completed successfully. */\n#define PSA_SUCCESS ((psa_status_t)0)\n\n/** An error occurred that does not correspond to any defined\n * failure cause.\n *\n * Implementations may use this error code if none of the other standard\n * error codes are applicable. */\n#define PSA_ERROR_GENERIC_ERROR         ((psa_status_t)-132)\n\n/** The requested operation or a parameter is not supported\n * by this implementation.\n *\n * Implementations should return this error code when an enumeration\n * parameter such as a key type, algorithm, etc. is not recognized.\n * If a combination of parameters is recognized and identified as\n * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */\n#define PSA_ERROR_NOT_SUPPORTED         ((psa_status_t)-134)\n\n/** The requested action is denied by a policy.\n *\n * Implementations should return this error code when the parameters\n * are recognized as valid and supported, and a policy explicitly\n * denies the requested operation.\n *\n * If a subset of the parameters of a function call identify a\n * forbidden operation, and another subset of the parameters are\n * not valid or not supported, it is unspecified whether the function\n * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or\n * #PSA_ERROR_INVALID_ARGUMENT. */\n#define PSA_ERROR_NOT_PERMITTED         ((psa_status_t)-133)\n\n/** An output buffer is too small.\n *\n * Applications can call the \\c PSA_xxx_SIZE macro listed in the function\n * description to determine a sufficient buffer size.\n *\n * Implementations should preferably return this error code only\n * in cases when performing the operation with a larger output\n * buffer would succeed. However implementations may return this\n * error if a function has invalid or unsupported parameters in addition\n * to the parameters that determine the necessary output buffer size. */\n#define PSA_ERROR_BUFFER_TOO_SMALL      ((psa_status_t)-138)\n\n/** Asking for an item that already exists\n *\n * Implementations should return this error, when attempting\n * to write an item (like a key) that already exists. */\n#define PSA_ERROR_ALREADY_EXISTS        ((psa_status_t)-139)\n\n/** Asking for an item that doesn't exist\n *\n * Implementations should return this error, if a requested item (like\n * a key) does not exist. */\n#define PSA_ERROR_DOES_NOT_EXIST        ((psa_status_t)-140)\n\n/** The requested action cannot be performed in the current state.\n *\n * Multipart operations return this error when one of the\n * functions is called out of sequence. Refer to the function\n * descriptions for permitted sequencing of functions.\n *\n * Implementations shall not return this error code to indicate\n * that a key either exists or not,\n * but shall instead return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST\n * as applicable.\n *\n * Implementations shall not return this error code to indicate that a\n * key identifier is invalid, but shall return #PSA_ERROR_INVALID_HANDLE\n * instead. */\n#define PSA_ERROR_BAD_STATE             ((psa_status_t)-137)\n\n/** The parameters passed to the function are invalid.\n *\n * Implementations may return this error any time a parameter or\n * combination of parameters are recognized as invalid.\n *\n * Implementations shall not return this error code to indicate that a\n * key identifier is invalid, but shall return #PSA_ERROR_INVALID_HANDLE\n * instead.\n */\n#define PSA_ERROR_INVALID_ARGUMENT      ((psa_status_t)-135)\n\n/** There is not enough runtime memory.\n *\n * If the action is carried out across multiple security realms, this\n * error can refer to available memory in any of the security realms. */\n#define PSA_ERROR_INSUFFICIENT_MEMORY   ((psa_status_t)-141)\n\n/** There is not enough persistent storage.\n *\n * Functions that modify the key storage return this error code if\n * there is insufficient storage space on the host media. In addition,\n * many functions that do not otherwise access storage may return this\n * error code if the implementation requires a mandatory log entry for\n * the requested action and the log storage space is full. */\n#define PSA_ERROR_INSUFFICIENT_STORAGE  ((psa_status_t)-142)\n\n/** There was a communication failure inside the implementation.\n *\n * This can indicate a communication failure between the application\n * and an external cryptoprocessor or between the cryptoprocessor and\n * an external volatile or persistent memory. A communication failure\n * may be transient or permanent depending on the cause.\n *\n * \\warning If a function returns this error, it is undetermined\n * whether the requested action has completed or not. Implementations\n * should return #PSA_SUCCESS on successful completion whenever\n * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE\n * if the requested action was completed successfully in an external\n * cryptoprocessor but there was a breakdown of communication before\n * the cryptoprocessor could report the status to the application.\n */\n#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145)\n\n/** There was a storage failure that may have led to data loss.\n *\n * This error indicates that some persistent storage is corrupted.\n * It should not be used for a corruption of volatile memory\n * (use #PSA_ERROR_CORRUPTION_DETECTED), for a communication error\n * between the cryptoprocessor and its external storage (use\n * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is\n * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE).\n *\n * Note that a storage failure does not indicate that any data that was\n * previously read is invalid. However this previously read data may no\n * longer be readable from storage.\n *\n * When a storage failure occurs, it is no longer possible to ensure\n * the global integrity of the keystore. Depending on the global\n * integrity guarantees offered by the implementation, access to other\n * data may or may not fail even if the data is still readable but\n * its integrity cannot be guaranteed.\n *\n * Implementations should only use this error code to report a\n * permanent storage corruption. However application writers should\n * keep in mind that transient errors while reading the storage may be\n * reported using this error code. */\n#define PSA_ERROR_STORAGE_FAILURE       ((psa_status_t)-146)\n\n/** A hardware failure was detected.\n *\n * A hardware failure may be transient or permanent depending on the\n * cause. */\n#define PSA_ERROR_HARDWARE_FAILURE      ((psa_status_t)-147)\n\n/** A tampering attempt was detected.\n *\n * If an application receives this error code, there is no guarantee\n * that previously accessed or computed data was correct and remains\n * confidential. Applications should not perform any security function\n * and should enter a safe failure state.\n *\n * Implementations may return this error code if they detect an invalid\n * state that cannot happen during normal operation and that indicates\n * that the implementation's security guarantees no longer hold. Depending\n * on the implementation architecture and on its security and safety goals,\n * the implementation may forcibly terminate the application.\n *\n * This error code is intended as a last resort when a security breach\n * is detected and it is unsure whether the keystore data is still\n * protected. Implementations shall only return this error code\n * to report an alarm from a tampering detector, to indicate that\n * the confidentiality of stored data can no longer be guaranteed,\n * or to indicate that the integrity of previously returned data is now\n * considered compromised. Implementations shall not use this error code\n * to indicate a hardware failure that merely makes it impossible to\n * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE,\n * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE,\n * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code\n * instead).\n *\n * This error indicates an attack against the application. Implementations\n * shall not return this error code as a consequence of the behavior of\n * the application itself. */\n#define PSA_ERROR_CORRUPTION_DETECTED    ((psa_status_t)-151)\n\n/** There is not enough entropy to generate random data needed\n * for the requested action.\n *\n * This error indicates a failure of a hardware random generator.\n * Application writers should note that this error can be returned not\n * only by functions whose purpose is to generate random data, such\n * as key, IV or nonce generation, but also by functions that execute\n * an algorithm with a randomized result, as well as functions that\n * use randomization of intermediate computations as a countermeasure\n * to certain attacks.\n *\n * Implementations should avoid returning this error after psa_crypto_init()\n * has succeeded. Implementations should generate sufficient\n * entropy during initialization and subsequently use a cryptographically\n * secure pseudorandom generator (PRNG). However implementations may return\n * this error at any time if a policy requires the PRNG to be reseeded\n * during normal operation. */\n#define PSA_ERROR_INSUFFICIENT_ENTROPY  ((psa_status_t)-148)\n\n/** The signature, MAC or hash is incorrect.\n *\n * Verification functions return this error if the verification\n * calculations completed successfully, and the value to be verified\n * was determined to be incorrect.\n *\n * If the value to verify has an invalid size, implementations may return\n * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */\n#define PSA_ERROR_INVALID_SIGNATURE     ((psa_status_t)-149)\n\n/** The decrypted padding is incorrect.\n *\n * \\warning In some protocols, when decrypting data, it is essential that\n * the behavior of the application does not depend on whether the padding\n * is correct, down to precise timing. Applications should prefer\n * protocols that use authenticated encryption rather than plain\n * encryption. If the application must perform a decryption of\n * unauthenticated data, the application writer should take care not\n * to reveal whether the padding is invalid.\n *\n * Implementations should strive to make valid and invalid padding\n * as close as possible to indistinguishable to an external observer.\n * In particular, the timing of a decryption operation should not\n * depend on the validity of the padding. */\n#define PSA_ERROR_INVALID_PADDING       ((psa_status_t)-150)\n\n/** Return this error when there's insufficient data when attempting\n * to read from a resource. */\n#define PSA_ERROR_INSUFFICIENT_DATA     ((psa_status_t)-143)\n\n/** This can be returned if a function can no longer operate correctly.\n * For example, if an essential initialization operation failed or\n * a mutex operation failed. */\n#define PSA_ERROR_SERVICE_FAILURE       ((psa_status_t)-144)\n\n/** The key identifier is not valid. See also :ref:\\`key-handles\\`.\n */\n#define PSA_ERROR_INVALID_HANDLE        ((psa_status_t)-136)\n\n/** Stored data has been corrupted.\n *\n * This error indicates that some persistent storage has suffered corruption.\n * It does not indicate the following situations, which have specific error\n * codes:\n *\n * - A corruption of volatile memory - use #PSA_ERROR_CORRUPTION_DETECTED.\n * - A communication error between the cryptoprocessor and its external\n *   storage - use #PSA_ERROR_COMMUNICATION_FAILURE.\n * - When the storage is in a valid state but is full - use\n *   #PSA_ERROR_INSUFFICIENT_STORAGE.\n * - When the storage fails for other reasons - use\n *   #PSA_ERROR_STORAGE_FAILURE.\n * - When the stored data is not valid - use #PSA_ERROR_DATA_INVALID.\n *\n * \\note A storage corruption does not indicate that any data that was\n * previously read is invalid. However this previously read data might no\n * longer be readable from storage.\n *\n * When a storage failure occurs, it is no longer possible to ensure the\n * global integrity of the keystore.\n */\n#define PSA_ERROR_DATA_CORRUPT          ((psa_status_t)-152)\n\n/** Data read from storage is not valid for the implementation.\n *\n * This error indicates that some data read from storage does not have a valid\n * format. It does not indicate the following situations, which have specific\n * error codes:\n *\n * - When the storage or stored data is corrupted - use #PSA_ERROR_DATA_CORRUPT\n * - When the storage fails for other reasons - use #PSA_ERROR_STORAGE_FAILURE\n * - An invalid argument to the API - use #PSA_ERROR_INVALID_ARGUMENT\n *\n * This error is typically a result of either storage corruption on a\n * cleartext storage backend, or an attempt to read data that was\n * written by an incompatible version of the library.\n */\n#define PSA_ERROR_DATA_INVALID          ((psa_status_t)-153)\n\n/** The function that returns this status is defined as interruptible and\n *  still has work to do, thus the user should call the function again with the\n *  same operation context until it either returns #PSA_SUCCESS or any other\n *  error. This is not an error per se, more a notification of status.\n */\n#define PSA_OPERATION_INCOMPLETE           ((psa_status_t)-248)\n\n/* *INDENT-ON* */\n\n/**@}*/\n\n/** \\defgroup crypto_types Key and algorithm types\n * @{\n */\n\n/* Note that key type values, including ECC family and DH group values, are\n * embedded in the persistent key store, as part of key metadata. As a\n * consequence, they must not be changed (unless the storage format version\n * changes).\n */\n\n/** An invalid key type value.\n *\n * Zero is not the encoding of any key type.\n */\n#define PSA_KEY_TYPE_NONE                           ((psa_key_type_t) 0x0000)\n\n/** Vendor-defined key type flag.\n *\n * Key types defined by this standard will never have the\n * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types\n * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should\n * respect the bitwise structure used by standard encodings whenever practical.\n */\n#define PSA_KEY_TYPE_VENDOR_FLAG                    ((psa_key_type_t) 0x8000)\n\n#define PSA_KEY_TYPE_CATEGORY_MASK                  ((psa_key_type_t) 0x7000)\n#define PSA_KEY_TYPE_CATEGORY_RAW                   ((psa_key_type_t) 0x1000)\n#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC             ((psa_key_type_t) 0x2000)\n#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY            ((psa_key_type_t) 0x4000)\n#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR              ((psa_key_type_t) 0x7000)\n\n#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR             ((psa_key_type_t) 0x3000)\n\n/** Whether a key type is vendor-defined.\n *\n * See also #PSA_KEY_TYPE_VENDOR_FLAG.\n */\n#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \\\n    (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0)\n\n/** Whether a key type is an unstructured array of bytes.\n *\n * This encompasses both symmetric keys and non-key data.\n */\n#define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \\\n    (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_RAW || \\\n     ((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC)\n\n/** Whether a key type is asymmetric: either a key pair or a public key. */\n#define PSA_KEY_TYPE_IS_ASYMMETRIC(type)                                \\\n    (((type) & PSA_KEY_TYPE_CATEGORY_MASK                               \\\n      & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) ==                            \\\n     PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY)\n/** Whether a key type is the public part of a key pair. */\n#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type)                                \\\n    (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY)\n/** Whether a key type is a key pair containing a private part and a public\n * part. */\n#define PSA_KEY_TYPE_IS_KEY_PAIR(type)                                   \\\n    (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_KEY_PAIR)\n/** The key pair type corresponding to a public key type.\n *\n * You may also pass a key pair type as \\p type, it will be left unchanged.\n *\n * \\param type      A public key type or key pair type.\n *\n * \\return          The corresponding key pair type.\n *                  If \\p type is not a public key or a key pair,\n *                  the return value is undefined.\n */\n#define PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type)        \\\n    ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR)\n/** The public key type corresponding to a key pair type.\n *\n * You may also pass a public key type as \\p type, it will be left unchanged.\n *\n * \\param type      A public key type or key pair type.\n *\n * \\return          The corresponding public key type.\n *                  If \\p type is not a public key or a key pair,\n *                  the return value is undefined.\n */\n#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type)        \\\n    ((type) & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR)\n\n/** Raw data.\n *\n * A \"key\" of this type cannot be used for any cryptographic operation.\n * Applications may use this type to store arbitrary data in the keystore. */\n#define PSA_KEY_TYPE_RAW_DATA                       ((psa_key_type_t) 0x1001)\n\n/** HMAC key.\n *\n * The key policy determines which underlying hash algorithm the key can be\n * used for.\n *\n * HMAC keys should generally have the same size as the underlying hash.\n * This size can be calculated with #PSA_HASH_LENGTH(\\c alg) where\n * \\c alg is the HMAC algorithm or the underlying hash algorithm. */\n#define PSA_KEY_TYPE_HMAC                           ((psa_key_type_t) 0x1100)\n\n/** A secret for key derivation.\n *\n * This key type is for high-entropy secrets only. For low-entropy secrets,\n * #PSA_KEY_TYPE_PASSWORD should be used instead.\n *\n * These keys can be used as the #PSA_KEY_DERIVATION_INPUT_SECRET or\n * #PSA_KEY_DERIVATION_INPUT_PASSWORD input of key derivation algorithms.\n *\n * The key policy determines which key derivation algorithm the key\n * can be used for.\n */\n#define PSA_KEY_TYPE_DERIVE                         ((psa_key_type_t) 0x1200)\n\n/** A low-entropy secret for password hashing or key derivation.\n *\n * This key type is suitable for passwords and passphrases which are typically\n * intended to be memorizable by humans, and have a low entropy relative to\n * their size. It can be used for randomly generated or derived keys with\n * maximum or near-maximum entropy, but #PSA_KEY_TYPE_DERIVE is more suitable\n * for such keys. It is not suitable for passwords with extremely low entropy,\n * such as numerical PINs.\n *\n * These keys can be used as the #PSA_KEY_DERIVATION_INPUT_PASSWORD input of\n * key derivation algorithms. Algorithms that accept such an input were\n * designed to accept low-entropy secret and are known as password hashing or\n * key stretching algorithms.\n *\n * These keys cannot be used as the #PSA_KEY_DERIVATION_INPUT_SECRET input of\n * key derivation algorithms, as the algorithms that take such an input expect\n * it to be high-entropy.\n *\n * The key policy determines which key derivation algorithm the key can be\n * used for, among the permissible subset defined above.\n */\n#define PSA_KEY_TYPE_PASSWORD                       ((psa_key_type_t) 0x1203)\n\n/** A secret value that can be used to verify a password hash.\n *\n * The key policy determines which key derivation algorithm the key\n * can be used for, among the same permissible subset as for\n * #PSA_KEY_TYPE_PASSWORD.\n */\n#define PSA_KEY_TYPE_PASSWORD_HASH                  ((psa_key_type_t) 0x1205)\n\n/** A secret value that can be used in when computing a password hash.\n *\n * The key policy determines which key derivation algorithm the key\n * can be used for, among the subset of algorithms that can use pepper.\n */\n#define PSA_KEY_TYPE_PEPPER                         ((psa_key_type_t) 0x1206)\n\n/** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher.\n *\n * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or\n * 32 bytes (AES-256).\n */\n#define PSA_KEY_TYPE_AES                            ((psa_key_type_t) 0x2400)\n\n/** Key for a cipher, AEAD or MAC algorithm based on the\n * ARIA block cipher. */\n#define PSA_KEY_TYPE_ARIA                           ((psa_key_type_t) 0x2406)\n\n/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES).\n *\n * The size of the key can be 64 bits (single DES), 128 bits (2-key 3DES) or\n * 192 bits (3-key 3DES).\n *\n * Note that single DES and 2-key 3DES are weak and strongly\n * deprecated and should only be used to decrypt legacy data. 3-key 3DES\n * is weak and deprecated and should only be used in legacy protocols.\n */\n#define PSA_KEY_TYPE_DES                            ((psa_key_type_t) 0x2301)\n\n/** Key for a cipher, AEAD or MAC algorithm based on the\n * Camellia block cipher. */\n#define PSA_KEY_TYPE_CAMELLIA                       ((psa_key_type_t) 0x2403)\n\n/** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm.\n *\n * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539.\n *\n * \\note For ChaCha20 and ChaCha20_Poly1305, Mbed TLS only supports\n *       12-byte nonces.\n *\n * \\note For ChaCha20, the initial counter value is 0. To encrypt or decrypt\n *       with the initial counter value 1, you can process and discard a\n *       64-byte block before the real data.\n */\n#define PSA_KEY_TYPE_CHACHA20                       ((psa_key_type_t) 0x2004)\n\n/** RSA public key.\n *\n * The size of an RSA key is the bit size of the modulus.\n */\n#define PSA_KEY_TYPE_RSA_PUBLIC_KEY                 ((psa_key_type_t) 0x4001)\n/** RSA key pair (private and public key).\n *\n * The size of an RSA key is the bit size of the modulus.\n */\n#define PSA_KEY_TYPE_RSA_KEY_PAIR                   ((psa_key_type_t) 0x7001)\n/** Whether a key type is an RSA key (pair or public-only). */\n#define PSA_KEY_TYPE_IS_RSA(type)                                       \\\n    (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY)\n\n#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE            ((psa_key_type_t) 0x4100)\n#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE              ((psa_key_type_t) 0x7100)\n#define PSA_KEY_TYPE_ECC_CURVE_MASK                 ((psa_key_type_t) 0x00ff)\n/** Elliptic curve key pair.\n *\n * The size of an elliptic curve key is the bit size associated with the curve,\n * i.e. the bit size of *q* for a curve over a field *F<sub>q</sub>*.\n * See the documentation of `PSA_ECC_FAMILY_xxx` curve families for details.\n *\n * \\param curve     A value of type ::psa_ecc_family_t that\n *                  identifies the ECC curve to be used.\n */\n#define PSA_KEY_TYPE_ECC_KEY_PAIR(curve)         \\\n    (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve))\n/** Elliptic curve public key.\n *\n * The size of an elliptic curve public key is the same as the corresponding\n * private key (see #PSA_KEY_TYPE_ECC_KEY_PAIR and the documentation of\n * `PSA_ECC_FAMILY_xxx` curve families).\n *\n * \\param curve     A value of type ::psa_ecc_family_t that\n *                  identifies the ECC curve to be used.\n */\n#define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve)              \\\n    (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve))\n\n/** Whether a key type is an elliptic curve key (pair or public-only). */\n#define PSA_KEY_TYPE_IS_ECC(type)                                       \\\n    ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) &                        \\\n      ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE)\n/** Whether a key type is an elliptic curve key pair. */\n#define PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)                               \\\n    (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) ==                         \\\n     PSA_KEY_TYPE_ECC_KEY_PAIR_BASE)\n/** Whether a key type is an elliptic curve public key. */\n#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type)                            \\\n    (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) ==                         \\\n     PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE)\n\n/** Extract the curve from an elliptic curve key type. */\n#define PSA_KEY_TYPE_ECC_GET_FAMILY(type)                        \\\n    ((psa_ecc_family_t) (PSA_KEY_TYPE_IS_ECC(type) ?             \\\n                         ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \\\n                         0))\n\n/** Check if the curve of given family is Weierstrass elliptic curve. */\n#define PSA_ECC_FAMILY_IS_WEIERSTRASS(family) ((family & 0xc0) == 0)\n\n/** SEC Koblitz curves over prime fields.\n *\n * This family comprises the following curves:\n * secp192k1, secp224k1, secp256k1.\n * They are defined in _Standards for Efficient Cryptography_,\n * _SEC 2: Recommended Elliptic Curve Domain Parameters_.\n * https://www.secg.org/sec2-v2.pdf\n *\n * \\note For secp224k1, the bit-size is 225 (size of a private value).\n *\n * \\note Mbed TLS only supports secp192k1 and secp256k1.\n */\n#define PSA_ECC_FAMILY_SECP_K1           ((psa_ecc_family_t) 0x17)\n\n/** SEC random curves over prime fields.\n *\n * This family comprises the following curves:\n * secp192r1, secp224r1, secp256r1, secp384r1, secp521r1.\n * They are defined in _Standards for Efficient Cryptography_,\n * _SEC 2: Recommended Elliptic Curve Domain Parameters_.\n * https://www.secg.org/sec2-v2.pdf\n */\n#define PSA_ECC_FAMILY_SECP_R1           ((psa_ecc_family_t) 0x12)\n/* SECP160R2 (SEC2 v1, obsolete, not supported in Mbed TLS) */\n#define PSA_ECC_FAMILY_SECP_R2           ((psa_ecc_family_t) 0x1b)\n\n/** SEC Koblitz curves over binary fields.\n *\n * This family comprises the following curves:\n * sect163k1, sect233k1, sect239k1, sect283k1, sect409k1, sect571k1.\n * They are defined in _Standards for Efficient Cryptography_,\n * _SEC 2: Recommended Elliptic Curve Domain Parameters_.\n * https://www.secg.org/sec2-v2.pdf\n *\n * \\note Mbed TLS does not support any curve in this family.\n */\n#define PSA_ECC_FAMILY_SECT_K1           ((psa_ecc_family_t) 0x27)\n\n/** SEC random curves over binary fields.\n *\n * This family comprises the following curves:\n * sect163r1, sect233r1, sect283r1, sect409r1, sect571r1.\n * They are defined in _Standards for Efficient Cryptography_,\n * _SEC 2: Recommended Elliptic Curve Domain Parameters_.\n * https://www.secg.org/sec2-v2.pdf\n *\n * \\note Mbed TLS does not support any curve in this family.\n */\n#define PSA_ECC_FAMILY_SECT_R1           ((psa_ecc_family_t) 0x22)\n\n/** SEC additional random curves over binary fields.\n *\n * This family comprises the following curve:\n * sect163r2.\n * It is defined in _Standards for Efficient Cryptography_,\n * _SEC 2: Recommended Elliptic Curve Domain Parameters_.\n * https://www.secg.org/sec2-v2.pdf\n *\n * \\note Mbed TLS does not support any curve in this family.\n */\n#define PSA_ECC_FAMILY_SECT_R2           ((psa_ecc_family_t) 0x2b)\n\n/** Brainpool P random curves.\n *\n * This family comprises the following curves:\n * brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1,\n * brainpoolP320r1, brainpoolP384r1, brainpoolP512r1.\n * It is defined in RFC 5639.\n *\n * \\note Mbed TLS only supports the 256-bit, 384-bit and 512-bit curves\n *       in this family.\n */\n#define PSA_ECC_FAMILY_BRAINPOOL_P_R1    ((psa_ecc_family_t) 0x30)\n\n/** Curve25519 and Curve448.\n *\n * This family comprises the following Montgomery curves:\n * - 255-bit: Bernstein et al.,\n *   _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006.\n *   The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve.\n * - 448-bit: Hamburg,\n *   _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015.\n *   The algorithm #PSA_ALG_ECDH performs X448 when used with this curve.\n */\n#define PSA_ECC_FAMILY_MONTGOMERY        ((psa_ecc_family_t) 0x41)\n\n/** The twisted Edwards curves Ed25519 and Ed448.\n *\n * These curves are suitable for EdDSA (#PSA_ALG_PURE_EDDSA for both curves,\n * #PSA_ALG_ED25519PH for the 255-bit curve,\n * #PSA_ALG_ED448PH for the 448-bit curve).\n *\n * This family comprises the following twisted Edwards curves:\n * - 255-bit: Edwards25519, the twisted Edwards curve birationally equivalent\n *   to Curve25519.\n *   Bernstein et al., _Twisted Edwards curves_, Africacrypt 2008.\n * - 448-bit: Edwards448, the twisted Edwards curve birationally equivalent\n *   to Curve448.\n *   Hamburg, _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015.\n *\n * \\note Mbed TLS does not support Edwards curves yet.\n */\n#define PSA_ECC_FAMILY_TWISTED_EDWARDS   ((psa_ecc_family_t) 0x42)\n\n#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE             ((psa_key_type_t) 0x4200)\n#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE               ((psa_key_type_t) 0x7200)\n#define PSA_KEY_TYPE_DH_GROUP_MASK                  ((psa_key_type_t) 0x00ff)\n/** Diffie-Hellman key pair.\n *\n * \\param group     A value of type ::psa_dh_family_t that identifies the\n *                  Diffie-Hellman group to be used.\n */\n#define PSA_KEY_TYPE_DH_KEY_PAIR(group)          \\\n    (PSA_KEY_TYPE_DH_KEY_PAIR_BASE | (group))\n/** Diffie-Hellman public key.\n *\n * \\param group     A value of type ::psa_dh_family_t that identifies the\n *                  Diffie-Hellman group to be used.\n */\n#define PSA_KEY_TYPE_DH_PUBLIC_KEY(group)               \\\n    (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group))\n\n/** Whether a key type is a Diffie-Hellman key (pair or public-only). */\n#define PSA_KEY_TYPE_IS_DH(type)                                        \\\n    ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) &                        \\\n      ~PSA_KEY_TYPE_DH_GROUP_MASK) == PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE)\n/** Whether a key type is a Diffie-Hellman key pair. */\n#define PSA_KEY_TYPE_IS_DH_KEY_PAIR(type)                               \\\n    (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) ==                         \\\n     PSA_KEY_TYPE_DH_KEY_PAIR_BASE)\n/** Whether a key type is a Diffie-Hellman public key. */\n#define PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type)                            \\\n    (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) ==                         \\\n     PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE)\n\n/** Extract the group from a Diffie-Hellman key type. */\n#define PSA_KEY_TYPE_DH_GET_FAMILY(type)                        \\\n    ((psa_dh_family_t) (PSA_KEY_TYPE_IS_DH(type) ?              \\\n                        ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) :  \\\n                        0))\n\n/** Diffie-Hellman groups defined in RFC 7919 Appendix A.\n *\n * This family includes groups with the following key sizes (in bits):\n * 2048, 3072, 4096, 6144, 8192. A given implementation may support\n * all of these sizes or only a subset.\n */\n#define PSA_DH_FAMILY_RFC7919            ((psa_dh_family_t) 0x03)\n\n#define PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type)      \\\n    (((type) >> 8) & 7)\n/** The block size of a block cipher.\n *\n * \\param type  A cipher key type (value of type #psa_key_type_t).\n *\n * \\return      The block size for a block cipher, or 1 for a stream cipher.\n *              The return value is undefined if \\p type is not a supported\n *              cipher key type.\n *\n * \\note It is possible to build stream cipher algorithms on top of a block\n *       cipher, for example CTR mode (#PSA_ALG_CTR).\n *       This macro only takes the key type into account, so it cannot be\n *       used to determine the size of the data that #psa_cipher_update()\n *       might buffer for future processing in general.\n *\n * \\note This macro returns a compile-time constant if its argument is one.\n *\n * \\warning This macro may evaluate its argument multiple times.\n */\n#define PSA_BLOCK_CIPHER_BLOCK_LENGTH(type)                                     \\\n    (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \\\n     1u << PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) :                         \\\n        0u)\n\n/* Note that algorithm values are embedded in the persistent key store,\n * as part of key metadata. As a consequence, they must not be changed\n * (unless the storage format version changes).\n */\n\n/** Vendor-defined algorithm flag.\n *\n * Algorithms defined by this standard will never have the #PSA_ALG_VENDOR_FLAG\n * bit set. Vendors who define additional algorithms must use an encoding with\n * the #PSA_ALG_VENDOR_FLAG bit set and should respect the bitwise structure\n * used by standard encodings whenever practical.\n */\n#define PSA_ALG_VENDOR_FLAG                     ((psa_algorithm_t) 0x80000000)\n\n#define PSA_ALG_CATEGORY_MASK                   ((psa_algorithm_t) 0x7f000000)\n#define PSA_ALG_CATEGORY_HASH                   ((psa_algorithm_t) 0x02000000)\n#define PSA_ALG_CATEGORY_MAC                    ((psa_algorithm_t) 0x03000000)\n#define PSA_ALG_CATEGORY_CIPHER                 ((psa_algorithm_t) 0x04000000)\n#define PSA_ALG_CATEGORY_AEAD                   ((psa_algorithm_t) 0x05000000)\n#define PSA_ALG_CATEGORY_SIGN                   ((psa_algorithm_t) 0x06000000)\n#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION  ((psa_algorithm_t) 0x07000000)\n#define PSA_ALG_CATEGORY_KEY_DERIVATION         ((psa_algorithm_t) 0x08000000)\n#define PSA_ALG_CATEGORY_KEY_AGREEMENT          ((psa_algorithm_t) 0x09000000)\n\n/** Whether an algorithm is vendor-defined.\n *\n * See also #PSA_ALG_VENDOR_FLAG.\n */\n#define PSA_ALG_IS_VENDOR_DEFINED(alg)                                  \\\n    (((alg) & PSA_ALG_VENDOR_FLAG) != 0)\n\n/** Whether the specified algorithm is a hash algorithm.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is a hash algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\p alg is not a supported\n *         algorithm identifier.\n */\n#define PSA_ALG_IS_HASH(alg)                                            \\\n    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH)\n\n/** Whether the specified algorithm is a MAC algorithm.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is a MAC algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\p alg is not a supported\n *         algorithm identifier.\n */\n#define PSA_ALG_IS_MAC(alg)                                             \\\n    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC)\n\n/** Whether the specified algorithm is a symmetric cipher algorithm.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is a symmetric cipher algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\p alg is not a supported\n *         algorithm identifier.\n */\n#define PSA_ALG_IS_CIPHER(alg)                                          \\\n    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER)\n\n/** Whether the specified algorithm is an authenticated encryption\n * with associated data (AEAD) algorithm.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is an AEAD algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\p alg is not a supported\n *         algorithm identifier.\n */\n#define PSA_ALG_IS_AEAD(alg)                                            \\\n    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD)\n\n/** Whether the specified algorithm is an asymmetric signature algorithm,\n * also known as public-key signature algorithm.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is an asymmetric signature algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\p alg is not a supported\n *         algorithm identifier.\n */\n#define PSA_ALG_IS_SIGN(alg)                                            \\\n    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN)\n\n/** Whether the specified algorithm is an asymmetric encryption algorithm,\n * also known as public-key encryption algorithm.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is an asymmetric encryption algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\p alg is not a supported\n *         algorithm identifier.\n */\n#define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg)                           \\\n    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION)\n\n/** Whether the specified algorithm is a key agreement algorithm.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is a key agreement algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\p alg is not a supported\n *         algorithm identifier.\n */\n#define PSA_ALG_IS_KEY_AGREEMENT(alg)                                   \\\n    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT)\n\n/** Whether the specified algorithm is a key derivation algorithm.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is a key derivation algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\p alg is not a supported\n *         algorithm identifier.\n */\n#define PSA_ALG_IS_KEY_DERIVATION(alg)                                  \\\n    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION)\n\n/** Whether the specified algorithm is a key stretching / password hashing\n * algorithm.\n *\n * A key stretching / password hashing algorithm is a key derivation algorithm\n * that is suitable for use with a low-entropy secret such as a password.\n * Equivalently, it's a key derivation algorithm that uses a\n * #PSA_KEY_DERIVATION_INPUT_PASSWORD input step.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is a key stretching / password hashing algorithm, 0\n *         otherwise. This macro may return either 0 or 1 if \\p alg is not a\n *         supported algorithm identifier.\n */\n#define PSA_ALG_IS_KEY_DERIVATION_STRETCHING(alg)                                  \\\n    (PSA_ALG_IS_KEY_DERIVATION(alg) &&              \\\n     (alg) & PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG)\n\n/** An invalid algorithm identifier value. */\n/* *INDENT-OFF* (https://github.com/ARM-software/psa-arch-tests/issues/337) */\n#define PSA_ALG_NONE                            ((psa_algorithm_t)0)\n/* *INDENT-ON* */\n\n#define PSA_ALG_HASH_MASK                       ((psa_algorithm_t) 0x000000ff)\n/** MD5 */\n#define PSA_ALG_MD5                             ((psa_algorithm_t) 0x02000003)\n/** PSA_ALG_RIPEMD160 */\n#define PSA_ALG_RIPEMD160                       ((psa_algorithm_t) 0x02000004)\n/** SHA1 */\n#define PSA_ALG_SHA_1                           ((psa_algorithm_t) 0x02000005)\n/** SHA2-224 */\n#define PSA_ALG_SHA_224                         ((psa_algorithm_t) 0x02000008)\n/** SHA2-256 */\n#define PSA_ALG_SHA_256                         ((psa_algorithm_t) 0x02000009)\n/** SHA2-384 */\n#define PSA_ALG_SHA_384                         ((psa_algorithm_t) 0x0200000a)\n/** SHA2-512 */\n#define PSA_ALG_SHA_512                         ((psa_algorithm_t) 0x0200000b)\n/** SHA2-512/224 */\n#define PSA_ALG_SHA_512_224                     ((psa_algorithm_t) 0x0200000c)\n/** SHA2-512/256 */\n#define PSA_ALG_SHA_512_256                     ((psa_algorithm_t) 0x0200000d)\n/** SHA3-224 */\n#define PSA_ALG_SHA3_224                        ((psa_algorithm_t) 0x02000010)\n/** SHA3-256 */\n#define PSA_ALG_SHA3_256                        ((psa_algorithm_t) 0x02000011)\n/** SHA3-384 */\n#define PSA_ALG_SHA3_384                        ((psa_algorithm_t) 0x02000012)\n/** SHA3-512 */\n#define PSA_ALG_SHA3_512                        ((psa_algorithm_t) 0x02000013)\n/** The first 512 bits (64 bytes) of the SHAKE256 output.\n *\n * This is the prehashing for Ed448ph (see #PSA_ALG_ED448PH). For other\n * scenarios where a hash function based on SHA3/SHAKE is desired, SHA3-512\n * has the same output size and a (theoretically) higher security strength.\n */\n#define PSA_ALG_SHAKE256_512                    ((psa_algorithm_t) 0x02000015)\n\n/** In a hash-and-sign algorithm policy, allow any hash algorithm.\n *\n * This value may be used to form the algorithm usage field of a policy\n * for a signature algorithm that is parametrized by a hash. The key\n * may then be used to perform operations using the same signature\n * algorithm parametrized with any supported hash.\n *\n * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros:\n * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, #PSA_ALG_RSA_PSS_ANY_SALT,\n * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA.\n * Then you may create and use a key as follows:\n * - Set the key usage field using #PSA_ALG_ANY_HASH, for example:\n *   ```\n *   psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); // or VERIFY\n *   psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH));\n *   ```\n * - Import or generate key material.\n * - Call psa_sign_hash() or psa_verify_hash(), passing\n *   an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each\n *   call to sign or verify a message may use a different hash.\n *   ```\n *   psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...);\n *   psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...);\n *   psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...);\n *   ```\n *\n * This value may not be used to build other algorithms that are\n * parametrized over a hash. For any valid use of this macro to build\n * an algorithm \\c alg, #PSA_ALG_IS_HASH_AND_SIGN(\\c alg) is true.\n *\n * This value may not be used to build an algorithm specification to\n * perform an operation. It is only valid to build policies.\n */\n#define PSA_ALG_ANY_HASH                        ((psa_algorithm_t) 0x020000ff)\n\n#define PSA_ALG_MAC_SUBCATEGORY_MASK            ((psa_algorithm_t) 0x00c00000)\n#define PSA_ALG_HMAC_BASE                       ((psa_algorithm_t) 0x03800000)\n/** Macro to build an HMAC algorithm.\n *\n * For example, #PSA_ALG_HMAC(#PSA_ALG_SHA_256) is HMAC-SHA-256.\n *\n * \\param hash_alg      A hash algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_HASH(\\p hash_alg) is true).\n *\n * \\return              The corresponding HMAC algorithm.\n * \\return              Unspecified if \\p hash_alg is not a supported\n *                      hash algorithm.\n */\n#define PSA_ALG_HMAC(hash_alg)                                  \\\n    (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))\n\n#define PSA_ALG_HMAC_GET_HASH(hmac_alg)                             \\\n    (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK))\n\n/** Whether the specified algorithm is an HMAC algorithm.\n *\n * HMAC is a family of MAC algorithms that are based on a hash function.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is an HMAC algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\p alg is not a supported\n *         algorithm identifier.\n */\n#define PSA_ALG_IS_HMAC(alg)                                            \\\n    (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \\\n     PSA_ALG_HMAC_BASE)\n\n/* In the encoding of a MAC algorithm, the bits corresponding to\n * PSA_ALG_MAC_TRUNCATION_MASK encode the length to which the MAC is\n * truncated. As an exception, the value 0 means the untruncated algorithm,\n * whatever its length is. The length is encoded in 6 bits, so it can\n * reach up to 63; the largest MAC is 64 bytes so its trivial truncation\n * to full length is correctly encoded as 0 and any non-trivial truncation\n * is correctly encoded as a value between 1 and 63. */\n#define PSA_ALG_MAC_TRUNCATION_MASK             ((psa_algorithm_t) 0x003f0000)\n#define PSA_MAC_TRUNCATION_OFFSET 16\n\n/* In the encoding of a MAC algorithm, the bit corresponding to\n * #PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG encodes the fact that the algorithm\n * is a wildcard algorithm. A key with such wildcard algorithm as permitted\n * algorithm policy can be used with any algorithm corresponding to the\n * same base class and having a (potentially truncated) MAC length greater or\n * equal than the one encoded in #PSA_ALG_MAC_TRUNCATION_MASK. */\n#define PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG   ((psa_algorithm_t) 0x00008000)\n\n/** Macro to build a truncated MAC algorithm.\n *\n * A truncated MAC algorithm is identical to the corresponding MAC\n * algorithm except that the MAC value for the truncated algorithm\n * consists of only the first \\p mac_length bytes of the MAC value\n * for the untruncated algorithm.\n *\n * \\note    This macro may allow constructing algorithm identifiers that\n *          are not valid, either because the specified length is larger\n *          than the untruncated MAC or because the specified length is\n *          smaller than permitted by the implementation.\n *\n * \\note    It is implementation-defined whether a truncated MAC that\n *          is truncated to the same length as the MAC of the untruncated\n *          algorithm is considered identical to the untruncated algorithm\n *          for policy comparison purposes.\n *\n * \\param mac_alg       A MAC algorithm identifier (value of type\n *                      #psa_algorithm_t such that #PSA_ALG_IS_MAC(\\p mac_alg)\n *                      is true). This may be a truncated or untruncated\n *                      MAC algorithm.\n * \\param mac_length    Desired length of the truncated MAC in bytes.\n *                      This must be at most the full length of the MAC\n *                      and must be at least an implementation-specified\n *                      minimum. The implementation-specified minimum\n *                      shall not be zero.\n *\n * \\return              The corresponding MAC algorithm with the specified\n *                      length.\n * \\return              Unspecified if \\p mac_alg is not a supported\n *                      MAC algorithm or if \\p mac_length is too small or\n *                      too large for the specified MAC algorithm.\n */\n#define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length)              \\\n    (((mac_alg) & ~(PSA_ALG_MAC_TRUNCATION_MASK |               \\\n                    PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG)) |   \\\n     ((mac_length) << PSA_MAC_TRUNCATION_OFFSET & PSA_ALG_MAC_TRUNCATION_MASK))\n\n/** Macro to build the base MAC algorithm corresponding to a truncated\n * MAC algorithm.\n *\n * \\param mac_alg       A MAC algorithm identifier (value of type\n *                      #psa_algorithm_t such that #PSA_ALG_IS_MAC(\\p mac_alg)\n *                      is true). This may be a truncated or untruncated\n *                      MAC algorithm.\n *\n * \\return              The corresponding base MAC algorithm.\n * \\return              Unspecified if \\p mac_alg is not a supported\n *                      MAC algorithm.\n */\n#define PSA_ALG_FULL_LENGTH_MAC(mac_alg)                        \\\n    ((mac_alg) & ~(PSA_ALG_MAC_TRUNCATION_MASK |                \\\n                   PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG))\n\n/** Length to which a MAC algorithm is truncated.\n *\n * \\param mac_alg       A MAC algorithm identifier (value of type\n *                      #psa_algorithm_t such that #PSA_ALG_IS_MAC(\\p mac_alg)\n *                      is true).\n *\n * \\return              Length of the truncated MAC in bytes.\n * \\return              0 if \\p mac_alg is a non-truncated MAC algorithm.\n * \\return              Unspecified if \\p mac_alg is not a supported\n *                      MAC algorithm.\n */\n#define PSA_MAC_TRUNCATED_LENGTH(mac_alg)                               \\\n    (((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET)\n\n/** Macro to build a MAC minimum-MAC-length wildcard algorithm.\n *\n * A minimum-MAC-length MAC wildcard algorithm permits all MAC algorithms\n * sharing the same base algorithm, and where the (potentially truncated) MAC\n * length of the specific algorithm is equal to or larger then the wildcard\n * algorithm's minimum MAC length.\n *\n * \\note    When setting the minimum required MAC length to less than the\n *          smallest MAC length allowed by the base algorithm, this effectively\n *          becomes an 'any-MAC-length-allowed' policy for that base algorithm.\n *\n * \\param mac_alg         A MAC algorithm identifier (value of type\n *                        #psa_algorithm_t such that #PSA_ALG_IS_MAC(\\p mac_alg)\n *                        is true).\n * \\param min_mac_length  Desired minimum length of the message authentication\n *                        code in bytes. This must be at most the untruncated\n *                        length of the MAC and must be at least 1.\n *\n * \\return                The corresponding MAC wildcard algorithm with the\n *                        specified minimum length.\n * \\return                Unspecified if \\p mac_alg is not a supported MAC\n *                        algorithm or if \\p min_mac_length is less than 1 or\n *                        too large for the specified MAC algorithm.\n */\n#define PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(mac_alg, min_mac_length)   \\\n    (PSA_ALG_TRUNCATED_MAC(mac_alg, min_mac_length) |              \\\n     PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG)\n\n#define PSA_ALG_CIPHER_MAC_BASE                 ((psa_algorithm_t) 0x03c00000)\n/** The CBC-MAC construction over a block cipher\n *\n * \\warning CBC-MAC is insecure in many cases.\n * A more secure mode, such as #PSA_ALG_CMAC, is recommended.\n */\n#define PSA_ALG_CBC_MAC                         ((psa_algorithm_t) 0x03c00100)\n/** The CMAC construction over a block cipher */\n#define PSA_ALG_CMAC                            ((psa_algorithm_t) 0x03c00200)\n\n/** Whether the specified algorithm is a MAC algorithm based on a block cipher.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is a MAC algorithm based on a block cipher, 0 otherwise.\n *         This macro may return either 0 or 1 if \\p alg is not a supported\n *         algorithm identifier.\n */\n#define PSA_ALG_IS_BLOCK_CIPHER_MAC(alg)                                \\\n    (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \\\n     PSA_ALG_CIPHER_MAC_BASE)\n\n#define PSA_ALG_CIPHER_STREAM_FLAG              ((psa_algorithm_t) 0x00800000)\n#define PSA_ALG_CIPHER_FROM_BLOCK_FLAG          ((psa_algorithm_t) 0x00400000)\n\n/** Whether the specified algorithm is a stream cipher.\n *\n * A stream cipher is a symmetric cipher that encrypts or decrypts messages\n * by applying a bitwise-xor with a stream of bytes that is generated\n * from a key.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is a stream cipher algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\p alg is not a supported\n *         algorithm identifier or if it is not a symmetric cipher algorithm.\n */\n#define PSA_ALG_IS_STREAM_CIPHER(alg)            \\\n    (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_STREAM_FLAG)) == \\\n     (PSA_ALG_CATEGORY_CIPHER | PSA_ALG_CIPHER_STREAM_FLAG))\n\n/** The stream cipher mode of a stream cipher algorithm.\n *\n * The underlying stream cipher is determined by the key type.\n * - To use ChaCha20, use a key type of #PSA_KEY_TYPE_CHACHA20.\n */\n#define PSA_ALG_STREAM_CIPHER                   ((psa_algorithm_t) 0x04800100)\n\n/** The CTR stream cipher mode.\n *\n * CTR is a stream cipher which is built from a block cipher.\n * The underlying block cipher is determined by the key type.\n * For example, to use AES-128-CTR, use this algorithm with\n * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes).\n */\n#define PSA_ALG_CTR                             ((psa_algorithm_t) 0x04c01000)\n\n/** The CFB stream cipher mode.\n *\n * The underlying block cipher is determined by the key type.\n */\n#define PSA_ALG_CFB                             ((psa_algorithm_t) 0x04c01100)\n\n/** The OFB stream cipher mode.\n *\n * The underlying block cipher is determined by the key type.\n */\n#define PSA_ALG_OFB                             ((psa_algorithm_t) 0x04c01200)\n\n/** The XTS cipher mode.\n *\n * XTS is a cipher mode which is built from a block cipher. It requires at\n * least one full block of input, but beyond this minimum the input\n * does not need to be a whole number of blocks.\n */\n#define PSA_ALG_XTS                             ((psa_algorithm_t) 0x0440ff00)\n\n/** The Electronic Code Book (ECB) mode of a block cipher, with no padding.\n *\n * \\warning ECB mode does not protect the confidentiality of the encrypted data\n * except in extremely narrow circumstances. It is recommended that applications\n * only use ECB if they need to construct an operating mode that the\n * implementation does not provide. Implementations are encouraged to provide\n * the modes that applications need in preference to supporting direct access\n * to ECB.\n *\n * The underlying block cipher is determined by the key type.\n *\n * This symmetric cipher mode can only be used with messages whose lengths are a\n * multiple of the block size of the chosen block cipher.\n *\n * ECB mode does not accept an initialization vector (IV). When using a\n * multi-part cipher operation with this algorithm, psa_cipher_generate_iv()\n * and psa_cipher_set_iv() must not be called.\n */\n#define PSA_ALG_ECB_NO_PADDING                  ((psa_algorithm_t) 0x04404400)\n\n/** The CBC block cipher chaining mode, with no padding.\n *\n * The underlying block cipher is determined by the key type.\n *\n * This symmetric cipher mode can only be used with messages whose lengths\n * are whole number of blocks for the chosen block cipher.\n */\n#define PSA_ALG_CBC_NO_PADDING                  ((psa_algorithm_t) 0x04404000)\n\n/** The CBC block cipher chaining mode with PKCS#7 padding.\n *\n * The underlying block cipher is determined by the key type.\n *\n * This is the padding method defined by PKCS#7 (RFC 2315) &sect;10.3.\n */\n#define PSA_ALG_CBC_PKCS7                       ((psa_algorithm_t) 0x04404100)\n\n#define PSA_ALG_AEAD_FROM_BLOCK_FLAG            ((psa_algorithm_t) 0x00400000)\n\n/** Whether the specified algorithm is an AEAD mode on a block cipher.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is an AEAD algorithm which is an AEAD mode based on\n *         a block cipher, 0 otherwise.\n *         This macro may return either 0 or 1 if \\p alg is not a supported\n *         algorithm identifier.\n */\n#define PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg)    \\\n    (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) == \\\n     (PSA_ALG_CATEGORY_AEAD | PSA_ALG_AEAD_FROM_BLOCK_FLAG))\n\n/** The CCM authenticated encryption algorithm.\n *\n * The underlying block cipher is determined by the key type.\n */\n#define PSA_ALG_CCM                             ((psa_algorithm_t) 0x05500100)\n\n/** The CCM* cipher mode without authentication.\n *\n * This is CCM* as specified in IEEE 802.15.4 §7, with a tag length of 0.\n * For CCM* with a nonzero tag length, use the AEAD algorithm #PSA_ALG_CCM.\n *\n * The underlying block cipher is determined by the key type.\n *\n * Currently only 13-byte long IV's are supported.\n */\n#define PSA_ALG_CCM_STAR_NO_TAG                 ((psa_algorithm_t) 0x04c01300)\n\n/** The GCM authenticated encryption algorithm.\n *\n * The underlying block cipher is determined by the key type.\n */\n#define PSA_ALG_GCM                             ((psa_algorithm_t) 0x05500200)\n\n/** The Chacha20-Poly1305 AEAD algorithm.\n *\n * The ChaCha20_Poly1305 construction is defined in RFC 7539.\n *\n * Implementations must support 12-byte nonces, may support 8-byte nonces,\n * and should reject other sizes.\n *\n * Implementations must support 16-byte tags and should reject other sizes.\n */\n#define PSA_ALG_CHACHA20_POLY1305               ((psa_algorithm_t) 0x05100500)\n\n/* In the encoding of an AEAD algorithm, the bits corresponding to\n * PSA_ALG_AEAD_TAG_LENGTH_MASK encode the length of the AEAD tag.\n * The constants for default lengths follow this encoding.\n */\n#define PSA_ALG_AEAD_TAG_LENGTH_MASK            ((psa_algorithm_t) 0x003f0000)\n#define PSA_AEAD_TAG_LENGTH_OFFSET 16\n\n/* In the encoding of an AEAD algorithm, the bit corresponding to\n * #PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG encodes the fact that the algorithm\n * is a wildcard algorithm. A key with such wildcard algorithm as permitted\n * algorithm policy can be used with any algorithm corresponding to the\n * same base class and having a tag length greater than or equal to the one\n * encoded in #PSA_ALG_AEAD_TAG_LENGTH_MASK. */\n#define PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG  ((psa_algorithm_t) 0x00008000)\n\n/** Macro to build a shortened AEAD algorithm.\n *\n * A shortened AEAD algorithm is similar to the corresponding AEAD\n * algorithm, but has an authentication tag that consists of fewer bytes.\n * Depending on the algorithm, the tag length may affect the calculation\n * of the ciphertext.\n *\n * \\param aead_alg      An AEAD algorithm identifier (value of type\n *                      #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\\p aead_alg)\n *                      is true).\n * \\param tag_length    Desired length of the authentication tag in bytes.\n *\n * \\return              The corresponding AEAD algorithm with the specified\n *                      length.\n * \\return              Unspecified if \\p aead_alg is not a supported\n *                      AEAD algorithm or if \\p tag_length is not valid\n *                      for the specified AEAD algorithm.\n */\n#define PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, tag_length)           \\\n    (((aead_alg) & ~(PSA_ALG_AEAD_TAG_LENGTH_MASK |                     \\\n                     PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG)) |         \\\n     ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET &                      \\\n        PSA_ALG_AEAD_TAG_LENGTH_MASK))\n\n/** Retrieve the tag length of a specified AEAD algorithm\n *\n * \\param aead_alg      An AEAD algorithm identifier (value of type\n *                      #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\\p aead_alg)\n *                      is true).\n *\n * \\return              The tag length specified by the input algorithm.\n * \\return              Unspecified if \\p aead_alg is not a supported\n *                      AEAD algorithm.\n */\n#define PSA_ALG_AEAD_GET_TAG_LENGTH(aead_alg)                           \\\n    (((aead_alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >>                     \\\n     PSA_AEAD_TAG_LENGTH_OFFSET)\n\n/** Calculate the corresponding AEAD algorithm with the default tag length.\n *\n * \\param aead_alg      An AEAD algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_AEAD(\\p aead_alg) is true).\n *\n * \\return              The corresponding AEAD algorithm with the default\n *                      tag length for that algorithm.\n */\n#define PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(aead_alg)                   \\\n    (                                                                    \\\n        PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_CCM) \\\n        PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_GCM) \\\n        PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \\\n        0)\n#define PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, ref)         \\\n    PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, 0) ==                      \\\n    PSA_ALG_AEAD_WITH_SHORTENED_TAG(ref, 0) ?                            \\\n    ref :\n\n/** Macro to build an AEAD minimum-tag-length wildcard algorithm.\n *\n * A minimum-tag-length AEAD wildcard algorithm permits all AEAD algorithms\n * sharing the same base algorithm, and where the tag length of the specific\n * algorithm is equal to or larger then the minimum tag length specified by the\n * wildcard algorithm.\n *\n * \\note    When setting the minimum required tag length to less than the\n *          smallest tag length allowed by the base algorithm, this effectively\n *          becomes an 'any-tag-length-allowed' policy for that base algorithm.\n *\n * \\param aead_alg        An AEAD algorithm identifier (value of type\n *                        #psa_algorithm_t such that\n *                        #PSA_ALG_IS_AEAD(\\p aead_alg) is true).\n * \\param min_tag_length  Desired minimum length of the authentication tag in\n *                        bytes. This must be at least 1 and at most the largest\n *                        allowed tag length of the algorithm.\n *\n * \\return                The corresponding AEAD wildcard algorithm with the\n *                        specified minimum length.\n * \\return                Unspecified if \\p aead_alg is not a supported\n *                        AEAD algorithm or if \\p min_tag_length is less than 1\n *                        or too large for the specified AEAD algorithm.\n */\n#define PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(aead_alg, min_tag_length) \\\n    (PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, min_tag_length) |            \\\n     PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG)\n\n#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE          ((psa_algorithm_t) 0x06000200)\n/** RSA PKCS#1 v1.5 signature with hashing.\n *\n * This is the signature scheme defined by RFC 8017\n * (PKCS#1: RSA Cryptography Specifications) under the name\n * RSASSA-PKCS1-v1_5.\n *\n * \\param hash_alg      A hash algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_HASH(\\p hash_alg) is true).\n *                      This includes #PSA_ALG_ANY_HASH\n *                      when specifying the algorithm in a usage policy.\n *\n * \\return              The corresponding RSA PKCS#1 v1.5 signature algorithm.\n * \\return              Unspecified if \\p hash_alg is not a supported\n *                      hash algorithm.\n */\n#define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg)                             \\\n    (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))\n/** Raw PKCS#1 v1.5 signature.\n *\n * The input to this algorithm is the DigestInfo structure used by\n * RFC 8017 (PKCS#1: RSA Cryptography Specifications), &sect;9.2\n * steps 3&ndash;6.\n */\n#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE\n#define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)                               \\\n    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE)\n\n#define PSA_ALG_RSA_PSS_BASE               ((psa_algorithm_t) 0x06000300)\n#define PSA_ALG_RSA_PSS_ANY_SALT_BASE      ((psa_algorithm_t) 0x06001300)\n/** RSA PSS signature with hashing.\n *\n * This is the signature scheme defined by RFC 8017\n * (PKCS#1: RSA Cryptography Specifications) under the name\n * RSASSA-PSS, with the message generation function MGF1, and with\n * a salt length equal to the length of the hash, or the largest\n * possible salt length for the algorithm and key size if that is\n * smaller than the hash length. The specified hash algorithm is\n * used to hash the input message, to create the salted hash, and\n * for the mask generation.\n *\n * \\param hash_alg      A hash algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_HASH(\\p hash_alg) is true).\n *                      This includes #PSA_ALG_ANY_HASH\n *                      when specifying the algorithm in a usage policy.\n *\n * \\return              The corresponding RSA PSS signature algorithm.\n * \\return              Unspecified if \\p hash_alg is not a supported\n *                      hash algorithm.\n */\n#define PSA_ALG_RSA_PSS(hash_alg)                               \\\n    (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))\n\n/** RSA PSS signature with hashing with relaxed verification.\n *\n * This algorithm has the same behavior as #PSA_ALG_RSA_PSS when signing,\n * but allows an arbitrary salt length (including \\c 0) when verifying a\n * signature.\n *\n * \\param hash_alg      A hash algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_HASH(\\p hash_alg) is true).\n *                      This includes #PSA_ALG_ANY_HASH\n *                      when specifying the algorithm in a usage policy.\n *\n * \\return              The corresponding RSA PSS signature algorithm.\n * \\return              Unspecified if \\p hash_alg is not a supported\n *                      hash algorithm.\n */\n#define PSA_ALG_RSA_PSS_ANY_SALT(hash_alg)                      \\\n    (PSA_ALG_RSA_PSS_ANY_SALT_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))\n\n/** Whether the specified algorithm is RSA PSS with standard salt.\n *\n * \\param alg           An algorithm value or an algorithm policy wildcard.\n *\n * \\return              1 if \\p alg is of the form\n *                      #PSA_ALG_RSA_PSS(\\c hash_alg),\n *                      where \\c hash_alg is a hash algorithm or\n *                      #PSA_ALG_ANY_HASH. 0 otherwise.\n *                      This macro may return either 0 or 1 if \\p alg is not\n *                      a supported algorithm identifier or policy.\n */\n#define PSA_ALG_IS_RSA_PSS_STANDARD_SALT(alg)                   \\\n    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE)\n\n/** Whether the specified algorithm is RSA PSS with any salt.\n *\n * \\param alg           An algorithm value or an algorithm policy wildcard.\n *\n * \\return              1 if \\p alg is of the form\n *                      #PSA_ALG_RSA_PSS_ANY_SALT_BASE(\\c hash_alg),\n *                      where \\c hash_alg is a hash algorithm or\n *                      #PSA_ALG_ANY_HASH. 0 otherwise.\n *                      This macro may return either 0 or 1 if \\p alg is not\n *                      a supported algorithm identifier or policy.\n */\n#define PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)                                \\\n    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_ANY_SALT_BASE)\n\n/** Whether the specified algorithm is RSA PSS.\n *\n * This includes any of the RSA PSS algorithm variants, regardless of the\n * constraints on salt length.\n *\n * \\param alg           An algorithm value or an algorithm policy wildcard.\n *\n * \\return              1 if \\p alg is of the form\n *                      #PSA_ALG_RSA_PSS(\\c hash_alg) or\n *                      #PSA_ALG_RSA_PSS_ANY_SALT_BASE(\\c hash_alg),\n *                      where \\c hash_alg is a hash algorithm or\n *                      #PSA_ALG_ANY_HASH. 0 otherwise.\n *                      This macro may return either 0 or 1 if \\p alg is not\n *                      a supported algorithm identifier or policy.\n */\n#define PSA_ALG_IS_RSA_PSS(alg)                                 \\\n    (PSA_ALG_IS_RSA_PSS_STANDARD_SALT(alg) ||                   \\\n     PSA_ALG_IS_RSA_PSS_ANY_SALT(alg))\n\n#define PSA_ALG_ECDSA_BASE                      ((psa_algorithm_t) 0x06000600)\n/** ECDSA signature with hashing.\n *\n * This is the ECDSA signature scheme defined by ANSI X9.62,\n * with a random per-message secret number (*k*).\n *\n * The representation of the signature as a byte string consists of\n * the concatenation of the signature values *r* and *s*. Each of\n * *r* and *s* is encoded as an *N*-octet string, where *N* is the length\n * of the base point of the curve in octets. Each value is represented\n * in big-endian order (most significant octet first).\n *\n * \\param hash_alg      A hash algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_HASH(\\p hash_alg) is true).\n *                      This includes #PSA_ALG_ANY_HASH\n *                      when specifying the algorithm in a usage policy.\n *\n * \\return              The corresponding ECDSA signature algorithm.\n * \\return              Unspecified if \\p hash_alg is not a supported\n *                      hash algorithm.\n */\n#define PSA_ALG_ECDSA(hash_alg)                                 \\\n    (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))\n/** ECDSA signature without hashing.\n *\n * This is the same signature scheme as #PSA_ALG_ECDSA(), but\n * without specifying a hash algorithm. This algorithm may only be\n * used to sign or verify a sequence of bytes that should be an\n * already-calculated hash. Note that the input is padded with\n * zeros on the left or truncated on the left as required to fit\n * the curve size.\n */\n#define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE\n#define PSA_ALG_DETERMINISTIC_ECDSA_BASE        ((psa_algorithm_t) 0x06000700)\n/** Deterministic ECDSA signature with hashing.\n *\n * This is the deterministic ECDSA signature scheme defined by RFC 6979.\n *\n * The representation of a signature is the same as with #PSA_ALG_ECDSA().\n *\n * Note that when this algorithm is used for verification, signatures\n * made with randomized ECDSA (#PSA_ALG_ECDSA(\\p hash_alg)) with the\n * same private key are accepted. In other words,\n * #PSA_ALG_DETERMINISTIC_ECDSA(\\p hash_alg) differs from\n * #PSA_ALG_ECDSA(\\p hash_alg) only for signature, not for verification.\n *\n * \\param hash_alg      A hash algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_HASH(\\p hash_alg) is true).\n *                      This includes #PSA_ALG_ANY_HASH\n *                      when specifying the algorithm in a usage policy.\n *\n * \\return              The corresponding deterministic ECDSA signature\n *                      algorithm.\n * \\return              Unspecified if \\p hash_alg is not a supported\n *                      hash algorithm.\n */\n#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg)                           \\\n    (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))\n#define PSA_ALG_ECDSA_DETERMINISTIC_FLAG        ((psa_algorithm_t) 0x00000100)\n#define PSA_ALG_IS_ECDSA(alg)                                           \\\n    (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) ==  \\\n     PSA_ALG_ECDSA_BASE)\n#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)             \\\n    (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0)\n#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg)                             \\\n    (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg))\n#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg)                                \\\n    (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg))\n\n/** Edwards-curve digital signature algorithm without prehashing (PureEdDSA),\n * using standard parameters.\n *\n * Contexts are not supported in the current version of this specification\n * because there is no suitable signature interface that can take the\n * context as a parameter. A future version of this specification may add\n * suitable functions and extend this algorithm to support contexts.\n *\n * PureEdDSA requires an elliptic curve key on a twisted Edwards curve.\n * In this specification, the following curves are supported:\n * - #PSA_ECC_FAMILY_TWISTED_EDWARDS, 255-bit: Ed25519 as specified\n *   in RFC 8032.\n *   The curve is Edwards25519.\n *   The hash function used internally is SHA-512.\n * - #PSA_ECC_FAMILY_TWISTED_EDWARDS, 448-bit: Ed448 as specified\n *   in RFC 8032.\n *   The curve is Edwards448.\n *   The hash function used internally is the first 114 bytes of the\n *   SHAKE256 output.\n *\n * This algorithm can be used with psa_sign_message() and\n * psa_verify_message(). Since there is no prehashing, it cannot be used\n * with psa_sign_hash() or psa_verify_hash().\n *\n * The signature format is the concatenation of R and S as defined by\n * RFC 8032 §5.1.6 and §5.2.6 (a 64-byte string for Ed25519, a 114-byte\n * string for Ed448).\n */\n#define PSA_ALG_PURE_EDDSA                      ((psa_algorithm_t) 0x06000800)\n\n#define PSA_ALG_HASH_EDDSA_BASE                 ((psa_algorithm_t) 0x06000900)\n#define PSA_ALG_IS_HASH_EDDSA(alg)              \\\n    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HASH_EDDSA_BASE)\n\n/** Edwards-curve digital signature algorithm with prehashing (HashEdDSA),\n * using SHA-512 and the Edwards25519 curve.\n *\n * See #PSA_ALG_PURE_EDDSA regarding context support and the signature format.\n *\n * This algorithm is Ed25519 as specified in RFC 8032.\n * The curve is Edwards25519.\n * The prehash is SHA-512.\n * The hash function used internally is SHA-512.\n *\n * This is a hash-and-sign algorithm: to calculate a signature,\n * you can either:\n * - call psa_sign_message() on the message;\n * - or calculate the SHA-512 hash of the message\n *   with psa_hash_compute()\n *   or with a multi-part hash operation started with psa_hash_setup(),\n *   using the hash algorithm #PSA_ALG_SHA_512,\n *   then sign the calculated hash with psa_sign_hash().\n * Verifying a signature is similar, using psa_verify_message() or\n * psa_verify_hash() instead of the signature function.\n */\n#define PSA_ALG_ED25519PH                               \\\n    (PSA_ALG_HASH_EDDSA_BASE | (PSA_ALG_SHA_512 & PSA_ALG_HASH_MASK))\n\n/** Edwards-curve digital signature algorithm with prehashing (HashEdDSA),\n * using SHAKE256 and the Edwards448 curve.\n *\n * See #PSA_ALG_PURE_EDDSA regarding context support and the signature format.\n *\n * This algorithm is Ed448 as specified in RFC 8032.\n * The curve is Edwards448.\n * The prehash is the first 64 bytes of the SHAKE256 output.\n * The hash function used internally is the first 114 bytes of the\n * SHAKE256 output.\n *\n * This is a hash-and-sign algorithm: to calculate a signature,\n * you can either:\n * - call psa_sign_message() on the message;\n * - or calculate the first 64 bytes of the SHAKE256 output of the message\n *   with psa_hash_compute()\n *   or with a multi-part hash operation started with psa_hash_setup(),\n *   using the hash algorithm #PSA_ALG_SHAKE256_512,\n *   then sign the calculated hash with psa_sign_hash().\n * Verifying a signature is similar, using psa_verify_message() or\n * psa_verify_hash() instead of the signature function.\n */\n#define PSA_ALG_ED448PH                                 \\\n    (PSA_ALG_HASH_EDDSA_BASE | (PSA_ALG_SHAKE256_512 & PSA_ALG_HASH_MASK))\n\n/* Default definition, to be overridden if the library is extended with\n * more hash-and-sign algorithms that we want to keep out of this header\n * file. */\n#define PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg) 0\n\n/** Whether the specified algorithm is a signature algorithm that can be used\n * with psa_sign_hash() and psa_verify_hash().\n *\n * This encompasses all strict hash-and-sign algorithms categorized by\n * PSA_ALG_IS_HASH_AND_SIGN(), as well as algorithms that follow the\n * paradigm more loosely:\n * - #PSA_ALG_RSA_PKCS1V15_SIGN_RAW (expects its input to be an encoded hash)\n * - #PSA_ALG_ECDSA_ANY (doesn't specify what kind of hash the input is)\n *\n * \\param alg An algorithm identifier (value of type psa_algorithm_t).\n *\n * \\return 1 if alg is a signature algorithm that can be used to sign a\n *         hash. 0 if alg is a signature algorithm that can only be used\n *         to sign a message. 0 if alg is not a signature algorithm.\n *         This macro can return either 0 or 1 if alg is not a\n *         supported algorithm identifier.\n */\n#define PSA_ALG_IS_SIGN_HASH(alg)                                       \\\n    (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||    \\\n     PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_HASH_EDDSA(alg) ||             \\\n     PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg))\n\n/** Whether the specified algorithm is a signature algorithm that can be used\n * with psa_sign_message() and psa_verify_message().\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if alg is a signature algorithm that can be used to sign a\n *         message. 0 if \\p alg is a signature algorithm that can only be used\n *         to sign an already-calculated hash. 0 if \\p alg is not a signature\n *         algorithm. This macro can return either 0 or 1 if \\p alg is not a\n *         supported algorithm identifier.\n */\n#define PSA_ALG_IS_SIGN_MESSAGE(alg)                                    \\\n    (PSA_ALG_IS_SIGN_HASH(alg) || (alg) == PSA_ALG_PURE_EDDSA)\n\n/** Whether the specified algorithm is a hash-and-sign algorithm.\n *\n * Hash-and-sign algorithms are asymmetric (public-key) signature algorithms\n * structured in two parts: first the calculation of a hash in a way that\n * does not depend on the key, then the calculation of a signature from the\n * hash value and the key. Hash-and-sign algorithms encode the hash\n * used for the hashing step, and you can call #PSA_ALG_SIGN_GET_HASH\n * to extract this algorithm.\n *\n * Thus, for a hash-and-sign algorithm,\n * `psa_sign_message(key, alg, input, ...)` is equivalent to\n * ```\n * psa_hash_compute(PSA_ALG_SIGN_GET_HASH(alg), input, ..., hash, ...);\n * psa_sign_hash(key, alg, hash, ..., signature, ...);\n * ```\n * Most usefully, separating the hash from the signature allows the hash\n * to be calculated in multiple steps with psa_hash_setup(), psa_hash_update()\n * and psa_hash_finish(). Likewise psa_verify_message() is equivalent to\n * calculating the hash and then calling psa_verify_hash().\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is a hash-and-sign algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\p alg is not a supported\n *         algorithm identifier.\n */\n#define PSA_ALG_IS_HASH_AND_SIGN(alg)                                   \\\n    (PSA_ALG_IS_SIGN_HASH(alg) &&                                       \\\n     ((alg) & PSA_ALG_HASH_MASK) != 0)\n\n/** Get the hash used by a hash-and-sign signature algorithm.\n *\n * A hash-and-sign algorithm is a signature algorithm which is\n * composed of two phases: first a hashing phase which does not use\n * the key and produces a hash of the input message, then a signing\n * phase which only uses the hash and the key and not the message\n * itself.\n *\n * \\param alg   A signature algorithm (\\c PSA_ALG_XXX value such that\n *              #PSA_ALG_IS_SIGN(\\p alg) is true).\n *\n * \\return      The underlying hash algorithm if \\p alg is a hash-and-sign\n *              algorithm.\n * \\return      0 if \\p alg is a signature algorithm that does not\n *              follow the hash-and-sign structure.\n * \\return      Unspecified if \\p alg is not a signature algorithm or\n *              if it is not supported by the implementation.\n */\n#define PSA_ALG_SIGN_GET_HASH(alg)                                     \\\n    (PSA_ALG_IS_HASH_AND_SIGN(alg) ?                                   \\\n     ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH :             \\\n     0)\n\n/** RSA PKCS#1 v1.5 encryption.\n *\n * \\warning     Calling psa_asymmetric_decrypt() with this algorithm as a\n *              parameter is considered an inherently dangerous function\n *              (CWE-242). Unless it is used in a side channel free and safe\n *              way (eg. implementing the TLS protocol as per 7.4.7.1 of\n *              RFC 5246), the calling code is vulnerable.\n *\n */\n#define PSA_ALG_RSA_PKCS1V15_CRYPT              ((psa_algorithm_t) 0x07000200)\n\n#define PSA_ALG_RSA_OAEP_BASE                   ((psa_algorithm_t) 0x07000300)\n/** RSA OAEP encryption.\n *\n * This is the encryption scheme defined by RFC 8017\n * (PKCS#1: RSA Cryptography Specifications) under the name\n * RSAES-OAEP, with the message generation function MGF1.\n *\n * \\param hash_alg      The hash algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_HASH(\\p hash_alg) is true) to use\n *                      for MGF1.\n *\n * \\return              The corresponding RSA OAEP encryption algorithm.\n * \\return              Unspecified if \\p hash_alg is not a supported\n *                      hash algorithm.\n */\n#define PSA_ALG_RSA_OAEP(hash_alg)                              \\\n    (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))\n#define PSA_ALG_IS_RSA_OAEP(alg)                                \\\n    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE)\n#define PSA_ALG_RSA_OAEP_GET_HASH(alg)                          \\\n    (PSA_ALG_IS_RSA_OAEP(alg) ?                                 \\\n     ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH :      \\\n     0)\n\n#define PSA_ALG_HKDF_BASE                       ((psa_algorithm_t) 0x08000100)\n/** Macro to build an HKDF algorithm.\n *\n * For example, `PSA_ALG_HKDF(PSA_ALG_SHA_256)` is HKDF using HMAC-SHA-256.\n *\n * This key derivation algorithm uses the following inputs:\n * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the \"extract\" step.\n *   It is optional; if omitted, the derivation uses an empty salt.\n * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key used in the \"extract\" step.\n * - #PSA_KEY_DERIVATION_INPUT_INFO is the info string used in the \"expand\" step.\n * You must pass #PSA_KEY_DERIVATION_INPUT_SALT before #PSA_KEY_DERIVATION_INPUT_SECRET.\n * You may pass #PSA_KEY_DERIVATION_INPUT_INFO at any time after steup and before\n * starting to generate output.\n *\n *  \\warning  HKDF processes the salt as follows: first hash it with hash_alg\n *  if the salt is longer than the block size of the hash algorithm; then\n *  pad with null bytes up to the block size. As a result, it is possible\n *  for distinct salt inputs to result in the same outputs. To ensure\n *  unique outputs, it is recommended to use a fixed length for salt values.\n *\n * \\param hash_alg      A hash algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_HASH(\\p hash_alg) is true).\n *\n * \\return              The corresponding HKDF algorithm.\n * \\return              Unspecified if \\p hash_alg is not a supported\n *                      hash algorithm.\n */\n#define PSA_ALG_HKDF(hash_alg)                                  \\\n    (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))\n/** Whether the specified algorithm is an HKDF algorithm.\n *\n * HKDF is a family of key derivation algorithms that are based on a hash\n * function and the HMAC construction.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\c alg is an HKDF algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\c alg is not a supported\n *         key derivation algorithm identifier.\n */\n#define PSA_ALG_IS_HKDF(alg)                            \\\n    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE)\n#define PSA_ALG_HKDF_GET_HASH(hkdf_alg)                         \\\n    (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK))\n\n#define PSA_ALG_HKDF_EXTRACT_BASE                       ((psa_algorithm_t) 0x08000400)\n/** Macro to build an HKDF-Extract algorithm.\n *\n * For example, `PSA_ALG_HKDF_EXTRACT(PSA_ALG_SHA_256)` is\n * HKDF-Extract using HMAC-SHA-256.\n *\n * This key derivation algorithm uses the following inputs:\n *  - PSA_KEY_DERIVATION_INPUT_SALT is the salt.\n *  - PSA_KEY_DERIVATION_INPUT_SECRET is the input keying material used in the\n *    \"extract\" step.\n * The inputs are mandatory and must be passed in the order above.\n * Each input may only be passed once.\n *\n *  \\warning HKDF-Extract is not meant to be used on its own. PSA_ALG_HKDF\n *  should be used instead if possible. PSA_ALG_HKDF_EXTRACT is provided\n *  as a separate algorithm for the sake of protocols that use it as a\n *  building block. It may also be a slight performance optimization\n *  in applications that use HKDF with the same salt and key but many\n *  different info strings.\n *\n *  \\warning  HKDF processes the salt as follows: first hash it with hash_alg\n *  if the salt is longer than the block size of the hash algorithm; then\n *  pad with null bytes up to the block size. As a result, it is possible\n *  for distinct salt inputs to result in the same outputs. To ensure\n *  unique outputs, it is recommended to use a fixed length for salt values.\n *\n * \\param hash_alg      A hash algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_HASH(\\p hash_alg) is true).\n *\n * \\return              The corresponding HKDF-Extract algorithm.\n * \\return              Unspecified if \\p hash_alg is not a supported\n *                      hash algorithm.\n */\n#define PSA_ALG_HKDF_EXTRACT(hash_alg)                                  \\\n    (PSA_ALG_HKDF_EXTRACT_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))\n/** Whether the specified algorithm is an HKDF-Extract algorithm.\n *\n * HKDF-Extract is a family of key derivation algorithms that are based\n * on a hash function and the HMAC construction.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\c alg is an HKDF-Extract algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\c alg is not a supported\n *         key derivation algorithm identifier.\n */\n#define PSA_ALG_IS_HKDF_EXTRACT(alg)                            \\\n    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXTRACT_BASE)\n\n#define PSA_ALG_HKDF_EXPAND_BASE                       ((psa_algorithm_t) 0x08000500)\n/** Macro to build an HKDF-Expand algorithm.\n *\n * For example, `PSA_ALG_HKDF_EXPAND(PSA_ALG_SHA_256)` is\n * HKDF-Expand using HMAC-SHA-256.\n *\n * This key derivation algorithm uses the following inputs:\n *  - PSA_KEY_DERIVATION_INPUT_SECRET is the pseudorandom key (PRK).\n *  - PSA_KEY_DERIVATION_INPUT_INFO is the info string.\n *\n *  The inputs are mandatory and must be passed in the order above.\n *  Each input may only be passed once.\n *\n *  \\warning HKDF-Expand is not meant to be used on its own. `PSA_ALG_HKDF`\n *  should be used instead if possible. `PSA_ALG_HKDF_EXPAND` is provided as\n *  a separate algorithm for the sake of protocols that use it as a building\n *  block. It may also be a slight performance optimization in applications\n *  that use HKDF with the same salt and key but many different info strings.\n *\n * \\param hash_alg      A hash algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_HASH(\\p hash_alg) is true).\n *\n * \\return              The corresponding HKDF-Expand algorithm.\n * \\return              Unspecified if \\p hash_alg is not a supported\n *                      hash algorithm.\n */\n#define PSA_ALG_HKDF_EXPAND(hash_alg)                                  \\\n    (PSA_ALG_HKDF_EXPAND_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))\n/** Whether the specified algorithm is an HKDF-Expand algorithm.\n *\n * HKDF-Expand is a family of key derivation algorithms that are based\n * on a hash function and the HMAC construction.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\c alg is an HKDF-Expand algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\c alg is not a supported\n *         key derivation algorithm identifier.\n */\n#define PSA_ALG_IS_HKDF_EXPAND(alg)                            \\\n    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXPAND_BASE)\n\n/** Whether the specified algorithm is an HKDF or HKDF-Extract or\n *  HKDF-Expand algorithm.\n *\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\c alg is any HKDF type algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\c alg is not a supported\n *         key derivation algorithm identifier.\n */\n#define PSA_ALG_IS_ANY_HKDF(alg)                                   \\\n    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE ||          \\\n     ((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXTRACT_BASE ||  \\\n     ((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXPAND_BASE)\n\n#define PSA_ALG_TLS12_PRF_BASE                  ((psa_algorithm_t) 0x08000200)\n/** Macro to build a TLS-1.2 PRF algorithm.\n *\n * TLS 1.2 uses a custom pseudorandom function (PRF) for key schedule,\n * specified in Section 5 of RFC 5246. It is based on HMAC and can be\n * used with either SHA-256 or SHA-384.\n *\n * This key derivation algorithm uses the following inputs, which must be\n * passed in the order given here:\n * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed.\n * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key.\n * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label.\n *\n * For the application to TLS-1.2 key expansion, the seed is the\n * concatenation of ServerHello.Random + ClientHello.Random,\n * and the label is \"key expansion\".\n *\n * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)` represents the\n * TLS 1.2 PRF using HMAC-SHA-256.\n *\n * \\param hash_alg      A hash algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_HASH(\\p hash_alg) is true).\n *\n * \\return              The corresponding TLS-1.2 PRF algorithm.\n * \\return              Unspecified if \\p hash_alg is not a supported\n *                      hash algorithm.\n */\n#define PSA_ALG_TLS12_PRF(hash_alg)                                  \\\n    (PSA_ALG_TLS12_PRF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))\n\n/** Whether the specified algorithm is a TLS-1.2 PRF algorithm.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\c alg is a TLS-1.2 PRF algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\c alg is not a supported\n *         key derivation algorithm identifier.\n */\n#define PSA_ALG_IS_TLS12_PRF(alg)                                    \\\n    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PRF_BASE)\n#define PSA_ALG_TLS12_PRF_GET_HASH(hkdf_alg)                         \\\n    (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK))\n\n#define PSA_ALG_TLS12_PSK_TO_MS_BASE            ((psa_algorithm_t) 0x08000300)\n/** Macro to build a TLS-1.2 PSK-to-MasterSecret algorithm.\n *\n * In a pure-PSK handshake in TLS 1.2, the master secret is derived\n * from the PreSharedKey (PSK) through the application of padding\n * (RFC 4279, Section 2) and the TLS-1.2 PRF (RFC 5246, Section 5).\n * The latter is based on HMAC and can be used with either SHA-256\n * or SHA-384.\n *\n * This key derivation algorithm uses the following inputs, which must be\n * passed in the order given here:\n * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed.\n * - #PSA_KEY_DERIVATION_INPUT_OTHER_SECRET is the other secret for the\n *   computation of the premaster secret. This input is optional;\n *   if omitted, it defaults to a string of null bytes with the same length\n *   as the secret (PSK) input.\n * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key.\n * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label.\n *\n * For the application to TLS-1.2, the seed (which is\n * forwarded to the TLS-1.2 PRF) is the concatenation of the\n * ClientHello.Random + ServerHello.Random,\n * the label is \"master secret\" or \"extended master secret\" and\n * the other secret depends on the key exchange specified in the cipher suite:\n * - for a plain PSK cipher suite (RFC 4279, Section 2), omit\n *   PSA_KEY_DERIVATION_INPUT_OTHER_SECRET\n * - for a DHE-PSK (RFC 4279, Section 3) or ECDHE-PSK cipher suite\n *   (RFC 5489, Section 2), the other secret should be the output of the\n *   PSA_ALG_FFDH or PSA_ALG_ECDH key agreement performed with the peer.\n *   The recommended way to pass this input is to use a key derivation\n *   algorithm constructed as\n *   PSA_ALG_KEY_AGREEMENT(ka_alg, PSA_ALG_TLS12_PSK_TO_MS(hash_alg))\n *   and to call psa_key_derivation_key_agreement(). Alternatively,\n *   this input may be an output of `psa_raw_key_agreement()` passed with\n *   psa_key_derivation_input_bytes(), or an equivalent input passed with\n *   psa_key_derivation_input_bytes() or psa_key_derivation_input_key().\n * - for a RSA-PSK cipher suite (RFC 4279, Section 4), the other secret\n *   should be the 48-byte client challenge (the PreMasterSecret of\n *   (RFC 5246, Section 7.4.7.1)) concatenation of the TLS version and\n *   a 46-byte random string chosen by the client. On the server, this is\n *   typically an output of psa_asymmetric_decrypt() using\n *   PSA_ALG_RSA_PKCS1V15_CRYPT, passed to the key derivation operation\n *   with `psa_key_derivation_input_bytes()`.\n *\n * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256)` represents the\n * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256.\n *\n * \\param hash_alg      A hash algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_HASH(\\p hash_alg) is true).\n *\n * \\return              The corresponding TLS-1.2 PSK to MS algorithm.\n * \\return              Unspecified if \\p hash_alg is not a supported\n *                      hash algorithm.\n */\n#define PSA_ALG_TLS12_PSK_TO_MS(hash_alg)                                  \\\n    (PSA_ALG_TLS12_PSK_TO_MS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))\n\n/** Whether the specified algorithm is a TLS-1.2 PSK to MS algorithm.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\c alg is a TLS-1.2 PSK to MS algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\c alg is not a supported\n *         key derivation algorithm identifier.\n */\n#define PSA_ALG_IS_TLS12_PSK_TO_MS(alg)                                    \\\n    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PSK_TO_MS_BASE)\n#define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg)                         \\\n    (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK))\n\n/* The TLS 1.2 ECJPAKE-to-PMS KDF. It takes the shared secret K (an EC point\n * in case of EC J-PAKE) and calculates SHA256(K.X) that the rest of TLS 1.2\n * will use to derive the session secret, as defined by step 2 of\n * https://datatracker.ietf.org/doc/html/draft-cragie-tls-ecjpake-01#section-8.7.\n * Uses PSA_ALG_SHA_256.\n * This function takes a single input:\n * #PSA_KEY_DERIVATION_INPUT_SECRET is the shared secret K from EC J-PAKE.\n * The only supported curve is secp256r1 (the 256-bit curve in\n * #PSA_ECC_FAMILY_SECP_R1), so the input must be exactly 65 bytes.\n * The output has to be read as a single chunk of 32 bytes, defined as\n * PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE.\n */\n#define PSA_ALG_TLS12_ECJPAKE_TO_PMS            ((psa_algorithm_t) 0x08000609)\n\n/* This flag indicates whether the key derivation algorithm is suitable for\n * use on low-entropy secrets such as password - these algorithms are also\n * known as key stretching or password hashing schemes. These are also the\n * algorithms that accepts inputs of type #PSA_KEY_DERIVATION_INPUT_PASSWORD.\n *\n * Those algorithms cannot be combined with a key agreement algorithm.\n */\n#define PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG  ((psa_algorithm_t) 0x00800000)\n\n#define PSA_ALG_PBKDF2_HMAC_BASE                ((psa_algorithm_t) 0x08800100)\n/** Macro to build a PBKDF2-HMAC password hashing / key stretching algorithm.\n *\n * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2).\n * This macro specifies the PBKDF2 algorithm constructed using a PRF based on\n * HMAC with the specified hash.\n * For example, `PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256)` specifies PBKDF2\n * using the PRF HMAC-SHA-256.\n *\n * This key derivation algorithm uses the following inputs, which must be\n * provided in the following order:\n * - #PSA_KEY_DERIVATION_INPUT_COST is the iteration count.\n *   This input step must be used exactly once.\n * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt.\n *   This input step must be used one or more times; if used several times, the\n *   inputs will be concatenated. This can be used to build the final salt\n *   from multiple sources, both public and secret (also known as pepper).\n * - #PSA_KEY_DERIVATION_INPUT_PASSWORD is the password to be hashed.\n *   This input step must be used exactly once.\n *\n * \\param hash_alg      A hash algorithm (\\c PSA_ALG_XXX value such that\n *                      #PSA_ALG_IS_HASH(\\p hash_alg) is true).\n *\n * \\return              The corresponding PBKDF2-HMAC-XXX algorithm.\n * \\return              Unspecified if \\p hash_alg is not a supported\n *                      hash algorithm.\n */\n#define PSA_ALG_PBKDF2_HMAC(hash_alg)                                  \\\n    (PSA_ALG_PBKDF2_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))\n\n/** Whether the specified algorithm is a PBKDF2-HMAC algorithm.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\c alg is a PBKDF2-HMAC algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\c alg is not a supported\n *         key derivation algorithm identifier.\n */\n#define PSA_ALG_IS_PBKDF2_HMAC(alg)                                    \\\n    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_PBKDF2_HMAC_BASE)\n#define PSA_ALG_PBKDF2_HMAC_GET_HASH(pbkdf2_alg)                         \\\n    (PSA_ALG_CATEGORY_HASH | ((pbkdf2_alg) & PSA_ALG_HASH_MASK))\n/** The PBKDF2-AES-CMAC-PRF-128 password hashing / key stretching algorithm.\n *\n * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2).\n * This macro specifies the PBKDF2 algorithm constructed using the\n * AES-CMAC-PRF-128 PRF specified by RFC 4615.\n *\n * This key derivation algorithm uses the same inputs as\n * #PSA_ALG_PBKDF2_HMAC() with the same constraints.\n */\n#define PSA_ALG_PBKDF2_AES_CMAC_PRF_128         ((psa_algorithm_t) 0x08800200)\n\n#define PSA_ALG_IS_PBKDF2(kdf_alg)                                      \\\n    (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg) || \\\n     ((kdf_alg) == PSA_ALG_PBKDF2_AES_CMAC_PRF_128))\n\n#define PSA_ALG_KEY_DERIVATION_MASK             ((psa_algorithm_t) 0xfe00ffff)\n#define PSA_ALG_KEY_AGREEMENT_MASK              ((psa_algorithm_t) 0xffff0000)\n\n/** Macro to build a combined algorithm that chains a key agreement with\n * a key derivation.\n *\n * \\param ka_alg        A key agreement algorithm (\\c PSA_ALG_XXX value such\n *                      that #PSA_ALG_IS_KEY_AGREEMENT(\\p ka_alg) is true).\n * \\param kdf_alg       A key derivation algorithm (\\c PSA_ALG_XXX value such\n *                      that #PSA_ALG_IS_KEY_DERIVATION(\\p kdf_alg) is true).\n *\n * \\return              The corresponding key agreement and derivation\n *                      algorithm.\n * \\return              Unspecified if \\p ka_alg is not a supported\n *                      key agreement algorithm or \\p kdf_alg is not a\n *                      supported key derivation algorithm.\n */\n#define PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg)  \\\n    ((ka_alg) | (kdf_alg))\n\n#define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg)                              \\\n    (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION)\n\n#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg)                             \\\n    (((alg) & PSA_ALG_KEY_AGREEMENT_MASK) | PSA_ALG_CATEGORY_KEY_AGREEMENT)\n\n/** Whether the specified algorithm is a raw key agreement algorithm.\n *\n * A raw key agreement algorithm is one that does not specify\n * a key derivation function.\n * Usually, raw key agreement algorithms are constructed directly with\n * a \\c PSA_ALG_xxx macro while non-raw key agreement algorithms are\n * constructed with #PSA_ALG_KEY_AGREEMENT().\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\p alg is a raw key agreement algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\p alg is not a supported\n *         algorithm identifier.\n */\n#define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)                               \\\n    (PSA_ALG_IS_KEY_AGREEMENT(alg) &&                                   \\\n     PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) == PSA_ALG_CATEGORY_KEY_DERIVATION)\n\n#define PSA_ALG_IS_KEY_DERIVATION_OR_AGREEMENT(alg)     \\\n    ((PSA_ALG_IS_KEY_DERIVATION(alg) || PSA_ALG_IS_KEY_AGREEMENT(alg)))\n\n/** The finite-field Diffie-Hellman (DH) key agreement algorithm.\n *\n * The shared secret produced by key agreement is\n * `g^{ab}` in big-endian format.\n * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p`\n * in bits.\n */\n#define PSA_ALG_FFDH                            ((psa_algorithm_t) 0x09010000)\n\n/** Whether the specified algorithm is a finite field Diffie-Hellman algorithm.\n *\n * This includes the raw finite field Diffie-Hellman algorithm as well as\n * finite-field Diffie-Hellman followed by any supporter key derivation\n * algorithm.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\c alg is a finite field Diffie-Hellman algorithm, 0 otherwise.\n *         This macro may return either 0 or 1 if \\c alg is not a supported\n *         key agreement algorithm identifier.\n */\n#define PSA_ALG_IS_FFDH(alg) \\\n    (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH)\n\n/** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm.\n *\n * The shared secret produced by key agreement is the x-coordinate of\n * the shared secret point. It is always `ceiling(m / 8)` bytes long where\n * `m` is the bit size associated with the curve, i.e. the bit size of the\n * order of the curve's coordinate field. When `m` is not a multiple of 8,\n * the byte containing the most significant bit of the shared secret\n * is padded with zero bits. The byte order is either little-endian\n * or big-endian depending on the curve type.\n *\n * - For Montgomery curves (curve types `PSA_ECC_FAMILY_CURVEXXX`),\n *   the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A`\n *   in little-endian byte order.\n *   The bit size is 448 for Curve448 and 255 for Curve25519.\n * - For Weierstrass curves over prime fields (curve types\n *   `PSA_ECC_FAMILY_SECPXXX` and `PSA_ECC_FAMILY_BRAINPOOL_PXXX`),\n *   the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A`\n *   in big-endian byte order.\n *   The bit size is `m = ceiling(log_2(p))` for the field `F_p`.\n * - For Weierstrass curves over binary fields (curve types\n *   `PSA_ECC_FAMILY_SECTXXX`),\n *   the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A`\n *   in big-endian byte order.\n *   The bit size is `m` for the field `F_{2^m}`.\n */\n#define PSA_ALG_ECDH                            ((psa_algorithm_t) 0x09020000)\n\n/** Whether the specified algorithm is an elliptic curve Diffie-Hellman\n * algorithm.\n *\n * This includes the raw elliptic curve Diffie-Hellman algorithm as well as\n * elliptic curve Diffie-Hellman followed by any supporter key derivation\n * algorithm.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\c alg is an elliptic curve Diffie-Hellman algorithm,\n *         0 otherwise.\n *         This macro may return either 0 or 1 if \\c alg is not a supported\n *         key agreement algorithm identifier.\n */\n#define PSA_ALG_IS_ECDH(alg) \\\n    (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH)\n\n/** Whether the specified algorithm encoding is a wildcard.\n *\n * Wildcard values may only be used to set the usage algorithm field in\n * a policy, not to perform an operation.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return 1 if \\c alg is a wildcard algorithm encoding.\n * \\return 0 if \\c alg is a non-wildcard algorithm encoding (suitable for\n *         an operation).\n * \\return This macro may return either 0 or 1 if \\c alg is not a supported\n *         algorithm identifier.\n */\n#define PSA_ALG_IS_WILDCARD(alg)                            \\\n    (PSA_ALG_IS_HASH_AND_SIGN(alg) ?                        \\\n     PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH :       \\\n     PSA_ALG_IS_MAC(alg) ?                                  \\\n     (alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0 :   \\\n     PSA_ALG_IS_AEAD(alg) ?                                 \\\n     (alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0 :  \\\n     (alg) == PSA_ALG_ANY_HASH)\n\n/** Get the hash used by a composite algorithm.\n *\n * \\param alg An algorithm identifier (value of type #psa_algorithm_t).\n *\n * \\return The underlying hash algorithm if alg is a composite algorithm that\n * uses a hash algorithm.\n *\n * \\return \\c 0 if alg is not a composite algorithm that uses a hash.\n */\n#define PSA_ALG_GET_HASH(alg) \\\n    (((alg) & 0x000000ff) == 0 ? ((psa_algorithm_t) 0) : 0x02000000 | ((alg) & 0x000000ff))\n\n/**@}*/\n\n/** \\defgroup key_lifetimes Key lifetimes\n * @{\n */\n\n/* Note that location and persistence level values are embedded in the\n * persistent key store, as part of key metadata. As a consequence, they\n * must not be changed (unless the storage format version changes).\n */\n\n/** The default lifetime for volatile keys.\n *\n * A volatile key only exists as long as the identifier to it is not destroyed.\n * The key material is guaranteed to be erased on a power reset.\n *\n * A key with this lifetime is typically stored in the RAM area of the\n * PSA Crypto subsystem. However this is an implementation choice.\n * If an implementation stores data about the key in a non-volatile memory,\n * it must release all the resources associated with the key and erase the\n * key material if the calling application terminates.\n */\n#define PSA_KEY_LIFETIME_VOLATILE               ((psa_key_lifetime_t) 0x00000000)\n\n/** The default lifetime for persistent keys.\n *\n * A persistent key remains in storage until it is explicitly destroyed or\n * until the corresponding storage area is wiped. This specification does\n * not define any mechanism to wipe a storage area, but integrations may\n * provide their own mechanism (for example to perform a factory reset,\n * to prepare for device refurbishment, or to uninstall an application).\n *\n * This lifetime value is the default storage area for the calling\n * application. Integrations of Mbed TLS may support other persistent lifetimes.\n * See ::psa_key_lifetime_t for more information.\n */\n#define PSA_KEY_LIFETIME_PERSISTENT             ((psa_key_lifetime_t) 0x00000001)\n\n/** The persistence level of volatile keys.\n *\n * See ::psa_key_persistence_t for more information.\n */\n#define PSA_KEY_PERSISTENCE_VOLATILE            ((psa_key_persistence_t) 0x00)\n\n/** The default persistence level for persistent keys.\n *\n * See ::psa_key_persistence_t for more information.\n */\n#define PSA_KEY_PERSISTENCE_DEFAULT             ((psa_key_persistence_t) 0x01)\n\n/** A persistence level indicating that a key is never destroyed.\n *\n * See ::psa_key_persistence_t for more information.\n */\n#define PSA_KEY_PERSISTENCE_READ_ONLY           ((psa_key_persistence_t) 0xff)\n\n#define PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime)      \\\n    ((psa_key_persistence_t) ((lifetime) & 0x000000ff))\n\n#define PSA_KEY_LIFETIME_GET_LOCATION(lifetime)      \\\n    ((psa_key_location_t) ((lifetime) >> 8))\n\n/** Whether a key lifetime indicates that the key is volatile.\n *\n * A volatile key is automatically destroyed by the implementation when\n * the application instance terminates. In particular, a volatile key\n * is automatically destroyed on a power reset of the device.\n *\n * A key that is not volatile is persistent. Persistent keys are\n * preserved until the application explicitly destroys them or until an\n * implementation-specific device management event occurs (for example,\n * a factory reset).\n *\n * \\param lifetime      The lifetime value to query (value of type\n *                      ::psa_key_lifetime_t).\n *\n * \\return \\c 1 if the key is volatile, otherwise \\c 0.\n */\n#define PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)  \\\n    (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \\\n     PSA_KEY_PERSISTENCE_VOLATILE)\n\n/** Whether a key lifetime indicates that the key is read-only.\n *\n * Read-only keys cannot be created or destroyed through the PSA Crypto API.\n * They must be created through platform-specific means that bypass the API.\n *\n * Some platforms may offer ways to destroy read-only keys. For example,\n * consider a platform with multiple levels of privilege, where a\n * low-privilege application can use a key but is not allowed to destroy\n * it, and the platform exposes the key to the application with a read-only\n * lifetime. High-privilege code can destroy the key even though the\n * application sees the key as read-only.\n *\n * \\param lifetime      The lifetime value to query (value of type\n *                      ::psa_key_lifetime_t).\n *\n * \\return \\c 1 if the key is read-only, otherwise \\c 0.\n */\n#define PSA_KEY_LIFETIME_IS_READ_ONLY(lifetime)  \\\n    (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \\\n     PSA_KEY_PERSISTENCE_READ_ONLY)\n\n/** Construct a lifetime from a persistence level and a location.\n *\n * \\param persistence   The persistence level\n *                      (value of type ::psa_key_persistence_t).\n * \\param location      The location indicator\n *                      (value of type ::psa_key_location_t).\n *\n * \\return The constructed lifetime value.\n */\n#define PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(persistence, location) \\\n    ((location) << 8 | (persistence))\n\n/** The local storage area for persistent keys.\n *\n * This storage area is available on all systems that can store persistent\n * keys without delegating the storage to a third-party cryptoprocessor.\n *\n * See ::psa_key_location_t for more information.\n */\n#define PSA_KEY_LOCATION_LOCAL_STORAGE          ((psa_key_location_t) 0x000000)\n\n#define PSA_KEY_LOCATION_VENDOR_FLAG            ((psa_key_location_t) 0x800000)\n\n/* Note that key identifier values are embedded in the\n * persistent key store, as part of key metadata. As a consequence, they\n * must not be changed (unless the storage format version changes).\n */\n\n/** The null key identifier.\n */\n/* *INDENT-OFF* (https://github.com/ARM-software/psa-arch-tests/issues/337) */\n#define PSA_KEY_ID_NULL                         ((psa_key_id_t)0)\n/* *INDENT-ON* */\n/** The minimum value for a key identifier chosen by the application.\n */\n#define PSA_KEY_ID_USER_MIN                     ((psa_key_id_t) 0x00000001)\n/** The maximum value for a key identifier chosen by the application.\n */\n#define PSA_KEY_ID_USER_MAX                     ((psa_key_id_t) 0x3fffffff)\n/** The minimum value for a key identifier chosen by the implementation.\n */\n#define PSA_KEY_ID_VENDOR_MIN                   ((psa_key_id_t) 0x40000000)\n/** The maximum value for a key identifier chosen by the implementation.\n */\n#define PSA_KEY_ID_VENDOR_MAX                   ((psa_key_id_t) 0x7fffffff)\n\n\n#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)\n\n#define MBEDTLS_SVC_KEY_ID_INIT ((psa_key_id_t) 0)\n#define MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id) (id)\n#define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(id) (0)\n\n/** Utility to initialize a key identifier at runtime.\n *\n * \\param unused  Unused parameter.\n * \\param key_id  Identifier of the key.\n */\nstatic inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make(\n    unsigned int unused, psa_key_id_t key_id)\n{\n    (void) unused;\n\n    return key_id;\n}\n\n/** Compare two key identifiers.\n *\n * \\param id1 First key identifier.\n * \\param id2 Second key identifier.\n *\n * \\return Non-zero if the two key identifier are equal, zero otherwise.\n */\nstatic inline int mbedtls_svc_key_id_equal(mbedtls_svc_key_id_t id1,\n                                           mbedtls_svc_key_id_t id2)\n{\n    return id1 == id2;\n}\n\n/** Check whether a key identifier is null.\n *\n * \\param key Key identifier.\n *\n * \\return Non-zero if the key identifier is null, zero otherwise.\n */\nstatic inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key)\n{\n    return key == 0;\n}\n\n#else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */\n\n#define MBEDTLS_SVC_KEY_ID_INIT ((mbedtls_svc_key_id_t){ 0, 0 })\n#define MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id) ((id).MBEDTLS_PRIVATE(key_id))\n#define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(id) ((id).MBEDTLS_PRIVATE(owner))\n\n/** Utility to initialize a key identifier at runtime.\n *\n * \\param owner_id Identifier of the key owner.\n * \\param key_id   Identifier of the key.\n */\nstatic inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make(\n    mbedtls_key_owner_id_t owner_id, psa_key_id_t key_id)\n{\n    return (mbedtls_svc_key_id_t){ .MBEDTLS_PRIVATE(key_id) = key_id,\n                                   .MBEDTLS_PRIVATE(owner) = owner_id };\n}\n\n/** Compare two key identifiers.\n *\n * \\param id1 First key identifier.\n * \\param id2 Second key identifier.\n *\n * \\return Non-zero if the two key identifier are equal, zero otherwise.\n */\nstatic inline int mbedtls_svc_key_id_equal(mbedtls_svc_key_id_t id1,\n                                           mbedtls_svc_key_id_t id2)\n{\n    return (id1.MBEDTLS_PRIVATE(key_id) == id2.MBEDTLS_PRIVATE(key_id)) &&\n           mbedtls_key_owner_id_equal(id1.MBEDTLS_PRIVATE(owner), id2.MBEDTLS_PRIVATE(owner));\n}\n\n/** Check whether a key identifier is null.\n *\n * \\param key Key identifier.\n *\n * \\return Non-zero if the key identifier is null, zero otherwise.\n */\nstatic inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key)\n{\n    return key.MBEDTLS_PRIVATE(key_id) == 0;\n}\n\n#endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */\n\n/**@}*/\n\n/** \\defgroup policy Key policies\n * @{\n */\n\n/* Note that key usage flags are embedded in the\n * persistent key store, as part of key metadata. As a consequence, they\n * must not be changed (unless the storage format version changes).\n */\n\n/** Whether the key may be exported.\n *\n * A public key or the public part of a key pair may always be exported\n * regardless of the value of this permission flag.\n *\n * If a key does not have export permission, implementations shall not\n * allow the key to be exported in plain form from the cryptoprocessor,\n * whether through psa_export_key() or through a proprietary interface.\n * The key may however be exportable in a wrapped form, i.e. in a form\n * where it is encrypted by another key.\n */\n#define PSA_KEY_USAGE_EXPORT                    ((psa_key_usage_t) 0x00000001)\n\n/** Whether the key may be copied.\n *\n * This flag allows the use of psa_copy_key() to make a copy of the key\n * with the same policy or a more restrictive policy.\n *\n * For lifetimes for which the key is located in a secure element which\n * enforce the non-exportability of keys, copying a key outside the secure\n * element also requires the usage flag #PSA_KEY_USAGE_EXPORT.\n * Copying the key inside the secure element is permitted with just\n * #PSA_KEY_USAGE_COPY if the secure element supports it.\n * For keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE or\n * #PSA_KEY_LIFETIME_PERSISTENT, the usage flag #PSA_KEY_USAGE_COPY\n * is sufficient to permit the copy.\n */\n#define PSA_KEY_USAGE_COPY                      ((psa_key_usage_t) 0x00000002)\n\n/** Whether the key may be used to encrypt a message.\n *\n * This flag allows the key to be used for a symmetric encryption operation,\n * for an AEAD encryption-and-authentication operation,\n * or for an asymmetric encryption operation,\n * if otherwise permitted by the key's type and policy.\n *\n * For a key pair, this concerns the public key.\n */\n#define PSA_KEY_USAGE_ENCRYPT                   ((psa_key_usage_t) 0x00000100)\n\n/** Whether the key may be used to decrypt a message.\n *\n * This flag allows the key to be used for a symmetric decryption operation,\n * for an AEAD decryption-and-verification operation,\n * or for an asymmetric decryption operation,\n * if otherwise permitted by the key's type and policy.\n *\n * For a key pair, this concerns the private key.\n */\n#define PSA_KEY_USAGE_DECRYPT                   ((psa_key_usage_t) 0x00000200)\n\n/** Whether the key may be used to sign a message.\n *\n * This flag allows the key to be used for a MAC calculation operation or for\n * an asymmetric message signature operation, if otherwise permitted by the\n * key’s type and policy.\n *\n * For a key pair, this concerns the private key.\n */\n#define PSA_KEY_USAGE_SIGN_MESSAGE              ((psa_key_usage_t) 0x00000400)\n\n/** Whether the key may be used to verify a message.\n *\n * This flag allows the key to be used for a MAC verification operation or for\n * an asymmetric message signature verification operation, if otherwise\n * permitted by the key’s type and policy.\n *\n * For a key pair, this concerns the public key.\n */\n#define PSA_KEY_USAGE_VERIFY_MESSAGE            ((psa_key_usage_t) 0x00000800)\n\n/** Whether the key may be used to sign a message.\n *\n * This flag allows the key to be used for a MAC calculation operation\n * or for an asymmetric signature operation,\n * if otherwise permitted by the key's type and policy.\n *\n * For a key pair, this concerns the private key.\n */\n#define PSA_KEY_USAGE_SIGN_HASH                 ((psa_key_usage_t) 0x00001000)\n\n/** Whether the key may be used to verify a message signature.\n *\n * This flag allows the key to be used for a MAC verification operation\n * or for an asymmetric signature verification operation,\n * if otherwise permitted by the key's type and policy.\n *\n * For a key pair, this concerns the public key.\n */\n#define PSA_KEY_USAGE_VERIFY_HASH               ((psa_key_usage_t) 0x00002000)\n\n/** Whether the key may be used to derive other keys or produce a password\n * hash.\n *\n * This flag allows the key to be used for a key derivation operation or for\n * a key agreement operation, if otherwise permitted by the key's type and\n * policy.\n *\n * If this flag is present on all keys used in calls to\n * psa_key_derivation_input_key() for a key derivation operation, then it\n * permits calling psa_key_derivation_output_bytes() or\n * psa_key_derivation_output_key() at the end of the operation.\n */\n#define PSA_KEY_USAGE_DERIVE                    ((psa_key_usage_t) 0x00004000)\n\n/** Whether the key may be used to verify the result of a key derivation,\n * including password hashing.\n *\n * This flag allows the key to be used:\n *\n * This flag allows the key to be used in a key derivation operation, if\n * otherwise permitted by the key's type and policy.\n *\n * If this flag is present on all keys used in calls to\n * psa_key_derivation_input_key() for a key derivation operation, then it\n * permits calling psa_key_derivation_verify_bytes() or\n * psa_key_derivation_verify_key() at the end of the operation.\n */\n#define PSA_KEY_USAGE_VERIFY_DERIVATION         ((psa_key_usage_t) 0x00008000)\n\n/**@}*/\n\n/** \\defgroup derivation Key derivation\n * @{\n */\n\n/* Key input steps are not embedded in the persistent storage, so you can\n * change them if needed: it's only an ABI change. */\n\n/** A secret input for key derivation.\n *\n * This should be a key of type #PSA_KEY_TYPE_DERIVE\n * (passed to psa_key_derivation_input_key())\n * or the shared secret resulting from a key agreement\n * (obtained via psa_key_derivation_key_agreement()).\n *\n * The secret can also be a direct input (passed to\n * key_derivation_input_bytes()). In this case, the derivation operation\n * may not be used to derive keys: the operation will only allow\n * psa_key_derivation_output_bytes(),\n * psa_key_derivation_verify_bytes(), or\n * psa_key_derivation_verify_key(), but not\n * psa_key_derivation_output_key().\n */\n#define PSA_KEY_DERIVATION_INPUT_SECRET     ((psa_key_derivation_step_t) 0x0101)\n\n/** A low-entropy secret input for password hashing / key stretching.\n *\n * This is usually a key of type #PSA_KEY_TYPE_PASSWORD (passed to\n * psa_key_derivation_input_key()) or a direct input (passed to\n * psa_key_derivation_input_bytes()) that is a password or passphrase. It can\n * also be high-entropy secret such as a key of type #PSA_KEY_TYPE_DERIVE or\n * the shared secret resulting from a key agreement.\n *\n * The secret can also be a direct input (passed to\n * key_derivation_input_bytes()). In this case, the derivation operation\n * may not be used to derive keys: the operation will only allow\n * psa_key_derivation_output_bytes(),\n * psa_key_derivation_verify_bytes(), or\n * psa_key_derivation_verify_key(), but not\n * psa_key_derivation_output_key().\n */\n#define PSA_KEY_DERIVATION_INPUT_PASSWORD   ((psa_key_derivation_step_t) 0x0102)\n\n/** A high-entropy additional secret input for key derivation.\n *\n * This is typically the shared secret resulting from a key agreement obtained\n * via `psa_key_derivation_key_agreement()`. It may alternatively be a key of\n * type `PSA_KEY_TYPE_DERIVE` passed to `psa_key_derivation_input_key()`, or\n * a direct input passed to `psa_key_derivation_input_bytes()`.\n */\n#define PSA_KEY_DERIVATION_INPUT_OTHER_SECRET \\\n    ((psa_key_derivation_step_t) 0x0103)\n\n/** A label for key derivation.\n *\n * This should be a direct input.\n * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA.\n */\n#define PSA_KEY_DERIVATION_INPUT_LABEL      ((psa_key_derivation_step_t) 0x0201)\n\n/** A salt for key derivation.\n *\n * This should be a direct input.\n * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA or\n * #PSA_KEY_TYPE_PEPPER.\n */\n#define PSA_KEY_DERIVATION_INPUT_SALT       ((psa_key_derivation_step_t) 0x0202)\n\n/** An information string for key derivation.\n *\n * This should be a direct input.\n * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA.\n */\n#define PSA_KEY_DERIVATION_INPUT_INFO       ((psa_key_derivation_step_t) 0x0203)\n\n/** A seed for key derivation.\n *\n * This should be a direct input.\n * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA.\n */\n#define PSA_KEY_DERIVATION_INPUT_SEED       ((psa_key_derivation_step_t) 0x0204)\n\n/** A cost parameter for password hashing / key stretching.\n *\n * This must be a direct input, passed to psa_key_derivation_input_integer().\n */\n#define PSA_KEY_DERIVATION_INPUT_COST       ((psa_key_derivation_step_t) 0x0205)\n\n/**@}*/\n\n/** \\defgroup helper_macros Helper macros\n * @{\n */\n\n/* Helper macros */\n\n/** Check if two AEAD algorithm identifiers refer to the same AEAD algorithm\n *  regardless of the tag length they encode.\n *\n * \\param aead_alg_1 An AEAD algorithm identifier.\n * \\param aead_alg_2 An AEAD algorithm identifier.\n *\n * \\return           1 if both identifiers refer to the same AEAD algorithm,\n *                   0 otherwise.\n *                   Unspecified if neither \\p aead_alg_1 nor \\p aead_alg_2 are\n *                   a supported AEAD algorithm.\n */\n#define MBEDTLS_PSA_ALG_AEAD_EQUAL(aead_alg_1, aead_alg_2) \\\n    (!(((aead_alg_1) ^ (aead_alg_2)) & \\\n       ~(PSA_ALG_AEAD_TAG_LENGTH_MASK | PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG)))\n\n/**@}*/\n\n/**@}*/\n\n/** \\defgroup interruptible Interruptible operations\n * @{\n */\n\n/** Maximum value for use with \\c psa_interruptible_set_max_ops() to determine\n *  the maximum number of ops allowed to be executed by an interruptible\n *  function in a single call.\n */\n#define PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED UINT32_MAX\n\n/**@}*/\n\n#endif /* PSA_CRYPTO_VALUES_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/aes.c",
    "content": "/*\n *  FIPS-197 compliant AES implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  The AES block cipher was designed by Vincent Rijmen and Joan Daemen.\n *\n *  https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/aes-development/rijndael-ammended.pdf\n *  http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_AES_C)\n\n#include <string.h>\n\n#include \"mbedtls/aes.h\"\n#include \"mbedtls/platform.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY)\n#if !((defined(MBEDTLS_ARCH_IS_ARMV8_A) && defined(MBEDTLS_AESCE_C)) || \\\n    (defined(MBEDTLS_ARCH_IS_X64)       && defined(MBEDTLS_AESNI_C)) || \\\n    (defined(MBEDTLS_ARCH_IS_X86)       && defined(MBEDTLS_AESNI_C)))\n#error \"MBEDTLS_AES_USE_HARDWARE_ONLY defined, but not all prerequisites\"\n#endif\n#endif\n\n#if defined(MBEDTLS_ARCH_IS_X86)\n#if defined(MBEDTLS_PADLOCK_C)\n#if !defined(MBEDTLS_HAVE_ASM)\n#error \"MBEDTLS_PADLOCK_C defined, but not all prerequisites\"\n#endif\n#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY)\n#error \"MBEDTLS_AES_USE_HARDWARE_ONLY cannot be defined when \" \\\n    \"MBEDTLS_PADLOCK_C is set\"\n#endif\n#endif\n#endif\n\n#if defined(MBEDTLS_PADLOCK_C)\n#include \"padlock.h\"\n#endif\n#if defined(MBEDTLS_AESNI_C)\n#include \"aesni.h\"\n#endif\n#if defined(MBEDTLS_AESCE_C)\n#include \"aesce.h\"\n#endif\n\n#include \"mbedtls/platform.h\"\n#include \"ctr.h\"\n\n/*\n * This is a convenience shorthand macro to check if we need reverse S-box and\n * reverse tables. It's private and only defined in this file.\n */\n#if (!defined(MBEDTLS_AES_DECRYPT_ALT) || \\\n    (!defined(MBEDTLS_AES_SETKEY_DEC_ALT) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY))) && \\\n    !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n#define MBEDTLS_AES_NEED_REVERSE_TABLES\n#endif\n\n#if !defined(MBEDTLS_AES_ALT)\n\n#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)\nstatic int aes_padlock_ace = -1;\n#endif\n\n#if defined(MBEDTLS_AES_ROM_TABLES)\n/*\n * Forward S-box\n */\nMBEDTLS_MAYBE_UNUSED static const unsigned char FSb[256] =\n{\n    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,\n    0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,\n    0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,\n    0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,\n    0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,\n    0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,\n    0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,\n    0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,\n    0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,\n    0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,\n    0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,\n    0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,\n    0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,\n    0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,\n    0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,\n    0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,\n    0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,\n    0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,\n    0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,\n    0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,\n    0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,\n    0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,\n    0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,\n    0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,\n    0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,\n    0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,\n    0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,\n    0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,\n    0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,\n    0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,\n    0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,\n    0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16\n};\n\n/*\n * Forward tables\n */\n#define FT \\\n\\\n    V(A5, 63, 63, C6), V(84, 7C, 7C, F8), V(99, 77, 77, EE), V(8D, 7B, 7B, F6), \\\n    V(0D, F2, F2, FF), V(BD, 6B, 6B, D6), V(B1, 6F, 6F, DE), V(54, C5, C5, 91), \\\n    V(50, 30, 30, 60), V(03, 01, 01, 02), V(A9, 67, 67, CE), V(7D, 2B, 2B, 56), \\\n    V(19, FE, FE, E7), V(62, D7, D7, B5), V(E6, AB, AB, 4D), V(9A, 76, 76, EC), \\\n    V(45, CA, CA, 8F), V(9D, 82, 82, 1F), V(40, C9, C9, 89), V(87, 7D, 7D, FA), \\\n    V(15, FA, FA, EF), V(EB, 59, 59, B2), V(C9, 47, 47, 8E), V(0B, F0, F0, FB), \\\n    V(EC, AD, AD, 41), V(67, D4, D4, B3), V(FD, A2, A2, 5F), V(EA, AF, AF, 45), \\\n    V(BF, 9C, 9C, 23), V(F7, A4, A4, 53), V(96, 72, 72, E4), V(5B, C0, C0, 9B), \\\n    V(C2, B7, B7, 75), V(1C, FD, FD, E1), V(AE, 93, 93, 3D), V(6A, 26, 26, 4C), \\\n    V(5A, 36, 36, 6C), V(41, 3F, 3F, 7E), V(02, F7, F7, F5), V(4F, CC, CC, 83), \\\n    V(5C, 34, 34, 68), V(F4, A5, A5, 51), V(34, E5, E5, D1), V(08, F1, F1, F9), \\\n    V(93, 71, 71, E2), V(73, D8, D8, AB), V(53, 31, 31, 62), V(3F, 15, 15, 2A), \\\n    V(0C, 04, 04, 08), V(52, C7, C7, 95), V(65, 23, 23, 46), V(5E, C3, C3, 9D), \\\n    V(28, 18, 18, 30), V(A1, 96, 96, 37), V(0F, 05, 05, 0A), V(B5, 9A, 9A, 2F), \\\n    V(09, 07, 07, 0E), V(36, 12, 12, 24), V(9B, 80, 80, 1B), V(3D, E2, E2, DF), \\\n    V(26, EB, EB, CD), V(69, 27, 27, 4E), V(CD, B2, B2, 7F), V(9F, 75, 75, EA), \\\n    V(1B, 09, 09, 12), V(9E, 83, 83, 1D), V(74, 2C, 2C, 58), V(2E, 1A, 1A, 34), \\\n    V(2D, 1B, 1B, 36), V(B2, 6E, 6E, DC), V(EE, 5A, 5A, B4), V(FB, A0, A0, 5B), \\\n    V(F6, 52, 52, A4), V(4D, 3B, 3B, 76), V(61, D6, D6, B7), V(CE, B3, B3, 7D), \\\n    V(7B, 29, 29, 52), V(3E, E3, E3, DD), V(71, 2F, 2F, 5E), V(97, 84, 84, 13), \\\n    V(F5, 53, 53, A6), V(68, D1, D1, B9), V(00, 00, 00, 00), V(2C, ED, ED, C1), \\\n    V(60, 20, 20, 40), V(1F, FC, FC, E3), V(C8, B1, B1, 79), V(ED, 5B, 5B, B6), \\\n    V(BE, 6A, 6A, D4), V(46, CB, CB, 8D), V(D9, BE, BE, 67), V(4B, 39, 39, 72), \\\n    V(DE, 4A, 4A, 94), V(D4, 4C, 4C, 98), V(E8, 58, 58, B0), V(4A, CF, CF, 85), \\\n    V(6B, D0, D0, BB), V(2A, EF, EF, C5), V(E5, AA, AA, 4F), V(16, FB, FB, ED), \\\n    V(C5, 43, 43, 86), V(D7, 4D, 4D, 9A), V(55, 33, 33, 66), V(94, 85, 85, 11), \\\n    V(CF, 45, 45, 8A), V(10, F9, F9, E9), V(06, 02, 02, 04), V(81, 7F, 7F, FE), \\\n    V(F0, 50, 50, A0), V(44, 3C, 3C, 78), V(BA, 9F, 9F, 25), V(E3, A8, A8, 4B), \\\n    V(F3, 51, 51, A2), V(FE, A3, A3, 5D), V(C0, 40, 40, 80), V(8A, 8F, 8F, 05), \\\n    V(AD, 92, 92, 3F), V(BC, 9D, 9D, 21), V(48, 38, 38, 70), V(04, F5, F5, F1), \\\n    V(DF, BC, BC, 63), V(C1, B6, B6, 77), V(75, DA, DA, AF), V(63, 21, 21, 42), \\\n    V(30, 10, 10, 20), V(1A, FF, FF, E5), V(0E, F3, F3, FD), V(6D, D2, D2, BF), \\\n    V(4C, CD, CD, 81), V(14, 0C, 0C, 18), V(35, 13, 13, 26), V(2F, EC, EC, C3), \\\n    V(E1, 5F, 5F, BE), V(A2, 97, 97, 35), V(CC, 44, 44, 88), V(39, 17, 17, 2E), \\\n    V(57, C4, C4, 93), V(F2, A7, A7, 55), V(82, 7E, 7E, FC), V(47, 3D, 3D, 7A), \\\n    V(AC, 64, 64, C8), V(E7, 5D, 5D, BA), V(2B, 19, 19, 32), V(95, 73, 73, E6), \\\n    V(A0, 60, 60, C0), V(98, 81, 81, 19), V(D1, 4F, 4F, 9E), V(7F, DC, DC, A3), \\\n    V(66, 22, 22, 44), V(7E, 2A, 2A, 54), V(AB, 90, 90, 3B), V(83, 88, 88, 0B), \\\n    V(CA, 46, 46, 8C), V(29, EE, EE, C7), V(D3, B8, B8, 6B), V(3C, 14, 14, 28), \\\n    V(79, DE, DE, A7), V(E2, 5E, 5E, BC), V(1D, 0B, 0B, 16), V(76, DB, DB, AD), \\\n    V(3B, E0, E0, DB), V(56, 32, 32, 64), V(4E, 3A, 3A, 74), V(1E, 0A, 0A, 14), \\\n    V(DB, 49, 49, 92), V(0A, 06, 06, 0C), V(6C, 24, 24, 48), V(E4, 5C, 5C, B8), \\\n    V(5D, C2, C2, 9F), V(6E, D3, D3, BD), V(EF, AC, AC, 43), V(A6, 62, 62, C4), \\\n    V(A8, 91, 91, 39), V(A4, 95, 95, 31), V(37, E4, E4, D3), V(8B, 79, 79, F2), \\\n    V(32, E7, E7, D5), V(43, C8, C8, 8B), V(59, 37, 37, 6E), V(B7, 6D, 6D, DA), \\\n    V(8C, 8D, 8D, 01), V(64, D5, D5, B1), V(D2, 4E, 4E, 9C), V(E0, A9, A9, 49), \\\n    V(B4, 6C, 6C, D8), V(FA, 56, 56, AC), V(07, F4, F4, F3), V(25, EA, EA, CF), \\\n    V(AF, 65, 65, CA), V(8E, 7A, 7A, F4), V(E9, AE, AE, 47), V(18, 08, 08, 10), \\\n    V(D5, BA, BA, 6F), V(88, 78, 78, F0), V(6F, 25, 25, 4A), V(72, 2E, 2E, 5C), \\\n    V(24, 1C, 1C, 38), V(F1, A6, A6, 57), V(C7, B4, B4, 73), V(51, C6, C6, 97), \\\n    V(23, E8, E8, CB), V(7C, DD, DD, A1), V(9C, 74, 74, E8), V(21, 1F, 1F, 3E), \\\n    V(DD, 4B, 4B, 96), V(DC, BD, BD, 61), V(86, 8B, 8B, 0D), V(85, 8A, 8A, 0F), \\\n    V(90, 70, 70, E0), V(42, 3E, 3E, 7C), V(C4, B5, B5, 71), V(AA, 66, 66, CC), \\\n    V(D8, 48, 48, 90), V(05, 03, 03, 06), V(01, F6, F6, F7), V(12, 0E, 0E, 1C), \\\n    V(A3, 61, 61, C2), V(5F, 35, 35, 6A), V(F9, 57, 57, AE), V(D0, B9, B9, 69), \\\n    V(91, 86, 86, 17), V(58, C1, C1, 99), V(27, 1D, 1D, 3A), V(B9, 9E, 9E, 27), \\\n    V(38, E1, E1, D9), V(13, F8, F8, EB), V(B3, 98, 98, 2B), V(33, 11, 11, 22), \\\n    V(BB, 69, 69, D2), V(70, D9, D9, A9), V(89, 8E, 8E, 07), V(A7, 94, 94, 33), \\\n    V(B6, 9B, 9B, 2D), V(22, 1E, 1E, 3C), V(92, 87, 87, 15), V(20, E9, E9, C9), \\\n    V(49, CE, CE, 87), V(FF, 55, 55, AA), V(78, 28, 28, 50), V(7A, DF, DF, A5), \\\n    V(8F, 8C, 8C, 03), V(F8, A1, A1, 59), V(80, 89, 89, 09), V(17, 0D, 0D, 1A), \\\n    V(DA, BF, BF, 65), V(31, E6, E6, D7), V(C6, 42, 42, 84), V(B8, 68, 68, D0), \\\n    V(C3, 41, 41, 82), V(B0, 99, 99, 29), V(77, 2D, 2D, 5A), V(11, 0F, 0F, 1E), \\\n    V(CB, B0, B0, 7B), V(FC, 54, 54, A8), V(D6, BB, BB, 6D), V(3A, 16, 16, 2C)\n\n#define V(a, b, c, d) 0x##a##b##c##d\nMBEDTLS_MAYBE_UNUSED static const uint32_t FT0[256] = { FT };\n#undef V\n\n#define V(a, b, c, d) 0x##b##c##d##a\nMBEDTLS_MAYBE_UNUSED static const uint32_t FT1[256] = { FT };\n#undef V\n\n#define V(a, b, c, d) 0x##c##d##a##b\nMBEDTLS_MAYBE_UNUSED static const uint32_t FT2[256] = { FT };\n#undef V\n\n#define V(a, b, c, d) 0x##d##a##b##c\nMBEDTLS_MAYBE_UNUSED static const uint32_t FT3[256] = { FT };\n#undef V\n\n#undef FT\n\n/*\n * Reverse S-box\n */\nMBEDTLS_MAYBE_UNUSED static const unsigned char RSb[256] =\n{\n    0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,\n    0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,\n    0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,\n    0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,\n    0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,\n    0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,\n    0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,\n    0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,\n    0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,\n    0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,\n    0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,\n    0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,\n    0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,\n    0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,\n    0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,\n    0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,\n    0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,\n    0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,\n    0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,\n    0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,\n    0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,\n    0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,\n    0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,\n    0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,\n    0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,\n    0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,\n    0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,\n    0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,\n    0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,\n    0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,\n    0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,\n    0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D\n};\n\n/*\n * Reverse tables\n */\n#define RT \\\n\\\n    V(50, A7, F4, 51), V(53, 65, 41, 7E), V(C3, A4, 17, 1A), V(96, 5E, 27, 3A), \\\n    V(CB, 6B, AB, 3B), V(F1, 45, 9D, 1F), V(AB, 58, FA, AC), V(93, 03, E3, 4B), \\\n    V(55, FA, 30, 20), V(F6, 6D, 76, AD), V(91, 76, CC, 88), V(25, 4C, 02, F5), \\\n    V(FC, D7, E5, 4F), V(D7, CB, 2A, C5), V(80, 44, 35, 26), V(8F, A3, 62, B5), \\\n    V(49, 5A, B1, DE), V(67, 1B, BA, 25), V(98, 0E, EA, 45), V(E1, C0, FE, 5D), \\\n    V(02, 75, 2F, C3), V(12, F0, 4C, 81), V(A3, 97, 46, 8D), V(C6, F9, D3, 6B), \\\n    V(E7, 5F, 8F, 03), V(95, 9C, 92, 15), V(EB, 7A, 6D, BF), V(DA, 59, 52, 95), \\\n    V(2D, 83, BE, D4), V(D3, 21, 74, 58), V(29, 69, E0, 49), V(44, C8, C9, 8E), \\\n    V(6A, 89, C2, 75), V(78, 79, 8E, F4), V(6B, 3E, 58, 99), V(DD, 71, B9, 27), \\\n    V(B6, 4F, E1, BE), V(17, AD, 88, F0), V(66, AC, 20, C9), V(B4, 3A, CE, 7D), \\\n    V(18, 4A, DF, 63), V(82, 31, 1A, E5), V(60, 33, 51, 97), V(45, 7F, 53, 62), \\\n    V(E0, 77, 64, B1), V(84, AE, 6B, BB), V(1C, A0, 81, FE), V(94, 2B, 08, F9), \\\n    V(58, 68, 48, 70), V(19, FD, 45, 8F), V(87, 6C, DE, 94), V(B7, F8, 7B, 52), \\\n    V(23, D3, 73, AB), V(E2, 02, 4B, 72), V(57, 8F, 1F, E3), V(2A, AB, 55, 66), \\\n    V(07, 28, EB, B2), V(03, C2, B5, 2F), V(9A, 7B, C5, 86), V(A5, 08, 37, D3), \\\n    V(F2, 87, 28, 30), V(B2, A5, BF, 23), V(BA, 6A, 03, 02), V(5C, 82, 16, ED), \\\n    V(2B, 1C, CF, 8A), V(92, B4, 79, A7), V(F0, F2, 07, F3), V(A1, E2, 69, 4E), \\\n    V(CD, F4, DA, 65), V(D5, BE, 05, 06), V(1F, 62, 34, D1), V(8A, FE, A6, C4), \\\n    V(9D, 53, 2E, 34), V(A0, 55, F3, A2), V(32, E1, 8A, 05), V(75, EB, F6, A4), \\\n    V(39, EC, 83, 0B), V(AA, EF, 60, 40), V(06, 9F, 71, 5E), V(51, 10, 6E, BD), \\\n    V(F9, 8A, 21, 3E), V(3D, 06, DD, 96), V(AE, 05, 3E, DD), V(46, BD, E6, 4D), \\\n    V(B5, 8D, 54, 91), V(05, 5D, C4, 71), V(6F, D4, 06, 04), V(FF, 15, 50, 60), \\\n    V(24, FB, 98, 19), V(97, E9, BD, D6), V(CC, 43, 40, 89), V(77, 9E, D9, 67), \\\n    V(BD, 42, E8, B0), V(88, 8B, 89, 07), V(38, 5B, 19, E7), V(DB, EE, C8, 79), \\\n    V(47, 0A, 7C, A1), V(E9, 0F, 42, 7C), V(C9, 1E, 84, F8), V(00, 00, 00, 00), \\\n    V(83, 86, 80, 09), V(48, ED, 2B, 32), V(AC, 70, 11, 1E), V(4E, 72, 5A, 6C), \\\n    V(FB, FF, 0E, FD), V(56, 38, 85, 0F), V(1E, D5, AE, 3D), V(27, 39, 2D, 36), \\\n    V(64, D9, 0F, 0A), V(21, A6, 5C, 68), V(D1, 54, 5B, 9B), V(3A, 2E, 36, 24), \\\n    V(B1, 67, 0A, 0C), V(0F, E7, 57, 93), V(D2, 96, EE, B4), V(9E, 91, 9B, 1B), \\\n    V(4F, C5, C0, 80), V(A2, 20, DC, 61), V(69, 4B, 77, 5A), V(16, 1A, 12, 1C), \\\n    V(0A, BA, 93, E2), V(E5, 2A, A0, C0), V(43, E0, 22, 3C), V(1D, 17, 1B, 12), \\\n    V(0B, 0D, 09, 0E), V(AD, C7, 8B, F2), V(B9, A8, B6, 2D), V(C8, A9, 1E, 14), \\\n    V(85, 19, F1, 57), V(4C, 07, 75, AF), V(BB, DD, 99, EE), V(FD, 60, 7F, A3), \\\n    V(9F, 26, 01, F7), V(BC, F5, 72, 5C), V(C5, 3B, 66, 44), V(34, 7E, FB, 5B), \\\n    V(76, 29, 43, 8B), V(DC, C6, 23, CB), V(68, FC, ED, B6), V(63, F1, E4, B8), \\\n    V(CA, DC, 31, D7), V(10, 85, 63, 42), V(40, 22, 97, 13), V(20, 11, C6, 84), \\\n    V(7D, 24, 4A, 85), V(F8, 3D, BB, D2), V(11, 32, F9, AE), V(6D, A1, 29, C7), \\\n    V(4B, 2F, 9E, 1D), V(F3, 30, B2, DC), V(EC, 52, 86, 0D), V(D0, E3, C1, 77), \\\n    V(6C, 16, B3, 2B), V(99, B9, 70, A9), V(FA, 48, 94, 11), V(22, 64, E9, 47), \\\n    V(C4, 8C, FC, A8), V(1A, 3F, F0, A0), V(D8, 2C, 7D, 56), V(EF, 90, 33, 22), \\\n    V(C7, 4E, 49, 87), V(C1, D1, 38, D9), V(FE, A2, CA, 8C), V(36, 0B, D4, 98), \\\n    V(CF, 81, F5, A6), V(28, DE, 7A, A5), V(26, 8E, B7, DA), V(A4, BF, AD, 3F), \\\n    V(E4, 9D, 3A, 2C), V(0D, 92, 78, 50), V(9B, CC, 5F, 6A), V(62, 46, 7E, 54), \\\n    V(C2, 13, 8D, F6), V(E8, B8, D8, 90), V(5E, F7, 39, 2E), V(F5, AF, C3, 82), \\\n    V(BE, 80, 5D, 9F), V(7C, 93, D0, 69), V(A9, 2D, D5, 6F), V(B3, 12, 25, CF), \\\n    V(3B, 99, AC, C8), V(A7, 7D, 18, 10), V(6E, 63, 9C, E8), V(7B, BB, 3B, DB), \\\n    V(09, 78, 26, CD), V(F4, 18, 59, 6E), V(01, B7, 9A, EC), V(A8, 9A, 4F, 83), \\\n    V(65, 6E, 95, E6), V(7E, E6, FF, AA), V(08, CF, BC, 21), V(E6, E8, 15, EF), \\\n    V(D9, 9B, E7, BA), V(CE, 36, 6F, 4A), V(D4, 09, 9F, EA), V(D6, 7C, B0, 29), \\\n    V(AF, B2, A4, 31), V(31, 23, 3F, 2A), V(30, 94, A5, C6), V(C0, 66, A2, 35), \\\n    V(37, BC, 4E, 74), V(A6, CA, 82, FC), V(B0, D0, 90, E0), V(15, D8, A7, 33), \\\n    V(4A, 98, 04, F1), V(F7, DA, EC, 41), V(0E, 50, CD, 7F), V(2F, F6, 91, 17), \\\n    V(8D, D6, 4D, 76), V(4D, B0, EF, 43), V(54, 4D, AA, CC), V(DF, 04, 96, E4), \\\n    V(E3, B5, D1, 9E), V(1B, 88, 6A, 4C), V(B8, 1F, 2C, C1), V(7F, 51, 65, 46), \\\n    V(04, EA, 5E, 9D), V(5D, 35, 8C, 01), V(73, 74, 87, FA), V(2E, 41, 0B, FB), \\\n    V(5A, 1D, 67, B3), V(52, D2, DB, 92), V(33, 56, 10, E9), V(13, 47, D6, 6D), \\\n    V(8C, 61, D7, 9A), V(7A, 0C, A1, 37), V(8E, 14, F8, 59), V(89, 3C, 13, EB), \\\n    V(EE, 27, A9, CE), V(35, C9, 61, B7), V(ED, E5, 1C, E1), V(3C, B1, 47, 7A), \\\n    V(59, DF, D2, 9C), V(3F, 73, F2, 55), V(79, CE, 14, 18), V(BF, 37, C7, 73), \\\n    V(EA, CD, F7, 53), V(5B, AA, FD, 5F), V(14, 6F, 3D, DF), V(86, DB, 44, 78), \\\n    V(81, F3, AF, CA), V(3E, C4, 68, B9), V(2C, 34, 24, 38), V(5F, 40, A3, C2), \\\n    V(72, C3, 1D, 16), V(0C, 25, E2, BC), V(8B, 49, 3C, 28), V(41, 95, 0D, FF), \\\n    V(71, 01, A8, 39), V(DE, B3, 0C, 08), V(9C, E4, B4, D8), V(90, C1, 56, 64), \\\n    V(61, 84, CB, 7B), V(70, B6, 32, D5), V(74, 5C, 6C, 48), V(42, 57, B8, D0)\n\n\n#define V(a, b, c, d) 0x##a##b##c##d\nMBEDTLS_MAYBE_UNUSED static const uint32_t RT0[256] = { RT };\n#undef V\n\n#define V(a, b, c, d) 0x##b##c##d##a\nMBEDTLS_MAYBE_UNUSED static const uint32_t RT1[256] = { RT };\n#undef V\n\n#define V(a, b, c, d) 0x##c##d##a##b\nMBEDTLS_MAYBE_UNUSED static const uint32_t RT2[256] = { RT };\n#undef V\n\n#define V(a, b, c, d) 0x##d##a##b##c\nMBEDTLS_MAYBE_UNUSED static const uint32_t RT3[256] = { RT };\n#undef V\n\n#undef RT\n\n/*\n * Round constants\n */\nMBEDTLS_MAYBE_UNUSED static const uint32_t round_constants[10] =\n{\n    0x00000001, 0x00000002, 0x00000004, 0x00000008,\n    0x00000010, 0x00000020, 0x00000040, 0x00000080,\n    0x0000001B, 0x00000036\n};\n\n#else /* MBEDTLS_AES_ROM_TABLES */\n\n/*\n * Forward S-box & tables\n */\nMBEDTLS_MAYBE_UNUSED static unsigned char FSb[256];\nMBEDTLS_MAYBE_UNUSED static uint32_t FT0[256];\nMBEDTLS_MAYBE_UNUSED static uint32_t FT1[256];\nMBEDTLS_MAYBE_UNUSED static uint32_t FT2[256];\nMBEDTLS_MAYBE_UNUSED static uint32_t FT3[256];\n\n/*\n * Reverse S-box & tables\n */\nMBEDTLS_MAYBE_UNUSED static unsigned char RSb[256];\n\nMBEDTLS_MAYBE_UNUSED static uint32_t RT0[256];\nMBEDTLS_MAYBE_UNUSED static uint32_t RT1[256];\nMBEDTLS_MAYBE_UNUSED static uint32_t RT2[256];\nMBEDTLS_MAYBE_UNUSED static uint32_t RT3[256];\n\n/*\n * Round constants\n */\nMBEDTLS_MAYBE_UNUSED static uint32_t round_constants[10];\n\n/*\n * Tables generation code\n */\n#define ROTL8(x) (((x) << 8) & 0xFFFFFFFF) | ((x) >> 24)\n#define XTIME(x) (((x) << 1) ^ (((x) & 0x80) ? 0x1B : 0x00))\n#define MUL(x, y) (((x) && (y)) ? pow[(log[(x)]+log[(y)]) % 255] : 0)\n\nMBEDTLS_MAYBE_UNUSED static int aes_init_done = 0;\n\nMBEDTLS_MAYBE_UNUSED static void aes_gen_tables(void)\n{\n    int i;\n    uint8_t x, y, z;\n    uint8_t pow[256];\n    uint8_t log[256];\n\n    /*\n     * compute pow and log tables over GF(2^8)\n     */\n    for (i = 0, x = 1; i < 256; i++) {\n        pow[i] = x;\n        log[x] = (uint8_t) i;\n        x ^= XTIME(x);\n    }\n\n    /*\n     * calculate the round constants\n     */\n    for (i = 0, x = 1; i < 10; i++) {\n        round_constants[i] = x;\n        x = XTIME(x);\n    }\n\n    /*\n     * generate the forward and reverse S-boxes\n     */\n    FSb[0x00] = 0x63;\n#if defined(MBEDTLS_AES_NEED_REVERSE_TABLES)\n    RSb[0x63] = 0x00;\n#endif\n\n    for (i = 1; i < 256; i++) {\n        x = pow[255 - log[i]];\n\n        y  = x; y = (y << 1) | (y >> 7);\n        x ^= y; y = (y << 1) | (y >> 7);\n        x ^= y; y = (y << 1) | (y >> 7);\n        x ^= y; y = (y << 1) | (y >> 7);\n        x ^= y ^ 0x63;\n\n        FSb[i] = x;\n#if defined(MBEDTLS_AES_NEED_REVERSE_TABLES)\n        RSb[x] = (unsigned char) i;\n#endif\n    }\n\n    /*\n     * generate the forward and reverse tables\n     */\n    for (i = 0; i < 256; i++) {\n        x = FSb[i];\n        y = XTIME(x);\n        z = y ^ x;\n\n        FT0[i] = ((uint32_t) y) ^\n                 ((uint32_t) x <<  8) ^\n                 ((uint32_t) x << 16) ^\n                 ((uint32_t) z << 24);\n\n#if !defined(MBEDTLS_AES_FEWER_TABLES)\n        FT1[i] = ROTL8(FT0[i]);\n        FT2[i] = ROTL8(FT1[i]);\n        FT3[i] = ROTL8(FT2[i]);\n#endif /* !MBEDTLS_AES_FEWER_TABLES */\n\n#if defined(MBEDTLS_AES_NEED_REVERSE_TABLES)\n        x = RSb[i];\n\n        RT0[i] = ((uint32_t) MUL(0x0E, x)) ^\n                 ((uint32_t) MUL(0x09, x) <<  8) ^\n                 ((uint32_t) MUL(0x0D, x) << 16) ^\n                 ((uint32_t) MUL(0x0B, x) << 24);\n\n#if !defined(MBEDTLS_AES_FEWER_TABLES)\n        RT1[i] = ROTL8(RT0[i]);\n        RT2[i] = ROTL8(RT1[i]);\n        RT3[i] = ROTL8(RT2[i]);\n#endif /* !MBEDTLS_AES_FEWER_TABLES */\n#endif /* MBEDTLS_AES_NEED_REVERSE_TABLES */\n    }\n}\n\n#undef ROTL8\n\n#endif /* MBEDTLS_AES_ROM_TABLES */\n\n#if defined(MBEDTLS_AES_FEWER_TABLES)\n\n#define ROTL8(x)  ((uint32_t) ((x) <<  8) + (uint32_t) ((x) >> 24))\n#define ROTL16(x) ((uint32_t) ((x) << 16) + (uint32_t) ((x) >> 16))\n#define ROTL24(x) ((uint32_t) ((x) << 24) + (uint32_t) ((x) >>  8))\n\n#define AES_RT0(idx) RT0[idx]\n#define AES_RT1(idx) ROTL8(RT0[idx])\n#define AES_RT2(idx) ROTL16(RT0[idx])\n#define AES_RT3(idx) ROTL24(RT0[idx])\n\n#define AES_FT0(idx) FT0[idx]\n#define AES_FT1(idx) ROTL8(FT0[idx])\n#define AES_FT2(idx) ROTL16(FT0[idx])\n#define AES_FT3(idx) ROTL24(FT0[idx])\n\n#else /* MBEDTLS_AES_FEWER_TABLES */\n\n#define AES_RT0(idx) RT0[idx]\n#define AES_RT1(idx) RT1[idx]\n#define AES_RT2(idx) RT2[idx]\n#define AES_RT3(idx) RT3[idx]\n\n#define AES_FT0(idx) FT0[idx]\n#define AES_FT1(idx) FT1[idx]\n#define AES_FT2(idx) FT2[idx]\n#define AES_FT3(idx) FT3[idx]\n\n#endif /* MBEDTLS_AES_FEWER_TABLES */\n\nvoid mbedtls_aes_init(mbedtls_aes_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_aes_context));\n}\n\nvoid mbedtls_aes_free(mbedtls_aes_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_aes_context));\n}\n\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\nvoid mbedtls_aes_xts_init(mbedtls_aes_xts_context *ctx)\n{\n    mbedtls_aes_init(&ctx->crypt);\n    mbedtls_aes_init(&ctx->tweak);\n}\n\nvoid mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_aes_free(&ctx->crypt);\n    mbedtls_aes_free(&ctx->tweak);\n}\n#endif /* MBEDTLS_CIPHER_MODE_XTS */\n\n/* Some implementations need the round keys to be aligned.\n * Return an offset to be added to buf, such that (buf + offset) is\n * correctly aligned.\n * Note that the offset is in units of elements of buf, i.e. 32-bit words,\n * i.e. an offset of 1 means 4 bytes and so on.\n */\n#if (defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)) ||        \\\n    (defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2)\n#define MAY_NEED_TO_ALIGN\n#endif\n\nMBEDTLS_MAYBE_UNUSED static unsigned mbedtls_aes_rk_offset(uint32_t *buf)\n{\n#if defined(MAY_NEED_TO_ALIGN)\n    int align_16_bytes = 0;\n\n#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)\n    if (aes_padlock_ace == -1) {\n        aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE);\n    }\n    if (aes_padlock_ace) {\n        align_16_bytes = 1;\n    }\n#endif\n\n#if defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2\n    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {\n        align_16_bytes = 1;\n    }\n#endif\n\n    if (align_16_bytes) {\n        /* These implementations needs 16-byte alignment\n         * for the round key array. */\n        unsigned delta = ((uintptr_t) buf & 0x0000000fU) / 4;\n        if (delta == 0) {\n            return 0;\n        } else {\n            return 4 - delta; // 16 bytes = 4 uint32_t\n        }\n    }\n#else /* MAY_NEED_TO_ALIGN */\n    (void) buf;\n#endif /* MAY_NEED_TO_ALIGN */\n\n    return 0;\n}\n\n/*\n * AES key schedule (encryption)\n */\n#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT)\nint mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,\n                           unsigned int keybits)\n{\n    uint32_t *RK;\n\n    switch (keybits) {\n        case 128: ctx->nr = 10; break;\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n        case 192: ctx->nr = 12; break;\n        case 256: ctx->nr = 14; break;\n#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */\n        default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;\n    }\n\n#if !defined(MBEDTLS_AES_ROM_TABLES)\n    if (aes_init_done == 0) {\n        aes_gen_tables();\n        aes_init_done = 1;\n    }\n#endif\n\n    ctx->rk_offset = mbedtls_aes_rk_offset(ctx->buf);\n    RK = ctx->buf + ctx->rk_offset;\n\n#if defined(MBEDTLS_AESNI_HAVE_CODE)\n    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {\n        return mbedtls_aesni_setkey_enc((unsigned char *) RK, key, keybits);\n    }\n#endif\n\n#if defined(MBEDTLS_AESCE_HAVE_CODE)\n    if (MBEDTLS_AESCE_HAS_SUPPORT()) {\n        return mbedtls_aesce_setkey_enc((unsigned char *) RK, key, keybits);\n    }\n#endif\n\n#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)\n    for (unsigned int i = 0; i < (keybits >> 5); i++) {\n        RK[i] = MBEDTLS_GET_UINT32_LE(key, i << 2);\n    }\n\n    switch (ctx->nr) {\n        case 10:\n\n            for (unsigned int i = 0; i < 10; i++, RK += 4) {\n                RK[4]  = RK[0] ^ round_constants[i] ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[3])]) ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[3])] <<  8) ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[3])] << 16) ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[3])] << 24);\n\n                RK[5]  = RK[1] ^ RK[4];\n                RK[6]  = RK[2] ^ RK[5];\n                RK[7]  = RK[3] ^ RK[6];\n            }\n            break;\n\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n        case 12:\n\n            for (unsigned int i = 0; i < 8; i++, RK += 6) {\n                RK[6]  = RK[0] ^ round_constants[i] ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[5])]) ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[5])] <<  8) ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[5])] << 16) ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[5])] << 24);\n\n                RK[7]  = RK[1] ^ RK[6];\n                RK[8]  = RK[2] ^ RK[7];\n                RK[9]  = RK[3] ^ RK[8];\n                RK[10] = RK[4] ^ RK[9];\n                RK[11] = RK[5] ^ RK[10];\n            }\n            break;\n\n        case 14:\n\n            for (unsigned int i = 0; i < 7; i++, RK += 8) {\n                RK[8]  = RK[0] ^ round_constants[i] ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[7])]) ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[7])] <<  8) ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[7])] << 16) ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[7])] << 24);\n\n                RK[9]  = RK[1] ^ RK[8];\n                RK[10] = RK[2] ^ RK[9];\n                RK[11] = RK[3] ^ RK[10];\n\n                RK[12] = RK[4] ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[11])]) ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[11])] <<  8) ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[11])] << 16) ^\n                         ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[11])] << 24);\n\n                RK[13] = RK[5] ^ RK[12];\n                RK[14] = RK[6] ^ RK[13];\n                RK[15] = RK[7] ^ RK[14];\n            }\n            break;\n#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */\n    }\n\n    return 0;\n#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */\n}\n#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */\n\n/*\n * AES key schedule (decryption)\n */\n#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) && !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\nint mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,\n                           unsigned int keybits)\n{\n#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)\n    uint32_t *SK;\n#endif\n    int ret;\n    mbedtls_aes_context cty;\n    uint32_t *RK;\n\n\n    mbedtls_aes_init(&cty);\n\n    ctx->rk_offset = mbedtls_aes_rk_offset(ctx->buf);\n    RK = ctx->buf + ctx->rk_offset;\n\n    /* Also checks keybits */\n    if ((ret = mbedtls_aes_setkey_enc(&cty, key, keybits)) != 0) {\n        goto exit;\n    }\n\n    ctx->nr = cty.nr;\n\n#if defined(MBEDTLS_AESNI_HAVE_CODE)\n    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {\n        mbedtls_aesni_inverse_key((unsigned char *) RK,\n                                  (const unsigned char *) (cty.buf + cty.rk_offset), ctx->nr);\n        goto exit;\n    }\n#endif\n\n#if defined(MBEDTLS_AESCE_HAVE_CODE)\n    if (MBEDTLS_AESCE_HAS_SUPPORT()) {\n        mbedtls_aesce_inverse_key(\n            (unsigned char *) RK,\n            (const unsigned char *) (cty.buf + cty.rk_offset),\n            ctx->nr);\n        goto exit;\n    }\n#endif\n\n#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)\n    SK = cty.buf + cty.rk_offset + cty.nr * 4;\n\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n    SK -= 8;\n    for (int i = ctx->nr - 1; i > 0; i--, SK -= 8) {\n        for (int j = 0; j < 4; j++, SK++) {\n            *RK++ = AES_RT0(FSb[MBEDTLS_BYTE_0(*SK)]) ^\n                    AES_RT1(FSb[MBEDTLS_BYTE_1(*SK)]) ^\n                    AES_RT2(FSb[MBEDTLS_BYTE_2(*SK)]) ^\n                    AES_RT3(FSb[MBEDTLS_BYTE_3(*SK)]);\n        }\n    }\n\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */\nexit:\n    mbedtls_aes_free(&cty);\n\n    return ret;\n}\n#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT && !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */\n\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\nstatic int mbedtls_aes_xts_decode_keys(const unsigned char *key,\n                                       unsigned int keybits,\n                                       const unsigned char **key1,\n                                       unsigned int *key1bits,\n                                       const unsigned char **key2,\n                                       unsigned int *key2bits)\n{\n    const unsigned int half_keybits = keybits / 2;\n    const unsigned int half_keybytes = half_keybits / 8;\n\n    switch (keybits) {\n        case 256: break;\n        case 512: break;\n        default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;\n    }\n\n    *key1bits = half_keybits;\n    *key2bits = half_keybits;\n    *key1 = &key[0];\n    *key2 = &key[half_keybytes];\n\n    return 0;\n}\n\nint mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context *ctx,\n                               const unsigned char *key,\n                               unsigned int keybits)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const unsigned char *key1, *key2;\n    unsigned int key1bits, key2bits;\n\n    ret = mbedtls_aes_xts_decode_keys(key, keybits, &key1, &key1bits,\n                                      &key2, &key2bits);\n    if (ret != 0) {\n        return ret;\n    }\n\n    /* Set the tweak key. Always set tweak key for the encryption mode. */\n    ret = mbedtls_aes_setkey_enc(&ctx->tweak, key2, key2bits);\n    if (ret != 0) {\n        return ret;\n    }\n\n    /* Set crypt key for encryption. */\n    return mbedtls_aes_setkey_enc(&ctx->crypt, key1, key1bits);\n}\n\nint mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context *ctx,\n                               const unsigned char *key,\n                               unsigned int keybits)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const unsigned char *key1, *key2;\n    unsigned int key1bits, key2bits;\n\n    ret = mbedtls_aes_xts_decode_keys(key, keybits, &key1, &key1bits,\n                                      &key2, &key2bits);\n    if (ret != 0) {\n        return ret;\n    }\n\n    /* Set the tweak key. Always set tweak key for encryption. */\n    ret = mbedtls_aes_setkey_enc(&ctx->tweak, key2, key2bits);\n    if (ret != 0) {\n        return ret;\n    }\n\n    /* Set crypt key for decryption. */\n    return mbedtls_aes_setkey_dec(&ctx->crypt, key1, key1bits);\n}\n#endif /* MBEDTLS_CIPHER_MODE_XTS */\n\n#define AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3)                 \\\n    do                                                      \\\n    {                                                       \\\n        (X0) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y0)) ^    \\\n               AES_FT1(MBEDTLS_BYTE_1(Y1)) ^    \\\n               AES_FT2(MBEDTLS_BYTE_2(Y2)) ^    \\\n               AES_FT3(MBEDTLS_BYTE_3(Y3));     \\\n                                                            \\\n        (X1) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y1)) ^    \\\n               AES_FT1(MBEDTLS_BYTE_1(Y2)) ^    \\\n               AES_FT2(MBEDTLS_BYTE_2(Y3)) ^    \\\n               AES_FT3(MBEDTLS_BYTE_3(Y0));     \\\n                                                            \\\n        (X2) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y2)) ^    \\\n               AES_FT1(MBEDTLS_BYTE_1(Y3)) ^    \\\n               AES_FT2(MBEDTLS_BYTE_2(Y0)) ^    \\\n               AES_FT3(MBEDTLS_BYTE_3(Y1));     \\\n                                                            \\\n        (X3) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y3)) ^    \\\n               AES_FT1(MBEDTLS_BYTE_1(Y0)) ^    \\\n               AES_FT2(MBEDTLS_BYTE_2(Y1)) ^    \\\n               AES_FT3(MBEDTLS_BYTE_3(Y2));     \\\n    } while (0)\n\n#define AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3)                 \\\n    do                                                      \\\n    {                                                       \\\n        (X0) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y0)) ^    \\\n               AES_RT1(MBEDTLS_BYTE_1(Y3)) ^    \\\n               AES_RT2(MBEDTLS_BYTE_2(Y2)) ^    \\\n               AES_RT3(MBEDTLS_BYTE_3(Y1));     \\\n                                                            \\\n        (X1) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y1)) ^    \\\n               AES_RT1(MBEDTLS_BYTE_1(Y0)) ^    \\\n               AES_RT2(MBEDTLS_BYTE_2(Y3)) ^    \\\n               AES_RT3(MBEDTLS_BYTE_3(Y2));     \\\n                                                            \\\n        (X2) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y2)) ^    \\\n               AES_RT1(MBEDTLS_BYTE_1(Y1)) ^    \\\n               AES_RT2(MBEDTLS_BYTE_2(Y0)) ^    \\\n               AES_RT3(MBEDTLS_BYTE_3(Y3));     \\\n                                                            \\\n        (X3) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y3)) ^    \\\n               AES_RT1(MBEDTLS_BYTE_1(Y2)) ^    \\\n               AES_RT2(MBEDTLS_BYTE_2(Y1)) ^    \\\n               AES_RT3(MBEDTLS_BYTE_3(Y0));     \\\n    } while (0)\n\n/*\n * AES-ECB block encryption\n */\n#if !defined(MBEDTLS_AES_ENCRYPT_ALT)\nint mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx,\n                                 const unsigned char input[16],\n                                 unsigned char output[16])\n{\n    int i;\n    uint32_t *RK = ctx->buf + ctx->rk_offset;\n    struct {\n        uint32_t X[4];\n        uint32_t Y[4];\n    } t;\n\n    t.X[0] = MBEDTLS_GET_UINT32_LE(input,  0); t.X[0] ^= *RK++;\n    t.X[1] = MBEDTLS_GET_UINT32_LE(input,  4); t.X[1] ^= *RK++;\n    t.X[2] = MBEDTLS_GET_UINT32_LE(input,  8); t.X[2] ^= *RK++;\n    t.X[3] = MBEDTLS_GET_UINT32_LE(input, 12); t.X[3] ^= *RK++;\n\n    for (i = (ctx->nr >> 1) - 1; i > 0; i--) {\n        AES_FROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]);\n        AES_FROUND(t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3]);\n    }\n\n    AES_FROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]);\n\n    t.X[0] = *RK++ ^ \\\n             ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[0])]) ^\n             ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[1])] <<  8) ^\n             ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[2])] << 16) ^\n             ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[3])] << 24);\n\n    t.X[1] = *RK++ ^ \\\n             ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[1])]) ^\n             ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[2])] <<  8) ^\n             ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[3])] << 16) ^\n             ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[0])] << 24);\n\n    t.X[2] = *RK++ ^ \\\n             ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[2])]) ^\n             ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[3])] <<  8) ^\n             ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[0])] << 16) ^\n             ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[1])] << 24);\n\n    t.X[3] = *RK++ ^ \\\n             ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[3])]) ^\n             ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[0])] <<  8) ^\n             ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[1])] << 16) ^\n             ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[2])] << 24);\n\n    MBEDTLS_PUT_UINT32_LE(t.X[0], output,  0);\n    MBEDTLS_PUT_UINT32_LE(t.X[1], output,  4);\n    MBEDTLS_PUT_UINT32_LE(t.X[2], output,  8);\n    MBEDTLS_PUT_UINT32_LE(t.X[3], output, 12);\n\n    mbedtls_platform_zeroize(&t, sizeof(t));\n\n    return 0;\n}\n#endif /* !MBEDTLS_AES_ENCRYPT_ALT */\n\n/*\n * AES-ECB block decryption\n */\n#if !defined(MBEDTLS_AES_DECRYPT_ALT) && !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\nint mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx,\n                                 const unsigned char input[16],\n                                 unsigned char output[16])\n{\n    int i;\n    uint32_t *RK = ctx->buf + ctx->rk_offset;\n    struct {\n        uint32_t X[4];\n        uint32_t Y[4];\n    } t;\n\n    t.X[0] = MBEDTLS_GET_UINT32_LE(input,  0); t.X[0] ^= *RK++;\n    t.X[1] = MBEDTLS_GET_UINT32_LE(input,  4); t.X[1] ^= *RK++;\n    t.X[2] = MBEDTLS_GET_UINT32_LE(input,  8); t.X[2] ^= *RK++;\n    t.X[3] = MBEDTLS_GET_UINT32_LE(input, 12); t.X[3] ^= *RK++;\n\n    for (i = (ctx->nr >> 1) - 1; i > 0; i--) {\n        AES_RROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]);\n        AES_RROUND(t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3]);\n    }\n\n    AES_RROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]);\n\n    t.X[0] = *RK++ ^ \\\n             ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[0])]) ^\n             ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[3])] <<  8) ^\n             ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[2])] << 16) ^\n             ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[1])] << 24);\n\n    t.X[1] = *RK++ ^ \\\n             ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[1])]) ^\n             ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[0])] <<  8) ^\n             ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[3])] << 16) ^\n             ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[2])] << 24);\n\n    t.X[2] = *RK++ ^ \\\n             ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[2])]) ^\n             ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[1])] <<  8) ^\n             ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[0])] << 16) ^\n             ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[3])] << 24);\n\n    t.X[3] = *RK++ ^ \\\n             ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[3])]) ^\n             ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[2])] <<  8) ^\n             ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[1])] << 16) ^\n             ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[0])] << 24);\n\n    MBEDTLS_PUT_UINT32_LE(t.X[0], output,  0);\n    MBEDTLS_PUT_UINT32_LE(t.X[1], output,  4);\n    MBEDTLS_PUT_UINT32_LE(t.X[2], output,  8);\n    MBEDTLS_PUT_UINT32_LE(t.X[3], output, 12);\n\n    mbedtls_platform_zeroize(&t, sizeof(t));\n\n    return 0;\n}\n#endif /* !MBEDTLS_AES_DECRYPT_ALT && !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */\n\n/* VIA Padlock and our intrinsics-based implementation of AESNI require\n * the round keys to be aligned on a 16-byte boundary. We take care of this\n * before creating them, but the AES context may have moved (this can happen\n * if the library is called from a language with managed memory), and in later\n * calls it might have a different alignment with respect to 16-byte memory.\n * So we may need to realign.\n */\nMBEDTLS_MAYBE_UNUSED static void aes_maybe_realign(mbedtls_aes_context *ctx)\n{\n    unsigned new_offset = mbedtls_aes_rk_offset(ctx->buf);\n    if (new_offset != ctx->rk_offset) {\n        memmove(ctx->buf + new_offset,     // new address\n                ctx->buf + ctx->rk_offset, // current address\n                (ctx->nr + 1) * 16);       // number of round keys * bytes per rk\n        ctx->rk_offset = new_offset;\n    }\n}\n\n/*\n * AES-ECB block encryption/decryption\n */\nint mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx,\n                          int mode,\n                          const unsigned char input[16],\n                          unsigned char output[16])\n{\n    if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) {\n        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;\n    }\n\n#if defined(MAY_NEED_TO_ALIGN)\n    aes_maybe_realign(ctx);\n#endif\n\n#if defined(MBEDTLS_AESNI_HAVE_CODE)\n    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {\n        return mbedtls_aesni_crypt_ecb(ctx, mode, input, output);\n    }\n#endif\n\n#if defined(MBEDTLS_AESCE_HAVE_CODE)\n    if (MBEDTLS_AESCE_HAS_SUPPORT()) {\n        return mbedtls_aesce_crypt_ecb(ctx, mode, input, output);\n    }\n#endif\n\n#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)\n    if (aes_padlock_ace > 0) {\n        return mbedtls_padlock_xcryptecb(ctx, mode, input, output);\n    }\n#endif\n\n#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    if (mode == MBEDTLS_AES_DECRYPT) {\n        return mbedtls_internal_aes_decrypt(ctx, input, output);\n    } else\n#endif\n    {\n        return mbedtls_internal_aes_encrypt(ctx, input, output);\n    }\n#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */\n}\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n\n/*\n * AES-CBC buffer encryption/decryption\n */\nint mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx,\n                          int mode,\n                          size_t length,\n                          unsigned char iv[16],\n                          const unsigned char *input,\n                          unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char temp[16];\n\n    if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) {\n        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;\n    }\n\n    /* Nothing to do if length is zero. */\n    if (length == 0) {\n        return 0;\n    }\n\n    if (length % 16) {\n        return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;\n    }\n\n#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)\n    if (aes_padlock_ace > 0) {\n        if (mbedtls_padlock_xcryptcbc(ctx, mode, length, iv, input, output) == 0) {\n            return 0;\n        }\n\n        // If padlock data misaligned, we just fall back to\n        // unaccelerated mode\n        //\n    }\n#endif\n\n    const unsigned char *ivp = iv;\n\n    if (mode == MBEDTLS_AES_DECRYPT) {\n        while (length > 0) {\n            memcpy(temp, input, 16);\n            ret = mbedtls_aes_crypt_ecb(ctx, mode, input, output);\n            if (ret != 0) {\n                goto exit;\n            }\n            /* Avoid using the NEON implementation of mbedtls_xor. Because of the dependency on\n             * the result for the next block in CBC, and the cost of transferring that data from\n             * NEON registers, NEON is slower on aarch64. */\n            mbedtls_xor_no_simd(output, output, iv, 16);\n\n            memcpy(iv, temp, 16);\n\n            input  += 16;\n            output += 16;\n            length -= 16;\n        }\n    } else {\n        while (length > 0) {\n            mbedtls_xor_no_simd(output, input, ivp, 16);\n\n            ret = mbedtls_aes_crypt_ecb(ctx, mode, output, output);\n            if (ret != 0) {\n                goto exit;\n            }\n            ivp = output;\n\n            input  += 16;\n            output += 16;\n            length -= 16;\n        }\n        memcpy(iv, ivp, 16);\n    }\n    ret = 0;\n\nexit:\n    return ret;\n}\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n\ntypedef unsigned char mbedtls_be128[16];\n\n/*\n * GF(2^128) multiplication function\n *\n * This function multiplies a field element by x in the polynomial field\n * representation. It uses 64-bit word operations to gain speed but compensates\n * for machine endianness and hence works correctly on both big and little\n * endian machines.\n */\n#if defined(MBEDTLS_AESCE_C) || defined(MBEDTLS_AESNI_C)\nMBEDTLS_OPTIMIZE_FOR_PERFORMANCE\n#endif\nstatic inline void mbedtls_gf128mul_x_ble(unsigned char r[16],\n                                          const unsigned char x[16])\n{\n    uint64_t a, b, ra, rb;\n\n    a = MBEDTLS_GET_UINT64_LE(x, 0);\n    b = MBEDTLS_GET_UINT64_LE(x, 8);\n\n    ra = (a << 1)  ^ 0x0087 >> (8 - ((b >> 63) << 3));\n    rb = (a >> 63) | (b << 1);\n\n    MBEDTLS_PUT_UINT64_LE(ra, r, 0);\n    MBEDTLS_PUT_UINT64_LE(rb, r, 8);\n}\n\n/*\n * AES-XTS buffer encryption/decryption\n *\n * Use of MBEDTLS_OPTIMIZE_FOR_PERFORMANCE here and for mbedtls_gf128mul_x_ble()\n * is a 3x performance improvement for gcc -Os, if we have hardware AES support.\n */\n#if defined(MBEDTLS_AESCE_C) || defined(MBEDTLS_AESNI_C)\nMBEDTLS_OPTIMIZE_FOR_PERFORMANCE\n#endif\nint mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx,\n                          int mode,\n                          size_t length,\n                          const unsigned char data_unit[16],\n                          const unsigned char *input,\n                          unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t blocks = length / 16;\n    size_t leftover = length % 16;\n    unsigned char tweak[16];\n    unsigned char prev_tweak[16];\n    unsigned char tmp[16];\n\n    if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) {\n        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;\n    }\n\n    /* Data units must be at least 16 bytes long. */\n    if (length < 16) {\n        return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;\n    }\n\n    /* NIST SP 800-38E disallows data units larger than 2**20 blocks. */\n    if (length > (1 << 20) * 16) {\n        return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;\n    }\n\n    /* Compute the tweak. */\n    ret = mbedtls_aes_crypt_ecb(&ctx->tweak, MBEDTLS_AES_ENCRYPT,\n                                data_unit, tweak);\n    if (ret != 0) {\n        return ret;\n    }\n\n    while (blocks--) {\n        if (MBEDTLS_UNLIKELY(leftover && (mode == MBEDTLS_AES_DECRYPT) && blocks == 0)) {\n            /* We are on the last block in a decrypt operation that has\n             * leftover bytes, so we need to use the next tweak for this block,\n             * and this tweak for the leftover bytes. Save the current tweak for\n             * the leftovers and then update the current tweak for use on this,\n             * the last full block. */\n            memcpy(prev_tweak, tweak, sizeof(tweak));\n            mbedtls_gf128mul_x_ble(tweak, tweak);\n        }\n\n        mbedtls_xor(tmp, input, tweak, 16);\n\n        ret = mbedtls_aes_crypt_ecb(&ctx->crypt, mode, tmp, tmp);\n        if (ret != 0) {\n            return ret;\n        }\n\n        mbedtls_xor(output, tmp, tweak, 16);\n\n        /* Update the tweak for the next block. */\n        mbedtls_gf128mul_x_ble(tweak, tweak);\n\n        output += 16;\n        input += 16;\n    }\n\n    if (leftover) {\n        /* If we are on the leftover bytes in a decrypt operation, we need to\n         * use the previous tweak for these bytes (as saved in prev_tweak). */\n        unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak;\n\n        /* We are now on the final part of the data unit, which doesn't divide\n         * evenly by 16. It's time for ciphertext stealing. */\n        size_t i;\n        unsigned char *prev_output = output - 16;\n\n        /* Copy ciphertext bytes from the previous block to our output for each\n         * byte of ciphertext we won't steal. */\n        for (i = 0; i < leftover; i++) {\n            output[i] = prev_output[i];\n        }\n\n        /* Copy the remainder of the input for this final round. */\n        mbedtls_xor(tmp, input, t, leftover);\n\n        /* Copy ciphertext bytes from the previous block for input in this\n         * round. */\n        mbedtls_xor(tmp + i, prev_output + i, t + i, 16 - i);\n\n        ret = mbedtls_aes_crypt_ecb(&ctx->crypt, mode, tmp, tmp);\n        if (ret != 0) {\n            return ret;\n        }\n\n        /* Write the result back to the previous block, overriding the previous\n         * output we copied. */\n        mbedtls_xor(prev_output, tmp, t, 16);\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_CIPHER_MODE_XTS */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n/*\n * AES-CFB128 buffer encryption/decryption\n */\nint mbedtls_aes_crypt_cfb128(mbedtls_aes_context *ctx,\n                             int mode,\n                             size_t length,\n                             size_t *iv_off,\n                             unsigned char iv[16],\n                             const unsigned char *input,\n                             unsigned char *output)\n{\n    int c;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t n;\n\n    if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) {\n        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;\n    }\n\n    n = *iv_off;\n\n    if (n > 15) {\n        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;\n    }\n\n    if (mode == MBEDTLS_AES_DECRYPT) {\n        while (length--) {\n            if (n == 0) {\n                ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv);\n                if (ret != 0) {\n                    goto exit;\n                }\n            }\n\n            c = *input++;\n            *output++ = (unsigned char) (c ^ iv[n]);\n            iv[n] = (unsigned char) c;\n\n            n = (n + 1) & 0x0F;\n        }\n    } else {\n        while (length--) {\n            if (n == 0) {\n                ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv);\n                if (ret != 0) {\n                    goto exit;\n                }\n            }\n\n            iv[n] = *output++ = (unsigned char) (iv[n] ^ *input++);\n\n            n = (n + 1) & 0x0F;\n        }\n    }\n\n    *iv_off = n;\n    ret = 0;\n\nexit:\n    return ret;\n}\n\n/*\n * AES-CFB8 buffer encryption/decryption\n */\nint mbedtls_aes_crypt_cfb8(mbedtls_aes_context *ctx,\n                           int mode,\n                           size_t length,\n                           unsigned char iv[16],\n                           const unsigned char *input,\n                           unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char c;\n    unsigned char ov[17];\n\n    if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) {\n        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;\n    }\n    while (length--) {\n        memcpy(ov, iv, 16);\n        ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv);\n        if (ret != 0) {\n            goto exit;\n        }\n\n        if (mode == MBEDTLS_AES_DECRYPT) {\n            ov[16] = *input;\n        }\n\n        c = *output++ = (unsigned char) (iv[0] ^ *input++);\n\n        if (mode == MBEDTLS_AES_ENCRYPT) {\n            ov[16] = c;\n        }\n\n        memcpy(iv, ov + 1, 16);\n    }\n    ret = 0;\n\nexit:\n    return ret;\n}\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n/*\n * AES-OFB (Output Feedback Mode) buffer encryption/decryption\n */\nint mbedtls_aes_crypt_ofb(mbedtls_aes_context *ctx,\n                          size_t length,\n                          size_t *iv_off,\n                          unsigned char iv[16],\n                          const unsigned char *input,\n                          unsigned char *output)\n{\n    int ret = 0;\n    size_t n;\n\n    n = *iv_off;\n\n    if (n > 15) {\n        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;\n    }\n\n    while (length--) {\n        if (n == 0) {\n            ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv);\n            if (ret != 0) {\n                goto exit;\n            }\n        }\n        *output++ =  *input++ ^ iv[n];\n\n        n = (n + 1) & 0x0F;\n    }\n\n    *iv_off = n;\n\nexit:\n    return ret;\n}\n#endif /* MBEDTLS_CIPHER_MODE_OFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n/*\n * AES-CTR buffer encryption/decryption\n */\nint mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx,\n                          size_t length,\n                          size_t *nc_off,\n                          unsigned char nonce_counter[16],\n                          unsigned char stream_block[16],\n                          const unsigned char *input,\n                          unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    size_t offset = *nc_off;\n\n    if (offset > 0x0F) {\n        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;\n    }\n\n    for (size_t i = 0; i < length;) {\n        size_t n = 16;\n        if (offset == 0) {\n            ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block);\n            if (ret != 0) {\n                goto exit;\n            }\n            mbedtls_ctr_increment_counter(nonce_counter);\n        } else {\n            n -= offset;\n        }\n\n        if (n > (length - i)) {\n            n = (length - i);\n        }\n        mbedtls_xor(&output[i], &input[i], &stream_block[offset], n);\n        // offset might be non-zero for the last block, but in that case, we don't use it again\n        offset = 0;\n        i += n;\n    }\n\n    // capture offset for future resumption\n    *nc_off = (*nc_off + length) % 16;\n\n    ret = 0;\n\nexit:\n    return ret;\n}\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n#endif /* !MBEDTLS_AES_ALT */\n\n#if defined(MBEDTLS_SELF_TEST)\n/*\n * AES test vectors from:\n *\n * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip\n */\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\nstatic const unsigned char aes_test_ecb_dec[][16] =\n{\n    { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58,\n      0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2,\n      0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 },\n    { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D,\n      0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE }\n#endif\n};\n#endif\n\nstatic const unsigned char aes_test_ecb_enc[][16] =\n{\n    { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73,\n      0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11,\n      0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 },\n    { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D,\n      0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 }\n#endif\n};\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\nstatic const unsigned char aes_test_cbc_dec[][16] =\n{\n    { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73,\n      0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75,\n      0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B },\n    { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75,\n      0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 }\n#endif\n};\n\nstatic const unsigned char aes_test_cbc_enc[][16] =\n{\n    { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84,\n      0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB,\n      0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 },\n    { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5,\n      0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 }\n#endif\n};\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n/*\n * AES-CFB128 test vectors from:\n *\n * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf\n */\nstatic const unsigned char aes_test_cfb128_key[][32] =\n{\n    { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,\n      0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,\n      0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,\n      0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },\n    { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,\n      0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,\n      0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,\n      0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }\n#endif\n};\n\nstatic const unsigned char aes_test_cfb128_iv[16] =\n{\n    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F\n};\n\nstatic const unsigned char aes_test_cfb128_pt[64] =\n{\n    0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,\n    0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,\n    0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,\n    0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,\n    0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,\n    0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,\n    0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,\n    0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10\n};\n\nstatic const unsigned char aes_test_cfb128_ct[][64] =\n{\n    { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,\n      0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,\n      0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F,\n      0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B,\n      0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40,\n      0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF,\n      0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E,\n      0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,\n      0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,\n      0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21,\n      0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A,\n      0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1,\n      0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9,\n      0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0,\n      0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF },\n    { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,\n      0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,\n      0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8,\n      0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B,\n      0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92,\n      0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9,\n      0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8,\n      0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 }\n#endif\n};\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n/*\n * AES-OFB test vectors from:\n *\n * https://csrc.nist.gov/publications/detail/sp/800-38a/final\n */\nstatic const unsigned char aes_test_ofb_key[][32] =\n{\n    { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,\n      0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,\n      0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,\n      0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },\n    { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,\n      0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,\n      0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,\n      0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }\n#endif\n};\n\nstatic const unsigned char aes_test_ofb_iv[16] =\n{\n    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F\n};\n\nstatic const unsigned char aes_test_ofb_pt[64] =\n{\n    0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,\n    0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,\n    0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,\n    0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,\n    0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,\n    0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,\n    0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,\n    0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10\n};\n\nstatic const unsigned char aes_test_ofb_ct[][64] =\n{\n    { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,\n      0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,\n      0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03,\n      0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25,\n      0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6,\n      0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc,\n      0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78,\n      0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,\n      0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,\n      0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c,\n      0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01,\n      0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f,\n      0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2,\n      0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e,\n      0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a },\n    { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,\n      0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,\n      0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a,\n      0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d,\n      0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed,\n      0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08,\n      0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8,\n      0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 }\n#endif\n};\n#endif /* MBEDTLS_CIPHER_MODE_OFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n/*\n * AES-CTR test vectors from:\n *\n * http://www.faqs.org/rfcs/rfc3686.html\n */\n\nstatic const unsigned char aes_test_ctr_key[][16] =\n{\n    { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,\n      0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },\n    { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,\n      0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },\n    { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,\n      0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }\n};\n\nstatic const unsigned char aes_test_ctr_nonce_counter[][16] =\n{\n    { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },\n    { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,\n      0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },\n    { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,\n      0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }\n};\n\nstatic const unsigned char aes_test_ctr_pt[][48] =\n{\n    { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,\n      0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },\n    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,\n      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,\n      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },\n\n    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,\n      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,\n      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,\n      0x20, 0x21, 0x22, 0x23 }\n};\n\nstatic const unsigned char aes_test_ctr_ct[][48] =\n{\n    { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79,\n      0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 },\n    { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9,\n      0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88,\n      0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8,\n      0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 },\n    { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9,\n      0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7,\n      0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36,\n      0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53,\n      0x25, 0xB2, 0x07, 0x2F }\n};\n\nstatic const int aes_test_ctr_len[3] =\n{ 16, 32, 36 };\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n/*\n * AES-XTS test vectors from:\n *\n * IEEE P1619/D16 Annex B\n * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf\n * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf)\n */\nstatic const unsigned char aes_test_xts_key[][32] =\n{\n    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n    { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,\n      0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,\n      0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,\n      0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },\n    { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,\n      0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,\n      0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,\n      0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },\n};\n\nstatic const unsigned char aes_test_xts_pt32[][32] =\n{\n    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n    { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,\n      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,\n      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,\n      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },\n    { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,\n      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,\n      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,\n      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },\n};\n\nstatic const unsigned char aes_test_xts_ct32[][32] =\n{\n    { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,\n      0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,\n      0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,\n      0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },\n    { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,\n      0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,\n      0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,\n      0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },\n    { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,\n      0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,\n      0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,\n      0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 },\n};\n\nstatic const unsigned char aes_test_xts_data_unit[][16] =\n{\n    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n    { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n    { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n};\n\n#endif /* MBEDTLS_CIPHER_MODE_XTS */\n\n/*\n * Checkup routine\n */\nint mbedtls_aes_self_test(int verbose)\n{\n    int ret = 0, i, j, u, mode;\n    unsigned int keybits;\n    unsigned char key[32];\n    unsigned char buf[64];\n    const unsigned char *aes_tests;\n#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \\\n    defined(MBEDTLS_CIPHER_MODE_OFB)\n    unsigned char iv[16];\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    unsigned char prv[16];\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \\\n    defined(MBEDTLS_CIPHER_MODE_OFB)\n    size_t offset;\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS)\n    int len;\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    unsigned char nonce_counter[16];\n    unsigned char stream_block[16];\n#endif\n    mbedtls_aes_context ctx;\n\n    memset(key, 0, 32);\n    mbedtls_aes_init(&ctx);\n\n    if (verbose != 0) {\n#if defined(MBEDTLS_AES_ALT)\n        mbedtls_printf(\"  AES note: alternative implementation.\\n\");\n#else /* MBEDTLS_AES_ALT */\n#if defined(MBEDTLS_AESNI_HAVE_CODE)\n#if MBEDTLS_AESNI_HAVE_CODE == 1\n        mbedtls_printf(\"  AES note: AESNI code present (assembly implementation).\\n\");\n#elif MBEDTLS_AESNI_HAVE_CODE == 2\n        mbedtls_printf(\"  AES note: AESNI code present (intrinsics implementation).\\n\");\n#else\n#error \"Unrecognised value for MBEDTLS_AESNI_HAVE_CODE\"\n#endif\n        if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {\n            mbedtls_printf(\"  AES note: using AESNI.\\n\");\n        } else\n#endif\n#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)\n        if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) {\n            mbedtls_printf(\"  AES note: using VIA Padlock.\\n\");\n        } else\n#endif\n#if defined(MBEDTLS_AESCE_HAVE_CODE)\n        if (MBEDTLS_AESCE_HAS_SUPPORT()) {\n            mbedtls_printf(\"  AES note: using AESCE.\\n\");\n        } else\n#endif\n        {\n#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)\n            mbedtls_printf(\"  AES note: built-in implementation.\\n\");\n#endif\n        }\n#endif /* MBEDTLS_AES_ALT */\n    }\n\n    /*\n     * ECB mode\n     */\n    {\n        static const int num_tests =\n            sizeof(aes_test_ecb_enc) / sizeof(*aes_test_ecb_enc);\n\n        for (i = 0; i < num_tests << 1; i++) {\n            u = i >> 1;\n            keybits = 128 + u * 64;\n            mode = i & 1;\n\n            if (verbose != 0) {\n                mbedtls_printf(\"  AES-ECB-%3u (%s): \", keybits,\n                               (mode == MBEDTLS_AES_DECRYPT) ? \"dec\" : \"enc\");\n            }\n#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n            if (mode == MBEDTLS_AES_DECRYPT) {\n                if (verbose != 0) {\n                    mbedtls_printf(\"skipped\\n\");\n                }\n                continue;\n            }\n#endif\n\n            memset(buf, 0, 16);\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n            if (mode == MBEDTLS_AES_DECRYPT) {\n                ret = mbedtls_aes_setkey_dec(&ctx, key, keybits);\n                aes_tests = aes_test_ecb_dec[u];\n            } else\n#endif\n            {\n                ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);\n                aes_tests = aes_test_ecb_enc[u];\n            }\n\n            /*\n             * AES-192 is an optional feature that may be unavailable when\n             * there is an alternative underlying implementation i.e. when\n             * MBEDTLS_AES_ALT is defined.\n             */\n            if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {\n                mbedtls_printf(\"skipped\\n\");\n                continue;\n            } else if (ret != 0) {\n                goto exit;\n            }\n\n            for (j = 0; j < 10000; j++) {\n                ret = mbedtls_aes_crypt_ecb(&ctx, mode, buf, buf);\n                if (ret != 0) {\n                    goto exit;\n                }\n            }\n\n            if (memcmp(buf, aes_tests, 16) != 0) {\n                ret = 1;\n                goto exit;\n            }\n\n            if (verbose != 0) {\n                mbedtls_printf(\"passed\\n\");\n            }\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"\\n\");\n        }\n    }\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    /*\n     * CBC mode\n     */\n    {\n        static const int num_tests =\n            sizeof(aes_test_cbc_dec) / sizeof(*aes_test_cbc_dec);\n\n        for (i = 0; i < num_tests << 1; i++) {\n            u = i >> 1;\n            keybits = 128 + u * 64;\n            mode = i & 1;\n\n            if (verbose != 0) {\n                mbedtls_printf(\"  AES-CBC-%3u (%s): \", keybits,\n                               (mode == MBEDTLS_AES_DECRYPT) ? \"dec\" : \"enc\");\n            }\n\n            memset(iv, 0, 16);\n            memset(prv, 0, 16);\n            memset(buf, 0, 16);\n\n            if (mode == MBEDTLS_AES_DECRYPT) {\n                ret = mbedtls_aes_setkey_dec(&ctx, key, keybits);\n                aes_tests = aes_test_cbc_dec[u];\n            } else {\n                ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);\n                aes_tests = aes_test_cbc_enc[u];\n            }\n\n            /*\n             * AES-192 is an optional feature that may be unavailable when\n             * there is an alternative underlying implementation i.e. when\n             * MBEDTLS_AES_ALT is defined.\n             */\n            if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {\n                mbedtls_printf(\"skipped\\n\");\n                continue;\n            } else if (ret != 0) {\n                goto exit;\n            }\n\n            for (j = 0; j < 10000; j++) {\n                if (mode == MBEDTLS_AES_ENCRYPT) {\n                    unsigned char tmp[16];\n\n                    memcpy(tmp, prv, 16);\n                    memcpy(prv, buf, 16);\n                    memcpy(buf, tmp, 16);\n                }\n\n                ret = mbedtls_aes_crypt_cbc(&ctx, mode, 16, iv, buf, buf);\n                if (ret != 0) {\n                    goto exit;\n                }\n\n            }\n\n            if (memcmp(buf, aes_tests, 16) != 0) {\n                ret = 1;\n                goto exit;\n            }\n\n            if (verbose != 0) {\n                mbedtls_printf(\"passed\\n\");\n            }\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"\\n\");\n        }\n    }\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    /*\n     * CFB128 mode\n     */\n    {\n        static const int num_tests =\n            sizeof(aes_test_cfb128_key) / sizeof(*aes_test_cfb128_key);\n\n        for (i = 0; i < num_tests << 1; i++) {\n            u = i >> 1;\n            keybits = 128 + u * 64;\n            mode = i & 1;\n\n            if (verbose != 0) {\n                mbedtls_printf(\"  AES-CFB128-%3u (%s): \", keybits,\n                               (mode == MBEDTLS_AES_DECRYPT) ? \"dec\" : \"enc\");\n            }\n\n            memcpy(iv,  aes_test_cfb128_iv, 16);\n            memcpy(key, aes_test_cfb128_key[u], keybits / 8);\n\n            offset = 0;\n            ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);\n            /*\n             * AES-192 is an optional feature that may be unavailable when\n             * there is an alternative underlying implementation i.e. when\n             * MBEDTLS_AES_ALT is defined.\n             */\n            if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {\n                mbedtls_printf(\"skipped\\n\");\n                continue;\n            } else if (ret != 0) {\n                goto exit;\n            }\n\n            if (mode == MBEDTLS_AES_DECRYPT) {\n                memcpy(buf, aes_test_cfb128_ct[u], 64);\n                aes_tests = aes_test_cfb128_pt;\n            } else {\n                memcpy(buf, aes_test_cfb128_pt, 64);\n                aes_tests = aes_test_cfb128_ct[u];\n            }\n\n            ret = mbedtls_aes_crypt_cfb128(&ctx, mode, 64, &offset, iv, buf, buf);\n            if (ret != 0) {\n                goto exit;\n            }\n\n            if (memcmp(buf, aes_tests, 64) != 0) {\n                ret = 1;\n                goto exit;\n            }\n\n            if (verbose != 0) {\n                mbedtls_printf(\"passed\\n\");\n            }\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"\\n\");\n        }\n    }\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    /*\n     * OFB mode\n     */\n    {\n        static const int num_tests =\n            sizeof(aes_test_ofb_key) / sizeof(*aes_test_ofb_key);\n\n        for (i = 0; i < num_tests << 1; i++) {\n            u = i >> 1;\n            keybits = 128 + u * 64;\n            mode = i & 1;\n\n            if (verbose != 0) {\n                mbedtls_printf(\"  AES-OFB-%3u (%s): \", keybits,\n                               (mode == MBEDTLS_AES_DECRYPT) ? \"dec\" : \"enc\");\n            }\n\n            memcpy(iv,  aes_test_ofb_iv, 16);\n            memcpy(key, aes_test_ofb_key[u], keybits / 8);\n\n            offset = 0;\n            ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);\n            /*\n             * AES-192 is an optional feature that may be unavailable when\n             * there is an alternative underlying implementation i.e. when\n             * MBEDTLS_AES_ALT is defined.\n             */\n            if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {\n                mbedtls_printf(\"skipped\\n\");\n                continue;\n            } else if (ret != 0) {\n                goto exit;\n            }\n\n            if (mode == MBEDTLS_AES_DECRYPT) {\n                memcpy(buf, aes_test_ofb_ct[u], 64);\n                aes_tests = aes_test_ofb_pt;\n            } else {\n                memcpy(buf, aes_test_ofb_pt, 64);\n                aes_tests = aes_test_ofb_ct[u];\n            }\n\n            ret = mbedtls_aes_crypt_ofb(&ctx, 64, &offset, iv, buf, buf);\n            if (ret != 0) {\n                goto exit;\n            }\n\n            if (memcmp(buf, aes_tests, 64) != 0) {\n                ret = 1;\n                goto exit;\n            }\n\n            if (verbose != 0) {\n                mbedtls_printf(\"passed\\n\");\n            }\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"\\n\");\n        }\n    }\n#endif /* MBEDTLS_CIPHER_MODE_OFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    /*\n     * CTR mode\n     */\n    {\n        static const int num_tests =\n            sizeof(aes_test_ctr_key) / sizeof(*aes_test_ctr_key);\n\n        for (i = 0; i < num_tests << 1; i++) {\n            u = i >> 1;\n            mode = i & 1;\n\n            if (verbose != 0) {\n                mbedtls_printf(\"  AES-CTR-128 (%s): \",\n                               (mode == MBEDTLS_AES_DECRYPT) ? \"dec\" : \"enc\");\n            }\n\n            memcpy(nonce_counter, aes_test_ctr_nonce_counter[u], 16);\n            memcpy(key, aes_test_ctr_key[u], 16);\n\n            offset = 0;\n            if ((ret = mbedtls_aes_setkey_enc(&ctx, key, 128)) != 0) {\n                goto exit;\n            }\n\n            len = aes_test_ctr_len[u];\n\n            if (mode == MBEDTLS_AES_DECRYPT) {\n                memcpy(buf, aes_test_ctr_ct[u], len);\n                aes_tests = aes_test_ctr_pt[u];\n            } else {\n                memcpy(buf, aes_test_ctr_pt[u], len);\n                aes_tests = aes_test_ctr_ct[u];\n            }\n\n            ret = mbedtls_aes_crypt_ctr(&ctx, len, &offset, nonce_counter,\n                                        stream_block, buf, buf);\n            if (ret != 0) {\n                goto exit;\n            }\n\n            if (memcmp(buf, aes_tests, len) != 0) {\n                ret = 1;\n                goto exit;\n            }\n\n            if (verbose != 0) {\n                mbedtls_printf(\"passed\\n\");\n            }\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    /*\n     * XTS mode\n     */\n    {\n        static const int num_tests =\n            sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key);\n        mbedtls_aes_xts_context ctx_xts;\n\n        mbedtls_aes_xts_init(&ctx_xts);\n\n        for (i = 0; i < num_tests << 1; i++) {\n            const unsigned char *data_unit;\n            u = i >> 1;\n            mode = i & 1;\n\n            if (verbose != 0) {\n                mbedtls_printf(\"  AES-XTS-128 (%s): \",\n                               (mode == MBEDTLS_AES_DECRYPT) ? \"dec\" : \"enc\");\n            }\n\n            memset(key, 0, sizeof(key));\n            memcpy(key, aes_test_xts_key[u], 32);\n            data_unit = aes_test_xts_data_unit[u];\n\n            len = sizeof(*aes_test_xts_ct32);\n\n            if (mode == MBEDTLS_AES_DECRYPT) {\n                ret = mbedtls_aes_xts_setkey_dec(&ctx_xts, key, 256);\n                if (ret != 0) {\n                    goto exit;\n                }\n                memcpy(buf, aes_test_xts_ct32[u], len);\n                aes_tests = aes_test_xts_pt32[u];\n            } else {\n                ret = mbedtls_aes_xts_setkey_enc(&ctx_xts, key, 256);\n                if (ret != 0) {\n                    goto exit;\n                }\n                memcpy(buf, aes_test_xts_pt32[u], len);\n                aes_tests = aes_test_xts_ct32[u];\n            }\n\n\n            ret = mbedtls_aes_crypt_xts(&ctx_xts, mode, len, data_unit,\n                                        buf, buf);\n            if (ret != 0) {\n                goto exit;\n            }\n\n            if (memcmp(buf, aes_tests, len) != 0) {\n                ret = 1;\n                goto exit;\n            }\n\n            if (verbose != 0) {\n                mbedtls_printf(\"passed\\n\");\n            }\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"\\n\");\n        }\n\n        mbedtls_aes_xts_free(&ctx_xts);\n    }\n#endif /* MBEDTLS_CIPHER_MODE_XTS */\n\n    ret = 0;\n\nexit:\n    if (ret != 0 && verbose != 0) {\n        mbedtls_printf(\"failed\\n\");\n    }\n\n    mbedtls_aes_free(&ctx);\n\n    return ret;\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_AES_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/aesce.c",
    "content": "/*\n *  Armv8-A Cryptographic Extension support functions for Aarch64\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#if defined(__clang__) &&  (__clang_major__ >= 4)\n\n/* Ideally, we would simply use MBEDTLS_ARCH_IS_ARMV8_A in the following #if,\n * but that is defined by build_info.h, and we need this block to happen first. */\n#if defined(__ARM_ARCH)\n#if __ARM_ARCH >= 8\n#define MBEDTLS_AESCE_ARCH_IS_ARMV8_A\n#endif\n#endif\n\n#if defined(MBEDTLS_AESCE_ARCH_IS_ARMV8_A) && !defined(__ARM_FEATURE_CRYPTO)\n/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged.\n *\n * The intrinsic declaration are guarded by predefined ACLE macros in clang:\n * these are normally only enabled by the -march option on the command line.\n * By defining the macros ourselves we gain access to those declarations without\n * requiring -march on the command line.\n *\n * `arm_neon.h` is included by common.h, so we put these defines\n * at the top of this file, before any includes.\n */\n#define __ARM_FEATURE_CRYPTO 1\n/* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions\n *\n * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it\n * for older compilers.\n */\n#define __ARM_FEATURE_AES    1\n#define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG\n#endif\n\n#endif /* defined(__clang__) &&  (__clang_major__ >= 4) */\n\n#include <string.h>\n#include \"common.h\"\n\n#if defined(MBEDTLS_AESCE_C)\n\n#include \"aesce.h\"\n\n#if defined(MBEDTLS_AESCE_HAVE_CODE)\n\n/* Compiler version checks. */\n#if defined(__clang__)\n#   if defined(MBEDTLS_ARCH_IS_ARM32) && (__clang_major__ < 11)\n#       error \"Minimum version of Clang for MBEDTLS_AESCE_C on 32-bit Arm or Thumb is 11.0.\"\n#   elif defined(MBEDTLS_ARCH_IS_ARM64) && (__clang_major__ < 4)\n#       error \"Minimum version of Clang for MBEDTLS_AESCE_C on aarch64 is 4.0.\"\n#   endif\n#elif defined(__GNUC__)\n#   if __GNUC__ < 6\n#       error \"Minimum version of GCC for MBEDTLS_AESCE_C is 6.0.\"\n#   endif\n#elif defined(_MSC_VER)\n/* TODO: We haven't verified MSVC from 1920 to 1928. If someone verified that,\n *       please update this and document of `MBEDTLS_AESCE_C` in\n *       `mbedtls_config.h`. */\n#   if _MSC_VER < 1929\n#       error \"Minimum version of MSVC for MBEDTLS_AESCE_C is 2019 version 16.11.2.\"\n#   endif\n#elif defined(__ARMCC_VERSION)\n#    if defined(MBEDTLS_ARCH_IS_ARM32) && (__ARMCC_VERSION < 6200002)\n/* TODO: We haven't verified armclang for 32-bit Arm/Thumb prior to 6.20.\n * If someone verified that, please update this and document of\n * `MBEDTLS_AESCE_C` in `mbedtls_config.h`. */\n#         error \"Minimum version of armclang for MBEDTLS_AESCE_C on 32-bit Arm is 6.20.\"\n#    elif defined(MBEDTLS_ARCH_IS_ARM64) && (__ARMCC_VERSION < 6060000)\n#         error \"Minimum version of armclang for MBEDTLS_AESCE_C on aarch64 is 6.6.\"\n#    endif\n#endif\n\n#if !(defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_AES)) || \\\n    defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)\n#   if defined(__ARMCOMPILER_VERSION)\n#       if __ARMCOMPILER_VERSION <= 6090000\n#           error \"Must use minimum -march=armv8-a+crypto for MBEDTLS_AESCE_C\"\n#       else\n#           pragma clang attribute push (__attribute__((target(\"aes\"))), apply_to=function)\n#           define MBEDTLS_POP_TARGET_PRAGMA\n#       endif\n#   elif defined(__clang__)\n#       pragma clang attribute push (__attribute__((target(\"aes\"))), apply_to=function)\n#       define MBEDTLS_POP_TARGET_PRAGMA\n#   elif defined(__GNUC__)\n#       pragma GCC push_options\n#       pragma GCC target (\"+crypto\")\n#       define MBEDTLS_POP_TARGET_PRAGMA\n#   elif defined(_MSC_VER)\n#       error \"Required feature(__ARM_FEATURE_AES) is not enabled.\"\n#   endif\n#endif /* !(__ARM_FEATURE_CRYPTO || __ARM_FEATURE_AES) ||\n          MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG */\n\n#if defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)\n\n#include <sys/auxv.h>\n#if !defined(HWCAP_NEON)\n#define HWCAP_NEON  (1 << 12)\n#endif\n#if !defined(HWCAP2_AES)\n#define HWCAP2_AES  (1 << 0)\n#endif\n#if !defined(HWCAP_AES)\n#define HWCAP_AES   (1 << 3)\n#endif\n#if !defined(HWCAP_ASIMD)\n#define HWCAP_ASIMD (1 << 1)\n#endif\n\nsigned char mbedtls_aesce_has_support_result = -1;\n\n#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)\n/*\n * AES instruction support detection routine\n */\nint mbedtls_aesce_has_support_impl(void)\n{\n    /* To avoid many calls to getauxval, cache the result. This is\n     * thread-safe, because we store the result in a char so cannot\n     * be vulnerable to non-atomic updates.\n     * It is possible that we could end up setting result more than\n     * once, but that is harmless.\n     */\n    if (mbedtls_aesce_has_support_result == -1) {\n#if defined(MBEDTLS_ARCH_IS_ARM32)\n        unsigned long auxval  = getauxval(AT_HWCAP);\n        unsigned long auxval2 = getauxval(AT_HWCAP2);\n        if (((auxval  & HWCAP_NEON) == HWCAP_NEON) &&\n            ((auxval2 & HWCAP2_AES) == HWCAP2_AES)) {\n            mbedtls_aesce_has_support_result = 1;\n        } else {\n            mbedtls_aesce_has_support_result = 0;\n        }\n#else\n        unsigned long auxval = getauxval(AT_HWCAP);\n        if ((auxval & (HWCAP_ASIMD | HWCAP_AES)) ==\n            (HWCAP_ASIMD | HWCAP_AES)) {\n            mbedtls_aesce_has_support_result = 1;\n        } else {\n            mbedtls_aesce_has_support_result = 0;\n        }\n#endif\n    }\n    return mbedtls_aesce_has_support_result;\n}\n#endif\n\n#endif /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */\n\n/* Single round of AESCE encryption */\n#define AESCE_ENCRYPT_ROUND                   \\\n    block = vaeseq_u8(block, vld1q_u8(keys)); \\\n    block = vaesmcq_u8(block);                \\\n    keys += 16\n/* Two rounds of AESCE encryption */\n#define AESCE_ENCRYPT_ROUND_X2        AESCE_ENCRYPT_ROUND; AESCE_ENCRYPT_ROUND\n\nMBEDTLS_OPTIMIZE_FOR_PERFORMANCE\nstatic uint8x16_t aesce_encrypt_block(uint8x16_t block,\n                                      unsigned char *keys,\n                                      int rounds)\n{\n    /* 10, 12 or 14 rounds. Unroll loop. */\n    if (rounds == 10) {\n        goto rounds_10;\n    }\n    if (rounds == 12) {\n        goto rounds_12;\n    }\n    AESCE_ENCRYPT_ROUND_X2;\nrounds_12:\n    AESCE_ENCRYPT_ROUND_X2;\nrounds_10:\n    AESCE_ENCRYPT_ROUND_X2;\n    AESCE_ENCRYPT_ROUND_X2;\n    AESCE_ENCRYPT_ROUND_X2;\n    AESCE_ENCRYPT_ROUND_X2;\n    AESCE_ENCRYPT_ROUND;\n\n    /* AES AddRoundKey for the previous round.\n     * SubBytes, ShiftRows for the final round.  */\n    block = vaeseq_u8(block, vld1q_u8(keys));\n    keys += 16;\n\n    /* Final round: no MixColumns */\n\n    /* Final AddRoundKey */\n    block = veorq_u8(block, vld1q_u8(keys));\n\n    return block;\n}\n\n/* Single round of AESCE decryption\n *\n * AES AddRoundKey, SubBytes, ShiftRows\n *\n *      block = vaesdq_u8(block, vld1q_u8(keys));\n *\n * AES inverse MixColumns for the next round.\n *\n * This means that we switch the order of the inverse AddRoundKey and\n * inverse MixColumns operations. We have to do this as AddRoundKey is\n * done in an atomic instruction together with the inverses of SubBytes\n * and ShiftRows.\n *\n * It works because MixColumns is a linear operation over GF(2^8) and\n * AddRoundKey is an exclusive or, which is equivalent to addition over\n * GF(2^8). (The inverse of MixColumns needs to be applied to the\n * affected round keys separately which has been done when the\n * decryption round keys were calculated.)\n *\n *      block = vaesimcq_u8(block);\n */\n#define AESCE_DECRYPT_ROUND                   \\\n    block = vaesdq_u8(block, vld1q_u8(keys)); \\\n    block = vaesimcq_u8(block);               \\\n    keys += 16\n/* Two rounds of AESCE decryption */\n#define AESCE_DECRYPT_ROUND_X2        AESCE_DECRYPT_ROUND; AESCE_DECRYPT_ROUND\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\nstatic uint8x16_t aesce_decrypt_block(uint8x16_t block,\n                                      unsigned char *keys,\n                                      int rounds)\n{\n    /* 10, 12 or 14 rounds. Unroll loop. */\n    if (rounds == 10) {\n        goto rounds_10;\n    }\n    if (rounds == 12) {\n        goto rounds_12;\n    }\n    AESCE_DECRYPT_ROUND_X2;\nrounds_12:\n    AESCE_DECRYPT_ROUND_X2;\nrounds_10:\n    AESCE_DECRYPT_ROUND_X2;\n    AESCE_DECRYPT_ROUND_X2;\n    AESCE_DECRYPT_ROUND_X2;\n    AESCE_DECRYPT_ROUND_X2;\n    AESCE_DECRYPT_ROUND;\n\n    /* The inverses of AES AddRoundKey, SubBytes, ShiftRows finishing up the\n     * last full round. */\n    block = vaesdq_u8(block, vld1q_u8(keys));\n    keys += 16;\n\n    /* Inverse AddRoundKey for inverting the initial round key addition. */\n    block = veorq_u8(block, vld1q_u8(keys));\n\n    return block;\n}\n#endif\n\n/*\n * AES-ECB block en(de)cryption\n */\nint mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx,\n                            int mode,\n                            const unsigned char input[16],\n                            unsigned char output[16])\n{\n    uint8x16_t block = vld1q_u8(&input[0]);\n    unsigned char *keys = (unsigned char *) (ctx->buf + ctx->rk_offset);\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    if (mode == MBEDTLS_AES_DECRYPT) {\n        block = aesce_decrypt_block(block, keys, ctx->nr);\n    } else\n#else\n    (void) mode;\n#endif\n    {\n        block = aesce_encrypt_block(block, keys, ctx->nr);\n    }\n    vst1q_u8(&output[0], block);\n\n    return 0;\n}\n\n/*\n * Compute decryption round keys from encryption round keys\n */\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\nvoid mbedtls_aesce_inverse_key(unsigned char *invkey,\n                               const unsigned char *fwdkey,\n                               int nr)\n{\n    int i, j;\n    j = nr;\n    vst1q_u8(invkey, vld1q_u8(fwdkey + j * 16));\n    for (i = 1, j--; j > 0; i++, j--) {\n        vst1q_u8(invkey + i * 16,\n                 vaesimcq_u8(vld1q_u8(fwdkey + j * 16)));\n    }\n    vst1q_u8(invkey + i * 16, vld1q_u8(fwdkey + j * 16));\n\n}\n#endif\n\nstatic inline uint32_t aes_rot_word(uint32_t word)\n{\n    return (word << (32 - 8)) | (word >> 8);\n}\n\nstatic inline uint32_t aes_sub_word(uint32_t in)\n{\n    uint8x16_t v = vreinterpretq_u8_u32(vdupq_n_u32(in));\n    uint8x16_t zero = vdupq_n_u8(0);\n\n    /* vaeseq_u8 does both SubBytes and ShiftRows. Taking the first row yields\n     * the correct result as ShiftRows doesn't change the first row. */\n    v = vaeseq_u8(zero, v);\n    return vgetq_lane_u32(vreinterpretq_u32_u8(v), 0);\n}\n\n/*\n * Key expansion function\n */\nstatic void aesce_setkey_enc(unsigned char *rk,\n                             const unsigned char *key,\n                             const size_t key_bit_length)\n{\n    static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10,\n                                    0x20, 0x40, 0x80, 0x1b, 0x36 };\n    /* See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf\n     *   - Section 5, Nr = Nk + 6\n     *   - Section 5.2, the length of round keys is Nb*(Nr+1)\n     */\n    const size_t key_len_in_words = key_bit_length / 32;    /* Nk */\n    const size_t round_key_len_in_words = 4;                /* Nb */\n    const size_t rounds_needed = key_len_in_words + 6;      /* Nr */\n    const size_t round_keys_len_in_words =\n        round_key_len_in_words * (rounds_needed + 1);       /* Nb*(Nr+1) */\n    const uint32_t *rko_end = (uint32_t *) rk + round_keys_len_in_words;\n\n    memcpy(rk, key, key_len_in_words * 4);\n\n    for (uint32_t *rki = (uint32_t *) rk;\n         rki + key_len_in_words < rko_end;\n         rki += key_len_in_words) {\n\n        size_t iteration = (size_t) (rki - (uint32_t *) rk) / key_len_in_words;\n        uint32_t *rko;\n        rko = rki + key_len_in_words;\n        rko[0] = aes_rot_word(aes_sub_word(rki[key_len_in_words - 1]));\n        rko[0] ^= rcon[iteration] ^ rki[0];\n        rko[1] = rko[0] ^ rki[1];\n        rko[2] = rko[1] ^ rki[2];\n        rko[3] = rko[2] ^ rki[3];\n        if (rko + key_len_in_words > rko_end) {\n            /* Do not write overflow words.*/\n            continue;\n        }\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n        switch (key_bit_length) {\n            case 128:\n                break;\n            case 192:\n                rko[4] = rko[3] ^ rki[4];\n                rko[5] = rko[4] ^ rki[5];\n                break;\n            case 256:\n                rko[4] = aes_sub_word(rko[3]) ^ rki[4];\n                rko[5] = rko[4] ^ rki[5];\n                rko[6] = rko[5] ^ rki[6];\n                rko[7] = rko[6] ^ rki[7];\n                break;\n        }\n#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */\n    }\n}\n\n/*\n * Key expansion, wrapper\n */\nint mbedtls_aesce_setkey_enc(unsigned char *rk,\n                             const unsigned char *key,\n                             size_t bits)\n{\n    switch (bits) {\n        case 128:\n        case 192:\n        case 256:\n            aesce_setkey_enc(rk, key, bits);\n            break;\n        default:\n            return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;\n    }\n\n    return 0;\n}\n\n#if defined(MBEDTLS_GCM_C)\n\n#if defined(MBEDTLS_ARCH_IS_ARM32)\n\n#if defined(__clang__)\n/* On clang for A32/T32, work around some missing intrinsics and types which are listed in\n * [ACLE](https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#polynomial-1)\n * These are only required for GCM.\n */\n#define vreinterpretq_u64_p64(a) ((uint64x2_t) a)\n\ntypedef uint8x16_t poly128_t;\n\nstatic inline poly128_t vmull_p64(poly64_t a, poly64_t b)\n{\n    poly128_t r;\n    asm (\"vmull.p64 %[r], %[a], %[b]\" : [r] \"=w\" (r) : [a] \"w\" (a), [b] \"w\" (b) :);\n    return r;\n}\n\n/* This is set to cause some more missing intrinsics to be defined below */\n#define COMMON_MISSING_INTRINSICS\n\nstatic inline poly128_t vmull_high_p64(poly64x2_t a, poly64x2_t b)\n{\n    return vmull_p64((poly64_t) (vget_high_u64((uint64x2_t) a)),\n                     (poly64_t) (vget_high_u64((uint64x2_t) b)));\n}\n\n#endif /* defined(__clang__) */\n\nstatic inline uint8x16_t vrbitq_u8(uint8x16_t x)\n{\n    /* There is no vrbitq_u8 instruction in A32/T32, so provide\n     * an equivalent non-Neon implementation. Reverse bit order in each\n     * byte with 4x rbit, rev. */\n    asm (\"ldm  %[p], { r2-r5 } \\n\\t\"\n         \"rbit r2, r2          \\n\\t\"\n         \"rev  r2, r2          \\n\\t\"\n         \"rbit r3, r3          \\n\\t\"\n         \"rev  r3, r3          \\n\\t\"\n         \"rbit r4, r4          \\n\\t\"\n         \"rev  r4, r4          \\n\\t\"\n         \"rbit r5, r5          \\n\\t\"\n         \"rev  r5, r5          \\n\\t\"\n         \"stm  %[p], { r2-r5 } \\n\\t\"\n         :\n         /* Output: 16 bytes of memory pointed to by &x */\n         \"+m\" (*(uint8_t(*)[16]) &x)\n         :\n         [p] \"r\" (&x)\n         :\n         \"r2\", \"r3\", \"r4\", \"r5\"\n         );\n    return x;\n}\n\n#endif /* defined(MBEDTLS_ARCH_IS_ARM32) */\n\n#if defined(MBEDTLS_COMPILER_IS_GCC) && __GNUC__ == 5\n/* Some intrinsics are not available for GCC 5.X. */\n#define COMMON_MISSING_INTRINSICS\n#endif /* MBEDTLS_COMPILER_IS_GCC && __GNUC__ == 5 */\n\n\n#if defined(COMMON_MISSING_INTRINSICS)\n\n/* Missing intrinsics common to both GCC 5, and Clang on 32-bit */\n\n#define vreinterpretq_p64_u8(a)  ((poly64x2_t) a)\n#define vreinterpretq_u8_p128(a) ((uint8x16_t) a)\n\nstatic inline poly64x1_t vget_low_p64(poly64x2_t a)\n{\n    uint64x1_t r = vget_low_u64(vreinterpretq_u64_p64(a));\n    return (poly64x1_t) r;\n\n}\n\n#endif /* COMMON_MISSING_INTRINSICS */\n\n/* vmull_p64/vmull_high_p64 wrappers.\n *\n * Older compilers miss some intrinsic functions for `poly*_t`. We use\n * uint8x16_t and uint8x16x3_t as input/output parameters.\n */\n#if defined(MBEDTLS_COMPILER_IS_GCC)\n/* GCC reports incompatible type error without cast. GCC think poly64_t and\n * poly64x1_t are different, that is different with MSVC and Clang. */\n#define MBEDTLS_VMULL_P64(a, b) vmull_p64((poly64_t) a, (poly64_t) b)\n#else\n/* MSVC reports `error C2440: 'type cast'` with cast. Clang does not report\n * error with/without cast. And I think poly64_t and poly64x1_t are same, no\n * cast for clang also. */\n#define MBEDTLS_VMULL_P64(a, b) vmull_p64(a, b)\n#endif /* MBEDTLS_COMPILER_IS_GCC */\n\nstatic inline uint8x16_t pmull_low(uint8x16_t a, uint8x16_t b)\n{\n\n    return vreinterpretq_u8_p128(\n        MBEDTLS_VMULL_P64(\n            (poly64_t) vget_low_p64(vreinterpretq_p64_u8(a)),\n            (poly64_t) vget_low_p64(vreinterpretq_p64_u8(b))\n            ));\n}\n\nstatic inline uint8x16_t pmull_high(uint8x16_t a, uint8x16_t b)\n{\n    return vreinterpretq_u8_p128(\n        vmull_high_p64(vreinterpretq_p64_u8(a),\n                       vreinterpretq_p64_u8(b)));\n}\n\n/* GHASH does 128b polynomial multiplication on block in GF(2^128) defined by\n * `x^128 + x^7 + x^2 + x + 1`.\n *\n * Arm64 only has 64b->128b polynomial multipliers, we need to do 4 64b\n * multiplies to generate a 128b.\n *\n * `poly_mult_128` executes polynomial multiplication and outputs 256b that\n * represented by 3 128b due to code size optimization.\n *\n * Output layout:\n * |            |             |             |\n * |------------|-------------|-------------|\n * | ret.val[0] | h3:h2:00:00 | high   128b |\n * | ret.val[1] |   :m2:m1:00 | middle 128b |\n * | ret.val[2] |   :  :l1:l0 | low    128b |\n */\nstatic inline uint8x16x3_t poly_mult_128(uint8x16_t a, uint8x16_t b)\n{\n    uint8x16x3_t ret;\n    uint8x16_t h, m, l; /* retval high/middle/low */\n    uint8x16_t c, d, e;\n\n    h = pmull_high(a, b);                       /* h3:h2:00:00 = a1*b1 */\n    l = pmull_low(a, b);                        /*   :  :l1:l0 = a0*b0 */\n    c = vextq_u8(b, b, 8);                      /*      :c1:c0 = b0:b1 */\n    d = pmull_high(a, c);                       /*   :d2:d1:00 = a1*b0 */\n    e = pmull_low(a, c);                        /*   :e2:e1:00 = a0*b1 */\n    m = veorq_u8(d, e);                         /*   :m2:m1:00 = d + e */\n\n    ret.val[0] = h;\n    ret.val[1] = m;\n    ret.val[2] = l;\n    return ret;\n}\n\n/*\n * Modulo reduction.\n *\n * See: https://www.researchgate.net/publication/285612706_Implementing_GCM_on_ARMv8\n *\n * Section 4.3\n *\n * Modular reduction is slightly more complex. Write the GCM modulus as f(z) =\n * z^128 +r(z), where r(z) = z^7+z^2+z+ 1. The well known approach is to\n * consider that z^128 ≡r(z) (mod z^128 +r(z)), allowing us to write the 256-bit\n * operand to be reduced as a(z) = h(z)z^128 +l(z)≡h(z)r(z) + l(z). That is, we\n * simply multiply the higher part of the operand by r(z) and add it to l(z). If\n * the result is still larger than 128 bits, we reduce again.\n */\nstatic inline uint8x16_t poly_mult_reduce(uint8x16x3_t input)\n{\n    uint8x16_t const ZERO = vdupq_n_u8(0);\n\n    uint64x2_t r = vreinterpretq_u64_u8(vdupq_n_u8(0x87));\n#if defined(__GNUC__)\n    /* use 'asm' as an optimisation barrier to prevent loading MODULO from\n     * memory. It is for GNUC compatible compilers.\n     */\n    asm volatile (\"\" : \"+w\" (r));\n#endif\n    uint8x16_t const MODULO = vreinterpretq_u8_u64(vshrq_n_u64(r, 64 - 8));\n    uint8x16_t h, m, l; /* input high/middle/low 128b */\n    uint8x16_t c, d, e, f, g, n, o;\n    h = input.val[0];            /* h3:h2:00:00                          */\n    m = input.val[1];            /*   :m2:m1:00                          */\n    l = input.val[2];            /*   :  :l1:l0                          */\n    c = pmull_high(h, MODULO);   /*   :c2:c1:00 = reduction of h3        */\n    d = pmull_low(h, MODULO);    /*   :  :d1:d0 = reduction of h2        */\n    e = veorq_u8(c, m);          /*   :e2:e1:00 = m2:m1:00 + c2:c1:00    */\n    f = pmull_high(e, MODULO);   /*   :  :f1:f0 = reduction of e2        */\n    g = vextq_u8(ZERO, e, 8);    /*   :  :g1:00 = e1:00                  */\n    n = veorq_u8(d, l);          /*   :  :n1:n0 = d1:d0 + l1:l0          */\n    o = veorq_u8(n, f);          /*       o1:o0 = f1:f0 + n1:n0          */\n    return veorq_u8(o, g);       /*             = o1:o0 + g1:00          */\n}\n\n/*\n * GCM multiplication: c = a times b in GF(2^128)\n */\nvoid mbedtls_aesce_gcm_mult(unsigned char c[16],\n                            const unsigned char a[16],\n                            const unsigned char b[16])\n{\n    uint8x16_t va, vb, vc;\n    va = vrbitq_u8(vld1q_u8(&a[0]));\n    vb = vrbitq_u8(vld1q_u8(&b[0]));\n    vc = vrbitq_u8(poly_mult_reduce(poly_mult_128(va, vb)));\n    vst1q_u8(&c[0], vc);\n}\n\n#endif /* MBEDTLS_GCM_C */\n\n#if defined(MBEDTLS_POP_TARGET_PRAGMA)\n#if defined(__clang__)\n#pragma clang attribute pop\n#elif defined(__GNUC__)\n#pragma GCC pop_options\n#endif\n#undef MBEDTLS_POP_TARGET_PRAGMA\n#endif\n\n#endif /* MBEDTLS_AESCE_HAVE_CODE */\n\n#endif /* MBEDTLS_AESCE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/aesce.h",
    "content": "/**\n * \\file aesce.h\n *\n * \\brief Support hardware AES acceleration on Armv8-A processors with\n *        the Armv8-A Cryptographic Extension.\n *\n * \\warning These functions are only for internal use by other library\n *          functions; you must not call them directly.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_AESCE_H\n#define MBEDTLS_AESCE_H\n\n#include \"mbedtls/build_info.h\"\n#include \"common.h\"\n\n#include \"mbedtls/aes.h\"\n\n\n#if defined(MBEDTLS_AESCE_C) \\\n    && defined(MBEDTLS_ARCH_IS_ARMV8_A) && defined(MBEDTLS_HAVE_NEON_INTRINSICS) \\\n    && (defined(MBEDTLS_COMPILER_IS_GCC) || defined(__clang__) || defined(MSC_VER))\n\n/* MBEDTLS_AESCE_HAVE_CODE is defined if we have a suitable target platform, and a\n * potentially suitable compiler (compiler version & flags are not checked when defining\n * this). */\n#define MBEDTLS_AESCE_HAVE_CODE\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)\n\nextern signed char mbedtls_aesce_has_support_result;\n\n/**\n * \\brief          Internal function to detect the crypto extension in CPUs.\n *\n * \\return         1 if CPU has support for the feature, 0 otherwise\n */\nint mbedtls_aesce_has_support_impl(void);\n\n#define MBEDTLS_AESCE_HAS_SUPPORT() (mbedtls_aesce_has_support_result == -1 ? \\\n                                     mbedtls_aesce_has_support_impl() : \\\n                                     mbedtls_aesce_has_support_result)\n\n#else /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */\n\n/* If we are not on Linux, we can't detect support so assume that it's supported.\n * Similarly, assume support if MBEDTLS_AES_USE_HARDWARE_ONLY is set.\n */\n#define MBEDTLS_AESCE_HAS_SUPPORT() 1\n\n#endif /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */\n\n/**\n * \\brief          Internal AES-ECB block encryption and decryption\n *\n * \\warning        This assumes that the context specifies either 10, 12 or 14\n *                 rounds and will behave incorrectly if this is not the case.\n *\n * \\param ctx      AES context\n * \\param mode     MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT\n * \\param input    16-byte input block\n * \\param output   16-byte output block\n *\n * \\return         0 on success (cannot fail)\n */\nint mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx,\n                            int mode,\n                            const unsigned char input[16],\n                            unsigned char output[16]);\n\n/**\n * \\brief          Internal GCM multiplication: c = a * b in GF(2^128)\n *\n * \\note           This function is only for internal use by other library\n *                 functions; you must not call it directly.\n *\n * \\param c        Result\n * \\param a        First operand\n * \\param b        Second operand\n *\n * \\note           Both operands and result are bit strings interpreted as\n *                 elements of GF(2^128) as per the GCM spec.\n */\nvoid mbedtls_aesce_gcm_mult(unsigned char c[16],\n                            const unsigned char a[16],\n                            const unsigned char b[16]);\n\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n/**\n * \\brief           Internal round key inversion. This function computes\n *                  decryption round keys from the encryption round keys.\n *\n * \\param invkey    Round keys for the equivalent inverse cipher\n * \\param fwdkey    Original round keys (for encryption)\n * \\param nr        Number of rounds (that is, number of round keys minus one)\n */\nvoid mbedtls_aesce_inverse_key(unsigned char *invkey,\n                               const unsigned char *fwdkey,\n                               int nr);\n#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */\n\n/**\n * \\brief           Internal key expansion for encryption\n *\n * \\param rk        Destination buffer where the round keys are written\n * \\param key       Encryption key\n * \\param bits      Key size in bits (must be 128, 192 or 256)\n *\n * \\return          0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH\n */\nint mbedtls_aesce_setkey_enc(unsigned char *rk,\n                             const unsigned char *key,\n                             size_t bits);\n\n#ifdef __cplusplus\n}\n#endif\n\n#else\n\n#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) && defined(MBEDTLS_ARCH_IS_ARMV8_A)\n#error \"AES hardware acceleration not supported on this platform / compiler\"\n#endif\n\n#endif /* MBEDTLS_AESCE_C && MBEDTLS_ARCH_IS_ARMV8_A && MBEDTLS_HAVE_NEON_INTRINSICS &&\n          (MBEDTLS_COMPILER_IS_GCC || __clang__ || MSC_VER) */\n\n#endif /* MBEDTLS_AESCE_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/aesni.c",
    "content": "/*\n *  AES-NI support functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n * [AES-WP] https://www.intel.com/content/www/us/en/developer/articles/tool/intel-advanced-encryption-standard-aes-instructions-set.html\n * [CLMUL-WP] https://www.intel.com/content/www/us/en/develop/download/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode.html\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_AESNI_C)\n\n#include \"aesni.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_AESNI_HAVE_CODE)\n\n#if MBEDTLS_AESNI_HAVE_CODE == 2\n#if defined(__GNUC__)\n#include <cpuid.h>\n#elif defined(_MSC_VER)\n#include <intrin.h>\n#else\n#error \"`__cpuid` required by MBEDTLS_AESNI_C is not supported by the compiler\"\n#endif\n#include <immintrin.h>\n#endif\n\n#if defined(MBEDTLS_ARCH_IS_X86)\n#if defined(MBEDTLS_COMPILER_IS_GCC)\n#pragma GCC push_options\n#pragma GCC target (\"pclmul,sse2,aes\")\n#define MBEDTLS_POP_TARGET_PRAGMA\n#elif defined(__clang__) && (__clang_major__ >= 5)\n#pragma clang attribute push (__attribute__((target(\"pclmul,sse2,aes\"))), apply_to=function)\n#define MBEDTLS_POP_TARGET_PRAGMA\n#endif\n#endif\n\n#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)\n/*\n * AES-NI support detection routine\n */\nint mbedtls_aesni_has_support(unsigned int what)\n{\n    /* To avoid a race condition, tell the compiler that the assignment\n     * `done = 1` and the assignment to `c` may not be reordered.\n     * https://github.com/Mbed-TLS/mbedtls/issues/9840\n     *\n     * Note that we may also be worried about memory access reordering,\n     * but fortunately the x86 memory model is not too wild: stores\n     * from the same thread are observed consistently by other threads.\n     * (See example 8-1 in Sewell et al., \"x86-TSO: A Rigorous and Usable\n     * Programmer’s Model for x86 Multiprocessors\", CACM, 2010,\n     * https://www.cl.cam.ac.uk/~pes20/weakmemory/cacm.pdf)\n     */\n    static volatile int done = 0;\n    static volatile unsigned int c = 0;\n\n    if (!done) {\n#if MBEDTLS_AESNI_HAVE_CODE == 2\n        static int info[4] = { 0, 0, 0, 0 };\n#if defined(_MSC_VER)\n        __cpuid(info, 1);\n#else\n        __cpuid(1, info[0], info[1], info[2], info[3]);\n#endif\n        c = info[2];\n#else /* AESNI using asm */\n        asm (\"movl  $1, %%eax   \\n\\t\"\n             \"cpuid             \\n\\t\"\n             : \"=c\" (c)\n             :\n             : \"eax\", \"ebx\", \"edx\");\n#endif /* MBEDTLS_AESNI_HAVE_CODE */\n        done = 1;\n    }\n\n    return (c & what) != 0;\n}\n#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */\n\n#if MBEDTLS_AESNI_HAVE_CODE == 2\n\n/*\n * AES-NI AES-ECB block en(de)cryption\n */\nint mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx,\n                            int mode,\n                            const unsigned char input[16],\n                            unsigned char output[16])\n{\n    const __m128i *rk = (const __m128i *) (ctx->buf + ctx->rk_offset);\n    unsigned nr = ctx->nr; // Number of remaining rounds\n\n    // Load round key 0\n    __m128i state;\n    memcpy(&state, input, 16);\n    state = _mm_xor_si128(state, rk[0]);  // state ^= *rk;\n    ++rk;\n    --nr;\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    if (mode == MBEDTLS_AES_DECRYPT) {\n        while (nr != 0) {\n            state = _mm_aesdec_si128(state, *rk);\n            ++rk;\n            --nr;\n        }\n        state = _mm_aesdeclast_si128(state, *rk);\n    } else\n#else\n    (void) mode;\n#endif\n    {\n        while (nr != 0) {\n            state = _mm_aesenc_si128(state, *rk);\n            ++rk;\n            --nr;\n        }\n        state = _mm_aesenclast_si128(state, *rk);\n    }\n\n    memcpy(output, &state, 16);\n    return 0;\n}\n\n/*\n * GCM multiplication: c = a times b in GF(2^128)\n * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5.\n */\n\nstatic void gcm_clmul(const __m128i aa, const __m128i bb,\n                      __m128i *cc, __m128i *dd)\n{\n    /*\n     * Caryless multiplication dd:cc = aa * bb\n     * using [CLMUL-WP] algorithm 1 (p. 12).\n     */\n    *cc = _mm_clmulepi64_si128(aa, bb, 0x00); // a0*b0 = c1:c0\n    *dd = _mm_clmulepi64_si128(aa, bb, 0x11); // a1*b1 = d1:d0\n    __m128i ee = _mm_clmulepi64_si128(aa, bb, 0x10); // a0*b1 = e1:e0\n    __m128i ff = _mm_clmulepi64_si128(aa, bb, 0x01); // a1*b0 = f1:f0\n    ff = _mm_xor_si128(ff, ee);                      // e1+f1:e0+f0\n    ee = ff;                                         // e1+f1:e0+f0\n    ff = _mm_srli_si128(ff, 8);                      // 0:e1+f1\n    ee = _mm_slli_si128(ee, 8);                      // e0+f0:0\n    *dd = _mm_xor_si128(*dd, ff);                    // d1:d0+e1+f1\n    *cc = _mm_xor_si128(*cc, ee);                    // c1+e0+f0:c0\n}\n\nstatic void gcm_shift(__m128i *cc, __m128i *dd)\n{\n    /* [CMUCL-WP] Algorithm 5 Step 1: shift cc:dd one bit to the left,\n     * taking advantage of [CLMUL-WP] eq 27 (p. 18). */\n    //                                        // *cc = r1:r0\n    //                                        // *dd = r3:r2\n    __m128i cc_lo = _mm_slli_epi64(*cc, 1);   // r1<<1:r0<<1\n    __m128i dd_lo = _mm_slli_epi64(*dd, 1);   // r3<<1:r2<<1\n    __m128i cc_hi = _mm_srli_epi64(*cc, 63);  // r1>>63:r0>>63\n    __m128i dd_hi = _mm_srli_epi64(*dd, 63);  // r3>>63:r2>>63\n    __m128i xmm5 = _mm_srli_si128(cc_hi, 8);  // 0:r1>>63\n    cc_hi = _mm_slli_si128(cc_hi, 8);         // r0>>63:0\n    dd_hi = _mm_slli_si128(dd_hi, 8);         // 0:r1>>63\n\n    *cc = _mm_or_si128(cc_lo, cc_hi);         // r1<<1|r0>>63:r0<<1\n    *dd = _mm_or_si128(_mm_or_si128(dd_lo, dd_hi), xmm5); // r3<<1|r2>>62:r2<<1|r1>>63\n}\n\nstatic __m128i gcm_reduce(__m128i xx)\n{\n    //                                            // xx = x1:x0\n    /* [CLMUL-WP] Algorithm 5 Step 2 */\n    __m128i aa = _mm_slli_epi64(xx, 63);          // x1<<63:x0<<63 = stuff:a\n    __m128i bb = _mm_slli_epi64(xx, 62);          // x1<<62:x0<<62 = stuff:b\n    __m128i cc = _mm_slli_epi64(xx, 57);          // x1<<57:x0<<57 = stuff:c\n    __m128i dd = _mm_slli_si128(_mm_xor_si128(_mm_xor_si128(aa, bb), cc), 8); // a+b+c:0\n    return _mm_xor_si128(dd, xx);                 // x1+a+b+c:x0 = d:x0\n}\n\nstatic __m128i gcm_mix(__m128i dx)\n{\n    /* [CLMUL-WP] Algorithm 5 Steps 3 and 4 */\n    __m128i ee = _mm_srli_epi64(dx, 1);           // e1:x0>>1 = e1:e0'\n    __m128i ff = _mm_srli_epi64(dx, 2);           // f1:x0>>2 = f1:f0'\n    __m128i gg = _mm_srli_epi64(dx, 7);           // g1:x0>>7 = g1:g0'\n\n    // e0'+f0'+g0' is almost e0+f0+g0, except for some missing\n    // bits carried from d. Now get those bits back in.\n    __m128i eh = _mm_slli_epi64(dx, 63);          // d<<63:stuff\n    __m128i fh = _mm_slli_epi64(dx, 62);          // d<<62:stuff\n    __m128i gh = _mm_slli_epi64(dx, 57);          // d<<57:stuff\n    __m128i hh = _mm_srli_si128(_mm_xor_si128(_mm_xor_si128(eh, fh), gh), 8); // 0:missing bits of d\n\n    return _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_xor_si128(ee, ff), gg), hh), dx);\n}\n\nvoid mbedtls_aesni_gcm_mult(unsigned char c[16],\n                            const unsigned char a[16],\n                            const unsigned char b[16])\n{\n    __m128i aa = { 0 }, bb = { 0 }, cc, dd;\n\n    /* The inputs are in big-endian order, so byte-reverse them */\n    for (size_t i = 0; i < 16; i++) {\n        ((uint8_t *) &aa)[i] = a[15 - i];\n        ((uint8_t *) &bb)[i] = b[15 - i];\n    }\n\n    gcm_clmul(aa, bb, &cc, &dd);\n    gcm_shift(&cc, &dd);\n    /*\n     * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1\n     * using [CLMUL-WP] algorithm 5 (p. 18).\n     * Currently dd:cc holds x3:x2:x1:x0 (already shifted).\n     */\n    __m128i dx = gcm_reduce(cc);\n    __m128i xh = gcm_mix(dx);\n    cc = _mm_xor_si128(xh, dd); // x3+h1:x2+h0\n\n    /* Now byte-reverse the outputs */\n    for (size_t i = 0; i < 16; i++) {\n        c[i] = ((uint8_t *) &cc)[15 - i];\n    }\n\n    return;\n}\n\n/*\n * Compute decryption round keys from encryption round keys\n */\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\nvoid mbedtls_aesni_inverse_key(unsigned char *invkey,\n                               const unsigned char *fwdkey, int nr)\n{\n    __m128i *ik = (__m128i *) invkey;\n    const __m128i *fk = (const __m128i *) fwdkey + nr;\n\n    *ik = *fk;\n    for (--fk, ++ik; fk > (const __m128i *) fwdkey; --fk, ++ik) {\n        *ik = _mm_aesimc_si128(*fk);\n    }\n    *ik = *fk;\n}\n#endif\n\n/*\n * Key expansion, 128-bit case\n */\nstatic __m128i aesni_set_rk_128(__m128i state, __m128i xword)\n{\n    /*\n     * Finish generating the next round key.\n     *\n     * On entry state is r3:r2:r1:r0 and xword is X:stuff:stuff:stuff\n     * with X = rot( sub( r3 ) ) ^ RCON (obtained with AESKEYGENASSIST).\n     *\n     * On exit, xword is r7:r6:r5:r4\n     * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3\n     * and this is returned, to be written to the round key buffer.\n     */\n    xword = _mm_shuffle_epi32(xword, 0xff);   // X:X:X:X\n    xword = _mm_xor_si128(xword, state);      // X+r3:X+r2:X+r1:r4\n    state = _mm_slli_si128(state, 4);         // r2:r1:r0:0\n    xword = _mm_xor_si128(xword, state);      // X+r3+r2:X+r2+r1:r5:r4\n    state = _mm_slli_si128(state, 4);         // r1:r0:0:0\n    xword = _mm_xor_si128(xword, state);      // X+r3+r2+r1:r6:r5:r4\n    state = _mm_slli_si128(state, 4);         // r0:0:0:0\n    state = _mm_xor_si128(xword, state);      // r7:r6:r5:r4\n    return state;\n}\n\nstatic void aesni_setkey_enc_128(unsigned char *rk_bytes,\n                                 const unsigned char *key)\n{\n    __m128i *rk = (__m128i *) rk_bytes;\n\n    memcpy(&rk[0], key, 16);\n    rk[1] = aesni_set_rk_128(rk[0], _mm_aeskeygenassist_si128(rk[0], 0x01));\n    rk[2] = aesni_set_rk_128(rk[1], _mm_aeskeygenassist_si128(rk[1], 0x02));\n    rk[3] = aesni_set_rk_128(rk[2], _mm_aeskeygenassist_si128(rk[2], 0x04));\n    rk[4] = aesni_set_rk_128(rk[3], _mm_aeskeygenassist_si128(rk[3], 0x08));\n    rk[5] = aesni_set_rk_128(rk[4], _mm_aeskeygenassist_si128(rk[4], 0x10));\n    rk[6] = aesni_set_rk_128(rk[5], _mm_aeskeygenassist_si128(rk[5], 0x20));\n    rk[7] = aesni_set_rk_128(rk[6], _mm_aeskeygenassist_si128(rk[6], 0x40));\n    rk[8] = aesni_set_rk_128(rk[7], _mm_aeskeygenassist_si128(rk[7], 0x80));\n    rk[9] = aesni_set_rk_128(rk[8], _mm_aeskeygenassist_si128(rk[8], 0x1B));\n    rk[10] = aesni_set_rk_128(rk[9], _mm_aeskeygenassist_si128(rk[9], 0x36));\n}\n\n/*\n * Key expansion, 192-bit case\n */\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic void aesni_set_rk_192(__m128i *state0, __m128i *state1, __m128i xword,\n                             unsigned char *rk)\n{\n    /*\n     * Finish generating the next 6 quarter-keys.\n     *\n     * On entry state0 is r3:r2:r1:r0, state1 is stuff:stuff:r5:r4\n     * and xword is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON\n     * (obtained with AESKEYGENASSIST).\n     *\n     * On exit, state0 is r9:r8:r7:r6 and state1 is stuff:stuff:r11:r10\n     * and those are written to the round key buffer.\n     */\n    xword = _mm_shuffle_epi32(xword, 0x55);   // X:X:X:X\n    xword = _mm_xor_si128(xword, *state0);    // X+r3:X+r2:X+r1:X+r0\n    *state0 = _mm_slli_si128(*state0, 4);     // r2:r1:r0:0\n    xword = _mm_xor_si128(xword, *state0);    // X+r3+r2:X+r2+r1:X+r1+r0:X+r0\n    *state0 = _mm_slli_si128(*state0, 4);     // r1:r0:0:0\n    xword = _mm_xor_si128(xword, *state0);    // X+r3+r2+r1:X+r2+r1+r0:X+r1+r0:X+r0\n    *state0 = _mm_slli_si128(*state0, 4);     // r0:0:0:0\n    xword = _mm_xor_si128(xword, *state0);    // X+r3+r2+r1+r0:X+r2+r1+r0:X+r1+r0:X+r0\n    *state0 = xword;                          // = r9:r8:r7:r6\n\n    xword = _mm_shuffle_epi32(xword, 0xff);   // r9:r9:r9:r9\n    xword = _mm_xor_si128(xword, *state1);    // stuff:stuff:r9+r5:r9+r4\n    *state1 = _mm_slli_si128(*state1, 4);     // stuff:stuff:r4:0\n    xword = _mm_xor_si128(xword, *state1);    // stuff:stuff:r9+r5+r4:r9+r4\n    *state1 = xword;                          // = stuff:stuff:r11:r10\n\n    /* Store state0 and the low half of state1 into rk, which is conceptually\n     * an array of 24-byte elements. Since 24 is not a multiple of 16,\n     * rk is not necessarily aligned so just `*rk = *state0` doesn't work. */\n    memcpy(rk, state0, 16);\n    memcpy(rk + 16, state1, 8);\n}\n\nstatic void aesni_setkey_enc_192(unsigned char *rk,\n                                 const unsigned char *key)\n{\n    /* First round: use original key */\n    memcpy(rk, key, 24);\n    /* aes.c guarantees that rk is aligned on a 16-byte boundary. */\n    __m128i state0 = ((__m128i *) rk)[0];\n    __m128i state1 = _mm_loadl_epi64(((__m128i *) rk) + 1);\n\n    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x01), rk + 24 * 1);\n    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x02), rk + 24 * 2);\n    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x04), rk + 24 * 3);\n    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x08), rk + 24 * 4);\n    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x10), rk + 24 * 5);\n    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x20), rk + 24 * 6);\n    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x40), rk + 24 * 7);\n    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x80), rk + 24 * 8);\n}\n#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */\n\n/*\n * Key expansion, 256-bit case\n */\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic void aesni_set_rk_256(__m128i state0, __m128i state1, __m128i xword,\n                             __m128i *rk0, __m128i *rk1)\n{\n    /*\n     * Finish generating the next two round keys.\n     *\n     * On entry state0 is r3:r2:r1:r0, state1 is r7:r6:r5:r4 and\n     * xword is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON\n     * (obtained with AESKEYGENASSIST).\n     *\n     * On exit, *rk0 is r11:r10:r9:r8 and *rk1 is r15:r14:r13:r12\n     */\n    xword = _mm_shuffle_epi32(xword, 0xff);\n    xword = _mm_xor_si128(xword, state0);\n    state0 = _mm_slli_si128(state0, 4);\n    xword = _mm_xor_si128(xword, state0);\n    state0 = _mm_slli_si128(state0, 4);\n    xword = _mm_xor_si128(xword, state0);\n    state0 = _mm_slli_si128(state0, 4);\n    state0 = _mm_xor_si128(state0, xword);\n    *rk0 = state0;\n\n    /* Set xword to stuff:Y:stuff:stuff with Y = subword( r11 )\n     * and proceed to generate next round key from there */\n    xword = _mm_aeskeygenassist_si128(state0, 0x00);\n    xword = _mm_shuffle_epi32(xword, 0xaa);\n    xword = _mm_xor_si128(xword, state1);\n    state1 = _mm_slli_si128(state1, 4);\n    xword = _mm_xor_si128(xword, state1);\n    state1 = _mm_slli_si128(state1, 4);\n    xword = _mm_xor_si128(xword, state1);\n    state1 = _mm_slli_si128(state1, 4);\n    state1 = _mm_xor_si128(state1, xword);\n    *rk1 = state1;\n}\n\nstatic void aesni_setkey_enc_256(unsigned char *rk_bytes,\n                                 const unsigned char *key)\n{\n    __m128i *rk = (__m128i *) rk_bytes;\n\n    memcpy(&rk[0], key, 16);\n    memcpy(&rk[1], key + 16, 16);\n\n    /*\n     * Main \"loop\" - Generating one more key than necessary,\n     * see definition of mbedtls_aes_context.buf\n     */\n    aesni_set_rk_256(rk[0], rk[1], _mm_aeskeygenassist_si128(rk[1], 0x01), &rk[2], &rk[3]);\n    aesni_set_rk_256(rk[2], rk[3], _mm_aeskeygenassist_si128(rk[3], 0x02), &rk[4], &rk[5]);\n    aesni_set_rk_256(rk[4], rk[5], _mm_aeskeygenassist_si128(rk[5], 0x04), &rk[6], &rk[7]);\n    aesni_set_rk_256(rk[6], rk[7], _mm_aeskeygenassist_si128(rk[7], 0x08), &rk[8], &rk[9]);\n    aesni_set_rk_256(rk[8], rk[9], _mm_aeskeygenassist_si128(rk[9], 0x10), &rk[10], &rk[11]);\n    aesni_set_rk_256(rk[10], rk[11], _mm_aeskeygenassist_si128(rk[11], 0x20), &rk[12], &rk[13]);\n    aesni_set_rk_256(rk[12], rk[13], _mm_aeskeygenassist_si128(rk[13], 0x40), &rk[14], &rk[15]);\n}\n#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */\n\n#if defined(MBEDTLS_POP_TARGET_PRAGMA)\n#if defined(__clang__)\n#pragma clang attribute pop\n#elif defined(__GNUC__)\n#pragma GCC pop_options\n#endif\n#undef MBEDTLS_POP_TARGET_PRAGMA\n#endif\n\n#else /* MBEDTLS_AESNI_HAVE_CODE == 1 */\n\n#if defined(__has_feature)\n#if __has_feature(memory_sanitizer)\n#warning \\\n    \"MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code.\"\n#endif\n#endif\n\n/*\n * Binutils needs to be at least 2.19 to support AES-NI instructions.\n * Unfortunately, a lot of users have a lower version now (2014-04).\n * Emit bytecode directly in order to support \"old\" version of gas.\n *\n * Opcodes from the Intel architecture reference manual, vol. 3.\n * We always use registers, so we don't need prefixes for memory operands.\n * Operand macros are in gas order (src, dst) as opposed to Intel order\n * (dst, src) in order to blend better into the surrounding assembly code.\n */\n#define AESDEC(regs)      \".byte 0x66,0x0F,0x38,0xDE,\" regs \"\\n\\t\"\n#define AESDECLAST(regs)  \".byte 0x66,0x0F,0x38,0xDF,\" regs \"\\n\\t\"\n#define AESENC(regs)      \".byte 0x66,0x0F,0x38,0xDC,\" regs \"\\n\\t\"\n#define AESENCLAST(regs)  \".byte 0x66,0x0F,0x38,0xDD,\" regs \"\\n\\t\"\n#define AESIMC(regs)      \".byte 0x66,0x0F,0x38,0xDB,\" regs \"\\n\\t\"\n#define AESKEYGENA(regs, imm)  \".byte 0x66,0x0F,0x3A,0xDF,\" regs \",\" imm \"\\n\\t\"\n#define PCLMULQDQ(regs, imm)   \".byte 0x66,0x0F,0x3A,0x44,\" regs \",\" imm \"\\n\\t\"\n\n#define xmm0_xmm0   \"0xC0\"\n#define xmm0_xmm1   \"0xC8\"\n#define xmm0_xmm2   \"0xD0\"\n#define xmm0_xmm3   \"0xD8\"\n#define xmm0_xmm4   \"0xE0\"\n#define xmm1_xmm0   \"0xC1\"\n#define xmm1_xmm2   \"0xD1\"\n\n/*\n * AES-NI AES-ECB block en(de)cryption\n */\nint mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx,\n                            int mode,\n                            const unsigned char input[16],\n                            unsigned char output[16])\n{\n    asm (\"movdqu    (%3), %%xmm0    \\n\\t\" // load input\n         \"movdqu    (%1), %%xmm1    \\n\\t\" // load round key 0\n         \"pxor      %%xmm1, %%xmm0  \\n\\t\" // round 0\n         \"add       $16, %1         \\n\\t\" // point to next round key\n         \"subl      $1, %0          \\n\\t\" // normal rounds = nr - 1\n         \"test      %2, %2          \\n\\t\" // mode?\n         \"jz        2f              \\n\\t\" // 0 = decrypt\n\n         \"1:                        \\n\\t\" // encryption loop\n         \"movdqu    (%1), %%xmm1    \\n\\t\" // load round key\n         AESENC(xmm1_xmm0)                // do round\n         \"add       $16, %1         \\n\\t\" // point to next round key\n         \"subl      $1, %0          \\n\\t\" // loop\n         \"jnz       1b              \\n\\t\"\n         \"movdqu    (%1), %%xmm1    \\n\\t\" // load round key\n         AESENCLAST(xmm1_xmm0)            // last round\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n         \"jmp       3f              \\n\\t\"\n\n         \"2:                        \\n\\t\" // decryption loop\n         \"movdqu    (%1), %%xmm1    \\n\\t\"\n         AESDEC(xmm1_xmm0)                // do round\n         \"add       $16, %1         \\n\\t\"\n         \"subl      $1, %0          \\n\\t\"\n         \"jnz       2b              \\n\\t\"\n         \"movdqu    (%1), %%xmm1    \\n\\t\" // load round key\n         AESDECLAST(xmm1_xmm0)            // last round\n#endif\n\n         \"3:                        \\n\\t\"\n         \"movdqu    %%xmm0, (%4)    \\n\\t\" // export output\n         :\n         : \"r\" (ctx->nr), \"r\" (ctx->buf + ctx->rk_offset), \"r\" (mode), \"r\" (input), \"r\" (output)\n         : \"memory\", \"cc\", \"xmm0\", \"xmm1\", \"0\", \"1\");\n\n\n    return 0;\n}\n\n/*\n * GCM multiplication: c = a times b in GF(2^128)\n * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5.\n */\nvoid mbedtls_aesni_gcm_mult(unsigned char c[16],\n                            const unsigned char a[16],\n                            const unsigned char b[16])\n{\n    unsigned char aa[16], bb[16], cc[16];\n    size_t i;\n\n    /* The inputs are in big-endian order, so byte-reverse them */\n    for (i = 0; i < 16; i++) {\n        aa[i] = a[15 - i];\n        bb[i] = b[15 - i];\n    }\n\n    asm (\"movdqu (%0), %%xmm0               \\n\\t\" // a1:a0\n         \"movdqu (%1), %%xmm1               \\n\\t\" // b1:b0\n\n         /*\n          * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1\n          * using [CLMUL-WP] algorithm 1 (p. 12).\n          */\n         \"movdqa %%xmm1, %%xmm2             \\n\\t\" // copy of b1:b0\n         \"movdqa %%xmm1, %%xmm3             \\n\\t\" // same\n         \"movdqa %%xmm1, %%xmm4             \\n\\t\" // same\n         PCLMULQDQ(xmm0_xmm1, \"0x00\")             // a0*b0 = c1:c0\n         PCLMULQDQ(xmm0_xmm2, \"0x11\")             // a1*b1 = d1:d0\n         PCLMULQDQ(xmm0_xmm3, \"0x10\")             // a0*b1 = e1:e0\n         PCLMULQDQ(xmm0_xmm4, \"0x01\")             // a1*b0 = f1:f0\n         \"pxor %%xmm3, %%xmm4               \\n\\t\" // e1+f1:e0+f0\n         \"movdqa %%xmm4, %%xmm3             \\n\\t\" // same\n         \"psrldq $8, %%xmm4                 \\n\\t\" // 0:e1+f1\n         \"pslldq $8, %%xmm3                 \\n\\t\" // e0+f0:0\n         \"pxor %%xmm4, %%xmm2               \\n\\t\" // d1:d0+e1+f1\n         \"pxor %%xmm3, %%xmm1               \\n\\t\" // c1+e0+f1:c0\n\n         /*\n          * Now shift the result one bit to the left,\n          * taking advantage of [CLMUL-WP] eq 27 (p. 18)\n          */\n         \"movdqa %%xmm1, %%xmm3             \\n\\t\" // r1:r0\n         \"movdqa %%xmm2, %%xmm4             \\n\\t\" // r3:r2\n         \"psllq $1, %%xmm1                  \\n\\t\" // r1<<1:r0<<1\n         \"psllq $1, %%xmm2                  \\n\\t\" // r3<<1:r2<<1\n         \"psrlq $63, %%xmm3                 \\n\\t\" // r1>>63:r0>>63\n         \"psrlq $63, %%xmm4                 \\n\\t\" // r3>>63:r2>>63\n         \"movdqa %%xmm3, %%xmm5             \\n\\t\" // r1>>63:r0>>63\n         \"pslldq $8, %%xmm3                 \\n\\t\" // r0>>63:0\n         \"pslldq $8, %%xmm4                 \\n\\t\" // r2>>63:0\n         \"psrldq $8, %%xmm5                 \\n\\t\" // 0:r1>>63\n         \"por %%xmm3, %%xmm1                \\n\\t\" // r1<<1|r0>>63:r0<<1\n         \"por %%xmm4, %%xmm2                \\n\\t\" // r3<<1|r2>>62:r2<<1\n         \"por %%xmm5, %%xmm2                \\n\\t\" // r3<<1|r2>>62:r2<<1|r1>>63\n\n         /*\n          * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1\n          * using [CLMUL-WP] algorithm 5 (p. 18).\n          * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted).\n          */\n         /* Step 2 (1) */\n         \"movdqa %%xmm1, %%xmm3             \\n\\t\" // x1:x0\n         \"movdqa %%xmm1, %%xmm4             \\n\\t\" // same\n         \"movdqa %%xmm1, %%xmm5             \\n\\t\" // same\n         \"psllq $63, %%xmm3                 \\n\\t\" // x1<<63:x0<<63 = stuff:a\n         \"psllq $62, %%xmm4                 \\n\\t\" // x1<<62:x0<<62 = stuff:b\n         \"psllq $57, %%xmm5                 \\n\\t\" // x1<<57:x0<<57 = stuff:c\n\n         /* Step 2 (2) */\n         \"pxor %%xmm4, %%xmm3               \\n\\t\" // stuff:a+b\n         \"pxor %%xmm5, %%xmm3               \\n\\t\" // stuff:a+b+c\n         \"pslldq $8, %%xmm3                 \\n\\t\" // a+b+c:0\n         \"pxor %%xmm3, %%xmm1               \\n\\t\" // x1+a+b+c:x0 = d:x0\n\n         /* Steps 3 and 4 */\n         \"movdqa %%xmm1,%%xmm0              \\n\\t\" // d:x0\n         \"movdqa %%xmm1,%%xmm4              \\n\\t\" // same\n         \"movdqa %%xmm1,%%xmm5              \\n\\t\" // same\n         \"psrlq $1, %%xmm0                  \\n\\t\" // e1:x0>>1 = e1:e0'\n         \"psrlq $2, %%xmm4                  \\n\\t\" // f1:x0>>2 = f1:f0'\n         \"psrlq $7, %%xmm5                  \\n\\t\" // g1:x0>>7 = g1:g0'\n         \"pxor %%xmm4, %%xmm0               \\n\\t\" // e1+f1:e0'+f0'\n         \"pxor %%xmm5, %%xmm0               \\n\\t\" // e1+f1+g1:e0'+f0'+g0'\n         // e0'+f0'+g0' is almost e0+f0+g0, ex\\tcept for some missing\n         // bits carried from d. Now get those\\t bits back in.\n         \"movdqa %%xmm1,%%xmm3              \\n\\t\" // d:x0\n         \"movdqa %%xmm1,%%xmm4              \\n\\t\" // same\n         \"movdqa %%xmm1,%%xmm5              \\n\\t\" // same\n         \"psllq $63, %%xmm3                 \\n\\t\" // d<<63:stuff\n         \"psllq $62, %%xmm4                 \\n\\t\" // d<<62:stuff\n         \"psllq $57, %%xmm5                 \\n\\t\" // d<<57:stuff\n         \"pxor %%xmm4, %%xmm3               \\n\\t\" // d<<63+d<<62:stuff\n         \"pxor %%xmm5, %%xmm3               \\n\\t\" // missing bits of d:stuff\n         \"psrldq $8, %%xmm3                 \\n\\t\" // 0:missing bits of d\n         \"pxor %%xmm3, %%xmm0               \\n\\t\" // e1+f1+g1:e0+f0+g0\n         \"pxor %%xmm1, %%xmm0               \\n\\t\" // h1:h0\n         \"pxor %%xmm2, %%xmm0               \\n\\t\" // x3+h1:x2+h0\n\n         \"movdqu %%xmm0, (%2)               \\n\\t\" // done\n         :\n         : \"r\" (aa), \"r\" (bb), \"r\" (cc)\n         : \"memory\", \"cc\", \"xmm0\", \"xmm1\", \"xmm2\", \"xmm3\", \"xmm4\", \"xmm5\");\n\n    /* Now byte-reverse the outputs */\n    for (i = 0; i < 16; i++) {\n        c[i] = cc[15 - i];\n    }\n\n    return;\n}\n\n/*\n * Compute decryption round keys from encryption round keys\n */\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\nvoid mbedtls_aesni_inverse_key(unsigned char *invkey,\n                               const unsigned char *fwdkey, int nr)\n{\n    unsigned char *ik = invkey;\n    const unsigned char *fk = fwdkey + 16 * nr;\n\n    memcpy(ik, fk, 16);\n\n    for (fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16) {\n        asm (\"movdqu (%0), %%xmm0       \\n\\t\"\n             AESIMC(xmm0_xmm0)\n             \"movdqu %%xmm0, (%1)       \\n\\t\"\n             :\n             : \"r\" (fk), \"r\" (ik)\n             : \"memory\", \"xmm0\");\n    }\n\n    memcpy(ik, fk, 16);\n}\n#endif\n\n/*\n * Key expansion, 128-bit case\n */\nstatic void aesni_setkey_enc_128(unsigned char *rk,\n                                 const unsigned char *key)\n{\n    asm (\"movdqu (%1), %%xmm0               \\n\\t\" // copy the original key\n         \"movdqu %%xmm0, (%0)               \\n\\t\" // as round key 0\n         \"jmp 2f                            \\n\\t\" // skip auxiliary routine\n\n         /*\n          * Finish generating the next round key.\n          *\n          * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff\n          * with X = rot( sub( r3 ) ) ^ RCON.\n          *\n          * On exit, xmm0 is r7:r6:r5:r4\n          * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3\n          * and those are written to the round key buffer.\n          */\n         \"1:                                \\n\\t\"\n         \"pshufd $0xff, %%xmm1, %%xmm1      \\n\\t\" // X:X:X:X\n         \"pxor %%xmm0, %%xmm1               \\n\\t\" // X+r3:X+r2:X+r1:r4\n         \"pslldq $4, %%xmm0                 \\n\\t\" // r2:r1:r0:0\n         \"pxor %%xmm0, %%xmm1               \\n\\t\" // X+r3+r2:X+r2+r1:r5:r4\n         \"pslldq $4, %%xmm0                 \\n\\t\" // etc\n         \"pxor %%xmm0, %%xmm1               \\n\\t\"\n         \"pslldq $4, %%xmm0                 \\n\\t\"\n         \"pxor %%xmm1, %%xmm0               \\n\\t\" // update xmm0 for next time!\n         \"add $16, %0                       \\n\\t\" // point to next round key\n         \"movdqu %%xmm0, (%0)               \\n\\t\" // write it\n         \"ret                               \\n\\t\"\n\n         /* Main \"loop\" */\n         \"2:                                \\n\\t\"\n         AESKEYGENA(xmm0_xmm1, \"0x01\")      \"call 1b \\n\\t\"\n         AESKEYGENA(xmm0_xmm1, \"0x02\")      \"call 1b \\n\\t\"\n         AESKEYGENA(xmm0_xmm1, \"0x04\")      \"call 1b \\n\\t\"\n         AESKEYGENA(xmm0_xmm1, \"0x08\")      \"call 1b \\n\\t\"\n         AESKEYGENA(xmm0_xmm1, \"0x10\")      \"call 1b \\n\\t\"\n         AESKEYGENA(xmm0_xmm1, \"0x20\")      \"call 1b \\n\\t\"\n         AESKEYGENA(xmm0_xmm1, \"0x40\")      \"call 1b \\n\\t\"\n         AESKEYGENA(xmm0_xmm1, \"0x80\")      \"call 1b \\n\\t\"\n         AESKEYGENA(xmm0_xmm1, \"0x1B\")      \"call 1b \\n\\t\"\n         AESKEYGENA(xmm0_xmm1, \"0x36\")      \"call 1b \\n\\t\"\n         :\n         : \"r\" (rk), \"r\" (key)\n         : \"memory\", \"cc\", \"xmm0\", \"xmm1\", \"0\");\n}\n\n/*\n * Key expansion, 192-bit case\n */\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic void aesni_setkey_enc_192(unsigned char *rk,\n                                 const unsigned char *key)\n{\n    asm (\"movdqu (%1), %%xmm0   \\n\\t\" // copy original round key\n         \"movdqu %%xmm0, (%0)   \\n\\t\"\n         \"add $16, %0           \\n\\t\"\n         \"movq 16(%1), %%xmm1   \\n\\t\"\n         \"movq %%xmm1, (%0)     \\n\\t\"\n         \"add $8, %0            \\n\\t\"\n         \"jmp 2f                \\n\\t\" // skip auxiliary routine\n\n         /*\n          * Finish generating the next 6 quarter-keys.\n          *\n          * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4\n          * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON.\n          *\n          * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10\n          * and those are written to the round key buffer.\n          */\n         \"1:                            \\n\\t\"\n         \"pshufd $0x55, %%xmm2, %%xmm2  \\n\\t\" // X:X:X:X\n         \"pxor %%xmm0, %%xmm2           \\n\\t\" // X+r3:X+r2:X+r1:r4\n         \"pslldq $4, %%xmm0             \\n\\t\" // etc\n         \"pxor %%xmm0, %%xmm2           \\n\\t\"\n         \"pslldq $4, %%xmm0             \\n\\t\"\n         \"pxor %%xmm0, %%xmm2           \\n\\t\"\n         \"pslldq $4, %%xmm0             \\n\\t\"\n         \"pxor %%xmm2, %%xmm0           \\n\\t\" // update xmm0 = r9:r8:r7:r6\n         \"movdqu %%xmm0, (%0)           \\n\\t\"\n         \"add $16, %0                   \\n\\t\"\n         \"pshufd $0xff, %%xmm0, %%xmm2  \\n\\t\" // r9:r9:r9:r9\n         \"pxor %%xmm1, %%xmm2           \\n\\t\" // stuff:stuff:r9+r5:r10\n         \"pslldq $4, %%xmm1             \\n\\t\" // r2:r1:r0:0\n         \"pxor %%xmm2, %%xmm1           \\n\\t\" // xmm1 = stuff:stuff:r11:r10\n         \"movq %%xmm1, (%0)             \\n\\t\"\n         \"add $8, %0                    \\n\\t\"\n         \"ret                           \\n\\t\"\n\n         \"2:                            \\n\\t\"\n         AESKEYGENA(xmm1_xmm2, \"0x01\")  \"call 1b \\n\\t\"\n         AESKEYGENA(xmm1_xmm2, \"0x02\")  \"call 1b \\n\\t\"\n         AESKEYGENA(xmm1_xmm2, \"0x04\")  \"call 1b \\n\\t\"\n         AESKEYGENA(xmm1_xmm2, \"0x08\")  \"call 1b \\n\\t\"\n         AESKEYGENA(xmm1_xmm2, \"0x10\")  \"call 1b \\n\\t\"\n         AESKEYGENA(xmm1_xmm2, \"0x20\")  \"call 1b \\n\\t\"\n         AESKEYGENA(xmm1_xmm2, \"0x40\")  \"call 1b \\n\\t\"\n         AESKEYGENA(xmm1_xmm2, \"0x80\")  \"call 1b \\n\\t\"\n\n         :\n         : \"r\" (rk), \"r\" (key)\n         : \"memory\", \"cc\", \"xmm0\", \"xmm1\", \"xmm2\", \"0\");\n}\n#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */\n\n/*\n * Key expansion, 256-bit case\n */\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic void aesni_setkey_enc_256(unsigned char *rk,\n                                 const unsigned char *key)\n{\n    asm (\"movdqu (%1), %%xmm0           \\n\\t\"\n         \"movdqu %%xmm0, (%0)           \\n\\t\"\n         \"add $16, %0                   \\n\\t\"\n         \"movdqu 16(%1), %%xmm1         \\n\\t\"\n         \"movdqu %%xmm1, (%0)           \\n\\t\"\n         \"jmp 2f                        \\n\\t\" // skip auxiliary routine\n\n         /*\n          * Finish generating the next two round keys.\n          *\n          * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and\n          * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON\n          *\n          * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12\n          * and those have been written to the output buffer.\n          */\n         \"1:                                \\n\\t\"\n         \"pshufd $0xff, %%xmm2, %%xmm2      \\n\\t\"\n         \"pxor %%xmm0, %%xmm2               \\n\\t\"\n         \"pslldq $4, %%xmm0                 \\n\\t\"\n         \"pxor %%xmm0, %%xmm2               \\n\\t\"\n         \"pslldq $4, %%xmm0                 \\n\\t\"\n         \"pxor %%xmm0, %%xmm2               \\n\\t\"\n         \"pslldq $4, %%xmm0                 \\n\\t\"\n         \"pxor %%xmm2, %%xmm0               \\n\\t\"\n         \"add $16, %0                       \\n\\t\"\n         \"movdqu %%xmm0, (%0)               \\n\\t\"\n\n         /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 )\n          * and proceed to generate next round key from there */\n         AESKEYGENA(xmm0_xmm2, \"0x00\")\n         \"pshufd $0xaa, %%xmm2, %%xmm2      \\n\\t\"\n         \"pxor %%xmm1, %%xmm2               \\n\\t\"\n         \"pslldq $4, %%xmm1                 \\n\\t\"\n         \"pxor %%xmm1, %%xmm2               \\n\\t\"\n         \"pslldq $4, %%xmm1                 \\n\\t\"\n         \"pxor %%xmm1, %%xmm2               \\n\\t\"\n         \"pslldq $4, %%xmm1                 \\n\\t\"\n         \"pxor %%xmm2, %%xmm1               \\n\\t\"\n         \"add $16, %0                       \\n\\t\"\n         \"movdqu %%xmm1, (%0)               \\n\\t\"\n         \"ret                               \\n\\t\"\n\n         /*\n          * Main \"loop\" - Generating one more key than necessary,\n          * see definition of mbedtls_aes_context.buf\n          */\n         \"2:                                \\n\\t\"\n         AESKEYGENA(xmm1_xmm2, \"0x01\")      \"call 1b \\n\\t\"\n         AESKEYGENA(xmm1_xmm2, \"0x02\")      \"call 1b \\n\\t\"\n         AESKEYGENA(xmm1_xmm2, \"0x04\")      \"call 1b \\n\\t\"\n         AESKEYGENA(xmm1_xmm2, \"0x08\")      \"call 1b \\n\\t\"\n         AESKEYGENA(xmm1_xmm2, \"0x10\")      \"call 1b \\n\\t\"\n         AESKEYGENA(xmm1_xmm2, \"0x20\")      \"call 1b \\n\\t\"\n         AESKEYGENA(xmm1_xmm2, \"0x40\")      \"call 1b \\n\\t\"\n         :\n         : \"r\" (rk), \"r\" (key)\n         : \"memory\", \"cc\", \"xmm0\", \"xmm1\", \"xmm2\", \"0\");\n}\n#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */\n\n#endif  /* MBEDTLS_AESNI_HAVE_CODE */\n\n/*\n * Key expansion, wrapper\n */\nint mbedtls_aesni_setkey_enc(unsigned char *rk,\n                             const unsigned char *key,\n                             size_t bits)\n{\n    switch (bits) {\n        case 128: aesni_setkey_enc_128(rk, key); break;\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n        case 192: aesni_setkey_enc_192(rk, key); break;\n        case 256: aesni_setkey_enc_256(rk, key); break;\n#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */\n        default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;\n    }\n\n    return 0;\n}\n\n#endif /* MBEDTLS_AESNI_HAVE_CODE */\n\n#endif /* MBEDTLS_AESNI_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/aesni.h",
    "content": "/**\n * \\file aesni.h\n *\n * \\brief AES-NI for hardware AES acceleration on some Intel processors\n *\n * \\warning These functions are only for internal use by other library\n *          functions; you must not call them directly.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_AESNI_H\n#define MBEDTLS_AESNI_H\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/aes.h\"\n\n#define MBEDTLS_AESNI_AES      0x02000000u\n#define MBEDTLS_AESNI_CLMUL    0x00000002u\n\n#if defined(MBEDTLS_AESNI_C) && \\\n    (defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_X86))\n\n/* Can we do AESNI with intrinsics?\n * (Only implemented with certain compilers, only for certain targets.)\n */\n#undef MBEDTLS_AESNI_HAVE_INTRINSICS\n#if defined(_MSC_VER) && !defined(__clang__)\n/* Visual Studio supports AESNI intrinsics since VS 2008 SP1. We only support\n * VS 2013 and up for other reasons anyway, so no need to check the version. */\n#define MBEDTLS_AESNI_HAVE_INTRINSICS\n#endif\n/* GCC-like compilers: currently, we only support intrinsics if the requisite\n * target flag is enabled when building the library (e.g. `gcc -mpclmul -msse2`\n * or `clang -maes -mpclmul`). */\n#if (defined(__GNUC__) || defined(__clang__)) && defined(__AES__) && defined(__PCLMUL__)\n#define MBEDTLS_AESNI_HAVE_INTRINSICS\n#endif\n/* For 32-bit, we only support intrinsics */\n#if defined(MBEDTLS_ARCH_IS_X86) && (defined(__GNUC__) || defined(__clang__))\n#define MBEDTLS_AESNI_HAVE_INTRINSICS\n#endif\n\n/* Choose the implementation of AESNI, if one is available.\n *\n * Favor the intrinsics-based implementation if it's available, for better\n * maintainability.\n * Performance is about the same (see #7380).\n * In the long run, we will likely remove the assembly implementation. */\n#if defined(MBEDTLS_AESNI_HAVE_INTRINSICS)\n#define MBEDTLS_AESNI_HAVE_CODE 2 // via intrinsics\n#elif defined(MBEDTLS_HAVE_ASM) && \\\n    (defined(__GNUC__) || defined(__clang__)) && defined(MBEDTLS_ARCH_IS_X64)\n/* Can we do AESNI with inline assembly?\n * (Only implemented with gas syntax, only for 64-bit.)\n */\n#define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly\n#else\n#error \"MBEDTLS_AESNI_C defined, but neither intrinsics nor assembly available\"\n#endif\n\n#if defined(MBEDTLS_AESNI_HAVE_CODE)\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief          Internal function to detect the AES-NI feature in CPUs.\n *\n * \\note           This function is only for internal use by other library\n *                 functions; you must not call it directly.\n *\n * \\param what     The feature to detect\n *                 (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL)\n *\n * \\return         1 if CPU has support for the feature, 0 otherwise\n */\n#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)\nint mbedtls_aesni_has_support(unsigned int what);\n#else\n#define mbedtls_aesni_has_support(what) 1\n#endif\n\n/**\n * \\brief          Internal AES-NI AES-ECB block encryption and decryption\n *\n * \\note           This function is only for internal use by other library\n *                 functions; you must not call it directly.\n *\n * \\param ctx      AES context\n * \\param mode     MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT\n * \\param input    16-byte input block\n * \\param output   16-byte output block\n *\n * \\return         0 on success (cannot fail)\n */\nint mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx,\n                            int mode,\n                            const unsigned char input[16],\n                            unsigned char output[16]);\n\n/**\n * \\brief          Internal GCM multiplication: c = a * b in GF(2^128)\n *\n * \\note           This function is only for internal use by other library\n *                 functions; you must not call it directly.\n *\n * \\param c        Result\n * \\param a        First operand\n * \\param b        Second operand\n *\n * \\note           Both operands and result are bit strings interpreted as\n *                 elements of GF(2^128) as per the GCM spec.\n */\nvoid mbedtls_aesni_gcm_mult(unsigned char c[16],\n                            const unsigned char a[16],\n                            const unsigned char b[16]);\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n/**\n * \\brief           Internal round key inversion. This function computes\n *                  decryption round keys from the encryption round keys.\n *\n * \\note            This function is only for internal use by other library\n *                  functions; you must not call it directly.\n *\n * \\param invkey    Round keys for the equivalent inverse cipher\n * \\param fwdkey    Original round keys (for encryption)\n * \\param nr        Number of rounds (that is, number of round keys minus one)\n */\nvoid mbedtls_aesni_inverse_key(unsigned char *invkey,\n                               const unsigned char *fwdkey,\n                               int nr);\n#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */\n\n/**\n * \\brief           Internal key expansion for encryption\n *\n * \\note            This function is only for internal use by other library\n *                  functions; you must not call it directly.\n *\n * \\param rk        Destination buffer where the round keys are written\n * \\param key       Encryption key\n * \\param bits      Key size in bits (must be 128, 192 or 256)\n *\n * \\return          0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH\n */\nint mbedtls_aesni_setkey_enc(unsigned char *rk,\n                             const unsigned char *key,\n                             size_t bits);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_AESNI_HAVE_CODE */\n#endif  /* MBEDTLS_AESNI_C && (MBEDTLS_ARCH_IS_X64 || MBEDTLS_ARCH_IS_X86) */\n\n#endif /* MBEDTLS_AESNI_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/alignment.h",
    "content": "/**\n * \\file alignment.h\n *\n * \\brief Utility code for dealing with unaligned memory accesses\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_LIBRARY_ALIGNMENT_H\n#define MBEDTLS_LIBRARY_ALIGNMENT_H\n\n#include <stdint.h>\n#include <string.h>\n#include <stdlib.h>\n\n/*\n * Define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS for architectures where unaligned memory\n * accesses are known to be efficient.\n *\n * All functions defined here will behave correctly regardless, but might be less\n * efficient when this is not defined.\n */\n#if defined(__ARM_FEATURE_UNALIGNED) \\\n    || defined(MBEDTLS_ARCH_IS_X86) || defined(MBEDTLS_ARCH_IS_X64) \\\n    || defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)\n/*\n * __ARM_FEATURE_UNALIGNED is defined where appropriate by armcc, gcc 7, clang 9\n * (and later versions) for Arm v7 and later; all x86 platforms should have\n * efficient unaligned access.\n *\n * https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#alignment\n * specifies that on Windows-on-Arm64, unaligned access is safe (except for uncached\n * device memory).\n */\n#define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS\n#endif\n\n#if defined(__IAR_SYSTEMS_ICC__) && \\\n    (defined(MBEDTLS_ARCH_IS_ARM64) || defined(MBEDTLS_ARCH_IS_ARM32) \\\n    || defined(__ICCRX__) || defined(__ICCRL78__) || defined(__ICCRISCV__))\n#pragma language=save\n#pragma language=extended\n#define MBEDTLS_POP_IAR_LANGUAGE_PRAGMA\n/* IAR recommend this technique for accessing unaligned data in\n * https://www.iar.com/knowledge/support/technical-notes/compiler/accessing-unaligned-data\n * This results in a single load / store instruction (if unaligned access is supported).\n * According to that document, this is only supported on certain architectures.\n */\n    #define UINT_UNALIGNED\ntypedef uint16_t __packed mbedtls_uint16_unaligned_t;\ntypedef uint32_t __packed mbedtls_uint32_unaligned_t;\ntypedef uint64_t __packed mbedtls_uint64_unaligned_t;\n#elif defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 40504) && \\\n    ((MBEDTLS_GCC_VERSION < 60300) || (!defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)))\n/*\n * gcc may generate a branch to memcpy for calls like `memcpy(dest, src, 4)` rather than\n * generating some LDR or LDRB instructions (similar for stores).\n *\n * This is architecture dependent: x86-64 seems fine even with old gcc; 32-bit Arm\n * is affected. To keep it simple, we enable for all architectures.\n *\n * For versions of gcc < 5.4.0 this issue always happens.\n * For gcc < 6.3.0, this issue happens at -O0\n * For all versions, this issue happens iff unaligned access is not supported.\n *\n * For gcc 4.x, this implementation will generate byte-by-byte loads even if unaligned access is\n * supported, which is correct but not optimal.\n *\n * For performance (and code size, in some cases), we want to avoid the branch and just generate\n * some inline load/store instructions since the access is small and constant-size.\n *\n * The manual states:\n * \"The packed attribute specifies that a variable or structure field should have the smallest\n *  possible alignment—one byte for a variable\"\n * https://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/Variable-Attributes.html\n *\n * Previous implementations used __attribute__((__aligned__(1)), but had issues with a gcc bug:\n * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94662\n *\n * Tested with several versions of GCC from 4.5.0 up to 13.2.0\n * We don't enable for older than 4.5.0 as this has not been tested.\n */\n #define UINT_UNALIGNED_STRUCT\ntypedef struct {\n    uint16_t x;\n} __attribute__((packed)) mbedtls_uint16_unaligned_t;\ntypedef struct {\n    uint32_t x;\n} __attribute__((packed)) mbedtls_uint32_unaligned_t;\ntypedef struct {\n    uint64_t x;\n} __attribute__((packed)) mbedtls_uint64_unaligned_t;\n #endif\n\n/*\n * We try to force mbedtls_(get|put)_unaligned_uintXX to be always inline, because this results\n * in code that is both smaller and faster. IAR and gcc both benefit from this when optimising\n * for size.\n */\n\n/**\n * Read the unsigned 16 bits integer from the given address, which need not\n * be aligned.\n *\n * \\param   p pointer to 2 bytes of data\n * \\return  Data at the given address\n */\n#if defined(__IAR_SYSTEMS_ICC__)\n#pragma inline = forced\n#elif defined(__GNUC__)\n__attribute__((always_inline))\n#endif\nstatic inline uint16_t mbedtls_get_unaligned_uint16(const void *p)\n{\n    uint16_t r;\n#if defined(UINT_UNALIGNED)\n    mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;\n    r = *p16;\n#elif defined(UINT_UNALIGNED_STRUCT)\n    mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;\n    r = p16->x;\n#else\n    memcpy(&r, p, sizeof(r));\n#endif\n    return r;\n}\n\n/**\n * Write the unsigned 16 bits integer to the given address, which need not\n * be aligned.\n *\n * \\param   p pointer to 2 bytes of data\n * \\param   x data to write\n */\n#if defined(__IAR_SYSTEMS_ICC__)\n#pragma inline = forced\n#elif defined(__GNUC__)\n__attribute__((always_inline))\n#endif\nstatic inline void mbedtls_put_unaligned_uint16(void *p, uint16_t x)\n{\n#if defined(UINT_UNALIGNED)\n    mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;\n    *p16 = x;\n#elif defined(UINT_UNALIGNED_STRUCT)\n    mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;\n    p16->x = x;\n#else\n    memcpy(p, &x, sizeof(x));\n#endif\n}\n\n/**\n * Read the unsigned 32 bits integer from the given address, which need not\n * be aligned.\n *\n * \\param   p pointer to 4 bytes of data\n * \\return  Data at the given address\n */\n#if defined(__IAR_SYSTEMS_ICC__)\n#pragma inline = forced\n#elif defined(__GNUC__)\n__attribute__((always_inline))\n#endif\nstatic inline uint32_t mbedtls_get_unaligned_uint32(const void *p)\n{\n    uint32_t r;\n#if defined(UINT_UNALIGNED)\n    mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;\n    r = *p32;\n#elif defined(UINT_UNALIGNED_STRUCT)\n    mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;\n    r = p32->x;\n#else\n    memcpy(&r, p, sizeof(r));\n#endif\n    return r;\n}\n\n/**\n * Write the unsigned 32 bits integer to the given address, which need not\n * be aligned.\n *\n * \\param   p pointer to 4 bytes of data\n * \\param   x data to write\n */\n#if defined(__IAR_SYSTEMS_ICC__)\n#pragma inline = forced\n#elif defined(__GNUC__)\n__attribute__((always_inline))\n#endif\nstatic inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x)\n{\n#if defined(UINT_UNALIGNED)\n    mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;\n    *p32 = x;\n#elif defined(UINT_UNALIGNED_STRUCT)\n    mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;\n    p32->x = x;\n#else\n    memcpy(p, &x, sizeof(x));\n#endif\n}\n\n/**\n * Read the unsigned 64 bits integer from the given address, which need not\n * be aligned.\n *\n * \\param   p pointer to 8 bytes of data\n * \\return  Data at the given address\n */\n#if defined(__IAR_SYSTEMS_ICC__)\n#pragma inline = forced\n#elif defined(__GNUC__)\n__attribute__((always_inline))\n#endif\nstatic inline uint64_t mbedtls_get_unaligned_uint64(const void *p)\n{\n    uint64_t r;\n#if defined(UINT_UNALIGNED)\n    mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;\n    r = *p64;\n#elif defined(UINT_UNALIGNED_STRUCT)\n    mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;\n    r = p64->x;\n#else\n    memcpy(&r, p, sizeof(r));\n#endif\n    return r;\n}\n\n/**\n * Write the unsigned 64 bits integer to the given address, which need not\n * be aligned.\n *\n * \\param   p pointer to 8 bytes of data\n * \\param   x data to write\n */\n#if defined(__IAR_SYSTEMS_ICC__)\n#pragma inline = forced\n#elif defined(__GNUC__)\n__attribute__((always_inline))\n#endif\nstatic inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x)\n{\n#if defined(UINT_UNALIGNED)\n    mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;\n    *p64 = x;\n#elif defined(UINT_UNALIGNED_STRUCT)\n    mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;\n    p64->x = x;\n#else\n    memcpy(p, &x, sizeof(x));\n#endif\n}\n\n#if defined(MBEDTLS_POP_IAR_LANGUAGE_PRAGMA)\n#pragma language=restore\n#endif\n\n/** Byte Reading Macros\n *\n * Given a multi-byte integer \\p x, MBEDTLS_BYTE_n retrieves the n-th\n * byte from x, where byte 0 is the least significant byte.\n */\n#define MBEDTLS_BYTE_0(x) ((uint8_t) ((x)         & 0xff))\n#define MBEDTLS_BYTE_1(x) ((uint8_t) (((x) >>  8) & 0xff))\n#define MBEDTLS_BYTE_2(x) ((uint8_t) (((x) >> 16) & 0xff))\n#define MBEDTLS_BYTE_3(x) ((uint8_t) (((x) >> 24) & 0xff))\n#define MBEDTLS_BYTE_4(x) ((uint8_t) (((x) >> 32) & 0xff))\n#define MBEDTLS_BYTE_5(x) ((uint8_t) (((x) >> 40) & 0xff))\n#define MBEDTLS_BYTE_6(x) ((uint8_t) (((x) >> 48) & 0xff))\n#define MBEDTLS_BYTE_7(x) ((uint8_t) (((x) >> 56) & 0xff))\n\n/*\n * Detect GCC built-in byteswap routines\n */\n#if defined(__GNUC__) && defined(__GNUC_PREREQ)\n#if __GNUC_PREREQ(4, 8)\n#define MBEDTLS_BSWAP16 __builtin_bswap16\n#endif /* __GNUC_PREREQ(4,8) */\n#if __GNUC_PREREQ(4, 3)\n#define MBEDTLS_BSWAP32 __builtin_bswap32\n#define MBEDTLS_BSWAP64 __builtin_bswap64\n#endif /* __GNUC_PREREQ(4,3) */\n#endif /* defined(__GNUC__) && defined(__GNUC_PREREQ) */\n\n/*\n * Detect Clang built-in byteswap routines\n */\n#if defined(__clang__) && defined(__has_builtin)\n#if __has_builtin(__builtin_bswap16) && !defined(MBEDTLS_BSWAP16)\n#define MBEDTLS_BSWAP16 __builtin_bswap16\n#endif /* __has_builtin(__builtin_bswap16) */\n#if __has_builtin(__builtin_bswap32) && !defined(MBEDTLS_BSWAP32)\n#define MBEDTLS_BSWAP32 __builtin_bswap32\n#endif /* __has_builtin(__builtin_bswap32) */\n#if __has_builtin(__builtin_bswap64) && !defined(MBEDTLS_BSWAP64)\n#define MBEDTLS_BSWAP64 __builtin_bswap64\n#endif /* __has_builtin(__builtin_bswap64) */\n#endif /* defined(__clang__) && defined(__has_builtin) */\n\n/*\n * Detect MSVC built-in byteswap routines\n */\n#if defined(_MSC_VER)\n#if !defined(MBEDTLS_BSWAP16)\n#define MBEDTLS_BSWAP16 _byteswap_ushort\n#endif\n#if !defined(MBEDTLS_BSWAP32)\n#define MBEDTLS_BSWAP32 _byteswap_ulong\n#endif\n#if !defined(MBEDTLS_BSWAP64)\n#define MBEDTLS_BSWAP64 _byteswap_uint64\n#endif\n#endif /* defined(_MSC_VER) */\n\n/* Detect armcc built-in byteswap routine */\n#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000) && !defined(MBEDTLS_BSWAP32)\n#if defined(__ARM_ACLE)  /* ARM Compiler 6 - earlier versions don't need a header */\n#include <arm_acle.h>\n#endif\n#define MBEDTLS_BSWAP32 __rev\n#endif\n\n/* Detect IAR built-in byteswap routine */\n#if defined(__IAR_SYSTEMS_ICC__)\n#if defined(__ARM_ACLE)\n#include <arm_acle.h>\n#define MBEDTLS_BSWAP16(x) ((uint16_t) __rev16((uint32_t) (x)))\n#define MBEDTLS_BSWAP32 __rev\n#define MBEDTLS_BSWAP64 __revll\n#endif\n#endif\n\n/*\n * Where compiler built-ins are not present, fall back to C code that the\n * compiler may be able to detect and transform into the relevant bswap or\n * similar instruction.\n */\n#if !defined(MBEDTLS_BSWAP16)\nstatic inline uint16_t mbedtls_bswap16(uint16_t x)\n{\n    return\n        (x & 0x00ff) << 8 |\n        (x & 0xff00) >> 8;\n}\n#define MBEDTLS_BSWAP16 mbedtls_bswap16\n#endif /* !defined(MBEDTLS_BSWAP16) */\n\n#if !defined(MBEDTLS_BSWAP32)\nstatic inline uint32_t mbedtls_bswap32(uint32_t x)\n{\n    return\n        (x & 0x000000ff) << 24 |\n        (x & 0x0000ff00) <<  8 |\n        (x & 0x00ff0000) >>  8 |\n        (x & 0xff000000) >> 24;\n}\n#define MBEDTLS_BSWAP32 mbedtls_bswap32\n#endif /* !defined(MBEDTLS_BSWAP32) */\n\n#if !defined(MBEDTLS_BSWAP64)\nstatic inline uint64_t mbedtls_bswap64(uint64_t x)\n{\n    return\n        (x & 0x00000000000000ffULL) << 56 |\n        (x & 0x000000000000ff00ULL) << 40 |\n        (x & 0x0000000000ff0000ULL) << 24 |\n        (x & 0x00000000ff000000ULL) <<  8 |\n        (x & 0x000000ff00000000ULL) >>  8 |\n        (x & 0x0000ff0000000000ULL) >> 24 |\n        (x & 0x00ff000000000000ULL) >> 40 |\n        (x & 0xff00000000000000ULL) >> 56;\n}\n#define MBEDTLS_BSWAP64 mbedtls_bswap64\n#endif /* !defined(MBEDTLS_BSWAP64) */\n\n#if !defined(__BYTE_ORDER__)\n\n#if defined(__LITTLE_ENDIAN__)\n/* IAR defines __xxx_ENDIAN__, but not __BYTE_ORDER__ */\n#define MBEDTLS_IS_BIG_ENDIAN 0\n#elif defined(__BIG_ENDIAN__)\n#define MBEDTLS_IS_BIG_ENDIAN 1\n#else\nstatic const uint16_t mbedtls_byte_order_detector = { 0x100 };\n#define MBEDTLS_IS_BIG_ENDIAN (*((unsigned char *) (&mbedtls_byte_order_detector)) == 0x01)\n#endif\n\n#else\n\n#if (__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__)\n#define MBEDTLS_IS_BIG_ENDIAN 1\n#else\n#define MBEDTLS_IS_BIG_ENDIAN 0\n#endif\n\n#endif /* !defined(__BYTE_ORDER__) */\n\n/**\n * Get the unsigned 32 bits integer corresponding to four bytes in\n * big-endian order (MSB first).\n *\n * \\param   data    Base address of the memory to get the four bytes from.\n * \\param   offset  Offset from \\p data of the first and most significant\n *                  byte of the four bytes to build the 32 bits unsigned\n *                  integer from.\n */\n#define MBEDTLS_GET_UINT32_BE(data, offset)                                \\\n    ((MBEDTLS_IS_BIG_ENDIAN)                                               \\\n        ? mbedtls_get_unaligned_uint32((data) + (offset))                  \\\n        : MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \\\n    )\n\n/**\n * Put in memory a 32 bits unsigned integer in big-endian order.\n *\n * \\param   n       32 bits unsigned integer to put in memory.\n * \\param   data    Base address of the memory where to put the 32\n *                  bits unsigned integer in.\n * \\param   offset  Offset from \\p data where to put the most significant\n *                  byte of the 32 bits unsigned integer \\p n.\n */\n#define MBEDTLS_PUT_UINT32_BE(n, data, offset)                                   \\\n    {                                                                            \\\n        if (MBEDTLS_IS_BIG_ENDIAN)                                               \\\n        {                                                                        \\\n            mbedtls_put_unaligned_uint32((data) + (offset), (uint32_t) (n));     \\\n        }                                                                        \\\n        else                                                                     \\\n        {                                                                        \\\n            mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \\\n        }                                                                        \\\n    }\n\n/**\n * Get the unsigned 32 bits integer corresponding to four bytes in\n * little-endian order (LSB first).\n *\n * \\param   data    Base address of the memory to get the four bytes from.\n * \\param   offset  Offset from \\p data of the first and least significant\n *                  byte of the four bytes to build the 32 bits unsigned\n *                  integer from.\n */\n#define MBEDTLS_GET_UINT32_LE(data, offset)                                \\\n    ((MBEDTLS_IS_BIG_ENDIAN)                                               \\\n        ? MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \\\n        : mbedtls_get_unaligned_uint32((data) + (offset))                  \\\n    )\n\n\n/**\n * Put in memory a 32 bits unsigned integer in little-endian order.\n *\n * \\param   n       32 bits unsigned integer to put in memory.\n * \\param   data    Base address of the memory where to put the 32\n *                  bits unsigned integer in.\n * \\param   offset  Offset from \\p data where to put the least significant\n *                  byte of the 32 bits unsigned integer \\p n.\n */\n#define MBEDTLS_PUT_UINT32_LE(n, data, offset)                                   \\\n    {                                                                            \\\n        if (MBEDTLS_IS_BIG_ENDIAN)                                               \\\n        {                                                                        \\\n            mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \\\n        }                                                                        \\\n        else                                                                     \\\n        {                                                                        \\\n            mbedtls_put_unaligned_uint32((data) + (offset), ((uint32_t) (n)));   \\\n        }                                                                        \\\n    }\n\n/**\n * Get the unsigned 16 bits integer corresponding to two bytes in\n * little-endian order (LSB first).\n *\n * \\param   data    Base address of the memory to get the two bytes from.\n * \\param   offset  Offset from \\p data of the first and least significant\n *                  byte of the two bytes to build the 16 bits unsigned\n *                  integer from.\n */\n#define MBEDTLS_GET_UINT16_LE(data, offset)                                \\\n    ((MBEDTLS_IS_BIG_ENDIAN)                                               \\\n        ? MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \\\n        : mbedtls_get_unaligned_uint16((data) + (offset))                  \\\n    )\n\n/**\n * Put in memory a 16 bits unsigned integer in little-endian order.\n *\n * \\param   n       16 bits unsigned integer to put in memory.\n * \\param   data    Base address of the memory where to put the 16\n *                  bits unsigned integer in.\n * \\param   offset  Offset from \\p data where to put the least significant\n *                  byte of the 16 bits unsigned integer \\p n.\n */\n#define MBEDTLS_PUT_UINT16_LE(n, data, offset)                                   \\\n    {                                                                            \\\n        if (MBEDTLS_IS_BIG_ENDIAN)                                               \\\n        {                                                                        \\\n            mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \\\n        }                                                                        \\\n        else                                                                     \\\n        {                                                                        \\\n            mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n));     \\\n        }                                                                        \\\n    }\n\n/**\n * Get the unsigned 16 bits integer corresponding to two bytes in\n * big-endian order (MSB first).\n *\n * \\param   data    Base address of the memory to get the two bytes from.\n * \\param   offset  Offset from \\p data of the first and most significant\n *                  byte of the two bytes to build the 16 bits unsigned\n *                  integer from.\n */\n#define MBEDTLS_GET_UINT16_BE(data, offset)                                \\\n    ((MBEDTLS_IS_BIG_ENDIAN)                                               \\\n        ? mbedtls_get_unaligned_uint16((data) + (offset))                  \\\n        : MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \\\n    )\n\n/**\n * Put in memory a 16 bits unsigned integer in big-endian order.\n *\n * \\param   n       16 bits unsigned integer to put in memory.\n * \\param   data    Base address of the memory where to put the 16\n *                  bits unsigned integer in.\n * \\param   offset  Offset from \\p data where to put the most significant\n *                  byte of the 16 bits unsigned integer \\p n.\n */\n#define MBEDTLS_PUT_UINT16_BE(n, data, offset)                                   \\\n    {                                                                            \\\n        if (MBEDTLS_IS_BIG_ENDIAN)                                               \\\n        {                                                                        \\\n            mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n));     \\\n        }                                                                        \\\n        else                                                                     \\\n        {                                                                        \\\n            mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \\\n        }                                                                        \\\n    }\n\n/**\n * Get the unsigned 24 bits integer corresponding to three bytes in\n * big-endian order (MSB first).\n *\n * \\param   data    Base address of the memory to get the three bytes from.\n * \\param   offset  Offset from \\p data of the first and most significant\n *                  byte of the three bytes to build the 24 bits unsigned\n *                  integer from.\n */\n#define MBEDTLS_GET_UINT24_BE(data, offset)        \\\n    (                                              \\\n        ((uint32_t) (data)[(offset)] << 16)        \\\n        | ((uint32_t) (data)[(offset) + 1] << 8)   \\\n        | ((uint32_t) (data)[(offset) + 2])        \\\n    )\n\n/**\n * Put in memory a 24 bits unsigned integer in big-endian order.\n *\n * \\param   n       24 bits unsigned integer to put in memory.\n * \\param   data    Base address of the memory where to put the 24\n *                  bits unsigned integer in.\n * \\param   offset  Offset from \\p data where to put the most significant\n *                  byte of the 24 bits unsigned integer \\p n.\n */\n#define MBEDTLS_PUT_UINT24_BE(n, data, offset)                \\\n    {                                                         \\\n        (data)[(offset)] = MBEDTLS_BYTE_2(n);                 \\\n        (data)[(offset) + 1] = MBEDTLS_BYTE_1(n);             \\\n        (data)[(offset) + 2] = MBEDTLS_BYTE_0(n);             \\\n    }\n\n/**\n * Get the unsigned 24 bits integer corresponding to three bytes in\n * little-endian order (LSB first).\n *\n * \\param   data    Base address of the memory to get the three bytes from.\n * \\param   offset  Offset from \\p data of the first and least significant\n *                  byte of the three bytes to build the 24 bits unsigned\n *                  integer from.\n */\n#define MBEDTLS_GET_UINT24_LE(data, offset)               \\\n    (                                                     \\\n        ((uint32_t) (data)[(offset)])                     \\\n        | ((uint32_t) (data)[(offset) + 1] <<  8)         \\\n        | ((uint32_t) (data)[(offset) + 2] << 16)         \\\n    )\n\n/**\n * Put in memory a 24 bits unsigned integer in little-endian order.\n *\n * \\param   n       24 bits unsigned integer to put in memory.\n * \\param   data    Base address of the memory where to put the 24\n *                  bits unsigned integer in.\n * \\param   offset  Offset from \\p data where to put the least significant\n *                  byte of the 24 bits unsigned integer \\p n.\n */\n#define MBEDTLS_PUT_UINT24_LE(n, data, offset)                \\\n    {                                                         \\\n        (data)[(offset)] = MBEDTLS_BYTE_0(n);                 \\\n        (data)[(offset) + 1] = MBEDTLS_BYTE_1(n);             \\\n        (data)[(offset) + 2] = MBEDTLS_BYTE_2(n);             \\\n    }\n\n/**\n * Get the unsigned 64 bits integer corresponding to eight bytes in\n * big-endian order (MSB first).\n *\n * \\param   data    Base address of the memory to get the eight bytes from.\n * \\param   offset  Offset from \\p data of the first and most significant\n *                  byte of the eight bytes to build the 64 bits unsigned\n *                  integer from.\n */\n#define MBEDTLS_GET_UINT64_BE(data, offset)                                \\\n    ((MBEDTLS_IS_BIG_ENDIAN)                                               \\\n        ? mbedtls_get_unaligned_uint64((data) + (offset))                  \\\n        : MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \\\n    )\n\n/**\n * Put in memory a 64 bits unsigned integer in big-endian order.\n *\n * \\param   n       64 bits unsigned integer to put in memory.\n * \\param   data    Base address of the memory where to put the 64\n *                  bits unsigned integer in.\n * \\param   offset  Offset from \\p data where to put the most significant\n *                  byte of the 64 bits unsigned integer \\p n.\n */\n#define MBEDTLS_PUT_UINT64_BE(n, data, offset)                                   \\\n    {                                                                            \\\n        if (MBEDTLS_IS_BIG_ENDIAN)                                               \\\n        {                                                                        \\\n            mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n));     \\\n        }                                                                        \\\n        else                                                                     \\\n        {                                                                        \\\n            mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \\\n        }                                                                        \\\n    }\n\n/**\n * Get the unsigned 64 bits integer corresponding to eight bytes in\n * little-endian order (LSB first).\n *\n * \\param   data    Base address of the memory to get the eight bytes from.\n * \\param   offset  Offset from \\p data of the first and least significant\n *                  byte of the eight bytes to build the 64 bits unsigned\n *                  integer from.\n */\n#define MBEDTLS_GET_UINT64_LE(data, offset)                                \\\n    ((MBEDTLS_IS_BIG_ENDIAN)                                               \\\n        ? MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \\\n        : mbedtls_get_unaligned_uint64((data) + (offset))                  \\\n    )\n\n/**\n * Put in memory a 64 bits unsigned integer in little-endian order.\n *\n * \\param   n       64 bits unsigned integer to put in memory.\n * \\param   data    Base address of the memory where to put the 64\n *                  bits unsigned integer in.\n * \\param   offset  Offset from \\p data where to put the least significant\n *                  byte of the 64 bits unsigned integer \\p n.\n */\n#define MBEDTLS_PUT_UINT64_LE(n, data, offset)                                   \\\n    {                                                                            \\\n        if (MBEDTLS_IS_BIG_ENDIAN)                                               \\\n        {                                                                        \\\n            mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \\\n        }                                                                        \\\n        else                                                                     \\\n        {                                                                        \\\n            mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n));     \\\n        }                                                                        \\\n    }\n\n#endif /* MBEDTLS_LIBRARY_ALIGNMENT_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/aria.c",
    "content": "/*\n *  ARIA implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n * This implementation is based on the following standards:\n * [1] http://210.104.33.10/ARIA/doc/ARIA-specification-e.pdf\n * [2] https://tools.ietf.org/html/rfc5794\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_ARIA_C)\n\n#include \"mbedtls/aria.h\"\n\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#if !defined(MBEDTLS_ARIA_ALT)\n\n#include \"mbedtls/platform_util.h\"\n\n/*\n * modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes\n *\n * This is submatrix P1 in [1] Appendix B.1\n *\n * Common compilers fail to translate this to minimal number of instructions,\n * so let's provide asm versions for common platforms with C fallback.\n */\n#if defined(MBEDTLS_HAVE_ASM)\n#if defined(__arm__) /* rev16 available from v6 up */\n/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */\n#if defined(__GNUC__) && \\\n    (!defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000) && \\\n    __ARM_ARCH >= 6\nstatic inline uint32_t aria_p1(uint32_t x)\n{\n    uint32_t r;\n    __asm(\"rev16 %0, %1\" : \"=l\" (r) : \"l\" (x));\n    return r;\n}\n#define ARIA_P1 aria_p1\n#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \\\n    (__TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3)\nstatic inline uint32_t aria_p1(uint32_t x)\n{\n    uint32_t r;\n    __asm(\"rev16 r, x\");\n    return r;\n}\n#define ARIA_P1 aria_p1\n#endif\n#endif /* arm */\n#if defined(__GNUC__) && \\\n    defined(__i386__) || defined(__amd64__) || defined(__x86_64__)\n/* I couldn't find an Intel equivalent of rev16, so two instructions */\n#define ARIA_P1(x) ARIA_P2(ARIA_P3(x))\n#endif /* x86 gnuc */\n#endif /* MBEDTLS_HAVE_ASM && GNUC */\n#if !defined(ARIA_P1)\n#define ARIA_P1(x) ((((x) >> 8) & 0x00FF00FF) ^ (((x) & 0x00FF00FF) << 8))\n#endif\n\n/*\n * modify byte order: ( A B C D ) -> ( C D A B ), i.e. rotate by 16 bits\n *\n * This is submatrix P2 in [1] Appendix B.1\n *\n * Common compilers will translate this to a single instruction.\n */\n#define ARIA_P2(x) (((x) >> 16) ^ ((x) << 16))\n\n/*\n * modify byte order: ( A B C D ) -> ( D C B A ), i.e. change endianness\n *\n * This is submatrix P3 in [1] Appendix B.1\n */\n#define ARIA_P3(x) MBEDTLS_BSWAP32(x)\n\n/*\n * ARIA Affine Transform\n * (a, b, c, d) = state in/out\n *\n * If we denote the first byte of input by 0, ..., the last byte by f,\n * then inputs are: a = 0123, b = 4567, c = 89ab, d = cdef.\n *\n * Reading [1] 2.4 or [2] 2.4.3 in columns and performing simple\n * rearrangements on adjacent pairs, output is:\n *\n * a = 3210 + 4545 + 6767 + 88aa + 99bb + dccd + effe\n *   = 3210 + 4567 + 6745 + 89ab + 98ba + dcfe + efcd\n * b = 0101 + 2323 + 5476 + 8998 + baab + eecc + ffdd\n *   = 0123 + 2301 + 5476 + 89ab + ba98 + efcd + fedc\n * c = 0022 + 1133 + 4554 + 7667 + ab89 + dcdc + fefe\n *   = 0123 + 1032 + 4567 + 7654 + ab89 + dcfe + fedc\n * d = 1001 + 2332 + 6644 + 7755 + 9898 + baba + cdef\n *   = 1032 + 2301 + 6745 + 7654 + 98ba + ba98 + cdef\n *\n * Note: another presentation of the A transform can be found as the first\n * half of App. B.1 in [1] in terms of 4-byte operators P1, P2, P3 and P4.\n * The implementation below uses only P1 and P2 as they are sufficient.\n */\nstatic inline void aria_a(uint32_t *a, uint32_t *b,\n                          uint32_t *c, uint32_t *d)\n{\n    uint32_t ta, tb, tc;\n    ta  =  *b;                      // 4567\n    *b  =  *a;                      // 0123\n    *a  =  ARIA_P2(ta);             // 6745\n    tb  =  ARIA_P2(*d);             // efcd\n    *d  =  ARIA_P1(*c);             // 98ba\n    *c  =  ARIA_P1(tb);             // fedc\n    ta  ^= *d;                      // 4567+98ba\n    tc  =  ARIA_P2(*b);             // 2301\n    ta  =  ARIA_P1(ta) ^ tc ^ *c;   // 2301+5476+89ab+fedc\n    tb  ^= ARIA_P2(*d);             // ba98+efcd\n    tc  ^= ARIA_P1(*a);             // 2301+7654\n    *b  ^= ta ^ tb;                 // 0123+2301+5476+89ab+ba98+efcd+fedc OUT\n    tb  =  ARIA_P2(tb) ^ ta;        // 2301+5476+89ab+98ba+cdef+fedc\n    *a  ^= ARIA_P1(tb);             // 3210+4567+6745+89ab+98ba+dcfe+efcd OUT\n    ta  =  ARIA_P2(ta);             // 0123+7654+ab89+dcfe\n    *d  ^= ARIA_P1(ta) ^ tc;        // 1032+2301+6745+7654+98ba+ba98+cdef OUT\n    tc  =  ARIA_P2(tc);             // 0123+5476\n    *c  ^= ARIA_P1(tc) ^ ta;        // 0123+1032+4567+7654+ab89+dcfe+fedc OUT\n}\n\n/*\n * ARIA Substitution Layer SL1 / SL2\n * (a, b, c, d) = state in/out\n * (sa, sb, sc, sd) = 256 8-bit S-Boxes (see below)\n *\n * By passing sb1, sb2, is1, is2 as S-Boxes you get SL1\n * By passing is1, is2, sb1, sb2 as S-Boxes you get SL2\n */\nstatic inline void aria_sl(uint32_t *a, uint32_t *b,\n                           uint32_t *c, uint32_t *d,\n                           const uint8_t sa[256], const uint8_t sb[256],\n                           const uint8_t sc[256], const uint8_t sd[256])\n{\n    *a = ((uint32_t) sa[MBEDTLS_BYTE_0(*a)]) ^\n         (((uint32_t) sb[MBEDTLS_BYTE_1(*a)]) <<  8) ^\n         (((uint32_t) sc[MBEDTLS_BYTE_2(*a)]) << 16) ^\n         (((uint32_t) sd[MBEDTLS_BYTE_3(*a)]) << 24);\n    *b = ((uint32_t) sa[MBEDTLS_BYTE_0(*b)]) ^\n         (((uint32_t) sb[MBEDTLS_BYTE_1(*b)]) <<  8) ^\n         (((uint32_t) sc[MBEDTLS_BYTE_2(*b)]) << 16) ^\n         (((uint32_t) sd[MBEDTLS_BYTE_3(*b)]) << 24);\n    *c = ((uint32_t) sa[MBEDTLS_BYTE_0(*c)]) ^\n         (((uint32_t) sb[MBEDTLS_BYTE_1(*c)]) <<  8) ^\n         (((uint32_t) sc[MBEDTLS_BYTE_2(*c)]) << 16) ^\n         (((uint32_t) sd[MBEDTLS_BYTE_3(*c)]) << 24);\n    *d = ((uint32_t) sa[MBEDTLS_BYTE_0(*d)]) ^\n         (((uint32_t) sb[MBEDTLS_BYTE_1(*d)]) <<  8) ^\n         (((uint32_t) sc[MBEDTLS_BYTE_2(*d)]) << 16) ^\n         (((uint32_t) sd[MBEDTLS_BYTE_3(*d)]) << 24);\n}\n\n/*\n * S-Boxes\n */\nstatic const uint8_t aria_sb1[256] =\n{\n    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,\n    0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,\n    0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26,\n    0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,\n    0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,\n    0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,\n    0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED,\n    0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,\n    0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,\n    0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,\n    0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC,\n    0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,\n    0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14,\n    0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,\n    0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,\n    0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,\n    0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F,\n    0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,\n    0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11,\n    0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,\n    0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F,\n    0xB0, 0x54, 0xBB, 0x16\n};\n\nstatic const uint8_t aria_sb2[256] =\n{\n    0xE2, 0x4E, 0x54, 0xFC, 0x94, 0xC2, 0x4A, 0xCC, 0x62, 0x0D, 0x6A, 0x46,\n    0x3C, 0x4D, 0x8B, 0xD1, 0x5E, 0xFA, 0x64, 0xCB, 0xB4, 0x97, 0xBE, 0x2B,\n    0xBC, 0x77, 0x2E, 0x03, 0xD3, 0x19, 0x59, 0xC1, 0x1D, 0x06, 0x41, 0x6B,\n    0x55, 0xF0, 0x99, 0x69, 0xEA, 0x9C, 0x18, 0xAE, 0x63, 0xDF, 0xE7, 0xBB,\n    0x00, 0x73, 0x66, 0xFB, 0x96, 0x4C, 0x85, 0xE4, 0x3A, 0x09, 0x45, 0xAA,\n    0x0F, 0xEE, 0x10, 0xEB, 0x2D, 0x7F, 0xF4, 0x29, 0xAC, 0xCF, 0xAD, 0x91,\n    0x8D, 0x78, 0xC8, 0x95, 0xF9, 0x2F, 0xCE, 0xCD, 0x08, 0x7A, 0x88, 0x38,\n    0x5C, 0x83, 0x2A, 0x28, 0x47, 0xDB, 0xB8, 0xC7, 0x93, 0xA4, 0x12, 0x53,\n    0xFF, 0x87, 0x0E, 0x31, 0x36, 0x21, 0x58, 0x48, 0x01, 0x8E, 0x37, 0x74,\n    0x32, 0xCA, 0xE9, 0xB1, 0xB7, 0xAB, 0x0C, 0xD7, 0xC4, 0x56, 0x42, 0x26,\n    0x07, 0x98, 0x60, 0xD9, 0xB6, 0xB9, 0x11, 0x40, 0xEC, 0x20, 0x8C, 0xBD,\n    0xA0, 0xC9, 0x84, 0x04, 0x49, 0x23, 0xF1, 0x4F, 0x50, 0x1F, 0x13, 0xDC,\n    0xD8, 0xC0, 0x9E, 0x57, 0xE3, 0xC3, 0x7B, 0x65, 0x3B, 0x02, 0x8F, 0x3E,\n    0xE8, 0x25, 0x92, 0xE5, 0x15, 0xDD, 0xFD, 0x17, 0xA9, 0xBF, 0xD4, 0x9A,\n    0x7E, 0xC5, 0x39, 0x67, 0xFE, 0x76, 0x9D, 0x43, 0xA7, 0xE1, 0xD0, 0xF5,\n    0x68, 0xF2, 0x1B, 0x34, 0x70, 0x05, 0xA3, 0x8A, 0xD5, 0x79, 0x86, 0xA8,\n    0x30, 0xC6, 0x51, 0x4B, 0x1E, 0xA6, 0x27, 0xF6, 0x35, 0xD2, 0x6E, 0x24,\n    0x16, 0x82, 0x5F, 0xDA, 0xE6, 0x75, 0xA2, 0xEF, 0x2C, 0xB2, 0x1C, 0x9F,\n    0x5D, 0x6F, 0x80, 0x0A, 0x72, 0x44, 0x9B, 0x6C, 0x90, 0x0B, 0x5B, 0x33,\n    0x7D, 0x5A, 0x52, 0xF3, 0x61, 0xA1, 0xF7, 0xB0, 0xD6, 0x3F, 0x7C, 0x6D,\n    0xED, 0x14, 0xE0, 0xA5, 0x3D, 0x22, 0xB3, 0xF8, 0x89, 0xDE, 0x71, 0x1A,\n    0xAF, 0xBA, 0xB5, 0x81\n};\n\nstatic const uint8_t aria_is1[256] =\n{\n    0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E,\n    0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,\n    0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32,\n    0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,\n    0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49,\n    0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,\n    0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50,\n    0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,\n    0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05,\n    0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,\n    0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41,\n    0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,\n    0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8,\n    0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,\n    0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B,\n    0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,\n    0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59,\n    0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,\n    0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D,\n    0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,\n    0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63,\n    0x55, 0x21, 0x0C, 0x7D\n};\n\nstatic const uint8_t aria_is2[256] =\n{\n    0x30, 0x68, 0x99, 0x1B, 0x87, 0xB9, 0x21, 0x78, 0x50, 0x39, 0xDB, 0xE1,\n    0x72, 0x09, 0x62, 0x3C, 0x3E, 0x7E, 0x5E, 0x8E, 0xF1, 0xA0, 0xCC, 0xA3,\n    0x2A, 0x1D, 0xFB, 0xB6, 0xD6, 0x20, 0xC4, 0x8D, 0x81, 0x65, 0xF5, 0x89,\n    0xCB, 0x9D, 0x77, 0xC6, 0x57, 0x43, 0x56, 0x17, 0xD4, 0x40, 0x1A, 0x4D,\n    0xC0, 0x63, 0x6C, 0xE3, 0xB7, 0xC8, 0x64, 0x6A, 0x53, 0xAA, 0x38, 0x98,\n    0x0C, 0xF4, 0x9B, 0xED, 0x7F, 0x22, 0x76, 0xAF, 0xDD, 0x3A, 0x0B, 0x58,\n    0x67, 0x88, 0x06, 0xC3, 0x35, 0x0D, 0x01, 0x8B, 0x8C, 0xC2, 0xE6, 0x5F,\n    0x02, 0x24, 0x75, 0x93, 0x66, 0x1E, 0xE5, 0xE2, 0x54, 0xD8, 0x10, 0xCE,\n    0x7A, 0xE8, 0x08, 0x2C, 0x12, 0x97, 0x32, 0xAB, 0xB4, 0x27, 0x0A, 0x23,\n    0xDF, 0xEF, 0xCA, 0xD9, 0xB8, 0xFA, 0xDC, 0x31, 0x6B, 0xD1, 0xAD, 0x19,\n    0x49, 0xBD, 0x51, 0x96, 0xEE, 0xE4, 0xA8, 0x41, 0xDA, 0xFF, 0xCD, 0x55,\n    0x86, 0x36, 0xBE, 0x61, 0x52, 0xF8, 0xBB, 0x0E, 0x82, 0x48, 0x69, 0x9A,\n    0xE0, 0x47, 0x9E, 0x5C, 0x04, 0x4B, 0x34, 0x15, 0x79, 0x26, 0xA7, 0xDE,\n    0x29, 0xAE, 0x92, 0xD7, 0x84, 0xE9, 0xD2, 0xBA, 0x5D, 0xF3, 0xC5, 0xB0,\n    0xBF, 0xA4, 0x3B, 0x71, 0x44, 0x46, 0x2B, 0xFC, 0xEB, 0x6F, 0xD5, 0xF6,\n    0x14, 0xFE, 0x7C, 0x70, 0x5A, 0x7D, 0xFD, 0x2F, 0x18, 0x83, 0x16, 0xA5,\n    0x91, 0x1F, 0x05, 0x95, 0x74, 0xA9, 0xC1, 0x5B, 0x4A, 0x85, 0x6D, 0x13,\n    0x07, 0x4F, 0x4E, 0x45, 0xB2, 0x0F, 0xC9, 0x1C, 0xA6, 0xBC, 0xEC, 0x73,\n    0x90, 0x7B, 0xCF, 0x59, 0x8F, 0xA1, 0xF9, 0x2D, 0xF2, 0xB1, 0x00, 0x94,\n    0x37, 0x9F, 0xD0, 0x2E, 0x9C, 0x6E, 0x28, 0x3F, 0x80, 0xF0, 0x3D, 0xD3,\n    0x25, 0x8A, 0xB5, 0xE7, 0x42, 0xB3, 0xC7, 0xEA, 0xF7, 0x4C, 0x11, 0x33,\n    0x03, 0xA2, 0xAC, 0x60\n};\n\n/*\n * Helper for key schedule: r = FO( p, k ) ^ x\n */\nstatic void aria_fo_xor(uint32_t r[4], const uint32_t p[4],\n                        const uint32_t k[4], const uint32_t x[4])\n{\n    uint32_t a, b, c, d;\n\n    a = p[0] ^ k[0];\n    b = p[1] ^ k[1];\n    c = p[2] ^ k[2];\n    d = p[3] ^ k[3];\n\n    aria_sl(&a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2);\n    aria_a(&a, &b, &c, &d);\n\n    r[0] = a ^ x[0];\n    r[1] = b ^ x[1];\n    r[2] = c ^ x[2];\n    r[3] = d ^ x[3];\n}\n\n/*\n * Helper for key schedule: r = FE( p, k ) ^ x\n */\nstatic void aria_fe_xor(uint32_t r[4], const uint32_t p[4],\n                        const uint32_t k[4], const uint32_t x[4])\n{\n    uint32_t a, b, c, d;\n\n    a = p[0] ^ k[0];\n    b = p[1] ^ k[1];\n    c = p[2] ^ k[2];\n    d = p[3] ^ k[3];\n\n    aria_sl(&a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2);\n    aria_a(&a, &b, &c, &d);\n\n    r[0] = a ^ x[0];\n    r[1] = b ^ x[1];\n    r[2] = c ^ x[2];\n    r[3] = d ^ x[3];\n}\n\n/*\n * Big endian 128-bit rotation: r = a ^ (b <<< n), used only in key setup.\n *\n * We chose to store bytes into 32-bit words in little-endian format (see\n * MBEDTLS_GET_UINT32_LE / MBEDTLS_PUT_UINT32_LE ) so we need to reverse\n * bytes here.\n */\nstatic void aria_rot128(uint32_t r[4], const uint32_t a[4],\n                        const uint32_t b[4], uint8_t n)\n{\n    uint8_t i, j;\n    uint32_t t, u;\n\n    const uint8_t n1 = n % 32;              // bit offset\n    const uint8_t n2 = n1 ? 32 - n1 : 0;    // reverse bit offset\n\n    j = (n / 32) % 4;                       // initial word offset\n    t = ARIA_P3(b[j]);                      // big endian\n    for (i = 0; i < 4; i++) {\n        j = (j + 1) % 4;                    // get next word, big endian\n        u = ARIA_P3(b[j]);\n        t <<= n1;                           // rotate\n        t |= u >> n2;\n        t = ARIA_P3(t);                     // back to little endian\n        r[i] = a[i] ^ t;                    // store\n        t = u;                              // move to next word\n    }\n}\n\n/*\n * Set encryption key\n */\nint mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx,\n                            const unsigned char *key, unsigned int keybits)\n{\n    /* round constant masks */\n    const uint32_t rc[3][4] =\n    {\n        {   0xB7C17C51, 0x940A2227, 0xE8AB13FE, 0xE06E9AFA  },\n        {   0xCC4AB16D, 0x20C8219E, 0xD5B128FF, 0xB0E25DEF  },\n        {   0x1D3792DB, 0x70E92621, 0x75972403, 0x0EC9E804  }\n    };\n\n    int i;\n    uint32_t w[4][4], *w2;\n\n    if (keybits != 128 && keybits != 192 && keybits != 256) {\n        return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;\n    }\n\n    /* Copy key to W0 (and potential remainder to W1) */\n    w[0][0] = MBEDTLS_GET_UINT32_LE(key,  0);\n    w[0][1] = MBEDTLS_GET_UINT32_LE(key,  4);\n    w[0][2] = MBEDTLS_GET_UINT32_LE(key,  8);\n    w[0][3] = MBEDTLS_GET_UINT32_LE(key, 12);\n\n    memset(w[1], 0, 16);\n    if (keybits >= 192) {\n        w[1][0] = MBEDTLS_GET_UINT32_LE(key, 16);    // 192 bit key\n        w[1][1] = MBEDTLS_GET_UINT32_LE(key, 20);\n    }\n    if (keybits == 256) {\n        w[1][2] = MBEDTLS_GET_UINT32_LE(key, 24);    // 256 bit key\n        w[1][3] = MBEDTLS_GET_UINT32_LE(key, 28);\n    }\n\n    i = (keybits - 128) >> 6;               // index: 0, 1, 2\n    ctx->nr = 12 + 2 * i;                   // no. rounds: 12, 14, 16\n\n    aria_fo_xor(w[1], w[0], rc[i], w[1]);   // W1 = FO(W0, CK1) ^ KR\n    i = i < 2 ? i + 1 : 0;\n    aria_fe_xor(w[2], w[1], rc[i], w[0]);   // W2 = FE(W1, CK2) ^ W0\n    i = i < 2 ? i + 1 : 0;\n    aria_fo_xor(w[3], w[2], rc[i], w[1]);   // W3 = FO(W2, CK3) ^ W1\n\n    for (i = 0; i < 4; i++) {               // create round keys\n        w2 = w[(i + 1) & 3];\n        aria_rot128(ctx->rk[i], w[i], w2, 128 - 19);\n        aria_rot128(ctx->rk[i +  4], w[i], w2, 128 - 31);\n        aria_rot128(ctx->rk[i +  8], w[i], w2,       61);\n        aria_rot128(ctx->rk[i + 12], w[i], w2,       31);\n    }\n    aria_rot128(ctx->rk[16], w[0], w[1], 19);\n\n    /* w holds enough info to reconstruct the round keys */\n    mbedtls_platform_zeroize(w, sizeof(w));\n\n    return 0;\n}\n\n/*\n * Set decryption key\n */\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\nint mbedtls_aria_setkey_dec(mbedtls_aria_context *ctx,\n                            const unsigned char *key, unsigned int keybits)\n{\n    int i, j, k, ret;\n\n    ret = mbedtls_aria_setkey_enc(ctx, key, keybits);\n    if (ret != 0) {\n        return ret;\n    }\n\n    /* flip the order of round keys */\n    for (i = 0, j = ctx->nr; i < j; i++, j--) {\n        for (k = 0; k < 4; k++) {\n            uint32_t t = ctx->rk[i][k];\n            ctx->rk[i][k] = ctx->rk[j][k];\n            ctx->rk[j][k] = t;\n        }\n    }\n\n    /* apply affine transform to middle keys */\n    for (i = 1; i < ctx->nr; i++) {\n        aria_a(&ctx->rk[i][0], &ctx->rk[i][1],\n               &ctx->rk[i][2], &ctx->rk[i][3]);\n    }\n\n    return 0;\n}\n#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */\n\n/*\n * Encrypt a block\n */\nint mbedtls_aria_crypt_ecb(mbedtls_aria_context *ctx,\n                           const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE],\n                           unsigned char output[MBEDTLS_ARIA_BLOCKSIZE])\n{\n    int i;\n\n    uint32_t a, b, c, d;\n\n    a = MBEDTLS_GET_UINT32_LE(input,  0);\n    b = MBEDTLS_GET_UINT32_LE(input,  4);\n    c = MBEDTLS_GET_UINT32_LE(input,  8);\n    d = MBEDTLS_GET_UINT32_LE(input, 12);\n\n    i = 0;\n    while (1) {\n        a ^= ctx->rk[i][0];\n        b ^= ctx->rk[i][1];\n        c ^= ctx->rk[i][2];\n        d ^= ctx->rk[i][3];\n        i++;\n\n        aria_sl(&a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2);\n        aria_a(&a, &b, &c, &d);\n\n        a ^= ctx->rk[i][0];\n        b ^= ctx->rk[i][1];\n        c ^= ctx->rk[i][2];\n        d ^= ctx->rk[i][3];\n        i++;\n\n        aria_sl(&a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2);\n        if (i >= ctx->nr) {\n            break;\n        }\n        aria_a(&a, &b, &c, &d);\n    }\n\n    /* final key mixing */\n    a ^= ctx->rk[i][0];\n    b ^= ctx->rk[i][1];\n    c ^= ctx->rk[i][2];\n    d ^= ctx->rk[i][3];\n\n    MBEDTLS_PUT_UINT32_LE(a, output,  0);\n    MBEDTLS_PUT_UINT32_LE(b, output,  4);\n    MBEDTLS_PUT_UINT32_LE(c, output,  8);\n    MBEDTLS_PUT_UINT32_LE(d, output, 12);\n\n    return 0;\n}\n\n/* Initialize context */\nvoid mbedtls_aria_init(mbedtls_aria_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_aria_context));\n}\n\n/* Clear context */\nvoid mbedtls_aria_free(mbedtls_aria_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_aria_context));\n}\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n/*\n * ARIA-CBC buffer encryption/decryption\n */\nint mbedtls_aria_crypt_cbc(mbedtls_aria_context *ctx,\n                           int mode,\n                           size_t length,\n                           unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE],\n                           const unsigned char *input,\n                           unsigned char *output)\n{\n    unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE];\n\n    if ((mode != MBEDTLS_ARIA_ENCRYPT) && (mode != MBEDTLS_ARIA_DECRYPT)) {\n        return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;\n    }\n\n    if (length % MBEDTLS_ARIA_BLOCKSIZE) {\n        return MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH;\n    }\n\n    if (mode == MBEDTLS_ARIA_DECRYPT) {\n        while (length > 0) {\n            memcpy(temp, input, MBEDTLS_ARIA_BLOCKSIZE);\n            mbedtls_aria_crypt_ecb(ctx, input, output);\n\n            mbedtls_xor(output, output, iv, MBEDTLS_ARIA_BLOCKSIZE);\n\n            memcpy(iv, temp, MBEDTLS_ARIA_BLOCKSIZE);\n\n            input  += MBEDTLS_ARIA_BLOCKSIZE;\n            output += MBEDTLS_ARIA_BLOCKSIZE;\n            length -= MBEDTLS_ARIA_BLOCKSIZE;\n        }\n    } else {\n        while (length > 0) {\n            mbedtls_xor(output, input, iv, MBEDTLS_ARIA_BLOCKSIZE);\n\n            mbedtls_aria_crypt_ecb(ctx, output, output);\n            memcpy(iv, output, MBEDTLS_ARIA_BLOCKSIZE);\n\n            input  += MBEDTLS_ARIA_BLOCKSIZE;\n            output += MBEDTLS_ARIA_BLOCKSIZE;\n            length -= MBEDTLS_ARIA_BLOCKSIZE;\n        }\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n/*\n * ARIA-CFB128 buffer encryption/decryption\n */\nint mbedtls_aria_crypt_cfb128(mbedtls_aria_context *ctx,\n                              int mode,\n                              size_t length,\n                              size_t *iv_off,\n                              unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE],\n                              const unsigned char *input,\n                              unsigned char *output)\n{\n    unsigned char c;\n    size_t n;\n\n    if ((mode != MBEDTLS_ARIA_ENCRYPT) && (mode != MBEDTLS_ARIA_DECRYPT)) {\n        return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;\n    }\n\n    n = *iv_off;\n\n    /* An overly large value of n can lead to an unlimited\n     * buffer overflow. */\n    if (n >= MBEDTLS_ARIA_BLOCKSIZE) {\n        return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;\n    }\n\n    if (mode == MBEDTLS_ARIA_DECRYPT) {\n        while (length--) {\n            if (n == 0) {\n                mbedtls_aria_crypt_ecb(ctx, iv, iv);\n            }\n\n            c = *input++;\n            *output++ = c ^ iv[n];\n            iv[n] = c;\n\n            n = (n + 1) & 0x0F;\n        }\n    } else {\n        while (length--) {\n            if (n == 0) {\n                mbedtls_aria_crypt_ecb(ctx, iv, iv);\n            }\n\n            iv[n] = *output++ = (unsigned char) (iv[n] ^ *input++);\n\n            n = (n + 1) & 0x0F;\n        }\n    }\n\n    *iv_off = n;\n\n    return 0;\n}\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n/*\n * ARIA-CTR buffer encryption/decryption\n */\nint mbedtls_aria_crypt_ctr(mbedtls_aria_context *ctx,\n                           size_t length,\n                           size_t *nc_off,\n                           unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE],\n                           unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE],\n                           const unsigned char *input,\n                           unsigned char *output)\n{\n    int c, i;\n    size_t n;\n\n    n = *nc_off;\n    /* An overly large value of n can lead to an unlimited\n     * buffer overflow. */\n    if (n >= MBEDTLS_ARIA_BLOCKSIZE) {\n        return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;\n    }\n\n    while (length--) {\n        if (n == 0) {\n            mbedtls_aria_crypt_ecb(ctx, nonce_counter,\n                                   stream_block);\n\n            for (i = MBEDTLS_ARIA_BLOCKSIZE; i > 0; i--) {\n                if (++nonce_counter[i - 1] != 0) {\n                    break;\n                }\n            }\n        }\n        c = *input++;\n        *output++ = (unsigned char) (c ^ stream_block[n]);\n\n        n = (n + 1) & 0x0F;\n    }\n\n    *nc_off = n;\n\n    return 0;\n}\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n#endif /* !MBEDTLS_ARIA_ALT */\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/*\n * Basic ARIA ECB test vectors from RFC 5794\n */\nstatic const uint8_t aria_test1_ecb_key[32] =           // test key\n{\n    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,     // 128 bit\n    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,\n    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,     // 192 bit\n    0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F      // 256 bit\n};\n\nstatic const uint8_t aria_test1_ecb_pt[MBEDTLS_ARIA_BLOCKSIZE] =            // plaintext\n{\n    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,     // same for all\n    0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF      // key sizes\n};\n\nstatic const uint8_t aria_test1_ecb_ct[3][MBEDTLS_ARIA_BLOCKSIZE] =         // ciphertext\n{\n    { 0xD7, 0x18, 0xFB, 0xD6, 0xAB, 0x64, 0x4C, 0x73,   // 128 bit\n      0x9D, 0xA9, 0x5F, 0x3B, 0xE6, 0x45, 0x17, 0x78 },\n    { 0x26, 0x44, 0x9C, 0x18, 0x05, 0xDB, 0xE7, 0xAA,   // 192 bit\n      0x25, 0xA4, 0x68, 0xCE, 0x26, 0x3A, 0x9E, 0x79 },\n    { 0xF9, 0x2B, 0xD7, 0xC7, 0x9F, 0xB7, 0x2E, 0x2F,   // 256 bit\n      0x2B, 0x8F, 0x80, 0xC1, 0x97, 0x2D, 0x24, 0xFC }\n};\n\n/*\n * Mode tests from \"Test Vectors for ARIA\"  Version 1.0\n * http://210.104.33.10/ARIA/doc/ARIA-testvector-e.pdf\n */\n#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \\\n    defined(MBEDTLS_CIPHER_MODE_CTR))\nstatic const uint8_t aria_test2_key[32] =\n{\n    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,     // 128 bit\n    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,\n    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,     // 192 bit\n    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff      // 256 bit\n};\n\nstatic const uint8_t aria_test2_pt[48] =\n{\n    0x11, 0x11, 0x11, 0x11, 0xaa, 0xaa, 0xaa, 0xaa,     // same for all\n    0x11, 0x11, 0x11, 0x11, 0xbb, 0xbb, 0xbb, 0xbb,\n    0x11, 0x11, 0x11, 0x11, 0xcc, 0xcc, 0xcc, 0xcc,\n    0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd,\n    0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa,\n    0x22, 0x22, 0x22, 0x22, 0xbb, 0xbb, 0xbb, 0xbb,\n};\n#endif\n\n#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB))\nstatic const uint8_t aria_test2_iv[MBEDTLS_ARIA_BLOCKSIZE] =\n{\n    0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78,     // same for CBC, CFB\n    0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0      // CTR has zero IV\n};\n#endif\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\nstatic const uint8_t aria_test2_cbc_ct[3][48] =         // CBC ciphertext\n{\n    { 0x49, 0xd6, 0x18, 0x60, 0xb1, 0x49, 0x09, 0x10,   // 128-bit key\n      0x9c, 0xef, 0x0d, 0x22, 0xa9, 0x26, 0x81, 0x34,\n      0xfa, 0xdf, 0x9f, 0xb2, 0x31, 0x51, 0xe9, 0x64,\n      0x5f, 0xba, 0x75, 0x01, 0x8b, 0xdb, 0x15, 0x38,\n      0xb5, 0x33, 0x34, 0x63, 0x4b, 0xbf, 0x7d, 0x4c,\n      0xd4, 0xb5, 0x37, 0x70, 0x33, 0x06, 0x0c, 0x15 },\n    { 0xaf, 0xe6, 0xcf, 0x23, 0x97, 0x4b, 0x53, 0x3c,   // 192-bit key\n      0x67, 0x2a, 0x82, 0x62, 0x64, 0xea, 0x78, 0x5f,\n      0x4e, 0x4f, 0x7f, 0x78, 0x0d, 0xc7, 0xf3, 0xf1,\n      0xe0, 0x96, 0x2b, 0x80, 0x90, 0x23, 0x86, 0xd5,\n      0x14, 0xe9, 0xc3, 0xe7, 0x72, 0x59, 0xde, 0x92,\n      0xdd, 0x11, 0x02, 0xff, 0xab, 0x08, 0x6c, 0x1e },\n    { 0x52, 0x3a, 0x8a, 0x80, 0x6a, 0xe6, 0x21, 0xf1,   // 256-bit key\n      0x55, 0xfd, 0xd2, 0x8d, 0xbc, 0x34, 0xe1, 0xab,\n      0x7b, 0x9b, 0x42, 0x43, 0x2a, 0xd8, 0xb2, 0xef,\n      0xb9, 0x6e, 0x23, 0xb1, 0x3f, 0x0a, 0x6e, 0x52,\n      0xf3, 0x61, 0x85, 0xd5, 0x0a, 0xd0, 0x02, 0xc5,\n      0xf6, 0x01, 0xbe, 0xe5, 0x49, 0x3f, 0x11, 0x8b }\n};\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\nstatic const uint8_t aria_test2_cfb_ct[3][48] =         // CFB ciphertext\n{\n    { 0x37, 0x20, 0xe5, 0x3b, 0xa7, 0xd6, 0x15, 0x38,   // 128-bit key\n      0x34, 0x06, 0xb0, 0x9f, 0x0a, 0x05, 0xa2, 0x00,\n      0xc0, 0x7c, 0x21, 0xe6, 0x37, 0x0f, 0x41, 0x3a,\n      0x5d, 0x13, 0x25, 0x00, 0xa6, 0x82, 0x85, 0x01,\n      0x7c, 0x61, 0xb4, 0x34, 0xc7, 0xb7, 0xca, 0x96,\n      0x85, 0xa5, 0x10, 0x71, 0x86, 0x1e, 0x4d, 0x4b },\n    { 0x41, 0x71, 0xf7, 0x19, 0x2b, 0xf4, 0x49, 0x54,   // 192-bit key\n      0x94, 0xd2, 0x73, 0x61, 0x29, 0x64, 0x0f, 0x5c,\n      0x4d, 0x87, 0xa9, 0xa2, 0x13, 0x66, 0x4c, 0x94,\n      0x48, 0x47, 0x7c, 0x6e, 0xcc, 0x20, 0x13, 0x59,\n      0x8d, 0x97, 0x66, 0x95, 0x2d, 0xd8, 0xc3, 0x86,\n      0x8f, 0x17, 0xe3, 0x6e, 0xf6, 0x6f, 0xd8, 0x4b },\n    { 0x26, 0x83, 0x47, 0x05, 0xb0, 0xf2, 0xc0, 0xe2,   // 256-bit key\n      0x58, 0x8d, 0x4a, 0x7f, 0x09, 0x00, 0x96, 0x35,\n      0xf2, 0x8b, 0xb9, 0x3d, 0x8c, 0x31, 0xf8, 0x70,\n      0xec, 0x1e, 0x0b, 0xdb, 0x08, 0x2b, 0x66, 0xfa,\n      0x40, 0x2d, 0xd9, 0xc2, 0x02, 0xbe, 0x30, 0x0c,\n      0x45, 0x17, 0xd1, 0x96, 0xb1, 0x4d, 0x4c, 0xe1 }\n};\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\nstatic const uint8_t aria_test2_ctr_ct[3][48] =         // CTR ciphertext\n{\n    { 0xac, 0x5d, 0x7d, 0xe8, 0x05, 0xa0, 0xbf, 0x1c,   // 128-bit key\n      0x57, 0xc8, 0x54, 0x50, 0x1a, 0xf6, 0x0f, 0xa1,\n      0x14, 0x97, 0xe2, 0xa3, 0x45, 0x19, 0xde, 0xa1,\n      0x56, 0x9e, 0x91, 0xe5, 0xb5, 0xcc, 0xae, 0x2f,\n      0xf3, 0xbf, 0xa1, 0xbf, 0x97, 0x5f, 0x45, 0x71,\n      0xf4, 0x8b, 0xe1, 0x91, 0x61, 0x35, 0x46, 0xc3 },\n    { 0x08, 0x62, 0x5c, 0xa8, 0xfe, 0x56, 0x9c, 0x19,   // 192-bit key\n      0xba, 0x7a, 0xf3, 0x76, 0x0a, 0x6e, 0xd1, 0xce,\n      0xf4, 0xd1, 0x99, 0x26, 0x3e, 0x99, 0x9d, 0xde,\n      0x14, 0x08, 0x2d, 0xbb, 0xa7, 0x56, 0x0b, 0x79,\n      0xa4, 0xc6, 0xb4, 0x56, 0xb8, 0x70, 0x7d, 0xce,\n      0x75, 0x1f, 0x98, 0x54, 0xf1, 0x88, 0x93, 0xdf },\n    { 0x30, 0x02, 0x6c, 0x32, 0x96, 0x66, 0x14, 0x17,   // 256-bit key\n      0x21, 0x17, 0x8b, 0x99, 0xc0, 0xa1, 0xf1, 0xb2,\n      0xf0, 0x69, 0x40, 0x25, 0x3f, 0x7b, 0x30, 0x89,\n      0xe2, 0xa3, 0x0e, 0xa8, 0x6a, 0xa3, 0xc8, 0x8f,\n      0x59, 0x40, 0xf0, 0x5a, 0xd7, 0xee, 0x41, 0xd7,\n      0x13, 0x47, 0xbb, 0x72, 0x61, 0xe3, 0x48, 0xf1 }\n};\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#define ARIA_SELF_TEST_ASSERT(cond)                   \\\n    do {                                            \\\n        if (cond) {                                \\\n            if (verbose)                           \\\n            mbedtls_printf(\"failed\\n\");       \\\n            goto exit;                              \\\n        } else {                                    \\\n            if (verbose)                           \\\n            mbedtls_printf(\"passed\\n\");       \\\n        }                                           \\\n    } while (0)\n\n/*\n * Checkup routine\n */\nint mbedtls_aria_self_test(int verbose)\n{\n    int i;\n    uint8_t blk[MBEDTLS_ARIA_BLOCKSIZE];\n    mbedtls_aria_context ctx;\n    int ret = 1;\n\n#if (defined(MBEDTLS_CIPHER_MODE_CFB) || defined(MBEDTLS_CIPHER_MODE_CTR))\n    size_t j;\n#endif\n\n#if (defined(MBEDTLS_CIPHER_MODE_CBC) || \\\n    defined(MBEDTLS_CIPHER_MODE_CFB) || \\\n    defined(MBEDTLS_CIPHER_MODE_CTR))\n    uint8_t buf[48], iv[MBEDTLS_ARIA_BLOCKSIZE];\n#endif\n\n    mbedtls_aria_init(&ctx);\n\n    /*\n     * Test set 1\n     */\n    for (i = 0; i < 3; i++) {\n        /* test ECB encryption */\n        if (verbose) {\n            mbedtls_printf(\"  ARIA-ECB-%d (enc): \", 128 + 64 * i);\n        }\n        mbedtls_aria_setkey_enc(&ctx, aria_test1_ecb_key, 128 + 64 * i);\n        mbedtls_aria_crypt_ecb(&ctx, aria_test1_ecb_pt, blk);\n        ARIA_SELF_TEST_ASSERT(\n            memcmp(blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE)\n            != 0);\n\n        /* test ECB decryption */\n        if (verbose) {\n            mbedtls_printf(\"  ARIA-ECB-%d (dec): \", 128 + 64 * i);\n#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n            mbedtls_printf(\"skipped\\n\");\n#endif\n        }\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n        mbedtls_aria_setkey_dec(&ctx, aria_test1_ecb_key, 128 + 64 * i);\n        mbedtls_aria_crypt_ecb(&ctx, aria_test1_ecb_ct[i], blk);\n        ARIA_SELF_TEST_ASSERT(\n            memcmp(blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE)\n            != 0);\n#endif\n    }\n    if (verbose) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    /*\n     * Test set 2\n     */\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    for (i = 0; i < 3; i++) {\n        /* Test CBC encryption */\n        if (verbose) {\n            mbedtls_printf(\"  ARIA-CBC-%d (enc): \", 128 + 64 * i);\n        }\n        mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i);\n        memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE);\n        memset(buf, 0x55, sizeof(buf));\n        mbedtls_aria_crypt_cbc(&ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv,\n                               aria_test2_pt, buf);\n        ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_cbc_ct[i], 48)\n                              != 0);\n\n        /* Test CBC decryption */\n        if (verbose) {\n            mbedtls_printf(\"  ARIA-CBC-%d (dec): \", 128 + 64 * i);\n        }\n        mbedtls_aria_setkey_dec(&ctx, aria_test2_key, 128 + 64 * i);\n        memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE);\n        memset(buf, 0xAA, sizeof(buf));\n        mbedtls_aria_crypt_cbc(&ctx, MBEDTLS_ARIA_DECRYPT, 48, iv,\n                               aria_test2_cbc_ct[i], buf);\n        ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0);\n    }\n    if (verbose) {\n        mbedtls_printf(\"\\n\");\n    }\n\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    for (i = 0; i < 3; i++) {\n        /* Test CFB encryption */\n        if (verbose) {\n            mbedtls_printf(\"  ARIA-CFB-%d (enc): \", 128 + 64 * i);\n        }\n        mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i);\n        memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE);\n        memset(buf, 0x55, sizeof(buf));\n        j = 0;\n        mbedtls_aria_crypt_cfb128(&ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv,\n                                  aria_test2_pt, buf);\n        ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_cfb_ct[i], 48) != 0);\n\n        /* Test CFB decryption */\n        if (verbose) {\n            mbedtls_printf(\"  ARIA-CFB-%d (dec): \", 128 + 64 * i);\n        }\n        mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i);\n        memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE);\n        memset(buf, 0xAA, sizeof(buf));\n        j = 0;\n        mbedtls_aria_crypt_cfb128(&ctx, MBEDTLS_ARIA_DECRYPT, 48, &j,\n                                  iv, aria_test2_cfb_ct[i], buf);\n        ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0);\n    }\n    if (verbose) {\n        mbedtls_printf(\"\\n\");\n    }\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    for (i = 0; i < 3; i++) {\n        /* Test CTR encryption */\n        if (verbose) {\n            mbedtls_printf(\"  ARIA-CTR-%d (enc): \", 128 + 64 * i);\n        }\n        mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i);\n        memset(iv, 0, MBEDTLS_ARIA_BLOCKSIZE);                      // IV = 0\n        memset(buf, 0x55, sizeof(buf));\n        j = 0;\n        mbedtls_aria_crypt_ctr(&ctx, 48, &j, iv, blk,\n                               aria_test2_pt, buf);\n        ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_ctr_ct[i], 48) != 0);\n\n        /* Test CTR decryption */\n        if (verbose) {\n            mbedtls_printf(\"  ARIA-CTR-%d (dec): \", 128 + 64 * i);\n        }\n        mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i);\n        memset(iv, 0, MBEDTLS_ARIA_BLOCKSIZE);                      // IV = 0\n        memset(buf, 0xAA, sizeof(buf));\n        j = 0;\n        mbedtls_aria_crypt_ctr(&ctx, 48, &j, iv, blk,\n                               aria_test2_ctr_ct[i], buf);\n        ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0);\n    }\n    if (verbose) {\n        mbedtls_printf(\"\\n\");\n    }\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n    ret = 0;\n\nexit:\n    mbedtls_aria_free(&ctx);\n    return ret;\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_ARIA_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/asn1parse.c",
    "content": "/*\n *  Generic ASN.1 parsing\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \\\n    defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)\n\n#include \"mbedtls/asn1.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_BIGNUM_C)\n#include \"mbedtls/bignum.h\"\n#endif\n\n#include \"mbedtls/platform.h\"\n\n/*\n * ASN.1 DER decoding routines\n */\nint mbedtls_asn1_get_len(unsigned char **p,\n                         const unsigned char *end,\n                         size_t *len)\n{\n    if ((end - *p) < 1) {\n        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;\n    }\n\n    if ((**p & 0x80) == 0) {\n        *len = *(*p)++;\n    } else {\n        int n = (**p) & 0x7F;\n        if (n == 0 || n > 4) {\n            return MBEDTLS_ERR_ASN1_INVALID_LENGTH;\n        }\n        if ((end - *p) <= n) {\n            return MBEDTLS_ERR_ASN1_OUT_OF_DATA;\n        }\n        *len = 0;\n        (*p)++;\n        while (n--) {\n            *len = (*len << 8) | **p;\n            (*p)++;\n        }\n    }\n\n    if (*len > (size_t) (end - *p)) {\n        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;\n    }\n\n    return 0;\n}\n\nint mbedtls_asn1_get_tag(unsigned char **p,\n                         const unsigned char *end,\n                         size_t *len, int tag)\n{\n    if ((end - *p) < 1) {\n        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;\n    }\n\n    if (**p != tag) {\n        return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;\n    }\n\n    (*p)++;\n\n    return mbedtls_asn1_get_len(p, end, len);\n}\n#endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */\n\n#if defined(MBEDTLS_ASN1_PARSE_C)\nint mbedtls_asn1_get_bool(unsigned char **p,\n                          const unsigned char *end,\n                          int *val)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0) {\n        return ret;\n    }\n\n    if (len != 1) {\n        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;\n    }\n\n    *val = (**p != 0) ? 1 : 0;\n    (*p)++;\n\n    return 0;\n}\n\nstatic int asn1_get_tagged_int(unsigned char **p,\n                               const unsigned char *end,\n                               int tag, int *val)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &len, tag)) != 0) {\n        return ret;\n    }\n\n    /*\n     * len==0 is malformed (0 must be represented as 020100 for INTEGER,\n     * or 0A0100 for ENUMERATED tags\n     */\n    if (len == 0) {\n        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;\n    }\n    /* This is a cryptography library. Reject negative integers. */\n    if ((**p & 0x80) != 0) {\n        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;\n    }\n\n    /* Skip leading zeros. */\n    while (len > 0 && **p == 0) {\n        ++(*p);\n        --len;\n    }\n\n    /* Reject integers that don't fit in an int. This code assumes that\n     * the int type has no padding bit. */\n    if (len > sizeof(int)) {\n        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;\n    }\n    if (len == sizeof(int) && (**p & 0x80) != 0) {\n        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;\n    }\n\n    *val = 0;\n    while (len-- > 0) {\n        *val = (*val << 8) | **p;\n        (*p)++;\n    }\n\n    return 0;\n}\n\nint mbedtls_asn1_get_int(unsigned char **p,\n                         const unsigned char *end,\n                         int *val)\n{\n    return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_INTEGER, val);\n}\n\nint mbedtls_asn1_get_enum(unsigned char **p,\n                          const unsigned char *end,\n                          int *val)\n{\n    return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_ENUMERATED, val);\n}\n\n#if defined(MBEDTLS_BIGNUM_C)\nint mbedtls_asn1_get_mpi(unsigned char **p,\n                         const unsigned char *end,\n                         mbedtls_mpi *X)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_mpi_read_binary(X, *p, len);\n\n    *p += len;\n\n    return ret;\n}\n#endif /* MBEDTLS_BIGNUM_C */\n\nint mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end,\n                               mbedtls_asn1_bitstring *bs)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* Certificate type is a single byte bitstring */\n    if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0) {\n        return ret;\n    }\n\n    /* Check length, subtract one for actual bit string length */\n    if (bs->len < 1) {\n        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;\n    }\n    bs->len -= 1;\n\n    /* Get number of unused bits, ensure unused bits <= 7 */\n    bs->unused_bits = **p;\n    if (bs->unused_bits > 7) {\n        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;\n    }\n    (*p)++;\n\n    /* Get actual bitstring */\n    bs->p = *p;\n    *p += bs->len;\n\n    if (*p != end) {\n        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;\n    }\n\n    return 0;\n}\n\n/*\n * Traverse an ASN.1 \"SEQUENCE OF <tag>\"\n * and call a callback for each entry found.\n */\nint mbedtls_asn1_traverse_sequence_of(\n    unsigned char **p,\n    const unsigned char *end,\n    unsigned char tag_must_mask, unsigned char tag_must_val,\n    unsigned char tag_may_mask, unsigned char tag_may_val,\n    int (*cb)(void *ctx, int tag,\n              unsigned char *start, size_t len),\n    void *ctx)\n{\n    int ret;\n    size_t len;\n\n    /* Get main sequence tag */\n    if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return ret;\n    }\n\n    if (*p + len != end) {\n        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;\n    }\n\n    while (*p < end) {\n        unsigned char const tag = *(*p)++;\n\n        if ((tag & tag_must_mask) != tag_must_val) {\n            return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;\n        }\n\n        if ((ret = mbedtls_asn1_get_len(p, end, &len)) != 0) {\n            return ret;\n        }\n\n        if ((tag & tag_may_mask) == tag_may_val) {\n            if (cb != NULL) {\n                ret = cb(ctx, tag, *p, len);\n                if (ret != 0) {\n                    return ret;\n                }\n            }\n        }\n\n        *p += len;\n    }\n\n    return 0;\n}\n\n/*\n * Get a bit string without unused bits\n */\nint mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end,\n                                    size_t *len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0) {\n        return ret;\n    }\n\n    if (*len == 0) {\n        return MBEDTLS_ERR_ASN1_INVALID_DATA;\n    }\n    --(*len);\n\n    if (**p != 0) {\n        return MBEDTLS_ERR_ASN1_INVALID_DATA;\n    }\n    ++(*p);\n\n    return 0;\n}\n\nvoid mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq)\n{\n    while (seq != NULL) {\n        mbedtls_asn1_sequence *next = seq->next;\n        mbedtls_free(seq);\n        seq = next;\n    }\n}\n\ntypedef struct {\n    int tag;\n    mbedtls_asn1_sequence *cur;\n} asn1_get_sequence_of_cb_ctx_t;\n\nstatic int asn1_get_sequence_of_cb(void *ctx,\n                                   int tag,\n                                   unsigned char *start,\n                                   size_t len)\n{\n    asn1_get_sequence_of_cb_ctx_t *cb_ctx =\n        (asn1_get_sequence_of_cb_ctx_t *) ctx;\n    mbedtls_asn1_sequence *cur =\n        cb_ctx->cur;\n\n    if (cur->buf.p != NULL) {\n        cur->next =\n            mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));\n\n        if (cur->next == NULL) {\n            return MBEDTLS_ERR_ASN1_ALLOC_FAILED;\n        }\n\n        cur = cur->next;\n    }\n\n    cur->buf.p = start;\n    cur->buf.len = len;\n    cur->buf.tag = tag;\n\n    cb_ctx->cur = cur;\n    return 0;\n}\n\n/*\n *  Parses and splits an ASN.1 \"SEQUENCE OF <tag>\"\n */\nint mbedtls_asn1_get_sequence_of(unsigned char **p,\n                                 const unsigned char *end,\n                                 mbedtls_asn1_sequence *cur,\n                                 int tag)\n{\n    asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };\n    memset(cur, 0, sizeof(mbedtls_asn1_sequence));\n    return mbedtls_asn1_traverse_sequence_of(\n        p, end, 0xFF, tag, 0, 0,\n        asn1_get_sequence_of_cb, &cb_ctx);\n}\n\nint mbedtls_asn1_get_alg(unsigned char **p,\n                         const unsigned char *end,\n                         mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return ret;\n    }\n\n    if ((end - *p) < 1) {\n        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;\n    }\n\n    alg->tag = **p;\n    end = *p + len;\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0) {\n        return ret;\n    }\n\n    alg->p = *p;\n    *p += alg->len;\n\n    if (*p == end) {\n        mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf));\n        return 0;\n    }\n\n    params->tag = **p;\n    (*p)++;\n\n    if ((ret = mbedtls_asn1_get_len(p, end, &params->len)) != 0) {\n        return ret;\n    }\n\n    params->p = *p;\n    *p += params->len;\n\n    if (*p != end) {\n        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;\n    }\n\n    return 0;\n}\n\nint mbedtls_asn1_get_alg_null(unsigned char **p,\n                              const unsigned char *end,\n                              mbedtls_asn1_buf *alg)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_asn1_buf params;\n\n    memset(&params, 0, sizeof(mbedtls_asn1_buf));\n\n    if ((ret = mbedtls_asn1_get_alg(p, end, alg, &params)) != 0) {\n        return ret;\n    }\n\n    if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0) {\n        return MBEDTLS_ERR_ASN1_INVALID_DATA;\n    }\n\n    return 0;\n}\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\nvoid mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur)\n{\n    if (cur == NULL) {\n        return;\n    }\n\n    mbedtls_free(cur->oid.p);\n    mbedtls_free(cur->val.p);\n\n    mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data));\n}\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n\nvoid mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head)\n{\n    mbedtls_asn1_named_data *cur;\n\n    while ((cur = *head) != NULL) {\n        *head = cur->next;\n        mbedtls_free(cur->oid.p);\n        mbedtls_free(cur->val.p);\n        mbedtls_free(cur);\n    }\n}\n\nvoid mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name)\n{\n    for (mbedtls_asn1_named_data *next; name != NULL; name = next) {\n        next = name->next;\n        mbedtls_free(name);\n    }\n}\n\nconst mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list,\n                                                            const char *oid, size_t len)\n{\n    while (list != NULL) {\n        if (list->oid.len == len &&\n            memcmp(list->oid.p, oid, len) == 0) {\n            break;\n        }\n\n        list = list->next;\n    }\n\n    return list;\n}\n\n#endif /* MBEDTLS_ASN1_PARSE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/asn1write.c",
    "content": "/*\n * ASN.1 buffer writing functionality\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C) || \\\n    defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)\n\n#include \"mbedtls/asn1write.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#if defined(MBEDTLS_ASN1_PARSE_C)\n#include \"mbedtls/asn1.h\"\n#endif\n\nint mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start, size_t len)\n{\n#if SIZE_MAX > 0xFFFFFFFF\n    if (len > 0xFFFFFFFF) {\n        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;\n    }\n#endif\n\n    int required = 1;\n\n    if (len >= 0x80) {\n        for (size_t l = len; l != 0; l >>= 8) {\n            required++;\n        }\n    }\n\n    if (required > (*p - start)) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n\n    do {\n        *--(*p) = MBEDTLS_BYTE_0(len);\n        len >>= 8;\n    } while (len);\n\n    if (required > 1) {\n        *--(*p) = (unsigned char) (0x80 + required - 1);\n    }\n\n    return required;\n}\n\nint mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start, unsigned char tag)\n{\n    if (*p - start < 1) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n\n    *--(*p) = tag;\n\n    return 1;\n}\n#endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */\n\n#if defined(MBEDTLS_ASN1_WRITE_C)\nstatic int mbedtls_asn1_write_len_and_tag(unsigned char **p,\n                                          const unsigned char *start,\n                                          size_t len,\n                                          unsigned char tag)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag));\n\n    return (int) len;\n}\n\nint mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start,\n                                  const unsigned char *buf, size_t size)\n{\n    size_t len = 0;\n\n    if (*p < start || (size_t) (*p - start) < size) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n\n    len = size;\n    (*p) -= len;\n    if (len != 0) {\n        memcpy(*p, buf, len);\n    }\n\n    return (int) len;\n}\n\n#if defined(MBEDTLS_BIGNUM_C)\nint mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start, const mbedtls_mpi *X)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n\n    // Write the MPI\n    //\n    len = mbedtls_mpi_size(X);\n\n    /* DER represents 0 with a sign bit (0=nonnegative) and 7 value bits, not\n     * as 0 digits. We need to end up with 020100, not with 0200. */\n    if (len == 0) {\n        len = 1;\n    }\n\n    if (*p < start || (size_t) (*p - start) < len) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n\n    (*p) -= len;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(X, *p, len));\n\n    // DER format assumes 2s complement for numbers, so the leftmost bit\n    // should be 0 for positive numbers and 1 for negative numbers.\n    //\n    if (X->s == 1 && **p & 0x80) {\n        if (*p - start < 1) {\n            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n        }\n\n        *--(*p) = 0x00;\n        len += 1;\n    }\n\n    ret = mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_INTEGER);\n\ncleanup:\n    return ret;\n}\n#endif /* MBEDTLS_BIGNUM_C */\n\nint mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start)\n{\n    // Write NULL\n    //\n    return mbedtls_asn1_write_len_and_tag(p, start, 0, MBEDTLS_ASN1_NULL);\n}\n\nint mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start,\n                           const char *oid, size_t oid_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,\n                                                            (const unsigned char *) oid, oid_len));\n    return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OID);\n}\n\nint mbedtls_asn1_write_algorithm_identifier(unsigned char **p, const unsigned char *start,\n                                            const char *oid, size_t oid_len,\n                                            size_t par_len)\n{\n    return mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len, par_len, 1);\n}\n\nint mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, const unsigned char *start,\n                                                const char *oid, size_t oid_len,\n                                                size_t par_len, int has_par)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n\n    if (has_par) {\n        if (par_len == 0) {\n            MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start));\n        } else {\n            len += par_len;\n        }\n    }\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));\n\n    return mbedtls_asn1_write_len_and_tag(p, start, len,\n                                          MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);\n}\n\nint mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start, int boolean)\n{\n    size_t len = 0;\n\n    if (*p - start < 1) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n\n    *--(*p) = (boolean) ? 255 : 0;\n    len++;\n\n    return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BOOLEAN);\n}\n\nstatic int asn1_write_tagged_int(unsigned char **p, const unsigned char *start, int val, int tag)\n{\n    size_t len = 0;\n\n    do {\n        if (*p - start < 1) {\n            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n        }\n        len += 1;\n        *--(*p) = val & 0xff;\n        val >>= 8;\n    } while (val > 0);\n\n    if (**p & 0x80) {\n        if (*p - start < 1) {\n            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n        }\n        *--(*p) = 0x00;\n        len += 1;\n    }\n\n    return mbedtls_asn1_write_len_and_tag(p, start, len, tag);\n}\n\nint mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val)\n{\n    return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_INTEGER);\n}\n\nint mbedtls_asn1_write_enum(unsigned char **p, const unsigned char *start, int val)\n{\n    return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_ENUMERATED);\n}\n\nint mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *start, int tag,\n                                     const char *text, size_t text_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,\n                                                            (const unsigned char *) text,\n                                                            text_len));\n\n    return mbedtls_asn1_write_len_and_tag(p, start, len, tag);\n}\n\nint mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start,\n                                   const char *text, size_t text_len)\n{\n    return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len);\n}\n\nint mbedtls_asn1_write_printable_string(unsigned char **p, const unsigned char *start,\n                                        const char *text, size_t text_len)\n{\n    return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text,\n                                            text_len);\n}\n\nint mbedtls_asn1_write_ia5_string(unsigned char **p, const unsigned char *start,\n                                  const char *text, size_t text_len)\n{\n    return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len);\n}\n\nint mbedtls_asn1_write_named_bitstring(unsigned char **p,\n                                       const unsigned char *start,\n                                       const unsigned char *buf,\n                                       size_t bits)\n{\n    size_t unused_bits, byte_len;\n    const unsigned char *cur_byte;\n    unsigned char cur_byte_shifted;\n    unsigned char bit;\n\n    byte_len = (bits + 7) / 8;\n    unused_bits = (byte_len * 8) - bits;\n\n    /*\n     * Named bitstrings require that trailing 0s are excluded in the encoding\n     * of the bitstring. Trailing 0s are considered part of the 'unused' bits\n     * when encoding this value in the first content octet\n     */\n    if (bits != 0) {\n        cur_byte = buf + byte_len - 1;\n        cur_byte_shifted = *cur_byte >> unused_bits;\n\n        for (;;) {\n            bit = cur_byte_shifted & 0x1;\n            cur_byte_shifted >>= 1;\n\n            if (bit != 0) {\n                break;\n            }\n\n            bits--;\n            if (bits == 0) {\n                break;\n            }\n\n            if (bits % 8 == 0) {\n                cur_byte_shifted = *--cur_byte;\n            }\n        }\n    }\n\n    return mbedtls_asn1_write_bitstring(p, start, buf, bits);\n}\n\nint mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start,\n                                 const unsigned char *buf, size_t bits)\n{\n    size_t len = 0;\n    size_t unused_bits, byte_len;\n\n    byte_len = (bits + 7) / 8;\n    unused_bits = (byte_len * 8) - bits;\n\n    if (*p < start || (size_t) (*p - start) < byte_len + 1) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n\n    len = byte_len + 1;\n\n    /* Write the bitstring. Ensure the unused bits are zeroed */\n    if (byte_len > 0) {\n        byte_len--;\n        *--(*p) = buf[byte_len] & ~((0x1 << unused_bits) - 1);\n        (*p) -= byte_len;\n        memcpy(*p, buf, byte_len);\n    }\n\n    /* Write unused bits */\n    *--(*p) = (unsigned char) unused_bits;\n\n    return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BIT_STRING);\n}\n\nint mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start,\n                                    const unsigned char *buf, size_t size)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, buf, size));\n\n    return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OCTET_STRING);\n}\n\n\n#if !defined(MBEDTLS_ASN1_PARSE_C)\n/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),\n * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */\nstatic mbedtls_asn1_named_data *asn1_find_named_data(\n    mbedtls_asn1_named_data *list,\n    const char *oid, size_t len)\n{\n    while (list != NULL) {\n        if (list->oid.len == len &&\n            memcmp(list->oid.p, oid, len) == 0) {\n            break;\n        }\n\n        list = list->next;\n    }\n\n    return list;\n}\n#else\n#define asn1_find_named_data(list, oid, len) \\\n    ((mbedtls_asn1_named_data *) mbedtls_asn1_find_named_data(list, oid, len))\n#endif\n\nmbedtls_asn1_named_data *mbedtls_asn1_store_named_data(\n    mbedtls_asn1_named_data **head,\n    const char *oid, size_t oid_len,\n    const unsigned char *val,\n    size_t val_len)\n{\n    mbedtls_asn1_named_data *cur;\n\n    if ((cur = asn1_find_named_data(*head, oid, oid_len)) == NULL) {\n        // Add new entry if not present yet based on OID\n        //\n        cur = (mbedtls_asn1_named_data *) mbedtls_calloc(1,\n                                                         sizeof(mbedtls_asn1_named_data));\n        if (cur == NULL) {\n            return NULL;\n        }\n\n        cur->oid.len = oid_len;\n        cur->oid.p = mbedtls_calloc(1, oid_len);\n        if (cur->oid.p == NULL) {\n            mbedtls_free(cur);\n            return NULL;\n        }\n\n        memcpy(cur->oid.p, oid, oid_len);\n\n        cur->val.len = val_len;\n        if (val_len != 0) {\n            cur->val.p = mbedtls_calloc(1, val_len);\n            if (cur->val.p == NULL) {\n                mbedtls_free(cur->oid.p);\n                mbedtls_free(cur);\n                return NULL;\n            }\n        }\n\n        cur->next = *head;\n        *head = cur;\n    } else if (val_len == 0) {\n        mbedtls_free(cur->val.p);\n        cur->val.p = NULL;\n        cur->val.len = 0;\n    } else if (cur->val.len != val_len) {\n        /*\n         * Enlarge existing value buffer if needed\n         * Preserve old data until the allocation succeeded, to leave list in\n         * a consistent state in case allocation fails.\n         */\n        void *p = mbedtls_calloc(1, val_len);\n        if (p == NULL) {\n            return NULL;\n        }\n\n        mbedtls_free(cur->val.p);\n        cur->val.p = p;\n        cur->val.len = val_len;\n    }\n\n    if (val != NULL && val_len != 0) {\n        memcpy(cur->val.p, val, val_len);\n    }\n\n    return cur;\n}\n#endif /* MBEDTLS_ASN1_WRITE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/base64.c",
    "content": "/*\n *  RFC 1521 base64 encoding/decoding\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include <limits.h>\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_BASE64_C)\n\n#include \"mbedtls/base64.h\"\n#include \"base64_internal.h\"\n#include \"constant_time_internal.h\"\n#include \"mbedtls/error.h\"\n\n#include <stdint.h>\n\n#if defined(MBEDTLS_SELF_TEST)\n#include <string.h>\n#include \"mbedtls/platform.h\"\n#endif /* MBEDTLS_SELF_TEST */\n\nMBEDTLS_STATIC_TESTABLE\nunsigned char mbedtls_ct_base64_enc_char(unsigned char value)\n{\n    unsigned char digit = 0;\n    /* For each range of values, if value is in that range, mask digit with\n     * the corresponding value. Since value can only be in a single range,\n     * only at most one masking will change digit. */\n    digit |= mbedtls_ct_uchar_in_range_if(0, 25, value, 'A' + value);\n    digit |= mbedtls_ct_uchar_in_range_if(26, 51, value, 'a' + value - 26);\n    digit |= mbedtls_ct_uchar_in_range_if(52, 61, value, '0' + value - 52);\n    digit |= mbedtls_ct_uchar_in_range_if(62, 62, value, '+');\n    digit |= mbedtls_ct_uchar_in_range_if(63, 63, value, '/');\n    return digit;\n}\n\nMBEDTLS_STATIC_TESTABLE\nsigned char mbedtls_ct_base64_dec_value(unsigned char c)\n{\n    unsigned char val = 0;\n    /* For each range of digits, if c is in that range, mask val with\n     * the corresponding value. Since c can only be in a single range,\n     * only at most one masking will change val. Set val to one plus\n     * the desired value so that it stays 0 if c is in none of the ranges. */\n    val |= mbedtls_ct_uchar_in_range_if('A', 'Z', c, c - 'A' +  0 + 1);\n    val |= mbedtls_ct_uchar_in_range_if('a', 'z', c, c - 'a' + 26 + 1);\n    val |= mbedtls_ct_uchar_in_range_if('0', '9', c, c - '0' + 52 + 1);\n    val |= mbedtls_ct_uchar_in_range_if('+', '+', c, c - '+' + 62 + 1);\n    val |= mbedtls_ct_uchar_in_range_if('/', '/', c, c - '/' + 63 + 1);\n    /* At this point, val is 0 if c is an invalid digit and v+1 if c is\n     * a digit with the value v. */\n    return val - 1;\n}\n\n/*\n * Encode a buffer into base64 format\n */\nint mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen,\n                          const unsigned char *src, size_t slen)\n{\n    size_t i, n;\n    int C1, C2, C3;\n    unsigned char *p;\n\n    if (slen == 0) {\n        *olen = 0;\n        return 0;\n    }\n\n    n = slen / 3 + (slen % 3 != 0);\n\n    if (n > (SIZE_MAX - 1) / 4) {\n        *olen = SIZE_MAX;\n        return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;\n    }\n\n    n *= 4;\n\n    if ((dlen < n + 1) || (NULL == dst)) {\n        *olen = n + 1;\n        return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;\n    }\n\n    n = (slen / 3) * 3;\n\n    for (i = 0, p = dst; i < n; i += 3) {\n        C1 = *src++;\n        C2 = *src++;\n        C3 = *src++;\n\n        *p++ = mbedtls_ct_base64_enc_char((C1 >> 2) & 0x3F);\n        *p++ = mbedtls_ct_base64_enc_char((((C1 &  3) << 4) + (C2 >> 4))\n                                          & 0x3F);\n        *p++ = mbedtls_ct_base64_enc_char((((C2 & 15) << 2) + (C3 >> 6))\n                                          & 0x3F);\n        *p++ = mbedtls_ct_base64_enc_char(C3 & 0x3F);\n    }\n\n    if (i < slen) {\n        C1 = *src++;\n        C2 = ((i + 1) < slen) ? *src++ : 0;\n\n        *p++ = mbedtls_ct_base64_enc_char((C1 >> 2) & 0x3F);\n        *p++ = mbedtls_ct_base64_enc_char((((C1 & 3) << 4) + (C2 >> 4))\n                                          & 0x3F);\n\n        if ((i + 1) < slen) {\n            *p++ = mbedtls_ct_base64_enc_char(((C2 & 15) << 2) & 0x3F);\n        } else {\n            *p++ = '=';\n        }\n\n        *p++ = '=';\n    }\n\n    *olen = (size_t) (p - dst);\n    *p = 0;\n\n    return 0;\n}\n\n/*\n * Decode a base64-formatted buffer\n */\nint mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen,\n                          const unsigned char *src, size_t slen)\n{\n    size_t i; /* index in source */\n    size_t n; /* number of digits or trailing = in source */\n    uint32_t x; /* value accumulator */\n    unsigned accumulated_digits = 0;\n    unsigned equals = 0;\n    int spaces_present = 0;\n    unsigned char *p;\n\n    /* First pass: check for validity and get output length */\n    for (i = n = 0; i < slen; i++) {\n        /* Skip spaces before checking for EOL */\n        spaces_present = 0;\n        while (i < slen && src[i] == ' ') {\n            ++i;\n            spaces_present = 1;\n        }\n\n        /* Spaces at end of buffer are OK */\n        if (i == slen) {\n            break;\n        }\n\n        if ((slen - i) >= 2 &&\n            src[i] == '\\r' && src[i + 1] == '\\n') {\n            continue;\n        }\n\n        if (src[i] == '\\n') {\n            continue;\n        }\n\n        /* Space inside a line is an error */\n        if (spaces_present) {\n            return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;\n        }\n\n        if (src[i] > 127) {\n            return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;\n        }\n\n        if (src[i] == '=') {\n            if (++equals > 2) {\n                return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;\n            }\n        } else {\n            if (equals != 0) {\n                return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;\n            }\n            if (mbedtls_ct_base64_dec_value(src[i]) < 0) {\n                return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;\n            }\n        }\n        n++;\n    }\n\n    /* In valid base64, the number of digits (n-equals) is always of the form\n     * 4*k, 4*k+2 or *4k+3. Also, the number n of digits plus the number of\n     * equal signs at the end is always a multiple of 4. */\n    if ((n - equals) % 4 == 1) {\n        return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;\n    }\n    if (n % 4 != 0) {\n        return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;\n    }\n\n    /* We've determined that the input is valid, and that it contains\n     * exactly k blocks of digits-or-equals, with n = 4 * k,\n     * and equals only present at the end of the last block if at all.\n     * Now we can calculate the length of the output.\n     *\n     * Each block of 4 digits in the input map to 3 bytes of output.\n     * For the last block:\n     * - abcd (where abcd are digits) is a full 3-byte block;\n     * - abc= means 1 byte less than a full 3-byte block of output;\n     * - ab== means 2 bytes less than a full 3-byte block of output;\n     * - a==== and ==== is rejected above.\n     */\n    *olen = (n / 4) * 3 - equals;\n\n    /* If the output buffer is too small, signal this and stop here.\n     * Also, as documented, stop here if `dst` is null, independently of\n     * `dlen`.\n     *\n     * There is an edge case when the output is empty: in this case,\n     * `dlen == 0` with `dst == NULL` is valid (on some platforms,\n     * `malloc(0)` returns `NULL`). Since the call is valid, we return\n     * 0 in this case.\n     */\n    if ((*olen != 0 && dst == NULL) || dlen < *olen) {\n        return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;\n    }\n\n    for (x = 0, p = dst; i > 0; i--, src++) {\n        if (*src == '\\r' || *src == '\\n' || *src == ' ') {\n            continue;\n        }\n        if (*src == '=') {\n            /* We already know from the first loop that equal signs are\n             * only at the end. */\n            break;\n        }\n        x = x << 6;\n        x |= mbedtls_ct_base64_dec_value(*src);\n\n        if (++accumulated_digits == 4) {\n            accumulated_digits = 0;\n            *p++ = MBEDTLS_BYTE_2(x);\n            *p++ = MBEDTLS_BYTE_1(x);\n            *p++ = MBEDTLS_BYTE_0(x);\n        }\n    }\n    if (accumulated_digits == 3) {\n        *p++ = MBEDTLS_BYTE_2(x << 6);\n        *p++ = MBEDTLS_BYTE_1(x << 6);\n    } else if (accumulated_digits == 2) {\n        *p++ = MBEDTLS_BYTE_2(x << 12);\n    }\n\n    if (*olen != (size_t) (p - dst)) {\n        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    }\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SELF_TEST)\n\nstatic const unsigned char base64_test_dec[64] =\n{\n    0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,\n    0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,\n    0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,\n    0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,\n    0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,\n    0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,\n    0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,\n    0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97\n};\n\nstatic const unsigned char base64_test_enc[] =\n    \"JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK\"\n    \"swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==\";\n\n/*\n * Checkup routine\n */\nint mbedtls_base64_self_test(int verbose)\n{\n    size_t len;\n    const unsigned char *src;\n    unsigned char buffer[128];\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  Base64 encoding test: \");\n    }\n\n    src = base64_test_dec;\n\n    if (mbedtls_base64_encode(buffer, sizeof(buffer), &len, src, 64) != 0 ||\n        memcmp(base64_test_enc, buffer, 88) != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n\n        return 1;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n  Base64 decoding test: \");\n    }\n\n    src = base64_test_enc;\n\n    if (mbedtls_base64_decode(buffer, sizeof(buffer), &len, src, 88) != 0 ||\n        memcmp(base64_test_dec, buffer, 64) != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n\n        return 1;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\\n\");\n    }\n\n    return 0;\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_BASE64_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/base64_internal.h",
    "content": "/**\n * \\file base64_internal.h\n *\n * \\brief RFC 1521 base64 encoding/decoding: interfaces for invasive testing\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_BASE64_INTERNAL\n#define MBEDTLS_BASE64_INTERNAL\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_TEST_HOOKS)\n\n/** Given a value in the range 0..63, return the corresponding Base64 digit.\n *\n * The implementation assumes that letters are consecutive (e.g. ASCII\n * but not EBCDIC).\n *\n * \\param value     A value in the range 0..63.\n *\n * \\return          A base64 digit converted from \\p value.\n */\nunsigned char mbedtls_ct_base64_enc_char(unsigned char value);\n\n/** Given a Base64 digit, return its value.\n *\n * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),\n * return -1.\n *\n * The implementation assumes that letters are consecutive (e.g. ASCII\n * but not EBCDIC).\n *\n * \\param c     A base64 digit.\n *\n * \\return      The value of the base64 digit \\p c.\n */\nsigned char mbedtls_ct_base64_dec_value(unsigned char c);\n\n#endif /* MBEDTLS_TEST_HOOKS */\n\n#endif /* MBEDTLS_BASE64_INTERNAL */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/bignum.c",
    "content": "/*\n *  Multi-precision integer library\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n *  The following sources were referenced in the design of this Multi-precision\n *  Integer library:\n *\n *  [1] Handbook of Applied Cryptography - 1997\n *      Menezes, van Oorschot and Vanstone\n *\n *  [2] Multi-Precision Math\n *      Tom St Denis\n *      https://github.com/libtom/libtommath/blob/develop/tommath.pdf\n *\n *  [3] GNU Multi-Precision Arithmetic Library\n *      https://gmplib.org/manual/index.html\n *\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_BIGNUM_C)\n\n#include \"mbedtls/bignum.h\"\n#include \"bignum_core.h\"\n#include \"bignum_internal.h\"\n#include \"bn_mul.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n#include \"constant_time_internal.h\"\n\n#include <limits.h>\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n\n\n/*\n * Conditionally select an MPI sign in constant time.\n * (MPI sign is the field s in mbedtls_mpi. It is unsigned short and only 1 and -1 are valid\n * values.)\n */\nstatic inline signed short mbedtls_ct_mpi_sign_if(mbedtls_ct_condition_t cond,\n                                                  signed short sign1, signed short sign2)\n{\n    return (signed short) mbedtls_ct_uint_if(cond, sign1 + 1, sign2 + 1) - 1;\n}\n\n/*\n * Compare signed values in constant time\n */\nint mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,\n                          const mbedtls_mpi *Y,\n                          unsigned *ret)\n{\n    mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result;\n\n    if (X->n != Y->n) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    /*\n     * Set N_is_negative to MBEDTLS_CT_FALSE if N >= 0, MBEDTLS_CT_TRUE if N < 0.\n     * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.\n     */\n    X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1);\n    Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1);\n\n    /*\n     * If the signs are different, then the positive operand is the bigger.\n     * That is if X is negative (X_is_negative == 1), then X < Y is true and it\n     * is false if X is positive (X_is_negative == 0).\n     */\n    different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign\n    result = mbedtls_ct_bool_and(different_sign, X_is_negative);\n\n    /*\n     * Assuming signs are the same, compare X and Y. We switch the comparison\n     * order if they are negative so that we get the right result, regardles of\n     * sign.\n     */\n\n    /* This array is used to conditionally swap the pointers in const time */\n    void * const p[2] = { X->p, Y->p };\n    size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1);\n    mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n);\n\n    /*\n     * Store in result iff the signs are the same (i.e., iff different_sign == false). If\n     * the signs differ, result has already been set, so we don't change it.\n     */\n    result = mbedtls_ct_bool_or(result,\n                                mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt));\n\n    *ret = mbedtls_ct_uint_if_else_0(result, 1);\n\n    return 0;\n}\n\n/*\n * Conditionally assign X = Y, without leaking information\n * about whether the assignment was made or not.\n * (Leaking information about the respective sizes of X and Y is ok however.)\n */\n#if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \\\n    (_MSC_FULL_VER < 193131103)\n/*\n * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:\n * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989\n */\n__declspec(noinline)\n#endif\nint mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,\n                                 const mbedtls_mpi *Y,\n                                 unsigned char assign)\n{\n    int ret = 0;\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));\n\n    {\n        mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);\n\n        X->s = mbedtls_ct_mpi_sign_if(do_assign, Y->s, X->s);\n\n        mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);\n\n        mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign);\n        for (size_t i = Y->n; i < X->n; i++) {\n            X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]);\n        }\n    }\n\ncleanup:\n    return ret;\n}\n\n/*\n * Conditionally swap X and Y, without leaking information\n * about whether the swap was made or not.\n * Here it is not ok to simply swap the pointers, which would lead to\n * different memory access patterns when X and Y are used afterwards.\n */\nint mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,\n                               mbedtls_mpi *Y,\n                               unsigned char swap)\n{\n    int ret = 0;\n    int s;\n\n    if (X == Y) {\n        return 0;\n    }\n\n    mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap);\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));\n\n    s = X->s;\n    X->s = mbedtls_ct_mpi_sign_if(do_swap, Y->s, X->s);\n    Y->s = mbedtls_ct_mpi_sign_if(do_swap, s, Y->s);\n\n    mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);\n\ncleanup:\n    return ret;\n}\n\n/* Implementation that should never be optimized out by the compiler */\n#define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n))\n\n/*\n * Initialize one MPI\n */\nvoid mbedtls_mpi_init(mbedtls_mpi *X)\n{\n    X->s = 1;\n    X->n = 0;\n    X->p = NULL;\n}\n\n/*\n * Unallocate one MPI\n */\nvoid mbedtls_mpi_free(mbedtls_mpi *X)\n{\n    if (X == NULL) {\n        return;\n    }\n\n    if (X->p != NULL) {\n        mbedtls_mpi_zeroize_and_free(X->p, X->n);\n    }\n\n    X->s = 1;\n    X->n = 0;\n    X->p = NULL;\n}\n\n/*\n * Enlarge to the specified number of limbs\n */\nint mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)\n{\n    mbedtls_mpi_uint *p;\n\n    if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {\n        return MBEDTLS_ERR_MPI_ALLOC_FAILED;\n    }\n\n    if (X->n < nblimbs) {\n        if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) {\n            return MBEDTLS_ERR_MPI_ALLOC_FAILED;\n        }\n\n        if (X->p != NULL) {\n            memcpy(p, X->p, X->n * ciL);\n            mbedtls_mpi_zeroize_and_free(X->p, X->n);\n        }\n\n        /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS\n         * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */\n        X->n = (unsigned short) nblimbs;\n        X->p = p;\n    }\n\n    return 0;\n}\n\n/*\n * Resize down as much as possible,\n * while keeping at least the specified number of limbs\n */\nint mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)\n{\n    mbedtls_mpi_uint *p;\n    size_t i;\n\n    if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {\n        return MBEDTLS_ERR_MPI_ALLOC_FAILED;\n    }\n\n    /* Actually resize up if there are currently fewer than nblimbs limbs. */\n    if (X->n <= nblimbs) {\n        return mbedtls_mpi_grow(X, nblimbs);\n    }\n    /* After this point, then X->n > nblimbs and in particular X->n > 0. */\n\n    for (i = X->n - 1; i > 0; i--) {\n        if (X->p[i] != 0) {\n            break;\n        }\n    }\n    i++;\n\n    if (i < nblimbs) {\n        i = nblimbs;\n    }\n\n    if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) {\n        return MBEDTLS_ERR_MPI_ALLOC_FAILED;\n    }\n\n    if (X->p != NULL) {\n        memcpy(p, X->p, i * ciL);\n        mbedtls_mpi_zeroize_and_free(X->p, X->n);\n    }\n\n    /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS\n     * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */\n    X->n = (unsigned short) i;\n    X->p = p;\n\n    return 0;\n}\n\n/* Resize X to have exactly n limbs and set it to 0. */\nstatic int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)\n{\n    if (limbs == 0) {\n        mbedtls_mpi_free(X);\n        return 0;\n    } else if (X->n == limbs) {\n        memset(X->p, 0, limbs * ciL);\n        X->s = 1;\n        return 0;\n    } else {\n        mbedtls_mpi_free(X);\n        return mbedtls_mpi_grow(X, limbs);\n    }\n}\n\n/*\n * Copy the contents of Y into X.\n *\n * This function is not constant-time. Leading zeros in Y may be removed.\n *\n * Ensure that X does not shrink. This is not guaranteed by the public API,\n * but some code in the bignum module might still rely on this property.\n */\nint mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)\n{\n    int ret = 0;\n    size_t i;\n\n    if (X == Y) {\n        return 0;\n    }\n\n    if (Y->n == 0) {\n        if (X->n != 0) {\n            X->s = 1;\n            memset(X->p, 0, X->n * ciL);\n        }\n        return 0;\n    }\n\n    for (i = Y->n - 1; i > 0; i--) {\n        if (Y->p[i] != 0) {\n            break;\n        }\n    }\n    i++;\n\n    X->s = Y->s;\n\n    if (X->n < i) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));\n    } else {\n        memset(X->p + i, 0, (X->n - i) * ciL);\n    }\n\n    memcpy(X->p, Y->p, i * ciL);\n\ncleanup:\n\n    return ret;\n}\n\n/*\n * Swap the contents of X and Y\n */\nvoid mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)\n{\n    mbedtls_mpi T;\n\n    memcpy(&T,  X, sizeof(mbedtls_mpi));\n    memcpy(X,  Y, sizeof(mbedtls_mpi));\n    memcpy(Y, &T, sizeof(mbedtls_mpi));\n}\n\nstatic inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)\n{\n    if (z >= 0) {\n        return z;\n    }\n    /* Take care to handle the most negative value (-2^(biL-1)) correctly.\n     * A naive -z would have undefined behavior.\n     * Write this in a way that makes popular compilers happy (GCC, Clang,\n     * MSVC). */\n    return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;\n}\n\n/* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative.\n * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */\n#define TO_SIGN(x) ((mbedtls_mpi_sint) (((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1)\n\n/*\n * Set value from integer\n */\nint mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));\n    memset(X->p, 0, X->n * ciL);\n\n    X->p[0] = mpi_sint_abs(z);\n    X->s    = TO_SIGN(z);\n\ncleanup:\n\n    return ret;\n}\n\n/*\n * Get a specific bit\n */\nint mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)\n{\n    if (X->n * biL <= pos) {\n        return 0;\n    }\n\n    return (X->p[pos / biL] >> (pos % biL)) & 0x01;\n}\n\n/*\n * Set a bit to a specific value of 0 or 1\n */\nint mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)\n{\n    int ret = 0;\n    size_t off = pos / biL;\n    size_t idx = pos % biL;\n\n    if (val != 0 && val != 1) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    if (X->n * biL <= pos) {\n        if (val == 0) {\n            return 0;\n        }\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));\n    }\n\n    X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);\n    X->p[off] |= (mbedtls_mpi_uint) val << idx;\n\ncleanup:\n\n    return ret;\n}\n\n#if defined(__has_builtin)\n#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz)\n    #define mbedtls_mpi_uint_ctz __builtin_ctz\n#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl)\n    #define mbedtls_mpi_uint_ctz __builtin_ctzl\n#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll)\n    #define mbedtls_mpi_uint_ctz __builtin_ctzll\n#endif\n#endif\n\n#if !defined(mbedtls_mpi_uint_ctz)\nstatic size_t mbedtls_mpi_uint_ctz(mbedtls_mpi_uint x)\n{\n    size_t count = 0;\n    mbedtls_ct_condition_t done = MBEDTLS_CT_FALSE;\n\n    for (size_t i = 0; i < biL; i++) {\n        mbedtls_ct_condition_t non_zero = mbedtls_ct_bool((x >> i) & 1);\n        done = mbedtls_ct_bool_or(done, non_zero);\n        count = mbedtls_ct_size_if(done, count, i + 1);\n    }\n\n    return count;\n}\n#endif\n\n/*\n * Return the number of less significant zero-bits\n */\nsize_t mbedtls_mpi_lsb(const mbedtls_mpi *X)\n{\n    size_t i;\n\n    for (i = 0; i < X->n; i++) {\n        if (X->p[i] != 0) {\n            return i * biL + mbedtls_mpi_uint_ctz(X->p[i]);\n        }\n    }\n\n    return 0;\n}\n\n/*\n * Return the number of bits\n */\nsize_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)\n{\n    return mbedtls_mpi_core_bitlen(X->p, X->n);\n}\n\n/*\n * Return the total size in bytes\n */\nsize_t mbedtls_mpi_size(const mbedtls_mpi *X)\n{\n    return (mbedtls_mpi_bitlen(X) + 7) >> 3;\n}\n\n/*\n * Convert an ASCII character to digit value\n */\nstatic int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)\n{\n    *d = 255;\n\n    if (c >= 0x30 && c <= 0x39) {\n        *d = c - 0x30;\n    }\n    if (c >= 0x41 && c <= 0x46) {\n        *d = c - 0x37;\n    }\n    if (c >= 0x61 && c <= 0x66) {\n        *d = c - 0x57;\n    }\n\n    if (*d >= (mbedtls_mpi_uint) radix) {\n        return MBEDTLS_ERR_MPI_INVALID_CHARACTER;\n    }\n\n    return 0;\n}\n\n/*\n * Import from an ASCII string\n */\nint mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t i, j, slen, n;\n    int sign = 1;\n    mbedtls_mpi_uint d;\n    mbedtls_mpi T;\n\n    if (radix < 2 || radix > 16) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    mbedtls_mpi_init(&T);\n\n    if (s[0] == 0) {\n        mbedtls_mpi_free(X);\n        return 0;\n    }\n\n    if (s[0] == '-') {\n        ++s;\n        sign = -1;\n    }\n\n    slen = strlen(s);\n\n    if (radix == 16) {\n        if (slen > SIZE_MAX >> 2) {\n            return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n        }\n\n        n = BITS_TO_LIMBS(slen << 2);\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));\n\n        for (i = slen, j = 0; i > 0; i--, j++) {\n            MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));\n            X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);\n        }\n    } else {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));\n\n        for (i = 0; i < slen; i++) {\n            MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));\n            MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));\n            MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));\n        }\n    }\n\n    if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {\n        X->s = -1;\n    }\n\ncleanup:\n\n    mbedtls_mpi_free(&T);\n\n    return ret;\n}\n\n/*\n * Helper to write the digits high-order first.\n */\nstatic int mpi_write_hlp(mbedtls_mpi *X, int radix,\n                         char **p, const size_t buflen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi_uint r;\n    size_t length = 0;\n    char *p_end = *p + buflen;\n\n    do {\n        if (length >= buflen) {\n            return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;\n        }\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));\n        /*\n         * Write the residue in the current position, as an ASCII character.\n         */\n        if (r < 0xA) {\n            *(--p_end) = (char) ('0' + r);\n        } else {\n            *(--p_end) = (char) ('A' + (r - 0xA));\n        }\n\n        length++;\n    } while (mbedtls_mpi_cmp_int(X, 0) != 0);\n\n    memmove(*p, p_end, length);\n    *p += length;\n\ncleanup:\n\n    return ret;\n}\n\n/*\n * Export into an ASCII string\n */\nint mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,\n                             char *buf, size_t buflen, size_t *olen)\n{\n    int ret = 0;\n    size_t n;\n    char *p;\n    mbedtls_mpi T;\n\n    if (radix < 2 || radix > 16) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    n = mbedtls_mpi_bitlen(X);   /* Number of bits necessary to present `n`. */\n    if (radix >=  4) {\n        n >>= 1;                 /* Number of 4-adic digits necessary to present\n                                  * `n`. If radix > 4, this might be a strict\n                                  * overapproximation of the number of\n                                  * radix-adic digits needed to present `n`. */\n    }\n    if (radix >= 16) {\n        n >>= 1;                 /* Number of hexadecimal digits necessary to\n                                  * present `n`. */\n\n    }\n    n += 1; /* Terminating null byte */\n    n += 1; /* Compensate for the divisions above, which round down `n`\n             * in case it's not even. */\n    n += 1; /* Potential '-'-sign. */\n    n += (n & 1);   /* Make n even to have enough space for hexadecimal writing,\n                     * which always uses an even number of hex-digits. */\n\n    if (buflen < n) {\n        *olen = n;\n        return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;\n    }\n\n    p = buf;\n    mbedtls_mpi_init(&T);\n\n    if (X->s == -1) {\n        *p++ = '-';\n        buflen--;\n    }\n\n    if (radix == 16) {\n        int c;\n        size_t i, j, k;\n\n        for (i = X->n, k = 0; i > 0; i--) {\n            for (j = ciL; j > 0; j--) {\n                c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;\n\n                if (c == 0 && k == 0 && (i + j) != 2) {\n                    continue;\n                }\n\n                *(p++) = \"0123456789ABCDEF\" [c / 16];\n                *(p++) = \"0123456789ABCDEF\" [c % 16];\n                k = 1;\n            }\n        }\n    } else {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));\n\n        if (T.s == -1) {\n            T.s = 1;\n        }\n\n        MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));\n    }\n\n    *p++ = '\\0';\n    *olen = (size_t) (p - buf);\n\ncleanup:\n\n    mbedtls_mpi_free(&T);\n\n    return ret;\n}\n\n#if defined(MBEDTLS_FS_IO)\n/*\n * Read X from an opened file\n */\nint mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)\n{\n    mbedtls_mpi_uint d;\n    size_t slen;\n    char *p;\n    /*\n     * Buffer should have space for (short) label and decimal formatted MPI,\n     * newline characters and '\\0'\n     */\n    char s[MBEDTLS_MPI_RW_BUFFER_SIZE];\n\n    if (radix < 2 || radix > 16) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    memset(s, 0, sizeof(s));\n    if (fgets(s, sizeof(s) - 1, fin) == NULL) {\n        return MBEDTLS_ERR_MPI_FILE_IO_ERROR;\n    }\n\n    slen = strlen(s);\n    if (slen == sizeof(s) - 2) {\n        return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;\n    }\n\n    if (slen > 0 && s[slen - 1] == '\\n') {\n        slen--; s[slen] = '\\0';\n    }\n    if (slen > 0 && s[slen - 1] == '\\r') {\n        slen--; s[slen] = '\\0';\n    }\n\n    p = s + slen;\n    while (p-- > s) {\n        if (mpi_get_digit(&d, radix, *p) != 0) {\n            break;\n        }\n    }\n\n    return mbedtls_mpi_read_string(X, radix, p + 1);\n}\n\n/*\n * Write X into an opened file (or stdout if fout == NULL)\n */\nint mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t n, slen, plen;\n    /*\n     * Buffer should have space for (short) label and decimal formatted MPI,\n     * newline characters and '\\0'\n     */\n    char s[MBEDTLS_MPI_RW_BUFFER_SIZE];\n\n    if (radix < 2 || radix > 16) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    memset(s, 0, sizeof(s));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));\n\n    if (p == NULL) {\n        p = \"\";\n    }\n\n    plen = strlen(p);\n    slen = strlen(s);\n    s[slen++] = '\\r';\n    s[slen++] = '\\n';\n\n    if (fout != NULL) {\n        if (fwrite(p, 1, plen, fout) != plen ||\n            fwrite(s, 1, slen, fout) != slen) {\n            return MBEDTLS_ERR_MPI_FILE_IO_ERROR;\n        }\n    } else {\n        mbedtls_printf(\"%s%s\", p, s);\n    }\n\ncleanup:\n\n    return ret;\n}\n#endif /* MBEDTLS_FS_IO */\n\n/*\n * Import X from unsigned binary data, little endian\n *\n * This function is guaranteed to return an MPI with exactly the necessary\n * number of limbs (in particular, it does not skip 0s in the input).\n */\nint mbedtls_mpi_read_binary_le(mbedtls_mpi *X,\n                               const unsigned char *buf, size_t buflen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const size_t limbs = CHARS_TO_LIMBS(buflen);\n\n    /* Ensure that target MPI has exactly the necessary number of limbs */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));\n\ncleanup:\n\n    /*\n     * This function is also used to import keys. However, wiping the buffers\n     * upon failure is not necessary because failure only can happen before any\n     * input is copied.\n     */\n    return ret;\n}\n\n/*\n * Import X from unsigned binary data, big endian\n *\n * This function is guaranteed to return an MPI with exactly the necessary\n * number of limbs (in particular, it does not skip 0s in the input).\n */\nint mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const size_t limbs = CHARS_TO_LIMBS(buflen);\n\n    /* Ensure that target MPI has exactly the necessary number of limbs */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));\n\ncleanup:\n\n    /*\n     * This function is also used to import keys. However, wiping the buffers\n     * upon failure is not necessary because failure only can happen before any\n     * input is copied.\n     */\n    return ret;\n}\n\n/*\n * Export X into unsigned binary data, little endian\n */\nint mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,\n                                unsigned char *buf, size_t buflen)\n{\n    return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);\n}\n\n/*\n * Export X into unsigned binary data, big endian\n */\nint mbedtls_mpi_write_binary(const mbedtls_mpi *X,\n                             unsigned char *buf, size_t buflen)\n{\n    return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);\n}\n\n/*\n * Left-shift: X <<= count\n */\nint mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t i;\n\n    i = mbedtls_mpi_bitlen(X) + count;\n\n    if (X->n * biL < i) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));\n    }\n\n    ret = 0;\n\n    mbedtls_mpi_core_shift_l(X->p, X->n, count);\ncleanup:\n\n    return ret;\n}\n\n/*\n * Right-shift: X >>= count\n */\nint mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)\n{\n    if (X->n != 0) {\n        mbedtls_mpi_core_shift_r(X->p, X->n, count);\n    }\n    return 0;\n}\n\n/*\n * Compare unsigned values\n */\nint mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)\n{\n    size_t i, j;\n\n    for (i = X->n; i > 0; i--) {\n        if (X->p[i - 1] != 0) {\n            break;\n        }\n    }\n\n    for (j = Y->n; j > 0; j--) {\n        if (Y->p[j - 1] != 0) {\n            break;\n        }\n    }\n\n    /* If i == j == 0, i.e. abs(X) == abs(Y),\n     * we end up returning 0 at the end of the function. */\n\n    if (i > j) {\n        return 1;\n    }\n    if (j > i) {\n        return -1;\n    }\n\n    for (; i > 0; i--) {\n        if (X->p[i - 1] > Y->p[i - 1]) {\n            return 1;\n        }\n        if (X->p[i - 1] < Y->p[i - 1]) {\n            return -1;\n        }\n    }\n\n    return 0;\n}\n\n/*\n * Compare signed values\n */\nint mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)\n{\n    size_t i, j;\n\n    for (i = X->n; i > 0; i--) {\n        if (X->p[i - 1] != 0) {\n            break;\n        }\n    }\n\n    for (j = Y->n; j > 0; j--) {\n        if (Y->p[j - 1] != 0) {\n            break;\n        }\n    }\n\n    if (i == 0 && j == 0) {\n        return 0;\n    }\n\n    if (i > j) {\n        return X->s;\n    }\n    if (j > i) {\n        return -Y->s;\n    }\n\n    if (X->s > 0 && Y->s < 0) {\n        return 1;\n    }\n    if (Y->s > 0 && X->s < 0) {\n        return -1;\n    }\n\n    for (; i > 0; i--) {\n        if (X->p[i - 1] > Y->p[i - 1]) {\n            return X->s;\n        }\n        if (X->p[i - 1] < Y->p[i - 1]) {\n            return -X->s;\n        }\n    }\n\n    return 0;\n}\n\n/*\n * Compare signed values\n */\nint mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)\n{\n    mbedtls_mpi Y;\n    mbedtls_mpi_uint p[1];\n\n    *p  = mpi_sint_abs(z);\n    Y.s = TO_SIGN(z);\n    Y.n = 1;\n    Y.p = p;\n\n    return mbedtls_mpi_cmp_mpi(X, &Y);\n}\n\n/*\n * Unsigned addition: X = |A| + |B|  (HAC 14.7)\n */\nint mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t j;\n    mbedtls_mpi_uint *p;\n    mbedtls_mpi_uint c;\n\n    if (X == B) {\n        const mbedtls_mpi *T = A; A = X; B = T;\n    }\n\n    if (X != A) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));\n    }\n\n    /*\n     * X must always be positive as a result of unsigned additions.\n     */\n    X->s = 1;\n\n    for (j = B->n; j > 0; j--) {\n        if (B->p[j - 1] != 0) {\n            break;\n        }\n    }\n\n    /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0\n     * and B is 0 (of any size). */\n    if (j == 0) {\n        return 0;\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));\n\n    /* j is the number of non-zero limbs of B. Add those to X. */\n\n    p = X->p;\n\n    c = mbedtls_mpi_core_add(p, p, B->p, j);\n\n    p += j;\n\n    /* Now propagate any carry */\n\n    while (c != 0) {\n        if (j >= X->n) {\n            MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));\n            p = X->p + j;\n        }\n\n        *p += c; c = (*p < c); j++; p++;\n    }\n\ncleanup:\n\n    return ret;\n}\n\n/*\n * Unsigned subtraction: X = |A| - |B|  (HAC 14.9, 14.10)\n */\nint mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t n;\n    mbedtls_mpi_uint carry;\n\n    for (n = B->n; n > 0; n--) {\n        if (B->p[n - 1] != 0) {\n            break;\n        }\n    }\n    if (n > A->n) {\n        /* B >= (2^ciL)^n > A */\n        ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;\n        goto cleanup;\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));\n\n    /* Set the high limbs of X to match A. Don't touch the lower limbs\n     * because X might be aliased to B, and we must not overwrite the\n     * significant digits of B. */\n    if (A->n > n && A != X) {\n        memcpy(X->p + n, A->p + n, (A->n - n) * ciL);\n    }\n    if (X->n > A->n) {\n        memset(X->p + A->n, 0, (X->n - A->n) * ciL);\n    }\n\n    carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);\n    if (carry != 0) {\n        /* Propagate the carry through the rest of X. */\n        carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);\n\n        /* If we have further carry/borrow, the result is negative. */\n        if (carry != 0) {\n            ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;\n            goto cleanup;\n        }\n    }\n\n    /* X should always be positive as a result of unsigned subtractions. */\n    X->s = 1;\n\ncleanup:\n    return ret;\n}\n\n/* Common function for signed addition and subtraction.\n * Calculate A + B * flip_B where flip_B is 1 or -1.\n */\nstatic int add_sub_mpi(mbedtls_mpi *X,\n                       const mbedtls_mpi *A, const mbedtls_mpi *B,\n                       int flip_B)\n{\n    int ret, s;\n\n    s = A->s;\n    if (A->s * B->s * flip_B < 0) {\n        int cmp = mbedtls_mpi_cmp_abs(A, B);\n        if (cmp >= 0) {\n            MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));\n            /* If |A| = |B|, the result is 0 and we must set the sign bit\n             * to +1 regardless of which of A or B was negative. Otherwise,\n             * since |A| > |B|, the sign is the sign of A. */\n            X->s = cmp == 0 ? 1 : s;\n        } else {\n            MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));\n            /* Since |A| < |B|, the sign is the opposite of A. */\n            X->s = -s;\n        }\n    } else {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));\n        X->s = s;\n    }\n\ncleanup:\n\n    return ret;\n}\n\n/*\n * Signed addition: X = A + B\n */\nint mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)\n{\n    return add_sub_mpi(X, A, B, 1);\n}\n\n/*\n * Signed subtraction: X = A - B\n */\nint mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)\n{\n    return add_sub_mpi(X, A, B, -1);\n}\n\n/*\n * Signed addition: X = A + b\n */\nint mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)\n{\n    mbedtls_mpi B;\n    mbedtls_mpi_uint p[1];\n\n    p[0] = mpi_sint_abs(b);\n    B.s = TO_SIGN(b);\n    B.n = 1;\n    B.p = p;\n\n    return mbedtls_mpi_add_mpi(X, A, &B);\n}\n\n/*\n * Signed subtraction: X = A - b\n */\nint mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)\n{\n    mbedtls_mpi B;\n    mbedtls_mpi_uint p[1];\n\n    p[0] = mpi_sint_abs(b);\n    B.s = TO_SIGN(b);\n    B.n = 1;\n    B.p = p;\n\n    return mbedtls_mpi_sub_mpi(X, A, &B);\n}\n\n/*\n * Baseline multiplication: X = A * B  (HAC 14.12)\n */\nint mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t i, j;\n    mbedtls_mpi TA, TB;\n    int result_is_zero = 0;\n\n    mbedtls_mpi_init(&TA);\n    mbedtls_mpi_init(&TB);\n\n    if (X == A) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;\n    }\n    if (X == B) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;\n    }\n\n    for (i = A->n; i > 0; i--) {\n        if (A->p[i - 1] != 0) {\n            break;\n        }\n    }\n    if (i == 0) {\n        result_is_zero = 1;\n    }\n\n    for (j = B->n; j > 0; j--) {\n        if (B->p[j - 1] != 0) {\n            break;\n        }\n    }\n    if (j == 0) {\n        result_is_zero = 1;\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));\n\n    mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);\n\n    /* If the result is 0, we don't shortcut the operation, which reduces\n     * but does not eliminate side channels leaking the zero-ness. We do\n     * need to take care to set the sign bit properly since the library does\n     * not fully support an MPI object with a value of 0 and s == -1. */\n    if (result_is_zero) {\n        X->s = 1;\n    } else {\n        X->s = A->s * B->s;\n    }\n\ncleanup:\n\n    mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);\n\n    return ret;\n}\n\n/*\n * Baseline multiplication: X = A * b\n */\nint mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)\n{\n    size_t n = A->n;\n    while (n > 0 && A->p[n - 1] == 0) {\n        --n;\n    }\n\n    /* The general method below doesn't work if b==0. */\n    if (b == 0 || n == 0) {\n        return mbedtls_mpi_lset(X, 0);\n    }\n\n    /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    /* In general, A * b requires 1 limb more than b. If\n     * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same\n     * number of limbs as A and the call to grow() is not required since\n     * copy() will take care of the growth if needed. However, experimentally,\n     * making the call to grow() unconditional causes slightly fewer\n     * calls to calloc() in ECP code, presumably because it reuses the\n     * same mpi for a while and this way the mpi is more likely to directly\n     * grow to its final size.\n     *\n     * Note that calculating A*b as 0 + A*b doesn't work as-is because\n     * A,X can be the same. */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));\n    mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);\n\ncleanup:\n    return ret;\n}\n\n/*\n * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and\n * mbedtls_mpi_uint divisor, d\n */\nstatic mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,\n                                            mbedtls_mpi_uint u0,\n                                            mbedtls_mpi_uint d,\n                                            mbedtls_mpi_uint *r)\n{\n#if defined(MBEDTLS_HAVE_UDBL)\n    mbedtls_t_udbl dividend, quotient;\n#else\n    const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;\n    const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;\n    mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;\n    mbedtls_mpi_uint u0_msw, u0_lsw;\n    size_t s;\n#endif\n\n    /*\n     * Check for overflow\n     */\n    if (0 == d || u1 >= d) {\n        if (r != NULL) {\n            *r = ~(mbedtls_mpi_uint) 0u;\n        }\n\n        return ~(mbedtls_mpi_uint) 0u;\n    }\n\n#if defined(MBEDTLS_HAVE_UDBL)\n    dividend  = (mbedtls_t_udbl) u1 << biL;\n    dividend |= (mbedtls_t_udbl) u0;\n    quotient = dividend / d;\n    if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {\n        quotient = ((mbedtls_t_udbl) 1 << biL) - 1;\n    }\n\n    if (r != NULL) {\n        *r = (mbedtls_mpi_uint) (dividend - (quotient * d));\n    }\n\n    return (mbedtls_mpi_uint) quotient;\n#else\n\n    /*\n     * Algorithm D, Section 4.3.1 - The Art of Computer Programming\n     *   Vol. 2 - Seminumerical Algorithms, Knuth\n     */\n\n    /*\n     * Normalize the divisor, d, and dividend, u0, u1\n     */\n    s = mbedtls_mpi_core_clz(d);\n    d = d << s;\n\n    u1 = u1 << s;\n    u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));\n    u0 =  u0 << s;\n\n    d1 = d >> biH;\n    d0 = d & uint_halfword_mask;\n\n    u0_msw = u0 >> biH;\n    u0_lsw = u0 & uint_halfword_mask;\n\n    /*\n     * Find the first quotient and remainder\n     */\n    q1 = u1 / d1;\n    r0 = u1 - d1 * q1;\n\n    while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {\n        q1 -= 1;\n        r0 += d1;\n\n        if (r0 >= radix) {\n            break;\n        }\n    }\n\n    rAX = (u1 * radix) + (u0_msw - q1 * d);\n    q0 = rAX / d1;\n    r0 = rAX - q0 * d1;\n\n    while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {\n        q0 -= 1;\n        r0 += d1;\n\n        if (r0 >= radix) {\n            break;\n        }\n    }\n\n    if (r != NULL) {\n        *r = (rAX * radix + u0_lsw - q0 * d) >> s;\n    }\n\n    quotient = q1 * radix + q0;\n\n    return quotient;\n#endif\n}\n\n/*\n * Division by mbedtls_mpi: A = Q * B + R  (HAC 14.20)\n */\nint mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,\n                        const mbedtls_mpi *B)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t i, n, t, k;\n    mbedtls_mpi X, Y, Z, T1, T2;\n    mbedtls_mpi_uint TP2[3];\n\n    if (mbedtls_mpi_cmp_int(B, 0) == 0) {\n        return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;\n    }\n\n    mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z);\n    mbedtls_mpi_init(&T1);\n    /*\n     * Avoid dynamic memory allocations for constant-size T2.\n     *\n     * T2 is used for comparison only and the 3 limbs are assigned explicitly,\n     * so nobody increase the size of the MPI and we're safe to use an on-stack\n     * buffer.\n     */\n    T2.s = 1;\n    T2.n = sizeof(TP2) / sizeof(*TP2);\n    T2.p = TP2;\n\n    if (mbedtls_mpi_cmp_abs(A, B) < 0) {\n        if (Q != NULL) {\n            MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));\n        }\n        if (R != NULL) {\n            MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));\n        }\n        return 0;\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));\n    X.s = Y.s = 1;\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z,  0));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));\n\n    k = mbedtls_mpi_bitlen(&Y) % biL;\n    if (k < biL - 1) {\n        k = biL - 1 - k;\n        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));\n    } else {\n        k = 0;\n    }\n\n    n = X.n - 1;\n    t = Y.n - 1;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));\n\n    while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {\n        Z.p[n - t]++;\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));\n    }\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));\n\n    for (i = n; i > t; i--) {\n        if (X.p[i] >= Y.p[t]) {\n            Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;\n        } else {\n            Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],\n                                                 Y.p[t], NULL);\n        }\n\n        T2.p[0] = (i < 2) ? 0 : X.p[i - 2];\n        T2.p[1] = (i < 1) ? 0 : X.p[i - 1];\n        T2.p[2] = X.p[i];\n\n        Z.p[i - t - 1]++;\n        do {\n            Z.p[i - t - 1]--;\n\n            MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));\n            T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];\n            T1.p[1] = Y.p[t];\n            MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));\n        } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1,  biL * (i - t - 1)));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));\n\n        if (mbedtls_mpi_cmp_int(&X, 0) < 0) {\n            MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));\n            MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));\n            MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));\n            Z.p[i - t - 1]--;\n        }\n    }\n\n    if (Q != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));\n        Q->s = A->s * B->s;\n    }\n\n    if (R != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));\n        X.s = A->s;\n        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));\n\n        if (mbedtls_mpi_cmp_int(R, 0) == 0) {\n            R->s = 1;\n        }\n    }\n\ncleanup:\n\n    mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);\n    mbedtls_mpi_free(&T1);\n    mbedtls_platform_zeroize(TP2, sizeof(TP2));\n\n    return ret;\n}\n\n/*\n * Division by int: A = Q * b + R\n */\nint mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,\n                        const mbedtls_mpi *A,\n                        mbedtls_mpi_sint b)\n{\n    mbedtls_mpi B;\n    mbedtls_mpi_uint p[1];\n\n    p[0] = mpi_sint_abs(b);\n    B.s = TO_SIGN(b);\n    B.n = 1;\n    B.p = p;\n\n    return mbedtls_mpi_div_mpi(Q, R, A, &B);\n}\n\n/*\n * Modulo: R = A mod B\n */\nint mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (mbedtls_mpi_cmp_int(B, 0) < 0) {\n        return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));\n\n    while (mbedtls_mpi_cmp_int(R, 0) < 0) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));\n    }\n\n    while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));\n    }\n\ncleanup:\n\n    return ret;\n}\n\n/*\n * Modulo: r = A mod b\n */\nint mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)\n{\n    size_t i;\n    mbedtls_mpi_uint x, y, z;\n\n    if (b == 0) {\n        return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;\n    }\n\n    if (b < 0) {\n        return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;\n    }\n\n    /*\n     * handle trivial cases\n     */\n    if (b == 1 || A->n == 0) {\n        *r = 0;\n        return 0;\n    }\n\n    if (b == 2) {\n        *r = A->p[0] & 1;\n        return 0;\n    }\n\n    /*\n     * general case\n     */\n    for (i = A->n, y = 0; i > 0; i--) {\n        x  = A->p[i - 1];\n        y  = (y << biH) | (x >> biH);\n        z  = y / b;\n        y -= z * b;\n\n        x <<= biH;\n        y  = (y << biH) | (x >> biH);\n        z  = y / b;\n        y -= z * b;\n    }\n\n    /*\n     * If A is negative, then the current y represents a negative value.\n     * Flipping it to the positive side.\n     */\n    if (A->s < 0 && y != 0) {\n        y = b - y;\n    }\n\n    *r = y;\n\n    return 0;\n}\n\n/*\n * Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value,\n * this function is not constant time with respect to the exponent (parameter E).\n */\nstatic int mbedtls_mpi_exp_mod_optionally_safe(mbedtls_mpi *X, const mbedtls_mpi *A,\n                                               const mbedtls_mpi *E, int E_public,\n                                               const mbedtls_mpi *N, mbedtls_mpi *prec_RR)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    if (mbedtls_mpi_cmp_int(E, 0) < 0) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||\n        mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    /*\n     * Ensure that the exponent that we are passing to the core is not NULL.\n     */\n    if (E->n == 0) {\n        ret = mbedtls_mpi_lset(X, 1);\n        return ret;\n    }\n\n    /*\n     * Allocate working memory for mbedtls_mpi_core_exp_mod()\n     */\n    size_t T_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N->n, E->n);\n    mbedtls_mpi_uint *T = (mbedtls_mpi_uint *) mbedtls_calloc(T_limbs, sizeof(mbedtls_mpi_uint));\n    if (T == NULL) {\n        return MBEDTLS_ERR_MPI_ALLOC_FAILED;\n    }\n\n    mbedtls_mpi RR;\n    mbedtls_mpi_init(&RR);\n\n    /*\n     * If 1st call, pre-compute R^2 mod N\n     */\n    if (prec_RR == NULL || prec_RR->p == NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N));\n\n        if (prec_RR != NULL) {\n            *prec_RR = RR;\n        }\n    } else {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(prec_RR, N->n));\n        RR = *prec_RR;\n    }\n\n    /*\n     * To preserve constness we need to make a copy of A. Using X for this to\n     * save memory.\n     */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));\n\n    /*\n     * Compensate for negative A (and correct at the end).\n     */\n    X->s = 1;\n\n    /*\n     * Make sure that X is in a form that is safe for consumption by\n     * the core functions.\n     *\n     * - The core functions will not touch the limbs of X above N->n. The\n     *   result will be correct if those limbs are 0, which the mod call\n     *   ensures.\n     * - Also, X must have at least as many limbs as N for the calls to the\n     *   core functions.\n     */\n    if (mbedtls_mpi_cmp_mpi(X, N) >= 0) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N));\n    }\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, N->n));\n\n    /*\n     * Convert to and from Montgomery around mbedtls_mpi_core_exp_mod().\n     */\n    {\n        mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p);\n        mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T);\n        if (E_public == MBEDTLS_MPI_IS_PUBLIC) {\n            mbedtls_mpi_core_exp_mod_unsafe(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);\n        } else {\n            mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);\n        }\n        mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T);\n    }\n\n    /*\n     * Correct for negative A.\n     */\n    if (A->s == -1 && (E->p[0] & 1) != 0) {\n        mbedtls_ct_condition_t is_x_non_zero = mbedtls_mpi_core_check_zero_ct(X->p, X->n);\n        X->s = mbedtls_ct_mpi_sign_if(is_x_non_zero, -1, 1);\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X));\n    }\n\ncleanup:\n\n    mbedtls_mpi_zeroize_and_free(T, T_limbs);\n\n    if (prec_RR == NULL || prec_RR->p == NULL) {\n        mbedtls_mpi_free(&RR);\n    }\n\n    return ret;\n}\n\nint mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,\n                        const mbedtls_mpi *E, const mbedtls_mpi *N,\n                        mbedtls_mpi *prec_RR)\n{\n    return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_SECRET, N, prec_RR);\n}\n\nint mbedtls_mpi_exp_mod_unsafe(mbedtls_mpi *X, const mbedtls_mpi *A,\n                               const mbedtls_mpi *E, const mbedtls_mpi *N,\n                               mbedtls_mpi *prec_RR)\n{\n    return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_PUBLIC, N, prec_RR);\n}\n\n/* Constant-time GCD and/or modinv with odd modulus and A <= N */\nint mbedtls_mpi_gcd_modinv_odd(mbedtls_mpi *G,\n                               mbedtls_mpi *I,\n                               const mbedtls_mpi *A,\n                               const mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi local_g;\n    mbedtls_mpi_uint *T = NULL;\n    const size_t T_factor = I != NULL ? 5 : 4;\n    const mbedtls_mpi_uint zero = 0;\n\n    /* Check requirements on A and N */\n    if (mbedtls_mpi_cmp_int(A, 0) < 0 ||\n        mbedtls_mpi_cmp_mpi(A, N) > 0 ||\n        mbedtls_mpi_get_bit(N, 0) != 1 ||\n        (I != NULL && mbedtls_mpi_cmp_int(N, 1) == 0)) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    /* Check aliasing requirements */\n    if (A == N || (I != NULL && (I == N || G == N))) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    mbedtls_mpi_init(&local_g);\n\n    if (G == NULL) {\n        G = &local_g;\n    }\n\n    /* We can't modify the values of G or I before use in the main function,\n     * as they could be aliased to A or N. */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(G, N->n));\n    if (I != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(I, N->n));\n    }\n\n    T = mbedtls_calloc(sizeof(mbedtls_mpi_uint) * N->n, T_factor);\n    if (T == NULL) {\n        ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;\n        goto cleanup;\n    }\n\n    mbedtls_mpi_uint *Ip = I != NULL ? I->p : NULL;\n    /* If A is 0 (null), then A->p would be null, and A->n would be 0,\n     * which would be an issue if A->p and A->n were passed to\n     * mbedtls_mpi_core_gcd_modinv_odd below. */\n    const mbedtls_mpi_uint *Ap = A->p != NULL ? A->p : &zero;\n    size_t An = A->n >= N->n ? N->n : A->p != NULL ? A->n : 1;\n    mbedtls_mpi_core_gcd_modinv_odd(G->p, Ip, Ap, An, N->p, N->n, T);\n\n    G->s = 1;\n    if (I != NULL) {\n        I->s = 1;\n    }\n\n    if (G->n > N->n) {\n        memset(G->p + N->n, 0, ciL * (G->n - N->n));\n    }\n    if (I != NULL && I->n > N->n) {\n        memset(I->p + N->n, 0, ciL * (I->n - N->n));\n    }\n\ncleanup:\n    mbedtls_mpi_free(&local_g);\n    mbedtls_free(T);\n    return ret;\n}\n\n/*\n * Greatest common divisor: G = gcd(A, B)\n * Wrapper around mbedtls_mpi_gcd_modinv() that removes its restrictions.\n */\nint mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi TA, TB;\n\n    mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);\n\n    /* Make copies and take absolute values */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));\n    TA.s = TB.s = 1;\n\n    /* Make the two values the same (non-zero) number of limbs.\n     * This is needed to use mbedtls_mpi_core functions below. */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&TA, TB.n != 0 ? TB.n : 1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&TB, TA.n)); // non-zero from above\n\n    /* Handle special cases (that don't happen in crypto usage) */\n    if (mbedtls_mpi_core_check_zero_ct(TA.p, TA.n) == MBEDTLS_CT_FALSE) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB)); // GCD(0, B) = abs(B)\n        goto cleanup;\n    }\n    if (mbedtls_mpi_core_check_zero_ct(TB.p, TB.n) == MBEDTLS_CT_FALSE) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TA)); // GCD(A, 0) = abs(A)\n        goto cleanup;\n    }\n\n    /* Make boths inputs odd by putting powers of 2 on the side */\n    const size_t za = mbedtls_mpi_lsb(&TA);\n    const size_t zb = mbedtls_mpi_lsb(&TB);\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, za));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, zb));\n\n    /* Ensure A <= B: if B < A, swap them */\n    mbedtls_ct_condition_t swap = mbedtls_mpi_core_lt_ct(TB.p, TA.p, TA.n);\n    mbedtls_mpi_core_cond_swap(TA.p, TB.p, TA.n, swap);\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(G, NULL, &TA, &TB));\n\n    /* Re-inject the power of 2 we had previously put aside */\n    size_t zg = za > zb ? zb : za; // zg = min(za, zb)\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(G, zg));\n\ncleanup:\n\n    mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);\n\n    return ret;\n}\n\n/*\n * Fill X with size bytes of random.\n * The bytes returned from the RNG are used in a specific order which\n * is suitable for deterministic ECDSA (see the specification of\n * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).\n */\nint mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,\n                            int (*f_rng)(void *, unsigned char *, size_t),\n                            void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const size_t limbs = CHARS_TO_LIMBS(size);\n\n    /* Ensure that target MPI has exactly the necessary number of limbs */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));\n    if (size == 0) {\n        return 0;\n    }\n\n    ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);\n\ncleanup:\n    return ret;\n}\n\nint mbedtls_mpi_random(mbedtls_mpi *X,\n                       mbedtls_mpi_sint min,\n                       const mbedtls_mpi *N,\n                       int (*f_rng)(void *, unsigned char *, size_t),\n                       void *p_rng)\n{\n    if (min < 0) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n    if (mbedtls_mpi_cmp_int(N, min) <= 0) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    /* Ensure that target MPI has exactly the same number of limbs\n     * as the upper bound, even if the upper bound has leading zeros.\n     * This is necessary for mbedtls_mpi_core_random. */\n    int ret = mbedtls_mpi_resize_clear(X, N->n);\n    if (ret != 0) {\n        return ret;\n    }\n\n    return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);\n}\n\n/*\n * Modular inverse: X = A^-1 mod N with N odd (and A any range)\n */\nint mbedtls_mpi_inv_mod_odd(mbedtls_mpi *X,\n                            const mbedtls_mpi *A,\n                            const mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi T, G;\n\n    mbedtls_mpi_init(&T);\n    mbedtls_mpi_init(&G);\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, A, N));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(&G, &T, &T, N));\n    if (mbedtls_mpi_cmp_int(&G, 1) != 0) {\n        ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;\n        goto cleanup;\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &T));\n\ncleanup:\n    mbedtls_mpi_free(&T);\n    mbedtls_mpi_free(&G);\n\n    return ret;\n}\n\n/*\n * Compute X = A^-1 mod N with N even, A odd and 1 < A < N.\n *\n * This is not obvious because our constant-time modinv function only works with\n * an odd modulus, and here the modulus is even. The idea is that computing a\n * a^-1 mod b is really just computing the u coefficient in the Bézout relation\n * a*u + b*v = 1 (assuming gcd(a,b) = 1, i.e. the inverse exists). But if we know\n * one of u, v in this relation then the other is easy to find. So we can\n * actually start by computing N^-1 mod A with gives us \"the wrong half\" of the\n * Bézout relation, from which we'll deduce the interesting half A^-1 mod N.\n *\n * Return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the inverse doesn't exist.\n */\nint mbedtls_mpi_inv_mod_even_in_range(mbedtls_mpi *X,\n                                      mbedtls_mpi const *A,\n                                      mbedtls_mpi const *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi I, G;\n\n    mbedtls_mpi_init(&I);\n    mbedtls_mpi_init(&G);\n\n    /* Set I = N^-1 mod A */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&I, N, A));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(&G, &I, &I, A));\n    if (mbedtls_mpi_cmp_int(&G, 1) != 0) {\n        ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;\n        goto cleanup;\n    }\n\n    /* We know N * I = 1 + k * A for some k, which we can easily compute\n     * as k = (N*I - 1) / A (we know there will be no remainder). */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&I, &I, N));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&I, &I, 1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&G, NULL, &I, A));\n\n    /* Now we have a Bézout relation N * (previous value of I) - G * A = 1,\n     * so A^-1 mod N is -G mod N, which is N - G.\n     * Note that 0 < k < N since 0 < I < A, so G (k) is already in range. */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(X, N, &G));\n\ncleanup:\n    mbedtls_mpi_free(&I);\n    mbedtls_mpi_free(&G);\n    return ret;\n}\n\n/*\n * Compute X = A^-1 mod N with N even and A odd (but in any range).\n *\n * Return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the inverse doesn't exist.\n */\nstatic int mbedtls_mpi_inv_mod_even(mbedtls_mpi *X,\n                                    mbedtls_mpi const *A,\n                                    mbedtls_mpi const *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi AA;\n\n    mbedtls_mpi_init(&AA);\n\n    /* Bring A in the range [0, N). */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&AA, A, N));\n\n    /* We know A >= 0 but the next function wants A > 1 */\n    int cmp = mbedtls_mpi_cmp_int(&AA, 1);\n    if (cmp < 0) { // AA == 0\n        ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;\n        goto cleanup;\n    }\n    if (cmp == 0) { // AA = 1\n        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 1));\n        goto cleanup;\n    }\n\n    /* Now we know 1 < A < N, N is even and AA is still odd */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod_even_in_range(X, &AA, N));\n\ncleanup:\n    mbedtls_mpi_free(&AA);\n    return ret;\n}\n\n/*\n * Modular inverse: X = A^-1 mod N\n *\n * Wrapper around mbedtls_mpi_gcd_modinv_odd() that lifts its limitations.\n */\nint mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)\n{\n    if (mbedtls_mpi_cmp_int(N, 1) <= 0) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    if (mbedtls_mpi_get_bit(N, 0) == 1) {\n        return mbedtls_mpi_inv_mod_odd(X, A, N);\n    }\n\n    if (mbedtls_mpi_get_bit(A, 0) == 1) {\n        return mbedtls_mpi_inv_mod_even(X, A, N);\n    }\n\n    /* If A and N are both even, 2 divides their GCD, so no inverse. */\n    return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;\n}\n\n#if defined(MBEDTLS_GENPRIME)\n\n/* Gaps between primes, starting at 3. https://oeis.org/A001223 */\nstatic const unsigned char small_prime_gaps[] = {\n    2, 2, 4, 2, 4, 2, 4, 6,\n    2, 6, 4, 2, 4, 6, 6, 2,\n    6, 4, 2, 6, 4, 6, 8, 4,\n    2, 4, 2, 4, 14, 4, 6, 2,\n    10, 2, 6, 6, 4, 6, 6, 2,\n    10, 2, 4, 2, 12, 12, 4, 2,\n    4, 6, 2, 10, 6, 6, 6, 2,\n    6, 4, 2, 10, 14, 4, 2, 4,\n    14, 6, 10, 2, 4, 6, 8, 6,\n    6, 4, 6, 8, 4, 8, 10, 2,\n    10, 2, 6, 4, 6, 8, 4, 2,\n    4, 12, 8, 4, 8, 4, 6, 12,\n    2, 18, 6, 10, 6, 6, 2, 6,\n    10, 6, 6, 2, 6, 6, 4, 2,\n    12, 10, 2, 4, 6, 6, 2, 12,\n    4, 6, 8, 10, 8, 10, 8, 6,\n    6, 4, 8, 6, 4, 8, 4, 14,\n    10, 12, 2, 10, 2, 4, 2, 10,\n    14, 4, 2, 4, 14, 4, 2, 4,\n    20, 4, 8, 10, 8, 4, 6, 6,\n    14, 4, 6, 6, 8, 6, /*reaches 997*/\n    0 /* the last entry is effectively unused */\n};\n\n/*\n * Small divisors test (X must be positive)\n *\n * Return values:\n * 0: no small factor (possible prime, more tests needed)\n * 1: certain prime\n * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime\n * other negative: error\n */\nstatic int mpi_check_small_factors(const mbedtls_mpi *X)\n{\n    int ret = 0;\n    size_t i;\n    mbedtls_mpi_uint r;\n    unsigned p = 3; /* The first odd prime */\n\n    if ((X->p[0] & 1) == 0) {\n        return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;\n    }\n\n    for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p));\n        if (r == 0) {\n            if (mbedtls_mpi_cmp_int(X, p) == 0) {\n                return 1;\n            } else {\n                return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;\n            }\n        }\n    }\n\ncleanup:\n    return ret;\n}\n\n/*\n * Miller-Rabin pseudo-primality test  (HAC 4.24)\n */\nstatic int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,\n                            int (*f_rng)(void *, unsigned char *, size_t),\n                            void *p_rng)\n{\n    int ret, count;\n    size_t i, j, k, s;\n    mbedtls_mpi W, R, T, A, RR;\n\n    mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);\n    mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);\n    mbedtls_mpi_init(&RR);\n\n    /*\n     * W = |X| - 1\n     * R = W >> lsb( W )\n     */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));\n    s = mbedtls_mpi_lsb(&W);\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));\n\n    for (i = 0; i < rounds; i++) {\n        /*\n         * pick a random A, 1 < A < |X| - 1\n         */\n        count = 0;\n        do {\n            MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));\n\n            j = mbedtls_mpi_bitlen(&A);\n            k = mbedtls_mpi_bitlen(&W);\n            if (j > k) {\n                A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;\n            }\n\n            if (count++ > 30) {\n                ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;\n                goto cleanup;\n            }\n\n        } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||\n                 mbedtls_mpi_cmp_int(&A, 1)  <= 0);\n\n        /*\n         * A = A^R mod |X|\n         */\n        MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));\n\n        if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||\n            mbedtls_mpi_cmp_int(&A,  1) == 0) {\n            continue;\n        }\n\n        j = 1;\n        while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {\n            /*\n             * A = A * A mod |X|\n             */\n            MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));\n            MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));\n\n            if (mbedtls_mpi_cmp_int(&A, 1) == 0) {\n                break;\n            }\n\n            j++;\n        }\n\n        /*\n         * not prime if A != |X| - 1 or A == 1\n         */\n        if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||\n            mbedtls_mpi_cmp_int(&A,  1) == 0) {\n            ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;\n            break;\n        }\n    }\n\ncleanup:\n    mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);\n    mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);\n    mbedtls_mpi_free(&RR);\n\n    return ret;\n}\n\n/*\n * Pseudo-primality test: small factors, then Miller-Rabin\n */\nint mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,\n                             int (*f_rng)(void *, unsigned char *, size_t),\n                             void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi XX;\n\n    XX.s = 1;\n    XX.n = X->n;\n    XX.p = X->p;\n\n    if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||\n        mbedtls_mpi_cmp_int(&XX, 1) == 0) {\n        return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;\n    }\n\n    if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {\n        return 0;\n    }\n\n    if ((ret = mpi_check_small_factors(&XX)) != 0) {\n        if (ret == 1) {\n            return 0;\n        }\n\n        return ret;\n    }\n\n    return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);\n}\n\n/*\n * Prime number generation\n *\n * To generate an RSA key in a way recommended by FIPS 186-4, both primes must\n * be either 1024 bits or 1536 bits long, and flags must contain\n * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.\n */\nint mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,\n                          int (*f_rng)(void *, unsigned char *, size_t),\n                          void *p_rng)\n{\n#ifdef MBEDTLS_HAVE_INT64\n// ceil(2^63.5)\n#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL\n#else\n// ceil(2^31.5)\n#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U\n#endif\n    int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;\n    size_t k, n;\n    int rounds;\n    mbedtls_mpi_uint r;\n    mbedtls_mpi Y;\n\n    if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    mbedtls_mpi_init(&Y);\n\n    n = BITS_TO_LIMBS(nbits);\n\n    if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {\n        /*\n         * 2^-80 error probability, number of rounds chosen per HAC, table 4.4\n         */\n        rounds = ((nbits >= 1300) ?  2 : (nbits >=  850) ?  3 :\n                  (nbits >=  650) ?  4 : (nbits >=  350) ?  8 :\n                  (nbits >=  250) ? 12 : (nbits >=  150) ? 18 : 27);\n    } else {\n        /*\n         * 2^-100 error probability, number of rounds computed based on HAC,\n         * fact 4.48\n         */\n        rounds = ((nbits >= 1450) ?  4 : (nbits >=  1150) ?  5 :\n                  (nbits >= 1000) ?  6 : (nbits >=   850) ?  7 :\n                  (nbits >=  750) ?  8 : (nbits >=   500) ? 13 :\n                  (nbits >=  250) ? 28 : (nbits >=   150) ? 40 : 51);\n    }\n\n    while (1) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));\n        /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */\n        if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {\n            continue;\n        }\n\n        k = n * biL;\n        if (k > nbits) {\n            MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));\n        }\n        X->p[0] |= 1;\n\n        if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {\n            ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);\n\n            if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {\n                goto cleanup;\n            }\n        } else {\n            /*\n             * A necessary condition for Y and X = 2Y + 1 to be prime\n             * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).\n             * Make sure it is satisfied, while keeping X = 3 mod 4\n             */\n\n            X->p[0] |= 2;\n\n            MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));\n            if (r == 0) {\n                MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));\n            } else if (r == 1) {\n                MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));\n            }\n\n            /* Set Y = (X-1) / 2, which is X / 2 because X is odd */\n            MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));\n            MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));\n\n            while (1) {\n                /*\n                 * First, check small factors for X and Y\n                 * before doing Miller-Rabin on any of them\n                 */\n                if ((ret = mpi_check_small_factors(X)) == 0 &&\n                    (ret = mpi_check_small_factors(&Y)) == 0 &&\n                    (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))\n                    == 0 &&\n                    (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))\n                    == 0) {\n                    goto cleanup;\n                }\n\n                if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {\n                    goto cleanup;\n                }\n\n                /*\n                 * Next candidates. We want to preserve Y = (X-1) / 2 and\n                 * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)\n                 * so up Y by 6 and X by 12.\n                 */\n                MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X,  X, 12));\n                MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));\n            }\n        }\n    }\n\ncleanup:\n\n    mbedtls_mpi_free(&Y);\n\n    return ret;\n}\n\n#endif /* MBEDTLS_GENPRIME */\n\n#if defined(MBEDTLS_SELF_TEST)\n\n#define GCD_PAIR_COUNT  3\n\nstatic const int gcd_pairs[GCD_PAIR_COUNT][3] =\n{\n    { 693, 609, 21 },\n    { 1764, 868, 28 },\n    { 768454923, 542167814, 1 }\n};\n\n/*\n * Checkup routine\n */\nint mbedtls_mpi_self_test(int verbose)\n{\n    int ret, i;\n    mbedtls_mpi A, E, N, X, Y, U, V;\n\n    mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X);\n    mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V);\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,\n                                            \"EFE021C2645FD1DC586E69184AF4A31E\" \\\n                                            \"D5F53E93B5F123FA41680867BA110131\" \\\n                                            \"944FE7952E2517337780CB0DB80E61AA\" \\\n                                            \"E7C8DDC6C5C6AADEB34EB38A2F40D5E6\"));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,\n                                            \"B2E7EFD37075B9F03FF989C7C5051C20\" \\\n                                            \"34D2A323810251127E7BF8625A4F49A5\" \\\n                                            \"F3E27F4DA8BD59C47D6DAABA4C8127BD\" \\\n                                            \"5B5C25763222FEFCCFC38B832366C29E\"));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,\n                                            \"0066A198186C18C10B2F5ED9B522752A\" \\\n                                            \"9830B69916E535C8F047518A889A43A5\" \\\n                                            \"94B6BED27A168D31D4A52F88925AA8F5\"));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,\n                                            \"602AB7ECA597A3D6B56FF9829A5E8B85\" \\\n                                            \"9E857EA95A03512E2BAE7391688D264A\" \\\n                                            \"A5663B0341DB9CCFD2C4C5F421FEC814\" \\\n                                            \"8001B72E848A38CAE1C65F78E56ABDEF\" \\\n                                            \"E12D3C039B8A02D6BE593F0BBBDA56F1\" \\\n                                            \"ECF677152EF804370C1A305CAF3B5BF1\" \\\n                                            \"30879B56C61DE584A0F53A2447A51E\"));\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  MPI test #1 (mul_mpi): \");\n    }\n\n    if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n\n        ret = 1;\n        goto cleanup;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,\n                                            \"256567336059E52CAE22925474705F39A94\"));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,\n                                            \"6613F26162223DF488E9CD48CC132C7A\" \\\n                                            \"0AC93C701B001B092E4E5B9F73BCD27B\" \\\n                                            \"9EE50D0657C77F374E903CDFA4C642\"));\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  MPI test #2 (div_mpi): \");\n    }\n\n    if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||\n        mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n\n        ret = 1;\n        goto cleanup;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,\n                                            \"36E139AEA55215609D2816998ED020BB\" \\\n                                            \"BD96C37890F65171D948E9BC7CBAA4D9\" \\\n                                            \"325D24D6A3C12710F10A09FA08AB87\"));\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  MPI test #3 (exp_mod): \");\n    }\n\n    if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n\n        ret = 1;\n        goto cleanup;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,\n                                            \"003A0AAEDD7E784FC07D8F9EC6E3BFD5\" \\\n                                            \"C3DBA76456363A10869622EAC2DD84EC\" \\\n                                            \"C5B8A74DAC4D09E03B5E0BE779F2DF61\"));\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  MPI test #4 (inv_mod): \");\n    }\n\n    if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n\n        ret = 1;\n        goto cleanup;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  MPI test #5 (simple gcd): \");\n    }\n\n    for (i = 0; i < GCD_PAIR_COUNT; i++) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));\n\n        if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {\n            if (verbose != 0) {\n                mbedtls_printf(\"failed at %d\\n\", i);\n            }\n\n            ret = 1;\n            goto cleanup;\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\ncleanup:\n\n    if (ret != 0 && verbose != 0) {\n        mbedtls_printf(\"Unexpected error, return code = %08X\\n\", (unsigned int) ret);\n    }\n\n    mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);\n    mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    return ret;\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_BIGNUM_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/bignum_core.c",
    "content": "/*\n *  Core bignum functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_BIGNUM_C)\n\n#include <string.h>\n\n#include \"mbedtls/error.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"constant_time_internal.h\"\n\n#include \"mbedtls/platform.h\"\n\n#include \"bignum_core.h\"\n#include \"bignum_core_invasive.h\"\n#include \"bn_mul.h\"\n#include \"constant_time_internal.h\"\n\nsize_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a)\n{\n#if defined(__has_builtin)\n#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_clz)\n    #define core_clz __builtin_clz\n#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_clzl)\n    #define core_clz __builtin_clzl\n#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_clzll)\n    #define core_clz __builtin_clzll\n#endif\n#endif\n#if defined(core_clz)\n    return (size_t) core_clz(a);\n#else\n    size_t j;\n    mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);\n\n    for (j = 0; j < biL; j++) {\n        if (a & mask) {\n            break;\n        }\n\n        mask >>= 1;\n    }\n\n    return j;\n#endif\n}\n\nsize_t mbedtls_mpi_core_bitlen(const mbedtls_mpi_uint *A, size_t A_limbs)\n{\n    int i;\n    size_t j;\n\n    for (i = ((int) A_limbs) - 1; i >= 0; i--) {\n        if (A[i] != 0) {\n            j = biL - mbedtls_mpi_core_clz(A[i]);\n            return (i * biL) + j;\n        }\n    }\n\n    return 0;\n}\n\nstatic mbedtls_mpi_uint mpi_bigendian_to_host(mbedtls_mpi_uint a)\n{\n    if (MBEDTLS_IS_BIG_ENDIAN) {\n        /* Nothing to do on bigendian systems. */\n        return a;\n    } else {\n#if defined(MBEDTLS_HAVE_INT32)\n        return (mbedtls_mpi_uint) MBEDTLS_BSWAP32(a);\n#elif defined(MBEDTLS_HAVE_INT64)\n        return (mbedtls_mpi_uint) MBEDTLS_BSWAP64(a);\n#endif\n    }\n}\n\nvoid mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A,\n                                        size_t A_limbs)\n{\n    mbedtls_mpi_uint *cur_limb_left;\n    mbedtls_mpi_uint *cur_limb_right;\n    if (A_limbs == 0) {\n        return;\n    }\n\n    /*\n     * Traverse limbs and\n     * - adapt byte-order in each limb\n     * - swap the limbs themselves.\n     * For that, simultaneously traverse the limbs from left to right\n     * and from right to left, as long as the left index is not bigger\n     * than the right index (it's not a problem if limbs is odd and the\n     * indices coincide in the last iteration).\n     */\n    for (cur_limb_left = A, cur_limb_right = A + (A_limbs - 1);\n         cur_limb_left <= cur_limb_right;\n         cur_limb_left++, cur_limb_right--) {\n        mbedtls_mpi_uint tmp;\n        /* Note that if cur_limb_left == cur_limb_right,\n         * this code effectively swaps the bytes only once. */\n        tmp             = mpi_bigendian_to_host(*cur_limb_left);\n        *cur_limb_left  = mpi_bigendian_to_host(*cur_limb_right);\n        *cur_limb_right = tmp;\n    }\n}\n\n/* Whether min <= A, in constant time.\n * A_limbs must be at least 1. */\nmbedtls_ct_condition_t mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,\n                                                    const mbedtls_mpi_uint *A,\n                                                    size_t A_limbs)\n{\n    /* min <= least significant limb? */\n    mbedtls_ct_condition_t min_le_lsl = mbedtls_ct_uint_ge(A[0], min);\n\n    /* limbs other than the least significant one are all zero? */\n    mbedtls_ct_condition_t msll_mask = MBEDTLS_CT_FALSE;\n    for (size_t i = 1; i < A_limbs; i++) {\n        msll_mask = mbedtls_ct_bool_or(msll_mask, mbedtls_ct_bool(A[i]));\n    }\n\n    /* min <= A iff the lowest limb of A is >= min or the other limbs\n     * are not all zero. */\n    return mbedtls_ct_bool_or(msll_mask, min_le_lsl);\n}\n\nmbedtls_ct_condition_t mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,\n                                              const mbedtls_mpi_uint *B,\n                                              size_t limbs)\n{\n    mbedtls_ct_condition_t ret = MBEDTLS_CT_FALSE, cond = MBEDTLS_CT_FALSE, done = MBEDTLS_CT_FALSE;\n\n    for (size_t i = limbs; i > 0; i--) {\n        /*\n         * If B[i - 1] < A[i - 1] then A < B is false and the result must\n         * remain 0.\n         *\n         * Again even if we can make a decision, we just mark the result and\n         * the fact that we are done and continue looping.\n         */\n        cond = mbedtls_ct_uint_lt(B[i - 1], A[i - 1]);\n        done = mbedtls_ct_bool_or(done, cond);\n\n        /*\n         * If A[i - 1] < B[i - 1] then A < B is true.\n         *\n         * Again even if we can make a decision, we just mark the result and\n         * the fact that we are done and continue looping.\n         */\n        cond = mbedtls_ct_uint_lt(A[i - 1], B[i - 1]);\n        ret  = mbedtls_ct_bool_or(ret, mbedtls_ct_bool_and(cond, mbedtls_ct_bool_not(done)));\n        done = mbedtls_ct_bool_or(done, cond);\n    }\n\n    /*\n     * If all the limbs were equal, then the numbers are equal, A < B is false\n     * and leaving the result 0 is correct.\n     */\n\n    return ret;\n}\n\nvoid mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X,\n                                  const mbedtls_mpi_uint *A,\n                                  size_t limbs,\n                                  mbedtls_ct_condition_t assign)\n{\n    if (X == A) {\n        return;\n    }\n\n    /* This function is very performance-sensitive for RSA. For this reason\n     * we have the loop below, instead of calling mbedtls_ct_memcpy_if\n     * (this is more optimal since here we don't have to handle the case where\n     * we copy awkwardly sized data).\n     */\n    for (size_t i = 0; i < limbs; i++) {\n        X[i] = mbedtls_ct_mpi_uint_if(assign, A[i], X[i]);\n    }\n}\n\nvoid mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X,\n                                mbedtls_mpi_uint *Y,\n                                size_t limbs,\n                                mbedtls_ct_condition_t swap)\n{\n    if (X == Y) {\n        return;\n    }\n\n    for (size_t i = 0; i < limbs; i++) {\n        mbedtls_mpi_uint tmp = X[i];\n        X[i] = mbedtls_ct_mpi_uint_if(swap, Y[i], X[i]);\n        Y[i] = mbedtls_ct_mpi_uint_if(swap, tmp, Y[i]);\n    }\n}\n\nint mbedtls_mpi_core_read_le(mbedtls_mpi_uint *X,\n                             size_t X_limbs,\n                             const unsigned char *input,\n                             size_t input_length)\n{\n    const size_t limbs = CHARS_TO_LIMBS(input_length);\n\n    if (X_limbs < limbs) {\n        return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;\n    }\n\n    if (X != NULL) {\n        memset(X, 0, X_limbs * ciL);\n\n        for (size_t i = 0; i < input_length; i++) {\n            size_t offset = ((i % ciL) << 3);\n            X[i / ciL] |= ((mbedtls_mpi_uint) input[i]) << offset;\n        }\n    }\n\n    return 0;\n}\n\nint mbedtls_mpi_core_read_be(mbedtls_mpi_uint *X,\n                             size_t X_limbs,\n                             const unsigned char *input,\n                             size_t input_length)\n{\n    const size_t limbs = CHARS_TO_LIMBS(input_length);\n\n    if (X_limbs < limbs) {\n        return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;\n    }\n\n    /* If X_limbs is 0, input_length must also be 0 (from previous test).\n     * Nothing to do. */\n    if (X_limbs == 0) {\n        return 0;\n    }\n\n    memset(X, 0, X_limbs * ciL);\n\n    /* memcpy() with (NULL, 0) is undefined behaviour */\n    if (input_length != 0) {\n        size_t overhead = (X_limbs * ciL) - input_length;\n        unsigned char *Xp = (unsigned char *) X;\n        memcpy(Xp + overhead, input, input_length);\n    }\n\n    mbedtls_mpi_core_bigendian_to_host(X, X_limbs);\n\n    return 0;\n}\n\nint mbedtls_mpi_core_write_le(const mbedtls_mpi_uint *A,\n                              size_t A_limbs,\n                              unsigned char *output,\n                              size_t output_length)\n{\n    size_t stored_bytes = A_limbs * ciL;\n    size_t bytes_to_copy;\n\n    if (stored_bytes < output_length) {\n        bytes_to_copy = stored_bytes;\n    } else {\n        bytes_to_copy = output_length;\n\n        /* The output buffer is smaller than the allocated size of A.\n         * However A may fit if its leading bytes are zero. */\n        for (size_t i = bytes_to_copy; i < stored_bytes; i++) {\n            if (GET_BYTE(A, i) != 0) {\n                return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;\n            }\n        }\n    }\n\n    for (size_t i = 0; i < bytes_to_copy; i++) {\n        output[i] = GET_BYTE(A, i);\n    }\n\n    if (stored_bytes < output_length) {\n        /* Write trailing 0 bytes */\n        memset(output + stored_bytes, 0, output_length - stored_bytes);\n    }\n\n    return 0;\n}\n\nint mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *X,\n                              size_t X_limbs,\n                              unsigned char *output,\n                              size_t output_length)\n{\n    size_t stored_bytes;\n    size_t bytes_to_copy;\n    unsigned char *p;\n\n    stored_bytes = X_limbs * ciL;\n\n    if (stored_bytes < output_length) {\n        /* There is enough space in the output buffer. Write initial\n         * null bytes and record the position at which to start\n         * writing the significant bytes. In this case, the execution\n         * trace of this function does not depend on the value of the\n         * number. */\n        bytes_to_copy = stored_bytes;\n        p = output + output_length - stored_bytes;\n        memset(output, 0, output_length - stored_bytes);\n    } else {\n        /* The output buffer is smaller than the allocated size of X.\n         * However X may fit if its leading bytes are zero. */\n        bytes_to_copy = output_length;\n        p = output;\n        for (size_t i = bytes_to_copy; i < stored_bytes; i++) {\n            if (GET_BYTE(X, i) != 0) {\n                return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;\n            }\n        }\n    }\n\n    for (size_t i = 0; i < bytes_to_copy; i++) {\n        p[bytes_to_copy - i - 1] = GET_BYTE(X, i);\n    }\n\n    return 0;\n}\n\nvoid mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs,\n                              size_t count)\n{\n    size_t i, v0, v1;\n    mbedtls_mpi_uint r0 = 0, r1;\n\n    v0 = count /  biL;\n    v1 = count & (biL - 1);\n\n    if (v0 > limbs || (v0 == limbs && v1 > 0)) {\n        memset(X, 0, limbs * ciL);\n        return;\n    }\n\n    /*\n     * shift by count / limb_size\n     */\n    if (v0 > 0) {\n        for (i = 0; i < limbs - v0; i++) {\n            X[i] = X[i + v0];\n        }\n\n        for (; i < limbs; i++) {\n            X[i] = 0;\n        }\n    }\n\n    /*\n     * shift by count % limb_size\n     */\n    if (v1 > 0) {\n        for (i = limbs; i > 0; i--) {\n            r1 = X[i - 1] << (biL - v1);\n            X[i - 1] >>= v1;\n            X[i - 1] |= r0;\n            r0 = r1;\n        }\n    }\n}\n\nvoid mbedtls_mpi_core_shift_l(mbedtls_mpi_uint *X, size_t limbs,\n                              size_t count)\n{\n    size_t i, v0, v1;\n    mbedtls_mpi_uint r0 = 0, r1;\n\n    v0 = count / (biL);\n    v1 = count & (biL - 1);\n\n    /*\n     * shift by count / limb_size\n     */\n    if (v0 > 0) {\n        for (i = limbs; i > v0; i--) {\n            X[i - 1] = X[i - v0 - 1];\n        }\n\n        for (; i > 0; i--) {\n            X[i - 1] = 0;\n        }\n    }\n\n    /*\n     * shift by count % limb_size\n     */\n    if (v1 > 0) {\n        for (i = v0; i < limbs; i++) {\n            r1 = X[i] >> (biL - v1);\n            X[i] <<= v1;\n            X[i] |= r0;\n            r0 = r1;\n        }\n    }\n}\n\nmbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X,\n                                      const mbedtls_mpi_uint *A,\n                                      const mbedtls_mpi_uint *B,\n                                      size_t limbs)\n{\n    mbedtls_mpi_uint c = 0;\n\n    for (size_t i = 0; i < limbs; i++) {\n        mbedtls_mpi_uint t = c + A[i];\n        c = (t < A[i]);\n        t += B[i];\n        c += (t < B[i]);\n        X[i] = t;\n    }\n\n    return c;\n}\n\nmbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X,\n                                         const mbedtls_mpi_uint *A,\n                                         size_t limbs,\n                                         unsigned cond)\n{\n    mbedtls_mpi_uint c = 0;\n\n    mbedtls_ct_condition_t do_add = mbedtls_ct_bool(cond);\n\n    for (size_t i = 0; i < limbs; i++) {\n        mbedtls_mpi_uint add = mbedtls_ct_mpi_uint_if_else_0(do_add, A[i]);\n        mbedtls_mpi_uint t = c + X[i];\n        c = (t < X[i]);\n        t += add;\n        c += (t < add);\n        X[i] = t;\n    }\n\n    return c;\n}\n\nmbedtls_mpi_uint mbedtls_mpi_core_sub(mbedtls_mpi_uint *X,\n                                      const mbedtls_mpi_uint *A,\n                                      const mbedtls_mpi_uint *B,\n                                      size_t limbs)\n{\n    mbedtls_mpi_uint c = 0;\n\n    for (size_t i = 0; i < limbs; i++) {\n        mbedtls_mpi_uint z = (A[i] < c);\n        mbedtls_mpi_uint t = A[i] - c;\n        c = (t < B[i]) + z;\n        X[i] = t - B[i];\n    }\n\n    return c;\n}\n\nmbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *d, size_t d_len,\n                                      const mbedtls_mpi_uint *s, size_t s_len,\n                                      mbedtls_mpi_uint b)\n{\n    mbedtls_mpi_uint c = 0; /* carry */\n    /*\n     * It is a documented precondition of this function that d_len >= s_len.\n     * If that's not the case, we swap these round: this turns what would be\n     * a buffer overflow into an incorrect result.\n     */\n    if (d_len < s_len) {\n        s_len = d_len;\n    }\n    size_t excess_len = d_len - s_len;\n    size_t steps_x8 = s_len / 8;\n    size_t steps_x1 = s_len & 7;\n\n    while (steps_x8--) {\n        MULADDC_X8_INIT\n        MULADDC_X8_CORE\n            MULADDC_X8_STOP\n    }\n\n    while (steps_x1--) {\n        MULADDC_X1_INIT\n        MULADDC_X1_CORE\n            MULADDC_X1_STOP\n    }\n\n    while (excess_len--) {\n        *d += c;\n        c = (*d < c);\n        d++;\n    }\n\n    return c;\n}\n\nvoid mbedtls_mpi_core_mul(mbedtls_mpi_uint *X,\n                          const mbedtls_mpi_uint *A, size_t A_limbs,\n                          const mbedtls_mpi_uint *B, size_t B_limbs)\n{\n    memset(X, 0, (A_limbs + B_limbs) * ciL);\n\n    for (size_t i = 0; i < B_limbs; i++) {\n        (void) mbedtls_mpi_core_mla(X + i, A_limbs + 1, A, A_limbs, B[i]);\n    }\n}\n\n/*\n * Fast Montgomery initialization (thanks to Tom St Denis).\n */\nmbedtls_mpi_uint mbedtls_mpi_core_montmul_init(const mbedtls_mpi_uint *N)\n{\n    mbedtls_mpi_uint x = N[0];\n\n    x += ((N[0] + 2) & 4) << 1;\n\n    for (unsigned int i = biL; i >= 8; i /= 2) {\n        x *= (2 - (N[0] * x));\n    }\n\n    return ~x + 1;\n}\n\nvoid mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X,\n                              const mbedtls_mpi_uint *A,\n                              const mbedtls_mpi_uint *B,\n                              size_t B_limbs,\n                              const mbedtls_mpi_uint *N,\n                              size_t AN_limbs,\n                              mbedtls_mpi_uint mm,\n                              mbedtls_mpi_uint *T)\n{\n    memset(T, 0, (2 * AN_limbs + 1) * ciL);\n\n    for (size_t i = 0; i < AN_limbs; i++) {\n        /* T = (T + u0*B + u1*N) / 2^biL */\n        mbedtls_mpi_uint u0 = A[i];\n        mbedtls_mpi_uint u1 = (T[0] + u0 * B[0]) * mm;\n\n        (void) mbedtls_mpi_core_mla(T, AN_limbs + 2, B, B_limbs, u0);\n        (void) mbedtls_mpi_core_mla(T, AN_limbs + 2, N, AN_limbs, u1);\n\n        T++;\n    }\n\n    /*\n     * The result we want is (T >= N) ? T - N : T.\n     *\n     * For better constant-time properties in this function, we always do the\n     * subtraction, with the result in X.\n     *\n     * We also look to see if there was any carry in the final additions in the\n     * loop above.\n     */\n\n    mbedtls_mpi_uint carry  = T[AN_limbs];\n    mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, T, N, AN_limbs);\n\n    /*\n     * Using R as the Montgomery radix (auxiliary modulus) i.e. 2^(biL*AN_limbs):\n     *\n     * T can be in one of 3 ranges:\n     *\n     * 1) T < N      : (carry, borrow) = (0, 1): we want T\n     * 2) N <= T < R : (carry, borrow) = (0, 0): we want X\n     * 3) T >= R     : (carry, borrow) = (1, 1): we want X\n     *\n     * and (carry, borrow) = (1, 0) can't happen.\n     *\n     * So the correct return value is already in X if (carry ^ borrow) = 0,\n     * but is in (the lower AN_limbs limbs of) T if (carry ^ borrow) = 1.\n     */\n    mbedtls_ct_memcpy_if(mbedtls_ct_bool(carry ^ borrow),\n                         (unsigned char *) X,\n                         (unsigned char *) T,\n                         NULL,\n                         AN_limbs * sizeof(mbedtls_mpi_uint));\n}\n\nint mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X,\n                                        const mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(X, N->n * 2 * biL));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(X, N->n));\n\ncleanup:\n    return ret;\n}\n\nMBEDTLS_STATIC_TESTABLE\nvoid mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest,\n                                           const mbedtls_mpi_uint *table,\n                                           size_t limbs,\n                                           size_t count,\n                                           size_t index)\n{\n    for (size_t i = 0; i < count; i++, table += limbs) {\n        mbedtls_ct_condition_t assign = mbedtls_ct_uint_eq(i, index);\n        mbedtls_mpi_core_cond_assign(dest, table, limbs, assign);\n    }\n}\n\n/* Fill X with n_bytes random bytes.\n * X must already have room for those bytes.\n * The ordering of the bytes returned from the RNG is suitable for\n * deterministic ECDSA (see RFC 6979 §3.3 and the specification of\n * mbedtls_mpi_core_random()).\n */\nint mbedtls_mpi_core_fill_random(\n    mbedtls_mpi_uint *X, size_t X_limbs,\n    size_t n_bytes,\n    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const size_t limbs = CHARS_TO_LIMBS(n_bytes);\n    const size_t overhead = (limbs * ciL) - n_bytes;\n\n    if (X_limbs < limbs) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    memset(X, 0, overhead);\n    memset((unsigned char *) X + limbs * ciL, 0, (X_limbs - limbs) * ciL);\n    MBEDTLS_MPI_CHK(f_rng(p_rng, (unsigned char *) X + overhead, n_bytes));\n    mbedtls_mpi_core_bigendian_to_host(X, limbs);\n\ncleanup:\n    return ret;\n}\n\nint mbedtls_mpi_core_random(mbedtls_mpi_uint *X,\n                            mbedtls_mpi_uint min,\n                            const mbedtls_mpi_uint *N,\n                            size_t limbs,\n                            int (*f_rng)(void *, unsigned char *, size_t),\n                            void *p_rng)\n{\n    mbedtls_ct_condition_t ge_lower = MBEDTLS_CT_TRUE, lt_upper = MBEDTLS_CT_FALSE;\n    size_t n_bits = mbedtls_mpi_core_bitlen(N, limbs);\n    size_t n_bytes = (n_bits + 7) / 8;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /*\n     * When min == 0, each try has at worst a probability 1/2 of failing\n     * (the msb has a probability 1/2 of being 0, and then the result will\n     * be < N), so after 30 tries failure probability is a most 2**(-30).\n     *\n     * When N is just below a power of 2, as is the case when generating\n     * a random scalar on most elliptic curves, 1 try is enough with\n     * overwhelming probability. When N is just above a power of 2,\n     * as when generating a random scalar on secp224k1, each try has\n     * a probability of failing that is almost 1/2.\n     *\n     * The probabilities are almost the same if min is nonzero but negligible\n     * compared to N. This is always the case when N is crypto-sized, but\n     * it's convenient to support small N for testing purposes. When N\n     * is small, use a higher repeat count, otherwise the probability of\n     * failure is macroscopic.\n     */\n    int count = (n_bytes > 4 ? 30 : 250);\n\n    /*\n     * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)\n     * when f_rng is a suitably parametrized instance of HMAC_DRBG:\n     * - use the same byte ordering;\n     * - keep the leftmost n_bits bits of the generated octet string;\n     * - try until result is in the desired range.\n     * This also avoids any bias, which is especially important for ECDSA.\n     */\n    do {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_core_fill_random(X, limbs,\n                                                     n_bytes,\n                                                     f_rng, p_rng));\n        mbedtls_mpi_core_shift_r(X, limbs, 8 * n_bytes - n_bits);\n\n        if (--count == 0) {\n            ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;\n            goto cleanup;\n        }\n\n        ge_lower = mbedtls_mpi_core_uint_le_mpi(min, X, limbs);\n        lt_upper = mbedtls_mpi_core_lt_ct(X, N, limbs);\n    } while (mbedtls_ct_bool_and(ge_lower, lt_upper) == MBEDTLS_CT_FALSE);\n\ncleanup:\n    return ret;\n}\n\nstatic size_t exp_mod_get_window_size(size_t Ebits)\n{\n#if MBEDTLS_MPI_WINDOW_SIZE >= 6\n    return (Ebits > 671) ? 6 : (Ebits > 239) ? 5 : (Ebits >  79) ? 4 : 1;\n#elif MBEDTLS_MPI_WINDOW_SIZE == 5\n    return (Ebits > 239) ? 5 : (Ebits >  79) ? 4 : 1;\n#elif MBEDTLS_MPI_WINDOW_SIZE > 1\n    return (Ebits >  79) ? MBEDTLS_MPI_WINDOW_SIZE : 1;\n#else\n    (void) Ebits;\n    return 1;\n#endif\n}\n\nsize_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs)\n{\n    const size_t wsize = exp_mod_get_window_size(E_limbs * biL);\n    const size_t welem = ((size_t) 1) << wsize;\n\n    /* How big does each part of the working memory pool need to be? */\n    const size_t table_limbs   = welem * AN_limbs;\n    const size_t select_limbs  = AN_limbs;\n    const size_t temp_limbs    = 2 * AN_limbs + 1;\n\n    return table_limbs + select_limbs + temp_limbs;\n}\n\nstatic void exp_mod_precompute_window(const mbedtls_mpi_uint *A,\n                                      const mbedtls_mpi_uint *N,\n                                      size_t AN_limbs,\n                                      mbedtls_mpi_uint mm,\n                                      const mbedtls_mpi_uint *RR,\n                                      size_t welem,\n                                      mbedtls_mpi_uint *Wtable,\n                                      mbedtls_mpi_uint *temp)\n{\n    /* W[0] = 1 (in Montgomery presentation) */\n    memset(Wtable, 0, AN_limbs * ciL);\n    Wtable[0] = 1;\n    mbedtls_mpi_core_montmul(Wtable, Wtable, RR, AN_limbs, N, AN_limbs, mm, temp);\n\n    /* W[1] = A (already in Montgomery presentation) */\n    mbedtls_mpi_uint *W1 = Wtable + AN_limbs;\n    memcpy(W1, A, AN_limbs * ciL);\n\n    /* W[i+1] = W[i] * W[1], i >= 2 */\n    mbedtls_mpi_uint *Wprev = W1;\n    for (size_t i = 2; i < welem; i++) {\n        mbedtls_mpi_uint *Wcur = Wprev + AN_limbs;\n        mbedtls_mpi_core_montmul(Wcur, Wprev, W1, AN_limbs, N, AN_limbs, mm, temp);\n        Wprev = Wcur;\n    }\n}\n\n#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)\nvoid (*mbedtls_safe_codepath_hook)(void) = NULL;\nvoid (*mbedtls_unsafe_codepath_hook)(void) = NULL;\n#endif\n\n/*\n * This function calculates the indices of the exponent where the exponentiation algorithm should\n * start processing.\n *\n * Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value,\n * this function is not constant time with respect to the exponent (parameter E).\n */\nstatic inline void exp_mod_calc_first_bit_optionally_safe(const mbedtls_mpi_uint *E,\n                                                          size_t E_limbs,\n                                                          int E_public,\n                                                          size_t *E_limb_index,\n                                                          size_t *E_bit_index)\n{\n    if (E_public == MBEDTLS_MPI_IS_PUBLIC) {\n        /*\n         * Skip leading zero bits.\n         */\n        size_t E_bits = mbedtls_mpi_core_bitlen(E, E_limbs);\n        if (E_bits == 0) {\n            /*\n             * If E is 0 mbedtls_mpi_core_bitlen() returns 0. Even if that is the case, we will want\n             * to represent it as a single 0 bit and as such the bitlength will be 1.\n             */\n            E_bits = 1;\n        }\n\n        *E_limb_index = E_bits / biL;\n        *E_bit_index = E_bits % biL;\n\n#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)\n        if (mbedtls_unsafe_codepath_hook != NULL) {\n            mbedtls_unsafe_codepath_hook();\n        }\n#endif\n    } else {\n        /*\n         * Here we need to be constant time with respect to E and can't do anything better than\n         * start at the first allocated bit.\n         */\n        *E_limb_index = E_limbs;\n        *E_bit_index = 0;\n#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)\n        if (mbedtls_safe_codepath_hook != NULL) {\n            mbedtls_safe_codepath_hook();\n        }\n#endif\n    }\n}\n\n/*\n * Warning! If the parameter window_public has MBEDTLS_MPI_IS_PUBLIC as its value, this function is\n * not constant time with respect to the window parameter and consequently the exponent of the\n * exponentiation (parameter E of mbedtls_mpi_core_exp_mod_optionally_safe).\n */\nstatic inline void exp_mod_table_lookup_optionally_safe(mbedtls_mpi_uint *Wselect,\n                                                        mbedtls_mpi_uint *Wtable,\n                                                        size_t AN_limbs, size_t welem,\n                                                        mbedtls_mpi_uint window,\n                                                        int window_public)\n{\n    if (window_public == MBEDTLS_MPI_IS_PUBLIC) {\n        memcpy(Wselect, Wtable + window * AN_limbs, AN_limbs * ciL);\n#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)\n        if (mbedtls_unsafe_codepath_hook != NULL) {\n            mbedtls_unsafe_codepath_hook();\n        }\n#endif\n    } else {\n        /* Select Wtable[window] without leaking window through\n         * memory access patterns. */\n        mbedtls_mpi_core_ct_uint_table_lookup(Wselect, Wtable,\n                                              AN_limbs, welem, window);\n#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)\n        if (mbedtls_safe_codepath_hook != NULL) {\n            mbedtls_safe_codepath_hook();\n        }\n#endif\n    }\n}\n\n/* Exponentiation: X := A^E mod N.\n *\n * Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value,\n * this function is not constant time with respect to the exponent (parameter E).\n *\n * A must already be in Montgomery form.\n *\n * As in other bignum functions, assume that AN_limbs and E_limbs are nonzero.\n *\n * RR must contain 2^{2*biL} mod N.\n *\n * The algorithm is a variant of Left-to-right k-ary exponentiation: HAC 14.82\n * (The difference is that the body in our loop processes a single bit instead\n * of a full window.)\n */\nstatic void mbedtls_mpi_core_exp_mod_optionally_safe(mbedtls_mpi_uint *X,\n                                                     const mbedtls_mpi_uint *A,\n                                                     const mbedtls_mpi_uint *N,\n                                                     size_t AN_limbs,\n                                                     const mbedtls_mpi_uint *E,\n                                                     size_t E_limbs,\n                                                     int E_public,\n                                                     const mbedtls_mpi_uint *RR,\n                                                     mbedtls_mpi_uint *T)\n{\n    /* We'll process the bits of E from most significant\n     * (limb_index=E_limbs-1, E_bit_index=biL-1) to least significant\n     * (limb_index=0, E_bit_index=0). */\n    size_t E_limb_index = E_limbs;\n    size_t E_bit_index = 0;\n    exp_mod_calc_first_bit_optionally_safe(E, E_limbs, E_public,\n                                           &E_limb_index, &E_bit_index);\n\n    const size_t wsize = exp_mod_get_window_size(E_limb_index * biL);\n    const size_t welem = ((size_t) 1) << wsize;\n\n    /* This is how we will use the temporary storage T, which must have space\n     * for table_limbs, select_limbs and (2 * AN_limbs + 1) for montmul. */\n    const size_t table_limbs  = welem * AN_limbs;\n    const size_t select_limbs = AN_limbs;\n\n    /* Pointers to specific parts of the temporary working memory pool */\n    mbedtls_mpi_uint *const Wtable  = T;\n    mbedtls_mpi_uint *const Wselect = Wtable  +  table_limbs;\n    mbedtls_mpi_uint *const temp    = Wselect + select_limbs;\n\n    /*\n     * Window precomputation\n     */\n\n    const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N);\n\n    /* Set Wtable[i] = A^i (in Montgomery representation) */\n    exp_mod_precompute_window(A, N, AN_limbs,\n                              mm, RR,\n                              welem, Wtable, temp);\n\n    /*\n     * Fixed window exponentiation\n     */\n\n    /* X = 1 (in Montgomery presentation) initially */\n    memcpy(X, Wtable, AN_limbs * ciL);\n\n    /* At any given time, window contains window_bits bits from E.\n     * window_bits can go up to wsize. */\n    size_t window_bits = 0;\n    mbedtls_mpi_uint window = 0;\n\n    do {\n        /* Square */\n        mbedtls_mpi_core_montmul(X, X, X, AN_limbs, N, AN_limbs, mm, temp);\n\n        /* Move to the next bit of the exponent */\n        if (E_bit_index == 0) {\n            --E_limb_index;\n            E_bit_index = biL - 1;\n        } else {\n            --E_bit_index;\n        }\n        /* Insert next exponent bit into window */\n        ++window_bits;\n        window <<= 1;\n        window |= (E[E_limb_index] >> E_bit_index) & 1;\n\n        /* Clear window if it's full. Also clear the window at the end,\n         * when we've finished processing the exponent. */\n        if (window_bits == wsize ||\n            (E_bit_index == 0 && E_limb_index == 0)) {\n\n            exp_mod_table_lookup_optionally_safe(Wselect, Wtable, AN_limbs, welem,\n                                                 window, E_public);\n            /* Multiply X by the selected element. */\n            mbedtls_mpi_core_montmul(X, X, Wselect, AN_limbs, N, AN_limbs, mm,\n                                     temp);\n            window = 0;\n            window_bits = 0;\n        }\n    } while (!(E_bit_index == 0 && E_limb_index == 0));\n}\n\nvoid mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,\n                              const mbedtls_mpi_uint *A,\n                              const mbedtls_mpi_uint *N, size_t AN_limbs,\n                              const mbedtls_mpi_uint *E, size_t E_limbs,\n                              const mbedtls_mpi_uint *RR,\n                              mbedtls_mpi_uint *T)\n{\n    mbedtls_mpi_core_exp_mod_optionally_safe(X,\n                                             A,\n                                             N,\n                                             AN_limbs,\n                                             E,\n                                             E_limbs,\n                                             MBEDTLS_MPI_IS_SECRET,\n                                             RR,\n                                             T);\n}\n\nvoid mbedtls_mpi_core_exp_mod_unsafe(mbedtls_mpi_uint *X,\n                                     const mbedtls_mpi_uint *A,\n                                     const mbedtls_mpi_uint *N, size_t AN_limbs,\n                                     const mbedtls_mpi_uint *E, size_t E_limbs,\n                                     const mbedtls_mpi_uint *RR,\n                                     mbedtls_mpi_uint *T)\n{\n    mbedtls_mpi_core_exp_mod_optionally_safe(X,\n                                             A,\n                                             N,\n                                             AN_limbs,\n                                             E,\n                                             E_limbs,\n                                             MBEDTLS_MPI_IS_PUBLIC,\n                                             RR,\n                                             T);\n}\n\nmbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X,\n                                          const mbedtls_mpi_uint *A,\n                                          mbedtls_mpi_uint c,  /* doubles as carry */\n                                          size_t limbs)\n{\n    for (size_t i = 0; i < limbs; i++) {\n        mbedtls_mpi_uint s = A[i];\n        mbedtls_mpi_uint t = s - c;\n        c = (t > s);\n        X[i] = t;\n    }\n\n    return c;\n}\n\nmbedtls_ct_condition_t mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,\n                                                      size_t limbs)\n{\n    volatile const mbedtls_mpi_uint *force_read_A = A;\n    mbedtls_mpi_uint bits = 0;\n\n    for (size_t i = 0; i < limbs; i++) {\n        bits |= force_read_A[i];\n    }\n\n    return mbedtls_ct_bool(bits);\n}\n\nvoid mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X,\n                                  const mbedtls_mpi_uint *A,\n                                  const mbedtls_mpi_uint *N,\n                                  size_t AN_limbs,\n                                  mbedtls_mpi_uint mm,\n                                  const mbedtls_mpi_uint *rr,\n                                  mbedtls_mpi_uint *T)\n{\n    mbedtls_mpi_core_montmul(X, A, rr, AN_limbs, N, AN_limbs, mm, T);\n}\n\nvoid mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X,\n                                    const mbedtls_mpi_uint *A,\n                                    const mbedtls_mpi_uint *N,\n                                    size_t AN_limbs,\n                                    mbedtls_mpi_uint mm,\n                                    mbedtls_mpi_uint *T)\n{\n    const mbedtls_mpi_uint Rinv = 1;    /* 1/R in Mont. rep => 1 */\n\n    mbedtls_mpi_core_montmul(X, A, &Rinv, 1, N, AN_limbs, mm, T);\n}\n\n/*\n * Compute X = A - B mod N.\n * Both A and B must be in [0, N) and so will the output.\n */\nstatic void mpi_core_sub_mod(mbedtls_mpi_uint *X,\n                             const mbedtls_mpi_uint *A,\n                             const mbedtls_mpi_uint *B,\n                             const mbedtls_mpi_uint *N,\n                             size_t limbs)\n{\n    mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, A, B, limbs);\n    (void) mbedtls_mpi_core_add_if(X, N, limbs, (unsigned) c);\n}\n\n/*\n * Divide X by 2 mod N in place, assuming N is odd.\n * The input must be in [0, N) and so will the output.\n */\nMBEDTLS_STATIC_TESTABLE\nvoid mbedtls_mpi_core_div2_mod_odd(mbedtls_mpi_uint *X,\n                                   const mbedtls_mpi_uint *N,\n                                   size_t limbs)\n{\n    /* If X is odd, add N to make it even before shifting. */\n    unsigned odd = (unsigned) X[0] & 1;\n    mbedtls_mpi_uint c = mbedtls_mpi_core_add_if(X, N, limbs, odd);\n    mbedtls_mpi_core_shift_r(X, limbs, 1);\n    X[limbs - 1] |= c << (biL - 1);\n}\n\n/*\n * Constant-time GCD and modular inversion - odd modulus.\n *\n * Pre-conditions: see public documentation.\n *\n * See https://www.jstage.jst.go.jp/article/transinf/E106.D/9/E106.D_2022ICP0009/_pdf\n *\n * The paper gives two computationally equivalent algorithms: Alg 7 (readable)\n * and Alg 8 (constant-time). We use a third version that's hopefully both:\n *\n *  u, v = A, N  # N is called p in the paper but doesn't have to be prime\n *  q, r = 0, 1\n *  repeat bits(A_limbs + N_limbs) times:\n *      d = v - u  # t1 in Alg 7\n *      t1 = (u and v both odd) ? u : d  # t1 in Alg 8\n *      t2 = (u and v both odd) ? d : (u odd) ? v : u  # t2 in Alg 8\n *      t2 >>= 1\n *      swap = t1 > t2  # similar to s, z in Alg 8\n *      u, v = (swap) ? t2, t1 : t1, t2\n *\n *      d = r - q mod N  # t2 in Alg 7\n *      t1 = (u and v both odd) ? q : d  # t3 in Alg 8\n *      t2 = (u and v both odd) ? d : (u odd) ? r : q  # t4 Alg 8\n *      t2 /= 2 mod N  # see below (pre_com)\n *      q, r = (swap) ? t2, t1 : t1, t2\n *  return v, q  # v: GCD, see Alg 6; q: no mult by pre_com, see below\n *\n * The ternary operators in the above pseudo-code need to be realised in a\n * constant-time fashion. We use conditional assign for t1, t2 and conditional\n * swap for the final update. (Note: the similarity between branches of Alg 7\n * are highlighted in tables 2 and 3 and the surrounding text.)\n *\n * Also, we re-order operations, grouping things related to the inverse, which\n * facilitates making its computation optional, and requires fewer temporaries.\n *\n * The only actual change from the paper is dropping the trick with pre_com,\n * which I think complicates things for no benefit.\n * See the comment on the big I != NULL block below for details.\n */\nvoid mbedtls_mpi_core_gcd_modinv_odd(mbedtls_mpi_uint *G,\n                                     mbedtls_mpi_uint *I,\n                                     const mbedtls_mpi_uint *A,\n                                     size_t A_limbs,\n                                     const mbedtls_mpi_uint *N,\n                                     size_t N_limbs,\n                                     mbedtls_mpi_uint *T)\n{\n    /* GCD and modinv, names common to Alg 7 and Alg 8 */\n    mbedtls_mpi_uint *u = T + 0 * N_limbs;\n    mbedtls_mpi_uint *v = G;\n\n    /* GCD and modinv, my name (t1, t2 from Alg 7) */\n    mbedtls_mpi_uint *d = T + 1 * N_limbs;\n\n    /* GCD and modinv, names from Alg 8 (note: t1, t2 from Alg 7 are d above) */\n    mbedtls_mpi_uint *t1 = T + 2 * N_limbs;\n    mbedtls_mpi_uint *t2 = T + 3 * N_limbs;\n\n    /* modinv only, names common to Alg 7 and Alg 8 */\n    mbedtls_mpi_uint *q = I;\n    mbedtls_mpi_uint *r = I != NULL ? T + 4 * N_limbs : NULL;\n\n    /*\n     * Initial values:\n     * u, v = A, N\n     * q, r = 0, 1\n     *\n     * We only write to G (aka v) after reading from inputs (A and N), which\n     * allows aliasing, except with N when I != NULL, as then we'll be operating\n     * mod N on q and r later - see the public documentation.\n     */\n    if (A_limbs > N_limbs) {\n        /* Violating this precondition should not result in memory errors. */\n        A_limbs = N_limbs;\n    }\n    memcpy(u, A, A_limbs * ciL);\n    memset((char *) u + A_limbs * ciL, 0, (N_limbs - A_limbs) * ciL);\n\n    /* Avoid possible UB with memcpy when src == dst. */\n    if (v != N) {\n        memcpy(v, N, N_limbs * ciL);\n    }\n\n    if (I != NULL) {\n        memset(q, 0, N_limbs * ciL);\n\n        memset(r, 0, N_limbs * ciL);\n        r[0] = 1;\n    }\n\n    /*\n     * At each step, out of u, v, v - u we keep one, shift another, and discard\n     * the third, then update (u, v) with the ordered result.\n     * Then we mirror those actions with q, r, r - q mod N.\n     *\n     * Loop invariants:\n     *  u <= v                  (on entry: A <= N)\n     *  GCD(u, v) == GCD(A, N)  (on entry: trivial)\n     *  v = A * q mod N         (on entry: N = A * 0 mod N)\n     *  u = A * r mod N         (on entry: A = A * 1 mod N)\n     *  q, r in [0, N)          (on entry: 0, 1)\n     *\n     * On exit:\n     *  u = 0\n     *  v = GCD(A, N) = A * q mod N\n     *  if v == 1 then 1 = A * q mod N ie q is A's inverse mod N\n     *  r = 0\n     *\n     * The exit state is a fixed point of the loop's body.\n     * Alg 7 and Alg 8 use 2 * bitlen(N) iterations but Theorem 2 (above in the\n     * paper) says bitlen(A) + bitlen(N) is actually enough.\n     */\n    for (size_t i = 0; i < (A_limbs + N_limbs) * biL; i++) {\n        /* s, z in Alg 8 - use meaningful names instead */\n        mbedtls_ct_condition_t u_odd = mbedtls_ct_bool(u[0] & 1);\n        mbedtls_ct_condition_t v_odd = mbedtls_ct_bool(v[0] & 1);\n\n        /* Other conditions that will be useful below */\n        mbedtls_ct_condition_t u_odd_v_odd = mbedtls_ct_bool_and(u_odd, v_odd);\n        mbedtls_ct_condition_t v_even = mbedtls_ct_bool_not(v_odd);\n        mbedtls_ct_condition_t u_odd_v_even = mbedtls_ct_bool_and(u_odd, v_even);\n\n        /* This is called t1 in Alg 7 (no name in Alg 8).\n         * We know that u <= v so there is no carry */\n        (void) mbedtls_mpi_core_sub(d, v, u, N_limbs);\n\n        /* t1 (the thing that's kept) can be d (default) or u (if t2 is d) */\n        memcpy(t1, d, N_limbs * ciL);\n        mbedtls_mpi_core_cond_assign(t1, u, N_limbs, u_odd_v_odd);\n\n        /* t2 (the thing that's shifted) can be u (if even), or v (if even),\n         * or d (which is even if both u and v were odd) */\n        memcpy(t2, u, N_limbs * ciL);\n        mbedtls_mpi_core_cond_assign(t2, v, N_limbs, u_odd_v_even);\n        mbedtls_mpi_core_cond_assign(t2, d, N_limbs, u_odd_v_odd);\n\n        mbedtls_mpi_core_shift_r(t2, N_limbs, 1); // t2 is even\n\n        /* Update u, v and re-order them if needed */\n        memcpy(u, t1, N_limbs * ciL);\n        memcpy(v, t2, N_limbs * ciL);\n        mbedtls_ct_condition_t swap = mbedtls_mpi_core_lt_ct(v, u, N_limbs);\n        mbedtls_mpi_core_cond_swap(u, v, N_limbs, swap);\n\n        /* Now, if modinv was requested, do the same with q, r, but:\n         * - decisions still based on u and v (their initial values);\n         * - operations are now mod N;\n         * - we re-use t1, t2 for what the paper calls t3, t4 in Alg 8.\n         *\n         * Here we slightly diverge from the paper and instead do the obvious\n         * thing that preserves the invariants involving q and r: mirror\n         * operations on u and v, ie also divide by 2 here (mod N).\n         *\n         * The paper uses a trick where it replaces division by 2 with\n         * multiplication by 2 here, and compensates in the end by multiplying\n         * by pre_com, which is probably intended as an optimisation.\n         *\n         * However I believe it's not actually an optimisation, since\n         * constant-time modular multiplication by 2 (left-shift + conditional\n         * subtract) is just as costly as constant-time modular division by 2\n         * (conditional add + right-shift). So, skip it and keep things simple.\n         */\n        if (I != NULL) {\n            /* This is called t2 in Alg 7 (no name in Alg 8). */\n            mpi_core_sub_mod(d, q, r, N, N_limbs);\n\n            /* t3 (the thing that's kept) */\n            memcpy(t1, d, N_limbs * ciL);\n            mbedtls_mpi_core_cond_assign(t1, r, N_limbs, u_odd_v_odd);\n\n            /* t4 (the thing that's shifted) */\n            memcpy(t2, r, N_limbs * ciL);\n            mbedtls_mpi_core_cond_assign(t2, q, N_limbs, u_odd_v_even);\n            mbedtls_mpi_core_cond_assign(t2, d, N_limbs, u_odd_v_odd);\n\n            mbedtls_mpi_core_div2_mod_odd(t2, N, N_limbs);\n\n            /* Update and possibly swap */\n            memcpy(r, t1, N_limbs * ciL);\n            memcpy(q, t2, N_limbs * ciL);\n            mbedtls_mpi_core_cond_swap(r, q, N_limbs, swap);\n        }\n    }\n\n    /* G and I already hold the correct values by virtue of being aliased */\n}\n\n#endif /* MBEDTLS_BIGNUM_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/bignum_core.h",
    "content": "/**\n *  Core bignum functions\n *\n *  This interface should only be used by the legacy bignum module (bignum.h)\n *  and the modular bignum modules (bignum_mod.c, bignum_mod_raw.c). All other\n *  modules should use the high-level modular bignum interface (bignum_mod.h)\n *  or the legacy bignum interface (bignum.h).\n *\n * This module is about processing non-negative integers with a fixed upper\n * bound that's of the form 2^n-1 where n is a multiple of #biL.\n * These can be thought of integers written in base 2^#biL with a fixed\n * number of digits. Digits in this base are called *limbs*.\n * Many operations treat these numbers as the principal representation of\n * a number modulo 2^n or a smaller bound.\n *\n * The functions in this module obey the following conventions unless\n * explicitly indicated otherwise:\n *\n * - **Overflow**: some functions indicate overflow from the range\n *   [0, 2^n-1] by returning carry parameters, while others operate\n *   modulo and so cannot overflow. This should be clear from the function\n *   documentation.\n * - **Bignum parameters**: Bignums are passed as pointers to an array of\n *   limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified:\n *     - Bignum parameters called \\p A, \\p B, ... are inputs, and are\n *       not modified by the function.\n *     - For operations modulo some number, the modulus is called \\p N\n *       and is input-only.\n *     - Bignum parameters called \\p X, \\p Y are outputs or input-output.\n *       The initial content of output-only parameters is ignored.\n *     - Some functions use different names that reflect traditional\n *       naming of operands of certain operations (e.g.\n *       divisor/dividend/quotient/remainder).\n *     - \\p T is a temporary storage area. The initial content of such\n *       parameter is ignored and the final content is unspecified.\n * - **Bignum sizes**: bignum sizes are always expressed in limbs.\n *   Most functions work on bignums of a given size and take a single\n *   \\p limbs parameter that applies to all parameters that are limb arrays.\n *   All bignum sizes must be at least 1 and must be significantly less than\n *   #SIZE_MAX. The behavior if a size is 0 is undefined. The behavior if the\n *   total size of all parameters overflows #SIZE_MAX is undefined.\n * - **Parameter ordering**: for bignum parameters, outputs come before inputs.\n *   Temporaries come last.\n * - **Aliasing**: in general, output bignums may be aliased to one or more\n *   inputs. As an exception, parameters that are documented as a modulus value\n *   may not be aliased to an output. Outputs may not be aliased to one another.\n *   Temporaries may not be aliased to any other parameter.\n * - **Overlap**: apart from aliasing of limb array pointers (where two\n *   arguments are equal pointers), overlap is not supported and may result\n *   in undefined behavior.\n * - **Error handling**: This is a low-level module. Functions generally do not\n *   try to protect against invalid arguments such as nonsensical sizes or\n *   null pointers. Note that some functions that operate on bignums of\n *   different sizes have constraints about their size, and violating those\n *   constraints may lead to buffer overflows.\n * - **Modular representatives**: functions that operate modulo \\p N expect\n *   all modular inputs to be in the range [0, \\p N - 1] and guarantee outputs\n *   in the range [0, \\p N - 1]. If an input is out of range, outputs are\n *   fully unspecified, though bignum values out of range should not cause\n *   buffer overflows (beware that this is not extensively tested).\n */\n\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_BIGNUM_CORE_H\n#define MBEDTLS_BIGNUM_CORE_H\n\n#include \"common.h\"\n\n#include \"mbedtls/bignum.h\"\n\n#include \"constant_time_internal.h\"\n\n#define ciL    (sizeof(mbedtls_mpi_uint))     /** chars in limb  */\n#define biL    (ciL << 3)                     /** bits  in limb  */\n#define biH    (ciL << 2)                     /** half limb size */\n\n/*\n * Convert between bits/chars and number of limbs\n * Divide first in order to avoid potential overflows\n */\n#define BITS_TO_LIMBS(i)  ((i) / biL + ((i) % biL != 0))\n#define CHARS_TO_LIMBS(i) ((i) / ciL + ((i) % ciL != 0))\n/* Get a specific byte, without range checks. */\n#define GET_BYTE(X, i)                                \\\n    (((X)[(i) / ciL] >> (((i) % ciL) * 8)) & 0xff)\n\n/* Constants to identify whether a value is public or secret. If a parameter is marked as secret by\n * this constant, the function must be constant time with respect to the parameter.\n *\n * This is only needed for functions with the _optionally_safe postfix. All other functions have\n * fixed behavior that can't be changed at runtime and are constant time with respect to their\n * parameters as prescribed by their documentation or by conventions in their module's documentation.\n *\n * Parameters should be named X_public where X is the name of the\n * corresponding input parameter.\n *\n * Implementation should always check using\n *  if (X_public == MBEDTLS_MPI_IS_PUBLIC) {\n *      // unsafe path\n *  } else {\n *      // safe path\n *  }\n * not the other way round, in order to prevent misuse. (That is, if a value\n * other than the two below is passed, default to the safe path.)\n *\n * The value of MBEDTLS_MPI_IS_PUBLIC is chosen in a way that is unlikely to happen by accident, but\n * which can be used as an immediate value in a Thumb2 comparison (for code size). */\n#define MBEDTLS_MPI_IS_PUBLIC  0x2a2a2a2a\n#define MBEDTLS_MPI_IS_SECRET  0\n#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)\n// Default value for testing that is neither MBEDTLS_MPI_IS_PUBLIC nor MBEDTLS_MPI_IS_SECRET\n#define MBEDTLS_MPI_IS_TEST  1\n#endif\n\n/** Count leading zero bits in a given integer.\n *\n * \\warning     The result is undefined if \\p a == 0\n *\n * \\param a     Integer to count leading zero bits.\n *\n * \\return      The number of leading zero bits in \\p a, if \\p a != 0.\n *              If \\p a == 0, the result is undefined.\n */\nsize_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a);\n\n/** Return the minimum number of bits required to represent the value held\n * in the MPI.\n *\n * \\note This function returns 0 if all the limbs of \\p A are 0.\n *\n * \\param[in] A     The address of the MPI.\n * \\param A_limbs   The number of limbs of \\p A.\n *\n * \\return      The number of bits in \\p A.\n */\nsize_t mbedtls_mpi_core_bitlen(const mbedtls_mpi_uint *A, size_t A_limbs);\n\n/** Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint\n * into the storage form used by mbedtls_mpi.\n *\n * \\param[in,out] A     The address of the MPI.\n * \\param A_limbs       The number of limbs of \\p A.\n */\nvoid mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A,\n                                        size_t A_limbs);\n\n/** \\brief         Compare a machine integer with an MPI.\n *\n *                 This function operates in constant time with respect\n *                 to the values of \\p min and \\p A.\n *\n * \\param min      A machine integer.\n * \\param[in] A    An MPI.\n * \\param A_limbs  The number of limbs of \\p A.\n *                 This must be at least 1.\n *\n * \\return         MBEDTLS_CT_TRUE if \\p min is less than or equal to \\p A, otherwise MBEDTLS_CT_FALSE.\n */\nmbedtls_ct_condition_t mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,\n                                                    const mbedtls_mpi_uint *A,\n                                                    size_t A_limbs);\n\n/**\n * \\brief          Check if one unsigned MPI is less than another in constant\n *                 time.\n *\n * \\param A        The left-hand MPI. This must point to an array of limbs\n *                 with the same allocated length as \\p B.\n * \\param B        The right-hand MPI. This must point to an array of limbs\n *                 with the same allocated length as \\p A.\n * \\param limbs    The number of limbs in \\p A and \\p B.\n *                 This must not be 0.\n *\n * \\return         MBEDTLS_CT_TRUE  if \\p A is less than \\p B.\n *                 MBEDTLS_CT_FALSE if \\p A is greater than or equal to \\p B.\n */\nmbedtls_ct_condition_t mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,\n                                              const mbedtls_mpi_uint *B,\n                                              size_t limbs);\n\n/**\n * \\brief   Perform a safe conditional copy of an MPI which doesn't reveal\n *          whether assignment was done or not.\n *\n * \\param[out] X        The address of the destination MPI.\n *                      This must be initialized. Must have enough limbs to\n *                      store the full value of \\p A.\n * \\param[in]  A        The address of the source MPI. This must be initialized.\n * \\param      limbs    The number of limbs of \\p A.\n * \\param      assign   The condition deciding whether to perform the\n *                      assignment or not. Callers will need to use\n *                      the constant time interface (e.g. `mbedtls_ct_bool()`)\n *                      to construct this argument.\n *\n * \\note           This function avoids leaking any information about whether\n *                 the assignment was done or not.\n */\nvoid mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X,\n                                  const mbedtls_mpi_uint *A,\n                                  size_t limbs,\n                                  mbedtls_ct_condition_t assign);\n\n/**\n * \\brief   Perform a safe conditional swap of two MPIs which doesn't reveal\n *          whether the swap was done or not.\n *\n * \\param[in,out] X         The address of the first MPI.\n *                          This must be initialized.\n * \\param[in,out] Y         The address of the second MPI.\n *                          This must be initialized.\n * \\param         limbs     The number of limbs of \\p X and \\p Y.\n * \\param         swap      The condition deciding whether to perform\n *                          the swap or not.\n *\n * \\note           This function avoids leaking any information about whether\n *                 the swap was done or not.\n */\nvoid mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X,\n                                mbedtls_mpi_uint *Y,\n                                size_t limbs,\n                                mbedtls_ct_condition_t swap);\n\n/** Import X from unsigned binary data, little-endian.\n *\n * The MPI needs to have enough limbs to store the full value (including any\n * most significant zero bytes in the input).\n *\n * \\param[out] X         The address of the MPI.\n * \\param X_limbs        The number of limbs of \\p X.\n * \\param[in] input      The input buffer to import from.\n * \\param input_length   The length bytes of \\p input.\n *\n * \\return       \\c 0 if successful.\n * \\return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \\p X isn't\n *               large enough to hold the value in \\p input.\n */\nint mbedtls_mpi_core_read_le(mbedtls_mpi_uint *X,\n                             size_t X_limbs,\n                             const unsigned char *input,\n                             size_t input_length);\n\n/** Import X from unsigned binary data, big-endian.\n *\n * The MPI needs to have enough limbs to store the full value (including any\n * most significant zero bytes in the input).\n *\n * \\param[out] X        The address of the MPI.\n *                      May only be #NULL if \\p X_limbs is 0 and \\p input_length\n *                      is 0.\n * \\param X_limbs       The number of limbs of \\p X.\n * \\param[in] input     The input buffer to import from.\n *                      May only be #NULL if \\p input_length is 0.\n * \\param input_length  The length in bytes of \\p input.\n *\n * \\return       \\c 0 if successful.\n * \\return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \\p X isn't\n *               large enough to hold the value in \\p input.\n */\nint mbedtls_mpi_core_read_be(mbedtls_mpi_uint *X,\n                             size_t X_limbs,\n                             const unsigned char *input,\n                             size_t input_length);\n\n/** Export A into unsigned binary data, little-endian.\n *\n * \\note If \\p output is shorter than \\p A the export is still successful if the\n *       value held in \\p A fits in the buffer (that is, if enough of the most\n *       significant bytes of \\p A are 0).\n *\n * \\param[in] A         The address of the MPI.\n * \\param A_limbs       The number of limbs of \\p A.\n * \\param[out] output   The output buffer to export to.\n * \\param output_length The length in bytes of \\p output.\n *\n * \\return       \\c 0 if successful.\n * \\return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \\p output isn't\n *               large enough to hold the value of \\p A.\n */\nint mbedtls_mpi_core_write_le(const mbedtls_mpi_uint *A,\n                              size_t A_limbs,\n                              unsigned char *output,\n                              size_t output_length);\n\n/** Export A into unsigned binary data, big-endian.\n *\n * \\note If \\p output is shorter than \\p A the export is still successful if the\n *       value held in \\p A fits in the buffer (that is, if enough of the most\n *       significant bytes of \\p A are 0).\n *\n * \\param[in] A         The address of the MPI.\n * \\param A_limbs       The number of limbs of \\p A.\n * \\param[out] output   The output buffer to export to.\n * \\param output_length The length in bytes of \\p output.\n *\n * \\return       \\c 0 if successful.\n * \\return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \\p output isn't\n *               large enough to hold the value of \\p A.\n */\nint mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *A,\n                              size_t A_limbs,\n                              unsigned char *output,\n                              size_t output_length);\n\n/** \\brief              Shift an MPI in-place right by a number of bits.\n *\n *                      Shifting by more bits than there are bit positions\n *                      in \\p X is valid and results in setting \\p X to 0.\n *\n *                      This function's execution time depends on the value\n *                      of \\p count (and of course \\p limbs).\n *\n * \\param[in,out] X     The number to shift.\n * \\param limbs         The number of limbs of \\p X. This must be at least 1.\n * \\param count         The number of bits to shift by.\n */\nvoid mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs,\n                              size_t count);\n\n/**\n * \\brief               Shift an MPI in-place left by a number of bits.\n *\n *                      Shifting by more bits than there are bit positions\n *                      in \\p X will produce an unspecified result.\n *\n *                      This function's execution time depends on the value\n *                      of \\p count (and of course \\p limbs).\n * \\param[in,out] X     The number to shift.\n * \\param limbs         The number of limbs of \\p X. This must be at least 1.\n * \\param count         The number of bits to shift by.\n */\nvoid mbedtls_mpi_core_shift_l(mbedtls_mpi_uint *X, size_t limbs,\n                              size_t count);\n\n/**\n * \\brief Add two fixed-size large unsigned integers, returning the carry.\n *\n * Calculates `A + B` where `A` and `B` have the same size.\n *\n * This function operates modulo `2^(biL*limbs)` and returns the carry\n * (1 if there was a wraparound, and 0 otherwise).\n *\n * \\p X may be aliased to \\p A or \\p B.\n *\n * \\param[out] X    The result of the addition.\n * \\param[in] A     Little-endian presentation of the left operand.\n * \\param[in] B     Little-endian presentation of the right operand.\n * \\param limbs     Number of limbs of \\p X, \\p A and \\p B.\n *\n * \\return          1 if `A + B >= 2^(biL*limbs)`, 0 otherwise.\n */\nmbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X,\n                                      const mbedtls_mpi_uint *A,\n                                      const mbedtls_mpi_uint *B,\n                                      size_t limbs);\n\n/**\n * \\brief Conditional addition of two fixed-size large unsigned integers,\n *        returning the carry.\n *\n * Functionally equivalent to\n *\n * ```\n * if( cond )\n *    X += A;\n * return carry;\n * ```\n *\n * This function operates modulo `2^(biL*limbs)`.\n *\n * \\param[in,out] X  The pointer to the (little-endian) array\n *                   representing the bignum to accumulate onto.\n * \\param[in] A      The pointer to the (little-endian) array\n *                   representing the bignum to conditionally add\n *                   to \\p X. This may be aliased to \\p X but may not\n *                   overlap otherwise.\n * \\param limbs      Number of limbs of \\p X and \\p A.\n * \\param cond       Condition bit dictating whether addition should\n *                   happen or not. This must be \\c 0 or \\c 1.\n *\n * \\warning          If \\p cond is neither 0 nor 1, the result of this function\n *                   is unspecified, and the resulting value in \\p X might be\n *                   neither its original value nor \\p X + \\p A.\n *\n * \\return           1 if `X + cond * A >= 2^(biL*limbs)`, 0 otherwise.\n */\nmbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X,\n                                         const mbedtls_mpi_uint *A,\n                                         size_t limbs,\n                                         unsigned cond);\n\n/**\n * \\brief Subtract two fixed-size large unsigned integers, returning the borrow.\n *\n * Calculate `A - B` where \\p A and \\p B have the same size.\n * This function operates modulo `2^(biL*limbs)` and returns the carry\n * (1 if there was a wraparound, i.e. if `A < B`, and 0 otherwise).\n *\n * \\p X may be aliased to \\p A or \\p B, or even both, but may not overlap\n * either otherwise.\n *\n * \\param[out] X    The result of the subtraction.\n * \\param[in] A     Little-endian presentation of left operand.\n * \\param[in] B     Little-endian presentation of right operand.\n * \\param limbs     Number of limbs of \\p X, \\p A and \\p B.\n *\n * \\return          1 if `A < B`.\n *                  0 if `A >= B`.\n */\nmbedtls_mpi_uint mbedtls_mpi_core_sub(mbedtls_mpi_uint *X,\n                                      const mbedtls_mpi_uint *A,\n                                      const mbedtls_mpi_uint *B,\n                                      size_t limbs);\n\n/**\n * \\brief Perform a fixed-size multiply accumulate operation: X += b * A\n *\n * \\p X may be aliased to \\p A (when \\p X_limbs == \\p A_limbs), but may not\n * otherwise overlap.\n *\n * This function operates modulo `2^(biL*X_limbs)`.\n *\n * \\param[in,out] X  The pointer to the (little-endian) array\n *                   representing the bignum to accumulate onto.\n * \\param X_limbs    The number of limbs of \\p X. This must be\n *                   at least \\p A_limbs.\n * \\param[in] A      The pointer to the (little-endian) array\n *                   representing the bignum to multiply with.\n *                   This may be aliased to \\p X but may not overlap\n *                   otherwise.\n * \\param A_limbs    The number of limbs of \\p A.\n * \\param b          X scalar to multiply with.\n *\n * \\return           The carry at the end of the operation.\n */\nmbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *X, size_t X_limbs,\n                                      const mbedtls_mpi_uint *A, size_t A_limbs,\n                                      mbedtls_mpi_uint b);\n\n/**\n * \\brief Perform a known-size multiplication\n *\n * \\p X may not be aliased to any of the inputs for this function.\n * \\p A may be aliased to \\p B.\n *\n * \\param[out] X     The pointer to the (little-endian) array to receive\n *                   the product of \\p A_limbs and \\p B_limbs.\n *                   This must be of length \\p A_limbs + \\p B_limbs.\n * \\param[in] A      The pointer to the (little-endian) array\n *                   representing the first factor.\n * \\param A_limbs    The number of limbs in \\p A.\n * \\param[in] B      The pointer to the (little-endian) array\n *                   representing the second factor.\n * \\param B_limbs    The number of limbs in \\p B.\n */\nvoid mbedtls_mpi_core_mul(mbedtls_mpi_uint *X,\n                          const mbedtls_mpi_uint *A, size_t A_limbs,\n                          const mbedtls_mpi_uint *B, size_t B_limbs);\n\n/**\n * \\brief Calculate initialisation value for fast Montgomery modular\n *        multiplication\n *\n * \\param[in] N  Little-endian presentation of the modulus. This must have\n *               at least one limb.\n *\n * \\return       The initialisation value for fast Montgomery modular multiplication\n */\nmbedtls_mpi_uint mbedtls_mpi_core_montmul_init(const mbedtls_mpi_uint *N);\n\n/**\n * \\brief Montgomery multiplication: X = A * B * R^-1 mod N (HAC 14.36)\n *\n * \\p A and \\p B must be in canonical form. That is, < \\p N.\n *\n * \\p X may be aliased to \\p A or \\p N, or even \\p B (if \\p AN_limbs ==\n * \\p B_limbs) but may not overlap any parameters otherwise.\n *\n * \\p A and \\p B may alias each other, if \\p AN_limbs == \\p B_limbs. They may\n * not alias \\p N (since they must be in canonical form, they cannot == \\p N).\n *\n * \\param[out]    X         The destination MPI, as a little-endian array of\n *                          length \\p AN_limbs.\n *                          On successful completion, X contains the result of\n *                          the multiplication `A * B * R^-1` mod N where\n *                          `R = 2^(biL*AN_limbs)`.\n * \\param[in]     A         Little-endian presentation of first operand.\n *                          Must have the same number of limbs as \\p N.\n * \\param[in]     B         Little-endian presentation of second operand.\n * \\param[in]     B_limbs   The number of limbs in \\p B.\n *                          Must be <= \\p AN_limbs.\n * \\param[in]     N         Little-endian presentation of the modulus.\n *                          This must be odd, and have exactly the same number\n *                          of limbs as \\p A.\n *                          It may alias \\p X, but must not alias or otherwise\n *                          overlap any of the other parameters.\n * \\param[in]     AN_limbs  The number of limbs in \\p X, \\p A and \\p N.\n * \\param         mm        The Montgomery constant for \\p N: -N^-1 mod 2^biL.\n *                          This can be calculated by `mbedtls_mpi_core_montmul_init()`.\n * \\param[in,out] T         Temporary storage of size at least 2*AN_limbs+1 limbs.\n *                          Its initial content is unused and\n *                          its final content is indeterminate.\n *                          It must not alias or otherwise overlap any of the\n *                          other parameters.\n */\nvoid mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X,\n                              const mbedtls_mpi_uint *A,\n                              const mbedtls_mpi_uint *B, size_t B_limbs,\n                              const mbedtls_mpi_uint *N, size_t AN_limbs,\n                              mbedtls_mpi_uint mm, mbedtls_mpi_uint *T);\n\n/**\n * \\brief Calculate the square of the Montgomery constant. (Needed\n *        for conversion and operations in Montgomery form.)\n *\n * \\param[out] X  A pointer to the result of the calculation of\n *                the square of the Montgomery constant:\n *                2^{2*n*biL} mod N.\n * \\param[in]  N  Little-endian presentation of the modulus, which must be odd.\n *\n * \\return        0 if successful.\n * \\return        #MBEDTLS_ERR_MPI_ALLOC_FAILED if there is not enough space\n *                to store the value of Montgomery constant squared.\n * \\return        #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \\p N modulus is zero.\n * \\return        #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \\p N modulus is negative.\n */\nint mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X,\n                                        const mbedtls_mpi *N);\n\n#if defined(MBEDTLS_TEST_HOOKS)\n/**\n * Copy an MPI from a table without leaking the index.\n *\n * \\param dest              The destination buffer. This must point to a writable\n *                          buffer of at least \\p limbs limbs.\n * \\param table             The address of the table. This must point to a readable\n *                          array of \\p count elements of \\p limbs limbs each.\n * \\param limbs             The number of limbs in each table entry.\n * \\param count             The number of entries in \\p table.\n * \\param index             The (secret) table index to look up. This must be in the\n *                          range `0 .. count-1`.\n */\nvoid mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest,\n                                           const mbedtls_mpi_uint *table,\n                                           size_t limbs,\n                                           size_t count,\n                                           size_t index);\n#endif /* MBEDTLS_TEST_HOOKS */\n\n/**\n * \\brief          Fill an integer with a number of random bytes.\n *\n * \\param X        The destination MPI.\n * \\param X_limbs  The number of limbs of \\p X.\n * \\param bytes    The number of random bytes to generate.\n * \\param f_rng    The RNG function to use. This must not be \\c NULL.\n * \\param p_rng    The RNG parameter to be passed to \\p f_rng. This may be\n *                 \\c NULL if \\p f_rng doesn't need a context argument.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \\p X does not have\n *                 enough room for \\p bytes bytes.\n * \\return         A negative error code on RNG failure.\n *\n * \\note           The bytes obtained from the RNG are interpreted\n *                 as a big-endian representation of an MPI; this can\n *                 be relevant in applications like deterministic ECDSA.\n */\nint mbedtls_mpi_core_fill_random(mbedtls_mpi_uint *X, size_t X_limbs,\n                                 size_t bytes,\n                                 int (*f_rng)(void *, unsigned char *, size_t),\n                                 void *p_rng);\n\n/** Generate a random number uniformly in a range.\n *\n * This function generates a random number between \\p min inclusive and\n * \\p N exclusive.\n *\n * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)\n * when the RNG is a suitably parametrized instance of HMAC_DRBG\n * and \\p min is \\c 1.\n *\n * \\note           There are `N - min` possible outputs. The lower bound\n *                 \\p min can be reached, but the upper bound \\p N cannot.\n *\n * \\param X        The destination MPI, with \\p limbs limbs.\n *                 It must not be aliased with \\p N or otherwise overlap it.\n * \\param min      The minimum value to return.\n * \\param N        The upper bound of the range, exclusive, with \\p limbs limbs.\n *                 In other words, this is one plus the maximum value to return.\n *                 \\p N must be strictly larger than \\p min.\n * \\param limbs    The number of limbs of \\p N and \\p X.\n *                 This must not be 0.\n * \\param f_rng    The RNG function to use. This must not be \\c NULL.\n * \\param p_rng    The RNG parameter to be passed to \\p f_rng.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was\n *                 unable to find a suitable value within a limited number\n *                 of attempts. This has a negligible probability if \\p N\n *                 is significantly larger than \\p min, which is the case\n *                 for all usual cryptographic applications.\n */\nint mbedtls_mpi_core_random(mbedtls_mpi_uint *X,\n                            mbedtls_mpi_uint min,\n                            const mbedtls_mpi_uint *N,\n                            size_t limbs,\n                            int (*f_rng)(void *, unsigned char *, size_t),\n                            void *p_rng);\n\n/**\n * \\brief          Returns the number of limbs of working memory required for\n *                 a call to `mbedtls_mpi_core_exp_mod()`.\n *\n * \\note           This will always be at least\n *                 `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`,\n *                 i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`.\n *\n * \\param AN_limbs The number of limbs in the input `A` and the modulus `N`\n *                 (they must be the same size) that will be given to\n *                 `mbedtls_mpi_core_exp_mod()`.\n * \\param E_limbs  The number of limbs in the exponent `E` that will be given\n *                 to `mbedtls_mpi_core_exp_mod()`.\n *\n * \\return         The number of limbs of working memory required by\n *                 `mbedtls_mpi_core_exp_mod()`.\n */\nsize_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs);\n\n/**\n * \\brief            Perform a modular exponentiation with public or secret exponent:\n *                   X = A^E mod N, where \\p A is already in Montgomery form.\n *\n * \\warning          This function is not constant time with respect to \\p E (the exponent).\n *\n * \\p X may be aliased to \\p A, but not to \\p RR or \\p E, even if \\p E_limbs ==\n * \\p AN_limbs.\n *\n * \\param[out] X     The destination MPI, as a little endian array of length\n *                   \\p AN_limbs.\n * \\param[in] A      The base MPI, as a little endian array of length \\p AN_limbs.\n *                   Must be in Montgomery form.\n * \\param[in] N      The modulus, as a little endian array of length \\p AN_limbs.\n * \\param AN_limbs   The number of limbs in \\p X, \\p A, \\p N, \\p RR.\n * \\param[in] E      The exponent, as a little endian array of length \\p E_limbs.\n * \\param E_limbs    The number of limbs in \\p E.\n * \\param[in] RR     The precomputed residue of 2^{2*biL} modulo N, as a little\n *                   endian array of length \\p AN_limbs.\n * \\param[in,out] T  Temporary storage of at least the number of limbs returned\n *                   by `mbedtls_mpi_core_exp_mod_working_limbs()`.\n *                   Its initial content is unused and its final content is\n *                   indeterminate.\n *                   It must not alias or otherwise overlap any of the other\n *                   parameters.\n *                   It is up to the caller to zeroize \\p T when it is no\n *                   longer needed, and before freeing it if it was dynamically\n *                   allocated.\n */\nvoid mbedtls_mpi_core_exp_mod_unsafe(mbedtls_mpi_uint *X,\n                                     const mbedtls_mpi_uint *A,\n                                     const mbedtls_mpi_uint *N, size_t AN_limbs,\n                                     const mbedtls_mpi_uint *E, size_t E_limbs,\n                                     const mbedtls_mpi_uint *RR,\n                                     mbedtls_mpi_uint *T);\n\n/**\n * \\brief            Perform a modular exponentiation with secret exponent:\n *                   X = A^E mod N, where \\p A is already in Montgomery form.\n *\n * \\p X may be aliased to \\p A, but not to \\p RR or \\p E, even if \\p E_limbs ==\n * \\p AN_limbs.\n *\n * \\param[out] X     The destination MPI, as a little endian array of length\n *                   \\p AN_limbs.\n * \\param[in] A      The base MPI, as a little endian array of length \\p AN_limbs.\n *                   Must be in Montgomery form.\n * \\param[in] N      The modulus, as a little endian array of length \\p AN_limbs.\n * \\param AN_limbs   The number of limbs in \\p X, \\p A, \\p N, \\p RR.\n * \\param[in] E      The exponent, as a little endian array of length \\p E_limbs.\n * \\param E_limbs    The number of limbs in \\p E.\n * \\param[in] RR     The precomputed residue of 2^{2*biL} modulo N, as a little\n *                   endian array of length \\p AN_limbs.\n * \\param[in,out] T  Temporary storage of at least the number of limbs returned\n *                   by `mbedtls_mpi_core_exp_mod_working_limbs()`.\n *                   Its initial content is unused and its final content is\n *                   indeterminate.\n *                   It must not alias or otherwise overlap any of the other\n *                   parameters.\n *                   It is up to the caller to zeroize \\p T when it is no\n *                   longer needed, and before freeing it if it was dynamically\n *                   allocated.\n */\nvoid mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,\n                              const mbedtls_mpi_uint *A,\n                              const mbedtls_mpi_uint *N, size_t AN_limbs,\n                              const mbedtls_mpi_uint *E, size_t E_limbs,\n                              const mbedtls_mpi_uint *RR,\n                              mbedtls_mpi_uint *T);\n\n/**\n * \\brief Subtract unsigned integer from known-size large unsigned integers.\n *        Return the borrow.\n *\n * \\param[out] X    The result of the subtraction.\n * \\param[in] A     The left operand.\n * \\param b         The unsigned scalar to subtract.\n * \\param limbs     Number of limbs of \\p X and \\p A.\n *\n * \\return          1 if `A < b`.\n *                  0 if `A >= b`.\n */\nmbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X,\n                                          const mbedtls_mpi_uint *A,\n                                          mbedtls_mpi_uint b,\n                                          size_t limbs);\n\n/**\n * \\brief Determine if a given MPI has the value \\c 0 in constant time with\n *        respect to the value (but not with respect to the number of limbs).\n *\n * \\param[in] A   The MPI to test.\n * \\param limbs   Number of limbs in \\p A.\n *\n * \\return        MBEDTLS_CT_FALSE if `A == 0`\n *                MBEDTLS_CT_TRUE  if `A != 0`.\n */\nmbedtls_ct_condition_t mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,\n                                                      size_t limbs);\n\n/**\n * \\brief          Returns the number of limbs of working memory required for\n *                 a call to `mbedtls_mpi_core_montmul()`.\n *\n * \\param AN_limbs The number of limbs in the input `A` and the modulus `N`\n *                 (they must be the same size) that will be given to\n *                 `mbedtls_mpi_core_montmul()` or one of the other functions\n *                 that specifies this as the amount of working memory needed.\n *\n * \\return         The number of limbs of working memory required by\n *                 `mbedtls_mpi_core_montmul()` (or other similar function).\n */\nstatic inline size_t mbedtls_mpi_core_montmul_working_limbs(size_t AN_limbs)\n{\n    return 2 * AN_limbs + 1;\n}\n\n/** Convert an MPI into Montgomery form.\n *\n * \\p X may be aliased to \\p A, but may not otherwise overlap it.\n *\n * \\p X may not alias \\p N (it is in canonical form, so must be strictly less\n * than \\p N). Nor may it alias or overlap \\p rr (this is unlikely to be\n * required in practice.)\n *\n * This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is\n * an alternative to calling `mbedtls_mpi_mod_raw_to_mont_rep()` when we\n * don't want to allocate memory.\n *\n * \\param[out]    X         The result of the conversion.\n *                          Must have the same number of limbs as \\p A.\n * \\param[in]     A         The MPI to convert into Montgomery form.\n *                          Must have the same number of limbs as the modulus.\n * \\param[in]     N         The address of the modulus, which gives the size of\n *                          the base `R` = 2^(biL*N->limbs).\n * \\param[in]     AN_limbs  The number of limbs in \\p X, \\p A, \\p N and \\p rr.\n * \\param         mm        The Montgomery constant for \\p N: -N^-1 mod 2^biL.\n *                          This can be determined by calling\n *                          `mbedtls_mpi_core_montmul_init()`.\n * \\param[in]     rr        The residue for `2^{2*n*biL} mod N`.\n * \\param[in,out] T         Temporary storage of size at least\n *                          `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`\n *                          limbs.\n *                          Its initial content is unused and\n *                          its final content is indeterminate.\n *                          It must not alias or otherwise overlap any of the\n *                          other parameters.\n */\nvoid mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X,\n                                  const mbedtls_mpi_uint *A,\n                                  const mbedtls_mpi_uint *N,\n                                  size_t AN_limbs,\n                                  mbedtls_mpi_uint mm,\n                                  const mbedtls_mpi_uint *rr,\n                                  mbedtls_mpi_uint *T);\n\n/** Convert an MPI from Montgomery form.\n *\n * \\p X may be aliased to \\p A, but may not otherwise overlap it.\n *\n * \\p X may not alias \\p N (it is in canonical form, so must be strictly less\n * than \\p N).\n *\n * This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is\n * an alternative to calling `mbedtls_mpi_mod_raw_from_mont_rep()` when we\n * don't want to allocate memory.\n *\n * \\param[out]    X         The result of the conversion.\n *                          Must have the same number of limbs as \\p A.\n * \\param[in]     A         The MPI to convert from Montgomery form.\n *                          Must have the same number of limbs as the modulus.\n * \\param[in]     N         The address of the modulus, which gives the size of\n *                          the base `R` = 2^(biL*N->limbs).\n * \\param[in]     AN_limbs  The number of limbs in \\p X, \\p A and \\p N.\n * \\param         mm        The Montgomery constant for \\p N: -N^-1 mod 2^biL.\n *                          This can be determined by calling\n *                          `mbedtls_mpi_core_montmul_init()`.\n * \\param[in,out] T         Temporary storage of size at least\n *                          `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`\n *                          limbs.\n *                          Its initial content is unused and\n *                          its final content is indeterminate.\n *                          It must not alias or otherwise overlap any of the\n *                          other parameters.\n */\nvoid mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X,\n                                    const mbedtls_mpi_uint *A,\n                                    const mbedtls_mpi_uint *N,\n                                    size_t AN_limbs,\n                                    mbedtls_mpi_uint mm,\n                                    mbedtls_mpi_uint *T);\n\n/** Compute GCD(A, N) and optionally the inverse of A mod N if it exists.\n *\n * Requires N to be odd, 0 <= A <= N and A_limbs <= N_limbs.\n * When I != NULL, N (the modulus) must be greater than 1.\n *\n * A and N may not alias each other.\n * When I == NULL (computing only the GCD), G may alias A or N.\n * When I != NULL (computing the modular inverse), G or I may alias A\n * but none of them may alias N (the modulus).\n *\n * If any of the above preconditions is not met, output values are unspecified.\n *\n * \\param[out]    G       The GCD of \\p A and \\p N.\n *                        Must have the same number of limbs as \\p N.\n * \\param[out]    I       The inverse of \\p A modulo \\p N if it exists (that is,\n *                        if \\p G above is 1 on exit); indeterminate otherwise.\n *                        This must either be NULL (to only compute the GCD),\n *                        or have the same number of limbs as \\p N.\n * \\param[in]     A       The 1st operand of GCD and number to invert.\n *                        This value must be less than or equal to \\p N.\n * \\param         A_limbs The number of limbs of \\p A.\n *                        Must be less than or equal to \\p N_limbs.\n * \\param[in]     N       The 2nd operand of GCD and modulus for inversion.\n *                        This value must be odd.\n *                        If I != NULL this value must be greater than 1.\n * \\param         N_limbs The number of limbs of \\p N.\n * \\param[in,out] T       Temporary storage of size at least 5 * N_limbs limbs,\n *                        or 4 * N_limbs if \\p I is NULL (GCD only).\n *                        Its initial content is unused and\n *                        its final content is indeterminate.\n *                        It must not alias or otherwise overlap any of the\n *                        other parameters.\n */\nvoid mbedtls_mpi_core_gcd_modinv_odd(mbedtls_mpi_uint *G,\n                                     mbedtls_mpi_uint *I,\n                                     const mbedtls_mpi_uint *A,\n                                     size_t A_limbs,\n                                     const mbedtls_mpi_uint *N,\n                                     size_t N_limbs,\n                                     mbedtls_mpi_uint *T);\n\n#endif /* MBEDTLS_BIGNUM_CORE_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/bignum_core_invasive.h",
    "content": "/**\n * \\file bignum_core_invasive.h\n *\n * \\brief Function declarations for invasive functions of bignum core.\n */\n/**\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_BIGNUM_CORE_INVASIVE_H\n#define MBEDTLS_BIGNUM_CORE_INVASIVE_H\n\n#include \"bignum_core.h\"\n\n#if defined(MBEDTLS_TEST_HOOKS)\n\n#if !defined(MBEDTLS_THREADING_C)\n\nextern void (*mbedtls_safe_codepath_hook)(void);\nextern void (*mbedtls_unsafe_codepath_hook)(void);\n\n#endif /* !MBEDTLS_THREADING_C */\n\n/** Divide X by 2 mod N in place, assuming N is odd.\n *\n * \\param[in,out] X     The value to divide by 2 mod \\p N.\n * \\param[in]     N     The modulus. Must be odd.\n * \\param[in]     limbs The number of limbs in \\p X and \\p N.\n */\nMBEDTLS_STATIC_TESTABLE\nvoid mbedtls_mpi_core_div2_mod_odd(mbedtls_mpi_uint *X,\n                                   const mbedtls_mpi_uint *N,\n                                   size_t limbs);\n\n#endif /* MBEDTLS_TEST_HOOKS */\n\n#endif /* MBEDTLS_BIGNUM_CORE_INVASIVE_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/bignum_internal.h",
    "content": "/**\n * \\file bignum_internal.h\n *\n * \\brief Internal-only bignum public-key cryptosystem API.\n *\n * This file declares bignum-related functions that are to be used\n * only from within the Mbed TLS library itself.\n *\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_BIGNUM_INTERNAL_H\n#define MBEDTLS_BIGNUM_INTERNAL_H\n\n/**\n * \\brief          Perform a modular exponentiation: X = A^E mod N\n *\n * \\warning        This function is not constant time with respect to \\p E (the exponent).\n *\n * \\param X        The destination MPI. This must point to an initialized MPI.\n *                 This must not alias E or N.\n * \\param A        The base of the exponentiation.\n *                 This must point to an initialized MPI.\n * \\param E        The exponent MPI. This must point to an initialized MPI.\n * \\param N        The base for the modular reduction. This must point to an\n *                 initialized MPI.\n * \\param prec_RR  A helper MPI depending solely on \\p N which can be used to\n *                 speed-up multiple modular exponentiations for the same value\n *                 of \\p N. This may be \\c NULL. If it is not \\c NULL, it must\n *                 point to an initialized MPI. If it hasn't been used after\n *                 the call to mbedtls_mpi_init(), this function will compute\n *                 the helper value and store it in \\p prec_RR for reuse on\n *                 subsequent calls to this function. Otherwise, the function\n *                 will assume that \\p prec_RR holds the helper value set by a\n *                 previous call to mbedtls_mpi_exp_mod(), and reuse it.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \\c N is negative or\n *                 even, or if \\c E is negative.\n * \\return         Another negative error code on different kinds of failures.\n *\n */\nint mbedtls_mpi_exp_mod_unsafe(mbedtls_mpi *X, const mbedtls_mpi *A,\n                               const mbedtls_mpi *E, const mbedtls_mpi *N,\n                               mbedtls_mpi *prec_RR);\n\n/**\n * \\brief          A wrapper around a constant time function to compute\n *                 GCD(A, N) and/or A^-1 mod N if it exists.\n *\n * \\warning        Requires N to be odd, and 0 <= A <= N. Additionally, if\n *                 I != NULL, requires N > 1.\n *                 The wrapper part of this function is not constant time.\n *\n * \\note           A and N must not alias each other.\n *                 When I == NULL (computing only the GCD), G can alias A or N.\n *                 When I != NULL (computing the modular inverse), G or I can\n *                 alias A, but neither of them can alias N (the modulus).\n *\n * \\param[out] G   The GCD of \\p A and \\p N.\n *                 This may be NULL, to only compute I.\n * \\param[out] I   The inverse of \\p A modulo \\p N if it exists (that is,\n *                 if \\p G above is 1 on exit), in the range [1, \\p N);\n *                 indeterminate otherwise.\n *                 This may be NULL, to only compute G.\n * \\param[in] A    The 1st operand of GCD and number to invert.\n *                 This value must be less than or equal to \\p N.\n * \\param[in] N    The 2nd operand of GCD and modulus for inversion.\n *                 Must be odd or the results are indeterminate.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if preconditions were not\n *                 met.\n */\nint mbedtls_mpi_gcd_modinv_odd(mbedtls_mpi *G,\n                               mbedtls_mpi *I,\n                               const mbedtls_mpi *A,\n                               const mbedtls_mpi *N);\n\n/**\n * \\brief          Modular inverse: X = A^-1 mod N with N odd\n *\n * \\param[out] X   The inverse of \\p A modulo \\p N in the range [1, \\p N)\n *                 on success; indeterminate otherwise.\n * \\param[in] A    The number to invert.\n * \\param[in] N    The modulus. Must be odd and greater than 1.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if preconditions were not\n *                 met.\n * \\return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A is not invertible mod N.\n */\nint mbedtls_mpi_inv_mod_odd(mbedtls_mpi *X,\n                            const mbedtls_mpi *A,\n                            const mbedtls_mpi *N);\n\n/**\n * \\brief          Modular inverse: X = A^-1 mod N with N even,\n *                 A odd and 1 < A < N.\n *\n * \\param[out] X   The inverse of \\p A modulo \\p N in the range [1, \\p N)\n *                 on success; indeterminate otherwise.\n * \\param[in] A    The number to invert. Must be odd, greated than 1\n *                 and less than \\p N.\n * \\param[in] N    The modulus. Must be even and greater than 1.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if preconditions were not\n *                 met.\n * \\return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A is not invertible mod N.\n */\nint mbedtls_mpi_inv_mod_even_in_range(mbedtls_mpi *X,\n                                      mbedtls_mpi const *A,\n                                      mbedtls_mpi const *N);\n\n#endif /* bignum_internal.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/bignum_mod.c",
    "content": "/**\n *  Modular bignum functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT)\n\n#include <string.h>\n\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/bignum.h\"\n\n#include \"mbedtls/platform.h\"\n\n#include \"bignum_core.h\"\n#include \"bignum_mod.h\"\n#include \"bignum_mod_raw.h\"\n#include \"constant_time_internal.h\"\n\nint mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r,\n                                  const mbedtls_mpi_mod_modulus *N,\n                                  mbedtls_mpi_uint *p,\n                                  size_t p_limbs)\n{\n    if (p_limbs != N->limbs || !mbedtls_mpi_core_lt_ct(p, N->p, N->limbs)) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    r->limbs = N->limbs;\n    r->p = p;\n\n    return 0;\n}\n\nvoid mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r)\n{\n    if (r == NULL) {\n        return;\n    }\n\n    r->limbs = 0;\n    r->p = NULL;\n}\n\nvoid mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N)\n{\n    if (N == NULL) {\n        return;\n    }\n\n    N->p = NULL;\n    N->limbs = 0;\n    N->bits = 0;\n    N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;\n}\n\nvoid mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N)\n{\n    if (N == NULL) {\n        return;\n    }\n\n    switch (N->int_rep) {\n        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:\n            if (N->rep.mont.rr != NULL) {\n                mbedtls_zeroize_and_free((mbedtls_mpi_uint *) N->rep.mont.rr,\n                                         N->limbs * sizeof(mbedtls_mpi_uint));\n                N->rep.mont.rr = NULL;\n            }\n            N->rep.mont.mm = 0;\n            break;\n        case MBEDTLS_MPI_MOD_REP_OPT_RED:\n            N->rep.ored.modp = NULL;\n            break;\n        case MBEDTLS_MPI_MOD_REP_INVALID:\n            break;\n    }\n\n    N->p = NULL;\n    N->limbs = 0;\n    N->bits = 0;\n    N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;\n}\n\nstatic int set_mont_const_square(const mbedtls_mpi_uint **X,\n                                 const mbedtls_mpi_uint *A,\n                                 size_t limbs)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi N;\n    mbedtls_mpi RR;\n    *X = NULL;\n\n    mbedtls_mpi_init(&N);\n    mbedtls_mpi_init(&RR);\n\n    if (A == NULL || limbs == 0 || limbs >= (MBEDTLS_MPI_MAX_LIMBS / 2) - 2) {\n        goto cleanup;\n    }\n\n    if (mbedtls_mpi_grow(&N, limbs)) {\n        goto cleanup;\n    }\n\n    memcpy(N.p, A, sizeof(mbedtls_mpi_uint) * limbs);\n\n    ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N);\n\n    if (ret == 0) {\n        *X = RR.p;\n        RR.p = NULL;\n    }\n\ncleanup:\n    mbedtls_mpi_free(&N);\n    mbedtls_mpi_free(&RR);\n    ret = (ret != 0) ? MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED : 0;\n    return ret;\n}\n\nstatic inline void standard_modulus_setup(mbedtls_mpi_mod_modulus *N,\n                                          const mbedtls_mpi_uint *p,\n                                          size_t p_limbs,\n                                          mbedtls_mpi_mod_rep_selector int_rep)\n{\n    N->p = p;\n    N->limbs = p_limbs;\n    N->bits = mbedtls_mpi_core_bitlen(p, p_limbs);\n    N->int_rep = int_rep;\n}\n\nint mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,\n                                  const mbedtls_mpi_uint *p,\n                                  size_t p_limbs)\n{\n    int ret = 0;\n    standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_MONTGOMERY);\n    N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p);\n    ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs);\n\n    if (ret != 0) {\n        mbedtls_mpi_mod_modulus_free(N);\n    }\n\n    return ret;\n}\n\nint mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N,\n                                         const mbedtls_mpi_uint *p,\n                                         size_t p_limbs,\n                                         mbedtls_mpi_modp_fn modp)\n{\n    standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_OPT_RED);\n    N->rep.ored.modp = modp;\n    return 0;\n}\n\nint mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X,\n                        const mbedtls_mpi_mod_residue *A,\n                        const mbedtls_mpi_mod_residue *B,\n                        const mbedtls_mpi_mod_modulus *N)\n{\n    if (N->limbs == 0) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    mbedtls_mpi_uint *T = mbedtls_calloc(N->limbs * 2 + 1, ciL);\n    if (T == NULL) {\n        return MBEDTLS_ERR_MPI_ALLOC_FAILED;\n    }\n\n    mbedtls_mpi_mod_raw_mul(X->p, A->p, B->p, N, T);\n\n    mbedtls_free(T);\n\n    return 0;\n}\n\nint mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X,\n                        const mbedtls_mpi_mod_residue *A,\n                        const mbedtls_mpi_mod_residue *B,\n                        const mbedtls_mpi_mod_modulus *N)\n{\n    if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    mbedtls_mpi_mod_raw_sub(X->p, A->p, B->p, N);\n\n    return 0;\n}\n\nstatic int mbedtls_mpi_mod_inv_mont(mbedtls_mpi_mod_residue *X,\n                                    const mbedtls_mpi_mod_residue *A,\n                                    const mbedtls_mpi_mod_modulus *N,\n                                    mbedtls_mpi_uint *working_memory)\n{\n    /* Input already in Montgomery form, so there's little to do */\n    mbedtls_mpi_mod_raw_inv_prime(X->p, A->p,\n                                  N->p, N->limbs,\n                                  N->rep.mont.rr,\n                                  working_memory);\n    return 0;\n}\n\nstatic int mbedtls_mpi_mod_inv_non_mont(mbedtls_mpi_mod_residue *X,\n                                        const mbedtls_mpi_mod_residue *A,\n                                        const mbedtls_mpi_mod_modulus *N,\n                                        mbedtls_mpi_uint *working_memory)\n{\n    /* Need to convert input into Montgomery form */\n\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_mpi_mod_modulus Nmont;\n    mbedtls_mpi_mod_modulus_init(&Nmont);\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs));\n\n    /* We'll use X->p to hold the Montgomery form of the input A->p */\n    mbedtls_mpi_core_to_mont_rep(X->p, A->p, Nmont.p, Nmont.limbs,\n                                 Nmont.rep.mont.mm, Nmont.rep.mont.rr,\n                                 working_memory);\n\n    mbedtls_mpi_mod_raw_inv_prime(X->p, X->p,\n                                  Nmont.p, Nmont.limbs,\n                                  Nmont.rep.mont.rr,\n                                  working_memory);\n\n    /* And convert back from Montgomery form */\n\n    mbedtls_mpi_core_from_mont_rep(X->p, X->p, Nmont.p, Nmont.limbs,\n                                   Nmont.rep.mont.mm, working_memory);\n\ncleanup:\n    mbedtls_mpi_mod_modulus_free(&Nmont);\n    return ret;\n}\n\nint mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X,\n                        const mbedtls_mpi_mod_residue *A,\n                        const mbedtls_mpi_mod_modulus *N)\n{\n    if (X->limbs != N->limbs || A->limbs != N->limbs) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    /* Zero has the same value regardless of Montgomery form or not */\n    if (mbedtls_mpi_core_check_zero_ct(A->p, A->limbs) == 0) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    size_t working_limbs =\n        mbedtls_mpi_mod_raw_inv_prime_working_limbs(N->limbs);\n\n    mbedtls_mpi_uint *working_memory = mbedtls_calloc(working_limbs,\n                                                      sizeof(mbedtls_mpi_uint));\n    if (working_memory == NULL) {\n        return MBEDTLS_ERR_MPI_ALLOC_FAILED;\n    }\n\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    switch (N->int_rep) {\n        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:\n            ret = mbedtls_mpi_mod_inv_mont(X, A, N, working_memory);\n            break;\n        case MBEDTLS_MPI_MOD_REP_OPT_RED:\n            ret = mbedtls_mpi_mod_inv_non_mont(X, A, N, working_memory);\n            break;\n        default:\n            ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n            break;\n    }\n\n    mbedtls_zeroize_and_free(working_memory,\n                             working_limbs * sizeof(mbedtls_mpi_uint));\n\n    return ret;\n}\n\nint mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X,\n                        const mbedtls_mpi_mod_residue *A,\n                        const mbedtls_mpi_mod_residue *B,\n                        const mbedtls_mpi_mod_modulus *N)\n{\n    if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    mbedtls_mpi_mod_raw_add(X->p, A->p, B->p, N);\n\n    return 0;\n}\n\nint mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X,\n                           mbedtls_mpi_uint min,\n                           const mbedtls_mpi_mod_modulus *N,\n                           int (*f_rng)(void *, unsigned char *, size_t),\n                           void *p_rng)\n{\n    if (X->limbs != N->limbs) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n    return mbedtls_mpi_mod_raw_random(X->p, min, N, f_rng, p_rng);\n}\n\nint mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r,\n                         const mbedtls_mpi_mod_modulus *N,\n                         const unsigned char *buf,\n                         size_t buflen,\n                         mbedtls_mpi_mod_ext_rep ext_rep)\n{\n    int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n\n    /* Do our best to check if r and m have been set up */\n    if (r->limbs == 0 || N->limbs == 0) {\n        goto cleanup;\n    }\n    if (r->limbs != N->limbs) {\n        goto cleanup;\n    }\n\n    ret = mbedtls_mpi_mod_raw_read(r->p, N, buf, buflen, ext_rep);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    r->limbs = N->limbs;\n\n    ret = mbedtls_mpi_mod_raw_canonical_to_modulus_rep(r->p, N);\n\ncleanup:\n    return ret;\n}\n\nint mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r,\n                          const mbedtls_mpi_mod_modulus *N,\n                          unsigned char *buf,\n                          size_t buflen,\n                          mbedtls_mpi_mod_ext_rep ext_rep)\n{\n    /* Do our best to check if r and m have been set up */\n    if (r->limbs == 0 || N->limbs == 0) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n    if (r->limbs != N->limbs) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi_uint *working_memory = r->p;\n    size_t working_memory_len = sizeof(mbedtls_mpi_uint) * r->limbs;\n\n    if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {\n\n        working_memory = mbedtls_calloc(r->limbs, sizeof(mbedtls_mpi_uint));\n\n        if (working_memory == NULL) {\n            ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;\n            goto cleanup;\n        }\n\n        memcpy(working_memory, r->p, working_memory_len);\n\n        ret = mbedtls_mpi_mod_raw_from_mont_rep(working_memory, N);\n        if (ret != 0) {\n            goto cleanup;\n        }\n    }\n\n    ret = mbedtls_mpi_mod_raw_write(working_memory, N, buf, buflen, ext_rep);\n\ncleanup:\n\n    if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY &&\n        working_memory != NULL) {\n\n        mbedtls_zeroize_and_free(working_memory, working_memory_len);\n    }\n\n    return ret;\n}\n\n#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/bignum_mod.h",
    "content": "/**\n *  Modular bignum functions\n *\n * This module implements operations on integers modulo some fixed modulus.\n *\n * The functions in this module obey the following conventions unless\n * explicitly indicated otherwise:\n *\n * - **Modulus parameters**: the modulus is passed as a pointer to a structure\n *   of type #mbedtls_mpi_mod_modulus. The structure must be set up with an\n *   array of limbs storing the bignum value of the modulus. The modulus must\n *   be odd and is assumed to have no leading zeroes. The modulus is usually\n *   named \\c N and is usually input-only. Functions which take a parameter\n *   of type \\c const #mbedtls_mpi_mod_modulus* must not modify its value.\n * - **Bignum parameters**: Bignums are passed as pointers to an array of\n *   limbs or to a #mbedtls_mpi_mod_residue structure. A limb has the type\n *   #mbedtls_mpi_uint. Residues must be initialized before use, and must be\n *   associated with the modulus \\c N. Unless otherwise specified:\n *     - Bignum parameters called \\c A, \\c B, ... are inputs and are not\n *       modified by the function. Functions which take a parameter of\n *       type \\c const #mbedtls_mpi_mod_residue* must not modify its value.\n *     - Bignum parameters called \\c X, \\c Y, ... are outputs or input-output.\n *       The initial bignum value of output-only parameters is ignored, but\n *       they must be set up and associated with the modulus \\c N. Some\n *       functions (typically constant-flow) require that the limbs in an\n *       output residue are initialized.\n *     - Bignum parameters called \\c p are inputs used to set up a modulus or\n *       residue. These must be pointers to an array of limbs.\n *     - \\c T is a temporary storage area. The initial content of such a\n *       parameter is ignored and the final content is unspecified.\n *     - Some functions use different names, such as \\c r for the residue.\n * - **Bignum sizes**: bignum sizes are always expressed in limbs. Both\n *   #mbedtls_mpi_mod_modulus and #mbedtls_mpi_mod_residue have a \\c limbs\n *   member storing its size. All bignum parameters must have the same\n *   number of limbs as the modulus. All bignum sizes must be at least 1 and\n *   must be significantly less than #SIZE_MAX. The behavior if a size is 0 is\n *   undefined.\n * - **Bignum representation**: the representation of inputs and outputs is\n *   specified by the \\c int_rep field of the modulus.\n * - **Parameter ordering**: for bignum parameters, outputs come before inputs.\n *   The modulus is passed after residues. Temporaries come last.\n * - **Aliasing**: in general, output bignums may be aliased to one or more\n *   inputs. Modulus values may not be aliased to any other parameter. Outputs\n *   may not be aliased to one another. Temporaries may not be aliased to any\n *   other parameter.\n * - **Overlap**: apart from aliasing of residue pointers (where two residue\n *   arguments are equal pointers), overlap is not supported and may result\n *   in undefined behavior.\n * - **Error handling**: functions generally check compatibility of input\n *   sizes. Most functions will not check that input values are in canonical\n *   form (i.e. that \\c A < \\c N), this is only checked during setup of a\n *   residue structure.\n * - **Modular representatives**: all functions expect inputs to be in the\n *   range [0, \\c N - 1] and guarantee outputs in the range [0, \\c N - 1].\n *   Residues are set up with an associated modulus, and operations are only\n *   guaranteed to work if the modulus is associated with all residue\n *   parameters. If a residue is passed with a modulus other than the one it\n *   is associated with, then it may be out of range. If an input is out of\n *   range, outputs are fully unspecified, though bignum values out of range\n *   should not cause buffer overflows (beware that this is not extensively\n *   tested).\n */\n\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_BIGNUM_MOD_H\n#define MBEDTLS_BIGNUM_MOD_H\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_BIGNUM_C)\n#include \"mbedtls/bignum.h\"\n#endif\n\n/** How residues associated with a modulus are represented.\n *\n * This also determines which fields of the modulus structure are valid and\n * what their contents are (see #mbedtls_mpi_mod_modulus).\n */\ntypedef enum {\n    /** Representation not chosen (makes the modulus structure invalid). */\n    MBEDTLS_MPI_MOD_REP_INVALID    = 0,\n    /* Skip 1 as it is slightly easier to accidentally pass to functions. */\n    /** Montgomery representation. */\n    MBEDTLS_MPI_MOD_REP_MONTGOMERY = 2,\n    /* Optimised reduction available. This indicates a coordinate modulus (P)\n     * and one or more of the following have been configured:\n     * - A nist curve (MBEDTLS_ECP_DP_SECPXXXR1_ENABLED) & MBEDTLS_ECP_NIST_OPTIM.\n     * - A Kobliz Curve.\n     * - A Fast Reduction Curve CURVE25519 or CURVE448. */\n    MBEDTLS_MPI_MOD_REP_OPT_RED,\n} mbedtls_mpi_mod_rep_selector;\n\n/* Make mbedtls_mpi_mod_rep_selector and mbedtls_mpi_mod_ext_rep disjoint to\n * make it easier to catch when they are accidentally swapped. */\ntypedef enum {\n    MBEDTLS_MPI_MOD_EXT_REP_INVALID = 0,\n    MBEDTLS_MPI_MOD_EXT_REP_LE      = 8,\n    MBEDTLS_MPI_MOD_EXT_REP_BE\n} mbedtls_mpi_mod_ext_rep;\n\ntypedef struct {\n    mbedtls_mpi_uint *p;\n    size_t limbs;\n} mbedtls_mpi_mod_residue;\n\ntypedef struct {\n    mbedtls_mpi_uint const *rr;  /* The residue for 2^{2*n*biL} mod N */\n    mbedtls_mpi_uint mm;         /* Montgomery const for -N^{-1} mod 2^{ciL} */\n} mbedtls_mpi_mont_struct;\n\ntypedef int (*mbedtls_mpi_modp_fn)(mbedtls_mpi_uint *X, size_t X_limbs);\n\ntypedef struct {\n    mbedtls_mpi_modp_fn modp;    /* The optimised reduction function pointer */\n} mbedtls_mpi_opt_red_struct;\n\ntypedef struct {\n    const mbedtls_mpi_uint *p;\n    size_t limbs;                            // number of limbs\n    size_t bits;                             // bitlen of p\n    mbedtls_mpi_mod_rep_selector int_rep;    // selector to signal the active member of the union\n    union rep {\n        /* if int_rep == #MBEDTLS_MPI_MOD_REP_MONTGOMERY */\n        mbedtls_mpi_mont_struct mont;\n        /* if int_rep == #MBEDTLS_MPI_MOD_REP_OPT_RED */\n        mbedtls_mpi_opt_red_struct ored;\n    } rep;\n} mbedtls_mpi_mod_modulus;\n\n/** Setup a residue structure.\n *\n * The residue will be set up with the buffer \\p p and modulus \\p N.\n *\n * The memory pointed to by \\p p will be used by the resulting residue structure.\n * The value at the pointed-to memory will be the initial value of \\p r and must\n * hold a value that is less than the modulus. This value will be used as-is\n * and interpreted according to the value of the `N->int_rep` field.\n *\n * The modulus \\p N will be the modulus associated with \\p r. The residue \\p r\n * should only be used in operations where the modulus is \\p N.\n *\n * \\param[out] r    The address of the residue to setup.\n * \\param[in] N     The address of the modulus related to \\p r.\n * \\param[in] p     The address of the limb array containing the value of \\p r.\n *                  The memory pointed to by \\p p will be used by \\p r and must\n *                  not be modified in any way until after\n *                  mbedtls_mpi_mod_residue_release() is called. The data\n *                  pointed to by \\p p must be less than the modulus (the value\n *                  pointed to by `N->p`) and already in the representation\n *                  indicated by `N->int_rep`.\n * \\param p_limbs   The number of limbs of \\p p. Must be the same as the number\n *                  of limbs in the modulus \\p N.\n *\n * \\return      \\c 0 if successful.\n * \\return      #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \\p p_limbs is less than the\n *              limbs in \\p N or if \\p p is not less than \\p N.\n */\nint mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r,\n                                  const mbedtls_mpi_mod_modulus *N,\n                                  mbedtls_mpi_uint *p,\n                                  size_t p_limbs);\n\n/** Unbind elements of a residue structure.\n *\n * This function removes the reference to the limb array that was passed to\n * mbedtls_mpi_mod_residue_setup() to make it safe to free or use again.\n *\n * This function invalidates \\p r and it must not be used until after\n * mbedtls_mpi_mod_residue_setup() is called on it again.\n *\n * \\param[out] r     The address of residue to release.\n */\nvoid mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r);\n\n/** Initialize a modulus structure.\n *\n * \\param[out] N     The address of the modulus structure to initialize.\n */\nvoid mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N);\n\n/** Setup a modulus structure.\n *\n * \\param[out] N    The address of the modulus structure to populate.\n * \\param[in] p     The address of the limb array storing the value of \\p N.\n *                  The memory pointed to by \\p p will be used by \\p N and must\n *                  not be modified in any way until after\n *                  mbedtls_mpi_mod_modulus_free() is called.\n * \\param p_limbs   The number of limbs of \\p p.\n *\n * \\return      \\c 0 if successful.\n */\nint mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,\n                                  const mbedtls_mpi_uint *p,\n                                  size_t p_limbs);\n\n/** Setup an optimised-reduction compatible modulus structure.\n *\n * \\param[out] N    The address of the modulus structure to populate.\n * \\param[in] p     The address of the limb array storing the value of \\p N.\n *                  The memory pointed to by \\p p will be used by \\p N and must\n *                  not be modified in any way until after\n *                  mbedtls_mpi_mod_modulus_free() is called.\n * \\param p_limbs   The number of limbs of \\p p.\n * \\param modp      A pointer to the optimised reduction function to use. \\p p.\n *\n * \\return      \\c 0 if successful.\n */\nint mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N,\n                                         const mbedtls_mpi_uint *p,\n                                         size_t p_limbs,\n                                         mbedtls_mpi_modp_fn modp);\n\n/** Free elements of a modulus structure.\n *\n * This function frees any memory allocated by mbedtls_mpi_mod_modulus_setup().\n *\n * \\warning This function does not free the limb array passed to\n *          mbedtls_mpi_mod_modulus_setup() only removes the reference to it,\n *          making it safe to free or to use it again.\n *\n * \\param[in,out] N     The address of the modulus structure to free.\n */\nvoid mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N);\n\n/** \\brief  Multiply two residues, returning the residue modulo the specified\n *          modulus.\n *\n * \\note Currently handles the case when `N->int_rep` is\n * MBEDTLS_MPI_MOD_REP_MONTGOMERY.\n *\n * The size of the operation is determined by \\p N. \\p A, \\p B and \\p X must\n * all be associated with the modulus \\p N and must all have the same number\n * of limbs as \\p N.\n *\n * \\p X may be aliased to \\p A or \\p B, or even both, but may not overlap\n * either otherwise. They may not alias \\p N (since they must be in canonical\n * form, they cannot == \\p N).\n *\n * \\param[out] X        The address of the result MPI. Must have the same\n *                      number of limbs as \\p N.\n *                      On successful completion, \\p X contains the result of\n *                      the multiplication `A * B * R^-1` mod N where\n *                      `R = 2^(biL * N->limbs)`.\n * \\param[in]  A        The address of the first MPI.\n * \\param[in]  B        The address of the second MPI.\n * \\param[in]  N        The address of the modulus. Used to perform a modulo\n *                      operation on the result of the multiplication.\n *\n * \\return      \\c 0 if successful.\n * \\return      #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if all the parameters do not\n *              have the same number of limbs or \\p N is invalid.\n * \\return      #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.\n */\nint mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X,\n                        const mbedtls_mpi_mod_residue *A,\n                        const mbedtls_mpi_mod_residue *B,\n                        const mbedtls_mpi_mod_modulus *N);\n\n/**\n * \\brief Perform a fixed-size modular subtraction.\n *\n * Calculate `A - B modulo N`.\n *\n * \\p A, \\p B and \\p X must all have the same number of limbs as \\p N.\n *\n * \\p X may be aliased to \\p A or \\p B, or even both, but may not overlap\n * either otherwise.\n *\n * \\note This function does not check that \\p A or \\p B are in canonical\n *       form (that is, are < \\p N) - that will have been done by\n *       mbedtls_mpi_mod_residue_setup().\n *\n * \\param[out] X    The address of the result MPI. Must be initialized.\n *                  Must have the same number of limbs as the modulus \\p N.\n * \\param[in]  A    The address of the first MPI.\n * \\param[in]  B    The address of the second MPI.\n * \\param[in]  N    The address of the modulus. Used to perform a modulo\n *                  operation on the result of the subtraction.\n *\n * \\return          \\c 0 if successful.\n * \\return          #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not\n *                  have the correct number of limbs.\n */\nint mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X,\n                        const mbedtls_mpi_mod_residue *A,\n                        const mbedtls_mpi_mod_residue *B,\n                        const mbedtls_mpi_mod_modulus *N);\n\n/**\n * \\brief Perform modular inversion of an MPI with respect to a modulus \\p N.\n *\n * \\p A and \\p X must be associated with the modulus \\p N and will therefore\n * have the same number of limbs as \\p N.\n *\n * \\p X may be aliased to \\p A.\n *\n * \\warning  Currently only supports prime moduli, but does not check for them.\n *\n * \\param[out] X   The modular inverse of \\p A with respect to \\p N.\n * \\param[in] A    The number to calculate the modular inverse of.\n *                 Must not be 0.\n * \\param[in] N    The modulus to use.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \\p A and \\p N do not\n *                 have the same number of limbs.\n * \\return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \\p A is zero.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough\n *                 memory (needed for conversion to and from Mongtomery form\n *                 when not in Montgomery form already, and for temporary use\n *                 by the inversion calculation itself).\n */\n\nint mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X,\n                        const mbedtls_mpi_mod_residue *A,\n                        const mbedtls_mpi_mod_modulus *N);\n/**\n * \\brief Perform a fixed-size modular addition.\n *\n * Calculate `A + B modulo N`.\n *\n * \\p A, \\p B and \\p X must all be associated with the modulus \\p N and must\n * all have the same number of limbs as \\p N.\n *\n * \\p X may be aliased to \\p A or \\p B, or even both, but may not overlap\n * either otherwise.\n *\n * \\note This function does not check that \\p A or \\p B are in canonical\n *       form (that is, are < \\p N) - that will have been done by\n *       mbedtls_mpi_mod_residue_setup().\n *\n * \\param[out] X    The address of the result residue. Must be initialized.\n *                  Must have the same number of limbs as the modulus \\p N.\n * \\param[in]  A    The address of the first input residue.\n * \\param[in]  B    The address of the second input residue.\n * \\param[in]  N    The address of the modulus. Used to perform a modulo\n *                  operation on the result of the addition.\n *\n * \\return          \\c 0 if successful.\n * \\return          #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not\n *                  have the correct number of limbs.\n */\nint mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X,\n                        const mbedtls_mpi_mod_residue *A,\n                        const mbedtls_mpi_mod_residue *B,\n                        const mbedtls_mpi_mod_modulus *N);\n\n/** Generate a random number uniformly in a range.\n *\n * This function generates a random number between \\p min inclusive and\n * \\p N exclusive.\n *\n * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)\n * when the RNG is a suitably parametrized instance of HMAC_DRBG\n * and \\p min is \\c 1.\n *\n * \\note           There are `N - min` possible outputs. The lower bound\n *                 \\p min can be reached, but the upper bound \\p N cannot.\n *\n * \\param X        The destination residue.\n * \\param min      The minimum value to return. It must be strictly smaller\n *                 than \\b N.\n * \\param N        The modulus.\n *                 This is the upper bound of the output range, exclusive.\n * \\param f_rng    The RNG function to use. This must not be \\c NULL.\n * \\param p_rng    The RNG parameter to be passed to \\p f_rng.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was\n *                 unable to find a suitable value within a limited number\n *                 of attempts. This has a negligible probability if \\p N\n *                 is significantly larger than \\p min, which is the case\n *                 for all usual cryptographic applications.\n */\nint mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X,\n                           mbedtls_mpi_uint min,\n                           const mbedtls_mpi_mod_modulus *N,\n                           int (*f_rng)(void *, unsigned char *, size_t),\n                           void *p_rng);\n\n/** Read a residue from a byte buffer.\n *\n * The residue will be automatically converted to the internal representation\n * based on the value of the `N->int_rep` field.\n *\n * The modulus \\p N will be the modulus associated with \\p r. The residue \\p r\n * should only be used in operations where the modulus is \\p N or a modulus\n * equivalent to \\p N (in the sense that all their fields or memory pointed by\n * their fields hold the same value).\n *\n * \\param[out] r    The address of the residue. It must have exactly the same\n *                  number of limbs as the modulus \\p N.\n * \\param[in] N     The address of the modulus.\n * \\param[in] buf   The input buffer to import from.\n * \\param buflen    The length in bytes of \\p buf.\n * \\param ext_rep   The endianness of the number in the input buffer.\n *\n * \\return       \\c 0 if successful.\n * \\return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \\p r isn't\n *               large enough to hold the value in \\p buf.\n * \\return       #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \\p ext_rep\n *               is invalid or the value in the buffer is not less than \\p N.\n */\nint mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r,\n                         const mbedtls_mpi_mod_modulus *N,\n                         const unsigned char *buf,\n                         size_t buflen,\n                         mbedtls_mpi_mod_ext_rep ext_rep);\n\n/** Write a residue into a byte buffer.\n *\n * The modulus \\p N must be the modulus associated with \\p r (see\n * mbedtls_mpi_mod_residue_setup() and mbedtls_mpi_mod_read()).\n *\n * The residue will be automatically converted from the internal representation\n * based on the value of `N->int_rep` field.\n *\n * \\warning     If the buffer is smaller than `N->bits`, the number of\n *              leading zeroes is leaked through timing. If \\p r is\n *              secret, the caller must ensure that \\p buflen is at least\n *              (`N->bits`+7)/8.\n *\n * \\param[in] r     The address of the residue. It must have the same number of\n *                  limbs as the modulus \\p N. (\\p r is an input parameter, but\n *                  its value will be modified during execution and restored\n *                  before the function returns.)\n * \\param[in] N     The address of the modulus associated with \\p r.\n * \\param[out] buf  The output buffer to export to.\n * \\param buflen    The length in bytes of \\p buf.\n * \\param ext_rep   The endianness in which the number should be written into\n *                  the output buffer.\n *\n * \\return       \\c 0 if successful.\n * \\return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \\p buf isn't\n *               large enough to hold the value of \\p r (without leading\n *               zeroes).\n * \\return       #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \\p ext_rep is invalid.\n * \\return       #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough\n *               memory for conversion. Can occur only for moduli with\n *               MBEDTLS_MPI_MOD_REP_MONTGOMERY.\n */\nint mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r,\n                          const mbedtls_mpi_mod_modulus *N,\n                          unsigned char *buf,\n                          size_t buflen,\n                          mbedtls_mpi_mod_ext_rep ext_rep);\n\n#endif /* MBEDTLS_BIGNUM_MOD_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/bignum_mod_raw.c",
    "content": "/*\n *  Low-level modular bignum functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT)\n\n#include <string.h>\n\n#include \"mbedtls/error.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include \"mbedtls/platform.h\"\n\n#include \"bignum_core.h\"\n#include \"bignum_mod_raw.h\"\n#include \"bignum_mod.h\"\n#include \"constant_time_internal.h\"\n\n#include \"bignum_mod_raw_invasive.h\"\n\nvoid mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X,\n                                     const mbedtls_mpi_uint *A,\n                                     const mbedtls_mpi_mod_modulus *N,\n                                     unsigned char assign)\n{\n    mbedtls_mpi_core_cond_assign(X, A, N->limbs, mbedtls_ct_bool(assign));\n}\n\nvoid mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,\n                                   mbedtls_mpi_uint *Y,\n                                   const mbedtls_mpi_mod_modulus *N,\n                                   unsigned char swap)\n{\n    mbedtls_mpi_core_cond_swap(X, Y, N->limbs, mbedtls_ct_bool(swap));\n}\n\nint mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X,\n                             const mbedtls_mpi_mod_modulus *N,\n                             const unsigned char *input,\n                             size_t input_length,\n                             mbedtls_mpi_mod_ext_rep ext_rep)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    switch (ext_rep) {\n        case MBEDTLS_MPI_MOD_EXT_REP_LE:\n            ret = mbedtls_mpi_core_read_le(X, N->limbs,\n                                           input, input_length);\n            break;\n        case MBEDTLS_MPI_MOD_EXT_REP_BE:\n            ret = mbedtls_mpi_core_read_be(X, N->limbs,\n                                           input, input_length);\n            break;\n        default:\n            return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    if (!mbedtls_mpi_core_lt_ct(X, N->p, N->limbs)) {\n        ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n\ncleanup:\n\n    return ret;\n}\n\nint mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A,\n                              const mbedtls_mpi_mod_modulus *N,\n                              unsigned char *output,\n                              size_t output_length,\n                              mbedtls_mpi_mod_ext_rep ext_rep)\n{\n    switch (ext_rep) {\n        case MBEDTLS_MPI_MOD_EXT_REP_LE:\n            return mbedtls_mpi_core_write_le(A, N->limbs,\n                                             output, output_length);\n        case MBEDTLS_MPI_MOD_EXT_REP_BE:\n            return mbedtls_mpi_core_write_be(A, N->limbs,\n                                             output, output_length);\n        default:\n            return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n}\n\nvoid mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X,\n                             const mbedtls_mpi_uint *A,\n                             const mbedtls_mpi_uint *B,\n                             const mbedtls_mpi_mod_modulus *N)\n{\n    mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, A, B, N->limbs);\n\n    (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);\n}\n\nMBEDTLS_STATIC_TESTABLE\nvoid mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,\n                                             const mbedtls_mpi_mod_modulus *N)\n{\n    mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);\n\n    (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);\n}\n\n\nvoid mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,\n                             const mbedtls_mpi_uint *A,\n                             const mbedtls_mpi_uint *B,\n                             const mbedtls_mpi_mod_modulus *N,\n                             mbedtls_mpi_uint *T)\n{\n    /* Standard (A * B) multiplication stored into pre-allocated T\n     * buffer of fixed limb size of (2N + 1).\n     *\n     * The space may not not fully filled by when\n     * MBEDTLS_MPI_MOD_REP_OPT_RED is used. */\n    const size_t T_limbs = BITS_TO_LIMBS(N->bits) * 2;\n    switch (N->int_rep) {\n        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:\n            mbedtls_mpi_core_montmul(X, A, B, N->limbs, N->p, N->limbs,\n                                     N->rep.mont.mm, T);\n            break;\n        case MBEDTLS_MPI_MOD_REP_OPT_RED:\n            mbedtls_mpi_core_mul(T, A, N->limbs, B, N->limbs);\n\n            /* Optimised Reduction */\n            (*N->rep.ored.modp)(T, T_limbs);\n\n            /* Convert back to canonical representation */\n            mbedtls_mpi_mod_raw_fix_quasi_reduction(T, N);\n            memcpy(X, T, N->limbs * sizeof(mbedtls_mpi_uint));\n            break;\n        default:\n            break;\n    }\n\n}\n\nsize_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs)\n{\n    /* mbedtls_mpi_mod_raw_inv_prime() needs a temporary for the exponent,\n     * which will be the same size as the modulus and input (AN_limbs),\n     * and additional space to pass to mbedtls_mpi_core_exp_mod(). */\n    return AN_limbs +\n           mbedtls_mpi_core_exp_mod_working_limbs(AN_limbs, AN_limbs);\n}\n\nvoid mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X,\n                                   const mbedtls_mpi_uint *A,\n                                   const mbedtls_mpi_uint *N,\n                                   size_t AN_limbs,\n                                   const mbedtls_mpi_uint *RR,\n                                   mbedtls_mpi_uint *T)\n{\n    /* Inversion by power: g^|G| = 1 => g^(-1) = g^(|G|-1), and\n     *                       |G| = N - 1, so we want\n     *                 g^(|G|-1) = g^(N - 2)\n     */\n\n    /* Use the first AN_limbs of T to hold N - 2 */\n    mbedtls_mpi_uint *Nminus2 = T;\n    (void) mbedtls_mpi_core_sub_int(Nminus2, N, 2, AN_limbs);\n\n    /* Rest of T is given to exp_mod for its working space */\n    mbedtls_mpi_core_exp_mod(X,\n                             A, N, AN_limbs, Nminus2, AN_limbs,\n                             RR, T + AN_limbs);\n}\n\nvoid mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X,\n                             const mbedtls_mpi_uint *A,\n                             const mbedtls_mpi_uint *B,\n                             const mbedtls_mpi_mod_modulus *N)\n{\n    mbedtls_mpi_uint carry, borrow;\n    carry  = mbedtls_mpi_core_add(X, A, B, N->limbs);\n    borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);\n    (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) (carry ^ borrow));\n}\n\nint mbedtls_mpi_mod_raw_canonical_to_modulus_rep(\n    mbedtls_mpi_uint *X,\n    const mbedtls_mpi_mod_modulus *N)\n{\n    switch (N->int_rep) {\n        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:\n            return mbedtls_mpi_mod_raw_to_mont_rep(X, N);\n        case MBEDTLS_MPI_MOD_REP_OPT_RED:\n            return 0;\n        default:\n            return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n}\n\nint mbedtls_mpi_mod_raw_modulus_to_canonical_rep(\n    mbedtls_mpi_uint *X,\n    const mbedtls_mpi_mod_modulus *N)\n{\n    switch (N->int_rep) {\n        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:\n            return mbedtls_mpi_mod_raw_from_mont_rep(X, N);\n        case MBEDTLS_MPI_MOD_REP_OPT_RED:\n            return 0;\n        default:\n            return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n}\n\nint mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X,\n                               mbedtls_mpi_uint min,\n                               const mbedtls_mpi_mod_modulus *N,\n                               int (*f_rng)(void *, unsigned char *, size_t),\n                               void *p_rng)\n{\n    int ret = mbedtls_mpi_core_random(X, min, N->p, N->limbs, f_rng, p_rng);\n    if (ret != 0) {\n        return ret;\n    }\n    return mbedtls_mpi_mod_raw_canonical_to_modulus_rep(X, N);\n}\n\nint mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X,\n                                    const mbedtls_mpi_mod_modulus *N)\n{\n    mbedtls_mpi_uint *T;\n    const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs);\n\n    if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) {\n        return MBEDTLS_ERR_MPI_ALLOC_FAILED;\n    }\n\n    mbedtls_mpi_core_to_mont_rep(X, X, N->p, N->limbs,\n                                 N->rep.mont.mm, N->rep.mont.rr, T);\n\n    mbedtls_zeroize_and_free(T, t_limbs * ciL);\n    return 0;\n}\n\nint mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X,\n                                      const mbedtls_mpi_mod_modulus *N)\n{\n    const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs);\n    mbedtls_mpi_uint *T;\n\n    if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) {\n        return MBEDTLS_ERR_MPI_ALLOC_FAILED;\n    }\n\n    mbedtls_mpi_core_from_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, T);\n\n    mbedtls_zeroize_and_free(T, t_limbs * ciL);\n    return 0;\n}\n\nvoid mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X,\n                             const mbedtls_mpi_uint *A,\n                             const mbedtls_mpi_mod_modulus *N)\n{\n    mbedtls_mpi_core_sub(X, N->p, A, N->limbs);\n\n    /* If A=0 initially, then X=N now. Detect this by\n     * subtracting N and catching the carry. */\n    mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);\n    (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) borrow);\n}\n\n#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/bignum_mod_raw.h",
    "content": "/**\n *  Low-level modular bignum functions\n *\n *  This interface should only be used by the higher-level modular bignum\n *  module (bignum_mod.c) and the ECP module (ecp.c, ecp_curves.c). All other\n *  modules should use the high-level modular bignum interface (bignum_mod.h)\n *  or the legacy bignum interface (bignum.h).\n *\n * This is a low-level interface to operations on integers modulo which\n * has no protection against passing invalid arguments such as arrays of\n * the wrong size. The functions in bignum_mod.h provide a higher-level\n * interface that includes protections against accidental misuse, at the\n * expense of code size and sometimes more cumbersome memory management.\n *\n * The functions in this module obey the following conventions unless\n * explicitly indicated otherwise:\n * - **Modulus parameters**: the modulus is passed as a pointer to a structure\n *   of type #mbedtls_mpi_mod_modulus. The structure must be set up with an\n *   array of limbs storing the bignum value of the modulus. The modulus must\n *   be odd and is assumed to have no leading zeroes. The modulus is usually\n *   named \\c N and is usually input-only.\n * - **Bignum parameters**: Bignums are passed as pointers to an array of\n *   limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified:\n *     - Bignum parameters called \\c A, \\c B, ... are inputs, and are not\n *       modified by the function.\n *     - Bignum parameters called \\c X, \\c Y are outputs or input-output.\n *       The initial content of output-only parameters is ignored.\n *     - \\c T is a temporary storage area. The initial content of such a\n *       parameter is ignored and the final content is unspecified.\n * - **Bignum sizes**: bignum sizes are usually expressed by the \\c limbs\n *   member of the modulus argument. All bignum parameters must have the same\n *   number of limbs as the modulus. All bignum sizes must be at least 1 and\n *   must be significantly less than #SIZE_MAX. The behavior if a size is 0 is\n *   undefined.\n * - **Bignum representation**: the representation of inputs and outputs is\n *   specified by the \\c int_rep field of the modulus for arithmetic\n *   functions. Utility functions may allow for different representation.\n * - **Parameter ordering**: for bignum parameters, outputs come before inputs.\n *   The modulus is passed after other bignum input parameters. Temporaries\n *   come last.\n * - **Aliasing**: in general, output bignums may be aliased to one or more\n *   inputs. Modulus values may not be aliased to any other parameter. Outputs\n *   may not be aliased to one another. Temporaries may not be aliased to any\n *   other parameter.\n * - **Overlap**: apart from aliasing of limb array pointers (where two\n *   arguments are equal pointers), overlap is not supported and may result\n *   in undefined behavior.\n * - **Error handling**: This is a low-level module. Functions generally do not\n *   try to protect against invalid arguments such as nonsensical sizes or\n *   null pointers. Note that passing bignums with a different size than the\n *   modulus may lead to buffer overflows. Some functions which allocate\n *   memory or handle reading/writing of bignums will return an error if\n *   memory allocation fails or if buffer sizes are invalid.\n * - **Modular representatives**: all functions expect inputs to be in the\n *   range [0, \\c N - 1] and guarantee outputs in the range [0, \\c N - 1]. If\n *   an input is out of range, outputs are fully unspecified, though bignum\n *   values out of range should not cause buffer overflows (beware that this is\n *   not extensively tested).\n */\n\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_BIGNUM_MOD_RAW_H\n#define MBEDTLS_BIGNUM_MOD_RAW_H\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_BIGNUM_C)\n#include \"mbedtls/bignum.h\"\n#endif\n\n#include \"bignum_mod.h\"\n\n/**\n * \\brief   Perform a safe conditional copy of an MPI which doesn't reveal\n *          whether the assignment was done or not.\n *\n * The size to copy is determined by \\p N.\n *\n * \\param[out] X        The address of the destination MPI.\n *                      This must be initialized. Must have enough limbs to\n *                      store the full value of \\p A.\n * \\param[in]  A        The address of the source MPI. This must be initialized.\n * \\param[in]  N        The address of the modulus related to \\p X and \\p A.\n * \\param      assign   The condition deciding whether to perform the\n *                      assignment or not. Must be either 0 or 1:\n *                      * \\c 1: Perform the assignment `X = A`.\n *                      * \\c 0: Keep the original value of \\p X.\n *\n * \\note           This function avoids leaking any information about whether\n *                 the assignment was done or not.\n *\n * \\warning        If \\p assign is neither 0 nor 1, the result of this function\n *                 is indeterminate, and the resulting value in \\p X might be\n *                 neither its original value nor the value in \\p A.\n */\nvoid mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X,\n                                     const mbedtls_mpi_uint *A,\n                                     const mbedtls_mpi_mod_modulus *N,\n                                     unsigned char assign);\n\n/**\n * \\brief   Perform a safe conditional swap of two MPIs which doesn't reveal\n *          whether the swap was done or not.\n *\n * The size to swap is determined by \\p N.\n *\n * \\param[in,out] X     The address of the first MPI. This must be initialized.\n * \\param[in,out] Y     The address of the second MPI. This must be initialized.\n * \\param[in]     N     The address of the modulus related to \\p X and \\p Y.\n * \\param         swap  The condition deciding whether to perform\n *                      the swap or not. Must be either 0 or 1:\n *                      * \\c 1: Swap the values of \\p X and \\p Y.\n *                      * \\c 0: Keep the original values of \\p X and \\p Y.\n *\n * \\note           This function avoids leaking any information about whether\n *                 the swap was done or not.\n *\n * \\warning        If \\p swap is neither 0 nor 1, the result of this function\n *                 is indeterminate, and both \\p X and \\p Y might end up with\n *                 values different to either of the original ones.\n */\nvoid mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,\n                                   mbedtls_mpi_uint *Y,\n                                   const mbedtls_mpi_mod_modulus *N,\n                                   unsigned char swap);\n\n/** Import X from unsigned binary data.\n *\n * The MPI needs to have enough limbs to store the full value (including any\n * most significant zero bytes in the input).\n *\n * \\param[out] X        The address of the MPI. The size is determined by \\p N.\n *                      (In particular, it must have at least as many limbs as\n *                      the modulus \\p N.)\n * \\param[in] N         The address of the modulus related to \\p X.\n * \\param[in] input     The input buffer to import from.\n * \\param input_length  The length in bytes of \\p input.\n * \\param ext_rep       The endianness of the number in the input buffer.\n *\n * \\return       \\c 0 if successful.\n * \\return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \\p X isn't\n *               large enough to hold the value in \\p input.\n * \\return       #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the external representation\n *               of \\p N is invalid or \\p X is not less than \\p N.\n */\nint mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X,\n                             const mbedtls_mpi_mod_modulus *N,\n                             const unsigned char *input,\n                             size_t input_length,\n                             mbedtls_mpi_mod_ext_rep ext_rep);\n\n/** Export A into unsigned binary data.\n *\n * \\param[in] A         The address of the MPI. The size is determined by \\p N.\n *                      (In particular, it must have at least as many limbs as\n *                      the modulus \\p N.)\n * \\param[in] N         The address of the modulus related to \\p A.\n * \\param[out] output   The output buffer to export to.\n * \\param output_length The length in bytes of \\p output.\n * \\param ext_rep       The endianness in which the number should be written into the output buffer.\n *\n * \\return       \\c 0 if successful.\n * \\return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \\p output isn't\n *               large enough to hold the value of \\p A.\n * \\return       #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the external representation\n *               of \\p N is invalid.\n */\nint mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A,\n                              const mbedtls_mpi_mod_modulus *N,\n                              unsigned char *output,\n                              size_t output_length,\n                              mbedtls_mpi_mod_ext_rep ext_rep);\n\n/** \\brief  Subtract two MPIs, returning the residue modulo the specified\n *          modulus.\n *\n * The size of the operation is determined by \\p N. \\p A and \\p B must have\n * the same number of limbs as \\p N.\n *\n * \\p X may be aliased to \\p A or \\p B, or even both, but may not overlap\n * either otherwise.\n *\n * \\param[out] X        The address of the result MPI.\n *                      This must be initialized. Must have enough limbs to\n *                      store the full value of the result.\n * \\param[in]  A        The address of the first MPI. This must be initialized.\n * \\param[in]  B        The address of the second MPI. This must be initialized.\n * \\param[in]  N        The address of the modulus. Used to perform a modulo\n *                      operation on the result of the subtraction.\n */\nvoid mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X,\n                             const mbedtls_mpi_uint *A,\n                             const mbedtls_mpi_uint *B,\n                             const mbedtls_mpi_mod_modulus *N);\n\n/** \\brief  Multiply two MPIs, returning the residue modulo the specified\n *          modulus.\n *\n * \\note Currently handles the case when `N->int_rep` is\n * MBEDTLS_MPI_MOD_REP_MONTGOMERY.\n *\n * The size of the operation is determined by \\p N. \\p A, \\p B and \\p X must\n * all be associated with the modulus \\p N and must all have the same number\n * of limbs as \\p N.\n *\n * \\p X may be aliased to \\p A or \\p B, or even both, but may not overlap\n * either otherwise. They may not alias \\p N (since they must be in canonical\n * form, they cannot == \\p N).\n *\n * \\param[out] X        The address of the result MPI. Must have the same\n *                      number of limbs as \\p N.\n *                      On successful completion, \\p X contains the result of\n *                      the multiplication `A * B * R^-1` mod N where\n *                      `R = 2^(biL * N->limbs)`.\n * \\param[in]  A        The address of the first MPI.\n * \\param[in]  B        The address of the second MPI.\n * \\param[in]  N        The address of the modulus. Used to perform a modulo\n *                      operation on the result of the multiplication.\n * \\param[in,out] T     Temporary storage of size at least 2 * N->limbs + 1\n *                      limbs. Its initial content is unused and\n *                      its final content is indeterminate.\n *                      It must not alias or otherwise overlap any of the\n *                      other parameters.\n */\nvoid mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,\n                             const mbedtls_mpi_uint *A,\n                             const mbedtls_mpi_uint *B,\n                             const mbedtls_mpi_mod_modulus *N,\n                             mbedtls_mpi_uint *T);\n\n/**\n * \\brief          Returns the number of limbs of working memory required for\n *                 a call to `mbedtls_mpi_mod_raw_inv_prime()`.\n *\n * \\note           This will always be at least\n *                 `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`,\n *                 i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`.\n *\n * \\param AN_limbs The number of limbs in the input `A` and the modulus `N`\n *                 (they must be the same size) that will be given to\n *                 `mbedtls_mpi_mod_raw_inv_prime()`.\n *\n * \\return         The number of limbs of working memory required by\n *                 `mbedtls_mpi_mod_raw_inv_prime()`.\n */\nsize_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs);\n\n/**\n * \\brief Perform fixed-width modular inversion of a Montgomery-form MPI with\n *        respect to a modulus \\p N that must be prime.\n *\n * \\p X may be aliased to \\p A, but not to \\p N or \\p RR.\n *\n * \\param[out] X     The modular inverse of \\p A with respect to \\p N.\n *                   Will be in Montgomery form.\n * \\param[in] A      The number to calculate the modular inverse of.\n *                   Must be in Montgomery form. Must not be 0.\n * \\param[in] N      The modulus, as a little-endian array of length \\p AN_limbs.\n *                   Must be prime.\n * \\param AN_limbs   The number of limbs in \\p A, \\p N and \\p RR.\n * \\param[in] RR     The precomputed residue of 2^{2*biL} modulo N, as a little-\n *                   endian array of length \\p AN_limbs.\n * \\param[in,out] T  Temporary storage of at least the number of limbs returned\n *                   by `mbedtls_mpi_mod_raw_inv_prime_working_limbs()`.\n *                   Its initial content is unused and its final content is\n *                   indeterminate.\n *                   It must not alias or otherwise overlap any of the other\n *                   parameters.\n *                   It is up to the caller to zeroize \\p T when it is no\n *                   longer needed, and before freeing it if it was dynamically\n *                   allocated.\n */\nvoid mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X,\n                                   const mbedtls_mpi_uint *A,\n                                   const mbedtls_mpi_uint *N,\n                                   size_t AN_limbs,\n                                   const mbedtls_mpi_uint *RR,\n                                   mbedtls_mpi_uint *T);\n\n/**\n * \\brief Perform a known-size modular addition.\n *\n * Calculate `A + B modulo N`.\n *\n * The number of limbs in each operand, and the result, is given by the\n * modulus \\p N.\n *\n * \\p X may be aliased to \\p A or \\p B, or even both, but may not overlap\n * either otherwise.\n *\n * \\param[out] X    The result of the modular addition.\n * \\param[in] A     Little-endian presentation of the left operand. This\n *                  must be smaller than \\p N.\n * \\param[in] B     Little-endian presentation of the right operand. This\n *                  must be smaller than \\p N.\n * \\param[in] N     The address of the modulus.\n */\nvoid mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X,\n                             const mbedtls_mpi_uint *A,\n                             const mbedtls_mpi_uint *B,\n                             const mbedtls_mpi_mod_modulus *N);\n\n/** Convert an MPI from canonical representation (little-endian limb array)\n * to the representation associated with the modulus.\n *\n * \\param[in,out] X The limb array to convert.\n *                  It must have as many limbs as \\p N.\n *                  It is converted in place.\n *                  If this function returns an error, the content of \\p X\n *                  is unspecified.\n * \\param[in] N     The modulus structure.\n *\n * \\return          \\c 0 if successful.\n *                  Otherwise an \\c MBEDTLS_ERR_MPI_xxx error code.\n */\nint mbedtls_mpi_mod_raw_canonical_to_modulus_rep(\n    mbedtls_mpi_uint *X,\n    const mbedtls_mpi_mod_modulus *N);\n\n/** Convert an MPI from the representation associated with the modulus\n * to canonical representation (little-endian limb array).\n *\n * \\param[in,out] X The limb array to convert.\n *                  It must have as many limbs as \\p N.\n *                  It is converted in place.\n *                  If this function returns an error, the content of \\p X\n *                  is unspecified.\n * \\param[in] N     The modulus structure.\n *\n * \\return          \\c 0 if successful.\n *                  Otherwise an \\c MBEDTLS_ERR_MPI_xxx error code.\n */\nint mbedtls_mpi_mod_raw_modulus_to_canonical_rep(\n    mbedtls_mpi_uint *X,\n    const mbedtls_mpi_mod_modulus *N);\n\n/** Generate a random number uniformly in a range.\n *\n * This function generates a random number between \\p min inclusive and\n * \\p N exclusive.\n *\n * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)\n * when the RNG is a suitably parametrized instance of HMAC_DRBG\n * and \\p min is \\c 1.\n *\n * \\note           There are `N - min` possible outputs. The lower bound\n *                 \\p min can be reached, but the upper bound \\p N cannot.\n *\n * \\param X        The destination MPI, in canonical representation modulo \\p N.\n *                 It must not be aliased with \\p N or otherwise overlap it.\n * \\param min      The minimum value to return. It must be strictly smaller\n *                 than \\b N.\n * \\param N        The modulus.\n *                 This is the upper bound of the output range, exclusive.\n * \\param f_rng    The RNG function to use. This must not be \\c NULL.\n * \\param p_rng    The RNG parameter to be passed to \\p f_rng.\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was\n *                 unable to find a suitable value within a limited number\n *                 of attempts. This has a negligible probability if \\p N\n *                 is significantly larger than \\p min, which is the case\n *                 for all usual cryptographic applications.\n */\nint mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X,\n                               mbedtls_mpi_uint min,\n                               const mbedtls_mpi_mod_modulus *N,\n                               int (*f_rng)(void *, unsigned char *, size_t),\n                               void *p_rng);\n\n/** Convert an MPI into Montgomery form.\n *\n * \\param X      The address of the MPI.\n *               Must have the same number of limbs as \\p N.\n * \\param N      The address of the modulus, which gives the size of\n *               the base `R` = 2^(biL*N->limbs).\n *\n * \\return       \\c 0 if successful.\n */\nint mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X,\n                                    const mbedtls_mpi_mod_modulus *N);\n\n/** Convert an MPI back from Montgomery representation.\n *\n * \\param X      The address of the MPI.\n *               Must have the same number of limbs as \\p N.\n * \\param N      The address of the modulus, which gives the size of\n *               the base `R`= 2^(biL*N->limbs).\n *\n * \\return       \\c 0 if successful.\n */\nint mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X,\n                                      const mbedtls_mpi_mod_modulus *N);\n\n/** \\brief  Perform fixed width modular negation.\n *\n * The size of the operation is determined by \\p N. \\p A must have\n * the same number of limbs as \\p N.\n *\n * \\p X may be aliased to \\p A.\n *\n * \\param[out] X        The result of the modular negation.\n *                      This must be initialized.\n * \\param[in] A         Little-endian presentation of the input operand. This\n *                      must be less than or equal to \\p N.\n * \\param[in] N         The modulus to use.\n */\nvoid mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X,\n                             const mbedtls_mpi_uint *A,\n                             const mbedtls_mpi_mod_modulus *N);\n\n#endif /* MBEDTLS_BIGNUM_MOD_RAW_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/bignum_mod_raw_invasive.h",
    "content": "/**\n * \\file bignum_mod_raw_invasive.h\n *\n * \\brief Function declarations for invasive functions of Low-level\n *        modular bignum.\n */\n/**\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H\n#define MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H\n\n#include \"common.h\"\n#include \"mbedtls/bignum.h\"\n#include \"bignum_mod.h\"\n\n#if defined(MBEDTLS_TEST_HOOKS)\n\n/** Convert the result of a quasi-reduction to its canonical representative.\n *\n * \\param[in,out] X     The address of the MPI to be converted. Must have the\n *                      same number of limbs as \\p N. The input value must\n *                      be in range 0 <= X < 2N.\n * \\param[in]     N     The address of the modulus.\n */\nMBEDTLS_STATIC_TESTABLE\nvoid mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,\n                                             const mbedtls_mpi_mod_modulus *N);\n\n#endif /* MBEDTLS_TEST_HOOKS */\n\n#endif /* MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/block_cipher.c",
    "content": "/**\n * \\file block_cipher.c\n *\n * \\brief Lightweight abstraction layer for block ciphers with 128 bit blocks,\n * for use by the GCM and CCM modules.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)\n#include \"psa/crypto.h\"\n#include \"psa_crypto_core.h\"\n#include \"psa_util_internal.h\"\n#endif\n\n#include \"block_cipher_internal.h\"\n\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n\n#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)\nstatic psa_key_type_t psa_key_type_from_block_cipher_id(mbedtls_block_cipher_id_t cipher_id)\n{\n    switch (cipher_id) {\n#if defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA)\n        case MBEDTLS_BLOCK_CIPHER_ID_AES:\n            return PSA_KEY_TYPE_AES;\n#endif\n#if defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA)\n        case MBEDTLS_BLOCK_CIPHER_ID_ARIA:\n            return PSA_KEY_TYPE_ARIA;\n#endif\n#if defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA)\n        case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:\n            return PSA_KEY_TYPE_CAMELLIA;\n#endif\n        default:\n            return PSA_KEY_TYPE_NONE;\n    }\n}\n\nstatic int mbedtls_cipher_error_from_psa(psa_status_t status)\n{\n    return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_cipher_errors,\n                                   psa_generic_status_to_mbedtls);\n}\n#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */\n\nvoid mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)\n    if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) {\n        psa_destroy_key(ctx->psa_key_id);\n        return;\n    }\n#endif\n    switch (ctx->id) {\n#if defined(MBEDTLS_AES_C)\n        case MBEDTLS_BLOCK_CIPHER_ID_AES:\n            mbedtls_aes_free(&ctx->ctx.aes);\n            break;\n#endif\n#if defined(MBEDTLS_ARIA_C)\n        case MBEDTLS_BLOCK_CIPHER_ID_ARIA:\n            mbedtls_aria_free(&ctx->ctx.aria);\n            break;\n#endif\n#if defined(MBEDTLS_CAMELLIA_C)\n        case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:\n            mbedtls_camellia_free(&ctx->ctx.camellia);\n            break;\n#endif\n        default:\n            break;\n    }\n    ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE;\n}\n\nint mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx,\n                               mbedtls_cipher_id_t cipher_id)\n{\n    ctx->id = (cipher_id == MBEDTLS_CIPHER_ID_AES) ? MBEDTLS_BLOCK_CIPHER_ID_AES :\n              (cipher_id == MBEDTLS_CIPHER_ID_ARIA) ? MBEDTLS_BLOCK_CIPHER_ID_ARIA :\n              (cipher_id == MBEDTLS_CIPHER_ID_CAMELLIA) ? MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA :\n              MBEDTLS_BLOCK_CIPHER_ID_NONE;\n\n#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)\n    psa_key_type_t psa_key_type = psa_key_type_from_block_cipher_id(ctx->id);\n    if (psa_key_type != PSA_KEY_TYPE_NONE &&\n        psa_can_do_cipher(psa_key_type, PSA_ALG_ECB_NO_PADDING)) {\n        ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_PSA;\n        return 0;\n    }\n    ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_LEGACY;\n#endif\n\n    switch (ctx->id) {\n#if defined(MBEDTLS_AES_C)\n        case MBEDTLS_BLOCK_CIPHER_ID_AES:\n            mbedtls_aes_init(&ctx->ctx.aes);\n            return 0;\n#endif\n#if defined(MBEDTLS_ARIA_C)\n        case MBEDTLS_BLOCK_CIPHER_ID_ARIA:\n            mbedtls_aria_init(&ctx->ctx.aria);\n            return 0;\n#endif\n#if defined(MBEDTLS_CAMELLIA_C)\n        case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:\n            mbedtls_camellia_init(&ctx->ctx.camellia);\n            return 0;\n#endif\n        default:\n            ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE;\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n}\n\nint mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx,\n                                const unsigned char *key,\n                                unsigned key_bitlen)\n{\n#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)\n    if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) {\n        psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;\n        psa_status_t status;\n\n        psa_set_key_type(&key_attr, psa_key_type_from_block_cipher_id(ctx->id));\n        psa_set_key_bits(&key_attr, key_bitlen);\n        psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);\n        psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT);\n\n        status = psa_import_key(&key_attr, key, PSA_BITS_TO_BYTES(key_bitlen), &ctx->psa_key_id);\n        if (status != PSA_SUCCESS) {\n            return mbedtls_cipher_error_from_psa(status);\n        }\n        psa_reset_key_attributes(&key_attr);\n\n        return 0;\n    }\n#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */\n\n    switch (ctx->id) {\n#if defined(MBEDTLS_AES_C)\n        case MBEDTLS_BLOCK_CIPHER_ID_AES:\n            return mbedtls_aes_setkey_enc(&ctx->ctx.aes, key, key_bitlen);\n#endif\n#if defined(MBEDTLS_ARIA_C)\n        case MBEDTLS_BLOCK_CIPHER_ID_ARIA:\n            return mbedtls_aria_setkey_enc(&ctx->ctx.aria, key, key_bitlen);\n#endif\n#if defined(MBEDTLS_CAMELLIA_C)\n        case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:\n            return mbedtls_camellia_setkey_enc(&ctx->ctx.camellia, key, key_bitlen);\n#endif\n        default:\n            return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;\n    }\n}\n\nint mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx,\n                                 const unsigned char input[16],\n                                 unsigned char output[16])\n{\n#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)\n    if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) {\n        psa_status_t status;\n        size_t olen;\n\n        status = psa_cipher_encrypt(ctx->psa_key_id, PSA_ALG_ECB_NO_PADDING,\n                                    input, 16, output, 16, &olen);\n        if (status != PSA_SUCCESS) {\n            return mbedtls_cipher_error_from_psa(status);\n        }\n        return 0;\n    }\n#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */\n\n    switch (ctx->id) {\n#if defined(MBEDTLS_AES_C)\n        case MBEDTLS_BLOCK_CIPHER_ID_AES:\n            return mbedtls_aes_crypt_ecb(&ctx->ctx.aes, MBEDTLS_AES_ENCRYPT,\n                                         input, output);\n#endif\n#if defined(MBEDTLS_ARIA_C)\n        case MBEDTLS_BLOCK_CIPHER_ID_ARIA:\n            return mbedtls_aria_crypt_ecb(&ctx->ctx.aria, input, output);\n#endif\n#if defined(MBEDTLS_CAMELLIA_C)\n        case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:\n            return mbedtls_camellia_crypt_ecb(&ctx->ctx.camellia,\n                                              MBEDTLS_CAMELLIA_ENCRYPT,\n                                              input, output);\n#endif\n        default:\n            return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;\n    }\n}\n\n#endif /* MBEDTLS_BLOCK_CIPHER_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/block_cipher_internal.h",
    "content": "/**\n * \\file block_cipher_internal.h\n *\n * \\brief Lightweight abstraction layer for block ciphers with 128 bit blocks,\n * for use by the GCM and CCM modules.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_BLOCK_CIPHER_INTERNAL_H\n#define MBEDTLS_BLOCK_CIPHER_INTERNAL_H\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/cipher.h\"\n\n#include \"mbedtls/block_cipher.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief           Initialize the context.\n *                  This must be the first API call before using the context.\n *\n * \\param ctx       The context to initialize.\n */\nstatic inline void mbedtls_block_cipher_init(mbedtls_block_cipher_context_t *ctx)\n{\n    memset(ctx, 0, sizeof(*ctx));\n}\n\n/**\n * \\brief           Set the block cipher to use with this context.\n *                  This must be called after mbedtls_block_cipher_init().\n *\n * \\param ctx       The context to set up.\n * \\param cipher_id The identifier of the cipher to use.\n *                  This must be either AES, ARIA or Camellia.\n *                  Warning: this is a ::mbedtls_cipher_id_t,\n *                  not a ::mbedtls_block_cipher_id_t!\n *\n * \\retval          \\c 0 on success.\n * \\retval          #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if \\p cipher_id was\n *                  invalid.\n */\nint mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx,\n                               mbedtls_cipher_id_t cipher_id);\n\n/**\n * \\brief           Set the key into the context.\n *\n * \\param ctx       The context to configure.\n * \\param key       The buffer holding the key material.\n * \\param key_bitlen    The size of the key in bits.\n *\n * \\retval          \\c 0 on success.\n * \\retval          #MBEDTLS_ERR_CIPHER_INVALID_CONTEXT if the context was not\n *                  properly set up before calling this function.\n * \\retval          One of #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH,\n *                  #MBEDTLS_ERR_ARIA_BAD_INPUT_DATA,\n *                  #MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA if \\p key_bitlen is\n *                  invalid.\n */\nint mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx,\n                                const unsigned char *key,\n                                unsigned key_bitlen);\n\n/**\n * \\brief           Encrypt one block (16 bytes) with the configured key.\n *\n * \\param ctx       The context holding the key.\n * \\param input     The buffer holding the input block. Must be 16 bytes.\n * \\param output    The buffer to which the output block will be written.\n *                  Must be writable and 16 bytes long.\n *                  This must either not overlap with \\p input, or be equal.\n *\n * \\retval          \\c 0 on success.\n * \\retval          #MBEDTLS_ERR_CIPHER_INVALID_CONTEXT if the context was not\n *                  properly set up before calling this function.\n * \\retval          Another negative value if encryption failed.\n */\nint mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx,\n                                 const unsigned char input[16],\n                                 unsigned char output[16]);\n/**\n * \\brief           Clear the context.\n *\n * \\param ctx       The context to clear.\n */\nvoid mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_BLOCK_CIPHER_INTERNAL_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/bn_mul.h",
    "content": "/**\n * \\file bn_mul.h\n *\n * \\brief Multi-precision integer library\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *      Multiply source vector [s] with b, add result\n *       to destination vector [d] and set carry c.\n *\n *      Currently supports:\n *\n *         . IA-32 (386+)         . AMD64 / EM64T\n *         . IA-32 (SSE2)         . Motorola 68000\n *         . PowerPC, 32-bit      . MicroBlaze\n *         . PowerPC, 64-bit      . TriCore\n *         . SPARC v8             . ARM v3+\n *         . Alpha                . MIPS32\n *         . C, longlong          . C, generic\n */\n#ifndef MBEDTLS_BN_MUL_H\n#define MBEDTLS_BN_MUL_H\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/bignum.h\"\n\n\n/*\n * Conversion macros for embedded constants:\n * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2\n */\n#if defined(MBEDTLS_HAVE_INT32)\n\n#define MBEDTLS_BYTES_TO_T_UINT_4(a, b, c, d)               \\\n    ((mbedtls_mpi_uint) (a) <<  0) |                        \\\n    ((mbedtls_mpi_uint) (b) <<  8) |                        \\\n    ((mbedtls_mpi_uint) (c) << 16) |                        \\\n    ((mbedtls_mpi_uint) (d) << 24)\n\n#define MBEDTLS_BYTES_TO_T_UINT_2(a, b)                   \\\n    MBEDTLS_BYTES_TO_T_UINT_4(a, b, 0, 0)\n\n#define MBEDTLS_BYTES_TO_T_UINT_8(a, b, c, d, e, f, g, h) \\\n    MBEDTLS_BYTES_TO_T_UINT_4(a, b, c, d),                \\\n    MBEDTLS_BYTES_TO_T_UINT_4(e, f, g, h)\n\n#else /* 64-bits */\n\n#define MBEDTLS_BYTES_TO_T_UINT_8(a, b, c, d, e, f, g, h)   \\\n    ((mbedtls_mpi_uint) (a) <<  0) |                        \\\n    ((mbedtls_mpi_uint) (b) <<  8) |                        \\\n    ((mbedtls_mpi_uint) (c) << 16) |                        \\\n    ((mbedtls_mpi_uint) (d) << 24) |                        \\\n    ((mbedtls_mpi_uint) (e) << 32) |                        \\\n    ((mbedtls_mpi_uint) (f) << 40) |                        \\\n    ((mbedtls_mpi_uint) (g) << 48) |                        \\\n    ((mbedtls_mpi_uint) (h) << 56)\n\n#define MBEDTLS_BYTES_TO_T_UINT_4(a, b, c, d)             \\\n    MBEDTLS_BYTES_TO_T_UINT_8(a, b, c, d, 0, 0, 0, 0)\n\n#define MBEDTLS_BYTES_TO_T_UINT_2(a, b)                   \\\n    MBEDTLS_BYTES_TO_T_UINT_8(a, b, 0, 0, 0, 0, 0, 0)\n\n#endif /* bits in mbedtls_mpi_uint */\n\n/* *INDENT-OFF* */\n#if defined(MBEDTLS_HAVE_ASM)\n\n/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */\n#if defined(__GNUC__) && \\\n    ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 )\n\n/*\n * GCC < 5.0 treated the x86 ebx (which is used for the GOT) as a\n * fixed reserved register when building as PIC, leading to errors\n * like: bn_mul.h:46:13: error: PIC register clobbered by 'ebx' in 'asm'\n *\n * This is fixed by an improved register allocator in GCC 5+. From the\n * release notes:\n * Register allocation improvements: Reuse of the PIC hard register,\n * instead of using a fixed register, was implemented on x86/x86-64\n * targets. This improves generated PIC code performance as more hard\n * registers can be used.\n */\n#if defined(__GNUC__) && __GNUC__ < 5 && defined(__PIC__)\n#define MULADDC_CANNOT_USE_EBX\n#endif\n\n/*\n * Disable use of the i386 assembly code below if option -O0, to disable all\n * compiler optimisations, is passed, detected with __OPTIMIZE__\n * This is done as the number of registers used in the assembly code doesn't\n * work with the -O0 option.\n */\n#if defined(__i386__) && defined(__OPTIMIZE__) && !defined(MULADDC_CANNOT_USE_EBX)\n\n#define MULADDC_X1_INIT                     \\\n    { mbedtls_mpi_uint t;                   \\\n    asm(                                    \\\n        \"movl   %%ebx, %0           \\n\\t\"   \\\n        \"movl   %5, %%esi           \\n\\t\"   \\\n        \"movl   %6, %%edi           \\n\\t\"   \\\n        \"movl   %7, %%ecx           \\n\\t\"   \\\n        \"movl   %8, %%ebx           \\n\\t\"\n\n#define MULADDC_X1_CORE                     \\\n        \"lodsl                      \\n\\t\"   \\\n        \"mull   %%ebx               \\n\\t\"   \\\n        \"addl   %%ecx,   %%eax      \\n\\t\"   \\\n        \"adcl   $0,      %%edx      \\n\\t\"   \\\n        \"addl   (%%edi), %%eax      \\n\\t\"   \\\n        \"adcl   $0,      %%edx      \\n\\t\"   \\\n        \"movl   %%edx,   %%ecx      \\n\\t\"   \\\n        \"stosl                      \\n\\t\"\n\n#define MULADDC_X1_STOP                                 \\\n        \"movl   %4, %%ebx       \\n\\t\"                   \\\n        \"movl   %%ecx, %1       \\n\\t\"                   \\\n        \"movl   %%edi, %2       \\n\\t\"                   \\\n        \"movl   %%esi, %3       \\n\\t\"                   \\\n        : \"=m\" (t), \"=m\" (c), \"=m\" (d), \"=m\" (s)        \\\n        : \"m\" (t), \"m\" (s), \"m\" (d), \"m\" (c), \"m\" (b)   \\\n        : \"eax\", \"ebx\", \"ecx\", \"edx\", \"esi\", \"edi\"      \\\n    ); }\n\n#if defined(MBEDTLS_HAVE_SSE2)\n\n#define MULADDC_X8_INIT MULADDC_X1_INIT\n\n#define MULADDC_X8_CORE                         \\\n        \"movd     %%ecx,     %%mm1      \\n\\t\"   \\\n        \"movd     %%ebx,     %%mm0      \\n\\t\"   \\\n        \"movd     (%%edi),   %%mm3      \\n\\t\"   \\\n        \"paddq    %%mm3,     %%mm1      \\n\\t\"   \\\n        \"movd     (%%esi),   %%mm2      \\n\\t\"   \\\n        \"pmuludq  %%mm0,     %%mm2      \\n\\t\"   \\\n        \"movd     4(%%esi),  %%mm4      \\n\\t\"   \\\n        \"pmuludq  %%mm0,     %%mm4      \\n\\t\"   \\\n        \"movd     8(%%esi),  %%mm6      \\n\\t\"   \\\n        \"pmuludq  %%mm0,     %%mm6      \\n\\t\"   \\\n        \"movd     12(%%esi), %%mm7      \\n\\t\"   \\\n        \"pmuludq  %%mm0,     %%mm7      \\n\\t\"   \\\n        \"paddq    %%mm2,     %%mm1      \\n\\t\"   \\\n        \"movd     4(%%edi),  %%mm3      \\n\\t\"   \\\n        \"paddq    %%mm4,     %%mm3      \\n\\t\"   \\\n        \"movd     8(%%edi),  %%mm5      \\n\\t\"   \\\n        \"paddq    %%mm6,     %%mm5      \\n\\t\"   \\\n        \"movd     12(%%edi), %%mm4      \\n\\t\"   \\\n        \"paddq    %%mm4,     %%mm7      \\n\\t\"   \\\n        \"movd     %%mm1,     (%%edi)    \\n\\t\"   \\\n        \"movd     16(%%esi), %%mm2      \\n\\t\"   \\\n        \"pmuludq  %%mm0,     %%mm2      \\n\\t\"   \\\n        \"psrlq    $32,       %%mm1      \\n\\t\"   \\\n        \"movd     20(%%esi), %%mm4      \\n\\t\"   \\\n        \"pmuludq  %%mm0,     %%mm4      \\n\\t\"   \\\n        \"paddq    %%mm3,     %%mm1      \\n\\t\"   \\\n        \"movd     24(%%esi), %%mm6      \\n\\t\"   \\\n        \"pmuludq  %%mm0,     %%mm6      \\n\\t\"   \\\n        \"movd     %%mm1,     4(%%edi)   \\n\\t\"   \\\n        \"psrlq    $32,       %%mm1      \\n\\t\"   \\\n        \"movd     28(%%esi), %%mm3      \\n\\t\"   \\\n        \"pmuludq  %%mm0,     %%mm3      \\n\\t\"   \\\n        \"paddq    %%mm5,     %%mm1      \\n\\t\"   \\\n        \"movd     16(%%edi), %%mm5      \\n\\t\"   \\\n        \"paddq    %%mm5,     %%mm2      \\n\\t\"   \\\n        \"movd     %%mm1,     8(%%edi)   \\n\\t\"   \\\n        \"psrlq    $32,       %%mm1      \\n\\t\"   \\\n        \"paddq    %%mm7,     %%mm1      \\n\\t\"   \\\n        \"movd     20(%%edi), %%mm5      \\n\\t\"   \\\n        \"paddq    %%mm5,     %%mm4      \\n\\t\"   \\\n        \"movd     %%mm1,     12(%%edi)  \\n\\t\"   \\\n        \"psrlq    $32,       %%mm1      \\n\\t\"   \\\n        \"paddq    %%mm2,     %%mm1      \\n\\t\"   \\\n        \"movd     24(%%edi), %%mm5      \\n\\t\"   \\\n        \"paddq    %%mm5,     %%mm6      \\n\\t\"   \\\n        \"movd     %%mm1,     16(%%edi)  \\n\\t\"   \\\n        \"psrlq    $32,       %%mm1      \\n\\t\"   \\\n        \"paddq    %%mm4,     %%mm1      \\n\\t\"   \\\n        \"movd     28(%%edi), %%mm5      \\n\\t\"   \\\n        \"paddq    %%mm5,     %%mm3      \\n\\t\"   \\\n        \"movd     %%mm1,     20(%%edi)  \\n\\t\"   \\\n        \"psrlq    $32,       %%mm1      \\n\\t\"   \\\n        \"paddq    %%mm6,     %%mm1      \\n\\t\"   \\\n        \"movd     %%mm1,     24(%%edi)  \\n\\t\"   \\\n        \"psrlq    $32,       %%mm1      \\n\\t\"   \\\n        \"paddq    %%mm3,     %%mm1      \\n\\t\"   \\\n        \"movd     %%mm1,     28(%%edi)  \\n\\t\"   \\\n        \"addl     $32,       %%edi      \\n\\t\"   \\\n        \"addl     $32,       %%esi      \\n\\t\"   \\\n        \"psrlq    $32,       %%mm1      \\n\\t\"   \\\n        \"movd     %%mm1,     %%ecx      \\n\\t\"\n\n#define MULADDC_X8_STOP                 \\\n        \"emms                   \\n\\t\"   \\\n        \"movl   %4, %%ebx       \\n\\t\"   \\\n        \"movl   %%ecx, %1       \\n\\t\"   \\\n        \"movl   %%edi, %2       \\n\\t\"   \\\n        \"movl   %%esi, %3       \\n\\t\"   \\\n        : \"=m\" (t), \"=m\" (c), \"=m\" (d), \"=m\" (s)        \\\n        : \"m\" (t), \"m\" (s), \"m\" (d), \"m\" (c), \"m\" (b)   \\\n        : \"eax\", \"ebx\", \"ecx\", \"edx\", \"esi\", \"edi\"      \\\n    ); }                                                \\\n\n#endif /* SSE2 */\n\n#endif /* i386 */\n\n#if defined(__amd64__) || defined (__x86_64__)\n\n#define MULADDC_X1_INIT                        \\\n    asm(                                    \\\n        \"xorq   %%r8, %%r8\\n\"\n\n#define MULADDC_X1_CORE                        \\\n        \"movq   (%%rsi), %%rax\\n\"           \\\n        \"mulq   %%rbx\\n\"                    \\\n        \"addq   $8, %%rsi\\n\"                \\\n        \"addq   %%rcx, %%rax\\n\"             \\\n        \"movq   %%r8, %%rcx\\n\"              \\\n        \"adcq   $0, %%rdx\\n\"                \\\n        \"nop    \\n\"                         \\\n        \"addq   %%rax, (%%rdi)\\n\"           \\\n        \"adcq   %%rdx, %%rcx\\n\"             \\\n        \"addq   $8, %%rdi\\n\"\n\n#define MULADDC_X1_STOP                                              \\\n        : \"+c\" (c), \"+D\" (d), \"+S\" (s), \"+m\" (*(uint64_t (*)[16]) d) \\\n        : \"b\" (b), \"m\" (*(const uint64_t (*)[16]) s)                 \\\n        : \"rax\", \"rdx\", \"r8\"                                         \\\n    );\n\n#endif /* AMD64 */\n\n// The following assembly code assumes that a pointer will fit in a 64-bit register\n// (including ILP32 __aarch64__ ABIs such as on watchOS, hence the 2^32 - 1)\n#if defined(__aarch64__) && (UINTPTR_MAX == 0xfffffffful || UINTPTR_MAX == 0xfffffffffffffffful)\n\n/*\n * There are some issues around different compilers requiring different constraint\n * syntax for updating pointers from assembly code (see notes for\n * MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT in common.h), especially on aarch64_32 (aka ILP32).\n *\n * For this reason we cast the pointers to/from uintptr_t here.\n */\n#define MULADDC_X1_INIT             \\\n    do { uintptr_t muladdc_d = (uintptr_t) d, muladdc_s = (uintptr_t) s; asm(\n\n#define MULADDC_X1_CORE             \\\n        \"ldr x4, [%x2], #8  \\n\\t\"   \\\n        \"ldr x5, [%x1]      \\n\\t\"   \\\n        \"mul x6, x4, %4     \\n\\t\"   \\\n        \"umulh x7, x4, %4   \\n\\t\"   \\\n        \"adds x5, x5, x6    \\n\\t\"   \\\n        \"adc x7, x7, xzr    \\n\\t\"   \\\n        \"adds x5, x5, %0    \\n\\t\"   \\\n        \"adc %0, x7, xzr    \\n\\t\"   \\\n        \"str x5, [%x1], #8  \\n\\t\"\n\n#define MULADDC_X1_STOP                                                 \\\n         : \"+r\" (c),                                                    \\\n           \"+r\" (muladdc_d),                                            \\\n           \"+r\" (muladdc_s),                                            \\\n           \"+m\" (*(uint64_t (*)[16]) d)                                 \\\n         : \"r\" (b), \"m\" (*(const uint64_t (*)[16]) s)                   \\\n         : \"x4\", \"x5\", \"x6\", \"x7\", \"cc\"                                 \\\n    ); d = (mbedtls_mpi_uint *)muladdc_d; s = (mbedtls_mpi_uint *)muladdc_s; } while (0);\n\n#endif /* Aarch64 */\n\n#if defined(__mc68020__) || defined(__mcpu32__)\n\n#define MULADDC_X1_INIT                 \\\n    asm(                                \\\n        \"movl   %3, %%a2        \\n\\t\"   \\\n        \"movl   %4, %%a3        \\n\\t\"   \\\n        \"movl   %5, %%d3        \\n\\t\"   \\\n        \"movl   %6, %%d2        \\n\\t\"   \\\n        \"moveq  #0, %%d0        \\n\\t\"\n\n#define MULADDC_X1_CORE                 \\\n        \"movel  %%a2@+, %%d1    \\n\\t\"   \\\n        \"mulul  %%d2, %%d4:%%d1 \\n\\t\"   \\\n        \"addl   %%d3, %%d1      \\n\\t\"   \\\n        \"addxl  %%d0, %%d4      \\n\\t\"   \\\n        \"moveq  #0,   %%d3      \\n\\t\"   \\\n        \"addl   %%d1, %%a3@+    \\n\\t\"   \\\n        \"addxl  %%d4, %%d3      \\n\\t\"\n\n#define MULADDC_X1_STOP                 \\\n        \"movl   %%d3, %0        \\n\\t\"   \\\n        \"movl   %%a3, %1        \\n\\t\"   \\\n        \"movl   %%a2, %2        \\n\\t\"   \\\n        : \"=m\" (c), \"=m\" (d), \"=m\" (s)              \\\n        : \"m\" (s), \"m\" (d), \"m\" (c), \"m\" (b)        \\\n        : \"d0\", \"d1\", \"d2\", \"d3\", \"d4\", \"a2\", \"a3\"  \\\n    );\n\n#define MULADDC_X8_INIT MULADDC_X1_INIT\n\n#define MULADDC_X8_CORE                     \\\n        \"movel  %%a2@+,  %%d1       \\n\\t\"   \\\n        \"mulul  %%d2,    %%d4:%%d1  \\n\\t\"   \\\n        \"addxl  %%d3,    %%d1       \\n\\t\"   \\\n        \"addxl  %%d0,    %%d4       \\n\\t\"   \\\n        \"addl   %%d1,    %%a3@+     \\n\\t\"   \\\n        \"movel  %%a2@+,  %%d1       \\n\\t\"   \\\n        \"mulul  %%d2,    %%d3:%%d1  \\n\\t\"   \\\n        \"addxl  %%d4,    %%d1       \\n\\t\"   \\\n        \"addxl  %%d0,    %%d3       \\n\\t\"   \\\n        \"addl   %%d1,    %%a3@+     \\n\\t\"   \\\n        \"movel  %%a2@+,  %%d1       \\n\\t\"   \\\n        \"mulul  %%d2,    %%d4:%%d1  \\n\\t\"   \\\n        \"addxl  %%d3,    %%d1       \\n\\t\"   \\\n        \"addxl  %%d0,    %%d4       \\n\\t\"   \\\n        \"addl   %%d1,    %%a3@+     \\n\\t\"   \\\n        \"movel  %%a2@+,  %%d1       \\n\\t\"   \\\n        \"mulul  %%d2,    %%d3:%%d1  \\n\\t\"   \\\n        \"addxl  %%d4,    %%d1       \\n\\t\"   \\\n        \"addxl  %%d0,    %%d3       \\n\\t\"   \\\n        \"addl   %%d1,    %%a3@+     \\n\\t\"   \\\n        \"movel  %%a2@+,  %%d1       \\n\\t\"   \\\n        \"mulul  %%d2,    %%d4:%%d1  \\n\\t\"   \\\n        \"addxl  %%d3,    %%d1       \\n\\t\"   \\\n        \"addxl  %%d0,    %%d4       \\n\\t\"   \\\n        \"addl   %%d1,    %%a3@+     \\n\\t\"   \\\n        \"movel  %%a2@+,  %%d1       \\n\\t\"   \\\n        \"mulul  %%d2,    %%d3:%%d1  \\n\\t\"   \\\n        \"addxl  %%d4,    %%d1       \\n\\t\"   \\\n        \"addxl  %%d0,    %%d3       \\n\\t\"   \\\n        \"addl   %%d1,    %%a3@+     \\n\\t\"   \\\n        \"movel  %%a2@+,  %%d1       \\n\\t\"   \\\n        \"mulul  %%d2,    %%d4:%%d1  \\n\\t\"   \\\n        \"addxl  %%d3,    %%d1       \\n\\t\"   \\\n        \"addxl  %%d0,    %%d4       \\n\\t\"   \\\n        \"addl   %%d1,    %%a3@+     \\n\\t\"   \\\n        \"movel  %%a2@+,  %%d1       \\n\\t\"   \\\n        \"mulul  %%d2,    %%d3:%%d1  \\n\\t\"   \\\n        \"addxl  %%d4,    %%d1       \\n\\t\"   \\\n        \"addxl  %%d0,    %%d3       \\n\\t\"   \\\n        \"addl   %%d1,    %%a3@+     \\n\\t\"   \\\n        \"addxl  %%d0,    %%d3       \\n\\t\"\n\n#define MULADDC_X8_STOP MULADDC_X1_STOP\n\n#endif /* MC68000 */\n\n#if defined(__powerpc64__) || defined(__ppc64__)\n\n#if defined(__MACH__) && defined(__APPLE__)\n\n#define MULADDC_X1_INIT                     \\\n    asm(                                    \\\n        \"ld     r3, %3              \\n\\t\"   \\\n        \"ld     r4, %4              \\n\\t\"   \\\n        \"ld     r5, %5              \\n\\t\"   \\\n        \"ld     r6, %6              \\n\\t\"   \\\n        \"addi   r3, r3, -8          \\n\\t\"   \\\n        \"addi   r4, r4, -8          \\n\\t\"   \\\n        \"addic  r5, r5,  0          \\n\\t\"\n\n#define MULADDC_X1_CORE                     \\\n        \"ldu    r7, 8(r3)           \\n\\t\"   \\\n        \"mulld  r8, r7, r6          \\n\\t\"   \\\n        \"mulhdu r9, r7, r6          \\n\\t\"   \\\n        \"adde   r8, r8, r5          \\n\\t\"   \\\n        \"ld     r7, 8(r4)           \\n\\t\"   \\\n        \"addze  r5, r9              \\n\\t\"   \\\n        \"addc   r8, r8, r7          \\n\\t\"   \\\n        \"stdu   r8, 8(r4)           \\n\\t\"\n\n#define MULADDC_X1_STOP                     \\\n        \"addze  r5, r5              \\n\\t\"   \\\n        \"addi   r4, r4, 8           \\n\\t\"   \\\n        \"addi   r3, r3, 8           \\n\\t\"   \\\n        \"std    r5, %0              \\n\\t\"   \\\n        \"std    r4, %1              \\n\\t\"   \\\n        \"std    r3, %2              \\n\\t\"   \\\n        : \"=m\" (c), \"=m\" (d), \"=m\" (s)              \\\n        : \"m\" (s), \"m\" (d), \"m\" (c), \"m\" (b)        \\\n        : \"r3\", \"r4\", \"r5\", \"r6\", \"r7\", \"r8\", \"r9\"  \\\n    );\n\n\n#else /* __MACH__ && __APPLE__ */\n\n#define MULADDC_X1_INIT                     \\\n    asm(                                    \\\n        \"ld     %%r3, %3            \\n\\t\"   \\\n        \"ld     %%r4, %4            \\n\\t\"   \\\n        \"ld     %%r5, %5            \\n\\t\"   \\\n        \"ld     %%r6, %6            \\n\\t\"   \\\n        \"addi   %%r3, %%r3, -8      \\n\\t\"   \\\n        \"addi   %%r4, %%r4, -8      \\n\\t\"   \\\n        \"addic  %%r5, %%r5,  0      \\n\\t\"\n\n#define MULADDC_X1_CORE                     \\\n        \"ldu    %%r7, 8(%%r3)       \\n\\t\"   \\\n        \"mulld  %%r8, %%r7, %%r6    \\n\\t\"   \\\n        \"mulhdu %%r9, %%r7, %%r6    \\n\\t\"   \\\n        \"adde   %%r8, %%r8, %%r5    \\n\\t\"   \\\n        \"ld     %%r7, 8(%%r4)       \\n\\t\"   \\\n        \"addze  %%r5, %%r9          \\n\\t\"   \\\n        \"addc   %%r8, %%r8, %%r7    \\n\\t\"   \\\n        \"stdu   %%r8, 8(%%r4)       \\n\\t\"\n\n#define MULADDC_X1_STOP                     \\\n        \"addze  %%r5, %%r5          \\n\\t\"   \\\n        \"addi   %%r4, %%r4, 8       \\n\\t\"   \\\n        \"addi   %%r3, %%r3, 8       \\n\\t\"   \\\n        \"std    %%r5, %0            \\n\\t\"   \\\n        \"std    %%r4, %1            \\n\\t\"   \\\n        \"std    %%r3, %2            \\n\\t\"   \\\n        : \"=m\" (c), \"=m\" (d), \"=m\" (s)              \\\n        : \"m\" (s), \"m\" (d), \"m\" (c), \"m\" (b)        \\\n        : \"r3\", \"r4\", \"r5\", \"r6\", \"r7\", \"r8\", \"r9\"  \\\n    );\n\n#endif /* __MACH__ && __APPLE__ */\n\n#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32  */\n\n#if defined(__MACH__) && defined(__APPLE__)\n\n#define MULADDC_X1_INIT                 \\\n    asm(                                \\\n        \"lwz    r3, %3          \\n\\t\"   \\\n        \"lwz    r4, %4          \\n\\t\"   \\\n        \"lwz    r5, %5          \\n\\t\"   \\\n        \"lwz    r6, %6          \\n\\t\"   \\\n        \"addi   r3, r3, -4      \\n\\t\"   \\\n        \"addi   r4, r4, -4      \\n\\t\"   \\\n        \"addic  r5, r5,  0      \\n\\t\"\n\n#define MULADDC_X1_CORE                 \\\n        \"lwzu   r7, 4(r3)       \\n\\t\"   \\\n        \"mullw  r8, r7, r6      \\n\\t\"   \\\n        \"mulhwu r9, r7, r6      \\n\\t\"   \\\n        \"adde   r8, r8, r5      \\n\\t\"   \\\n        \"lwz    r7, 4(r4)       \\n\\t\"   \\\n        \"addze  r5, r9          \\n\\t\"   \\\n        \"addc   r8, r8, r7      \\n\\t\"   \\\n        \"stwu   r8, 4(r4)       \\n\\t\"\n\n#define MULADDC_X1_STOP                 \\\n        \"addze  r5, r5          \\n\\t\"   \\\n        \"addi   r4, r4, 4       \\n\\t\"   \\\n        \"addi   r3, r3, 4       \\n\\t\"   \\\n        \"stw    r5, %0          \\n\\t\"   \\\n        \"stw    r4, %1          \\n\\t\"   \\\n        \"stw    r3, %2          \\n\\t\"   \\\n        : \"=m\" (c), \"=m\" (d), \"=m\" (s)              \\\n        : \"m\" (s), \"m\" (d), \"m\" (c), \"m\" (b)        \\\n        : \"r3\", \"r4\", \"r5\", \"r6\", \"r7\", \"r8\", \"r9\"  \\\n    );\n\n#else /* __MACH__ && __APPLE__ */\n\n#define MULADDC_X1_INIT                     \\\n    asm(                                    \\\n        \"lwz    %%r3, %3            \\n\\t\"   \\\n        \"lwz    %%r4, %4            \\n\\t\"   \\\n        \"lwz    %%r5, %5            \\n\\t\"   \\\n        \"lwz    %%r6, %6            \\n\\t\"   \\\n        \"addi   %%r3, %%r3, -4      \\n\\t\"   \\\n        \"addi   %%r4, %%r4, -4      \\n\\t\"   \\\n        \"addic  %%r5, %%r5,  0      \\n\\t\"\n\n#define MULADDC_X1_CORE                     \\\n        \"lwzu   %%r7, 4(%%r3)       \\n\\t\"   \\\n        \"mullw  %%r8, %%r7, %%r6    \\n\\t\"   \\\n        \"mulhwu %%r9, %%r7, %%r6    \\n\\t\"   \\\n        \"adde   %%r8, %%r8, %%r5    \\n\\t\"   \\\n        \"lwz    %%r7, 4(%%r4)       \\n\\t\"   \\\n        \"addze  %%r5, %%r9          \\n\\t\"   \\\n        \"addc   %%r8, %%r8, %%r7    \\n\\t\"   \\\n        \"stwu   %%r8, 4(%%r4)       \\n\\t\"\n\n#define MULADDC_X1_STOP                     \\\n        \"addze  %%r5, %%r5          \\n\\t\"   \\\n        \"addi   %%r4, %%r4, 4       \\n\\t\"   \\\n        \"addi   %%r3, %%r3, 4       \\n\\t\"   \\\n        \"stw    %%r5, %0            \\n\\t\"   \\\n        \"stw    %%r4, %1            \\n\\t\"   \\\n        \"stw    %%r3, %2            \\n\\t\"   \\\n        : \"=m\" (c), \"=m\" (d), \"=m\" (s)              \\\n        : \"m\" (s), \"m\" (d), \"m\" (c), \"m\" (b)        \\\n        : \"r3\", \"r4\", \"r5\", \"r6\", \"r7\", \"r8\", \"r9\"  \\\n    );\n\n#endif /* __MACH__ && __APPLE__ */\n\n#endif /* PPC32 */\n\n/*\n * The Sparc(64) assembly is reported to be broken.\n * Disable it for now, until we're able to fix it.\n */\n#if 0 && defined(__sparc__)\n#if defined(__sparc64__)\n\n#define MULADDC_X1_INIT                                 \\\n    asm(                                                \\\n                \"ldx     %3, %%o0               \\n\\t\"   \\\n                \"ldx     %4, %%o1               \\n\\t\"   \\\n                \"ld      %5, %%o2               \\n\\t\"   \\\n                \"ld      %6, %%o3               \\n\\t\"\n\n#define MULADDC_X1_CORE                                 \\\n                \"ld      [%%o0], %%o4           \\n\\t\"   \\\n                \"inc     4, %%o0                \\n\\t\"   \\\n                \"ld      [%%o1], %%o5           \\n\\t\"   \\\n                \"umul    %%o3, %%o4, %%o4       \\n\\t\"   \\\n                \"addcc   %%o4, %%o2, %%o4       \\n\\t\"   \\\n                \"rd      %%y, %%g1              \\n\\t\"   \\\n                \"addx    %%g1, 0, %%g1          \\n\\t\"   \\\n                \"addcc   %%o4, %%o5, %%o4       \\n\\t\"   \\\n                \"st      %%o4, [%%o1]           \\n\\t\"   \\\n                \"addx    %%g1, 0, %%o2          \\n\\t\"   \\\n                \"inc     4, %%o1                \\n\\t\"\n\n#define MULADDC_X1_STOP                                 \\\n                \"st      %%o2, %0               \\n\\t\"   \\\n                \"stx     %%o1, %1               \\n\\t\"   \\\n                \"stx     %%o0, %2               \\n\\t\"   \\\n        : \"=m\" (c), \"=m\" (d), \"=m\" (s)          \\\n        : \"m\" (s), \"m\" (d), \"m\" (c), \"m\" (b)    \\\n        : \"g1\", \"o0\", \"o1\", \"o2\", \"o3\", \"o4\",   \\\n          \"o5\"                                  \\\n        );\n\n#else /* __sparc64__ */\n\n#define MULADDC_X1_INIT                                 \\\n    asm(                                                \\\n                \"ld      %3, %%o0               \\n\\t\"   \\\n                \"ld      %4, %%o1               \\n\\t\"   \\\n                \"ld      %5, %%o2               \\n\\t\"   \\\n                \"ld      %6, %%o3               \\n\\t\"\n\n#define MULADDC_X1_CORE                                 \\\n                \"ld      [%%o0], %%o4           \\n\\t\"   \\\n                \"inc     4, %%o0                \\n\\t\"   \\\n                \"ld      [%%o1], %%o5           \\n\\t\"   \\\n                \"umul    %%o3, %%o4, %%o4       \\n\\t\"   \\\n                \"addcc   %%o4, %%o2, %%o4       \\n\\t\"   \\\n                \"rd      %%y, %%g1              \\n\\t\"   \\\n                \"addx    %%g1, 0, %%g1          \\n\\t\"   \\\n                \"addcc   %%o4, %%o5, %%o4       \\n\\t\"   \\\n                \"st      %%o4, [%%o1]           \\n\\t\"   \\\n                \"addx    %%g1, 0, %%o2          \\n\\t\"   \\\n                \"inc     4, %%o1                \\n\\t\"\n\n#define MULADDC_X1_STOP                                 \\\n                \"st      %%o2, %0               \\n\\t\"   \\\n                \"st      %%o1, %1               \\n\\t\"   \\\n                \"st      %%o0, %2               \\n\\t\"   \\\n        : \"=m\" (c), \"=m\" (d), \"=m\" (s)          \\\n        : \"m\" (s), \"m\" (d), \"m\" (c), \"m\" (b)    \\\n        : \"g1\", \"o0\", \"o1\", \"o2\", \"o3\", \"o4\",   \\\n          \"o5\"                                  \\\n        );\n\n#endif /* __sparc64__ */\n#endif /* __sparc__ */\n\n#if defined(__microblaze__) || defined(microblaze)\n\n#define MULADDC_X1_INIT                 \\\n    asm(                                \\\n        \"lwi   r3,   %3         \\n\\t\"   \\\n        \"lwi   r4,   %4         \\n\\t\"   \\\n        \"lwi   r5,   %5         \\n\\t\"   \\\n        \"lwi   r6,   %6         \\n\\t\"   \\\n        \"andi  r7,   r6, 0xffff \\n\\t\"   \\\n        \"bsrli r6,   r6, 16     \\n\\t\"\n\n#if(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n#define MULADDC_LHUI                    \\\n        \"lhui  r9,   r3,   0    \\n\\t\"   \\\n        \"addi  r3,   r3,   2    \\n\\t\"   \\\n        \"lhui  r8,   r3,   0    \\n\\t\"\n#else\n#define MULADDC_LHUI                    \\\n        \"lhui  r8,   r3,   0    \\n\\t\"   \\\n        \"addi  r3,   r3,   2    \\n\\t\"   \\\n        \"lhui  r9,   r3,   0    \\n\\t\"\n#endif\n\n#define MULADDC_X1_CORE                    \\\n        MULADDC_LHUI                    \\\n        \"addi  r3,   r3,   2    \\n\\t\"   \\\n        \"mul   r10,  r9,  r6    \\n\\t\"   \\\n        \"mul   r11,  r8,  r7    \\n\\t\"   \\\n        \"mul   r12,  r9,  r7    \\n\\t\"   \\\n        \"mul   r13,  r8,  r6    \\n\\t\"   \\\n        \"bsrli  r8, r10,  16    \\n\\t\"   \\\n        \"bsrli  r9, r11,  16    \\n\\t\"   \\\n        \"add   r13, r13,  r8    \\n\\t\"   \\\n        \"add   r13, r13,  r9    \\n\\t\"   \\\n        \"bslli r10, r10,  16    \\n\\t\"   \\\n        \"bslli r11, r11,  16    \\n\\t\"   \\\n        \"add   r12, r12, r10    \\n\\t\"   \\\n        \"addc  r13, r13,  r0    \\n\\t\"   \\\n        \"add   r12, r12, r11    \\n\\t\"   \\\n        \"addc  r13, r13,  r0    \\n\\t\"   \\\n        \"lwi   r10,  r4,   0    \\n\\t\"   \\\n        \"add   r12, r12, r10    \\n\\t\"   \\\n        \"addc  r13, r13,  r0    \\n\\t\"   \\\n        \"add   r12, r12,  r5    \\n\\t\"   \\\n        \"addc   r5, r13,  r0    \\n\\t\"   \\\n        \"swi   r12,  r4,   0    \\n\\t\"   \\\n        \"addi   r4,  r4,   4    \\n\\t\"\n\n#define MULADDC_X1_STOP                 \\\n        \"swi   r5,   %0         \\n\\t\"   \\\n        \"swi   r4,   %1         \\n\\t\"   \\\n        \"swi   r3,   %2         \\n\\t\"   \\\n        : \"=m\" (c), \"=m\" (d), \"=m\" (s)              \\\n        : \"m\" (s), \"m\" (d), \"m\" (c), \"m\" (b)        \\\n        : \"r3\", \"r4\", \"r5\", \"r6\", \"r7\", \"r8\",       \\\n          \"r9\", \"r10\", \"r11\", \"r12\", \"r13\"          \\\n    );\n\n#endif /* MicroBlaze */\n\n#if defined(__tricore__)\n\n#define MULADDC_X1_INIT                         \\\n    asm(                                        \\\n        \"ld.a   %%a2, %3                \\n\\t\"   \\\n        \"ld.a   %%a3, %4                \\n\\t\"   \\\n        \"ld.w   %%d4, %5                \\n\\t\"   \\\n        \"ld.w   %%d1, %6                \\n\\t\"   \\\n        \"xor    %%d5, %%d5              \\n\\t\"\n\n#define MULADDC_X1_CORE                         \\\n        \"ld.w   %%d0,   [%%a2+]         \\n\\t\"   \\\n        \"madd.u %%e2, %%e4, %%d0, %%d1  \\n\\t\"   \\\n        \"ld.w   %%d0,   [%%a3]          \\n\\t\"   \\\n        \"addx   %%d2,    %%d2,  %%d0    \\n\\t\"   \\\n        \"addc   %%d3,    %%d3,    0     \\n\\t\"   \\\n        \"mov    %%d4,    %%d3           \\n\\t\"   \\\n        \"st.w  [%%a3+],  %%d2           \\n\\t\"\n\n#define MULADDC_X1_STOP                         \\\n        \"st.w   %0, %%d4                \\n\\t\"   \\\n        \"st.a   %1, %%a3                \\n\\t\"   \\\n        \"st.a   %2, %%a2                \\n\\t\"   \\\n        : \"=m\" (c), \"=m\" (d), \"=m\" (s)          \\\n        : \"m\" (s), \"m\" (d), \"m\" (c), \"m\" (b)    \\\n        : \"d0\", \"d1\", \"e2\", \"d4\", \"a2\", \"a3\"    \\\n    );\n\n#endif /* TriCore */\n\n#if defined(__arm__)\n\n#if defined(__thumb__) && !defined(__thumb2__)\n#if defined(MBEDTLS_COMPILER_IS_GCC)\n/*\n * Thumb 1 ISA. This code path has only been tested successfully on gcc;\n * it does not compile on clang or armclang.\n */\n\n#if !defined(__OPTIMIZE__) && defined(__GNUC__)\n/*\n * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about\n * our use of r7 below, unless -fomit-frame-pointer is passed.\n *\n * On the other hand, -fomit-frame-pointer is implied by any -Ox options with\n * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by\n * clang and armcc5 under the same conditions).\n *\n * If gcc needs to use r7, we use r1 as a scratch register and have a few extra\n * instructions to preserve/restore it; otherwise, we can use r7 and avoid\n * the preserve/restore overhead.\n */\n#define MULADDC_SCRATCH              \"RS .req r1         \\n\\t\"\n#define MULADDC_PRESERVE_SCRATCH     \"mov    r10, r1     \\n\\t\"\n#define MULADDC_RESTORE_SCRATCH      \"mov    r1, r10     \\n\\t\"\n#define MULADDC_SCRATCH_CLOBBER      \"r10\"\n#else /* !defined(__OPTIMIZE__) && defined(__GNUC__) */\n#define MULADDC_SCRATCH              \"RS .req r7         \\n\\t\"\n#define MULADDC_PRESERVE_SCRATCH     \"\"\n#define MULADDC_RESTORE_SCRATCH      \"\"\n#define MULADDC_SCRATCH_CLOBBER      \"r7\"\n#endif /* !defined(__OPTIMIZE__) && defined(__GNUC__) */\n\n#define MULADDC_X1_INIT                                 \\\n    asm(                                                \\\n    MULADDC_SCRATCH                                     \\\n            \"ldr    r0, %3                      \\n\\t\"   \\\n            \"ldr    r1, %4                      \\n\\t\"   \\\n            \"ldr    r2, %5                      \\n\\t\"   \\\n            \"ldr    r3, %6                      \\n\\t\"   \\\n            \"lsr    r4, r3, #16                 \\n\\t\"   \\\n            \"mov    r9, r4                      \\n\\t\"   \\\n            \"lsl    r4, r3, #16                 \\n\\t\"   \\\n            \"lsr    r4, r4, #16                 \\n\\t\"   \\\n            \"mov    r8, r4                      \\n\\t\"   \\\n\n\n#define MULADDC_X1_CORE                                 \\\n            MULADDC_PRESERVE_SCRATCH                    \\\n            \"ldmia  r0!, {r6}                   \\n\\t\"   \\\n            \"lsr    RS, r6, #16                 \\n\\t\"   \\\n            \"lsl    r6, r6, #16                 \\n\\t\"   \\\n            \"lsr    r6, r6, #16                 \\n\\t\"   \\\n            \"mov    r4, r8                      \\n\\t\"   \\\n            \"mul    r4, r6                      \\n\\t\"   \\\n            \"mov    r3, r9                      \\n\\t\"   \\\n            \"mul    r6, r3                      \\n\\t\"   \\\n            \"mov    r5, r9                      \\n\\t\"   \\\n            \"mul    r5, RS                      \\n\\t\"   \\\n            \"mov    r3, r8                      \\n\\t\"   \\\n            \"mul    RS, r3                      \\n\\t\"   \\\n            \"lsr    r3, r6, #16                 \\n\\t\"   \\\n            \"add    r5, r5, r3                  \\n\\t\"   \\\n            \"lsr    r3, RS, #16                 \\n\\t\"   \\\n            \"add    r5, r5, r3                  \\n\\t\"   \\\n            \"add    r4, r4, r2                  \\n\\t\"   \\\n            \"mov    r2, #0                      \\n\\t\"   \\\n            \"adc    r5, r2                      \\n\\t\"   \\\n            \"lsl    r3, r6, #16                 \\n\\t\"   \\\n            \"add    r4, r4, r3                  \\n\\t\"   \\\n            \"adc    r5, r2                      \\n\\t\"   \\\n            \"lsl    r3, RS, #16                 \\n\\t\"   \\\n            \"add    r4, r4, r3                  \\n\\t\"   \\\n            \"adc    r5, r2                      \\n\\t\"   \\\n            MULADDC_RESTORE_SCRATCH                     \\\n            \"ldr    r3, [r1]                    \\n\\t\"   \\\n            \"add    r4, r4, r3                  \\n\\t\"   \\\n            \"adc    r2, r5                      \\n\\t\"   \\\n            \"stmia  r1!, {r4}                   \\n\\t\"\n\n#define MULADDC_X1_STOP                                 \\\n            \"str    r2, %0                      \\n\\t\"   \\\n            \"str    r1, %1                      \\n\\t\"   \\\n            \"str    r0, %2                      \\n\\t\"   \\\n         : \"=m\" (c),  \"=m\" (d), \"=m\" (s)        \\\n         : \"m\" (s), \"m\" (d), \"m\" (c), \"m\" (b)   \\\n         : \"r0\", \"r1\", \"r2\", \"r3\", \"r4\", \"r5\",  \\\n           \"r6\", MULADDC_SCRATCH_CLOBBER, \"r8\", \"r9\", \"cc\" \\\n         );\n#endif /* !defined(__ARMCC_VERSION) && !defined(__clang__) */\n\n#elif (__ARM_ARCH >= 6) && \\\n    defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)\n/* Armv6-M (or later) with DSP Instruction Set Extensions.\n * Requires support for either Thumb 2 or Arm ISA.\n */\n\n#define MULADDC_X1_INIT                            \\\n    {                                              \\\n        mbedtls_mpi_uint tmp_a, tmp_b;             \\\n        asm volatile (\n\n#define MULADDC_X1_CORE                                         \\\n           \".p2align  2                                 \\n\\t\"   \\\n            \"ldr      %[a], [%[in]], #4                 \\n\\t\"   \\\n            \"ldr      %[b], [%[acc]]                    \\n\\t\"   \\\n            \"umaal    %[b], %[carry], %[scalar], %[a]   \\n\\t\"   \\\n            \"str      %[b], [%[acc]], #4                \\n\\t\"\n\n#define MULADDC_X1_STOP                                      \\\n            : [a]      \"=&r\" (tmp_a),                        \\\n              [b]      \"=&r\" (tmp_b),                        \\\n              [in]     \"+r\"  (s),                            \\\n              [acc]    \"+r\"  (d),                            \\\n              [carry]  \"+l\"  (c)                             \\\n            : [scalar] \"r\"   (b)                             \\\n            : \"memory\"                                       \\\n        );                                                   \\\n    }\n\n#define MULADDC_X2_INIT                              \\\n    {                                                \\\n        mbedtls_mpi_uint tmp_a0, tmp_b0;             \\\n        mbedtls_mpi_uint tmp_a1, tmp_b1;             \\\n        asm volatile (\n\n            /* - Make sure loop is 4-byte aligned to avoid stalls\n             *   upon repeated non-word aligned instructions in\n             *   some microarchitectures.\n             * - Don't use ldm with post-increment or back-to-back\n             *   loads with post-increment and same address register\n             *   to avoid stalls on some microarchitectures.\n             * - Bunch loads and stores to reduce latency on some\n             *   microarchitectures. E.g., on Cortex-M4, the first\n             *   in a series of load/store operations has latency\n             *   2 cycles, while subsequent loads/stores are single-cycle. */\n#define MULADDC_X2_CORE                                           \\\n           \".p2align  2                                   \\n\\t\"   \\\n            \"ldr      %[a0], [%[in]],  #+8                \\n\\t\"   \\\n            \"ldr      %[b0], [%[acc]], #+8                \\n\\t\"   \\\n            \"ldr      %[a1], [%[in],  #-4]                \\n\\t\"   \\\n            \"ldr      %[b1], [%[acc], #-4]                \\n\\t\"   \\\n            \"umaal    %[b0], %[carry], %[scalar], %[a0]   \\n\\t\"   \\\n            \"umaal    %[b1], %[carry], %[scalar], %[a1]   \\n\\t\"   \\\n            \"str      %[b0], [%[acc], #-8]                \\n\\t\"   \\\n            \"str      %[b1], [%[acc], #-4]                \\n\\t\"\n\n#define MULADDC_X2_STOP                                      \\\n            : [a0]     \"=&r\" (tmp_a0),                       \\\n              [b0]     \"=&r\" (tmp_b0),                       \\\n              [a1]     \"=&r\" (tmp_a1),                       \\\n              [b1]     \"=&r\" (tmp_b1),                       \\\n              [in]     \"+r\"  (s),                            \\\n              [acc]    \"+r\"  (d),                            \\\n              [carry]  \"+l\"  (c)                             \\\n            : [scalar] \"r\"   (b)                             \\\n            : \"memory\"                                       \\\n        );                                                   \\\n    }\n\n#else /* Thumb 2 or Arm ISA, without DSP extensions */\n\n#define MULADDC_X1_INIT                                 \\\n    asm(                                                \\\n            \"ldr    r0, %3                      \\n\\t\"   \\\n            \"ldr    r1, %4                      \\n\\t\"   \\\n            \"ldr    r2, %5                      \\n\\t\"   \\\n            \"ldr    r3, %6                      \\n\\t\"\n\n#define MULADDC_X1_CORE                                 \\\n            \"ldr    r4, [r0], #4                \\n\\t\"   \\\n            \"mov    r5, #0                      \\n\\t\"   \\\n            \"ldr    r6, [r1]                    \\n\\t\"   \\\n            \"umlal  r2, r5, r3, r4              \\n\\t\"   \\\n            \"adds   r4, r6, r2                  \\n\\t\"   \\\n            \"adc    r2, r5, #0                  \\n\\t\"   \\\n            \"str    r4, [r1], #4                \\n\\t\"\n\n#define MULADDC_X1_STOP                                 \\\n            \"str    r2, %0                      \\n\\t\"   \\\n            \"str    r1, %1                      \\n\\t\"   \\\n            \"str    r0, %2                      \\n\\t\"   \\\n         : \"=m\" (c),  \"=m\" (d), \"=m\" (s)        \\\n         : \"m\" (s), \"m\" (d), \"m\" (c), \"m\" (b)   \\\n         : \"r0\", \"r1\", \"r2\", \"r3\", \"r4\", \"r5\",  \\\n           \"r6\", \"cc\"                     \\\n         );\n\n#endif /* ISA codepath selection */\n\n#endif /* defined(__arm__) */\n\n#if defined(__alpha__)\n\n#define MULADDC_X1_INIT                 \\\n    asm(                                \\\n        \"ldq    $1, %3          \\n\\t\"   \\\n        \"ldq    $2, %4          \\n\\t\"   \\\n        \"ldq    $3, %5          \\n\\t\"   \\\n        \"ldq    $4, %6          \\n\\t\"\n\n#define MULADDC_X1_CORE                 \\\n        \"ldq    $6,  0($1)      \\n\\t\"   \\\n        \"addq   $1,  8, $1      \\n\\t\"   \\\n        \"mulq   $6, $4, $7      \\n\\t\"   \\\n        \"umulh  $6, $4, $6      \\n\\t\"   \\\n        \"addq   $7, $3, $7      \\n\\t\"   \\\n        \"cmpult $7, $3, $3      \\n\\t\"   \\\n        \"ldq    $5,  0($2)      \\n\\t\"   \\\n        \"addq   $7, $5, $7      \\n\\t\"   \\\n        \"cmpult $7, $5, $5      \\n\\t\"   \\\n        \"stq    $7,  0($2)      \\n\\t\"   \\\n        \"addq   $2,  8, $2      \\n\\t\"   \\\n        \"addq   $6, $3, $3      \\n\\t\"   \\\n        \"addq   $5, $3, $3      \\n\\t\"\n\n#define MULADDC_X1_STOP                 \\\n        \"stq    $3, %0          \\n\\t\"   \\\n        \"stq    $2, %1          \\n\\t\"   \\\n        \"stq    $1, %2          \\n\\t\"   \\\n        : \"=m\" (c), \"=m\" (d), \"=m\" (s)              \\\n        : \"m\" (s), \"m\" (d), \"m\" (c), \"m\" (b)        \\\n        : \"$1\", \"$2\", \"$3\", \"$4\", \"$5\", \"$6\", \"$7\"  \\\n    );\n#endif /* Alpha */\n\n#if defined(__mips__) && !defined(__mips64)\n\n#define MULADDC_X1_INIT                 \\\n    asm(                                \\\n        \"lw     $10, %3         \\n\\t\"   \\\n        \"lw     $11, %4         \\n\\t\"   \\\n        \"lw     $12, %5         \\n\\t\"   \\\n        \"lw     $13, %6         \\n\\t\"\n\n#define MULADDC_X1_CORE                 \\\n        \"lw     $14, 0($10)     \\n\\t\"   \\\n        \"multu  $13, $14        \\n\\t\"   \\\n        \"addi   $10, $10, 4     \\n\\t\"   \\\n        \"mflo   $14             \\n\\t\"   \\\n        \"mfhi   $9              \\n\\t\"   \\\n        \"addu   $14, $12, $14   \\n\\t\"   \\\n        \"lw     $15, 0($11)     \\n\\t\"   \\\n        \"sltu   $12, $14, $12   \\n\\t\"   \\\n        \"addu   $15, $14, $15   \\n\\t\"   \\\n        \"sltu   $14, $15, $14   \\n\\t\"   \\\n        \"addu   $12, $12, $9    \\n\\t\"   \\\n        \"sw     $15, 0($11)     \\n\\t\"   \\\n        \"addu   $12, $12, $14   \\n\\t\"   \\\n        \"addi   $11, $11, 4     \\n\\t\"\n\n#define MULADDC_X1_STOP                 \\\n        \"sw     $12, %0         \\n\\t\"   \\\n        \"sw     $11, %1         \\n\\t\"   \\\n        \"sw     $10, %2         \\n\\t\"   \\\n        : \"=m\" (c), \"=m\" (d), \"=m\" (s)                      \\\n        : \"m\" (s), \"m\" (d), \"m\" (c), \"m\" (b)                \\\n        : \"$9\", \"$10\", \"$11\", \"$12\", \"$13\", \"$14\", \"$15\", \"lo\", \"hi\" \\\n    );\n\n#endif /* MIPS */\n#endif /* GNUC */\n\n#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)\n\n#define MULADDC_X1_INIT                         \\\n    __asm   mov     esi, s                      \\\n    __asm   mov     edi, d                      \\\n    __asm   mov     ecx, c                      \\\n    __asm   mov     ebx, b\n\n#define MULADDC_X1_CORE                         \\\n    __asm   lodsd                               \\\n    __asm   mul     ebx                         \\\n    __asm   add     eax, ecx                    \\\n    __asm   adc     edx, 0                      \\\n    __asm   add     eax, [edi]                  \\\n    __asm   adc     edx, 0                      \\\n    __asm   mov     ecx, edx                    \\\n    __asm   stosd\n\n#define MULADDC_X1_STOP                         \\\n    __asm   mov     c, ecx                      \\\n    __asm   mov     d, edi                      \\\n    __asm   mov     s, esi\n\n#if defined(MBEDTLS_HAVE_SSE2)\n\n#define EMIT __asm _emit\n\n#define MULADDC_X8_INIT MULADDC_X1_INIT\n\n#define MULADDC_X8_CORE                         \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0xC9             \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0xC3             \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x1F             \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x16             \\\n    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x04  \\\n    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x08  \\\n    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x7E  EMIT 0x0C  \\\n    EMIT 0x0F  EMIT 0xF4  EMIT 0xF8             \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x5F  EMIT 0x04  \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xDC             \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x08  \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xEE             \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x67  EMIT 0x0C  \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xFC             \\\n    EMIT 0x0F  EMIT 0x7E  EMIT 0x0F             \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x56  EMIT 0x10  \\\n    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \\\n    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x14  \\\n    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x18  \\\n    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \\\n    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x04  \\\n    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x5E  EMIT 0x1C  \\\n    EMIT 0x0F  EMIT 0xF4  EMIT 0xD8             \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xCD             \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x10  \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xD5             \\\n    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x08  \\\n    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xCF             \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x14  \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xE5             \\\n    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x0C  \\\n    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x18  \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xF5             \\\n    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x10  \\\n    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xCC             \\\n    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x1C  \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xDD             \\\n    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x14  \\\n    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xCE             \\\n    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x18  \\\n    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \\\n    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \\\n    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x1C  \\\n    EMIT 0x83  EMIT 0xC7  EMIT 0x20             \\\n    EMIT 0x83  EMIT 0xC6  EMIT 0x20             \\\n    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \\\n    EMIT 0x0F  EMIT 0x7E  EMIT 0xC9\n\n#define MULADDC_X8_STOP                         \\\n    EMIT 0x0F  EMIT 0x77                        \\\n    __asm   mov     c, ecx                      \\\n    __asm   mov     d, edi                      \\\n    __asm   mov     s, esi\n\n#endif /* SSE2 */\n#endif /* MSVC */\n\n#endif /* MBEDTLS_HAVE_ASM */\n\n#if !defined(MULADDC_X1_CORE)\n#if defined(MBEDTLS_HAVE_UDBL)\n\n#define MULADDC_X1_INIT                 \\\n{                                       \\\n    mbedtls_t_udbl r;                           \\\n    mbedtls_mpi_uint r0, r1;\n\n#define MULADDC_X1_CORE                 \\\n    r   = *(s++) * (mbedtls_t_udbl) b;          \\\n    r0  = (mbedtls_mpi_uint) r;                   \\\n    r1  = (mbedtls_mpi_uint)( r >> biL );         \\\n    r0 += c;  r1 += (r0 <  c);          \\\n    r0 += *d; r1 += (r0 < *d);          \\\n    c = r1; *(d++) = r0;\n\n#define MULADDC_X1_STOP                 \\\n}\n\n#else /* MBEDTLS_HAVE_UDBL */\n\n#define MULADDC_X1_INIT                 \\\n{                                       \\\n    mbedtls_mpi_uint s0, s1, b0, b1;              \\\n    mbedtls_mpi_uint r0, r1, rx, ry;              \\\n    b0 = ( b << biH ) >> biH;           \\\n    b1 = ( b >> biH );\n\n#define MULADDC_X1_CORE                 \\\n    s0 = ( *s << biH ) >> biH;          \\\n    s1 = ( *s >> biH ); s++;            \\\n    rx = s0 * b1; r0 = s0 * b0;         \\\n    ry = s1 * b0; r1 = s1 * b1;         \\\n    r1 += ( rx >> biH );                \\\n    r1 += ( ry >> biH );                \\\n    rx <<= biH; ry <<= biH;             \\\n    r0 += rx; r1 += (r0 < rx);          \\\n    r0 += ry; r1 += (r0 < ry);          \\\n    r0 +=  c; r1 += (r0 <  c);          \\\n    r0 += *d; r1 += (r0 < *d);          \\\n    c = r1; *(d++) = r0;\n\n#define MULADDC_X1_STOP                 \\\n}\n\n#endif /* C (longlong) */\n#endif /* C (generic)  */\n\n#if !defined(MULADDC_X2_CORE)\n#define MULADDC_X2_INIT MULADDC_X1_INIT\n#define MULADDC_X2_STOP MULADDC_X1_STOP\n#define MULADDC_X2_CORE MULADDC_X1_CORE MULADDC_X1_CORE\n#endif /* MULADDC_X2_CORE */\n\n#if !defined(MULADDC_X4_CORE)\n#define MULADDC_X4_INIT MULADDC_X2_INIT\n#define MULADDC_X4_STOP MULADDC_X2_STOP\n#define MULADDC_X4_CORE MULADDC_X2_CORE MULADDC_X2_CORE\n#endif /* MULADDC_X4_CORE */\n\n#if !defined(MULADDC_X8_CORE)\n#define MULADDC_X8_INIT MULADDC_X4_INIT\n#define MULADDC_X8_STOP MULADDC_X4_STOP\n#define MULADDC_X8_CORE MULADDC_X4_CORE MULADDC_X4_CORE\n#endif /* MULADDC_X8_CORE */\n\n/* *INDENT-ON* */\n#endif /* bn_mul.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/camellia.c",
    "content": "/*\n *  Camellia implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  The Camellia block cipher was designed by NTT and Mitsubishi Electric\n *  Corporation.\n *\n *  http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_CAMELLIA_C)\n\n#include \"mbedtls/camellia.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#if !defined(MBEDTLS_CAMELLIA_ALT)\n\nstatic const unsigned char SIGMA_CHARS[6][8] =\n{\n    { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b },\n    { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 },\n    { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe },\n    { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c },\n    { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d },\n    { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd }\n};\n\n#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY)\n\nstatic const unsigned char FSb[256] =\n{\n    112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65,\n    35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189,\n    134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26,\n    166, 225, 57, 202, 213, 71, 93, 61, 217,  1, 90, 214, 81, 86, 108, 77,\n    139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153,\n    223, 76, 203, 194, 52, 126, 118,  5, 109, 183, 169, 49, 209, 23,  4, 215,\n    20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34,\n    254, 68, 207, 178, 195, 181, 122, 145, 36,  8, 232, 168, 96, 252, 105, 80,\n    170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210,\n    16, 196,  0, 72, 163, 247, 117, 219, 138,  3, 230, 218,  9, 63, 221, 148,\n    135, 92, 131,  2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226,\n    82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46,\n    233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89,\n    120, 152,  6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250,\n    114,  7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164,\n    64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158\n};\n\n#define SBOX1(n) FSb[(n)]\n#define SBOX2(n) (unsigned char) ((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff)\n#define SBOX3(n) (unsigned char) ((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff)\n#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff]\n\n#else /* MBEDTLS_CAMELLIA_SMALL_MEMORY */\n\nstatic const unsigned char FSb[256] =\n{\n    112, 130,  44, 236, 179,  39, 192, 229, 228, 133,  87,  53, 234,  12, 174,  65,\n    35, 239, 107, 147,  69,  25, 165,  33, 237,  14,  79,  78,  29, 101, 146, 189,\n    134, 184, 175, 143, 124, 235,  31, 206,  62,  48, 220,  95,  94, 197,  11,  26,\n    166, 225,  57, 202, 213,  71,  93,  61, 217,   1,  90, 214,  81,  86, 108,  77,\n    139,  13, 154, 102, 251, 204, 176,  45, 116,  18,  43,  32, 240, 177, 132, 153,\n    223,  76, 203, 194,  52, 126, 118,   5, 109, 183, 169,  49, 209,  23,   4, 215,\n    20,  88,  58,  97, 222,  27,  17,  28,  50,  15, 156,  22,  83,  24, 242,  34,\n    254,  68, 207, 178, 195, 181, 122, 145,  36,   8, 232, 168,  96, 252, 105,  80,\n    170, 208, 160, 125, 161, 137,  98, 151,  84,  91,  30, 149, 224, 255, 100, 210,\n    16, 196,   0,  72, 163, 247, 117, 219, 138,   3, 230, 218,   9,  63, 221, 148,\n    135,  92, 131,   2, 205,  74, 144,  51, 115, 103, 246, 243, 157, 127, 191, 226,\n    82, 155, 216,  38, 200,  55, 198,  59, 129, 150, 111,  75,  19, 190,  99,  46,\n    233, 121, 167, 140, 159, 110, 188, 142,  41, 245, 249, 182,  47, 253, 180,  89,\n    120, 152,   6, 106, 231,  70, 113, 186, 212,  37, 171,  66, 136, 162, 141, 250,\n    114,   7, 185,  85, 248, 238, 172,  10,  54,  73,  42, 104,  60,  56, 241, 164,\n    64,  40, 211, 123, 187, 201,  67, 193,  21, 227, 173, 244, 119, 199, 128, 158\n};\n\nstatic const unsigned char FSb2[256] =\n{\n    224,   5,  88, 217, 103,  78, 129, 203, 201,  11, 174, 106, 213,  24,  93, 130,\n    70, 223, 214,  39, 138,  50,  75,  66, 219,  28, 158, 156,  58, 202,  37, 123,\n    13, 113,  95,  31, 248, 215,  62, 157, 124,  96, 185, 190, 188, 139,  22,  52,\n    77, 195, 114, 149, 171, 142, 186, 122, 179,   2, 180, 173, 162, 172, 216, 154,\n    23,  26,  53, 204, 247, 153,  97,  90, 232,  36,  86,  64, 225,  99,   9,  51,\n    191, 152, 151, 133, 104, 252, 236,  10, 218, 111,  83,  98, 163,  46,   8, 175,\n    40, 176, 116, 194, 189,  54,  34,  56, 100,  30,  57,  44, 166,  48, 229,  68,\n    253, 136, 159, 101, 135, 107, 244,  35,  72,  16, 209,  81, 192, 249, 210, 160,\n    85, 161,  65, 250,  67,  19, 196,  47, 168, 182,  60,  43, 193, 255, 200, 165,\n    32, 137,   0, 144,  71, 239, 234, 183,  21,   6, 205, 181,  18, 126, 187,  41,\n    15, 184,   7,   4, 155, 148,  33, 102, 230, 206, 237, 231,  59, 254, 127, 197,\n    164,  55, 177,  76, 145, 110, 141, 118,   3,  45, 222, 150,  38, 125, 198,  92,\n    211, 242,  79,  25,  63, 220, 121,  29,  82, 235, 243, 109,  94, 251, 105, 178,\n    240,  49,  12, 212, 207, 140, 226, 117, 169,  74,  87, 132,  17,  69,  27, 245,\n    228,  14, 115, 170, 241, 221,  89,  20, 108, 146,  84, 208, 120, 112, 227,  73,\n    128,  80, 167, 246, 119, 147, 134, 131,  42, 199,  91, 233, 238, 143,   1,  61\n};\n\nstatic const unsigned char FSb3[256] =\n{\n    56,  65,  22, 118, 217, 147,  96, 242, 114, 194, 171, 154, 117,   6,  87, 160,\n    145, 247, 181, 201, 162, 140, 210, 144, 246,   7, 167,  39, 142, 178,  73, 222,\n    67,  92, 215, 199,  62, 245, 143, 103,  31,  24, 110, 175,  47, 226, 133,  13,\n    83, 240, 156, 101, 234, 163, 174, 158, 236, 128,  45, 107, 168,  43,  54, 166,\n    197, 134,  77,  51, 253, 102,  88, 150,  58,   9, 149,  16, 120, 216,  66, 204,\n    239,  38, 229,  97,  26,  63,  59, 130, 182, 219, 212, 152, 232, 139,   2, 235,\n    10,  44,  29, 176, 111, 141, 136,  14,  25, 135,  78,  11, 169,  12, 121,  17,\n    127,  34, 231,  89, 225, 218,  61, 200,  18,   4, 116,  84,  48, 126, 180,  40,\n    85, 104,  80, 190, 208, 196,  49, 203,  42, 173,  15, 202, 112, 255,  50, 105,\n    8,  98,   0,  36, 209, 251, 186, 237,  69, 129, 115, 109, 132, 159, 238,  74,\n    195,  46, 193,   1, 230,  37,  72, 153, 185, 179, 123, 249, 206, 191, 223, 113,\n    41, 205, 108,  19, 100, 155,  99, 157, 192,  75, 183, 165, 137,  95, 177,  23,\n    244, 188, 211,  70, 207,  55,  94,  71, 148, 250, 252,  91, 151, 254,  90, 172,\n    60,  76,   3,  53, 243,  35, 184,  93, 106, 146, 213,  33,  68,  81, 198, 125,\n    57, 131, 220, 170, 124, 119,  86,   5,  27, 164,  21,  52,  30,  28, 248,  82,\n    32,  20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227,  64,  79\n};\n\nstatic const unsigned char FSb4[256] =\n{\n    112,  44, 179, 192, 228,  87, 234, 174,  35, 107,  69, 165, 237,  79,  29, 146,\n    134, 175, 124,  31,  62, 220,  94,  11, 166,  57, 213,  93, 217,  90,  81, 108,\n    139, 154, 251, 176, 116,  43, 240, 132, 223, 203,  52, 118, 109, 169, 209,   4,\n    20,  58, 222,  17,  50, 156,  83, 242, 254, 207, 195, 122,  36, 232,  96, 105,\n    170, 160, 161,  98,  84,  30, 224, 100,  16,   0, 163, 117, 138, 230,   9, 221,\n    135, 131, 205, 144, 115, 246, 157, 191,  82, 216, 200, 198, 129, 111,  19,  99,\n    233, 167, 159, 188,  41, 249,  47, 180, 120,   6, 231, 113, 212, 171, 136, 141,\n    114, 185, 248, 172,  54,  42,  60, 241,  64, 211, 187,  67,  21, 173, 119, 128,\n    130, 236,  39, 229, 133,  53,  12,  65, 239, 147,  25,  33,  14,  78, 101, 189,\n    184, 143, 235, 206,  48,  95, 197,  26, 225, 202,  71,  61,   1, 214,  86,  77,\n    13, 102, 204,  45,  18,  32, 177, 153,  76, 194, 126,   5, 183,  49,  23, 215,\n    88,  97,  27,  28,  15,  22,  24,  34,  68, 178, 181, 145,   8, 168, 252,  80,\n    208, 125, 137, 151,  91, 149, 255, 210, 196,  72, 247, 219,   3, 218,  63, 148,\n    92,   2,  74,  51, 103, 243, 127, 226, 155,  38,  55,  59, 150,  75, 190,  46,\n    121, 140, 110, 142, 245, 182, 253,  89, 152, 106,  70, 186,  37,  66, 162, 250,\n    7,  85, 238,  10,  73, 104,  56, 164,  40, 123, 201, 193, 227, 244, 199, 158\n};\n\n#define SBOX1(n) FSb[(n)]\n#define SBOX2(n) FSb2[(n)]\n#define SBOX3(n) FSb3[(n)]\n#define SBOX4(n) FSb4[(n)]\n\n#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */\n\nstatic const unsigned char shifts[2][4][4] =\n{\n    {\n        { 1, 1, 1, 1 }, /* KL */\n        { 0, 0, 0, 0 }, /* KR */\n        { 1, 1, 1, 1 }, /* KA */\n        { 0, 0, 0, 0 }  /* KB */\n    },\n    {\n        { 1, 0, 1, 1 }, /* KL */\n        { 1, 1, 0, 1 }, /* KR */\n        { 1, 1, 1, 0 }, /* KA */\n        { 1, 1, 0, 1 }  /* KB */\n    }\n};\n\nstatic const signed char indexes[2][4][20] =\n{\n    {\n        {  0,  1,  2,  3,  8,  9, 10, 11, 38, 39,\n           36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */\n        { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */\n        {  4,  5,  6,  7, 12, 13, 14, 15, 16, 17,\n           18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */\n        { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }  /* KB -> RK */\n    },\n    {\n        {  0,  1,  2,  3, 61, 62, 63, 60, -1, -1,\n           -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */\n        { -1, -1, -1, -1,  8,  9, 10, 11, 16, 17,\n          18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */\n        { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59,\n          56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */\n        {  4,  5,  6,  7, 65, 66, 67, 64, 20, 21,\n           22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */\n    }\n};\n\nstatic const signed char transposes[2][20] =\n{\n    {\n        21, 22, 23, 20,\n        -1, -1, -1, -1,\n        18, 19, 16, 17,\n        11,  8,  9, 10,\n        15, 12, 13, 14\n    },\n    {\n        25, 26, 27, 24,\n        29, 30, 31, 28,\n        18, 19, 16, 17,\n        -1, -1, -1, -1,\n        -1, -1, -1, -1\n    }\n};\n\n/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */\n#define ROTL(DEST, SRC, SHIFT)                                      \\\n    {                                                                   \\\n        (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT));   \\\n        (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT));   \\\n        (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT));   \\\n        (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT));   \\\n    }\n\n#define FL(XL, XR, KL, KR)                                          \\\n    {                                                                   \\\n        (XR) = ((((XL) &(KL)) << 1) | (((XL) &(KL)) >> 31)) ^ (XR);   \\\n        (XL) = ((XR) | (KR)) ^ (XL);                                    \\\n    }\n\n#define FLInv(YL, YR, KL, KR)                                       \\\n    {                                                                   \\\n        (YL) = ((YR) | (KR)) ^ (YL);                                    \\\n        (YR) = ((((YL) &(KL)) << 1) | (((YL) &(KL)) >> 31)) ^ (YR);   \\\n    }\n\n#define SHIFT_AND_PLACE(INDEX, OFFSET)                      \\\n    {                                                           \\\n        TK[0] = KC[(OFFSET) * 4 + 0];                           \\\n        TK[1] = KC[(OFFSET) * 4 + 1];                           \\\n        TK[2] = KC[(OFFSET) * 4 + 2];                           \\\n        TK[3] = KC[(OFFSET) * 4 + 3];                           \\\n                                                            \\\n        for (i = 1; i <= 4; i++)                               \\\n        if (shifts[(INDEX)][(OFFSET)][i -1])               \\\n        ROTL(TK + i * 4, TK, (15 * i) % 32);          \\\n                                                            \\\n        for (i = 0; i < 20; i++)                               \\\n        if (indexes[(INDEX)][(OFFSET)][i] != -1) {         \\\n            RK[indexes[(INDEX)][(OFFSET)][i]] = TK[i];    \\\n        }                                                   \\\n    }\n\nstatic void camellia_feistel(const uint32_t x[2], const uint32_t k[2],\n                             uint32_t z[2])\n{\n    uint32_t I0, I1;\n    I0 = x[0] ^ k[0];\n    I1 = x[1] ^ k[1];\n\n    I0 = ((uint32_t) SBOX1(MBEDTLS_BYTE_3(I0)) << 24) |\n         ((uint32_t) SBOX2(MBEDTLS_BYTE_2(I0)) << 16) |\n         ((uint32_t) SBOX3(MBEDTLS_BYTE_1(I0)) <<  8) |\n         ((uint32_t) SBOX4(MBEDTLS_BYTE_0(I0)));\n    I1 = ((uint32_t) SBOX2(MBEDTLS_BYTE_3(I1)) << 24) |\n         ((uint32_t) SBOX3(MBEDTLS_BYTE_2(I1)) << 16) |\n         ((uint32_t) SBOX4(MBEDTLS_BYTE_1(I1)) <<  8) |\n         ((uint32_t) SBOX1(MBEDTLS_BYTE_0(I1)));\n\n    I0 ^= (I1 << 8) | (I1 >> 24);\n    I1 ^= (I0 << 16) | (I0 >> 16);\n    I0 ^= (I1 >> 8) | (I1 << 24);\n    I1 ^= (I0 >> 8) | (I0 << 24);\n\n    z[0] ^= I1;\n    z[1] ^= I0;\n}\n\nvoid mbedtls_camellia_init(mbedtls_camellia_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_camellia_context));\n}\n\nvoid mbedtls_camellia_free(mbedtls_camellia_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_camellia_context));\n}\n\n/*\n * Camellia key schedule (encryption)\n */\nint mbedtls_camellia_setkey_enc(mbedtls_camellia_context *ctx,\n                                const unsigned char *key,\n                                unsigned int keybits)\n{\n    int idx;\n    size_t i;\n    uint32_t *RK;\n    unsigned char t[64];\n    uint32_t SIGMA[6][2];\n    uint32_t KC[16];\n    uint32_t TK[20];\n\n    RK = ctx->rk;\n\n    memset(t, 0, 64);\n    memset(RK, 0, sizeof(ctx->rk));\n\n    switch (keybits) {\n        case 128: ctx->nr = 3; idx = 0; break;\n        case 192:\n        case 256: ctx->nr = 4; idx = 1; break;\n        default: return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;\n    }\n\n    for (i = 0; i < keybits / 8; ++i) {\n        t[i] = key[i];\n    }\n\n    if (keybits == 192) {\n        for (i = 0; i < 8; i++) {\n            t[24 + i] = ~t[16 + i];\n        }\n    }\n\n    /*\n     * Prepare SIGMA values\n     */\n    for (i = 0; i < 6; i++) {\n        SIGMA[i][0] = MBEDTLS_GET_UINT32_BE(SIGMA_CHARS[i], 0);\n        SIGMA[i][1] = MBEDTLS_GET_UINT32_BE(SIGMA_CHARS[i], 4);\n    }\n\n    /*\n     * Key storage in KC\n     * Order: KL, KR, KA, KB\n     */\n    memset(KC, 0, sizeof(KC));\n\n    /* Store KL, KR */\n    for (i = 0; i < 8; i++) {\n        KC[i] = MBEDTLS_GET_UINT32_BE(t, i * 4);\n    }\n\n    /* Generate KA */\n    for (i = 0; i < 4; ++i) {\n        KC[8 + i] = KC[i] ^ KC[4 + i];\n    }\n\n    camellia_feistel(KC + 8, SIGMA[0], KC + 10);\n    camellia_feistel(KC + 10, SIGMA[1], KC + 8);\n\n    for (i = 0; i < 4; ++i) {\n        KC[8 + i] ^= KC[i];\n    }\n\n    camellia_feistel(KC + 8, SIGMA[2], KC + 10);\n    camellia_feistel(KC + 10, SIGMA[3], KC + 8);\n\n    if (keybits > 128) {\n        /* Generate KB */\n        for (i = 0; i < 4; ++i) {\n            KC[12 + i] = KC[4 + i] ^ KC[8 + i];\n        }\n\n        camellia_feistel(KC + 12, SIGMA[4], KC + 14);\n        camellia_feistel(KC + 14, SIGMA[5], KC + 12);\n    }\n\n    /*\n     * Generating subkeys\n     */\n\n    /* Manipulating KL */\n    SHIFT_AND_PLACE(idx, 0);\n\n    /* Manipulating KR */\n    if (keybits > 128) {\n        SHIFT_AND_PLACE(idx, 1);\n    }\n\n    /* Manipulating KA */\n    SHIFT_AND_PLACE(idx, 2);\n\n    /* Manipulating KB */\n    if (keybits > 128) {\n        SHIFT_AND_PLACE(idx, 3);\n    }\n\n    /* Do transpositions */\n    for (i = 0; i < 20; i++) {\n        if (transposes[idx][i] != -1) {\n            RK[32 + 12 * idx + i] = RK[transposes[idx][i]];\n        }\n    }\n\n    return 0;\n}\n\n/*\n * Camellia key schedule (decryption)\n */\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\nint mbedtls_camellia_setkey_dec(mbedtls_camellia_context *ctx,\n                                const unsigned char *key,\n                                unsigned int keybits)\n{\n    int idx, ret;\n    size_t i;\n    mbedtls_camellia_context cty;\n    uint32_t *RK;\n    uint32_t *SK;\n\n    mbedtls_camellia_init(&cty);\n\n    /* Also checks keybits */\n    if ((ret = mbedtls_camellia_setkey_enc(&cty, key, keybits)) != 0) {\n        goto exit;\n    }\n\n    ctx->nr = cty.nr;\n    idx = (ctx->nr == 4);\n\n    RK = ctx->rk;\n    SK = cty.rk + 24 * 2 + 8 * idx * 2;\n\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n\n    for (i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4) {\n        *RK++ = *SK++;\n        *RK++ = *SK++;\n    }\n\n    SK -= 2;\n\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n    *RK++ = *SK++;\n\nexit:\n    mbedtls_camellia_free(&cty);\n\n    return ret;\n}\n#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */\n\n/*\n * Camellia-ECB block encryption/decryption\n */\nint mbedtls_camellia_crypt_ecb(mbedtls_camellia_context *ctx,\n                               int mode,\n                               const unsigned char input[16],\n                               unsigned char output[16])\n{\n    int NR;\n    uint32_t *RK, X[4];\n    if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) {\n        return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;\n    }\n\n    ((void) mode);\n\n    NR = ctx->nr;\n    RK = ctx->rk;\n\n    X[0] = MBEDTLS_GET_UINT32_BE(input,  0);\n    X[1] = MBEDTLS_GET_UINT32_BE(input,  4);\n    X[2] = MBEDTLS_GET_UINT32_BE(input,  8);\n    X[3] = MBEDTLS_GET_UINT32_BE(input, 12);\n\n    X[0] ^= *RK++;\n    X[1] ^= *RK++;\n    X[2] ^= *RK++;\n    X[3] ^= *RK++;\n\n    while (NR) {\n        --NR;\n        camellia_feistel(X, RK, X + 2);\n        RK += 2;\n        camellia_feistel(X + 2, RK, X);\n        RK += 2;\n        camellia_feistel(X, RK, X + 2);\n        RK += 2;\n        camellia_feistel(X + 2, RK, X);\n        RK += 2;\n        camellia_feistel(X, RK, X + 2);\n        RK += 2;\n        camellia_feistel(X + 2, RK, X);\n        RK += 2;\n\n        if (NR) {\n            FL(X[0], X[1], RK[0], RK[1]);\n            RK += 2;\n            FLInv(X[2], X[3], RK[0], RK[1]);\n            RK += 2;\n        }\n    }\n\n    X[2] ^= *RK++;\n    X[3] ^= *RK++;\n    X[0] ^= *RK++;\n    X[1] ^= *RK++;\n\n    MBEDTLS_PUT_UINT32_BE(X[2], output,  0);\n    MBEDTLS_PUT_UINT32_BE(X[3], output,  4);\n    MBEDTLS_PUT_UINT32_BE(X[0], output,  8);\n    MBEDTLS_PUT_UINT32_BE(X[1], output, 12);\n\n    return 0;\n}\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n/*\n * Camellia-CBC buffer encryption/decryption\n */\nint mbedtls_camellia_crypt_cbc(mbedtls_camellia_context *ctx,\n                               int mode,\n                               size_t length,\n                               unsigned char iv[16],\n                               const unsigned char *input,\n                               unsigned char *output)\n{\n    unsigned char temp[16];\n    if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) {\n        return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;\n    }\n\n    if (length % 16) {\n        return MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH;\n    }\n\n    if (mode == MBEDTLS_CAMELLIA_DECRYPT) {\n        while (length > 0) {\n            memcpy(temp, input, 16);\n            mbedtls_camellia_crypt_ecb(ctx, mode, input, output);\n\n            mbedtls_xor(output, output, iv, 16);\n\n            memcpy(iv, temp, 16);\n\n            input  += 16;\n            output += 16;\n            length -= 16;\n        }\n    } else {\n        while (length > 0) {\n            mbedtls_xor(output, input, iv, 16);\n\n            mbedtls_camellia_crypt_ecb(ctx, mode, output, output);\n            memcpy(iv, output, 16);\n\n            input  += 16;\n            output += 16;\n            length -= 16;\n        }\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n/*\n * Camellia-CFB128 buffer encryption/decryption\n */\nint mbedtls_camellia_crypt_cfb128(mbedtls_camellia_context *ctx,\n                                  int mode,\n                                  size_t length,\n                                  size_t *iv_off,\n                                  unsigned char iv[16],\n                                  const unsigned char *input,\n                                  unsigned char *output)\n{\n    int c;\n    size_t n;\n    if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) {\n        return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;\n    }\n\n    n = *iv_off;\n    if (n >= 16) {\n        return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;\n    }\n\n    if (mode == MBEDTLS_CAMELLIA_DECRYPT) {\n        while (length--) {\n            if (n == 0) {\n                mbedtls_camellia_crypt_ecb(ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv);\n            }\n\n            c = *input++;\n            *output++ = (unsigned char) (c ^ iv[n]);\n            iv[n] = (unsigned char) c;\n\n            n = (n + 1) & 0x0F;\n        }\n    } else {\n        while (length--) {\n            if (n == 0) {\n                mbedtls_camellia_crypt_ecb(ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv);\n            }\n\n            iv[n] = *output++ = (unsigned char) (iv[n] ^ *input++);\n\n            n = (n + 1) & 0x0F;\n        }\n    }\n\n    *iv_off = n;\n\n    return 0;\n}\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n/*\n * Camellia-CTR buffer encryption/decryption\n */\nint mbedtls_camellia_crypt_ctr(mbedtls_camellia_context *ctx,\n                               size_t length,\n                               size_t *nc_off,\n                               unsigned char nonce_counter[16],\n                               unsigned char stream_block[16],\n                               const unsigned char *input,\n                               unsigned char *output)\n{\n    int c, i;\n    size_t n;\n\n    n = *nc_off;\n    if (n >= 16) {\n        return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;\n    }\n\n    while (length--) {\n        if (n == 0) {\n            mbedtls_camellia_crypt_ecb(ctx, MBEDTLS_CAMELLIA_ENCRYPT, nonce_counter,\n                                       stream_block);\n\n            for (i = 16; i > 0; i--) {\n                if (++nonce_counter[i - 1] != 0) {\n                    break;\n                }\n            }\n        }\n        c = *input++;\n        *output++ = (unsigned char) (c ^ stream_block[n]);\n\n        n = (n + 1) & 0x0F;\n    }\n\n    *nc_off = n;\n\n    return 0;\n}\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n#endif /* !MBEDTLS_CAMELLIA_ALT */\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/*\n * Camellia test vectors from:\n *\n * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html:\n *   http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt\n *   http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt\n *                      (For each bitlength: Key 0, Nr 39)\n */\n#define CAMELLIA_TESTS_ECB  2\n\nstatic const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] =\n{\n    {\n        { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,\n          0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },\n        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }\n    },\n    {\n        { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,\n          0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,\n          0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },\n        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }\n    },\n    {\n        { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,\n          0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,\n          0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,\n          0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },\n        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }\n    },\n};\n\nstatic const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] =\n{\n    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,\n      0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },\n    { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }\n};\n\nstatic const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] =\n{\n    {\n        { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,\n          0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },\n        { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE,\n          0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 }\n    },\n    {\n        { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,\n          0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },\n        { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9,\n          0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 }\n    },\n    {\n        { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,\n          0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },\n        { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C,\n          0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 }\n    }\n};\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n#define CAMELLIA_TESTS_CBC  3\n\nstatic const unsigned char camellia_test_cbc_key[3][32] =\n{\n    { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,\n      0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }\n    ,\n    { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,\n      0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,\n      0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }\n    ,\n    { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,\n      0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,\n      0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,\n      0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }\n};\n\nstatic const unsigned char camellia_test_cbc_iv[16] =\n\n{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }\n;\n\nstatic const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] =\n{\n    { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,\n      0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A },\n    { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,\n      0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 },\n    { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,\n      0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF }\n\n};\n\nstatic const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] =\n{\n    {\n        { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0,\n          0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB },\n        { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78,\n          0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 },\n        { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B,\n          0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 }\n    },\n    {\n        { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2,\n          0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 },\n        { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42,\n          0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 },\n        { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8,\n          0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 }\n    },\n    {\n        { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A,\n          0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA },\n        { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40,\n          0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 },\n        { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA,\n          0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 }\n    }\n};\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n/*\n * Camellia-CTR test vectors from:\n *\n * http://www.faqs.org/rfcs/rfc5528.html\n */\n\nstatic const unsigned char camellia_test_ctr_key[3][16] =\n{\n    { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,\n      0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },\n    { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,\n      0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },\n    { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,\n      0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }\n};\n\nstatic const unsigned char camellia_test_ctr_nonce_counter[3][16] =\n{\n    { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },\n    { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,\n      0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },\n    { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,\n      0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }\n};\n\nstatic const unsigned char camellia_test_ctr_pt[3][48] =\n{\n    { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,\n      0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },\n\n    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,\n      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,\n      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },\n\n    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,\n      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,\n      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,\n      0x20, 0x21, 0x22, 0x23 }\n};\n\nstatic const unsigned char camellia_test_ctr_ct[3][48] =\n{\n    { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A,\n      0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F },\n    { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4,\n      0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44,\n      0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7,\n      0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 },\n    { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88,\n      0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73,\n      0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1,\n      0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD,\n      0xDF, 0x50, 0x86, 0x96 }\n};\n\nstatic const int camellia_test_ctr_len[3] =\n{ 16, 32, 36 };\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n/*\n * Checkup routine\n */\nint mbedtls_camellia_self_test(int verbose)\n{\n    int i, j, u, v;\n    unsigned char key[32];\n    unsigned char buf[64];\n    unsigned char src[16];\n    unsigned char dst[16];\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    unsigned char iv[16];\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    size_t offset, len;\n    unsigned char nonce_counter[16];\n    unsigned char stream_block[16];\n#endif\n    int ret = 1;\n\n    mbedtls_camellia_context ctx;\n\n    mbedtls_camellia_init(&ctx);\n    memset(key, 0, 32);\n\n    for (j = 0; j < 6; j++) {\n        u = j >> 1;\n        v = j & 1;\n\n        if (verbose != 0) {\n            mbedtls_printf(\"  CAMELLIA-ECB-%3d (%s): \", 128 + u * 64,\n                           (v == MBEDTLS_CAMELLIA_DECRYPT) ? \"dec\" : \"enc\");\n        }\n\n#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n        if (v == MBEDTLS_CAMELLIA_DECRYPT) {\n            if (verbose != 0) {\n                mbedtls_printf(\"skipped\\n\");\n            }\n            continue;\n        }\n#endif\n\n        for (i = 0; i < CAMELLIA_TESTS_ECB; i++) {\n            memcpy(key, camellia_test_ecb_key[u][i], 16 + 8 * u);\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n            if (v == MBEDTLS_CAMELLIA_DECRYPT) {\n                mbedtls_camellia_setkey_dec(&ctx, key, 128 + u * 64);\n                memcpy(src, camellia_test_ecb_cipher[u][i], 16);\n                memcpy(dst, camellia_test_ecb_plain[i], 16);\n            } else\n#endif\n            { /* MBEDTLS_CAMELLIA_ENCRYPT */\n                mbedtls_camellia_setkey_enc(&ctx, key, 128 + u * 64);\n                memcpy(src, camellia_test_ecb_plain[i], 16);\n                memcpy(dst, camellia_test_ecb_cipher[u][i], 16);\n            }\n\n            mbedtls_camellia_crypt_ecb(&ctx, v, src, buf);\n\n            if (memcmp(buf, dst, 16) != 0) {\n                if (verbose != 0) {\n                    mbedtls_printf(\"failed\\n\");\n                }\n                goto exit;\n            }\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    /*\n     * CBC mode\n     */\n    for (j = 0; j < 6; j++) {\n        u = j >> 1;\n        v = j  & 1;\n\n        if (verbose != 0) {\n            mbedtls_printf(\"  CAMELLIA-CBC-%3d (%s): \", 128 + u * 64,\n                           (v == MBEDTLS_CAMELLIA_DECRYPT) ? \"dec\" : \"enc\");\n        }\n\n        memcpy(src, camellia_test_cbc_iv, 16);\n        memcpy(dst, camellia_test_cbc_iv, 16);\n        memcpy(key, camellia_test_cbc_key[u], 16 + 8 * u);\n\n        if (v == MBEDTLS_CAMELLIA_DECRYPT) {\n            mbedtls_camellia_setkey_dec(&ctx, key, 128 + u * 64);\n        } else {\n            mbedtls_camellia_setkey_enc(&ctx, key, 128 + u * 64);\n        }\n\n        for (i = 0; i < CAMELLIA_TESTS_CBC; i++) {\n\n            if (v == MBEDTLS_CAMELLIA_DECRYPT) {\n                memcpy(iv, src, 16);\n                memcpy(src, camellia_test_cbc_cipher[u][i], 16);\n                memcpy(dst, camellia_test_cbc_plain[i], 16);\n            } else { /* MBEDTLS_CAMELLIA_ENCRYPT */\n                memcpy(iv, dst, 16);\n                memcpy(src, camellia_test_cbc_plain[i], 16);\n                memcpy(dst, camellia_test_cbc_cipher[u][i], 16);\n            }\n\n            mbedtls_camellia_crypt_cbc(&ctx, v, 16, iv, src, buf);\n\n            if (memcmp(buf, dst, 16) != 0) {\n                if (verbose != 0) {\n                    mbedtls_printf(\"failed\\n\");\n                }\n                goto exit;\n            }\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    /*\n     * CTR mode\n     */\n    for (i = 0; i < 6; i++) {\n        u = i >> 1;\n        v = i  & 1;\n\n        if (verbose != 0) {\n            mbedtls_printf(\"  CAMELLIA-CTR-128 (%s): \",\n                           (v == MBEDTLS_CAMELLIA_DECRYPT) ? \"dec\" : \"enc\");\n        }\n\n        memcpy(nonce_counter, camellia_test_ctr_nonce_counter[u], 16);\n        memcpy(key, camellia_test_ctr_key[u], 16);\n\n        offset = 0;\n        mbedtls_camellia_setkey_enc(&ctx, key, 128);\n\n        if (v == MBEDTLS_CAMELLIA_DECRYPT) {\n            len = camellia_test_ctr_len[u];\n            memcpy(buf, camellia_test_ctr_ct[u], len);\n\n            mbedtls_camellia_crypt_ctr(&ctx, len, &offset, nonce_counter, stream_block,\n                                       buf, buf);\n\n            if (memcmp(buf, camellia_test_ctr_pt[u], len) != 0) {\n                if (verbose != 0) {\n                    mbedtls_printf(\"failed\\n\");\n                }\n                goto exit;\n            }\n        } else {\n            len = camellia_test_ctr_len[u];\n            memcpy(buf, camellia_test_ctr_pt[u], len);\n\n            mbedtls_camellia_crypt_ctr(&ctx, len, &offset, nonce_counter, stream_block,\n                                       buf, buf);\n\n            if (memcmp(buf, camellia_test_ctr_ct[u], len) != 0) {\n                if (verbose != 0) {\n                    mbedtls_printf(\"failed\\n\");\n                }\n                goto exit;\n            }\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n    ret = 0;\n\nexit:\n    mbedtls_camellia_free(&ctx);\n    return ret;\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_CAMELLIA_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ccm.c",
    "content": "/*\n *  NIST SP800-38C compliant CCM implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n * Definition of CCM:\n * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf\n * RFC 3610 \"Counter with CBC-MAC (CCM)\"\n *\n * Related:\n * RFC 5116 \"An Interface and Algorithms for Authenticated Encryption\"\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_CCM_C)\n\n#include \"mbedtls/ccm.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/constant_time.h\"\n\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n#include \"block_cipher_internal.h\"\n#endif\n\n#include <string.h>\n\n#if defined(MBEDTLS_PLATFORM_C)\n#include \"mbedtls/platform.h\"\n#else\n#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)\n#include <stdio.h>\n#define mbedtls_printf printf\n#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */\n#endif /* MBEDTLS_PLATFORM_C */\n\n#if !defined(MBEDTLS_CCM_ALT)\n\n\n/*\n * Initialize context\n */\nvoid mbedtls_ccm_init(mbedtls_ccm_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_ccm_context));\n}\n\nint mbedtls_ccm_setkey(mbedtls_ccm_context *ctx,\n                       mbedtls_cipher_id_t cipher,\n                       const unsigned char *key,\n                       unsigned int keybits)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n    mbedtls_block_cipher_free(&ctx->block_cipher_ctx);\n\n    if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) {\n        return MBEDTLS_ERR_CCM_BAD_INPUT;\n    }\n\n    if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) {\n        return MBEDTLS_ERR_CCM_BAD_INPUT;\n    }\n#else\n    const mbedtls_cipher_info_t *cipher_info;\n\n    cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,\n                                                  MBEDTLS_MODE_ECB);\n    if (cipher_info == NULL) {\n        return MBEDTLS_ERR_CCM_BAD_INPUT;\n    }\n\n    if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {\n        return MBEDTLS_ERR_CCM_BAD_INPUT;\n    }\n\n    mbedtls_cipher_free(&ctx->cipher_ctx);\n\n    if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,\n                                     MBEDTLS_ENCRYPT)) != 0) {\n        return ret;\n    }\n#endif\n\n    return ret;\n}\n\n/*\n * Free context\n */\nvoid mbedtls_ccm_free(mbedtls_ccm_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n    mbedtls_block_cipher_free(&ctx->block_cipher_ctx);\n#else\n    mbedtls_cipher_free(&ctx->cipher_ctx);\n#endif\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ccm_context));\n}\n\n#define CCM_STATE__CLEAR                0\n#define CCM_STATE__STARTED              (1 << 0)\n#define CCM_STATE__LENGTHS_SET          (1 << 1)\n#define CCM_STATE__AUTH_DATA_STARTED    (1 << 2)\n#define CCM_STATE__AUTH_DATA_FINISHED   (1 << 3)\n#define CCM_STATE__ERROR                (1 << 4)\n\n/*\n * Encrypt or decrypt a partial block with CTR\n */\nstatic int mbedtls_ccm_crypt(mbedtls_ccm_context *ctx,\n                             size_t offset, size_t use_len,\n                             const unsigned char *input,\n                             unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char tmp_buf[16] = { 0 };\n\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n    ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->ctr, tmp_buf);\n#else\n    size_t olen = 0;\n    ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->ctr, 16, tmp_buf, &olen);\n#endif\n    if (ret != 0) {\n        ctx->state |= CCM_STATE__ERROR;\n        mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf));\n        return ret;\n    }\n\n    mbedtls_xor(output, input, tmp_buf + offset, use_len);\n\n    mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf));\n    return ret;\n}\n\nstatic void mbedtls_ccm_clear_state(mbedtls_ccm_context *ctx)\n{\n    ctx->state = CCM_STATE__CLEAR;\n    memset(ctx->y, 0, 16);\n    memset(ctx->ctr, 0, 16);\n}\n\nstatic int ccm_calculate_first_block_if_ready(mbedtls_ccm_context *ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char i;\n    size_t len_left;\n#if !defined(MBEDTLS_BLOCK_CIPHER_C)\n    size_t olen;\n#endif\n\n    /* length calculation can be done only after both\n     * mbedtls_ccm_starts() and mbedtls_ccm_set_lengths() have been executed\n     */\n    if (!(ctx->state & CCM_STATE__STARTED) || !(ctx->state & CCM_STATE__LENGTHS_SET)) {\n        return 0;\n    }\n\n    /* CCM expects non-empty tag.\n     * CCM* allows empty tag. For CCM* without tag, the tag calculation is skipped.\n     */\n    if (ctx->tag_len == 0) {\n        if (ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT || ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) {\n            ctx->plaintext_len = 0;\n            return 0;\n        } else {\n            return MBEDTLS_ERR_CCM_BAD_INPUT;\n        }\n    }\n\n    /*\n     * First block:\n     * 0        .. 0        flags\n     * 1        .. iv_len   nonce (aka iv)  - set by: mbedtls_ccm_starts()\n     * iv_len+1 .. 15       length\n     *\n     * With flags as (bits):\n     * 7        0\n     * 6        add present?\n     * 5 .. 3   (t - 2) / 2\n     * 2 .. 0   q - 1\n     */\n    ctx->y[0] |= (ctx->add_len > 0) << 6;\n    ctx->y[0] |= ((ctx->tag_len - 2) / 2) << 3;\n    ctx->y[0] |= ctx->q - 1;\n\n    for (i = 0, len_left = ctx->plaintext_len; i < ctx->q; i++, len_left >>= 8) {\n        ctx->y[15-i] = MBEDTLS_BYTE_0(len_left);\n    }\n\n    if (len_left > 0) {\n        ctx->state |= CCM_STATE__ERROR;\n        return MBEDTLS_ERR_CCM_BAD_INPUT;\n    }\n\n    /* Start CBC-MAC with first block*/\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n    ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y);\n#else\n    ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen);\n#endif\n    if (ret != 0) {\n        ctx->state |= CCM_STATE__ERROR;\n        return ret;\n    }\n\n    return 0;\n}\n\nint mbedtls_ccm_starts(mbedtls_ccm_context *ctx,\n                       int mode,\n                       const unsigned char *iv,\n                       size_t iv_len)\n{\n    /* Also implies q is within bounds */\n    if (iv_len < 7 || iv_len > 13) {\n        return MBEDTLS_ERR_CCM_BAD_INPUT;\n    }\n\n    ctx->mode = mode;\n    ctx->q = 16 - 1 - (unsigned char) iv_len;\n\n    /*\n     * Prepare counter block for encryption:\n     * 0        .. 0        flags\n     * 1        .. iv_len   nonce (aka iv)\n     * iv_len+1 .. 15       counter (initially 1)\n     *\n     * With flags as (bits):\n     * 7 .. 3   0\n     * 2 .. 0   q - 1\n     */\n    memset(ctx->ctr, 0, 16);\n    ctx->ctr[0] = ctx->q - 1;\n    memcpy(ctx->ctr + 1, iv, iv_len);\n    memset(ctx->ctr + 1 + iv_len, 0, ctx->q);\n    ctx->ctr[15] = 1;\n\n    /*\n     * See ccm_calculate_first_block_if_ready() for block layout description\n     */\n    memcpy(ctx->y + 1, iv, iv_len);\n\n    ctx->state |= CCM_STATE__STARTED;\n    return ccm_calculate_first_block_if_ready(ctx);\n}\n\nint mbedtls_ccm_set_lengths(mbedtls_ccm_context *ctx,\n                            size_t total_ad_len,\n                            size_t plaintext_len,\n                            size_t tag_len)\n{\n    /*\n     * Check length requirements: SP800-38C A.1\n     * Additional requirement: a < 2^16 - 2^8 to simplify the code.\n     * 'length' checked later (when writing it to the first block)\n     *\n     * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4).\n     */\n    if (tag_len == 2 || tag_len > 16 || tag_len % 2 != 0) {\n        return MBEDTLS_ERR_CCM_BAD_INPUT;\n    }\n\n    if (total_ad_len >= 0xFF00) {\n        return MBEDTLS_ERR_CCM_BAD_INPUT;\n    }\n\n    ctx->plaintext_len = plaintext_len;\n    ctx->add_len = total_ad_len;\n    ctx->tag_len = tag_len;\n    ctx->processed = 0;\n\n    ctx->state |= CCM_STATE__LENGTHS_SET;\n    return ccm_calculate_first_block_if_ready(ctx);\n}\n\nint mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx,\n                          const unsigned char *add,\n                          size_t add_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t use_len, offset;\n#if !defined(MBEDTLS_BLOCK_CIPHER_C)\n    size_t olen;\n#endif\n\n    if (ctx->state & CCM_STATE__ERROR) {\n        return MBEDTLS_ERR_CCM_BAD_INPUT;\n    }\n\n    if (add_len > 0) {\n        if (ctx->state & CCM_STATE__AUTH_DATA_FINISHED) {\n            return MBEDTLS_ERR_CCM_BAD_INPUT;\n        }\n\n        if (!(ctx->state & CCM_STATE__AUTH_DATA_STARTED)) {\n            if (add_len > ctx->add_len) {\n                return MBEDTLS_ERR_CCM_BAD_INPUT;\n            }\n\n            ctx->y[0] ^= (unsigned char) ((ctx->add_len >> 8) & 0xFF);\n            ctx->y[1] ^= (unsigned char) ((ctx->add_len) & 0xFF);\n\n            ctx->state |= CCM_STATE__AUTH_DATA_STARTED;\n        } else if (ctx->processed + add_len > ctx->add_len) {\n            return MBEDTLS_ERR_CCM_BAD_INPUT;\n        }\n\n        while (add_len > 0) {\n            offset = (ctx->processed + 2) % 16; /* account for y[0] and y[1]\n                                                 * holding total auth data length */\n            use_len = 16 - offset;\n\n            if (use_len > add_len) {\n                use_len = add_len;\n            }\n\n            mbedtls_xor(ctx->y + offset, ctx->y + offset, add, use_len);\n\n            ctx->processed += use_len;\n            add_len -= use_len;\n            add += use_len;\n\n            if (use_len + offset == 16 || ctx->processed == ctx->add_len) {\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n                ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y);\n#else\n                ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen);\n#endif\n                if (ret != 0) {\n                    ctx->state |= CCM_STATE__ERROR;\n                    return ret;\n                }\n            }\n        }\n\n        if (ctx->processed == ctx->add_len) {\n            ctx->state |= CCM_STATE__AUTH_DATA_FINISHED;\n            ctx->processed = 0; // prepare for mbedtls_ccm_update()\n        }\n    }\n\n    return 0;\n}\n\nint mbedtls_ccm_update(mbedtls_ccm_context *ctx,\n                       const unsigned char *input, size_t input_len,\n                       unsigned char *output, size_t output_size,\n                       size_t *output_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char i;\n    size_t use_len, offset;\n#if !defined(MBEDTLS_BLOCK_CIPHER_C)\n    size_t olen;\n#endif\n\n    unsigned char local_output[16];\n\n    if (ctx->state & CCM_STATE__ERROR) {\n        return MBEDTLS_ERR_CCM_BAD_INPUT;\n    }\n\n    /* Check against plaintext length only if performing operation with\n     * authentication\n     */\n    if (ctx->tag_len != 0 && ctx->processed + input_len > ctx->plaintext_len) {\n        return MBEDTLS_ERR_CCM_BAD_INPUT;\n    }\n\n    if (output_size < input_len) {\n        return MBEDTLS_ERR_CCM_BAD_INPUT;\n    }\n    *output_len = input_len;\n\n    ret = 0;\n\n    while (input_len > 0) {\n        offset = ctx->processed % 16;\n\n        use_len = 16 - offset;\n\n        if (use_len > input_len) {\n            use_len = input_len;\n        }\n\n        ctx->processed += use_len;\n\n        if (ctx->mode == MBEDTLS_CCM_ENCRYPT || \\\n            ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT) {\n            mbedtls_xor(ctx->y + offset, ctx->y + offset, input, use_len);\n\n            if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) {\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n                ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y);\n#else\n                ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen);\n#endif\n                if (ret != 0) {\n                    ctx->state |= CCM_STATE__ERROR;\n                    goto exit;\n                }\n            }\n\n            ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, output);\n            if (ret != 0) {\n                goto exit;\n            }\n        }\n\n        if (ctx->mode == MBEDTLS_CCM_DECRYPT || \\\n            ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) {\n            /* Since output may be in shared memory, we cannot be sure that\n             * it will contain what we wrote to it. Therefore, we should avoid using\n             * it as input to any operations.\n             * Write decrypted data to local_output to avoid using output variable as\n             * input in the XOR operation for Y.\n             */\n            ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, local_output);\n            if (ret != 0) {\n                goto exit;\n            }\n\n            mbedtls_xor(ctx->y + offset, ctx->y + offset, local_output, use_len);\n\n            memcpy(output, local_output, use_len);\n\n            if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) {\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n                ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y);\n#else\n                ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen);\n#endif\n                if (ret != 0) {\n                    ctx->state |= CCM_STATE__ERROR;\n                    goto exit;\n                }\n            }\n        }\n\n        if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) {\n            for (i = 0; i < ctx->q; i++) {\n                if (++(ctx->ctr)[15-i] != 0) {\n                    break;\n                }\n            }\n        }\n\n        input_len -= use_len;\n        input += use_len;\n        output += use_len;\n    }\n\nexit:\n    mbedtls_platform_zeroize(local_output, 16);\n\n    return ret;\n}\n\nint mbedtls_ccm_finish(mbedtls_ccm_context *ctx,\n                       unsigned char *tag, size_t tag_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char i;\n\n    if (ctx->state & CCM_STATE__ERROR) {\n        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    }\n\n    if (ctx->add_len > 0 && !(ctx->state & CCM_STATE__AUTH_DATA_FINISHED)) {\n        return MBEDTLS_ERR_CCM_BAD_INPUT;\n    }\n\n    if (ctx->plaintext_len > 0 && ctx->processed != ctx->plaintext_len) {\n        return MBEDTLS_ERR_CCM_BAD_INPUT;\n    }\n\n    /*\n     * Authentication: reset counter and crypt/mask internal tag\n     */\n    for (i = 0; i < ctx->q; i++) {\n        ctx->ctr[15-i] = 0;\n    }\n\n    ret = mbedtls_ccm_crypt(ctx, 0, 16, ctx->y, ctx->y);\n    if (ret != 0) {\n        return ret;\n    }\n    if (tag != NULL) {\n        memcpy(tag, ctx->y, tag_len);\n    }\n    mbedtls_ccm_clear_state(ctx);\n\n    return 0;\n}\n\n/*\n * Authenticated encryption or decryption\n */\nstatic int ccm_auth_crypt(mbedtls_ccm_context *ctx, int mode, size_t length,\n                          const unsigned char *iv, size_t iv_len,\n                          const unsigned char *add, size_t add_len,\n                          const unsigned char *input, unsigned char *output,\n                          unsigned char *tag, size_t tag_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t olen;\n\n    if ((ret = mbedtls_ccm_starts(ctx, mode, iv, iv_len)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_ccm_set_lengths(ctx, add_len, length, tag_len)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_ccm_update_ad(ctx, add, add_len)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_ccm_update(ctx, input, length,\n                                  output, length, &olen)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_ccm_finish(ctx, tag, tag_len)) != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\n/*\n * Authenticated encryption\n */\nint mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length,\n                                     const unsigned char *iv, size_t iv_len,\n                                     const unsigned char *add, size_t add_len,\n                                     const unsigned char *input, unsigned char *output,\n                                     unsigned char *tag, size_t tag_len)\n{\n    return ccm_auth_crypt(ctx, MBEDTLS_CCM_STAR_ENCRYPT, length, iv, iv_len,\n                          add, add_len, input, output, tag, tag_len);\n}\n\nint mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length,\n                                const unsigned char *iv, size_t iv_len,\n                                const unsigned char *add, size_t add_len,\n                                const unsigned char *input, unsigned char *output,\n                                unsigned char *tag, size_t tag_len)\n{\n    return ccm_auth_crypt(ctx, MBEDTLS_CCM_ENCRYPT, length, iv, iv_len,\n                          add, add_len, input, output, tag, tag_len);\n}\n\n/*\n * Authenticated decryption\n */\nstatic int mbedtls_ccm_compare_tags(const unsigned char *tag1,\n                                    const unsigned char *tag2,\n                                    size_t tag_len)\n{\n    /* Check tag in \"constant-time\" */\n    int diff = mbedtls_ct_memcmp(tag1, tag2, tag_len);\n\n    if (diff != 0) {\n        return MBEDTLS_ERR_CCM_AUTH_FAILED;\n    }\n\n    return 0;\n}\n\nstatic int ccm_auth_decrypt(mbedtls_ccm_context *ctx, int mode, size_t length,\n                            const unsigned char *iv, size_t iv_len,\n                            const unsigned char *add, size_t add_len,\n                            const unsigned char *input, unsigned char *output,\n                            const unsigned char *tag, size_t tag_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char check_tag[16];\n\n    if ((ret = ccm_auth_crypt(ctx, mode, length,\n                              iv, iv_len, add, add_len,\n                              input, output, check_tag, tag_len)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_ccm_compare_tags(tag, check_tag, tag_len)) != 0) {\n        mbedtls_platform_zeroize(output, length);\n        return ret;\n    }\n\n    return 0;\n}\n\nint mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length,\n                                  const unsigned char *iv, size_t iv_len,\n                                  const unsigned char *add, size_t add_len,\n                                  const unsigned char *input, unsigned char *output,\n                                  const unsigned char *tag, size_t tag_len)\n{\n    return ccm_auth_decrypt(ctx, MBEDTLS_CCM_STAR_DECRYPT, length,\n                            iv, iv_len, add, add_len,\n                            input, output, tag, tag_len);\n}\n\nint mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length,\n                             const unsigned char *iv, size_t iv_len,\n                             const unsigned char *add, size_t add_len,\n                             const unsigned char *input, unsigned char *output,\n                             const unsigned char *tag, size_t tag_len)\n{\n    return ccm_auth_decrypt(ctx, MBEDTLS_CCM_DECRYPT, length,\n                            iv, iv_len, add, add_len,\n                            input, output, tag, tag_len);\n}\n#endif /* !MBEDTLS_CCM_ALT */\n\n#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES)\n/*\n * Examples 1 to 3 from SP800-38C Appendix C\n */\n\n#define NB_TESTS 3\n#define CCM_SELFTEST_PT_MAX_LEN 24\n#define CCM_SELFTEST_CT_MAX_LEN 32\n/*\n * The data is the same for all tests, only the used length changes\n */\nstatic const unsigned char key_test_data[] = {\n    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,\n    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f\n};\n\nstatic const unsigned char iv_test_data[] = {\n    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,\n    0x18, 0x19, 0x1a, 0x1b\n};\n\nstatic const unsigned char ad_test_data[] = {\n    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,\n    0x10, 0x11, 0x12, 0x13\n};\n\nstatic const unsigned char msg_test_data[CCM_SELFTEST_PT_MAX_LEN] = {\n    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,\n    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,\n    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,\n};\n\nstatic const size_t iv_len_test_data[NB_TESTS] = { 7, 8,  12 };\nstatic const size_t add_len_test_data[NB_TESTS] = { 8, 16, 20 };\nstatic const size_t msg_len_test_data[NB_TESTS] = { 4, 16, 24 };\nstatic const size_t tag_len_test_data[NB_TESTS] = { 4, 6,  8  };\n\nstatic const unsigned char res_test_data[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = {\n    {   0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },\n    {   0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,\n        0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,\n        0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd },\n    {   0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a,\n        0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b,\n        0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5,\n        0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 }\n};\n\nint mbedtls_ccm_self_test(int verbose)\n{\n    mbedtls_ccm_context ctx;\n    /*\n     * Some hardware accelerators require the input and output buffers\n     * would be in RAM, because the flash is not accessible.\n     * Use buffers on the stack to hold the test vectors data.\n     */\n    unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN];\n    unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN];\n    size_t i;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_ccm_init(&ctx);\n\n    if (mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key_test_data,\n                           8 * sizeof(key_test_data)) != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"  CCM: setup failed\");\n        }\n\n        return 1;\n    }\n\n    for (i = 0; i < NB_TESTS; i++) {\n        if (verbose != 0) {\n            mbedtls_printf(\"  CCM-AES #%u: \", (unsigned int) i + 1);\n        }\n\n        memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN);\n        memset(ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN);\n        memcpy(plaintext, msg_test_data, msg_len_test_data[i]);\n\n        ret = mbedtls_ccm_encrypt_and_tag(&ctx, msg_len_test_data[i],\n                                          iv_test_data, iv_len_test_data[i],\n                                          ad_test_data, add_len_test_data[i],\n                                          plaintext, ciphertext,\n                                          ciphertext + msg_len_test_data[i],\n                                          tag_len_test_data[i]);\n\n        if (ret != 0 ||\n            memcmp(ciphertext, res_test_data[i],\n                   msg_len_test_data[i] + tag_len_test_data[i]) != 0) {\n            if (verbose != 0) {\n                mbedtls_printf(\"failed\\n\");\n            }\n\n            return 1;\n        }\n        memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN);\n\n        ret = mbedtls_ccm_auth_decrypt(&ctx, msg_len_test_data[i],\n                                       iv_test_data, iv_len_test_data[i],\n                                       ad_test_data, add_len_test_data[i],\n                                       ciphertext, plaintext,\n                                       ciphertext + msg_len_test_data[i],\n                                       tag_len_test_data[i]);\n\n        if (ret != 0 ||\n            memcmp(plaintext, msg_test_data, msg_len_test_data[i]) != 0) {\n            if (verbose != 0) {\n                mbedtls_printf(\"failed\\n\");\n            }\n\n            return 1;\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n\n    mbedtls_ccm_free(&ctx);\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    return 0;\n}\n\n#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */\n\n#endif /* MBEDTLS_CCM_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/chacha20.c",
    "content": "/**\n * \\file chacha20.c\n *\n * \\brief ChaCha20 cipher.\n *\n * \\author Daniel King <damaki.gh@gmail.com>\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_CHACHA20_C)\n\n#include \"mbedtls/chacha20.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <stddef.h>\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#if !defined(MBEDTLS_CHACHA20_ALT)\n\n#define ROTL32(value, amount) \\\n    ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))\n\n#define CHACHA20_CTR_INDEX (12U)\n\n#define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U)\n\n/**\n * \\brief           ChaCha20 quarter round operation.\n *\n *                  The quarter round is defined as follows (from RFC 7539):\n *                      1.  a += b; d ^= a; d <<<= 16;\n *                      2.  c += d; b ^= c; b <<<= 12;\n *                      3.  a += b; d ^= a; d <<<= 8;\n *                      4.  c += d; b ^= c; b <<<= 7;\n *\n * \\param state     ChaCha20 state to modify.\n * \\param a         The index of 'a' in the state.\n * \\param b         The index of 'b' in the state.\n * \\param c         The index of 'c' in the state.\n * \\param d         The index of 'd' in the state.\n */\nstatic inline void chacha20_quarter_round(uint32_t state[16],\n                                          size_t a,\n                                          size_t b,\n                                          size_t c,\n                                          size_t d)\n{\n    /* a += b; d ^= a; d <<<= 16; */\n    state[a] += state[b];\n    state[d] ^= state[a];\n    state[d] = ROTL32(state[d], 16);\n\n    /* c += d; b ^= c; b <<<= 12 */\n    state[c] += state[d];\n    state[b] ^= state[c];\n    state[b] = ROTL32(state[b], 12);\n\n    /* a += b; d ^= a; d <<<= 8; */\n    state[a] += state[b];\n    state[d] ^= state[a];\n    state[d] = ROTL32(state[d], 8);\n\n    /* c += d; b ^= c; b <<<= 7; */\n    state[c] += state[d];\n    state[b] ^= state[c];\n    state[b] = ROTL32(state[b], 7);\n}\n\n/**\n * \\brief           Perform the ChaCha20 inner block operation.\n *\n *                  This function performs two rounds: the column round and the\n *                  diagonal round.\n *\n * \\param state     The ChaCha20 state to update.\n */\nstatic void chacha20_inner_block(uint32_t state[16])\n{\n    chacha20_quarter_round(state, 0, 4, 8,  12);\n    chacha20_quarter_round(state, 1, 5, 9,  13);\n    chacha20_quarter_round(state, 2, 6, 10, 14);\n    chacha20_quarter_round(state, 3, 7, 11, 15);\n\n    chacha20_quarter_round(state, 0, 5, 10, 15);\n    chacha20_quarter_round(state, 1, 6, 11, 12);\n    chacha20_quarter_round(state, 2, 7, 8,  13);\n    chacha20_quarter_round(state, 3, 4, 9,  14);\n}\n\n/**\n * \\brief               Generates a keystream block.\n *\n * \\param initial_state The initial ChaCha20 state (key, nonce, counter).\n * \\param keystream     Generated keystream bytes are written to this buffer.\n */\nstatic void chacha20_block(const uint32_t initial_state[16],\n                           unsigned char keystream[64])\n{\n    uint32_t working_state[16];\n    size_t i;\n\n    memcpy(working_state,\n           initial_state,\n           CHACHA20_BLOCK_SIZE_BYTES);\n\n    for (i = 0U; i < 10U; i++) {\n        chacha20_inner_block(working_state);\n    }\n\n    working_state[0] += initial_state[0];\n    working_state[1] += initial_state[1];\n    working_state[2] += initial_state[2];\n    working_state[3] += initial_state[3];\n    working_state[4] += initial_state[4];\n    working_state[5] += initial_state[5];\n    working_state[6] += initial_state[6];\n    working_state[7] += initial_state[7];\n    working_state[8] += initial_state[8];\n    working_state[9] += initial_state[9];\n    working_state[10] += initial_state[10];\n    working_state[11] += initial_state[11];\n    working_state[12] += initial_state[12];\n    working_state[13] += initial_state[13];\n    working_state[14] += initial_state[14];\n    working_state[15] += initial_state[15];\n\n    for (i = 0U; i < 16; i++) {\n        size_t offset = i * 4U;\n\n        MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);\n    }\n\n    mbedtls_platform_zeroize(working_state, sizeof(working_state));\n}\n\nvoid mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)\n{\n    mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));\n    mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));\n\n    /* Initially, there's no keystream bytes available */\n    ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;\n}\n\nvoid mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)\n{\n    if (ctx != NULL) {\n        mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));\n    }\n}\n\nint mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,\n                            const unsigned char key[32])\n{\n    /* ChaCha20 constants - the string \"expand 32-byte k\" */\n    ctx->state[0] = 0x61707865;\n    ctx->state[1] = 0x3320646e;\n    ctx->state[2] = 0x79622d32;\n    ctx->state[3] = 0x6b206574;\n\n    /* Set key */\n    ctx->state[4]  = MBEDTLS_GET_UINT32_LE(key, 0);\n    ctx->state[5]  = MBEDTLS_GET_UINT32_LE(key, 4);\n    ctx->state[6]  = MBEDTLS_GET_UINT32_LE(key, 8);\n    ctx->state[7]  = MBEDTLS_GET_UINT32_LE(key, 12);\n    ctx->state[8]  = MBEDTLS_GET_UINT32_LE(key, 16);\n    ctx->state[9]  = MBEDTLS_GET_UINT32_LE(key, 20);\n    ctx->state[10] = MBEDTLS_GET_UINT32_LE(key, 24);\n    ctx->state[11] = MBEDTLS_GET_UINT32_LE(key, 28);\n\n    return 0;\n}\n\nint mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,\n                            const unsigned char nonce[12],\n                            uint32_t counter)\n{\n    /* Counter */\n    ctx->state[12] = counter;\n\n    /* Nonce */\n    ctx->state[13] = MBEDTLS_GET_UINT32_LE(nonce, 0);\n    ctx->state[14] = MBEDTLS_GET_UINT32_LE(nonce, 4);\n    ctx->state[15] = MBEDTLS_GET_UINT32_LE(nonce, 8);\n\n    mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));\n\n    /* Initially, there's no keystream bytes available */\n    ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;\n\n    return 0;\n}\n\nint mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,\n                            size_t size,\n                            const unsigned char *input,\n                            unsigned char *output)\n{\n    size_t offset = 0U;\n\n    /* Use leftover keystream bytes, if available */\n    while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) {\n        output[offset] = input[offset]\n                         ^ ctx->keystream8[ctx->keystream_bytes_used];\n\n        ctx->keystream_bytes_used++;\n        offset++;\n        size--;\n    }\n\n    /* Process full blocks */\n    while (size >= CHACHA20_BLOCK_SIZE_BYTES) {\n        /* Generate new keystream block and increment counter */\n        chacha20_block(ctx->state, ctx->keystream8);\n        ctx->state[CHACHA20_CTR_INDEX]++;\n\n        mbedtls_xor(output + offset, input + offset, ctx->keystream8, 64U);\n\n        offset += CHACHA20_BLOCK_SIZE_BYTES;\n        size   -= CHACHA20_BLOCK_SIZE_BYTES;\n    }\n\n    /* Last (partial) block */\n    if (size > 0U) {\n        /* Generate new keystream block and increment counter */\n        chacha20_block(ctx->state, ctx->keystream8);\n        ctx->state[CHACHA20_CTR_INDEX]++;\n\n        mbedtls_xor(output + offset, input + offset, ctx->keystream8, size);\n\n        ctx->keystream_bytes_used = size;\n\n    }\n\n    return 0;\n}\n\nint mbedtls_chacha20_crypt(const unsigned char key[32],\n                           const unsigned char nonce[12],\n                           uint32_t counter,\n                           size_t data_len,\n                           const unsigned char *input,\n                           unsigned char *output)\n{\n    mbedtls_chacha20_context ctx;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_chacha20_init(&ctx);\n\n    ret = mbedtls_chacha20_setkey(&ctx, key);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    ret = mbedtls_chacha20_starts(&ctx, nonce, counter);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    ret = mbedtls_chacha20_update(&ctx, data_len, input, output);\n\ncleanup:\n    mbedtls_chacha20_free(&ctx);\n    return ret;\n}\n\n#endif /* !MBEDTLS_CHACHA20_ALT */\n\n#if defined(MBEDTLS_SELF_TEST)\n\nstatic const unsigned char test_keys[2][32] =\n{\n    {\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\n    },\n    {\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01\n    }\n};\n\nstatic const unsigned char test_nonces[2][12] =\n{\n    {\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00\n    },\n    {\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x02\n    }\n};\n\nstatic const uint32_t test_counters[2] =\n{\n    0U,\n    1U\n};\n\nstatic const unsigned char test_input[2][375] =\n{\n    {\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\n    },\n    {\n        0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,\n        0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,\n        0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,\n        0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,\n        0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,\n        0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,\n        0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,\n        0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,\n        0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,\n        0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,\n        0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,\n        0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,\n        0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,\n        0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,\n        0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,\n        0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,\n        0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,\n        0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,\n        0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,\n        0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,\n        0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,\n        0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,\n        0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,\n        0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,\n        0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,\n        0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,\n        0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,\n        0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,\n        0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,\n        0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,\n        0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,\n        0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,\n        0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,\n        0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,\n        0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,\n        0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,\n        0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,\n        0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,\n        0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,\n        0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,\n        0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,\n        0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,\n        0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,\n        0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,\n        0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,\n        0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,\n        0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f\n    }\n};\n\nstatic const unsigned char test_output[2][375] =\n{\n    {\n        0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,\n        0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,\n        0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,\n        0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,\n        0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,\n        0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,\n        0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,\n        0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86\n    },\n    {\n        0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,\n        0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,\n        0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,\n        0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,\n        0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,\n        0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,\n        0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,\n        0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,\n        0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,\n        0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,\n        0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,\n        0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,\n        0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,\n        0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,\n        0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,\n        0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,\n        0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,\n        0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,\n        0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,\n        0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,\n        0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,\n        0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,\n        0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,\n        0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,\n        0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,\n        0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,\n        0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,\n        0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,\n        0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,\n        0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,\n        0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,\n        0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,\n        0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,\n        0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,\n        0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,\n        0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,\n        0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,\n        0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,\n        0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,\n        0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,\n        0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,\n        0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,\n        0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,\n        0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,\n        0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,\n        0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,\n        0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21\n    }\n};\n\nstatic const size_t test_lengths[2] =\n{\n    64U,\n    375U\n};\n\n/* Make sure no other definition is already present. */\n#undef ASSERT\n\n#define ASSERT(cond, args)            \\\n    do                                  \\\n    {                                   \\\n        if (!(cond))                \\\n        {                               \\\n            if (verbose != 0)          \\\n            mbedtls_printf args;    \\\n                                        \\\n            return -1;               \\\n        }                               \\\n    }                                   \\\n    while (0)\n\nint mbedtls_chacha20_self_test(int verbose)\n{\n    unsigned char output[381];\n    unsigned i;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    for (i = 0U; i < 2U; i++) {\n        if (verbose != 0) {\n            mbedtls_printf(\"  ChaCha20 test %u \", i);\n        }\n\n        ret = mbedtls_chacha20_crypt(test_keys[i],\n                                     test_nonces[i],\n                                     test_counters[i],\n                                     test_lengths[i],\n                                     test_input[i],\n                                     output);\n\n        ASSERT(0 == ret, (\"error code: %i\\n\", ret));\n\n        ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),\n               (\"failed (output)\\n\"));\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    return 0;\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* !MBEDTLS_CHACHA20_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/chachapoly.c",
    "content": "/**\n * \\file chachapoly.c\n *\n * \\brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#include \"common.h\"\n\n#if defined(MBEDTLS_CHACHAPOLY_C)\n\n#include \"mbedtls/chachapoly.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/constant_time.h\"\n\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#if !defined(MBEDTLS_CHACHAPOLY_ALT)\n\n#define CHACHAPOLY_STATE_INIT       (0)\n#define CHACHAPOLY_STATE_AAD        (1)\n#define CHACHAPOLY_STATE_CIPHERTEXT (2)   /* Encrypting or decrypting */\n#define CHACHAPOLY_STATE_FINISHED   (3)\n\n/**\n * \\brief           Adds nul bytes to pad the AAD for Poly1305.\n *\n * \\param ctx       The ChaCha20-Poly1305 context.\n */\nstatic int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)\n{\n    uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U);\n    unsigned char zeroes[15];\n\n    if (partial_block_len == 0U) {\n        return 0;\n    }\n\n    memset(zeroes, 0, sizeof(zeroes));\n\n    return mbedtls_poly1305_update(&ctx->poly1305_ctx,\n                                   zeroes,\n                                   16U - partial_block_len);\n}\n\n/**\n * \\brief           Adds nul bytes to pad the ciphertext for Poly1305.\n *\n * \\param ctx       The ChaCha20-Poly1305 context.\n */\nstatic int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)\n{\n    uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U);\n    unsigned char zeroes[15];\n\n    if (partial_block_len == 0U) {\n        return 0;\n    }\n\n    memset(zeroes, 0, sizeof(zeroes));\n    return mbedtls_poly1305_update(&ctx->poly1305_ctx,\n                                   zeroes,\n                                   16U - partial_block_len);\n}\n\nvoid mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)\n{\n    mbedtls_chacha20_init(&ctx->chacha20_ctx);\n    mbedtls_poly1305_init(&ctx->poly1305_ctx);\n    ctx->aad_len        = 0U;\n    ctx->ciphertext_len = 0U;\n    ctx->state          = CHACHAPOLY_STATE_INIT;\n    ctx->mode           = MBEDTLS_CHACHAPOLY_ENCRYPT;\n}\n\nvoid mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_chacha20_free(&ctx->chacha20_ctx);\n    mbedtls_poly1305_free(&ctx->poly1305_ctx);\n    ctx->aad_len        = 0U;\n    ctx->ciphertext_len = 0U;\n    ctx->state          = CHACHAPOLY_STATE_INIT;\n    ctx->mode           = MBEDTLS_CHACHAPOLY_ENCRYPT;\n}\n\nint mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,\n                              const unsigned char key[32])\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);\n\n    return ret;\n}\n\nint mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,\n                              const unsigned char nonce[12],\n                              mbedtls_chachapoly_mode_t mode)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char poly1305_key[64];\n\n    /* Set counter = 0, will be update to 1 when generating Poly1305 key */\n    ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    /* Generate the Poly1305 key by getting the ChaCha20 keystream output with\n     * counter = 0.  This is the same as encrypting a buffer of zeroes.\n     * Only the first 256-bits (32 bytes) of the key is used for Poly1305.\n     * The other 256 bits are discarded.\n     */\n    memset(poly1305_key, 0, sizeof(poly1305_key));\n    ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, sizeof(poly1305_key),\n                                  poly1305_key, poly1305_key);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);\n\n    if (ret == 0) {\n        ctx->aad_len        = 0U;\n        ctx->ciphertext_len = 0U;\n        ctx->state          = CHACHAPOLY_STATE_AAD;\n        ctx->mode           = mode;\n    }\n\ncleanup:\n    mbedtls_platform_zeroize(poly1305_key, 64U);\n    return ret;\n}\n\nint mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx,\n                                  const unsigned char *aad,\n                                  size_t aad_len)\n{\n    if (ctx->state != CHACHAPOLY_STATE_AAD) {\n        return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;\n    }\n\n    ctx->aad_len += aad_len;\n\n    return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);\n}\n\nint mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,\n                              size_t len,\n                              const unsigned char *input,\n                              unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if ((ctx->state != CHACHAPOLY_STATE_AAD) &&\n        (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {\n        return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;\n    }\n\n    if (ctx->state == CHACHAPOLY_STATE_AAD) {\n        ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;\n\n        ret = chachapoly_pad_aad(ctx);\n        if (ret != 0) {\n            return ret;\n        }\n    }\n\n    ctx->ciphertext_len += len;\n\n    if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {\n        ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);\n        if (ret != 0) {\n            return ret;\n        }\n\n        ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len);\n        if (ret != 0) {\n            return ret;\n        }\n    } else { /* DECRYPT */\n        ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len);\n        if (ret != 0) {\n            return ret;\n        }\n\n        ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);\n        if (ret != 0) {\n            return ret;\n        }\n    }\n\n    return 0;\n}\n\nint mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,\n                              unsigned char mac[16])\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char len_block[16];\n\n    if (ctx->state == CHACHAPOLY_STATE_INIT) {\n        return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;\n    }\n\n    if (ctx->state == CHACHAPOLY_STATE_AAD) {\n        ret = chachapoly_pad_aad(ctx);\n        if (ret != 0) {\n            return ret;\n        }\n    } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) {\n        ret = chachapoly_pad_ciphertext(ctx);\n        if (ret != 0) {\n            return ret;\n        }\n    }\n\n    ctx->state = CHACHAPOLY_STATE_FINISHED;\n\n    /* The lengths of the AAD and ciphertext are processed by\n     * Poly1305 as the final 128-bit block, encoded as little-endian integers.\n     */\n    MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);\n    MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);\n\n    ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);\n\n    return ret;\n}\n\nstatic int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx,\n                                    mbedtls_chachapoly_mode_t mode,\n                                    size_t length,\n                                    const unsigned char nonce[12],\n                                    const unsigned char *aad,\n                                    size_t aad_len,\n                                    const unsigned char *input,\n                                    unsigned char *output,\n                                    unsigned char tag[16])\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    ret = mbedtls_chachapoly_starts(ctx, nonce, mode);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    ret = mbedtls_chachapoly_update(ctx, length, input, output);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    ret = mbedtls_chachapoly_finish(ctx, tag);\n\ncleanup:\n    return ret;\n}\n\nint mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx,\n                                       size_t length,\n                                       const unsigned char nonce[12],\n                                       const unsigned char *aad,\n                                       size_t aad_len,\n                                       const unsigned char *input,\n                                       unsigned char *output,\n                                       unsigned char tag[16])\n{\n    return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,\n                                    length, nonce, aad, aad_len,\n                                    input, output, tag);\n}\n\nint mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,\n                                    size_t length,\n                                    const unsigned char nonce[12],\n                                    const unsigned char *aad,\n                                    size_t aad_len,\n                                    const unsigned char tag[16],\n                                    const unsigned char *input,\n                                    unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char check_tag[16];\n    int diff;\n\n    if ((ret = chachapoly_crypt_and_tag(ctx,\n                                        MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,\n                                        aad, aad_len, input, output, check_tag)) != 0) {\n        return ret;\n    }\n\n    /* Check tag in \"constant-time\" */\n    diff = mbedtls_ct_memcmp(tag, check_tag, sizeof(check_tag));\n\n    if (diff != 0) {\n        mbedtls_platform_zeroize(output, length);\n        return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;\n    }\n\n    return 0;\n}\n\n#endif /* MBEDTLS_CHACHAPOLY_ALT */\n\n#if defined(MBEDTLS_SELF_TEST)\n\nstatic const unsigned char test_key[1][32] =\n{\n    {\n        0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,\n        0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,\n        0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,\n        0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f\n    }\n};\n\nstatic const unsigned char test_nonce[1][12] =\n{\n    {\n        0x07, 0x00, 0x00, 0x00,                         /* 32-bit common part */\n        0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47  /* 64-bit IV */\n    }\n};\n\nstatic const unsigned char test_aad[1][12] =\n{\n    {\n        0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,\n        0xc4, 0xc5, 0xc6, 0xc7\n    }\n};\n\nstatic const size_t test_aad_len[1] =\n{\n    12U\n};\n\nstatic const unsigned char test_input[1][114] =\n{\n    {\n        0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,\n        0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,\n        0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,\n        0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,\n        0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,\n        0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,\n        0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,\n        0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,\n        0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,\n        0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,\n        0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,\n        0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,\n        0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,\n        0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,\n        0x74, 0x2e\n    }\n};\n\nstatic const unsigned char test_output[1][114] =\n{\n    {\n        0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,\n        0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,\n        0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,\n        0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,\n        0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,\n        0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,\n        0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,\n        0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,\n        0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,\n        0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,\n        0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,\n        0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,\n        0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,\n        0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,\n        0x61, 0x16\n    }\n};\n\nstatic const size_t test_input_len[1] =\n{\n    114U\n};\n\nstatic const unsigned char test_mac[1][16] =\n{\n    {\n        0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,\n        0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91\n    }\n};\n\n/* Make sure no other definition is already present. */\n#undef ASSERT\n\n#define ASSERT(cond, args)            \\\n    do                                  \\\n    {                                   \\\n        if (!(cond))                \\\n        {                               \\\n            if (verbose != 0)          \\\n            mbedtls_printf args;    \\\n                                        \\\n            return -1;               \\\n        }                               \\\n    }                                   \\\n    while (0)\n\nint mbedtls_chachapoly_self_test(int verbose)\n{\n    mbedtls_chachapoly_context ctx;\n    unsigned i;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char output[200];\n    unsigned char mac[16];\n\n    for (i = 0U; i < 1U; i++) {\n        if (verbose != 0) {\n            mbedtls_printf(\"  ChaCha20-Poly1305 test %u \", i);\n        }\n\n        mbedtls_chachapoly_init(&ctx);\n\n        ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]);\n        ASSERT(0 == ret, (\"setkey() error code: %i\\n\", ret));\n\n        ret = mbedtls_chachapoly_encrypt_and_tag(&ctx,\n                                                 test_input_len[i],\n                                                 test_nonce[i],\n                                                 test_aad[i],\n                                                 test_aad_len[i],\n                                                 test_input[i],\n                                                 output,\n                                                 mac);\n\n        ASSERT(0 == ret, (\"crypt_and_tag() error code: %i\\n\", ret));\n\n        ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]),\n               (\"failure (wrong output)\\n\"));\n\n        ASSERT(0 == memcmp(mac, test_mac[i], 16U),\n               (\"failure (wrong MAC)\\n\"));\n\n        mbedtls_chachapoly_free(&ctx);\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    return 0;\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_CHACHAPOLY_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/check_crypto_config.h",
    "content": "/**\n * \\file check_crypto_config.h\n *\n * \\brief Consistency checks for PSA configuration options\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n * It is recommended to include this file from your crypto_config.h\n * in order to catch dependency issues early.\n */\n\n#ifndef MBEDTLS_CHECK_CRYPTO_CONFIG_H\n#define MBEDTLS_CHECK_CRYPTO_CONFIG_H\n\n#if defined(PSA_WANT_ALG_CCM) && \\\n    !(defined(PSA_WANT_KEY_TYPE_AES) || \\\n    defined(PSA_WANT_KEY_TYPE_CAMELLIA))\n#error \"PSA_WANT_ALG_CCM defined, but not all prerequisites\"\n#endif\n\n#if defined(PSA_WANT_ALG_CMAC) && \\\n    !(defined(PSA_WANT_KEY_TYPE_AES) || \\\n    defined(PSA_WANT_KEY_TYPE_CAMELLIA) || \\\n    defined(PSA_WANT_KEY_TYPE_DES))\n#error \"PSA_WANT_ALG_CMAC defined, but not all prerequisites\"\n#endif\n\n#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \\\n    !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \\\n    defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY))\n#error \"PSA_WANT_ALG_DETERMINISTIC_ECDSA defined, but not all prerequisites\"\n#endif\n\n#if defined(PSA_WANT_ALG_ECDSA) && \\\n    !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \\\n    defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY))\n#error \"PSA_WANT_ALG_ECDSA defined, but not all prerequisites\"\n#endif\n\n#if defined(PSA_WANT_ALG_GCM) && \\\n    !(defined(PSA_WANT_KEY_TYPE_AES) || \\\n    defined(PSA_WANT_KEY_TYPE_CAMELLIA))\n#error \"PSA_WANT_ALG_GCM defined, but not all prerequisites\"\n#endif\n\n#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) && \\\n    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \\\n    defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))\n#error \"PSA_WANT_ALG_RSA_PKCS1V15_CRYPT defined, but not all prerequisites\"\n#endif\n\n#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) && \\\n    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \\\n    defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))\n#error \"PSA_WANT_ALG_RSA_PKCS1V15_SIGN defined, but not all prerequisites\"\n#endif\n\n#if defined(PSA_WANT_ALG_RSA_OAEP) && \\\n    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \\\n    defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))\n#error \"PSA_WANT_ALG_RSA_OAEP defined, but not all prerequisites\"\n#endif\n\n#if defined(PSA_WANT_ALG_RSA_PSS) && \\\n    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \\\n    defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))\n#error \"PSA_WANT_ALG_RSA_PSS defined, but not all prerequisites\"\n#endif\n\n#if (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \\\n    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \\\n    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \\\n    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \\\n    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)) && \\\n    !defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)\n#error \"PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx defined, but not all prerequisites\"\n#endif\n\n#if (defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \\\n    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \\\n    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \\\n    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)) && \\\n    !defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)\n#error \"PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx defined, but not all prerequisites\"\n#endif\n\n#if (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) || \\\n    defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \\\n    defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \\\n    defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)) && \\\n    !defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY)\n#error \"PSA_WANT_KEY_TYPE_DH_KEY_PAIR_xxx defined, but not all prerequisites\"\n#endif\n\n#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR)\n#if defined(MBEDTLS_DEPRECATED_REMOVED)\n#error \"PSA_WANT_KEY_TYPE_ECC_KEY_PAIR is deprecated and will be removed in a \\\n    future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx \\\n    symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE\"\n#elif defined(MBEDTLS_DEPRECATED_WARNING)\n#warning \"PSA_WANT_KEY_TYPE_ECC_KEY_PAIR is deprecated and will be removed in a \\\n    future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx \\\n    symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE\"\n#endif /* MBEDTLS_DEPRECATED_WARNING */\n#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR */\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)\n#if defined(MBEDTLS_DEPRECATED_REMOVED)\n#error \"PSA_WANT_KEY_TYPE_RSA_KEY_PAIR is deprecated and will be removed in a \\\n    future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx \\\n    symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE\"\n#elif defined(MBEDTLS_DEPRECATED_WARNING)\n#warning \"PSA_WANT_KEY_TYPE_RSA_KEY_PAIR is deprecated and will be removed in a \\\n    future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx \\\n    symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE\"\n#endif /* MBEDTLS_DEPRECATED_WARNING */\n#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE)\n#error \"PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE defined, but feature is not supported\"\n#endif\n\n#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE)\n#error \"PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE defined, but feature is not supported\"\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_USE_PSA_CRYPTO) && \\\n    !(defined(PSA_WANT_ALG_SHA_1) || defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_512))\n#error \"MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites\"\n#endif\n\n#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) && \\\n    !defined(PSA_WANT_ALG_SHA_256)\n#error \"PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS defined, but not all prerequisites\"\n#endif\n\n#endif /* MBEDTLS_CHECK_CRYPTO_CONFIG_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/cipher.c",
    "content": "/**\n * \\file cipher.c\n *\n * \\brief Generic cipher wrapper for Mbed TLS\n *\n * \\author Adriaan de Jong <dejong@fox-it.com>\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_CIPHER_C)\n\n#include \"mbedtls/cipher.h\"\n#include \"cipher_invasive.h\"\n#include \"cipher_wrap.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/constant_time.h\"\n#include \"constant_time_internal.h\"\n\n#include <stdlib.h>\n#include <string.h>\n\n#if defined(MBEDTLS_CHACHAPOLY_C)\n#include \"mbedtls/chachapoly.h\"\n#endif\n\n#if defined(MBEDTLS_GCM_C)\n#include \"mbedtls/gcm.h\"\n#endif\n\n#if defined(MBEDTLS_CCM_C)\n#include \"mbedtls/ccm.h\"\n#endif\n\n#if defined(MBEDTLS_CHACHA20_C)\n#include \"mbedtls/chacha20.h\"\n#endif\n\n#if defined(MBEDTLS_CMAC_C)\n#include \"mbedtls/cmac.h\"\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n#include \"psa/crypto.h\"\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\n#if defined(MBEDTLS_NIST_KW_C)\n#include \"mbedtls/nist_kw.h\"\n#endif\n\n#include \"mbedtls/platform.h\"\n\nstatic int supported_init = 0;\n\nstatic inline const mbedtls_cipher_base_t *mbedtls_cipher_get_base(\n    const mbedtls_cipher_info_t *info)\n{\n    return mbedtls_cipher_base_lookup_table[info->base_idx];\n}\n\nconst int *mbedtls_cipher_list(void)\n{\n    const mbedtls_cipher_definition_t *def;\n    int *type;\n\n    if (!supported_init) {\n        def = mbedtls_cipher_definitions;\n        type = mbedtls_cipher_supported;\n\n        while (def->type != 0) {\n            *type++ = (*def++).type;\n        }\n\n        *type = 0;\n\n        supported_init = 1;\n    }\n\n    return mbedtls_cipher_supported;\n}\n\nconst mbedtls_cipher_info_t *mbedtls_cipher_info_from_type(\n    const mbedtls_cipher_type_t cipher_type)\n{\n    const mbedtls_cipher_definition_t *def;\n\n    for (def = mbedtls_cipher_definitions; def->info != NULL; def++) {\n        if (def->type == cipher_type) {\n            return def->info;\n        }\n    }\n\n    return NULL;\n}\n\nconst mbedtls_cipher_info_t *mbedtls_cipher_info_from_string(\n    const char *cipher_name)\n{\n    const mbedtls_cipher_definition_t *def;\n\n    if (NULL == cipher_name) {\n        return NULL;\n    }\n\n    for (def = mbedtls_cipher_definitions; def->info != NULL; def++) {\n        if (!strcmp(def->info->name, cipher_name)) {\n            return def->info;\n        }\n    }\n\n    return NULL;\n}\n\nconst mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(\n    const mbedtls_cipher_id_t cipher_id,\n    int key_bitlen,\n    const mbedtls_cipher_mode_t mode)\n{\n    const mbedtls_cipher_definition_t *def;\n\n    for (def = mbedtls_cipher_definitions; def->info != NULL; def++) {\n        if (mbedtls_cipher_get_base(def->info)->cipher == cipher_id &&\n            mbedtls_cipher_info_get_key_bitlen(def->info) == (unsigned) key_bitlen &&\n            def->info->mode == mode) {\n            return def->info;\n        }\n    }\n\n    return NULL;\n}\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\nstatic inline psa_key_type_t mbedtls_psa_translate_cipher_type(\n    mbedtls_cipher_type_t cipher)\n{\n    switch (cipher) {\n        case MBEDTLS_CIPHER_AES_128_CCM:\n        case MBEDTLS_CIPHER_AES_192_CCM:\n        case MBEDTLS_CIPHER_AES_256_CCM:\n        case MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG:\n        case MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG:\n        case MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG:\n        case MBEDTLS_CIPHER_AES_128_GCM:\n        case MBEDTLS_CIPHER_AES_192_GCM:\n        case MBEDTLS_CIPHER_AES_256_GCM:\n        case MBEDTLS_CIPHER_AES_128_CBC:\n        case MBEDTLS_CIPHER_AES_192_CBC:\n        case MBEDTLS_CIPHER_AES_256_CBC:\n        case MBEDTLS_CIPHER_AES_128_ECB:\n        case MBEDTLS_CIPHER_AES_192_ECB:\n        case MBEDTLS_CIPHER_AES_256_ECB:\n            return PSA_KEY_TYPE_AES;\n\n        /* ARIA not yet supported in PSA. */\n        /* case MBEDTLS_CIPHER_ARIA_128_CCM:\n           case MBEDTLS_CIPHER_ARIA_192_CCM:\n           case MBEDTLS_CIPHER_ARIA_256_CCM:\n           case MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG:\n           case MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG:\n           case MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG:\n           case MBEDTLS_CIPHER_ARIA_128_GCM:\n           case MBEDTLS_CIPHER_ARIA_192_GCM:\n           case MBEDTLS_CIPHER_ARIA_256_GCM:\n           case MBEDTLS_CIPHER_ARIA_128_CBC:\n           case MBEDTLS_CIPHER_ARIA_192_CBC:\n           case MBEDTLS_CIPHER_ARIA_256_CBC:\n               return( PSA_KEY_TYPE_ARIA ); */\n\n        default:\n            return 0;\n    }\n}\n\nstatic inline psa_algorithm_t mbedtls_psa_translate_cipher_mode(\n    mbedtls_cipher_mode_t mode, size_t taglen)\n{\n    switch (mode) {\n        case MBEDTLS_MODE_ECB:\n            return PSA_ALG_ECB_NO_PADDING;\n        case MBEDTLS_MODE_GCM:\n            return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, taglen);\n        case MBEDTLS_MODE_CCM:\n            return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen);\n        case MBEDTLS_MODE_CCM_STAR_NO_TAG:\n            return PSA_ALG_CCM_STAR_NO_TAG;\n        case MBEDTLS_MODE_CBC:\n            if (taglen == 0) {\n                return PSA_ALG_CBC_NO_PADDING;\n            } else {\n                return 0;\n            }\n        default:\n            return 0;\n    }\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\nvoid mbedtls_cipher_init(mbedtls_cipher_context_t *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_cipher_context_t));\n}\n\nvoid mbedtls_cipher_free(mbedtls_cipher_context_t *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ctx->psa_enabled == 1) {\n        if (ctx->cipher_ctx != NULL) {\n            mbedtls_cipher_context_psa * const cipher_psa =\n                (mbedtls_cipher_context_psa *) ctx->cipher_ctx;\n\n            if (cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED) {\n                /* xxx_free() doesn't allow to return failures. */\n                (void) psa_destroy_key(cipher_psa->slot);\n            }\n\n            mbedtls_zeroize_and_free(cipher_psa, sizeof(*cipher_psa));\n        }\n\n        mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t));\n        return;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\n#if defined(MBEDTLS_CMAC_C)\n    if (ctx->cmac_ctx) {\n        mbedtls_zeroize_and_free(ctx->cmac_ctx,\n                                 sizeof(mbedtls_cmac_context_t));\n    }\n#endif\n\n    if (ctx->cipher_ctx) {\n        mbedtls_cipher_get_base(ctx->cipher_info)->ctx_free_func(ctx->cipher_ctx);\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t));\n}\n\nint mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx,\n                         const mbedtls_cipher_info_t *cipher_info)\n{\n    if (cipher_info == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    memset(ctx, 0, sizeof(mbedtls_cipher_context_t));\n\n    if (mbedtls_cipher_get_base(cipher_info)->ctx_alloc_func != NULL) {\n        ctx->cipher_ctx = mbedtls_cipher_get_base(cipher_info)->ctx_alloc_func();\n        if (ctx->cipher_ctx == NULL) {\n            return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;\n        }\n    }\n\n    ctx->cipher_info = cipher_info;\n\n    return 0;\n}\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\nint mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx,\n                             const mbedtls_cipher_info_t *cipher_info,\n                             size_t taglen)\n{\n    psa_algorithm_t alg;\n    mbedtls_cipher_context_psa *cipher_psa;\n\n    if (NULL == cipher_info || NULL == ctx) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    /* Check that the underlying cipher mode and cipher type are\n     * supported by the underlying PSA Crypto implementation. */\n    alg = mbedtls_psa_translate_cipher_mode(((mbedtls_cipher_mode_t) cipher_info->mode), taglen);\n    if (alg == 0) {\n        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n    }\n    if (mbedtls_psa_translate_cipher_type(((mbedtls_cipher_type_t) cipher_info->type)) == 0) {\n        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n    }\n\n    memset(ctx, 0, sizeof(mbedtls_cipher_context_t));\n\n    cipher_psa = mbedtls_calloc(1, sizeof(mbedtls_cipher_context_psa));\n    if (cipher_psa == NULL) {\n        return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;\n    }\n    cipher_psa->alg  = alg;\n    ctx->cipher_ctx  = cipher_psa;\n    ctx->cipher_info = cipher_info;\n    ctx->psa_enabled = 1;\n    return 0;\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\nint mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx,\n                          const unsigned char *key,\n                          int key_bitlen,\n                          const mbedtls_operation_t operation)\n{\n    if (operation != MBEDTLS_ENCRYPT && operation != MBEDTLS_DECRYPT) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n    if (ctx->cipher_info == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    if (MBEDTLS_MODE_ECB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) &&\n        MBEDTLS_DECRYPT == operation) {\n        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n    }\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ctx->psa_enabled == 1) {\n        mbedtls_cipher_context_psa * const cipher_psa =\n            (mbedtls_cipher_context_psa *) ctx->cipher_ctx;\n\n        size_t const key_bytelen = ((size_t) key_bitlen + 7) / 8;\n\n        psa_status_t status;\n        psa_key_type_t key_type;\n        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n\n        /* PSA Crypto API only accepts byte-aligned keys. */\n        if (key_bitlen % 8 != 0) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        /* Don't allow keys to be set multiple times. */\n        if (cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        key_type = mbedtls_psa_translate_cipher_type(\n            ((mbedtls_cipher_type_t) ctx->cipher_info->type));\n        if (key_type == 0) {\n            return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n        }\n        psa_set_key_type(&attributes, key_type);\n\n        /* Mbed TLS' cipher layer doesn't enforce the mode of operation\n         * (encrypt vs. decrypt): it is possible to setup a key for encryption\n         * and use it for AEAD decryption. Until tests relying on this\n         * are changed, allow any usage in PSA. */\n        psa_set_key_usage_flags(&attributes,\n                                PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);\n        psa_set_key_algorithm(&attributes, cipher_psa->alg);\n\n        status = psa_import_key(&attributes, key, key_bytelen,\n                                &cipher_psa->slot);\n        switch (status) {\n            case PSA_SUCCESS:\n                break;\n            case PSA_ERROR_INSUFFICIENT_MEMORY:\n                return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;\n            case PSA_ERROR_NOT_SUPPORTED:\n                return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n            default:\n                return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;\n        }\n        /* Indicate that we own the key slot and need to\n         * destroy it in mbedtls_cipher_free(). */\n        cipher_psa->slot_state = MBEDTLS_CIPHER_PSA_KEY_OWNED;\n\n        ctx->key_bitlen = key_bitlen;\n        ctx->operation = operation;\n        return 0;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\n    if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN) == 0 &&\n        (int) mbedtls_cipher_info_get_key_bitlen(ctx->cipher_info) != key_bitlen) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    ctx->key_bitlen = key_bitlen;\n    ctx->operation = operation;\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    /*\n     * For OFB, CFB and CTR mode always use the encryption key schedule\n     */\n    if (MBEDTLS_ENCRYPT == operation ||\n        MBEDTLS_MODE_CFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||\n        MBEDTLS_MODE_OFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||\n        MBEDTLS_MODE_CTR == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {\n        return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_enc_func(ctx->cipher_ctx, key,\n                                                                          ctx->key_bitlen);\n    }\n\n    if (MBEDTLS_DECRYPT == operation) {\n        return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_dec_func(ctx->cipher_ctx, key,\n                                                                          ctx->key_bitlen);\n    }\n#else\n    if (operation == MBEDTLS_ENCRYPT || operation == MBEDTLS_DECRYPT) {\n        return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_enc_func(ctx->cipher_ctx, key,\n                                                                          ctx->key_bitlen);\n    }\n#endif\n\n    return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n}\n\nint mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx,\n                          const unsigned char *iv,\n                          size_t iv_len)\n{\n    size_t actual_iv_size;\n\n    if (ctx->cipher_info == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ctx->psa_enabled == 1) {\n        /* While PSA Crypto has an API for multipart\n         * operations, we currently don't make it\n         * accessible through the cipher layer. */\n        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\n    /* avoid buffer overflow in ctx->iv */\n    if (iv_len > MBEDTLS_MAX_IV_LENGTH) {\n        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n    }\n\n    if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN) != 0) {\n        actual_iv_size = iv_len;\n    } else {\n        actual_iv_size = mbedtls_cipher_info_get_iv_size(ctx->cipher_info);\n\n        /* avoid reading past the end of input buffer */\n        if (actual_iv_size > iv_len) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n    }\n\n#if defined(MBEDTLS_CHACHA20_C)\n    if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20) {\n        /* Even though the actual_iv_size is overwritten with a correct value\n         * of 12 from the cipher info, return an error to indicate that\n         * the input iv_len is wrong. */\n        if (iv_len != 12) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        if (0 != mbedtls_chacha20_starts((mbedtls_chacha20_context *) ctx->cipher_ctx,\n                                         iv,\n                                         0U)) {   /* Initial counter value */\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n    }\n#if defined(MBEDTLS_CHACHAPOLY_C)\n    if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20_POLY1305 &&\n        iv_len != 12) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n#endif\n#endif\n\n#if defined(MBEDTLS_GCM_C)\n    if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {\n        return mbedtls_gcm_starts((mbedtls_gcm_context *) ctx->cipher_ctx,\n                                  ctx->operation,\n                                  iv, iv_len);\n    }\n#endif\n\n#if defined(MBEDTLS_CCM_C)\n    if (MBEDTLS_MODE_CCM_STAR_NO_TAG == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {\n        int set_lengths_result;\n        int ccm_star_mode;\n\n        set_lengths_result = mbedtls_ccm_set_lengths(\n            (mbedtls_ccm_context *) ctx->cipher_ctx,\n            0, 0, 0);\n        if (set_lengths_result != 0) {\n            return set_lengths_result;\n        }\n\n        if (ctx->operation == MBEDTLS_DECRYPT) {\n            ccm_star_mode = MBEDTLS_CCM_STAR_DECRYPT;\n        } else if (ctx->operation == MBEDTLS_ENCRYPT) {\n            ccm_star_mode = MBEDTLS_CCM_STAR_ENCRYPT;\n        } else {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        return mbedtls_ccm_starts((mbedtls_ccm_context *) ctx->cipher_ctx,\n                                  ccm_star_mode,\n                                  iv, iv_len);\n    }\n#endif\n\n    if (actual_iv_size != 0) {\n        memcpy(ctx->iv, iv, actual_iv_size);\n        ctx->iv_size = actual_iv_size;\n    }\n\n    return 0;\n}\n\nint mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx)\n{\n    if (ctx->cipher_info == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ctx->psa_enabled == 1) {\n        /* We don't support resetting PSA-based\n         * cipher contexts, yet. */\n        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\n    ctx->unprocessed_len = 0;\n\n    return 0;\n}\n\n#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)\nint mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx,\n                             const unsigned char *ad, size_t ad_len)\n{\n    if (ctx->cipher_info == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ctx->psa_enabled == 1) {\n        /* While PSA Crypto has an API for multipart\n         * operations, we currently don't make it\n         * accessible through the cipher layer. */\n        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\n#if defined(MBEDTLS_GCM_C)\n    if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {\n        return mbedtls_gcm_update_ad((mbedtls_gcm_context *) ctx->cipher_ctx,\n                                     ad, ad_len);\n    }\n#endif\n\n#if defined(MBEDTLS_CHACHAPOLY_C)\n    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) {\n        int result;\n        mbedtls_chachapoly_mode_t mode;\n\n        mode = (ctx->operation == MBEDTLS_ENCRYPT)\n                ? MBEDTLS_CHACHAPOLY_ENCRYPT\n                : MBEDTLS_CHACHAPOLY_DECRYPT;\n\n        result = mbedtls_chachapoly_starts((mbedtls_chachapoly_context *) ctx->cipher_ctx,\n                                           ctx->iv,\n                                           mode);\n        if (result != 0) {\n            return result;\n        }\n\n        return mbedtls_chachapoly_update_aad((mbedtls_chachapoly_context *) ctx->cipher_ctx,\n                                             ad, ad_len);\n    }\n#endif\n\n    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n}\n#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */\n\nint mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *input,\n                          size_t ilen, unsigned char *output, size_t *olen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t block_size;\n\n    if (ctx->cipher_info == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ctx->psa_enabled == 1) {\n        /* While PSA Crypto has an API for multipart\n         * operations, we currently don't make it\n         * accessible through the cipher layer. */\n        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\n    *olen = 0;\n    block_size = mbedtls_cipher_get_block_size(ctx);\n    if (0 == block_size) {\n        return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;\n    }\n\n    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_ECB) {\n        if (ilen != block_size) {\n            return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;\n        }\n\n        *olen = ilen;\n\n        if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ecb_func(ctx->cipher_ctx,\n                                                                            ctx->operation, input,\n                                                                            output))) {\n            return ret;\n        }\n\n        return 0;\n    }\n\n#if defined(MBEDTLS_GCM_C)\n    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_GCM) {\n        return mbedtls_gcm_update((mbedtls_gcm_context *) ctx->cipher_ctx,\n                                  input, ilen,\n                                  output, ilen, olen);\n    }\n#endif\n\n#if defined(MBEDTLS_CCM_C)\n    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CCM_STAR_NO_TAG) {\n        return mbedtls_ccm_update((mbedtls_ccm_context *) ctx->cipher_ctx,\n                                  input, ilen,\n                                  output, ilen, olen);\n    }\n#endif\n\n#if defined(MBEDTLS_CHACHAPOLY_C)\n    if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20_POLY1305) {\n        *olen = ilen;\n        return mbedtls_chachapoly_update((mbedtls_chachapoly_context *) ctx->cipher_ctx,\n                                         ilen, input, output);\n    }\n#endif\n\n    if (input == output &&\n        (ctx->unprocessed_len != 0 || ilen % block_size)) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CBC) {\n        size_t copy_len = 0;\n\n        /*\n         * If there is not enough data for a full block, cache it.\n         */\n        if ((ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding &&\n             ilen <= block_size - ctx->unprocessed_len) ||\n            (ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding &&\n             ilen < block_size - ctx->unprocessed_len) ||\n            (ctx->operation == MBEDTLS_ENCRYPT &&\n             ilen < block_size - ctx->unprocessed_len)) {\n            memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input,\n                   ilen);\n\n            ctx->unprocessed_len += ilen;\n            return 0;\n        }\n\n        /*\n         * Process cached data first\n         */\n        if (0 != ctx->unprocessed_len) {\n            copy_len = block_size - ctx->unprocessed_len;\n\n            memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input,\n                   copy_len);\n\n            if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx,\n                                                                                ctx->operation,\n                                                                                block_size, ctx->iv,\n                                                                                ctx->\n                                                                                unprocessed_data,\n                                                                                output))) {\n                return ret;\n            }\n\n            *olen += block_size;\n            output += block_size;\n            ctx->unprocessed_len = 0;\n\n            input += copy_len;\n            ilen -= copy_len;\n        }\n\n        /*\n         * Cache final, incomplete block\n         */\n        if (0 != ilen) {\n            /* Encryption: only cache partial blocks\n             * Decryption w/ padding: always keep at least one whole block\n             * Decryption w/o padding: only cache partial blocks\n             */\n            copy_len = ilen % block_size;\n            if (copy_len == 0 &&\n                ctx->operation == MBEDTLS_DECRYPT &&\n                NULL != ctx->add_padding) {\n                copy_len = block_size;\n            }\n\n            memcpy(ctx->unprocessed_data, &(input[ilen - copy_len]),\n                   copy_len);\n\n            ctx->unprocessed_len += copy_len;\n            ilen -= copy_len;\n        }\n\n        /*\n         * Process remaining full blocks\n         */\n        if (ilen) {\n            if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx,\n                                                                                ctx->operation,\n                                                                                ilen, ctx->iv,\n                                                                                input,\n                                                                                output))) {\n                return ret;\n            }\n\n            *olen += ilen;\n        }\n\n        return 0;\n    }\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CFB) {\n        if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cfb_func(ctx->cipher_ctx,\n                                                                            ctx->operation, ilen,\n                                                                            &ctx->unprocessed_len,\n                                                                            ctx->iv,\n                                                                            input, output))) {\n            return ret;\n        }\n\n        *olen = ilen;\n\n        return 0;\n    }\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_OFB) {\n        if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ofb_func(ctx->cipher_ctx,\n                                                                            ilen,\n                                                                            &ctx->unprocessed_len,\n                                                                            ctx->iv,\n                                                                            input, output))) {\n            return ret;\n        }\n\n        *olen = ilen;\n\n        return 0;\n    }\n#endif /* MBEDTLS_CIPHER_MODE_OFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CTR) {\n        if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ctr_func(ctx->cipher_ctx,\n                                                                            ilen,\n                                                                            &ctx->unprocessed_len,\n                                                                            ctx->iv,\n                                                                            ctx->unprocessed_data,\n                                                                            input, output))) {\n            return ret;\n        }\n\n        *olen = ilen;\n\n        return 0;\n    }\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_XTS) {\n        if (ctx->unprocessed_len > 0) {\n            /* We can only process an entire data unit at a time. */\n            return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n        }\n\n        ret = mbedtls_cipher_get_base(ctx->cipher_info)->xts_func(ctx->cipher_ctx,\n                                                                  ctx->operation,\n                                                                  ilen,\n                                                                  ctx->iv,\n                                                                  input,\n                                                                  output);\n        if (ret != 0) {\n            return ret;\n        }\n\n        *olen = ilen;\n\n        return 0;\n    }\n#endif /* MBEDTLS_CIPHER_MODE_XTS */\n\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_STREAM) {\n        if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->stream_func(ctx->cipher_ctx,\n                                                                               ilen, input,\n                                                                               output))) {\n            return ret;\n        }\n\n        *olen = ilen;\n\n        return 0;\n    }\n#endif /* MBEDTLS_CIPHER_MODE_STREAM */\n\n    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n}\n\n#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)\n#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)\n/*\n * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len\n */\nstatic void add_pkcs_padding(unsigned char *output, size_t output_len,\n                             size_t data_len)\n{\n    size_t padding_len = output_len - data_len;\n    unsigned char i;\n\n    for (i = 0; i < padding_len; i++) {\n        output[data_len + i] = (unsigned char) padding_len;\n    }\n}\n\n/*\n * Get the length of the PKCS7 padding.\n *\n * Note: input_len must be the block size of the cipher.\n */\nMBEDTLS_STATIC_TESTABLE int mbedtls_get_pkcs_padding(unsigned char *input,\n                                                     size_t input_len,\n                                                     size_t *data_len,\n                                                     size_t *invalid_padding)\n{\n    size_t i, pad_idx;\n    unsigned char padding_len;\n\n    if (NULL == input || NULL == data_len) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    padding_len = input[input_len - 1];\n\n    mbedtls_ct_condition_t bad = mbedtls_ct_uint_gt(padding_len, input_len);\n    bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0));\n\n    /* The number of bytes checked must be independent of padding_len,\n     * so pick input_len, which is usually 8 or 16 (one block) */\n    pad_idx = input_len - padding_len;\n    for (i = 0; i < input_len; i++) {\n        mbedtls_ct_condition_t in_padding = mbedtls_ct_uint_ge(i, pad_idx);\n        mbedtls_ct_condition_t different  = mbedtls_ct_uint_ne(input[i], padding_len);\n        bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different));\n    }\n\n    /* If the padding is invalid, set the output length to 0 */\n    *data_len = mbedtls_ct_if(bad, 0, input_len - padding_len);\n\n    *invalid_padding = mbedtls_ct_size_if_else_0(bad, SIZE_MAX);\n    return 0;\n}\n#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */\n\n#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)\n/*\n * One and zeros padding: fill with 80 00 ... 00\n */\nstatic void add_one_and_zeros_padding(unsigned char *output,\n                                      size_t output_len, size_t data_len)\n{\n    size_t padding_len = output_len - data_len;\n    unsigned char i = 0;\n\n    output[data_len] = 0x80;\n    for (i = 1; i < padding_len; i++) {\n        output[data_len + i] = 0x00;\n    }\n}\n\nstatic int get_one_and_zeros_padding(unsigned char *input, size_t input_len,\n                                     size_t *data_len, size_t *invalid_padding)\n{\n    if (NULL == input || NULL == data_len) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    mbedtls_ct_condition_t in_padding = MBEDTLS_CT_TRUE;\n    mbedtls_ct_condition_t bad = MBEDTLS_CT_TRUE;\n\n    *data_len = 0;\n\n    for (ptrdiff_t i = (ptrdiff_t) (input_len) - 1; i >= 0; i--) {\n        mbedtls_ct_condition_t is_nonzero = mbedtls_ct_bool(input[i]);\n\n        mbedtls_ct_condition_t hit_first_nonzero = mbedtls_ct_bool_and(is_nonzero, in_padding);\n\n        *data_len = mbedtls_ct_size_if(hit_first_nonzero, i, *data_len);\n\n        bad = mbedtls_ct_bool_if(hit_first_nonzero, mbedtls_ct_uint_ne(input[i], 0x80), bad);\n\n        in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero));\n    }\n\n    *invalid_padding = mbedtls_ct_size_if_else_0(bad, SIZE_MAX);\n    return 0;\n}\n#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */\n\n#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)\n/*\n * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length\n */\nstatic void add_zeros_and_len_padding(unsigned char *output,\n                                      size_t output_len, size_t data_len)\n{\n    size_t padding_len = output_len - data_len;\n    unsigned char i = 0;\n\n    for (i = 1; i < padding_len; i++) {\n        output[data_len + i - 1] = 0x00;\n    }\n    output[output_len - 1] = (unsigned char) padding_len;\n}\n\nstatic int get_zeros_and_len_padding(unsigned char *input, size_t input_len,\n                                     size_t *data_len, size_t *invalid_padding)\n{\n    size_t i, pad_idx;\n    unsigned char padding_len;\n    mbedtls_ct_condition_t bad;\n\n    if (NULL == input || NULL == data_len) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    padding_len = input[input_len - 1];\n    *data_len = input_len - padding_len;\n\n    /* Avoid logical || since it results in a branch */\n    bad = mbedtls_ct_uint_gt(padding_len, input_len);\n    bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0));\n\n    /* The number of bytes checked must be independent of padding_len */\n    pad_idx = input_len - padding_len;\n    for (i = 0; i < input_len - 1; i++) {\n        mbedtls_ct_condition_t is_padding = mbedtls_ct_uint_ge(i, pad_idx);\n        mbedtls_ct_condition_t nonzero_pad_byte;\n        nonzero_pad_byte = mbedtls_ct_bool_if_else_0(is_padding, mbedtls_ct_bool(input[i]));\n        bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte);\n    }\n\n    *invalid_padding = mbedtls_ct_size_if_else_0(bad, SIZE_MAX);\n    return 0;\n}\n#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */\n\n#if defined(MBEDTLS_CIPHER_PADDING_ZEROS)\n/*\n * Zero padding: fill with 00 ... 00\n */\nstatic void add_zeros_padding(unsigned char *output,\n                              size_t output_len, size_t data_len)\n{\n    memset(output + data_len, 0, output_len - data_len);\n}\n\nstatic int get_zeros_padding(unsigned char *input, size_t input_len,\n                             size_t *data_len, size_t *invalid_padding)\n{\n    size_t i;\n    mbedtls_ct_condition_t done = MBEDTLS_CT_FALSE, prev_done;\n\n    if (NULL == input || NULL == data_len) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    *data_len = 0;\n    for (i = input_len; i > 0; i--) {\n        prev_done = done;\n        done = mbedtls_ct_bool_or(done, mbedtls_ct_uint_ne(input[i-1], 0));\n        *data_len = mbedtls_ct_size_if(mbedtls_ct_bool_ne(done, prev_done), i, *data_len);\n    }\n\n    *invalid_padding = 0;\n    return 0;\n}\n#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */\n\n/*\n * No padding: don't pad :)\n *\n * There is no add_padding function (check for NULL in mbedtls_cipher_finish)\n * but a trivial get_padding function\n */\nstatic int get_no_padding(unsigned char *input, size_t input_len,\n                          size_t *data_len, size_t *invalid_padding)\n{\n    if (NULL == input || NULL == data_len) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    *data_len = input_len;\n    *invalid_padding = 0;\n    return 0;\n}\n#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */\n\nint mbedtls_cipher_finish_padded(mbedtls_cipher_context_t *ctx,\n                                 unsigned char *output, size_t *olen,\n                                 size_t *invalid_padding)\n{\n    if (ctx->cipher_info == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ctx->psa_enabled == 1) {\n        /* While PSA Crypto has an API for multipart\n         * operations, we currently don't make it\n         * accessible through the cipher layer. */\n        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\n    *olen = 0;\n    *invalid_padding = 0;\n\n#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)\n    /* CBC mode requires padding so we make sure a call to\n     * mbedtls_cipher_set_padding_mode has been done successfully. */\n    if (MBEDTLS_MODE_CBC == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {\n        if (ctx->get_padding == NULL) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n    }\n#endif\n\n    if (MBEDTLS_MODE_CFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||\n        MBEDTLS_MODE_OFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||\n        MBEDTLS_MODE_CTR == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||\n        MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||\n        MBEDTLS_MODE_CCM_STAR_NO_TAG == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||\n        MBEDTLS_MODE_XTS == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||\n        MBEDTLS_MODE_STREAM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {\n        return 0;\n    }\n\n    if ((MBEDTLS_CIPHER_CHACHA20          == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) ||\n        (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type))) {\n        return 0;\n    }\n\n    if (MBEDTLS_MODE_ECB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {\n        if (ctx->unprocessed_len != 0) {\n            return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;\n        }\n\n        return 0;\n    }\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    if (MBEDTLS_MODE_CBC == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {\n        int ret = 0;\n\n        if (MBEDTLS_ENCRYPT == ctx->operation) {\n            /* check for 'no padding' mode */\n            if (NULL == ctx->add_padding) {\n                if (0 != ctx->unprocessed_len) {\n                    return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;\n                }\n\n                return 0;\n            }\n\n            ctx->add_padding(ctx->unprocessed_data, mbedtls_cipher_get_iv_size(ctx),\n                             ctx->unprocessed_len);\n        } else if (mbedtls_cipher_get_block_size(ctx) != ctx->unprocessed_len) {\n            /*\n             * For decrypt operations, expect a full block,\n             * or an empty block if no padding\n             */\n            if (NULL == ctx->add_padding && 0 == ctx->unprocessed_len) {\n                return 0;\n            }\n\n            return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;\n        }\n\n        /* cipher block */\n        if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx,\n                                                                            ctx->operation,\n                                                                            mbedtls_cipher_get_block_size(\n                                                                                ctx),\n                                                                            ctx->iv,\n                                                                            ctx->unprocessed_data,\n                                                                            output))) {\n            return ret;\n        }\n\n        /* Set output size for decryption */\n        if (MBEDTLS_DECRYPT == ctx->operation) {\n            return ctx->get_padding(output, mbedtls_cipher_get_block_size(ctx),\n                                    olen, invalid_padding);\n        }\n\n        /* Set output size for encryption */\n        *olen = mbedtls_cipher_get_block_size(ctx);\n        return 0;\n    }\n#else\n    ((void) output);\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n}\n\nint mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx,\n                          unsigned char *output, size_t *olen)\n{\n    size_t invalid_padding = 0;\n    int ret = mbedtls_cipher_finish_padded(ctx, output, olen,\n                                           &invalid_padding);\n    if (ret == 0) {\n        ret = mbedtls_ct_error_if_else_0(invalid_padding,\n                                         MBEDTLS_ERR_CIPHER_INVALID_PADDING);\n    }\n    return ret;\n}\n\n#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)\nint mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx,\n                                    mbedtls_cipher_padding_t mode)\n{\n    if (NULL == ctx->cipher_info ||\n        MBEDTLS_MODE_CBC != ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ctx->psa_enabled == 1) {\n        /* While PSA Crypto knows about CBC padding\n         * schemes, we currently don't make them\n         * accessible through the cipher layer. */\n        if (mode != MBEDTLS_PADDING_NONE) {\n            return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n        }\n\n        return 0;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\n    switch (mode) {\n#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)\n        case MBEDTLS_PADDING_PKCS7:\n            ctx->add_padding = add_pkcs_padding;\n            ctx->get_padding = mbedtls_get_pkcs_padding;\n            break;\n#endif\n#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)\n        case MBEDTLS_PADDING_ONE_AND_ZEROS:\n            ctx->add_padding = add_one_and_zeros_padding;\n            ctx->get_padding = get_one_and_zeros_padding;\n            break;\n#endif\n#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)\n        case MBEDTLS_PADDING_ZEROS_AND_LEN:\n            ctx->add_padding = add_zeros_and_len_padding;\n            ctx->get_padding = get_zeros_and_len_padding;\n            break;\n#endif\n#if defined(MBEDTLS_CIPHER_PADDING_ZEROS)\n        case MBEDTLS_PADDING_ZEROS:\n            ctx->add_padding = add_zeros_padding;\n            ctx->get_padding = get_zeros_padding;\n            break;\n#endif\n        case MBEDTLS_PADDING_NONE:\n            ctx->add_padding = NULL;\n            ctx->get_padding = get_no_padding;\n            break;\n\n        default:\n            return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */\n\n#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)\nint mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx,\n                             unsigned char *tag, size_t tag_len)\n{\n    if (ctx->cipher_info == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    if (MBEDTLS_ENCRYPT != ctx->operation) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ctx->psa_enabled == 1) {\n        /* While PSA Crypto has an API for multipart\n         * operations, we currently don't make it\n         * accessible through the cipher layer. */\n        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\n#if defined(MBEDTLS_GCM_C)\n    if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {\n        size_t output_length;\n        /* The code here doesn't yet support alternative implementations\n         * that can delay up to a block of output. */\n        return mbedtls_gcm_finish((mbedtls_gcm_context *) ctx->cipher_ctx,\n                                  NULL, 0, &output_length,\n                                  tag, tag_len);\n    }\n#endif\n\n#if defined(MBEDTLS_CHACHAPOLY_C)\n    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) {\n        /* Don't allow truncated MAC for Poly1305 */\n        if (tag_len != 16U) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        return mbedtls_chachapoly_finish(\n            (mbedtls_chachapoly_context *) ctx->cipher_ctx, tag);\n    }\n#endif\n\n    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n}\n\nint mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx,\n                             const unsigned char *tag, size_t tag_len)\n{\n    unsigned char check_tag[16];\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (ctx->cipher_info == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    if (MBEDTLS_DECRYPT != ctx->operation) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ctx->psa_enabled == 1) {\n        /* While PSA Crypto has an API for multipart\n         * operations, we currently don't make it\n         * accessible through the cipher layer. */\n        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\n    /* Status to return on a non-authenticated algorithm. */\n    ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n\n#if defined(MBEDTLS_GCM_C)\n    if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {\n        size_t output_length;\n        /* The code here doesn't yet support alternative implementations\n         * that can delay up to a block of output. */\n\n        if (tag_len > sizeof(check_tag)) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        if (0 != (ret = mbedtls_gcm_finish(\n                      (mbedtls_gcm_context *) ctx->cipher_ctx,\n                      NULL, 0, &output_length,\n                      check_tag, tag_len))) {\n            return ret;\n        }\n\n        /* Check the tag in \"constant-time\" */\n        if (mbedtls_ct_memcmp(tag, check_tag, tag_len) != 0) {\n            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;\n            goto exit;\n        }\n    }\n#endif /* MBEDTLS_GCM_C */\n\n#if defined(MBEDTLS_CHACHAPOLY_C)\n    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) {\n        /* Don't allow truncated MAC for Poly1305 */\n        if (tag_len != sizeof(check_tag)) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        ret = mbedtls_chachapoly_finish(\n            (mbedtls_chachapoly_context *) ctx->cipher_ctx, check_tag);\n        if (ret != 0) {\n            return ret;\n        }\n\n        /* Check the tag in \"constant-time\" */\n        if (mbedtls_ct_memcmp(tag, check_tag, tag_len) != 0) {\n            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;\n            goto exit;\n        }\n    }\n#endif /* MBEDTLS_CHACHAPOLY_C */\n\nexit:\n    mbedtls_platform_zeroize(check_tag, tag_len);\n    return ret;\n}\n#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */\n\n/*\n * Packet-oriented wrapper for non-AEAD modes\n */\nint mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx,\n                         const unsigned char *iv, size_t iv_len,\n                         const unsigned char *input, size_t ilen,\n                         unsigned char *output, size_t *olen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t finish_olen;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ctx->psa_enabled == 1) {\n        /* As in the non-PSA case, we don't check that\n         * a key has been set. If not, the key slot will\n         * still be in its default state of 0, which is\n         * guaranteed to be invalid, hence the PSA-call\n         * below will gracefully fail. */\n        mbedtls_cipher_context_psa * const cipher_psa =\n            (mbedtls_cipher_context_psa *) ctx->cipher_ctx;\n\n        psa_status_t status;\n        psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT;\n        size_t part_len;\n\n        if (ctx->operation == MBEDTLS_DECRYPT) {\n            status = psa_cipher_decrypt_setup(&cipher_op,\n                                              cipher_psa->slot,\n                                              cipher_psa->alg);\n        } else if (ctx->operation == MBEDTLS_ENCRYPT) {\n            status = psa_cipher_encrypt_setup(&cipher_op,\n                                              cipher_psa->slot,\n                                              cipher_psa->alg);\n        } else {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        /* In the following, we can immediately return on an error,\n         * because the PSA Crypto API guarantees that cipher operations\n         * are terminated by unsuccessful calls to psa_cipher_update(),\n         * and by any call to psa_cipher_finish(). */\n        if (status != PSA_SUCCESS) {\n            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;\n        }\n\n        if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) != MBEDTLS_MODE_ECB) {\n            status = psa_cipher_set_iv(&cipher_op, iv, iv_len);\n            if (status != PSA_SUCCESS) {\n                return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;\n            }\n        }\n\n        status = psa_cipher_update(&cipher_op,\n                                   input, ilen,\n                                   output, ilen, olen);\n        if (status != PSA_SUCCESS) {\n            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;\n        }\n\n        status = psa_cipher_finish(&cipher_op,\n                                   output + *olen, ilen - *olen,\n                                   &part_len);\n        if (status != PSA_SUCCESS) {\n            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;\n        }\n\n        *olen += part_len;\n        return 0;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\n    if ((ret = mbedtls_cipher_set_iv(ctx, iv, iv_len)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_cipher_reset(ctx)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_cipher_update(ctx, input, ilen,\n                                     output, olen)) != 0) {\n        return ret;\n    }\n\n    size_t invalid_padding = 0;\n    if ((ret = mbedtls_cipher_finish_padded(ctx, output + *olen,\n                                            &finish_olen,\n                                            &invalid_padding)) != 0) {\n        return ret;\n    }\n    *olen += finish_olen;\n\n    ret = mbedtls_ct_error_if_else_0(invalid_padding,\n                                     MBEDTLS_ERR_CIPHER_INVALID_PADDING);\n    return ret;\n}\n\n#if defined(MBEDTLS_CIPHER_MODE_AEAD)\n/*\n * Packet-oriented encryption for AEAD modes: internal function used by\n * mbedtls_cipher_auth_encrypt_ext().\n */\nstatic int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx,\n                                       const unsigned char *iv, size_t iv_len,\n                                       const unsigned char *ad, size_t ad_len,\n                                       const unsigned char *input, size_t ilen,\n                                       unsigned char *output, size_t *olen,\n                                       unsigned char *tag, size_t tag_len)\n{\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ctx->psa_enabled == 1) {\n        /* As in the non-PSA case, we don't check that\n         * a key has been set. If not, the key slot will\n         * still be in its default state of 0, which is\n         * guaranteed to be invalid, hence the PSA-call\n         * below will gracefully fail. */\n        mbedtls_cipher_context_psa * const cipher_psa =\n            (mbedtls_cipher_context_psa *) ctx->cipher_ctx;\n\n        psa_status_t status;\n\n        /* PSA Crypto API always writes the authentication tag\n         * at the end of the encrypted message. */\n        if (output == NULL || tag != output + ilen) {\n            return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n        }\n\n        status = psa_aead_encrypt(cipher_psa->slot,\n                                  cipher_psa->alg,\n                                  iv, iv_len,\n                                  ad, ad_len,\n                                  input, ilen,\n                                  output, ilen + tag_len, olen);\n        if (status != PSA_SUCCESS) {\n            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;\n        }\n\n        *olen -= tag_len;\n        return 0;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\n#if defined(MBEDTLS_GCM_C)\n    if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {\n        *olen = ilen;\n        return mbedtls_gcm_crypt_and_tag(ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT,\n                                         ilen, iv, iv_len, ad, ad_len,\n                                         input, output, tag_len, tag);\n    }\n#endif /* MBEDTLS_GCM_C */\n#if defined(MBEDTLS_CCM_C)\n    if (MBEDTLS_MODE_CCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {\n        *olen = ilen;\n        return mbedtls_ccm_encrypt_and_tag(ctx->cipher_ctx, ilen,\n                                           iv, iv_len, ad, ad_len, input, output,\n                                           tag, tag_len);\n    }\n#endif /* MBEDTLS_CCM_C */\n#if defined(MBEDTLS_CHACHAPOLY_C)\n    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) {\n        /* ChachaPoly has fixed length nonce and MAC (tag) */\n        if ((iv_len != mbedtls_cipher_info_get_iv_size(ctx->cipher_info)) ||\n            (tag_len != 16U)) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        *olen = ilen;\n        return mbedtls_chachapoly_encrypt_and_tag(ctx->cipher_ctx,\n                                                  ilen, iv, ad, ad_len, input, output, tag);\n    }\n#endif /* MBEDTLS_CHACHAPOLY_C */\n\n    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n}\n\n/*\n * Packet-oriented encryption for AEAD modes: internal function used by\n * mbedtls_cipher_auth_encrypt_ext().\n */\nstatic int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx,\n                                       const unsigned char *iv, size_t iv_len,\n                                       const unsigned char *ad, size_t ad_len,\n                                       const unsigned char *input, size_t ilen,\n                                       unsigned char *output, size_t *olen,\n                                       const unsigned char *tag, size_t tag_len)\n{\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ctx->psa_enabled == 1) {\n        /* As in the non-PSA case, we don't check that\n         * a key has been set. If not, the key slot will\n         * still be in its default state of 0, which is\n         * guaranteed to be invalid, hence the PSA-call\n         * below will gracefully fail. */\n        mbedtls_cipher_context_psa * const cipher_psa =\n            (mbedtls_cipher_context_psa *) ctx->cipher_ctx;\n\n        psa_status_t status;\n\n        /* PSA Crypto API always writes the authentication tag\n         * at the end of the encrypted message. */\n        if (input == NULL || tag != input + ilen) {\n            return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n        }\n\n        status = psa_aead_decrypt(cipher_psa->slot,\n                                  cipher_psa->alg,\n                                  iv, iv_len,\n                                  ad, ad_len,\n                                  input, ilen + tag_len,\n                                  output, ilen, olen);\n        if (status == PSA_ERROR_INVALID_SIGNATURE) {\n            return MBEDTLS_ERR_CIPHER_AUTH_FAILED;\n        } else if (status != PSA_SUCCESS) {\n            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;\n        }\n\n        return 0;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */\n\n#if defined(MBEDTLS_GCM_C)\n    if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n        *olen = ilen;\n        ret = mbedtls_gcm_auth_decrypt(ctx->cipher_ctx, ilen,\n                                       iv, iv_len, ad, ad_len,\n                                       tag, tag_len, input, output);\n\n        if (ret == MBEDTLS_ERR_GCM_AUTH_FAILED) {\n            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;\n        }\n\n        return ret;\n    }\n#endif /* MBEDTLS_GCM_C */\n#if defined(MBEDTLS_CCM_C)\n    if (MBEDTLS_MODE_CCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n        *olen = ilen;\n        ret = mbedtls_ccm_auth_decrypt(ctx->cipher_ctx, ilen,\n                                       iv, iv_len, ad, ad_len,\n                                       input, output, tag, tag_len);\n\n        if (ret == MBEDTLS_ERR_CCM_AUTH_FAILED) {\n            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;\n        }\n\n        return ret;\n    }\n#endif /* MBEDTLS_CCM_C */\n#if defined(MBEDTLS_CHACHAPOLY_C)\n    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n        /* ChachaPoly has fixed length nonce and MAC (tag) */\n        if ((iv_len != mbedtls_cipher_info_get_iv_size(ctx->cipher_info)) ||\n            (tag_len != 16U)) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        *olen = ilen;\n        ret = mbedtls_chachapoly_auth_decrypt(ctx->cipher_ctx, ilen,\n                                              iv, ad, ad_len, tag, input, output);\n\n        if (ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) {\n            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;\n        }\n\n        return ret;\n    }\n#endif /* MBEDTLS_CHACHAPOLY_C */\n\n    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n}\n#endif /* MBEDTLS_CIPHER_MODE_AEAD */\n\n#if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C)\n/*\n * Packet-oriented encryption for AEAD/NIST_KW: public function.\n */\nint mbedtls_cipher_auth_encrypt_ext(mbedtls_cipher_context_t *ctx,\n                                    const unsigned char *iv, size_t iv_len,\n                                    const unsigned char *ad, size_t ad_len,\n                                    const unsigned char *input, size_t ilen,\n                                    unsigned char *output, size_t output_len,\n                                    size_t *olen, size_t tag_len)\n{\n#if defined(MBEDTLS_NIST_KW_C)\n    if (\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n        ctx->psa_enabled == 0 &&\n#endif\n        (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||\n         MBEDTLS_MODE_KWP == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode))) {\n        mbedtls_nist_kw_mode_t mode =\n            (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) ?\n            MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;\n\n        /* There is no iv, tag or ad associated with KW and KWP,\n         * so these length should be 0 as documented. */\n        if (iv_len != 0 || tag_len != 0 || ad_len != 0) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        (void) iv;\n        (void) ad;\n\n        return mbedtls_nist_kw_wrap(ctx->cipher_ctx, mode, input, ilen,\n                                    output, olen, output_len);\n    }\n#endif /* MBEDTLS_NIST_KW_C */\n\n#if defined(MBEDTLS_CIPHER_MODE_AEAD)\n    /* AEAD case: check length before passing on to shared function */\n    if (output_len < ilen + tag_len) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    int ret = mbedtls_cipher_aead_encrypt(ctx, iv, iv_len, ad, ad_len,\n                                          input, ilen, output, olen,\n                                          output + ilen, tag_len);\n    *olen += tag_len;\n    return ret;\n#else\n    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n#endif /* MBEDTLS_CIPHER_MODE_AEAD */\n}\n\n/*\n * Packet-oriented decryption for AEAD/NIST_KW: public function.\n */\nint mbedtls_cipher_auth_decrypt_ext(mbedtls_cipher_context_t *ctx,\n                                    const unsigned char *iv, size_t iv_len,\n                                    const unsigned char *ad, size_t ad_len,\n                                    const unsigned char *input, size_t ilen,\n                                    unsigned char *output, size_t output_len,\n                                    size_t *olen, size_t tag_len)\n{\n#if defined(MBEDTLS_NIST_KW_C)\n    if (\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n        ctx->psa_enabled == 0 &&\n#endif\n        (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||\n         MBEDTLS_MODE_KWP == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode))) {\n        mbedtls_nist_kw_mode_t mode =\n            (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) ?\n            MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;\n\n        /* There is no iv, tag or ad associated with KW and KWP,\n         * so these length should be 0 as documented. */\n        if (iv_len != 0 || tag_len != 0 || ad_len != 0) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        (void) iv;\n        (void) ad;\n\n        return mbedtls_nist_kw_unwrap(ctx->cipher_ctx, mode, input, ilen,\n                                      output, olen, output_len);\n    }\n#endif /* MBEDTLS_NIST_KW_C */\n\n#if defined(MBEDTLS_CIPHER_MODE_AEAD)\n    /* AEAD case: check length before passing on to shared function */\n    if (ilen < tag_len || output_len < ilen - tag_len) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    return mbedtls_cipher_aead_decrypt(ctx, iv, iv_len, ad, ad_len,\n                                       input, ilen - tag_len, output, olen,\n                                       input + ilen - tag_len, tag_len);\n#else\n    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n#endif /* MBEDTLS_CIPHER_MODE_AEAD */\n}\n#endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */\n\n#endif /* MBEDTLS_CIPHER_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/cipher_invasive.h",
    "content": "/**\n * \\file cipher_invasive.h\n *\n * \\brief Cipher module: interfaces for invasive testing only.\n *\n * The interfaces in this file are intended for testing purposes only.\n * They SHOULD NOT be made available in library integrations except when\n * building the library for testing.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_CIPHER_INVASIVE_H\n#define MBEDTLS_CIPHER_INVASIVE_H\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_CIPHER_C)\n\nMBEDTLS_STATIC_TESTABLE int mbedtls_get_pkcs_padding(unsigned char *input,\n                                                     size_t input_len,\n                                                     size_t *data_len,\n                                                     size_t *invalid_padding);\n\n#endif\n\n#endif /* MBEDTLS_CIPHER_INVASIVE_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/cipher_wrap.c",
    "content": "/**\n * \\file cipher_wrap.c\n *\n * \\brief Generic cipher wrapper for Mbed TLS\n *\n * \\author Adriaan de Jong <dejong@fox-it.com>\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_CIPHER_C)\n\n#include \"cipher_wrap.h\"\n#include \"mbedtls/error.h\"\n\n#if defined(MBEDTLS_CHACHAPOLY_C)\n#include \"mbedtls/chachapoly.h\"\n#endif\n\n#if defined(MBEDTLS_AES_C)\n#include \"mbedtls/aes.h\"\n#endif\n\n#if defined(MBEDTLS_CAMELLIA_C)\n#include \"mbedtls/camellia.h\"\n#endif\n\n#if defined(MBEDTLS_ARIA_C)\n#include \"mbedtls/aria.h\"\n#endif\n\n#if defined(MBEDTLS_DES_C)\n#include \"mbedtls/des.h\"\n#endif\n\n#if defined(MBEDTLS_CHACHA20_C)\n#include \"mbedtls/chacha20.h\"\n#endif\n\n#if defined(MBEDTLS_GCM_C)\n#include \"mbedtls/gcm.h\"\n#endif\n\n#if defined(MBEDTLS_CCM_C)\n#include \"mbedtls/ccm.h\"\n#endif\n\n#if defined(MBEDTLS_NIST_KW_C)\n#include \"mbedtls/nist_kw.h\"\n#endif\n\n#if defined(MBEDTLS_CIPHER_NULL_CIPHER)\n#include <string.h>\n#endif\n\n#include \"mbedtls/platform.h\"\n\nenum mbedtls_cipher_base_index {\n#if defined(MBEDTLS_AES_C)\n    MBEDTLS_CIPHER_BASE_INDEX_AES,\n#endif\n#if defined(MBEDTLS_ARIA_C)\n    MBEDTLS_CIPHER_BASE_INDEX_ARIA,\n#endif\n#if defined(MBEDTLS_CAMELLIA_C)\n    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA,\n#endif\n#if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA)\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_AES,\n#endif\n#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_ARIA_C)\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA,\n#endif\n#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CAMELLIA_C)\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA,\n#endif\n#if defined(MBEDTLS_CHACHA20_C)\n    MBEDTLS_CIPHER_BASE_INDEX_CHACHA20_BASE,\n#endif\n#if defined(MBEDTLS_CHACHAPOLY_C)\n    MBEDTLS_CIPHER_BASE_INDEX_CHACHAPOLY_BASE,\n#endif\n#if defined(MBEDTLS_DES_C)\n    MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3,\n#endif\n#if defined(MBEDTLS_DES_C)\n    MBEDTLS_CIPHER_BASE_INDEX_DES_EDE,\n#endif\n#if defined(MBEDTLS_DES_C)\n    MBEDTLS_CIPHER_BASE_INDEX_DES,\n#endif\n#if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA)\n    MBEDTLS_CIPHER_BASE_INDEX_GCM_AES,\n#endif\n#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_ARIA_C)\n    MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA,\n#endif\n#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_CAMELLIA_C)\n    MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA,\n#endif\n#if defined(MBEDTLS_NIST_KW_C)\n    MBEDTLS_CIPHER_BASE_INDEX_KW_AES,\n#endif\n#if defined(MBEDTLS_CIPHER_NULL_CIPHER)\n    MBEDTLS_CIPHER_BASE_INDEX_NULL_BASE,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS) && defined(MBEDTLS_AES_C)\n    MBEDTLS_CIPHER_BASE_INDEX_XTS_AES,\n#endif\n    /* Prevent compile failure due to empty enum */\n    MBEDTLS_CIPHER_BASE_PREVENT_EMPTY_ENUM\n};\n\n#if defined(MBEDTLS_GCM_C) && \\\n    (defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) || \\\n    defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C))\n/* shared by all GCM ciphers */\nstatic void *gcm_ctx_alloc(void)\n{\n    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_gcm_context));\n\n    if (ctx != NULL) {\n        mbedtls_gcm_init((mbedtls_gcm_context *) ctx);\n    }\n\n    return ctx;\n}\n\nstatic void gcm_ctx_free(void *ctx)\n{\n    mbedtls_gcm_free(ctx);\n    mbedtls_free(ctx);\n}\n#endif /* MBEDTLS_GCM_C */\n\n#if defined(MBEDTLS_CCM_C) && \\\n    (defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) || \\\n    defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C))\n/* shared by all CCM ciphers */\nstatic void *ccm_ctx_alloc(void)\n{\n    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ccm_context));\n\n    if (ctx != NULL) {\n        mbedtls_ccm_init((mbedtls_ccm_context *) ctx);\n    }\n\n    return ctx;\n}\n\nstatic void ccm_ctx_free(void *ctx)\n{\n    mbedtls_ccm_free(ctx);\n    mbedtls_free(ctx);\n}\n#endif /* MBEDTLS_CCM_C */\n\n#if defined(MBEDTLS_AES_C)\n\nstatic int aes_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation,\n                              const unsigned char *input, unsigned char *output)\n{\n    return mbedtls_aes_crypt_ecb((mbedtls_aes_context *) ctx, operation, input, output);\n}\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\nstatic int aes_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length,\n                              unsigned char *iv, const unsigned char *input, unsigned char *output)\n{\n    return mbedtls_aes_crypt_cbc((mbedtls_aes_context *) ctx, operation, length, iv, input,\n                                 output);\n}\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\nstatic int aes_crypt_cfb128_wrap(void *ctx, mbedtls_operation_t operation,\n                                 size_t length, size_t *iv_off, unsigned char *iv,\n                                 const unsigned char *input, unsigned char *output)\n{\n    return mbedtls_aes_crypt_cfb128((mbedtls_aes_context *) ctx, operation, length, iv_off, iv,\n                                    input, output);\n}\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\nstatic int aes_crypt_ofb_wrap(void *ctx, size_t length, size_t *iv_off,\n                              unsigned char *iv, const unsigned char *input, unsigned char *output)\n{\n    return mbedtls_aes_crypt_ofb((mbedtls_aes_context *) ctx, length, iv_off,\n                                 iv, input, output);\n}\n#endif /* MBEDTLS_CIPHER_MODE_OFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\nstatic int aes_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off,\n                              unsigned char *nonce_counter, unsigned char *stream_block,\n                              const unsigned char *input, unsigned char *output)\n{\n    return mbedtls_aes_crypt_ctr((mbedtls_aes_context *) ctx, length, nc_off, nonce_counter,\n                                 stream_block, input, output);\n}\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\nstatic int aes_crypt_xts_wrap(void *ctx, mbedtls_operation_t operation,\n                              size_t length,\n                              const unsigned char data_unit[16],\n                              const unsigned char *input,\n                              unsigned char *output)\n{\n    mbedtls_aes_xts_context *xts_ctx = ctx;\n    int mode;\n\n    switch (operation) {\n        case MBEDTLS_ENCRYPT:\n            mode = MBEDTLS_AES_ENCRYPT;\n            break;\n        case MBEDTLS_DECRYPT:\n            mode = MBEDTLS_AES_DECRYPT;\n            break;\n        default:\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    return mbedtls_aes_crypt_xts(xts_ctx, mode, length,\n                                 data_unit, input, output);\n}\n#endif /* MBEDTLS_CIPHER_MODE_XTS */\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\nstatic int aes_setkey_dec_wrap(void *ctx, const unsigned char *key,\n                               unsigned int key_bitlen)\n{\n    return mbedtls_aes_setkey_dec((mbedtls_aes_context *) ctx, key, key_bitlen);\n}\n#endif\n\nstatic int aes_setkey_enc_wrap(void *ctx, const unsigned char *key,\n                               unsigned int key_bitlen)\n{\n    return mbedtls_aes_setkey_enc((mbedtls_aes_context *) ctx, key, key_bitlen);\n}\n\nstatic void *aes_ctx_alloc(void)\n{\n    mbedtls_aes_context *aes = mbedtls_calloc(1, sizeof(mbedtls_aes_context));\n\n    if (aes == NULL) {\n        return NULL;\n    }\n\n    mbedtls_aes_init(aes);\n\n    return aes;\n}\n\nstatic void aes_ctx_free(void *ctx)\n{\n    mbedtls_aes_free((mbedtls_aes_context *) ctx);\n    mbedtls_free(ctx);\n}\n\nstatic const mbedtls_cipher_base_t aes_info = {\n    MBEDTLS_CIPHER_ID_AES,\n    aes_crypt_ecb_wrap,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    aes_crypt_cbc_wrap,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    aes_crypt_cfb128_wrap,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    aes_crypt_ofb_wrap,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    aes_crypt_ctr_wrap,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    NULL,\n#endif\n    aes_setkey_enc_wrap,\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    aes_setkey_dec_wrap,\n#endif\n    aes_ctx_alloc,\n    aes_ctx_free\n};\n\nstatic const mbedtls_cipher_info_t aes_128_ecb_info = {\n    \"AES-128-ECB\",\n    16,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_ECB,\n    MBEDTLS_CIPHER_AES_128_ECB,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_AES\n};\n\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic const mbedtls_cipher_info_t aes_192_ecb_info = {\n    \"AES-192-ECB\",\n    16,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_ECB,\n    MBEDTLS_CIPHER_AES_192_ECB,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_AES\n};\n\nstatic const mbedtls_cipher_info_t aes_256_ecb_info = {\n    \"AES-256-ECB\",\n    16,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_ECB,\n    MBEDTLS_CIPHER_AES_256_ECB,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_AES\n};\n#endif\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\nstatic const mbedtls_cipher_info_t aes_128_cbc_info = {\n    \"AES-128-CBC\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CBC,\n    MBEDTLS_CIPHER_AES_128_CBC,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_AES\n};\n\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic const mbedtls_cipher_info_t aes_192_cbc_info = {\n    \"AES-192-CBC\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CBC,\n    MBEDTLS_CIPHER_AES_192_CBC,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_AES\n};\n\nstatic const mbedtls_cipher_info_t aes_256_cbc_info = {\n    \"AES-256-CBC\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CBC,\n    MBEDTLS_CIPHER_AES_256_CBC,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_AES\n};\n#endif\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\nstatic const mbedtls_cipher_info_t aes_128_cfb128_info = {\n    \"AES-128-CFB128\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CFB,\n    MBEDTLS_CIPHER_AES_128_CFB128,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_AES\n};\n\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic const mbedtls_cipher_info_t aes_192_cfb128_info = {\n    \"AES-192-CFB128\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CFB,\n    MBEDTLS_CIPHER_AES_192_CFB128,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_AES\n};\n\nstatic const mbedtls_cipher_info_t aes_256_cfb128_info = {\n    \"AES-256-CFB128\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CFB,\n    MBEDTLS_CIPHER_AES_256_CFB128,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_AES\n};\n#endif\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\nstatic const mbedtls_cipher_info_t aes_128_ofb_info = {\n    \"AES-128-OFB\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_OFB,\n    MBEDTLS_CIPHER_AES_128_OFB,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_AES\n};\n\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic const mbedtls_cipher_info_t aes_192_ofb_info = {\n    \"AES-192-OFB\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_OFB,\n    MBEDTLS_CIPHER_AES_192_OFB,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_AES\n};\n\nstatic const mbedtls_cipher_info_t aes_256_ofb_info = {\n    \"AES-256-OFB\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_OFB,\n    MBEDTLS_CIPHER_AES_256_OFB,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_AES\n};\n#endif\n#endif /* MBEDTLS_CIPHER_MODE_OFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\nstatic const mbedtls_cipher_info_t aes_128_ctr_info = {\n    \"AES-128-CTR\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CTR,\n    MBEDTLS_CIPHER_AES_128_CTR,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_AES\n};\n\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic const mbedtls_cipher_info_t aes_192_ctr_info = {\n    \"AES-192-CTR\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CTR,\n    MBEDTLS_CIPHER_AES_192_CTR,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_AES\n};\n\nstatic const mbedtls_cipher_info_t aes_256_ctr_info = {\n    \"AES-256-CTR\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CTR,\n    MBEDTLS_CIPHER_AES_256_CTR,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_AES\n};\n#endif\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\nstatic int xts_aes_setkey_enc_wrap(void *ctx, const unsigned char *key,\n                                   unsigned int key_bitlen)\n{\n    mbedtls_aes_xts_context *xts_ctx = ctx;\n    return mbedtls_aes_xts_setkey_enc(xts_ctx, key, key_bitlen);\n}\n\nstatic int xts_aes_setkey_dec_wrap(void *ctx, const unsigned char *key,\n                                   unsigned int key_bitlen)\n{\n    mbedtls_aes_xts_context *xts_ctx = ctx;\n    return mbedtls_aes_xts_setkey_dec(xts_ctx, key, key_bitlen);\n}\n\nstatic void *xts_aes_ctx_alloc(void)\n{\n    mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc(1, sizeof(*xts_ctx));\n\n    if (xts_ctx != NULL) {\n        mbedtls_aes_xts_init(xts_ctx);\n    }\n\n    return xts_ctx;\n}\n\nstatic void xts_aes_ctx_free(void *ctx)\n{\n    mbedtls_aes_xts_context *xts_ctx = ctx;\n\n    if (xts_ctx == NULL) {\n        return;\n    }\n\n    mbedtls_aes_xts_free(xts_ctx);\n    mbedtls_free(xts_ctx);\n}\n\nstatic const mbedtls_cipher_base_t xts_aes_info = {\n    MBEDTLS_CIPHER_ID_AES,\n    NULL,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    aes_crypt_xts_wrap,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    NULL,\n#endif\n    xts_aes_setkey_enc_wrap,\n    xts_aes_setkey_dec_wrap,\n    xts_aes_ctx_alloc,\n    xts_aes_ctx_free\n};\n\nstatic const mbedtls_cipher_info_t aes_128_xts_info = {\n    \"AES-128-XTS\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_XTS,\n    MBEDTLS_CIPHER_AES_128_XTS,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_XTS_AES\n};\n\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic const mbedtls_cipher_info_t aes_256_xts_info = {\n    \"AES-256-XTS\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    512 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_XTS,\n    MBEDTLS_CIPHER_AES_256_XTS,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_XTS_AES\n};\n#endif\n#endif /* MBEDTLS_CIPHER_MODE_XTS */\n#endif /* MBEDTLS_AES_C */\n\n#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_CCM_GCM_CAN_AES)\nstatic int gcm_aes_setkey_wrap(void *ctx, const unsigned char *key,\n                               unsigned int key_bitlen)\n{\n    return mbedtls_gcm_setkey((mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES,\n                              key, key_bitlen);\n}\n#endif /* MBEDTLS_GCM_C && MBEDTLS_CCM_GCM_CAN_AES */\n\n#if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA)\nstatic const mbedtls_cipher_base_t gcm_aes_info = {\n    MBEDTLS_CIPHER_ID_AES,\n    NULL,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    NULL,\n#endif\n#if defined(MBEDTLS_GCM_C)\n    gcm_aes_setkey_wrap,\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    gcm_aes_setkey_wrap,\n#endif\n    gcm_ctx_alloc,\n    gcm_ctx_free,\n#else\n    NULL,\n    NULL,\n    NULL,\n    NULL,\n#endif /* MBEDTLS_GCM_C */\n};\n#endif /* MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA */\n\n#if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA)\nstatic const mbedtls_cipher_info_t aes_128_gcm_info = {\n    \"AES-128-GCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_GCM,\n    MBEDTLS_CIPHER_AES_128_GCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_GCM_AES\n};\n\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic const mbedtls_cipher_info_t aes_192_gcm_info = {\n    \"AES-192-GCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_GCM,\n    MBEDTLS_CIPHER_AES_192_GCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_GCM_AES\n};\n\nstatic const mbedtls_cipher_info_t aes_256_gcm_info = {\n    \"AES-256-GCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_GCM,\n    MBEDTLS_CIPHER_AES_256_GCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_GCM_AES\n};\n#endif\n#endif /* MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA */\n\n#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CCM_GCM_CAN_AES)\nstatic int ccm_aes_setkey_wrap(void *ctx, const unsigned char *key,\n                               unsigned int key_bitlen)\n{\n    return mbedtls_ccm_setkey((mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES,\n                              key, key_bitlen);\n}\n#endif /* MBEDTLS_CCM_C && MBEDTLS_CCM_GCM_CAN_AES */\n\n#if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA)\nstatic const mbedtls_cipher_base_t ccm_aes_info = {\n    MBEDTLS_CIPHER_ID_AES,\n    NULL,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    NULL,\n#endif\n#if defined(MBEDTLS_CCM_C)\n    ccm_aes_setkey_wrap,\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    ccm_aes_setkey_wrap,\n#endif\n    ccm_ctx_alloc,\n    ccm_ctx_free,\n#else\n    NULL,\n    NULL,\n    NULL,\n    NULL,\n#endif\n};\n#endif /* MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA */\n\n#if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA)\nstatic const mbedtls_cipher_info_t aes_128_ccm_info = {\n    \"AES-128-CCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM,\n    MBEDTLS_CIPHER_AES_128_CCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_AES\n};\n\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic const mbedtls_cipher_info_t aes_192_ccm_info = {\n    \"AES-192-CCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM,\n    MBEDTLS_CIPHER_AES_192_CCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_AES\n};\n\nstatic const mbedtls_cipher_info_t aes_256_ccm_info = {\n    \"AES-256-CCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM,\n    MBEDTLS_CIPHER_AES_256_CCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_AES\n};\n#endif\n#endif /* MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA */\n\n#if defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA)\nstatic const mbedtls_cipher_info_t aes_128_ccm_star_no_tag_info = {\n    \"AES-128-CCM*-NO-TAG\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_AES\n};\n\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic const mbedtls_cipher_info_t aes_192_ccm_star_no_tag_info = {\n    \"AES-192-CCM*-NO-TAG\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_AES\n};\n\nstatic const mbedtls_cipher_info_t aes_256_ccm_star_no_tag_info = {\n    \"AES-256-CCM*-NO-TAG\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_AES\n};\n#endif\n#endif /* MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA */\n\n\n#if defined(MBEDTLS_CAMELLIA_C)\n\nstatic int camellia_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation,\n                                   const unsigned char *input, unsigned char *output)\n{\n    return mbedtls_camellia_crypt_ecb((mbedtls_camellia_context *) ctx, operation, input,\n                                      output);\n}\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\nstatic int camellia_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation,\n                                   size_t length, unsigned char *iv,\n                                   const unsigned char *input, unsigned char *output)\n{\n    return mbedtls_camellia_crypt_cbc((mbedtls_camellia_context *) ctx, operation, length, iv,\n                                      input, output);\n}\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\nstatic int camellia_crypt_cfb128_wrap(void *ctx, mbedtls_operation_t operation,\n                                      size_t length, size_t *iv_off, unsigned char *iv,\n                                      const unsigned char *input, unsigned char *output)\n{\n    return mbedtls_camellia_crypt_cfb128((mbedtls_camellia_context *) ctx, operation, length,\n                                         iv_off, iv, input, output);\n}\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\nstatic int camellia_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off,\n                                   unsigned char *nonce_counter, unsigned char *stream_block,\n                                   const unsigned char *input, unsigned char *output)\n{\n    return mbedtls_camellia_crypt_ctr((mbedtls_camellia_context *) ctx, length, nc_off,\n                                      nonce_counter, stream_block, input, output);\n}\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\nstatic int camellia_setkey_dec_wrap(void *ctx, const unsigned char *key,\n                                    unsigned int key_bitlen)\n{\n    return mbedtls_camellia_setkey_dec((mbedtls_camellia_context *) ctx, key, key_bitlen);\n}\n#endif\n\nstatic int camellia_setkey_enc_wrap(void *ctx, const unsigned char *key,\n                                    unsigned int key_bitlen)\n{\n    return mbedtls_camellia_setkey_enc((mbedtls_camellia_context *) ctx, key, key_bitlen);\n}\n\nstatic void *camellia_ctx_alloc(void)\n{\n    mbedtls_camellia_context *ctx;\n    ctx = mbedtls_calloc(1, sizeof(mbedtls_camellia_context));\n\n    if (ctx == NULL) {\n        return NULL;\n    }\n\n    mbedtls_camellia_init(ctx);\n\n    return ctx;\n}\n\nstatic void camellia_ctx_free(void *ctx)\n{\n    mbedtls_camellia_free((mbedtls_camellia_context *) ctx);\n    mbedtls_free(ctx);\n}\n\nstatic const mbedtls_cipher_base_t camellia_info = {\n    MBEDTLS_CIPHER_ID_CAMELLIA,\n    camellia_crypt_ecb_wrap,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    camellia_crypt_cbc_wrap,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    camellia_crypt_cfb128_wrap,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    camellia_crypt_ctr_wrap,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    NULL,\n#endif\n    camellia_setkey_enc_wrap,\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    camellia_setkey_dec_wrap,\n#endif\n    camellia_ctx_alloc,\n    camellia_ctx_free\n};\n\nstatic const mbedtls_cipher_info_t camellia_128_ecb_info = {\n    \"CAMELLIA-128-ECB\",\n    16,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_ECB,\n    MBEDTLS_CIPHER_CAMELLIA_128_ECB,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA\n};\n\nstatic const mbedtls_cipher_info_t camellia_192_ecb_info = {\n    \"CAMELLIA-192-ECB\",\n    16,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_ECB,\n    MBEDTLS_CIPHER_CAMELLIA_192_ECB,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA\n};\n\nstatic const mbedtls_cipher_info_t camellia_256_ecb_info = {\n    \"CAMELLIA-256-ECB\",\n    16,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_ECB,\n    MBEDTLS_CIPHER_CAMELLIA_256_ECB,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA\n};\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\nstatic const mbedtls_cipher_info_t camellia_128_cbc_info = {\n    \"CAMELLIA-128-CBC\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CBC,\n    MBEDTLS_CIPHER_CAMELLIA_128_CBC,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA\n};\n\nstatic const mbedtls_cipher_info_t camellia_192_cbc_info = {\n    \"CAMELLIA-192-CBC\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CBC,\n    MBEDTLS_CIPHER_CAMELLIA_192_CBC,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA\n};\n\nstatic const mbedtls_cipher_info_t camellia_256_cbc_info = {\n    \"CAMELLIA-256-CBC\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CBC,\n    MBEDTLS_CIPHER_CAMELLIA_256_CBC,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA\n};\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\nstatic const mbedtls_cipher_info_t camellia_128_cfb128_info = {\n    \"CAMELLIA-128-CFB128\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CFB,\n    MBEDTLS_CIPHER_CAMELLIA_128_CFB128,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA\n};\n\nstatic const mbedtls_cipher_info_t camellia_192_cfb128_info = {\n    \"CAMELLIA-192-CFB128\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CFB,\n    MBEDTLS_CIPHER_CAMELLIA_192_CFB128,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA\n};\n\nstatic const mbedtls_cipher_info_t camellia_256_cfb128_info = {\n    \"CAMELLIA-256-CFB128\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CFB,\n    MBEDTLS_CIPHER_CAMELLIA_256_CFB128,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA\n};\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\nstatic const mbedtls_cipher_info_t camellia_128_ctr_info = {\n    \"CAMELLIA-128-CTR\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CTR,\n    MBEDTLS_CIPHER_CAMELLIA_128_CTR,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA\n};\n\nstatic const mbedtls_cipher_info_t camellia_192_ctr_info = {\n    \"CAMELLIA-192-CTR\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CTR,\n    MBEDTLS_CIPHER_CAMELLIA_192_CTR,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA\n};\n\nstatic const mbedtls_cipher_info_t camellia_256_ctr_info = {\n    \"CAMELLIA-256-CTR\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CTR,\n    MBEDTLS_CIPHER_CAMELLIA_256_CTR,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA\n};\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n#if defined(MBEDTLS_GCM_C)\nstatic int gcm_camellia_setkey_wrap(void *ctx, const unsigned char *key,\n                                    unsigned int key_bitlen)\n{\n    return mbedtls_gcm_setkey((mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA,\n                              key, key_bitlen);\n}\n\nstatic const mbedtls_cipher_base_t gcm_camellia_info = {\n    MBEDTLS_CIPHER_ID_CAMELLIA,\n    NULL,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    NULL,\n#endif\n    gcm_camellia_setkey_wrap,\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    gcm_camellia_setkey_wrap,\n#endif\n    gcm_ctx_alloc,\n    gcm_ctx_free,\n};\n\nstatic const mbedtls_cipher_info_t camellia_128_gcm_info = {\n    \"CAMELLIA-128-GCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_GCM,\n    MBEDTLS_CIPHER_CAMELLIA_128_GCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA\n};\n\nstatic const mbedtls_cipher_info_t camellia_192_gcm_info = {\n    \"CAMELLIA-192-GCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_GCM,\n    MBEDTLS_CIPHER_CAMELLIA_192_GCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA\n};\n\nstatic const mbedtls_cipher_info_t camellia_256_gcm_info = {\n    \"CAMELLIA-256-GCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_GCM,\n    MBEDTLS_CIPHER_CAMELLIA_256_GCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA\n};\n#endif /* MBEDTLS_GCM_C */\n\n#if defined(MBEDTLS_CCM_C)\nstatic int ccm_camellia_setkey_wrap(void *ctx, const unsigned char *key,\n                                    unsigned int key_bitlen)\n{\n    return mbedtls_ccm_setkey((mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA,\n                              key, key_bitlen);\n}\n\nstatic const mbedtls_cipher_base_t ccm_camellia_info = {\n    MBEDTLS_CIPHER_ID_CAMELLIA,\n    NULL,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    NULL,\n#endif\n    ccm_camellia_setkey_wrap,\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    ccm_camellia_setkey_wrap,\n#endif\n    ccm_ctx_alloc,\n    ccm_ctx_free,\n};\n\nstatic const mbedtls_cipher_info_t camellia_128_ccm_info = {\n    \"CAMELLIA-128-CCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM,\n    MBEDTLS_CIPHER_CAMELLIA_128_CCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA\n};\n\nstatic const mbedtls_cipher_info_t camellia_192_ccm_info = {\n    \"CAMELLIA-192-CCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM,\n    MBEDTLS_CIPHER_CAMELLIA_192_CCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA\n};\n\nstatic const mbedtls_cipher_info_t camellia_256_ccm_info = {\n    \"CAMELLIA-256-CCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM,\n    MBEDTLS_CIPHER_CAMELLIA_256_CCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA\n};\n\nstatic const mbedtls_cipher_info_t camellia_128_ccm_star_no_tag_info = {\n    \"CAMELLIA-128-CCM*-NO-TAG\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA\n};\n\nstatic const mbedtls_cipher_info_t camellia_192_ccm_star_no_tag_info = {\n    \"CAMELLIA-192-CCM*-NO-TAG\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA\n};\n\nstatic const mbedtls_cipher_info_t camellia_256_ccm_star_no_tag_info = {\n    \"CAMELLIA-256-CCM*-NO-TAG\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA\n};\n#endif /* MBEDTLS_CCM_C */\n\n#endif /* MBEDTLS_CAMELLIA_C */\n\n#if defined(MBEDTLS_ARIA_C)\n\nstatic int aria_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation,\n                               const unsigned char *input, unsigned char *output)\n{\n    (void) operation;\n    return mbedtls_aria_crypt_ecb((mbedtls_aria_context *) ctx, input,\n                                  output);\n}\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\nstatic int aria_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation,\n                               size_t length, unsigned char *iv,\n                               const unsigned char *input, unsigned char *output)\n{\n    return mbedtls_aria_crypt_cbc((mbedtls_aria_context *) ctx, operation, length, iv,\n                                  input, output);\n}\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\nstatic int aria_crypt_cfb128_wrap(void *ctx, mbedtls_operation_t operation,\n                                  size_t length, size_t *iv_off, unsigned char *iv,\n                                  const unsigned char *input, unsigned char *output)\n{\n    return mbedtls_aria_crypt_cfb128((mbedtls_aria_context *) ctx, operation, length,\n                                     iv_off, iv, input, output);\n}\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\nstatic int aria_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off,\n                               unsigned char *nonce_counter, unsigned char *stream_block,\n                               const unsigned char *input, unsigned char *output)\n{\n    return mbedtls_aria_crypt_ctr((mbedtls_aria_context *) ctx, length, nc_off,\n                                  nonce_counter, stream_block, input, output);\n}\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\nstatic int aria_setkey_dec_wrap(void *ctx, const unsigned char *key,\n                                unsigned int key_bitlen)\n{\n    return mbedtls_aria_setkey_dec((mbedtls_aria_context *) ctx, key, key_bitlen);\n}\n#endif\n\nstatic int aria_setkey_enc_wrap(void *ctx, const unsigned char *key,\n                                unsigned int key_bitlen)\n{\n    return mbedtls_aria_setkey_enc((mbedtls_aria_context *) ctx, key, key_bitlen);\n}\n\nstatic void *aria_ctx_alloc(void)\n{\n    mbedtls_aria_context *ctx;\n    ctx = mbedtls_calloc(1, sizeof(mbedtls_aria_context));\n\n    if (ctx == NULL) {\n        return NULL;\n    }\n\n    mbedtls_aria_init(ctx);\n\n    return ctx;\n}\n\nstatic void aria_ctx_free(void *ctx)\n{\n    mbedtls_aria_free((mbedtls_aria_context *) ctx);\n    mbedtls_free(ctx);\n}\n\nstatic const mbedtls_cipher_base_t aria_info = {\n    MBEDTLS_CIPHER_ID_ARIA,\n    aria_crypt_ecb_wrap,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    aria_crypt_cbc_wrap,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    aria_crypt_cfb128_wrap,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    aria_crypt_ctr_wrap,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    NULL,\n#endif\n    aria_setkey_enc_wrap,\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    aria_setkey_dec_wrap,\n#endif\n    aria_ctx_alloc,\n    aria_ctx_free\n};\n\nstatic const mbedtls_cipher_info_t aria_128_ecb_info = {\n    \"ARIA-128-ECB\",\n    16,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_ECB,\n    MBEDTLS_CIPHER_ARIA_128_ECB,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_ARIA\n};\n\nstatic const mbedtls_cipher_info_t aria_192_ecb_info = {\n    \"ARIA-192-ECB\",\n    16,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_ECB,\n    MBEDTLS_CIPHER_ARIA_192_ECB,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_ARIA\n};\n\nstatic const mbedtls_cipher_info_t aria_256_ecb_info = {\n    \"ARIA-256-ECB\",\n    16,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_ECB,\n    MBEDTLS_CIPHER_ARIA_256_ECB,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_ARIA\n};\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\nstatic const mbedtls_cipher_info_t aria_128_cbc_info = {\n    \"ARIA-128-CBC\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CBC,\n    MBEDTLS_CIPHER_ARIA_128_CBC,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_ARIA\n};\n\nstatic const mbedtls_cipher_info_t aria_192_cbc_info = {\n    \"ARIA-192-CBC\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CBC,\n    MBEDTLS_CIPHER_ARIA_192_CBC,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_ARIA\n};\n\nstatic const mbedtls_cipher_info_t aria_256_cbc_info = {\n    \"ARIA-256-CBC\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CBC,\n    MBEDTLS_CIPHER_ARIA_256_CBC,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_ARIA\n};\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\nstatic const mbedtls_cipher_info_t aria_128_cfb128_info = {\n    \"ARIA-128-CFB128\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CFB,\n    MBEDTLS_CIPHER_ARIA_128_CFB128,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_ARIA\n};\n\nstatic const mbedtls_cipher_info_t aria_192_cfb128_info = {\n    \"ARIA-192-CFB128\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CFB,\n    MBEDTLS_CIPHER_ARIA_192_CFB128,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_ARIA\n};\n\nstatic const mbedtls_cipher_info_t aria_256_cfb128_info = {\n    \"ARIA-256-CFB128\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CFB,\n    MBEDTLS_CIPHER_ARIA_256_CFB128,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_ARIA\n};\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\nstatic const mbedtls_cipher_info_t aria_128_ctr_info = {\n    \"ARIA-128-CTR\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CTR,\n    MBEDTLS_CIPHER_ARIA_128_CTR,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_ARIA\n};\n\nstatic const mbedtls_cipher_info_t aria_192_ctr_info = {\n    \"ARIA-192-CTR\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CTR,\n    MBEDTLS_CIPHER_ARIA_192_CTR,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_ARIA\n};\n\nstatic const mbedtls_cipher_info_t aria_256_ctr_info = {\n    \"ARIA-256-CTR\",\n    16,\n    16 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CTR,\n    MBEDTLS_CIPHER_ARIA_256_CTR,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_ARIA\n};\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n\n#if defined(MBEDTLS_GCM_C)\nstatic int gcm_aria_setkey_wrap(void *ctx, const unsigned char *key,\n                                unsigned int key_bitlen)\n{\n    return mbedtls_gcm_setkey((mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA,\n                              key, key_bitlen);\n}\n\nstatic const mbedtls_cipher_base_t gcm_aria_info = {\n    MBEDTLS_CIPHER_ID_ARIA,\n    NULL,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    NULL,\n#endif\n    gcm_aria_setkey_wrap,\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    gcm_aria_setkey_wrap,\n#endif\n    gcm_ctx_alloc,\n    gcm_ctx_free,\n};\n\nstatic const mbedtls_cipher_info_t aria_128_gcm_info = {\n    \"ARIA-128-GCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_GCM,\n    MBEDTLS_CIPHER_ARIA_128_GCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA\n};\n\nstatic const mbedtls_cipher_info_t aria_192_gcm_info = {\n    \"ARIA-192-GCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_GCM,\n    MBEDTLS_CIPHER_ARIA_192_GCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA\n};\n\nstatic const mbedtls_cipher_info_t aria_256_gcm_info = {\n    \"ARIA-256-GCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_GCM,\n    MBEDTLS_CIPHER_ARIA_256_GCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA\n};\n#endif /* MBEDTLS_GCM_C */\n\n#if defined(MBEDTLS_CCM_C)\nstatic int ccm_aria_setkey_wrap(void *ctx, const unsigned char *key,\n                                unsigned int key_bitlen)\n{\n    return mbedtls_ccm_setkey((mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA,\n                              key, key_bitlen);\n}\n\nstatic const mbedtls_cipher_base_t ccm_aria_info = {\n    MBEDTLS_CIPHER_ID_ARIA,\n    NULL,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    NULL,\n#endif\n    ccm_aria_setkey_wrap,\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    ccm_aria_setkey_wrap,\n#endif\n    ccm_ctx_alloc,\n    ccm_ctx_free,\n};\n\nstatic const mbedtls_cipher_info_t aria_128_ccm_info = {\n    \"ARIA-128-CCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM,\n    MBEDTLS_CIPHER_ARIA_128_CCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA\n};\n\nstatic const mbedtls_cipher_info_t aria_192_ccm_info = {\n    \"ARIA-192-CCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM,\n    MBEDTLS_CIPHER_ARIA_192_CCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA\n};\n\nstatic const mbedtls_cipher_info_t aria_256_ccm_info = {\n    \"ARIA-256-CCM\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM,\n    MBEDTLS_CIPHER_ARIA_256_CCM,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA\n};\n\nstatic const mbedtls_cipher_info_t aria_128_ccm_star_no_tag_info = {\n    \"ARIA-128-CCM*-NO-TAG\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA\n};\n\nstatic const mbedtls_cipher_info_t aria_192_ccm_star_no_tag_info = {\n    \"ARIA-192-CCM*-NO-TAG\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA\n};\n\nstatic const mbedtls_cipher_info_t aria_256_ccm_star_no_tag_info = {\n    \"ARIA-256-CCM*-NO-TAG\",\n    16,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG,\n    MBEDTLS_CIPHER_VARIABLE_IV_LEN,\n    MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA\n};\n#endif /* MBEDTLS_CCM_C */\n\n#endif /* MBEDTLS_ARIA_C */\n\n#if defined(MBEDTLS_DES_C)\n\nstatic int des_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation,\n                              const unsigned char *input, unsigned char *output)\n{\n    ((void) operation);\n    return mbedtls_des_crypt_ecb((mbedtls_des_context *) ctx, input, output);\n}\n\nstatic int des3_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation,\n                               const unsigned char *input, unsigned char *output)\n{\n    ((void) operation);\n    return mbedtls_des3_crypt_ecb((mbedtls_des3_context *) ctx, input, output);\n}\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\nstatic int des_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length,\n                              unsigned char *iv, const unsigned char *input, unsigned char *output)\n{\n    return mbedtls_des_crypt_cbc((mbedtls_des_context *) ctx, operation, length, iv, input,\n                                 output);\n}\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\nstatic int des3_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length,\n                               unsigned char *iv, const unsigned char *input, unsigned char *output)\n{\n    return mbedtls_des3_crypt_cbc((mbedtls_des3_context *) ctx, operation, length, iv, input,\n                                  output);\n}\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\nstatic int des_setkey_dec_wrap(void *ctx, const unsigned char *key,\n                               unsigned int key_bitlen)\n{\n    ((void) key_bitlen);\n\n    return mbedtls_des_setkey_dec((mbedtls_des_context *) ctx, key);\n}\n\nstatic int des_setkey_enc_wrap(void *ctx, const unsigned char *key,\n                               unsigned int key_bitlen)\n{\n    ((void) key_bitlen);\n\n    return mbedtls_des_setkey_enc((mbedtls_des_context *) ctx, key);\n}\n\nstatic int des3_set2key_dec_wrap(void *ctx, const unsigned char *key,\n                                 unsigned int key_bitlen)\n{\n    ((void) key_bitlen);\n\n    return mbedtls_des3_set2key_dec((mbedtls_des3_context *) ctx, key);\n}\n\nstatic int des3_set2key_enc_wrap(void *ctx, const unsigned char *key,\n                                 unsigned int key_bitlen)\n{\n    ((void) key_bitlen);\n\n    return mbedtls_des3_set2key_enc((mbedtls_des3_context *) ctx, key);\n}\n\nstatic int des3_set3key_dec_wrap(void *ctx, const unsigned char *key,\n                                 unsigned int key_bitlen)\n{\n    ((void) key_bitlen);\n\n    return mbedtls_des3_set3key_dec((mbedtls_des3_context *) ctx, key);\n}\n\nstatic int des3_set3key_enc_wrap(void *ctx, const unsigned char *key,\n                                 unsigned int key_bitlen)\n{\n    ((void) key_bitlen);\n\n    return mbedtls_des3_set3key_enc((mbedtls_des3_context *) ctx, key);\n}\n\nstatic void *des_ctx_alloc(void)\n{\n    mbedtls_des_context *des = mbedtls_calloc(1, sizeof(mbedtls_des_context));\n\n    if (des == NULL) {\n        return NULL;\n    }\n\n    mbedtls_des_init(des);\n\n    return des;\n}\n\nstatic void des_ctx_free(void *ctx)\n{\n    mbedtls_des_free((mbedtls_des_context *) ctx);\n    mbedtls_free(ctx);\n}\n\nstatic void *des3_ctx_alloc(void)\n{\n    mbedtls_des3_context *des3;\n    des3 = mbedtls_calloc(1, sizeof(mbedtls_des3_context));\n\n    if (des3 == NULL) {\n        return NULL;\n    }\n\n    mbedtls_des3_init(des3);\n\n    return des3;\n}\n\nstatic void des3_ctx_free(void *ctx)\n{\n    mbedtls_des3_free((mbedtls_des3_context *) ctx);\n    mbedtls_free(ctx);\n}\n\nstatic const mbedtls_cipher_base_t des_info = {\n    MBEDTLS_CIPHER_ID_DES,\n    des_crypt_ecb_wrap,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    des_crypt_cbc_wrap,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    NULL,\n#endif\n    des_setkey_enc_wrap,\n    des_setkey_dec_wrap,\n    des_ctx_alloc,\n    des_ctx_free\n};\n\nstatic const mbedtls_cipher_info_t des_ecb_info = {\n    \"DES-ECB\",\n    8,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    MBEDTLS_KEY_LENGTH_DES >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_ECB,\n    MBEDTLS_CIPHER_DES_ECB,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_DES\n};\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\nstatic const mbedtls_cipher_info_t des_cbc_info = {\n    \"DES-CBC\",\n    8,\n    8 >> MBEDTLS_IV_SIZE_SHIFT,\n    MBEDTLS_KEY_LENGTH_DES >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CBC,\n    MBEDTLS_CIPHER_DES_CBC,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_DES\n};\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\nstatic const mbedtls_cipher_base_t des_ede_info = {\n    MBEDTLS_CIPHER_ID_DES,\n    des3_crypt_ecb_wrap,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    des3_crypt_cbc_wrap,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    NULL,\n#endif\n    des3_set2key_enc_wrap,\n    des3_set2key_dec_wrap,\n    des3_ctx_alloc,\n    des3_ctx_free\n};\n\nstatic const mbedtls_cipher_info_t des_ede_ecb_info = {\n    \"DES-EDE-ECB\",\n    8,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    MBEDTLS_KEY_LENGTH_DES_EDE >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_ECB,\n    MBEDTLS_CIPHER_DES_EDE_ECB,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_DES_EDE\n};\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\nstatic const mbedtls_cipher_info_t des_ede_cbc_info = {\n    \"DES-EDE-CBC\",\n    8,\n    8 >> MBEDTLS_IV_SIZE_SHIFT,\n    MBEDTLS_KEY_LENGTH_DES_EDE >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CBC,\n    MBEDTLS_CIPHER_DES_EDE_CBC,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_DES_EDE\n};\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\nstatic const mbedtls_cipher_base_t des_ede3_info = {\n    MBEDTLS_CIPHER_ID_3DES,\n    des3_crypt_ecb_wrap,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    des3_crypt_cbc_wrap,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    NULL,\n#endif\n    des3_set3key_enc_wrap,\n    des3_set3key_dec_wrap,\n    des3_ctx_alloc,\n    des3_ctx_free\n};\n\nstatic const mbedtls_cipher_info_t des_ede3_ecb_info = {\n    \"DES-EDE3-ECB\",\n    8,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    MBEDTLS_KEY_LENGTH_DES_EDE3 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_ECB,\n    MBEDTLS_CIPHER_DES_EDE3_ECB,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3\n};\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\nstatic const mbedtls_cipher_info_t des_ede3_cbc_info = {\n    \"DES-EDE3-CBC\",\n    8,\n    8 >> MBEDTLS_IV_SIZE_SHIFT,\n    MBEDTLS_KEY_LENGTH_DES_EDE3 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CBC,\n    MBEDTLS_CIPHER_DES_EDE3_CBC,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3\n};\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n#endif /* MBEDTLS_DES_C */\n\n#if defined(MBEDTLS_CHACHA20_C)\n\nstatic int chacha20_setkey_wrap(void *ctx, const unsigned char *key,\n                                unsigned int key_bitlen)\n{\n    if (key_bitlen != 256U) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    if (0 != mbedtls_chacha20_setkey((mbedtls_chacha20_context *) ctx, key)) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    return 0;\n}\n\nstatic int chacha20_stream_wrap(void *ctx,  size_t length,\n                                const unsigned char *input,\n                                unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    ret = mbedtls_chacha20_update(ctx, length, input, output);\n    if (ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    return ret;\n}\n\nstatic void *chacha20_ctx_alloc(void)\n{\n    mbedtls_chacha20_context *ctx;\n    ctx = mbedtls_calloc(1, sizeof(mbedtls_chacha20_context));\n\n    if (ctx == NULL) {\n        return NULL;\n    }\n\n    mbedtls_chacha20_init(ctx);\n\n    return ctx;\n}\n\nstatic void chacha20_ctx_free(void *ctx)\n{\n    mbedtls_chacha20_free((mbedtls_chacha20_context *) ctx);\n    mbedtls_free(ctx);\n}\n\nstatic const mbedtls_cipher_base_t chacha20_base_info = {\n    MBEDTLS_CIPHER_ID_CHACHA20,\n    NULL,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    chacha20_stream_wrap,\n#endif\n    chacha20_setkey_wrap,\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    chacha20_setkey_wrap,\n#endif\n    chacha20_ctx_alloc,\n    chacha20_ctx_free\n};\nstatic const mbedtls_cipher_info_t chacha20_info = {\n    \"CHACHA20\",\n    1,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_STREAM,\n    MBEDTLS_CIPHER_CHACHA20,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_CHACHA20_BASE\n};\n#endif /* MBEDTLS_CHACHA20_C */\n\n#if defined(MBEDTLS_CHACHAPOLY_C)\n\nstatic int chachapoly_setkey_wrap(void *ctx,\n                                  const unsigned char *key,\n                                  unsigned int key_bitlen)\n{\n    if (key_bitlen != 256U) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    if (0 != mbedtls_chachapoly_setkey((mbedtls_chachapoly_context *) ctx, key)) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    return 0;\n}\n\nstatic void *chachapoly_ctx_alloc(void)\n{\n    mbedtls_chachapoly_context *ctx;\n    ctx = mbedtls_calloc(1, sizeof(mbedtls_chachapoly_context));\n\n    if (ctx == NULL) {\n        return NULL;\n    }\n\n    mbedtls_chachapoly_init(ctx);\n\n    return ctx;\n}\n\nstatic void chachapoly_ctx_free(void *ctx)\n{\n    mbedtls_chachapoly_free((mbedtls_chachapoly_context *) ctx);\n    mbedtls_free(ctx);\n}\n\nstatic const mbedtls_cipher_base_t chachapoly_base_info = {\n    MBEDTLS_CIPHER_ID_CHACHA20,\n    NULL,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    NULL,\n#endif\n    chachapoly_setkey_wrap,\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    chachapoly_setkey_wrap,\n#endif\n    chachapoly_ctx_alloc,\n    chachapoly_ctx_free\n};\nstatic const mbedtls_cipher_info_t chachapoly_info = {\n    \"CHACHA20-POLY1305\",\n    1,\n    12 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_CHACHAPOLY,\n    MBEDTLS_CIPHER_CHACHA20_POLY1305,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_CHACHAPOLY_BASE\n};\n#endif /* MBEDTLS_CHACHAPOLY_C */\n\n#if defined(MBEDTLS_CIPHER_NULL_CIPHER)\nstatic int null_crypt_stream(void *ctx, size_t length,\n                             const unsigned char *input,\n                             unsigned char *output)\n{\n    ((void) ctx);\n    memmove(output, input, length);\n    return 0;\n}\n\nstatic int null_setkey(void *ctx, const unsigned char *key,\n                       unsigned int key_bitlen)\n{\n    ((void) ctx);\n    ((void) key);\n    ((void) key_bitlen);\n\n    return 0;\n}\n\nstatic void *null_ctx_alloc(void)\n{\n    return (void *) 1;\n}\n\nstatic void null_ctx_free(void *ctx)\n{\n    ((void) ctx);\n}\n\nstatic const mbedtls_cipher_base_t null_base_info = {\n    MBEDTLS_CIPHER_ID_NULL,\n    NULL,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    null_crypt_stream,\n#endif\n    null_setkey,\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    null_setkey,\n#endif\n    null_ctx_alloc,\n    null_ctx_free\n};\n\nstatic const mbedtls_cipher_info_t null_cipher_info = {\n    \"NULL\",\n    1,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    0 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_STREAM,\n    MBEDTLS_CIPHER_NULL,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_NULL_BASE\n};\n#endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */\n\n#if defined(MBEDTLS_NIST_KW_C)\nstatic void *kw_ctx_alloc(void)\n{\n    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_nist_kw_context));\n\n    if (ctx != NULL) {\n        mbedtls_nist_kw_init((mbedtls_nist_kw_context *) ctx);\n    }\n\n    return ctx;\n}\n\nstatic void kw_ctx_free(void *ctx)\n{\n    mbedtls_nist_kw_free(ctx);\n    mbedtls_free(ctx);\n}\n\nstatic int kw_aes_setkey_wrap(void *ctx, const unsigned char *key,\n                              unsigned int key_bitlen)\n{\n    return mbedtls_nist_kw_setkey((mbedtls_nist_kw_context *) ctx,\n                                  MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 1);\n}\n\nstatic int kw_aes_setkey_unwrap(void *ctx, const unsigned char *key,\n                                unsigned int key_bitlen)\n{\n    return mbedtls_nist_kw_setkey((mbedtls_nist_kw_context *) ctx,\n                                  MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 0);\n}\n\nstatic const mbedtls_cipher_base_t kw_aes_info = {\n    MBEDTLS_CIPHER_ID_AES,\n    NULL,\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    NULL,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    NULL,\n#endif\n    kw_aes_setkey_wrap,\n    kw_aes_setkey_unwrap,\n    kw_ctx_alloc,\n    kw_ctx_free,\n};\n\nstatic const mbedtls_cipher_info_t aes_128_nist_kw_info = {\n    \"AES-128-KW\",\n    16,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_KW,\n    MBEDTLS_CIPHER_AES_128_KW,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_KW_AES\n};\n\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic const mbedtls_cipher_info_t aes_192_nist_kw_info = {\n    \"AES-192-KW\",\n    16,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_KW,\n    MBEDTLS_CIPHER_AES_192_KW,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_KW_AES\n};\n\nstatic const mbedtls_cipher_info_t aes_256_nist_kw_info = {\n    \"AES-256-KW\",\n    16,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_KW,\n    MBEDTLS_CIPHER_AES_256_KW,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_KW_AES\n};\n#endif\n\nstatic const mbedtls_cipher_info_t aes_128_nist_kwp_info = {\n    \"AES-128-KWP\",\n    16,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    128 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_KWP,\n    MBEDTLS_CIPHER_AES_128_KWP,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_KW_AES\n};\n\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic const mbedtls_cipher_info_t aes_192_nist_kwp_info = {\n    \"AES-192-KWP\",\n    16,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    192 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_KWP,\n    MBEDTLS_CIPHER_AES_192_KWP,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_KW_AES\n};\n\nstatic const mbedtls_cipher_info_t aes_256_nist_kwp_info = {\n    \"AES-256-KWP\",\n    16,\n    0 >> MBEDTLS_IV_SIZE_SHIFT,\n    256 >> MBEDTLS_KEY_BITLEN_SHIFT,\n    MBEDTLS_MODE_KWP,\n    MBEDTLS_CIPHER_AES_256_KWP,\n    0,\n    MBEDTLS_CIPHER_BASE_INDEX_KW_AES\n};\n#endif\n#endif /* MBEDTLS_NIST_KW_C */\n\nconst mbedtls_cipher_definition_t mbedtls_cipher_definitions[] =\n{\n#if defined(MBEDTLS_AES_C)\n    { MBEDTLS_CIPHER_AES_128_ECB,          &aes_128_ecb_info },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { MBEDTLS_CIPHER_AES_192_ECB,          &aes_192_ecb_info },\n    { MBEDTLS_CIPHER_AES_256_ECB,          &aes_256_ecb_info },\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    { MBEDTLS_CIPHER_AES_128_CBC,          &aes_128_cbc_info },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { MBEDTLS_CIPHER_AES_192_CBC,          &aes_192_cbc_info },\n    { MBEDTLS_CIPHER_AES_256_CBC,          &aes_256_cbc_info },\n#endif\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    { MBEDTLS_CIPHER_AES_128_CFB128,       &aes_128_cfb128_info },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { MBEDTLS_CIPHER_AES_192_CFB128,       &aes_192_cfb128_info },\n    { MBEDTLS_CIPHER_AES_256_CFB128,       &aes_256_cfb128_info },\n#endif\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    { MBEDTLS_CIPHER_AES_128_OFB,          &aes_128_ofb_info },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { MBEDTLS_CIPHER_AES_192_OFB,          &aes_192_ofb_info },\n    { MBEDTLS_CIPHER_AES_256_OFB,          &aes_256_ofb_info },\n#endif\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    { MBEDTLS_CIPHER_AES_128_CTR,          &aes_128_ctr_info },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { MBEDTLS_CIPHER_AES_192_CTR,          &aes_192_ctr_info },\n    { MBEDTLS_CIPHER_AES_256_CTR,          &aes_256_ctr_info },\n#endif\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    { MBEDTLS_CIPHER_AES_128_XTS,          &aes_128_xts_info },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { MBEDTLS_CIPHER_AES_256_XTS,          &aes_256_xts_info },\n#endif\n#endif\n#endif /* MBEDTLS_AES_C */\n#if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA)\n    { MBEDTLS_CIPHER_AES_128_GCM,          &aes_128_gcm_info },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { MBEDTLS_CIPHER_AES_192_GCM,          &aes_192_gcm_info },\n    { MBEDTLS_CIPHER_AES_256_GCM,          &aes_256_gcm_info },\n#endif\n#endif\n#if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA)\n    { MBEDTLS_CIPHER_AES_128_CCM,          &aes_128_ccm_info },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { MBEDTLS_CIPHER_AES_192_CCM,          &aes_192_ccm_info },\n    { MBEDTLS_CIPHER_AES_256_CCM,          &aes_256_ccm_info },\n#endif\n#endif\n#if defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA)\n    { MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG,          &aes_128_ccm_star_no_tag_info },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG,          &aes_192_ccm_star_no_tag_info },\n    { MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG,          &aes_256_ccm_star_no_tag_info },\n#endif\n#endif\n\n#if defined(MBEDTLS_CAMELLIA_C)\n    { MBEDTLS_CIPHER_CAMELLIA_128_ECB,     &camellia_128_ecb_info },\n    { MBEDTLS_CIPHER_CAMELLIA_192_ECB,     &camellia_192_ecb_info },\n    { MBEDTLS_CIPHER_CAMELLIA_256_ECB,     &camellia_256_ecb_info },\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    { MBEDTLS_CIPHER_CAMELLIA_128_CBC,     &camellia_128_cbc_info },\n    { MBEDTLS_CIPHER_CAMELLIA_192_CBC,     &camellia_192_cbc_info },\n    { MBEDTLS_CIPHER_CAMELLIA_256_CBC,     &camellia_256_cbc_info },\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    { MBEDTLS_CIPHER_CAMELLIA_128_CFB128,  &camellia_128_cfb128_info },\n    { MBEDTLS_CIPHER_CAMELLIA_192_CFB128,  &camellia_192_cfb128_info },\n    { MBEDTLS_CIPHER_CAMELLIA_256_CFB128,  &camellia_256_cfb128_info },\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    { MBEDTLS_CIPHER_CAMELLIA_128_CTR,     &camellia_128_ctr_info },\n    { MBEDTLS_CIPHER_CAMELLIA_192_CTR,     &camellia_192_ctr_info },\n    { MBEDTLS_CIPHER_CAMELLIA_256_CTR,     &camellia_256_ctr_info },\n#endif\n#if defined(MBEDTLS_GCM_C)\n    { MBEDTLS_CIPHER_CAMELLIA_128_GCM,     &camellia_128_gcm_info },\n    { MBEDTLS_CIPHER_CAMELLIA_192_GCM,     &camellia_192_gcm_info },\n    { MBEDTLS_CIPHER_CAMELLIA_256_GCM,     &camellia_256_gcm_info },\n#endif\n#if defined(MBEDTLS_CCM_C)\n    { MBEDTLS_CIPHER_CAMELLIA_128_CCM,     &camellia_128_ccm_info },\n    { MBEDTLS_CIPHER_CAMELLIA_192_CCM,     &camellia_192_ccm_info },\n    { MBEDTLS_CIPHER_CAMELLIA_256_CCM,     &camellia_256_ccm_info },\n    { MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG,     &camellia_128_ccm_star_no_tag_info },\n    { MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG,     &camellia_192_ccm_star_no_tag_info },\n    { MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG,     &camellia_256_ccm_star_no_tag_info },\n#endif\n#endif /* MBEDTLS_CAMELLIA_C */\n\n#if defined(MBEDTLS_ARIA_C)\n    { MBEDTLS_CIPHER_ARIA_128_ECB,     &aria_128_ecb_info },\n    { MBEDTLS_CIPHER_ARIA_192_ECB,     &aria_192_ecb_info },\n    { MBEDTLS_CIPHER_ARIA_256_ECB,     &aria_256_ecb_info },\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    { MBEDTLS_CIPHER_ARIA_128_CBC,     &aria_128_cbc_info },\n    { MBEDTLS_CIPHER_ARIA_192_CBC,     &aria_192_cbc_info },\n    { MBEDTLS_CIPHER_ARIA_256_CBC,     &aria_256_cbc_info },\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    { MBEDTLS_CIPHER_ARIA_128_CFB128,  &aria_128_cfb128_info },\n    { MBEDTLS_CIPHER_ARIA_192_CFB128,  &aria_192_cfb128_info },\n    { MBEDTLS_CIPHER_ARIA_256_CFB128,  &aria_256_cfb128_info },\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    { MBEDTLS_CIPHER_ARIA_128_CTR,     &aria_128_ctr_info },\n    { MBEDTLS_CIPHER_ARIA_192_CTR,     &aria_192_ctr_info },\n    { MBEDTLS_CIPHER_ARIA_256_CTR,     &aria_256_ctr_info },\n#endif\n#if defined(MBEDTLS_GCM_C)\n    { MBEDTLS_CIPHER_ARIA_128_GCM,     &aria_128_gcm_info },\n    { MBEDTLS_CIPHER_ARIA_192_GCM,     &aria_192_gcm_info },\n    { MBEDTLS_CIPHER_ARIA_256_GCM,     &aria_256_gcm_info },\n#endif\n#if defined(MBEDTLS_CCM_C)\n    { MBEDTLS_CIPHER_ARIA_128_CCM,     &aria_128_ccm_info },\n    { MBEDTLS_CIPHER_ARIA_192_CCM,     &aria_192_ccm_info },\n    { MBEDTLS_CIPHER_ARIA_256_CCM,     &aria_256_ccm_info },\n    { MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG,     &aria_128_ccm_star_no_tag_info },\n    { MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG,     &aria_192_ccm_star_no_tag_info },\n    { MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG,     &aria_256_ccm_star_no_tag_info },\n#endif\n#endif /* MBEDTLS_ARIA_C */\n\n#if defined(MBEDTLS_DES_C)\n    { MBEDTLS_CIPHER_DES_ECB,              &des_ecb_info },\n    { MBEDTLS_CIPHER_DES_EDE_ECB,          &des_ede_ecb_info },\n    { MBEDTLS_CIPHER_DES_EDE3_ECB,         &des_ede3_ecb_info },\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    { MBEDTLS_CIPHER_DES_CBC,              &des_cbc_info },\n    { MBEDTLS_CIPHER_DES_EDE_CBC,          &des_ede_cbc_info },\n    { MBEDTLS_CIPHER_DES_EDE3_CBC,         &des_ede3_cbc_info },\n#endif\n#endif /* MBEDTLS_DES_C */\n\n#if defined(MBEDTLS_CHACHA20_C)\n    { MBEDTLS_CIPHER_CHACHA20,             &chacha20_info },\n#endif\n\n#if defined(MBEDTLS_CHACHAPOLY_C)\n    { MBEDTLS_CIPHER_CHACHA20_POLY1305,    &chachapoly_info },\n#endif\n\n#if defined(MBEDTLS_NIST_KW_C)\n    { MBEDTLS_CIPHER_AES_128_KW,          &aes_128_nist_kw_info },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { MBEDTLS_CIPHER_AES_192_KW,          &aes_192_nist_kw_info },\n    { MBEDTLS_CIPHER_AES_256_KW,          &aes_256_nist_kw_info },\n#endif\n    { MBEDTLS_CIPHER_AES_128_KWP,         &aes_128_nist_kwp_info },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { MBEDTLS_CIPHER_AES_192_KWP,         &aes_192_nist_kwp_info },\n    { MBEDTLS_CIPHER_AES_256_KWP,         &aes_256_nist_kwp_info },\n#endif\n#endif\n\n#if defined(MBEDTLS_CIPHER_NULL_CIPHER)\n    { MBEDTLS_CIPHER_NULL,                 &null_cipher_info },\n#endif /* MBEDTLS_CIPHER_NULL_CIPHER */\n\n    { MBEDTLS_CIPHER_NONE, NULL }\n};\n\n#define NUM_CIPHERS (sizeof(mbedtls_cipher_definitions) /      \\\n                     sizeof(mbedtls_cipher_definitions[0]))\nint mbedtls_cipher_supported[NUM_CIPHERS];\n\nconst mbedtls_cipher_base_t * const mbedtls_cipher_base_lookup_table[] = {\n#if defined(MBEDTLS_AES_C)\n    [MBEDTLS_CIPHER_BASE_INDEX_AES] = &aes_info,\n#endif\n#if defined(MBEDTLS_ARIA_C)\n    [MBEDTLS_CIPHER_BASE_INDEX_ARIA] = &aria_info,\n#endif\n#if defined(MBEDTLS_CAMELLIA_C)\n    [MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA] = &camellia_info,\n#endif\n#if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA)\n    [MBEDTLS_CIPHER_BASE_INDEX_CCM_AES] = &ccm_aes_info,\n#endif\n#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_ARIA_C)\n    [MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA] = &ccm_aria_info,\n#endif\n#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CAMELLIA_C)\n    [MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA] = &ccm_camellia_info,\n#endif\n#if defined(MBEDTLS_CHACHA20_C)\n    [MBEDTLS_CIPHER_BASE_INDEX_CHACHA20_BASE] = &chacha20_base_info,\n#endif\n#if defined(MBEDTLS_CHACHAPOLY_C)\n    [MBEDTLS_CIPHER_BASE_INDEX_CHACHAPOLY_BASE] = &chachapoly_base_info,\n#endif\n#if defined(MBEDTLS_DES_C)\n    [MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3] = &des_ede3_info,\n#endif\n#if defined(MBEDTLS_DES_C)\n    [MBEDTLS_CIPHER_BASE_INDEX_DES_EDE] = &des_ede_info,\n#endif\n#if defined(MBEDTLS_DES_C)\n    [MBEDTLS_CIPHER_BASE_INDEX_DES] = &des_info,\n#endif\n#if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA)\n    [MBEDTLS_CIPHER_BASE_INDEX_GCM_AES] = &gcm_aes_info,\n#endif\n#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_ARIA_C)\n    [MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA] = &gcm_aria_info,\n#endif\n#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_CAMELLIA_C)\n    [MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA] = &gcm_camellia_info,\n#endif\n#if defined(MBEDTLS_NIST_KW_C)\n    [MBEDTLS_CIPHER_BASE_INDEX_KW_AES] = &kw_aes_info,\n#endif\n#if defined(MBEDTLS_CIPHER_NULL_CIPHER)\n    [MBEDTLS_CIPHER_BASE_INDEX_NULL_BASE] = &null_base_info,\n#endif\n#if defined(MBEDTLS_CIPHER_MODE_XTS) && defined(MBEDTLS_AES_C)\n    [MBEDTLS_CIPHER_BASE_INDEX_XTS_AES] = &xts_aes_info\n#endif\n};\n\n#endif /* MBEDTLS_CIPHER_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/cipher_wrap.h",
    "content": "/**\n * \\file cipher_wrap.h\n *\n * \\brief Cipher wrappers.\n *\n * \\author Adriaan de Jong <dejong@fox-it.com>\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_CIPHER_WRAP_H\n#define MBEDTLS_CIPHER_WRAP_H\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/cipher.h\"\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"psa/crypto.h\"\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Support for GCM either through Mbed TLS SW implementation or PSA */\n#if defined(MBEDTLS_GCM_C) || \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM))\n#define MBEDTLS_CIPHER_HAVE_GCM_VIA_LEGACY_OR_USE_PSA\n#endif\n\n#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_AES_C)) || \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM) && defined(PSA_WANT_KEY_TYPE_AES))\n#define MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA\n#endif\n\n#if defined(MBEDTLS_CCM_C) || \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM))\n#define MBEDTLS_CIPHER_HAVE_CCM_VIA_LEGACY_OR_USE_PSA\n#endif\n\n#if (defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)) || \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM) && defined(PSA_WANT_KEY_TYPE_AES))\n#define MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA\n#endif\n\n#if defined(MBEDTLS_CCM_C) || \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM_STAR_NO_TAG))\n#define MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_VIA_LEGACY_OR_USE_PSA\n#endif\n\n#if (defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)) || \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) && \\\n    defined(PSA_WANT_KEY_TYPE_AES))\n#define MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA\n#endif\n\n#if defined(MBEDTLS_CHACHAPOLY_C) || \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CHACHA20_POLY1305))\n#define MBEDTLS_CIPHER_HAVE_CHACHAPOLY_VIA_LEGACY_OR_USE_PSA\n#endif\n\n#if defined(MBEDTLS_CIPHER_HAVE_GCM_VIA_LEGACY_OR_USE_PSA) || \\\n    defined(MBEDTLS_CIPHER_HAVE_CCM_VIA_LEGACY_OR_USE_PSA) || \\\n    defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_VIA_LEGACY_OR_USE_PSA) || \\\n    defined(MBEDTLS_CIPHER_HAVE_CHACHAPOLY_VIA_LEGACY_OR_USE_PSA)\n#define MBEDTLS_CIPHER_HAVE_SOME_AEAD_VIA_LEGACY_OR_USE_PSA\n#endif\n\n/**\n * Base cipher information. The non-mode specific functions and values.\n */\nstruct mbedtls_cipher_base_t {\n    /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */\n    mbedtls_cipher_id_t cipher;\n\n    /** Encrypt using ECB */\n    int (*ecb_func)(void *ctx, mbedtls_operation_t mode,\n                    const unsigned char *input, unsigned char *output);\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    /** Encrypt using CBC */\n    int (*cbc_func)(void *ctx, mbedtls_operation_t mode, size_t length,\n                    unsigned char *iv, const unsigned char *input,\n                    unsigned char *output);\n#endif\n\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    /** Encrypt using CFB (Full length) */\n    int (*cfb_func)(void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off,\n                    unsigned char *iv, const unsigned char *input,\n                    unsigned char *output);\n#endif\n\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    /** Encrypt using OFB (Full length) */\n    int (*ofb_func)(void *ctx, size_t length, size_t *iv_off,\n                    unsigned char *iv,\n                    const unsigned char *input,\n                    unsigned char *output);\n#endif\n\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    /** Encrypt using CTR */\n    int (*ctr_func)(void *ctx, size_t length, size_t *nc_off,\n                    unsigned char *nonce_counter, unsigned char *stream_block,\n                    const unsigned char *input, unsigned char *output);\n#endif\n\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    /** Encrypt or decrypt using XTS. */\n    int (*xts_func)(void *ctx, mbedtls_operation_t mode, size_t length,\n                    const unsigned char data_unit[16],\n                    const unsigned char *input, unsigned char *output);\n#endif\n\n#if defined(MBEDTLS_CIPHER_MODE_STREAM)\n    /** Encrypt using STREAM */\n    int (*stream_func)(void *ctx, size_t length,\n                       const unsigned char *input, unsigned char *output);\n#endif\n\n    /** Set key for encryption purposes */\n    int (*setkey_enc_func)(void *ctx, const unsigned char *key,\n                           unsigned int key_bitlen);\n\n#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    /** Set key for decryption purposes */\n    int (*setkey_dec_func)(void *ctx, const unsigned char *key,\n                           unsigned int key_bitlen);\n#endif\n\n    /** Allocate a new context */\n    void * (*ctx_alloc_func)(void);\n\n    /** Free the given context */\n    void (*ctx_free_func)(void *ctx);\n\n};\n\ntypedef struct {\n    mbedtls_cipher_type_t type;\n    const mbedtls_cipher_info_t *info;\n} mbedtls_cipher_definition_t;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\ntypedef enum {\n    MBEDTLS_CIPHER_PSA_KEY_UNSET = 0,\n    MBEDTLS_CIPHER_PSA_KEY_OWNED, /* Used for PSA-based cipher contexts which */\n                                  /* use raw key material internally imported */\n                                  /* as a volatile key, and which hence need  */\n                                  /* to destroy that key when the context is  */\n                                  /* freed.                                   */\n    MBEDTLS_CIPHER_PSA_KEY_NOT_OWNED, /* Used for PSA-based cipher contexts   */\n                                      /* which use a key provided by the      */\n                                      /* user, and which hence will not be    */\n                                      /* destroyed when the context is freed. */\n} mbedtls_cipher_psa_key_ownership;\n\ntypedef struct {\n    psa_algorithm_t alg;\n    mbedtls_svc_key_id_t slot;\n    mbedtls_cipher_psa_key_ownership slot_state;\n} mbedtls_cipher_context_psa;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\nextern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[];\n\nextern int mbedtls_cipher_supported[];\n\nextern const mbedtls_cipher_base_t * const mbedtls_cipher_base_lookup_table[];\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_CIPHER_WRAP_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/cmac.c",
    "content": "/**\n * \\file cmac.c\n *\n * \\brief NIST SP800-38B compliant CMAC implementation for AES and 3DES\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n * References:\n *\n * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The\n *      CMAC Mode for Authentication\n *   http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf\n *\n * - RFC 4493 - The AES-CMAC Algorithm\n *   https://tools.ietf.org/html/rfc4493\n *\n * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message\n *      Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128)\n *      Algorithm for the Internet Key Exchange Protocol (IKE)\n *   https://tools.ietf.org/html/rfc4615\n *\n *   Additional test vectors: ISO/IEC 9797-1\n *\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_CMAC_C)\n\n#include \"mbedtls/cmac.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/platform.h\"\n#include \"constant_time_internal.h\"\n\n#include <string.h>\n\n#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST)\n\n/*\n * Multiplication by u in the Galois field of GF(2^n)\n *\n * As explained in NIST SP 800-38B, this can be computed:\n *\n *   If MSB(p) = 0, then p = (p << 1)\n *   If MSB(p) = 1, then p = (p << 1) ^ R_n\n *   with R_64 = 0x1B and  R_128 = 0x87\n *\n * Input and output MUST NOT point to the same buffer\n * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES.\n */\nstatic int cmac_multiply_by_u(unsigned char *output,\n                              const unsigned char *input,\n                              size_t blocksize)\n{\n    const unsigned char R_128 = 0x87;\n    unsigned char R_n;\n    uint32_t overflow = 0x00;\n    int i;\n\n    if (blocksize == MBEDTLS_AES_BLOCK_SIZE) {\n        R_n = R_128;\n    }\n#if defined(MBEDTLS_DES_C)\n    else if (blocksize == MBEDTLS_DES3_BLOCK_SIZE) {\n        const unsigned char R_64 = 0x1B;\n        R_n = R_64;\n    }\n#endif\n    else {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    for (i = (int) blocksize - 4; i >= 0; i -= 4) {\n        uint32_t i32 = MBEDTLS_GET_UINT32_BE(&input[i], 0);\n        uint32_t new_overflow = i32 >> 31;\n        i32 = (i32 << 1) | overflow;\n        MBEDTLS_PUT_UINT32_BE(i32, &output[i], 0);\n        overflow = new_overflow;\n    }\n\n    R_n = (unsigned char) mbedtls_ct_uint_if_else_0(mbedtls_ct_bool(input[0] >> 7), R_n);\n    output[blocksize - 1] ^= R_n;\n\n    return 0;\n}\n\n/*\n * Generate subkeys\n *\n * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm\n */\nstatic int cmac_generate_subkeys(mbedtls_cipher_context_t *ctx,\n                                 unsigned char *K1, unsigned char *K2)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char L[MBEDTLS_CMAC_MAX_BLOCK_SIZE];\n    size_t olen, block_size;\n\n    mbedtls_platform_zeroize(L, sizeof(L));\n\n    block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);\n\n    /* Calculate Ek(0) */\n    if ((ret = mbedtls_cipher_update(ctx, L, block_size, L, &olen)) != 0) {\n        goto exit;\n    }\n\n    /*\n     * Generate K1 and K2\n     */\n    if ((ret = cmac_multiply_by_u(K1, L, block_size)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = cmac_multiply_by_u(K2, K1, block_size)) != 0) {\n        goto exit;\n    }\n\nexit:\n    mbedtls_platform_zeroize(L, sizeof(L));\n\n    return ret;\n}\n#endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */\n\n#if !defined(MBEDTLS_CMAC_ALT)\n\n/*\n * Create padded last block from (partial) last block.\n *\n * We can't use the padding option from the cipher layer, as it only works for\n * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.\n */\nstatic void cmac_pad(unsigned char padded_block[MBEDTLS_CMAC_MAX_BLOCK_SIZE],\n                     size_t padded_block_len,\n                     const unsigned char *last_block,\n                     size_t last_block_len)\n{\n    size_t j;\n\n    for (j = 0; j < padded_block_len; j++) {\n        if (j < last_block_len) {\n            padded_block[j] = last_block[j];\n        } else if (j == last_block_len) {\n            padded_block[j] = 0x80;\n        } else {\n            padded_block[j] = 0x00;\n        }\n    }\n}\n\nint mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx,\n                               const unsigned char *key, size_t keybits)\n{\n    mbedtls_cipher_type_t type;\n    mbedtls_cmac_context_t *cmac_ctx;\n    int retval;\n\n    if (ctx == NULL || ctx->cipher_info == NULL || key == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    if ((retval = mbedtls_cipher_setkey(ctx, key, (int) keybits,\n                                        MBEDTLS_ENCRYPT)) != 0) {\n        return retval;\n    }\n\n    type = mbedtls_cipher_info_get_type(ctx->cipher_info);\n\n    switch (type) {\n        case MBEDTLS_CIPHER_AES_128_ECB:\n        case MBEDTLS_CIPHER_AES_192_ECB:\n        case MBEDTLS_CIPHER_AES_256_ECB:\n        case MBEDTLS_CIPHER_DES_EDE3_ECB:\n            break;\n        default:\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    /* Allocated and initialise in the cipher context memory for the CMAC\n     * context */\n    cmac_ctx = mbedtls_calloc(1, sizeof(mbedtls_cmac_context_t));\n    if (cmac_ctx == NULL) {\n        return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;\n    }\n\n    ctx->cmac_ctx = cmac_ctx;\n\n    mbedtls_platform_zeroize(cmac_ctx->state, sizeof(cmac_ctx->state));\n\n    return 0;\n}\n\nint mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx,\n                               const unsigned char *input, size_t ilen)\n{\n    mbedtls_cmac_context_t *cmac_ctx;\n    unsigned char *state;\n    int ret = 0;\n    size_t n, j, olen, block_size;\n\n    if (ctx == NULL || ctx->cipher_info == NULL || input == NULL ||\n        ctx->cmac_ctx == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    cmac_ctx = ctx->cmac_ctx;\n    block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);\n    state = ctx->cmac_ctx->state;\n\n    /* Without the MBEDTLS_ASSUME below, gcc -O3 will generate a warning of the form\n     * error: writing 16 bytes into a region of size 0 [-Werror=stringop-overflow=] */\n    MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE);\n\n    /* Is there data still to process from the last call, that's greater in\n     * size than a block? */\n    if (cmac_ctx->unprocessed_len > 0 &&\n        ilen > block_size - cmac_ctx->unprocessed_len) {\n        memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],\n               input,\n               block_size - cmac_ctx->unprocessed_len);\n\n        mbedtls_xor_no_simd(state, cmac_ctx->unprocessed_block, state, block_size);\n\n        if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,\n                                         &olen)) != 0) {\n            goto exit;\n        }\n\n        input += block_size - cmac_ctx->unprocessed_len;\n        ilen -= block_size - cmac_ctx->unprocessed_len;\n        cmac_ctx->unprocessed_len = 0;\n    }\n\n    /* n is the number of blocks including any final partial block */\n    n = (ilen + block_size - 1) / block_size;\n\n    /* Iterate across the input data in block sized chunks, excluding any\n     * final partial or complete block */\n    for (j = 1; j < n; j++) {\n        mbedtls_xor_no_simd(state, input, state, block_size);\n\n        if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,\n                                         &olen)) != 0) {\n            goto exit;\n        }\n\n        ilen -= block_size;\n        input += block_size;\n    }\n\n    /* If there is data left over that wasn't aligned to a block */\n    if (ilen > 0) {\n        memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],\n               input,\n               ilen);\n        cmac_ctx->unprocessed_len += ilen;\n    }\n\nexit:\n    return ret;\n}\n\nint mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx,\n                               unsigned char *output)\n{\n    mbedtls_cmac_context_t *cmac_ctx;\n    unsigned char *state, *last_block;\n    unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE];\n    unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE];\n    unsigned char M_last[MBEDTLS_CMAC_MAX_BLOCK_SIZE];\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t olen, block_size;\n\n    if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||\n        output == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    cmac_ctx = ctx->cmac_ctx;\n    block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);\n    MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE); // silence GCC warning\n    state = cmac_ctx->state;\n\n    mbedtls_platform_zeroize(K1, sizeof(K1));\n    mbedtls_platform_zeroize(K2, sizeof(K2));\n    cmac_generate_subkeys(ctx, K1, K2);\n\n    last_block = cmac_ctx->unprocessed_block;\n\n    /* Calculate last block */\n    if (cmac_ctx->unprocessed_len < block_size) {\n        cmac_pad(M_last, block_size, last_block, cmac_ctx->unprocessed_len);\n        mbedtls_xor(M_last, M_last, K2, block_size);\n    } else {\n        /* Last block is complete block */\n        mbedtls_xor(M_last, last_block, K1, block_size);\n    }\n\n\n    mbedtls_xor(state, M_last, state, block_size);\n    if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,\n                                     &olen)) != 0) {\n        goto exit;\n    }\n\n    memcpy(output, state, block_size);\n\nexit:\n    /* Wipe the generated keys on the stack, and any other transients to avoid\n     * side channel leakage */\n    mbedtls_platform_zeroize(K1, sizeof(K1));\n    mbedtls_platform_zeroize(K2, sizeof(K2));\n\n    cmac_ctx->unprocessed_len = 0;\n    mbedtls_platform_zeroize(cmac_ctx->unprocessed_block,\n                             sizeof(cmac_ctx->unprocessed_block));\n\n    mbedtls_platform_zeroize(state, MBEDTLS_CMAC_MAX_BLOCK_SIZE);\n    return ret;\n}\n\nint mbedtls_cipher_cmac_reset(mbedtls_cipher_context_t *ctx)\n{\n    mbedtls_cmac_context_t *cmac_ctx;\n\n    if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    cmac_ctx = ctx->cmac_ctx;\n\n    /* Reset the internal state */\n    cmac_ctx->unprocessed_len = 0;\n    mbedtls_platform_zeroize(cmac_ctx->unprocessed_block,\n                             sizeof(cmac_ctx->unprocessed_block));\n    mbedtls_platform_zeroize(cmac_ctx->state,\n                             sizeof(cmac_ctx->state));\n\n    return 0;\n}\n\nint mbedtls_cipher_cmac(const mbedtls_cipher_info_t *cipher_info,\n                        const unsigned char *key, size_t keylen,\n                        const unsigned char *input, size_t ilen,\n                        unsigned char *output)\n{\n    mbedtls_cipher_context_t ctx;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (cipher_info == NULL || key == NULL || input == NULL || output == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    mbedtls_cipher_init(&ctx);\n\n    if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) {\n        goto exit;\n    }\n\n    ret = mbedtls_cipher_cmac_starts(&ctx, key, keylen);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    ret = mbedtls_cipher_cmac_update(&ctx, input, ilen);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    ret = mbedtls_cipher_cmac_finish(&ctx, output);\n\nexit:\n    mbedtls_cipher_free(&ctx);\n\n    return ret;\n}\n\n#if defined(MBEDTLS_AES_C)\n/*\n * Implementation of AES-CMAC-PRF-128 defined in RFC 4615\n */\nint mbedtls_aes_cmac_prf_128(const unsigned char *key, size_t key_length,\n                             const unsigned char *input, size_t in_len,\n                             unsigned char output[16])\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const mbedtls_cipher_info_t *cipher_info;\n    unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE];\n    unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE];\n\n    if (key == NULL || input == NULL || output == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);\n    if (cipher_info == NULL) {\n        /* Failing at this point must be due to a build issue */\n        ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n        goto exit;\n    }\n\n    if (key_length == MBEDTLS_AES_BLOCK_SIZE) {\n        /* Use key as is */\n        memcpy(int_key, key, MBEDTLS_AES_BLOCK_SIZE);\n    } else {\n        memset(zero_key, 0, MBEDTLS_AES_BLOCK_SIZE);\n\n        ret = mbedtls_cipher_cmac(cipher_info, zero_key, 128, key,\n                                  key_length, int_key);\n        if (ret != 0) {\n            goto exit;\n        }\n    }\n\n    ret = mbedtls_cipher_cmac(cipher_info, int_key, 128, input, in_len,\n                              output);\n\nexit:\n    mbedtls_platform_zeroize(int_key, sizeof(int_key));\n\n    return ret;\n}\n#endif /* MBEDTLS_AES_C */\n\n#endif /* !MBEDTLS_CMAC_ALT */\n\n#if defined(MBEDTLS_SELF_TEST)\n/*\n * CMAC test data for SP800-38B\n * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf\n * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf\n *\n * AES-CMAC-PRF-128 test data from RFC 4615\n * https://tools.ietf.org/html/rfc4615#page-4\n */\n\n#define NB_CMAC_TESTS_PER_KEY 4\n#define NB_PRF_TESTS 3\n\n#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)\n/* All CMAC test inputs are truncated from the same 64 byte buffer. */\nstatic const unsigned char test_message[] = {\n    /* PT */\n    0x6b, 0xc1, 0xbe, 0xe2,     0x2e, 0x40, 0x9f, 0x96,\n    0xe9, 0x3d, 0x7e, 0x11,     0x73, 0x93, 0x17, 0x2a,\n    0xae, 0x2d, 0x8a, 0x57,     0x1e, 0x03, 0xac, 0x9c,\n    0x9e, 0xb7, 0x6f, 0xac,     0x45, 0xaf, 0x8e, 0x51,\n    0x30, 0xc8, 0x1c, 0x46,     0xa3, 0x5c, 0xe4, 0x11,\n    0xe5, 0xfb, 0xc1, 0x19,     0x1a, 0x0a, 0x52, 0xef,\n    0xf6, 0x9f, 0x24, 0x45,     0xdf, 0x4f, 0x9b, 0x17,\n    0xad, 0x2b, 0x41, 0x7b,     0xe6, 0x6c, 0x37, 0x10\n};\n#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */\n\n#if defined(MBEDTLS_AES_C)\n/* Truncation point of message for AES CMAC tests  */\nstatic const  unsigned int  aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {\n    /* Mlen */\n    0,\n    16,\n    20,\n    64\n};\n\n/* CMAC-AES128 Test Data */\nstatic const unsigned char aes_128_key[16] = {\n    0x2b, 0x7e, 0x15, 0x16,     0x28, 0xae, 0xd2, 0xa6,\n    0xab, 0xf7, 0x15, 0x88,     0x09, 0xcf, 0x4f, 0x3c\n};\nstatic const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {\n    {\n        /* K1 */\n        0xfb, 0xee, 0xd6, 0x18,     0x35, 0x71, 0x33, 0x66,\n        0x7c, 0x85, 0xe0, 0x8f,     0x72, 0x36, 0xa8, 0xde\n    },\n    {\n        /* K2 */\n        0xf7, 0xdd, 0xac, 0x30,     0x6a, 0xe2, 0x66, 0xcc,\n        0xf9, 0x0b, 0xc1, 0x1e,     0xe4, 0x6d, 0x51, 0x3b\n    }\n};\nstatic const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] =\n{\n    {\n        /* Example #1 */\n        0xbb, 0x1d, 0x69, 0x29,     0xe9, 0x59, 0x37, 0x28,\n        0x7f, 0xa3, 0x7d, 0x12,     0x9b, 0x75, 0x67, 0x46\n    },\n    {\n        /* Example #2 */\n        0x07, 0x0a, 0x16, 0xb4,     0x6b, 0x4d, 0x41, 0x44,\n        0xf7, 0x9b, 0xdd, 0x9d,     0xd0, 0x4a, 0x28, 0x7c\n    },\n    {\n        /* Example #3 */\n        0x7d, 0x85, 0x44, 0x9e,     0xa6, 0xea, 0x19, 0xc8,\n        0x23, 0xa7, 0xbf, 0x78,     0x83, 0x7d, 0xfa, 0xde\n    },\n    {\n        /* Example #4 */\n        0x51, 0xf0, 0xbe, 0xbf,     0x7e, 0x3b, 0x9d, 0x92,\n        0xfc, 0x49, 0x74, 0x17,     0x79, 0x36, 0x3c, 0xfe\n    }\n};\n\n/* CMAC-AES192 Test Data */\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic const unsigned char aes_192_key[24] = {\n    0x8e, 0x73, 0xb0, 0xf7,     0xda, 0x0e, 0x64, 0x52,\n    0xc8, 0x10, 0xf3, 0x2b,     0x80, 0x90, 0x79, 0xe5,\n    0x62, 0xf8, 0xea, 0xd2,     0x52, 0x2c, 0x6b, 0x7b\n};\nstatic const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {\n    {\n        /* K1 */\n        0x44, 0x8a, 0x5b, 0x1c,     0x93, 0x51, 0x4b, 0x27,\n        0x3e, 0xe6, 0x43, 0x9d,     0xd4, 0xda, 0xa2, 0x96\n    },\n    {\n        /* K2 */\n        0x89, 0x14, 0xb6, 0x39,     0x26, 0xa2, 0x96, 0x4e,\n        0x7d, 0xcc, 0x87, 0x3b,     0xa9, 0xb5, 0x45, 0x2c\n    }\n};\nstatic const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] =\n{\n    {\n        /* Example #1 */\n        0xd1, 0x7d, 0xdf, 0x46,     0xad, 0xaa, 0xcd, 0xe5,\n        0x31, 0xca, 0xc4, 0x83,     0xde, 0x7a, 0x93, 0x67\n    },\n    {\n        /* Example #2 */\n        0x9e, 0x99, 0xa7, 0xbf,     0x31, 0xe7, 0x10, 0x90,\n        0x06, 0x62, 0xf6, 0x5e,     0x61, 0x7c, 0x51, 0x84\n    },\n    {\n        /* Example #3 */\n        0x3d, 0x75, 0xc1, 0x94,     0xed, 0x96, 0x07, 0x04,\n        0x44, 0xa9, 0xfa, 0x7e,     0xc7, 0x40, 0xec, 0xf8\n    },\n    {\n        /* Example #4 */\n        0xa1, 0xd5, 0xdf, 0x0e,     0xed, 0x79, 0x0f, 0x79,\n        0x4d, 0x77, 0x58, 0x96,     0x59, 0xf3, 0x9a, 0x11\n    }\n};\n#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */\n\n/* CMAC-AES256 Test Data */\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\nstatic const unsigned char aes_256_key[32] = {\n    0x60, 0x3d, 0xeb, 0x10,     0x15, 0xca, 0x71, 0xbe,\n    0x2b, 0x73, 0xae, 0xf0,     0x85, 0x7d, 0x77, 0x81,\n    0x1f, 0x35, 0x2c, 0x07,     0x3b, 0x61, 0x08, 0xd7,\n    0x2d, 0x98, 0x10, 0xa3,     0x09, 0x14, 0xdf, 0xf4\n};\nstatic const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {\n    {\n        /* K1 */\n        0xca, 0xd1, 0xed, 0x03,     0x29, 0x9e, 0xed, 0xac,\n        0x2e, 0x9a, 0x99, 0x80,     0x86, 0x21, 0x50, 0x2f\n    },\n    {\n        /* K2 */\n        0x95, 0xa3, 0xda, 0x06,     0x53, 0x3d, 0xdb, 0x58,\n        0x5d, 0x35, 0x33, 0x01,     0x0c, 0x42, 0xa0, 0xd9\n    }\n};\nstatic const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] =\n{\n    {\n        /* Example #1 */\n        0x02, 0x89, 0x62, 0xf6,     0x1b, 0x7b, 0xf8, 0x9e,\n        0xfc, 0x6b, 0x55, 0x1f,     0x46, 0x67, 0xd9, 0x83\n    },\n    {\n        /* Example #2 */\n        0x28, 0xa7, 0x02, 0x3f,     0x45, 0x2e, 0x8f, 0x82,\n        0xbd, 0x4b, 0xf2, 0x8d,     0x8c, 0x37, 0xc3, 0x5c\n    },\n    {\n        /* Example #3 */\n        0x15, 0x67, 0x27, 0xdc,     0x08, 0x78, 0x94, 0x4a,\n        0x02, 0x3c, 0x1f, 0xe0,     0x3b, 0xad, 0x6d, 0x93\n    },\n    {\n        /* Example #4 */\n        0xe1, 0x99, 0x21, 0x90,     0x54, 0x9f, 0x6e, 0xd5,\n        0x69, 0x6a, 0x2c, 0x05,     0x6c, 0x31, 0x54, 0x10\n    }\n};\n#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */\n#endif /* MBEDTLS_AES_C */\n\n#if defined(MBEDTLS_DES_C)\n/* Truncation point of message for 3DES CMAC tests  */\nstatic const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {\n    0,\n    16,\n    20,\n    32\n};\n\n/* CMAC-TDES (Generation) - 2 Key Test Data */\nstatic const unsigned char des3_2key_key[24] = {\n    /* Key1 */\n    0x01, 0x23, 0x45, 0x67,     0x89, 0xab, 0xcd, 0xef,\n    /* Key2 */\n    0x23, 0x45, 0x67, 0x89,     0xab, 0xcd, 0xEF, 0x01,\n    /* Key3 */\n    0x01, 0x23, 0x45, 0x67,     0x89, 0xab, 0xcd, 0xef\n};\nstatic const unsigned char des3_2key_subkeys[2][8] = {\n    {\n        /* K1 */\n        0x0d, 0xd2, 0xcb, 0x7a,     0x3d, 0x88, 0x88, 0xd9\n    },\n    {\n        /* K2 */\n        0x1b, 0xa5, 0x96, 0xf4,     0x7b, 0x11, 0x11, 0xb2\n    }\n};\nstatic const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE]\n    = {\n    {\n        /* Sample #1 */\n        0x79, 0xce, 0x52, 0xa7,     0xf7, 0x86, 0xa9, 0x60\n    },\n    {\n        /* Sample #2 */\n        0xcc, 0x18, 0xa0, 0xb7,     0x9a, 0xf2, 0x41, 0x3b\n    },\n    {\n        /* Sample #3 */\n        0xc0, 0x6d, 0x37, 0x7e,     0xcd, 0x10, 0x19, 0x69\n    },\n    {\n        /* Sample #4 */\n        0x9c, 0xd3, 0x35, 0x80,     0xf9, 0xb6, 0x4d, 0xfb\n    }\n    };\n\n/* CMAC-TDES (Generation) - 3 Key Test Data */\nstatic const unsigned char des3_3key_key[24] = {\n    /* Key1 */\n    0x01, 0x23, 0x45, 0x67,     0x89, 0xaa, 0xcd, 0xef,\n    /* Key2 */\n    0x23, 0x45, 0x67, 0x89,     0xab, 0xcd, 0xef, 0x01,\n    /* Key3 */\n    0x45, 0x67, 0x89, 0xab,     0xcd, 0xef, 0x01, 0x23\n};\nstatic const unsigned char des3_3key_subkeys[2][8] = {\n    {\n        /* K1 */\n        0x9d, 0x74, 0xe7, 0x39,     0x33, 0x17, 0x96, 0xc0\n    },\n    {\n        /* K2 */\n        0x3a, 0xe9, 0xce, 0x72,     0x66, 0x2f, 0x2d, 0x9b\n    }\n};\nstatic const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE]\n    = {\n    {\n        /* Sample #1 */\n        0x7d, 0xb0, 0xd3, 0x7d,     0xf9, 0x36, 0xc5, 0x50\n    },\n    {\n        /* Sample #2 */\n        0x30, 0x23, 0x9c, 0xf1,     0xf5, 0x2e, 0x66, 0x09\n    },\n    {\n        /* Sample #3 */\n        0x6c, 0x9f, 0x3e, 0xe4,     0x92, 0x3f, 0x6b, 0xe2\n    },\n    {\n        /* Sample #4 */\n        0x99, 0x42, 0x9b, 0xd0,     0xbF, 0x79, 0x04, 0xe5\n    }\n    };\n\n#endif /* MBEDTLS_DES_C */\n\n#if defined(MBEDTLS_AES_C)\n/* AES AES-CMAC-PRF-128 Test Data */\nstatic const unsigned char PRFK[] = {\n    /* Key */\n    0x00, 0x01, 0x02, 0x03,     0x04, 0x05, 0x06, 0x07,\n    0x08, 0x09, 0x0a, 0x0b,     0x0c, 0x0d, 0x0e, 0x0f,\n    0xed, 0xcb\n};\n\n/* Sizes in bytes */\nstatic const size_t PRFKlen[NB_PRF_TESTS] = {\n    18,\n    16,\n    10\n};\n\n/* Message */\nstatic const unsigned char PRFM[] = {\n    0x00, 0x01, 0x02, 0x03,     0x04, 0x05, 0x06, 0x07,\n    0x08, 0x09, 0x0a, 0x0b,     0x0c, 0x0d, 0x0e, 0x0f,\n    0x10, 0x11, 0x12, 0x13\n};\n\nstatic const unsigned char PRFT[NB_PRF_TESTS][16] = {\n    {\n        0x84, 0xa3, 0x48, 0xa4,     0xa4, 0x5d, 0x23, 0x5b,\n        0xab, 0xff, 0xfc, 0x0d,     0x2b, 0x4d, 0xa0, 0x9a\n    },\n    {\n        0x98, 0x0a, 0xe8, 0x7b,     0x5f, 0x4c, 0x9c, 0x52,\n        0x14, 0xf5, 0xb6, 0xa8,     0x45, 0x5e, 0x4c, 0x2d\n    },\n    {\n        0x29, 0x0d, 0x9e, 0x11,     0x2e, 0xdb, 0x09, 0xee,\n        0x14, 0x1f, 0xcf, 0x64,     0xc0, 0xb7, 0x2f, 0x3d\n    }\n};\n#endif /* MBEDTLS_AES_C */\n\nstatic int cmac_test_subkeys(int verbose,\n                             const char *testname,\n                             const unsigned char *key,\n                             int keybits,\n                             const unsigned char *subkeys,\n                             mbedtls_cipher_type_t cipher_type,\n                             int block_size,\n                             int num_tests)\n{\n    int i, ret = 0;\n    mbedtls_cipher_context_t ctx;\n    const mbedtls_cipher_info_t *cipher_info;\n    unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE];\n    unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE];\n\n    cipher_info = mbedtls_cipher_info_from_type(cipher_type);\n    if (cipher_info == NULL) {\n        /* Failing at this point must be due to a build issue */\n        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n    }\n\n    for (i = 0; i < num_tests; i++) {\n        if (verbose != 0) {\n            mbedtls_printf(\"  %s CMAC subkey #%d: \", testname, i + 1);\n        }\n\n        mbedtls_cipher_init(&ctx);\n\n        if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) {\n            if (verbose != 0) {\n                mbedtls_printf(\"test execution failed\\n\");\n            }\n\n            goto cleanup;\n        }\n\n        if ((ret = mbedtls_cipher_setkey(&ctx, key, keybits,\n                                         MBEDTLS_ENCRYPT)) != 0) {\n            /* When CMAC is implemented by an alternative implementation, or\n             * the underlying primitive itself is implemented alternatively,\n             * AES-192 may be unavailable. This should not cause the selftest\n             * function to fail. */\n            if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||\n                 ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) &&\n                cipher_type == MBEDTLS_CIPHER_AES_192_ECB) {\n                if (verbose != 0) {\n                    mbedtls_printf(\"skipped\\n\");\n                }\n                goto next_test;\n            }\n\n            if (verbose != 0) {\n                mbedtls_printf(\"test execution failed\\n\");\n            }\n\n            goto cleanup;\n        }\n\n        ret = cmac_generate_subkeys(&ctx, K1, K2);\n        if (ret != 0) {\n            if (verbose != 0) {\n                mbedtls_printf(\"failed\\n\");\n            }\n\n            goto cleanup;\n        }\n\n        if ((ret = memcmp(K1, subkeys, block_size)) != 0  ||\n            (ret = memcmp(K2, &subkeys[block_size], block_size)) != 0) {\n            if (verbose != 0) {\n                mbedtls_printf(\"failed\\n\");\n            }\n\n            goto cleanup;\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n\nnext_test:\n        mbedtls_cipher_free(&ctx);\n    }\n\n    ret = 0;\n    goto exit;\n\ncleanup:\n    mbedtls_cipher_free(&ctx);\n\nexit:\n    return ret;\n}\n\nstatic int cmac_test_wth_cipher(int verbose,\n                                const char *testname,\n                                const unsigned char *key,\n                                int keybits,\n                                const unsigned char *messages,\n                                const unsigned int message_lengths[4],\n                                const unsigned char *expected_result,\n                                mbedtls_cipher_type_t cipher_type,\n                                int block_size,\n                                int num_tests)\n{\n    const mbedtls_cipher_info_t *cipher_info;\n    int i, ret = 0;\n    unsigned char output[MBEDTLS_CMAC_MAX_BLOCK_SIZE];\n\n    cipher_info = mbedtls_cipher_info_from_type(cipher_type);\n    if (cipher_info == NULL) {\n        /* Failing at this point must be due to a build issue */\n        ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n        goto exit;\n    }\n\n    for (i = 0; i < num_tests; i++) {\n        if (verbose != 0) {\n            mbedtls_printf(\"  %s CMAC #%d: \", testname, i + 1);\n        }\n\n        if ((ret = mbedtls_cipher_cmac(cipher_info, key, keybits, messages,\n                                       message_lengths[i], output)) != 0) {\n            /* When CMAC is implemented by an alternative implementation, or\n             * the underlying primitive itself is implemented alternatively,\n             * AES-192 and/or 3DES may be unavailable. This should not cause\n             * the selftest function to fail. */\n            if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||\n                 ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) &&\n                (cipher_type == MBEDTLS_CIPHER_AES_192_ECB ||\n                 cipher_type == MBEDTLS_CIPHER_DES_EDE3_ECB)) {\n                if (verbose != 0) {\n                    mbedtls_printf(\"skipped\\n\");\n                }\n                continue;\n            }\n\n            if (verbose != 0) {\n                mbedtls_printf(\"failed\\n\");\n            }\n            goto exit;\n        }\n\n        if ((ret = memcmp(output, &expected_result[i * block_size], block_size)) != 0) {\n            if (verbose != 0) {\n                mbedtls_printf(\"failed\\n\");\n            }\n            goto exit;\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n    ret = 0;\n\nexit:\n    return ret;\n}\n\n#if defined(MBEDTLS_AES_C)\nstatic int test_aes128_cmac_prf(int verbose)\n{\n    int i;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char output[MBEDTLS_AES_BLOCK_SIZE];\n\n    for (i = 0; i < NB_PRF_TESTS; i++) {\n        mbedtls_printf(\"  AES CMAC 128 PRF #%d: \", i);\n        ret = mbedtls_aes_cmac_prf_128(PRFK, PRFKlen[i], PRFM, 20, output);\n        if (ret != 0 ||\n            memcmp(output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE) != 0) {\n\n            if (verbose != 0) {\n                mbedtls_printf(\"failed\\n\");\n            }\n\n            return ret;\n        } else if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n    return ret;\n}\n#endif /* MBEDTLS_AES_C */\n\nint mbedtls_cmac_self_test(int verbose)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n#if defined(MBEDTLS_AES_C)\n    /* AES-128 */\n    if ((ret = cmac_test_subkeys(verbose,\n                                 \"AES 128\",\n                                 aes_128_key,\n                                 128,\n                                 (const unsigned char *) aes_128_subkeys,\n                                 MBEDTLS_CIPHER_AES_128_ECB,\n                                 MBEDTLS_AES_BLOCK_SIZE,\n                                 NB_CMAC_TESTS_PER_KEY)) != 0) {\n        return ret;\n    }\n\n    if ((ret = cmac_test_wth_cipher(verbose,\n                                    \"AES 128\",\n                                    aes_128_key,\n                                    128,\n                                    test_message,\n                                    aes_message_lengths,\n                                    (const unsigned char *) aes_128_expected_result,\n                                    MBEDTLS_CIPHER_AES_128_ECB,\n                                    MBEDTLS_AES_BLOCK_SIZE,\n                                    NB_CMAC_TESTS_PER_KEY)) != 0) {\n        return ret;\n    }\n\n    /* AES-192 */\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    if ((ret = cmac_test_subkeys(verbose,\n                                 \"AES 192\",\n                                 aes_192_key,\n                                 192,\n                                 (const unsigned char *) aes_192_subkeys,\n                                 MBEDTLS_CIPHER_AES_192_ECB,\n                                 MBEDTLS_AES_BLOCK_SIZE,\n                                 NB_CMAC_TESTS_PER_KEY)) != 0) {\n        return ret;\n    }\n\n    if ((ret = cmac_test_wth_cipher(verbose,\n                                    \"AES 192\",\n                                    aes_192_key,\n                                    192,\n                                    test_message,\n                                    aes_message_lengths,\n                                    (const unsigned char *) aes_192_expected_result,\n                                    MBEDTLS_CIPHER_AES_192_ECB,\n                                    MBEDTLS_AES_BLOCK_SIZE,\n                                    NB_CMAC_TESTS_PER_KEY)) != 0) {\n        return ret;\n    }\n#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */\n\n    /* AES-256 */\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    if ((ret = cmac_test_subkeys(verbose,\n                                 \"AES 256\",\n                                 aes_256_key,\n                                 256,\n                                 (const unsigned char *) aes_256_subkeys,\n                                 MBEDTLS_CIPHER_AES_256_ECB,\n                                 MBEDTLS_AES_BLOCK_SIZE,\n                                 NB_CMAC_TESTS_PER_KEY)) != 0) {\n        return ret;\n    }\n\n    if ((ret = cmac_test_wth_cipher(verbose,\n                                    \"AES 256\",\n                                    aes_256_key,\n                                    256,\n                                    test_message,\n                                    aes_message_lengths,\n                                    (const unsigned char *) aes_256_expected_result,\n                                    MBEDTLS_CIPHER_AES_256_ECB,\n                                    MBEDTLS_AES_BLOCK_SIZE,\n                                    NB_CMAC_TESTS_PER_KEY)) != 0) {\n        return ret;\n    }\n#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */\n#endif /* MBEDTLS_AES_C */\n\n#if defined(MBEDTLS_DES_C)\n    /* 3DES 2 key */\n    if ((ret = cmac_test_subkeys(verbose,\n                                 \"3DES 2 key\",\n                                 des3_2key_key,\n                                 192,\n                                 (const unsigned char *) des3_2key_subkeys,\n                                 MBEDTLS_CIPHER_DES_EDE3_ECB,\n                                 MBEDTLS_DES3_BLOCK_SIZE,\n                                 NB_CMAC_TESTS_PER_KEY)) != 0) {\n        return ret;\n    }\n\n    if ((ret = cmac_test_wth_cipher(verbose,\n                                    \"3DES 2 key\",\n                                    des3_2key_key,\n                                    192,\n                                    test_message,\n                                    des3_message_lengths,\n                                    (const unsigned char *) des3_2key_expected_result,\n                                    MBEDTLS_CIPHER_DES_EDE3_ECB,\n                                    MBEDTLS_DES3_BLOCK_SIZE,\n                                    NB_CMAC_TESTS_PER_KEY)) != 0) {\n        return ret;\n    }\n\n    /* 3DES 3 key */\n    if ((ret = cmac_test_subkeys(verbose,\n                                 \"3DES 3 key\",\n                                 des3_3key_key,\n                                 192,\n                                 (const unsigned char *) des3_3key_subkeys,\n                                 MBEDTLS_CIPHER_DES_EDE3_ECB,\n                                 MBEDTLS_DES3_BLOCK_SIZE,\n                                 NB_CMAC_TESTS_PER_KEY)) != 0) {\n        return ret;\n    }\n\n    if ((ret = cmac_test_wth_cipher(verbose,\n                                    \"3DES 3 key\",\n                                    des3_3key_key,\n                                    192,\n                                    test_message,\n                                    des3_message_lengths,\n                                    (const unsigned char *) des3_3key_expected_result,\n                                    MBEDTLS_CIPHER_DES_EDE3_ECB,\n                                    MBEDTLS_DES3_BLOCK_SIZE,\n                                    NB_CMAC_TESTS_PER_KEY)) != 0) {\n        return ret;\n    }\n#endif /* MBEDTLS_DES_C */\n\n#if defined(MBEDTLS_AES_C)\n    if ((ret = test_aes128_cmac_prf(verbose)) != 0) {\n        return ret;\n    }\n#endif /* MBEDTLS_AES_C */\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    return 0;\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_CMAC_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/common.h",
    "content": "/**\n * \\file common.h\n *\n * \\brief Utility macros for internal use in the library\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_LIBRARY_COMMON_H\n#define MBEDTLS_LIBRARY_COMMON_H\n\n#include \"mbedtls/build_info.h\"\n#include \"alignment.h\"\n\n#include <assert.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <stddef.h>\n\n#if defined(__ARM_NEON)\n#include <arm_neon.h>\n#define MBEDTLS_HAVE_NEON_INTRINSICS\n#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)\n#include <arm64_neon.h>\n#define MBEDTLS_HAVE_NEON_INTRINSICS\n#endif\n\n/** Helper to define a function as static except when building invasive tests.\n *\n * If a function is only used inside its own source file and should be\n * declared `static` to allow the compiler to optimize for code size,\n * but that function has unit tests, define it with\n * ```\n * MBEDTLS_STATIC_TESTABLE int mbedtls_foo(...) { ... }\n * ```\n * and declare it in a header in the `library/` directory with\n * ```\n * #if defined(MBEDTLS_TEST_HOOKS)\n * int mbedtls_foo(...);\n * #endif\n * ```\n */\n#if defined(MBEDTLS_TEST_HOOKS)\n#define MBEDTLS_STATIC_TESTABLE\n#else\n#define MBEDTLS_STATIC_TESTABLE static\n#endif\n\n#if defined(MBEDTLS_TEST_HOOKS)\nextern void (*mbedtls_test_hook_test_fail)(const char *test, int line, const char *file);\n#define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST) \\\n    do { \\\n        if ((!(TEST)) && ((*mbedtls_test_hook_test_fail) != NULL)) \\\n        { \\\n            (*mbedtls_test_hook_test_fail)( #TEST, __LINE__, __FILE__); \\\n        } \\\n    } while (0)\n#else\n#define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST)\n#endif /* defined(MBEDTLS_TEST_HOOKS) */\n\n/** \\def ARRAY_LENGTH\n * Return the number of elements of a static or stack array.\n *\n * \\param array         A value of array (not pointer) type.\n *\n * \\return The number of elements of the array.\n */\n/* A correct implementation of ARRAY_LENGTH, but which silently gives\n * a nonsensical result if called with a pointer rather than an array. */\n#define ARRAY_LENGTH_UNSAFE(array)            \\\n    (sizeof(array) / sizeof(*(array)))\n\n#if defined(__GNUC__)\n/* Test if arg and &(arg)[0] have the same type. This is true if arg is\n * an array but not if it's a pointer. */\n#define IS_ARRAY_NOT_POINTER(arg)                                     \\\n    (!__builtin_types_compatible_p(__typeof__(arg),                \\\n                                   __typeof__(&(arg)[0])))\n/* A compile-time constant with the value 0. If `const_expr` is not a\n * compile-time constant with a nonzero value, cause a compile-time error. */\n#define STATIC_ASSERT_EXPR(const_expr)                                \\\n    (0 && sizeof(struct { unsigned int STATIC_ASSERT : 1 - 2 * !(const_expr); }))\n\n/* Return the scalar value `value` (possibly promoted). This is a compile-time\n * constant if `value` is. `condition` must be a compile-time constant.\n * If `condition` is false, arrange to cause a compile-time error. */\n#define STATIC_ASSERT_THEN_RETURN(condition, value)   \\\n    (STATIC_ASSERT_EXPR(condition) ? 0 : (value))\n\n#define ARRAY_LENGTH(array)                                           \\\n    (STATIC_ASSERT_THEN_RETURN(IS_ARRAY_NOT_POINTER(array),         \\\n                               ARRAY_LENGTH_UNSAFE(array)))\n\n#else\n/* If we aren't sure the compiler supports our non-standard tricks,\n * fall back to the unsafe implementation. */\n#define ARRAY_LENGTH(array) ARRAY_LENGTH_UNSAFE(array)\n#endif\n/** Allow library to access its structs' private members.\n *\n * Although structs defined in header files are publicly available,\n * their members are private and should not be accessed by the user.\n */\n#define MBEDTLS_ALLOW_PRIVATE_ACCESS\n\n/**\n * \\brief       Securely zeroize a buffer then free it.\n *\n *              Similar to making consecutive calls to\n *              \\c mbedtls_platform_zeroize() and \\c mbedtls_free(), but has\n *              code size savings, and potential for optimisation in the future.\n *\n *              Guaranteed to be a no-op if \\p buf is \\c NULL and \\p len is 0.\n *\n * \\param buf   Buffer to be zeroized then freed.\n * \\param len   Length of the buffer in bytes\n */\nvoid mbedtls_zeroize_and_free(void *buf, size_t len);\n\n/** Return an offset into a buffer.\n *\n * This is just the addition of an offset to a pointer, except that this\n * function also accepts an offset of 0 into a buffer whose pointer is null.\n * (`p + n` has undefined behavior when `p` is null, even when `n == 0`.\n * A null pointer is a valid buffer pointer when the size is 0, for example\n * as the result of `malloc(0)` on some platforms.)\n *\n * \\param p     Pointer to a buffer of at least n bytes.\n *              This may be \\p NULL if \\p n is zero.\n * \\param n     An offset in bytes.\n * \\return      Pointer to offset \\p n in the buffer \\p p.\n *              Note that this is only a valid pointer if the size of the\n *              buffer is at least \\p n + 1.\n */\nstatic inline unsigned char *mbedtls_buffer_offset(\n    unsigned char *p, size_t n)\n{\n    return p == NULL ? NULL : p + n;\n}\n\n/** Return an offset into a read-only buffer.\n *\n * Similar to mbedtls_buffer_offset(), but for const pointers.\n *\n * \\param p     Pointer to a buffer of at least n bytes.\n *              This may be \\p NULL if \\p n is zero.\n * \\param n     An offset in bytes.\n * \\return      Pointer to offset \\p n in the buffer \\p p.\n *              Note that this is only a valid pointer if the size of the\n *              buffer is at least \\p n + 1.\n */\nstatic inline const unsigned char *mbedtls_buffer_offset_const(\n    const unsigned char *p, size_t n)\n{\n    return p == NULL ? NULL : p + n;\n}\n\n/* Always inline mbedtls_xor() for similar reasons as mbedtls_xor_no_simd(). */\n#if defined(__IAR_SYSTEMS_ICC__)\n#pragma inline = forced\n#elif defined(__GNUC__)\n__attribute__((always_inline))\n#endif\n/**\n * Perform a fast block XOR operation, such that\n * r[i] = a[i] ^ b[i] where 0 <= i < n\n *\n * \\param   r Pointer to result (buffer of at least \\p n bytes). \\p r\n *            may be equal to either \\p a or \\p b, but behaviour when\n *            it overlaps in other ways is undefined.\n * \\param   a Pointer to input (buffer of at least \\p n bytes)\n * \\param   b Pointer to input (buffer of at least \\p n bytes)\n * \\param   n Number of bytes to process.\n *\n * \\note      Depending on the situation, it may be faster to use either mbedtls_xor() or\n *            mbedtls_xor_no_simd() (these are functionally equivalent).\n *            If the result is used immediately after the xor operation in non-SIMD code (e.g, in\n *            AES-CBC), there may be additional latency to transfer the data from SIMD to scalar\n *            registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where\n *            the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster.\n *            For targets without SIMD support, they will behave the same.\n */\nstatic inline void mbedtls_xor(unsigned char *r,\n                               const unsigned char *a,\n                               const unsigned char *b,\n                               size_t n)\n{\n    size_t i = 0;\n#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)\n#if defined(MBEDTLS_HAVE_NEON_INTRINSICS) && \\\n    (!(defined(MBEDTLS_COMPILER_IS_GCC) && MBEDTLS_GCC_VERSION < 70300))\n    /* Old GCC versions generate a warning here, so disable the NEON path for these compilers */\n    for (; (i + 16) <= n; i += 16) {\n        uint8x16_t v1 = vld1q_u8(a + i);\n        uint8x16_t v2 = vld1q_u8(b + i);\n        uint8x16_t x = veorq_u8(v1, v2);\n        vst1q_u8(r + i, x);\n    }\n#if defined(__IAR_SYSTEMS_ICC__)\n    /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case\n     * where n is a constant multiple of 16.\n     * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time\n     * constant, and is a very small perf regression if n is not a compile-time constant. */\n    if (n % 16 == 0) {\n        return;\n    }\n#endif\n#elif defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64)\n    /* This codepath probably only makes sense on architectures with 64-bit registers */\n    for (; (i + 8) <= n; i += 8) {\n        uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i);\n        mbedtls_put_unaligned_uint64(r + i, x);\n    }\n#if defined(__IAR_SYSTEMS_ICC__)\n    if (n % 8 == 0) {\n        return;\n    }\n#endif\n#else\n    for (; (i + 4) <= n; i += 4) {\n        uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i);\n        mbedtls_put_unaligned_uint32(r + i, x);\n    }\n#if defined(__IAR_SYSTEMS_ICC__)\n    if (n % 4 == 0) {\n        return;\n    }\n#endif\n#endif\n#endif\n    for (; i < n; i++) {\n        r[i] = a[i] ^ b[i];\n    }\n}\n\n/* Always inline mbedtls_xor_no_simd() as we see significant perf regressions when it does not get\n * inlined (e.g., observed about 3x perf difference in gcm_mult_largetable with gcc 7 - 12) */\n#if defined(__IAR_SYSTEMS_ICC__)\n#pragma inline = forced\n#elif defined(__GNUC__)\n__attribute__((always_inline))\n#endif\n/**\n * Perform a fast block XOR operation, such that\n * r[i] = a[i] ^ b[i] where 0 <= i < n\n *\n * In some situations, this can perform better than mbedtls_xor() (e.g., it's about 5%\n * better in AES-CBC).\n *\n * \\param   r Pointer to result (buffer of at least \\p n bytes). \\p r\n *            may be equal to either \\p a or \\p b, but behaviour when\n *            it overlaps in other ways is undefined.\n * \\param   a Pointer to input (buffer of at least \\p n bytes)\n * \\param   b Pointer to input (buffer of at least \\p n bytes)\n * \\param   n Number of bytes to process.\n *\n * \\note      Depending on the situation, it may be faster to use either mbedtls_xor() or\n *            mbedtls_xor_no_simd() (these are functionally equivalent).\n *            If the result is used immediately after the xor operation in non-SIMD code (e.g, in\n *            AES-CBC), there may be additional latency to transfer the data from SIMD to scalar\n *            registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where\n *            the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster.\n *            For targets without SIMD support, they will behave the same.\n */\nstatic inline void mbedtls_xor_no_simd(unsigned char *r,\n                                       const unsigned char *a,\n                                       const unsigned char *b,\n                                       size_t n)\n{\n    size_t i = 0;\n#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)\n#if defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64)\n    /* This codepath probably only makes sense on architectures with 64-bit registers */\n    for (; (i + 8) <= n; i += 8) {\n        uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i);\n        mbedtls_put_unaligned_uint64(r + i, x);\n    }\n#if defined(__IAR_SYSTEMS_ICC__)\n    /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case\n     * where n is a constant multiple of 8.\n     * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time\n     * constant, and is a very small perf regression if n is not a compile-time constant. */\n    if (n % 8 == 0) {\n        return;\n    }\n#endif\n#else\n    for (; (i + 4) <= n; i += 4) {\n        uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i);\n        mbedtls_put_unaligned_uint32(r + i, x);\n    }\n#if defined(__IAR_SYSTEMS_ICC__)\n    if (n % 4 == 0) {\n        return;\n    }\n#endif\n#endif\n#endif\n    for (; i < n; i++) {\n        r[i] = a[i] ^ b[i];\n    }\n}\n\n/* Fix MSVC C99 compatible issue\n *      MSVC support __func__ from visual studio 2015( 1900 )\n *      Use MSVC predefine macro to avoid name check fail.\n */\n#if (defined(_MSC_VER) && (_MSC_VER <= 1900))\n#define /*no-check-names*/ __func__ __FUNCTION__\n#endif\n\n/* Define `asm` for compilers which don't define it. */\n/* *INDENT-OFF* */\n#ifndef asm\n#if defined(__IAR_SYSTEMS_ICC__)\n#define asm __asm\n#else\n#define asm __asm__\n#endif\n#endif\n/* *INDENT-ON* */\n\n/*\n * Define the constraint used for read-only pointer operands to aarch64 asm.\n *\n * This is normally the usual \"r\", but for aarch64_32 (aka ILP32,\n * as found in watchos), \"p\" is required to avoid warnings from clang.\n *\n * Note that clang does not recognise '+p' or '=p', and armclang\n * does not recognise 'p' at all. Therefore, to update a pointer from\n * aarch64 assembly, it is necessary to use something like:\n *\n * uintptr_t uptr = (uintptr_t) ptr;\n * asm( \"ldr x4, [%x0], #8\" ... : \"+r\" (uptr) : : )\n * ptr = (void*) uptr;\n *\n * Note that the \"x\" in \"%x0\" is neccessary; writing \"%0\" will cause warnings.\n */\n#if defined(__aarch64__) && defined(MBEDTLS_HAVE_ASM)\n#if UINTPTR_MAX == 0xfffffffful\n/* ILP32: Specify the pointer operand slightly differently, as per #7787. */\n#define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT \"p\"\n#elif UINTPTR_MAX == 0xfffffffffffffffful\n/* Normal case (64-bit pointers): use \"r\" as the constraint for pointer operands to asm */\n#define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT \"r\"\n#else\n#error \"Unrecognised pointer size for aarch64\"\n#endif\n#endif\n\n/* Always provide a static assert macro, so it can be used unconditionally.\n * It does nothing on systems where we don't know how to define a static assert.\n */\n/* Can't use the C11-style `defined(static_assert)` on FreeBSD, since it\n * defines static_assert even with -std=c99, but then complains about it.\n */\n#if defined(static_assert) && !defined(__FreeBSD__)\n#define MBEDTLS_STATIC_ASSERT(expr, msg)    static_assert(expr, msg)\n#else\n/* Make sure `MBEDTLS_STATIC_ASSERT(expr, msg);` is valid both inside and\n * outside a function. We choose a struct declaration, which can be repeated\n * any number of times and does not need a matching definition. */\n#define MBEDTLS_STATIC_ASSERT(expr, msg)                                \\\n    struct ISO_C_does_not_allow_extra_semicolon_outside_of_a_function\n#endif\n\n#if defined(__has_builtin)\n#define MBEDTLS_HAS_BUILTIN(x) __has_builtin(x)\n#else\n#define MBEDTLS_HAS_BUILTIN(x) 0\n#endif\n\n/* Define compiler branch hints */\n#if MBEDTLS_HAS_BUILTIN(__builtin_expect)\n#define MBEDTLS_LIKELY(x)       __builtin_expect(!!(x), 1)\n#define MBEDTLS_UNLIKELY(x)     __builtin_expect(!!(x), 0)\n#else\n#define MBEDTLS_LIKELY(x)       x\n#define MBEDTLS_UNLIKELY(x)     x\n#endif\n\n/* MBEDTLS_ASSUME may be used to provide additional information to the compiler\n * which can result in smaller code-size. */\n#if MBEDTLS_HAS_BUILTIN(__builtin_assume)\n/* clang provides __builtin_assume */\n#define MBEDTLS_ASSUME(x)       __builtin_assume(x)\n#elif MBEDTLS_HAS_BUILTIN(__builtin_unreachable)\n/* gcc and IAR can use __builtin_unreachable */\n#define MBEDTLS_ASSUME(x)       do { if (!(x)) __builtin_unreachable(); } while (0)\n#elif defined(_MSC_VER)\n/* Supported by MSVC since VS 2005 */\n#define MBEDTLS_ASSUME(x)       __assume(x)\n#else\n#define MBEDTLS_ASSUME(x)       do { } while (0)\n#endif\n\n/* For gcc -Os, override with -O2 for a given function.\n *\n * This will not affect behaviour for other optimisation settings, e.g. -O0.\n */\n#if defined(MBEDTLS_COMPILER_IS_GCC) && defined(__OPTIMIZE_SIZE__)\n#define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE __attribute__((optimize(\"-O2\")))\n#else\n#define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE\n#endif\n\n/* Suppress compiler warnings for unused functions and variables. */\n#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__has_attribute)\n#    if __has_attribute(unused)\n#        define MBEDTLS_MAYBE_UNUSED __attribute__((unused))\n#    endif\n#endif\n#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__GNUC__)\n#    define MBEDTLS_MAYBE_UNUSED __attribute__((unused))\n#endif\n#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__IAR_SYSTEMS_ICC__) && defined(__VER__)\n/* IAR does support __attribute__((unused)), but only if the -e flag (extended language support)\n * is given; the pragma always works.\n * Unfortunately the pragma affects the rest of the file where it is used, but this is harmless.\n * Check for version 5.2 or later - this pragma may be supported by earlier versions, but I wasn't\n * able to find documentation).\n */\n#    if (__VER__ >= 5020000)\n#        define MBEDTLS_MAYBE_UNUSED _Pragma(\"diag_suppress=Pe177\")\n#    endif\n#endif\n#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(_MSC_VER)\n#    define MBEDTLS_MAYBE_UNUSED __pragma(warning(suppress:4189))\n#endif\n#if !defined(MBEDTLS_MAYBE_UNUSED)\n#    define MBEDTLS_MAYBE_UNUSED\n#endif\n\n/* GCC >= 15 has a warning 'unterminated-string-initialization' which complains if you initialize\n * a string into an array without space for a terminating NULL character. In some places in the\n * codebase this behaviour is intended, so we add the macro MBEDTLS_ATTRIBUTE_UNTERMINATED_STRING\n * to suppress the warning in these places.\n */\n#if defined(__has_attribute)\n#if __has_attribute(nonstring)\n#define MBEDTLS_HAS_ATTRIBUTE_NONSTRING\n#endif /* __has_attribute(nonstring) */\n#endif /* __has_attribute */\n#if defined(MBEDTLS_HAS_ATTRIBUTE_NONSTRING)\n#define MBEDTLS_ATTRIBUTE_UNTERMINATED_STRING __attribute__((nonstring))\n#else\n#define MBEDTLS_ATTRIBUTE_UNTERMINATED_STRING\n#endif /* MBEDTLS_HAS_ATTRIBUTE_NONSTRING */\n\n#endif /* MBEDTLS_LIBRARY_COMMON_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/constant_time.c",
    "content": "/**\n *  Constant-time functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n * The following functions are implemented without using comparison operators, as those\n * might be translated to branches by some compilers on some platforms.\n */\n\n#include <stdint.h>\n#include <limits.h>\n\n#include \"common.h\"\n#include \"constant_time_internal.h\"\n#include \"mbedtls/constant_time.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include <string.h>\n\n#if !defined(MBEDTLS_CT_ASM)\n/*\n * Define an object with the value zero, such that the compiler cannot prove that it\n * has the value zero (because it is volatile, it \"may be modified in ways unknown to\n * the implementation\").\n */\nvolatile mbedtls_ct_uint_t mbedtls_ct_zero = 0;\n#endif\n\n/*\n * Define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS where assembly is present to\n * perform fast unaligned access to volatile data.\n *\n * This is needed because mbedtls_get_unaligned_uintXX etc don't support volatile\n * memory accesses.\n *\n * Some of these definitions could be moved into alignment.h but for now they are\n * only used here.\n */\n#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) && \\\n    ((defined(MBEDTLS_CT_ARM_ASM) && (UINTPTR_MAX == 0xfffffffful)) || \\\n    defined(MBEDTLS_CT_AARCH64_ASM))\n/* We check pointer sizes to avoid issues with them not matching register size requirements */\n#define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS\n\nstatic inline uint32_t mbedtls_get_unaligned_volatile_uint32(volatile const unsigned char *p)\n{\n    /* This is UB, even where it's safe:\n     *    return *((volatile uint32_t*)p);\n     * so instead the same thing is expressed in assembly below.\n     */\n    uint32_t r;\n#if defined(MBEDTLS_CT_ARM_ASM)\n    asm volatile (\"ldr %0, [%1]\" : \"=r\" (r) : \"r\" (p) :);\n#elif defined(MBEDTLS_CT_AARCH64_ASM)\n    asm volatile (\"ldr %w0, [%1]\" : \"=r\" (r) : MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT(p) :);\n#else\n#error \"No assembly defined for mbedtls_get_unaligned_volatile_uint32\"\n#endif\n    return r;\n}\n#endif /* defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) &&\n          (defined(MBEDTLS_CT_ARM_ASM) || defined(MBEDTLS_CT_AARCH64_ASM)) */\n\nint mbedtls_ct_memcmp(const void *a,\n                      const void *b,\n                      size_t n)\n{\n    size_t i = 0;\n    /*\n     * `A` and `B` are cast to volatile to ensure that the compiler\n     * generates code that always fully reads both buffers.\n     * Otherwise it could generate a test to exit early if `diff` has all\n     * bits set early in the loop.\n     */\n    volatile const unsigned char *A = (volatile const unsigned char *) a;\n    volatile const unsigned char *B = (volatile const unsigned char *) b;\n    uint32_t diff = 0;\n\n#if defined(MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS)\n    for (; (i + 4) <= n; i += 4) {\n        uint32_t x = mbedtls_get_unaligned_volatile_uint32(A + i);\n        uint32_t y = mbedtls_get_unaligned_volatile_uint32(B + i);\n        diff |= x ^ y;\n    }\n#endif\n\n    for (; i < n; i++) {\n        /* Read volatile data in order before computing diff.\n         * This avoids IAR compiler warning:\n         * 'the order of volatile accesses is undefined ..' */\n        unsigned char x = A[i], y = B[i];\n        diff |= x ^ y;\n    }\n\n\n#if (INT_MAX < INT32_MAX)\n    /* We don't support int smaller than 32-bits, but if someone tried to build\n     * with this configuration, there is a risk that, for differing data, the\n     * only bits set in diff are in the top 16-bits, and would be lost by a\n     * simple cast from uint32 to int.\n     * This would have significant security implications, so protect against it. */\n#error \"mbedtls_ct_memcmp() requires minimum 32-bit ints\"\n#else\n    /* The bit-twiddling ensures that when we cast uint32_t to int, we are casting\n     * a value that is in the range 0..INT_MAX - a value larger than this would\n     * result in implementation defined behaviour.\n     *\n     * This ensures that the value returned by the function is non-zero iff\n     * diff is non-zero.\n     */\n    return (int) ((diff & 0xffff) | (diff >> 16));\n#endif\n}\n\n#if defined(MBEDTLS_NIST_KW_C)\n\nint mbedtls_ct_memcmp_partial(const void *a,\n                              const void *b,\n                              size_t n,\n                              size_t skip_head,\n                              size_t skip_tail)\n{\n    unsigned int diff = 0;\n\n    volatile const unsigned char *A = (volatile const unsigned char *) a;\n    volatile const unsigned char *B = (volatile const unsigned char *) b;\n\n    size_t valid_end = n - skip_tail;\n\n    for (size_t i = 0; i < n; i++) {\n        unsigned char x = A[i], y = B[i];\n        unsigned int d = x ^ y;\n        mbedtls_ct_condition_t valid = mbedtls_ct_bool_and(mbedtls_ct_uint_ge(i, skip_head),\n                                                           mbedtls_ct_uint_lt(i, valid_end));\n        diff |= mbedtls_ct_uint_if_else_0(valid, d);\n    }\n\n    /* Since we go byte-by-byte, the only bits set will be in the bottom 8 bits, so the\n     * cast from uint to int is safe. */\n    return (int) diff;\n}\n\n#endif\n\n#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)\n\nvoid mbedtls_ct_memmove_left(void *start, size_t total, size_t offset)\n{\n    volatile unsigned char *buf = start;\n    for (size_t i = 0; i < total; i++) {\n        mbedtls_ct_condition_t no_op = mbedtls_ct_uint_gt(total - offset, i);\n        /* The first `total - offset` passes are a no-op. The last\n         * `offset` passes shift the data one byte to the left and\n         * zero out the last byte. */\n        for (size_t n = 0; n < total - 1; n++) {\n            unsigned char current = buf[n];\n            unsigned char next    = buf[n+1];\n            buf[n] = mbedtls_ct_uint_if(no_op, current, next);\n        }\n        buf[total-1] = mbedtls_ct_uint_if_else_0(no_op, buf[total-1]);\n    }\n}\n\n#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */\n\nvoid mbedtls_ct_memcpy_if(mbedtls_ct_condition_t condition,\n                          unsigned char *dest,\n                          const unsigned char *src1,\n                          const unsigned char *src2,\n                          size_t len)\n{\n#if defined(MBEDTLS_CT_SIZE_64)\n    const uint64_t mask     = (uint64_t) condition;\n    const uint64_t not_mask = (uint64_t) ~mbedtls_ct_compiler_opaque(condition);\n#else\n    const uint32_t mask     = (uint32_t) condition;\n    const uint32_t not_mask = (uint32_t) ~mbedtls_ct_compiler_opaque(condition);\n#endif\n\n    /* If src2 is NULL, setup src2 so that we read from the destination address.\n     *\n     * This means that if src2 == NULL && condition is false, the result will be a\n     * no-op because we read from dest and write the same data back into dest.\n     */\n    if (src2 == NULL) {\n        src2 = dest;\n    }\n\n    /* dest[i] = c1 == c2 ? src[i] : dest[i] */\n    size_t i = 0;\n#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)\n#if defined(MBEDTLS_CT_SIZE_64)\n    for (; (i + 8) <= len; i += 8) {\n        uint64_t a = mbedtls_get_unaligned_uint64(src1 + i) & mask;\n        uint64_t b = mbedtls_get_unaligned_uint64(src2 + i) & not_mask;\n        mbedtls_put_unaligned_uint64(dest + i, a | b);\n    }\n#else\n    for (; (i + 4) <= len; i += 4) {\n        uint32_t a = mbedtls_get_unaligned_uint32(src1 + i) & mask;\n        uint32_t b = mbedtls_get_unaligned_uint32(src2 + i) & not_mask;\n        mbedtls_put_unaligned_uint32(dest + i, a | b);\n    }\n#endif /* defined(MBEDTLS_CT_SIZE_64) */\n#endif /* MBEDTLS_EFFICIENT_UNALIGNED_ACCESS */\n    for (; i < len; i++) {\n        dest[i] = (src1[i] & mask) | (src2[i] & not_mask);\n    }\n}\n\nvoid mbedtls_ct_memcpy_offset(unsigned char *dest,\n                              const unsigned char *src,\n                              size_t offset,\n                              size_t offset_min,\n                              size_t offset_max,\n                              size_t len)\n{\n    size_t offsetval;\n\n    for (offsetval = offset_min; offsetval <= offset_max; offsetval++) {\n        mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offsetval, offset), dest, src + offsetval, NULL,\n                             len);\n    }\n}\n\n#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)\n\nvoid mbedtls_ct_zeroize_if(mbedtls_ct_condition_t condition, void *buf, size_t len)\n{\n    uint32_t mask = (uint32_t) ~condition;\n    uint8_t *p = (uint8_t *) buf;\n    size_t i = 0;\n#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)\n    for (; (i + 4) <= len; i += 4) {\n        mbedtls_put_unaligned_uint32((void *) (p + i),\n                                     mbedtls_get_unaligned_uint32((void *) (p + i)) & mask);\n    }\n#endif\n    for (; i < len; i++) {\n        p[i] = p[i] & mask;\n    }\n}\n\n#endif /* defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/constant_time_impl.h",
    "content": "/**\n *  Constant-time functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CONSTANT_TIME_IMPL_H\n#define MBEDTLS_CONSTANT_TIME_IMPL_H\n\n#include <stddef.h>\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_BIGNUM_C)\n#include \"mbedtls/bignum.h\"\n#endif\n\n/*\n * To improve readability of constant_time_internal.h, the static inline\n * definitions are here, and constant_time_internal.h has only the declarations.\n *\n * This results in duplicate declarations of the form:\n *     static inline void f();         // from constant_time_internal.h\n *     static inline void f() { ... }  // from constant_time_impl.h\n * when constant_time_internal.h is included.\n *\n * This appears to behave as if the declaration-without-definition was not present\n * (except for warnings if gcc -Wredundant-decls or similar is used).\n *\n * Disable -Wredundant-decls so that gcc does not warn about this. This is re-enabled\n * at the bottom of this file.\n */\n#if defined(MBEDTLS_COMPILER_IS_GCC) && (__GNUC__ > 4)\n    #pragma GCC diagnostic push\n    #pragma GCC diagnostic ignored \"-Wredundant-decls\"\n#endif\n\n/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */\n#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && (!defined(__ARMCC_VERSION) || \\\n    __ARMCC_VERSION >= 6000000)\n#define MBEDTLS_CT_ASM\n#if (defined(__arm__) || defined(__thumb__) || defined(__thumb2__))\n#define MBEDTLS_CT_ARM_ASM\n#elif defined(__aarch64__)\n#define MBEDTLS_CT_AARCH64_ASM\n#elif defined(__amd64__) || defined(__x86_64__)\n#define MBEDTLS_CT_X86_64_ASM\n#elif defined(__i386__)\n#define MBEDTLS_CT_X86_ASM\n#endif\n#endif\n\n#define MBEDTLS_CT_SIZE (sizeof(mbedtls_ct_uint_t) * 8)\n\n\n/* ============================================================================\n * Core const-time primitives\n */\n\n/* Ensure that the compiler cannot know the value of x (i.e., cannot optimise\n * based on its value) after this function is called.\n *\n * If we are not using assembly, this will be fairly inefficient, so its use\n * should be minimised.\n */\n\n#if !defined(MBEDTLS_CT_ASM)\nextern volatile mbedtls_ct_uint_t mbedtls_ct_zero;\n#endif\n\n/**\n * \\brief   Ensure that a value cannot be known at compile time.\n *\n * \\param x        The value to hide from the compiler.\n * \\return         The same value that was passed in, such that the compiler\n *                 cannot prove its value (even for calls of the form\n *                 x = mbedtls_ct_compiler_opaque(1), x will be unknown).\n *\n * \\note           This is mainly used in constructing mbedtls_ct_condition_t\n *                 values and performing operations over them, to ensure that\n *                 there is no way for the compiler to ever know anything about\n *                 the value of an mbedtls_ct_condition_t.\n */\nstatic inline mbedtls_ct_uint_t mbedtls_ct_compiler_opaque(mbedtls_ct_uint_t x)\n{\n#if defined(MBEDTLS_CT_ASM)\n    asm volatile (\"\" : [x] \"+r\" (x) :);\n    return x;\n#else\n    return x ^ mbedtls_ct_zero;\n#endif\n}\n\n/*\n * Selecting unified syntax is needed for gcc, and harmless on clang.\n *\n * This is needed because on Thumb 1, condition flags are always set, so\n * e.g. \"negs\" is supported but \"neg\" is not (on Thumb 2, both exist).\n *\n * Under Thumb 1 unified syntax, only the \"negs\" form is accepted, and\n * under divided syntax, only the \"neg\" form is accepted. clang only\n * supports unified syntax.\n *\n * On Thumb 2 and Arm, both compilers are happy with the \"s\" suffix,\n * although we don't actually care about setting the flags.\n *\n * For old versions of gcc (see #8516 for details), restore divided\n * syntax afterwards - otherwise old versions of gcc seem to apply\n * unified syntax globally, which breaks other asm code.\n */\n#if defined(MBEDTLS_COMPILER_IS_GCC) && defined(__thumb__) && !defined(__thumb2__) && \\\n    (__GNUC__ < 11) && !defined(__ARM_ARCH_2__)\n#define RESTORE_ASM_SYNTAX  \".syntax divided                      \\n\\t\"\n#else\n#define RESTORE_ASM_SYNTAX\n#endif\n\n/* Convert a number into a condition in constant time. */\nstatic inline mbedtls_ct_condition_t mbedtls_ct_bool(mbedtls_ct_uint_t x)\n{\n    /*\n     * Define mask-generation code that, as far as possible, will not use branches or conditional instructions.\n     *\n     * For some platforms / type sizes, we define assembly to assure this.\n     *\n     * Otherwise, we define a plain C fallback which (in May 2023) does not get optimised into\n     * conditional instructions or branches by trunk clang, gcc, or MSVC v19.\n     */\n#if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))\n    mbedtls_ct_uint_t s;\n    asm volatile (\"neg %x[s], %x[x]                               \\n\\t\"\n                  \"orr %x[x], %x[s], %x[x]                        \\n\\t\"\n                  \"asr %x[x], %x[x], 63                           \\n\\t\"\n                  :\n                  [s] \"=&r\" (s),\n                  [x] \"+&r\" (x)\n                  :\n                  :\n                  );\n    return (mbedtls_ct_condition_t) x;\n#elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32)\n    uint32_t s;\n    asm volatile (\".syntax unified                                \\n\\t\"\n                  \"negs %[s], %[x]                                \\n\\t\"\n                  \"orrs %[x], %[x], %[s]                          \\n\\t\"\n                  \"asrs %[x], %[x], #31                           \\n\\t\"\n                  RESTORE_ASM_SYNTAX\n                  :\n                  [s] \"=&l\" (s),\n                  [x] \"+&l\" (x)\n                  :\n                  :\n                  \"cc\" /* clobbers flag bits */\n                  );\n    return (mbedtls_ct_condition_t) x;\n#elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))\n    uint64_t s;\n    asm volatile (\"mov  %[x], %[s]                                \\n\\t\"\n                  \"neg  %[s]                                      \\n\\t\"\n                  \"or   %[x], %[s]                                \\n\\t\"\n                  \"sar  $63, %[s]                                 \\n\\t\"\n                  :\n                  [s] \"=&a\" (s)\n                  :\n                  [x] \"D\" (x)\n                  :\n                  );\n    return (mbedtls_ct_condition_t) s;\n#elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32)\n    uint32_t s;\n    asm volatile (\"mov %[x], %[s]                                 \\n\\t\"\n                  \"neg %[s]                                       \\n\\t\"\n                  \"or %[s], %[x]                                  \\n\\t\"\n                  \"sar $31, %[x]                                  \\n\\t\"\n                  :\n                  [s] \"=&c\" (s),\n                  [x] \"+&a\" (x)\n                  :\n                  :\n                  );\n    return (mbedtls_ct_condition_t) x;\n#else\n    const mbedtls_ct_uint_t xo = mbedtls_ct_compiler_opaque(x);\n#if defined(_MSC_VER)\n    /* MSVC has a warning about unary minus on unsigned, but this is\n     * well-defined and precisely what we want to do here */\n#pragma warning( push )\n#pragma warning( disable : 4146 )\n#endif\n    // y is negative (i.e., top bit set) iff x is non-zero\n    mbedtls_ct_int_t y = (-xo) | -(xo >> 1);\n\n    // extract only the sign bit of y so that y == 1 (if x is non-zero) or 0 (if x is zero)\n    y = (((mbedtls_ct_uint_t) y) >> (MBEDTLS_CT_SIZE - 1));\n\n    // -y has all bits set (if x is non-zero), or all bits clear (if x is zero)\n    return (mbedtls_ct_condition_t) (-y);\n#if defined(_MSC_VER)\n#pragma warning( pop )\n#endif\n#endif\n}\n\nstatic inline mbedtls_ct_uint_t mbedtls_ct_if(mbedtls_ct_condition_t condition,\n                                              mbedtls_ct_uint_t if1,\n                                              mbedtls_ct_uint_t if0)\n{\n#if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))\n    asm volatile (\"and %x[if1], %x[if1], %x[condition]            \\n\\t\"\n                  \"mvn %x[condition], %x[condition]               \\n\\t\"\n                  \"and %x[condition], %x[condition], %x[if0]      \\n\\t\"\n                  \"orr %x[condition], %x[if1], %x[condition]\"\n                  :\n                  [condition] \"+&r\" (condition),\n                  [if1] \"+&r\" (if1)\n                  :\n                  [if0] \"r\" (if0)\n                  :\n                  );\n    return (mbedtls_ct_uint_t) condition;\n#elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32)\n    asm volatile (\".syntax unified                                \\n\\t\"\n                  \"ands %[if1], %[if1], %[condition]              \\n\\t\"\n                  \"mvns %[condition], %[condition]                \\n\\t\"\n                  \"ands %[condition], %[condition], %[if0]        \\n\\t\"\n                  \"orrs %[condition], %[if1], %[condition]        \\n\\t\"\n                  RESTORE_ASM_SYNTAX\n                  :\n                  [condition] \"+&l\" (condition),\n                  [if1] \"+&l\" (if1)\n                  :\n                  [if0] \"l\" (if0)\n                  :\n                  \"cc\"\n                  );\n    return (mbedtls_ct_uint_t) condition;\n#elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))\n    asm volatile (\"and  %[condition], %[if1]                      \\n\\t\"\n                  \"not  %[condition]                              \\n\\t\"\n                  \"and  %[condition], %[if0]                      \\n\\t\"\n                  \"or   %[if1], %[if0]                            \\n\\t\"\n                  :\n                  [condition] \"+&D\" (condition),\n                  [if1] \"+&S\" (if1),\n                  [if0] \"+&a\" (if0)\n                  :\n                  :\n                  );\n    return if0;\n#elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32)\n    asm volatile (\"and %[condition], %[if1]                       \\n\\t\"\n                  \"not %[condition]                               \\n\\t\"\n                  \"and %[if0], %[condition]                       \\n\\t\"\n                  \"or %[condition], %[if1]                        \\n\\t\"\n                  :\n                  [condition] \"+&c\" (condition),\n                  [if1] \"+&a\" (if1)\n                  :\n                  [if0] \"b\" (if0)\n                  :\n                  );\n    return if1;\n#else\n    mbedtls_ct_condition_t not_cond =\n        (mbedtls_ct_condition_t) (~mbedtls_ct_compiler_opaque(condition));\n    return (mbedtls_ct_uint_t) ((condition & if1) | (not_cond & if0));\n#endif\n}\n\nstatic inline mbedtls_ct_condition_t mbedtls_ct_uint_lt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y)\n{\n#if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))\n    uint64_t s1;\n    asm volatile (\"eor     %x[s1], %x[y], %x[x]                   \\n\\t\"\n                  \"sub     %x[x], %x[x], %x[y]                    \\n\\t\"\n                  \"bic     %x[x], %x[x], %x[s1]                   \\n\\t\"\n                  \"and     %x[s1], %x[s1], %x[y]                  \\n\\t\"\n                  \"orr     %x[s1], %x[x], %x[s1]                  \\n\\t\"\n                  \"asr     %x[x], %x[s1], 63\"\n                  :\n                  [s1] \"=&r\" (s1),\n                  [x] \"+&r\" (x)\n                  :\n                  [y] \"r\" (y)\n                  :\n                  );\n    return (mbedtls_ct_condition_t) x;\n#elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32)\n    uint32_t s1;\n    asm volatile (\n        \".syntax unified                                          \\n\\t\"\n#if defined(__thumb__) && !defined(__thumb2__)\n        \"movs     %[s1], %[x]                                     \\n\\t\"\n        \"eors     %[s1], %[s1], %[y]                              \\n\\t\"\n#else\n        \"eors     %[s1], %[x], %[y]                               \\n\\t\"\n#endif\n        \"subs    %[x], %[x], %[y]                                 \\n\\t\"\n        \"bics    %[x], %[x], %[s1]                                \\n\\t\"\n        \"ands    %[y], %[s1], %[y]                                \\n\\t\"\n        \"orrs    %[x], %[x], %[y]                                 \\n\\t\"\n        \"asrs    %[x], %[x], #31                                  \\n\\t\"\n        RESTORE_ASM_SYNTAX\n        :\n        [s1] \"=&l\" (s1),\n        [x] \"+&l\" (x),\n        [y] \"+&l\" (y)\n        :\n        :\n        \"cc\"\n        );\n    return (mbedtls_ct_condition_t) x;\n#elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))\n    uint64_t s;\n    asm volatile (\"mov %[x], %[s]                                 \\n\\t\"\n                  \"xor %[y], %[s]                                 \\n\\t\"\n                  \"sub %[y], %[x]                                 \\n\\t\"\n                  \"and %[s], %[y]                                 \\n\\t\"\n                  \"not %[s]                                       \\n\\t\"\n                  \"and %[s], %[x]                                 \\n\\t\"\n                  \"or %[y], %[x]                                  \\n\\t\"\n                  \"sar $63, %[x]                                  \\n\\t\"\n                  :\n                  [s] \"=&a\" (s),\n                  [x] \"+&D\" (x),\n                  [y] \"+&S\" (y)\n                  :\n                  :\n                  );\n    return (mbedtls_ct_condition_t) x;\n#elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32)\n    uint32_t s;\n    asm volatile (\"mov %[x], %[s]                                 \\n\\t\"\n                  \"xor %[y], %[s]                                 \\n\\t\"\n                  \"sub %[y], %[x]                                 \\n\\t\"\n                  \"and %[s], %[y]                                 \\n\\t\"\n                  \"not %[s]                                       \\n\\t\"\n                  \"and %[s], %[x]                                 \\n\\t\"\n                  \"or  %[y], %[x]                                 \\n\\t\"\n                  \"sar $31, %[x]                                  \\n\\t\"\n                  :\n                  [s] \"=&b\" (s),\n                  [x] \"+&a\" (x),\n                  [y] \"+&c\" (y)\n                  :\n                  :\n                  );\n    return (mbedtls_ct_condition_t) x;\n#else\n    /* Ensure that the compiler cannot optimise the following operations over x and y,\n     * even if it knows the value of x and y.\n     */\n    const mbedtls_ct_uint_t xo = mbedtls_ct_compiler_opaque(x);\n    const mbedtls_ct_uint_t yo = mbedtls_ct_compiler_opaque(y);\n    /*\n     * Check if the most significant bits (MSB) of the operands are different.\n     * cond is true iff the MSBs differ.\n     */\n    mbedtls_ct_condition_t cond = mbedtls_ct_bool((xo ^ yo) >> (MBEDTLS_CT_SIZE - 1));\n\n    /*\n     * If the MSB are the same then the difference x-y will be negative (and\n     * have its MSB set to 1 during conversion to unsigned) if and only if x<y.\n     *\n     * If the MSB are different, then the operand with the MSB of 1 is the\n     * bigger. (That is if y has MSB of 1, then x<y is true and it is false if\n     * the MSB of y is 0.)\n     */\n\n    // Select either y, or x - y\n    mbedtls_ct_uint_t ret = mbedtls_ct_if(cond, yo, (mbedtls_ct_uint_t) (xo - yo));\n\n    // Extract only the MSB of ret\n    ret = ret >> (MBEDTLS_CT_SIZE - 1);\n\n    // Convert to a condition (i.e., all bits set iff non-zero)\n    return mbedtls_ct_bool(ret);\n#endif\n}\n\nstatic inline mbedtls_ct_condition_t mbedtls_ct_uint_ne(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y)\n{\n    /* diff = 0 if x == y, non-zero otherwise */\n    const mbedtls_ct_uint_t diff = mbedtls_ct_compiler_opaque(x) ^ mbedtls_ct_compiler_opaque(y);\n\n    /* all ones if x != y, 0 otherwise */\n    return mbedtls_ct_bool(diff);\n}\n\nstatic inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low,\n                                                         unsigned char high,\n                                                         unsigned char c,\n                                                         unsigned char t)\n{\n    const unsigned char co = (unsigned char) mbedtls_ct_compiler_opaque(c);\n    const unsigned char to = (unsigned char) mbedtls_ct_compiler_opaque(t);\n\n    /* low_mask is: 0 if low <= c, 0x...ff if low > c */\n    unsigned low_mask = ((unsigned) co - low) >> 8;\n    /* high_mask is: 0 if c <= high, 0x...ff if c > high */\n    unsigned high_mask = ((unsigned) high - co) >> 8;\n\n    return (unsigned char) (~(low_mask | high_mask)) & to;\n}\n\n/* ============================================================================\n * Everything below here is trivial wrapper functions\n */\n\nstatic inline size_t mbedtls_ct_size_if(mbedtls_ct_condition_t condition,\n                                        size_t if1,\n                                        size_t if0)\n{\n    return (size_t) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0);\n}\n\nstatic inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition,\n                                          unsigned if1,\n                                          unsigned if0)\n{\n    return (unsigned) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0);\n}\n\nstatic inline mbedtls_ct_condition_t mbedtls_ct_bool_if(mbedtls_ct_condition_t condition,\n                                                        mbedtls_ct_condition_t if1,\n                                                        mbedtls_ct_condition_t if0)\n{\n    return (mbedtls_ct_condition_t) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1,\n                                                  (mbedtls_ct_uint_t) if0);\n}\n\n#if defined(MBEDTLS_BIGNUM_C)\n\nstatic inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition,\n                                                      mbedtls_mpi_uint if1,\n                                                      mbedtls_mpi_uint if0)\n{\n    return (mbedtls_mpi_uint) mbedtls_ct_if(condition,\n                                            (mbedtls_ct_uint_t) if1,\n                                            (mbedtls_ct_uint_t) if0);\n}\n\n#endif\n\nstatic inline size_t mbedtls_ct_size_if_else_0(mbedtls_ct_condition_t condition, size_t if1)\n{\n    return (size_t) (condition & if1);\n}\n\nstatic inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1)\n{\n    return (unsigned) (condition & if1);\n}\n\nstatic inline mbedtls_ct_condition_t mbedtls_ct_bool_if_else_0(mbedtls_ct_condition_t condition,\n                                                               mbedtls_ct_condition_t if1)\n{\n    return (mbedtls_ct_condition_t) (condition & if1);\n}\n\n#if defined(MBEDTLS_BIGNUM_C)\n\nstatic inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition,\n                                                             mbedtls_mpi_uint if1)\n{\n    return (mbedtls_mpi_uint) (condition & if1);\n}\n\n#endif /* MBEDTLS_BIGNUM_C */\n\nstatic inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0)\n{\n    /* Coverting int -> uint -> int here is safe, because we require if1 and if0 to be\n     * in the range -32767..0, and we require 32-bit int and uint types.\n     *\n     * This means that (0 <= -if0 < INT_MAX), so negating if0 is safe, and similarly for\n     * converting back to int.\n     */\n    return -((int) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) (-if1),\n                                 (mbedtls_ct_uint_t) (-if0)));\n}\n\nstatic inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1)\n{\n    return -((int) (condition & (-if1)));\n}\n\nstatic inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x,\n                                                        mbedtls_ct_uint_t y)\n{\n    return ~mbedtls_ct_uint_ne(x, y);\n}\n\nstatic inline mbedtls_ct_condition_t mbedtls_ct_uint_gt(mbedtls_ct_uint_t x,\n                                                        mbedtls_ct_uint_t y)\n{\n    return mbedtls_ct_uint_lt(y, x);\n}\n\nstatic inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x,\n                                                        mbedtls_ct_uint_t y)\n{\n    return ~mbedtls_ct_uint_lt(x, y);\n}\n\nstatic inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x,\n                                                        mbedtls_ct_uint_t y)\n{\n    return ~mbedtls_ct_uint_gt(x, y);\n}\n\nstatic inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x,\n                                                        mbedtls_ct_condition_t y)\n{\n    return (mbedtls_ct_condition_t) (x ^ y);\n}\n\nstatic inline mbedtls_ct_condition_t mbedtls_ct_bool_and(mbedtls_ct_condition_t x,\n                                                         mbedtls_ct_condition_t y)\n{\n    return (mbedtls_ct_condition_t) (x & y);\n}\n\nstatic inline mbedtls_ct_condition_t mbedtls_ct_bool_or(mbedtls_ct_condition_t x,\n                                                        mbedtls_ct_condition_t y)\n{\n    return (mbedtls_ct_condition_t) (x | y);\n}\n\nstatic inline mbedtls_ct_condition_t mbedtls_ct_bool_not(mbedtls_ct_condition_t x)\n{\n    return (mbedtls_ct_condition_t) (~x);\n}\n\n#if defined(MBEDTLS_COMPILER_IS_GCC) && (__GNUC__ > 4)\n/* Restore warnings for -Wredundant-decls on gcc */\n    #pragma GCC diagnostic pop\n#endif\n\n#endif /* MBEDTLS_CONSTANT_TIME_IMPL_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/constant_time_internal.h",
    "content": "/**\n *  Constant-time functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CONSTANT_TIME_INTERNAL_H\n#define MBEDTLS_CONSTANT_TIME_INTERNAL_H\n\n#include <stdint.h>\n#include <stddef.h>\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_BIGNUM_C)\n#include \"mbedtls/bignum.h\"\n#endif\n\n/* The constant-time interface provides various operations that are likely\n * to result in constant-time code that does not branch or use conditional\n * instructions for secret data (for secret pointers, this also applies to\n * the data pointed to).\n *\n * It has three main parts:\n *\n * - boolean operations\n *   These are all named mbedtls_ct_<type>_<operation>.\n *   They operate over <type> and return mbedtls_ct_condition_t.\n *   All arguments are considered secret.\n *   example: bool x = y | z          =>    x = mbedtls_ct_bool_or(y, z)\n *   example: bool x = y == z         =>    x = mbedtls_ct_uint_eq(y, z)\n *\n * - conditional data selection\n *   These are all named mbedtls_ct_<type>_if and mbedtls_ct_<type>_if_else_0\n *   All arguments are considered secret.\n *   example: size_t a = x ? b : c    =>    a = mbedtls_ct_size_if(x, b, c)\n *   example: unsigned a = x ? b : 0  =>    a = mbedtls_ct_uint_if_else_0(x, b)\n *\n * - block memory operations\n *   Only some arguments are considered secret, as documented for each\n *   function.\n *   example: if (x) memcpy(...)      =>    mbedtls_ct_memcpy_if(x, ...)\n *\n * mbedtls_ct_condition_t must be treated as opaque and only created and\n * manipulated via the functions in this header. The compiler should never\n * be able to prove anything about its value at compile-time.\n *\n * mbedtls_ct_uint_t is an unsigned integer type over which constant time\n * operations may be performed via the functions in this header. It is as big\n * as the larger of size_t and mbedtls_mpi_uint, i.e. it is safe to cast\n * to/from \"unsigned int\", \"size_t\", and \"mbedtls_mpi_uint\" (and any other\n * not-larger integer types).\n *\n * For Arm (32-bit, 64-bit and Thumb), x86 and x86-64, assembly implementations\n * are used to ensure that the generated code is constant time. For other\n * architectures, it uses a plain C fallback designed to yield constant-time code\n * (this has been observed to be constant-time on latest gcc, clang and MSVC\n * as of May 2023).\n *\n * For readability, the static inline definitions are separated out into\n * constant_time_impl.h.\n */\n\n#if (SIZE_MAX > 0xffffffffffffffffULL)\n/* Pointer size > 64-bit */\ntypedef size_t    mbedtls_ct_condition_t;\ntypedef size_t    mbedtls_ct_uint_t;\ntypedef ptrdiff_t mbedtls_ct_int_t;\n#define MBEDTLS_CT_TRUE  ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(SIZE_MAX))\n#elif (SIZE_MAX > 0xffffffff) || defined(MBEDTLS_HAVE_INT64)\n/* 32-bit < pointer size <= 64-bit, or 64-bit MPI */\ntypedef uint64_t  mbedtls_ct_condition_t;\ntypedef uint64_t  mbedtls_ct_uint_t;\ntypedef int64_t   mbedtls_ct_int_t;\n#define MBEDTLS_CT_SIZE_64\n#define MBEDTLS_CT_TRUE  ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT64_MAX))\n#else\n/* Pointer size <= 32-bit, and no 64-bit MPIs */\ntypedef uint32_t  mbedtls_ct_condition_t;\ntypedef uint32_t  mbedtls_ct_uint_t;\ntypedef int32_t   mbedtls_ct_int_t;\n#define MBEDTLS_CT_SIZE_32\n#define MBEDTLS_CT_TRUE  ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT32_MAX))\n#endif\n#define MBEDTLS_CT_FALSE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(0))\n\n/* ============================================================================\n * Boolean operations\n */\n\n/** Convert a number into a mbedtls_ct_condition_t.\n *\n * \\param x Number to convert.\n *\n * \\return MBEDTLS_CT_TRUE if \\p x != 0, or MBEDTLS_CT_FALSE if \\p x == 0\n *\n */\nstatic inline mbedtls_ct_condition_t mbedtls_ct_bool(mbedtls_ct_uint_t x);\n\n/** Boolean \"not equal\" operation.\n *\n * Functionally equivalent to:\n *\n * \\p x != \\p y\n *\n * \\param x     The first value to analyze.\n * \\param y     The second value to analyze.\n *\n * \\return      MBEDTLS_CT_TRUE if \\p x != \\p y, otherwise MBEDTLS_CT_FALSE.\n */\nstatic inline mbedtls_ct_condition_t mbedtls_ct_uint_ne(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y);\n\n/** Boolean \"equals\" operation.\n *\n * Functionally equivalent to:\n *\n * \\p x == \\p y\n *\n * \\param x     The first value to analyze.\n * \\param y     The second value to analyze.\n *\n * \\return      MBEDTLS_CT_TRUE if \\p x == \\p y, otherwise MBEDTLS_CT_FALSE.\n */\nstatic inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x,\n                                                        mbedtls_ct_uint_t y);\n\n/** Boolean \"less than\" operation.\n *\n * Functionally equivalent to:\n *\n * \\p x < \\p y\n *\n * \\param x     The first value to analyze.\n * \\param y     The second value to analyze.\n *\n * \\return      MBEDTLS_CT_TRUE if \\p x < \\p y, otherwise MBEDTLS_CT_FALSE.\n */\nstatic inline mbedtls_ct_condition_t mbedtls_ct_uint_lt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y);\n\n/** Boolean \"greater than\" operation.\n *\n * Functionally equivalent to:\n *\n * \\p x > \\p y\n *\n * \\param x     The first value to analyze.\n * \\param y     The second value to analyze.\n *\n * \\return      MBEDTLS_CT_TRUE if \\p x > \\p y, otherwise MBEDTLS_CT_FALSE.\n */\nstatic inline mbedtls_ct_condition_t mbedtls_ct_uint_gt(mbedtls_ct_uint_t x,\n                                                        mbedtls_ct_uint_t y);\n\n/** Boolean \"greater or equal\" operation.\n *\n * Functionally equivalent to:\n *\n * \\p x >= \\p y\n *\n * \\param x     The first value to analyze.\n * \\param y     The second value to analyze.\n *\n * \\return      MBEDTLS_CT_TRUE if \\p x >= \\p y,\n *              otherwise MBEDTLS_CT_FALSE.\n */\nstatic inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x,\n                                                        mbedtls_ct_uint_t y);\n\n/** Boolean \"less than or equal\" operation.\n *\n * Functionally equivalent to:\n *\n * \\p x <= \\p y\n *\n * \\param x     The first value to analyze.\n * \\param y     The second value to analyze.\n *\n * \\return      MBEDTLS_CT_TRUE if \\p x <= \\p y,\n *              otherwise MBEDTLS_CT_FALSE.\n */\nstatic inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x,\n                                                        mbedtls_ct_uint_t y);\n\n/** Boolean not-equals operation.\n *\n * Functionally equivalent to:\n *\n * \\p x != \\p y\n *\n * \\param x     The first value to analyze.\n * \\param y     The second value to analyze.\n *\n * \\note        This is more efficient than mbedtls_ct_uint_ne if both arguments are\n *              mbedtls_ct_condition_t.\n *\n * \\return      MBEDTLS_CT_TRUE if \\p x != \\p y,\n *              otherwise MBEDTLS_CT_FALSE.\n */\nstatic inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x,\n                                                        mbedtls_ct_condition_t y);\n\n/** Boolean \"and\" operation.\n *\n * Functionally equivalent to:\n *\n * \\p x && \\p y\n *\n * \\param x     The first value to analyze.\n * \\param y     The second value to analyze.\n *\n * \\return      MBEDTLS_CT_TRUE if \\p x && \\p y,\n *              otherwise MBEDTLS_CT_FALSE.\n */\nstatic inline mbedtls_ct_condition_t mbedtls_ct_bool_and(mbedtls_ct_condition_t x,\n                                                         mbedtls_ct_condition_t y);\n\n/** Boolean \"or\" operation.\n *\n * Functionally equivalent to:\n *\n * \\p x || \\p y\n *\n * \\param x     The first value to analyze.\n * \\param y     The second value to analyze.\n *\n * \\return      MBEDTLS_CT_TRUE if \\p x || \\p y,\n *              otherwise MBEDTLS_CT_FALSE.\n */\nstatic inline mbedtls_ct_condition_t mbedtls_ct_bool_or(mbedtls_ct_condition_t x,\n                                                        mbedtls_ct_condition_t y);\n\n/** Boolean \"not\" operation.\n *\n * Functionally equivalent to:\n *\n * ! \\p x\n *\n * \\param x     The value to invert\n *\n * \\return      MBEDTLS_CT_FALSE if \\p x, otherwise MBEDTLS_CT_TRUE.\n */\nstatic inline mbedtls_ct_condition_t mbedtls_ct_bool_not(mbedtls_ct_condition_t x);\n\n\n/* ============================================================================\n * Data selection operations\n */\n\n/** Choose between two size_t values.\n *\n * Functionally equivalent to:\n *\n * condition ? if1 : if0.\n *\n * \\param condition     Condition to test.\n * \\param if1           Value to use if \\p condition == MBEDTLS_CT_TRUE.\n * \\param if0           Value to use if \\p condition == MBEDTLS_CT_FALSE.\n *\n * \\return  \\c if1 if \\p condition == MBEDTLS_CT_TRUE, otherwise \\c if0.\n */\nstatic inline size_t mbedtls_ct_size_if(mbedtls_ct_condition_t condition,\n                                        size_t if1,\n                                        size_t if0);\n\n/** Choose between two unsigned values.\n *\n * Functionally equivalent to:\n *\n * condition ? if1 : if0.\n *\n * \\param condition     Condition to test.\n * \\param if1           Value to use if \\p condition == MBEDTLS_CT_TRUE.\n * \\param if0           Value to use if \\p condition == MBEDTLS_CT_FALSE.\n *\n * \\return  \\c if1 if \\p condition == MBEDTLS_CT_TRUE, otherwise \\c if0.\n */\nstatic inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition,\n                                          unsigned if1,\n                                          unsigned if0);\n\n/** Choose between two mbedtls_ct_condition_t values.\n *\n * Functionally equivalent to:\n *\n * condition ? if1 : if0.\n *\n * \\param condition     Condition to test.\n * \\param if1           Value to use if \\p condition == MBEDTLS_CT_TRUE.\n * \\param if0           Value to use if \\p condition == MBEDTLS_CT_FALSE.\n *\n * \\return  \\c if1 if \\p condition == MBEDTLS_CT_TRUE, otherwise \\c if0.\n */\nstatic inline mbedtls_ct_condition_t mbedtls_ct_bool_if(mbedtls_ct_condition_t condition,\n                                                        mbedtls_ct_condition_t if1,\n                                                        mbedtls_ct_condition_t if0);\n\n#if defined(MBEDTLS_BIGNUM_C)\n\n/** Choose between two mbedtls_mpi_uint values.\n *\n * Functionally equivalent to:\n *\n * condition ? if1 : if0.\n *\n * \\param condition     Condition to test.\n * \\param if1           Value to use if \\p condition == MBEDTLS_CT_TRUE.\n * \\param if0           Value to use if \\p condition == MBEDTLS_CT_FALSE.\n *\n * \\return  \\c if1 if \\p condition == MBEDTLS_CT_TRUE, otherwise \\c if0.\n */\nstatic inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition, \\\n                                                      mbedtls_mpi_uint if1, \\\n                                                      mbedtls_mpi_uint if0);\n\n#endif\n\n/** Choose between an unsigned value and 0.\n *\n * Functionally equivalent to:\n *\n * condition ? if1 : 0.\n *\n * Functionally equivalent to mbedtls_ct_uint_if(condition, if1, 0) but\n * results in smaller code size.\n *\n * \\param condition     Condition to test.\n * \\param if1           Value to use if \\p condition == MBEDTLS_CT_TRUE.\n *\n * \\return  \\c if1 if \\p condition == MBEDTLS_CT_TRUE, otherwise 0.\n */\nstatic inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1);\n\n/** Choose between an mbedtls_ct_condition_t and 0.\n *\n * Functionally equivalent to:\n *\n * condition ? if1 : 0.\n *\n * Functionally equivalent to mbedtls_ct_bool_if(condition, if1, 0) but\n * results in smaller code size.\n *\n * \\param condition     Condition to test.\n * \\param if1           Value to use if \\p condition == MBEDTLS_CT_TRUE.\n *\n * \\return  \\c if1 if \\p condition == MBEDTLS_CT_TRUE, otherwise 0.\n */\nstatic inline mbedtls_ct_condition_t mbedtls_ct_bool_if_else_0(mbedtls_ct_condition_t condition,\n                                                               mbedtls_ct_condition_t if1);\n\n/** Choose between a size_t value and 0.\n *\n * Functionally equivalent to:\n *\n * condition ? if1 : 0.\n *\n * Functionally equivalent to mbedtls_ct_size_if(condition, if1, 0) but\n * results in smaller code size.\n *\n * \\param condition     Condition to test.\n * \\param if1           Value to use if \\p condition == MBEDTLS_CT_TRUE.\n *\n * \\return  \\c if1 if \\p condition == MBEDTLS_CT_TRUE, otherwise 0.\n */\nstatic inline size_t mbedtls_ct_size_if_else_0(mbedtls_ct_condition_t condition, size_t if1);\n\n#if defined(MBEDTLS_BIGNUM_C)\n\n/** Choose between an mbedtls_mpi_uint value and 0.\n *\n * Functionally equivalent to:\n *\n * condition ? if1 : 0.\n *\n * Functionally equivalent to mbedtls_ct_mpi_uint_if(condition, if1, 0) but\n * results in smaller code size.\n *\n * \\param condition     Condition to test.\n * \\param if1           Value to use if \\p condition == MBEDTLS_CT_TRUE.\n *\n * \\return  \\c if1 if \\p condition == MBEDTLS_CT_TRUE, otherwise 0.\n */\nstatic inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition,\n                                                             mbedtls_mpi_uint if1);\n\n#endif\n\n/** Constant-flow char selection\n *\n * \\param low   Secret. Bottom of range\n * \\param high  Secret. Top of range\n * \\param c     Secret. Value to compare to range\n * \\param t     Secret. Value to return, if in range\n *\n * \\return      \\p t if \\p low <= \\p c <= \\p high, 0 otherwise.\n */\nstatic inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low,\n                                                         unsigned char high,\n                                                         unsigned char c,\n                                                         unsigned char t);\n\n/** Choose between two error values. The values must be in the range [-32767..0].\n *\n * Functionally equivalent to:\n *\n * condition ? if1 : if0.\n *\n * \\param condition     Condition to test.\n * \\param if1           Value to use if \\p condition == MBEDTLS_CT_TRUE.\n * \\param if0           Value to use if \\p condition == MBEDTLS_CT_FALSE.\n *\n * \\return  \\c if1 if \\p condition == MBEDTLS_CT_TRUE, otherwise \\c if0.\n */\nstatic inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0);\n\n/** Choose between an error value and 0. The error value must be in the range [-32767..0].\n *\n * Functionally equivalent to:\n *\n * condition ? if1 : 0.\n *\n * Functionally equivalent to mbedtls_ct_error_if(condition, if1, 0) but\n * results in smaller code size.\n *\n * \\param condition     Condition to test.\n * \\param if1           Value to use if \\p condition == MBEDTLS_CT_TRUE.\n *\n * \\return  \\c if1 if \\p condition == MBEDTLS_CT_TRUE, otherwise 0.\n */\nstatic inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1);\n\n/* ============================================================================\n * Block memory operations\n */\n\n#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)\n\n/** Conditionally set a block of memory to zero.\n *\n * Regardless of the condition, every byte will be read once and written to\n * once.\n *\n * \\param condition     Secret. Condition to test.\n * \\param buf           Secret. Pointer to the start of the buffer.\n * \\param len           Number of bytes to set to zero.\n *\n * \\warning Unlike mbedtls_platform_zeroize, this does not have the same guarantees\n * about not being optimised away if the memory is never read again.\n */\nvoid mbedtls_ct_zeroize_if(mbedtls_ct_condition_t condition, void *buf, size_t len);\n\n/** Shift some data towards the left inside a buffer.\n *\n * Functionally equivalent to:\n *\n * memmove(start, start + offset, total - offset);\n * memset(start + (total - offset), 0, offset);\n *\n * Timing independence comes at the expense of performance.\n *\n * \\param start     Secret. Pointer to the start of the buffer.\n * \\param total     Total size of the buffer.\n * \\param offset    Secret. Offset from which to copy \\p total - \\p offset bytes.\n */\nvoid mbedtls_ct_memmove_left(void *start,\n                             size_t total,\n                             size_t offset);\n\n#endif /* defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) */\n\n/** Conditional memcpy.\n *\n * Functionally equivalent to:\n *\n * if (condition) {\n *      memcpy(dest, src1, len);\n * } else {\n *      if (src2 != NULL)\n *          memcpy(dest, src2, len);\n * }\n *\n * It will always read len bytes from src1.\n * If src2 != NULL, it will always read len bytes from src2.\n * If src2 == NULL, it will instead read len bytes from dest (as if src2 == dest).\n *\n * \\param condition The condition\n * \\param dest      Secret. Destination pointer.\n * \\param src1      Secret. Pointer to copy from (if \\p condition == MBEDTLS_CT_TRUE).\n *                  This may be equal to \\p dest, but may not overlap in other ways.\n * \\param src2      Secret (contents only - may branch to determine if this parameter is NULL).\n *                  Pointer to copy from (if \\p condition == MBEDTLS_CT_FALSE and \\p src2 is not NULL). May be NULL.\n *                  This may be equal to \\p dest, but may not overlap it in other ways. It may overlap with \\p src1.\n * \\param len       Number of bytes to copy.\n */\nvoid mbedtls_ct_memcpy_if(mbedtls_ct_condition_t condition,\n                          unsigned char *dest,\n                          const unsigned char *src1,\n                          const unsigned char *src2,\n                          size_t len\n                          );\n\n/** Copy data from a secret position.\n *\n * Functionally equivalent to:\n *\n * memcpy(dst, src + offset, len)\n *\n * This function copies \\p len bytes from \\p src + \\p offset to\n * \\p dst, with a code flow and memory access pattern that does not depend on\n * \\p offset, but only on \\p offset_min, \\p offset_max and \\p len.\n *\n * \\note                This function reads from \\p dest, but the value that\n *                      is read does not influence the result and this\n *                      function's behavior is well-defined regardless of the\n *                      contents of the buffers. This may result in false\n *                      positives from static or dynamic analyzers, especially\n *                      if \\p dest is not initialized.\n *\n * \\param dest          Secret. The destination buffer. This must point to a writable\n *                      buffer of at least \\p len bytes.\n * \\param src           Secret. The base of the source buffer. This must point to a\n *                      readable buffer of at least \\p offset_max + \\p len\n *                      bytes. Shouldn't overlap with \\p dest\n * \\param offset        Secret. The offset in the source buffer from which to copy.\n *                      This must be no less than \\p offset_min and no greater\n *                      than \\p offset_max.\n * \\param offset_min    The minimal value of \\p offset.\n * \\param offset_max    The maximal value of \\p offset.\n * \\param len           The number of bytes to copy.\n */\nvoid mbedtls_ct_memcpy_offset(unsigned char *dest,\n                              const unsigned char *src,\n                              size_t offset,\n                              size_t offset_min,\n                              size_t offset_max,\n                              size_t len);\n\n/* Documented in include/mbedtls/constant_time.h. a and b are secret.\n\n   int mbedtls_ct_memcmp(const void *a,\n                         const void *b,\n                         size_t n);\n */\n\n#if defined(MBEDTLS_NIST_KW_C)\n\n/** Constant-time buffer comparison without branches.\n *\n * Similar to mbedtls_ct_memcmp, except that the result only depends on part of\n * the input data - differences in the head or tail are ignored. Functionally equivalent to:\n *\n * memcmp(a + skip_head, b + skip_head, size - skip_head - skip_tail)\n *\n * Time taken depends on \\p n, but not on \\p skip_head or \\p skip_tail .\n *\n * Behaviour is undefined if ( \\p skip_head + \\p skip_tail) > \\p n.\n *\n * \\param a         Secret. Pointer to the first buffer, containing at least \\p n bytes. May not be NULL.\n * \\param b         Secret. Pointer to the second buffer, containing at least \\p n bytes. May not be NULL.\n * \\param n         The number of bytes to examine (total size of the buffers).\n * \\param skip_head Secret. The number of bytes to treat as non-significant at the start of the buffer.\n *                  These bytes will still be read.\n * \\param skip_tail Secret. The number of bytes to treat as non-significant at the end of the buffer.\n *                  These bytes will still be read.\n *\n * \\return          Zero if the contents of the two buffers are the same, otherwise non-zero.\n */\nint mbedtls_ct_memcmp_partial(const void *a,\n                              const void *b,\n                              size_t n,\n                              size_t skip_head,\n                              size_t skip_tail);\n\n#endif\n\n/* Include the implementation of static inline functions above. */\n#include \"constant_time_impl.h\"\n\n#endif /* MBEDTLS_CONSTANT_TIME_INTERNAL_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ctr.h",
    "content": "/**\n * \\file ctr.h\n *\n * \\brief    This file contains common functionality for counter algorithms.\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_CTR_H\n#define MBEDTLS_CTR_H\n\n#include \"common.h\"\n\n/**\n * \\brief               Increment a big-endian 16-byte value.\n *                      This is quite performance-sensitive for AES-CTR and CTR-DRBG.\n *\n * \\param n             A 16-byte value to be incremented.\n */\nstatic inline void mbedtls_ctr_increment_counter(uint8_t n[16])\n{\n    // The 32-bit version seems to perform about the same as a 64-bit version\n    // on 64-bit architectures, so no need to define a 64-bit version.\n    for (int i = 3;; i--) {\n        uint32_t x = MBEDTLS_GET_UINT32_BE(n, i << 2);\n        x += 1;\n        MBEDTLS_PUT_UINT32_BE(x, n, i << 2);\n        if (x != 0 || i == 0) {\n            break;\n        }\n    }\n}\n\n#endif /* MBEDTLS_CTR_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ctr_drbg.c",
    "content": "/*\n *  CTR_DRBG implementation based on AES-256 (NIST SP 800-90)\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  The NIST SP 800-90 DRBGs are described in the following publication.\n *\n *  https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-90r.pdf\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_CTR_DRBG_C)\n\n#include \"ctr.h\"\n#include \"mbedtls/ctr_drbg.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_FS_IO)\n#include <stdio.h>\n#endif\n\n/* Using error translation functions from PSA to MbedTLS */\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n#include \"psa_util_internal.h\"\n#endif\n\n#include \"mbedtls/platform.h\"\n\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\nstatic psa_status_t ctr_drbg_setup_psa_context(mbedtls_ctr_drbg_psa_context *psa_ctx,\n                                               unsigned char *key, size_t key_len)\n{\n    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;\n    psa_status_t status;\n\n    psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT);\n    psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);\n    psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);\n    status = psa_import_key(&key_attr, key, key_len, &psa_ctx->key_id);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_cipher_encrypt_setup(&psa_ctx->operation, psa_ctx->key_id, PSA_ALG_ECB_NO_PADDING);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\nexit:\n    psa_reset_key_attributes(&key_attr);\n    return status;\n}\n\nstatic void ctr_drbg_destroy_psa_contex(mbedtls_ctr_drbg_psa_context *psa_ctx)\n{\n    psa_cipher_abort(&psa_ctx->operation);\n    psa_destroy_key(psa_ctx->key_id);\n\n    psa_ctx->operation = psa_cipher_operation_init();\n    psa_ctx->key_id = MBEDTLS_SVC_KEY_ID_INIT;\n}\n#endif\n\n/*\n * CTR_DRBG context initialization\n */\nvoid mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n    ctx->psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;\n    ctx->psa_ctx.operation = psa_cipher_operation_init();\n#else\n    mbedtls_aes_init(&ctx->aes_ctx);\n#endif\n    /* Indicate that the entropy nonce length is not set explicitly.\n     * See mbedtls_ctr_drbg_set_nonce_len(). */\n    ctx->reseed_counter = -1;\n\n    ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;\n}\n\n/*\n *  This function resets CTR_DRBG context to the state immediately\n *  after initial call of mbedtls_ctr_drbg_init().\n */\nvoid mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    /* The mutex is initialized iff f_entropy is set. */\n    if (ctx->f_entropy != NULL) {\n        mbedtls_mutex_free(&ctx->mutex);\n    }\n#endif\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n    ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);\n#else\n    mbedtls_aes_free(&ctx->aes_ctx);\n#endif\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));\n    ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;\n    ctx->reseed_counter = -1;\n}\n\nvoid mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,\n                                                int resistance)\n{\n    ctx->prediction_resistance = resistance;\n}\n\nvoid mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx,\n                                      size_t len)\n{\n    ctx->entropy_len = len;\n}\n\nint mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx,\n                                   size_t len)\n{\n    /* If mbedtls_ctr_drbg_seed() has already been called, it's\n     * too late. Return the error code that's closest to making sense. */\n    if (ctx->f_entropy != NULL) {\n        return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;\n    }\n\n    if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {\n        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;\n    }\n\n    /* This shouldn't be an issue because\n     * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible\n     * configuration, but make sure anyway. */\n    if (len > INT_MAX) {\n        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;\n    }\n\n    /* For backward compatibility with Mbed TLS <= 2.19, store the\n     * entropy nonce length in a field that already exists, but isn't\n     * used until after the initial seeding. */\n    /* Due to the capping of len above, the value fits in an int. */\n    ctx->reseed_counter = (int) len;\n    return 0;\n}\n\nvoid mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx,\n                                          int interval)\n{\n    ctx->reseed_interval = interval;\n}\n\nstatic int block_cipher_df(unsigned char *output,\n                           const unsigned char *data, size_t data_len)\n{\n    unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +\n                      MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];\n    unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];\n    unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];\n    unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];\n    unsigned char *p, *iv;\n    int ret = 0;\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n    psa_status_t status;\n    size_t tmp_len;\n    mbedtls_ctr_drbg_psa_context psa_ctx;\n\n    psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;\n    psa_ctx.operation = psa_cipher_operation_init();\n#else\n    mbedtls_aes_context aes_ctx;\n#endif\n\n    int i, j;\n    size_t buf_len, use_len;\n\n    if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {\n        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;\n    }\n\n    memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +\n           MBEDTLS_CTR_DRBG_BLOCKSIZE + 16);\n\n    /*\n     * Construct IV (16 bytes) and S in buffer\n     * IV = Counter (in 32-bits) padded to 16 with zeroes\n     * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||\n     *     data || 0x80\n     *     (Total is padded to a multiple of 16-bytes with zeroes)\n     */\n    p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;\n    MBEDTLS_PUT_UINT32_BE(data_len, p, 0);\n    p += 4 + 3;\n    *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;\n    memcpy(p, data, data_len);\n    p[data_len] = 0x80;\n\n    buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;\n\n    for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) {\n        key[i] = i;\n    }\n\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n    status = ctr_drbg_setup_psa_context(&psa_ctx, key, sizeof(key));\n    if (status != PSA_SUCCESS) {\n        ret = psa_generic_status_to_mbedtls(status);\n        goto exit;\n    }\n#else\n    mbedtls_aes_init(&aes_ctx);\n\n    if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,\n                                      MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {\n        goto exit;\n    }\n#endif\n\n    /*\n     * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data\n     */\n    for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {\n        p = buf;\n        memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE);\n        use_len = buf_len;\n\n        while (use_len > 0) {\n            mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE);\n            p += MBEDTLS_CTR_DRBG_BLOCKSIZE;\n            use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?\n                       MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;\n\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n            status = psa_cipher_update(&psa_ctx.operation, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE,\n                                       chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);\n            if (status != PSA_SUCCESS) {\n                ret = psa_generic_status_to_mbedtls(status);\n                goto exit;\n            }\n#else\n            if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,\n                                             chain, chain)) != 0) {\n                goto exit;\n            }\n#endif\n        }\n\n        memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);\n\n        /*\n         * Update IV\n         */\n        buf[3]++;\n    }\n\n    /*\n     * Do final encryption with reduced data\n     */\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n    ctr_drbg_destroy_psa_contex(&psa_ctx);\n\n    status = ctr_drbg_setup_psa_context(&psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);\n    if (status != PSA_SUCCESS) {\n        ret = psa_generic_status_to_mbedtls(status);\n        goto exit;\n    }\n#else\n    if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,\n                                      MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {\n        goto exit;\n    }\n#endif\n    iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;\n    p = output;\n\n    for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n        status = psa_cipher_update(&psa_ctx.operation, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE,\n                                   iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);\n        if (status != PSA_SUCCESS) {\n            ret = psa_generic_status_to_mbedtls(status);\n            goto exit;\n        }\n#else\n        if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,\n                                         iv, iv)) != 0) {\n            goto exit;\n        }\n#endif\n        memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);\n        p += MBEDTLS_CTR_DRBG_BLOCKSIZE;\n    }\nexit:\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n    ctr_drbg_destroy_psa_contex(&psa_ctx);\n#else\n    mbedtls_aes_free(&aes_ctx);\n#endif\n    /*\n     * tidy up the stack\n     */\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n    mbedtls_platform_zeroize(tmp, sizeof(tmp));\n    mbedtls_platform_zeroize(key, sizeof(key));\n    mbedtls_platform_zeroize(chain, sizeof(chain));\n    if (0 != ret) {\n        /*\n         * wipe partial seed from memory\n         */\n        mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN);\n    }\n\n    return ret;\n}\n\n/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)\n * ctr_drbg_update_internal(ctx, provided_data)\n * implements\n * CTR_DRBG_Update(provided_data, Key, V)\n * with inputs and outputs\n *   ctx->aes_ctx = Key\n *   ctx->counter = V\n */\nstatic int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,\n                                    const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])\n{\n    unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];\n    unsigned char *p = tmp;\n    int j;\n    int ret = 0;\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n    psa_status_t status;\n    size_t tmp_len;\n#endif\n\n    memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);\n\n    for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {\n        /*\n         * Increase counter\n         */\n        mbedtls_ctr_increment_counter(ctx->counter);\n\n        /*\n         * Crypt counter block\n         */\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n        status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),\n                                   p, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);\n        if (status != PSA_SUCCESS) {\n            ret = psa_generic_status_to_mbedtls(status);\n            goto exit;\n        }\n#else\n        if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,\n                                         ctx->counter, p)) != 0) {\n            goto exit;\n        }\n#endif\n\n        p += MBEDTLS_CTR_DRBG_BLOCKSIZE;\n    }\n\n    mbedtls_xor(tmp, tmp, data, MBEDTLS_CTR_DRBG_SEEDLEN);\n\n    /*\n     * Update key and counter\n     */\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n    ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);\n\n    status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);\n    if (status != PSA_SUCCESS) {\n        ret = psa_generic_status_to_mbedtls(status);\n        goto exit;\n    }\n#else\n    if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,\n                                      MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {\n        goto exit;\n    }\n#endif\n    memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,\n           MBEDTLS_CTR_DRBG_BLOCKSIZE);\n\nexit:\n    mbedtls_platform_zeroize(tmp, sizeof(tmp));\n    return ret;\n}\n\n/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)\n * mbedtls_ctr_drbg_update(ctx, additional, add_len)\n * implements\n * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,\n *                      security_strength) -> initial_working_state\n * with inputs\n *   ctx->counter = all-bits-0\n *   ctx->aes_ctx = context from all-bits-0 key\n *   additional[:add_len] = entropy_input || nonce || personalization_string\n * and with outputs\n *   ctx = initial_working_state\n */\nint mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,\n                            const unsigned char *additional,\n                            size_t add_len)\n{\n    unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (add_len == 0) {\n        return 0;\n    }\n\n    if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {\n        goto exit;\n    }\n    if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {\n        goto exit;\n    }\n\nexit:\n    mbedtls_platform_zeroize(add_input, sizeof(add_input));\n    return ret;\n}\n\n/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)\n * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)\n * implements\n * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)\n *                -> new_working_state\n * with inputs\n *   ctx contains working_state\n *   additional[:len] = additional_input\n * and entropy_input comes from calling ctx->f_entropy\n *                              for (ctx->entropy_len + nonce_len) bytes\n * and with output\n *   ctx contains new_working_state\n */\nstatic int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx,\n                                            const unsigned char *additional,\n                                            size_t len,\n                                            size_t nonce_len)\n{\n    unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];\n    size_t seedlen = 0;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {\n        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;\n    }\n    if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) {\n        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;\n    }\n    if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) {\n        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;\n    }\n\n    memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);\n\n    /* Gather entropy_len bytes of entropy to seed state. */\n    if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {\n        return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;\n    }\n    seedlen += ctx->entropy_len;\n\n    /* Gather entropy for a nonce if requested. */\n    if (nonce_len != 0) {\n        if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) {\n            return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;\n        }\n        seedlen += nonce_len;\n    }\n\n    /* Add additional data if provided. */\n    if (additional != NULL && len != 0) {\n        memcpy(seed + seedlen, additional, len);\n        seedlen += len;\n    }\n\n    /* Reduce to 384 bits. */\n    if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) {\n        goto exit;\n    }\n\n    /* Update state. */\n    if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) {\n        goto exit;\n    }\n    ctx->reseed_counter = 1;\n\nexit:\n    mbedtls_platform_zeroize(seed, sizeof(seed));\n    return ret;\n}\n\nint mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,\n                            const unsigned char *additional, size_t len)\n{\n    return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);\n}\n\n/* Return a \"good\" nonce length for CTR_DRBG. The chosen nonce length\n * is sufficient to achieve the maximum security strength given the key\n * size and entropy length. If there is enough entropy in the initial\n * call to the entropy function to serve as both the entropy input and\n * the nonce, don't make a second call to get a nonce. */\nstatic size_t good_nonce_len(size_t entropy_len)\n{\n    if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) {\n        return 0;\n    } else {\n        return (entropy_len + 1) / 2;\n    }\n}\n\n/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)\n * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)\n * implements\n * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,\n *                      security_strength) -> initial_working_state\n * with inputs\n *   custom[:len] = nonce || personalization_string\n * where entropy_input comes from f_entropy for ctx->entropy_len bytes\n * and with outputs\n *   ctx = initial_working_state\n */\nint mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,\n                          int (*f_entropy)(void *, unsigned char *, size_t),\n                          void *p_entropy,\n                          const unsigned char *custom,\n                          size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];\n    size_t nonce_len;\n\n    memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);\n\n    /* The mutex is initialized iff f_entropy is set. */\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_init(&ctx->mutex);\n#endif\n\n    ctx->f_entropy = f_entropy;\n    ctx->p_entropy = p_entropy;\n\n    if (ctx->entropy_len == 0) {\n        ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;\n    }\n    /* ctx->reseed_counter contains the desired amount of entropy to\n     * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).\n     * If it's -1, indicating that the entropy nonce length was not set\n     * explicitly, use a sufficiently large nonce for security. */\n    nonce_len = (ctx->reseed_counter >= 0 ?\n                 (size_t) ctx->reseed_counter :\n                 good_nonce_len(ctx->entropy_len));\n\n    /* Initialize with an empty key. */\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n    psa_status_t status;\n\n    status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, key, MBEDTLS_CTR_DRBG_KEYSIZE);\n    if (status != PSA_SUCCESS) {\n        ret = psa_generic_status_to_mbedtls(status);\n        return status;\n    }\n#else\n    if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,\n                                      MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {\n        return ret;\n    }\n#endif\n\n    /* Do the initial seeding. */\n    if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,\n                                                nonce_len)) != 0) {\n        return ret;\n    }\n    return 0;\n}\n\n/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)\n * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)\n * implements\n * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])\n *                -> working_state_after_reseed\n *                if required, then\n * CTR_DRBG_Generate(working_state_after_reseed,\n *                   requested_number_of_bits, additional_input)\n *                -> status, returned_bits, new_working_state\n * with inputs\n *   ctx contains working_state\n *   requested_number_of_bits = 8 * output_len\n *   additional[:add_len] = additional_input\n * and entropy_input comes from calling ctx->f_entropy\n * and with outputs\n *   status = SUCCESS (this function does the reseed internally)\n *   returned_bits = output[:output_len]\n *   ctx contains new_working_state\n */\nint mbedtls_ctr_drbg_random_with_add(void *p_rng,\n                                     unsigned char *output, size_t output_len,\n                                     const unsigned char *additional, size_t add_len)\n{\n    int ret = 0;\n    mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;\n    unsigned char *p = output;\n    struct {\n        unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];\n        unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];\n    } locals;\n    size_t use_len;\n\n    if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {\n        return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;\n    }\n\n    if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) {\n        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;\n    }\n\n    memset(locals.add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);\n\n    if (ctx->reseed_counter > ctx->reseed_interval ||\n        ctx->prediction_resistance) {\n        if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) {\n            return ret;\n        }\n        add_len = 0;\n    }\n\n    if (add_len > 0) {\n        if ((ret = block_cipher_df(locals.add_input, additional, add_len)) != 0) {\n            goto exit;\n        }\n        if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) {\n            goto exit;\n        }\n    }\n\n    while (output_len > 0) {\n        /*\n         * Increase counter (treat it as a 128-bit big-endian integer).\n         */\n        mbedtls_ctr_increment_counter(ctx->counter);\n\n        /*\n         * Crypt counter block\n         */\n#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)\n        psa_status_t status;\n        size_t tmp_len;\n\n        status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),\n                                   locals.tmp, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);\n        if (status != PSA_SUCCESS) {\n            ret = psa_generic_status_to_mbedtls(status);\n            goto exit;\n        }\n#else\n        if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,\n                                         ctx->counter, locals.tmp)) != 0) {\n            goto exit;\n        }\n#endif\n\n        use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)\n            ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;\n        /*\n         * Copy random block to destination\n         */\n        memcpy(p, locals.tmp, use_len);\n        p += use_len;\n        output_len -= use_len;\n    }\n\n    if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) {\n        goto exit;\n    }\n\n    ctx->reseed_counter++;\n\nexit:\n    mbedtls_platform_zeroize(&locals, sizeof(locals));\n    return ret;\n}\n\nint mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output,\n                            size_t output_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;\n\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {\n        return ret;\n    }\n#endif\n\n    ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);\n\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {\n        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n#endif\n\n    return ret;\n}\n\n#if defined(MBEDTLS_FS_IO)\nint mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,\n                                     const char *path)\n{\n    int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;\n    FILE *f;\n    unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];\n\n    if ((f = fopen(path, \"wb\")) == NULL) {\n        return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;\n    }\n\n    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */\n    mbedtls_setbuf(f, NULL);\n\n    if ((ret = mbedtls_ctr_drbg_random(ctx, buf,\n                                       MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) {\n        goto exit;\n    }\n\n    if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) !=\n        MBEDTLS_CTR_DRBG_MAX_INPUT) {\n        ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;\n    } else {\n        ret = 0;\n    }\n\nexit:\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n\n    fclose(f);\n    return ret;\n}\n\nint mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,\n                                      const char *path)\n{\n    int ret = 0;\n    FILE *f = NULL;\n    size_t n;\n    unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];\n    unsigned char c;\n\n    if ((f = fopen(path, \"rb\")) == NULL) {\n        return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;\n    }\n\n    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */\n    mbedtls_setbuf(f, NULL);\n\n    n = fread(buf, 1, sizeof(buf), f);\n    if (fread(&c, 1, 1, f) != 0) {\n        ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;\n        goto exit;\n    }\n    if (n == 0 || ferror(f)) {\n        ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;\n        goto exit;\n    }\n    fclose(f);\n    f = NULL;\n\n    ret = mbedtls_ctr_drbg_update(ctx, buf, n);\n\nexit:\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n    if (f != NULL) {\n        fclose(f);\n    }\n    if (ret != 0) {\n        return ret;\n    }\n    return mbedtls_ctr_drbg_write_seed_file(ctx, path);\n}\n#endif /* MBEDTLS_FS_IO */\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/* The CTR_DRBG NIST test vectors used here are available at\n * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip\n *\n * The parameters used to derive the test data are:\n *\n * [AES-128 use df]\n * [PredictionResistance = True/False]\n * [EntropyInputLen = 128]\n * [NonceLen = 64]\n * [PersonalizationStringLen = 128]\n * [AdditionalInputLen = 0]\n * [ReturnedBitsLen = 512]\n *\n * [AES-256 use df]\n * [PredictionResistance = True/False]\n * [EntropyInputLen = 256]\n * [NonceLen = 128]\n * [PersonalizationStringLen = 256]\n * [AdditionalInputLen = 0]\n * [ReturnedBitsLen = 512]\n *\n */\n\n#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)\nstatic const unsigned char entropy_source_pr[] =\n{ 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,\n  0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,\n  0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,\n  0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,\n  0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,\n  0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,\n  0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };\n\nstatic const unsigned char entropy_source_nopr[] =\n{ 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,\n  0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,\n  0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,\n  0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,\n  0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };\n\nstatic const unsigned char pers_pr[] =\n{ 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,\n  0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };\n\nstatic const unsigned char pers_nopr[] =\n{ 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,\n  0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };\n\nstatic const unsigned char result_pr[] =\n{ 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,\n  0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,\n  0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,\n  0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,\n  0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,\n  0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,\n  0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,\n  0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };\n\nstatic const unsigned char result_nopr[] =\n{ 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,\n  0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,\n  0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,\n  0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,\n  0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,\n  0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,\n  0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,\n  0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };\n#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */\n\nstatic const unsigned char entropy_source_pr[] =\n{ 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,\n  0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,\n  0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,\n  0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,\n  0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,\n  0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,\n  0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,\n  0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,\n  0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,\n  0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,\n  0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,\n  0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,\n  0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,\n  0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };\n\nstatic const unsigned char entropy_source_nopr[] =\n{ 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,\n  0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,\n  0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,\n  0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,\n  0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,\n  0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,\n  0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,\n  0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,\n  0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,\n  0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };\n\nstatic const unsigned char pers_pr[] =\n{ 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,\n  0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,\n  0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,\n  0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };\n\nstatic const unsigned char pers_nopr[] =\n{ 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,\n  0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,\n  0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,\n  0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };\n\nstatic const unsigned char result_pr[] =\n{ 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,\n  0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,\n  0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,\n  0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,\n  0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,\n  0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,\n  0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,\n  0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };\n\nstatic const unsigned char result_nopr[] =\n{ 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,\n  0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,\n  0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,\n  0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,\n  0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,\n  0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,\n  0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,\n  0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };\n#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */\n\nstatic size_t test_offset;\nstatic int ctr_drbg_self_test_entropy(void *data, unsigned char *buf,\n                                      size_t len)\n{\n    const unsigned char *p = data;\n    memcpy(buf, p + test_offset, len);\n    test_offset += len;\n    return 0;\n}\n\n#define CHK(c)    if ((c) != 0)                          \\\n    {                                       \\\n        if (verbose != 0)                  \\\n        mbedtls_printf(\"failed\\n\");  \\\n        return 1;                        \\\n    }\n\n#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64\n\n/*\n * Checkup routine\n */\nint mbedtls_ctr_drbg_self_test(int verbose)\n{\n    mbedtls_ctr_drbg_context ctx;\n    unsigned char buf[sizeof(result_pr)];\n\n    mbedtls_ctr_drbg_init(&ctx);\n\n    /*\n     * Based on a NIST CTR_DRBG test vector (PR = True)\n     */\n    if (verbose != 0) {\n        mbedtls_printf(\"  CTR_DRBG (PR = TRUE) : \");\n    }\n\n    test_offset = 0;\n    mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);\n    mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);\n    CHK(mbedtls_ctr_drbg_seed(&ctx,\n                              ctr_drbg_self_test_entropy,\n                              (void *) entropy_source_pr,\n                              pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE));\n    mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);\n    CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));\n    CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr)));\n    CHK(memcmp(buf, result_pr, sizeof(result_pr)));\n\n    mbedtls_ctr_drbg_free(&ctx);\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\n    /*\n     * Based on a NIST CTR_DRBG test vector (PR = FALSE)\n     */\n    if (verbose != 0) {\n        mbedtls_printf(\"  CTR_DRBG (PR = FALSE): \");\n    }\n\n    mbedtls_ctr_drbg_init(&ctx);\n\n    test_offset = 0;\n    mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);\n    mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);\n    CHK(mbedtls_ctr_drbg_seed(&ctx,\n                              ctr_drbg_self_test_entropy,\n                              (void *) entropy_source_nopr,\n                              pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE));\n    CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0));\n    CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));\n    CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr)));\n    CHK(memcmp(buf, result_nopr, sizeof(result_nopr)));\n\n    mbedtls_ctr_drbg_free(&ctx);\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_CTR_DRBG_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/debug.c",
    "content": "/*\n *  Debugging routines\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_DEBUG_C)\n\n#include \"mbedtls/platform.h\"\n\n#include \"debug_internal.h\"\n#include \"mbedtls/error.h\"\n\n#include <stdarg.h>\n#include <stdio.h>\n#include <string.h>\n\n/* DEBUG_BUF_SIZE must be at least 2 */\n#define DEBUG_BUF_SIZE      512\n\nstatic int debug_threshold = 0;\n\nvoid mbedtls_debug_set_threshold(int threshold)\n{\n    debug_threshold = threshold;\n}\n\n/*\n * All calls to f_dbg must be made via this function\n */\nstatic inline void debug_send_line(const mbedtls_ssl_context *ssl, int level,\n                                   const char *file, int line,\n                                   const char *str)\n{\n    /*\n     * If in a threaded environment, we need a thread identifier.\n     * Since there is no portable way to get one, use the address of the ssl\n     * context instead, as it shouldn't be shared between threads.\n     */\n#if defined(MBEDTLS_THREADING_C)\n    char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */\n    mbedtls_snprintf(idstr, sizeof(idstr), \"%p: %s\", (void *) ssl, str);\n    ssl->conf->f_dbg(ssl->conf->p_dbg, level, file, line, idstr);\n#else\n    ssl->conf->f_dbg(ssl->conf->p_dbg, level, file, line, str);\n#endif\n}\n\nMBEDTLS_PRINTF_ATTRIBUTE(5, 6)\nvoid mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level,\n                             const char *file, int line,\n                             const char *format, ...)\n{\n    va_list argp;\n    char str[DEBUG_BUF_SIZE];\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_STATIC_ASSERT(DEBUG_BUF_SIZE >= 2, \"DEBUG_BUF_SIZE too small\");\n\n    if (NULL == ssl              ||\n        NULL == ssl->conf        ||\n        NULL == ssl->conf->f_dbg ||\n        level > debug_threshold) {\n        return;\n    }\n\n    va_start(argp, format);\n    ret = mbedtls_vsnprintf(str, DEBUG_BUF_SIZE, format, argp);\n    va_end(argp);\n\n    if (ret < 0) {\n        ret = 0;\n    } else {\n        if (ret >= DEBUG_BUF_SIZE - 1) {\n            ret = DEBUG_BUF_SIZE - 2;\n        }\n    }\n    str[ret]     = '\\n';\n    str[ret + 1] = '\\0';\n\n    debug_send_line(ssl, level, file, line, str);\n}\n\nvoid mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level,\n                             const char *file, int line,\n                             const char *text, int ret)\n{\n    char str[DEBUG_BUF_SIZE];\n\n    if (NULL == ssl              ||\n        NULL == ssl->conf        ||\n        NULL == ssl->conf->f_dbg ||\n        level > debug_threshold) {\n        return;\n    }\n\n    /*\n     * With non-blocking I/O and examples that just retry immediately,\n     * the logs would be quickly flooded with WANT_READ, so ignore that.\n     * Don't ignore WANT_WRITE however, since it is usually rare.\n     */\n    if (ret == MBEDTLS_ERR_SSL_WANT_READ) {\n        return;\n    }\n\n    mbedtls_snprintf(str, sizeof(str), \"%s() returned %d (-0x%04x)\\n\",\n                     text, ret, (unsigned int) -ret);\n\n    debug_send_line(ssl, level, file, line, str);\n}\n\nvoid mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level,\n                             const char *file, int line, const char *text,\n                             const unsigned char *buf, size_t len)\n{\n    char str[DEBUG_BUF_SIZE];\n    char txt[17];\n    size_t i, idx = 0;\n\n    if (NULL == ssl              ||\n        NULL == ssl->conf        ||\n        NULL == ssl->conf->f_dbg ||\n        level > debug_threshold) {\n        return;\n    }\n\n    mbedtls_snprintf(str + idx, sizeof(str) - idx, \"dumping '%s' (%u bytes)\\n\",\n                     text, (unsigned int) len);\n\n    debug_send_line(ssl, level, file, line, str);\n\n    memset(txt, 0, sizeof(txt));\n    for (i = 0; i < len; i++) {\n        if (i >= 4096) {\n            break;\n        }\n\n        if (i % 16 == 0) {\n            if (i > 0) {\n                mbedtls_snprintf(str + idx, sizeof(str) - idx, \"  %s\\n\", txt);\n                debug_send_line(ssl, level, file, line, str);\n\n                idx = 0;\n                memset(txt, 0, sizeof(txt));\n            }\n\n            idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, \"%04x: \",\n                                    (unsigned int) i);\n\n        }\n\n        idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, \" %02x\",\n                                (unsigned int) buf[i]);\n        txt[i % 16] = (buf[i] > 31 && buf[i] < 127) ? buf[i] : '.';\n    }\n\n    if (len > 0) {\n        for (/* i = i */; i % 16 != 0; i++) {\n            idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, \"   \");\n        }\n\n        mbedtls_snprintf(str + idx, sizeof(str) - idx, \"  %s\\n\", txt);\n        debug_send_line(ssl, level, file, line, str);\n    }\n}\n\n#if defined(MBEDTLS_ECP_LIGHT)\nvoid mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level,\n                             const char *file, int line,\n                             const char *text, const mbedtls_ecp_point *X)\n{\n    char str[DEBUG_BUF_SIZE];\n\n    if (NULL == ssl              ||\n        NULL == ssl->conf        ||\n        NULL == ssl->conf->f_dbg ||\n        level > debug_threshold) {\n        return;\n    }\n\n    mbedtls_snprintf(str, sizeof(str), \"%s(X)\", text);\n    mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->X);\n\n    mbedtls_snprintf(str, sizeof(str), \"%s(Y)\", text);\n    mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->Y);\n}\n#endif /* MBEDTLS_ECP_LIGHT */\n\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\nstatic void mbedtls_debug_print_ec_coord(const mbedtls_ssl_context *ssl, int level,\n                                         const char *file, int line, const char *text,\n                                         const unsigned char *buf, size_t len)\n{\n    char str[DEBUG_BUF_SIZE];\n    size_t i, idx = 0;\n\n    mbedtls_snprintf(str + idx, sizeof(str) - idx, \"value of '%s' (%u bits) is:\\n\",\n                     text, (unsigned int) len * 8);\n\n    debug_send_line(ssl, level, file, line, str);\n\n    for (i = 0; i < len; i++) {\n        if (i >= 4096) {\n            break;\n        }\n\n        if (i % 16 == 0) {\n            if (i > 0) {\n                mbedtls_snprintf(str + idx, sizeof(str) - idx, \"\\n\");\n                debug_send_line(ssl, level, file, line, str);\n\n                idx = 0;\n            }\n        }\n\n        idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, \" %02x\",\n                                (unsigned int) buf[i]);\n    }\n\n    if (len > 0) {\n        for (/* i = i */; i % 16 != 0; i++) {\n            idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, \"   \");\n        }\n\n        mbedtls_snprintf(str + idx, sizeof(str) - idx, \"\\n\");\n        debug_send_line(ssl, level, file, line, str);\n    }\n}\n\nvoid mbedtls_debug_print_psa_ec(const mbedtls_ssl_context *ssl, int level,\n                                const char *file, int line,\n                                const char *text, const mbedtls_pk_context *pk)\n{\n    char str[DEBUG_BUF_SIZE];\n    const uint8_t *coord_start;\n    size_t coord_len;\n\n    if (NULL == ssl              ||\n        NULL == ssl->conf        ||\n        NULL == ssl->conf->f_dbg ||\n        level > debug_threshold) {\n        return;\n    }\n\n    /* For the description of pk->pk_raw content please refer to the description\n     * psa_export_public_key() function. */\n    coord_len = (pk->pub_raw_len - 1)/2;\n\n    /* X coordinate */\n    coord_start = pk->pub_raw + 1;\n    mbedtls_snprintf(str, sizeof(str), \"%s(X)\", text);\n    mbedtls_debug_print_ec_coord(ssl, level, file, line, str, coord_start, coord_len);\n\n    /* Y coordinate */\n    coord_start = coord_start + coord_len;\n    mbedtls_snprintf(str, sizeof(str), \"%s(Y)\", text);\n    mbedtls_debug_print_ec_coord(ssl, level, file, line, str, coord_start, coord_len);\n}\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n\n#if defined(MBEDTLS_BIGNUM_C)\nvoid mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level,\n                             const char *file, int line,\n                             const char *text, const mbedtls_mpi *X)\n{\n    char str[DEBUG_BUF_SIZE];\n    size_t bitlen;\n    size_t idx = 0;\n\n    if (NULL == ssl              ||\n        NULL == ssl->conf        ||\n        NULL == ssl->conf->f_dbg ||\n        NULL == X                ||\n        level > debug_threshold) {\n        return;\n    }\n\n    bitlen = mbedtls_mpi_bitlen(X);\n\n    mbedtls_snprintf(str, sizeof(str), \"value of '%s' (%u bits) is:\\n\",\n                     text, (unsigned) bitlen);\n    debug_send_line(ssl, level, file, line, str);\n\n    if (bitlen == 0) {\n        str[0] = ' '; str[1] = '0'; str[2] = '0';\n        idx = 3;\n    } else {\n        int n;\n        for (n = (int) ((bitlen - 1) / 8); n >= 0; n--) {\n            size_t limb_offset = n / sizeof(mbedtls_mpi_uint);\n            size_t offset_in_limb = n % sizeof(mbedtls_mpi_uint);\n            unsigned char octet =\n                (X->p[limb_offset] >> (offset_in_limb * 8)) & 0xff;\n            mbedtls_snprintf(str + idx, sizeof(str) - idx, \" %02x\", octet);\n            idx += 3;\n            /* Wrap lines after 16 octets that each take 3 columns */\n            if (idx >= 3 * 16) {\n                mbedtls_snprintf(str + idx, sizeof(str) - idx, \"\\n\");\n                debug_send_line(ssl, level, file, line, str);\n                idx = 0;\n            }\n        }\n    }\n\n    if (idx != 0) {\n        mbedtls_snprintf(str + idx, sizeof(str) - idx, \"\\n\");\n        debug_send_line(ssl, level, file, line, str);\n    }\n}\n#endif /* MBEDTLS_BIGNUM_C */\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO)\nstatic void debug_print_pk(const mbedtls_ssl_context *ssl, int level,\n                           const char *file, int line,\n                           const char *text, const mbedtls_pk_context *pk)\n{\n    size_t i;\n    mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS];\n    char name[16];\n\n    memset(items, 0, sizeof(items));\n\n    if (mbedtls_pk_debug(pk, items) != 0) {\n        debug_send_line(ssl, level, file, line,\n                        \"invalid PK context\\n\");\n        return;\n    }\n\n    for (i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++) {\n        if (items[i].type == MBEDTLS_PK_DEBUG_NONE) {\n            return;\n        }\n\n        mbedtls_snprintf(name, sizeof(name), \"%s%s\", text, items[i].name);\n        name[sizeof(name) - 1] = '\\0';\n\n#if defined(MBEDTLS_RSA_C)\n        if (items[i].type == MBEDTLS_PK_DEBUG_MPI) {\n            mbedtls_debug_print_mpi(ssl, level, file, line, name, items[i].value);\n        } else\n#endif /* MBEDTLS_RSA_C */\n#if defined(MBEDTLS_ECP_LIGHT)\n        if (items[i].type == MBEDTLS_PK_DEBUG_ECP) {\n            mbedtls_debug_print_ecp(ssl, level, file, line, name, items[i].value);\n        } else\n#endif /* MBEDTLS_ECP_LIGHT */\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n        if (items[i].type == MBEDTLS_PK_DEBUG_PSA_EC) {\n            mbedtls_debug_print_psa_ec(ssl, level, file, line, name, items[i].value);\n        } else\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n        { debug_send_line(ssl, level, file, line,\n                          \"should not happen\\n\"); }\n    }\n}\n\nstatic void debug_print_line_by_line(const mbedtls_ssl_context *ssl, int level,\n                                     const char *file, int line, const char *text)\n{\n    char str[DEBUG_BUF_SIZE];\n    const char *start, *cur;\n\n    start = text;\n    for (cur = text; *cur != '\\0'; cur++) {\n        if (*cur == '\\n') {\n            size_t len = (size_t) (cur - start) + 1;\n            if (len > DEBUG_BUF_SIZE - 1) {\n                len = DEBUG_BUF_SIZE - 1;\n            }\n\n            memcpy(str, start, len);\n            str[len] = '\\0';\n\n            debug_send_line(ssl, level, file, line, str);\n\n            start = cur + 1;\n        }\n    }\n}\n\nvoid mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level,\n                             const char *file, int line,\n                             const char *text, const mbedtls_x509_crt *crt)\n{\n    char str[DEBUG_BUF_SIZE];\n    int i = 0;\n\n    if (NULL == ssl              ||\n        NULL == ssl->conf        ||\n        NULL == ssl->conf->f_dbg ||\n        NULL == crt              ||\n        level > debug_threshold) {\n        return;\n    }\n\n    while (crt != NULL) {\n        char buf[1024];\n\n        mbedtls_snprintf(str, sizeof(str), \"%s #%d:\\n\", text, ++i);\n        debug_send_line(ssl, level, file, line, str);\n\n        mbedtls_x509_crt_info(buf, sizeof(buf) - 1, \"\", crt);\n        debug_print_line_by_line(ssl, level, file, line, buf);\n\n        debug_print_pk(ssl, level, file, line, \"crt->\", &crt->pk);\n\n        crt = crt->next;\n    }\n}\n#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_X509_REMOVE_INFO */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) && \\\n    defined(MBEDTLS_ECDH_C)\nstatic void mbedtls_debug_printf_ecdh_internal(const mbedtls_ssl_context *ssl,\n                                               int level, const char *file,\n                                               int line,\n                                               const mbedtls_ecdh_context *ecdh,\n                                               mbedtls_debug_ecdh_attr attr)\n{\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n    const mbedtls_ecdh_context *ctx = ecdh;\n#else\n    const mbedtls_ecdh_context_mbed *ctx = &ecdh->ctx.mbed_ecdh;\n#endif\n\n    switch (attr) {\n        case MBEDTLS_DEBUG_ECDH_Q:\n            mbedtls_debug_print_ecp(ssl, level, file, line, \"ECDH: Q\",\n                                    &ctx->Q);\n            break;\n        case MBEDTLS_DEBUG_ECDH_QP:\n            mbedtls_debug_print_ecp(ssl, level, file, line, \"ECDH: Qp\",\n                                    &ctx->Qp);\n            break;\n        case MBEDTLS_DEBUG_ECDH_Z:\n            mbedtls_debug_print_mpi(ssl, level, file, line, \"ECDH: z\",\n                                    &ctx->z);\n            break;\n        default:\n            break;\n    }\n}\n\nvoid mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level,\n                               const char *file, int line,\n                               const mbedtls_ecdh_context *ecdh,\n                               mbedtls_debug_ecdh_attr attr)\n{\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n    mbedtls_debug_printf_ecdh_internal(ssl, level, file, line, ecdh, attr);\n#else\n    switch (ecdh->var) {\n        default:\n            mbedtls_debug_printf_ecdh_internal(ssl, level, file, line, ecdh,\n                                               attr);\n    }\n#endif\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED &&\n          MBEDTLS_ECDH_C */\n\n#endif /* MBEDTLS_DEBUG_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/debug_internal.h",
    "content": "/**\n * \\file debug_internal.h\n *\n * \\brief Internal part of the public \"debug.h\".\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_DEBUG_INTERNAL_H\n#define MBEDTLS_DEBUG_INTERNAL_H\n\n#include \"mbedtls/debug.h\"\n\n/**\n * \\brief    Print a message to the debug output. This function is always used\n *          through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl\n *          context, file and line number parameters.\n *\n * \\param ssl       SSL context\n * \\param level     error level of the debug message\n * \\param file      file the message has occurred in\n * \\param line      line number the message has occurred at\n * \\param format    format specifier, in printf format\n * \\param ...       variables used by the format specifier\n *\n * \\attention       This function is intended for INTERNAL usage within the\n *                  library only.\n */\nvoid mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level,\n                             const char *file, int line,\n                             const char *format, ...) MBEDTLS_PRINTF_ATTRIBUTE(5, 6);\n\n/**\n * \\brief   Print the return value of a function to the debug output. This\n *          function is always used through the MBEDTLS_SSL_DEBUG_RET() macro,\n *          which supplies the ssl context, file and line number parameters.\n *\n * \\param ssl       SSL context\n * \\param level     error level of the debug message\n * \\param file      file the error has occurred in\n * \\param line      line number the error has occurred in\n * \\param text      the name of the function that returned the error\n * \\param ret       the return code value\n *\n * \\attention       This function is intended for INTERNAL usage within the\n *                  library only.\n */\nvoid mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level,\n                             const char *file, int line,\n                             const char *text, int ret);\n\n/**\n * \\brief   Output a buffer of size len bytes to the debug output. This function\n *          is always used through the MBEDTLS_SSL_DEBUG_BUF() macro,\n *          which supplies the ssl context, file and line number parameters.\n *\n * \\param ssl       SSL context\n * \\param level     error level of the debug message\n * \\param file      file the error has occurred in\n * \\param line      line number the error has occurred in\n * \\param text      a name or label for the buffer being dumped. Normally the\n *                  variable or buffer name\n * \\param buf       the buffer to be outputted\n * \\param len       length of the buffer\n *\n * \\attention       This function is intended for INTERNAL usage within the\n *                  library only.\n */\nvoid mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level,\n                             const char *file, int line, const char *text,\n                             const unsigned char *buf, size_t len);\n\n#if defined(MBEDTLS_BIGNUM_C)\n/**\n * \\brief   Print a MPI variable to the debug output. This function is always\n *          used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the\n *          ssl context, file and line number parameters.\n *\n * \\param ssl       SSL context\n * \\param level     error level of the debug message\n * \\param file      file the error has occurred in\n * \\param line      line number the error has occurred in\n * \\param text      a name or label for the MPI being output. Normally the\n *                  variable name\n * \\param X         the MPI variable\n *\n * \\attention       This function is intended for INTERNAL usage within the\n *                  library only.\n */\nvoid mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level,\n                             const char *file, int line,\n                             const char *text, const mbedtls_mpi *X);\n#endif\n\n#if defined(MBEDTLS_ECP_LIGHT)\n/**\n * \\brief   Print an ECP point to the debug output. This function is always\n *          used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the\n *          ssl context, file and line number parameters.\n *\n * \\param ssl       SSL context\n * \\param level     error level of the debug message\n * \\param file      file the error has occurred in\n * \\param line      line number the error has occurred in\n * \\param text      a name or label for the ECP point being output. Normally the\n *                  variable name\n * \\param X         the ECP point\n *\n * \\attention       This function is intended for INTERNAL usage within the\n *                  library only.\n */\nvoid mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level,\n                             const char *file, int line,\n                             const char *text, const mbedtls_ecp_point *X);\n#endif\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO)\n/**\n * \\brief   Print a X.509 certificate structure to the debug output. This\n *          function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro,\n *          which supplies the ssl context, file and line number parameters.\n *\n * \\param ssl       SSL context\n * \\param level     error level of the debug message\n * \\param file      file the error has occurred in\n * \\param line      line number the error has occurred in\n * \\param text      a name or label for the certificate being output\n * \\param crt       X.509 certificate structure\n *\n * \\attention       This function is intended for INTERNAL usage within the\n *                  library only.\n */\nvoid mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level,\n                             const char *file, int line,\n                             const char *text, const mbedtls_x509_crt *crt);\n#endif\n\n/* Note: the MBEDTLS_ECDH_C guard here is mandatory because this debug function\n         only works for the built-in implementation. */\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) && \\\n    defined(MBEDTLS_ECDH_C)\ntypedef enum {\n    MBEDTLS_DEBUG_ECDH_Q,\n    MBEDTLS_DEBUG_ECDH_QP,\n    MBEDTLS_DEBUG_ECDH_Z,\n} mbedtls_debug_ecdh_attr;\n\n/**\n * \\brief   Print a field of the ECDH structure in the SSL context to the debug\n *          output. This function is always used through the\n *          MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file\n *          and line number parameters.\n *\n * \\param ssl       SSL context\n * \\param level     error level of the debug message\n * \\param file      file the error has occurred in\n * \\param line      line number the error has occurred in\n * \\param ecdh      the ECDH context\n * \\param attr      the identifier of the attribute being output\n *\n * \\attention       This function is intended for INTERNAL usage within the\n *                  library only.\n */\nvoid mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level,\n                               const char *file, int line,\n                               const mbedtls_ecdh_context *ecdh,\n                               mbedtls_debug_ecdh_attr attr);\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED &&\n          MBEDTLS_ECDH_C */\n\n#endif /* MBEDTLS_DEBUG_INTERNAL_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/des.c",
    "content": "/*\n *  FIPS-46-3 compliant Triple-DES implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  DES, on which TDES is based, was originally designed by Horst Feistel\n *  at IBM in 1974, and was adopted as a standard by NIST (formerly NBS).\n *\n *  http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_DES_C)\n\n#include \"mbedtls/des.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#if !defined(MBEDTLS_DES_ALT)\n\n/*\n * Expanded DES S-boxes\n */\nstatic const uint32_t SB1[64] =\n{\n    0x01010400, 0x00000000, 0x00010000, 0x01010404,\n    0x01010004, 0x00010404, 0x00000004, 0x00010000,\n    0x00000400, 0x01010400, 0x01010404, 0x00000400,\n    0x01000404, 0x01010004, 0x01000000, 0x00000004,\n    0x00000404, 0x01000400, 0x01000400, 0x00010400,\n    0x00010400, 0x01010000, 0x01010000, 0x01000404,\n    0x00010004, 0x01000004, 0x01000004, 0x00010004,\n    0x00000000, 0x00000404, 0x00010404, 0x01000000,\n    0x00010000, 0x01010404, 0x00000004, 0x01010000,\n    0x01010400, 0x01000000, 0x01000000, 0x00000400,\n    0x01010004, 0x00010000, 0x00010400, 0x01000004,\n    0x00000400, 0x00000004, 0x01000404, 0x00010404,\n    0x01010404, 0x00010004, 0x01010000, 0x01000404,\n    0x01000004, 0x00000404, 0x00010404, 0x01010400,\n    0x00000404, 0x01000400, 0x01000400, 0x00000000,\n    0x00010004, 0x00010400, 0x00000000, 0x01010004\n};\n\nstatic const uint32_t SB2[64] =\n{\n    0x80108020, 0x80008000, 0x00008000, 0x00108020,\n    0x00100000, 0x00000020, 0x80100020, 0x80008020,\n    0x80000020, 0x80108020, 0x80108000, 0x80000000,\n    0x80008000, 0x00100000, 0x00000020, 0x80100020,\n    0x00108000, 0x00100020, 0x80008020, 0x00000000,\n    0x80000000, 0x00008000, 0x00108020, 0x80100000,\n    0x00100020, 0x80000020, 0x00000000, 0x00108000,\n    0x00008020, 0x80108000, 0x80100000, 0x00008020,\n    0x00000000, 0x00108020, 0x80100020, 0x00100000,\n    0x80008020, 0x80100000, 0x80108000, 0x00008000,\n    0x80100000, 0x80008000, 0x00000020, 0x80108020,\n    0x00108020, 0x00000020, 0x00008000, 0x80000000,\n    0x00008020, 0x80108000, 0x00100000, 0x80000020,\n    0x00100020, 0x80008020, 0x80000020, 0x00100020,\n    0x00108000, 0x00000000, 0x80008000, 0x00008020,\n    0x80000000, 0x80100020, 0x80108020, 0x00108000\n};\n\nstatic const uint32_t SB3[64] =\n{\n    0x00000208, 0x08020200, 0x00000000, 0x08020008,\n    0x08000200, 0x00000000, 0x00020208, 0x08000200,\n    0x00020008, 0x08000008, 0x08000008, 0x00020000,\n    0x08020208, 0x00020008, 0x08020000, 0x00000208,\n    0x08000000, 0x00000008, 0x08020200, 0x00000200,\n    0x00020200, 0x08020000, 0x08020008, 0x00020208,\n    0x08000208, 0x00020200, 0x00020000, 0x08000208,\n    0x00000008, 0x08020208, 0x00000200, 0x08000000,\n    0x08020200, 0x08000000, 0x00020008, 0x00000208,\n    0x00020000, 0x08020200, 0x08000200, 0x00000000,\n    0x00000200, 0x00020008, 0x08020208, 0x08000200,\n    0x08000008, 0x00000200, 0x00000000, 0x08020008,\n    0x08000208, 0x00020000, 0x08000000, 0x08020208,\n    0x00000008, 0x00020208, 0x00020200, 0x08000008,\n    0x08020000, 0x08000208, 0x00000208, 0x08020000,\n    0x00020208, 0x00000008, 0x08020008, 0x00020200\n};\n\nstatic const uint32_t SB4[64] =\n{\n    0x00802001, 0x00002081, 0x00002081, 0x00000080,\n    0x00802080, 0x00800081, 0x00800001, 0x00002001,\n    0x00000000, 0x00802000, 0x00802000, 0x00802081,\n    0x00000081, 0x00000000, 0x00800080, 0x00800001,\n    0x00000001, 0x00002000, 0x00800000, 0x00802001,\n    0x00000080, 0x00800000, 0x00002001, 0x00002080,\n    0x00800081, 0x00000001, 0x00002080, 0x00800080,\n    0x00002000, 0x00802080, 0x00802081, 0x00000081,\n    0x00800080, 0x00800001, 0x00802000, 0x00802081,\n    0x00000081, 0x00000000, 0x00000000, 0x00802000,\n    0x00002080, 0x00800080, 0x00800081, 0x00000001,\n    0x00802001, 0x00002081, 0x00002081, 0x00000080,\n    0x00802081, 0x00000081, 0x00000001, 0x00002000,\n    0x00800001, 0x00002001, 0x00802080, 0x00800081,\n    0x00002001, 0x00002080, 0x00800000, 0x00802001,\n    0x00000080, 0x00800000, 0x00002000, 0x00802080\n};\n\nstatic const uint32_t SB5[64] =\n{\n    0x00000100, 0x02080100, 0x02080000, 0x42000100,\n    0x00080000, 0x00000100, 0x40000000, 0x02080000,\n    0x40080100, 0x00080000, 0x02000100, 0x40080100,\n    0x42000100, 0x42080000, 0x00080100, 0x40000000,\n    0x02000000, 0x40080000, 0x40080000, 0x00000000,\n    0x40000100, 0x42080100, 0x42080100, 0x02000100,\n    0x42080000, 0x40000100, 0x00000000, 0x42000000,\n    0x02080100, 0x02000000, 0x42000000, 0x00080100,\n    0x00080000, 0x42000100, 0x00000100, 0x02000000,\n    0x40000000, 0x02080000, 0x42000100, 0x40080100,\n    0x02000100, 0x40000000, 0x42080000, 0x02080100,\n    0x40080100, 0x00000100, 0x02000000, 0x42080000,\n    0x42080100, 0x00080100, 0x42000000, 0x42080100,\n    0x02080000, 0x00000000, 0x40080000, 0x42000000,\n    0x00080100, 0x02000100, 0x40000100, 0x00080000,\n    0x00000000, 0x40080000, 0x02080100, 0x40000100\n};\n\nstatic const uint32_t SB6[64] =\n{\n    0x20000010, 0x20400000, 0x00004000, 0x20404010,\n    0x20400000, 0x00000010, 0x20404010, 0x00400000,\n    0x20004000, 0x00404010, 0x00400000, 0x20000010,\n    0x00400010, 0x20004000, 0x20000000, 0x00004010,\n    0x00000000, 0x00400010, 0x20004010, 0x00004000,\n    0x00404000, 0x20004010, 0x00000010, 0x20400010,\n    0x20400010, 0x00000000, 0x00404010, 0x20404000,\n    0x00004010, 0x00404000, 0x20404000, 0x20000000,\n    0x20004000, 0x00000010, 0x20400010, 0x00404000,\n    0x20404010, 0x00400000, 0x00004010, 0x20000010,\n    0x00400000, 0x20004000, 0x20000000, 0x00004010,\n    0x20000010, 0x20404010, 0x00404000, 0x20400000,\n    0x00404010, 0x20404000, 0x00000000, 0x20400010,\n    0x00000010, 0x00004000, 0x20400000, 0x00404010,\n    0x00004000, 0x00400010, 0x20004010, 0x00000000,\n    0x20404000, 0x20000000, 0x00400010, 0x20004010\n};\n\nstatic const uint32_t SB7[64] =\n{\n    0x00200000, 0x04200002, 0x04000802, 0x00000000,\n    0x00000800, 0x04000802, 0x00200802, 0x04200800,\n    0x04200802, 0x00200000, 0x00000000, 0x04000002,\n    0x00000002, 0x04000000, 0x04200002, 0x00000802,\n    0x04000800, 0x00200802, 0x00200002, 0x04000800,\n    0x04000002, 0x04200000, 0x04200800, 0x00200002,\n    0x04200000, 0x00000800, 0x00000802, 0x04200802,\n    0x00200800, 0x00000002, 0x04000000, 0x00200800,\n    0x04000000, 0x00200800, 0x00200000, 0x04000802,\n    0x04000802, 0x04200002, 0x04200002, 0x00000002,\n    0x00200002, 0x04000000, 0x04000800, 0x00200000,\n    0x04200800, 0x00000802, 0x00200802, 0x04200800,\n    0x00000802, 0x04000002, 0x04200802, 0x04200000,\n    0x00200800, 0x00000000, 0x00000002, 0x04200802,\n    0x00000000, 0x00200802, 0x04200000, 0x00000800,\n    0x04000002, 0x04000800, 0x00000800, 0x00200002\n};\n\nstatic const uint32_t SB8[64] =\n{\n    0x10001040, 0x00001000, 0x00040000, 0x10041040,\n    0x10000000, 0x10001040, 0x00000040, 0x10000000,\n    0x00040040, 0x10040000, 0x10041040, 0x00041000,\n    0x10041000, 0x00041040, 0x00001000, 0x00000040,\n    0x10040000, 0x10000040, 0x10001000, 0x00001040,\n    0x00041000, 0x00040040, 0x10040040, 0x10041000,\n    0x00001040, 0x00000000, 0x00000000, 0x10040040,\n    0x10000040, 0x10001000, 0x00041040, 0x00040000,\n    0x00041040, 0x00040000, 0x10041000, 0x00001000,\n    0x00000040, 0x10040040, 0x00001000, 0x00041040,\n    0x10001000, 0x00000040, 0x10000040, 0x10040000,\n    0x10040040, 0x10000000, 0x00040000, 0x10001040,\n    0x00000000, 0x10041040, 0x00040040, 0x10000040,\n    0x10040000, 0x10001000, 0x10001040, 0x00000000,\n    0x10041040, 0x00041000, 0x00041000, 0x00001040,\n    0x00001040, 0x00040040, 0x10000000, 0x10041000\n};\n\n/*\n * PC1: left and right halves bit-swap\n */\nstatic const uint32_t LHs[16] =\n{\n    0x00000000, 0x00000001, 0x00000100, 0x00000101,\n    0x00010000, 0x00010001, 0x00010100, 0x00010101,\n    0x01000000, 0x01000001, 0x01000100, 0x01000101,\n    0x01010000, 0x01010001, 0x01010100, 0x01010101\n};\n\nstatic const uint32_t RHs[16] =\n{\n    0x00000000, 0x01000000, 0x00010000, 0x01010000,\n    0x00000100, 0x01000100, 0x00010100, 0x01010100,\n    0x00000001, 0x01000001, 0x00010001, 0x01010001,\n    0x00000101, 0x01000101, 0x00010101, 0x01010101,\n};\n\n/*\n * Initial Permutation macro\n */\n#define DES_IP(X, Y)                                                       \\\n    do                                                                    \\\n    {                                                                     \\\n        T = (((X) >>  4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T <<  4); \\\n        T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \\\n        T = (((Y) >>  2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T <<  2); \\\n        T = (((Y) >>  8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T <<  8); \\\n        (Y) = (((Y) << 1) | ((Y) >> 31)) & 0xFFFFFFFF;                    \\\n        T = ((X) ^ (Y)) & 0xAAAAAAAA; (Y) ^= T; (X) ^= T;                 \\\n        (X) = (((X) << 1) | ((X) >> 31)) & 0xFFFFFFFF;                    \\\n    } while (0)\n\n/*\n * Final Permutation macro\n */\n#define DES_FP(X, Y)                                                       \\\n    do                                                                    \\\n    {                                                                     \\\n        (X) = (((X) << 31) | ((X) >> 1)) & 0xFFFFFFFF;                    \\\n        T = ((X) ^ (Y)) & 0xAAAAAAAA; (X) ^= T; (Y) ^= T;                 \\\n        (Y) = (((Y) << 31) | ((Y) >> 1)) & 0xFFFFFFFF;                    \\\n        T = (((Y) >>  8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T <<  8); \\\n        T = (((Y) >>  2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T <<  2); \\\n        T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \\\n        T = (((X) >>  4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T <<  4); \\\n    } while (0)\n\n/*\n * DES round macro\n */\n#define DES_ROUND(X, Y)                              \\\n    do                                              \\\n    {                                               \\\n        T = *SK++ ^ (X);                            \\\n        (Y) ^= SB8[(T) & 0x3F] ^            \\\n               SB6[(T >>  8) & 0x3F] ^            \\\n               SB4[(T >> 16) & 0x3F] ^            \\\n               SB2[(T >> 24) & 0x3F];             \\\n                                                    \\\n        T = *SK++ ^ (((X) << 28) | ((X) >> 4));     \\\n        (Y) ^= SB7[(T) & 0x3F] ^            \\\n               SB5[(T >>  8) & 0x3F] ^            \\\n               SB3[(T >> 16) & 0x3F] ^            \\\n               SB1[(T >> 24) & 0x3F];             \\\n    } while (0)\n\n#define SWAP(a, b)                                       \\\n    do                                                  \\\n    {                                                   \\\n        uint32_t t = (a); (a) = (b); (b) = t; t = 0;    \\\n    } while (0)\n\nvoid mbedtls_des_init(mbedtls_des_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_des_context));\n}\n\nvoid mbedtls_des_free(mbedtls_des_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_des_context));\n}\n\nvoid mbedtls_des3_init(mbedtls_des3_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_des3_context));\n}\n\nvoid mbedtls_des3_free(mbedtls_des3_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_des3_context));\n}\n\nstatic const unsigned char odd_parity_table[128] = { 1,  2,  4,  7,  8,\n                                                     11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32,\n                                                     35, 37, 38, 41, 42, 44,\n                                                     47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69,\n                                                     70, 73, 74, 76, 79, 81,\n                                                     82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103,\n                                                     104, 107, 109, 110, 112,\n                                                     115, 117, 118, 121, 122, 124, 127, 128, 131,\n                                                     133, 134, 137, 138, 140,\n                                                     143, 145, 146, 148, 151, 152, 155, 157, 158,\n                                                     161, 162, 164, 167, 168,\n                                                     171, 173, 174, 176, 179, 181, 182, 185, 186,\n                                                     188, 191, 193, 194, 196,\n                                                     199, 200, 203, 205, 206, 208, 211, 213, 214,\n                                                     217, 218, 220, 223, 224,\n                                                     227, 229, 230, 233, 234, 236, 239, 241, 242,\n                                                     244, 247, 248, 251, 253,\n                                                     254 };\n\nvoid mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE])\n{\n    int i;\n\n    for (i = 0; i < MBEDTLS_DES_KEY_SIZE; i++) {\n        key[i] = odd_parity_table[key[i] / 2];\n    }\n}\n\n/*\n * Check the given key's parity, returns 1 on failure, 0 on SUCCESS\n */\nint mbedtls_des_key_check_key_parity(const unsigned char key[MBEDTLS_DES_KEY_SIZE])\n{\n    int i;\n\n    for (i = 0; i < MBEDTLS_DES_KEY_SIZE; i++) {\n        if (key[i] != odd_parity_table[key[i] / 2]) {\n            return 1;\n        }\n    }\n\n    return 0;\n}\n\n/*\n * Table of weak and semi-weak keys\n *\n * Source: http://en.wikipedia.org/wiki/Weak_key\n *\n * Weak:\n * Alternating ones + zeros (0x0101010101010101)\n * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE)\n * '0xE0E0E0E0F1F1F1F1'\n * '0x1F1F1F1F0E0E0E0E'\n *\n * Semi-weak:\n * 0x011F011F010E010E and 0x1F011F010E010E01\n * 0x01E001E001F101F1 and 0xE001E001F101F101\n * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01\n * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E\n * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E\n * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1\n *\n */\n\n#define WEAK_KEY_COUNT 16\n\nstatic const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] =\n{\n    { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n    { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },\n    { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },\n    { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },\n\n    { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },\n    { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },\n    { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },\n    { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },\n    { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },\n    { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },\n    { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },\n    { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },\n    { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },\n    { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },\n    { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },\n    { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }\n};\n\nint mbedtls_des_key_check_weak(const unsigned char key[MBEDTLS_DES_KEY_SIZE])\n{\n    int i;\n\n    for (i = 0; i < WEAK_KEY_COUNT; i++) {\n        if (memcmp(weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0) {\n            return 1;\n        }\n    }\n\n    return 0;\n}\n\n#if !defined(MBEDTLS_DES_SETKEY_ALT)\nvoid mbedtls_des_setkey(uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE])\n{\n    int i;\n    uint32_t X, Y, T;\n\n    X = MBEDTLS_GET_UINT32_BE(key, 0);\n    Y = MBEDTLS_GET_UINT32_BE(key, 4);\n\n    /*\n     * Permuted Choice 1\n     */\n    T =  ((Y >>  4) ^ X) & 0x0F0F0F0F;  X ^= T; Y ^= (T <<  4);\n    T =  ((Y) ^ X) & 0x10101010;  X ^= T; Y ^= (T);\n\n    X =   (LHs[(X) & 0xF] << 3) | (LHs[(X >>  8) & 0xF] << 2)\n        | (LHs[(X >> 16) & 0xF] << 1) | (LHs[(X >> 24) & 0xF])\n        | (LHs[(X >>  5) & 0xF] << 7) | (LHs[(X >> 13) & 0xF] << 6)\n        | (LHs[(X >> 21) & 0xF] << 5) | (LHs[(X >> 29) & 0xF] << 4);\n\n    Y =   (RHs[(Y >>  1) & 0xF] << 3) | (RHs[(Y >>  9) & 0xF] << 2)\n        | (RHs[(Y >> 17) & 0xF] << 1) | (RHs[(Y >> 25) & 0xF])\n        | (RHs[(Y >>  4) & 0xF] << 7) | (RHs[(Y >> 12) & 0xF] << 6)\n        | (RHs[(Y >> 20) & 0xF] << 5) | (RHs[(Y >> 28) & 0xF] << 4);\n\n    X &= 0x0FFFFFFF;\n    Y &= 0x0FFFFFFF;\n\n    /*\n     * calculate subkeys\n     */\n    for (i = 0; i < 16; i++) {\n        if (i < 2 || i == 8 || i == 15) {\n            X = ((X <<  1) | (X >> 27)) & 0x0FFFFFFF;\n            Y = ((Y <<  1) | (Y >> 27)) & 0x0FFFFFFF;\n        } else {\n            X = ((X <<  2) | (X >> 26)) & 0x0FFFFFFF;\n            Y = ((Y <<  2) | (Y >> 26)) & 0x0FFFFFFF;\n        }\n\n        *SK++ =   ((X <<  4) & 0x24000000) | ((X << 28) & 0x10000000)\n                | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)\n                | ((X <<  6) & 0x01000000) | ((X <<  9) & 0x00200000)\n                | ((X >>  1) & 0x00100000) | ((X << 10) & 0x00040000)\n                | ((X <<  2) & 0x00020000) | ((X >> 10) & 0x00010000)\n                | ((Y >> 13) & 0x00002000) | ((Y >>  4) & 0x00001000)\n                | ((Y <<  6) & 0x00000800) | ((Y >>  1) & 0x00000400)\n                | ((Y >> 14) & 0x00000200) | ((Y) & 0x00000100)\n                | ((Y >>  5) & 0x00000020) | ((Y >> 10) & 0x00000010)\n                | ((Y >>  3) & 0x00000008) | ((Y >> 18) & 0x00000004)\n                | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);\n\n        *SK++ =   ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)\n                | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)\n                | ((X >>  2) & 0x02000000) | ((X <<  1) & 0x01000000)\n                | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)\n                | ((X <<  3) & 0x00080000) | ((X >>  6) & 0x00040000)\n                | ((X << 15) & 0x00020000) | ((X >>  4) & 0x00010000)\n                | ((Y >>  2) & 0x00002000) | ((Y <<  8) & 0x00001000)\n                | ((Y >> 14) & 0x00000808) | ((Y >>  9) & 0x00000400)\n                | ((Y) & 0x00000200) | ((Y <<  7) & 0x00000100)\n                | ((Y >>  7) & 0x00000020) | ((Y >>  3) & 0x00000011)\n                | ((Y <<  2) & 0x00000004) | ((Y >> 21) & 0x00000002);\n    }\n}\n#endif /* !MBEDTLS_DES_SETKEY_ALT */\n\n/*\n * DES key schedule (56-bit, encryption)\n */\nint mbedtls_des_setkey_enc(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE])\n{\n    mbedtls_des_setkey(ctx->sk, key);\n\n    return 0;\n}\n\n/*\n * DES key schedule (56-bit, decryption)\n */\nint mbedtls_des_setkey_dec(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE])\n{\n    int i;\n\n    mbedtls_des_setkey(ctx->sk, key);\n\n    for (i = 0; i < 16; i += 2) {\n        SWAP(ctx->sk[i], ctx->sk[30 - i]);\n        SWAP(ctx->sk[i + 1], ctx->sk[31 - i]);\n    }\n\n    return 0;\n}\n\nstatic void des3_set2key(uint32_t esk[96],\n                         uint32_t dsk[96],\n                         const unsigned char key[MBEDTLS_DES_KEY_SIZE*2])\n{\n    int i;\n\n    mbedtls_des_setkey(esk, key);\n    mbedtls_des_setkey(dsk + 32, key + 8);\n\n    for (i = 0; i < 32; i += 2) {\n        dsk[i] = esk[30 - i];\n        dsk[i +  1] = esk[31 - i];\n\n        esk[i + 32] = dsk[62 - i];\n        esk[i + 33] = dsk[63 - i];\n\n        esk[i + 64] = esk[i];\n        esk[i + 65] = esk[i + 1];\n\n        dsk[i + 64] = dsk[i];\n        dsk[i + 65] = dsk[i + 1];\n    }\n}\n\n/*\n * Triple-DES key schedule (112-bit, encryption)\n */\nint mbedtls_des3_set2key_enc(mbedtls_des3_context *ctx,\n                             const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2])\n{\n    uint32_t sk[96];\n\n    des3_set2key(ctx->sk, sk, key);\n    mbedtls_platform_zeroize(sk,  sizeof(sk));\n\n    return 0;\n}\n\n/*\n * Triple-DES key schedule (112-bit, decryption)\n */\nint mbedtls_des3_set2key_dec(mbedtls_des3_context *ctx,\n                             const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2])\n{\n    uint32_t sk[96];\n\n    des3_set2key(sk, ctx->sk, key);\n    mbedtls_platform_zeroize(sk,  sizeof(sk));\n\n    return 0;\n}\n\nstatic void des3_set3key(uint32_t esk[96],\n                         uint32_t dsk[96],\n                         const unsigned char key[24])\n{\n    int i;\n\n    mbedtls_des_setkey(esk, key);\n    mbedtls_des_setkey(dsk + 32, key +  8);\n    mbedtls_des_setkey(esk + 64, key + 16);\n\n    for (i = 0; i < 32; i += 2) {\n        dsk[i] = esk[94 - i];\n        dsk[i +  1] = esk[95 - i];\n\n        esk[i + 32] = dsk[62 - i];\n        esk[i + 33] = dsk[63 - i];\n\n        dsk[i + 64] = esk[30 - i];\n        dsk[i + 65] = esk[31 - i];\n    }\n}\n\n/*\n * Triple-DES key schedule (168-bit, encryption)\n */\nint mbedtls_des3_set3key_enc(mbedtls_des3_context *ctx,\n                             const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3])\n{\n    uint32_t sk[96];\n\n    des3_set3key(ctx->sk, sk, key);\n    mbedtls_platform_zeroize(sk,  sizeof(sk));\n\n    return 0;\n}\n\n/*\n * Triple-DES key schedule (168-bit, decryption)\n */\nint mbedtls_des3_set3key_dec(mbedtls_des3_context *ctx,\n                             const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3])\n{\n    uint32_t sk[96];\n\n    des3_set3key(sk, ctx->sk, key);\n    mbedtls_platform_zeroize(sk,  sizeof(sk));\n\n    return 0;\n}\n\n/*\n * DES-ECB block encryption/decryption\n */\n#if !defined(MBEDTLS_DES_CRYPT_ECB_ALT)\nint mbedtls_des_crypt_ecb(mbedtls_des_context *ctx,\n                          const unsigned char input[8],\n                          unsigned char output[8])\n{\n    int i;\n    uint32_t X, Y, T, *SK;\n\n    SK = ctx->sk;\n\n    X = MBEDTLS_GET_UINT32_BE(input, 0);\n    Y = MBEDTLS_GET_UINT32_BE(input, 4);\n\n    DES_IP(X, Y);\n\n    for (i = 0; i < 8; i++) {\n        DES_ROUND(Y, X);\n        DES_ROUND(X, Y);\n    }\n\n    DES_FP(Y, X);\n\n    MBEDTLS_PUT_UINT32_BE(Y, output, 0);\n    MBEDTLS_PUT_UINT32_BE(X, output, 4);\n\n    return 0;\n}\n#endif /* !MBEDTLS_DES_CRYPT_ECB_ALT */\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n/*\n * DES-CBC buffer encryption/decryption\n */\nint mbedtls_des_crypt_cbc(mbedtls_des_context *ctx,\n                          int mode,\n                          size_t length,\n                          unsigned char iv[8],\n                          const unsigned char *input,\n                          unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char temp[8];\n\n    if (length % 8) {\n        return MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH;\n    }\n\n    if (mode == MBEDTLS_DES_ENCRYPT) {\n        while (length > 0) {\n            mbedtls_xor(output, input, iv, 8);\n\n            ret = mbedtls_des_crypt_ecb(ctx, output, output);\n            if (ret != 0) {\n                goto exit;\n            }\n            memcpy(iv, output, 8);\n\n            input  += 8;\n            output += 8;\n            length -= 8;\n        }\n    } else { /* MBEDTLS_DES_DECRYPT */\n        while (length > 0) {\n            memcpy(temp, input, 8);\n            ret = mbedtls_des_crypt_ecb(ctx, input, output);\n            if (ret != 0) {\n                goto exit;\n            }\n\n            mbedtls_xor(output, output, iv, 8);\n\n            memcpy(iv, temp, 8);\n\n            input  += 8;\n            output += 8;\n            length -= 8;\n        }\n    }\n    ret = 0;\n\nexit:\n    return ret;\n}\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n/*\n * 3DES-ECB block encryption/decryption\n */\n#if !defined(MBEDTLS_DES3_CRYPT_ECB_ALT)\nint mbedtls_des3_crypt_ecb(mbedtls_des3_context *ctx,\n                           const unsigned char input[8],\n                           unsigned char output[8])\n{\n    int i;\n    uint32_t X, Y, T, *SK;\n\n    SK = ctx->sk;\n\n    X = MBEDTLS_GET_UINT32_BE(input, 0);\n    Y = MBEDTLS_GET_UINT32_BE(input, 4);\n\n    DES_IP(X, Y);\n\n    for (i = 0; i < 8; i++) {\n        DES_ROUND(Y, X);\n        DES_ROUND(X, Y);\n    }\n\n    for (i = 0; i < 8; i++) {\n        DES_ROUND(X, Y);\n        DES_ROUND(Y, X);\n    }\n\n    for (i = 0; i < 8; i++) {\n        DES_ROUND(Y, X);\n        DES_ROUND(X, Y);\n    }\n\n    DES_FP(Y, X);\n\n    MBEDTLS_PUT_UINT32_BE(Y, output, 0);\n    MBEDTLS_PUT_UINT32_BE(X, output, 4);\n\n    return 0;\n}\n#endif /* !MBEDTLS_DES3_CRYPT_ECB_ALT */\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n/*\n * 3DES-CBC buffer encryption/decryption\n */\nint mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx,\n                           int mode,\n                           size_t length,\n                           unsigned char iv[8],\n                           const unsigned char *input,\n                           unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char temp[8];\n\n    if (length % 8) {\n        return MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH;\n    }\n\n    if (mode == MBEDTLS_DES_ENCRYPT) {\n        while (length > 0) {\n            mbedtls_xor(output, input, iv, 8);\n\n            ret = mbedtls_des3_crypt_ecb(ctx, output, output);\n            if (ret != 0) {\n                goto exit;\n            }\n            memcpy(iv, output, 8);\n\n            input  += 8;\n            output += 8;\n            length -= 8;\n        }\n    } else { /* MBEDTLS_DES_DECRYPT */\n        while (length > 0) {\n            memcpy(temp, input, 8);\n            ret = mbedtls_des3_crypt_ecb(ctx, input, output);\n            if (ret != 0) {\n                goto exit;\n            }\n\n            mbedtls_xor(output, output, iv, 8);\n\n            memcpy(iv, temp, 8);\n\n            input  += 8;\n            output += 8;\n            length -= 8;\n        }\n    }\n    ret = 0;\n\nexit:\n    return ret;\n}\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#endif /* !MBEDTLS_DES_ALT */\n\n#if defined(MBEDTLS_SELF_TEST)\n/*\n * DES and 3DES test vectors from:\n *\n * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip\n */\nstatic const unsigned char des3_test_keys[24] =\n{\n    0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,\n    0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,\n    0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23\n};\n\nstatic const unsigned char des3_test_buf[8] =\n{\n    0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74\n};\n\nstatic const unsigned char des3_test_ecb_dec[3][8] =\n{\n    { 0x37, 0x2B, 0x98, 0xBF, 0x52, 0x65, 0xB0, 0x59 },\n    { 0xC2, 0x10, 0x19, 0x9C, 0x38, 0x5A, 0x65, 0xA1 },\n    { 0xA2, 0x70, 0x56, 0x68, 0x69, 0xE5, 0x15, 0x1D }\n};\n\nstatic const unsigned char des3_test_ecb_enc[3][8] =\n{\n    { 0x1C, 0xD5, 0x97, 0xEA, 0x84, 0x26, 0x73, 0xFB },\n    { 0xB3, 0x92, 0x4D, 0xF3, 0xC5, 0xB5, 0x42, 0x93 },\n    { 0xDA, 0x37, 0x64, 0x41, 0xBA, 0x6F, 0x62, 0x6F }\n};\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\nstatic const unsigned char des3_test_iv[8] =\n{\n    0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF,\n};\n\nstatic const unsigned char des3_test_cbc_dec[3][8] =\n{\n    { 0x58, 0xD9, 0x48, 0xEF, 0x85, 0x14, 0x65, 0x9A },\n    { 0x5F, 0xC8, 0x78, 0xD4, 0xD7, 0x92, 0xD9, 0x54 },\n    { 0x25, 0xF9, 0x75, 0x85, 0xA8, 0x1E, 0x48, 0xBF }\n};\n\nstatic const unsigned char des3_test_cbc_enc[3][8] =\n{\n    { 0x91, 0x1C, 0x6D, 0xCF, 0x48, 0xA7, 0xC3, 0x4D },\n    { 0x60, 0x1A, 0x76, 0x8F, 0xA1, 0xF9, 0x66, 0xF1 },\n    { 0xA1, 0x50, 0x0F, 0x99, 0xB2, 0xCD, 0x64, 0x76 }\n};\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n/*\n * Checkup routine\n */\nint mbedtls_des_self_test(int verbose)\n{\n    int i, j, u, v, ret = 0;\n    mbedtls_des_context ctx;\n    mbedtls_des3_context ctx3;\n    unsigned char buf[8];\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    unsigned char prv[8];\n    unsigned char iv[8];\n#endif\n\n    mbedtls_des_init(&ctx);\n    mbedtls_des3_init(&ctx3);\n    /*\n     * ECB mode\n     */\n    for (i = 0; i < 6; i++) {\n        u = i >> 1;\n        v = i  & 1;\n\n        if (verbose != 0) {\n            mbedtls_printf(\"  DES%c-ECB-%3d (%s): \",\n                           (u == 0) ? ' ' : '3', 56 + u * 56,\n                           (v == MBEDTLS_DES_DECRYPT) ? \"dec\" : \"enc\");\n        }\n\n        memcpy(buf, des3_test_buf, 8);\n\n        switch (i) {\n            case 0:\n                ret = mbedtls_des_setkey_dec(&ctx, des3_test_keys);\n                break;\n\n            case 1:\n                ret = mbedtls_des_setkey_enc(&ctx, des3_test_keys);\n                break;\n\n            case 2:\n                ret = mbedtls_des3_set2key_dec(&ctx3, des3_test_keys);\n                break;\n\n            case 3:\n                ret = mbedtls_des3_set2key_enc(&ctx3, des3_test_keys);\n                break;\n\n            case 4:\n                ret = mbedtls_des3_set3key_dec(&ctx3, des3_test_keys);\n                break;\n\n            case 5:\n                ret = mbedtls_des3_set3key_enc(&ctx3, des3_test_keys);\n                break;\n\n            default:\n                return 1;\n        }\n        if (ret != 0) {\n            goto exit;\n        }\n\n        for (j = 0; j < 100; j++) {\n            if (u == 0) {\n                ret = mbedtls_des_crypt_ecb(&ctx, buf, buf);\n            } else {\n                ret = mbedtls_des3_crypt_ecb(&ctx3, buf, buf);\n            }\n            if (ret != 0) {\n                goto exit;\n            }\n        }\n\n        if ((v == MBEDTLS_DES_DECRYPT &&\n             memcmp(buf, des3_test_ecb_dec[u], 8) != 0) ||\n            (v != MBEDTLS_DES_DECRYPT &&\n             memcmp(buf, des3_test_ecb_enc[u], 8) != 0)) {\n            if (verbose != 0) {\n                mbedtls_printf(\"failed\\n\");\n            }\n\n            ret = 1;\n            goto exit;\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    /*\n     * CBC mode\n     */\n    for (i = 0; i < 6; i++) {\n        u = i >> 1;\n        v = i  & 1;\n\n        if (verbose != 0) {\n            mbedtls_printf(\"  DES%c-CBC-%3d (%s): \",\n                           (u == 0) ? ' ' : '3', 56 + u * 56,\n                           (v == MBEDTLS_DES_DECRYPT) ? \"dec\" : \"enc\");\n        }\n\n        memcpy(iv,  des3_test_iv,  8);\n        memcpy(prv, des3_test_iv,  8);\n        memcpy(buf, des3_test_buf, 8);\n\n        switch (i) {\n            case 0:\n                ret = mbedtls_des_setkey_dec(&ctx, des3_test_keys);\n                break;\n\n            case 1:\n                ret = mbedtls_des_setkey_enc(&ctx, des3_test_keys);\n                break;\n\n            case 2:\n                ret = mbedtls_des3_set2key_dec(&ctx3, des3_test_keys);\n                break;\n\n            case 3:\n                ret = mbedtls_des3_set2key_enc(&ctx3, des3_test_keys);\n                break;\n\n            case 4:\n                ret = mbedtls_des3_set3key_dec(&ctx3, des3_test_keys);\n                break;\n\n            case 5:\n                ret = mbedtls_des3_set3key_enc(&ctx3, des3_test_keys);\n                break;\n\n            default:\n                return 1;\n        }\n        if (ret != 0) {\n            goto exit;\n        }\n\n        if (v == MBEDTLS_DES_DECRYPT) {\n            for (j = 0; j < 100; j++) {\n                if (u == 0) {\n                    ret = mbedtls_des_crypt_cbc(&ctx, v, 8, iv, buf, buf);\n                } else {\n                    ret = mbedtls_des3_crypt_cbc(&ctx3, v, 8, iv, buf, buf);\n                }\n                if (ret != 0) {\n                    goto exit;\n                }\n            }\n        } else {\n            for (j = 0; j < 100; j++) {\n                unsigned char tmp[8];\n\n                if (u == 0) {\n                    ret = mbedtls_des_crypt_cbc(&ctx, v, 8, iv, buf, buf);\n                } else {\n                    ret = mbedtls_des3_crypt_cbc(&ctx3, v, 8, iv, buf, buf);\n                }\n                if (ret != 0) {\n                    goto exit;\n                }\n\n                memcpy(tmp, prv, 8);\n                memcpy(prv, buf, 8);\n                memcpy(buf, tmp, 8);\n            }\n\n            memcpy(buf, prv, 8);\n        }\n\n        if ((v == MBEDTLS_DES_DECRYPT &&\n             memcmp(buf, des3_test_cbc_dec[u], 8) != 0) ||\n            (v != MBEDTLS_DES_DECRYPT &&\n             memcmp(buf, des3_test_cbc_enc[u], 8) != 0)) {\n            if (verbose != 0) {\n                mbedtls_printf(\"failed\\n\");\n            }\n\n            ret = 1;\n            goto exit;\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\nexit:\n    mbedtls_des_free(&ctx);\n    mbedtls_des3_free(&ctx3);\n\n    if (ret != 0) {\n        ret = 1;\n    }\n    return ret;\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_DES_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/dhm.c",
    "content": "/*\n *  Diffie-Hellman-Merkle key exchange\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  The following sources were referenced in the design of this implementation\n *  of the Diffie-Hellman-Merkle algorithm:\n *\n *  [1] Handbook of Applied Cryptography - 1997, Chapter 12\n *      Menezes, van Oorschot and Vanstone\n *\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_DHM_C)\n\n#include \"mbedtls/dhm.h\"\n#include \"bignum_internal.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_PEM_PARSE_C)\n#include \"mbedtls/pem.h\"\n#endif\n\n#if defined(MBEDTLS_ASN1_PARSE_C)\n#include \"mbedtls/asn1.h\"\n#endif\n\n#include \"mbedtls/platform.h\"\n\n#if !defined(MBEDTLS_DHM_ALT)\n\n/*\n * helper to validate the mbedtls_mpi size and import it\n */\nstatic int dhm_read_bignum(mbedtls_mpi *X,\n                           unsigned char **p,\n                           const unsigned char *end)\n{\n    int ret, n;\n\n    if (end - *p < 2) {\n        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;\n    }\n\n    n = MBEDTLS_GET_UINT16_BE(*p, 0);\n    (*p) += 2;\n\n    if ((size_t) (end - *p) < (size_t) n) {\n        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;\n    }\n\n    if ((ret = mbedtls_mpi_read_binary(X, *p, n)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret);\n    }\n\n    (*p) += n;\n\n    return 0;\n}\n\n/*\n * Verify sanity of parameter with regards to P\n *\n * Parameter should be: 2 <= public_param <= P - 2\n *\n * This means that we need to return an error if\n *              public_param < 2 or public_param > P-2\n *\n * For more information on the attack, see:\n *  http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf\n *  http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643\n */\nstatic int dhm_check_range(const mbedtls_mpi *param, const mbedtls_mpi *P)\n{\n    mbedtls_mpi U;\n    int ret = 0;\n\n    mbedtls_mpi_init(&U);\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&U, P, 2));\n\n    if (mbedtls_mpi_cmp_int(param, 2) < 0 ||\n        mbedtls_mpi_cmp_mpi(param, &U) > 0) {\n        ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;\n    }\n\ncleanup:\n    mbedtls_mpi_free(&U);\n    return ret;\n}\n\nvoid mbedtls_dhm_init(mbedtls_dhm_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_dhm_context));\n}\n\nsize_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx)\n{\n    return mbedtls_mpi_bitlen(&ctx->P);\n}\n\nsize_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx)\n{\n    return mbedtls_mpi_size(&ctx->P);\n}\n\nint mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx,\n                          mbedtls_dhm_parameter param,\n                          mbedtls_mpi *dest)\n{\n    const mbedtls_mpi *src = NULL;\n    switch (param) {\n        case MBEDTLS_DHM_PARAM_P:\n            src = &ctx->P;\n            break;\n        case MBEDTLS_DHM_PARAM_G:\n            src = &ctx->G;\n            break;\n        case MBEDTLS_DHM_PARAM_X:\n            src = &ctx->X;\n            break;\n        case MBEDTLS_DHM_PARAM_GX:\n            src = &ctx->GX;\n            break;\n        case MBEDTLS_DHM_PARAM_GY:\n            src = &ctx->GY;\n            break;\n        case MBEDTLS_DHM_PARAM_K:\n            src = &ctx->K;\n            break;\n        default:\n            return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;\n    }\n    return mbedtls_mpi_copy(dest, src);\n}\n\n/*\n * Parse the ServerKeyExchange parameters\n */\nint mbedtls_dhm_read_params(mbedtls_dhm_context *ctx,\n                            unsigned char **p,\n                            const unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if ((ret = dhm_read_bignum(&ctx->P,  p, end)) != 0 ||\n        (ret = dhm_read_bignum(&ctx->G,  p, end)) != 0 ||\n        (ret = dhm_read_bignum(&ctx->GY, p, end)) != 0) {\n        return ret;\n    }\n\n    if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\n/*\n * Pick a random R in the range [2, M-2] for blinding or key generation.\n */\nstatic int dhm_random_below(mbedtls_mpi *R, const mbedtls_mpi *M,\n                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    int ret;\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_random(R, 3, M, f_rng, p_rng));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(R, R, 1));\n\ncleanup:\n    return ret;\n}\n\nstatic int dhm_make_common(mbedtls_dhm_context *ctx, int x_size,\n                           int (*f_rng)(void *, unsigned char *, size_t),\n                           void *p_rng)\n{\n    int ret = 0;\n\n    if (mbedtls_mpi_cmp_int(&ctx->P, 0) == 0) {\n        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;\n    }\n    if (x_size < 0) {\n        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;\n    }\n\n    if ((unsigned) x_size < mbedtls_mpi_size(&ctx->P)) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->X, x_size, f_rng, p_rng));\n    } else {\n        /* Generate X as large as possible ( <= P - 2 ) */\n        ret = dhm_random_below(&ctx->X, &ctx->P, f_rng, p_rng);\n        if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {\n            return MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED;\n        }\n        if (ret != 0) {\n            return ret;\n        }\n    }\n\n    /*\n     * Calculate GX = G^X mod P\n     */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->GX, &ctx->G, &ctx->X,\n                                        &ctx->P, &ctx->RP));\n\n    if ((ret = dhm_check_range(&ctx->GX, &ctx->P)) != 0) {\n        return ret;\n    }\n\ncleanup:\n    return ret;\n}\n\n/*\n * Setup and write the ServerKeyExchange parameters\n */\nint mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size,\n                            unsigned char *output, size_t *olen,\n                            int (*f_rng)(void *, unsigned char *, size_t),\n                            void *p_rng)\n{\n    int ret;\n    size_t n1, n2, n3;\n    unsigned char *p;\n\n    ret = dhm_make_common(ctx, x_size, f_rng, p_rng);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    /*\n     * Export P, G, GX. RFC 5246 §4.4 states that \"leading zero octets are\n     * not required\". We omit leading zeros for compactness.\n     */\n#define DHM_MPI_EXPORT(X, n)                                          \\\n    do {                                                                \\\n        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary((X),               \\\n                                                 p + 2,               \\\n                                                 (n)));           \\\n        *p++ = MBEDTLS_BYTE_1(n);                                     \\\n        *p++ = MBEDTLS_BYTE_0(n);                                     \\\n        p += (n);                                                     \\\n    } while (0)\n\n    n1 = mbedtls_mpi_size(&ctx->P);\n    n2 = mbedtls_mpi_size(&ctx->G);\n    n3 = mbedtls_mpi_size(&ctx->GX);\n\n    p = output;\n    DHM_MPI_EXPORT(&ctx->P, n1);\n    DHM_MPI_EXPORT(&ctx->G, n2);\n    DHM_MPI_EXPORT(&ctx->GX, n3);\n\n    *olen = (size_t) (p - output);\n\ncleanup:\n    if (ret != 0 && ret > -128) {\n        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret);\n    }\n    return ret;\n}\n\n/*\n * Set prime modulus and generator\n */\nint mbedtls_dhm_set_group(mbedtls_dhm_context *ctx,\n                          const mbedtls_mpi *P,\n                          const mbedtls_mpi *G)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if ((ret = mbedtls_mpi_copy(&ctx->P, P)) != 0 ||\n        (ret = mbedtls_mpi_copy(&ctx->G, G)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret);\n    }\n\n    return 0;\n}\n\n/*\n * Import the peer's public value G^Y\n */\nint mbedtls_dhm_read_public(mbedtls_dhm_context *ctx,\n                            const unsigned char *input, size_t ilen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (ilen < 1 || ilen > mbedtls_dhm_get_len(ctx)) {\n        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;\n    }\n\n    if ((ret = mbedtls_mpi_read_binary(&ctx->GY, input, ilen)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret);\n    }\n\n    return 0;\n}\n\n/*\n * Create own private value X and export G^X\n */\nint mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size,\n                            unsigned char *output, size_t olen,\n                            int (*f_rng)(void *, unsigned char *, size_t),\n                            void *p_rng)\n{\n    int ret;\n\n    if (olen < 1 || olen > mbedtls_dhm_get_len(ctx)) {\n        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;\n    }\n\n    ret = dhm_make_common(ctx, x_size, f_rng, p_rng);\n    if (ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) {\n        return MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED;\n    }\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->GX, output, olen));\n\ncleanup:\n    if (ret != 0 && ret > -128) {\n        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret);\n    }\n    return ret;\n}\n\n\n/*\n * Use the blinding method and optimisation suggested in section 10 of:\n *  KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,\n *  DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer\n *  Berlin Heidelberg, 1996. p. 104-113.\n */\nstatic int dhm_update_blinding(mbedtls_dhm_context *ctx,\n                               int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    int ret;\n\n    /*\n     * Don't use any blinding the first time a particular X is used,\n     * but remember it to use blinding next time.\n     */\n    if (mbedtls_mpi_cmp_mpi(&ctx->X, &ctx->pX) != 0) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&ctx->pX, &ctx->X));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vi, 1));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vf, 1));\n\n        return 0;\n    }\n\n    /*\n     * Ok, we need blinding. Can we re-use existing values?\n     * If yes, just update them by squaring them.\n     */\n    if (mbedtls_mpi_cmp_int(&ctx->Vi, 1) != 0) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->P));\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));\n\n        return 0;\n    }\n\n    /*\n     * We need to generate blinding values from scratch\n     */\n\n    /* Vi = random( 2, P-2 ) */\n    MBEDTLS_MPI_CHK(dhm_random_below(&ctx->Vi, &ctx->P, f_rng, p_rng));\n\n    /* Vf = Vi^-X = (Vi^-1)^X mod P */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(NULL, &ctx->Vf, &ctx->Vi, &ctx->P));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP));\n\ncleanup:\n    return ret;\n}\n\n/*\n * Derive and export the shared secret (G^Y)^X mod P\n */\nint mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx,\n                            unsigned char *output, size_t output_size, size_t *olen,\n                            int (*f_rng)(void *, unsigned char *, size_t),\n                            void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi GYb;\n\n    if (f_rng == NULL) {\n        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;\n    }\n\n    if (output_size < mbedtls_dhm_get_len(ctx)) {\n        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;\n    }\n\n    if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {\n        return ret;\n    }\n\n    mbedtls_mpi_init(&GYb);\n\n    /* Blind peer's value */\n    MBEDTLS_MPI_CHK(dhm_update_blinding(ctx, f_rng, p_rng));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&GYb, &ctx->GY, &ctx->Vi));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&GYb, &GYb, &ctx->P));\n\n    /* Do modular exponentiation */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->K, &GYb, &ctx->X,\n                                        &ctx->P, &ctx->RP));\n\n    /* Unblind secret value */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->K, &ctx->K, &ctx->Vf));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->K, &ctx->K, &ctx->P));\n\n    /* Output the secret without any leading zero byte. This is mandatory\n     * for TLS per RFC 5246 §8.1.2. */\n    *olen = mbedtls_mpi_size(&ctx->K);\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->K, output, *olen));\n\ncleanup:\n    mbedtls_mpi_free(&GYb);\n\n    if (ret != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret);\n    }\n\n    return 0;\n}\n\n/*\n * Free the components of a DHM key\n */\nvoid mbedtls_dhm_free(mbedtls_dhm_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_mpi_free(&ctx->pX);\n    mbedtls_mpi_free(&ctx->Vf);\n    mbedtls_mpi_free(&ctx->Vi);\n    mbedtls_mpi_free(&ctx->RP);\n    mbedtls_mpi_free(&ctx->K);\n    mbedtls_mpi_free(&ctx->GY);\n    mbedtls_mpi_free(&ctx->GX);\n    mbedtls_mpi_free(&ctx->X);\n    mbedtls_mpi_free(&ctx->G);\n    mbedtls_mpi_free(&ctx->P);\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_dhm_context));\n}\n\n#if defined(MBEDTLS_ASN1_PARSE_C)\n/*\n * Parse DHM parameters\n */\nint mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin,\n                          size_t dhminlen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n    unsigned char *p, *end;\n#if defined(MBEDTLS_PEM_PARSE_C)\n    mbedtls_pem_context pem;\n#endif /* MBEDTLS_PEM_PARSE_C */\n\n#if defined(MBEDTLS_PEM_PARSE_C)\n    mbedtls_pem_init(&pem);\n\n    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */\n    if (dhminlen == 0 || dhmin[dhminlen - 1] != '\\0') {\n        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;\n    } else {\n        ret = mbedtls_pem_read_buffer(&pem,\n                                      \"-----BEGIN DH PARAMETERS-----\",\n                                      \"-----END DH PARAMETERS-----\",\n                                      dhmin, NULL, 0, &dhminlen);\n    }\n\n    if (ret == 0) {\n        /*\n         * Was PEM encoded\n         */\n        dhminlen = pem.buflen;\n    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {\n        goto exit;\n    }\n\n    p = (ret == 0) ? pem.buf : (unsigned char *) dhmin;\n#else\n    p = (unsigned char *) dhmin;\n#endif /* MBEDTLS_PEM_PARSE_C */\n    end = p + dhminlen;\n\n    /*\n     *  DHParams ::= SEQUENCE {\n     *      prime              INTEGER,  -- P\n     *      generator          INTEGER,  -- g\n     *      privateValueLength INTEGER OPTIONAL\n     *  }\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);\n        goto exit;\n    }\n\n    end = p + len;\n\n    if ((ret = mbedtls_asn1_get_mpi(&p, end, &dhm->P)) != 0 ||\n        (ret = mbedtls_asn1_get_mpi(&p, end, &dhm->G)) != 0) {\n        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);\n        goto exit;\n    }\n\n    if (p != end) {\n        /* This might be the optional privateValueLength.\n         * If so, we can cleanly discard it */\n        mbedtls_mpi rec;\n        mbedtls_mpi_init(&rec);\n        ret = mbedtls_asn1_get_mpi(&p, end, &rec);\n        mbedtls_mpi_free(&rec);\n        if (ret != 0) {\n            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);\n            goto exit;\n        }\n        if (p != end) {\n            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT,\n                                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n            goto exit;\n        }\n    }\n\n    ret = 0;\n\nexit:\n#if defined(MBEDTLS_PEM_PARSE_C)\n    mbedtls_pem_free(&pem);\n#endif\n    if (ret != 0) {\n        mbedtls_dhm_free(dhm);\n    }\n\n    return ret;\n}\n\n#if defined(MBEDTLS_FS_IO)\n/*\n * Load all data from a file into a given buffer.\n *\n * The file is expected to contain either PEM or DER encoded data.\n * A terminating null byte is always appended. It is included in the announced\n * length only if the data looks like it is PEM encoded.\n */\nstatic int load_file(const char *path, unsigned char **buf, size_t *n)\n{\n    FILE *f;\n    long size;\n\n    if ((f = fopen(path, \"rb\")) == NULL) {\n        return MBEDTLS_ERR_DHM_FILE_IO_ERROR;\n    }\n    /* The data loaded here is public, so don't bother disabling buffering. */\n\n    fseek(f, 0, SEEK_END);\n    if ((size = ftell(f)) == -1) {\n        fclose(f);\n        return MBEDTLS_ERR_DHM_FILE_IO_ERROR;\n    }\n    fseek(f, 0, SEEK_SET);\n\n    *n = (size_t) size;\n\n    if (*n + 1 == 0 ||\n        (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {\n        fclose(f);\n        return MBEDTLS_ERR_DHM_ALLOC_FAILED;\n    }\n\n    if (fread(*buf, 1, *n, f) != *n) {\n        fclose(f);\n\n        mbedtls_zeroize_and_free(*buf, *n + 1);\n\n        return MBEDTLS_ERR_DHM_FILE_IO_ERROR;\n    }\n\n    fclose(f);\n\n    (*buf)[*n] = '\\0';\n\n    if (strstr((const char *) *buf, \"-----BEGIN \") != NULL) {\n        ++*n;\n    }\n\n    return 0;\n}\n\n/*\n * Load and parse DHM parameters\n */\nint mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t n;\n    unsigned char *buf;\n\n    if ((ret = load_file(path, &buf, &n)) != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_dhm_parse_dhm(dhm, buf, n);\n\n    mbedtls_zeroize_and_free(buf, n);\n\n    return ret;\n}\n#endif /* MBEDTLS_FS_IO */\n#endif /* MBEDTLS_ASN1_PARSE_C */\n#endif /* MBEDTLS_DHM_ALT */\n\n#if defined(MBEDTLS_SELF_TEST)\n\n#if defined(MBEDTLS_PEM_PARSE_C)\nstatic const char mbedtls_test_dhm_params[] =\n    \"-----BEGIN DH PARAMETERS-----\\r\\n\"\n    \"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\\r\\n\"\n    \"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\\r\\n\"\n    \"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\\r\\n\"\n    \"-----END DH PARAMETERS-----\\r\\n\";\n#else /* MBEDTLS_PEM_PARSE_C */\nstatic const char mbedtls_test_dhm_params[] = {\n    0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,\n    0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,\n    0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,\n    0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,\n    0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,\n    0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,\n    0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,\n    0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,\n    0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,\n    0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,\n    0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,\n    0x49, 0x75, 0xb3, 0x02, 0x01, 0x02\n};\n#endif /* MBEDTLS_PEM_PARSE_C */\n\nstatic const size_t mbedtls_test_dhm_params_len = sizeof(mbedtls_test_dhm_params);\n\n/*\n * Checkup routine\n */\nint mbedtls_dhm_self_test(int verbose)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_dhm_context dhm;\n\n    mbedtls_dhm_init(&dhm);\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  DHM parameter load: \");\n    }\n\n    if ((ret = mbedtls_dhm_parse_dhm(&dhm,\n                                     (const unsigned char *) mbedtls_test_dhm_params,\n                                     mbedtls_test_dhm_params_len)) != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n\n        ret = 1;\n        goto exit;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\\n\");\n    }\n\nexit:\n    mbedtls_dhm_free(&dhm);\n\n    return ret;\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_DHM_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ecdh.c",
    "content": "/*\n *  Elliptic curve Diffie-Hellman\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n * References:\n *\n * SEC1 https://www.secg.org/sec1-v2.pdf\n * RFC 4492\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_ECDH_C)\n\n#include \"mbedtls/ecdh.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\ntypedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;\n#endif\n\nstatic mbedtls_ecp_group_id mbedtls_ecdh_grp_id(\n    const mbedtls_ecdh_context *ctx)\n{\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n    return ctx->grp.id;\n#else\n    return ctx->grp_id;\n#endif\n}\n\nint mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid)\n{\n    /* At this time, all groups support ECDH. */\n    (void) gid;\n    return 1;\n}\n\n#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)\n/*\n * Generate public key (restartable version)\n *\n * Note: this internal function relies on its caller preserving the value of\n * the output parameter 'd' across continuation calls. This would not be\n * acceptable for a public function but is OK here as we control call sites.\n */\nstatic int ecdh_gen_public_restartable(mbedtls_ecp_group *grp,\n                                       mbedtls_mpi *d, mbedtls_ecp_point *Q,\n                                       int (*f_rng)(void *, unsigned char *, size_t),\n                                       void *p_rng,\n                                       mbedtls_ecp_restart_ctx *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    int restarting = 0;\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);\n#endif\n    /* If multiplication is in progress, we already generated a privkey */\n    if (!restarting) {\n        MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G,\n                                                f_rng, p_rng, rs_ctx));\n\ncleanup:\n    return ret;\n}\n\n/*\n * Generate public key\n */\nint mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,\n                            int (*f_rng)(void *, unsigned char *, size_t),\n                            void *p_rng)\n{\n    return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL);\n}\n#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */\n\n#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)\n/*\n * Compute shared secret (SEC1 3.3.1)\n */\nstatic int ecdh_compute_shared_restartable(mbedtls_ecp_group *grp,\n                                           mbedtls_mpi *z,\n                                           const mbedtls_ecp_point *Q, const mbedtls_mpi *d,\n                                           int (*f_rng)(void *, unsigned char *, size_t),\n                                           void *p_rng,\n                                           mbedtls_ecp_restart_ctx *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_point P;\n\n    mbedtls_ecp_point_init(&P);\n\n    MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q,\n                                                f_rng, p_rng, rs_ctx));\n\n    if (mbedtls_ecp_is_zero(&P)) {\n        ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X));\n\ncleanup:\n    mbedtls_ecp_point_free(&P);\n\n    return ret;\n}\n\n/*\n * Compute shared secret (SEC1 3.3.1)\n */\nint mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z,\n                                const mbedtls_ecp_point *Q, const mbedtls_mpi *d,\n                                int (*f_rng)(void *, unsigned char *, size_t),\n                                void *p_rng)\n{\n    return ecdh_compute_shared_restartable(grp, z, Q, d,\n                                           f_rng, p_rng, NULL);\n}\n#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */\n\nstatic void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)\n{\n    mbedtls_ecp_group_init(&ctx->grp);\n    mbedtls_mpi_init(&ctx->d);\n    mbedtls_ecp_point_init(&ctx->Q);\n    mbedtls_ecp_point_init(&ctx->Qp);\n    mbedtls_mpi_init(&ctx->z);\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    mbedtls_ecp_restart_init(&ctx->rs);\n#endif\n}\n\nmbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx)\n{\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n    return ctx->MBEDTLS_PRIVATE(grp).id;\n#else\n    return ctx->MBEDTLS_PRIVATE(grp_id);\n#endif\n}\n\n/*\n * Initialize context\n */\nvoid mbedtls_ecdh_init(mbedtls_ecdh_context *ctx)\n{\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n    ecdh_init_internal(ctx);\n    mbedtls_ecp_point_init(&ctx->Vi);\n    mbedtls_ecp_point_init(&ctx->Vf);\n    mbedtls_mpi_init(&ctx->_d);\n#else\n    memset(ctx, 0, sizeof(mbedtls_ecdh_context));\n\n    ctx->var = MBEDTLS_ECDH_VARIANT_NONE;\n#endif\n    ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    ctx->restart_enabled = 0;\n#endif\n}\n\nstatic int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,\n                               mbedtls_ecp_group_id grp_id)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);\n    if (ret != 0) {\n        return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n    }\n\n    return 0;\n}\n\n/*\n * Setup context\n */\nint mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id)\n{\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n    return ecdh_setup_internal(ctx, grp_id);\n#else\n    switch (grp_id) {\n#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)\n        case MBEDTLS_ECP_DP_CURVE25519:\n            ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;\n            ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;\n            ctx->grp_id = grp_id;\n            return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id);\n#endif\n        default:\n            ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;\n            ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;\n            ctx->grp_id = grp_id;\n            ecdh_init_internal(&ctx->ctx.mbed_ecdh);\n            return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id);\n    }\n#endif\n}\n\nstatic void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)\n{\n    mbedtls_ecp_group_free(&ctx->grp);\n    mbedtls_mpi_free(&ctx->d);\n    mbedtls_ecp_point_free(&ctx->Q);\n    mbedtls_ecp_point_free(&ctx->Qp);\n    mbedtls_mpi_free(&ctx->z);\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    mbedtls_ecp_restart_free(&ctx->rs);\n#endif\n}\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n/*\n * Enable restartable operations for context\n */\nvoid mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx)\n{\n    ctx->restart_enabled = 1;\n}\n#endif\n\n/*\n * Free context\n */\nvoid mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n    mbedtls_ecp_point_free(&ctx->Vi);\n    mbedtls_ecp_point_free(&ctx->Vf);\n    mbedtls_mpi_free(&ctx->_d);\n    ecdh_free_internal(ctx);\n#else\n    switch (ctx->var) {\n#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)\n        case MBEDTLS_ECDH_VARIANT_EVEREST:\n            mbedtls_everest_free(&ctx->ctx.everest_ecdh);\n            break;\n#endif\n        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:\n            ecdh_free_internal(&ctx->ctx.mbed_ecdh);\n            break;\n        default:\n            break;\n    }\n\n    ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;\n    ctx->var = MBEDTLS_ECDH_VARIANT_NONE;\n    ctx->grp_id = MBEDTLS_ECP_DP_NONE;\n#endif\n}\n\nstatic int ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx,\n                                     size_t *olen, int point_format,\n                                     unsigned char *buf, size_t blen,\n                                     int (*f_rng)(void *,\n                                                  unsigned char *,\n                                                  size_t),\n                                     void *p_rng,\n                                     int restart_enabled)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t grp_len, pt_len;\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    mbedtls_ecp_restart_ctx *rs_ctx = NULL;\n#endif\n\n    if (ctx->grp.pbits == 0) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (restart_enabled) {\n        rs_ctx = &ctx->rs;\n    }\n#else\n    (void) restart_enabled;\n#endif\n\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,\n                                           f_rng, p_rng, rs_ctx)) != 0) {\n        return ret;\n    }\n#else\n    if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,\n                                       f_rng, p_rng)) != 0) {\n        return ret;\n    }\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n    if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf,\n                                           blen)) != 0) {\n        return ret;\n    }\n\n    buf += grp_len;\n    blen -= grp_len;\n\n    if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format,\n                                           &pt_len, buf, blen)) != 0) {\n        return ret;\n    }\n\n    *olen = grp_len + pt_len;\n    return 0;\n}\n\n/*\n * Setup and write the ServerKeyExchange parameters (RFC 4492)\n *      struct {\n *          ECParameters    curve_params;\n *          ECPoint         public;\n *      } ServerECDHParams;\n */\nint mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen,\n                             unsigned char *buf, size_t blen,\n                             int (*f_rng)(void *, unsigned char *, size_t),\n                             void *p_rng)\n{\n    int restart_enabled = 0;\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    restart_enabled = ctx->restart_enabled;\n#else\n    (void) restart_enabled;\n#endif\n\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n    return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen,\n                                     f_rng, p_rng, restart_enabled);\n#else\n    switch (ctx->var) {\n#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)\n        case MBEDTLS_ECDH_VARIANT_EVEREST:\n            return mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen,\n                                               buf, blen, f_rng, p_rng);\n#endif\n        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:\n            return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen,\n                                             ctx->point_format, buf, blen,\n                                             f_rng, p_rng,\n                                             restart_enabled);\n        default:\n            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n#endif\n}\n\nstatic int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,\n                                     const unsigned char **buf,\n                                     const unsigned char *end)\n{\n    return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf,\n                                      (size_t) (end - *buf));\n}\n\n/*\n * Read the ServerKeyExchange parameters (RFC 4492)\n *      struct {\n *          ECParameters    curve_params;\n *          ECPoint         public;\n *      } ServerECDHParams;\n */\nint mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,\n                             const unsigned char **buf,\n                             const unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_group_id grp_id;\n    if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf)))\n        != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) {\n        return ret;\n    }\n\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n    return ecdh_read_params_internal(ctx, buf, end);\n#else\n    switch (ctx->var) {\n#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)\n        case MBEDTLS_ECDH_VARIANT_EVEREST:\n            return mbedtls_everest_read_params(&ctx->ctx.everest_ecdh,\n                                               buf, end);\n#endif\n        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:\n            return ecdh_read_params_internal(&ctx->ctx.mbed_ecdh,\n                                             buf, end);\n        default:\n            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n#endif\n}\n\nstatic int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx,\n                                    const mbedtls_ecp_keypair *key,\n                                    mbedtls_ecdh_side side)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* If it's not our key, just import the public part as Qp */\n    if (side == MBEDTLS_ECDH_THEIRS) {\n        return mbedtls_ecp_copy(&ctx->Qp, &key->Q);\n    }\n\n    /* Our key: import public (as Q) and private parts */\n    if (side != MBEDTLS_ECDH_OURS) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||\n        (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\n/*\n * Get parameters from a keypair\n */\nint mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx,\n                            const mbedtls_ecp_keypair *key,\n                            mbedtls_ecdh_side side)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) {\n        /* This is the first call to get_params(). Set up the context\n         * for use with the group. */\n        if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) {\n            return ret;\n        }\n    } else {\n        /* This is not the first call to get_params(). Check that the\n         * current key's group is the same as the context's, which was set\n         * from the first key's group. */\n        if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) {\n            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n        }\n    }\n\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n    return ecdh_get_params_internal(ctx, key, side);\n#else\n    switch (ctx->var) {\n#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)\n        case MBEDTLS_ECDH_VARIANT_EVEREST:\n        {\n            mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?\n                                          MBEDTLS_EVEREST_ECDH_OURS :\n                                          MBEDTLS_EVEREST_ECDH_THEIRS;\n            return mbedtls_everest_get_params(&ctx->ctx.everest_ecdh,\n                                              key, s);\n        }\n#endif\n        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:\n            return ecdh_get_params_internal(&ctx->ctx.mbed_ecdh,\n                                            key, side);\n        default:\n            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n#endif\n}\n\nstatic int ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx,\n                                     size_t *olen, int point_format,\n                                     unsigned char *buf, size_t blen,\n                                     int (*f_rng)(void *,\n                                                  unsigned char *,\n                                                  size_t),\n                                     void *p_rng,\n                                     int restart_enabled)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    mbedtls_ecp_restart_ctx *rs_ctx = NULL;\n#endif\n\n    if (ctx->grp.pbits == 0) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (restart_enabled) {\n        rs_ctx = &ctx->rs;\n    }\n#else\n    (void) restart_enabled;\n#endif\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,\n                                           f_rng, p_rng, rs_ctx)) != 0) {\n        return ret;\n    }\n#else\n    if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,\n                                       f_rng, p_rng)) != 0) {\n        return ret;\n    }\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n    return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen,\n                                       buf, blen);\n}\n\n/*\n * Setup and export the client public value\n */\nint mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen,\n                             unsigned char *buf, size_t blen,\n                             int (*f_rng)(void *, unsigned char *, size_t),\n                             void *p_rng)\n{\n    int restart_enabled = 0;\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    restart_enabled = ctx->restart_enabled;\n#endif\n\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n    return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen,\n                                     f_rng, p_rng, restart_enabled);\n#else\n    switch (ctx->var) {\n#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)\n        case MBEDTLS_ECDH_VARIANT_EVEREST:\n            return mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen,\n                                               buf, blen, f_rng, p_rng);\n#endif\n        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:\n            return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen,\n                                             ctx->point_format, buf, blen,\n                                             f_rng, p_rng,\n                                             restart_enabled);\n        default:\n            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n#endif\n}\n\nstatic int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx,\n                                     const unsigned char *buf, size_t blen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const unsigned char *p = buf;\n\n    if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p,\n                                          blen)) != 0) {\n        return ret;\n    }\n\n    if ((size_t) (p - buf) != blen) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    return 0;\n}\n\n/*\n * Parse and import the client's public value\n */\nint mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx,\n                             const unsigned char *buf, size_t blen)\n{\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n    return ecdh_read_public_internal(ctx, buf, blen);\n#else\n    switch (ctx->var) {\n#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)\n        case MBEDTLS_ECDH_VARIANT_EVEREST:\n            return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh,\n                                               buf, blen);\n#endif\n        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:\n            return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh,\n                                             buf, blen);\n        default:\n            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n#endif\n}\n\nstatic int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx,\n                                     size_t *olen, unsigned char *buf,\n                                     size_t blen,\n                                     int (*f_rng)(void *,\n                                                  unsigned char *,\n                                                  size_t),\n                                     void *p_rng,\n                                     int restart_enabled)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    mbedtls_ecp_restart_ctx *rs_ctx = NULL;\n#endif\n\n    if (ctx == NULL || ctx->grp.pbits == 0) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (restart_enabled) {\n        rs_ctx = &ctx->rs;\n    }\n#else\n    (void) restart_enabled;\n#endif\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp,\n                                               &ctx->d, f_rng, p_rng,\n                                               rs_ctx)) != 0) {\n        return ret;\n    }\n#else\n    if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp,\n                                           &ctx->d, f_rng, p_rng)) != 0) {\n        return ret;\n    }\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n    if (mbedtls_mpi_size(&ctx->z) > blen) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);\n\n    if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {\n        return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen);\n    }\n\n    return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);\n}\n\n/*\n * Derive and export the shared secret\n */\nint mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen,\n                             unsigned char *buf, size_t blen,\n                             int (*f_rng)(void *, unsigned char *, size_t),\n                             void *p_rng)\n{\n    int restart_enabled = 0;\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    restart_enabled = ctx->restart_enabled;\n#endif\n\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n    return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng,\n                                     restart_enabled);\n#else\n    switch (ctx->var) {\n#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)\n        case MBEDTLS_ECDH_VARIANT_EVEREST:\n            return mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen,\n                                               buf, blen, f_rng, p_rng);\n#endif\n        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:\n            return ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf,\n                                             blen, f_rng, p_rng,\n                                             restart_enabled);\n        default:\n            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n#endif\n}\n#endif /* MBEDTLS_ECDH_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ecdsa.c",
    "content": "/*\n *  Elliptic curve DSA\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n * References:\n *\n * SEC1 https://www.secg.org/sec1-v2.pdf\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_ECDSA_C)\n\n#include \"mbedtls/ecdsa.h\"\n#include \"mbedtls/asn1write.h\"\n#include \"bignum_internal.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC)\n#include \"mbedtls/hmac_drbg.h\"\n#endif\n\n#include \"mbedtls/platform.h\"\n\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n\n/*\n * Sub-context for ecdsa_verify()\n */\nstruct mbedtls_ecdsa_restart_ver {\n    mbedtls_mpi u1, u2;     /* intermediate values  */\n    enum {                  /* what to do next?     */\n        ecdsa_ver_init = 0, /* getting started      */\n        ecdsa_ver_muladd,   /* muladd step          */\n    } state;\n};\n\n/*\n * Init verify restart sub-context\n */\nstatic void ecdsa_restart_ver_init(mbedtls_ecdsa_restart_ver_ctx *ctx)\n{\n    mbedtls_mpi_init(&ctx->u1);\n    mbedtls_mpi_init(&ctx->u2);\n    ctx->state = ecdsa_ver_init;\n}\n\n/*\n * Free the components of a verify restart sub-context\n */\nstatic void ecdsa_restart_ver_free(mbedtls_ecdsa_restart_ver_ctx *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_mpi_free(&ctx->u1);\n    mbedtls_mpi_free(&ctx->u2);\n\n    ecdsa_restart_ver_init(ctx);\n}\n\n/*\n * Sub-context for ecdsa_sign()\n */\nstruct mbedtls_ecdsa_restart_sig {\n    int sign_tries;\n    int key_tries;\n    mbedtls_mpi k;          /* per-signature random */\n    mbedtls_mpi r;          /* r value              */\n    enum {                  /* what to do next?     */\n        ecdsa_sig_init = 0, /* getting started      */\n        ecdsa_sig_mul,      /* doing ecp_mul()      */\n        ecdsa_sig_modn,     /* mod N computations   */\n    } state;\n};\n\n/*\n * Init verify sign sub-context\n */\nstatic void ecdsa_restart_sig_init(mbedtls_ecdsa_restart_sig_ctx *ctx)\n{\n    ctx->sign_tries = 0;\n    ctx->key_tries = 0;\n    mbedtls_mpi_init(&ctx->k);\n    mbedtls_mpi_init(&ctx->r);\n    ctx->state = ecdsa_sig_init;\n}\n\n/*\n * Free the components of a sign restart sub-context\n */\nstatic void ecdsa_restart_sig_free(mbedtls_ecdsa_restart_sig_ctx *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_mpi_free(&ctx->k);\n    mbedtls_mpi_free(&ctx->r);\n}\n\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC)\n/*\n * Sub-context for ecdsa_sign_det()\n */\nstruct mbedtls_ecdsa_restart_det {\n    mbedtls_hmac_drbg_context rng_ctx;  /* DRBG state   */\n    enum {                      /* what to do next?     */\n        ecdsa_det_init = 0,     /* getting started      */\n        ecdsa_det_sign,         /* make signature       */\n    } state;\n};\n\n/*\n * Init verify sign_det sub-context\n */\nstatic void ecdsa_restart_det_init(mbedtls_ecdsa_restart_det_ctx *ctx)\n{\n    mbedtls_hmac_drbg_init(&ctx->rng_ctx);\n    ctx->state = ecdsa_det_init;\n}\n\n/*\n * Free the components of a sign_det restart sub-context\n */\nstatic void ecdsa_restart_det_free(mbedtls_ecdsa_restart_det_ctx *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_hmac_drbg_free(&ctx->rng_ctx);\n\n    ecdsa_restart_det_init(ctx);\n}\n#endif /* MBEDTLS_ECDSA_DETERMINISTIC */\n\n#define ECDSA_RS_ECP    (rs_ctx == NULL ? NULL : &rs_ctx->ecp)\n\n/* Utility macro for checking and updating ops budget */\n#define ECDSA_BUDGET(ops)   \\\n    MBEDTLS_MPI_CHK(mbedtls_ecp_check_budget(grp, ECDSA_RS_ECP, ops));\n\n/* Call this when entering a function that needs its own sub-context */\n#define ECDSA_RS_ENTER(SUB)   do {                                 \\\n        /* reset ops count for this call if top-level */                 \\\n        if (rs_ctx != NULL && rs_ctx->ecp.depth++ == 0)                 \\\n        rs_ctx->ecp.ops_done = 0;                                    \\\n                                                                     \\\n        /* set up our own sub-context if needed */                       \\\n        if (mbedtls_ecp_restart_is_enabled() &&                          \\\n            rs_ctx != NULL && rs_ctx->SUB == NULL)                      \\\n        {                                                                \\\n            rs_ctx->SUB = mbedtls_calloc(1, sizeof(*rs_ctx->SUB));   \\\n            if (rs_ctx->SUB == NULL)                                    \\\n            return MBEDTLS_ERR_ECP_ALLOC_FAILED;                  \\\n                                                                   \\\n            ecdsa_restart_## SUB ##_init(rs_ctx->SUB);                 \\\n        }                                                                \\\n} while (0)\n\n/* Call this when leaving a function that needs its own sub-context */\n#define ECDSA_RS_LEAVE(SUB)   do {                                 \\\n        /* clear our sub-context when not in progress (done or error) */ \\\n        if (rs_ctx != NULL && rs_ctx->SUB != NULL &&                     \\\n            ret != MBEDTLS_ERR_ECP_IN_PROGRESS)                         \\\n        {                                                                \\\n            ecdsa_restart_## SUB ##_free(rs_ctx->SUB);                 \\\n            mbedtls_free(rs_ctx->SUB);                                 \\\n            rs_ctx->SUB = NULL;                                          \\\n        }                                                                \\\n                                                                     \\\n        if (rs_ctx != NULL)                                             \\\n        rs_ctx->ecp.depth--;                                         \\\n} while (0)\n\n#else /* MBEDTLS_ECP_RESTARTABLE */\n\n#define ECDSA_RS_ECP    NULL\n\n#define ECDSA_BUDGET(ops)     /* no-op; for compatibility */\n\n#define ECDSA_RS_ENTER(SUB)   (void) rs_ctx\n#define ECDSA_RS_LEAVE(SUB)   (void) rs_ctx\n\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \\\n    !defined(MBEDTLS_ECDSA_SIGN_ALT)     || \\\n    !defined(MBEDTLS_ECDSA_VERIFY_ALT)\n/*\n * Derive a suitable integer for group grp from a buffer of length len\n * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3\n */\nstatic int derive_mpi(const mbedtls_ecp_group *grp, mbedtls_mpi *x,\n                      const unsigned char *buf, size_t blen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t n_size = (grp->nbits + 7) / 8;\n    size_t use_size = blen > n_size ? n_size : blen;\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(x, buf, use_size));\n    if (use_size * 8 > grp->nbits) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(x, use_size * 8 - grp->nbits));\n    }\n\n    /* While at it, reduce modulo N */\n    if (mbedtls_mpi_cmp_mpi(x, &grp->N) >= 0) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(x, x, &grp->N));\n    }\n\ncleanup:\n    return ret;\n}\n#endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */\n\nint mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid)\n{\n    switch (gid) {\n#ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED\n        case MBEDTLS_ECP_DP_CURVE25519: return 0;\n#endif\n#ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED\n        case MBEDTLS_ECP_DP_CURVE448: return 0;\n#endif\n        default: return 1;\n    }\n}\n\n#if !defined(MBEDTLS_ECDSA_SIGN_ALT)\n/*\n * Compute ECDSA signature of a hashed message (SEC1 4.1.3)\n * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)\n */\nint mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp,\n                                   mbedtls_mpi *r, mbedtls_mpi *s,\n                                   const mbedtls_mpi *d, const unsigned char *buf, size_t blen,\n                                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,\n                                   int (*f_rng_blind)(void *, unsigned char *, size_t),\n                                   void *p_rng_blind,\n                                   mbedtls_ecdsa_restart_ctx *rs_ctx)\n{\n    int ret, key_tries, sign_tries;\n    int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries;\n    mbedtls_ecp_point R;\n    mbedtls_mpi k, e;\n    mbedtls_mpi *pk = &k, *pr = r;\n\n    /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */\n    if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    /* Make sure d is in range 1..n-1 */\n    if (mbedtls_mpi_cmp_int(d, 1) < 0 || mbedtls_mpi_cmp_mpi(d, &grp->N) >= 0) {\n        return MBEDTLS_ERR_ECP_INVALID_KEY;\n    }\n\n    mbedtls_ecp_point_init(&R);\n    mbedtls_mpi_init(&k); mbedtls_mpi_init(&e);\n\n    ECDSA_RS_ENTER(sig);\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->sig != NULL) {\n        /* redirect to our context */\n        p_sign_tries = &rs_ctx->sig->sign_tries;\n        p_key_tries = &rs_ctx->sig->key_tries;\n        pk = &rs_ctx->sig->k;\n        pr = &rs_ctx->sig->r;\n\n        /* jump to current step */\n        if (rs_ctx->sig->state == ecdsa_sig_mul) {\n            goto mul;\n        }\n        if (rs_ctx->sig->state == ecdsa_sig_modn) {\n            goto modn;\n        }\n    }\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n    *p_sign_tries = 0;\n    do {\n        if ((*p_sign_tries)++ > 10) {\n            ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;\n            goto cleanup;\n        }\n\n        /*\n         * Steps 1-3: generate a suitable ephemeral keypair\n         * and set r = xR mod n\n         */\n        *p_key_tries = 0;\n        do {\n            if ((*p_key_tries)++ > 10) {\n                ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;\n                goto cleanup;\n            }\n\n            MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, pk, f_rng, p_rng));\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n            if (rs_ctx != NULL && rs_ctx->sig != NULL) {\n                rs_ctx->sig->state = ecdsa_sig_mul;\n            }\n\nmul:\n#endif\n            MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &R, pk, &grp->G,\n                                                        f_rng_blind,\n                                                        p_rng_blind,\n                                                        ECDSA_RS_ECP));\n            MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pr, &R.X, &grp->N));\n        } while (mbedtls_mpi_cmp_int(pr, 0) == 0);\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n        if (rs_ctx != NULL && rs_ctx->sig != NULL) {\n            rs_ctx->sig->state = ecdsa_sig_modn;\n        }\n\nmodn:\n#endif\n        /*\n         * Accounting for everything up to the end of the loop\n         * (step 6, but checking now avoids saving e and t)\n         */\n        ECDSA_BUDGET(MBEDTLS_ECP_OPS_INV + 4);\n\n        /*\n         * Step 5: derive MPI from hashed message\n         */\n        MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen));\n\n        /*\n         * Step 6: compute s = (e + r * d) / k\n         */\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, pr, d));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&e, &e, s));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(NULL, s, pk, &grp->N));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, s, &e));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(s, s, &grp->N));\n    } while (mbedtls_mpi_cmp_int(s, 0) == 0);\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->sig != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(r, pr));\n    }\n#endif\n\ncleanup:\n    mbedtls_ecp_point_free(&R);\n    mbedtls_mpi_free(&k); mbedtls_mpi_free(&e);\n\n    ECDSA_RS_LEAVE(sig);\n\n    return ret;\n}\n\n/*\n * Compute ECDSA signature of a hashed message\n */\nint mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,\n                       const mbedtls_mpi *d, const unsigned char *buf, size_t blen,\n                       int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    /* Use the same RNG for both blinding and ephemeral key generation */\n    return mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen,\n                                          f_rng, p_rng, f_rng, p_rng, NULL);\n}\n#endif /* !MBEDTLS_ECDSA_SIGN_ALT */\n\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC)\n/*\n * Deterministic signature wrapper\n *\n * note:    The f_rng_blind parameter must not be NULL.\n *\n */\nint mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group *grp,\n                                       mbedtls_mpi *r, mbedtls_mpi *s,\n                                       const mbedtls_mpi *d, const unsigned char *buf, size_t blen,\n                                       mbedtls_md_type_t md_alg,\n                                       int (*f_rng_blind)(void *, unsigned char *, size_t),\n                                       void *p_rng_blind,\n                                       mbedtls_ecdsa_restart_ctx *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_hmac_drbg_context rng_ctx;\n    mbedtls_hmac_drbg_context *p_rng = &rng_ctx;\n    unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];\n    size_t grp_len = (grp->nbits + 7) / 8;\n    const mbedtls_md_info_t *md_info;\n    mbedtls_mpi h;\n\n    if ((md_info = mbedtls_md_info_from_type(md_alg)) == NULL) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    mbedtls_mpi_init(&h);\n    mbedtls_hmac_drbg_init(&rng_ctx);\n\n    ECDSA_RS_ENTER(det);\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->det != NULL) {\n        /* redirect to our context */\n        p_rng = &rs_ctx->det->rng_ctx;\n\n        /* jump to current step */\n        if (rs_ctx->det->state == ecdsa_det_sign) {\n            goto sign;\n        }\n    }\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n    /* Use private key and message hash (reduced) to initialize HMAC_DRBG */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(d, data, grp_len));\n    MBEDTLS_MPI_CHK(derive_mpi(grp, &h, buf, blen));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, data + grp_len, grp_len));\n    MBEDTLS_MPI_CHK(mbedtls_hmac_drbg_seed_buf(p_rng, md_info, data, 2 * grp_len));\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->det != NULL) {\n        rs_ctx->det->state = ecdsa_det_sign;\n    }\n\nsign:\n#endif\n#if defined(MBEDTLS_ECDSA_SIGN_ALT)\n    (void) f_rng_blind;\n    (void) p_rng_blind;\n    ret = mbedtls_ecdsa_sign(grp, r, s, d, buf, blen,\n                             mbedtls_hmac_drbg_random, p_rng);\n#else\n    ret = mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen,\n                                         mbedtls_hmac_drbg_random, p_rng,\n                                         f_rng_blind, p_rng_blind, rs_ctx);\n#endif /* MBEDTLS_ECDSA_SIGN_ALT */\n\ncleanup:\n    mbedtls_hmac_drbg_free(&rng_ctx);\n    mbedtls_mpi_free(&h);\n\n    ECDSA_RS_LEAVE(det);\n\n    return ret;\n}\n\n/*\n * Deterministic signature wrapper\n */\nint mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r,\n                               mbedtls_mpi *s, const mbedtls_mpi *d,\n                               const unsigned char *buf, size_t blen,\n                               mbedtls_md_type_t md_alg,\n                               int (*f_rng_blind)(void *, unsigned char *,\n                                                  size_t),\n                               void *p_rng_blind)\n{\n    return mbedtls_ecdsa_sign_det_restartable(grp, r, s, d, buf, blen, md_alg,\n                                              f_rng_blind, p_rng_blind, NULL);\n}\n#endif /* MBEDTLS_ECDSA_DETERMINISTIC */\n\n#if !defined(MBEDTLS_ECDSA_VERIFY_ALT)\n/*\n * Verify ECDSA signature of hashed message (SEC1 4.1.4)\n * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)\n */\nint mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp,\n                                     const unsigned char *buf, size_t blen,\n                                     const mbedtls_ecp_point *Q,\n                                     const mbedtls_mpi *r,\n                                     const mbedtls_mpi *s,\n                                     mbedtls_ecdsa_restart_ctx *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi e, s_inv, u1, u2;\n    mbedtls_ecp_point R;\n    mbedtls_mpi *pu1 = &u1, *pu2 = &u2;\n\n    mbedtls_ecp_point_init(&R);\n    mbedtls_mpi_init(&e); mbedtls_mpi_init(&s_inv);\n    mbedtls_mpi_init(&u1); mbedtls_mpi_init(&u2);\n\n    /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */\n    if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    ECDSA_RS_ENTER(ver);\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->ver != NULL) {\n        /* redirect to our context */\n        pu1 = &rs_ctx->ver->u1;\n        pu2 = &rs_ctx->ver->u2;\n\n        /* jump to current step */\n        if (rs_ctx->ver->state == ecdsa_ver_muladd) {\n            goto muladd;\n        }\n    }\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n    /*\n     * Step 1: make sure r and s are in range 1..n-1\n     */\n    if (mbedtls_mpi_cmp_int(r, 1) < 0 || mbedtls_mpi_cmp_mpi(r, &grp->N) >= 0 ||\n        mbedtls_mpi_cmp_int(s, 1) < 0 || mbedtls_mpi_cmp_mpi(s, &grp->N) >= 0) {\n        ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;\n        goto cleanup;\n    }\n\n    /*\n     * Step 3: derive MPI from hashed message\n     */\n    MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen));\n\n    /*\n     * Step 4: u1 = e / s mod n, u2 = r / s mod n\n     */\n    ECDSA_BUDGET(MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2);\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(NULL, &s_inv, s, &grp->N));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu1, &e, &s_inv));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu1, pu1, &grp->N));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu2, r, &s_inv));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu2, pu2, &grp->N));\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->ver != NULL) {\n        rs_ctx->ver->state = ecdsa_ver_muladd;\n    }\n\nmuladd:\n#endif\n    /*\n     * Step 5: R = u1 G + u2 Q\n     */\n    MBEDTLS_MPI_CHK(mbedtls_ecp_muladd_restartable(grp,\n                                                   &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP));\n\n    if (mbedtls_ecp_is_zero(&R)) {\n        ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;\n        goto cleanup;\n    }\n\n    /*\n     * Step 6: convert xR to an integer (no-op)\n     * Step 7: reduce xR mod n (gives v)\n     */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&R.X, &R.X, &grp->N));\n\n    /*\n     * Step 8: check if v (that is, R.X) is equal to r\n     */\n    if (mbedtls_mpi_cmp_mpi(&R.X, r) != 0) {\n        ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;\n        goto cleanup;\n    }\n\ncleanup:\n    mbedtls_ecp_point_free(&R);\n    mbedtls_mpi_free(&e); mbedtls_mpi_free(&s_inv);\n    mbedtls_mpi_free(&u1); mbedtls_mpi_free(&u2);\n\n    ECDSA_RS_LEAVE(ver);\n\n    return ret;\n}\n\n/*\n * Verify ECDSA signature of hashed message\n */\nint mbedtls_ecdsa_verify(mbedtls_ecp_group *grp,\n                         const unsigned char *buf, size_t blen,\n                         const mbedtls_ecp_point *Q,\n                         const mbedtls_mpi *r,\n                         const mbedtls_mpi *s)\n{\n    return mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, NULL);\n}\n#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */\n\n/*\n * Convert a signature (given by context) to ASN.1\n */\nstatic int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s,\n                                   unsigned char *sig, size_t sig_size,\n                                   size_t *slen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 };\n    unsigned char *p = buf + sizeof(buf);\n    size_t len = 0;\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, s));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, r));\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, buf,\n                                                     MBEDTLS_ASN1_CONSTRUCTED |\n                                                     MBEDTLS_ASN1_SEQUENCE));\n\n    if (len > sig_size) {\n        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n    }\n\n    memcpy(sig, p, len);\n    *slen = len;\n\n    return 0;\n}\n\n/*\n * Compute and write signature\n */\nint mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx,\n                                              mbedtls_md_type_t md_alg,\n                                              const unsigned char *hash, size_t hlen,\n                                              unsigned char *sig, size_t sig_size, size_t *slen,\n                                              int (*f_rng)(void *, unsigned char *, size_t),\n                                              void *p_rng,\n                                              mbedtls_ecdsa_restart_ctx *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi r, s;\n    if (f_rng == NULL) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    mbedtls_mpi_init(&r);\n    mbedtls_mpi_init(&s);\n\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC)\n    MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_restartable(&ctx->grp, &r, &s, &ctx->d,\n                                                       hash, hlen, md_alg, f_rng,\n                                                       p_rng, rs_ctx));\n#else\n    (void) md_alg;\n\n#if defined(MBEDTLS_ECDSA_SIGN_ALT)\n    (void) rs_ctx;\n\n    MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ctx->grp, &r, &s, &ctx->d,\n                                       hash, hlen, f_rng, p_rng));\n#else\n    /* Use the same RNG for both blinding and ephemeral key generation */\n    MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_restartable(&ctx->grp, &r, &s, &ctx->d,\n                                                   hash, hlen, f_rng, p_rng, f_rng,\n                                                   p_rng, rs_ctx));\n#endif /* MBEDTLS_ECDSA_SIGN_ALT */\n#endif /* MBEDTLS_ECDSA_DETERMINISTIC */\n\n    MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, sig_size, slen));\n\ncleanup:\n    mbedtls_mpi_free(&r);\n    mbedtls_mpi_free(&s);\n\n    return ret;\n}\n\n/*\n * Compute and write signature\n */\nint mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx,\n                                  mbedtls_md_type_t md_alg,\n                                  const unsigned char *hash, size_t hlen,\n                                  unsigned char *sig, size_t sig_size, size_t *slen,\n                                  int (*f_rng)(void *, unsigned char *, size_t),\n                                  void *p_rng)\n{\n    return mbedtls_ecdsa_write_signature_restartable(\n        ctx, md_alg, hash, hlen, sig, sig_size, slen,\n        f_rng, p_rng, NULL);\n}\n\n/*\n * Read and check signature\n */\nint mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx,\n                                 const unsigned char *hash, size_t hlen,\n                                 const unsigned char *sig, size_t slen)\n{\n    return mbedtls_ecdsa_read_signature_restartable(\n        ctx, hash, hlen, sig, slen, NULL);\n}\n\n/*\n * Restartable read and check signature\n */\nint mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx,\n                                             const unsigned char *hash, size_t hlen,\n                                             const unsigned char *sig, size_t slen,\n                                             mbedtls_ecdsa_restart_ctx *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = (unsigned char *) sig;\n    const unsigned char *end = sig + slen;\n    size_t len;\n    mbedtls_mpi r, s;\n    mbedtls_mpi_init(&r);\n    mbedtls_mpi_init(&s);\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n\n    if (p + len != end) {\n        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_ECP_BAD_INPUT_DATA,\n                                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n        goto cleanup;\n    }\n\n    if ((ret = mbedtls_asn1_get_mpi(&p, end, &r)) != 0 ||\n        (ret = mbedtls_asn1_get_mpi(&p, end, &s)) != 0) {\n        ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n#if defined(MBEDTLS_ECDSA_VERIFY_ALT)\n    (void) rs_ctx;\n\n    if ((ret = mbedtls_ecdsa_verify(&ctx->grp, hash, hlen,\n                                    &ctx->Q, &r, &s)) != 0) {\n        goto cleanup;\n    }\n#else\n    if ((ret = mbedtls_ecdsa_verify_restartable(&ctx->grp, hash, hlen,\n                                                &ctx->Q, &r, &s, rs_ctx)) != 0) {\n        goto cleanup;\n    }\n#endif /* MBEDTLS_ECDSA_VERIFY_ALT */\n\n    /* At this point we know that the buffer starts with a valid signature.\n     * Return 0 if the buffer just contains the signature, and a specific\n     * error code if the valid signature is followed by more data. */\n    if (p != end) {\n        ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH;\n    }\n\ncleanup:\n    mbedtls_mpi_free(&r);\n    mbedtls_mpi_free(&s);\n\n    return ret;\n}\n\n#if !defined(MBEDTLS_ECDSA_GENKEY_ALT)\n/*\n * Generate key pair\n */\nint mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,\n                         int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    int ret = 0;\n    ret = mbedtls_ecp_group_load(&ctx->grp, gid);\n    if (ret != 0) {\n        return ret;\n    }\n\n    return mbedtls_ecp_gen_keypair(&ctx->grp, &ctx->d,\n                                   &ctx->Q, f_rng, p_rng);\n}\n#endif /* !MBEDTLS_ECDSA_GENKEY_ALT */\n\n/*\n * Set context from an mbedtls_ecp_keypair\n */\nint mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    if ((ret = mbedtls_ecp_group_copy(&ctx->grp, &key->grp)) != 0 ||\n        (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0 ||\n        (ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0) {\n        mbedtls_ecdsa_free(ctx);\n    }\n\n    return ret;\n}\n\n/*\n * Initialize context\n */\nvoid mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx)\n{\n    mbedtls_ecp_keypair_init(ctx);\n}\n\n/*\n * Free context\n */\nvoid mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_ecp_keypair_free(ctx);\n}\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n/*\n * Initialize a restart context\n */\nvoid mbedtls_ecdsa_restart_init(mbedtls_ecdsa_restart_ctx *ctx)\n{\n    mbedtls_ecp_restart_init(&ctx->ecp);\n\n    ctx->ver = NULL;\n    ctx->sig = NULL;\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC)\n    ctx->det = NULL;\n#endif\n}\n\n/*\n * Free the components of a restart context\n */\nvoid mbedtls_ecdsa_restart_free(mbedtls_ecdsa_restart_ctx *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_ecp_restart_free(&ctx->ecp);\n\n    ecdsa_restart_ver_free(ctx->ver);\n    mbedtls_free(ctx->ver);\n    ctx->ver = NULL;\n\n    ecdsa_restart_sig_free(ctx->sig);\n    mbedtls_free(ctx->sig);\n    ctx->sig = NULL;\n\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC)\n    ecdsa_restart_det_free(ctx->det);\n    mbedtls_free(ctx->det);\n    ctx->det = NULL;\n#endif\n}\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n#endif /* MBEDTLS_ECDSA_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ecjpake.c",
    "content": "/*\n *  Elliptic curve J-PAKE\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n * References in the code are to the Thread v1.0 Specification,\n * available to members of the Thread Group http://threadgroup.org/\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_ECJPAKE_C)\n\n#include \"mbedtls/ecjpake.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#if !defined(MBEDTLS_ECJPAKE_ALT)\n\n/*\n * Convert a mbedtls_ecjpake_role to identifier string\n */\nstatic const char * const ecjpake_id[] = {\n    \"client\",\n    \"server\"\n};\n\n#define ID_MINE     (ecjpake_id[ctx->role])\n#define ID_PEER     (ecjpake_id[1 - ctx->role])\n\n/**\n * Helper to Compute a hash from md_type\n */\nstatic int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,\n                                        const unsigned char *input, size_t ilen,\n                                        unsigned char *output)\n{\n    return mbedtls_md(mbedtls_md_info_from_type(md_type),\n                      input, ilen, output);\n}\n\n/*\n * Initialize context\n */\nvoid mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)\n{\n    ctx->md_type = MBEDTLS_MD_NONE;\n    mbedtls_ecp_group_init(&ctx->grp);\n    ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;\n\n    mbedtls_ecp_point_init(&ctx->Xm1);\n    mbedtls_ecp_point_init(&ctx->Xm2);\n    mbedtls_ecp_point_init(&ctx->Xp1);\n    mbedtls_ecp_point_init(&ctx->Xp2);\n    mbedtls_ecp_point_init(&ctx->Xp);\n\n    mbedtls_mpi_init(&ctx->xm1);\n    mbedtls_mpi_init(&ctx->xm2);\n    mbedtls_mpi_init(&ctx->s);\n}\n\n/*\n * Free context\n */\nvoid mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    ctx->md_type = MBEDTLS_MD_NONE;\n    mbedtls_ecp_group_free(&ctx->grp);\n\n    mbedtls_ecp_point_free(&ctx->Xm1);\n    mbedtls_ecp_point_free(&ctx->Xm2);\n    mbedtls_ecp_point_free(&ctx->Xp1);\n    mbedtls_ecp_point_free(&ctx->Xp2);\n    mbedtls_ecp_point_free(&ctx->Xp);\n\n    mbedtls_mpi_free(&ctx->xm1);\n    mbedtls_mpi_free(&ctx->xm2);\n    mbedtls_mpi_free(&ctx->s);\n}\n\n/*\n * Setup context\n */\nint mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,\n                          mbedtls_ecjpake_role role,\n                          mbedtls_md_type_t hash,\n                          mbedtls_ecp_group_id curve,\n                          const unsigned char *secret,\n                          size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    ctx->role = role;\n\n    if ((mbedtls_md_info_from_type(hash)) == NULL) {\n        return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;\n    }\n\n    ctx->md_type = hash;\n\n    MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));\n\ncleanup:\n    if (ret != 0) {\n        mbedtls_ecjpake_free(ctx);\n    }\n\n    return ret;\n}\n\nint mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,\n                                     int point_format)\n{\n    switch (point_format) {\n        case MBEDTLS_ECP_PF_UNCOMPRESSED:\n        case MBEDTLS_ECP_PF_COMPRESSED:\n            ctx->point_format = point_format;\n            return 0;\n        default:\n            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n}\n\n/*\n * Check if context is ready for use\n */\nint mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)\n{\n    if (ctx->md_type == MBEDTLS_MD_NONE ||\n        ctx->grp.id == MBEDTLS_ECP_DP_NONE ||\n        ctx->s.p == NULL) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    return 0;\n}\n\n/*\n * Write a point plus its length to a buffer\n */\nstatic int ecjpake_write_len_point(unsigned char **p,\n                                   const unsigned char *end,\n                                   const mbedtls_ecp_group *grp,\n                                   const int pf,\n                                   const mbedtls_ecp_point *P)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n\n    /* Need at least 4 for length plus 1 for point */\n    if (end < *p || end - *p < 5) {\n        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n    }\n\n    ret = mbedtls_ecp_point_write_binary(grp, P, pf,\n                                         &len, *p + 4, (size_t) (end - (*p + 4)));\n    if (ret != 0) {\n        return ret;\n    }\n\n    MBEDTLS_PUT_UINT32_BE(len, *p, 0);\n\n    *p += 4 + len;\n\n    return 0;\n}\n\n/*\n * Size of the temporary buffer for ecjpake_hash:\n * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)\n */\n#define ECJPAKE_HASH_BUF_LEN    (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)\n\n/*\n * Compute hash for ZKP (7.4.2.2.2.1)\n */\nstatic int ecjpake_hash(const mbedtls_md_type_t md_type,\n                        const mbedtls_ecp_group *grp,\n                        const int pf,\n                        const mbedtls_ecp_point *G,\n                        const mbedtls_ecp_point *V,\n                        const mbedtls_ecp_point *X,\n                        const char *id,\n                        mbedtls_mpi *h)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char buf[ECJPAKE_HASH_BUF_LEN];\n    unsigned char *p = buf;\n    const unsigned char *end = buf + sizeof(buf);\n    const size_t id_len = strlen(id);\n    unsigned char hash[MBEDTLS_MD_MAX_SIZE];\n\n    /* Write things to temporary buffer */\n    MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));\n    MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));\n    MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));\n\n    if (end - p < 4) {\n        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n    }\n\n    MBEDTLS_PUT_UINT32_BE(id_len, p, 0);\n    p += 4;\n\n    if (end < p || (size_t) (end - p) < id_len) {\n        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n    }\n\n    memcpy(p, id, id_len);\n    p += id_len;\n\n    /* Compute hash */\n    MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,\n                                                 buf, (size_t) (p - buf), hash));\n\n    /* Turn it into an integer mod n */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,\n                                            mbedtls_md_get_size_from_type(md_type)));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));\n\ncleanup:\n    return ret;\n}\n\n/*\n * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)\n */\nstatic int ecjpake_zkp_read(const mbedtls_md_type_t md_type,\n                            const mbedtls_ecp_group *grp,\n                            const int pf,\n                            const mbedtls_ecp_point *G,\n                            const mbedtls_ecp_point *X,\n                            const char *id,\n                            const unsigned char **p,\n                            const unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_point V, VV;\n    mbedtls_mpi r, h;\n    size_t r_len;\n\n    mbedtls_ecp_point_init(&V);\n    mbedtls_ecp_point_init(&VV);\n    mbedtls_mpi_init(&r);\n    mbedtls_mpi_init(&h);\n\n    /*\n     * struct {\n     *     ECPoint V;\n     *     opaque r<1..2^8-1>;\n     * } ECSchnorrZKP;\n     */\n    if (end < *p) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, (size_t) (end - *p)));\n\n    if (end < *p || (size_t) (end - *p) < 1) {\n        ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n\n    r_len = *(*p)++;\n\n    if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {\n        ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));\n    *p += r_len;\n\n    /*\n     * Verification\n     */\n    MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));\n    MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,\n                                       &VV, &h, X, &r, G));\n\n    if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {\n        ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;\n        goto cleanup;\n    }\n\ncleanup:\n    mbedtls_ecp_point_free(&V);\n    mbedtls_ecp_point_free(&VV);\n    mbedtls_mpi_free(&r);\n    mbedtls_mpi_free(&h);\n\n    return ret;\n}\n\n/*\n * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)\n */\nstatic int ecjpake_zkp_write(const mbedtls_md_type_t md_type,\n                             const mbedtls_ecp_group *grp,\n                             const int pf,\n                             const mbedtls_ecp_point *G,\n                             const mbedtls_mpi *x,\n                             const mbedtls_ecp_point *X,\n                             const char *id,\n                             unsigned char **p,\n                             const unsigned char *end,\n                             int (*f_rng)(void *, unsigned char *, size_t),\n                             void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_point V;\n    mbedtls_mpi v;\n    mbedtls_mpi h; /* later recycled to hold r */\n    size_t len;\n\n    if (end < *p) {\n        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n    }\n\n    mbedtls_ecp_point_init(&V);\n    mbedtls_mpi_init(&v);\n    mbedtls_mpi_init(&h);\n\n    /* Compute signature */\n    MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,\n                                                 G, &v, &V, f_rng, p_rng));\n    MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x));     /* x*h */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h));     /* v - x*h */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N));     /* r */\n\n    /* Write it out */\n    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,\n                                                pf, &len, *p, (size_t) (end - *p)));\n    *p += len;\n\n    len = mbedtls_mpi_size(&h);   /* actually r */\n    if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {\n        ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n        goto cleanup;\n    }\n\n    *(*p)++ = MBEDTLS_BYTE_0(len);\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len));     /* r */\n    *p += len;\n\ncleanup:\n    mbedtls_ecp_point_free(&V);\n    mbedtls_mpi_free(&v);\n    mbedtls_mpi_free(&h);\n\n    return ret;\n}\n\n/*\n * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof\n * Output: verified public key X\n */\nstatic int ecjpake_kkp_read(const mbedtls_md_type_t md_type,\n                            const mbedtls_ecp_group *grp,\n                            const int pf,\n                            const mbedtls_ecp_point *G,\n                            mbedtls_ecp_point *X,\n                            const char *id,\n                            const unsigned char **p,\n                            const unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (end < *p) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    /*\n     * struct {\n     *     ECPoint X;\n     *     ECSchnorrZKP zkp;\n     * } ECJPAKEKeyKP;\n     */\n    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, (size_t) (end - *p)));\n    if (mbedtls_ecp_is_zero(X)) {\n        ret = MBEDTLS_ERR_ECP_INVALID_KEY;\n        goto cleanup;\n    }\n\n    MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));\n\ncleanup:\n    return ret;\n}\n\n/*\n * Generate an ECJPAKEKeyKP\n * Output: the serialized structure, plus private/public key pair\n */\nstatic int ecjpake_kkp_write(const mbedtls_md_type_t md_type,\n                             const mbedtls_ecp_group *grp,\n                             const int pf,\n                             const mbedtls_ecp_point *G,\n                             mbedtls_mpi *x,\n                             mbedtls_ecp_point *X,\n                             const char *id,\n                             unsigned char **p,\n                             const unsigned char *end,\n                             int (*f_rng)(void *, unsigned char *, size_t),\n                             void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n\n    if (end < *p) {\n        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n    }\n\n    /* Generate key (7.4.2.3.1) and write it out */\n    MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,\n                                                 f_rng, p_rng));\n    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,\n                                                pf, &len, *p, (size_t) (end - *p)));\n    *p += len;\n\n    /* Generate and write proof */\n    MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,\n                                      p, end, f_rng, p_rng));\n\ncleanup:\n    return ret;\n}\n\n/*\n * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs\n * Outputs: verified peer public keys Xa, Xb\n */\nstatic int ecjpake_kkpp_read(const mbedtls_md_type_t md_type,\n                             const mbedtls_ecp_group *grp,\n                             const int pf,\n                             const mbedtls_ecp_point *G,\n                             mbedtls_ecp_point *Xa,\n                             mbedtls_ecp_point *Xb,\n                             const char *id,\n                             const unsigned char *buf,\n                             size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const unsigned char *p = buf;\n    const unsigned char *end = buf + len;\n\n    /*\n     * struct {\n     *     ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];\n     * } ECJPAKEKeyKPPairList;\n     */\n    MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end));\n    MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end));\n\n    if (p != end) {\n        ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\ncleanup:\n    return ret;\n}\n\n/*\n * Generate a ECJPAKEKeyKPPairList\n * Outputs: the serialized structure, plus two private/public key pairs\n */\nstatic int ecjpake_kkpp_write(const mbedtls_md_type_t md_type,\n                              const mbedtls_ecp_group *grp,\n                              const int pf,\n                              const mbedtls_ecp_point *G,\n                              mbedtls_mpi *xm1,\n                              mbedtls_ecp_point *Xa,\n                              mbedtls_mpi *xm2,\n                              mbedtls_ecp_point *Xb,\n                              const char *id,\n                              unsigned char *buf,\n                              size_t len,\n                              size_t *olen,\n                              int (*f_rng)(void *, unsigned char *, size_t),\n                              void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = buf;\n    const unsigned char *end = buf + len;\n\n    MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id,\n                                      &p, end, f_rng, p_rng));\n    MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,\n                                      &p, end, f_rng, p_rng));\n\n    *olen = (size_t) (p - buf);\n\ncleanup:\n    return ret;\n}\n\n/*\n * Read and process the first round message\n */\nint mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,\n                                   const unsigned char *buf,\n                                   size_t len)\n{\n    return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format,\n                             &ctx->grp.G,\n                             &ctx->Xp1, &ctx->Xp2, ID_PEER,\n                             buf, len);\n}\n\n/*\n * Generate and write the first round message\n */\nint mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,\n                                    unsigned char *buf, size_t len, size_t *olen,\n                                    int (*f_rng)(void *, unsigned char *, size_t),\n                                    void *p_rng)\n{\n    return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format,\n                              &ctx->grp.G,\n                              &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,\n                              ID_MINE, buf, len, olen, f_rng, p_rng);\n}\n\n/*\n * Compute the sum of three points R = A + B + C\n */\nstatic int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n                            const mbedtls_ecp_point *A,\n                            const mbedtls_ecp_point *B,\n                            const mbedtls_ecp_point *C)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi one;\n\n    mbedtls_mpi_init(&one);\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));\n    MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));\n    MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));\n\ncleanup:\n    mbedtls_mpi_free(&one);\n\n    return ret;\n}\n\n/*\n * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)\n */\nint mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,\n                                   const unsigned char *buf,\n                                   size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const unsigned char *p = buf;\n    const unsigned char *end = buf + len;\n    mbedtls_ecp_group grp;\n    mbedtls_ecp_point G;    /* C: GB, S: GA */\n\n    mbedtls_ecp_group_init(&grp);\n    mbedtls_ecp_point_init(&G);\n\n    /*\n     * Server: GA = X3  + X4  + X1      (7.4.2.6.1)\n     * Client: GB = X1  + X2  + X3      (7.4.2.5.1)\n     * Unified: G = Xm1 + Xm2 + Xp1\n     * We need that before parsing in order to check Xp as we read it\n     */\n    MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,\n                                     &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));\n\n    /*\n     * struct {\n     *     ECParameters curve_params;   // only client reading server msg\n     *     ECJPAKEKeyKP ecjpake_key_kp;\n     * } Client/ServerECJPAKEParams;\n     */\n    if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {\n        MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));\n        if (grp.id != ctx->grp.id) {\n            ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n            goto cleanup;\n        }\n    }\n\n    MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,\n                                     ctx->point_format,\n                                     &G, &ctx->Xp, ID_PEER, &p, end));\n\n    if (p != end) {\n        ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n\ncleanup:\n    mbedtls_ecp_group_free(&grp);\n    mbedtls_ecp_point_free(&G);\n\n    return ret;\n}\n\n/*\n * Compute R = +/- X * S mod N, taking care not to leak S\n */\nstatic int ecjpake_mul_secret(mbedtls_mpi *R, int sign,\n                              const mbedtls_mpi *X,\n                              const mbedtls_mpi *S,\n                              const mbedtls_mpi *N,\n                              int (*f_rng)(void *, unsigned char *, size_t),\n                              void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi b; /* Blinding value, then s + N * blinding */\n\n    mbedtls_mpi_init(&b);\n\n    /* b = s + rnd-128-bit * N */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));\n\n    /* R = sign * X * b mod N */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));\n    R->s *= sign;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));\n\ncleanup:\n    mbedtls_mpi_free(&b);\n\n    return ret;\n}\n\n/*\n * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)\n */\nint mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,\n                                    unsigned char *buf, size_t len, size_t *olen,\n                                    int (*f_rng)(void *, unsigned char *, size_t),\n                                    void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_point G;    /* C: GA, S: GB */\n    mbedtls_ecp_point Xm;   /* C: Xc, S: Xs */\n    mbedtls_mpi xm;         /* C: xc, S: xs */\n    unsigned char *p = buf;\n    const unsigned char *end = buf + len;\n    size_t ec_len;\n\n    mbedtls_ecp_point_init(&G);\n    mbedtls_ecp_point_init(&Xm);\n    mbedtls_mpi_init(&xm);\n\n    /*\n     * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1)\n     *\n     * Client:  GA = X1  + X3  + X4  | xs = x2  * s | Xc = xc * GA\n     * Server:  GB = X3  + X1  + X2  | xs = x4  * s | Xs = xs * GB\n     * Unified: G  = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G\n     */\n    MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,\n                                     &ctx->Xp1, &ctx->Xp2, &ctx->Xm1));\n    MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s,\n                                       &ctx->grp.N, f_rng, p_rng));\n    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng));\n\n    /*\n     * Now write things out\n     *\n     * struct {\n     *     ECParameters curve_params;   // only server writing its message\n     *     ECJPAKEKeyKP ecjpake_key_kp;\n     * } Client/ServerECJPAKEParams;\n     */\n    if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {\n        if (end < p) {\n            ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n            goto cleanup;\n        }\n        MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,\n                                                    p, (size_t) (end - p)));\n        p += ec_len;\n    }\n\n    if (end < p) {\n        ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n        goto cleanup;\n    }\n    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,\n                                                ctx->point_format, &ec_len, p, (size_t) (end - p)));\n    p += ec_len;\n\n    MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,\n                                      ctx->point_format,\n                                      &G, &xm, &Xm, ID_MINE,\n                                      &p, end, f_rng, p_rng));\n\n    *olen = (size_t) (p - buf);\n\ncleanup:\n    mbedtls_ecp_point_free(&G);\n    mbedtls_ecp_point_free(&Xm);\n    mbedtls_mpi_free(&xm);\n\n    return ret;\n}\n\n/*\n * Derive PMS (7.4.2.7 / 7.4.2.8)\n */\nstatic int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx,\n                                    mbedtls_ecp_point *K,\n                                    int (*f_rng)(void *, unsigned char *, size_t),\n                                    void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi m_xm2_s, one;\n\n    mbedtls_mpi_init(&m_xm2_s);\n    mbedtls_mpi_init(&one);\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));\n\n    /*\n     * Client:  K = ( Xs - X4  * x2  * s ) * x2\n     * Server:  K = ( Xc - X2  * x4  * s ) * x4\n     * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2\n     */\n    MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,\n                                       &ctx->grp.N, f_rng, p_rng));\n    MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K,\n                                       &one, &ctx->Xp,\n                                       &m_xm2_s, &ctx->Xp2));\n    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K,\n                                    f_rng, p_rng));\n\ncleanup:\n    mbedtls_mpi_free(&m_xm2_s);\n    mbedtls_mpi_free(&one);\n\n    return ret;\n}\n\nint mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,\n                                  unsigned char *buf, size_t len, size_t *olen,\n                                  int (*f_rng)(void *, unsigned char *, size_t),\n                                  void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_point K;\n    unsigned char kx[MBEDTLS_ECP_MAX_BYTES];\n    size_t x_bytes;\n\n    *olen = mbedtls_md_get_size_from_type(ctx->md_type);\n    if (len < *olen) {\n        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n    }\n\n    mbedtls_ecp_point_init(&K);\n\n    ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);\n    if (ret) {\n        goto cleanup;\n    }\n\n    /* PMS = SHA-256( K.X ) */\n    x_bytes = (ctx->grp.pbits + 7) / 8;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));\n    MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type,\n                                                 kx, x_bytes, buf));\n\ncleanup:\n    mbedtls_ecp_point_free(&K);\n\n    return ret;\n}\n\nint mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx,\n                                     unsigned char *buf, size_t len, size_t *olen,\n                                     int (*f_rng)(void *, unsigned char *, size_t),\n                                     void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_point K;\n\n    mbedtls_ecp_point_init(&K);\n\n    ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);\n    if (ret) {\n        goto cleanup;\n    }\n\n    ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format,\n                                         olen, buf, len);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\ncleanup:\n    mbedtls_ecp_point_free(&K);\n\n    return ret;\n}\n\n#undef ID_MINE\n#undef ID_PEER\n\n#endif /* ! MBEDTLS_ECJPAKE_ALT */\n\n#if defined(MBEDTLS_SELF_TEST)\n\n#include \"mbedtls/platform.h\"\n\n#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \\\n    !defined(MBEDTLS_MD_CAN_SHA256)\nint mbedtls_ecjpake_self_test(int verbose)\n{\n    (void) verbose;\n    return 0;\n}\n#else\n\nstatic const unsigned char ecjpake_test_password[] = {\n    0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,\n    0x65, 0x73, 0x74\n};\n\n#if !defined(MBEDTLS_ECJPAKE_ALT)\n\nstatic const unsigned char ecjpake_test_x1[] = {\n    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,\n    0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,\n    0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21\n};\n\nstatic const unsigned char ecjpake_test_x2[] = {\n    0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,\n    0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,\n    0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81\n};\n\nstatic const unsigned char ecjpake_test_x3[] = {\n    0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,\n    0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,\n    0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81\n};\n\nstatic const unsigned char ecjpake_test_x4[] = {\n    0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,\n    0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,\n    0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1\n};\n\nstatic const unsigned char ecjpake_test_cli_one[] = {\n    0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,\n    0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,\n    0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,\n    0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,\n    0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,\n    0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,\n    0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,\n    0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,\n    0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,\n    0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,\n    0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,\n    0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,\n    0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,\n    0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,\n    0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,\n    0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,\n    0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,\n    0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,\n    0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,\n    0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,\n    0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,\n    0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,\n    0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,\n    0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,\n    0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,\n    0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,\n    0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,\n    0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0\n};\n\nstatic const unsigned char ecjpake_test_srv_one[] = {\n    0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,\n    0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,\n    0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,\n    0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,\n    0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,\n    0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,\n    0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,\n    0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,\n    0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,\n    0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,\n    0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,\n    0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,\n    0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,\n    0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,\n    0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,\n    0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,\n    0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,\n    0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,\n    0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,\n    0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,\n    0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,\n    0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,\n    0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,\n    0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,\n    0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,\n    0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,\n    0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,\n    0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12\n};\n\nstatic const unsigned char ecjpake_test_srv_two[] = {\n    0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,\n    0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,\n    0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,\n    0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,\n    0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,\n    0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,\n    0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,\n    0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,\n    0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,\n    0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,\n    0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,\n    0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,\n    0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,\n    0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c\n};\n\nstatic const unsigned char ecjpake_test_cli_two[] = {\n    0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,\n    0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,\n    0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,\n    0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,\n    0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,\n    0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,\n    0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,\n    0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,\n    0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,\n    0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,\n    0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,\n    0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,\n    0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,\n    0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c\n};\n\nstatic const unsigned char ecjpake_test_shared_key[] = {\n    0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,\n    0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,\n    0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,\n    0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,\n    0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,\n    0x17, 0xc3, 0xde, 0x27, 0xb4,\n};\n\nstatic const unsigned char ecjpake_test_pms[] = {\n    0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,\n    0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,\n    0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51\n};\n\n/*\n * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!\n *\n * This is the linear congruential generator from numerical recipes,\n * except we only use the low byte as the output. See\n * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use\n */\nstatic int self_test_rng(void *ctx, unsigned char *out, size_t len)\n{\n    static uint32_t state = 42;\n\n    (void) ctx;\n\n    for (size_t i = 0; i < len; i++) {\n        state = state * 1664525u + 1013904223u;\n        out[i] = (unsigned char) state;\n    }\n\n    return 0;\n}\n\n/* Load my private keys and generate the corresponding public keys */\nstatic int ecjpake_test_load(mbedtls_ecjpake_context *ctx,\n                             const unsigned char *xm1, size_t len1,\n                             const unsigned char *xm2, size_t len2)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));\n    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,\n                                    &ctx->grp.G, self_test_rng, NULL));\n    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,\n                                    &ctx->grp.G, self_test_rng, NULL));\n\ncleanup:\n    return ret;\n}\n\n#endif /* ! MBEDTLS_ECJPAKE_ALT */\n\n/* For tests we don't need a secure RNG;\n * use the LGC from Numerical Recipes for simplicity */\nstatic int ecjpake_lgc(void *p, unsigned char *out, size_t len)\n{\n    static uint32_t x = 42;\n    (void) p;\n\n    while (len > 0) {\n        size_t use_len = len > 4 ? 4 : len;\n        x = 1664525 * x + 1013904223;\n        memcpy(out, &x, use_len);\n        out += use_len;\n        len -= use_len;\n    }\n\n    return 0;\n}\n\n#define TEST_ASSERT(x)    \\\n    do {                    \\\n        if (x)             \\\n        ret = 0;        \\\n        else                \\\n        {                   \\\n            ret = 1;        \\\n            goto cleanup;   \\\n        }                   \\\n    } while (0)\n\n/*\n * Checkup routine\n */\nint mbedtls_ecjpake_self_test(int verbose)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecjpake_context cli;\n    mbedtls_ecjpake_context srv;\n    unsigned char buf[512], pms[32];\n    size_t len, pmslen;\n\n    mbedtls_ecjpake_init(&cli);\n    mbedtls_ecjpake_init(&srv);\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  ECJPAKE test #0 (setup): \");\n    }\n\n    TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,\n                                      MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,\n                                      ecjpake_test_password,\n                                      sizeof(ecjpake_test_password)) == 0);\n\n    TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,\n                                      MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,\n                                      ecjpake_test_password,\n                                      sizeof(ecjpake_test_password)) == 0);\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  ECJPAKE test #1 (random handshake): \");\n    }\n\n    TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,\n                                                buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);\n\n    TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);\n\n    TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,\n                                                buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);\n\n    TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);\n\n    TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,\n                                                buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);\n\n    TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);\n\n    TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,\n                                              pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);\n\n    TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,\n                                                buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);\n\n    TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);\n\n    TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,\n                                              buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);\n\n    TEST_ASSERT(len == pmslen);\n    TEST_ASSERT(memcmp(buf, pms, len) == 0);\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\n#if !defined(MBEDTLS_ECJPAKE_ALT)\n    /* 'reference handshake' tests can only be run against implementations\n     * for which we have 100% control over how the random ephemeral keys\n     * are generated. This is only the case for the internal Mbed TLS\n     * implementation, so these tests are skipped in case the internal\n     * implementation is swapped out for an alternative one. */\n    if (verbose != 0) {\n        mbedtls_printf(\"  ECJPAKE test #2 (reference handshake): \");\n    }\n\n    /* Simulate generation of round one */\n    MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,\n                                      ecjpake_test_x1, sizeof(ecjpake_test_x1),\n                                      ecjpake_test_x2, sizeof(ecjpake_test_x2)));\n\n    MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,\n                                      ecjpake_test_x3, sizeof(ecjpake_test_x3),\n                                      ecjpake_test_x4, sizeof(ecjpake_test_x4)));\n\n    /* Read round one */\n    TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,\n                                               ecjpake_test_cli_one,\n                                               sizeof(ecjpake_test_cli_one)) == 0);\n\n    TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,\n                                               ecjpake_test_srv_one,\n                                               sizeof(ecjpake_test_srv_one)) == 0);\n\n    /* Skip generation of round two, read round two */\n    TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,\n                                               ecjpake_test_srv_two,\n                                               sizeof(ecjpake_test_srv_two)) == 0);\n\n    TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,\n                                               ecjpake_test_cli_two,\n                                               sizeof(ecjpake_test_cli_two)) == 0);\n\n    /* Server derives PMS */\n    TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,\n                                              buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);\n\n    TEST_ASSERT(len == sizeof(ecjpake_test_pms));\n    TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);\n\n    /* Server derives K as unsigned binary data */\n    TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv,\n                                                 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);\n\n    TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));\n    TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);\n\n    memset(buf, 0, len);   /* Avoid interferences with next step */\n\n    /* Client derives PMS */\n    TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,\n                                              buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);\n\n    TEST_ASSERT(len == sizeof(ecjpake_test_pms));\n    TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);\n\n    /* Client derives K as unsigned binary data */\n    TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli,\n                                                 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);\n\n    TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));\n    TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n#endif /* ! MBEDTLS_ECJPAKE_ALT */\n\ncleanup:\n    mbedtls_ecjpake_free(&cli);\n    mbedtls_ecjpake_free(&srv);\n\n    if (ret != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n\n        ret = 1;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    return ret;\n}\n\n#undef TEST_ASSERT\n\n#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_MD_CAN_SHA256 */\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_ECJPAKE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ecp.c",
    "content": "/*\n *  Elliptic curves over GF(p): generic functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n * References:\n *\n * SEC1 https://www.secg.org/sec1-v2.pdf\n * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone\n * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf\n * RFC 4492 for the related TLS structures and constants\n * - https://www.rfc-editor.org/rfc/rfc4492\n * RFC 7748 for the Curve448 and Curve25519 curve definitions\n * - https://www.rfc-editor.org/rfc/rfc7748\n *\n * [Curve25519] https://cr.yp.to/ecdh/curve25519-20060209.pdf\n *\n * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis\n *     for elliptic curve cryptosystems. In : Cryptographic Hardware and\n *     Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.\n *     <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>\n *\n * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to\n *     render ECC resistant against Side Channel Attacks. IACR Cryptology\n *     ePrint Archive, 2004, vol. 2004, p. 342.\n *     <http://eprint.iacr.org/2004/342.pdf>\n */\n\n#include \"common.h\"\n\n/**\n * \\brief Function level alternative implementation.\n *\n * The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to\n * replace certain functions in this module. The alternative implementations are\n * typically hardware accelerators and need to activate the hardware before the\n * computation starts and deactivate it after it finishes. The\n * mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve\n * this purpose.\n *\n * To preserve the correct functionality the following conditions must hold:\n *\n * - The alternative implementation must be activated by\n *   mbedtls_internal_ecp_init() before any of the replaceable functions is\n *   called.\n * - mbedtls_internal_ecp_free() must \\b only be called when the alternative\n *   implementation is activated.\n * - mbedtls_internal_ecp_init() must \\b not be called when the alternative\n *   implementation is activated.\n * - Public functions must not return while the alternative implementation is\n *   activated.\n * - Replaceable functions are guarded by \\c MBEDTLS_ECP_XXX_ALT macros and\n *   before calling them an \\code if( mbedtls_internal_ecp_grp_capable( grp ) )\n *   \\endcode ensures that the alternative implementation supports the current\n *   group.\n */\n#if defined(MBEDTLS_ECP_INTERNAL_ALT)\n#endif\n\n#if defined(MBEDTLS_ECP_LIGHT)\n\n#include \"mbedtls/ecp.h\"\n#include \"mbedtls/threading.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include \"bn_mul.h\"\n#include \"bignum_internal.h\"\n#include \"ecp_invasive.h\"\n\n#include <string.h>\n\n#if !defined(MBEDTLS_ECP_ALT)\n\n#include \"mbedtls/platform.h\"\n\n#include \"ecp_internal_alt.h\"\n\n#if defined(MBEDTLS_SELF_TEST)\n/*\n * Counts of point addition and doubling, and field multiplications.\n * Used to test resistance of point multiplication to simple timing attacks.\n */\n#if defined(MBEDTLS_ECP_C)\nstatic unsigned long add_count, dbl_count;\n#endif /* MBEDTLS_ECP_C */\nstatic unsigned long mul_count;\n#endif\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n/*\n * Maximum number of \"basic operations\" to be done in a row.\n *\n * Default value 0 means that ECC operations will not yield.\n * Note that regardless of the value of ecp_max_ops, always at\n * least one step is performed before yielding.\n *\n * Setting ecp_max_ops=1 can be suitable for testing purposes\n * as it will interrupt computation at all possible points.\n */\nstatic unsigned ecp_max_ops = 0;\n\n/*\n * Set ecp_max_ops\n */\nvoid mbedtls_ecp_set_max_ops(unsigned max_ops)\n{\n    ecp_max_ops = max_ops;\n}\n\n/*\n * Check if restart is enabled\n */\nint mbedtls_ecp_restart_is_enabled(void)\n{\n    return ecp_max_ops != 0;\n}\n\n/*\n * Restart sub-context for ecp_mul_comb()\n */\nstruct mbedtls_ecp_restart_mul {\n    mbedtls_ecp_point R;    /* current intermediate result                  */\n    size_t i;               /* current index in various loops, 0 outside    */\n    mbedtls_ecp_point *T;   /* table for precomputed points                 */\n    unsigned char T_size;   /* number of points in table T                  */\n    enum {                  /* what were we doing last time we returned?    */\n        ecp_rsm_init = 0,       /* nothing so far, dummy initial state      */\n        ecp_rsm_pre_dbl,        /* precompute 2^n multiples                 */\n        ecp_rsm_pre_norm_dbl,   /* normalize precomputed 2^n multiples      */\n        ecp_rsm_pre_add,        /* precompute remaining points by adding    */\n        ecp_rsm_pre_norm_add,   /* normalize all precomputed points         */\n        ecp_rsm_comb_core,      /* ecp_mul_comb_core()                      */\n        ecp_rsm_final_norm,     /* do the final normalization               */\n    } state;\n};\n\n/*\n * Init restart_mul sub-context\n */\nstatic void ecp_restart_rsm_init(mbedtls_ecp_restart_mul_ctx *ctx)\n{\n    mbedtls_ecp_point_init(&ctx->R);\n    ctx->i = 0;\n    ctx->T = NULL;\n    ctx->T_size = 0;\n    ctx->state = ecp_rsm_init;\n}\n\n/*\n * Free the components of a restart_mul sub-context\n */\nstatic void ecp_restart_rsm_free(mbedtls_ecp_restart_mul_ctx *ctx)\n{\n    unsigned char i;\n\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_ecp_point_free(&ctx->R);\n\n    if (ctx->T != NULL) {\n        for (i = 0; i < ctx->T_size; i++) {\n            mbedtls_ecp_point_free(ctx->T + i);\n        }\n        mbedtls_free(ctx->T);\n    }\n\n    ecp_restart_rsm_init(ctx);\n}\n\n/*\n * Restart context for ecp_muladd()\n */\nstruct mbedtls_ecp_restart_muladd {\n    mbedtls_ecp_point mP;       /* mP value                             */\n    mbedtls_ecp_point R;        /* R intermediate result                */\n    enum {                      /* what should we do next?              */\n        ecp_rsma_mul1 = 0,      /* first multiplication                 */\n        ecp_rsma_mul2,          /* second multiplication                */\n        ecp_rsma_add,           /* addition                             */\n        ecp_rsma_norm,          /* normalization                        */\n    } state;\n};\n\n/*\n * Init restart_muladd sub-context\n */\nstatic void ecp_restart_ma_init(mbedtls_ecp_restart_muladd_ctx *ctx)\n{\n    mbedtls_ecp_point_init(&ctx->mP);\n    mbedtls_ecp_point_init(&ctx->R);\n    ctx->state = ecp_rsma_mul1;\n}\n\n/*\n * Free the components of a restart_muladd sub-context\n */\nstatic void ecp_restart_ma_free(mbedtls_ecp_restart_muladd_ctx *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_ecp_point_free(&ctx->mP);\n    mbedtls_ecp_point_free(&ctx->R);\n\n    ecp_restart_ma_init(ctx);\n}\n\n/*\n * Initialize a restart context\n */\nvoid mbedtls_ecp_restart_init(mbedtls_ecp_restart_ctx *ctx)\n{\n    ctx->ops_done = 0;\n    ctx->depth = 0;\n    ctx->rsm = NULL;\n    ctx->ma = NULL;\n}\n\n/*\n * Free the components of a restart context\n */\nvoid mbedtls_ecp_restart_free(mbedtls_ecp_restart_ctx *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    ecp_restart_rsm_free(ctx->rsm);\n    mbedtls_free(ctx->rsm);\n\n    ecp_restart_ma_free(ctx->ma);\n    mbedtls_free(ctx->ma);\n\n    mbedtls_ecp_restart_init(ctx);\n}\n\n/*\n * Check if we can do the next step\n */\nint mbedtls_ecp_check_budget(const mbedtls_ecp_group *grp,\n                             mbedtls_ecp_restart_ctx *rs_ctx,\n                             unsigned ops)\n{\n    if (rs_ctx != NULL && ecp_max_ops != 0) {\n        /* scale depending on curve size: the chosen reference is 256-bit,\n         * and multiplication is quadratic. Round to the closest integer. */\n        if (grp->pbits >= 512) {\n            ops *= 4;\n        } else if (grp->pbits >= 384) {\n            ops *= 2;\n        }\n\n        /* Avoid infinite loops: always allow first step.\n         * Because of that, however, it's not generally true\n         * that ops_done <= ecp_max_ops, so the check\n         * ops_done > ecp_max_ops below is mandatory. */\n        if ((rs_ctx->ops_done != 0) &&\n            (rs_ctx->ops_done > ecp_max_ops ||\n             ops > ecp_max_ops - rs_ctx->ops_done)) {\n            return MBEDTLS_ERR_ECP_IN_PROGRESS;\n        }\n\n        /* update running count */\n        rs_ctx->ops_done += ops;\n    }\n\n    return 0;\n}\n\n/* Call this when entering a function that needs its own sub-context */\n#define ECP_RS_ENTER(SUB)   do {                                      \\\n        /* reset ops count for this call if top-level */                    \\\n        if (rs_ctx != NULL && rs_ctx->depth++ == 0)                        \\\n        rs_ctx->ops_done = 0;                                           \\\n                                                                        \\\n        /* set up our own sub-context if needed */                          \\\n        if (mbedtls_ecp_restart_is_enabled() &&                             \\\n            rs_ctx != NULL && rs_ctx->SUB == NULL)                         \\\n        {                                                                   \\\n            rs_ctx->SUB = mbedtls_calloc(1, sizeof(*rs_ctx->SUB));      \\\n            if (rs_ctx->SUB == NULL)                                       \\\n            return MBEDTLS_ERR_ECP_ALLOC_FAILED;                     \\\n                                                                      \\\n            ecp_restart_## SUB ##_init(rs_ctx->SUB);                      \\\n        }                                                                   \\\n} while (0)\n\n/* Call this when leaving a function that needs its own sub-context */\n#define ECP_RS_LEAVE(SUB)   do {                                      \\\n        /* clear our sub-context when not in progress (done or error) */    \\\n        if (rs_ctx != NULL && rs_ctx->SUB != NULL &&                        \\\n            ret != MBEDTLS_ERR_ECP_IN_PROGRESS)                            \\\n        {                                                                   \\\n            ecp_restart_## SUB ##_free(rs_ctx->SUB);                      \\\n            mbedtls_free(rs_ctx->SUB);                                    \\\n            rs_ctx->SUB = NULL;                                             \\\n        }                                                                   \\\n                                                                        \\\n        if (rs_ctx != NULL)                                                \\\n        rs_ctx->depth--;                                                \\\n} while (0)\n\n#else /* MBEDTLS_ECP_RESTARTABLE */\n\n#define ECP_RS_ENTER(sub)     (void) rs_ctx;\n#define ECP_RS_LEAVE(sub)     (void) rs_ctx;\n\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n#if defined(MBEDTLS_ECP_C)\nstatic void mpi_init_many(mbedtls_mpi *arr, size_t size)\n{\n    while (size--) {\n        mbedtls_mpi_init(arr++);\n    }\n}\n\nstatic void mpi_free_many(mbedtls_mpi *arr, size_t size)\n{\n    while (size--) {\n        mbedtls_mpi_free(arr++);\n    }\n}\n#endif /* MBEDTLS_ECP_C */\n\n/*\n * List of supported curves:\n *  - internal ID\n *  - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2, RFC 8446 sec. 4.2.7)\n *  - size in bits\n *  - readable name\n *\n * Curves are listed in order: largest curves first, and for a given size,\n * fastest curves first.\n *\n * Reminder: update profiles in x509_crt.c and ssl_tls.c when adding a new curve!\n */\nstatic const mbedtls_ecp_curve_info ecp_supported_curves[] =\n{\n#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)\n    { MBEDTLS_ECP_DP_SECP521R1,    25,     521,    \"secp521r1\"         },\n#endif\n#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)\n    { MBEDTLS_ECP_DP_BP512R1,      28,     512,    \"brainpoolP512r1\"   },\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\n    { MBEDTLS_ECP_DP_SECP384R1,    24,     384,    \"secp384r1\"         },\n#endif\n#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)\n    { MBEDTLS_ECP_DP_BP384R1,      27,     384,    \"brainpoolP384r1\"   },\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)\n    { MBEDTLS_ECP_DP_SECP256R1,    23,     256,    \"secp256r1\"         },\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n    { MBEDTLS_ECP_DP_SECP256K1,    22,     256,    \"secp256k1\"         },\n#endif\n#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)\n    { MBEDTLS_ECP_DP_BP256R1,      26,     256,    \"brainpoolP256r1\"   },\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)\n    { MBEDTLS_ECP_DP_SECP224R1,    21,     224,    \"secp224r1\"         },\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)\n    { MBEDTLS_ECP_DP_SECP224K1,    20,     224,    \"secp224k1\"         },\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\n    { MBEDTLS_ECP_DP_SECP192R1,    19,     192,    \"secp192r1\"         },\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)\n    { MBEDTLS_ECP_DP_SECP192K1,    18,     192,    \"secp192k1\"         },\n#endif\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n    { MBEDTLS_ECP_DP_CURVE25519,   29,     256,    \"x25519\"            },\n#endif\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n    { MBEDTLS_ECP_DP_CURVE448,     30,     448,    \"x448\"              },\n#endif\n    { MBEDTLS_ECP_DP_NONE,          0,     0,      NULL                },\n};\n\n#define ECP_NB_CURVES   sizeof(ecp_supported_curves) /    \\\n    sizeof(ecp_supported_curves[0])\n\nstatic mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];\n\n/*\n * List of supported curves and associated info\n */\nconst mbedtls_ecp_curve_info *mbedtls_ecp_curve_list(void)\n{\n    return ecp_supported_curves;\n}\n\n/*\n * List of supported curves, group ID only\n */\nconst mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list(void)\n{\n    static int init_done = 0;\n\n    if (!init_done) {\n        size_t i = 0;\n        const mbedtls_ecp_curve_info *curve_info;\n\n        for (curve_info = mbedtls_ecp_curve_list();\n             curve_info->grp_id != MBEDTLS_ECP_DP_NONE;\n             curve_info++) {\n            ecp_supported_grp_id[i++] = curve_info->grp_id;\n        }\n        ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;\n\n        init_done = 1;\n    }\n\n    return ecp_supported_grp_id;\n}\n\n/*\n * Get the curve info for the internal identifier\n */\nconst mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id(mbedtls_ecp_group_id grp_id)\n{\n    const mbedtls_ecp_curve_info *curve_info;\n\n    for (curve_info = mbedtls_ecp_curve_list();\n         curve_info->grp_id != MBEDTLS_ECP_DP_NONE;\n         curve_info++) {\n        if (curve_info->grp_id == grp_id) {\n            return curve_info;\n        }\n    }\n\n    return NULL;\n}\n\n/*\n * Get the curve info from the TLS identifier\n */\nconst mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id(uint16_t tls_id)\n{\n    const mbedtls_ecp_curve_info *curve_info;\n\n    for (curve_info = mbedtls_ecp_curve_list();\n         curve_info->grp_id != MBEDTLS_ECP_DP_NONE;\n         curve_info++) {\n        if (curve_info->tls_id == tls_id) {\n            return curve_info;\n        }\n    }\n\n    return NULL;\n}\n\n/*\n * Get the curve info from the name\n */\nconst mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name(const char *name)\n{\n    const mbedtls_ecp_curve_info *curve_info;\n\n    if (name == NULL) {\n        return NULL;\n    }\n\n    for (curve_info = mbedtls_ecp_curve_list();\n         curve_info->grp_id != MBEDTLS_ECP_DP_NONE;\n         curve_info++) {\n        if (strcmp(curve_info->name, name) == 0) {\n            return curve_info;\n        }\n    }\n\n    return NULL;\n}\n\n/*\n * Get the type of a curve\n */\nmbedtls_ecp_curve_type mbedtls_ecp_get_type(const mbedtls_ecp_group *grp)\n{\n    if (grp->G.X.p == NULL) {\n        return MBEDTLS_ECP_TYPE_NONE;\n    }\n\n    if (grp->G.Y.p == NULL) {\n        return MBEDTLS_ECP_TYPE_MONTGOMERY;\n    } else {\n        return MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS;\n    }\n}\n\n/*\n * Initialize (the components of) a point\n */\nvoid mbedtls_ecp_point_init(mbedtls_ecp_point *pt)\n{\n    mbedtls_mpi_init(&pt->X);\n    mbedtls_mpi_init(&pt->Y);\n    mbedtls_mpi_init(&pt->Z);\n}\n\n/*\n * Initialize (the components of) a group\n */\nvoid mbedtls_ecp_group_init(mbedtls_ecp_group *grp)\n{\n    grp->id = MBEDTLS_ECP_DP_NONE;\n    mbedtls_mpi_init(&grp->P);\n    mbedtls_mpi_init(&grp->A);\n    mbedtls_mpi_init(&grp->B);\n    mbedtls_ecp_point_init(&grp->G);\n    mbedtls_mpi_init(&grp->N);\n    grp->pbits = 0;\n    grp->nbits = 0;\n    grp->h = 0;\n    grp->modp = NULL;\n    grp->t_pre = NULL;\n    grp->t_post = NULL;\n    grp->t_data = NULL;\n    grp->T = NULL;\n    grp->T_size = 0;\n}\n\n/*\n * Initialize (the components of) a key pair\n */\nvoid mbedtls_ecp_keypair_init(mbedtls_ecp_keypair *key)\n{\n    mbedtls_ecp_group_init(&key->grp);\n    mbedtls_mpi_init(&key->d);\n    mbedtls_ecp_point_init(&key->Q);\n}\n\n/*\n * Unallocate (the components of) a point\n */\nvoid mbedtls_ecp_point_free(mbedtls_ecp_point *pt)\n{\n    if (pt == NULL) {\n        return;\n    }\n\n    mbedtls_mpi_free(&(pt->X));\n    mbedtls_mpi_free(&(pt->Y));\n    mbedtls_mpi_free(&(pt->Z));\n}\n\n/*\n * Check that the comb table (grp->T) is static initialized.\n */\nstatic int ecp_group_is_static_comb_table(const mbedtls_ecp_group *grp)\n{\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\n    return grp->T != NULL && grp->T_size == 0;\n#else\n    (void) grp;\n    return 0;\n#endif\n}\n\n/*\n * Unallocate (the components of) a group\n */\nvoid mbedtls_ecp_group_free(mbedtls_ecp_group *grp)\n{\n    size_t i;\n\n    if (grp == NULL) {\n        return;\n    }\n\n    if (grp->h != 1) {\n        mbedtls_mpi_free(&grp->A);\n        mbedtls_mpi_free(&grp->B);\n        mbedtls_ecp_point_free(&grp->G);\n\n#if !defined(MBEDTLS_ECP_WITH_MPI_UINT)\n        mbedtls_mpi_free(&grp->N);\n        mbedtls_mpi_free(&grp->P);\n#endif\n    }\n\n    if (!ecp_group_is_static_comb_table(grp) && grp->T != NULL) {\n        for (i = 0; i < grp->T_size; i++) {\n            mbedtls_ecp_point_free(&grp->T[i]);\n        }\n        mbedtls_free(grp->T);\n    }\n\n    mbedtls_platform_zeroize(grp, sizeof(mbedtls_ecp_group));\n}\n\n/*\n * Unallocate (the components of) a key pair\n */\nvoid mbedtls_ecp_keypair_free(mbedtls_ecp_keypair *key)\n{\n    if (key == NULL) {\n        return;\n    }\n\n    mbedtls_ecp_group_free(&key->grp);\n    mbedtls_mpi_free(&key->d);\n    mbedtls_ecp_point_free(&key->Q);\n}\n\n/*\n * Copy the contents of a point\n */\nint mbedtls_ecp_copy(mbedtls_ecp_point *P, const mbedtls_ecp_point *Q)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&P->X, &Q->X));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&P->Y, &Q->Y));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&P->Z, &Q->Z));\n\ncleanup:\n    return ret;\n}\n\n/*\n * Copy the contents of a group object\n */\nint mbedtls_ecp_group_copy(mbedtls_ecp_group *dst, const mbedtls_ecp_group *src)\n{\n    return mbedtls_ecp_group_load(dst, src->id);\n}\n\n/*\n * Set point to zero\n */\nint mbedtls_ecp_set_zero(mbedtls_ecp_point *pt)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->X, 1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Y, 1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 0));\n\ncleanup:\n    return ret;\n}\n\n/*\n * Tell if a point is zero\n */\nint mbedtls_ecp_is_zero(mbedtls_ecp_point *pt)\n{\n    return mbedtls_mpi_cmp_int(&pt->Z, 0) == 0;\n}\n\n/*\n * Compare two points lazily\n */\nint mbedtls_ecp_point_cmp(const mbedtls_ecp_point *P,\n                          const mbedtls_ecp_point *Q)\n{\n    if (mbedtls_mpi_cmp_mpi(&P->X, &Q->X) == 0 &&\n        mbedtls_mpi_cmp_mpi(&P->Y, &Q->Y) == 0 &&\n        mbedtls_mpi_cmp_mpi(&P->Z, &Q->Z) == 0) {\n        return 0;\n    }\n\n    return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n}\n\n/*\n * Import a non-zero point from ASCII strings\n */\nint mbedtls_ecp_point_read_string(mbedtls_ecp_point *P, int radix,\n                                  const char *x, const char *y)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&P->X, radix, x));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&P->Y, radix, y));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&P->Z, 1));\n\ncleanup:\n    return ret;\n}\n\n/*\n * Export a point into unsigned binary data (SEC1 2.3.3 and RFC7748)\n */\nint mbedtls_ecp_point_write_binary(const mbedtls_ecp_group *grp,\n                                   const mbedtls_ecp_point *P,\n                                   int format, size_t *olen,\n                                   unsigned char *buf, size_t buflen)\n{\n    int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n    size_t plen;\n    if (format != MBEDTLS_ECP_PF_UNCOMPRESSED &&\n        format != MBEDTLS_ECP_PF_COMPRESSED) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    plen = mbedtls_mpi_size(&grp->P);\n\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\n    (void) format; /* Montgomery curves always use the same point format */\n    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {\n        *olen = plen;\n        if (buflen < *olen) {\n            return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n        }\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(&P->X, buf, plen));\n    }\n#endif\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {\n        /*\n         * Common case: P == 0\n         */\n        if (mbedtls_mpi_cmp_int(&P->Z, 0) == 0) {\n            if (buflen < 1) {\n                return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n            }\n\n            buf[0] = 0x00;\n            *olen = 1;\n\n            return 0;\n        }\n\n        if (format == MBEDTLS_ECP_PF_UNCOMPRESSED) {\n            *olen = 2 * plen + 1;\n\n            if (buflen < *olen) {\n                return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n            }\n\n            buf[0] = 0x04;\n            MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&P->X, buf + 1, plen));\n            MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&P->Y, buf + 1 + plen, plen));\n        } else if (format == MBEDTLS_ECP_PF_COMPRESSED) {\n            *olen = plen + 1;\n\n            if (buflen < *olen) {\n                return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n            }\n\n            buf[0] = 0x02 + mbedtls_mpi_get_bit(&P->Y, 0);\n            MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&P->X, buf + 1, plen));\n        }\n    }\n#endif\n\ncleanup:\n    return ret;\n}\n\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\nstatic int mbedtls_ecp_sw_derive_y(const mbedtls_ecp_group *grp,\n                                   const mbedtls_mpi *X,\n                                   mbedtls_mpi *Y,\n                                   int parity_bit);\n#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */\n\n/*\n * Import a point from unsigned binary data (SEC1 2.3.4 and RFC7748)\n */\nint mbedtls_ecp_point_read_binary(const mbedtls_ecp_group *grp,\n                                  mbedtls_ecp_point *pt,\n                                  const unsigned char *buf, size_t ilen)\n{\n    int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n    size_t plen;\n    if (ilen < 1) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    plen = mbedtls_mpi_size(&grp->P);\n\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\n    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {\n        if (plen != ilen) {\n            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n        }\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&pt->X, buf, plen));\n        mbedtls_mpi_free(&pt->Y);\n\n        if (grp->id == MBEDTLS_ECP_DP_CURVE25519) {\n            /* Set most significant bit to 0 as prescribed in RFC7748 §5 */\n            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&pt->X, plen * 8 - 1, 0));\n        }\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 1));\n    }\n#endif\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {\n        if (buf[0] == 0x00) {\n            if (ilen == 1) {\n                return mbedtls_ecp_set_zero(pt);\n            } else {\n                return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n            }\n        }\n\n        if (ilen < 1 + plen) {\n            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n        }\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->X, buf + 1, plen));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 1));\n\n        if (buf[0] == 0x04) {\n            /* format == MBEDTLS_ECP_PF_UNCOMPRESSED */\n            if (ilen != 1 + plen * 2) {\n                return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n            }\n            return mbedtls_mpi_read_binary(&pt->Y, buf + 1 + plen, plen);\n        } else if (buf[0] == 0x02 || buf[0] == 0x03) {\n            /* format == MBEDTLS_ECP_PF_COMPRESSED */\n            if (ilen != 1 + plen) {\n                return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n            }\n            return mbedtls_ecp_sw_derive_y(grp, &pt->X, &pt->Y,\n                                           (buf[0] & 1));\n        } else {\n            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n        }\n    }\n#endif\n\ncleanup:\n    return ret;\n}\n\n/*\n * Import a point from a TLS ECPoint record (RFC 4492)\n *      struct {\n *          opaque point <1..2^8-1>;\n *      } ECPoint;\n */\nint mbedtls_ecp_tls_read_point(const mbedtls_ecp_group *grp,\n                               mbedtls_ecp_point *pt,\n                               const unsigned char **buf, size_t buf_len)\n{\n    unsigned char data_len;\n    const unsigned char *buf_start;\n    /*\n     * We must have at least two bytes (1 for length, at least one for data)\n     */\n    if (buf_len < 2) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    data_len = *(*buf)++;\n    if (data_len < 1 || data_len > buf_len - 1) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    /*\n     * Save buffer start for read_binary and update buf\n     */\n    buf_start = *buf;\n    *buf += data_len;\n\n    return mbedtls_ecp_point_read_binary(grp, pt, buf_start, data_len);\n}\n\n/*\n * Export a point as a TLS ECPoint record (RFC 4492)\n *      struct {\n *          opaque point <1..2^8-1>;\n *      } ECPoint;\n */\nint mbedtls_ecp_tls_write_point(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,\n                                int format, size_t *olen,\n                                unsigned char *buf, size_t blen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    if (format != MBEDTLS_ECP_PF_UNCOMPRESSED &&\n        format != MBEDTLS_ECP_PF_COMPRESSED) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    /*\n     * buffer length must be at least one, for our length byte\n     */\n    if (blen < 1) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    if ((ret = mbedtls_ecp_point_write_binary(grp, pt, format,\n                                              olen, buf + 1, blen - 1)) != 0) {\n        return ret;\n    }\n\n    /*\n     * write length to the first byte and update total length\n     */\n    buf[0] = (unsigned char) *olen;\n    ++*olen;\n\n    return 0;\n}\n\n/*\n * Set a group from an ECParameters record (RFC 4492)\n */\nint mbedtls_ecp_tls_read_group(mbedtls_ecp_group *grp,\n                               const unsigned char **buf, size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_group_id grp_id;\n    if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, len)) != 0) {\n        return ret;\n    }\n\n    return mbedtls_ecp_group_load(grp, grp_id);\n}\n\n/*\n * Read a group id from an ECParameters record (RFC 4492) and convert it to\n * mbedtls_ecp_group_id.\n */\nint mbedtls_ecp_tls_read_group_id(mbedtls_ecp_group_id *grp,\n                                  const unsigned char **buf, size_t len)\n{\n    uint16_t tls_id;\n    const mbedtls_ecp_curve_info *curve_info;\n    /*\n     * We expect at least three bytes (see below)\n     */\n    if (len < 3) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    /*\n     * First byte is curve_type; only named_curve is handled\n     */\n    if (*(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    /*\n     * Next two bytes are the namedcurve value\n     */\n    tls_id = MBEDTLS_GET_UINT16_BE(*buf, 0);\n    *buf += 2;\n\n    if ((curve_info = mbedtls_ecp_curve_info_from_tls_id(tls_id)) == NULL) {\n        return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n    }\n\n    *grp = curve_info->grp_id;\n\n    return 0;\n}\n\n/*\n * Write the ECParameters record corresponding to a group (RFC 4492)\n */\nint mbedtls_ecp_tls_write_group(const mbedtls_ecp_group *grp, size_t *olen,\n                                unsigned char *buf, size_t blen)\n{\n    const mbedtls_ecp_curve_info *curve_info;\n    if ((curve_info = mbedtls_ecp_curve_info_from_grp_id(grp->id)) == NULL) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    /*\n     * We are going to write 3 bytes (see below)\n     */\n    *olen = 3;\n    if (blen < *olen) {\n        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n    }\n\n    /*\n     * First byte is curve_type, always named_curve\n     */\n    *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;\n\n    /*\n     * Next two bytes are the namedcurve value\n     */\n    MBEDTLS_PUT_UINT16_BE(curve_info->tls_id, buf, 0);\n\n    return 0;\n}\n\n/*\n * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.\n * See the documentation of struct mbedtls_ecp_group.\n *\n * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf.\n */\nstatic int ecp_modp(mbedtls_mpi *N, const mbedtls_ecp_group *grp)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (grp->modp == NULL) {\n        return mbedtls_mpi_mod_mpi(N, N, &grp->P);\n    }\n\n    /* N->s < 0 is a much faster test, which fails only if N is 0 */\n    if ((N->s < 0 && mbedtls_mpi_cmp_int(N, 0) != 0) ||\n        mbedtls_mpi_bitlen(N) > 2 * grp->pbits) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    MBEDTLS_MPI_CHK(grp->modp(N));\n\n    /* N->s < 0 is a much faster test, which fails only if N is 0 */\n    while (N->s < 0 && mbedtls_mpi_cmp_int(N, 0) != 0) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &grp->P));\n    }\n\n    while (mbedtls_mpi_cmp_mpi(N, &grp->P) >= 0) {\n        /* we known P, N and the result are positive */\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(N, N, &grp->P));\n    }\n\ncleanup:\n    return ret;\n}\n\n/*\n * Fast mod-p functions expect their argument to be in the 0..p^2 range.\n *\n * In order to guarantee that, we need to ensure that operands of\n * mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will\n * bring the result back to this range.\n *\n * The following macros are shortcuts for doing that.\n */\n\n/*\n * Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi\n */\n#if defined(MBEDTLS_SELF_TEST)\n#define INC_MUL_COUNT   mul_count++;\n#else\n#define INC_MUL_COUNT\n#endif\n\n#define MOD_MUL(N)                                                    \\\n    do                                                                  \\\n    {                                                                   \\\n        MBEDTLS_MPI_CHK(ecp_modp(&(N), grp));                       \\\n        INC_MUL_COUNT                                                   \\\n    } while (0)\n\nstatic inline int mbedtls_mpi_mul_mod(const mbedtls_ecp_group *grp,\n                                      mbedtls_mpi *X,\n                                      const mbedtls_mpi *A,\n                                      const mbedtls_mpi *B)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(X, A, B));\n    MOD_MUL(*X);\ncleanup:\n    return ret;\n}\n\n/*\n * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi\n * N->s < 0 is a very fast test, which fails only if N is 0\n */\n#define MOD_SUB(N)                                                          \\\n    do {                                                                      \\\n        while ((N)->s < 0 && mbedtls_mpi_cmp_int((N), 0) != 0)             \\\n        MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi((N), (N), &grp->P));      \\\n    } while (0)\n\nMBEDTLS_MAYBE_UNUSED\nstatic inline int mbedtls_mpi_sub_mod(const mbedtls_ecp_group *grp,\n                                      mbedtls_mpi *X,\n                                      const mbedtls_mpi *A,\n                                      const mbedtls_mpi *B)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(X, A, B));\n    MOD_SUB(X);\ncleanup:\n    return ret;\n}\n\n/*\n * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int.\n * We known P, N and the result are positive, so sub_abs is correct, and\n * a bit faster.\n */\n#define MOD_ADD(N)                                                   \\\n    while (mbedtls_mpi_cmp_mpi((N), &grp->P) >= 0)                  \\\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs((N), (N), &grp->P))\n\nstatic inline int mbedtls_mpi_add_mod(const mbedtls_ecp_group *grp,\n                                      mbedtls_mpi *X,\n                                      const mbedtls_mpi *A,\n                                      const mbedtls_mpi *B)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, A, B));\n    MOD_ADD(X);\ncleanup:\n    return ret;\n}\n\nMBEDTLS_MAYBE_UNUSED\nstatic inline int mbedtls_mpi_mul_int_mod(const mbedtls_ecp_group *grp,\n                                          mbedtls_mpi *X,\n                                          const mbedtls_mpi *A,\n                                          mbedtls_mpi_uint c)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(X, A, c));\n    MOD_ADD(X);\ncleanup:\n    return ret;\n}\n\nMBEDTLS_MAYBE_UNUSED\nstatic inline int mbedtls_mpi_sub_int_mod(const mbedtls_ecp_group *grp,\n                                          mbedtls_mpi *X,\n                                          const mbedtls_mpi *A,\n                                          mbedtls_mpi_uint c)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(X, A, c));\n    MOD_SUB(X);\ncleanup:\n    return ret;\n}\n\n#define MPI_ECP_SUB_INT(X, A, c)             \\\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int_mod(grp, X, A, c))\n\nMBEDTLS_MAYBE_UNUSED\nstatic inline int mbedtls_mpi_shift_l_mod(const mbedtls_ecp_group *grp,\n                                          mbedtls_mpi *X,\n                                          size_t count)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(X, count));\n    MOD_ADD(X);\ncleanup:\n    return ret;\n}\n\n/*\n * Macro wrappers around ECP modular arithmetic\n *\n * Currently, these wrappers are defined via the bignum module.\n */\n\n#define MPI_ECP_ADD(X, A, B)                                                  \\\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mod(grp, X, A, B))\n\n#define MPI_ECP_SUB(X, A, B)                                                  \\\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, X, A, B))\n\n#define MPI_ECP_MUL(X, A, B)                                                  \\\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, X, A, B))\n\n#define MPI_ECP_SQR(X, A)                                                     \\\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, X, A, A))\n\n#define MPI_ECP_MUL_INT(X, A, c)                                              \\\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int_mod(grp, X, A, c))\n\n#define MPI_ECP_INV(dst, src)                                                 \\\n    MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(NULL, (dst), (src), &grp->P))\n\n#define MPI_ECP_MOV(X, A)                                                     \\\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A))\n\n#define MPI_ECP_SHIFT_L(X, count)                                             \\\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l_mod(grp, X, count))\n\n#define MPI_ECP_LSET(X, c)                                                    \\\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, c))\n\n#define MPI_ECP_CMP_INT(X, c)                                                 \\\n    mbedtls_mpi_cmp_int(X, c)\n\n#define MPI_ECP_CMP(X, Y)                                                     \\\n    mbedtls_mpi_cmp_mpi(X, Y)\n\n/* Needs f_rng, p_rng to be defined. */\n#define MPI_ECP_RAND(X)                                                       \\\n    MBEDTLS_MPI_CHK(mbedtls_mpi_random((X), 2, &grp->P, f_rng, p_rng))\n\n/* Conditional negation\n * Needs grp and a temporary MPI tmp to be defined. */\n#define MPI_ECP_COND_NEG(X, cond)                                        \\\n    do                                                                     \\\n    {                                                                      \\\n        unsigned char nonzero = mbedtls_mpi_cmp_int((X), 0) != 0;        \\\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&tmp, &grp->P, (X)));      \\\n        MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign((X), &tmp,          \\\n                                                     nonzero & cond)); \\\n    } while (0)\n\n#define MPI_ECP_NEG(X) MPI_ECP_COND_NEG((X), 1)\n\n#define MPI_ECP_VALID(X)                      \\\n    ((X)->p != NULL)\n\n#define MPI_ECP_COND_ASSIGN(X, Y, cond)       \\\n    MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign((X), (Y), (cond)))\n\n#define MPI_ECP_COND_SWAP(X, Y, cond)       \\\n    MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_swap((X), (Y), (cond)))\n\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n\n/*\n * Computes the right-hand side of the Short Weierstrass equation\n * RHS = X^3 + A X + B\n */\nstatic int ecp_sw_rhs(const mbedtls_ecp_group *grp,\n                      mbedtls_mpi *rhs,\n                      const mbedtls_mpi *X)\n{\n    int ret;\n\n    /* Compute X^3 + A X + B as X (X^2 + A) + B */\n    MPI_ECP_SQR(rhs, X);\n\n    /* Special case for A = -3 */\n    if (mbedtls_ecp_group_a_is_minus_3(grp)) {\n        MPI_ECP_SUB_INT(rhs, rhs, 3);\n    } else {\n        MPI_ECP_ADD(rhs, rhs, &grp->A);\n    }\n\n    MPI_ECP_MUL(rhs, rhs, X);\n    MPI_ECP_ADD(rhs, rhs, &grp->B);\n\ncleanup:\n    return ret;\n}\n\n/*\n * Derive Y from X and a parity bit\n */\nstatic int mbedtls_ecp_sw_derive_y(const mbedtls_ecp_group *grp,\n                                   const mbedtls_mpi *X,\n                                   mbedtls_mpi *Y,\n                                   int parity_bit)\n{\n    /* w = y^2 = x^3 + ax + b\n     * y = sqrt(w) = w^((p+1)/4) mod p   (for prime p where p = 3 mod 4)\n     *\n     * Note: this method for extracting square root does not validate that w\n     * was indeed a square so this function will return garbage in Y if X\n     * does not correspond to a point on the curve.\n     */\n\n    /* Check prerequisite p = 3 mod 4 */\n    if (mbedtls_mpi_get_bit(&grp->P, 0) != 1 ||\n        mbedtls_mpi_get_bit(&grp->P, 1) != 1) {\n        return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n    }\n\n    int ret;\n    mbedtls_mpi exp;\n    mbedtls_mpi_init(&exp);\n\n    /* use Y to store intermediate result, actually w above */\n    MBEDTLS_MPI_CHK(ecp_sw_rhs(grp, Y, X));\n\n    /* w = y^2 */ /* Y contains y^2 intermediate result */\n    /* exp = ((p+1)/4) */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&exp, &grp->P, 1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&exp, 2));\n    /* sqrt(w) = w^((p+1)/4) mod p   (for prime p where p = 3 mod 4) */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(Y, Y /*y^2*/, &exp, &grp->P, NULL));\n\n    /* check parity bit match or else invert Y */\n    /* This quick inversion implementation is valid because Y != 0 for all\n     * Short Weierstrass curves supported by mbedtls, as each supported curve\n     * has an order that is a large prime, so each supported curve does not\n     * have any point of order 2, and a point with Y == 0 would be of order 2 */\n    if (mbedtls_mpi_get_bit(Y, 0) != parity_bit) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(Y, &grp->P, Y));\n    }\n\ncleanup:\n\n    mbedtls_mpi_free(&exp);\n    return ret;\n}\n#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */\n\n#if defined(MBEDTLS_ECP_C)\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n/*\n * For curves in short Weierstrass form, we do all the internal operations in\n * Jacobian coordinates.\n *\n * For multiplication, we'll use a comb method with countermeasures against\n * SPA, hence timing attacks.\n */\n\n/*\n * Normalize jacobian coordinates so that Z == 0 || Z == 1  (GECC 3.2.1)\n * Cost: 1N := 1I + 3M + 1S\n */\nstatic int ecp_normalize_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt)\n{\n    if (MPI_ECP_CMP_INT(&pt->Z, 0) == 0) {\n        return 0;\n    }\n\n#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)\n    if (mbedtls_internal_ecp_grp_capable(grp)) {\n        return mbedtls_internal_ecp_normalize_jac(grp, pt);\n    }\n#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */\n\n#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)\n    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n#else\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi T;\n    mbedtls_mpi_init(&T);\n\n    MPI_ECP_INV(&T,       &pt->Z);            /* T   <-          1 / Z   */\n    MPI_ECP_MUL(&pt->Y,   &pt->Y,     &T);    /* Y'  <- Y*T    = Y / Z   */\n    MPI_ECP_SQR(&T,       &T);                /* T   <- T^2    = 1 / Z^2 */\n    MPI_ECP_MUL(&pt->X,   &pt->X,     &T);    /* X   <- X  * T = X / Z^2 */\n    MPI_ECP_MUL(&pt->Y,   &pt->Y,     &T);    /* Y'' <- Y' * T = Y / Z^3 */\n\n    MPI_ECP_LSET(&pt->Z, 1);\n\ncleanup:\n\n    mbedtls_mpi_free(&T);\n\n    return ret;\n#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) */\n}\n\n/*\n * Normalize jacobian coordinates of an array of (pointers to) points,\n * using Montgomery's trick to perform only one inversion mod P.\n * (See for example Cohen's \"A Course in Computational Algebraic Number\n * Theory\", Algorithm 10.3.4.)\n *\n * Warning: fails (returning an error) if one of the points is zero!\n * This should never happen, see choice of w in ecp_mul_comb().\n *\n * Cost: 1N(t) := 1I + (6t - 3)M + 1S\n */\nstatic int ecp_normalize_jac_many(const mbedtls_ecp_group *grp,\n                                  mbedtls_ecp_point *T[], size_t T_size)\n{\n    if (T_size < 2) {\n        return ecp_normalize_jac(grp, *T);\n    }\n\n#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)\n    if (mbedtls_internal_ecp_grp_capable(grp)) {\n        return mbedtls_internal_ecp_normalize_jac_many(grp, T, T_size);\n    }\n#endif\n\n#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)\n    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n#else\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t i;\n    mbedtls_mpi *c, t;\n\n    if ((c = mbedtls_calloc(T_size, sizeof(mbedtls_mpi))) == NULL) {\n        return MBEDTLS_ERR_ECP_ALLOC_FAILED;\n    }\n\n    mbedtls_mpi_init(&t);\n\n    mpi_init_many(c, T_size);\n    /*\n     * c[i] = Z_0 * ... * Z_i,   i = 0,..,n := T_size-1\n     */\n    MPI_ECP_MOV(&c[0], &T[0]->Z);\n    for (i = 1; i < T_size; i++) {\n        MPI_ECP_MUL(&c[i], &c[i-1], &T[i]->Z);\n    }\n\n    /*\n     * c[n] = 1 / (Z_0 * ... * Z_n) mod P\n     */\n    MPI_ECP_INV(&c[T_size-1], &c[T_size-1]);\n\n    for (i = T_size - 1;; i--) {\n        /* At the start of iteration i (note that i decrements), we have\n         * - c[j] = Z_0 * .... * Z_j        for j  < i,\n         * - c[j] = 1 / (Z_0 * .... * Z_j)  for j == i,\n         *\n         * This is maintained via\n         * - c[i-1] <- c[i] * Z_i\n         *\n         * We also derive 1/Z_i = c[i] * c[i-1] for i>0 and use that\n         * to do the actual normalization. For i==0, we already have\n         * c[0] = 1 / Z_0.\n         */\n\n        if (i > 0) {\n            /* Compute 1/Z_i and establish invariant for the next iteration. */\n            MPI_ECP_MUL(&t,      &c[i], &c[i-1]);\n            MPI_ECP_MUL(&c[i-1], &c[i], &T[i]->Z);\n        } else {\n            MPI_ECP_MOV(&t, &c[0]);\n        }\n\n        /* Now t holds 1 / Z_i; normalize as in ecp_normalize_jac() */\n        MPI_ECP_MUL(&T[i]->Y, &T[i]->Y, &t);\n        MPI_ECP_SQR(&t,       &t);\n        MPI_ECP_MUL(&T[i]->X, &T[i]->X, &t);\n        MPI_ECP_MUL(&T[i]->Y, &T[i]->Y, &t);\n\n        /*\n         * Post-precessing: reclaim some memory by shrinking coordinates\n         * - not storing Z (always 1)\n         * - shrinking other coordinates, but still keeping the same number of\n         *   limbs as P, as otherwise it will too likely be regrown too fast.\n         */\n        MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(&T[i]->X, grp->P.n));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(&T[i]->Y, grp->P.n));\n\n        MPI_ECP_LSET(&T[i]->Z, 1);\n\n        if (i == 0) {\n            break;\n        }\n    }\n\ncleanup:\n\n    mbedtls_mpi_free(&t);\n    mpi_free_many(c, T_size);\n    mbedtls_free(c);\n\n    return ret;\n#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) */\n}\n\n/*\n * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.\n * \"inv\" must be 0 (don't invert) or 1 (invert) or the result will be invalid\n */\nstatic int ecp_safe_invert_jac(const mbedtls_ecp_group *grp,\n                               mbedtls_ecp_point *Q,\n                               unsigned char inv)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi tmp;\n    mbedtls_mpi_init(&tmp);\n\n    MPI_ECP_COND_NEG(&Q->Y, inv);\n\ncleanup:\n    mbedtls_mpi_free(&tmp);\n    return ret;\n}\n\n/*\n * Point doubling R = 2 P, Jacobian coordinates\n *\n * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 .\n *\n * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR\n * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.\n *\n * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.\n *\n * Cost: 1D := 3M + 4S          (A ==  0)\n *             4M + 4S          (A == -3)\n *             3M + 6S + 1a     otherwise\n */\nstatic int ecp_double_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n                          const mbedtls_ecp_point *P,\n                          mbedtls_mpi tmp[4])\n{\n#if defined(MBEDTLS_SELF_TEST)\n    dbl_count++;\n#endif\n\n#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)\n    if (mbedtls_internal_ecp_grp_capable(grp)) {\n        return mbedtls_internal_ecp_double_jac(grp, R, P);\n    }\n#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */\n\n#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)\n    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n#else\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* Special case for A = -3 */\n    if (mbedtls_ecp_group_a_is_minus_3(grp)) {\n        /* tmp[0] <- M = 3(X + Z^2)(X - Z^2) */\n        MPI_ECP_SQR(&tmp[1],  &P->Z);\n        MPI_ECP_ADD(&tmp[2],  &P->X,  &tmp[1]);\n        MPI_ECP_SUB(&tmp[3],  &P->X,  &tmp[1]);\n        MPI_ECP_MUL(&tmp[1],  &tmp[2],     &tmp[3]);\n        MPI_ECP_MUL_INT(&tmp[0],  &tmp[1],     3);\n    } else {\n        /* tmp[0] <- M = 3.X^2 + A.Z^4 */\n        MPI_ECP_SQR(&tmp[1],  &P->X);\n        MPI_ECP_MUL_INT(&tmp[0],  &tmp[1],  3);\n\n        /* Optimize away for \"koblitz\" curves with A = 0 */\n        if (MPI_ECP_CMP_INT(&grp->A, 0) != 0) {\n            /* M += A.Z^4 */\n            MPI_ECP_SQR(&tmp[1],  &P->Z);\n            MPI_ECP_SQR(&tmp[2],  &tmp[1]);\n            MPI_ECP_MUL(&tmp[1],  &tmp[2],     &grp->A);\n            MPI_ECP_ADD(&tmp[0],  &tmp[0],     &tmp[1]);\n        }\n    }\n\n    /* tmp[1] <- S = 4.X.Y^2 */\n    MPI_ECP_SQR(&tmp[2],  &P->Y);\n    MPI_ECP_SHIFT_L(&tmp[2],  1);\n    MPI_ECP_MUL(&tmp[1],  &P->X, &tmp[2]);\n    MPI_ECP_SHIFT_L(&tmp[1],  1);\n\n    /* tmp[3] <- U = 8.Y^4 */\n    MPI_ECP_SQR(&tmp[3],  &tmp[2]);\n    MPI_ECP_SHIFT_L(&tmp[3],  1);\n\n    /* tmp[2] <- T = M^2 - 2.S */\n    MPI_ECP_SQR(&tmp[2],  &tmp[0]);\n    MPI_ECP_SUB(&tmp[2],  &tmp[2], &tmp[1]);\n    MPI_ECP_SUB(&tmp[2],  &tmp[2], &tmp[1]);\n\n    /* tmp[1] <- S = M(S - T) - U */\n    MPI_ECP_SUB(&tmp[1],  &tmp[1],     &tmp[2]);\n    MPI_ECP_MUL(&tmp[1],  &tmp[1],     &tmp[0]);\n    MPI_ECP_SUB(&tmp[1],  &tmp[1],     &tmp[3]);\n\n    /* tmp[3] <- U = 2.Y.Z */\n    MPI_ECP_MUL(&tmp[3],  &P->Y,  &P->Z);\n    MPI_ECP_SHIFT_L(&tmp[3],  1);\n\n    /* Store results */\n    MPI_ECP_MOV(&R->X, &tmp[2]);\n    MPI_ECP_MOV(&R->Y, &tmp[1]);\n    MPI_ECP_MOV(&R->Z, &tmp[3]);\n\ncleanup:\n\n    return ret;\n#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) */\n}\n\n/*\n * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)\n *\n * The coordinates of Q must be normalized (= affine),\n * but those of P don't need to. R is not normalized.\n *\n * P,Q,R may alias, but only at the level of EC points: they must be either\n * equal as pointers, or disjoint (including the coordinate data buffers).\n * Fine-grained aliasing at the level of coordinates is not supported.\n *\n * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.\n * None of these cases can happen as intermediate step in ecp_mul_comb():\n * - at each step, P, Q and R are multiples of the base point, the factor\n *   being less than its order, so none of them is zero;\n * - Q is an odd multiple of the base point, P an even multiple,\n *   due to the choice of precomputed points in the modified comb method.\n * So branches for these cases do not leak secret information.\n *\n * Cost: 1A := 8M + 3S\n */\nstatic int ecp_add_mixed(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n                         const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,\n                         mbedtls_mpi tmp[4])\n{\n#if defined(MBEDTLS_SELF_TEST)\n    add_count++;\n#endif\n\n#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)\n    if (mbedtls_internal_ecp_grp_capable(grp)) {\n        return mbedtls_internal_ecp_add_mixed(grp, R, P, Q);\n    }\n#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */\n\n#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_ADD_MIXED_ALT)\n    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n#else\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* NOTE: Aliasing between input and output is allowed, so one has to make\n     *       sure that at the point X,Y,Z are written, {P,Q}->{X,Y,Z} are no\n     *       longer read from. */\n    mbedtls_mpi * const X = &R->X;\n    mbedtls_mpi * const Y = &R->Y;\n    mbedtls_mpi * const Z = &R->Z;\n\n    if (!MPI_ECP_VALID(&Q->Z)) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    /*\n     * Trivial cases: P == 0 or Q == 0 (case 1)\n     */\n    if (MPI_ECP_CMP_INT(&P->Z, 0) == 0) {\n        return mbedtls_ecp_copy(R, Q);\n    }\n\n    if (MPI_ECP_CMP_INT(&Q->Z, 0) == 0) {\n        return mbedtls_ecp_copy(R, P);\n    }\n\n    /*\n     * Make sure Q coordinates are normalized\n     */\n    if (MPI_ECP_CMP_INT(&Q->Z, 1) != 0) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    MPI_ECP_SQR(&tmp[0], &P->Z);\n    MPI_ECP_MUL(&tmp[1], &tmp[0], &P->Z);\n    MPI_ECP_MUL(&tmp[0], &tmp[0], &Q->X);\n    MPI_ECP_MUL(&tmp[1], &tmp[1], &Q->Y);\n    MPI_ECP_SUB(&tmp[0], &tmp[0], &P->X);\n    MPI_ECP_SUB(&tmp[1], &tmp[1], &P->Y);\n\n    /* Special cases (2) and (3) */\n    if (MPI_ECP_CMP_INT(&tmp[0], 0) == 0) {\n        if (MPI_ECP_CMP_INT(&tmp[1], 0) == 0) {\n            ret = ecp_double_jac(grp, R, P, tmp);\n            goto cleanup;\n        } else {\n            ret = mbedtls_ecp_set_zero(R);\n            goto cleanup;\n        }\n    }\n\n    /* {P,Q}->Z no longer used, so OK to write to Z even if there's aliasing. */\n    MPI_ECP_MUL(Z,        &P->Z,    &tmp[0]);\n    MPI_ECP_SQR(&tmp[2],  &tmp[0]);\n    MPI_ECP_MUL(&tmp[3],  &tmp[2],  &tmp[0]);\n    MPI_ECP_MUL(&tmp[2],  &tmp[2],  &P->X);\n\n    MPI_ECP_MOV(&tmp[0], &tmp[2]);\n    MPI_ECP_SHIFT_L(&tmp[0], 1);\n\n    /* {P,Q}->X no longer used, so OK to write to X even if there's aliasing. */\n    MPI_ECP_SQR(X,        &tmp[1]);\n    MPI_ECP_SUB(X,        X,        &tmp[0]);\n    MPI_ECP_SUB(X,        X,        &tmp[3]);\n    MPI_ECP_SUB(&tmp[2],  &tmp[2],  X);\n    MPI_ECP_MUL(&tmp[2],  &tmp[2],  &tmp[1]);\n    MPI_ECP_MUL(&tmp[3],  &tmp[3],  &P->Y);\n    /* {P,Q}->Y no longer used, so OK to write to Y even if there's aliasing. */\n    MPI_ECP_SUB(Y,     &tmp[2],     &tmp[3]);\n\ncleanup:\n\n    return ret;\n#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_ADD_MIXED_ALT) */\n}\n\n/*\n * Randomize jacobian coordinates:\n * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l\n * This is sort of the reverse operation of ecp_normalize_jac().\n *\n * This countermeasure was first suggested in [2].\n */\nstatic int ecp_randomize_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,\n                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)\n    if (mbedtls_internal_ecp_grp_capable(grp)) {\n        return mbedtls_internal_ecp_randomize_jac(grp, pt, f_rng, p_rng);\n    }\n#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */\n\n#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)\n    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n#else\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi l;\n\n    mbedtls_mpi_init(&l);\n\n    /* Generate l such that 1 < l < p */\n    MPI_ECP_RAND(&l);\n\n    /* Z' = l * Z */\n    MPI_ECP_MUL(&pt->Z,   &pt->Z,     &l);\n\n    /* Y' = l * Y */\n    MPI_ECP_MUL(&pt->Y,   &pt->Y,     &l);\n\n    /* X' = l^2 * X */\n    MPI_ECP_SQR(&l,       &l);\n    MPI_ECP_MUL(&pt->X,   &pt->X,     &l);\n\n    /* Y'' = l^2 * Y' = l^3 * Y */\n    MPI_ECP_MUL(&pt->Y,   &pt->Y,     &l);\n\ncleanup:\n    mbedtls_mpi_free(&l);\n\n    if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {\n        ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;\n    }\n    return ret;\n#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) */\n}\n\n/*\n * Check and define parameters used by the comb method (see below for details)\n */\n#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7\n#error \"MBEDTLS_ECP_WINDOW_SIZE out of bounds\"\n#endif\n\n/* d = ceil( n / w ) */\n#define COMB_MAX_D      (MBEDTLS_ECP_MAX_BITS + 1) / 2\n\n/* number of precomputed points */\n#define COMB_MAX_PRE    (1 << (MBEDTLS_ECP_WINDOW_SIZE - 1))\n\n/*\n * Compute the representation of m that will be used with our comb method.\n *\n * The basic comb method is described in GECC 3.44 for example. We use a\n * modified version that provides resistance to SPA by avoiding zero\n * digits in the representation as in [3]. We modify the method further by\n * requiring that all K_i be odd, which has the small cost that our\n * representation uses one more K_i, due to carries, but saves on the size of\n * the precomputed table.\n *\n * Summary of the comb method and its modifications:\n *\n * - The goal is to compute m*P for some w*d-bit integer m.\n *\n * - The basic comb method splits m into the w-bit integers\n *   x[0] .. x[d-1] where x[i] consists of the bits in m whose\n *   index has residue i modulo d, and computes m * P as\n *   S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where\n *   S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P.\n *\n * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by\n *    .. + 2^{i-1} S[x[i-1]] - 2^i S[x[i]] + 2^{i+1} S[x[i]] + 2^{i+2} S[x[i+2]] ..,\n *   thereby successively converting it into a form where all summands\n *   are nonzero, at the cost of negative summands. This is the basic idea of [3].\n *\n * - More generally, even if x[i+1] != 0, we can first transform the sum as\n *   .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] ..,\n *   and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]].\n *   Performing and iterating this procedure for those x[i] that are even\n *   (keeping track of carry), we can transform the original sum into one of the form\n *   S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]]\n *   with all x'[i] odd. It is therefore only necessary to know S at odd indices,\n *   which is why we are only computing half of it in the first place in\n *   ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb.\n *\n * - For the sake of compactness, only the seven low-order bits of x[i]\n *   are used to represent its absolute value (K_i in the paper), and the msb\n *   of x[i] encodes the sign (s_i in the paper): it is set if and only if\n *   if s_i == -1;\n *\n * Calling conventions:\n * - x is an array of size d + 1\n * - w is the size, ie number of teeth, of the comb, and must be between\n *   2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)\n * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d\n *   (the result will be incorrect if these assumptions are not satisfied)\n */\nstatic void ecp_comb_recode_core(unsigned char x[], size_t d,\n                                 unsigned char w, const mbedtls_mpi *m)\n{\n    size_t i, j;\n    unsigned char c, cc, adjust;\n\n    memset(x, 0, d+1);\n\n    /* First get the classical comb values (except for x_d = 0) */\n    for (i = 0; i < d; i++) {\n        for (j = 0; j < w; j++) {\n            x[i] |= mbedtls_mpi_get_bit(m, i + d * j) << j;\n        }\n    }\n\n    /* Now make sure x_1 .. x_d are odd */\n    c = 0;\n    for (i = 1; i <= d; i++) {\n        /* Add carry and update it */\n        cc   = x[i] & c;\n        x[i] = x[i] ^ c;\n        c = cc;\n\n        /* Adjust if needed, avoiding branches */\n        adjust = 1 - (x[i] & 0x01);\n        c   |= x[i] & (x[i-1] * adjust);\n        x[i] = x[i] ^ (x[i-1] * adjust);\n        x[i-1] |= adjust << 7;\n    }\n}\n\n/*\n * Precompute points for the adapted comb method\n *\n * Assumption: T must be able to hold 2^{w - 1} elements.\n *\n * Operation: If i = i_{w-1} ... i_1 is the binary representation of i,\n *            sets T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P.\n *\n * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1)\n *\n * Note: Even comb values (those where P would be omitted from the\n *       sum defining T[i] above) are not needed in our adaption\n *       the comb method. See ecp_comb_recode_core().\n *\n * This function currently works in four steps:\n * (1) [dbl]      Computation of intermediate T[i] for 2-power values of i\n * (2) [norm_dbl] Normalization of coordinates of these T[i]\n * (3) [add]      Computation of all T[i]\n * (4) [norm_add] Normalization of all T[i]\n *\n * Step 1 can be interrupted but not the others; together with the final\n * coordinate normalization they are the largest steps done at once, depending\n * on the window size. Here are operation counts for P-256:\n *\n * step     (2)     (3)     (4)\n * w = 5    142     165     208\n * w = 4    136      77     160\n * w = 3    130      33     136\n * w = 2    124      11     124\n *\n * So if ECC operations are blocking for too long even with a low max_ops\n * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order\n * to minimize maximum blocking time.\n */\nstatic int ecp_precompute_comb(const mbedtls_ecp_group *grp,\n                               mbedtls_ecp_point T[], const mbedtls_ecp_point *P,\n                               unsigned char w, size_t d,\n                               mbedtls_ecp_restart_ctx *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char i;\n    size_t j = 0;\n    const unsigned char T_size = 1U << (w - 1);\n    mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1] = { NULL };\n\n    mbedtls_mpi tmp[4];\n\n    mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {\n        if (rs_ctx->rsm->state == ecp_rsm_pre_dbl) {\n            goto dbl;\n        }\n        if (rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl) {\n            goto norm_dbl;\n        }\n        if (rs_ctx->rsm->state == ecp_rsm_pre_add) {\n            goto add;\n        }\n        if (rs_ctx->rsm->state == ecp_rsm_pre_norm_add) {\n            goto norm_add;\n        }\n    }\n#else\n    (void) rs_ctx;\n#endif\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {\n        rs_ctx->rsm->state = ecp_rsm_pre_dbl;\n\n        /* initial state for the loop */\n        rs_ctx->rsm->i = 0;\n    }\n\ndbl:\n#endif\n    /*\n     * Set T[0] = P and\n     * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)\n     */\n    MBEDTLS_MPI_CHK(mbedtls_ecp_copy(&T[0], P));\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0) {\n        j = rs_ctx->rsm->i;\n    } else\n#endif\n    j = 0;\n\n    for (; j < d * (w - 1); j++) {\n        MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_DBL);\n\n        i = 1U << (j / d);\n        cur = T + i;\n\n        if (j % d == 0) {\n            MBEDTLS_MPI_CHK(mbedtls_ecp_copy(cur, T + (i >> 1)));\n        }\n\n        MBEDTLS_MPI_CHK(ecp_double_jac(grp, cur, cur, tmp));\n    }\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {\n        rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl;\n    }\n\nnorm_dbl:\n#endif\n    /*\n     * Normalize current elements in T to allow them to be used in\n     * ecp_add_mixed() below, which requires one normalized input.\n     *\n     * As T has holes, use an auxiliary array of pointers to elements in T.\n     *\n     */\n    j = 0;\n    for (i = 1; i < T_size; i <<= 1) {\n        TT[j++] = T + i;\n    }\n\n    MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV + 6 * j - 2);\n\n    MBEDTLS_MPI_CHK(ecp_normalize_jac_many(grp, TT, j));\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {\n        rs_ctx->rsm->state = ecp_rsm_pre_add;\n    }\n\nadd:\n#endif\n    /*\n     * Compute the remaining ones using the minimal number of additions\n     * Be careful to update T[2^l] only after using it!\n     */\n    MBEDTLS_ECP_BUDGET((T_size - 1) * MBEDTLS_ECP_OPS_ADD);\n\n    for (i = 1; i < T_size; i <<= 1) {\n        j = i;\n        while (j--) {\n            MBEDTLS_MPI_CHK(ecp_add_mixed(grp, &T[i + j], &T[j], &T[i], tmp));\n        }\n    }\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {\n        rs_ctx->rsm->state = ecp_rsm_pre_norm_add;\n    }\n\nnorm_add:\n#endif\n    /*\n     * Normalize final elements in T. Even though there are no holes now, we\n     * still need the auxiliary array for homogeneity with the previous\n     * call. Also, skip T[0] which is already normalised, being a copy of P.\n     */\n    for (j = 0; j + 1 < T_size; j++) {\n        TT[j] = T + j + 1;\n    }\n\n    MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV + 6 * j - 2);\n\n    MBEDTLS_MPI_CHK(ecp_normalize_jac_many(grp, TT, j));\n\n    /* Free Z coordinate (=1 after normalization) to save RAM.\n     * This makes T[i] invalid as mbedtls_ecp_points, but this is OK\n     * since from this point onwards, they are only accessed indirectly\n     * via the getter function ecp_select_comb() which does set the\n     * target's Z coordinate to 1. */\n    for (i = 0; i < T_size; i++) {\n        mbedtls_mpi_free(&T[i].Z);\n    }\n\ncleanup:\n\n    mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->rsm != NULL &&\n        ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {\n        if (rs_ctx->rsm->state == ecp_rsm_pre_dbl) {\n            rs_ctx->rsm->i = j;\n        }\n    }\n#endif\n\n    return ret;\n}\n\n/*\n * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]\n *\n * See ecp_comb_recode_core() for background\n */\nstatic int ecp_select_comb(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n                           const mbedtls_ecp_point T[], unsigned char T_size,\n                           unsigned char i)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char ii, j;\n\n    /* Ignore the \"sign\" bit and scale down */\n    ii =  (i & 0x7Fu) >> 1;\n\n    /* Read the whole table to thwart cache-based timing attacks */\n    for (j = 0; j < T_size; j++) {\n        MPI_ECP_COND_ASSIGN(&R->X, &T[j].X, j == ii);\n        MPI_ECP_COND_ASSIGN(&R->Y, &T[j].Y, j == ii);\n    }\n\n    /* Safely invert result if i is \"negative\" */\n    MBEDTLS_MPI_CHK(ecp_safe_invert_jac(grp, R, i >> 7));\n\n    MPI_ECP_LSET(&R->Z, 1);\n\ncleanup:\n    return ret;\n}\n\n/*\n * Core multiplication algorithm for the (modified) comb method.\n * This part is actually common with the basic comb method (GECC 3.44)\n *\n * Cost: d A + d D + 1 R\n */\nstatic int ecp_mul_comb_core(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n                             const mbedtls_ecp_point T[], unsigned char T_size,\n                             const unsigned char x[], size_t d,\n                             int (*f_rng)(void *, unsigned char *, size_t),\n                             void *p_rng,\n                             mbedtls_ecp_restart_ctx *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_point Txi;\n    mbedtls_mpi tmp[4];\n    size_t i;\n\n    mbedtls_ecp_point_init(&Txi);\n    mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));\n\n#if !defined(MBEDTLS_ECP_RESTARTABLE)\n    (void) rs_ctx;\n#endif\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->rsm != NULL &&\n        rs_ctx->rsm->state != ecp_rsm_comb_core) {\n        rs_ctx->rsm->i = 0;\n        rs_ctx->rsm->state = ecp_rsm_comb_core;\n    }\n\n    /* new 'if' instead of nested for the sake of the 'else' branch */\n    if (rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0) {\n        /* restore current index (R already pointing to rs_ctx->rsm->R) */\n        i = rs_ctx->rsm->i;\n    } else\n#endif\n    {\n        /* Start with a non-zero point and randomize its coordinates */\n        i = d;\n        MBEDTLS_MPI_CHK(ecp_select_comb(grp, R, T, T_size, x[i]));\n        if (f_rng != 0) {\n            MBEDTLS_MPI_CHK(ecp_randomize_jac(grp, R, f_rng, p_rng));\n        }\n    }\n\n    while (i != 0) {\n        MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD);\n        --i;\n\n        MBEDTLS_MPI_CHK(ecp_double_jac(grp, R, R, tmp));\n        MBEDTLS_MPI_CHK(ecp_select_comb(grp, &Txi, T, T_size, x[i]));\n        MBEDTLS_MPI_CHK(ecp_add_mixed(grp, R, R, &Txi, tmp));\n    }\n\ncleanup:\n\n    mbedtls_ecp_point_free(&Txi);\n    mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->rsm != NULL &&\n        ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {\n        rs_ctx->rsm->i = i;\n        /* no need to save R, already pointing to rs_ctx->rsm->R */\n    }\n#endif\n\n    return ret;\n}\n\n/*\n * Recode the scalar to get constant-time comb multiplication\n *\n * As the actual scalar recoding needs an odd scalar as a starting point,\n * this wrapper ensures that by replacing m by N - m if necessary, and\n * informs the caller that the result of multiplication will be negated.\n *\n * This works because we only support large prime order for Short Weierstrass\n * curves, so N is always odd hence either m or N - m is.\n *\n * See ecp_comb_recode_core() for background.\n */\nstatic int ecp_comb_recode_scalar(const mbedtls_ecp_group *grp,\n                                  const mbedtls_mpi *m,\n                                  unsigned char k[COMB_MAX_D + 1],\n                                  size_t d,\n                                  unsigned char w,\n                                  unsigned char *parity_trick)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi M, mm;\n\n    mbedtls_mpi_init(&M);\n    mbedtls_mpi_init(&mm);\n\n    /* N is always odd (see above), just make extra sure */\n    if (mbedtls_mpi_get_bit(&grp->N, 0) != 1) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    /* do we need the parity trick? */\n    *parity_trick = (mbedtls_mpi_get_bit(m, 0) == 0);\n\n    /* execute parity fix in constant time */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&M, m));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&mm, &grp->N, m));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(&M, &mm, *parity_trick));\n\n    /* actual scalar recoding */\n    ecp_comb_recode_core(k, d, w, &M);\n\ncleanup:\n    mbedtls_mpi_free(&mm);\n    mbedtls_mpi_free(&M);\n\n    return ret;\n}\n\n/*\n * Perform comb multiplication (for short Weierstrass curves)\n * once the auxiliary table has been pre-computed.\n *\n * Scalar recoding may use a parity trick that makes us compute -m * P,\n * if that is the case we'll need to recover m * P at the end.\n */\nstatic int ecp_mul_comb_after_precomp(const mbedtls_ecp_group *grp,\n                                      mbedtls_ecp_point *R,\n                                      const mbedtls_mpi *m,\n                                      const mbedtls_ecp_point *T,\n                                      unsigned char T_size,\n                                      unsigned char w,\n                                      size_t d,\n                                      int (*f_rng)(void *, unsigned char *, size_t),\n                                      void *p_rng,\n                                      mbedtls_ecp_restart_ctx *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char parity_trick;\n    unsigned char k[COMB_MAX_D + 1];\n    mbedtls_ecp_point *RR = R;\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {\n        RR = &rs_ctx->rsm->R;\n\n        if (rs_ctx->rsm->state == ecp_rsm_final_norm) {\n            goto final_norm;\n        }\n    }\n#endif\n\n    MBEDTLS_MPI_CHK(ecp_comb_recode_scalar(grp, m, k, d, w,\n                                           &parity_trick));\n    MBEDTLS_MPI_CHK(ecp_mul_comb_core(grp, RR, T, T_size, k, d,\n                                      f_rng, p_rng, rs_ctx));\n    MBEDTLS_MPI_CHK(ecp_safe_invert_jac(grp, RR, parity_trick));\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {\n        rs_ctx->rsm->state = ecp_rsm_final_norm;\n    }\n\nfinal_norm:\n    MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV);\n#endif\n    MBEDTLS_MPI_CHK(ecp_normalize_jac(grp, RR));\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, RR));\n    }\n#endif\n\ncleanup:\n    return ret;\n}\n\n/*\n * Pick window size based on curve size and whether we optimize for base point\n */\nstatic unsigned char ecp_pick_window_size(const mbedtls_ecp_group *grp,\n                                          unsigned char p_eq_g)\n{\n    unsigned char w;\n\n    /*\n     * Minimize the number of multiplications, that is minimize\n     * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )\n     * (see costs of the various parts, with 1S = 1M)\n     */\n    w = grp->nbits >= 384 ? 5 : 4;\n\n    /*\n     * If P == G, pre-compute a bit more, since this may be re-used later.\n     * Just adding one avoids upping the cost of the first mul too much,\n     * and the memory cost too.\n     */\n    if (p_eq_g) {\n        w++;\n    }\n\n    /*\n     * If static comb table may not be used (!p_eq_g) or static comb table does\n     * not exists, make sure w is within bounds.\n     * (The last test is useful only for very small curves in the test suite.)\n     *\n     * The user reduces MBEDTLS_ECP_WINDOW_SIZE does not changes the size of\n     * static comb table, because the size of static comb table is fixed when\n     * it is generated.\n     */\n#if (MBEDTLS_ECP_WINDOW_SIZE < 6)\n    if ((!p_eq_g || !ecp_group_is_static_comb_table(grp)) && w > MBEDTLS_ECP_WINDOW_SIZE) {\n        w = MBEDTLS_ECP_WINDOW_SIZE;\n    }\n#endif\n    if (w >= grp->nbits) {\n        w = 2;\n    }\n\n    return w;\n}\n\n/*\n * Multiplication using the comb method - for curves in short Weierstrass form\n *\n * This function is mainly responsible for administrative work:\n * - managing the restart context if enabled\n * - managing the table of precomputed points (passed between the below two\n *   functions): allocation, computation, ownership transfer, freeing.\n *\n * It delegates the actual arithmetic work to:\n *      ecp_precompute_comb() and ecp_mul_comb_with_precomp()\n *\n * See comments on ecp_comb_recode_core() regarding the computation strategy.\n */\nstatic int ecp_mul_comb(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n                        const mbedtls_mpi *m, const mbedtls_ecp_point *P,\n                        int (*f_rng)(void *, unsigned char *, size_t),\n                        void *p_rng,\n                        mbedtls_ecp_restart_ctx *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char w, p_eq_g, i;\n    size_t d;\n    unsigned char T_size = 0, T_ok = 0;\n    mbedtls_ecp_point *T = NULL;\n\n    ECP_RS_ENTER(rsm);\n\n    /* Is P the base point ? */\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\n    p_eq_g = (MPI_ECP_CMP(&P->Y, &grp->G.Y) == 0 &&\n              MPI_ECP_CMP(&P->X, &grp->G.X) == 0);\n#else\n    p_eq_g = 0;\n#endif\n\n    /* Pick window size and deduce related sizes */\n    w = ecp_pick_window_size(grp, p_eq_g);\n    T_size = 1U << (w - 1);\n    d = (grp->nbits + w - 1) / w;\n\n    /* Pre-computed table: do we have it already for the base point? */\n    if (p_eq_g && grp->T != NULL) {\n        /* second pointer to the same table, will be deleted on exit */\n        T = grp->T;\n        T_ok = 1;\n    } else\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    /* Pre-computed table: do we have one in progress? complete? */\n    if (rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL) {\n        /* transfer ownership of T from rsm to local function */\n        T = rs_ctx->rsm->T;\n        rs_ctx->rsm->T = NULL;\n        rs_ctx->rsm->T_size = 0;\n\n        /* This effectively jumps to the call to mul_comb_after_precomp() */\n        T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core;\n    } else\n#endif\n    /* Allocate table if we didn't have any */\n    {\n        T = mbedtls_calloc(T_size, sizeof(mbedtls_ecp_point));\n        if (T == NULL) {\n            ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;\n            goto cleanup;\n        }\n\n        for (i = 0; i < T_size; i++) {\n            mbedtls_ecp_point_init(&T[i]);\n        }\n\n        T_ok = 0;\n    }\n\n    /* Compute table (or finish computing it) if not done already */\n    if (!T_ok) {\n        MBEDTLS_MPI_CHK(ecp_precompute_comb(grp, T, P, w, d, rs_ctx));\n\n        if (p_eq_g) {\n            /* almost transfer ownership of T to the group, but keep a copy of\n             * the pointer to use for calling the next function more easily */\n            grp->T = T;\n            grp->T_size = T_size;\n        }\n    }\n\n    /* Actual comb multiplication using precomputed points */\n    MBEDTLS_MPI_CHK(ecp_mul_comb_after_precomp(grp, R, m,\n                                               T, T_size, w, d,\n                                               f_rng, p_rng, rs_ctx));\n\ncleanup:\n\n    /* does T belong to the group? */\n    if (T == grp->T) {\n        T = NULL;\n    }\n\n    /* does T belong to the restart context? */\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL) {\n        /* transfer ownership of T from local function to rsm */\n        rs_ctx->rsm->T_size = T_size;\n        rs_ctx->rsm->T = T;\n        T = NULL;\n    }\n#endif\n\n    /* did T belong to us? then let's destroy it! */\n    if (T != NULL) {\n        for (i = 0; i < T_size; i++) {\n            mbedtls_ecp_point_free(&T[i]);\n        }\n        mbedtls_free(T);\n    }\n\n    /* prevent caller from using invalid value */\n    int should_free_R = (ret != 0);\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    /* don't free R while in progress in case R == P */\n    if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {\n        should_free_R = 0;\n    }\n#endif\n    if (should_free_R) {\n        mbedtls_ecp_point_free(R);\n    }\n\n    ECP_RS_LEAVE(rsm);\n\n    return ret;\n}\n\n#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */\n\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\n/*\n * For Montgomery curves, we do all the internal arithmetic in projective\n * coordinates. Import/export of points uses only the x coordinates, which is\n * internally represented as X / Z.\n *\n * For scalar multiplication, we'll use a Montgomery ladder.\n */\n\n/*\n * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1\n * Cost: 1M + 1I\n */\nstatic int ecp_normalize_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P)\n{\n#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)\n    if (mbedtls_internal_ecp_grp_capable(grp)) {\n        return mbedtls_internal_ecp_normalize_mxz(grp, P);\n    }\n#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */\n\n#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)\n    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n#else\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    MPI_ECP_INV(&P->Z, &P->Z);\n    MPI_ECP_MUL(&P->X, &P->X, &P->Z);\n    MPI_ECP_LSET(&P->Z, 1);\n\ncleanup:\n    return ret;\n#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) */\n}\n\n/*\n * Randomize projective x/z coordinates:\n * (X, Z) -> (l X, l Z) for random l\n * This is sort of the reverse operation of ecp_normalize_mxz().\n *\n * This countermeasure was first suggested in [2].\n * Cost: 2M\n */\nstatic int ecp_randomize_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,\n                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)\n    if (mbedtls_internal_ecp_grp_capable(grp)) {\n        return mbedtls_internal_ecp_randomize_mxz(grp, P, f_rng, p_rng);\n    }\n#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */\n\n#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)\n    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n#else\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi l;\n    mbedtls_mpi_init(&l);\n\n    /* Generate l such that 1 < l < p */\n    MPI_ECP_RAND(&l);\n\n    MPI_ECP_MUL(&P->X, &P->X, &l);\n    MPI_ECP_MUL(&P->Z, &P->Z, &l);\n\ncleanup:\n    mbedtls_mpi_free(&l);\n\n    if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {\n        ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;\n    }\n    return ret;\n#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) */\n}\n\n/*\n * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),\n * for Montgomery curves in x/z coordinates.\n *\n * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3\n * with\n * d =  X1\n * P = (X2, Z2)\n * Q = (X3, Z3)\n * R = (X4, Z4)\n * S = (X5, Z5)\n * and eliminating temporary variables tO, ..., t4.\n *\n * Cost: 5M + 4S\n */\nstatic int ecp_double_add_mxz(const mbedtls_ecp_group *grp,\n                              mbedtls_ecp_point *R, mbedtls_ecp_point *S,\n                              const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,\n                              const mbedtls_mpi *d,\n                              mbedtls_mpi T[4])\n{\n#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)\n    if (mbedtls_internal_ecp_grp_capable(grp)) {\n        return mbedtls_internal_ecp_double_add_mxz(grp, R, S, P, Q, d);\n    }\n#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */\n\n#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)\n    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n#else\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MPI_ECP_ADD(&T[0], &P->X,   &P->Z);   /* Pp := PX + PZ                    */\n    MPI_ECP_SUB(&T[1], &P->X,   &P->Z);   /* Pm := PX - PZ                    */\n    MPI_ECP_ADD(&T[2], &Q->X,   &Q->Z);   /* Qp := QX + XZ                    */\n    MPI_ECP_SUB(&T[3], &Q->X,   &Q->Z);   /* Qm := QX - QZ                    */\n    MPI_ECP_MUL(&T[3], &T[3],   &T[0]);   /* Qm * Pp                          */\n    MPI_ECP_MUL(&T[2], &T[2],   &T[1]);   /* Qp * Pm                          */\n    MPI_ECP_SQR(&T[0], &T[0]);            /* Pp^2                             */\n    MPI_ECP_SQR(&T[1], &T[1]);            /* Pm^2                             */\n    MPI_ECP_MUL(&R->X, &T[0],   &T[1]);   /* Pp^2 * Pm^2                      */\n    MPI_ECP_SUB(&T[0], &T[0],   &T[1]);   /* Pp^2 - Pm^2                      */\n    MPI_ECP_MUL(&R->Z, &grp->A, &T[0]);   /* A * (Pp^2 - Pm^2)                */\n    MPI_ECP_ADD(&R->Z, &T[1],   &R->Z);   /* [ A * (Pp^2-Pm^2) ] + Pm^2       */\n    MPI_ECP_ADD(&S->X, &T[3],   &T[2]);   /* Qm*Pp + Qp*Pm                    */\n    MPI_ECP_SQR(&S->X, &S->X);            /* (Qm*Pp + Qp*Pm)^2                */\n    MPI_ECP_SUB(&S->Z, &T[3],   &T[2]);   /* Qm*Pp - Qp*Pm                    */\n    MPI_ECP_SQR(&S->Z, &S->Z);            /* (Qm*Pp - Qp*Pm)^2                */\n    MPI_ECP_MUL(&S->Z, d,       &S->Z);   /* d * ( Qm*Pp - Qp*Pm )^2          */\n    MPI_ECP_MUL(&R->Z, &T[0],   &R->Z);   /* [A*(Pp^2-Pm^2)+Pm^2]*(Pp^2-Pm^2) */\n\ncleanup:\n\n    return ret;\n#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) */\n}\n\n/*\n * Multiplication with Montgomery ladder in x/z coordinates,\n * for curves in Montgomery form\n */\nstatic int ecp_mul_mxz(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n                       const mbedtls_mpi *m, const mbedtls_ecp_point *P,\n                       int (*f_rng)(void *, unsigned char *, size_t),\n                       void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t i;\n    unsigned char b;\n    mbedtls_ecp_point RP;\n    mbedtls_mpi PX;\n    mbedtls_mpi tmp[4];\n    mbedtls_ecp_point_init(&RP); mbedtls_mpi_init(&PX);\n\n    mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));\n\n    if (f_rng == NULL) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    /* Save PX and read from P before writing to R, in case P == R */\n    MPI_ECP_MOV(&PX, &P->X);\n    MBEDTLS_MPI_CHK(mbedtls_ecp_copy(&RP, P));\n\n    /* Set R to zero in modified x/z coordinates */\n    MPI_ECP_LSET(&R->X, 1);\n    MPI_ECP_LSET(&R->Z, 0);\n    mbedtls_mpi_free(&R->Y);\n\n    /* RP.X might be slightly larger than P, so reduce it */\n    MOD_ADD(&RP.X);\n\n    /* Randomize coordinates of the starting point */\n    MBEDTLS_MPI_CHK(ecp_randomize_mxz(grp, &RP, f_rng, p_rng));\n\n    /* Loop invariant: R = result so far, RP = R + P */\n    i = grp->nbits + 1; /* one past the (zero-based) required msb for private keys */\n    while (i-- > 0) {\n        b = mbedtls_mpi_get_bit(m, i);\n        /*\n         *  if (b) R = 2R + P else R = 2R,\n         * which is:\n         *  if (b) double_add( RP, R, RP, R )\n         *  else   double_add( R, RP, R, RP )\n         * but using safe conditional swaps to avoid leaks\n         */\n        MPI_ECP_COND_SWAP(&R->X, &RP.X, b);\n        MPI_ECP_COND_SWAP(&R->Z, &RP.Z, b);\n        MBEDTLS_MPI_CHK(ecp_double_add_mxz(grp, R, &RP, R, &RP, &PX, tmp));\n        MPI_ECP_COND_SWAP(&R->X, &RP.X, b);\n        MPI_ECP_COND_SWAP(&R->Z, &RP.Z, b);\n    }\n\n    MBEDTLS_MPI_CHK(ecp_normalize_mxz(grp, R));\n\ncleanup:\n    mbedtls_ecp_point_free(&RP); mbedtls_mpi_free(&PX);\n\n    mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));\n    return ret;\n}\n\n#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */\n\n/*\n * Restartable multiplication R = m * P\n *\n * This internal function can be called without an RNG in case where we know\n * the inputs are not sensitive.\n */\nstatic int ecp_mul_restartable_internal(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n                                        const mbedtls_mpi *m, const mbedtls_ecp_point *P,\n                                        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,\n                                        mbedtls_ecp_restart_ctx *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n#if defined(MBEDTLS_ECP_INTERNAL_ALT)\n    char is_grp_capable = 0;\n#endif\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    /* reset ops count for this call if top-level */\n    if (rs_ctx != NULL && rs_ctx->depth++ == 0) {\n        rs_ctx->ops_done = 0;\n    }\n#else\n    (void) rs_ctx;\n#endif\n\n#if defined(MBEDTLS_ECP_INTERNAL_ALT)\n    if ((is_grp_capable = mbedtls_internal_ecp_grp_capable(grp))) {\n        MBEDTLS_MPI_CHK(mbedtls_internal_ecp_init(grp));\n    }\n#endif /* MBEDTLS_ECP_INTERNAL_ALT */\n\n    int restarting = 0;\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);\n#endif\n    /* skip argument check when restarting */\n    if (!restarting) {\n        /* check_privkey is free */\n        MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_CHK);\n\n        /* Common sanity checks */\n        MBEDTLS_MPI_CHK(mbedtls_ecp_check_privkey(grp, m));\n        MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P));\n    }\n\n    ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\n    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {\n        MBEDTLS_MPI_CHK(ecp_mul_mxz(grp, R, m, P, f_rng, p_rng));\n    }\n#endif\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {\n        MBEDTLS_MPI_CHK(ecp_mul_comb(grp, R, m, P, f_rng, p_rng, rs_ctx));\n    }\n#endif\n\ncleanup:\n\n#if defined(MBEDTLS_ECP_INTERNAL_ALT)\n    if (is_grp_capable) {\n        mbedtls_internal_ecp_free(grp);\n    }\n#endif /* MBEDTLS_ECP_INTERNAL_ALT */\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL) {\n        rs_ctx->depth--;\n    }\n#endif\n\n    return ret;\n}\n\n/*\n * Restartable multiplication R = m * P\n */\nint mbedtls_ecp_mul_restartable(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n                                const mbedtls_mpi *m, const mbedtls_ecp_point *P,\n                                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,\n                                mbedtls_ecp_restart_ctx *rs_ctx)\n{\n    if (f_rng == NULL) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    return ecp_mul_restartable_internal(grp, R, m, P, f_rng, p_rng, rs_ctx);\n}\n\n/*\n * Multiplication R = m * P\n */\nint mbedtls_ecp_mul(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n                    const mbedtls_mpi *m, const mbedtls_ecp_point *P,\n                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    return mbedtls_ecp_mul_restartable(grp, R, m, P, f_rng, p_rng, NULL);\n}\n#endif /* MBEDTLS_ECP_C */\n\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n/*\n * Check that an affine point is valid as a public key,\n * short weierstrass curves (SEC1 3.2.3.1)\n */\nstatic int ecp_check_pubkey_sw(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi YY, RHS;\n\n    /* pt coordinates must be normalized for our checks */\n    if (mbedtls_mpi_cmp_int(&pt->X, 0) < 0 ||\n        mbedtls_mpi_cmp_int(&pt->Y, 0) < 0 ||\n        mbedtls_mpi_cmp_mpi(&pt->X, &grp->P) >= 0 ||\n        mbedtls_mpi_cmp_mpi(&pt->Y, &grp->P) >= 0) {\n        return MBEDTLS_ERR_ECP_INVALID_KEY;\n    }\n\n    mbedtls_mpi_init(&YY); mbedtls_mpi_init(&RHS);\n\n    /*\n     * YY = Y^2\n     * RHS = X^3 + A X + B\n     */\n    MPI_ECP_SQR(&YY,  &pt->Y);\n    MBEDTLS_MPI_CHK(ecp_sw_rhs(grp, &RHS, &pt->X));\n\n    if (MPI_ECP_CMP(&YY, &RHS) != 0) {\n        ret = MBEDTLS_ERR_ECP_INVALID_KEY;\n    }\n\ncleanup:\n\n    mbedtls_mpi_free(&YY); mbedtls_mpi_free(&RHS);\n\n    return ret;\n}\n#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */\n\n#if defined(MBEDTLS_ECP_C)\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n/*\n * R = m * P with shortcuts for m == 0, m == 1 and m == -1\n * NOT constant-time - ONLY for short Weierstrass!\n */\nstatic int mbedtls_ecp_mul_shortcuts(mbedtls_ecp_group *grp,\n                                     mbedtls_ecp_point *R,\n                                     const mbedtls_mpi *m,\n                                     const mbedtls_ecp_point *P,\n                                     mbedtls_ecp_restart_ctx *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi tmp;\n    mbedtls_mpi_init(&tmp);\n\n    if (mbedtls_mpi_cmp_int(m, 0) == 0) {\n        MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P));\n        MBEDTLS_MPI_CHK(mbedtls_ecp_set_zero(R));\n    } else if (mbedtls_mpi_cmp_int(m, 1) == 0) {\n        MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P));\n        MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P));\n    } else if (mbedtls_mpi_cmp_int(m, -1) == 0) {\n        MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P));\n        MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P));\n        MPI_ECP_NEG(&R->Y);\n    } else {\n        MBEDTLS_MPI_CHK(ecp_mul_restartable_internal(grp, R, m, P,\n                                                     NULL, NULL, rs_ctx));\n    }\n\ncleanup:\n    mbedtls_mpi_free(&tmp);\n\n    return ret;\n}\n\n/*\n * Restartable linear combination\n * NOT constant-time\n */\nint mbedtls_ecp_muladd_restartable(\n    mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n    const mbedtls_mpi *m, const mbedtls_ecp_point *P,\n    const mbedtls_mpi *n, const mbedtls_ecp_point *Q,\n    mbedtls_ecp_restart_ctx *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_point mP;\n    mbedtls_ecp_point *pmP = &mP;\n    mbedtls_ecp_point *pR = R;\n    mbedtls_mpi tmp[4];\n#if defined(MBEDTLS_ECP_INTERNAL_ALT)\n    char is_grp_capable = 0;\n#endif\n    if (mbedtls_ecp_get_type(grp) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {\n        return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n    }\n\n    mbedtls_ecp_point_init(&mP);\n    mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));\n\n    ECP_RS_ENTER(ma);\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->ma != NULL) {\n        /* redirect intermediate results to restart context */\n        pmP = &rs_ctx->ma->mP;\n        pR  = &rs_ctx->ma->R;\n\n        /* jump to next operation */\n        if (rs_ctx->ma->state == ecp_rsma_mul2) {\n            goto mul2;\n        }\n        if (rs_ctx->ma->state == ecp_rsma_add) {\n            goto add;\n        }\n        if (rs_ctx->ma->state == ecp_rsma_norm) {\n            goto norm;\n        }\n    }\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n\n    MBEDTLS_MPI_CHK(mbedtls_ecp_mul_shortcuts(grp, pmP, m, P, rs_ctx));\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->ma != NULL) {\n        rs_ctx->ma->state = ecp_rsma_mul2;\n    }\n\nmul2:\n#endif\n    MBEDTLS_MPI_CHK(mbedtls_ecp_mul_shortcuts(grp, pR,  n, Q, rs_ctx));\n\n#if defined(MBEDTLS_ECP_INTERNAL_ALT)\n    if ((is_grp_capable = mbedtls_internal_ecp_grp_capable(grp))) {\n        MBEDTLS_MPI_CHK(mbedtls_internal_ecp_init(grp));\n    }\n#endif /* MBEDTLS_ECP_INTERNAL_ALT */\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->ma != NULL) {\n        rs_ctx->ma->state = ecp_rsma_add;\n    }\n\nadd:\n#endif\n    MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_ADD);\n    MBEDTLS_MPI_CHK(ecp_add_mixed(grp, pR, pmP, pR, tmp));\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->ma != NULL) {\n        rs_ctx->ma->state = ecp_rsma_norm;\n    }\n\nnorm:\n#endif\n    MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV);\n    MBEDTLS_MPI_CHK(ecp_normalize_jac(grp, pR));\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && rs_ctx->ma != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, pR));\n    }\n#endif\n\ncleanup:\n\n    mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));\n\n#if defined(MBEDTLS_ECP_INTERNAL_ALT)\n    if (is_grp_capable) {\n        mbedtls_internal_ecp_free(grp);\n    }\n#endif /* MBEDTLS_ECP_INTERNAL_ALT */\n\n    mbedtls_ecp_point_free(&mP);\n\n    ECP_RS_LEAVE(ma);\n\n    return ret;\n}\n\n/*\n * Linear combination\n * NOT constant-time\n */\nint mbedtls_ecp_muladd(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,\n                       const mbedtls_mpi *m, const mbedtls_ecp_point *P,\n                       const mbedtls_mpi *n, const mbedtls_ecp_point *Q)\n{\n    return mbedtls_ecp_muladd_restartable(grp, R, m, P, n, Q, NULL);\n}\n#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */\n#endif /* MBEDTLS_ECP_C */\n\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n#define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) }\n#define ECP_MPI_INIT_ARRAY(x)   \\\n    ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint))\n/*\n * Constants for the two points other than 0, 1, -1 (mod p) in\n * https://cr.yp.to/ecdh.html#validate\n * See ecp_check_pubkey_x25519().\n */\nstatic const mbedtls_mpi_uint x25519_bad_point_1[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00),\n};\nstatic const mbedtls_mpi_uint x25519_bad_point_2[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57),\n};\nstatic const mbedtls_mpi ecp_x25519_bad_point_1 = ECP_MPI_INIT_ARRAY(\n    x25519_bad_point_1);\nstatic const mbedtls_mpi ecp_x25519_bad_point_2 = ECP_MPI_INIT_ARRAY(\n    x25519_bad_point_2);\n#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */\n\n/*\n * Check that the input point is not one of the low-order points.\n * This is recommended by the \"May the Fourth\" paper:\n * https://eprint.iacr.org/2017/806.pdf\n * Those points are never sent by an honest peer.\n */\nstatic int ecp_check_bad_points_mx(const mbedtls_mpi *X, const mbedtls_mpi *P,\n                                   const mbedtls_ecp_group_id grp_id)\n{\n    int ret;\n    mbedtls_mpi XmP;\n\n    mbedtls_mpi_init(&XmP);\n\n    /* Reduce X mod P so that we only need to check values less than P.\n     * We know X < 2^256 so we can proceed by subtraction. */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&XmP, X));\n    while (mbedtls_mpi_cmp_mpi(&XmP, P) >= 0) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&XmP, &XmP, P));\n    }\n\n    /* Check against the known bad values that are less than P. For Curve448\n     * these are 0, 1 and -1. For Curve25519 we check the values less than P\n     * from the following list: https://cr.yp.to/ecdh.html#validate */\n    if (mbedtls_mpi_cmp_int(&XmP, 1) <= 0) {  /* takes care of 0 and 1 */\n        ret = MBEDTLS_ERR_ECP_INVALID_KEY;\n        goto cleanup;\n    }\n\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n    if (grp_id == MBEDTLS_ECP_DP_CURVE25519) {\n        if (mbedtls_mpi_cmp_mpi(&XmP, &ecp_x25519_bad_point_1) == 0) {\n            ret = MBEDTLS_ERR_ECP_INVALID_KEY;\n            goto cleanup;\n        }\n\n        if (mbedtls_mpi_cmp_mpi(&XmP, &ecp_x25519_bad_point_2) == 0) {\n            ret = MBEDTLS_ERR_ECP_INVALID_KEY;\n            goto cleanup;\n        }\n    }\n#else\n    (void) grp_id;\n#endif\n\n    /* Final check: check if XmP + 1 is P (final because it changes XmP!) */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&XmP, &XmP, 1));\n    if (mbedtls_mpi_cmp_mpi(&XmP, P) == 0) {\n        ret = MBEDTLS_ERR_ECP_INVALID_KEY;\n        goto cleanup;\n    }\n\n    ret = 0;\n\ncleanup:\n    mbedtls_mpi_free(&XmP);\n\n    return ret;\n}\n\n/*\n * Check validity of a public key for Montgomery curves with x-only schemes\n */\nstatic int ecp_check_pubkey_mx(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt)\n{\n    /* [Curve25519 p. 5] Just check X is the correct number of bytes */\n    /* Allow any public value, if it's too big then we'll just reduce it mod p\n     * (RFC 7748 sec. 5 para. 3). */\n    if (mbedtls_mpi_size(&pt->X) > (grp->nbits + 7) / 8) {\n        return MBEDTLS_ERR_ECP_INVALID_KEY;\n    }\n\n    /* Implicit in all standards (as they don't consider negative numbers):\n     * X must be non-negative. This is normally ensured by the way it's\n     * encoded for transmission, but let's be extra sure. */\n    if (mbedtls_mpi_cmp_int(&pt->X, 0) < 0) {\n        return MBEDTLS_ERR_ECP_INVALID_KEY;\n    }\n\n    return ecp_check_bad_points_mx(&pt->X, &grp->P, grp->id);\n}\n#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */\n\n/*\n * Check that a point is valid as a public key\n */\nint mbedtls_ecp_check_pubkey(const mbedtls_ecp_group *grp,\n                             const mbedtls_ecp_point *pt)\n{\n    /* Must use affine coordinates */\n    if (mbedtls_mpi_cmp_int(&pt->Z, 1) != 0) {\n        return MBEDTLS_ERR_ECP_INVALID_KEY;\n    }\n\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\n    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {\n        return ecp_check_pubkey_mx(grp, pt);\n    }\n#endif\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {\n        return ecp_check_pubkey_sw(grp, pt);\n    }\n#endif\n    return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n}\n\n/*\n * Check that an mbedtls_mpi is valid as a private key\n */\nint mbedtls_ecp_check_privkey(const mbedtls_ecp_group *grp,\n                              const mbedtls_mpi *d)\n{\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\n    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {\n        /* see RFC 7748 sec. 5 para. 5 */\n        if (mbedtls_mpi_get_bit(d, 0) != 0 ||\n            mbedtls_mpi_get_bit(d, 1) != 0 ||\n            mbedtls_mpi_bitlen(d) != grp->nbits + 1) {  /* mbedtls_mpi_bitlen is one-based! */\n            return MBEDTLS_ERR_ECP_INVALID_KEY;\n        }\n\n        /* see [Curve25519] page 5 */\n        if (grp->nbits == 254 && mbedtls_mpi_get_bit(d, 2) != 0) {\n            return MBEDTLS_ERR_ECP_INVALID_KEY;\n        }\n\n        return 0;\n    }\n#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {\n        /* see SEC1 3.2 */\n        if (mbedtls_mpi_cmp_int(d, 1) < 0 ||\n            mbedtls_mpi_cmp_mpi(d, &grp->N) >= 0) {\n            return MBEDTLS_ERR_ECP_INVALID_KEY;\n        } else {\n            return 0;\n        }\n    }\n#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */\n\n    return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n}\n\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_gen_privkey_mx(size_t high_bit,\n                               mbedtls_mpi *d,\n                               int (*f_rng)(void *, unsigned char *, size_t),\n                               void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    size_t n_random_bytes = high_bit / 8 + 1;\n\n    /* [Curve25519] page 5 */\n    /* Generate a (high_bit+1)-bit random number by generating just enough\n     * random bytes, then shifting out extra bits from the top (necessary\n     * when (high_bit+1) is not a multiple of 8). */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(d, n_random_bytes,\n                                            f_rng, p_rng));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(d, 8 * n_random_bytes - high_bit - 1));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, high_bit, 1));\n\n    /* Make sure the last two bits are unset for Curve448, three bits for\n       Curve25519 */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, 0, 0));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, 1, 0));\n    if (high_bit == 254) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, 2, 0));\n    }\n\ncleanup:\n    return ret;\n}\n#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */\n\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\nstatic int mbedtls_ecp_gen_privkey_sw(\n    const mbedtls_mpi *N, mbedtls_mpi *d,\n    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    int ret = mbedtls_mpi_random(d, 1, N, f_rng, p_rng);\n    switch (ret) {\n        case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE:\n            return MBEDTLS_ERR_ECP_RANDOM_FAILED;\n        default:\n            return ret;\n    }\n}\n#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */\n\n/*\n * Generate a private key\n */\nint mbedtls_ecp_gen_privkey(const mbedtls_ecp_group *grp,\n                            mbedtls_mpi *d,\n                            int (*f_rng)(void *, unsigned char *, size_t),\n                            void *p_rng)\n{\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\n    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {\n        return mbedtls_ecp_gen_privkey_mx(grp->nbits, d, f_rng, p_rng);\n    }\n#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */\n\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {\n        return mbedtls_ecp_gen_privkey_sw(&grp->N, d, f_rng, p_rng);\n    }\n#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */\n\n    return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n}\n\n#if defined(MBEDTLS_ECP_C)\n/*\n * Generate a keypair with configurable base point\n */\nint mbedtls_ecp_gen_keypair_base(mbedtls_ecp_group *grp,\n                                 const mbedtls_ecp_point *G,\n                                 mbedtls_mpi *d, mbedtls_ecp_point *Q,\n                                 int (*f_rng)(void *, unsigned char *, size_t),\n                                 void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));\n    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, Q, d, G, f_rng, p_rng));\n\ncleanup:\n    return ret;\n}\n\n/*\n * Generate key pair, wrapper for conventional base point\n */\nint mbedtls_ecp_gen_keypair(mbedtls_ecp_group *grp,\n                            mbedtls_mpi *d, mbedtls_ecp_point *Q,\n                            int (*f_rng)(void *, unsigned char *, size_t),\n                            void *p_rng)\n{\n    return mbedtls_ecp_gen_keypair_base(grp, &grp->G, d, Q, f_rng, p_rng);\n}\n\n/*\n * Generate a keypair, prettier wrapper\n */\nint mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,\n                        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) {\n        return ret;\n    }\n\n    return mbedtls_ecp_gen_keypair(&key->grp, &key->d, &key->Q, f_rng, p_rng);\n}\n#endif /* MBEDTLS_ECP_C */\n\nint mbedtls_ecp_set_public_key(mbedtls_ecp_group_id grp_id,\n                               mbedtls_ecp_keypair *key,\n                               const mbedtls_ecp_point *Q)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (key->grp.id == MBEDTLS_ECP_DP_NONE) {\n        /* Group not set yet */\n        if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) {\n            return ret;\n        }\n    } else if (key->grp.id != grp_id) {\n        /* Group mismatch */\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n    return mbedtls_ecp_copy(&key->Q, Q);\n}\n\n\n#define ECP_CURVE25519_KEY_SIZE 32\n#define ECP_CURVE448_KEY_SIZE   56\n/*\n * Read a private key.\n */\nint mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,\n                         const unsigned char *buf, size_t buflen)\n{\n    int ret = 0;\n\n    if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) {\n        return ret;\n    }\n\n    ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\n    if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {\n        /*\n         * Mask the key as mandated by RFC7748 for Curve25519 and Curve448.\n         */\n        if (grp_id == MBEDTLS_ECP_DP_CURVE25519) {\n            if (buflen != ECP_CURVE25519_KEY_SIZE) {\n                return MBEDTLS_ERR_ECP_INVALID_KEY;\n            }\n\n            MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&key->d, buf, buflen));\n\n            /* Set the three least significant bits to 0 */\n            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 0, 0));\n            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 1, 0));\n            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 2, 0));\n\n            /* Set the most significant bit to 0 */\n            MBEDTLS_MPI_CHK(\n                mbedtls_mpi_set_bit(&key->d,\n                                    ECP_CURVE25519_KEY_SIZE * 8 - 1, 0)\n                );\n\n            /* Set the second most significant bit to 1 */\n            MBEDTLS_MPI_CHK(\n                mbedtls_mpi_set_bit(&key->d,\n                                    ECP_CURVE25519_KEY_SIZE * 8 - 2, 1)\n                );\n        } else if (grp_id == MBEDTLS_ECP_DP_CURVE448) {\n            if (buflen != ECP_CURVE448_KEY_SIZE) {\n                return MBEDTLS_ERR_ECP_INVALID_KEY;\n            }\n\n            MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&key->d, buf, buflen));\n\n            /* Set the two least significant bits to 0 */\n            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 0, 0));\n            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 1, 0));\n\n            /* Set the most significant bit to 1 */\n            MBEDTLS_MPI_CHK(\n                mbedtls_mpi_set_bit(&key->d,\n                                    ECP_CURVE448_KEY_SIZE * 8 - 1, 1)\n                );\n        }\n    }\n#endif\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n    if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&key->d, buf, buflen));\n    }\n#endif\n\n    if (ret == 0) {\n        MBEDTLS_MPI_CHK(mbedtls_ecp_check_privkey(&key->grp, &key->d));\n    }\n\ncleanup:\n\n    if (ret != 0) {\n        mbedtls_mpi_free(&key->d);\n    }\n\n    return ret;\n}\n\n/*\n * Write a private key.\n */\n#if !defined MBEDTLS_DEPRECATED_REMOVED\nint mbedtls_ecp_write_key(mbedtls_ecp_keypair *key,\n                          unsigned char *buf, size_t buflen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\n    if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {\n        if (key->grp.id == MBEDTLS_ECP_DP_CURVE25519) {\n            if (buflen < ECP_CURVE25519_KEY_SIZE) {\n                return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n            }\n\n        } else if (key->grp.id == MBEDTLS_ECP_DP_CURVE448) {\n            if (buflen < ECP_CURVE448_KEY_SIZE) {\n                return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n            }\n        }\n        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(&key->d, buf, buflen));\n    }\n#endif\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n    if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&key->d, buf, buflen));\n    }\n\n#endif\ncleanup:\n\n    return ret;\n}\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n\nint mbedtls_ecp_write_key_ext(const mbedtls_ecp_keypair *key,\n                              size_t *olen, unsigned char *buf, size_t buflen)\n{\n    size_t len = (key->grp.nbits + 7) / 8;\n    if (len > buflen) {\n        /* For robustness, ensure *olen <= buflen even on error. */\n        *olen = 0;\n        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n    }\n    *olen = len;\n\n    /* Private key not set */\n    if (key->d.n == 0) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\n    if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {\n        return mbedtls_mpi_write_binary_le(&key->d, buf, len);\n    }\n#endif\n\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n    if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {\n        return mbedtls_mpi_write_binary(&key->d, buf, len);\n    }\n#endif\n\n    /* Private key set but no recognized curve type? This shouldn't happen. */\n    return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n}\n\n/*\n * Write a public key.\n */\nint mbedtls_ecp_write_public_key(const mbedtls_ecp_keypair *key,\n                                 int format, size_t *olen,\n                                 unsigned char *buf, size_t buflen)\n{\n    return mbedtls_ecp_point_write_binary(&key->grp, &key->Q,\n                                          format, olen, buf, buflen);\n}\n\n\n#if defined(MBEDTLS_ECP_C)\n/*\n * Check a public-private key pair\n */\nint mbedtls_ecp_check_pub_priv(\n    const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv,\n    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_point Q;\n    mbedtls_ecp_group grp;\n    if (pub->grp.id == MBEDTLS_ECP_DP_NONE ||\n        pub->grp.id != prv->grp.id ||\n        mbedtls_mpi_cmp_mpi(&pub->Q.X, &prv->Q.X) ||\n        mbedtls_mpi_cmp_mpi(&pub->Q.Y, &prv->Q.Y) ||\n        mbedtls_mpi_cmp_mpi(&pub->Q.Z, &prv->Q.Z)) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    mbedtls_ecp_point_init(&Q);\n    mbedtls_ecp_group_init(&grp);\n\n    /* mbedtls_ecp_mul() needs a non-const group... */\n    mbedtls_ecp_group_copy(&grp, &prv->grp);\n\n    /* Also checks d is valid */\n    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&grp, &Q, &prv->d, &prv->grp.G, f_rng, p_rng));\n\n    if (mbedtls_mpi_cmp_mpi(&Q.X, &prv->Q.X) ||\n        mbedtls_mpi_cmp_mpi(&Q.Y, &prv->Q.Y) ||\n        mbedtls_mpi_cmp_mpi(&Q.Z, &prv->Q.Z)) {\n        ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n\ncleanup:\n    mbedtls_ecp_point_free(&Q);\n    mbedtls_ecp_group_free(&grp);\n\n    return ret;\n}\n\nint mbedtls_ecp_keypair_calc_public(mbedtls_ecp_keypair *key,\n                                    int (*f_rng)(void *, unsigned char *, size_t),\n                                    void *p_rng)\n{\n    return mbedtls_ecp_mul(&key->grp, &key->Q, &key->d, &key->grp.G,\n                           f_rng, p_rng);\n}\n#endif /* MBEDTLS_ECP_C */\n\nmbedtls_ecp_group_id mbedtls_ecp_keypair_get_group_id(\n    const mbedtls_ecp_keypair *key)\n{\n    return key->grp.id;\n}\n\n/*\n * Export generic key-pair parameters.\n */\nint mbedtls_ecp_export(const mbedtls_ecp_keypair *key, mbedtls_ecp_group *grp,\n                       mbedtls_mpi *d, mbedtls_ecp_point *Q)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (grp != NULL && (ret = mbedtls_ecp_group_copy(grp, &key->grp)) != 0) {\n        return ret;\n    }\n\n    if (d != NULL && (ret = mbedtls_mpi_copy(d, &key->d)) != 0) {\n        return ret;\n    }\n\n    if (Q != NULL && (ret = mbedtls_ecp_copy(Q, &key->Q)) != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SELF_TEST)\n\n#if defined(MBEDTLS_ECP_C)\n/*\n * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!\n *\n * This is the linear congruential generator from numerical recipes,\n * except we only use the low byte as the output. See\n * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use\n */\nstatic int self_test_rng(void *ctx, unsigned char *out, size_t len)\n{\n    static uint32_t state = 42;\n\n    (void) ctx;\n\n    for (size_t i = 0; i < len; i++) {\n        state = state * 1664525u + 1013904223u;\n        out[i] = (unsigned char) state;\n    }\n\n    return 0;\n}\n\n/* Adjust the exponent to be a valid private point for the specified curve.\n * This is sometimes necessary because we use a single set of exponents\n * for all curves but the validity of values depends on the curve. */\nstatic int self_test_adjust_exponent(const mbedtls_ecp_group *grp,\n                                     mbedtls_mpi *m)\n{\n    int ret = 0;\n    switch (grp->id) {\n    /* If Curve25519 is available, then that's what we use for the\n     * Montgomery test, so we don't need the adjustment code. */\n#if !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n        case MBEDTLS_ECP_DP_CURVE448:\n            /* Move highest bit from 254 to N-1. Setting bit N-1 is\n             * necessary to enforce the highest-bit-set constraint. */\n            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(m, 254, 0));\n            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(m, grp->nbits, 1));\n            /* Copy second-highest bit from 253 to N-2. This is not\n             * necessary but improves the test variety a bit. */\n            MBEDTLS_MPI_CHK(\n                mbedtls_mpi_set_bit(m, grp->nbits - 1,\n                                    mbedtls_mpi_get_bit(m, 253)));\n            break;\n#endif\n#endif /* ! defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) */\n        default:\n            /* Non-Montgomery curves and Curve25519 need no adjustment. */\n            (void) grp;\n            (void) m;\n            goto cleanup;\n    }\ncleanup:\n    return ret;\n}\n\n/* Calculate R = m.P for each m in exponents. Check that the number of\n * basic operations doesn't depend on the value of m. */\nstatic int self_test_point(int verbose,\n                           mbedtls_ecp_group *grp,\n                           mbedtls_ecp_point *R,\n                           mbedtls_mpi *m,\n                           const mbedtls_ecp_point *P,\n                           const char *const *exponents,\n                           size_t n_exponents)\n{\n    int ret = 0;\n    size_t i = 0;\n    unsigned long add_c_prev, dbl_c_prev, mul_c_prev;\n    add_count = 0;\n    dbl_count = 0;\n    mul_count = 0;\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(m, 16, exponents[0]));\n    MBEDTLS_MPI_CHK(self_test_adjust_exponent(grp, m));\n    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, R, m, P, self_test_rng, NULL));\n\n    for (i = 1; i < n_exponents; i++) {\n        add_c_prev = add_count;\n        dbl_c_prev = dbl_count;\n        mul_c_prev = mul_count;\n        add_count = 0;\n        dbl_count = 0;\n        mul_count = 0;\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(m, 16, exponents[i]));\n        MBEDTLS_MPI_CHK(self_test_adjust_exponent(grp, m));\n        MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, R, m, P, self_test_rng, NULL));\n\n        if (add_count != add_c_prev ||\n            dbl_count != dbl_c_prev ||\n            mul_count != mul_c_prev) {\n            ret = 1;\n            break;\n        }\n    }\n\ncleanup:\n    if (verbose != 0) {\n        if (ret != 0) {\n            mbedtls_printf(\"failed (%u)\\n\", (unsigned int) i);\n        } else {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n    return ret;\n}\n#endif /* MBEDTLS_ECP_C */\n\n/*\n * Checkup routine\n */\nint mbedtls_ecp_self_test(int verbose)\n{\n#if defined(MBEDTLS_ECP_C)\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_group grp;\n    mbedtls_ecp_point R, P;\n    mbedtls_mpi m;\n\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n    /* Exponents especially adapted for secp192k1, which has the lowest\n     * order n of all supported curves (secp192r1 is in a slightly larger\n     * field but the order of its base point is slightly smaller). */\n    const char *sw_exponents[] =\n    {\n        \"000000000000000000000000000000000000000000000001\", /* one */\n        \"FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8C\", /* n - 1 */\n        \"5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25\", /* random */\n        \"400000000000000000000000000000000000000000000000\", /* one and zeros */\n        \"7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\", /* all ones */\n        \"555555555555555555555555555555555555555555555555\", /* 101010... */\n    };\n#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\n    const char *m_exponents[] =\n    {\n        /* Valid private values for Curve25519. In a build with Curve448\n         * but not Curve25519, they will be adjusted in\n         * self_test_adjust_exponent(). */\n        \"4000000000000000000000000000000000000000000000000000000000000000\",\n        \"5C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C30\",\n        \"5715ECCE24583F7A7023C24164390586842E816D7280A49EF6DF4EAE6B280BF8\",\n        \"41A2B017516F6D254E1F002BCCBADD54BE30F8CEC737A0E912B4963B6BA74460\",\n        \"5555555555555555555555555555555555555555555555555555555555555550\",\n        \"7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8\",\n    };\n#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */\n\n    mbedtls_ecp_group_init(&grp);\n    mbedtls_ecp_point_init(&R);\n    mbedtls_ecp_point_init(&P);\n    mbedtls_mpi_init(&m);\n\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n    /* Use secp192r1 if available, or any available curve */\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\n    MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP192R1));\n#else\n    MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, mbedtls_ecp_curve_list()->grp_id));\n#endif\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  ECP SW test #1 (constant op_count, base point G): \");\n    }\n    /* Do a dummy multiplication first to trigger precomputation */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&m, 2));\n    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&grp, &P, &m, &grp.G, self_test_rng, NULL));\n    ret = self_test_point(verbose,\n                          &grp, &R, &m, &grp.G,\n                          sw_exponents,\n                          sizeof(sw_exponents) / sizeof(sw_exponents[0]));\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  ECP SW test #2 (constant op_count, other point): \");\n    }\n    /* We computed P = 2G last time, use it */\n    ret = self_test_point(verbose,\n                          &grp, &R, &m, &P,\n                          sw_exponents,\n                          sizeof(sw_exponents) / sizeof(sw_exponents[0]));\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    mbedtls_ecp_group_free(&grp);\n    mbedtls_ecp_point_free(&R);\n#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */\n\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\n    if (verbose != 0) {\n        mbedtls_printf(\"  ECP Montgomery test (constant op_count): \");\n    }\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n    MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_CURVE25519));\n#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n    MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_CURVE448));\n#else\n#error \"MBEDTLS_ECP_MONTGOMERY_ENABLED is defined, but no curve is supported for self-test\"\n#endif\n    ret = self_test_point(verbose,\n                          &grp, &R, &m, &grp.G,\n                          m_exponents,\n                          sizeof(m_exponents) / sizeof(m_exponents[0]));\n    if (ret != 0) {\n        goto cleanup;\n    }\n#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */\n\ncleanup:\n\n    if (ret < 0 && verbose != 0) {\n        mbedtls_printf(\"Unexpected error, return code = %08X\\n\", (unsigned int) ret);\n    }\n\n    mbedtls_ecp_group_free(&grp);\n    mbedtls_ecp_point_free(&R);\n    mbedtls_ecp_point_free(&P);\n    mbedtls_mpi_free(&m);\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    return ret;\n#else /* MBEDTLS_ECP_C */\n    (void) verbose;\n    return 0;\n#endif /* MBEDTLS_ECP_C */\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* !MBEDTLS_ECP_ALT */\n\n#endif /* MBEDTLS_ECP_LIGHT */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ecp_curves.c",
    "content": "/*\n *  Elliptic curves over GF(p): curve-specific data and functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if !defined(MBEDTLS_ECP_WITH_MPI_UINT)\n\n#if defined(MBEDTLS_ECP_LIGHT)\n\n#include \"mbedtls/ecp.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include \"bn_mul.h\"\n#include \"bignum_core.h\"\n#include \"ecp_invasive.h\"\n\n#include <string.h>\n\n#if !defined(MBEDTLS_ECP_ALT)\n\n#define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) }\n\n#define ECP_MPI_INIT_ARRAY(x)   \\\n    ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint))\n\n#define ECP_POINT_INIT_XY_Z0(x, y) { \\\n        ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(NULL, 0) }\n#define ECP_POINT_INIT_XY_Z1(x, y) { \\\n        ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(mpi_one, 1) }\n\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)   ||   \\\n    defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)   ||   \\\n    defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)   ||   \\\n    defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n/* For these curves, we build the group parameters dynamically. */\n#define ECP_LOAD_GROUP\nstatic const mbedtls_mpi_uint mpi_one[] = { 1 };\n#endif\n\n/*\n * Note: the constants are in little-endian order\n * to be directly usable in MPIs\n */\n\n/*\n * Domain parameters for secp192r1\n */\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\nstatic const mbedtls_mpi_uint secp192r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp192r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64),\n};\nstatic const mbedtls_mpi_uint secp192r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18),\n};\nstatic const mbedtls_mpi_uint secp192r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07),\n};\nstatic const mbedtls_mpi_uint secp192r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp192r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x9E, 0xE3, 0x60, 0x59, 0xD1, 0xC4, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBD, 0x22, 0xD7, 0x2D, 0x07, 0xBD, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x2A, 0xCF, 0x33, 0xF0, 0xBE, 0xD1, 0xED),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x71, 0x4B, 0xA8, 0xED, 0x7E, 0xC9, 0x1A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x2A, 0xF6, 0xDF, 0x0E, 0xE8, 0x4C, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x35, 0xF7, 0x8A, 0xC3, 0xEC, 0xDE, 0x1E),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0xC2, 0x1D, 0x32, 0x8F, 0x10, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x2D, 0x17, 0xF3, 0xE4, 0xFE, 0xD8, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x45, 0x10, 0x70, 0x2C, 0x3E, 0x52, 0x3E),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF1, 0x04, 0x5D, 0xEE, 0xD4, 0x56, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xB7, 0x38, 0x27, 0x61, 0xAA, 0x81, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0xD7, 0x0E, 0x29, 0x0E, 0x11, 0x14),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x35, 0x52, 0xC6, 0x31, 0xB7, 0x27, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xD4, 0x15, 0x98, 0x0F, 0xE7, 0xF3, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x31, 0x70, 0x35, 0x09, 0xA0, 0x2B, 0xC2),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x75, 0xA7, 0x4C, 0x88, 0xCF, 0x5B, 0xE4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x17, 0x48, 0x8D, 0xF2, 0xF0, 0x86, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCF, 0xFE, 0x6B, 0xB0, 0xA5, 0x06, 0xAB),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x6A, 0xDC, 0x9A, 0x6D, 0x7B, 0x47, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xFC, 0x51, 0x12, 0x62, 0x66, 0x0B, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x40, 0x93, 0xA0, 0xB5, 0x5A, 0x58, 0xD7),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCB, 0xAF, 0xDC, 0x0B, 0xA1, 0x26, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x36, 0x9D, 0xA3, 0xD7, 0x3B, 0xAD, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x3B, 0x05, 0x9A, 0xA8, 0xAA, 0x69, 0xB2),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD9, 0xD1, 0x4D, 0x4A, 0x6E, 0x96, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x66, 0x32, 0x39, 0xC6, 0x57, 0x7D, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xA0, 0x36, 0xC2, 0x45, 0xF9, 0x00, 0x62),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xEF, 0x59, 0x46, 0xDC, 0x60, 0xD9, 0x8F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xB0, 0xE9, 0x41, 0xA4, 0x87, 0x76, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xD4, 0x0E, 0xB2, 0xFA, 0x16, 0x56, 0xDC),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x62, 0xD2, 0xB1, 0x34, 0xB2, 0xF1, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xED, 0x55, 0xC5, 0x47, 0xB5, 0x07, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF6, 0x2F, 0x94, 0xC3, 0xDD, 0x54, 0x2F),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xA6, 0xD4, 0x8C, 0xA9, 0xCE, 0x4D, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x4B, 0x46, 0xCC, 0xB2, 0x55, 0xC8, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x31, 0xED, 0x89, 0x65, 0x59, 0x55),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x0A, 0xD1, 0x1A, 0xC5, 0xF6, 0xEA, 0x43),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xFC, 0x0C, 0x1A, 0xFB, 0xA0, 0xC8, 0x70),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xFD, 0x53, 0x6F, 0x6D, 0xBF, 0xBA, 0xAF),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xB0, 0x7D, 0x83, 0x96, 0xE3, 0xCB, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x6E, 0x55, 0x2C, 0x20, 0x53, 0x2F, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x66, 0x00, 0x17, 0x08, 0xFE, 0xAC, 0x31),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x12, 0x97, 0x3A, 0xC7, 0x57, 0x45, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x25, 0x99, 0x00, 0xF6, 0x97, 0xB4, 0x64),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x74, 0xE6, 0xE6, 0xA3, 0xDF, 0x9C, 0xCC),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xF4, 0x76, 0xD5, 0x5F, 0x2A, 0xFD, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x80, 0x7E, 0x3E, 0xE5, 0xE8, 0xD6, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xAD, 0x1E, 0x70, 0x79, 0x3E, 0x3D, 0x83),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x15, 0xBB, 0xB3, 0x42, 0x6A, 0xA1, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x58, 0xCB, 0x43, 0x25, 0x00, 0x14, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x4E, 0x93, 0x11, 0xE0, 0x32, 0x54, 0x98),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x52, 0xA2, 0xB4, 0x57, 0x32, 0xB9, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x43, 0xA1, 0xB1, 0xFB, 0x01, 0xE1, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xFB, 0x5A, 0x11, 0xB8, 0xC2, 0x03, 0xE5),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x2B, 0x71, 0x26, 0x4E, 0x7C, 0xC5, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF5, 0xD3, 0xA8, 0xE4, 0x95, 0x48, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAE, 0xD9, 0x5D, 0x9F, 0x6A, 0x22, 0xAD),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xCC, 0xA3, 0x4D, 0xA0, 0x1C, 0x34, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x3C, 0x62, 0xF8, 0x5E, 0xA6, 0x58, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x6E, 0x66, 0x8A, 0x3D, 0x17, 0xFF, 0x0F),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xCD, 0xA8, 0xDD, 0xD1, 0x20, 0x5C, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xFE, 0x17, 0xE2, 0xCF, 0xEA, 0x63, 0xDE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x51, 0xC9, 0x16, 0xDE, 0xB4, 0xB2, 0xDD),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBE, 0x12, 0xD7, 0xA3, 0x0A, 0x50, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x87, 0xC5, 0x8A, 0x76, 0x57, 0x07, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x1F, 0xC6, 0x1B, 0x66, 0xC4, 0x3D, 0x8A),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xA4, 0x85, 0x13, 0x8F, 0xA7, 0x35, 0x19),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x0D, 0xFD, 0xFF, 0x1B, 0xD1, 0xD6, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x7A, 0xD0, 0xC3, 0xB4, 0xEF, 0x39, 0x66),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xFE, 0xA5, 0x9C, 0x34, 0x30, 0x49, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xC5, 0x39, 0x26, 0x06, 0xE3, 0x01, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x2B, 0x66, 0xFC, 0x95, 0x5F, 0x35, 0xF7),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xCF, 0x54, 0x63, 0x99, 0x57, 0x05, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x6F, 0x00, 0x5F, 0x65, 0x08, 0x47, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x2A, 0x90, 0x6D, 0x67, 0xC6, 0xBC, 0x45),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x4D, 0x88, 0x0A, 0x35, 0x9E, 0x33, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x17, 0x0C, 0xF8, 0xE1, 0x7A, 0x49, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x44, 0x06, 0x8F, 0x0B, 0x70, 0x2F, 0x71),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4B, 0xCB, 0xF9, 0x8E, 0x6A, 0xDA, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x43, 0xA1, 0x3F, 0xCE, 0x17, 0xD2, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x0D, 0xD2, 0x6C, 0x82, 0x37, 0xE5, 0xFC),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x3C, 0xF4, 0x92, 0xB4, 0x8A, 0x95, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x96, 0xF1, 0x0A, 0x34, 0x2F, 0x74, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0xAA, 0xBA, 0x86, 0x77, 0x4F, 0xA2),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x7F, 0xEF, 0x60, 0x50, 0x80, 0xD7, 0xD4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xAC, 0xC9, 0xFE, 0xEC, 0x0A, 0x1A, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x2F, 0xBE, 0x91, 0xD7, 0xB7, 0x38, 0x48),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xAE, 0x85, 0x98, 0xFE, 0x05, 0x7F, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBE, 0xFD, 0x11, 0x31, 0x3D, 0x14, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x75, 0xE8, 0x30, 0x01, 0xCB, 0x9B, 0x1C),\n};\nstatic const mbedtls_ecp_point secp192r1_T[16] = {\n    ECP_POINT_INIT_XY_Z1(secp192r1_T_0_X, secp192r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_1_X, secp192r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_2_X, secp192r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_3_X, secp192r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_4_X, secp192r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_5_X, secp192r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_6_X, secp192r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_7_X, secp192r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_8_X, secp192r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_9_X, secp192r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_10_X, secp192r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_11_X, secp192r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_12_X, secp192r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_13_X, secp192r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_14_X, secp192r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_15_X, secp192r1_T_15_Y),\n};\n#else\n#define secp192r1_T NULL\n#endif\n#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */\n\n/*\n * Domain parameters for secp224r1\n */\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)\nstatic const mbedtls_mpi_uint secp224r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C),\n    MBEDTLS_BYTES_TO_T_UINT_4(0x85, 0x0A, 0x05, 0xB4),\n};\nstatic const mbedtls_mpi_uint secp224r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_4(0xBD, 0x0C, 0x0E, 0xB7),\n};\nstatic const mbedtls_mpi_uint secp224r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_4(0x88, 0x63, 0x37, 0xBD),\n};\nstatic const mbedtls_mpi_uint secp224r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF),\n};\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp224r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x0C, 0x0E, 0xB7, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x63, 0x37, 0xBD, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF9, 0xB8, 0xD0, 0x3D, 0xD2, 0xD3, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xFD, 0x99, 0x26, 0x19, 0xFE, 0x13, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x0E, 0x4C, 0x48, 0x7C, 0xA2, 0x17, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA3, 0x13, 0x57, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x16, 0x5C, 0x8F, 0xAA, 0xED, 0x0F, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xC5, 0x43, 0x34, 0x93, 0x05, 0x2A, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE3, 0x6C, 0xCA, 0xC6, 0x14, 0xC2, 0x25),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x43, 0x6C, 0xD7, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x5A, 0x98, 0x1E, 0xC8, 0xA5, 0x42, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x49, 0x56, 0x78, 0xF8, 0xEF, 0xED, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xBB, 0x64, 0xB6, 0x4C, 0x54, 0x5F, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x0C, 0x33, 0xCC, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x79, 0xCB, 0x2E, 0x08, 0xFF, 0xD8, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x1F, 0xD4, 0xD7, 0x57, 0xE9, 0x39, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xD6, 0x3B, 0x0A, 0x1C, 0x87, 0xB7, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x30, 0xD8, 0x05, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x79, 0x74, 0x9A, 0xE6, 0xBB, 0xC2, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x5B, 0xA6, 0x67, 0xC1, 0x91, 0xE7, 0x64),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xDF, 0x38, 0x82, 0x19, 0x2C, 0x4C, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x2E, 0x39, 0xC5, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x36, 0x78, 0x4E, 0xAE, 0x5B, 0x02, 0x76),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF6, 0x8B, 0xF8, 0xF4, 0x92, 0x6B, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x4D, 0x71, 0x35, 0xE7, 0x0C, 0x2C, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xA5, 0x1F, 0xAE, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x1C, 0x4B, 0xDF, 0x5B, 0xF2, 0x51, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0xB1, 0x5A, 0xC6, 0x0F, 0x0E, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x24, 0x09, 0x62, 0xAF, 0xFC, 0xDB, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xE1, 0x80, 0x55, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x82, 0xFE, 0xAD, 0xC3, 0xE5, 0xCF, 0xD8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xA2, 0x62, 0x17, 0x76, 0xF0, 0x5A, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB8, 0xE5, 0xAC, 0xB7, 0x66, 0x38, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xFD, 0x86, 0x05, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0x0C, 0x3C, 0xD1, 0x66, 0xB0, 0xF1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x59, 0xB4, 0x8D, 0x90, 0x10, 0xB7, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x47, 0x9B, 0xE6, 0x55, 0x8A, 0xE4, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x49, 0xDB, 0x78, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x97, 0xED, 0xDE, 0xFF, 0xB3, 0xDF, 0x48),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xB9, 0x83, 0xB7, 0xEB, 0xBE, 0x40, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xD3, 0xD3, 0xCD, 0x0E, 0x82, 0x79, 0x3D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x83, 0x1B, 0xF0, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x22, 0xBB, 0x54, 0xD3, 0x31, 0x56, 0xFC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0xE5, 0xE0, 0x89, 0x96, 0x8E, 0x71),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xEF, 0x0A, 0xED, 0xD0, 0x11, 0x4A, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x00, 0x57, 0x27, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCA, 0x3D, 0xF7, 0x64, 0x9B, 0x6E, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xE3, 0x70, 0x6B, 0x41, 0xD7, 0xED, 0x8F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x44, 0x44, 0x80, 0xCE, 0x13, 0x37, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x73, 0x80, 0x79, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x4D, 0x70, 0x7D, 0x31, 0x0F, 0x1C, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x35, 0x88, 0x47, 0xC4, 0x24, 0x78, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF0, 0xCD, 0x91, 0x81, 0xB3, 0xDE, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xCE, 0xC6, 0xF7, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x9C, 0x2D, 0xE8, 0xD2, 0x00, 0x8F, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x5E, 0x7C, 0x0E, 0x0C, 0x6E, 0x58, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x81, 0x21, 0xCE, 0x43, 0xF4, 0x24, 0x3D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xBC, 0xF0, 0xF4, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x10, 0xC2, 0x74, 0x4A, 0x8F, 0x8A, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x67, 0xF4, 0x2B, 0x38, 0x2B, 0x35, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0C, 0xA9, 0xFA, 0x77, 0x5C, 0xBD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x19, 0x2B, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x3E, 0x96, 0x22, 0x53, 0xE1, 0xE9, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x13, 0xBC, 0xA1, 0x16, 0xEC, 0x01, 0x1A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x00, 0xC9, 0x7A, 0xC3, 0x73, 0xA5, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xF4, 0x5E, 0xC1, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x95, 0xD6, 0xD9, 0x32, 0x30, 0x2B, 0xD0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x42, 0x09, 0x05, 0x61, 0x2A, 0x7E, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x84, 0xA2, 0x05, 0x88, 0x64, 0x65, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2D, 0x90, 0xB3, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE7, 0x2E, 0x85, 0x55, 0x80, 0x7C, 0x79),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC1, 0xAC, 0x78, 0xB4, 0xAF, 0xFB, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xC3, 0x28, 0x8E, 0x79, 0x18, 0x1F, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x46, 0xCF, 0x49, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x5F, 0xA8, 0x6C, 0x46, 0x83, 0x43, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xA9, 0x93, 0x11, 0xB6, 0x07, 0x57, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x2A, 0x9D, 0x03, 0x89, 0x7E, 0xD7, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x8C, 0x62, 0xCF, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x2C, 0x13, 0x59, 0xCC, 0xFA, 0x84, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB9, 0x48, 0xBC, 0x57, 0xC7, 0xB3, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x0A, 0x38, 0x24, 0x2E, 0x3A, 0x28, 0x25),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x0A, 0x43, 0xB8, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x25, 0xAB, 0xC1, 0xEE, 0x70, 0x3C, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xDB, 0x45, 0x1D, 0x4A, 0x80, 0x75, 0x35),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1F, 0x4D, 0x2D, 0x9A, 0x05, 0xF4, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x10, 0xF0, 0x5A, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x95, 0xE1, 0xDC, 0x15, 0x86, 0xC3, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xDC, 0x27, 0xD1, 0x56, 0xA1, 0x14, 0x0D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x0B, 0xD6, 0x77, 0x4E, 0x44, 0xA2, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x42, 0x71, 0x1F, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x86, 0xB2, 0xB0, 0xC8, 0x2F, 0x7B, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xEF, 0xCB, 0xDB, 0xBC, 0x9E, 0x3B, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x03, 0x86, 0xDD, 0x5B, 0xF5, 0x8D, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x95, 0x79, 0xD6, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x32, 0x14, 0xDA, 0x9B, 0x4F, 0x07, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x3E, 0xFB, 0x06, 0xEE, 0xA7, 0x40, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x1F, 0xDF, 0x71, 0x61, 0xFD, 0x8B, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x8B, 0xAB, 0x8B, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x34, 0xB3, 0xB4, 0xBC, 0x9F, 0xB0, 0x5E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x58, 0x48, 0xA8, 0x77, 0xBB, 0x13, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC6, 0xF7, 0x34, 0xCC, 0x89, 0x21, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x33, 0xDD, 0x1F, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x81, 0xEF, 0xA4, 0xF2, 0x10, 0x0B, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF7, 0x6E, 0x72, 0x4A, 0xDF, 0xDD, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x23, 0x0A, 0x53, 0x03, 0x16, 0x62, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x76, 0xFD, 0x3C, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x14, 0xA1, 0xFA, 0xA0, 0x18, 0xBE, 0x07),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2A, 0xE1, 0xD7, 0xB0, 0x6C, 0xA0, 0xDE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xC0, 0xB0, 0xC6, 0x63, 0x24, 0xCD, 0x4E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x38, 0x2C, 0xB1, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCD, 0x7D, 0x20, 0x0C, 0xFE, 0xAC, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x9F, 0xA2, 0xB6, 0x45, 0xF7, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x99, 0xF3, 0xD2, 0x20, 0x02, 0xEB, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x5B, 0x7B, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xDD, 0x77, 0x91, 0x60, 0xEA, 0xFD, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xD3, 0xB5, 0xD6, 0x90, 0x17, 0x0E, 0x1A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xF4, 0x28, 0xC1, 0xF2, 0x53, 0xF6, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x58, 0xDC, 0x61, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x20, 0x01, 0xFB, 0xF1, 0xBD, 0x5F, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x7F, 0x06, 0xDA, 0x11, 0xCB, 0xBA, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x41, 0x00, 0xA4, 0x1B, 0x30, 0x33, 0x79),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xFF, 0x27, 0xCA, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_ecp_point secp224r1_T[16] = {\n    ECP_POINT_INIT_XY_Z1(secp224r1_T_0_X, secp224r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_1_X, secp224r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_2_X, secp224r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_3_X, secp224r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_4_X, secp224r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_5_X, secp224r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_6_X, secp224r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_7_X, secp224r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_8_X, secp224r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_9_X, secp224r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_10_X, secp224r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_11_X, secp224r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_12_X, secp224r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_13_X, secp224r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_14_X, secp224r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_15_X, secp224r1_T_15_Y),\n};\n#else\n#define secp224r1_T NULL\n#endif\n#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */\n\n/*\n * Domain parameters for secp256r1\n */\n#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)\nstatic const mbedtls_mpi_uint secp256r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp256r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A),\n};\nstatic const mbedtls_mpi_uint secp256r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B),\n};\nstatic const mbedtls_mpi_uint secp256r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F),\n};\nstatic const mbedtls_mpi_uint secp256r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),\n};\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp256r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xC8, 0xBA, 0x04, 0xB7, 0x4B, 0xD2, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC6, 0x23, 0x3A, 0xA0, 0x09, 0x3A, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x9D, 0x4C, 0xF9, 0x58, 0x23, 0xCC, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xED, 0x7B, 0x29, 0x87, 0x0F, 0xFA, 0x3C),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x69, 0xF2, 0x40, 0x0B, 0xA3, 0x98, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xA8, 0x48, 0x02, 0x0D, 0x1C, 0x12, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xAF, 0x09, 0x83, 0x80, 0xAA, 0x58, 0xA7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x12, 0xBE, 0x70, 0x94, 0x76, 0xE3, 0xE4),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x7D, 0xEF, 0x86, 0xFF, 0xE3, 0x37, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x86, 0x8B, 0x08, 0x27, 0x7C, 0xD7, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x54, 0x4C, 0x25, 0x4F, 0x9A, 0xFE, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xFD, 0xF0, 0x6D, 0x37, 0x03, 0x69, 0xD6),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xD5, 0xDA, 0xAD, 0x92, 0x49, 0xF0, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x73, 0x43, 0x9E, 0xAF, 0xA7, 0xD1, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x41, 0x07, 0xDF, 0x78, 0x95, 0x3E, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x3D, 0xD1, 0xE6, 0x3C, 0xA5, 0xE2, 0x20),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x6A, 0x5D, 0x52, 0x35, 0xD7, 0xBF, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xA2, 0xBE, 0x96, 0xF4, 0xF8, 0x02, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x20, 0x49, 0x54, 0xEA, 0xB3, 0x82, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0xDB, 0xEA, 0x02, 0xD1, 0x75, 0x1C, 0x62),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x85, 0xF4, 0x9E, 0x4C, 0xDC, 0x39, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x6D, 0xC4, 0x57, 0xD8, 0x03, 0x5D, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x7F, 0x2D, 0x52, 0x6F, 0xC9, 0xDA, 0x4F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x64, 0xFA, 0xB4, 0xFE, 0xA4, 0xC4, 0xD7),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x37, 0xB9, 0xC0, 0xAA, 0x59, 0xC6, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x58, 0xD9, 0xED, 0x58, 0x99, 0x65, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x7D, 0x26, 0x8C, 0x4A, 0xF9, 0x05, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x73, 0x9A, 0xC9, 0xE7, 0x46, 0xDC, 0x00),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xD0, 0x55, 0xDF, 0x00, 0x0A, 0xF5, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xBF, 0x56, 0x81, 0x2D, 0x20, 0xEB, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC1, 0x28, 0x52, 0xAB, 0xE3, 0xD1, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x34, 0x79, 0x45, 0x57, 0xA5, 0x12, 0x03),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCF, 0xB8, 0x7E, 0xF7, 0x92, 0x96, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x01, 0x8C, 0x0D, 0x23, 0xF2, 0xE3, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x2E, 0xE3, 0x84, 0x52, 0x7A, 0x34, 0x76),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xA1, 0xB0, 0x15, 0x90, 0xE2, 0x53, 0x3C),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x98, 0xE7, 0xFA, 0xA5, 0x7D, 0x8B, 0x53),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x35, 0xD2, 0x00, 0xD1, 0x1B, 0x9F, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x69, 0x08, 0x9A, 0x72, 0xF0, 0xA9, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xFE, 0x0E, 0x14, 0xDA, 0x7C, 0x0E, 0xD3),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF6, 0xE8, 0xF8, 0x87, 0xF7, 0xFC, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xBE, 0x7F, 0x3F, 0x7A, 0x2B, 0xD7, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x32, 0xF2, 0x2D, 0x94, 0x6D, 0x42, 0xFD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x9A, 0xE3, 0x5F, 0x42, 0xBB, 0x84, 0xED),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x95, 0x29, 0x73, 0xA1, 0x67, 0x3E, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x30, 0x54, 0x35, 0x8E, 0x0A, 0xDD, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xD7, 0xA1, 0x97, 0x61, 0x3B, 0xF8, 0x0C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x33, 0x3C, 0x58, 0x55, 0x34, 0x23, 0xA3),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x5D, 0x16, 0x5F, 0x7B, 0xBC, 0xBB, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xEE, 0x4E, 0x8A, 0xC1, 0x51, 0xCC, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0D, 0x4D, 0x1B, 0x53, 0x23, 0x1D, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x2A, 0x38, 0x66, 0x52, 0x84, 0xE1, 0x95),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x9B, 0x83, 0x0A, 0x81, 0x4F, 0xAD, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xFF, 0x42, 0x41, 0x6E, 0xA9, 0xA2, 0xA0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA1, 0x4F, 0x1F, 0x89, 0x82, 0xAA, 0x3E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xB8, 0x0F, 0x6B, 0x8F, 0x8C, 0xD6, 0x68),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0xB3, 0xBB, 0x51, 0x69, 0xA2, 0x11, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x4F, 0x0F, 0x8D, 0xBD, 0x26, 0x0F, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xCB, 0xEC, 0x6B, 0x34, 0xC3, 0x3D, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x5D, 0x1E, 0x10, 0xD5, 0x44, 0xE2, 0x54),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x9E, 0xB1, 0xF1, 0x6E, 0x4C, 0xAD, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE3, 0xC2, 0x58, 0xC0, 0xFB, 0x34, 0x43),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x9C, 0xDF, 0x35, 0x07, 0x41, 0xBD, 0x19),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x10, 0xEC, 0x0E, 0xEC, 0xBB, 0xD6),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xCF, 0xEF, 0x3F, 0x83, 0x1A, 0x88, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x29, 0xB5, 0xB9, 0xE0, 0xC9, 0xA3, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x46, 0x1E, 0x77, 0xCD, 0x7E, 0xB3, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x21, 0xD0, 0xD4, 0xA3, 0x16, 0x08, 0xEE),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xCA, 0xA8, 0xB3, 0xBF, 0x29, 0x99, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF2, 0x05, 0xC1, 0xCF, 0x5D, 0x91, 0x48),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x01, 0x49, 0xDB, 0x82, 0xDF, 0x5F, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x06, 0x90, 0xAD, 0xE3, 0x38, 0xA4, 0xC4),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xD2, 0x3A, 0xE8, 0x03, 0xC5, 0x6D, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x35, 0xD0, 0xAE, 0x1D, 0x7A, 0x9F, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x1E, 0xD2, 0xCB, 0xAC, 0x88, 0x27, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x9C, 0xE0, 0x31, 0xDD, 0x99, 0x86),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF9, 0x9B, 0x32, 0x96, 0x41, 0x58, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x5A, 0x2A, 0xB8, 0x96, 0x0E, 0xB2, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x78, 0x2C, 0xC7, 0x08, 0x99, 0x19, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x59, 0x28, 0xE9, 0x84, 0x54, 0xE6, 0x16),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x38, 0x30, 0xDB, 0x70, 0x2C, 0x0A, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x5C, 0x9D, 0xE9, 0xD5, 0x46, 0x0B, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x0B, 0x60, 0x4B, 0x37, 0x7D, 0xB9, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x24, 0xF3, 0x3D, 0x79, 0x7F, 0x6C, 0x18),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7F, 0xE5, 0x1C, 0x4F, 0x60, 0x24, 0xF7, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xD8, 0xE2, 0x91, 0x7F, 0x89, 0x49, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xA7, 0x2E, 0x8D, 0x6A, 0xB3, 0x39, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x89, 0xB5, 0x9A, 0xB8, 0x8D, 0x42, 0x9C),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x45, 0xE6, 0x4B, 0x3F, 0x4F, 0x1E, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x65, 0x5E, 0x59, 0x22, 0xCC, 0x72, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x93, 0x1A, 0x27, 0x1E, 0x34, 0xC5, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xF2, 0xA5, 0x58, 0x5C, 0x15, 0x2E, 0xC6),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x7F, 0xBA, 0x58, 0x5A, 0x84, 0x6F, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA6, 0x36, 0x7E, 0xDC, 0xF7, 0xE1, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x4D, 0xAA, 0xEE, 0x57, 0x76, 0x3A, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x7E, 0x26, 0x18, 0x22, 0x23, 0x9F, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x4C, 0x64, 0xC7, 0x55, 0x02, 0x3F, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x02, 0x90, 0xBB, 0xC3, 0xEC, 0x30, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x6F, 0x64, 0xF4, 0x16, 0x69, 0x48, 0xA4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x44, 0x9C, 0x95, 0x0C, 0x7D, 0x67, 0x5E),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x91, 0x8B, 0xD8, 0xD0, 0xD7, 0xE7, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF9, 0x48, 0x62, 0x6F, 0xA8, 0x93, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x3A, 0x99, 0x02, 0xD5, 0x0B, 0x3D, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xD3, 0x00, 0x31, 0xE6, 0x0C, 0x9F, 0x44),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xB2, 0xAA, 0xFD, 0x88, 0x15, 0xDF, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0x35, 0x27, 0x31, 0x44, 0xCD, 0xC0, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xF8, 0x91, 0xA5, 0x71, 0x94, 0x84, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xCB, 0xD0, 0x93, 0xE9, 0x88, 0xDA, 0xE4),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC6, 0x39, 0x16, 0x5D, 0xA3, 0x1E, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x07, 0x37, 0x26, 0x36, 0x2A, 0xFE, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xBC, 0xF3, 0xD0, 0xDE, 0x50, 0xFC, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x2E, 0x06, 0x10, 0x15, 0x4D, 0xFA, 0xF7),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x65, 0x69, 0x5B, 0x66, 0xA2, 0x75, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x16, 0x00, 0x5A, 0xB0, 0x30, 0x25, 0x1A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xFB, 0x86, 0x42, 0x80, 0xC1, 0xC4, 0x76),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x1D, 0x83, 0x8E, 0x94, 0x01, 0x5F, 0x82),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x37, 0x70, 0xEF, 0x1F, 0xA1, 0xF0, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x5B, 0xCE, 0xC4, 0x9B, 0x6F, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x11, 0x11, 0x24, 0x4F, 0x4C, 0x79, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x3A, 0x72, 0xBC, 0xFE, 0x72, 0x58, 0x43),\n};\nstatic const mbedtls_ecp_point secp256r1_T[16] = {\n    ECP_POINT_INIT_XY_Z1(secp256r1_T_0_X, secp256r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_1_X, secp256r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_2_X, secp256r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_3_X, secp256r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_4_X, secp256r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_5_X, secp256r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_6_X, secp256r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_7_X, secp256r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_8_X, secp256r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_9_X, secp256r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_10_X, secp256r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_11_X, secp256r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_12_X, secp256r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_13_X, secp256r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_14_X, secp256r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_15_X, secp256r1_T_15_Y),\n};\n#else\n#define secp256r1_T NULL\n#endif\n\n#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */\n\n/*\n * Domain parameters for secp384r1\n */\n#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\nstatic const mbedtls_mpi_uint secp384r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp384r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3),\n};\nstatic const mbedtls_mpi_uint secp384r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA),\n};\nstatic const mbedtls_mpi_uint secp384r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36),\n};\nstatic const mbedtls_mpi_uint secp384r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp384r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x92, 0x00, 0x2C, 0x78, 0xDB, 0x1F, 0x37),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF3, 0xEB, 0xB7, 0x06, 0xF7, 0xB6, 0xBC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBC, 0x2C, 0xCF, 0xD8, 0xED, 0x53, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x75, 0x7B, 0xA3, 0xAB, 0xC3, 0x2C, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x9D, 0x78, 0x41, 0xF6, 0x76, 0x84, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x56, 0xE8, 0x52, 0xB3, 0xCB, 0xA8, 0xBD),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xF2, 0xAE, 0xA4, 0xB6, 0x89, 0x1B, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0xCE, 0x1C, 0x7C, 0xF6, 0x50, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xEB, 0x90, 0xE6, 0x4D, 0xC7, 0xD4, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x49, 0x2D, 0x8A, 0x01, 0x99, 0x60, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x80, 0x9B, 0x9B, 0x6A, 0xB0, 0x07, 0xD9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xA2, 0xEE, 0x59, 0xBE, 0x95, 0xBC, 0x23),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x9D, 0x56, 0xAE, 0x59, 0xFB, 0x1F, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xAC, 0x91, 0x80, 0x87, 0xA8, 0x6E, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x08, 0xA7, 0x08, 0x94, 0x32, 0xFC, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x29, 0x9E, 0x84, 0xF4, 0xE5, 0x6E, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x21, 0xB9, 0x50, 0x24, 0xF8, 0x9C, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x04, 0x01, 0xC2, 0xFB, 0x77, 0x3E, 0xDE),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x38, 0xEE, 0xE3, 0xC7, 0x9D, 0xEC, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x88, 0xCF, 0x43, 0xFA, 0x92, 0x5E, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xCA, 0x43, 0xF8, 0x3B, 0x49, 0x7E, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xE7, 0xEB, 0x17, 0x45, 0x86, 0xC2, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x69, 0x57, 0x32, 0xE0, 0x9C, 0xD1, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x10, 0xB8, 0x4D, 0xB8, 0xF4, 0x0D, 0xE3),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0xDC, 0x9A, 0xB2, 0x79, 0x39, 0x27, 0x16),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x71, 0xE4, 0x3B, 0x4D, 0x60, 0x0C, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xBD, 0x19, 0x40, 0xFA, 0x19, 0x2A, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xF8, 0x1E, 0x43, 0xA1, 0x50, 0x8D, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x18, 0x7C, 0x41, 0xFA, 0x7C, 0x1B, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x24, 0xC4, 0xE9, 0xB7, 0xD3, 0xAD),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x01, 0x3D, 0x63, 0x54, 0x45, 0x6F, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xB2, 0x19, 0xA3, 0x86, 0x1D, 0x42, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x02, 0x87, 0x18, 0x92, 0x52, 0x1A, 0x71),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x18, 0xB1, 0x5D, 0x18, 0x1B, 0x37, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x74, 0x61, 0xBA, 0x18, 0xAF, 0x40, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7D, 0x3C, 0x52, 0x0F, 0x07, 0xB0, 0x6F),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x39, 0x13, 0xAA, 0x60, 0x15, 0x99, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x00, 0xCB, 0xC6, 0xB1, 0xDB, 0x97, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xFA, 0x60, 0xB8, 0x24, 0xE4, 0x7D, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x75, 0xB3, 0x70, 0xB2, 0x83, 0xB1, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xE3, 0x6C, 0xCD, 0x33, 0x62, 0x7A, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x30, 0xDC, 0x0F, 0x9F, 0xBB, 0xB8, 0xAA),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD5, 0x0A, 0x60, 0x81, 0xB9, 0xC5, 0x16),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xAA, 0x2F, 0xD6, 0xF2, 0x73, 0xDF, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x7B, 0x74, 0xC9, 0xB3, 0x5B, 0x95, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x04, 0xEB, 0x15, 0xC8, 0x5F, 0x00, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x50, 0x20, 0x28, 0xD1, 0x01, 0xAF, 0xF0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x4F, 0x31, 0x81, 0x2F, 0x94, 0x48),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2F, 0xD8, 0xB6, 0x63, 0x7C, 0xE9, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x8C, 0xB9, 0x14, 0xD9, 0x37, 0x63, 0xDE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x02, 0xB8, 0x46, 0xAD, 0xCE, 0x7B, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x47, 0x2D, 0x66, 0xA7, 0xE9, 0x33, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF9, 0x93, 0x94, 0xA8, 0x48, 0xB3, 0x4F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x4A, 0xAC, 0x51, 0x08, 0x72, 0x2F, 0x1A),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xAD, 0xA0, 0xF9, 0x81, 0xE1, 0x78, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9A, 0x63, 0xD8, 0xBA, 0x79, 0x1A, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x31, 0x7B, 0x7A, 0x5A, 0x5D, 0x7D, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x96, 0x12, 0x4B, 0x19, 0x09, 0xE0, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8A, 0x57, 0xEE, 0x4E, 0x6E, 0x7E, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x9D, 0x69, 0xDC, 0xB3, 0xDA, 0xD8, 0x08),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x49, 0x03, 0x03, 0x33, 0x6F, 0x28, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xDB, 0xA7, 0x05, 0x8C, 0xF3, 0x4D, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x92, 0xB1, 0xA8, 0xEC, 0x0D, 0x64, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0xFC, 0xFD, 0xD0, 0x4B, 0x88, 0x1B, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x9C, 0x51, 0x69, 0xCE, 0x71, 0x73, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5A, 0x14, 0x23, 0x1A, 0x46, 0x63, 0x5F),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x4C, 0x70, 0x44, 0x18, 0xCD, 0xEF, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x49, 0xDD, 0x64, 0x7E, 0x7E, 0x4D, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x32, 0x7C, 0x09, 0xD0, 0x3F, 0xD6, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE0, 0x4F, 0x65, 0x0C, 0x7A, 0x54, 0x3E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFA, 0xFB, 0x4A, 0xB4, 0x79, 0x5A, 0x8C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x1B, 0x2B, 0xDA, 0xBC, 0x9A, 0x74),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xAC, 0x56, 0xF7, 0x5F, 0x51, 0x68, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xE0, 0x1D, 0xBC, 0x13, 0x4E, 0xAC, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF5, 0xC5, 0xE6, 0xD2, 0x88, 0xBA, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x0E, 0x28, 0x23, 0x58, 0x67, 0xFA, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x80, 0x4B, 0xD8, 0xC4, 0xDF, 0x15, 0xE4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x0E, 0x58, 0xE6, 0x2C, 0x59, 0xC2, 0x03),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x26, 0x27, 0x99, 0x16, 0x2B, 0x22, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF3, 0x8F, 0xC3, 0x2A, 0x9B, 0xFC, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2E, 0x83, 0x3D, 0xFE, 0x9E, 0x3C, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0xCD, 0x2D, 0xC1, 0x49, 0x38, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x42, 0x8B, 0x33, 0x89, 0x1F, 0xEA, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x1D, 0x13, 0xD7, 0x50, 0xBB, 0x3E, 0xEB),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x9A, 0x52, 0xD2, 0x54, 0x7C, 0x97, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x6E, 0xED, 0xD9, 0x87, 0x50, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x35, 0x7E, 0x16, 0x40, 0x15, 0x83, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x2B, 0xA4, 0xAB, 0x03, 0x91, 0xEA, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x47, 0x39, 0xEF, 0x05, 0x59, 0xD0, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x24, 0x0D, 0x76, 0x11, 0x53, 0x08, 0xAF),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x2F, 0xDD, 0xBD, 0x50, 0x48, 0xB1, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x1C, 0x84, 0x55, 0x78, 0x14, 0xEB, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x5E, 0x3E, 0xA6, 0xAF, 0xF6, 0xC7, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x11, 0xE2, 0x65, 0xCA, 0x41, 0x95, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x83, 0xD8, 0xE6, 0x4D, 0x22, 0x06, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x7F, 0x25, 0x2A, 0xAA, 0x28, 0x46, 0x97),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xDB, 0x15, 0x56, 0x84, 0xCB, 0xC0, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xDB, 0x0E, 0x08, 0xC9, 0xF5, 0xD4, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x62, 0xD0, 0x1A, 0x7C, 0x13, 0xD5, 0x07),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xAD, 0x53, 0xE0, 0x32, 0x21, 0xA0, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x38, 0x81, 0x21, 0x23, 0x0E, 0xD2, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x51, 0x05, 0xD0, 0x1E, 0x82, 0xA9, 0x71),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xC3, 0x27, 0xBF, 0xC6, 0xAA, 0xB7, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x65, 0x45, 0xDF, 0xB9, 0x46, 0x17, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x38, 0x3F, 0xB2, 0xB1, 0x5D, 0xCA, 0x1C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x29, 0x6C, 0x63, 0xE9, 0xD7, 0x48, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xF1, 0xD7, 0x99, 0x8C, 0xC2, 0x05, 0x99),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE6, 0x5E, 0x82, 0x6D, 0xE5, 0x7E, 0xD5),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x61, 0xFA, 0x7D, 0x01, 0xDB, 0xB6, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC6, 0x58, 0x39, 0xF4, 0xC6, 0x82, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0x7A, 0x80, 0x08, 0xCD, 0xAA, 0xD8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x8C, 0xC6, 0x3F, 0x3C, 0xA5, 0x68, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xF5, 0xD5, 0x17, 0xAE, 0x36, 0xD8, 0x8A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xAD, 0x92, 0xC5, 0x57, 0x6C, 0xDA, 0x91),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x67, 0x17, 0xC0, 0x40, 0x78, 0x8C, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x9F, 0xF4, 0xAA, 0xDA, 0x5C, 0x7E, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xDB, 0x42, 0x3E, 0x72, 0x64, 0xA0, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xF9, 0x41, 0x17, 0x43, 0xE3, 0xE8, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xDD, 0xCC, 0x43, 0x7E, 0x16, 0x05, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x4B, 0xCF, 0x48, 0x8F, 0x41, 0x90, 0xE5),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x0C, 0x6B, 0x9D, 0x22, 0x04, 0xBC, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x63, 0x79, 0x2F, 0x6A, 0x0E, 0x8A, 0xDE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x67, 0x3F, 0x02, 0xB8, 0x91, 0x7F, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x14, 0x64, 0xA0, 0x33, 0xF4, 0x6B, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x44, 0x71, 0x87, 0xB8, 0x88, 0x3F, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x2B, 0x85, 0x05, 0xC5, 0x44, 0x53, 0x15),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x2B, 0xFE, 0xD1, 0x1C, 0x73, 0xE3, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x33, 0xA1, 0xD3, 0x69, 0x1C, 0x9D, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x5A, 0xBA, 0xB6, 0xAE, 0x1B, 0x94, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x74, 0x90, 0x5C, 0x57, 0xB0, 0x3A, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x2F, 0x93, 0x20, 0x24, 0x54, 0x1D, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x78, 0x9D, 0x71, 0x67, 0x5D, 0x49, 0x98),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xC8, 0x0E, 0x11, 0x8D, 0xE0, 0x8F, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x7F, 0x79, 0x6C, 0x5F, 0xB7, 0xBC, 0xB1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xE1, 0x83, 0x3C, 0x12, 0xBB, 0xEE, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC2, 0xC4, 0x1B, 0x41, 0x71, 0xB9, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0xEE, 0xBB, 0x1D, 0x89, 0x50, 0x88, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x1C, 0x55, 0x74, 0xEB, 0xDE, 0x92, 0x3F),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x38, 0x92, 0x06, 0x19, 0xD0, 0xB3, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x99, 0x26, 0xA3, 0x5F, 0xE2, 0xC1, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xFC, 0xFD, 0xC3, 0xB6, 0x26, 0x24, 0x8F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xAD, 0xE7, 0x49, 0xB7, 0x64, 0x4B, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x4E, 0x95, 0xAD, 0x07, 0xFE, 0xB6, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x15, 0xE7, 0x2D, 0x19, 0xA9, 0x08, 0x10),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xBD, 0xAC, 0x0A, 0x3F, 0x6B, 0xFF, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xE4, 0x74, 0x14, 0xD9, 0x70, 0x1D, 0x71),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xB0, 0x71, 0xBB, 0xD8, 0x18, 0x96, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xB8, 0x19, 0x90, 0x80, 0xB5, 0xEE, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x21, 0x20, 0xA6, 0x17, 0x48, 0x03, 0x6F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0xBB, 0x6D, 0x94, 0x20, 0x34, 0xF1),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x82, 0x67, 0x4B, 0x8E, 0x4E, 0xBE, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xDA, 0x77, 0xF8, 0x23, 0x55, 0x2B, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x02, 0xDE, 0x25, 0x35, 0x2D, 0x74, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0C, 0xB8, 0x0B, 0x39, 0xBA, 0xAD, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x0E, 0x28, 0x4D, 0xE1, 0x3D, 0xE4, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xEC, 0x0A, 0xD4, 0xB8, 0xC4, 0x8D, 0xB0),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x68, 0xCE, 0xC2, 0x55, 0x4D, 0x0C, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x20, 0x93, 0x32, 0x90, 0xD6, 0xAE, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x78, 0xAB, 0x43, 0x9E, 0xEB, 0x73, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x97, 0xC3, 0x83, 0xA6, 0x3C, 0xF1, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x25, 0x25, 0x66, 0x08, 0x26, 0xFA, 0x4B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xFB, 0x44, 0x5D, 0x82, 0xEC, 0x3B, 0xAC),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x90, 0xEA, 0xB5, 0x04, 0x99, 0xD0, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0xF2, 0x22, 0xA0, 0xEB, 0xFD, 0x45, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA4, 0x81, 0x32, 0xFC, 0xFA, 0xEE, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xBB, 0xA4, 0x6A, 0x77, 0x41, 0x5C, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x1E, 0xAA, 0x4F, 0xF0, 0x10, 0xB3, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x74, 0x13, 0x14, 0x9E, 0x90, 0xD7, 0xE6),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xBD, 0x70, 0x4F, 0xA8, 0xD1, 0x06, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4E, 0x2E, 0x68, 0xFC, 0x35, 0xFA, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x53, 0x75, 0xED, 0xF2, 0x5F, 0xC2, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x87, 0x6B, 0x9F, 0x05, 0xE2, 0x22, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x1A, 0xA8, 0xB7, 0x03, 0x9E, 0x6D, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD0, 0x69, 0x88, 0xA8, 0x39, 0x9E, 0x3A),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xEF, 0x68, 0xFE, 0xEC, 0x24, 0x08, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x4B, 0x92, 0x0D, 0xB7, 0x34, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF4, 0xDD, 0x1A, 0xA0, 0x4A, 0xE4, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x63, 0x4F, 0x4F, 0xCE, 0xBB, 0xD6, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xEE, 0x8D, 0xDF, 0x3F, 0x73, 0xB7, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x06, 0xB6, 0x80, 0x4D, 0x81, 0xD9, 0x53),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_16_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF5, 0x13, 0xDF, 0x13, 0x19, 0x97, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xF9, 0xB3, 0x33, 0x66, 0x82, 0x21, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xFC, 0x39, 0x16, 0x23, 0x43, 0x76, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x48, 0x25, 0xA1, 0x64, 0x95, 0x1C, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xAC, 0x15, 0x57, 0xD9, 0xDE, 0xA0, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x5F, 0xB8, 0x3D, 0x48, 0x91, 0x24, 0xCC),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_16_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xF2, 0xC8, 0x54, 0xD1, 0x32, 0xBD, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x3B, 0xF0, 0xAA, 0x9D, 0xD8, 0xF4, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xC3, 0xBB, 0x6C, 0x66, 0xAC, 0x25, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x25, 0x10, 0xB2, 0xE1, 0x41, 0xDE, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xE8, 0x30, 0xB8, 0x37, 0xBC, 0x2A, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x57, 0x01, 0x4A, 0x1E, 0x78, 0x9F, 0x85),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_17_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x19, 0xCD, 0x12, 0x0B, 0x51, 0x4F, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x4B, 0x3D, 0x24, 0xA4, 0x16, 0x59, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xEB, 0xD3, 0x59, 0x2E, 0x75, 0x7C, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB9, 0xB4, 0xA5, 0xD9, 0x2E, 0x29, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x16, 0x05, 0x75, 0x02, 0xB3, 0x06, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x7C, 0x9F, 0x79, 0x91, 0xF1, 0x4F, 0x23),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_17_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x98, 0x7C, 0x84, 0xE1, 0xFF, 0x30, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE2, 0xC2, 0x5F, 0x55, 0x40, 0xBD, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x65, 0x87, 0x3F, 0xC4, 0xC2, 0x24, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x30, 0x0A, 0x60, 0x15, 0xD1, 0x24, 0x48),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x99, 0xD9, 0xB6, 0xAE, 0xB1, 0xAF, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x80, 0xEE, 0xA2, 0x0F, 0x74, 0xB9, 0xF3),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_18_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xE6, 0x0F, 0x37, 0xC1, 0x10, 0x99, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xAD, 0x9D, 0x5D, 0x80, 0x01, 0xA6, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x0F, 0x10, 0x2A, 0x9D, 0x20, 0x38, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x60, 0xCB, 0xCE, 0x5A, 0xA0, 0xA7, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xCF, 0x14, 0xDF, 0xBF, 0xE5, 0x74, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x12, 0x1A, 0xDD, 0x59, 0x02, 0x5D, 0xC6),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_18_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0xF8, 0xF5, 0xB6, 0x13, 0x4D, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x45, 0xB1, 0x93, 0xB3, 0xA2, 0x79, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xF6, 0xCF, 0xF7, 0xE6, 0x29, 0x9C, 0xCC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x50, 0x65, 0x80, 0xBC, 0x59, 0x0A, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xF0, 0x24, 0x35, 0xA2, 0x46, 0xF0, 0x0C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x26, 0xC0, 0x9D, 0x61, 0x56, 0x62, 0x67),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_19_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xBB, 0xC2, 0x24, 0x43, 0x2E, 0x37, 0x54),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xF7, 0xCE, 0x35, 0xFC, 0x77, 0xF3, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x34, 0x96, 0xD5, 0x4A, 0x76, 0x9D, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x3B, 0x0F, 0xEA, 0xA8, 0x12, 0x0B, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x3F, 0x5D, 0x2D, 0x1C, 0xD4, 0x9E, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x2E, 0xDD, 0xC7, 0x6E, 0xAB, 0xAF, 0xDC),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_19_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB2, 0x7B, 0x0C, 0x9A, 0x83, 0x8E, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x51, 0x90, 0x92, 0x79, 0x32, 0x19, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x89, 0xF9, 0xD0, 0xCF, 0x2C, 0xA5, 0x8F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x50, 0x21, 0xDE, 0x50, 0x41, 0x9D, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x7D, 0x2B, 0x9E, 0x9D, 0x95, 0xA8, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA5, 0x20, 0x87, 0x88, 0x97, 0x5F, 0xAA),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_20_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x59, 0xB4, 0x66, 0x7E, 0xE8, 0x5A, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x5C, 0x7E, 0xB2, 0xAD, 0xD9, 0xC9, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x97, 0x49, 0xA3, 0x13, 0x83, 0x07, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x26, 0xC7, 0x13, 0x35, 0x0D, 0xB0, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x60, 0xAB, 0xFA, 0x4B, 0x93, 0x18, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2D, 0x1C, 0x31, 0x4C, 0xE4, 0x61, 0xAE),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_20_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x4D, 0x1E, 0x51, 0x59, 0x6E, 0x91, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x54, 0x4D, 0x51, 0xED, 0x36, 0xCC, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xA8, 0x56, 0xC7, 0x78, 0x27, 0x33, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB7, 0x95, 0xC9, 0x8B, 0xC8, 0x6A, 0xBC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xE9, 0x13, 0x96, 0xB3, 0xE1, 0xF9, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x46, 0xB0, 0x5E, 0xC3, 0x94, 0x03, 0x05),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_21_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x5B, 0x29, 0x30, 0x41, 0x1A, 0x9E, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xCA, 0x83, 0x31, 0x5B, 0xA7, 0xCB, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x41, 0x50, 0x44, 0x4D, 0x64, 0x31, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x84, 0xC2, 0x5D, 0x97, 0xA5, 0x3C, 0x18),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x0F, 0xA5, 0xFD, 0x8E, 0x5A, 0x47, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x58, 0x02, 0x2D, 0x40, 0xB1, 0x0B, 0xBA),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_21_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x33, 0x8C, 0x67, 0xCE, 0x23, 0x43, 0x99),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x53, 0x47, 0x72, 0x44, 0x1F, 0x5B, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xC1, 0xD9, 0xA4, 0x50, 0x88, 0x63, 0x18),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xF2, 0x75, 0x69, 0x73, 0x00, 0xC4, 0x31),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x90, 0x1D, 0xDF, 0x1A, 0x00, 0xD8, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xB1, 0x89, 0x48, 0xA8, 0x70, 0x62, 0xEF),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_22_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x8A, 0x55, 0x50, 0x7B, 0xEF, 0x8A, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1B, 0x23, 0x48, 0x23, 0x63, 0x91, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x04, 0x54, 0x3C, 0x24, 0x9B, 0xC7, 0x9A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x38, 0xC3, 0x84, 0xFB, 0xFF, 0x9F, 0x49),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x2A, 0xE0, 0x6D, 0x68, 0x8A, 0x5C, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x93, 0x53, 0x85, 0xA1, 0x0D, 0xAF, 0x63),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_22_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x88, 0x95, 0x4C, 0x0B, 0xD0, 0x06, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xAF, 0x8D, 0x49, 0xA2, 0xC8, 0xB4, 0xE0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x76, 0x53, 0x09, 0x88, 0x43, 0x87, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA4, 0x77, 0x3F, 0x5E, 0x21, 0xB4, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x9E, 0x86, 0x64, 0xCC, 0x91, 0xC1, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x17, 0x56, 0xCB, 0xC3, 0x7D, 0x5B, 0xB1),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_23_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x74, 0x9F, 0xB5, 0x91, 0x21, 0xB1, 0x1C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xED, 0xE1, 0x11, 0xEF, 0x45, 0xAF, 0xC1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x31, 0xBE, 0xB2, 0xBC, 0x72, 0x65, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x4B, 0x8C, 0x77, 0xCE, 0x1E, 0x42, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC9, 0xAA, 0xB9, 0xD9, 0x86, 0x99, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x23, 0x80, 0xC6, 0x4E, 0x35, 0x0B, 0x6D),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_23_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xD8, 0xA2, 0x0A, 0x39, 0x32, 0x1D, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xC8, 0x86, 0xF1, 0x12, 0x9A, 0x4A, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xF1, 0x7C, 0xAA, 0x70, 0x8E, 0xBC, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x01, 0x47, 0x8F, 0xDD, 0x8B, 0xA5, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x08, 0x21, 0xF4, 0xAB, 0xC7, 0xF5, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x76, 0xA5, 0x95, 0xC4, 0x0F, 0x88, 0x1D),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_24_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x42, 0x2A, 0x52, 0xCD, 0x75, 0x51, 0x49),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x36, 0xE5, 0x04, 0x2B, 0x44, 0xC6, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xEE, 0x16, 0x13, 0x07, 0x83, 0xB5, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x59, 0xC6, 0xA2, 0x19, 0x05, 0xD3, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8B, 0xA8, 0x16, 0x09, 0xB7, 0xEA, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xEE, 0x14, 0xAF, 0xB5, 0xFD, 0xD0, 0xEF),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_24_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x7C, 0xCA, 0x71, 0x3E, 0x6E, 0x66, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x31, 0x0E, 0x3F, 0xE5, 0x91, 0xC4, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x3D, 0xC2, 0x3E, 0x95, 0x37, 0x58, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x1F, 0x02, 0x03, 0xF3, 0xEF, 0xEE, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x5B, 0x1A, 0xFC, 0x38, 0xCD, 0xE8, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x57, 0x42, 0x85, 0xC6, 0x21, 0x68, 0x71),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_25_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA2, 0x4A, 0x66, 0xB1, 0x0A, 0xE6, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x0C, 0x94, 0x9D, 0x5E, 0x99, 0xB2, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x03, 0x40, 0xCA, 0xB2, 0xB3, 0x30, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0x48, 0x27, 0x34, 0x1E, 0xE2, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x72, 0x5B, 0xAC, 0xC1, 0x6D, 0xE3, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAB, 0x46, 0xCB, 0xEA, 0x5E, 0x4B, 0x0B),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_25_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x08, 0xAD, 0x4E, 0x51, 0x9F, 0x2A, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5C, 0x7D, 0x4C, 0xD6, 0xCF, 0xDD, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x76, 0x26, 0xE0, 0x8B, 0x10, 0xD9, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA7, 0x23, 0x4E, 0x5F, 0xD2, 0x42, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xE5, 0xA4, 0xEC, 0x77, 0x21, 0x34, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x14, 0x65, 0xEA, 0x4A, 0x85, 0xC3, 0x2F),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_26_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xD8, 0x40, 0x27, 0x73, 0x15, 0x7E, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xBB, 0x53, 0x7E, 0x0F, 0x40, 0xC8, 0xD4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x37, 0x19, 0x73, 0xEF, 0x5A, 0x5E, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x73, 0x2B, 0x49, 0x7E, 0xAC, 0x97, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xB2, 0xC3, 0x1E, 0x0E, 0xE7, 0xD2, 0x21),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x08, 0xD6, 0xDD, 0xAC, 0x21, 0xD6, 0x3E),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_26_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x26, 0xBE, 0x6D, 0x6D, 0xF2, 0x38, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6C, 0x31, 0xA7, 0x49, 0x50, 0x3A, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x99, 0xC6, 0xF5, 0xD2, 0xC2, 0x30, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE4, 0xF6, 0x8B, 0x8B, 0x97, 0xE9, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x21, 0xB7, 0x0D, 0xFC, 0x15, 0x54, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x83, 0x1C, 0xA4, 0xCD, 0x6B, 0x9D, 0xF2),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_27_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE8, 0x4C, 0x48, 0xE4, 0xAA, 0x69, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x7A, 0x27, 0xFC, 0x37, 0x96, 0x1A, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xE7, 0x30, 0xA5, 0xCF, 0x13, 0x46, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xD8, 0xAF, 0x74, 0x23, 0x4D, 0x56, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3D, 0x44, 0x14, 0x1B, 0x97, 0x83, 0xF0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x47, 0xD7, 0x5F, 0xFD, 0x98, 0x38, 0xF7),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_27_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x73, 0x64, 0x36, 0xFD, 0x7B, 0xC1, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x5D, 0x32, 0xD2, 0x47, 0x94, 0x89, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xE9, 0x30, 0xAC, 0x06, 0xC8, 0x65, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x6C, 0xB9, 0x1B, 0xF7, 0x61, 0x49, 0x53),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xFF, 0x32, 0x43, 0x80, 0xDA, 0xA6, 0xB1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF8, 0x04, 0x01, 0x95, 0x35, 0xCE, 0x21),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_28_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x06, 0x46, 0x0D, 0x51, 0xE2, 0xD8, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x57, 0x1D, 0x6F, 0x79, 0xA0, 0xCD, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xFB, 0x36, 0xCA, 0xAD, 0xF5, 0x9E, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x7A, 0x1D, 0x9E, 0x1D, 0x95, 0x48, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x26, 0xA5, 0xB7, 0x15, 0x2C, 0xC2, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x42, 0x72, 0xAA, 0x11, 0xDC, 0xC9, 0xB6),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_28_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x6C, 0x64, 0xA7, 0x62, 0x3C, 0xAB, 0xD4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x6A, 0x44, 0xD8, 0x60, 0xC0, 0xA8, 0x80),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x76, 0x58, 0x12, 0x57, 0x3C, 0x89, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x4F, 0x83, 0xCE, 0xCB, 0xB8, 0xD0, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0x04, 0xB0, 0xAD, 0xEB, 0xFA, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA4, 0xC3, 0x41, 0x44, 0x4E, 0x65, 0x3E),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_29_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x16, 0xA9, 0x1C, 0xE7, 0x65, 0x20, 0xC1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x53, 0x32, 0xF8, 0xC0, 0xA6, 0xBD, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF0, 0xE6, 0x57, 0x31, 0xCC, 0x26, 0x6F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xE3, 0x54, 0x1C, 0x34, 0xD3, 0x17, 0xBC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xAE, 0xED, 0xFB, 0xCD, 0xE7, 0x1E, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x16, 0x1C, 0x34, 0x40, 0x00, 0x1F, 0xB6),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_29_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x32, 0x00, 0xC2, 0xD4, 0x3B, 0x1A, 0x09),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xE0, 0x99, 0x8F, 0x0C, 0x4A, 0x16, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x73, 0x18, 0x1B, 0xD4, 0x94, 0x29, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA4, 0x2D, 0xB1, 0x9D, 0x74, 0x32, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xF4, 0xB1, 0x0C, 0x37, 0x62, 0x8B, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xFF, 0xDA, 0xE2, 0x35, 0xA3, 0xB6, 0x42),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_30_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x49, 0x99, 0x65, 0xC5, 0xED, 0x16, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x42, 0x9A, 0xF3, 0xA7, 0x4E, 0x6F, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x0A, 0x7E, 0xC0, 0xD7, 0x4E, 0x07, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x7A, 0x31, 0x69, 0xA6, 0xB9, 0x15, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xE0, 0x72, 0xA4, 0x3F, 0xB9, 0xF8, 0x0C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x75, 0x32, 0x85, 0xA2, 0xDE, 0x37, 0x12),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_30_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC0, 0x0D, 0xCF, 0x25, 0x41, 0xA4, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xFC, 0xB2, 0x48, 0xC3, 0x85, 0x83, 0x4B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBE, 0x0B, 0x58, 0x2D, 0x7A, 0x9A, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xF3, 0x81, 0x18, 0x1B, 0x74, 0x4F, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x43, 0xA3, 0x0A, 0x16, 0x8B, 0xA3, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x18, 0x81, 0x7B, 0x8D, 0xA2, 0x35, 0x77),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_31_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xC4, 0x3F, 0x2C, 0xE7, 0x5F, 0x99, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2B, 0xB7, 0xB6, 0xAD, 0x5A, 0x56, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x00, 0xA4, 0x48, 0xC8, 0xE8, 0xBA, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xA1, 0xB5, 0x13, 0x5A, 0xCD, 0x99, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x95, 0xAD, 0xFC, 0xE2, 0x7E, 0xE7, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x6B, 0xD1, 0x34, 0x99, 0x53, 0x63, 0x0B),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_31_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x8A, 0x77, 0x5D, 0x2B, 0xAB, 0x01, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x85, 0xD0, 0xD5, 0x49, 0x83, 0x4D, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xC6, 0x91, 0x30, 0x3B, 0x00, 0xAF, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x61, 0x07, 0xE1, 0xB6, 0xE2, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x43, 0x41, 0xFE, 0x9B, 0xB6, 0xF0, 0xA5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x97, 0xAE, 0xAD, 0x89, 0x88, 0x9E, 0x41),\n};\nstatic const mbedtls_ecp_point secp384r1_T[32] = {\n    ECP_POINT_INIT_XY_Z1(secp384r1_T_0_X, secp384r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_1_X, secp384r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_2_X, secp384r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_3_X, secp384r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_4_X, secp384r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_5_X, secp384r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_6_X, secp384r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_7_X, secp384r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_8_X, secp384r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_9_X, secp384r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_10_X, secp384r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_11_X, secp384r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_12_X, secp384r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_13_X, secp384r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_14_X, secp384r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_15_X, secp384r1_T_15_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_16_X, secp384r1_T_16_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_17_X, secp384r1_T_17_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_18_X, secp384r1_T_18_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_19_X, secp384r1_T_19_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_20_X, secp384r1_T_20_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_21_X, secp384r1_T_21_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_22_X, secp384r1_T_22_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_23_X, secp384r1_T_23_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_24_X, secp384r1_T_24_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_25_X, secp384r1_T_25_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_26_X, secp384r1_T_26_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_27_X, secp384r1_T_27_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_28_X, secp384r1_T_28_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_29_X, secp384r1_T_29_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_30_X, secp384r1_T_30_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_31_X, secp384r1_T_31_Y),\n};\n#else\n#define secp384r1_T NULL\n#endif\n\n#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */\n\n/*\n * Domain parameters for secp521r1\n */\n#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)\nstatic const mbedtls_mpi_uint secp521r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01),\n};\nstatic const mbedtls_mpi_uint secp521r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_2(0x51, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_2(0xC6, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_2(0x18, 0x01),\n};\nstatic const mbedtls_mpi_uint secp521r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01),\n};\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp521r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xB1, 0x2D, 0xEB, 0x27, 0x2F, 0xE8, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x4B, 0x44, 0x25, 0xDB, 0x5C, 0x5F, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x85, 0x28, 0x78, 0x2E, 0x75, 0x34, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x57, 0x0F, 0x73, 0x78, 0x7A, 0xE3, 0x53),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD8, 0xEC, 0xDC, 0xDA, 0x04, 0xAD, 0xAB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x8A, 0x09, 0xF3, 0x58, 0x79, 0xD8, 0x29),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x03, 0xCB, 0x50, 0x1A, 0x7F, 0x56, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA6, 0x78, 0x38, 0x85, 0x67, 0x0B, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xD5, 0xD2, 0x22, 0xC4, 0x00, 0x3B, 0xBA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x93, 0x0E, 0x7B, 0x85, 0x51, 0xC3, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA6, 0x5F, 0x54, 0x49, 0x02, 0x81, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xE9, 0x6B, 0x3A, 0x92, 0xE7, 0x72, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x5F, 0x28, 0x9E, 0x91, 0x27, 0x88, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x28, 0x31, 0xB3, 0x84, 0xCA, 0x12, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xF9, 0xAC, 0x22, 0x10, 0x0A, 0x64, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xC6, 0x33, 0x1F, 0x69, 0x19, 0x18, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x48, 0xB8, 0xC7, 0x37, 0x5A, 0x00, 0x36),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xCC, 0x32, 0xE0, 0xEE, 0x03, 0xC2, 0xBA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x29, 0xC2, 0xE4, 0x6E, 0x24, 0x20, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x6B, 0x7F, 0x7B, 0xF9, 0xB0, 0xB8, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x7B, 0x3C, 0xE1, 0x19, 0xA1, 0x23, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE3, 0xC2, 0x53, 0xC0, 0x07, 0x13, 0xA9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFE, 0x36, 0x35, 0x9F, 0x5E, 0x59, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x55, 0x89, 0x84, 0xBC, 0xEF, 0xA2, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x1A, 0x08, 0x67, 0xB4, 0xE7, 0x22, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x26, 0xDF, 0x81, 0x3C, 0x5F, 0x1C, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x4D, 0xD0, 0x0A, 0x48, 0x06, 0xF4, 0x48),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x18, 0x39, 0xF7, 0xD1, 0x20, 0x77, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x8F, 0x44, 0x13, 0xCB, 0x78, 0x11, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE2, 0x49, 0xEA, 0x43, 0x79, 0x08, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xD1, 0xD8, 0x73, 0x2C, 0x71, 0x2F, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE5, 0xE7, 0xF4, 0x46, 0xAB, 0x20, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x0B, 0xB9, 0x71, 0x1A, 0x27, 0xB7, 0xA7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xA2, 0x2C, 0xD1, 0xDA, 0xBC, 0xC1, 0xBD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xA3, 0x10, 0x1F, 0x90, 0xF2, 0xA5, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xFB, 0x20, 0xF4, 0xC0, 0x70, 0xC0, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xA7, 0x99, 0xF0, 0xA5, 0xD3, 0x09, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xE8, 0x14, 0x39, 0xBE, 0xCB, 0x60, 0xAF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD6, 0x14, 0xA9, 0xC9, 0x20, 0xC3, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x5B, 0xFD, 0x2D, 0x96, 0xBC, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x04, 0x45, 0xBE, 0xCE, 0x75, 0x95, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xDA, 0x58, 0x49, 0x35, 0x09, 0x8D, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xF0, 0xC0, 0x36, 0xF2, 0xA6, 0x2D, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFC, 0x3D, 0xA8, 0xFB, 0x3C, 0xD2, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x4D, 0x71, 0x09, 0x18, 0x42, 0xF0, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xC1, 0xCE, 0x9E, 0x6A, 0x49, 0x60, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xB1, 0x00, 0xF7, 0xA1, 0x7A, 0x31, 0xB4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC3, 0x86, 0xCD, 0x20, 0x4A, 0x17, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xAB, 0x8B, 0x47, 0x8D, 0xAA, 0xA6, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x97, 0xF0, 0xBC, 0x2D, 0xDC, 0x9D, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x86, 0xB0, 0x74, 0xB2, 0xF4, 0xF6, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBD, 0xAC, 0xE3, 0x8F, 0x43, 0x5C, 0xB1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xC3, 0xE2, 0x6E, 0x25, 0x49, 0xCD, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5E, 0x08, 0xB3, 0xB9, 0xAC, 0x5F, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xB7, 0xD1, 0xF4, 0xDC, 0x19, 0xE9, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xE4, 0xFA, 0xE1, 0x36, 0x3E, 0xED, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0x92, 0x84, 0x6E, 0x48, 0x03, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x95, 0xEF, 0x8F, 0xB2, 0x82, 0x6B, 0x1C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFA, 0xB9, 0x55, 0x23, 0xFE, 0x09, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x79, 0x85, 0x4B, 0x0E, 0xD4, 0x35, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x27, 0x45, 0x81, 0xE0, 0x88, 0x52, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x63, 0xA2, 0x4B, 0xBC, 0x5D, 0xB1, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x8C, 0x83, 0xD9, 0x3E, 0xD3, 0x42, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x03, 0x3A, 0x31, 0xBA, 0xE9, 0x3A, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x10, 0xCD, 0x2D, 0x00, 0xFE, 0x32, 0xA7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x6E, 0x1F, 0xDA, 0xF8, 0x6F, 0x4D, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x79, 0x7D, 0x09, 0xE5, 0xD3, 0x03, 0x21),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC3, 0xBE, 0xDF, 0x07, 0x65, 0x49, 0xCC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0x33, 0xEF, 0xAE, 0x4F, 0x04, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xE9, 0x9B, 0xFE, 0xBF, 0xE6, 0x85, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xBA, 0xAA, 0x06, 0xC4, 0xC6, 0xB8, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x83, 0x01, 0xA9, 0xF6, 0x51, 0xE7, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xA6, 0x15, 0x8E, 0xAB, 0x1F, 0x10, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x08, 0x27, 0x1A, 0xA1, 0x21, 0xAD, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x09, 0x90, 0x6E, 0x50, 0x90, 0x9A, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x9A, 0xFE, 0xD7, 0xA1, 0xF5, 0xA2, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x7D, 0xE3, 0xDC, 0x21, 0xFB, 0xA4, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBF, 0x07, 0xFF, 0x45, 0xDF, 0x51, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x5C, 0x34, 0x02, 0x62, 0x9B, 0x08, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xCE, 0x9A, 0x6A, 0xEC, 0x75, 0xF6, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x59, 0xF4, 0x78, 0x3C, 0x60, 0xB1, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x37, 0x84, 0x6A, 0xDC, 0xF2, 0x9A, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9A, 0x9A, 0x15, 0x36, 0xE0, 0x2B, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x38, 0x9C, 0x50, 0x3D, 0x1E, 0x37, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x79, 0xF0, 0x92, 0xF2, 0x8B, 0x18, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE0, 0x82, 0x1E, 0x80, 0x82, 0x4B, 0xD7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xBB, 0x59, 0x6B, 0x8A, 0x77, 0x41, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xF9, 0xD4, 0xB8, 0x4A, 0x82, 0xCF, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x8C, 0xC8, 0x9B, 0x72, 0x9E, 0xF7, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xCE, 0xE9, 0x77, 0x0A, 0x19, 0x59, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xA1, 0x41, 0x6A, 0x72, 0x4B, 0xB4, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x35, 0x43, 0xE2, 0x8C, 0xBE, 0x0D, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xEB, 0xAD, 0xF3, 0xA9, 0xA6, 0x68, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2F, 0xE2, 0x48, 0x0C, 0xDB, 0x1F, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x1E, 0x60, 0x9B, 0x2A, 0xD2, 0xC1, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x64, 0xB5, 0xD2, 0xF6, 0xF6, 0x6E, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x3D, 0x30, 0x78, 0x10, 0x18, 0x41, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x1D, 0x1C, 0xE0, 0x6D, 0x83, 0xD1, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x03, 0x0B, 0xF5, 0x2F, 0x6C, 0x04, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x3E, 0xD5, 0xFC, 0x31, 0x5B, 0x3A, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x82, 0x2F, 0xFB, 0xFE, 0xF8, 0x76, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x26, 0xDA, 0x9C, 0x36, 0xF5, 0x93, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xE7, 0x6E, 0xD2, 0x7D, 0x81, 0x09, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x03, 0xF9, 0x58, 0x48, 0x24, 0xA2, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x79, 0x0C, 0x8E, 0x6B, 0x95, 0xF3, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x10, 0x5C, 0x87, 0x03, 0x39, 0xCF, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xF0, 0xF7, 0xC1, 0x07, 0xA4, 0xF4, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE8, 0x02, 0x89, 0x65, 0xC4, 0x72, 0x36),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x88, 0xEA, 0x96, 0x67, 0x0B, 0x5D, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x75, 0x60, 0xA8, 0xBD, 0x74, 0xDF, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xE5, 0x71, 0x50, 0x67, 0xD0, 0xD2, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFC, 0xE5, 0xC7, 0x77, 0xB0, 0x7F, 0x8C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x86, 0x69, 0xCD, 0x0D, 0x9A, 0xBD, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x17, 0xBC, 0xBB, 0x59, 0x85, 0x7D, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA8, 0x76, 0xAC, 0x80, 0xA9, 0x72, 0xE0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0xC1, 0xE2, 0x4D, 0xAF, 0xF9, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x97, 0x8E, 0x74, 0xC4, 0x4B, 0xB2, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD8, 0xF6, 0xF3, 0xAF, 0x2F, 0x52, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x57, 0xF4, 0xCE, 0xEE, 0x43, 0xED, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x46, 0x38, 0xDE, 0x20, 0xFD, 0x59, 0x18),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x18, 0xE8, 0x58, 0xB9, 0x76, 0x2C, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x54, 0xE4, 0xFE, 0xC7, 0xBC, 0x31, 0x37),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF8, 0x89, 0xEE, 0x70, 0xB5, 0xB0, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x22, 0x26, 0x9A, 0x53, 0xB9, 0x38, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xA7, 0x19, 0x8C, 0x74, 0x7E, 0x88, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xDA, 0x0A, 0xE8, 0xDA, 0xA5, 0xBE, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x5C, 0xF7, 0xB1, 0x0C, 0x72, 0xFB, 0x09),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xE2, 0x23, 0xE7, 0x46, 0xB7, 0xE0, 0x91),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x36, 0xBC, 0xBD, 0x48, 0x11, 0x8E, 0x72),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xBB, 0xA1, 0xF7, 0x0B, 0x9E, 0xBF, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x28, 0xE1, 0xA2, 0x8F, 0xFC, 0xFC, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xFE, 0x19, 0x0A, 0xE5, 0xE7, 0x69, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xCD, 0x12, 0xF5, 0xBE, 0xD3, 0x04, 0xF1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA8, 0x0D, 0x81, 0x59, 0xC4, 0x79, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xF3, 0x4B, 0x92, 0x65, 0xC3, 0x31, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xB5, 0x4F, 0x4D, 0x91, 0xD4, 0xE2, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x09, 0x41, 0x79, 0x1D, 0x4D, 0x0D, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x31, 0x18, 0xBA, 0xA0, 0xF2, 0x6E, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x5B, 0x4D, 0x4F, 0xAF, 0xC9, 0x8C, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x9C, 0x06, 0x68, 0xDE, 0xD8, 0x29),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x04, 0xE1, 0xB5, 0x9D, 0x00, 0xBC, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x95, 0x92, 0x8D, 0x72, 0xD3, 0x37, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x4B, 0x27, 0xA2, 0xE8, 0xA4, 0x26, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x45, 0x9C, 0xA9, 0xCB, 0x9F, 0xBA, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x7E, 0x1B, 0x64, 0xF4, 0xE8, 0xA5, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x20, 0xA9, 0xCA, 0xF3, 0x89, 0xE5, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xED, 0xFC, 0xAB, 0xD9, 0x0A, 0xB9, 0x07),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6F, 0x46, 0x7C, 0xCD, 0x78, 0xFF, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAB, 0x71, 0x5A, 0x94, 0xAB, 0x20, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x2E, 0xEE, 0x87, 0x57, 0x1F, 0xAD, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x4C, 0x3D, 0xFB, 0x7E, 0xA1, 0x8B, 0x07),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xCF, 0x07, 0x86, 0xBA, 0x53, 0x37, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x26, 0xB2, 0xB9, 0xE2, 0x91, 0xE3, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xC9, 0x54, 0x84, 0x08, 0x3D, 0x0B, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x77, 0x2F, 0x64, 0x45, 0x99, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x96, 0x16, 0x1F, 0xDB, 0x96, 0x28, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x2B, 0x8D, 0xFF, 0xA2, 0x4F, 0x55, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE6, 0x48, 0xBD, 0x99, 0x3D, 0x12, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x84, 0x59, 0xDA, 0xB9, 0xB6, 0x66, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x78, 0x41, 0x92, 0xDF, 0xF4, 0x3F, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x86, 0x6F, 0x4F, 0xBF, 0x67, 0xDF, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x2B, 0x1E, 0x5F, 0x00, 0xEA, 0xF6, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xB9, 0x6A, 0x89, 0xD8, 0xC0, 0xD7, 0xA7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x9A, 0x32, 0x23, 0xA0, 0x02, 0x91, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x7F, 0x6A, 0x15, 0x64, 0x6A, 0x8B, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x57, 0x82, 0x58, 0xA9, 0x56, 0xB5, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x50, 0x92, 0x60, 0xCC, 0x81, 0x24, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x3D, 0xAD, 0xDA, 0xD9, 0x51, 0x3E, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xFE, 0x8F, 0xB0, 0x0B, 0xDE, 0x2E, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xD2, 0xBE, 0xEF, 0xAC, 0x76, 0x71, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xE8, 0x72, 0x0B, 0xAC, 0xFE, 0xCA, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0xC7, 0xFC, 0xE3, 0x3C, 0x7C, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x04, 0xA7, 0xB9, 0x9B, 0x93, 0xC0, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x48, 0x4B, 0x8E, 0x32, 0xC5, 0xF0, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x42, 0x07, 0xC1, 0xF2, 0xF1, 0x72, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x37, 0x54, 0x9C, 0x88, 0xD2, 0x62, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x19, 0x8A, 0x89, 0x58, 0xA2, 0x0F, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xCC, 0x4C, 0x97, 0x30, 0x66, 0x34, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x6A, 0x1E, 0x1F, 0xDB, 0xC9, 0x5E, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x4D, 0x49, 0xFF, 0x9B, 0x9C, 0xAC, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xE4, 0x4B, 0xF2, 0xD4, 0x1A, 0xD2, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xDA, 0xE8, 0x61, 0x9F, 0xC8, 0x49, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xCB, 0xF2, 0x2D, 0x85, 0xF6, 0x8D, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xC5, 0xCD, 0x2C, 0x79, 0xC6, 0x0E, 0x4F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x1D, 0x55, 0x0F, 0xF8, 0x22, 0x9F, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x56, 0xBA, 0xE7, 0x57, 0x32, 0xEC, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x9A, 0xC6, 0x4C, 0x09, 0xC4, 0x52, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x1E, 0x6F, 0xF4, 0x7D, 0x27, 0xDD, 0xAF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x11, 0x16, 0xEC, 0x79, 0x83, 0xAD, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x4E, 0x92, 0x1F, 0x19, 0x7D, 0x65, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xFF, 0x78, 0x15, 0x45, 0x63, 0x32, 0xE4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x91, 0xD0, 0x78, 0x58, 0xDA, 0x50, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xDE, 0x40, 0xF6, 0x41, 0xB4, 0x3B, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x8D, 0xE0, 0xE1, 0xA9, 0xF0, 0x35, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xD4, 0xBA, 0x7B, 0xCC, 0x1B, 0x3A, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x5A, 0x2E, 0x74, 0x47, 0x14, 0xC3, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xF0, 0x8B, 0x06, 0x15, 0x8E, 0x0E, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xD2, 0xEB, 0x97, 0x50, 0x7D, 0x31, 0xFC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x93, 0x4C, 0xDB, 0x97, 0x79, 0x44, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xA2, 0xA0, 0x0B, 0xC8, 0x3A, 0x8A, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x50, 0x92, 0x9E, 0x24, 0x1F, 0xCB, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x16, 0xC9, 0xC5, 0x3D, 0x5A, 0xAF, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xE3, 0x97, 0xE4, 0xA8, 0x50, 0xF6, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x57, 0x97, 0x42, 0x78, 0x92, 0x49, 0x0D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEB, 0x62, 0x24, 0xFB, 0x8F, 0x32, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x0C, 0x36, 0x6E, 0x8F, 0xE8, 0xE8, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xD3, 0x7C, 0xC7, 0x8D, 0x3F, 0x5C, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x64, 0x6A, 0x73, 0x10, 0x79, 0xB8, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xF9, 0xEF, 0xA5, 0x20, 0x4A, 0x5C, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xF3, 0xF4, 0x49, 0x5B, 0x73, 0xAA, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xF2, 0xEA, 0x0F, 0x00, 0xAD, 0x53, 0xAB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xB8, 0x66, 0xED, 0xC4, 0x2B, 0x4C, 0x35),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x2F, 0xC1, 0x9A, 0x37, 0xD2, 0x7F, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA7, 0x81, 0x38, 0x64, 0xC9, 0x37, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x3B, 0x6C, 0x9F, 0x5B, 0xD9, 0x8B, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x14, 0xD9, 0x08, 0xD8, 0xD2, 0x7E, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x71, 0xE6, 0x3D, 0xD1, 0xB0, 0xE7, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x81, 0x23, 0xEC, 0x2D, 0x42, 0x45, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x5B, 0x44, 0x6B, 0x89, 0x03, 0x67, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x27, 0xAE, 0x80, 0x5A, 0x33, 0xBE, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB6, 0x64, 0x1A, 0xDF, 0xD3, 0x85, 0x91),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x8C, 0x22, 0xBA, 0xD0, 0xBD, 0xCC, 0xA0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x3C, 0x01, 0x3A, 0xFF, 0x9D, 0xC7, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC7, 0x64, 0xB4, 0x59, 0x4E, 0x9F, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x34, 0x0A, 0x41, 0x94, 0xA8, 0xF2, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD4, 0xE4, 0xF0, 0x97, 0x45, 0x6D, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x1F, 0x4D, 0x6D, 0xFE, 0xA0, 0xC4, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x28, 0x5C, 0x40, 0xBB, 0x65, 0xD4, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xA8, 0x87, 0x35, 0x20, 0x3A, 0x89, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFD, 0x4F, 0xAB, 0x2D, 0xD1, 0xD0, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE8, 0x00, 0xFC, 0x69, 0x52, 0xF8, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x9A, 0x99, 0xE1, 0xDC, 0x9C, 0x3F, 0xD9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x08, 0x98, 0xD9, 0xCA, 0x73, 0xD5, 0xA9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x2C, 0xE0, 0xA7, 0x3E, 0x91, 0xD7, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x04, 0xB0, 0x54, 0x09, 0xF4, 0x72, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xEE, 0x28, 0xCC, 0xE8, 0x50, 0x78, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x91, 0x03, 0x76, 0xDB, 0x68, 0x24, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xE0, 0x56, 0xB2, 0x5D, 0x12, 0xD3, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x42, 0x59, 0x8B, 0xDF, 0x67, 0xB5, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xCC, 0xE5, 0x31, 0x53, 0x7A, 0x46, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_16_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8D, 0x59, 0xB5, 0x1B, 0x0F, 0xF4, 0xAF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x2F, 0xD1, 0x2C, 0xE0, 0xD8, 0x04, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0xD7, 0xBA, 0xB0, 0xA3, 0x7E, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x08, 0x51, 0x56, 0xA6, 0x76, 0x67, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x17, 0x63, 0xFE, 0x56, 0xD0, 0xD9, 0x71),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xF6, 0xC3, 0x14, 0x47, 0xC5, 0xA7, 0x31),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x4C, 0x80, 0xF6, 0xA2, 0x57, 0xA7, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xB3, 0x7B, 0xF8, 0x2F, 0xE1, 0x3E, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_16_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xF4, 0xF9, 0x6B, 0x7B, 0x90, 0xDF, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x82, 0xEF, 0x62, 0xA1, 0x4C, 0x53, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x99, 0x76, 0x01, 0xBA, 0x8D, 0x0F, 0x54),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xF4, 0x58, 0x73, 0x56, 0xFE, 0xDD, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xCE, 0xF9, 0xE8, 0xA1, 0x34, 0xC3, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x5F, 0xDC, 0x6A, 0x3D, 0xD8, 0x7F, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xF4, 0x51, 0xB8, 0xB8, 0xC1, 0xD7, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x7D, 0x58, 0xD1, 0xD4, 0x1B, 0x4D, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_17_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x95, 0xDF, 0x00, 0xD8, 0x21, 0xDE, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x47, 0x3C, 0xC3, 0xB2, 0x01, 0x53, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x17, 0x43, 0x23, 0xBD, 0xCA, 0x71, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xBA, 0x0F, 0x4F, 0xDC, 0x41, 0x54, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x39, 0x26, 0x70, 0x53, 0x32, 0x18, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x46, 0x07, 0x97, 0x3A, 0x57, 0xE0, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x92, 0x4F, 0xCE, 0xDF, 0x25, 0x80, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x6F, 0x9A, 0x03, 0x05, 0x4B, 0xD1, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_17_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x01, 0x72, 0x30, 0x90, 0x17, 0x51, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xFB, 0x41, 0x65, 0x5C, 0xB4, 0x2D, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xCD, 0xCD, 0xAA, 0x41, 0xCC, 0xBB, 0x07),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xCE, 0x08, 0x0A, 0x63, 0xE9, 0xA2, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA8, 0x21, 0x7F, 0x7A, 0x5B, 0x9B, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x6B, 0x89, 0x44, 0x0A, 0x7F, 0x85, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xDE, 0x7C, 0x19, 0x5C, 0x65, 0x26, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xAC, 0x62, 0x29, 0x4A, 0xF1, 0xD0, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_18_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x00, 0x40, 0x87, 0xEB, 0xA9, 0x58, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x51, 0x0B, 0xFF, 0x56, 0x35, 0x51, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xAC, 0x08, 0x94, 0x71, 0xDA, 0xEC, 0x99),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x4D, 0xC5, 0x7B, 0x31, 0x8B, 0x8D, 0x5E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x05, 0xF1, 0x3E, 0x9E, 0x8F, 0x17, 0x8F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x9C, 0x4B, 0x62, 0x94, 0xAD, 0x49, 0xFC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC9, 0xC6, 0x8F, 0xFD, 0x33, 0x44, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x96, 0x17, 0x7F, 0x42, 0xBE, 0xF7, 0x0D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_18_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x29, 0x39, 0x13, 0x08, 0x8D, 0x91, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x79, 0xF9, 0x2F, 0xA9, 0x0A, 0xCF, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x87, 0x7A, 0xA3, 0x19, 0xAB, 0x55, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x0B, 0x01, 0xC5, 0x56, 0x19, 0x9D, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xDE, 0x82, 0x3B, 0xEA, 0xD3, 0x0B, 0x8C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x6B, 0xC7, 0xF3, 0x0F, 0x82, 0x87, 0x6C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x2E, 0x23, 0xF2, 0x39, 0x9D, 0x49, 0x70),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xDE, 0xAF, 0x7A, 0xEE, 0xB0, 0xDA, 0x70),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_19_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x4E, 0x2A, 0x50, 0xFD, 0x8E, 0xC0, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x0F, 0x7C, 0x76, 0x63, 0xD8, 0x89, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x2D, 0xB9, 0x4E, 0xF4, 0xEE, 0x85, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x95, 0x5C, 0x96, 0x5D, 0xAA, 0x59, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xDB, 0xD2, 0x68, 0x8E, 0x5A, 0x94, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x02, 0xBF, 0x77, 0x9F, 0xB9, 0x4C, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xDC, 0xC0, 0xCF, 0x81, 0x1E, 0xC4, 0x6C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xCC, 0x37, 0x86, 0xDC, 0xE2, 0x64, 0x72),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_19_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x30, 0xB1, 0x59, 0x20, 0x9D, 0x98, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x0C, 0x9D, 0xF8, 0x20, 0xDC, 0x90, 0xBA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xA0, 0xF4, 0xE7, 0x3E, 0x9C, 0x9E, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x25, 0xA2, 0xB0, 0x54, 0xCD, 0x2E, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD9, 0x42, 0xB0, 0x80, 0xB0, 0xA3, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xFE, 0x9D, 0x8D, 0x40, 0xFF, 0x27, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9D, 0xA6, 0x88, 0x3A, 0x8B, 0x6F, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x39, 0xEE, 0x1F, 0x3F, 0xB1, 0x4F, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_20_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD7, 0x9E, 0xFF, 0xD2, 0x35, 0x67, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x4F, 0x15, 0x5D, 0xE3, 0xE8, 0x53, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF7, 0x24, 0x98, 0xA2, 0xCB, 0x11, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x2E, 0x25, 0xE1, 0x94, 0xC5, 0xA3, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x82, 0x6E, 0xBA, 0xE7, 0x43, 0x25, 0xB0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x65, 0xB4, 0x49, 0x73, 0x18, 0x35, 0x54),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x5B, 0xBC, 0x62, 0x86, 0x4C, 0xC1, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xF2, 0x95, 0xA2, 0xBB, 0xA2, 0x35, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_20_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x59, 0x62, 0xB0, 0x4B, 0x1E, 0xB4, 0xD8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x55, 0xCE, 0xB0, 0x69, 0xBA, 0x63, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x69, 0x86, 0xDB, 0x34, 0x7D, 0x68, 0x64),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x06, 0xCA, 0x55, 0x44, 0x36, 0x2B, 0xBA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xD4, 0xC4, 0x3D, 0xCD, 0x9E, 0x69, 0xA4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x44, 0xE4, 0xBF, 0x31, 0xE6, 0x40, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x4F, 0xFA, 0x75, 0xE3, 0xFB, 0x97, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xC0, 0xBD, 0x1C, 0x48, 0xB0, 0x26, 0xD0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_21_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x7B, 0x32, 0xFA, 0xF2, 0x6D, 0x84, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x21, 0x03, 0x1D, 0x0D, 0x22, 0x55, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xF9, 0x42, 0x03, 0x9C, 0xC2, 0xCB, 0xBA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xA1, 0x96, 0xD9, 0x9D, 0x11, 0x6F, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x40, 0x57, 0xEB, 0x40, 0x2D, 0xC0, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x96, 0xBB, 0x4F, 0x2F, 0x23, 0xA8, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x29, 0x85, 0x21, 0xA5, 0x50, 0x62, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x7D, 0x92, 0xCF, 0x87, 0x0C, 0x22, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_21_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x0E, 0xA5, 0x32, 0x5B, 0xDF, 0x9C, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x96, 0x37, 0x2C, 0x88, 0x35, 0x30, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xB4, 0x69, 0xFF, 0xEB, 0xC6, 0x94, 0x08),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x55, 0x60, 0xAD, 0xAA, 0x58, 0x14, 0x88),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xFF, 0xF2, 0xB2, 0xD5, 0xA7, 0xD9, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xAE, 0x54, 0xD2, 0x60, 0x31, 0xF3, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x92, 0x83, 0xE3, 0xF1, 0x42, 0x83, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD2, 0xC8, 0xB7, 0x76, 0x45, 0x7F, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_22_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x11, 0xA4, 0xFB, 0x7A, 0x01, 0xBC, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x27, 0x73, 0x8D, 0x02, 0x91, 0x27, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x62, 0xF6, 0xDD, 0x6B, 0xFA, 0x5B, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCA, 0xA2, 0x44, 0x2C, 0xF0, 0x28, 0xD8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xF1, 0x7A, 0xA2, 0x42, 0x4C, 0x50, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x83, 0x3E, 0x50, 0xAB, 0x9C, 0xF7, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xED, 0x78, 0xCB, 0x76, 0x69, 0xDA, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x1E, 0x43, 0x27, 0x47, 0x6E, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_22_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x4F, 0x54, 0xB9, 0x3E, 0xBD, 0xD5, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x40, 0x69, 0x7F, 0x74, 0x9D, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x06, 0x6F, 0x67, 0x68, 0x2B, 0x4D, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x65, 0x41, 0xFC, 0x7C, 0x1E, 0xE8, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x79, 0x37, 0xAF, 0xFD, 0xD2, 0xDA, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xA8, 0x69, 0x56, 0x62, 0xA4, 0xE4, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x71, 0x73, 0x21, 0x8A, 0x17, 0x81, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x55, 0x8F, 0x7B, 0xB8, 0xAF, 0xF7, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_23_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xD1, 0xBD, 0xBE, 0x8C, 0xBC, 0x60, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA6, 0x57, 0x8C, 0xAE, 0x5C, 0x19, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x43, 0xE4, 0xD9, 0xD8, 0x7B, 0xE7, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xB9, 0xE4, 0x85, 0x7C, 0x2E, 0xFC, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2E, 0x01, 0x2A, 0x6D, 0x56, 0xBE, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x0C, 0x25, 0x9B, 0xAE, 0x86, 0x37, 0x43),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x22, 0xB3, 0xCB, 0x99, 0x66, 0xB7, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xF7, 0x90, 0xF0, 0x1B, 0x09, 0x27, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_23_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x16, 0x08, 0xEF, 0x39, 0x64, 0x49, 0x31),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA0, 0xE3, 0x97, 0xA9, 0x07, 0x54, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xFF, 0xE2, 0x00, 0x07, 0x21, 0x88, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFD, 0x59, 0x53, 0x05, 0x6C, 0x42, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xF7, 0x39, 0x5C, 0x82, 0x36, 0xE8, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x83, 0xA8, 0xE2, 0xA8, 0x43, 0x07, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xAF, 0x2B, 0x79, 0xED, 0xD8, 0x39, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x20, 0x91, 0x7A, 0xC4, 0x07, 0xEF, 0x6C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_24_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x2F, 0xAA, 0x0C, 0x94, 0x0E, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x81, 0x87, 0x41, 0x23, 0xEB, 0x55, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x53, 0xCC, 0x79, 0xB6, 0xEB, 0x6C, 0xCC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x77, 0x73, 0x9D, 0xFC, 0x64, 0x6F, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x40, 0xE3, 0x6D, 0x1C, 0x16, 0x71, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xF4, 0x1B, 0xFF, 0x1C, 0x2F, 0xA5, 0xD7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x0E, 0x0B, 0x11, 0xF4, 0x8D, 0x93, 0xAF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC5, 0x64, 0x6F, 0x24, 0x19, 0xF2, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_24_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xB3, 0xAF, 0xA5, 0x0E, 0x4F, 0x5E, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x77, 0xCA, 0xF2, 0x6D, 0xC5, 0xF6, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x18, 0x8E, 0x33, 0x68, 0x6C, 0xE8, 0xE0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x8B, 0x80, 0x90, 0x19, 0x7F, 0x90, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x80, 0x6B, 0x68, 0xE2, 0x7D, 0xD4, 0xD0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC1, 0x67, 0xB3, 0x72, 0xCB, 0xBF, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xD5, 0xD3, 0x1D, 0x14, 0x58, 0x0A, 0x80),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x7A, 0x65, 0x98, 0xB3, 0x07, 0x4B, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_25_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x87, 0x0F, 0x5F, 0xCF, 0xA2, 0x01, 0x08),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC9, 0xC8, 0x6E, 0x35, 0x87, 0xA5, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x3E, 0x91, 0xA0, 0xAB, 0x24, 0x1E, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBC, 0x02, 0x35, 0x70, 0xC1, 0x5F, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x59, 0xA0, 0x50, 0x04, 0x80, 0x52, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x56, 0x6E, 0x42, 0x8F, 0x8C, 0x91, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xA2, 0xCB, 0xA5, 0xDE, 0x14, 0x24, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xCB, 0x74, 0x28, 0xE6, 0xA7, 0xE7, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_25_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x73, 0xA8, 0x8F, 0x9E, 0x0E, 0x63, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x1B, 0x77, 0xC7, 0xC1, 0x38, 0xF9, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x3C, 0xCF, 0xA8, 0x7A, 0xD7, 0xF3, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x5F, 0x9A, 0xC9, 0xAD, 0xE9, 0x1A, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0x2B, 0x5E, 0xD5, 0x81, 0x95, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x88, 0x75, 0x29, 0x1F, 0xC7, 0xC7, 0xD0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA9, 0x5A, 0x4D, 0x63, 0x95, 0xF9, 0x4E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xCD, 0x04, 0x8F, 0xCD, 0x91, 0xDE, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_26_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xD4, 0xFD, 0x25, 0x11, 0x99, 0x6E, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x83, 0x01, 0x3D, 0xFB, 0x56, 0xA5, 0x4E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x3A, 0xDC, 0x74, 0xC2, 0xD7, 0xCF, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xBD, 0xF1, 0xDD, 0xA3, 0x07, 0x03, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xBE, 0xE9, 0x2E, 0x58, 0x84, 0x66, 0xFC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x20, 0x78, 0x37, 0x79, 0x0B, 0xA6, 0x64),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xF2, 0xAC, 0x65, 0xC8, 0xC9, 0x2F, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x93, 0xE5, 0x0D, 0x0C, 0xC6, 0xB8, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_26_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAD, 0x5C, 0x19, 0x12, 0x61, 0x0E, 0x25),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x4F, 0x0B, 0x1F, 0x49, 0x7E, 0xCD, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2E, 0x30, 0x61, 0xDB, 0x08, 0x68, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x78, 0xAF, 0xB3, 0x08, 0xC1, 0x69, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x5F, 0x5D, 0xC1, 0x57, 0x6F, 0xD8, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xD3, 0x6A, 0xF7, 0xFD, 0x86, 0xE5, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x63, 0xBD, 0x70, 0x7B, 0x47, 0xE8, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x62, 0xC8, 0x7E, 0x9D, 0x11, 0x2B, 0xA5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_27_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x84, 0xFD, 0xD5, 0x9A, 0x56, 0x7F, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBB, 0xA4, 0x6F, 0x12, 0x6E, 0x4D, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x08, 0xA1, 0x82, 0x9C, 0x62, 0x74, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x22, 0x05, 0x1D, 0x15, 0x35, 0x79),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x88, 0xCF, 0x5C, 0x05, 0x78, 0xFB, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x6B, 0x2F, 0x79, 0x09, 0x73, 0x67, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA0, 0x80, 0xD8, 0xE8, 0xEC, 0xFB, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0B, 0xB7, 0x81, 0x48, 0x7B, 0xD9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_27_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x53, 0xA9, 0xED, 0x61, 0x92, 0xD7, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x49, 0xD9, 0x5D, 0x9B, 0x4E, 0x89, 0x35),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x12, 0xEB, 0x9A, 0xC9, 0xCB, 0xC1, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xDC, 0x95, 0x16, 0xFE, 0x29, 0x70, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x33, 0xB1, 0xD6, 0x78, 0xB9, 0xE2, 0x36),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xCE, 0x88, 0xC3, 0xFD, 0x7A, 0x6B, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x1E, 0x50, 0x1E, 0xAF, 0xB1, 0x25, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xE7, 0xD7, 0xD5, 0xBD, 0x7A, 0x12, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_28_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xAA, 0xA2, 0x80, 0x5D, 0x8F, 0xCD, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x39, 0x79, 0x64, 0xA1, 0x67, 0x3C, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xC7, 0x49, 0xFF, 0x7F, 0xAC, 0xAB, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x54, 0x3E, 0x83, 0xF0, 0x3D, 0xBC, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x92, 0x4A, 0x38, 0x42, 0x8A, 0xAB, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x0B, 0x4F, 0xEE, 0x9E, 0x92, 0xA5, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xDD, 0x19, 0x96, 0xF2, 0xF0, 0x6B, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xFC, 0xDD, 0xB2, 0x8A, 0xE5, 0x4C, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_28_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x06, 0x49, 0xAC, 0x99, 0x7E, 0xF8, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xC8, 0x01, 0x51, 0xEA, 0xF6, 0x52, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x89, 0x66, 0x2B, 0x1F, 0x9B, 0x2A, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x0F, 0x95, 0x07, 0x2B, 0x6C, 0x6E, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC3, 0xB4, 0xBB, 0x91, 0x1F, 0xA3, 0x72),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x6E, 0x54, 0x28, 0x7B, 0x9C, 0x79, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x45, 0xFF, 0xA6, 0xDA, 0xA2, 0x83, 0x71),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xDE, 0x8F, 0x17, 0x37, 0x82, 0xCB, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_29_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x94, 0x3F, 0x26, 0xC9, 0x1D, 0xD9, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x28, 0x20, 0xCD, 0xC1, 0xF3, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC9, 0xB5, 0x60, 0x9B, 0x1E, 0xDC, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xB9, 0x5B, 0x7D, 0xA0, 0xB2, 0x8C, 0xF0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xD1, 0x42, 0xE6, 0x39, 0x33, 0x6D, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xC0, 0xFC, 0xD2, 0x14, 0x5D, 0x3E, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x4A, 0x3E, 0x40, 0x16, 0x93, 0x15, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x24, 0xC1, 0x27, 0x27, 0xE5, 0x4B, 0xD8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_29_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x50, 0xD8, 0xBC, 0xC1, 0x46, 0x22, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x0E, 0x60, 0xA1, 0xB3, 0x50, 0xD4, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xB1, 0x26, 0xB6, 0x6D, 0x47, 0x5A, 0x6F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0xAC, 0x11, 0x35, 0x3E, 0xB9, 0xF4, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x97, 0xFA, 0xBB, 0x6B, 0x39, 0x13, 0xD8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x34, 0x12, 0x75, 0x8E, 0x9B, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x9E, 0xCD, 0x29, 0xB6, 0xEF, 0x8D, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xAC, 0xE9, 0x25, 0x27, 0xBB, 0x78, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_30_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x7A, 0xA8, 0xD3, 0xE3, 0x66, 0xE5, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x4C, 0xC4, 0x2C, 0x76, 0x81, 0x50, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x71, 0x08, 0xB8, 0x52, 0x7C, 0xAF, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x59, 0x24, 0xDD, 0xFB, 0x2F, 0xD0, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCD, 0x56, 0xE9, 0xAC, 0x91, 0xE6, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x64, 0x20, 0xC6, 0x9F, 0xE4, 0xEF, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x2C, 0x8F, 0x8C, 0x97, 0xF6, 0x22, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0x88, 0xAA, 0xA8, 0xD7, 0xA5, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_30_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x6C, 0xAE, 0x83, 0xB1, 0x55, 0x55, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x67, 0x84, 0x47, 0x7C, 0x83, 0x5C, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x10, 0x4D, 0xDD, 0x30, 0x60, 0xB0, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xA7, 0x36, 0x76, 0x24, 0x32, 0x9F, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x42, 0x81, 0xFB, 0xA4, 0x2E, 0x13, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x94, 0x91, 0xFF, 0x99, 0xA0, 0x09, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x83, 0xA1, 0x76, 0xAF, 0x37, 0x5C, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA8, 0x04, 0x86, 0xC4, 0xA9, 0x79, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_31_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8C, 0xC2, 0x34, 0xFB, 0x83, 0x28, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x03, 0x7D, 0x5E, 0x9E, 0x0E, 0xB0, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x02, 0x46, 0x7F, 0xB9, 0xAC, 0xBB, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xED, 0x48, 0xC2, 0x96, 0x4D, 0x56, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xC5, 0xD1, 0xE6, 0x1C, 0x7E, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x2E, 0x18, 0x71, 0x2D, 0x7B, 0xD7, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x46, 0x9D, 0xDE, 0xAA, 0x78, 0x8E, 0xB1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD7, 0x69, 0x2E, 0xE1, 0xD9, 0x48, 0xDE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_31_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFF, 0x9E, 0x09, 0x22, 0x22, 0xE6, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x14, 0x28, 0x13, 0x1B, 0x62, 0x12, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x7F, 0x67, 0x03, 0xB0, 0xC0, 0xF3, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xC3, 0x0F, 0xFB, 0x25, 0x48, 0x3E, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x6E, 0x53, 0x98, 0x36, 0xB3, 0xD3, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x81, 0x54, 0x22, 0xA4, 0xCC, 0xC1, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xBA, 0xFC, 0xA9, 0xDF, 0x68, 0x86, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x92, 0x0E, 0xC3, 0xF2, 0x58, 0xE8, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_ecp_point secp521r1_T[32] = {\n    ECP_POINT_INIT_XY_Z1(secp521r1_T_0_X, secp521r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_1_X, secp521r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_2_X, secp521r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_3_X, secp521r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_4_X, secp521r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_5_X, secp521r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_6_X, secp521r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_7_X, secp521r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_8_X, secp521r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_9_X, secp521r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_10_X, secp521r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_11_X, secp521r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_12_X, secp521r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_13_X, secp521r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_14_X, secp521r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_15_X, secp521r1_T_15_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_16_X, secp521r1_T_16_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_17_X, secp521r1_T_17_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_18_X, secp521r1_T_18_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_19_X, secp521r1_T_19_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_20_X, secp521r1_T_20_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_21_X, secp521r1_T_21_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_22_X, secp521r1_T_22_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_23_X, secp521r1_T_23_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_24_X, secp521r1_T_24_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_25_X, secp521r1_T_25_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_26_X, secp521r1_T_26_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_27_X, secp521r1_T_27_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_28_X, secp521r1_T_28_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_29_X, secp521r1_T_29_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_30_X, secp521r1_T_30_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_31_X, secp521r1_T_31_Y),\n};\n#else\n#define secp521r1_T NULL\n#endif\n#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)\nstatic const mbedtls_mpi_uint secp192k1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp192k1_a[] = {\n    MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp192k1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_2(0x03, 0x00),\n};\nstatic const mbedtls_mpi_uint secp192k1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB),\n};\nstatic const mbedtls_mpi_uint secp192k1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B),\n};\nstatic const mbedtls_mpi_uint secp192k1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\n\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp192k1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x77, 0x3D, 0x0D, 0x85, 0x48, 0xA8, 0xA9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x07, 0xDF, 0x1D, 0xB3, 0xB3, 0x01, 0x54),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x86, 0xF6, 0xAF, 0x19, 0x2A, 0x88, 0x2E),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x90, 0xB6, 0x2F, 0x48, 0x36, 0x4C, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x11, 0x14, 0xA6, 0xCB, 0xBA, 0x15, 0xD9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB0, 0xF2, 0xD4, 0xC9, 0xDA, 0xBA, 0xD7),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xC1, 0x9C, 0xE6, 0xBB, 0xFB, 0xCF, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x19, 0xAC, 0x5A, 0xC9, 0x8A, 0x1C, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xF6, 0x76, 0x86, 0x89, 0x27, 0x8D, 0x28),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xE0, 0x6F, 0x34, 0xBA, 0x5E, 0xD3, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xDC, 0xA6, 0x87, 0xC9, 0x9D, 0xC0, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x11, 0x7E, 0xD6, 0xF7, 0x33, 0xFC, 0xE4),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x37, 0x3E, 0xC0, 0x7F, 0x62, 0xE7, 0x54),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3B, 0x69, 0x9D, 0x44, 0xBC, 0x82, 0x99),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x84, 0xB3, 0x5F, 0x2B, 0xA5, 0x9E, 0x2C),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x95, 0xEB, 0x4C, 0x04, 0xB4, 0xF4, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAD, 0x4B, 0xD5, 0x9A, 0xEB, 0xC4, 0x4E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xB1, 0xC5, 0x59, 0xE3, 0xD5, 0x16, 0x2A),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x2A, 0xCC, 0xAC, 0xD0, 0xEE, 0x50, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x83, 0xE0, 0x5B, 0x14, 0x44, 0x52, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x15, 0x2D, 0x78, 0xF6, 0x51, 0x32, 0xCF),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x36, 0x9B, 0xDD, 0xF8, 0xDD, 0xEF, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xB1, 0x6A, 0x2B, 0xAF, 0xEB, 0x2B, 0xB1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x87, 0x7A, 0x66, 0x5D, 0x5B, 0xDF, 0x8F),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x45, 0xE5, 0x81, 0x9B, 0xEB, 0x37, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x29, 0xE2, 0x20, 0x64, 0x23, 0x6B, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1D, 0x41, 0xE1, 0x9B, 0x61, 0x7B, 0xD9),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x57, 0xA3, 0x0A, 0x13, 0xE4, 0x59, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x6E, 0x4A, 0x48, 0x84, 0x90, 0xAC, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB8, 0xF5, 0xF3, 0xDE, 0xA0, 0xA1, 0x1D),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x32, 0x81, 0xA9, 0x91, 0x5A, 0x4E, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xA8, 0x90, 0xBE, 0x0F, 0xEC, 0xC0, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x30, 0xD7, 0x08, 0xAE, 0xC4, 0x3A, 0xA5),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x55, 0xE3, 0x76, 0xB3, 0x64, 0x74, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x75, 0xD4, 0xDB, 0x98, 0xD7, 0x39, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xEB, 0x8A, 0xAB, 0x16, 0xD9, 0xD4, 0x0B),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xBE, 0xF9, 0xC7, 0xC7, 0xBA, 0xF3, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x85, 0x59, 0xF3, 0x60, 0x41, 0x02, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x1C, 0x4A, 0xA4, 0xC7, 0xED, 0x66, 0xBC),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x2E, 0x46, 0x52, 0x18, 0x87, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x35, 0x5A, 0x75, 0xAC, 0x4D, 0x75, 0x91),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x2F, 0xAC, 0xFC, 0xBC, 0xE6, 0x93, 0x5E),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x4D, 0xC9, 0x18, 0xE9, 0x00, 0xEB, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x69, 0x72, 0x07, 0x5A, 0x59, 0xA8, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x65, 0x83, 0x20, 0x10, 0xF9, 0x69, 0x82),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x56, 0x7F, 0x9F, 0xBF, 0x46, 0x0C, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0xF0, 0xDC, 0xDF, 0x2D, 0xE6, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xF0, 0x72, 0x3A, 0x7A, 0x03, 0xE5, 0x22),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xAA, 0x57, 0x13, 0x37, 0xA7, 0x2C, 0xD4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xAC, 0xA2, 0x23, 0xF9, 0x84, 0x60, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xEB, 0x51, 0x70, 0x64, 0x78, 0xCA, 0x05),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xCC, 0x30, 0x62, 0x93, 0x46, 0x13, 0xE9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x26, 0xCC, 0x6C, 0x3D, 0x5C, 0xDA, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xAA, 0xB8, 0x03, 0xA4, 0x1A, 0x00, 0x96),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x9D, 0xE6, 0xCC, 0x4E, 0x2E, 0xC2, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xC3, 0x8A, 0xAE, 0x6F, 0x40, 0x05, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x8F, 0x4A, 0x4D, 0x35, 0xD3, 0x50, 0x9D),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xFD, 0x98, 0xAB, 0xC7, 0x03, 0xB4, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x40, 0xD2, 0x9F, 0xCA, 0xD0, 0x53, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x84, 0x00, 0x6F, 0xC8, 0xAD, 0xED, 0x8D),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xD3, 0x57, 0xD7, 0xC3, 0x07, 0xBD, 0xD7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xBA, 0x47, 0x1D, 0x3D, 0xEF, 0x98, 0x6C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC0, 0x6C, 0x7F, 0x12, 0xEE, 0x9F, 0x67),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x02, 0xDA, 0x79, 0xAA, 0xC9, 0x27, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x79, 0xC7, 0x71, 0x84, 0xCB, 0xE5, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x37, 0x06, 0xBA, 0xB5, 0xD5, 0x18, 0x4C),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x65, 0x72, 0x6C, 0xF2, 0x63, 0x27, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xBC, 0x71, 0xDF, 0x75, 0xF8, 0x98, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x70, 0x9B, 0xDC, 0xE7, 0x18, 0x71, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x5B, 0x9F, 0x00, 0x5A, 0xB6, 0x80, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE0, 0xBB, 0xFC, 0x5E, 0x78, 0x9C, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x03, 0x68, 0x83, 0x3D, 0x2E, 0x4C, 0xDD),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x49, 0x23, 0xA8, 0xCB, 0x3B, 0x1A, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x3D, 0xA7, 0x46, 0xCF, 0x75, 0xB6, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xFD, 0x30, 0x01, 0xB6, 0xEF, 0xF9, 0xE8),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xFA, 0xDA, 0xB8, 0x29, 0x42, 0xC9, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xD7, 0xA0, 0xE6, 0x6B, 0x86, 0x61, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xE9, 0xD3, 0x37, 0xD8, 0xE7, 0x35, 0xA9),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC8, 0x8E, 0xB1, 0xCB, 0xB1, 0xB5, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xD7, 0x46, 0x7D, 0xAF, 0xE2, 0xDC, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x46, 0xE7, 0xD8, 0x76, 0x31, 0x90, 0x76),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD3, 0xF4, 0x74, 0xE1, 0x67, 0xD8, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x70, 0x3C, 0xC8, 0xAF, 0x5F, 0xF4, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x4E, 0xED, 0x5C, 0x43, 0xB3, 0x16, 0x35),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAE, 0xD1, 0xDD, 0x31, 0x14, 0xD3, 0xF0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x14, 0x06, 0x13, 0x12, 0x1C, 0x81, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xF9, 0x0C, 0x91, 0xF7, 0x67, 0x59, 0x63),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x91, 0xE2, 0xF4, 0x9D, 0xEB, 0x88, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x82, 0x30, 0x9C, 0xAE, 0x18, 0x4D, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x79, 0xCF, 0x17, 0xA5, 0x1E, 0xE8, 0xC8),\n};\nstatic const mbedtls_ecp_point secp192k1_T[16] = {\n    ECP_POINT_INIT_XY_Z1(secp192k1_T_0_X, secp192k1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_1_X, secp192k1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_2_X, secp192k1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_3_X, secp192k1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_4_X, secp192k1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_5_X, secp192k1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_6_X, secp192k1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_7_X, secp192k1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_8_X, secp192k1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_9_X, secp192k1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_10_X, secp192k1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_11_X, secp192k1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_12_X, secp192k1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_13_X, secp192k1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_14_X, secp192k1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_15_X, secp192k1_T_15_Y),\n};\n#else\n#define secp192k1_T NULL\n#endif\n\n#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)\nstatic const mbedtls_mpi_uint secp224k1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp224k1_a[] = {\n    MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_2(0x05, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_4(0x33, 0x5B, 0x45, 0xA1),\n};\nstatic const mbedtls_mpi_uint secp224k1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_4(0xED, 0x9F, 0x08, 0x7E),\n};\nstatic const mbedtls_mpi_uint secp224k1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),\n};\n\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp224k1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x5B, 0x45, 0xA1, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x9F, 0x08, 0x7E, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x6C, 0x22, 0x22, 0x40, 0x89, 0xAE, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x92, 0xE1, 0x87, 0x56, 0x35, 0xAF, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xAF, 0x08, 0x35, 0x27, 0xEA, 0x04, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x53, 0xFD, 0xCF, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xD0, 0x9F, 0x8D, 0xF3, 0x63, 0x54, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xDB, 0x0F, 0x61, 0x54, 0x26, 0xD1, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x21, 0xF7, 0x1B, 0xB5, 0x1D, 0xF6, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x05, 0xDA, 0x8F, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x26, 0x73, 0xBC, 0xE4, 0x29, 0x62, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x95, 0x17, 0x8B, 0xC3, 0x9B, 0xAC, 0xCC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xDB, 0x77, 0xDF, 0xDD, 0x13, 0x04, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xFC, 0x22, 0x93, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0xF1, 0x5A, 0x37, 0xEF, 0x79, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x37, 0xAC, 0x9A, 0x5B, 0x51, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x75, 0x13, 0xA9, 0x4A, 0xAD, 0xFE, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x82, 0x6F, 0x66, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x5E, 0xF0, 0x40, 0xC3, 0xA6, 0xE2, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x9A, 0x6F, 0xCF, 0x11, 0x26, 0x66, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x73, 0xA8, 0xCF, 0x2B, 0x12, 0x36, 0x37),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xB3, 0x0A, 0x58, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x79, 0x00, 0x55, 0x04, 0x34, 0x90, 0x1A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x54, 0x1C, 0xC2, 0x45, 0x0C, 0x1B, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x19, 0xAB, 0xA8, 0xFC, 0x73, 0xDC, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xFB, 0x93, 0xCE, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x75, 0xD0, 0x66, 0x95, 0x86, 0xCA, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xEA, 0x29, 0x16, 0x6A, 0x38, 0xDF, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA2, 0x36, 0x2F, 0xDC, 0xBB, 0x5E, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x89, 0x59, 0x49, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xA3, 0x99, 0x9D, 0xB8, 0x77, 0x9D, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x93, 0x43, 0x47, 0xC6, 0x5C, 0xF9, 0xFD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x00, 0x79, 0x42, 0x64, 0xB8, 0x25, 0x3E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x54, 0xB4, 0x33, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x0C, 0x42, 0x90, 0x83, 0x0B, 0x31, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2E, 0xAE, 0xC8, 0xC7, 0x5F, 0xD2, 0x70),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xBC, 0xAD, 0x41, 0xE7, 0x32, 0x3A, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x97, 0x52, 0x83, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x13, 0x7A, 0xBD, 0xAE, 0x94, 0x60, 0xFD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x9B, 0x95, 0xB4, 0x6E, 0x68, 0xB2, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x49, 0xBE, 0x51, 0xFE, 0x66, 0x15, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x37, 0xE4, 0xFE, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x9B, 0xEE, 0x64, 0xC9, 0x1B, 0xBD, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x5F, 0x34, 0xA9, 0x0B, 0xB7, 0x25, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x13, 0xB1, 0x38, 0xFB, 0x9D, 0x78, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xE7, 0x1B, 0xFA, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xB3, 0xB7, 0x44, 0x92, 0x6B, 0x00, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x82, 0x44, 0x3E, 0x18, 0x1A, 0x58, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF8, 0xC0, 0xE4, 0xEE, 0xC1, 0xBF, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x32, 0x27, 0xB2, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x9A, 0x42, 0x62, 0x8B, 0x26, 0x54, 0x21),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x85, 0x74, 0xA0, 0x79, 0xA8, 0xEE, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0x60, 0xB3, 0x28, 0x4D, 0x55, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x27, 0x82, 0x29, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xFC, 0x73, 0x77, 0xAF, 0x5C, 0xAC, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xED, 0xE5, 0xF6, 0x1D, 0xA8, 0x67, 0x43),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xDE, 0x33, 0x1C, 0xF1, 0x80, 0x73, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE2, 0xDE, 0x3C, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x3E, 0x6B, 0xFE, 0xF0, 0x04, 0x28, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xB2, 0x14, 0x9D, 0x18, 0x11, 0x7D, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC4, 0xD6, 0x2E, 0x6E, 0x57, 0x4D, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x55, 0x1B, 0xDE, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xF7, 0x17, 0xBC, 0x45, 0xAB, 0x16, 0xAB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xB0, 0xEF, 0x61, 0xE3, 0x20, 0x7C, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x85, 0x41, 0x4D, 0xF1, 0x7E, 0x4D, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC2, 0x9B, 0x5E, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x2E, 0x49, 0x3D, 0x3E, 0x4B, 0xD3, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x2B, 0x9D, 0xD5, 0x27, 0xFA, 0xCA, 0xE0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xB3, 0x6A, 0xE0, 0x79, 0x14, 0x28, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x1E, 0xDC, 0xF5, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x44, 0x56, 0xCD, 0xFC, 0x9F, 0x09, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x8C, 0x59, 0xA4, 0x64, 0x2A, 0x3A, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xA0, 0xB5, 0x86, 0x4E, 0x69, 0xDA, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x8B, 0x11, 0x38, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x17, 0x16, 0x12, 0x17, 0xDC, 0x00, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x76, 0x24, 0x6C, 0x97, 0x2C, 0xB5, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x71, 0xE3, 0xB0, 0xBB, 0x4E, 0x50, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x48, 0x26, 0xD5, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x5F, 0x28, 0xF6, 0x01, 0x5A, 0x60, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x95, 0xFE, 0xD0, 0xAD, 0x15, 0xD4, 0xD9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0x7A, 0xFD, 0x80, 0xF7, 0x9F, 0x64),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xBC, 0x1B, 0xDF, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xE6, 0xDF, 0x14, 0x29, 0xF4, 0xD4, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x12, 0xDD, 0xEC, 0x5B, 0x8A, 0x59, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x92, 0x3E, 0x35, 0x08, 0xE9, 0xCF, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x35, 0x29, 0x97, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xDB, 0xD6, 0x6A, 0xC5, 0x43, 0xA4, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x33, 0x50, 0x61, 0x70, 0xA1, 0xE9, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x15, 0x6E, 0x5F, 0x01, 0x0C, 0x8C, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xA1, 0x9A, 0x9D, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xC6, 0xF7, 0xE2, 0x4A, 0xCD, 0x9B, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x4D, 0x5A, 0xB8, 0xE2, 0x6D, 0xA6, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3F, 0xB6, 0x17, 0xE3, 0x2C, 0x6F, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA4, 0x59, 0x51, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x4F, 0x7C, 0x49, 0xCD, 0x6E, 0xEB, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xC9, 0x1F, 0xB7, 0x4D, 0x98, 0xC7, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xFD, 0x98, 0x20, 0x95, 0xBB, 0x20, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF2, 0x73, 0x92, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xEF, 0xFB, 0x30, 0xFA, 0x12, 0x1A, 0xB0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x4C, 0x24, 0xB4, 0x5B, 0xC9, 0x4C, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xDD, 0x5E, 0x84, 0x95, 0x4D, 0x26, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xFA, 0xF9, 0x3A, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xA3, 0x2E, 0x7A, 0xDC, 0xA7, 0x53, 0xA9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x9F, 0x81, 0x84, 0xB2, 0x0D, 0xFE, 0x31),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x89, 0x1B, 0x77, 0x0C, 0x89, 0x71, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0x7F, 0xB2, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xE9, 0x2C, 0x79, 0xA6, 0x3C, 0xAD, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE0, 0x23, 0x02, 0x86, 0x0F, 0x77, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x93, 0x6D, 0xE9, 0xF9, 0x3C, 0xBE, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xE7, 0x24, 0x92, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x3C, 0x5B, 0x4B, 0x1B, 0x25, 0x37, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xE8, 0x38, 0x1B, 0xA1, 0x5A, 0x2E, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x19, 0xFD, 0xF4, 0x78, 0x01, 0x6B, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x69, 0x37, 0x4F, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xE2, 0xBF, 0xD3, 0xEC, 0x95, 0x9C, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x7B, 0xFC, 0xD5, 0xD3, 0x25, 0x5E, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x55, 0x09, 0xA2, 0x58, 0x6A, 0xC9, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xCC, 0x3B, 0xD9, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x08, 0x65, 0x5E, 0xCB, 0xAB, 0x48, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x79, 0x8B, 0xC0, 0x11, 0xC0, 0x69, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xE8, 0x8C, 0x4C, 0xC5, 0x28, 0xE4, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x1F, 0x34, 0x5C, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_ecp_point secp224k1_T[16] = {\n    ECP_POINT_INIT_XY_Z1(secp224k1_T_0_X, secp224k1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_1_X, secp224k1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_2_X, secp224k1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_3_X, secp224k1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_4_X, secp224k1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_5_X, secp224k1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_6_X, secp224k1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_7_X, secp224k1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_8_X, secp224k1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_9_X, secp224k1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_10_X, secp224k1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_11_X, secp224k1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_12_X, secp224k1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_13_X, secp224k1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_14_X, secp224k1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_15_X, secp224k1_T_15_Y),\n};\n#else\n#define secp224k1_T NULL\n#endif\n#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\nstatic const mbedtls_mpi_uint secp256k1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp256k1_a[] = {\n    MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp256k1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_2(0x07, 0x00),\n};\nstatic const mbedtls_mpi_uint secp256k1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79),\n};\nstatic const mbedtls_mpi_uint secp256k1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48),\n};\nstatic const mbedtls_mpi_uint secp256k1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\n\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp256k1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xEE, 0xD7, 0x1E, 0x67, 0x86, 0x32, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0xB1, 0xA9, 0xD5, 0xCC, 0x27, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0E, 0x11, 0x01, 0x71, 0xFE, 0x92, 0x73),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x28, 0x63, 0x6D, 0x72, 0x09, 0xA6, 0xC0),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0x69, 0xDC, 0x3E, 0x2C, 0x75, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xB7, 0x3F, 0x30, 0x26, 0x3C, 0xDF, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBE, 0xB9, 0x5D, 0x0E, 0xE8, 0x5E, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xC3, 0x05, 0xD6, 0xB7, 0xD5, 0x24, 0xFC),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCF, 0x7B, 0xDC, 0xCD, 0xC3, 0x39, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xDA, 0xB9, 0xE5, 0x64, 0xA7, 0x47, 0x91),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x46, 0xA8, 0x61, 0xF6, 0x23, 0xEB, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xC1, 0xFF, 0xE4, 0x55, 0xD5, 0xC2, 0xBF),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xBE, 0xB9, 0x59, 0x24, 0x13, 0x4A, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x45, 0x12, 0xDE, 0xBA, 0x4F, 0xEF, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x08, 0xBF, 0xC1, 0x66, 0xAA, 0x0A, 0xBC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xFE, 0x30, 0x55, 0x31, 0x86, 0xA7, 0xB4),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBF, 0x18, 0x81, 0x67, 0x27, 0x42, 0xBD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x05, 0x83, 0xA4, 0xDD, 0x57, 0xD3, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x63, 0xAB, 0xE4, 0x90, 0x70, 0xD0, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x5D, 0xFD, 0xA0, 0xEF, 0xCF, 0x1C, 0x54),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x80, 0xE4, 0xF6, 0x09, 0xBC, 0x57, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x9F, 0x6E, 0x88, 0x54, 0x6E, 0x51, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x5F, 0x85, 0xFB, 0x84, 0x3E, 0x4A, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x19, 0xF5, 0x55, 0xC9, 0x07, 0xD8, 0xCE),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xB4, 0xC3, 0xD9, 0x5C, 0xA0, 0xD4, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x30, 0xAF, 0x59, 0x9B, 0xF8, 0x04, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xA6, 0xFD, 0x66, 0x7B, 0xC3, 0x39, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xBF, 0xF0, 0xC2, 0xE9, 0x71, 0xA4, 0x9E),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x2D, 0xB9, 0x88, 0x28, 0xF1, 0xBE, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF3, 0x1A, 0x0E, 0xB9, 0x01, 0x66, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0xA4, 0xF4, 0x05, 0xD0, 0xAA, 0x53),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x39, 0x1E, 0x47, 0xE5, 0x68, 0xC8, 0xC0),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xB9, 0xFC, 0xE0, 0x33, 0x8A, 0x7D, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x93, 0xA5, 0x53, 0x55, 0x16, 0xB4, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x5F, 0xEA, 0x9B, 0x29, 0x52, 0x71, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xF0, 0x24, 0xB8, 0x7D, 0xB7, 0xA0, 0x9B),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x00, 0x27, 0xB2, 0xDF, 0x73, 0xA2, 0xE0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x2E, 0x4D, 0x7C, 0xDE, 0x7A, 0x23, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0x60, 0xC7, 0x97, 0x1E, 0xA4, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x13, 0x5B, 0x77, 0x59, 0xCB, 0x36, 0xE1),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xBC, 0x9F, 0x9E, 0x2D, 0x53, 0x2A, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x5F, 0x64, 0x9F, 0x1A, 0x19, 0xE6, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x7B, 0x39, 0xD2, 0xDB, 0x85, 0x84, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xC7, 0x0D, 0x58, 0x6E, 0x3F, 0x52, 0x15),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x68, 0x19, 0x0B, 0x68, 0xC9, 0x1E, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x4E, 0x21, 0x49, 0x3D, 0x55, 0xCC, 0x25),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF9, 0x25, 0x45, 0x54, 0x45, 0xB1, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xF7, 0xCD, 0x80, 0xA4, 0x04, 0x05),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x1E, 0x88, 0xC4, 0xAA, 0x18, 0x7E, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xAC, 0xD9, 0xB2, 0xA1, 0xC0, 0x71, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xA2, 0xF1, 0x15, 0xA6, 0x5F, 0x6C, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x5B, 0x05, 0xBC, 0xB7, 0xC6, 0x4E, 0x72),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x80, 0xF8, 0x5C, 0x20, 0x2A, 0xE1, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x48, 0x2E, 0x68, 0x82, 0x7F, 0xEB, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x3B, 0x25, 0xDB, 0x32, 0x4D, 0x88, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x6E, 0xA6, 0xB6, 0x6D, 0x62, 0x78, 0x22),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4D, 0x3E, 0x86, 0x58, 0xC3, 0xEB, 0xBA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x89, 0x33, 0x18, 0x21, 0x1D, 0x9B, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x9D, 0xFF, 0xC3, 0x79, 0xC1, 0x88, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xD4, 0x48, 0x53, 0xE8, 0xAD, 0x21, 0x16),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x7B, 0xDE, 0xCB, 0xD8, 0x39, 0x17, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xF3, 0x03, 0xF2, 0x5C, 0xBC, 0xC8, 0x8A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xAE, 0x4C, 0xB0, 0x16, 0xA4, 0x93, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8B, 0x6B, 0xDC, 0xD7, 0x9A, 0x3E, 0x7E),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x2D, 0x7A, 0xD2, 0x59, 0x05, 0xA2, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x56, 0x09, 0x32, 0xF1, 0xE8, 0xE3, 0x72),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xCA, 0xE5, 0x2E, 0xF0, 0xFB, 0x18, 0x19),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x85, 0xA9, 0x23, 0x15, 0x31, 0x1F, 0x0E),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xE5, 0xB1, 0x86, 0xB9, 0x6E, 0x8D, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x77, 0xFC, 0xC9, 0xA3, 0x3F, 0x89, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x6A, 0xDC, 0x25, 0xB0, 0xC7, 0x41, 0x54),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x11, 0x6B, 0xA6, 0x11, 0x62, 0xD4, 0x2D),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7D, 0x34, 0xB3, 0x20, 0x7F, 0x37, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xD4, 0x45, 0xE8, 0xC2, 0xE9, 0xC5, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x32, 0x3B, 0x25, 0x7E, 0x79, 0xAF, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xE4, 0x54, 0x71, 0xBE, 0x35, 0x4E, 0xD0),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x94, 0xDD, 0x8F, 0xB5, 0xC2, 0xDD, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x49, 0xE9, 0x1C, 0x2F, 0x08, 0x49, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xB6, 0x03, 0x88, 0x6F, 0xB8, 0x15, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xD3, 0x1C, 0xF3, 0xA5, 0xEB, 0x79, 0x01),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF9, 0x43, 0x88, 0x89, 0x0D, 0x06, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2D, 0xF5, 0x98, 0x32, 0xF6, 0xB1, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0x8F, 0x2B, 0x50, 0x27, 0x0A, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE3, 0xBD, 0x16, 0x05, 0xC8, 0x93, 0x12),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x6A, 0xF7, 0xE3, 0x3D, 0xDE, 0x5F, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA3, 0x9C, 0x22, 0x3C, 0x33, 0x36, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x24, 0x4C, 0x69, 0x45, 0x78, 0x14, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xF8, 0xD4, 0xBF, 0xB8, 0xC0, 0xA1, 0x25),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x88, 0xE1, 0x91, 0x03, 0xEB, 0xB3, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x11, 0xA1, 0xEF, 0x14, 0x0D, 0xC4, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xD4, 0x0D, 0x1D, 0x96, 0x33, 0x5C, 0x19),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x45, 0x2A, 0x1A, 0xE6, 0x57, 0x04, 0x9B),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xB5, 0xA7, 0x80, 0xE9, 0x93, 0x97, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xB9, 0x7C, 0xA0, 0xC9, 0x57, 0x26, 0x43),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xEF, 0x56, 0xDA, 0x66, 0xF6, 0x1B, 0x9A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x89, 0x6B, 0x91, 0xE0, 0xA9, 0x65, 0x2B),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x98, 0x96, 0x9B, 0x06, 0x7D, 0x5E, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xFA, 0xC1, 0x5F, 0x19, 0x37, 0x94, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xBE, 0x6B, 0x1A, 0x05, 0xE4, 0xBF, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xCD, 0x5D, 0x35, 0xB4, 0x51, 0xF7, 0x64),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xEF, 0x96, 0xDB, 0xF2, 0x61, 0x63, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x04, 0x88, 0xC9, 0x9F, 0x1B, 0x94, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x30, 0x79, 0x7E, 0x24, 0xE7, 0x5F, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xB8, 0x90, 0xB7, 0x94, 0x25, 0xBB, 0x0F),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x79, 0xEA, 0xAD, 0xC0, 0x6D, 0x18, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xA4, 0x58, 0x2A, 0x8D, 0x95, 0xB3, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC4, 0xC2, 0x12, 0x0D, 0x79, 0xE2, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6F, 0xBE, 0x97, 0x4D, 0xA4, 0x20, 0x07),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x31, 0x71, 0xC6, 0xA6, 0x91, 0xEB, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x9B, 0xA8, 0x4A, 0xE7, 0x77, 0xE1, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x06, 0xD3, 0x3D, 0x94, 0x30, 0xEF, 0x8C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xDF, 0xCA, 0xFA, 0xF5, 0x28, 0xF8, 0xC9),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xE1, 0x32, 0xFD, 0x3E, 0x81, 0xF8, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xF2, 0x4B, 0x1D, 0x19, 0xC9, 0x0F, 0xCC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB1, 0x8A, 0x22, 0x8B, 0x05, 0x6B, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x21, 0xEF, 0x30, 0xEC, 0x09, 0x2A, 0x89),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x84, 0x4A, 0x46, 0x07, 0x6C, 0x3C, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x18, 0x3A, 0xF4, 0xCC, 0xF5, 0xB2, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x8F, 0xCD, 0x0A, 0x9C, 0xF4, 0xBD, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x89, 0x7F, 0x8A, 0xB1, 0x52, 0x3A, 0xAB),\n};\nstatic const mbedtls_ecp_point secp256k1_T[16] = {\n    ECP_POINT_INIT_XY_Z1(secp256k1_T_0_X, secp256k1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_1_X, secp256k1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_2_X, secp256k1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_3_X, secp256k1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_4_X, secp256k1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_5_X, secp256k1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_6_X, secp256k1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_7_X, secp256k1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_8_X, secp256k1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_9_X, secp256k1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_10_X, secp256k1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_11_X, secp256k1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_12_X, secp256k1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_13_X, secp256k1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_14_X, secp256k1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_15_X, secp256k1_T_15_Y),\n};\n#else\n#define secp256k1_T NULL\n#endif\n#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */\n\n/*\n * Domain parameters for brainpoolP256r1 (RFC 5639 3.4)\n */\n#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)\nstatic const mbedtls_mpi_uint brainpoolP256r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_a[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9),\n};\n\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xA2, 0xED, 0x52, 0xC9, 0x8C, 0xE3, 0xA5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xC9, 0xC4, 0x87, 0x3F, 0x93, 0x7A, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x12, 0x53, 0x61, 0x3E, 0x76, 0x08, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x8C, 0x74, 0xF4, 0x08, 0xC3, 0x76, 0x80),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xDD, 0x09, 0xA6, 0xED, 0xEE, 0xC4, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xD9, 0xBE, 0x4B, 0xA5, 0xB7, 0x2B, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x20, 0x12, 0xCA, 0x0A, 0x38, 0x24, 0xAB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x72, 0x71, 0x90, 0x7A, 0x2E, 0xB7, 0x23),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0xA1, 0x93, 0x10, 0x2A, 0x51, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x10, 0x11, 0x12, 0xBC, 0xB0, 0xB6, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x58, 0xD7, 0x0A, 0x84, 0x05, 0xA3, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x8E, 0x95, 0x61, 0xD3, 0x0B, 0xDF, 0x36),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x92, 0x12, 0x0F, 0x5E, 0x87, 0x70, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xE9, 0x9B, 0xEB, 0x3A, 0xFB, 0xCF, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0x92, 0xB9, 0xF7, 0x45, 0xD3, 0x06, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x28, 0x65, 0xE1, 0xC5, 0x6C, 0x57, 0x18),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x0E, 0x77, 0x01, 0x81, 0x9E, 0x38, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xF0, 0xD5, 0xA5, 0x91, 0x2B, 0xDF, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xEE, 0xB6, 0x25, 0xD6, 0x98, 0xDE, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0x55, 0x63, 0x39, 0xEB, 0xB5, 0x47),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD6, 0xB8, 0xE3, 0x13, 0xED, 0x7F, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xE8, 0xAE, 0x36, 0xB8, 0xCD, 0x19, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x82, 0x83, 0x7A, 0x7B, 0x46, 0x56, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x60, 0x46, 0x15, 0x5A, 0xAC, 0x99, 0x30),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x61, 0x50, 0xC6, 0xFF, 0x10, 0x7D, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x51, 0xDF, 0xA9, 0x7D, 0x78, 0x26, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x15, 0x9A, 0xF7, 0x01, 0xC1, 0xBB, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x0F, 0xE6, 0x2A, 0xBD, 0x4A, 0x9E, 0x87),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF8, 0xD1, 0x77, 0xD2, 0x49, 0xB3, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x86, 0xFB, 0x9E, 0x1F, 0x5A, 0x60, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xC4, 0x8D, 0xCD, 0x86, 0x61, 0x2F, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xF6, 0xB9, 0xAC, 0x37, 0x9D, 0xE9, 0x28),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x77, 0xAA, 0x97, 0x9C, 0x0B, 0x04, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xA6, 0x60, 0x81, 0xCE, 0x25, 0x13, 0x3E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x00, 0xF3, 0xBB, 0x82, 0x99, 0x95, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0xCE, 0x90, 0x71, 0x38, 0x2F, 0x10),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x1A, 0xC0, 0x84, 0x27, 0xD6, 0x9D, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x37, 0x52, 0x16, 0x13, 0x0E, 0xCE, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBF, 0x5A, 0xDB, 0xDB, 0x6E, 0x1E, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB7, 0x5E, 0xF9, 0x86, 0xDD, 0x8A, 0x5C),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xAB, 0x5C, 0x8D, 0x1D, 0xF2, 0x2D, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC5, 0xF8, 0xF7, 0x1D, 0x96, 0x0B, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x4C, 0xA7, 0x45, 0x20, 0x6A, 0x1E, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x5D, 0xEF, 0xDE, 0xEE, 0x39, 0x44, 0x19),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x2F, 0x6D, 0x52, 0xC9, 0x58, 0x60, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xC9, 0x62, 0xCB, 0x38, 0x3C, 0x55, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xA5, 0x09, 0x10, 0x88, 0xDB, 0xE3, 0xBD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xE0, 0x3C, 0xCE, 0x06, 0x0B, 0x4B, 0x5D),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x1D, 0xB4, 0x10, 0x76, 0x8F, 0xBA, 0x09),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x70, 0x5A, 0x07, 0xF5, 0x1A, 0x74, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xE9, 0x94, 0xA8, 0xC0, 0xD5, 0x4A, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x6D, 0xD4, 0xE8, 0x9B, 0xE9, 0x6D, 0x0E),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x00, 0x32, 0x41, 0x57, 0x84, 0x89, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC7, 0x14, 0xEC, 0xE9, 0x27, 0xFF, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x67, 0x9E, 0xFB, 0xB6, 0xB8, 0x96, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x4A, 0xE3, 0x97, 0x4B, 0x58, 0xDE, 0x30),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x1E, 0x5C, 0xF5, 0x7F, 0xD5, 0xD4, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x08, 0x7A, 0xF1, 0xBD, 0x89, 0xC7, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xF9, 0x11, 0x1B, 0xF5, 0x3C, 0x6D, 0x8C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x50, 0xE5, 0x69, 0x1D, 0x59, 0xFC, 0x0C),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x2F, 0xF8, 0x3F, 0xEC, 0x55, 0x99, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xA7, 0x29, 0x90, 0x43, 0x81, 0x31, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x18, 0x44, 0x50, 0x5D, 0x76, 0xCB, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xC5, 0x5B, 0x9A, 0x03, 0xE6, 0x17, 0x39),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x89, 0xFC, 0x55, 0x94, 0x91, 0x6A, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x46, 0x35, 0xF2, 0x3A, 0x42, 0x08, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xD2, 0x76, 0x49, 0x42, 0x87, 0xD3, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xEA, 0xA0, 0x52, 0xF1, 0x6A, 0x30, 0x57),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xB2, 0x57, 0xA3, 0x8A, 0x4D, 0x1B, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xA3, 0x99, 0x94, 0xB5, 0x3D, 0x64, 0x09),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC3, 0xD7, 0x53, 0xF6, 0x49, 0x1C, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x23, 0x41, 0x4D, 0xFB, 0x7A, 0x5C, 0x53),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xB8, 0x15, 0x65, 0x5C, 0x85, 0x94, 0xD7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x37, 0xC7, 0xF8, 0x7E, 0xAE, 0x6C, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xD8, 0x11, 0x54, 0x98, 0x44, 0xE3, 0xF1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x4D, 0xA6, 0x4B, 0x28, 0xF2, 0x57, 0x9E),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD0, 0xEB, 0x1E, 0xAA, 0x30, 0xD3, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x9B, 0x4D, 0xA7, 0x73, 0x6E, 0xB6, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x47, 0xF6, 0xED, 0x37, 0xEF, 0x71, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xB5, 0x49, 0x61, 0x5E, 0x45, 0xF6, 0x4A),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x0E, 0xB3, 0x84, 0x3A, 0x63, 0x72, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x53, 0x5C, 0xA7, 0xC6, 0x2E, 0xAB, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x0F, 0x8F, 0x87, 0x50, 0x28, 0xB4, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x98, 0x4A, 0x98, 0x31, 0x86, 0xCA, 0x51),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC9, 0xE2, 0xFD, 0x5D, 0x1F, 0xE8, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x90, 0x91, 0xC4, 0x84, 0xF0, 0xBA, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5A, 0xB3, 0x4E, 0xFB, 0xE0, 0x57, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x0B, 0x90, 0xA6, 0xFD, 0x9D, 0x8E, 0x02),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x41, 0x8F, 0x31, 0xFA, 0x5A, 0xF6, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xE9, 0xE3, 0xF6, 0xE0, 0x4A, 0xE7, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x4E, 0xCD, 0xA2, 0x22, 0x14, 0xD4, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xED, 0x21, 0xB7, 0x0F, 0x53, 0x10, 0x17),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x06, 0x24, 0x2C, 0x4E, 0xD1, 0x1E, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x3F, 0xC1, 0x9F, 0xAB, 0xF0, 0x37, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x5E, 0x12, 0xCE, 0x83, 0x1B, 0x2A, 0x18),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x65, 0xCF, 0xE8, 0x5C, 0xA5, 0xA2, 0x70),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x86, 0x76, 0x3A, 0x94, 0xF6, 0x1D, 0xC1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xDA, 0xC9, 0xA6, 0x29, 0x93, 0x15, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x61, 0x6A, 0x7D, 0xC7, 0xA9, 0xF3, 0x76),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x03, 0x71, 0xA2, 0x15, 0xCE, 0x50, 0x72),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD0, 0xA8, 0x1E, 0x91, 0xC4, 0x4F, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x4B, 0x7E, 0xD7, 0x71, 0x58, 0x7E, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x45, 0xAF, 0x2A, 0x18, 0x93, 0x95, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x8F, 0xC7, 0xFA, 0x4C, 0x7A, 0x86, 0x54),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xAF, 0x68, 0x3A, 0x23, 0xC1, 0x2E, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x50, 0x11, 0x67, 0x39, 0xB9, 0xAF, 0x48),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x86, 0xAA, 0x1E, 0x88, 0x21, 0x29, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x28, 0xA4, 0x9D, 0x89, 0xA9, 0x9A, 0x10),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBA, 0x04, 0x67, 0xB7, 0x01, 0x40, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xE9, 0x09, 0xA3, 0xCA, 0xA6, 0x37, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x97, 0xA8, 0xB6, 0x3C, 0xEE, 0x90, 0x3D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xED, 0xC4, 0xF7, 0xC3, 0x95, 0xEC, 0x85),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x84, 0xBD, 0xEB, 0xD5, 0x64, 0xBB, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x9B, 0xE2, 0x28, 0x50, 0xC2, 0x72, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xF2, 0x74, 0xD1, 0x26, 0xBF, 0x32, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xCB, 0xAF, 0x72, 0xDB, 0x6D, 0x30, 0x98),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x50, 0x85, 0xF4, 0x2B, 0x48, 0xC1, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x28, 0xBB, 0x11, 0xBA, 0x5B, 0x22, 0x6C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA1, 0xE5, 0x5C, 0xC9, 0x1D, 0x44, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xE8, 0xE6, 0x6F, 0xBB, 0xC1, 0x81, 0x7F),\n};\nstatic const mbedtls_ecp_point brainpoolP256r1_T[16] = {\n    ECP_POINT_INIT_XY_Z1(brainpoolP256r1_T_0_X, brainpoolP256r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_1_X, brainpoolP256r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_2_X, brainpoolP256r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_3_X, brainpoolP256r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_4_X, brainpoolP256r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_5_X, brainpoolP256r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_6_X, brainpoolP256r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_7_X, brainpoolP256r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_8_X, brainpoolP256r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_9_X, brainpoolP256r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_10_X, brainpoolP256r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_11_X, brainpoolP256r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_12_X, brainpoolP256r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_13_X, brainpoolP256r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_14_X, brainpoolP256r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_15_X, brainpoolP256r1_T_15_Y),\n};\n#else\n#define brainpoolP256r1_T NULL\n#endif\n\n#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */\n\n/*\n * Domain parameters for brainpoolP384r1 (RFC 5639 3.6)\n */\n#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)\nstatic const mbedtls_mpi_uint brainpoolP384r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_a[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C),\n};\n\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xD8, 0x8A, 0x54, 0x41, 0xD6, 0x6B, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x3B, 0xF1, 0x22, 0xFD, 0x2D, 0x4B, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x55, 0xE3, 0x33, 0xF0, 0x73, 0x52, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x3F, 0x30, 0x26, 0xCA, 0x7F, 0x52, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x6E, 0x17, 0x9B, 0xD5, 0x2A, 0x4A, 0x31),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xDA, 0x6B, 0xE5, 0x03, 0x07, 0x1D, 0x2E),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x7A, 0xAF, 0x98, 0xE3, 0xA4, 0xF6, 0x19),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x7D, 0xFE, 0x51, 0x40, 0x3B, 0x47, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x88, 0xEC, 0xC4, 0xE2, 0x8F, 0xCB, 0xA4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xE2, 0x88, 0x2D, 0x4E, 0x50, 0xEB, 0x9A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x54, 0x94, 0x5E, 0xF4, 0x7F, 0x3A, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x07, 0x1C, 0xE1, 0xBD, 0x0F, 0xF8, 0x63),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x92, 0x28, 0x2E, 0x32, 0x04, 0xB1, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x82, 0x44, 0x43, 0x76, 0x0D, 0x55, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xE3, 0xFF, 0x89, 0x46, 0xDE, 0x4E, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x22, 0xBB, 0x67, 0x1A, 0x81, 0xEE, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x54, 0xE2, 0x7A, 0xAE, 0xDA, 0x2C, 0xD0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x9A, 0x90, 0xAA, 0x6E, 0x8B, 0xCC, 0x5F),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x40, 0xAC, 0xED, 0x7D, 0x37, 0x87, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xF8, 0xB1, 0x80, 0x4C, 0x8C, 0x04, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x98, 0x2C, 0xAD, 0x30, 0x69, 0x35, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x2E, 0x00, 0x2F, 0x44, 0x8C, 0xF0, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x58, 0x07, 0xD7, 0xCD, 0x60, 0xA1, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFB, 0x7B, 0x03, 0x05, 0x5E, 0x79, 0x73),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x17, 0xCE, 0x38, 0x4B, 0x5E, 0x5B, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x0E, 0x0A, 0x61, 0x9D, 0x7C, 0x62, 0x08),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF0, 0x98, 0x71, 0x7F, 0x17, 0x26, 0xD7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xD3, 0xFA, 0x3C, 0xF0, 0x70, 0x07, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x47, 0x5C, 0x09, 0x43, 0xB7, 0x65, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xA7, 0x3E, 0xFA, 0xF3, 0xEC, 0x22),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x78, 0x22, 0x2B, 0x58, 0x71, 0xFA, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x30, 0xCE, 0x6A, 0xB3, 0xB0, 0x4F, 0x83),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x95, 0x20, 0xA9, 0x23, 0xC2, 0x65, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xCF, 0x03, 0x5B, 0x8A, 0x80, 0x44, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xF8, 0x91, 0xF7, 0xD5, 0xED, 0xEA, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x5B, 0x16, 0x10, 0x25, 0xAC, 0x2A, 0x17),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEC, 0xDC, 0xC4, 0x7B, 0x8C, 0x6B, 0xE9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBB, 0x1C, 0xD3, 0x5A, 0xEE, 0xD9, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5D, 0x30, 0x5E, 0xF7, 0xB2, 0x41, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xCE, 0x0F, 0x1A, 0xC6, 0x41, 0x64, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x18, 0xE1, 0xE3, 0x82, 0x15, 0x66, 0x4B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xE2, 0x24, 0x04, 0x72, 0x39, 0xA0, 0x7C),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x51, 0xA2, 0x58, 0x88, 0x62, 0xE1, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xD2, 0x65, 0x14, 0xE9, 0x4C, 0x82, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE1, 0xAC, 0x87, 0xAE, 0x31, 0x1A, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4F, 0x96, 0x1E, 0x85, 0x7A, 0xC3, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x86, 0xBB, 0xF0, 0xC0, 0x9D, 0x08, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x53, 0x03, 0x09, 0x80, 0x91, 0xEF, 0x68),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xD7, 0xAF, 0x6F, 0x69, 0x7B, 0x88, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x13, 0xE4, 0x30, 0xA2, 0x47, 0xB5, 0xC1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD2, 0xC0, 0xDD, 0x8A, 0x1C, 0x3C, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x8C, 0xB3, 0x4C, 0xBA, 0x8B, 0x6D, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xC7, 0xA1, 0xA8, 0x6E, 0x3C, 0x4F, 0xF1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x4A, 0x97, 0xC8, 0x03, 0x6F, 0x01, 0x82),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x18, 0x12, 0xA9, 0x39, 0xD5, 0x22, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA7, 0xC0, 0xBD, 0x9D, 0x8D, 0x78, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xD0, 0x7F, 0xDF, 0xD0, 0x30, 0xDE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x73, 0x96, 0xEC, 0xA8, 0x1D, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xD1, 0x65, 0x66, 0xDC, 0xD9, 0xCF, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xED, 0x7B, 0x37, 0xAD, 0xE2, 0xBE, 0x2D),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x79, 0x42, 0x6A, 0x07, 0x66, 0xB1, 0xBD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x53, 0x62, 0x65, 0x92, 0x09, 0x4C, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xAF, 0xC3, 0x03, 0xF6, 0xF4, 0x2D, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xCA, 0x41, 0xD9, 0xA2, 0x69, 0x9B, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xB2, 0xA6, 0x8D, 0xE1, 0xAA, 0x61, 0x76),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xBA, 0x4D, 0x12, 0xB6, 0xBE, 0xF3, 0x7E),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x92, 0x22, 0x07, 0xCE, 0xC9, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA1, 0x7C, 0x91, 0xDB, 0x32, 0xF7, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x49, 0x4B, 0x6D, 0xFB, 0xD9, 0x70, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xFB, 0x4E, 0x4C, 0x5E, 0x66, 0x81, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xB3, 0xE1, 0x00, 0xB7, 0xD9, 0xCC, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x36, 0x8B, 0xC4, 0x39, 0x20, 0xFD, 0x30),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x1F, 0x60, 0x03, 0xBB, 0xD7, 0x60, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x3C, 0x62, 0xDD, 0x71, 0x95, 0xE9, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x5B, 0x7A, 0x5F, 0x68, 0x81, 0xC5, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xB5, 0xB9, 0x98, 0x42, 0x28, 0xA5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x29, 0x8E, 0x11, 0x49, 0xB4, 0xD7, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x3E, 0xD2, 0x30, 0xA1, 0xBA, 0xCA, 0x03),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x37, 0x64, 0x44, 0x2F, 0x03, 0xE5, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x42, 0xBC, 0xFF, 0xA2, 0x1A, 0x5F, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x04, 0xAB, 0x04, 0xE0, 0x24, 0xAD, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x45, 0x17, 0x67, 0x1F, 0x3E, 0x53, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x0F, 0xB3, 0x1B, 0x57, 0x54, 0xC2, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0xF8, 0xC4, 0x1B, 0x9B, 0xFA, 0x30),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x90, 0xFD, 0xFB, 0xCA, 0x49, 0x38, 0x4E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xCF, 0xC6, 0xDD, 0xF0, 0xFF, 0x8C, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x69, 0x9D, 0xBD, 0x5F, 0x33, 0xE9, 0xB4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x19, 0x82, 0x3D, 0xAC, 0x1C, 0x40, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC7, 0x02, 0x46, 0x14, 0x77, 0x00, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x05, 0xF2, 0x77, 0x3A, 0x66, 0x5C, 0x39),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xE6, 0x17, 0xDE, 0xB2, 0xA1, 0xE5, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x71, 0xEC, 0x9D, 0xD8, 0xF5, 0xD4, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xC6, 0x42, 0x5E, 0xE7, 0x18, 0xBA, 0xD0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x21, 0x68, 0x5A, 0x26, 0xFB, 0xD7, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x00, 0x5C, 0xBA, 0x8A, 0x34, 0xEC, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x3C, 0xAF, 0x53, 0xE8, 0x65, 0x35),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xEF, 0x28, 0xDC, 0x67, 0x05, 0xC8, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x78, 0xC3, 0x85, 0x49, 0xA0, 0xBC, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x3E, 0x2D, 0xA0, 0xCF, 0xD4, 0x7A, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x93, 0xFE, 0x60, 0xB3, 0x6E, 0x99, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xAD, 0x04, 0xE7, 0x49, 0xAF, 0x5E, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x7A, 0xED, 0xA6, 0x9E, 0x18, 0x09, 0x31),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x05, 0x94, 0x44, 0xDC, 0xB8, 0x85, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xB7, 0x37, 0xC2, 0x50, 0x75, 0x15, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xC6, 0x0F, 0xB2, 0xA9, 0x91, 0x3E, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x81, 0xAD, 0x25, 0xA1, 0x26, 0x73, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xF1, 0xD1, 0x61, 0x7C, 0x76, 0x8F, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xDB, 0x4A, 0xFF, 0x14, 0xA7, 0x48, 0x0B),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x73, 0xC6, 0xC2, 0xCC, 0xF1, 0x57, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xED, 0x73, 0x27, 0x70, 0x82, 0xB6, 0x5E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xBA, 0xAC, 0x3A, 0xCF, 0xF4, 0xEA, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xD6, 0xB1, 0x8F, 0x0E, 0x08, 0x2C, 0x5E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE3, 0x8F, 0x2F, 0x0E, 0xA1, 0xF3, 0x07),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xF5, 0x7C, 0x9B, 0x29, 0x0A, 0xF6, 0x28),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xEE, 0x17, 0x47, 0x34, 0x15, 0xA3, 0xAF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBE, 0x88, 0x48, 0xE7, 0xA2, 0xBB, 0xDE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xAD, 0xDC, 0x65, 0x61, 0x37, 0x0F, 0xC1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x67, 0xAD, 0xA2, 0x3A, 0x1C, 0x91, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x07, 0x0C, 0x3A, 0x41, 0x6E, 0x13, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBD, 0x7E, 0xED, 0xAA, 0x14, 0xDD, 0x61),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xDC, 0x20, 0x01, 0x72, 0x11, 0x48, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xC4, 0x7B, 0xF8, 0x62, 0x3D, 0xF0, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xC2, 0x3D, 0x2E, 0x52, 0xA3, 0x4A, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE2, 0x53, 0x46, 0x5E, 0x21, 0xF8, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xC7, 0x8F, 0xA9, 0x26, 0x42, 0x32, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xA6, 0xA0, 0x8D, 0x4B, 0x9A, 0x19, 0x03),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xAB, 0x6D, 0x1E, 0xFB, 0xEE, 0x60, 0x0C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x56, 0x3C, 0xC5, 0x5D, 0x10, 0x79, 0x1C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xBC, 0x41, 0x9F, 0x71, 0xEF, 0x02, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x36, 0xC4, 0xD0, 0x88, 0x9B, 0x32, 0xFC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xD4, 0x5D, 0x17, 0x39, 0xE6, 0x22, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x26, 0x01, 0xCE, 0xBE, 0x4A, 0x9C, 0x27),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x6D, 0x11, 0xCA, 0x6C, 0x5A, 0x93, 0x0C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x96, 0x26, 0xAF, 0x2F, 0xE4, 0x30, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC1, 0x4C, 0xC6, 0x30, 0x1F, 0x5C, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB3, 0xE8, 0xFC, 0x35, 0xEB, 0x63, 0x6C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x1D, 0xCA, 0xFC, 0x50, 0x36, 0x4B, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0E, 0x23, 0x5B, 0xAF, 0xEB, 0x2D, 0x31),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x88, 0xB6, 0xD7, 0x74, 0x4A, 0x23, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x66, 0xE2, 0xBB, 0x29, 0xA6, 0x4F, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x6F, 0x7E, 0x68, 0x6E, 0xA0, 0x14, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x73, 0xD4, 0xE8, 0xAB, 0x5B, 0xF6, 0x0D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xE0, 0x3C, 0x24, 0x00, 0x95, 0xE9, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x0D, 0x4F, 0x81, 0xD0, 0xF2, 0x3F, 0x00),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x1D, 0xCD, 0x78, 0x39, 0xC4, 0x6B, 0xD9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x45, 0xC7, 0xB8, 0x2F, 0xAA, 0x5D, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x8C, 0x6E, 0xA3, 0x24, 0xB2, 0xDB, 0x4B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x2D, 0xD9, 0xF1, 0xC7, 0x9B, 0x8A, 0xAF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xE1, 0x2C, 0xB9, 0x40, 0x37, 0x91, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2C, 0xB5, 0x23, 0x03, 0x2B, 0xAF, 0x2F),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x9D, 0x5A, 0x20, 0x10, 0xA9, 0x84, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x30, 0x89, 0x20, 0x13, 0xE9, 0xB2, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x52, 0xEB, 0x03, 0x18, 0x1F, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x9E, 0x1C, 0x35, 0x87, 0x92, 0x69, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xC9, 0x88, 0xAF, 0xC6, 0x6C, 0x83, 0x72),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD5, 0x7A, 0x54, 0x34, 0x99, 0xB6, 0x6F),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xAD, 0x45, 0x9B, 0x4B, 0x41, 0x4D, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x5D, 0xAB, 0x7F, 0x35, 0x34, 0xE9, 0x29),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBE, 0x78, 0x34, 0x44, 0xF3, 0x4A, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xDE, 0xE3, 0xC4, 0xEE, 0x0B, 0xF9, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x86, 0x16, 0x48, 0x32, 0xB8, 0x74, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEE, 0x7C, 0xBA, 0xBD, 0x81, 0xE3, 0x55),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x6A, 0xFA, 0x84, 0xDA, 0xB8, 0xD5, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x9F, 0x8A, 0xD5, 0x1B, 0x2E, 0x1A, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0C, 0x61, 0xE2, 0xFF, 0x5B, 0xE6, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x62, 0xC1, 0x87, 0x53, 0x1B, 0x92, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x90, 0x00, 0xD1, 0x6A, 0x0C, 0x0E, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x2E, 0xB5, 0x3B, 0x44, 0xB5, 0xA0, 0x78),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5D, 0x02, 0x58, 0xB5, 0xBE, 0x45, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xEF, 0x8E, 0x90, 0x4D, 0x2A, 0x32, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x75, 0x5C, 0x0A, 0x33, 0x8F, 0x36),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x6C, 0x95, 0xD4, 0x1F, 0xF3, 0xEB, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xE4, 0x4C, 0x91, 0x20, 0xF3, 0x25, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x95, 0xEB, 0x29, 0x6F, 0x20, 0x34, 0x81),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x15, 0xE5, 0x13, 0x7E, 0x64, 0x8B, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xBC, 0x0D, 0x18, 0x7E, 0x37, 0x9E, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x82, 0x20, 0xF7, 0x2D, 0x7A, 0x77, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x29, 0xA2, 0xDB, 0x7A, 0xE6, 0x6F, 0xA5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xC6, 0x50, 0x5C, 0xBC, 0xE6, 0x4F, 0xBD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x9F, 0xD5, 0xE8, 0xC5, 0x3D, 0xB7, 0x30),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_16_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x03, 0x55, 0x10, 0xDB, 0xA6, 0x8B, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x17, 0xAE, 0x78, 0xC9, 0x1D, 0x43, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x35, 0x49, 0xD4, 0x47, 0x84, 0x8D, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x95, 0x2F, 0xEA, 0xBC, 0xB4, 0x18, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x48, 0xAE, 0x89, 0xF5, 0x65, 0x3D, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xF2, 0x2B, 0x20, 0xD1, 0x75, 0x50, 0x63),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_16_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xE6, 0x5C, 0x2C, 0xE0, 0x7D, 0xDF, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x07, 0x3E, 0xCE, 0x9F, 0x18, 0xB6, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xF8, 0xF0, 0xD5, 0xFA, 0x42, 0x1D, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x6C, 0x1D, 0x03, 0xC9, 0x0E, 0x2B, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x52, 0xA5, 0xB4, 0x63, 0xE1, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0xD9, 0xC4, 0xFD, 0x16, 0x60, 0x54),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_17_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x7D, 0xDE, 0xDF, 0x4B, 0x4A, 0xB0, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x4E, 0x8C, 0x94, 0xC1, 0xE2, 0x85, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xF0, 0xEA, 0xB5, 0x9B, 0x70, 0xEF, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xC2, 0x39, 0x5D, 0xF3, 0x2C, 0xD9, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x1C, 0x2E, 0xCC, 0x2F, 0x54, 0x87, 0x80),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x72, 0xC7, 0xB5, 0x50, 0xA3, 0x84, 0x77),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_17_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xD1, 0xAF, 0xA9, 0xB4, 0x8B, 0x5D, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xF6, 0x52, 0x8A, 0xC3, 0x56, 0xA5, 0x5E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x52, 0xFF, 0xEA, 0x05, 0x42, 0x77, 0x83),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x08, 0x90, 0x72, 0x86, 0xC4, 0xC3, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x15, 0xF8, 0xF1, 0x16, 0x67, 0xC6, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x87, 0xAC, 0x8F, 0x71, 0xEC, 0x83, 0x81),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_18_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xE1, 0xE6, 0x2D, 0x0E, 0x11, 0xA1, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xE2, 0xA8, 0x32, 0xE6, 0xE3, 0x83, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x56, 0xE5, 0xCD, 0xB7, 0x2B, 0x67, 0x6F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xED, 0xC9, 0x65, 0x6D, 0x87, 0xE1, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xFD, 0x9A, 0x53, 0x0E, 0xFA, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x4C, 0x4A, 0xE2, 0x23, 0x84, 0xFA, 0x01),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_18_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFE, 0x49, 0x81, 0xD1, 0x3E, 0xF4, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x72, 0xE0, 0xEF, 0x0D, 0xB8, 0x3E, 0x6F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x00, 0x0F, 0x5F, 0xCE, 0x60, 0x72, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCC, 0xD8, 0x03, 0x07, 0x6E, 0x5A, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x3A, 0x35, 0x50, 0x4E, 0x1F, 0xCA, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xEA, 0x88, 0x55, 0xBD, 0x6E, 0x05, 0x7F),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_19_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x6D, 0xF1, 0x97, 0xA6, 0x69, 0x39, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x41, 0x99, 0xFF, 0x3B, 0xA1, 0x26, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x2F, 0x95, 0x80, 0x12, 0x4A, 0x1B, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xBF, 0x51, 0xAA, 0xAE, 0x2D, 0xDA, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1C, 0xB3, 0x52, 0x36, 0x49, 0xD4, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC1, 0x1F, 0x3A, 0xD3, 0x3E, 0x5C, 0x1A),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_19_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x51, 0xF7, 0x2B, 0xC8, 0xA9, 0xA7, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x4E, 0x7F, 0x98, 0x41, 0x66, 0xB0, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x1D, 0xC0, 0x42, 0xCD, 0xF8, 0xC3, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x41, 0x91, 0x7D, 0xCC, 0x8B, 0xCC, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xAE, 0x76, 0xED, 0x56, 0x18, 0xC5, 0xAB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x6A, 0x06, 0xA3, 0x7F, 0x65, 0x10, 0x1F),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_20_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xEC, 0x3C, 0x05, 0x05, 0xCA, 0xF6, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0xCD, 0x02, 0x51, 0x12, 0x16, 0x3C, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xEB, 0xB3, 0x43, 0x7B, 0xDD, 0xB2, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x90, 0x41, 0xDB, 0xE4, 0xF5, 0x91),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0E, 0x18, 0x2A, 0x5A, 0x83, 0x7C, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x37, 0xA1, 0x0D, 0xF1, 0x2F, 0x63, 0x79),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_20_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC0, 0xFA, 0x6F, 0x1F, 0x67, 0xCF, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x34, 0x45, 0xBB, 0xF4, 0xF9, 0x9B, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x69, 0xFE, 0x67, 0x1D, 0x64, 0x8F, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x39, 0xBF, 0xD8, 0xB3, 0xC7, 0xAD, 0x8A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x93, 0xFF, 0xF3, 0x28, 0xFA, 0x39, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF9, 0xC3, 0x85, 0x26, 0x7A, 0x88, 0x89),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_21_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD5, 0x79, 0xD8, 0x11, 0xDE, 0xEB, 0x4E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x46, 0xA4, 0x6A, 0xDA, 0x74, 0x34, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBD, 0xD3, 0xF5, 0x14, 0xEE, 0xFE, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4C, 0xA3, 0x71, 0x43, 0x65, 0xF8, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x6C, 0x35, 0xFA, 0x90, 0x25, 0xD8, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x34, 0x84, 0x96, 0xA1, 0x43, 0x03, 0x4D),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_21_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x3B, 0x3B, 0x2F, 0xCA, 0x59, 0xF2, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x48, 0x24, 0x74, 0xD8, 0x72, 0x90, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x42, 0x74, 0x8C, 0x6F, 0x52, 0x19, 0x3D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9E, 0x41, 0x63, 0x68, 0x78, 0x4C, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x94, 0xB6, 0x6B, 0x38, 0x52, 0xA8, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x30, 0x25, 0x93, 0xA1, 0x6F, 0x6E, 0x68),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_22_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2F, 0x4B, 0x64, 0x79, 0x50, 0xFF, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x36, 0xED, 0x57, 0x39, 0x3B, 0xE7, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x85, 0xEA, 0x35, 0xD6, 0xC0, 0xA0, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x89, 0x3A, 0xCC, 0x22, 0x1C, 0x46, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x7A, 0xB0, 0xA1, 0x1B, 0x69, 0x62, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xB8, 0x8A, 0x6C, 0x18, 0x85, 0x0D, 0x88),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_22_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB6, 0x50, 0xE9, 0x4E, 0x7F, 0xE8, 0x07),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5B, 0x5C, 0xD1, 0x4B, 0x11, 0x9A, 0xD8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x25, 0x56, 0x74, 0x51, 0x9C, 0xEC, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x7F, 0xB6, 0x8A, 0xCB, 0x3A, 0x10, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x33, 0x07, 0x01, 0xE9, 0x49, 0x59, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xA5, 0x2E, 0xF2, 0xBA, 0x32, 0x63, 0x44),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_23_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x06, 0x0B, 0xA5, 0x44, 0x27, 0x7F, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x74, 0xAC, 0x0F, 0xCC, 0x4F, 0x13, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB1, 0xBF, 0x97, 0x49, 0xA5, 0x1C, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x64, 0x68, 0x7B, 0x0F, 0xCC, 0x77, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x39, 0xF9, 0x4E, 0x84, 0x9C, 0xF6, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xCF, 0x6D, 0xE2, 0xA1, 0x2D, 0xF9, 0x2B),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_23_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC4, 0x90, 0x57, 0x31, 0x01, 0x05, 0x5E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x1E, 0xBB, 0xBF, 0x98, 0xA4, 0x7C, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xE3, 0xA0, 0xB2, 0xCD, 0x39, 0x9A, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x34, 0x60, 0x7A, 0x89, 0x98, 0xB5, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x20, 0x3D, 0x3A, 0x04, 0x8F, 0x5A, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x26, 0xB6, 0x49, 0x09, 0x9C, 0x0F, 0x59),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_24_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x66, 0xD2, 0x38, 0x2A, 0x62, 0x81, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xC8, 0x20, 0x5E, 0x28, 0xA3, 0x81, 0xA7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x31, 0xA4, 0xF1, 0xEA, 0x7D, 0x87, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x2C, 0x99, 0x09, 0x6F, 0x63, 0xEB, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x76, 0xDA, 0x1A, 0x06, 0xBE, 0xDE, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x09, 0x2E, 0x75, 0x39, 0x30, 0x2D, 0x42),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_24_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x9B, 0xC1, 0x5A, 0x17, 0xC3, 0x8C, 0x31),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x8D, 0x94, 0x4D, 0x3D, 0xAB, 0x60, 0xD4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFD, 0x1E, 0x0F, 0x43, 0xAE, 0x9D, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF2, 0xF3, 0x20, 0x1B, 0xAA, 0xB7, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x5B, 0xA4, 0xF4, 0x90, 0x3B, 0xE3, 0x71),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x78, 0x72, 0xBD, 0x65, 0x09, 0x0B, 0x01),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_25_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x37, 0x2A, 0x6C, 0x16, 0x4F, 0x64, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xCE, 0xA3, 0x90, 0xB4, 0x9A, 0xBC, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x55, 0x63, 0x1D, 0x3A, 0x6E, 0x18),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xB4, 0xAA, 0x99, 0x22, 0x45, 0x89, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x7C, 0x8C, 0xA6, 0x3D, 0xA7, 0x3E, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x06, 0x42, 0xDC, 0xA6, 0xE3, 0xC6, 0x12),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_25_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8C, 0x3D, 0x5D, 0x47, 0x31, 0x7C, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x85, 0xEE, 0x46, 0x7E, 0x13, 0x04, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x3C, 0x8B, 0x43, 0x2E, 0x74, 0xF5, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x88, 0x8E, 0x07, 0x29, 0x08, 0x03, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x9B, 0x89, 0xEB, 0x08, 0xE8, 0x43, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x07, 0x67, 0xFD, 0xD9, 0x73, 0x6F, 0x18),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_26_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xEB, 0x21, 0x8D, 0x98, 0x43, 0x74, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xCC, 0x14, 0xD8, 0x08, 0xBB, 0xA6, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x98, 0xF2, 0x6A, 0x18, 0xC3, 0xDD, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x38, 0x91, 0xA0, 0x03, 0xF2, 0x04, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xAF, 0xE8, 0xFD, 0xFB, 0x13, 0x70, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x93, 0x87, 0x98, 0x4A, 0xE0, 0x00, 0x12),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_26_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x2E, 0x69, 0x9C, 0xA2, 0x2D, 0x03, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFE, 0xF3, 0xB9, 0xC1, 0x85, 0x2A, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xFD, 0x86, 0xB1, 0xCD, 0xBF, 0x41, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xD8, 0x9A, 0x21, 0xF3, 0xFE, 0xCB, 0xF1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x78, 0x04, 0x60, 0xB7, 0xA9, 0xA2, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1E, 0x66, 0x2A, 0x54, 0x51, 0xBD, 0x8B),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_27_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x16, 0x36, 0xEF, 0x61, 0x2D, 0xEE, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x5F, 0x88, 0xA0, 0x13, 0x12, 0xF7, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xC6, 0xAD, 0x4A, 0x4A, 0x07, 0x01, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x74, 0xB1, 0x4F, 0xEB, 0xBD, 0xD5, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF9, 0x71, 0xA2, 0x06, 0x4F, 0xD7, 0xBC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x8B, 0x4D, 0x48, 0xE0, 0x98, 0xFB, 0x6A),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_27_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xBA, 0x10, 0xA3, 0x0D, 0x52, 0xAC, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xD0, 0xE0, 0x36, 0xE6, 0x07, 0x3A, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x80, 0xF0, 0xAA, 0x49, 0x22, 0x4B, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC7, 0xAB, 0x1C, 0x89, 0xCD, 0x24, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x2A, 0xFC, 0xB3, 0x6D, 0x45, 0x96, 0x49),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xE4, 0xDB, 0x52, 0x3F, 0xC4, 0xB4, 0x19),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_28_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xCC, 0xC8, 0x7F, 0xBB, 0x6B, 0x87, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x21, 0x3C, 0x69, 0x7D, 0x38, 0x57, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x4C, 0x18, 0x3C, 0x53, 0xA5, 0x48, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC3, 0x64, 0x45, 0xDB, 0xC4, 0x6D, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCC, 0xD1, 0xBB, 0x17, 0xB8, 0x34, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x69, 0x71, 0xFA, 0xA0, 0x28, 0x4A, 0x3D),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_28_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xE8, 0x9E, 0x39, 0xEA, 0x8D, 0x38, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x9C, 0xBB, 0xCD, 0x80, 0x1A, 0xEE, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA0, 0x45, 0xBF, 0xD9, 0x22, 0x11, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7C, 0x5C, 0xD9, 0xC0, 0x9F, 0x69, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x8A, 0xA6, 0x79, 0x4E, 0x35, 0xB9, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8B, 0x9A, 0x3E, 0xA1, 0xB8, 0x28, 0x10),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_29_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x2F, 0xEF, 0xBB, 0xA9, 0x72, 0x7F, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x34, 0xB7, 0x12, 0xB9, 0xE7, 0xC3, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x1D, 0xD9, 0x42, 0x77, 0x0C, 0x71, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x01, 0x59, 0xA7, 0x56, 0x03, 0x91, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x91, 0x99, 0x33, 0x30, 0x3E, 0xEF, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xC9, 0x5A, 0x9A, 0x54, 0x66, 0xF1, 0x70),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_29_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x2C, 0xB7, 0x6E, 0x71, 0x7D, 0x35, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x0D, 0xEF, 0xD1, 0x2D, 0x99, 0x63, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x31, 0xAF, 0x2D, 0xC9, 0xC6, 0xC2, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xC0, 0xDF, 0x80, 0x54, 0xC4, 0xAC, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x6B, 0xA0, 0x84, 0x96, 0xF7, 0x31, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xE2, 0x7C, 0x7A, 0x41, 0x45, 0x75, 0x6A),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_30_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xEE, 0x58, 0x31, 0xE8, 0x68, 0xD6, 0x76),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x2E, 0x48, 0xB7, 0x09, 0x9F, 0xD4, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA9, 0x5C, 0xE7, 0x64, 0x43, 0x5D, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x9F, 0x50, 0xAB, 0x68, 0xFF, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x88, 0x2D, 0xBA, 0x12, 0xBF, 0x8D, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xDF, 0x6F, 0xB3, 0x75, 0xA4, 0x55, 0x73),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_30_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x17, 0x92, 0x39, 0xB7, 0x13, 0x37, 0x6F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x43, 0x71, 0xA7, 0xCA, 0x17, 0x1B, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xB9, 0xB0, 0x78, 0xEF, 0xA0, 0xDA, 0x83),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0xF2, 0x0F, 0x85, 0xA2, 0xB6, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x65, 0x2E, 0x6E, 0x45, 0xB9, 0x4C, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x6A, 0x8C, 0x2B, 0x77, 0x96, 0x36, 0x22),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_31_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x7A, 0x13, 0x4A, 0x97, 0x63, 0x02, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x1E, 0x06, 0x03, 0x8F, 0xB9, 0xEE, 0x64),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0xEE, 0x8B, 0x89, 0xA9, 0x70, 0xDB, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x81, 0xC9, 0x70, 0x8D, 0x62, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xDA, 0x46, 0xF8, 0xF9, 0x3A, 0xBE, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x9C, 0x7A, 0x97, 0x62, 0xEB, 0xFA, 0x0F),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_31_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x03, 0x3D, 0x3C, 0x46, 0x27, 0x9E, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x08, 0x1C, 0xD5, 0x25, 0xAF, 0xE9, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x69, 0xDC, 0x59, 0xF4, 0x8A, 0x7C, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x9A, 0x7A, 0x99, 0x21, 0x0C, 0x4E, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xCE, 0x85, 0x5F, 0xAC, 0xAA, 0x82, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x57, 0x69, 0x90, 0x76, 0xF3, 0x53, 0x3F),\n};\nstatic const mbedtls_ecp_point brainpoolP384r1_T[32] = {\n    ECP_POINT_INIT_XY_Z1(brainpoolP384r1_T_0_X, brainpoolP384r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_1_X, brainpoolP384r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_2_X, brainpoolP384r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_3_X, brainpoolP384r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_4_X, brainpoolP384r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_5_X, brainpoolP384r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_6_X, brainpoolP384r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_7_X, brainpoolP384r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_8_X, brainpoolP384r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_9_X, brainpoolP384r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_10_X, brainpoolP384r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_11_X, brainpoolP384r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_12_X, brainpoolP384r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_13_X, brainpoolP384r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_14_X, brainpoolP384r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_15_X, brainpoolP384r1_T_15_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_16_X, brainpoolP384r1_T_16_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_17_X, brainpoolP384r1_T_17_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_18_X, brainpoolP384r1_T_18_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_19_X, brainpoolP384r1_T_19_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_20_X, brainpoolP384r1_T_20_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_21_X, brainpoolP384r1_T_21_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_22_X, brainpoolP384r1_T_22_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_23_X, brainpoolP384r1_T_23_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_24_X, brainpoolP384r1_T_24_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_25_X, brainpoolP384r1_T_25_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_26_X, brainpoolP384r1_T_26_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_27_X, brainpoolP384r1_T_27_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_28_X, brainpoolP384r1_T_28_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_29_X, brainpoolP384r1_T_29_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_30_X, brainpoolP384r1_T_30_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_31_X, brainpoolP384r1_T_31_Y),\n};\n#else\n#define brainpoolP384r1_T NULL\n#endif\n\n#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */\n\n/*\n * Domain parameters for brainpoolP512r1 (RFC 5639 3.7)\n */\n#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)\nstatic const mbedtls_mpi_uint brainpoolP512r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_a[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA),\n};\n\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xE9, 0x6B, 0x8C, 0x6F, 0x9D, 0x88, 0x43),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x4F, 0x86, 0x96, 0xA7, 0x56, 0xD1, 0x37),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xAB, 0xFA, 0xEE, 0xA7, 0xF5, 0x0E, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x40, 0xEF, 0x9E, 0x6D, 0xD6, 0x32, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xED, 0x56, 0x14, 0x57, 0x1A, 0x8D, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xED, 0x4D, 0x3A, 0xFA, 0x71, 0x75, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xC5, 0x76, 0x1C, 0x14, 0xBE, 0xB5, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x5A, 0xCB, 0xE7, 0x36, 0x1D, 0x52, 0x1C),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8D, 0x7A, 0xEB, 0xA3, 0x8B, 0xD5, 0xB0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xA3, 0x41, 0xF8, 0xAC, 0x9E, 0xAB, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xE3, 0x65, 0x0D, 0x1C, 0xFE, 0x09, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xCA, 0x13, 0x3F, 0xC5, 0xF9, 0x7E, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x5D, 0x63, 0x28, 0xA6, 0x89, 0xD3, 0x91),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x95, 0x3F, 0x7A, 0x82, 0xD4, 0x77, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xBB, 0x92, 0x32, 0x00, 0xF4, 0x66, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x58, 0x31, 0xD1, 0x17, 0x9F, 0x2A, 0x22),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x36, 0xA9, 0xCD, 0x80, 0xA5, 0x2D, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x44, 0xAB, 0xCE, 0x71, 0xFF, 0x0C, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x24, 0x58, 0x35, 0x5A, 0x21, 0x32, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xA6, 0x28, 0xF8, 0x7A, 0x97, 0xAE, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xE7, 0x08, 0xFA, 0x47, 0xC9, 0x55, 0x09),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xAC, 0x2E, 0x84, 0xA4, 0xF5, 0x52, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x58, 0x05, 0x9D, 0xA7, 0xC8, 0x71, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x92, 0xB4, 0x92, 0xC1, 0x92, 0xEC, 0x6B),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x48, 0x2D, 0x79, 0x5E, 0x58, 0xE5, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x85, 0x26, 0xEC, 0xE9, 0x6E, 0xD4, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x68, 0x26, 0x87, 0x38, 0xA2, 0xD2, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x17, 0x60, 0xCE, 0x75, 0xF8, 0xA5, 0x6F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x51, 0xDB, 0xA9, 0xAE, 0x87, 0xF1, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x49, 0x92, 0x3B, 0x19, 0x96, 0xF5, 0xB0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xD5, 0x52, 0x52, 0x8C, 0xCE, 0xFD, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x18, 0x0A, 0xE6, 0xF6, 0xAE, 0x08, 0x41),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x2B, 0xD8, 0x54, 0xCE, 0xB0, 0x57, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xB0, 0xF8, 0x9E, 0x03, 0x03, 0x3C, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x0E, 0x29, 0x29, 0x00, 0xF3, 0x70, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x33, 0x99, 0x0E, 0x00, 0x5D, 0xFE, 0x4B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2D, 0xF2, 0x59, 0x32, 0xCF, 0x03, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xC9, 0x72, 0xAE, 0x0C, 0xEF, 0xD1, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x5A, 0x27, 0xBF, 0x2F, 0x45, 0xF9, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xBE, 0xE5, 0x2C, 0xFF, 0x5B, 0x1E, 0x88),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xAC, 0xBB, 0xD8, 0x83, 0xC2, 0x46, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xDC, 0xCE, 0x15, 0xB4, 0xEF, 0xCF, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xDB, 0x5E, 0x94, 0x31, 0x0B, 0xB2, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xB9, 0xE3, 0xE3, 0x11, 0x71, 0x41, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xE3, 0x01, 0xB7, 0x7D, 0xBC, 0x65, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x07, 0x65, 0x87, 0xA7, 0xE8, 0x48, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x48, 0x8F, 0xD4, 0x30, 0x8E, 0xB4, 0x6C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE0, 0x73, 0xBE, 0x1E, 0xBF, 0x56, 0x36),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x0E, 0x5E, 0x87, 0xC5, 0xAB, 0x0E, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xF9, 0x5F, 0x80, 0x24, 0x4C, 0x2A, 0xF1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x15, 0x21, 0x54, 0x92, 0x84, 0x8D, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x8A, 0x47, 0x74, 0xDC, 0x42, 0xB1, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xF7, 0x30, 0xFD, 0xC1, 0x9B, 0x0C, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x6C, 0xCC, 0xDF, 0xC5, 0xE3, 0xA9, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x67, 0x59, 0x10, 0x5C, 0x51, 0x54, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x37, 0xFB, 0x6E, 0xB0, 0x78, 0x63, 0x8E),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEF, 0xC4, 0x39, 0x20, 0xF1, 0x46, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x62, 0xAE, 0xFF, 0x10, 0xE4, 0xE2, 0xE9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x5C, 0xF5, 0x2E, 0x22, 0x89, 0xE5, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x0C, 0x29, 0xA8, 0x62, 0xAE, 0xDB, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x9E, 0x0F, 0xCA, 0x87, 0x2A, 0x6F, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xDC, 0x9B, 0x9F, 0x65, 0xD4, 0xAD, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xC3, 0x08, 0x0F, 0xCF, 0x67, 0xE9, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5C, 0xD7, 0xFF, 0x41, 0x9C, 0xCB, 0x26),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x05, 0x12, 0xAD, 0x73, 0x63, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x99, 0x07, 0x86, 0x57, 0xE7, 0x94, 0xB1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x4B, 0xA5, 0xBF, 0x18, 0xA9, 0xEF, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x4C, 0xC4, 0x09, 0xF2, 0x2F, 0x0C, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x3A, 0x04, 0xEA, 0x89, 0x6C, 0x91, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0x3A, 0xE7, 0xA3, 0xEC, 0x24, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xA1, 0x26, 0x21, 0x04, 0xE3, 0xB9, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x71, 0x4B, 0x7B, 0xC2, 0x89, 0xCD, 0xA2),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xB9, 0xA8, 0x9D, 0xFD, 0x00, 0x3A, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x41, 0x6C, 0xBB, 0x5A, 0xCA, 0x1F, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xD7, 0xE2, 0x6C, 0x6B, 0xA7, 0x48, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x19, 0xAD, 0xA7, 0xC1, 0x7E, 0x4F, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF7, 0x19, 0x3C, 0x06, 0x74, 0x2C, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x23, 0x4F, 0x0C, 0x09, 0xB0, 0x80, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x74, 0x34, 0x08, 0x44, 0x7E, 0xA3, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xCC, 0x8D, 0x12, 0x6E, 0xE1, 0x3D, 0x0B),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x18, 0xB1, 0x71, 0x02, 0x93, 0xC2, 0xA4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x89, 0x40, 0xE2, 0x1F, 0xE7, 0x5E, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xAE, 0x89, 0x01, 0xD4, 0x0C, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xDA, 0x58, 0x70, 0x24, 0xF2, 0xE4, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xC7, 0x1D, 0xD6, 0x4A, 0x6F, 0x66, 0x4F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x1D, 0x7E, 0x4A, 0x2C, 0xCA, 0xEC, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x7F, 0xA8, 0x99, 0xE4, 0xD3, 0x4E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x1D, 0x5A, 0xDF, 0x5E, 0x58, 0x36, 0x49),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB9, 0x32, 0x69, 0x1F, 0x72, 0x2A, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x73, 0xE2, 0x03, 0x39, 0x35, 0xAA, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x5E, 0x5D, 0x48, 0xEF, 0xAE, 0x30, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x7F, 0x60, 0x19, 0xAF, 0xEC, 0x9D, 0xFC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x19, 0xE4, 0x1B, 0x56, 0x15, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xD7, 0x33, 0x59, 0x1F, 0x43, 0x59, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xCE, 0xEE, 0xCA, 0xA4, 0x7F, 0x63, 0xD4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x40, 0xC0, 0xF6, 0x19, 0x89, 0x43, 0x20),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x92, 0xEA, 0x07, 0x65, 0x79, 0x86, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xB7, 0x13, 0x75, 0xD3, 0xC5, 0x0A, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x9E, 0xFA, 0xE1, 0x1F, 0x0C, 0xF9, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x8C, 0xED, 0x5C, 0x21, 0xE9, 0x09, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x4D, 0xD8, 0x18, 0xC4, 0xF6, 0x36, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xC9, 0xAC, 0x5C, 0xFA, 0x69, 0xA4, 0xA0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8C, 0x94, 0x1C, 0x7B, 0x71, 0x36, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBD, 0x46, 0xCE, 0xB7, 0x1D, 0x9C, 0x5E),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD6, 0x96, 0x4B, 0xA6, 0x47, 0xEB, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xF1, 0x5F, 0x15, 0xDE, 0x99, 0x6F, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xBD, 0xE5, 0x04, 0xB8, 0xE6, 0xC0, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD3, 0xF0, 0x04, 0x00, 0xE4, 0x05, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xF3, 0x06, 0xA3, 0x1A, 0xFF, 0xEA, 0x73),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x32, 0xAA, 0x99, 0x33, 0x09, 0xB6, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xEF, 0xFC, 0x61, 0x10, 0x42, 0x31, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF1, 0xF4, 0x33, 0xCF, 0x28, 0x90, 0x9C),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xDE, 0xF9, 0x88, 0x87, 0x7B, 0xEB, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xB8, 0xDA, 0xFA, 0xDA, 0x3D, 0xA6, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF0, 0x62, 0x82, 0x53, 0x32, 0x55, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA5, 0x32, 0x4A, 0x19, 0x11, 0x9C, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xB3, 0x27, 0xE9, 0x75, 0x90, 0x05, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x1C, 0x90, 0x48, 0x77, 0x01, 0x85, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD6, 0x9B, 0x84, 0xA8, 0xD7, 0xC5, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x7A, 0xCB, 0xB3, 0x11, 0x46, 0xD7, 0x99),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x23, 0xBF, 0x75, 0x75, 0xA1, 0x95, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x66, 0x5D, 0x34, 0x13, 0xA9, 0x03, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x80, 0x9D, 0x5F, 0xD2, 0x44, 0xE1, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x5D, 0xBD, 0xA8, 0xBF, 0xB4, 0x25, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x99, 0x1F, 0x53, 0xF1, 0x57, 0xDB, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x7C, 0xE5, 0xC5, 0x51, 0x0B, 0x4C, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xB0, 0x1A, 0x9C, 0x16, 0xB0, 0x32, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xE3, 0xCF, 0xDD, 0x48, 0xB4, 0x7B, 0x33),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xDD, 0x9E, 0x3C, 0x98, 0x0E, 0x77, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xAB, 0x01, 0xD3, 0x87, 0x74, 0x25, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xA3, 0xE3, 0x76, 0x43, 0x87, 0x12, 0xBD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0xB1, 0x3B, 0x60, 0x66, 0xEB, 0x98, 0x54),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x78, 0xC8, 0xD7, 0x4E, 0x75, 0xCA, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xDF, 0x71, 0x19, 0xE7, 0x07, 0x36, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC9, 0xA8, 0x5F, 0x91, 0xBF, 0x47, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x96, 0x58, 0x96, 0x18, 0xB6, 0xFA, 0x01),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x2D, 0xA9, 0x9B, 0x86, 0xDB, 0x0C, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0B, 0x2D, 0x56, 0x4A, 0xD3, 0x93, 0x8A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x15, 0xE2, 0x65, 0x12, 0x86, 0x0E, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x41, 0x4D, 0xC1, 0xCB, 0xE4, 0xC3, 0xD7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x53, 0x10, 0xCA, 0xA3, 0xAC, 0x83, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x01, 0x22, 0x96, 0x10, 0xAD, 0x69, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x46, 0x4E, 0xD8, 0xEA, 0xD6, 0x9D, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x2F, 0x7F, 0x62, 0x62, 0x80, 0xD0, 0x14),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xDA, 0x00, 0x63, 0x09, 0xBD, 0x6A, 0x83),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD4, 0x6E, 0x48, 0x05, 0xB7, 0xF7, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x4D, 0xD7, 0x00, 0x4A, 0x15, 0x27, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x15, 0xAA, 0x37, 0x27, 0x34, 0x18, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x20, 0x2C, 0x84, 0x1B, 0x88, 0xBA, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x09, 0xD6, 0x04, 0xA2, 0x60, 0x84, 0x72),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x04, 0x94, 0x08, 0xD4, 0xED, 0x47, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xF3, 0xE4, 0x3E, 0xB9, 0x5B, 0x35, 0x42),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xD8, 0xB6, 0x80, 0xD6, 0xF1, 0x30, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x14, 0xA6, 0x85, 0xEE, 0xA7, 0xD8, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x49, 0x2A, 0x1E, 0x7C, 0xE9, 0x2D, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x87, 0x56, 0x91, 0x03, 0x77, 0x4D, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x52, 0xD4, 0xAA, 0xF7, 0xFA, 0xB0, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x11, 0x39, 0xB1, 0xE7, 0x76, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x13, 0xBC, 0x37, 0x5D, 0x74, 0xCD, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x48, 0x14, 0x23, 0x30, 0xF8, 0x46, 0x37),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x27, 0xB0, 0xD9, 0xB2, 0x74, 0xB4, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xA6, 0xB9, 0x6F, 0x9F, 0x64, 0x36, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x2B, 0x78, 0x40, 0x05, 0x2B, 0x7B, 0xA9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x68, 0x3A, 0xB6, 0x4A, 0xE2, 0xDB, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x33, 0xD7, 0x34, 0x8B, 0x25, 0x45, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xCE, 0xA8, 0xC9, 0x01, 0xFB, 0x0E, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF9, 0x51, 0x4C, 0x12, 0x9F, 0x60, 0xE4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x85, 0xBD, 0x30, 0x37, 0x84, 0x39, 0x44),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x33, 0xAF, 0x2E, 0xB8, 0x2E, 0xCC, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xB1, 0x73, 0x59, 0x4E, 0x0C, 0x09, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x24, 0x89, 0x81, 0x12, 0xFF, 0xBB, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0x1A, 0x66, 0xEE, 0xED, 0xB6, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xBD, 0x04, 0x20, 0x5D, 0xFB, 0xBF, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF8, 0x34, 0xA3, 0xFF, 0x45, 0xDE, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x18, 0x73, 0xF1, 0x32, 0x25, 0x58, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xC1, 0x14, 0xE3, 0x9E, 0x40, 0x0F, 0x12),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0x9D, 0x9C, 0x00, 0xF7, 0x56, 0x19),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBA, 0x87, 0xF9, 0x15, 0x0C, 0x66, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x1F, 0xC1, 0x28, 0xB0, 0x47, 0x0D, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xCA, 0x27, 0xEE, 0x4B, 0x23, 0x2B, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB5, 0x68, 0xC8, 0x17, 0x5D, 0xC3, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x02, 0x08, 0xEE, 0x20, 0x9D, 0xEA, 0x64),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x14, 0x50, 0xD4, 0x7D, 0x5F, 0xCF, 0xA0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFA, 0xF8, 0xA7, 0xC6, 0xDC, 0x14, 0x8C),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xBD, 0x0A, 0x1A, 0x18, 0x98, 0xDC, 0xB0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x63, 0x02, 0xB7, 0xD5, 0x5B, 0x5A, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB1, 0xD7, 0x4B, 0x15, 0x39, 0x61, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x32, 0xE1, 0x9E, 0x70, 0x1B, 0xCE, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD8, 0x18, 0x83, 0x52, 0x9B, 0x6D, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x55, 0x56, 0x19, 0x34, 0xA4, 0xEA, 0xFC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA9, 0x55, 0x80, 0xE3, 0x15, 0x36, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x06, 0xC8, 0x1D, 0x17, 0x0D, 0xAD, 0x16),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xD6, 0xF0, 0xCC, 0xF3, 0x63, 0x53, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x5A, 0xDC, 0x46, 0xBD, 0x0D, 0xAD, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x2F, 0x11, 0x60, 0x15, 0x51, 0x4A, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE3, 0x93, 0x38, 0xD5, 0x83, 0xAA, 0x0D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA6, 0xCC, 0xB1, 0xFD, 0xBB, 0x1A, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x54, 0xC8, 0x54, 0x6F, 0x79, 0x1A, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4A, 0xDA, 0x28, 0x92, 0x97, 0x9D, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x4B, 0xDB, 0xC7, 0x52, 0xC5, 0x66, 0x34),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7E, 0x92, 0x53, 0x30, 0x93, 0xFD, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0x6A, 0xB1, 0x91, 0x0A, 0xB4, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x9D, 0x40, 0x3F, 0xE3, 0xF1, 0x01, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x0E, 0xD8, 0xED, 0x11, 0x8E, 0x4C, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x4A, 0x1B, 0x88, 0xDF, 0x8D, 0x29, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x23, 0x21, 0x11, 0xAB, 0x77, 0x81, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xAF, 0x11, 0xFA, 0xBA, 0x40, 0x63, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x6F, 0x8D, 0x80, 0xDF, 0x67, 0xF5, 0x44),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x8B, 0xB7, 0x08, 0xF4, 0xD7, 0x2D, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x2B, 0x30, 0x02, 0x45, 0x71, 0x08, 0x49),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x3A, 0xCA, 0x50, 0xF6, 0xC2, 0x19, 0x8C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xB9, 0x9B, 0x3E, 0x73, 0x95, 0x1D, 0x49),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x60, 0x59, 0x48, 0xCB, 0xD8, 0xD6, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x6C, 0x89, 0xAB, 0x99, 0xA8, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xA1, 0x8B, 0x4E, 0x06, 0x19, 0xEC, 0x99),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x95, 0x04, 0xCF, 0xD5, 0x94, 0xB3, 0x02),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x35, 0x93, 0x7C, 0xB3, 0xB8, 0x9E, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x45, 0x5C, 0x7E, 0xBF, 0x75, 0x81, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE8, 0x24, 0xDF, 0xEC, 0x2F, 0x7D, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x8B, 0xD5, 0x6A, 0x9B, 0xA0, 0xE0, 0x4F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE3, 0x27, 0x82, 0xDE, 0xDD, 0xCA, 0x4B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x57, 0x56, 0x46, 0x05, 0x06, 0x01, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x35, 0xA7, 0x47, 0xE2, 0x6B, 0x2C, 0x4F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x9D, 0x4C, 0xEC, 0x1F, 0x11, 0x75, 0x2B),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xAA, 0x41, 0xC1, 0xE9, 0x0E, 0xE9, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xCF, 0x9C, 0x4B, 0xE8, 0xED, 0x0A, 0x49),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x73, 0xCA, 0x0C, 0x46, 0x0A, 0x9C, 0xE4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE1, 0x9E, 0xBC, 0xFE, 0x44, 0x63, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x43, 0x71, 0xEE, 0xF8, 0xC1, 0x8C, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x4B, 0xF0, 0x69, 0x25, 0xBD, 0x71, 0x1A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x9A, 0xFE, 0x82, 0xE7, 0xC1, 0xC1, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x5A, 0x6E, 0x5E, 0x97, 0x6A, 0x35, 0x8D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x18, 0x6C, 0x7E, 0xB8, 0x9E, 0x57, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xB9, 0xC1, 0xD0, 0xFE, 0x78, 0xFB, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x08, 0xAE, 0x46, 0x34, 0xEA, 0x7A, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1C, 0x56, 0xA9, 0x18, 0x37, 0xD4, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x63, 0xE9, 0x0A, 0xB6, 0x38, 0x3C, 0xC1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x4F, 0xA4, 0x6E, 0x85, 0x31, 0x23, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xAD, 0xC4, 0xC3, 0xB1, 0x4B, 0x1C, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x56, 0x4A, 0x38, 0xB3, 0x6B, 0x6F, 0x2C),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_16_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xC7, 0x19, 0xDE, 0x21, 0xED, 0x89, 0xD0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xBE, 0xA6, 0xAE, 0xEB, 0x9D, 0xA7, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x0E, 0x13, 0x1E, 0x86, 0x57, 0xC3, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4B, 0x30, 0x46, 0x52, 0xC1, 0xEC, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xD5, 0x44, 0x31, 0x96, 0x3B, 0x26, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x68, 0xA8, 0x67, 0x78, 0x39, 0xE8, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x78, 0xB7, 0xDD, 0xF2, 0x58, 0xB6, 0x3D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x3C, 0xB3, 0x26, 0xC4, 0x2C, 0x8C, 0xA5),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_16_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x24, 0xE5, 0x73, 0xEE, 0x9A, 0x02, 0xA9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x6A, 0x65, 0x60, 0xF3, 0x62, 0xE3, 0xE9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x07, 0x84, 0xE6, 0x3B, 0x46, 0x65, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x8F, 0x0C, 0xB0, 0xE1, 0x04, 0x82, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x13, 0xBF, 0x3D, 0xA0, 0x48, 0xA2, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x26, 0x76, 0x74, 0xAB, 0x0B, 0x29, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x6E, 0x5F, 0x03, 0x34, 0x7C, 0x38, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x72, 0xF9, 0x3B, 0x3C, 0xA4, 0xBC, 0x7C),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_17_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xCE, 0x18, 0x80, 0xB8, 0x24, 0x45, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x09, 0x03, 0xB8, 0x06, 0x64, 0xF7, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x26, 0xB1, 0x10, 0x6D, 0x71, 0x12, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x12, 0xC6, 0x6E, 0x1E, 0x6A, 0xC3, 0x80),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xD3, 0x0A, 0xDE, 0xD8, 0x6B, 0x04, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x87, 0x5B, 0xAE, 0xDB, 0x3C, 0xC0, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF5, 0xF9, 0xC1, 0x9A, 0x89, 0xBB, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x69, 0x72, 0x8B, 0xAE, 0x32, 0x13, 0x11),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_17_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x16, 0x07, 0x50, 0xFA, 0x4C, 0xCF, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x50, 0x21, 0xE9, 0xDE, 0xEC, 0x7E, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x2F, 0xE8, 0x83, 0x30, 0x0B, 0x65, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x0B, 0x99, 0xAC, 0xC9, 0xBA, 0x6C, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x59, 0x5A, 0x0D, 0x7B, 0x9E, 0x08, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x91, 0xB2, 0xDC, 0x90, 0xCE, 0x67, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x93, 0x60, 0x0C, 0xD7, 0x1F, 0x2F, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7F, 0x9D, 0x40, 0xF8, 0x78, 0x7A, 0x54),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_18_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x22, 0x95, 0xE8, 0xEF, 0x31, 0x57, 0x35),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x88, 0x53, 0xFE, 0xAF, 0x7C, 0x47, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xCE, 0xCC, 0x79, 0xE8, 0x9F, 0x8C, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x16, 0xDD, 0x77, 0x6E, 0x8A, 0x73, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x07, 0x97, 0x21, 0x3B, 0xF8, 0x5F, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xB5, 0xD2, 0x81, 0x84, 0xF0, 0xE7, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x8F, 0x75, 0x09, 0x6A, 0x0E, 0x53, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x4F, 0x70, 0x97, 0xC7, 0xAC, 0x7D, 0x3F),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_18_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x3C, 0x6A, 0xB4, 0x10, 0xA9, 0xC8, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC5, 0xD6, 0x69, 0x16, 0xB8, 0xAC, 0x25),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x44, 0xDC, 0xEB, 0x48, 0x54, 0x5D, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x48, 0x9B, 0xD7, 0x72, 0x69, 0xA4, 0x8A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x0D, 0x36, 0x9A, 0x66, 0x0B, 0xEC, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC6, 0xD4, 0xB6, 0x60, 0xE5, 0xC3, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x29, 0x42, 0xE0, 0x9D, 0xFD, 0x7C, 0x3E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x10, 0xBA, 0x55, 0xBC, 0x3B, 0x38, 0x5D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_19_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x66, 0xFA, 0x05, 0x73, 0x03, 0x1B, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xA4, 0x66, 0x12, 0x96, 0x7B, 0x02, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xDE, 0x6D, 0x98, 0xD1, 0xD5, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF5, 0x44, 0xB8, 0x8E, 0xF6, 0x8C, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x15, 0x2B, 0x72, 0xBC, 0x49, 0xE5, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x44, 0xD7, 0xDF, 0x8F, 0xEB, 0x8D, 0x80),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x64, 0x88, 0xAA, 0xB7, 0xE4, 0x70, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x14, 0xBB, 0xE9, 0x9B, 0xB9, 0x65, 0x5D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_19_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x8E, 0x88, 0xF5, 0xF1, 0xC1, 0x89, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x30, 0x53, 0xE6, 0xFB, 0x2D, 0x82, 0xB4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE4, 0xFF, 0xBA, 0x31, 0x79, 0xAB, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x09, 0xF7, 0xB7, 0x09, 0x78, 0x4C, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xAE, 0xC2, 0x44, 0xDC, 0x17, 0x78, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD4, 0x17, 0x43, 0x19, 0x74, 0x9E, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x64, 0x3B, 0x73, 0xA2, 0x99, 0x27, 0x76),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0x36, 0x5F, 0xD3, 0x14, 0xB1, 0x31),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_20_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x07, 0xAB, 0xFD, 0x9B, 0x03, 0xC5, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xBE, 0xB0, 0x1D, 0xF2, 0x0C, 0x73, 0x73),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE7, 0x7B, 0x87, 0xD3, 0x34, 0xFD, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x25, 0x3D, 0xC7, 0x36, 0x83, 0x53, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x7C, 0xCF, 0x63, 0x55, 0x12, 0x11, 0xB0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x34, 0x4D, 0x27, 0x92, 0xAC, 0x18, 0x16),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x42, 0x61, 0x9D, 0x2E, 0xFF, 0x13, 0x16),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xDE, 0x92, 0x65, 0x57, 0x0D, 0xBC, 0x0A),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_20_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x7B, 0x6E, 0xC6, 0x2A, 0x21, 0x74, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xA7, 0x53, 0x4D, 0x29, 0x36, 0xEF, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xD6, 0x41, 0xC7, 0x99, 0xAD, 0x50, 0x53),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xAC, 0x41, 0x9F, 0xFB, 0x4C, 0x86, 0xF1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xBB, 0xE6, 0x25, 0x28, 0xAA, 0xEB, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x04, 0xA2, 0xC3, 0xAA, 0x08, 0x8A, 0xCC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x2B, 0x5B, 0xE2, 0x8D, 0x76, 0xEA, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x33, 0xD2, 0x21, 0x4D, 0x62, 0xE3, 0x8E),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_21_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x06, 0x8B, 0x2B, 0xC2, 0xC4, 0xB1, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF5, 0xA1, 0xC0, 0x03, 0x6A, 0x29, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA9, 0xEF, 0x55, 0xB6, 0x1A, 0x9F, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x54, 0x32, 0xBE, 0x06, 0x43, 0xB5, 0xFD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xD6, 0xD9, 0x20, 0x89, 0xBE, 0xD4, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x26, 0x95, 0x10, 0xCE, 0xB4, 0x88, 0x79),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xA6, 0x27, 0xAC, 0x32, 0xBA, 0xBD, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xA6, 0xAE, 0x9C, 0x7B, 0xBE, 0xA1, 0x63),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_21_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xCD, 0x4D, 0x3D, 0xDF, 0x96, 0xBB, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0x11, 0x06, 0xCC, 0x0E, 0x31, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xE4, 0xF4, 0xAD, 0x7B, 0x5F, 0xF1, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x54, 0xBE, 0xF4, 0x8A, 0x03, 0x47, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x53, 0x00, 0x7F, 0xB0, 0x8A, 0x68, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0xB1, 0x73, 0x6F, 0x5B, 0x0E, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x32, 0xE3, 0x43, 0x64, 0x75, 0xFB, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x18, 0x55, 0x8A, 0x4E, 0x6E, 0x35, 0x54),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_22_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x97, 0x15, 0x1E, 0xCB, 0xF2, 0x9C, 0xA5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xD1, 0xBB, 0xF3, 0x70, 0xAD, 0x13, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x96, 0xA4, 0xC5, 0x5E, 0xDA, 0xD5, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x81, 0xE9, 0x65, 0x66, 0x76, 0x47, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x87, 0x06, 0x73, 0xCF, 0x34, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x81, 0x15, 0x42, 0xA2, 0x79, 0x5B, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA2, 0x7D, 0x09, 0x14, 0x64, 0xC6, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x6D, 0xC4, 0xED, 0xF1, 0xD6, 0xE9, 0x24),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_22_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xD5, 0xBB, 0x25, 0xA3, 0xDD, 0xA3, 0x88),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xF2, 0x68, 0x67, 0x39, 0x8F, 0x73, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x76, 0x28, 0x89, 0xAD, 0x32, 0xE0, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x90, 0xCC, 0x57, 0x58, 0xAA, 0xC9, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD7, 0x43, 0xD2, 0xCE, 0x5E, 0xA0, 0x08),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xB0, 0xB8, 0xA4, 0x9E, 0x96, 0x26, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x61, 0x1D, 0xF3, 0x65, 0x5E, 0x60, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x1E, 0x65, 0xED, 0xCF, 0x07, 0x60, 0x20),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_23_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x30, 0x17, 0x8A, 0x91, 0x88, 0x0A, 0xA4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7D, 0x18, 0xA4, 0xAC, 0x59, 0xFC, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x31, 0x8B, 0x25, 0x65, 0x39, 0x9A, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x16, 0x4B, 0x68, 0xBA, 0x59, 0x13, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xD3, 0xC5, 0x56, 0xC9, 0x8C, 0x5E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC6, 0x9F, 0xF4, 0xE6, 0xF7, 0xB4, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x7C, 0x03, 0x00, 0x26, 0x9F, 0xD8, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x1D, 0x6E, 0x00, 0xB9, 0x00, 0x6E, 0x93),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_23_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x63, 0xDA, 0x03, 0x2B, 0xD5, 0x0B, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xFC, 0xE2, 0xC8, 0x47, 0xF0, 0xAE, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x4C, 0xF7, 0x50, 0x0C, 0x48, 0x06, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2B, 0x32, 0x98, 0x0E, 0x7E, 0x61, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x02, 0x27, 0xFE, 0x75, 0x86, 0xDF, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x30, 0xB1, 0x22, 0x32, 0x1B, 0xFE, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x27, 0xF7, 0x78, 0x6F, 0xD7, 0xFD, 0xE4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x78, 0xCC, 0xEA, 0xC0, 0x50, 0x24, 0x44),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_24_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x2B, 0x4F, 0x7F, 0x58, 0xE6, 0xC2, 0x70),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x43, 0xD5, 0xA7, 0x35, 0x3C, 0x80, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x6D, 0x4B, 0x12, 0x00, 0x7B, 0xE6, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x15, 0xBD, 0xD0, 0x9B, 0xCA, 0xAA, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xCE, 0x9C, 0xE3, 0x8B, 0x60, 0x7A, 0x53),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xDA, 0x4B, 0x03, 0xA7, 0x8D, 0x43, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAF, 0x00, 0x2B, 0x32, 0xF0, 0x22, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xD9, 0x99, 0x99, 0xBE, 0x43, 0x99, 0x3E),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_24_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x71, 0x41, 0xF4, 0xB5, 0xFD, 0xDD, 0x36),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xE2, 0x20, 0x4C, 0xD1, 0x2E, 0x1F, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x43, 0x48, 0x76, 0x8A, 0x49, 0xAC, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1A, 0x55, 0xA8, 0xA3, 0xD4, 0x57, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xA6, 0x84, 0x39, 0xC9, 0x13, 0xBB, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xFA, 0xA9, 0x70, 0xDE, 0x83, 0xDD, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xC9, 0xD9, 0x3E, 0x44, 0x91, 0x68, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x9F, 0x85, 0x6D, 0xF7, 0x54, 0x36, 0x82),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_25_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x6B, 0xA6, 0xA3, 0xE5, 0xD4, 0x46, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x3E, 0xDC, 0x84, 0x7C, 0x7B, 0x24, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xED, 0x7F, 0x86, 0x07, 0x6C, 0x57, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x06, 0xFE, 0x52, 0x12, 0x79, 0x69, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xD1, 0x44, 0x5F, 0x21, 0x3A, 0xC3, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD9, 0x4A, 0xC0, 0x75, 0xAB, 0x17, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x81, 0x94, 0xB6, 0x80, 0x6B, 0x6F, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBE, 0x8E, 0xA5, 0xAA, 0xBC, 0x1E, 0x3E),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_25_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xC7, 0x85, 0xA6, 0x59, 0x9B, 0xB1, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xCE, 0x40, 0xD1, 0xFB, 0xDF, 0x94, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xB8, 0x5E, 0xBF, 0x45, 0xA8, 0x2D, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9C, 0x06, 0x1B, 0xA9, 0x57, 0xB9, 0x79),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xE9, 0xCE, 0xA2, 0xD3, 0x74, 0xA1, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x5F, 0x34, 0x78, 0xDB, 0xAE, 0x3A, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x32, 0x84, 0x3E, 0x68, 0x6A, 0x43, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xBC, 0x39, 0x36, 0xA4, 0xC5, 0xBB, 0x11),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_26_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x07, 0xA2, 0xB5, 0xC9, 0x0F, 0x4D, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0x67, 0xE6, 0xF1, 0x46, 0xEB, 0x71),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x41, 0x23, 0x95, 0xE7, 0xE0, 0x10, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x69, 0xFE, 0x68, 0x8C, 0xC6, 0x5F, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB9, 0x2B, 0x3D, 0xD2, 0x4F, 0xD8, 0x1A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x09, 0xF5, 0x5F, 0xCF, 0xF6, 0x91, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x15, 0x42, 0x6B, 0x6D, 0xB5, 0xF3, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x56, 0x9D, 0xC5, 0xFF, 0xCA, 0x13, 0x9B),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_26_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x38, 0xE6, 0x23, 0x63, 0x48, 0x3C, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x68, 0x3C, 0xD1, 0x3B, 0xE9, 0x3B, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x08, 0x54, 0x49, 0xD1, 0x46, 0x45, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x70, 0x52, 0x6E, 0x79, 0xC4, 0x5E, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xDF, 0xE8, 0x5A, 0x32, 0x81, 0xDA, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x2D, 0x94, 0x5B, 0xB5, 0x35, 0x9F, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x12, 0x8D, 0xC3, 0x36, 0x36, 0xB2, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x2F, 0x22, 0x38, 0x5B, 0x18, 0x4C, 0x35),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_27_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC1, 0x22, 0x0E, 0xF0, 0x73, 0x11, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xAE, 0xA4, 0x56, 0x18, 0x61, 0x66, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFB, 0x72, 0x08, 0x84, 0x38, 0x51, 0xB0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x86, 0xA8, 0xB9, 0x31, 0x99, 0x29, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xFB, 0xC3, 0x42, 0xB3, 0xC7, 0x6F, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xF8, 0xE1, 0x09, 0xBE, 0x75, 0xB0, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x7D, 0xFF, 0xF4, 0x99, 0xFC, 0x13, 0xAB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x1B, 0x84, 0x81, 0x42, 0x22, 0xC6, 0x3D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_27_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE0, 0x37, 0xA4, 0xA0, 0x2F, 0x38, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x3D, 0xB7, 0x40, 0x2F, 0x39, 0x3C, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x3B, 0x8A, 0x51, 0xAE, 0x40, 0x49, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x20, 0x9F, 0xDD, 0xA9, 0xD0, 0x77, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x1D, 0x64, 0xDA, 0xA0, 0x53, 0xC7, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x7B, 0x66, 0x55, 0x94, 0xD1, 0x51, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xB5, 0x5B, 0x38, 0x35, 0x40, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0x0F, 0xF0, 0x73, 0x79, 0x43, 0x61),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_28_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x47, 0x45, 0x69, 0x80, 0x72, 0x72, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x11, 0x99, 0x59, 0xDB, 0x48, 0x80, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x6E, 0x3D, 0xFC, 0x37, 0x15, 0xF4, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xBB, 0x5B, 0xA6, 0x35, 0x8D, 0x28, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x1A, 0x3B, 0x2C, 0x8F, 0xD3, 0xAA, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x1C, 0x1A, 0xF8, 0x02, 0xD9, 0x7B, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x69, 0xAC, 0xF8, 0x54, 0x31, 0x14, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x8A, 0xE6, 0xDE, 0x58, 0xB9, 0xC4, 0x7A),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_28_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x83, 0x52, 0xFE, 0xF9, 0x7B, 0xE9, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xA2, 0x55, 0x46, 0x15, 0x49, 0xC1, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBC, 0x5C, 0x91, 0xBD, 0xB9, 0x9C, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xFD, 0xB1, 0x4E, 0x5F, 0x74, 0xEE, 0x53),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x8B, 0xD8, 0x8B, 0x17, 0x73, 0x1B, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x92, 0xD7, 0x67, 0x06, 0xAD, 0x25, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0x80, 0x24, 0xE2, 0x27, 0x5F, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x1C, 0xCE, 0xD0, 0x67, 0xCA, 0xD4, 0x0B),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_29_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xF1, 0xDD, 0x33, 0x66, 0xF9, 0x05, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xE5, 0x6B, 0x79, 0xBD, 0x48, 0x42, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x14, 0x52, 0xE3, 0x53, 0xB4, 0x50, 0xD4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x84, 0x6C, 0xCF, 0xDA, 0xB2, 0x20, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xD6, 0x1A, 0xE5, 0xE2, 0x29, 0x70, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x61, 0xFE, 0xBB, 0x21, 0x82, 0xD1, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0xF0, 0x9C, 0x8B, 0x1A, 0x42, 0x30, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xD6, 0x49, 0x81, 0x92, 0xF1, 0xD0, 0x90),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_29_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x91, 0x93, 0x6A, 0xA6, 0x22, 0xE9, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xDC, 0xC3, 0x69, 0x11, 0x95, 0x7D, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xA3, 0x9D, 0x87, 0x5E, 0x64, 0x41, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x87, 0x5A, 0x15, 0xBD, 0x6E, 0x3C, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x8D, 0x50, 0xCC, 0xCF, 0xB7, 0x8F, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x65, 0xCD, 0x31, 0x30, 0xF1, 0x68, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x5C, 0x66, 0x67, 0x92, 0x30, 0x57, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x9B, 0x01, 0x3D, 0x20, 0x8B, 0xD1, 0x0D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_30_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC0, 0xE6, 0x4F, 0xDE, 0x62, 0xAB, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x48, 0xB3, 0x1C, 0x0F, 0x16, 0x93, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x63, 0xBD, 0x1F, 0x16, 0x50, 0x56, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x06, 0xBC, 0xE9, 0x27, 0x1C, 0x9A, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xFE, 0x21, 0xC5, 0x39, 0x55, 0xE1, 0xFD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA8, 0xD0, 0x96, 0x0E, 0xB5, 0xB2, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xE7, 0x4B, 0xF3, 0x11, 0x0C, 0xC9, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x3A, 0xC4, 0x87, 0x71, 0xEE, 0xFA, 0x18),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_30_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x77, 0xEE, 0x81, 0x5E, 0x96, 0xEA, 0x4B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xDF, 0xA9, 0xF4, 0x4F, 0x7C, 0xB2, 0x43),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD4, 0xDF, 0x35, 0x63, 0x47, 0x25, 0x8A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3D, 0xFF, 0xA4, 0x02, 0xC3, 0x95, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x10, 0x78, 0xD1, 0x2B, 0xB7, 0xBE, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE9, 0x57, 0xF9, 0xE0, 0xD8, 0xFC, 0xBC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xC4, 0x01, 0xD6, 0xB4, 0xE7, 0x78, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6C, 0xB9, 0x13, 0xA4, 0xE8, 0x6D, 0x6F),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_31_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xB0, 0xC9, 0xCD, 0xBF, 0xA2, 0x1E, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x4F, 0x86, 0x22, 0x9B, 0xEA, 0xE8, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x46, 0xDF, 0x43, 0xB9, 0x82, 0x2D, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x32, 0xF1, 0x4E, 0x95, 0x41, 0xAE, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x93, 0x26, 0xFC, 0xD3, 0x90, 0xDC, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x05, 0x45, 0xCA, 0xF9, 0x5A, 0x89, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x82, 0x63, 0x4E, 0x55, 0x1D, 0x3A, 0x08),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x69, 0x52, 0x49, 0xE9, 0xED, 0x57, 0x34),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_31_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x64, 0xE9, 0xAC, 0x4C, 0x4A, 0xEA, 0x25),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xE9, 0x0B, 0x99, 0xE7, 0xF9, 0xA9, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x0C, 0xC1, 0xF4, 0x8D, 0x07, 0xB6, 0xB1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x68, 0xFA, 0x35, 0xE4, 0x9E, 0xAE, 0xD9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2D, 0x1A, 0x13, 0x8E, 0x02, 0xE2, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x28, 0x86, 0x46, 0x7B, 0x3A, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4C, 0x64, 0x59, 0x0A, 0xF9, 0x02, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x4F, 0x23, 0xA2, 0xC3, 0xD5, 0xEF, 0x42),\n};\nstatic const mbedtls_ecp_point brainpoolP512r1_T[32] = {\n    ECP_POINT_INIT_XY_Z1(brainpoolP512r1_T_0_X, brainpoolP512r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_1_X, brainpoolP512r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_2_X, brainpoolP512r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_3_X, brainpoolP512r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_4_X, brainpoolP512r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_5_X, brainpoolP512r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_6_X, brainpoolP512r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_7_X, brainpoolP512r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_8_X, brainpoolP512r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_9_X, brainpoolP512r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_10_X, brainpoolP512r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_11_X, brainpoolP512r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_12_X, brainpoolP512r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_13_X, brainpoolP512r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_14_X, brainpoolP512r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_15_X, brainpoolP512r1_T_15_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_16_X, brainpoolP512r1_T_16_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_17_X, brainpoolP512r1_T_17_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_18_X, brainpoolP512r1_T_18_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_19_X, brainpoolP512r1_T_19_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_20_X, brainpoolP512r1_T_20_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_21_X, brainpoolP512r1_T_21_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_22_X, brainpoolP512r1_T_22_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_23_X, brainpoolP512r1_T_23_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_24_X, brainpoolP512r1_T_24_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_25_X, brainpoolP512r1_T_25_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_26_X, brainpoolP512r1_T_26_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_27_X, brainpoolP512r1_T_27_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_28_X, brainpoolP512r1_T_28_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_29_X, brainpoolP512r1_T_29_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_30_X, brainpoolP512r1_T_30_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_31_X, brainpoolP512r1_T_31_Y),\n};\n#else\n#define brainpoolP512r1_T NULL\n#endif\n#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */\n\n#if defined(ECP_LOAD_GROUP)\n/*\n * Create an MPI from embedded constants\n * (assumes len is an exact multiple of sizeof(mbedtls_mpi_uint))\n */\nstatic inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len)\n{\n    X->s = 1;\n    X->n = (unsigned short) (len / sizeof(mbedtls_mpi_uint));\n    X->p = (mbedtls_mpi_uint *) p;\n}\n\n/*\n * Set an MPI to static value 1\n */\nstatic inline void ecp_mpi_set1(mbedtls_mpi *X)\n{\n    X->s = 1;\n    X->n = 1;\n    X->p = (mbedtls_mpi_uint *) mpi_one; /* X->p will not be modified so the cast is safe */\n}\n\n/*\n * Make group available from embedded constants\n */\nstatic int ecp_group_load(mbedtls_ecp_group *grp,\n                          const mbedtls_mpi_uint *p,  size_t plen,\n                          const mbedtls_mpi_uint *a,  size_t alen,\n                          const mbedtls_mpi_uint *b,  size_t blen,\n                          const mbedtls_mpi_uint *gx, size_t gxlen,\n                          const mbedtls_mpi_uint *gy, size_t gylen,\n                          const mbedtls_mpi_uint *n,  size_t nlen,\n                          const mbedtls_ecp_point *T)\n{\n    ecp_mpi_load(&grp->P, p, plen);\n    if (a != NULL) {\n        ecp_mpi_load(&grp->A, a, alen);\n    }\n    ecp_mpi_load(&grp->B, b, blen);\n    ecp_mpi_load(&grp->N, n, nlen);\n\n    ecp_mpi_load(&grp->G.X, gx, gxlen);\n    ecp_mpi_load(&grp->G.Y, gy, gylen);\n    ecp_mpi_set1(&grp->G.Z);\n\n    grp->pbits = mbedtls_mpi_bitlen(&grp->P);\n    grp->nbits = mbedtls_mpi_bitlen(&grp->N);\n\n    grp->h = 1;\n\n    grp->T = (mbedtls_ecp_point *) T;\n    /*\n     * Set T_size to 0 to prevent T free by mbedtls_ecp_group_free.\n     */\n    grp->T_size = 0;\n\n    return 0;\n}\n#endif /* ECP_LOAD_GROUP */\n\n#if defined(MBEDTLS_ECP_NIST_OPTIM)\n/* Forward declarations */\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\nstatic int ecp_mod_p192(mbedtls_mpi *);\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)\nstatic int ecp_mod_p224(mbedtls_mpi *);\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)\nstatic int ecp_mod_p256(mbedtls_mpi *);\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\nstatic int ecp_mod_p384(mbedtls_mpi *);\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)\nstatic int ecp_mod_p521(mbedtls_mpi *);\n#endif\n\n#define NIST_MODP(P)      grp->modp = ecp_mod_ ## P;\n#else\n#define NIST_MODP(P)\n#endif /* MBEDTLS_ECP_NIST_OPTIM */\n\n/* Additional forward declarations */\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\nstatic int ecp_mod_p255(mbedtls_mpi *);\n#endif\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\nstatic int ecp_mod_p448(mbedtls_mpi *);\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)\nstatic int ecp_mod_p192k1(mbedtls_mpi *);\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)\nstatic int ecp_mod_p224k1(mbedtls_mpi *);\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\nstatic int ecp_mod_p256k1(mbedtls_mpi *);\n#endif\n\n#if defined(ECP_LOAD_GROUP)\n#define LOAD_GROUP_A(G)   ecp_group_load(grp,            \\\n                                         G ## _p,  sizeof(G ## _p),   \\\n                                         G ## _a,  sizeof(G ## _a),   \\\n                                         G ## _b,  sizeof(G ## _b),   \\\n                                         G ## _gx, sizeof(G ## _gx),   \\\n                                         G ## _gy, sizeof(G ## _gy),   \\\n                                         G ## _n,  sizeof(G ## _n),   \\\n                                         G ## _T                         \\\n                                         )\n\n#define LOAD_GROUP(G)     ecp_group_load(grp,            \\\n                                         G ## _p,  sizeof(G ## _p),   \\\n                                         NULL,     0,                    \\\n                                         G ## _b,  sizeof(G ## _b),   \\\n                                         G ## _gx, sizeof(G ## _gx),   \\\n                                         G ## _gy, sizeof(G ## _gy),   \\\n                                         G ## _n,  sizeof(G ## _n),   \\\n                                         G ## _T                         \\\n                                         )\n#endif /* ECP_LOAD_GROUP */\n\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n/* Constants used by ecp_use_curve25519() */\nstatic const mbedtls_mpi_sint curve25519_a24 = 0x01DB42;\nstatic const unsigned char curve25519_part_of_n[] = {\n    0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6,\n    0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED,\n};\n\n/*\n * Specialized function for creating the Curve25519 group\n */\nstatic int ecp_use_curve25519(mbedtls_ecp_group *grp)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* Actually ( A + 2 ) / 4 */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve25519_a24));\n\n    /* P = 2^255 - 19 */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->P, 1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&grp->P, 255));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&grp->P, &grp->P, 19));\n    grp->pbits = mbedtls_mpi_bitlen(&grp->P);\n\n    /* N = 2^252 + 27742317777372353535851937790883648493 */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&grp->N,\n                                            curve25519_part_of_n, sizeof(curve25519_part_of_n)));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&grp->N, 252, 1));\n\n    /* Y intentionally not set, since we use x/z coordinates.\n     * This is used as a marker to identify Montgomery curves! */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 9));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1));\n    mbedtls_mpi_free(&grp->G.Y);\n\n    /* Actually, the required msb for private keys */\n    grp->nbits = 254;\n\ncleanup:\n    if (ret != 0) {\n        mbedtls_ecp_group_free(grp);\n    }\n\n    return ret;\n}\n#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n/* Constants used by ecp_use_curve448() */\nstatic const mbedtls_mpi_sint curve448_a24 = 0x98AA;\nstatic const unsigned char curve448_part_of_n[] = {\n    0x83, 0x35, 0xDC, 0x16, 0x3B, 0xB1, 0x24,\n    0xB6, 0x51, 0x29, 0xC9, 0x6F, 0xDE, 0x93,\n    0x3D, 0x8D, 0x72, 0x3A, 0x70, 0xAA, 0xDC,\n    0x87, 0x3D, 0x6D, 0x54, 0xA7, 0xBB, 0x0D,\n};\n\n/*\n * Specialized function for creating the Curve448 group\n */\nstatic int ecp_use_curve448(mbedtls_ecp_group *grp)\n{\n    mbedtls_mpi Ns;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_mpi_init(&Ns);\n\n    /* Actually ( A + 2 ) / 4 */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve448_a24));\n\n    /* P = 2^448 - 2^224 - 1 */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->P, 1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&grp->P, 224));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&grp->P, &grp->P, 1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&grp->P, 224));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&grp->P, &grp->P, 1));\n    grp->pbits = mbedtls_mpi_bitlen(&grp->P);\n\n    /* Y intentionally not set, since we use x/z coordinates.\n     * This is used as a marker to identify Montgomery curves! */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 5));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1));\n    mbedtls_mpi_free(&grp->G.Y);\n\n    /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&grp->N, 446, 1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&Ns,\n                                            curve448_part_of_n, sizeof(curve448_part_of_n)));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&grp->N, &grp->N, &Ns));\n\n    /* Actually, the required msb for private keys */\n    grp->nbits = 447;\n\ncleanup:\n    mbedtls_mpi_free(&Ns);\n    if (ret != 0) {\n        mbedtls_ecp_group_free(grp);\n    }\n\n    return ret;\n}\n#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */\n\n/*\n * Set a group using well-known domain parameters\n */\nint mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id)\n{\n    mbedtls_ecp_group_free(grp);\n\n    mbedtls_ecp_group_init(grp);\n\n    grp->id = id;\n\n    switch (id) {\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP192R1:\n            NIST_MODP(p192);\n            return LOAD_GROUP(secp192r1);\n#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP224R1:\n            NIST_MODP(p224);\n            return LOAD_GROUP(secp224r1);\n#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP256R1:\n            NIST_MODP(p256);\n            return LOAD_GROUP(secp256r1);\n#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP384R1:\n            NIST_MODP(p384);\n            return LOAD_GROUP(secp384r1);\n#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP521R1:\n            NIST_MODP(p521);\n            return LOAD_GROUP(secp521r1);\n#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP192K1:\n            grp->modp = ecp_mod_p192k1;\n            return LOAD_GROUP_A(secp192k1);\n#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP224K1:\n            grp->modp = ecp_mod_p224k1;\n            return LOAD_GROUP_A(secp224k1);\n#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP256K1:\n            grp->modp = ecp_mod_p256k1;\n            return LOAD_GROUP_A(secp256k1);\n#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)\n        case MBEDTLS_ECP_DP_BP256R1:\n            return LOAD_GROUP_A(brainpoolP256r1);\n#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)\n        case MBEDTLS_ECP_DP_BP384R1:\n            return LOAD_GROUP_A(brainpoolP384r1);\n#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)\n        case MBEDTLS_ECP_DP_BP512R1:\n            return LOAD_GROUP_A(brainpoolP512r1);\n#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n        case MBEDTLS_ECP_DP_CURVE25519:\n            grp->modp = ecp_mod_p255;\n            return ecp_use_curve25519(grp);\n#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n        case MBEDTLS_ECP_DP_CURVE448:\n            grp->modp = ecp_mod_p448;\n            return ecp_use_curve448(grp);\n#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */\n\n        default:\n            grp->id = MBEDTLS_ECP_DP_NONE;\n            return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n    }\n}\n\n#if defined(MBEDTLS_ECP_NIST_OPTIM)\n/*\n * Fast reduction modulo the primes used by the NIST curves.\n *\n * These functions are critical for speed, but not needed for correct\n * operations. So, we make the choice to heavily rely on the internals of our\n * bignum library, which creates a tight coupling between these functions and\n * our MPI implementation.  However, the coupling between the ECP module and\n * MPI remains loose, since these functions can be deactivated at will.\n */\n\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\n/*\n * Compared to the way things are presented in FIPS 186-3 D.2,\n * we proceed in columns, from right (least significant chunk) to left,\n * adding chunks to N in place, and keeping a carry for the next chunk.\n * This avoids moving things around in memory, and uselessly adding zeros,\n * compared to the more straightforward, line-oriented approach.\n *\n * For this prime we need to handle data in chunks of 64 bits.\n * Since this is always a multiple of our basic mbedtls_mpi_uint, we can\n * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it.\n */\n\n/* Add 64-bit chunks (dst += src) and update carry */\nstatic inline void add64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry)\n{\n    unsigned char i;\n    mbedtls_mpi_uint c = 0;\n    for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++, src++) {\n        *dst += c;      c  = (*dst < c);\n        *dst += *src;   c += (*dst < *src);\n    }\n    *carry += c;\n}\n\n/* Add carry to a 64-bit chunk and update carry */\nstatic inline void carry64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry)\n{\n    unsigned char i;\n    for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++) {\n        *dst += *carry;\n        *carry  = (*dst < *carry);\n    }\n}\n\n#define WIDTH       8 / sizeof(mbedtls_mpi_uint)\n#define A(i)      N->p + (i) * WIDTH\n#define ADD(i)    add64(p, A(i), &c)\n#define NEXT        p += WIDTH; carry64(p, &c)\n#define LAST        p += WIDTH; *p = c; while (++p < end) *p = 0\n\n/*\n * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)\n */\nstatic int ecp_mod_p192(mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi_uint c = 0;\n    mbedtls_mpi_uint *p, *end;\n\n    /* Make sure we have enough blocks so that A(5) is legal */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, 6 * WIDTH));\n\n    p = N->p;\n    end = p + N->n;\n\n    ADD(3); ADD(5);             NEXT;     // A0 += A3 + A5\n    ADD(3); ADD(4); ADD(5);   NEXT;       // A1 += A3 + A4 + A5\n    ADD(4); ADD(5);             LAST;     // A2 += A4 + A5\n\ncleanup:\n    return ret;\n}\n\n#undef WIDTH\n#undef A\n#undef ADD\n#undef NEXT\n#undef LAST\n#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\n/*\n * The reader is advised to first understand ecp_mod_p192() since the same\n * general structure is used here, but with additional complications:\n * (1) chunks of 32 bits, and (2) subtractions.\n */\n\n/*\n * For these primes, we need to handle data in chunks of 32 bits.\n * This makes it more complicated if we use 64 bits limbs in MPI,\n * which prevents us from using a uniform access method as for p192.\n *\n * So, we define a mini abstraction layer to access 32 bit chunks,\n * load them in 'cur' for work, and store them back from 'cur' when done.\n *\n * While at it, also define the size of N in terms of 32-bit chunks.\n */\n#define LOAD32      cur = A(i);\n\n#if defined(MBEDTLS_HAVE_INT32)  /* 32 bit */\n\n#define MAX32       N->n\n#define A(j)      N->p[j]\n#define STORE32     N->p[i] = cur;\n\n#else                               /* 64-bit */\n\n#define MAX32       N->n * 2\n#define A(j) (j) % 2 ? (uint32_t) (N->p[(j)/2] >> 32) : \\\n    (uint32_t) (N->p[(j)/2])\n#define STORE32                                   \\\n    if (i % 2) {                                 \\\n        N->p[i/2] &= 0x00000000FFFFFFFF;          \\\n        N->p[i/2] |= ((mbedtls_mpi_uint) cur) << 32;        \\\n    } else {                                      \\\n        N->p[i/2] &= 0xFFFFFFFF00000000;          \\\n        N->p[i/2] |= (mbedtls_mpi_uint) cur;                \\\n    }\n\n#endif /* sizeof( mbedtls_mpi_uint ) */\n\n/*\n * Helpers for addition and subtraction of chunks, with signed carry.\n */\nstatic inline void add32(uint32_t *dst, uint32_t src, signed char *carry)\n{\n    *dst += src;\n    *carry += (*dst < src);\n}\n\nstatic inline void sub32(uint32_t *dst, uint32_t src, signed char *carry)\n{\n    *carry -= (*dst < src);\n    *dst -= src;\n}\n\n#define ADD(j)    add32(&cur, A(j), &c);\n#define SUB(j)    sub32(&cur, A(j), &c);\n\n/*\n * Helpers for the main 'loop'\n */\n#define INIT(b)                                                       \\\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;                    \\\n    signed char c = 0, cc;                                              \\\n    uint32_t cur;                                                       \\\n    size_t i = 0, bits = (b);                                           \\\n    /* N is the size of the product of two b-bit numbers, plus one */   \\\n    /* limb for fix_negative */                                         \\\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, (b) * 2 / biL + 1));      \\\n    LOAD32;\n\n#define NEXT                    \\\n    STORE32; i++; LOAD32;       \\\n    cc = c; c = 0;              \\\n    if (cc < 0)                \\\n    sub32(&cur, -cc, &c); \\\n    else                        \\\n    add32(&cur, cc, &c);  \\\n\n#define LAST                                    \\\n    STORE32; i++;                               \\\n    cur = c > 0 ? c : 0; STORE32;               \\\n    cur = 0; while (++i < MAX32) { STORE32; }  \\\n    if (c < 0) mbedtls_ecp_fix_negative(N, c, bits);\n\n/*\n * If the result is negative, we get it in the form\n * c * 2^bits + N, with c negative and N positive shorter than 'bits'\n */\nstatic void mbedtls_ecp_fix_negative(mbedtls_mpi *N, signed char c, size_t bits)\n{\n    size_t i;\n\n    /* Set N := 2^bits - 1 - N. We know that 0 <= N < 2^bits, so\n     * set the absolute value to 0xfff...fff - N. There is no carry\n     * since we're subtracting from all-bits-one.  */\n    for (i = 0; i <= bits / 8 / sizeof(mbedtls_mpi_uint); i++) {\n        N->p[i] = ~(mbedtls_mpi_uint) 0 - N->p[i];\n    }\n    /* Add 1, taking care of the carry. */\n    i = 0;\n    do {\n        ++N->p[i];\n    } while (N->p[i++] == 0 && i <= bits / 8 / sizeof(mbedtls_mpi_uint));\n    /* Invert the sign.\n     * Now N = N0 - 2^bits where N0 is the initial value of N. */\n    N->s = -1;\n\n    /* Add |c| * 2^bits to the absolute value. Since c and N are\n     * negative, this adds c * 2^bits. */\n    mbedtls_mpi_uint msw = (mbedtls_mpi_uint) -c;\n#if defined(MBEDTLS_HAVE_INT64)\n    if (bits == 224) {\n        msw <<= 32;\n    }\n#endif\n    N->p[bits / 8 / sizeof(mbedtls_mpi_uint)] += msw;\n}\n\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)\n/*\n * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)\n */\nstatic int ecp_mod_p224(mbedtls_mpi *N)\n{\n    INIT(224);\n\n    SUB(7); SUB(11);               NEXT;      // A0 += -A7 - A11\n    SUB(8); SUB(12);               NEXT;      // A1 += -A8 - A12\n    SUB(9); SUB(13);               NEXT;      // A2 += -A9 - A13\n    SUB(10); ADD(7); ADD(11);    NEXT;        // A3 += -A10 + A7 + A11\n    SUB(11); ADD(8); ADD(12);    NEXT;        // A4 += -A11 + A8 + A12\n    SUB(12); ADD(9); ADD(13);    NEXT;        // A5 += -A12 + A9 + A13\n    SUB(13); ADD(10);               LAST;     // A6 += -A13 + A10\n\ncleanup:\n    return ret;\n}\n#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)\n/*\n * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)\n */\nstatic int ecp_mod_p256(mbedtls_mpi *N)\n{\n    INIT(256);\n\n    ADD(8); ADD(9);\n    SUB(11); SUB(12); SUB(13); SUB(14);             NEXT;         // A0\n\n    ADD(9); ADD(10);\n    SUB(12); SUB(13); SUB(14); SUB(15);             NEXT;         // A1\n\n    ADD(10); ADD(11);\n    SUB(13); SUB(14); SUB(15);                        NEXT;       // A2\n\n    ADD(11); ADD(11); ADD(12); ADD(12); ADD(13);\n    SUB(15); SUB(8); SUB(9);                        NEXT;         // A3\n\n    ADD(12); ADD(12); ADD(13); ADD(13); ADD(14);\n    SUB(9); SUB(10);                                   NEXT;      // A4\n\n    ADD(13); ADD(13); ADD(14); ADD(14); ADD(15);\n    SUB(10); SUB(11);                                   NEXT;     // A5\n\n    ADD(14); ADD(14); ADD(15); ADD(15); ADD(14); ADD(13);\n    SUB(8); SUB(9);                                   NEXT;       // A6\n\n    ADD(15); ADD(15); ADD(15); ADD(8);\n    SUB(10); SUB(11); SUB(12); SUB(13);             LAST;         // A7\n\ncleanup:\n    return ret;\n}\n#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\n/*\n * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)\n */\nstatic int ecp_mod_p384(mbedtls_mpi *N)\n{\n    INIT(384);\n\n    ADD(12); ADD(21); ADD(20);\n    SUB(23);                                              NEXT;   // A0\n\n    ADD(13); ADD(22); ADD(23);\n    SUB(12); SUB(20);                                   NEXT;     // A2\n\n    ADD(14); ADD(23);\n    SUB(13); SUB(21);                                   NEXT;     // A2\n\n    ADD(15); ADD(12); ADD(20); ADD(21);\n    SUB(14); SUB(22); SUB(23);                        NEXT;       // A3\n\n    ADD(21); ADD(21); ADD(16); ADD(13); ADD(12); ADD(20); ADD(22);\n    SUB(15); SUB(23); SUB(23);                        NEXT;       // A4\n\n    ADD(22); ADD(22); ADD(17); ADD(14); ADD(13); ADD(21); ADD(23);\n    SUB(16);                                              NEXT;   // A5\n\n    ADD(23); ADD(23); ADD(18); ADD(15); ADD(14); ADD(22);\n    SUB(17);                                              NEXT;   // A6\n\n    ADD(19); ADD(16); ADD(15); ADD(23);\n    SUB(18);                                              NEXT;   // A7\n\n    ADD(20); ADD(17); ADD(16);\n    SUB(19);                                              NEXT;   // A8\n\n    ADD(21); ADD(18); ADD(17);\n    SUB(20);                                              NEXT;   // A9\n\n    ADD(22); ADD(19); ADD(18);\n    SUB(21);                                              NEXT;   // A10\n\n    ADD(23); ADD(20); ADD(19);\n    SUB(22);                                              LAST;   // A11\n\ncleanup:\n    return ret;\n}\n#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */\n\n#undef A\n#undef LOAD32\n#undef STORE32\n#undef MAX32\n#undef INIT\n#undef NEXT\n#undef LAST\n\n#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED ||\n          MBEDTLS_ECP_DP_SECP256R1_ENABLED ||\n          MBEDTLS_ECP_DP_SECP384R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)\n/*\n * Here we have an actual Mersenne prime, so things are more straightforward.\n * However, chunks are aligned on a 'weird' boundary (521 bits).\n */\n\n/* Size of p521 in terms of mbedtls_mpi_uint */\n#define P521_WIDTH      (521 / 8 / sizeof(mbedtls_mpi_uint) + 1)\n\n/* Bits to keep in the most significant mbedtls_mpi_uint */\n#define P521_MASK       0x01FF\n\n/*\n * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5)\n * Write N as A1 + 2^521 A0, return A0 + A1\n */\nstatic int ecp_mod_p521(mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t i;\n    mbedtls_mpi M;\n    mbedtls_mpi_uint Mp[P521_WIDTH + 1];\n    /* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits:\n     * we need to hold bits 513 to 1056, which is 34 limbs, that is\n     * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */\n\n    if (N->n < P521_WIDTH) {\n        return 0;\n    }\n\n    /* M = A1 */\n    M.s = 1;\n    M.n = N->n - (P521_WIDTH - 1);\n    if (M.n > P521_WIDTH + 1) {\n        M.n = P521_WIDTH + 1;\n    }\n    M.p = Mp;\n    memcpy(Mp, N->p + P521_WIDTH - 1, M.n * sizeof(mbedtls_mpi_uint));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, 521 % (8 * sizeof(mbedtls_mpi_uint))));\n\n    /* N = A0 */\n    N->p[P521_WIDTH - 1] &= P521_MASK;\n    for (i = P521_WIDTH; i < N->n; i++) {\n        N->p[i] = 0;\n    }\n\n    /* N = A0 + A1 */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(N, N, &M));\n\ncleanup:\n    return ret;\n}\n\n#undef P521_WIDTH\n#undef P521_MASK\n#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */\n\n#endif /* MBEDTLS_ECP_NIST_OPTIM */\n\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n\n/* Size of p255 in terms of mbedtls_mpi_uint */\n#define P255_WIDTH      (255 / 8 / sizeof(mbedtls_mpi_uint) + 1)\n\n/*\n * Fast quasi-reduction modulo p255 = 2^255 - 19\n * Write N as A0 + 2^256 A1, return A0 + 38 * A1\n */\nstatic int ecp_mod_p255(mbedtls_mpi *N)\n{\n    mbedtls_mpi_uint Mp[P255_WIDTH];\n\n    /* Helper references for top part of N */\n    mbedtls_mpi_uint * const NT_p = N->p + P255_WIDTH;\n    const size_t NT_n = N->n - P255_WIDTH;\n    if (N->n <= P255_WIDTH) {\n        return 0;\n    }\n    if (NT_n > P255_WIDTH) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    /* Split N as N + 2^256 M */\n    memcpy(Mp,   NT_p, sizeof(mbedtls_mpi_uint) * NT_n);\n    memset(NT_p, 0,    sizeof(mbedtls_mpi_uint) * NT_n);\n\n    /* N = A0 + 38 * A1 */\n    mbedtls_mpi_core_mla(N->p, P255_WIDTH + 1,\n                         Mp, NT_n,\n                         38);\n\n    return 0;\n}\n#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n\n/* Size of p448 in terms of mbedtls_mpi_uint */\n#define P448_WIDTH      (448 / 8 / sizeof(mbedtls_mpi_uint))\n\n/* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */\n#define DIV_ROUND_UP(X, Y) (((X) + (Y) -1) / (Y))\n#define P224_SIZE        (224 / 8)\n#define P224_WIDTH_MIN   (P224_SIZE / sizeof(mbedtls_mpi_uint))\n#define P224_WIDTH_MAX   DIV_ROUND_UP(P224_SIZE, sizeof(mbedtls_mpi_uint))\n#define P224_UNUSED_BITS ((P224_WIDTH_MAX * sizeof(mbedtls_mpi_uint) * 8) - 224)\n\n/*\n * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1\n * Write N as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return\n * A0 + A1 + B1 + (B0 + B1) * 2^224.  This is different to the reference\n * implementation of Curve448, which uses its own special 56-bit limbs rather\n * than a generic bignum library.  We could squeeze some extra speed out on\n * 32-bit machines by splitting N up into 32-bit limbs and doing the\n * arithmetic using the limbs directly as we do for the NIST primes above,\n * but for 64-bit targets it should use half the number of operations if we do\n * the reduction with 224-bit limbs, since mpi_add_mpi will then use 64-bit adds.\n */\nstatic int ecp_mod_p448(mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t i;\n    mbedtls_mpi M, Q;\n    mbedtls_mpi_uint Mp[P448_WIDTH + 1], Qp[P448_WIDTH];\n\n    if (N->n <= P448_WIDTH) {\n        return 0;\n    }\n\n    /* M = A1 */\n    M.s = 1;\n    M.n = N->n - (P448_WIDTH);\n    if (M.n > P448_WIDTH) {\n        /* Shouldn't be called with N larger than 2^896! */\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n    M.p = Mp;\n    memset(Mp, 0, sizeof(Mp));\n    memcpy(Mp, N->p + P448_WIDTH, M.n * sizeof(mbedtls_mpi_uint));\n\n    /* N = A0 */\n    for (i = P448_WIDTH; i < N->n; i++) {\n        N->p[i] = 0;\n    }\n\n    /* N += A1 */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &M));\n\n    /* Q = B1, N += B1 */\n    Q = M;\n    Q.p = Qp;\n    memcpy(Qp, Mp, sizeof(Qp));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Q, 224));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &Q));\n\n    /* M = (B0 + B1) * 2^224, N += M */\n    if (sizeof(mbedtls_mpi_uint) > 4) {\n        Mp[P224_WIDTH_MIN] &= ((mbedtls_mpi_uint)-1) >> (P224_UNUSED_BITS);\n    }\n    for (i = P224_WIDTH_MAX; i < M.n; ++i) {\n        Mp[i] = 0;\n    }\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&M, &M, &Q));\n    M.n = P448_WIDTH + 1; /* Make room for shifted carry bit from the addition */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&M, 224));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &M));\n\ncleanup:\n    return ret;\n}\n#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n/*\n * Fast quasi-reduction modulo P = 2^s - R,\n * with R about 33 bits, used by the Koblitz curves.\n *\n * Write N as A0 + 2^224 A1, return A0 + R * A1.\n * Actually do two passes, since R is big.\n */\n#define P_KOBLITZ_MAX   (256 / 8 / sizeof(mbedtls_mpi_uint))      // Max limbs in P\n#define P_KOBLITZ_R     (8 / sizeof(mbedtls_mpi_uint))            // Limbs in R\nstatic inline int ecp_mod_koblitz(mbedtls_mpi *N, const mbedtls_mpi_uint *Rp, size_t p_limbs,\n                                  size_t adjust, size_t shift, mbedtls_mpi_uint mask)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t i;\n    mbedtls_mpi M, R;\n    mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1];\n\n    if (N->n < p_limbs) {\n        return 0;\n    }\n\n    /* Init R */\n    R.s = 1;\n    R.p = (mbedtls_mpi_uint *) Rp; /* R.p will not be modified so the cast is safe */\n    R.n = P_KOBLITZ_R;\n\n    /* Common setup for M */\n    M.s = 1;\n    M.p = Mp;\n\n    /* M = A1 */\n    M.n = (unsigned short) (N->n - (p_limbs - adjust));\n    if (M.n > p_limbs + adjust) {\n        M.n = (unsigned short) (p_limbs + adjust);\n    }\n    memset(Mp, 0, sizeof(Mp));\n    memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint));\n    if (shift != 0) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, shift));\n    }\n    M.n += R.n; /* Make room for multiplication by R */\n\n    /* N = A0 */\n    if (mask != 0) {\n        N->p[p_limbs - 1] &= mask;\n    }\n    for (i = p_limbs; i < N->n; i++) {\n        N->p[i] = 0;\n    }\n\n    /* N = A0 + R * A1 */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&M, &M, &R));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(N, N, &M));\n\n    /* Second pass */\n\n    /* M = A1 */\n    M.n = (unsigned short) (N->n - (p_limbs - adjust));\n    if (M.n > p_limbs + adjust) {\n        M.n = (unsigned short) (p_limbs + adjust);\n    }\n    memset(Mp, 0, sizeof(Mp));\n    memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint));\n    if (shift != 0) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, shift));\n    }\n    M.n += R.n; /* Make room for multiplication by R */\n\n    /* N = A0 */\n    if (mask != 0) {\n        N->p[p_limbs - 1] &= mask;\n    }\n    for (i = p_limbs; i < N->n; i++) {\n        N->p[i] = 0;\n    }\n\n    /* N = A0 + R * A1 */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&M, &M, &R));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(N, N, &M));\n\ncleanup:\n    return ret;\n}\n#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) ||\n          MBEDTLS_ECP_DP_SECP224K1_ENABLED) ||\n          MBEDTLS_ECP_DP_SECP256K1_ENABLED) */\n\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)\n/*\n * Fast quasi-reduction modulo p192k1 = 2^192 - R,\n * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9\n */\nstatic int ecp_mod_p192k1(mbedtls_mpi *N)\n{\n    static const mbedtls_mpi_uint Rp[] = {\n        MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00,\n                                  0x00)\n    };\n\n    return ecp_mod_koblitz(N, Rp, 192 / 8 / sizeof(mbedtls_mpi_uint), 0, 0,\n                           0);\n}\n#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)\n/*\n * Fast quasi-reduction modulo p224k1 = 2^224 - R,\n * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93\n */\nstatic int ecp_mod_p224k1(mbedtls_mpi *N)\n{\n    static const mbedtls_mpi_uint Rp[] = {\n        MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00,\n                                  0x00)\n    };\n\n#if defined(MBEDTLS_HAVE_INT64)\n    return ecp_mod_koblitz(N, Rp, 4, 1, 32, 0xFFFFFFFF);\n#else\n    return ecp_mod_koblitz(N, Rp, 224 / 8 / sizeof(mbedtls_mpi_uint), 0, 0,\n                           0);\n#endif\n}\n\n#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n/*\n * Fast quasi-reduction modulo p256k1 = 2^256 - R,\n * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1\n */\nstatic int ecp_mod_p256k1(mbedtls_mpi *N)\n{\n    static const mbedtls_mpi_uint Rp[] = {\n        MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00,\n                                  0x00)\n    };\n    return ecp_mod_koblitz(N, Rp, 256 / 8 / sizeof(mbedtls_mpi_uint), 0, 0,\n                           0);\n}\n#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */\n\n#if defined(MBEDTLS_TEST_HOOKS)\n\nMBEDTLS_STATIC_TESTABLE\nmbedtls_ecp_variant mbedtls_ecp_get_variant(void)\n{\n    return MBEDTLS_ECP_VARIANT_WITH_MPI_STRUCT;\n}\n\n#endif /* MBEDTLS_TEST_HOOKS */\n\n#endif /* !MBEDTLS_ECP_ALT */\n\n#endif /* MBEDTLS_ECP_LIGHT */\n#endif /* MBEDTLS_ECP_WITH_MPI_UINT */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ecp_curves_new.c",
    "content": "/*\n *  Elliptic curves over GF(p): curve-specific data and functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_ECP_WITH_MPI_UINT)\n\n#if defined(MBEDTLS_ECP_LIGHT)\n\n#include \"mbedtls/ecp.h\"\n#include \"mbedtls/platform.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include \"mbedtls/platform.h\"\n\n#include \"constant_time_internal.h\"\n\n#include \"bn_mul.h\"\n#include \"bignum_core.h\"\n#include \"ecp_invasive.h\"\n\n#include <string.h>\n\n#if !defined(MBEDTLS_ECP_ALT)\n\n#define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) }\n\n#define ECP_MPI_INIT_ARRAY(x)   \\\n    ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint))\n\n#define ECP_POINT_INIT_XY_Z0(x, y) { \\\n        ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(NULL, 0) }\n#define ECP_POINT_INIT_XY_Z1(x, y) { \\\n        ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(mpi_one, 1) }\n\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)   ||   \\\n    defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)   ||   \\\n    defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)   ||   \\\n    defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n/* For these curves, we build the group parameters dynamically. */\n#define ECP_LOAD_GROUP\nstatic mbedtls_mpi_uint mpi_one[] = { 1 };\n#endif\n\n/*\n * Note: the constants are in little-endian order\n * to be directly usable in MPIs\n */\n\n/*\n * Domain parameters for secp192r1\n */\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\nstatic const mbedtls_mpi_uint secp192r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp192r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64),\n};\nstatic const mbedtls_mpi_uint secp192r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18),\n};\nstatic const mbedtls_mpi_uint secp192r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07),\n};\nstatic const mbedtls_mpi_uint secp192r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp192r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x9E, 0xE3, 0x60, 0x59, 0xD1, 0xC4, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBD, 0x22, 0xD7, 0x2D, 0x07, 0xBD, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x2A, 0xCF, 0x33, 0xF0, 0xBE, 0xD1, 0xED),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x71, 0x4B, 0xA8, 0xED, 0x7E, 0xC9, 0x1A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x2A, 0xF6, 0xDF, 0x0E, 0xE8, 0x4C, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x35, 0xF7, 0x8A, 0xC3, 0xEC, 0xDE, 0x1E),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0xC2, 0x1D, 0x32, 0x8F, 0x10, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x2D, 0x17, 0xF3, 0xE4, 0xFE, 0xD8, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x45, 0x10, 0x70, 0x2C, 0x3E, 0x52, 0x3E),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF1, 0x04, 0x5D, 0xEE, 0xD4, 0x56, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xB7, 0x38, 0x27, 0x61, 0xAA, 0x81, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0xD7, 0x0E, 0x29, 0x0E, 0x11, 0x14),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x35, 0x52, 0xC6, 0x31, 0xB7, 0x27, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xD4, 0x15, 0x98, 0x0F, 0xE7, 0xF3, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x31, 0x70, 0x35, 0x09, 0xA0, 0x2B, 0xC2),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x75, 0xA7, 0x4C, 0x88, 0xCF, 0x5B, 0xE4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x17, 0x48, 0x8D, 0xF2, 0xF0, 0x86, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCF, 0xFE, 0x6B, 0xB0, 0xA5, 0x06, 0xAB),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x6A, 0xDC, 0x9A, 0x6D, 0x7B, 0x47, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xFC, 0x51, 0x12, 0x62, 0x66, 0x0B, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x40, 0x93, 0xA0, 0xB5, 0x5A, 0x58, 0xD7),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCB, 0xAF, 0xDC, 0x0B, 0xA1, 0x26, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x36, 0x9D, 0xA3, 0xD7, 0x3B, 0xAD, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x3B, 0x05, 0x9A, 0xA8, 0xAA, 0x69, 0xB2),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD9, 0xD1, 0x4D, 0x4A, 0x6E, 0x96, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x66, 0x32, 0x39, 0xC6, 0x57, 0x7D, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xA0, 0x36, 0xC2, 0x45, 0xF9, 0x00, 0x62),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xEF, 0x59, 0x46, 0xDC, 0x60, 0xD9, 0x8F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xB0, 0xE9, 0x41, 0xA4, 0x87, 0x76, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xD4, 0x0E, 0xB2, 0xFA, 0x16, 0x56, 0xDC),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x62, 0xD2, 0xB1, 0x34, 0xB2, 0xF1, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xED, 0x55, 0xC5, 0x47, 0xB5, 0x07, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF6, 0x2F, 0x94, 0xC3, 0xDD, 0x54, 0x2F),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xA6, 0xD4, 0x8C, 0xA9, 0xCE, 0x4D, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x4B, 0x46, 0xCC, 0xB2, 0x55, 0xC8, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x31, 0xED, 0x89, 0x65, 0x59, 0x55),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x0A, 0xD1, 0x1A, 0xC5, 0xF6, 0xEA, 0x43),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xFC, 0x0C, 0x1A, 0xFB, 0xA0, 0xC8, 0x70),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xFD, 0x53, 0x6F, 0x6D, 0xBF, 0xBA, 0xAF),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xB0, 0x7D, 0x83, 0x96, 0xE3, 0xCB, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x6E, 0x55, 0x2C, 0x20, 0x53, 0x2F, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x66, 0x00, 0x17, 0x08, 0xFE, 0xAC, 0x31),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x12, 0x97, 0x3A, 0xC7, 0x57, 0x45, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x25, 0x99, 0x00, 0xF6, 0x97, 0xB4, 0x64),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x74, 0xE6, 0xE6, 0xA3, 0xDF, 0x9C, 0xCC),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xF4, 0x76, 0xD5, 0x5F, 0x2A, 0xFD, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x80, 0x7E, 0x3E, 0xE5, 0xE8, 0xD6, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xAD, 0x1E, 0x70, 0x79, 0x3E, 0x3D, 0x83),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x15, 0xBB, 0xB3, 0x42, 0x6A, 0xA1, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x58, 0xCB, 0x43, 0x25, 0x00, 0x14, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x4E, 0x93, 0x11, 0xE0, 0x32, 0x54, 0x98),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x52, 0xA2, 0xB4, 0x57, 0x32, 0xB9, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x43, 0xA1, 0xB1, 0xFB, 0x01, 0xE1, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xFB, 0x5A, 0x11, 0xB8, 0xC2, 0x03, 0xE5),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x2B, 0x71, 0x26, 0x4E, 0x7C, 0xC5, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF5, 0xD3, 0xA8, 0xE4, 0x95, 0x48, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAE, 0xD9, 0x5D, 0x9F, 0x6A, 0x22, 0xAD),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xCC, 0xA3, 0x4D, 0xA0, 0x1C, 0x34, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x3C, 0x62, 0xF8, 0x5E, 0xA6, 0x58, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x6E, 0x66, 0x8A, 0x3D, 0x17, 0xFF, 0x0F),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xCD, 0xA8, 0xDD, 0xD1, 0x20, 0x5C, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xFE, 0x17, 0xE2, 0xCF, 0xEA, 0x63, 0xDE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x51, 0xC9, 0x16, 0xDE, 0xB4, 0xB2, 0xDD),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBE, 0x12, 0xD7, 0xA3, 0x0A, 0x50, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x87, 0xC5, 0x8A, 0x76, 0x57, 0x07, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x1F, 0xC6, 0x1B, 0x66, 0xC4, 0x3D, 0x8A),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xA4, 0x85, 0x13, 0x8F, 0xA7, 0x35, 0x19),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x0D, 0xFD, 0xFF, 0x1B, 0xD1, 0xD6, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x7A, 0xD0, 0xC3, 0xB4, 0xEF, 0x39, 0x66),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xFE, 0xA5, 0x9C, 0x34, 0x30, 0x49, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xC5, 0x39, 0x26, 0x06, 0xE3, 0x01, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x2B, 0x66, 0xFC, 0x95, 0x5F, 0x35, 0xF7),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xCF, 0x54, 0x63, 0x99, 0x57, 0x05, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x6F, 0x00, 0x5F, 0x65, 0x08, 0x47, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x2A, 0x90, 0x6D, 0x67, 0xC6, 0xBC, 0x45),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x4D, 0x88, 0x0A, 0x35, 0x9E, 0x33, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x17, 0x0C, 0xF8, 0xE1, 0x7A, 0x49, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x44, 0x06, 0x8F, 0x0B, 0x70, 0x2F, 0x71),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4B, 0xCB, 0xF9, 0x8E, 0x6A, 0xDA, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x43, 0xA1, 0x3F, 0xCE, 0x17, 0xD2, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x0D, 0xD2, 0x6C, 0x82, 0x37, 0xE5, 0xFC),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x3C, 0xF4, 0x92, 0xB4, 0x8A, 0x95, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x96, 0xF1, 0x0A, 0x34, 0x2F, 0x74, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0xAA, 0xBA, 0x86, 0x77, 0x4F, 0xA2),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x7F, 0xEF, 0x60, 0x50, 0x80, 0xD7, 0xD4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xAC, 0xC9, 0xFE, 0xEC, 0x0A, 0x1A, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x2F, 0xBE, 0x91, 0xD7, 0xB7, 0x38, 0x48),\n};\nstatic const mbedtls_mpi_uint secp192r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xAE, 0x85, 0x98, 0xFE, 0x05, 0x7F, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBE, 0xFD, 0x11, 0x31, 0x3D, 0x14, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x75, 0xE8, 0x30, 0x01, 0xCB, 0x9B, 0x1C),\n};\nstatic const mbedtls_ecp_point secp192r1_T[16] = {\n    ECP_POINT_INIT_XY_Z1(secp192r1_T_0_X, secp192r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_1_X, secp192r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_2_X, secp192r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_3_X, secp192r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_4_X, secp192r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_5_X, secp192r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_6_X, secp192r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_7_X, secp192r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_8_X, secp192r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_9_X, secp192r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_10_X, secp192r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_11_X, secp192r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_12_X, secp192r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_13_X, secp192r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_14_X, secp192r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp192r1_T_15_X, secp192r1_T_15_Y),\n};\n#else\n#define secp192r1_T NULL\n#endif\n#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */\n\n/*\n * Domain parameters for secp224r1\n */\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)\nstatic const mbedtls_mpi_uint secp224r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C),\n    MBEDTLS_BYTES_TO_T_UINT_4(0x85, 0x0A, 0x05, 0xB4),\n};\nstatic const mbedtls_mpi_uint secp224r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_4(0xBD, 0x0C, 0x0E, 0xB7),\n};\nstatic const mbedtls_mpi_uint secp224r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_4(0x88, 0x63, 0x37, 0xBD),\n};\nstatic const mbedtls_mpi_uint secp224r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF),\n};\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp224r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x0C, 0x0E, 0xB7, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x63, 0x37, 0xBD, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF9, 0xB8, 0xD0, 0x3D, 0xD2, 0xD3, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xFD, 0x99, 0x26, 0x19, 0xFE, 0x13, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x0E, 0x4C, 0x48, 0x7C, 0xA2, 0x17, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA3, 0x13, 0x57, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x16, 0x5C, 0x8F, 0xAA, 0xED, 0x0F, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xC5, 0x43, 0x34, 0x93, 0x05, 0x2A, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE3, 0x6C, 0xCA, 0xC6, 0x14, 0xC2, 0x25),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x43, 0x6C, 0xD7, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x5A, 0x98, 0x1E, 0xC8, 0xA5, 0x42, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x49, 0x56, 0x78, 0xF8, 0xEF, 0xED, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xBB, 0x64, 0xB6, 0x4C, 0x54, 0x5F, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x0C, 0x33, 0xCC, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x79, 0xCB, 0x2E, 0x08, 0xFF, 0xD8, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x1F, 0xD4, 0xD7, 0x57, 0xE9, 0x39, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xD6, 0x3B, 0x0A, 0x1C, 0x87, 0xB7, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x30, 0xD8, 0x05, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x79, 0x74, 0x9A, 0xE6, 0xBB, 0xC2, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x5B, 0xA6, 0x67, 0xC1, 0x91, 0xE7, 0x64),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xDF, 0x38, 0x82, 0x19, 0x2C, 0x4C, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x2E, 0x39, 0xC5, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x36, 0x78, 0x4E, 0xAE, 0x5B, 0x02, 0x76),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF6, 0x8B, 0xF8, 0xF4, 0x92, 0x6B, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x4D, 0x71, 0x35, 0xE7, 0x0C, 0x2C, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xA5, 0x1F, 0xAE, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x1C, 0x4B, 0xDF, 0x5B, 0xF2, 0x51, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0xB1, 0x5A, 0xC6, 0x0F, 0x0E, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x24, 0x09, 0x62, 0xAF, 0xFC, 0xDB, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xE1, 0x80, 0x55, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x82, 0xFE, 0xAD, 0xC3, 0xE5, 0xCF, 0xD8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xA2, 0x62, 0x17, 0x76, 0xF0, 0x5A, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB8, 0xE5, 0xAC, 0xB7, 0x66, 0x38, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xFD, 0x86, 0x05, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0x0C, 0x3C, 0xD1, 0x66, 0xB0, 0xF1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x59, 0xB4, 0x8D, 0x90, 0x10, 0xB7, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x47, 0x9B, 0xE6, 0x55, 0x8A, 0xE4, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x49, 0xDB, 0x78, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x97, 0xED, 0xDE, 0xFF, 0xB3, 0xDF, 0x48),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xB9, 0x83, 0xB7, 0xEB, 0xBE, 0x40, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xD3, 0xD3, 0xCD, 0x0E, 0x82, 0x79, 0x3D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x83, 0x1B, 0xF0, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x22, 0xBB, 0x54, 0xD3, 0x31, 0x56, 0xFC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0xE5, 0xE0, 0x89, 0x96, 0x8E, 0x71),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xEF, 0x0A, 0xED, 0xD0, 0x11, 0x4A, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x00, 0x57, 0x27, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCA, 0x3D, 0xF7, 0x64, 0x9B, 0x6E, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xE3, 0x70, 0x6B, 0x41, 0xD7, 0xED, 0x8F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x44, 0x44, 0x80, 0xCE, 0x13, 0x37, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x73, 0x80, 0x79, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x4D, 0x70, 0x7D, 0x31, 0x0F, 0x1C, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x35, 0x88, 0x47, 0xC4, 0x24, 0x78, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF0, 0xCD, 0x91, 0x81, 0xB3, 0xDE, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xCE, 0xC6, 0xF7, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x9C, 0x2D, 0xE8, 0xD2, 0x00, 0x8F, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x5E, 0x7C, 0x0E, 0x0C, 0x6E, 0x58, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x81, 0x21, 0xCE, 0x43, 0xF4, 0x24, 0x3D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xBC, 0xF0, 0xF4, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x10, 0xC2, 0x74, 0x4A, 0x8F, 0x8A, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x67, 0xF4, 0x2B, 0x38, 0x2B, 0x35, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0C, 0xA9, 0xFA, 0x77, 0x5C, 0xBD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x19, 0x2B, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x3E, 0x96, 0x22, 0x53, 0xE1, 0xE9, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x13, 0xBC, 0xA1, 0x16, 0xEC, 0x01, 0x1A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x00, 0xC9, 0x7A, 0xC3, 0x73, 0xA5, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xF4, 0x5E, 0xC1, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x95, 0xD6, 0xD9, 0x32, 0x30, 0x2B, 0xD0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x42, 0x09, 0x05, 0x61, 0x2A, 0x7E, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x84, 0xA2, 0x05, 0x88, 0x64, 0x65, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2D, 0x90, 0xB3, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE7, 0x2E, 0x85, 0x55, 0x80, 0x7C, 0x79),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC1, 0xAC, 0x78, 0xB4, 0xAF, 0xFB, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xC3, 0x28, 0x8E, 0x79, 0x18, 0x1F, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x46, 0xCF, 0x49, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x5F, 0xA8, 0x6C, 0x46, 0x83, 0x43, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xA9, 0x93, 0x11, 0xB6, 0x07, 0x57, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x2A, 0x9D, 0x03, 0x89, 0x7E, 0xD7, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x8C, 0x62, 0xCF, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x2C, 0x13, 0x59, 0xCC, 0xFA, 0x84, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB9, 0x48, 0xBC, 0x57, 0xC7, 0xB3, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x0A, 0x38, 0x24, 0x2E, 0x3A, 0x28, 0x25),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x0A, 0x43, 0xB8, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x25, 0xAB, 0xC1, 0xEE, 0x70, 0x3C, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xDB, 0x45, 0x1D, 0x4A, 0x80, 0x75, 0x35),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1F, 0x4D, 0x2D, 0x9A, 0x05, 0xF4, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x10, 0xF0, 0x5A, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x95, 0xE1, 0xDC, 0x15, 0x86, 0xC3, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xDC, 0x27, 0xD1, 0x56, 0xA1, 0x14, 0x0D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x0B, 0xD6, 0x77, 0x4E, 0x44, 0xA2, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x42, 0x71, 0x1F, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x86, 0xB2, 0xB0, 0xC8, 0x2F, 0x7B, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xEF, 0xCB, 0xDB, 0xBC, 0x9E, 0x3B, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x03, 0x86, 0xDD, 0x5B, 0xF5, 0x8D, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x95, 0x79, 0xD6, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x32, 0x14, 0xDA, 0x9B, 0x4F, 0x07, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x3E, 0xFB, 0x06, 0xEE, 0xA7, 0x40, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x1F, 0xDF, 0x71, 0x61, 0xFD, 0x8B, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x8B, 0xAB, 0x8B, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x34, 0xB3, 0xB4, 0xBC, 0x9F, 0xB0, 0x5E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x58, 0x48, 0xA8, 0x77, 0xBB, 0x13, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC6, 0xF7, 0x34, 0xCC, 0x89, 0x21, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x33, 0xDD, 0x1F, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x81, 0xEF, 0xA4, 0xF2, 0x10, 0x0B, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF7, 0x6E, 0x72, 0x4A, 0xDF, 0xDD, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x23, 0x0A, 0x53, 0x03, 0x16, 0x62, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x76, 0xFD, 0x3C, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x14, 0xA1, 0xFA, 0xA0, 0x18, 0xBE, 0x07),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2A, 0xE1, 0xD7, 0xB0, 0x6C, 0xA0, 0xDE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xC0, 0xB0, 0xC6, 0x63, 0x24, 0xCD, 0x4E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x38, 0x2C, 0xB1, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCD, 0x7D, 0x20, 0x0C, 0xFE, 0xAC, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x9F, 0xA2, 0xB6, 0x45, 0xF7, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x99, 0xF3, 0xD2, 0x20, 0x02, 0xEB, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x5B, 0x7B, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xDD, 0x77, 0x91, 0x60, 0xEA, 0xFD, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xD3, 0xB5, 0xD6, 0x90, 0x17, 0x0E, 0x1A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xF4, 0x28, 0xC1, 0xF2, 0x53, 0xF6, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x58, 0xDC, 0x61, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x20, 0x01, 0xFB, 0xF1, 0xBD, 0x5F, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x7F, 0x06, 0xDA, 0x11, 0xCB, 0xBA, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x41, 0x00, 0xA4, 0x1B, 0x30, 0x33, 0x79),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xFF, 0x27, 0xCA, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_ecp_point secp224r1_T[16] = {\n    ECP_POINT_INIT_XY_Z1(secp224r1_T_0_X, secp224r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_1_X, secp224r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_2_X, secp224r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_3_X, secp224r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_4_X, secp224r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_5_X, secp224r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_6_X, secp224r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_7_X, secp224r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_8_X, secp224r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_9_X, secp224r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_10_X, secp224r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_11_X, secp224r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_12_X, secp224r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_13_X, secp224r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_14_X, secp224r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp224r1_T_15_X, secp224r1_T_15_Y),\n};\n#else\n#define secp224r1_T NULL\n#endif\n#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */\n\n/*\n * Domain parameters for secp256r1\n */\n#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)\nstatic const mbedtls_mpi_uint secp256r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp256r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A),\n};\nstatic const mbedtls_mpi_uint secp256r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B),\n};\nstatic const mbedtls_mpi_uint secp256r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F),\n};\nstatic const mbedtls_mpi_uint secp256r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),\n};\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp256r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xC8, 0xBA, 0x04, 0xB7, 0x4B, 0xD2, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC6, 0x23, 0x3A, 0xA0, 0x09, 0x3A, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x9D, 0x4C, 0xF9, 0x58, 0x23, 0xCC, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xED, 0x7B, 0x29, 0x87, 0x0F, 0xFA, 0x3C),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x69, 0xF2, 0x40, 0x0B, 0xA3, 0x98, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xA8, 0x48, 0x02, 0x0D, 0x1C, 0x12, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xAF, 0x09, 0x83, 0x80, 0xAA, 0x58, 0xA7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x12, 0xBE, 0x70, 0x94, 0x76, 0xE3, 0xE4),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x7D, 0xEF, 0x86, 0xFF, 0xE3, 0x37, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x86, 0x8B, 0x08, 0x27, 0x7C, 0xD7, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x54, 0x4C, 0x25, 0x4F, 0x9A, 0xFE, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xFD, 0xF0, 0x6D, 0x37, 0x03, 0x69, 0xD6),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xD5, 0xDA, 0xAD, 0x92, 0x49, 0xF0, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x73, 0x43, 0x9E, 0xAF, 0xA7, 0xD1, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x41, 0x07, 0xDF, 0x78, 0x95, 0x3E, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x3D, 0xD1, 0xE6, 0x3C, 0xA5, 0xE2, 0x20),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x6A, 0x5D, 0x52, 0x35, 0xD7, 0xBF, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xA2, 0xBE, 0x96, 0xF4, 0xF8, 0x02, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x20, 0x49, 0x54, 0xEA, 0xB3, 0x82, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0xDB, 0xEA, 0x02, 0xD1, 0x75, 0x1C, 0x62),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x85, 0xF4, 0x9E, 0x4C, 0xDC, 0x39, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x6D, 0xC4, 0x57, 0xD8, 0x03, 0x5D, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x7F, 0x2D, 0x52, 0x6F, 0xC9, 0xDA, 0x4F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x64, 0xFA, 0xB4, 0xFE, 0xA4, 0xC4, 0xD7),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x37, 0xB9, 0xC0, 0xAA, 0x59, 0xC6, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x58, 0xD9, 0xED, 0x58, 0x99, 0x65, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x7D, 0x26, 0x8C, 0x4A, 0xF9, 0x05, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x73, 0x9A, 0xC9, 0xE7, 0x46, 0xDC, 0x00),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xD0, 0x55, 0xDF, 0x00, 0x0A, 0xF5, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xBF, 0x56, 0x81, 0x2D, 0x20, 0xEB, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC1, 0x28, 0x52, 0xAB, 0xE3, 0xD1, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x34, 0x79, 0x45, 0x57, 0xA5, 0x12, 0x03),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCF, 0xB8, 0x7E, 0xF7, 0x92, 0x96, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x01, 0x8C, 0x0D, 0x23, 0xF2, 0xE3, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x2E, 0xE3, 0x84, 0x52, 0x7A, 0x34, 0x76),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xA1, 0xB0, 0x15, 0x90, 0xE2, 0x53, 0x3C),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x98, 0xE7, 0xFA, 0xA5, 0x7D, 0x8B, 0x53),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x35, 0xD2, 0x00, 0xD1, 0x1B, 0x9F, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x69, 0x08, 0x9A, 0x72, 0xF0, 0xA9, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xFE, 0x0E, 0x14, 0xDA, 0x7C, 0x0E, 0xD3),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF6, 0xE8, 0xF8, 0x87, 0xF7, 0xFC, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xBE, 0x7F, 0x3F, 0x7A, 0x2B, 0xD7, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x32, 0xF2, 0x2D, 0x94, 0x6D, 0x42, 0xFD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x9A, 0xE3, 0x5F, 0x42, 0xBB, 0x84, 0xED),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x95, 0x29, 0x73, 0xA1, 0x67, 0x3E, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x30, 0x54, 0x35, 0x8E, 0x0A, 0xDD, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xD7, 0xA1, 0x97, 0x61, 0x3B, 0xF8, 0x0C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x33, 0x3C, 0x58, 0x55, 0x34, 0x23, 0xA3),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x5D, 0x16, 0x5F, 0x7B, 0xBC, 0xBB, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xEE, 0x4E, 0x8A, 0xC1, 0x51, 0xCC, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0D, 0x4D, 0x1B, 0x53, 0x23, 0x1D, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x2A, 0x38, 0x66, 0x52, 0x84, 0xE1, 0x95),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x9B, 0x83, 0x0A, 0x81, 0x4F, 0xAD, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xFF, 0x42, 0x41, 0x6E, 0xA9, 0xA2, 0xA0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA1, 0x4F, 0x1F, 0x89, 0x82, 0xAA, 0x3E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xB8, 0x0F, 0x6B, 0x8F, 0x8C, 0xD6, 0x68),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0xB3, 0xBB, 0x51, 0x69, 0xA2, 0x11, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x4F, 0x0F, 0x8D, 0xBD, 0x26, 0x0F, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xCB, 0xEC, 0x6B, 0x34, 0xC3, 0x3D, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x5D, 0x1E, 0x10, 0xD5, 0x44, 0xE2, 0x54),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x9E, 0xB1, 0xF1, 0x6E, 0x4C, 0xAD, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE3, 0xC2, 0x58, 0xC0, 0xFB, 0x34, 0x43),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x9C, 0xDF, 0x35, 0x07, 0x41, 0xBD, 0x19),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x10, 0xEC, 0x0E, 0xEC, 0xBB, 0xD6),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xCF, 0xEF, 0x3F, 0x83, 0x1A, 0x88, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x29, 0xB5, 0xB9, 0xE0, 0xC9, 0xA3, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x46, 0x1E, 0x77, 0xCD, 0x7E, 0xB3, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x21, 0xD0, 0xD4, 0xA3, 0x16, 0x08, 0xEE),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xCA, 0xA8, 0xB3, 0xBF, 0x29, 0x99, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF2, 0x05, 0xC1, 0xCF, 0x5D, 0x91, 0x48),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x01, 0x49, 0xDB, 0x82, 0xDF, 0x5F, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x06, 0x90, 0xAD, 0xE3, 0x38, 0xA4, 0xC4),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xD2, 0x3A, 0xE8, 0x03, 0xC5, 0x6D, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x35, 0xD0, 0xAE, 0x1D, 0x7A, 0x9F, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x1E, 0xD2, 0xCB, 0xAC, 0x88, 0x27, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x9C, 0xE0, 0x31, 0xDD, 0x99, 0x86),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF9, 0x9B, 0x32, 0x96, 0x41, 0x58, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x5A, 0x2A, 0xB8, 0x96, 0x0E, 0xB2, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x78, 0x2C, 0xC7, 0x08, 0x99, 0x19, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x59, 0x28, 0xE9, 0x84, 0x54, 0xE6, 0x16),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x38, 0x30, 0xDB, 0x70, 0x2C, 0x0A, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x5C, 0x9D, 0xE9, 0xD5, 0x46, 0x0B, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x0B, 0x60, 0x4B, 0x37, 0x7D, 0xB9, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x24, 0xF3, 0x3D, 0x79, 0x7F, 0x6C, 0x18),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7F, 0xE5, 0x1C, 0x4F, 0x60, 0x24, 0xF7, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xD8, 0xE2, 0x91, 0x7F, 0x89, 0x49, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xA7, 0x2E, 0x8D, 0x6A, 0xB3, 0x39, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x89, 0xB5, 0x9A, 0xB8, 0x8D, 0x42, 0x9C),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x45, 0xE6, 0x4B, 0x3F, 0x4F, 0x1E, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x65, 0x5E, 0x59, 0x22, 0xCC, 0x72, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x93, 0x1A, 0x27, 0x1E, 0x34, 0xC5, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xF2, 0xA5, 0x58, 0x5C, 0x15, 0x2E, 0xC6),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x7F, 0xBA, 0x58, 0x5A, 0x84, 0x6F, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA6, 0x36, 0x7E, 0xDC, 0xF7, 0xE1, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x4D, 0xAA, 0xEE, 0x57, 0x76, 0x3A, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x7E, 0x26, 0x18, 0x22, 0x23, 0x9F, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x4C, 0x64, 0xC7, 0x55, 0x02, 0x3F, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x02, 0x90, 0xBB, 0xC3, 0xEC, 0x30, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x6F, 0x64, 0xF4, 0x16, 0x69, 0x48, 0xA4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x44, 0x9C, 0x95, 0x0C, 0x7D, 0x67, 0x5E),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x91, 0x8B, 0xD8, 0xD0, 0xD7, 0xE7, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF9, 0x48, 0x62, 0x6F, 0xA8, 0x93, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x3A, 0x99, 0x02, 0xD5, 0x0B, 0x3D, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xD3, 0x00, 0x31, 0xE6, 0x0C, 0x9F, 0x44),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xB2, 0xAA, 0xFD, 0x88, 0x15, 0xDF, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0x35, 0x27, 0x31, 0x44, 0xCD, 0xC0, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xF8, 0x91, 0xA5, 0x71, 0x94, 0x84, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xCB, 0xD0, 0x93, 0xE9, 0x88, 0xDA, 0xE4),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC6, 0x39, 0x16, 0x5D, 0xA3, 0x1E, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x07, 0x37, 0x26, 0x36, 0x2A, 0xFE, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xBC, 0xF3, 0xD0, 0xDE, 0x50, 0xFC, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x2E, 0x06, 0x10, 0x15, 0x4D, 0xFA, 0xF7),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x65, 0x69, 0x5B, 0x66, 0xA2, 0x75, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x16, 0x00, 0x5A, 0xB0, 0x30, 0x25, 0x1A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xFB, 0x86, 0x42, 0x80, 0xC1, 0xC4, 0x76),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x1D, 0x83, 0x8E, 0x94, 0x01, 0x5F, 0x82),\n};\nstatic const mbedtls_mpi_uint secp256r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x37, 0x70, 0xEF, 0x1F, 0xA1, 0xF0, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x5B, 0xCE, 0xC4, 0x9B, 0x6F, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x11, 0x11, 0x24, 0x4F, 0x4C, 0x79, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x3A, 0x72, 0xBC, 0xFE, 0x72, 0x58, 0x43),\n};\nstatic const mbedtls_ecp_point secp256r1_T[16] = {\n    ECP_POINT_INIT_XY_Z1(secp256r1_T_0_X, secp256r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_1_X, secp256r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_2_X, secp256r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_3_X, secp256r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_4_X, secp256r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_5_X, secp256r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_6_X, secp256r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_7_X, secp256r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_8_X, secp256r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_9_X, secp256r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_10_X, secp256r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_11_X, secp256r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_12_X, secp256r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_13_X, secp256r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_14_X, secp256r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp256r1_T_15_X, secp256r1_T_15_Y),\n};\n#else\n#define secp256r1_T NULL\n#endif\n\n#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */\n\n/*\n * Domain parameters for secp384r1\n */\n#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\nstatic const mbedtls_mpi_uint secp384r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp384r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3),\n};\nstatic const mbedtls_mpi_uint secp384r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA),\n};\nstatic const mbedtls_mpi_uint secp384r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36),\n};\nstatic const mbedtls_mpi_uint secp384r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp384r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x92, 0x00, 0x2C, 0x78, 0xDB, 0x1F, 0x37),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF3, 0xEB, 0xB7, 0x06, 0xF7, 0xB6, 0xBC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBC, 0x2C, 0xCF, 0xD8, 0xED, 0x53, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x75, 0x7B, 0xA3, 0xAB, 0xC3, 0x2C, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x9D, 0x78, 0x41, 0xF6, 0x76, 0x84, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x56, 0xE8, 0x52, 0xB3, 0xCB, 0xA8, 0xBD),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xF2, 0xAE, 0xA4, 0xB6, 0x89, 0x1B, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0xCE, 0x1C, 0x7C, 0xF6, 0x50, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xEB, 0x90, 0xE6, 0x4D, 0xC7, 0xD4, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x49, 0x2D, 0x8A, 0x01, 0x99, 0x60, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x80, 0x9B, 0x9B, 0x6A, 0xB0, 0x07, 0xD9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xA2, 0xEE, 0x59, 0xBE, 0x95, 0xBC, 0x23),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x9D, 0x56, 0xAE, 0x59, 0xFB, 0x1F, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xAC, 0x91, 0x80, 0x87, 0xA8, 0x6E, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x08, 0xA7, 0x08, 0x94, 0x32, 0xFC, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x29, 0x9E, 0x84, 0xF4, 0xE5, 0x6E, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x21, 0xB9, 0x50, 0x24, 0xF8, 0x9C, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x04, 0x01, 0xC2, 0xFB, 0x77, 0x3E, 0xDE),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x38, 0xEE, 0xE3, 0xC7, 0x9D, 0xEC, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x88, 0xCF, 0x43, 0xFA, 0x92, 0x5E, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xCA, 0x43, 0xF8, 0x3B, 0x49, 0x7E, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xE7, 0xEB, 0x17, 0x45, 0x86, 0xC2, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x69, 0x57, 0x32, 0xE0, 0x9C, 0xD1, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x10, 0xB8, 0x4D, 0xB8, 0xF4, 0x0D, 0xE3),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0xDC, 0x9A, 0xB2, 0x79, 0x39, 0x27, 0x16),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x71, 0xE4, 0x3B, 0x4D, 0x60, 0x0C, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xBD, 0x19, 0x40, 0xFA, 0x19, 0x2A, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xF8, 0x1E, 0x43, 0xA1, 0x50, 0x8D, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x18, 0x7C, 0x41, 0xFA, 0x7C, 0x1B, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x24, 0xC4, 0xE9, 0xB7, 0xD3, 0xAD),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x01, 0x3D, 0x63, 0x54, 0x45, 0x6F, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xB2, 0x19, 0xA3, 0x86, 0x1D, 0x42, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x02, 0x87, 0x18, 0x92, 0x52, 0x1A, 0x71),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x18, 0xB1, 0x5D, 0x18, 0x1B, 0x37, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x74, 0x61, 0xBA, 0x18, 0xAF, 0x40, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7D, 0x3C, 0x52, 0x0F, 0x07, 0xB0, 0x6F),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x39, 0x13, 0xAA, 0x60, 0x15, 0x99, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x00, 0xCB, 0xC6, 0xB1, 0xDB, 0x97, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xFA, 0x60, 0xB8, 0x24, 0xE4, 0x7D, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x75, 0xB3, 0x70, 0xB2, 0x83, 0xB1, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xE3, 0x6C, 0xCD, 0x33, 0x62, 0x7A, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x30, 0xDC, 0x0F, 0x9F, 0xBB, 0xB8, 0xAA),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD5, 0x0A, 0x60, 0x81, 0xB9, 0xC5, 0x16),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xAA, 0x2F, 0xD6, 0xF2, 0x73, 0xDF, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x7B, 0x74, 0xC9, 0xB3, 0x5B, 0x95, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x04, 0xEB, 0x15, 0xC8, 0x5F, 0x00, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x50, 0x20, 0x28, 0xD1, 0x01, 0xAF, 0xF0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x4F, 0x31, 0x81, 0x2F, 0x94, 0x48),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2F, 0xD8, 0xB6, 0x63, 0x7C, 0xE9, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x8C, 0xB9, 0x14, 0xD9, 0x37, 0x63, 0xDE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x02, 0xB8, 0x46, 0xAD, 0xCE, 0x7B, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x47, 0x2D, 0x66, 0xA7, 0xE9, 0x33, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF9, 0x93, 0x94, 0xA8, 0x48, 0xB3, 0x4F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x4A, 0xAC, 0x51, 0x08, 0x72, 0x2F, 0x1A),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xAD, 0xA0, 0xF9, 0x81, 0xE1, 0x78, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9A, 0x63, 0xD8, 0xBA, 0x79, 0x1A, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x31, 0x7B, 0x7A, 0x5A, 0x5D, 0x7D, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x96, 0x12, 0x4B, 0x19, 0x09, 0xE0, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8A, 0x57, 0xEE, 0x4E, 0x6E, 0x7E, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x9D, 0x69, 0xDC, 0xB3, 0xDA, 0xD8, 0x08),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x49, 0x03, 0x03, 0x33, 0x6F, 0x28, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xDB, 0xA7, 0x05, 0x8C, 0xF3, 0x4D, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x92, 0xB1, 0xA8, 0xEC, 0x0D, 0x64, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0xFC, 0xFD, 0xD0, 0x4B, 0x88, 0x1B, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x9C, 0x51, 0x69, 0xCE, 0x71, 0x73, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5A, 0x14, 0x23, 0x1A, 0x46, 0x63, 0x5F),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x4C, 0x70, 0x44, 0x18, 0xCD, 0xEF, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x49, 0xDD, 0x64, 0x7E, 0x7E, 0x4D, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x32, 0x7C, 0x09, 0xD0, 0x3F, 0xD6, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE0, 0x4F, 0x65, 0x0C, 0x7A, 0x54, 0x3E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFA, 0xFB, 0x4A, 0xB4, 0x79, 0x5A, 0x8C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x1B, 0x2B, 0xDA, 0xBC, 0x9A, 0x74),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xAC, 0x56, 0xF7, 0x5F, 0x51, 0x68, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xE0, 0x1D, 0xBC, 0x13, 0x4E, 0xAC, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF5, 0xC5, 0xE6, 0xD2, 0x88, 0xBA, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x0E, 0x28, 0x23, 0x58, 0x67, 0xFA, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x80, 0x4B, 0xD8, 0xC4, 0xDF, 0x15, 0xE4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x0E, 0x58, 0xE6, 0x2C, 0x59, 0xC2, 0x03),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x26, 0x27, 0x99, 0x16, 0x2B, 0x22, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF3, 0x8F, 0xC3, 0x2A, 0x9B, 0xFC, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2E, 0x83, 0x3D, 0xFE, 0x9E, 0x3C, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0xCD, 0x2D, 0xC1, 0x49, 0x38, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x42, 0x8B, 0x33, 0x89, 0x1F, 0xEA, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x1D, 0x13, 0xD7, 0x50, 0xBB, 0x3E, 0xEB),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x9A, 0x52, 0xD2, 0x54, 0x7C, 0x97, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x6E, 0xED, 0xD9, 0x87, 0x50, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x35, 0x7E, 0x16, 0x40, 0x15, 0x83, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x2B, 0xA4, 0xAB, 0x03, 0x91, 0xEA, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x47, 0x39, 0xEF, 0x05, 0x59, 0xD0, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x24, 0x0D, 0x76, 0x11, 0x53, 0x08, 0xAF),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x2F, 0xDD, 0xBD, 0x50, 0x48, 0xB1, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x1C, 0x84, 0x55, 0x78, 0x14, 0xEB, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x5E, 0x3E, 0xA6, 0xAF, 0xF6, 0xC7, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x11, 0xE2, 0x65, 0xCA, 0x41, 0x95, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x83, 0xD8, 0xE6, 0x4D, 0x22, 0x06, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x7F, 0x25, 0x2A, 0xAA, 0x28, 0x46, 0x97),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xDB, 0x15, 0x56, 0x84, 0xCB, 0xC0, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xDB, 0x0E, 0x08, 0xC9, 0xF5, 0xD4, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x62, 0xD0, 0x1A, 0x7C, 0x13, 0xD5, 0x07),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xAD, 0x53, 0xE0, 0x32, 0x21, 0xA0, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x38, 0x81, 0x21, 0x23, 0x0E, 0xD2, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x51, 0x05, 0xD0, 0x1E, 0x82, 0xA9, 0x71),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xC3, 0x27, 0xBF, 0xC6, 0xAA, 0xB7, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x65, 0x45, 0xDF, 0xB9, 0x46, 0x17, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x38, 0x3F, 0xB2, 0xB1, 0x5D, 0xCA, 0x1C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x29, 0x6C, 0x63, 0xE9, 0xD7, 0x48, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xF1, 0xD7, 0x99, 0x8C, 0xC2, 0x05, 0x99),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE6, 0x5E, 0x82, 0x6D, 0xE5, 0x7E, 0xD5),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x61, 0xFA, 0x7D, 0x01, 0xDB, 0xB6, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC6, 0x58, 0x39, 0xF4, 0xC6, 0x82, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0x7A, 0x80, 0x08, 0xCD, 0xAA, 0xD8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x8C, 0xC6, 0x3F, 0x3C, 0xA5, 0x68, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xF5, 0xD5, 0x17, 0xAE, 0x36, 0xD8, 0x8A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xAD, 0x92, 0xC5, 0x57, 0x6C, 0xDA, 0x91),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x67, 0x17, 0xC0, 0x40, 0x78, 0x8C, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x9F, 0xF4, 0xAA, 0xDA, 0x5C, 0x7E, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xDB, 0x42, 0x3E, 0x72, 0x64, 0xA0, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xF9, 0x41, 0x17, 0x43, 0xE3, 0xE8, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xDD, 0xCC, 0x43, 0x7E, 0x16, 0x05, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x4B, 0xCF, 0x48, 0x8F, 0x41, 0x90, 0xE5),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x0C, 0x6B, 0x9D, 0x22, 0x04, 0xBC, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x63, 0x79, 0x2F, 0x6A, 0x0E, 0x8A, 0xDE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x67, 0x3F, 0x02, 0xB8, 0x91, 0x7F, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x14, 0x64, 0xA0, 0x33, 0xF4, 0x6B, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x44, 0x71, 0x87, 0xB8, 0x88, 0x3F, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x2B, 0x85, 0x05, 0xC5, 0x44, 0x53, 0x15),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x2B, 0xFE, 0xD1, 0x1C, 0x73, 0xE3, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x33, 0xA1, 0xD3, 0x69, 0x1C, 0x9D, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x5A, 0xBA, 0xB6, 0xAE, 0x1B, 0x94, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x74, 0x90, 0x5C, 0x57, 0xB0, 0x3A, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x2F, 0x93, 0x20, 0x24, 0x54, 0x1D, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x78, 0x9D, 0x71, 0x67, 0x5D, 0x49, 0x98),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xC8, 0x0E, 0x11, 0x8D, 0xE0, 0x8F, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x7F, 0x79, 0x6C, 0x5F, 0xB7, 0xBC, 0xB1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xE1, 0x83, 0x3C, 0x12, 0xBB, 0xEE, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC2, 0xC4, 0x1B, 0x41, 0x71, 0xB9, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0xEE, 0xBB, 0x1D, 0x89, 0x50, 0x88, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x1C, 0x55, 0x74, 0xEB, 0xDE, 0x92, 0x3F),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x38, 0x92, 0x06, 0x19, 0xD0, 0xB3, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x99, 0x26, 0xA3, 0x5F, 0xE2, 0xC1, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xFC, 0xFD, 0xC3, 0xB6, 0x26, 0x24, 0x8F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xAD, 0xE7, 0x49, 0xB7, 0x64, 0x4B, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x4E, 0x95, 0xAD, 0x07, 0xFE, 0xB6, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x15, 0xE7, 0x2D, 0x19, 0xA9, 0x08, 0x10),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xBD, 0xAC, 0x0A, 0x3F, 0x6B, 0xFF, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xE4, 0x74, 0x14, 0xD9, 0x70, 0x1D, 0x71),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xB0, 0x71, 0xBB, 0xD8, 0x18, 0x96, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xB8, 0x19, 0x90, 0x80, 0xB5, 0xEE, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x21, 0x20, 0xA6, 0x17, 0x48, 0x03, 0x6F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0xBB, 0x6D, 0x94, 0x20, 0x34, 0xF1),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x82, 0x67, 0x4B, 0x8E, 0x4E, 0xBE, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xDA, 0x77, 0xF8, 0x23, 0x55, 0x2B, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x02, 0xDE, 0x25, 0x35, 0x2D, 0x74, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0C, 0xB8, 0x0B, 0x39, 0xBA, 0xAD, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x0E, 0x28, 0x4D, 0xE1, 0x3D, 0xE4, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xEC, 0x0A, 0xD4, 0xB8, 0xC4, 0x8D, 0xB0),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x68, 0xCE, 0xC2, 0x55, 0x4D, 0x0C, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x20, 0x93, 0x32, 0x90, 0xD6, 0xAE, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x78, 0xAB, 0x43, 0x9E, 0xEB, 0x73, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x97, 0xC3, 0x83, 0xA6, 0x3C, 0xF1, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x25, 0x25, 0x66, 0x08, 0x26, 0xFA, 0x4B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xFB, 0x44, 0x5D, 0x82, 0xEC, 0x3B, 0xAC),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x90, 0xEA, 0xB5, 0x04, 0x99, 0xD0, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0xF2, 0x22, 0xA0, 0xEB, 0xFD, 0x45, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA4, 0x81, 0x32, 0xFC, 0xFA, 0xEE, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xBB, 0xA4, 0x6A, 0x77, 0x41, 0x5C, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x1E, 0xAA, 0x4F, 0xF0, 0x10, 0xB3, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x74, 0x13, 0x14, 0x9E, 0x90, 0xD7, 0xE6),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xBD, 0x70, 0x4F, 0xA8, 0xD1, 0x06, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4E, 0x2E, 0x68, 0xFC, 0x35, 0xFA, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x53, 0x75, 0xED, 0xF2, 0x5F, 0xC2, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x87, 0x6B, 0x9F, 0x05, 0xE2, 0x22, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x1A, 0xA8, 0xB7, 0x03, 0x9E, 0x6D, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD0, 0x69, 0x88, 0xA8, 0x39, 0x9E, 0x3A),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xEF, 0x68, 0xFE, 0xEC, 0x24, 0x08, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x4B, 0x92, 0x0D, 0xB7, 0x34, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF4, 0xDD, 0x1A, 0xA0, 0x4A, 0xE4, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x63, 0x4F, 0x4F, 0xCE, 0xBB, 0xD6, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xEE, 0x8D, 0xDF, 0x3F, 0x73, 0xB7, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x06, 0xB6, 0x80, 0x4D, 0x81, 0xD9, 0x53),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_16_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF5, 0x13, 0xDF, 0x13, 0x19, 0x97, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xF9, 0xB3, 0x33, 0x66, 0x82, 0x21, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xFC, 0x39, 0x16, 0x23, 0x43, 0x76, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x48, 0x25, 0xA1, 0x64, 0x95, 0x1C, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xAC, 0x15, 0x57, 0xD9, 0xDE, 0xA0, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x5F, 0xB8, 0x3D, 0x48, 0x91, 0x24, 0xCC),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_16_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xF2, 0xC8, 0x54, 0xD1, 0x32, 0xBD, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x3B, 0xF0, 0xAA, 0x9D, 0xD8, 0xF4, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xC3, 0xBB, 0x6C, 0x66, 0xAC, 0x25, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x25, 0x10, 0xB2, 0xE1, 0x41, 0xDE, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xE8, 0x30, 0xB8, 0x37, 0xBC, 0x2A, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x57, 0x01, 0x4A, 0x1E, 0x78, 0x9F, 0x85),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_17_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x19, 0xCD, 0x12, 0x0B, 0x51, 0x4F, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x4B, 0x3D, 0x24, 0xA4, 0x16, 0x59, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xEB, 0xD3, 0x59, 0x2E, 0x75, 0x7C, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB9, 0xB4, 0xA5, 0xD9, 0x2E, 0x29, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x16, 0x05, 0x75, 0x02, 0xB3, 0x06, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x7C, 0x9F, 0x79, 0x91, 0xF1, 0x4F, 0x23),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_17_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x98, 0x7C, 0x84, 0xE1, 0xFF, 0x30, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE2, 0xC2, 0x5F, 0x55, 0x40, 0xBD, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x65, 0x87, 0x3F, 0xC4, 0xC2, 0x24, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x30, 0x0A, 0x60, 0x15, 0xD1, 0x24, 0x48),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x99, 0xD9, 0xB6, 0xAE, 0xB1, 0xAF, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x80, 0xEE, 0xA2, 0x0F, 0x74, 0xB9, 0xF3),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_18_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xE6, 0x0F, 0x37, 0xC1, 0x10, 0x99, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xAD, 0x9D, 0x5D, 0x80, 0x01, 0xA6, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x0F, 0x10, 0x2A, 0x9D, 0x20, 0x38, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x60, 0xCB, 0xCE, 0x5A, 0xA0, 0xA7, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xCF, 0x14, 0xDF, 0xBF, 0xE5, 0x74, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x12, 0x1A, 0xDD, 0x59, 0x02, 0x5D, 0xC6),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_18_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0xF8, 0xF5, 0xB6, 0x13, 0x4D, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x45, 0xB1, 0x93, 0xB3, 0xA2, 0x79, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xF6, 0xCF, 0xF7, 0xE6, 0x29, 0x9C, 0xCC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x50, 0x65, 0x80, 0xBC, 0x59, 0x0A, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xF0, 0x24, 0x35, 0xA2, 0x46, 0xF0, 0x0C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x26, 0xC0, 0x9D, 0x61, 0x56, 0x62, 0x67),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_19_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xBB, 0xC2, 0x24, 0x43, 0x2E, 0x37, 0x54),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xF7, 0xCE, 0x35, 0xFC, 0x77, 0xF3, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x34, 0x96, 0xD5, 0x4A, 0x76, 0x9D, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x3B, 0x0F, 0xEA, 0xA8, 0x12, 0x0B, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x3F, 0x5D, 0x2D, 0x1C, 0xD4, 0x9E, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x2E, 0xDD, 0xC7, 0x6E, 0xAB, 0xAF, 0xDC),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_19_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB2, 0x7B, 0x0C, 0x9A, 0x83, 0x8E, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x51, 0x90, 0x92, 0x79, 0x32, 0x19, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x89, 0xF9, 0xD0, 0xCF, 0x2C, 0xA5, 0x8F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x50, 0x21, 0xDE, 0x50, 0x41, 0x9D, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x7D, 0x2B, 0x9E, 0x9D, 0x95, 0xA8, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA5, 0x20, 0x87, 0x88, 0x97, 0x5F, 0xAA),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_20_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x59, 0xB4, 0x66, 0x7E, 0xE8, 0x5A, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x5C, 0x7E, 0xB2, 0xAD, 0xD9, 0xC9, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x97, 0x49, 0xA3, 0x13, 0x83, 0x07, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x26, 0xC7, 0x13, 0x35, 0x0D, 0xB0, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x60, 0xAB, 0xFA, 0x4B, 0x93, 0x18, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2D, 0x1C, 0x31, 0x4C, 0xE4, 0x61, 0xAE),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_20_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x4D, 0x1E, 0x51, 0x59, 0x6E, 0x91, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x54, 0x4D, 0x51, 0xED, 0x36, 0xCC, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xA8, 0x56, 0xC7, 0x78, 0x27, 0x33, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB7, 0x95, 0xC9, 0x8B, 0xC8, 0x6A, 0xBC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xE9, 0x13, 0x96, 0xB3, 0xE1, 0xF9, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x46, 0xB0, 0x5E, 0xC3, 0x94, 0x03, 0x05),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_21_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x5B, 0x29, 0x30, 0x41, 0x1A, 0x9E, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xCA, 0x83, 0x31, 0x5B, 0xA7, 0xCB, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x41, 0x50, 0x44, 0x4D, 0x64, 0x31, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x84, 0xC2, 0x5D, 0x97, 0xA5, 0x3C, 0x18),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x0F, 0xA5, 0xFD, 0x8E, 0x5A, 0x47, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x58, 0x02, 0x2D, 0x40, 0xB1, 0x0B, 0xBA),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_21_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x33, 0x8C, 0x67, 0xCE, 0x23, 0x43, 0x99),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x53, 0x47, 0x72, 0x44, 0x1F, 0x5B, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xC1, 0xD9, 0xA4, 0x50, 0x88, 0x63, 0x18),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xF2, 0x75, 0x69, 0x73, 0x00, 0xC4, 0x31),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x90, 0x1D, 0xDF, 0x1A, 0x00, 0xD8, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xB1, 0x89, 0x48, 0xA8, 0x70, 0x62, 0xEF),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_22_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x8A, 0x55, 0x50, 0x7B, 0xEF, 0x8A, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1B, 0x23, 0x48, 0x23, 0x63, 0x91, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x04, 0x54, 0x3C, 0x24, 0x9B, 0xC7, 0x9A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x38, 0xC3, 0x84, 0xFB, 0xFF, 0x9F, 0x49),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x2A, 0xE0, 0x6D, 0x68, 0x8A, 0x5C, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x93, 0x53, 0x85, 0xA1, 0x0D, 0xAF, 0x63),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_22_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x88, 0x95, 0x4C, 0x0B, 0xD0, 0x06, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xAF, 0x8D, 0x49, 0xA2, 0xC8, 0xB4, 0xE0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x76, 0x53, 0x09, 0x88, 0x43, 0x87, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA4, 0x77, 0x3F, 0x5E, 0x21, 0xB4, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x9E, 0x86, 0x64, 0xCC, 0x91, 0xC1, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x17, 0x56, 0xCB, 0xC3, 0x7D, 0x5B, 0xB1),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_23_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x74, 0x9F, 0xB5, 0x91, 0x21, 0xB1, 0x1C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xED, 0xE1, 0x11, 0xEF, 0x45, 0xAF, 0xC1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x31, 0xBE, 0xB2, 0xBC, 0x72, 0x65, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x4B, 0x8C, 0x77, 0xCE, 0x1E, 0x42, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC9, 0xAA, 0xB9, 0xD9, 0x86, 0x99, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x23, 0x80, 0xC6, 0x4E, 0x35, 0x0B, 0x6D),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_23_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xD8, 0xA2, 0x0A, 0x39, 0x32, 0x1D, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xC8, 0x86, 0xF1, 0x12, 0x9A, 0x4A, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xF1, 0x7C, 0xAA, 0x70, 0x8E, 0xBC, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x01, 0x47, 0x8F, 0xDD, 0x8B, 0xA5, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x08, 0x21, 0xF4, 0xAB, 0xC7, 0xF5, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x76, 0xA5, 0x95, 0xC4, 0x0F, 0x88, 0x1D),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_24_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x42, 0x2A, 0x52, 0xCD, 0x75, 0x51, 0x49),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x36, 0xE5, 0x04, 0x2B, 0x44, 0xC6, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xEE, 0x16, 0x13, 0x07, 0x83, 0xB5, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x59, 0xC6, 0xA2, 0x19, 0x05, 0xD3, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8B, 0xA8, 0x16, 0x09, 0xB7, 0xEA, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xEE, 0x14, 0xAF, 0xB5, 0xFD, 0xD0, 0xEF),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_24_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x7C, 0xCA, 0x71, 0x3E, 0x6E, 0x66, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x31, 0x0E, 0x3F, 0xE5, 0x91, 0xC4, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x3D, 0xC2, 0x3E, 0x95, 0x37, 0x58, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x1F, 0x02, 0x03, 0xF3, 0xEF, 0xEE, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x5B, 0x1A, 0xFC, 0x38, 0xCD, 0xE8, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x57, 0x42, 0x85, 0xC6, 0x21, 0x68, 0x71),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_25_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA2, 0x4A, 0x66, 0xB1, 0x0A, 0xE6, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x0C, 0x94, 0x9D, 0x5E, 0x99, 0xB2, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x03, 0x40, 0xCA, 0xB2, 0xB3, 0x30, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0x48, 0x27, 0x34, 0x1E, 0xE2, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x72, 0x5B, 0xAC, 0xC1, 0x6D, 0xE3, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAB, 0x46, 0xCB, 0xEA, 0x5E, 0x4B, 0x0B),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_25_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x08, 0xAD, 0x4E, 0x51, 0x9F, 0x2A, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5C, 0x7D, 0x4C, 0xD6, 0xCF, 0xDD, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x76, 0x26, 0xE0, 0x8B, 0x10, 0xD9, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA7, 0x23, 0x4E, 0x5F, 0xD2, 0x42, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xE5, 0xA4, 0xEC, 0x77, 0x21, 0x34, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x14, 0x65, 0xEA, 0x4A, 0x85, 0xC3, 0x2F),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_26_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xD8, 0x40, 0x27, 0x73, 0x15, 0x7E, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xBB, 0x53, 0x7E, 0x0F, 0x40, 0xC8, 0xD4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x37, 0x19, 0x73, 0xEF, 0x5A, 0x5E, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x73, 0x2B, 0x49, 0x7E, 0xAC, 0x97, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xB2, 0xC3, 0x1E, 0x0E, 0xE7, 0xD2, 0x21),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x08, 0xD6, 0xDD, 0xAC, 0x21, 0xD6, 0x3E),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_26_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x26, 0xBE, 0x6D, 0x6D, 0xF2, 0x38, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6C, 0x31, 0xA7, 0x49, 0x50, 0x3A, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x99, 0xC6, 0xF5, 0xD2, 0xC2, 0x30, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE4, 0xF6, 0x8B, 0x8B, 0x97, 0xE9, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x21, 0xB7, 0x0D, 0xFC, 0x15, 0x54, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x83, 0x1C, 0xA4, 0xCD, 0x6B, 0x9D, 0xF2),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_27_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE8, 0x4C, 0x48, 0xE4, 0xAA, 0x69, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x7A, 0x27, 0xFC, 0x37, 0x96, 0x1A, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xE7, 0x30, 0xA5, 0xCF, 0x13, 0x46, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xD8, 0xAF, 0x74, 0x23, 0x4D, 0x56, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3D, 0x44, 0x14, 0x1B, 0x97, 0x83, 0xF0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x47, 0xD7, 0x5F, 0xFD, 0x98, 0x38, 0xF7),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_27_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x73, 0x64, 0x36, 0xFD, 0x7B, 0xC1, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x5D, 0x32, 0xD2, 0x47, 0x94, 0x89, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xE9, 0x30, 0xAC, 0x06, 0xC8, 0x65, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x6C, 0xB9, 0x1B, 0xF7, 0x61, 0x49, 0x53),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xFF, 0x32, 0x43, 0x80, 0xDA, 0xA6, 0xB1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF8, 0x04, 0x01, 0x95, 0x35, 0xCE, 0x21),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_28_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x06, 0x46, 0x0D, 0x51, 0xE2, 0xD8, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x57, 0x1D, 0x6F, 0x79, 0xA0, 0xCD, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xFB, 0x36, 0xCA, 0xAD, 0xF5, 0x9E, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x7A, 0x1D, 0x9E, 0x1D, 0x95, 0x48, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x26, 0xA5, 0xB7, 0x15, 0x2C, 0xC2, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x42, 0x72, 0xAA, 0x11, 0xDC, 0xC9, 0xB6),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_28_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x6C, 0x64, 0xA7, 0x62, 0x3C, 0xAB, 0xD4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x6A, 0x44, 0xD8, 0x60, 0xC0, 0xA8, 0x80),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x76, 0x58, 0x12, 0x57, 0x3C, 0x89, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x4F, 0x83, 0xCE, 0xCB, 0xB8, 0xD0, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0x04, 0xB0, 0xAD, 0xEB, 0xFA, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA4, 0xC3, 0x41, 0x44, 0x4E, 0x65, 0x3E),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_29_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x16, 0xA9, 0x1C, 0xE7, 0x65, 0x20, 0xC1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x53, 0x32, 0xF8, 0xC0, 0xA6, 0xBD, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF0, 0xE6, 0x57, 0x31, 0xCC, 0x26, 0x6F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xE3, 0x54, 0x1C, 0x34, 0xD3, 0x17, 0xBC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xAE, 0xED, 0xFB, 0xCD, 0xE7, 0x1E, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x16, 0x1C, 0x34, 0x40, 0x00, 0x1F, 0xB6),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_29_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x32, 0x00, 0xC2, 0xD4, 0x3B, 0x1A, 0x09),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xE0, 0x99, 0x8F, 0x0C, 0x4A, 0x16, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x73, 0x18, 0x1B, 0xD4, 0x94, 0x29, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA4, 0x2D, 0xB1, 0x9D, 0x74, 0x32, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xF4, 0xB1, 0x0C, 0x37, 0x62, 0x8B, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xFF, 0xDA, 0xE2, 0x35, 0xA3, 0xB6, 0x42),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_30_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x49, 0x99, 0x65, 0xC5, 0xED, 0x16, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x42, 0x9A, 0xF3, 0xA7, 0x4E, 0x6F, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x0A, 0x7E, 0xC0, 0xD7, 0x4E, 0x07, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x7A, 0x31, 0x69, 0xA6, 0xB9, 0x15, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xE0, 0x72, 0xA4, 0x3F, 0xB9, 0xF8, 0x0C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x75, 0x32, 0x85, 0xA2, 0xDE, 0x37, 0x12),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_30_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC0, 0x0D, 0xCF, 0x25, 0x41, 0xA4, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xFC, 0xB2, 0x48, 0xC3, 0x85, 0x83, 0x4B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBE, 0x0B, 0x58, 0x2D, 0x7A, 0x9A, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xF3, 0x81, 0x18, 0x1B, 0x74, 0x4F, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x43, 0xA3, 0x0A, 0x16, 0x8B, 0xA3, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x18, 0x81, 0x7B, 0x8D, 0xA2, 0x35, 0x77),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_31_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xC4, 0x3F, 0x2C, 0xE7, 0x5F, 0x99, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2B, 0xB7, 0xB6, 0xAD, 0x5A, 0x56, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x00, 0xA4, 0x48, 0xC8, 0xE8, 0xBA, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xA1, 0xB5, 0x13, 0x5A, 0xCD, 0x99, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x95, 0xAD, 0xFC, 0xE2, 0x7E, 0xE7, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x6B, 0xD1, 0x34, 0x99, 0x53, 0x63, 0x0B),\n};\nstatic const mbedtls_mpi_uint secp384r1_T_31_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x8A, 0x77, 0x5D, 0x2B, 0xAB, 0x01, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x85, 0xD0, 0xD5, 0x49, 0x83, 0x4D, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xC6, 0x91, 0x30, 0x3B, 0x00, 0xAF, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x61, 0x07, 0xE1, 0xB6, 0xE2, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x43, 0x41, 0xFE, 0x9B, 0xB6, 0xF0, 0xA5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x97, 0xAE, 0xAD, 0x89, 0x88, 0x9E, 0x41),\n};\nstatic const mbedtls_ecp_point secp384r1_T[32] = {\n    ECP_POINT_INIT_XY_Z1(secp384r1_T_0_X, secp384r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_1_X, secp384r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_2_X, secp384r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_3_X, secp384r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_4_X, secp384r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_5_X, secp384r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_6_X, secp384r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_7_X, secp384r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_8_X, secp384r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_9_X, secp384r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_10_X, secp384r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_11_X, secp384r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_12_X, secp384r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_13_X, secp384r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_14_X, secp384r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_15_X, secp384r1_T_15_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_16_X, secp384r1_T_16_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_17_X, secp384r1_T_17_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_18_X, secp384r1_T_18_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_19_X, secp384r1_T_19_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_20_X, secp384r1_T_20_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_21_X, secp384r1_T_21_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_22_X, secp384r1_T_22_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_23_X, secp384r1_T_23_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_24_X, secp384r1_T_24_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_25_X, secp384r1_T_25_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_26_X, secp384r1_T_26_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_27_X, secp384r1_T_27_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_28_X, secp384r1_T_28_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_29_X, secp384r1_T_29_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_30_X, secp384r1_T_30_Y),\n    ECP_POINT_INIT_XY_Z0(secp384r1_T_31_X, secp384r1_T_31_Y),\n};\n#else\n#define secp384r1_T NULL\n#endif\n\n#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */\n\n/*\n * Domain parameters for secp521r1\n */\n#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)\nstatic const mbedtls_mpi_uint secp521r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01),\n};\nstatic const mbedtls_mpi_uint secp521r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_2(0x51, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_2(0xC6, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_2(0x18, 0x01),\n};\nstatic const mbedtls_mpi_uint secp521r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01),\n};\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp521r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xB1, 0x2D, 0xEB, 0x27, 0x2F, 0xE8, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x4B, 0x44, 0x25, 0xDB, 0x5C, 0x5F, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x85, 0x28, 0x78, 0x2E, 0x75, 0x34, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x57, 0x0F, 0x73, 0x78, 0x7A, 0xE3, 0x53),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD8, 0xEC, 0xDC, 0xDA, 0x04, 0xAD, 0xAB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x8A, 0x09, 0xF3, 0x58, 0x79, 0xD8, 0x29),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x03, 0xCB, 0x50, 0x1A, 0x7F, 0x56, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA6, 0x78, 0x38, 0x85, 0x67, 0x0B, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xD5, 0xD2, 0x22, 0xC4, 0x00, 0x3B, 0xBA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x93, 0x0E, 0x7B, 0x85, 0x51, 0xC3, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA6, 0x5F, 0x54, 0x49, 0x02, 0x81, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xE9, 0x6B, 0x3A, 0x92, 0xE7, 0x72, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x5F, 0x28, 0x9E, 0x91, 0x27, 0x88, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x28, 0x31, 0xB3, 0x84, 0xCA, 0x12, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xF9, 0xAC, 0x22, 0x10, 0x0A, 0x64, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xC6, 0x33, 0x1F, 0x69, 0x19, 0x18, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x48, 0xB8, 0xC7, 0x37, 0x5A, 0x00, 0x36),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xCC, 0x32, 0xE0, 0xEE, 0x03, 0xC2, 0xBA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x29, 0xC2, 0xE4, 0x6E, 0x24, 0x20, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x6B, 0x7F, 0x7B, 0xF9, 0xB0, 0xB8, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x7B, 0x3C, 0xE1, 0x19, 0xA1, 0x23, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE3, 0xC2, 0x53, 0xC0, 0x07, 0x13, 0xA9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFE, 0x36, 0x35, 0x9F, 0x5E, 0x59, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x55, 0x89, 0x84, 0xBC, 0xEF, 0xA2, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x1A, 0x08, 0x67, 0xB4, 0xE7, 0x22, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x26, 0xDF, 0x81, 0x3C, 0x5F, 0x1C, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x4D, 0xD0, 0x0A, 0x48, 0x06, 0xF4, 0x48),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x18, 0x39, 0xF7, 0xD1, 0x20, 0x77, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x8F, 0x44, 0x13, 0xCB, 0x78, 0x11, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE2, 0x49, 0xEA, 0x43, 0x79, 0x08, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xD1, 0xD8, 0x73, 0x2C, 0x71, 0x2F, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE5, 0xE7, 0xF4, 0x46, 0xAB, 0x20, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x0B, 0xB9, 0x71, 0x1A, 0x27, 0xB7, 0xA7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xA2, 0x2C, 0xD1, 0xDA, 0xBC, 0xC1, 0xBD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xA3, 0x10, 0x1F, 0x90, 0xF2, 0xA5, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xFB, 0x20, 0xF4, 0xC0, 0x70, 0xC0, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xA7, 0x99, 0xF0, 0xA5, 0xD3, 0x09, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xE8, 0x14, 0x39, 0xBE, 0xCB, 0x60, 0xAF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD6, 0x14, 0xA9, 0xC9, 0x20, 0xC3, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x5B, 0xFD, 0x2D, 0x96, 0xBC, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x04, 0x45, 0xBE, 0xCE, 0x75, 0x95, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xDA, 0x58, 0x49, 0x35, 0x09, 0x8D, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xF0, 0xC0, 0x36, 0xF2, 0xA6, 0x2D, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFC, 0x3D, 0xA8, 0xFB, 0x3C, 0xD2, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x4D, 0x71, 0x09, 0x18, 0x42, 0xF0, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xC1, 0xCE, 0x9E, 0x6A, 0x49, 0x60, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xB1, 0x00, 0xF7, 0xA1, 0x7A, 0x31, 0xB4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC3, 0x86, 0xCD, 0x20, 0x4A, 0x17, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xAB, 0x8B, 0x47, 0x8D, 0xAA, 0xA6, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x97, 0xF0, 0xBC, 0x2D, 0xDC, 0x9D, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x86, 0xB0, 0x74, 0xB2, 0xF4, 0xF6, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBD, 0xAC, 0xE3, 0x8F, 0x43, 0x5C, 0xB1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xC3, 0xE2, 0x6E, 0x25, 0x49, 0xCD, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5E, 0x08, 0xB3, 0xB9, 0xAC, 0x5F, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xB7, 0xD1, 0xF4, 0xDC, 0x19, 0xE9, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xE4, 0xFA, 0xE1, 0x36, 0x3E, 0xED, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0x92, 0x84, 0x6E, 0x48, 0x03, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x95, 0xEF, 0x8F, 0xB2, 0x82, 0x6B, 0x1C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFA, 0xB9, 0x55, 0x23, 0xFE, 0x09, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x79, 0x85, 0x4B, 0x0E, 0xD4, 0x35, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x27, 0x45, 0x81, 0xE0, 0x88, 0x52, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x63, 0xA2, 0x4B, 0xBC, 0x5D, 0xB1, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x8C, 0x83, 0xD9, 0x3E, 0xD3, 0x42, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x03, 0x3A, 0x31, 0xBA, 0xE9, 0x3A, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x10, 0xCD, 0x2D, 0x00, 0xFE, 0x32, 0xA7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x6E, 0x1F, 0xDA, 0xF8, 0x6F, 0x4D, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x79, 0x7D, 0x09, 0xE5, 0xD3, 0x03, 0x21),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC3, 0xBE, 0xDF, 0x07, 0x65, 0x49, 0xCC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0x33, 0xEF, 0xAE, 0x4F, 0x04, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xE9, 0x9B, 0xFE, 0xBF, 0xE6, 0x85, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xBA, 0xAA, 0x06, 0xC4, 0xC6, 0xB8, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x83, 0x01, 0xA9, 0xF6, 0x51, 0xE7, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xA6, 0x15, 0x8E, 0xAB, 0x1F, 0x10, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x08, 0x27, 0x1A, 0xA1, 0x21, 0xAD, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x09, 0x90, 0x6E, 0x50, 0x90, 0x9A, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x9A, 0xFE, 0xD7, 0xA1, 0xF5, 0xA2, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x7D, 0xE3, 0xDC, 0x21, 0xFB, 0xA4, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBF, 0x07, 0xFF, 0x45, 0xDF, 0x51, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x5C, 0x34, 0x02, 0x62, 0x9B, 0x08, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xCE, 0x9A, 0x6A, 0xEC, 0x75, 0xF6, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x59, 0xF4, 0x78, 0x3C, 0x60, 0xB1, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x37, 0x84, 0x6A, 0xDC, 0xF2, 0x9A, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9A, 0x9A, 0x15, 0x36, 0xE0, 0x2B, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x38, 0x9C, 0x50, 0x3D, 0x1E, 0x37, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x79, 0xF0, 0x92, 0xF2, 0x8B, 0x18, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE0, 0x82, 0x1E, 0x80, 0x82, 0x4B, 0xD7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xBB, 0x59, 0x6B, 0x8A, 0x77, 0x41, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xF9, 0xD4, 0xB8, 0x4A, 0x82, 0xCF, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x8C, 0xC8, 0x9B, 0x72, 0x9E, 0xF7, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xCE, 0xE9, 0x77, 0x0A, 0x19, 0x59, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xA1, 0x41, 0x6A, 0x72, 0x4B, 0xB4, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x35, 0x43, 0xE2, 0x8C, 0xBE, 0x0D, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xEB, 0xAD, 0xF3, 0xA9, 0xA6, 0x68, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2F, 0xE2, 0x48, 0x0C, 0xDB, 0x1F, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x1E, 0x60, 0x9B, 0x2A, 0xD2, 0xC1, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x64, 0xB5, 0xD2, 0xF6, 0xF6, 0x6E, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x3D, 0x30, 0x78, 0x10, 0x18, 0x41, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x1D, 0x1C, 0xE0, 0x6D, 0x83, 0xD1, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x03, 0x0B, 0xF5, 0x2F, 0x6C, 0x04, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x3E, 0xD5, 0xFC, 0x31, 0x5B, 0x3A, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x82, 0x2F, 0xFB, 0xFE, 0xF8, 0x76, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x26, 0xDA, 0x9C, 0x36, 0xF5, 0x93, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xE7, 0x6E, 0xD2, 0x7D, 0x81, 0x09, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x03, 0xF9, 0x58, 0x48, 0x24, 0xA2, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x79, 0x0C, 0x8E, 0x6B, 0x95, 0xF3, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x10, 0x5C, 0x87, 0x03, 0x39, 0xCF, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xF0, 0xF7, 0xC1, 0x07, 0xA4, 0xF4, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE8, 0x02, 0x89, 0x65, 0xC4, 0x72, 0x36),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x88, 0xEA, 0x96, 0x67, 0x0B, 0x5D, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x75, 0x60, 0xA8, 0xBD, 0x74, 0xDF, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xE5, 0x71, 0x50, 0x67, 0xD0, 0xD2, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFC, 0xE5, 0xC7, 0x77, 0xB0, 0x7F, 0x8C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x86, 0x69, 0xCD, 0x0D, 0x9A, 0xBD, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x17, 0xBC, 0xBB, 0x59, 0x85, 0x7D, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA8, 0x76, 0xAC, 0x80, 0xA9, 0x72, 0xE0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0xC1, 0xE2, 0x4D, 0xAF, 0xF9, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x97, 0x8E, 0x74, 0xC4, 0x4B, 0xB2, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD8, 0xF6, 0xF3, 0xAF, 0x2F, 0x52, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x57, 0xF4, 0xCE, 0xEE, 0x43, 0xED, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x46, 0x38, 0xDE, 0x20, 0xFD, 0x59, 0x18),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x18, 0xE8, 0x58, 0xB9, 0x76, 0x2C, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x54, 0xE4, 0xFE, 0xC7, 0xBC, 0x31, 0x37),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF8, 0x89, 0xEE, 0x70, 0xB5, 0xB0, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x22, 0x26, 0x9A, 0x53, 0xB9, 0x38, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xA7, 0x19, 0x8C, 0x74, 0x7E, 0x88, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xDA, 0x0A, 0xE8, 0xDA, 0xA5, 0xBE, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x5C, 0xF7, 0xB1, 0x0C, 0x72, 0xFB, 0x09),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xE2, 0x23, 0xE7, 0x46, 0xB7, 0xE0, 0x91),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x36, 0xBC, 0xBD, 0x48, 0x11, 0x8E, 0x72),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xBB, 0xA1, 0xF7, 0x0B, 0x9E, 0xBF, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x28, 0xE1, 0xA2, 0x8F, 0xFC, 0xFC, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xFE, 0x19, 0x0A, 0xE5, 0xE7, 0x69, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xCD, 0x12, 0xF5, 0xBE, 0xD3, 0x04, 0xF1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA8, 0x0D, 0x81, 0x59, 0xC4, 0x79, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xF3, 0x4B, 0x92, 0x65, 0xC3, 0x31, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xB5, 0x4F, 0x4D, 0x91, 0xD4, 0xE2, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x09, 0x41, 0x79, 0x1D, 0x4D, 0x0D, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x31, 0x18, 0xBA, 0xA0, 0xF2, 0x6E, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x5B, 0x4D, 0x4F, 0xAF, 0xC9, 0x8C, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x9C, 0x06, 0x68, 0xDE, 0xD8, 0x29),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x04, 0xE1, 0xB5, 0x9D, 0x00, 0xBC, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x95, 0x92, 0x8D, 0x72, 0xD3, 0x37, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x4B, 0x27, 0xA2, 0xE8, 0xA4, 0x26, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x45, 0x9C, 0xA9, 0xCB, 0x9F, 0xBA, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x7E, 0x1B, 0x64, 0xF4, 0xE8, 0xA5, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x20, 0xA9, 0xCA, 0xF3, 0x89, 0xE5, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xED, 0xFC, 0xAB, 0xD9, 0x0A, 0xB9, 0x07),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6F, 0x46, 0x7C, 0xCD, 0x78, 0xFF, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAB, 0x71, 0x5A, 0x94, 0xAB, 0x20, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x2E, 0xEE, 0x87, 0x57, 0x1F, 0xAD, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x4C, 0x3D, 0xFB, 0x7E, 0xA1, 0x8B, 0x07),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xCF, 0x07, 0x86, 0xBA, 0x53, 0x37, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x26, 0xB2, 0xB9, 0xE2, 0x91, 0xE3, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xC9, 0x54, 0x84, 0x08, 0x3D, 0x0B, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x77, 0x2F, 0x64, 0x45, 0x99, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x96, 0x16, 0x1F, 0xDB, 0x96, 0x28, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x2B, 0x8D, 0xFF, 0xA2, 0x4F, 0x55, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE6, 0x48, 0xBD, 0x99, 0x3D, 0x12, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x84, 0x59, 0xDA, 0xB9, 0xB6, 0x66, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x78, 0x41, 0x92, 0xDF, 0xF4, 0x3F, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x86, 0x6F, 0x4F, 0xBF, 0x67, 0xDF, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x2B, 0x1E, 0x5F, 0x00, 0xEA, 0xF6, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xB9, 0x6A, 0x89, 0xD8, 0xC0, 0xD7, 0xA7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x9A, 0x32, 0x23, 0xA0, 0x02, 0x91, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x7F, 0x6A, 0x15, 0x64, 0x6A, 0x8B, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x57, 0x82, 0x58, 0xA9, 0x56, 0xB5, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x50, 0x92, 0x60, 0xCC, 0x81, 0x24, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x3D, 0xAD, 0xDA, 0xD9, 0x51, 0x3E, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xFE, 0x8F, 0xB0, 0x0B, 0xDE, 0x2E, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xD2, 0xBE, 0xEF, 0xAC, 0x76, 0x71, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xE8, 0x72, 0x0B, 0xAC, 0xFE, 0xCA, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0xC7, 0xFC, 0xE3, 0x3C, 0x7C, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x04, 0xA7, 0xB9, 0x9B, 0x93, 0xC0, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x48, 0x4B, 0x8E, 0x32, 0xC5, 0xF0, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x42, 0x07, 0xC1, 0xF2, 0xF1, 0x72, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x37, 0x54, 0x9C, 0x88, 0xD2, 0x62, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x19, 0x8A, 0x89, 0x58, 0xA2, 0x0F, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xCC, 0x4C, 0x97, 0x30, 0x66, 0x34, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x6A, 0x1E, 0x1F, 0xDB, 0xC9, 0x5E, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x4D, 0x49, 0xFF, 0x9B, 0x9C, 0xAC, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xE4, 0x4B, 0xF2, 0xD4, 0x1A, 0xD2, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xDA, 0xE8, 0x61, 0x9F, 0xC8, 0x49, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xCB, 0xF2, 0x2D, 0x85, 0xF6, 0x8D, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xC5, 0xCD, 0x2C, 0x79, 0xC6, 0x0E, 0x4F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x1D, 0x55, 0x0F, 0xF8, 0x22, 0x9F, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x56, 0xBA, 0xE7, 0x57, 0x32, 0xEC, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x9A, 0xC6, 0x4C, 0x09, 0xC4, 0x52, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x1E, 0x6F, 0xF4, 0x7D, 0x27, 0xDD, 0xAF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x11, 0x16, 0xEC, 0x79, 0x83, 0xAD, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x4E, 0x92, 0x1F, 0x19, 0x7D, 0x65, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xFF, 0x78, 0x15, 0x45, 0x63, 0x32, 0xE4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x91, 0xD0, 0x78, 0x58, 0xDA, 0x50, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xDE, 0x40, 0xF6, 0x41, 0xB4, 0x3B, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x8D, 0xE0, 0xE1, 0xA9, 0xF0, 0x35, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xD4, 0xBA, 0x7B, 0xCC, 0x1B, 0x3A, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x5A, 0x2E, 0x74, 0x47, 0x14, 0xC3, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xF0, 0x8B, 0x06, 0x15, 0x8E, 0x0E, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xD2, 0xEB, 0x97, 0x50, 0x7D, 0x31, 0xFC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x93, 0x4C, 0xDB, 0x97, 0x79, 0x44, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xA2, 0xA0, 0x0B, 0xC8, 0x3A, 0x8A, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x50, 0x92, 0x9E, 0x24, 0x1F, 0xCB, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x16, 0xC9, 0xC5, 0x3D, 0x5A, 0xAF, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xE3, 0x97, 0xE4, 0xA8, 0x50, 0xF6, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x57, 0x97, 0x42, 0x78, 0x92, 0x49, 0x0D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEB, 0x62, 0x24, 0xFB, 0x8F, 0x32, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x0C, 0x36, 0x6E, 0x8F, 0xE8, 0xE8, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xD3, 0x7C, 0xC7, 0x8D, 0x3F, 0x5C, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x64, 0x6A, 0x73, 0x10, 0x79, 0xB8, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xF9, 0xEF, 0xA5, 0x20, 0x4A, 0x5C, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xF3, 0xF4, 0x49, 0x5B, 0x73, 0xAA, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xF2, 0xEA, 0x0F, 0x00, 0xAD, 0x53, 0xAB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xB8, 0x66, 0xED, 0xC4, 0x2B, 0x4C, 0x35),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x2F, 0xC1, 0x9A, 0x37, 0xD2, 0x7F, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA7, 0x81, 0x38, 0x64, 0xC9, 0x37, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x3B, 0x6C, 0x9F, 0x5B, 0xD9, 0x8B, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x14, 0xD9, 0x08, 0xD8, 0xD2, 0x7E, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x71, 0xE6, 0x3D, 0xD1, 0xB0, 0xE7, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x81, 0x23, 0xEC, 0x2D, 0x42, 0x45, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x5B, 0x44, 0x6B, 0x89, 0x03, 0x67, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x27, 0xAE, 0x80, 0x5A, 0x33, 0xBE, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB6, 0x64, 0x1A, 0xDF, 0xD3, 0x85, 0x91),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x8C, 0x22, 0xBA, 0xD0, 0xBD, 0xCC, 0xA0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x3C, 0x01, 0x3A, 0xFF, 0x9D, 0xC7, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC7, 0x64, 0xB4, 0x59, 0x4E, 0x9F, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x34, 0x0A, 0x41, 0x94, 0xA8, 0xF2, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD4, 0xE4, 0xF0, 0x97, 0x45, 0x6D, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x1F, 0x4D, 0x6D, 0xFE, 0xA0, 0xC4, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x28, 0x5C, 0x40, 0xBB, 0x65, 0xD4, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xA8, 0x87, 0x35, 0x20, 0x3A, 0x89, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFD, 0x4F, 0xAB, 0x2D, 0xD1, 0xD0, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE8, 0x00, 0xFC, 0x69, 0x52, 0xF8, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x9A, 0x99, 0xE1, 0xDC, 0x9C, 0x3F, 0xD9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x08, 0x98, 0xD9, 0xCA, 0x73, 0xD5, 0xA9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x2C, 0xE0, 0xA7, 0x3E, 0x91, 0xD7, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x04, 0xB0, 0x54, 0x09, 0xF4, 0x72, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xEE, 0x28, 0xCC, 0xE8, 0x50, 0x78, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x91, 0x03, 0x76, 0xDB, 0x68, 0x24, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xE0, 0x56, 0xB2, 0x5D, 0x12, 0xD3, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x42, 0x59, 0x8B, 0xDF, 0x67, 0xB5, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xCC, 0xE5, 0x31, 0x53, 0x7A, 0x46, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_16_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8D, 0x59, 0xB5, 0x1B, 0x0F, 0xF4, 0xAF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x2F, 0xD1, 0x2C, 0xE0, 0xD8, 0x04, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0xD7, 0xBA, 0xB0, 0xA3, 0x7E, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x08, 0x51, 0x56, 0xA6, 0x76, 0x67, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x17, 0x63, 0xFE, 0x56, 0xD0, 0xD9, 0x71),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xF6, 0xC3, 0x14, 0x47, 0xC5, 0xA7, 0x31),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x4C, 0x80, 0xF6, 0xA2, 0x57, 0xA7, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xB3, 0x7B, 0xF8, 0x2F, 0xE1, 0x3E, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_16_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xF4, 0xF9, 0x6B, 0x7B, 0x90, 0xDF, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x82, 0xEF, 0x62, 0xA1, 0x4C, 0x53, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x99, 0x76, 0x01, 0xBA, 0x8D, 0x0F, 0x54),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xF4, 0x58, 0x73, 0x56, 0xFE, 0xDD, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xCE, 0xF9, 0xE8, 0xA1, 0x34, 0xC3, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x5F, 0xDC, 0x6A, 0x3D, 0xD8, 0x7F, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xF4, 0x51, 0xB8, 0xB8, 0xC1, 0xD7, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x7D, 0x58, 0xD1, 0xD4, 0x1B, 0x4D, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_17_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x95, 0xDF, 0x00, 0xD8, 0x21, 0xDE, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x47, 0x3C, 0xC3, 0xB2, 0x01, 0x53, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x17, 0x43, 0x23, 0xBD, 0xCA, 0x71, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xBA, 0x0F, 0x4F, 0xDC, 0x41, 0x54, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x39, 0x26, 0x70, 0x53, 0x32, 0x18, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x46, 0x07, 0x97, 0x3A, 0x57, 0xE0, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x92, 0x4F, 0xCE, 0xDF, 0x25, 0x80, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x6F, 0x9A, 0x03, 0x05, 0x4B, 0xD1, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_17_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x01, 0x72, 0x30, 0x90, 0x17, 0x51, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xFB, 0x41, 0x65, 0x5C, 0xB4, 0x2D, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xCD, 0xCD, 0xAA, 0x41, 0xCC, 0xBB, 0x07),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xCE, 0x08, 0x0A, 0x63, 0xE9, 0xA2, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA8, 0x21, 0x7F, 0x7A, 0x5B, 0x9B, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x6B, 0x89, 0x44, 0x0A, 0x7F, 0x85, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xDE, 0x7C, 0x19, 0x5C, 0x65, 0x26, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xAC, 0x62, 0x29, 0x4A, 0xF1, 0xD0, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_18_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x00, 0x40, 0x87, 0xEB, 0xA9, 0x58, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x51, 0x0B, 0xFF, 0x56, 0x35, 0x51, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xAC, 0x08, 0x94, 0x71, 0xDA, 0xEC, 0x99),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x4D, 0xC5, 0x7B, 0x31, 0x8B, 0x8D, 0x5E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x05, 0xF1, 0x3E, 0x9E, 0x8F, 0x17, 0x8F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x9C, 0x4B, 0x62, 0x94, 0xAD, 0x49, 0xFC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC9, 0xC6, 0x8F, 0xFD, 0x33, 0x44, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x96, 0x17, 0x7F, 0x42, 0xBE, 0xF7, 0x0D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_18_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x29, 0x39, 0x13, 0x08, 0x8D, 0x91, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x79, 0xF9, 0x2F, 0xA9, 0x0A, 0xCF, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x87, 0x7A, 0xA3, 0x19, 0xAB, 0x55, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x0B, 0x01, 0xC5, 0x56, 0x19, 0x9D, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xDE, 0x82, 0x3B, 0xEA, 0xD3, 0x0B, 0x8C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x6B, 0xC7, 0xF3, 0x0F, 0x82, 0x87, 0x6C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x2E, 0x23, 0xF2, 0x39, 0x9D, 0x49, 0x70),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xDE, 0xAF, 0x7A, 0xEE, 0xB0, 0xDA, 0x70),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_19_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x4E, 0x2A, 0x50, 0xFD, 0x8E, 0xC0, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x0F, 0x7C, 0x76, 0x63, 0xD8, 0x89, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x2D, 0xB9, 0x4E, 0xF4, 0xEE, 0x85, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x95, 0x5C, 0x96, 0x5D, 0xAA, 0x59, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xDB, 0xD2, 0x68, 0x8E, 0x5A, 0x94, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x02, 0xBF, 0x77, 0x9F, 0xB9, 0x4C, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xDC, 0xC0, 0xCF, 0x81, 0x1E, 0xC4, 0x6C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xCC, 0x37, 0x86, 0xDC, 0xE2, 0x64, 0x72),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_19_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x30, 0xB1, 0x59, 0x20, 0x9D, 0x98, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x0C, 0x9D, 0xF8, 0x20, 0xDC, 0x90, 0xBA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xA0, 0xF4, 0xE7, 0x3E, 0x9C, 0x9E, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x25, 0xA2, 0xB0, 0x54, 0xCD, 0x2E, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD9, 0x42, 0xB0, 0x80, 0xB0, 0xA3, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xFE, 0x9D, 0x8D, 0x40, 0xFF, 0x27, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9D, 0xA6, 0x88, 0x3A, 0x8B, 0x6F, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x39, 0xEE, 0x1F, 0x3F, 0xB1, 0x4F, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_20_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD7, 0x9E, 0xFF, 0xD2, 0x35, 0x67, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x4F, 0x15, 0x5D, 0xE3, 0xE8, 0x53, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF7, 0x24, 0x98, 0xA2, 0xCB, 0x11, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x2E, 0x25, 0xE1, 0x94, 0xC5, 0xA3, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x82, 0x6E, 0xBA, 0xE7, 0x43, 0x25, 0xB0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x65, 0xB4, 0x49, 0x73, 0x18, 0x35, 0x54),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x5B, 0xBC, 0x62, 0x86, 0x4C, 0xC1, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xF2, 0x95, 0xA2, 0xBB, 0xA2, 0x35, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_20_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x59, 0x62, 0xB0, 0x4B, 0x1E, 0xB4, 0xD8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x55, 0xCE, 0xB0, 0x69, 0xBA, 0x63, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x69, 0x86, 0xDB, 0x34, 0x7D, 0x68, 0x64),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x06, 0xCA, 0x55, 0x44, 0x36, 0x2B, 0xBA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xD4, 0xC4, 0x3D, 0xCD, 0x9E, 0x69, 0xA4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x44, 0xE4, 0xBF, 0x31, 0xE6, 0x40, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x4F, 0xFA, 0x75, 0xE3, 0xFB, 0x97, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xC0, 0xBD, 0x1C, 0x48, 0xB0, 0x26, 0xD0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_21_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x7B, 0x32, 0xFA, 0xF2, 0x6D, 0x84, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x21, 0x03, 0x1D, 0x0D, 0x22, 0x55, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xF9, 0x42, 0x03, 0x9C, 0xC2, 0xCB, 0xBA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xA1, 0x96, 0xD9, 0x9D, 0x11, 0x6F, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x40, 0x57, 0xEB, 0x40, 0x2D, 0xC0, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x96, 0xBB, 0x4F, 0x2F, 0x23, 0xA8, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x29, 0x85, 0x21, 0xA5, 0x50, 0x62, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x7D, 0x92, 0xCF, 0x87, 0x0C, 0x22, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_21_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x0E, 0xA5, 0x32, 0x5B, 0xDF, 0x9C, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x96, 0x37, 0x2C, 0x88, 0x35, 0x30, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xB4, 0x69, 0xFF, 0xEB, 0xC6, 0x94, 0x08),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x55, 0x60, 0xAD, 0xAA, 0x58, 0x14, 0x88),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xFF, 0xF2, 0xB2, 0xD5, 0xA7, 0xD9, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xAE, 0x54, 0xD2, 0x60, 0x31, 0xF3, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x92, 0x83, 0xE3, 0xF1, 0x42, 0x83, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD2, 0xC8, 0xB7, 0x76, 0x45, 0x7F, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_22_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x11, 0xA4, 0xFB, 0x7A, 0x01, 0xBC, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x27, 0x73, 0x8D, 0x02, 0x91, 0x27, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x62, 0xF6, 0xDD, 0x6B, 0xFA, 0x5B, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCA, 0xA2, 0x44, 0x2C, 0xF0, 0x28, 0xD8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xF1, 0x7A, 0xA2, 0x42, 0x4C, 0x50, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x83, 0x3E, 0x50, 0xAB, 0x9C, 0xF7, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xED, 0x78, 0xCB, 0x76, 0x69, 0xDA, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x1E, 0x43, 0x27, 0x47, 0x6E, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_22_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x4F, 0x54, 0xB9, 0x3E, 0xBD, 0xD5, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x40, 0x69, 0x7F, 0x74, 0x9D, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x06, 0x6F, 0x67, 0x68, 0x2B, 0x4D, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x65, 0x41, 0xFC, 0x7C, 0x1E, 0xE8, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x79, 0x37, 0xAF, 0xFD, 0xD2, 0xDA, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xA8, 0x69, 0x56, 0x62, 0xA4, 0xE4, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x71, 0x73, 0x21, 0x8A, 0x17, 0x81, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x55, 0x8F, 0x7B, 0xB8, 0xAF, 0xF7, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_23_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xD1, 0xBD, 0xBE, 0x8C, 0xBC, 0x60, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA6, 0x57, 0x8C, 0xAE, 0x5C, 0x19, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x43, 0xE4, 0xD9, 0xD8, 0x7B, 0xE7, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xB9, 0xE4, 0x85, 0x7C, 0x2E, 0xFC, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2E, 0x01, 0x2A, 0x6D, 0x56, 0xBE, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x0C, 0x25, 0x9B, 0xAE, 0x86, 0x37, 0x43),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x22, 0xB3, 0xCB, 0x99, 0x66, 0xB7, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xF7, 0x90, 0xF0, 0x1B, 0x09, 0x27, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_23_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x16, 0x08, 0xEF, 0x39, 0x64, 0x49, 0x31),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA0, 0xE3, 0x97, 0xA9, 0x07, 0x54, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xFF, 0xE2, 0x00, 0x07, 0x21, 0x88, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFD, 0x59, 0x53, 0x05, 0x6C, 0x42, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xF7, 0x39, 0x5C, 0x82, 0x36, 0xE8, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x83, 0xA8, 0xE2, 0xA8, 0x43, 0x07, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xAF, 0x2B, 0x79, 0xED, 0xD8, 0x39, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x20, 0x91, 0x7A, 0xC4, 0x07, 0xEF, 0x6C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_24_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x2F, 0xAA, 0x0C, 0x94, 0x0E, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x81, 0x87, 0x41, 0x23, 0xEB, 0x55, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x53, 0xCC, 0x79, 0xB6, 0xEB, 0x6C, 0xCC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x77, 0x73, 0x9D, 0xFC, 0x64, 0x6F, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x40, 0xE3, 0x6D, 0x1C, 0x16, 0x71, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xF4, 0x1B, 0xFF, 0x1C, 0x2F, 0xA5, 0xD7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x0E, 0x0B, 0x11, 0xF4, 0x8D, 0x93, 0xAF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC5, 0x64, 0x6F, 0x24, 0x19, 0xF2, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_24_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xB3, 0xAF, 0xA5, 0x0E, 0x4F, 0x5E, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x77, 0xCA, 0xF2, 0x6D, 0xC5, 0xF6, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x18, 0x8E, 0x33, 0x68, 0x6C, 0xE8, 0xE0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x8B, 0x80, 0x90, 0x19, 0x7F, 0x90, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x80, 0x6B, 0x68, 0xE2, 0x7D, 0xD4, 0xD0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC1, 0x67, 0xB3, 0x72, 0xCB, 0xBF, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xD5, 0xD3, 0x1D, 0x14, 0x58, 0x0A, 0x80),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x7A, 0x65, 0x98, 0xB3, 0x07, 0x4B, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_25_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x87, 0x0F, 0x5F, 0xCF, 0xA2, 0x01, 0x08),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC9, 0xC8, 0x6E, 0x35, 0x87, 0xA5, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x3E, 0x91, 0xA0, 0xAB, 0x24, 0x1E, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBC, 0x02, 0x35, 0x70, 0xC1, 0x5F, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x59, 0xA0, 0x50, 0x04, 0x80, 0x52, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x56, 0x6E, 0x42, 0x8F, 0x8C, 0x91, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xA2, 0xCB, 0xA5, 0xDE, 0x14, 0x24, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xCB, 0x74, 0x28, 0xE6, 0xA7, 0xE7, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_25_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x73, 0xA8, 0x8F, 0x9E, 0x0E, 0x63, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x1B, 0x77, 0xC7, 0xC1, 0x38, 0xF9, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x3C, 0xCF, 0xA8, 0x7A, 0xD7, 0xF3, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x5F, 0x9A, 0xC9, 0xAD, 0xE9, 0x1A, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0x2B, 0x5E, 0xD5, 0x81, 0x95, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x88, 0x75, 0x29, 0x1F, 0xC7, 0xC7, 0xD0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA9, 0x5A, 0x4D, 0x63, 0x95, 0xF9, 0x4E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xCD, 0x04, 0x8F, 0xCD, 0x91, 0xDE, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_26_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xD4, 0xFD, 0x25, 0x11, 0x99, 0x6E, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x83, 0x01, 0x3D, 0xFB, 0x56, 0xA5, 0x4E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x3A, 0xDC, 0x74, 0xC2, 0xD7, 0xCF, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xBD, 0xF1, 0xDD, 0xA3, 0x07, 0x03, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xBE, 0xE9, 0x2E, 0x58, 0x84, 0x66, 0xFC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x20, 0x78, 0x37, 0x79, 0x0B, 0xA6, 0x64),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xF2, 0xAC, 0x65, 0xC8, 0xC9, 0x2F, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x93, 0xE5, 0x0D, 0x0C, 0xC6, 0xB8, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_26_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAD, 0x5C, 0x19, 0x12, 0x61, 0x0E, 0x25),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x4F, 0x0B, 0x1F, 0x49, 0x7E, 0xCD, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2E, 0x30, 0x61, 0xDB, 0x08, 0x68, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x78, 0xAF, 0xB3, 0x08, 0xC1, 0x69, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x5F, 0x5D, 0xC1, 0x57, 0x6F, 0xD8, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xD3, 0x6A, 0xF7, 0xFD, 0x86, 0xE5, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x63, 0xBD, 0x70, 0x7B, 0x47, 0xE8, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x62, 0xC8, 0x7E, 0x9D, 0x11, 0x2B, 0xA5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_27_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x84, 0xFD, 0xD5, 0x9A, 0x56, 0x7F, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBB, 0xA4, 0x6F, 0x12, 0x6E, 0x4D, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x08, 0xA1, 0x82, 0x9C, 0x62, 0x74, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x22, 0x05, 0x1D, 0x15, 0x35, 0x79),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x88, 0xCF, 0x5C, 0x05, 0x78, 0xFB, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x6B, 0x2F, 0x79, 0x09, 0x73, 0x67, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA0, 0x80, 0xD8, 0xE8, 0xEC, 0xFB, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0B, 0xB7, 0x81, 0x48, 0x7B, 0xD9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_27_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x53, 0xA9, 0xED, 0x61, 0x92, 0xD7, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x49, 0xD9, 0x5D, 0x9B, 0x4E, 0x89, 0x35),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x12, 0xEB, 0x9A, 0xC9, 0xCB, 0xC1, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xDC, 0x95, 0x16, 0xFE, 0x29, 0x70, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x33, 0xB1, 0xD6, 0x78, 0xB9, 0xE2, 0x36),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xCE, 0x88, 0xC3, 0xFD, 0x7A, 0x6B, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x1E, 0x50, 0x1E, 0xAF, 0xB1, 0x25, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xE7, 0xD7, 0xD5, 0xBD, 0x7A, 0x12, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_28_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xAA, 0xA2, 0x80, 0x5D, 0x8F, 0xCD, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x39, 0x79, 0x64, 0xA1, 0x67, 0x3C, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xC7, 0x49, 0xFF, 0x7F, 0xAC, 0xAB, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x54, 0x3E, 0x83, 0xF0, 0x3D, 0xBC, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x92, 0x4A, 0x38, 0x42, 0x8A, 0xAB, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x0B, 0x4F, 0xEE, 0x9E, 0x92, 0xA5, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xDD, 0x19, 0x96, 0xF2, 0xF0, 0x6B, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xFC, 0xDD, 0xB2, 0x8A, 0xE5, 0x4C, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_28_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x06, 0x49, 0xAC, 0x99, 0x7E, 0xF8, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xC8, 0x01, 0x51, 0xEA, 0xF6, 0x52, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x89, 0x66, 0x2B, 0x1F, 0x9B, 0x2A, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x0F, 0x95, 0x07, 0x2B, 0x6C, 0x6E, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC3, 0xB4, 0xBB, 0x91, 0x1F, 0xA3, 0x72),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x6E, 0x54, 0x28, 0x7B, 0x9C, 0x79, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x45, 0xFF, 0xA6, 0xDA, 0xA2, 0x83, 0x71),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xDE, 0x8F, 0x17, 0x37, 0x82, 0xCB, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_29_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x94, 0x3F, 0x26, 0xC9, 0x1D, 0xD9, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x28, 0x20, 0xCD, 0xC1, 0xF3, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC9, 0xB5, 0x60, 0x9B, 0x1E, 0xDC, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xB9, 0x5B, 0x7D, 0xA0, 0xB2, 0x8C, 0xF0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xD1, 0x42, 0xE6, 0x39, 0x33, 0x6D, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xC0, 0xFC, 0xD2, 0x14, 0x5D, 0x3E, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x4A, 0x3E, 0x40, 0x16, 0x93, 0x15, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x24, 0xC1, 0x27, 0x27, 0xE5, 0x4B, 0xD8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_29_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x50, 0xD8, 0xBC, 0xC1, 0x46, 0x22, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x0E, 0x60, 0xA1, 0xB3, 0x50, 0xD4, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xB1, 0x26, 0xB6, 0x6D, 0x47, 0x5A, 0x6F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0xAC, 0x11, 0x35, 0x3E, 0xB9, 0xF4, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x97, 0xFA, 0xBB, 0x6B, 0x39, 0x13, 0xD8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x34, 0x12, 0x75, 0x8E, 0x9B, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x9E, 0xCD, 0x29, 0xB6, 0xEF, 0x8D, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xAC, 0xE9, 0x25, 0x27, 0xBB, 0x78, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_30_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x7A, 0xA8, 0xD3, 0xE3, 0x66, 0xE5, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x4C, 0xC4, 0x2C, 0x76, 0x81, 0x50, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x71, 0x08, 0xB8, 0x52, 0x7C, 0xAF, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x59, 0x24, 0xDD, 0xFB, 0x2F, 0xD0, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCD, 0x56, 0xE9, 0xAC, 0x91, 0xE6, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x64, 0x20, 0xC6, 0x9F, 0xE4, 0xEF, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x2C, 0x8F, 0x8C, 0x97, 0xF6, 0x22, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0x88, 0xAA, 0xA8, 0xD7, 0xA5, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_30_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x6C, 0xAE, 0x83, 0xB1, 0x55, 0x55, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x67, 0x84, 0x47, 0x7C, 0x83, 0x5C, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x10, 0x4D, 0xDD, 0x30, 0x60, 0xB0, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xA7, 0x36, 0x76, 0x24, 0x32, 0x9F, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x42, 0x81, 0xFB, 0xA4, 0x2E, 0x13, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x94, 0x91, 0xFF, 0x99, 0xA0, 0x09, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x83, 0xA1, 0x76, 0xAF, 0x37, 0x5C, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA8, 0x04, 0x86, 0xC4, 0xA9, 0x79, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_31_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8C, 0xC2, 0x34, 0xFB, 0x83, 0x28, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x03, 0x7D, 0x5E, 0x9E, 0x0E, 0xB0, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x02, 0x46, 0x7F, 0xB9, 0xAC, 0xBB, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xED, 0x48, 0xC2, 0x96, 0x4D, 0x56, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xC5, 0xD1, 0xE6, 0x1C, 0x7E, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x2E, 0x18, 0x71, 0x2D, 0x7B, 0xD7, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x46, 0x9D, 0xDE, 0xAA, 0x78, 0x8E, 0xB1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD7, 0x69, 0x2E, 0xE1, 0xD9, 0x48, 0xDE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp521r1_T_31_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFF, 0x9E, 0x09, 0x22, 0x22, 0xE6, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x14, 0x28, 0x13, 0x1B, 0x62, 0x12, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x7F, 0x67, 0x03, 0xB0, 0xC0, 0xF3, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xC3, 0x0F, 0xFB, 0x25, 0x48, 0x3E, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x6E, 0x53, 0x98, 0x36, 0xB3, 0xD3, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x81, 0x54, 0x22, 0xA4, 0xCC, 0xC1, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xBA, 0xFC, 0xA9, 0xDF, 0x68, 0x86, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x92, 0x0E, 0xC3, 0xF2, 0x58, 0xE8, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_ecp_point secp521r1_T[32] = {\n    ECP_POINT_INIT_XY_Z1(secp521r1_T_0_X, secp521r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_1_X, secp521r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_2_X, secp521r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_3_X, secp521r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_4_X, secp521r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_5_X, secp521r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_6_X, secp521r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_7_X, secp521r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_8_X, secp521r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_9_X, secp521r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_10_X, secp521r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_11_X, secp521r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_12_X, secp521r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_13_X, secp521r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_14_X, secp521r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_15_X, secp521r1_T_15_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_16_X, secp521r1_T_16_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_17_X, secp521r1_T_17_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_18_X, secp521r1_T_18_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_19_X, secp521r1_T_19_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_20_X, secp521r1_T_20_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_21_X, secp521r1_T_21_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_22_X, secp521r1_T_22_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_23_X, secp521r1_T_23_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_24_X, secp521r1_T_24_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_25_X, secp521r1_T_25_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_26_X, secp521r1_T_26_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_27_X, secp521r1_T_27_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_28_X, secp521r1_T_28_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_29_X, secp521r1_T_29_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_30_X, secp521r1_T_30_Y),\n    ECP_POINT_INIT_XY_Z0(secp521r1_T_31_X, secp521r1_T_31_Y),\n};\n#else\n#define secp521r1_T NULL\n#endif\n#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)\nstatic const mbedtls_mpi_uint secp192k1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp192k1_a[] = {\n    MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp192k1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_2(0x03, 0x00),\n};\nstatic const mbedtls_mpi_uint secp192k1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB),\n};\nstatic const mbedtls_mpi_uint secp192k1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B),\n};\nstatic const mbedtls_mpi_uint secp192k1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\n\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp192k1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x77, 0x3D, 0x0D, 0x85, 0x48, 0xA8, 0xA9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x07, 0xDF, 0x1D, 0xB3, 0xB3, 0x01, 0x54),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x86, 0xF6, 0xAF, 0x19, 0x2A, 0x88, 0x2E),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x90, 0xB6, 0x2F, 0x48, 0x36, 0x4C, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x11, 0x14, 0xA6, 0xCB, 0xBA, 0x15, 0xD9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB0, 0xF2, 0xD4, 0xC9, 0xDA, 0xBA, 0xD7),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xC1, 0x9C, 0xE6, 0xBB, 0xFB, 0xCF, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x19, 0xAC, 0x5A, 0xC9, 0x8A, 0x1C, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xF6, 0x76, 0x86, 0x89, 0x27, 0x8D, 0x28),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xE0, 0x6F, 0x34, 0xBA, 0x5E, 0xD3, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xDC, 0xA6, 0x87, 0xC9, 0x9D, 0xC0, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x11, 0x7E, 0xD6, 0xF7, 0x33, 0xFC, 0xE4),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x37, 0x3E, 0xC0, 0x7F, 0x62, 0xE7, 0x54),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3B, 0x69, 0x9D, 0x44, 0xBC, 0x82, 0x99),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x84, 0xB3, 0x5F, 0x2B, 0xA5, 0x9E, 0x2C),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x95, 0xEB, 0x4C, 0x04, 0xB4, 0xF4, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAD, 0x4B, 0xD5, 0x9A, 0xEB, 0xC4, 0x4E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xB1, 0xC5, 0x59, 0xE3, 0xD5, 0x16, 0x2A),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x2A, 0xCC, 0xAC, 0xD0, 0xEE, 0x50, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x83, 0xE0, 0x5B, 0x14, 0x44, 0x52, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x15, 0x2D, 0x78, 0xF6, 0x51, 0x32, 0xCF),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x36, 0x9B, 0xDD, 0xF8, 0xDD, 0xEF, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xB1, 0x6A, 0x2B, 0xAF, 0xEB, 0x2B, 0xB1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x87, 0x7A, 0x66, 0x5D, 0x5B, 0xDF, 0x8F),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x45, 0xE5, 0x81, 0x9B, 0xEB, 0x37, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x29, 0xE2, 0x20, 0x64, 0x23, 0x6B, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1D, 0x41, 0xE1, 0x9B, 0x61, 0x7B, 0xD9),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x57, 0xA3, 0x0A, 0x13, 0xE4, 0x59, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x6E, 0x4A, 0x48, 0x84, 0x90, 0xAC, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB8, 0xF5, 0xF3, 0xDE, 0xA0, 0xA1, 0x1D),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x32, 0x81, 0xA9, 0x91, 0x5A, 0x4E, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xA8, 0x90, 0xBE, 0x0F, 0xEC, 0xC0, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x30, 0xD7, 0x08, 0xAE, 0xC4, 0x3A, 0xA5),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x55, 0xE3, 0x76, 0xB3, 0x64, 0x74, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x75, 0xD4, 0xDB, 0x98, 0xD7, 0x39, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xEB, 0x8A, 0xAB, 0x16, 0xD9, 0xD4, 0x0B),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xBE, 0xF9, 0xC7, 0xC7, 0xBA, 0xF3, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x85, 0x59, 0xF3, 0x60, 0x41, 0x02, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x1C, 0x4A, 0xA4, 0xC7, 0xED, 0x66, 0xBC),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x2E, 0x46, 0x52, 0x18, 0x87, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x35, 0x5A, 0x75, 0xAC, 0x4D, 0x75, 0x91),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x2F, 0xAC, 0xFC, 0xBC, 0xE6, 0x93, 0x5E),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x4D, 0xC9, 0x18, 0xE9, 0x00, 0xEB, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x69, 0x72, 0x07, 0x5A, 0x59, 0xA8, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x65, 0x83, 0x20, 0x10, 0xF9, 0x69, 0x82),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x56, 0x7F, 0x9F, 0xBF, 0x46, 0x0C, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0xF0, 0xDC, 0xDF, 0x2D, 0xE6, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xF0, 0x72, 0x3A, 0x7A, 0x03, 0xE5, 0x22),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xAA, 0x57, 0x13, 0x37, 0xA7, 0x2C, 0xD4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xAC, 0xA2, 0x23, 0xF9, 0x84, 0x60, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xEB, 0x51, 0x70, 0x64, 0x78, 0xCA, 0x05),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xCC, 0x30, 0x62, 0x93, 0x46, 0x13, 0xE9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x26, 0xCC, 0x6C, 0x3D, 0x5C, 0xDA, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xAA, 0xB8, 0x03, 0xA4, 0x1A, 0x00, 0x96),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x9D, 0xE6, 0xCC, 0x4E, 0x2E, 0xC2, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xC3, 0x8A, 0xAE, 0x6F, 0x40, 0x05, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x8F, 0x4A, 0x4D, 0x35, 0xD3, 0x50, 0x9D),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xFD, 0x98, 0xAB, 0xC7, 0x03, 0xB4, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x40, 0xD2, 0x9F, 0xCA, 0xD0, 0x53, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x84, 0x00, 0x6F, 0xC8, 0xAD, 0xED, 0x8D),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xD3, 0x57, 0xD7, 0xC3, 0x07, 0xBD, 0xD7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xBA, 0x47, 0x1D, 0x3D, 0xEF, 0x98, 0x6C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC0, 0x6C, 0x7F, 0x12, 0xEE, 0x9F, 0x67),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x02, 0xDA, 0x79, 0xAA, 0xC9, 0x27, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x79, 0xC7, 0x71, 0x84, 0xCB, 0xE5, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x37, 0x06, 0xBA, 0xB5, 0xD5, 0x18, 0x4C),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x65, 0x72, 0x6C, 0xF2, 0x63, 0x27, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xBC, 0x71, 0xDF, 0x75, 0xF8, 0x98, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x70, 0x9B, 0xDC, 0xE7, 0x18, 0x71, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x5B, 0x9F, 0x00, 0x5A, 0xB6, 0x80, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE0, 0xBB, 0xFC, 0x5E, 0x78, 0x9C, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x03, 0x68, 0x83, 0x3D, 0x2E, 0x4C, 0xDD),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x49, 0x23, 0xA8, 0xCB, 0x3B, 0x1A, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x3D, 0xA7, 0x46, 0xCF, 0x75, 0xB6, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xFD, 0x30, 0x01, 0xB6, 0xEF, 0xF9, 0xE8),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xFA, 0xDA, 0xB8, 0x29, 0x42, 0xC9, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xD7, 0xA0, 0xE6, 0x6B, 0x86, 0x61, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xE9, 0xD3, 0x37, 0xD8, 0xE7, 0x35, 0xA9),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC8, 0x8E, 0xB1, 0xCB, 0xB1, 0xB5, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xD7, 0x46, 0x7D, 0xAF, 0xE2, 0xDC, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x46, 0xE7, 0xD8, 0x76, 0x31, 0x90, 0x76),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD3, 0xF4, 0x74, 0xE1, 0x67, 0xD8, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x70, 0x3C, 0xC8, 0xAF, 0x5F, 0xF4, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x4E, 0xED, 0x5C, 0x43, 0xB3, 0x16, 0x35),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAE, 0xD1, 0xDD, 0x31, 0x14, 0xD3, 0xF0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x14, 0x06, 0x13, 0x12, 0x1C, 0x81, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xF9, 0x0C, 0x91, 0xF7, 0x67, 0x59, 0x63),\n};\nstatic const mbedtls_mpi_uint secp192k1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x91, 0xE2, 0xF4, 0x9D, 0xEB, 0x88, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x82, 0x30, 0x9C, 0xAE, 0x18, 0x4D, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x79, 0xCF, 0x17, 0xA5, 0x1E, 0xE8, 0xC8),\n};\nstatic const mbedtls_ecp_point secp192k1_T[16] = {\n    ECP_POINT_INIT_XY_Z1(secp192k1_T_0_X, secp192k1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_1_X, secp192k1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_2_X, secp192k1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_3_X, secp192k1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_4_X, secp192k1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_5_X, secp192k1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_6_X, secp192k1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_7_X, secp192k1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_8_X, secp192k1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_9_X, secp192k1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_10_X, secp192k1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_11_X, secp192k1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_12_X, secp192k1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_13_X, secp192k1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_14_X, secp192k1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp192k1_T_15_X, secp192k1_T_15_Y),\n};\n#else\n#define secp192k1_T NULL\n#endif\n\n#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)\nstatic const mbedtls_mpi_uint secp224k1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp224k1_a[] = {\n    MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_2(0x05, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_4(0x33, 0x5B, 0x45, 0xA1),\n};\nstatic const mbedtls_mpi_uint secp224k1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_4(0xED, 0x9F, 0x08, 0x7E),\n};\nstatic const mbedtls_mpi_uint secp224k1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),\n};\n\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp224k1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x5B, 0x45, 0xA1, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x9F, 0x08, 0x7E, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x6C, 0x22, 0x22, 0x40, 0x89, 0xAE, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x92, 0xE1, 0x87, 0x56, 0x35, 0xAF, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xAF, 0x08, 0x35, 0x27, 0xEA, 0x04, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x53, 0xFD, 0xCF, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xD0, 0x9F, 0x8D, 0xF3, 0x63, 0x54, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xDB, 0x0F, 0x61, 0x54, 0x26, 0xD1, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x21, 0xF7, 0x1B, 0xB5, 0x1D, 0xF6, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x05, 0xDA, 0x8F, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x26, 0x73, 0xBC, 0xE4, 0x29, 0x62, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x95, 0x17, 0x8B, 0xC3, 0x9B, 0xAC, 0xCC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xDB, 0x77, 0xDF, 0xDD, 0x13, 0x04, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xFC, 0x22, 0x93, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0xF1, 0x5A, 0x37, 0xEF, 0x79, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x37, 0xAC, 0x9A, 0x5B, 0x51, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x75, 0x13, 0xA9, 0x4A, 0xAD, 0xFE, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x82, 0x6F, 0x66, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x5E, 0xF0, 0x40, 0xC3, 0xA6, 0xE2, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x9A, 0x6F, 0xCF, 0x11, 0x26, 0x66, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x73, 0xA8, 0xCF, 0x2B, 0x12, 0x36, 0x37),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xB3, 0x0A, 0x58, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x79, 0x00, 0x55, 0x04, 0x34, 0x90, 0x1A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x54, 0x1C, 0xC2, 0x45, 0x0C, 0x1B, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x19, 0xAB, 0xA8, 0xFC, 0x73, 0xDC, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xFB, 0x93, 0xCE, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x75, 0xD0, 0x66, 0x95, 0x86, 0xCA, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xEA, 0x29, 0x16, 0x6A, 0x38, 0xDF, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA2, 0x36, 0x2F, 0xDC, 0xBB, 0x5E, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x89, 0x59, 0x49, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xA3, 0x99, 0x9D, 0xB8, 0x77, 0x9D, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x93, 0x43, 0x47, 0xC6, 0x5C, 0xF9, 0xFD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x00, 0x79, 0x42, 0x64, 0xB8, 0x25, 0x3E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x54, 0xB4, 0x33, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x0C, 0x42, 0x90, 0x83, 0x0B, 0x31, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2E, 0xAE, 0xC8, 0xC7, 0x5F, 0xD2, 0x70),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xBC, 0xAD, 0x41, 0xE7, 0x32, 0x3A, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x97, 0x52, 0x83, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x13, 0x7A, 0xBD, 0xAE, 0x94, 0x60, 0xFD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x9B, 0x95, 0xB4, 0x6E, 0x68, 0xB2, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x49, 0xBE, 0x51, 0xFE, 0x66, 0x15, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x37, 0xE4, 0xFE, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x9B, 0xEE, 0x64, 0xC9, 0x1B, 0xBD, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x5F, 0x34, 0xA9, 0x0B, 0xB7, 0x25, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x13, 0xB1, 0x38, 0xFB, 0x9D, 0x78, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xE7, 0x1B, 0xFA, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xB3, 0xB7, 0x44, 0x92, 0x6B, 0x00, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x82, 0x44, 0x3E, 0x18, 0x1A, 0x58, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF8, 0xC0, 0xE4, 0xEE, 0xC1, 0xBF, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x32, 0x27, 0xB2, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x9A, 0x42, 0x62, 0x8B, 0x26, 0x54, 0x21),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x85, 0x74, 0xA0, 0x79, 0xA8, 0xEE, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0x60, 0xB3, 0x28, 0x4D, 0x55, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x27, 0x82, 0x29, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xFC, 0x73, 0x77, 0xAF, 0x5C, 0xAC, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xED, 0xE5, 0xF6, 0x1D, 0xA8, 0x67, 0x43),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xDE, 0x33, 0x1C, 0xF1, 0x80, 0x73, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE2, 0xDE, 0x3C, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x3E, 0x6B, 0xFE, 0xF0, 0x04, 0x28, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xB2, 0x14, 0x9D, 0x18, 0x11, 0x7D, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC4, 0xD6, 0x2E, 0x6E, 0x57, 0x4D, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x55, 0x1B, 0xDE, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xF7, 0x17, 0xBC, 0x45, 0xAB, 0x16, 0xAB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xB0, 0xEF, 0x61, 0xE3, 0x20, 0x7C, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x85, 0x41, 0x4D, 0xF1, 0x7E, 0x4D, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC2, 0x9B, 0x5E, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x2E, 0x49, 0x3D, 0x3E, 0x4B, 0xD3, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x2B, 0x9D, 0xD5, 0x27, 0xFA, 0xCA, 0xE0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xB3, 0x6A, 0xE0, 0x79, 0x14, 0x28, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x1E, 0xDC, 0xF5, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x44, 0x56, 0xCD, 0xFC, 0x9F, 0x09, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x8C, 0x59, 0xA4, 0x64, 0x2A, 0x3A, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xA0, 0xB5, 0x86, 0x4E, 0x69, 0xDA, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x8B, 0x11, 0x38, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x17, 0x16, 0x12, 0x17, 0xDC, 0x00, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x76, 0x24, 0x6C, 0x97, 0x2C, 0xB5, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x71, 0xE3, 0xB0, 0xBB, 0x4E, 0x50, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x48, 0x26, 0xD5, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x5F, 0x28, 0xF6, 0x01, 0x5A, 0x60, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x95, 0xFE, 0xD0, 0xAD, 0x15, 0xD4, 0xD9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0x7A, 0xFD, 0x80, 0xF7, 0x9F, 0x64),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xBC, 0x1B, 0xDF, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xE6, 0xDF, 0x14, 0x29, 0xF4, 0xD4, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x12, 0xDD, 0xEC, 0x5B, 0x8A, 0x59, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x92, 0x3E, 0x35, 0x08, 0xE9, 0xCF, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x35, 0x29, 0x97, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xDB, 0xD6, 0x6A, 0xC5, 0x43, 0xA4, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x33, 0x50, 0x61, 0x70, 0xA1, 0xE9, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x15, 0x6E, 0x5F, 0x01, 0x0C, 0x8C, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xA1, 0x9A, 0x9D, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xC6, 0xF7, 0xE2, 0x4A, 0xCD, 0x9B, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x4D, 0x5A, 0xB8, 0xE2, 0x6D, 0xA6, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3F, 0xB6, 0x17, 0xE3, 0x2C, 0x6F, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA4, 0x59, 0x51, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x4F, 0x7C, 0x49, 0xCD, 0x6E, 0xEB, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xC9, 0x1F, 0xB7, 0x4D, 0x98, 0xC7, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xFD, 0x98, 0x20, 0x95, 0xBB, 0x20, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF2, 0x73, 0x92, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xEF, 0xFB, 0x30, 0xFA, 0x12, 0x1A, 0xB0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x4C, 0x24, 0xB4, 0x5B, 0xC9, 0x4C, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xDD, 0x5E, 0x84, 0x95, 0x4D, 0x26, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xFA, 0xF9, 0x3A, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xA3, 0x2E, 0x7A, 0xDC, 0xA7, 0x53, 0xA9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x9F, 0x81, 0x84, 0xB2, 0x0D, 0xFE, 0x31),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x89, 0x1B, 0x77, 0x0C, 0x89, 0x71, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0x7F, 0xB2, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xE9, 0x2C, 0x79, 0xA6, 0x3C, 0xAD, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE0, 0x23, 0x02, 0x86, 0x0F, 0x77, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x93, 0x6D, 0xE9, 0xF9, 0x3C, 0xBE, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xE7, 0x24, 0x92, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x3C, 0x5B, 0x4B, 0x1B, 0x25, 0x37, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xE8, 0x38, 0x1B, 0xA1, 0x5A, 0x2E, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x19, 0xFD, 0xF4, 0x78, 0x01, 0x6B, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x69, 0x37, 0x4F, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xE2, 0xBF, 0xD3, 0xEC, 0x95, 0x9C, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x7B, 0xFC, 0xD5, 0xD3, 0x25, 0x5E, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x55, 0x09, 0xA2, 0x58, 0x6A, 0xC9, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xCC, 0x3B, 0xD9, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp224k1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x08, 0x65, 0x5E, 0xCB, 0xAB, 0x48, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x79, 0x8B, 0xC0, 0x11, 0xC0, 0x69, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xE8, 0x8C, 0x4C, 0xC5, 0x28, 0xE4, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x1F, 0x34, 0x5C, 0x00, 0x00, 0x00, 0x00),\n};\nstatic const mbedtls_ecp_point secp224k1_T[16] = {\n    ECP_POINT_INIT_XY_Z1(secp224k1_T_0_X, secp224k1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_1_X, secp224k1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_2_X, secp224k1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_3_X, secp224k1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_4_X, secp224k1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_5_X, secp224k1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_6_X, secp224k1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_7_X, secp224k1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_8_X, secp224k1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_9_X, secp224k1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_10_X, secp224k1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_11_X, secp224k1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_12_X, secp224k1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_13_X, secp224k1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_14_X, secp224k1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp224k1_T_15_X, secp224k1_T_15_Y),\n};\n#else\n#define secp224k1_T NULL\n#endif\n#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\nstatic const mbedtls_mpi_uint secp256k1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\nstatic const mbedtls_mpi_uint secp256k1_a[] = {\n    MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00),\n};\nstatic const mbedtls_mpi_uint secp256k1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_2(0x07, 0x00),\n};\nstatic const mbedtls_mpi_uint secp256k1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79),\n};\nstatic const mbedtls_mpi_uint secp256k1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48),\n};\nstatic const mbedtls_mpi_uint secp256k1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),\n};\n\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint secp256k1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xEE, 0xD7, 0x1E, 0x67, 0x86, 0x32, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0xB1, 0xA9, 0xD5, 0xCC, 0x27, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0E, 0x11, 0x01, 0x71, 0xFE, 0x92, 0x73),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x28, 0x63, 0x6D, 0x72, 0x09, 0xA6, 0xC0),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0x69, 0xDC, 0x3E, 0x2C, 0x75, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xB7, 0x3F, 0x30, 0x26, 0x3C, 0xDF, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBE, 0xB9, 0x5D, 0x0E, 0xE8, 0x5E, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xC3, 0x05, 0xD6, 0xB7, 0xD5, 0x24, 0xFC),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCF, 0x7B, 0xDC, 0xCD, 0xC3, 0x39, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xDA, 0xB9, 0xE5, 0x64, 0xA7, 0x47, 0x91),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x46, 0xA8, 0x61, 0xF6, 0x23, 0xEB, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xC1, 0xFF, 0xE4, 0x55, 0xD5, 0xC2, 0xBF),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xBE, 0xB9, 0x59, 0x24, 0x13, 0x4A, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x45, 0x12, 0xDE, 0xBA, 0x4F, 0xEF, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x08, 0xBF, 0xC1, 0x66, 0xAA, 0x0A, 0xBC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xFE, 0x30, 0x55, 0x31, 0x86, 0xA7, 0xB4),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBF, 0x18, 0x81, 0x67, 0x27, 0x42, 0xBD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x05, 0x83, 0xA4, 0xDD, 0x57, 0xD3, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x63, 0xAB, 0xE4, 0x90, 0x70, 0xD0, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x5D, 0xFD, 0xA0, 0xEF, 0xCF, 0x1C, 0x54),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x80, 0xE4, 0xF6, 0x09, 0xBC, 0x57, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x9F, 0x6E, 0x88, 0x54, 0x6E, 0x51, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x5F, 0x85, 0xFB, 0x84, 0x3E, 0x4A, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x19, 0xF5, 0x55, 0xC9, 0x07, 0xD8, 0xCE),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xB4, 0xC3, 0xD9, 0x5C, 0xA0, 0xD4, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x30, 0xAF, 0x59, 0x9B, 0xF8, 0x04, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xA6, 0xFD, 0x66, 0x7B, 0xC3, 0x39, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xBF, 0xF0, 0xC2, 0xE9, 0x71, 0xA4, 0x9E),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x2D, 0xB9, 0x88, 0x28, 0xF1, 0xBE, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF3, 0x1A, 0x0E, 0xB9, 0x01, 0x66, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0xA4, 0xF4, 0x05, 0xD0, 0xAA, 0x53),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x39, 0x1E, 0x47, 0xE5, 0x68, 0xC8, 0xC0),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xB9, 0xFC, 0xE0, 0x33, 0x8A, 0x7D, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x93, 0xA5, 0x53, 0x55, 0x16, 0xB4, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x5F, 0xEA, 0x9B, 0x29, 0x52, 0x71, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xF0, 0x24, 0xB8, 0x7D, 0xB7, 0xA0, 0x9B),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x00, 0x27, 0xB2, 0xDF, 0x73, 0xA2, 0xE0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x2E, 0x4D, 0x7C, 0xDE, 0x7A, 0x23, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0x60, 0xC7, 0x97, 0x1E, 0xA4, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x13, 0x5B, 0x77, 0x59, 0xCB, 0x36, 0xE1),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xBC, 0x9F, 0x9E, 0x2D, 0x53, 0x2A, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x5F, 0x64, 0x9F, 0x1A, 0x19, 0xE6, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x7B, 0x39, 0xD2, 0xDB, 0x85, 0x84, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xC7, 0x0D, 0x58, 0x6E, 0x3F, 0x52, 0x15),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x68, 0x19, 0x0B, 0x68, 0xC9, 0x1E, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x4E, 0x21, 0x49, 0x3D, 0x55, 0xCC, 0x25),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF9, 0x25, 0x45, 0x54, 0x45, 0xB1, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xF7, 0xCD, 0x80, 0xA4, 0x04, 0x05),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x1E, 0x88, 0xC4, 0xAA, 0x18, 0x7E, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xAC, 0xD9, 0xB2, 0xA1, 0xC0, 0x71, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xA2, 0xF1, 0x15, 0xA6, 0x5F, 0x6C, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x5B, 0x05, 0xBC, 0xB7, 0xC6, 0x4E, 0x72),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x80, 0xF8, 0x5C, 0x20, 0x2A, 0xE1, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x48, 0x2E, 0x68, 0x82, 0x7F, 0xEB, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x3B, 0x25, 0xDB, 0x32, 0x4D, 0x88, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x6E, 0xA6, 0xB6, 0x6D, 0x62, 0x78, 0x22),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4D, 0x3E, 0x86, 0x58, 0xC3, 0xEB, 0xBA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x89, 0x33, 0x18, 0x21, 0x1D, 0x9B, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x9D, 0xFF, 0xC3, 0x79, 0xC1, 0x88, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xD4, 0x48, 0x53, 0xE8, 0xAD, 0x21, 0x16),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x7B, 0xDE, 0xCB, 0xD8, 0x39, 0x17, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xF3, 0x03, 0xF2, 0x5C, 0xBC, 0xC8, 0x8A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xAE, 0x4C, 0xB0, 0x16, 0xA4, 0x93, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8B, 0x6B, 0xDC, 0xD7, 0x9A, 0x3E, 0x7E),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x2D, 0x7A, 0xD2, 0x59, 0x05, 0xA2, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x56, 0x09, 0x32, 0xF1, 0xE8, 0xE3, 0x72),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xCA, 0xE5, 0x2E, 0xF0, 0xFB, 0x18, 0x19),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x85, 0xA9, 0x23, 0x15, 0x31, 0x1F, 0x0E),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xE5, 0xB1, 0x86, 0xB9, 0x6E, 0x8D, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x77, 0xFC, 0xC9, 0xA3, 0x3F, 0x89, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x6A, 0xDC, 0x25, 0xB0, 0xC7, 0x41, 0x54),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x11, 0x6B, 0xA6, 0x11, 0x62, 0xD4, 0x2D),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7D, 0x34, 0xB3, 0x20, 0x7F, 0x37, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xD4, 0x45, 0xE8, 0xC2, 0xE9, 0xC5, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x32, 0x3B, 0x25, 0x7E, 0x79, 0xAF, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xE4, 0x54, 0x71, 0xBE, 0x35, 0x4E, 0xD0),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x94, 0xDD, 0x8F, 0xB5, 0xC2, 0xDD, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x49, 0xE9, 0x1C, 0x2F, 0x08, 0x49, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xB6, 0x03, 0x88, 0x6F, 0xB8, 0x15, 0x67),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xD3, 0x1C, 0xF3, 0xA5, 0xEB, 0x79, 0x01),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF9, 0x43, 0x88, 0x89, 0x0D, 0x06, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2D, 0xF5, 0x98, 0x32, 0xF6, 0xB1, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0x8F, 0x2B, 0x50, 0x27, 0x0A, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE3, 0xBD, 0x16, 0x05, 0xC8, 0x93, 0x12),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x6A, 0xF7, 0xE3, 0x3D, 0xDE, 0x5F, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA3, 0x9C, 0x22, 0x3C, 0x33, 0x36, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x24, 0x4C, 0x69, 0x45, 0x78, 0x14, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xF8, 0xD4, 0xBF, 0xB8, 0xC0, 0xA1, 0x25),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x88, 0xE1, 0x91, 0x03, 0xEB, 0xB3, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x11, 0xA1, 0xEF, 0x14, 0x0D, 0xC4, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xD4, 0x0D, 0x1D, 0x96, 0x33, 0x5C, 0x19),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x45, 0x2A, 0x1A, 0xE6, 0x57, 0x04, 0x9B),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xB5, 0xA7, 0x80, 0xE9, 0x93, 0x97, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xB9, 0x7C, 0xA0, 0xC9, 0x57, 0x26, 0x43),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xEF, 0x56, 0xDA, 0x66, 0xF6, 0x1B, 0x9A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x89, 0x6B, 0x91, 0xE0, 0xA9, 0x65, 0x2B),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x98, 0x96, 0x9B, 0x06, 0x7D, 0x5E, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xFA, 0xC1, 0x5F, 0x19, 0x37, 0x94, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xBE, 0x6B, 0x1A, 0x05, 0xE4, 0xBF, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xCD, 0x5D, 0x35, 0xB4, 0x51, 0xF7, 0x64),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xEF, 0x96, 0xDB, 0xF2, 0x61, 0x63, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x04, 0x88, 0xC9, 0x9F, 0x1B, 0x94, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x30, 0x79, 0x7E, 0x24, 0xE7, 0x5F, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xB8, 0x90, 0xB7, 0x94, 0x25, 0xBB, 0x0F),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x79, 0xEA, 0xAD, 0xC0, 0x6D, 0x18, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xA4, 0x58, 0x2A, 0x8D, 0x95, 0xB3, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC4, 0xC2, 0x12, 0x0D, 0x79, 0xE2, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6F, 0xBE, 0x97, 0x4D, 0xA4, 0x20, 0x07),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x31, 0x71, 0xC6, 0xA6, 0x91, 0xEB, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x9B, 0xA8, 0x4A, 0xE7, 0x77, 0xE1, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x06, 0xD3, 0x3D, 0x94, 0x30, 0xEF, 0x8C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xDF, 0xCA, 0xFA, 0xF5, 0x28, 0xF8, 0xC9),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xE1, 0x32, 0xFD, 0x3E, 0x81, 0xF8, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xF2, 0x4B, 0x1D, 0x19, 0xC9, 0x0F, 0xCC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB1, 0x8A, 0x22, 0x8B, 0x05, 0x6B, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x21, 0xEF, 0x30, 0xEC, 0x09, 0x2A, 0x89),\n};\nstatic const mbedtls_mpi_uint secp256k1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x84, 0x4A, 0x46, 0x07, 0x6C, 0x3C, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x18, 0x3A, 0xF4, 0xCC, 0xF5, 0xB2, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x8F, 0xCD, 0x0A, 0x9C, 0xF4, 0xBD, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x89, 0x7F, 0x8A, 0xB1, 0x52, 0x3A, 0xAB),\n};\nstatic const mbedtls_ecp_point secp256k1_T[16] = {\n    ECP_POINT_INIT_XY_Z1(secp256k1_T_0_X, secp256k1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_1_X, secp256k1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_2_X, secp256k1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_3_X, secp256k1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_4_X, secp256k1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_5_X, secp256k1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_6_X, secp256k1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_7_X, secp256k1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_8_X, secp256k1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_9_X, secp256k1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_10_X, secp256k1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_11_X, secp256k1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_12_X, secp256k1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_13_X, secp256k1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_14_X, secp256k1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(secp256k1_T_15_X, secp256k1_T_15_Y),\n};\n#else\n#define secp256k1_T NULL\n#endif\n#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */\n\n/*\n * Domain parameters for brainpoolP256r1 (RFC 5639 3.4)\n */\n#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)\nstatic const mbedtls_mpi_uint brainpoolP256r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_a[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9),\n};\n\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xA2, 0xED, 0x52, 0xC9, 0x8C, 0xE3, 0xA5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xC9, 0xC4, 0x87, 0x3F, 0x93, 0x7A, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x12, 0x53, 0x61, 0x3E, 0x76, 0x08, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x8C, 0x74, 0xF4, 0x08, 0xC3, 0x76, 0x80),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xDD, 0x09, 0xA6, 0xED, 0xEE, 0xC4, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xD9, 0xBE, 0x4B, 0xA5, 0xB7, 0x2B, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x20, 0x12, 0xCA, 0x0A, 0x38, 0x24, 0xAB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x72, 0x71, 0x90, 0x7A, 0x2E, 0xB7, 0x23),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0xA1, 0x93, 0x10, 0x2A, 0x51, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x10, 0x11, 0x12, 0xBC, 0xB0, 0xB6, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x58, 0xD7, 0x0A, 0x84, 0x05, 0xA3, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x8E, 0x95, 0x61, 0xD3, 0x0B, 0xDF, 0x36),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x92, 0x12, 0x0F, 0x5E, 0x87, 0x70, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xE9, 0x9B, 0xEB, 0x3A, 0xFB, 0xCF, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0x92, 0xB9, 0xF7, 0x45, 0xD3, 0x06, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x28, 0x65, 0xE1, 0xC5, 0x6C, 0x57, 0x18),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x0E, 0x77, 0x01, 0x81, 0x9E, 0x38, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xF0, 0xD5, 0xA5, 0x91, 0x2B, 0xDF, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xEE, 0xB6, 0x25, 0xD6, 0x98, 0xDE, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0x55, 0x63, 0x39, 0xEB, 0xB5, 0x47),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD6, 0xB8, 0xE3, 0x13, 0xED, 0x7F, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xE8, 0xAE, 0x36, 0xB8, 0xCD, 0x19, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x82, 0x83, 0x7A, 0x7B, 0x46, 0x56, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x60, 0x46, 0x15, 0x5A, 0xAC, 0x99, 0x30),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x61, 0x50, 0xC6, 0xFF, 0x10, 0x7D, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x51, 0xDF, 0xA9, 0x7D, 0x78, 0x26, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x15, 0x9A, 0xF7, 0x01, 0xC1, 0xBB, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x0F, 0xE6, 0x2A, 0xBD, 0x4A, 0x9E, 0x87),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF8, 0xD1, 0x77, 0xD2, 0x49, 0xB3, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x86, 0xFB, 0x9E, 0x1F, 0x5A, 0x60, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xC4, 0x8D, 0xCD, 0x86, 0x61, 0x2F, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xF6, 0xB9, 0xAC, 0x37, 0x9D, 0xE9, 0x28),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x77, 0xAA, 0x97, 0x9C, 0x0B, 0x04, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xA6, 0x60, 0x81, 0xCE, 0x25, 0x13, 0x3E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x00, 0xF3, 0xBB, 0x82, 0x99, 0x95, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0xCE, 0x90, 0x71, 0x38, 0x2F, 0x10),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x1A, 0xC0, 0x84, 0x27, 0xD6, 0x9D, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x37, 0x52, 0x16, 0x13, 0x0E, 0xCE, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBF, 0x5A, 0xDB, 0xDB, 0x6E, 0x1E, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB7, 0x5E, 0xF9, 0x86, 0xDD, 0x8A, 0x5C),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xAB, 0x5C, 0x8D, 0x1D, 0xF2, 0x2D, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC5, 0xF8, 0xF7, 0x1D, 0x96, 0x0B, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x4C, 0xA7, 0x45, 0x20, 0x6A, 0x1E, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x5D, 0xEF, 0xDE, 0xEE, 0x39, 0x44, 0x19),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x2F, 0x6D, 0x52, 0xC9, 0x58, 0x60, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xC9, 0x62, 0xCB, 0x38, 0x3C, 0x55, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xA5, 0x09, 0x10, 0x88, 0xDB, 0xE3, 0xBD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xE0, 0x3C, 0xCE, 0x06, 0x0B, 0x4B, 0x5D),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x1D, 0xB4, 0x10, 0x76, 0x8F, 0xBA, 0x09),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x70, 0x5A, 0x07, 0xF5, 0x1A, 0x74, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xE9, 0x94, 0xA8, 0xC0, 0xD5, 0x4A, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x6D, 0xD4, 0xE8, 0x9B, 0xE9, 0x6D, 0x0E),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x00, 0x32, 0x41, 0x57, 0x84, 0x89, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC7, 0x14, 0xEC, 0xE9, 0x27, 0xFF, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x67, 0x9E, 0xFB, 0xB6, 0xB8, 0x96, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x4A, 0xE3, 0x97, 0x4B, 0x58, 0xDE, 0x30),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x1E, 0x5C, 0xF5, 0x7F, 0xD5, 0xD4, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x08, 0x7A, 0xF1, 0xBD, 0x89, 0xC7, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xF9, 0x11, 0x1B, 0xF5, 0x3C, 0x6D, 0x8C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x50, 0xE5, 0x69, 0x1D, 0x59, 0xFC, 0x0C),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x2F, 0xF8, 0x3F, 0xEC, 0x55, 0x99, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xA7, 0x29, 0x90, 0x43, 0x81, 0x31, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x18, 0x44, 0x50, 0x5D, 0x76, 0xCB, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xC5, 0x5B, 0x9A, 0x03, 0xE6, 0x17, 0x39),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x89, 0xFC, 0x55, 0x94, 0x91, 0x6A, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x46, 0x35, 0xF2, 0x3A, 0x42, 0x08, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xD2, 0x76, 0x49, 0x42, 0x87, 0xD3, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xEA, 0xA0, 0x52, 0xF1, 0x6A, 0x30, 0x57),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xB2, 0x57, 0xA3, 0x8A, 0x4D, 0x1B, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xA3, 0x99, 0x94, 0xB5, 0x3D, 0x64, 0x09),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC3, 0xD7, 0x53, 0xF6, 0x49, 0x1C, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x23, 0x41, 0x4D, 0xFB, 0x7A, 0x5C, 0x53),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xB8, 0x15, 0x65, 0x5C, 0x85, 0x94, 0xD7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x37, 0xC7, 0xF8, 0x7E, 0xAE, 0x6C, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xD8, 0x11, 0x54, 0x98, 0x44, 0xE3, 0xF1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x4D, 0xA6, 0x4B, 0x28, 0xF2, 0x57, 0x9E),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD0, 0xEB, 0x1E, 0xAA, 0x30, 0xD3, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x9B, 0x4D, 0xA7, 0x73, 0x6E, 0xB6, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x47, 0xF6, 0xED, 0x37, 0xEF, 0x71, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xB5, 0x49, 0x61, 0x5E, 0x45, 0xF6, 0x4A),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x0E, 0xB3, 0x84, 0x3A, 0x63, 0x72, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x53, 0x5C, 0xA7, 0xC6, 0x2E, 0xAB, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x0F, 0x8F, 0x87, 0x50, 0x28, 0xB4, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x98, 0x4A, 0x98, 0x31, 0x86, 0xCA, 0x51),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC9, 0xE2, 0xFD, 0x5D, 0x1F, 0xE8, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x90, 0x91, 0xC4, 0x84, 0xF0, 0xBA, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5A, 0xB3, 0x4E, 0xFB, 0xE0, 0x57, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x0B, 0x90, 0xA6, 0xFD, 0x9D, 0x8E, 0x02),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x41, 0x8F, 0x31, 0xFA, 0x5A, 0xF6, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xE9, 0xE3, 0xF6, 0xE0, 0x4A, 0xE7, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x4E, 0xCD, 0xA2, 0x22, 0x14, 0xD4, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xED, 0x21, 0xB7, 0x0F, 0x53, 0x10, 0x17),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x06, 0x24, 0x2C, 0x4E, 0xD1, 0x1E, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x3F, 0xC1, 0x9F, 0xAB, 0xF0, 0x37, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x5E, 0x12, 0xCE, 0x83, 0x1B, 0x2A, 0x18),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x65, 0xCF, 0xE8, 0x5C, 0xA5, 0xA2, 0x70),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x86, 0x76, 0x3A, 0x94, 0xF6, 0x1D, 0xC1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xDA, 0xC9, 0xA6, 0x29, 0x93, 0x15, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x61, 0x6A, 0x7D, 0xC7, 0xA9, 0xF3, 0x76),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x03, 0x71, 0xA2, 0x15, 0xCE, 0x50, 0x72),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD0, 0xA8, 0x1E, 0x91, 0xC4, 0x4F, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x4B, 0x7E, 0xD7, 0x71, 0x58, 0x7E, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x45, 0xAF, 0x2A, 0x18, 0x93, 0x95, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x8F, 0xC7, 0xFA, 0x4C, 0x7A, 0x86, 0x54),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xAF, 0x68, 0x3A, 0x23, 0xC1, 0x2E, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x50, 0x11, 0x67, 0x39, 0xB9, 0xAF, 0x48),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x86, 0xAA, 0x1E, 0x88, 0x21, 0x29, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x28, 0xA4, 0x9D, 0x89, 0xA9, 0x9A, 0x10),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBA, 0x04, 0x67, 0xB7, 0x01, 0x40, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xE9, 0x09, 0xA3, 0xCA, 0xA6, 0x37, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x97, 0xA8, 0xB6, 0x3C, 0xEE, 0x90, 0x3D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xED, 0xC4, 0xF7, 0xC3, 0x95, 0xEC, 0x85),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x84, 0xBD, 0xEB, 0xD5, 0x64, 0xBB, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x9B, 0xE2, 0x28, 0x50, 0xC2, 0x72, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xF2, 0x74, 0xD1, 0x26, 0xBF, 0x32, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xCB, 0xAF, 0x72, 0xDB, 0x6D, 0x30, 0x98),\n};\nstatic const mbedtls_mpi_uint brainpoolP256r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x50, 0x85, 0xF4, 0x2B, 0x48, 0xC1, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x28, 0xBB, 0x11, 0xBA, 0x5B, 0x22, 0x6C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA1, 0xE5, 0x5C, 0xC9, 0x1D, 0x44, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xE8, 0xE6, 0x6F, 0xBB, 0xC1, 0x81, 0x7F),\n};\nstatic const mbedtls_ecp_point brainpoolP256r1_T[16] = {\n    ECP_POINT_INIT_XY_Z1(brainpoolP256r1_T_0_X, brainpoolP256r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_1_X, brainpoolP256r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_2_X, brainpoolP256r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_3_X, brainpoolP256r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_4_X, brainpoolP256r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_5_X, brainpoolP256r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_6_X, brainpoolP256r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_7_X, brainpoolP256r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_8_X, brainpoolP256r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_9_X, brainpoolP256r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_10_X, brainpoolP256r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_11_X, brainpoolP256r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_12_X, brainpoolP256r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_13_X, brainpoolP256r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_14_X, brainpoolP256r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_15_X, brainpoolP256r1_T_15_Y),\n};\n#else\n#define brainpoolP256r1_T NULL\n#endif\n\n#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */\n\n/*\n * Domain parameters for brainpoolP384r1 (RFC 5639 3.6)\n */\n#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)\nstatic const mbedtls_mpi_uint brainpoolP384r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_a[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C),\n};\n\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xD8, 0x8A, 0x54, 0x41, 0xD6, 0x6B, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x3B, 0xF1, 0x22, 0xFD, 0x2D, 0x4B, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x55, 0xE3, 0x33, 0xF0, 0x73, 0x52, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x3F, 0x30, 0x26, 0xCA, 0x7F, 0x52, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x6E, 0x17, 0x9B, 0xD5, 0x2A, 0x4A, 0x31),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xDA, 0x6B, 0xE5, 0x03, 0x07, 0x1D, 0x2E),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x7A, 0xAF, 0x98, 0xE3, 0xA4, 0xF6, 0x19),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x7D, 0xFE, 0x51, 0x40, 0x3B, 0x47, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x88, 0xEC, 0xC4, 0xE2, 0x8F, 0xCB, 0xA4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xE2, 0x88, 0x2D, 0x4E, 0x50, 0xEB, 0x9A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x54, 0x94, 0x5E, 0xF4, 0x7F, 0x3A, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x07, 0x1C, 0xE1, 0xBD, 0x0F, 0xF8, 0x63),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x92, 0x28, 0x2E, 0x32, 0x04, 0xB1, 0x4D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x82, 0x44, 0x43, 0x76, 0x0D, 0x55, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xE3, 0xFF, 0x89, 0x46, 0xDE, 0x4E, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x22, 0xBB, 0x67, 0x1A, 0x81, 0xEE, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x54, 0xE2, 0x7A, 0xAE, 0xDA, 0x2C, 0xD0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x9A, 0x90, 0xAA, 0x6E, 0x8B, 0xCC, 0x5F),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x40, 0xAC, 0xED, 0x7D, 0x37, 0x87, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xF8, 0xB1, 0x80, 0x4C, 0x8C, 0x04, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x98, 0x2C, 0xAD, 0x30, 0x69, 0x35, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x2E, 0x00, 0x2F, 0x44, 0x8C, 0xF0, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x58, 0x07, 0xD7, 0xCD, 0x60, 0xA1, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFB, 0x7B, 0x03, 0x05, 0x5E, 0x79, 0x73),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x17, 0xCE, 0x38, 0x4B, 0x5E, 0x5B, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x0E, 0x0A, 0x61, 0x9D, 0x7C, 0x62, 0x08),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF0, 0x98, 0x71, 0x7F, 0x17, 0x26, 0xD7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xD3, 0xFA, 0x3C, 0xF0, 0x70, 0x07, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x47, 0x5C, 0x09, 0x43, 0xB7, 0x65, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xA7, 0x3E, 0xFA, 0xF3, 0xEC, 0x22),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x78, 0x22, 0x2B, 0x58, 0x71, 0xFA, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x30, 0xCE, 0x6A, 0xB3, 0xB0, 0x4F, 0x83),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x95, 0x20, 0xA9, 0x23, 0xC2, 0x65, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xCF, 0x03, 0x5B, 0x8A, 0x80, 0x44, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xF8, 0x91, 0xF7, 0xD5, 0xED, 0xEA, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x5B, 0x16, 0x10, 0x25, 0xAC, 0x2A, 0x17),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEC, 0xDC, 0xC4, 0x7B, 0x8C, 0x6B, 0xE9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBB, 0x1C, 0xD3, 0x5A, 0xEE, 0xD9, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5D, 0x30, 0x5E, 0xF7, 0xB2, 0x41, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xCE, 0x0F, 0x1A, 0xC6, 0x41, 0x64, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x18, 0xE1, 0xE3, 0x82, 0x15, 0x66, 0x4B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xE2, 0x24, 0x04, 0x72, 0x39, 0xA0, 0x7C),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x51, 0xA2, 0x58, 0x88, 0x62, 0xE1, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xD2, 0x65, 0x14, 0xE9, 0x4C, 0x82, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE1, 0xAC, 0x87, 0xAE, 0x31, 0x1A, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4F, 0x96, 0x1E, 0x85, 0x7A, 0xC3, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x86, 0xBB, 0xF0, 0xC0, 0x9D, 0x08, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x53, 0x03, 0x09, 0x80, 0x91, 0xEF, 0x68),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xD7, 0xAF, 0x6F, 0x69, 0x7B, 0x88, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x13, 0xE4, 0x30, 0xA2, 0x47, 0xB5, 0xC1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD2, 0xC0, 0xDD, 0x8A, 0x1C, 0x3C, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x8C, 0xB3, 0x4C, 0xBA, 0x8B, 0x6D, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xC7, 0xA1, 0xA8, 0x6E, 0x3C, 0x4F, 0xF1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x4A, 0x97, 0xC8, 0x03, 0x6F, 0x01, 0x82),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x18, 0x12, 0xA9, 0x39, 0xD5, 0x22, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA7, 0xC0, 0xBD, 0x9D, 0x8D, 0x78, 0x38),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xD0, 0x7F, 0xDF, 0xD0, 0x30, 0xDE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x73, 0x96, 0xEC, 0xA8, 0x1D, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xD1, 0x65, 0x66, 0xDC, 0xD9, 0xCF, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xED, 0x7B, 0x37, 0xAD, 0xE2, 0xBE, 0x2D),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x79, 0x42, 0x6A, 0x07, 0x66, 0xB1, 0xBD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x53, 0x62, 0x65, 0x92, 0x09, 0x4C, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xAF, 0xC3, 0x03, 0xF6, 0xF4, 0x2D, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xCA, 0x41, 0xD9, 0xA2, 0x69, 0x9B, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xB2, 0xA6, 0x8D, 0xE1, 0xAA, 0x61, 0x76),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xBA, 0x4D, 0x12, 0xB6, 0xBE, 0xF3, 0x7E),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x92, 0x22, 0x07, 0xCE, 0xC9, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA1, 0x7C, 0x91, 0xDB, 0x32, 0xF7, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x49, 0x4B, 0x6D, 0xFB, 0xD9, 0x70, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xFB, 0x4E, 0x4C, 0x5E, 0x66, 0x81, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xB3, 0xE1, 0x00, 0xB7, 0xD9, 0xCC, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x36, 0x8B, 0xC4, 0x39, 0x20, 0xFD, 0x30),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x1F, 0x60, 0x03, 0xBB, 0xD7, 0x60, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x3C, 0x62, 0xDD, 0x71, 0x95, 0xE9, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x5B, 0x7A, 0x5F, 0x68, 0x81, 0xC5, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xB5, 0xB9, 0x98, 0x42, 0x28, 0xA5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x29, 0x8E, 0x11, 0x49, 0xB4, 0xD7, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x3E, 0xD2, 0x30, 0xA1, 0xBA, 0xCA, 0x03),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x37, 0x64, 0x44, 0x2F, 0x03, 0xE5, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x42, 0xBC, 0xFF, 0xA2, 0x1A, 0x5F, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x04, 0xAB, 0x04, 0xE0, 0x24, 0xAD, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x45, 0x17, 0x67, 0x1F, 0x3E, 0x53, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x0F, 0xB3, 0x1B, 0x57, 0x54, 0xC2, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0xF8, 0xC4, 0x1B, 0x9B, 0xFA, 0x30),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x90, 0xFD, 0xFB, 0xCA, 0x49, 0x38, 0x4E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xCF, 0xC6, 0xDD, 0xF0, 0xFF, 0x8C, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x69, 0x9D, 0xBD, 0x5F, 0x33, 0xE9, 0xB4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x19, 0x82, 0x3D, 0xAC, 0x1C, 0x40, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC7, 0x02, 0x46, 0x14, 0x77, 0x00, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x05, 0xF2, 0x77, 0x3A, 0x66, 0x5C, 0x39),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xE6, 0x17, 0xDE, 0xB2, 0xA1, 0xE5, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x71, 0xEC, 0x9D, 0xD8, 0xF5, 0xD4, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xC6, 0x42, 0x5E, 0xE7, 0x18, 0xBA, 0xD0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x21, 0x68, 0x5A, 0x26, 0xFB, 0xD7, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x00, 0x5C, 0xBA, 0x8A, 0x34, 0xEC, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x3C, 0xAF, 0x53, 0xE8, 0x65, 0x35),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xEF, 0x28, 0xDC, 0x67, 0x05, 0xC8, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x78, 0xC3, 0x85, 0x49, 0xA0, 0xBC, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x3E, 0x2D, 0xA0, 0xCF, 0xD4, 0x7A, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x93, 0xFE, 0x60, 0xB3, 0x6E, 0x99, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xAD, 0x04, 0xE7, 0x49, 0xAF, 0x5E, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x7A, 0xED, 0xA6, 0x9E, 0x18, 0x09, 0x31),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x05, 0x94, 0x44, 0xDC, 0xB8, 0x85, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xB7, 0x37, 0xC2, 0x50, 0x75, 0x15, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xC6, 0x0F, 0xB2, 0xA9, 0x91, 0x3E, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x81, 0xAD, 0x25, 0xA1, 0x26, 0x73, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xF1, 0xD1, 0x61, 0x7C, 0x76, 0x8F, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xDB, 0x4A, 0xFF, 0x14, 0xA7, 0x48, 0x0B),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x73, 0xC6, 0xC2, 0xCC, 0xF1, 0x57, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xED, 0x73, 0x27, 0x70, 0x82, 0xB6, 0x5E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xBA, 0xAC, 0x3A, 0xCF, 0xF4, 0xEA, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xD6, 0xB1, 0x8F, 0x0E, 0x08, 0x2C, 0x5E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE3, 0x8F, 0x2F, 0x0E, 0xA1, 0xF3, 0x07),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xF5, 0x7C, 0x9B, 0x29, 0x0A, 0xF6, 0x28),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xEE, 0x17, 0x47, 0x34, 0x15, 0xA3, 0xAF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBE, 0x88, 0x48, 0xE7, 0xA2, 0xBB, 0xDE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xAD, 0xDC, 0x65, 0x61, 0x37, 0x0F, 0xC1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x67, 0xAD, 0xA2, 0x3A, 0x1C, 0x91, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x07, 0x0C, 0x3A, 0x41, 0x6E, 0x13, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBD, 0x7E, 0xED, 0xAA, 0x14, 0xDD, 0x61),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xDC, 0x20, 0x01, 0x72, 0x11, 0x48, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xC4, 0x7B, 0xF8, 0x62, 0x3D, 0xF0, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xC2, 0x3D, 0x2E, 0x52, 0xA3, 0x4A, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE2, 0x53, 0x46, 0x5E, 0x21, 0xF8, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xC7, 0x8F, 0xA9, 0x26, 0x42, 0x32, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xA6, 0xA0, 0x8D, 0x4B, 0x9A, 0x19, 0x03),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xAB, 0x6D, 0x1E, 0xFB, 0xEE, 0x60, 0x0C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x56, 0x3C, 0xC5, 0x5D, 0x10, 0x79, 0x1C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xBC, 0x41, 0x9F, 0x71, 0xEF, 0x02, 0xF9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x36, 0xC4, 0xD0, 0x88, 0x9B, 0x32, 0xFC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xD4, 0x5D, 0x17, 0x39, 0xE6, 0x22, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x26, 0x01, 0xCE, 0xBE, 0x4A, 0x9C, 0x27),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x6D, 0x11, 0xCA, 0x6C, 0x5A, 0x93, 0x0C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x96, 0x26, 0xAF, 0x2F, 0xE4, 0x30, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC1, 0x4C, 0xC6, 0x30, 0x1F, 0x5C, 0x04),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB3, 0xE8, 0xFC, 0x35, 0xEB, 0x63, 0x6C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x1D, 0xCA, 0xFC, 0x50, 0x36, 0x4B, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0E, 0x23, 0x5B, 0xAF, 0xEB, 0x2D, 0x31),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x88, 0xB6, 0xD7, 0x74, 0x4A, 0x23, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x66, 0xE2, 0xBB, 0x29, 0xA6, 0x4F, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x6F, 0x7E, 0x68, 0x6E, 0xA0, 0x14, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x73, 0xD4, 0xE8, 0xAB, 0x5B, 0xF6, 0x0D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xE0, 0x3C, 0x24, 0x00, 0x95, 0xE9, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x0D, 0x4F, 0x81, 0xD0, 0xF2, 0x3F, 0x00),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x1D, 0xCD, 0x78, 0x39, 0xC4, 0x6B, 0xD9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x45, 0xC7, 0xB8, 0x2F, 0xAA, 0x5D, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x8C, 0x6E, 0xA3, 0x24, 0xB2, 0xDB, 0x4B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x2D, 0xD9, 0xF1, 0xC7, 0x9B, 0x8A, 0xAF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xE1, 0x2C, 0xB9, 0x40, 0x37, 0x91, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2C, 0xB5, 0x23, 0x03, 0x2B, 0xAF, 0x2F),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x9D, 0x5A, 0x20, 0x10, 0xA9, 0x84, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x30, 0x89, 0x20, 0x13, 0xE9, 0xB2, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x52, 0xEB, 0x03, 0x18, 0x1F, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x9E, 0x1C, 0x35, 0x87, 0x92, 0x69, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xC9, 0x88, 0xAF, 0xC6, 0x6C, 0x83, 0x72),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD5, 0x7A, 0x54, 0x34, 0x99, 0xB6, 0x6F),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xAD, 0x45, 0x9B, 0x4B, 0x41, 0x4D, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x5D, 0xAB, 0x7F, 0x35, 0x34, 0xE9, 0x29),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBE, 0x78, 0x34, 0x44, 0xF3, 0x4A, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xDE, 0xE3, 0xC4, 0xEE, 0x0B, 0xF9, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x86, 0x16, 0x48, 0x32, 0xB8, 0x74, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEE, 0x7C, 0xBA, 0xBD, 0x81, 0xE3, 0x55),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x6A, 0xFA, 0x84, 0xDA, 0xB8, 0xD5, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x9F, 0x8A, 0xD5, 0x1B, 0x2E, 0x1A, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0C, 0x61, 0xE2, 0xFF, 0x5B, 0xE6, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x62, 0xC1, 0x87, 0x53, 0x1B, 0x92, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x90, 0x00, 0xD1, 0x6A, 0x0C, 0x0E, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x2E, 0xB5, 0x3B, 0x44, 0xB5, 0xA0, 0x78),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5D, 0x02, 0x58, 0xB5, 0xBE, 0x45, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xEF, 0x8E, 0x90, 0x4D, 0x2A, 0x32, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x75, 0x5C, 0x0A, 0x33, 0x8F, 0x36),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x6C, 0x95, 0xD4, 0x1F, 0xF3, 0xEB, 0xDA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xE4, 0x4C, 0x91, 0x20, 0xF3, 0x25, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x95, 0xEB, 0x29, 0x6F, 0x20, 0x34, 0x81),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x15, 0xE5, 0x13, 0x7E, 0x64, 0x8B, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xBC, 0x0D, 0x18, 0x7E, 0x37, 0x9E, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x82, 0x20, 0xF7, 0x2D, 0x7A, 0x77, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x29, 0xA2, 0xDB, 0x7A, 0xE6, 0x6F, 0xA5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xC6, 0x50, 0x5C, 0xBC, 0xE6, 0x4F, 0xBD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x9F, 0xD5, 0xE8, 0xC5, 0x3D, 0xB7, 0x30),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_16_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x03, 0x55, 0x10, 0xDB, 0xA6, 0x8B, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x17, 0xAE, 0x78, 0xC9, 0x1D, 0x43, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x35, 0x49, 0xD4, 0x47, 0x84, 0x8D, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x95, 0x2F, 0xEA, 0xBC, 0xB4, 0x18, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x48, 0xAE, 0x89, 0xF5, 0x65, 0x3D, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xF2, 0x2B, 0x20, 0xD1, 0x75, 0x50, 0x63),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_16_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xE6, 0x5C, 0x2C, 0xE0, 0x7D, 0xDF, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x07, 0x3E, 0xCE, 0x9F, 0x18, 0xB6, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xF8, 0xF0, 0xD5, 0xFA, 0x42, 0x1D, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x6C, 0x1D, 0x03, 0xC9, 0x0E, 0x2B, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x52, 0xA5, 0xB4, 0x63, 0xE1, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0xD9, 0xC4, 0xFD, 0x16, 0x60, 0x54),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_17_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x7D, 0xDE, 0xDF, 0x4B, 0x4A, 0xB0, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x4E, 0x8C, 0x94, 0xC1, 0xE2, 0x85, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xF0, 0xEA, 0xB5, 0x9B, 0x70, 0xEF, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xC2, 0x39, 0x5D, 0xF3, 0x2C, 0xD9, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x1C, 0x2E, 0xCC, 0x2F, 0x54, 0x87, 0x80),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x72, 0xC7, 0xB5, 0x50, 0xA3, 0x84, 0x77),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_17_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xD1, 0xAF, 0xA9, 0xB4, 0x8B, 0x5D, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xF6, 0x52, 0x8A, 0xC3, 0x56, 0xA5, 0x5E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x52, 0xFF, 0xEA, 0x05, 0x42, 0x77, 0x83),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x08, 0x90, 0x72, 0x86, 0xC4, 0xC3, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x15, 0xF8, 0xF1, 0x16, 0x67, 0xC6, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x87, 0xAC, 0x8F, 0x71, 0xEC, 0x83, 0x81),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_18_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xE1, 0xE6, 0x2D, 0x0E, 0x11, 0xA1, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xE2, 0xA8, 0x32, 0xE6, 0xE3, 0x83, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x56, 0xE5, 0xCD, 0xB7, 0x2B, 0x67, 0x6F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xED, 0xC9, 0x65, 0x6D, 0x87, 0xE1, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xFD, 0x9A, 0x53, 0x0E, 0xFA, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x4C, 0x4A, 0xE2, 0x23, 0x84, 0xFA, 0x01),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_18_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFE, 0x49, 0x81, 0xD1, 0x3E, 0xF4, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x72, 0xE0, 0xEF, 0x0D, 0xB8, 0x3E, 0x6F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x00, 0x0F, 0x5F, 0xCE, 0x60, 0x72, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCC, 0xD8, 0x03, 0x07, 0x6E, 0x5A, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x3A, 0x35, 0x50, 0x4E, 0x1F, 0xCA, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xEA, 0x88, 0x55, 0xBD, 0x6E, 0x05, 0x7F),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_19_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x6D, 0xF1, 0x97, 0xA6, 0x69, 0x39, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x41, 0x99, 0xFF, 0x3B, 0xA1, 0x26, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x2F, 0x95, 0x80, 0x12, 0x4A, 0x1B, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xBF, 0x51, 0xAA, 0xAE, 0x2D, 0xDA, 0xCF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1C, 0xB3, 0x52, 0x36, 0x49, 0xD4, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC1, 0x1F, 0x3A, 0xD3, 0x3E, 0x5C, 0x1A),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_19_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x51, 0xF7, 0x2B, 0xC8, 0xA9, 0xA7, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x4E, 0x7F, 0x98, 0x41, 0x66, 0xB0, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x1D, 0xC0, 0x42, 0xCD, 0xF8, 0xC3, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x41, 0x91, 0x7D, 0xCC, 0x8B, 0xCC, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xAE, 0x76, 0xED, 0x56, 0x18, 0xC5, 0xAB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x6A, 0x06, 0xA3, 0x7F, 0x65, 0x10, 0x1F),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_20_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xEC, 0x3C, 0x05, 0x05, 0xCA, 0xF6, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0xCD, 0x02, 0x51, 0x12, 0x16, 0x3C, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xEB, 0xB3, 0x43, 0x7B, 0xDD, 0xB2, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x90, 0x41, 0xDB, 0xE4, 0xF5, 0x91),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0E, 0x18, 0x2A, 0x5A, 0x83, 0x7C, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x37, 0xA1, 0x0D, 0xF1, 0x2F, 0x63, 0x79),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_20_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC0, 0xFA, 0x6F, 0x1F, 0x67, 0xCF, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x34, 0x45, 0xBB, 0xF4, 0xF9, 0x9B, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x69, 0xFE, 0x67, 0x1D, 0x64, 0x8F, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x39, 0xBF, 0xD8, 0xB3, 0xC7, 0xAD, 0x8A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x93, 0xFF, 0xF3, 0x28, 0xFA, 0x39, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF9, 0xC3, 0x85, 0x26, 0x7A, 0x88, 0x89),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_21_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD5, 0x79, 0xD8, 0x11, 0xDE, 0xEB, 0x4E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x46, 0xA4, 0x6A, 0xDA, 0x74, 0x34, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBD, 0xD3, 0xF5, 0x14, 0xEE, 0xFE, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4C, 0xA3, 0x71, 0x43, 0x65, 0xF8, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x6C, 0x35, 0xFA, 0x90, 0x25, 0xD8, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x34, 0x84, 0x96, 0xA1, 0x43, 0x03, 0x4D),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_21_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x3B, 0x3B, 0x2F, 0xCA, 0x59, 0xF2, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x48, 0x24, 0x74, 0xD8, 0x72, 0x90, 0xA3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x42, 0x74, 0x8C, 0x6F, 0x52, 0x19, 0x3D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9E, 0x41, 0x63, 0x68, 0x78, 0x4C, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x94, 0xB6, 0x6B, 0x38, 0x52, 0xA8, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x30, 0x25, 0x93, 0xA1, 0x6F, 0x6E, 0x68),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_22_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2F, 0x4B, 0x64, 0x79, 0x50, 0xFF, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x36, 0xED, 0x57, 0x39, 0x3B, 0xE7, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x85, 0xEA, 0x35, 0xD6, 0xC0, 0xA0, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x89, 0x3A, 0xCC, 0x22, 0x1C, 0x46, 0x02),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x7A, 0xB0, 0xA1, 0x1B, 0x69, 0x62, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xB8, 0x8A, 0x6C, 0x18, 0x85, 0x0D, 0x88),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_22_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB6, 0x50, 0xE9, 0x4E, 0x7F, 0xE8, 0x07),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5B, 0x5C, 0xD1, 0x4B, 0x11, 0x9A, 0xD8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x25, 0x56, 0x74, 0x51, 0x9C, 0xEC, 0x9C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x7F, 0xB6, 0x8A, 0xCB, 0x3A, 0x10, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x33, 0x07, 0x01, 0xE9, 0x49, 0x59, 0xE6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xA5, 0x2E, 0xF2, 0xBA, 0x32, 0x63, 0x44),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_23_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x06, 0x0B, 0xA5, 0x44, 0x27, 0x7F, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x74, 0xAC, 0x0F, 0xCC, 0x4F, 0x13, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB1, 0xBF, 0x97, 0x49, 0xA5, 0x1C, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x64, 0x68, 0x7B, 0x0F, 0xCC, 0x77, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x39, 0xF9, 0x4E, 0x84, 0x9C, 0xF6, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xCF, 0x6D, 0xE2, 0xA1, 0x2D, 0xF9, 0x2B),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_23_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC4, 0x90, 0x57, 0x31, 0x01, 0x05, 0x5E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x1E, 0xBB, 0xBF, 0x98, 0xA4, 0x7C, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xE3, 0xA0, 0xB2, 0xCD, 0x39, 0x9A, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x34, 0x60, 0x7A, 0x89, 0x98, 0xB5, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x20, 0x3D, 0x3A, 0x04, 0x8F, 0x5A, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x26, 0xB6, 0x49, 0x09, 0x9C, 0x0F, 0x59),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_24_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x66, 0xD2, 0x38, 0x2A, 0x62, 0x81, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xC8, 0x20, 0x5E, 0x28, 0xA3, 0x81, 0xA7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x31, 0xA4, 0xF1, 0xEA, 0x7D, 0x87, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x2C, 0x99, 0x09, 0x6F, 0x63, 0xEB, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x76, 0xDA, 0x1A, 0x06, 0xBE, 0xDE, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x09, 0x2E, 0x75, 0x39, 0x30, 0x2D, 0x42),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_24_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x9B, 0xC1, 0x5A, 0x17, 0xC3, 0x8C, 0x31),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x8D, 0x94, 0x4D, 0x3D, 0xAB, 0x60, 0xD4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFD, 0x1E, 0x0F, 0x43, 0xAE, 0x9D, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF2, 0xF3, 0x20, 0x1B, 0xAA, 0xB7, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x5B, 0xA4, 0xF4, 0x90, 0x3B, 0xE3, 0x71),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x78, 0x72, 0xBD, 0x65, 0x09, 0x0B, 0x01),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_25_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x37, 0x2A, 0x6C, 0x16, 0x4F, 0x64, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xCE, 0xA3, 0x90, 0xB4, 0x9A, 0xBC, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x55, 0x63, 0x1D, 0x3A, 0x6E, 0x18),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xB4, 0xAA, 0x99, 0x22, 0x45, 0x89, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x7C, 0x8C, 0xA6, 0x3D, 0xA7, 0x3E, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x06, 0x42, 0xDC, 0xA6, 0xE3, 0xC6, 0x12),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_25_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8C, 0x3D, 0x5D, 0x47, 0x31, 0x7C, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x85, 0xEE, 0x46, 0x7E, 0x13, 0x04, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x3C, 0x8B, 0x43, 0x2E, 0x74, 0xF5, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x88, 0x8E, 0x07, 0x29, 0x08, 0x03, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x9B, 0x89, 0xEB, 0x08, 0xE8, 0x43, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x07, 0x67, 0xFD, 0xD9, 0x73, 0x6F, 0x18),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_26_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xEB, 0x21, 0x8D, 0x98, 0x43, 0x74, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xCC, 0x14, 0xD8, 0x08, 0xBB, 0xA6, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x98, 0xF2, 0x6A, 0x18, 0xC3, 0xDD, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x38, 0x91, 0xA0, 0x03, 0xF2, 0x04, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xAF, 0xE8, 0xFD, 0xFB, 0x13, 0x70, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x93, 0x87, 0x98, 0x4A, 0xE0, 0x00, 0x12),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_26_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x2E, 0x69, 0x9C, 0xA2, 0x2D, 0x03, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFE, 0xF3, 0xB9, 0xC1, 0x85, 0x2A, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xFD, 0x86, 0xB1, 0xCD, 0xBF, 0x41, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xD8, 0x9A, 0x21, 0xF3, 0xFE, 0xCB, 0xF1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x78, 0x04, 0x60, 0xB7, 0xA9, 0xA2, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1E, 0x66, 0x2A, 0x54, 0x51, 0xBD, 0x8B),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_27_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x16, 0x36, 0xEF, 0x61, 0x2D, 0xEE, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x5F, 0x88, 0xA0, 0x13, 0x12, 0xF7, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xC6, 0xAD, 0x4A, 0x4A, 0x07, 0x01, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x74, 0xB1, 0x4F, 0xEB, 0xBD, 0xD5, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF9, 0x71, 0xA2, 0x06, 0x4F, 0xD7, 0xBC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x8B, 0x4D, 0x48, 0xE0, 0x98, 0xFB, 0x6A),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_27_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xBA, 0x10, 0xA3, 0x0D, 0x52, 0xAC, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xD0, 0xE0, 0x36, 0xE6, 0x07, 0x3A, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x80, 0xF0, 0xAA, 0x49, 0x22, 0x4B, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC7, 0xAB, 0x1C, 0x89, 0xCD, 0x24, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x2A, 0xFC, 0xB3, 0x6D, 0x45, 0x96, 0x49),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xE4, 0xDB, 0x52, 0x3F, 0xC4, 0xB4, 0x19),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_28_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xCC, 0xC8, 0x7F, 0xBB, 0x6B, 0x87, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x21, 0x3C, 0x69, 0x7D, 0x38, 0x57, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x4C, 0x18, 0x3C, 0x53, 0xA5, 0x48, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC3, 0x64, 0x45, 0xDB, 0xC4, 0x6D, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCC, 0xD1, 0xBB, 0x17, 0xB8, 0x34, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x69, 0x71, 0xFA, 0xA0, 0x28, 0x4A, 0x3D),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_28_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xE8, 0x9E, 0x39, 0xEA, 0x8D, 0x38, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x9C, 0xBB, 0xCD, 0x80, 0x1A, 0xEE, 0xB7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA0, 0x45, 0xBF, 0xD9, 0x22, 0x11, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7C, 0x5C, 0xD9, 0xC0, 0x9F, 0x69, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x8A, 0xA6, 0x79, 0x4E, 0x35, 0xB9, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8B, 0x9A, 0x3E, 0xA1, 0xB8, 0x28, 0x10),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_29_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x2F, 0xEF, 0xBB, 0xA9, 0x72, 0x7F, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x34, 0xB7, 0x12, 0xB9, 0xE7, 0xC3, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x1D, 0xD9, 0x42, 0x77, 0x0C, 0x71, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x01, 0x59, 0xA7, 0x56, 0x03, 0x91, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x91, 0x99, 0x33, 0x30, 0x3E, 0xEF, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xC9, 0x5A, 0x9A, 0x54, 0x66, 0xF1, 0x70),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_29_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x2C, 0xB7, 0x6E, 0x71, 0x7D, 0x35, 0x30),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x0D, 0xEF, 0xD1, 0x2D, 0x99, 0x63, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x31, 0xAF, 0x2D, 0xC9, 0xC6, 0xC2, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xC0, 0xDF, 0x80, 0x54, 0xC4, 0xAC, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x6B, 0xA0, 0x84, 0x96, 0xF7, 0x31, 0xC8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xE2, 0x7C, 0x7A, 0x41, 0x45, 0x75, 0x6A),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_30_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xEE, 0x58, 0x31, 0xE8, 0x68, 0xD6, 0x76),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x2E, 0x48, 0xB7, 0x09, 0x9F, 0xD4, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA9, 0x5C, 0xE7, 0x64, 0x43, 0x5D, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x9F, 0x50, 0xAB, 0x68, 0xFF, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x88, 0x2D, 0xBA, 0x12, 0xBF, 0x8D, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xDF, 0x6F, 0xB3, 0x75, 0xA4, 0x55, 0x73),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_30_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x17, 0x92, 0x39, 0xB7, 0x13, 0x37, 0x6F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x43, 0x71, 0xA7, 0xCA, 0x17, 0x1B, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xB9, 0xB0, 0x78, 0xEF, 0xA0, 0xDA, 0x83),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0xF2, 0x0F, 0x85, 0xA2, 0xB6, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x65, 0x2E, 0x6E, 0x45, 0xB9, 0x4C, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x6A, 0x8C, 0x2B, 0x77, 0x96, 0x36, 0x22),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_31_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x7A, 0x13, 0x4A, 0x97, 0x63, 0x02, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x1E, 0x06, 0x03, 0x8F, 0xB9, 0xEE, 0x64),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0xEE, 0x8B, 0x89, 0xA9, 0x70, 0xDB, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x81, 0xC9, 0x70, 0x8D, 0x62, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xDA, 0x46, 0xF8, 0xF9, 0x3A, 0xBE, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x9C, 0x7A, 0x97, 0x62, 0xEB, 0xFA, 0x0F),\n};\nstatic const mbedtls_mpi_uint brainpoolP384r1_T_31_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x03, 0x3D, 0x3C, 0x46, 0x27, 0x9E, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x08, 0x1C, 0xD5, 0x25, 0xAF, 0xE9, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x69, 0xDC, 0x59, 0xF4, 0x8A, 0x7C, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x9A, 0x7A, 0x99, 0x21, 0x0C, 0x4E, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xCE, 0x85, 0x5F, 0xAC, 0xAA, 0x82, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x57, 0x69, 0x90, 0x76, 0xF3, 0x53, 0x3F),\n};\nstatic const mbedtls_ecp_point brainpoolP384r1_T[32] = {\n    ECP_POINT_INIT_XY_Z1(brainpoolP384r1_T_0_X, brainpoolP384r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_1_X, brainpoolP384r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_2_X, brainpoolP384r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_3_X, brainpoolP384r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_4_X, brainpoolP384r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_5_X, brainpoolP384r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_6_X, brainpoolP384r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_7_X, brainpoolP384r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_8_X, brainpoolP384r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_9_X, brainpoolP384r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_10_X, brainpoolP384r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_11_X, brainpoolP384r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_12_X, brainpoolP384r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_13_X, brainpoolP384r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_14_X, brainpoolP384r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_15_X, brainpoolP384r1_T_15_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_16_X, brainpoolP384r1_T_16_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_17_X, brainpoolP384r1_T_17_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_18_X, brainpoolP384r1_T_18_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_19_X, brainpoolP384r1_T_19_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_20_X, brainpoolP384r1_T_20_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_21_X, brainpoolP384r1_T_21_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_22_X, brainpoolP384r1_T_22_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_23_X, brainpoolP384r1_T_23_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_24_X, brainpoolP384r1_T_24_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_25_X, brainpoolP384r1_T_25_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_26_X, brainpoolP384r1_T_26_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_27_X, brainpoolP384r1_T_27_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_28_X, brainpoolP384r1_T_28_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_29_X, brainpoolP384r1_T_29_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_30_X, brainpoolP384r1_T_30_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_31_X, brainpoolP384r1_T_31_Y),\n};\n#else\n#define brainpoolP384r1_T NULL\n#endif\n\n#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */\n\n/*\n * Domain parameters for brainpoolP512r1 (RFC 5639 3.7)\n */\n#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)\nstatic const mbedtls_mpi_uint brainpoolP512r1_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_a[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_b[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_gx[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_gy[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA),\n};\n\n#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_0_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_0_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_1_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xE9, 0x6B, 0x8C, 0x6F, 0x9D, 0x88, 0x43),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x4F, 0x86, 0x96, 0xA7, 0x56, 0xD1, 0x37),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xAB, 0xFA, 0xEE, 0xA7, 0xF5, 0x0E, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x40, 0xEF, 0x9E, 0x6D, 0xD6, 0x32, 0x33),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xED, 0x56, 0x14, 0x57, 0x1A, 0x8D, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xED, 0x4D, 0x3A, 0xFA, 0x71, 0x75, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xC5, 0x76, 0x1C, 0x14, 0xBE, 0xB5, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x5A, 0xCB, 0xE7, 0x36, 0x1D, 0x52, 0x1C),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_1_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8D, 0x7A, 0xEB, 0xA3, 0x8B, 0xD5, 0xB0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xA3, 0x41, 0xF8, 0xAC, 0x9E, 0xAB, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xE3, 0x65, 0x0D, 0x1C, 0xFE, 0x09, 0x2B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xCA, 0x13, 0x3F, 0xC5, 0xF9, 0x7E, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x5D, 0x63, 0x28, 0xA6, 0x89, 0xD3, 0x91),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x95, 0x3F, 0x7A, 0x82, 0xD4, 0x77, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xBB, 0x92, 0x32, 0x00, 0xF4, 0x66, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x58, 0x31, 0xD1, 0x17, 0x9F, 0x2A, 0x22),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_2_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x36, 0xA9, 0xCD, 0x80, 0xA5, 0x2D, 0x78),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x44, 0xAB, 0xCE, 0x71, 0xFF, 0x0C, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x24, 0x58, 0x35, 0x5A, 0x21, 0x32, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xA6, 0x28, 0xF8, 0x7A, 0x97, 0xAE, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xE7, 0x08, 0xFA, 0x47, 0xC9, 0x55, 0x09),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xAC, 0x2E, 0x84, 0xA4, 0xF5, 0x52, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x58, 0x05, 0x9D, 0xA7, 0xC8, 0x71, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x92, 0xB4, 0x92, 0xC1, 0x92, 0xEC, 0x6B),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_2_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x48, 0x2D, 0x79, 0x5E, 0x58, 0xE5, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x85, 0x26, 0xEC, 0xE9, 0x6E, 0xD4, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x68, 0x26, 0x87, 0x38, 0xA2, 0xD2, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x17, 0x60, 0xCE, 0x75, 0xF8, 0xA5, 0x6F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x51, 0xDB, 0xA9, 0xAE, 0x87, 0xF1, 0x15),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x49, 0x92, 0x3B, 0x19, 0x96, 0xF5, 0xB0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xD5, 0x52, 0x52, 0x8C, 0xCE, 0xFD, 0xFA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x18, 0x0A, 0xE6, 0xF6, 0xAE, 0x08, 0x41),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_3_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x2B, 0xD8, 0x54, 0xCE, 0xB0, 0x57, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xB0, 0xF8, 0x9E, 0x03, 0x03, 0x3C, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x0E, 0x29, 0x29, 0x00, 0xF3, 0x70, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x33, 0x99, 0x0E, 0x00, 0x5D, 0xFE, 0x4B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2D, 0xF2, 0x59, 0x32, 0xCF, 0x03, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xC9, 0x72, 0xAE, 0x0C, 0xEF, 0xD1, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x5A, 0x27, 0xBF, 0x2F, 0x45, 0xF9, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xBE, 0xE5, 0x2C, 0xFF, 0x5B, 0x1E, 0x88),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_3_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xAC, 0xBB, 0xD8, 0x83, 0xC2, 0x46, 0xF6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xDC, 0xCE, 0x15, 0xB4, 0xEF, 0xCF, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xDB, 0x5E, 0x94, 0x31, 0x0B, 0xB2, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xB9, 0xE3, 0xE3, 0x11, 0x71, 0x41, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xE3, 0x01, 0xB7, 0x7D, 0xBC, 0x65, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x07, 0x65, 0x87, 0xA7, 0xE8, 0x48, 0xE3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x48, 0x8F, 0xD4, 0x30, 0x8E, 0xB4, 0x6C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE0, 0x73, 0xBE, 0x1E, 0xBF, 0x56, 0x36),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_4_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x0E, 0x5E, 0x87, 0xC5, 0xAB, 0x0E, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xF9, 0x5F, 0x80, 0x24, 0x4C, 0x2A, 0xF1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x15, 0x21, 0x54, 0x92, 0x84, 0x8D, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x8A, 0x47, 0x74, 0xDC, 0x42, 0xB1, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xF7, 0x30, 0xFD, 0xC1, 0x9B, 0x0C, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x6C, 0xCC, 0xDF, 0xC5, 0xE3, 0xA9, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x67, 0x59, 0x10, 0x5C, 0x51, 0x54, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x37, 0xFB, 0x6E, 0xB0, 0x78, 0x63, 0x8E),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_4_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEF, 0xC4, 0x39, 0x20, 0xF1, 0x46, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x62, 0xAE, 0xFF, 0x10, 0xE4, 0xE2, 0xE9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x5C, 0xF5, 0x2E, 0x22, 0x89, 0xE5, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x0C, 0x29, 0xA8, 0x62, 0xAE, 0xDB, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x9E, 0x0F, 0xCA, 0x87, 0x2A, 0x6F, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xDC, 0x9B, 0x9F, 0x65, 0xD4, 0xAD, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xC3, 0x08, 0x0F, 0xCF, 0x67, 0xE9, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5C, 0xD7, 0xFF, 0x41, 0x9C, 0xCB, 0x26),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_5_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x05, 0x12, 0xAD, 0x73, 0x63, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x99, 0x07, 0x86, 0x57, 0xE7, 0x94, 0xB1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x4B, 0xA5, 0xBF, 0x18, 0xA9, 0xEF, 0x6A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x4C, 0xC4, 0x09, 0xF2, 0x2F, 0x0C, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x3A, 0x04, 0xEA, 0x89, 0x6C, 0x91, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0x3A, 0xE7, 0xA3, 0xEC, 0x24, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xA1, 0x26, 0x21, 0x04, 0xE3, 0xB9, 0x40),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x71, 0x4B, 0x7B, 0xC2, 0x89, 0xCD, 0xA2),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_5_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xB9, 0xA8, 0x9D, 0xFD, 0x00, 0x3A, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x41, 0x6C, 0xBB, 0x5A, 0xCA, 0x1F, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xD7, 0xE2, 0x6C, 0x6B, 0xA7, 0x48, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x19, 0xAD, 0xA7, 0xC1, 0x7E, 0x4F, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF7, 0x19, 0x3C, 0x06, 0x74, 0x2C, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x23, 0x4F, 0x0C, 0x09, 0xB0, 0x80, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x74, 0x34, 0x08, 0x44, 0x7E, 0xA3, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xCC, 0x8D, 0x12, 0x6E, 0xE1, 0x3D, 0x0B),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_6_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x18, 0xB1, 0x71, 0x02, 0x93, 0xC2, 0xA4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x89, 0x40, 0xE2, 0x1F, 0xE7, 0x5E, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xAE, 0x89, 0x01, 0xD4, 0x0C, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xDA, 0x58, 0x70, 0x24, 0xF2, 0xE4, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xC7, 0x1D, 0xD6, 0x4A, 0x6F, 0x66, 0x4F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x1D, 0x7E, 0x4A, 0x2C, 0xCA, 0xEC, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x7F, 0xA8, 0x99, 0xE4, 0xD3, 0x4E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x1D, 0x5A, 0xDF, 0x5E, 0x58, 0x36, 0x49),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_6_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB9, 0x32, 0x69, 0x1F, 0x72, 0x2A, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x73, 0xE2, 0x03, 0x39, 0x35, 0xAA, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x5E, 0x5D, 0x48, 0xEF, 0xAE, 0x30, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x7F, 0x60, 0x19, 0xAF, 0xEC, 0x9D, 0xFC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x19, 0xE4, 0x1B, 0x56, 0x15, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xD7, 0x33, 0x59, 0x1F, 0x43, 0x59, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xCE, 0xEE, 0xCA, 0xA4, 0x7F, 0x63, 0xD4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x40, 0xC0, 0xF6, 0x19, 0x89, 0x43, 0x20),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_7_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x92, 0xEA, 0x07, 0x65, 0x79, 0x86, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xB7, 0x13, 0x75, 0xD3, 0xC5, 0x0A, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x9E, 0xFA, 0xE1, 0x1F, 0x0C, 0xF9, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x8C, 0xED, 0x5C, 0x21, 0xE9, 0x09, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x4D, 0xD8, 0x18, 0xC4, 0xF6, 0x36, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xC9, 0xAC, 0x5C, 0xFA, 0x69, 0xA4, 0xA0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8C, 0x94, 0x1C, 0x7B, 0x71, 0x36, 0x58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBD, 0x46, 0xCE, 0xB7, 0x1D, 0x9C, 0x5E),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_7_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD6, 0x96, 0x4B, 0xA6, 0x47, 0xEB, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xF1, 0x5F, 0x15, 0xDE, 0x99, 0x6F, 0x66),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xBD, 0xE5, 0x04, 0xB8, 0xE6, 0xC0, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD3, 0xF0, 0x04, 0x00, 0xE4, 0x05, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xF3, 0x06, 0xA3, 0x1A, 0xFF, 0xEA, 0x73),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x32, 0xAA, 0x99, 0x33, 0x09, 0xB6, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xEF, 0xFC, 0x61, 0x10, 0x42, 0x31, 0x94),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF1, 0xF4, 0x33, 0xCF, 0x28, 0x90, 0x9C),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_8_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xDE, 0xF9, 0x88, 0x87, 0x7B, 0xEB, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xB8, 0xDA, 0xFA, 0xDA, 0x3D, 0xA6, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF0, 0x62, 0x82, 0x53, 0x32, 0x55, 0x03),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA5, 0x32, 0x4A, 0x19, 0x11, 0x9C, 0x10),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xB3, 0x27, 0xE9, 0x75, 0x90, 0x05, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x1C, 0x90, 0x48, 0x77, 0x01, 0x85, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD6, 0x9B, 0x84, 0xA8, 0xD7, 0xC5, 0x28),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x7A, 0xCB, 0xB3, 0x11, 0x46, 0xD7, 0x99),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_8_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x23, 0xBF, 0x75, 0x75, 0xA1, 0x95, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x66, 0x5D, 0x34, 0x13, 0xA9, 0x03, 0xBE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x80, 0x9D, 0x5F, 0xD2, 0x44, 0xE1, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x5D, 0xBD, 0xA8, 0xBF, 0xB4, 0x25, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x99, 0x1F, 0x53, 0xF1, 0x57, 0xDB, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x7C, 0xE5, 0xC5, 0x51, 0x0B, 0x4C, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xB0, 0x1A, 0x9C, 0x16, 0xB0, 0x32, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xE3, 0xCF, 0xDD, 0x48, 0xB4, 0x7B, 0x33),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_9_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xDD, 0x9E, 0x3C, 0x98, 0x0E, 0x77, 0x65),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xAB, 0x01, 0xD3, 0x87, 0x74, 0x25, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xA3, 0xE3, 0x76, 0x43, 0x87, 0x12, 0xBD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0xB1, 0x3B, 0x60, 0x66, 0xEB, 0x98, 0x54),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x78, 0xC8, 0xD7, 0x4E, 0x75, 0xCA, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xDF, 0x71, 0x19, 0xE7, 0x07, 0x36, 0xB5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC9, 0xA8, 0x5F, 0x91, 0xBF, 0x47, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x96, 0x58, 0x96, 0x18, 0xB6, 0xFA, 0x01),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_9_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x2D, 0xA9, 0x9B, 0x86, 0xDB, 0x0C, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0B, 0x2D, 0x56, 0x4A, 0xD3, 0x93, 0x8A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x15, 0xE2, 0x65, 0x12, 0x86, 0x0E, 0xB2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x41, 0x4D, 0xC1, 0xCB, 0xE4, 0xC3, 0xD7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x53, 0x10, 0xCA, 0xA3, 0xAC, 0x83, 0x26),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x01, 0x22, 0x96, 0x10, 0xAD, 0x69, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x46, 0x4E, 0xD8, 0xEA, 0xD6, 0x9D, 0xF3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x2F, 0x7F, 0x62, 0x62, 0x80, 0xD0, 0x14),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_10_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xDA, 0x00, 0x63, 0x09, 0xBD, 0x6A, 0x83),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD4, 0x6E, 0x48, 0x05, 0xB7, 0xF7, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x4D, 0xD7, 0x00, 0x4A, 0x15, 0x27, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x15, 0xAA, 0x37, 0x27, 0x34, 0x18, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x20, 0x2C, 0x84, 0x1B, 0x88, 0xBA, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x09, 0xD6, 0x04, 0xA2, 0x60, 0x84, 0x72),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x04, 0x94, 0x08, 0xD4, 0xED, 0x47, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xF3, 0xE4, 0x3E, 0xB9, 0x5B, 0x35, 0x42),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_10_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xD8, 0xB6, 0x80, 0xD6, 0xF1, 0x30, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x14, 0xA6, 0x85, 0xEE, 0xA7, 0xD8, 0x61),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x49, 0x2A, 0x1E, 0x7C, 0xE9, 0x2D, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x87, 0x56, 0x91, 0x03, 0x77, 0x4D, 0x55),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x52, 0xD4, 0xAA, 0xF7, 0xFA, 0xB0, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x11, 0x39, 0xB1, 0xE7, 0x76, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x13, 0xBC, 0x37, 0x5D, 0x74, 0xCD, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x48, 0x14, 0x23, 0x30, 0xF8, 0x46, 0x37),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_11_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x27, 0xB0, 0xD9, 0xB2, 0x74, 0xB4, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xA6, 0xB9, 0x6F, 0x9F, 0x64, 0x36, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x2B, 0x78, 0x40, 0x05, 0x2B, 0x7B, 0xA9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x68, 0x3A, 0xB6, 0x4A, 0xE2, 0xDB, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x33, 0xD7, 0x34, 0x8B, 0x25, 0x45, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xCE, 0xA8, 0xC9, 0x01, 0xFB, 0x0E, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF9, 0x51, 0x4C, 0x12, 0x9F, 0x60, 0xE4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x85, 0xBD, 0x30, 0x37, 0x84, 0x39, 0x44),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_11_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x33, 0xAF, 0x2E, 0xB8, 0x2E, 0xCC, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xB1, 0x73, 0x59, 0x4E, 0x0C, 0x09, 0x4A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x24, 0x89, 0x81, 0x12, 0xFF, 0xBB, 0x6E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0x1A, 0x66, 0xEE, 0xED, 0xB6, 0x9B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xBD, 0x04, 0x20, 0x5D, 0xFB, 0xBF, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF8, 0x34, 0xA3, 0xFF, 0x45, 0xDE, 0x92),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x18, 0x73, 0xF1, 0x32, 0x25, 0x58, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xC1, 0x14, 0xE3, 0x9E, 0x40, 0x0F, 0x12),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_12_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0x9D, 0x9C, 0x00, 0xF7, 0x56, 0x19),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBA, 0x87, 0xF9, 0x15, 0x0C, 0x66, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x1F, 0xC1, 0x28, 0xB0, 0x47, 0x0D, 0xF5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xCA, 0x27, 0xEE, 0x4B, 0x23, 0x2B, 0x89),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB5, 0x68, 0xC8, 0x17, 0x5D, 0xC3, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x02, 0x08, 0xEE, 0x20, 0x9D, 0xEA, 0x64),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x14, 0x50, 0xD4, 0x7D, 0x5F, 0xCF, 0xA0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFA, 0xF8, 0xA7, 0xC6, 0xDC, 0x14, 0x8C),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_12_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xBD, 0x0A, 0x1A, 0x18, 0x98, 0xDC, 0xB0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x63, 0x02, 0xB7, 0xD5, 0x5B, 0x5A, 0xC6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB1, 0xD7, 0x4B, 0x15, 0x39, 0x61, 0x5D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x32, 0xE1, 0x9E, 0x70, 0x1B, 0xCE, 0x51),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD8, 0x18, 0x83, 0x52, 0x9B, 0x6D, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x55, 0x56, 0x19, 0x34, 0xA4, 0xEA, 0xFC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA9, 0x55, 0x80, 0xE3, 0x15, 0x36, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x06, 0xC8, 0x1D, 0x17, 0x0D, 0xAD, 0x16),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_13_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xD6, 0xF0, 0xCC, 0xF3, 0x63, 0x53, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x5A, 0xDC, 0x46, 0xBD, 0x0D, 0xAD, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x2F, 0x11, 0x60, 0x15, 0x51, 0x4A, 0xEA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE3, 0x93, 0x38, 0xD5, 0x83, 0xAA, 0x0D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA6, 0xCC, 0xB1, 0xFD, 0xBB, 0x1A, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x54, 0xC8, 0x54, 0x6F, 0x79, 0x1A, 0x59),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4A, 0xDA, 0x28, 0x92, 0x97, 0x9D, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x4B, 0xDB, 0xC7, 0x52, 0xC5, 0x66, 0x34),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_13_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7E, 0x92, 0x53, 0x30, 0x93, 0xFD, 0xFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0x6A, 0xB1, 0x91, 0x0A, 0xB4, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x9D, 0x40, 0x3F, 0xE3, 0xF1, 0x01, 0x46),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x0E, 0xD8, 0xED, 0x11, 0x8E, 0x4C, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x4A, 0x1B, 0x88, 0xDF, 0x8D, 0x29, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x23, 0x21, 0x11, 0xAB, 0x77, 0x81, 0x62),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xAF, 0x11, 0xFA, 0xBA, 0x40, 0x63, 0xE7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x6F, 0x8D, 0x80, 0xDF, 0x67, 0xF5, 0x44),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_14_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x8B, 0xB7, 0x08, 0xF4, 0xD7, 0x2D, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x2B, 0x30, 0x02, 0x45, 0x71, 0x08, 0x49),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x3A, 0xCA, 0x50, 0xF6, 0xC2, 0x19, 0x8C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xB9, 0x9B, 0x3E, 0x73, 0x95, 0x1D, 0x49),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x60, 0x59, 0x48, 0xCB, 0xD8, 0xD6, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x6C, 0x89, 0xAB, 0x99, 0xA8, 0xF8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xA1, 0x8B, 0x4E, 0x06, 0x19, 0xEC, 0x99),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x95, 0x04, 0xCF, 0xD5, 0x94, 0xB3, 0x02),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_14_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x35, 0x93, 0x7C, 0xB3, 0xB8, 0x9E, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x45, 0x5C, 0x7E, 0xBF, 0x75, 0x81, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE8, 0x24, 0xDF, 0xEC, 0x2F, 0x7D, 0xB9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x8B, 0xD5, 0x6A, 0x9B, 0xA0, 0xE0, 0x4F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE3, 0x27, 0x82, 0xDE, 0xDD, 0xCA, 0x4B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x57, 0x56, 0x46, 0x05, 0x06, 0x01, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x35, 0xA7, 0x47, 0xE2, 0x6B, 0x2C, 0x4F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x9D, 0x4C, 0xEC, 0x1F, 0x11, 0x75, 0x2B),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_15_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xAA, 0x41, 0xC1, 0xE9, 0x0E, 0xE9, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xCF, 0x9C, 0x4B, 0xE8, 0xED, 0x0A, 0x49),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x73, 0xCA, 0x0C, 0x46, 0x0A, 0x9C, 0xE4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE1, 0x9E, 0xBC, 0xFE, 0x44, 0x63, 0x6D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x43, 0x71, 0xEE, 0xF8, 0xC1, 0x8C, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x4B, 0xF0, 0x69, 0x25, 0xBD, 0x71, 0x1A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x9A, 0xFE, 0x82, 0xE7, 0xC1, 0xC1, 0xEE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x5A, 0x6E, 0x5E, 0x97, 0x6A, 0x35, 0x8D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_15_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x18, 0x6C, 0x7E, 0xB8, 0x9E, 0x57, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xB9, 0xC1, 0xD0, 0xFE, 0x78, 0xFB, 0x32),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x08, 0xAE, 0x46, 0x34, 0xEA, 0x7A, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1C, 0x56, 0xA9, 0x18, 0x37, 0xD4, 0x9E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x63, 0xE9, 0x0A, 0xB6, 0x38, 0x3C, 0xC1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x4F, 0xA4, 0x6E, 0x85, 0x31, 0x23, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xAD, 0xC4, 0xC3, 0xB1, 0x4B, 0x1C, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x56, 0x4A, 0x38, 0xB3, 0x6B, 0x6F, 0x2C),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_16_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xC7, 0x19, 0xDE, 0x21, 0xED, 0x89, 0xD0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xBE, 0xA6, 0xAE, 0xEB, 0x9D, 0xA7, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x0E, 0x13, 0x1E, 0x86, 0x57, 0xC3, 0x3B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4B, 0x30, 0x46, 0x52, 0xC1, 0xEC, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xD5, 0x44, 0x31, 0x96, 0x3B, 0x26, 0x27),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x68, 0xA8, 0x67, 0x78, 0x39, 0xE8, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x78, 0xB7, 0xDD, 0xF2, 0x58, 0xB6, 0x3D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x3C, 0xB3, 0x26, 0xC4, 0x2C, 0x8C, 0xA5),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_16_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x24, 0xE5, 0x73, 0xEE, 0x9A, 0x02, 0xA9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x6A, 0x65, 0x60, 0xF3, 0x62, 0xE3, 0xE9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x07, 0x84, 0xE6, 0x3B, 0x46, 0x65, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x8F, 0x0C, 0xB0, 0xE1, 0x04, 0x82, 0x9D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x13, 0xBF, 0x3D, 0xA0, 0x48, 0xA2, 0x74),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x26, 0x76, 0x74, 0xAB, 0x0B, 0x29, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x6E, 0x5F, 0x03, 0x34, 0x7C, 0x38, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x72, 0xF9, 0x3B, 0x3C, 0xA4, 0xBC, 0x7C),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_17_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xCE, 0x18, 0x80, 0xB8, 0x24, 0x45, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x09, 0x03, 0xB8, 0x06, 0x64, 0xF7, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x26, 0xB1, 0x10, 0x6D, 0x71, 0x12, 0x2E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x12, 0xC6, 0x6E, 0x1E, 0x6A, 0xC3, 0x80),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xD3, 0x0A, 0xDE, 0xD8, 0x6B, 0x04, 0x5C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x87, 0x5B, 0xAE, 0xDB, 0x3C, 0xC0, 0xC5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF5, 0xF9, 0xC1, 0x9A, 0x89, 0xBB, 0x7E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x69, 0x72, 0x8B, 0xAE, 0x32, 0x13, 0x11),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_17_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x16, 0x07, 0x50, 0xFA, 0x4C, 0xCF, 0xE8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x50, 0x21, 0xE9, 0xDE, 0xEC, 0x7E, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x2F, 0xE8, 0x83, 0x30, 0x0B, 0x65, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x0B, 0x99, 0xAC, 0xC9, 0xBA, 0x6C, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x59, 0x5A, 0x0D, 0x7B, 0x9E, 0x08, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x91, 0xB2, 0xDC, 0x90, 0xCE, 0x67, 0xED),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x93, 0x60, 0x0C, 0xD7, 0x1F, 0x2F, 0x17),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7F, 0x9D, 0x40, 0xF8, 0x78, 0x7A, 0x54),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_18_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x22, 0x95, 0xE8, 0xEF, 0x31, 0x57, 0x35),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x88, 0x53, 0xFE, 0xAF, 0x7C, 0x47, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xCE, 0xCC, 0x79, 0xE8, 0x9F, 0x8C, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x16, 0xDD, 0x77, 0x6E, 0x8A, 0x73, 0x97),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x07, 0x97, 0x21, 0x3B, 0xF8, 0x5F, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xB5, 0xD2, 0x81, 0x84, 0xF0, 0xE7, 0x9F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x8F, 0x75, 0x09, 0x6A, 0x0E, 0x53, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x4F, 0x70, 0x97, 0xC7, 0xAC, 0x7D, 0x3F),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_18_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x3C, 0x6A, 0xB4, 0x10, 0xA9, 0xC8, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC5, 0xD6, 0x69, 0x16, 0xB8, 0xAC, 0x25),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x44, 0xDC, 0xEB, 0x48, 0x54, 0x5D, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x48, 0x9B, 0xD7, 0x72, 0x69, 0xA4, 0x8A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x0D, 0x36, 0x9A, 0x66, 0x0B, 0xEC, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC6, 0xD4, 0xB6, 0x60, 0xE5, 0xC3, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x29, 0x42, 0xE0, 0x9D, 0xFD, 0x7C, 0x3E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x10, 0xBA, 0x55, 0xBC, 0x3B, 0x38, 0x5D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_19_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x66, 0xFA, 0x05, 0x73, 0x03, 0x1B, 0x69),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xA4, 0x66, 0x12, 0x96, 0x7B, 0x02, 0x4C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xDE, 0x6D, 0x98, 0xD1, 0xD5, 0xA8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF5, 0x44, 0xB8, 0x8E, 0xF6, 0x8C, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x15, 0x2B, 0x72, 0xBC, 0x49, 0xE5, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x44, 0xD7, 0xDF, 0x8F, 0xEB, 0x8D, 0x80),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x64, 0x88, 0xAA, 0xB7, 0xE4, 0x70, 0x1D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x14, 0xBB, 0xE9, 0x9B, 0xB9, 0x65, 0x5D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_19_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x8E, 0x88, 0xF5, 0xF1, 0xC1, 0x89, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x30, 0x53, 0xE6, 0xFB, 0x2D, 0x82, 0xB4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE4, 0xFF, 0xBA, 0x31, 0x79, 0xAB, 0xC2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x09, 0xF7, 0xB7, 0x09, 0x78, 0x4C, 0x90),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xAE, 0xC2, 0x44, 0xDC, 0x17, 0x78, 0x47),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD4, 0x17, 0x43, 0x19, 0x74, 0x9E, 0x23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x64, 0x3B, 0x73, 0xA2, 0x99, 0x27, 0x76),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0x36, 0x5F, 0xD3, 0x14, 0xB1, 0x31),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_20_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x07, 0xAB, 0xFD, 0x9B, 0x03, 0xC5, 0xD5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xBE, 0xB0, 0x1D, 0xF2, 0x0C, 0x73, 0x73),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE7, 0x7B, 0x87, 0xD3, 0x34, 0xFD, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x25, 0x3D, 0xC7, 0x36, 0x83, 0x53, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x7C, 0xCF, 0x63, 0x55, 0x12, 0x11, 0xB0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x34, 0x4D, 0x27, 0x92, 0xAC, 0x18, 0x16),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x42, 0x61, 0x9D, 0x2E, 0xFF, 0x13, 0x16),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xDE, 0x92, 0x65, 0x57, 0x0D, 0xBC, 0x0A),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_20_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x7B, 0x6E, 0xC6, 0x2A, 0x21, 0x74, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xA7, 0x53, 0x4D, 0x29, 0x36, 0xEF, 0xE5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xD6, 0x41, 0xC7, 0x99, 0xAD, 0x50, 0x53),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xAC, 0x41, 0x9F, 0xFB, 0x4C, 0x86, 0xF1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xBB, 0xE6, 0x25, 0x28, 0xAA, 0xEB, 0x1E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x04, 0xA2, 0xC3, 0xAA, 0x08, 0x8A, 0xCC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x2B, 0x5B, 0xE2, 0x8D, 0x76, 0xEA, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x33, 0xD2, 0x21, 0x4D, 0x62, 0xE3, 0x8E),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_21_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x06, 0x8B, 0x2B, 0xC2, 0xC4, 0xB1, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF5, 0xA1, 0xC0, 0x03, 0x6A, 0x29, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA9, 0xEF, 0x55, 0xB6, 0x1A, 0x9F, 0x6B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x54, 0x32, 0xBE, 0x06, 0x43, 0xB5, 0xFD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xD6, 0xD9, 0x20, 0x89, 0xBE, 0xD4, 0x1B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x26, 0x95, 0x10, 0xCE, 0xB4, 0x88, 0x79),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xA6, 0x27, 0xAC, 0x32, 0xBA, 0xBD, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xA6, 0xAE, 0x9C, 0x7B, 0xBE, 0xA1, 0x63),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_21_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xCD, 0x4D, 0x3D, 0xDF, 0x96, 0xBB, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0x11, 0x06, 0xCC, 0x0E, 0x31, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xE4, 0xF4, 0xAD, 0x7B, 0x5F, 0xF1, 0xEF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x54, 0xBE, 0xF4, 0x8A, 0x03, 0x47, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x53, 0x00, 0x7F, 0xB0, 0x8A, 0x68, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0xB1, 0x73, 0x6F, 0x5B, 0x0E, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x32, 0xE3, 0x43, 0x64, 0x75, 0xFB, 0xFB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x18, 0x55, 0x8A, 0x4E, 0x6E, 0x35, 0x54),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_22_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x97, 0x15, 0x1E, 0xCB, 0xF2, 0x9C, 0xA5),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xD1, 0xBB, 0xF3, 0x70, 0xAD, 0x13, 0xAD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x96, 0xA4, 0xC5, 0x5E, 0xDA, 0xD5, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x81, 0xE9, 0x65, 0x66, 0x76, 0x47, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x87, 0x06, 0x73, 0xCF, 0x34, 0xD2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x81, 0x15, 0x42, 0xA2, 0x79, 0x5B, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA2, 0x7D, 0x09, 0x14, 0x64, 0xC6, 0xAE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x6D, 0xC4, 0xED, 0xF1, 0xD6, 0xE9, 0x24),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_22_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xD5, 0xBB, 0x25, 0xA3, 0xDD, 0xA3, 0x88),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xF2, 0x68, 0x67, 0x39, 0x8F, 0x73, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x76, 0x28, 0x89, 0xAD, 0x32, 0xE0, 0xDF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x90, 0xCC, 0x57, 0x58, 0xAA, 0xC9, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD7, 0x43, 0xD2, 0xCE, 0x5E, 0xA0, 0x08),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xB0, 0xB8, 0xA4, 0x9E, 0x96, 0x26, 0x86),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x61, 0x1D, 0xF3, 0x65, 0x5E, 0x60, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x1E, 0x65, 0xED, 0xCF, 0x07, 0x60, 0x20),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_23_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x30, 0x17, 0x8A, 0x91, 0x88, 0x0A, 0xA4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7D, 0x18, 0xA4, 0xAC, 0x59, 0xFC, 0x5F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x31, 0x8B, 0x25, 0x65, 0x39, 0x9A, 0xDC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x16, 0x4B, 0x68, 0xBA, 0x59, 0x13, 0x2F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xD3, 0xC5, 0x56, 0xC9, 0x8C, 0x5E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC6, 0x9F, 0xF4, 0xE6, 0xF7, 0xB4, 0x01),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x7C, 0x03, 0x00, 0x26, 0x9F, 0xD8, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x1D, 0x6E, 0x00, 0xB9, 0x00, 0x6E, 0x93),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_23_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x63, 0xDA, 0x03, 0x2B, 0xD5, 0x0B, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xFC, 0xE2, 0xC8, 0x47, 0xF0, 0xAE, 0xF2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x4C, 0xF7, 0x50, 0x0C, 0x48, 0x06, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2B, 0x32, 0x98, 0x0E, 0x7E, 0x61, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x02, 0x27, 0xFE, 0x75, 0x86, 0xDF, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x30, 0xB1, 0x22, 0x32, 0x1B, 0xFE, 0x24),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x27, 0xF7, 0x78, 0x6F, 0xD7, 0xFD, 0xE4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x78, 0xCC, 0xEA, 0xC0, 0x50, 0x24, 0x44),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_24_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x2B, 0x4F, 0x7F, 0x58, 0xE6, 0xC2, 0x70),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x43, 0xD5, 0xA7, 0x35, 0x3C, 0x80, 0xB8),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x6D, 0x4B, 0x12, 0x00, 0x7B, 0xE6, 0xA6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x15, 0xBD, 0xD0, 0x9B, 0xCA, 0xAA, 0x81),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xCE, 0x9C, 0xE3, 0x8B, 0x60, 0x7A, 0x53),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xDA, 0x4B, 0x03, 0xA7, 0x8D, 0x43, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAF, 0x00, 0x2B, 0x32, 0xF0, 0x22, 0x68),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xD9, 0x99, 0x99, 0xBE, 0x43, 0x99, 0x3E),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_24_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x71, 0x41, 0xF4, 0xB5, 0xFD, 0xDD, 0x36),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xE2, 0x20, 0x4C, 0xD1, 0x2E, 0x1F, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x43, 0x48, 0x76, 0x8A, 0x49, 0xAC, 0x87),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1A, 0x55, 0xA8, 0xA3, 0xD4, 0x57, 0x75),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xA6, 0x84, 0x39, 0xC9, 0x13, 0xBB, 0x60),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xFA, 0xA9, 0x70, 0xDE, 0x83, 0xDD, 0xC9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xC9, 0xD9, 0x3E, 0x44, 0x91, 0x68, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x9F, 0x85, 0x6D, 0xF7, 0x54, 0x36, 0x82),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_25_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x6B, 0xA6, 0xA3, 0xE5, 0xD4, 0x46, 0xDB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x3E, 0xDC, 0x84, 0x7C, 0x7B, 0x24, 0x34),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xED, 0x7F, 0x86, 0x07, 0x6C, 0x57, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x06, 0xFE, 0x52, 0x12, 0x79, 0x69, 0x56),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xD1, 0x44, 0x5F, 0x21, 0x3A, 0xC3, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD9, 0x4A, 0xC0, 0x75, 0xAB, 0x17, 0xAC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x81, 0x94, 0xB6, 0x80, 0x6B, 0x6F, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBE, 0x8E, 0xA5, 0xAA, 0xBC, 0x1E, 0x3E),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_25_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xC7, 0x85, 0xA6, 0x59, 0x9B, 0xB1, 0x52),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xCE, 0x40, 0xD1, 0xFB, 0xDF, 0x94, 0xF7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xB8, 0x5E, 0xBF, 0x45, 0xA8, 0x2D, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9C, 0x06, 0x1B, 0xA9, 0x57, 0xB9, 0x79),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xE9, 0xCE, 0xA2, 0xD3, 0x74, 0xA1, 0x3C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x5F, 0x34, 0x78, 0xDB, 0xAE, 0x3A, 0x14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x32, 0x84, 0x3E, 0x68, 0x6A, 0x43, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xBC, 0x39, 0x36, 0xA4, 0xC5, 0xBB, 0x11),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_26_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x07, 0xA2, 0xB5, 0xC9, 0x0F, 0x4D, 0x0F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0x67, 0xE6, 0xF1, 0x46, 0xEB, 0x71),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x41, 0x23, 0x95, 0xE7, 0xE0, 0x10, 0xDD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x69, 0xFE, 0x68, 0x8C, 0xC6, 0x5F, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB9, 0x2B, 0x3D, 0xD2, 0x4F, 0xD8, 0x1A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x09, 0xF5, 0x5F, 0xCF, 0xF6, 0x91, 0x57),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x15, 0x42, 0x6B, 0x6D, 0xB5, 0xF3, 0xB6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x56, 0x9D, 0xC5, 0xFF, 0xCA, 0x13, 0x9B),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_26_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x38, 0xE6, 0x23, 0x63, 0x48, 0x3C, 0xCA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x68, 0x3C, 0xD1, 0x3B, 0xE9, 0x3B, 0x82),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x08, 0x54, 0x49, 0xD1, 0x46, 0x45, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x70, 0x52, 0x6E, 0x79, 0xC4, 0x5E, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xDF, 0xE8, 0x5A, 0x32, 0x81, 0xDA, 0xD3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x2D, 0x94, 0x5B, 0xB5, 0x35, 0x9F, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x12, 0x8D, 0xC3, 0x36, 0x36, 0xB2, 0x2A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x2F, 0x22, 0x38, 0x5B, 0x18, 0x4C, 0x35),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_27_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC1, 0x22, 0x0E, 0xF0, 0x73, 0x11, 0x05),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xAE, 0xA4, 0x56, 0x18, 0x61, 0x66, 0x12),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFB, 0x72, 0x08, 0x84, 0x38, 0x51, 0xB0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x86, 0xA8, 0xB9, 0x31, 0x99, 0x29, 0xC3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xFB, 0xC3, 0x42, 0xB3, 0xC7, 0x6F, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xF8, 0xE1, 0x09, 0xBE, 0x75, 0xB0, 0x22),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x7D, 0xFF, 0xF4, 0x99, 0xFC, 0x13, 0xAB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x1B, 0x84, 0x81, 0x42, 0x22, 0xC6, 0x3D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_27_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE0, 0x37, 0xA4, 0xA0, 0x2F, 0x38, 0x7F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x3D, 0xB7, 0x40, 0x2F, 0x39, 0x3C, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x3B, 0x8A, 0x51, 0xAE, 0x40, 0x49, 0x7A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x20, 0x9F, 0xDD, 0xA9, 0xD0, 0x77, 0xC7),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x1D, 0x64, 0xDA, 0xA0, 0x53, 0xC7, 0x7D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x7B, 0x66, 0x55, 0x94, 0xD1, 0x51, 0x44),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xB5, 0x5B, 0x38, 0x35, 0x40, 0xC0),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0x0F, 0xF0, 0x73, 0x79, 0x43, 0x61),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_28_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x47, 0x45, 0x69, 0x80, 0x72, 0x72, 0x42),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x11, 0x99, 0x59, 0xDB, 0x48, 0x80, 0x39),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x6E, 0x3D, 0xFC, 0x37, 0x15, 0xF4, 0xBF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xBB, 0x5B, 0xA6, 0x35, 0x8D, 0x28, 0x20),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x1A, 0x3B, 0x2C, 0x8F, 0xD3, 0xAA, 0x2D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x1C, 0x1A, 0xF8, 0x02, 0xD9, 0x7B, 0x41),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x69, 0xAC, 0xF8, 0x54, 0x31, 0x14, 0xA1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x8A, 0xE6, 0xDE, 0x58, 0xB9, 0xC4, 0x7A),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_28_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x83, 0x52, 0xFE, 0xF9, 0x7B, 0xE9, 0x1F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xA2, 0x55, 0x46, 0x15, 0x49, 0xC1, 0x3A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBC, 0x5C, 0x91, 0xBD, 0xB9, 0x9C, 0xF4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xFD, 0xB1, 0x4E, 0x5F, 0x74, 0xEE, 0x53),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x8B, 0xD8, 0x8B, 0x17, 0x73, 0x1B, 0x96),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x92, 0xD7, 0x67, 0x06, 0xAD, 0x25, 0xCD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0x80, 0x24, 0xE2, 0x27, 0x5F, 0x8B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x1C, 0xCE, 0xD0, 0x67, 0xCA, 0xD4, 0x0B),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_29_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xF1, 0xDD, 0x33, 0x66, 0xF9, 0x05, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xE5, 0x6B, 0x79, 0xBD, 0x48, 0x42, 0xAA),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x14, 0x52, 0xE3, 0x53, 0xB4, 0x50, 0xD4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x84, 0x6C, 0xCF, 0xDA, 0xB2, 0x20, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xD6, 0x1A, 0xE5, 0xE2, 0x29, 0x70, 0xCE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x61, 0xFE, 0xBB, 0x21, 0x82, 0xD1, 0xFE),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0xF0, 0x9C, 0x8B, 0x1A, 0x42, 0x30, 0x06),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xD6, 0x49, 0x81, 0x92, 0xF1, 0xD0, 0x90),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_29_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x91, 0x93, 0x6A, 0xA6, 0x22, 0xE9, 0xD6),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xDC, 0xC3, 0x69, 0x11, 0x95, 0x7D, 0xEC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xA3, 0x9D, 0x87, 0x5E, 0x64, 0x41, 0xA2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x87, 0x5A, 0x15, 0xBD, 0x6E, 0x3C, 0x8D),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x8D, 0x50, 0xCC, 0xCF, 0xB7, 0x8F, 0x0B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x65, 0xCD, 0x31, 0x30, 0xF1, 0x68, 0x13),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x5C, 0x66, 0x67, 0x92, 0x30, 0x57, 0x95),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x9B, 0x01, 0x3D, 0x20, 0x8B, 0xD1, 0x0D),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_30_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC0, 0xE6, 0x4F, 0xDE, 0x62, 0xAB, 0xB3),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x48, 0xB3, 0x1C, 0x0F, 0x16, 0x93, 0x45),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x63, 0xBD, 0x1F, 0x16, 0x50, 0x56, 0x98),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x06, 0xBC, 0xE9, 0x27, 0x1C, 0x9A, 0x7B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xFE, 0x21, 0xC5, 0x39, 0x55, 0xE1, 0xFD),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA8, 0xD0, 0x96, 0x0E, 0xB5, 0xB2, 0x84),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xE7, 0x4B, 0xF3, 0x11, 0x0C, 0xC9, 0x5B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x3A, 0xC4, 0x87, 0x71, 0xEE, 0xFA, 0x18),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_30_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x77, 0xEE, 0x81, 0x5E, 0x96, 0xEA, 0x4B),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xDF, 0xA9, 0xF4, 0x4F, 0x7C, 0xB2, 0x43),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD4, 0xDF, 0x35, 0x63, 0x47, 0x25, 0x8A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3D, 0xFF, 0xA4, 0x02, 0xC3, 0x95, 0x11),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x10, 0x78, 0xD1, 0x2B, 0xB7, 0xBE, 0x0E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE9, 0x57, 0xF9, 0xE0, 0xD8, 0xFC, 0xBC),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xC4, 0x01, 0xD6, 0xB4, 0xE7, 0x78, 0xE2),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6C, 0xB9, 0x13, 0xA4, 0xE8, 0x6D, 0x6F),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_31_X[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xB0, 0xC9, 0xCD, 0xBF, 0xA2, 0x1E, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x4F, 0x86, 0x22, 0x9B, 0xEA, 0xE8, 0xBB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x46, 0xDF, 0x43, 0xB9, 0x82, 0x2D, 0x0A),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x32, 0xF1, 0x4E, 0x95, 0x41, 0xAE, 0x8E),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x93, 0x26, 0xFC, 0xD3, 0x90, 0xDC, 0xEB),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x05, 0x45, 0xCA, 0xF9, 0x5A, 0x89, 0x93),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x82, 0x63, 0x4E, 0x55, 0x1D, 0x3A, 0x08),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x69, 0x52, 0x49, 0xE9, 0xED, 0x57, 0x34),\n};\nstatic const mbedtls_mpi_uint brainpoolP512r1_T_31_Y[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x64, 0xE9, 0xAC, 0x4C, 0x4A, 0xEA, 0x25),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xE9, 0x0B, 0x99, 0xE7, 0xF9, 0xA9, 0x2C),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x0C, 0xC1, 0xF4, 0x8D, 0x07, 0xB6, 0xB1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x68, 0xFA, 0x35, 0xE4, 0x9E, 0xAE, 0xD9),\n    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2D, 0x1A, 0x13, 0x8E, 0x02, 0xE2, 0x63),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x28, 0x86, 0x46, 0x7B, 0x3A, 0xE1),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4C, 0x64, 0x59, 0x0A, 0xF9, 0x02, 0xC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x4F, 0x23, 0xA2, 0xC3, 0xD5, 0xEF, 0x42),\n};\nstatic const mbedtls_ecp_point brainpoolP512r1_T[32] = {\n    ECP_POINT_INIT_XY_Z1(brainpoolP512r1_T_0_X, brainpoolP512r1_T_0_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_1_X, brainpoolP512r1_T_1_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_2_X, brainpoolP512r1_T_2_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_3_X, brainpoolP512r1_T_3_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_4_X, brainpoolP512r1_T_4_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_5_X, brainpoolP512r1_T_5_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_6_X, brainpoolP512r1_T_6_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_7_X, brainpoolP512r1_T_7_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_8_X, brainpoolP512r1_T_8_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_9_X, brainpoolP512r1_T_9_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_10_X, brainpoolP512r1_T_10_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_11_X, brainpoolP512r1_T_11_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_12_X, brainpoolP512r1_T_12_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_13_X, brainpoolP512r1_T_13_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_14_X, brainpoolP512r1_T_14_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_15_X, brainpoolP512r1_T_15_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_16_X, brainpoolP512r1_T_16_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_17_X, brainpoolP512r1_T_17_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_18_X, brainpoolP512r1_T_18_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_19_X, brainpoolP512r1_T_19_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_20_X, brainpoolP512r1_T_20_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_21_X, brainpoolP512r1_T_21_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_22_X, brainpoolP512r1_T_22_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_23_X, brainpoolP512r1_T_23_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_24_X, brainpoolP512r1_T_24_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_25_X, brainpoolP512r1_T_25_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_26_X, brainpoolP512r1_T_26_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_27_X, brainpoolP512r1_T_27_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_28_X, brainpoolP512r1_T_28_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_29_X, brainpoolP512r1_T_29_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_30_X, brainpoolP512r1_T_30_Y),\n    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_31_X, brainpoolP512r1_T_31_Y),\n};\n#else\n#define brainpoolP512r1_T NULL\n#endif\n#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */\n\n\n#if defined(ECP_LOAD_GROUP) || defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \\\n    defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n/*\n * Create an MPI from embedded constants\n * (assumes len is an exact multiple of sizeof(mbedtls_mpi_uint) and\n * len < 1048576)\n */\nstatic inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len)\n{\n    X->s = 1;\n    X->n = (unsigned short) (len / sizeof(mbedtls_mpi_uint));\n    X->p = (mbedtls_mpi_uint *) p;\n}\n#endif\n\n#if defined(ECP_LOAD_GROUP)\n/*\n * Set an MPI to static value 1\n */\nstatic inline void ecp_mpi_set1(mbedtls_mpi *X)\n{\n    X->s = 1;\n    X->n = 1;\n    X->p = mpi_one;\n}\n\n/*\n * Make group available from embedded constants\n */\nstatic int ecp_group_load(mbedtls_ecp_group *grp,\n                          const mbedtls_mpi_uint *p,  size_t plen,\n                          const mbedtls_mpi_uint *a,  size_t alen,\n                          const mbedtls_mpi_uint *b,  size_t blen,\n                          const mbedtls_mpi_uint *gx, size_t gxlen,\n                          const mbedtls_mpi_uint *gy, size_t gylen,\n                          const mbedtls_mpi_uint *n,  size_t nlen,\n                          const mbedtls_ecp_point *T)\n{\n    ecp_mpi_load(&grp->P, p, plen);\n    if (a != NULL) {\n        ecp_mpi_load(&grp->A, a, alen);\n    }\n    ecp_mpi_load(&grp->B, b, blen);\n    ecp_mpi_load(&grp->N, n, nlen);\n\n    ecp_mpi_load(&grp->G.X, gx, gxlen);\n    ecp_mpi_load(&grp->G.Y, gy, gylen);\n    ecp_mpi_set1(&grp->G.Z);\n\n    grp->pbits = mbedtls_mpi_bitlen(&grp->P);\n    grp->nbits = mbedtls_mpi_bitlen(&grp->N);\n\n    grp->h = 1;\n\n    grp->T = (mbedtls_ecp_point *) T;\n    /*\n     * Set T_size to 0 to prevent T free by mbedtls_ecp_group_free.\n     */\n    grp->T_size = 0;\n\n    return 0;\n}\n#endif /* ECP_LOAD_GROUP */\n\n#if defined(MBEDTLS_ECP_NIST_OPTIM)\n/* Forward declarations */\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\nstatic int ecp_mod_p192(mbedtls_mpi *);\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn);\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)\nstatic int ecp_mod_p224(mbedtls_mpi *);\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)\nstatic int ecp_mod_p256(mbedtls_mpi *);\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\nstatic int ecp_mod_p384(mbedtls_mpi *);\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)\nstatic int ecp_mod_p521(mbedtls_mpi *);\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *N_p, size_t N_n);\n#endif\n\n#define NIST_MODP(P)      grp->modp = ecp_mod_ ## P;\n#else\n#define NIST_MODP(P)\n#endif /* MBEDTLS_ECP_NIST_OPTIM */\n\n/* Additional forward declarations */\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\nstatic int ecp_mod_p255(mbedtls_mpi *);\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n#endif\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\nstatic int ecp_mod_p448(mbedtls_mpi *);\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *, size_t);\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)\nstatic int ecp_mod_p192k1(mbedtls_mpi *);\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)\nstatic int ecp_mod_p224k1(mbedtls_mpi *);\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n#endif\n#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\nstatic int ecp_mod_p256k1(mbedtls_mpi *);\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n#endif\n\n#if defined(ECP_LOAD_GROUP)\n#define LOAD_GROUP_A(G)   ecp_group_load(grp,            \\\n                                         G ## _p,  sizeof(G ## _p),   \\\n                                         G ## _a,  sizeof(G ## _a),   \\\n                                         G ## _b,  sizeof(G ## _b),   \\\n                                         G ## _gx, sizeof(G ## _gx),   \\\n                                         G ## _gy, sizeof(G ## _gy),   \\\n                                         G ## _n,  sizeof(G ## _n),   \\\n                                         G ## _T                         \\\n                                         )\n\n#define LOAD_GROUP(G)     ecp_group_load(grp,            \\\n                                         G ## _p,  sizeof(G ## _p),   \\\n                                         NULL,     0,                    \\\n                                         G ## _b,  sizeof(G ## _b),   \\\n                                         G ## _gx, sizeof(G ## _gx),   \\\n                                         G ## _gy, sizeof(G ## _gy),   \\\n                                         G ## _n,  sizeof(G ## _n),   \\\n                                         G ## _T                         \\\n                                         )\n#endif /* ECP_LOAD_GROUP */\n\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n/* Constants used by ecp_use_curve25519() */\nstatic const mbedtls_mpi_sint curve25519_a24 = 0x01DB42;\n\n/* P = 2^255 - 19 */\nstatic const mbedtls_mpi_uint curve25519_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X7F)\n};\n\n/* N = 2^252 + 27742317777372353535851937790883648493 */\nstatic const mbedtls_mpi_uint curve25519_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0XED, 0XD3, 0XF5, 0X5C, 0X1A, 0X63, 0X12, 0X58),\n    MBEDTLS_BYTES_TO_T_UINT_8(0XD6, 0X9C, 0XF7, 0XA2, 0XDE, 0XF9, 0XDE, 0X14),\n    MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0x00, 0x00, 0x00, 0x00),\n    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10)\n};\n\n/*\n * Specialized function for creating the Curve25519 group\n */\nstatic int ecp_use_curve25519(mbedtls_ecp_group *grp)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* Actually ( A + 2 ) / 4 */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve25519_a24));\n\n    ecp_mpi_load(&grp->P, curve25519_p, sizeof(curve25519_p));\n\n    grp->pbits = mbedtls_mpi_bitlen(&grp->P);\n\n    ecp_mpi_load(&grp->N, curve25519_n, sizeof(curve25519_n));\n\n    /* Y intentionally not set, since we use x/z coordinates.\n     * This is used as a marker to identify Montgomery curves! */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 9));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1));\n    mbedtls_mpi_free(&grp->G.Y);\n\n    /* Actually, the required msb for private keys */\n    grp->nbits = 254;\n\ncleanup:\n    if (ret != 0) {\n        mbedtls_ecp_group_free(grp);\n    }\n\n    return ret;\n}\n#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n/* Constants used by ecp_use_curve448() */\nstatic const mbedtls_mpi_sint curve448_a24 = 0x98AA;\n\n/* P = 2^448 - 2^224 - 1 */\nstatic const mbedtls_mpi_uint curve448_p[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFE, 0XFF, 0XFF, 0XFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00)\n};\n\n/* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */\nstatic const mbedtls_mpi_uint curve448_n[] = {\n    MBEDTLS_BYTES_TO_T_UINT_8(0XF3, 0X44, 0X58, 0XAB, 0X92, 0XC2, 0X78, 0X23),\n    MBEDTLS_BYTES_TO_T_UINT_8(0X55, 0X8F, 0XC5, 0X8D, 0X72, 0XC2, 0X6C, 0X21),\n    MBEDTLS_BYTES_TO_T_UINT_8(0X90, 0X36, 0XD6, 0XAE, 0X49, 0XDB, 0X4E, 0XC4),\n    MBEDTLS_BYTES_TO_T_UINT_8(0XE9, 0X23, 0XCA, 0X7C, 0XFF, 0XFF, 0XFF, 0XFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),\n    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X3F),\n    MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00)\n};\n\n/*\n * Specialized function for creating the Curve448 group\n */\nstatic int ecp_use_curve448(mbedtls_ecp_group *grp)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* Actually ( A + 2 ) / 4 */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve448_a24));\n\n    ecp_mpi_load(&grp->P, curve448_p, sizeof(curve448_p));\n    grp->pbits = mbedtls_mpi_bitlen(&grp->P);\n\n    /* Y intentionally not set, since we use x/z coordinates.\n     * This is used as a marker to identify Montgomery curves! */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 5));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1));\n    mbedtls_mpi_free(&grp->G.Y);\n\n    ecp_mpi_load(&grp->N, curve448_n, sizeof(curve448_n));\n\n    /* Actually, the required msb for private keys */\n    grp->nbits = 447;\n\ncleanup:\n    if (ret != 0) {\n        mbedtls_ecp_group_free(grp);\n    }\n\n    return ret;\n}\n#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */\n\n/*\n * Set a group using well-known domain parameters\n */\nint mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id)\n{\n    mbedtls_ecp_group_free(grp);\n\n    mbedtls_ecp_group_init(grp);\n\n    grp->id = id;\n\n    switch (id) {\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP192R1:\n            NIST_MODP(p192);\n            return LOAD_GROUP(secp192r1);\n#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP224R1:\n            NIST_MODP(p224);\n            return LOAD_GROUP(secp224r1);\n#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP256R1:\n            NIST_MODP(p256);\n            return LOAD_GROUP(secp256r1);\n#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP384R1:\n            NIST_MODP(p384);\n            return LOAD_GROUP(secp384r1);\n#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP521R1:\n            NIST_MODP(p521);\n            return LOAD_GROUP(secp521r1);\n#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP192K1:\n            grp->modp = ecp_mod_p192k1;\n            return LOAD_GROUP_A(secp192k1);\n#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP224K1:\n            grp->modp = ecp_mod_p224k1;\n            return LOAD_GROUP_A(secp224k1);\n#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP256K1:\n            grp->modp = ecp_mod_p256k1;\n            return LOAD_GROUP_A(secp256k1);\n#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)\n        case MBEDTLS_ECP_DP_BP256R1:\n            return LOAD_GROUP_A(brainpoolP256r1);\n#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)\n        case MBEDTLS_ECP_DP_BP384R1:\n            return LOAD_GROUP_A(brainpoolP384r1);\n#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)\n        case MBEDTLS_ECP_DP_BP512R1:\n            return LOAD_GROUP_A(brainpoolP512r1);\n#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n        case MBEDTLS_ECP_DP_CURVE25519:\n            grp->modp = ecp_mod_p255;\n            return ecp_use_curve25519(grp);\n#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n        case MBEDTLS_ECP_DP_CURVE448:\n            grp->modp = ecp_mod_p448;\n            return ecp_use_curve448(grp);\n#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */\n\n        default:\n            grp->id = MBEDTLS_ECP_DP_NONE;\n            return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n    }\n}\n\n#if defined(MBEDTLS_ECP_NIST_OPTIM)\n/*\n * Fast reduction modulo the primes used by the NIST curves.\n *\n * These functions are critical for speed, but not needed for correct\n * operations. So, we make the choice to heavily rely on the internals of our\n * bignum library, which creates a tight coupling between these functions and\n * our MPI implementation.  However, the coupling between the ECP module and\n * MPI remains loose, since these functions can be deactivated at will.\n */\n\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\n/*\n * Compared to the way things are presented in FIPS 186-3 D.2,\n * we proceed in columns, from right (least significant chunk) to left,\n * adding chunks to N in place, and keeping a carry for the next chunk.\n * This avoids moving things around in memory, and uselessly adding zeros,\n * compared to the more straightforward, line-oriented approach.\n *\n * For this prime we need to handle data in chunks of 64 bits.\n * Since this is always a multiple of our basic mbedtls_mpi_uint, we can\n * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it.\n */\n\n/* Add 64-bit chunks (dst += src) and update carry */\nstatic inline void add64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry)\n{\n    unsigned char i;\n    mbedtls_mpi_uint c = 0;\n    for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++, src++) {\n        *dst += c;      c  = (*dst < c);\n        *dst += *src;   c += (*dst < *src);\n    }\n    *carry += c;\n}\n\n/* Add carry to a 64-bit chunk and update carry */\nstatic inline void carry64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry)\n{\n    unsigned char i;\n    for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++) {\n        *dst += *carry;\n        *carry  = (*dst < *carry);\n    }\n}\n\n#define WIDTH       8 / sizeof(mbedtls_mpi_uint)\n#define A(i)        Np + (i) * WIDTH\n#define ADD(i)      add64(p, A(i), &c)\n#define NEXT        p += WIDTH; carry64(p, &c)\n#define LAST        p += WIDTH; do *p = 0; while (++p < end)\n#define RESET       last_carry[0] = c; c = 0; p = Np\n#define ADD_LAST    add64(p, last_carry, &c)\n\n/*\n * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)\n */\nstatic int ecp_mod_p192(mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t expected_width = BITS_TO_LIMBS(192) * 2;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));\n    ret = mbedtls_ecp_mod_p192_raw(N->p, expected_width);\n\ncleanup:\n    return ret;\n}\n\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn)\n{\n    mbedtls_mpi_uint c = 0, last_carry[WIDTH] = { 0 };\n    mbedtls_mpi_uint *p, *end;\n\n    if (Nn != BITS_TO_LIMBS(192) * 2) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    p = Np;\n    end = p + Nn;\n\n    ADD(3); ADD(5);         NEXT;   // A0 += A3 + A5\n    ADD(3); ADD(4); ADD(5); NEXT;   // A1 += A3 + A4 + A5\n    ADD(4); ADD(5);                 // A2 += A4 + A5\n\n    RESET;\n\n    /* Use the reduction for the carry as well:\n     * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192\n     * It can generate a carry. */\n    ADD_LAST; NEXT;                 // A0 += last_carry\n    ADD_LAST; NEXT;                 // A1 += last_carry\n                                    // A2 += carry\n\n    RESET;\n\n    /* Use the reduction for the carry as well:\n     * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192\n     */\n    ADD_LAST; NEXT;                 // A0 += last_carry\n    ADD_LAST; NEXT;                 // A1 += last_carry\n                                    // A2 += carry\n\n    LAST;\n\n    return 0;\n}\n\n#undef WIDTH\n#undef A\n#undef ADD\n#undef NEXT\n#undef LAST\n#undef RESET\n#undef ADD_LAST\n#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\n\n/*\n * The reader is advised to first understand ecp_mod_p192() since the same\n * general structure is used here, but with additional complications:\n * (1) chunks of 32 bits, and (2) subtractions.\n */\n\n/*\n * For these primes, we need to handle data in chunks of 32 bits.\n * This makes it more complicated if we use 64 bits limbs in MPI,\n * which prevents us from using a uniform access method as for p192.\n *\n * So, we define a mini abstraction layer to access 32 bit chunks,\n * load them in 'cur' for work, and store them back from 'cur' when done.\n *\n * While at it, also define the size of N in terms of 32-bit chunks.\n */\n#define LOAD32      cur = A(i);\n\n#if defined(MBEDTLS_HAVE_INT32)  /* 32 bit */\n\n#define MAX32       X_limbs\n#define A(j)        X[j]\n#define STORE32     X[i] = (mbedtls_mpi_uint) cur;\n#define STORE0      X[i] = 0;\n\n#else /* 64 bit */\n\n#define MAX32   X_limbs * 2\n#define A(j)                                                \\\n    (j) % 2 ?                                               \\\n    (uint32_t) (X[(j) / 2] >> 32) :                         \\\n    (uint32_t) (X[(j) / 2])\n#define STORE32                                             \\\n    if (i % 2) {                                            \\\n        X[i/2] &= 0x00000000FFFFFFFF;                       \\\n        X[i/2] |= (uint64_t) (cur) << 32;                   \\\n    } else {                                                \\\n        X[i/2] &= 0xFFFFFFFF00000000;                       \\\n        X[i/2] |= (uint32_t) cur;                           \\\n    }\n\n#define STORE0                                              \\\n    if (i % 2) {                                            \\\n        X[i/2] &= 0x00000000FFFFFFFF;                       \\\n    } else {                                                \\\n        X[i/2] &= 0xFFFFFFFF00000000;                       \\\n    }\n\n#endif\n\nstatic inline int8_t extract_carry(int64_t cur)\n{\n    return (int8_t) (cur >> 32);\n}\n\n#define ADD(j)    cur += A(j)\n#define SUB(j)    cur -= A(j)\n\n#define ADD_CARRY(cc) cur += (cc)\n#define SUB_CARRY(cc) cur -= (cc)\n\n#define ADD_LAST ADD_CARRY(last_c)\n#define SUB_LAST SUB_CARRY(last_c)\n\n/*\n * Helpers for the main 'loop'\n */\n#define INIT(b)                                         \\\n    int8_t c = 0, last_c;                               \\\n    int64_t cur;                                        \\\n    size_t i = 0;                                       \\\n    LOAD32;\n\n#define NEXT                                            \\\n    c = extract_carry(cur);                             \\\n    STORE32; i++; LOAD32;                               \\\n    ADD_CARRY(c);\n\n#define RESET                                           \\\n    c = extract_carry(cur);                             \\\n    last_c = c;                                         \\\n    STORE32; i = 0; LOAD32;                             \\\n    c = 0;                                              \\\n\n#define LAST                                            \\\n    c = extract_carry(cur);                             \\\n    STORE32; i++;                                       \\\n    if (c != 0)                                         \\\n    return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;              \\\n    while (i < MAX32) { STORE0; i++; }\n\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)\n\n/*\n * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)\n */\nstatic int ecp_mod_p224(mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t expected_width = BITS_TO_LIMBS(224) * 2;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));\n    ret = mbedtls_ecp_mod_p224_raw(N->p, expected_width);\ncleanup:\n    return ret;\n}\n\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs)\n{\n    if (X_limbs != BITS_TO_LIMBS(224) * 2) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    INIT(224);\n\n    SUB(7);  SUB(11);           NEXT;   // A0 += -A7  - A11\n    SUB(8);  SUB(12);           NEXT;   // A1 += -A8  - A12\n    SUB(9);  SUB(13);           NEXT;   // A2 += -A9  - A13\n    SUB(10); ADD(7);  ADD(11);  NEXT;   // A3 += -A10 + A7 + A11\n    SUB(11); ADD(8);  ADD(12);  NEXT;   // A4 += -A11 + A8 + A12\n    SUB(12); ADD(9);  ADD(13);  NEXT;   // A5 += -A12 + A9 + A13\n    SUB(13); ADD(10);                   // A6 += -A13 + A10\n\n    RESET;\n\n    /* Use 2^224 = P + 2^96 - 1 to modulo reduce the final carry */\n    SUB_LAST; NEXT;                     // A0 -= last_c\n    ;         NEXT;                     // A1\n    ;         NEXT;                     // A2\n    ADD_LAST; NEXT;                     // A3 += last_c\n    ;         NEXT;                     // A4\n    ;         NEXT;                     // A5\n                                        // A6\n\n    /* The carry reduction cannot generate a carry\n     * (see commit 73e8553 for details)*/\n\n    LAST;\n\n    return 0;\n}\n\n#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)\n\n/*\n * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)\n */\nstatic int ecp_mod_p256(mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t expected_width = BITS_TO_LIMBS(256) * 2;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));\n    ret = mbedtls_ecp_mod_p256_raw(N->p, expected_width);\ncleanup:\n    return ret;\n}\n\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs)\n{\n    if (X_limbs != BITS_TO_LIMBS(256) * 2) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    INIT(256);\n\n    ADD(8);  ADD(9);\n    SUB(11); SUB(12); SUB(13); SUB(14);                   NEXT; // A0\n\n    ADD(9);  ADD(10);\n    SUB(12); SUB(13); SUB(14); SUB(15);                   NEXT; // A1\n\n    ADD(10); ADD(11);\n    SUB(13); SUB(14); SUB(15);                            NEXT; // A2\n\n    ADD(11); ADD(11); ADD(12); ADD(12); ADD(13);\n    SUB(15); SUB(8);  SUB(9);                             NEXT; // A3\n\n    ADD(12); ADD(12); ADD(13); ADD(13); ADD(14);\n    SUB(9);  SUB(10);                                     NEXT; // A4\n\n    ADD(13); ADD(13); ADD(14); ADD(14); ADD(15);\n    SUB(10); SUB(11);                                     NEXT; // A5\n\n    ADD(14); ADD(14); ADD(15); ADD(15); ADD(14); ADD(13);\n    SUB(8);  SUB(9);                                      NEXT; // A6\n\n    ADD(15); ADD(15); ADD(15); ADD(8);\n    SUB(10); SUB(11); SUB(12); SUB(13);                         // A7\n\n    RESET;\n\n    /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1\n     * to modulo reduce the final carry. */\n    ADD_LAST; NEXT;                                             // A0\n    ;         NEXT;                                             // A1\n    ;         NEXT;                                             // A2\n    SUB_LAST; NEXT;                                             // A3\n    ;         NEXT;                                             // A4\n    ;         NEXT;                                             // A5\n    SUB_LAST; NEXT;                                             // A6\n    ADD_LAST;                                                   // A7\n\n    RESET;\n\n    /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1\n     * to modulo reduce the carry generated by the previous reduction. */\n    ADD_LAST; NEXT;                                             // A0\n    ;         NEXT;                                             // A1\n    ;         NEXT;                                             // A2\n    SUB_LAST; NEXT;                                             // A3\n    ;         NEXT;                                             // A4\n    ;         NEXT;                                             // A5\n    SUB_LAST; NEXT;                                             // A6\n    ADD_LAST;                                                   // A7\n\n    LAST;\n\n    return 0;\n}\n\n#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\n/*\n * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)\n */\nstatic int ecp_mod_p384(mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t expected_width = BITS_TO_LIMBS(384) * 2;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));\n    ret = mbedtls_ecp_mod_p384_raw(N->p, expected_width);\ncleanup:\n    return ret;\n}\n\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs)\n{\n    if (X_limbs != BITS_TO_LIMBS(384) * 2) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    INIT(384);\n\n    ADD(12); ADD(21); ADD(20);\n    SUB(23);                                                NEXT; // A0\n\n    ADD(13); ADD(22); ADD(23);\n    SUB(12); SUB(20);                                       NEXT; // A1\n\n    ADD(14); ADD(23);\n    SUB(13); SUB(21);                                       NEXT; // A2\n\n    ADD(15); ADD(12); ADD(20); ADD(21);\n    SUB(14); SUB(22); SUB(23);                              NEXT; // A3\n\n    ADD(21); ADD(21); ADD(16); ADD(13); ADD(12); ADD(20); ADD(22);\n    SUB(15); SUB(23); SUB(23);                              NEXT; // A4\n\n    ADD(22); ADD(22); ADD(17); ADD(14); ADD(13); ADD(21); ADD(23);\n    SUB(16);                                                NEXT; // A5\n\n    ADD(23); ADD(23); ADD(18); ADD(15); ADD(14); ADD(22);\n    SUB(17);                                                NEXT; // A6\n\n    ADD(19); ADD(16); ADD(15); ADD(23);\n    SUB(18);                                                NEXT; // A7\n\n    ADD(20); ADD(17); ADD(16);\n    SUB(19);                                                NEXT; // A8\n\n    ADD(21); ADD(18); ADD(17);\n    SUB(20);                                                NEXT; // A9\n\n    ADD(22); ADD(19); ADD(18);\n    SUB(21);                                                NEXT; // A10\n\n    ADD(23); ADD(20); ADD(19);\n    SUB(22);                                                      // A11\n\n    RESET;\n\n    /* Use 2^384 = P + 2^128 + 2^96 - 2^32 + 1 to modulo reduce the final carry */\n    ADD_LAST; NEXT;                                               // A0\n    SUB_LAST; NEXT;                                               // A1\n    ;         NEXT;                                               // A2\n    ADD_LAST; NEXT;                                               // A3\n    ADD_LAST; NEXT;                                               // A4\n    ;         NEXT;                                               // A5\n    ;         NEXT;                                               // A6\n    ;         NEXT;                                               // A7\n    ;         NEXT;                                               // A8\n    ;         NEXT;                                               // A9\n    ;         NEXT;                                               // A10\n                                                                  // A11\n\n    RESET;\n\n    ADD_LAST; NEXT;                                               // A0\n    SUB_LAST; NEXT;                                               // A1\n    ;         NEXT;                                               // A2\n    ADD_LAST; NEXT;                                               // A3\n    ADD_LAST; NEXT;                                               // A4\n    ;         NEXT;                                               // A5\n    ;         NEXT;                                               // A6\n    ;         NEXT;                                               // A7\n    ;         NEXT;                                               // A8\n    ;         NEXT;                                               // A9\n    ;         NEXT;                                               // A10\n                                                                  // A11\n\n    LAST;\n\n    return 0;\n}\n#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */\n\n#undef LOAD32\n#undef MAX32\n#undef A\n#undef STORE32\n#undef STORE0\n#undef ADD\n#undef SUB\n#undef ADD_CARRY\n#undef SUB_CARRY\n#undef ADD_LAST\n#undef SUB_LAST\n#undef INIT\n#undef NEXT\n#undef RESET\n#undef LAST\n\n#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED ||\n          MBEDTLS_ECP_DP_SECP256R1_ENABLED ||\n          MBEDTLS_ECP_DP_SECP384R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)\n/* Size of p521 in terms of mbedtls_mpi_uint */\n#define P521_WIDTH      (521 / 8 / sizeof(mbedtls_mpi_uint) + 1)\n\n/* Bits to keep in the most significant mbedtls_mpi_uint */\n#define P521_MASK       0x01FF\n\n/*\n * Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5)\n */\nstatic int ecp_mod_p521(mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t expected_width = BITS_TO_LIMBS(521) * 2;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));\n    ret = mbedtls_ecp_mod_p521_raw(N->p, expected_width);\ncleanup:\n    return ret;\n}\n\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs)\n{\n    mbedtls_mpi_uint carry = 0;\n\n    if (X_limbs != BITS_TO_LIMBS(521) * 2) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    /* Step 1: Reduction to P521_WIDTH limbs */\n    /* Helper references for bottom part of X */\n    mbedtls_mpi_uint *X0 = X;\n    size_t X0_limbs = P521_WIDTH;\n    /* Helper references for top part of X */\n    mbedtls_mpi_uint *X1 = X + X0_limbs;\n    size_t X1_limbs = X_limbs - X0_limbs;\n    /* Split X as X0 + 2^P521_WIDTH X1 and compute X0 + 2^(biL - 9) X1.\n     * (We are using that 2^P521_WIDTH = 2^(512 + biL) and that\n     * 2^(512 + biL) X1 = 2^(biL - 9) X1 mod P521.)\n     * The high order limb of the result will be held in carry and the rest\n     * in X0 (that is the result will be represented as\n     * 2^P521_WIDTH carry + X0).\n     *\n     * Also, note that the resulting carry is either 0 or 1:\n     * X0 < 2^P521_WIDTH = 2^(512 + biL) and X1 < 2^(P521_WIDTH-biL) = 2^512\n     * therefore\n     * X0 + 2^(biL - 9) X1 < 2^(512 + biL) + 2^(512 + biL - 9)\n     * which in turn is less than 2 * 2^(512 + biL).\n     */\n    mbedtls_mpi_uint shift = ((mbedtls_mpi_uint) 1u) << (biL - 9);\n    carry = mbedtls_mpi_core_mla(X0, X0_limbs, X1, X1_limbs, shift);\n    /* Set X to X0 (by clearing the top part). */\n    memset(X1, 0, X1_limbs * sizeof(mbedtls_mpi_uint));\n\n    /* Step 2: Reduction modulo P521\n     *\n     * At this point X is reduced to P521_WIDTH limbs. What remains is to add\n     * the carry (that is 2^P521_WIDTH carry) and to reduce mod P521. */\n\n    /* 2^P521_WIDTH carry = 2^(512 + biL) carry = 2^(biL - 9) carry mod P521.\n     * Also, recall that carry is either 0 or 1. */\n    mbedtls_mpi_uint addend = carry << (biL - 9);\n    /* Keep the top 9 bits and reduce the rest, using 2^521 = 1 mod P521. */\n    addend += (X[P521_WIDTH - 1] >> 9);\n    X[P521_WIDTH - 1] &= P521_MASK;\n\n    /* Reuse the top part of X (already zeroed) as a helper array for\n     * carrying out the addition. */\n    mbedtls_mpi_uint *addend_arr = X + P521_WIDTH;\n    addend_arr[0] = addend;\n    (void) mbedtls_mpi_core_add(X, X, addend_arr, P521_WIDTH);\n    /* Both addends were less than P521 therefore X < 2 * P521. (This also means\n     * that the result fit in P521_WIDTH limbs and there won't be any carry.) */\n\n    /* Clear the reused part of X. */\n    addend_arr[0] = 0;\n\n    return 0;\n}\n\n#undef P521_WIDTH\n#undef P521_MASK\n\n#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */\n\n#endif /* MBEDTLS_ECP_NIST_OPTIM */\n\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n\n/* Size of p255 in terms of mbedtls_mpi_uint */\n#define P255_WIDTH      (255 / 8 / sizeof(mbedtls_mpi_uint) + 1)\n\n/*\n * Fast quasi-reduction modulo p255 = 2^255 - 19\n * Write N as A0 + 2^256 A1, return A0 + 38 * A1\n */\nstatic int ecp_mod_p255(mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t expected_width = BITS_TO_LIMBS(255) * 2;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));\n    ret = mbedtls_ecp_mod_p255_raw(N->p, expected_width);\ncleanup:\n    return ret;\n}\n\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_Limbs)\n{\n\n    if (X_Limbs != BITS_TO_LIMBS(255) * 2) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    mbedtls_mpi_uint *carry = mbedtls_calloc(P255_WIDTH, ciL);\n    if (carry == NULL) {\n        return MBEDTLS_ERR_ECP_ALLOC_FAILED;\n    }\n\n    /* Step 1: Reduction to P255_WIDTH limbs */\n    if (X_Limbs > P255_WIDTH) {\n        /* Helper references for top part of X */\n        mbedtls_mpi_uint * const A1 = X + P255_WIDTH;\n        const size_t A1_limbs = X_Limbs - P255_WIDTH;\n\n        /* X = A0 + 38 * A1, capture carry out */\n        *carry = mbedtls_mpi_core_mla(X, P255_WIDTH, A1, A1_limbs, 38);\n        /* Clear top part */\n        memset(A1, 0, sizeof(mbedtls_mpi_uint) * A1_limbs);\n    }\n\n    /* Step 2: Reduce to <2p\n     * Split as A0 + 2^255*c, with c a scalar, and compute A0 + 19*c */\n    *carry <<= 1;\n    *carry += (X[P255_WIDTH - 1] >> (biL - 1));\n    *carry *= 19;\n\n    /* Clear top bit */\n    X[P255_WIDTH - 1] <<= 1; X[P255_WIDTH - 1] >>= 1;\n    /* Since the top bit for X has been cleared 0 + 0 + Carry\n     * will not overflow.\n     *\n     * Furthermore for 2p = 2^256-38. When a carry propagation on the highest\n     * limb occurs, X > 2^255 and all the remaining bits on the limb are zero.\n     *   - If X < 2^255 ==> X < 2p\n     *   - If X > 2^255 ==> X < 2^256 - 2^255 < 2p  */\n    (void) mbedtls_mpi_core_add(X, X, carry, P255_WIDTH);\n\n    mbedtls_free(carry);\n    return 0;\n}\n#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n\n/* Size of p448 in terms of mbedtls_mpi_uint */\n#define P448_WIDTH      (448 / 8 / sizeof(mbedtls_mpi_uint))\n\n/* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */\n#define DIV_ROUND_UP(X, Y) (((X) + (Y) -1) / (Y))\n#define P224_SIZE        (224 / 8)\n#define P224_WIDTH_MIN   (P224_SIZE / sizeof(mbedtls_mpi_uint))\n#define P224_WIDTH_MAX   DIV_ROUND_UP(P224_SIZE, sizeof(mbedtls_mpi_uint))\n#define P224_UNUSED_BITS ((P224_WIDTH_MAX * sizeof(mbedtls_mpi_uint) * 8) - 224)\n\nstatic int ecp_mod_p448(mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t expected_width = BITS_TO_LIMBS(448) * 2;\n\n    /* This is required as some tests and use cases do not pass in a Bignum of\n     * the correct size, and expect the growth to be done automatically, which\n     * will no longer happen. */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));\n\n    ret = mbedtls_ecp_mod_p448_raw(N->p, N->n);\n\ncleanup:\n    return ret;\n}\n\n/*\n * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1\n * Write X as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return A0 + A1 + B1 +\n * (B0 + B1) * 2^224.  This is different to the reference implementation of\n * Curve448, which uses its own special 56-bit limbs rather than a generic\n * bignum library.  We could squeeze some extra speed out on 32-bit machines by\n * splitting N up into 32-bit limbs and doing the arithmetic using the limbs\n * directly as we do for the NIST primes above, but for 64-bit targets it should\n * use half the number of operations if we do the reduction with 224-bit limbs,\n * since mpi_core_add will then use 64-bit adds.\n */\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *X, size_t X_limbs)\n{\n    size_t round;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (X_limbs != BITS_TO_LIMBS(448) * 2) {\n        return 0;\n    }\n\n    size_t M_limbs = X_limbs - (P448_WIDTH);\n\n    if (M_limbs > P448_WIDTH) {\n        /* Shouldn't be called with X larger than 2^896! */\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    /* Both M and Q require an extra limb to catch carries. */\n    M_limbs++;\n\n    const size_t Q_limbs = M_limbs;\n    mbedtls_mpi_uint *M = NULL;\n    mbedtls_mpi_uint *Q = NULL;\n\n    M = mbedtls_calloc(M_limbs, ciL);\n\n    if (M == NULL) {\n        return MBEDTLS_ERR_ECP_ALLOC_FAILED;\n    }\n\n    Q = mbedtls_calloc(Q_limbs, ciL);\n\n    if (Q == NULL) {\n        ret =  MBEDTLS_ERR_ECP_ALLOC_FAILED;\n        goto cleanup;\n    }\n\n    /* M = A1 */\n    memset(M, 0, (M_limbs * ciL));\n    /* Do not copy into the overflow limb, as this would read past the end of\n     * X. */\n    memcpy(M, X + P448_WIDTH, ((M_limbs - 1) * ciL));\n\n    /* X = A0 */\n    memset(X + P448_WIDTH, 0, ((M_limbs - 1) * ciL));\n\n    /* X = X + M = A0 + A1 */\n    /* Carry here fits in oversize X. Oversize M means it will get\n     * added in, not returned as carry. */\n    (void) mbedtls_mpi_core_add(X, X, M, M_limbs);\n\n    /* Q = B1 = M >> 224 */\n    memcpy(Q, (char *) M + P224_SIZE, P224_SIZE);\n    memset((char *) Q + P224_SIZE, 0, P224_SIZE);\n\n    /* X = X + Q = (A0 + A1) + B1\n     * Oversize Q catches potential carry here when X is already max 448 bits.\n     */\n    (void) mbedtls_mpi_core_add(X, X, Q, Q_limbs);\n\n    /* M = B0 */\n#ifdef MBEDTLS_HAVE_INT64\n    M[P224_WIDTH_MIN] &= ((mbedtls_mpi_uint)-1) >> (P224_UNUSED_BITS);\n #endif\n    memset(M + P224_WIDTH_MAX, 0, ((M_limbs - P224_WIDTH_MAX) * ciL));\n\n    /* M = M + Q = B0 + B1 */\n    (void) mbedtls_mpi_core_add(M, M, Q, Q_limbs);\n\n    /* M = (B0 + B1) * 2^224 */\n    /* Shifted carry bit from the addition fits in oversize M. */\n    memmove((char *) M + P224_SIZE, M, P224_SIZE + ciL);\n    memset(M, 0, P224_SIZE);\n\n    /* X = X + M = (A0 + A1 + B1) + (B0 + B1) * 2^224 */\n    (void) mbedtls_mpi_core_add(X, X, M, M_limbs);\n\n    /* In the second and third rounds A1 and B0 have at most 1 non-zero limb and\n     * B1=0.\n     * Using this we need to calculate:\n     * A0 + A1 + B1 + (B0 + B1) * 2^224 = A0 + A1 + B0 * 2^224. */\n    for (round = 0; round < 2; ++round) {\n\n        /* M = A1 */\n        memset(M, 0, (M_limbs * ciL));\n        memcpy(M, X + P448_WIDTH, ((M_limbs - 1) * ciL));\n\n        /* X = A0 */\n        memset(X + P448_WIDTH, 0, ((M_limbs - 1) * ciL));\n\n        /* M = A1 + B0 * 2^224\n         * We know that only one limb of A1 will be non-zero and that it will be\n         * limb 0. We also know that B0 is the bottom 224 bits of A1 (which is\n         * then shifted up 224 bits), so, given M is currently A1 this turns\n         * into:\n         * M = M + (M << 224)\n         * As the single non-zero limb in B0 will be A1 limb 0 shifted up by 224\n         * bits, we can just move that into the right place, shifted up\n         * accordingly.*/\n        M[P224_WIDTH_MIN] = M[0] << (224 & (biL - 1));\n\n        /* X = A0 + (A1 + B0 * 2^224) */\n        (void) mbedtls_mpi_core_add(X, X, M, M_limbs);\n    }\n\n    ret = 0;\n\ncleanup:\n    mbedtls_free(M);\n    mbedtls_free(Q);\n\n    return ret;\n}\n#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) ||   \\\n    defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n\n/*\n * Fast quasi-reduction modulo P = 2^s - R,\n * with R about 33 bits, used by the Koblitz curves.\n *\n * Write X as A0 + 2^224 A1, return A0 + R * A1.\n */\n#define P_KOBLITZ_R     (8 / sizeof(mbedtls_mpi_uint))            // Limbs in R\n\nstatic inline int ecp_mod_koblitz(mbedtls_mpi_uint *X,\n                                  size_t X_limbs,\n                                  mbedtls_mpi_uint *R,\n                                  size_t bits)\n{\n    int ret = 0;\n\n    /* Determine if A1 is aligned to limb bitsize. If not then the used limbs\n     * of P, A0 and A1 must be set accordingly and there is a middle limb\n     * which is shared by A0 and A1 and need to handle accordingly.\n     */\n    size_t shift   = bits % biL;\n    size_t adjust  = (shift + biL - 1) / biL;\n    size_t P_limbs = bits / biL + adjust;\n\n    mbedtls_mpi_uint *A1 = mbedtls_calloc(P_limbs, ciL);\n    if (A1 == NULL) {\n        return MBEDTLS_ERR_ECP_ALLOC_FAILED;\n    }\n\n    /* Create a buffer to store the value of `R * A1` */\n    size_t R_limbs = P_KOBLITZ_R;\n    size_t M_limbs = P_limbs + R_limbs;\n    mbedtls_mpi_uint *M = mbedtls_calloc(M_limbs, ciL);\n    if (M == NULL) {\n        ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;\n        goto cleanup;\n    }\n\n    mbedtls_mpi_uint mask = 0;\n    if (adjust != 0) {\n        mask  = ((mbedtls_mpi_uint) 1 << shift) - 1;\n    }\n\n    /* Two passes are needed to reduce the value of `A0 + R * A1` and then\n     * we need an additional one to reduce the possible overflow during\n     * the addition.\n     */\n    for (size_t pass = 0; pass < 3; pass++) {\n        /* Copy A1 */\n        memcpy(A1, X + P_limbs - adjust, P_limbs * ciL);\n\n        /* Shift A1 to be aligned */\n        if (shift != 0) {\n            mbedtls_mpi_core_shift_r(A1, P_limbs, shift);\n        }\n\n        /* Zeroize the A1 part of the shared limb */\n        if (mask != 0) {\n            X[P_limbs - 1] &= mask;\n        }\n\n        /* X = A0\n         * Zeroize the A1 part of X to keep only the A0 part.\n         */\n        for (size_t i = P_limbs; i < X_limbs; i++) {\n            X[i] = 0;\n        }\n\n        /* X = A0 + R * A1 */\n        mbedtls_mpi_core_mul(M, A1, P_limbs, R, R_limbs);\n        (void) mbedtls_mpi_core_add(X, X, M, P_limbs + R_limbs);\n\n        /* Carry can not be generated since R is a 33-bit value and stored in\n         * 64 bits. The result value of the multiplication is at most\n         * P length + 33 bits in length and the result value of the addition\n         * is at most P length + 34 bits in length. So the result of the\n         * addition always fits in P length + 64 bits.\n         */\n    }\n\ncleanup:\n    mbedtls_free(M);\n    mbedtls_free(A1);\n\n    return ret;\n}\n\n#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) ||\n          MBEDTLS_ECP_DP_SECP224K1_ENABLED) ||\n          MBEDTLS_ECP_DP_SECP256K1_ENABLED) */\n\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)\n\n/*\n * Fast quasi-reduction modulo p192k1 = 2^192 - R,\n * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9\n */\nstatic int ecp_mod_p192k1(mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t expected_width = BITS_TO_LIMBS(192) * 2;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));\n    ret = mbedtls_ecp_mod_p192k1_raw(N->p, expected_width);\n\ncleanup:\n    return ret;\n}\n\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs)\n{\n    static mbedtls_mpi_uint Rp[] = {\n        MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x11, 0x00, 0x00,\n                                  0x01, 0x00, 0x00, 0x00)\n    };\n\n    if (X_limbs != BITS_TO_LIMBS(192) * 2) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    return ecp_mod_koblitz(X, X_limbs, Rp, 192);\n}\n\n#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)\n\n/*\n * Fast quasi-reduction modulo p224k1 = 2^224 - R,\n * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93\n */\nstatic int ecp_mod_p224k1(mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t expected_width = BITS_TO_LIMBS(224) * 2;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));\n    ret = mbedtls_ecp_mod_p224k1_raw(N->p, expected_width);\n\ncleanup:\n    return ret;\n}\n\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs)\n{\n    static mbedtls_mpi_uint Rp[] = {\n        MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x1A, 0x00, 0x00,\n                                  0x01, 0x00, 0x00, 0x00)\n    };\n\n    if (X_limbs !=  BITS_TO_LIMBS(224) * 2) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    return ecp_mod_koblitz(X, X_limbs, Rp, 224);\n}\n\n#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n\n/*\n * Fast quasi-reduction modulo p256k1 = 2^256 - R,\n * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1\n */\nstatic int ecp_mod_p256k1(mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t expected_width = BITS_TO_LIMBS(256) * 2;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));\n    ret = mbedtls_ecp_mod_p256k1_raw(N->p, expected_width);\n\ncleanup:\n    return ret;\n}\n\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs)\n{\n    static mbedtls_mpi_uint Rp[] = {\n        MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00,\n                                  0x01, 0x00, 0x00, 0x00)\n    };\n\n    if (X_limbs != BITS_TO_LIMBS(256) * 2) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    return ecp_mod_koblitz(X, X_limbs, Rp, 256);\n}\n\n#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */\n\n#if defined(MBEDTLS_TEST_HOOKS)\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N,\n                              const mbedtls_ecp_group_id id,\n                              const mbedtls_ecp_modulus_type ctype)\n{\n    mbedtls_mpi_modp_fn modp = NULL;\n    mbedtls_mpi_uint *p = NULL;\n    size_t p_limbs;\n\n    if (!(ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE || \\\n          ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_SCALAR)) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    switch (id) {\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP192R1:\n            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {\n#if defined(MBEDTLS_ECP_NIST_OPTIM)\n                modp = &mbedtls_ecp_mod_p192_raw;\n#endif\n                p = (mbedtls_mpi_uint *) secp192r1_p;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_p));\n            } else {\n                p = (mbedtls_mpi_uint *) secp192r1_n;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_n));\n            }\n            break;\n#endif\n\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP224R1:\n            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {\n#if defined(MBEDTLS_ECP_NIST_OPTIM)\n                modp = &mbedtls_ecp_mod_p224_raw;\n#endif\n                p = (mbedtls_mpi_uint *) secp224r1_p;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_p));\n            } else {\n                p = (mbedtls_mpi_uint *) secp224r1_n;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_n));\n            }\n            break;\n#endif\n\n#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP256R1:\n            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {\n#if defined(MBEDTLS_ECP_NIST_OPTIM)\n                modp = &mbedtls_ecp_mod_p256_raw;\n#endif\n                p = (mbedtls_mpi_uint *) secp256r1_p;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_p));\n            } else {\n                p = (mbedtls_mpi_uint *) secp256r1_n;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_n));\n            }\n            break;\n#endif\n\n#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP384R1:\n            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {\n#if defined(MBEDTLS_ECP_NIST_OPTIM)\n                modp = &mbedtls_ecp_mod_p384_raw;\n#endif\n                p = (mbedtls_mpi_uint *) secp384r1_p;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_p));\n            } else {\n                p = (mbedtls_mpi_uint *) secp384r1_n;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_n));\n            }\n            break;\n#endif\n\n#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP521R1:\n            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {\n#if defined(MBEDTLS_ECP_NIST_OPTIM)\n                modp = &mbedtls_ecp_mod_p521_raw;\n#endif\n                p = (mbedtls_mpi_uint *) secp521r1_p;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_p));\n            } else {\n                p = (mbedtls_mpi_uint *) secp521r1_n;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_n));\n            }\n            break;\n#endif\n\n#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)\n        case MBEDTLS_ECP_DP_BP256R1:\n            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {\n                p = (mbedtls_mpi_uint *) brainpoolP256r1_p;\n                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_p));\n            } else {\n                p = (mbedtls_mpi_uint *) brainpoolP256r1_n;\n                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_n));\n            }\n            break;\n#endif\n\n#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)\n        case MBEDTLS_ECP_DP_BP384R1:\n            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {\n                p = (mbedtls_mpi_uint *) brainpoolP384r1_p;\n                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_p));\n            } else {\n                p = (mbedtls_mpi_uint *) brainpoolP384r1_n;\n                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_n));\n            }\n            break;\n#endif\n\n#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)\n        case MBEDTLS_ECP_DP_BP512R1:\n            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {\n                p = (mbedtls_mpi_uint *) brainpoolP512r1_p;\n                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_p));\n            } else {\n                p = (mbedtls_mpi_uint *) brainpoolP512r1_n;\n                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_n));\n            }\n            break;\n#endif\n\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n        case MBEDTLS_ECP_DP_CURVE25519:\n            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {\n                modp = &mbedtls_ecp_mod_p255_raw;\n                p = (mbedtls_mpi_uint *) curve25519_p;\n                p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_p));\n            } else {\n                p = (mbedtls_mpi_uint *) curve25519_n;\n                p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_n));\n            }\n            break;\n#endif\n\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP192K1:\n            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {\n                modp = &mbedtls_ecp_mod_p192k1_raw;\n                p = (mbedtls_mpi_uint *) secp192k1_p;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_p));\n            } else {\n                p = (mbedtls_mpi_uint *) secp192k1_n;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_n));\n            }\n            break;\n#endif\n\n#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP224K1:\n            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {\n                modp = &mbedtls_ecp_mod_p224k1_raw;\n                p = (mbedtls_mpi_uint *) secp224k1_p;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_p));\n            } else {\n                p = (mbedtls_mpi_uint *) secp224k1_n;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_n));\n            }\n            break;\n#endif\n\n#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n        case MBEDTLS_ECP_DP_SECP256K1:\n            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {\n                modp = &mbedtls_ecp_mod_p256k1_raw;\n                p = (mbedtls_mpi_uint *) secp256k1_p;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_p));\n            } else {\n                p = (mbedtls_mpi_uint *) secp256k1_n;\n                p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_n));\n            }\n            break;\n#endif\n\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n        case MBEDTLS_ECP_DP_CURVE448:\n            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {\n                modp = &mbedtls_ecp_mod_p448_raw;\n                p = (mbedtls_mpi_uint *) curve448_p;\n                p_limbs = CHARS_TO_LIMBS(sizeof(curve448_p));\n            } else {\n                p = (mbedtls_mpi_uint *) curve448_n;\n                p_limbs = CHARS_TO_LIMBS(sizeof(curve448_n));\n            }\n            break;\n#endif\n\n        default:\n        case MBEDTLS_ECP_DP_NONE:\n            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    if (modp != NULL) {\n        if (mbedtls_mpi_mod_optred_modulus_setup(N, p, p_limbs, modp)) {\n            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n        }\n    } else {\n        if (mbedtls_mpi_mod_modulus_setup(N, p, p_limbs)) {\n            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n        }\n    }\n    return 0;\n}\n#endif /* MBEDTLS_TEST_HOOKS */\n\n#if defined(MBEDTLS_TEST_HOOKS)\n\nMBEDTLS_STATIC_TESTABLE\nmbedtls_ecp_variant mbedtls_ecp_get_variant(void)\n{\n    return MBEDTLS_ECP_VARIANT_WITH_MPI_UINT;\n}\n\n#endif /* MBEDTLS_TEST_HOOKS */\n\n#endif /* !MBEDTLS_ECP_ALT */\n#endif /* MBEDTLS_ECP_LIGHT */\n#endif /* MBEDTLS_ECP_WITH_MPI_UINT */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ecp_internal_alt.h",
    "content": "/**\n * \\file ecp_internal_alt.h\n *\n * \\brief Function declarations for alternative implementation of elliptic curve\n * point arithmetic.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n * References:\n *\n * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records.\n *     <http://cr.yp.to/ecdh/curve25519-20060209.pdf>\n *\n * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis\n *     for elliptic curve cryptosystems. In : Cryptographic Hardware and\n *     Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.\n *     <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>\n *\n * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to\n *     render ECC resistant against Side Channel Attacks. IACR Cryptology\n *     ePrint Archive, 2004, vol. 2004, p. 342.\n *     <http://eprint.iacr.org/2004/342.pdf>\n *\n * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters.\n *     <http://www.secg.org/sec2-v2.pdf>\n *\n * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic\n *     Curve Cryptography.\n *\n * [6] Digital Signature Standard (DSS), FIPS 186-4.\n *     <http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf>\n *\n * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer\n *     Security (TLS), RFC 4492.\n *     <https://tools.ietf.org/search/rfc4492>\n *\n * [8] <http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html>\n *\n * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory.\n *     Springer Science & Business Media, 1 Aug 2000\n */\n\n#ifndef MBEDTLS_ECP_INTERNAL_H\n#define MBEDTLS_ECP_INTERNAL_H\n\n#include \"mbedtls/build_info.h\"\n\n#if defined(MBEDTLS_ECP_INTERNAL_ALT)\n\n/**\n * \\brief           Indicate if the Elliptic Curve Point module extension can\n *                  handle the group.\n *\n * \\param grp       The pointer to the elliptic curve group that will be the\n *                  basis of the cryptographic computations.\n *\n * \\return          Non-zero if successful.\n */\nunsigned char mbedtls_internal_ecp_grp_capable(const mbedtls_ecp_group *grp);\n\n/**\n * \\brief           Initialise the Elliptic Curve Point module extension.\n *\n *                  If mbedtls_internal_ecp_grp_capable returns true for a\n *                  group, this function has to be able to initialise the\n *                  module for it.\n *\n *                  This module can be a driver to a crypto hardware\n *                  accelerator, for which this could be an initialise function.\n *\n * \\param grp       The pointer to the group the module needs to be\n *                  initialised for.\n *\n * \\return          0 if successful.\n */\nint mbedtls_internal_ecp_init(const mbedtls_ecp_group *grp);\n\n/**\n * \\brief           Frees and deallocates the Elliptic Curve Point module\n *                  extension.\n *\n * \\param grp       The pointer to the group the module was initialised for.\n */\nvoid mbedtls_internal_ecp_free(const mbedtls_ecp_group *grp);\n\n#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)\n\n#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)\n/**\n * \\brief           Randomize jacobian coordinates:\n *                  (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l.\n *\n * \\param grp       Pointer to the group representing the curve.\n *\n * \\param pt        The point on the curve to be randomised, given with Jacobian\n *                  coordinates.\n *\n * \\param f_rng     A function pointer to the random number generator.\n *\n * \\param p_rng     A pointer to the random number generator state.\n *\n * \\return          0 if successful.\n */\nint mbedtls_internal_ecp_randomize_jac(const mbedtls_ecp_group *grp,\n                                       mbedtls_ecp_point *pt, int (*f_rng)(void *,\n                                                                           unsigned char *,\n                                                                           size_t),\n                                       void *p_rng);\n#endif\n\n#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)\n/**\n * \\brief           Addition: R = P + Q, mixed affine-Jacobian coordinates.\n *\n *                  The coordinates of Q must be normalized (= affine),\n *                  but those of P don't need to. R is not normalized.\n *\n *                  This function is used only as a subrutine of\n *                  ecp_mul_comb().\n *\n *                  Special cases: (1) P or Q is zero, (2) R is zero,\n *                      (3) P == Q.\n *                  None of these cases can happen as intermediate step in\n *                  ecp_mul_comb():\n *                      - at each step, P, Q and R are multiples of the base\n *                      point, the factor being less than its order, so none of\n *                      them is zero;\n *                      - Q is an odd multiple of the base point, P an even\n *                      multiple, due to the choice of precomputed points in the\n *                      modified comb method.\n *                  So branches for these cases do not leak secret information.\n *\n *                  We accept Q->Z being unset (saving memory in tables) as\n *                  meaning 1.\n *\n *                  Cost in field operations if done by [5] 3.22:\n *                      1A := 8M + 3S\n *\n * \\param grp       Pointer to the group representing the curve.\n *\n * \\param R         Pointer to a point structure to hold the result.\n *\n * \\param P         Pointer to the first summand, given with Jacobian\n *                  coordinates\n *\n * \\param Q         Pointer to the second summand, given with affine\n *                  coordinates.\n *\n * \\return          0 if successful.\n */\nint mbedtls_internal_ecp_add_mixed(const mbedtls_ecp_group *grp,\n                                   mbedtls_ecp_point *R, const mbedtls_ecp_point *P,\n                                   const mbedtls_ecp_point *Q);\n#endif\n\n/**\n * \\brief           Point doubling R = 2 P, Jacobian coordinates.\n *\n *                  Cost:   1D := 3M + 4S    (A ==  0)\n *                          4M + 4S          (A == -3)\n *                          3M + 6S + 1a     otherwise\n *                  when the implementation is based on the \"dbl-1998-cmo-2\"\n *                  doubling formulas in [8] and standard optimizations are\n *                  applied when curve parameter A is one of { 0, -3 }.\n *\n * \\param grp       Pointer to the group representing the curve.\n *\n * \\param R         Pointer to a point structure to hold the result.\n *\n * \\param P         Pointer to the point that has to be doubled, given with\n *                  Jacobian coordinates.\n *\n * \\return          0 if successful.\n */\n#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)\nint mbedtls_internal_ecp_double_jac(const mbedtls_ecp_group *grp,\n                                    mbedtls_ecp_point *R, const mbedtls_ecp_point *P);\n#endif\n\n/**\n * \\brief           Normalize jacobian coordinates of an array of (pointers to)\n *                  points.\n *\n *                  Using Montgomery's trick to perform only one inversion mod P\n *                  the cost is:\n *                      1N(t) := 1I + (6t - 3)M + 1S\n *                  (See for example Algorithm 10.3.4. in [9])\n *\n *                  This function is used only as a subrutine of\n *                  ecp_mul_comb().\n *\n *                  Warning: fails (returning an error) if one of the points is\n *                  zero!\n *                  This should never happen, see choice of w in ecp_mul_comb().\n *\n * \\param grp       Pointer to the group representing the curve.\n *\n * \\param T         Array of pointers to the points to normalise.\n *\n * \\param t_len     Number of elements in the array.\n *\n * \\return          0 if successful,\n *                      an error if one of the points is zero.\n */\n#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)\nint mbedtls_internal_ecp_normalize_jac_many(const mbedtls_ecp_group *grp,\n                                            mbedtls_ecp_point *T[], size_t t_len);\n#endif\n\n/**\n * \\brief           Normalize jacobian coordinates so that Z == 0 || Z == 1.\n *\n *                  Cost in field operations if done by [5] 3.2.1:\n *                      1N := 1I + 3M + 1S\n *\n * \\param grp       Pointer to the group representing the curve.\n *\n * \\param pt        pointer to the point to be normalised. This is an\n *                  input/output parameter.\n *\n * \\return          0 if successful.\n */\n#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)\nint mbedtls_internal_ecp_normalize_jac(const mbedtls_ecp_group *grp,\n                                       mbedtls_ecp_point *pt);\n#endif\n\n#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */\n\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\n\n#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)\nint mbedtls_internal_ecp_double_add_mxz(const mbedtls_ecp_group *grp,\n                                        mbedtls_ecp_point *R,\n                                        mbedtls_ecp_point *S,\n                                        const mbedtls_ecp_point *P,\n                                        const mbedtls_ecp_point *Q,\n                                        const mbedtls_mpi *d);\n#endif\n\n/**\n * \\brief           Randomize projective x/z coordinates:\n *                      (X, Z) -> (l X, l Z) for random l\n *\n * \\param grp       pointer to the group representing the curve\n *\n * \\param P         the point on the curve to be randomised given with\n *                  projective coordinates. This is an input/output parameter.\n *\n * \\param f_rng     a function pointer to the random number generator\n *\n * \\param p_rng     a pointer to the random number generator state\n *\n * \\return          0 if successful\n */\n#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)\nint mbedtls_internal_ecp_randomize_mxz(const mbedtls_ecp_group *grp,\n                                       mbedtls_ecp_point *P, int (*f_rng)(void *,\n                                                                          unsigned char *,\n                                                                          size_t),\n                                       void *p_rng);\n#endif\n\n/**\n * \\brief           Normalize Montgomery x/z coordinates: X = X/Z, Z = 1.\n *\n * \\param grp       pointer to the group representing the curve\n *\n * \\param P         pointer to the point to be normalised. This is an\n *                  input/output parameter.\n *\n * \\return          0 if successful\n */\n#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)\nint mbedtls_internal_ecp_normalize_mxz(const mbedtls_ecp_group *grp,\n                                       mbedtls_ecp_point *P);\n#endif\n\n#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */\n\n#endif /* MBEDTLS_ECP_INTERNAL_ALT */\n\n#endif /* ecp_internal_alt.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ecp_invasive.h",
    "content": "/**\n * \\file ecp_invasive.h\n *\n * \\brief ECP module: interfaces for invasive testing only.\n *\n * The interfaces in this file are intended for testing purposes only.\n * They SHOULD NOT be made available in library integrations except when\n * building the library for testing.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_ECP_INVASIVE_H\n#define MBEDTLS_ECP_INVASIVE_H\n\n#include \"common.h\"\n#include \"mbedtls/bignum.h\"\n#include \"bignum_mod.h\"\n#include \"mbedtls/ecp.h\"\n\n/*\n * Curve modulus types\n */\ntypedef enum {\n    MBEDTLS_ECP_MOD_NONE = 0,\n    MBEDTLS_ECP_MOD_COORDINATE,\n    MBEDTLS_ECP_MOD_SCALAR\n} mbedtls_ecp_modulus_type;\n\ntypedef enum {\n    MBEDTLS_ECP_VARIANT_NONE = 0,\n    MBEDTLS_ECP_VARIANT_WITH_MPI_STRUCT,\n    MBEDTLS_ECP_VARIANT_WITH_MPI_UINT\n} mbedtls_ecp_variant;\n\n#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_LIGHT)\n\n/** Queries the ecp variant.\n *\n * \\return  The id of the ecp variant.\n */\nMBEDTLS_STATIC_TESTABLE\nmbedtls_ecp_variant mbedtls_ecp_get_variant(void);\n\n#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)\n/** Generate a private key on a Montgomery curve (Curve25519 or Curve448).\n *\n * This function implements key generation for the set of secret keys\n * specified in [Curve25519] p. 5 and in [Curve448]. The resulting value\n * has the lower bits masked but is not necessarily canonical.\n *\n * \\note            - [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf\n *                  - [RFC7748] https://tools.ietf.org/html/rfc7748\n *\n * \\p high_bit      The position of the high-order bit of the key to generate.\n *                  This is the bit-size of the key minus 1:\n *                  254 for Curve25519 or 447 for Curve448.\n * \\param d         The randomly generated key. This is a number of size\n *                  exactly \\p high_bit + 1 bits, with the least significant bits\n *                  masked as specified in [Curve25519] and in [RFC7748] §5.\n * \\param f_rng     The RNG function.\n * \\param p_rng     The RNG context to be passed to \\p f_rng.\n *\n * \\return          \\c 0 on success.\n * \\return          \\c MBEDTLS_ERR_ECP_xxx or MBEDTLS_ERR_MPI_xxx on failure.\n */\nint mbedtls_ecp_gen_privkey_mx(size_t high_bit,\n                               mbedtls_mpi *d,\n                               int (*f_rng)(void *, unsigned char *, size_t),\n                               void *p_rng);\n\n#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\n\n/** Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)\n *\n * This operation expects a 384 bit MPI and the result of the reduction\n * is a 192 bit MPI.\n *\n * \\param[in,out]   Np  The address of the MPI to be converted.\n *                      Must have twice as many limbs as the modulus.\n *                      Upon return this holds the reduced value. The bitlength\n *                      of the reduced value is the same as that of the modulus\n *                      (192 bits).\n * \\param[in]       Nn  The length of \\p Np in limbs.\n */\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn);\n\n#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)\n\n/** Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)\n *\n * \\param[in,out]   X       The address of the MPI to be converted.\n *                          Must have exact limb size that stores a 448-bit MPI\n *                          (double the bitlength of the modulus).\n *                          Upon return holds the reduced value which is\n *                          in range `0 <= X < 2 * N` (where N is the modulus).\n *                          The bitlength of the reduced value is the same as\n *                          that of the modulus (224 bits).\n * \\param[in]       X_limbs The length of \\p X in limbs.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \\p X_limbs is not the\n *                  limb size that sores a 448-bit MPI.\n */\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n\n#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)\n\n/** Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)\n *\n * \\param[in,out]   X       The address of the MPI to be converted.\n *                          Must have exact limb size that stores a 512-bit MPI\n *                          (double the bitlength of the modulus).\n *                          Upon return holds the reduced value which is\n *                          in range `0 <= X < 2 * N` (where N is the modulus).\n *                          The bitlength of the reduced value is the same as\n *                          that of the modulus (256 bits).\n * \\param[in]       X_limbs The length of \\p X in limbs.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \\p X_limbs is not the\n *                  limb size that sores a 512-bit MPI.\n */\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n\n#endif\n\n#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)\n\n/** Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5)\n *\n * \\param[in,out]   X       The address of the MPI to be converted.\n *                          Must have twice as many limbs as the modulus\n *                          (the modulus is 521 bits long). Upon return this\n *                          holds the reduced value. The reduced value is\n *                          in range `0 <= X < 2 * N` (where N is the modulus).\n *                          and its the bitlength is one plus the bitlength\n *                          of the modulus.\n * \\param[in]       X_limbs The length of \\p X in limbs.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \\p X_limbs does not have\n *                  twice as many limbs as the modulus.\n */\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n\n#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\n\n/** Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)\n *\n * \\param[in,out]   X       The address of the MPI to be converted.\n *                          Must have exact limb size that stores a 768-bit MPI\n *                          (double the bitlength of the modulus).\n *                          Upon return holds the reduced value which is\n *                          in range `0 <= X < 2 * N` (where N is the modulus).\n *                          The bitlength of the reduced value is the same as\n *                          that of the modulus (384 bits).\n * \\param[in]       X_limbs The length of \\p N in limbs.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \\p N_n does not have\n *                  twice as many limbs as the modulus.\n */\nMBEDTLS_STATIC_TESTABLE\nint  mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n\n#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)\n\n/** Fast quasi-reduction modulo p192k1 = 2^192 - R,\n * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9\n *\n * \\param[in,out]   X       The address of the MPI to be converted.\n *                          Must have exact limb size that stores a 384-bit MPI\n *                          (double the bitlength of the modulus).\n *                          Upon return holds the reduced value which is\n *                          in range `0 <= X < 2 * N` (where N is the modulus).\n *                          The bitlength of the reduced value is the same as\n *                          that of the modulus (192 bits).\n * \\param[in]       X_limbs The length of \\p X in limbs.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \\p X does not have\n *                  twice as many limbs as the modulus.\n * \\return          #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed.\n */\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n\n#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)\n\n/** Fast quasi-reduction modulo p224k1 = 2^224 - R,\n * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93\n *\n * \\param[in,out]   X       The address of the MPI to be converted.\n *                          Must have exact limb size that stores a 448-bit MPI\n *                          (double the bitlength of the modulus).\n *                          Upon return holds the reduced value which is\n *                          in range `0 <= X < 2 * N` (where N is the modulus).\n *                          The bitlength of the reduced value is the same as\n *                          that of the modulus (224 bits).\n * \\param[in]       X_limbs The length of \\p X in limbs.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \\p X does not have\n *                  twice as many limbs as the modulus.\n * \\return          #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed.\n */\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n\n#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n\n/** Fast quasi-reduction modulo p256k1 = 2^256 - R,\n * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1\n *\n * \\param[in,out]   X       The address of the MPI to be converted.\n *                          Must have exact limb size that stores a 512-bit MPI\n *                          (double the bitlength of the modulus).\n *                          Upon return holds the reduced value which is\n *                          in range `0 <= X < 2 * N` (where N is the modulus).\n *                          The bitlength of the reduced value is the same as\n *                          that of the modulus (256 bits).\n * \\param[in]       X_limbs The length of \\p X in limbs.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \\p X does not have\n *                  twice as many limbs as the modulus.\n * \\return          #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed.\n */\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n\n#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n\n/** Fast quasi-reduction modulo p255 = 2^255 - 19\n *\n * \\param[in,out]   X       The address of the MPI to be converted.\n *                          Must have exact limb size that stores a 510-bit MPI\n *                          (double the bitlength of the modulus).\n *                          Upon return holds the reduced value which is\n *                          in range `0 <= X < 2 * N` (where N is the modulus).\n * \\param[in]       X_limbs The length of \\p X in limbs.\n *\n * \\return          \\c 0 on success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \\p X does not have\n *                  twice as many limbs as the modulus.\n * \\return          #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed.\n */\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n\n#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */\n\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n\n/** Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1\n * Write X as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return A0 + A1 + B1 +\n * (B0 + B1) * 2^224.\n *\n * \\param[in,out]   X       The address of the MPI to be converted.\n *                          Must have exact limb size that stores a 896-bit MPI\n *                          (double the bitlength of the modulus). Upon return\n *                          holds the reduced value which is in range `0 <= X <\n *                          N` (where N is the modulus). The bitlength of the\n *                          reduced value is the same as that of the modulus\n *                          (448 bits).\n * \\param[in]       X_limbs The length of \\p X in limbs.\n *\n * \\return          \\c 0 on Success.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \\p X does not have\n *                  twice as many limbs as the modulus.\n * \\return          #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation\n *                  failed.\n */\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *X, size_t X_limbs);\n\n#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */\n\n/** Initialise a modulus with hard-coded const curve data.\n *\n * \\note            The caller is responsible for the \\p N modulus' memory.\n *                  mbedtls_mpi_mod_modulus_free(&N) should be invoked at the\n *                  end of its lifecycle.\n *\n * \\param[in,out] N The address of the modulus structure to populate.\n *                  Must be initialized.\n * \\param[in] id    The mbedtls_ecp_group_id for which to initialise the modulus.\n * \\param[in] ctype The mbedtls_ecp_modulus_type identifier for a coordinate modulus (P)\n *                  or a scalar modulus (N).\n *\n * \\return          \\c 0 if successful.\n * \\return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the given MPIs do not\n *                  have the correct number of limbs.\n *\n */\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N,\n                              const mbedtls_ecp_group_id id,\n                              const mbedtls_ecp_modulus_type ctype);\n\n#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_ECP_C */\n\n#endif /* MBEDTLS_ECP_INVASIVE_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/entropy.c",
    "content": "/*\n *  Entropy accumulator implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_ENTROPY_C)\n\n#include \"mbedtls/entropy.h\"\n#include \"entropy_poll.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_FS_IO)\n#include <stdio.h>\n#endif\n\n#include \"mbedtls/platform.h\"\n\n#define ENTROPY_MAX_LOOP    256     /**< Maximum amount to loop before error */\n\nvoid mbedtls_entropy_init(mbedtls_entropy_context *ctx)\n{\n    ctx->source_count = 0;\n    memset(ctx->source, 0, sizeof(ctx->source));\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_init(&ctx->mutex);\n#endif\n\n    ctx->accumulator_started = 0;\n    mbedtls_md_init(&ctx->accumulator);\n\n    /* Reminder: Update ENTROPY_HAVE_STRONG in the test files\n     *           when adding more strong entropy sources here. */\n\n#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)\n#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)\n    mbedtls_entropy_add_source(ctx, mbedtls_platform_entropy_poll, NULL,\n                               MBEDTLS_ENTROPY_MIN_PLATFORM,\n                               MBEDTLS_ENTROPY_SOURCE_STRONG);\n#endif\n#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)\n    mbedtls_entropy_add_source(ctx, mbedtls_hardware_poll, NULL,\n                               MBEDTLS_ENTROPY_MIN_HARDWARE,\n                               MBEDTLS_ENTROPY_SOURCE_STRONG);\n#endif\n#if defined(MBEDTLS_ENTROPY_NV_SEED)\n    mbedtls_entropy_add_source(ctx, mbedtls_nv_seed_poll, NULL,\n                               MBEDTLS_ENTROPY_BLOCK_SIZE,\n                               MBEDTLS_ENTROPY_SOURCE_STRONG);\n    ctx->initial_entropy_run = 0;\n#endif\n#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */\n}\n\nvoid mbedtls_entropy_free(mbedtls_entropy_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    /* If the context was already free, don't call free() again.\n     * This is important for mutexes which don't allow double-free. */\n    if (ctx->accumulator_started == -1) {\n        return;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_free(&ctx->mutex);\n#endif\n    mbedtls_md_free(&ctx->accumulator);\n#if defined(MBEDTLS_ENTROPY_NV_SEED)\n    ctx->initial_entropy_run = 0;\n#endif\n    ctx->source_count = 0;\n    mbedtls_platform_zeroize(ctx->source, sizeof(ctx->source));\n    ctx->accumulator_started = -1;\n}\n\nint mbedtls_entropy_add_source(mbedtls_entropy_context *ctx,\n                               mbedtls_entropy_f_source_ptr f_source, void *p_source,\n                               size_t threshold, int strong)\n{\n    int idx, ret = 0;\n\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {\n        return ret;\n    }\n#endif\n\n    idx = ctx->source_count;\n    if (idx >= MBEDTLS_ENTROPY_MAX_SOURCES) {\n        ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES;\n        goto exit;\n    }\n\n    ctx->source[idx].f_source  = f_source;\n    ctx->source[idx].p_source  = p_source;\n    ctx->source[idx].threshold = threshold;\n    ctx->source[idx].strong    = strong;\n\n    ctx->source_count++;\n\nexit:\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {\n        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n#endif\n\n    return ret;\n}\n\n/*\n * Entropy accumulator update\n */\nstatic int entropy_update(mbedtls_entropy_context *ctx, unsigned char source_id,\n                          const unsigned char *data, size_t len)\n{\n    unsigned char header[2];\n    unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE];\n    size_t use_len = len;\n    const unsigned char *p = data;\n    int ret = 0;\n\n    if (use_len > MBEDTLS_ENTROPY_BLOCK_SIZE) {\n        if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD),\n                              data, len, tmp)) != 0) {\n            goto cleanup;\n        }\n        p = tmp;\n        use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;\n    }\n\n    header[0] = source_id;\n    header[1] = use_len & 0xFF;\n\n    /*\n     * Start the accumulator if this has not already happened. Note that\n     * it is sufficient to start the accumulator here only because all calls to\n     * gather entropy eventually execute this code.\n     */\n    if (ctx->accumulator_started == 0) {\n        ret = mbedtls_md_setup(&ctx->accumulator,\n                               mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0);\n        if (ret != 0) {\n            goto cleanup;\n        }\n        ret = mbedtls_md_starts(&ctx->accumulator);\n        if (ret != 0) {\n            goto cleanup;\n        }\n        ctx->accumulator_started = 1;\n    }\n    if ((ret = mbedtls_md_update(&ctx->accumulator, header, 2)) != 0) {\n        goto cleanup;\n    }\n    ret = mbedtls_md_update(&ctx->accumulator, p, use_len);\n\ncleanup:\n    mbedtls_platform_zeroize(tmp, sizeof(tmp));\n\n    return ret;\n}\n\nint mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx,\n                                  const unsigned char *data, size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {\n        return ret;\n    }\n#endif\n\n    ret = entropy_update(ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len);\n\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {\n        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n#endif\n\n    return ret;\n}\n\n/*\n * Run through the different sources to add entropy to our accumulator\n */\nstatic int entropy_gather_internal(mbedtls_entropy_context *ctx)\n{\n    int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;\n    int i;\n    int have_one_strong = 0;\n    unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER];\n    size_t olen;\n\n    if (ctx->source_count == 0) {\n        return MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED;\n    }\n\n    /*\n     * Run through our entropy sources\n     */\n    for (i = 0; i < ctx->source_count; i++) {\n        if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) {\n            have_one_strong = 1;\n        }\n\n        olen = 0;\n        if ((ret = ctx->source[i].f_source(ctx->source[i].p_source,\n                                           buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen)) != 0) {\n            goto cleanup;\n        }\n\n        /*\n         * Add if we actually gathered something\n         */\n        if (olen > 0) {\n            if ((ret = entropy_update(ctx, (unsigned char) i,\n                                      buf, olen)) != 0) {\n                return ret;\n            }\n            ctx->source[i].size += olen;\n        }\n    }\n\n    if (have_one_strong == 0) {\n        ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE;\n    }\n\ncleanup:\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n\n    return ret;\n}\n\n/*\n * Thread-safe wrapper for entropy_gather_internal()\n */\nint mbedtls_entropy_gather(mbedtls_entropy_context *ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {\n        return ret;\n    }\n#endif\n\n    ret = entropy_gather_internal(ctx);\n\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {\n        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n#endif\n\n    return ret;\n}\n\nint mbedtls_entropy_func(void *data, unsigned char *output, size_t len)\n{\n    int ret, count = 0, i, thresholds_reached;\n    size_t strong_size;\n    mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;\n    unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];\n\n    if (len > MBEDTLS_ENTROPY_BLOCK_SIZE) {\n        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;\n    }\n\n#if defined(MBEDTLS_ENTROPY_NV_SEED)\n    /* Update the NV entropy seed before generating any entropy for outside\n     * use.\n     */\n    if (ctx->initial_entropy_run == 0) {\n        ctx->initial_entropy_run = 1;\n        if ((ret = mbedtls_entropy_update_nv_seed(ctx)) != 0) {\n            return ret;\n        }\n    }\n#endif\n\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {\n        return ret;\n    }\n#endif\n\n    /*\n     * Always gather extra entropy before a call\n     */\n    do {\n        if (count++ > ENTROPY_MAX_LOOP) {\n            ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;\n            goto exit;\n        }\n\n        if ((ret = entropy_gather_internal(ctx)) != 0) {\n            goto exit;\n        }\n\n        thresholds_reached = 1;\n        strong_size = 0;\n        for (i = 0; i < ctx->source_count; i++) {\n            if (ctx->source[i].size < ctx->source[i].threshold) {\n                thresholds_reached = 0;\n            }\n            if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) {\n                strong_size += ctx->source[i].size;\n            }\n        }\n    } while (!thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE);\n\n    memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);\n\n    /*\n     * Note that at this stage it is assumed that the accumulator was started\n     * in a previous call to entropy_update(). If this is not guaranteed, the\n     * code below will fail.\n     */\n    if ((ret = mbedtls_md_finish(&ctx->accumulator, buf)) != 0) {\n        goto exit;\n    }\n\n    /*\n     * Reset accumulator and counters and recycle existing entropy\n     */\n    mbedtls_md_free(&ctx->accumulator);\n    mbedtls_md_init(&ctx->accumulator);\n    ret = mbedtls_md_setup(&ctx->accumulator,\n                           mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0);\n    if (ret != 0) {\n        goto exit;\n    }\n    ret = mbedtls_md_starts(&ctx->accumulator);\n    if (ret != 0) {\n        goto exit;\n    }\n    if ((ret = mbedtls_md_update(&ctx->accumulator, buf,\n                                 MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {\n        goto exit;\n    }\n\n    /*\n     * Perform second hashing on entropy\n     */\n    if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD),\n                          buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf)) != 0) {\n        goto exit;\n    }\n\n    for (i = 0; i < ctx->source_count; i++) {\n        ctx->source[i].size = 0;\n    }\n\n    memcpy(output, buf, len);\n\n    ret = 0;\n\nexit:\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {\n        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n#endif\n\n    return ret;\n}\n\n#if defined(MBEDTLS_ENTROPY_NV_SEED)\nint mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx)\n{\n    int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;\n    unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];\n\n    /* Read new seed  and write it to NV */\n    if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {\n        return ret;\n    }\n\n    if (mbedtls_nv_seed_write(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) {\n        return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;\n    }\n\n    /* Manually update the remaining stream with a separator value to diverge */\n    memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);\n    ret = mbedtls_entropy_update_manual(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE);\n\n    return ret;\n}\n#endif /* MBEDTLS_ENTROPY_NV_SEED */\n\n#if defined(MBEDTLS_FS_IO)\nint mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *path)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    FILE *f = NULL;\n    unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];\n\n    if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {\n        ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;\n        goto exit;\n    }\n\n    if ((f = fopen(path, \"wb\")) == NULL) {\n        ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;\n        goto exit;\n    }\n\n    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */\n    mbedtls_setbuf(f, NULL);\n\n    if (fwrite(buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f) != MBEDTLS_ENTROPY_BLOCK_SIZE) {\n        ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;\n        goto exit;\n    }\n\n    ret = 0;\n\nexit:\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n\n    if (f != NULL) {\n        fclose(f);\n    }\n\n    return ret;\n}\n\nint mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *path)\n{\n    int ret = 0;\n    FILE *f;\n    size_t n;\n    unsigned char buf[MBEDTLS_ENTROPY_MAX_SEED_SIZE];\n\n    if ((f = fopen(path, \"rb\")) == NULL) {\n        return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;\n    }\n\n    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */\n    mbedtls_setbuf(f, NULL);\n\n    fseek(f, 0, SEEK_END);\n    n = (size_t) ftell(f);\n    fseek(f, 0, SEEK_SET);\n\n    if (n > MBEDTLS_ENTROPY_MAX_SEED_SIZE) {\n        n = MBEDTLS_ENTROPY_MAX_SEED_SIZE;\n    }\n\n    if (fread(buf, 1, n, f) != n) {\n        ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;\n    } else {\n        ret = mbedtls_entropy_update_manual(ctx, buf, n);\n    }\n\n    fclose(f);\n\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n\n    if (ret != 0) {\n        return ret;\n    }\n\n    return mbedtls_entropy_write_seed_file(ctx, path);\n}\n#endif /* MBEDTLS_FS_IO */\n\n#if defined(MBEDTLS_SELF_TEST)\n/*\n * Dummy source function\n */\nstatic int entropy_dummy_source(void *data, unsigned char *output,\n                                size_t len, size_t *olen)\n{\n    ((void) data);\n\n    memset(output, 0x2a, len);\n    *olen = len;\n\n    return 0;\n}\n\n#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)\n\nstatic int mbedtls_entropy_source_self_test_gather(unsigned char *buf, size_t buf_len)\n{\n    int ret = 0;\n    size_t entropy_len = 0;\n    size_t olen = 0;\n    size_t attempts = buf_len;\n\n    while (attempts > 0 && entropy_len < buf_len) {\n        if ((ret = mbedtls_hardware_poll(NULL, buf + entropy_len,\n                                         buf_len - entropy_len, &olen)) != 0) {\n            return ret;\n        }\n\n        entropy_len += olen;\n        attempts--;\n    }\n\n    if (entropy_len < buf_len) {\n        ret = 1;\n    }\n\n    return ret;\n}\n\n\nstatic int mbedtls_entropy_source_self_test_check_bits(const unsigned char *buf,\n                                                       size_t buf_len)\n{\n    unsigned char set = 0xFF;\n    unsigned char unset = 0x00;\n    size_t i;\n\n    for (i = 0; i < buf_len; i++) {\n        set &= buf[i];\n        unset |= buf[i];\n    }\n\n    return set == 0xFF || unset == 0x00;\n}\n\n/*\n * A test to ensure that the entropy sources are functioning correctly\n * and there is no obvious failure. The test performs the following checks:\n *  - The entropy source is not providing only 0s (all bits unset) or 1s (all\n *    bits set).\n *  - The entropy source is not providing values in a pattern. Because the\n *    hardware could be providing data in an arbitrary length, this check polls\n *    the hardware entropy source twice and compares the result to ensure they\n *    are not equal.\n *  - The error code returned by the entropy source is not an error.\n */\nint mbedtls_entropy_source_self_test(int verbose)\n{\n    int ret = 0;\n    unsigned char buf0[2 * sizeof(unsigned long long int)];\n    unsigned char buf1[2 * sizeof(unsigned long long int)];\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  ENTROPY_BIAS test: \");\n    }\n\n    memset(buf0, 0x00, sizeof(buf0));\n    memset(buf1, 0x00, sizeof(buf1));\n\n    if ((ret = mbedtls_entropy_source_self_test_gather(buf0, sizeof(buf0))) != 0) {\n        goto cleanup;\n    }\n    if ((ret = mbedtls_entropy_source_self_test_gather(buf1, sizeof(buf1))) != 0) {\n        goto cleanup;\n    }\n\n    /* Make sure that the returned values are not all 0 or 1 */\n    if ((ret = mbedtls_entropy_source_self_test_check_bits(buf0, sizeof(buf0))) != 0) {\n        goto cleanup;\n    }\n    if ((ret = mbedtls_entropy_source_self_test_check_bits(buf1, sizeof(buf1))) != 0) {\n        goto cleanup;\n    }\n\n    /* Make sure that the entropy source is not returning values in a\n     * pattern */\n    ret = memcmp(buf0, buf1, sizeof(buf0)) == 0;\n\ncleanup:\n    if (verbose != 0) {\n        if (ret != 0) {\n            mbedtls_printf(\"failed\\n\");\n        } else {\n            mbedtls_printf(\"passed\\n\");\n        }\n\n        mbedtls_printf(\"\\n\");\n    }\n\n    return ret != 0;\n}\n\n#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */\n\n/*\n * The actual entropy quality is hard to test, but we can at least\n * test that the functions don't cause errors and write the correct\n * amount of data to buffers.\n */\nint mbedtls_entropy_self_test(int verbose)\n{\n    int ret = 1;\n    mbedtls_entropy_context ctx;\n    unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };\n    unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };\n    size_t i, j;\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  ENTROPY test: \");\n    }\n\n    mbedtls_entropy_init(&ctx);\n\n    /* First do a gather to make sure we have default sources */\n    if ((ret = mbedtls_entropy_gather(&ctx)) != 0) {\n        goto cleanup;\n    }\n\n    ret = mbedtls_entropy_add_source(&ctx, entropy_dummy_source, NULL, 16,\n                                     MBEDTLS_ENTROPY_SOURCE_WEAK);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    if ((ret = mbedtls_entropy_update_manual(&ctx, buf, sizeof(buf))) != 0) {\n        goto cleanup;\n    }\n\n    /*\n     * To test that mbedtls_entropy_func writes correct number of bytes:\n     * - use the whole buffer and rely on ASan to detect overruns\n     * - collect entropy 8 times and OR the result in an accumulator:\n     *   any byte should then be 0 with probably 2^(-64), so requiring\n     *   each of the 32 or 64 bytes to be non-zero has a false failure rate\n     *   of at most 2^(-58) which is acceptable.\n     */\n    for (i = 0; i < 8; i++) {\n        if ((ret = mbedtls_entropy_func(&ctx, buf, sizeof(buf))) != 0) {\n            goto cleanup;\n        }\n\n        for (j = 0; j < sizeof(buf); j++) {\n            acc[j] |= buf[j];\n        }\n    }\n\n    for (j = 0; j < sizeof(buf); j++) {\n        if (acc[j] == 0) {\n            ret = 1;\n            goto cleanup;\n        }\n    }\n\n#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)\n    if ((ret = mbedtls_entropy_source_self_test(0)) != 0) {\n        goto cleanup;\n    }\n#endif\n\ncleanup:\n    mbedtls_entropy_free(&ctx);\n\n    if (verbose != 0) {\n        if (ret != 0) {\n            mbedtls_printf(\"failed\\n\");\n        } else {\n            mbedtls_printf(\"passed\\n\");\n        }\n\n        mbedtls_printf(\"\\n\");\n    }\n\n    return ret != 0;\n}\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_ENTROPY_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/entropy_poll.c",
    "content": "/*\n *  Platform-specific and custom entropy polling functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#if defined(__linux__) || defined(__midipix__)\n/* Ensure that syscall() is available even when compiling with -std=c99 */\n#if !defined(_GNU_SOURCE)\n#define _GNU_SOURCE\n#endif\n#endif\n\n#include \"common.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_ENTROPY_C)\n\n#include \"mbedtls/entropy.h\"\n#include \"entropy_poll.h\"\n#include \"mbedtls/error.h\"\n\n#if defined(MBEDTLS_TIMING_C)\n#include \"mbedtls/timing.h\"\n#endif\n#include \"mbedtls/platform.h\"\n\n#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)\n\n#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \\\n    !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \\\n    !defined(__HAIKU__) && !defined(__midipix__) && !defined(__MVS__)\n#error \\\n    \"Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in mbedtls_config.h\"\n#endif\n\n#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)\n\n// fallback to 3.3.0 implmentation, as 3.6.5 need a high version of Windows SDK\n#if !defined(_WIN32_WINNT)\n#define _WIN32_WINNT 0x0400\n#endif\n#include <windows.h>\n#include <wincrypt.h>\n\nint mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len,\n                           size_t *olen )\n{\n    HCRYPTPROV provider;\n    ((void) data);\n    *olen = 0;\n\n    if( CryptAcquireContext( &provider, NULL, NULL,\n                              PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )\n    {\n        return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );\n    }\n\n    if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE )\n    {\n        CryptReleaseContext( provider, 0 );\n        return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );\n    }\n\n    CryptReleaseContext( provider, 0 );\n    *olen = len;\n\n    return( 0 );\n}\n#else /* _WIN32 && !EFIX64 && !EFI32 */\n\n/*\n * Test for Linux getrandom() support.\n * Since there is no wrapper in the libc yet, use the generic syscall wrapper\n * available in GNU libc and compatible libc's (eg uClibc).\n */\n#if ((defined(__linux__) && defined(__GLIBC__)) || defined(__midipix__))\n#include <unistd.h>\n#include <sys/syscall.h>\n#if defined(SYS_getrandom)\n#define HAVE_GETRANDOM\n#include <errno.h>\n\nstatic int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags)\n{\n    /* MemSan cannot understand that the syscall writes to the buffer */\n#if defined(__has_feature)\n#if __has_feature(memory_sanitizer)\n    memset(buf, 0, buflen);\n#endif\n#endif\n    return (int) syscall(SYS_getrandom, buf, buflen, flags);\n}\n#endif /* SYS_getrandom */\n#endif /* __linux__ || __midipix__ */\n\n#if defined(__FreeBSD__) || defined(__DragonFly__)\n#include <sys/param.h>\n#if (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || \\\n    (defined(__DragonFly__) && __DragonFly_version >= 500700)\n#include <errno.h>\n#include <sys/random.h>\n#define HAVE_GETRANDOM\nstatic int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags)\n{\n    return (int) getrandom(buf, buflen, flags);\n}\n#endif /* (__FreeBSD__ && __FreeBSD_version >= 1200000) ||\n          (__DragonFly__ && __DragonFly_version >= 500700) */\n#endif /* __FreeBSD__ || __DragonFly__ */\n\n/*\n * Some BSD systems provide KERN_ARND.\n * This is equivalent to reading from /dev/urandom, only it doesn't require an\n * open file descriptor, and provides up to 256 bytes per call (basically the\n * same as getentropy(), but with a longer history).\n *\n * Documentation: https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7\n */\n#if (defined(__FreeBSD__) || defined(__NetBSD__)) && !defined(HAVE_GETRANDOM)\n#include <sys/param.h>\n#include <sys/sysctl.h>\n#if defined(KERN_ARND)\n#define HAVE_SYSCTL_ARND\n\nstatic int sysctl_arnd_wrapper(unsigned char *buf, size_t buflen)\n{\n    int name[2];\n    size_t len;\n\n    name[0] = CTL_KERN;\n    name[1] = KERN_ARND;\n\n    while (buflen > 0) {\n        len = buflen > 256 ? 256 : buflen;\n        if (sysctl(name, 2, buf, &len, NULL, 0) == -1) {\n            return -1;\n        }\n        buflen -= len;\n        buf += len;\n    }\n    return 0;\n}\n#endif /* KERN_ARND */\n#endif /* __FreeBSD__ || __NetBSD__ */\n\n#include <stdio.h>\n\nint mbedtls_platform_entropy_poll(void *data,\n                                  unsigned char *output, size_t len, size_t *olen)\n{\n    FILE *file;\n    size_t read_len;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    ((void) data);\n\n#if defined(HAVE_GETRANDOM)\n    ret = getrandom_wrapper(output, len, 0);\n    if (ret >= 0) {\n        *olen = (size_t) ret;\n        return 0;\n    } else if (errno != ENOSYS) {\n        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;\n    }\n    /* Fall through if the system call isn't known. */\n#else\n    ((void) ret);\n#endif /* HAVE_GETRANDOM */\n\n#if defined(HAVE_SYSCTL_ARND)\n    ((void) file);\n    ((void) read_len);\n    if (sysctl_arnd_wrapper(output, len) == -1) {\n        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;\n    }\n    *olen = len;\n    return 0;\n#else\n\n    *olen = 0;\n\n    file = fopen(\"/dev/urandom\", \"rb\");\n    if (file == NULL) {\n        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;\n    }\n\n    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */\n    mbedtls_setbuf(file, NULL);\n\n    read_len = fread(output, 1, len, file);\n    if (read_len != len) {\n        fclose(file);\n        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;\n    }\n\n    fclose(file);\n    *olen = len;\n\n    return 0;\n#endif /* HAVE_SYSCTL_ARND */\n}\n#endif /* _WIN32 && !EFIX64 && !EFI32 */\n#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */\n\n#if defined(MBEDTLS_ENTROPY_NV_SEED)\nint mbedtls_nv_seed_poll(void *data,\n                         unsigned char *output, size_t len, size_t *olen)\n{\n    unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];\n    size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;\n    ((void) data);\n\n    memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);\n\n    if (mbedtls_nv_seed_read(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) {\n        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;\n    }\n\n    if (len < use_len) {\n        use_len = len;\n    }\n\n    memcpy(output, buf, use_len);\n    *olen = use_len;\n\n    return 0;\n}\n#endif /* MBEDTLS_ENTROPY_NV_SEED */\n\n#endif /* MBEDTLS_ENTROPY_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/entropy_poll.h",
    "content": "/**\n * \\file entropy_poll.h\n *\n * \\brief Platform-specific and custom entropy polling functions\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_ENTROPY_POLL_H\n#define MBEDTLS_ENTROPY_POLL_H\n\n#include \"mbedtls/build_info.h\"\n\n#include <stddef.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n * Default thresholds for built-in sources, in bytes\n */\n#define MBEDTLS_ENTROPY_MIN_PLATFORM     32     /**< Minimum for platform source    */\n#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE)\n#define MBEDTLS_ENTROPY_MIN_HARDWARE     32     /**< Minimum for the hardware source */\n#endif\n\n#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)\n/**\n * \\brief           Platform-specific entropy poll callback\n */\nint mbedtls_platform_entropy_poll(void *data,\n                                  unsigned char *output, size_t len, size_t *olen);\n#endif\n\n#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)\n/**\n * \\brief           Entropy poll callback for a hardware source\n *\n * \\warning         This is not provided by Mbed TLS!\n *                  See \\c MBEDTLS_ENTROPY_HARDWARE_ALT in mbedtls_config.h.\n *\n * \\note            This must accept NULL as its first argument.\n */\nint mbedtls_hardware_poll(void *data,\n                          unsigned char *output, size_t len, size_t *olen);\n#endif\n\n#if defined(MBEDTLS_ENTROPY_NV_SEED)\n/**\n * \\brief           Entropy poll callback for a non-volatile seed file\n *\n * \\note            This must accept NULL as its first argument.\n */\nint mbedtls_nv_seed_poll(void *data,\n                         unsigned char *output, size_t len, size_t *olen);\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* entropy_poll.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/error.c",
    "content": "/*\n *  Error message information\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#include \"mbedtls/error.h\"\n\n#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)\n\n#if defined(MBEDTLS_ERROR_C)\n\n#include \"mbedtls/platform.h\"\n\n#include <stdio.h>\n#include <string.h>\n\n#if defined(MBEDTLS_AES_C)\n#include \"mbedtls/aes.h\"\n#endif\n\n#if defined(MBEDTLS_ARIA_C)\n#include \"mbedtls/aria.h\"\n#endif\n\n#if defined(MBEDTLS_ASN1_PARSE_C)\n#include \"mbedtls/asn1.h\"\n#endif\n\n#if defined(MBEDTLS_BASE64_C)\n#include \"mbedtls/base64.h\"\n#endif\n\n#if defined(MBEDTLS_BIGNUM_C)\n#include \"mbedtls/bignum.h\"\n#endif\n\n#if defined(MBEDTLS_CAMELLIA_C)\n#include \"mbedtls/camellia.h\"\n#endif\n\n#if defined(MBEDTLS_CCM_C)\n#include \"mbedtls/ccm.h\"\n#endif\n\n#if defined(MBEDTLS_CHACHA20_C)\n#include \"mbedtls/chacha20.h\"\n#endif\n\n#if defined(MBEDTLS_CHACHAPOLY_C)\n#include \"mbedtls/chachapoly.h\"\n#endif\n\n#if defined(MBEDTLS_CIPHER_C)\n#include \"mbedtls/cipher.h\"\n#endif\n\n#if defined(MBEDTLS_CTR_DRBG_C)\n#include \"mbedtls/ctr_drbg.h\"\n#endif\n\n#if defined(MBEDTLS_DES_C)\n#include \"mbedtls/des.h\"\n#endif\n\n#if defined(MBEDTLS_DHM_C)\n#include \"mbedtls/dhm.h\"\n#endif\n\n#if defined(MBEDTLS_ECP_C)\n#include \"mbedtls/ecp.h\"\n#endif\n\n#if defined(MBEDTLS_ENTROPY_C)\n#include \"mbedtls/entropy.h\"\n#endif\n\n#if defined(MBEDTLS_ERROR_C)\n#include \"mbedtls/error.h\"\n#endif\n\n#if defined(MBEDTLS_PLATFORM_C)\n#include \"mbedtls/platform.h\"\n#endif\n\n#if defined(MBEDTLS_GCM_C)\n#include \"mbedtls/gcm.h\"\n#endif\n\n#if defined(MBEDTLS_HKDF_C)\n#include \"mbedtls/hkdf.h\"\n#endif\n\n#if defined(MBEDTLS_HMAC_DRBG_C)\n#include \"mbedtls/hmac_drbg.h\"\n#endif\n\n#if defined(MBEDTLS_LMS_C)\n#include \"mbedtls/lms.h\"\n#endif\n\n#if defined(MBEDTLS_MD_C)\n#include \"mbedtls/md.h\"\n#endif\n\n#if defined(MBEDTLS_NET_C)\n#include \"mbedtls/net_sockets.h\"\n#endif\n\n#if defined(MBEDTLS_OID_C)\n#include \"mbedtls/oid.h\"\n#endif\n\n#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)\n#include \"mbedtls/pem.h\"\n#endif\n\n#if defined(MBEDTLS_PK_C)\n#include \"mbedtls/pk.h\"\n#endif\n\n#if defined(MBEDTLS_PKCS12_C)\n#include \"mbedtls/pkcs12.h\"\n#endif\n\n#if defined(MBEDTLS_PKCS5_C)\n#include \"mbedtls/pkcs5.h\"\n#endif\n\n#if defined(MBEDTLS_PKCS7_C)\n#include \"mbedtls/pkcs7.h\"\n#endif\n\n#if defined(MBEDTLS_POLY1305_C)\n#include \"mbedtls/poly1305.h\"\n#endif\n\n#if defined(MBEDTLS_RSA_C)\n#include \"mbedtls/rsa.h\"\n#endif\n\n#if defined(MBEDTLS_SHA1_C)\n#include \"mbedtls/sha1.h\"\n#endif\n\n#if defined(MBEDTLS_SHA256_C)\n#include \"mbedtls/sha256.h\"\n#endif\n\n#if defined(MBEDTLS_SHA3_C)\n#include \"mbedtls/sha3.h\"\n#endif\n\n#if defined(MBEDTLS_SHA512_C)\n#include \"mbedtls/sha512.h\"\n#endif\n\n#if defined(MBEDTLS_SSL_TLS_C)\n#include \"mbedtls/ssl.h\"\n#endif\n\n#if defined(MBEDTLS_THREADING_C)\n#include \"mbedtls/threading.h\"\n#endif\n\n#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)\n#include \"mbedtls/x509.h\"\n#endif\n\n\nconst char *mbedtls_high_level_strerr(int error_code)\n{\n    int high_level_error_code;\n\n    if (error_code < 0) {\n        error_code = -error_code;\n    }\n\n    /* Extract the high-level part from the error code. */\n    high_level_error_code = error_code & 0xFF80;\n\n    switch (high_level_error_code) {\n    /* Begin Auto-Generated Code. */\n    #if defined(MBEDTLS_CIPHER_C)\n        case -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE):\n            return( \"CIPHER - The selected feature is not available\" );\n        case -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA):\n            return( \"CIPHER - Bad input parameters\" );\n        case -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED):\n            return( \"CIPHER - Failed to allocate memory\" );\n        case -(MBEDTLS_ERR_CIPHER_INVALID_PADDING):\n            return( \"CIPHER - Input data contains invalid padding and is rejected\" );\n        case -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED):\n            return( \"CIPHER - Decryption of block requires a full block\" );\n        case -(MBEDTLS_ERR_CIPHER_AUTH_FAILED):\n            return( \"CIPHER - Authentication failed (for AEAD modes)\" );\n        case -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT):\n            return( \"CIPHER - The context is invalid. For example, because it was freed\" );\n#endif /* MBEDTLS_CIPHER_C */\n\n#if defined(MBEDTLS_DHM_C)\n        case -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA):\n            return( \"DHM - Bad input parameters\" );\n        case -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED):\n            return( \"DHM - Reading of the DHM parameters failed\" );\n        case -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED):\n            return( \"DHM - Making of the DHM parameters failed\" );\n        case -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED):\n            return( \"DHM - Reading of the public values failed\" );\n        case -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED):\n            return( \"DHM - Making of the public value failed\" );\n        case -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED):\n            return( \"DHM - Calculation of the DHM secret failed\" );\n        case -(MBEDTLS_ERR_DHM_INVALID_FORMAT):\n            return( \"DHM - The ASN.1 data is not formatted correctly\" );\n        case -(MBEDTLS_ERR_DHM_ALLOC_FAILED):\n            return( \"DHM - Allocation of memory failed\" );\n        case -(MBEDTLS_ERR_DHM_FILE_IO_ERROR):\n            return( \"DHM - Read or write of file failed\" );\n        case -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED):\n            return( \"DHM - Setting the modulus and generator failed\" );\n#endif /* MBEDTLS_DHM_C */\n\n#if defined(MBEDTLS_ECP_C)\n        case -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA):\n            return( \"ECP - Bad input parameters to function\" );\n        case -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL):\n            return( \"ECP - The buffer is too small to write to\" );\n        case -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE):\n            return( \"ECP - The requested feature is not available, for example, the requested curve is not supported\" );\n        case -(MBEDTLS_ERR_ECP_VERIFY_FAILED):\n            return( \"ECP - The signature is not valid\" );\n        case -(MBEDTLS_ERR_ECP_ALLOC_FAILED):\n            return( \"ECP - Memory allocation failed\" );\n        case -(MBEDTLS_ERR_ECP_RANDOM_FAILED):\n            return( \"ECP - Generation of random value, such as ephemeral key, failed\" );\n        case -(MBEDTLS_ERR_ECP_INVALID_KEY):\n            return( \"ECP - Invalid private or public key\" );\n        case -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH):\n            return( \"ECP - The buffer contains a valid signature followed by more data\" );\n        case -(MBEDTLS_ERR_ECP_IN_PROGRESS):\n            return( \"ECP - Operation in progress, call again with the same parameters to continue\" );\n#endif /* MBEDTLS_ECP_C */\n\n#if defined(MBEDTLS_MD_C)\n        case -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE):\n            return( \"MD - The selected feature is not available\" );\n        case -(MBEDTLS_ERR_MD_BAD_INPUT_DATA):\n            return( \"MD - Bad input parameters to function\" );\n        case -(MBEDTLS_ERR_MD_ALLOC_FAILED):\n            return( \"MD - Failed to allocate memory\" );\n        case -(MBEDTLS_ERR_MD_FILE_IO_ERROR):\n            return( \"MD - Opening or reading of file failed\" );\n#endif /* MBEDTLS_MD_C */\n\n#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)\n        case -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT):\n            return( \"PEM - No PEM header or footer found\" );\n        case -(MBEDTLS_ERR_PEM_INVALID_DATA):\n            return( \"PEM - PEM string is not as expected\" );\n        case -(MBEDTLS_ERR_PEM_ALLOC_FAILED):\n            return( \"PEM - Failed to allocate memory\" );\n        case -(MBEDTLS_ERR_PEM_INVALID_ENC_IV):\n            return( \"PEM - RSA IV is not in hex-format\" );\n        case -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG):\n            return( \"PEM - Unsupported key encryption algorithm\" );\n        case -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED):\n            return( \"PEM - Private key password can't be empty\" );\n        case -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH):\n            return( \"PEM - Given private key password does not allow for correct decryption\" );\n        case -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE):\n            return( \"PEM - Unavailable feature, e.g. hashing/encryption combination\" );\n        case -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA):\n            return( \"PEM - Bad input parameters to function\" );\n#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */\n\n#if defined(MBEDTLS_PK_C)\n        case -(MBEDTLS_ERR_PK_ALLOC_FAILED):\n            return( \"PK - Memory allocation failed\" );\n        case -(MBEDTLS_ERR_PK_TYPE_MISMATCH):\n            return( \"PK - Type mismatch, eg attempt to encrypt with an ECDSA key\" );\n        case -(MBEDTLS_ERR_PK_BAD_INPUT_DATA):\n            return( \"PK - Bad input parameters to function\" );\n        case -(MBEDTLS_ERR_PK_FILE_IO_ERROR):\n            return( \"PK - Read/write of file failed\" );\n        case -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION):\n            return( \"PK - Unsupported key version\" );\n        case -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT):\n            return( \"PK - Invalid key tag or value\" );\n        case -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG):\n            return( \"PK - Key algorithm is unsupported (only RSA and EC are supported)\" );\n        case -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED):\n            return( \"PK - Private key password can't be empty\" );\n        case -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH):\n            return( \"PK - Given private key password does not allow for correct decryption\" );\n        case -(MBEDTLS_ERR_PK_INVALID_PUBKEY):\n            return( \"PK - The pubkey tag or value is invalid (only RSA and EC are supported)\" );\n        case -(MBEDTLS_ERR_PK_INVALID_ALG):\n            return( \"PK - The algorithm tag or value is invalid\" );\n        case -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE):\n            return( \"PK - Elliptic curve is unsupported (only NIST curves are supported)\" );\n        case -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE):\n            return( \"PK - Unavailable feature, e.g. RSA disabled for RSA key\" );\n        case -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH):\n            return( \"PK - The buffer contains a valid signature followed by more data\" );\n        case -(MBEDTLS_ERR_PK_BUFFER_TOO_SMALL):\n            return( \"PK - The output buffer is too small\" );\n#endif /* MBEDTLS_PK_C */\n\n#if defined(MBEDTLS_PKCS12_C)\n        case -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA):\n            return( \"PKCS12 - Bad input parameters to function\" );\n        case -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE):\n            return( \"PKCS12 - Feature not available, e.g. unsupported encryption scheme\" );\n        case -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT):\n            return( \"PKCS12 - PBE ASN.1 data not as expected\" );\n        case -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH):\n            return( \"PKCS12 - Given private key password does not allow for correct decryption\" );\n#endif /* MBEDTLS_PKCS12_C */\n\n#if defined(MBEDTLS_PKCS5_C)\n        case -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA):\n            return( \"PKCS5 - Bad input parameters to function\" );\n        case -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT):\n            return( \"PKCS5 - Unexpected ASN.1 data\" );\n        case -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE):\n            return( \"PKCS5 - Requested encryption or digest alg not available\" );\n        case -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH):\n            return( \"PKCS5 - Given private key password does not allow for correct decryption\" );\n#endif /* MBEDTLS_PKCS5_C */\n\n#if defined(MBEDTLS_PKCS7_C)\n        case -(MBEDTLS_ERR_PKCS7_INVALID_FORMAT):\n            return( \"PKCS7 - The format is invalid, e.g. different type expected\" );\n        case -(MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE):\n            return( \"PKCS7 - Unavailable feature, e.g. anything other than signed data\" );\n        case -(MBEDTLS_ERR_PKCS7_INVALID_VERSION):\n            return( \"PKCS7 - The PKCS #7 version element is invalid or cannot be parsed\" );\n        case -(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO):\n            return( \"PKCS7 - The PKCS #7 content info is invalid or cannot be parsed\" );\n        case -(MBEDTLS_ERR_PKCS7_INVALID_ALG):\n            return( \"PKCS7 - The algorithm tag or value is invalid or cannot be parsed\" );\n        case -(MBEDTLS_ERR_PKCS7_INVALID_CERT):\n            return( \"PKCS7 - The certificate tag or value is invalid or cannot be parsed\" );\n        case -(MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE):\n            return( \"PKCS7 - Error parsing the signature\" );\n        case -(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO):\n            return( \"PKCS7 - Error parsing the signer's info\" );\n        case -(MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA):\n            return( \"PKCS7 - Input invalid\" );\n        case -(MBEDTLS_ERR_PKCS7_ALLOC_FAILED):\n            return( \"PKCS7 - Allocation of memory failed\" );\n        case -(MBEDTLS_ERR_PKCS7_VERIFY_FAIL):\n            return( \"PKCS7 - Verification Failed\" );\n        case -(MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID):\n            return( \"PKCS7 - The PKCS #7 date issued/expired dates are invalid\" );\n#endif /* MBEDTLS_PKCS7_C */\n\n#if defined(MBEDTLS_RSA_C)\n        case -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA):\n            return( \"RSA - Bad input parameters to function\" );\n        case -(MBEDTLS_ERR_RSA_INVALID_PADDING):\n            return( \"RSA - Input data contains invalid padding and is rejected\" );\n        case -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED):\n            return( \"RSA - Something failed during generation of a key\" );\n        case -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED):\n            return( \"RSA - Key failed to pass the validity check of the library\" );\n        case -(MBEDTLS_ERR_RSA_PUBLIC_FAILED):\n            return( \"RSA - The public key operation failed\" );\n        case -(MBEDTLS_ERR_RSA_PRIVATE_FAILED):\n            return( \"RSA - The private key operation failed\" );\n        case -(MBEDTLS_ERR_RSA_VERIFY_FAILED):\n            return( \"RSA - The PKCS#1 verification failed\" );\n        case -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE):\n            return( \"RSA - The output buffer for decryption is not large enough\" );\n        case -(MBEDTLS_ERR_RSA_RNG_FAILED):\n            return( \"RSA - The random generator failed to generate non-zeros\" );\n#endif /* MBEDTLS_RSA_C */\n\n#if defined(MBEDTLS_SSL_TLS_C)\n        case -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS):\n            return( \"SSL - A cryptographic operation is in progress. Try again later\" );\n        case -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE):\n            return( \"SSL - The requested feature is not available\" );\n        case -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA):\n            return( \"SSL - Bad input parameters to function\" );\n        case -(MBEDTLS_ERR_SSL_INVALID_MAC):\n            return( \"SSL - Verification of the message MAC failed\" );\n        case -(MBEDTLS_ERR_SSL_INVALID_RECORD):\n            return( \"SSL - An invalid SSL record was received\" );\n        case -(MBEDTLS_ERR_SSL_CONN_EOF):\n            return( \"SSL - The connection indicated an EOF\" );\n        case -(MBEDTLS_ERR_SSL_DECODE_ERROR):\n            return( \"SSL - A message could not be parsed due to a syntactic error\" );\n        case -(MBEDTLS_ERR_SSL_NO_RNG):\n            return( \"SSL - No RNG was provided to the SSL module\" );\n        case -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE):\n            return( \"SSL - No client certification received from the client, but required by the authentication mode\" );\n        case -(MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION):\n            return( \"SSL - Client received an extended server hello containing an unsupported extension\" );\n        case -(MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL):\n            return( \"SSL - No ALPN protocols supported that the client advertises\" );\n        case -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED):\n            return( \"SSL - The own private key or pre-shared key is not set, but needed\" );\n        case -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED):\n            return( \"SSL - No CA Chain is set, but required to operate\" );\n        case -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE):\n            return( \"SSL - An unexpected message was received from our peer\" );\n        case -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE):\n            return( \"SSL - A fatal alert message was received from our peer\" );\n        case -(MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME):\n            return( \"SSL - No server could be identified matching the client's SNI\" );\n        case -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY):\n            return( \"SSL - The peer notified us that the connection is going to be closed\" );\n        case -(MBEDTLS_ERR_SSL_BAD_CERTIFICATE):\n            return( \"SSL - Processing of the Certificate handshake message failed\" );\n        case -(MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET):\n            return( \"SSL - A TLS 1.3 NewSessionTicket message has been received\" );\n        case -(MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA):\n            return( \"SSL - Not possible to read early data\" );\n        case -(MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA):\n            return( \"SSL - * Early data has been received as part of an on-going handshake. This error code can be returned only on server side if and only if early data has been enabled by means of the mbedtls_ssl_conf_early_data() API. This error code can then be returned by mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or mbedtls_ssl_write() if early data has been received as part of the handshake sequence they triggered. To read the early data, call mbedtls_ssl_read_early_data()\" );\n        case -(MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA):\n            return( \"SSL - Not possible to write early data\" );\n        case -(MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND):\n            return( \"SSL - Cache entry not found\" );\n        case -(MBEDTLS_ERR_SSL_ALLOC_FAILED):\n            return( \"SSL - Memory allocation failed\" );\n        case -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED):\n            return( \"SSL - Hardware acceleration function returned with error\" );\n        case -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH):\n            return( \"SSL - Hardware acceleration function skipped / left alone data\" );\n        case -(MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION):\n            return( \"SSL - Handshake protocol not within min/max boundaries\" );\n        case -(MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE):\n            return( \"SSL - The handshake negotiation failed\" );\n        case -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED):\n            return( \"SSL - Session ticket has expired\" );\n        case -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH):\n            return( \"SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)\" );\n        case -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY):\n            return( \"SSL - Unknown identity received (eg, PSK identity)\" );\n        case -(MBEDTLS_ERR_SSL_INTERNAL_ERROR):\n            return( \"SSL - Internal error (eg, unexpected failure in lower-level module)\" );\n        case -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING):\n            return( \"SSL - A counter would wrap (eg, too many messages exchanged)\" );\n        case -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO):\n            return( \"SSL - Unexpected message at ServerHello in renegotiation\" );\n        case -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED):\n            return( \"SSL - DTLS client must retry for hello verification\" );\n        case -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL):\n            return( \"SSL - A buffer is too small to receive or write a message\" );\n        case -(MBEDTLS_ERR_SSL_WANT_READ):\n            return( \"SSL - No data of requested type currently available on underlying transport\" );\n        case -(MBEDTLS_ERR_SSL_WANT_WRITE):\n            return( \"SSL - Connection requires a write call\" );\n        case -(MBEDTLS_ERR_SSL_TIMEOUT):\n            return( \"SSL - The operation timed out\" );\n        case -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT):\n            return( \"SSL - The client initiated a reconnect from the same port\" );\n        case -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD):\n            return( \"SSL - Record header looks valid but is not expected\" );\n        case -(MBEDTLS_ERR_SSL_NON_FATAL):\n            return( \"SSL - The alert message received indicates a non-fatal error\" );\n        case -(MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER):\n            return( \"SSL - A field in a message was incorrect or inconsistent with other fields\" );\n        case -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING):\n            return( \"SSL - Internal-only message signaling that further message-processing should be done\" );\n        case -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS):\n            return( \"SSL - The asynchronous operation is not completed yet\" );\n        case -(MBEDTLS_ERR_SSL_EARLY_MESSAGE):\n            return( \"SSL - Internal-only message signaling that a message arrived early\" );\n        case -(MBEDTLS_ERR_SSL_UNEXPECTED_CID):\n            return( \"SSL - An encrypted DTLS-frame with an unexpected CID was received\" );\n        case -(MBEDTLS_ERR_SSL_VERSION_MISMATCH):\n            return( \"SSL - An operation failed due to an unexpected version or configuration\" );\n        case -(MBEDTLS_ERR_SSL_BAD_CONFIG):\n            return( \"SSL - Invalid value in SSL config\" );\n        case -(MBEDTLS_ERR_SSL_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME):\n            return( \"SSL - Attempt to verify a certificate without an expected hostname. This is usually insecure.  In TLS clients, when a client authenticates a server through its certificate, the client normally checks three things: - the certificate chain must be valid; - the chain must start from a trusted CA; - the certificate must cover the server name that is expected by the client.  Omitting any of these checks is generally insecure, and can allow a malicious server to impersonate a legitimate server.  The third check may be safely skipped in some unusual scenarios, such as networks where eavesdropping is a risk but not active attacks, or a private PKI where the client equally trusts all servers that are accredited by the root CA.  You should call mbedtls_ssl_set_hostname() with the expected server name before starting a TLS handshake on a client (unless the client is set up to only use PSK-based authentication, which does not rely on the host name). If you have determined that server name verification is not required for security in your scenario, call mbedtls_ssl_set_hostname() with \\\\p NULL as the server name.  This error is raised if all of the following conditions are met:  - A TLS client is configured with the authentication mode #MBEDTLS_SSL_VERIFY_REQUIRED (default). - Certificate authentication is enabled. - The client does not call mbedtls_ssl_set_hostname(). - The configuration option #MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME is not enabled\" );\n#endif /* MBEDTLS_SSL_TLS_C */\n\n#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)\n        case -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE):\n            return( \"X509 - Unavailable feature, e.g. RSA hashing/encryption combination\" );\n        case -(MBEDTLS_ERR_X509_UNKNOWN_OID):\n            return( \"X509 - Requested OID is unknown\" );\n        case -(MBEDTLS_ERR_X509_INVALID_FORMAT):\n            return( \"X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected\" );\n        case -(MBEDTLS_ERR_X509_INVALID_VERSION):\n            return( \"X509 - The CRT/CRL/CSR version element is invalid\" );\n        case -(MBEDTLS_ERR_X509_INVALID_SERIAL):\n            return( \"X509 - The serial tag or value is invalid\" );\n        case -(MBEDTLS_ERR_X509_INVALID_ALG):\n            return( \"X509 - The algorithm tag or value is invalid\" );\n        case -(MBEDTLS_ERR_X509_INVALID_NAME):\n            return( \"X509 - The name tag or value is invalid\" );\n        case -(MBEDTLS_ERR_X509_INVALID_DATE):\n            return( \"X509 - The date tag or value is invalid\" );\n        case -(MBEDTLS_ERR_X509_INVALID_SIGNATURE):\n            return( \"X509 - The signature tag or value invalid\" );\n        case -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS):\n            return( \"X509 - The extension tag or value is invalid\" );\n        case -(MBEDTLS_ERR_X509_UNKNOWN_VERSION):\n            return( \"X509 - CRT/CRL/CSR has an unsupported version number\" );\n        case -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG):\n            return( \"X509 - Signature algorithm (oid) is unsupported\" );\n        case -(MBEDTLS_ERR_X509_SIG_MISMATCH):\n            return( \"X509 - Signature algorithms do not match. (see \\\\c ::mbedtls_x509_crt sig_oid)\" );\n        case -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED):\n            return( \"X509 - Certificate verification failed, e.g. CRL, CA or signature check failed\" );\n        case -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT):\n            return( \"X509 - Format not recognized as DER or PEM\" );\n        case -(MBEDTLS_ERR_X509_BAD_INPUT_DATA):\n            return( \"X509 - Input invalid\" );\n        case -(MBEDTLS_ERR_X509_ALLOC_FAILED):\n            return( \"X509 - Allocation of memory failed\" );\n        case -(MBEDTLS_ERR_X509_FILE_IO_ERROR):\n            return( \"X509 - Read/write of file failed\" );\n        case -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL):\n            return( \"X509 - Destination buffer is too small\" );\n        case -(MBEDTLS_ERR_X509_FATAL_ERROR):\n            return( \"X509 - A fatal error occurred, eg the chain is too long or the vrfy callback failed\" );\n#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */\n        /* End Auto-Generated Code. */\n\n        default:\n            break;\n    }\n\n    return NULL;\n}\n\nconst char *mbedtls_low_level_strerr(int error_code)\n{\n    int low_level_error_code;\n\n    if (error_code < 0) {\n        error_code = -error_code;\n    }\n\n    /* Extract the low-level part from the error code. */\n    low_level_error_code = error_code & ~0xFF80;\n\n    switch (low_level_error_code) {\n    /* Begin Auto-Generated Code. */\n    #if defined(MBEDTLS_AES_C)\n        case -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH):\n            return( \"AES - Invalid key length\" );\n        case -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH):\n            return( \"AES - Invalid data input length\" );\n        case -(MBEDTLS_ERR_AES_BAD_INPUT_DATA):\n            return( \"AES - Invalid input data\" );\n#endif /* MBEDTLS_AES_C */\n\n#if defined(MBEDTLS_ARIA_C)\n        case -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA):\n            return( \"ARIA - Bad input data\" );\n        case -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH):\n            return( \"ARIA - Invalid data input length\" );\n#endif /* MBEDTLS_ARIA_C */\n\n#if defined(MBEDTLS_ASN1_PARSE_C)\n        case -(MBEDTLS_ERR_ASN1_OUT_OF_DATA):\n            return( \"ASN1 - Out of data when parsing an ASN1 data structure\" );\n        case -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG):\n            return( \"ASN1 - ASN1 tag was of an unexpected value\" );\n        case -(MBEDTLS_ERR_ASN1_INVALID_LENGTH):\n            return( \"ASN1 - Error when trying to determine the length or invalid length\" );\n        case -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH):\n            return( \"ASN1 - Actual length differs from expected length\" );\n        case -(MBEDTLS_ERR_ASN1_INVALID_DATA):\n            return( \"ASN1 - Data is invalid\" );\n        case -(MBEDTLS_ERR_ASN1_ALLOC_FAILED):\n            return( \"ASN1 - Memory allocation failed\" );\n        case -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL):\n            return( \"ASN1 - Buffer too small when writing ASN.1 data structure\" );\n#endif /* MBEDTLS_ASN1_PARSE_C */\n\n#if defined(MBEDTLS_BASE64_C)\n        case -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL):\n            return( \"BASE64 - Output buffer too small\" );\n        case -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER):\n            return( \"BASE64 - Invalid character in input\" );\n#endif /* MBEDTLS_BASE64_C */\n\n#if defined(MBEDTLS_BIGNUM_C)\n        case -(MBEDTLS_ERR_MPI_FILE_IO_ERROR):\n            return( \"BIGNUM - An error occurred while reading from or writing to a file\" );\n        case -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA):\n            return( \"BIGNUM - Bad input parameters to function\" );\n        case -(MBEDTLS_ERR_MPI_INVALID_CHARACTER):\n            return( \"BIGNUM - There is an invalid character in the digit string\" );\n        case -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL):\n            return( \"BIGNUM - The buffer is too small to write to\" );\n        case -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE):\n            return( \"BIGNUM - The input arguments are negative or result in illegal output\" );\n        case -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO):\n            return( \"BIGNUM - The input argument for division is zero, which is not allowed\" );\n        case -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE):\n            return( \"BIGNUM - The input arguments are not acceptable\" );\n        case -(MBEDTLS_ERR_MPI_ALLOC_FAILED):\n            return( \"BIGNUM - Memory allocation failed\" );\n#endif /* MBEDTLS_BIGNUM_C */\n\n#if defined(MBEDTLS_CAMELLIA_C)\n        case -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA):\n            return( \"CAMELLIA - Bad input data\" );\n        case -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH):\n            return( \"CAMELLIA - Invalid data input length\" );\n#endif /* MBEDTLS_CAMELLIA_C */\n\n#if defined(MBEDTLS_CCM_C)\n        case -(MBEDTLS_ERR_CCM_BAD_INPUT):\n            return( \"CCM - Bad input parameters to the function\" );\n        case -(MBEDTLS_ERR_CCM_AUTH_FAILED):\n            return( \"CCM - Authenticated decryption failed\" );\n#endif /* MBEDTLS_CCM_C */\n\n#if defined(MBEDTLS_CHACHA20_C)\n        case -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA):\n            return( \"CHACHA20 - Invalid input parameter(s)\" );\n#endif /* MBEDTLS_CHACHA20_C */\n\n#if defined(MBEDTLS_CHACHAPOLY_C)\n        case -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE):\n            return( \"CHACHAPOLY - The requested operation is not permitted in the current state\" );\n        case -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED):\n            return( \"CHACHAPOLY - Authenticated decryption failed: data was not authentic\" );\n#endif /* MBEDTLS_CHACHAPOLY_C */\n\n#if defined(MBEDTLS_CTR_DRBG_C)\n        case -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED):\n            return( \"CTR_DRBG - The entropy source failed\" );\n        case -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG):\n            return( \"CTR_DRBG - The requested random buffer length is too big\" );\n        case -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG):\n            return( \"CTR_DRBG - The input (entropy + additional data) is too large\" );\n        case -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR):\n            return( \"CTR_DRBG - Read or write error in file\" );\n#endif /* MBEDTLS_CTR_DRBG_C */\n\n#if defined(MBEDTLS_DES_C)\n        case -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH):\n            return( \"DES - The data input has an invalid length\" );\n#endif /* MBEDTLS_DES_C */\n\n#if defined(MBEDTLS_ENTROPY_C)\n        case -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED):\n            return( \"ENTROPY - Critical entropy source failure\" );\n        case -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES):\n            return( \"ENTROPY - No more sources can be added\" );\n        case -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED):\n            return( \"ENTROPY - No sources have been added to poll\" );\n        case -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE):\n            return( \"ENTROPY - No strong sources have been added to poll\" );\n        case -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR):\n            return( \"ENTROPY - Read/write error in file\" );\n#endif /* MBEDTLS_ENTROPY_C */\n\n#if defined(MBEDTLS_ERROR_C)\n        case -(MBEDTLS_ERR_ERROR_GENERIC_ERROR):\n            return( \"ERROR - Generic error\" );\n        case -(MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED):\n            return( \"ERROR - This is a bug in the library\" );\n#endif /* MBEDTLS_ERROR_C */\n\n#if defined(MBEDTLS_PLATFORM_C)\n        case -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED):\n            return( \"PLATFORM - Hardware accelerator failed\" );\n        case -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED):\n            return( \"PLATFORM - The requested feature is not supported by the platform\" );\n#endif /* MBEDTLS_PLATFORM_C */\n\n#if defined(MBEDTLS_GCM_C)\n        case -(MBEDTLS_ERR_GCM_AUTH_FAILED):\n            return( \"GCM - Authenticated decryption failed\" );\n        case -(MBEDTLS_ERR_GCM_BAD_INPUT):\n            return( \"GCM - Bad input parameters to function\" );\n        case -(MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL):\n            return( \"GCM - An output buffer is too small\" );\n#endif /* MBEDTLS_GCM_C */\n\n#if defined(MBEDTLS_HKDF_C)\n        case -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA):\n            return( \"HKDF - Bad input parameters to function\" );\n#endif /* MBEDTLS_HKDF_C */\n\n#if defined(MBEDTLS_HMAC_DRBG_C)\n        case -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG):\n            return( \"HMAC_DRBG - Too many random requested in single call\" );\n        case -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG):\n            return( \"HMAC_DRBG - Input too large (Entropy + additional)\" );\n        case -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR):\n            return( \"HMAC_DRBG - Read/write error in file\" );\n        case -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED):\n            return( \"HMAC_DRBG - The entropy source failed\" );\n#endif /* MBEDTLS_HMAC_DRBG_C */\n\n#if defined(MBEDTLS_LMS_C)\n        case -(MBEDTLS_ERR_LMS_BAD_INPUT_DATA):\n            return( \"LMS - Bad data has been input to an LMS function\" );\n        case -(MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS):\n            return( \"LMS - Specified LMS key has utilised all of its private keys\" );\n        case -(MBEDTLS_ERR_LMS_VERIFY_FAILED):\n            return( \"LMS - LMS signature verification failed\" );\n        case -(MBEDTLS_ERR_LMS_ALLOC_FAILED):\n            return( \"LMS - LMS failed to allocate space for a private key\" );\n        case -(MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL):\n            return( \"LMS - Input/output buffer is too small to contain requited data\" );\n#endif /* MBEDTLS_LMS_C */\n\n#if defined(MBEDTLS_NET_C)\n        case -(MBEDTLS_ERR_NET_SOCKET_FAILED):\n            return( \"NET - Failed to open a socket\" );\n        case -(MBEDTLS_ERR_NET_CONNECT_FAILED):\n            return( \"NET - The connection to the given server / port failed\" );\n        case -(MBEDTLS_ERR_NET_BIND_FAILED):\n            return( \"NET - Binding of the socket failed\" );\n        case -(MBEDTLS_ERR_NET_LISTEN_FAILED):\n            return( \"NET - Could not listen on the socket\" );\n        case -(MBEDTLS_ERR_NET_ACCEPT_FAILED):\n            return( \"NET - Could not accept the incoming connection\" );\n        case -(MBEDTLS_ERR_NET_RECV_FAILED):\n            return( \"NET - Reading information from the socket failed\" );\n        case -(MBEDTLS_ERR_NET_SEND_FAILED):\n            return( \"NET - Sending information through the socket failed\" );\n        case -(MBEDTLS_ERR_NET_CONN_RESET):\n            return( \"NET - Connection was reset by peer\" );\n        case -(MBEDTLS_ERR_NET_UNKNOWN_HOST):\n            return( \"NET - Failed to get an IP address for the given hostname\" );\n        case -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL):\n            return( \"NET - Buffer is too small to hold the data\" );\n        case -(MBEDTLS_ERR_NET_INVALID_CONTEXT):\n            return( \"NET - The context is invalid, eg because it was free()ed\" );\n        case -(MBEDTLS_ERR_NET_POLL_FAILED):\n            return( \"NET - Polling the net context failed\" );\n        case -(MBEDTLS_ERR_NET_BAD_INPUT_DATA):\n            return( \"NET - Input invalid\" );\n#endif /* MBEDTLS_NET_C */\n\n#if defined(MBEDTLS_OID_C)\n        case -(MBEDTLS_ERR_OID_NOT_FOUND):\n            return( \"OID - OID is not found\" );\n        case -(MBEDTLS_ERR_OID_BUF_TOO_SMALL):\n            return( \"OID - output buffer is too small\" );\n#endif /* MBEDTLS_OID_C */\n\n#if defined(MBEDTLS_POLY1305_C)\n        case -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA):\n            return( \"POLY1305 - Invalid input parameter(s)\" );\n#endif /* MBEDTLS_POLY1305_C */\n\n#if defined(MBEDTLS_SHA1_C)\n        case -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA):\n            return( \"SHA1 - SHA-1 input data was malformed\" );\n#endif /* MBEDTLS_SHA1_C */\n\n#if defined(MBEDTLS_SHA256_C)\n        case -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA):\n            return( \"SHA256 - SHA-256 input data was malformed\" );\n#endif /* MBEDTLS_SHA256_C */\n\n#if defined(MBEDTLS_SHA3_C)\n        case -(MBEDTLS_ERR_SHA3_BAD_INPUT_DATA):\n            return( \"SHA3 - SHA-3 input data was malformed\" );\n#endif /* MBEDTLS_SHA3_C */\n\n#if defined(MBEDTLS_SHA512_C)\n        case -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA):\n            return( \"SHA512 - SHA-512 input data was malformed\" );\n#endif /* MBEDTLS_SHA512_C */\n\n#if defined(MBEDTLS_THREADING_C)\n        case -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA):\n            return( \"THREADING - Bad input parameters to function\" );\n        case -(MBEDTLS_ERR_THREADING_MUTEX_ERROR):\n            return( \"THREADING - Locking / unlocking / free failed with error code\" );\n#endif /* MBEDTLS_THREADING_C */\n        /* End Auto-Generated Code. */\n\n        default:\n            break;\n    }\n\n    return NULL;\n}\n\nvoid mbedtls_strerror(int ret, char *buf, size_t buflen)\n{\n    size_t len;\n    int use_ret;\n    const char *high_level_error_description = NULL;\n    const char *low_level_error_description = NULL;\n\n    if (buflen == 0) {\n        return;\n    }\n\n    memset(buf, 0x00, buflen);\n\n    if (ret < 0) {\n        ret = -ret;\n    }\n\n    if (ret & 0xFF80) {\n        use_ret = ret & 0xFF80;\n\n        // Translate high level error code.\n        high_level_error_description = mbedtls_high_level_strerr(ret);\n\n        if (high_level_error_description == NULL) {\n            mbedtls_snprintf(buf, buflen, \"UNKNOWN ERROR CODE (%04X)\", (unsigned int) use_ret);\n        } else {\n            mbedtls_snprintf(buf, buflen, \"%s\", high_level_error_description);\n        }\n\n#if defined(MBEDTLS_SSL_TLS_C)\n        // Early return in case of a fatal error - do not try to translate low\n        // level code.\n        if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) {\n            return;\n        }\n#endif /* MBEDTLS_SSL_TLS_C */\n    }\n\n    use_ret = ret & ~0xFF80;\n\n    if (use_ret == 0) {\n        return;\n    }\n\n    // If high level code is present, make a concatenation between both\n    // error strings.\n    //\n    len = strlen(buf);\n\n    if (len > 0) {\n        if (buflen - len < 5) {\n            return;\n        }\n\n        mbedtls_snprintf(buf + len, buflen - len, \" : \");\n\n        buf += len + 3;\n        buflen -= len + 3;\n    }\n\n    // Translate low level error code.\n    low_level_error_description = mbedtls_low_level_strerr(ret);\n\n    if (low_level_error_description == NULL) {\n        mbedtls_snprintf(buf, buflen, \"UNKNOWN ERROR CODE (%04X)\", (unsigned int) use_ret);\n    } else {\n        mbedtls_snprintf(buf, buflen, \"%s\", low_level_error_description);\n    }\n}\n\n#else /* MBEDTLS_ERROR_C */\n\n/*\n * Provide a dummy implementation when MBEDTLS_ERROR_C is not defined\n */\nvoid mbedtls_strerror(int ret, char *buf, size_t buflen)\n{\n    ((void) ret);\n\n    if (buflen > 0) {\n        buf[0] = '\\0';\n    }\n}\n\n#endif /* MBEDTLS_ERROR_C */\n\n#endif /* MBEDTLS_ERROR_C || MBEDTLS_ERROR_STRERROR_DUMMY */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/gcm.c",
    "content": "/*\n *  NIST SP800-38D compliant GCM implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf\n *\n * See also:\n * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf\n *\n * We use the algorithm described as Shoup's method with 4-bit tables in\n * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_GCM_C)\n\n#include \"mbedtls/gcm.h\"\n#include \"mbedtls/platform.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/constant_time.h\"\n\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n#include \"block_cipher_internal.h\"\n#endif\n\n#include <string.h>\n\n#if defined(MBEDTLS_AESNI_C)\n#include \"aesni.h\"\n#endif\n\n#if defined(MBEDTLS_AESCE_C)\n#include \"aesce.h\"\n#endif\n\n#if !defined(MBEDTLS_GCM_ALT)\n\n/* Used to select the acceleration mechanism */\n#define MBEDTLS_GCM_ACC_SMALLTABLE  0\n#define MBEDTLS_GCM_ACC_LARGETABLE  1\n#define MBEDTLS_GCM_ACC_AESNI       2\n#define MBEDTLS_GCM_ACC_AESCE       3\n\n/*\n * Initialize a context\n */\nvoid mbedtls_gcm_init(mbedtls_gcm_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_gcm_context));\n}\n\nstatic inline void gcm_set_acceleration(mbedtls_gcm_context *ctx)\n{\n#if defined(MBEDTLS_GCM_LARGE_TABLE)\n    ctx->acceleration = MBEDTLS_GCM_ACC_LARGETABLE;\n#else\n    ctx->acceleration = MBEDTLS_GCM_ACC_SMALLTABLE;\n#endif\n\n#if defined(MBEDTLS_AESNI_HAVE_CODE)\n    /* With CLMUL support, we need only h, not the rest of the table */\n    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {\n        ctx->acceleration = MBEDTLS_GCM_ACC_AESNI;\n    }\n#endif\n\n#if defined(MBEDTLS_AESCE_HAVE_CODE)\n    if (MBEDTLS_AESCE_HAS_SUPPORT()) {\n        ctx->acceleration = MBEDTLS_GCM_ACC_AESCE;\n    }\n#endif\n}\n\nstatic inline void gcm_gen_table_rightshift(uint64_t dst[2], const uint64_t src[2])\n{\n    uint8_t *u8Dst = (uint8_t *) dst;\n    uint8_t *u8Src = (uint8_t *) src;\n\n    MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[1], 0) >> 1, &dst[1], 0);\n    u8Dst[8] |= (u8Src[7] & 0x01) << 7;\n    MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[0], 0) >> 1, &dst[0], 0);\n    u8Dst[0] ^= (u8Src[15] & 0x01) ? 0xE1 : 0;\n}\n\n/*\n * Precompute small multiples of H, that is set\n *      HH[i] || HL[i] = H times i,\n * where i is seen as a field element as in [MGV], ie high-order bits\n * correspond to low powers of P. The result is stored in the same way, that\n * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL\n * corresponds to P^127.\n */\nstatic int gcm_gen_table(mbedtls_gcm_context *ctx)\n{\n    int ret, i, j;\n    uint64_t u64h[2] = { 0 };\n    uint8_t *h = (uint8_t *) u64h;\n\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n    ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, h, h);\n#else\n    size_t olen = 0;\n    ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen);\n#endif\n    if (ret != 0) {\n        return ret;\n    }\n\n    gcm_set_acceleration(ctx);\n\n    /* MBEDTLS_GCM_HTABLE_SIZE/2 = 1000 corresponds to 1 in GF(2^128) */\n    ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][0] = u64h[0];\n    ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][1] = u64h[1];\n\n    switch (ctx->acceleration) {\n#if defined(MBEDTLS_AESNI_HAVE_CODE)\n        case MBEDTLS_GCM_ACC_AESNI:\n            return 0;\n#endif\n\n#if defined(MBEDTLS_AESCE_HAVE_CODE)\n        case MBEDTLS_GCM_ACC_AESCE:\n            return 0;\n#endif\n\n        default:\n            /* 0 corresponds to 0 in GF(2^128) */\n            ctx->H[0][0] = 0;\n            ctx->H[0][1] = 0;\n\n            for (i = MBEDTLS_GCM_HTABLE_SIZE/4; i > 0; i >>= 1) {\n                gcm_gen_table_rightshift(ctx->H[i], ctx->H[i*2]);\n            }\n\n#if !defined(MBEDTLS_GCM_LARGE_TABLE)\n            /* pack elements of H as 64-bits ints, big-endian */\n            for (i = MBEDTLS_GCM_HTABLE_SIZE/2; i > 0; i >>= 1) {\n                MBEDTLS_PUT_UINT64_BE(ctx->H[i][0], &ctx->H[i][0], 0);\n                MBEDTLS_PUT_UINT64_BE(ctx->H[i][1], &ctx->H[i][1], 0);\n            }\n#endif\n\n            for (i = 2; i < MBEDTLS_GCM_HTABLE_SIZE; i <<= 1) {\n                for (j = 1; j < i; j++) {\n                    mbedtls_xor_no_simd((unsigned char *) ctx->H[i+j],\n                                        (unsigned char *) ctx->H[i],\n                                        (unsigned char *) ctx->H[j],\n                                        16);\n                }\n            }\n    }\n\n    return 0;\n}\n\nint mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,\n                       mbedtls_cipher_id_t cipher,\n                       const unsigned char *key,\n                       unsigned int keybits)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (keybits != 128 && keybits != 192 && keybits != 256) {\n        return MBEDTLS_ERR_GCM_BAD_INPUT;\n    }\n\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n    mbedtls_block_cipher_free(&ctx->block_cipher_ctx);\n\n    if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) {\n        return ret;\n    }\n#else\n    const mbedtls_cipher_info_t *cipher_info;\n\n    cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,\n                                                  MBEDTLS_MODE_ECB);\n    if (cipher_info == NULL) {\n        return MBEDTLS_ERR_GCM_BAD_INPUT;\n    }\n\n    if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {\n        return MBEDTLS_ERR_GCM_BAD_INPUT;\n    }\n\n    mbedtls_cipher_free(&ctx->cipher_ctx);\n\n    if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,\n                                     MBEDTLS_ENCRYPT)) != 0) {\n        return ret;\n    }\n#endif\n\n    if ((ret = gcm_gen_table(ctx)) != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\n#if defined(MBEDTLS_GCM_LARGE_TABLE)\nstatic const uint16_t last8[256] = {\n    0x0000, 0xc201, 0x8403, 0x4602, 0x0807, 0xca06, 0x8c04, 0x4e05,\n    0x100e, 0xd20f, 0x940d, 0x560c, 0x1809, 0xda08, 0x9c0a, 0x5e0b,\n    0x201c, 0xe21d, 0xa41f, 0x661e, 0x281b, 0xea1a, 0xac18, 0x6e19,\n    0x3012, 0xf213, 0xb411, 0x7610, 0x3815, 0xfa14, 0xbc16, 0x7e17,\n    0x4038, 0x8239, 0xc43b, 0x063a, 0x483f, 0x8a3e, 0xcc3c, 0x0e3d,\n    0x5036, 0x9237, 0xd435, 0x1634, 0x5831, 0x9a30, 0xdc32, 0x1e33,\n    0x6024, 0xa225, 0xe427, 0x2626, 0x6823, 0xaa22, 0xec20, 0x2e21,\n    0x702a, 0xb22b, 0xf429, 0x3628, 0x782d, 0xba2c, 0xfc2e, 0x3e2f,\n    0x8070, 0x4271, 0x0473, 0xc672, 0x8877, 0x4a76, 0x0c74, 0xce75,\n    0x907e, 0x527f, 0x147d, 0xd67c, 0x9879, 0x5a78, 0x1c7a, 0xde7b,\n    0xa06c, 0x626d, 0x246f, 0xe66e, 0xa86b, 0x6a6a, 0x2c68, 0xee69,\n    0xb062, 0x7263, 0x3461, 0xf660, 0xb865, 0x7a64, 0x3c66, 0xfe67,\n    0xc048, 0x0249, 0x444b, 0x864a, 0xc84f, 0x0a4e, 0x4c4c, 0x8e4d,\n    0xd046, 0x1247, 0x5445, 0x9644, 0xd841, 0x1a40, 0x5c42, 0x9e43,\n    0xe054, 0x2255, 0x6457, 0xa656, 0xe853, 0x2a52, 0x6c50, 0xae51,\n    0xf05a, 0x325b, 0x7459, 0xb658, 0xf85d, 0x3a5c, 0x7c5e, 0xbe5f,\n    0x00e1, 0xc2e0, 0x84e2, 0x46e3, 0x08e6, 0xcae7, 0x8ce5, 0x4ee4,\n    0x10ef, 0xd2ee, 0x94ec, 0x56ed, 0x18e8, 0xdae9, 0x9ceb, 0x5eea,\n    0x20fd, 0xe2fc, 0xa4fe, 0x66ff, 0x28fa, 0xeafb, 0xacf9, 0x6ef8,\n    0x30f3, 0xf2f2, 0xb4f0, 0x76f1, 0x38f4, 0xfaf5, 0xbcf7, 0x7ef6,\n    0x40d9, 0x82d8, 0xc4da, 0x06db, 0x48de, 0x8adf, 0xccdd, 0x0edc,\n    0x50d7, 0x92d6, 0xd4d4, 0x16d5, 0x58d0, 0x9ad1, 0xdcd3, 0x1ed2,\n    0x60c5, 0xa2c4, 0xe4c6, 0x26c7, 0x68c2, 0xaac3, 0xecc1, 0x2ec0,\n    0x70cb, 0xb2ca, 0xf4c8, 0x36c9, 0x78cc, 0xbacd, 0xfccf, 0x3ece,\n    0x8091, 0x4290, 0x0492, 0xc693, 0x8896, 0x4a97, 0x0c95, 0xce94,\n    0x909f, 0x529e, 0x149c, 0xd69d, 0x9898, 0x5a99, 0x1c9b, 0xde9a,\n    0xa08d, 0x628c, 0x248e, 0xe68f, 0xa88a, 0x6a8b, 0x2c89, 0xee88,\n    0xb083, 0x7282, 0x3480, 0xf681, 0xb884, 0x7a85, 0x3c87, 0xfe86,\n    0xc0a9, 0x02a8, 0x44aa, 0x86ab, 0xc8ae, 0x0aaf, 0x4cad, 0x8eac,\n    0xd0a7, 0x12a6, 0x54a4, 0x96a5, 0xd8a0, 0x1aa1, 0x5ca3, 0x9ea2,\n    0xe0b5, 0x22b4, 0x64b6, 0xa6b7, 0xe8b2, 0x2ab3, 0x6cb1, 0xaeb0,\n    0xf0bb, 0x32ba, 0x74b8, 0xb6b9, 0xf8bc, 0x3abd, 0x7cbf, 0xbebe\n};\n\nstatic void gcm_mult_largetable(uint8_t *output, const uint8_t *x, uint64_t H[256][2])\n{\n    int i;\n    uint64_t u64z[2];\n    uint16_t *u16z = (uint16_t *) u64z;\n    uint8_t *u8z = (uint8_t *) u64z;\n    uint8_t rem;\n\n    u64z[0] = 0;\n    u64z[1] = 0;\n\n    if (MBEDTLS_IS_BIG_ENDIAN) {\n        for (i = 15; i > 0; i--) {\n            mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16);\n            rem = u8z[15];\n\n            u64z[1] >>= 8;\n            u8z[8] = u8z[7];\n            u64z[0] >>= 8;\n\n            u16z[0] ^= MBEDTLS_GET_UINT16_LE(&last8[rem], 0);\n        }\n    } else {\n        for (i = 15; i > 0; i--) {\n            mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16);\n            rem = u8z[15];\n\n            u64z[1] <<= 8;\n            u8z[8] = u8z[7];\n            u64z[0] <<= 8;\n\n            u16z[0] ^= last8[rem];\n        }\n    }\n\n    mbedtls_xor_no_simd(output, u8z, (uint8_t *) H[x[0]], 16);\n}\n#else\n/*\n * Shoup's method for multiplication use this table with\n *      last4[x] = x times P^128\n * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]\n */\nstatic const uint16_t last4[16] =\n{\n    0x0000, 0x1c20, 0x3840, 0x2460,\n    0x7080, 0x6ca0, 0x48c0, 0x54e0,\n    0xe100, 0xfd20, 0xd940, 0xc560,\n    0x9180, 0x8da0, 0xa9c0, 0xb5e0\n};\n\nstatic void gcm_mult_smalltable(uint8_t *output, const uint8_t *x, uint64_t H[16][2])\n{\n    int i = 0;\n    unsigned char lo, hi, rem;\n    uint64_t u64z[2];\n    const uint64_t *pu64z = NULL;\n    uint8_t *u8z = (uint8_t *) u64z;\n\n    lo = x[15] & 0xf;\n    hi = (x[15] >> 4) & 0xf;\n\n    pu64z = H[lo];\n\n    rem = (unsigned char) pu64z[1] & 0xf;\n    u64z[1] = (pu64z[0] << 60) | (pu64z[1] >> 4);\n    u64z[0] = (pu64z[0] >> 4);\n    u64z[0] ^= (uint64_t) last4[rem] << 48;\n    mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);\n\n    for (i = 14; i >= 0; i--) {\n        lo = x[i] & 0xf;\n        hi = (x[i] >> 4) & 0xf;\n\n        rem = (unsigned char) u64z[1] & 0xf;\n        u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);\n        u64z[0] = (u64z[0] >> 4);\n        u64z[0] ^= (uint64_t) last4[rem] << 48;\n        mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[lo], 16);\n\n        rem = (unsigned char) u64z[1] & 0xf;\n        u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);\n        u64z[0] = (u64z[0] >> 4);\n        u64z[0] ^= (uint64_t) last4[rem] << 48;\n        mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);\n    }\n\n    MBEDTLS_PUT_UINT64_BE(u64z[0], output, 0);\n    MBEDTLS_PUT_UINT64_BE(u64z[1], output, 8);\n}\n#endif\n\n/*\n * Sets output to x times H using the precomputed tables.\n * x and output are seen as elements of GF(2^128) as in [MGV].\n */\nstatic void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],\n                     unsigned char output[16])\n{\n    switch (ctx->acceleration) {\n#if defined(MBEDTLS_AESNI_HAVE_CODE)\n        case MBEDTLS_GCM_ACC_AESNI:\n            mbedtls_aesni_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);\n            break;\n#endif\n\n#if defined(MBEDTLS_AESCE_HAVE_CODE)\n        case MBEDTLS_GCM_ACC_AESCE:\n            mbedtls_aesce_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);\n            break;\n#endif\n\n#if defined(MBEDTLS_GCM_LARGE_TABLE)\n        case MBEDTLS_GCM_ACC_LARGETABLE:\n            gcm_mult_largetable(output, x, ctx->H);\n            break;\n#else\n        case MBEDTLS_GCM_ACC_SMALLTABLE:\n            gcm_mult_smalltable(output, x, ctx->H);\n            break;\n#endif\n    }\n\n    return;\n}\n\nint mbedtls_gcm_starts(mbedtls_gcm_context *ctx,\n                       int mode,\n                       const unsigned char *iv, size_t iv_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char work_buf[16];\n    const unsigned char *p;\n    size_t use_len;\n    uint64_t iv_bits;\n#if !defined(MBEDTLS_BLOCK_CIPHER_C)\n    size_t olen = 0;\n#endif\n\n    /* IV is limited to 2^64 bits, so 2^61 bytes */\n    /* IV is not allowed to be zero length */\n    if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) {\n        return MBEDTLS_ERR_GCM_BAD_INPUT;\n    }\n\n    memset(ctx->y, 0x00, sizeof(ctx->y));\n    memset(ctx->buf, 0x00, sizeof(ctx->buf));\n\n    ctx->mode = mode;\n    ctx->len = 0;\n    ctx->add_len = 0;\n\n    if (iv_len == 12) {\n        memcpy(ctx->y, iv, iv_len);\n        ctx->y[15] = 1;\n    } else {\n        memset(work_buf, 0x00, 16);\n        iv_bits = (uint64_t) iv_len * 8;\n        MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);\n\n        p = iv;\n        while (iv_len > 0) {\n            use_len = (iv_len < 16) ? iv_len : 16;\n\n#if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic warning \"-Wstringop-overflow=0\"\n#endif\n\n            mbedtls_xor(ctx->y, ctx->y, p, use_len);\n\n#if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)\n#pragma GCC diagnostic pop\n#endif\n\n            gcm_mult(ctx, ctx->y, ctx->y);\n\n            iv_len -= use_len;\n            p += use_len;\n        }\n\n        mbedtls_xor(ctx->y, ctx->y, work_buf, 16);\n\n        gcm_mult(ctx, ctx->y, ctx->y);\n    }\n\n\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n    ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->base_ectr);\n#else\n    ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, &olen);\n#endif\n    if (ret != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\n/**\n * mbedtls_gcm_context::buf contains the partial state of the computation of\n * the authentication tag.\n * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate\n * different stages of the computation:\n *     * len == 0 && add_len == 0:      initial state\n *     * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have\n *                                      a partial block of AD that has been\n *                                      xored in but not yet multiplied in.\n *     * len == 0 && add_len % 16 == 0: the authentication tag is correct if\n *                                      the data ends now.\n *     * len % 16 != 0:                 the first `len % 16` bytes have\n *                                      a partial block of ciphertext that has\n *                                      been xored in but not yet multiplied in.\n *     * len > 0 && len % 16 == 0:      the authentication tag is correct if\n *                                      the data ends now.\n */\nint mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,\n                          const unsigned char *add, size_t add_len)\n{\n    const unsigned char *p;\n    size_t use_len, offset;\n    uint64_t new_add_len;\n\n    /* AD is limited to 2^64 bits, ie 2^61 bytes\n     * Also check for possible overflow */\n#if SIZE_MAX > 0xFFFFFFFFFFFFFFFFULL\n    if (add_len > 0xFFFFFFFFFFFFFFFFULL) {\n        return MBEDTLS_ERR_GCM_BAD_INPUT;\n    }\n#endif\n    new_add_len = ctx->add_len + (uint64_t) add_len;\n    if (new_add_len < ctx->add_len || new_add_len >> 61 != 0) {\n        return MBEDTLS_ERR_GCM_BAD_INPUT;\n    }\n\n    offset = ctx->add_len % 16;\n    p = add;\n\n    if (offset != 0) {\n        use_len = 16 - offset;\n        if (use_len > add_len) {\n            use_len = add_len;\n        }\n\n        mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);\n\n        if (offset + use_len == 16) {\n            gcm_mult(ctx, ctx->buf, ctx->buf);\n        }\n\n        ctx->add_len += use_len;\n        add_len -= use_len;\n        p += use_len;\n    }\n\n    ctx->add_len += add_len;\n\n    while (add_len >= 16) {\n        mbedtls_xor(ctx->buf, ctx->buf, p, 16);\n\n        gcm_mult(ctx, ctx->buf, ctx->buf);\n\n        add_len -= 16;\n        p += 16;\n    }\n\n    if (add_len > 0) {\n        mbedtls_xor(ctx->buf, ctx->buf, p, add_len);\n    }\n\n    return 0;\n}\n\n/* Increment the counter. */\nstatic void gcm_incr(unsigned char y[16])\n{\n    uint32_t x = MBEDTLS_GET_UINT32_BE(y, 12);\n    x++;\n    MBEDTLS_PUT_UINT32_BE(x, y, 12);\n}\n\n/* Calculate and apply the encryption mask. Process use_len bytes of data,\n * starting at position offset in the mask block. */\nstatic int gcm_mask(mbedtls_gcm_context *ctx,\n                    unsigned char ectr[16],\n                    size_t offset, size_t use_len,\n                    const unsigned char *input,\n                    unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n    ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ectr);\n#else\n    size_t olen = 0;\n    ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr, &olen);\n#endif\n    if (ret != 0) {\n        mbedtls_platform_zeroize(ectr, 16);\n        return ret;\n    }\n\n    if (ctx->mode == MBEDTLS_GCM_DECRYPT) {\n        mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len);\n    }\n    mbedtls_xor(output, ectr + offset, input, use_len);\n    if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {\n        mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len);\n    }\n\n    return 0;\n}\n\nint mbedtls_gcm_update(mbedtls_gcm_context *ctx,\n                       const unsigned char *input, size_t input_length,\n                       unsigned char *output, size_t output_size,\n                       size_t *output_length)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const unsigned char *p = input;\n    unsigned char *out_p = output;\n    size_t offset;\n    unsigned char ectr[16] = { 0 };\n\n    if (output_size < input_length) {\n        return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;\n    }\n    *output_length = input_length;\n\n    /* Exit early if input_length==0 so that we don't do any pointer arithmetic\n     * on a potentially null pointer.\n     * Returning early also means that the last partial block of AD remains\n     * untouched for mbedtls_gcm_finish */\n    if (input_length == 0) {\n        return 0;\n    }\n\n    if (output > input && (size_t) (output - input) < input_length) {\n        return MBEDTLS_ERR_GCM_BAD_INPUT;\n    }\n\n    /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes\n     * Also check for possible overflow */\n    if (ctx->len + input_length < ctx->len ||\n        (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {\n        return MBEDTLS_ERR_GCM_BAD_INPUT;\n    }\n\n    if (ctx->len == 0 && ctx->add_len % 16 != 0) {\n        gcm_mult(ctx, ctx->buf, ctx->buf);\n    }\n\n    offset = ctx->len % 16;\n    if (offset != 0) {\n        size_t use_len = 16 - offset;\n        if (use_len > input_length) {\n            use_len = input_length;\n        }\n\n        if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {\n            return ret;\n        }\n\n        if (offset + use_len == 16) {\n            gcm_mult(ctx, ctx->buf, ctx->buf);\n        }\n\n        ctx->len += use_len;\n        input_length -= use_len;\n        p += use_len;\n        out_p += use_len;\n    }\n\n    ctx->len += input_length;\n\n    while (input_length >= 16) {\n        gcm_incr(ctx->y);\n        if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {\n            return ret;\n        }\n\n        gcm_mult(ctx, ctx->buf, ctx->buf);\n\n        input_length -= 16;\n        p += 16;\n        out_p += 16;\n    }\n\n    if (input_length > 0) {\n        gcm_incr(ctx->y);\n        if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {\n            return ret;\n        }\n    }\n\n    mbedtls_platform_zeroize(ectr, sizeof(ectr));\n    return 0;\n}\n\nint mbedtls_gcm_finish(mbedtls_gcm_context *ctx,\n                       unsigned char *output, size_t output_size,\n                       size_t *output_length,\n                       unsigned char *tag, size_t tag_len)\n{\n    unsigned char work_buf[16];\n    uint64_t orig_len;\n    uint64_t orig_add_len;\n\n    /* We never pass any output in finish(). The output parameter exists only\n     * for the sake of alternative implementations. */\n    (void) output;\n    (void) output_size;\n    *output_length = 0;\n\n    /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes\n     * and AD length is restricted to 2^64 bits, ie 2^61 bytes so neither of\n     * the two multiplications would overflow. */\n    orig_len = ctx->len * 8;\n    orig_add_len = ctx->add_len * 8;\n\n    if (ctx->len == 0 && ctx->add_len % 16 != 0) {\n        gcm_mult(ctx, ctx->buf, ctx->buf);\n    }\n\n    if (tag_len > 16 || tag_len < 4) {\n        return MBEDTLS_ERR_GCM_BAD_INPUT;\n    }\n\n    if (ctx->len % 16 != 0) {\n        gcm_mult(ctx, ctx->buf, ctx->buf);\n    }\n\n    memcpy(tag, ctx->base_ectr, tag_len);\n\n    if (orig_len || orig_add_len) {\n        memset(work_buf, 0x00, 16);\n\n        MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);\n        MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);\n        MBEDTLS_PUT_UINT32_BE((orig_len     >> 32), work_buf, 8);\n        MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);\n\n        mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);\n\n        gcm_mult(ctx, ctx->buf, ctx->buf);\n\n        mbedtls_xor(tag, tag, ctx->buf, tag_len);\n    }\n\n    return 0;\n}\n\nint mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,\n                              int mode,\n                              size_t length,\n                              const unsigned char *iv,\n                              size_t iv_len,\n                              const unsigned char *add,\n                              size_t add_len,\n                              const unsigned char *input,\n                              unsigned char *output,\n                              size_t tag_len,\n                              unsigned char *tag)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t olen;\n\n    if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_gcm_update(ctx, input, length,\n                                  output, length, &olen)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\nint mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,\n                             size_t length,\n                             const unsigned char *iv,\n                             size_t iv_len,\n                             const unsigned char *add,\n                             size_t add_len,\n                             const unsigned char *tag,\n                             size_t tag_len,\n                             const unsigned char *input,\n                             unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char check_tag[16];\n    int diff;\n\n    if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,\n                                         iv, iv_len, add, add_len,\n                                         input, output, tag_len, check_tag)) != 0) {\n        return ret;\n    }\n\n    /* Check tag in \"constant-time\" */\n    diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);\n\n    if (diff != 0) {\n        mbedtls_platform_zeroize(output, length);\n        return MBEDTLS_ERR_GCM_AUTH_FAILED;\n    }\n\n    return 0;\n}\n\nvoid mbedtls_gcm_free(mbedtls_gcm_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n#if defined(MBEDTLS_BLOCK_CIPHER_C)\n    mbedtls_block_cipher_free(&ctx->block_cipher_ctx);\n#else\n    mbedtls_cipher_free(&ctx->cipher_ctx);\n#endif\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));\n}\n\n#endif /* !MBEDTLS_GCM_ALT */\n\n#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES)\n/*\n * AES-GCM test vectors from:\n *\n * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip\n */\n#define MAX_TESTS   6\n\nstatic const int key_index_test_data[MAX_TESTS] =\n{ 0, 0, 1, 1, 1, 1 };\n\nstatic const unsigned char key_test_data[][32] =\n{\n    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n    { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,\n      0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,\n      0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,\n      0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },\n};\n\nstatic const size_t iv_len_test_data[MAX_TESTS] =\n{ 12, 12, 12, 12, 8, 60 };\n\nstatic const int iv_index_test_data[MAX_TESTS] =\n{ 0, 0, 1, 1, 1, 2 };\n\nstatic const unsigned char iv_test_data[][64] =\n{\n    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00 },\n    { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,\n      0xde, 0xca, 0xf8, 0x88 },\n    { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,\n      0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,\n      0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,\n      0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,\n      0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,\n      0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,\n      0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,\n      0xa6, 0x37, 0xb3, 0x9b },\n};\n\nstatic const size_t add_len_test_data[MAX_TESTS] =\n{ 0, 0, 0, 20, 20, 20 };\n\nstatic const int add_index_test_data[MAX_TESTS] =\n{ 0, 0, 0, 1, 1, 1 };\n\nstatic const unsigned char additional_test_data[][64] =\n{\n    { 0x00 },\n    { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,\n      0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,\n      0xab, 0xad, 0xda, 0xd2 },\n};\n\nstatic const size_t pt_len_test_data[MAX_TESTS] =\n{ 0, 16, 64, 60, 60, 60 };\n\nstatic const int pt_index_test_data[MAX_TESTS] =\n{ 0, 0, 1, 1, 1, 1 };\n\nstatic const unsigned char pt_test_data[][64] =\n{\n    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n    { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,\n      0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,\n      0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,\n      0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,\n      0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,\n      0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,\n      0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,\n      0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },\n};\n\nstatic const unsigned char ct_test_data[][64] =\n{\n    { 0x00 },\n    { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,\n      0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },\n    { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,\n      0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,\n      0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,\n      0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,\n      0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,\n      0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,\n      0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,\n      0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },\n    { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,\n      0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,\n      0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,\n      0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,\n      0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,\n      0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,\n      0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,\n      0x3d, 0x58, 0xe0, 0x91 },\n    { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,\n      0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,\n      0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,\n      0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,\n      0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,\n      0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,\n      0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,\n      0xc2, 0x3f, 0x45, 0x98 },\n    { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,\n      0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,\n      0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,\n      0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,\n      0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,\n      0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,\n      0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,\n      0x4c, 0x34, 0xae, 0xe5 },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0x00 },\n    { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,\n      0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },\n    { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,\n      0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,\n      0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,\n      0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,\n      0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,\n      0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,\n      0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,\n      0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },\n    { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,\n      0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,\n      0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,\n      0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,\n      0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,\n      0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,\n      0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,\n      0xcc, 0xda, 0x27, 0x10 },\n    { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,\n      0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,\n      0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,\n      0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,\n      0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,\n      0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,\n      0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,\n      0xa0, 0xf0, 0x62, 0xf7 },\n    { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,\n      0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,\n      0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,\n      0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,\n      0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,\n      0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,\n      0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,\n      0xe9, 0xb7, 0x37, 0x3b },\n    { 0x00 },\n    { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,\n      0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },\n    { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,\n      0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,\n      0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,\n      0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,\n      0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,\n      0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,\n      0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,\n      0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },\n    { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,\n      0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,\n      0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,\n      0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,\n      0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,\n      0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,\n      0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,\n      0xbc, 0xc9, 0xf6, 0x62 },\n    { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,\n      0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,\n      0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,\n      0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,\n      0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,\n      0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,\n      0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,\n      0xf4, 0x7c, 0x9b, 0x1f },\n    { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,\n      0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,\n      0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,\n      0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,\n      0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,\n      0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,\n      0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,\n      0x44, 0xae, 0x7e, 0x3f },\n#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */\n};\n\nstatic const unsigned char tag_test_data[][16] =\n{\n    { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,\n      0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },\n    { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,\n      0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },\n    { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,\n      0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },\n    { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,\n      0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },\n    { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,\n      0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },\n    { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,\n      0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,\n      0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },\n    { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,\n      0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },\n    { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,\n      0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },\n    { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,\n      0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },\n    { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,\n      0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },\n    { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,\n      0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },\n    { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,\n      0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },\n    { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,\n      0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },\n    { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,\n      0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },\n    { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,\n      0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },\n    { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,\n      0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },\n    { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,\n      0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },\n#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */\n};\n\nint mbedtls_gcm_self_test(int verbose)\n{\n    mbedtls_gcm_context ctx;\n    unsigned char buf[64];\n    unsigned char tag_buf[16];\n    int i, j, ret;\n    mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;\n    size_t olen;\n\n    if (verbose != 0) {\n#if defined(MBEDTLS_GCM_ALT)\n        mbedtls_printf(\"  GCM note: alternative implementation.\\n\");\n#else /* MBEDTLS_GCM_ALT */\n#if defined(MBEDTLS_AESNI_HAVE_CODE)\n        if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {\n            mbedtls_printf(\"  GCM note: using AESNI.\\n\");\n        } else\n#endif\n\n#if defined(MBEDTLS_AESCE_HAVE_CODE)\n        if (MBEDTLS_AESCE_HAS_SUPPORT()) {\n            mbedtls_printf(\"  GCM note: using AESCE.\\n\");\n        } else\n#endif\n\n        mbedtls_printf(\"  GCM note: built-in implementation.\\n\");\n#endif /* MBEDTLS_GCM_ALT */\n    }\n\n    static const int loop_limit =\n        (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS;\n\n    for (j = 0; j < loop_limit; j++) {\n        int key_len = 128 + 64 * j;\n\n        for (i = 0; i < MAX_TESTS; i++) {\n            if (verbose != 0) {\n                mbedtls_printf(\"  AES-GCM-%3d #%d (%s): \",\n                               key_len, i, \"enc\");\n            }\n\n            mbedtls_gcm_init(&ctx);\n\n            ret = mbedtls_gcm_setkey(&ctx, cipher,\n                                     key_test_data[key_index_test_data[i]],\n                                     key_len);\n            /*\n             * AES-192 is an optional feature that may be unavailable when\n             * there is an alternative underlying implementation i.e. when\n             * MBEDTLS_AES_ALT is defined.\n             */\n            if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {\n                mbedtls_printf(\"skipped\\n\");\n                break;\n            } else if (ret != 0) {\n                goto exit;\n            }\n\n            ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,\n                                            pt_len_test_data[i],\n                                            iv_test_data[iv_index_test_data[i]],\n                                            iv_len_test_data[i],\n                                            additional_test_data[add_index_test_data[i]],\n                                            add_len_test_data[i],\n                                            pt_test_data[pt_index_test_data[i]],\n                                            buf, 16, tag_buf);\n#if defined(MBEDTLS_GCM_ALT)\n            /* Allow alternative implementations to only support 12-byte nonces. */\n            if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&\n                iv_len_test_data[i] != 12) {\n                mbedtls_printf(\"skipped\\n\");\n                break;\n            }\n#endif /* defined(MBEDTLS_GCM_ALT) */\n            if (ret != 0) {\n                goto exit;\n            }\n\n            if (memcmp(buf, ct_test_data[j * 6 + i],\n                       pt_len_test_data[i]) != 0 ||\n                memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {\n                ret = 1;\n                goto exit;\n            }\n\n            mbedtls_gcm_free(&ctx);\n\n            if (verbose != 0) {\n                mbedtls_printf(\"passed\\n\");\n            }\n\n            mbedtls_gcm_init(&ctx);\n\n            if (verbose != 0) {\n                mbedtls_printf(\"  AES-GCM-%3d #%d (%s): \",\n                               key_len, i, \"dec\");\n            }\n\n            ret = mbedtls_gcm_setkey(&ctx, cipher,\n                                     key_test_data[key_index_test_data[i]],\n                                     key_len);\n            if (ret != 0) {\n                goto exit;\n            }\n\n            ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,\n                                            pt_len_test_data[i],\n                                            iv_test_data[iv_index_test_data[i]],\n                                            iv_len_test_data[i],\n                                            additional_test_data[add_index_test_data[i]],\n                                            add_len_test_data[i],\n                                            ct_test_data[j * 6 + i], buf, 16, tag_buf);\n\n            if (ret != 0) {\n                goto exit;\n            }\n\n            if (memcmp(buf, pt_test_data[pt_index_test_data[i]],\n                       pt_len_test_data[i]) != 0 ||\n                memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {\n                ret = 1;\n                goto exit;\n            }\n\n            mbedtls_gcm_free(&ctx);\n\n            if (verbose != 0) {\n                mbedtls_printf(\"passed\\n\");\n            }\n\n            mbedtls_gcm_init(&ctx);\n\n            if (verbose != 0) {\n                mbedtls_printf(\"  AES-GCM-%3d #%d split (%s): \",\n                               key_len, i, \"enc\");\n            }\n\n            ret = mbedtls_gcm_setkey(&ctx, cipher,\n                                     key_test_data[key_index_test_data[i]],\n                                     key_len);\n            if (ret != 0) {\n                goto exit;\n            }\n\n            ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,\n                                     iv_test_data[iv_index_test_data[i]],\n                                     iv_len_test_data[i]);\n            if (ret != 0) {\n                goto exit;\n            }\n\n            ret = mbedtls_gcm_update_ad(&ctx,\n                                        additional_test_data[add_index_test_data[i]],\n                                        add_len_test_data[i]);\n            if (ret != 0) {\n                goto exit;\n            }\n\n            if (pt_len_test_data[i] > 32) {\n                size_t rest_len = pt_len_test_data[i] - 32;\n                ret = mbedtls_gcm_update(&ctx,\n                                         pt_test_data[pt_index_test_data[i]],\n                                         32,\n                                         buf, sizeof(buf), &olen);\n                if (ret != 0) {\n                    goto exit;\n                }\n                if (olen != 32) {\n                    goto exit;\n                }\n\n                ret = mbedtls_gcm_update(&ctx,\n                                         pt_test_data[pt_index_test_data[i]] + 32,\n                                         rest_len,\n                                         buf + 32, sizeof(buf) - 32, &olen);\n                if (ret != 0) {\n                    goto exit;\n                }\n                if (olen != rest_len) {\n                    goto exit;\n                }\n            } else {\n                ret = mbedtls_gcm_update(&ctx,\n                                         pt_test_data[pt_index_test_data[i]],\n                                         pt_len_test_data[i],\n                                         buf, sizeof(buf), &olen);\n                if (ret != 0) {\n                    goto exit;\n                }\n                if (olen != pt_len_test_data[i]) {\n                    goto exit;\n                }\n            }\n\n            ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);\n            if (ret != 0) {\n                goto exit;\n            }\n\n            if (memcmp(buf, ct_test_data[j * 6 + i],\n                       pt_len_test_data[i]) != 0 ||\n                memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {\n                ret = 1;\n                goto exit;\n            }\n\n            mbedtls_gcm_free(&ctx);\n\n            if (verbose != 0) {\n                mbedtls_printf(\"passed\\n\");\n            }\n\n            mbedtls_gcm_init(&ctx);\n\n            if (verbose != 0) {\n                mbedtls_printf(\"  AES-GCM-%3d #%d split (%s): \",\n                               key_len, i, \"dec\");\n            }\n\n            ret = mbedtls_gcm_setkey(&ctx, cipher,\n                                     key_test_data[key_index_test_data[i]],\n                                     key_len);\n            if (ret != 0) {\n                goto exit;\n            }\n\n            ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,\n                                     iv_test_data[iv_index_test_data[i]],\n                                     iv_len_test_data[i]);\n            if (ret != 0) {\n                goto exit;\n            }\n            ret = mbedtls_gcm_update_ad(&ctx,\n                                        additional_test_data[add_index_test_data[i]],\n                                        add_len_test_data[i]);\n            if (ret != 0) {\n                goto exit;\n            }\n\n            if (pt_len_test_data[i] > 32) {\n                size_t rest_len = pt_len_test_data[i] - 32;\n                ret = mbedtls_gcm_update(&ctx,\n                                         ct_test_data[j * 6 + i], 32,\n                                         buf, sizeof(buf), &olen);\n                if (ret != 0) {\n                    goto exit;\n                }\n                if (olen != 32) {\n                    goto exit;\n                }\n\n                ret = mbedtls_gcm_update(&ctx,\n                                         ct_test_data[j * 6 + i] + 32,\n                                         rest_len,\n                                         buf + 32, sizeof(buf) - 32, &olen);\n                if (ret != 0) {\n                    goto exit;\n                }\n                if (olen != rest_len) {\n                    goto exit;\n                }\n            } else {\n                ret = mbedtls_gcm_update(&ctx,\n                                         ct_test_data[j * 6 + i],\n                                         pt_len_test_data[i],\n                                         buf, sizeof(buf), &olen);\n                if (ret != 0) {\n                    goto exit;\n                }\n                if (olen != pt_len_test_data[i]) {\n                    goto exit;\n                }\n            }\n\n            ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);\n            if (ret != 0) {\n                goto exit;\n            }\n\n            if (memcmp(buf, pt_test_data[pt_index_test_data[i]],\n                       pt_len_test_data[i]) != 0 ||\n                memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {\n                ret = 1;\n                goto exit;\n            }\n\n            mbedtls_gcm_free(&ctx);\n\n            if (verbose != 0) {\n                mbedtls_printf(\"passed\\n\");\n            }\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    ret = 0;\n\nexit:\n    if (ret != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n        mbedtls_gcm_free(&ctx);\n    }\n\n    return ret;\n}\n\n#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */\n\n#endif /* MBEDTLS_GCM_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/hkdf.c",
    "content": "/*\n *  HKDF implementation -- RFC 5869\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#include \"common.h\"\n\n#if defined(MBEDTLS_HKDF_C)\n\n#include <string.h>\n#include \"mbedtls/hkdf.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\nint mbedtls_hkdf(const mbedtls_md_info_t *md, const unsigned char *salt,\n                 size_t salt_len, const unsigned char *ikm, size_t ikm_len,\n                 const unsigned char *info, size_t info_len,\n                 unsigned char *okm, size_t okm_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char prk[MBEDTLS_MD_MAX_SIZE];\n\n    ret = mbedtls_hkdf_extract(md, salt, salt_len, ikm, ikm_len, prk);\n\n    if (ret == 0) {\n        ret = mbedtls_hkdf_expand(md, prk, mbedtls_md_get_size(md),\n                                  info, info_len, okm, okm_len);\n    }\n\n    mbedtls_platform_zeroize(prk, sizeof(prk));\n\n    return ret;\n}\n\nint mbedtls_hkdf_extract(const mbedtls_md_info_t *md,\n                         const unsigned char *salt, size_t salt_len,\n                         const unsigned char *ikm, size_t ikm_len,\n                         unsigned char *prk)\n{\n    unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\\0' };\n\n    if (salt == NULL) {\n        size_t hash_len;\n\n        if (salt_len != 0) {\n            return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;\n        }\n\n        hash_len = mbedtls_md_get_size(md);\n\n        if (hash_len == 0) {\n            return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;\n        }\n\n        salt = null_salt;\n        salt_len = hash_len;\n    }\n\n    return mbedtls_md_hmac(md, salt, salt_len, ikm, ikm_len, prk);\n}\n\nint mbedtls_hkdf_expand(const mbedtls_md_info_t *md, const unsigned char *prk,\n                        size_t prk_len, const unsigned char *info,\n                        size_t info_len, unsigned char *okm, size_t okm_len)\n{\n    size_t hash_len;\n    size_t where = 0;\n    size_t n;\n    size_t t_len = 0;\n    size_t i;\n    int ret = 0;\n    mbedtls_md_context_t ctx;\n    unsigned char t[MBEDTLS_MD_MAX_SIZE];\n\n    if (okm == NULL) {\n        return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;\n    }\n\n    hash_len = mbedtls_md_get_size(md);\n\n    if (prk_len < hash_len || hash_len == 0) {\n        return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;\n    }\n\n    if (info == NULL) {\n        info = (const unsigned char *) \"\";\n        info_len = 0;\n    }\n\n    n = okm_len / hash_len;\n\n    if (okm_len % hash_len != 0) {\n        n++;\n    }\n\n    /*\n     * Per RFC 5869 Section 2.3, okm_len must not exceed\n     * 255 times the hash length\n     */\n    if (n > 255) {\n        return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;\n    }\n\n    mbedtls_md_init(&ctx);\n\n    if ((ret = mbedtls_md_setup(&ctx, md, 1)) != 0) {\n        goto exit;\n    }\n\n    memset(t, 0, hash_len);\n\n    /*\n     * Compute T = T(1) | T(2) | T(3) | ... | T(N)\n     * Where T(N) is defined in RFC 5869 Section 2.3\n     */\n    for (i = 1; i <= n; i++) {\n        size_t num_to_copy;\n        unsigned char c = i & 0xff;\n\n        ret = mbedtls_md_hmac_starts(&ctx, prk, prk_len);\n        if (ret != 0) {\n            goto exit;\n        }\n\n        ret = mbedtls_md_hmac_update(&ctx, t, t_len);\n        if (ret != 0) {\n            goto exit;\n        }\n\n        ret = mbedtls_md_hmac_update(&ctx, info, info_len);\n        if (ret != 0) {\n            goto exit;\n        }\n\n        /* The constant concatenated to the end of each T(n) is a single octet.\n         * */\n        ret = mbedtls_md_hmac_update(&ctx, &c, 1);\n        if (ret != 0) {\n            goto exit;\n        }\n\n        ret = mbedtls_md_hmac_finish(&ctx, t);\n        if (ret != 0) {\n            goto exit;\n        }\n\n        num_to_copy = i != n ? hash_len : okm_len - where;\n        memcpy(okm + where, t, num_to_copy);\n        where += hash_len;\n        t_len = hash_len;\n    }\n\nexit:\n    mbedtls_md_free(&ctx);\n    mbedtls_platform_zeroize(t, sizeof(t));\n\n    return ret;\n}\n\n#endif /* MBEDTLS_HKDF_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/hmac_drbg.c",
    "content": "/*\n *  HMAC_DRBG implementation (NIST SP 800-90)\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n *  The NIST SP 800-90A DRBGs are described in the following publication.\n *  http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf\n *  References below are based on rev. 1 (January 2012).\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_HMAC_DRBG_C)\n\n#include \"mbedtls/hmac_drbg.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_FS_IO)\n#include <stdio.h>\n#endif\n\n#include \"mbedtls/platform.h\"\n\n/*\n * HMAC_DRBG context initialization\n */\nvoid mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_hmac_drbg_context));\n\n    ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;\n}\n\n/*\n * HMAC_DRBG update, using optional additional data (10.1.2.2)\n */\nint mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx,\n                             const unsigned char *additional,\n                             size_t add_len)\n{\n    size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);\n    unsigned char rounds = (additional != NULL && add_len != 0) ? 2 : 1;\n    unsigned char sep[1];\n    unsigned char K[MBEDTLS_MD_MAX_SIZE];\n    int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n\n    for (sep[0] = 0; sep[0] < rounds; sep[0]++) {\n        /* Step 1 or 4 */\n        if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {\n            goto exit;\n        }\n        if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,\n                                          ctx->V, md_len)) != 0) {\n            goto exit;\n        }\n        if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,\n                                          sep, 1)) != 0) {\n            goto exit;\n        }\n        if (rounds == 2) {\n            if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,\n                                              additional, add_len)) != 0) {\n                goto exit;\n            }\n        }\n        if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, K)) != 0) {\n            goto exit;\n        }\n\n        /* Step 2 or 5 */\n        if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, K, md_len)) != 0) {\n            goto exit;\n        }\n        if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,\n                                          ctx->V, md_len)) != 0) {\n            goto exit;\n        }\n        if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {\n            goto exit;\n        }\n    }\n\nexit:\n    mbedtls_platform_zeroize(K, sizeof(K));\n    return ret;\n}\n\n/*\n * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)\n */\nint mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context *ctx,\n                               const mbedtls_md_info_t *md_info,\n                               const unsigned char *data, size_t data_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {\n        return ret;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_init(&ctx->mutex);\n#endif\n\n    /*\n     * Set initial working state.\n     * Use the V memory location, which is currently all 0, to initialize the\n     * MD context with an all-zero key. Then set V to its initial value.\n     */\n    if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V,\n                                      mbedtls_md_get_size(md_info))) != 0) {\n        return ret;\n    }\n    memset(ctx->V, 0x01, mbedtls_md_get_size(md_info));\n\n    if ((ret = mbedtls_hmac_drbg_update(ctx, data, data_len)) != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\n/*\n * Internal function used both for seeding and reseeding the DRBG.\n * Comments starting with arabic numbers refer to section 10.1.2.4\n * of SP800-90A, while roman numbers refer to section 9.2.\n */\nstatic int hmac_drbg_reseed_core(mbedtls_hmac_drbg_context *ctx,\n                                 const unsigned char *additional, size_t len,\n                                 int use_nonce)\n{\n    unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];\n    size_t seedlen = 0;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    {\n        size_t total_entropy_len;\n\n        if (use_nonce == 0) {\n            total_entropy_len = ctx->entropy_len;\n        } else {\n            total_entropy_len = ctx->entropy_len * 3 / 2;\n        }\n\n        /* III. Check input length */\n        if (len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||\n            total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) {\n            return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;\n        }\n    }\n\n    memset(seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT);\n\n    /* IV. Gather entropy_len bytes of entropy for the seed */\n    if ((ret = ctx->f_entropy(ctx->p_entropy,\n                              seed, ctx->entropy_len)) != 0) {\n        return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;\n    }\n    seedlen += ctx->entropy_len;\n\n    /* For initial seeding, allow adding of nonce generated\n     * from the entropy source. See Sect 8.6.7 in SP800-90A. */\n    if (use_nonce) {\n        /* Note: We don't merge the two calls to f_entropy() in order\n         *       to avoid requesting too much entropy from f_entropy()\n         *       at once. Specifically, if the underlying digest is not\n         *       SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which\n         *       is larger than the maximum of 32 Bytes that our own\n         *       entropy source implementation can emit in a single\n         *       call in configurations disabling SHA-512. */\n        if ((ret = ctx->f_entropy(ctx->p_entropy,\n                                  seed + seedlen,\n                                  ctx->entropy_len / 2)) != 0) {\n            return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;\n        }\n\n        seedlen += ctx->entropy_len / 2;\n    }\n\n\n    /* 1. Concatenate entropy and additional data if any */\n    if (additional != NULL && len != 0) {\n        memcpy(seed + seedlen, additional, len);\n        seedlen += len;\n    }\n\n    /* 2. Update state */\n    if ((ret = mbedtls_hmac_drbg_update(ctx, seed, seedlen)) != 0) {\n        goto exit;\n    }\n\n    /* 3. Reset reseed_counter */\n    ctx->reseed_counter = 1;\n\nexit:\n    /* 4. Done */\n    mbedtls_platform_zeroize(seed, seedlen);\n    return ret;\n}\n\n/*\n * HMAC_DRBG reseeding: 10.1.2.4 + 9.2\n */\nint mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context *ctx,\n                             const unsigned char *additional, size_t len)\n{\n    return hmac_drbg_reseed_core(ctx, additional, len, 0);\n}\n\n/*\n * HMAC_DRBG initialisation (10.1.2.3 + 9.1)\n *\n * The nonce is not passed as a separate parameter but extracted\n * from the entropy source as suggested in 8.6.7.\n */\nint mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context *ctx,\n                           const mbedtls_md_info_t *md_info,\n                           int (*f_entropy)(void *, unsigned char *, size_t),\n                           void *p_entropy,\n                           const unsigned char *custom,\n                           size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t md_size;\n\n    if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {\n        return ret;\n    }\n\n    /* The mutex is initialized iff the md context is set up. */\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_init(&ctx->mutex);\n#endif\n\n    md_size = mbedtls_md_get_size(md_info);\n\n    /*\n     * Set initial working state.\n     * Use the V memory location, which is currently all 0, to initialize the\n     * MD context with an all-zero key. Then set V to its initial value.\n     */\n    if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V, md_size)) != 0) {\n        return ret;\n    }\n    memset(ctx->V, 0x01, md_size);\n\n    ctx->f_entropy = f_entropy;\n    ctx->p_entropy = p_entropy;\n\n    if (ctx->entropy_len == 0) {\n        /*\n         * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by\n         * each hash function, then according to SP800-90A rev1 10.1 table 2,\n         * min_entropy_len (in bits) is security_strength.\n         *\n         * (This also matches the sizes used in the NIST test vectors.)\n         */\n        ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */\n                           md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */\n                           32;  /* better (256+) -> 256 bits */\n    }\n\n    if ((ret = hmac_drbg_reseed_core(ctx, custom, len,\n                                     1 /* add nonce */)) != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\n/*\n * Set prediction resistance\n */\nvoid mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context *ctx,\n                                                 int resistance)\n{\n    ctx->prediction_resistance = resistance;\n}\n\n/*\n * Set entropy length grabbed for seeding\n */\nvoid mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context *ctx, size_t len)\n{\n    ctx->entropy_len = len;\n}\n\n/*\n * Set reseed interval\n */\nvoid mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context *ctx, int interval)\n{\n    ctx->reseed_interval = interval;\n}\n\n/*\n * HMAC_DRBG random function with optional additional data:\n * 10.1.2.5 (arabic) + 9.3 (Roman)\n */\nint mbedtls_hmac_drbg_random_with_add(void *p_rng,\n                                      unsigned char *output, size_t out_len,\n                                      const unsigned char *additional, size_t add_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;\n    size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);\n    size_t left = out_len;\n    unsigned char *out = output;\n\n    /* II. Check request length */\n    if (out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST) {\n        return MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG;\n    }\n\n    /* III. Check input length */\n    if (add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT) {\n        return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;\n    }\n\n    /* 1. (aka VII and IX) Check reseed counter and PR */\n    if (ctx->f_entropy != NULL && /* For no-reseeding instances */\n        (ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||\n         ctx->reseed_counter > ctx->reseed_interval)) {\n        if ((ret = mbedtls_hmac_drbg_reseed(ctx, additional, add_len)) != 0) {\n            return ret;\n        }\n\n        add_len = 0; /* VII.4 */\n    }\n\n    /* 2. Use additional data if any */\n    if (additional != NULL && add_len != 0) {\n        if ((ret = mbedtls_hmac_drbg_update(ctx,\n                                            additional, add_len)) != 0) {\n            goto exit;\n        }\n    }\n\n    /* 3, 4, 5. Generate bytes */\n    while (left != 0) {\n        size_t use_len = left > md_len ? md_len : left;\n\n        if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {\n            goto exit;\n        }\n        if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,\n                                          ctx->V, md_len)) != 0) {\n            goto exit;\n        }\n        if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {\n            goto exit;\n        }\n\n        memcpy(out, ctx->V, use_len);\n        out += use_len;\n        left -= use_len;\n    }\n\n    /* 6. Update */\n    if ((ret = mbedtls_hmac_drbg_update(ctx,\n                                        additional, add_len)) != 0) {\n        goto exit;\n    }\n\n    /* 7. Update reseed counter */\n    ctx->reseed_counter++;\n\nexit:\n    /* 8. Done */\n    return ret;\n}\n\n/*\n * HMAC_DRBG random function\n */\nint mbedtls_hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;\n\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {\n        return ret;\n    }\n#endif\n\n    ret = mbedtls_hmac_drbg_random_with_add(ctx, output, out_len, NULL, 0);\n\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {\n        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n#endif\n\n    return ret;\n}\n\n/*\n *  This function resets HMAC_DRBG context to the state immediately\n *  after initial call of mbedtls_hmac_drbg_init().\n */\nvoid mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    /* The mutex is initialized iff the md context is set up. */\n    if (ctx->md_ctx.md_info != NULL) {\n        mbedtls_mutex_free(&ctx->mutex);\n    }\n#endif\n    mbedtls_md_free(&ctx->md_ctx);\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_hmac_drbg_context));\n    ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;\n}\n\n#if defined(MBEDTLS_FS_IO)\nint mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    FILE *f;\n    unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];\n\n    if ((f = fopen(path, \"wb\")) == NULL) {\n        return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;\n    }\n\n    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */\n    mbedtls_setbuf(f, NULL);\n\n    if ((ret = mbedtls_hmac_drbg_random(ctx, buf, sizeof(buf))) != 0) {\n        goto exit;\n    }\n\n    if (fwrite(buf, 1, sizeof(buf), f) != sizeof(buf)) {\n        ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;\n        goto exit;\n    }\n\n    ret = 0;\n\nexit:\n    fclose(f);\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n\n    return ret;\n}\n\nint mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)\n{\n    int ret = 0;\n    FILE *f = NULL;\n    size_t n;\n    unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];\n    unsigned char c;\n\n    if ((f = fopen(path, \"rb\")) == NULL) {\n        return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;\n    }\n\n    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */\n    mbedtls_setbuf(f, NULL);\n\n    n = fread(buf, 1, sizeof(buf), f);\n    if (fread(&c, 1, 1, f) != 0) {\n        ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;\n        goto exit;\n    }\n    if (n == 0 || ferror(f)) {\n        ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;\n        goto exit;\n    }\n    fclose(f);\n    f = NULL;\n\n    ret = mbedtls_hmac_drbg_update(ctx, buf, n);\n\nexit:\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n    if (f != NULL) {\n        fclose(f);\n    }\n    if (ret != 0) {\n        return ret;\n    }\n    return mbedtls_hmac_drbg_write_seed_file(ctx, path);\n}\n#endif /* MBEDTLS_FS_IO */\n\n\n#if defined(MBEDTLS_SELF_TEST)\n\n#if !defined(MBEDTLS_MD_CAN_SHA1)\n/* Dummy checkup routine */\nint mbedtls_hmac_drbg_self_test(int verbose)\n{\n    (void) verbose;\n    return 0;\n}\n#else\n\n#define OUTPUT_LEN  80\n\n/* From a NIST PR=true test vector */\nstatic const unsigned char entropy_pr[] = {\n    0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,\n    0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,\n    0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,\n    0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,\n    0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4\n};\nstatic const unsigned char result_pr[OUTPUT_LEN] = {\n    0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,\n    0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,\n    0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,\n    0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,\n    0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,\n    0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,\n    0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44\n};\n\n/* From a NIST PR=false test vector */\nstatic const unsigned char entropy_nopr[] = {\n    0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,\n    0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,\n    0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,\n    0xe9, 0x9d, 0xfe, 0xdf\n};\nstatic const unsigned char result_nopr[OUTPUT_LEN] = {\n    0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,\n    0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,\n    0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,\n    0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,\n    0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,\n    0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,\n    0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7\n};\n\n/* \"Entropy\" from buffer */\nstatic size_t test_offset;\nstatic int hmac_drbg_self_test_entropy(void *data,\n                                       unsigned char *buf, size_t len)\n{\n    const unsigned char *p = data;\n    memcpy(buf, p + test_offset, len);\n    test_offset += len;\n    return 0;\n}\n\n#define CHK(c)    if ((c) != 0)                          \\\n    {                                       \\\n        if (verbose != 0)                  \\\n        mbedtls_printf(\"failed\\n\");  \\\n        return 1;                        \\\n    }\n\n/*\n * Checkup routine for HMAC_DRBG with SHA-1\n */\nint mbedtls_hmac_drbg_self_test(int verbose)\n{\n    mbedtls_hmac_drbg_context ctx;\n    unsigned char buf[OUTPUT_LEN];\n    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);\n\n    mbedtls_hmac_drbg_init(&ctx);\n\n    /*\n     * PR = True\n     */\n    if (verbose != 0) {\n        mbedtls_printf(\"  HMAC_DRBG (PR = True) : \");\n    }\n\n    test_offset = 0;\n    CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,\n                               hmac_drbg_self_test_entropy, (void *) entropy_pr,\n                               NULL, 0));\n    mbedtls_hmac_drbg_set_prediction_resistance(&ctx, MBEDTLS_HMAC_DRBG_PR_ON);\n    CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));\n    CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));\n    CHK(memcmp(buf, result_pr, OUTPUT_LEN));\n    mbedtls_hmac_drbg_free(&ctx);\n\n    mbedtls_hmac_drbg_free(&ctx);\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\n    /*\n     * PR = False\n     */\n    if (verbose != 0) {\n        mbedtls_printf(\"  HMAC_DRBG (PR = False) : \");\n    }\n\n    mbedtls_hmac_drbg_init(&ctx);\n\n    test_offset = 0;\n    CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,\n                               hmac_drbg_self_test_entropy, (void *) entropy_nopr,\n                               NULL, 0));\n    CHK(mbedtls_hmac_drbg_reseed(&ctx, NULL, 0));\n    CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));\n    CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));\n    CHK(memcmp(buf, result_nopr, OUTPUT_LEN));\n    mbedtls_hmac_drbg_free(&ctx);\n\n    mbedtls_hmac_drbg_free(&ctx);\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_HMAC_DRBG_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/lmots.c",
    "content": "/*\n * The LM-OTS one-time public-key signature scheme\n *\n * Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n *  The following sources were referenced in the design of this implementation\n *  of the LM-OTS algorithm:\n *\n *  [1] IETF RFC8554\n *      D. McGrew, M. Curcio, S.Fluhrer\n *      https://datatracker.ietf.org/doc/html/rfc8554\n *\n *  [2] NIST Special Publication 800-208\n *      David A. Cooper et. al.\n *      https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_LMS_C)\n\n#include <string.h>\n\n#include \"lmots.h\"\n\n#include \"mbedtls/lms.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n#include \"psa_util_internal.h\"\n\n#include \"psa/crypto.h\"\n\n/* Define a local translating function to save code size by not using too many\n * arguments in each translating place. */\nstatic int local_err_translation(psa_status_t status)\n{\n    return psa_status_to_mbedtls(status, psa_to_lms_errors,\n                                 ARRAY_LENGTH(psa_to_lms_errors),\n                                 psa_generic_status_to_mbedtls);\n}\n#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)\n\n#define PUBLIC_KEY_TYPE_OFFSET     (0)\n#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \\\n                                    MBEDTLS_LMOTS_TYPE_LEN)\n#define PUBLIC_KEY_Q_LEAF_ID_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \\\n                                     MBEDTLS_LMOTS_I_KEY_ID_LEN)\n#define PUBLIC_KEY_KEY_HASH_OFFSET (PUBLIC_KEY_Q_LEAF_ID_OFFSET + \\\n                                    MBEDTLS_LMOTS_Q_LEAF_ID_LEN)\n\n/* We only support parameter sets that use 8-bit digits, as it does not require\n * translation logic between digits and bytes */\n#define W_WINTERNITZ_PARAMETER (8u)\n#define CHECKSUM_LEN           (2)\n#define I_DIGIT_IDX_LEN        (2)\n#define J_HASH_IDX_LEN         (1)\n#define D_CONST_LEN            (2)\n\n#define DIGIT_MAX_VALUE        ((1u << W_WINTERNITZ_PARAMETER) - 1u)\n\n#define D_CONST_LEN            (2)\nstatic const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = { 0x80, 0x80 };\nstatic const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = { 0x81, 0x81 };\n\n#if defined(MBEDTLS_TEST_HOOKS)\nint (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *) = NULL;\n#endif /* defined(MBEDTLS_TEST_HOOKS) */\n\n/* Calculate the checksum digits that are appended to the end of the LMOTS digit\n * string. See NIST SP800-208 section 3.1 or RFC8554 Algorithm 2 for details of\n * the checksum algorithm.\n *\n *  params              The LMOTS parameter set, I and q values which\n *                      describe the key being used.\n *\n *  digest              The digit string to create the digest from. As\n *                      this does not contain a checksum, it is the same\n *                      size as a hash output.\n */\nstatic unsigned short lmots_checksum_calculate(const mbedtls_lmots_parameters_t *params,\n                                               const unsigned char *digest)\n{\n    size_t idx;\n    unsigned sum = 0;\n\n    for (idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN(params->type); idx++) {\n        sum += DIGIT_MAX_VALUE - digest[idx];\n    }\n\n    return sum;\n}\n\n/* Create the string of digest digits (in the base determined by the Winternitz\n * parameter with the checksum appended to the end (Q || cksm(Q)). See NIST\n * SP800-208 section 3.1 or RFC8554 Algorithm 3 step 5 (also used in Algorithm\n * 4b step 3) for details.\n *\n *  params              The LMOTS parameter set, I and q values which\n *                      describe the key being used.\n *\n *  msg                 The message that will be hashed to create the\n *                      digest.\n *\n *  msg_size            The size of the message.\n *\n *  C_random_value      The random value that will be combined with the\n *                      message digest. This is always the same size as a\n *                      hash output for whichever hash algorithm is\n *                      determined by the parameter set.\n *\n *  output              An output containing the digit string (+\n *                      checksum) of length P digits (in the case of\n *                      MBEDTLS_LMOTS_SHA256_N32_W8, this means it is of\n *                      size P bytes).\n */\nstatic int create_digit_array_with_checksum(const mbedtls_lmots_parameters_t *params,\n                                            const unsigned char *msg,\n                                            size_t msg_len,\n                                            const unsigned char *C_random_value,\n                                            unsigned char *out)\n{\n    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t output_hash_len;\n    unsigned short checksum;\n\n    status = psa_hash_setup(&op, PSA_ALG_SHA_256);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op, params->I_key_identifier,\n                             MBEDTLS_LMOTS_I_KEY_ID_LEN);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op, params->q_leaf_identifier,\n                             MBEDTLS_LMOTS_Q_LEAF_ID_LEN);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op, D_MESSAGE_CONSTANT_BYTES, D_CONST_LEN);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op, C_random_value,\n                             MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(params->type));\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op, msg, msg_len);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_finish(&op, out,\n                             MBEDTLS_LMOTS_N_HASH_LEN(params->type),\n                             &output_hash_len);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    checksum = lmots_checksum_calculate(params, out);\n    MBEDTLS_PUT_UINT16_BE(checksum, out, MBEDTLS_LMOTS_N_HASH_LEN(params->type));\n\nexit:\n    psa_hash_abort(&op);\n\n    return PSA_TO_MBEDTLS_ERR(status);\n}\n\n/* Hash each element of the string of digits (+ checksum), producing a hash\n * output for each element. This is used in several places (by varying the\n * hash_idx_min/max_values) in order to calculate a public key from a private\n * key (RFC8554 Algorithm 1 step 4), in order to sign a message (RFC8554\n * Algorithm 3 step 5), and to calculate a public key candidate from a\n * signature and message (RFC8554 Algorithm 4b step 3).\n *\n *  params              The LMOTS parameter set, I and q values which\n *                      describe the key being used.\n *\n *  x_digit_array       The array of digits (of size P, 34 in the case of\n *                      MBEDTLS_LMOTS_SHA256_N32_W8).\n *\n *  hash_idx_min_values An array of the starting values of the j iterator\n *                      for each of the members of the digit array. If\n *                      this value in NULL, then all iterators will start\n *                      at 0.\n *\n *  hash_idx_max_values An array of the upper bound values of the j\n *                      iterator for each of the members of the digit\n *                      array. If this value in NULL, then iterator is\n *                      bounded to be less than 2^w - 1 (255 in the case\n *                      of MBEDTLS_LMOTS_SHA256_N32_W8)\n *\n *  output              An array containing a hash output for each member\n *                      of the digit string P. In the case of\n *                      MBEDTLS_LMOTS_SHA256_N32_W8, this is of size 32 *\n *                      34.\n */\nstatic int hash_digit_array(const mbedtls_lmots_parameters_t *params,\n                            const unsigned char *x_digit_array,\n                            const unsigned char *hash_idx_min_values,\n                            const unsigned char *hash_idx_max_values,\n                            unsigned char *output)\n{\n    unsigned int i_digit_idx;\n    unsigned char i_digit_idx_bytes[I_DIGIT_IDX_LEN];\n    unsigned int j_hash_idx;\n    unsigned char j_hash_idx_bytes[J_HASH_IDX_LEN];\n    unsigned int j_hash_idx_min;\n    unsigned int j_hash_idx_max;\n    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t output_hash_len;\n    unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX];\n\n    for (i_digit_idx = 0;\n         i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type);\n         i_digit_idx++) {\n\n        memcpy(tmp_hash,\n               &x_digit_array[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)],\n               MBEDTLS_LMOTS_N_HASH_LEN(params->type));\n\n        j_hash_idx_min = hash_idx_min_values != NULL ?\n                         hash_idx_min_values[i_digit_idx] : 0;\n        j_hash_idx_max = hash_idx_max_values != NULL ?\n                         hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE;\n\n        for (j_hash_idx = j_hash_idx_min;\n             j_hash_idx < j_hash_idx_max;\n             j_hash_idx++) {\n            status = psa_hash_setup(&op, PSA_ALG_SHA_256);\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n\n            status = psa_hash_update(&op,\n                                     params->I_key_identifier,\n                                     MBEDTLS_LMOTS_I_KEY_ID_LEN);\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n\n            status = psa_hash_update(&op,\n                                     params->q_leaf_identifier,\n                                     MBEDTLS_LMOTS_Q_LEAF_ID_LEN);\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n\n            MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0);\n            status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN);\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n\n            j_hash_idx_bytes[0] = (uint8_t) j_hash_idx;\n            status = psa_hash_update(&op, j_hash_idx_bytes, J_HASH_IDX_LEN);\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n\n            status = psa_hash_update(&op, tmp_hash,\n                                     MBEDTLS_LMOTS_N_HASH_LEN(params->type));\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n\n            status = psa_hash_finish(&op, tmp_hash, sizeof(tmp_hash),\n                                     &output_hash_len);\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n\n            psa_hash_abort(&op);\n        }\n\n        memcpy(&output[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)],\n               tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type));\n    }\n\nexit:\n    psa_hash_abort(&op);\n    mbedtls_platform_zeroize(tmp_hash, sizeof(tmp_hash));\n\n    return PSA_TO_MBEDTLS_ERR(status);\n}\n\n/* Combine the hashes of the digit array into a public key. This is used in\n * in order to calculate a public key from a private key (RFC8554 Algorithm 1\n * step 4), and to calculate a public key candidate from a signature and message\n * (RFC8554 Algorithm 4b step 3).\n *\n *  params           The LMOTS parameter set, I and q values which describe\n *                   the key being used.\n *  y_hashed_digits  The array of hashes, one hash for each digit of the\n *                   symbol array (which is of size P, 34 in the case of\n *                   MBEDTLS_LMOTS_SHA256_N32_W8)\n *\n *  pub_key          The output public key (or candidate public key in\n *                   case this is being run as part of signature\n *                   verification), in the form of a hash output.\n */\nstatic int public_key_from_hashed_digit_array(const mbedtls_lmots_parameters_t *params,\n                                              const unsigned char *y_hashed_digits,\n                                              unsigned char *pub_key)\n{\n    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t output_hash_len;\n\n    status = psa_hash_setup(&op, PSA_ALG_SHA_256);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op,\n                             params->I_key_identifier,\n                             MBEDTLS_LMOTS_I_KEY_ID_LEN);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op, params->q_leaf_identifier,\n                             MBEDTLS_LMOTS_Q_LEAF_ID_LEN);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op, D_PUBLIC_CONSTANT_BYTES, D_CONST_LEN);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op, y_hashed_digits,\n                             MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type) *\n                             MBEDTLS_LMOTS_N_HASH_LEN(params->type));\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_finish(&op, pub_key,\n                             MBEDTLS_LMOTS_N_HASH_LEN(params->type),\n                             &output_hash_len);\n    if (status != PSA_SUCCESS) {\n\nexit:\n        psa_hash_abort(&op);\n    }\n\n    return PSA_TO_MBEDTLS_ERR(status);\n}\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\nint mbedtls_lms_error_from_psa(psa_status_t status)\n{\n    switch (status) {\n        case PSA_SUCCESS:\n            return 0;\n        case PSA_ERROR_HARDWARE_FAILURE:\n            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;\n        case PSA_ERROR_NOT_SUPPORTED:\n            return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;\n        case PSA_ERROR_BUFFER_TOO_SMALL:\n            return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;\n        case PSA_ERROR_INVALID_ARGUMENT:\n            return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n        default:\n            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;\n    }\n}\n#endif /* !MBEDTLS_DEPRECATED_REMOVED */\n\nvoid mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx)\n{\n    memset(ctx, 0, sizeof(*ctx));\n}\n\nvoid mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(*ctx));\n}\n\nint mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx,\n                                    const unsigned char *key, size_t key_len)\n{\n    if (key_len < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    uint32_t type = MBEDTLS_GET_UINT32_BE(key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET);\n    if (type != (uint32_t) MBEDTLS_LMOTS_SHA256_N32_W8) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n    ctx->params.type = (mbedtls_lmots_algorithm_type_t) type;\n\n    if (key_len != MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    memcpy(ctx->params.I_key_identifier,\n           key + PUBLIC_KEY_I_KEY_ID_OFFSET,\n           MBEDTLS_LMOTS_I_KEY_ID_LEN);\n\n    memcpy(ctx->params.q_leaf_identifier,\n           key + PUBLIC_KEY_Q_LEAF_ID_OFFSET,\n           MBEDTLS_LMOTS_Q_LEAF_ID_LEN);\n\n    memcpy(ctx->public_key,\n           key + PUBLIC_KEY_KEY_HASH_OFFSET,\n           MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));\n\n    ctx->have_public_key = 1;\n\n    return 0;\n}\n\nint mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx,\n                                    unsigned char *key, size_t key_size,\n                                    size_t *key_len)\n{\n    if (key_size < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) {\n        return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;\n    }\n\n    if (!ctx->have_public_key) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET);\n\n    memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET,\n           ctx->params.I_key_identifier,\n           MBEDTLS_LMOTS_I_KEY_ID_LEN);\n\n    memcpy(key + PUBLIC_KEY_Q_LEAF_ID_OFFSET,\n           ctx->params.q_leaf_identifier,\n           MBEDTLS_LMOTS_Q_LEAF_ID_LEN);\n\n    memcpy(key + PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key,\n           MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));\n\n    if (key_len != NULL) {\n        *key_len = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type);\n    }\n\n    return 0;\n}\n\nint mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params,\n                                                 const unsigned char  *msg,\n                                                 size_t msg_size,\n                                                 const unsigned char *sig,\n                                                 size_t sig_size,\n                                                 unsigned char *out,\n                                                 size_t out_size,\n                                                 size_t *out_len)\n{\n    unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX];\n    unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (msg == NULL && msg_size != 0) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (sig_size != MBEDTLS_LMOTS_SIG_LEN(params->type) ||\n        out_size < MBEDTLS_LMOTS_N_HASH_LEN(params->type)) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    ret = create_digit_array_with_checksum(params, msg, msg_size,\n                                           sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET,\n                                           tmp_digit_array);\n    if (ret) {\n        return ret;\n    }\n\n    ret = hash_digit_array(params,\n                           sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(params->type),\n                           tmp_digit_array, NULL, (unsigned char *) y_hashed_digits);\n    if (ret) {\n        return ret;\n    }\n\n    ret = public_key_from_hashed_digit_array(params,\n                                             (unsigned char *) y_hashed_digits,\n                                             out);\n    if (ret) {\n        return ret;\n    }\n\n    if (out_len != NULL) {\n        *out_len = MBEDTLS_LMOTS_N_HASH_LEN(params->type);\n    }\n\n    return 0;\n}\n\nint mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx,\n                         const unsigned char *msg, size_t msg_size,\n                         const unsigned char *sig, size_t sig_size)\n{\n    unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN_MAX];\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (msg == NULL && msg_size != 0) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (!ctx->have_public_key) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (ctx->params.type != MBEDTLS_LMOTS_SHA256_N32_W8) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (sig_size < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {\n        return MBEDTLS_ERR_LMS_VERIFY_FAILED;\n    }\n\n    if (MBEDTLS_GET_UINT32_BE(sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET) != MBEDTLS_LMOTS_SHA256_N32_W8) {\n        return MBEDTLS_ERR_LMS_VERIFY_FAILED;\n    }\n\n    ret = mbedtls_lmots_calculate_public_key_candidate(&ctx->params,\n                                                       msg, msg_size, sig, sig_size,\n                                                       Kc_public_key_candidate,\n                                                       MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type),\n                                                       NULL);\n    if (ret) {\n        return MBEDTLS_ERR_LMS_VERIFY_FAILED;\n    }\n\n    if (memcmp(&Kc_public_key_candidate, ctx->public_key,\n               sizeof(ctx->public_key))) {\n        return MBEDTLS_ERR_LMS_VERIFY_FAILED;\n    }\n\n    return 0;\n}\n\n#if defined(MBEDTLS_LMS_PRIVATE)\n\nvoid mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx)\n{\n    memset(ctx, 0, sizeof(*ctx));\n}\n\nvoid mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_platform_zeroize(ctx,\n                             sizeof(*ctx));\n}\n\nint mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx,\n                                       mbedtls_lmots_algorithm_type_t type,\n                                       const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN],\n                                       uint32_t q_leaf_identifier,\n                                       const unsigned char *seed,\n                                       size_t seed_size)\n{\n    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t output_hash_len;\n    unsigned int i_digit_idx;\n    unsigned char i_digit_idx_bytes[2];\n    unsigned char const_bytes[1] = { 0xFF };\n\n    if (ctx->have_private_key) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (type != MBEDTLS_LMOTS_SHA256_N32_W8) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    ctx->params.type = type;\n\n    memcpy(ctx->params.I_key_identifier,\n           I_key_identifier,\n           sizeof(ctx->params.I_key_identifier));\n\n    MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ctx->params.q_leaf_identifier, 0);\n\n    for (i_digit_idx = 0;\n         i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type);\n         i_digit_idx++) {\n        status = psa_hash_setup(&op, PSA_ALG_SHA_256);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n\n        status = psa_hash_update(&op,\n                                 ctx->params.I_key_identifier,\n                                 sizeof(ctx->params.I_key_identifier));\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n\n        status = psa_hash_update(&op,\n                                 ctx->params.q_leaf_identifier,\n                                 MBEDTLS_LMOTS_Q_LEAF_ID_LEN);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n\n        MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0);\n        status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n\n        status = psa_hash_update(&op, const_bytes, sizeof(const_bytes));\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n\n        status = psa_hash_update(&op, seed, seed_size);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n\n        status = psa_hash_finish(&op,\n                                 ctx->private_key[i_digit_idx],\n                                 MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type),\n                                 &output_hash_len);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n\n        psa_hash_abort(&op);\n    }\n\n    ctx->have_private_key = 1;\n\nexit:\n    psa_hash_abort(&op);\n\n    return PSA_TO_MBEDTLS_ERR(status);\n}\n\nint mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx,\n                                       const mbedtls_lmots_private_t *priv_ctx)\n{\n    unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* Check that a private key is loaded */\n    if (!priv_ctx->have_private_key) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    ret = hash_digit_array(&priv_ctx->params,\n                           (unsigned char *) priv_ctx->private_key, NULL,\n                           NULL, (unsigned char *) y_hashed_digits);\n    if (ret) {\n        goto exit;\n    }\n\n    ret = public_key_from_hashed_digit_array(&priv_ctx->params,\n                                             (unsigned char *) y_hashed_digits,\n                                             ctx->public_key);\n    if (ret) {\n        goto exit;\n    }\n\n    memcpy(&ctx->params, &priv_ctx->params,\n           sizeof(ctx->params));\n\n    ctx->have_public_key = 1;\n\nexit:\n    mbedtls_platform_zeroize(y_hashed_digits, sizeof(y_hashed_digits));\n\n    return ret;\n}\n\nint mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx,\n                       int (*f_rng)(void *, unsigned char *, size_t),\n                       void *p_rng, const unsigned char *msg, size_t msg_size,\n                       unsigned char *sig, size_t sig_size, size_t *sig_len)\n{\n    unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX];\n    /* Create a temporary buffer to prepare the signature in. This allows us to\n     * finish creating a signature (ensuring the process doesn't fail), and then\n     * erase the private key **before** writing any data into the sig parameter\n     * buffer. If data were directly written into the sig buffer, it might leak\n     * a partial signature on failure, which effectively compromises the private\n     * key.\n     */\n    unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];\n    unsigned char tmp_c_random[MBEDTLS_LMOTS_N_HASH_LEN_MAX];\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (msg == NULL && msg_size != 0) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (sig_size < MBEDTLS_LMOTS_SIG_LEN(ctx->params.type)) {\n        return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;\n    }\n\n    /* Check that a private key is loaded */\n    if (!ctx->have_private_key) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    ret = f_rng(p_rng, tmp_c_random,\n                MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));\n    if (ret) {\n        return ret;\n    }\n\n    ret = create_digit_array_with_checksum(&ctx->params,\n                                           msg, msg_size,\n                                           tmp_c_random,\n                                           tmp_digit_array);\n    if (ret) {\n        goto exit;\n    }\n\n    ret = hash_digit_array(&ctx->params, (unsigned char *) ctx->private_key,\n                           NULL, tmp_digit_array, (unsigned char *) tmp_sig);\n    if (ret) {\n        goto exit;\n    }\n\n    MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET);\n\n    /* Test hook to check if sig is being written to before we invalidate the\n     * private key.\n     */\n#if defined(MBEDTLS_TEST_HOOKS)\n    if (mbedtls_lmots_sign_private_key_invalidated_hook != NULL) {\n        ret = (*mbedtls_lmots_sign_private_key_invalidated_hook)(sig);\n        if (ret != 0) {\n            return ret;\n        }\n    }\n#endif /* defined(MBEDTLS_TEST_HOOKS) */\n\n    /* We've got a valid signature now, so it's time to make sure the private\n     * key can't be reused.\n     */\n    ctx->have_private_key = 0;\n    mbedtls_platform_zeroize(ctx->private_key,\n                             sizeof(ctx->private_key));\n\n    memcpy(sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_c_random,\n           MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(ctx->params.type));\n\n    memcpy(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(ctx->params.type), tmp_sig,\n           MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type)\n           * MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));\n\n    if (sig_len != NULL) {\n        *sig_len = MBEDTLS_LMOTS_SIG_LEN(ctx->params.type);\n    }\n\n    ret = 0;\n\nexit:\n    mbedtls_platform_zeroize(tmp_digit_array, sizeof(tmp_digit_array));\n    mbedtls_platform_zeroize(tmp_sig, sizeof(tmp_sig));\n\n    return ret;\n}\n\n#endif /* defined(MBEDTLS_LMS_PRIVATE) */\n#endif /* defined(MBEDTLS_LMS_C) */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/lmots.h",
    "content": "/**\n * \\file lmots.h\n *\n * \\brief This file provides an API for the LM-OTS post-quantum-safe one-time\n *        public-key signature scheme as defined in RFC8554 and NIST.SP.200-208.\n *        This implementation currently only supports a single parameter set\n *        MBEDTLS_LMOTS_SHA256_N32_W8 in order to reduce complexity.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_LMOTS_H\n#define MBEDTLS_LMOTS_H\n\n#include \"mbedtls/build_info.h\"\n\n#include \"psa/crypto.h\"\n\n#include \"mbedtls/lms.h\"\n\n#include <stdint.h>\n#include <stddef.h>\n\n\n#define MBEDTLS_LMOTS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \\\n                                            MBEDTLS_LMOTS_I_KEY_ID_LEN + \\\n                                            MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \\\n                                            MBEDTLS_LMOTS_N_HASH_LEN(type))\n\n#define MBEDTLS_LMOTS_SIG_TYPE_OFFSET       (0)\n#define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + \\\n                                           MBEDTLS_LMOTS_TYPE_LEN)\n#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(type) (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + \\\n                                                  MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type))\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n#if defined(MBEDTLS_TEST_HOOKS)\nextern int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *);\n#endif /* defined(MBEDTLS_TEST_HOOKS) */\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n/**\n * \\brief                    This function converts a \\ref psa_status_t to a\n *                           low-level LMS error code.\n *\n * \\param status             The psa_status_t to convert\n *\n * \\return                   The corresponding LMS error code.\n */\nint MBEDTLS_DEPRECATED mbedtls_lms_error_from_psa(psa_status_t status);\n#endif\n\n/**\n * \\brief                    This function initializes a public LMOTS context\n *\n * \\param ctx                The uninitialized LMOTS context that will then be\n *                           initialized.\n */\nvoid mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx);\n\n/**\n * \\brief                    This function uninitializes a public LMOTS context\n *\n * \\param ctx                The initialized LMOTS context that will then be\n *                           uninitialized.\n */\nvoid mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx);\n\n/**\n * \\brief                    This function imports an LMOTS public key into a\n *                           LMOTS context.\n *\n * \\note                     Before this function is called, the context must\n *                           have been initialized.\n *\n * \\note                     See IETF RFC8554 for details of the encoding of\n *                           this public key.\n *\n * \\param ctx                The initialized LMOTS context store the key in.\n * \\param key                The buffer from which the key will be read.\n *                           #MBEDTLS_LMOTS_PUBLIC_KEY_LEN bytes will be read\n *                           from this.\n *\n * \\return         \\c 0 on success.\n * \\return         A non-zero error code on failure.\n */\nint mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx,\n                                    const unsigned char *key, size_t key_size);\n\n/**\n * \\brief                    This function exports an LMOTS public key from a\n *                           LMOTS context that already contains a public key.\n *\n * \\note                     Before this function is called, the context must\n *                           have been initialized and the context must contain\n *                           a public key.\n *\n * \\note                     See IETF RFC8554 for details of the encoding of\n *                           this public key.\n *\n * \\param ctx                The initialized LMOTS context that contains the\n *                           public key.\n * \\param key                The buffer into which the key will be output. Must\n *                           be at least #MBEDTLS_LMOTS_PUBLIC_KEY_LEN in size.\n *\n * \\return         \\c 0 on success.\n * \\return         A non-zero error code on failure.\n */\nint mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx,\n                                    unsigned char *key, size_t key_size,\n                                    size_t *key_len);\n\n/**\n * \\brief                    This function creates a candidate public key from\n *                           an LMOTS signature. This can then be compared to\n *                           the real public key to determine the validity of\n *                           the signature.\n *\n * \\note                     This function is exposed publicly to be used in LMS\n *                           signature verification, it is expected that\n *                           mbedtls_lmots_verify will be used for LMOTS\n *                           signature verification.\n *\n * \\param params             The LMOTS parameter set, q and I values as an\n *                           mbedtls_lmots_parameters_t struct.\n * \\param msg                The buffer from which the message will be read.\n * \\param msg_size           The size of the message that will be read.\n * \\param sig                The buffer from which the signature will be read.\n *                           #MBEDTLS_LMOTS_SIG_LEN bytes will be read from\n *                           this.\n * \\param out                The buffer where the candidate public key will be\n *                           stored. Must be at least #MBEDTLS_LMOTS_N_HASH_LEN\n *                           bytes in size.\n *\n * \\return         \\c 0 on success.\n * \\return         A non-zero error code on failure.\n */\nint mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params,\n                                                 const unsigned char *msg,\n                                                 size_t msg_size,\n                                                 const unsigned char *sig,\n                                                 size_t sig_size,\n                                                 unsigned char *out,\n                                                 size_t out_size,\n                                                 size_t *out_len);\n\n/**\n * \\brief                    This function verifies a LMOTS signature, using a\n *                           LMOTS context that contains a public key.\n *\n * \\warning                  This function is **not intended for use in\n *                           production**, due to as-yet unsolved problems with\n *                           handling stateful keys. The API for this function\n *                           may change considerably in future versions.\n *\n * \\note                     Before this function is called, the context must\n *                           have been initialized and must contain a public key\n *                           (either by import or calculation from a private\n *                           key).\n *\n * \\param ctx                The initialized LMOTS context from which the public\n *                           key will be read.\n * \\param msg                The buffer from which the message will be read.\n * \\param msg_size           The size of the message that will be read.\n * \\param sig                The buf from which the signature will be read.\n *                           #MBEDTLS_LMOTS_SIG_LEN bytes will be read from\n *                           this.\n *\n * \\return         \\c 0 on successful verification.\n * \\return         A non-zero error code on failure.\n */\nint mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx,\n                         const unsigned char *msg,\n                         size_t msg_size, const unsigned char *sig,\n                         size_t sig_size);\n\n#if defined(MBEDTLS_LMS_PRIVATE)\n\n/**\n * \\brief                    This function initializes a private LMOTS context\n *\n * \\param ctx                The uninitialized LMOTS context that will then be\n *                           initialized.\n */\nvoid mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx);\n\n/**\n * \\brief                    This function uninitializes a private LMOTS context\n *\n * \\param ctx                The initialized LMOTS context that will then be\n *                           uninitialized.\n */\nvoid mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx);\n\n/**\n * \\brief                    This function calculates an LMOTS private key, and\n *                           stores in into an LMOTS context.\n *\n * \\warning                  This function is **not intended for use in\n *                           production**, due to as-yet unsolved problems with\n *                           handling stateful keys. The API for this function\n *                           may change considerably in future versions.\n *\n * \\note                     The seed must have at least 256 bits of entropy.\n *\n * \\param ctx                The initialized LMOTS context to generate the key\n *                           into.\n * \\param I_key_identifier   The key identifier of the key, as a 16-byte string.\n * \\param q_leaf_identifier  The leaf identifier of key. If this LMOTS key is\n *                           not being used as part of an LMS key, this should\n *                           be set to 0.\n * \\param seed               The seed used to deterministically generate the\n *                           key.\n * \\param seed_size          The length of the seed.\n *\n * \\return         \\c 0 on success.\n * \\return         A non-zero error code on failure.\n */\nint mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx,\n                                       mbedtls_lmots_algorithm_type_t type,\n                                       const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN],\n                                       uint32_t q_leaf_identifier,\n                                       const unsigned char *seed,\n                                       size_t seed_size);\n\n/**\n * \\brief                    This function generates an LMOTS public key from a\n *                           LMOTS context that already contains a private key.\n *\n * \\note                     Before this function is called, the context must\n *                           have been initialized and the context must contain\n *                           a private key.\n *\n * \\param ctx                The initialized LMOTS context to generate the key\n *                           from and store it into.\n *\n * \\return         \\c 0 on success.\n * \\return         A non-zero error code on failure.\n */\nint mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx,\n                                       const mbedtls_lmots_private_t *priv_ctx);\n\n/**\n * \\brief                    This function creates a LMOTS signature, using a\n *                           LMOTS context that contains a private key.\n *\n * \\note                     Before this function is called, the context must\n *                           have been initialized and must contain a private\n *                           key.\n *\n * \\note                     LMOTS private keys can only be used once, otherwise\n *                           attackers may be able to create forged signatures.\n *                           If the signing operation is successful, the private\n *                           key in the context will be erased, and no further\n *                           signing will be possible until another private key\n *                           is loaded\n *\n * \\param ctx                The initialized LMOTS context from which the\n *                           private key will be read.\n * \\param f_rng              The RNG function to be used for signature\n *                           generation.\n * \\param p_rng              The RNG context to be passed to f_rng\n * \\param msg                The buffer from which the message will be read.\n * \\param msg_size           The size of the message that will be read.\n * \\param sig                The buf into which the signature will be stored.\n *                           Must be at least #MBEDTLS_LMOTS_SIG_LEN in size.\n *\n * \\return         \\c 0 on success.\n * \\return         A non-zero error code on failure.\n */\nint mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx,\n                       int (*f_rng)(void *, unsigned char *, size_t),\n                       void *p_rng, const unsigned char *msg, size_t msg_size,\n                       unsigned char *sig, size_t sig_size, size_t *sig_len);\n\n#endif /* defined(MBEDTLS_LMS_PRIVATE) */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_LMOTS_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/lms.c",
    "content": "/*\n *  The LMS stateful-hash public-key signature scheme\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n *  The following sources were referenced in the design of this implementation\n *  of the LMS algorithm:\n *\n *  [1] IETF RFC8554\n *      D. McGrew, M. Curcio, S.Fluhrer\n *      https://datatracker.ietf.org/doc/html/rfc8554\n *\n *  [2] NIST Special Publication 800-208\n *      David A. Cooper et. al.\n *      https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_LMS_C)\n\n#include <string.h>\n\n#include \"lmots.h\"\n\n#include \"psa/crypto.h\"\n#include \"psa_util_internal.h\"\n#include \"mbedtls/lms.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include \"mbedtls/platform.h\"\n\n/* Define a local translating function to save code size by not using too many\n * arguments in each translating place. */\nstatic int local_err_translation(psa_status_t status)\n{\n    return psa_status_to_mbedtls(status, psa_to_lms_errors,\n                                 ARRAY_LENGTH(psa_to_lms_errors),\n                                 psa_generic_status_to_mbedtls);\n}\n#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)\n\n#define SIG_Q_LEAF_ID_OFFSET     (0)\n#define SIG_OTS_SIG_OFFSET       (SIG_Q_LEAF_ID_OFFSET + \\\n                                  MBEDTLS_LMOTS_Q_LEAF_ID_LEN)\n#define SIG_TYPE_OFFSET(otstype) (SIG_OTS_SIG_OFFSET   + \\\n                                  MBEDTLS_LMOTS_SIG_LEN(otstype))\n#define SIG_PATH_OFFSET(otstype) (SIG_TYPE_OFFSET(otstype) + \\\n                                  MBEDTLS_LMS_TYPE_LEN)\n\n#define PUBLIC_KEY_TYPE_OFFSET      (0)\n#define PUBLIC_KEY_OTSTYPE_OFFSET   (PUBLIC_KEY_TYPE_OFFSET + \\\n                                     MBEDTLS_LMS_TYPE_LEN)\n#define PUBLIC_KEY_I_KEY_ID_OFFSET  (PUBLIC_KEY_OTSTYPE_OFFSET  + \\\n                                     MBEDTLS_LMOTS_TYPE_LEN)\n#define PUBLIC_KEY_ROOT_NODE_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \\\n                                     MBEDTLS_LMOTS_I_KEY_ID_LEN)\n\n\n/* Currently only support H=10 */\n#define H_TREE_HEIGHT_MAX                  10\n#define MERKLE_TREE_NODE_AM(type)          ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u))\n#define MERKLE_TREE_LEAF_NODE_AM(type)     ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))\n#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((unsigned int) \\\n                                            (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type)))\n\n#define D_CONST_LEN           (2)\nstatic const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = { 0x82, 0x82 };\nstatic const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = { 0x83, 0x83 };\n\n\n/* Calculate the value of a leaf node of the Merkle tree (which is a hash of a\n * public key and some other parameters like the leaf index). This function\n * implements RFC8554 section 5.3, in the case where r >= 2^h.\n *\n *  params              The LMS parameter set, the underlying LMOTS\n *                      parameter set, and I value which describe the key\n *                      being used.\n *\n *  pub_key             The public key of the private whose index\n *                      corresponds to the index of this leaf node. This\n *                      is a hash output.\n *\n *  r_node_idx          The index of this node in the Merkle tree. Note\n *                      that the root node of the Merkle tree is\n *                      1-indexed.\n *\n *  out                 The output node value, which is a hash output.\n */\nstatic int create_merkle_leaf_value(const mbedtls_lms_parameters_t *params,\n                                    unsigned char *pub_key,\n                                    unsigned int r_node_idx,\n                                    unsigned char *out)\n{\n    psa_hash_operation_t op;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t output_hash_len;\n    unsigned char r_node_idx_bytes[4];\n\n    /* Always zeroize the output buffer because it may contain data from the previous invocation */\n    memset(out, 0, MBEDTLS_LMS_M_NODE_BYTES(params->type));\n\n    op = psa_hash_operation_init();\n    status = psa_hash_setup(&op, PSA_ALG_SHA_256);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op, params->I_key_identifier,\n                             MBEDTLS_LMOTS_I_KEY_ID_LEN);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0);\n    status = psa_hash_update(&op, r_node_idx_bytes, 4);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op, D_LEAF_CONSTANT_BYTES, D_CONST_LEN);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op, pub_key,\n                             MBEDTLS_LMOTS_N_HASH_LEN(params->otstype));\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type),\n                             &output_hash_len);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\nexit:\n    psa_hash_abort(&op);\n\n    return PSA_TO_MBEDTLS_ERR(status);\n}\n\n/* Calculate the value of an internal node of the Merkle tree (which is a hash\n * of a public key and some other parameters like the node index). This function\n * implements RFC8554 section 5.3, in the case where r < 2^h.\n *\n *  params              The LMS parameter set, the underlying LMOTS\n *                      parameter set, and I value which describe the key\n *                      being used.\n *\n *  left_node           The value of the child of this node which is on\n *                      the left-hand side. As with all nodes on the\n *                      Merkle tree, this is a hash output.\n *\n *  right_node          The value of the child of this node which is on\n *                      the right-hand side. As with all nodes on the\n *                      Merkle tree, this is a hash output.\n *\n *  r_node_idx          The index of this node in the Merkle tree. Note\n *                      that the root node of the Merkle tree is\n *                      1-indexed.\n *\n *  out                 The output node value, which is a hash output.\n */\nstatic int create_merkle_internal_value(const mbedtls_lms_parameters_t *params,\n                                        const unsigned char *left_node,\n                                        const unsigned char *right_node,\n                                        unsigned int r_node_idx,\n                                        unsigned char *out)\n{\n    psa_hash_operation_t op;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t output_hash_len;\n    unsigned char r_node_idx_bytes[4];\n\n    op = psa_hash_operation_init();\n    status = psa_hash_setup(&op, PSA_ALG_SHA_256);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op, params->I_key_identifier,\n                             MBEDTLS_LMOTS_I_KEY_ID_LEN);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0);\n    status = psa_hash_update(&op, r_node_idx_bytes, 4);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op, D_INTR_CONSTANT_BYTES, D_CONST_LEN);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op, left_node,\n                             MBEDTLS_LMS_M_NODE_BYTES(params->type));\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&op, right_node,\n                             MBEDTLS_LMS_M_NODE_BYTES(params->type));\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type),\n                             &output_hash_len);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\nexit:\n    psa_hash_abort(&op);\n\n    return PSA_TO_MBEDTLS_ERR(status);\n}\n\nvoid mbedtls_lms_public_init(mbedtls_lms_public_t *ctx)\n{\n    memset(ctx, 0, sizeof(*ctx));\n}\n\nvoid mbedtls_lms_public_free(mbedtls_lms_public_t *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(*ctx));\n}\n\nint mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx,\n                                  const unsigned char *key, size_t key_size)\n{\n    if (key_size < 4) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    uint32_t type = MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_TYPE_OFFSET);\n    if (type != (uint32_t) MBEDTLS_LMS_SHA256_M32_H10) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n    ctx->params.type = (mbedtls_lms_algorithm_type_t) type;\n\n    if (key_size != MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    uint32_t otstype = MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_OTSTYPE_OFFSET);\n    if (otstype != (uint32_t) MBEDTLS_LMOTS_SHA256_N32_W8) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n    ctx->params.otstype = (mbedtls_lmots_algorithm_type_t) otstype;\n\n    memcpy(ctx->params.I_key_identifier,\n           key + PUBLIC_KEY_I_KEY_ID_OFFSET,\n           MBEDTLS_LMOTS_I_KEY_ID_LEN);\n    memcpy(ctx->T_1_pub_key, key + PUBLIC_KEY_ROOT_NODE_OFFSET,\n           MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type));\n\n    ctx->have_public_key = 1;\n\n    return 0;\n}\n\nint mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx,\n                                  unsigned char *key,\n                                  size_t key_size, size_t *key_len)\n{\n    if (key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) {\n        return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;\n    }\n\n    if (!ctx->have_public_key) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, PUBLIC_KEY_TYPE_OFFSET);\n    MBEDTLS_PUT_UINT32_BE(ctx->params.otstype, key, PUBLIC_KEY_OTSTYPE_OFFSET);\n    memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET,\n           ctx->params.I_key_identifier,\n           MBEDTLS_LMOTS_I_KEY_ID_LEN);\n    memcpy(key +PUBLIC_KEY_ROOT_NODE_OFFSET,\n           ctx->T_1_pub_key,\n           MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type));\n\n    if (key_len != NULL) {\n        *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type);\n    }\n\n    return 0;\n}\n\nint mbedtls_lms_verify(const mbedtls_lms_public_t *ctx,\n                       const unsigned char *msg, size_t msg_size,\n                       const unsigned char *sig, size_t sig_size)\n{\n    unsigned int q_leaf_identifier;\n    unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN_MAX];\n    unsigned char Tc_candidate_root_node[MBEDTLS_LMS_M_NODE_BYTES_MAX];\n    unsigned int height;\n    unsigned int curr_node_id;\n    unsigned int parent_node_id;\n    const unsigned char *left_node;\n    const unsigned char *right_node;\n    mbedtls_lmots_parameters_t ots_params;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (!ctx->have_public_key) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (ctx->params.type\n        != MBEDTLS_LMS_SHA256_M32_H10) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (ctx->params.otstype\n        != MBEDTLS_LMOTS_SHA256_N32_W8) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (sig_size != MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) {\n        return MBEDTLS_ERR_LMS_VERIFY_FAILED;\n    }\n\n    if (sig_size < SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {\n        return MBEDTLS_ERR_LMS_VERIFY_FAILED;\n    }\n\n    if (MBEDTLS_GET_UINT32_BE(sig, SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET)\n        != MBEDTLS_LMOTS_SHA256_N32_W8) {\n        return MBEDTLS_ERR_LMS_VERIFY_FAILED;\n    }\n\n    if (sig_size < SIG_TYPE_OFFSET(ctx->params.otstype) + MBEDTLS_LMS_TYPE_LEN) {\n        return MBEDTLS_ERR_LMS_VERIFY_FAILED;\n    }\n\n    if (MBEDTLS_GET_UINT32_BE(sig, SIG_TYPE_OFFSET(ctx->params.otstype))\n        != MBEDTLS_LMS_SHA256_M32_H10) {\n        return MBEDTLS_ERR_LMS_VERIFY_FAILED;\n    }\n\n\n    q_leaf_identifier = MBEDTLS_GET_UINT32_BE(sig, SIG_Q_LEAF_ID_OFFSET);\n\n    if (q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) {\n        return MBEDTLS_ERR_LMS_VERIFY_FAILED;\n    }\n\n    memcpy(ots_params.I_key_identifier,\n           ctx->params.I_key_identifier,\n           MBEDTLS_LMOTS_I_KEY_ID_LEN);\n    MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ots_params.q_leaf_identifier, 0);\n    ots_params.type = ctx->params.otstype;\n\n    ret = mbedtls_lmots_calculate_public_key_candidate(&ots_params,\n                                                       msg,\n                                                       msg_size,\n                                                       sig + SIG_OTS_SIG_OFFSET,\n                                                       MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype),\n                                                       Kc_candidate_ots_pub_key,\n                                                       sizeof(Kc_candidate_ots_pub_key),\n                                                       NULL);\n    if (ret != 0) {\n        return MBEDTLS_ERR_LMS_VERIFY_FAILED;\n    }\n\n    ret = create_merkle_leaf_value(\n        &ctx->params,\n        Kc_candidate_ots_pub_key,\n        MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier,\n        Tc_candidate_root_node);\n\n    if (ret != 0) {\n        return MBEDTLS_ERR_LMS_VERIFY_FAILED;\n    }\n\n    curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) +\n                   q_leaf_identifier;\n\n    for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type);\n         height++) {\n        parent_node_id = curr_node_id / 2;\n\n        /* Left/right node ordering matters for the hash */\n        if (curr_node_id & 1) {\n            left_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) +\n                        height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);\n            right_node = Tc_candidate_root_node;\n        } else {\n            left_node = Tc_candidate_root_node;\n            right_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) +\n                         height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);\n        }\n\n        ret = create_merkle_internal_value(&ctx->params, left_node, right_node,\n                                           parent_node_id, Tc_candidate_root_node);\n        if (ret != 0) {\n            return MBEDTLS_ERR_LMS_VERIFY_FAILED;\n        }\n        curr_node_id /= 2;\n    }\n\n    if (memcmp(Tc_candidate_root_node, ctx->T_1_pub_key,\n               MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type))) {\n        return MBEDTLS_ERR_LMS_VERIFY_FAILED;\n    }\n\n    return 0;\n}\n\n#if defined(MBEDTLS_LMS_PRIVATE)\n\n/* Calculate a full Merkle tree based on a private key. This function\n * implements RFC8554 section 5.3, and is used to generate a public key (as the\n * public key is the root node of the Merkle tree).\n *\n *  ctx                 The LMS private context, containing a parameter\n *                      set and private key material consisting of both\n *                      public and private OTS.\n *\n *  tree                The output tree, which is 2^(H + 1) hash outputs.\n *                      In the case of H=10 we have 2048 tree nodes (of\n *                      which 1024 of them are leaf nodes). Note that\n *                      because the Merkle tree root is 1-indexed, the 0\n *                      index tree node is never used.\n */\nstatic int calculate_merkle_tree(const mbedtls_lms_private_t *ctx,\n                                 unsigned char *tree)\n{\n    unsigned int priv_key_idx;\n    unsigned int r_node_idx;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* First create the leaf nodes, in ascending order */\n    for (priv_key_idx = 0;\n         priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type);\n         priv_key_idx++) {\n        r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + priv_key_idx;\n\n        ret = create_merkle_leaf_value(&ctx->params,\n                                       ctx->ots_public_keys[priv_key_idx].public_key,\n                                       r_node_idx,\n                                       &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(\n                                                 ctx->params.type)]);\n        if (ret != 0) {\n            return ret;\n        }\n    }\n\n    /* Then the internal nodes, in reverse order so that we can guarantee the\n     * parent has been created */\n    for (r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) - 1;\n         r_node_idx > 0;\n         r_node_idx--) {\n        ret = create_merkle_internal_value(&ctx->params,\n                                           &tree[(r_node_idx * 2) *\n                                                 MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],\n                                           &tree[(r_node_idx * 2 + 1) *\n                                                 MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],\n                                           r_node_idx,\n                                           &tree[r_node_idx *\n                                                 MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)]);\n        if (ret != 0) {\n            return ret;\n        }\n    }\n\n    return 0;\n}\n\n/* Calculate a path from a leaf node of the Merkle tree to the root of the tree,\n * and return the full path. This function implements RFC8554 section 5.4.1, as\n * the Merkle path is the main component of an LMS signature.\n *\n *  ctx                 The LMS private context, containing a parameter\n *                      set and private key material consisting of both\n *                      public and private OTS.\n *\n *  leaf_node_id        Which leaf node to calculate the path from.\n *\n *  path                The output path, which is H hash outputs.\n */\nstatic int get_merkle_path(mbedtls_lms_private_t *ctx,\n                           unsigned int leaf_node_id,\n                           unsigned char *path)\n{\n    const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);\n    unsigned int curr_node_id = leaf_node_id;\n    unsigned int adjacent_node_id;\n    unsigned char *tree = NULL;\n    unsigned int height;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(ctx->params.type),\n                          node_bytes);\n    if (tree == NULL) {\n        return MBEDTLS_ERR_LMS_ALLOC_FAILED;\n    }\n\n    ret = calculate_merkle_tree(ctx, tree);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type);\n         height++) {\n        adjacent_node_id = curr_node_id ^ 1;\n\n        memcpy(&path[height * node_bytes],\n               &tree[adjacent_node_id * node_bytes], node_bytes);\n\n        curr_node_id >>= 1;\n    }\n\n    ret = 0;\n\nexit:\n    mbedtls_zeroize_and_free(tree, node_bytes *\n                             (size_t) MERKLE_TREE_NODE_AM(ctx->params.type));\n\n    return ret;\n}\n\nvoid mbedtls_lms_private_init(mbedtls_lms_private_t *ctx)\n{\n    memset(ctx, 0, sizeof(*ctx));\n}\n\nvoid mbedtls_lms_private_free(mbedtls_lms_private_t *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    unsigned int idx;\n\n    if (ctx->have_private_key) {\n        if (ctx->ots_private_keys != NULL) {\n            for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {\n                mbedtls_lmots_private_free(&ctx->ots_private_keys[idx]);\n            }\n        }\n\n        if (ctx->ots_public_keys != NULL) {\n            for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {\n                mbedtls_lmots_public_free(&ctx->ots_public_keys[idx]);\n            }\n        }\n\n        mbedtls_free(ctx->ots_private_keys);\n        mbedtls_free(ctx->ots_public_keys);\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(*ctx));\n}\n\n\nint mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx,\n                                     mbedtls_lms_algorithm_type_t type,\n                                     mbedtls_lmots_algorithm_type_t otstype,\n                                     int (*f_rng)(void *, unsigned char *, size_t),\n                                     void *p_rng, const unsigned char *seed,\n                                     size_t seed_size)\n{\n    unsigned int idx = 0;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (type != MBEDTLS_LMS_SHA256_M32_H10) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (ctx->have_private_key) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    ctx->params.type = type;\n    ctx->params.otstype = otstype;\n    ctx->have_private_key = 1;\n\n    ret = f_rng(p_rng,\n                ctx->params.I_key_identifier,\n                MBEDTLS_LMOTS_I_KEY_ID_LEN);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    /* Requires a cast to size_t to avoid an implicit cast warning on certain\n     * platforms (particularly Windows) */\n    ctx->ots_private_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type),\n                                           sizeof(*ctx->ots_private_keys));\n    if (ctx->ots_private_keys == NULL) {\n        ret = MBEDTLS_ERR_LMS_ALLOC_FAILED;\n        goto exit;\n    }\n\n    /* Requires a cast to size_t to avoid an implicit cast warning on certain\n     * platforms (particularly Windows) */\n    ctx->ots_public_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type),\n                                          sizeof(*ctx->ots_public_keys));\n    if (ctx->ots_public_keys == NULL) {\n        ret = MBEDTLS_ERR_LMS_ALLOC_FAILED;\n        goto exit;\n    }\n\n    for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {\n        mbedtls_lmots_private_init(&ctx->ots_private_keys[idx]);\n        mbedtls_lmots_public_init(&ctx->ots_public_keys[idx]);\n    }\n\n\n    for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {\n        ret = mbedtls_lmots_generate_private_key(&ctx->ots_private_keys[idx],\n                                                 otstype,\n                                                 ctx->params.I_key_identifier,\n                                                 idx, seed, seed_size);\n        if (ret != 0) {\n            goto exit;\n        }\n\n        ret = mbedtls_lmots_calculate_public_key(&ctx->ots_public_keys[idx],\n                                                 &ctx->ots_private_keys[idx]);\n        if (ret != 0) {\n            goto exit;\n        }\n    }\n\n    ctx->q_next_usable_key = 0;\n\nexit:\n    if (ret != 0) {\n        mbedtls_lms_private_free(ctx);\n    }\n\n    return ret;\n}\n\nint mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx,\n                                     const mbedtls_lms_private_t *priv_ctx)\n{\n    const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(priv_ctx->params.type);\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *tree = NULL;\n\n    if (!priv_ctx->have_private_key) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (priv_ctx->params.type\n        != MBEDTLS_LMS_SHA256_M32_H10) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (priv_ctx->params.otstype\n        != MBEDTLS_LMOTS_SHA256_N32_W8) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type),\n                          node_bytes);\n    if (tree == NULL) {\n        return MBEDTLS_ERR_LMS_ALLOC_FAILED;\n    }\n\n    memcpy(&ctx->params, &priv_ctx->params,\n           sizeof(mbedtls_lmots_parameters_t));\n\n    ret = calculate_merkle_tree(priv_ctx, tree);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    /* Root node is always at position 1, due to 1-based indexing */\n    memcpy(ctx->T_1_pub_key, &tree[node_bytes], node_bytes);\n\n    ctx->have_public_key = 1;\n\n    ret = 0;\n\nexit:\n    mbedtls_zeroize_and_free(tree, node_bytes *\n                             (size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type));\n\n    return ret;\n}\n\n\nint mbedtls_lms_sign(mbedtls_lms_private_t *ctx,\n                     int (*f_rng)(void *, unsigned char *, size_t),\n                     void *p_rng, const unsigned char *msg,\n                     unsigned int msg_size, unsigned char *sig, size_t sig_size,\n                     size_t *sig_len)\n{\n    uint32_t q_leaf_identifier;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (!ctx->have_private_key) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (sig_size < MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) {\n        return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;\n    }\n\n    if (ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (ctx->params.otstype\n        != MBEDTLS_LMOTS_SHA256_N32_W8) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    if (ctx->q_next_usable_key >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) {\n        return MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS;\n    }\n\n\n    q_leaf_identifier = ctx->q_next_usable_key;\n    /* This new value must _always_ be written back to the disk before the\n     * signature is returned.\n     */\n    ctx->q_next_usable_key += 1;\n\n    if (MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)\n        < SIG_OTS_SIG_OFFSET) {\n        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;\n    }\n\n    ret = mbedtls_lmots_sign(&ctx->ots_private_keys[q_leaf_identifier],\n                             f_rng,\n                             p_rng,\n                             msg,\n                             msg_size,\n                             sig + SIG_OTS_SIG_OFFSET,\n                             MBEDTLS_LMS_SIG_LEN(ctx->params.type,\n                                                 ctx->params.otstype) - SIG_OTS_SIG_OFFSET,\n                             NULL);\n    if (ret != 0) {\n        return ret;\n    }\n\n    MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, SIG_TYPE_OFFSET(ctx->params.otstype));\n    MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, sig, SIG_Q_LEAF_ID_OFFSET);\n\n    ret = get_merkle_path(ctx,\n                          MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier,\n                          sig + SIG_PATH_OFFSET(ctx->params.otstype));\n    if (ret != 0) {\n        return ret;\n    }\n\n    if (sig_len != NULL) {\n        *sig_len = MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype);\n    }\n\n\n    return 0;\n}\n\n#endif /* defined(MBEDTLS_LMS_PRIVATE) */\n#endif /* defined(MBEDTLS_LMS_C) */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/md.c",
    "content": "/**\n * \\file md.c\n *\n * \\brief Generic message digest wrapper for Mbed TLS\n *\n * \\author Adriaan de Jong <dejong@fox-it.com>\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n/*\n * Availability of functions in this module is controlled by two\n * feature macros:\n * - MBEDTLS_MD_C enables the whole module;\n * - MBEDTLS_MD_LIGHT enables only functions for hashing and accessing\n * most hash metadata (everything except string names); is it\n * automatically set whenever MBEDTLS_MD_C is defined.\n *\n * In this file, functions from MD_LIGHT are at the top, MD_C at the end.\n *\n * In the future we may want to change the contract of some functions\n * (behaviour with NULL arguments) depending on whether MD_C is defined or\n * only MD_LIGHT. Also, the exact scope of MD_LIGHT might vary.\n *\n * For these reasons, we're keeping MD_LIGHT internal for now.\n */\n#if defined(MBEDTLS_MD_LIGHT)\n\n#include \"mbedtls/md.h\"\n#include \"md_wrap.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include \"mbedtls/md5.h\"\n#include \"mbedtls/ripemd160.h\"\n#include \"mbedtls/sha1.h\"\n#include \"mbedtls/sha256.h\"\n#include \"mbedtls/sha512.h\"\n#include \"mbedtls/sha3.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)\n#include <psa/crypto.h>\n#include \"md_psa.h\"\n#include \"psa_util_internal.h\"\n#endif\n\n#if defined(MBEDTLS_MD_SOME_PSA)\n#include \"psa_crypto_core.h\"\n#endif\n\n#include \"mbedtls/platform.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_FS_IO)\n#include <stdio.h>\n#endif\n\n/* See comment above MBEDTLS_MD_MAX_SIZE in md.h */\n#if defined(MBEDTLS_PSA_CRYPTO_C) && MBEDTLS_MD_MAX_SIZE < PSA_HASH_MAX_SIZE\n#error \"Internal error: MBEDTLS_MD_MAX_SIZE < PSA_HASH_MAX_SIZE\"\n#endif\n\n#if defined(MBEDTLS_MD_C)\n#define MD_INFO(type, out_size, block_size) type, out_size, block_size,\n#else\n#define MD_INFO(type, out_size, block_size) type, out_size,\n#endif\n\n#if defined(MBEDTLS_MD_CAN_MD5)\nstatic const mbedtls_md_info_t mbedtls_md5_info = {\n    MD_INFO(MBEDTLS_MD_MD5, 16, 64)\n};\n#endif\n\n#if defined(MBEDTLS_MD_CAN_RIPEMD160)\nstatic const mbedtls_md_info_t mbedtls_ripemd160_info = {\n    MD_INFO(MBEDTLS_MD_RIPEMD160, 20, 64)\n};\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA1)\nstatic const mbedtls_md_info_t mbedtls_sha1_info = {\n    MD_INFO(MBEDTLS_MD_SHA1, 20, 64)\n};\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA224)\nstatic const mbedtls_md_info_t mbedtls_sha224_info = {\n    MD_INFO(MBEDTLS_MD_SHA224, 28, 64)\n};\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\nstatic const mbedtls_md_info_t mbedtls_sha256_info = {\n    MD_INFO(MBEDTLS_MD_SHA256, 32, 64)\n};\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\nstatic const mbedtls_md_info_t mbedtls_sha384_info = {\n    MD_INFO(MBEDTLS_MD_SHA384, 48, 128)\n};\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA512)\nstatic const mbedtls_md_info_t mbedtls_sha512_info = {\n    MD_INFO(MBEDTLS_MD_SHA512, 64, 128)\n};\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA3_224)\nstatic const mbedtls_md_info_t mbedtls_sha3_224_info = {\n    MD_INFO(MBEDTLS_MD_SHA3_224, 28, 144)\n};\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA3_256)\nstatic const mbedtls_md_info_t mbedtls_sha3_256_info = {\n    MD_INFO(MBEDTLS_MD_SHA3_256, 32, 136)\n};\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA3_384)\nstatic const mbedtls_md_info_t mbedtls_sha3_384_info = {\n    MD_INFO(MBEDTLS_MD_SHA3_384, 48, 104)\n};\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA3_512)\nstatic const mbedtls_md_info_t mbedtls_sha3_512_info = {\n    MD_INFO(MBEDTLS_MD_SHA3_512, 64, 72)\n};\n#endif\n\nconst mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type)\n{\n    switch (md_type) {\n#if defined(MBEDTLS_MD_CAN_MD5)\n        case MBEDTLS_MD_MD5:\n            return &mbedtls_md5_info;\n#endif\n#if defined(MBEDTLS_MD_CAN_RIPEMD160)\n        case MBEDTLS_MD_RIPEMD160:\n            return &mbedtls_ripemd160_info;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA1)\n        case MBEDTLS_MD_SHA1:\n            return &mbedtls_sha1_info;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA224)\n        case MBEDTLS_MD_SHA224:\n            return &mbedtls_sha224_info;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA256)\n        case MBEDTLS_MD_SHA256:\n            return &mbedtls_sha256_info;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA384)\n        case MBEDTLS_MD_SHA384:\n            return &mbedtls_sha384_info;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA512)\n        case MBEDTLS_MD_SHA512:\n            return &mbedtls_sha512_info;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA3_224)\n        case MBEDTLS_MD_SHA3_224:\n            return &mbedtls_sha3_224_info;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA3_256)\n        case MBEDTLS_MD_SHA3_256:\n            return &mbedtls_sha3_256_info;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA3_384)\n        case MBEDTLS_MD_SHA3_384:\n            return &mbedtls_sha3_384_info;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA3_512)\n        case MBEDTLS_MD_SHA3_512:\n            return &mbedtls_sha3_512_info;\n#endif\n        default:\n            return NULL;\n    }\n}\n\n#if defined(MBEDTLS_MD_SOME_PSA)\nstatic psa_algorithm_t psa_alg_of_md(const mbedtls_md_info_t *info)\n{\n    switch (info->type) {\n#if defined(MBEDTLS_MD_MD5_VIA_PSA)\n        case MBEDTLS_MD_MD5:\n            return PSA_ALG_MD5;\n#endif\n#if defined(MBEDTLS_MD_RIPEMD160_VIA_PSA)\n        case MBEDTLS_MD_RIPEMD160:\n            return PSA_ALG_RIPEMD160;\n#endif\n#if defined(MBEDTLS_MD_SHA1_VIA_PSA)\n        case MBEDTLS_MD_SHA1:\n            return PSA_ALG_SHA_1;\n#endif\n#if defined(MBEDTLS_MD_SHA224_VIA_PSA)\n        case MBEDTLS_MD_SHA224:\n            return PSA_ALG_SHA_224;\n#endif\n#if defined(MBEDTLS_MD_SHA256_VIA_PSA)\n        case MBEDTLS_MD_SHA256:\n            return PSA_ALG_SHA_256;\n#endif\n#if defined(MBEDTLS_MD_SHA384_VIA_PSA)\n        case MBEDTLS_MD_SHA384:\n            return PSA_ALG_SHA_384;\n#endif\n#if defined(MBEDTLS_MD_SHA512_VIA_PSA)\n        case MBEDTLS_MD_SHA512:\n            return PSA_ALG_SHA_512;\n#endif\n#if defined(MBEDTLS_MD_SHA3_224_VIA_PSA)\n        case MBEDTLS_MD_SHA3_224:\n            return PSA_ALG_SHA3_224;\n#endif\n#if defined(MBEDTLS_MD_SHA3_256_VIA_PSA)\n        case MBEDTLS_MD_SHA3_256:\n            return PSA_ALG_SHA3_256;\n#endif\n#if defined(MBEDTLS_MD_SHA3_384_VIA_PSA)\n        case MBEDTLS_MD_SHA3_384:\n            return PSA_ALG_SHA3_384;\n#endif\n#if defined(MBEDTLS_MD_SHA3_512_VIA_PSA)\n        case MBEDTLS_MD_SHA3_512:\n            return PSA_ALG_SHA3_512;\n#endif\n        default:\n            return PSA_ALG_NONE;\n    }\n}\n\nstatic int md_can_use_psa(const mbedtls_md_info_t *info)\n{\n    psa_algorithm_t alg = psa_alg_of_md(info);\n    if (alg == PSA_ALG_NONE) {\n        return 0;\n    }\n\n    return psa_can_do_hash(alg);\n}\n#endif /* MBEDTLS_MD_SOME_PSA */\n\nvoid mbedtls_md_init(mbedtls_md_context_t *ctx)\n{\n    /* Note: this sets engine (if present) to MBEDTLS_MD_ENGINE_LEGACY */\n    memset(ctx, 0, sizeof(mbedtls_md_context_t));\n}\n\nvoid mbedtls_md_free(mbedtls_md_context_t *ctx)\n{\n    if (ctx == NULL || ctx->md_info == NULL) {\n        return;\n    }\n\n    if (ctx->md_ctx != NULL) {\n#if defined(MBEDTLS_MD_SOME_PSA)\n        if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) {\n            psa_hash_abort(ctx->md_ctx);\n        } else\n#endif\n        switch (ctx->md_info->type) {\n#if defined(MBEDTLS_MD5_C)\n            case MBEDTLS_MD_MD5:\n                mbedtls_md5_free(ctx->md_ctx);\n                break;\n#endif\n#if defined(MBEDTLS_RIPEMD160_C)\n            case MBEDTLS_MD_RIPEMD160:\n                mbedtls_ripemd160_free(ctx->md_ctx);\n                break;\n#endif\n#if defined(MBEDTLS_SHA1_C)\n            case MBEDTLS_MD_SHA1:\n                mbedtls_sha1_free(ctx->md_ctx);\n                break;\n#endif\n#if defined(MBEDTLS_SHA224_C)\n            case MBEDTLS_MD_SHA224:\n                mbedtls_sha256_free(ctx->md_ctx);\n                break;\n#endif\n#if defined(MBEDTLS_SHA256_C)\n            case MBEDTLS_MD_SHA256:\n                mbedtls_sha256_free(ctx->md_ctx);\n                break;\n#endif\n#if defined(MBEDTLS_SHA384_C)\n            case MBEDTLS_MD_SHA384:\n                mbedtls_sha512_free(ctx->md_ctx);\n                break;\n#endif\n#if defined(MBEDTLS_SHA512_C)\n            case MBEDTLS_MD_SHA512:\n                mbedtls_sha512_free(ctx->md_ctx);\n                break;\n#endif\n#if defined(MBEDTLS_SHA3_C)\n            case MBEDTLS_MD_SHA3_224:\n            case MBEDTLS_MD_SHA3_256:\n            case MBEDTLS_MD_SHA3_384:\n            case MBEDTLS_MD_SHA3_512:\n                mbedtls_sha3_free(ctx->md_ctx);\n                break;\n#endif\n            default:\n                /* Shouldn't happen */\n                break;\n        }\n        mbedtls_free(ctx->md_ctx);\n    }\n\n#if defined(MBEDTLS_MD_C)\n    if (ctx->hmac_ctx != NULL) {\n        mbedtls_zeroize_and_free(ctx->hmac_ctx,\n                                 2 * ctx->md_info->block_size);\n    }\n#endif\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md_context_t));\n}\n\nint mbedtls_md_clone(mbedtls_md_context_t *dst,\n                     const mbedtls_md_context_t *src)\n{\n    if (dst == NULL || dst->md_info == NULL ||\n        src == NULL || src->md_info == NULL ||\n        dst->md_info != src->md_info) {\n        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_MD_SOME_PSA)\n    if (src->engine != dst->engine) {\n        /* This can happen with src set to legacy because PSA wasn't ready\n         * yet, and dst to PSA because it became ready in the meantime.\n         * We currently don't support that case (we'd need to re-allocate\n         * md_ctx to the size of the appropriate MD context). */\n        return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;\n    }\n\n    if (src->engine == MBEDTLS_MD_ENGINE_PSA) {\n        psa_status_t status = psa_hash_clone(src->md_ctx, dst->md_ctx);\n        return mbedtls_md_error_from_psa(status);\n    }\n#endif\n\n    switch (src->md_info->type) {\n#if defined(MBEDTLS_MD5_C)\n        case MBEDTLS_MD_MD5:\n            mbedtls_md5_clone(dst->md_ctx, src->md_ctx);\n            break;\n#endif\n#if defined(MBEDTLS_RIPEMD160_C)\n        case MBEDTLS_MD_RIPEMD160:\n            mbedtls_ripemd160_clone(dst->md_ctx, src->md_ctx);\n            break;\n#endif\n#if defined(MBEDTLS_SHA1_C)\n        case MBEDTLS_MD_SHA1:\n            mbedtls_sha1_clone(dst->md_ctx, src->md_ctx);\n            break;\n#endif\n#if defined(MBEDTLS_SHA224_C)\n        case MBEDTLS_MD_SHA224:\n            mbedtls_sha256_clone(dst->md_ctx, src->md_ctx);\n            break;\n#endif\n#if defined(MBEDTLS_SHA256_C)\n        case MBEDTLS_MD_SHA256:\n            mbedtls_sha256_clone(dst->md_ctx, src->md_ctx);\n            break;\n#endif\n#if defined(MBEDTLS_SHA384_C)\n        case MBEDTLS_MD_SHA384:\n            mbedtls_sha512_clone(dst->md_ctx, src->md_ctx);\n            break;\n#endif\n#if defined(MBEDTLS_SHA512_C)\n        case MBEDTLS_MD_SHA512:\n            mbedtls_sha512_clone(dst->md_ctx, src->md_ctx);\n            break;\n#endif\n#if defined(MBEDTLS_SHA3_C)\n        case MBEDTLS_MD_SHA3_224:\n        case MBEDTLS_MD_SHA3_256:\n        case MBEDTLS_MD_SHA3_384:\n        case MBEDTLS_MD_SHA3_512:\n            mbedtls_sha3_clone(dst->md_ctx, src->md_ctx);\n            break;\n#endif\n        default:\n            return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n\n    return 0;\n}\n\n#define ALLOC(type)                                                   \\\n    do {                                                                \\\n        ctx->md_ctx = mbedtls_calloc(1, sizeof(mbedtls_##type##_context)); \\\n        if (ctx->md_ctx == NULL)                                       \\\n        return MBEDTLS_ERR_MD_ALLOC_FAILED;                      \\\n        mbedtls_##type##_init(ctx->md_ctx);                           \\\n    }                                                                   \\\n    while (0)\n\nint mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac)\n{\n#if defined(MBEDTLS_MD_C)\n    if (ctx == NULL) {\n        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n#endif\n    if (md_info == NULL) {\n        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n\n    ctx->md_info = md_info;\n    ctx->md_ctx = NULL;\n#if defined(MBEDTLS_MD_C)\n    ctx->hmac_ctx = NULL;\n#else\n    if (hmac != 0) {\n        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n#endif\n\n#if defined(MBEDTLS_MD_SOME_PSA)\n    if (md_can_use_psa(ctx->md_info)) {\n        ctx->md_ctx = mbedtls_calloc(1, sizeof(psa_hash_operation_t));\n        if (ctx->md_ctx == NULL) {\n            return MBEDTLS_ERR_MD_ALLOC_FAILED;\n        }\n        ctx->engine = MBEDTLS_MD_ENGINE_PSA;\n    } else\n#endif\n    switch (md_info->type) {\n#if defined(MBEDTLS_MD5_C)\n        case MBEDTLS_MD_MD5:\n            ALLOC(md5);\n            break;\n#endif\n#if defined(MBEDTLS_RIPEMD160_C)\n        case MBEDTLS_MD_RIPEMD160:\n            ALLOC(ripemd160);\n            break;\n#endif\n#if defined(MBEDTLS_SHA1_C)\n        case MBEDTLS_MD_SHA1:\n            ALLOC(sha1);\n            break;\n#endif\n#if defined(MBEDTLS_SHA224_C)\n        case MBEDTLS_MD_SHA224:\n            ALLOC(sha256);\n            break;\n#endif\n#if defined(MBEDTLS_SHA256_C)\n        case MBEDTLS_MD_SHA256:\n            ALLOC(sha256);\n            break;\n#endif\n#if defined(MBEDTLS_SHA384_C)\n        case MBEDTLS_MD_SHA384:\n            ALLOC(sha512);\n            break;\n#endif\n#if defined(MBEDTLS_SHA512_C)\n        case MBEDTLS_MD_SHA512:\n            ALLOC(sha512);\n            break;\n#endif\n#if defined(MBEDTLS_SHA3_C)\n        case MBEDTLS_MD_SHA3_224:\n        case MBEDTLS_MD_SHA3_256:\n        case MBEDTLS_MD_SHA3_384:\n        case MBEDTLS_MD_SHA3_512:\n            ALLOC(sha3);\n            break;\n#endif\n        default:\n            return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_MD_C)\n    if (hmac != 0) {\n        ctx->hmac_ctx = mbedtls_calloc(2, md_info->block_size);\n        if (ctx->hmac_ctx == NULL) {\n            mbedtls_md_free(ctx);\n            return MBEDTLS_ERR_MD_ALLOC_FAILED;\n        }\n    }\n#endif\n\n    return 0;\n}\n#undef ALLOC\n\nint mbedtls_md_starts(mbedtls_md_context_t *ctx)\n{\n#if defined(MBEDTLS_MD_C)\n    if (ctx == NULL || ctx->md_info == NULL) {\n        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n#endif\n\n#if defined(MBEDTLS_MD_SOME_PSA)\n    if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) {\n        psa_algorithm_t alg = psa_alg_of_md(ctx->md_info);\n        psa_hash_abort(ctx->md_ctx);\n        psa_status_t status = psa_hash_setup(ctx->md_ctx, alg);\n        return mbedtls_md_error_from_psa(status);\n    }\n#endif\n\n    switch (ctx->md_info->type) {\n#if defined(MBEDTLS_MD5_C)\n        case MBEDTLS_MD_MD5:\n            return mbedtls_md5_starts(ctx->md_ctx);\n#endif\n#if defined(MBEDTLS_RIPEMD160_C)\n        case MBEDTLS_MD_RIPEMD160:\n            return mbedtls_ripemd160_starts(ctx->md_ctx);\n#endif\n#if defined(MBEDTLS_SHA1_C)\n        case MBEDTLS_MD_SHA1:\n            return mbedtls_sha1_starts(ctx->md_ctx);\n#endif\n#if defined(MBEDTLS_SHA224_C)\n        case MBEDTLS_MD_SHA224:\n            return mbedtls_sha256_starts(ctx->md_ctx, 1);\n#endif\n#if defined(MBEDTLS_SHA256_C)\n        case MBEDTLS_MD_SHA256:\n            return mbedtls_sha256_starts(ctx->md_ctx, 0);\n#endif\n#if defined(MBEDTLS_SHA384_C)\n        case MBEDTLS_MD_SHA384:\n            return mbedtls_sha512_starts(ctx->md_ctx, 1);\n#endif\n#if defined(MBEDTLS_SHA512_C)\n        case MBEDTLS_MD_SHA512:\n            return mbedtls_sha512_starts(ctx->md_ctx, 0);\n#endif\n#if defined(MBEDTLS_SHA3_C)\n        case MBEDTLS_MD_SHA3_224:\n            return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_224);\n        case MBEDTLS_MD_SHA3_256:\n            return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_256);\n        case MBEDTLS_MD_SHA3_384:\n            return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_384);\n        case MBEDTLS_MD_SHA3_512:\n            return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_512);\n#endif\n        default:\n            return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n}\n\nint mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen)\n{\n#if defined(MBEDTLS_MD_C)\n    if (ctx == NULL || ctx->md_info == NULL) {\n        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n#endif\n\n#if defined(MBEDTLS_MD_SOME_PSA)\n    if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) {\n        psa_status_t status = psa_hash_update(ctx->md_ctx, input, ilen);\n        return mbedtls_md_error_from_psa(status);\n    }\n#endif\n\n    switch (ctx->md_info->type) {\n#if defined(MBEDTLS_MD5_C)\n        case MBEDTLS_MD_MD5:\n            return mbedtls_md5_update(ctx->md_ctx, input, ilen);\n#endif\n#if defined(MBEDTLS_RIPEMD160_C)\n        case MBEDTLS_MD_RIPEMD160:\n            return mbedtls_ripemd160_update(ctx->md_ctx, input, ilen);\n#endif\n#if defined(MBEDTLS_SHA1_C)\n        case MBEDTLS_MD_SHA1:\n            return mbedtls_sha1_update(ctx->md_ctx, input, ilen);\n#endif\n#if defined(MBEDTLS_SHA224_C)\n        case MBEDTLS_MD_SHA224:\n            return mbedtls_sha256_update(ctx->md_ctx, input, ilen);\n#endif\n#if defined(MBEDTLS_SHA256_C)\n        case MBEDTLS_MD_SHA256:\n            return mbedtls_sha256_update(ctx->md_ctx, input, ilen);\n#endif\n#if defined(MBEDTLS_SHA384_C)\n        case MBEDTLS_MD_SHA384:\n            return mbedtls_sha512_update(ctx->md_ctx, input, ilen);\n#endif\n#if defined(MBEDTLS_SHA512_C)\n        case MBEDTLS_MD_SHA512:\n            return mbedtls_sha512_update(ctx->md_ctx, input, ilen);\n#endif\n#if defined(MBEDTLS_SHA3_C)\n        case MBEDTLS_MD_SHA3_224:\n        case MBEDTLS_MD_SHA3_256:\n        case MBEDTLS_MD_SHA3_384:\n        case MBEDTLS_MD_SHA3_512:\n            return mbedtls_sha3_update(ctx->md_ctx, input, ilen);\n#endif\n        default:\n            return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n}\n\nint mbedtls_md_finish(mbedtls_md_context_t *ctx, unsigned char *output)\n{\n#if defined(MBEDTLS_MD_C)\n    if (ctx == NULL || ctx->md_info == NULL) {\n        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n#endif\n\n#if defined(MBEDTLS_MD_SOME_PSA)\n    if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) {\n        size_t size = ctx->md_info->size;\n        psa_status_t status = psa_hash_finish(ctx->md_ctx,\n                                              output, size, &size);\n        return mbedtls_md_error_from_psa(status);\n    }\n#endif\n\n    switch (ctx->md_info->type) {\n#if defined(MBEDTLS_MD5_C)\n        case MBEDTLS_MD_MD5:\n            return mbedtls_md5_finish(ctx->md_ctx, output);\n#endif\n#if defined(MBEDTLS_RIPEMD160_C)\n        case MBEDTLS_MD_RIPEMD160:\n            return mbedtls_ripemd160_finish(ctx->md_ctx, output);\n#endif\n#if defined(MBEDTLS_SHA1_C)\n        case MBEDTLS_MD_SHA1:\n            return mbedtls_sha1_finish(ctx->md_ctx, output);\n#endif\n#if defined(MBEDTLS_SHA224_C)\n        case MBEDTLS_MD_SHA224:\n            return mbedtls_sha256_finish(ctx->md_ctx, output);\n#endif\n#if defined(MBEDTLS_SHA256_C)\n        case MBEDTLS_MD_SHA256:\n            return mbedtls_sha256_finish(ctx->md_ctx, output);\n#endif\n#if defined(MBEDTLS_SHA384_C)\n        case MBEDTLS_MD_SHA384:\n            return mbedtls_sha512_finish(ctx->md_ctx, output);\n#endif\n#if defined(MBEDTLS_SHA512_C)\n        case MBEDTLS_MD_SHA512:\n            return mbedtls_sha512_finish(ctx->md_ctx, output);\n#endif\n#if defined(MBEDTLS_SHA3_C)\n        case MBEDTLS_MD_SHA3_224:\n        case MBEDTLS_MD_SHA3_256:\n        case MBEDTLS_MD_SHA3_384:\n        case MBEDTLS_MD_SHA3_512:\n            return mbedtls_sha3_finish(ctx->md_ctx, output, ctx->md_info->size);\n#endif\n        default:\n            return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n}\n\nint mbedtls_md(const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,\n               unsigned char *output)\n{\n    if (md_info == NULL) {\n        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_MD_SOME_PSA)\n    if (md_can_use_psa(md_info)) {\n        size_t size = md_info->size;\n        psa_status_t status = psa_hash_compute(psa_alg_of_md(md_info),\n                                               input, ilen,\n                                               output, size, &size);\n        return mbedtls_md_error_from_psa(status);\n    }\n#endif\n\n    switch (md_info->type) {\n#if defined(MBEDTLS_MD5_C)\n        case MBEDTLS_MD_MD5:\n            return mbedtls_md5(input, ilen, output);\n#endif\n#if defined(MBEDTLS_RIPEMD160_C)\n        case MBEDTLS_MD_RIPEMD160:\n            return mbedtls_ripemd160(input, ilen, output);\n#endif\n#if defined(MBEDTLS_SHA1_C)\n        case MBEDTLS_MD_SHA1:\n            return mbedtls_sha1(input, ilen, output);\n#endif\n#if defined(MBEDTLS_SHA224_C)\n        case MBEDTLS_MD_SHA224:\n            return mbedtls_sha256(input, ilen, output, 1);\n#endif\n#if defined(MBEDTLS_SHA256_C)\n        case MBEDTLS_MD_SHA256:\n            return mbedtls_sha256(input, ilen, output, 0);\n#endif\n#if defined(MBEDTLS_SHA384_C)\n        case MBEDTLS_MD_SHA384:\n            return mbedtls_sha512(input, ilen, output, 1);\n#endif\n#if defined(MBEDTLS_SHA512_C)\n        case MBEDTLS_MD_SHA512:\n            return mbedtls_sha512(input, ilen, output, 0);\n#endif\n#if defined(MBEDTLS_SHA3_C)\n        case MBEDTLS_MD_SHA3_224:\n            return mbedtls_sha3(MBEDTLS_SHA3_224, input, ilen, output, md_info->size);\n        case MBEDTLS_MD_SHA3_256:\n            return mbedtls_sha3(MBEDTLS_SHA3_256, input, ilen, output, md_info->size);\n        case MBEDTLS_MD_SHA3_384:\n            return mbedtls_sha3(MBEDTLS_SHA3_384, input, ilen, output, md_info->size);\n        case MBEDTLS_MD_SHA3_512:\n            return mbedtls_sha3(MBEDTLS_SHA3_512, input, ilen, output, md_info->size);\n#endif\n        default:\n            return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n}\n\nunsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info)\n{\n    if (md_info == NULL) {\n        return 0;\n    }\n\n    return md_info->size;\n}\n\nmbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info)\n{\n    if (md_info == NULL) {\n        return MBEDTLS_MD_NONE;\n    }\n\n    return md_info->type;\n}\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)\nint mbedtls_md_error_from_psa(psa_status_t status)\n{\n    return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_md_errors,\n                                   psa_generic_status_to_mbedtls);\n}\n#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */\n\n\n/************************************************************************\n * Functions above this separator are part of MBEDTLS_MD_LIGHT,         *\n * functions below are only available when MBEDTLS_MD_C is set.         *\n ************************************************************************/\n#if defined(MBEDTLS_MD_C)\n\n/*\n * Reminder: update profiles in x509_crt.c when adding a new hash!\n */\nstatic const int supported_digests[] = {\n\n#if defined(MBEDTLS_MD_CAN_SHA512)\n    MBEDTLS_MD_SHA512,\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    MBEDTLS_MD_SHA384,\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    MBEDTLS_MD_SHA256,\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA224)\n    MBEDTLS_MD_SHA224,\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    MBEDTLS_MD_SHA1,\n#endif\n\n#if defined(MBEDTLS_MD_CAN_RIPEMD160)\n    MBEDTLS_MD_RIPEMD160,\n#endif\n\n#if defined(MBEDTLS_MD_CAN_MD5)\n    MBEDTLS_MD_MD5,\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA3_224)\n    MBEDTLS_MD_SHA3_224,\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA3_256)\n    MBEDTLS_MD_SHA3_256,\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA3_384)\n    MBEDTLS_MD_SHA3_384,\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA3_512)\n    MBEDTLS_MD_SHA3_512,\n#endif\n\n    MBEDTLS_MD_NONE\n};\n\nconst int *mbedtls_md_list(void)\n{\n    return supported_digests;\n}\n\ntypedef struct {\n    const char *md_name;\n    mbedtls_md_type_t md_type;\n} md_name_entry;\n\nstatic const md_name_entry md_names[] = {\n#if defined(MBEDTLS_MD_CAN_MD5)\n    { \"MD5\", MBEDTLS_MD_MD5 },\n#endif\n#if defined(MBEDTLS_MD_CAN_RIPEMD160)\n    { \"RIPEMD160\", MBEDTLS_MD_RIPEMD160 },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { \"SHA1\", MBEDTLS_MD_SHA1 },\n    { \"SHA\", MBEDTLS_MD_SHA1 }, // compatibility fallback\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA224)\n    { \"SHA224\", MBEDTLS_MD_SHA224 },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { \"SHA256\", MBEDTLS_MD_SHA256 },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { \"SHA384\", MBEDTLS_MD_SHA384 },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA512)\n    { \"SHA512\", MBEDTLS_MD_SHA512 },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA3_224)\n    { \"SHA3-224\", MBEDTLS_MD_SHA3_224 },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA3_256)\n    { \"SHA3-256\", MBEDTLS_MD_SHA3_256 },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA3_384)\n    { \"SHA3-384\", MBEDTLS_MD_SHA3_384 },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA3_512)\n    { \"SHA3-512\", MBEDTLS_MD_SHA3_512 },\n#endif\n    { NULL, MBEDTLS_MD_NONE },\n};\n\nconst mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name)\n{\n    if (NULL == md_name) {\n        return NULL;\n    }\n\n    const md_name_entry *entry = md_names;\n    while (entry->md_name != NULL &&\n           strcmp(entry->md_name, md_name) != 0) {\n        ++entry;\n    }\n\n    return mbedtls_md_info_from_type(entry->md_type);\n}\n\nconst char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info)\n{\n    if (md_info == NULL) {\n        return NULL;\n    }\n\n    const md_name_entry *entry = md_names;\n    while (entry->md_type != MBEDTLS_MD_NONE &&\n           entry->md_type != md_info->type) {\n        ++entry;\n    }\n\n    return entry->md_name;\n}\n\nconst mbedtls_md_info_t *mbedtls_md_info_from_ctx(\n    const mbedtls_md_context_t *ctx)\n{\n    if (ctx == NULL) {\n        return NULL;\n    }\n\n    return ctx->MBEDTLS_PRIVATE(md_info);\n}\n\n#if defined(MBEDTLS_FS_IO)\nint mbedtls_md_file(const mbedtls_md_info_t *md_info, const char *path, unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    FILE *f;\n    size_t n;\n    mbedtls_md_context_t ctx;\n    unsigned char buf[1024];\n\n    if (md_info == NULL) {\n        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n\n    if ((f = fopen(path, \"rb\")) == NULL) {\n        return MBEDTLS_ERR_MD_FILE_IO_ERROR;\n    }\n\n    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */\n    mbedtls_setbuf(f, NULL);\n\n    mbedtls_md_init(&ctx);\n\n    if ((ret = mbedtls_md_setup(&ctx, md_info, 0)) != 0) {\n        goto cleanup;\n    }\n\n    if ((ret = mbedtls_md_starts(&ctx)) != 0) {\n        goto cleanup;\n    }\n\n    while ((n = fread(buf, 1, sizeof(buf), f)) > 0) {\n        if ((ret = mbedtls_md_update(&ctx, buf, n)) != 0) {\n            goto cleanup;\n        }\n    }\n\n    if (ferror(f) != 0) {\n        ret = MBEDTLS_ERR_MD_FILE_IO_ERROR;\n    } else {\n        ret = mbedtls_md_finish(&ctx, output);\n    }\n\ncleanup:\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n    fclose(f);\n    mbedtls_md_free(&ctx);\n\n    return ret;\n}\n#endif /* MBEDTLS_FS_IO */\n\nint mbedtls_md_hmac_starts(mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char sum[MBEDTLS_MD_MAX_SIZE];\n    unsigned char *ipad, *opad;\n\n    if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) {\n        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n\n    if (keylen > (size_t) ctx->md_info->block_size) {\n        if ((ret = mbedtls_md_starts(ctx)) != 0) {\n            goto cleanup;\n        }\n        if ((ret = mbedtls_md_update(ctx, key, keylen)) != 0) {\n            goto cleanup;\n        }\n        if ((ret = mbedtls_md_finish(ctx, sum)) != 0) {\n            goto cleanup;\n        }\n\n        keylen = ctx->md_info->size;\n        key = sum;\n    }\n\n    ipad = (unsigned char *) ctx->hmac_ctx;\n    opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size;\n\n    memset(ipad, 0x36, ctx->md_info->block_size);\n    memset(opad, 0x5C, ctx->md_info->block_size);\n\n    mbedtls_xor(ipad, ipad, key, keylen);\n    mbedtls_xor(opad, opad, key, keylen);\n\n    if ((ret = mbedtls_md_starts(ctx)) != 0) {\n        goto cleanup;\n    }\n    if ((ret = mbedtls_md_update(ctx, ipad,\n                                 ctx->md_info->block_size)) != 0) {\n        goto cleanup;\n    }\n\ncleanup:\n    mbedtls_platform_zeroize(sum, sizeof(sum));\n\n    return ret;\n}\n\nint mbedtls_md_hmac_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen)\n{\n    if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) {\n        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n\n    return mbedtls_md_update(ctx, input, ilen);\n}\n\nint mbedtls_md_hmac_finish(mbedtls_md_context_t *ctx, unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char tmp[MBEDTLS_MD_MAX_SIZE];\n    unsigned char *opad;\n\n    if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) {\n        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n\n    opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size;\n\n    if ((ret = mbedtls_md_finish(ctx, tmp)) != 0) {\n        return ret;\n    }\n    if ((ret = mbedtls_md_starts(ctx)) != 0) {\n        return ret;\n    }\n    if ((ret = mbedtls_md_update(ctx, opad,\n                                 ctx->md_info->block_size)) != 0) {\n        return ret;\n    }\n    if ((ret = mbedtls_md_update(ctx, tmp,\n                                 ctx->md_info->size)) != 0) {\n        return ret;\n    }\n    return mbedtls_md_finish(ctx, output);\n}\n\nint mbedtls_md_hmac_reset(mbedtls_md_context_t *ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *ipad;\n\n    if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) {\n        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n\n    ipad = (unsigned char *) ctx->hmac_ctx;\n\n    if ((ret = mbedtls_md_starts(ctx)) != 0) {\n        return ret;\n    }\n    return mbedtls_md_update(ctx, ipad, ctx->md_info->block_size);\n}\n\nint mbedtls_md_hmac(const mbedtls_md_info_t *md_info,\n                    const unsigned char *key, size_t keylen,\n                    const unsigned char *input, size_t ilen,\n                    unsigned char *output)\n{\n    mbedtls_md_context_t ctx;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (md_info == NULL) {\n        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n    }\n\n    mbedtls_md_init(&ctx);\n\n    if ((ret = mbedtls_md_setup(&ctx, md_info, 1)) != 0) {\n        goto cleanup;\n    }\n\n    if ((ret = mbedtls_md_hmac_starts(&ctx, key, keylen)) != 0) {\n        goto cleanup;\n    }\n    if ((ret = mbedtls_md_hmac_update(&ctx, input, ilen)) != 0) {\n        goto cleanup;\n    }\n    if ((ret = mbedtls_md_hmac_finish(&ctx, output)) != 0) {\n        goto cleanup;\n    }\n\ncleanup:\n    mbedtls_md_free(&ctx);\n\n    return ret;\n}\n\n#endif /* MBEDTLS_MD_C */\n\n#endif /* MBEDTLS_MD_LIGHT */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/md5.c",
    "content": "/*\n *  RFC 1321 compliant MD5 implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  The MD5 algorithm was designed by Ron Rivest in 1991.\n *\n *  http://www.ietf.org/rfc/rfc1321.txt\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_MD5_C)\n\n#include \"mbedtls/md5.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#if !defined(MBEDTLS_MD5_ALT)\n\nvoid mbedtls_md5_init(mbedtls_md5_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_md5_context));\n}\n\nvoid mbedtls_md5_free(mbedtls_md5_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md5_context));\n}\n\nvoid mbedtls_md5_clone(mbedtls_md5_context *dst,\n                       const mbedtls_md5_context *src)\n{\n    *dst = *src;\n}\n\n/*\n * MD5 context setup\n */\nint mbedtls_md5_starts(mbedtls_md5_context *ctx)\n{\n    ctx->total[0] = 0;\n    ctx->total[1] = 0;\n\n    ctx->state[0] = 0x67452301;\n    ctx->state[1] = 0xEFCDAB89;\n    ctx->state[2] = 0x98BADCFE;\n    ctx->state[3] = 0x10325476;\n\n    return 0;\n}\n\n#if !defined(MBEDTLS_MD5_PROCESS_ALT)\nint mbedtls_internal_md5_process(mbedtls_md5_context *ctx,\n                                 const unsigned char data[64])\n{\n    struct {\n        uint32_t X[16], A, B, C, D;\n    } local;\n\n    local.X[0] = MBEDTLS_GET_UINT32_LE(data,  0);\n    local.X[1] = MBEDTLS_GET_UINT32_LE(data,  4);\n    local.X[2] = MBEDTLS_GET_UINT32_LE(data,  8);\n    local.X[3] = MBEDTLS_GET_UINT32_LE(data, 12);\n    local.X[4] = MBEDTLS_GET_UINT32_LE(data, 16);\n    local.X[5] = MBEDTLS_GET_UINT32_LE(data, 20);\n    local.X[6] = MBEDTLS_GET_UINT32_LE(data, 24);\n    local.X[7] = MBEDTLS_GET_UINT32_LE(data, 28);\n    local.X[8] = MBEDTLS_GET_UINT32_LE(data, 32);\n    local.X[9] = MBEDTLS_GET_UINT32_LE(data, 36);\n    local.X[10] = MBEDTLS_GET_UINT32_LE(data, 40);\n    local.X[11] = MBEDTLS_GET_UINT32_LE(data, 44);\n    local.X[12] = MBEDTLS_GET_UINT32_LE(data, 48);\n    local.X[13] = MBEDTLS_GET_UINT32_LE(data, 52);\n    local.X[14] = MBEDTLS_GET_UINT32_LE(data, 56);\n    local.X[15] = MBEDTLS_GET_UINT32_LE(data, 60);\n\n#define S(x, n)                                                          \\\n    (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))\n\n#define P(a, b, c, d, k, s, t)                                                \\\n    do                                                                  \\\n    {                                                                   \\\n        (a) += F((b), (c), (d)) + local.X[(k)] + (t);                     \\\n        (a) = S((a), (s)) + (b);                                         \\\n    } while (0)\n\n    local.A = ctx->state[0];\n    local.B = ctx->state[1];\n    local.C = ctx->state[2];\n    local.D = ctx->state[3];\n\n#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))\n\n    P(local.A, local.B, local.C, local.D,  0,  7, 0xD76AA478);\n    P(local.D, local.A, local.B, local.C,  1, 12, 0xE8C7B756);\n    P(local.C, local.D, local.A, local.B,  2, 17, 0x242070DB);\n    P(local.B, local.C, local.D, local.A,  3, 22, 0xC1BDCEEE);\n    P(local.A, local.B, local.C, local.D,  4,  7, 0xF57C0FAF);\n    P(local.D, local.A, local.B, local.C,  5, 12, 0x4787C62A);\n    P(local.C, local.D, local.A, local.B,  6, 17, 0xA8304613);\n    P(local.B, local.C, local.D, local.A,  7, 22, 0xFD469501);\n    P(local.A, local.B, local.C, local.D,  8,  7, 0x698098D8);\n    P(local.D, local.A, local.B, local.C,  9, 12, 0x8B44F7AF);\n    P(local.C, local.D, local.A, local.B, 10, 17, 0xFFFF5BB1);\n    P(local.B, local.C, local.D, local.A, 11, 22, 0x895CD7BE);\n    P(local.A, local.B, local.C, local.D, 12,  7, 0x6B901122);\n    P(local.D, local.A, local.B, local.C, 13, 12, 0xFD987193);\n    P(local.C, local.D, local.A, local.B, 14, 17, 0xA679438E);\n    P(local.B, local.C, local.D, local.A, 15, 22, 0x49B40821);\n\n#undef F\n\n#define F(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))\n\n    P(local.A, local.B, local.C, local.D,  1,  5, 0xF61E2562);\n    P(local.D, local.A, local.B, local.C,  6,  9, 0xC040B340);\n    P(local.C, local.D, local.A, local.B, 11, 14, 0x265E5A51);\n    P(local.B, local.C, local.D, local.A,  0, 20, 0xE9B6C7AA);\n    P(local.A, local.B, local.C, local.D,  5,  5, 0xD62F105D);\n    P(local.D, local.A, local.B, local.C, 10,  9, 0x02441453);\n    P(local.C, local.D, local.A, local.B, 15, 14, 0xD8A1E681);\n    P(local.B, local.C, local.D, local.A,  4, 20, 0xE7D3FBC8);\n    P(local.A, local.B, local.C, local.D,  9,  5, 0x21E1CDE6);\n    P(local.D, local.A, local.B, local.C, 14,  9, 0xC33707D6);\n    P(local.C, local.D, local.A, local.B,  3, 14, 0xF4D50D87);\n    P(local.B, local.C, local.D, local.A,  8, 20, 0x455A14ED);\n    P(local.A, local.B, local.C, local.D, 13,  5, 0xA9E3E905);\n    P(local.D, local.A, local.B, local.C,  2,  9, 0xFCEFA3F8);\n    P(local.C, local.D, local.A, local.B,  7, 14, 0x676F02D9);\n    P(local.B, local.C, local.D, local.A, 12, 20, 0x8D2A4C8A);\n\n#undef F\n\n#define F(x, y, z) ((x) ^ (y) ^ (z))\n\n    P(local.A, local.B, local.C, local.D,  5,  4, 0xFFFA3942);\n    P(local.D, local.A, local.B, local.C,  8, 11, 0x8771F681);\n    P(local.C, local.D, local.A, local.B, 11, 16, 0x6D9D6122);\n    P(local.B, local.C, local.D, local.A, 14, 23, 0xFDE5380C);\n    P(local.A, local.B, local.C, local.D,  1,  4, 0xA4BEEA44);\n    P(local.D, local.A, local.B, local.C,  4, 11, 0x4BDECFA9);\n    P(local.C, local.D, local.A, local.B,  7, 16, 0xF6BB4B60);\n    P(local.B, local.C, local.D, local.A, 10, 23, 0xBEBFBC70);\n    P(local.A, local.B, local.C, local.D, 13,  4, 0x289B7EC6);\n    P(local.D, local.A, local.B, local.C,  0, 11, 0xEAA127FA);\n    P(local.C, local.D, local.A, local.B,  3, 16, 0xD4EF3085);\n    P(local.B, local.C, local.D, local.A,  6, 23, 0x04881D05);\n    P(local.A, local.B, local.C, local.D,  9,  4, 0xD9D4D039);\n    P(local.D, local.A, local.B, local.C, 12, 11, 0xE6DB99E5);\n    P(local.C, local.D, local.A, local.B, 15, 16, 0x1FA27CF8);\n    P(local.B, local.C, local.D, local.A,  2, 23, 0xC4AC5665);\n\n#undef F\n\n#define F(x, y, z) ((y) ^ ((x) | ~(z)))\n\n    P(local.A, local.B, local.C, local.D,  0,  6, 0xF4292244);\n    P(local.D, local.A, local.B, local.C,  7, 10, 0x432AFF97);\n    P(local.C, local.D, local.A, local.B, 14, 15, 0xAB9423A7);\n    P(local.B, local.C, local.D, local.A,  5, 21, 0xFC93A039);\n    P(local.A, local.B, local.C, local.D, 12,  6, 0x655B59C3);\n    P(local.D, local.A, local.B, local.C,  3, 10, 0x8F0CCC92);\n    P(local.C, local.D, local.A, local.B, 10, 15, 0xFFEFF47D);\n    P(local.B, local.C, local.D, local.A,  1, 21, 0x85845DD1);\n    P(local.A, local.B, local.C, local.D,  8,  6, 0x6FA87E4F);\n    P(local.D, local.A, local.B, local.C, 15, 10, 0xFE2CE6E0);\n    P(local.C, local.D, local.A, local.B,  6, 15, 0xA3014314);\n    P(local.B, local.C, local.D, local.A, 13, 21, 0x4E0811A1);\n    P(local.A, local.B, local.C, local.D,  4,  6, 0xF7537E82);\n    P(local.D, local.A, local.B, local.C, 11, 10, 0xBD3AF235);\n    P(local.C, local.D, local.A, local.B,  2, 15, 0x2AD7D2BB);\n    P(local.B, local.C, local.D, local.A,  9, 21, 0xEB86D391);\n\n#undef F\n\n    ctx->state[0] += local.A;\n    ctx->state[1] += local.B;\n    ctx->state[2] += local.C;\n    ctx->state[3] += local.D;\n\n    /* Zeroise variables to clear sensitive data from memory. */\n    mbedtls_platform_zeroize(&local, sizeof(local));\n\n    return 0;\n}\n\n#endif /* !MBEDTLS_MD5_PROCESS_ALT */\n\n/*\n * MD5 process buffer\n */\nint mbedtls_md5_update(mbedtls_md5_context *ctx,\n                       const unsigned char *input,\n                       size_t ilen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t fill;\n    uint32_t left;\n\n    if (ilen == 0) {\n        return 0;\n    }\n\n    left = ctx->total[0] & 0x3F;\n    fill = 64 - left;\n\n    ctx->total[0] += (uint32_t) ilen;\n    ctx->total[0] &= 0xFFFFFFFF;\n\n    if (ctx->total[0] < (uint32_t) ilen) {\n        ctx->total[1]++;\n    }\n\n    if (left && ilen >= fill) {\n        memcpy((void *) (ctx->buffer + left), input, fill);\n        if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) {\n            return ret;\n        }\n\n        input += fill;\n        ilen  -= fill;\n        left = 0;\n    }\n\n    while (ilen >= 64) {\n        if ((ret = mbedtls_internal_md5_process(ctx, input)) != 0) {\n            return ret;\n        }\n\n        input += 64;\n        ilen  -= 64;\n    }\n\n    if (ilen > 0) {\n        memcpy((void *) (ctx->buffer + left), input, ilen);\n    }\n\n    return 0;\n}\n\n/*\n * MD5 final digest\n */\nint mbedtls_md5_finish(mbedtls_md5_context *ctx,\n                       unsigned char output[16])\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    uint32_t used;\n    uint32_t high, low;\n\n    /*\n     * Add padding: 0x80 then 0x00 until 8 bytes remain for the length\n     */\n    used = ctx->total[0] & 0x3F;\n\n    ctx->buffer[used++] = 0x80;\n\n    if (used <= 56) {\n        /* Enough room for padding + length in current block */\n        memset(ctx->buffer + used, 0, 56 - used);\n    } else {\n        /* We'll need an extra block */\n        memset(ctx->buffer + used, 0, 64 - used);\n\n        if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) {\n            goto exit;\n        }\n\n        memset(ctx->buffer, 0, 56);\n    }\n\n    /*\n     * Add message length\n     */\n    high = (ctx->total[0] >> 29)\n           | (ctx->total[1] <<  3);\n    low  = (ctx->total[0] <<  3);\n\n    MBEDTLS_PUT_UINT32_LE(low,  ctx->buffer, 56);\n    MBEDTLS_PUT_UINT32_LE(high, ctx->buffer, 60);\n\n    if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) {\n        goto exit;\n    }\n\n    /*\n     * Output final state\n     */\n    MBEDTLS_PUT_UINT32_LE(ctx->state[0], output,  0);\n    MBEDTLS_PUT_UINT32_LE(ctx->state[1], output,  4);\n    MBEDTLS_PUT_UINT32_LE(ctx->state[2], output,  8);\n    MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12);\n\n    ret = 0;\n\nexit:\n    mbedtls_md5_free(ctx);\n    return ret;\n}\n\n#endif /* !MBEDTLS_MD5_ALT */\n\n/*\n * output = MD5( input buffer )\n */\nint mbedtls_md5(const unsigned char *input,\n                size_t ilen,\n                unsigned char output[16])\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_md5_context ctx;\n\n    mbedtls_md5_init(&ctx);\n\n    if ((ret = mbedtls_md5_starts(&ctx)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_md5_update(&ctx, input, ilen)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_md5_finish(&ctx, output)) != 0) {\n        goto exit;\n    }\n\nexit:\n    mbedtls_md5_free(&ctx);\n\n    return ret;\n}\n\n#if defined(MBEDTLS_SELF_TEST)\n/*\n * RFC 1321 test vectors\n */\nstatic const unsigned char md5_test_buf[7][81] =\n{\n    { \"\" },\n    { \"a\" },\n    { \"abc\" },\n    { \"message digest\" },\n    { \"abcdefghijklmnopqrstuvwxyz\" },\n    { \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" },\n    { \"12345678901234567890123456789012345678901234567890123456789012345678901234567890\" }\n};\n\nstatic const size_t md5_test_buflen[7] =\n{\n    0, 1, 3, 14, 26, 62, 80\n};\n\nstatic const unsigned char md5_test_sum[7][16] =\n{\n    { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,\n      0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },\n    { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,\n      0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },\n    { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,\n      0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },\n    { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,\n      0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },\n    { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,\n      0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },\n    { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,\n      0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },\n    { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,\n      0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }\n};\n\n/*\n * Checkup routine\n */\nint mbedtls_md5_self_test(int verbose)\n{\n    int i, ret = 0;\n    unsigned char md5sum[16];\n\n    for (i = 0; i < 7; i++) {\n        if (verbose != 0) {\n            mbedtls_printf(\"  MD5 test #%d: \", i + 1);\n        }\n\n        ret = mbedtls_md5(md5_test_buf[i], md5_test_buflen[i], md5sum);\n        if (ret != 0) {\n            goto fail;\n        }\n\n        if (memcmp(md5sum, md5_test_sum[i], 16) != 0) {\n            ret = 1;\n            goto fail;\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    return 0;\n\nfail:\n    if (verbose != 0) {\n        mbedtls_printf(\"failed\\n\");\n    }\n\n    return ret;\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_MD5_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/md_psa.h",
    "content": "/**\n * Translation between MD and PSA identifiers (algorithms, errors).\n *\n *  Note: this internal module will go away when everything becomes based on\n *  PSA Crypto; it is a helper for the transition period.\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_MD_PSA_H\n#define MBEDTLS_MD_PSA_H\n\n#include \"common.h\"\n\n#include \"mbedtls/md.h\"\n#include \"psa/crypto.h\"\n\n/** Convert PSA status to MD error code.\n *\n * \\param status    PSA status.\n *\n * \\return          The corresponding MD error code,\n */\nint mbedtls_md_error_from_psa(psa_status_t status);\n\n#endif /* MBEDTLS_MD_PSA_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/md_wrap.h",
    "content": "/**\n * \\file md_wrap.h\n *\n * \\brief Message digest wrappers.\n *\n * \\warning This in an internal header. Do not include directly.\n *\n * \\author Adriaan de Jong <dejong@fox-it.com>\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_MD_WRAP_H\n#define MBEDTLS_MD_WRAP_H\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/md.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Message digest information.\n * Allows message digest functions to be called in a generic way.\n */\nstruct mbedtls_md_info_t {\n    /** Digest identifier */\n    mbedtls_md_type_t type;\n\n    /** Output length of the digest function in bytes */\n    unsigned char size;\n\n#if defined(MBEDTLS_MD_C)\n    /** Block length of the digest function in bytes */\n    unsigned char block_size;\n#endif\n};\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MBEDTLS_MD_WRAP_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/memory_buffer_alloc.c",
    "content": "/*\n *  Buffer-based memory allocator\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)\n#include \"mbedtls/memory_buffer_alloc.h\"\n\n/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C\n   is dependent upon MBEDTLS_PLATFORM_C */\n#include \"mbedtls/platform.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_MEMORY_BACKTRACE)\n#include <execinfo.h>\n#endif\n\n#if defined(MBEDTLS_THREADING_C)\n#include \"mbedtls/threading.h\"\n#endif\n\n#define MAGIC1       0xFF00AA55\n#define MAGIC2       0xEE119966\n#define MAX_BT 20\n\ntypedef struct _memory_header memory_header;\nstruct _memory_header {\n    size_t          magic1;\n    size_t          size;\n    size_t          alloc;\n    memory_header   *prev;\n    memory_header   *next;\n    memory_header   *prev_free;\n    memory_header   *next_free;\n#if defined(MBEDTLS_MEMORY_BACKTRACE)\n    char            **trace;\n    size_t          trace_count;\n#endif\n    size_t          magic2;\n};\n\ntypedef struct {\n    unsigned char   *buf;\n    size_t          len;\n    memory_header   *first;\n    memory_header   *first_free;\n    int             verify;\n#if defined(MBEDTLS_MEMORY_DEBUG)\n    size_t          alloc_count;\n    size_t          free_count;\n    size_t          total_used;\n    size_t          maximum_used;\n    size_t          header_count;\n    size_t          maximum_header_count;\n#endif\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_threading_mutex_t   mutex;\n#endif\n}\nbuffer_alloc_ctx;\n\nstatic buffer_alloc_ctx heap;\n\n#if defined(MBEDTLS_MEMORY_DEBUG)\nstatic void debug_header(memory_header *hdr)\n{\n#if defined(MBEDTLS_MEMORY_BACKTRACE)\n    size_t i;\n#endif\n\n    mbedtls_fprintf(stderr, \"HDR:  PTR(%10zu), PREV(%10zu), NEXT(%10zu), \"\n                            \"ALLOC(%zu), SIZE(%10zu)\\n\",\n                    (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,\n                    hdr->alloc, hdr->size);\n    mbedtls_fprintf(stderr, \"      FPREV(%10zu), FNEXT(%10zu)\\n\",\n                    (size_t) hdr->prev_free, (size_t) hdr->next_free);\n\n#if defined(MBEDTLS_MEMORY_BACKTRACE)\n    mbedtls_fprintf(stderr, \"TRACE: \\n\");\n    for (i = 0; i < hdr->trace_count; i++) {\n        mbedtls_fprintf(stderr, \"%s\\n\", hdr->trace[i]);\n    }\n    mbedtls_fprintf(stderr, \"\\n\");\n#endif\n}\n\nstatic void debug_chain(void)\n{\n    memory_header *cur = heap.first;\n\n    mbedtls_fprintf(stderr, \"\\nBlock list\\n\");\n    while (cur != NULL) {\n        debug_header(cur);\n        cur = cur->next;\n    }\n\n    mbedtls_fprintf(stderr, \"Free list\\n\");\n    cur = heap.first_free;\n\n    while (cur != NULL) {\n        debug_header(cur);\n        cur = cur->next_free;\n    }\n}\n#endif /* MBEDTLS_MEMORY_DEBUG */\n\nstatic int verify_header(memory_header *hdr)\n{\n    if (hdr->magic1 != MAGIC1) {\n#if defined(MBEDTLS_MEMORY_DEBUG)\n        mbedtls_fprintf(stderr, \"FATAL: MAGIC1 mismatch\\n\");\n#endif\n        return 1;\n    }\n\n    if (hdr->magic2 != MAGIC2) {\n#if defined(MBEDTLS_MEMORY_DEBUG)\n        mbedtls_fprintf(stderr, \"FATAL: MAGIC2 mismatch\\n\");\n#endif\n        return 1;\n    }\n\n    if (hdr->alloc > 1) {\n#if defined(MBEDTLS_MEMORY_DEBUG)\n        mbedtls_fprintf(stderr, \"FATAL: alloc has illegal value\\n\");\n#endif\n        return 1;\n    }\n\n    if (hdr->prev != NULL && hdr->prev == hdr->next) {\n#if defined(MBEDTLS_MEMORY_DEBUG)\n        mbedtls_fprintf(stderr, \"FATAL: prev == next\\n\");\n#endif\n        return 1;\n    }\n\n    if (hdr->prev_free != NULL && hdr->prev_free == hdr->next_free) {\n#if defined(MBEDTLS_MEMORY_DEBUG)\n        mbedtls_fprintf(stderr, \"FATAL: prev_free == next_free\\n\");\n#endif\n        return 1;\n    }\n\n    return 0;\n}\n\nstatic int verify_chain(void)\n{\n    memory_header *prv = heap.first, *cur;\n\n    if (prv == NULL || verify_header(prv) != 0) {\n#if defined(MBEDTLS_MEMORY_DEBUG)\n        mbedtls_fprintf(stderr, \"FATAL: verification of first header \"\n                                \"failed\\n\");\n#endif\n        return 1;\n    }\n\n    if (heap.first->prev != NULL) {\n#if defined(MBEDTLS_MEMORY_DEBUG)\n        mbedtls_fprintf(stderr, \"FATAL: verification failed: \"\n                                \"first->prev != NULL\\n\");\n#endif\n        return 1;\n    }\n\n    cur = heap.first->next;\n\n    while (cur != NULL) {\n        if (verify_header(cur) != 0) {\n#if defined(MBEDTLS_MEMORY_DEBUG)\n            mbedtls_fprintf(stderr, \"FATAL: verification of header \"\n                                    \"failed\\n\");\n#endif\n            return 1;\n        }\n\n        if (cur->prev != prv) {\n#if defined(MBEDTLS_MEMORY_DEBUG)\n            mbedtls_fprintf(stderr, \"FATAL: verification failed: \"\n                                    \"cur->prev != prv\\n\");\n#endif\n            return 1;\n        }\n\n        prv = cur;\n        cur = cur->next;\n    }\n\n    return 0;\n}\n\nstatic void *buffer_alloc_calloc(size_t n, size_t size)\n{\n    memory_header *new, *cur = heap.first_free;\n    unsigned char *p;\n    void *ret;\n    size_t original_len, len;\n#if defined(MBEDTLS_MEMORY_BACKTRACE)\n    void *trace_buffer[MAX_BT];\n    size_t trace_cnt;\n#endif\n\n    if (heap.buf == NULL || heap.first == NULL) {\n        return NULL;\n    }\n\n    original_len = len = n * size;\n\n    if (n == 0 || size == 0 || len / n != size) {\n        return NULL;\n    } else if (len > (size_t) -MBEDTLS_MEMORY_ALIGN_MULTIPLE) {\n        return NULL;\n    }\n\n    if (len % MBEDTLS_MEMORY_ALIGN_MULTIPLE) {\n        len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE;\n        len += MBEDTLS_MEMORY_ALIGN_MULTIPLE;\n    }\n\n    // Find block that fits\n    //\n    while (cur != NULL) {\n        if (cur->size >= len) {\n            break;\n        }\n\n        cur = cur->next_free;\n    }\n\n    if (cur == NULL) {\n        return NULL;\n    }\n\n    if (cur->alloc != 0) {\n#if defined(MBEDTLS_MEMORY_DEBUG)\n        mbedtls_fprintf(stderr, \"FATAL: block in free_list but allocated \"\n                                \"data\\n\");\n#endif\n        mbedtls_exit(1);\n    }\n\n#if defined(MBEDTLS_MEMORY_DEBUG)\n    heap.alloc_count++;\n#endif\n\n    // Found location, split block if > memory_header + 4 room left\n    //\n    if (cur->size - len < sizeof(memory_header) +\n        MBEDTLS_MEMORY_ALIGN_MULTIPLE) {\n        cur->alloc = 1;\n\n        // Remove from free_list\n        //\n        if (cur->prev_free != NULL) {\n            cur->prev_free->next_free = cur->next_free;\n        } else {\n            heap.first_free = cur->next_free;\n        }\n\n        if (cur->next_free != NULL) {\n            cur->next_free->prev_free = cur->prev_free;\n        }\n\n        cur->prev_free = NULL;\n        cur->next_free = NULL;\n\n#if defined(MBEDTLS_MEMORY_DEBUG)\n        heap.total_used += cur->size;\n        if (heap.total_used > heap.maximum_used) {\n            heap.maximum_used = heap.total_used;\n        }\n#endif\n#if defined(MBEDTLS_MEMORY_BACKTRACE)\n        trace_cnt = backtrace(trace_buffer, MAX_BT);\n        cur->trace = backtrace_symbols(trace_buffer, trace_cnt);\n        cur->trace_count = trace_cnt;\n#endif\n\n        if ((heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC) && verify_chain() != 0) {\n            mbedtls_exit(1);\n        }\n\n        ret = (unsigned char *) cur + sizeof(memory_header);\n        memset(ret, 0, original_len);\n\n        return ret;\n    }\n\n    p = ((unsigned char *) cur) + sizeof(memory_header) + len;\n    new = (memory_header *) p;\n\n    new->size = cur->size - len - sizeof(memory_header);\n    new->alloc = 0;\n    new->prev = cur;\n    new->next = cur->next;\n#if defined(MBEDTLS_MEMORY_BACKTRACE)\n    new->trace = NULL;\n    new->trace_count = 0;\n#endif\n    new->magic1 = MAGIC1;\n    new->magic2 = MAGIC2;\n\n    if (new->next != NULL) {\n        new->next->prev = new;\n    }\n\n    // Replace cur with new in free_list\n    //\n    new->prev_free = cur->prev_free;\n    new->next_free = cur->next_free;\n    if (new->prev_free != NULL) {\n        new->prev_free->next_free = new;\n    } else {\n        heap.first_free = new;\n    }\n\n    if (new->next_free != NULL) {\n        new->next_free->prev_free = new;\n    }\n\n    cur->alloc = 1;\n    cur->size = len;\n    cur->next = new;\n    cur->prev_free = NULL;\n    cur->next_free = NULL;\n\n#if defined(MBEDTLS_MEMORY_DEBUG)\n    heap.header_count++;\n    if (heap.header_count > heap.maximum_header_count) {\n        heap.maximum_header_count = heap.header_count;\n    }\n    heap.total_used += cur->size;\n    if (heap.total_used > heap.maximum_used) {\n        heap.maximum_used = heap.total_used;\n    }\n#endif\n#if defined(MBEDTLS_MEMORY_BACKTRACE)\n    trace_cnt = backtrace(trace_buffer, MAX_BT);\n    cur->trace = backtrace_symbols(trace_buffer, trace_cnt);\n    cur->trace_count = trace_cnt;\n#endif\n\n    if ((heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC) && verify_chain() != 0) {\n        mbedtls_exit(1);\n    }\n\n    ret = (unsigned char *) cur + sizeof(memory_header);\n    memset(ret, 0, original_len);\n\n    return ret;\n}\n\nstatic void buffer_alloc_free(void *ptr)\n{\n    memory_header *hdr, *old = NULL;\n    unsigned char *p = (unsigned char *) ptr;\n\n    if (ptr == NULL || heap.buf == NULL || heap.first == NULL) {\n        return;\n    }\n\n    if (p < heap.buf || p >= heap.buf + heap.len) {\n#if defined(MBEDTLS_MEMORY_DEBUG)\n        mbedtls_fprintf(stderr, \"FATAL: mbedtls_free() outside of managed \"\n                                \"space\\n\");\n#endif\n        mbedtls_exit(1);\n    }\n\n    p -= sizeof(memory_header);\n    hdr = (memory_header *) p;\n\n    if (verify_header(hdr) != 0) {\n        mbedtls_exit(1);\n    }\n\n    if (hdr->alloc != 1) {\n#if defined(MBEDTLS_MEMORY_DEBUG)\n        mbedtls_fprintf(stderr, \"FATAL: mbedtls_free() on unallocated \"\n                                \"data\\n\");\n#endif\n        mbedtls_exit(1);\n    }\n\n    hdr->alloc = 0;\n\n#if defined(MBEDTLS_MEMORY_DEBUG)\n    heap.free_count++;\n    heap.total_used -= hdr->size;\n#endif\n\n#if defined(MBEDTLS_MEMORY_BACKTRACE)\n    free(hdr->trace);\n    hdr->trace = NULL;\n    hdr->trace_count = 0;\n#endif\n\n    // Regroup with block before\n    //\n    if (hdr->prev != NULL && hdr->prev->alloc == 0) {\n#if defined(MBEDTLS_MEMORY_DEBUG)\n        heap.header_count--;\n#endif\n        hdr->prev->size += sizeof(memory_header) + hdr->size;\n        hdr->prev->next = hdr->next;\n        old = hdr;\n        hdr = hdr->prev;\n\n        if (hdr->next != NULL) {\n            hdr->next->prev = hdr;\n        }\n\n        memset(old, 0, sizeof(memory_header));\n    }\n\n    // Regroup with block after\n    //\n    if (hdr->next != NULL && hdr->next->alloc == 0) {\n#if defined(MBEDTLS_MEMORY_DEBUG)\n        heap.header_count--;\n#endif\n        hdr->size += sizeof(memory_header) + hdr->next->size;\n        old = hdr->next;\n        hdr->next = hdr->next->next;\n\n        if (hdr->prev_free != NULL || hdr->next_free != NULL) {\n            if (hdr->prev_free != NULL) {\n                hdr->prev_free->next_free = hdr->next_free;\n            } else {\n                heap.first_free = hdr->next_free;\n            }\n\n            if (hdr->next_free != NULL) {\n                hdr->next_free->prev_free = hdr->prev_free;\n            }\n        }\n\n        hdr->prev_free = old->prev_free;\n        hdr->next_free = old->next_free;\n\n        if (hdr->prev_free != NULL) {\n            hdr->prev_free->next_free = hdr;\n        } else {\n            heap.first_free = hdr;\n        }\n\n        if (hdr->next_free != NULL) {\n            hdr->next_free->prev_free = hdr;\n        }\n\n        if (hdr->next != NULL) {\n            hdr->next->prev = hdr;\n        }\n\n        memset(old, 0, sizeof(memory_header));\n    }\n\n    // Prepend to free_list if we have not merged\n    // (Does not have to stay in same order as prev / next list)\n    //\n    if (old == NULL) {\n        hdr->next_free = heap.first_free;\n        if (heap.first_free != NULL) {\n            heap.first_free->prev_free = hdr;\n        }\n        heap.first_free = hdr;\n    }\n\n    if ((heap.verify & MBEDTLS_MEMORY_VERIFY_FREE) && verify_chain() != 0) {\n        mbedtls_exit(1);\n    }\n}\n\nvoid mbedtls_memory_buffer_set_verify(int verify)\n{\n    heap.verify = verify;\n}\n\nint mbedtls_memory_buffer_alloc_verify(void)\n{\n    return verify_chain();\n}\n\n#if defined(MBEDTLS_MEMORY_DEBUG)\nvoid mbedtls_memory_buffer_alloc_status(void)\n{\n    mbedtls_fprintf(stderr,\n                    \"Current use: %zu blocks / %zu bytes, max: %zu blocks / \"\n                    \"%zu bytes (total %zu bytes), alloc / free: %zu / %zu\\n\",\n                    heap.header_count, heap.total_used,\n                    heap.maximum_header_count, heap.maximum_used,\n                    heap.maximum_header_count * sizeof(memory_header)\n                    + heap.maximum_used,\n                    heap.alloc_count, heap.free_count);\n\n    if (heap.first->next == NULL) {\n        mbedtls_fprintf(stderr, \"All memory de-allocated in stack buffer\\n\");\n    } else {\n        mbedtls_fprintf(stderr, \"Memory currently allocated:\\n\");\n        debug_chain();\n    }\n}\n\nvoid mbedtls_memory_buffer_alloc_count_get(size_t *alloc_count, size_t *free_count)\n{\n    *alloc_count = heap.alloc_count;\n    *free_count = heap.free_count;\n}\n\nvoid mbedtls_memory_buffer_alloc_max_get(size_t *max_used, size_t *max_blocks)\n{\n    *max_used   = heap.maximum_used;\n    *max_blocks = heap.maximum_header_count;\n}\n\nvoid mbedtls_memory_buffer_alloc_max_reset(void)\n{\n    heap.maximum_used = 0;\n    heap.maximum_header_count = 0;\n}\n\nvoid mbedtls_memory_buffer_alloc_cur_get(size_t *cur_used, size_t *cur_blocks)\n{\n    *cur_used   = heap.total_used;\n    *cur_blocks = heap.header_count;\n}\n#endif /* MBEDTLS_MEMORY_DEBUG */\n\n#if defined(MBEDTLS_THREADING_C)\nstatic void *buffer_alloc_calloc_mutexed(size_t n, size_t size)\n{\n    void *buf;\n    if (mbedtls_mutex_lock(&heap.mutex) != 0) {\n        return NULL;\n    }\n    buf = buffer_alloc_calloc(n, size);\n    if (mbedtls_mutex_unlock(&heap.mutex)) {\n        return NULL;\n    }\n    return buf;\n}\n\nstatic void buffer_alloc_free_mutexed(void *ptr)\n{\n    /* We have no good option here, but corrupting the heap seems\n     * worse than losing memory. */\n    if (mbedtls_mutex_lock(&heap.mutex)) {\n        return;\n    }\n    buffer_alloc_free(ptr);\n    (void) mbedtls_mutex_unlock(&heap.mutex);\n}\n#endif /* MBEDTLS_THREADING_C */\n\nvoid mbedtls_memory_buffer_alloc_init(unsigned char *buf, size_t len)\n{\n    memset(&heap, 0, sizeof(buffer_alloc_ctx));\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_init(&heap.mutex);\n    mbedtls_platform_set_calloc_free(buffer_alloc_calloc_mutexed,\n                                     buffer_alloc_free_mutexed);\n#else\n    mbedtls_platform_set_calloc_free(buffer_alloc_calloc, buffer_alloc_free);\n#endif\n\n    if (len < sizeof(memory_header) + MBEDTLS_MEMORY_ALIGN_MULTIPLE) {\n        return;\n    } else if ((size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE) {\n        /* Adjust len first since buf is used in the computation */\n        len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE\n               - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;\n        buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE\n               - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;\n    }\n\n    memset(buf, 0, len);\n\n    heap.buf = buf;\n    heap.len = len;\n\n    heap.first = (memory_header *) buf;\n    heap.first->size = len - sizeof(memory_header);\n    heap.first->magic1 = MAGIC1;\n    heap.first->magic2 = MAGIC2;\n    heap.first_free = heap.first;\n}\n\nvoid mbedtls_memory_buffer_alloc_free(void)\n{\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_free(&heap.mutex);\n#endif\n    mbedtls_platform_zeroize(&heap, sizeof(buffer_alloc_ctx));\n}\n\n#if defined(MBEDTLS_SELF_TEST)\nstatic int check_pointer(void *p)\n{\n    if (p == NULL) {\n        return -1;\n    }\n\n    if ((size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0) {\n        return -1;\n    }\n\n    return 0;\n}\n\nstatic int check_all_free(void)\n{\n    if (\n#if defined(MBEDTLS_MEMORY_DEBUG)\n        heap.total_used != 0 ||\n#endif\n        heap.first != heap.first_free ||\n        (void *) heap.first != (void *) heap.buf) {\n        return -1;\n    }\n\n    return 0;\n}\n\n#define TEST_ASSERT(condition)            \\\n    if (!(condition))                     \\\n    {                                       \\\n        if (verbose != 0)                  \\\n        mbedtls_printf(\"failed\\n\");  \\\n                                            \\\n        ret = 1;                            \\\n        goto cleanup;                       \\\n    }\n\nint mbedtls_memory_buffer_alloc_self_test(int verbose)\n{\n    unsigned char buf[1024];\n    unsigned char *p, *q, *r, *end;\n    int ret = 0;\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  MBA test #1 (basic alloc-free cycle): \");\n    }\n\n    mbedtls_memory_buffer_alloc_init(buf, sizeof(buf));\n\n    p = mbedtls_calloc(1, 1);\n    q = mbedtls_calloc(1, 128);\n    r = mbedtls_calloc(1, 16);\n\n    TEST_ASSERT(check_pointer(p) == 0 &&\n                check_pointer(q) == 0 &&\n                check_pointer(r) == 0);\n\n    mbedtls_free(r);\n    mbedtls_free(q);\n    mbedtls_free(p);\n\n    TEST_ASSERT(check_all_free() == 0);\n\n    /* Memorize end to compare with the next test */\n    end = heap.buf + heap.len;\n\n    mbedtls_memory_buffer_alloc_free();\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  MBA test #2 (buf not aligned): \");\n    }\n\n    mbedtls_memory_buffer_alloc_init(buf + 1, sizeof(buf) - 1);\n\n    TEST_ASSERT(heap.buf + heap.len == end);\n\n    p = mbedtls_calloc(1, 1);\n    q = mbedtls_calloc(1, 128);\n    r = mbedtls_calloc(1, 16);\n\n    TEST_ASSERT(check_pointer(p) == 0 &&\n                check_pointer(q) == 0 &&\n                check_pointer(r) == 0);\n\n    mbedtls_free(r);\n    mbedtls_free(q);\n    mbedtls_free(p);\n\n    TEST_ASSERT(check_all_free() == 0);\n\n    mbedtls_memory_buffer_alloc_free();\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  MBA test #3 (full): \");\n    }\n\n    mbedtls_memory_buffer_alloc_init(buf, sizeof(buf));\n\n    p = mbedtls_calloc(1, sizeof(buf) - sizeof(memory_header));\n\n    TEST_ASSERT(check_pointer(p) == 0);\n    TEST_ASSERT(mbedtls_calloc(1, 1) == NULL);\n\n    mbedtls_free(p);\n\n    p = mbedtls_calloc(1, sizeof(buf) - 2 * sizeof(memory_header) - 16);\n    q = mbedtls_calloc(1, 16);\n\n    TEST_ASSERT(check_pointer(p) == 0 && check_pointer(q) == 0);\n    TEST_ASSERT(mbedtls_calloc(1, 1) == NULL);\n\n    mbedtls_free(q);\n\n    TEST_ASSERT(mbedtls_calloc(1, 17) == NULL);\n\n    mbedtls_free(p);\n\n    TEST_ASSERT(check_all_free() == 0);\n\n    mbedtls_memory_buffer_alloc_free();\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\ncleanup:\n    mbedtls_memory_buffer_alloc_free();\n\n    return ret;\n}\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/mps_common.h",
    "content": "/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/**\n * \\file mps_common.h\n *\n * \\brief Common functions and macros used by MPS\n */\n\n#ifndef MBEDTLS_MPS_COMMON_H\n#define MBEDTLS_MPS_COMMON_H\n\n#include \"mps_error.h\"\n\n#include <stdio.h>\n\n/**\n * \\name SECTION:       MPS Configuration\n *\n * \\{\n */\n\n/*! This flag controls whether the MPS-internal components\n *  (reader, writer, Layer 1-3) perform validation of the\n *  expected abstract state at the entry of API calls.\n *\n *  Context: All MPS API functions impose assumptions/preconditions on the\n *  context on which they operate. For example, every structure has a notion of\n *  state integrity which is established by `xxx_init()` and preserved by any\n *  calls to the MPS API which satisfy their preconditions and either succeed,\n *  or fail with an error code which is explicitly documented to not corrupt\n *  structure integrity (such as WANT_READ and WANT_WRITE);\n *  apart from `xxx_init()` any function assumes state integrity as a\n *  precondition (but usually more). If any of the preconditions is violated,\n *  the function's behavior is entirely undefined.\n *  In addition to state integrity, all MPS structures have a more refined\n *  notion of abstract state that the API operates on. For example, all layers\n *  have a notion of 'abstract read state' which indicates if incoming data has\n *  been passed to the user, e.g. through mps_l2_read_start() for Layer 2\n *  or mps_l3_read() in Layer 3. After such a call, it doesn't make sense to\n *  call these reading functions again until the incoming data has been\n *  explicitly 'consumed', e.g. through mps_l2_read_consume() for Layer 2 or\n *  mps_l3_read_consume() on Layer 3. However, even if it doesn't make sense,\n *  it's a design choice whether the API should fail gracefully on such\n *  non-sensical calls or not, and that's what this option is about:\n *\n *  This option determines whether the expected abstract state\n *  is part of the API preconditions or not: If the option is set,\n *  then the abstract state is not part of the precondition and is\n *  thus required to be validated by the implementation. If an unexpected\n *  abstract state is encountered, the implementation must fail gracefully\n *  with error #MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED.\n *  Conversely, if this option is not set, then the expected abstract state\n *  is included in the preconditions of the respective API calls, and\n *  an implementation's behaviour is undefined if the abstract state is\n *  not as expected.\n *\n *  For example: Enabling this makes mps_l2_read_done() fail if\n *  no incoming record is currently open; disabling this would\n *  lead to undefined behavior in this case.\n *\n *  Comment this to remove state validation.\n */\n#define MBEDTLS_MPS_STATE_VALIDATION\n\n/*! This flag enables/disables assertions on the internal state of MPS.\n *\n *  Assertions are sanity checks that should never trigger when MPS\n *  is used within the bounds of its API and preconditions.\n *\n *  Enabling this increases security by limiting the scope of\n *  potential bugs, but comes at the cost of increased code size.\n *\n *  Note: So far, there is no guiding principle as to what\n *  expected conditions merit an assertion, and which don't.\n *\n *  Comment this to disable assertions.\n */\n#define MBEDTLS_MPS_ENABLE_ASSERTIONS\n\n/*! This flag controls whether tracing for MPS should be enabled. */\n//#define MBEDTLS_MPS_ENABLE_TRACE\n\n#if defined(MBEDTLS_MPS_STATE_VALIDATION)\n\n#define MBEDTLS_MPS_STATE_VALIDATE_RAW(cond, string)                         \\\n    do                                                                         \\\n    {                                                                          \\\n        if (!(cond))                                                          \\\n        {                                                                      \\\n            MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_ERROR, string);         \\\n            MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED);  \\\n        }                                                                      \\\n    } while (0)\n\n#else /* MBEDTLS_MPS_STATE_VALIDATION */\n\n#define MBEDTLS_MPS_STATE_VALIDATE_RAW(cond, string)           \\\n    do                                                           \\\n    {                                                            \\\n        (cond);                                                \\\n    } while (0)\n\n#endif /* MBEDTLS_MPS_STATE_VALIDATION */\n\n#if defined(MBEDTLS_MPS_ENABLE_ASSERTIONS)\n\n#define MBEDTLS_MPS_ASSERT_RAW(cond, string)                          \\\n    do                                                                  \\\n    {                                                                   \\\n        if (!(cond))                                                   \\\n        {                                                               \\\n            MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_ERROR, string);  \\\n            MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_INTERNAL_ERROR); \\\n        }                                                               \\\n    } while (0)\n\n#else /* MBEDTLS_MPS_ENABLE_ASSERTIONS */\n\n#define MBEDTLS_MPS_ASSERT_RAW(cond, string) do {} while (0)\n\n#endif /* MBEDTLS_MPS_ENABLE_ASSERTIONS */\n\n\n/* \\} name SECTION: MPS Configuration */\n\n/**\n * \\name SECTION:       Common types\n *\n * Various common types used throughout MPS.\n * \\{\n */\n\n/** \\brief   The type of buffer sizes and offsets used in MPS structures.\n *\n *           This is an unsigned integer type that should be large enough to\n *           hold the length of any buffer or message processed by MPS.\n *\n *           The reason to pick a value as small as possible here is\n *           to reduce the size of MPS structures.\n *\n * \\warning  Care has to be taken when using a narrower type\n *           than ::mbedtls_mps_size_t here because of\n *           potential truncation during conversion.\n *\n * \\warning  Handshake messages in TLS may be up to 2^24 ~ 16Mb in size.\n *           If mbedtls_mps_[opt_]stored_size_t is smaller than that, the\n *           maximum handshake message is restricted accordingly.\n *\n * For now, we use the default type of size_t throughout, and the use of\n * smaller types or different types for ::mbedtls_mps_size_t and\n * ::mbedtls_mps_stored_size_t is not yet supported.\n *\n */\ntypedef size_t mbedtls_mps_stored_size_t;\n#define MBEDTLS_MPS_STORED_SIZE_MAX  (SIZE_MAX)\n\n/** \\brief The type of buffer sizes and offsets used in the MPS API\n *         and implementation.\n *\n *         This must be at least as wide as ::mbedtls_stored_size_t but\n *         may be chosen to be strictly larger if more suitable for the\n *         target architecture.\n *\n *         For example, in a test build for ARM Thumb, using uint_fast16_t\n *         instead of uint16_t reduced the code size from 1060 Byte to 962 Byte,\n *         so almost 10%.\n */\ntypedef size_t mbedtls_mps_size_t;\n#define MBEDTLS_MPS_SIZE_MAX  (SIZE_MAX)\n\n#if MBEDTLS_MPS_STORED_SIZE_MAX > MBEDTLS_MPS_SIZE_MAX\n#error \"Misconfiguration of mbedtls_mps_size_t and mbedtls_mps_stored_size_t.\"\n#endif\n\n/* \\} SECTION: Common types */\n\n\n#endif /* MBEDTLS_MPS_COMMON_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/mps_error.h",
    "content": "/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/**\n * \\file mps_error.h\n *\n * \\brief Error codes used by MPS\n */\n\n#ifndef MBEDTLS_MPS_ERROR_H\n#define MBEDTLS_MPS_ERROR_H\n\n\n/* TODO: The error code allocation needs to be revisited:\n *\n * - Should we make (some of) the MPS Reader error codes public?\n *   If so, we need to adjust MBEDTLS_MPS_READER_MAKE_ERROR() to hit\n *   a gap in the Mbed TLS public error space.\n *   If not, we have to make sure we don't forward those errors\n *   at the level of the public API -- no risk at the moment as\n *   long as MPS is an experimental component not accessible from\n *   public API.\n */\n\n/**\n * \\name SECTION:       MPS general error codes\n *\n * \\{\n */\n\n#ifndef MBEDTLS_MPS_ERR_BASE\n#define MBEDTLS_MPS_ERR_BASE (0)\n#endif\n\n#define MBEDTLS_MPS_MAKE_ERROR(code) \\\n    (-(MBEDTLS_MPS_ERR_BASE | (code)))\n\n#define MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED  MBEDTLS_MPS_MAKE_ERROR(0x1)\n#define MBEDTLS_ERR_MPS_INTERNAL_ERROR        MBEDTLS_MPS_MAKE_ERROR(0x2)\n\n/* \\} name SECTION: MPS general error codes */\n\n/**\n * \\name SECTION:       MPS Reader error codes\n *\n * \\{\n */\n\n#ifndef MBEDTLS_MPS_READER_ERR_BASE\n#define MBEDTLS_MPS_READER_ERR_BASE (1 << 8)\n#endif\n\n#define MBEDTLS_MPS_READER_MAKE_ERROR(code) \\\n    (-(MBEDTLS_MPS_READER_ERR_BASE | (code)))\n\n/*! An attempt to reclaim the data buffer from a reader failed because\n *  the user hasn't yet read and committed all of it. */\n#define MBEDTLS_ERR_MPS_READER_DATA_LEFT             MBEDTLS_MPS_READER_MAKE_ERROR(0x1)\n\n/*! An invalid argument was passed to the reader. */\n#define MBEDTLS_ERR_MPS_READER_INVALID_ARG           MBEDTLS_MPS_READER_MAKE_ERROR(0x2)\n\n/*! An attempt to move a reader to consuming mode through mbedtls_mps_reader_feed()\n *  after pausing failed because the provided data is not sufficient to serve the\n *  read requests that led to the pausing. */\n#define MBEDTLS_ERR_MPS_READER_NEED_MORE             MBEDTLS_MPS_READER_MAKE_ERROR(0x3)\n\n/*! A get request failed because not enough data is available in the reader. */\n#define MBEDTLS_ERR_MPS_READER_OUT_OF_DATA           MBEDTLS_MPS_READER_MAKE_ERROR(0x4)\n\n/*!< A get request after pausing and reactivating the reader failed because\n *   the request is not in line with the request made prior to pausing. The user\n *   must not change it's 'strategy' after pausing and reactivating a reader. */\n#define MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS MBEDTLS_MPS_READER_MAKE_ERROR(0x5)\n\n/*! An attempt to reclaim the data buffer from a reader failed because the reader\n *  has no accumulator it can use to backup the data that hasn't been processed. */\n#define MBEDTLS_ERR_MPS_READER_NEED_ACCUMULATOR      MBEDTLS_MPS_READER_MAKE_ERROR(0x6)\n\n/*! An attempt to reclaim the data buffer from a reader failed because the\n *  accumulator passed to the reader is not large enough to hold both the\n *  data that hasn't been processed and the excess of the last read-request. */\n#define MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL MBEDTLS_MPS_READER_MAKE_ERROR(0x7)\n\n/* \\} name SECTION: MPS Reader error codes */\n\n#endif /* MBEDTLS_MPS_ERROR_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/mps_reader.c",
    "content": "/*\n *  Message Processing Stack, Reader implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n\n#include \"mps_reader.h\"\n#include \"mps_common.h\"\n#include \"mps_trace.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_MPS_ENABLE_TRACE)\nstatic int mbedtls_mps_trace_id = MBEDTLS_MPS_TRACE_BIT_READER;\n#endif /* MBEDTLS_MPS_ENABLE_TRACE */\n\n/*\n * GENERAL NOTE ON CODING STYLE\n *\n * The following code intentionally separates memory loads\n * and stores from other operations (arithmetic or branches).\n * This leads to the introduction of many local variables\n * and significantly increases the C-code line count, but\n * should not increase the size of generated assembly.\n *\n * The reason for this is twofold:\n * (1) It will ease verification efforts using the VST\n *     (Verified Software Toolchain)\n *     whose program logic cannot directly reason\n *     about instructions containing a load or store in\n *     addition to other operations (e.g. *p = *q or\n *     tmp = *p + 42).\n * (2) Operating on local variables and writing the results\n *     back to the target contexts on success only\n *     allows to maintain structure invariants even\n *     on failure - this in turn has two benefits:\n *     (2.a) If for some reason an error code is not caught\n *           and operation continues, functions are nonetheless\n *           called with sane contexts, reducing the risk\n *           of dangerous behavior.\n *     (2.b) Randomized testing is easier if structures\n *           remain intact even in the face of failing\n *           and/or non-sensical calls.\n *     Moreover, it might even reduce code-size because\n *     the compiler need not write back temporary results\n *     to memory in case of failure.\n *\n */\n\nstatic inline int mps_reader_is_accumulating(\n    mbedtls_mps_reader const *rd)\n{\n    mbedtls_mps_size_t acc_remaining;\n    if (rd->acc == NULL) {\n        return 0;\n    }\n\n    acc_remaining = rd->acc_share.acc_remaining;\n    return acc_remaining > 0;\n}\n\nstatic inline int mps_reader_is_producing(\n    mbedtls_mps_reader const *rd)\n{\n    unsigned char *frag = rd->frag;\n    return frag == NULL;\n}\n\nstatic inline int mps_reader_is_consuming(\n    mbedtls_mps_reader const *rd)\n{\n    return !mps_reader_is_producing(rd);\n}\n\nstatic inline mbedtls_mps_size_t mps_reader_get_fragment_offset(\n    mbedtls_mps_reader const *rd)\n{\n    unsigned char *acc = rd->acc;\n    mbedtls_mps_size_t frag_offset;\n\n    if (acc == NULL) {\n        return 0;\n    }\n\n    frag_offset = rd->acc_share.frag_offset;\n    return frag_offset;\n}\n\nstatic inline mbedtls_mps_size_t mps_reader_serving_from_accumulator(\n    mbedtls_mps_reader const *rd)\n{\n    mbedtls_mps_size_t frag_offset, end;\n\n    frag_offset = mps_reader_get_fragment_offset(rd);\n    end = rd->end;\n\n    return end < frag_offset;\n}\n\nstatic inline void mps_reader_zero(mbedtls_mps_reader *rd)\n{\n    /* A plain memset() would likely be more efficient,\n     * but the current way of zeroing makes it harder\n     * to overlook fields which should not be zero-initialized.\n     * It's also more suitable for FV efforts since it\n     * doesn't require reasoning about structs being\n     * interpreted as unstructured binary blobs. */\n    static mbedtls_mps_reader const zero =\n    { .frag          = NULL,\n      .frag_len      = 0,\n      .commit        = 0,\n      .end           = 0,\n      .pending       = 0,\n      .acc           = NULL,\n      .acc_len       = 0,\n      .acc_available = 0,\n      .acc_share     = { .acc_remaining = 0 } };\n    *rd = zero;\n}\n\nint mbedtls_mps_reader_init(mbedtls_mps_reader *rd,\n                            unsigned char *acc,\n                            mbedtls_mps_size_t acc_len)\n{\n    MBEDTLS_MPS_TRACE_INIT(\"mbedtls_mps_reader_init\");\n    MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                      \"* Accumulator size: %u bytes\", (unsigned) acc_len);\n    mps_reader_zero(rd);\n    rd->acc = acc;\n    rd->acc_len = acc_len;\n    MBEDTLS_MPS_TRACE_RETURN(0);\n}\n\nint mbedtls_mps_reader_free(mbedtls_mps_reader *rd)\n{\n    MBEDTLS_MPS_TRACE_INIT(\"mbedtls_mps_reader_free\");\n    mps_reader_zero(rd);\n    MBEDTLS_MPS_TRACE_RETURN(0);\n}\n\nint mbedtls_mps_reader_feed(mbedtls_mps_reader *rd,\n                            unsigned char *new_frag,\n                            mbedtls_mps_size_t new_frag_len)\n{\n    mbedtls_mps_size_t copy_to_acc;\n    MBEDTLS_MPS_TRACE_INIT(\"mbedtls_mps_reader_feed\");\n    MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                      \"* Fragment length: %u bytes\", (unsigned) new_frag_len);\n\n    if (new_frag == NULL) {\n        MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_READER_INVALID_ARG);\n    }\n\n    MBEDTLS_MPS_STATE_VALIDATE_RAW(mps_reader_is_producing(\n                                       rd),\n                                   \"mbedtls_mps_reader_feed() requires reader to be in producing mode\");\n\n    if (mps_reader_is_accumulating(rd)) {\n        unsigned char *acc    = rd->acc;\n        mbedtls_mps_size_t acc_remaining = rd->acc_share.acc_remaining;\n        mbedtls_mps_size_t acc_available = rd->acc_available;\n\n        /* Skip over parts of the accumulator that have already been filled. */\n        acc += acc_available;\n\n        copy_to_acc = acc_remaining;\n        if (copy_to_acc > new_frag_len) {\n            copy_to_acc = new_frag_len;\n        }\n\n        /* Copy new contents to accumulator. */\n        memcpy(acc, new_frag, copy_to_acc);\n\n        MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                          \"Copy new data of size %u of %u into accumulator at offset %u\",\n                          (unsigned) copy_to_acc, (unsigned) new_frag_len,\n                          (unsigned) acc_available);\n\n        /* Check if, with the new fragment, we have enough data. */\n        acc_remaining -= copy_to_acc;\n        if (acc_remaining > 0) {\n            /* We need to accumulate more data. Stay in producing mode. */\n            acc_available += copy_to_acc;\n            rd->acc_share.acc_remaining = acc_remaining;\n            rd->acc_available = acc_available;\n            MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_READER_NEED_MORE);\n        }\n\n        /* We have filled the accumulator: Move to consuming mode. */\n\n        MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                          \"Enough data available to serve user request\");\n\n        /* Remember overlap of accumulator and fragment. */\n        rd->acc_share.frag_offset = acc_available;\n        acc_available += copy_to_acc;\n        rd->acc_available = acc_available;\n    } else { /* Not accumulating */\n        rd->acc_share.frag_offset = 0;\n    }\n\n    rd->frag = new_frag;\n    rd->frag_len = new_frag_len;\n    rd->commit = 0;\n    rd->end = 0;\n    MBEDTLS_MPS_TRACE_RETURN(0);\n}\n\n\nint mbedtls_mps_reader_get(mbedtls_mps_reader *rd,\n                           mbedtls_mps_size_t desired,\n                           unsigned char **buffer,\n                           mbedtls_mps_size_t *buflen)\n{\n    unsigned char *frag;\n    mbedtls_mps_size_t frag_len, frag_offset, end, frag_fetched, frag_remaining;\n    MBEDTLS_MPS_TRACE_INIT(\"mbedtls_mps_reader_get\");\n    MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                      \"* Bytes requested: %u\", (unsigned) desired);\n\n    MBEDTLS_MPS_STATE_VALIDATE_RAW(mps_reader_is_consuming(\n                                       rd),\n                                   \"mbedtls_mps_reader_get() requires reader to be in consuming mode\");\n\n    end = rd->end;\n    frag_offset = mps_reader_get_fragment_offset(rd);\n\n    /* Check if we're still serving from the accumulator. */\n    if (mps_reader_serving_from_accumulator(rd)) {\n        /* Illustration of supported and unsupported cases:\n         *\n         * - Allowed #1\n         *\n         *                          +-----------------------------------+\n         *                          |               frag                |\n         *                          +-----------------------------------+\n         *\n         *             end end+desired\n         *              |       |\n         *        +-----v-------v-------------+\n         *        |          acc              |\n         *        +---------------------------+\n         *                          |         |\n         *                     frag_offset  acc_available\n         *\n         * - Allowed #2\n         *\n         *                          +-----------------------------------+\n         *                          |               frag                |\n         *                          +-----------------------------------+\n         *\n         *                  end          end+desired\n         *                   |                |\n         *        +----------v----------------v\n         *        |          acc              |\n         *        +---------------------------+\n         *                          |         |\n         *                   frag_offset acc_available\n         *\n         * - Not allowed #1 (could be served, but we don't actually use it):\n         *\n         *                      +-----------------------------------+\n         *                      |               frag                |\n         *                      +-----------------------------------+\n         *\n         *              end        end+desired\n         *               |             |\n         *        +------v-------------v------+\n         *        |          acc              |\n         *        +---------------------------+\n         *                      |             |\n         *                frag_offset   acc_available\n         *\n         *\n         * - Not allowed #2 (can't be served with a contiguous buffer):\n         *\n         *                      +-----------------------------------+\n         *                      |               frag                |\n         *                      +-----------------------------------+\n         *\n         *              end                 end + desired\n         *               |                        |\n         *        +------v--------------------+   v\n         *        |            acc            |\n         *        +---------------------------+\n         *                      |             |\n         *                frag_offset   acc_available\n         *\n         * In case of Allowed #2 we're switching to serve from\n         * `frag` starting from the next call to mbedtls_mps_reader_get().\n         */\n\n        unsigned char *acc;\n\n        MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                          \"Serve the request from the accumulator\");\n        if (frag_offset - end < desired) {\n            mbedtls_mps_size_t acc_available;\n            acc_available = rd->acc_available;\n            if (acc_available - end != desired) {\n                /* It might be possible to serve some of these situations by\n                 * making additional space in the accumulator, removing those\n                 * parts that have already been committed.\n                 * On the other hand, this brings additional complexity and\n                 * enlarges the code size, while there doesn't seem to be a use\n                 * case where we don't attempt exactly the same `get` calls when\n                 * resuming on a reader than what we tried before pausing it.\n                 * If we believe we adhere to this restricted usage throughout\n                 * the library, this check is a good opportunity to\n                 * validate this. */\n                MBEDTLS_MPS_TRACE_RETURN(\n                    MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS);\n            }\n        }\n\n        acc = rd->acc;\n        acc += end;\n\n        *buffer = acc;\n        if (buflen != NULL) {\n            *buflen = desired;\n        }\n\n        end += desired;\n        rd->end = end;\n        rd->pending = 0;\n\n        MBEDTLS_MPS_TRACE_RETURN(0);\n    }\n\n    /* Attempt to serve the request from the current fragment */\n    MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                      \"Serve the request from the current fragment.\");\n\n    frag_len = rd->frag_len;\n    frag_fetched = end - frag_offset; /* The amount of data from the current\n                                       * fragment that has already been passed\n                                       * to the user. */\n    frag_remaining = frag_len - frag_fetched; /* Remaining data in fragment */\n\n    /* Check if we can serve the read request from the fragment. */\n    if (frag_remaining < desired) {\n        MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                          \"There's not enough data in the current fragment \"\n                          \"to serve the request.\");\n        /* There's not enough data in the current fragment,\n         * so either just RETURN what we have or fail. */\n        if (buflen == NULL) {\n            if (frag_remaining > 0) {\n                rd->pending = desired - frag_remaining;\n                MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                                  \"Remember to collect %u bytes before re-opening\",\n                                  (unsigned) rd->pending);\n            }\n            MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_READER_OUT_OF_DATA);\n        }\n\n        desired = frag_remaining;\n    }\n\n    /* There's enough data in the current fragment to serve the\n     * (potentially modified) read request. */\n\n    frag = rd->frag;\n    frag += frag_fetched;\n\n    *buffer = frag;\n    if (buflen != NULL) {\n        *buflen = desired;\n    }\n\n    end += desired;\n    rd->end = end;\n    rd->pending = 0;\n    MBEDTLS_MPS_TRACE_RETURN(0);\n}\n\nint mbedtls_mps_reader_commit(mbedtls_mps_reader *rd)\n{\n    mbedtls_mps_size_t end;\n    MBEDTLS_MPS_TRACE_INIT(\"mbedtls_mps_reader_commit\");\n    MBEDTLS_MPS_STATE_VALIDATE_RAW(mps_reader_is_consuming(\n                                       rd),\n                                   \"mbedtls_mps_reader_commit() requires reader to be in consuming mode\");\n\n    end = rd->end;\n    rd->commit = end;\n\n    MBEDTLS_MPS_TRACE_RETURN(0);\n}\n\nint mbedtls_mps_reader_reclaim(mbedtls_mps_reader *rd,\n                               int *paused)\n{\n    unsigned char *frag, *acc;\n    mbedtls_mps_size_t pending, commit;\n    mbedtls_mps_size_t acc_len, frag_offset, frag_len;\n    MBEDTLS_MPS_TRACE_INIT(\"mbedtls_mps_reader_reclaim\");\n\n    if (paused != NULL) {\n        *paused = 0;\n    }\n\n    MBEDTLS_MPS_STATE_VALIDATE_RAW(mps_reader_is_consuming(\n                                       rd),\n                                   \"mbedtls_mps_reader_reclaim() requires reader to be in consuming mode\");\n\n    frag     = rd->frag;\n    acc      = rd->acc;\n    pending  = rd->pending;\n    commit   = rd->commit;\n    frag_len = rd->frag_len;\n\n    frag_offset = mps_reader_get_fragment_offset(rd);\n\n    if (pending == 0) {\n        MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                          \"No unsatisfied read-request has been logged.\");\n\n        /* Check if there's data left to be consumed. */\n        if (commit < frag_offset || commit - frag_offset < frag_len) {\n            MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                              \"There is data left to be consumed.\");\n            rd->end = commit;\n            MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_READER_DATA_LEFT);\n        }\n\n        rd->acc_available = 0;\n        rd->acc_share.acc_remaining = 0;\n\n        MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                          \"Fragment has been fully processed and committed.\");\n    } else {\n        int overflow;\n\n        mbedtls_mps_size_t acc_backup_offset;\n        mbedtls_mps_size_t acc_backup_len;\n        mbedtls_mps_size_t frag_backup_offset;\n        mbedtls_mps_size_t frag_backup_len;\n\n        mbedtls_mps_size_t backup_len;\n        mbedtls_mps_size_t acc_len_needed;\n\n        MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                          \"There has been an unsatisfied read with %u bytes overhead.\",\n                          (unsigned) pending);\n\n        if (acc == NULL) {\n            MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                              \"No accumulator present\");\n            MBEDTLS_MPS_TRACE_RETURN(\n                MBEDTLS_ERR_MPS_READER_NEED_ACCUMULATOR);\n        }\n        acc_len = rd->acc_len;\n\n        /* Check if the upper layer has already fetched\n         * and committed the contents of the accumulator. */\n        if (commit < frag_offset) {\n            /* No, accumulator is still being processed. */\n            frag_backup_offset = 0;\n            frag_backup_len = frag_len;\n            acc_backup_offset = commit;\n            acc_backup_len = frag_offset - commit;\n        } else {\n            /* Yes, the accumulator is already processed. */\n            frag_backup_offset = commit - frag_offset;\n            frag_backup_len = frag_len - frag_backup_offset;\n            acc_backup_offset = 0;\n            acc_backup_len = 0;\n        }\n\n        backup_len = acc_backup_len + frag_backup_len;\n        acc_len_needed = backup_len + pending;\n\n        overflow  = 0;\n        overflow |= (backup_len     < acc_backup_len);\n        overflow |= (acc_len_needed < backup_len);\n\n        if (overflow || acc_len < acc_len_needed) {\n            /* Except for the different return code, we behave as if\n             * there hadn't been a call to mbedtls_mps_reader_get()\n             * since the last commit. */\n            rd->end = commit;\n            rd->pending = 0;\n            MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_ERROR,\n                              \"The accumulator is too small to handle the backup.\");\n            MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_ERROR,\n                              \"* Size: %u\", (unsigned) acc_len);\n            MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_ERROR,\n                              \"* Needed: %u (%u + %u)\",\n                              (unsigned) acc_len_needed,\n                              (unsigned) backup_len, (unsigned) pending);\n            MBEDTLS_MPS_TRACE_RETURN(\n                MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL);\n        }\n\n        MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                          \"Fragment backup: %u\", (unsigned) frag_backup_len);\n        MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                          \"Accumulator backup: %u\", (unsigned) acc_backup_len);\n\n        /* Move uncommitted parts from the accumulator to the front\n         * of the accumulator. */\n        memmove(acc, acc + acc_backup_offset, acc_backup_len);\n\n        /* Copy uncommitted parts of the current fragment to the\n         * accumulator. */\n        memcpy(acc + acc_backup_len,\n               frag + frag_backup_offset, frag_backup_len);\n\n        rd->acc_available = backup_len;\n        rd->acc_share.acc_remaining = pending;\n\n        if (paused != NULL) {\n            *paused = 1;\n        }\n    }\n\n    rd->frag     = NULL;\n    rd->frag_len = 0;\n\n    rd->commit  = 0;\n    rd->end     = 0;\n    rd->pending = 0;\n\n    MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n                      \"Final state: aa %u, al %u, ar %u\",\n                      (unsigned) rd->acc_available, (unsigned) rd->acc_len,\n                      (unsigned) rd->acc_share.acc_remaining);\n    MBEDTLS_MPS_TRACE_RETURN(0);\n}\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/mps_reader.h",
    "content": "/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/**\n * \\file mps_reader.h\n *\n * \\brief This file defines reader objects, which together with their\n *        sibling writer objects form the basis for the communication\n *        between the various layers of the Mbed TLS messaging stack,\n *        as well as the communication between the messaging stack and\n *        the (D)TLS handshake protocol implementation.\n *\n * Readers provide a means of transferring incoming data from\n * a 'producer' providing it in chunks of arbitrary size, to\n * a 'consumer' which fetches and processes it in chunks of\n * again arbitrary, and potentially different, size.\n *\n * Readers can thus be seen as datagram-to-stream converters,\n * and they abstract away the following two tasks from the user:\n * 1. The pointer arithmetic of stepping through a producer-\n *    provided chunk in smaller chunks.\n * 2. The merging of incoming data chunks in case the\n *    consumer requests data in larger chunks than what the\n *    producer provides.\n *\n * The basic abstract flow of operation is the following:\n * - Initially, the reader is in 'producing mode'.\n * - The producer hands an incoming data buffer to the reader,\n *   moving it from 'producing' to 'consuming' mode.\n * - The consumer subsequently fetches and processes the buffer\n *   content. Once that's done -- or partially done and a consumer's\n *   request can't be fulfilled -- the producer revokes the reader's\n *   access to the incoming data buffer, putting the reader back to\n *   producing mode.\n * - The producer subsequently gathers more incoming data and hands\n *   it to the reader until it switches back to consuming mode\n *   if enough data is available for the last consumer request to\n *   be satisfiable.\n * - Repeat the above.\n *\n * The abstract states of the reader from the producer's and\n * consumer's perspective are as follows:\n *\n * - From the perspective of the consumer, the state of the\n *   reader consists of the following:\n *   - A byte stream representing (concatenation of) the data\n *     received through calls to mbedtls_mps_reader_get(),\n *   - A marker within that byte stream indicating which data\n *     can be considered processed, and hence need not be retained,\n *     when the reader is passed back to the producer via\n *     mbedtls_mps_reader_reclaim().\n *     The marker is set via mbedtls_mps_reader_commit()\n *     which places it at the end of the current byte stream.\n *   The consumer need not be aware of the distinction between consumer\n *   and producer mode, because it only interfaces with the reader\n *   when the latter is in consuming mode.\n *\n * - From the perspective of the producer, the reader's state is one of:\n *   - Attached: The reader is in consuming mode.\n *   - Unset: No incoming data buffer is currently managed by the reader,\n *            and all previously handed incoming data buffers have been\n *            fully processed. More data needs to be fed into the reader\n *            via mbedtls_mps_reader_feed().\n *\n *   - Accumulating: No incoming data buffer is currently managed by the\n *                   reader, but some data from the previous incoming data\n *                   buffer hasn't been processed yet and is internally\n *                   held back.\n *   The Attached state belongs to consuming mode, while the Unset and\n *   Accumulating states belong to producing mode.\n *\n * Transitioning from the Unset or Accumulating state to Attached is\n * done via successful calls to mbedtls_mps_reader_feed(), while\n * transitioning from Attached to either Unset or Accumulating (depending\n * on what has been processed) is done via mbedtls_mps_reader_reclaim().\n *\n * The following diagram depicts the producer-state progression:\n *\n *        +------------------+             reclaim\n *        |      Unset       +<-------------------------------------+       get\n *        +--------|---------+                                      |   +------+\n *                 |                                                |   |      |\n *                 |                                                |   |      |\n *                 |                feed                  +---------+---+--+   |\n *                 +-------------------------------------->                <---+\n *                                                        |    Attached    |\n *                 +-------------------------------------->                <---+\n *                 |     feed, enough data available      +---------+---+--+   |\n *                 |     to serve previous consumer request         |   |      |\n *                 |                                                |   |      |\n *        +--------+---------+                                      |   +------+\n *   +---->   Accumulating   |<-------------------------------------+    commit\n *   |    +---+--------------+      reclaim, previous read request\n *   |        |                        couldn't be fulfilled\n *   |        |\n *   +--------+\n *     feed, need more data to serve\n *     previous consumer request\n *                                         |\n *                                         |\n *               producing mode            |           consuming mode\n *                                         |\n *\n */\n\n#ifndef MBEDTLS_READER_H\n#define MBEDTLS_READER_H\n\n#include <stdio.h>\n\n#include \"mps_common.h\"\n#include \"mps_error.h\"\n\nstruct mbedtls_mps_reader;\ntypedef struct mbedtls_mps_reader mbedtls_mps_reader;\n\n/*\n * Structure definitions\n */\n\nstruct mbedtls_mps_reader {\n    unsigned char *frag;  /*!< The fragment of incoming data managed by\n                           *   the reader; it is provided to the reader\n                           *   through mbedtls_mps_reader_feed(). The reader\n                           *   does not own the fragment and does not\n                           *   perform any allocation operations on it,\n                           *   but does have read and write access to it.\n                           *\n                           *   The reader is in consuming mode if\n                           *   and only if \\c frag is not \\c NULL.          */\n    mbedtls_mps_stored_size_t frag_len;\n    /*!< The length of the current fragment.\n     *   Must be 0 if \\c frag == \\c NULL.             */\n    mbedtls_mps_stored_size_t commit;\n    /*!< The offset of the last commit, relative\n     *   to the first byte in the fragment, if\n     *   no accumulator is present. If an accumulator\n     *   is present, it is viewed as a prefix to the\n     *   current fragment, and this variable contains\n     *   an offset from the beginning of the accumulator.\n     *\n     *   This is only used when the reader is in\n     *   consuming mode, i.e. \\c frag != \\c NULL;\n     *   otherwise, its value is \\c 0.                */\n    mbedtls_mps_stored_size_t end;\n    /*!< The offset of the end of the last chunk\n     *   passed to the user through a call to\n     *   mbedtls_mps_reader_get(), relative to the first\n     *   byte in the fragment, if no accumulator is\n     *   present. If an accumulator is present, it is\n     *   viewed as a prefix to the current fragment, and\n     *   this variable contains an offset from the\n     *   beginning of the accumulator.\n     *\n     *   This is only used when the reader is in\n     *   consuming mode, i.e. \\c frag != \\c NULL;\n     *   otherwise, its value is \\c 0.                */\n    mbedtls_mps_stored_size_t pending;\n    /*!< The amount of incoming data missing on the\n     *   last call to mbedtls_mps_reader_get().\n     *   In particular, it is \\c 0 if the last call\n     *   was successful.\n     *   If a reader is reclaimed after an\n     *   unsuccessful call to mbedtls_mps_reader_get(),\n     *   this variable is used to have the reader\n     *   remember how much data should be accumulated\n     *   so that the call to mbedtls_mps_reader_get()\n     *   succeeds next time.\n     *   This is only used when the reader is in\n     *   consuming mode, i.e. \\c frag != \\c NULL;\n     *   otherwise, its value is \\c 0.                */\n\n    /* The accumulator is only needed if we need to be able to pause\n     * the reader. A few bytes could be saved by moving this to a\n     * separate struct and using a pointer here. */\n\n    unsigned char *acc;   /*!< The accumulator is used to gather incoming\n                           *   data if a read-request via mbedtls_mps_reader_get()\n                           *   cannot be served from the current fragment.   */\n    mbedtls_mps_stored_size_t acc_len;\n    /*!< The total size of the accumulator.           */\n    mbedtls_mps_stored_size_t acc_available;\n    /*!< The number of bytes currently gathered in\n     *   the accumulator. This is both used in\n     *   producing and in consuming mode:\n     *   While producing, it is increased until\n     *   it reaches the value of \\c acc_remaining below.\n     *   While consuming, it is used to judge if a\n     *   get request can be served from the\n     *   accumulator or not.\n     *   Must not be larger than \\c acc_len.           */\n    union {\n        mbedtls_mps_stored_size_t acc_remaining;\n        /*!< This indicates the amount of data still\n         *   to be gathered in the accumulator. It is\n         *   only used in producing mode.\n         *   Must be at most acc_len - acc_available.  */\n        mbedtls_mps_stored_size_t frag_offset;\n        /*!< If an accumulator is present and in use, this\n         *   field indicates the offset of the current\n         *   fragment from the beginning of the\n         *   accumulator. If no accumulator is present\n         *   or the accumulator is not in use, this is \\c 0.\n         *   It is only used in consuming mode.\n         *   Must not be larger than \\c acc_available. */\n    } acc_share;\n};\n\n/*\n * API organization:\n * A reader object is usually prepared and maintained\n * by some lower layer and passed for usage to an upper\n * layer, and the API naturally splits according to which\n * layer is supposed to use the respective functions.\n */\n\n/*\n * Maintenance API (Lower layer)\n */\n\n/**\n * \\brief           Initialize a reader object\n *\n * \\param reader    The reader to be initialized.\n * \\param acc       The buffer to be used as a temporary accumulator\n *                  in case get requests through mbedtls_mps_reader_get()\n *                  exceed the buffer provided by mbedtls_mps_reader_feed().\n *                  This buffer is owned by the caller and exclusive use\n *                  for reading and writing is given to the reader for the\n *                  duration of the reader's lifetime. It is thus the caller's\n *                  responsibility to maintain (and not touch) the buffer for\n *                  the lifetime of the reader, and to properly zeroize and\n *                  free the memory after the reader has been destroyed.\n * \\param acc_len   The size in Bytes of \\p acc.\n *\n * \\return          \\c 0 on success.\n * \\return          A negative \\c MBEDTLS_ERR_READER_XXX error code on failure.\n */\nint mbedtls_mps_reader_init(mbedtls_mps_reader *reader,\n                            unsigned char *acc,\n                            mbedtls_mps_size_t acc_len);\n\n/**\n * \\brief           Free a reader object\n *\n * \\param reader    The reader to be freed.\n *\n * \\return          \\c 0 on success.\n * \\return          A negative \\c MBEDTLS_ERR_READER_XXX error code on failure.\n */\nint mbedtls_mps_reader_free(mbedtls_mps_reader *reader);\n\n/**\n * \\brief           Pass chunk of data for the reader to manage.\n *\n * \\param reader    The reader context to use. The reader must be\n *                  in producing mode.\n * \\param buf       The buffer to be managed by the reader.\n * \\param buflen    The size in Bytes of \\p buffer.\n *\n * \\return          \\c 0 on success. In this case, the reader will be\n *                  moved to consuming mode and obtains read access\n *                  of \\p buf until mbedtls_mps_reader_reclaim()\n *                  is called. It is the responsibility of the caller\n *                  to ensure that the \\p buf persists and is not changed\n *                  between successful calls to mbedtls_mps_reader_feed()\n *                  and mbedtls_mps_reader_reclaim().\n * \\return          \\c MBEDTLS_ERR_MPS_READER_NEED_MORE if more input data is\n *                  required to fulfill a previous request to mbedtls_mps_reader_get().\n *                  In this case, the reader remains in producing mode and\n *                  takes no ownership of the provided buffer (an internal copy\n *                  is made instead).\n * \\return          Another negative \\c MBEDTLS_ERR_READER_XXX error code on\n *                  different kinds of failures.\n */\nint mbedtls_mps_reader_feed(mbedtls_mps_reader *reader,\n                            unsigned char *buf,\n                            mbedtls_mps_size_t buflen);\n\n/**\n * \\brief           Reclaim reader's access to the current input buffer.\n *\n * \\param reader    The reader context to use. The reader must be\n *                  in consuming mode.\n * \\param paused    If not \\c NULL, the integer at address \\p paused will be\n *                  modified to indicate whether the reader has been paused\n *                  (value \\c 1) or not (value \\c 0). Pausing happens if there\n *                  is uncommitted data and a previous request to\n *                  mbedtls_mps_reader_get() has exceeded the bounds of the\n *                  input buffer.\n *\n * \\return          \\c 0 on success.\n * \\return          A negative \\c MBEDTLS_ERR_READER_XXX error code on failure.\n */\nint mbedtls_mps_reader_reclaim(mbedtls_mps_reader *reader,\n                               int *paused);\n\n/*\n * Usage API (Upper layer)\n */\n\n/**\n * \\brief           Request data from the reader.\n *\n * \\param reader    The reader context to use. The reader must\n *                  be in consuming mode.\n * \\param desired   The desired amount of data to be read, in Bytes.\n * \\param buffer    The address to store the buffer pointer in.\n *                  This must not be \\c NULL.\n * \\param buflen    The address to store the actual buffer\n *                  length in, or \\c NULL.\n *\n * \\return          \\c 0 on success. In this case, \\c *buf holds the\n *                  address of a buffer of size \\c *buflen\n *                  (if \\c buflen != \\c NULL) or \\c desired\n *                  (if \\c buflen == \\c NULL). The user has read access\n *                  to the buffer and guarantee of stability of the data\n *                  until the next call to mbedtls_mps_reader_reclaim().\n * \\return          #MBEDTLS_ERR_MPS_READER_OUT_OF_DATA if there is not enough\n *                  data available to serve the get request. In this case, the\n *                  reader remains intact and in consuming mode, and the consumer\n *                  should retry the call after a successful cycle of\n *                  mbedtls_mps_reader_reclaim() and mbedtls_mps_reader_feed().\n *                  If, after such a cycle, the consumer requests a different\n *                  amount of data, the result is implementation-defined;\n *                  progress is guaranteed only if the same amount of data\n *                  is requested after a mbedtls_mps_reader_reclaim() and\n *                  mbedtls_mps_reader_feed() cycle.\n * \\return          Another negative \\c MBEDTLS_ERR_READER_XXX error\n *                  code for different kinds of failure.\n *\n * \\note            Passing \\c NULL as \\p buflen is a convenient way to\n *                  indicate that fragmentation is not tolerated.\n *                  It's functionally equivalent to passing a valid\n *                  address as buflen and checking \\c *buflen == \\c desired\n *                  afterwards.\n */\nint mbedtls_mps_reader_get(mbedtls_mps_reader *reader,\n                           mbedtls_mps_size_t desired,\n                           unsigned char **buffer,\n                           mbedtls_mps_size_t *buflen);\n\n/**\n * \\brief         Mark data obtained from mbedtls_mps_reader_get() as processed.\n *\n *                This call indicates that all data received from prior calls to\n *                mbedtls_mps_reader_get() has been or will have been\n *                processed when mbedtls_mps_reader_reclaim() is called,\n *                and thus need not be backed up.\n *\n *                This function has no user observable effect until\n *                mbedtls_mps_reader_reclaim() is called. In particular,\n *                buffers received from mbedtls_mps_reader_get() remain\n *                valid until mbedtls_mps_reader_reclaim() is called.\n *\n * \\param reader  The reader context to use.\n *\n * \\return        \\c 0 on success.\n * \\return        A negative \\c MBEDTLS_ERR_READER_XXX error code on failure.\n *\n */\nint mbedtls_mps_reader_commit(mbedtls_mps_reader *reader);\n\n#endif /* MBEDTLS_READER_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/mps_trace.c",
    "content": "/*\n *  Message Processing Stack, Trace module\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n\n#include \"mps_common.h\"\n\n#if defined(MBEDTLS_MPS_ENABLE_TRACE)\n\n#include \"mps_trace.h\"\n#include <stdarg.h>\n\nstatic int trace_depth = 0;\n\n#define color_default  \"\\x1B[0m\"\n#define color_red      \"\\x1B[1;31m\"\n#define color_green    \"\\x1B[1;32m\"\n#define color_yellow   \"\\x1B[1;33m\"\n#define color_blue     \"\\x1B[1;34m\"\n#define color_magenta  \"\\x1B[1;35m\"\n#define color_cyan     \"\\x1B[1;36m\"\n#define color_white    \"\\x1B[1;37m\"\n\nstatic char const *colors[] =\n{\n    color_default,\n    color_green,\n    color_yellow,\n    color_magenta,\n    color_cyan,\n    color_blue,\n    color_white\n};\n\n#define MPS_TRACE_BUF_SIZE 100\n\nvoid mbedtls_mps_trace_print_msg(int id, int line, const char *format, ...)\n{\n    int ret;\n    char str[MPS_TRACE_BUF_SIZE];\n    va_list argp;\n    va_start(argp, format);\n    ret = mbedtls_vsnprintf(str, MPS_TRACE_BUF_SIZE, format, argp);\n    va_end(argp);\n\n    if (ret >= 0 && ret < MPS_TRACE_BUF_SIZE) {\n        str[ret] = '\\0';\n        mbedtls_printf(\"[%d|L%d]: %s\\n\", id, line, str);\n    }\n}\n\nint mbedtls_mps_trace_get_depth()\n{\n    return trace_depth;\n}\nvoid mbedtls_mps_trace_dec_depth()\n{\n    trace_depth--;\n}\nvoid mbedtls_mps_trace_inc_depth()\n{\n    trace_depth++;\n}\n\nvoid mbedtls_mps_trace_color(int id)\n{\n    if (id > (int) (sizeof(colors) / sizeof(*colors))) {\n        return;\n    }\n    printf(\"%s\", colors[id]);\n}\n\nvoid mbedtls_mps_trace_indent(int level, mbedtls_mps_trace_type ty)\n{\n    if (level > 0) {\n        while (--level) {\n            printf(\"|  \");\n        }\n\n        printf(\"|  \");\n    }\n\n    switch (ty) {\n        case MBEDTLS_MPS_TRACE_TYPE_COMMENT:\n            mbedtls_printf(\"@ \");\n            break;\n\n        case MBEDTLS_MPS_TRACE_TYPE_CALL:\n            mbedtls_printf(\"+--> \");\n            break;\n\n        case MBEDTLS_MPS_TRACE_TYPE_ERROR:\n            mbedtls_printf(\"E \");\n            break;\n\n        case MBEDTLS_MPS_TRACE_TYPE_RETURN:\n            mbedtls_printf(\"< \");\n            break;\n\n        default:\n            break;\n    }\n}\n\n#endif /* MBEDTLS_MPS_ENABLE_TRACE */\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/mps_trace.h",
    "content": "/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/**\n * \\file mps_trace.h\n *\n * \\brief Tracing module for MPS\n */\n\n#ifndef MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H\n#define MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H\n\n#include \"common.h\"\n#include \"mps_common.h\"\n#include \"mps_trace.h\"\n\n#include \"mbedtls/platform.h\"\n\n#if defined(MBEDTLS_MPS_ENABLE_TRACE)\n\n/*\n * Adapt this to enable/disable tracing output\n * from the various layers of the MPS.\n */\n\n#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_1\n#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_2\n#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_3\n#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_4\n#define MBEDTLS_MPS_TRACE_ENABLE_READER\n#define MBEDTLS_MPS_TRACE_ENABLE_WRITER\n\n/*\n * To use the existing trace module, only change\n * MBEDTLS_MPS_TRACE_ENABLE_XXX above, but don't modify the\n * rest of this file.\n */\n\ntypedef enum {\n    MBEDTLS_MPS_TRACE_TYPE_COMMENT,\n    MBEDTLS_MPS_TRACE_TYPE_CALL,\n    MBEDTLS_MPS_TRACE_TYPE_ERROR,\n    MBEDTLS_MPS_TRACE_TYPE_RETURN\n} mbedtls_mps_trace_type;\n\n#define MBEDTLS_MPS_TRACE_BIT_LAYER_1 1\n#define MBEDTLS_MPS_TRACE_BIT_LAYER_2 2\n#define MBEDTLS_MPS_TRACE_BIT_LAYER_3 3\n#define MBEDTLS_MPS_TRACE_BIT_LAYER_4 4\n#define MBEDTLS_MPS_TRACE_BIT_WRITER  5\n#define MBEDTLS_MPS_TRACE_BIT_READER  6\n\n#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_1)\n#define MBEDTLS_MPS_TRACE_MASK_LAYER_1 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_1)\n#else\n#define MBEDTLS_MPS_TRACE_MASK_LAYER_1 0\n#endif\n\n#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_2)\n#define MBEDTLS_MPS_TRACE_MASK_LAYER_2 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_2)\n#else\n#define MBEDTLS_MPS_TRACE_MASK_LAYER_2 0\n#endif\n\n#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_3)\n#define MBEDTLS_MPS_TRACE_MASK_LAYER_3 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_3)\n#else\n#define MBEDTLS_MPS_TRACE_MASK_LAYER_3 0\n#endif\n\n#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_4)\n#define MBEDTLS_MPS_TRACE_MASK_LAYER_4 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_4)\n#else\n#define MBEDTLS_MPS_TRACE_MASK_LAYER_4 0\n#endif\n\n#if defined(MBEDTLS_MPS_TRACE_ENABLE_READER)\n#define MBEDTLS_MPS_TRACE_MASK_READER (1u << MBEDTLS_MPS_TRACE_BIT_READER)\n#else\n#define MBEDTLS_MPS_TRACE_MASK_READER 0\n#endif\n\n#if defined(MBEDTLS_MPS_TRACE_ENABLE_WRITER)\n#define MBEDTLS_MPS_TRACE_MASK_WRITER (1u << MBEDTLS_MPS_TRACE_BIT_WRITER)\n#else\n#define MBEDTLS_MPS_TRACE_MASK_WRITER 0\n#endif\n\n#define MBEDTLS_MPS_TRACE_MASK (MBEDTLS_MPS_TRACE_MASK_LAYER_1 |       \\\n                                MBEDTLS_MPS_TRACE_MASK_LAYER_2 |       \\\n                                MBEDTLS_MPS_TRACE_MASK_LAYER_3 |       \\\n                                MBEDTLS_MPS_TRACE_MASK_LAYER_4 |       \\\n                                MBEDTLS_MPS_TRACE_MASK_READER  |       \\\n                                MBEDTLS_MPS_TRACE_MASK_WRITER)\n\n/* We have to avoid globals because E-ACSL chokes on them...\n * Wrap everything in stub functions. */\nint  mbedtls_mps_trace_get_depth(void);\nvoid mbedtls_mps_trace_inc_depth(void);\nvoid mbedtls_mps_trace_dec_depth(void);\n\nvoid mbedtls_mps_trace_color(int id);\nvoid mbedtls_mps_trace_indent(int level, mbedtls_mps_trace_type ty);\n\nvoid mbedtls_mps_trace_print_msg(int id, int line, const char *format, ...);\n\n#define MBEDTLS_MPS_TRACE(type, ...)                                              \\\n    do {                                                                            \\\n        if (!(MBEDTLS_MPS_TRACE_MASK & (1u << mbedtls_mps_trace_id)))         \\\n        break;                                                                  \\\n        mbedtls_mps_trace_indent(mbedtls_mps_trace_get_depth(), type);            \\\n        mbedtls_mps_trace_color(mbedtls_mps_trace_id);                            \\\n        mbedtls_mps_trace_print_msg(mbedtls_mps_trace_id, __LINE__, __VA_ARGS__); \\\n        mbedtls_mps_trace_color(0);                                               \\\n    } while (0)\n\n#define MBEDTLS_MPS_TRACE_INIT(...)                                         \\\n    do {                                                                      \\\n        if (!(MBEDTLS_MPS_TRACE_MASK & (1u << mbedtls_mps_trace_id)))   \\\n        break;                                                            \\\n        MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_CALL, __VA_ARGS__);        \\\n        mbedtls_mps_trace_inc_depth();                                        \\\n    } while (0)\n\n#define MBEDTLS_MPS_TRACE_END(val)                                        \\\n    do {                                                                    \\\n        if (!(MBEDTLS_MPS_TRACE_MASK & (1u << mbedtls_mps_trace_id))) \\\n        break;                                                          \\\n        MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_RETURN, \"%d (-%#04x)\",    \\\n                          (int) (val), -((unsigned) (val)));                           \\\n        mbedtls_mps_trace_dec_depth();                                      \\\n    } while (0)\n\n#define MBEDTLS_MPS_TRACE_RETURN(val)         \\\n    do {                                        \\\n        /* Breaks tail recursion. */            \\\n        int ret__ = val;                        \\\n        MBEDTLS_MPS_TRACE_END(ret__);         \\\n        return ret__;                        \\\n    } while (0)\n\n#else /* MBEDTLS_MPS_TRACE */\n\n#define MBEDTLS_MPS_TRACE(type, ...) do { } while (0)\n#define MBEDTLS_MPS_TRACE_INIT(...)  do { } while (0)\n#define MBEDTLS_MPS_TRACE_END          do { } while (0)\n\n#define MBEDTLS_MPS_TRACE_RETURN(val) return val;\n\n#endif /* MBEDTLS_MPS_TRACE */\n\n#endif /* MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/net_sockets.c",
    "content": "/*\n *  TCP/IP or UDP/IP networking functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must\n * be set before mbedtls_config.h, which pulls in glibc's features.h indirectly.\n * Harmless on other platforms. */\n#ifndef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 200112L\n#endif\n#ifndef _XOPEN_SOURCE\n#define _XOPEN_SOURCE 600 /* sockaddr_storage */\n#endif\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_NET_C)\n\n#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \\\n    !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \\\n    !defined(__HAIKU__) && !defined(__midipix__)\n#error \"This module only works on Unix and Windows, see MBEDTLS_NET_C in mbedtls_config.h\"\n#endif\n\n#include \"mbedtls/platform.h\"\n\n#include \"mbedtls/net_sockets.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \\\n    !defined(EFI32)\n\n#define IS_EINTR(ret) ((ret) == WSAEINTR)\n\n#include <ws2tcpip.h>\n\n#include <winsock2.h>\n#include <windows.h>\n#if (_WIN32_WINNT < 0x0501)\n#include <wspiapi.h>\n#endif\n\n#if defined(_MSC_VER)\n#if defined(_WIN32_WCE)\n#pragma comment( lib, \"ws2.lib\" )\n#else\n#pragma comment( lib, \"ws2_32.lib\" )\n#endif\n#endif /* _MSC_VER */\n\n#define read(fd, buf, len)        recv(fd, (char *) (buf), (int) (len), 0)\n#define write(fd, buf, len)       send(fd, (char *) (buf), (int) (len), 0)\n#define close(fd)               closesocket(fd)\n\nstatic int wsa_init_done = 0;\n\n#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */\n\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <arpa/inet.h>\n#include <sys/time.h>\n#include <unistd.h>\n#include <signal.h>\n#include <fcntl.h>\n#include <netdb.h>\n#include <errno.h>\n\n#define IS_EINTR(ret) ((ret) == EINTR)\n#define SOCKET int\n\n#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */\n\n/* Some MS functions want int and MSVC warns if we pass size_t,\n * but the standard functions use socklen_t, so cast only for MSVC */\n#if defined(_MSC_VER)\n#define MSVC_INT_CAST   (int)\n#else\n#define MSVC_INT_CAST\n#endif\n\n#include <stdio.h>\n\n#if defined(MBEDTLS_HAVE_TIME)\n#include <time.h>\n#endif\n\n#include <stdint.h>\n\n/*\n * Prepare for using the sockets interface\n */\nstatic int net_prepare(void)\n{\n#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \\\n    !defined(EFI32)\n    WSADATA wsaData;\n\n    if (wsa_init_done == 0) {\n        if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {\n            return MBEDTLS_ERR_NET_SOCKET_FAILED;\n        }\n\n        wsa_init_done = 1;\n    }\n#else\n#if !defined(EFIX64) && !defined(EFI32)\n    signal(SIGPIPE, SIG_IGN);\n#endif\n#endif\n    return 0;\n}\n\n/*\n * Return 0 if the file descriptor is valid, an error otherwise.\n * If for_select != 0, check whether the file descriptor is within the range\n * allowed for fd_set used for the FD_xxx macros and the select() function.\n */\nstatic int check_fd(int fd, int for_select)\n{\n    if (fd < 0) {\n        return MBEDTLS_ERR_NET_INVALID_CONTEXT;\n    }\n\n#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \\\n    !defined(EFI32)\n    (void) for_select;\n#else\n    /* A limitation of select() is that it only works with file descriptors\n     * that are strictly less than FD_SETSIZE. This is a limitation of the\n     * fd_set type. Error out early, because attempting to call FD_SET on a\n     * large file descriptor is a buffer overflow on typical platforms. */\n    if (for_select && fd >= FD_SETSIZE) {\n        return MBEDTLS_ERR_NET_POLL_FAILED;\n    }\n#endif\n\n    return 0;\n}\n\n/*\n * Initialize a context\n */\nvoid mbedtls_net_init(mbedtls_net_context *ctx)\n{\n    ctx->fd = -1;\n}\n\n/*\n * Initiate a TCP connection with host:port and the given protocol\n */\nint mbedtls_net_connect(mbedtls_net_context *ctx, const char *host,\n                        const char *port, int proto)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    struct addrinfo hints, *addr_list, *cur;\n\n    if ((ret = net_prepare()) != 0) {\n        return ret;\n    }\n\n    /* Do name resolution with both IPv6 and IPv4 */\n    memset(&hints, 0, sizeof(hints));\n    hints.ai_family = AF_UNSPEC;\n    hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;\n    hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;\n\n    if (getaddrinfo(host, port, &hints, &addr_list) != 0) {\n        return MBEDTLS_ERR_NET_UNKNOWN_HOST;\n    }\n\n    /* Try the sockaddrs until a connection succeeds */\n    ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;\n    for (cur = addr_list; cur != NULL; cur = cur->ai_next) {\n        ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype,\n                               cur->ai_protocol);\n        if (ctx->fd < 0) {\n            ret = MBEDTLS_ERR_NET_SOCKET_FAILED;\n            continue;\n        }\n\n        if (connect(ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen) == 0) {\n            ret = 0;\n            break;\n        }\n\n        mbedtls_net_close(ctx);\n        ret = MBEDTLS_ERR_NET_CONNECT_FAILED;\n    }\n\n    freeaddrinfo(addr_list);\n\n    return ret;\n}\n\n/*\n * Create a listening socket on bind_ip:port\n */\nint mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto)\n{\n    int n, ret;\n    struct addrinfo hints, *addr_list, *cur;\n\n    if ((ret = net_prepare()) != 0) {\n        return ret;\n    }\n\n    /* Bind to IPv6 and/or IPv4, but only in the desired protocol */\n    memset(&hints, 0, sizeof(hints));\n    hints.ai_family = AF_UNSPEC;\n    hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;\n    hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;\n    if (bind_ip == NULL) {\n        hints.ai_flags = AI_PASSIVE;\n    }\n\n    if (getaddrinfo(bind_ip, port, &hints, &addr_list) != 0) {\n        return MBEDTLS_ERR_NET_UNKNOWN_HOST;\n    }\n\n    /* Try the sockaddrs until a binding succeeds */\n    ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;\n    for (cur = addr_list; cur != NULL; cur = cur->ai_next) {\n        ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype,\n                               cur->ai_protocol);\n        if (ctx->fd < 0) {\n            ret = MBEDTLS_ERR_NET_SOCKET_FAILED;\n            continue;\n        }\n\n        n = 1;\n        if (setsockopt(ctx->fd, SOL_SOCKET, SO_REUSEADDR,\n                       (const char *) &n, sizeof(n)) != 0) {\n            mbedtls_net_close(ctx);\n            ret = MBEDTLS_ERR_NET_SOCKET_FAILED;\n            continue;\n        }\n\n        if (bind(ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen) != 0) {\n            mbedtls_net_close(ctx);\n            ret = MBEDTLS_ERR_NET_BIND_FAILED;\n            continue;\n        }\n\n        /* Listen only makes sense for TCP */\n        if (proto == MBEDTLS_NET_PROTO_TCP) {\n            if (listen(ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG) != 0) {\n                mbedtls_net_close(ctx);\n                ret = MBEDTLS_ERR_NET_LISTEN_FAILED;\n                continue;\n            }\n        }\n\n        /* Bind was successful */\n        ret = 0;\n        break;\n    }\n\n    freeaddrinfo(addr_list);\n\n    return ret;\n\n}\n\n#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \\\n    !defined(EFI32)\n/*\n * Check if the requested operation would be blocking on a non-blocking socket\n * and thus 'failed' with a negative return value.\n */\nstatic int net_would_block(const mbedtls_net_context *ctx)\n{\n    ((void) ctx);\n    return WSAGetLastError() == WSAEWOULDBLOCK;\n}\n#else\n/*\n * Check if the requested operation would be blocking on a non-blocking socket\n * and thus 'failed' with a negative return value.\n *\n * Note: on a blocking socket this function always returns 0!\n */\nstatic int net_would_block(const mbedtls_net_context *ctx)\n{\n    int err = errno;\n\n    /*\n     * Never return 'WOULD BLOCK' on a blocking socket\n     */\n    if ((fcntl(ctx->fd, F_GETFL) & O_NONBLOCK) != O_NONBLOCK) {\n        errno = err;\n        return 0;\n    }\n\n    switch (errno = err) {\n#if defined EAGAIN\n        case EAGAIN:\n#endif\n#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN\n        case EWOULDBLOCK:\n#endif\n    return 1;\n    }\n    return 0;\n}\n#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */\n\n/*\n * Accept a connection from a remote client\n */\nint mbedtls_net_accept(mbedtls_net_context *bind_ctx,\n                       mbedtls_net_context *client_ctx,\n                       void *client_ip, size_t buf_size, size_t *cip_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    int type;\n\n    struct sockaddr_storage client_addr;\n\n#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) ||  \\\n    defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) || \\\n    defined(socklen_t) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L)\n    socklen_t n = (socklen_t) sizeof(client_addr);\n    socklen_t type_len = (socklen_t) sizeof(type);\n#else\n    int n = (int) sizeof(client_addr);\n    int type_len = (int) sizeof(type);\n#endif\n\n    /* Is this a TCP or UDP socket? */\n    if (getsockopt(bind_ctx->fd, SOL_SOCKET, SO_TYPE,\n                   (void *) &type, &type_len) != 0 ||\n        (type != SOCK_STREAM && type != SOCK_DGRAM)) {\n        return MBEDTLS_ERR_NET_ACCEPT_FAILED;\n    }\n\n    if (type == SOCK_STREAM) {\n        /* TCP: actual accept() */\n        ret = client_ctx->fd = (int) accept(bind_ctx->fd,\n                                            (struct sockaddr *) &client_addr, &n);\n    } else {\n        /* UDP: wait for a message, but keep it in the queue */\n        char buf[1] = { 0 };\n\n        ret = (int) recvfrom(bind_ctx->fd, buf, sizeof(buf), MSG_PEEK,\n                             (struct sockaddr *) &client_addr, &n);\n\n#if defined(_WIN32)\n        if (ret == SOCKET_ERROR &&\n            WSAGetLastError() == WSAEMSGSIZE) {\n            /* We know buf is too small, thanks, just peeking here */\n            ret = 0;\n        }\n#endif\n    }\n\n    if (ret < 0) {\n        if (net_would_block(bind_ctx) != 0) {\n            return MBEDTLS_ERR_SSL_WANT_READ;\n        }\n\n        return MBEDTLS_ERR_NET_ACCEPT_FAILED;\n    }\n\n    /* UDP: hijack the listening socket to communicate with the client,\n     * then bind a new socket to accept new connections */\n    if (type != SOCK_STREAM) {\n        struct sockaddr_storage local_addr;\n        int one = 1;\n\n        if (connect(bind_ctx->fd, (struct sockaddr *) &client_addr, n) != 0) {\n            return MBEDTLS_ERR_NET_ACCEPT_FAILED;\n        }\n\n        client_ctx->fd = bind_ctx->fd;\n        bind_ctx->fd   = -1; /* In case we exit early */\n\n        n = sizeof(struct sockaddr_storage);\n        if (getsockname(client_ctx->fd,\n                        (struct sockaddr *) &local_addr, &n) != 0 ||\n            (bind_ctx->fd = (int) socket(local_addr.ss_family,\n                                         SOCK_DGRAM, IPPROTO_UDP)) < 0 ||\n            setsockopt(bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,\n                       (const char *) &one, sizeof(one)) != 0) {\n            return MBEDTLS_ERR_NET_SOCKET_FAILED;\n        }\n\n        if (bind(bind_ctx->fd, (struct sockaddr *) &local_addr, n) != 0) {\n            return MBEDTLS_ERR_NET_BIND_FAILED;\n        }\n    }\n\n    if (client_ip != NULL) {\n        if (client_addr.ss_family == AF_INET) {\n            struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;\n            *cip_len = sizeof(addr4->sin_addr.s_addr);\n\n            if (buf_size < *cip_len) {\n                return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL;\n            }\n\n            memcpy(client_ip, &addr4->sin_addr.s_addr, *cip_len);\n        } else {\n            struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;\n            *cip_len = sizeof(addr6->sin6_addr.s6_addr);\n\n            if (buf_size < *cip_len) {\n                return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL;\n            }\n\n            memcpy(client_ip, &addr6->sin6_addr.s6_addr, *cip_len);\n        }\n    }\n\n    return 0;\n}\n\n/*\n * Set the socket blocking or non-blocking\n */\nint mbedtls_net_set_block(mbedtls_net_context *ctx)\n{\n#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \\\n    !defined(EFI32)\n    u_long n = 0;\n    return ioctlsocket(ctx->fd, FIONBIO, &n);\n#else\n    return fcntl(ctx->fd, F_SETFL, fcntl(ctx->fd, F_GETFL) & ~O_NONBLOCK);\n#endif\n}\n\nint mbedtls_net_set_nonblock(mbedtls_net_context *ctx)\n{\n#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \\\n    !defined(EFI32)\n    u_long n = 1;\n    return ioctlsocket(ctx->fd, FIONBIO, &n);\n#else\n    return fcntl(ctx->fd, F_SETFL, fcntl(ctx->fd, F_GETFL) | O_NONBLOCK);\n#endif\n}\n\n/*\n * Check if data is available on the socket\n */\n\nint mbedtls_net_poll(mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    struct timeval tv;\n\n    fd_set read_fds;\n    fd_set write_fds;\n\n    int fd = ctx->fd;\n\n    ret = check_fd(fd, 1);\n    if (ret != 0) {\n        return ret;\n    }\n\n#if defined(__has_feature)\n#if __has_feature(memory_sanitizer)\n    /* Ensure that memory sanitizers consider read_fds and write_fds as\n     * initialized even on platforms such as Glibc/x86_64 where FD_ZERO\n     * is implemented in assembly. */\n    memset(&read_fds, 0, sizeof(read_fds));\n    memset(&write_fds, 0, sizeof(write_fds));\n#endif\n#endif\n\n    FD_ZERO(&read_fds);\n    if (rw & MBEDTLS_NET_POLL_READ) {\n        rw &= ~MBEDTLS_NET_POLL_READ;\n        FD_SET((SOCKET) fd, &read_fds);\n    }\n\n    FD_ZERO(&write_fds);\n    if (rw & MBEDTLS_NET_POLL_WRITE) {\n        rw &= ~MBEDTLS_NET_POLL_WRITE;\n        FD_SET((SOCKET) fd, &write_fds);\n    }\n\n    if (rw != 0) {\n        return MBEDTLS_ERR_NET_BAD_INPUT_DATA;\n    }\n\n    tv.tv_sec  = timeout / 1000;\n    tv.tv_usec = (timeout % 1000) * 1000;\n\n    do {\n        ret = select(fd + 1, &read_fds, &write_fds, NULL,\n                     timeout == (uint32_t) -1 ? NULL : &tv);\n    } while (IS_EINTR(ret));\n\n    if (ret < 0) {\n        return MBEDTLS_ERR_NET_POLL_FAILED;\n    }\n\n    ret = 0;\n    if (FD_ISSET(fd, &read_fds)) {\n        ret |= MBEDTLS_NET_POLL_READ;\n    }\n    if (FD_ISSET(fd, &write_fds)) {\n        ret |= MBEDTLS_NET_POLL_WRITE;\n    }\n\n    return ret;\n}\n\n/*\n * Portable usleep helper\n */\nvoid mbedtls_net_usleep(unsigned long usec)\n{\n#if defined(_WIN32)\n    Sleep((usec + 999) / 1000);\n#else\n    struct timeval tv;\n    tv.tv_sec  = usec / 1000000;\n#if (defined(__unix__) || defined(__unix) || \\\n    (defined(__APPLE__) && defined(__MACH__))) && !defined(__DJGPP__)\n    tv.tv_usec = (suseconds_t) usec % 1000000;\n#else\n    tv.tv_usec = usec % 1000000;\n#endif\n    select(0, NULL, NULL, NULL, &tv);\n#endif\n}\n\n/*\n * Read at most 'len' characters\n */\nint mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    int fd = ((mbedtls_net_context *) ctx)->fd;\n\n    ret = check_fd(fd, 0);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = (int) read(fd, buf, len);\n\n    if (ret < 0) {\n        if (net_would_block(ctx) != 0) {\n            return MBEDTLS_ERR_SSL_WANT_READ;\n        }\n\n#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \\\n        !defined(EFI32)\n        if (WSAGetLastError() == WSAECONNRESET) {\n            return MBEDTLS_ERR_NET_CONN_RESET;\n        }\n#else\n        if (errno == EPIPE || errno == ECONNRESET) {\n            return MBEDTLS_ERR_NET_CONN_RESET;\n        }\n\n        if (errno == EINTR) {\n            return MBEDTLS_ERR_SSL_WANT_READ;\n        }\n#endif\n\n        return MBEDTLS_ERR_NET_RECV_FAILED;\n    }\n\n    return ret;\n}\n\n/*\n * Read at most 'len' characters, blocking for at most 'timeout' ms\n */\nint mbedtls_net_recv_timeout(void *ctx, unsigned char *buf,\n                             size_t len, uint32_t timeout)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    struct timeval tv;\n    fd_set read_fds;\n    int fd = ((mbedtls_net_context *) ctx)->fd;\n\n    ret = check_fd(fd, 1);\n    if (ret != 0) {\n        return ret;\n    }\n\n    FD_ZERO(&read_fds);\n    FD_SET((SOCKET) fd, &read_fds);\n\n    tv.tv_sec  = timeout / 1000;\n    tv.tv_usec = (timeout % 1000) * 1000;\n\n    ret = select(fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv);\n\n    /* Zero fds ready means we timed out */\n    if (ret == 0) {\n        return MBEDTLS_ERR_SSL_TIMEOUT;\n    }\n\n    if (ret < 0) {\n#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \\\n        !defined(EFI32)\n        if (WSAGetLastError() == WSAEINTR) {\n            return MBEDTLS_ERR_SSL_WANT_READ;\n        }\n#else\n        if (errno == EINTR) {\n            return MBEDTLS_ERR_SSL_WANT_READ;\n        }\n#endif\n\n        return MBEDTLS_ERR_NET_RECV_FAILED;\n    }\n\n    /* This call will not block */\n    return mbedtls_net_recv(ctx, buf, len);\n}\n\n/*\n * Write at most 'len' characters\n */\nint mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    int fd = ((mbedtls_net_context *) ctx)->fd;\n\n    ret = check_fd(fd, 0);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = (int) write(fd, buf, len);\n\n    if (ret < 0) {\n        if (net_would_block(ctx) != 0) {\n            return MBEDTLS_ERR_SSL_WANT_WRITE;\n        }\n\n#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \\\n        !defined(EFI32)\n        if (WSAGetLastError() == WSAECONNRESET) {\n            return MBEDTLS_ERR_NET_CONN_RESET;\n        }\n#else\n        if (errno == EPIPE || errno == ECONNRESET) {\n            return MBEDTLS_ERR_NET_CONN_RESET;\n        }\n\n        if (errno == EINTR) {\n            return MBEDTLS_ERR_SSL_WANT_WRITE;\n        }\n#endif\n\n        return MBEDTLS_ERR_NET_SEND_FAILED;\n    }\n\n    return ret;\n}\n\n/*\n * Close the connection\n */\nvoid mbedtls_net_close(mbedtls_net_context *ctx)\n{\n    if (ctx->fd == -1) {\n        return;\n    }\n\n    close(ctx->fd);\n\n    ctx->fd = -1;\n}\n\n/*\n * Gracefully close the connection\n */\nvoid mbedtls_net_free(mbedtls_net_context *ctx)\n{\n    if (ctx == NULL || ctx->fd == -1) {\n        return;\n    }\n\n    shutdown(ctx->fd, 2);\n    close(ctx->fd);\n\n    ctx->fd = -1;\n}\n\n#endif /* MBEDTLS_NET_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/nist_kw.c",
    "content": "/*\n *  Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes\n *  only\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n * Definition of Key Wrapping:\n * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf\n * RFC 3394 \"Advanced Encryption Standard (AES) Key Wrap Algorithm\"\n * RFC 5649 \"Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm\"\n *\n * Note: RFC 3394 defines different methodology for intermediate operations for\n * the wrapping and unwrapping operation than the definition in NIST SP 800-38F.\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_NIST_KW_C)\n\n#include \"mbedtls/nist_kw.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/constant_time.h\"\n#include \"constant_time_internal.h\"\n\n#include <stdint.h>\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#if !defined(MBEDTLS_NIST_KW_ALT)\n\n#define KW_SEMIBLOCK_LENGTH    8\n#define MIN_SEMIBLOCKS_COUNT   3\n\n/*! The 64-bit default integrity check value (ICV) for KW mode. */\nstatic const unsigned char NIST_KW_ICV1[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 };\n/*! The 32-bit default integrity check value (ICV) for KWP mode. */\nstatic const  unsigned char NIST_KW_ICV2[] = { 0xA6, 0x59, 0x59, 0xA6 };\n\n/*\n * Initialize context\n */\nvoid mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_nist_kw_context));\n}\n\nint mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx,\n                           mbedtls_cipher_id_t cipher,\n                           const unsigned char *key,\n                           unsigned int keybits,\n                           const int is_wrap)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const mbedtls_cipher_info_t *cipher_info;\n\n    cipher_info = mbedtls_cipher_info_from_values(cipher,\n                                                  keybits,\n                                                  MBEDTLS_MODE_ECB);\n    if (cipher_info == NULL) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    /*\n     * SP 800-38F currently defines AES cipher as the only block cipher allowed:\n     * \"For KW and KWP, the underlying block cipher shall be approved, and the\n     *  block size shall be 128 bits. Currently, the AES block cipher, with key\n     *  lengths of 128, 192, or 256 bits, is the only block cipher that fits\n     *  this profile.\"\n     *  Currently we don't support other 128 bit block ciphers for key wrapping,\n     *  such as Camellia and Aria.\n     */\n    if (cipher != MBEDTLS_CIPHER_ID_AES) {\n        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n    }\n\n    mbedtls_cipher_free(&ctx->cipher_ctx);\n\n    if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,\n                                     is_wrap ? MBEDTLS_ENCRYPT :\n                                     MBEDTLS_DECRYPT)\n         ) != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\n/*\n * Free context\n */\nvoid mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_cipher_free(&ctx->cipher_ctx);\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));\n}\n\n/*\n * Helper function for Xoring the uint64_t \"t\" with the encrypted A.\n * Defined in NIST SP 800-38F section 6.1\n */\nstatic void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t)\n{\n    size_t i = 0;\n    for (i = 0; i < sizeof(t); i++) {\n        A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff;\n    }\n}\n\n/*\n * KW-AE as defined in SP 800-38F section 6.2\n * KWP-AE as defined in SP 800-38F section 6.3\n */\nint mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx,\n                         mbedtls_nist_kw_mode_t mode,\n                         const unsigned char *input, size_t in_len,\n                         unsigned char *output, size_t *out_len, size_t out_size)\n{\n    int ret = 0;\n    size_t semiblocks = 0;\n    size_t s;\n    size_t olen, padlen = 0;\n    uint64_t t = 0;\n    unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];\n    unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];\n\n    *out_len = 0;\n    /*\n     * Generate the String to work on\n     */\n    if (mode == MBEDTLS_KW_MODE_KW) {\n        if (out_size < in_len + KW_SEMIBLOCK_LENGTH) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        /*\n         * According to SP 800-38F Table 1, the plaintext length for KW\n         * must be between 2 to 2^54-1 semiblocks inclusive.\n         */\n        if (in_len < 16 ||\n#if SIZE_MAX > 0x1FFFFFFFFFFFFF8\n            in_len > 0x1FFFFFFFFFFFFF8 ||\n#endif\n            in_len % KW_SEMIBLOCK_LENGTH != 0) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH);\n        memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len);\n    } else {\n        if (in_len % 8 != 0) {\n            padlen = (8 - (in_len % 8));\n        }\n\n        if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        /*\n         * According to SP 800-38F Table 1, the plaintext length for KWP\n         * must be between 1 and 2^32-1 octets inclusive.\n         */\n        if (in_len < 1\n#if SIZE_MAX > 0xFFFFFFFF\n            || in_len > 0xFFFFFFFF\n#endif\n            ) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2);\n        MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output,\n                              KW_SEMIBLOCK_LENGTH / 2);\n\n        memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len);\n        memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen);\n    }\n    semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1;\n\n    s = 6 * (semiblocks - 1);\n\n    if (mode == MBEDTLS_KW_MODE_KWP\n        && in_len <= KW_SEMIBLOCK_LENGTH) {\n        memcpy(inbuff, output, 16);\n        ret = mbedtls_cipher_update(&ctx->cipher_ctx,\n                                    inbuff, 16, output, &olen);\n        if (ret != 0) {\n            goto cleanup;\n        }\n    } else {\n        unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;\n        unsigned char *A = output;\n\n        /*\n         * Do the wrapping function W, as defined in RFC 3394 section 2.2.1\n         */\n        if (semiblocks < MIN_SEMIBLOCKS_COUNT) {\n            ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n            goto cleanup;\n        }\n\n        /* Calculate intermediate values */\n        for (t = 1; t <= s; t++) {\n            memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);\n            memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH);\n\n            ret = mbedtls_cipher_update(&ctx->cipher_ctx,\n                                        inbuff, 16, outbuff, &olen);\n            if (ret != 0) {\n                goto cleanup;\n            }\n\n            memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);\n            calc_a_xor_t(A, t);\n\n            memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);\n            R2 += KW_SEMIBLOCK_LENGTH;\n            if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) {\n                R2 = output + KW_SEMIBLOCK_LENGTH;\n            }\n        }\n    }\n\n    *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;\n\ncleanup:\n\n    if (ret != 0) {\n        memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH);\n    }\n    mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2);\n    mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2);\n\n    return ret;\n}\n\n/*\n * W-1 function as defined in RFC 3394 section 2.2.2\n * This function assumes the following:\n * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.\n * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.\n * 3. Minimal number of semiblocks is 3.\n * 4. A is a buffer to hold the first semiblock of the input buffer.\n */\nstatic int unwrap(mbedtls_nist_kw_context *ctx,\n                  const unsigned char *input, size_t semiblocks,\n                  unsigned char A[KW_SEMIBLOCK_LENGTH],\n                  unsigned char *output, size_t *out_len)\n{\n    int ret = 0;\n    const size_t s = 6 * (semiblocks - 1);\n    size_t olen;\n    uint64_t t = 0;\n    unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];\n    unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];\n    unsigned char *R = NULL;\n    *out_len = 0;\n\n    if (semiblocks < MIN_SEMIBLOCKS_COUNT) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    memcpy(A, input, KW_SEMIBLOCK_LENGTH);\n    memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);\n    R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;\n\n    /* Calculate intermediate values */\n    for (t = s; t >= 1; t--) {\n        calc_a_xor_t(A, t);\n\n        memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);\n        memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH);\n\n        ret = mbedtls_cipher_update(&ctx->cipher_ctx,\n                                    inbuff, 16, outbuff, &olen);\n        if (ret != 0) {\n            goto cleanup;\n        }\n\n        memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);\n\n        /* Set R as LSB64 of outbuff */\n        memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);\n\n        if (R == output) {\n            R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;\n        } else {\n            R -= KW_SEMIBLOCK_LENGTH;\n        }\n    }\n\n    *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH;\n\ncleanup:\n    if (ret != 0) {\n        memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);\n    }\n    mbedtls_platform_zeroize(inbuff, sizeof(inbuff));\n    mbedtls_platform_zeroize(outbuff, sizeof(outbuff));\n\n    return ret;\n}\n\n/*\n * KW-AD as defined in SP 800-38F section 6.2\n * KWP-AD as defined in SP 800-38F section 6.3\n */\nint mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,\n                           mbedtls_nist_kw_mode_t mode,\n                           const unsigned char *input, size_t in_len,\n                           unsigned char *output, size_t *out_len, size_t out_size)\n{\n    int ret = 0;\n    size_t olen;\n    unsigned char A[KW_SEMIBLOCK_LENGTH];\n    int diff;\n\n    *out_len = 0;\n    if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n    if (mode == MBEDTLS_KW_MODE_KW) {\n        /*\n         * According to SP 800-38F Table 1, the ciphertext length for KW\n         * must be between 3 to 2^54 semiblocks inclusive.\n         */\n        if (in_len < 24 ||\n#if SIZE_MAX > 0x200000000000000\n            in_len > 0x200000000000000 ||\n#endif\n            in_len % KW_SEMIBLOCK_LENGTH != 0) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,\n                     A, output, out_len);\n        if (ret != 0) {\n            goto cleanup;\n        }\n\n        /* Check ICV in \"constant-time\" */\n        diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH);\n\n        if (diff != 0) {\n            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;\n            goto cleanup;\n        }\n\n    } else if (mode == MBEDTLS_KW_MODE_KWP) {\n        size_t padlen = 0;\n        uint32_t Plen;\n        /*\n         * According to SP 800-38F Table 1, the ciphertext length for KWP\n         * must be between 2 to 2^29 semiblocks inclusive.\n         */\n        if (in_len < KW_SEMIBLOCK_LENGTH * 2 ||\n#if SIZE_MAX > 0x100000000\n            in_len > 0x100000000 ||\n#endif\n            in_len % KW_SEMIBLOCK_LENGTH != 0) {\n            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n        }\n\n        if (in_len == KW_SEMIBLOCK_LENGTH * 2) {\n            unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];\n            ret = mbedtls_cipher_update(&ctx->cipher_ctx,\n                                        input, 16, outbuff, &olen);\n            if (ret != 0) {\n                goto cleanup;\n            }\n\n            memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);\n            memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);\n            mbedtls_platform_zeroize(outbuff, sizeof(outbuff));\n            *out_len = KW_SEMIBLOCK_LENGTH;\n        } else {\n            /* in_len >=  KW_SEMIBLOCK_LENGTH * 3 */\n            ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,\n                         A, output, out_len);\n            if (ret != 0) {\n                goto cleanup;\n            }\n        }\n\n        /* Check ICV in \"constant-time\" */\n        diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2);\n\n        if (diff != 0) {\n            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;\n        }\n\n        Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2);\n\n        /*\n         * Plen is the length of the plaintext, when the input is valid.\n         * If Plen is larger than the plaintext and padding, padlen will be\n         * larger than 8, because of the type wrap around.\n         */\n        padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;\n        ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7),\n                                  MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret);\n        padlen &= 7;\n\n        /* Check padding in \"constant-time\" */\n        const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 };\n        diff = mbedtls_ct_memcmp_partial(\n            &output[*out_len - KW_SEMIBLOCK_LENGTH], zero,\n            KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0);\n\n        if (diff != 0) {\n            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;\n        }\n\n        if (ret != 0) {\n            goto cleanup;\n        }\n        memset(output + Plen, 0, padlen);\n        *out_len = Plen;\n    } else {\n        ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;\n        goto cleanup;\n    }\n\ncleanup:\n    if (ret != 0) {\n        memset(output, 0, *out_len);\n        *out_len = 0;\n    }\n\n    mbedtls_platform_zeroize(&diff, sizeof(diff));\n    mbedtls_platform_zeroize(A, sizeof(A));\n\n    return ret;\n}\n\n#endif /* !MBEDTLS_NIST_KW_ALT */\n\n#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)\n\n/*\n * Test vectors taken from NIST\n * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW\n */\nstatic const unsigned int key_len[] = {\n    16,\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    24,\n    32\n#endif\n};\n\nstatic const unsigned char kw_key[][32] = {\n    { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,\n      0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,\n      0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,\n      0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },\n    { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,\n      0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,\n      0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,\n      0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }\n#endif\n};\n\nstatic const unsigned char kw_msg[][40] = {\n    { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,\n      0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,\n      0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,\n      0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,\n      0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,\n      0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },\n    { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,\n      0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,\n      0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }\n#endif\n};\n\nstatic const size_t kw_msg_len[] = {\n    16,\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    40,\n    24\n#endif\n};\nstatic const size_t kw_out_len[] = {\n    24,\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    48,\n    32\n#endif\n};\nstatic const unsigned char kw_res[][48] = {\n    { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,\n      0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,\n      0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,\n      0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,\n      0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,\n      0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,\n      0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,\n      0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },\n    { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,\n      0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,\n      0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,\n      0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }\n#endif\n};\n\nstatic const unsigned char kwp_key[][32] = {\n    { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,\n      0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,\n      0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,\n      0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },\n    { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,\n      0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,\n      0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,\n      0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }\n#endif\n};\n\nstatic const unsigned char kwp_msg[][31] = {\n    { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,\n      0x96 },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,\n      0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,\n      0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,\n      0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },\n    { 0xd1 }\n#endif\n};\nstatic const size_t kwp_msg_len[] = {\n    9,\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    31,\n    1\n#endif\n};\n\nstatic const unsigned char kwp_res[][48] = {\n    { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,\n      0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,\n      0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,\n      0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,\n      0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,\n      0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,\n      0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },\n    { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,\n      0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4  }\n#endif\n};\nstatic const size_t kwp_out_len[] = {\n    24,\n#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    40,\n    16\n#endif\n};\n\nint mbedtls_nist_kw_self_test(int verbose)\n{\n    mbedtls_nist_kw_context ctx;\n    unsigned char out[48];\n    size_t olen;\n    int i;\n    int ret = 0;\n    mbedtls_nist_kw_init(&ctx);\n\n    /*\n     * KW mode\n     */\n    {\n        static const int num_tests = sizeof(kw_key) / sizeof(*kw_key);\n\n        for (i = 0; i < num_tests; i++) {\n            if (verbose != 0) {\n                mbedtls_printf(\"  KW-AES-%u \", (unsigned int) key_len[i] * 8);\n            }\n\n            ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,\n                                         kw_key[i], key_len[i] * 8, 1);\n            if (ret != 0) {\n                if (verbose != 0) {\n                    mbedtls_printf(\"  KW: setup failed \");\n                }\n\n                goto end;\n            }\n\n            ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],\n                                       kw_msg_len[i], out, &olen, sizeof(out));\n            if (ret != 0 || kw_out_len[i] != olen ||\n                memcmp(out, kw_res[i], kw_out_len[i]) != 0) {\n                if (verbose != 0) {\n                    mbedtls_printf(\"failed. \");\n                }\n\n                ret = 1;\n                goto end;\n            }\n\n            if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,\n                                              kw_key[i], key_len[i] * 8, 0))\n                != 0) {\n                if (verbose != 0) {\n                    mbedtls_printf(\"  KW: setup failed \");\n                }\n\n                goto end;\n            }\n\n            ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,\n                                         out, olen, out, &olen, sizeof(out));\n\n            if (ret != 0 || olen != kw_msg_len[i] ||\n                memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {\n                if (verbose != 0) {\n                    mbedtls_printf(\"failed\\n\");\n                }\n\n                ret = 1;\n                goto end;\n            }\n\n            if (verbose != 0) {\n                mbedtls_printf(\" passed\\n\");\n            }\n        }\n    }\n\n    /*\n     * KWP mode\n     */\n    {\n        static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key);\n\n        for (i = 0; i < num_tests; i++) {\n            olen = sizeof(out);\n            if (verbose != 0) {\n                mbedtls_printf(\"  KWP-AES-%u \", (unsigned int) key_len[i] * 8);\n            }\n\n            ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],\n                                         key_len[i] * 8, 1);\n            if (ret  != 0) {\n                if (verbose != 0) {\n                    mbedtls_printf(\"  KWP: setup failed \");\n                }\n\n                goto end;\n            }\n            ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],\n                                       kwp_msg_len[i], out, &olen, sizeof(out));\n\n            if (ret != 0 || kwp_out_len[i] != olen ||\n                memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {\n                if (verbose != 0) {\n                    mbedtls_printf(\"failed. \");\n                }\n\n                ret = 1;\n                goto end;\n            }\n\n            if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,\n                                              kwp_key[i], key_len[i] * 8, 0))\n                != 0) {\n                if (verbose != 0) {\n                    mbedtls_printf(\"  KWP: setup failed \");\n                }\n\n                goto end;\n            }\n\n            ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,\n                                         olen, out, &olen, sizeof(out));\n\n            if (ret != 0 || olen != kwp_msg_len[i] ||\n                memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {\n                if (verbose != 0) {\n                    mbedtls_printf(\"failed. \");\n                }\n\n                ret = 1;\n                goto end;\n            }\n\n            if (verbose != 0) {\n                mbedtls_printf(\" passed\\n\");\n            }\n        }\n    }\nend:\n    mbedtls_nist_kw_free(&ctx);\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    return ret;\n}\n\n#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */\n\n#endif /* MBEDTLS_NIST_KW_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/oid.c",
    "content": "/**\n * \\file oid.c\n *\n * \\brief Object Identifier (OID) database\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_OID_C)\n\n#include \"mbedtls/oid.h\"\n#include \"mbedtls/rsa.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/pk.h\"\n\n#include <stdio.h>\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n/*\n * Macro to automatically add the size of #define'd OIDs\n */\n#define ADD_LEN(s)      s, MBEDTLS_OID_SIZE(s)\n\n/*\n * Macro to generate mbedtls_oid_descriptor_t\n */\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\n#define OID_DESCRIPTOR(s, name, description)  { ADD_LEN(s), name, description }\n#define NULL_OID_DESCRIPTOR                   { NULL, 0, NULL, NULL }\n#else\n#define OID_DESCRIPTOR(s, name, description)  { ADD_LEN(s) }\n#define NULL_OID_DESCRIPTOR                   { NULL, 0 }\n#endif\n\n/*\n * Macro to generate an internal function for oid_XXX_from_asn1() (used by\n * the other functions)\n */\n#define FN_OID_TYPED_FROM_ASN1(TYPE_T, NAME, LIST)                    \\\n    static const TYPE_T *oid_ ## NAME ## _from_asn1(                   \\\n        const mbedtls_asn1_buf *oid)     \\\n    {                                                                   \\\n        const TYPE_T *p = (LIST);                                       \\\n        const mbedtls_oid_descriptor_t *cur =                           \\\n            (const mbedtls_oid_descriptor_t *) p;                       \\\n        if (p == NULL || oid == NULL) return NULL;                  \\\n        while (cur->asn1 != NULL) {                                    \\\n            if (cur->asn1_len == oid->len &&                            \\\n                memcmp(cur->asn1, oid->p, oid->len) == 0) {          \\\n                return p;                                            \\\n            }                                                           \\\n            p++;                                                        \\\n            cur = (const mbedtls_oid_descriptor_t *) p;                 \\\n        }                                                               \\\n        return NULL;                                                 \\\n    }\n\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\n/*\n * Macro to generate a function for retrieving a single attribute from the\n * descriptor of an mbedtls_oid_descriptor_t wrapper.\n */\n#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \\\n    int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1)                  \\\n    {                                                                       \\\n        const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid);        \\\n        if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND;            \\\n        *ATTR1 = data->descriptor.ATTR1;                                    \\\n        return 0;                                                        \\\n    }\n#endif /* MBEDTLS_X509_REMOVE_INFO */\n\n/*\n * Macro to generate a function for retrieving a single attribute from an\n * mbedtls_oid_descriptor_t wrapper.\n */\n#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \\\n    int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1)                  \\\n    {                                                                       \\\n        const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid);        \\\n        if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND;            \\\n        *ATTR1 = data->ATTR1;                                               \\\n        return 0;                                                        \\\n    }\n\n/*\n * Macro to generate a function for retrieving two attributes from an\n * mbedtls_oid_descriptor_t wrapper.\n */\n#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1,     \\\n                         ATTR2_TYPE, ATTR2)                                 \\\n    int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1,               \\\n                ATTR2_TYPE * ATTR2)              \\\n    {                                                                           \\\n        const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid);            \\\n        if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND;                 \\\n        *(ATTR1) = data->ATTR1;                                                 \\\n        *(ATTR2) = data->ATTR2;                                                 \\\n        return 0;                                                            \\\n    }\n\n/*\n * Macro to generate a function for retrieving the OID based on a single\n * attribute from a mbedtls_oid_descriptor_t wrapper.\n */\n#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1)   \\\n    int FN_NAME(ATTR1_TYPE ATTR1, const char **oid, size_t *olen)             \\\n    {                                                                           \\\n        const TYPE_T *cur = (LIST);                                             \\\n        while (cur->descriptor.asn1 != NULL) {                                 \\\n            if (cur->ATTR1 == (ATTR1)) {                                       \\\n                *oid = cur->descriptor.asn1;                                    \\\n                *olen = cur->descriptor.asn1_len;                               \\\n                return 0;                                                    \\\n            }                                                                   \\\n            cur++;                                                              \\\n        }                                                                       \\\n        return MBEDTLS_ERR_OID_NOT_FOUND;                                    \\\n    }\n\n/*\n * Macro to generate a function for retrieving the OID based on two\n * attributes from a mbedtls_oid_descriptor_t wrapper.\n */\n#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1,   \\\n                                ATTR2_TYPE, ATTR2)                          \\\n    int FN_NAME(ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid,         \\\n                size_t *olen)                                                 \\\n    {                                                                           \\\n        const TYPE_T *cur = (LIST);                                             \\\n        while (cur->descriptor.asn1 != NULL) {                                 \\\n            if (cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2)) {              \\\n                *oid = cur->descriptor.asn1;                                    \\\n                *olen = cur->descriptor.asn1_len;                               \\\n                return 0;                                                    \\\n            }                                                                   \\\n            cur++;                                                              \\\n        }                                                                       \\\n        return MBEDTLS_ERR_OID_NOT_FOUND;                                   \\\n    }\n\n/*\n * For X520 attribute types\n */\ntypedef struct {\n    mbedtls_oid_descriptor_t    descriptor;\n    const char          *short_name;\n} oid_x520_attr_t;\n\nstatic const oid_x520_attr_t oid_x520_attr_type[] =\n{\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_CN,          \"id-at-commonName\",               \"Common Name\"),\n        \"CN\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_COUNTRY,     \"id-at-countryName\",              \"Country\"),\n        \"C\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_LOCALITY,    \"id-at-locality\",                 \"Locality\"),\n        \"L\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_STATE,       \"id-at-state\",                    \"State\"),\n        \"ST\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_ORGANIZATION, \"id-at-organizationName\",\n                       \"Organization\"),\n        \"O\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_ORG_UNIT,    \"id-at-organizationalUnitName\",   \"Org Unit\"),\n        \"OU\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_PKCS9_EMAIL,\n                       \"emailAddress\",\n                       \"E-mail address\"),\n        \"emailAddress\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_SERIAL_NUMBER,\n                       \"id-at-serialNumber\",\n                       \"Serial number\"),\n        \"serialNumber\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_ADDRESS,\n                       \"id-at-postalAddress\",\n                       \"Postal address\"),\n        \"postalAddress\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_CODE, \"id-at-postalCode\",               \"Postal code\"),\n        \"postalCode\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_SUR_NAME,    \"id-at-surName\",                  \"Surname\"),\n        \"SN\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_GIVEN_NAME,  \"id-at-givenName\",                \"Given name\"),\n        \"GN\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_INITIALS,    \"id-at-initials\",                 \"Initials\"),\n        \"initials\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_GENERATION_QUALIFIER,\n                       \"id-at-generationQualifier\",\n                       \"Generation qualifier\"),\n        \"generationQualifier\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_TITLE,       \"id-at-title\",                    \"Title\"),\n        \"title\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_DN_QUALIFIER,\n                       \"id-at-dnQualifier\",\n                       \"Distinguished Name qualifier\"),\n        \"dnQualifier\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_PSEUDONYM,   \"id-at-pseudonym\",                \"Pseudonym\"),\n        \"pseudonym\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_UID,            \"id-uid\",                         \"User Id\"),\n        \"uid\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_DOMAIN_COMPONENT,\n                       \"id-domainComponent\",\n                       \"Domain component\"),\n        \"DC\",\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AT_UNIQUE_IDENTIFIER,\n                       \"id-at-uniqueIdentifier\",\n                       \"Unique Identifier\"),\n        \"uniqueIdentifier\",\n    },\n    {\n        NULL_OID_DESCRIPTOR,\n        NULL,\n    }\n};\n\nFN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type)\nFN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name,\n                 oid_x520_attr_t,\n                 x520_attr,\n                 const char *,\n                 short_name)\n\n/*\n * For X509 extensions\n */\ntypedef struct {\n    mbedtls_oid_descriptor_t    descriptor;\n    int                 ext_type;\n} oid_x509_ext_t;\n\nstatic const oid_x509_ext_t oid_x509_ext[] =\n{\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_BASIC_CONSTRAINTS,\n                       \"id-ce-basicConstraints\",\n                       \"Basic Constraints\"),\n        MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS,\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_KEY_USAGE,            \"id-ce-keyUsage\",            \"Key Usage\"),\n        MBEDTLS_OID_X509_EXT_KEY_USAGE,\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_EXTENDED_KEY_USAGE,\n                       \"id-ce-extKeyUsage\",\n                       \"Extended Key Usage\"),\n        MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE,\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_ALT_NAME,\n                       \"id-ce-subjectAltName\",\n                       \"Subject Alt Name\"),\n        MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME,\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_NS_CERT_TYPE,\n                       \"id-netscape-certtype\",\n                       \"Netscape Certificate Type\"),\n        MBEDTLS_OID_X509_EXT_NS_CERT_TYPE,\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_CERTIFICATE_POLICIES,\n                       \"id-ce-certificatePolicies\",\n                       \"Certificate Policies\"),\n        MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES,\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,\n                       \"id-ce-subjectKeyIdentifier\",\n                       \"Subject Key Identifier\"),\n        MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER,\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,\n                       \"id-ce-authorityKeyIdentifier\",\n                       \"Authority Key Identifier\"),\n        MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER,\n    },\n    {\n        NULL_OID_DESCRIPTOR,\n        0,\n    },\n};\n\nFN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext)\nFN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type)\n\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\nstatic const mbedtls_oid_descriptor_t oid_ext_key_usage[] =\n{\n    OID_DESCRIPTOR(MBEDTLS_OID_SERVER_AUTH,\n                   \"id-kp-serverAuth\",\n                   \"TLS Web Server Authentication\"),\n    OID_DESCRIPTOR(MBEDTLS_OID_CLIENT_AUTH,\n                   \"id-kp-clientAuth\",\n                   \"TLS Web Client Authentication\"),\n    OID_DESCRIPTOR(MBEDTLS_OID_CODE_SIGNING,     \"id-kp-codeSigning\",     \"Code Signing\"),\n    OID_DESCRIPTOR(MBEDTLS_OID_EMAIL_PROTECTION, \"id-kp-emailProtection\", \"E-mail Protection\"),\n    OID_DESCRIPTOR(MBEDTLS_OID_TIME_STAMPING,    \"id-kp-timeStamping\",    \"Time Stamping\"),\n    OID_DESCRIPTOR(MBEDTLS_OID_OCSP_SIGNING,     \"id-kp-OCSPSigning\",     \"OCSP Signing\"),\n    OID_DESCRIPTOR(MBEDTLS_OID_WISUN_FAN,\n                   \"id-kp-wisun-fan-device\",\n                   \"Wi-SUN Alliance Field Area Network (FAN)\"),\n    NULL_OID_DESCRIPTOR,\n};\n\nFN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage)\nFN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage,\n                 mbedtls_oid_descriptor_t,\n                 ext_key_usage,\n                 const char *,\n                 description)\n\nstatic const mbedtls_oid_descriptor_t oid_certificate_policies[] =\n{\n    OID_DESCRIPTOR(MBEDTLS_OID_ANY_POLICY,      \"anyPolicy\",       \"Any Policy\"),\n    NULL_OID_DESCRIPTOR,\n};\n\nFN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, certificate_policies, oid_certificate_policies)\nFN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies,\n                 mbedtls_oid_descriptor_t,\n                 certificate_policies,\n                 const char *,\n                 description)\n#endif /* MBEDTLS_X509_REMOVE_INFO */\n\n/*\n * For SignatureAlgorithmIdentifier\n */\ntypedef struct {\n    mbedtls_oid_descriptor_t    descriptor;\n    mbedtls_md_type_t           md_alg;\n    mbedtls_pk_type_t           pk_alg;\n} oid_sig_alg_t;\n\nstatic const oid_sig_alg_t oid_sig_alg[] =\n{\n#if defined(MBEDTLS_RSA_C)\n#if defined(MBEDTLS_MD_CAN_MD5)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_MD5,        \"md5WithRSAEncryption\",     \"RSA with MD5\"),\n        MBEDTLS_MD_MD5,      MBEDTLS_PK_RSA,\n    },\n#endif /* MBEDTLS_MD_CAN_MD5 */\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA1,       \"sha-1WithRSAEncryption\",   \"RSA with SHA1\"),\n        MBEDTLS_MD_SHA1,     MBEDTLS_PK_RSA,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#if defined(MBEDTLS_MD_CAN_SHA224)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA224,     \"sha224WithRSAEncryption\",\n                       \"RSA with SHA-224\"),\n        MBEDTLS_MD_SHA224,   MBEDTLS_PK_RSA,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA224 */\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA256,     \"sha256WithRSAEncryption\",\n                       \"RSA with SHA-256\"),\n        MBEDTLS_MD_SHA256,   MBEDTLS_PK_RSA,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA384,     \"sha384WithRSAEncryption\",\n                       \"RSA with SHA-384\"),\n        MBEDTLS_MD_SHA384,   MBEDTLS_PK_RSA,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#if defined(MBEDTLS_MD_CAN_SHA512)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA512,     \"sha512WithRSAEncryption\",\n                       \"RSA with SHA-512\"),\n        MBEDTLS_MD_SHA512,   MBEDTLS_PK_RSA,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA512 */\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_RSA_SHA_OBS,      \"sha-1WithRSAEncryption\",   \"RSA with SHA1\"),\n        MBEDTLS_MD_SHA1,     MBEDTLS_PK_RSA,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#endif /* MBEDTLS_RSA_C */\n#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA1,       \"ecdsa-with-SHA1\",      \"ECDSA with SHA1\"),\n        MBEDTLS_MD_SHA1,     MBEDTLS_PK_ECDSA,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#if defined(MBEDTLS_MD_CAN_SHA224)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA224,     \"ecdsa-with-SHA224\",    \"ECDSA with SHA224\"),\n        MBEDTLS_MD_SHA224,   MBEDTLS_PK_ECDSA,\n    },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA256,     \"ecdsa-with-SHA256\",    \"ECDSA with SHA256\"),\n        MBEDTLS_MD_SHA256,   MBEDTLS_PK_ECDSA,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA384,     \"ecdsa-with-SHA384\",    \"ECDSA with SHA384\"),\n        MBEDTLS_MD_SHA384,   MBEDTLS_PK_ECDSA,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#if defined(MBEDTLS_MD_CAN_SHA512)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA512,     \"ecdsa-with-SHA512\",    \"ECDSA with SHA512\"),\n        MBEDTLS_MD_SHA512,   MBEDTLS_PK_ECDSA,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA512 */\n#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */\n#if defined(MBEDTLS_RSA_C)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_RSASSA_PSS,        \"RSASSA-PSS\",           \"RSASSA-PSS\"),\n        MBEDTLS_MD_NONE,     MBEDTLS_PK_RSASSA_PSS,\n    },\n#endif /* MBEDTLS_RSA_C */\n    {\n        NULL_OID_DESCRIPTOR,\n        MBEDTLS_MD_NONE, MBEDTLS_PK_NONE,\n    },\n};\n\nFN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg)\n\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\nFN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc,\n                            oid_sig_alg_t,\n                            sig_alg,\n                            const char *,\n                            description)\n#endif\n\nFN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg,\n                 oid_sig_alg_t,\n                 sig_alg,\n                 mbedtls_md_type_t,\n                 md_alg,\n                 mbedtls_pk_type_t,\n                 pk_alg)\nFN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg,\n                        oid_sig_alg_t,\n                        oid_sig_alg,\n                        mbedtls_pk_type_t,\n                        pk_alg,\n                        mbedtls_md_type_t,\n                        md_alg)\n\n/*\n * For PublicKeyInfo (PKCS1, RFC 5480)\n */\ntypedef struct {\n    mbedtls_oid_descriptor_t    descriptor;\n    mbedtls_pk_type_t           pk_alg;\n} oid_pk_alg_t;\n\nstatic const oid_pk_alg_t oid_pk_alg[] =\n{\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_RSA,           \"rsaEncryption\",    \"RSA\"),\n        MBEDTLS_PK_RSA,\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_UNRESTRICTED, \"id-ecPublicKey\",   \"Generic EC key\"),\n        MBEDTLS_PK_ECKEY,\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_ECDH,         \"id-ecDH\",          \"EC key for ECDH\"),\n        MBEDTLS_PK_ECKEY_DH,\n    },\n    {\n        NULL_OID_DESCRIPTOR,\n        MBEDTLS_PK_NONE,\n    },\n};\n\nFN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg)\nFN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg)\nFN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg,\n                        oid_pk_alg_t,\n                        oid_pk_alg,\n                        mbedtls_pk_type_t,\n                        pk_alg)\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n/*\n * For elliptic curves that use namedCurve inside ECParams (RFC 5480)\n */\ntypedef struct {\n    mbedtls_oid_descriptor_t    descriptor;\n    mbedtls_ecp_group_id        grp_id;\n} oid_ecp_grp_t;\n\nstatic const oid_ecp_grp_t oid_ecp_grp[] =\n{\n#if defined(MBEDTLS_ECP_HAVE_SECP192R1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192R1, \"secp192r1\",    \"secp192r1\"),\n        MBEDTLS_ECP_DP_SECP192R1,\n    },\n#endif /* MBEDTLS_ECP_HAVE_SECP192R1 */\n#if defined(MBEDTLS_ECP_HAVE_SECP224R1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224R1, \"secp224r1\",    \"secp224r1\"),\n        MBEDTLS_ECP_DP_SECP224R1,\n    },\n#endif /* MBEDTLS_ECP_HAVE_SECP224R1 */\n#if defined(MBEDTLS_ECP_HAVE_SECP256R1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256R1, \"secp256r1\",    \"secp256r1\"),\n        MBEDTLS_ECP_DP_SECP256R1,\n    },\n#endif /* MBEDTLS_ECP_HAVE_SECP256R1 */\n#if defined(MBEDTLS_ECP_HAVE_SECP384R1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP384R1, \"secp384r1\",    \"secp384r1\"),\n        MBEDTLS_ECP_DP_SECP384R1,\n    },\n#endif /* MBEDTLS_ECP_HAVE_SECP384R1 */\n#if defined(MBEDTLS_ECP_HAVE_SECP521R1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP521R1, \"secp521r1\",    \"secp521r1\"),\n        MBEDTLS_ECP_DP_SECP521R1,\n    },\n#endif /* MBEDTLS_ECP_HAVE_SECP521R1 */\n#if defined(MBEDTLS_ECP_HAVE_SECP192K1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192K1, \"secp192k1\",    \"secp192k1\"),\n        MBEDTLS_ECP_DP_SECP192K1,\n    },\n#endif /* MBEDTLS_ECP_HAVE_SECP192K1 */\n#if defined(MBEDTLS_ECP_HAVE_SECP224K1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224K1, \"secp224k1\",    \"secp224k1\"),\n        MBEDTLS_ECP_DP_SECP224K1,\n    },\n#endif /* MBEDTLS_ECP_HAVE_SECP224K1 */\n#if defined(MBEDTLS_ECP_HAVE_SECP256K1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256K1, \"secp256k1\",    \"secp256k1\"),\n        MBEDTLS_ECP_DP_SECP256K1,\n    },\n#endif /* MBEDTLS_ECP_HAVE_SECP256K1 */\n#if defined(MBEDTLS_ECP_HAVE_BP256R1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP256R1,   \"brainpoolP256r1\", \"brainpool256r1\"),\n        MBEDTLS_ECP_DP_BP256R1,\n    },\n#endif /* MBEDTLS_ECP_HAVE_BP256R1 */\n#if defined(MBEDTLS_ECP_HAVE_BP384R1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP384R1,   \"brainpoolP384r1\", \"brainpool384r1\"),\n        MBEDTLS_ECP_DP_BP384R1,\n    },\n#endif /* MBEDTLS_ECP_HAVE_BP384R1 */\n#if defined(MBEDTLS_ECP_HAVE_BP512R1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP512R1,   \"brainpoolP512r1\", \"brainpool512r1\"),\n        MBEDTLS_ECP_DP_BP512R1,\n    },\n#endif /* MBEDTLS_ECP_HAVE_BP512R1 */\n    {\n        NULL_OID_DESCRIPTOR,\n        MBEDTLS_ECP_DP_NONE,\n    },\n};\n\nFN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp)\nFN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id)\nFN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp,\n                        oid_ecp_grp_t,\n                        oid_ecp_grp,\n                        mbedtls_ecp_group_id,\n                        grp_id)\n\n/*\n * For Elliptic Curve algorithms that are directly\n * encoded in the AlgorithmIdentifier (RFC 8410)\n */\ntypedef struct {\n    mbedtls_oid_descriptor_t    descriptor;\n    mbedtls_ecp_group_id        grp_id;\n} oid_ecp_grp_algid_t;\n\nstatic const oid_ecp_grp_algid_t oid_ecp_grp_algid[] =\n{\n#if defined(MBEDTLS_ECP_HAVE_CURVE25519)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_X25519,               \"X25519\",       \"X25519\"),\n        MBEDTLS_ECP_DP_CURVE25519,\n    },\n#endif /* MBEDTLS_ECP_HAVE_CURVE25519 */\n#if defined(MBEDTLS_ECP_HAVE_CURVE448)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_X448,                 \"X448\",         \"X448\"),\n        MBEDTLS_ECP_DP_CURVE448,\n    },\n#endif /* MBEDTLS_ECP_HAVE_CURVE448 */\n    {\n        NULL_OID_DESCRIPTOR,\n        MBEDTLS_ECP_DP_NONE,\n    },\n};\n\nFN_OID_TYPED_FROM_ASN1(oid_ecp_grp_algid_t, grp_id_algid, oid_ecp_grp_algid)\nFN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp_algid,\n                 oid_ecp_grp_algid_t,\n                 grp_id_algid,\n                 mbedtls_ecp_group_id,\n                 grp_id)\nFN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp_algid,\n                        oid_ecp_grp_algid_t,\n                        oid_ecp_grp_algid,\n                        mbedtls_ecp_group_id,\n                        grp_id)\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n#if defined(MBEDTLS_CIPHER_C)\n/*\n * For PKCS#5 PBES2 encryption algorithm\n */\ntypedef struct {\n    mbedtls_oid_descriptor_t    descriptor;\n    mbedtls_cipher_type_t       cipher_alg;\n} oid_cipher_alg_t;\n\nstatic const oid_cipher_alg_t oid_cipher_alg[] =\n{\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_DES_CBC,              \"desCBC\",       \"DES-CBC\"),\n        MBEDTLS_CIPHER_DES_CBC,\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_DES_EDE3_CBC,         \"des-ede3-cbc\", \"DES-EDE3-CBC\"),\n        MBEDTLS_CIPHER_DES_EDE3_CBC,\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AES_128_CBC,          \"aes128-cbc\", \"AES128-CBC\"),\n        MBEDTLS_CIPHER_AES_128_CBC,\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AES_192_CBC,          \"aes192-cbc\", \"AES192-CBC\"),\n        MBEDTLS_CIPHER_AES_192_CBC,\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_AES_256_CBC,          \"aes256-cbc\", \"AES256-CBC\"),\n        MBEDTLS_CIPHER_AES_256_CBC,\n    },\n    {\n        NULL_OID_DESCRIPTOR,\n        MBEDTLS_CIPHER_NONE,\n    },\n};\n\nFN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg)\nFN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg,\n                 oid_cipher_alg_t,\n                 cipher_alg,\n                 mbedtls_cipher_type_t,\n                 cipher_alg)\n#endif /* MBEDTLS_CIPHER_C */\n\n/*\n * For digestAlgorithm\n */\ntypedef struct {\n    mbedtls_oid_descriptor_t    descriptor;\n    mbedtls_md_type_t           md_alg;\n} oid_md_alg_t;\n\nstatic const oid_md_alg_t oid_md_alg[] =\n{\n#if defined(MBEDTLS_MD_CAN_MD5)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_MD5,       \"id-md5\",       \"MD5\"),\n        MBEDTLS_MD_MD5,\n    },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA1,      \"id-sha1\",      \"SHA-1\"),\n        MBEDTLS_MD_SHA1,\n    },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA224)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA224,    \"id-sha224\",    \"SHA-224\"),\n        MBEDTLS_MD_SHA224,\n    },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA256,    \"id-sha256\",    \"SHA-256\"),\n        MBEDTLS_MD_SHA256,\n    },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA384,    \"id-sha384\",    \"SHA-384\"),\n        MBEDTLS_MD_SHA384,\n    },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA512)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA512,    \"id-sha512\",    \"SHA-512\"),\n        MBEDTLS_MD_SHA512,\n    },\n#endif\n#if defined(MBEDTLS_MD_CAN_RIPEMD160)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_RIPEMD160, \"id-ripemd160\", \"RIPEMD-160\"),\n        MBEDTLS_MD_RIPEMD160,\n    },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA3_224)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_224,    \"id-sha3-224\",    \"SHA-3-224\"),\n        MBEDTLS_MD_SHA3_224,\n    },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA3_256)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_256,    \"id-sha3-256\",    \"SHA-3-256\"),\n        MBEDTLS_MD_SHA3_256,\n    },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA3_384)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_384,    \"id-sha3-384\",    \"SHA-3-384\"),\n        MBEDTLS_MD_SHA3_384,\n    },\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA3_512)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_512,    \"id-sha3-512\",    \"SHA-3-512\"),\n        MBEDTLS_MD_SHA3_512,\n    },\n#endif\n    {\n        NULL_OID_DESCRIPTOR,\n        MBEDTLS_MD_NONE,\n    },\n};\n\nFN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg)\nFN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg)\nFN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md,\n                        oid_md_alg_t,\n                        oid_md_alg,\n                        mbedtls_md_type_t,\n                        md_alg)\n\n/*\n * For HMAC digestAlgorithm\n */\ntypedef struct {\n    mbedtls_oid_descriptor_t    descriptor;\n    mbedtls_md_type_t           md_hmac;\n} oid_md_hmac_t;\n\nstatic const oid_md_hmac_t oid_md_hmac[] =\n{\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA1,      \"hmacSHA1\",      \"HMAC-SHA-1\"),\n        MBEDTLS_MD_SHA1,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#if defined(MBEDTLS_MD_CAN_SHA224)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA224,    \"hmacSHA224\",    \"HMAC-SHA-224\"),\n        MBEDTLS_MD_SHA224,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA224 */\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA256,    \"hmacSHA256\",    \"HMAC-SHA-256\"),\n        MBEDTLS_MD_SHA256,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA384,    \"hmacSHA384\",    \"HMAC-SHA-384\"),\n        MBEDTLS_MD_SHA384,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#if defined(MBEDTLS_MD_CAN_SHA512)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA512,    \"hmacSHA512\",    \"HMAC-SHA-512\"),\n        MBEDTLS_MD_SHA512,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA512 */\n#if defined(MBEDTLS_MD_CAN_SHA3_224)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_224,    \"hmacSHA3-224\",    \"HMAC-SHA3-224\"),\n        MBEDTLS_MD_SHA3_224,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA3_224 */\n#if defined(MBEDTLS_MD_CAN_SHA3_256)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_256,    \"hmacSHA3-256\",    \"HMAC-SHA3-256\"),\n        MBEDTLS_MD_SHA3_256,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA3_256 */\n#if defined(MBEDTLS_MD_CAN_SHA3_384)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_384,    \"hmacSHA3-384\",    \"HMAC-SHA3-384\"),\n        MBEDTLS_MD_SHA3_384,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA3_384 */\n#if defined(MBEDTLS_MD_CAN_SHA3_512)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_512,    \"hmacSHA3-512\",    \"HMAC-SHA3-512\"),\n        MBEDTLS_MD_SHA3_512,\n    },\n#endif /* MBEDTLS_MD_CAN_SHA3_512 */\n#if defined(MBEDTLS_MD_CAN_RIPEMD160)\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_RIPEMD160,    \"hmacRIPEMD160\",    \"HMAC-RIPEMD160\"),\n        MBEDTLS_MD_RIPEMD160,\n    },\n#endif /* MBEDTLS_MD_CAN_RIPEMD160 */\n    {\n        NULL_OID_DESCRIPTOR,\n        MBEDTLS_MD_NONE,\n    },\n};\n\nFN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac)\nFN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac)\n\n#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_C)\n/*\n * For PKCS#12 PBEs\n */\ntypedef struct {\n    mbedtls_oid_descriptor_t    descriptor;\n    mbedtls_md_type_t           md_alg;\n    mbedtls_cipher_type_t       cipher_alg;\n} oid_pkcs12_pbe_alg_t;\n\nstatic const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] =\n{\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC,\n                       \"pbeWithSHAAnd3-KeyTripleDES-CBC\",\n                       \"PBE with SHA1 and 3-Key 3DES\"),\n        MBEDTLS_MD_SHA1,      MBEDTLS_CIPHER_DES_EDE3_CBC,\n    },\n    {\n        OID_DESCRIPTOR(MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC,\n                       \"pbeWithSHAAnd2-KeyTripleDES-CBC\",\n                       \"PBE with SHA1 and 2-Key 3DES\"),\n        MBEDTLS_MD_SHA1,      MBEDTLS_CIPHER_DES_EDE_CBC,\n    },\n    {\n        NULL_OID_DESCRIPTOR,\n        MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE,\n    },\n};\n\nFN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg)\nFN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg,\n                 oid_pkcs12_pbe_alg_t,\n                 pkcs12_pbe_alg,\n                 mbedtls_md_type_t,\n                 md_alg,\n                 mbedtls_cipher_type_t,\n                 cipher_alg)\n#endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_C */\n\n/* Return the x.y.z.... style numeric string for the given OID */\nint mbedtls_oid_get_numeric_string(char *buf, size_t size,\n                                   const mbedtls_asn1_buf *oid)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    char *p = buf;\n    size_t n = size;\n    unsigned int value = 0;\n\n    if (size > INT_MAX) {\n        /* Avoid overflow computing return value */\n        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;\n    }\n\n    if (oid->len <= 0) {\n        /* OID must not be empty */\n        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;\n    }\n\n    for (size_t i = 0; i < oid->len; i++) {\n        /* Prevent overflow in value. */\n        if (value > (UINT_MAX >> 7)) {\n            return MBEDTLS_ERR_ASN1_INVALID_DATA;\n        }\n        if ((value == 0) && ((oid->p[i]) == 0x80)) {\n            /* Overlong encoding is not allowed */\n            return MBEDTLS_ERR_ASN1_INVALID_DATA;\n        }\n\n        value <<= 7;\n        value |= oid->p[i] & 0x7F;\n\n        if (!(oid->p[i] & 0x80)) {\n            /* Last byte */\n            if (n == size) {\n                int component1;\n                unsigned int component2;\n                /* First subidentifier contains first two OID components */\n                if (value >= 80) {\n                    component1 = '2';\n                    component2 = value - 80;\n                } else if (value >= 40) {\n                    component1 = '1';\n                    component2 = value - 40;\n                } else {\n                    component1 = '0';\n                    component2 = value;\n                }\n                ret = mbedtls_snprintf(p, n, \"%c.%u\", component1, component2);\n            } else {\n                ret = mbedtls_snprintf(p, n, \".%u\", value);\n            }\n            if (ret < 2 || (size_t) ret >= n) {\n                return MBEDTLS_ERR_OID_BUF_TOO_SMALL;\n            }\n            n -= (size_t) ret;\n            p += ret;\n            value = 0;\n        }\n    }\n\n    if (value != 0) {\n        /* Unterminated subidentifier */\n        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;\n    }\n\n    return (int) (size - n);\n}\n\nstatic int oid_parse_number(unsigned int *num, const char **p, const char *bound)\n{\n    int ret = MBEDTLS_ERR_ASN1_INVALID_DATA;\n\n    *num = 0;\n\n    while (*p < bound && **p >= '0' && **p <= '9') {\n        ret = 0;\n        if (*num > (UINT_MAX / 10)) {\n            return MBEDTLS_ERR_ASN1_INVALID_DATA;\n        }\n        *num *= 10;\n        *num += **p - '0';\n        (*p)++;\n    }\n    return ret;\n}\n\nstatic size_t oid_subidentifier_num_bytes(unsigned int value)\n{\n    size_t num_bytes = 0;\n\n    do {\n        value >>= 7;\n        num_bytes++;\n    } while (value != 0);\n\n    return num_bytes;\n}\n\nstatic int oid_subidentifier_encode_into(unsigned char **p,\n                                         unsigned char *bound,\n                                         unsigned int value)\n{\n    size_t num_bytes = oid_subidentifier_num_bytes(value);\n\n    if ((size_t) (bound - *p) < num_bytes) {\n        return MBEDTLS_ERR_OID_BUF_TOO_SMALL;\n    }\n    (*p)[num_bytes - 1] = (unsigned char) (value & 0x7f);\n    value >>= 7;\n\n    for (size_t i = 2; i <= num_bytes; i++) {\n        (*p)[num_bytes - i] = 0x80 | (unsigned char) (value & 0x7f);\n        value >>= 7;\n    }\n    *p += num_bytes;\n\n    return 0;\n}\n\n/* Return the OID for the given x.y.z.... style numeric string  */\nint mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid,\n                                    const char *oid_str, size_t size)\n{\n    int ret = MBEDTLS_ERR_ASN1_INVALID_DATA;\n    const char *str_ptr = oid_str;\n    const char *str_bound = oid_str + size;\n    unsigned int val = 0;\n    unsigned int component1, component2;\n    size_t encoded_len;\n    unsigned char *resized_mem;\n\n    /* Count the number of dots to get a worst-case allocation size. */\n    size_t num_dots = 0;\n    for (size_t i = 0; i < size; i++) {\n        if (oid_str[i] == '.') {\n            num_dots++;\n        }\n    }\n    /* Allocate maximum possible required memory:\n     * There are (num_dots + 1) integer components, but the first 2 share the\n     * same subidentifier, so we only need num_dots subidentifiers maximum. */\n    if (num_dots == 0 || (num_dots > MBEDTLS_OID_MAX_COMPONENTS - 1)) {\n        return MBEDTLS_ERR_ASN1_INVALID_DATA;\n    }\n    /* Each byte can store 7 bits, calculate number of bytes for a\n     * subidentifier:\n     *\n     * bytes = ceil(subidentifer_size * 8 / 7)\n     */\n    size_t bytes_per_subidentifier = (((sizeof(unsigned int) * 8) - 1) / 7)\n                                     + 1;\n    size_t max_possible_bytes = num_dots * bytes_per_subidentifier;\n    oid->p = mbedtls_calloc(max_possible_bytes, 1);\n    if (oid->p == NULL) {\n        return MBEDTLS_ERR_ASN1_ALLOC_FAILED;\n    }\n    unsigned char *out_ptr = oid->p;\n    unsigned char *out_bound = oid->p + max_possible_bytes;\n\n    ret = oid_parse_number(&component1, &str_ptr, str_bound);\n    if (ret != 0) {\n        goto error;\n    }\n    if (component1 > 2) {\n        /* First component can't be > 2 */\n        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;\n        goto error;\n    }\n    if (str_ptr >= str_bound || *str_ptr != '.') {\n        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;\n        goto error;\n    }\n    str_ptr++;\n\n    ret = oid_parse_number(&component2, &str_ptr, str_bound);\n    if (ret != 0) {\n        goto error;\n    }\n    if ((component1 < 2) && (component2 > 39)) {\n        /* Root nodes 0 and 1 may have up to 40 children, numbered 0-39 */\n        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;\n        goto error;\n    }\n    if (str_ptr < str_bound) {\n        if (*str_ptr == '.') {\n            str_ptr++;\n        } else {\n            ret = MBEDTLS_ERR_ASN1_INVALID_DATA;\n            goto error;\n        }\n    }\n\n    if (component2 > (UINT_MAX - (component1 * 40))) {\n        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;\n        goto error;\n    }\n    ret = oid_subidentifier_encode_into(&out_ptr, out_bound,\n                                        (component1 * 40) + component2);\n    if (ret != 0) {\n        goto error;\n    }\n\n    while (str_ptr < str_bound) {\n        ret = oid_parse_number(&val, &str_ptr, str_bound);\n        if (ret != 0) {\n            goto error;\n        }\n        if (str_ptr < str_bound) {\n            if (*str_ptr == '.') {\n                str_ptr++;\n            } else {\n                ret = MBEDTLS_ERR_ASN1_INVALID_DATA;\n                goto error;\n            }\n        }\n\n        ret = oid_subidentifier_encode_into(&out_ptr, out_bound, val);\n        if (ret != 0) {\n            goto error;\n        }\n    }\n\n    encoded_len = (size_t) (out_ptr - oid->p);\n    resized_mem = mbedtls_calloc(encoded_len, 1);\n    if (resized_mem == NULL) {\n        ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED;\n        goto error;\n    }\n    memcpy(resized_mem, oid->p, encoded_len);\n    mbedtls_free(oid->p);\n    oid->p = resized_mem;\n    oid->len = encoded_len;\n\n    oid->tag = MBEDTLS_ASN1_OID;\n\n    return 0;\n\nerror:\n    mbedtls_free(oid->p);\n    oid->p = NULL;\n    oid->len = 0;\n    return ret;\n}\n\n#endif /* MBEDTLS_OID_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/padlock.c",
    "content": "/*\n *  VIA PadLock support functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  This implementation is based on the VIA PadLock Programming Guide:\n *\n *  http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/\n *  programming_guide.pdf\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PADLOCK_C)\n\n#include \"padlock.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)\n\n/*\n * PadLock detection routine\n */\nint mbedtls_padlock_has_support(int feature)\n{\n    static int flags = -1;\n    int ebx = 0, edx = 0;\n\n    if (flags == -1) {\n        asm (\"movl  %%ebx, %0           \\n\\t\"\n             \"movl  $0xC0000000, %%eax  \\n\\t\"\n             \"cpuid                     \\n\\t\"\n             \"cmpl  $0xC0000001, %%eax  \\n\\t\"\n             \"movl  $0, %%edx           \\n\\t\"\n             \"jb    1f                  \\n\\t\"\n             \"movl  $0xC0000001, %%eax  \\n\\t\"\n             \"cpuid                     \\n\\t\"\n             \"1:                        \\n\\t\"\n             \"movl  %%edx, %1           \\n\\t\"\n             \"movl  %2, %%ebx           \\n\\t\"\n             : \"=m\" (ebx), \"=m\" (edx)\n             :  \"m\" (ebx)\n             : \"eax\", \"ecx\", \"edx\");\n\n        flags = edx;\n    }\n\n    return flags & feature;\n}\n\n/*\n * PadLock AES-ECB block en(de)cryption\n */\nint mbedtls_padlock_xcryptecb(mbedtls_aes_context *ctx,\n                              int mode,\n                              const unsigned char input[16],\n                              unsigned char output[16])\n{\n    int ebx = 0;\n    uint32_t *rk;\n    uint32_t *blk;\n    uint32_t *ctrl;\n    unsigned char buf[256];\n\n    rk = ctx->buf + ctx->rk_offset;\n\n    if (((long) rk & 15) != 0) {\n        return MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED;\n    }\n\n    blk = MBEDTLS_PADLOCK_ALIGN16(buf);\n    memcpy(blk, input, 16);\n\n    ctrl = blk + 4;\n    *ctrl = 0x80 | ctx->nr | ((ctx->nr + (mode^1) - 10) << 9);\n\n    asm (\"pushfl                        \\n\\t\"\n         \"popfl                         \\n\\t\"\n         \"movl    %%ebx, %0             \\n\\t\"\n         \"movl    $1, %%ecx             \\n\\t\"\n         \"movl    %2, %%edx             \\n\\t\"\n         \"movl    %3, %%ebx             \\n\\t\"\n         \"movl    %4, %%esi             \\n\\t\"\n         \"movl    %4, %%edi             \\n\\t\"\n         \".byte  0xf3,0x0f,0xa7,0xc8    \\n\\t\"\n         \"movl    %1, %%ebx             \\n\\t\"\n         : \"=m\" (ebx)\n         :  \"m\" (ebx), \"m\" (ctrl), \"m\" (rk), \"m\" (blk)\n         : \"memory\", \"ecx\", \"edx\", \"esi\", \"edi\");\n\n    memcpy(output, blk, 16);\n\n    return 0;\n}\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n/*\n * PadLock AES-CBC buffer en(de)cryption\n */\nint mbedtls_padlock_xcryptcbc(mbedtls_aes_context *ctx,\n                              int mode,\n                              size_t length,\n                              unsigned char iv[16],\n                              const unsigned char *input,\n                              unsigned char *output)\n{\n    int ebx = 0;\n    size_t count;\n    uint32_t *rk;\n    uint32_t *iw;\n    uint32_t *ctrl;\n    unsigned char buf[256];\n\n    rk = ctx->buf + ctx->rk_offset;\n\n    if (((long) input  & 15) != 0 ||\n        ((long) output & 15) != 0 ||\n        ((long) rk & 15) != 0) {\n        return MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED;\n    }\n\n    iw = MBEDTLS_PADLOCK_ALIGN16(buf);\n    memcpy(iw, iv, 16);\n\n    ctrl = iw + 4;\n    *ctrl = 0x80 | ctx->nr | ((ctx->nr + (mode ^ 1) - 10) << 9);\n\n    count = (length + 15) >> 4;\n\n    asm (\"pushfl                        \\n\\t\"\n         \"popfl                         \\n\\t\"\n         \"movl    %%ebx, %0             \\n\\t\"\n         \"movl    %2, %%ecx             \\n\\t\"\n         \"movl    %3, %%edx             \\n\\t\"\n         \"movl    %4, %%ebx             \\n\\t\"\n         \"movl    %5, %%esi             \\n\\t\"\n         \"movl    %6, %%edi             \\n\\t\"\n         \"movl    %7, %%eax             \\n\\t\"\n         \".byte  0xf3,0x0f,0xa7,0xd0    \\n\\t\"\n         \"movl    %1, %%ebx             \\n\\t\"\n         : \"=m\" (ebx)\n         :  \"m\" (ebx), \"m\" (count), \"m\" (ctrl),\n         \"m\"  (rk), \"m\" (input), \"m\" (output), \"m\" (iw)\n         : \"memory\", \"eax\", \"ecx\", \"edx\", \"esi\", \"edi\");\n\n    memcpy(iv, iw, 16);\n\n    return 0;\n}\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n\n#endif /* MBEDTLS_VIA_PADLOCK_HAVE_CODE */\n\n#endif /* MBEDTLS_PADLOCK_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/padlock.h",
    "content": "/**\n * \\file padlock.h\n *\n * \\brief VIA PadLock ACE for HW encryption/decryption supported by some\n *        processors\n *\n * \\warning These functions are only for internal use by other library\n *          functions; you must not call them directly.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_PADLOCK_H\n#define MBEDTLS_PADLOCK_H\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/aes.h\"\n\n#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED               -0x0030  /**< Input data should be aligned. */\n\n#if defined(__has_feature)\n#if __has_feature(address_sanitizer)\n#define MBEDTLS_HAVE_ASAN\n#endif\n#endif\n\n/*\n * - `padlock` is implements with GNUC assembly for x86 target.\n * - Some versions of ASan result in errors about not enough registers.\n */\n#if defined(MBEDTLS_PADLOCK_C) && \\\n    defined(__GNUC__) && defined(MBEDTLS_ARCH_IS_X86) && \\\n    defined(MBEDTLS_HAVE_ASM) && \\\n    !defined(MBEDTLS_HAVE_ASAN)\n\n#define MBEDTLS_VIA_PADLOCK_HAVE_CODE\n\n#include <stdint.h>\n\n#define MBEDTLS_PADLOCK_RNG 0x000C\n#define MBEDTLS_PADLOCK_ACE 0x00C0\n#define MBEDTLS_PADLOCK_PHE 0x0C00\n#define MBEDTLS_PADLOCK_PMM 0x3000\n\n#define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) (x) & ~15))\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * \\brief          Internal PadLock detection routine\n *\n * \\note           This function is only for internal use by other library\n *                 functions; you must not call it directly.\n *\n * \\param feature  The feature to detect\n *\n * \\return         non-zero if CPU has support for the feature, 0 otherwise\n */\nint mbedtls_padlock_has_support(int feature);\n\n/**\n * \\brief          Internal PadLock AES-ECB block en(de)cryption\n *\n * \\note           This function is only for internal use by other library\n *                 functions; you must not call it directly.\n *\n * \\param ctx      AES context\n * \\param mode     MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT\n * \\param input    16-byte input block\n * \\param output   16-byte output block\n *\n * \\return         0 if success, 1 if operation failed\n */\nint mbedtls_padlock_xcryptecb(mbedtls_aes_context *ctx,\n                              int mode,\n                              const unsigned char input[16],\n                              unsigned char output[16]);\n\n/**\n * \\brief          Internal PadLock AES-CBC buffer en(de)cryption\n *\n * \\note           This function is only for internal use by other library\n *                 functions; you must not call it directly.\n *\n * \\param ctx      AES context\n * \\param mode     MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT\n * \\param length   length of the input data\n * \\param iv       initialization vector (updated after use)\n * \\param input    buffer holding the input data\n * \\param output   buffer holding the output data\n *\n * \\return         0 if success, 1 if operation failed\n */\nint mbedtls_padlock_xcryptcbc(mbedtls_aes_context *ctx,\n                              int mode,\n                              size_t length,\n                              unsigned char iv[16],\n                              const unsigned char *input,\n                              unsigned char *output);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* HAVE_X86  */\n\n#endif /* padlock.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/pem.c",
    "content": "/*\n *  Privacy Enhanced Mail (PEM) decoding\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)\n\n#include \"mbedtls/pem.h\"\n#include \"mbedtls/base64.h\"\n#include \"mbedtls/des.h\"\n#include \"mbedtls/aes.h\"\n#include \"mbedtls/md.h\"\n#include \"mbedtls/cipher.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"psa/crypto.h\"\n#endif\n\n#if defined(MBEDTLS_MD_CAN_MD5) &&  \\\n    defined(MBEDTLS_CIPHER_MODE_CBC) &&                             \\\n    (defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C))\n#define PEM_RFC1421\n#endif /* MBEDTLS_MD_CAN_MD5 &&\n          MBEDTLS_CIPHER_MODE_CBC &&\n          ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */\n\n#if defined(MBEDTLS_PEM_PARSE_C)\nvoid mbedtls_pem_init(mbedtls_pem_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_pem_context));\n}\n\n#if defined(PEM_RFC1421)\n/*\n * Read a 16-byte hex string and convert it to binary\n */\nstatic int pem_get_iv(const unsigned char *s, unsigned char *iv,\n                      size_t iv_len)\n{\n    size_t i, j, k;\n\n    memset(iv, 0, iv_len);\n\n    for (i = 0; i < iv_len * 2; i++, s++) {\n        if (*s >= '0' && *s <= '9') {\n            j = *s - '0';\n        } else\n        if (*s >= 'A' && *s <= 'F') {\n            j = *s - '7';\n        } else\n        if (*s >= 'a' && *s <= 'f') {\n            j = *s - 'W';\n        } else {\n            return MBEDTLS_ERR_PEM_INVALID_ENC_IV;\n        }\n\n        k = ((i & 1) != 0) ? j : j << 4;\n\n        iv[i >> 1] = (unsigned char) (iv[i >> 1] | k);\n    }\n\n    return 0;\n}\n\nstatic int pem_pbkdf1(unsigned char *key, size_t keylen,\n                      unsigned char *iv,\n                      const unsigned char *pwd, size_t pwdlen)\n{\n    mbedtls_md_context_t md5_ctx;\n    const mbedtls_md_info_t *md5_info;\n    unsigned char md5sum[16];\n    size_t use_len;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_md_init(&md5_ctx);\n\n    /* Prepare the context. (setup() errors gracefully on NULL info.) */\n    md5_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5);\n    if ((ret = mbedtls_md_setup(&md5_ctx, md5_info, 0)) != 0) {\n        goto exit;\n    }\n\n    /*\n     * key[ 0..15] = MD5(pwd || IV)\n     */\n    if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) {\n        goto exit;\n    }\n    if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) {\n        goto exit;\n    }\n    if ((ret = mbedtls_md_update(&md5_ctx, iv,  8)) != 0) {\n        goto exit;\n    }\n    if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) {\n        goto exit;\n    }\n\n    if (keylen <= 16) {\n        memcpy(key, md5sum, keylen);\n        goto exit;\n    }\n\n    memcpy(key, md5sum, 16);\n\n    /*\n     * key[16..23] = MD5(key[ 0..15] || pwd || IV])\n     */\n    if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) {\n        goto exit;\n    }\n    if ((ret = mbedtls_md_update(&md5_ctx, md5sum, 16)) != 0) {\n        goto exit;\n    }\n    if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) {\n        goto exit;\n    }\n    if ((ret = mbedtls_md_update(&md5_ctx, iv, 8)) != 0) {\n        goto exit;\n    }\n    if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) {\n        goto exit;\n    }\n\n    use_len = 16;\n    if (keylen < 32) {\n        use_len = keylen - 16;\n    }\n\n    memcpy(key + 16, md5sum, use_len);\n\nexit:\n    mbedtls_md_free(&md5_ctx);\n    mbedtls_platform_zeroize(md5sum, 16);\n\n    return ret;\n}\n\n#if defined(MBEDTLS_DES_C)\n/*\n * Decrypt with DES-CBC, using PBKDF1 for key derivation\n */\nstatic int pem_des_decrypt(unsigned char des_iv[8],\n                           unsigned char *buf, size_t buflen,\n                           const unsigned char *pwd, size_t pwdlen)\n{\n    mbedtls_des_context des_ctx;\n    unsigned char des_key[8];\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_des_init(&des_ctx);\n\n    if ((ret = pem_pbkdf1(des_key, 8, des_iv, pwd, pwdlen)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_des_setkey_dec(&des_ctx, des_key)) != 0) {\n        goto exit;\n    }\n    ret = mbedtls_des_crypt_cbc(&des_ctx, MBEDTLS_DES_DECRYPT, buflen,\n                                des_iv, buf, buf);\n\nexit:\n    mbedtls_des_free(&des_ctx);\n    mbedtls_platform_zeroize(des_key, 8);\n\n    return ret;\n}\n\n/*\n * Decrypt with 3DES-CBC, using PBKDF1 for key derivation\n */\nstatic int pem_des3_decrypt(unsigned char des3_iv[8],\n                            unsigned char *buf, size_t buflen,\n                            const unsigned char *pwd, size_t pwdlen)\n{\n    mbedtls_des3_context des3_ctx;\n    unsigned char des3_key[24];\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_des3_init(&des3_ctx);\n\n    if ((ret = pem_pbkdf1(des3_key, 24, des3_iv, pwd, pwdlen)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_des3_set3key_dec(&des3_ctx, des3_key)) != 0) {\n        goto exit;\n    }\n    ret = mbedtls_des3_crypt_cbc(&des3_ctx, MBEDTLS_DES_DECRYPT, buflen,\n                                 des3_iv, buf, buf);\n\nexit:\n    mbedtls_des3_free(&des3_ctx);\n    mbedtls_platform_zeroize(des3_key, 24);\n\n    return ret;\n}\n#endif /* MBEDTLS_DES_C */\n\n#if defined(MBEDTLS_AES_C)\n/*\n * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation\n */\nstatic int pem_aes_decrypt(unsigned char aes_iv[16], unsigned int keylen,\n                           unsigned char *buf, size_t buflen,\n                           const unsigned char *pwd, size_t pwdlen)\n{\n    mbedtls_aes_context aes_ctx;\n    unsigned char aes_key[32];\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_aes_init(&aes_ctx);\n\n    if ((ret = pem_pbkdf1(aes_key, keylen, aes_iv, pwd, pwdlen)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_aes_setkey_dec(&aes_ctx, aes_key, keylen * 8)) != 0) {\n        goto exit;\n    }\n    ret = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, buflen,\n                                aes_iv, buf, buf);\n\nexit:\n    mbedtls_aes_free(&aes_ctx);\n    mbedtls_platform_zeroize(aes_key, keylen);\n\n    return ret;\n}\n#endif /* MBEDTLS_AES_C */\n\n#if defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C)\nstatic int pem_check_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len)\n{\n    /* input_len > 0 is not guaranteed by mbedtls_pem_read_buffer(). */\n    if (input_len < 1) {\n        return MBEDTLS_ERR_PEM_INVALID_DATA;\n    }\n    size_t pad_len = input[input_len - 1];\n    size_t i;\n\n    if (pad_len > input_len) {\n        return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;\n    }\n\n    *data_len = input_len - pad_len;\n\n    for (i = *data_len; i < input_len; i++) {\n        if (input[i] != pad_len) {\n            return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;\n        }\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_DES_C || MBEDTLS_AES_C */\n\n#endif /* PEM_RFC1421 */\n\nint mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer,\n                            const unsigned char *data, const unsigned char *pwd,\n                            size_t pwdlen, size_t *use_len)\n{\n    int ret, enc;\n    size_t len;\n    unsigned char *buf;\n    const unsigned char *s1, *s2, *end;\n#if defined(PEM_RFC1421)\n    unsigned char pem_iv[16];\n    mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE;\n#else\n    ((void) pwd);\n    ((void) pwdlen);\n#endif /* PEM_RFC1421 */\n\n    if (ctx == NULL) {\n        return MBEDTLS_ERR_PEM_BAD_INPUT_DATA;\n    }\n\n    s1 = (unsigned char *) strstr((const char *) data, header);\n\n    if (s1 == NULL) {\n        return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;\n    }\n\n    s2 = (unsigned char *) strstr((const char *) data, footer);\n\n    if (s2 == NULL || s2 <= s1) {\n        return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;\n    }\n\n    s1 += strlen(header);\n    if (*s1 == ' ') {\n        s1++;\n    }\n    if (*s1 == '\\r') {\n        s1++;\n    }\n    if (*s1 == '\\n') {\n        s1++;\n    } else {\n        return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;\n    }\n\n    end = s2;\n    end += strlen(footer);\n    if (*end == ' ') {\n        end++;\n    }\n    if (*end == '\\r') {\n        end++;\n    }\n    if (*end == '\\n') {\n        end++;\n    }\n    *use_len = (size_t) (end - data);\n\n    enc = 0;\n\n    if (s2 - s1 >= 22 && memcmp(s1, \"Proc-Type: 4,ENCRYPTED\", 22) == 0) {\n#if defined(PEM_RFC1421)\n        enc++;\n\n        s1 += 22;\n        if (*s1 == '\\r') {\n            s1++;\n        }\n        if (*s1 == '\\n') {\n            s1++;\n        } else {\n            return MBEDTLS_ERR_PEM_INVALID_DATA;\n        }\n\n\n#if defined(MBEDTLS_DES_C)\n        if (s2 - s1 >= 23 && memcmp(s1, \"DEK-Info: DES-EDE3-CBC,\", 23) == 0) {\n            enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC;\n\n            s1 += 23;\n            if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) {\n                return MBEDTLS_ERR_PEM_INVALID_ENC_IV;\n            }\n\n            s1 += 16;\n        } else if (s2 - s1 >= 18 && memcmp(s1, \"DEK-Info: DES-CBC,\", 18) == 0) {\n            enc_alg = MBEDTLS_CIPHER_DES_CBC;\n\n            s1 += 18;\n            if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) {\n                return MBEDTLS_ERR_PEM_INVALID_ENC_IV;\n            }\n\n            s1 += 16;\n        }\n#endif /* MBEDTLS_DES_C */\n\n#if defined(MBEDTLS_AES_C)\n        if (s2 - s1 >= 14 && memcmp(s1, \"DEK-Info: AES-\", 14) == 0) {\n            if (s2 - s1 < 22) {\n                return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG;\n            } else if (memcmp(s1, \"DEK-Info: AES-128-CBC,\", 22) == 0) {\n                enc_alg = MBEDTLS_CIPHER_AES_128_CBC;\n            } else if (memcmp(s1, \"DEK-Info: AES-192-CBC,\", 22) == 0) {\n                enc_alg = MBEDTLS_CIPHER_AES_192_CBC;\n            } else if (memcmp(s1, \"DEK-Info: AES-256-CBC,\", 22) == 0) {\n                enc_alg = MBEDTLS_CIPHER_AES_256_CBC;\n            } else {\n                return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG;\n            }\n\n            s1 += 22;\n            if (s2 - s1 < 32 || pem_get_iv(s1, pem_iv, 16) != 0) {\n                return MBEDTLS_ERR_PEM_INVALID_ENC_IV;\n            }\n\n            s1 += 32;\n        }\n#endif /* MBEDTLS_AES_C */\n\n        if (enc_alg == MBEDTLS_CIPHER_NONE) {\n            return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG;\n        }\n\n        if (*s1 == '\\r') {\n            s1++;\n        }\n        if (*s1 == '\\n') {\n            s1++;\n        } else {\n            return MBEDTLS_ERR_PEM_INVALID_DATA;\n        }\n#else\n        return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE;\n#endif /* PEM_RFC1421 */\n    }\n\n    if (s1 >= s2) {\n        return MBEDTLS_ERR_PEM_INVALID_DATA;\n    }\n\n    ret = mbedtls_base64_decode(NULL, 0, &len, s1, (size_t) (s2 - s1));\n\n    if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret);\n    }\n\n    if (len == 0) {\n        return MBEDTLS_ERR_PEM_BAD_INPUT_DATA;\n    }\n\n    if ((buf = mbedtls_calloc(1, len)) == NULL) {\n        return MBEDTLS_ERR_PEM_ALLOC_FAILED;\n    }\n\n    if ((ret = mbedtls_base64_decode(buf, len, &len, s1, (size_t) (s2 - s1))) != 0) {\n        mbedtls_zeroize_and_free(buf, len);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret);\n    }\n\n    if (enc != 0) {\n#if defined(PEM_RFC1421)\n        if (pwd == NULL) {\n            mbedtls_zeroize_and_free(buf, len);\n            return MBEDTLS_ERR_PEM_PASSWORD_REQUIRED;\n        }\n\n        ret = 0;\n\n#if defined(MBEDTLS_DES_C)\n        if (enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC) {\n            ret = pem_des3_decrypt(pem_iv, buf, len, pwd, pwdlen);\n        } else if (enc_alg == MBEDTLS_CIPHER_DES_CBC) {\n            ret = pem_des_decrypt(pem_iv, buf, len, pwd, pwdlen);\n        }\n#endif /* MBEDTLS_DES_C */\n\n#if defined(MBEDTLS_AES_C)\n        if (enc_alg == MBEDTLS_CIPHER_AES_128_CBC) {\n            ret = pem_aes_decrypt(pem_iv, 16, buf, len, pwd, pwdlen);\n        } else if (enc_alg == MBEDTLS_CIPHER_AES_192_CBC) {\n            ret = pem_aes_decrypt(pem_iv, 24, buf, len, pwd, pwdlen);\n        } else if (enc_alg == MBEDTLS_CIPHER_AES_256_CBC) {\n            ret = pem_aes_decrypt(pem_iv, 32, buf, len, pwd, pwdlen);\n        }\n#endif /* MBEDTLS_AES_C */\n\n        if (ret != 0) {\n            mbedtls_zeroize_and_free(buf, len);\n            return ret;\n        }\n\n        /* Check PKCS padding and update data length based on padding info.\n         * This can be used to detect invalid padding data and password\n         * mismatches. */\n        size_t unpadded_len;\n        ret = pem_check_pkcs_padding(buf, len, &unpadded_len);\n        if (ret != 0) {\n            mbedtls_zeroize_and_free(buf, len);\n            return ret;\n        }\n        len = unpadded_len;\n#else\n        mbedtls_zeroize_and_free(buf, len);\n        return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE;\n#endif /* PEM_RFC1421 */\n    }\n\n    ctx->buf = buf;\n    ctx->buflen = len;\n\n    return 0;\n}\n\nvoid mbedtls_pem_free(mbedtls_pem_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    if (ctx->buf != NULL) {\n        mbedtls_zeroize_and_free(ctx->buf, ctx->buflen);\n    }\n    mbedtls_free(ctx->info);\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pem_context));\n}\n#endif /* MBEDTLS_PEM_PARSE_C */\n\n#if defined(MBEDTLS_PEM_WRITE_C)\nint mbedtls_pem_write_buffer(const char *header, const char *footer,\n                             const unsigned char *der_data, size_t der_len,\n                             unsigned char *buf, size_t buf_len, size_t *olen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *encode_buf = NULL, *c, *p = buf;\n    size_t len = 0, use_len, add_len = 0;\n\n    mbedtls_base64_encode(NULL, 0, &use_len, der_data, der_len);\n    add_len = strlen(header) + strlen(footer) + (((use_len > 2) ? (use_len - 2) : 0) / 64) + 1;\n\n    if (use_len + add_len > buf_len) {\n        *olen = use_len + add_len;\n        return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;\n    }\n\n    if (use_len != 0 &&\n        ((encode_buf = mbedtls_calloc(1, use_len)) == NULL)) {\n        return MBEDTLS_ERR_PEM_ALLOC_FAILED;\n    }\n\n    if ((ret = mbedtls_base64_encode(encode_buf, use_len, &use_len, der_data,\n                                     der_len)) != 0) {\n        mbedtls_free(encode_buf);\n        return ret;\n    }\n\n    memcpy(p, header, strlen(header));\n    p += strlen(header);\n    c = encode_buf;\n\n    while (use_len) {\n        len = (use_len > 64) ? 64 : use_len;\n        memcpy(p, c, len);\n        use_len -= len;\n        p += len;\n        c += len;\n        *p++ = '\\n';\n    }\n\n    memcpy(p, footer, strlen(footer));\n    p += strlen(footer);\n\n    *p++ = '\\0';\n    *olen = (size_t) (p - buf);\n\n    /* Clean any remaining data previously written to the buffer */\n    memset(buf + *olen, 0, buf_len - *olen);\n\n    mbedtls_free(encode_buf);\n    return 0;\n}\n#endif /* MBEDTLS_PEM_WRITE_C */\n#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/pk.c",
    "content": "/*\n *  Public Key abstraction layer\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PK_C)\n#include \"mbedtls/pk.h\"\n#include \"pk_wrap.h\"\n#include \"pkwrite.h\"\n#include \"pk_internal.h\"\n\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#if defined(MBEDTLS_RSA_C)\n#include \"mbedtls/rsa.h\"\n#include \"rsa_internal.h\"\n#endif\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n#include \"mbedtls/ecp.h\"\n#endif\n#if defined(MBEDTLS_ECDSA_C)\n#include \"mbedtls/ecdsa.h\"\n#endif\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)\n#include \"psa_util_internal.h\"\n#include \"mbedtls/psa_util.h\"\n#endif\n\n#include <limits.h>\n#include <stdint.h>\n\n/*\n * Initialise a mbedtls_pk_context\n */\nvoid mbedtls_pk_init(mbedtls_pk_context *ctx)\n{\n    ctx->pk_info = NULL;\n    ctx->pk_ctx = NULL;\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    ctx->priv_id = MBEDTLS_SVC_KEY_ID_INIT;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n    memset(ctx->pub_raw, 0, sizeof(ctx->pub_raw));\n    ctx->pub_raw_len = 0;\n    ctx->ec_family = 0;\n    ctx->ec_bits = 0;\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n}\n\n/*\n * Free (the components of) a mbedtls_pk_context\n */\nvoid mbedtls_pk_free(mbedtls_pk_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    if ((ctx->pk_info != NULL) && (ctx->pk_info->ctx_free_func != NULL)) {\n        ctx->pk_info->ctx_free_func(ctx->pk_ctx);\n    }\n\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n    /* The ownership of the priv_id key for opaque keys is external of the PK\n     * module. It's the user responsibility to clear it after use. */\n    if ((ctx->pk_info != NULL) && (ctx->pk_info->type != MBEDTLS_PK_OPAQUE)) {\n        psa_destroy_key(ctx->priv_id);\n    }\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pk_context));\n}\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n/*\n * Initialize a restart context\n */\nvoid mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx)\n{\n    ctx->pk_info = NULL;\n    ctx->rs_ctx = NULL;\n}\n\n/*\n * Free the components of a restart context\n */\nvoid mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx)\n{\n    if (ctx == NULL || ctx->pk_info == NULL ||\n        ctx->pk_info->rs_free_func == NULL) {\n        return;\n    }\n\n    ctx->pk_info->rs_free_func(ctx->rs_ctx);\n\n    ctx->pk_info = NULL;\n    ctx->rs_ctx = NULL;\n}\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n\n/*\n * Get pk_info structure from type\n */\nconst mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type)\n{\n    switch (pk_type) {\n#if defined(MBEDTLS_RSA_C)\n        case MBEDTLS_PK_RSA:\n            return &mbedtls_rsa_info;\n#endif /* MBEDTLS_RSA_C */\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n        case MBEDTLS_PK_ECKEY:\n            return &mbedtls_eckey_info;\n        case MBEDTLS_PK_ECKEY_DH:\n            return &mbedtls_eckeydh_info;\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)\n        case MBEDTLS_PK_ECDSA:\n            return &mbedtls_ecdsa_info;\n#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */\n        /* MBEDTLS_PK_RSA_ALT omitted on purpose */\n        default:\n            return NULL;\n    }\n}\n\n/*\n * Initialise context\n */\nint mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info)\n{\n    if (info == NULL || ctx->pk_info != NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if ((info->ctx_alloc_func != NULL) &&\n        ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL)) {\n        return MBEDTLS_ERR_PK_ALLOC_FAILED;\n    }\n\n    ctx->pk_info = info;\n\n    return 0;\n}\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n/*\n * Initialise a PSA-wrapping context\n */\nint mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx,\n                            const mbedtls_svc_key_id_t key)\n{\n    const mbedtls_pk_info_t *info = NULL;\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    psa_key_type_t type;\n\n    if (ctx == NULL || ctx->pk_info != NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if (PSA_SUCCESS != psa_get_key_attributes(key, &attributes)) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n    type = psa_get_key_type(&attributes);\n    psa_reset_key_attributes(&attributes);\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {\n        info = &mbedtls_ecdsa_opaque_info;\n    } else\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n    if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {\n        info = &mbedtls_rsa_opaque_info;\n    } else {\n        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n    }\n\n    ctx->pk_info = info;\n    ctx->priv_id = key;\n\n    return 0;\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)\n/*\n * Initialize an RSA-alt context\n */\nint mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key,\n                             mbedtls_pk_rsa_alt_decrypt_func decrypt_func,\n                             mbedtls_pk_rsa_alt_sign_func sign_func,\n                             mbedtls_pk_rsa_alt_key_len_func key_len_func)\n{\n    mbedtls_rsa_alt_context *rsa_alt;\n    const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info;\n\n    if (ctx->pk_info != NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) {\n        return MBEDTLS_ERR_PK_ALLOC_FAILED;\n    }\n\n    ctx->pk_info = info;\n\n    rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx;\n\n    rsa_alt->key = key;\n    rsa_alt->decrypt_func = decrypt_func;\n    rsa_alt->sign_func = sign_func;\n    rsa_alt->key_len_func = key_len_func;\n\n    return 0;\n}\n#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */\n\n/*\n * Tell if a PK can do the operations of the given type\n */\nint mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type)\n{\n    /* A context with null pk_info is not set up yet and can't do anything.\n     * For backward compatibility, also accept NULL instead of a context\n     * pointer. */\n    if (ctx == NULL || ctx->pk_info == NULL) {\n        return 0;\n    }\n\n    return ctx->pk_info->can_do(type);\n}\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n/*\n * Tell if a PK can do the operations of the given PSA algorithm\n */\nint mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg,\n                          psa_key_usage_t usage)\n{\n    psa_key_usage_t key_usage;\n\n    /* A context with null pk_info is not set up yet and can't do anything.\n     * For backward compatibility, also accept NULL instead of a context\n     * pointer. */\n    if (ctx == NULL || ctx->pk_info == NULL) {\n        return 0;\n    }\n\n    /* Filter out non allowed algorithms */\n    if (PSA_ALG_IS_ECDSA(alg) == 0 &&\n        PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) == 0 &&\n        PSA_ALG_IS_RSA_PSS(alg) == 0 &&\n        alg != PSA_ALG_RSA_PKCS1V15_CRYPT &&\n        PSA_ALG_IS_ECDH(alg) == 0) {\n        return 0;\n    }\n\n    /* Filter out non allowed usage flags */\n    if (usage == 0 ||\n        (usage & ~(PSA_KEY_USAGE_SIGN_HASH |\n                   PSA_KEY_USAGE_DECRYPT |\n                   PSA_KEY_USAGE_DERIVE)) != 0) {\n        return 0;\n    }\n\n    /* Wildcard hash is not allowed */\n    if (PSA_ALG_IS_SIGN_HASH(alg) &&\n        PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH) {\n        return 0;\n    }\n\n    if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_OPAQUE) {\n        mbedtls_pk_type_t type;\n\n        if (PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_ECDH(alg)) {\n            type = MBEDTLS_PK_ECKEY;\n        } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||\n                   alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {\n            type = MBEDTLS_PK_RSA;\n        } else if (PSA_ALG_IS_RSA_PSS(alg)) {\n            type = MBEDTLS_PK_RSASSA_PSS;\n        } else {\n            return 0;\n        }\n\n        if (ctx->pk_info->can_do(type) == 0) {\n            return 0;\n        }\n\n        switch (type) {\n            case MBEDTLS_PK_ECKEY:\n                key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DERIVE;\n                break;\n            case MBEDTLS_PK_RSA:\n            case MBEDTLS_PK_RSASSA_PSS:\n                key_usage = PSA_KEY_USAGE_SIGN_HASH |\n                            PSA_KEY_USAGE_SIGN_MESSAGE |\n                            PSA_KEY_USAGE_DECRYPT;\n                break;\n            default:\n                /* Should never happen */\n                return 0;\n        }\n\n        return (key_usage & usage) == usage;\n    }\n\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    psa_status_t status;\n\n    status = psa_get_key_attributes(ctx->priv_id, &attributes);\n    if (status != PSA_SUCCESS) {\n        return 0;\n    }\n\n    psa_algorithm_t key_alg = psa_get_key_algorithm(&attributes);\n    /* Key's enrollment is available only when an Mbed TLS implementation of PSA\n     * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined.\n     * Even though we don't officially support using other implementations of PSA\n     * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations\n     * separated. */\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n    psa_algorithm_t key_alg2 = psa_get_key_enrollment_algorithm(&attributes);\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n    key_usage = psa_get_key_usage_flags(&attributes);\n    psa_reset_key_attributes(&attributes);\n\n    if ((key_usage & usage) != usage) {\n        return 0;\n    }\n\n    /*\n     * Common case: the key alg [or alg2] only allows alg.\n     * This will match PSA_ALG_RSA_PKCS1V15_CRYPT & PSA_ALG_IS_ECDH\n     * directly.\n     * This would also match ECDSA/RSA_PKCS1V15_SIGN/RSA_PSS with\n     * a fixed hash on key_alg [or key_alg2].\n     */\n    if (alg == key_alg) {\n        return 1;\n    }\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n    if (alg == key_alg2) {\n        return 1;\n    }\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n\n    /*\n     * If key_alg [or key_alg2] is a hash-and-sign with a wildcard for the hash,\n     * and alg is the same hash-and-sign family with any hash,\n     * then alg is compliant with this key alg\n     */\n    if (PSA_ALG_IS_SIGN_HASH(alg)) {\n        if (PSA_ALG_IS_SIGN_HASH(key_alg) &&\n            PSA_ALG_SIGN_GET_HASH(key_alg) == PSA_ALG_ANY_HASH &&\n            (alg & ~PSA_ALG_HASH_MASK) == (key_alg & ~PSA_ALG_HASH_MASK)) {\n            return 1;\n        }\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n        if (PSA_ALG_IS_SIGN_HASH(key_alg2) &&\n            PSA_ALG_SIGN_GET_HASH(key_alg2) == PSA_ALG_ANY_HASH &&\n            (alg & ~PSA_ALG_HASH_MASK) == (key_alg2 & ~PSA_ALG_HASH_MASK)) {\n            return 1;\n        }\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)\n#if defined(MBEDTLS_RSA_C)\nstatic psa_algorithm_t psa_algorithm_for_rsa(const mbedtls_rsa_context *rsa,\n                                             int want_crypt)\n{\n    if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {\n        if (want_crypt) {\n            mbedtls_md_type_t md_type = (mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa);\n            return PSA_ALG_RSA_OAEP(mbedtls_md_psa_alg_from_type(md_type));\n        } else {\n            return PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH);\n        }\n    } else {\n        if (want_crypt) {\n            return PSA_ALG_RSA_PKCS1V15_CRYPT;\n        } else {\n            return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH);\n        }\n    }\n}\n#endif /* MBEDTLS_RSA_C */\n\nint mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk,\n                                  psa_key_usage_t usage,\n                                  psa_key_attributes_t *attributes)\n{\n    mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);\n\n    psa_key_usage_t more_usage = usage;\n    if (usage == PSA_KEY_USAGE_SIGN_MESSAGE) {\n        more_usage |= PSA_KEY_USAGE_VERIFY_MESSAGE;\n    } else if (usage == PSA_KEY_USAGE_SIGN_HASH) {\n        more_usage |= PSA_KEY_USAGE_VERIFY_HASH;\n    } else if (usage == PSA_KEY_USAGE_DECRYPT) {\n        more_usage |= PSA_KEY_USAGE_ENCRYPT;\n    }\n    more_usage |= PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY;\n\n    int want_private = !(usage == PSA_KEY_USAGE_VERIFY_MESSAGE ||\n                         usage == PSA_KEY_USAGE_VERIFY_HASH ||\n                         usage == PSA_KEY_USAGE_ENCRYPT);\n\n    switch (pk_type) {\n#if defined(MBEDTLS_RSA_C)\n        case MBEDTLS_PK_RSA:\n        {\n            int want_crypt = 0; /* 0: sign/verify; 1: encrypt/decrypt */\n            switch (usage) {\n                case PSA_KEY_USAGE_SIGN_MESSAGE:\n                case PSA_KEY_USAGE_SIGN_HASH:\n                case PSA_KEY_USAGE_VERIFY_MESSAGE:\n                case PSA_KEY_USAGE_VERIFY_HASH:\n                    /* Nothing to do. */\n                    break;\n                case PSA_KEY_USAGE_DECRYPT:\n                case PSA_KEY_USAGE_ENCRYPT:\n                    want_crypt = 1;\n                    break;\n                default:\n                    return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n            }\n            /* Detect the presence of a private key in a way that works both\n             * in CRT and non-CRT configurations. */\n            mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);\n            int has_private = (mbedtls_rsa_check_privkey(rsa) == 0);\n            if (want_private && !has_private) {\n                return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n            }\n            psa_set_key_type(attributes, (want_private ?\n                                          PSA_KEY_TYPE_RSA_KEY_PAIR :\n                                          PSA_KEY_TYPE_RSA_PUBLIC_KEY));\n            psa_set_key_bits(attributes, mbedtls_pk_get_bitlen(pk));\n            psa_set_key_algorithm(attributes,\n                                  psa_algorithm_for_rsa(rsa, want_crypt));\n            break;\n        }\n#endif /* MBEDTLS_RSA_C */\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n        case MBEDTLS_PK_ECKEY:\n        case MBEDTLS_PK_ECKEY_DH:\n        case MBEDTLS_PK_ECDSA:\n        {\n            int sign_ok = (pk_type != MBEDTLS_PK_ECKEY_DH);\n            int derive_ok = (pk_type != MBEDTLS_PK_ECDSA);\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n            psa_ecc_family_t family = pk->ec_family;\n            size_t bits = pk->ec_bits;\n            int has_private = 0;\n            if (pk->priv_id != MBEDTLS_SVC_KEY_ID_INIT) {\n                has_private = 1;\n            }\n#else\n            const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);\n            int has_private = (ec->d.n != 0);\n            size_t bits = 0;\n            psa_ecc_family_t family =\n                mbedtls_ecc_group_to_psa(ec->grp.id, &bits);\n#endif\n            psa_algorithm_t alg = 0;\n            switch (usage) {\n                case PSA_KEY_USAGE_SIGN_MESSAGE:\n                case PSA_KEY_USAGE_SIGN_HASH:\n                case PSA_KEY_USAGE_VERIFY_MESSAGE:\n                case PSA_KEY_USAGE_VERIFY_HASH:\n                    if (!sign_ok) {\n                        return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n                    }\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC)\n                    alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH);\n#else\n                    alg = PSA_ALG_ECDSA(PSA_ALG_ANY_HASH);\n#endif\n                    break;\n                case PSA_KEY_USAGE_DERIVE:\n                    alg = PSA_ALG_ECDH;\n                    if (!derive_ok) {\n                        return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n                    }\n                    break;\n                default:\n                    return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n            }\n            if (want_private && !has_private) {\n                return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n            }\n            psa_set_key_type(attributes, (want_private ?\n                                          PSA_KEY_TYPE_ECC_KEY_PAIR(family) :\n                                          PSA_KEY_TYPE_ECC_PUBLIC_KEY(family)));\n            psa_set_key_bits(attributes, bits);\n            psa_set_key_algorithm(attributes, alg);\n            break;\n        }\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)\n        case MBEDTLS_PK_RSA_ALT:\n            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        case MBEDTLS_PK_OPAQUE:\n        {\n            psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;\n            psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n            status = psa_get_key_attributes(pk->priv_id, &old_attributes);\n            if (status != PSA_SUCCESS) {\n                return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n            }\n            psa_key_type_t old_type = psa_get_key_type(&old_attributes);\n            switch (usage) {\n                case PSA_KEY_USAGE_SIGN_MESSAGE:\n                case PSA_KEY_USAGE_SIGN_HASH:\n                case PSA_KEY_USAGE_VERIFY_MESSAGE:\n                case PSA_KEY_USAGE_VERIFY_HASH:\n                    if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type) ||\n                          old_type == PSA_KEY_TYPE_RSA_KEY_PAIR)) {\n                        return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n                    }\n                    break;\n                case PSA_KEY_USAGE_DECRYPT:\n                case PSA_KEY_USAGE_ENCRYPT:\n                    if (old_type != PSA_KEY_TYPE_RSA_KEY_PAIR) {\n                        return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n                    }\n                    break;\n                case PSA_KEY_USAGE_DERIVE:\n                    if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type))) {\n                        return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n                    }\n                    break;\n                default:\n                    return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n            }\n            psa_key_type_t new_type = old_type;\n            /* Opaque keys are always key pairs, so we don't need a check\n             * on the input if the required usage is private. We just need\n             * to adjust the type correctly if the required usage is public. */\n            if (!want_private) {\n                new_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(new_type);\n            }\n            more_usage = psa_get_key_usage_flags(&old_attributes);\n            if ((usage & more_usage) == 0) {\n                return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n            }\n            psa_set_key_type(attributes, new_type);\n            psa_set_key_bits(attributes, psa_get_key_bits(&old_attributes));\n            psa_set_key_algorithm(attributes, psa_get_key_algorithm(&old_attributes));\n            break;\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        default:\n            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    psa_set_key_usage_flags(attributes, more_usage);\n    /* Key's enrollment is available only when an Mbed TLS implementation of PSA\n     * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined.\n     * Even though we don't officially support using other implementations of PSA\n     * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations\n     * separated. */\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n    psa_set_key_enrollment_algorithm(attributes, PSA_ALG_NONE);\n#endif\n\n    return 0;\n}\n\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) || defined(MBEDTLS_USE_PSA_CRYPTO)\nstatic psa_status_t export_import_into_psa(mbedtls_svc_key_id_t old_key_id,\n                                           const psa_key_attributes_t *attributes,\n                                           mbedtls_svc_key_id_t *new_key_id)\n{\n    unsigned char key_buffer[PSA_EXPORT_KEY_PAIR_MAX_SIZE];\n    size_t key_length = 0;\n    psa_status_t status = psa_export_key(old_key_id,\n                                         key_buffer, sizeof(key_buffer),\n                                         &key_length);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n    status = psa_import_key(attributes, key_buffer, key_length, new_key_id);\n    mbedtls_platform_zeroize(key_buffer, key_length);\n    return status;\n}\n\nstatic int copy_into_psa(mbedtls_svc_key_id_t old_key_id,\n                         const psa_key_attributes_t *attributes,\n                         mbedtls_svc_key_id_t *new_key_id)\n{\n    /* Normally, we prefer copying: it's more efficient and works even\n     * for non-exportable keys. */\n    psa_status_t status = psa_copy_key(old_key_id, attributes, new_key_id);\n    if (status == PSA_ERROR_NOT_PERMITTED /*missing COPY usage*/ ||\n        status == PSA_ERROR_INVALID_ARGUMENT /*incompatible policy*/) {\n        /* There are edge cases where copying won't work, but export+import\n         * might:\n         * - If the old key does not allow PSA_KEY_USAGE_COPY.\n         * - If the old key's usage does not allow what attributes wants.\n         *   Because the key was intended for use in the pk module, and may\n         *   have had a policy chosen solely for what pk needs rather than\n         *   based on a detailed understanding of PSA policies, we are a bit\n         *   more liberal than psa_copy_key() here.\n         */\n        /* Here we need to check that the types match, otherwise we risk\n         * importing nonsensical data. */\n        psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;\n        status = psa_get_key_attributes(old_key_id, &old_attributes);\n        if (status != PSA_SUCCESS) {\n            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n        }\n        psa_key_type_t old_type = psa_get_key_type(&old_attributes);\n        psa_reset_key_attributes(&old_attributes);\n        if (old_type != psa_get_key_type(attributes)) {\n            return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n        }\n        status = export_import_into_psa(old_key_id, attributes, new_key_id);\n    }\n    return PSA_PK_TO_MBEDTLS_ERR(status);\n}\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_USE_PSA_CRYPTO */\n\nstatic int import_pair_into_psa(const mbedtls_pk_context *pk,\n                                const psa_key_attributes_t *attributes,\n                                mbedtls_svc_key_id_t *key_id)\n{\n    switch (mbedtls_pk_get_type(pk)) {\n#if defined(MBEDTLS_RSA_C)\n        case MBEDTLS_PK_RSA:\n        {\n            if (psa_get_key_type(attributes) != PSA_KEY_TYPE_RSA_KEY_PAIR) {\n                return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n            }\n            unsigned char key_buffer[\n                PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)];\n            unsigned char *const key_end = key_buffer + sizeof(key_buffer);\n            unsigned char *key_data = key_end;\n            int ret = mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk),\n                                            key_buffer, &key_data);\n            if (ret < 0) {\n                return ret;\n            }\n            size_t key_length = key_end - key_data;\n            ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,\n                                                       key_data, key_length,\n                                                       key_id));\n            mbedtls_platform_zeroize(key_data, key_length);\n            return ret;\n        }\n#endif /* MBEDTLS_RSA_C */\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n        case MBEDTLS_PK_ECKEY:\n        case MBEDTLS_PK_ECKEY_DH:\n        case MBEDTLS_PK_ECDSA:\n        {\n            /* We need to check the curve family, otherwise the import could\n             * succeed with nonsensical data.\n             * We don't check the bit-size: it's optional in attributes,\n             * and if it's specified, psa_import_key() will know from the key\n             * data length and will check that the bit-size matches. */\n            psa_key_type_t to_type = psa_get_key_type(attributes);\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n            psa_ecc_family_t from_family = pk->ec_family;\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\n            const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);\n            size_t from_bits = 0;\n            psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id,\n                                                                    &from_bits);\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n            if (to_type != PSA_KEY_TYPE_ECC_KEY_PAIR(from_family)) {\n                return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n            }\n\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n            if (mbedtls_svc_key_id_is_null(pk->priv_id)) {\n                /* We have a public key and want a key pair. */\n                return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n            }\n            return copy_into_psa(pk->priv_id, attributes, key_id);\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\n            if (ec->d.n == 0) {\n                /* Private key not set. Assume the input is a public key only.\n                 * (The other possibility is that it's an incomplete object\n                 * where the group is set but neither the public key nor\n                 * the private key. This is not possible through ecp.h\n                 * functions, so we don't bother reporting a more suitable\n                 * error in that case.) */\n                return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n            }\n            unsigned char key_buffer[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];\n            size_t key_length = 0;\n            int ret = mbedtls_ecp_write_key_ext(ec, &key_length,\n                                                key_buffer, sizeof(key_buffer));\n            if (ret < 0) {\n                return ret;\n            }\n            ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,\n                                                       key_buffer, key_length,\n                                                       key_id));\n            mbedtls_platform_zeroize(key_buffer, key_length);\n            return ret;\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n        }\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        case MBEDTLS_PK_OPAQUE:\n            return copy_into_psa(pk->priv_id, attributes, key_id);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        default:\n            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n}\n\nstatic int import_public_into_psa(const mbedtls_pk_context *pk,\n                                  const psa_key_attributes_t *attributes,\n                                  mbedtls_svc_key_id_t *key_id)\n{\n    psa_key_type_t psa_type = psa_get_key_type(attributes);\n\n#if defined(MBEDTLS_RSA_C) ||                                           \\\n    (defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)) || \\\n    defined(MBEDTLS_USE_PSA_CRYPTO)\n    unsigned char key_buffer[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];\n#endif\n    unsigned char *key_data = NULL;\n    size_t key_length = 0;\n\n    switch (mbedtls_pk_get_type(pk)) {\n#if defined(MBEDTLS_RSA_C)\n        case MBEDTLS_PK_RSA:\n        {\n            if (psa_type != PSA_KEY_TYPE_RSA_PUBLIC_KEY) {\n                return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n            }\n            unsigned char *const key_end = key_buffer + sizeof(key_buffer);\n            key_data = key_end;\n            int ret = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*pk),\n                                               key_buffer, &key_data);\n            if (ret < 0) {\n                return ret;\n            }\n            key_length = (size_t) ret;\n            break;\n        }\n#endif /*MBEDTLS_RSA_C */\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n        case MBEDTLS_PK_ECKEY:\n        case MBEDTLS_PK_ECKEY_DH:\n        case MBEDTLS_PK_ECDSA:\n        {\n            /* We need to check the curve family, otherwise the import could\n             * succeed with nonsensical data.\n             * We don't check the bit-size: it's optional in attributes,\n             * and if it's specified, psa_import_key() will know from the key\n             * data length and will check that the bit-size matches. */\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n            if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family)) {\n                return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n            }\n            key_data = (unsigned char *) pk->pub_raw;\n            key_length = pk->pub_raw_len;\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\n            const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);\n            size_t from_bits = 0;\n            psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id,\n                                                                    &from_bits);\n            if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(from_family)) {\n                return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n            }\n            int ret = mbedtls_ecp_write_public_key(\n                ec, MBEDTLS_ECP_PF_UNCOMPRESSED,\n                &key_length, key_buffer, sizeof(key_buffer));\n            if (ret < 0) {\n                return ret;\n            }\n            key_data = key_buffer;\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n            break;\n        }\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        case MBEDTLS_PK_OPAQUE:\n        {\n            psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;\n            psa_status_t status =\n                psa_get_key_attributes(pk->priv_id, &old_attributes);\n            if (status != PSA_SUCCESS) {\n                return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n            }\n            psa_key_type_t old_type = psa_get_key_type(&old_attributes);\n            psa_reset_key_attributes(&old_attributes);\n            if (psa_type != PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(old_type)) {\n                return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n            }\n            status = psa_export_public_key(pk->priv_id,\n                                           key_buffer, sizeof(key_buffer),\n                                           &key_length);\n            if (status != PSA_SUCCESS) {\n                return PSA_PK_TO_MBEDTLS_ERR(status);\n            }\n            key_data = key_buffer;\n            break;\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        default:\n            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    return PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,\n                                                key_data, key_length,\n                                                key_id));\n}\n\nint mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk,\n                               const psa_key_attributes_t *attributes,\n                               mbedtls_svc_key_id_t *key_id)\n{\n    /* Set the output immediately so that it won't contain garbage even\n     * if we error out before calling psa_import_key(). */\n    *key_id = MBEDTLS_SVC_KEY_ID_INIT;\n\n#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)\n    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA_ALT) {\n        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n    }\n#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */\n\n    int want_public = PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(attributes));\n    if (want_public) {\n        return import_public_into_psa(pk, attributes, key_id);\n    } else {\n        return import_pair_into_psa(pk, attributes, key_id);\n    }\n}\n\nstatic int copy_from_psa(mbedtls_svc_key_id_t key_id,\n                         mbedtls_pk_context *pk,\n                         int public_only)\n{\n    psa_status_t status;\n    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;\n    psa_key_type_t key_type;\n    size_t key_bits;\n    /* Use a buffer size large enough to contain either a key pair or public key. */\n    unsigned char exp_key[PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE];\n    size_t exp_key_len;\n    int ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n\n    if (pk == NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    status = psa_get_key_attributes(key_id, &key_attr);\n    if (status != PSA_SUCCESS) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if (public_only) {\n        status = psa_export_public_key(key_id, exp_key, sizeof(exp_key), &exp_key_len);\n    } else {\n        status = psa_export_key(key_id, exp_key, sizeof(exp_key), &exp_key_len);\n    }\n    if (status != PSA_SUCCESS) {\n        ret = PSA_PK_TO_MBEDTLS_ERR(status);\n        goto exit;\n    }\n\n    key_type = psa_get_key_type(&key_attr);\n    if (public_only) {\n        key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type);\n    }\n    key_bits = psa_get_key_bits(&key_attr);\n\n#if defined(MBEDTLS_RSA_C)\n    if ((key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) ||\n        (key_type == PSA_KEY_TYPE_RSA_PUBLIC_KEY)) {\n\n        ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));\n        if (ret != 0) {\n            goto exit;\n        }\n\n        if (key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) {\n            ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), exp_key, exp_key_len);\n        } else {\n            ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), exp_key, exp_key_len);\n        }\n        if (ret != 0) {\n            goto exit;\n        }\n\n        psa_algorithm_t alg_type = psa_get_key_algorithm(&key_attr);\n        mbedtls_md_type_t md_type = MBEDTLS_MD_NONE;\n        if (PSA_ALG_GET_HASH(alg_type) != PSA_ALG_ANY_HASH) {\n            md_type = mbedtls_md_type_from_psa_alg(alg_type);\n        }\n\n        if (PSA_ALG_IS_RSA_OAEP(alg_type) || PSA_ALG_IS_RSA_PSS(alg_type)) {\n            ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V21, md_type);\n        } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg_type) ||\n                   alg_type == PSA_ALG_RSA_PKCS1V15_CRYPT) {\n            ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V15, md_type);\n        }\n        if (ret != 0) {\n            goto exit;\n        }\n    } else\n#endif /* MBEDTLS_RSA_C */\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ||\n        PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type)) {\n        mbedtls_ecp_group_id grp_id;\n\n        ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));\n        if (ret != 0) {\n            goto exit;\n        }\n\n        grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(key_type), key_bits);\n        ret = mbedtls_pk_ecc_set_group(pk, grp_id);\n        if (ret != 0) {\n            goto exit;\n        }\n\n        if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) {\n            ret = mbedtls_pk_ecc_set_key(pk, exp_key, exp_key_len);\n            if (ret != 0) {\n                goto exit;\n            }\n            ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, exp_key, exp_key_len,\n                                                     mbedtls_psa_get_random,\n                                                     MBEDTLS_PSA_RANDOM_STATE);\n        } else {\n            ret = mbedtls_pk_ecc_set_pubkey(pk, exp_key, exp_key_len);\n        }\n        if (ret != 0) {\n            goto exit;\n        }\n    } else\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n    {\n        (void) key_bits;\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\nexit:\n    psa_reset_key_attributes(&key_attr);\n    mbedtls_platform_zeroize(exp_key, sizeof(exp_key));\n\n    return ret;\n}\n\nint mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id,\n                             mbedtls_pk_context *pk)\n{\n    return copy_from_psa(key_id, pk, 0);\n}\n\nint mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id,\n                                    mbedtls_pk_context *pk)\n{\n    return copy_from_psa(key_id, pk, 1);\n}\n#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */\n\n/*\n * Helper for mbedtls_pk_sign and mbedtls_pk_verify\n */\nstatic inline int pk_hashlen_helper(mbedtls_md_type_t md_alg, size_t *hash_len)\n{\n    if (*hash_len != 0) {\n        return 0;\n    }\n\n    *hash_len = mbedtls_md_get_size_from_type(md_alg);\n\n    if (*hash_len == 0) {\n        return -1;\n    }\n\n    return 0;\n}\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n/*\n * Helper to set up a restart context if needed\n */\nstatic int pk_restart_setup(mbedtls_pk_restart_ctx *ctx,\n                            const mbedtls_pk_info_t *info)\n{\n    /* Don't do anything if already set up or invalid */\n    if (ctx == NULL || ctx->pk_info != NULL) {\n        return 0;\n    }\n\n    /* Should never happen when we're called */\n    if (info->rs_alloc_func == NULL || info->rs_free_func == NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if ((ctx->rs_ctx = info->rs_alloc_func()) == NULL) {\n        return MBEDTLS_ERR_PK_ALLOC_FAILED;\n    }\n\n    ctx->pk_info = info;\n\n    return 0;\n}\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n\n/*\n * Verify a signature (restartable)\n */\nint mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx,\n                                  mbedtls_md_type_t md_alg,\n                                  const unsigned char *hash, size_t hash_len,\n                                  const unsigned char *sig, size_t sig_len,\n                                  mbedtls_pk_restart_ctx *rs_ctx)\n{\n    if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if (ctx->pk_info == NULL ||\n        pk_hashlen_helper(md_alg, &hash_len) != 0) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    /* optimization: use non-restartable version if restart disabled */\n    if (rs_ctx != NULL &&\n        mbedtls_ecp_restart_is_enabled() &&\n        ctx->pk_info->verify_rs_func != NULL) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n        if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) {\n            return ret;\n        }\n\n        ret = ctx->pk_info->verify_rs_func(ctx,\n                                           md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx);\n\n        if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) {\n            mbedtls_pk_restart_free(rs_ctx);\n        }\n\n        return ret;\n    }\n#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n    (void) rs_ctx;\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n\n    if (ctx->pk_info->verify_func == NULL) {\n        return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n    }\n\n    return ctx->pk_info->verify_func(ctx, md_alg, hash, hash_len,\n                                     sig, sig_len);\n}\n\n/*\n * Verify a signature\n */\nint mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,\n                      const unsigned char *hash, size_t hash_len,\n                      const unsigned char *sig, size_t sig_len)\n{\n    return mbedtls_pk_verify_restartable(ctx, md_alg, hash, hash_len,\n                                         sig, sig_len, NULL);\n}\n\n/*\n * Verify a signature with options\n */\nint mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options,\n                          mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,\n                          const unsigned char *hash, size_t hash_len,\n                          const unsigned char *sig, size_t sig_len)\n{\n    if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if (ctx->pk_info == NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if (!mbedtls_pk_can_do(ctx, type)) {\n        return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n    }\n\n    if (type != MBEDTLS_PK_RSASSA_PSS) {\n        /* General case: no options */\n        if (options != NULL) {\n            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n        }\n\n        return mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len);\n    }\n\n    /* Ensure the PK context is of the right type otherwise mbedtls_pk_rsa()\n     * below would return a NULL pointer. */\n    if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_RSA) {\n        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n    }\n\n#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const mbedtls_pk_rsassa_pss_options *pss_opts;\n\n#if SIZE_MAX > UINT_MAX\n    if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n#endif\n\n    if (options == NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    pss_opts = (const mbedtls_pk_rsassa_pss_options *) options;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (pss_opts->mgf1_hash_id == md_alg) {\n        unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];\n        unsigned char *p;\n        int key_len;\n        size_t signature_length;\n        psa_status_t status = PSA_ERROR_DATA_CORRUPT;\n        psa_status_t destruction_status = PSA_ERROR_DATA_CORRUPT;\n\n        psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);\n        mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;\n        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n        psa_algorithm_t psa_sig_alg = PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg);\n        p = buf + sizeof(buf);\n        key_len = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*ctx), buf, &p);\n\n        if (key_len < 0) {\n            return key_len;\n        }\n\n        psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);\n        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);\n        psa_set_key_algorithm(&attributes, psa_sig_alg);\n\n        status = psa_import_key(&attributes,\n                                buf + sizeof(buf) - key_len, key_len,\n                                &key_id);\n        if (status != PSA_SUCCESS) {\n            psa_destroy_key(key_id);\n            return PSA_PK_TO_MBEDTLS_ERR(status);\n        }\n\n        /* This function requires returning MBEDTLS_ERR_PK_SIG_LEN_MISMATCH\n         * on a valid signature with trailing data in a buffer, but\n         * mbedtls_psa_rsa_verify_hash requires the sig_len to be exact,\n         * so for this reason the passed sig_len is overwritten. Smaller\n         * signature lengths should not be accepted for verification. */\n        signature_length = sig_len > mbedtls_pk_get_len(ctx) ?\n                           mbedtls_pk_get_len(ctx) : sig_len;\n        status = psa_verify_hash(key_id, psa_sig_alg, hash,\n                                 hash_len, sig, signature_length);\n        destruction_status = psa_destroy_key(key_id);\n\n        if (status == PSA_SUCCESS && sig_len > mbedtls_pk_get_len(ctx)) {\n            return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;\n        }\n\n        if (status == PSA_SUCCESS) {\n            status = destruction_status;\n        }\n\n        return PSA_PK_RSA_TO_MBEDTLS_ERR(status);\n    } else\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    {\n        if (sig_len < mbedtls_pk_get_len(ctx)) {\n            return MBEDTLS_ERR_RSA_VERIFY_FAILED;\n        }\n\n        ret = mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_pk_rsa(*ctx),\n                                                md_alg, (unsigned int) hash_len, hash,\n                                                pss_opts->mgf1_hash_id,\n                                                pss_opts->expected_salt_len,\n                                                sig);\n        if (ret != 0) {\n            return ret;\n        }\n\n        if (sig_len > mbedtls_pk_get_len(ctx)) {\n            return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;\n        }\n\n        return 0;\n    }\n#else\n    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */\n}\n\n/*\n * Make a signature (restartable)\n */\nint mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx,\n                                mbedtls_md_type_t md_alg,\n                                const unsigned char *hash, size_t hash_len,\n                                unsigned char *sig, size_t sig_size, size_t *sig_len,\n                                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,\n                                mbedtls_pk_restart_ctx *rs_ctx)\n{\n    if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if (ctx == NULL) return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    if (ctx->pk_info == NULL || pk_hashlen_helper(md_alg, &hash_len) != 0) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    /* optimization: use non-restartable version if restart disabled */\n    if (rs_ctx != NULL &&\n        mbedtls_ecp_restart_is_enabled() &&\n        ctx->pk_info->sign_rs_func != NULL) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n        if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) {\n            return ret;\n        }\n\n        ret = ctx->pk_info->sign_rs_func(ctx, md_alg,\n                                         hash, hash_len,\n                                         sig, sig_size, sig_len,\n                                         f_rng, p_rng, rs_ctx->rs_ctx);\n\n        if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) {\n            mbedtls_pk_restart_free(rs_ctx);\n        }\n\n        return ret;\n    }\n#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n    (void) rs_ctx;\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n\n    if (ctx->pk_info->sign_func == NULL) {\n        return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n    }\n\n    return ctx->pk_info->sign_func(ctx, md_alg,\n                                   hash, hash_len,\n                                   sig, sig_size, sig_len,\n                                   f_rng, p_rng);\n}\n\n/*\n * Make a signature\n */\nint mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,\n                    const unsigned char *hash, size_t hash_len,\n                    unsigned char *sig, size_t sig_size, size_t *sig_len,\n                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    return mbedtls_pk_sign_restartable(ctx, md_alg, hash, hash_len,\n                                       sig, sig_size, sig_len,\n                                       f_rng, p_rng, NULL);\n}\n\n/*\n * Make a signature given a signature type.\n */\nint mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type,\n                        mbedtls_pk_context *ctx,\n                        mbedtls_md_type_t md_alg,\n                        const unsigned char *hash, size_t hash_len,\n                        unsigned char *sig, size_t sig_size, size_t *sig_len,\n                        int (*f_rng)(void *, unsigned char *, size_t),\n                        void *p_rng)\n{\n    if (ctx->pk_info == NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if (!mbedtls_pk_can_do(ctx, pk_type)) {\n        return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n    }\n\n    if (pk_type != MBEDTLS_PK_RSASSA_PSS) {\n        return mbedtls_pk_sign(ctx, md_alg, hash, hash_len,\n                               sig, sig_size, sig_len, f_rng, p_rng);\n    }\n\n#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    const psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);\n    if (psa_md_alg == 0) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) {\n        psa_status_t status;\n\n        /* PSA_ALG_RSA_PSS() behaves the same as PSA_ALG_RSA_PSS_ANY_SALT() when\n         * performing a signature, but they are encoded differently. Instead of\n         * extracting the proper one from the wrapped key policy, just try both. */\n        status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS(psa_md_alg),\n                               hash, hash_len,\n                               sig, sig_size, sig_len);\n        if (status == PSA_ERROR_NOT_PERMITTED) {\n            status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg),\n                                   hash, hash_len,\n                                   sig, sig_size, sig_len);\n        }\n        return PSA_PK_RSA_TO_MBEDTLS_ERR(status);\n    }\n\n    return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PSS(psa_md_alg),\n                                       ctx->pk_ctx, hash, hash_len,\n                                       sig, sig_size, sig_len);\n#else /* MBEDTLS_USE_PSA_CRYPTO */\n\n    if (sig_size < mbedtls_pk_get_len(ctx)) {\n        return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;\n    }\n\n    if (pk_hashlen_helper(md_alg, &hash_len) != 0) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    mbedtls_rsa_context *const rsa_ctx = mbedtls_pk_rsa(*ctx);\n\n    const int ret = mbedtls_rsa_rsassa_pss_sign_no_mode_check(rsa_ctx, f_rng, p_rng, md_alg,\n                                                              (unsigned int) hash_len, hash, sig);\n    if (ret == 0) {\n        *sig_len = rsa_ctx->len;\n    }\n    return ret;\n\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#else\n    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */\n}\n\n/*\n * Decrypt message\n */\nint mbedtls_pk_decrypt(mbedtls_pk_context *ctx,\n                       const unsigned char *input, size_t ilen,\n                       unsigned char *output, size_t *olen, size_t osize,\n                       int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    if (ctx->pk_info == NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if (ctx->pk_info->decrypt_func == NULL) {\n        return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n    }\n\n    return ctx->pk_info->decrypt_func(ctx, input, ilen,\n                                      output, olen, osize, f_rng, p_rng);\n}\n\n/*\n * Encrypt message\n */\nint mbedtls_pk_encrypt(mbedtls_pk_context *ctx,\n                       const unsigned char *input, size_t ilen,\n                       unsigned char *output, size_t *olen, size_t osize,\n                       int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    if (ctx->pk_info == NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if (ctx->pk_info->encrypt_func == NULL) {\n        return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n    }\n\n    return ctx->pk_info->encrypt_func(ctx, input, ilen,\n                                      output, olen, osize, f_rng, p_rng);\n}\n\n/*\n * Check public-private key pair\n */\nint mbedtls_pk_check_pair(const mbedtls_pk_context *pub,\n                          const mbedtls_pk_context *prv,\n                          int (*f_rng)(void *, unsigned char *, size_t),\n                          void *p_rng)\n{\n    if (pub->pk_info == NULL ||\n        prv->pk_info == NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if (f_rng == NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if (prv->pk_info->check_pair_func == NULL) {\n        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n    }\n\n    if (prv->pk_info->type == MBEDTLS_PK_RSA_ALT) {\n        if (pub->pk_info->type != MBEDTLS_PK_RSA) {\n            return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n        }\n    } else {\n        if ((prv->pk_info->type != MBEDTLS_PK_OPAQUE) &&\n            (pub->pk_info != prv->pk_info)) {\n            return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n        }\n    }\n\n    return prv->pk_info->check_pair_func((mbedtls_pk_context *) pub,\n                                         (mbedtls_pk_context *) prv,\n                                         f_rng, p_rng);\n}\n\n/*\n * Get key size in bits\n */\nsize_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx)\n{\n    /* For backward compatibility, accept NULL or a context that\n     * isn't set up yet, and return a fake value that should be safe. */\n    if (ctx == NULL || ctx->pk_info == NULL) {\n        return 0;\n    }\n\n    return ctx->pk_info->get_bitlen((mbedtls_pk_context *) ctx);\n}\n\n/*\n * Export debug information\n */\nint mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items)\n{\n    if (ctx->pk_info == NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if (ctx->pk_info->debug_func == NULL) {\n        return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n    }\n\n    ctx->pk_info->debug_func((mbedtls_pk_context *) ctx, items);\n    return 0;\n}\n\n/*\n * Access the PK type name\n */\nconst char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx)\n{\n    if (ctx == NULL || ctx->pk_info == NULL) {\n        return \"invalid PK\";\n    }\n\n    return ctx->pk_info->name;\n}\n\n/*\n * Access the PK type\n */\nmbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx)\n{\n    if (ctx == NULL || ctx->pk_info == NULL) {\n        return MBEDTLS_PK_NONE;\n    }\n\n    return ctx->pk_info->type;\n}\n\n#endif /* MBEDTLS_PK_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/pk_ecc.c",
    "content": "/*\n *  ECC setters for PK.\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#include \"mbedtls/pk.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/ecp.h\"\n#include \"pk_internal.h\"\n\n#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n\nint mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id)\n{\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n    size_t ec_bits;\n    psa_ecc_family_t ec_family = mbedtls_ecc_group_to_psa(grp_id, &ec_bits);\n\n    /* group may already be initialized; if so, make sure IDs match */\n    if ((pk->ec_family != 0 && pk->ec_family != ec_family) ||\n        (pk->ec_bits != 0 && pk->ec_bits != ec_bits)) {\n        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;\n    }\n\n    /* set group */\n    pk->ec_family = ec_family;\n    pk->ec_bits = ec_bits;\n\n    return 0;\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\n    mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk);\n\n    /* grp may already be initialized; if so, make sure IDs match */\n    if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE &&\n        mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) {\n        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;\n    }\n\n    /* set group */\n    return mbedtls_ecp_group_load(&(ecp->grp), grp_id);\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n}\n\nint mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len)\n{\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    psa_key_usage_t flags;\n    psa_status_t status;\n\n    psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family));\n    if (pk->ec_family == PSA_ECC_FAMILY_MONTGOMERY) {\n        /* Do not set algorithm here because Montgomery keys cannot do ECDSA and\n         * the PK module cannot do ECDH. When the key will be used in TLS for\n         * ECDH, it will be exported and then re-imported with proper flags\n         * and algorithm. */\n        flags = PSA_KEY_USAGE_EXPORT;\n    } else {\n        psa_set_key_algorithm(&attributes,\n                              MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(PSA_ALG_ANY_HASH));\n        flags = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE |\n                PSA_KEY_USAGE_EXPORT;\n    }\n    psa_set_key_usage_flags(&attributes, flags);\n\n    status = psa_import_key(&attributes, key, key_len, &pk->priv_id);\n    return psa_pk_status_to_mbedtls(status);\n\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\n\n    mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk);\n    int ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, key_len);\n    if (ret != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n    return 0;\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n}\n\nint mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk,\n                                       const unsigned char *prv, size_t prv_len,\n                                       int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n\n    (void) f_rng;\n    (void) p_rng;\n    (void) prv;\n    (void) prv_len;\n    psa_status_t status;\n\n    status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw),\n                                   &pk->pub_raw_len);\n    return psa_pk_status_to_mbedtls(status);\n\n#elif defined(MBEDTLS_USE_PSA_CRYPTO) /* && !MBEDTLS_PK_USE_PSA_EC_DATA */\n\n    (void) f_rng;\n    (void) p_rng;\n    psa_status_t status;\n\n    mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;\n    size_t curve_bits;\n    psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits);\n\n    /* Import private key into PSA, from serialized input */\n    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;\n    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;\n    psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));\n    psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT);\n    status = psa_import_key(&key_attr, prv, prv_len, &key_id);\n    if (status != PSA_SUCCESS) {\n        return psa_pk_status_to_mbedtls(status);\n    }\n\n    /* Export public key from PSA */\n    unsigned char pub[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];\n    size_t pub_len;\n    status = psa_export_public_key(key_id, pub, sizeof(pub), &pub_len);\n    psa_status_t destruction_status = psa_destroy_key(key_id);\n    if (status != PSA_SUCCESS) {\n        return psa_pk_status_to_mbedtls(status);\n    } else if (destruction_status != PSA_SUCCESS) {\n        return psa_pk_status_to_mbedtls(destruction_status);\n    }\n\n    /* Load serialized public key into ecp_keypair structure */\n    return mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, pub, pub_len);\n\n#else /* MBEDTLS_USE_PSA_CRYPTO */\n\n    (void) prv;\n    (void) prv_len;\n\n    mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;\n    return mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng);\n\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n}\n\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n/*\n * Set the public key: fallback using ECP_LIGHT in the USE_PSA_EC_DATA case.\n *\n * Normally, when MBEDTLS_PK_USE_PSA_EC_DATA is enabled, we only use PSA\n * functions to handle keys. However, currently psa_import_key() does not\n * support compressed points. In case that support was explicitly requested,\n * this fallback uses ECP functions to get the job done. This is the reason\n * why MBEDTLS_PK_PARSE_EC_COMPRESSED auto-enables MBEDTLS_ECP_LIGHT.\n *\n * [in/out] pk: in: must have the group set, see mbedtls_pk_ecc_set_group().\n *              out: will have the public key set.\n * [in] pub, pub_len: the public key as an ECPoint,\n *                    in any format supported by ECP.\n *\n * Return:\n * - 0 on success;\n * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid\n *   but not supported;\n * - another error code otherwise.\n */\nstatic int pk_ecc_set_pubkey_psa_ecp_fallback(mbedtls_pk_context *pk,\n                                              const unsigned char *pub,\n                                              size_t pub_len)\n{\n#if !defined(MBEDTLS_PK_PARSE_EC_COMPRESSED)\n    (void) pk;\n    (void) pub;\n    (void) pub_len;\n    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n#else /* MBEDTLS_PK_PARSE_EC_COMPRESSED */\n    mbedtls_ecp_keypair ecp_key;\n    mbedtls_ecp_group_id ecp_group_id;\n    int ret;\n\n    ecp_group_id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits);\n\n    mbedtls_ecp_keypair_init(&ecp_key);\n    ret = mbedtls_ecp_group_load(&(ecp_key.grp), ecp_group_id);\n    if (ret != 0) {\n        goto exit;\n    }\n    ret = mbedtls_ecp_point_read_binary(&(ecp_key.grp), &ecp_key.Q,\n                                        pub, pub_len);\n    if (ret != 0) {\n        goto exit;\n    }\n    ret = mbedtls_ecp_point_write_binary(&(ecp_key.grp), &ecp_key.Q,\n                                         MBEDTLS_ECP_PF_UNCOMPRESSED,\n                                         &pk->pub_raw_len, pk->pub_raw,\n                                         sizeof(pk->pub_raw));\n\nexit:\n    mbedtls_ecp_keypair_free(&ecp_key);\n    return ret;\n#endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */\n}\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n\nint mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len)\n{\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n\n    /* Load the key */\n    if (!PSA_ECC_FAMILY_IS_WEIERSTRASS(pk->ec_family) || *pub == 0x04) {\n        /* Format directly supported by PSA:\n         * - non-Weierstrass curves that only have one format;\n         * - uncompressed format for Weierstrass curves. */\n        if (pub_len > sizeof(pk->pub_raw)) {\n            return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;\n        }\n        memcpy(pk->pub_raw, pub, pub_len);\n        pk->pub_raw_len = pub_len;\n    } else {\n        /* Other format, try the fallback */\n        int ret = pk_ecc_set_pubkey_psa_ecp_fallback(pk, pub, pub_len);\n        if (ret != 0) {\n            return ret;\n        }\n    }\n\n    /* Validate the key by trying to import it */\n    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;\n    psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT;\n\n    psa_set_key_usage_flags(&key_attrs, 0);\n    psa_set_key_type(&key_attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family));\n    psa_set_key_bits(&key_attrs, pk->ec_bits);\n\n    if ((psa_import_key(&key_attrs, pk->pub_raw, pk->pub_raw_len,\n                        &key_id) != PSA_SUCCESS) ||\n        (psa_destroy_key(key_id) != PSA_SUCCESS)) {\n        return MBEDTLS_ERR_PK_INVALID_PUBKEY;\n    }\n\n    return 0;\n\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\n\n    int ret;\n    mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx;\n    ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q, pub, pub_len);\n    if (ret != 0) {\n        return ret;\n    }\n    return mbedtls_ecp_check_pubkey(&ec_key->grp, &ec_key->Q);\n\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n}\n\n#endif /* MBEDTLS_PK_C && MBEDTLS_PK_HAVE_ECC_KEYS */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/pk_internal.h",
    "content": "/**\n * \\file pk_internal.h\n *\n * \\brief Public Key abstraction layer: internal (i.e. library only) functions\n *        and definitions.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_PK_INTERNAL_H\n#define MBEDTLS_PK_INTERNAL_H\n\n#include \"mbedtls/pk.h\"\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n#include \"mbedtls/ecp.h\"\n#endif\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)\n#include \"psa/crypto.h\"\n\n#include \"psa_util_internal.h\"\n#define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status)\n#define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,     \\\n                                                                  psa_to_pk_rsa_errors,            \\\n                                                                  psa_pk_status_to_mbedtls)\n#define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \\\n                                                                    psa_to_pk_ecdsa_errors,        \\\n                                                                    psa_pk_status_to_mbedtls)\n#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */\n\n/* Headers/footers for PEM files */\n#define PEM_BEGIN_PUBLIC_KEY    \"-----BEGIN PUBLIC KEY-----\"\n#define PEM_END_PUBLIC_KEY      \"-----END PUBLIC KEY-----\"\n#define PEM_BEGIN_PRIVATE_KEY_RSA   \"-----BEGIN RSA PRIVATE KEY-----\"\n#define PEM_END_PRIVATE_KEY_RSA     \"-----END RSA PRIVATE KEY-----\"\n#define PEM_BEGIN_PUBLIC_KEY_RSA     \"-----BEGIN RSA PUBLIC KEY-----\"\n#define PEM_END_PUBLIC_KEY_RSA     \"-----END RSA PUBLIC KEY-----\"\n#define PEM_BEGIN_PRIVATE_KEY_EC    \"-----BEGIN EC PRIVATE KEY-----\"\n#define PEM_END_PRIVATE_KEY_EC      \"-----END EC PRIVATE KEY-----\"\n#define PEM_BEGIN_PRIVATE_KEY_PKCS8 \"-----BEGIN PRIVATE KEY-----\"\n#define PEM_END_PRIVATE_KEY_PKCS8   \"-----END PRIVATE KEY-----\"\n#define PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8 \"-----BEGIN ENCRYPTED PRIVATE KEY-----\"\n#define PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8   \"-----END ENCRYPTED PRIVATE KEY-----\"\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n/**\n * Public function mbedtls_pk_ec() can be used to get direct access to the\n * wrapped ecp_keypair structure pointed to the pk_ctx. However this is not\n * ideal because it bypasses the PK module on the control of its internal\n * structure (pk_context) fields.\n * For backward compatibility we keep mbedtls_pk_ec() when ECP_C is defined, but\n * we provide 2 very similar functions when only ECP_LIGHT is enabled and not\n * ECP_C.\n * These variants embed the \"ro\" or \"rw\" keywords in their name to make the\n * usage of the returned pointer explicit. Of course the returned value is\n * const or non-const accordingly.\n */\nstatic inline const mbedtls_ecp_keypair *mbedtls_pk_ec_ro(const mbedtls_pk_context pk)\n{\n    switch (mbedtls_pk_get_type(&pk)) {\n        case MBEDTLS_PK_ECKEY:\n        case MBEDTLS_PK_ECKEY_DH:\n        case MBEDTLS_PK_ECDSA:\n            return (const mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx);\n        default:\n            return NULL;\n    }\n}\n\nstatic inline mbedtls_ecp_keypair *mbedtls_pk_ec_rw(const mbedtls_pk_context pk)\n{\n    switch (mbedtls_pk_get_type(&pk)) {\n        case MBEDTLS_PK_ECKEY:\n        case MBEDTLS_PK_ECKEY_DH:\n        case MBEDTLS_PK_ECDSA:\n            return (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx);\n        default:\n            return NULL;\n    }\n}\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_PK_USE_PSA_EC_DATA */\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\nstatic inline mbedtls_ecp_group_id mbedtls_pk_get_ec_group_id(const mbedtls_pk_context *pk)\n{\n    mbedtls_ecp_group_id id;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {\n        psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT;\n        psa_key_type_t opaque_key_type;\n        psa_ecc_family_t curve;\n\n        if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) {\n            return MBEDTLS_ECP_DP_NONE;\n        }\n        opaque_key_type = psa_get_key_type(&opaque_attrs);\n        curve = PSA_KEY_TYPE_ECC_GET_FAMILY(opaque_key_type);\n        id = mbedtls_ecc_group_from_psa(curve, psa_get_key_bits(&opaque_attrs));\n        psa_reset_key_attributes(&opaque_attrs);\n    } else\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    {\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n        id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits);\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\n        id = mbedtls_pk_ec_ro(*pk)->grp.id;\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n    }\n\n    return id;\n}\n\n/* Helper for Montgomery curves */\n#if defined(MBEDTLS_ECP_HAVE_CURVE25519) || defined(MBEDTLS_ECP_HAVE_CURVE448)\n#define MBEDTLS_PK_HAVE_RFC8410_CURVES\n#endif /* MBEDTLS_ECP_HAVE_CURVE25519 || MBEDTLS_ECP_DP_CURVE448 */\n\n#define MBEDTLS_PK_IS_RFC8410_GROUP_ID(id)  \\\n    ((id == MBEDTLS_ECP_DP_CURVE25519) || (id == MBEDTLS_ECP_DP_CURVE448))\n\nstatic inline int mbedtls_pk_is_rfc8410(const mbedtls_pk_context *pk)\n{\n    mbedtls_ecp_group_id id = mbedtls_pk_get_ec_group_id(pk);\n\n    return MBEDTLS_PK_IS_RFC8410_GROUP_ID(id);\n}\n\n/*\n * Set the group used by this key.\n *\n * [in/out] pk: in: must have been pk_setup() to an ECC type\n *              out: will have group (curve) information set\n * [in] grp_in: a supported group ID (not NONE)\n */\nint mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id);\n\n/*\n * Set the private key material\n *\n * [in/out] pk: in: must have the group set already, see mbedtls_pk_ecc_set_group().\n *              out: will have the private key set.\n * [in] key, key_len: the raw private key (no ASN.1 wrapping).\n */\nint mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len);\n\n/*\n * Set the public key.\n *\n * [in/out] pk: in: must have its group set, see mbedtls_pk_ecc_set_group().\n *              out: will have the public key set.\n * [in] pub, pub_len: the raw public key (an ECPoint).\n *\n * Return:\n * - 0 on success;\n * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid\n *   but not supported;\n * - another error code otherwise.\n */\nint mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len);\n\n/*\n * Derive a public key from its private counterpart.\n * Computationally intensive, only use when public key is not available.\n *\n * [in/out] pk: in: must have the private key set, see mbedtls_pk_ecc_set_key().\n *              out: will have the public key set.\n * [in] prv, prv_len: the raw private key (see note below).\n * [in] f_rng, p_rng: RNG function and context.\n *\n * Note: the private key information is always available from pk,\n * however for convenience the serialized version is also passed,\n * as it's available at each calling site, and useful in some configs\n * (as otherwise we would have to re-serialize it from the pk context).\n *\n * There are three implementations of this function:\n * 1. MBEDTLS_PK_USE_PSA_EC_DATA,\n * 2. MBEDTLS_USE_PSA_CRYPTO but not MBEDTLS_PK_USE_PSA_EC_DATA,\n * 3. not MBEDTLS_USE_PSA_CRYPTO.\n */\nint mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk,\n                                       const unsigned char *prv, size_t prv_len,\n                                       int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n/* Helper for (deterministic) ECDSA */\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC)\n#define MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET  PSA_ALG_DETERMINISTIC_ECDSA\n#else\n#define MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET  PSA_ALG_ECDSA\n#endif\n\n#if defined(MBEDTLS_TEST_HOOKS)\nMBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der(\n    mbedtls_pk_context *pk,\n    unsigned char *key, size_t keylen,\n    const unsigned char *pwd, size_t pwdlen,\n    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);\n#endif\n\n#if defined(MBEDTLS_FS_IO)\nint mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n);\n#endif\n\n#endif /* MBEDTLS_PK_INTERNAL_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/pk_wrap.c",
    "content": "/*\n *  Public Key abstraction layer: wrapper functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#include \"mbedtls/platform_util.h\"\n\n#if defined(MBEDTLS_PK_C)\n#include \"pk_wrap.h\"\n#include \"pk_internal.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/psa_util.h\"\n\n/* Even if RSA not activated, for the sake of RSA-alt */\n#include \"mbedtls/rsa.h\"\n\n#if defined(MBEDTLS_ECP_C)\n#include \"mbedtls/ecp.h\"\n#endif\n\n#if defined(MBEDTLS_ECDSA_C)\n#include \"mbedtls/ecdsa.h\"\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"psa_util_internal.h\"\n#include \"psa/crypto.h\"\n#include \"mbedtls/psa_util.h\"\n\n#if defined(MBEDTLS_RSA_C)\n#include \"pkwrite.h\"\n#include \"rsa_internal.h\"\n#endif\n\n#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)\n#include \"mbedtls/asn1write.h\"\n#include \"mbedtls/asn1.h\"\n#endif\n#endif  /* MBEDTLS_USE_PSA_CRYPTO */\n\n#include \"mbedtls/platform.h\"\n\n#include <limits.h>\n#include <stdint.h>\n#include <string.h>\n\n#if defined(MBEDTLS_RSA_C)\nstatic int rsa_can_do(mbedtls_pk_type_t type)\n{\n    return type == MBEDTLS_PK_RSA ||\n           type == MBEDTLS_PK_RSASSA_PSS;\n}\n\nstatic size_t rsa_get_bitlen(mbedtls_pk_context *pk)\n{\n    const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *) pk->pk_ctx;\n    return mbedtls_rsa_get_bitlen(rsa);\n}\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nstatic int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                           const unsigned char *hash, size_t hash_len,\n                           const unsigned char *sig, size_t sig_len)\n{\n    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;\n    psa_status_t status;\n    int key_len;\n    unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];\n    unsigned char *p = buf + sizeof(buf);\n    psa_algorithm_t psa_alg_md;\n    size_t rsa_len = mbedtls_rsa_get_len(rsa);\n\n#if SIZE_MAX > UINT_MAX\n    if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n#endif\n\n    if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {\n        psa_alg_md = PSA_ALG_RSA_PSS(mbedtls_md_psa_alg_from_type(md_alg));\n    } else {\n        psa_alg_md = PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg));\n    }\n\n    if (sig_len < rsa_len) {\n        return MBEDTLS_ERR_RSA_VERIFY_FAILED;\n    }\n\n    key_len = mbedtls_rsa_write_pubkey(rsa, buf, &p);\n    if (key_len <= 0) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);\n    psa_set_key_algorithm(&attributes, psa_alg_md);\n    psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);\n\n    status = psa_import_key(&attributes,\n                            buf + sizeof(buf) - key_len, key_len,\n                            &key_id);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_PK_TO_MBEDTLS_ERR(status);\n        goto cleanup;\n    }\n\n    status = psa_verify_hash(key_id, psa_alg_md, hash, hash_len,\n                             sig, sig_len);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);\n        goto cleanup;\n    }\n    ret = 0;\n\ncleanup:\n    status = psa_destroy_key(key_id);\n    if (ret == 0 && status != PSA_SUCCESS) {\n        ret = PSA_PK_TO_MBEDTLS_ERR(status);\n    }\n\n    return ret;\n}\n#else /* MBEDTLS_USE_PSA_CRYPTO */\nstatic int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                           const unsigned char *hash, size_t hash_len,\n                           const unsigned char *sig, size_t sig_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;\n    size_t rsa_len = mbedtls_rsa_get_len(rsa);\n\n#if SIZE_MAX > UINT_MAX\n    if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n#endif\n\n    if (sig_len < rsa_len) {\n        return MBEDTLS_ERR_RSA_VERIFY_FAILED;\n    }\n\n    if ((ret = mbedtls_rsa_pkcs1_verify(rsa, md_alg,\n                                        (unsigned int) hash_len,\n                                        hash, sig)) != 0) {\n        return ret;\n    }\n\n    /* The buffer contains a valid signature followed by extra data.\n     * We have a special error code for that so that so that callers can\n     * use mbedtls_pk_verify() to check \"Does the buffer start with a\n     * valid signature?\" and not just \"Does the buffer contain a valid\n     * signature?\". */\n    if (sig_len > rsa_len) {\n        return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nint  mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t alg,\n                                 mbedtls_rsa_context *rsa_ctx,\n                                 const unsigned char *hash, size_t hash_len,\n                                 unsigned char *sig, size_t sig_size,\n                                 size_t *sig_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;\n    psa_status_t status;\n    int key_len;\n    unsigned char *buf = NULL;\n    unsigned char *p;\n\n    buf = mbedtls_calloc(1, MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES);\n    if (buf == NULL) {\n        return MBEDTLS_ERR_PK_ALLOC_FAILED;\n    }\n    p = buf + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES;\n\n    *sig_len = mbedtls_rsa_get_len(rsa_ctx);\n    if (sig_size < *sig_len) {\n        mbedtls_free(buf);\n        return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;\n    }\n\n    key_len = mbedtls_rsa_write_key(rsa_ctx, buf, &p);\n    if (key_len <= 0) {\n        mbedtls_free(buf);\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);\n    psa_set_key_algorithm(&attributes, alg);\n    psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);\n\n    status = psa_import_key(&attributes,\n                            buf + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES - key_len, key_len,\n                            &key_id);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_PK_TO_MBEDTLS_ERR(status);\n        goto cleanup;\n    }\n    status = psa_sign_hash(key_id, alg, hash, hash_len,\n                           sig, sig_size, sig_len);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);\n        goto cleanup;\n    }\n\n    ret = 0;\n\ncleanup:\n    mbedtls_free(buf);\n    status = psa_destroy_key(key_id);\n    if (ret == 0 && status != PSA_SUCCESS) {\n        ret = PSA_PK_TO_MBEDTLS_ERR(status);\n    }\n    return ret;\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nstatic int rsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                         const unsigned char *hash, size_t hash_len,\n                         unsigned char *sig, size_t sig_size, size_t *sig_len,\n                         int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    ((void) f_rng);\n    ((void) p_rng);\n\n    psa_algorithm_t psa_md_alg;\n    psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);\n    if (psa_md_alg == 0) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n    psa_algorithm_t psa_alg;\n    if (mbedtls_rsa_get_padding_mode(mbedtls_pk_rsa(*pk)) == MBEDTLS_RSA_PKCS_V21) {\n        psa_alg = PSA_ALG_RSA_PSS(psa_md_alg);\n    } else {\n        psa_alg = PSA_ALG_RSA_PKCS1V15_SIGN(psa_md_alg);\n    }\n\n    return mbedtls_pk_psa_rsa_sign_ext(psa_alg, pk->pk_ctx, hash, hash_len,\n                                       sig, sig_size, sig_len);\n}\n#else /* MBEDTLS_USE_PSA_CRYPTO */\nstatic int rsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                         const unsigned char *hash, size_t hash_len,\n                         unsigned char *sig, size_t sig_size, size_t *sig_len,\n                         int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;\n\n#if SIZE_MAX > UINT_MAX\n    if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n#endif\n\n    *sig_len = mbedtls_rsa_get_len(rsa);\n    if (sig_size < *sig_len) {\n        return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;\n    }\n\n    return mbedtls_rsa_pkcs1_sign(rsa, f_rng, p_rng,\n                                  md_alg, (unsigned int) hash_len,\n                                  hash, sig);\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nstatic int rsa_decrypt_wrap(mbedtls_pk_context *pk,\n                            const unsigned char *input, size_t ilen,\n                            unsigned char *output, size_t *olen, size_t osize,\n                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;\n    psa_algorithm_t psa_md_alg, decrypt_alg;\n    psa_status_t status;\n    int key_len;\n    unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];\n    unsigned char *p = buf + sizeof(buf);\n\n    ((void) f_rng);\n    ((void) p_rng);\n\n    if (ilen != mbedtls_rsa_get_len(rsa)) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    key_len = mbedtls_rsa_write_key(rsa, buf, &p);\n    if (key_len <= 0) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);\n    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);\n    if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {\n        psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa));\n        decrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg);\n    } else {\n        decrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT;\n    }\n    psa_set_key_algorithm(&attributes, decrypt_alg);\n\n    status = psa_import_key(&attributes,\n                            buf + sizeof(buf) - key_len, key_len,\n                            &key_id);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_PK_TO_MBEDTLS_ERR(status);\n        goto cleanup;\n    }\n\n    status = psa_asymmetric_decrypt(key_id, decrypt_alg,\n                                    input, ilen,\n                                    NULL, 0,\n                                    output, osize, olen);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);\n        goto cleanup;\n    }\n\n    ret = 0;\n\ncleanup:\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n    status = psa_destroy_key(key_id);\n    if (ret == 0 && status != PSA_SUCCESS) {\n        ret = PSA_PK_TO_MBEDTLS_ERR(status);\n    }\n\n    return ret;\n}\n#else /* MBEDTLS_USE_PSA_CRYPTO */\nstatic int rsa_decrypt_wrap(mbedtls_pk_context *pk,\n                            const unsigned char *input, size_t ilen,\n                            unsigned char *output, size_t *olen, size_t osize,\n                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;\n\n    if (ilen != mbedtls_rsa_get_len(rsa)) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    return mbedtls_rsa_pkcs1_decrypt(rsa, f_rng, p_rng,\n                                     olen, input, output, osize);\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nstatic int rsa_encrypt_wrap(mbedtls_pk_context *pk,\n                            const unsigned char *input, size_t ilen,\n                            unsigned char *output, size_t *olen, size_t osize,\n                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;\n    psa_algorithm_t psa_md_alg, psa_encrypt_alg;\n    psa_status_t status;\n    int key_len;\n    unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];\n    unsigned char *p = buf + sizeof(buf);\n\n    ((void) f_rng);\n    ((void) p_rng);\n\n    if (mbedtls_rsa_get_len(rsa) > osize) {\n        return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;\n    }\n\n    key_len = mbedtls_rsa_write_pubkey(rsa, buf, &p);\n    if (key_len <= 0) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);\n    if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {\n        psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa));\n        psa_encrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg);\n    } else {\n        psa_encrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT;\n    }\n    psa_set_key_algorithm(&attributes, psa_encrypt_alg);\n    psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);\n\n    status = psa_import_key(&attributes,\n                            buf + sizeof(buf) - key_len, key_len,\n                            &key_id);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_PK_TO_MBEDTLS_ERR(status);\n        goto cleanup;\n    }\n\n    status = psa_asymmetric_encrypt(key_id, psa_encrypt_alg,\n                                    input, ilen,\n                                    NULL, 0,\n                                    output, osize, olen);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);\n        goto cleanup;\n    }\n\n    ret = 0;\n\ncleanup:\n    status = psa_destroy_key(key_id);\n    if (ret == 0 && status != PSA_SUCCESS) {\n        ret = PSA_PK_TO_MBEDTLS_ERR(status);\n    }\n\n    return ret;\n}\n#else /* MBEDTLS_USE_PSA_CRYPTO */\nstatic int rsa_encrypt_wrap(mbedtls_pk_context *pk,\n                            const unsigned char *input, size_t ilen,\n                            unsigned char *output, size_t *olen, size_t osize,\n                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;\n    *olen = mbedtls_rsa_get_len(rsa);\n\n    if (*olen > osize) {\n        return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;\n    }\n\n    return mbedtls_rsa_pkcs1_encrypt(rsa, f_rng, p_rng,\n                                     ilen, input, output);\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\nstatic int rsa_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv,\n                               int (*f_rng)(void *, unsigned char *, size_t),\n                               void *p_rng)\n{\n    (void) f_rng;\n    (void) p_rng;\n    return mbedtls_rsa_check_pub_priv((const mbedtls_rsa_context *) pub->pk_ctx,\n                                      (const mbedtls_rsa_context *) prv->pk_ctx);\n}\n\nstatic void *rsa_alloc_wrap(void)\n{\n    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_context));\n\n    if (ctx != NULL) {\n        mbedtls_rsa_init((mbedtls_rsa_context *) ctx);\n    }\n\n    return ctx;\n}\n\nstatic void rsa_free_wrap(void *ctx)\n{\n    mbedtls_rsa_free((mbedtls_rsa_context *) ctx);\n    mbedtls_free(ctx);\n}\n\nstatic void rsa_debug(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items)\n{\n#if defined(MBEDTLS_RSA_ALT)\n    /* Not supported */\n    (void) pk;\n    (void) items;\n#else\n    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;\n\n    items->type = MBEDTLS_PK_DEBUG_MPI;\n    items->name = \"rsa.N\";\n    items->value = &(rsa->N);\n\n    items++;\n\n    items->type = MBEDTLS_PK_DEBUG_MPI;\n    items->name = \"rsa.E\";\n    items->value = &(rsa->E);\n#endif\n}\n\nconst mbedtls_pk_info_t mbedtls_rsa_info = {\n    .type = MBEDTLS_PK_RSA,\n    .name = \"RSA\",\n    .get_bitlen = rsa_get_bitlen,\n    .can_do = rsa_can_do,\n    .verify_func = rsa_verify_wrap,\n    .sign_func = rsa_sign_wrap,\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    .verify_rs_func = NULL,\n    .sign_rs_func = NULL,\n    .rs_alloc_func = NULL,\n    .rs_free_func = NULL,\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n    .decrypt_func = rsa_decrypt_wrap,\n    .encrypt_func = rsa_encrypt_wrap,\n    .check_pair_func = rsa_check_pair_wrap,\n    .ctx_alloc_func = rsa_alloc_wrap,\n    .ctx_free_func = rsa_free_wrap,\n    .debug_func = rsa_debug,\n};\n#endif /* MBEDTLS_RSA_C */\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n/*\n * Generic EC key\n */\nstatic int eckey_can_do(mbedtls_pk_type_t type)\n{\n    return type == MBEDTLS_PK_ECKEY ||\n           type == MBEDTLS_PK_ECKEY_DH ||\n           type == MBEDTLS_PK_ECDSA;\n}\n\nstatic size_t eckey_get_bitlen(mbedtls_pk_context *pk)\n{\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n    return pk->ec_bits;\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\n    mbedtls_ecp_keypair *ecp = (mbedtls_ecp_keypair *) pk->pk_ctx;\n    return ecp->grp.pbits;\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n}\n\n#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n/* Common helper for ECDSA verify using PSA functions. */\nstatic int ecdsa_verify_psa(unsigned char *key, size_t key_len,\n                            psa_ecc_family_t curve, size_t curve_bits,\n                            const unsigned char *hash, size_t hash_len,\n                            const unsigned char *sig, size_t sig_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;\n    psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY;\n    size_t signature_len = PSA_ECDSA_SIGNATURE_SIZE(curve_bits);\n    size_t converted_sig_len;\n    unsigned char extracted_sig[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE];\n    unsigned char *p;\n    psa_status_t status;\n\n    if (curve == 0) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve));\n    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);\n    psa_set_key_algorithm(&attributes, psa_sig_md);\n\n    status = psa_import_key(&attributes, key, key_len, &key_id);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_PK_TO_MBEDTLS_ERR(status);\n        goto cleanup;\n    }\n\n    if (signature_len > sizeof(extracted_sig)) {\n        ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n\n    p = (unsigned char *) sig;\n    ret = mbedtls_ecdsa_der_to_raw(curve_bits, p, sig_len, extracted_sig,\n                                   sizeof(extracted_sig), &converted_sig_len);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    if (converted_sig_len != signature_len) {\n        ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n\n    status = psa_verify_hash(key_id, psa_sig_md, hash, hash_len,\n                             extracted_sig, signature_len);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);\n        goto cleanup;\n    }\n\n    ret = 0;\n\ncleanup:\n    status = psa_destroy_key(key_id);\n    if (ret == 0 && status != PSA_SUCCESS) {\n        ret = PSA_PK_TO_MBEDTLS_ERR(status);\n    }\n\n    return ret;\n}\n\nstatic int ecdsa_opaque_verify_wrap(mbedtls_pk_context *pk,\n                                    mbedtls_md_type_t md_alg,\n                                    const unsigned char *hash, size_t hash_len,\n                                    const unsigned char *sig, size_t sig_len)\n{\n    (void) md_alg;\n    unsigned char key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN];\n    size_t key_len;\n    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;\n    psa_ecc_family_t curve;\n    size_t curve_bits;\n    psa_status_t status;\n\n    status = psa_get_key_attributes(pk->priv_id, &key_attr);\n    if (status != PSA_SUCCESS) {\n        return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);\n    }\n    curve = PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(&key_attr));\n    curve_bits = psa_get_key_bits(&key_attr);\n    psa_reset_key_attributes(&key_attr);\n\n    status = psa_export_public_key(pk->priv_id, key, sizeof(key), &key_len);\n    if (status != PSA_SUCCESS) {\n        return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);\n    }\n\n    return ecdsa_verify_psa(key, key_len, curve, curve_bits,\n                            hash, hash_len, sig, sig_len);\n}\n\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\nstatic int ecdsa_verify_wrap(mbedtls_pk_context *pk,\n                             mbedtls_md_type_t md_alg,\n                             const unsigned char *hash, size_t hash_len,\n                             const unsigned char *sig, size_t sig_len)\n{\n    (void) md_alg;\n    psa_ecc_family_t curve = pk->ec_family;\n    size_t curve_bits = pk->ec_bits;\n\n    return ecdsa_verify_psa(pk->pub_raw, pk->pub_raw_len, curve, curve_bits,\n                            hash, hash_len, sig, sig_len);\n}\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\nstatic int ecdsa_verify_wrap(mbedtls_pk_context *pk,\n                             mbedtls_md_type_t md_alg,\n                             const unsigned char *hash, size_t hash_len,\n                             const unsigned char *sig, size_t sig_len)\n{\n    (void) md_alg;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_keypair *ctx = pk->pk_ctx;\n    unsigned char key[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];\n    size_t key_len;\n    size_t curve_bits;\n    psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits);\n\n    ret = mbedtls_ecp_point_write_binary(&ctx->grp, &ctx->Q,\n                                         MBEDTLS_ECP_PF_UNCOMPRESSED,\n                                         &key_len, key, sizeof(key));\n    if (ret != 0) {\n        return ret;\n    }\n\n    return ecdsa_verify_psa(key, key_len, curve, curve_bits,\n                            hash, hash_len, sig, sig_len);\n}\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n#else /* MBEDTLS_USE_PSA_CRYPTO */\nstatic int ecdsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                             const unsigned char *hash, size_t hash_len,\n                             const unsigned char *sig, size_t sig_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    ((void) md_alg);\n\n    ret = mbedtls_ecdsa_read_signature((mbedtls_ecdsa_context *) pk->pk_ctx,\n                                       hash, hash_len, sig, sig_len);\n\n    if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) {\n        return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;\n    }\n\n    return ret;\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */\n\n#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n/* Common helper for ECDSA sign using PSA functions.\n * Instead of extracting key's properties in order to check which kind of ECDSA\n * signature it supports, we try both deterministic and non-deterministic.\n */\nstatic int ecdsa_sign_psa(mbedtls_svc_key_id_t key_id, mbedtls_md_type_t md_alg,\n                          const unsigned char *hash, size_t hash_len,\n                          unsigned char *sig, size_t sig_size, size_t *sig_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    psa_status_t status;\n    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;\n    size_t key_bits = 0;\n\n    status = psa_get_key_attributes(key_id, &key_attr);\n    if (status != PSA_SUCCESS) {\n        return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);\n    }\n    key_bits = psa_get_key_bits(&key_attr);\n    psa_reset_key_attributes(&key_attr);\n\n    status = psa_sign_hash(key_id,\n                           PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)),\n                           hash, hash_len, sig, sig_size, sig_len);\n    if (status == PSA_SUCCESS) {\n        goto done;\n    } else if (status != PSA_ERROR_NOT_PERMITTED) {\n        return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);\n    }\n\n    status = psa_sign_hash(key_id,\n                           PSA_ALG_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)),\n                           hash, hash_len, sig, sig_size, sig_len);\n    if (status != PSA_SUCCESS) {\n        return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);\n    }\n\ndone:\n    ret = mbedtls_ecdsa_raw_to_der(key_bits, sig, *sig_len, sig, sig_size, sig_len);\n\n    return ret;\n}\n\nstatic int ecdsa_opaque_sign_wrap(mbedtls_pk_context *pk,\n                                  mbedtls_md_type_t md_alg,\n                                  const unsigned char *hash, size_t hash_len,\n                                  unsigned char *sig, size_t sig_size,\n                                  size_t *sig_len,\n                                  int (*f_rng)(void *, unsigned char *, size_t),\n                                  void *p_rng)\n{\n    ((void) f_rng);\n    ((void) p_rng);\n\n    return ecdsa_sign_psa(pk->priv_id, md_alg, hash, hash_len, sig, sig_size,\n                          sig_len);\n}\n\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n/* When PK_USE_PSA_EC_DATA is defined opaque and non-opaque keys end up\n * using the same function. */\n#define ecdsa_sign_wrap     ecdsa_opaque_sign_wrap\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\nstatic int ecdsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                           const unsigned char *hash, size_t hash_len,\n                           unsigned char *sig, size_t sig_size, size_t *sig_len,\n                           int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;\n    psa_status_t status;\n    mbedtls_ecp_keypair *ctx = pk->pk_ctx;\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    unsigned char buf[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH];\n    size_t curve_bits;\n    psa_ecc_family_t curve =\n        mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits);\n    size_t key_len = PSA_BITS_TO_BYTES(curve_bits);\n    psa_algorithm_t psa_hash = mbedtls_md_psa_alg_from_type(md_alg);\n    psa_algorithm_t psa_sig_md = MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(psa_hash);\n    ((void) f_rng);\n    ((void) p_rng);\n\n    if (curve == 0) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    if (key_len > sizeof(buf)) {\n        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    }\n    ret = mbedtls_mpi_write_binary(&ctx->d, buf, key_len);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));\n    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);\n    psa_set_key_algorithm(&attributes, psa_sig_md);\n\n    status = psa_import_key(&attributes, buf, key_len, &key_id);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_PK_TO_MBEDTLS_ERR(status);\n        goto cleanup;\n    }\n\n    ret = ecdsa_sign_psa(key_id, md_alg, hash, hash_len, sig, sig_size, sig_len);\n\ncleanup:\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n    status = psa_destroy_key(key_id);\n    if (ret == 0 && status != PSA_SUCCESS) {\n        ret = PSA_PK_TO_MBEDTLS_ERR(status);\n    }\n\n    return ret;\n}\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n#else /* MBEDTLS_USE_PSA_CRYPTO */\nstatic int ecdsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                           const unsigned char *hash, size_t hash_len,\n                           unsigned char *sig, size_t sig_size, size_t *sig_len,\n                           int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    return mbedtls_ecdsa_write_signature((mbedtls_ecdsa_context *) pk->pk_ctx,\n                                         md_alg, hash, hash_len,\n                                         sig, sig_size, sig_len,\n                                         f_rng, p_rng);\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n/* Forward declarations */\nstatic int ecdsa_verify_rs_wrap(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,\n                                const unsigned char *hash, size_t hash_len,\n                                const unsigned char *sig, size_t sig_len,\n                                void *rs_ctx);\n\nstatic int ecdsa_sign_rs_wrap(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,\n                              const unsigned char *hash, size_t hash_len,\n                              unsigned char *sig, size_t sig_size, size_t *sig_len,\n                              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,\n                              void *rs_ctx);\n\n/*\n * Restart context for ECDSA operations with ECKEY context\n *\n * We need to store an actual ECDSA context, as we need to pass the same to\n * the underlying ecdsa function, so we can't create it on the fly every time.\n */\ntypedef struct {\n    mbedtls_ecdsa_restart_ctx ecdsa_rs;\n    mbedtls_ecdsa_context ecdsa_ctx;\n} eckey_restart_ctx;\n\nstatic void *eckey_rs_alloc(void)\n{\n    eckey_restart_ctx *rs_ctx;\n\n    void *ctx = mbedtls_calloc(1, sizeof(eckey_restart_ctx));\n\n    if (ctx != NULL) {\n        rs_ctx = ctx;\n        mbedtls_ecdsa_restart_init(&rs_ctx->ecdsa_rs);\n        mbedtls_ecdsa_init(&rs_ctx->ecdsa_ctx);\n    }\n\n    return ctx;\n}\n\nstatic void eckey_rs_free(void *ctx)\n{\n    eckey_restart_ctx *rs_ctx;\n\n    if (ctx == NULL) {\n        return;\n    }\n\n    rs_ctx = ctx;\n    mbedtls_ecdsa_restart_free(&rs_ctx->ecdsa_rs);\n    mbedtls_ecdsa_free(&rs_ctx->ecdsa_ctx);\n\n    mbedtls_free(ctx);\n}\n\nstatic int eckey_verify_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                                const unsigned char *hash, size_t hash_len,\n                                const unsigned char *sig, size_t sig_len,\n                                void *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    eckey_restart_ctx *rs = rs_ctx;\n\n    /* Should never happen */\n    if (rs == NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    /* set up our own sub-context if needed (that is, on first run) */\n    if (rs->ecdsa_ctx.grp.pbits == 0) {\n        MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, pk->pk_ctx));\n    }\n\n    MBEDTLS_MPI_CHK(ecdsa_verify_rs_wrap(pk,\n                                         md_alg, hash, hash_len,\n                                         sig, sig_len, &rs->ecdsa_rs));\n\ncleanup:\n    return ret;\n}\n\nstatic int eckey_sign_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                              const unsigned char *hash, size_t hash_len,\n                              unsigned char *sig, size_t sig_size, size_t *sig_len,\n                              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,\n                              void *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    eckey_restart_ctx *rs = rs_ctx;\n\n    /* Should never happen */\n    if (rs == NULL) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    /* set up our own sub-context if needed (that is, on first run) */\n    if (rs->ecdsa_ctx.grp.pbits == 0) {\n        MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, pk->pk_ctx));\n    }\n\n    MBEDTLS_MPI_CHK(ecdsa_sign_rs_wrap(pk, md_alg,\n                                       hash, hash_len, sig, sig_size, sig_len,\n                                       f_rng, p_rng, &rs->ecdsa_rs));\n\ncleanup:\n    return ret;\n}\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\nstatic int eckey_check_pair_psa(mbedtls_pk_context *pub, mbedtls_pk_context *prv)\n{\n    psa_status_t status;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    uint8_t prv_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];\n    size_t prv_key_len;\n    mbedtls_svc_key_id_t key_id = prv->priv_id;\n\n    status = psa_export_public_key(key_id, prv_key_buf, sizeof(prv_key_buf),\n                                   &prv_key_len);\n    ret = PSA_PK_TO_MBEDTLS_ERR(status);\n    if (ret != 0) {\n        return ret;\n    }\n\n    if (memcmp(prv_key_buf, pub->pub_raw, pub->pub_raw_len) != 0) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    return 0;\n}\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\nstatic int eckey_check_pair_psa(mbedtls_pk_context *pub, mbedtls_pk_context *prv)\n{\n    psa_status_t status;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    uint8_t prv_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];\n    size_t prv_key_len;\n    psa_status_t destruction_status;\n    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;\n    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;\n    uint8_t pub_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];\n    size_t pub_key_len;\n    size_t curve_bits;\n    const psa_ecc_family_t curve =\n        mbedtls_ecc_group_to_psa(mbedtls_pk_ec_ro(*prv)->grp.id, &curve_bits);\n    const size_t curve_bytes = PSA_BITS_TO_BYTES(curve_bits);\n\n    if (curve == 0) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));\n    psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT);\n\n    ret = mbedtls_mpi_write_binary(&mbedtls_pk_ec_ro(*prv)->d,\n                                   prv_key_buf, curve_bytes);\n    if (ret != 0) {\n        mbedtls_platform_zeroize(prv_key_buf, sizeof(prv_key_buf));\n        return ret;\n    }\n\n    status = psa_import_key(&key_attr, prv_key_buf, curve_bytes, &key_id);\n    mbedtls_platform_zeroize(prv_key_buf, sizeof(prv_key_buf));\n    ret = PSA_PK_TO_MBEDTLS_ERR(status);\n    if (ret != 0) {\n        return ret;\n    }\n\n    // From now on prv_key_buf is used to store the public key of prv.\n    status = psa_export_public_key(key_id, prv_key_buf, sizeof(prv_key_buf),\n                                   &prv_key_len);\n    ret = PSA_PK_TO_MBEDTLS_ERR(status);\n    destruction_status = psa_destroy_key(key_id);\n    if (ret != 0) {\n        return ret;\n    } else if (destruction_status != PSA_SUCCESS) {\n        return PSA_PK_TO_MBEDTLS_ERR(destruction_status);\n    }\n\n    ret = mbedtls_ecp_point_write_binary(&mbedtls_pk_ec_rw(*pub)->grp,\n                                         &mbedtls_pk_ec_rw(*pub)->Q,\n                                         MBEDTLS_ECP_PF_UNCOMPRESSED,\n                                         &pub_key_len, pub_key_buf,\n                                         sizeof(pub_key_buf));\n    if (ret != 0) {\n        return ret;\n    }\n\n    if (memcmp(prv_key_buf, pub_key_buf, curve_bytes) != 0) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n\nstatic int eckey_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv,\n                                 int (*f_rng)(void *, unsigned char *, size_t),\n                                 void *p_rng)\n{\n    (void) f_rng;\n    (void) p_rng;\n    return eckey_check_pair_psa(pub, prv);\n}\n#else /* MBEDTLS_USE_PSA_CRYPTO */\nstatic int eckey_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv,\n                                 int (*f_rng)(void *, unsigned char *, size_t),\n                                 void *p_rng)\n{\n    return mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair *) pub->pk_ctx,\n                                      (const mbedtls_ecp_keypair *) prv->pk_ctx,\n                                      f_rng, p_rng);\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n/* When PK_USE_PSA_EC_DATA is defined opaque and non-opaque keys end up\n * using the same function. */\n#define ecdsa_opaque_check_pair_wrap    eckey_check_pair_wrap\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\nstatic int ecdsa_opaque_check_pair_wrap(mbedtls_pk_context *pub,\n                                        mbedtls_pk_context *prv,\n                                        int (*f_rng)(void *, unsigned char *, size_t),\n                                        void *p_rng)\n{\n    psa_status_t status;\n    uint8_t exp_pub_key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN];\n    size_t exp_pub_key_len = 0;\n    uint8_t pub_key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN];\n    size_t pub_key_len = 0;\n    int ret;\n    (void) f_rng;\n    (void) p_rng;\n\n    status = psa_export_public_key(prv->priv_id, exp_pub_key, sizeof(exp_pub_key),\n                                   &exp_pub_key_len);\n    if (status != PSA_SUCCESS) {\n        ret = psa_pk_status_to_mbedtls(status);\n        return ret;\n    }\n    ret = mbedtls_ecp_point_write_binary(&(mbedtls_pk_ec_ro(*pub)->grp),\n                                         &(mbedtls_pk_ec_ro(*pub)->Q),\n                                         MBEDTLS_ECP_PF_UNCOMPRESSED,\n                                         &pub_key_len, pub_key, sizeof(pub_key));\n    if (ret != 0) {\n        return ret;\n    }\n    if ((exp_pub_key_len != pub_key_len) ||\n        memcmp(exp_pub_key, pub_key, exp_pub_key_len)) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n    return 0;\n}\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA)\nstatic void *eckey_alloc_wrap(void)\n{\n    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair));\n\n    if (ctx != NULL) {\n        mbedtls_ecp_keypair_init(ctx);\n    }\n\n    return ctx;\n}\n\nstatic void eckey_free_wrap(void *ctx)\n{\n    mbedtls_ecp_keypair_free((mbedtls_ecp_keypair *) ctx);\n    mbedtls_free(ctx);\n}\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n\nstatic void eckey_debug(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items)\n{\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n    items->type = MBEDTLS_PK_DEBUG_PSA_EC;\n    items->name = \"eckey.Q\";\n    items->value = pk;\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\n    mbedtls_ecp_keypair *ecp = (mbedtls_ecp_keypair *) pk->pk_ctx;\n    items->type = MBEDTLS_PK_DEBUG_ECP;\n    items->name = \"eckey.Q\";\n    items->value = &(ecp->Q);\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n}\n\nconst mbedtls_pk_info_t mbedtls_eckey_info = {\n    .type = MBEDTLS_PK_ECKEY,\n    .name = \"EC\",\n    .get_bitlen = eckey_get_bitlen,\n    .can_do = eckey_can_do,\n#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)\n    .verify_func = ecdsa_verify_wrap,   /* Compatible key structures */\n#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */\n    .verify_func = NULL,\n#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */\n#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)\n    .sign_func = ecdsa_sign_wrap,   /* Compatible key structures */\n#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */\n    .sign_func = NULL,\n#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    .verify_rs_func = eckey_verify_rs_wrap,\n    .sign_rs_func = eckey_sign_rs_wrap,\n    .rs_alloc_func = eckey_rs_alloc,\n    .rs_free_func = eckey_rs_free,\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n    .decrypt_func = NULL,\n    .encrypt_func = NULL,\n    .check_pair_func = eckey_check_pair_wrap,\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n    .ctx_alloc_func = NULL,\n    .ctx_free_func = NULL,\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\n    .ctx_alloc_func = eckey_alloc_wrap,\n    .ctx_free_func = eckey_free_wrap,\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n    .debug_func = eckey_debug,\n};\n\n/*\n * EC key restricted to ECDH\n */\nstatic int eckeydh_can_do(mbedtls_pk_type_t type)\n{\n    return type == MBEDTLS_PK_ECKEY ||\n           type == MBEDTLS_PK_ECKEY_DH;\n}\n\nconst mbedtls_pk_info_t mbedtls_eckeydh_info = {\n    .type = MBEDTLS_PK_ECKEY_DH,\n    .name = \"EC_DH\",\n    .get_bitlen = eckey_get_bitlen,         /* Same underlying key structure */\n    .can_do = eckeydh_can_do,\n    .verify_func = NULL,\n    .sign_func = NULL,\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    .verify_rs_func = NULL,\n    .sign_rs_func = NULL,\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n    .decrypt_func = NULL,\n    .encrypt_func = NULL,\n    .check_pair_func = eckey_check_pair_wrap,\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n    .ctx_alloc_func = NULL,\n    .ctx_free_func = NULL,\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\n    .ctx_alloc_func = eckey_alloc_wrap,   /* Same underlying key structure */\n    .ctx_free_func = eckey_free_wrap,    /* Same underlying key structure */\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n    .debug_func = eckey_debug,            /* Same underlying key structure */\n};\n\n#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)\nstatic int ecdsa_can_do(mbedtls_pk_type_t type)\n{\n    return type == MBEDTLS_PK_ECDSA;\n}\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\nstatic int ecdsa_verify_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                                const unsigned char *hash, size_t hash_len,\n                                const unsigned char *sig, size_t sig_len,\n                                void *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    ((void) md_alg);\n\n    ret = mbedtls_ecdsa_read_signature_restartable(\n        (mbedtls_ecdsa_context *) pk->pk_ctx,\n        hash, hash_len, sig, sig_len,\n        (mbedtls_ecdsa_restart_ctx *) rs_ctx);\n\n    if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) {\n        return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;\n    }\n\n    return ret;\n}\n\nstatic int ecdsa_sign_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                              const unsigned char *hash, size_t hash_len,\n                              unsigned char *sig, size_t sig_size, size_t *sig_len,\n                              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,\n                              void *rs_ctx)\n{\n    return mbedtls_ecdsa_write_signature_restartable(\n        (mbedtls_ecdsa_context *) pk->pk_ctx,\n        md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng,\n        (mbedtls_ecdsa_restart_ctx *) rs_ctx);\n\n}\n\nstatic void *ecdsa_rs_alloc(void)\n{\n    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecdsa_restart_ctx));\n\n    if (ctx != NULL) {\n        mbedtls_ecdsa_restart_init(ctx);\n    }\n\n    return ctx;\n}\n\nstatic void ecdsa_rs_free(void *ctx)\n{\n    mbedtls_ecdsa_restart_free(ctx);\n    mbedtls_free(ctx);\n}\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n\nconst mbedtls_pk_info_t mbedtls_ecdsa_info = {\n    .type = MBEDTLS_PK_ECDSA,\n    .name = \"ECDSA\",\n    .get_bitlen = eckey_get_bitlen,     /* Compatible key structures */\n    .can_do = ecdsa_can_do,\n#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)\n    .verify_func = ecdsa_verify_wrap,   /* Compatible key structures */\n#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */\n    .verify_func = NULL,\n#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */\n#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)\n    .sign_func = ecdsa_sign_wrap,   /* Compatible key structures */\n#else /* MBEDTLS_PK_CAN_ECDSA_SIGN */\n    .sign_func = NULL,\n#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    .verify_rs_func = ecdsa_verify_rs_wrap,\n    .sign_rs_func = ecdsa_sign_rs_wrap,\n    .rs_alloc_func = ecdsa_rs_alloc,\n    .rs_free_func = ecdsa_rs_free,\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n    .decrypt_func = NULL,\n    .encrypt_func = NULL,\n    .check_pair_func = eckey_check_pair_wrap,   /* Compatible key structures */\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n    .ctx_alloc_func = NULL,\n    .ctx_free_func = NULL,\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\n    .ctx_alloc_func = eckey_alloc_wrap,   /* Compatible key structures */\n    .ctx_free_func = eckey_free_wrap,   /* Compatible key structures */\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n    .debug_func = eckey_debug,        /* Compatible key structures */\n};\n#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)\n/*\n * Support for alternative RSA-private implementations\n */\n\nstatic int rsa_alt_can_do(mbedtls_pk_type_t type)\n{\n    return type == MBEDTLS_PK_RSA;\n}\n\nstatic size_t rsa_alt_get_bitlen(mbedtls_pk_context *pk)\n{\n    const mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx;\n\n    return 8 * rsa_alt->key_len_func(rsa_alt->key);\n}\n\nstatic int rsa_alt_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                             const unsigned char *hash, size_t hash_len,\n                             unsigned char *sig, size_t sig_size, size_t *sig_len,\n                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx;\n\n#if SIZE_MAX > UINT_MAX\n    if (UINT_MAX < hash_len) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n#endif\n\n    *sig_len = rsa_alt->key_len_func(rsa_alt->key);\n    if (*sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n    if (*sig_len > sig_size) {\n        return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;\n    }\n\n    return rsa_alt->sign_func(rsa_alt->key, f_rng, p_rng,\n                              md_alg, (unsigned int) hash_len, hash, sig);\n}\n\nstatic int rsa_alt_decrypt_wrap(mbedtls_pk_context *pk,\n                                const unsigned char *input, size_t ilen,\n                                unsigned char *output, size_t *olen, size_t osize,\n                                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx;\n\n    ((void) f_rng);\n    ((void) p_rng);\n\n    if (ilen != rsa_alt->key_len_func(rsa_alt->key)) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    return rsa_alt->decrypt_func(rsa_alt->key,\n                                 olen, input, output, osize);\n}\n\n#if defined(MBEDTLS_RSA_C)\nstatic int rsa_alt_check_pair(mbedtls_pk_context *pub, mbedtls_pk_context *prv,\n                              int (*f_rng)(void *, unsigned char *, size_t),\n                              void *p_rng)\n{\n    unsigned char sig[MBEDTLS_MPI_MAX_SIZE];\n    unsigned char hash[32];\n    size_t sig_len = 0;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (rsa_alt_get_bitlen(prv) != rsa_get_bitlen(pub)) {\n        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n    }\n\n    memset(hash, 0x2a, sizeof(hash));\n\n    if ((ret = rsa_alt_sign_wrap(prv, MBEDTLS_MD_NONE,\n                                 hash, sizeof(hash),\n                                 sig, sizeof(sig), &sig_len,\n                                 f_rng, p_rng)) != 0) {\n        return ret;\n    }\n\n    if (rsa_verify_wrap(pub, MBEDTLS_MD_NONE,\n                        hash, sizeof(hash), sig, sig_len) != 0) {\n        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_RSA_C */\n\nstatic void *rsa_alt_alloc_wrap(void)\n{\n    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_alt_context));\n\n    if (ctx != NULL) {\n        memset(ctx, 0, sizeof(mbedtls_rsa_alt_context));\n    }\n\n    return ctx;\n}\n\nstatic void rsa_alt_free_wrap(void *ctx)\n{\n    mbedtls_zeroize_and_free(ctx, sizeof(mbedtls_rsa_alt_context));\n}\n\nconst mbedtls_pk_info_t mbedtls_rsa_alt_info = {\n    .type = MBEDTLS_PK_RSA_ALT,\n    .name = \"RSA-alt\",\n    .get_bitlen = rsa_alt_get_bitlen,\n    .can_do = rsa_alt_can_do,\n    .verify_func = NULL,\n    .sign_func = rsa_alt_sign_wrap,\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    .verify_rs_func = NULL,\n    .sign_rs_func = NULL,\n    .rs_alloc_func = NULL,\n    .rs_free_func = NULL,\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n    .decrypt_func = rsa_alt_decrypt_wrap,\n    .encrypt_func = NULL,\n#if defined(MBEDTLS_RSA_C)\n    .check_pair_func = rsa_alt_check_pair,\n#else\n    .check_pair_func = NULL,\n#endif\n    .ctx_alloc_func = rsa_alt_alloc_wrap,\n    .ctx_free_func = rsa_alt_free_wrap,\n    .debug_func = NULL,\n};\n#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nstatic size_t opaque_get_bitlen(mbedtls_pk_context *pk)\n{\n    size_t bits;\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n\n    if (PSA_SUCCESS != psa_get_key_attributes(pk->priv_id, &attributes)) {\n        return 0;\n    }\n\n    bits = psa_get_key_bits(&attributes);\n    psa_reset_key_attributes(&attributes);\n    return bits;\n}\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\nstatic int ecdsa_opaque_can_do(mbedtls_pk_type_t type)\n{\n    return type == MBEDTLS_PK_ECKEY ||\n           type == MBEDTLS_PK_ECDSA;\n}\n\nconst mbedtls_pk_info_t mbedtls_ecdsa_opaque_info = {\n    .type = MBEDTLS_PK_OPAQUE,\n    .name = \"Opaque\",\n    .get_bitlen = opaque_get_bitlen,\n    .can_do = ecdsa_opaque_can_do,\n#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)\n    .verify_func = ecdsa_opaque_verify_wrap,\n#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */\n    .verify_func = NULL,\n#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */\n#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)\n    .sign_func = ecdsa_opaque_sign_wrap,\n#else /* MBEDTLS_PK_CAN_ECDSA_SIGN */\n    .sign_func = NULL,\n#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    .verify_rs_func = NULL,\n    .sign_rs_func = NULL,\n    .rs_alloc_func = NULL,\n    .rs_free_func = NULL,\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n    .decrypt_func = NULL,\n    .encrypt_func = NULL,\n    .check_pair_func = ecdsa_opaque_check_pair_wrap,\n    .ctx_alloc_func = NULL,\n    .ctx_free_func = NULL,\n    .debug_func = NULL,\n};\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\nstatic int rsa_opaque_can_do(mbedtls_pk_type_t type)\n{\n    return type == MBEDTLS_PK_RSA ||\n           type == MBEDTLS_PK_RSASSA_PSS;\n}\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)\nstatic int rsa_opaque_decrypt(mbedtls_pk_context *pk,\n                              const unsigned char *input, size_t ilen,\n                              unsigned char *output, size_t *olen, size_t osize,\n                              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    psa_algorithm_t alg;\n    psa_key_type_t type;\n    psa_status_t status;\n\n    /* PSA has its own RNG */\n    (void) f_rng;\n    (void) p_rng;\n\n    status = psa_get_key_attributes(pk->priv_id, &attributes);\n    if (status != PSA_SUCCESS) {\n        return PSA_PK_TO_MBEDTLS_ERR(status);\n    }\n\n    type = psa_get_key_type(&attributes);\n    alg = psa_get_key_algorithm(&attributes);\n    psa_reset_key_attributes(&attributes);\n\n    if (!PSA_KEY_TYPE_IS_RSA(type)) {\n        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n    }\n\n    status = psa_asymmetric_decrypt(pk->priv_id, alg, input, ilen, NULL, 0, output, osize, olen);\n    if (status != PSA_SUCCESS) {\n        return PSA_PK_RSA_TO_MBEDTLS_ERR(status);\n    }\n\n    return 0;\n}\n#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */\n\nstatic int rsa_opaque_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                                const unsigned char *hash, size_t hash_len,\n                                unsigned char *sig, size_t sig_size, size_t *sig_len,\n                                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n#if defined(MBEDTLS_RSA_C)\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    psa_algorithm_t alg;\n    psa_key_type_t type;\n    psa_status_t status;\n\n    /* PSA has its own RNG */\n    (void) f_rng;\n    (void) p_rng;\n\n    status = psa_get_key_attributes(pk->priv_id, &attributes);\n    if (status != PSA_SUCCESS) {\n        return PSA_PK_TO_MBEDTLS_ERR(status);\n    }\n\n    type = psa_get_key_type(&attributes);\n    alg = psa_get_key_algorithm(&attributes);\n    psa_reset_key_attributes(&attributes);\n\n    if (PSA_KEY_TYPE_IS_RSA(type)) {\n        alg = (alg & ~PSA_ALG_HASH_MASK) | mbedtls_md_psa_alg_from_type(md_alg);\n    } else {\n        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n    }\n\n    status = psa_sign_hash(pk->priv_id, alg, hash, hash_len, sig, sig_size, sig_len);\n    if (status != PSA_SUCCESS) {\n        if (PSA_KEY_TYPE_IS_RSA(type)) {\n            return PSA_PK_RSA_TO_MBEDTLS_ERR(status);\n        } else {\n            return PSA_PK_TO_MBEDTLS_ERR(status);\n        }\n    }\n\n    return 0;\n#else /* !MBEDTLS_RSA_C */\n    ((void) pk);\n    ((void) md_alg);\n    ((void) hash);\n    ((void) hash_len);\n    ((void) sig);\n    ((void) sig_size);\n    ((void) sig_len);\n    ((void) f_rng);\n    ((void) p_rng);\n    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n#endif /* !MBEDTLS_RSA_C */\n}\n\nconst mbedtls_pk_info_t mbedtls_rsa_opaque_info = {\n    .type = MBEDTLS_PK_OPAQUE,\n    .name = \"Opaque\",\n    .get_bitlen = opaque_get_bitlen,\n    .can_do = rsa_opaque_can_do,\n    .verify_func = NULL,\n    .sign_func = rsa_opaque_sign_wrap,\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    .verify_rs_func = NULL,\n    .sign_rs_func = NULL,\n    .rs_alloc_func = NULL,\n    .rs_free_func = NULL,\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)\n    .decrypt_func = rsa_opaque_decrypt,\n#else /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */\n    .decrypt_func = NULL,\n#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */\n    .encrypt_func = NULL,\n    .check_pair_func = NULL,\n    .ctx_alloc_func = NULL,\n    .ctx_free_func = NULL,\n    .debug_func = NULL,\n};\n\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#endif /* MBEDTLS_PK_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/pk_wrap.h",
    "content": "/**\n * \\file pk_wrap.h\n *\n * \\brief Public Key abstraction layer: wrapper functions\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_PK_WRAP_H\n#define MBEDTLS_PK_WRAP_H\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/pk.h\"\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"psa/crypto.h\"\n#endif\n\nstruct mbedtls_pk_info_t {\n    /** Public key type */\n    mbedtls_pk_type_t type;\n\n    /** Type name */\n    const char *name;\n\n    /** Get key size in bits */\n    size_t (*get_bitlen)(mbedtls_pk_context *pk);\n\n    /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */\n    int (*can_do)(mbedtls_pk_type_t type);\n\n    /** Verify signature */\n    int (*verify_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                       const unsigned char *hash, size_t hash_len,\n                       const unsigned char *sig, size_t sig_len);\n\n    /** Make signature */\n    int (*sign_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                     const unsigned char *hash, size_t hash_len,\n                     unsigned char *sig, size_t sig_size, size_t *sig_len,\n                     int (*f_rng)(void *, unsigned char *, size_t),\n                     void *p_rng);\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    /** Verify signature (restartable) */\n    int (*verify_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                          const unsigned char *hash, size_t hash_len,\n                          const unsigned char *sig, size_t sig_len,\n                          void *rs_ctx);\n\n    /** Make signature (restartable) */\n    int (*sign_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,\n                        const unsigned char *hash, size_t hash_len,\n                        unsigned char *sig, size_t sig_size, size_t *sig_len,\n                        int (*f_rng)(void *, unsigned char *, size_t),\n                        void *p_rng, void *rs_ctx);\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n\n    /** Decrypt message */\n    int (*decrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen,\n                        unsigned char *output, size_t *olen, size_t osize,\n                        int (*f_rng)(void *, unsigned char *, size_t),\n                        void *p_rng);\n\n    /** Encrypt message */\n    int (*encrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen,\n                        unsigned char *output, size_t *olen, size_t osize,\n                        int (*f_rng)(void *, unsigned char *, size_t),\n                        void *p_rng);\n\n    /** Check public-private key pair */\n    int (*check_pair_func)(mbedtls_pk_context *pub, mbedtls_pk_context *prv,\n                           int (*f_rng)(void *, unsigned char *, size_t),\n                           void *p_rng);\n\n    /** Allocate a new context */\n    void * (*ctx_alloc_func)(void);\n\n    /** Free the given context */\n    void (*ctx_free_func)(void *ctx);\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    /** Allocate the restart context */\n    void *(*rs_alloc_func)(void);\n\n    /** Free the restart context */\n    void (*rs_free_func)(void *rs_ctx);\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n\n    /** Interface with the debug module */\n    void (*debug_func)(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items);\n\n};\n#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)\n/* Container for RSA-alt */\ntypedef struct {\n    void *key;\n    mbedtls_pk_rsa_alt_decrypt_func decrypt_func;\n    mbedtls_pk_rsa_alt_sign_func sign_func;\n    mbedtls_pk_rsa_alt_key_len_func key_len_func;\n} mbedtls_rsa_alt_context;\n#endif\n\n#if defined(MBEDTLS_RSA_C)\nextern const mbedtls_pk_info_t mbedtls_rsa_info;\n#endif\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\nextern const mbedtls_pk_info_t mbedtls_eckey_info;\nextern const mbedtls_pk_info_t mbedtls_eckeydh_info;\n#endif\n\n#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)\nextern const mbedtls_pk_info_t mbedtls_ecdsa_info;\n#endif\n\n#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)\nextern const mbedtls_pk_info_t mbedtls_rsa_alt_info;\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nextern const mbedtls_pk_info_t mbedtls_ecdsa_opaque_info;\nextern const mbedtls_pk_info_t mbedtls_rsa_opaque_info;\n\n#if defined(MBEDTLS_RSA_C)\nint mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t psa_alg_md,\n                                mbedtls_rsa_context *rsa_ctx,\n                                const unsigned char *hash, size_t hash_len,\n                                unsigned char *sig, size_t sig_size,\n                                size_t *sig_len);\n#endif /* MBEDTLS_RSA_C */\n\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#endif /* MBEDTLS_PK_WRAP_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/pkcs12.c",
    "content": "/*\n *  PKCS#12 Personal Information Exchange Syntax\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  The PKCS #12 Personal Information Exchange Syntax Standard v1.1\n *\n *  http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf\n *  ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PKCS12_C)\n\n#include \"mbedtls/pkcs12.h\"\n#include \"mbedtls/asn1.h\"\n#if defined(MBEDTLS_CIPHER_C)\n#include \"mbedtls/cipher.h\"\n#endif /* MBEDTLS_CIPHER_C */\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_DES_C)\n#include \"mbedtls/des.h\"\n#endif\n\n#include \"psa_util_internal.h\"\n\n#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C)\n\nstatic int pkcs12_parse_pbe_params(mbedtls_asn1_buf *params,\n                                   mbedtls_asn1_buf *salt, int *iterations)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char **p = &params->p;\n    const unsigned char *end = params->p + params->len;\n\n    /*\n     *  pkcs-12PbeParams ::= SEQUENCE {\n     *    salt          OCTET STRING,\n     *    iterations    INTEGER\n     *  }\n     *\n     */\n    if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);\n    }\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret);\n    }\n\n    salt->p = *p;\n    *p += salt->len;\n\n    if ((ret = mbedtls_asn1_get_int(p, end, iterations)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret);\n    }\n\n    if (*p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n#define PKCS12_MAX_PWDLEN 128\n\nstatic int pkcs12_pbe_derive_key_iv(mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type,\n                                    const unsigned char *pwd,  size_t pwdlen,\n                                    unsigned char *key, size_t keylen,\n                                    unsigned char *iv,  size_t ivlen)\n{\n    int ret, iterations = 0;\n    mbedtls_asn1_buf salt;\n    size_t i;\n    unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2];\n\n    if (pwdlen > PKCS12_MAX_PWDLEN) {\n        return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;\n    }\n\n    memset(&salt, 0, sizeof(mbedtls_asn1_buf));\n    memset(&unipwd, 0, sizeof(unipwd));\n\n    if ((ret = pkcs12_parse_pbe_params(pbe_params, &salt,\n                                       &iterations)) != 0) {\n        return ret;\n    }\n\n    for (i = 0; i < pwdlen; i++) {\n        unipwd[i * 2 + 1] = pwd[i];\n    }\n\n    if ((ret = mbedtls_pkcs12_derivation(key, keylen, unipwd, pwdlen * 2 + 2,\n                                         salt.p, salt.len, md_type,\n                                         MBEDTLS_PKCS12_DERIVE_KEY, iterations)) != 0) {\n        return ret;\n    }\n\n    if (iv == NULL || ivlen == 0) {\n        return 0;\n    }\n\n    if ((ret = mbedtls_pkcs12_derivation(iv, ivlen, unipwd, pwdlen * 2 + 2,\n                                         salt.p, salt.len, md_type,\n                                         MBEDTLS_PKCS12_DERIVE_IV, iterations)) != 0) {\n        return ret;\n    }\n    return 0;\n}\n\n#undef PKCS12_MAX_PWDLEN\n\n#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)\nint mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode,\n                           mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,\n                           const unsigned char *pwd,  size_t pwdlen,\n                           const unsigned char *data, size_t len,\n                           unsigned char *output, size_t output_size,\n                           size_t *output_len);\n#endif\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\nint mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode,\n                       mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,\n                       const unsigned char *pwd,  size_t pwdlen,\n                       const unsigned char *data, size_t len,\n                       unsigned char *output)\n{\n    size_t output_len = 0;\n\n    /* We assume caller of the function is providing a big enough output buffer\n     * so we pass output_size as SIZE_MAX to pass checks, However, no guarantees\n     * for the output size actually being correct.\n     */\n    return mbedtls_pkcs12_pbe_ext(pbe_params, mode, cipher_type, md_type,\n                                  pwd, pwdlen, data, len, output, SIZE_MAX,\n                                  &output_len);\n}\n#endif\n\nint mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode,\n                           mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,\n                           const unsigned char *pwd,  size_t pwdlen,\n                           const unsigned char *data, size_t len,\n                           unsigned char *output, size_t output_size,\n                           size_t *output_len)\n{\n    int ret, keylen = 0;\n    unsigned char key[32];\n    unsigned char iv[16];\n    const mbedtls_cipher_info_t *cipher_info;\n    mbedtls_cipher_context_t cipher_ctx;\n    size_t iv_len = 0;\n    size_t finish_olen = 0;\n    unsigned int padlen = 0;\n\n    if (pwd == NULL && pwdlen != 0) {\n        return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;\n    }\n\n    cipher_info = mbedtls_cipher_info_from_type(cipher_type);\n    if (cipher_info == NULL) {\n        return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE;\n    }\n\n    keylen = (int) mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;\n\n    if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) {\n        if (output_size < len) {\n            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n        }\n    }\n\n    if (mode == MBEDTLS_PKCS12_PBE_ENCRYPT) {\n        padlen = cipher_info->block_size - (len % cipher_info->block_size);\n        if (output_size < (len + padlen)) {\n            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n        }\n    }\n\n    iv_len = mbedtls_cipher_info_get_iv_size(cipher_info);\n    if ((ret = pkcs12_pbe_derive_key_iv(pbe_params, md_type, pwd, pwdlen,\n                                        key, keylen,\n                                        iv, iv_len)) != 0) {\n        return ret;\n    }\n\n    mbedtls_cipher_init(&cipher_ctx);\n\n    if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen,\n                                     (mbedtls_operation_t) mode)) != 0) {\n        goto exit;\n    }\n\n#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)\n    {\n        /* PKCS12 uses CBC with PKCS7 padding */\n        mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7;\n#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)\n        /* For historical reasons, when decrypting, this function works when\n         * decrypting even when support for PKCS7 padding is disabled. In this\n         * case, it ignores the padding, and so will never report a\n         * password mismatch.\n         */\n        if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) {\n            padding = MBEDTLS_PADDING_NONE;\n        }\n#endif\n        if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) {\n            goto exit;\n        }\n    }\n#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */\n\n    ret = mbedtls_cipher_crypt(&cipher_ctx, iv, iv_len, data, len, output, &finish_olen);\n    if (ret == MBEDTLS_ERR_CIPHER_INVALID_PADDING) {\n        ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH;\n    }\n\n    *output_len += finish_olen;\n\nexit:\n    mbedtls_platform_zeroize(key, sizeof(key));\n    mbedtls_platform_zeroize(iv,  sizeof(iv));\n    mbedtls_cipher_free(&cipher_ctx);\n\n    return ret;\n}\n\n#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */\n\nstatic void pkcs12_fill_buffer(unsigned char *data, size_t data_len,\n                               const unsigned char *filler, size_t fill_len)\n{\n    unsigned char *p = data;\n    size_t use_len;\n\n    if (filler != NULL && fill_len != 0) {\n        while (data_len > 0) {\n            use_len = (data_len > fill_len) ? fill_len : data_len;\n            memcpy(p, filler, use_len);\n            p += use_len;\n            data_len -= use_len;\n        }\n    } else {\n        /* If either of the above are not true then clearly there is nothing\n         * that this function can do. The function should *not* be called\n         * under either of those circumstances, as you could end up with an\n         * incorrect output but for safety's sake, leaving the check in as\n         * otherwise we could end up with memory corruption.*/\n    }\n}\n\n\nstatic int calculate_hashes(mbedtls_md_type_t md_type, int iterations,\n                            unsigned char *diversifier, unsigned char *salt_block,\n                            unsigned char *pwd_block, unsigned char *hash_output, int use_salt,\n                            int use_password, size_t hlen, size_t v)\n{\n    int ret = -1;\n    size_t i;\n    const mbedtls_md_info_t *md_info;\n    mbedtls_md_context_t md_ctx;\n    md_info = mbedtls_md_info_from_type(md_type);\n    if (md_info == NULL) {\n        return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE;\n    }\n\n    mbedtls_md_init(&md_ctx);\n\n    if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) {\n        return ret;\n    }\n    // Calculate hash( diversifier || salt_block || pwd_block )\n    if ((ret = mbedtls_md_starts(&md_ctx)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_md_update(&md_ctx, diversifier, v)) != 0) {\n        goto exit;\n    }\n\n    if (use_salt != 0) {\n        if ((ret = mbedtls_md_update(&md_ctx, salt_block, v)) != 0) {\n            goto exit;\n        }\n    }\n\n    if (use_password != 0) {\n        if ((ret = mbedtls_md_update(&md_ctx, pwd_block, v)) != 0) {\n            goto exit;\n        }\n    }\n\n    if ((ret = mbedtls_md_finish(&md_ctx, hash_output)) != 0) {\n        goto exit;\n    }\n\n    // Perform remaining ( iterations - 1 ) recursive hash calculations\n    for (i = 1; i < (size_t) iterations; i++) {\n        if ((ret = mbedtls_md(md_info, hash_output, hlen, hash_output))\n            != 0) {\n            goto exit;\n        }\n    }\n\nexit:\n    mbedtls_md_free(&md_ctx);\n    return ret;\n}\n\n\nint mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen,\n                              const unsigned char *pwd, size_t pwdlen,\n                              const unsigned char *salt, size_t saltlen,\n                              mbedtls_md_type_t md_type, int id, int iterations)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned int j;\n\n    unsigned char diversifier[128];\n    unsigned char salt_block[128], pwd_block[128], hash_block[128] = { 0 };\n    unsigned char hash_output[MBEDTLS_MD_MAX_SIZE];\n    unsigned char *p;\n    unsigned char c;\n    int           use_password = 0;\n    int           use_salt = 0;\n\n    size_t hlen, use_len, v, i;\n\n    // This version only allows max of 64 bytes of password or salt\n    if (datalen > 128 || pwdlen > 64 || saltlen > 64) {\n        return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;\n    }\n\n    if (pwd == NULL && pwdlen != 0) {\n        return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;\n    }\n\n    if (salt == NULL && saltlen != 0) {\n        return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;\n    }\n\n    use_password = (pwd && pwdlen != 0);\n    use_salt = (salt && saltlen != 0);\n\n    hlen = mbedtls_md_get_size_from_type(md_type);\n\n    if (hlen <= 32) {\n        v = 64;\n    } else {\n        v = 128;\n    }\n\n    memset(diversifier, (unsigned char) id, v);\n\n    if (use_salt != 0) {\n        pkcs12_fill_buffer(salt_block, v, salt, saltlen);\n    }\n\n    if (use_password != 0) {\n        pkcs12_fill_buffer(pwd_block,  v, pwd,  pwdlen);\n    }\n\n    p = data;\n    while (datalen > 0) {\n        if (calculate_hashes(md_type, iterations, diversifier, salt_block,\n                             pwd_block, hash_output, use_salt, use_password, hlen,\n                             v) != 0) {\n            goto exit;\n        }\n\n        use_len = (datalen > hlen) ? hlen : datalen;\n        memcpy(p, hash_output, use_len);\n        datalen -= use_len;\n        p += use_len;\n\n        if (datalen == 0) {\n            break;\n        }\n\n        // Concatenating copies of hash_output into hash_block (B)\n        pkcs12_fill_buffer(hash_block, v, hash_output, hlen);\n\n        // B += 1\n        for (i = v; i > 0; i--) {\n            if (++hash_block[i - 1] != 0) {\n                break;\n            }\n        }\n\n        if (use_salt != 0) {\n            // salt_block += B\n            c = 0;\n            for (i = v; i > 0; i--) {\n                j = salt_block[i - 1] + hash_block[i - 1] + c;\n                c = MBEDTLS_BYTE_1(j);\n                salt_block[i - 1] = MBEDTLS_BYTE_0(j);\n            }\n        }\n\n        if (use_password != 0) {\n            // pwd_block  += B\n            c = 0;\n            for (i = v; i > 0; i--) {\n                j = pwd_block[i - 1] + hash_block[i - 1] + c;\n                c = MBEDTLS_BYTE_1(j);\n                pwd_block[i - 1] = MBEDTLS_BYTE_0(j);\n            }\n        }\n    }\n\n    ret = 0;\n\nexit:\n    mbedtls_platform_zeroize(salt_block, sizeof(salt_block));\n    mbedtls_platform_zeroize(pwd_block, sizeof(pwd_block));\n    mbedtls_platform_zeroize(hash_block, sizeof(hash_block));\n    mbedtls_platform_zeroize(hash_output, sizeof(hash_output));\n\n    return ret;\n}\n\n#endif /* MBEDTLS_PKCS12_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/pkcs5.c",
    "content": "/**\n * \\file pkcs5.c\n *\n * \\brief PKCS#5 functions\n *\n * \\author Mathias Olsson <mathias@kompetensum.com>\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n * PKCS#5 includes PBKDF2 and more\n *\n * http://tools.ietf.org/html/rfc2898 (Specification)\n * http://tools.ietf.org/html/rfc6070 (Test vectors)\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PKCS5_C)\n\n#include \"mbedtls/pkcs5.h\"\n#include \"mbedtls/error.h\"\n\n#if defined(MBEDTLS_ASN1_PARSE_C)\n#include \"mbedtls/asn1.h\"\n#if defined(MBEDTLS_CIPHER_C)\n#include \"mbedtls/cipher.h\"\n#endif /* MBEDTLS_CIPHER_C */\n#include \"mbedtls/oid.h\"\n#endif /* MBEDTLS_ASN1_PARSE_C */\n\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#include \"psa_util_internal.h\"\n\n#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C)\nstatic int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,\n                                     mbedtls_asn1_buf *salt, int *iterations,\n                                     int *keylen, mbedtls_md_type_t *md_type)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_asn1_buf prf_alg_oid;\n    unsigned char *p = params->p;\n    const unsigned char *end = params->p + params->len;\n\n    if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);\n    }\n    /*\n     *  PBKDF2-params ::= SEQUENCE {\n     *    salt              OCTET STRING,\n     *    iterationCount    INTEGER,\n     *    keyLength         INTEGER OPTIONAL\n     *    prf               AlgorithmIdentifier DEFAULT algid-hmacWithSHA1\n     *  }\n     *\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &salt->len,\n                                    MBEDTLS_ASN1_OCTET_STRING)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);\n    }\n\n    salt->p = p;\n    p += salt->len;\n\n    if ((ret = mbedtls_asn1_get_int(&p, end, iterations)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);\n    }\n\n    if (p == end) {\n        return 0;\n    }\n\n    if ((ret = mbedtls_asn1_get_int(&p, end, keylen)) != 0) {\n        if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);\n        }\n    }\n\n    if (p == end) {\n        return 0;\n    }\n\n    if ((ret = mbedtls_asn1_get_alg_null(&p, end, &prf_alg_oid)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);\n    }\n\n    if (mbedtls_oid_get_md_hmac(&prf_alg_oid, md_type) != 0) {\n        return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;\n    }\n\n    if (p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)\nint mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode,\n                            const unsigned char *pwd,  size_t pwdlen,\n                            const unsigned char *data, size_t datalen,\n                            unsigned char *output, size_t output_size,\n                            size_t *output_len);\n#endif\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\nint mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,\n                        const unsigned char *pwd,  size_t pwdlen,\n                        const unsigned char *data, size_t datalen,\n                        unsigned char *output)\n{\n    size_t output_len = 0;\n\n    /* We assume caller of the function is providing a big enough output buffer\n     * so we pass output_size as SIZE_MAX to pass checks, However, no guarantees\n     * for the output size actually being correct.\n     */\n    return mbedtls_pkcs5_pbes2_ext(pbe_params, mode, pwd, pwdlen, data,\n                                   datalen, output, SIZE_MAX, &output_len);\n}\n#endif\n\nint mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode,\n                            const unsigned char *pwd,  size_t pwdlen,\n                            const unsigned char *data, size_t datalen,\n                            unsigned char *output, size_t output_size,\n                            size_t *output_len)\n{\n    int ret, iterations = 0, keylen = 0;\n    unsigned char *p, *end;\n    mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params;\n    mbedtls_asn1_buf salt;\n    mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;\n    unsigned char key[32], iv[32];\n    const mbedtls_cipher_info_t *cipher_info;\n    mbedtls_cipher_type_t cipher_alg;\n    mbedtls_cipher_context_t cipher_ctx;\n    unsigned int padlen = 0;\n\n    p = pbe_params->p;\n    end = p + pbe_params->len;\n\n    /*\n     *  PBES2-params ::= SEQUENCE {\n     *    keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},\n     *    encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}\n     *  }\n     */\n    if (pbe_params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);\n    }\n\n    if ((ret = mbedtls_asn1_get_alg(&p, end, &kdf_alg_oid,\n                                    &kdf_alg_params)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);\n    }\n\n    // Only PBKDF2 supported at the moment\n    //\n    if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid) != 0) {\n        return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;\n    }\n\n    if ((ret = pkcs5_parse_pbkdf2_params(&kdf_alg_params,\n                                         &salt, &iterations, &keylen,\n                                         &md_type)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_asn1_get_alg(&p, end, &enc_scheme_oid,\n                                    &enc_scheme_params)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);\n    }\n\n    if (mbedtls_oid_get_cipher_alg(&enc_scheme_oid, &cipher_alg) != 0) {\n        return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;\n    }\n\n    cipher_info = mbedtls_cipher_info_from_type(cipher_alg);\n    if (cipher_info == NULL) {\n        return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;\n    }\n\n    /*\n     * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored\n     * since it is optional and we don't know if it was set or not\n     */\n    keylen = (int) mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;\n\n    if (enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING ||\n        enc_scheme_params.len != mbedtls_cipher_info_get_iv_size(cipher_info)) {\n        return MBEDTLS_ERR_PKCS5_INVALID_FORMAT;\n    }\n\n    if (mode == MBEDTLS_PKCS5_DECRYPT) {\n        if (output_size < datalen) {\n            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n        }\n    }\n\n    if (mode == MBEDTLS_PKCS5_ENCRYPT) {\n        padlen = cipher_info->block_size - (datalen % cipher_info->block_size);\n        if (output_size < (datalen + padlen)) {\n            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n        }\n    }\n\n    mbedtls_cipher_init(&cipher_ctx);\n\n    memcpy(iv, enc_scheme_params.p, enc_scheme_params.len);\n\n    if ((ret = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, pwd, pwdlen, salt.p,\n                                             salt.len, iterations, keylen,\n                                             key)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen,\n                                     (mbedtls_operation_t) mode)) != 0) {\n        goto exit;\n    }\n\n#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)\n    {\n        /* PKCS5 uses CBC with PKCS7 padding (which is the same as\n         * \"PKCS5 padding\" except that it's typically only called PKCS5\n         * with 64-bit-block ciphers).\n         */\n        mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7;\n#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)\n        /* For historical reasons, when decrypting, this function works when\n         * decrypting even when support for PKCS7 padding is disabled. In this\n         * case, it ignores the padding, and so will never report a\n         * password mismatch.\n         */\n        if (mode == MBEDTLS_DECRYPT) {\n            padding = MBEDTLS_PADDING_NONE;\n        }\n#endif\n        if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) {\n            goto exit;\n        }\n    }\n#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */\n    if ((ret = mbedtls_cipher_crypt(&cipher_ctx, iv, enc_scheme_params.len,\n                                    data, datalen, output, output_len)) != 0) {\n        ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH;\n    }\n\nexit:\n    mbedtls_cipher_free(&cipher_ctx);\n\n    return ret;\n}\n#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */\n\nstatic int pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx,\n                             const unsigned char *password,\n                             size_t plen, const unsigned char *salt, size_t slen,\n                             unsigned int iteration_count,\n                             uint32_t key_length, unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned int i;\n    unsigned char md1[MBEDTLS_MD_MAX_SIZE];\n    unsigned char work[MBEDTLS_MD_MAX_SIZE];\n    unsigned char md_size = mbedtls_md_get_size(ctx->md_info);\n    size_t use_len;\n    unsigned char *out_p = output;\n    unsigned char counter[4];\n\n    memset(counter, 0, 4);\n    counter[3] = 1;\n\n#if UINT_MAX > 0xFFFFFFFF\n    if (iteration_count > 0xFFFFFFFF) {\n        return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA;\n    }\n#endif\n\n    if ((ret = mbedtls_md_hmac_starts(ctx, password, plen)) != 0) {\n        return ret;\n    }\n    while (key_length) {\n        // U1 ends up in work\n        //\n        if ((ret = mbedtls_md_hmac_update(ctx, salt, slen)) != 0) {\n            goto cleanup;\n        }\n\n        if ((ret = mbedtls_md_hmac_update(ctx, counter, 4)) != 0) {\n            goto cleanup;\n        }\n\n        if ((ret = mbedtls_md_hmac_finish(ctx, work)) != 0) {\n            goto cleanup;\n        }\n\n        if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) {\n            goto cleanup;\n        }\n\n        memcpy(md1, work, md_size);\n\n        for (i = 1; i < iteration_count; i++) {\n            // U2 ends up in md1\n            //\n            if ((ret = mbedtls_md_hmac_update(ctx, md1, md_size)) != 0) {\n                goto cleanup;\n            }\n\n            if ((ret = mbedtls_md_hmac_finish(ctx, md1)) != 0) {\n                goto cleanup;\n            }\n\n            if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) {\n                goto cleanup;\n            }\n\n            // U1 xor U2\n            //\n            mbedtls_xor(work, work, md1, md_size);\n        }\n\n        use_len = (key_length < md_size) ? key_length : md_size;\n        memcpy(out_p, work, use_len);\n\n        key_length -= (uint32_t) use_len;\n        out_p += use_len;\n\n        for (i = 4; i > 0; i--) {\n            if (++counter[i - 1] != 0) {\n                break;\n            }\n        }\n    }\n\ncleanup:\n    /* Zeroise buffers to clear sensitive data from memory. */\n    mbedtls_platform_zeroize(work, MBEDTLS_MD_MAX_SIZE);\n    mbedtls_platform_zeroize(md1, MBEDTLS_MD_MAX_SIZE);\n\n    return ret;\n}\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\nint mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx,\n                              const unsigned char *password,\n                              size_t plen, const unsigned char *salt, size_t slen,\n                              unsigned int iteration_count,\n                              uint32_t key_length, unsigned char *output)\n{\n    return pkcs5_pbkdf2_hmac(ctx, password, plen, salt, slen, iteration_count,\n                             key_length, output);\n}\n#endif\n\nint mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg,\n                                  const unsigned char *password,\n                                  size_t plen, const unsigned char *salt, size_t slen,\n                                  unsigned int iteration_count,\n                                  uint32_t key_length, unsigned char *output)\n{\n    mbedtls_md_context_t md_ctx;\n    const mbedtls_md_info_t *md_info = NULL;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    md_info = mbedtls_md_info_from_type(md_alg);\n    if (md_info == NULL) {\n        return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;\n    }\n\n    mbedtls_md_init(&md_ctx);\n\n    if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) {\n        goto exit;\n    }\n    ret = pkcs5_pbkdf2_hmac(&md_ctx, password, plen, salt, slen,\n                            iteration_count, key_length, output);\nexit:\n    mbedtls_md_free(&md_ctx);\n    return ret;\n}\n\n#if defined(MBEDTLS_SELF_TEST)\n\n#if !defined(MBEDTLS_MD_CAN_SHA1)\nint mbedtls_pkcs5_self_test(int verbose)\n{\n    if (verbose != 0) {\n        mbedtls_printf(\"  PBKDF2 (SHA1): skipped\\n\\n\");\n    }\n\n    return 0;\n}\n#else\n\n#define MAX_TESTS   6\n\nstatic const size_t plen_test_data[MAX_TESTS] =\n{ 8, 8, 8, 24, 9 };\n\nstatic const unsigned char password_test_data[MAX_TESTS][32] =\n{\n    \"password\",\n    \"password\",\n    \"password\",\n    \"passwordPASSWORDpassword\",\n    \"pass\\0word\",\n};\n\nstatic const size_t slen_test_data[MAX_TESTS] =\n{ 4, 4, 4, 36, 5 };\n\nstatic const unsigned char salt_test_data[MAX_TESTS][40] =\n{\n    \"salt\",\n    \"salt\",\n    \"salt\",\n    \"saltSALTsaltSALTsaltSALTsaltSALTsalt\",\n    \"sa\\0lt\",\n};\n\nstatic const uint32_t it_cnt_test_data[MAX_TESTS] =\n{ 1, 2, 4096, 4096, 4096 };\n\nstatic const uint32_t key_len_test_data[MAX_TESTS] =\n{ 20, 20, 20, 25, 16 };\n\nstatic const unsigned char result_key_test_data[MAX_TESTS][32] =\n{\n    { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,\n      0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,\n      0x2f, 0xe0, 0x37, 0xa6 },\n    { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,\n      0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,\n      0xd8, 0xde, 0x89, 0x57 },\n    { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,\n      0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,\n      0x65, 0xa4, 0x29, 0xc1 },\n    { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,\n      0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,\n      0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,\n      0x38 },\n    { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,\n      0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 },\n};\n\nint mbedtls_pkcs5_self_test(int verbose)\n{\n    int ret, i;\n    unsigned char key[64];\n\n    for (i = 0; i < MAX_TESTS; i++) {\n        if (verbose != 0) {\n            mbedtls_printf(\"  PBKDF2 (SHA1) #%d: \", i);\n        }\n\n        ret = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, password_test_data[i],\n                                            plen_test_data[i], salt_test_data[i],\n                                            slen_test_data[i], it_cnt_test_data[i],\n                                            key_len_test_data[i], key);\n        if (ret != 0 ||\n            memcmp(result_key_test_data[i], key, key_len_test_data[i]) != 0) {\n            if (verbose != 0) {\n                mbedtls_printf(\"failed\\n\");\n            }\n\n            ret = 1;\n            goto exit;\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\nexit:\n    return ret;\n}\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_PKCS5_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/pkcs7.c",
    "content": "/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#include \"common.h\"\n\n#include \"mbedtls/build_info.h\"\n#if defined(MBEDTLS_PKCS7_C)\n#include \"mbedtls/pkcs7.h\"\n#include \"x509_internal.h\"\n#include \"mbedtls/asn1.h\"\n#include \"mbedtls/x509_crt.h\"\n#include \"mbedtls/x509_crl.h\"\n#include \"mbedtls/oid.h\"\n#include \"mbedtls/error.h\"\n\n#if defined(MBEDTLS_FS_IO)\n#include <sys/types.h>\n#include <sys/stat.h>\n#endif\n\n#include \"mbedtls/platform.h\"\n#include \"mbedtls/platform_util.h\"\n\n#if defined(MBEDTLS_HAVE_TIME)\n#include \"mbedtls/platform_time.h\"\n#endif\n#if defined(MBEDTLS_HAVE_TIME_DATE)\n#include <time.h>\n#endif\n\n/**\n * Initializes the mbedtls_pkcs7 structure.\n */\nvoid mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7)\n{\n    memset(pkcs7, 0, sizeof(*pkcs7));\n}\n\nstatic int pkcs7_get_next_content_len(unsigned char **p, unsigned char *end,\n                                      size_t *len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_CONSTRUCTED\n                               | MBEDTLS_ASN1_CONTEXT_SPECIFIC);\n    if (ret != 0) {\n        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);\n    } else if ((size_t) (end - *p) != *len) {\n        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO,\n                                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return ret;\n}\n\n/**\n * version Version\n * Version ::= INTEGER\n **/\nstatic int pkcs7_get_version(unsigned char **p, unsigned char *end, int *ver)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    ret = mbedtls_asn1_get_int(p, end, ver);\n    if (ret != 0) {\n        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret);\n    }\n\n    /* If version != 1, return invalid version */\n    if (*ver != MBEDTLS_PKCS7_SUPPORTED_VERSION) {\n        ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION;\n    }\n\n    return ret;\n}\n\n/**\n * ContentInfo ::= SEQUENCE {\n *      contentType ContentType,\n *      content\n *              [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }\n **/\nstatic int pkcs7_get_content_info_type(unsigned char **p, unsigned char *end,\n                                       unsigned char **seq_end,\n                                       mbedtls_pkcs7_buf *pkcs7)\n{\n    size_t len = 0;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *start = *p;\n\n    ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED\n                               | MBEDTLS_ASN1_SEQUENCE);\n    if (ret != 0) {\n        *p = start;\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);\n    }\n    *seq_end = *p + len;\n    ret = mbedtls_asn1_get_tag(p, *seq_end, &len, MBEDTLS_ASN1_OID);\n    if (ret != 0) {\n        *p = start;\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);\n    }\n\n    pkcs7->tag = MBEDTLS_ASN1_OID;\n    pkcs7->len = len;\n    pkcs7->p = *p;\n    *p += len;\n\n    return ret;\n}\n\n/**\n * DigestAlgorithmIdentifier ::= AlgorithmIdentifier\n *\n * This is from x509.h\n **/\nstatic int pkcs7_get_digest_algorithm(unsigned char **p, unsigned char *end,\n                                      mbedtls_x509_buf *alg)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) {\n        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);\n    }\n\n    return ret;\n}\n\n/**\n * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier\n **/\nstatic int pkcs7_get_digest_algorithm_set(unsigned char **p,\n                                          unsigned char *end,\n                                          mbedtls_x509_buf *alg)\n{\n    size_t len = 0;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED\n                               | MBEDTLS_ASN1_SET);\n    if (ret != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);\n    }\n\n    end = *p + len;\n\n    ret = mbedtls_asn1_get_alg_null(p, end, alg);\n    if (ret != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);\n    }\n\n    /** For now, it assumes there is only one digest algorithm specified **/\n    if (*p != end) {\n        return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;\n    }\n\n    return 0;\n}\n\n/**\n * certificates :: SET OF ExtendedCertificateOrCertificate,\n * ExtendedCertificateOrCertificate ::= CHOICE {\n *      certificate Certificate -- x509,\n *      extendedCertificate[0] IMPLICIT ExtendedCertificate }\n * Return number of certificates added to the signed data,\n * 0 or higher is valid.\n * Return negative error code for failure.\n **/\nstatic int pkcs7_get_certificates(unsigned char **p, unsigned char *end,\n                                  mbedtls_x509_crt *certs)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len1 = 0;\n    size_t len2 = 0;\n    unsigned char *end_set, *end_cert, *start;\n\n    ret = mbedtls_asn1_get_tag(p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED\n                               | MBEDTLS_ASN1_CONTEXT_SPECIFIC);\n    if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n        return 0;\n    }\n    if (ret != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);\n    }\n    start = *p;\n    end_set = *p + len1;\n\n    ret = mbedtls_asn1_get_tag(p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED\n                               | MBEDTLS_ASN1_SEQUENCE);\n    if (ret != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CERT, ret);\n    }\n\n    end_cert = *p + len2;\n\n    /*\n     * This is to verify that there is only one signer certificate. It seems it is\n     * not easy to differentiate between the chain vs different signer's certificate.\n     * So, we support only the root certificate and the single signer.\n     * The behaviour would be improved with addition of multiple signer support.\n     */\n    if (end_cert != end_set) {\n        return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;\n    }\n\n    if ((ret = mbedtls_x509_crt_parse_der(certs, start, len1)) < 0) {\n        return MBEDTLS_ERR_PKCS7_INVALID_CERT;\n    }\n\n    *p = end_cert;\n\n    /*\n     * Since in this version we strictly support single certificate, and reaching\n     * here implies we have parsed successfully, we return 1.\n     */\n    return 1;\n}\n\n/**\n * EncryptedDigest ::= OCTET STRING\n **/\nstatic int pkcs7_get_signature(unsigned char **p, unsigned char *end,\n                               mbedtls_pkcs7_buf *signature)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n\n    ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING);\n    if (ret != 0) {\n        return ret;\n    }\n\n    signature->tag = MBEDTLS_ASN1_OCTET_STRING;\n    signature->len = len;\n    signature->p = *p;\n\n    *p = *p + len;\n\n    return 0;\n}\n\nstatic void pkcs7_free_signer_info(mbedtls_pkcs7_signer_info *signer)\n{\n    mbedtls_x509_name *name_cur;\n    mbedtls_x509_name *name_prv;\n\n    if (signer == NULL) {\n        return;\n    }\n\n    name_cur = signer->issuer.next;\n    while (name_cur != NULL) {\n        name_prv = name_cur;\n        name_cur = name_cur->next;\n        mbedtls_free(name_prv);\n    }\n    signer->issuer.next = NULL;\n}\n\n/**\n * SignerInfo ::= SEQUENCE {\n *      version Version;\n *      issuerAndSerialNumber   IssuerAndSerialNumber,\n *      digestAlgorithm DigestAlgorithmIdentifier,\n *      authenticatedAttributes\n *              [0] IMPLICIT Attributes OPTIONAL,\n *      digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,\n *      encryptedDigest EncryptedDigest,\n *      unauthenticatedAttributes\n *              [1] IMPLICIT Attributes OPTIONAL,\n * Returns 0 if the signerInfo is valid.\n * Return negative error code for failure.\n * Structure must not contain vales for authenticatedAttributes\n * and unauthenticatedAttributes.\n **/\nstatic int pkcs7_get_signer_info(unsigned char **p, unsigned char *end,\n                                 mbedtls_pkcs7_signer_info *signer,\n                                 mbedtls_x509_buf *alg)\n{\n    unsigned char *end_signer, *end_issuer_and_sn;\n    int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n\n    asn1_ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED\n                                    | MBEDTLS_ASN1_SEQUENCE);\n    if (asn1_ret != 0) {\n        goto out;\n    }\n\n    end_signer = *p + len;\n\n    ret = pkcs7_get_version(p, end_signer, &signer->version);\n    if (ret != 0) {\n        goto out;\n    }\n\n    asn1_ret = mbedtls_asn1_get_tag(p, end_signer, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);\n    if (asn1_ret != 0) {\n        goto out;\n    }\n\n    end_issuer_and_sn = *p + len;\n    /* Parsing IssuerAndSerialNumber */\n    signer->issuer_raw.p = *p;\n\n    asn1_ret = mbedtls_asn1_get_tag(p, end_issuer_and_sn, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);\n    if (asn1_ret != 0) {\n        goto out;\n    }\n\n    ret  = mbedtls_x509_get_name(p, *p + len, &signer->issuer);\n    if (ret != 0) {\n        goto out;\n    }\n\n    signer->issuer_raw.len =  (size_t) (*p - signer->issuer_raw.p);\n\n    ret = mbedtls_x509_get_serial(p, end_issuer_and_sn, &signer->serial);\n    if (ret != 0) {\n        goto out;\n    }\n\n    /* ensure no extra or missing bytes */\n    if (*p != end_issuer_and_sn) {\n        ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;\n        goto out;\n    }\n\n    ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->alg_identifier);\n    if (ret != 0) {\n        goto out;\n    }\n\n    /* Check that the digest algorithm used matches the one provided earlier */\n    if (signer->alg_identifier.tag != alg->tag ||\n        signer->alg_identifier.len != alg->len ||\n        memcmp(signer->alg_identifier.p, alg->p, alg->len) != 0) {\n        ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;\n        goto out;\n    }\n\n    /* Assume authenticatedAttributes is nonexistent */\n    ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->sig_alg_identifier);\n    if (ret != 0) {\n        goto out;\n    }\n\n    ret = pkcs7_get_signature(p, end_signer, &signer->sig);\n    if (ret != 0) {\n        goto out;\n    }\n\n    /* Do not permit any unauthenticated attributes */\n    if (*p != end_signer) {\n        ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;\n    }\n\nout:\n    if (asn1_ret != 0 || ret != 0) {\n        pkcs7_free_signer_info(signer);\n        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,\n                                asn1_ret);\n    }\n\n    return ret;\n}\n\n/**\n * SignerInfos ::= SET of SignerInfo\n * Return number of signers added to the signed data,\n * 0 or higher is valid.\n * Return negative error code for failure.\n **/\nstatic int pkcs7_get_signers_info_set(unsigned char **p, unsigned char *end,\n                                      mbedtls_pkcs7_signer_info *signers_set,\n                                      mbedtls_x509_buf *digest_alg)\n{\n    unsigned char *end_set;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    int count = 0;\n    size_t len = 0;\n\n    ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED\n                               | MBEDTLS_ASN1_SET);\n    if (ret != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret);\n    }\n\n    /* Detect zero signers */\n    if (len == 0) {\n        return 0;\n    }\n\n    end_set = *p + len;\n\n    ret = pkcs7_get_signer_info(p, end_set, signers_set, digest_alg);\n    if (ret != 0) {\n        return ret;\n    }\n    count++;\n\n    mbedtls_pkcs7_signer_info *prev = signers_set;\n    while (*p != end_set) {\n        mbedtls_pkcs7_signer_info *signer =\n            mbedtls_calloc(1, sizeof(mbedtls_pkcs7_signer_info));\n        if (!signer) {\n            ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;\n            goto cleanup;\n        }\n\n        ret = pkcs7_get_signer_info(p, end_set, signer, digest_alg);\n        if (ret != 0) {\n            mbedtls_free(signer);\n            goto cleanup;\n        }\n        prev->next = signer;\n        prev = signer;\n        count++;\n    }\n\n    return count;\n\ncleanup:\n    pkcs7_free_signer_info(signers_set);\n    mbedtls_pkcs7_signer_info *signer = signers_set->next;\n    while (signer != NULL) {\n        prev = signer;\n        signer = signer->next;\n        pkcs7_free_signer_info(prev);\n        mbedtls_free(prev);\n    }\n    signers_set->next = NULL;\n    return ret;\n}\n\n/**\n * SignedData ::= SEQUENCE {\n *      version Version,\n *      digestAlgorithms DigestAlgorithmIdentifiers,\n *      contentInfo ContentInfo,\n *      certificates\n *              [0] IMPLICIT ExtendedCertificatesAndCertificates\n *                  OPTIONAL,\n *      crls\n *              [0] IMPLICIT CertificateRevocationLists OPTIONAL,\n *      signerInfos SignerInfos }\n */\nstatic int pkcs7_get_signed_data(unsigned char *buf, size_t buflen,\n                                 mbedtls_pkcs7_signed_data *signed_data)\n{\n    unsigned char *p = buf;\n    unsigned char *end = buf + buflen;\n    unsigned char *end_content_info = NULL;\n    size_t len = 0;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_md_type_t md_alg;\n\n    ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED\n                               | MBEDTLS_ASN1_SEQUENCE);\n    if (ret != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);\n    }\n\n    if (p + len != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    /* Get version of signed data */\n    ret = pkcs7_get_version(&p, end, &signed_data->version);\n    if (ret != 0) {\n        return ret;\n    }\n\n    /* Get digest algorithm */\n    ret = pkcs7_get_digest_algorithm_set(&p, end,\n                                         &signed_data->digest_alg_identifiers);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_oid_get_md_alg(&signed_data->digest_alg_identifiers, &md_alg);\n    if (ret != 0) {\n        return MBEDTLS_ERR_PKCS7_INVALID_ALG;\n    }\n\n    mbedtls_pkcs7_buf content_type;\n    memset(&content_type, 0, sizeof(content_type));\n    ret = pkcs7_get_content_info_type(&p, end, &end_content_info, &content_type);\n    if (ret != 0) {\n        return ret;\n    }\n    if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &content_type)) {\n        return MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO;\n    }\n\n    if (p != end_content_info) {\n        /* Determine if valid content is present */\n        ret = mbedtls_asn1_get_tag(&p,\n                                   end_content_info,\n                                   &len,\n                                   MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC);\n        if (ret != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);\n        }\n        p += len;\n        if (p != end_content_info) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);\n        }\n        /* Valid content is present - this is not supported */\n        return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;\n    }\n\n    /* Look for certificates, there may or may not be any */\n    mbedtls_x509_crt_init(&signed_data->certs);\n    ret = pkcs7_get_certificates(&p, end, &signed_data->certs);\n    if (ret < 0) {\n        return ret;\n    }\n\n    signed_data->no_of_certs = ret;\n\n    /*\n     * Currently CRLs are not supported. If CRL exist, the parsing will fail\n     * at next step of getting signers info and return error as invalid\n     * signer info.\n     */\n\n    signed_data->no_of_crls = 0;\n\n    /* Get signers info */\n    ret = pkcs7_get_signers_info_set(&p,\n                                     end,\n                                     &signed_data->signers,\n                                     &signed_data->digest_alg_identifiers);\n    if (ret < 0) {\n        return ret;\n    }\n\n    signed_data->no_of_signers = ret;\n\n    /* Don't permit trailing data */\n    if (p != end) {\n        return MBEDTLS_ERR_PKCS7_INVALID_FORMAT;\n    }\n\n    return 0;\n}\n\nint mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf,\n                            const size_t buflen)\n{\n    unsigned char *p;\n    unsigned char *end;\n    size_t len = 0;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (pkcs7 == NULL) {\n        return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;\n    }\n\n    /* make an internal copy of the buffer for parsing */\n    pkcs7->raw.p = p = mbedtls_calloc(1, buflen);\n    if (pkcs7->raw.p == NULL) {\n        ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;\n        goto out;\n    }\n    memcpy(p, buf, buflen);\n    pkcs7->raw.len = buflen;\n    end = p + buflen;\n\n    ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED\n                               | MBEDTLS_ASN1_SEQUENCE);\n    if (ret != 0) {\n        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);\n        goto out;\n    }\n\n    if ((size_t) (end - p) != len) {\n        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,\n                                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n        goto out;\n    }\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {\n        if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n            goto out;\n        }\n        p = pkcs7->raw.p;\n        len = buflen;\n        goto try_data;\n    }\n\n    if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_DATA, p, len)) {\n        /* OID is not MBEDTLS_OID_PKCS7_SIGNED_DATA, which is the only supported feature */\n        if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DATA, p, len)\n            || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, p, len)\n            || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENVELOPED_DATA, p, len)\n            || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, p, len)\n            || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DIGESTED_DATA, p, len)) {\n            /* OID is valid according to the spec, but unsupported */\n            ret =  MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;\n        } else {\n            /* OID is invalid according to the spec */\n            ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;\n        }\n        goto out;\n    }\n\n    p += len;\n\n    ret = pkcs7_get_next_content_len(&p, end, &len);\n    if (ret != 0) {\n        goto out;\n    }\n\n    /* ensure no extra/missing data */\n    if (p + len != end) {\n        ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;\n        goto out;\n    }\n\ntry_data:\n    ret = pkcs7_get_signed_data(p, len, &pkcs7->signed_data);\n    if (ret != 0) {\n        goto out;\n    }\n\n    ret = MBEDTLS_PKCS7_SIGNED_DATA;\n\nout:\n    if (ret < 0) {\n        mbedtls_pkcs7_free(pkcs7);\n    }\n\n    return ret;\n}\n\nstatic int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7,\n                                             const mbedtls_x509_crt *cert,\n                                             const unsigned char *data,\n                                             size_t datalen,\n                                             const int is_data_hash)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *hash;\n    mbedtls_pk_context pk_cxt = cert->pk;\n    const mbedtls_md_info_t *md_info;\n    mbedtls_md_type_t md_alg;\n    mbedtls_pkcs7_signer_info *signer;\n\n    if (pkcs7->signed_data.no_of_signers == 0) {\n        return MBEDTLS_ERR_PKCS7_INVALID_CERT;\n    }\n\n    if (mbedtls_x509_time_is_past(&cert->valid_to) ||\n        mbedtls_x509_time_is_future(&cert->valid_from)) {\n        return MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID;\n    }\n\n    ret = mbedtls_oid_get_md_alg(&pkcs7->signed_data.digest_alg_identifiers, &md_alg);\n    if (ret != 0) {\n        return ret;\n    }\n\n    md_info = mbedtls_md_info_from_type(md_alg);\n    if (md_info == NULL) {\n        return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;\n    }\n\n    hash = mbedtls_calloc(mbedtls_md_get_size(md_info), 1);\n    if (hash == NULL) {\n        return MBEDTLS_ERR_PKCS7_ALLOC_FAILED;\n    }\n\n    /* BEGIN must free hash before jumping out */\n    if (is_data_hash) {\n        if (datalen != mbedtls_md_get_size(md_info)) {\n            ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;\n        } else {\n            memcpy(hash, data, datalen);\n        }\n    } else {\n        ret = mbedtls_md(md_info, data, datalen, hash);\n    }\n    if (ret != 0) {\n        mbedtls_free(hash);\n        return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;\n    }\n\n    /* assume failure */\n    ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;\n\n    /*\n     * Potential TODOs\n     * Currently we iterate over all signers and return success if any of them\n     * verify.\n     *\n     * However, we could make this better by checking against the certificate's\n     * identification and SignerIdentifier fields first. That would also allow\n     * us to distinguish between 'no signature for key' and 'signature for key\n     * failed to validate'.\n     */\n    for (signer = &pkcs7->signed_data.signers; signer; signer = signer->next) {\n        ret = mbedtls_pk_verify(&pk_cxt, md_alg, hash,\n                                mbedtls_md_get_size(md_info),\n                                signer->sig.p, signer->sig.len);\n\n        if (ret == 0) {\n            break;\n        }\n    }\n\n    mbedtls_free(hash);\n    /* END must free hash before jumping out */\n    return ret;\n}\n\nint mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7,\n                                     const mbedtls_x509_crt *cert,\n                                     const unsigned char *data,\n                                     size_t datalen)\n{\n    if (data == NULL) {\n        return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;\n    }\n    return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, data, datalen, 0);\n}\n\nint mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7,\n                                     const mbedtls_x509_crt *cert,\n                                     const unsigned char *hash,\n                                     size_t hashlen)\n{\n    if (hash == NULL) {\n        return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;\n    }\n    return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, hash, hashlen, 1);\n}\n\n/*\n * Unallocate all pkcs7 data\n */\nvoid mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7)\n{\n    mbedtls_pkcs7_signer_info *signer_cur;\n    mbedtls_pkcs7_signer_info *signer_prev;\n\n    if (pkcs7 == NULL || pkcs7->raw.p == NULL) {\n        return;\n    }\n\n    mbedtls_free(pkcs7->raw.p);\n\n    mbedtls_x509_crt_free(&pkcs7->signed_data.certs);\n    mbedtls_x509_crl_free(&pkcs7->signed_data.crl);\n\n    signer_cur = pkcs7->signed_data.signers.next;\n    pkcs7_free_signer_info(&pkcs7->signed_data.signers);\n    while (signer_cur != NULL) {\n        signer_prev = signer_cur;\n        signer_cur = signer_prev->next;\n        pkcs7_free_signer_info(signer_prev);\n        mbedtls_free(signer_prev);\n    }\n\n    pkcs7->raw.p = NULL;\n}\n\n#endif\n"
  },
  {
    "path": "thirdparty/mbedtls/library/pkparse.c",
    "content": "/*\n *  Public Key layer for parsing key files and structures\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PK_PARSE_C)\n\n#include \"mbedtls/pk.h\"\n#include \"mbedtls/asn1.h\"\n#include \"mbedtls/oid.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/platform.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/ecp.h\"\n#include \"pk_internal.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"mbedtls/psa_util.h\"\n#include \"psa/crypto.h\"\n#endif\n\n/* Key types */\n#if defined(MBEDTLS_RSA_C)\n#include \"mbedtls/rsa.h\"\n#include \"rsa_internal.h\"\n#endif\n\n/* Extended formats */\n#if defined(MBEDTLS_PEM_PARSE_C)\n#include \"mbedtls/pem.h\"\n#endif\n#if defined(MBEDTLS_PKCS5_C)\n#include \"mbedtls/pkcs5.h\"\n#endif\n#if defined(MBEDTLS_PKCS12_C)\n#include \"mbedtls/pkcs12.h\"\n#endif\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n\n/***********************************************************************\n *\n *      Low-level ECC parsing: optional support for SpecifiedECDomain\n *\n * There are two functions here that are used by the rest of the code:\n * - pk_ecc_tag_is_speficied_ec_domain()\n * - pk_ecc_group_id_from_specified()\n *\n * All the other functions are internal to this section.\n *\n * The two \"public\" functions have a dummy variant provided\n * in configs without MBEDTLS_PK_PARSE_EC_EXTENDED. This acts as an\n * abstraction layer for this macro, which should not appear outside\n * this section.\n *\n **********************************************************************/\n\n#if !defined(MBEDTLS_PK_PARSE_EC_EXTENDED)\n/* See the \"real\" version for documentation */\nstatic int pk_ecc_tag_is_specified_ec_domain(int tag)\n{\n    (void) tag;\n    return 0;\n}\n\n/* See the \"real\" version for documentation */\nstatic int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params,\n                                          mbedtls_ecp_group_id *grp_id)\n{\n    (void) params;\n    (void) grp_id;\n    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n}\n#else /* MBEDTLS_PK_PARSE_EC_EXTENDED */\n/*\n * Tell if the passed tag might be the start of SpecifiedECDomain\n * (that is, a sequence).\n */\nstatic int pk_ecc_tag_is_specified_ec_domain(int tag)\n{\n    return tag == (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);\n}\n\n/*\n * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it.\n * WARNING: the resulting group should only be used with\n * pk_ecc_group_id_from_specified(), since its base point may not be set correctly\n * if it was encoded compressed.\n *\n *  SpecifiedECDomain ::= SEQUENCE {\n *      version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...),\n *      fieldID FieldID {{FieldTypes}},\n *      curve Curve,\n *      base ECPoint,\n *      order INTEGER,\n *      cofactor INTEGER OPTIONAL,\n *      hash HashAlgorithm OPTIONAL,\n *      ...\n *  }\n *\n * We only support prime-field as field type, and ignore hash and cofactor.\n */\nstatic int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = params->p;\n    const unsigned char *const end = params->p + params->len;\n    const unsigned char *end_field, *end_curve;\n    size_t len;\n    int ver;\n\n    /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */\n    if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    if (ver < 1 || ver > 3) {\n        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;\n    }\n\n    /*\n     * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field\n     *       fieldType FIELD-ID.&id({IOSet}),\n     *       parameters FIELD-ID.&Type({IOSet}{@fieldType})\n     * }\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return ret;\n    }\n\n    end_field = p + len;\n\n    /*\n     * FIELD-ID ::= TYPE-IDENTIFIER\n     * FieldTypes FIELD-ID ::= {\n     *       { Prime-p IDENTIFIED BY prime-field } |\n     *       { Characteristic-two IDENTIFIED BY characteristic-two-field }\n     * }\n     * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) != 0) {\n        return ret;\n    }\n\n    if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD) ||\n        memcmp(p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len) != 0) {\n        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n    }\n\n    p += len;\n\n    /* Prime-p ::= INTEGER -- Field of size p. */\n    if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    grp->pbits = mbedtls_mpi_bitlen(&grp->P);\n\n    if (p != end_field) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    /*\n     * Curve ::= SEQUENCE {\n     *       a FieldElement,\n     *       b FieldElement,\n     *       seed BIT STRING OPTIONAL\n     *       -- Shall be present if used in SpecifiedECDomain\n     *       -- with version equal to ecdpVer2 or ecdpVer3\n     * }\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return ret;\n    }\n\n    end_curve = p + len;\n\n    /*\n     * FieldElement ::= OCTET STRING\n     * containing an integer in the case of a prime field\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 ||\n        (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    p += len;\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 ||\n        (ret = mbedtls_mpi_read_binary(&grp->B, p, len)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    p += len;\n\n    /* Ignore seed BIT STRING OPTIONAL */\n    if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING)) == 0) {\n        p += len;\n    }\n\n    if (p != end_curve) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    /*\n     * ECPoint ::= OCTET STRING\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    if ((ret = mbedtls_ecp_point_read_binary(grp, &grp->G,\n                                             (const unsigned char *) p, len)) != 0) {\n        /*\n         * If we can't read the point because it's compressed, cheat by\n         * reading only the X coordinate and the parity bit of Y.\n         */\n        if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ||\n            (p[0] != 0x02 && p[0] != 0x03) ||\n            len != mbedtls_mpi_size(&grp->P) + 1 ||\n            mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 ||\n            mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 ||\n            mbedtls_mpi_lset(&grp->G.Z, 1) != 0) {\n            return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;\n        }\n    }\n\n    p += len;\n\n    /*\n     * order INTEGER\n     */\n    if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    grp->nbits = mbedtls_mpi_bitlen(&grp->N);\n\n    /*\n     * Allow optional elements by purposefully not enforcing p == end here.\n     */\n\n    return 0;\n}\n\n/*\n * Find the group id associated with an (almost filled) group as generated by\n * pk_group_from_specified(), or return an error if unknown.\n */\nstatic int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id)\n{\n    int ret = 0;\n    mbedtls_ecp_group ref;\n    const mbedtls_ecp_group_id *id;\n\n    mbedtls_ecp_group_init(&ref);\n\n    for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) {\n        /* Load the group associated to that id */\n        mbedtls_ecp_group_free(&ref);\n        MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id));\n\n        /* Compare to the group we were given, starting with easy tests */\n        if (grp->pbits == ref.pbits && grp->nbits == ref.nbits &&\n            mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 &&\n            mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 &&\n            mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 &&\n            mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 &&\n            mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 &&\n            mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 &&\n            /* For Y we may only know the parity bit, so compare only that */\n            mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) {\n            break;\n        }\n    }\n\ncleanup:\n    mbedtls_ecp_group_free(&ref);\n\n    *grp_id = *id;\n\n    if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE) {\n        ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n    }\n\n    return ret;\n}\n\n/*\n * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID\n */\nstatic int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params,\n                                          mbedtls_ecp_group_id *grp_id)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_group grp;\n\n    mbedtls_ecp_group_init(&grp);\n\n    if ((ret = pk_group_from_specified(params, &grp)) != 0) {\n        goto cleanup;\n    }\n\n    ret = pk_group_id_from_group(&grp, grp_id);\n\ncleanup:\n    /* The API respecting lifecycle for mbedtls_ecp_group struct is\n     * _init(), _load() and _free(). In pk_ecc_group_id_from_specified() the\n     * temporary grp breaks that flow and it's members are populated\n     * by pk_group_id_from_group(). As such mbedtls_ecp_group_free()\n     * which is assuming a group populated by _setup() may not clean-up\n     * properly -> Manually free it's members.\n     */\n    mbedtls_mpi_free(&grp.N);\n    mbedtls_mpi_free(&grp.P);\n    mbedtls_mpi_free(&grp.A);\n    mbedtls_mpi_free(&grp.B);\n    mbedtls_ecp_point_free(&grp.G);\n\n    return ret;\n}\n#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */\n\n/***********************************************************************\n *\n * Unsorted (yet!) from this point on until the next section header\n *\n **********************************************************************/\n\n/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf\n *\n * ECParameters ::= CHOICE {\n *   namedCurve         OBJECT IDENTIFIER\n *   specifiedCurve     SpecifiedECDomain -- = SEQUENCE { ... }\n *   -- implicitCurve   NULL\n * }\n */\nstatic int pk_get_ecparams(unsigned char **p, const unsigned char *end,\n                           mbedtls_asn1_buf *params)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (end - *p < 1) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);\n    }\n\n    /* Acceptable tags: OID for namedCurve, or specifiedECDomain */\n    params->tag = **p;\n    if (params->tag != MBEDTLS_ASN1_OID &&\n        !pk_ecc_tag_is_specified_ec_domain(params->tag)) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);\n    }\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &params->len, params->tag)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    params->p = *p;\n    *p += params->len;\n\n    if (*p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n/*\n * Use EC parameters to initialise an EC group\n *\n * ECParameters ::= CHOICE {\n *   namedCurve         OBJECT IDENTIFIER\n *   specifiedCurve     SpecifiedECDomain -- = SEQUENCE { ... }\n *   -- implicitCurve   NULL\n */\nstatic int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_pk_context *pk)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_group_id grp_id;\n\n    if (params->tag == MBEDTLS_ASN1_OID) {\n        if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) {\n            return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE;\n        }\n    } else {\n        ret = pk_ecc_group_id_from_specified(params, &grp_id);\n        if (ret != 0) {\n            return ret;\n        }\n    }\n\n    return mbedtls_pk_ecc_set_group(pk, grp_id);\n}\n\n#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)\n\n/*\n * Load an RFC8410 EC key, which doesn't have any parameters\n */\nstatic int pk_use_ecparams_rfc8410(const mbedtls_asn1_buf *params,\n                                   mbedtls_ecp_group_id grp_id,\n                                   mbedtls_pk_context *pk)\n{\n    if (params->tag != 0 || params->len != 0) {\n        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;\n    }\n\n    return mbedtls_pk_ecc_set_group(pk, grp_id);\n}\n\n/*\n * Parse an RFC 8410 encoded private EC key\n *\n * CurvePrivateKey ::= OCTET STRING\n */\nstatic int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk,\n                                    unsigned char *key, size_t keylen, const unsigned char *end,\n                                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n\n    if ((ret = mbedtls_asn1_get_tag(&key, (key + keylen), &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    if (key + len != end) {\n        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;\n    }\n\n    /*\n     * Load the private key\n     */\n    ret = mbedtls_pk_ecc_set_key(pk, key, len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    /* pk_parse_key_pkcs8_unencrypted_der() only supports version 1 PKCS8 keys,\n     * which never contain a public key. As such, derive the public key\n     * unconditionally. */\n    if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, key, len, f_rng, p_rng)) != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */\n\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n/* Get a PK algorithm identifier\n *\n *  AlgorithmIdentifier  ::=  SEQUENCE  {\n *       algorithm               OBJECT IDENTIFIER,\n *       parameters              ANY DEFINED BY algorithm OPTIONAL  }\n */\nstatic int pk_get_pk_alg(unsigned char **p,\n                         const unsigned char *end,\n                         mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params,\n                         mbedtls_ecp_group_id *ec_grp_id)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_asn1_buf alg_oid;\n\n    memset(params, 0, sizeof(mbedtls_asn1_buf));\n\n    if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret);\n    }\n\n    ret = mbedtls_oid_get_pk_alg(&alg_oid, pk_alg);\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    if (ret == MBEDTLS_ERR_OID_NOT_FOUND) {\n        ret = mbedtls_oid_get_ec_grp_algid(&alg_oid, ec_grp_id);\n        if (ret == 0) {\n            *pk_alg = MBEDTLS_PK_ECKEY;\n        }\n    }\n#else\n    (void) ec_grp_id;\n#endif\n    if (ret != 0) {\n        return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;\n    }\n\n    /*\n     * No parameters with RSA (only for EC)\n     */\n    if (*pk_alg == MBEDTLS_PK_RSA &&\n        ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) ||\n         params->len != 0)) {\n        return MBEDTLS_ERR_PK_INVALID_ALG;\n    }\n\n    return 0;\n}\n\n/*\n *  SubjectPublicKeyInfo  ::=  SEQUENCE  {\n *       algorithm            AlgorithmIdentifier,\n *       subjectPublicKey     BIT STRING }\n */\nint mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,\n                               mbedtls_pk_context *pk)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n    mbedtls_asn1_buf alg_params;\n    mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;\n    mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;\n    const mbedtls_pk_info_t *pk_info;\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    end = *p + len;\n\n    if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params, &ec_grp_id)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);\n    }\n\n    if (*p + len != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) {\n        return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;\n    }\n\n    if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) {\n        return ret;\n    }\n\n#if defined(MBEDTLS_RSA_C)\n    if (pk_alg == MBEDTLS_PK_RSA) {\n        ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), *p, (size_t) (end - *p));\n        if (ret == 0) {\n            /* On success all the input has been consumed by the parsing function. */\n            *p += end - *p;\n        } else if ((ret <= MBEDTLS_ERR_ASN1_OUT_OF_DATA) &&\n                   (ret >= MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)) {\n            /* In case of ASN1 error codes add MBEDTLS_ERR_PK_INVALID_PUBKEY. */\n            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);\n        } else {\n            ret = MBEDTLS_ERR_PK_INVALID_PUBKEY;\n        }\n    } else\n#endif /* MBEDTLS_RSA_C */\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) {\n#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)\n        if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {\n            ret = pk_use_ecparams_rfc8410(&alg_params, ec_grp_id, pk);\n        } else\n#endif\n        {\n            ret = pk_use_ecparams(&alg_params, pk);\n        }\n        if (ret == 0) {\n            ret = mbedtls_pk_ecc_set_pubkey(pk, *p, (size_t) (end - *p));\n            *p += end - *p;\n        }\n    } else\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n    ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;\n\n    if (ret == 0 && *p != end) {\n        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,\n                                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    if (ret != 0) {\n        mbedtls_pk_free(pk);\n    }\n\n    return ret;\n}\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n/*\n * Parse a SEC1 encoded private EC key\n */\nstatic int pk_parse_key_sec1_der(mbedtls_pk_context *pk,\n                                 const unsigned char *key, size_t keylen,\n                                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    int version, pubkey_done;\n    size_t len, d_len;\n    mbedtls_asn1_buf params = { 0, 0, NULL };\n    unsigned char *p = (unsigned char *) key;\n    unsigned char *d;\n    unsigned char *end = p + keylen;\n    unsigned char *end2;\n\n    /*\n     * RFC 5915, or SEC1 Appendix C.4\n     *\n     * ECPrivateKey ::= SEQUENCE {\n     *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),\n     *      privateKey     OCTET STRING,\n     *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,\n     *      publicKey  [1] BIT STRING OPTIONAL\n     *    }\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    end = p + len;\n\n    if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    if (version != 1) {\n        return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;\n    }\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    /* Keep a reference to the position fo the private key. It will be used\n     * later in this function. */\n    d = p;\n    d_len = len;\n\n    p += len;\n\n    pubkey_done = 0;\n    if (p != end) {\n        /*\n         * Is 'parameters' present?\n         */\n        if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                        MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |\n                                        0)) == 0) {\n            if ((ret = pk_get_ecparams(&p, p + len, &params)) != 0 ||\n                (ret = pk_use_ecparams(&params, pk)) != 0) {\n                return ret;\n            }\n        } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n        }\n    }\n\n    /*\n     * Load the private key\n     */\n    ret = mbedtls_pk_ecc_set_key(pk, d, d_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    if (p != end) {\n        /*\n         * Is 'publickey' present? If not, or if we can't read it (eg because it\n         * is compressed), create it from the private key.\n         */\n        if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                        MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |\n                                        1)) == 0) {\n            end2 = p + len;\n\n            if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) {\n                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n            }\n\n            if (p + len != end2) {\n                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,\n                                         MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n            }\n\n            if ((ret = mbedtls_pk_ecc_set_pubkey(pk, p, (size_t) (end2 - p))) == 0) {\n                pubkey_done = 1;\n            } else {\n                /*\n                 * The only acceptable failure mode of mbedtls_pk_ecc_set_pubkey() above\n                 * is if the point format is not recognized.\n                 */\n                if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) {\n                    return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;\n                }\n            }\n        } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n        }\n    }\n\n    if (!pubkey_done) {\n        if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, d, d_len, f_rng, p_rng)) != 0) {\n            return ret;\n        }\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n/***********************************************************************\n *\n *      PKCS#8 parsing functions\n *\n **********************************************************************/\n\n/*\n * Parse an unencrypted PKCS#8 encoded private key\n *\n * Notes:\n *\n * - This function does not own the key buffer. It is the\n *   responsibility of the caller to take care of zeroizing\n *   and freeing it after use.\n *\n * - The function is responsible for freeing the provided\n *   PK context on failure.\n *\n */\nstatic int pk_parse_key_pkcs8_unencrypted_der(\n    mbedtls_pk_context *pk,\n    const unsigned char *key, size_t keylen,\n    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    int ret, version;\n    size_t len;\n    mbedtls_asn1_buf params;\n    unsigned char *p = (unsigned char *) key;\n    unsigned char *end = p + keylen;\n    mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;\n    mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;\n    const mbedtls_pk_info_t *pk_info;\n\n#if !defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    (void) f_rng;\n    (void) p_rng;\n#endif\n\n    /*\n     * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208)\n     *\n     *    PrivateKeyInfo ::= SEQUENCE {\n     *      version                   Version,\n     *      privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,\n     *      privateKey                PrivateKey,\n     *      attributes           [0]  IMPLICIT Attributes OPTIONAL }\n     *\n     *    Version ::= INTEGER\n     *    PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier\n     *    PrivateKey ::= OCTET STRING\n     *\n     *  The PrivateKey OCTET STRING is a SEC1 ECPrivateKey\n     */\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    end = p + len;\n\n    if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    if (version != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret);\n    }\n\n    if ((ret = pk_get_pk_alg(&p, end, &pk_alg, &params, &ec_grp_id)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    if (len < 1) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);\n    }\n\n    if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) {\n        return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;\n    }\n\n    if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) {\n        return ret;\n    }\n\n#if defined(MBEDTLS_RSA_C)\n    if (pk_alg == MBEDTLS_PK_RSA) {\n        if ((ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), p, len)) != 0) {\n            mbedtls_pk_free(pk);\n            return ret;\n        }\n    } else\n#endif /* MBEDTLS_RSA_C */\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) {\n#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)\n        if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {\n            if ((ret =\n                     pk_use_ecparams_rfc8410(&params, ec_grp_id, pk)) != 0 ||\n                (ret =\n                     pk_parse_key_rfc8410_der(pk, p, len, end, f_rng,\n                                              p_rng)) != 0) {\n                mbedtls_pk_free(pk);\n                return ret;\n            }\n        } else\n#endif\n        {\n            if ((ret = pk_use_ecparams(&params, pk)) != 0 ||\n                (ret = pk_parse_key_sec1_der(pk, p, len, f_rng, p_rng)) != 0) {\n                mbedtls_pk_free(pk);\n                return ret;\n            }\n        }\n    } else\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n    return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;\n\n    end = p + len;\n    if (end != (key + keylen)) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n/*\n * Parse an encrypted PKCS#8 encoded private key\n *\n * To save space, the decryption happens in-place on the given key buffer.\n * Also, while this function may modify the keybuffer, it doesn't own it,\n * and instead it is the responsibility of the caller to zeroize and properly\n * free it after use.\n *\n */\n#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)\nMBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der(\n    mbedtls_pk_context *pk,\n    unsigned char *key, size_t keylen,\n    const unsigned char *pwd, size_t pwdlen,\n    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    int ret, decrypted = 0;\n    size_t len;\n    unsigned char *buf;\n    unsigned char *p, *end;\n    mbedtls_asn1_buf pbe_alg_oid, pbe_params;\n#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)\n    mbedtls_cipher_type_t cipher_alg;\n    mbedtls_md_type_t md_alg;\n#endif\n    size_t outlen = 0;\n\n    p = key;\n    end = p + keylen;\n\n    if (pwdlen == 0) {\n        return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;\n    }\n\n    /*\n     * This function parses the EncryptedPrivateKeyInfo object (PKCS#8)\n     *\n     *  EncryptedPrivateKeyInfo ::= SEQUENCE {\n     *    encryptionAlgorithm  EncryptionAlgorithmIdentifier,\n     *    encryptedData        EncryptedData\n     *  }\n     *\n     *  EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier\n     *\n     *  EncryptedData ::= OCTET STRING\n     *\n     *  The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo\n     *\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    end = p + len;\n\n    if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);\n    }\n\n    buf = p;\n\n    /*\n     * Decrypt EncryptedData with appropriate PBE\n     */\n#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)\n    if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) {\n        if ((ret = mbedtls_pkcs12_pbe_ext(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,\n                                          cipher_alg, md_alg,\n                                          pwd, pwdlen, p, len, buf, len, &outlen)) != 0) {\n            if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) {\n                return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;\n            }\n\n            return ret;\n        }\n\n        decrypted = 1;\n    } else\n#endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */\n#if defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)\n    if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) {\n        if ((ret = mbedtls_pkcs5_pbes2_ext(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,\n                                           p, len, buf, len, &outlen)) != 0) {\n            if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) {\n                return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;\n            }\n\n            return ret;\n        }\n\n        decrypted = 1;\n    } else\n#endif /* MBEDTLS_PKCS5_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */\n    {\n        ((void) pwd);\n    }\n\n    if (decrypted == 0) {\n        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n    }\n    return pk_parse_key_pkcs8_unencrypted_der(pk, buf, outlen, f_rng, p_rng);\n}\n#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */\n\n/***********************************************************************\n *\n *      Top-level functions, with format auto-discovery\n *\n **********************************************************************/\n\n/*\n * Parse a private key\n */\nint mbedtls_pk_parse_key(mbedtls_pk_context *pk,\n                         const unsigned char *key, size_t keylen,\n                         const unsigned char *pwd, size_t pwdlen,\n                         int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const mbedtls_pk_info_t *pk_info;\n#if defined(MBEDTLS_PEM_PARSE_C)\n    size_t len;\n    mbedtls_pem_context pem;\n#endif\n\n    if (keylen == 0) {\n        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;\n    }\n\n#if defined(MBEDTLS_PEM_PARSE_C)\n    mbedtls_pem_init(&pem);\n\n#if defined(MBEDTLS_RSA_C)\n    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */\n    if (key[keylen - 1] != '\\0') {\n        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;\n    } else {\n        ret = mbedtls_pem_read_buffer(&pem,\n                                      PEM_BEGIN_PRIVATE_KEY_RSA, PEM_END_PRIVATE_KEY_RSA,\n                                      key, pwd, pwdlen, &len);\n    }\n\n    if (ret == 0) {\n        pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);\n        if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||\n            (ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk),\n                                         pem.buf, pem.buflen)) != 0) {\n            mbedtls_pk_free(pk);\n        }\n\n        mbedtls_pem_free(&pem);\n        return ret;\n    } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {\n        return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;\n    } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {\n        return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;\n    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {\n        return ret;\n    }\n#endif /* MBEDTLS_RSA_C */\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */\n    if (key[keylen - 1] != '\\0') {\n        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;\n    } else {\n        ret = mbedtls_pem_read_buffer(&pem,\n                                      PEM_BEGIN_PRIVATE_KEY_EC,\n                                      PEM_END_PRIVATE_KEY_EC,\n                                      key, pwd, pwdlen, &len);\n    }\n    if (ret == 0) {\n        pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);\n\n        if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||\n            (ret = pk_parse_key_sec1_der(pk,\n                                         pem.buf, pem.buflen,\n                                         f_rng, p_rng)) != 0) {\n            mbedtls_pk_free(pk);\n        }\n\n        mbedtls_pem_free(&pem);\n        return ret;\n    } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {\n        return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;\n    } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {\n        return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;\n    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {\n        return ret;\n    }\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */\n    if (key[keylen - 1] != '\\0') {\n        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;\n    } else {\n        ret = mbedtls_pem_read_buffer(&pem,\n                                      PEM_BEGIN_PRIVATE_KEY_PKCS8, PEM_END_PRIVATE_KEY_PKCS8,\n                                      key, NULL, 0, &len);\n    }\n    if (ret == 0) {\n        if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk,\n                                                      pem.buf, pem.buflen, f_rng, p_rng)) != 0) {\n            mbedtls_pk_free(pk);\n        }\n\n        mbedtls_pem_free(&pem);\n        return ret;\n    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {\n        return ret;\n    }\n\n#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)\n    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */\n    if (key[keylen - 1] != '\\0') {\n        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;\n    } else {\n        ret = mbedtls_pem_read_buffer(&pem,\n                                      PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8,\n                                      PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8,\n                                      key, NULL, 0, &len);\n    }\n    if (ret == 0) {\n        if ((ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen,\n                                                            pwd, pwdlen, f_rng, p_rng)) != 0) {\n            mbedtls_pk_free(pk);\n        }\n\n        mbedtls_pem_free(&pem);\n        return ret;\n    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {\n        return ret;\n    }\n#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */\n#else\n    ((void) pwd);\n    ((void) pwdlen);\n#endif /* MBEDTLS_PEM_PARSE_C */\n\n    /*\n     * At this point we only know it's not a PEM formatted key. Could be any\n     * of the known DER encoded private key formats\n     *\n     * We try the different DER format parsers to see if one passes without\n     * error\n     */\n#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)\n    if (pwdlen != 0) {\n        unsigned char *key_copy;\n\n        if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) {\n            return MBEDTLS_ERR_PK_ALLOC_FAILED;\n        }\n\n        memcpy(key_copy, key, keylen);\n\n        ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen,\n                                                       pwd, pwdlen, f_rng, p_rng);\n\n        mbedtls_zeroize_and_free(key_copy, keylen);\n    }\n\n    if (ret == 0) {\n        return 0;\n    }\n\n    mbedtls_pk_free(pk);\n    mbedtls_pk_init(pk);\n\n    if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) {\n        return ret;\n    }\n#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */\n\n    ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen, f_rng, p_rng);\n    if (ret == 0) {\n        return 0;\n    }\n\n    mbedtls_pk_free(pk);\n    mbedtls_pk_init(pk);\n\n#if defined(MBEDTLS_RSA_C)\n\n    pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);\n    if (mbedtls_pk_setup(pk, pk_info) == 0 &&\n        mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), key, keylen) == 0) {\n        return 0;\n    }\n\n    mbedtls_pk_free(pk);\n    mbedtls_pk_init(pk);\n#endif /* MBEDTLS_RSA_C */\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);\n    if (mbedtls_pk_setup(pk, pk_info) == 0 &&\n        pk_parse_key_sec1_der(pk,\n                              key, keylen, f_rng, p_rng) == 0) {\n        return 0;\n    }\n    mbedtls_pk_free(pk);\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n    /* If MBEDTLS_RSA_C is defined but MBEDTLS_PK_HAVE_ECC_KEYS isn't,\n     * it is ok to leave the PK context initialized but not\n     * freed: It is the caller's responsibility to call pk_init()\n     * before calling this function, and to call pk_free()\n     * when it fails. If MBEDTLS_PK_HAVE_ECC_KEYS is defined but MBEDTLS_RSA_C\n     * isn't, this leads to mbedtls_pk_free() being called\n     * twice, once here and once by the caller, but this is\n     * also ok and in line with the mbedtls_pk_free() calls\n     * on failed PEM parsing attempts. */\n\n    return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;\n}\n\n/*\n * Parse a public key\n */\nint mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,\n                                const unsigned char *key, size_t keylen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p;\n#if defined(MBEDTLS_RSA_C)\n    const mbedtls_pk_info_t *pk_info;\n#endif\n#if defined(MBEDTLS_PEM_PARSE_C)\n    size_t len;\n    mbedtls_pem_context pem;\n#endif\n\n    if (keylen == 0) {\n        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;\n    }\n\n#if defined(MBEDTLS_PEM_PARSE_C)\n    mbedtls_pem_init(&pem);\n#if defined(MBEDTLS_RSA_C)\n    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */\n    if (key[keylen - 1] != '\\0') {\n        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;\n    } else {\n        ret = mbedtls_pem_read_buffer(&pem,\n                                      PEM_BEGIN_PUBLIC_KEY_RSA, PEM_END_PUBLIC_KEY_RSA,\n                                      key, NULL, 0, &len);\n    }\n\n    if (ret == 0) {\n        p = pem.buf;\n        if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {\n            mbedtls_pem_free(&pem);\n            return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;\n        }\n\n        if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {\n            mbedtls_pem_free(&pem);\n            return ret;\n        }\n\n        if ((ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, pem.buflen)) != 0) {\n            mbedtls_pk_free(ctx);\n        }\n\n        mbedtls_pem_free(&pem);\n        return ret;\n    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {\n        mbedtls_pem_free(&pem);\n        return ret;\n    }\n#endif /* MBEDTLS_RSA_C */\n\n    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */\n    if (key[keylen - 1] != '\\0') {\n        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;\n    } else {\n        ret = mbedtls_pem_read_buffer(&pem,\n                                      PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,\n                                      key, NULL, 0, &len);\n    }\n\n    if (ret == 0) {\n        /*\n         * Was PEM encoded\n         */\n        p = pem.buf;\n\n        ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx);\n        mbedtls_pem_free(&pem);\n        return ret;\n    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {\n        mbedtls_pem_free(&pem);\n        return ret;\n    }\n    mbedtls_pem_free(&pem);\n#endif /* MBEDTLS_PEM_PARSE_C */\n\n#if defined(MBEDTLS_RSA_C)\n    if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {\n        return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;\n    }\n\n    if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {\n        return ret;\n    }\n\n    p = (unsigned char *) key;\n    ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, keylen);\n    if (ret == 0) {\n        return ret;\n    }\n    mbedtls_pk_free(ctx);\n    if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n        return ret;\n    }\n#endif /* MBEDTLS_RSA_C */\n    p = (unsigned char *) key;\n\n    ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx);\n\n    return ret;\n}\n\n/***********************************************************************\n *\n *      Top-level functions, with filesystem support\n *\n **********************************************************************/\n\n#if defined(MBEDTLS_FS_IO)\n/*\n * Load all data from a file into a given buffer.\n *\n * The file is expected to contain either PEM or DER encoded data.\n * A terminating null byte is always appended. It is included in the announced\n * length only if the data looks like it is PEM encoded.\n */\nint mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n)\n{\n    FILE *f;\n    long size;\n\n    if ((f = fopen(path, \"rb\")) == NULL) {\n        return MBEDTLS_ERR_PK_FILE_IO_ERROR;\n    }\n\n    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */\n    mbedtls_setbuf(f, NULL);\n\n    fseek(f, 0, SEEK_END);\n    if ((size = ftell(f)) == -1) {\n        fclose(f);\n        return MBEDTLS_ERR_PK_FILE_IO_ERROR;\n    }\n    fseek(f, 0, SEEK_SET);\n\n    *n = (size_t) size;\n\n    if (*n + 1 == 0 ||\n        (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {\n        fclose(f);\n        return MBEDTLS_ERR_PK_ALLOC_FAILED;\n    }\n\n    if (fread(*buf, 1, *n, f) != *n) {\n        fclose(f);\n\n        mbedtls_zeroize_and_free(*buf, *n);\n\n        return MBEDTLS_ERR_PK_FILE_IO_ERROR;\n    }\n\n    fclose(f);\n\n    (*buf)[*n] = '\\0';\n\n    if (strstr((const char *) *buf, \"-----BEGIN \") != NULL) {\n        ++*n;\n    }\n\n    return 0;\n}\n\n/*\n * Load and parse a private key\n */\nint mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx,\n                             const char *path, const char *pwd,\n                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t n;\n    unsigned char *buf;\n\n    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {\n        return ret;\n    }\n\n    if (pwd == NULL) {\n        ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng);\n    } else {\n        ret = mbedtls_pk_parse_key(ctx, buf, n,\n                                   (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng);\n    }\n\n    mbedtls_zeroize_and_free(buf, n);\n\n    return ret;\n}\n\n/*\n * Load and parse a public key\n */\nint mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t n;\n    unsigned char *buf;\n\n    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_pk_parse_public_key(ctx, buf, n);\n\n    mbedtls_zeroize_and_free(buf, n);\n\n    return ret;\n}\n#endif /* MBEDTLS_FS_IO */\n\n#endif /* MBEDTLS_PK_PARSE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/pkwrite.c",
    "content": "/*\n *  Public Key layer for writing key files and structures\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PK_WRITE_C)\n\n#include \"mbedtls/pk.h\"\n#include \"mbedtls/asn1write.h\"\n#include \"mbedtls/oid.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n#include \"pk_internal.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_ECP_C)\n#include \"mbedtls/bignum.h\"\n#include \"mbedtls/ecp.h\"\n#include \"mbedtls/platform_util.h\"\n#endif\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n#include \"pk_internal.h\"\n#endif\n#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n#include \"pkwrite.h\"\n#endif\n#if defined(MBEDTLS_PEM_WRITE_C)\n#include \"mbedtls/pem.h\"\n#endif\n#if defined(MBEDTLS_RSA_C)\n#include \"rsa_internal.h\"\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"psa/crypto.h\"\n#include \"psa_util_internal.h\"\n#endif\n#include \"mbedtls/platform.h\"\n\n/* Helpers for properly sizing buffers aimed at holding public keys or\n * key-pairs based on build symbols. */\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n#define PK_MAX_EC_PUBLIC_KEY_SIZE       PSA_EXPORT_PUBLIC_KEY_MAX_SIZE\n#define PK_MAX_EC_KEY_PAIR_SIZE         MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH\n#elif defined(MBEDTLS_USE_PSA_CRYPTO)\n#define PK_MAX_EC_PUBLIC_KEY_SIZE       PSA_EXPORT_PUBLIC_KEY_MAX_SIZE\n#define PK_MAX_EC_KEY_PAIR_SIZE         MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH\n#else\n#define PK_MAX_EC_PUBLIC_KEY_SIZE       MBEDTLS_ECP_MAX_PT_LEN\n#define PK_MAX_EC_KEY_PAIR_SIZE         MBEDTLS_ECP_MAX_BYTES\n#endif\n\n/******************************************************************************\n * Internal functions for RSA keys.\n ******************************************************************************/\n#if defined(MBEDTLS_RSA_C)\nstatic int pk_write_rsa_der(unsigned char **p, unsigned char *buf,\n                            const mbedtls_pk_context *pk)\n{\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {\n        uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE];\n        size_t tmp_len = 0;\n\n        if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) {\n            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n        }\n        /* Ensure there's enough space in the provided buffer before copying data into it. */\n        if (tmp_len > (size_t) (*p - buf)) {\n            mbedtls_platform_zeroize(tmp, sizeof(tmp));\n            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n        }\n        *p -= tmp_len;\n        memcpy(*p, tmp, tmp_len);\n        mbedtls_platform_zeroize(tmp, sizeof(tmp));\n\n        return (int) tmp_len;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    return mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), buf, p);\n}\n#endif /* MBEDTLS_RSA_C */\n\n/******************************************************************************\n * Internal functions for EC keys.\n ******************************************************************************/\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\nstatic int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,\n                              const mbedtls_pk_context *pk)\n{\n    size_t len = 0;\n    uint8_t buf[PK_MAX_EC_PUBLIC_KEY_SIZE];\n\n    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {\n        if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {\n            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n        }\n    } else {\n        len = pk->pub_raw_len;\n        memcpy(buf, pk->pub_raw, len);\n    }\n\n    if (*p < start || (size_t) (*p - start) < len) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n\n    *p -= len;\n    memcpy(*p, buf, len);\n\n    return (int) len;\n}\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\nstatic int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,\n                              const mbedtls_pk_context *pk)\n{\n    size_t len = 0;\n    unsigned char buf[PK_MAX_EC_PUBLIC_KEY_SIZE];\n    mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk);\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {\n        if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {\n            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n        }\n        /* Ensure there's enough space in the provided buffer before copying data into it. */\n        if (len > (size_t) (*p - start)) {\n            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n        }\n        *p -= len;\n        memcpy(*p, buf, len);\n        return (int) len;\n    } else\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    {\n        if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,\n                                                  MBEDTLS_ECP_PF_UNCOMPRESSED,\n                                                  &len, buf, sizeof(buf))) != 0) {\n            return ret;\n        }\n    }\n\n    if (*p < start || (size_t) (*p - start) < len) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n\n    *p -= len;\n    memcpy(*p, buf, len);\n\n    return (int) len;\n}\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n\n/*\n * privateKey  OCTET STRING -- always of length ceil(log2(n)/8)\n */\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\nstatic int pk_write_ec_private(unsigned char **p, unsigned char *start,\n                               const mbedtls_pk_context *pk)\n{\n    size_t byte_length;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];\n    psa_status_t status;\n\n    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {\n        status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);\n        if (status != PSA_SUCCESS) {\n            ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);\n            return ret;\n        }\n    } else {\n        status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);\n        if (status != PSA_SUCCESS) {\n            ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);\n            goto exit;\n        }\n    }\n\n    ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);\nexit:\n    mbedtls_platform_zeroize(tmp, sizeof(tmp));\n    return ret;\n}\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\nstatic int pk_write_ec_private(unsigned char **p, unsigned char *start,\n                               const mbedtls_pk_context *pk)\n{\n    size_t byte_length;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_status_t status;\n    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {\n        status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);\n        if (status != PSA_SUCCESS) {\n            ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);\n            return ret;\n        }\n    } else\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    {\n        mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk);\n        byte_length = (ec->grp.pbits + 7) / 8;\n\n        ret = mbedtls_ecp_write_key_ext(ec, &byte_length, tmp, sizeof(tmp));\n        if (ret != 0) {\n            goto exit;\n        }\n    }\n    ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);\nexit:\n    mbedtls_platform_zeroize(tmp, sizeof(tmp));\n    return ret;\n}\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n\n/*\n * ECParameters ::= CHOICE {\n *   namedCurve         OBJECT IDENTIFIER\n * }\n */\nstatic int pk_write_ec_param(unsigned char **p, unsigned char *start,\n                             mbedtls_ecp_group_id grp_id)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n    const char *oid;\n    size_t oid_len;\n\n    if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) {\n        return ret;\n    }\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));\n\n    return (int) len;\n}\n\n#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)\n/*\n * RFC8410 section 7\n *\n * OneAsymmetricKey ::= SEQUENCE {\n *    version Version,\n *    privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,\n *    privateKey PrivateKey,\n *    attributes [0] IMPLICIT Attributes OPTIONAL,\n *    ...,\n *    [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]],\n *    ...\n * }\n * ...\n * CurvePrivateKey ::= OCTET STRING\n */\nstatic int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf,\n                                   const mbedtls_pk_context *pk)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n    size_t oid_len = 0;\n    const char *oid;\n    mbedtls_ecp_group_id grp_id;\n\n    /* privateKey */\n    MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING));\n\n    grp_id = mbedtls_pk_get_ec_group_id(pk);\n    /* privateKeyAlgorithm */\n    if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(grp_id, &oid, &oid_len)) != 0) {\n        return ret;\n    }\n    MBEDTLS_ASN1_CHK_ADD(len,\n                         mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0));\n\n    /* version */\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0));\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |\n                                                     MBEDTLS_ASN1_SEQUENCE));\n\n    return (int) len;\n}\n#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */\n\n/*\n * RFC 5915, or SEC1 Appendix C.4\n *\n * ECPrivateKey ::= SEQUENCE {\n *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),\n *      privateKey     OCTET STRING,\n *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,\n *      publicKey  [1] BIT STRING OPTIONAL\n *    }\n */\nstatic int pk_write_ec_der(unsigned char **p, unsigned char *buf,\n                           const mbedtls_pk_context *pk)\n{\n    size_t len = 0;\n    int ret;\n    size_t pub_len = 0, par_len = 0;\n    mbedtls_ecp_group_id grp_id;\n\n    /* publicKey */\n    MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(p, buf, pk));\n\n    if (*p - buf < 1) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n    (*p)--;\n    **p = 0;\n    pub_len += 1;\n\n    MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));\n    MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING));\n\n    MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));\n    MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf,\n                                                         MBEDTLS_ASN1_CONTEXT_SPECIFIC |\n                                                         MBEDTLS_ASN1_CONSTRUCTED | 1));\n    len += pub_len;\n\n    /* parameters */\n    grp_id = mbedtls_pk_get_ec_group_id(pk);\n    MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(p, buf, grp_id));\n    MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(p, buf, par_len));\n    MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(p, buf,\n                                                         MBEDTLS_ASN1_CONTEXT_SPECIFIC |\n                                                         MBEDTLS_ASN1_CONSTRUCTED | 0));\n    len += par_len;\n\n    /* privateKey */\n    MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));\n\n    /* version */\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 1));\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |\n                                                     MBEDTLS_ASN1_SEQUENCE));\n\n    return (int) len;\n}\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n/******************************************************************************\n * Internal functions for Opaque keys.\n ******************************************************************************/\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nstatic int pk_write_opaque_pubkey(unsigned char **p, unsigned char *start,\n                                  const mbedtls_pk_context *pk)\n{\n    size_t buffer_size;\n    size_t len = 0;\n\n    if (*p < start) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    buffer_size = (size_t) (*p - start);\n    if (psa_export_public_key(pk->priv_id, start, buffer_size,\n                              &len) != PSA_SUCCESS) {\n        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n    }\n\n    *p -= len;\n    memmove(*p, start, len);\n\n    return (int) len;\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n/******************************************************************************\n * Generic helpers\n ******************************************************************************/\n\n/* Extend the public mbedtls_pk_get_type() by getting key type also in case of\n * opaque keys. */\nstatic mbedtls_pk_type_t pk_get_type_ext(const mbedtls_pk_context *pk)\n{\n    mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (pk_type == MBEDTLS_PK_OPAQUE) {\n        psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT;\n        psa_key_type_t opaque_key_type;\n\n        if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) {\n            return MBEDTLS_PK_NONE;\n        }\n        opaque_key_type = psa_get_key_type(&opaque_attrs);\n        psa_reset_key_attributes(&opaque_attrs);\n\n        if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) {\n            return MBEDTLS_PK_ECKEY;\n        } else if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) {\n            return MBEDTLS_PK_RSA;\n        } else {\n            return MBEDTLS_PK_NONE;\n        }\n    } else\n#endif\n    return pk_type;\n}\n\n/******************************************************************************\n * Public functions for writing private/public DER keys.\n ******************************************************************************/\nint mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,\n                            const mbedtls_pk_context *key)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n\n#if defined(MBEDTLS_RSA_C)\n    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*key), start, p));\n    } else\n#endif\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {\n        MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key));\n    } else\n#endif\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {\n        MBEDTLS_ASN1_CHK_ADD(len, pk_write_opaque_pubkey(p, start, key));\n    } else\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n\n    return (int) len;\n}\n\nint mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *c;\n    int has_par = 1;\n    size_t len = 0, par_len = 0, oid_len = 0;\n    mbedtls_pk_type_t pk_type;\n    const char *oid = NULL;\n\n    if (size == 0) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n\n    c = buf + size;\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key));\n\n    if (c - buf < 1) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n\n    /*\n     *  SubjectPublicKeyInfo  ::=  SEQUENCE  {\n     *       algorithm            AlgorithmIdentifier,\n     *       subjectPublicKey     BIT STRING }\n     */\n    *--c = 0;\n    len += 1;\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));\n\n    pk_type = pk_get_type_ext(key);\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {\n        mbedtls_ecp_group_id ec_grp_id = mbedtls_pk_get_ec_group_id(key);\n        if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {\n            ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len);\n            if (ret != 0) {\n                return ret;\n            }\n            has_par = 0;\n        } else {\n            MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id));\n        }\n    }\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n    /* At this point oid_len is not null only for EC Montgomery keys. */\n    if (oid_len == 0) {\n        ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, &oid_len);\n        if (ret != 0) {\n            return ret;\n        }\n    }\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len,\n                                                                          par_len, has_par));\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |\n                                                     MBEDTLS_ASN1_SEQUENCE));\n\n    return (int) len;\n}\n\nint mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)\n{\n    unsigned char *c;\n\n    if (size == 0) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n\n    c = buf + size;\n\n#if defined(MBEDTLS_RSA_C)\n    if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {\n        return pk_write_rsa_der(&c, buf, key);\n    } else\n#endif /* MBEDTLS_RSA_C */\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {\n#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)\n        if (mbedtls_pk_is_rfc8410(key)) {\n            return pk_write_ec_rfc8410_der(&c, buf, key);\n        }\n#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */\n        return pk_write_ec_der(&c, buf, key);\n    } else\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n}\n\n/******************************************************************************\n * Public functions for wrinting private/public PEM keys.\n ******************************************************************************/\n#if defined(MBEDTLS_PEM_WRITE_C)\n\n#define PUB_DER_MAX_BYTES                                                   \\\n    (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \\\n     MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)\n#define PRV_DER_MAX_BYTES                                                   \\\n    (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \\\n     MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES)\n\nint mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *output_buf = NULL;\n    output_buf = mbedtls_calloc(1, PUB_DER_MAX_BYTES);\n    if (output_buf == NULL) {\n        return MBEDTLS_ERR_PK_ALLOC_FAILED;\n    }\n    size_t olen = 0;\n\n    if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf,\n                                           PUB_DER_MAX_BYTES)) < 0) {\n        goto cleanup;\n    }\n\n    if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY \"\\n\", PEM_END_PUBLIC_KEY \"\\n\",\n                                        output_buf + PUB_DER_MAX_BYTES - ret,\n                                        ret, buf, size, &olen)) != 0) {\n        goto cleanup;\n    }\n\n    ret = 0;\ncleanup:\n    mbedtls_free(output_buf);\n    return ret;\n}\n\nint mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *output_buf = NULL;\n    output_buf = mbedtls_calloc(1, PRV_DER_MAX_BYTES);\n    if (output_buf == NULL) {\n        return MBEDTLS_ERR_PK_ALLOC_FAILED;\n    }\n    const char *begin, *end;\n    size_t olen = 0;\n\n    if ((ret = mbedtls_pk_write_key_der(key, output_buf, PRV_DER_MAX_BYTES)) < 0) {\n        goto cleanup;\n    }\n\n#if defined(MBEDTLS_RSA_C)\n    if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {\n        begin = PEM_BEGIN_PRIVATE_KEY_RSA \"\\n\";\n        end = PEM_END_PRIVATE_KEY_RSA \"\\n\";\n    } else\n#endif\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {\n        if (mbedtls_pk_is_rfc8410(key)) {\n            begin = PEM_BEGIN_PRIVATE_KEY_PKCS8 \"\\n\";\n            end = PEM_END_PRIVATE_KEY_PKCS8 \"\\n\";\n        } else {\n            begin = PEM_BEGIN_PRIVATE_KEY_EC \"\\n\";\n            end = PEM_END_PRIVATE_KEY_EC \"\\n\";\n        }\n    } else\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n    {\n        ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n        goto cleanup;\n    }\n\n    if ((ret = mbedtls_pem_write_buffer(begin, end,\n                                        output_buf + PRV_DER_MAX_BYTES - ret,\n                                        ret, buf, size, &olen)) != 0) {\n        goto cleanup;\n    }\n\n    ret = 0;\ncleanup:\n    mbedtls_zeroize_and_free(output_buf, PRV_DER_MAX_BYTES);\n    return ret;\n}\n#endif /* MBEDTLS_PEM_WRITE_C */\n\n#endif /* MBEDTLS_PK_WRITE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/pkwrite.h",
    "content": "/**\n * \\file pkwrite.h\n *\n * \\brief Internal defines shared by the PK write module\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_PK_WRITE_H\n#define MBEDTLS_PK_WRITE_H\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/pk.h\"\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"psa/crypto.h\"\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n/*\n * Max sizes of key per types. Shown as tag + len (+ content).\n */\n\n#if defined(MBEDTLS_RSA_C)\n/*\n * RSA public keys:\n *  SubjectPublicKeyInfo  ::=  SEQUENCE  {          1 + 3\n *       algorithm            AlgorithmIdentifier,  1 + 1 (sequence)\n *                                                + 1 + 1 + 9 (rsa oid)\n *                                                + 1 + 1 (params null)\n *       subjectPublicKey     BIT STRING }          1 + 3 + (1 + below)\n *  RSAPublicKey ::= SEQUENCE {                     1 + 3\n *      modulus           INTEGER,  -- n            1 + 3 + MPI_MAX + 1\n *      publicExponent    INTEGER   -- e            1 + 3 + MPI_MAX + 1\n *  }\n */\n#define MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES    (38 + 2 * MBEDTLS_MPI_MAX_SIZE)\n\n/*\n * RSA private keys:\n *  RSAPrivateKey ::= SEQUENCE {                    1 + 3\n *      version           Version,                  1 + 1 + 1\n *      modulus           INTEGER,                  1 + 3 + MPI_MAX + 1\n *      publicExponent    INTEGER,                  1 + 3 + MPI_MAX + 1\n *      privateExponent   INTEGER,                  1 + 3 + MPI_MAX + 1\n *      prime1            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1\n *      prime2            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1\n *      exponent1         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1\n *      exponent2         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1\n *      coefficient       INTEGER,                  1 + 3 + MPI_MAX / 2 + 1\n *      otherPrimeInfos   OtherPrimeInfos OPTIONAL  0 (not supported)\n *  }\n */\n#define MBEDTLS_MPI_MAX_SIZE_2  (MBEDTLS_MPI_MAX_SIZE / 2 + \\\n                                 MBEDTLS_MPI_MAX_SIZE % 2)\n#define MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES    (47 + 3 * MBEDTLS_MPI_MAX_SIZE \\\n                                             + 5 * MBEDTLS_MPI_MAX_SIZE_2)\n\n#else /* MBEDTLS_RSA_C */\n\n#define MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES   0\n#define MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES   0\n\n#endif /* MBEDTLS_RSA_C */\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n\n/* Find the maximum number of bytes necessary to store an EC point. When USE_PSA\n * is defined this means looking for the maximum between PSA and built-in\n * supported curves. */\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#define MBEDTLS_PK_MAX_ECC_BYTES   (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \\\n                                    MBEDTLS_ECP_MAX_BYTES ? \\\n                                    PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) : \\\n                                    MBEDTLS_ECP_MAX_BYTES)\n#else /* MBEDTLS_USE_PSA_CRYPTO */\n#define MBEDTLS_PK_MAX_ECC_BYTES   MBEDTLS_ECP_MAX_BYTES\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n/*\n * EC public keys:\n *  SubjectPublicKeyInfo  ::=  SEQUENCE  {      1 + 2\n *    algorithm         AlgorithmIdentifier,    1 + 1 (sequence)\n *                                            + 1 + 1 + 7 (ec oid)\n *                                            + 1 + 1 + 9 (namedCurve oid)\n *    subjectPublicKey  BIT STRING              1 + 2 + 1               [1]\n *                                            + 1 (point format)        [1]\n *                                            + 2 * ECP_MAX (coords)    [1]\n *  }\n */\n#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES    (30 + 2 * MBEDTLS_PK_MAX_ECC_BYTES)\n\n/*\n * EC private keys:\n * ECPrivateKey ::= SEQUENCE {                  1 + 2\n *      version        INTEGER ,                1 + 1 + 1\n *      privateKey     OCTET STRING,            1 + 1 + ECP_MAX\n *      parameters [0] ECParameters OPTIONAL,   1 + 1 + (1 + 1 + 9)\n *      publicKey  [1] BIT STRING OPTIONAL      1 + 2 + [1] above\n *    }\n */\n#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES    (29 + 3 * MBEDTLS_PK_MAX_ECC_BYTES)\n\n#else /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES   0\n#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES   0\n\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n/* Define the maximum available public key DER length based on the supported\n * key types (EC and/or RSA). */\n#if (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)\n#define MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE    MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES\n#else\n#define MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE    MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES\n#endif\n\n#endif /* MBEDTLS_PK_WRITE_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/platform.c",
    "content": "/*\n *  Platform abstraction layer\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PLATFORM_C)\n\n#include \"mbedtls/platform.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n/* The compile time configuration of memory allocation via the macros\n * MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime\n * configuration via mbedtls_platform_set_calloc_free(). So, omit everything\n * related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */\n#if defined(MBEDTLS_PLATFORM_MEMORY) &&                 \\\n    !(defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&        \\\n    defined(MBEDTLS_PLATFORM_FREE_MACRO))\n\n#if !defined(MBEDTLS_PLATFORM_STD_CALLOC)\nstatic void *platform_calloc_uninit(size_t n, size_t size)\n{\n    ((void) n);\n    ((void) size);\n    return NULL;\n}\n\n#define MBEDTLS_PLATFORM_STD_CALLOC   platform_calloc_uninit\n#endif /* !MBEDTLS_PLATFORM_STD_CALLOC */\n\n#if !defined(MBEDTLS_PLATFORM_STD_FREE)\nstatic void platform_free_uninit(void *ptr)\n{\n    ((void) ptr);\n}\n\n#define MBEDTLS_PLATFORM_STD_FREE     platform_free_uninit\n#endif /* !MBEDTLS_PLATFORM_STD_FREE */\n\nstatic void * (*mbedtls_calloc_func)(size_t, size_t) = MBEDTLS_PLATFORM_STD_CALLOC;\nstatic void (*mbedtls_free_func)(void *) = MBEDTLS_PLATFORM_STD_FREE;\n\nvoid *mbedtls_calloc(size_t nmemb, size_t size)\n{\n    return (*mbedtls_calloc_func)(nmemb, size);\n}\n\nvoid mbedtls_free(void *ptr)\n{\n    (*mbedtls_free_func)(ptr);\n}\n\nint mbedtls_platform_set_calloc_free(void *(*calloc_func)(size_t, size_t),\n                                     void (*free_func)(void *))\n{\n    mbedtls_calloc_func = calloc_func;\n    mbedtls_free_func = free_func;\n    return 0;\n}\n#endif /* MBEDTLS_PLATFORM_MEMORY &&\n          !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\n             defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */\n\n#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF)\n#include <stdarg.h>\nint mbedtls_platform_win32_snprintf(char *s, size_t n, const char *fmt, ...)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    va_list argp;\n\n    va_start(argp, fmt);\n    ret = mbedtls_vsnprintf(s, n, fmt, argp);\n    va_end(argp);\n\n    return ret;\n}\n#endif\n\n#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)\n#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF)\n/*\n * Make dummy function to prevent NULL pointer dereferences\n */\nstatic int platform_snprintf_uninit(char *s, size_t n,\n                                    const char *format, ...)\n{\n    ((void) s);\n    ((void) n);\n    ((void) format);\n    return 0;\n}\n\n#define MBEDTLS_PLATFORM_STD_SNPRINTF    platform_snprintf_uninit\n#endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */\n\nint (*mbedtls_snprintf)(char *s, size_t n,\n                        const char *format,\n                        ...) = MBEDTLS_PLATFORM_STD_SNPRINTF;\n\nint mbedtls_platform_set_snprintf(int (*snprintf_func)(char *s, size_t n,\n                                                       const char *format,\n                                                       ...))\n{\n    mbedtls_snprintf = snprintf_func;\n    return 0;\n}\n#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */\n\n#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF)\n#include <stdarg.h>\nint mbedtls_platform_win32_vsnprintf(char *s, size_t n, const char *fmt, va_list arg)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* Avoid calling the invalid parameter handler by checking ourselves */\n    if (s == NULL || n == 0 || fmt == NULL) {\n        return -1;\n    }\n\n#if defined(_TRUNCATE)\n    ret = vsnprintf_s(s, n, _TRUNCATE, fmt, arg);\n#else\n    ret = vsnprintf(s, n, fmt, arg);\n    if (ret < 0 || (size_t) ret == n) {\n        s[n-1] = '\\0';\n        ret = -1;\n    }\n#endif\n\n    return ret;\n}\n#endif\n\n#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT)\n#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF)\n/*\n * Make dummy function to prevent NULL pointer dereferences\n */\nstatic int platform_vsnprintf_uninit(char *s, size_t n,\n                                     const char *format, va_list arg)\n{\n    ((void) s);\n    ((void) n);\n    ((void) format);\n    ((void) arg);\n    return -1;\n}\n\n#define MBEDTLS_PLATFORM_STD_VSNPRINTF    platform_vsnprintf_uninit\n#endif /* !MBEDTLS_PLATFORM_STD_VSNPRINTF */\n\nint (*mbedtls_vsnprintf)(char *s, size_t n,\n                         const char *format,\n                         va_list arg) = MBEDTLS_PLATFORM_STD_VSNPRINTF;\n\nint mbedtls_platform_set_vsnprintf(int (*vsnprintf_func)(char *s, size_t n,\n                                                         const char *format,\n                                                         va_list arg))\n{\n    mbedtls_vsnprintf = vsnprintf_func;\n    return 0;\n}\n#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */\n\n#if defined(MBEDTLS_PLATFORM_PRINTF_ALT)\n#if !defined(MBEDTLS_PLATFORM_STD_PRINTF)\n/*\n * Make dummy function to prevent NULL pointer dereferences\n */\nstatic int platform_printf_uninit(const char *format, ...)\n{\n    ((void) format);\n    return 0;\n}\n\n#define MBEDTLS_PLATFORM_STD_PRINTF    platform_printf_uninit\n#endif /* !MBEDTLS_PLATFORM_STD_PRINTF */\n\nint (*mbedtls_printf)(const char *, ...) = MBEDTLS_PLATFORM_STD_PRINTF;\n\nint mbedtls_platform_set_printf(int (*printf_func)(const char *, ...))\n{\n    mbedtls_printf = printf_func;\n    return 0;\n}\n#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */\n\n#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT)\n#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF)\n/*\n * Make dummy function to prevent NULL pointer dereferences\n */\nstatic int platform_fprintf_uninit(FILE *stream, const char *format, ...)\n{\n    ((void) stream);\n    ((void) format);\n    return 0;\n}\n\n#define MBEDTLS_PLATFORM_STD_FPRINTF   platform_fprintf_uninit\n#endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */\n\nint (*mbedtls_fprintf)(FILE *, const char *, ...) =\n    MBEDTLS_PLATFORM_STD_FPRINTF;\n\nint mbedtls_platform_set_fprintf(int (*fprintf_func)(FILE *, const char *, ...))\n{\n    mbedtls_fprintf = fprintf_func;\n    return 0;\n}\n#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */\n\n#if defined(MBEDTLS_PLATFORM_SETBUF_ALT)\n#if !defined(MBEDTLS_PLATFORM_STD_SETBUF)\n/*\n * Make dummy function to prevent NULL pointer dereferences\n */\nstatic void platform_setbuf_uninit(FILE *stream, char *buf)\n{\n    ((void) stream);\n    ((void) buf);\n}\n\n#define MBEDTLS_PLATFORM_STD_SETBUF   platform_setbuf_uninit\n#endif /* !MBEDTLS_PLATFORM_STD_SETBUF */\nvoid (*mbedtls_setbuf)(FILE *stream, char *buf) = MBEDTLS_PLATFORM_STD_SETBUF;\n\nint mbedtls_platform_set_setbuf(void (*setbuf_func)(FILE *stream, char *buf))\n{\n    mbedtls_setbuf = setbuf_func;\n    return 0;\n}\n#endif /* MBEDTLS_PLATFORM_SETBUF_ALT */\n\n#if defined(MBEDTLS_PLATFORM_EXIT_ALT)\n#if !defined(MBEDTLS_PLATFORM_STD_EXIT)\n/*\n * Make dummy function to prevent NULL pointer dereferences\n */\nstatic void platform_exit_uninit(int status)\n{\n    ((void) status);\n}\n\n#define MBEDTLS_PLATFORM_STD_EXIT   platform_exit_uninit\n#endif /* !MBEDTLS_PLATFORM_STD_EXIT */\n\nvoid (*mbedtls_exit)(int status) = MBEDTLS_PLATFORM_STD_EXIT;\n\nint mbedtls_platform_set_exit(void (*exit_func)(int status))\n{\n    mbedtls_exit = exit_func;\n    return 0;\n}\n#endif /* MBEDTLS_PLATFORM_EXIT_ALT */\n\n#if defined(MBEDTLS_HAVE_TIME)\n\n#if defined(MBEDTLS_PLATFORM_TIME_ALT)\n#if !defined(MBEDTLS_PLATFORM_STD_TIME)\n/*\n * Make dummy function to prevent NULL pointer dereferences\n */\nstatic mbedtls_time_t platform_time_uninit(mbedtls_time_t *timer)\n{\n    ((void) timer);\n    return 0;\n}\n\n#define MBEDTLS_PLATFORM_STD_TIME   platform_time_uninit\n#endif /* !MBEDTLS_PLATFORM_STD_TIME */\n\nmbedtls_time_t (*mbedtls_time)(mbedtls_time_t *timer) = MBEDTLS_PLATFORM_STD_TIME;\n\nint mbedtls_platform_set_time(mbedtls_time_t (*time_func)(mbedtls_time_t *timer))\n{\n    mbedtls_time = time_func;\n    return 0;\n}\n#endif /* MBEDTLS_PLATFORM_TIME_ALT */\n\n#endif /* MBEDTLS_HAVE_TIME */\n\n#if defined(MBEDTLS_ENTROPY_NV_SEED)\n#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO)\n/* Default implementations for the platform independent seed functions use\n * standard libc file functions to read from and write to a pre-defined filename\n */\nint mbedtls_platform_std_nv_seed_read(unsigned char *buf, size_t buf_len)\n{\n    FILE *file;\n    size_t n;\n\n    if ((file = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, \"rb\")) == NULL) {\n        return -1;\n    }\n\n    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */\n    mbedtls_setbuf(file, NULL);\n\n    if ((n = fread(buf, 1, buf_len, file)) != buf_len) {\n        fclose(file);\n        mbedtls_platform_zeroize(buf, buf_len);\n        return -1;\n    }\n\n    fclose(file);\n    return (int) n;\n}\n\nint mbedtls_platform_std_nv_seed_write(unsigned char *buf, size_t buf_len)\n{\n    FILE *file;\n    size_t n;\n\n    if ((file = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, \"w\")) == NULL) {\n        return -1;\n    }\n\n    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */\n    mbedtls_setbuf(file, NULL);\n\n    if ((n = fwrite(buf, 1, buf_len, file)) != buf_len) {\n        fclose(file);\n        return -1;\n    }\n\n    fclose(file);\n    return (int) n;\n}\n#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */\n\n#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT)\n#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ)\n/*\n * Make dummy function to prevent NULL pointer dereferences\n */\nstatic int platform_nv_seed_read_uninit(unsigned char *buf, size_t buf_len)\n{\n    ((void) buf);\n    ((void) buf_len);\n    return -1;\n}\n\n#define MBEDTLS_PLATFORM_STD_NV_SEED_READ   platform_nv_seed_read_uninit\n#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */\n\n#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE)\n/*\n * Make dummy function to prevent NULL pointer dereferences\n */\nstatic int platform_nv_seed_write_uninit(unsigned char *buf, size_t buf_len)\n{\n    ((void) buf);\n    ((void) buf_len);\n    return -1;\n}\n\n#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE   platform_nv_seed_write_uninit\n#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */\n\nint (*mbedtls_nv_seed_read)(unsigned char *buf, size_t buf_len) =\n    MBEDTLS_PLATFORM_STD_NV_SEED_READ;\nint (*mbedtls_nv_seed_write)(unsigned char *buf, size_t buf_len) =\n    MBEDTLS_PLATFORM_STD_NV_SEED_WRITE;\n\nint mbedtls_platform_set_nv_seed(\n    int (*nv_seed_read_func)(unsigned char *buf, size_t buf_len),\n    int (*nv_seed_write_func)(unsigned char *buf, size_t buf_len))\n{\n    mbedtls_nv_seed_read = nv_seed_read_func;\n    mbedtls_nv_seed_write = nv_seed_write_func;\n    return 0;\n}\n#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */\n#endif /* MBEDTLS_ENTROPY_NV_SEED */\n\n#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT)\n/*\n * Placeholder platform setup that does nothing by default\n */\nint mbedtls_platform_setup(mbedtls_platform_context *ctx)\n{\n    (void) ctx;\n\n    return 0;\n}\n\n/*\n * Placeholder platform teardown that does nothing by default\n */\nvoid mbedtls_platform_teardown(mbedtls_platform_context *ctx)\n{\n    (void) ctx;\n}\n#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */\n\n#endif /* MBEDTLS_PLATFORM_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/platform_util.c",
    "content": "/*\n * Common and shared functions used by multiple modules in the Mbed TLS\n * library.\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n * Ensure gmtime_r is available even with -std=c99; must be defined before\n * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms\n * except OpenBSD, where it stops us accessing explicit_bzero.\n */\n#if !defined(_POSIX_C_SOURCE) && !defined(__OpenBSD__)\n#define _POSIX_C_SOURCE 200112L\n#endif\n\n#if !defined(_GNU_SOURCE)\n/* Clang requires this to get support for explicit_bzero */\n#define _GNU_SOURCE\n#endif\n\n#include \"common.h\"\n\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/platform.h\"\n#include \"mbedtls/threading.h\"\n\n#include <stddef.h>\n\n#ifndef __STDC_WANT_LIB_EXT1__\n#define __STDC_WANT_LIB_EXT1__ 1 /* Ask for the C11 gmtime_s() and memset_s() if available */\n#endif\n#include <string.h>\n\n#if defined(_WIN32)\n#include <windows.h>\n#endif\n\n// Detect platforms known to support explicit_bzero()\n#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)\n#define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1\n#elif (defined(__FreeBSD__) && (__FreeBSD_version >= 1100037)) || defined(__OpenBSD__)\n#define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1\n#endif\n\n#if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT)\n\n#undef HAVE_MEMORY_SANITIZER\n#if defined(__has_feature)\n#if __has_feature(memory_sanitizer)\n#include <sanitizer/msan_interface.h>\n#define HAVE_MEMORY_SANITIZER\n#endif\n#endif\n\n/*\n * Where possible, we try to detect the presence of a platform-provided\n * secure memset, such as explicit_bzero(), that is safe against being optimized\n * out, and use that.\n *\n * For other platforms, we provide an implementation that aims not to be\n * optimized out by the compiler.\n *\n * This implementation for mbedtls_platform_zeroize() was inspired from Colin\n * Percival's blog article at:\n *\n * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html\n *\n * It uses a volatile function pointer to the standard memset(). Because the\n * pointer is volatile the compiler expects it to change at\n * any time and will not optimize out the call that could potentially perform\n * other operations on the input buffer instead of just setting it to 0.\n * Nevertheless, as pointed out by davidtgoldblatt on Hacker News\n * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for\n * details), optimizations of the following form are still possible:\n *\n * if (memset_func != memset)\n *     memset_func(buf, 0, len);\n *\n * Note that it is extremely difficult to guarantee that\n * the memset() call will not be optimized out by aggressive compilers\n * in a portable way. For this reason, Mbed TLS also provides the configuration\n * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure\n * mbedtls_platform_zeroize() to use a suitable implementation for their\n * platform and needs.\n */\n#if !defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) && !(defined(__STDC_LIB_EXT1__) && \\\n    !defined(__IAR_SYSTEMS_ICC__)) \\\n    && !(defined(_WIN32) && !defined(__TINYC__))\nstatic void *(*const volatile memset_func)(void *, int, size_t) = memset;\n#endif\n\nvoid mbedtls_platform_zeroize(void *buf, size_t len)\n{\n    if (len > 0) {\n#if defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO)\n        explicit_bzero(buf, len);\n#if defined(HAVE_MEMORY_SANITIZER)\n        /* You'd think that Msan would recognize explicit_bzero() as\n         * equivalent to bzero(), but it actually doesn't on several\n         * platforms, including Linux (Ubuntu 20.04).\n         * https://github.com/google/sanitizers/issues/1507\n         * https://github.com/openssh/openssh-portable/commit/74433a19bb6f4cef607680fa4d1d7d81ca3826aa\n         */\n        __msan_unpoison(buf, len);\n#endif\n#elif defined(__STDC_LIB_EXT1__) && !defined(__IAR_SYSTEMS_ICC__)\n        memset_s(buf, len, 0, len);\n#elif defined(_WIN32) && !defined(__TINYC__)\n        /* tcc has a bad implementation of `SecureZeroMemory` */\n        SecureZeroMemory(buf, len);\n#else\n        memset_func(buf, 0, len);\n#endif\n\n#if defined(__GNUC__)\n        /* For clang and recent gcc, pretend that we have some assembly that reads the\n         * zero'd memory as an additional protection against being optimised away. */\n#if defined(__clang__) || (__GNUC__ >= 10)\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wvla\"\n#elif defined(MBEDTLS_COMPILER_IS_GCC)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wvla\"\n#endif\n        asm volatile (\"\" : : \"m\" (*(char (*)[len]) buf) :);\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#elif defined(MBEDTLS_COMPILER_IS_GCC)\n#pragma GCC diagnostic pop\n#endif\n#endif\n#endif\n    }\n}\n#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */\n\nvoid mbedtls_zeroize_and_free(void *buf, size_t len)\n{\n    if (buf != NULL) {\n        mbedtls_platform_zeroize(buf, len);\n    }\n\n    mbedtls_free(buf);\n}\n\n#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)\n#include <time.h>\n#if !defined(_WIN32) && (defined(unix) || \\\n    defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \\\n    defined(__MACH__)) || defined(__midipix__))\n#include <unistd.h>\n#endif /* !_WIN32 && (unix || __unix || __unix__ ||\n        * (__APPLE__ && __MACH__) || __midipix__) */\n\n#if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) ||     \\\n    (defined(_POSIX_THREAD_SAFE_FUNCTIONS) &&                     \\\n    _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L))\n/*\n * This is a convenience shorthand macro to avoid checking the long\n * preprocessor conditions above. Ideally, we could expose this macro in\n * platform_util.h and simply use it in platform_util.c, threading.c and\n * threading.h. However, this macro is not part of the Mbed TLS public API, so\n * we keep it private by only defining it in this file\n */\n#if !(defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)) || \\\n    (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))\n#define PLATFORM_UTIL_USE_GMTIME\n#endif\n\n#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \\\n             ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \\\n                _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */\n\nstruct tm *mbedtls_platform_gmtime_r(const mbedtls_time_t *tt,\n                                     struct tm *tm_buf)\n{\n#if defined(_WIN32) && !defined(PLATFORM_UTIL_USE_GMTIME)\n#if defined(__STDC_LIB_EXT1__)\n    return (gmtime_s(tt, tm_buf) == 0) ? NULL : tm_buf;\n#else\n    /* MSVC and mingw64 argument order and return value are inconsistent with the C11 standard */\n    return (gmtime_s(tm_buf, tt) == 0) ? tm_buf : NULL;\n#endif\n#elif !defined(PLATFORM_UTIL_USE_GMTIME)\n    return gmtime_r(tt, tm_buf);\n#else\n    struct tm *lt;\n\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_lock(&mbedtls_threading_gmtime_mutex) != 0) {\n        return NULL;\n    }\n#endif /* MBEDTLS_THREADING_C */\n\n    lt = gmtime(tt);\n\n    if (lt != NULL) {\n        memcpy(tm_buf, lt, sizeof(struct tm));\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&mbedtls_threading_gmtime_mutex) != 0) {\n        return NULL;\n    }\n#endif /* MBEDTLS_THREADING_C */\n\n    return (lt == NULL) ? NULL : tm_buf;\n#endif /* _WIN32 && !EFIX64 && !EFI32 */\n}\n#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */\n\n#if defined(MBEDTLS_TEST_HOOKS)\nvoid (*mbedtls_test_hook_test_fail)(const char *, int, const char *);\n#endif /* MBEDTLS_TEST_HOOKS */\n\n#if defined(MBEDTLS_HAVE_TIME) && !defined(MBEDTLS_PLATFORM_MS_TIME_ALT)\n\n#include <time.h>\n#if !defined(_WIN32) && \\\n    (defined(unix) || defined(__unix) || defined(__unix__) || \\\n    (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__) || defined(__midipix__))\n#include <unistd.h>\n#endif \\\n    /* !_WIN32 && (unix || __unix || __unix__ || (__APPLE__ && __MACH__) || __HAIKU__ || __midipix__) */\n#if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 199309L) || defined(__HAIKU__)\nmbedtls_ms_time_t mbedtls_ms_time(void)\n{\n    int ret;\n    struct timespec tv;\n    mbedtls_ms_time_t current_ms;\n\n#if defined(__linux__) && defined(CLOCK_BOOTTIME) || defined(__midipix__)\n    ret = clock_gettime(CLOCK_BOOTTIME, &tv);\n#else\n    ret = clock_gettime(CLOCK_MONOTONIC, &tv);\n#endif\n    if (ret) {\n        return time(NULL) * 1000;\n    }\n\n    current_ms = tv.tv_sec;\n\n    return current_ms*1000 + tv.tv_nsec / 1000000;\n}\n#elif defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \\\n    defined(__MINGW32__) || defined(_WIN64)\n#include <windows.h>\nmbedtls_ms_time_t mbedtls_ms_time(void)\n{\n    FILETIME ct;\n    mbedtls_ms_time_t current_ms;\n\n    GetSystemTimeAsFileTime(&ct);\n    current_ms = ((mbedtls_ms_time_t) ct.dwLowDateTime +\n                  ((mbedtls_ms_time_t) (ct.dwHighDateTime) << 32LL))/10000;\n    return current_ms;\n}\n#else\n#error \"No mbedtls_ms_time available\"\n#endif\n#endif /* MBEDTLS_HAVE_TIME && !MBEDTLS_PLATFORM_MS_TIME_ALT */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/poly1305.c",
    "content": "/**\n * \\file poly1305.c\n *\n * \\brief Poly1305 authentication algorithm.\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#include \"common.h\"\n\n#if defined(MBEDTLS_POLY1305_C)\n\n#include \"mbedtls/poly1305.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#if !defined(MBEDTLS_POLY1305_ALT)\n\n#define POLY1305_BLOCK_SIZE_BYTES (16U)\n\n/*\n * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier.\n * However we provided an alternative for platforms without such a multiplier.\n */\n#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION)\nstatic uint64_t mul64(uint32_t a, uint32_t b)\n{\n    /* a = al + 2**16 ah, b = bl + 2**16 bh */\n    const uint16_t al = (uint16_t) a;\n    const uint16_t bl = (uint16_t) b;\n    const uint16_t ah = a >> 16;\n    const uint16_t bh = b >> 16;\n\n    /* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */\n    const uint32_t lo = (uint32_t) al * bl;\n    const uint64_t me = (uint64_t) ((uint32_t) ah * bl) + (uint32_t) al * bh;\n    const uint32_t hi = (uint32_t) ah * bh;\n\n    return lo + (me << 16) + ((uint64_t) hi << 32);\n}\n#else\nstatic inline uint64_t mul64(uint32_t a, uint32_t b)\n{\n    return (uint64_t) a * b;\n}\n#endif\n\n\n/**\n * \\brief                   Process blocks with Poly1305.\n *\n * \\param ctx               The Poly1305 context.\n * \\param nblocks           Number of blocks to process. Note that this\n *                          function only processes full blocks.\n * \\param input             Buffer containing the input block(s).\n * \\param needs_padding     Set to 0 if the padding bit has already been\n *                          applied to the input data before calling this\n *                          function.  Otherwise, set this parameter to 1.\n */\nstatic void poly1305_process(mbedtls_poly1305_context *ctx,\n                             size_t nblocks,\n                             const unsigned char *input,\n                             uint32_t needs_padding)\n{\n    uint64_t d0, d1, d2, d3;\n    uint32_t acc0, acc1, acc2, acc3, acc4;\n    uint32_t r0, r1, r2, r3;\n    uint32_t rs1, rs2, rs3;\n    size_t offset  = 0U;\n    size_t i;\n\n    r0 = ctx->r[0];\n    r1 = ctx->r[1];\n    r2 = ctx->r[2];\n    r3 = ctx->r[3];\n\n    rs1 = r1 + (r1 >> 2U);\n    rs2 = r2 + (r2 >> 2U);\n    rs3 = r3 + (r3 >> 2U);\n\n    acc0 = ctx->acc[0];\n    acc1 = ctx->acc[1];\n    acc2 = ctx->acc[2];\n    acc3 = ctx->acc[3];\n    acc4 = ctx->acc[4];\n\n    /* Process full blocks */\n    for (i = 0U; i < nblocks; i++) {\n        /* The input block is treated as a 128-bit little-endian integer */\n        d0   = MBEDTLS_GET_UINT32_LE(input, offset + 0);\n        d1   = MBEDTLS_GET_UINT32_LE(input, offset + 4);\n        d2   = MBEDTLS_GET_UINT32_LE(input, offset + 8);\n        d3   = MBEDTLS_GET_UINT32_LE(input, offset + 12);\n\n        /* Compute: acc += (padded) block as a 130-bit integer */\n        d0  += (uint64_t) acc0;\n        d1  += (uint64_t) acc1 + (d0 >> 32U);\n        d2  += (uint64_t) acc2 + (d1 >> 32U);\n        d3  += (uint64_t) acc3 + (d2 >> 32U);\n        acc0 = (uint32_t) d0;\n        acc1 = (uint32_t) d1;\n        acc2 = (uint32_t) d2;\n        acc3 = (uint32_t) d3;\n        acc4 += (uint32_t) (d3 >> 32U) + needs_padding;\n\n        /* Compute: acc *= r */\n        d0 = mul64(acc0, r0) +\n             mul64(acc1, rs3) +\n             mul64(acc2, rs2) +\n             mul64(acc3, rs1);\n        d1 = mul64(acc0, r1) +\n             mul64(acc1, r0) +\n             mul64(acc2, rs3) +\n             mul64(acc3, rs2) +\n             mul64(acc4, rs1);\n        d2 = mul64(acc0, r2) +\n             mul64(acc1, r1) +\n             mul64(acc2, r0) +\n             mul64(acc3, rs3) +\n             mul64(acc4, rs2);\n        d3 = mul64(acc0, r3) +\n             mul64(acc1, r2) +\n             mul64(acc2, r1) +\n             mul64(acc3, r0) +\n             mul64(acc4, rs3);\n        acc4 *= r0;\n\n        /* Compute: acc %= (2^130 - 5) (partial remainder) */\n        d1 += (d0 >> 32);\n        d2 += (d1 >> 32);\n        d3 += (d2 >> 32);\n        acc0 = (uint32_t) d0;\n        acc1 = (uint32_t) d1;\n        acc2 = (uint32_t) d2;\n        acc3 = (uint32_t) d3;\n        acc4 = (uint32_t) (d3 >> 32) + acc4;\n\n        d0 = (uint64_t) acc0 + (acc4 >> 2) + (acc4 & 0xFFFFFFFCU);\n        acc4 &= 3U;\n        acc0 = (uint32_t) d0;\n        d0 = (uint64_t) acc1 + (d0 >> 32U);\n        acc1 = (uint32_t) d0;\n        d0 = (uint64_t) acc2 + (d0 >> 32U);\n        acc2 = (uint32_t) d0;\n        d0 = (uint64_t) acc3 + (d0 >> 32U);\n        acc3 = (uint32_t) d0;\n        d0 = (uint64_t) acc4 + (d0 >> 32U);\n        acc4 = (uint32_t) d0;\n\n        offset    += POLY1305_BLOCK_SIZE_BYTES;\n    }\n\n    ctx->acc[0] = acc0;\n    ctx->acc[1] = acc1;\n    ctx->acc[2] = acc2;\n    ctx->acc[3] = acc3;\n    ctx->acc[4] = acc4;\n}\n\n/**\n * \\brief                   Compute the Poly1305 MAC\n *\n * \\param ctx               The Poly1305 context.\n * \\param mac               The buffer to where the MAC is written. Must be\n *                          big enough to contain the 16-byte MAC.\n */\nstatic void poly1305_compute_mac(const mbedtls_poly1305_context *ctx,\n                                 unsigned char mac[16])\n{\n    uint64_t d;\n    uint32_t g0, g1, g2, g3, g4;\n    uint32_t acc0, acc1, acc2, acc3, acc4;\n    uint32_t mask;\n    uint32_t mask_inv;\n\n    acc0 = ctx->acc[0];\n    acc1 = ctx->acc[1];\n    acc2 = ctx->acc[2];\n    acc3 = ctx->acc[3];\n    acc4 = ctx->acc[4];\n\n    /* Before adding 's' we ensure that the accumulator is mod 2^130 - 5.\n     * We do this by calculating acc - (2^130 - 5), then checking if\n     * the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5)\n     */\n\n    /* Calculate acc + -(2^130 - 5) */\n    d  = ((uint64_t) acc0 + 5U);\n    g0 = (uint32_t) d;\n    d  = ((uint64_t) acc1 + (d >> 32));\n    g1 = (uint32_t) d;\n    d  = ((uint64_t) acc2 + (d >> 32));\n    g2 = (uint32_t) d;\n    d  = ((uint64_t) acc3 + (d >> 32));\n    g3 = (uint32_t) d;\n    g4 = acc4 + (uint32_t) (d >> 32U);\n\n    /* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */\n    mask = (uint32_t) 0U - (g4 >> 2U);\n    mask_inv = ~mask;\n\n    /* If 131st bit is set then acc=g, otherwise, acc is unmodified */\n    acc0 = (acc0 & mask_inv) | (g0 & mask);\n    acc1 = (acc1 & mask_inv) | (g1 & mask);\n    acc2 = (acc2 & mask_inv) | (g2 & mask);\n    acc3 = (acc3 & mask_inv) | (g3 & mask);\n\n    /* Add 's' */\n    d = (uint64_t) acc0 + ctx->s[0];\n    acc0 = (uint32_t) d;\n    d = (uint64_t) acc1 + ctx->s[1] + (d >> 32U);\n    acc1 = (uint32_t) d;\n    d = (uint64_t) acc2 + ctx->s[2] + (d >> 32U);\n    acc2 = (uint32_t) d;\n    acc3 += ctx->s[3] + (uint32_t) (d >> 32U);\n\n    /* Compute MAC (128 least significant bits of the accumulator) */\n    MBEDTLS_PUT_UINT32_LE(acc0, mac,  0);\n    MBEDTLS_PUT_UINT32_LE(acc1, mac,  4);\n    MBEDTLS_PUT_UINT32_LE(acc2, mac,  8);\n    MBEDTLS_PUT_UINT32_LE(acc3, mac, 12);\n}\n\nvoid mbedtls_poly1305_init(mbedtls_poly1305_context *ctx)\n{\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_poly1305_context));\n}\n\nvoid mbedtls_poly1305_free(mbedtls_poly1305_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_poly1305_context));\n}\n\nint mbedtls_poly1305_starts(mbedtls_poly1305_context *ctx,\n                            const unsigned char key[32])\n{\n    /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */\n    ctx->r[0] = MBEDTLS_GET_UINT32_LE(key, 0)  & 0x0FFFFFFFU;\n    ctx->r[1] = MBEDTLS_GET_UINT32_LE(key, 4)  & 0x0FFFFFFCU;\n    ctx->r[2] = MBEDTLS_GET_UINT32_LE(key, 8)  & 0x0FFFFFFCU;\n    ctx->r[3] = MBEDTLS_GET_UINT32_LE(key, 12) & 0x0FFFFFFCU;\n\n    ctx->s[0] = MBEDTLS_GET_UINT32_LE(key, 16);\n    ctx->s[1] = MBEDTLS_GET_UINT32_LE(key, 20);\n    ctx->s[2] = MBEDTLS_GET_UINT32_LE(key, 24);\n    ctx->s[3] = MBEDTLS_GET_UINT32_LE(key, 28);\n\n    /* Initial accumulator state */\n    ctx->acc[0] = 0U;\n    ctx->acc[1] = 0U;\n    ctx->acc[2] = 0U;\n    ctx->acc[3] = 0U;\n    ctx->acc[4] = 0U;\n\n    /* Queue initially empty */\n    mbedtls_platform_zeroize(ctx->queue, sizeof(ctx->queue));\n    ctx->queue_len = 0U;\n\n    return 0;\n}\n\nint mbedtls_poly1305_update(mbedtls_poly1305_context *ctx,\n                            const unsigned char *input,\n                            size_t ilen)\n{\n    size_t offset    = 0U;\n    size_t remaining = ilen;\n    size_t queue_free_len;\n    size_t nblocks;\n\n    if ((remaining > 0U) && (ctx->queue_len > 0U)) {\n        queue_free_len = (POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len);\n\n        if (ilen < queue_free_len) {\n            /* Not enough data to complete the block.\n             * Store this data with the other leftovers.\n             */\n            memcpy(&ctx->queue[ctx->queue_len],\n                   input,\n                   ilen);\n\n            ctx->queue_len += ilen;\n\n            remaining = 0U;\n        } else {\n            /* Enough data to produce a complete block */\n            memcpy(&ctx->queue[ctx->queue_len],\n                   input,\n                   queue_free_len);\n\n            ctx->queue_len = 0U;\n\n            poly1305_process(ctx, 1U, ctx->queue, 1U);   /* add padding bit */\n\n            offset    += queue_free_len;\n            remaining -= queue_free_len;\n        }\n    }\n\n    if (remaining >= POLY1305_BLOCK_SIZE_BYTES) {\n        nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES;\n\n        poly1305_process(ctx, nblocks, &input[offset], 1U);\n\n        offset += nblocks * POLY1305_BLOCK_SIZE_BYTES;\n        remaining %= POLY1305_BLOCK_SIZE_BYTES;\n    }\n\n    if (remaining > 0U) {\n        /* Store partial block */\n        ctx->queue_len = remaining;\n        memcpy(ctx->queue, &input[offset], remaining);\n    }\n\n    return 0;\n}\n\nint mbedtls_poly1305_finish(mbedtls_poly1305_context *ctx,\n                            unsigned char mac[16])\n{\n    /* Process any leftover data */\n    if (ctx->queue_len > 0U) {\n        /* Add padding bit */\n        ctx->queue[ctx->queue_len] = 1U;\n        ctx->queue_len++;\n\n        /* Pad with zeroes */\n        memset(&ctx->queue[ctx->queue_len],\n               0,\n               POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len);\n\n        poly1305_process(ctx, 1U,           /* Process 1 block */\n                         ctx->queue, 0U);   /* Already padded above */\n    }\n\n    poly1305_compute_mac(ctx, mac);\n\n    return 0;\n}\n\nint mbedtls_poly1305_mac(const unsigned char key[32],\n                         const unsigned char *input,\n                         size_t ilen,\n                         unsigned char mac[16])\n{\n    mbedtls_poly1305_context ctx;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_poly1305_init(&ctx);\n\n    ret = mbedtls_poly1305_starts(&ctx, key);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    ret = mbedtls_poly1305_update(&ctx, input, ilen);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    ret = mbedtls_poly1305_finish(&ctx, mac);\n\ncleanup:\n    mbedtls_poly1305_free(&ctx);\n    return ret;\n}\n\n#endif /* MBEDTLS_POLY1305_ALT */\n\n#if defined(MBEDTLS_SELF_TEST)\n\nstatic const unsigned char test_keys[2][32] =\n{\n    {\n        0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33,\n        0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8,\n        0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd,\n        0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b\n    },\n    {\n        0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a,\n        0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0,\n        0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09,\n        0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0\n    }\n};\n\nstatic const unsigned char test_data[2][127] =\n{\n    {\n        0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72,\n        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f,\n        0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65,\n        0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f,\n        0x75, 0x70\n    },\n    {\n        0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72,\n        0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61,\n        0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,\n        0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f,\n        0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20,\n        0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64,\n        0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20,\n        0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,\n        0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c,\n        0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77,\n        0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,\n        0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65,\n        0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,\n        0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20,\n        0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75,\n        0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e\n    }\n};\n\nstatic const size_t test_data_len[2] =\n{\n    34U,\n    127U\n};\n\nstatic const unsigned char test_mac[2][16] =\n{\n    {\n        0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6,\n        0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9\n    },\n    {\n        0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61,\n        0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62\n    }\n};\n\n/* Make sure no other definition is already present. */\n#undef ASSERT\n\n#define ASSERT(cond, args)            \\\n    do                                  \\\n    {                                   \\\n        if (!(cond))                \\\n        {                               \\\n            if (verbose != 0)          \\\n            mbedtls_printf args;    \\\n                                        \\\n            return -1;               \\\n        }                               \\\n    }                                   \\\n    while (0)\n\nint mbedtls_poly1305_self_test(int verbose)\n{\n    unsigned char mac[16];\n    unsigned i;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    for (i = 0U; i < 2U; i++) {\n        if (verbose != 0) {\n            mbedtls_printf(\"  Poly1305 test %u \", i);\n        }\n\n        ret = mbedtls_poly1305_mac(test_keys[i],\n                                   test_data[i],\n                                   test_data_len[i],\n                                   mac);\n        ASSERT(0 == ret, (\"error code: %i\\n\", ret));\n\n        ASSERT(0 == memcmp(mac, test_mac[i], 16U), (\"failed (mac)\\n\"));\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    return 0;\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_POLY1305_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto.c",
    "content": "/*\n *  PSA crypto layer on top of Mbed TLS crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n#include \"psa_crypto_core_common.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n\n#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)\n#include \"check_crypto_config.h\"\n#endif\n\n#include \"psa/crypto.h\"\n#include \"psa/crypto_values.h\"\n\n#include \"psa_crypto_cipher.h\"\n#include \"psa_crypto_core.h\"\n#include \"psa_crypto_invasive.h\"\n#include \"psa_crypto_driver_wrappers.h\"\n#include \"psa_crypto_driver_wrappers_no_static.h\"\n#include \"psa_crypto_ecp.h\"\n#include \"psa_crypto_ffdh.h\"\n#include \"psa_crypto_hash.h\"\n#include \"psa_crypto_mac.h\"\n#include \"psa_crypto_rsa.h\"\n#include \"psa_crypto_ecp.h\"\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n#include \"psa_crypto_se.h\"\n#endif\n#include \"psa_crypto_slot_management.h\"\n/* Include internal declarations that are useful for implementing persistently\n * stored keys. */\n#include \"psa_crypto_storage.h\"\n\n#include \"psa_crypto_random_impl.h\"\n\n#include <stdlib.h>\n#include <string.h>\n#include \"mbedtls/platform.h\"\n\n#include \"mbedtls/aes.h\"\n#include \"mbedtls/asn1.h\"\n#include \"mbedtls/asn1write.h\"\n#include \"mbedtls/bignum.h\"\n#include \"mbedtls/camellia.h\"\n#include \"mbedtls/chacha20.h\"\n#include \"mbedtls/chachapoly.h\"\n#include \"mbedtls/cipher.h\"\n#include \"mbedtls/ccm.h\"\n#include \"mbedtls/cmac.h\"\n#include \"mbedtls/constant_time.h\"\n#include \"mbedtls/des.h\"\n#include \"mbedtls/ecdh.h\"\n#include \"mbedtls/ecp.h\"\n#include \"mbedtls/entropy.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/gcm.h\"\n#include \"mbedtls/md5.h\"\n#include \"mbedtls/pk.h\"\n#include \"pk_wrap.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/ripemd160.h\"\n#include \"mbedtls/rsa.h\"\n#include \"mbedtls/sha1.h\"\n#include \"mbedtls/sha256.h\"\n#include \"mbedtls/sha512.h\"\n#include \"mbedtls/psa_util.h\"\n#include \"mbedtls/threading.h\"\n\n#include \"constant_time_internal.h\"\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) ||          \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) ||  \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)\n#define BUILTIN_ALG_ANY_HKDF 1\n#endif\n\n/****************************************************************/\n/* Global data, support functions and library management */\n/****************************************************************/\n\nstatic int key_type_is_raw_bytes(psa_key_type_t type)\n{\n    return PSA_KEY_TYPE_IS_UNSTRUCTURED(type);\n}\n\n/* Values for psa_global_data_t::rng_state */\n#define RNG_NOT_INITIALIZED 0\n#define RNG_INITIALIZED 1\n#define RNG_SEEDED 2\n\n/* IDs for PSA crypto subsystems. Starts at 1 to catch potential uninitialized\n * variables as arguments. */\ntypedef enum {\n    PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS = 1,\n    PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS,\n    PSA_CRYPTO_SUBSYSTEM_RNG,\n    PSA_CRYPTO_SUBSYSTEM_TRANSACTION,\n} mbedtls_psa_crypto_subsystem;\n\n/* Initialization flags for global_data::initialized */\n#define PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED    0x01\n#define PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED          0x02\n#define PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED        0x04\n\n#define PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED                ( \\\n        PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED | \\\n        PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED | \\\n        PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)\n\ntypedef struct {\n    uint8_t initialized;\n    uint8_t rng_state;\n    mbedtls_psa_random_context_t rng;\n} psa_global_data_t;\n\nstatic psa_global_data_t global_data;\n\nstatic uint8_t psa_get_initialized(void)\n{\n    uint8_t initialized;\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n    initialized = global_data.rng_state == RNG_SEEDED;\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n    initialized =\n        (initialized && (global_data.initialized == PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED));\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n    return initialized;\n}\n\nstatic uint8_t psa_get_drivers_initialized(void)\n{\n    uint8_t initialized;\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n    initialized = (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) != 0;\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n    return initialized;\n}\n\n#define GUARD_MODULE_INITIALIZED        \\\n    if (psa_get_initialized() == 0)     \\\n    return PSA_ERROR_BAD_STATE;\n\n#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\n\n/* Declare a local copy of an input buffer and a variable that will be used\n * to store a pointer to the start of the buffer.\n *\n * Note: This macro must be called before any operations which may jump to\n * the exit label, so that the local input copy object is safe to be freed.\n *\n * Assumptions:\n * - input is the name of a pointer to the buffer to be copied\n * - The name LOCAL_INPUT_COPY_OF_input is unused in the current scope\n * - input_copy_name is a name that is unused in the current scope\n */\n#define LOCAL_INPUT_DECLARE(input, input_copy_name) \\\n    psa_crypto_local_input_t LOCAL_INPUT_COPY_OF_##input = PSA_CRYPTO_LOCAL_INPUT_INIT; \\\n    const uint8_t *input_copy_name = NULL;\n\n/* Allocate a copy of the buffer input and set the pointer input_copy to\n * point to the start of the copy.\n *\n * Assumptions:\n * - psa_status_t status exists\n * - An exit label is declared\n * - input is the name of a pointer to the buffer to be copied\n * - LOCAL_INPUT_DECLARE(input, input_copy) has previously been called\n */\n#define LOCAL_INPUT_ALLOC(input, length, input_copy) \\\n    status = psa_crypto_local_input_alloc(input, length, \\\n                                          &LOCAL_INPUT_COPY_OF_##input); \\\n    if (status != PSA_SUCCESS) { \\\n        goto exit; \\\n    } \\\n    input_copy = LOCAL_INPUT_COPY_OF_##input.buffer;\n\n/* Free the local input copy allocated previously by LOCAL_INPUT_ALLOC()\n *\n * Assumptions:\n * - input_copy is the name of the input copy pointer set by LOCAL_INPUT_ALLOC()\n * - input is the name of the original buffer that was copied\n */\n#define LOCAL_INPUT_FREE(input, input_copy) \\\n    input_copy = NULL; \\\n    psa_crypto_local_input_free(&LOCAL_INPUT_COPY_OF_##input);\n\n/* Declare a local copy of an output buffer and a variable that will be used\n * to store a pointer to the start of the buffer.\n *\n * Note: This macro must be called before any operations which may jump to\n * the exit label, so that the local output copy object is safe to be freed.\n *\n * Assumptions:\n * - output is the name of a pointer to the buffer to be copied\n * - The name LOCAL_OUTPUT_COPY_OF_output is unused in the current scope\n * - output_copy_name is a name that is unused in the current scope\n */\n#define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \\\n    psa_crypto_local_output_t LOCAL_OUTPUT_COPY_OF_##output = PSA_CRYPTO_LOCAL_OUTPUT_INIT; \\\n    uint8_t *output_copy_name = NULL;\n\n/* Allocate a copy of the buffer output and set the pointer output_copy to\n * point to the start of the copy.\n *\n * Assumptions:\n * - psa_status_t status exists\n * - An exit label is declared\n * - output is the name of a pointer to the buffer to be copied\n * - LOCAL_OUTPUT_DECLARE(output, output_copy) has previously been called\n */\n#define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \\\n    status = psa_crypto_local_output_alloc(output, length, \\\n                                           &LOCAL_OUTPUT_COPY_OF_##output); \\\n    if (status != PSA_SUCCESS) { \\\n        goto exit; \\\n    } \\\n    output_copy = LOCAL_OUTPUT_COPY_OF_##output.buffer;\n\n/* Free the local output copy allocated previously by LOCAL_OUTPUT_ALLOC()\n * after first copying back its contents to the original buffer.\n *\n * Assumptions:\n * - psa_status_t status exists\n * - output_copy is the name of the output copy pointer set by LOCAL_OUTPUT_ALLOC()\n * - output is the name of the original buffer that was copied\n */\n#define LOCAL_OUTPUT_FREE(output, output_copy) \\\n    output_copy = NULL; \\\n    do { \\\n        psa_status_t local_output_status; \\\n        local_output_status = psa_crypto_local_output_free(&LOCAL_OUTPUT_COPY_OF_##output); \\\n        if (local_output_status != PSA_SUCCESS) { \\\n            /* Since this error case is an internal error, it's more serious than \\\n             * any existing error code and so it's fine to overwrite the existing \\\n             * status. */ \\\n            status = local_output_status; \\\n        } \\\n    } while (0)\n#else /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */\n#define LOCAL_INPUT_DECLARE(input, input_copy_name) \\\n    const uint8_t *input_copy_name = NULL;\n#define LOCAL_INPUT_ALLOC(input, length, input_copy) \\\n    input_copy = input;\n#define LOCAL_INPUT_FREE(input, input_copy) \\\n    input_copy = NULL;\n#define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \\\n    uint8_t *output_copy_name = NULL;\n#define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \\\n    output_copy = output;\n#define LOCAL_OUTPUT_FREE(output, output_copy) \\\n    output_copy = NULL;\n#endif /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */\n\n\nint psa_can_do_hash(psa_algorithm_t hash_alg)\n{\n    (void) hash_alg;\n    return psa_get_drivers_initialized();\n}\n\nint psa_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t cipher_alg)\n{\n    (void) key_type;\n    (void) cipher_alg;\n    return psa_get_drivers_initialized();\n}\n\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) ||       \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) ||     \\\n    defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)\nstatic int psa_is_dh_key_size_valid(size_t bits)\n{\n    switch (bits) {\n#if defined(PSA_WANT_DH_RFC7919_2048)\n        case 2048:\n            return 1;\n#endif /* PSA_WANT_DH_RFC7919_2048 */\n#if defined(PSA_WANT_DH_RFC7919_3072)\n        case 3072:\n            return 1;\n#endif /* PSA_WANT_DH_RFC7919_3072 */\n#if defined(PSA_WANT_DH_RFC7919_4096)\n        case 4096:\n            return 1;\n#endif /* PSA_WANT_DH_RFC7919_4096 */\n#if defined(PSA_WANT_DH_RFC7919_6144)\n        case 6144:\n            return 1;\n#endif /* PSA_WANT_DH_RFC7919_6144 */\n#if defined(PSA_WANT_DH_RFC7919_8192)\n        case 8192:\n            return 1;\n#endif /* PSA_WANT_DH_RFC7919_8192 */\n        default:\n            return 0;\n    }\n}\n#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT ||\n          MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY ||\n          PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE */\n\npsa_status_t mbedtls_to_psa_error(int ret)\n{\n    /* Mbed TLS error codes can combine a high-level error code and a\n     * low-level error code. The low-level error usually reflects the\n     * root cause better, so dispatch on that preferably. */\n    int low_level_ret = -(-ret & 0x007f);\n    switch (low_level_ret != 0 ? low_level_ret : ret) {\n        case 0:\n            return PSA_SUCCESS;\n\n#if defined(MBEDTLS_AES_C)\n        case MBEDTLS_ERR_AES_INVALID_KEY_LENGTH:\n        case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH:\n            return PSA_ERROR_NOT_SUPPORTED;\n        case MBEDTLS_ERR_AES_BAD_INPUT_DATA:\n            return PSA_ERROR_INVALID_ARGUMENT;\n#endif\n\n#if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_ASN1_WRITE_C)\n        case MBEDTLS_ERR_ASN1_OUT_OF_DATA:\n        case MBEDTLS_ERR_ASN1_UNEXPECTED_TAG:\n        case MBEDTLS_ERR_ASN1_INVALID_LENGTH:\n        case MBEDTLS_ERR_ASN1_LENGTH_MISMATCH:\n        case MBEDTLS_ERR_ASN1_INVALID_DATA:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case MBEDTLS_ERR_ASN1_ALLOC_FAILED:\n            return PSA_ERROR_INSUFFICIENT_MEMORY;\n        case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL:\n            return PSA_ERROR_BUFFER_TOO_SMALL;\n#endif\n\n#if defined(MBEDTLS_CAMELLIA_C)\n        case MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA:\n        case MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH:\n            return PSA_ERROR_NOT_SUPPORTED;\n#endif\n\n#if defined(MBEDTLS_CCM_C)\n        case MBEDTLS_ERR_CCM_BAD_INPUT:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case MBEDTLS_ERR_CCM_AUTH_FAILED:\n            return PSA_ERROR_INVALID_SIGNATURE;\n#endif\n\n#if defined(MBEDTLS_CHACHA20_C)\n        case MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA:\n            return PSA_ERROR_INVALID_ARGUMENT;\n#endif\n\n#if defined(MBEDTLS_CHACHAPOLY_C)\n        case MBEDTLS_ERR_CHACHAPOLY_BAD_STATE:\n            return PSA_ERROR_BAD_STATE;\n        case MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED:\n            return PSA_ERROR_INVALID_SIGNATURE;\n#endif\n\n#if defined(MBEDTLS_CIPHER_C)\n        case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE:\n            return PSA_ERROR_NOT_SUPPORTED;\n        case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case MBEDTLS_ERR_CIPHER_ALLOC_FAILED:\n            return PSA_ERROR_INSUFFICIENT_MEMORY;\n        case MBEDTLS_ERR_CIPHER_INVALID_PADDING:\n            return PSA_ERROR_INVALID_PADDING;\n        case MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case MBEDTLS_ERR_CIPHER_AUTH_FAILED:\n            return PSA_ERROR_INVALID_SIGNATURE;\n        case MBEDTLS_ERR_CIPHER_INVALID_CONTEXT:\n            return PSA_ERROR_CORRUPTION_DETECTED;\n#endif\n\n#if !(defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) ||      \\\n            defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE))\n        /* Only check CTR_DRBG error codes if underlying mbedtls_xxx\n         * functions are passed a CTR_DRBG instance. */\n        case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED:\n            return PSA_ERROR_INSUFFICIENT_ENTROPY;\n        case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG:\n        case MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG:\n            return PSA_ERROR_NOT_SUPPORTED;\n        case MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR:\n            return PSA_ERROR_INSUFFICIENT_ENTROPY;\n#endif\n\n#if defined(MBEDTLS_DES_C)\n        case MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH:\n            return PSA_ERROR_NOT_SUPPORTED;\n#endif\n\n        case MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED:\n        case MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE:\n        case MBEDTLS_ERR_ENTROPY_SOURCE_FAILED:\n            return PSA_ERROR_INSUFFICIENT_ENTROPY;\n\n#if defined(MBEDTLS_GCM_C)\n        case MBEDTLS_ERR_GCM_AUTH_FAILED:\n            return PSA_ERROR_INVALID_SIGNATURE;\n        case MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL:\n            return PSA_ERROR_BUFFER_TOO_SMALL;\n        case MBEDTLS_ERR_GCM_BAD_INPUT:\n            return PSA_ERROR_INVALID_ARGUMENT;\n#endif\n\n#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) &&        \\\n            defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)\n        /* Only check HMAC_DRBG error codes if underlying mbedtls_xxx\n         * functions are passed a HMAC_DRBG instance. */\n        case MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED:\n            return PSA_ERROR_INSUFFICIENT_ENTROPY;\n        case MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG:\n        case MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG:\n            return PSA_ERROR_NOT_SUPPORTED;\n        case MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR:\n            return PSA_ERROR_INSUFFICIENT_ENTROPY;\n#endif\n\n#if defined(MBEDTLS_MD_LIGHT)\n        case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE:\n            return PSA_ERROR_NOT_SUPPORTED;\n        case MBEDTLS_ERR_MD_BAD_INPUT_DATA:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case MBEDTLS_ERR_MD_ALLOC_FAILED:\n            return PSA_ERROR_INSUFFICIENT_MEMORY;\n#if defined(MBEDTLS_FS_IO)\n        case MBEDTLS_ERR_MD_FILE_IO_ERROR:\n            return PSA_ERROR_STORAGE_FAILURE;\n#endif\n#endif\n\n#if defined(MBEDTLS_BIGNUM_C)\n#if defined(MBEDTLS_FS_IO)\n        case MBEDTLS_ERR_MPI_FILE_IO_ERROR:\n            return PSA_ERROR_STORAGE_FAILURE;\n#endif\n        case MBEDTLS_ERR_MPI_BAD_INPUT_DATA:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case MBEDTLS_ERR_MPI_INVALID_CHARACTER:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL:\n            return PSA_ERROR_BUFFER_TOO_SMALL;\n        case MBEDTLS_ERR_MPI_NEGATIVE_VALUE:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case MBEDTLS_ERR_MPI_DIVISION_BY_ZERO:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case MBEDTLS_ERR_MPI_ALLOC_FAILED:\n            return PSA_ERROR_INSUFFICIENT_MEMORY;\n#endif\n\n#if defined(MBEDTLS_PK_C)\n        case MBEDTLS_ERR_PK_ALLOC_FAILED:\n            return PSA_ERROR_INSUFFICIENT_MEMORY;\n        case MBEDTLS_ERR_PK_TYPE_MISMATCH:\n        case MBEDTLS_ERR_PK_BAD_INPUT_DATA:\n            return PSA_ERROR_INVALID_ARGUMENT;\n#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || defined(MBEDTLS_FS_IO) || \\\n            defined(MBEDTLS_PSA_ITS_FILE_C)\n        case MBEDTLS_ERR_PK_FILE_IO_ERROR:\n            return PSA_ERROR_STORAGE_FAILURE;\n#endif\n        case MBEDTLS_ERR_PK_KEY_INVALID_VERSION:\n        case MBEDTLS_ERR_PK_KEY_INVALID_FORMAT:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case MBEDTLS_ERR_PK_UNKNOWN_PK_ALG:\n            return PSA_ERROR_NOT_SUPPORTED;\n        case MBEDTLS_ERR_PK_PASSWORD_REQUIRED:\n        case MBEDTLS_ERR_PK_PASSWORD_MISMATCH:\n            return PSA_ERROR_NOT_PERMITTED;\n        case MBEDTLS_ERR_PK_INVALID_PUBKEY:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case MBEDTLS_ERR_PK_INVALID_ALG:\n        case MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE:\n        case MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE:\n            return PSA_ERROR_NOT_SUPPORTED;\n        case MBEDTLS_ERR_PK_SIG_LEN_MISMATCH:\n            return PSA_ERROR_INVALID_SIGNATURE;\n        case MBEDTLS_ERR_PK_BUFFER_TOO_SMALL:\n            return PSA_ERROR_BUFFER_TOO_SMALL;\n#endif\n\n        case MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED:\n            return PSA_ERROR_HARDWARE_FAILURE;\n        case MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:\n            return PSA_ERROR_NOT_SUPPORTED;\n\n#if defined(MBEDTLS_RSA_C)\n        case MBEDTLS_ERR_RSA_BAD_INPUT_DATA:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case MBEDTLS_ERR_RSA_INVALID_PADDING:\n            return PSA_ERROR_INVALID_PADDING;\n        case MBEDTLS_ERR_RSA_KEY_GEN_FAILED:\n            return PSA_ERROR_HARDWARE_FAILURE;\n        case MBEDTLS_ERR_RSA_KEY_CHECK_FAILED:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case MBEDTLS_ERR_RSA_PUBLIC_FAILED:\n        case MBEDTLS_ERR_RSA_PRIVATE_FAILED:\n            return PSA_ERROR_CORRUPTION_DETECTED;\n        case MBEDTLS_ERR_RSA_VERIFY_FAILED:\n            return PSA_ERROR_INVALID_SIGNATURE;\n        case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE:\n            return PSA_ERROR_BUFFER_TOO_SMALL;\n        case MBEDTLS_ERR_RSA_RNG_FAILED:\n            return PSA_ERROR_INSUFFICIENT_ENTROPY;\n#endif\n\n#if defined(MBEDTLS_ECP_LIGHT)\n        case MBEDTLS_ERR_ECP_BAD_INPUT_DATA:\n        case MBEDTLS_ERR_ECP_INVALID_KEY:\n            return PSA_ERROR_INVALID_ARGUMENT;\n        case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL:\n            return PSA_ERROR_BUFFER_TOO_SMALL;\n        case MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE:\n            return PSA_ERROR_NOT_SUPPORTED;\n        case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH:\n        case MBEDTLS_ERR_ECP_VERIFY_FAILED:\n            return PSA_ERROR_INVALID_SIGNATURE;\n        case MBEDTLS_ERR_ECP_ALLOC_FAILED:\n            return PSA_ERROR_INSUFFICIENT_MEMORY;\n        case MBEDTLS_ERR_ECP_RANDOM_FAILED:\n            return PSA_ERROR_INSUFFICIENT_ENTROPY;\n\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n        case MBEDTLS_ERR_ECP_IN_PROGRESS:\n            return PSA_OPERATION_INCOMPLETE;\n#endif\n#endif\n\n        case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED:\n            return PSA_ERROR_CORRUPTION_DETECTED;\n\n        default:\n            return PSA_ERROR_GENERIC_ERROR;\n    }\n}\n\n/**\n * \\brief                       For output buffers which contain \"tags\"\n *                              (outputs that may be checked for validity like\n *                              hashes, MACs and signatures), fill the unused\n *                              part of the output buffer (the whole buffer on\n *                              error, the trailing part on success) with\n *                              something that isn't a valid tag (barring an\n *                              attack on the tag and deliberately-crafted\n *                              input), in case the caller doesn't check the\n *                              return status properly.\n *\n * \\param output_buffer         Pointer to buffer to wipe. May not be NULL\n *                              unless \\p output_buffer_size is zero.\n * \\param status                Status of function called to generate\n *                              output_buffer originally\n * \\param output_buffer_size    Size of output buffer. If zero, \\p output_buffer\n *                              could be NULL.\n * \\param output_buffer_length  Length of data written to output_buffer, must be\n *                              less than \\p output_buffer_size\n */\nstatic void psa_wipe_tag_output_buffer(uint8_t *output_buffer, psa_status_t status,\n                                       size_t output_buffer_size, size_t output_buffer_length)\n{\n    size_t offset = 0;\n\n    if (output_buffer_size == 0) {\n        /* If output_buffer_size is 0 then we have nothing to do. We must not\n           call memset because output_buffer may be NULL in this case */\n        return;\n    }\n\n    if (status == PSA_SUCCESS) {\n        offset = output_buffer_length;\n    }\n\n    memset(output_buffer + offset, '!', output_buffer_size - offset);\n}\n\n\npsa_status_t psa_validate_unstructured_key_bit_size(psa_key_type_t type,\n                                                    size_t bits)\n{\n    /* Check that the bit size is acceptable for the key type */\n    switch (type) {\n        case PSA_KEY_TYPE_RAW_DATA:\n        case PSA_KEY_TYPE_HMAC:\n        case PSA_KEY_TYPE_DERIVE:\n        case PSA_KEY_TYPE_PASSWORD:\n        case PSA_KEY_TYPE_PASSWORD_HASH:\n            break;\n#if defined(PSA_WANT_KEY_TYPE_AES)\n        case PSA_KEY_TYPE_AES:\n            if (bits != 128 && bits != 192 && bits != 256) {\n                return PSA_ERROR_INVALID_ARGUMENT;\n            }\n            break;\n#endif\n#if defined(PSA_WANT_KEY_TYPE_ARIA)\n        case PSA_KEY_TYPE_ARIA:\n            if (bits != 128 && bits != 192 && bits != 256) {\n                return PSA_ERROR_INVALID_ARGUMENT;\n            }\n            break;\n#endif\n#if defined(PSA_WANT_KEY_TYPE_CAMELLIA)\n        case PSA_KEY_TYPE_CAMELLIA:\n            if (bits != 128 && bits != 192 && bits != 256) {\n                return PSA_ERROR_INVALID_ARGUMENT;\n            }\n            break;\n#endif\n#if defined(PSA_WANT_KEY_TYPE_DES)\n        case PSA_KEY_TYPE_DES:\n            if (bits != 64 && bits != 128 && bits != 192) {\n                return PSA_ERROR_INVALID_ARGUMENT;\n            }\n            break;\n#endif\n#if defined(PSA_WANT_KEY_TYPE_CHACHA20)\n        case PSA_KEY_TYPE_CHACHA20:\n            if (bits != 256) {\n                return PSA_ERROR_INVALID_ARGUMENT;\n            }\n            break;\n#endif\n        default:\n            return PSA_ERROR_NOT_SUPPORTED;\n    }\n    if (bits % 8 != 0) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    return PSA_SUCCESS;\n}\n\n/** Check whether a given key type is valid for use with a given MAC algorithm\n *\n * Upon successful return of this function, the behavior of #PSA_MAC_LENGTH\n * when called with the validated \\p algorithm and \\p key_type is well-defined.\n *\n * \\param[in] algorithm     The specific MAC algorithm (can be wildcard).\n * \\param[in] key_type      The key type of the key to be used with the\n *                          \\p algorithm.\n *\n * \\retval #PSA_SUCCESS\n *         The \\p key_type is valid for use with the \\p algorithm\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The \\p key_type is not valid for use with the \\p algorithm\n */\nMBEDTLS_STATIC_TESTABLE psa_status_t psa_mac_key_can_do(\n    psa_algorithm_t algorithm,\n    psa_key_type_t key_type)\n{\n    if (PSA_ALG_IS_HMAC(algorithm)) {\n        if (key_type == PSA_KEY_TYPE_HMAC) {\n            return PSA_SUCCESS;\n        }\n    }\n\n    if (PSA_ALG_IS_BLOCK_CIPHER_MAC(algorithm)) {\n        /* Check that we're calling PSA_BLOCK_CIPHER_BLOCK_LENGTH with a cipher\n         * key. */\n        if ((key_type & PSA_KEY_TYPE_CATEGORY_MASK) ==\n            PSA_KEY_TYPE_CATEGORY_SYMMETRIC) {\n            /* PSA_BLOCK_CIPHER_BLOCK_LENGTH returns 1 for stream ciphers and\n             * the block length (larger than 1) for block ciphers. */\n            if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) > 1) {\n                return PSA_SUCCESS;\n            }\n        }\n    }\n\n    return PSA_ERROR_INVALID_ARGUMENT;\n}\n\npsa_status_t psa_allocate_buffer_to_slot(psa_key_slot_t *slot,\n                                         size_t buffer_length)\n{\n#if defined(MBEDTLS_PSA_STATIC_KEY_SLOTS)\n    if (buffer_length > ((size_t) MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE)) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n#else\n    if (slot->key.data != NULL) {\n        return PSA_ERROR_ALREADY_EXISTS;\n    }\n\n    slot->key.data = mbedtls_calloc(1, buffer_length);\n    if (slot->key.data == NULL) {\n        return PSA_ERROR_INSUFFICIENT_MEMORY;\n    }\n#endif\n\n    slot->key.bytes = buffer_length;\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_copy_key_material_into_slot(psa_key_slot_t *slot,\n                                             const uint8_t *data,\n                                             size_t data_length)\n{\n    psa_status_t status = psa_allocate_buffer_to_slot(slot,\n                                                      data_length);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    memcpy(slot->key.data, data, data_length);\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_import_key_into_slot(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *data, size_t data_length,\n    uint8_t *key_buffer, size_t key_buffer_size,\n    size_t *key_buffer_length, size_t *bits)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_type_t type = attributes->type;\n\n    /* zero-length keys are never supported. */\n    if (data_length == 0) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    if (key_type_is_raw_bytes(type)) {\n        *bits = PSA_BYTES_TO_BITS(data_length);\n\n        status = psa_validate_unstructured_key_bit_size(attributes->type,\n                                                        *bits);\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n\n        /* Copy the key material. */\n        memcpy(key_buffer, data, data_length);\n        *key_buffer_length = data_length;\n        (void) key_buffer_size;\n\n        return PSA_SUCCESS;\n    } else if (PSA_KEY_TYPE_IS_ASYMMETRIC(type)) {\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \\\n        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY)\n        if (PSA_KEY_TYPE_IS_DH(type)) {\n            if (psa_is_dh_key_size_valid(PSA_BYTES_TO_BITS(data_length)) == 0) {\n                return PSA_ERROR_NOT_SUPPORTED;\n            }\n            return mbedtls_psa_ffdh_import_key(attributes,\n                                               data, data_length,\n                                               key_buffer, key_buffer_size,\n                                               key_buffer_length,\n                                               bits);\n        }\n#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \\\n        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)\n        if (PSA_KEY_TYPE_IS_ECC(type)) {\n            return mbedtls_psa_ecp_import_key(attributes,\n                                              data, data_length,\n                                              key_buffer, key_buffer_size,\n                                              key_buffer_length,\n                                              bits);\n        }\n#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */\n#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \\\n        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \\\n        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)\n        if (PSA_KEY_TYPE_IS_RSA(type)) {\n            return mbedtls_psa_rsa_import_key(attributes,\n                                              data, data_length,\n                                              key_buffer, key_buffer_size,\n                                              key_buffer_length,\n                                              bits);\n        }\n#endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) &&\n           defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */\n    }\n\n    return PSA_ERROR_NOT_SUPPORTED;\n}\n\n/** Calculate the intersection of two algorithm usage policies.\n *\n * Return 0 (which allows no operation) on incompatibility.\n */\nstatic psa_algorithm_t psa_key_policy_algorithm_intersection(\n    psa_key_type_t key_type,\n    psa_algorithm_t alg1,\n    psa_algorithm_t alg2)\n{\n    /* Common case: both sides actually specify the same policy. */\n    if (alg1 == alg2) {\n        return alg1;\n    }\n    /* If the policies are from the same hash-and-sign family, check\n     * if one is a wildcard. If so the other has the specific algorithm. */\n    if (PSA_ALG_IS_SIGN_HASH(alg1) &&\n        PSA_ALG_IS_SIGN_HASH(alg2) &&\n        (alg1 & ~PSA_ALG_HASH_MASK) == (alg2 & ~PSA_ALG_HASH_MASK)) {\n        if (PSA_ALG_SIGN_GET_HASH(alg1) == PSA_ALG_ANY_HASH) {\n            return alg2;\n        }\n        if (PSA_ALG_SIGN_GET_HASH(alg2) == PSA_ALG_ANY_HASH) {\n            return alg1;\n        }\n    }\n    /* If the policies are from the same AEAD family, check whether\n     * one of them is a minimum-tag-length wildcard. Calculate the most\n     * restrictive tag length. */\n    if (PSA_ALG_IS_AEAD(alg1) && PSA_ALG_IS_AEAD(alg2) &&\n        (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg1, 0) ==\n         PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg2, 0))) {\n        size_t alg1_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg1);\n        size_t alg2_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg2);\n        size_t restricted_len = alg1_len > alg2_len ? alg1_len : alg2_len;\n\n        /* If both are wildcards, return most restrictive wildcard */\n        if (((alg1 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) &&\n            ((alg2 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0)) {\n            return PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(\n                alg1, restricted_len);\n        }\n        /* If only one is a wildcard, return specific algorithm if compatible. */\n        if (((alg1 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) &&\n            (alg1_len <= alg2_len)) {\n            return alg2;\n        }\n        if (((alg2 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) &&\n            (alg2_len <= alg1_len)) {\n            return alg1;\n        }\n    }\n    /* If the policies are from the same MAC family, check whether one\n     * of them is a minimum-MAC-length policy. Calculate the most\n     * restrictive tag length. */\n    if (PSA_ALG_IS_MAC(alg1) && PSA_ALG_IS_MAC(alg2) &&\n        (PSA_ALG_FULL_LENGTH_MAC(alg1) ==\n         PSA_ALG_FULL_LENGTH_MAC(alg2))) {\n        /* Validate the combination of key type and algorithm. Since the base\n         * algorithm of alg1 and alg2 are the same, we only need this once. */\n        if (PSA_SUCCESS != psa_mac_key_can_do(alg1, key_type)) {\n            return 0;\n        }\n\n        /* Get the (exact or at-least) output lengths for both sides of the\n         * requested intersection. None of the currently supported algorithms\n         * have an output length dependent on the actual key size, so setting it\n         * to a bogus value of 0 is currently OK.\n         *\n         * Note that for at-least-this-length wildcard algorithms, the output\n         * length is set to the shortest allowed length, which allows us to\n         * calculate the most restrictive tag length for the intersection. */\n        size_t alg1_len = PSA_MAC_LENGTH(key_type, 0, alg1);\n        size_t alg2_len = PSA_MAC_LENGTH(key_type, 0, alg2);\n        size_t restricted_len = alg1_len > alg2_len ? alg1_len : alg2_len;\n\n        /* If both are wildcards, return most restrictive wildcard */\n        if (((alg1 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) &&\n            ((alg2 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0)) {\n            return PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(alg1, restricted_len);\n        }\n\n        /* If only one is an at-least-this-length policy, the intersection would\n         * be the other (fixed-length) policy as long as said fixed length is\n         * equal to or larger than the shortest allowed length. */\n        if ((alg1 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) {\n            return (alg1_len <= alg2_len) ? alg2 : 0;\n        }\n        if ((alg2 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) {\n            return (alg2_len <= alg1_len) ? alg1 : 0;\n        }\n\n        /* If none of them are wildcards, check whether they define the same tag\n         * length. This is still possible here when one is default-length and\n         * the other specific-length. Ensure to always return the\n         * specific-length version for the intersection. */\n        if (alg1_len == alg2_len) {\n            return PSA_ALG_TRUNCATED_MAC(alg1, alg1_len);\n        }\n    }\n    /* If the policies are incompatible, allow nothing. */\n    return 0;\n}\n\nstatic int psa_key_algorithm_permits(psa_key_type_t key_type,\n                                     psa_algorithm_t policy_alg,\n                                     psa_algorithm_t requested_alg)\n{\n    /* Common case: the policy only allows requested_alg. */\n    if (requested_alg == policy_alg) {\n        return 1;\n    }\n    /* If policy_alg is a hash-and-sign with a wildcard for the hash,\n     * and requested_alg is the same hash-and-sign family with any hash,\n     * then requested_alg is compliant with policy_alg. */\n    if (PSA_ALG_IS_SIGN_HASH(requested_alg) &&\n        PSA_ALG_SIGN_GET_HASH(policy_alg) == PSA_ALG_ANY_HASH) {\n        return (policy_alg & ~PSA_ALG_HASH_MASK) ==\n               (requested_alg & ~PSA_ALG_HASH_MASK);\n    }\n    /* If policy_alg is a wildcard AEAD algorithm of the same base as\n     * the requested algorithm, check the requested tag length to be\n     * equal-length or longer than the wildcard-specified length. */\n    if (PSA_ALG_IS_AEAD(policy_alg) &&\n        PSA_ALG_IS_AEAD(requested_alg) &&\n        (PSA_ALG_AEAD_WITH_SHORTENED_TAG(policy_alg, 0) ==\n         PSA_ALG_AEAD_WITH_SHORTENED_TAG(requested_alg, 0)) &&\n        ((policy_alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0)) {\n        return PSA_ALG_AEAD_GET_TAG_LENGTH(policy_alg) <=\n               PSA_ALG_AEAD_GET_TAG_LENGTH(requested_alg);\n    }\n    /* If policy_alg is a MAC algorithm of the same base as the requested\n     * algorithm, check whether their MAC lengths are compatible. */\n    if (PSA_ALG_IS_MAC(policy_alg) &&\n        PSA_ALG_IS_MAC(requested_alg) &&\n        (PSA_ALG_FULL_LENGTH_MAC(policy_alg) ==\n         PSA_ALG_FULL_LENGTH_MAC(requested_alg))) {\n        /* Validate the combination of key type and algorithm. Since the policy\n         * and requested algorithms are the same, we only need this once. */\n        if (PSA_SUCCESS != psa_mac_key_can_do(policy_alg, key_type)) {\n            return 0;\n        }\n\n        /* Get both the requested output length for the algorithm which is to be\n         * verified, and the default output length for the base algorithm.\n         * Note that none of the currently supported algorithms have an output\n         * length dependent on actual key size, so setting it to a bogus value\n         * of 0 is currently OK. */\n        size_t requested_output_length = PSA_MAC_LENGTH(\n            key_type, 0, requested_alg);\n        size_t default_output_length = PSA_MAC_LENGTH(\n            key_type, 0,\n            PSA_ALG_FULL_LENGTH_MAC(requested_alg));\n\n        /* If the policy is default-length, only allow an algorithm with\n         * a declared exact-length matching the default. */\n        if (PSA_MAC_TRUNCATED_LENGTH(policy_alg) == 0) {\n            return requested_output_length == default_output_length;\n        }\n\n        /* If the requested algorithm is default-length, allow it if the policy\n         * length exactly matches the default length. */\n        if (PSA_MAC_TRUNCATED_LENGTH(requested_alg) == 0 &&\n            PSA_MAC_TRUNCATED_LENGTH(policy_alg) == default_output_length) {\n            return 1;\n        }\n\n        /* If policy_alg is an at-least-this-length wildcard MAC algorithm,\n         * check for the requested MAC length to be equal to or longer than the\n         * minimum allowed length. */\n        if ((policy_alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) {\n            return PSA_MAC_TRUNCATED_LENGTH(policy_alg) <=\n                   requested_output_length;\n        }\n    }\n    /* If policy_alg is a generic key agreement operation, then using it for\n     * a key derivation with that key agreement should also be allowed. This\n     * behaviour is expected to be defined in a future specification version. */\n    if (PSA_ALG_IS_RAW_KEY_AGREEMENT(policy_alg) &&\n        PSA_ALG_IS_KEY_AGREEMENT(requested_alg)) {\n        return PSA_ALG_KEY_AGREEMENT_GET_BASE(requested_alg) ==\n               policy_alg;\n    }\n    /* If it isn't explicitly permitted, it's forbidden. */\n    return 0;\n}\n\n/** Test whether a policy permits an algorithm.\n *\n * The caller must test usage flags separately.\n *\n * \\note This function requires providing the key type for which the policy is\n *       being validated, since some algorithm policy definitions (e.g. MAC)\n *       have different properties depending on what kind of cipher it is\n *       combined with.\n *\n * \\retval PSA_SUCCESS                  When \\p alg is a specific algorithm\n *                                      allowed by the \\p policy.\n * \\retval PSA_ERROR_INVALID_ARGUMENT   When \\p alg is not a specific algorithm\n * \\retval PSA_ERROR_NOT_PERMITTED      When \\p alg is a specific algorithm, but\n *                                      the \\p policy does not allow it.\n */\nstatic psa_status_t psa_key_policy_permits(const psa_key_policy_t *policy,\n                                           psa_key_type_t key_type,\n                                           psa_algorithm_t alg)\n{\n    /* '0' is not a valid algorithm */\n    if (alg == 0) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    /* A requested algorithm cannot be a wildcard. */\n    if (PSA_ALG_IS_WILDCARD(alg)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    if (psa_key_algorithm_permits(key_type, policy->alg, alg) ||\n        psa_key_algorithm_permits(key_type, policy->alg2, alg)) {\n        return PSA_SUCCESS;\n    } else {\n        return PSA_ERROR_NOT_PERMITTED;\n    }\n}\n\n/** Restrict a key policy based on a constraint.\n *\n * \\note This function requires providing the key type for which the policy is\n *       being restricted, since some algorithm policy definitions (e.g. MAC)\n *       have different properties depending on what kind of cipher it is\n *       combined with.\n *\n * \\param[in] key_type      The key type for which to restrict the policy\n * \\param[in,out] policy    The policy to restrict.\n * \\param[in] constraint    The policy constraint to apply.\n *\n * \\retval #PSA_SUCCESS\n *         \\c *policy contains the intersection of the original value of\n *         \\c *policy and \\c *constraint.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\c key_type, \\c *policy and \\c *constraint are incompatible.\n *         \\c *policy is unchanged.\n */\nstatic psa_status_t psa_restrict_key_policy(\n    psa_key_type_t key_type,\n    psa_key_policy_t *policy,\n    const psa_key_policy_t *constraint)\n{\n    psa_algorithm_t intersection_alg =\n        psa_key_policy_algorithm_intersection(key_type, policy->alg,\n                                              constraint->alg);\n    psa_algorithm_t intersection_alg2 =\n        psa_key_policy_algorithm_intersection(key_type, policy->alg2,\n                                              constraint->alg2);\n    if (intersection_alg == 0 && policy->alg != 0 && constraint->alg != 0) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n    if (intersection_alg2 == 0 && policy->alg2 != 0 && constraint->alg2 != 0) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n    policy->usage &= constraint->usage;\n    policy->alg = intersection_alg;\n    policy->alg2 = intersection_alg2;\n    return PSA_SUCCESS;\n}\n\n/** Get the description of a key given its identifier and policy constraints\n *  and lock it.\n *\n * The key must have allow all the usage flags set in \\p usage. If \\p alg is\n * nonzero, the key must allow operations with this algorithm. If \\p alg is\n * zero, the algorithm is not checked.\n *\n * In case of a persistent key, the function loads the description of the key\n * into a key slot if not already done.\n *\n * On success, the returned key slot has been registered for reading.\n * It is the responsibility of the caller to then unregister\n * once they have finished reading the contents of the slot.\n * The caller unregisters by calling psa_unregister_read() or\n * psa_unregister_read_under_mutex(). psa_unregister_read() must be called\n * if and only if the caller already holds the global key slot mutex\n * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates\n * the unregister with mutex lock and unlock operations.\n */\nstatic psa_status_t psa_get_and_lock_key_slot_with_policy(\n    mbedtls_svc_key_id_t key,\n    psa_key_slot_t **p_slot,\n    psa_key_usage_t usage,\n    psa_algorithm_t alg)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot = NULL;\n\n    status = psa_get_and_lock_key_slot(key, p_slot);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n    slot = *p_slot;\n\n    /* Enforce that usage policy for the key slot contains all the flags\n     * required by the usage parameter. There is one exception: public\n     * keys can always be exported, so we treat public key objects as\n     * if they had the export flag. */\n    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type)) {\n        usage &= ~PSA_KEY_USAGE_EXPORT;\n    }\n\n    if ((slot->attr.policy.usage & usage) != usage) {\n        status = PSA_ERROR_NOT_PERMITTED;\n        goto error;\n    }\n\n    /* Enforce that the usage policy permits the requested algorithm. */\n    if (alg != 0) {\n        status = psa_key_policy_permits(&slot->attr.policy,\n                                        slot->attr.type,\n                                        alg);\n        if (status != PSA_SUCCESS) {\n            goto error;\n        }\n    }\n\n    return PSA_SUCCESS;\n\nerror:\n    *p_slot = NULL;\n    psa_unregister_read_under_mutex(slot);\n\n    return status;\n}\n\n/** Get a key slot containing a transparent key and lock it.\n *\n * A transparent key is a key for which the key material is directly\n * available, as opposed to a key in a secure element and/or to be used\n * by a secure element.\n *\n * This is a temporary function that may be used instead of\n * psa_get_and_lock_key_slot_with_policy() when there is no opaque key support\n * for a cryptographic operation.\n *\n * On success, the returned key slot has been registered for reading.\n * It is the responsibility of the caller to then unregister\n * once they have finished reading the contents of the slot.\n * The caller unregisters by calling psa_unregister_read() or\n * psa_unregister_read_under_mutex(). psa_unregister_read() must be called\n * if and only if the caller already holds the global key slot mutex\n * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates\n * psa_unregister_read() with mutex lock and unlock operations.\n */\nstatic psa_status_t psa_get_and_lock_transparent_key_slot_with_policy(\n    mbedtls_svc_key_id_t key,\n    psa_key_slot_t **p_slot,\n    psa_key_usage_t usage,\n    psa_algorithm_t alg)\n{\n    psa_status_t status = psa_get_and_lock_key_slot_with_policy(key, p_slot,\n                                                                usage, alg);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    if (psa_key_lifetime_is_external((*p_slot)->attr.lifetime)) {\n        psa_unregister_read_under_mutex(*p_slot);\n        *p_slot = NULL;\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_remove_key_data_from_memory(psa_key_slot_t *slot)\n{\n#if defined(MBEDTLS_PSA_STATIC_KEY_SLOTS)\n    if (slot->key.bytes > 0) {\n        mbedtls_platform_zeroize(slot->key.data, MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE);\n    }\n#else\n    if (slot->key.data != NULL) {\n        mbedtls_zeroize_and_free(slot->key.data, slot->key.bytes);\n    }\n\n    slot->key.data = NULL;\n#endif /* MBEDTLS_PSA_STATIC_KEY_SLOTS */\n\n    slot->key.bytes = 0;\n\n    return PSA_SUCCESS;\n}\n\n/** Completely wipe a slot in memory, including its policy.\n * Persistent storage is not affected. */\npsa_status_t psa_wipe_key_slot(psa_key_slot_t *slot)\n{\n    psa_status_t status = psa_remove_key_data_from_memory(slot);\n\n    /*\n     * As the return error code may not be handled in case of multiple errors,\n     * do our best to report an unexpected amount of registered readers or\n     * an unexpected state.\n     * Assert with MBEDTLS_TEST_HOOK_TEST_ASSERT that the slot is valid for\n     * wiping.\n     * if the MBEDTLS_TEST_HOOKS configuration option is enabled and the\n     * function is called as part of the execution of a test suite, the\n     * execution of the test suite is stopped in error if the assertion fails.\n     */\n    switch (slot->state) {\n        case PSA_SLOT_FULL:\n        /* In this state psa_wipe_key_slot() must only be called if the\n         * caller is the last reader. */\n        case PSA_SLOT_PENDING_DELETION:\n            /* In this state psa_wipe_key_slot() must only be called if the\n             * caller is the last reader. */\n            if (slot->var.occupied.registered_readers != 1) {\n                MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->var.occupied.registered_readers == 1);\n                status = PSA_ERROR_CORRUPTION_DETECTED;\n            }\n            break;\n        case PSA_SLOT_FILLING:\n            /* In this state registered_readers must be 0. */\n            if (slot->var.occupied.registered_readers != 0) {\n                MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->var.occupied.registered_readers == 0);\n                status = PSA_ERROR_CORRUPTION_DETECTED;\n            }\n            break;\n        case PSA_SLOT_EMPTY:\n            /* The slot is already empty, it cannot be wiped. */\n            MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->state != PSA_SLOT_EMPTY);\n            status = PSA_ERROR_CORRUPTION_DETECTED;\n            break;\n        default:\n            /* The slot's state is invalid. */\n            status = PSA_ERROR_CORRUPTION_DETECTED;\n    }\n\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n    size_t slice_index = slot->slice_index;\n#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n\n\n    /* Multipart operations may still be using the key. This is safe\n     * because all multipart operation objects are independent from\n     * the key slot: if they need to access the key after the setup\n     * phase, they have a copy of the key. Note that this means that\n     * key material can linger until all operations are completed. */\n    /* At this point, key material and other type-specific content has\n     * been wiped. Clear remaining metadata. We can call memset and not\n     * zeroize because the metadata is not particularly sensitive.\n     * This memset also sets the slot's state to PSA_SLOT_EMPTY. */\n    memset(slot, 0, sizeof(*slot));\n\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n    /* If the slot is already corrupted, something went deeply wrong,\n     * like a thread still using the slot or a stray pointer leading\n     * to the slot's memory being used for another object. Let the slot\n     * leak rather than make the corruption worse. */\n    if (status == PSA_SUCCESS) {\n        status = psa_free_key_slot(slice_index, slot);\n    }\n#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n\n    return status;\n}\n\npsa_status_t psa_destroy_key(mbedtls_svc_key_id_t key)\n{\n    psa_key_slot_t *slot;\n    psa_status_t status; /* status of the last operation */\n    psa_status_t overall_status = PSA_SUCCESS;\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    psa_se_drv_table_entry_t *driver;\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n    if (mbedtls_svc_key_id_is_null(key)) {\n        return PSA_SUCCESS;\n    }\n\n    /*\n     * Get the description of the key in a key slot, and register to read it.\n     * In the case of a persistent key, this will load the key description\n     * from persistent memory if not done yet.\n     * We cannot avoid this loading as without it we don't know if\n     * the key is operated by an SE or not and this information is needed by\n     * the current implementation. */\n    status = psa_get_and_lock_key_slot(key, &slot);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    /* We cannot unlock between setting the state to PENDING_DELETION\n     * and destroying the key in storage, as otherwise another thread\n     * could load the key into a new slot and the key will not be\n     * fully destroyed. */\n    PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(\n                                    &mbedtls_threading_key_slot_mutex));\n\n    if (slot->state == PSA_SLOT_PENDING_DELETION) {\n        /* Another thread has destroyed the key between us locking the slot\n         * and us gaining the mutex. Unregister from the slot,\n         * and report that the key does not exist. */\n        status = psa_unregister_read(slot);\n\n        PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(\n                                  &mbedtls_threading_key_slot_mutex));\n        return (status == PSA_SUCCESS) ? PSA_ERROR_INVALID_HANDLE : status;\n    }\n#endif\n    /* Set the key slot containing the key description's state to\n     * PENDING_DELETION. This stops new operations from registering\n     * to read the slot. Current readers can safely continue to access\n     * the key within the slot; the last registered reader will\n     * automatically wipe the slot when they call psa_unregister_read().\n     * If the key is persistent, we can now delete the copy of the key\n     * from memory. If the key is opaque, we require the driver to\n     * deal with the deletion. */\n    overall_status = psa_key_slot_state_transition(slot, PSA_SLOT_FULL,\n                                                   PSA_SLOT_PENDING_DELETION);\n\n    if (overall_status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (PSA_KEY_LIFETIME_IS_READ_ONLY(slot->attr.lifetime)) {\n        /* Refuse the destruction of a read-only key (which may or may not work\n         * if we attempt it, depending on whether the key is merely read-only\n         * by policy or actually physically read-only).\n         * Just do the best we can, which is to wipe the copy in memory\n         * (done in this function's cleanup code). */\n        overall_status = PSA_ERROR_NOT_PERMITTED;\n        goto exit;\n    }\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    driver = psa_get_se_driver_entry(slot->attr.lifetime);\n    if (driver != NULL) {\n        /* For a key in a secure element, we need to do three things:\n         * remove the key file in internal storage, destroy the\n         * key inside the secure element, and update the driver's\n         * persistent data. Start a transaction that will encompass these\n         * three actions. */\n        psa_crypto_prepare_transaction(PSA_CRYPTO_TRANSACTION_DESTROY_KEY);\n        psa_crypto_transaction.key.lifetime = slot->attr.lifetime;\n        psa_crypto_transaction.key.slot = psa_key_slot_get_slot_number(slot);\n        psa_crypto_transaction.key.id = slot->attr.id;\n        status = psa_crypto_save_transaction();\n        if (status != PSA_SUCCESS) {\n            (void) psa_crypto_stop_transaction();\n            /* We should still try to destroy the key in the secure\n             * element and the key metadata in storage. This is especially\n             * important if the error is that the storage is full.\n             * But how to do it exactly without risking an inconsistent\n             * state after a reset?\n             * https://github.com/ARMmbed/mbed-crypto/issues/215\n             */\n            overall_status = status;\n            goto exit;\n        }\n\n        status = psa_destroy_se_key(driver,\n                                    psa_key_slot_get_slot_number(slot));\n        if (overall_status == PSA_SUCCESS) {\n            overall_status = status;\n        }\n    }\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)\n    if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {\n        /* Destroy the copy of the persistent key from storage.\n         * The slot will still hold a copy of the key until the last reader\n         * unregisters. */\n        status = psa_destroy_persistent_key(slot->attr.id);\n        if (overall_status == PSA_SUCCESS) {\n            overall_status = status;\n        }\n    }\n#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    if (driver != NULL) {\n        status = psa_save_se_persistent_data(driver);\n        if (overall_status == PSA_SUCCESS) {\n            overall_status = status;\n        }\n        status = psa_crypto_stop_transaction();\n        if (overall_status == PSA_SUCCESS) {\n            overall_status = status;\n        }\n    }\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\nexit:\n    /* Unregister from reading the slot. If we are the last active reader\n     * then this will wipe the slot. */\n    status = psa_unregister_read(slot);\n    /* Prioritize CORRUPTION_DETECTED from unregistering over\n     * a storage error. */\n    if (status != PSA_SUCCESS) {\n        overall_status = status;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    /* Don't overwrite existing errors if the unlock fails. */\n    status = overall_status;\n    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(\n                              &mbedtls_threading_key_slot_mutex));\n#endif\n\n    return overall_status;\n}\n\n/** Retrieve all the publicly-accessible attributes of a key.\n */\npsa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key,\n                                    psa_key_attributes_t *attributes)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n\n    psa_reset_key_attributes(attributes);\n\n    status = psa_get_and_lock_key_slot_with_policy(key, &slot, 0, 0);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    *attributes = slot->attr;\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    if (psa_get_se_driver_entry(slot->attr.lifetime) != NULL) {\n        psa_set_key_slot_number(attributes,\n                                psa_key_slot_get_slot_number(slot));\n    }\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n    return psa_unregister_read_under_mutex(slot);\n}\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\npsa_status_t psa_get_key_slot_number(\n    const psa_key_attributes_t *attributes,\n    psa_key_slot_number_t *slot_number)\n{\n    if (attributes->has_slot_number) {\n        *slot_number = attributes->slot_number;\n        return PSA_SUCCESS;\n    } else {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n}\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\nstatic psa_status_t psa_export_key_buffer_internal(const uint8_t *key_buffer,\n                                                   size_t key_buffer_size,\n                                                   uint8_t *data,\n                                                   size_t data_size,\n                                                   size_t *data_length)\n{\n    if (key_buffer_size > data_size) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n    memcpy(data, key_buffer, key_buffer_size);\n    memset(data + key_buffer_size, 0,\n           data_size - key_buffer_size);\n    *data_length = key_buffer_size;\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_export_key_internal(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    uint8_t *data, size_t data_size, size_t *data_length)\n{\n    psa_key_type_t type = attributes->type;\n\n    if (key_type_is_raw_bytes(type) ||\n        PSA_KEY_TYPE_IS_RSA(type)   ||\n        PSA_KEY_TYPE_IS_ECC(type)   ||\n        PSA_KEY_TYPE_IS_DH(type)) {\n        return psa_export_key_buffer_internal(\n            key_buffer, key_buffer_size,\n            data, data_size, data_length);\n    } else {\n        /* This shouldn't happen in the built-in implementation, but\n           it is valid for a special-purpose drivers to omit\n           support for exporting certain key types. */\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n}\n\npsa_status_t psa_export_key(mbedtls_svc_key_id_t key,\n                            uint8_t *data_external,\n                            size_t data_size,\n                            size_t *data_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n    LOCAL_OUTPUT_DECLARE(data_external, data);\n\n    /* Reject a zero-length output buffer now, since this can never be a\n     * valid key representation. This way we know that data must be a valid\n     * pointer and we can do things like memset(data, ..., data_size). */\n    if (data_size == 0) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n\n    /* Set the key to empty now, so that even when there are errors, we always\n     * set data_length to a value between 0 and data_size. On error, setting\n     * the key to empty is a good choice because an empty key representation is\n     * unlikely to be accepted anywhere. */\n    *data_length = 0;\n\n    /* Export requires the EXPORT flag. There is an exception for public keys,\n     * which don't require any flag, but\n     * psa_get_and_lock_key_slot_with_policy() takes care of this.\n     */\n    status = psa_get_and_lock_key_slot_with_policy(key, &slot,\n                                                   PSA_KEY_USAGE_EXPORT, 0);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    LOCAL_OUTPUT_ALLOC(data_external, data_size, data);\n\n    status = psa_driver_wrapper_export_key(&slot->attr,\n                                           slot->key.data, slot->key.bytes,\n                                           data, data_size, data_length);\n\n#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\nexit:\n#endif\n    unlock_status = psa_unregister_read_under_mutex(slot);\n\n    LOCAL_OUTPUT_FREE(data_external, data);\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n}\n\npsa_status_t psa_export_public_key_internal(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    uint8_t *data,\n    size_t data_size,\n    size_t *data_length)\n{\n    psa_key_type_t type = attributes->type;\n\n    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) &&\n        (PSA_KEY_TYPE_IS_RSA(type) || PSA_KEY_TYPE_IS_ECC(type) ||\n         PSA_KEY_TYPE_IS_DH(type))) {\n        /* Exporting public -> public */\n        return psa_export_key_buffer_internal(\n            key_buffer, key_buffer_size,\n            data, data_size, data_length);\n    } else if (PSA_KEY_TYPE_IS_RSA(type)) {\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \\\n        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)\n        return mbedtls_psa_rsa_export_public_key(attributes,\n                                                 key_buffer,\n                                                 key_buffer_size,\n                                                 data,\n                                                 data_size,\n                                                 data_length);\n#else\n        /* We don't know how to convert a private RSA key to public. */\n        return PSA_ERROR_NOT_SUPPORTED;\n#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */\n    } else if (PSA_KEY_TYPE_IS_ECC(type)) {\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \\\n        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)\n        return mbedtls_psa_ecp_export_public_key(attributes,\n                                                 key_buffer,\n                                                 key_buffer_size,\n                                                 data,\n                                                 data_size,\n                                                 data_length);\n#else\n        /* We don't know how to convert a private ECC key to public */\n        return PSA_ERROR_NOT_SUPPORTED;\n#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */\n    } else if (PSA_KEY_TYPE_IS_DH(type)) {\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \\\n        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY)\n        return mbedtls_psa_ffdh_export_public_key(attributes,\n                                                  key_buffer,\n                                                  key_buffer_size,\n                                                  data, data_size,\n                                                  data_length);\n#else\n        return PSA_ERROR_NOT_SUPPORTED;\n#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */\n    } else {\n        (void) key_buffer;\n        (void) key_buffer_size;\n        (void) data;\n        (void) data_size;\n        (void) data_length;\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n}\n\npsa_status_t psa_export_public_key(mbedtls_svc_key_id_t key,\n                                   uint8_t *data_external,\n                                   size_t data_size,\n                                   size_t *data_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n\n    LOCAL_OUTPUT_DECLARE(data_external, data);\n\n    /* Reject a zero-length output buffer now, since this can never be a\n     * valid key representation. This way we know that data must be a valid\n     * pointer and we can do things like memset(data, ..., data_size). */\n    if (data_size == 0) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n\n    /* Set the key to empty now, so that even when there are errors, we always\n     * set data_length to a value between 0 and data_size. On error, setting\n     * the key to empty is a good choice because an empty key representation is\n     * unlikely to be accepted anywhere. */\n    *data_length = 0;\n\n    /* Exporting a public key doesn't require a usage flag. */\n    status = psa_get_and_lock_key_slot_with_policy(key, &slot, 0, 0);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    LOCAL_OUTPUT_ALLOC(data_external, data_size, data);\n\n    if (!PSA_KEY_TYPE_IS_ASYMMETRIC(slot->attr.type)) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    status = psa_driver_wrapper_export_public_key(\n        &slot->attr, slot->key.data, slot->key.bytes,\n        data, data_size, data_length);\n\nexit:\n    unlock_status = psa_unregister_read_under_mutex(slot);\n\n    LOCAL_OUTPUT_FREE(data_external, data);\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n}\n\n/** Validate that a key policy is internally well-formed.\n *\n * This function only rejects invalid policies. It does not validate the\n * consistency of the policy with respect to other attributes of the key\n * such as the key type.\n */\nstatic psa_status_t psa_validate_key_policy(const psa_key_policy_t *policy)\n{\n    if ((policy->usage & ~(PSA_KEY_USAGE_EXPORT |\n                           PSA_KEY_USAGE_COPY |\n                           PSA_KEY_USAGE_ENCRYPT |\n                           PSA_KEY_USAGE_DECRYPT |\n                           PSA_KEY_USAGE_SIGN_MESSAGE |\n                           PSA_KEY_USAGE_VERIFY_MESSAGE |\n                           PSA_KEY_USAGE_SIGN_HASH |\n                           PSA_KEY_USAGE_VERIFY_HASH |\n                           PSA_KEY_USAGE_VERIFY_DERIVATION |\n                           PSA_KEY_USAGE_DERIVE)) != 0) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    return PSA_SUCCESS;\n}\n\n/** Validate the internal consistency of key attributes.\n *\n * This function only rejects invalid attribute values. If does not\n * validate the consistency of the attributes with any key data that may\n * be involved in the creation of the key.\n *\n * Call this function early in the key creation process.\n *\n * \\param[in] attributes    Key attributes for the new key.\n * \\param[out] p_drv        On any return, the driver for the key, if any.\n *                          NULL for a transparent key.\n *\n */\nstatic psa_status_t psa_validate_key_attributes(\n    const psa_key_attributes_t *attributes,\n    psa_se_drv_table_entry_t **p_drv)\n{\n    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;\n    psa_key_lifetime_t lifetime = psa_get_key_lifetime(attributes);\n    mbedtls_svc_key_id_t key = psa_get_key_id(attributes);\n\n    status = psa_validate_key_location(lifetime, p_drv);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    status = psa_validate_key_persistence(lifetime);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) {\n        if (MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key) != 0) {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n    } else {\n        if (!psa_is_valid_key_id(psa_get_key_id(attributes), 0)) {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n    }\n\n    status = psa_validate_key_policy(&attributes->policy);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    /* Refuse to create overly large keys.\n     * Note that this doesn't trigger on import if the attributes don't\n     * explicitly specify a size (so psa_get_key_bits returns 0), so\n     * psa_import_key() needs its own checks. */\n    if (psa_get_key_bits(attributes) > PSA_MAX_KEY_BITS) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    return PSA_SUCCESS;\n}\n\n/** Prepare a key slot to receive key material.\n *\n * This function allocates a key slot and sets its metadata.\n *\n * If this function fails, call psa_fail_key_creation().\n *\n * This function is intended to be used as follows:\n * -# Call psa_start_key_creation() to allocate a key slot, prepare\n *    it with the specified attributes, and in case of a volatile key assign it\n *    a volatile key identifier.\n * -# Populate the slot with the key material.\n * -# Call psa_finish_key_creation() to finalize the creation of the slot.\n * In case of failure at any step, stop the sequence and call\n * psa_fail_key_creation().\n *\n * On success, the key slot's state is PSA_SLOT_FILLING.\n * It is the responsibility of the caller to change the slot's state to\n * PSA_SLOT_EMPTY/FULL once key creation has finished.\n *\n * \\param method            An identification of the calling function.\n * \\param[in] attributes    Key attributes for the new key.\n * \\param[out] p_slot       On success, a pointer to the prepared slot.\n * \\param[out] p_drv        On any return, the driver for the key, if any.\n *                          NULL for a transparent key.\n *\n * \\retval #PSA_SUCCESS\n *         The key slot is ready to receive key material.\n * \\return If this function fails, the key slot is an invalid state.\n *         You must call psa_fail_key_creation() to wipe and free the slot.\n */\nstatic psa_status_t psa_start_key_creation(\n    psa_key_creation_method_t method,\n    const psa_key_attributes_t *attributes,\n    psa_key_slot_t **p_slot,\n    psa_se_drv_table_entry_t **p_drv)\n{\n    psa_status_t status;\n\n    (void) method;\n    *p_drv = NULL;\n\n    status = psa_validate_key_attributes(attributes, p_drv);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    int key_is_volatile = PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime);\n    psa_key_id_t volatile_key_id;\n\n#if defined(MBEDTLS_THREADING_C)\n    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(\n                              &mbedtls_threading_key_slot_mutex));\n#endif\n    status = psa_reserve_free_key_slot(\n        key_is_volatile ? &volatile_key_id : NULL,\n        p_slot);\n#if defined(MBEDTLS_THREADING_C)\n    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(\n                              &mbedtls_threading_key_slot_mutex));\n#endif\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n    psa_key_slot_t *slot = *p_slot;\n\n    /* We're storing the declared bit-size of the key. It's up to each\n     * creation mechanism to verify that this information is correct.\n     * It's automatically correct for mechanisms that use the bit-size as\n     * an input (generate, device) but not for those where the bit-size\n     * is optional (import, copy). In case of a volatile key, assign it the\n     * volatile key identifier associated to the slot returned to contain its\n     * definition. */\n\n    slot->attr = *attributes;\n    if (key_is_volatile) {\n#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)\n        slot->attr.id = volatile_key_id;\n#else\n        slot->attr.id.key_id = volatile_key_id;\n#endif\n    }\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    /* For a key in a secure element, we need to do three things\n     * when creating or registering a persistent key:\n     * create the key file in internal storage, create the\n     * key inside the secure element, and update the driver's\n     * persistent data. This is done by starting a transaction that will\n     * encompass these three actions.\n     * For registering a volatile key, we just need to find an appropriate\n     * slot number inside the SE. Since the key is designated volatile, creating\n     * a transaction is not required. */\n    /* The first thing to do is to find a slot number for the new key.\n     * We save the slot number in persistent storage as part of the\n     * transaction data. It will be needed to recover if the power\n     * fails during the key creation process, to clean up on the secure\n     * element side after restarting. Obtaining a slot number from the\n     * secure element driver updates its persistent state, but we do not yet\n     * save the driver's persistent state, so that if the power fails,\n     * we can roll back to a state where the key doesn't exist. */\n    if (*p_drv != NULL) {\n        psa_key_slot_number_t slot_number;\n        status = psa_find_se_slot_for_key(attributes, method, *p_drv,\n                                          &slot_number);\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n\n        if (!PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime)) {\n            psa_crypto_prepare_transaction(PSA_CRYPTO_TRANSACTION_CREATE_KEY);\n            psa_crypto_transaction.key.lifetime = slot->attr.lifetime;\n            psa_crypto_transaction.key.slot = slot_number;\n            psa_crypto_transaction.key.id = slot->attr.id;\n            status = psa_crypto_save_transaction();\n            if (status != PSA_SUCCESS) {\n                (void) psa_crypto_stop_transaction();\n                return status;\n            }\n        }\n\n        status = psa_copy_key_material_into_slot(\n            slot, (uint8_t *) (&slot_number), sizeof(slot_number));\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n    }\n\n    if (*p_drv == NULL && method == PSA_KEY_CREATION_REGISTER) {\n        /* Key registration only makes sense with a secure element. */\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n    return PSA_SUCCESS;\n}\n\n/** Finalize the creation of a key once its key material has been set.\n *\n * This entails writing the key to persistent storage.\n *\n * If this function fails, call psa_fail_key_creation().\n * See the documentation of psa_start_key_creation() for the intended use\n * of this function.\n *\n * If the finalization succeeds, the function sets the key slot's state to\n * PSA_SLOT_FULL, and the key slot can no longer be accessed as part of the\n * key creation process.\n *\n * \\param[in,out] slot  Pointer to the slot with key material.\n * \\param[in] driver    The secure element driver for the key,\n *                      or NULL for a transparent key.\n * \\param[out] key      On success, identifier of the key. Note that the\n *                      key identifier is also stored in the key slot.\n *\n * \\retval #PSA_SUCCESS\n *         The key was successfully created.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n * \\retval #PSA_ERROR_ALREADY_EXISTS \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n *\n * \\return If this function fails, the key slot is an invalid state.\n *         You must call psa_fail_key_creation() to wipe and free the slot.\n */\nstatic psa_status_t psa_finish_key_creation(\n    psa_key_slot_t *slot,\n    psa_se_drv_table_entry_t *driver,\n    mbedtls_svc_key_id_t *key)\n{\n    psa_status_t status = PSA_SUCCESS;\n    (void) slot;\n    (void) driver;\n\n#if defined(MBEDTLS_THREADING_C)\n    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(\n                              &mbedtls_threading_key_slot_mutex));\n#endif\n\n#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)\n    if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n        if (driver != NULL) {\n            psa_se_key_data_storage_t data;\n            psa_key_slot_number_t slot_number =\n                psa_key_slot_get_slot_number(slot);\n\n            MBEDTLS_STATIC_ASSERT(sizeof(slot_number) ==\n                                  sizeof(data.slot_number),\n                                  \"Slot number size does not match psa_se_key_data_storage_t\");\n\n            memcpy(&data.slot_number, &slot_number, sizeof(slot_number));\n            status = psa_save_persistent_key(&slot->attr,\n                                             (uint8_t *) &data,\n                                             sizeof(data));\n        } else\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n        {\n            /* Key material is saved in export representation in the slot, so\n             * just pass the slot buffer for storage. */\n            status = psa_save_persistent_key(&slot->attr,\n                                             slot->key.data,\n                                             slot->key.bytes);\n        }\n    }\n#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    /* Finish the transaction for a key creation. This does not\n     * happen when registering an existing key. Detect this case\n     * by checking whether a transaction is in progress (actual\n     * creation of a persistent key in a secure element requires a transaction,\n     * but registration or volatile key creation doesn't use one). */\n    if (driver != NULL &&\n        psa_crypto_transaction.unknown.type == PSA_CRYPTO_TRANSACTION_CREATE_KEY) {\n        status = psa_save_se_persistent_data(driver);\n        if (status != PSA_SUCCESS) {\n            psa_destroy_persistent_key(slot->attr.id);\n\n#if defined(MBEDTLS_THREADING_C)\n            PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(\n                                      &mbedtls_threading_key_slot_mutex));\n#endif\n            return status;\n        }\n        status = psa_crypto_stop_transaction();\n    }\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n    if (status == PSA_SUCCESS) {\n        *key = slot->attr.id;\n        status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING,\n                                               PSA_SLOT_FULL);\n        if (status != PSA_SUCCESS) {\n            *key = MBEDTLS_SVC_KEY_ID_INIT;\n        }\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(\n                              &mbedtls_threading_key_slot_mutex));\n#endif\n    return status;\n}\n\n/** Abort the creation of a key.\n *\n * You may call this function after calling psa_start_key_creation(),\n * or after psa_finish_key_creation() fails. In other circumstances, this\n * function may not clean up persistent storage.\n * See the documentation of psa_start_key_creation() for the intended use\n * of this function. Sets the slot's state to PSA_SLOT_EMPTY.\n *\n * \\param[in,out] slot  Pointer to the slot with key material.\n * \\param[in] driver    The secure element driver for the key,\n *                      or NULL for a transparent key.\n */\nstatic void psa_fail_key_creation(psa_key_slot_t *slot,\n                                  psa_se_drv_table_entry_t *driver)\n{\n    (void) driver;\n\n    if (slot == NULL) {\n        return;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    /* If the lock operation fails we still wipe the slot.\n     * Operations will no longer work after a failed lock,\n     * but we still need to wipe the slot of confidential data. */\n    mbedtls_mutex_lock(&mbedtls_threading_key_slot_mutex);\n#endif\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    /* TODO: If the key has already been created in the secure\n     * element, and the failure happened later (when saving metadata\n     * to internal storage), we need to destroy the key in the secure\n     * element.\n     * https://github.com/ARMmbed/mbed-crypto/issues/217\n     */\n\n    /* Abort the ongoing transaction if any (there may not be one if\n     * the creation process failed before starting one, or if the\n     * key creation is a registration of a key in a secure element).\n     * Earlier functions must already have done what it takes to undo any\n     * partial creation. All that's left is to update the transaction data\n     * itself. */\n    (void) psa_crypto_stop_transaction();\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n    psa_wipe_key_slot(slot);\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_unlock(&mbedtls_threading_key_slot_mutex);\n#endif\n}\n\n/** Validate optional attributes during key creation.\n *\n * Some key attributes are optional during key creation. If they are\n * specified in the attributes structure, check that they are consistent\n * with the data in the slot.\n *\n * This function should be called near the end of key creation, after\n * the slot in memory is fully populated but before saving persistent data.\n */\nstatic psa_status_t psa_validate_optional_attributes(\n    const psa_key_slot_t *slot,\n    const psa_key_attributes_t *attributes)\n{\n    if (attributes->type != 0) {\n        if (attributes->type != slot->attr.type) {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n    }\n\n    if (attributes->bits != 0) {\n        if (attributes->bits != slot->attr.bits) {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n    }\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_import_key(const psa_key_attributes_t *attributes,\n                            const uint8_t *data_external,\n                            size_t data_length,\n                            mbedtls_svc_key_id_t *key)\n{\n    psa_status_t status;\n    LOCAL_INPUT_DECLARE(data_external, data);\n    psa_key_slot_t *slot = NULL;\n    psa_se_drv_table_entry_t *driver = NULL;\n    size_t bits;\n    size_t storage_size = data_length;\n\n    *key = MBEDTLS_SVC_KEY_ID_INIT;\n\n    /* Reject zero-length symmetric keys (including raw data key objects).\n     * This also rejects any key which might be encoded as an empty string,\n     * which is never valid. */\n    if (data_length == 0) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    /* Ensure that the bytes-to-bits conversion cannot overflow. */\n    if (data_length > SIZE_MAX / 8) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    LOCAL_INPUT_ALLOC(data_external, data_length, data);\n\n    status = psa_start_key_creation(PSA_KEY_CREATION_IMPORT, attributes,\n                                    &slot, &driver);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    /* In the case of a transparent key or an opaque key stored in local\n     * storage ( thus not in the case of importing a key in a secure element\n     * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a\n     * buffer to hold the imported key material. */\n    if (slot->key.bytes == 0) {\n        if (psa_key_lifetime_is_external(attributes->lifetime)) {\n            status = psa_driver_wrapper_get_key_buffer_size_from_key_data(\n                attributes, data, data_length, &storage_size);\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n        }\n        status = psa_allocate_buffer_to_slot(slot, storage_size);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n    }\n\n    bits = slot->attr.bits;\n    status = psa_driver_wrapper_import_key(attributes,\n                                           data, data_length,\n                                           slot->key.data,\n                                           slot->key.bytes,\n                                           &slot->key.bytes, &bits);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (slot->attr.bits == 0) {\n        slot->attr.bits = (psa_key_bits_t) bits;\n    } else if (bits != slot->attr.bits) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    /* Enforce a size limit, and in particular ensure that the bit\n     * size fits in its representation type.*/\n    if (bits > PSA_MAX_KEY_BITS) {\n        status = PSA_ERROR_NOT_SUPPORTED;\n        goto exit;\n    }\n    status = psa_validate_optional_attributes(slot, attributes);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_finish_key_creation(slot, driver, key);\nexit:\n    LOCAL_INPUT_FREE(data_external, data);\n    if (status != PSA_SUCCESS) {\n        psa_fail_key_creation(slot, driver);\n    }\n\n    return status;\n}\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\npsa_status_t mbedtls_psa_register_se_key(\n    const psa_key_attributes_t *attributes)\n{\n    psa_status_t status;\n    psa_key_slot_t *slot = NULL;\n    psa_se_drv_table_entry_t *driver = NULL;\n    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;\n\n    /* Leaving attributes unspecified is not currently supported.\n     * It could make sense to query the key type and size from the\n     * secure element, but not all secure elements support this\n     * and the driver HAL doesn't currently support it. */\n    if (psa_get_key_type(attributes) == PSA_KEY_TYPE_NONE) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n    if (psa_get_key_bits(attributes) == 0) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    /* Not usable with volatile keys, even with an appropriate location,\n     * due to the API design.\n     * https://github.com/Mbed-TLS/mbedtls/issues/9253\n     */\n    if (PSA_KEY_LIFETIME_IS_VOLATILE(psa_get_key_lifetime(attributes))) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    status = psa_start_key_creation(PSA_KEY_CREATION_REGISTER, attributes,\n                                    &slot, &driver);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_finish_key_creation(slot, driver, &key);\n\nexit:\n    if (status != PSA_SUCCESS) {\n        psa_fail_key_creation(slot, driver);\n    }\n\n    /* Registration doesn't keep the key in RAM. */\n    psa_close_key(key);\n    return status;\n}\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\npsa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key,\n                          const psa_key_attributes_t *specified_attributes,\n                          mbedtls_svc_key_id_t *target_key)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *source_slot = NULL;\n    psa_key_slot_t *target_slot = NULL;\n    psa_key_attributes_t actual_attributes = *specified_attributes;\n    psa_se_drv_table_entry_t *driver = NULL;\n    size_t storage_size = 0;\n\n    *target_key = MBEDTLS_SVC_KEY_ID_INIT;\n\n    status = psa_get_and_lock_key_slot_with_policy(\n        source_key, &source_slot, PSA_KEY_USAGE_COPY, 0);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_validate_optional_attributes(source_slot,\n                                              specified_attributes);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    /* The target key type and number of bits have been validated by\n     * psa_validate_optional_attributes() to be either equal to zero or\n     * equal to the ones of the source key. So it is safe to inherit\n     * them from the source key now.\"\n     * */\n    actual_attributes.bits = source_slot->attr.bits;\n    actual_attributes.type = source_slot->attr.type;\n\n\n    status = psa_restrict_key_policy(source_slot->attr.type,\n                                     &actual_attributes.policy,\n                                     &source_slot->attr.policy);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_start_key_creation(PSA_KEY_CREATION_COPY, &actual_attributes,\n                                    &target_slot, &driver);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n    if (PSA_KEY_LIFETIME_GET_LOCATION(target_slot->attr.lifetime) !=\n        PSA_KEY_LIFETIME_GET_LOCATION(source_slot->attr.lifetime)) {\n        /*\n         * If the source and target keys are stored in different locations,\n         * the source key would need to be exported as plaintext and re-imported\n         * in the other location. This has security implications which have not\n         * been fully mapped. For now, this can be achieved through\n         * appropriate API invocations from the application, if needed.\n         * */\n        status = PSA_ERROR_NOT_SUPPORTED;\n        goto exit;\n    }\n    /*\n     * When the source and target keys are within the same location,\n     * - For transparent keys it is a blind copy without any driver invocation,\n     * - For opaque keys this translates to an invocation of the drivers'\n     *   copy_key entry point through the dispatch layer.\n     * */\n    if (psa_key_lifetime_is_external(actual_attributes.lifetime)) {\n        status = psa_driver_wrapper_get_key_buffer_size(&actual_attributes,\n                                                        &storage_size);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n\n        status = psa_allocate_buffer_to_slot(target_slot, storage_size);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n\n        status = psa_driver_wrapper_copy_key(&actual_attributes,\n                                             source_slot->key.data,\n                                             source_slot->key.bytes,\n                                             target_slot->key.data,\n                                             target_slot->key.bytes,\n                                             &target_slot->key.bytes);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n    } else {\n        status = psa_copy_key_material_into_slot(target_slot,\n                                                 source_slot->key.data,\n                                                 source_slot->key.bytes);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n    }\n    status = psa_finish_key_creation(target_slot, driver, target_key);\nexit:\n    if (status != PSA_SUCCESS) {\n        psa_fail_key_creation(target_slot, driver);\n    }\n\n    unlock_status = psa_unregister_read_under_mutex(source_slot);\n\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n}\n\n\n\n/****************************************************************/\n/* Message digests */\n/****************************************************************/\n\nstatic int is_hash_supported(psa_algorithm_t alg)\n{\n    switch (alg) {\n#if defined(PSA_WANT_ALG_MD5)\n        case PSA_ALG_MD5:\n            return 1;\n#endif\n#if defined(PSA_WANT_ALG_RIPEMD160)\n        case PSA_ALG_RIPEMD160:\n            return 1;\n#endif\n#if defined(PSA_WANT_ALG_SHA_1)\n        case PSA_ALG_SHA_1:\n            return 1;\n#endif\n#if defined(PSA_WANT_ALG_SHA_224)\n        case PSA_ALG_SHA_224:\n            return 1;\n#endif\n#if defined(PSA_WANT_ALG_SHA_256)\n        case PSA_ALG_SHA_256:\n            return 1;\n#endif\n#if defined(PSA_WANT_ALG_SHA_384)\n        case PSA_ALG_SHA_384:\n            return 1;\n#endif\n#if defined(PSA_WANT_ALG_SHA_512)\n        case PSA_ALG_SHA_512:\n            return 1;\n#endif\n#if defined(PSA_WANT_ALG_SHA3_224)\n        case PSA_ALG_SHA3_224:\n            return 1;\n#endif\n#if defined(PSA_WANT_ALG_SHA3_256)\n        case PSA_ALG_SHA3_256:\n            return 1;\n#endif\n#if defined(PSA_WANT_ALG_SHA3_384)\n        case PSA_ALG_SHA3_384:\n            return 1;\n#endif\n#if defined(PSA_WANT_ALG_SHA3_512)\n        case PSA_ALG_SHA3_512:\n            return 1;\n#endif\n        default:\n            return 0;\n    }\n}\n\npsa_status_t psa_hash_abort(psa_hash_operation_t *operation)\n{\n    /* Aborting a non-active operation is allowed */\n    if (operation->id == 0) {\n        return PSA_SUCCESS;\n    }\n\n    psa_status_t status = psa_driver_wrapper_hash_abort(operation);\n    operation->id = 0;\n\n    return status;\n}\n\npsa_status_t psa_hash_setup(psa_hash_operation_t *operation,\n                            psa_algorithm_t alg)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    /* A context must be freshly initialized before it can be set up. */\n    if (operation->id != 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (!PSA_ALG_IS_HASH(alg)) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    /* Make sure the driver-dependent part of the operation is zeroed.\n     * This is a guarantee we make to drivers. Initializing the operation\n     * does not necessarily take care of it, since the context is a\n     * union and initializing a union does not necessarily initialize\n     * all of its members. */\n    memset(&operation->ctx, 0, sizeof(operation->ctx));\n\n    status = psa_driver_wrapper_hash_setup(operation, alg);\n\nexit:\n    if (status != PSA_SUCCESS) {\n        psa_hash_abort(operation);\n    }\n\n    return status;\n}\n\npsa_status_t psa_hash_update(psa_hash_operation_t *operation,\n                             const uint8_t *input_external,\n                             size_t input_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    LOCAL_INPUT_DECLARE(input_external, input);\n\n    if (operation->id == 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    /* Don't require hash implementations to behave correctly on a\n     * zero-length input, which may have an invalid pointer. */\n    if (input_length == 0) {\n        return PSA_SUCCESS;\n    }\n\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n    status = psa_driver_wrapper_hash_update(operation, input, input_length);\n\nexit:\n    if (status != PSA_SUCCESS) {\n        psa_hash_abort(operation);\n    }\n\n    LOCAL_INPUT_FREE(input_external, input);\n    return status;\n}\n\nstatic psa_status_t psa_hash_finish_internal(psa_hash_operation_t *operation,\n                                             uint8_t *hash,\n                                             size_t hash_size,\n                                             size_t *hash_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    *hash_length = 0;\n    if (operation->id == 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    status = psa_driver_wrapper_hash_finish(\n        operation, hash, hash_size, hash_length);\n    psa_hash_abort(operation);\n\n    return status;\n}\n\npsa_status_t psa_hash_finish(psa_hash_operation_t *operation,\n                             uint8_t *hash_external,\n                             size_t hash_size,\n                             size_t *hash_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    LOCAL_OUTPUT_DECLARE(hash_external, hash);\n\n    LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash);\n    status = psa_hash_finish_internal(operation, hash, hash_size, hash_length);\n\n#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\nexit:\n#endif\n    LOCAL_OUTPUT_FREE(hash_external, hash);\n    return status;\n}\n\npsa_status_t psa_hash_verify(psa_hash_operation_t *operation,\n                             const uint8_t *hash_external,\n                             size_t hash_length)\n{\n    uint8_t actual_hash[PSA_HASH_MAX_SIZE];\n    size_t actual_hash_length;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    LOCAL_INPUT_DECLARE(hash_external, hash);\n\n    status = psa_hash_finish_internal(\n        operation,\n        actual_hash, sizeof(actual_hash),\n        &actual_hash_length);\n\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (actual_hash_length != hash_length) {\n        status = PSA_ERROR_INVALID_SIGNATURE;\n        goto exit;\n    }\n\n    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);\n    if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) {\n        status = PSA_ERROR_INVALID_SIGNATURE;\n    }\n\nexit:\n    mbedtls_platform_zeroize(actual_hash, sizeof(actual_hash));\n    if (status != PSA_SUCCESS) {\n        psa_hash_abort(operation);\n    }\n    LOCAL_INPUT_FREE(hash_external, hash);\n    return status;\n}\n\npsa_status_t psa_hash_compute(psa_algorithm_t alg,\n                              const uint8_t *input_external, size_t input_length,\n                              uint8_t *hash_external, size_t hash_size,\n                              size_t *hash_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    LOCAL_INPUT_DECLARE(input_external, input);\n    LOCAL_OUTPUT_DECLARE(hash_external, hash);\n\n    *hash_length = 0;\n    if (!PSA_ALG_IS_HASH(alg)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n    LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash);\n    status = psa_driver_wrapper_hash_compute(alg, input, input_length,\n                                             hash, hash_size, hash_length);\n\n#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\nexit:\n#endif\n    LOCAL_INPUT_FREE(input_external, input);\n    LOCAL_OUTPUT_FREE(hash_external, hash);\n    return status;\n}\n\npsa_status_t psa_hash_compare(psa_algorithm_t alg,\n                              const uint8_t *input_external, size_t input_length,\n                              const uint8_t *hash_external, size_t hash_length)\n{\n    uint8_t actual_hash[PSA_HASH_MAX_SIZE];\n    size_t actual_hash_length;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    LOCAL_INPUT_DECLARE(input_external, input);\n    LOCAL_INPUT_DECLARE(hash_external, hash);\n\n    if (!PSA_ALG_IS_HASH(alg)) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        return status;\n    }\n\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n    status = psa_driver_wrapper_hash_compute(\n        alg, input, input_length,\n        actual_hash, sizeof(actual_hash),\n        &actual_hash_length);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n    if (actual_hash_length != hash_length) {\n        status = PSA_ERROR_INVALID_SIGNATURE;\n        goto exit;\n    }\n\n    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);\n    if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) {\n        status = PSA_ERROR_INVALID_SIGNATURE;\n    }\n\nexit:\n    mbedtls_platform_zeroize(actual_hash, sizeof(actual_hash));\n\n    LOCAL_INPUT_FREE(input_external, input);\n    LOCAL_INPUT_FREE(hash_external, hash);\n\n    return status;\n}\n\npsa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation,\n                            psa_hash_operation_t *target_operation)\n{\n    if (source_operation->id == 0 ||\n        target_operation->id != 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    /* Make sure the driver-dependent part of the operation is zeroed.\n     * This is a guarantee we make to drivers. Initializing the operation\n     * does not necessarily take care of it, since the context is a\n     * union and initializing a union does not necessarily initialize\n     * all of its members. */\n    memset(&target_operation->ctx, 0, sizeof(target_operation->ctx));\n\n    psa_status_t status = psa_driver_wrapper_hash_clone(source_operation,\n                                                        target_operation);\n    if (status != PSA_SUCCESS) {\n        psa_hash_abort(target_operation);\n    }\n\n    return status;\n}\n\n\n/****************************************************************/\n/* MAC */\n/****************************************************************/\n\npsa_status_t psa_mac_abort(psa_mac_operation_t *operation)\n{\n    /* Aborting a non-active operation is allowed */\n    if (operation->id == 0) {\n        return PSA_SUCCESS;\n    }\n\n    psa_status_t status = psa_driver_wrapper_mac_abort(operation);\n    operation->mac_size = 0;\n    operation->is_sign = 0;\n    operation->id = 0;\n\n    return status;\n}\n\nstatic psa_status_t psa_mac_finalize_alg_and_key_validation(\n    psa_algorithm_t alg,\n    const psa_key_attributes_t *attributes,\n    uint8_t *mac_size)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_type_t key_type = psa_get_key_type(attributes);\n    size_t key_bits = psa_get_key_bits(attributes);\n\n    if (!PSA_ALG_IS_MAC(alg)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    /* Validate the combination of key type and algorithm */\n    status = psa_mac_key_can_do(alg, key_type);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    /* Get the output length for the algorithm and key combination */\n    *mac_size = PSA_MAC_LENGTH(key_type, key_bits, alg);\n\n    if (*mac_size < 4) {\n        /* A very short MAC is too short for security since it can be\n         * brute-forced. Ancient protocols with 32-bit MACs do exist,\n         * so we make this our minimum, even though 32 bits is still\n         * too small for security. */\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    if (*mac_size > PSA_MAC_LENGTH(key_type, key_bits,\n                                   PSA_ALG_FULL_LENGTH_MAC(alg))) {\n        /* It's impossible to \"truncate\" to a larger length than the full length\n         * of the algorithm. */\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    if (*mac_size > PSA_MAC_MAX_SIZE) {\n        /* PSA_MAC_LENGTH returns the correct length even for a MAC algorithm\n         * that is disabled in the compile-time configuration. The result can\n         * therefore be larger than PSA_MAC_MAX_SIZE, which does take the\n         * configuration into account. In this case, force a return of\n         * PSA_ERROR_NOT_SUPPORTED here. Otherwise psa_mac_verify(), or\n         * psa_mac_compute(mac_size=PSA_MAC_MAX_SIZE), would return\n         * PSA_ERROR_BUFFER_TOO_SMALL for an unsupported algorithm whose MAC size\n         * is larger than PSA_MAC_MAX_SIZE, which is misleading and which breaks\n         * systematically generated tests. */\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    return PSA_SUCCESS;\n}\n\nstatic psa_status_t psa_mac_setup(psa_mac_operation_t *operation,\n                                  mbedtls_svc_key_id_t key,\n                                  psa_algorithm_t alg,\n                                  int is_sign)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot = NULL;\n\n    /* A context must be freshly initialized before it can be set up. */\n    if (operation->id != 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    /* Make sure the driver-dependent part of the operation is zeroed.\n     * This is a guarantee we make to drivers. Initializing the operation\n     * does not necessarily take care of it, since the context is a\n     * union and initializing a union does not necessarily initialize\n     * all of its members. */\n    memset(&operation->ctx, 0, sizeof(operation->ctx));\n\n    status = psa_get_and_lock_key_slot_with_policy(\n        key,\n        &slot,\n        is_sign ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_VERIFY_MESSAGE,\n        alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr,\n                                                     &operation->mac_size);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    operation->is_sign = is_sign;\n    /* Dispatch the MAC setup call with validated input */\n    if (is_sign) {\n        status = psa_driver_wrapper_mac_sign_setup(operation,\n                                                   &slot->attr,\n                                                   slot->key.data,\n                                                   slot->key.bytes,\n                                                   alg);\n    } else {\n        status = psa_driver_wrapper_mac_verify_setup(operation,\n                                                     &slot->attr,\n                                                     slot->key.data,\n                                                     slot->key.bytes,\n                                                     alg);\n    }\n\nexit:\n    if (status != PSA_SUCCESS) {\n        psa_mac_abort(operation);\n    }\n\n    unlock_status = psa_unregister_read_under_mutex(slot);\n\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n}\n\npsa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation,\n                                mbedtls_svc_key_id_t key,\n                                psa_algorithm_t alg)\n{\n    return psa_mac_setup(operation, key, alg, 1);\n}\n\npsa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation,\n                                  mbedtls_svc_key_id_t key,\n                                  psa_algorithm_t alg)\n{\n    return psa_mac_setup(operation, key, alg, 0);\n}\n\npsa_status_t psa_mac_update(psa_mac_operation_t *operation,\n                            const uint8_t *input_external,\n                            size_t input_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    LOCAL_INPUT_DECLARE(input_external, input);\n\n    if (operation->id == 0) {\n        status = PSA_ERROR_BAD_STATE;\n        return status;\n    }\n\n    /* Don't require hash implementations to behave correctly on a\n     * zero-length input, which may have an invalid pointer. */\n    if (input_length == 0) {\n        status = PSA_SUCCESS;\n        return status;\n    }\n\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n    status = psa_driver_wrapper_mac_update(operation, input, input_length);\n\n    if (status != PSA_SUCCESS) {\n        psa_mac_abort(operation);\n    }\n\n#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\nexit:\n#endif\n    LOCAL_INPUT_FREE(input_external, input);\n\n    return status;\n}\n\npsa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation,\n                                 uint8_t *mac_external,\n                                 size_t mac_size,\n                                 size_t *mac_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;\n    LOCAL_OUTPUT_DECLARE(mac_external, mac);\n    LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac);\n\n    if (operation->id == 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (!operation->is_sign) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    /* Sanity check. This will guarantee that mac_size != 0 (and so mac != NULL)\n     * once all the error checks are done. */\n    if (operation->mac_size == 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (mac_size < operation->mac_size) {\n        status = PSA_ERROR_BUFFER_TOO_SMALL;\n        goto exit;\n    }\n\n\n    status = psa_driver_wrapper_mac_sign_finish(operation,\n                                                mac, operation->mac_size,\n                                                mac_length);\n\nexit:\n    /* In case of success, set the potential excess room in the output buffer\n     * to an invalid value, to avoid potentially leaking a longer MAC.\n     * In case of error, set the output length and content to a safe default,\n     * such that in case the caller misses an error check, the output would be\n     * an unachievable MAC.\n     */\n    if (status != PSA_SUCCESS) {\n        *mac_length = mac_size;\n        operation->mac_size = 0;\n    }\n\n    if (mac != NULL) {\n        psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length);\n    }\n\n    abort_status = psa_mac_abort(operation);\n    LOCAL_OUTPUT_FREE(mac_external, mac);\n\n    return status == PSA_SUCCESS ? abort_status : status;\n}\n\npsa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation,\n                                   const uint8_t *mac_external,\n                                   size_t mac_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;\n    LOCAL_INPUT_DECLARE(mac_external, mac);\n\n    if (operation->id == 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (operation->is_sign) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (operation->mac_size != mac_length) {\n        status = PSA_ERROR_INVALID_SIGNATURE;\n        goto exit;\n    }\n\n    LOCAL_INPUT_ALLOC(mac_external, mac_length, mac);\n    status = psa_driver_wrapper_mac_verify_finish(operation,\n                                                  mac, mac_length);\n\nexit:\n    abort_status = psa_mac_abort(operation);\n    LOCAL_INPUT_FREE(mac_external, mac);\n\n    return status == PSA_SUCCESS ? abort_status : status;\n}\n\nstatic psa_status_t psa_mac_compute_internal(mbedtls_svc_key_id_t key,\n                                             psa_algorithm_t alg,\n                                             const uint8_t *input,\n                                             size_t input_length,\n                                             uint8_t *mac,\n                                             size_t mac_size,\n                                             size_t *mac_length,\n                                             int is_sign)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n    uint8_t operation_mac_size = 0;\n\n    status = psa_get_and_lock_key_slot_with_policy(\n        key,\n        &slot,\n        is_sign ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_VERIFY_MESSAGE,\n        alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr,\n                                                     &operation_mac_size);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (mac_size < operation_mac_size) {\n        status = PSA_ERROR_BUFFER_TOO_SMALL;\n        goto exit;\n    }\n\n    status = psa_driver_wrapper_mac_compute(\n        &slot->attr,\n        slot->key.data, slot->key.bytes,\n        alg,\n        input, input_length,\n        mac, operation_mac_size, mac_length);\n\nexit:\n    /* In case of success, set the potential excess room in the output buffer\n     * to an invalid value, to avoid potentially leaking a longer MAC.\n     * In case of error, set the output length and content to a safe default,\n     * such that in case the caller misses an error check, the output would be\n     * an unachievable MAC.\n     */\n    if (status != PSA_SUCCESS) {\n        *mac_length = mac_size;\n        operation_mac_size = 0;\n    }\n\n    psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length);\n\n    unlock_status = psa_unregister_read_under_mutex(slot);\n\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n}\n\npsa_status_t psa_mac_compute(mbedtls_svc_key_id_t key,\n                             psa_algorithm_t alg,\n                             const uint8_t *input_external,\n                             size_t input_length,\n                             uint8_t *mac_external,\n                             size_t mac_size,\n                             size_t *mac_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    LOCAL_INPUT_DECLARE(input_external, input);\n    LOCAL_OUTPUT_DECLARE(mac_external, mac);\n\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n    LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac);\n    status = psa_mac_compute_internal(key, alg,\n                                      input, input_length,\n                                      mac, mac_size, mac_length, 1);\n\n#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\nexit:\n#endif\n    LOCAL_INPUT_FREE(input_external, input);\n    LOCAL_OUTPUT_FREE(mac_external, mac);\n\n    return status;\n}\n\npsa_status_t psa_mac_verify(mbedtls_svc_key_id_t key,\n                            psa_algorithm_t alg,\n                            const uint8_t *input_external,\n                            size_t input_length,\n                            const uint8_t *mac_external,\n                            size_t mac_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    uint8_t actual_mac[PSA_MAC_MAX_SIZE];\n    size_t actual_mac_length;\n    LOCAL_INPUT_DECLARE(input_external, input);\n    LOCAL_INPUT_DECLARE(mac_external, mac);\n\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n    status = psa_mac_compute_internal(key, alg,\n                                      input, input_length,\n                                      actual_mac, sizeof(actual_mac),\n                                      &actual_mac_length, 0);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (mac_length != actual_mac_length) {\n        status = PSA_ERROR_INVALID_SIGNATURE;\n        goto exit;\n    }\n\n    LOCAL_INPUT_ALLOC(mac_external, mac_length, mac);\n    if (mbedtls_ct_memcmp(mac, actual_mac, actual_mac_length) != 0) {\n        status = PSA_ERROR_INVALID_SIGNATURE;\n        goto exit;\n    }\n\nexit:\n    mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac));\n    LOCAL_INPUT_FREE(input_external, input);\n    LOCAL_INPUT_FREE(mac_external, mac);\n\n    return status;\n}\n\n/****************************************************************/\n/* Asymmetric cryptography */\n/****************************************************************/\n\nstatic psa_status_t psa_sign_verify_check_alg(int input_is_message,\n                                              psa_algorithm_t alg)\n{\n    if (input_is_message) {\n        if (!PSA_ALG_IS_SIGN_MESSAGE(alg)) {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n    }\n\n    psa_algorithm_t hash_alg = 0;\n    if (PSA_ALG_IS_SIGN_HASH(alg)) {\n        hash_alg = PSA_ALG_SIGN_GET_HASH(alg);\n    }\n\n    /* Now hash_alg==0 if alg by itself doesn't need a hash.\n     * This is good enough for sign-hash, but a guaranteed failure for\n     * sign-message which needs to hash first for all algorithms\n     * supported at the moment. */\n\n    if (hash_alg == 0 && input_is_message) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n    if (hash_alg == PSA_ALG_ANY_HASH) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n    /* Give up immediately if the hash is not supported. This has\n     * several advantages:\n     * - For mechanisms that don't use the hash at all (e.g.\n     *   ECDSA verification, randomized ECDSA signature), without\n     *   this check, the operation would succeed even though it has\n     *   been given an invalid argument. This would not be insecure\n     *   since the hash was not necessary, but it would be weird.\n     * - For mechanisms that do use the hash, we avoid an error\n     *   deep inside the execution. In principle this doesn't matter,\n     *   but there is a little more risk of a bug in error handling\n     *   deep inside than in this preliminary check.\n     * - When calling a driver, the driver might be capable of using\n     *   a hash that the core doesn't support. This could potentially\n     *   result in a buffer overflow if the hash is larger than the\n     *   maximum hash size assumed by the core.\n     * - Returning a consistent error makes it possible to test\n     *   not-supported hashes in a consistent way.\n     */\n    if (hash_alg != 0 && !is_hash_supported(hash_alg)) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    return PSA_SUCCESS;\n}\n\nstatic psa_status_t psa_sign_internal(mbedtls_svc_key_id_t key,\n                                      int input_is_message,\n                                      psa_algorithm_t alg,\n                                      const uint8_t *input,\n                                      size_t input_length,\n                                      uint8_t *signature,\n                                      size_t signature_size,\n                                      size_t *signature_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n\n    *signature_length = 0;\n\n    status = psa_sign_verify_check_alg(input_is_message, alg);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    /* Immediately reject a zero-length signature buffer. This guarantees\n     * that signature must be a valid pointer. (On the other hand, the input\n     * buffer can in principle be empty since it doesn't actually have\n     * to be a hash.) */\n    if (signature_size == 0) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n\n    status = psa_get_and_lock_key_slot_with_policy(\n        key, &slot,\n        input_is_message ? PSA_KEY_USAGE_SIGN_MESSAGE :\n        PSA_KEY_USAGE_SIGN_HASH,\n        alg);\n\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    if (input_is_message) {\n        status = psa_driver_wrapper_sign_message(\n            &slot->attr, slot->key.data, slot->key.bytes,\n            alg, input, input_length,\n            signature, signature_size, signature_length);\n    } else {\n\n        status = psa_driver_wrapper_sign_hash(\n            &slot->attr, slot->key.data, slot->key.bytes,\n            alg, input, input_length,\n            signature, signature_size, signature_length);\n    }\n\n\nexit:\n    psa_wipe_tag_output_buffer(signature, status, signature_size,\n                               *signature_length);\n\n    unlock_status = psa_unregister_read_under_mutex(slot);\n\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n}\n\nstatic psa_status_t psa_verify_internal(mbedtls_svc_key_id_t key,\n                                        int input_is_message,\n                                        psa_algorithm_t alg,\n                                        const uint8_t *input,\n                                        size_t input_length,\n                                        const uint8_t *signature,\n                                        size_t signature_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n\n    status = psa_sign_verify_check_alg(input_is_message, alg);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    status = psa_get_and_lock_key_slot_with_policy(\n        key, &slot,\n        input_is_message ? PSA_KEY_USAGE_VERIFY_MESSAGE :\n        PSA_KEY_USAGE_VERIFY_HASH,\n        alg);\n\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    if (input_is_message) {\n        status = psa_driver_wrapper_verify_message(\n            &slot->attr, slot->key.data, slot->key.bytes,\n            alg, input, input_length,\n            signature, signature_length);\n    } else {\n        status = psa_driver_wrapper_verify_hash(\n            &slot->attr, slot->key.data, slot->key.bytes,\n            alg, input, input_length,\n            signature, signature_length);\n    }\n\n    unlock_status = psa_unregister_read_under_mutex(slot);\n\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n\n}\n\npsa_status_t psa_sign_message_builtin(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *signature,\n    size_t signature_size,\n    size_t *signature_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    if (PSA_ALG_IS_SIGN_HASH(alg)) {\n        size_t hash_length;\n        uint8_t hash[PSA_HASH_MAX_SIZE];\n\n        status = psa_driver_wrapper_hash_compute(\n            PSA_ALG_SIGN_GET_HASH(alg),\n            input, input_length,\n            hash, sizeof(hash), &hash_length);\n\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n\n        return psa_driver_wrapper_sign_hash(\n            attributes, key_buffer, key_buffer_size,\n            alg, hash, hash_length,\n            signature, signature_size, signature_length);\n    }\n\n    return PSA_ERROR_NOT_SUPPORTED;\n}\n\npsa_status_t psa_sign_message(mbedtls_svc_key_id_t key,\n                              psa_algorithm_t alg,\n                              const uint8_t *input_external,\n                              size_t input_length,\n                              uint8_t *signature_external,\n                              size_t signature_size,\n                              size_t *signature_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    LOCAL_INPUT_DECLARE(input_external, input);\n    LOCAL_OUTPUT_DECLARE(signature_external, signature);\n\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n    LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature);\n    status = psa_sign_internal(key, 1, alg, input, input_length, signature,\n                               signature_size, signature_length);\n\n#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\nexit:\n#endif\n    LOCAL_INPUT_FREE(input_external, input);\n    LOCAL_OUTPUT_FREE(signature_external, signature);\n    return status;\n}\n\npsa_status_t psa_verify_message_builtin(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *input,\n    size_t input_length,\n    const uint8_t *signature,\n    size_t signature_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    if (PSA_ALG_IS_SIGN_HASH(alg)) {\n        size_t hash_length;\n        uint8_t hash[PSA_HASH_MAX_SIZE];\n\n        status = psa_driver_wrapper_hash_compute(\n            PSA_ALG_SIGN_GET_HASH(alg),\n            input, input_length,\n            hash, sizeof(hash), &hash_length);\n\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n\n        return psa_driver_wrapper_verify_hash(\n            attributes, key_buffer, key_buffer_size,\n            alg, hash, hash_length,\n            signature, signature_length);\n    }\n\n    return PSA_ERROR_NOT_SUPPORTED;\n}\n\npsa_status_t psa_verify_message(mbedtls_svc_key_id_t key,\n                                psa_algorithm_t alg,\n                                const uint8_t *input_external,\n                                size_t input_length,\n                                const uint8_t *signature_external,\n                                size_t signature_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    LOCAL_INPUT_DECLARE(input_external, input);\n    LOCAL_INPUT_DECLARE(signature_external, signature);\n\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n    LOCAL_INPUT_ALLOC(signature_external, signature_length, signature);\n    status = psa_verify_internal(key, 1, alg, input, input_length, signature,\n                                 signature_length);\n\n#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\nexit:\n#endif\n    LOCAL_INPUT_FREE(input_external, input);\n    LOCAL_INPUT_FREE(signature_external, signature);\n\n    return status;\n}\n\npsa_status_t psa_sign_hash_builtin(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,\n    uint8_t *signature, size_t signature_size, size_t *signature_length)\n{\n    if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) {\n        if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||\n            PSA_ALG_IS_RSA_PSS(alg)) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \\\n            defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)\n            return mbedtls_psa_rsa_sign_hash(\n                attributes,\n                key_buffer, key_buffer_size,\n                alg, hash, hash_length,\n                signature, signature_size, signature_length);\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */\n        } else {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n    } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) {\n        if (PSA_ALG_IS_ECDSA(alg)) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n            defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)\n            return mbedtls_psa_ecdsa_sign_hash(\n                attributes,\n                key_buffer, key_buffer_size,\n                alg, hash, hash_length,\n                signature, signature_size, signature_length);\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */\n        } else {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n    }\n\n    (void) key_buffer;\n    (void) key_buffer_size;\n    (void) hash;\n    (void) hash_length;\n    (void) signature;\n    (void) signature_size;\n    (void) signature_length;\n\n    return PSA_ERROR_NOT_SUPPORTED;\n}\n\npsa_status_t psa_sign_hash(mbedtls_svc_key_id_t key,\n                           psa_algorithm_t alg,\n                           const uint8_t *hash_external,\n                           size_t hash_length,\n                           uint8_t *signature_external,\n                           size_t signature_size,\n                           size_t *signature_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    LOCAL_INPUT_DECLARE(hash_external, hash);\n    LOCAL_OUTPUT_DECLARE(signature_external, signature);\n\n    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);\n    LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature);\n    status = psa_sign_internal(key, 0, alg, hash, hash_length, signature,\n                               signature_size, signature_length);\n\n#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\nexit:\n#endif\n    LOCAL_INPUT_FREE(hash_external, hash);\n    LOCAL_OUTPUT_FREE(signature_external, signature);\n\n    return status;\n}\n\npsa_status_t psa_verify_hash_builtin(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,\n    const uint8_t *signature, size_t signature_length)\n{\n    if (PSA_KEY_TYPE_IS_RSA(attributes->type)) {\n        if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||\n            PSA_ALG_IS_RSA_PSS(alg)) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \\\n            defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)\n            return mbedtls_psa_rsa_verify_hash(\n                attributes,\n                key_buffer, key_buffer_size,\n                alg, hash, hash_length,\n                signature, signature_length);\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */\n        } else {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n    } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) {\n        if (PSA_ALG_IS_ECDSA(alg)) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n            defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)\n            return mbedtls_psa_ecdsa_verify_hash(\n                attributes,\n                key_buffer, key_buffer_size,\n                alg, hash, hash_length,\n                signature, signature_length);\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */\n        } else {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n    }\n\n    (void) key_buffer;\n    (void) key_buffer_size;\n    (void) hash;\n    (void) hash_length;\n    (void) signature;\n    (void) signature_length;\n\n    return PSA_ERROR_NOT_SUPPORTED;\n}\n\npsa_status_t psa_verify_hash(mbedtls_svc_key_id_t key,\n                             psa_algorithm_t alg,\n                             const uint8_t *hash_external,\n                             size_t hash_length,\n                             const uint8_t *signature_external,\n                             size_t signature_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    LOCAL_INPUT_DECLARE(hash_external, hash);\n    LOCAL_INPUT_DECLARE(signature_external, signature);\n\n    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);\n    LOCAL_INPUT_ALLOC(signature_external, signature_length, signature);\n    status = psa_verify_internal(key, 0, alg, hash, hash_length, signature,\n                                 signature_length);\n\n#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\nexit:\n#endif\n    LOCAL_INPUT_FREE(hash_external, hash);\n    LOCAL_INPUT_FREE(signature_external, signature);\n\n    return status;\n}\n\npsa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key,\n                                    psa_algorithm_t alg,\n                                    const uint8_t *input_external,\n                                    size_t input_length,\n                                    const uint8_t *salt_external,\n                                    size_t salt_length,\n                                    uint8_t *output_external,\n                                    size_t output_size,\n                                    size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n\n    LOCAL_INPUT_DECLARE(input_external, input);\n    LOCAL_INPUT_DECLARE(salt_external, salt);\n    LOCAL_OUTPUT_DECLARE(output_external, output);\n\n    (void) input;\n    (void) input_length;\n    (void) salt;\n    (void) output;\n    (void) output_size;\n\n    *output_length = 0;\n\n    if (!PSA_ALG_IS_RSA_OAEP(alg) && salt_length != 0) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    status = psa_get_and_lock_key_slot_with_policy(\n        key, &slot, PSA_KEY_USAGE_ENCRYPT, alg);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n    if (!(PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type) ||\n          PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type))) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n    LOCAL_INPUT_ALLOC(salt_external, salt_length, salt);\n    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);\n\n    status = psa_driver_wrapper_asymmetric_encrypt(\n        &slot->attr, slot->key.data, slot->key.bytes,\n        alg, input, input_length, salt, salt_length,\n        output, output_size, output_length);\nexit:\n    unlock_status = psa_unregister_read_under_mutex(slot);\n\n    LOCAL_INPUT_FREE(input_external, input);\n    LOCAL_INPUT_FREE(salt_external, salt);\n    LOCAL_OUTPUT_FREE(output_external, output);\n\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n}\n\npsa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key,\n                                    psa_algorithm_t alg,\n                                    const uint8_t *input_external,\n                                    size_t input_length,\n                                    const uint8_t *salt_external,\n                                    size_t salt_length,\n                                    uint8_t *output_external,\n                                    size_t output_size,\n                                    size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n\n    LOCAL_INPUT_DECLARE(input_external, input);\n    LOCAL_INPUT_DECLARE(salt_external, salt);\n    LOCAL_OUTPUT_DECLARE(output_external, output);\n\n    (void) input;\n    (void) input_length;\n    (void) salt;\n    (void) output;\n    (void) output_size;\n\n    *output_length = 0;\n\n    if (!PSA_ALG_IS_RSA_OAEP(alg) && salt_length != 0) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    status = psa_get_and_lock_key_slot_with_policy(\n        key, &slot, PSA_KEY_USAGE_DECRYPT, alg);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n    if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n    LOCAL_INPUT_ALLOC(salt_external, salt_length, salt);\n    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);\n\n    status = psa_driver_wrapper_asymmetric_decrypt(\n        &slot->attr, slot->key.data, slot->key.bytes,\n        alg, input, input_length, salt, salt_length,\n        output, output_size, output_length);\n\nexit:\n    unlock_status = psa_unregister_read_under_mutex(slot);\n\n    LOCAL_INPUT_FREE(input_external, input);\n    LOCAL_INPUT_FREE(salt_external, salt);\n    LOCAL_OUTPUT_FREE(output_external, output);\n\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n}\n\n/****************************************************************/\n/* Asymmetric interruptible cryptography                        */\n/****************************************************************/\n\nstatic uint32_t psa_interruptible_max_ops = PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED;\n\nvoid psa_interruptible_set_max_ops(uint32_t max_ops)\n{\n    psa_interruptible_max_ops = max_ops;\n}\n\nuint32_t psa_interruptible_get_max_ops(void)\n{\n    return psa_interruptible_max_ops;\n}\n\nuint32_t psa_sign_hash_get_num_ops(\n    const psa_sign_hash_interruptible_operation_t *operation)\n{\n    return operation->num_ops;\n}\n\nuint32_t psa_verify_hash_get_num_ops(\n    const psa_verify_hash_interruptible_operation_t *operation)\n{\n    return operation->num_ops;\n}\n\nstatic psa_status_t psa_sign_hash_abort_internal(\n    psa_sign_hash_interruptible_operation_t *operation)\n{\n    if (operation->id == 0) {\n        /* The object has (apparently) been initialized but it is not (yet)\n         * in use. It's ok to call abort on such an object, and there's\n         * nothing to do. */\n        return PSA_SUCCESS;\n    }\n\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    status = psa_driver_wrapper_sign_hash_abort(operation);\n\n    operation->id = 0;\n\n    /* Do not clear either the error_occurred or num_ops elements here as they\n     * only want to be cleared by the application calling abort, not by abort\n     * being called at completion of an operation. */\n\n    return status;\n}\n\npsa_status_t psa_sign_hash_start(\n    psa_sign_hash_interruptible_operation_t *operation,\n    mbedtls_svc_key_id_t key, psa_algorithm_t alg,\n    const uint8_t *hash_external, size_t hash_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n\n    LOCAL_INPUT_DECLARE(hash_external, hash);\n\n    /* Check that start has not been previously called, or operation has not\n     * previously errored. */\n    if (operation->id != 0 || operation->error_occurred) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    /* Make sure the driver-dependent part of the operation is zeroed.\n     * This is a guarantee we make to drivers. Initializing the operation\n     * does not necessarily take care of it, since the context is a\n     * union and initializing a union does not necessarily initialize\n     * all of its members. */\n    memset(&operation->ctx, 0, sizeof(operation->ctx));\n\n    status = psa_sign_verify_check_alg(0, alg);\n    if (status != PSA_SUCCESS) {\n        operation->error_occurred = 1;\n        return status;\n    }\n\n    status = psa_get_and_lock_key_slot_with_policy(key, &slot,\n                                                   PSA_KEY_USAGE_SIGN_HASH,\n                                                   alg);\n\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);\n\n    /* Ensure ops count gets reset, in case of operation re-use. */\n    operation->num_ops = 0;\n\n    status = psa_driver_wrapper_sign_hash_start(operation, &slot->attr,\n                                                slot->key.data,\n                                                slot->key.bytes, alg,\n                                                hash, hash_length);\nexit:\n\n    if (status != PSA_SUCCESS) {\n        operation->error_occurred = 1;\n        psa_sign_hash_abort_internal(operation);\n    }\n\n    unlock_status = psa_unregister_read_under_mutex(slot);\n\n    if (unlock_status != PSA_SUCCESS) {\n        operation->error_occurred = 1;\n    }\n\n    LOCAL_INPUT_FREE(hash_external, hash);\n\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n}\n\n\npsa_status_t psa_sign_hash_complete(\n    psa_sign_hash_interruptible_operation_t *operation,\n    uint8_t *signature_external, size_t signature_size,\n    size_t *signature_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    LOCAL_OUTPUT_DECLARE(signature_external, signature);\n\n    *signature_length = 0;\n\n    /* Check that start has been called first, and that operation has not\n     * previously errored. */\n    if (operation->id == 0 || operation->error_occurred) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    /* Immediately reject a zero-length signature buffer. This guarantees that\n     * signature must be a valid pointer. */\n    if (signature_size == 0) {\n        status = PSA_ERROR_BUFFER_TOO_SMALL;\n        goto exit;\n    }\n\n    LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature);\n\n    status = psa_driver_wrapper_sign_hash_complete(operation, signature,\n                                                   signature_size,\n                                                   signature_length);\n\n    /* Update ops count with work done. */\n    operation->num_ops = psa_driver_wrapper_sign_hash_get_num_ops(operation);\n\nexit:\n\n    if (signature != NULL) {\n        psa_wipe_tag_output_buffer(signature, status, signature_size,\n                                   *signature_length);\n    }\n\n    if (status != PSA_OPERATION_INCOMPLETE) {\n        if (status != PSA_SUCCESS) {\n            operation->error_occurred = 1;\n        }\n\n        psa_sign_hash_abort_internal(operation);\n    }\n\n    LOCAL_OUTPUT_FREE(signature_external, signature);\n\n    return status;\n}\n\npsa_status_t psa_sign_hash_abort(\n    psa_sign_hash_interruptible_operation_t *operation)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    status = psa_sign_hash_abort_internal(operation);\n\n    /* We clear the number of ops done here, so that it is not cleared when\n     * the operation fails or succeeds, only on manual abort. */\n    operation->num_ops = 0;\n\n    /* Likewise, failure state. */\n    operation->error_occurred = 0;\n\n    return status;\n}\n\nstatic psa_status_t psa_verify_hash_abort_internal(\n    psa_verify_hash_interruptible_operation_t *operation)\n{\n    if (operation->id == 0) {\n        /* The object has (apparently) been initialized but it is not (yet)\n         * in use. It's ok to call abort on such an object, and there's\n         * nothing to do. */\n        return PSA_SUCCESS;\n    }\n\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    status = psa_driver_wrapper_verify_hash_abort(operation);\n\n    operation->id = 0;\n\n    /* Do not clear either the error_occurred or num_ops elements here as they\n     * only want to be cleared by the application calling abort, not by abort\n     * being called at completion of an operation. */\n\n    return status;\n}\n\npsa_status_t psa_verify_hash_start(\n    psa_verify_hash_interruptible_operation_t *operation,\n    mbedtls_svc_key_id_t key, psa_algorithm_t alg,\n    const uint8_t *hash_external, size_t hash_length,\n    const uint8_t *signature_external, size_t signature_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n\n    LOCAL_INPUT_DECLARE(hash_external, hash);\n    LOCAL_INPUT_DECLARE(signature_external, signature);\n\n    /* Check that start has not been previously called, or operation has not\n     * previously errored. */\n    if (operation->id != 0 || operation->error_occurred) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    /* Make sure the driver-dependent part of the operation is zeroed.\n     * This is a guarantee we make to drivers. Initializing the operation\n     * does not necessarily take care of it, since the context is a\n     * union and initializing a union does not necessarily initialize\n     * all of its members. */\n    memset(&operation->ctx, 0, sizeof(operation->ctx));\n\n    status = psa_sign_verify_check_alg(0, alg);\n    if (status != PSA_SUCCESS) {\n        operation->error_occurred = 1;\n        return status;\n    }\n\n    status = psa_get_and_lock_key_slot_with_policy(key, &slot,\n                                                   PSA_KEY_USAGE_VERIFY_HASH,\n                                                   alg);\n\n    if (status != PSA_SUCCESS) {\n        operation->error_occurred = 1;\n        return status;\n    }\n\n    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);\n    LOCAL_INPUT_ALLOC(signature_external, signature_length, signature);\n\n    /* Ensure ops count gets reset, in case of operation re-use. */\n    operation->num_ops = 0;\n\n    status = psa_driver_wrapper_verify_hash_start(operation, &slot->attr,\n                                                  slot->key.data,\n                                                  slot->key.bytes,\n                                                  alg, hash, hash_length,\n                                                  signature, signature_length);\n#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\nexit:\n#endif\n\n    if (status != PSA_SUCCESS) {\n        operation->error_occurred = 1;\n        psa_verify_hash_abort_internal(operation);\n    }\n\n    unlock_status = psa_unregister_read_under_mutex(slot);\n\n    if (unlock_status != PSA_SUCCESS) {\n        operation->error_occurred = 1;\n    }\n\n    LOCAL_INPUT_FREE(hash_external, hash);\n    LOCAL_INPUT_FREE(signature_external, signature);\n\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n}\n\npsa_status_t psa_verify_hash_complete(\n    psa_verify_hash_interruptible_operation_t *operation)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    /* Check that start has been called first, and that operation has not\n     * previously errored. */\n    if (operation->id == 0 || operation->error_occurred) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    status = psa_driver_wrapper_verify_hash_complete(operation);\n\n    /* Update ops count with work done. */\n    operation->num_ops = psa_driver_wrapper_verify_hash_get_num_ops(\n        operation);\n\nexit:\n\n    if (status != PSA_OPERATION_INCOMPLETE) {\n        if (status != PSA_SUCCESS) {\n            operation->error_occurred = 1;\n        }\n\n        psa_verify_hash_abort_internal(operation);\n    }\n\n    return status;\n}\n\npsa_status_t psa_verify_hash_abort(\n    psa_verify_hash_interruptible_operation_t *operation)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    status = psa_verify_hash_abort_internal(operation);\n\n    /* We clear the number of ops done here, so that it is not cleared when\n     * the operation fails or succeeds, only on manual abort. */\n    operation->num_ops = 0;\n\n    /* Likewise, failure state. */\n    operation->error_occurred = 0;\n\n    return status;\n}\n\n/****************************************************************/\n/* Asymmetric interruptible cryptography internal               */\n/* implementations                                              */\n/****************************************************************/\n\nvoid mbedtls_psa_interruptible_set_max_ops(uint32_t max_ops)\n{\n\n#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \\\n    defined(MBEDTLS_ECP_RESTARTABLE)\n\n    /* Internal implementation uses zero to indicate infinite number max ops,\n     * therefore avoid this value, and set to minimum possible. */\n    if (max_ops == 0) {\n        max_ops = 1;\n    }\n\n    mbedtls_ecp_set_max_ops(max_ops);\n#else\n    (void) max_ops;\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&\n        * defined( MBEDTLS_ECP_RESTARTABLE ) */\n}\n\nuint32_t mbedtls_psa_sign_hash_get_num_ops(\n    const mbedtls_psa_sign_hash_interruptible_operation_t *operation)\n{\n#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \\\n    defined(MBEDTLS_ECP_RESTARTABLE)\n\n    return operation->num_ops;\n#else\n    (void) operation;\n    return 0;\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&\n        * defined( MBEDTLS_ECP_RESTARTABLE ) */\n}\n\nuint32_t mbedtls_psa_verify_hash_get_num_ops(\n    const mbedtls_psa_verify_hash_interruptible_operation_t *operation)\n{\n    #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \\\n    defined(MBEDTLS_ECP_RESTARTABLE)\n\n    return operation->num_ops;\n#else\n    (void) operation;\n    return 0;\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&\n        * defined( MBEDTLS_ECP_RESTARTABLE ) */\n}\n\n/* Detect supported interruptible sign/verify mechanisms precisely.\n * This is not strictly needed: we could accept everything, and let the\n * code fail later during complete() if the mechanism is unsupported\n * (e.g. attempting deterministic ECDSA when only the randomized variant\n * is available). But it's easier for applications and especially for our\n * test code to detect all not-supported errors during start().\n *\n * Note that this function ignores the hash component. The core code\n * is supposed to check the hash part by calling is_hash_supported().\n */\nstatic inline int can_do_interruptible_sign_verify(psa_algorithm_t alg)\n{\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)\n    if (PSA_ALG_IS_DETERMINISTIC_ECDSA(alg)) {\n        return 1;\n    }\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA)\n    if (PSA_ALG_IS_RANDOMIZED_ECDSA(alg)) {\n        return 1;\n    }\n#endif\n#endif /* defined(MBEDTLS_ECP_RESTARTABLE) */\n    (void) alg;\n    return 0;\n}\n\npsa_status_t mbedtls_psa_sign_hash_start(\n    mbedtls_psa_sign_hash_interruptible_operation_t *operation,\n    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,\n    size_t key_buffer_size, psa_algorithm_t alg,\n    const uint8_t *hash, size_t hash_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t required_hash_length;\n\n    if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->type)) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n    psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type);\n    if (!PSA_ECC_FAMILY_IS_WEIERSTRASS(curve)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    if (!can_do_interruptible_sign_verify(alg)) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \\\n    defined(MBEDTLS_ECP_RESTARTABLE)\n\n    mbedtls_ecdsa_restart_init(&operation->restart_ctx);\n\n    /* Ensure num_ops is zero'ed in case of context re-use. */\n    operation->num_ops = 0;\n\n    status = mbedtls_psa_ecp_load_representation(attributes->type,\n                                                 attributes->bits,\n                                                 key_buffer,\n                                                 key_buffer_size,\n                                                 &operation->ctx);\n\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    operation->coordinate_bytes = PSA_BITS_TO_BYTES(\n        operation->ctx->grp.nbits);\n\n    psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);\n    operation->md_alg = mbedtls_md_type_from_psa_alg(hash_alg);\n    operation->alg = alg;\n\n    /* We only need to store the same length of hash as the private key size\n     * here, it would be truncated by the internal implementation anyway. */\n    required_hash_length = (hash_length < operation->coordinate_bytes ?\n                            hash_length : operation->coordinate_bytes);\n\n    if (required_hash_length > sizeof(operation->hash)) {\n        /* Shouldn't happen, but better safe than sorry. */\n        return PSA_ERROR_CORRUPTION_DETECTED;\n    }\n\n    memcpy(operation->hash, hash, required_hash_length);\n    operation->hash_length = required_hash_length;\n\n    return PSA_SUCCESS;\n\n#else\n    (void) operation;\n    (void) key_buffer;\n    (void) key_buffer_size;\n    (void) alg;\n    (void) hash;\n    (void) hash_length;\n    (void) status;\n    (void) required_hash_length;\n\n    return PSA_ERROR_NOT_SUPPORTED;\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&\n        * defined( MBEDTLS_ECP_RESTARTABLE ) */\n}\n\npsa_status_t mbedtls_psa_sign_hash_complete(\n    mbedtls_psa_sign_hash_interruptible_operation_t *operation,\n    uint8_t *signature, size_t signature_size,\n    size_t *signature_length)\n{\n#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \\\n    defined(MBEDTLS_ECP_RESTARTABLE)\n\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi r;\n    mbedtls_mpi s;\n\n    mbedtls_mpi_init(&r);\n    mbedtls_mpi_init(&s);\n\n    /* Ensure max_ops is set to the current value (or default). */\n    mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops());\n\n    if (signature_size < 2 * operation->coordinate_bytes) {\n        status = PSA_ERROR_BUFFER_TOO_SMALL;\n        goto exit;\n    }\n\n    if (PSA_ALG_ECDSA_IS_DETERMINISTIC(operation->alg)) {\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)\n        status = mbedtls_to_psa_error(\n            mbedtls_ecdsa_sign_det_restartable(&operation->ctx->grp,\n                                               &r,\n                                               &s,\n                                               &operation->ctx->d,\n                                               operation->hash,\n                                               operation->hash_length,\n                                               operation->md_alg,\n                                               mbedtls_psa_get_random,\n                                               MBEDTLS_PSA_RANDOM_STATE,\n                                               &operation->restart_ctx));\n#else /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */\n        status = PSA_ERROR_NOT_SUPPORTED;\n        goto exit;\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */\n    } else {\n        status = mbedtls_to_psa_error(\n            mbedtls_ecdsa_sign_restartable(&operation->ctx->grp,\n                                           &r,\n                                           &s,\n                                           &operation->ctx->d,\n                                           operation->hash,\n                                           operation->hash_length,\n                                           mbedtls_psa_get_random,\n                                           MBEDTLS_PSA_RANDOM_STATE,\n                                           mbedtls_psa_get_random,\n                                           MBEDTLS_PSA_RANDOM_STATE,\n                                           &operation->restart_ctx));\n    }\n\n    /* Hide the fact that the restart context only holds a delta of number of\n     * ops done during the last operation, not an absolute value. */\n    operation->num_ops += operation->restart_ctx.ecp.ops_done;\n\n    if (status == PSA_SUCCESS) {\n        status =  mbedtls_to_psa_error(\n            mbedtls_mpi_write_binary(&r,\n                                     signature,\n                                     operation->coordinate_bytes)\n            );\n\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n\n        status =  mbedtls_to_psa_error(\n            mbedtls_mpi_write_binary(&s,\n                                     signature +\n                                     operation->coordinate_bytes,\n                                     operation->coordinate_bytes)\n            );\n\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n\n        *signature_length = operation->coordinate_bytes * 2;\n\n        status = PSA_SUCCESS;\n    }\n\nexit:\n\n    mbedtls_mpi_free(&r);\n    mbedtls_mpi_free(&s);\n    return status;\n\n #else\n\n    (void) operation;\n    (void) signature;\n    (void) signature_size;\n    (void) signature_length;\n\n    return PSA_ERROR_NOT_SUPPORTED;\n\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&\n        * defined( MBEDTLS_ECP_RESTARTABLE ) */\n}\n\npsa_status_t mbedtls_psa_sign_hash_abort(\n    mbedtls_psa_sign_hash_interruptible_operation_t *operation)\n{\n\n#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \\\n    defined(MBEDTLS_ECP_RESTARTABLE)\n\n    if (operation->ctx) {\n        mbedtls_ecdsa_free(operation->ctx);\n        mbedtls_free(operation->ctx);\n        operation->ctx = NULL;\n    }\n\n    mbedtls_ecdsa_restart_free(&operation->restart_ctx);\n\n    operation->num_ops = 0;\n\n    return PSA_SUCCESS;\n\n#else\n\n    (void) operation;\n\n    return PSA_ERROR_NOT_SUPPORTED;\n\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&\n        * defined( MBEDTLS_ECP_RESTARTABLE ) */\n}\n\npsa_status_t mbedtls_psa_verify_hash_start(\n    mbedtls_psa_verify_hash_interruptible_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *hash, size_t hash_length,\n    const uint8_t *signature, size_t signature_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t coordinate_bytes = 0;\n    size_t required_hash_length = 0;\n\n    if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n    psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type);\n    if (!PSA_ECC_FAMILY_IS_WEIERSTRASS(curve)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    if (!can_do_interruptible_sign_verify(alg)) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \\\n    defined(MBEDTLS_ECP_RESTARTABLE)\n\n    mbedtls_ecdsa_restart_init(&operation->restart_ctx);\n    mbedtls_mpi_init(&operation->r);\n    mbedtls_mpi_init(&operation->s);\n\n    /* Ensure num_ops is zero'ed in case of context re-use. */\n    operation->num_ops = 0;\n\n    status = mbedtls_psa_ecp_load_representation(attributes->type,\n                                                 attributes->bits,\n                                                 key_buffer,\n                                                 key_buffer_size,\n                                                 &operation->ctx);\n\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    coordinate_bytes = PSA_BITS_TO_BYTES(operation->ctx->grp.nbits);\n\n    if (signature_length != 2 * coordinate_bytes) {\n        return PSA_ERROR_INVALID_SIGNATURE;\n    }\n\n    status = mbedtls_to_psa_error(\n        mbedtls_mpi_read_binary(&operation->r,\n                                signature,\n                                coordinate_bytes));\n\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    status = mbedtls_to_psa_error(\n        mbedtls_mpi_read_binary(&operation->s,\n                                signature +\n                                coordinate_bytes,\n                                coordinate_bytes));\n\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    status = mbedtls_psa_ecp_load_public_part(operation->ctx);\n\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    /* We only need to store the same length of hash as the private key size\n     * here, it would be truncated by the internal implementation anyway. */\n    required_hash_length = (hash_length < coordinate_bytes ? hash_length :\n                            coordinate_bytes);\n\n    if (required_hash_length > sizeof(operation->hash)) {\n        /* Shouldn't happen, but better safe than sorry. */\n        return PSA_ERROR_CORRUPTION_DETECTED;\n    }\n\n    memcpy(operation->hash, hash, required_hash_length);\n    operation->hash_length = required_hash_length;\n\n    return PSA_SUCCESS;\n#else\n    (void) operation;\n    (void) key_buffer;\n    (void) key_buffer_size;\n    (void) alg;\n    (void) hash;\n    (void) hash_length;\n    (void) signature;\n    (void) signature_length;\n    (void) status;\n    (void) coordinate_bytes;\n    (void) required_hash_length;\n\n    return PSA_ERROR_NOT_SUPPORTED;\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&\n        * defined( MBEDTLS_ECP_RESTARTABLE ) */\n}\n\npsa_status_t mbedtls_psa_verify_hash_complete(\n    mbedtls_psa_verify_hash_interruptible_operation_t *operation)\n{\n\n#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \\\n    defined(MBEDTLS_ECP_RESTARTABLE)\n\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    /* Ensure max_ops is set to the current value (or default). */\n    mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops());\n\n    status = mbedtls_to_psa_error(\n        mbedtls_ecdsa_verify_restartable(&operation->ctx->grp,\n                                         operation->hash,\n                                         operation->hash_length,\n                                         &operation->ctx->Q,\n                                         &operation->r,\n                                         &operation->s,\n                                         &operation->restart_ctx));\n\n    /* Hide the fact that the restart context only holds a delta of number of\n     * ops done during the last operation, not an absolute value. */\n    operation->num_ops += operation->restart_ctx.ecp.ops_done;\n\n    return status;\n#else\n    (void) operation;\n\n    return PSA_ERROR_NOT_SUPPORTED;\n\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&\n        * defined( MBEDTLS_ECP_RESTARTABLE ) */\n}\n\npsa_status_t mbedtls_psa_verify_hash_abort(\n    mbedtls_psa_verify_hash_interruptible_operation_t *operation)\n{\n\n#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \\\n    defined(MBEDTLS_ECP_RESTARTABLE)\n\n    if (operation->ctx) {\n        mbedtls_ecdsa_free(operation->ctx);\n        mbedtls_free(operation->ctx);\n        operation->ctx = NULL;\n    }\n\n    mbedtls_ecdsa_restart_free(&operation->restart_ctx);\n\n    operation->num_ops = 0;\n\n    mbedtls_mpi_free(&operation->r);\n    mbedtls_mpi_free(&operation->s);\n\n    return PSA_SUCCESS;\n\n#else\n    (void) operation;\n\n    return PSA_ERROR_NOT_SUPPORTED;\n\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&\n        * defined( MBEDTLS_ECP_RESTARTABLE ) */\n}\n\nstatic psa_status_t psa_generate_random_internal(uint8_t *output,\n                                                 size_t output_size)\n{\n    GUARD_MODULE_INITIALIZED;\n\n#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)\n\n    psa_status_t status;\n    size_t output_length = 0;\n    status = mbedtls_psa_external_get_random(&global_data.rng,\n                                             output, output_size,\n                                             &output_length);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n    /* Breaking up a request into smaller chunks is currently not supported\n     * for the external RNG interface. */\n    if (output_length != output_size) {\n        return PSA_ERROR_INSUFFICIENT_ENTROPY;\n    }\n    return PSA_SUCCESS;\n\n#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */\n\n    while (output_size > 0) {\n        int ret = MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;\n        size_t request_size =\n            (output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ?\n             MBEDTLS_PSA_RANDOM_MAX_REQUEST :\n             output_size);\n#if defined(MBEDTLS_CTR_DRBG_C)\n        ret = mbedtls_ctr_drbg_random(&global_data.rng.drbg, output, request_size);\n#elif defined(MBEDTLS_HMAC_DRBG_C)\n        ret = mbedtls_hmac_drbg_random(&global_data.rng.drbg, output, request_size);\n#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */\n        if (ret != 0) {\n            return mbedtls_to_psa_error(ret);\n        }\n        output_size -= request_size;\n        output += request_size;\n    }\n    return PSA_SUCCESS;\n#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */\n}\n\n\n/****************************************************************/\n/* Symmetric cryptography */\n/****************************************************************/\n\nstatic psa_status_t psa_cipher_setup(psa_cipher_operation_t *operation,\n                                     mbedtls_svc_key_id_t key,\n                                     psa_algorithm_t alg,\n                                     mbedtls_operation_t cipher_operation)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot = NULL;\n    psa_key_usage_t usage = (cipher_operation == MBEDTLS_ENCRYPT ?\n                             PSA_KEY_USAGE_ENCRYPT :\n                             PSA_KEY_USAGE_DECRYPT);\n\n    /* A context must be freshly initialized before it can be set up. */\n    if (operation->id != 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (!PSA_ALG_IS_CIPHER(alg)) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    status = psa_get_and_lock_key_slot_with_policy(key, &slot, usage, alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    /* Initialize the operation struct members, except for id. The id member\n     * is used to indicate to psa_cipher_abort that there are resources to free,\n     * so we only set it (in the driver wrapper) after resources have been\n     * allocated/initialized. */\n    operation->iv_set = 0;\n    if (alg == PSA_ALG_ECB_NO_PADDING) {\n        operation->iv_required = 0;\n    } else {\n        operation->iv_required = 1;\n    }\n    operation->default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg);\n\n\n    /* Make sure the driver-dependent part of the operation is zeroed.\n     * This is a guarantee we make to drivers. Initializing the operation\n     * does not necessarily take care of it, since the context is a\n     * union and initializing a union does not necessarily initialize\n     * all of its members. */\n    memset(&operation->ctx, 0, sizeof(operation->ctx));\n\n    /* Try doing the operation through a driver before using software fallback. */\n    if (cipher_operation == MBEDTLS_ENCRYPT) {\n        status = psa_driver_wrapper_cipher_encrypt_setup(operation,\n                                                         &slot->attr,\n                                                         slot->key.data,\n                                                         slot->key.bytes,\n                                                         alg);\n    } else {\n        status = psa_driver_wrapper_cipher_decrypt_setup(operation,\n                                                         &slot->attr,\n                                                         slot->key.data,\n                                                         slot->key.bytes,\n                                                         alg);\n    }\n\nexit:\n    if (status != PSA_SUCCESS) {\n        psa_cipher_abort(operation);\n    }\n\n    unlock_status = psa_unregister_read_under_mutex(slot);\n\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n}\n\npsa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,\n                                      mbedtls_svc_key_id_t key,\n                                      psa_algorithm_t alg)\n{\n    return psa_cipher_setup(operation, key, alg, MBEDTLS_ENCRYPT);\n}\n\npsa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation,\n                                      mbedtls_svc_key_id_t key,\n                                      psa_algorithm_t alg)\n{\n    return psa_cipher_setup(operation, key, alg, MBEDTLS_DECRYPT);\n}\n\npsa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation,\n                                    uint8_t *iv_external,\n                                    size_t iv_size,\n                                    size_t *iv_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t default_iv_length = 0;\n\n    LOCAL_OUTPUT_DECLARE(iv_external, iv);\n\n    if (operation->id == 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (operation->iv_set || !operation->iv_required) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    default_iv_length = operation->default_iv_length;\n    if (iv_size < default_iv_length) {\n        status = PSA_ERROR_BUFFER_TOO_SMALL;\n        goto exit;\n    }\n\n    if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) {\n        status = PSA_ERROR_GENERIC_ERROR;\n        goto exit;\n    }\n\n    LOCAL_OUTPUT_ALLOC(iv_external, default_iv_length, iv);\n\n    status = psa_generate_random_internal(iv, default_iv_length);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_driver_wrapper_cipher_set_iv(operation,\n                                              iv, default_iv_length);\n\nexit:\n    if (status == PSA_SUCCESS) {\n        *iv_length = default_iv_length;\n        operation->iv_set = 1;\n    } else {\n        *iv_length = 0;\n        psa_cipher_abort(operation);\n        if (iv != NULL) {\n            mbedtls_platform_zeroize(iv, default_iv_length);\n        }\n    }\n\n    LOCAL_OUTPUT_FREE(iv_external, iv);\n    return status;\n}\n\npsa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation,\n                               const uint8_t *iv_external,\n                               size_t iv_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    LOCAL_INPUT_DECLARE(iv_external, iv);\n\n    if (operation->id == 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (operation->iv_set || !operation->iv_required) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (iv_length > PSA_CIPHER_IV_MAX_SIZE) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    LOCAL_INPUT_ALLOC(iv_external, iv_length, iv);\n\n    status = psa_driver_wrapper_cipher_set_iv(operation,\n                                              iv,\n                                              iv_length);\n\nexit:\n    if (status == PSA_SUCCESS) {\n        operation->iv_set = 1;\n    } else {\n        psa_cipher_abort(operation);\n    }\n\n    LOCAL_INPUT_FREE(iv_external, iv);\n\n    return status;\n}\n\npsa_status_t psa_cipher_update(psa_cipher_operation_t *operation,\n                               const uint8_t *input_external,\n                               size_t input_length,\n                               uint8_t *output_external,\n                               size_t output_size,\n                               size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    LOCAL_INPUT_DECLARE(input_external, input);\n    LOCAL_OUTPUT_DECLARE(output_external, output);\n\n    if (operation->id == 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (operation->iv_required && !operation->iv_set) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);\n\n    status = psa_driver_wrapper_cipher_update(operation,\n                                              input,\n                                              input_length,\n                                              output,\n                                              output_size,\n                                              output_length);\n\nexit:\n    if (status != PSA_SUCCESS) {\n        psa_cipher_abort(operation);\n    }\n\n    LOCAL_INPUT_FREE(input_external, input);\n    LOCAL_OUTPUT_FREE(output_external, output);\n\n    return status;\n}\n\npsa_status_t psa_cipher_finish(psa_cipher_operation_t *operation,\n                               uint8_t *output_external,\n                               size_t output_size,\n                               size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_GENERIC_ERROR;\n\n    LOCAL_OUTPUT_DECLARE(output_external, output);\n\n    if (operation->id == 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (operation->iv_required && !operation->iv_set) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);\n\n    status = psa_driver_wrapper_cipher_finish(operation,\n                                              output,\n                                              output_size,\n                                              output_length);\n\nexit:\n    /* C99 doesn't allow a declaration to follow a label */;\n    psa_status_t abort_status = psa_cipher_abort(operation);\n    /* Normally abort shouldn't fail unless the operation is in a bad\n     * state, in which case we'd expect finish to fail with the same error.\n     * So it doesn't matter much which call's error code we pick when both\n     * fail. However, in unauthenticated decryption specifically, the\n     * distinction between PSA_SUCCESS and PSA_ERROR_INVALID_PADDING is\n     * security-sensitive (risk of a padding oracle attack), so here we\n     * must not have a code path that depends on the value of status. */\n    if (abort_status != PSA_SUCCESS) {\n        status = abort_status;\n    }\n\n    /* Set *output_length to 0 if status != PSA_SUCCESS, without\n     * leaking the value of status through a timing side channel\n     * (status == PSA_ERROR_INVALID_PADDING is sensitive when doing\n     * unpadded decryption, due to the risk of padding oracle attack). */\n    mbedtls_ct_condition_t success =\n        mbedtls_ct_bool_not(mbedtls_ct_bool(status));\n    *output_length = mbedtls_ct_size_if_else_0(success, *output_length);\n\n    LOCAL_OUTPUT_FREE(output_external, output);\n\n    return status;\n}\n\npsa_status_t psa_cipher_abort(psa_cipher_operation_t *operation)\n{\n    if (operation->id == 0) {\n        /* The object has (apparently) been initialized but it is not (yet)\n         * in use. It's ok to call abort on such an object, and there's\n         * nothing to do. */\n        return PSA_SUCCESS;\n    }\n\n    psa_driver_wrapper_cipher_abort(operation);\n\n    operation->id = 0;\n    operation->iv_set = 0;\n    operation->iv_required = 0;\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key,\n                                psa_algorithm_t alg,\n                                const uint8_t *input_external,\n                                size_t input_length,\n                                uint8_t *output_external,\n                                size_t output_size,\n                                size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot = NULL;\n    uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE];\n    size_t default_iv_length = 0;\n\n    LOCAL_INPUT_DECLARE(input_external, input);\n    LOCAL_OUTPUT_DECLARE(output_external, output);\n\n    if (!PSA_ALG_IS_CIPHER(alg)) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    status = psa_get_and_lock_key_slot_with_policy(key, &slot,\n                                                   PSA_KEY_USAGE_ENCRYPT,\n                                                   alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg);\n    if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) {\n        status = PSA_ERROR_GENERIC_ERROR;\n        goto exit;\n    }\n\n    if (default_iv_length > 0) {\n        if (output_size < default_iv_length) {\n            status = PSA_ERROR_BUFFER_TOO_SMALL;\n            goto exit;\n        }\n\n        status = psa_generate_random_internal(local_iv, default_iv_length);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n    }\n\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);\n\n    status = psa_driver_wrapper_cipher_encrypt(\n        &slot->attr, slot->key.data, slot->key.bytes,\n        alg, local_iv, default_iv_length, input, input_length,\n        psa_crypto_buffer_offset(output, default_iv_length),\n        output_size - default_iv_length, output_length);\n\nexit:\n    unlock_status = psa_unregister_read_under_mutex(slot);\n    if (status == PSA_SUCCESS) {\n        status = unlock_status;\n    }\n\n    if (status == PSA_SUCCESS) {\n        if (default_iv_length > 0) {\n            memcpy(output, local_iv, default_iv_length);\n        }\n        *output_length += default_iv_length;\n    } else {\n        *output_length = 0;\n    }\n\n    LOCAL_INPUT_FREE(input_external, input);\n    LOCAL_OUTPUT_FREE(output_external, output);\n\n    return status;\n}\n\npsa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key,\n                                psa_algorithm_t alg,\n                                const uint8_t *input_external,\n                                size_t input_length,\n                                uint8_t *output_external,\n                                size_t output_size,\n                                size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot = NULL;\n\n    LOCAL_INPUT_DECLARE(input_external, input);\n    LOCAL_OUTPUT_DECLARE(output_external, output);\n\n    if (!PSA_ALG_IS_CIPHER(alg)) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    status = psa_get_and_lock_key_slot_with_policy(key, &slot,\n                                                   PSA_KEY_USAGE_DECRYPT,\n                                                   alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (input_length < PSA_CIPHER_IV_LENGTH(slot->attr.type, alg)) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);\n\n    status = psa_driver_wrapper_cipher_decrypt(\n        &slot->attr, slot->key.data, slot->key.bytes,\n        alg, input, input_length,\n        output, output_size, output_length);\n\nexit:\n    unlock_status = psa_unregister_read_under_mutex(slot);\n    if (unlock_status != PSA_SUCCESS) {\n        status = unlock_status;\n    }\n\n    /* Set *output_length to 0 if status != PSA_SUCCESS, without\n     * leaking the value of status through a timing side channel\n     * (status == PSA_ERROR_INVALID_PADDING is sensitive when doing\n     * unpadded decryption, due to the risk of padding oracle attack). */\n    mbedtls_ct_condition_t success =\n        mbedtls_ct_bool_not(mbedtls_ct_bool(status));\n    *output_length = mbedtls_ct_size_if_else_0(success, *output_length);\n\n    LOCAL_INPUT_FREE(input_external, input);\n    LOCAL_OUTPUT_FREE(output_external, output);\n\n    return status;\n}\n\n\n/****************************************************************/\n/* AEAD */\n/****************************************************************/\n\n/* Helper function to get the base algorithm from its variants. */\nstatic psa_algorithm_t psa_aead_get_base_algorithm(psa_algorithm_t alg)\n{\n    return PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg);\n}\n\n/* Helper function to perform common nonce length checks. */\nstatic psa_status_t psa_aead_check_nonce_length(psa_algorithm_t alg,\n                                                size_t nonce_length)\n{\n    psa_algorithm_t base_alg = psa_aead_get_base_algorithm(alg);\n\n    switch (base_alg) {\n#if defined(PSA_WANT_ALG_GCM)\n        case PSA_ALG_GCM:\n            /* Not checking max nonce size here as GCM spec allows almost\n             * arbitrarily large nonces. Please note that we do not generally\n             * recommend the usage of nonces of greater length than\n             * PSA_AEAD_NONCE_MAX_SIZE, as large nonces are hashed to a shorter\n             * size, which can then lead to collisions if you encrypt a very\n             * large number of messages.*/\n            if (nonce_length != 0) {\n                return PSA_SUCCESS;\n            }\n            break;\n#endif /* PSA_WANT_ALG_GCM */\n#if defined(PSA_WANT_ALG_CCM)\n        case PSA_ALG_CCM:\n            if (nonce_length >= 7 && nonce_length <= 13) {\n                return PSA_SUCCESS;\n            }\n            break;\n#endif /* PSA_WANT_ALG_CCM */\n#if defined(PSA_WANT_ALG_CHACHA20_POLY1305)\n        case PSA_ALG_CHACHA20_POLY1305:\n            if (nonce_length == 12) {\n                return PSA_SUCCESS;\n            } else if (nonce_length == 8) {\n                return PSA_ERROR_NOT_SUPPORTED;\n            }\n            break;\n#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */\n        default:\n            (void) nonce_length;\n            return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    return PSA_ERROR_INVALID_ARGUMENT;\n}\n\nstatic psa_status_t psa_aead_check_algorithm(psa_algorithm_t alg)\n{\n    if (!PSA_ALG_IS_AEAD(alg) || PSA_ALG_IS_WILDCARD(alg)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key,\n                              psa_algorithm_t alg,\n                              const uint8_t *nonce_external,\n                              size_t nonce_length,\n                              const uint8_t *additional_data_external,\n                              size_t additional_data_length,\n                              const uint8_t *plaintext_external,\n                              size_t plaintext_length,\n                              uint8_t *ciphertext_external,\n                              size_t ciphertext_size,\n                              size_t *ciphertext_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n\n    LOCAL_INPUT_DECLARE(nonce_external, nonce);\n    LOCAL_INPUT_DECLARE(additional_data_external, additional_data);\n    LOCAL_INPUT_DECLARE(plaintext_external, plaintext);\n    LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext);\n\n    *ciphertext_length = 0;\n\n    status = psa_aead_check_algorithm(alg);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    status = psa_get_and_lock_key_slot_with_policy(\n        key, &slot, PSA_KEY_USAGE_ENCRYPT, alg);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce);\n    LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length, additional_data);\n    LOCAL_INPUT_ALLOC(plaintext_external, plaintext_length, plaintext);\n    LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext);\n\n    status = psa_aead_check_nonce_length(alg, nonce_length);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_driver_wrapper_aead_encrypt(\n        &slot->attr, slot->key.data, slot->key.bytes,\n        alg,\n        nonce, nonce_length,\n        additional_data, additional_data_length,\n        plaintext, plaintext_length,\n        ciphertext, ciphertext_size, ciphertext_length);\n\n    if (status != PSA_SUCCESS && ciphertext_size != 0) {\n        memset(ciphertext, 0, ciphertext_size);\n    }\n\nexit:\n    LOCAL_INPUT_FREE(nonce_external, nonce);\n    LOCAL_INPUT_FREE(additional_data_external, additional_data);\n    LOCAL_INPUT_FREE(plaintext_external, plaintext);\n    LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext);\n\n    psa_unregister_read_under_mutex(slot);\n\n    return status;\n}\n\npsa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key,\n                              psa_algorithm_t alg,\n                              const uint8_t *nonce_external,\n                              size_t nonce_length,\n                              const uint8_t *additional_data_external,\n                              size_t additional_data_length,\n                              const uint8_t *ciphertext_external,\n                              size_t ciphertext_length,\n                              uint8_t *plaintext_external,\n                              size_t plaintext_size,\n                              size_t *plaintext_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n\n    LOCAL_INPUT_DECLARE(nonce_external, nonce);\n    LOCAL_INPUT_DECLARE(additional_data_external, additional_data);\n    LOCAL_INPUT_DECLARE(ciphertext_external, ciphertext);\n    LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext);\n\n    *plaintext_length = 0;\n\n    status = psa_aead_check_algorithm(alg);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    status = psa_get_and_lock_key_slot_with_policy(\n        key, &slot, PSA_KEY_USAGE_DECRYPT, alg);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce);\n    LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length,\n                      additional_data);\n    LOCAL_INPUT_ALLOC(ciphertext_external, ciphertext_length, ciphertext);\n    LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext);\n\n    status = psa_aead_check_nonce_length(alg, nonce_length);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_driver_wrapper_aead_decrypt(\n        &slot->attr, slot->key.data, slot->key.bytes,\n        alg,\n        nonce, nonce_length,\n        additional_data, additional_data_length,\n        ciphertext, ciphertext_length,\n        plaintext, plaintext_size, plaintext_length);\n\n    if (status != PSA_SUCCESS && plaintext_size != 0) {\n        memset(plaintext, 0, plaintext_size);\n    }\n\nexit:\n    LOCAL_INPUT_FREE(nonce_external, nonce);\n    LOCAL_INPUT_FREE(additional_data_external, additional_data);\n    LOCAL_INPUT_FREE(ciphertext_external, ciphertext);\n    LOCAL_OUTPUT_FREE(plaintext_external, plaintext);\n\n    psa_unregister_read_under_mutex(slot);\n\n    return status;\n}\n\nstatic psa_status_t psa_validate_tag_length(psa_algorithm_t alg)\n{\n    const uint8_t tag_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);\n\n    switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) {\n#if defined(PSA_WANT_ALG_CCM)\n        case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):\n            /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.*/\n            if (tag_len < 4 || tag_len > 16 || tag_len % 2) {\n                return PSA_ERROR_INVALID_ARGUMENT;\n            }\n            break;\n#endif /* PSA_WANT_ALG_CCM */\n\n#if defined(PSA_WANT_ALG_GCM)\n        case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):\n            /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. */\n            if (tag_len != 4 && tag_len != 8 && (tag_len < 12 || tag_len > 16)) {\n                return PSA_ERROR_INVALID_ARGUMENT;\n            }\n            break;\n#endif /* PSA_WANT_ALG_GCM */\n\n#if defined(PSA_WANT_ALG_CHACHA20_POLY1305)\n        case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):\n            /* We only support the default tag length. */\n            if (tag_len != 16) {\n                return PSA_ERROR_INVALID_ARGUMENT;\n            }\n            break;\n#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */\n\n        default:\n            (void) tag_len;\n            return PSA_ERROR_NOT_SUPPORTED;\n    }\n    return PSA_SUCCESS;\n}\n\n/* Set the key for a multipart authenticated operation. */\nstatic psa_status_t psa_aead_setup(psa_aead_operation_t *operation,\n                                   int is_encrypt,\n                                   mbedtls_svc_key_id_t key,\n                                   psa_algorithm_t alg)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot = NULL;\n    psa_key_usage_t key_usage = 0;\n\n    status = psa_aead_check_algorithm(alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (operation->id != 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (operation->nonce_set || operation->lengths_set ||\n        operation->ad_started || operation->body_started) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    /* Make sure the driver-dependent part of the operation is zeroed.\n     * This is a guarantee we make to drivers. Initializing the operation\n     * does not necessarily take care of it, since the context is a\n     * union and initializing a union does not necessarily initialize\n     * all of its members. */\n    memset(&operation->ctx, 0, sizeof(operation->ctx));\n\n    if (is_encrypt) {\n        key_usage = PSA_KEY_USAGE_ENCRYPT;\n    } else {\n        key_usage = PSA_KEY_USAGE_DECRYPT;\n    }\n\n    status = psa_get_and_lock_key_slot_with_policy(key, &slot, key_usage,\n                                                   alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if ((status = psa_validate_tag_length(alg)) != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (is_encrypt) {\n        status = psa_driver_wrapper_aead_encrypt_setup(operation,\n                                                       &slot->attr,\n                                                       slot->key.data,\n                                                       slot->key.bytes,\n                                                       alg);\n    } else {\n        status = psa_driver_wrapper_aead_decrypt_setup(operation,\n                                                       &slot->attr,\n                                                       slot->key.data,\n                                                       slot->key.bytes,\n                                                       alg);\n    }\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    operation->key_type = psa_get_key_type(&slot->attr);\n\nexit:\n    unlock_status = psa_unregister_read_under_mutex(slot);\n\n    if (status == PSA_SUCCESS) {\n        status = unlock_status;\n        operation->alg = psa_aead_get_base_algorithm(alg);\n        operation->is_encrypt = is_encrypt;\n    } else {\n        psa_aead_abort(operation);\n    }\n\n    return status;\n}\n\n/* Set the key for a multipart authenticated encryption operation. */\npsa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation,\n                                    mbedtls_svc_key_id_t key,\n                                    psa_algorithm_t alg)\n{\n    return psa_aead_setup(operation, 1, key, alg);\n}\n\n/* Set the key for a multipart authenticated decryption operation. */\npsa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation,\n                                    mbedtls_svc_key_id_t key,\n                                    psa_algorithm_t alg)\n{\n    return psa_aead_setup(operation, 0, key, alg);\n}\n\nstatic psa_status_t psa_aead_set_nonce_internal(psa_aead_operation_t *operation,\n                                                const uint8_t *nonce,\n                                                size_t nonce_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    if (operation->id == 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (operation->nonce_set) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    status = psa_aead_check_nonce_length(operation->alg, nonce_length);\n    if (status != PSA_SUCCESS) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    status = psa_driver_wrapper_aead_set_nonce(operation, nonce,\n                                               nonce_length);\n\nexit:\n    if (status == PSA_SUCCESS) {\n        operation->nonce_set = 1;\n    } else {\n        psa_aead_abort(operation);\n    }\n\n    return status;\n}\n\n/* Generate a random nonce / IV for multipart AEAD operation */\npsa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation,\n                                     uint8_t *nonce_external,\n                                     size_t nonce_size,\n                                     size_t *nonce_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    uint8_t local_nonce[PSA_AEAD_NONCE_MAX_SIZE];\n    size_t required_nonce_size = 0;\n\n    LOCAL_OUTPUT_DECLARE(nonce_external, nonce);\n    LOCAL_OUTPUT_ALLOC(nonce_external, nonce_size, nonce);\n\n    *nonce_length = 0;\n\n    if (operation->id == 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (operation->nonce_set || !operation->is_encrypt) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    /* For CCM, this size may not be correct according to the PSA\n     * specification. The PSA Crypto 1.0.1 specification states:\n     *\n     * CCM encodes the plaintext length pLen in L octets, with L the smallest\n     * integer >= 2 where pLen < 2^(8L). The nonce length is then 15 - L bytes.\n     *\n     * However this restriction that L has to be the smallest integer is not\n     * applied in practice, and it is not implementable here since the\n     * plaintext length may or may not be known at this time. */\n    required_nonce_size = PSA_AEAD_NONCE_LENGTH(operation->key_type,\n                                                operation->alg);\n    if (nonce_size < required_nonce_size) {\n        status = PSA_ERROR_BUFFER_TOO_SMALL;\n        goto exit;\n    }\n\n    status = psa_generate_random_internal(local_nonce, required_nonce_size);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_aead_set_nonce_internal(operation, local_nonce,\n                                         required_nonce_size);\n\nexit:\n    if (status == PSA_SUCCESS) {\n        memcpy(nonce, local_nonce, required_nonce_size);\n        *nonce_length = required_nonce_size;\n    } else {\n        psa_aead_abort(operation);\n    }\n\n    LOCAL_OUTPUT_FREE(nonce_external, nonce);\n\n    return status;\n}\n\n/* Set the nonce for a multipart authenticated encryption or decryption\n   operation.*/\npsa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation,\n                                const uint8_t *nonce_external,\n                                size_t nonce_length)\n{\n    psa_status_t status;\n\n    LOCAL_INPUT_DECLARE(nonce_external, nonce);\n    LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce);\n\n    status = psa_aead_set_nonce_internal(operation, nonce, nonce_length);\n\n/* Exit label is only needed for buffer copying, prevent unused warnings. */\n#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\nexit:\n#endif\n\n    LOCAL_INPUT_FREE(nonce_external, nonce);\n\n    return status;\n}\n\n/* Declare the lengths of the message and additional data for multipart AEAD. */\npsa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation,\n                                  size_t ad_length,\n                                  size_t plaintext_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    if (operation->id == 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (operation->lengths_set || operation->ad_started ||\n        operation->body_started) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    switch (operation->alg) {\n#if defined(PSA_WANT_ALG_GCM)\n        case PSA_ALG_GCM:\n            /* Lengths can only be too large for GCM if size_t is bigger than 32\n             * bits. Without the guard this code will generate warnings on 32bit\n             * builds. */\n#if SIZE_MAX > UINT32_MAX\n            if (((uint64_t) ad_length) >> 61 != 0 ||\n                ((uint64_t) plaintext_length) > 0xFFFFFFFE0ull) {\n                status = PSA_ERROR_INVALID_ARGUMENT;\n                goto exit;\n            }\n#endif\n            break;\n#endif /* PSA_WANT_ALG_GCM */\n#if defined(PSA_WANT_ALG_CCM)\n        case PSA_ALG_CCM:\n            if (ad_length > 0xFF00) {\n                status = PSA_ERROR_INVALID_ARGUMENT;\n                goto exit;\n            }\n            break;\n#endif /* PSA_WANT_ALG_CCM */\n#if defined(PSA_WANT_ALG_CHACHA20_POLY1305)\n        case PSA_ALG_CHACHA20_POLY1305:\n            /* No length restrictions for ChaChaPoly. */\n            break;\n#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */\n        default:\n            break;\n    }\n\n    status = psa_driver_wrapper_aead_set_lengths(operation, ad_length,\n                                                 plaintext_length);\n\nexit:\n    if (status == PSA_SUCCESS) {\n        operation->ad_remaining = ad_length;\n        operation->body_remaining = plaintext_length;\n        operation->lengths_set = 1;\n    } else {\n        psa_aead_abort(operation);\n    }\n\n    return status;\n}\n\n/* Pass additional data to an active multipart AEAD operation. */\npsa_status_t psa_aead_update_ad(psa_aead_operation_t *operation,\n                                const uint8_t *input_external,\n                                size_t input_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    LOCAL_INPUT_DECLARE(input_external, input);\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n\n    if (operation->id == 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (!operation->nonce_set || operation->body_started) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    /* No input to add (zero length), nothing to do. */\n    if (input_length == 0) {\n        status = PSA_SUCCESS;\n        goto exit;\n    }\n\n    if (operation->lengths_set) {\n        if (operation->ad_remaining < input_length) {\n            status = PSA_ERROR_INVALID_ARGUMENT;\n            goto exit;\n        }\n\n        operation->ad_remaining -= input_length;\n    }\n#if defined(PSA_WANT_ALG_CCM)\n    else if (operation->alg == PSA_ALG_CCM) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n#endif /* PSA_WANT_ALG_CCM */\n\n    status = psa_driver_wrapper_aead_update_ad(operation, input,\n                                               input_length);\n\nexit:\n    if (status == PSA_SUCCESS) {\n        operation->ad_started = 1;\n    } else {\n        psa_aead_abort(operation);\n    }\n\n    LOCAL_INPUT_FREE(input_external, input);\n\n    return status;\n}\n\n/* Encrypt or decrypt a message fragment in an active multipart AEAD\n   operation.*/\npsa_status_t psa_aead_update(psa_aead_operation_t *operation,\n                             const uint8_t *input_external,\n                             size_t input_length,\n                             uint8_t *output_external,\n                             size_t output_size,\n                             size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n\n    LOCAL_INPUT_DECLARE(input_external, input);\n    LOCAL_OUTPUT_DECLARE(output_external, output);\n\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);\n\n    *output_length = 0;\n\n    if (operation->id == 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (!operation->nonce_set) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (operation->lengths_set) {\n        /* Additional data length was supplied, but not all the additional\n           data was supplied.*/\n        if (operation->ad_remaining != 0) {\n            status = PSA_ERROR_INVALID_ARGUMENT;\n            goto exit;\n        }\n\n        /* Too much data provided. */\n        if (operation->body_remaining < input_length) {\n            status = PSA_ERROR_INVALID_ARGUMENT;\n            goto exit;\n        }\n\n        operation->body_remaining -= input_length;\n    }\n#if defined(PSA_WANT_ALG_CCM)\n    else if (operation->alg == PSA_ALG_CCM) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n#endif /* PSA_WANT_ALG_CCM */\n\n    status = psa_driver_wrapper_aead_update(operation, input, input_length,\n                                            output, output_size,\n                                            output_length);\n\nexit:\n    if (status == PSA_SUCCESS) {\n        operation->body_started = 1;\n    } else {\n        psa_aead_abort(operation);\n    }\n\n    LOCAL_INPUT_FREE(input_external, input);\n    LOCAL_OUTPUT_FREE(output_external, output);\n\n    return status;\n}\n\nstatic psa_status_t psa_aead_final_checks(const psa_aead_operation_t *operation)\n{\n    if (operation->id == 0 || !operation->nonce_set) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    if (operation->lengths_set && (operation->ad_remaining != 0 ||\n                                   operation->body_remaining != 0)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    return PSA_SUCCESS;\n}\n\n/* Finish encrypting a message in a multipart AEAD operation. */\npsa_status_t psa_aead_finish(psa_aead_operation_t *operation,\n                             uint8_t *ciphertext_external,\n                             size_t ciphertext_size,\n                             size_t *ciphertext_length,\n                             uint8_t *tag_external,\n                             size_t tag_size,\n                             size_t *tag_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext);\n    LOCAL_OUTPUT_DECLARE(tag_external, tag);\n\n    LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext);\n    LOCAL_OUTPUT_ALLOC(tag_external, tag_size, tag);\n\n    *ciphertext_length = 0;\n    *tag_length = tag_size;\n\n    status = psa_aead_final_checks(operation);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (!operation->is_encrypt) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    status = psa_driver_wrapper_aead_finish(operation, ciphertext,\n                                            ciphertext_size,\n                                            ciphertext_length,\n                                            tag, tag_size, tag_length);\n\nexit:\n\n\n    /* In case the operation fails and the user fails to check for failure or\n     * the zero tag size, make sure the tag is set to something implausible.\n     * Even if the operation succeeds, make sure we clear the rest of the\n     * buffer to prevent potential leakage of anything previously placed in\n     * the same buffer.*/\n    psa_wipe_tag_output_buffer(tag, status, tag_size, *tag_length);\n\n    psa_aead_abort(operation);\n\n    LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext);\n    LOCAL_OUTPUT_FREE(tag_external, tag);\n\n    return status;\n}\n\n/* Finish authenticating and decrypting a message in a multipart AEAD\n   operation.*/\npsa_status_t psa_aead_verify(psa_aead_operation_t *operation,\n                             uint8_t *plaintext_external,\n                             size_t plaintext_size,\n                             size_t *plaintext_length,\n                             const uint8_t *tag_external,\n                             size_t tag_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext);\n    LOCAL_INPUT_DECLARE(tag_external, tag);\n\n    LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext);\n    LOCAL_INPUT_ALLOC(tag_external, tag_length, tag);\n\n    *plaintext_length = 0;\n\n    status = psa_aead_final_checks(operation);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (operation->is_encrypt) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    status = psa_driver_wrapper_aead_verify(operation, plaintext,\n                                            plaintext_size,\n                                            plaintext_length,\n                                            tag, tag_length);\n\nexit:\n    psa_aead_abort(operation);\n\n    LOCAL_OUTPUT_FREE(plaintext_external, plaintext);\n    LOCAL_INPUT_FREE(tag_external, tag);\n\n    return status;\n}\n\n/* Abort an AEAD operation. */\npsa_status_t psa_aead_abort(psa_aead_operation_t *operation)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    if (operation->id == 0) {\n        /* The object has (apparently) been initialized but it is not (yet)\n         * in use. It's ok to call abort on such an object, and there's\n         * nothing to do. */\n        return PSA_SUCCESS;\n    }\n\n    status = psa_driver_wrapper_aead_abort(operation);\n\n    memset(operation, 0, sizeof(*operation));\n\n    return status;\n}\n\n/****************************************************************/\n/* Key derivation: output generation */\n/****************************************************************/\n\n#if defined(BUILTIN_ALG_ANY_HKDF) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) || \\\n    defined(PSA_HAVE_SOFT_PBKDF2)\n#define AT_LEAST_ONE_BUILTIN_KDF\n#endif /* At least one builtin KDF */\n\n#if defined(BUILTIN_ALG_ANY_HKDF) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)\n\n/** Internal helper to set up an HMAC operation with a key passed directly.\n *\n * \\param[in,out] operation     A MAC operation object. It does not need to\n *                              be initialized.\n * \\param hash_alg              The hash algorithm used for HMAC.\n * \\param hmac_key              The HMAC key.\n * \\param hmac_key_length       Length of \\p hmac_key in bytes.\n *\n * \\return A PSA status code.\n */\nstatic psa_status_t psa_key_derivation_start_hmac(\n    psa_mac_operation_t *operation,\n    psa_algorithm_t hash_alg,\n    const uint8_t *hmac_key,\n    size_t hmac_key_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);\n    psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(hmac_key_length));\n    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);\n\n    /* Make sure the whole the operation is zeroed.\n     * It isn't enough to require the caller to initialize operation to\n     * PSA_MAC_OPERATION_INIT, since one field is a union and initializing\n     * a union does not necessarily initialize all of its members.\n     * psa_mac_setup() would handle PSA_MAC_OPERATION_INIT, but here we\n     * bypass it and call lower-level functions directly. */\n    memset(operation, 0, sizeof(*operation));\n\n    operation->is_sign = 1;\n    operation->mac_size = PSA_HASH_LENGTH(hash_alg);\n\n    status = psa_driver_wrapper_mac_sign_setup(operation,\n                                               &attributes,\n                                               hmac_key, hmac_key_length,\n                                               PSA_ALG_HMAC(hash_alg));\n\n    psa_reset_key_attributes(&attributes);\n    return status;\n}\n#endif /* KDF algorithms reliant on HMAC */\n\n#define HKDF_STATE_INIT 0 /* no input yet */\n#define HKDF_STATE_STARTED 1 /* got salt */\n#define HKDF_STATE_KEYED 2 /* got key */\n#define HKDF_STATE_OUTPUT 3 /* output started */\n\nstatic psa_algorithm_t psa_key_derivation_get_kdf_alg(\n    const psa_key_derivation_operation_t *operation)\n{\n    if (PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) {\n        return PSA_ALG_KEY_AGREEMENT_GET_KDF(operation->alg);\n    } else {\n        return operation->alg;\n    }\n}\n\npsa_status_t psa_key_derivation_abort(psa_key_derivation_operation_t *operation)\n{\n    psa_status_t status = PSA_SUCCESS;\n    psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation);\n    if (kdf_alg == 0) {\n        /* The object has (apparently) been initialized but it is not\n         * in use. It's ok to call abort on such an object, and there's\n         * nothing to do. */\n    } else\n#if defined(BUILTIN_ALG_ANY_HKDF)\n    if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) {\n        mbedtls_free(operation->ctx.hkdf.info);\n        status = psa_mac_abort(&operation->ctx.hkdf.hmac);\n    } else\n#endif /* BUILTIN_ALG_ANY_HKDF */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)\n    if (PSA_ALG_IS_TLS12_PRF(kdf_alg) ||\n        /* TLS-1.2 PSK-to-MS KDF uses the same core as TLS-1.2 PRF */\n        PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {\n        if (operation->ctx.tls12_prf.secret != NULL) {\n            mbedtls_zeroize_and_free(operation->ctx.tls12_prf.secret,\n                                     operation->ctx.tls12_prf.secret_length);\n        }\n\n        if (operation->ctx.tls12_prf.seed != NULL) {\n            mbedtls_zeroize_and_free(operation->ctx.tls12_prf.seed,\n                                     operation->ctx.tls12_prf.seed_length);\n        }\n\n        if (operation->ctx.tls12_prf.label != NULL) {\n            mbedtls_zeroize_and_free(operation->ctx.tls12_prf.label,\n                                     operation->ctx.tls12_prf.label_length);\n        }\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)\n        if (operation->ctx.tls12_prf.other_secret != NULL) {\n            mbedtls_zeroize_and_free(operation->ctx.tls12_prf.other_secret,\n                                     operation->ctx.tls12_prf.other_secret_length);\n        }\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */\n        status = PSA_SUCCESS;\n\n        /* We leave the fields Ai and output_block to be erased safely by the\n         * mbedtls_platform_zeroize() in the end of this function. */\n    } else\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)\n    if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {\n        mbedtls_platform_zeroize(operation->ctx.tls12_ecjpake_to_pms.data,\n                                 sizeof(operation->ctx.tls12_ecjpake_to_pms.data));\n    } else\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) */\n#if defined(PSA_HAVE_SOFT_PBKDF2)\n    if (PSA_ALG_IS_PBKDF2(kdf_alg)) {\n        if (operation->ctx.pbkdf2.salt != NULL) {\n            mbedtls_zeroize_and_free(operation->ctx.pbkdf2.salt,\n                                     operation->ctx.pbkdf2.salt_length);\n        }\n\n        status = PSA_SUCCESS;\n    } else\n#endif /* defined(PSA_HAVE_SOFT_PBKDF2) */\n    {\n        status = PSA_ERROR_BAD_STATE;\n    }\n    mbedtls_platform_zeroize(operation, sizeof(*operation));\n    return status;\n}\n\npsa_status_t psa_key_derivation_get_capacity(const psa_key_derivation_operation_t *operation,\n                                             size_t *capacity)\n{\n    if (operation->alg == 0) {\n        /* This is a blank key derivation operation. */\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    *capacity = operation->capacity;\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_key_derivation_set_capacity(psa_key_derivation_operation_t *operation,\n                                             size_t capacity)\n{\n    if (operation->alg == 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n    if (capacity > operation->capacity) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n    operation->capacity = capacity;\n    return PSA_SUCCESS;\n}\n\n#if defined(BUILTIN_ALG_ANY_HKDF)\n/* Read some bytes from an HKDF-based operation. */\nstatic psa_status_t psa_key_derivation_hkdf_read(psa_hkdf_key_derivation_t *hkdf,\n                                                 psa_algorithm_t kdf_alg,\n                                                 uint8_t *output,\n                                                 size_t output_length)\n{\n    psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg);\n    uint8_t hash_length = PSA_HASH_LENGTH(hash_alg);\n    size_t hmac_output_length;\n    psa_status_t status;\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)\n    const uint8_t last_block = PSA_ALG_IS_HKDF_EXTRACT(kdf_alg) ? 0 : 0xff;\n#else\n    const uint8_t last_block = 0xff;\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */\n\n    if (hkdf->state < HKDF_STATE_KEYED ||\n        (!hkdf->info_set\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)\n         && !PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */\n        )) {\n        return PSA_ERROR_BAD_STATE;\n    }\n    hkdf->state = HKDF_STATE_OUTPUT;\n\n    while (output_length != 0) {\n        /* Copy what remains of the current block */\n        uint8_t n = hash_length - hkdf->offset_in_block;\n        if (n > output_length) {\n            n = (uint8_t) output_length;\n        }\n        memcpy(output, hkdf->output_block + hkdf->offset_in_block, n);\n        output += n;\n        output_length -= n;\n        hkdf->offset_in_block += n;\n        if (output_length == 0) {\n            break;\n        }\n        /* We can't be wanting more output after the last block, otherwise\n         * the capacity check in psa_key_derivation_output_bytes() would have\n         * prevented this call. It could happen only if the operation\n         * object was corrupted or if this function is called directly\n         * inside the library. */\n        if (hkdf->block_number == last_block) {\n            return PSA_ERROR_BAD_STATE;\n        }\n\n        /* We need a new block */\n        ++hkdf->block_number;\n        hkdf->offset_in_block = 0;\n\n        status = psa_key_derivation_start_hmac(&hkdf->hmac,\n                                               hash_alg,\n                                               hkdf->prk,\n                                               hash_length);\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n\n        if (hkdf->block_number != 1) {\n            status = psa_mac_update(&hkdf->hmac,\n                                    hkdf->output_block,\n                                    hash_length);\n            if (status != PSA_SUCCESS) {\n                return status;\n            }\n        }\n        status = psa_mac_update(&hkdf->hmac,\n                                hkdf->info,\n                                hkdf->info_length);\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n        status = psa_mac_update(&hkdf->hmac,\n                                &hkdf->block_number, 1);\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n        status = psa_mac_sign_finish(&hkdf->hmac,\n                                     hkdf->output_block,\n                                     sizeof(hkdf->output_block),\n                                     &hmac_output_length);\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n    }\n\n    return PSA_SUCCESS;\n}\n#endif /* BUILTIN_ALG_ANY_HKDF */\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)\nstatic psa_status_t psa_key_derivation_tls12_prf_generate_next_block(\n    psa_tls12_prf_key_derivation_t *tls12_prf,\n    psa_algorithm_t alg)\n{\n    psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(alg);\n    uint8_t hash_length = PSA_HASH_LENGTH(hash_alg);\n    psa_mac_operation_t hmac;\n    size_t hmac_output_length;\n    psa_status_t status, cleanup_status;\n\n    /* We can't be wanting more output after block 0xff, otherwise\n     * the capacity check in psa_key_derivation_output_bytes() would have\n     * prevented this call. It could happen only if the operation\n     * object was corrupted or if this function is called directly\n     * inside the library. */\n    if (tls12_prf->block_number == 0xff) {\n        return PSA_ERROR_CORRUPTION_DETECTED;\n    }\n\n    /* We need a new block */\n    ++tls12_prf->block_number;\n    tls12_prf->left_in_block = hash_length;\n\n    /* Recall the definition of the TLS-1.2-PRF from RFC 5246:\n     *\n     * PRF(secret, label, seed) = P_<hash>(secret, label + seed)\n     *\n     * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +\n     *                        HMAC_hash(secret, A(2) + seed) +\n     *                        HMAC_hash(secret, A(3) + seed) + ...\n     *\n     * A(0) = seed\n     * A(i) = HMAC_hash(secret, A(i-1))\n     *\n     * The `psa_tls12_prf_key_derivation` structure saves the block\n     * `HMAC_hash(secret, A(i) + seed)` from which the output\n     * is currently extracted as `output_block` and where i is\n     * `block_number`.\n     */\n\n    status = psa_key_derivation_start_hmac(&hmac,\n                                           hash_alg,\n                                           tls12_prf->secret,\n                                           tls12_prf->secret_length);\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    /* Calculate A(i) where i = tls12_prf->block_number. */\n    if (tls12_prf->block_number == 1) {\n        /* A(1) = HMAC_hash(secret, A(0)), where A(0) = seed. (The RFC overloads\n         * the variable seed and in this instance means it in the context of the\n         * P_hash function, where seed = label + seed.) */\n        status = psa_mac_update(&hmac,\n                                tls12_prf->label,\n                                tls12_prf->label_length);\n        if (status != PSA_SUCCESS) {\n            goto cleanup;\n        }\n        status = psa_mac_update(&hmac,\n                                tls12_prf->seed,\n                                tls12_prf->seed_length);\n        if (status != PSA_SUCCESS) {\n            goto cleanup;\n        }\n    } else {\n        /* A(i) = HMAC_hash(secret, A(i-1)) */\n        status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length);\n        if (status != PSA_SUCCESS) {\n            goto cleanup;\n        }\n    }\n\n    status = psa_mac_sign_finish(&hmac,\n                                 tls12_prf->Ai, hash_length,\n                                 &hmac_output_length);\n    if (hmac_output_length != hash_length) {\n        status = PSA_ERROR_CORRUPTION_DETECTED;\n    }\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    /* Calculate HMAC_hash(secret, A(i) + label + seed). */\n    status = psa_key_derivation_start_hmac(&hmac,\n                                           hash_alg,\n                                           tls12_prf->secret,\n                                           tls12_prf->secret_length);\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n    status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length);\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n    status = psa_mac_update(&hmac, tls12_prf->label, tls12_prf->label_length);\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n    status = psa_mac_update(&hmac, tls12_prf->seed, tls12_prf->seed_length);\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n    status = psa_mac_sign_finish(&hmac,\n                                 tls12_prf->output_block, hash_length,\n                                 &hmac_output_length);\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n\ncleanup:\n    cleanup_status = psa_mac_abort(&hmac);\n    if (status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS) {\n        status = cleanup_status;\n    }\n\n    return status;\n}\n\nstatic psa_status_t psa_key_derivation_tls12_prf_read(\n    psa_tls12_prf_key_derivation_t *tls12_prf,\n    psa_algorithm_t alg,\n    uint8_t *output,\n    size_t output_length)\n{\n    psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH(alg);\n    uint8_t hash_length = PSA_HASH_LENGTH(hash_alg);\n    psa_status_t status;\n    uint8_t offset, length;\n\n    switch (tls12_prf->state) {\n        case PSA_TLS12_PRF_STATE_LABEL_SET:\n            tls12_prf->state = PSA_TLS12_PRF_STATE_OUTPUT;\n            break;\n        case PSA_TLS12_PRF_STATE_OUTPUT:\n            break;\n        default:\n            return PSA_ERROR_BAD_STATE;\n    }\n\n    while (output_length != 0) {\n        /* Check if we have fully processed the current block. */\n        if (tls12_prf->left_in_block == 0) {\n            status = psa_key_derivation_tls12_prf_generate_next_block(tls12_prf,\n                                                                      alg);\n            if (status != PSA_SUCCESS) {\n                return status;\n            }\n\n            continue;\n        }\n\n        if (tls12_prf->left_in_block > output_length) {\n            length = (uint8_t) output_length;\n        } else {\n            length = tls12_prf->left_in_block;\n        }\n\n        offset = hash_length - tls12_prf->left_in_block;\n        memcpy(output, tls12_prf->output_block + offset, length);\n        output += length;\n        output_length -= length;\n        tls12_prf->left_in_block -= length;\n    }\n\n    return PSA_SUCCESS;\n}\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF ||\n        * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)\nstatic psa_status_t psa_key_derivation_tls12_ecjpake_to_pms_read(\n    psa_tls12_ecjpake_to_pms_t *ecjpake,\n    uint8_t *output,\n    size_t output_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t output_size = 0;\n\n    if (output_length != 32) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    status = psa_hash_compute(PSA_ALG_SHA_256, ecjpake->data,\n                              PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE, output, output_length,\n                              &output_size);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    if (output_size != output_length) {\n        return PSA_ERROR_GENERIC_ERROR;\n    }\n\n    return PSA_SUCCESS;\n}\n#endif\n\n#if defined(PSA_HAVE_SOFT_PBKDF2)\nstatic psa_status_t psa_key_derivation_pbkdf2_generate_block(\n    psa_pbkdf2_key_derivation_t *pbkdf2,\n    psa_algorithm_t prf_alg,\n    uint8_t prf_output_length,\n    psa_key_attributes_t *attributes)\n{\n    psa_status_t status;\n    psa_mac_operation_t mac_operation;\n    /* Make sure the whole the operation is zeroed.\n     * PSA_MAC_OPERATION_INIT does not necessarily do it fully,\n     * since one field is a union and initializing a union does not\n     * necessarily initialize all of its members.\n     * psa_mac_setup() would do it, but here we bypass it and call\n     * lower-level functions directly. */\n    memset(&mac_operation, 0, sizeof(mac_operation));\n    size_t mac_output_length;\n    uint8_t U_i[PSA_MAC_MAX_SIZE];\n    uint8_t *U_accumulator = pbkdf2->output_block;\n    uint64_t i;\n    uint8_t block_counter[4];\n\n    mac_operation.is_sign = 1;\n    mac_operation.mac_size = prf_output_length;\n    MBEDTLS_PUT_UINT32_BE(pbkdf2->block_number, block_counter, 0);\n\n    status = psa_driver_wrapper_mac_sign_setup(&mac_operation,\n                                               attributes,\n                                               pbkdf2->password,\n                                               pbkdf2->password_length,\n                                               prf_alg);\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n    status = psa_mac_update(&mac_operation, pbkdf2->salt, pbkdf2->salt_length);\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n    status = psa_mac_update(&mac_operation, block_counter, sizeof(block_counter));\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n    status = psa_mac_sign_finish(&mac_operation, U_i, sizeof(U_i),\n                                 &mac_output_length);\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    if (mac_output_length != prf_output_length) {\n        status = PSA_ERROR_CORRUPTION_DETECTED;\n        goto cleanup;\n    }\n\n    memcpy(U_accumulator, U_i, prf_output_length);\n\n    for (i = 1; i < pbkdf2->input_cost; i++) {\n        /* We are passing prf_output_length as mac_size because the driver\n         * function directly sets mac_output_length as mac_size upon success.\n         * See https://github.com/Mbed-TLS/mbedtls/issues/7801 */\n        status = psa_driver_wrapper_mac_compute(attributes,\n                                                pbkdf2->password,\n                                                pbkdf2->password_length,\n                                                prf_alg, U_i, prf_output_length,\n                                                U_i, prf_output_length,\n                                                &mac_output_length);\n        if (status != PSA_SUCCESS) {\n            goto cleanup;\n        }\n\n        mbedtls_xor(U_accumulator, U_accumulator, U_i, prf_output_length);\n    }\n\ncleanup:\n    /* Zeroise buffers to clear sensitive data from memory. */\n    mbedtls_platform_zeroize(U_i, PSA_MAC_MAX_SIZE);\n    return status;\n}\n\nstatic psa_status_t psa_key_derivation_pbkdf2_read(\n    psa_pbkdf2_key_derivation_t *pbkdf2,\n    psa_algorithm_t kdf_alg,\n    uint8_t *output,\n    size_t output_length)\n{\n    psa_status_t status;\n    psa_algorithm_t prf_alg;\n    uint8_t prf_output_length;\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(pbkdf2->password_length));\n    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);\n\n    if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {\n        prf_alg = PSA_ALG_HMAC(PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg));\n        prf_output_length = PSA_HASH_LENGTH(prf_alg);\n        psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);\n    } else if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) {\n        prf_alg = PSA_ALG_CMAC;\n        prf_output_length = PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC);\n        psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);\n    } else {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    switch (pbkdf2->state) {\n        case PSA_PBKDF2_STATE_PASSWORD_SET:\n            /* Initially we need a new block so bytes_used is equal to block size*/\n            pbkdf2->bytes_used = prf_output_length;\n            pbkdf2->state = PSA_PBKDF2_STATE_OUTPUT;\n            break;\n        case PSA_PBKDF2_STATE_OUTPUT:\n            break;\n        default:\n            return PSA_ERROR_BAD_STATE;\n    }\n\n    while (output_length != 0) {\n        uint8_t n = prf_output_length - pbkdf2->bytes_used;\n        if (n > output_length) {\n            n = (uint8_t) output_length;\n        }\n        memcpy(output, pbkdf2->output_block + pbkdf2->bytes_used, n);\n        output += n;\n        output_length -= n;\n        pbkdf2->bytes_used += n;\n\n        if (output_length == 0) {\n            break;\n        }\n\n        /* We need a new block */\n        pbkdf2->bytes_used = 0;\n        pbkdf2->block_number++;\n\n        status = psa_key_derivation_pbkdf2_generate_block(pbkdf2, prf_alg,\n                                                          prf_output_length,\n                                                          &attributes);\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n    }\n\n    return PSA_SUCCESS;\n}\n#endif /* PSA_HAVE_SOFT_PBKDF2 */\n\npsa_status_t psa_key_derivation_output_bytes(\n    psa_key_derivation_operation_t *operation,\n    uint8_t *output_external,\n    size_t output_length)\n{\n    psa_status_t status;\n    LOCAL_OUTPUT_DECLARE(output_external, output);\n\n    psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation);\n\n    if (operation->alg == 0) {\n        /* This is a blank operation. */\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    if (output_length == 0 && operation->capacity == 0) {\n        /* Edge case: this is a finished operation, and 0 bytes\n         * were requested. The right error in this case could\n         * be either INSUFFICIENT_CAPACITY or BAD_STATE. Return\n         * INSUFFICIENT_CAPACITY, which is right for a finished\n         * operation, for consistency with the case when\n         * output_length > 0. */\n        return PSA_ERROR_INSUFFICIENT_DATA;\n    }\n\n    LOCAL_OUTPUT_ALLOC(output_external, output_length, output);\n    if (output_length > operation->capacity) {\n        operation->capacity = 0;\n        /* Go through the error path to wipe all confidential data now\n         * that the operation object is useless. */\n        status = PSA_ERROR_INSUFFICIENT_DATA;\n        goto exit;\n    }\n\n    operation->capacity -= output_length;\n\n#if defined(BUILTIN_ALG_ANY_HKDF)\n    if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) {\n        status = psa_key_derivation_hkdf_read(&operation->ctx.hkdf, kdf_alg,\n                                              output, output_length);\n    } else\n#endif /* BUILTIN_ALG_ANY_HKDF */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)\n    if (PSA_ALG_IS_TLS12_PRF(kdf_alg) ||\n        PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {\n        status = psa_key_derivation_tls12_prf_read(&operation->ctx.tls12_prf,\n                                                   kdf_alg, output,\n                                                   output_length);\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF ||\n        * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)\n    if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {\n        status = psa_key_derivation_tls12_ecjpake_to_pms_read(\n            &operation->ctx.tls12_ecjpake_to_pms, output, output_length);\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */\n#if defined(PSA_HAVE_SOFT_PBKDF2)\n    if (PSA_ALG_IS_PBKDF2(kdf_alg)) {\n        status = psa_key_derivation_pbkdf2_read(&operation->ctx.pbkdf2, kdf_alg,\n                                                output, output_length);\n    } else\n#endif /* PSA_HAVE_SOFT_PBKDF2 */\n\n    {\n        (void) kdf_alg;\n        status = PSA_ERROR_BAD_STATE;\n        LOCAL_OUTPUT_FREE(output_external, output);\n\n        return status;\n    }\n\nexit:\n    if (status != PSA_SUCCESS) {\n        /* Preserve the algorithm upon errors, but clear all sensitive state.\n         * This allows us to differentiate between exhausted operations and\n         * blank operations, so we can return PSA_ERROR_BAD_STATE on blank\n         * operations. */\n        psa_algorithm_t alg = operation->alg;\n        psa_key_derivation_abort(operation);\n        operation->alg = alg;\n        if (output != NULL) {\n            memset(output, '!', output_length);\n        }\n    }\n\n    LOCAL_OUTPUT_FREE(output_external, output);\n    return status;\n}\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)\nstatic void psa_des_set_key_parity(uint8_t *data, size_t data_size)\n{\n    if (data_size >= 8) {\n        mbedtls_des_key_set_parity(data);\n    }\n    if (data_size >= 16) {\n        mbedtls_des_key_set_parity(data + 8);\n    }\n    if (data_size >= 24) {\n        mbedtls_des_key_set_parity(data + 16);\n    }\n}\n#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */\n\n/*\n * ECC keys on a Weierstrass elliptic curve require the generation\n * of a private key which is an integer\n * in the range [1, N - 1], where N is the boundary of the private key domain:\n * N is the prime p for Diffie-Hellman, or the order of the\n * curve’s base point for ECC.\n *\n * Let m be the bit size of N, such that 2^m > N >= 2^(m-1).\n * This function generates the private key using the following process:\n *\n * 1. Draw a byte string of length ceiling(m/8) bytes.\n * 2. If m is not a multiple of 8, set the most significant\n *    (8 * ceiling(m/8) - m) bits of the first byte in the string to zero.\n * 3. Convert the string to integer k by decoding it as a big-endian byte string.\n * 4. If k > N - 2, discard the result and return to step 1.\n * 5. Output k + 1 as the private key.\n *\n * This method allows compliance to NIST standards, specifically the methods titled\n * Key-Pair Generation by Testing Candidates in the following publications:\n * - NIST Special Publication 800-56A: Recommendation for Pair-Wise Key-Establishment\n *   Schemes Using Discrete Logarithm Cryptography [SP800-56A] §5.6.1.1.4 for\n *   Diffie-Hellman keys.\n *\n * - [SP800-56A] §5.6.1.2.2 or FIPS Publication 186-4: Digital Signature\n *   Standard (DSS) [FIPS186-4] §B.4.2 for elliptic curve keys.\n *\n * Note: Function allocates memory for *data buffer, so given *data should be\n *       always NULL.\n */\n#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE)\nstatic psa_status_t psa_generate_derived_ecc_key_weierstrass_helper(\n    psa_key_slot_t *slot,\n    size_t bits,\n    psa_key_derivation_operation_t *operation,\n    uint8_t **data\n    )\n{\n    unsigned key_out_of_range = 1;\n    mbedtls_mpi k;\n    mbedtls_mpi diff_N_2;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t m;\n    size_t m_bytes = 0;\n\n    mbedtls_mpi_init(&k);\n    mbedtls_mpi_init(&diff_N_2);\n\n    psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(\n        slot->attr.type);\n    mbedtls_ecp_group_id grp_id =\n        mbedtls_ecc_group_from_psa(curve, bits);\n\n    if (grp_id == MBEDTLS_ECP_DP_NONE) {\n        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;\n        goto cleanup;\n    }\n\n    mbedtls_ecp_group ecp_group;\n    mbedtls_ecp_group_init(&ecp_group);\n\n    MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ecp_group, grp_id));\n\n    /* N is the boundary of the private key domain (ecp_group.N). */\n    /* Let m be the bit size of N. */\n    m = ecp_group.nbits;\n\n    m_bytes = PSA_BITS_TO_BYTES(m);\n\n    /* Calculate N - 2 - it will be needed later. */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&diff_N_2, &ecp_group.N, 2));\n\n    /* Note: This function is always called with *data == NULL and it\n     * allocates memory for the data buffer. */\n    *data = mbedtls_calloc(1, m_bytes);\n    if (*data == NULL) {\n        ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED;\n        goto cleanup;\n    }\n\n    while (key_out_of_range) {\n        /* 1. Draw a byte string of length ceiling(m/8) bytes. */\n        if ((status = psa_key_derivation_output_bytes(operation, *data, m_bytes)) != 0) {\n            goto cleanup;\n        }\n\n        /* 2. If m is not a multiple of 8 */\n        if (m % 8 != 0) {\n            /* Set the most significant\n             * (8 * ceiling(m/8) - m) bits of the first byte in\n             * the string to zero.\n             */\n            uint8_t clear_bit_mask = (1 << (m % 8)) - 1;\n            (*data)[0] &= clear_bit_mask;\n        }\n\n        /* 3. Convert the string to integer k by decoding it as a\n         *    big-endian byte string.\n         */\n        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&k, *data, m_bytes));\n\n        /* 4. If k > N - 2, discard the result and return to step 1.\n         *    Result of comparison is returned. When it indicates error\n         *    then this function is called again.\n         */\n        MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(&diff_N_2, &k, &key_out_of_range));\n    }\n\n    /* 5. Output k + 1 as the private key. */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&k, &k, 1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&k, *data, m_bytes));\ncleanup:\n    if (ret != 0) {\n        status = mbedtls_to_psa_error(ret);\n    }\n    if (status != PSA_SUCCESS) {\n        mbedtls_zeroize_and_free(*data, m_bytes);\n        *data = NULL;\n    }\n    mbedtls_mpi_free(&k);\n    mbedtls_mpi_free(&diff_N_2);\n    return status;\n}\n\n/* ECC keys on a Montgomery elliptic curve draws a byte string whose length\n * is determined by the curve, and sets the mandatory bits accordingly. That is:\n *\n * - Curve25519 (PSA_ECC_FAMILY_MONTGOMERY, 255 bits):\n *   draw a 32-byte string and process it as specified in\n *   Elliptic Curves for Security [RFC7748] §5.\n *\n * - Curve448 (PSA_ECC_FAMILY_MONTGOMERY, 448 bits):\n *   draw a 56-byte string and process it as specified in [RFC7748] §5.\n *\n * Note: Function allocates memory for *data buffer, so given *data should be\n *       always NULL.\n */\n\nstatic psa_status_t psa_generate_derived_ecc_key_montgomery_helper(\n    size_t bits,\n    psa_key_derivation_operation_t *operation,\n    uint8_t **data\n    )\n{\n    size_t output_length;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    switch (bits) {\n        case 255:\n            output_length = 32;\n            break;\n        case 448:\n            output_length = 56;\n            break;\n        default:\n            return PSA_ERROR_INVALID_ARGUMENT;\n            break;\n    }\n\n    *data = mbedtls_calloc(1, output_length);\n\n    if (*data == NULL) {\n        return PSA_ERROR_INSUFFICIENT_MEMORY;\n    }\n\n    status = psa_key_derivation_output_bytes(operation, *data, output_length);\n\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    switch (bits) {\n        case 255:\n            (*data)[0] &= 248;\n            (*data)[31] &= 127;\n            (*data)[31] |= 64;\n            break;\n        case 448:\n            (*data)[0] &= 252;\n            (*data)[55] |= 128;\n            break;\n        default:\n            return PSA_ERROR_CORRUPTION_DETECTED;\n            break;\n    }\n\n    return status;\n}\n#else /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE */\nstatic psa_status_t psa_generate_derived_ecc_key_weierstrass_helper(\n    psa_key_slot_t *slot, size_t bits,\n    psa_key_derivation_operation_t *operation, uint8_t **data)\n{\n    (void) slot;\n    (void) bits;\n    (void) operation;\n    (void) data;\n    return PSA_ERROR_NOT_SUPPORTED;\n}\n\nstatic psa_status_t psa_generate_derived_ecc_key_montgomery_helper(\n    size_t bits, psa_key_derivation_operation_t *operation, uint8_t **data)\n{\n    (void) bits;\n    (void) operation;\n    (void) data;\n    return PSA_ERROR_NOT_SUPPORTED;\n}\n#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE */\n#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE */\n\nstatic psa_status_t psa_generate_derived_key_internal(\n    psa_key_slot_t *slot,\n    size_t bits,\n    psa_key_derivation_operation_t *operation)\n{\n    uint8_t *data = NULL;\n    size_t bytes = PSA_BITS_TO_BYTES(bits);\n    size_t storage_size = bytes;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE)\n    if (PSA_KEY_TYPE_IS_ECC(slot->attr.type)) {\n        psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(slot->attr.type);\n        if (PSA_ECC_FAMILY_IS_WEIERSTRASS(curve)) {\n            /* Weierstrass elliptic curve */\n            status = psa_generate_derived_ecc_key_weierstrass_helper(slot, bits, operation, &data);\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n        } else {\n            /* Montgomery elliptic curve */\n            status = psa_generate_derived_ecc_key_montgomery_helper(bits, operation, &data);\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n        }\n    } else\n#endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) ||\n          defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) */\n    if (key_type_is_raw_bytes(slot->attr.type)) {\n        if (bits % 8 != 0) {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n        data = mbedtls_calloc(1, bytes);\n        if (data == NULL) {\n            return PSA_ERROR_INSUFFICIENT_MEMORY;\n        }\n\n        status = psa_key_derivation_output_bytes(operation, data, bytes);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)\n        if (slot->attr.type == PSA_KEY_TYPE_DES) {\n            psa_des_set_key_parity(data, bytes);\n        }\n#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) */\n    } else {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    slot->attr.bits = (psa_key_bits_t) bits;\n\n    if (psa_key_lifetime_is_external(slot->attr.lifetime)) {\n        status = psa_driver_wrapper_get_key_buffer_size(&slot->attr,\n                                                        &storage_size);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n    }\n    status = psa_allocate_buffer_to_slot(slot, storage_size);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_driver_wrapper_import_key(&slot->attr,\n                                           data, bytes,\n                                           slot->key.data,\n                                           slot->key.bytes,\n                                           &slot->key.bytes, &bits);\n    if (bits != slot->attr.bits) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n    }\n\nexit:\n    mbedtls_zeroize_and_free(data, bytes);\n    return status;\n}\n\nstatic const psa_custom_key_parameters_t default_custom_production =\n    PSA_CUSTOM_KEY_PARAMETERS_INIT;\n\nint psa_custom_key_parameters_are_default(\n    const psa_custom_key_parameters_t *custom,\n    size_t custom_data_length)\n{\n    if (custom->flags != 0) {\n        return 0;\n    }\n    if (custom_data_length != 0) {\n        return 0;\n    }\n    return 1;\n}\n\npsa_status_t psa_key_derivation_output_key_custom(\n    const psa_key_attributes_t *attributes,\n    psa_key_derivation_operation_t *operation,\n    const psa_custom_key_parameters_t *custom,\n    const uint8_t *custom_data,\n    size_t custom_data_length,\n    mbedtls_svc_key_id_t *key)\n{\n    psa_status_t status;\n    psa_key_slot_t *slot = NULL;\n    psa_se_drv_table_entry_t *driver = NULL;\n\n    *key = MBEDTLS_SVC_KEY_ID_INIT;\n\n    /* Reject any attempt to create a zero-length key so that we don't\n     * risk tripping up later, e.g. on a malloc(0) that returns NULL. */\n    if (psa_get_key_bits(attributes) == 0) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    (void) custom_data;         /* We only accept 0-length data */\n    if (!psa_custom_key_parameters_are_default(custom, custom_data_length)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    if (operation->alg == PSA_ALG_NONE) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    if (!operation->can_output_key) {\n        return PSA_ERROR_NOT_PERMITTED;\n    }\n\n    status = psa_start_key_creation(PSA_KEY_CREATION_DERIVE, attributes,\n                                    &slot, &driver);\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    if (driver != NULL) {\n        /* Deriving a key in a secure element is not implemented yet. */\n        status = PSA_ERROR_NOT_SUPPORTED;\n    }\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n    if (status == PSA_SUCCESS) {\n        status = psa_generate_derived_key_internal(slot,\n                                                   attributes->bits,\n                                                   operation);\n    }\n    if (status == PSA_SUCCESS) {\n        status = psa_finish_key_creation(slot, driver, key);\n    }\n    if (status != PSA_SUCCESS) {\n        psa_fail_key_creation(slot, driver);\n    }\n\n    return status;\n}\n\npsa_status_t psa_key_derivation_output_key_ext(\n    const psa_key_attributes_t *attributes,\n    psa_key_derivation_operation_t *operation,\n    const psa_key_production_parameters_t *params,\n    size_t params_data_length,\n    mbedtls_svc_key_id_t *key)\n{\n    return psa_key_derivation_output_key_custom(\n        attributes, operation,\n        (const psa_custom_key_parameters_t *) params,\n        params->data, params_data_length,\n        key);\n}\n\npsa_status_t psa_key_derivation_output_key(\n    const psa_key_attributes_t *attributes,\n    psa_key_derivation_operation_t *operation,\n    mbedtls_svc_key_id_t *key)\n{\n    return psa_key_derivation_output_key_custom(attributes, operation,\n                                                &default_custom_production,\n                                                NULL, 0,\n                                                key);\n}\n\n\n/****************************************************************/\n/* Key derivation: operation management */\n/****************************************************************/\n\n#if defined(AT_LEAST_ONE_BUILTIN_KDF)\nstatic int is_kdf_alg_supported(psa_algorithm_t kdf_alg)\n{\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)\n    if (PSA_ALG_IS_HKDF(kdf_alg)) {\n        return 1;\n    }\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)\n    if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {\n        return 1;\n    }\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)\n    if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {\n        return 1;\n    }\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF)\n    if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) {\n        return 1;\n    }\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)\n    if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {\n        return 1;\n    }\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)\n    if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {\n        return 1;\n    }\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)\n    if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {\n        return 1;\n    }\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128)\n    if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) {\n        return 1;\n    }\n#endif\n    return 0;\n}\n\nstatic psa_status_t psa_hash_try_support(psa_algorithm_t alg)\n{\n    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;\n    psa_status_t status = psa_hash_setup(&operation, alg);\n    psa_hash_abort(&operation);\n    return status;\n}\n\nstatic psa_status_t psa_key_derivation_set_maximum_capacity(\n    psa_key_derivation_operation_t *operation,\n    psa_algorithm_t kdf_alg)\n{\n#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS)\n    if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {\n        operation->capacity = PSA_HASH_LENGTH(PSA_ALG_SHA_256);\n        return PSA_SUCCESS;\n    }\n#endif\n#if defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128)\n    if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) {\n#if (SIZE_MAX > UINT32_MAX)\n        operation->capacity = UINT32_MAX * (size_t) PSA_MAC_LENGTH(\n            PSA_KEY_TYPE_AES,\n            128U,\n            PSA_ALG_CMAC);\n#else\n        operation->capacity = SIZE_MAX;\n#endif\n        return PSA_SUCCESS;\n    }\n#endif /* PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 */\n\n    /* After this point, if kdf_alg is not valid then value of hash_alg may be\n     * invalid or meaningless but it does not affect this function */\n    psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(kdf_alg);\n    size_t hash_size = PSA_HASH_LENGTH(hash_alg);\n    if (hash_size == 0) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    /* Make sure that hash_alg is a supported hash algorithm. Otherwise\n     * we might fail later, which is somewhat unfriendly and potentially\n     * risk-prone. */\n    psa_status_t status = psa_hash_try_support(hash_alg);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n#if defined(PSA_WANT_ALG_HKDF)\n    if (PSA_ALG_IS_HKDF(kdf_alg)) {\n        operation->capacity = 255 * hash_size;\n    } else\n#endif\n#if defined(PSA_WANT_ALG_HKDF_EXTRACT)\n    if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {\n        operation->capacity = hash_size;\n    } else\n#endif\n#if defined(PSA_WANT_ALG_HKDF_EXPAND)\n    if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {\n        operation->capacity = 255 * hash_size;\n    } else\n#endif\n#if defined(PSA_WANT_ALG_TLS12_PRF)\n    if (PSA_ALG_IS_TLS12_PRF(kdf_alg) &&\n        (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) {\n        operation->capacity = SIZE_MAX;\n    } else\n#endif\n#if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS)\n    if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg) &&\n        (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) {\n        /* Master Secret is always 48 bytes\n         * https://datatracker.ietf.org/doc/html/rfc5246.html#section-8.1 */\n        operation->capacity = 48U;\n    } else\n#endif\n#if defined(PSA_WANT_ALG_PBKDF2_HMAC)\n    if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {\n#if (SIZE_MAX > UINT32_MAX)\n        operation->capacity = UINT32_MAX * hash_size;\n#else\n        operation->capacity = SIZE_MAX;\n#endif\n    } else\n#endif /* PSA_WANT_ALG_PBKDF2_HMAC */\n    {\n        (void) hash_size;\n        status = PSA_ERROR_NOT_SUPPORTED;\n    }\n    return status;\n}\n\nstatic psa_status_t psa_key_derivation_setup_kdf(\n    psa_key_derivation_operation_t *operation,\n    psa_algorithm_t kdf_alg)\n{\n    /* Make sure that operation->ctx is properly zero-initialised. (Macro\n     * initialisers for this union leave some bytes unspecified.) */\n    memset(&operation->ctx, 0, sizeof(operation->ctx));\n\n    /* Make sure that kdf_alg is a supported key derivation algorithm. */\n    if (!is_kdf_alg_supported(kdf_alg)) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    psa_status_t status = psa_key_derivation_set_maximum_capacity(operation,\n                                                                  kdf_alg);\n    return status;\n}\n\nstatic psa_status_t psa_key_agreement_try_support(psa_algorithm_t alg)\n{\n#if defined(PSA_WANT_ALG_ECDH)\n    if (alg == PSA_ALG_ECDH) {\n        return PSA_SUCCESS;\n    }\n#endif\n#if defined(PSA_WANT_ALG_FFDH)\n    if (alg == PSA_ALG_FFDH) {\n        return PSA_SUCCESS;\n    }\n#endif\n    (void) alg;\n    return PSA_ERROR_NOT_SUPPORTED;\n}\n\nstatic int psa_key_derivation_allows_free_form_secret_input(\n    psa_algorithm_t kdf_alg)\n{\n#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS)\n    if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {\n        return 0;\n    }\n#endif\n    (void) kdf_alg;\n    return 1;\n}\n#endif /* AT_LEAST_ONE_BUILTIN_KDF */\n\npsa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation,\n                                      psa_algorithm_t alg)\n{\n    psa_status_t status;\n\n    if (operation->alg != 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    if (PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    } else if (PSA_ALG_IS_KEY_AGREEMENT(alg)) {\n#if defined(AT_LEAST_ONE_BUILTIN_KDF)\n        psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF(alg);\n        psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(alg);\n        status = psa_key_agreement_try_support(ka_alg);\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n        if (!psa_key_derivation_allows_free_form_secret_input(kdf_alg)) {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n        status = psa_key_derivation_setup_kdf(operation, kdf_alg);\n#else\n        return PSA_ERROR_NOT_SUPPORTED;\n#endif /* AT_LEAST_ONE_BUILTIN_KDF */\n    } else if (PSA_ALG_IS_KEY_DERIVATION(alg)) {\n#if defined(AT_LEAST_ONE_BUILTIN_KDF)\n        status = psa_key_derivation_setup_kdf(operation, alg);\n#else\n        return PSA_ERROR_NOT_SUPPORTED;\n#endif /* AT_LEAST_ONE_BUILTIN_KDF */\n    } else {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    if (status == PSA_SUCCESS) {\n        operation->alg = alg;\n    }\n    return status;\n}\n\n#if defined(BUILTIN_ALG_ANY_HKDF)\nstatic psa_status_t psa_hkdf_input(psa_hkdf_key_derivation_t *hkdf,\n                                   psa_algorithm_t kdf_alg,\n                                   psa_key_derivation_step_t step,\n                                   const uint8_t *data,\n                                   size_t data_length)\n{\n    psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg);\n    psa_status_t status;\n    switch (step) {\n        case PSA_KEY_DERIVATION_INPUT_SALT:\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)\n            if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {\n                return PSA_ERROR_INVALID_ARGUMENT;\n            }\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */\n            if (hkdf->state != HKDF_STATE_INIT) {\n                return PSA_ERROR_BAD_STATE;\n            } else {\n                status = psa_key_derivation_start_hmac(&hkdf->hmac,\n                                                       hash_alg,\n                                                       data, data_length);\n                if (status != PSA_SUCCESS) {\n                    return status;\n                }\n                hkdf->state = HKDF_STATE_STARTED;\n                return PSA_SUCCESS;\n            }\n        case PSA_KEY_DERIVATION_INPUT_SECRET:\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)\n            if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {\n                /* We shouldn't be in different state as HKDF_EXPAND only allows\n                 * two inputs: SECRET (this case) and INFO which does not modify\n                 * the state. It could happen only if the hkdf\n                 * object was corrupted. */\n                if (hkdf->state != HKDF_STATE_INIT) {\n                    return PSA_ERROR_BAD_STATE;\n                }\n\n                /* Allow only input that fits expected prk size */\n                if (data_length != PSA_HASH_LENGTH(hash_alg)) {\n                    return PSA_ERROR_INVALID_ARGUMENT;\n                }\n\n                memcpy(hkdf->prk, data, data_length);\n            } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */\n            {\n                /* HKDF: If no salt was provided, use an empty salt.\n                 * HKDF-EXTRACT: salt is mandatory. */\n                if (hkdf->state == HKDF_STATE_INIT) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)\n                    if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {\n                        return PSA_ERROR_BAD_STATE;\n                    }\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */\n                    status = psa_key_derivation_start_hmac(&hkdf->hmac,\n                                                           hash_alg,\n                                                           NULL, 0);\n                    if (status != PSA_SUCCESS) {\n                        return status;\n                    }\n                    hkdf->state = HKDF_STATE_STARTED;\n                }\n                if (hkdf->state != HKDF_STATE_STARTED) {\n                    return PSA_ERROR_BAD_STATE;\n                }\n                status = psa_mac_update(&hkdf->hmac,\n                                        data, data_length);\n                if (status != PSA_SUCCESS) {\n                    return status;\n                }\n                status = psa_mac_sign_finish(&hkdf->hmac,\n                                             hkdf->prk,\n                                             sizeof(hkdf->prk),\n                                             &data_length);\n                if (status != PSA_SUCCESS) {\n                    return status;\n                }\n            }\n\n            hkdf->state = HKDF_STATE_KEYED;\n            hkdf->block_number = 0;\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)\n            if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {\n                /* The only block of output is the PRK. */\n                memcpy(hkdf->output_block, hkdf->prk, PSA_HASH_LENGTH(hash_alg));\n                hkdf->offset_in_block = 0;\n            } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */\n            {\n                /* Block 0 is empty, and the next block will be\n                 * generated by psa_key_derivation_hkdf_read(). */\n                hkdf->offset_in_block = PSA_HASH_LENGTH(hash_alg);\n            }\n\n            return PSA_SUCCESS;\n        case PSA_KEY_DERIVATION_INPUT_INFO:\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)\n            if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {\n                return PSA_ERROR_INVALID_ARGUMENT;\n            }\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)\n            if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg) &&\n                hkdf->state == HKDF_STATE_INIT) {\n                return PSA_ERROR_BAD_STATE;\n            }\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */\n            if (hkdf->state == HKDF_STATE_OUTPUT) {\n                return PSA_ERROR_BAD_STATE;\n            }\n            if (hkdf->info_set) {\n                return PSA_ERROR_BAD_STATE;\n            }\n            hkdf->info_length = data_length;\n            if (data_length != 0) {\n                hkdf->info = mbedtls_calloc(1, data_length);\n                if (hkdf->info == NULL) {\n                    return PSA_ERROR_INSUFFICIENT_MEMORY;\n                }\n                memcpy(hkdf->info, data, data_length);\n            }\n            hkdf->info_set = 1;\n            return PSA_SUCCESS;\n        default:\n            return PSA_ERROR_INVALID_ARGUMENT;\n    }\n}\n#endif /* BUILTIN_ALG_ANY_HKDF */\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)\nstatic psa_status_t psa_tls12_prf_set_seed(psa_tls12_prf_key_derivation_t *prf,\n                                           const uint8_t *data,\n                                           size_t data_length)\n{\n    if (prf->state != PSA_TLS12_PRF_STATE_INIT) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    if (data_length != 0) {\n        prf->seed = mbedtls_calloc(1, data_length);\n        if (prf->seed == NULL) {\n            return PSA_ERROR_INSUFFICIENT_MEMORY;\n        }\n\n        memcpy(prf->seed, data, data_length);\n        prf->seed_length = data_length;\n    }\n\n    prf->state = PSA_TLS12_PRF_STATE_SEED_SET;\n\n    return PSA_SUCCESS;\n}\n\nstatic psa_status_t psa_tls12_prf_set_key(psa_tls12_prf_key_derivation_t *prf,\n                                          const uint8_t *data,\n                                          size_t data_length)\n{\n    if (prf->state != PSA_TLS12_PRF_STATE_SEED_SET &&\n        prf->state != PSA_TLS12_PRF_STATE_OTHER_KEY_SET) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    if (data_length != 0) {\n        prf->secret = mbedtls_calloc(1, data_length);\n        if (prf->secret == NULL) {\n            return PSA_ERROR_INSUFFICIENT_MEMORY;\n        }\n\n        memcpy(prf->secret, data, data_length);\n        prf->secret_length = data_length;\n    }\n\n    prf->state = PSA_TLS12_PRF_STATE_KEY_SET;\n\n    return PSA_SUCCESS;\n}\n\nstatic psa_status_t psa_tls12_prf_set_label(psa_tls12_prf_key_derivation_t *prf,\n                                            const uint8_t *data,\n                                            size_t data_length)\n{\n    if (prf->state != PSA_TLS12_PRF_STATE_KEY_SET) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    if (data_length != 0) {\n        prf->label = mbedtls_calloc(1, data_length);\n        if (prf->label == NULL) {\n            return PSA_ERROR_INSUFFICIENT_MEMORY;\n        }\n\n        memcpy(prf->label, data, data_length);\n        prf->label_length = data_length;\n    }\n\n    prf->state = PSA_TLS12_PRF_STATE_LABEL_SET;\n\n    return PSA_SUCCESS;\n}\n\nstatic psa_status_t psa_tls12_prf_input(psa_tls12_prf_key_derivation_t *prf,\n                                        psa_key_derivation_step_t step,\n                                        const uint8_t *data,\n                                        size_t data_length)\n{\n    switch (step) {\n        case PSA_KEY_DERIVATION_INPUT_SEED:\n            return psa_tls12_prf_set_seed(prf, data, data_length);\n        case PSA_KEY_DERIVATION_INPUT_SECRET:\n            return psa_tls12_prf_set_key(prf, data, data_length);\n        case PSA_KEY_DERIVATION_INPUT_LABEL:\n            return psa_tls12_prf_set_label(prf, data, data_length);\n        default:\n            return PSA_ERROR_INVALID_ARGUMENT;\n    }\n}\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||\n        * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)\nstatic psa_status_t psa_tls12_prf_psk_to_ms_set_key(\n    psa_tls12_prf_key_derivation_t *prf,\n    const uint8_t *data,\n    size_t data_length)\n{\n    psa_status_t status;\n    const size_t pms_len = (prf->state == PSA_TLS12_PRF_STATE_OTHER_KEY_SET ?\n                            4 + data_length + prf->other_secret_length :\n                            4 + 2 * data_length);\n\n    if (data_length > PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    uint8_t *pms = mbedtls_calloc(1, pms_len);\n    if (pms == NULL) {\n        return PSA_ERROR_INSUFFICIENT_MEMORY;\n    }\n    uint8_t *cur = pms;\n\n    /* pure-PSK:\n     * Quoting RFC 4279, Section 2:\n     *\n     * The premaster secret is formed as follows: if the PSK is N octets\n     * long, concatenate a uint16 with the value N, N zero octets, a second\n     * uint16 with the value N, and the PSK itself.\n     *\n     * mixed-PSK:\n     * In a DHE-PSK, RSA-PSK, ECDHE-PSK the premaster secret is formed as\n     * follows: concatenate a uint16 with the length of the other secret,\n     * the other secret itself, uint16 with the length of PSK, and the\n     * PSK itself.\n     * For details please check:\n     * - RFC 4279, Section 4 for the definition of RSA-PSK,\n     * - RFC 4279, Section 3 for the definition of DHE-PSK,\n     * - RFC 5489 for the definition of ECDHE-PSK.\n     */\n\n    if (prf->state == PSA_TLS12_PRF_STATE_OTHER_KEY_SET) {\n        *cur++ = MBEDTLS_BYTE_1(prf->other_secret_length);\n        *cur++ = MBEDTLS_BYTE_0(prf->other_secret_length);\n        if (prf->other_secret_length != 0) {\n            memcpy(cur, prf->other_secret, prf->other_secret_length);\n            mbedtls_platform_zeroize(prf->other_secret, prf->other_secret_length);\n            cur += prf->other_secret_length;\n        }\n    } else {\n        *cur++ = MBEDTLS_BYTE_1(data_length);\n        *cur++ = MBEDTLS_BYTE_0(data_length);\n        memset(cur, 0, data_length);\n        cur += data_length;\n    }\n\n    *cur++ = MBEDTLS_BYTE_1(data_length);\n    *cur++ = MBEDTLS_BYTE_0(data_length);\n    memcpy(cur, data, data_length);\n    cur += data_length;\n\n    status = psa_tls12_prf_set_key(prf, pms, (size_t) (cur - pms));\n\n    mbedtls_zeroize_and_free(pms, pms_len);\n    return status;\n}\n\nstatic psa_status_t psa_tls12_prf_psk_to_ms_set_other_key(\n    psa_tls12_prf_key_derivation_t *prf,\n    const uint8_t *data,\n    size_t data_length)\n{\n    if (prf->state != PSA_TLS12_PRF_STATE_SEED_SET) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    if (data_length != 0) {\n        prf->other_secret = mbedtls_calloc(1, data_length);\n        if (prf->other_secret == NULL) {\n            return PSA_ERROR_INSUFFICIENT_MEMORY;\n        }\n\n        memcpy(prf->other_secret, data, data_length);\n        prf->other_secret_length = data_length;\n    } else {\n        prf->other_secret_length = 0;\n    }\n\n    prf->state = PSA_TLS12_PRF_STATE_OTHER_KEY_SET;\n\n    return PSA_SUCCESS;\n}\n\nstatic psa_status_t psa_tls12_prf_psk_to_ms_input(\n    psa_tls12_prf_key_derivation_t *prf,\n    psa_key_derivation_step_t step,\n    const uint8_t *data,\n    size_t data_length)\n{\n    switch (step) {\n        case PSA_KEY_DERIVATION_INPUT_SECRET:\n            return psa_tls12_prf_psk_to_ms_set_key(prf,\n                                                   data, data_length);\n            break;\n        case PSA_KEY_DERIVATION_INPUT_OTHER_SECRET:\n            return psa_tls12_prf_psk_to_ms_set_other_key(prf,\n                                                         data,\n                                                         data_length);\n            break;\n        default:\n            return psa_tls12_prf_input(prf, step, data, data_length);\n            break;\n\n    }\n}\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)\nstatic psa_status_t psa_tls12_ecjpake_to_pms_input(\n    psa_tls12_ecjpake_to_pms_t *ecjpake,\n    psa_key_derivation_step_t step,\n    const uint8_t *data,\n    size_t data_length)\n{\n    if (data_length != PSA_TLS12_ECJPAKE_TO_PMS_INPUT_SIZE ||\n        step != PSA_KEY_DERIVATION_INPUT_SECRET) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    /* Check if the passed point is in an uncompressed form */\n    if (data[0] != 0x04) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    /* Only K.X has to be extracted - bytes 1 to 32 inclusive. */\n    memcpy(ecjpake->data, data + 1, PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE);\n\n    return PSA_SUCCESS;\n}\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */\n\n#if defined(PSA_HAVE_SOFT_PBKDF2)\nstatic psa_status_t psa_pbkdf2_set_input_cost(\n    psa_pbkdf2_key_derivation_t *pbkdf2,\n    psa_key_derivation_step_t step,\n    uint64_t data)\n{\n    if (step != PSA_KEY_DERIVATION_INPUT_COST) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    if (pbkdf2->state != PSA_PBKDF2_STATE_INIT) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    if (data > PSA_VENDOR_PBKDF2_MAX_ITERATIONS) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    if (data == 0) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    pbkdf2->input_cost = data;\n    pbkdf2->state = PSA_PBKDF2_STATE_INPUT_COST_SET;\n\n    return PSA_SUCCESS;\n}\n\nstatic psa_status_t psa_pbkdf2_set_salt(psa_pbkdf2_key_derivation_t *pbkdf2,\n                                        const uint8_t *data,\n                                        size_t data_length)\n{\n    if (pbkdf2->state == PSA_PBKDF2_STATE_INPUT_COST_SET) {\n        pbkdf2->state = PSA_PBKDF2_STATE_SALT_SET;\n    } else if (pbkdf2->state == PSA_PBKDF2_STATE_SALT_SET) {\n        /* Appending to existing salt. No state change. */\n    } else {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    if (data_length == 0) {\n        /* Appending an empty string, nothing to do. */\n    } else {\n        uint8_t *next_salt;\n\n        next_salt = mbedtls_calloc(1, data_length + pbkdf2->salt_length);\n        if (next_salt == NULL) {\n            return PSA_ERROR_INSUFFICIENT_MEMORY;\n        }\n\n        if (pbkdf2->salt_length != 0) {\n            memcpy(next_salt, pbkdf2->salt, pbkdf2->salt_length);\n        }\n        memcpy(next_salt + pbkdf2->salt_length, data, data_length);\n        pbkdf2->salt_length += data_length;\n        mbedtls_free(pbkdf2->salt);\n        pbkdf2->salt = next_salt;\n    }\n    return PSA_SUCCESS;\n}\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)\nstatic psa_status_t psa_pbkdf2_hmac_set_password(psa_algorithm_t hash_alg,\n                                                 const uint8_t *input,\n                                                 size_t input_len,\n                                                 uint8_t *output,\n                                                 size_t *output_len)\n{\n    psa_status_t status = PSA_SUCCESS;\n    if (input_len > PSA_HASH_BLOCK_LENGTH(hash_alg)) {\n        return psa_hash_compute(hash_alg, input, input_len, output,\n                                PSA_HMAC_MAX_HASH_BLOCK_SIZE, output_len);\n    } else if (input_len > 0) {\n        memcpy(output, input, input_len);\n    }\n    *output_len = PSA_HASH_BLOCK_LENGTH(hash_alg);\n    return status;\n}\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128)\nstatic psa_status_t psa_pbkdf2_cmac_set_password(const uint8_t *input,\n                                                 size_t input_len,\n                                                 uint8_t *output,\n                                                 size_t *output_len)\n{\n    psa_status_t status = PSA_SUCCESS;\n    if (input_len != PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC)) {\n        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n        uint8_t zeros[16] = { 0 };\n        psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);\n        psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(sizeof(zeros)));\n        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);\n        /* Passing PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC) as\n         * mac_size as the driver function sets mac_output_length = mac_size\n         * on success. See https://github.com/Mbed-TLS/mbedtls/issues/7801 */\n        status = psa_driver_wrapper_mac_compute(&attributes,\n                                                zeros, sizeof(zeros),\n                                                PSA_ALG_CMAC, input, input_len,\n                                                output,\n                                                PSA_MAC_LENGTH(PSA_KEY_TYPE_AES,\n                                                               128U,\n                                                               PSA_ALG_CMAC),\n                                                output_len);\n    } else {\n        memcpy(output, input, input_len);\n        *output_len = PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC);\n    }\n    return status;\n}\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 */\n\nstatic psa_status_t psa_pbkdf2_set_password(psa_pbkdf2_key_derivation_t *pbkdf2,\n                                            psa_algorithm_t kdf_alg,\n                                            const uint8_t *data,\n                                            size_t data_length)\n{\n    psa_status_t status = PSA_SUCCESS;\n    if (pbkdf2->state != PSA_PBKDF2_STATE_SALT_SET) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)\n    if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {\n        psa_algorithm_t hash_alg = PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg);\n        status = psa_pbkdf2_hmac_set_password(hash_alg, data, data_length,\n                                              pbkdf2->password,\n                                              &pbkdf2->password_length);\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128)\n    if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) {\n        status = psa_pbkdf2_cmac_set_password(data, data_length,\n                                              pbkdf2->password,\n                                              &pbkdf2->password_length);\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 */\n    {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    pbkdf2->state = PSA_PBKDF2_STATE_PASSWORD_SET;\n\n    return status;\n}\n\nstatic psa_status_t psa_pbkdf2_input(psa_pbkdf2_key_derivation_t *pbkdf2,\n                                     psa_algorithm_t kdf_alg,\n                                     psa_key_derivation_step_t step,\n                                     const uint8_t *data,\n                                     size_t data_length)\n{\n    switch (step) {\n        case PSA_KEY_DERIVATION_INPUT_SALT:\n            return psa_pbkdf2_set_salt(pbkdf2, data, data_length);\n        case PSA_KEY_DERIVATION_INPUT_PASSWORD:\n            return psa_pbkdf2_set_password(pbkdf2, kdf_alg, data, data_length);\n        default:\n            return PSA_ERROR_INVALID_ARGUMENT;\n    }\n}\n#endif /* PSA_HAVE_SOFT_PBKDF2 */\n\n/** Check whether the given key type is acceptable for the given\n * input step of a key derivation.\n *\n * Secret inputs must have the type #PSA_KEY_TYPE_DERIVE.\n * Non-secret inputs must have the type #PSA_KEY_TYPE_RAW_DATA.\n * Both secret and non-secret inputs can alternatively have the type\n * #PSA_KEY_TYPE_NONE, which is never the type of a key object, meaning\n * that the input was passed as a buffer rather than via a key object.\n */\nstatic int psa_key_derivation_check_input_type(\n    psa_key_derivation_step_t step,\n    psa_key_type_t key_type)\n{\n    switch (step) {\n        case PSA_KEY_DERIVATION_INPUT_SECRET:\n            if (key_type == PSA_KEY_TYPE_DERIVE) {\n                return PSA_SUCCESS;\n            }\n            if (key_type == PSA_KEY_TYPE_NONE) {\n                return PSA_SUCCESS;\n            }\n            break;\n        case PSA_KEY_DERIVATION_INPUT_OTHER_SECRET:\n            if (key_type == PSA_KEY_TYPE_DERIVE) {\n                return PSA_SUCCESS;\n            }\n            if (key_type == PSA_KEY_TYPE_NONE) {\n                return PSA_SUCCESS;\n            }\n            break;\n        case PSA_KEY_DERIVATION_INPUT_LABEL:\n        case PSA_KEY_DERIVATION_INPUT_SALT:\n        case PSA_KEY_DERIVATION_INPUT_INFO:\n        case PSA_KEY_DERIVATION_INPUT_SEED:\n            if (key_type == PSA_KEY_TYPE_RAW_DATA) {\n                return PSA_SUCCESS;\n            }\n            if (key_type == PSA_KEY_TYPE_NONE) {\n                return PSA_SUCCESS;\n            }\n            break;\n        case PSA_KEY_DERIVATION_INPUT_PASSWORD:\n            if (key_type == PSA_KEY_TYPE_PASSWORD) {\n                return PSA_SUCCESS;\n            }\n            if (key_type == PSA_KEY_TYPE_DERIVE) {\n                return PSA_SUCCESS;\n            }\n            if (key_type == PSA_KEY_TYPE_NONE) {\n                return PSA_SUCCESS;\n            }\n            break;\n    }\n    return PSA_ERROR_INVALID_ARGUMENT;\n}\n\nstatic psa_status_t psa_key_derivation_input_internal(\n    psa_key_derivation_operation_t *operation,\n    psa_key_derivation_step_t step,\n    psa_key_type_t key_type,\n    const uint8_t *data,\n    size_t data_length)\n{\n    psa_status_t status;\n    psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation);\n\n    if (kdf_alg == PSA_ALG_NONE) {\n        /* This is a blank or aborted operation. */\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    status = psa_key_derivation_check_input_type(step, key_type);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n#if defined(BUILTIN_ALG_ANY_HKDF)\n    if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) {\n        status = psa_hkdf_input(&operation->ctx.hkdf, kdf_alg,\n                                step, data, data_length);\n    } else\n#endif /* BUILTIN_ALG_ANY_HKDF */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF)\n    if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) {\n        status = psa_tls12_prf_input(&operation->ctx.tls12_prf,\n                                     step, data, data_length);\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)\n    if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {\n        status = psa_tls12_prf_psk_to_ms_input(&operation->ctx.tls12_prf,\n                                               step, data, data_length);\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)\n    if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {\n        status = psa_tls12_ecjpake_to_pms_input(\n            &operation->ctx.tls12_ecjpake_to_pms, step, data, data_length);\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */\n#if defined(PSA_HAVE_SOFT_PBKDF2)\n    if (PSA_ALG_IS_PBKDF2(kdf_alg)) {\n        status = psa_pbkdf2_input(&operation->ctx.pbkdf2, kdf_alg,\n                                  step, data, data_length);\n    } else\n#endif /* PSA_HAVE_SOFT_PBKDF2 */\n    {\n        /* This can't happen unless the operation object was not initialized */\n        (void) data;\n        (void) data_length;\n        (void) kdf_alg;\n        return PSA_ERROR_BAD_STATE;\n    }\n\nexit:\n    if (status != PSA_SUCCESS) {\n        psa_key_derivation_abort(operation);\n    }\n    return status;\n}\n\nstatic psa_status_t psa_key_derivation_input_integer_internal(\n    psa_key_derivation_operation_t *operation,\n    psa_key_derivation_step_t step,\n    uint64_t value)\n{\n    psa_status_t status;\n    psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation);\n\n    if (kdf_alg == PSA_ALG_NONE) {\n        /* This is a blank or aborted operation. */\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n#if defined(PSA_HAVE_SOFT_PBKDF2)\n    if (PSA_ALG_IS_PBKDF2(kdf_alg)) {\n        status = psa_pbkdf2_set_input_cost(\n            &operation->ctx.pbkdf2, step, value);\n    } else\n#endif /* PSA_HAVE_SOFT_PBKDF2 */\n    {\n        (void) step;\n        (void) value;\n        (void) kdf_alg;\n        status = PSA_ERROR_INVALID_ARGUMENT;\n    }\n\nexit:\n    if (status != PSA_SUCCESS) {\n        psa_key_derivation_abort(operation);\n    }\n    return status;\n}\n\npsa_status_t psa_key_derivation_input_bytes(\n    psa_key_derivation_operation_t *operation,\n    psa_key_derivation_step_t step,\n    const uint8_t *data_external,\n    size_t data_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    LOCAL_INPUT_DECLARE(data_external, data);\n\n    LOCAL_INPUT_ALLOC(data_external, data_length, data);\n\n    status = psa_key_derivation_input_internal(operation, step,\n                                               PSA_KEY_TYPE_NONE,\n                                               data, data_length);\n#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\nexit:\n#endif\n    LOCAL_INPUT_FREE(data_external, data);\n    return status;\n}\n\npsa_status_t psa_key_derivation_input_integer(\n    psa_key_derivation_operation_t *operation,\n    psa_key_derivation_step_t step,\n    uint64_t value)\n{\n    return psa_key_derivation_input_integer_internal(operation, step, value);\n}\n\npsa_status_t psa_key_derivation_input_key(\n    psa_key_derivation_operation_t *operation,\n    psa_key_derivation_step_t step,\n    mbedtls_svc_key_id_t key)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n\n    status = psa_get_and_lock_transparent_key_slot_with_policy(\n        key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg);\n    if (status != PSA_SUCCESS) {\n        psa_key_derivation_abort(operation);\n        return status;\n    }\n\n    /* Passing a key object as a SECRET or PASSWORD input unlocks the\n     * permission to output to a key object. */\n    if (step == PSA_KEY_DERIVATION_INPUT_SECRET ||\n        step == PSA_KEY_DERIVATION_INPUT_PASSWORD) {\n        operation->can_output_key = 1;\n    }\n\n    status = psa_key_derivation_input_internal(operation,\n                                               step, slot->attr.type,\n                                               slot->key.data,\n                                               slot->key.bytes);\n\n    unlock_status = psa_unregister_read_under_mutex(slot);\n\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n}\n\n\n\n/****************************************************************/\n/* Key agreement */\n/****************************************************************/\n\npsa_status_t psa_key_agreement_raw_builtin(const psa_key_attributes_t *attributes,\n                                           const uint8_t *key_buffer,\n                                           size_t key_buffer_size,\n                                           psa_algorithm_t alg,\n                                           const uint8_t *peer_key,\n                                           size_t peer_key_length,\n                                           uint8_t *shared_secret,\n                                           size_t shared_secret_size,\n                                           size_t *shared_secret_length)\n{\n    switch (alg) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)\n        case PSA_ALG_ECDH:\n            return mbedtls_psa_key_agreement_ecdh(attributes, key_buffer,\n                                                  key_buffer_size, alg,\n                                                  peer_key, peer_key_length,\n                                                  shared_secret,\n                                                  shared_secret_size,\n                                                  shared_secret_length);\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH)\n        case PSA_ALG_FFDH:\n            return mbedtls_psa_ffdh_key_agreement(attributes,\n                                                  peer_key,\n                                                  peer_key_length,\n                                                  key_buffer,\n                                                  key_buffer_size,\n                                                  shared_secret,\n                                                  shared_secret_size,\n                                                  shared_secret_length);\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */\n\n        default:\n            (void) attributes;\n            (void) key_buffer;\n            (void) key_buffer_size;\n            (void) peer_key;\n            (void) peer_key_length;\n            (void) shared_secret;\n            (void) shared_secret_size;\n            (void) shared_secret_length;\n            return PSA_ERROR_NOT_SUPPORTED;\n    }\n}\n\n/** Internal function for raw key agreement\n *  Calls the driver wrapper which will hand off key agreement task\n *  to the driver's implementation if a driver is present.\n *  Fallback specified in the driver wrapper is built-in raw key agreement\n *  (psa_key_agreement_raw_builtin).\n */\nstatic psa_status_t psa_key_agreement_raw_internal(psa_algorithm_t alg,\n                                                   psa_key_slot_t *private_key,\n                                                   const uint8_t *peer_key,\n                                                   size_t peer_key_length,\n                                                   uint8_t *shared_secret,\n                                                   size_t shared_secret_size,\n                                                   size_t *shared_secret_length)\n{\n    if (!PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    return psa_driver_wrapper_key_agreement(&private_key->attr,\n                                            private_key->key.data,\n                                            private_key->key.bytes, alg,\n                                            peer_key, peer_key_length,\n                                            shared_secret,\n                                            shared_secret_size,\n                                            shared_secret_length);\n}\n\n/* Note that if this function fails, you must call psa_key_derivation_abort()\n * to potentially free embedded data structures and wipe confidential data.\n */\nstatic psa_status_t psa_key_agreement_internal(psa_key_derivation_operation_t *operation,\n                                               psa_key_derivation_step_t step,\n                                               psa_key_slot_t *private_key,\n                                               const uint8_t *peer_key,\n                                               size_t peer_key_length)\n{\n    psa_status_t status;\n    uint8_t shared_secret[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE] = { 0 };\n    size_t shared_secret_length = 0;\n    psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(operation->alg);\n\n    /* Step 1: run the secret agreement algorithm to generate the shared\n     * secret. */\n    status = psa_key_agreement_raw_internal(ka_alg,\n                                            private_key,\n                                            peer_key, peer_key_length,\n                                            shared_secret,\n                                            sizeof(shared_secret),\n                                            &shared_secret_length);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    /* Step 2: set up the key derivation to generate key material from\n     * the shared secret. A shared secret is permitted wherever a key\n     * of type DERIVE is permitted. */\n    status = psa_key_derivation_input_internal(operation, step,\n                                               PSA_KEY_TYPE_DERIVE,\n                                               shared_secret,\n                                               shared_secret_length);\nexit:\n    mbedtls_platform_zeroize(shared_secret, shared_secret_length);\n    return status;\n}\n\npsa_status_t psa_key_derivation_key_agreement(psa_key_derivation_operation_t *operation,\n                                              psa_key_derivation_step_t step,\n                                              mbedtls_svc_key_id_t private_key,\n                                              const uint8_t *peer_key_external,\n                                              size_t peer_key_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n    LOCAL_INPUT_DECLARE(peer_key_external, peer_key);\n\n    if (!PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n    status = psa_get_and_lock_transparent_key_slot_with_policy(\n        private_key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key);\n    status = psa_key_agreement_internal(operation, step,\n                                        slot,\n                                        peer_key, peer_key_length);\n\n#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\nexit:\n#endif\n    if (status != PSA_SUCCESS) {\n        psa_key_derivation_abort(operation);\n    } else {\n        /* If a private key has been added as SECRET, we allow the derived\n         * key material to be used as a key in PSA Crypto. */\n        if (step == PSA_KEY_DERIVATION_INPUT_SECRET) {\n            operation->can_output_key = 1;\n        }\n    }\n\n    unlock_status = psa_unregister_read_under_mutex(slot);\n    LOCAL_INPUT_FREE(peer_key_external, peer_key);\n\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n}\n\npsa_status_t psa_raw_key_agreement(psa_algorithm_t alg,\n                                   mbedtls_svc_key_id_t private_key,\n                                   const uint8_t *peer_key_external,\n                                   size_t peer_key_length,\n                                   uint8_t *output_external,\n                                   size_t output_size,\n                                   size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot = NULL;\n    size_t expected_length;\n    LOCAL_INPUT_DECLARE(peer_key_external, peer_key);\n    LOCAL_OUTPUT_DECLARE(output_external, output);\n    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);\n\n    if (!PSA_ALG_IS_KEY_AGREEMENT(alg)) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n    status = psa_get_and_lock_transparent_key_slot_with_policy(\n        private_key, &slot, PSA_KEY_USAGE_DERIVE, alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    /* PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is in general an upper bound\n     * for the output size. The PSA specification only guarantees that this\n     * function works if output_size >= PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(...),\n     * but it might be nice to allow smaller buffers if the output fits.\n     * At the time of writing this comment, with only ECDH implemented,\n     * PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is exact so the point is moot.\n     * If FFDH is implemented, PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() can easily\n     * be exact for it as well. */\n    expected_length =\n        PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(slot->attr.type, slot->attr.bits);\n    if (output_size < expected_length) {\n        status = PSA_ERROR_BUFFER_TOO_SMALL;\n        goto exit;\n    }\n\n    LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key);\n    status = psa_key_agreement_raw_internal(alg, slot,\n                                            peer_key, peer_key_length,\n                                            output, output_size,\n                                            output_length);\n\nexit:\n    /* Check for successful allocation of output,\n     * with an unsuccessful status. */\n    if (output != NULL && status != PSA_SUCCESS) {\n        /* If an error happens and is not handled properly, the output\n         * may be used as a key to protect sensitive data. Arrange for such\n         * a key to be random, which is likely to result in decryption or\n         * verification errors. This is better than filling the buffer with\n         * some constant data such as zeros, which would result in the data\n         * being protected with a reproducible, easily knowable key.\n         */\n        psa_generate_random_internal(output, output_size);\n        *output_length = output_size;\n    }\n\n    if (output == NULL) {\n        /* output allocation failed. */\n        *output_length = 0;\n    }\n\n    unlock_status = psa_unregister_read_under_mutex(slot);\n\n    LOCAL_INPUT_FREE(peer_key_external, peer_key);\n    LOCAL_OUTPUT_FREE(output_external, output);\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n}\n\n\n/****************************************************************/\n/* Random generation */\n/****************************************************************/\n\n#if defined(MBEDTLS_PSA_INJECT_ENTROPY)\n#include \"entropy_poll.h\"\n#endif\n\n/** Initialize the PSA random generator.\n *\n *  Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling\n *  this function if mutexes are enabled.\n */\nstatic void mbedtls_psa_random_init(mbedtls_psa_random_context_t *rng)\n{\n#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)\n    memset(rng, 0, sizeof(*rng));\n#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */\n\n    /* Set default configuration if\n     * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */\n    if (rng->entropy_init == NULL) {\n        rng->entropy_init = mbedtls_entropy_init;\n    }\n    if (rng->entropy_free == NULL) {\n        rng->entropy_free = mbedtls_entropy_free;\n    }\n\n    rng->entropy_init(&rng->entropy);\n#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \\\n    defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)\n    /* The PSA entropy injection feature depends on using NV seed as an entropy\n     * source. Add NV seed as an entropy source for PSA entropy injection. */\n    mbedtls_entropy_add_source(&rng->entropy,\n                               mbedtls_nv_seed_poll, NULL,\n                               MBEDTLS_ENTROPY_BLOCK_SIZE,\n                               MBEDTLS_ENTROPY_SOURCE_STRONG);\n#endif\n\n    mbedtls_psa_drbg_init(&rng->drbg);\n#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */\n}\n\n/** Deinitialize the PSA random generator.\n *\n *  Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling\n *  this function if mutexes are enabled.\n */\nstatic void mbedtls_psa_random_free(mbedtls_psa_random_context_t *rng)\n{\n#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)\n    memset(rng, 0, sizeof(*rng));\n#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */\n    mbedtls_psa_drbg_free(&rng->drbg);\n    rng->entropy_free(&rng->entropy);\n#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */\n}\n\n/** Seed the PSA random generator.\n */\nstatic psa_status_t mbedtls_psa_random_seed(mbedtls_psa_random_context_t *rng)\n{\n#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)\n    /* Do nothing: the external RNG seeds itself. */\n    (void) rng;\n    return PSA_SUCCESS;\n#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */\n    const unsigned char drbg_seed[] = \"PSA\";\n    int ret = mbedtls_psa_drbg_seed(&rng->drbg, &rng->entropy,\n                                    drbg_seed, sizeof(drbg_seed) - 1);\n    return mbedtls_to_psa_error(ret);\n#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */\n}\n\npsa_status_t psa_generate_random(uint8_t *output_external,\n                                 size_t output_size)\n{\n    psa_status_t status;\n\n    LOCAL_OUTPUT_DECLARE(output_external, output);\n    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);\n\n    status = psa_generate_random_internal(output, output_size);\n\n#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\nexit:\n#endif\n    LOCAL_OUTPUT_FREE(output_external, output);\n    return status;\n}\n\n#if defined(MBEDTLS_PSA_INJECT_ENTROPY)\npsa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed,\n                                        size_t seed_size)\n{\n    if (psa_get_initialized()) {\n        return PSA_ERROR_NOT_PERMITTED;\n    }\n\n    if (((seed_size < MBEDTLS_ENTROPY_MIN_PLATFORM) ||\n         (seed_size < MBEDTLS_ENTROPY_BLOCK_SIZE)) ||\n        (seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    return mbedtls_psa_storage_inject_entropy(seed, seed_size);\n}\n#endif /* MBEDTLS_PSA_INJECT_ENTROPY */\n\n/** Validate the key type and size for key generation\n *\n * \\param  type  The key type\n * \\param  bits  The number of bits of the key\n *\n * \\retval #PSA_SUCCESS\n *         The key type and size are valid.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The size in bits of the key is not valid.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         The type and/or the size in bits of the key or the combination of\n *         the two is not supported.\n */\nstatic psa_status_t psa_validate_key_type_and_size_for_key_generation(\n    psa_key_type_t type, size_t bits)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    if (key_type_is_raw_bytes(type)) {\n        status = psa_validate_unstructured_key_bit_size(type, bits);\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n    } else\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)\n    if (PSA_KEY_TYPE_IS_RSA(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {\n        if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) {\n            return PSA_ERROR_NOT_SUPPORTED;\n        }\n        if (bits < PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS) {\n            return PSA_ERROR_NOT_SUPPORTED;\n        }\n\n        /* Accept only byte-aligned keys, for the same reasons as\n         * in psa_import_rsa_key(). */\n        if (bits % 8 != 0) {\n            return PSA_ERROR_NOT_SUPPORTED;\n        }\n    } else\n#endif /* defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */\n\n#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE)\n    if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {\n        /* To avoid empty block, return successfully here. */\n        return PSA_SUCCESS;\n    } else\n#endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) */\n\n#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)\n    if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {\n        if (psa_is_dh_key_size_valid(bits) == 0) {\n            return PSA_ERROR_NOT_SUPPORTED;\n        }\n    } else\n#endif /* defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) */\n    {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_generate_key_internal(\n    const psa_key_attributes_t *attributes,\n    const psa_custom_key_parameters_t *custom,\n    const uint8_t *custom_data,\n    size_t custom_data_length,\n    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_type_t type = attributes->type;\n\n    /* Only used for RSA */\n    (void) custom;\n    (void) custom_data;\n    (void) custom_data_length;\n\n    if (key_type_is_raw_bytes(type)) {\n        status = psa_generate_random_internal(key_buffer, key_buffer_size);\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)\n        if (type == PSA_KEY_TYPE_DES) {\n            psa_des_set_key_parity(key_buffer, key_buffer_size);\n        }\n#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */\n    } else\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)\n    if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {\n        return mbedtls_psa_rsa_generate_key(attributes,\n                                            custom_data, custom_data_length,\n                                            key_buffer,\n                                            key_buffer_size,\n                                            key_buffer_length);\n    } else\n#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE)\n    if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {\n        return mbedtls_psa_ecp_generate_key(attributes,\n                                            key_buffer,\n                                            key_buffer_size,\n                                            key_buffer_length);\n    } else\n#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) */\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE)\n    if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {\n        return mbedtls_psa_ffdh_generate_key(attributes,\n                                             key_buffer,\n                                             key_buffer_size,\n                                             key_buffer_length);\n    } else\n#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) */\n    {\n        (void) key_buffer_length;\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_generate_key_custom(const psa_key_attributes_t *attributes,\n                                     const psa_custom_key_parameters_t *custom,\n                                     const uint8_t *custom_data,\n                                     size_t custom_data_length,\n                                     mbedtls_svc_key_id_t *key)\n{\n    psa_status_t status;\n    psa_key_slot_t *slot = NULL;\n    psa_se_drv_table_entry_t *driver = NULL;\n    size_t key_buffer_size;\n\n    *key = MBEDTLS_SVC_KEY_ID_INIT;\n\n    /* Reject any attempt to create a zero-length key so that we don't\n     * risk tripping up later, e.g. on a malloc(0) that returns NULL. */\n    if (psa_get_key_bits(attributes) == 0) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    /* Reject any attempt to create a public key. */\n    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(attributes->type)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)\n    if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) {\n        if (custom->flags != 0) {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n    } else\n#endif\n    if (!psa_custom_key_parameters_are_default(custom, custom_data_length)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    status = psa_start_key_creation(PSA_KEY_CREATION_GENERATE, attributes,\n                                    &slot, &driver);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    /* In the case of a transparent key or an opaque key stored in local\n     * storage ( thus not in the case of generating a key in a secure element\n     * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a\n     * buffer to hold the generated key material. */\n    if (slot->key.bytes == 0) {\n        if (PSA_KEY_LIFETIME_GET_LOCATION(attributes->lifetime) ==\n            PSA_KEY_LOCATION_LOCAL_STORAGE) {\n            status = psa_validate_key_type_and_size_for_key_generation(\n                attributes->type, attributes->bits);\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n\n            key_buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE(\n                attributes->type,\n                attributes->bits);\n        } else {\n            status = psa_driver_wrapper_get_key_buffer_size(\n                attributes, &key_buffer_size);\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n        }\n\n        status = psa_allocate_buffer_to_slot(slot, key_buffer_size);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n    }\n\n    status = psa_driver_wrapper_generate_key(attributes,\n                                             custom,\n                                             custom_data, custom_data_length,\n                                             slot->key.data, slot->key.bytes,\n                                             &slot->key.bytes);\n    if (status != PSA_SUCCESS) {\n        psa_remove_key_data_from_memory(slot);\n    }\n\nexit:\n    if (status == PSA_SUCCESS) {\n        status = psa_finish_key_creation(slot, driver, key);\n    }\n    if (status != PSA_SUCCESS) {\n        psa_fail_key_creation(slot, driver);\n    }\n\n    return status;\n}\n\npsa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes,\n                                  const psa_key_production_parameters_t *params,\n                                  size_t params_data_length,\n                                  mbedtls_svc_key_id_t *key)\n{\n    return psa_generate_key_custom(\n        attributes,\n        (const psa_custom_key_parameters_t *) params,\n        params->data, params_data_length,\n        key);\n}\n\npsa_status_t psa_generate_key(const psa_key_attributes_t *attributes,\n                              mbedtls_svc_key_id_t *key)\n{\n    return psa_generate_key_custom(attributes,\n                                   &default_custom_production,\n                                   NULL, 0,\n                                   key);\n}\n\n\n\n/****************************************************************/\n/* Module setup */\n/****************************************************************/\n\n#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)\npsa_status_t mbedtls_psa_crypto_configure_entropy_sources(\n    void (* entropy_init)(mbedtls_entropy_context *ctx),\n    void (* entropy_free)(mbedtls_entropy_context *ctx))\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n    if (global_data.rng_state != RNG_NOT_INITIALIZED) {\n        status = PSA_ERROR_BAD_STATE;\n    } else {\n        global_data.rng.entropy_init = entropy_init;\n        global_data.rng.entropy_free = entropy_free;\n        status = PSA_SUCCESS;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n    return status;\n}\n#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */\n\nvoid mbedtls_psa_crypto_free(void)\n{\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n    /* Nothing to do to free transaction. */\n    if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED) {\n        global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;\n    }\n\n    if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED) {\n        psa_wipe_all_key_slots();\n        global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n    if (global_data.rng_state != RNG_NOT_INITIALIZED) {\n        mbedtls_psa_random_free(&global_data.rng);\n    }\n    global_data.rng_state = RNG_NOT_INITIALIZED;\n    mbedtls_platform_zeroize(&global_data.rng, sizeof(global_data.rng));\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n    /* Terminate drivers */\n    if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) {\n        psa_driver_wrapper_free();\n        global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n}\n\n#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)\n/** Recover a transaction that was interrupted by a power failure.\n *\n * This function is called during initialization, before psa_crypto_init()\n * returns. If this function returns a failure status, the initialization\n * fails.\n */\nstatic psa_status_t psa_crypto_recover_transaction(\n    const psa_crypto_transaction_t *transaction)\n{\n    switch (transaction->unknown.type) {\n        case PSA_CRYPTO_TRANSACTION_CREATE_KEY:\n        case PSA_CRYPTO_TRANSACTION_DESTROY_KEY:\n        /* TODO - fall through to the failure case until this\n         * is implemented.\n         * https://github.com/ARMmbed/mbed-crypto/issues/218\n         */\n        default:\n            /* We found an unsupported transaction in the storage.\n             * We don't know what state the storage is in. Give up. */\n            return PSA_ERROR_DATA_INVALID;\n    }\n}\n#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */\n\nstatic psa_status_t mbedtls_psa_crypto_init_subsystem(mbedtls_psa_crypto_subsystem subsystem)\n{\n    psa_status_t status = PSA_SUCCESS;\n    uint8_t driver_wrappers_initialized = 0;\n\n    switch (subsystem) {\n        case PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS:\n\n#if defined(MBEDTLS_THREADING_C)\n            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n            if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED)) {\n                /* Init drivers */\n                status = psa_driver_wrapper_init();\n\n                /* Drivers need shutdown regardless of startup errors. */\n                global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED;\n\n\n            }\n#if defined(MBEDTLS_THREADING_C)\n            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(\n                                            &mbedtls_threading_psa_globaldata_mutex));\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n            break;\n\n        case PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS:\n\n#if defined(MBEDTLS_THREADING_C)\n            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n            if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED)) {\n                status = psa_initialize_key_slots();\n\n                /* Need to wipe keys even if initialization fails. */\n                global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED;\n\n            }\n#if defined(MBEDTLS_THREADING_C)\n            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(\n                                            &mbedtls_threading_psa_globaldata_mutex));\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n            break;\n\n        case PSA_CRYPTO_SUBSYSTEM_RNG:\n\n#if defined(MBEDTLS_THREADING_C)\n            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n            driver_wrappers_initialized =\n                (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED);\n\n#if defined(MBEDTLS_THREADING_C)\n            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(\n                                            &mbedtls_threading_psa_globaldata_mutex));\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n            /* Need to use separate mutex here, as initialisation can require\n             * testing of init flags, which requires locking the global data\n             * mutex. */\n#if defined(MBEDTLS_THREADING_C)\n            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex));\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n            /* Initialize and seed the random generator. */\n            if (global_data.rng_state == RNG_NOT_INITIALIZED && driver_wrappers_initialized) {\n                mbedtls_psa_random_init(&global_data.rng);\n                global_data.rng_state = RNG_INITIALIZED;\n\n                status = mbedtls_psa_random_seed(&global_data.rng);\n                if (status == PSA_SUCCESS) {\n                    global_data.rng_state = RNG_SEEDED;\n                }\n            }\n\n#if defined(MBEDTLS_THREADING_C)\n            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(\n                                            &mbedtls_threading_psa_rngdata_mutex));\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n            break;\n\n        case PSA_CRYPTO_SUBSYSTEM_TRANSACTION:\n\n#if defined(MBEDTLS_THREADING_C)\n            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n            if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)) {\n#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)\n                status = psa_crypto_load_transaction();\n                if (status == PSA_SUCCESS) {\n                    status = psa_crypto_recover_transaction(&psa_crypto_transaction);\n                    if (status == PSA_SUCCESS) {\n                        global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;\n                    }\n                    status = psa_crypto_stop_transaction();\n                } else if (status == PSA_ERROR_DOES_NOT_EXIST) {\n                    /* There's no transaction to complete. It's all good. */\n                    global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;\n                    status = PSA_SUCCESS;\n                }\n#else /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */\n                global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;\n                status = PSA_SUCCESS;\n#endif /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */\n            }\n\n#if defined(MBEDTLS_THREADING_C)\n            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(\n                                            &mbedtls_threading_psa_globaldata_mutex));\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n            break;\n\n        default:\n            status = PSA_ERROR_CORRUPTION_DETECTED;\n    }\n\n    /* Exit label only required when using threading macros. */\n#if defined(MBEDTLS_THREADING_C)\nexit:\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n    return status;\n}\n\npsa_status_t psa_crypto_init(void)\n{\n    psa_status_t status;\n\n    /* Double initialization is explicitly allowed. Early out if everything is\n     * done. */\n    if (psa_get_initialized()) {\n        return PSA_SUCCESS;\n    }\n\n    status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_RNG);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_TRANSACTION);\n\nexit:\n\n    if (status != PSA_SUCCESS) {\n        mbedtls_psa_crypto_free();\n    }\n\n    return status;\n}\n\n\n\n/****************************************************************/\n/* PAKE */\n/****************************************************************/\n\n#if defined(PSA_WANT_ALG_SOME_PAKE)\npsa_status_t psa_crypto_driver_pake_get_password_len(\n    const psa_crypto_driver_pake_inputs_t *inputs,\n    size_t *password_len)\n{\n    if (inputs->password_len == 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    *password_len = inputs->password_len;\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_crypto_driver_pake_get_password(\n    const psa_crypto_driver_pake_inputs_t *inputs,\n    uint8_t *buffer, size_t buffer_size, size_t *buffer_length)\n{\n    if (inputs->password_len == 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    if (buffer_size < inputs->password_len) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n\n    memcpy(buffer, inputs->password, inputs->password_len);\n    *buffer_length = inputs->password_len;\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_crypto_driver_pake_get_user_len(\n    const psa_crypto_driver_pake_inputs_t *inputs,\n    size_t *user_len)\n{\n    if (inputs->user_len == 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    *user_len = inputs->user_len;\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_crypto_driver_pake_get_user(\n    const psa_crypto_driver_pake_inputs_t *inputs,\n    uint8_t *user_id, size_t user_id_size, size_t *user_id_len)\n{\n    if (inputs->user_len == 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    if (user_id_size < inputs->user_len) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n\n    memcpy(user_id, inputs->user, inputs->user_len);\n    *user_id_len = inputs->user_len;\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_crypto_driver_pake_get_peer_len(\n    const psa_crypto_driver_pake_inputs_t *inputs,\n    size_t *peer_len)\n{\n    if (inputs->peer_len == 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    *peer_len = inputs->peer_len;\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_crypto_driver_pake_get_peer(\n    const psa_crypto_driver_pake_inputs_t *inputs,\n    uint8_t *peer_id, size_t peer_id_size, size_t *peer_id_length)\n{\n    if (inputs->peer_len == 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    if (peer_id_size < inputs->peer_len) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n\n    memcpy(peer_id, inputs->peer, inputs->peer_len);\n    *peer_id_length = inputs->peer_len;\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_crypto_driver_pake_get_cipher_suite(\n    const psa_crypto_driver_pake_inputs_t *inputs,\n    psa_pake_cipher_suite_t *cipher_suite)\n{\n    if (inputs->cipher_suite.algorithm == PSA_ALG_NONE) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    *cipher_suite = inputs->cipher_suite;\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_pake_setup(\n    psa_pake_operation_t *operation,\n    const psa_pake_cipher_suite_t *cipher_suite)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    if (operation->stage != PSA_PAKE_OPERATION_STAGE_SETUP) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (PSA_ALG_IS_PAKE(cipher_suite->algorithm) == 0 ||\n        PSA_ALG_IS_HASH(cipher_suite->hash) == 0) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    /* Make sure the variable-purpose part of the operation is zeroed.\n     * Initializing the operation does not necessarily take care of it,\n     * since the context is a union and initializing a union does not\n     * necessarily initialize all of its members. */\n    memset(&operation->data, 0, sizeof(operation->data));\n\n    operation->alg = cipher_suite->algorithm;\n    operation->primitive = PSA_PAKE_PRIMITIVE(cipher_suite->type,\n                                              cipher_suite->family, cipher_suite->bits);\n    operation->data.inputs.cipher_suite = *cipher_suite;\n\n#if defined(PSA_WANT_ALG_JPAKE)\n    if (operation->alg == PSA_ALG_JPAKE) {\n        psa_jpake_computation_stage_t *computation_stage =\n            &operation->computation_stage.jpake;\n\n        memset(computation_stage, 0, sizeof(*computation_stage));\n        computation_stage->step = PSA_PAKE_STEP_KEY_SHARE;\n    } else\n#endif /* PSA_WANT_ALG_JPAKE */\n    {\n        status = PSA_ERROR_NOT_SUPPORTED;\n        goto exit;\n    }\n\n    operation->stage = PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS;\n\n    return PSA_SUCCESS;\nexit:\n    psa_pake_abort(operation);\n    return status;\n}\n\npsa_status_t psa_pake_set_password_key(\n    psa_pake_operation_t *operation,\n    mbedtls_svc_key_id_t password)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot = NULL;\n    psa_key_type_t type;\n\n    if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    status = psa_get_and_lock_key_slot_with_policy(password, &slot,\n                                                   PSA_KEY_USAGE_DERIVE,\n                                                   operation->alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    type = psa_get_key_type(&slot->attr);\n\n    if (type != PSA_KEY_TYPE_PASSWORD &&\n        type != PSA_KEY_TYPE_PASSWORD_HASH) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    operation->data.inputs.password = mbedtls_calloc(1, slot->key.bytes);\n    if (operation->data.inputs.password == NULL) {\n        status = PSA_ERROR_INSUFFICIENT_MEMORY;\n        goto exit;\n    }\n\n    memcpy(operation->data.inputs.password, slot->key.data, slot->key.bytes);\n    operation->data.inputs.password_len = slot->key.bytes;\n    operation->data.inputs.attributes = slot->attr;\n\nexit:\n    if (status != PSA_SUCCESS) {\n        psa_pake_abort(operation);\n    }\n    unlock_status = psa_unregister_read_under_mutex(slot);\n    return (status == PSA_SUCCESS) ? unlock_status : status;\n}\n\npsa_status_t psa_pake_set_user(\n    psa_pake_operation_t *operation,\n    const uint8_t *user_id_external,\n    size_t user_id_len)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    LOCAL_INPUT_DECLARE(user_id_external, user_id);\n\n    if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (user_id_len == 0) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    if (operation->data.inputs.user_len != 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    operation->data.inputs.user = mbedtls_calloc(1, user_id_len);\n    if (operation->data.inputs.user == NULL) {\n        status = PSA_ERROR_INSUFFICIENT_MEMORY;\n        goto exit;\n    }\n\n    LOCAL_INPUT_ALLOC(user_id_external, user_id_len, user_id);\n\n    memcpy(operation->data.inputs.user, user_id, user_id_len);\n    operation->data.inputs.user_len = user_id_len;\n\n    status = PSA_SUCCESS;\n\nexit:\n    LOCAL_INPUT_FREE(user_id_external, user_id);\n    if (status != PSA_SUCCESS) {\n        psa_pake_abort(operation);\n    }\n    return status;\n}\n\npsa_status_t psa_pake_set_peer(\n    psa_pake_operation_t *operation,\n    const uint8_t *peer_id_external,\n    size_t peer_id_len)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    LOCAL_INPUT_DECLARE(peer_id_external, peer_id);\n\n    if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (peer_id_len == 0) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    if (operation->data.inputs.peer_len != 0) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    operation->data.inputs.peer = mbedtls_calloc(1, peer_id_len);\n    if (operation->data.inputs.peer == NULL) {\n        status = PSA_ERROR_INSUFFICIENT_MEMORY;\n        goto exit;\n    }\n\n    LOCAL_INPUT_ALLOC(peer_id_external, peer_id_len, peer_id);\n\n    memcpy(operation->data.inputs.peer, peer_id, peer_id_len);\n    operation->data.inputs.peer_len = peer_id_len;\n\n    status = PSA_SUCCESS;\n\nexit:\n    LOCAL_INPUT_FREE(peer_id_external, peer_id);\n    if (status != PSA_SUCCESS) {\n        psa_pake_abort(operation);\n    }\n    return status;\n}\n\npsa_status_t psa_pake_set_role(\n    psa_pake_operation_t *operation,\n    psa_pake_role_t role)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    switch (operation->alg) {\n#if defined(PSA_WANT_ALG_JPAKE)\n        case PSA_ALG_JPAKE:\n            if (role == PSA_PAKE_ROLE_NONE) {\n                return PSA_SUCCESS;\n            }\n            status = PSA_ERROR_INVALID_ARGUMENT;\n            break;\n#endif\n        default:\n            (void) role;\n            status = PSA_ERROR_NOT_SUPPORTED;\n            goto exit;\n    }\nexit:\n    psa_pake_abort(operation);\n    return status;\n}\n\n/* Auxiliary function to convert core computation stage to single driver step. */\n#if defined(PSA_WANT_ALG_JPAKE)\nstatic psa_crypto_driver_pake_step_t convert_jpake_computation_stage_to_driver_step(\n    psa_jpake_computation_stage_t *stage)\n{\n    psa_crypto_driver_pake_step_t key_share_step;\n    if (stage->round == PSA_JPAKE_FIRST) {\n        int is_x1;\n\n        if (stage->io_mode == PSA_JPAKE_OUTPUT) {\n            is_x1 = (stage->outputs < 1);\n        } else {\n            is_x1 = (stage->inputs < 1);\n        }\n\n        key_share_step = is_x1 ?\n                         PSA_JPAKE_X1_STEP_KEY_SHARE :\n                         PSA_JPAKE_X2_STEP_KEY_SHARE;\n    } else if (stage->round == PSA_JPAKE_SECOND) {\n        key_share_step = (stage->io_mode == PSA_JPAKE_OUTPUT) ?\n                         PSA_JPAKE_X2S_STEP_KEY_SHARE :\n                         PSA_JPAKE_X4S_STEP_KEY_SHARE;\n    } else {\n        return PSA_JPAKE_STEP_INVALID;\n    }\n    return (psa_crypto_driver_pake_step_t) (key_share_step + stage->step - PSA_PAKE_STEP_KEY_SHARE);\n}\n#endif /* PSA_WANT_ALG_JPAKE */\n\nstatic psa_status_t psa_pake_complete_inputs(\n    psa_pake_operation_t *operation)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    /* Create copy of the inputs on stack as inputs share memory\n       with the driver context which will be setup by the driver. */\n    psa_crypto_driver_pake_inputs_t inputs = operation->data.inputs;\n\n    if (inputs.password_len == 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    if (operation->alg == PSA_ALG_JPAKE) {\n        if (inputs.user_len == 0 || inputs.peer_len == 0) {\n            return PSA_ERROR_BAD_STATE;\n        }\n    }\n\n    /* Clear driver context */\n    mbedtls_platform_zeroize(&operation->data, sizeof(operation->data));\n\n    status = psa_driver_wrapper_pake_setup(operation, &inputs);\n\n    /* Driver is responsible for creating its own copy of the password. */\n    mbedtls_zeroize_and_free(inputs.password, inputs.password_len);\n\n    /* User and peer are translated to role. */\n    mbedtls_free(inputs.user);\n    mbedtls_free(inputs.peer);\n\n    if (status == PSA_SUCCESS) {\n#if defined(PSA_WANT_ALG_JPAKE)\n        if (operation->alg == PSA_ALG_JPAKE) {\n            operation->stage = PSA_PAKE_OPERATION_STAGE_COMPUTATION;\n        } else\n#endif /* PSA_WANT_ALG_JPAKE */\n        {\n            status = PSA_ERROR_NOT_SUPPORTED;\n        }\n    }\n    return status;\n}\n\n#if defined(PSA_WANT_ALG_JPAKE)\nstatic psa_status_t psa_jpake_prologue(\n    psa_pake_operation_t *operation,\n    psa_pake_step_t step,\n    psa_jpake_io_mode_t io_mode)\n{\n    if (step != PSA_PAKE_STEP_KEY_SHARE &&\n        step != PSA_PAKE_STEP_ZK_PUBLIC &&\n        step != PSA_PAKE_STEP_ZK_PROOF) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    psa_jpake_computation_stage_t *computation_stage =\n        &operation->computation_stage.jpake;\n\n    if (computation_stage->round != PSA_JPAKE_FIRST &&\n        computation_stage->round != PSA_JPAKE_SECOND) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    /* Check that the step we are given is the one we were expecting */\n    if (step != computation_stage->step) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    if (step == PSA_PAKE_STEP_KEY_SHARE &&\n        computation_stage->inputs == 0 &&\n        computation_stage->outputs == 0) {\n        /* Start of the round, so function decides whether we are inputting\n         * or outputting */\n        computation_stage->io_mode = io_mode;\n    } else if (computation_stage->io_mode != io_mode) {\n        /* Middle of the round so the mode we are in must match the function\n         * called by the user */\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    return PSA_SUCCESS;\n}\n\nstatic psa_status_t psa_jpake_epilogue(\n    psa_pake_operation_t *operation,\n    psa_jpake_io_mode_t io_mode)\n{\n    psa_jpake_computation_stage_t *stage =\n        &operation->computation_stage.jpake;\n\n    if (stage->step == PSA_PAKE_STEP_ZK_PROOF) {\n        /* End of an input/output */\n        if (io_mode == PSA_JPAKE_INPUT) {\n            stage->inputs++;\n            if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round)) {\n                stage->io_mode = PSA_JPAKE_OUTPUT;\n            }\n        }\n        if (io_mode == PSA_JPAKE_OUTPUT) {\n            stage->outputs++;\n            if (stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) {\n                stage->io_mode = PSA_JPAKE_INPUT;\n            }\n        }\n        if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round) &&\n            stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) {\n            /* End of a round, move to the next round */\n            stage->inputs = 0;\n            stage->outputs = 0;\n            stage->round++;\n        }\n        stage->step = PSA_PAKE_STEP_KEY_SHARE;\n    } else {\n        stage->step++;\n    }\n    return PSA_SUCCESS;\n}\n\n#endif /* PSA_WANT_ALG_JPAKE */\n\npsa_status_t psa_pake_output(\n    psa_pake_operation_t *operation,\n    psa_pake_step_t step,\n    uint8_t *output_external,\n    size_t output_size,\n    size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID;\n    LOCAL_OUTPUT_DECLARE(output_external, output);\n    *output_length = 0;\n\n    if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {\n        status = psa_pake_complete_inputs(operation);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n    }\n\n    if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (output_size == 0) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    switch (operation->alg) {\n#if defined(PSA_WANT_ALG_JPAKE)\n        case PSA_ALG_JPAKE:\n            status = psa_jpake_prologue(operation, step, PSA_JPAKE_OUTPUT);\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n            driver_step = convert_jpake_computation_stage_to_driver_step(\n                &operation->computation_stage.jpake);\n            break;\n#endif /* PSA_WANT_ALG_JPAKE */\n        default:\n            (void) step;\n            status = PSA_ERROR_NOT_SUPPORTED;\n            goto exit;\n    }\n\n    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);\n\n    status = psa_driver_wrapper_pake_output(operation, driver_step,\n                                            output, output_size, output_length);\n\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    switch (operation->alg) {\n#if defined(PSA_WANT_ALG_JPAKE)\n        case PSA_ALG_JPAKE:\n            status = psa_jpake_epilogue(operation, PSA_JPAKE_OUTPUT);\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n            break;\n#endif /* PSA_WANT_ALG_JPAKE */\n        default:\n            status = PSA_ERROR_NOT_SUPPORTED;\n            goto exit;\n    }\n\nexit:\n    LOCAL_OUTPUT_FREE(output_external, output);\n    if (status != PSA_SUCCESS) {\n        psa_pake_abort(operation);\n    }\n    return status;\n}\n\npsa_status_t psa_pake_input(\n    psa_pake_operation_t *operation,\n    psa_pake_step_t step,\n    const uint8_t *input_external,\n    size_t input_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID;\n    const size_t max_input_length = (size_t) PSA_PAKE_INPUT_SIZE(operation->alg,\n                                                                 operation->primitive,\n                                                                 step);\n    LOCAL_INPUT_DECLARE(input_external, input);\n\n    if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {\n        status = psa_pake_complete_inputs(operation);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n    }\n\n    if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) {\n        status =  PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n    if (input_length == 0 || input_length > max_input_length) {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    switch (operation->alg) {\n#if defined(PSA_WANT_ALG_JPAKE)\n        case PSA_ALG_JPAKE:\n            status = psa_jpake_prologue(operation, step, PSA_JPAKE_INPUT);\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n            driver_step = convert_jpake_computation_stage_to_driver_step(\n                &operation->computation_stage.jpake);\n            break;\n#endif /* PSA_WANT_ALG_JPAKE */\n        default:\n            (void) step;\n            status = PSA_ERROR_NOT_SUPPORTED;\n            goto exit;\n    }\n\n    LOCAL_INPUT_ALLOC(input_external, input_length, input);\n    status = psa_driver_wrapper_pake_input(operation, driver_step,\n                                           input, input_length);\n\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    switch (operation->alg) {\n#if defined(PSA_WANT_ALG_JPAKE)\n        case PSA_ALG_JPAKE:\n            status = psa_jpake_epilogue(operation, PSA_JPAKE_INPUT);\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n            break;\n#endif /* PSA_WANT_ALG_JPAKE */\n        default:\n            status = PSA_ERROR_NOT_SUPPORTED;\n            goto exit;\n    }\n\nexit:\n    LOCAL_INPUT_FREE(input_external, input);\n    if (status != PSA_SUCCESS) {\n        psa_pake_abort(operation);\n    }\n    return status;\n}\n\npsa_status_t psa_pake_get_implicit_key(\n    psa_pake_operation_t *operation,\n    psa_key_derivation_operation_t *output)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;\n    uint8_t shared_key[MBEDTLS_PSA_JPAKE_BUFFER_SIZE];\n    size_t shared_key_len = 0;\n\n    if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) {\n        status = PSA_ERROR_BAD_STATE;\n        goto exit;\n    }\n\n#if defined(PSA_WANT_ALG_JPAKE)\n    if (operation->alg == PSA_ALG_JPAKE) {\n        psa_jpake_computation_stage_t *computation_stage =\n            &operation->computation_stage.jpake;\n        if (computation_stage->round != PSA_JPAKE_FINISHED) {\n            status = PSA_ERROR_BAD_STATE;\n            goto exit;\n        }\n    } else\n#endif /* PSA_WANT_ALG_JPAKE */\n    {\n        status = PSA_ERROR_NOT_SUPPORTED;\n        goto exit;\n    }\n\n    status = psa_driver_wrapper_pake_get_implicit_key(operation,\n                                                      shared_key,\n                                                      sizeof(shared_key),\n                                                      &shared_key_len);\n\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_key_derivation_input_bytes(output,\n                                            PSA_KEY_DERIVATION_INPUT_SECRET,\n                                            shared_key,\n                                            shared_key_len);\n\n    mbedtls_platform_zeroize(shared_key, sizeof(shared_key));\nexit:\n    abort_status = psa_pake_abort(operation);\n    return status == PSA_SUCCESS ? abort_status : status;\n}\n\npsa_status_t psa_pake_abort(\n    psa_pake_operation_t *operation)\n{\n    psa_status_t status = PSA_SUCCESS;\n\n    if (operation->stage == PSA_PAKE_OPERATION_STAGE_COMPUTATION) {\n        status = psa_driver_wrapper_pake_abort(operation);\n    }\n\n    if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {\n        if (operation->data.inputs.password != NULL) {\n            mbedtls_zeroize_and_free(operation->data.inputs.password,\n                                     operation->data.inputs.password_len);\n        }\n        if (operation->data.inputs.user != NULL) {\n            mbedtls_free(operation->data.inputs.user);\n        }\n        if (operation->data.inputs.peer != NULL) {\n            mbedtls_free(operation->data.inputs.peer);\n        }\n    }\n    memset(operation, 0, sizeof(psa_pake_operation_t));\n\n    return status;\n}\n#endif /* PSA_WANT_ALG_SOME_PAKE */\n\n/* Memory copying test hooks. These are called before input copy, after input\n * copy, before output copy and after output copy, respectively.\n * They are used by memory-poisoning tests to temporarily unpoison buffers\n * while they are copied. */\n#if defined(MBEDTLS_TEST_HOOKS)\nvoid (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len) = NULL;\nvoid (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len) = NULL;\nvoid (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len) = NULL;\nvoid (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len) = NULL;\n#endif\n\n/** Copy from an input buffer to a local copy.\n *\n * \\param[in] input             Pointer to input buffer.\n * \\param[in] input_len         Length of the input buffer.\n * \\param[out] input_copy       Pointer to a local copy in which to store the input data.\n * \\param[out] input_copy_len   Length of the local copy buffer.\n * \\return                      #PSA_SUCCESS, if the buffer was successfully\n *                              copied.\n * \\return                      #PSA_ERROR_CORRUPTION_DETECTED, if the local\n *                              copy is too small to hold contents of the\n *                              input buffer.\n */\nMBEDTLS_STATIC_TESTABLE\npsa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len,\n                                   uint8_t *input_copy, size_t input_copy_len)\n{\n    if (input_len > input_copy_len) {\n        return PSA_ERROR_CORRUPTION_DETECTED;\n    }\n\n#if defined(MBEDTLS_TEST_HOOKS)\n    if (psa_input_pre_copy_hook != NULL) {\n        psa_input_pre_copy_hook(input, input_len);\n    }\n#endif\n\n    if (input_len > 0) {\n        memcpy(input_copy, input, input_len);\n    }\n\n#if defined(MBEDTLS_TEST_HOOKS)\n    if (psa_input_post_copy_hook != NULL) {\n        psa_input_post_copy_hook(input, input_len);\n    }\n#endif\n\n    return PSA_SUCCESS;\n}\n\n/** Copy from a local output buffer into a user-supplied one.\n *\n * \\param[in] output_copy       Pointer to a local buffer containing the output.\n * \\param[in] output_copy_len   Length of the local buffer.\n * \\param[out] output           Pointer to user-supplied output buffer.\n * \\param[out] output_len       Length of the user-supplied output buffer.\n * \\return                      #PSA_SUCCESS, if the buffer was successfully\n *                              copied.\n * \\return                      #PSA_ERROR_BUFFER_TOO_SMALL, if the\n *                              user-supplied output buffer is too small to\n *                              hold the contents of the local buffer.\n */\nMBEDTLS_STATIC_TESTABLE\npsa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len,\n                                    uint8_t *output, size_t output_len)\n{\n    if (output_len < output_copy_len) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n\n#if defined(MBEDTLS_TEST_HOOKS)\n    if (psa_output_pre_copy_hook != NULL) {\n        psa_output_pre_copy_hook(output, output_len);\n    }\n#endif\n\n    if (output_copy_len > 0) {\n        memcpy(output, output_copy, output_copy_len);\n    }\n\n#if defined(MBEDTLS_TEST_HOOKS)\n    if (psa_output_post_copy_hook != NULL) {\n        psa_output_post_copy_hook(output, output_len);\n    }\n#endif\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len,\n                                          psa_crypto_local_input_t *local_input)\n{\n    psa_status_t status;\n\n    *local_input = PSA_CRYPTO_LOCAL_INPUT_INIT;\n\n    if (input_len == 0) {\n        return PSA_SUCCESS;\n    }\n\n    local_input->buffer = mbedtls_calloc(input_len, 1);\n    if (local_input->buffer == NULL) {\n        /* Since we dealt with the zero-length case above, we know that\n         * a NULL return value means a failure of allocation. */\n        return PSA_ERROR_INSUFFICIENT_MEMORY;\n    }\n    /* From now on, we must free local_input->buffer on error. */\n\n    local_input->length = input_len;\n\n    status = psa_crypto_copy_input(input, input_len,\n                                   local_input->buffer, local_input->length);\n    if (status != PSA_SUCCESS) {\n        goto error;\n    }\n\n    return PSA_SUCCESS;\n\nerror:\n    mbedtls_zeroize_and_free(local_input->buffer, local_input->length);\n    local_input->buffer = NULL;\n    local_input->length = 0;\n    return status;\n}\n\nvoid psa_crypto_local_input_free(psa_crypto_local_input_t *local_input)\n{\n    mbedtls_zeroize_and_free(local_input->buffer, local_input->length);\n    local_input->buffer = NULL;\n    local_input->length = 0;\n}\n\npsa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len,\n                                           psa_crypto_local_output_t *local_output)\n{\n    *local_output = PSA_CRYPTO_LOCAL_OUTPUT_INIT;\n\n    if (output_len == 0) {\n        return PSA_SUCCESS;\n    }\n    local_output->buffer = mbedtls_calloc(output_len, 1);\n    if (local_output->buffer == NULL) {\n        /* Since we dealt with the zero-length case above, we know that\n         * a NULL return value means a failure of allocation. */\n        return PSA_ERROR_INSUFFICIENT_MEMORY;\n    }\n    local_output->length = output_len;\n    local_output->original = output;\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output)\n{\n    psa_status_t status;\n\n    if (local_output->buffer == NULL) {\n        local_output->length = 0;\n        return PSA_SUCCESS;\n    }\n    if (local_output->original == NULL) {\n        /* We have an internal copy but nothing to copy back to. */\n        return PSA_ERROR_CORRUPTION_DETECTED;\n    }\n\n    status = psa_crypto_copy_output(local_output->buffer, local_output->length,\n                                    local_output->original, local_output->length);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    mbedtls_zeroize_and_free(local_output->buffer, local_output->length);\n    local_output->buffer = NULL;\n    local_output->length = 0;\n\n    return PSA_SUCCESS;\n}\n\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_aead.c",
    "content": "/*\n *  PSA AEAD entry points\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n\n#include \"psa_crypto_aead.h\"\n#include \"psa_crypto_core.h\"\n#include \"psa_crypto_cipher.h\"\n\n#include <string.h>\n#include \"mbedtls/platform.h\"\n\n#include \"mbedtls/ccm.h\"\n#include \"mbedtls/chachapoly.h\"\n#include \"mbedtls/cipher.h\"\n#include \"mbedtls/gcm.h\"\n#include \"mbedtls/error.h\"\n\nstatic psa_status_t psa_aead_setup(\n    mbedtls_psa_aead_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_cipher_id_t cipher_id;\n    mbedtls_cipher_mode_t mode;\n    size_t key_bits = attributes->bits;\n    (void) key_buffer_size;\n\n    status = mbedtls_cipher_values_from_psa(alg, attributes->type,\n                                            &key_bits, &mode, &cipher_id);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)\n        case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):\n            operation->alg = PSA_ALG_CCM;\n            /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.\n             * The call to mbedtls_ccm_encrypt_and_tag or\n             * mbedtls_ccm_auth_decrypt will validate the tag length. */\n            if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) {\n                return PSA_ERROR_INVALID_ARGUMENT;\n            }\n\n            mbedtls_ccm_init(&operation->ctx.ccm);\n            status = mbedtls_to_psa_error(\n                mbedtls_ccm_setkey(&operation->ctx.ccm, cipher_id,\n                                   key_buffer, (unsigned int) key_bits));\n            if (status != PSA_SUCCESS) {\n                return status;\n            }\n            break;\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)\n        case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):\n            operation->alg = PSA_ALG_GCM;\n            /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.\n             * The call to mbedtls_gcm_crypt_and_tag or\n             * mbedtls_gcm_auth_decrypt will validate the tag length. */\n            if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) {\n                return PSA_ERROR_INVALID_ARGUMENT;\n            }\n\n            mbedtls_gcm_init(&operation->ctx.gcm);\n            status = mbedtls_to_psa_error(\n                mbedtls_gcm_setkey(&operation->ctx.gcm, cipher_id,\n                                   key_buffer, (unsigned int) key_bits));\n            if (status != PSA_SUCCESS) {\n                return status;\n            }\n            break;\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)\n        case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):\n            operation->alg = PSA_ALG_CHACHA20_POLY1305;\n            /* We only support the default tag length. */\n            if (alg != PSA_ALG_CHACHA20_POLY1305) {\n                return PSA_ERROR_NOT_SUPPORTED;\n            }\n\n            mbedtls_chachapoly_init(&operation->ctx.chachapoly);\n            status = mbedtls_to_psa_error(\n                mbedtls_chachapoly_setkey(&operation->ctx.chachapoly,\n                                          key_buffer));\n            if (status != PSA_SUCCESS) {\n                return status;\n            }\n            break;\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */\n\n        default:\n            (void) status;\n            (void) key_buffer;\n            return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    operation->key_type = psa_get_key_type(attributes);\n\n    operation->tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t mbedtls_psa_aead_encrypt(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *nonce, size_t nonce_length,\n    const uint8_t *additional_data, size_t additional_data_length,\n    const uint8_t *plaintext, size_t plaintext_length,\n    uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;\n    uint8_t *tag;\n\n    status = psa_aead_setup(&operation, attributes, key_buffer,\n                            key_buffer_size, alg);\n\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    /* For all currently supported modes, the tag is at the end of the\n     * ciphertext. */\n    if (ciphertext_size < (plaintext_length + operation.tag_length)) {\n        status = PSA_ERROR_BUFFER_TOO_SMALL;\n        goto exit;\n    }\n    tag = ciphertext + plaintext_length;\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)\n    if (operation.alg == PSA_ALG_CCM) {\n        status = mbedtls_to_psa_error(\n            mbedtls_ccm_encrypt_and_tag(&operation.ctx.ccm,\n                                        plaintext_length,\n                                        nonce, nonce_length,\n                                        additional_data,\n                                        additional_data_length,\n                                        plaintext, ciphertext,\n                                        tag, operation.tag_length));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)\n    if (operation.alg == PSA_ALG_GCM) {\n        status = mbedtls_to_psa_error(\n            mbedtls_gcm_crypt_and_tag(&operation.ctx.gcm,\n                                      MBEDTLS_GCM_ENCRYPT,\n                                      plaintext_length,\n                                      nonce, nonce_length,\n                                      additional_data, additional_data_length,\n                                      plaintext, ciphertext,\n                                      operation.tag_length, tag));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)\n    if (operation.alg == PSA_ALG_CHACHA20_POLY1305) {\n        if (operation.tag_length != 16) {\n            status = PSA_ERROR_NOT_SUPPORTED;\n            goto exit;\n        }\n        status = mbedtls_to_psa_error(\n            mbedtls_chachapoly_encrypt_and_tag(&operation.ctx.chachapoly,\n                                               plaintext_length,\n                                               nonce,\n                                               additional_data,\n                                               additional_data_length,\n                                               plaintext,\n                                               ciphertext,\n                                               tag));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */\n    {\n        (void) tag;\n        (void) nonce;\n        (void) nonce_length;\n        (void) additional_data;\n        (void) additional_data_length;\n        (void) plaintext;\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    if (status == PSA_SUCCESS) {\n        *ciphertext_length = plaintext_length + operation.tag_length;\n    }\n\nexit:\n    mbedtls_psa_aead_abort(&operation);\n\n    return status;\n}\n\n/* Locate the tag in a ciphertext buffer containing the encrypted data\n * followed by the tag. Return the length of the part preceding the tag in\n * *plaintext_length. This is the size of the plaintext in modes where\n * the encrypted data has the same size as the plaintext, such as\n * CCM and GCM. */\nstatic psa_status_t psa_aead_unpadded_locate_tag(size_t tag_length,\n                                                 const uint8_t *ciphertext,\n                                                 size_t ciphertext_length,\n                                                 size_t plaintext_size,\n                                                 const uint8_t **p_tag)\n{\n    size_t payload_length;\n    if (tag_length > ciphertext_length) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n    payload_length = ciphertext_length - tag_length;\n    if (payload_length > plaintext_size) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n    *p_tag = ciphertext + payload_length;\n    return PSA_SUCCESS;\n}\n\npsa_status_t mbedtls_psa_aead_decrypt(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *nonce, size_t nonce_length,\n    const uint8_t *additional_data, size_t additional_data_length,\n    const uint8_t *ciphertext, size_t ciphertext_length,\n    uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;\n    const uint8_t *tag = NULL;\n\n    status = psa_aead_setup(&operation, attributes, key_buffer,\n                            key_buffer_size, alg);\n\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_aead_unpadded_locate_tag(operation.tag_length,\n                                          ciphertext, ciphertext_length,\n                                          plaintext_size, &tag);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)\n    if (operation.alg == PSA_ALG_CCM) {\n        status = mbedtls_to_psa_error(\n            mbedtls_ccm_auth_decrypt(&operation.ctx.ccm,\n                                     ciphertext_length - operation.tag_length,\n                                     nonce, nonce_length,\n                                     additional_data,\n                                     additional_data_length,\n                                     ciphertext, plaintext,\n                                     tag, operation.tag_length));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)\n    if (operation.alg == PSA_ALG_GCM) {\n        status = mbedtls_to_psa_error(\n            mbedtls_gcm_auth_decrypt(&operation.ctx.gcm,\n                                     ciphertext_length - operation.tag_length,\n                                     nonce, nonce_length,\n                                     additional_data,\n                                     additional_data_length,\n                                     tag, operation.tag_length,\n                                     ciphertext, plaintext));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)\n    if (operation.alg == PSA_ALG_CHACHA20_POLY1305) {\n        if (operation.tag_length != 16) {\n            status = PSA_ERROR_NOT_SUPPORTED;\n            goto exit;\n        }\n        status = mbedtls_to_psa_error(\n            mbedtls_chachapoly_auth_decrypt(&operation.ctx.chachapoly,\n                                            ciphertext_length - operation.tag_length,\n                                            nonce,\n                                            additional_data,\n                                            additional_data_length,\n                                            tag,\n                                            ciphertext,\n                                            plaintext));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */\n    {\n        (void) nonce;\n        (void) nonce_length;\n        (void) additional_data;\n        (void) additional_data_length;\n        (void) plaintext;\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    if (status == PSA_SUCCESS) {\n        *plaintext_length = ciphertext_length - operation.tag_length;\n    }\n\nexit:\n    mbedtls_psa_aead_abort(&operation);\n\n    if (status == PSA_SUCCESS) {\n        *plaintext_length = ciphertext_length - operation.tag_length;\n    }\n    return status;\n}\n\n/* Set the key and algorithm for a multipart authenticated encryption\n * operation. */\npsa_status_t mbedtls_psa_aead_encrypt_setup(\n    mbedtls_psa_aead_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    status = psa_aead_setup(operation, attributes, key_buffer,\n                            key_buffer_size, alg);\n\n    if (status == PSA_SUCCESS) {\n        operation->is_encrypt = 1;\n    }\n\n    return status;\n}\n\n/* Set the key and algorithm for a multipart authenticated decryption\n * operation. */\npsa_status_t mbedtls_psa_aead_decrypt_setup(\n    mbedtls_psa_aead_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    status = psa_aead_setup(operation, attributes, key_buffer,\n                            key_buffer_size, alg);\n\n    if (status == PSA_SUCCESS) {\n        operation->is_encrypt = 0;\n    }\n\n    return status;\n}\n\n/* Set a nonce for the multipart AEAD operation*/\npsa_status_t mbedtls_psa_aead_set_nonce(\n    mbedtls_psa_aead_operation_t *operation,\n    const uint8_t *nonce,\n    size_t nonce_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)\n    if (operation->alg == PSA_ALG_GCM) {\n        status = mbedtls_to_psa_error(\n            mbedtls_gcm_starts(&operation->ctx.gcm,\n                               operation->is_encrypt ?\n                               MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT,\n                               nonce,\n                               nonce_length));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)\n    if (operation->alg == PSA_ALG_CCM) {\n        status = mbedtls_to_psa_error(\n            mbedtls_ccm_starts(&operation->ctx.ccm,\n                               operation->is_encrypt ?\n                               MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT,\n                               nonce,\n                               nonce_length));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)\n    if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {\n        /* Note - ChaChaPoly allows an 8 byte nonce, but we would have to\n         * allocate a buffer in the operation, copy the nonce to it and pad\n         * it, so for now check the nonce is 12 bytes, as\n         * mbedtls_chachapoly_starts() assumes it can read 12 bytes from the\n         * passed in buffer. */\n        if (nonce_length != 12) {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n\n        status = mbedtls_to_psa_error(\n            mbedtls_chachapoly_starts(&operation->ctx.chachapoly,\n                                      nonce,\n                                      operation->is_encrypt ?\n                                      MBEDTLS_CHACHAPOLY_ENCRYPT :\n                                      MBEDTLS_CHACHAPOLY_DECRYPT));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */\n    {\n        (void) operation;\n        (void) nonce;\n        (void) nonce_length;\n\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    return status;\n}\n\n/* Declare the lengths of the message and additional data for AEAD. */\npsa_status_t mbedtls_psa_aead_set_lengths(\n    mbedtls_psa_aead_operation_t *operation,\n    size_t ad_length,\n    size_t plaintext_length)\n{\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)\n    if (operation->alg == PSA_ALG_CCM) {\n        return mbedtls_to_psa_error(\n            mbedtls_ccm_set_lengths(&operation->ctx.ccm,\n                                    ad_length,\n                                    plaintext_length,\n                                    operation->tag_length));\n\n    }\n#else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */\n    (void) operation;\n    (void) ad_length;\n    (void) plaintext_length;\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */\n\n    return PSA_SUCCESS;\n}\n\n/* Pass additional data to an active multipart AEAD operation. */\npsa_status_t mbedtls_psa_aead_update_ad(\n    mbedtls_psa_aead_operation_t *operation,\n    const uint8_t *input,\n    size_t input_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)\n    if (operation->alg == PSA_ALG_GCM) {\n        status = mbedtls_to_psa_error(\n            mbedtls_gcm_update_ad(&operation->ctx.gcm, input, input_length));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)\n    if (operation->alg == PSA_ALG_CCM) {\n        status = mbedtls_to_psa_error(\n            mbedtls_ccm_update_ad(&operation->ctx.ccm, input, input_length));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)\n    if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {\n        status = mbedtls_to_psa_error(\n            mbedtls_chachapoly_update_aad(&operation->ctx.chachapoly,\n                                          input,\n                                          input_length));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */\n    {\n        (void) operation;\n        (void) input;\n        (void) input_length;\n\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    return status;\n}\n\n/* Encrypt or decrypt a message fragment in an active multipart AEAD\n * operation.*/\npsa_status_t mbedtls_psa_aead_update(\n    mbedtls_psa_aead_operation_t *operation,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *output,\n    size_t output_size,\n    size_t *output_length)\n{\n    size_t update_output_length;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    update_output_length = input_length;\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)\n    if (operation->alg == PSA_ALG_GCM) {\n        status =  mbedtls_to_psa_error(\n            mbedtls_gcm_update(&operation->ctx.gcm,\n                               input, input_length,\n                               output, output_size,\n                               &update_output_length));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)\n    if (operation->alg == PSA_ALG_CCM) {\n        if (output_size < input_length) {\n            return PSA_ERROR_BUFFER_TOO_SMALL;\n        }\n\n        status = mbedtls_to_psa_error(\n            mbedtls_ccm_update(&operation->ctx.ccm,\n                               input, input_length,\n                               output, output_size,\n                               &update_output_length));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)\n    if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {\n        if (output_size < input_length) {\n            return PSA_ERROR_BUFFER_TOO_SMALL;\n        }\n\n        status = mbedtls_to_psa_error(\n            mbedtls_chachapoly_update(&operation->ctx.chachapoly,\n                                      input_length,\n                                      input,\n                                      output));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */\n    {\n        (void) operation;\n        (void) input;\n        (void) output;\n        (void) output_size;\n\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    if (status == PSA_SUCCESS) {\n        *output_length = update_output_length;\n    }\n\n    return status;\n}\n\n/* Finish encrypting a message in a multipart AEAD operation. */\npsa_status_t mbedtls_psa_aead_finish(\n    mbedtls_psa_aead_operation_t *operation,\n    uint8_t *ciphertext,\n    size_t ciphertext_size,\n    size_t *ciphertext_length,\n    uint8_t *tag,\n    size_t tag_size,\n    size_t *tag_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t finish_output_size = 0;\n\n    if (tag_size < operation->tag_length) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)\n    if (operation->alg == PSA_ALG_GCM) {\n        status =  mbedtls_to_psa_error(\n            mbedtls_gcm_finish(&operation->ctx.gcm,\n                               ciphertext, ciphertext_size, ciphertext_length,\n                               tag, operation->tag_length));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)\n    if (operation->alg == PSA_ALG_CCM) {\n        /* tag must be big enough to store a tag of size passed into set\n         * lengths. */\n        if (tag_size < operation->tag_length) {\n            return PSA_ERROR_BUFFER_TOO_SMALL;\n        }\n\n        status = mbedtls_to_psa_error(\n            mbedtls_ccm_finish(&operation->ctx.ccm,\n                               tag, operation->tag_length));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)\n    if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {\n        /* Belt and braces. Although the above tag_size check should have\n         * already done this, if we later start supporting smaller tag sizes\n         * for chachapoly, then passing a tag buffer smaller than 16 into here\n         * could cause a buffer overflow, so better safe than sorry. */\n        if (tag_size < 16) {\n            return PSA_ERROR_BUFFER_TOO_SMALL;\n        }\n\n        status = mbedtls_to_psa_error(\n            mbedtls_chachapoly_finish(&operation->ctx.chachapoly,\n                                      tag));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */\n    {\n        (void) ciphertext;\n        (void) ciphertext_size;\n        (void) ciphertext_length;\n        (void) tag;\n        (void) tag_size;\n        (void) tag_length;\n\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    if (status == PSA_SUCCESS) {\n        /* This will be zero for all supported algorithms currently, but left\n         * here for future support. */\n        *ciphertext_length = finish_output_size;\n        *tag_length = operation->tag_length;\n    }\n\n    return status;\n}\n\n/* Abort an AEAD operation */\npsa_status_t mbedtls_psa_aead_abort(\n    mbedtls_psa_aead_operation_t *operation)\n{\n    switch (operation->alg) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)\n        case PSA_ALG_CCM:\n            mbedtls_ccm_free(&operation->ctx.ccm);\n            break;\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)\n        case PSA_ALG_GCM:\n            mbedtls_gcm_free(&operation->ctx.gcm);\n            break;\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)\n        case PSA_ALG_CHACHA20_POLY1305:\n            mbedtls_chachapoly_free(&operation->ctx.chachapoly);\n            break;\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */\n    }\n\n    operation->is_encrypt = 0;\n\n    return PSA_SUCCESS;\n}\n\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_aead.h",
    "content": "/*\n *  PSA AEAD driver entry points\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_AEAD_H\n#define PSA_CRYPTO_AEAD_H\n\n#include <psa/crypto.h>\n\n/**\n * \\brief Process an authenticated encryption operation.\n *\n * \\note The signature of this function is that of a PSA driver\n *       aead_encrypt entry point. This function behaves as an aead_encrypt\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in]  attributes         The attributes of the key to use for the\n *                                operation.\n * \\param[in]  key_buffer         The buffer containing the key context.\n * \\param      key_buffer_size    Size of the \\p key_buffer buffer in bytes.\n * \\param      alg                The AEAD algorithm to compute.\n * \\param[in]  nonce              Nonce or IV to use.\n * \\param      nonce_length       Size of the nonce buffer in bytes. This must\n *                                be appropriate for the selected algorithm.\n *                                The default nonce size is\n *                                PSA_AEAD_NONCE_LENGTH(key_type, alg) where\n *                                key_type is the type of key.\n * \\param[in]  additional_data    Additional data that will be authenticated\n *                                but not encrypted.\n * \\param      additional_data_length  Size of additional_data in bytes.\n * \\param[in]  plaintext          Data that will be authenticated and encrypted.\n * \\param      plaintext_length   Size of plaintext in bytes.\n * \\param[out] ciphertext         Output buffer for the authenticated and\n *                                encrypted data. The additional data is not\n *                                part of this output. For algorithms where the\n *                                encrypted data and the authentication tag are\n *                                defined as separate outputs, the\n *                                authentication tag is appended to the\n *                                encrypted data.\n * \\param      ciphertext_size    Size of the ciphertext buffer in bytes. This\n *                                must be appropriate for the selected algorithm\n *                                and key:\n *                                - A sufficient output size is\n *                                  PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg,\n *                                  plaintext_length) where key_type is the type\n *                                  of key.\n *                                - PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\n *                                  plaintext_length) evaluates to the maximum\n *                                  ciphertext size of any supported AEAD\n *                                  encryption.\n * \\param[out] ciphertext_length  On success, the size of the output in the\n *                                ciphertext buffer.\n *\n * \\retval #PSA_SUCCESS Success.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         ciphertext_size is too small.\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_aead_encrypt(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *nonce, size_t nonce_length,\n    const uint8_t *additional_data, size_t additional_data_length,\n    const uint8_t *plaintext, size_t plaintext_length,\n    uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length);\n\n/**\n * \\brief Process an authenticated decryption operation.\n *\n * \\note The signature of this function is that of a PSA driver\n *       aead_decrypt entry point. This function behaves as an aead_decrypt\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in]  attributes         The attributes of the key to use for the\n *                                operation.\n * \\param[in]  key_buffer         The buffer containing the key context.\n * \\param      key_buffer_size    Size of the \\p key_buffer buffer in bytes.\n * \\param      alg                The AEAD algorithm to compute.\n * \\param[in]  nonce              Nonce or IV to use.\n * \\param      nonce_length       Size of the nonce buffer in bytes. This must\n *                                be appropriate for the selected algorithm.\n *                                The default nonce size is\n *                                PSA_AEAD_NONCE_LENGTH(key_type, alg) where\n *                                key_type is the type of key.\n * \\param[in]  additional_data    Additional data that has been authenticated\n *                                but not encrypted.\n * \\param      additional_data_length  Size of additional_data in bytes.\n * \\param[in]  ciphertext         Data that has been authenticated and\n *                                encrypted. For algorithms where the encrypted\n *                                data and the authentication tag are defined\n *                                as separate inputs, the buffer contains\n *                                encrypted data followed by the authentication\n *                                tag.\n * \\param      ciphertext_length  Size of ciphertext in bytes.\n * \\param[out] plaintext          Output buffer for the decrypted data.\n * \\param      plaintext_size     Size of the plaintext buffer in bytes. This\n *                                must be appropriate for the selected algorithm\n *                                and key:\n *                                - A sufficient output size is\n *                                  PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg,\n *                                  ciphertext_length) where key_type is the\n *                                  type of key.\n *                                - PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\n *                                  ciphertext_length) evaluates to the maximum\n *                                  plaintext size of any supported AEAD\n *                                  decryption.\n * \\param[out] plaintext_length   On success, the size of the output in the\n *                                plaintext buffer.\n *\n * \\retval #PSA_SUCCESS Success.\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The cipher is not authentic.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         plaintext_size is too small.\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_aead_decrypt(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *nonce, size_t nonce_length,\n    const uint8_t *additional_data, size_t additional_data_length,\n    const uint8_t *ciphertext, size_t ciphertext_length,\n    uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length);\n\n/** Set the key for a multipart authenticated encryption operation.\n *\n *  \\note The signature of this function is that of a PSA driver\n *       aead_encrypt_setup entry point. This function behaves as an\n *       aead_encrypt_setup entry point as defined in the PSA driver interface\n *       specification for transparent drivers.\n *\n * If an error occurs at any step after a call to\n * mbedtls_psa_aead_encrypt_setup(), the operation is reset by the PSA core by a\n * call to mbedtls_psa_aead_abort(). The PSA core may call\n * mbedtls_psa_aead_abort() at any time after the operation has been\n * initialized, and is required to when the operation is no longer needed.\n *\n * \\param[in,out] operation     The operation object to set up. It must have\n *                              been initialized as per the documentation for\n *                              #mbedtls_psa_aead_operation_t and not yet in\n *                              use.\n * \\param[in]  attributes       The attributes of the key to use for the\n *                              operation.\n * \\param[in]  key_buffer       The buffer containing the key context.\n * \\param      key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n                                It must be consistent with the size in bits\n                                recorded in \\p attributes.\n * \\param alg                   The AEAD algorithm to compute\n *                              (\\c PSA_ALG_XXX value such that\n *                              #PSA_ALG_IS_AEAD(\\p alg) is true).\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         An invalid block length was supplied.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY\n *         Failed to allocate memory for key material\n */\npsa_status_t mbedtls_psa_aead_encrypt_setup(\n    mbedtls_psa_aead_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg);\n\n/** Set the key for a multipart authenticated decryption operation.\n *\n * \\note The signature of this function is that of a PSA driver\n *       aead_decrypt_setup entry point. This function behaves as an\n *       aead_decrypt_setup entry point as defined in the PSA driver interface\n *       specification for transparent drivers.\n *\n * If an error occurs at any step after a call to\n * mbedtls_psa_aead_decrypt_setup(), the PSA core resets the operation by a\n * call to mbedtls_psa_aead_abort(). The PSA core may call\n * mbedtls_psa_aead_abort() at any time after the operation has been\n * initialized, and is required to when the operation is no longer needed.\n *\n * \\param[in,out] operation     The operation object to set up. It must have\n *                              been initialized as per the documentation for\n *                              #mbedtls_psa_aead_operation_t and not yet in\n *                              use.\n * \\param[in]  attributes       The attributes of the key to use for the\n *                              operation.\n * \\param[in]  key_buffer       The buffer containing the key context.\n * \\param      key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n                                It must be consistent with the size in bits\n                                recorded in \\p attributes.\n * \\param alg                   The AEAD algorithm to compute\n *                              (\\c PSA_ALG_XXX value such that\n *                              #PSA_ALG_IS_AEAD(\\p alg) is true).\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         An invalid block length was supplied.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY\n *         Failed to allocate memory for key material\n */\npsa_status_t mbedtls_psa_aead_decrypt_setup(\n    mbedtls_psa_aead_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg);\n\n/** Set the nonce for an authenticated encryption or decryption operation.\n *\n * \\note The signature of this function is that of a PSA driver aead_set_nonce\n *       entry point. This function behaves as an aead_set_nonce entry point as\n *       defined in the PSA driver interface specification for transparent\n *       drivers.\n *\n * This function sets the nonce for the authenticated\n * encryption or decryption operation.\n *\n * The PSA core calls mbedtls_psa_aead_encrypt_setup() or\n * mbedtls_psa_aead_decrypt_setup() before calling this function.\n *\n * If this function returns an error status, the PSA core will call\n * mbedtls_psa_aead_abort().\n *\n * \\param[in,out] operation     Active AEAD operation.\n * \\param[in] nonce             Buffer containing the nonce to use.\n * \\param nonce_length          Size of the nonce in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The size of \\p nonce is not acceptable for the chosen algorithm.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         Algorithm previously set is not supported in this configuration of\n *         the library.\n */\npsa_status_t mbedtls_psa_aead_set_nonce(\n    mbedtls_psa_aead_operation_t *operation,\n    const uint8_t *nonce,\n    size_t nonce_length);\n\n/** Declare the lengths of the message and additional data for AEAD.\n *\n * \\note The signature of this function is that of a PSA driver aead_set_lengths\n *       entry point. This function behaves as an aead_set_lengths entry point\n *       as defined in the PSA driver interface specification for transparent\n *       drivers.\n *\n * The PSA core calls this function before calling mbedtls_psa_aead_update_ad()\n * or mbedtls_psa_aead_update() if the algorithm for the operation requires it.\n * If the algorithm does not require it, calling this function is optional, but\n * if this function is called then the implementation must enforce the lengths.\n *\n * The PSA core may call this function before or after setting the nonce with\n * mbedtls_psa_aead_set_nonce().\n *\n * - For #PSA_ALG_CCM, calling this function is required.\n * - For the other AEAD algorithms defined in this specification, calling\n *   this function is not required.\n *\n * If this function returns an error status, the PSA core calls\n * mbedtls_psa_aead_abort().\n *\n * \\param[in,out] operation     Active AEAD operation.\n * \\param ad_length             Size of the non-encrypted additional\n *                              authenticated data in bytes.\n * \\param plaintext_length      Size of the plaintext to encrypt in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         At least one of the lengths is not acceptable for the chosen\n *         algorithm.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         Algorithm previously set is not supported in this configuration of\n *         the library.\n */\npsa_status_t mbedtls_psa_aead_set_lengths(\n    mbedtls_psa_aead_operation_t *operation,\n    size_t ad_length,\n    size_t plaintext_length);\n\n/** Pass additional data to an active AEAD operation.\n *\n *  \\note The signature of this function is that of a PSA driver\n *       aead_update_ad entry point. This function behaves as an aead_update_ad\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * Additional data is authenticated, but not encrypted.\n *\n * The PSA core can call this function multiple times to pass successive\n * fragments of the additional data. It will not call this function after\n * passing data to encrypt or decrypt with mbedtls_psa_aead_update().\n *\n * Before calling this function, the PSA core will:\n *    1. Call either mbedtls_psa_aead_encrypt_setup() or\n *       mbedtls_psa_aead_decrypt_setup().\n *    2. Set the nonce with mbedtls_psa_aead_set_nonce().\n *\n * If this function returns an error status, the PSA core will call\n * mbedtls_psa_aead_abort().\n *\n * \\param[in,out] operation     Active AEAD operation.\n * \\param[in] input             Buffer containing the fragment of\n *                              additional data.\n * \\param input_length          Size of the \\p input buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         Algorithm previously set is not supported in this configuration of\n *         the library.\n */\npsa_status_t mbedtls_psa_aead_update_ad(\n    mbedtls_psa_aead_operation_t *operation,\n    const uint8_t *input,\n    size_t input_length);\n\n/** Encrypt or decrypt a message fragment in an active AEAD operation.\n *\n *  \\note The signature of this function is that of a PSA driver\n *       aead_update entry point. This function behaves as an aead_update entry\n *       point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * Before calling this function, the PSA core will:\n *    1. Call either mbedtls_psa_aead_encrypt_setup() or\n *       mbedtls_psa_aead_decrypt_setup(). The choice of setup function\n *       determines whether this function encrypts or decrypts its input.\n *    2. Set the nonce with mbedtls_psa_aead_set_nonce().\n *    3. Call mbedtls_psa_aead_update_ad() to pass all the additional data.\n *\n * If this function returns an error status, the PSA core will call\n * mbedtls_psa_aead_abort().\n *\n * This function does not require the input to be aligned to any\n * particular block boundary. If the implementation can only process\n * a whole block at a time, it must consume all the input provided, but\n * it may delay the end of the corresponding output until a subsequent\n * call to mbedtls_psa_aead_update(), mbedtls_psa_aead_finish() provides\n * sufficient input. The amount of data that can be delayed in this way is\n * bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE.\n *\n * \\param[in,out] operation     Active AEAD operation.\n * \\param[in] input             Buffer containing the message fragment to\n *                              encrypt or decrypt.\n * \\param input_length          Size of the \\p input buffer in bytes.\n * \\param[out] output           Buffer where the output is to be written.\n * \\param output_size           Size of the \\p output buffer in bytes.\n *                              This must be appropriate for the selected\n *                                algorithm and key:\n *                                - A sufficient output size is\n *                                  #PSA_AEAD_UPDATE_OUTPUT_SIZE(\\c key_type,\n *                                  \\c alg, \\p input_length) where\n *                                  \\c key_type is the type of key and \\c alg is\n *                                  the algorithm that were used to set up the\n *                                  operation.\n *                                - #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\\p\n *                                  input_length) evaluates to the maximum\n *                                  output size of any supported AEAD\n *                                  algorithm.\n * \\param[out] output_length    On success, the number of bytes\n *                              that make up the returned output.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n *\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p output buffer is too small.\n *         #PSA_AEAD_UPDATE_OUTPUT_SIZE(\\c key_type, \\c alg, \\p input_length) or\n *         #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\\p input_length) can be used to\n *         determine the required buffer size.\n */\npsa_status_t mbedtls_psa_aead_update(\n    mbedtls_psa_aead_operation_t *operation,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *output,\n    size_t output_size,\n    size_t *output_length);\n\n/** Finish encrypting a message in an AEAD operation.\n *\n *  \\note The signature of this function is that of a PSA driver\n *       aead_finish entry point. This function behaves as an aead_finish entry\n *       point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * The operation must have been set up by the PSA core with\n * mbedtls_psa_aead_encrypt_setup().\n *\n * This function finishes the authentication of the additional data\n * formed by concatenating the inputs passed to preceding calls to\n * mbedtls_psa_aead_update_ad() with the plaintext formed by concatenating the\n * inputs passed to preceding calls to mbedtls_psa_aead_update().\n *\n * This function has two output buffers:\n * - \\p ciphertext contains trailing ciphertext that was buffered from\n *   preceding calls to mbedtls_psa_aead_update().\n * - \\p tag contains the authentication tag.\n *\n * Whether or not this function returns successfully, the PSA core subsequently\n * calls mbedtls_psa_aead_abort() to deactivate the operation.\n *\n * \\param[in,out] operation     Active AEAD operation.\n * \\param[out] ciphertext       Buffer where the last part of the ciphertext\n *                              is to be written.\n * \\param ciphertext_size       Size of the \\p ciphertext buffer in bytes.\n *                              This must be appropriate for the selected\n *                              algorithm and key:\n *                              - A sufficient output size is\n *                                #PSA_AEAD_FINISH_OUTPUT_SIZE(\\c key_type,\n *                                \\c alg) where \\c key_type is the type of key\n *                                and \\c alg is the algorithm that were used to\n *                                set up the operation.\n *                              - #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE evaluates to\n *                                the maximum output size of any supported AEAD\n *                                algorithm.\n * \\param[out] ciphertext_length On success, the number of bytes of\n *                              returned ciphertext.\n * \\param[out] tag              Buffer where the authentication tag is\n *                              to be written.\n * \\param tag_size              Size of the \\p tag buffer in bytes.\n *                              This must be appropriate for the selected\n *                              algorithm and key:\n *                              - The exact tag size is #PSA_AEAD_TAG_LENGTH(\\c\n *                                key_type, \\c key_bits, \\c alg) where\n *                                \\c key_type and \\c key_bits are the type and\n *                                bit-size of the key, and \\c alg are the\n *                                algorithm that were used in the call to\n *                                mbedtls_psa_aead_encrypt_setup().\n *                              - #PSA_AEAD_TAG_MAX_SIZE evaluates to the\n *                                maximum tag size of any supported AEAD\n *                                algorithm.\n * \\param[out] tag_length       On success, the number of bytes\n *                              that make up the returned tag.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p tag buffer is too small.\n *         #PSA_AEAD_TAG_LENGTH(\\c key_type, key_bits, \\c alg) or\n *         #PSA_AEAD_TAG_MAX_SIZE can be used to determine the required \\p tag\n *         buffer size.\n */\npsa_status_t mbedtls_psa_aead_finish(\n    mbedtls_psa_aead_operation_t *operation,\n    uint8_t *ciphertext,\n    size_t ciphertext_size,\n    size_t *ciphertext_length,\n    uint8_t *tag,\n    size_t tag_size,\n    size_t *tag_length);\n\n/** Abort an AEAD operation.\n *\n *  \\note The signature of this function is that of a PSA driver\n *       aead_abort entry point. This function behaves as an aead_abort entry\n *       point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * Aborting an operation frees all associated resources except for the\n * \\p operation structure itself. Once aborted, the operation object\n * can be reused for another operation by the PSA core by it calling\n * mbedtls_psa_aead_encrypt_setup() or mbedtls_psa_aead_decrypt_setup() again.\n *\n * The PSA core may call this function any time after the operation object has\n * been initialized as described in #mbedtls_psa_aead_operation_t.\n *\n * In particular, calling mbedtls_psa_aead_abort() after the operation has been\n * terminated by a call to mbedtls_psa_aead_abort() or\n * mbedtls_psa_aead_finish() is safe and has no effect.\n *\n * \\param[in,out] operation     Initialized AEAD operation.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n */\npsa_status_t mbedtls_psa_aead_abort(\n    mbedtls_psa_aead_operation_t *operation);\n\n#endif /* PSA_CRYPTO_AEAD_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_cipher.c",
    "content": "/*\n *  PSA cipher driver entry points\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n\n#include \"psa_crypto_cipher.h\"\n#include \"psa_crypto_core.h\"\n#include \"psa_crypto_random_impl.h\"\n#include \"constant_time_internal.h\"\n\n#include \"mbedtls/cipher.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n/* mbedtls_cipher_values_from_psa() below only checks if the proper build symbols\n * are enabled, but it does not provide any compatibility check between them\n * (i.e. if the specified key works with the specified algorithm). This helper\n * function is meant to provide this support.\n * mbedtls_cipher_info_from_psa() might be used for the same purpose, but it\n * requires CIPHER_C to be enabled.\n */\nstatic psa_status_t mbedtls_cipher_validate_values(\n    psa_algorithm_t alg,\n    psa_key_type_t key_type)\n{\n    /* Reduce code size - hinting to the compiler about what it can assume allows the compiler to\n       eliminate bits of the logic below. */\n#if !defined(PSA_WANT_KEY_TYPE_AES)\n    MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_AES);\n#endif\n#if !defined(PSA_WANT_KEY_TYPE_ARIA)\n    MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_ARIA);\n#endif\n#if !defined(PSA_WANT_KEY_TYPE_CAMELLIA)\n    MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CAMELLIA);\n#endif\n#if !defined(PSA_WANT_KEY_TYPE_CHACHA20)\n    MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CHACHA20);\n#endif\n#if !defined(PSA_WANT_KEY_TYPE_DES)\n    MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_DES);\n#endif\n#if !defined(PSA_WANT_ALG_CCM)\n    MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0));\n#endif\n#if !defined(PSA_WANT_ALG_GCM)\n    MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0));\n#endif\n#if !defined(PSA_WANT_ALG_STREAM_CIPHER)\n    MBEDTLS_ASSUME(alg != PSA_ALG_STREAM_CIPHER);\n#endif\n#if !defined(PSA_WANT_ALG_CHACHA20_POLY1305)\n    MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0));\n#endif\n#if !defined(PSA_WANT_ALG_CCM_STAR_NO_TAG)\n    MBEDTLS_ASSUME(alg != PSA_ALG_CCM_STAR_NO_TAG);\n#endif\n#if !defined(PSA_WANT_ALG_CTR)\n    MBEDTLS_ASSUME(alg != PSA_ALG_CTR);\n#endif\n#if !defined(PSA_WANT_ALG_CFB)\n    MBEDTLS_ASSUME(alg != PSA_ALG_CFB);\n#endif\n#if !defined(PSA_WANT_ALG_OFB)\n    MBEDTLS_ASSUME(alg != PSA_ALG_OFB);\n#endif\n#if !defined(PSA_WANT_ALG_ECB_NO_PADDING)\n    MBEDTLS_ASSUME(alg != PSA_ALG_ECB_NO_PADDING);\n#endif\n#if !defined(PSA_WANT_ALG_CBC_NO_PADDING)\n    MBEDTLS_ASSUME(alg != PSA_ALG_CBC_NO_PADDING);\n#endif\n#if !defined(PSA_WANT_ALG_CBC_PKCS7)\n    MBEDTLS_ASSUME(alg != PSA_ALG_CBC_PKCS7);\n#endif\n#if !defined(PSA_WANT_ALG_CMAC)\n    MBEDTLS_ASSUME(alg != PSA_ALG_CMAC);\n#endif\n\n    if (alg == PSA_ALG_STREAM_CIPHER ||\n        alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0)) {\n        if (key_type == PSA_KEY_TYPE_CHACHA20) {\n            return PSA_SUCCESS;\n        }\n    }\n\n    if (alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0) ||\n        alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0) ||\n        alg == PSA_ALG_CCM_STAR_NO_TAG) {\n        if (key_type == PSA_KEY_TYPE_AES ||\n            key_type == PSA_KEY_TYPE_ARIA ||\n            key_type == PSA_KEY_TYPE_CAMELLIA) {\n            return PSA_SUCCESS;\n        }\n    }\n\n    if (alg == PSA_ALG_CTR ||\n        alg == PSA_ALG_CFB ||\n        alg == PSA_ALG_OFB ||\n        alg == PSA_ALG_XTS ||\n        alg == PSA_ALG_ECB_NO_PADDING ||\n        alg == PSA_ALG_CBC_NO_PADDING ||\n        alg == PSA_ALG_CBC_PKCS7 ||\n        alg == PSA_ALG_CMAC) {\n        if (key_type == PSA_KEY_TYPE_AES ||\n            key_type == PSA_KEY_TYPE_ARIA ||\n            key_type == PSA_KEY_TYPE_DES ||\n            key_type == PSA_KEY_TYPE_CAMELLIA) {\n            return PSA_SUCCESS;\n        }\n    }\n\n    return PSA_ERROR_NOT_SUPPORTED;\n}\n\npsa_status_t mbedtls_cipher_values_from_psa(\n    psa_algorithm_t alg,\n    psa_key_type_t key_type,\n    size_t *key_bits,\n    mbedtls_cipher_mode_t *mode,\n    mbedtls_cipher_id_t *cipher_id)\n{\n    mbedtls_cipher_id_t cipher_id_tmp;\n    /* Only DES modifies key_bits */\n#if !defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)\n    (void) key_bits;\n#endif\n\n    if (PSA_ALG_IS_AEAD(alg)) {\n        alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0);\n    }\n\n    if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) {\n        switch (alg) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER)\n            case PSA_ALG_STREAM_CIPHER:\n                *mode = MBEDTLS_MODE_STREAM;\n                break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR)\n            case PSA_ALG_CTR:\n                *mode = MBEDTLS_MODE_CTR;\n                break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB)\n            case PSA_ALG_CFB:\n                *mode = MBEDTLS_MODE_CFB;\n                break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB)\n            case PSA_ALG_OFB:\n                *mode = MBEDTLS_MODE_OFB;\n                break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)\n            case PSA_ALG_ECB_NO_PADDING:\n                *mode = MBEDTLS_MODE_ECB;\n                break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING)\n            case PSA_ALG_CBC_NO_PADDING:\n                *mode = MBEDTLS_MODE_CBC;\n                break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)\n            case PSA_ALG_CBC_PKCS7:\n                *mode = MBEDTLS_MODE_CBC;\n                break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)\n            case PSA_ALG_CCM_STAR_NO_TAG:\n                *mode = MBEDTLS_MODE_CCM_STAR_NO_TAG;\n                break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)\n            case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):\n                *mode = MBEDTLS_MODE_CCM;\n                break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)\n            case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):\n                *mode = MBEDTLS_MODE_GCM;\n                break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)\n            case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):\n                *mode = MBEDTLS_MODE_CHACHAPOLY;\n                break;\n#endif\n            default:\n                return PSA_ERROR_NOT_SUPPORTED;\n        }\n    } else if (alg == PSA_ALG_CMAC) {\n        *mode = MBEDTLS_MODE_ECB;\n    } else {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    switch (key_type) {\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES)\n        case PSA_KEY_TYPE_AES:\n            cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA)\n        case PSA_KEY_TYPE_ARIA:\n            cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA;\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)\n        case PSA_KEY_TYPE_DES:\n            /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,\n             * and 192 for three-key Triple-DES. */\n            if (*key_bits == 64) {\n                cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;\n            } else {\n                cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;\n            }\n            /* mbedtls doesn't recognize two-key Triple-DES as an algorithm,\n             * but two-key Triple-DES is functionally three-key Triple-DES\n             * with K1=K3, so that's how we present it to mbedtls. */\n            if (*key_bits == 128) {\n                *key_bits = 192;\n            }\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA)\n        case PSA_KEY_TYPE_CAMELLIA:\n            cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20)\n        case PSA_KEY_TYPE_CHACHA20:\n            cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;\n            break;\n#endif\n        default:\n            return PSA_ERROR_NOT_SUPPORTED;\n    }\n    if (cipher_id != NULL) {\n        *cipher_id = cipher_id_tmp;\n    }\n\n    return mbedtls_cipher_validate_values(alg, key_type);\n}\n\n#if defined(MBEDTLS_CIPHER_C)\nconst mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(\n    psa_algorithm_t alg,\n    psa_key_type_t key_type,\n    size_t key_bits,\n    mbedtls_cipher_id_t *cipher_id)\n{\n    mbedtls_cipher_mode_t mode;\n    psa_status_t status;\n    mbedtls_cipher_id_t cipher_id_tmp = MBEDTLS_CIPHER_ID_NONE;\n\n    status = mbedtls_cipher_values_from_psa(alg, key_type, &key_bits, &mode, &cipher_id_tmp);\n    if (status != PSA_SUCCESS) {\n        return NULL;\n    }\n    if (cipher_id != NULL) {\n        *cipher_id = cipher_id_tmp;\n    }\n\n    return mbedtls_cipher_info_from_values(cipher_id_tmp, (int) key_bits, mode);\n}\n#endif /* MBEDTLS_CIPHER_C */\n\n#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)\n\nstatic psa_status_t psa_cipher_setup(\n    mbedtls_psa_cipher_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg,\n    mbedtls_operation_t cipher_operation)\n{\n    int ret = 0;\n    size_t key_bits;\n    const mbedtls_cipher_info_t *cipher_info = NULL;\n    psa_key_type_t key_type = attributes->type;\n\n    (void) key_buffer_size;\n\n    mbedtls_cipher_init(&operation->ctx.cipher);\n\n    operation->alg = alg;\n    key_bits = attributes->bits;\n    cipher_info = mbedtls_cipher_info_from_psa(alg, key_type,\n                                               key_bits, NULL);\n    if (cipher_info == NULL) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info);\n    if (ret != 0) {\n        goto exit;\n    }\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)\n    if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) {\n        /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */\n        uint8_t keys[24];\n        memcpy(keys, key_buffer, 16);\n        memcpy(keys + 16, key_buffer, 8);\n        ret = mbedtls_cipher_setkey(&operation->ctx.cipher,\n                                    keys,\n                                    192, cipher_operation);\n    } else\n#endif\n    {\n        ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer,\n                                    (int) key_bits, cipher_operation);\n    }\n    if (ret != 0) {\n        goto exit;\n    }\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)\n    switch (alg) {\n        case PSA_ALG_CBC_NO_PADDING:\n            ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,\n                                                  MBEDTLS_PADDING_NONE);\n            break;\n        case PSA_ALG_CBC_PKCS7:\n            ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,\n                                                  MBEDTLS_PADDING_PKCS7);\n            break;\n        default:\n            /* The algorithm doesn't involve padding. */\n            ret = 0;\n            break;\n    }\n    if (ret != 0) {\n        goto exit;\n    }\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING ||\n          MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */\n\n    operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :\n                               PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));\n    operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);\n\nexit:\n    return mbedtls_to_psa_error(ret);\n}\n\npsa_status_t mbedtls_psa_cipher_encrypt_setup(\n    mbedtls_psa_cipher_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg)\n{\n    return psa_cipher_setup(operation, attributes,\n                            key_buffer, key_buffer_size,\n                            alg, MBEDTLS_ENCRYPT);\n}\n\npsa_status_t mbedtls_psa_cipher_decrypt_setup(\n    mbedtls_psa_cipher_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg)\n{\n    return psa_cipher_setup(operation, attributes,\n                            key_buffer, key_buffer_size,\n                            alg, MBEDTLS_DECRYPT);\n}\n\npsa_status_t mbedtls_psa_cipher_set_iv(\n    mbedtls_psa_cipher_operation_t *operation,\n    const uint8_t *iv, size_t iv_length)\n{\n    if (iv_length != operation->iv_length) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    return mbedtls_to_psa_error(\n        mbedtls_cipher_set_iv(&operation->ctx.cipher,\n                              iv, iv_length));\n}\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)\n/** Process input for which the algorithm is set to ECB mode.\n *\n * This requires manual processing, since the PSA API is defined as being\n * able to process arbitrary-length calls to psa_cipher_update() with ECB mode,\n * but the underlying mbedtls_cipher_update only takes full blocks.\n *\n * \\param ctx           The mbedtls cipher context to use. It must have been\n *                      set up for ECB.\n * \\param[in] input     The input plaintext or ciphertext to process.\n * \\param input_length  The number of bytes to process from \\p input.\n *                      This does not need to be aligned to a block boundary.\n *                      If there is a partial block at the end of the input,\n *                      it is stored in \\p ctx for future processing.\n * \\param output        The buffer where the output is written. It must be\n *                      at least `BS * floor((p + input_length) / BS)` bytes\n *                      long, where `p` is the number of bytes in the\n *                      unprocessed partial block in \\p ctx (with\n *                      `0 <= p <= BS - 1`) and `BS` is the block size.\n * \\param output_length On success, the number of bytes written to \\p output.\n *                      \\c 0 on error.\n *\n * \\return #PSA_SUCCESS or an error from a hardware accelerator\n */\nstatic psa_status_t psa_cipher_update_ecb(\n    mbedtls_cipher_context_t *ctx,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *output,\n    size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);\n    size_t internal_output_length = 0;\n    *output_length = 0;\n\n    if (input_length == 0) {\n        status = PSA_SUCCESS;\n        goto exit;\n    }\n\n    if (ctx->unprocessed_len > 0) {\n        /* Fill up to block size, and run the block if there's a full one. */\n        size_t bytes_to_copy = block_size - ctx->unprocessed_len;\n\n        if (input_length < bytes_to_copy) {\n            bytes_to_copy = input_length;\n        }\n\n        memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),\n               input, bytes_to_copy);\n        input_length -= bytes_to_copy;\n        input += bytes_to_copy;\n        ctx->unprocessed_len += bytes_to_copy;\n\n        if (ctx->unprocessed_len == block_size) {\n            status = mbedtls_to_psa_error(\n                mbedtls_cipher_update(ctx,\n                                      ctx->unprocessed_data,\n                                      block_size,\n                                      output, &internal_output_length));\n\n            if (status != PSA_SUCCESS) {\n                goto exit;\n            }\n\n            output += internal_output_length;\n            *output_length += internal_output_length;\n            ctx->unprocessed_len = 0;\n        }\n    }\n\n    while (input_length >= block_size) {\n        /* Run all full blocks we have, one by one */\n        status = mbedtls_to_psa_error(\n            mbedtls_cipher_update(ctx, input,\n                                  block_size,\n                                  output, &internal_output_length));\n\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n\n        input_length -= block_size;\n        input += block_size;\n\n        output += internal_output_length;\n        *output_length += internal_output_length;\n    }\n\n    if (input_length > 0) {\n        /* Save unprocessed bytes for later processing */\n        memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),\n               input, input_length);\n        ctx->unprocessed_len += input_length;\n    }\n\n    status = PSA_SUCCESS;\n\nexit:\n    return status;\n}\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */\n\npsa_status_t mbedtls_psa_cipher_update(\n    mbedtls_psa_cipher_operation_t *operation,\n    const uint8_t *input, size_t input_length,\n    uint8_t *output, size_t output_size, size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t expected_output_size;\n\n    if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {\n        /* Take the unprocessed partial block left over from previous\n         * update calls, if any, plus the input to this call. Remove\n         * the last partial block, if any. You get the data that will be\n         * output in this call. */\n        expected_output_size =\n            (operation->ctx.cipher.unprocessed_len + input_length)\n            / operation->block_length * operation->block_length;\n    } else {\n        expected_output_size = input_length;\n    }\n\n    if (output_size < expected_output_size) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)\n    if (operation->alg == PSA_ALG_ECB_NO_PADDING) {\n        /* mbedtls_cipher_update has an API inconsistency: it will only\n         * process a single block at a time in ECB mode. Abstract away that\n         * inconsistency here to match the PSA API behaviour. */\n        status = psa_cipher_update_ecb(&operation->ctx.cipher,\n                                       input,\n                                       input_length,\n                                       output,\n                                       output_length);\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */\n    if (input_length == 0) {\n        /* There is no input, nothing to be done */\n        *output_length = 0;\n        status = PSA_SUCCESS;\n    } else {\n        status = mbedtls_to_psa_error(\n            mbedtls_cipher_update(&operation->ctx.cipher, input,\n                                  input_length, output, output_length));\n\n        if (*output_length > output_size) {\n            return PSA_ERROR_CORRUPTION_DETECTED;\n        }\n    }\n\n    return status;\n}\n\npsa_status_t mbedtls_psa_cipher_finish(\n    mbedtls_psa_cipher_operation_t *operation,\n    uint8_t *output, size_t output_size, size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_GENERIC_ERROR;\n    size_t invalid_padding = 0;\n\n    /* We will copy output_size bytes from temp_output_buffer to the\n     * output buffer. We can't use *output_length to determine how\n     * much to copy because we must not leak that value through timing\n     * when doing decryption with unpadding. But the underlying function\n     * is not guaranteed to write beyond *output_length. To ensure we don't\n     * leak the former content of the stack to the caller, wipe that\n     * former content. */\n    uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH] = { 0 };\n    if (output_size > sizeof(temp_output_buffer)) {\n        output_size = sizeof(temp_output_buffer);\n    }\n\n    if (operation->ctx.cipher.unprocessed_len != 0) {\n        if (operation->alg == PSA_ALG_ECB_NO_PADDING ||\n            operation->alg == PSA_ALG_CBC_NO_PADDING) {\n            status = PSA_ERROR_INVALID_ARGUMENT;\n            goto exit;\n        }\n    }\n\n    status = mbedtls_to_psa_error(\n        mbedtls_cipher_finish_padded(&operation->ctx.cipher,\n                                     temp_output_buffer,\n                                     output_length,\n                                     &invalid_padding));\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (output_size == 0) {\n        ; /* Nothing to copy. Note that output may be NULL in this case. */\n    } else {\n        /* Do not use the value of *output_length to determine how much\n         * to copy. When decrypting a padded cipher, the output length is\n         * sensitive, and leaking it could allow a padding oracle attack. */\n        memcpy(output, temp_output_buffer, output_size);\n    }\n\n    status = mbedtls_ct_error_if_else_0(invalid_padding,\n                                        PSA_ERROR_INVALID_PADDING);\n    mbedtls_ct_condition_t buffer_too_small =\n        mbedtls_ct_uint_lt(output_size, *output_length);\n    status = mbedtls_ct_error_if(buffer_too_small,\n                                 PSA_ERROR_BUFFER_TOO_SMALL,\n                                 status);\n\nexit:\n    mbedtls_platform_zeroize(temp_output_buffer,\n                             sizeof(temp_output_buffer));\n    return status;\n}\n\npsa_status_t mbedtls_psa_cipher_abort(\n    mbedtls_psa_cipher_operation_t *operation)\n{\n    /* Sanity check (shouldn't happen: operation->alg should\n     * always have been initialized to a valid value). */\n    if (!PSA_ALG_IS_CIPHER(operation->alg)) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    mbedtls_cipher_free(&operation->ctx.cipher);\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t mbedtls_psa_cipher_encrypt(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *iv,\n    size_t iv_length,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *output,\n    size_t output_size,\n    size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;\n    size_t update_output_length, finish_output_length;\n\n    status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes,\n                                              key_buffer, key_buffer_size,\n                                              alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (iv_length > 0) {\n        status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n    }\n\n    status = mbedtls_psa_cipher_update(&operation, input, input_length,\n                                       output, output_size,\n                                       &update_output_length);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = mbedtls_psa_cipher_finish(\n        &operation,\n        mbedtls_buffer_offset(output, update_output_length),\n        output_size - update_output_length, &finish_output_length);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    *output_length = update_output_length + finish_output_length;\n\nexit:\n    if (status == PSA_SUCCESS) {\n        status = mbedtls_psa_cipher_abort(&operation);\n    } else {\n        mbedtls_psa_cipher_abort(&operation);\n    }\n\n    return status;\n}\n\npsa_status_t mbedtls_psa_cipher_decrypt(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *output,\n    size_t output_size,\n    size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;\n    size_t olength, accumulated_length;\n\n    status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes,\n                                              key_buffer, key_buffer_size,\n                                              alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (operation.iv_length > 0) {\n        status = mbedtls_psa_cipher_set_iv(&operation,\n                                           input, operation.iv_length);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n    }\n\n    status = mbedtls_psa_cipher_update(\n        &operation,\n        mbedtls_buffer_offset_const(input, operation.iv_length),\n        input_length - operation.iv_length,\n        output, output_size, &olength);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    accumulated_length = olength;\n\n    status = mbedtls_psa_cipher_finish(\n        &operation,\n        mbedtls_buffer_offset(output, accumulated_length),\n        output_size - accumulated_length, &olength);\n\n    *output_length = accumulated_length + olength;\n\nexit:\n    /* C99 doesn't allow a declaration to follow a label */;\n    psa_status_t abort_status = mbedtls_psa_cipher_abort(&operation);\n    /* Normally abort shouldn't fail unless the operation is in a bad\n     * state, in which case we'd expect finish to fail with the same error.\n     * So it doesn't matter much which call's error code we pick when both\n     * fail. However, in unauthenticated decryption specifically, the\n     * distinction between PSA_SUCCESS and PSA_ERROR_INVALID_PADDING is\n     * security-sensitive (risk of a padding oracle attack), so here we\n     * must not have a code path that depends on the value of status. */\n    if (abort_status != PSA_SUCCESS) {\n        status = abort_status;\n    }\n\n    return status;\n}\n#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */\n\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_cipher.h",
    "content": "/*\n *  PSA cipher driver entry points and associated auxiliary functions\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_CIPHER_H\n#define PSA_CRYPTO_CIPHER_H\n\n#include <mbedtls/cipher.h>\n#include <psa/crypto.h>\n\n/** Get Mbed TLS cipher information given the cipher algorithm PSA identifier\n *  as well as the PSA type and size of the key to be used with the cipher\n *  algorithm.\n *\n * \\param[in]      alg          PSA cipher algorithm identifier\n * \\param[in]      key_type     PSA key type\n * \\param[in,out]  key_bits     Size of the key in bits. The value provided in input\n *                              might be updated if necessary.\n * \\param[out]     mode         Mbed TLS cipher mode\n * \\param[out]     cipher_id    Mbed TLS cipher algorithm identifier\n *\n * \\return  On success \\c PSA_SUCCESS is returned and key_bits, mode and cipher_id\n *          are properly updated.\n *          \\c PSA_ERROR_NOT_SUPPORTED is returned if the cipher algorithm is not\n *          supported.\n */\n\npsa_status_t mbedtls_cipher_values_from_psa(psa_algorithm_t alg, psa_key_type_t key_type,\n                                            size_t *key_bits, mbedtls_cipher_mode_t *mode,\n                                            mbedtls_cipher_id_t *cipher_id);\n\n#if defined(MBEDTLS_CIPHER_C)\n/** Get Mbed TLS cipher information given the cipher algorithm PSA identifier\n *  as well as the PSA type and size of the key to be used with the cipher\n *  algorithm.\n *\n * \\param       alg        PSA cipher algorithm identifier\n * \\param       key_type   PSA key type\n * \\param       key_bits   Size of the key in bits\n * \\param[out]  cipher_id  Mbed TLS cipher algorithm identifier\n *\n * \\return  The Mbed TLS cipher information of the cipher algorithm.\n *          \\c NULL if the PSA cipher algorithm is not supported.\n */\nconst mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(\n    psa_algorithm_t alg, psa_key_type_t key_type, size_t key_bits,\n    mbedtls_cipher_id_t *cipher_id);\n#endif /* MBEDTLS_CIPHER_C */\n\n/**\n * \\brief Set the key for a multipart symmetric encryption operation.\n *\n * \\note The signature of this function is that of a PSA driver\n *       cipher_encrypt_setup entry point. This function behaves as a\n *       cipher_encrypt_setup entry point as defined in the PSA driver\n *       interface specification for transparent drivers.\n *\n * \\param[in,out] operation     The operation object to set up. It has been\n *                              initialized as per the documentation for\n *                              #psa_cipher_operation_t and not yet in use.\n * \\param[in] attributes        The attributes of the key to use for the\n *                              operation.\n * \\param[in] key_buffer        The buffer containing the key context.\n * \\param[in] key_buffer_size   Size of the \\p key_buffer buffer in bytes.\n * \\param[in] alg               The cipher algorithm to compute\n *                              (\\c PSA_ALG_XXX value such that\n *                              #PSA_ALG_IS_CIPHER(\\p alg) is true).\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_cipher_encrypt_setup(\n    mbedtls_psa_cipher_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg);\n\n/**\n * \\brief Set the key for a multipart symmetric decryption operation.\n *\n * \\note The signature of this function is that of a PSA driver\n *       cipher_decrypt_setup entry point. This function behaves as a\n *       cipher_decrypt_setup entry point as defined in the PSA driver\n *       interface specification for transparent drivers.\n *\n * \\param[in,out] operation     The operation object to set up. It has been\n *                              initialized as per the documentation for\n *                              #psa_cipher_operation_t and not yet in use.\n * \\param[in] attributes        The attributes of the key to use for the\n *                              operation.\n * \\param[in] key_buffer        The buffer containing the key context.\n * \\param[in] key_buffer_size   Size of the \\p key_buffer buffer in bytes.\n * \\param[in] alg               The cipher algorithm to compute\n *                              (\\c PSA_ALG_XXX value such that\n *                              #PSA_ALG_IS_CIPHER(\\p alg) is true).\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_cipher_decrypt_setup(\n    mbedtls_psa_cipher_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg);\n\n/** Set the IV for a symmetric encryption or decryption operation.\n *\n * This function sets the IV (initialization vector), nonce\n * or initial counter value for the encryption or decryption operation.\n *\n * \\note The signature of this function is that of a PSA driver\n *       cipher_set_iv entry point. This function behaves as a\n *       cipher_set_iv entry point as defined in the PSA driver\n *       interface specification for transparent drivers.\n *\n * \\param[in,out] operation     Active cipher operation.\n * \\param[in] iv                Buffer containing the IV to use.\n * \\param[in] iv_length         Size of the IV in bytes. It is guaranteed by\n *                              the core to be less or equal to\n *                              PSA_CIPHER_IV_MAX_SIZE.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The size of \\p iv is not acceptable for the chosen algorithm,\n *         or the chosen algorithm does not use an IV.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n */\npsa_status_t mbedtls_psa_cipher_set_iv(\n    mbedtls_psa_cipher_operation_t *operation,\n    const uint8_t *iv, size_t iv_length);\n\n/** Encrypt or decrypt a message fragment in an active cipher operation.\n *\n * \\note The signature of this function is that of a PSA driver\n *       cipher_update entry point. This function behaves as a\n *       cipher_update entry point as defined in the PSA driver\n *       interface specification for transparent drivers.\n *\n * \\param[in,out] operation     Active cipher operation.\n * \\param[in] input             Buffer containing the message fragment to\n *                              encrypt or decrypt.\n * \\param[in] input_length      Size of the \\p input buffer in bytes.\n * \\param[out] output           Buffer where the output is to be written.\n * \\param[in]  output_size      Size of the \\p output buffer in bytes.\n * \\param[out] output_length    On success, the number of bytes\n *                              that make up the returned output.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p output buffer is too small.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n */\npsa_status_t mbedtls_psa_cipher_update(\n    mbedtls_psa_cipher_operation_t *operation,\n    const uint8_t *input, size_t input_length,\n    uint8_t *output, size_t output_size, size_t *output_length);\n\n/** Finish encrypting or decrypting a message in a cipher operation.\n *\n * \\note The signature of this function is that of a PSA driver\n *       cipher_finish entry point. This function behaves as a\n *       cipher_finish entry point as defined in the PSA driver\n *       interface specification for transparent drivers.\n *\n * \\param[in,out] operation     Active cipher operation.\n * \\param[out] output           Buffer where the output is to be written.\n * \\param[in]  output_size      Size of the \\p output buffer in bytes.\n * \\param[out] output_length    On success, the number of bytes\n *                              that make up the returned output.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The total input size passed to this operation is not valid for\n *         this particular algorithm. For example, the algorithm is a based\n *         on block cipher and requires a whole number of blocks, but the\n *         total input size is not a multiple of the block size.\n * \\retval #PSA_ERROR_INVALID_PADDING\n *         This is a decryption operation for an algorithm that includes\n *         padding, and the ciphertext does not contain valid padding.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p output buffer is too small.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n */\npsa_status_t mbedtls_psa_cipher_finish(\n    mbedtls_psa_cipher_operation_t *operation,\n    uint8_t *output, size_t output_size, size_t *output_length);\n\n/** Abort a cipher operation.\n *\n * Aborting an operation frees all associated resources except for the\n * \\p operation structure itself. Once aborted, the operation object\n * can be reused for another operation.\n *\n * \\note The signature of this function is that of a PSA driver\n *       cipher_abort entry point. This function behaves as a\n *       cipher_abort entry point as defined in the PSA driver\n *       interface specification for transparent drivers.\n *\n * \\param[in,out] operation     Initialized cipher operation.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n */\npsa_status_t mbedtls_psa_cipher_abort(mbedtls_psa_cipher_operation_t *operation);\n\n/** Encrypt a message using a symmetric cipher.\n *\n * \\note The signature of this function is that of a PSA driver\n *       cipher_encrypt entry point. This function behaves as a\n *       cipher_encrypt entry point as defined in the PSA driver\n *       interface specification for transparent drivers.\n *\n * \\param[in] attributes        The attributes of the key to use for the\n *                              operation.\n * \\param[in] key_buffer        The buffer containing the key context.\n * \\param[in] key_buffer_size   Size of the \\p key_buffer buffer in bytes.\n * \\param[in] alg               The cipher algorithm to compute\n *                              (\\c PSA_ALG_XXX value such that\n *                              #PSA_ALG_IS_CIPHER(\\p alg) is true).\n * \\param[in] iv                Buffer containing the IV for encryption. The\n *                              IV has been generated by the core.\n * \\param[in] iv_length         Size of the \\p iv in bytes.\n * \\param[in] input             Buffer containing the message to encrypt.\n * \\param[in] input_length      Size of the \\p input buffer in bytes.\n * \\param[in,out] output        Buffer where the output is to be written.\n * \\param[in]  output_size      Size of the \\p output buffer in bytes.\n * \\param[out] output_length    On success, the number of bytes that make up\n *                              the returned output. Initialized to zero\n *                              by the core.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p output buffer is too small.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The size \\p iv_length is not acceptable for the chosen algorithm,\n *         or the chosen algorithm does not use an IV.\n *         The total input size passed to this operation is not valid for\n *         this particular algorithm. For example, the algorithm is a based\n *         on block cipher and requires a whole number of blocks, but the\n *         total input size is not a multiple of the block size.\n * \\retval #PSA_ERROR_INVALID_PADDING\n *         This is a decryption operation for an algorithm that includes\n *         padding, and the ciphertext does not contain valid padding.\n */\npsa_status_t mbedtls_psa_cipher_encrypt(const psa_key_attributes_t *attributes,\n                                        const uint8_t *key_buffer,\n                                        size_t key_buffer_size,\n                                        psa_algorithm_t alg,\n                                        const uint8_t *iv,\n                                        size_t iv_length,\n                                        const uint8_t *input,\n                                        size_t input_length,\n                                        uint8_t *output,\n                                        size_t output_size,\n                                        size_t *output_length);\n\n/** Decrypt a message using a symmetric cipher.\n *\n * \\note The signature of this function is that of a PSA driver\n *       cipher_decrypt entry point. This function behaves as a\n *       cipher_decrypt entry point as defined in the PSA driver\n *       interface specification for transparent drivers.\n *\n * \\param[in]  attributes       The attributes of the key to use for the\n *                              operation.\n * \\param[in]  key_buffer       The buffer containing the key context.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[in]  alg              The cipher algorithm to compute\n *                              (\\c PSA_ALG_XXX value such that\n *                              #PSA_ALG_IS_CIPHER(\\p alg) is true).\n * \\param[in]  input            Buffer containing the iv and the ciphertext.\n * \\param[in]  input_length     Size of the \\p input buffer in bytes.\n * \\param[out] output           Buffer where the output is to be written.\n * \\param[in]  output_size      Size of the \\p output buffer in bytes.\n * \\param[out] output_length    On success, the number of bytes that make up\n *                              the returned output. Initialized to zero\n *                              by the core.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p output buffer is too small.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The size of \\p iv is not acceptable for the chosen algorithm,\n *         or the chosen algorithm does not use an IV.\n *         The total input size passed to this operation is not valid for\n *         this particular algorithm. For example, the algorithm is a based\n *         on block cipher and requires a whole number of blocks, but the\n *         total input size is not a multiple of the block size.\n * \\retval #PSA_ERROR_INVALID_PADDING\n *         This is a decryption operation for an algorithm that includes\n *         padding, and the ciphertext does not contain valid padding.\n */\npsa_status_t mbedtls_psa_cipher_decrypt(const psa_key_attributes_t *attributes,\n                                        const uint8_t *key_buffer,\n                                        size_t key_buffer_size,\n                                        psa_algorithm_t alg,\n                                        const uint8_t *input,\n                                        size_t input_length,\n                                        uint8_t *output,\n                                        size_t output_size,\n                                        size_t *output_length);\n\n#endif /* PSA_CRYPTO_CIPHER_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_client.c",
    "content": "/*\n *  PSA crypto client code\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n#include \"psa/crypto.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)\n\n#include <string.h>\n#include \"mbedtls/platform.h\"\n\nvoid psa_reset_key_attributes(psa_key_attributes_t *attributes)\n{\n    memset(attributes, 0, sizeof(*attributes));\n}\n\n#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_core.h",
    "content": "/*\n *  PSA crypto core internal interfaces\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_CORE_H\n#define PSA_CRYPTO_CORE_H\n\n/*\n * Include the build-time configuration information header. Here, we do not\n * include `\"mbedtls/build_info.h\"` directly but `\"psa/build_info.h\"`, which\n * is basically just an alias to it. This is to ease the maintenance of the\n * TF-PSA-Crypto repository which has a different build system and\n * configuration.\n */\n#include \"psa/build_info.h\"\n\n#include \"psa/crypto.h\"\n#include \"psa/crypto_se_driver.h\"\n#if defined(MBEDTLS_THREADING_C)\n#include \"mbedtls/threading.h\"\n#endif\n\ntypedef enum {\n    PSA_SLOT_EMPTY = 0,\n    PSA_SLOT_FILLING,\n    PSA_SLOT_FULL,\n    PSA_SLOT_PENDING_DELETION,\n} psa_key_slot_state_t;\n\n/** The data structure representing a key slot, containing key material\n * and metadata for one key.\n */\ntypedef struct {\n    /* This field is accessed in a lot of places. Putting it first\n     * reduces the code size. */\n    psa_key_attributes_t attr;\n\n    /*\n     * The current state of the key slot, as described in\n     * docs/architecture/psa-thread-safety/psa-thread-safety.md.\n     *\n     * Library functions can modify the state of a key slot by calling\n     * psa_key_slot_state_transition.\n     *\n     * The state variable is used to help determine whether library functions\n     * which operate on the slot succeed. For example, psa_finish_key_creation,\n     * which transfers the state of a slot from PSA_SLOT_FILLING to\n     * PSA_SLOT_FULL, must fail with error code PSA_ERROR_CORRUPTION_DETECTED\n     * if the state of the slot is not PSA_SLOT_FILLING.\n     *\n     * Library functions which traverse the array of key slots only consider\n     * slots that are in a suitable state for the function.\n     * For example, psa_get_and_lock_key_slot_in_memory, which finds a slot\n     * containing a given key ID, will only check slots whose state variable is\n     * PSA_SLOT_FULL.\n     */\n    psa_key_slot_state_t state;\n\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n    /* The index of the slice containing this slot.\n     * This field must be filled if the slot contains a key\n     * (including keys being created or destroyed), and can be either\n     * filled or 0 when the slot is free.\n     *\n     * In most cases, the slice index can be deduced from the key identifer.\n     * We keep it in a separate field for robustness (it reduces the chance\n     * that a coding mistake in the key store will result in accessing the\n     * wrong slice), and also so that it's available even on code paths\n     * during creation or destruction where the key identifier might not be\n     * filled in.\n     * */\n    uint8_t slice_index;\n#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n\n    union {\n        struct {\n            /* The index of the next slot in the free list for this\n             * slice, relative * to the next array element.\n             *\n             * That is, 0 means the next slot, 1 means the next slot\n             * but one, etc. -1 would mean the slot itself. -2 means\n             * the previous slot, etc.\n             *\n             * If this is beyond the array length, the free list ends with the\n             * current element.\n             *\n             * The reason for this strange encoding is that 0 means the next\n             * element. This way, when we allocate a slice and initialize it\n             * to all-zero, the slice is ready for use, with a free list that\n             * consists of all the slots in order.\n             */\n            int32_t next_free_relative_to_next;\n        } free;\n\n        struct {\n            /*\n             * Number of functions registered as reading the material in the key slot.\n             *\n             * Library functions must not write directly to registered_readers\n             *\n             * A function must call psa_register_read(slot) before reading\n             * the current contents of the slot for an operation.\n             * They then must call psa_unregister_read(slot) once they have\n             * finished reading the current contents of the slot. If the key\n             * slot mutex is not held (when mutexes are enabled), this call\n             * must be done via a call to\n             * psa_unregister_read_under_mutex(slot).\n             * A function must call psa_key_slot_has_readers(slot) to check if\n             * the slot is in use for reading.\n             *\n             * This counter is used to prevent resetting the key slot while\n             * the library may access it. For example, such control is needed\n             * in the following scenarios:\n             * . In case of key slot starvation, all key slots contain the\n             *   description of a key, and the library asks for the\n             *   description of a persistent key not present in the\n             *   key slots, the key slots currently accessed by the\n             *   library cannot be reclaimed to free a key slot to load\n             *   the persistent key.\n             * . In case of a multi-threaded application where one thread\n             *   asks to close or purge or destroy a key while it is in use\n             *   by the library through another thread. */\n            size_t registered_readers;\n        } occupied;\n    } var;\n\n    /* Dynamically allocated key data buffer.\n     * Format as specified in psa_export_key(). */\n    struct key_data {\n#if defined(MBEDTLS_PSA_STATIC_KEY_SLOTS)\n        uint8_t data[MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE];\n#else\n        uint8_t *data;\n#endif\n        size_t bytes;\n    } key;\n} psa_key_slot_t;\n\n#if defined(MBEDTLS_THREADING_C)\n\n/** Perform a mutex operation and return immediately upon failure.\n *\n * Returns PSA_ERROR_SERVICE_FAILURE if the operation fails\n * and status was PSA_SUCCESS.\n *\n * Assumptions:\n *  psa_status_t status exists.\n *  f is a mutex operation which returns 0 upon success.\n */\n#define PSA_THREADING_CHK_RET(f)                       \\\n    do                                                 \\\n    {                                                  \\\n        if ((f) != 0) {                                \\\n            if (status == PSA_SUCCESS) {               \\\n                return PSA_ERROR_SERVICE_FAILURE;      \\\n            }                                          \\\n            return status;                             \\\n        }                                              \\\n    } while (0);\n\n/** Perform a mutex operation and goto exit on failure.\n *\n * Sets status to PSA_ERROR_SERVICE_FAILURE if status was PSA_SUCCESS.\n *\n * Assumptions:\n *  psa_status_t status exists.\n *  Label exit: exists.\n *  f is a mutex operation which returns 0 upon success.\n */\n#define PSA_THREADING_CHK_GOTO_EXIT(f)                 \\\n    do                                                 \\\n    {                                                  \\\n        if ((f) != 0) {                                \\\n            if (status == PSA_SUCCESS) {               \\\n                status = PSA_ERROR_SERVICE_FAILURE;    \\\n            }                                          \\\n            goto exit;                                 \\\n        }                                              \\\n    } while (0);\n#endif\n\n/** Test whether a key slot has any registered readers.\n * If multi-threading is enabled, the caller must hold the\n * global key slot mutex.\n *\n * \\param[in] slot      The key slot to test.\n *\n * \\return 1 if the slot has any registered readers, 0 otherwise.\n */\nstatic inline int psa_key_slot_has_readers(const psa_key_slot_t *slot)\n{\n    return slot->var.occupied.registered_readers > 0;\n}\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n/** Get the SE slot number of a key from the key slot storing its description.\n *\n * \\param[in]  slot  The key slot to query. This must be a key slot storing\n *                   the description of a key of a dynamically registered\n *                   secure element, otherwise the behaviour is undefined.\n */\nstatic inline psa_key_slot_number_t psa_key_slot_get_slot_number(\n    const psa_key_slot_t *slot)\n{\n    return *((psa_key_slot_number_t *) (slot->key.data));\n}\n#endif\n\n/** Completely wipe a slot in memory, including its policy.\n *\n * Persistent storage is not affected.\n * Sets the slot's state to PSA_SLOT_EMPTY.\n * If multi-threading is enabled, the caller must hold the\n * global key slot mutex.\n *\n * \\param[in,out] slot  The key slot to wipe.\n *\n * \\retval #PSA_SUCCESS\n *         The slot has been successfully wiped.\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED\n *         The slot's state was PSA_SLOT_FULL or PSA_SLOT_PENDING_DELETION, and\n *         the amount of registered readers was not equal to 1. Or,\n *         the slot's state was PSA_SLOT_EMPTY. Or,\n *         the slot's state was PSA_SLOT_FILLING, and the amount\n *         of registered readers was not equal to 0.\n */\npsa_status_t psa_wipe_key_slot(psa_key_slot_t *slot);\n\n/** Try to allocate a buffer to an empty key slot.\n *\n * \\param[in,out] slot          Key slot to attach buffer to.\n * \\param[in] buffer_length     Requested size of the buffer.\n *\n * \\retval #PSA_SUCCESS\n *         The buffer has been successfully allocated.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY\n *         Not enough memory was available for allocation.\n * \\retval #PSA_ERROR_ALREADY_EXISTS\n *         Trying to allocate a buffer to a non-empty key slot.\n */\npsa_status_t psa_allocate_buffer_to_slot(psa_key_slot_t *slot,\n                                         size_t buffer_length);\n\n/** Wipe key data from a slot. Preserves metadata such as the policy. */\npsa_status_t psa_remove_key_data_from_memory(psa_key_slot_t *slot);\n\n/** Copy key data (in export format) into an empty key slot.\n *\n * This function assumes that the slot does not contain\n * any key material yet. On failure, the slot content is unchanged.\n *\n * \\param[in,out] slot          Key slot to copy the key into.\n * \\param[in] data              Buffer containing the key material.\n * \\param data_length           Size of the key buffer.\n *\n * \\retval #PSA_SUCCESS\n *         The key has been copied successfully.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY\n *         Not enough memory was available for allocation of the\n *         copy buffer.\n * \\retval #PSA_ERROR_ALREADY_EXISTS\n *         There was other key material already present in the slot.\n */\npsa_status_t psa_copy_key_material_into_slot(psa_key_slot_t *slot,\n                                             const uint8_t *data,\n                                             size_t data_length);\n\n/** Convert an Mbed TLS error code to a PSA error code\n *\n * \\note This function is provided solely for the convenience of\n *       Mbed TLS and may be removed at any time without notice.\n *\n * \\param ret           An Mbed TLS-thrown error code\n *\n * \\return              The corresponding PSA error code\n */\npsa_status_t mbedtls_to_psa_error(int ret);\n\n/** Import a key in binary format.\n *\n * \\note The signature of this function is that of a PSA driver\n *       import_key entry point. This function behaves as an import_key\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in]  attributes       The attributes for the key to import.\n * \\param[in]  data             The buffer containing the key data in import\n *                              format.\n * \\param[in]  data_length      Size of the \\p data buffer in bytes.\n * \\param[out] key_buffer       The buffer to contain the key data in output\n *                              format upon successful return.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes. This\n *                              size is greater or equal to \\p data_length.\n * \\param[out] key_buffer_length  The length of the data written in \\p\n *                                key_buffer in bytes.\n * \\param[out] bits             The key size in number of bits.\n *\n * \\retval #PSA_SUCCESS  The key was imported successfully.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The key data is not correctly formatted.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t psa_import_key_into_slot(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *data, size_t data_length,\n    uint8_t *key_buffer, size_t key_buffer_size,\n    size_t *key_buffer_length, size_t *bits);\n\n/** Export a key in binary format\n *\n * \\note The signature of this function is that of a PSA driver export_key\n *       entry point. This function behaves as an export_key entry point as\n *       defined in the PSA driver interface specification.\n *\n * \\param[in]  attributes       The attributes for the key to export.\n * \\param[in]  key_buffer       Material or context of the key to export.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[out] data             Buffer where the key data is to be written.\n * \\param[in]  data_size        Size of the \\p data buffer in bytes.\n * \\param[out] data_length      On success, the number of bytes written in\n *                              \\p data\n *\n * \\retval #PSA_SUCCESS  The key was exported successfully.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n */\npsa_status_t psa_export_key_internal(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    uint8_t *data, size_t data_size, size_t *data_length);\n\n/** Export a public key or the public part of a key pair in binary format.\n *\n * \\note The signature of this function is that of a PSA driver\n *       export_public_key entry point. This function behaves as an\n *       export_public_key entry point as defined in the PSA driver interface\n *       specification.\n *\n * \\param[in]  attributes       The attributes for the key to export.\n * \\param[in]  key_buffer       Material or context of the key to export.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[out] data             Buffer where the key data is to be written.\n * \\param[in]  data_size        Size of the \\p data buffer in bytes.\n * \\param[out] data_length      On success, the number of bytes written in\n *                              \\p data\n *\n * \\retval #PSA_SUCCESS  The public key was exported successfully.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n */\npsa_status_t psa_export_public_key_internal(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    uint8_t *data, size_t data_size, size_t *data_length);\n\n/** Whether a key custom production parameters structure is the default.\n *\n * Calls to a key generation driver with non-default custom production parameters\n * require a driver supporting custom production parameters.\n *\n * \\param[in] custom            The key custom production parameters to check.\n * \\param custom_data_length    Size of the associated variable-length data\n *                              in bytes.\n */\nint psa_custom_key_parameters_are_default(\n    const psa_custom_key_parameters_t *custom,\n    size_t custom_data_length);\n\n/**\n * \\brief Generate a key.\n *\n * \\note The signature of the function is that of a PSA driver generate_key\n *       entry point.\n *\n * \\param[in]  attributes         The attributes for the key to generate.\n * \\param[in] custom              Custom parameters for the key generation.\n * \\param[in] custom_data         Variable-length data associated with \\c custom.\n * \\param custom_data_length      Length of `custom_data` in bytes.\n * \\param[out] key_buffer         Buffer where the key data is to be written.\n * \\param[in]  key_buffer_size    Size of \\p key_buffer in bytes.\n * \\param[out] key_buffer_length  On success, the number of bytes written in\n *                                \\p key_buffer.\n *\n * \\retval #PSA_SUCCESS\n *         The key was generated successfully.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         Key size in bits or type not supported.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of \\p key_buffer is too small.\n */\npsa_status_t psa_generate_key_internal(const psa_key_attributes_t *attributes,\n                                       const psa_custom_key_parameters_t *custom,\n                                       const uint8_t *custom_data,\n                                       size_t custom_data_length,\n                                       uint8_t *key_buffer,\n                                       size_t key_buffer_size,\n                                       size_t *key_buffer_length);\n\n/** Sign a message with a private key. For hash-and-sign algorithms,\n *  this includes the hashing step.\n *\n * \\note The signature of this function is that of a PSA driver\n *       sign_message entry point. This function behaves as a sign_message\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\note This function will call the driver for psa_sign_hash\n *       and go through driver dispatch again.\n *\n * \\param[in]  attributes       The attributes of the key to use for the\n *                              operation.\n * \\param[in]  key_buffer       The buffer containing the key context.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[in]  alg              A signature algorithm that is compatible with\n *                              the type of the key.\n * \\param[in]  input            The input message to sign.\n * \\param[in]  input_length     Size of the \\p input buffer in bytes.\n * \\param[out] signature        Buffer where the signature is to be written.\n * \\param[in]  signature_size   Size of the \\p signature buffer in bytes.\n * \\param[out] signature_length On success, the number of bytes\n *                              that make up the returned signature value.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p signature buffer is too small. You can\n *         determine a sufficient buffer size by calling\n *         #PSA_SIGN_OUTPUT_SIZE(\\c key_type, \\c key_bits, \\p alg)\n *         where \\c key_type and \\c key_bits are the type and bit-size\n *         respectively of the key.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n */\npsa_status_t psa_sign_message_builtin(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *input, size_t input_length,\n    uint8_t *signature, size_t signature_size, size_t *signature_length);\n\n/** Verify the signature of a message with a public key, using\n *  a hash-and-sign verification algorithm.\n *\n * \\note The signature of this function is that of a PSA driver\n *       verify_message entry point. This function behaves as a verify_message\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\note This function will call the driver for psa_verify_hash\n *       and go through driver dispatch again.\n *\n * \\param[in]  attributes       The attributes of the key to use for the\n *                              operation.\n * \\param[in]  key_buffer       The buffer containing the key context.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[in]  alg              A signature algorithm that is compatible with\n *                              the type of the key.\n * \\param[in]  input            The message whose signature is to be verified.\n * \\param[in]  input_length     Size of the \\p input buffer in bytes.\n * \\param[in]  signature        Buffer containing the signature to verify.\n * \\param[in]  signature_length Size of the \\p signature buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         The signature is valid.\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The calculation was performed successfully, but the passed\n *         signature is not a valid signature.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n */\npsa_status_t psa_verify_message_builtin(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *input, size_t input_length,\n    const uint8_t *signature, size_t signature_length);\n\n/** Sign an already-calculated hash with a private key.\n *\n * \\note The signature of this function is that of a PSA driver\n *       sign_hash entry point. This function behaves as a sign_hash\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in]  attributes       The attributes of the key to use for the\n *                              operation.\n * \\param[in]  key_buffer       The buffer containing the key context.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[in]  alg              A signature algorithm that is compatible with\n *                              the type of the key.\n * \\param[in]  hash             The hash or message to sign.\n * \\param[in]  hash_length      Size of the \\p hash buffer in bytes.\n * \\param[out] signature        Buffer where the signature is to be written.\n * \\param[in]  signature_size   Size of the \\p signature buffer in bytes.\n * \\param[out] signature_length On success, the number of bytes\n *                              that make up the returned signature value.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p signature buffer is too small. You can\n *         determine a sufficient buffer size by calling\n *         #PSA_SIGN_OUTPUT_SIZE(\\c key_type, \\c key_bits, \\p alg)\n *         where \\c key_type and \\c key_bits are the type and bit-size\n *         respectively of the key.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n */\npsa_status_t psa_sign_hash_builtin(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,\n    uint8_t *signature, size_t signature_size, size_t *signature_length);\n\n/**\n * \\brief Verify the signature a hash or short message using a public key.\n *\n * \\note The signature of this function is that of a PSA driver\n *       verify_hash entry point. This function behaves as a verify_hash\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in]  attributes       The attributes of the key to use for the\n *                              operation.\n * \\param[in]  key_buffer       The buffer containing the key context.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[in]  alg              A signature algorithm that is compatible with\n *                              the type of the key.\n * \\param[in]  hash             The hash or message whose signature is to be\n *                              verified.\n * \\param[in]  hash_length      Size of the \\p hash buffer in bytes.\n * \\param[in]  signature        Buffer containing the signature to verify.\n * \\param[in]  signature_length Size of the \\p signature buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         The signature is valid.\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The calculation was performed successfully, but the passed\n *         signature is not a valid signature.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n */\npsa_status_t psa_verify_hash_builtin(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,\n    const uint8_t *signature, size_t signature_length);\n\n/**\n * \\brief Validate the key bit size for unstructured keys.\n *\n * \\note  Check that the bit size is acceptable for a given key type for\n *        unstructured keys.\n *\n * \\param[in]  type  The key type\n * \\param[in]  bits  The number of bits of the key\n *\n * \\retval #PSA_SUCCESS\n *         The key type and size are valid.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The size in bits of the key is not valid.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         The type and/or the size in bits of the key or the combination of\n *         the two is not supported.\n */\npsa_status_t psa_validate_unstructured_key_bit_size(psa_key_type_t type,\n                                                    size_t bits);\n\n/** Perform a key agreement and return the raw shared secret, using\n    built-in raw key agreement functions.\n *\n * \\note The signature of this function is that of a PSA driver\n *       key_agreement entry point. This function behaves as a key_agreement\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in]  attributes           The attributes of the key to use for the\n *                                  operation.\n * \\param[in]  key_buffer           The buffer containing the private key\n *                                  context.\n * \\param[in]  key_buffer_size      Size of the \\p key_buffer buffer in\n *                                  bytes.\n * \\param[in]  alg                  A key agreement algorithm that is\n *                                  compatible with the type of the key.\n * \\param[in]  peer_key             The buffer containing the key context\n *                                  of the peer's public key.\n * \\param[in]  peer_key_length      Size of the \\p peer_key buffer in\n *                                  bytes.\n * \\param[out] shared_secret        The buffer to which the shared secret\n *                                  is to be written.\n * \\param[in]  shared_secret_size   Size of the \\p shared_secret buffer in\n *                                  bytes.\n * \\param[out] shared_secret_length On success, the number of bytes that make\n *                                  up the returned shared secret.\n * \\retval #PSA_SUCCESS\n *         Success. Shared secret successfully calculated.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p alg is not a key agreement algorithm, or\n *         \\p private_key is not compatible with \\p alg,\n *         or \\p peer_key is not valid for \\p alg or not compatible with\n *         \\p private_key.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         \\p shared_secret_size is too small\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not a supported key agreement algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE \\emptydescription\n */\npsa_status_t psa_key_agreement_raw_builtin(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *peer_key,\n    size_t peer_key_length,\n    uint8_t *shared_secret,\n    size_t shared_secret_size,\n    size_t *shared_secret_length);\n\n/**\n * \\brief Set the maximum number of ops allowed to be executed by an\n *        interruptible function in a single call.\n *\n * \\note The signature of this function is that of a PSA driver\n *       interruptible_set_max_ops entry point. This function behaves as an\n *       interruptible_set_max_ops entry point as defined in the PSA driver\n *       interface specification for transparent drivers.\n *\n * \\param[in]  max_ops          The maximum number of ops to be executed in a\n *                              single call, this can be a number from 0 to\n *                              #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, where 0\n *                              is obviously the least amount of work done per\n *                              call.\n */\nvoid mbedtls_psa_interruptible_set_max_ops(uint32_t max_ops);\n\n/**\n * \\brief Get the maximum number of ops allowed to be executed by an\n *        interruptible function in a single call.\n *\n * \\note The signature of this function is that of a PSA driver\n *       interruptible_get_max_ops entry point. This function behaves as an\n *       interruptible_get_max_ops entry point as defined in the PSA driver\n *       interface specification for transparent drivers.\n *\n * \\return                      Maximum number of ops allowed to be executed\n *                              by an interruptible function in a single call.\n */\nuint32_t mbedtls_psa_interruptible_get_max_ops(void);\n\n/**\n * \\brief Get the number of ops that a hash signing operation has taken for the\n *        previous call. If no call or work has taken place, this will return\n *        zero.\n *\n * \\note The signature of this function is that of a PSA driver\n *       sign_hash_get_num_ops entry point. This function behaves as an\n *       sign_hash_get_num_ops entry point as defined in the PSA driver\n *       interface specification for transparent drivers.\n *\n * \\param   operation           The \\c\n *                              mbedtls_psa_sign_hash_interruptible_operation_t\n *                              to use. This must be initialized first.\n *\n * \\return                      Number of ops that were completed\n *                              in the last call to \\c\n *                              mbedtls_psa_sign_hash_complete().\n */\nuint32_t mbedtls_psa_sign_hash_get_num_ops(\n    const mbedtls_psa_sign_hash_interruptible_operation_t *operation);\n\n/**\n * \\brief Get the number of ops that a hash verification operation has taken for\n *        the previous call. If no call or work has taken place, this will\n *        return zero.\n *\n * \\note The signature of this function is that of a PSA driver\n *       verify_hash_get_num_ops entry point. This function behaves as an\n *       verify_hash_get_num_ops entry point as defined in the PSA driver\n *       interface specification for transparent drivers.\n *\n * \\param   operation           The \\c\n *                              mbedtls_psa_verify_hash_interruptible_operation_t\n *                              to use. This must be initialized first.\n *\n * \\return                      Number of ops that were completed\n *                              in the last call to \\c\n *                              mbedtls_psa_verify_hash_complete().\n */\nuint32_t mbedtls_psa_verify_hash_get_num_ops(\n    const mbedtls_psa_verify_hash_interruptible_operation_t *operation);\n\n/**\n * \\brief  Start signing a hash or short message with a private key, in an\n *         interruptible manner.\n *\n * \\note The signature of this function is that of a PSA driver\n *       sign_hash_start entry point. This function behaves as a\n *       sign_hash_start entry point as defined in the PSA driver interface\n *       specification for transparent drivers.\n *\n * \\param[in]  operation        The \\c\n *                              mbedtls_psa_sign_hash_interruptible_operation_t\n *                              to use. This must be initialized first.\n * \\param[in]  attributes       The attributes of the key to use for the\n *                              operation.\n * \\param[in]  key_buffer       The buffer containing the key context.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[in]  alg              A signature algorithm that is compatible with\n *                              the type of the key.\n * \\param[in] hash              The hash or message to sign.\n * \\param hash_length           Size of the \\p hash buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         The operation started successfully - call \\c psa_sign_hash_complete()\n *         with the same context to complete the operation\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         An unsupported, incorrectly formatted or incorrect type of key was\n *         used.\n * \\retval #PSA_ERROR_NOT_SUPPORTED Either no internal interruptible operations\n *         are currently supported, or the key type is currently unsupported.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY\n *         There was insufficient memory to load the key representation.\n */\npsa_status_t mbedtls_psa_sign_hash_start(\n    mbedtls_psa_sign_hash_interruptible_operation_t *operation,\n    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,\n    size_t key_buffer_size, psa_algorithm_t alg,\n    const uint8_t *hash, size_t hash_length);\n\n/**\n * \\brief Continue and eventually complete the action of signing a hash or\n *        short message with a private key, in an interruptible manner.\n *\n * \\note The signature of this function is that of a PSA driver\n *       sign_hash_complete entry point. This function behaves as a\n *       sign_hash_complete entry point as defined in the PSA driver interface\n *       specification for transparent drivers.\n *\n * \\param[in]  operation        The \\c\n *                              mbedtls_psa_sign_hash_interruptible_operation_t\n *                              to use. This must be initialized first.\n *\n * \\param[out] signature        Buffer where the signature is to be written.\n * \\param signature_size        Size of the \\p signature buffer in bytes. This\n *                              must be appropriate for the selected\n *                              algorithm and key.\n * \\param[out] signature_length On success, the number of bytes that make up\n *                              the returned signature value.\n *\n * \\retval #PSA_SUCCESS\n *         Operation completed successfully\n *\n * \\retval #PSA_OPERATION_INCOMPLETE\n *         Operation was interrupted due to the setting of \\c\n *         psa_interruptible_set_max_ops(), there is still work to be done,\n *         please call this function again with the same operation object.\n *\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p signature buffer is too small. You can\n *         determine a sufficient buffer size by calling\n *         #PSA_SIGN_OUTPUT_SIZE(\\c key_type, \\c key_bits, \\p alg)\n *         where \\c key_type and \\c key_bits are the type and bit-size\n *         respectively of \\p key.\n *\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n */\npsa_status_t mbedtls_psa_sign_hash_complete(\n    mbedtls_psa_sign_hash_interruptible_operation_t *operation,\n    uint8_t *signature, size_t signature_size,\n    size_t *signature_length);\n\n/**\n * \\brief Abort a sign hash operation.\n *\n * \\note The signature of this function is that of a PSA driver sign_hash_abort\n *       entry point. This function behaves as a sign_hash_abort entry point as\n *       defined in the PSA driver interface specification for transparent\n *       drivers.\n *\n * \\param[in]  operation        The \\c\n *                              mbedtls_psa_sign_hash_interruptible_operation_t\n *                              to abort.\n *\n * \\retval #PSA_SUCCESS\n *         The operation was aborted successfully.\n */\npsa_status_t mbedtls_psa_sign_hash_abort(\n    mbedtls_psa_sign_hash_interruptible_operation_t *operation);\n\n/**\n * \\brief  Start reading and verifying a hash or short message, in an\n *         interruptible manner.\n *\n * \\note The signature of this function is that of a PSA driver\n *       verify_hash_start entry point. This function behaves as a\n *       verify_hash_start entry point as defined in the PSA driver interface\n *       specification for transparent drivers.\n *\n * \\param[in]  operation        The \\c\n *                              mbedtls_psa_verify_hash_interruptible_operation_t\n *                              to use. This must be initialized first.\n * \\param[in]  attributes       The attributes of the key to use for the\n *                              operation.\n * \\param[in]  key_buffer       The buffer containing the key context.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[in]  alg              A signature algorithm that is compatible with\n *                              the type of the key.\n * \\param[in] hash              The hash whose signature is to be verified.\n * \\param hash_length           Size of the \\p hash buffer in bytes.\n * \\param[in] signature         Buffer containing the signature to verify.\n * \\param signature_length      Size of the \\p signature buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         The operation started successfully - call \\c psa_sign_hash_complete()\n *         with the same context to complete the operation\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         An unsupported or incorrect type of key was used.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *        Either no internal interruptible operations are currently supported,\n *         or the key type is currently unsupported.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY\n *        There was insufficient memory either to load the key representation,\n *        or to prepare the operation.\n */\npsa_status_t mbedtls_psa_verify_hash_start(\n    mbedtls_psa_verify_hash_interruptible_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *hash, size_t hash_length,\n    const uint8_t *signature, size_t signature_length);\n\n/**\n * \\brief Continue and eventually complete the action of signing a hash or\n *        short message with a private key, in an interruptible manner.\n *\n * \\note The signature of this function is that of a PSA driver\n *       sign_hash_complete entry point. This function behaves as a\n *       sign_hash_complete entry point as defined in the PSA driver interface\n *       specification for transparent drivers.\n *\n * \\param[in]  operation        The \\c\n *                              mbedtls_psa_sign_hash_interruptible_operation_t\n *                              to use. This must be initialized first.\n *\n * \\retval #PSA_SUCCESS\n *         Operation completed successfully, and the passed signature is valid.\n *\n * \\retval #PSA_OPERATION_INCOMPLETE\n *         Operation was interrupted due to the setting of \\c\n *         psa_interruptible_set_max_ops(), there is still work to be done,\n *         please call this function again with the same operation object.\n *\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The calculation was performed successfully, but the passed\n *         signature is not a valid signature.\n *\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n */\npsa_status_t mbedtls_psa_verify_hash_complete(\n    mbedtls_psa_verify_hash_interruptible_operation_t *operation);\n\n/**\n * \\brief Abort a verify signed hash operation.\n *\n * \\note The signature of this function is that of a PSA driver\n *       verify_hash_abort entry point. This function behaves as a\n *       verify_hash_abort entry point as defined in the PSA driver interface\n *       specification for transparent drivers.\n *\n * \\param[in]  operation        The \\c\n *                              mbedtls_psa_verify_hash_interruptible_operation_t\n *                              to abort.\n *\n * \\retval #PSA_SUCCESS\n *         The operation was aborted successfully.\n */\npsa_status_t mbedtls_psa_verify_hash_abort(\n    mbedtls_psa_verify_hash_interruptible_operation_t *operation);\n\ntypedef struct psa_crypto_local_input_s {\n    uint8_t *buffer;\n    size_t length;\n} psa_crypto_local_input_t;\n\n#define PSA_CRYPTO_LOCAL_INPUT_INIT ((psa_crypto_local_input_t) { NULL, 0 })\n\n/** Allocate a local copy of an input buffer and copy the contents into it.\n *\n * \\param[in] input             Pointer to input buffer.\n * \\param[in] input_len         Length of the input buffer.\n * \\param[out] local_input      Pointer to a psa_crypto_local_input_t struct\n *                              containing a local input copy.\n * \\return                      #PSA_SUCCESS, if the buffer was successfully\n *                              copied.\n * \\return                      #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of\n *                              the buffer cannot be allocated.\n */\npsa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len,\n                                          psa_crypto_local_input_t *local_input);\n\n/** Free a local copy of an input buffer.\n *\n * \\param[in] local_input       Pointer to a psa_crypto_local_input_t struct\n *                              populated by a previous call to\n *                              psa_crypto_local_input_alloc().\n */\nvoid psa_crypto_local_input_free(psa_crypto_local_input_t *local_input);\n\ntypedef struct psa_crypto_local_output_s {\n    uint8_t *original;\n    uint8_t *buffer;\n    size_t length;\n} psa_crypto_local_output_t;\n\n#define PSA_CRYPTO_LOCAL_OUTPUT_INIT ((psa_crypto_local_output_t) { NULL, NULL, 0 })\n\n/** Allocate a local copy of an output buffer.\n *\n * \\note                        This does not copy any data from the original\n *                              output buffer but only allocates a buffer\n *                              whose contents will be copied back to the\n *                              original in a future call to\n *                              psa_crypto_local_output_free().\n *\n * \\param[in] output            Pointer to output buffer.\n * \\param[in] output_len        Length of the output buffer.\n * \\param[out] local_output     Pointer to a psa_crypto_local_output_t struct to\n *                              populate with the local output copy.\n * \\return                      #PSA_SUCCESS, if the buffer was successfully\n *                              copied.\n * \\return                      #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of\n *                              the buffer cannot be allocated.\n */\npsa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len,\n                                           psa_crypto_local_output_t *local_output);\n\n/** Copy from a local copy of an output buffer back to the original, then\n *  free the local copy.\n *\n * \\param[in] local_output      Pointer to a psa_crypto_local_output_t struct\n *                              populated by a previous call to\n *                              psa_crypto_local_output_alloc().\n * \\return                      #PSA_SUCCESS, if the local output was\n *                              successfully copied back to the original.\n * \\return                      #PSA_ERROR_CORRUPTION_DETECTED, if the output\n *                              could not be copied back to the original.\n */\npsa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output);\n\n#endif /* PSA_CRYPTO_CORE_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_core_common.h",
    "content": "/**\n * \\file psa_crypto_core_common.h\n *\n * \\brief Utility macros for internal use in the PSA cryptography core.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_CORE_COMMON_H\n#define PSA_CRYPTO_CORE_COMMON_H\n\n/** Return an offset into a buffer.\n *\n * This is just the addition of an offset to a pointer, except that this\n * function also accepts an offset of 0 into a buffer whose pointer is null.\n * (`p + n` has undefined behavior when `p` is null, even when `n == 0`.\n * A null pointer is a valid buffer pointer when the size is 0, for example\n * as the result of `malloc(0)` on some platforms.)\n *\n * \\param p     Pointer to a buffer of at least n bytes.\n *              This may be \\p NULL if \\p n is zero.\n * \\param n     An offset in bytes.\n * \\return      Pointer to offset \\p n in the buffer \\p p.\n *              Note that this is only a valid pointer if the size of the\n *              buffer is at least \\p n + 1.\n */\nstatic inline unsigned char *psa_crypto_buffer_offset(\n    unsigned char *p, size_t n)\n{\n    return p == NULL ? NULL : p + n;\n}\n\n/** Return an offset into a read-only buffer.\n *\n * Similar to mbedtls_buffer_offset(), but for const pointers.\n *\n * \\param p     Pointer to a buffer of at least n bytes.\n *              This may be \\p NULL if \\p n is zero.\n * \\param n     An offset in bytes.\n * \\return      Pointer to offset \\p n in the buffer \\p p.\n *              Note that this is only a valid pointer if the size of the\n *              buffer is at least \\p n + 1.\n */\nstatic inline const unsigned char *psa_crypto_buffer_offset_const(\n    const unsigned char *p, size_t n)\n{\n    return p == NULL ? NULL : p + n;\n}\n\n#endif /* PSA_CRYPTO_CORE_COMMON_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_driver_wrappers.h",
    "content": "/*\n *  Functions to delegate cryptographic operations to an available\n *  and appropriate accelerator.\n *  Warning: This file is now auto-generated.\n */\n/*  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n\n/* BEGIN-common headers */\n#include \"common.h\"\n#include \"psa_crypto_aead.h\"\n#include \"psa_crypto_cipher.h\"\n#include \"psa_crypto_core.h\"\n#include \"psa_crypto_driver_wrappers_no_static.h\"\n#include \"psa_crypto_hash.h\"\n#include \"psa_crypto_mac.h\"\n#include \"psa_crypto_pake.h\"\n#include \"psa_crypto_rsa.h\"\n\n#include \"mbedtls/platform.h\"\n#include \"mbedtls/constant_time.h\"\n/* END-common headers */\n\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n\n/* BEGIN-driver headers */\n/* Headers for mbedtls_test opaque driver */\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n#include \"test/drivers/test_driver.h\"\n\n#endif\n/* Headers for mbedtls_test transparent driver */\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n#include \"test/drivers/test_driver.h\"\n\n#endif\n/* Headers for p256 transparent driver */\n#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)\n#include \"../3rdparty/p256-m/p256-m_driver_entrypoints.h\"\n\n#endif\n\n/* END-driver headers */\n\n/* Auto-generated values depending on which drivers are registered.\n * ID 0 is reserved for unallocated operations.\n * ID 1 is reserved for the Mbed TLS software driver. */\n/* BEGIN-driver id definition */\n#define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1)\n#define MBEDTLS_TEST_OPAQUE_DRIVER_ID (2)\n#define MBEDTLS_TEST_TRANSPARENT_DRIVER_ID (3)\n#define P256_TRANSPARENT_DRIVER_ID (4)\n\n/* END-driver id */\n\n/* BEGIN-Common Macro definitions */\n\n/* END-Common Macro definitions */\n\n/* Support the 'old' SE interface when asked to */\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style\n * SE driver is present, to avoid unused argument errors at compile time. */\n#ifndef PSA_CRYPTO_DRIVER_PRESENT\n#define PSA_CRYPTO_DRIVER_PRESENT\n#endif\n#include \"psa_crypto_se.h\"\n#endif\n\nstatic inline psa_status_t psa_driver_wrapper_init( void )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    status = psa_init_all_se_drivers( );\n    if( status != PSA_SUCCESS )\n        return( status );\n#endif\n\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n    status = mbedtls_test_transparent_init( );\n    if( status != PSA_SUCCESS )\n        return( status );\n\n    status = mbedtls_test_opaque_init( );\n    if( status != PSA_SUCCESS )\n        return( status );\n#endif\n\n    (void) status;\n    return( PSA_SUCCESS );\n}\n\nstatic inline void psa_driver_wrapper_free( void )\n{\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    /* Unregister all secure element drivers, so that we restart from\n     * a pristine state. */\n    psa_unregister_all_se_drivers( );\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n    mbedtls_test_transparent_free( );\n    mbedtls_test_opaque_free( );\n#endif\n}\n\n/* Start delegation functions */\nstatic inline psa_status_t psa_driver_wrapper_sign_message(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *signature,\n    size_t signature_size,\n    size_t *signature_length )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_signature_sign_message(\n                        attributes,\n                        key_buffer,\n                        key_buffer_size,\n                        alg,\n                        input,\n                        input_length,\n                        signature,\n                        signature_size,\n                        signature_length );\n            /* Declared with fallback == true */\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n            break;\n\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            status = mbedtls_test_opaque_signature_sign_message(\n                        attributes,\n                        key_buffer,\n                        key_buffer_size,\n                        alg,\n                        input,\n                        input_length,\n                        signature,\n                        signature_size,\n                        signature_length );\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n            break;\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void)status;\n            break;\n    }\n\n    return( psa_sign_message_builtin( attributes,\n                                      key_buffer,\n                                      key_buffer_size,\n                                      alg,\n                                      input,\n                                      input_length,\n                                      signature,\n                                      signature_size,\n                                      signature_length ) );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_verify_message(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *input,\n    size_t input_length,\n    const uint8_t *signature,\n    size_t signature_length )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_signature_verify_message(\n                        attributes,\n                        key_buffer,\n                        key_buffer_size,\n                        alg,\n                        input,\n                        input_length,\n                        signature,\n                        signature_length );\n            /* Declared with fallback == true */\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n            break;\n\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            return( mbedtls_test_opaque_signature_verify_message(\n                        attributes,\n                        key_buffer,\n                        key_buffer_size,\n                        alg,\n                        input,\n                        input_length,\n                        signature,\n                        signature_length ) );\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n            break;\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void)status;\n            break;\n    }\n\n    return( psa_verify_message_builtin( attributes,\n                                        key_buffer,\n                                        key_buffer_size,\n                                        alg,\n                                        input,\n                                        input_length,\n                                        signature,\n                                        signature_length ) );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_sign_hash(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,\n    uint8_t *signature, size_t signature_size, size_t *signature_length )\n{\n    /* Try dynamically-registered SE interface first */\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    const psa_drv_se_t *drv;\n    psa_drv_se_context_t *drv_context;\n\n    if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )\n    {\n        if( drv->asymmetric == NULL ||\n            drv->asymmetric->p_sign == NULL )\n        {\n            /* Key is defined in SE, but we have no way to exercise it */\n            return( PSA_ERROR_NOT_SUPPORTED );\n        }\n        return( drv->asymmetric->p_sign(\n                    drv_context, *( (psa_key_slot_number_t *)key_buffer ),\n                    alg, hash, hash_length,\n                    signature, signature_size, signature_length ) );\n    }\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_signature_sign_hash( attributes,\n                                                           key_buffer,\n                                                           key_buffer_size,\n                                                           alg,\n                                                           hash,\n                                                           hash_length,\n                                                           signature,\n                                                           signature_size,\n                                                           signature_length );\n            /* Declared with fallback == true */\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#if defined (MBEDTLS_PSA_P256M_DRIVER_ENABLED)\n            if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) &&\n                PSA_ALG_IS_RANDOMIZED_ECDSA(alg) &&\n                PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(attributes)) == PSA_ECC_FAMILY_SECP_R1 &&\n                psa_get_key_bits(attributes) == 256 )\n            {\n                status = p256_transparent_sign_hash( attributes,\n                                                     key_buffer,\n                                                     key_buffer_size,\n                                                     alg,\n                                                     hash,\n                                                     hash_length,\n                                                     signature,\n                                                     signature_size,\n                                                     signature_length );\n                if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n            }\n#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n            /* Fell through, meaning no accelerator supports this operation */\n            return( psa_sign_hash_builtin( attributes,\n                                           key_buffer,\n                                           key_buffer_size,\n                                           alg,\n                                           hash,\n                                           hash_length,\n                                           signature,\n                                           signature_size,\n                                           signature_length ) );\n\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            return( mbedtls_test_opaque_signature_sign_hash( attributes,\n                                                             key_buffer,\n                                                             key_buffer_size,\n                                                             alg,\n                                                             hash,\n                                                             hash_length,\n                                                             signature,\n                                                             signature_size,\n                                                             signature_length ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void)status;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_verify_hash(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,\n    const uint8_t *signature, size_t signature_length )\n{\n    /* Try dynamically-registered SE interface first */\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    const psa_drv_se_t *drv;\n    psa_drv_se_context_t *drv_context;\n\n    if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )\n    {\n        if( drv->asymmetric == NULL ||\n            drv->asymmetric->p_verify == NULL )\n        {\n            /* Key is defined in SE, but we have no way to exercise it */\n            return( PSA_ERROR_NOT_SUPPORTED );\n        }\n        return( drv->asymmetric->p_verify(\n                    drv_context, *( (psa_key_slot_number_t *)key_buffer ),\n                    alg, hash, hash_length,\n                    signature, signature_length ) );\n    }\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_signature_verify_hash(\n                         attributes,\n                         key_buffer,\n                         key_buffer_size,\n                         alg,\n                         hash,\n                         hash_length,\n                         signature,\n                         signature_length );\n            /* Declared with fallback == true */\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#if defined (MBEDTLS_PSA_P256M_DRIVER_ENABLED)\n            if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) &&\n                PSA_ALG_IS_ECDSA(alg) &&\n                PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(attributes)) == PSA_ECC_FAMILY_SECP_R1 &&\n                psa_get_key_bits(attributes) == 256 )\n            {\n                status = p256_transparent_verify_hash( attributes,\n                                                       key_buffer,\n                                                       key_buffer_size,\n                                                       alg,\n                                                       hash,\n                                                       hash_length,\n                                                       signature,\n                                                       signature_length );\n                if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n            }\n#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n            return( psa_verify_hash_builtin( attributes,\n                                             key_buffer,\n                                             key_buffer_size,\n                                             alg,\n                                             hash,\n                                             hash_length,\n                                             signature,\n                                             signature_length ) );\n\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            return( mbedtls_test_opaque_signature_verify_hash( attributes,\n                                                               key_buffer,\n                                                               key_buffer_size,\n                                                               alg,\n                                                               hash,\n                                                               hash_length,\n                                                               signature,\n                                                               signature_length ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void)status;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline uint32_t psa_driver_wrapper_sign_hash_get_num_ops(\n    psa_sign_hash_interruptible_operation_t *operation )\n{\n    switch( operation->id )\n    {\n        /* If uninitialised, return 0, as no work can have been done. */\n        case 0:\n            return 0;\n\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return(mbedtls_psa_sign_hash_get_num_ops(&operation->ctx.mbedtls_ctx));\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            /* Add test driver tests here */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    /* Can't happen (see discussion in #8271) */\n    return 0;\n}\n\nstatic inline uint32_t psa_driver_wrapper_verify_hash_get_num_ops(\n    psa_verify_hash_interruptible_operation_t *operation )\n{\n    switch( operation->id )\n    {\n        /* If uninitialised, return 0, as no work can have been done. */\n        case 0:\n            return 0;\n\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return (mbedtls_psa_verify_hash_get_num_ops(&operation->ctx.mbedtls_ctx));\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            /* Add test driver tests here */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n    }\n\n    /* Can't happen (see discussion in #8271) */\n    return 0;\n}\n\nstatic inline psa_status_t psa_driver_wrapper_sign_hash_start(\n    psa_sign_hash_interruptible_operation_t *operation,\n    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,\n    size_t key_buffer_size, psa_algorithm_t alg,\n    const uint8_t *hash, size_t hash_length )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(\n                                                    psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n\n            /* Add test driver tests here */\n\n            /* Declared with fallback == true */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n            /* Fell through, meaning no accelerator supports this operation */\n            operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;\n            status = mbedtls_psa_sign_hash_start( &operation->ctx.mbedtls_ctx,\n                                                  attributes,\n                                                  key_buffer, key_buffer_size,\n                                                  alg, hash, hash_length );\n            break;\n\n            /* Add cases for opaque driver here */\n\n        default:\n            /* Key is declared with a lifetime not known to us */\n            status = PSA_ERROR_INVALID_ARGUMENT;\n            break;\n    }\n\n    return( status );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_sign_hash_complete(\n    psa_sign_hash_interruptible_operation_t *operation,\n    uint8_t *signature, size_t signature_size,\n    size_t *signature_length )\n{\n    switch( operation->id )\n    {\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_sign_hash_complete( &operation->ctx.mbedtls_ctx,\n                                                    signature, signature_size,\n                                                    signature_length ) );\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            /* Add test driver tests here */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    ( void ) signature;\n    ( void ) signature_size;\n    ( void ) signature_length;\n\n    return( PSA_ERROR_INVALID_ARGUMENT );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_sign_hash_abort(\n    psa_sign_hash_interruptible_operation_t *operation )\n{\n    switch( operation->id )\n    {\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_sign_hash_abort( &operation->ctx.mbedtls_ctx ) );\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            /* Add test driver tests here */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    return( PSA_ERROR_INVALID_ARGUMENT );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_verify_hash_start(\n    psa_verify_hash_interruptible_operation_t *operation,\n    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,\n    size_t key_buffer_size, psa_algorithm_t alg,\n    const uint8_t *hash, size_t hash_length,\n    const uint8_t *signature, size_t signature_length )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(\n                                                    psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n\n            /* Add test driver tests here */\n\n            /* Declared with fallback == true */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n            /* Fell through, meaning no accelerator supports this operation */\n            operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;\n            status = mbedtls_psa_verify_hash_start( &operation->ctx.mbedtls_ctx,\n                                                    attributes,\n                                                    key_buffer, key_buffer_size,\n                                                    alg, hash, hash_length,\n                                                    signature, signature_length );\n            break;\n\n            /* Add cases for opaque driver here */\n\n        default:\n            /* Key is declared with a lifetime not known to us */\n            status = PSA_ERROR_INVALID_ARGUMENT;\n            break;\n    }\n\n    return( status );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_verify_hash_complete(\n    psa_verify_hash_interruptible_operation_t *operation )\n{\n    switch( operation->id )\n    {\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_verify_hash_complete(\n                                                     &operation->ctx.mbedtls_ctx\n                                                     ) );\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            /* Add test driver tests here */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    return( PSA_ERROR_INVALID_ARGUMENT );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_verify_hash_abort(\n    psa_verify_hash_interruptible_operation_t *operation )\n{\n    switch( operation->id )\n    {\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_verify_hash_abort( &operation->ctx.mbedtls_ctx\n                                                 ) );\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            /* Add test driver tests here */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    return( PSA_ERROR_INVALID_ARGUMENT );\n}\n\n/** Calculate the key buffer size required to store the key material of a key\n *  associated with an opaque driver from input key data.\n *\n * \\param[in] attributes        The key attributes\n * \\param[in] data              The input key data.\n * \\param[in] data_length       The input data length.\n * \\param[out] key_buffer_size  Minimum buffer size to contain the key material.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n */\nstatic inline psa_status_t psa_driver_wrapper_get_key_buffer_size_from_key_data(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *data,\n    size_t data_length,\n    size_t *key_buffer_size )\n{\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n    psa_key_type_t key_type = psa_get_key_type(attributes);\n\n    *key_buffer_size = 0;\n    switch( location )\n    {\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            *key_buffer_size = mbedtls_test_opaque_size_function( key_type,\n                                     PSA_BYTES_TO_BITS( data_length ) );\n            return( ( *key_buffer_size != 0 ) ?\n                    PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n\n        default:\n            (void)key_type;\n            (void)data;\n            (void)data_length;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_generate_key(\n    const psa_key_attributes_t *attributes,\n    const psa_custom_key_parameters_t *custom,\n    const uint8_t *custom_data, size_t custom_data_length,\n    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes));\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)\n    int is_default_production =\n        psa_custom_key_parameters_are_default(custom, custom_data_length);\n    if( location != PSA_KEY_LOCATION_LOCAL_STORAGE && !is_default_production )\n    {\n        /* We don't support passing custom production parameters\n         * to drivers yet. */\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n#else\n    int is_default_production = 1;\n    (void) is_default_production;\n#endif\n\n    /* Try dynamically-registered SE interface first */\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    const psa_drv_se_t *drv;\n    psa_drv_se_context_t *drv_context;\n\n    if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )\n    {\n        size_t pubkey_length = 0; /* We don't support this feature yet */\n        if( drv->key_management == NULL ||\n            drv->key_management->p_generate == NULL )\n        {\n            /* Key is defined as being in SE, but we have no way to generate it */\n            return( PSA_ERROR_NOT_SUPPORTED );\n        }\n        return( drv->key_management->p_generate(\n            drv_context,\n            *( (psa_key_slot_number_t *)key_buffer ),\n            attributes, NULL, 0, &pubkey_length ) );\n    }\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n            /* Transparent drivers are limited to generating asymmetric keys. */\n            /* We don't support passing custom production parameters\n             * to drivers yet. */\n            if( PSA_KEY_TYPE_IS_ASYMMETRIC( psa_get_key_type(attributes) ) &&\n                is_default_production )\n            {\n            /* Cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n                status = mbedtls_test_transparent_generate_key(\n                    attributes, key_buffer, key_buffer_size,\n                    key_buffer_length );\n                /* Declared with fallback == true */\n                if( status != PSA_ERROR_NOT_SUPPORTED )\n                    break;\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)\n                if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) &&\n                    psa_get_key_type(attributes) == PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1) &&\n                    psa_get_key_bits(attributes) == 256 )\n                {\n                    status = p256_transparent_generate_key( attributes,\n                                                            key_buffer,\n                                                            key_buffer_size,\n                                                            key_buffer_length );\n                    if( status != PSA_ERROR_NOT_SUPPORTED )\n                        break;\n                }\n\n#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */\n            }\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n            /* Software fallback */\n            status = psa_generate_key_internal(\n                attributes, custom, custom_data, custom_data_length,\n                key_buffer, key_buffer_size, key_buffer_length );\n            break;\n\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            status = mbedtls_test_opaque_generate_key(\n                attributes, key_buffer, key_buffer_size, key_buffer_length );\n            break;\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n        default:\n            /* Key is declared with a lifetime not known to us */\n            status = PSA_ERROR_INVALID_ARGUMENT;\n            break;\n    }\n\n    return( status );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_import_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *data,\n    size_t data_length,\n    uint8_t *key_buffer,\n    size_t key_buffer_size,\n    size_t *key_buffer_length,\n    size_t *bits )\n{\n\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(\n                                      psa_get_key_lifetime( attributes ) );\n\n    /* Try dynamically-registered SE interface first */\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    const psa_drv_se_t *drv;\n    psa_drv_se_context_t *drv_context;\n\n    if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )\n    {\n        if( drv->key_management == NULL ||\n            drv->key_management->p_import == NULL )\n            return( PSA_ERROR_NOT_SUPPORTED );\n\n        /* The driver should set the number of key bits, however in\n         * case it doesn't, we initialize bits to an invalid value. */\n        *bits = PSA_MAX_KEY_BITS + 1;\n        status = drv->key_management->p_import(\n            drv_context,\n            *( (psa_key_slot_number_t *)key_buffer ),\n            attributes, data, data_length, bits );\n\n        if( status != PSA_SUCCESS )\n            return( status );\n\n        if( (*bits) > PSA_MAX_KEY_BITS )\n            return( PSA_ERROR_NOT_SUPPORTED );\n\n        return( PSA_SUCCESS );\n    }\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n\n#if (defined(PSA_CRYPTO_DRIVER_TEST) )\n            status = mbedtls_test_transparent_import_key\n                (attributes,\n                                data,\n                                data_length,\n                                key_buffer,\n                                key_buffer_size,\n                                key_buffer_length,\n                                bits\n            );\n\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif\n\n#if (defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) )\n            status = p256_transparent_import_key\n                (attributes,\n                                data,\n                                data_length,\n                                key_buffer,\n                                key_buffer_size,\n                                key_buffer_length,\n                                bits\n            );\n\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif\n\n\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n            /* Fell through, meaning no accelerator supports this operation */\n            return( psa_import_key_into_slot( attributes,\n                                              data, data_length,\n                                              key_buffer, key_buffer_size,\n                                              key_buffer_length, bits ) );\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n\n#if (defined(PSA_CRYPTO_DRIVER_TEST) )\n        case 0x7fffff:\n            return( mbedtls_test_opaque_import_key\n            (attributes,\n                            data,\n                            data_length,\n                            key_buffer,\n                            key_buffer_size,\n                            key_buffer_length,\n                            bits\n        ));\n#endif\n\n\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            (void)status;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n\n}\n\nstatic inline psa_status_t psa_driver_wrapper_export_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    uint8_t *data, size_t data_size, size_t *data_length )\n\n{\n\n    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;\n    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(\n                                      psa_get_key_lifetime( attributes ) );\n\n    /* Try dynamically-registered SE interface first */\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    const psa_drv_se_t *drv;\n    psa_drv_se_context_t *drv_context;\n\n    if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )\n    {\n        if( ( drv->key_management == NULL   ) ||\n            ( drv->key_management->p_export == NULL ) )\n        {\n            return( PSA_ERROR_NOT_SUPPORTED );\n        }\n\n        return( drv->key_management->p_export(\n                     drv_context,\n                     *( (psa_key_slot_number_t *)key_buffer ),\n                     data, data_size, data_length ) );\n    }\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            return( psa_export_key_internal( attributes,\n                                             key_buffer,\n                                             key_buffer_size,\n                                             data,\n                                             data_size,\n                                             data_length ) );\n\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n\n#if (defined(PSA_CRYPTO_DRIVER_TEST) )\n        case 0x7fffff:\n            return( mbedtls_test_opaque_export_key\n            (attributes,\n                            key_buffer,\n                            key_buffer_size,\n                            data,\n                            data_size,\n                            data_length\n        ));\n#endif\n\n\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            /* Key is declared with a lifetime not known to us */\n            return( status );\n    }\n\n}\n\nstatic inline psa_status_t psa_driver_wrapper_copy_key(\n    psa_key_attributes_t *attributes,\n    const uint8_t *source_key, size_t source_key_length,\n    uint8_t *target_key_buffer, size_t target_key_buffer_size,\n    size_t *target_key_buffer_length )\n{\n\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    const psa_drv_se_t *drv;\n    psa_drv_se_context_t *drv_context;\n\n    if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )\n    {\n        /* Copying to a secure element is not implemented yet. */\n        return( PSA_ERROR_NOT_SUPPORTED );\n    }\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n    switch( location )\n    {\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n\n#if (defined(PSA_CRYPTO_DRIVER_TEST) )\n        case 0x7fffff:\n            return( mbedtls_test_opaque_copy_key\n            (attributes,\n                            source_key,\n                            source_key_length,\n                            target_key_buffer,\n                            target_key_buffer_size,\n                            target_key_buffer_length\n        ));\n#endif\n\n\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            (void)source_key;\n            (void)source_key_length;\n            (void)target_key_buffer;\n            (void)target_key_buffer_size;\n            (void)target_key_buffer_length;\n            status = PSA_ERROR_INVALID_ARGUMENT;\n    }\n    return( status );\n\n}\n\n/*\n * Cipher functions\n */\nstatic inline psa_status_t psa_driver_wrapper_cipher_encrypt(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *iv,\n    size_t iv_length,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *output,\n    size_t output_size,\n    size_t *output_length )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_cipher_encrypt( attributes,\n                                                              key_buffer,\n                                                              key_buffer_size,\n                                                              alg,\n                                                              iv,\n                                                              iv_length,\n                                                              input,\n                                                              input_length,\n                                                              output,\n                                                              output_size,\n                                                              output_length );\n            /* Declared with fallback == true */\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)\n            return( mbedtls_psa_cipher_encrypt( attributes,\n                                                key_buffer,\n                                                key_buffer_size,\n                                                alg,\n                                                iv,\n                                                iv_length,\n                                                input,\n                                                input_length,\n                                                output,\n                                                output_size,\n                                                output_length ) );\n#else\n            return( PSA_ERROR_NOT_SUPPORTED );\n#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */\n\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            return( mbedtls_test_opaque_cipher_encrypt( attributes,\n                                                        key_buffer,\n                                                        key_buffer_size,\n                                                        alg,\n                                                        iv,\n                                                        iv_length,\n                                                        input,\n                                                        input_length,\n                                                        output,\n                                                        output_size,\n                                                        output_length ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void)status;\n            (void)key_buffer;\n            (void)key_buffer_size;\n            (void)alg;\n            (void)iv;\n            (void)iv_length;\n            (void)input;\n            (void)input_length;\n            (void)output;\n            (void)output_size;\n            (void)output_length;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_cipher_decrypt(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *output,\n    size_t output_size,\n    size_t *output_length )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_cipher_decrypt( attributes,\n                                                              key_buffer,\n                                                              key_buffer_size,\n                                                              alg,\n                                                              input,\n                                                              input_length,\n                                                              output,\n                                                              output_size,\n                                                              output_length );\n            /* Declared with fallback == true */\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)\n            return( mbedtls_psa_cipher_decrypt( attributes,\n                                                key_buffer,\n                                                key_buffer_size,\n                                                alg,\n                                                input,\n                                                input_length,\n                                                output,\n                                                output_size,\n                                                output_length ) );\n#else\n            return( PSA_ERROR_NOT_SUPPORTED );\n#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */\n\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            return( mbedtls_test_opaque_cipher_decrypt( attributes,\n                                                        key_buffer,\n                                                        key_buffer_size,\n                                                        alg,\n                                                        input,\n                                                        input_length,\n                                                        output,\n                                                        output_size,\n                                                        output_length ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void)status;\n            (void)key_buffer;\n            (void)key_buffer_size;\n            (void)alg;\n            (void)input;\n            (void)input_length;\n            (void)output;\n            (void)output_size;\n            (void)output_length;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_cipher_encrypt_setup(\n    psa_cipher_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_cipher_encrypt_setup(\n                &operation->ctx.transparent_test_driver_ctx,\n                attributes,\n                key_buffer,\n                key_buffer_size,\n                alg );\n            /* Declared with fallback == true */\n            if( status == PSA_SUCCESS )\n                operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;\n\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)\n            /* Fell through, meaning no accelerator supports this operation */\n            status = mbedtls_psa_cipher_encrypt_setup( &operation->ctx.mbedtls_ctx,\n                                                       attributes,\n                                                       key_buffer,\n                                                       key_buffer_size,\n                                                       alg );\n            if( status == PSA_SUCCESS )\n                operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;\n\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */\n            return( PSA_ERROR_NOT_SUPPORTED );\n\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            status = mbedtls_test_opaque_cipher_encrypt_setup(\n                &operation->ctx.opaque_test_driver_ctx,\n                attributes,\n                key_buffer, key_buffer_size,\n                alg );\n\n            if( status == PSA_SUCCESS )\n                operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID;\n\n            return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void)status;\n            (void)operation;\n            (void)key_buffer;\n            (void)key_buffer_size;\n            (void)alg;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_cipher_decrypt_setup(\n    psa_cipher_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg )\n{\n    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_cipher_decrypt_setup(\n                &operation->ctx.transparent_test_driver_ctx,\n                attributes,\n                key_buffer,\n                key_buffer_size,\n                alg );\n            /* Declared with fallback == true */\n            if( status == PSA_SUCCESS )\n                operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;\n\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)\n            /* Fell through, meaning no accelerator supports this operation */\n            status = mbedtls_psa_cipher_decrypt_setup( &operation->ctx.mbedtls_ctx,\n                                                       attributes,\n                                                       key_buffer,\n                                                       key_buffer_size,\n                                                       alg );\n            if( status == PSA_SUCCESS )\n                operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;\n\n            return( status );\n#else /* MBEDTLS_PSA_BUILTIN_CIPHER */\n            return( PSA_ERROR_NOT_SUPPORTED );\n#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */\n\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            status = mbedtls_test_opaque_cipher_decrypt_setup(\n                         &operation->ctx.opaque_test_driver_ctx,\n                         attributes,\n                         key_buffer, key_buffer_size,\n                         alg );\n\n            if( status == PSA_SUCCESS )\n                operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID;\n\n            return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void)status;\n            (void)operation;\n            (void)key_buffer;\n            (void)key_buffer_size;\n            (void)alg;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_cipher_set_iv(\n    psa_cipher_operation_t *operation,\n    const uint8_t *iv,\n    size_t iv_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_cipher_set_iv( &operation->ctx.mbedtls_ctx,\n                                               iv,\n                                               iv_length ) );\n#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_cipher_set_iv(\n                        &operation->ctx.transparent_test_driver_ctx,\n                        iv, iv_length ) );\n\n        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:\n            return( mbedtls_test_opaque_cipher_set_iv(\n                        &operation->ctx.opaque_test_driver_ctx,\n                        iv, iv_length ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    (void)iv;\n    (void)iv_length;\n\n    return( PSA_ERROR_INVALID_ARGUMENT );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_cipher_update(\n    psa_cipher_operation_t *operation,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *output,\n    size_t output_size,\n    size_t *output_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_cipher_update( &operation->ctx.mbedtls_ctx,\n                                               input,\n                                               input_length,\n                                               output,\n                                               output_size,\n                                               output_length ) );\n#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_cipher_update(\n                        &operation->ctx.transparent_test_driver_ctx,\n                        input, input_length,\n                        output, output_size, output_length ) );\n\n        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:\n            return( mbedtls_test_opaque_cipher_update(\n                        &operation->ctx.opaque_test_driver_ctx,\n                        input, input_length,\n                        output, output_size, output_length ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    (void)input;\n    (void)input_length;\n    (void)output;\n    (void)output_size;\n    (void)output_length;\n\n    return( PSA_ERROR_INVALID_ARGUMENT );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_cipher_finish(\n    psa_cipher_operation_t *operation,\n    uint8_t *output,\n    size_t output_size,\n    size_t *output_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_cipher_finish( &operation->ctx.mbedtls_ctx,\n                                               output,\n                                               output_size,\n                                               output_length ) );\n#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_cipher_finish(\n                        &operation->ctx.transparent_test_driver_ctx,\n                        output, output_size, output_length ) );\n\n        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:\n            return( mbedtls_test_opaque_cipher_finish(\n                        &operation->ctx.opaque_test_driver_ctx,\n                        output, output_size, output_length ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    (void)output;\n    (void)output_size;\n    (void)output_length;\n\n    return( PSA_ERROR_INVALID_ARGUMENT );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_cipher_abort(\n    psa_cipher_operation_t *operation )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_cipher_abort( &operation->ctx.mbedtls_ctx ) );\n#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            status = mbedtls_test_transparent_cipher_abort(\n                         &operation->ctx.transparent_test_driver_ctx );\n            mbedtls_platform_zeroize(\n                &operation->ctx.transparent_test_driver_ctx,\n                sizeof( operation->ctx.transparent_test_driver_ctx ) );\n            return( status );\n\n        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:\n            status = mbedtls_test_opaque_cipher_abort(\n                         &operation->ctx.opaque_test_driver_ctx );\n            mbedtls_platform_zeroize(\n                &operation->ctx.opaque_test_driver_ctx,\n                sizeof( operation->ctx.opaque_test_driver_ctx ) );\n            return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    (void)status;\n    return( PSA_ERROR_INVALID_ARGUMENT );\n}\n\n/*\n * Hashing functions\n */\nstatic inline psa_status_t psa_driver_wrapper_hash_compute(\n    psa_algorithm_t alg,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *hash,\n    size_t hash_size,\n    size_t *hash_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    /* Try accelerators first */\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n    status = mbedtls_test_transparent_hash_compute(\n                alg, input, input_length, hash, hash_size, hash_length );\n    if( status != PSA_ERROR_NOT_SUPPORTED )\n        return( status );\n#endif\n\n    /* If software fallback is compiled in, try fallback */\n#if defined(MBEDTLS_PSA_BUILTIN_HASH)\n    status = mbedtls_psa_hash_compute( alg, input, input_length,\n                                       hash, hash_size, hash_length );\n    if( status != PSA_ERROR_NOT_SUPPORTED )\n        return( status );\n#endif\n    (void) status;\n    (void) alg;\n    (void) input;\n    (void) input_length;\n    (void) hash;\n    (void) hash_size;\n    (void) hash_length;\n\n    return( PSA_ERROR_NOT_SUPPORTED );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_hash_setup(\n    psa_hash_operation_t *operation,\n    psa_algorithm_t alg )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    /* Try setup on accelerators first */\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n    status = mbedtls_test_transparent_hash_setup(\n                &operation->ctx.test_driver_ctx, alg );\n    if( status == PSA_SUCCESS )\n        operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;\n\n    if( status != PSA_ERROR_NOT_SUPPORTED )\n        return( status );\n#endif\n\n    /* If software fallback is compiled in, try fallback */\n#if defined(MBEDTLS_PSA_BUILTIN_HASH)\n    status = mbedtls_psa_hash_setup( &operation->ctx.mbedtls_ctx, alg );\n    if( status == PSA_SUCCESS )\n        operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;\n\n    if( status != PSA_ERROR_NOT_SUPPORTED )\n        return( status );\n#endif\n    /* Nothing left to try if we fall through here */\n    (void) status;\n    (void) operation;\n    (void) alg;\n    return( PSA_ERROR_NOT_SUPPORTED );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_hash_clone(\n    const psa_hash_operation_t *source_operation,\n    psa_hash_operation_t *target_operation )\n{\n    switch( source_operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_HASH)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            target_operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;\n            return( mbedtls_psa_hash_clone( &source_operation->ctx.mbedtls_ctx,\n                                            &target_operation->ctx.mbedtls_ctx ) );\n#endif\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            target_operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;\n            return( mbedtls_test_transparent_hash_clone(\n                        &source_operation->ctx.test_driver_ctx,\n                        &target_operation->ctx.test_driver_ctx ) );\n#endif\n        default:\n            (void) target_operation;\n            return( PSA_ERROR_BAD_STATE );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_hash_update(\n    psa_hash_operation_t *operation,\n    const uint8_t *input,\n    size_t input_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_HASH)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_hash_update( &operation->ctx.mbedtls_ctx,\n                                             input, input_length ) );\n#endif\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_hash_update(\n                        &operation->ctx.test_driver_ctx,\n                        input, input_length ) );\n#endif\n        default:\n            (void) input;\n            (void) input_length;\n            return( PSA_ERROR_BAD_STATE );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_hash_finish(\n    psa_hash_operation_t *operation,\n    uint8_t *hash,\n    size_t hash_size,\n    size_t *hash_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_HASH)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_hash_finish( &operation->ctx.mbedtls_ctx,\n                                             hash, hash_size, hash_length ) );\n#endif\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_hash_finish(\n                        &operation->ctx.test_driver_ctx,\n                        hash, hash_size, hash_length ) );\n#endif\n        default:\n            (void) hash;\n            (void) hash_size;\n            (void) hash_length;\n            return( PSA_ERROR_BAD_STATE );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_hash_abort(\n    psa_hash_operation_t *operation )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_HASH)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_hash_abort( &operation->ctx.mbedtls_ctx ) );\n#endif\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_hash_abort(\n                        &operation->ctx.test_driver_ctx ) );\n#endif\n        default:\n            return( PSA_ERROR_BAD_STATE );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_aead_encrypt(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *nonce, size_t nonce_length,\n    const uint8_t *additional_data, size_t additional_data_length,\n    const uint8_t *plaintext, size_t plaintext_length,\n    uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_aead_encrypt(\n                         attributes, key_buffer, key_buffer_size,\n                         alg,\n                         nonce, nonce_length,\n                         additional_data, additional_data_length,\n                         plaintext, plaintext_length,\n                         ciphertext, ciphertext_size, ciphertext_length );\n            /* Declared with fallback == true */\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n            /* Fell through, meaning no accelerator supports this operation */\n            return( mbedtls_psa_aead_encrypt(\n                        attributes, key_buffer, key_buffer_size,\n                        alg,\n                        nonce, nonce_length,\n                        additional_data, additional_data_length,\n                        plaintext, plaintext_length,\n                        ciphertext, ciphertext_size, ciphertext_length ) );\n\n        /* Add cases for opaque driver here */\n\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void)status;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_aead_decrypt(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *nonce, size_t nonce_length,\n    const uint8_t *additional_data, size_t additional_data_length,\n    const uint8_t *ciphertext, size_t ciphertext_length,\n    uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_aead_decrypt(\n                        attributes, key_buffer, key_buffer_size,\n                        alg,\n                        nonce, nonce_length,\n                        additional_data, additional_data_length,\n                        ciphertext, ciphertext_length,\n                        plaintext, plaintext_size, plaintext_length );\n            /* Declared with fallback == true */\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n            /* Fell through, meaning no accelerator supports this operation */\n            return( mbedtls_psa_aead_decrypt(\n                        attributes, key_buffer, key_buffer_size,\n                        alg,\n                        nonce, nonce_length,\n                        additional_data, additional_data_length,\n                        ciphertext, ciphertext_length,\n                        plaintext, plaintext_size, plaintext_length ) );\n\n        /* Add cases for opaque driver here */\n\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void)status;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_aead_encrypt_setup(\n   psa_aead_operation_t *operation,\n   const psa_key_attributes_t *attributes,\n   const uint8_t *key_buffer, size_t key_buffer_size,\n   psa_algorithm_t alg )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;\n            status = mbedtls_test_transparent_aead_encrypt_setup(\n                        &operation->ctx.transparent_test_driver_ctx,\n                        attributes, key_buffer, key_buffer_size,\n                        alg );\n\n            /* Declared with fallback == true */\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n            /* Fell through, meaning no accelerator supports this operation */\n            operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;\n            status = mbedtls_psa_aead_encrypt_setup(\n                        &operation->ctx.mbedtls_ctx, attributes,\n                        key_buffer, key_buffer_size,\n                        alg );\n\n            return( status );\n\n        /* Add cases for opaque driver here */\n\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void)status;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_aead_decrypt_setup(\n   psa_aead_operation_t *operation,\n   const psa_key_attributes_t *attributes,\n   const uint8_t *key_buffer, size_t key_buffer_size,\n   psa_algorithm_t alg )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;\n            status = mbedtls_test_transparent_aead_decrypt_setup(\n                        &operation->ctx.transparent_test_driver_ctx,\n                        attributes,\n                        key_buffer, key_buffer_size,\n                        alg );\n\n            /* Declared with fallback == true */\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n            /* Fell through, meaning no accelerator supports this operation */\n            operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;\n            status = mbedtls_psa_aead_decrypt_setup(\n                        &operation->ctx.mbedtls_ctx,\n                        attributes,\n                        key_buffer, key_buffer_size,\n                        alg );\n\n            return( status );\n\n        /* Add cases for opaque driver here */\n\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void)status;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_aead_set_nonce(\n   psa_aead_operation_t *operation,\n   const uint8_t *nonce,\n   size_t nonce_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_AEAD)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_aead_set_nonce( &operation->ctx.mbedtls_ctx,\n                                                nonce,\n                                                nonce_length ) );\n\n#endif /* MBEDTLS_PSA_BUILTIN_AEAD */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_aead_set_nonce(\n                         &operation->ctx.transparent_test_driver_ctx,\n                         nonce, nonce_length ) );\n\n        /* Add cases for opaque driver here */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    (void)nonce;\n    (void)nonce_length;\n\n    return( PSA_ERROR_INVALID_ARGUMENT );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_aead_set_lengths(\n   psa_aead_operation_t *operation,\n   size_t ad_length,\n   size_t plaintext_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_AEAD)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_aead_set_lengths( &operation->ctx.mbedtls_ctx,\n                                                  ad_length,\n                                                  plaintext_length ) );\n\n#endif /* MBEDTLS_PSA_BUILTIN_AEAD */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_aead_set_lengths(\n                        &operation->ctx.transparent_test_driver_ctx,\n                        ad_length, plaintext_length ) );\n\n        /* Add cases for opaque driver here */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    (void)ad_length;\n    (void)plaintext_length;\n\n    return( PSA_ERROR_INVALID_ARGUMENT );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_aead_update_ad(\n   psa_aead_operation_t *operation,\n   const uint8_t *input,\n   size_t input_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_AEAD)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_aead_update_ad( &operation->ctx.mbedtls_ctx,\n                                                input,\n                                                input_length ) );\n\n#endif /* MBEDTLS_PSA_BUILTIN_AEAD */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_aead_update_ad(\n                        &operation->ctx.transparent_test_driver_ctx,\n                        input, input_length ) );\n\n        /* Add cases for opaque driver here */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    (void)input;\n    (void)input_length;\n\n    return( PSA_ERROR_INVALID_ARGUMENT );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_aead_update(\n   psa_aead_operation_t *operation,\n   const uint8_t *input,\n   size_t input_length,\n   uint8_t *output,\n   size_t output_size,\n   size_t *output_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_AEAD)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_aead_update( &operation->ctx.mbedtls_ctx,\n                                             input, input_length,\n                                             output, output_size,\n                                             output_length ) );\n\n#endif /* MBEDTLS_PSA_BUILTIN_AEAD */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_aead_update(\n                        &operation->ctx.transparent_test_driver_ctx,\n                        input, input_length, output, output_size,\n                        output_length ) );\n\n        /* Add cases for opaque driver here */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    (void)input;\n    (void)input_length;\n    (void)output;\n    (void)output_size;\n    (void)output_length;\n\n    return( PSA_ERROR_INVALID_ARGUMENT );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_aead_finish(\n   psa_aead_operation_t *operation,\n   uint8_t *ciphertext,\n   size_t ciphertext_size,\n   size_t *ciphertext_length,\n   uint8_t *tag,\n   size_t tag_size,\n   size_t *tag_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_AEAD)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx,\n                                             ciphertext,\n                                             ciphertext_size,\n                                             ciphertext_length, tag,\n                                             tag_size, tag_length ) );\n\n#endif /* MBEDTLS_PSA_BUILTIN_AEAD */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_aead_finish(\n                        &operation->ctx.transparent_test_driver_ctx,\n                        ciphertext, ciphertext_size,\n                        ciphertext_length, tag, tag_size, tag_length ) );\n\n        /* Add cases for opaque driver here */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    (void)ciphertext;\n    (void)ciphertext_size;\n    (void)ciphertext_length;\n    (void)tag;\n    (void)tag_size;\n    (void)tag_length;\n\n    return( PSA_ERROR_INVALID_ARGUMENT );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_aead_verify(\n   psa_aead_operation_t *operation,\n   uint8_t *plaintext,\n   size_t plaintext_size,\n   size_t *plaintext_length,\n   const uint8_t *tag,\n   size_t tag_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_AEAD)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            {\n                psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n                uint8_t check_tag[PSA_AEAD_TAG_MAX_SIZE];\n                size_t check_tag_length;\n\n                status = mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx,\n                                                  plaintext,\n                                                  plaintext_size,\n                                                  plaintext_length,\n                                                  check_tag,\n                                                  sizeof( check_tag ),\n                                                  &check_tag_length );\n\n                if( status == PSA_SUCCESS )\n                {\n                    if( tag_length != check_tag_length ||\n                        mbedtls_ct_memcmp( tag, check_tag, tag_length )\n                        != 0 )\n                        status = PSA_ERROR_INVALID_SIGNATURE;\n                }\n\n                mbedtls_platform_zeroize( check_tag, sizeof( check_tag ) );\n\n                return( status );\n            }\n\n#endif /* MBEDTLS_PSA_BUILTIN_AEAD */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_aead_verify(\n                        &operation->ctx.transparent_test_driver_ctx,\n                        plaintext, plaintext_size,\n                        plaintext_length, tag, tag_length ) );\n\n        /* Add cases for opaque driver here */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    (void)plaintext;\n    (void)plaintext_size;\n    (void)plaintext_length;\n    (void)tag;\n    (void)tag_length;\n\n    return( PSA_ERROR_INVALID_ARGUMENT );\n}\n\nstatic inline psa_status_t psa_driver_wrapper_aead_abort(\n   psa_aead_operation_t *operation )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_AEAD)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_aead_abort( &operation->ctx.mbedtls_ctx ) );\n\n#endif /* MBEDTLS_PSA_BUILTIN_AEAD */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_aead_abort(\n               &operation->ctx.transparent_test_driver_ctx ) );\n\n        /* Add cases for opaque driver here */\n\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n    }\n\n    return( PSA_ERROR_INVALID_ARGUMENT );\n}\n\n/*\n * MAC functions\n */\nstatic inline psa_status_t psa_driver_wrapper_mac_compute(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *mac,\n    size_t mac_size,\n    size_t *mac_length )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_mac_compute(\n                attributes, key_buffer, key_buffer_size, alg,\n                input, input_length,\n                mac, mac_size, mac_length );\n            /* Declared with fallback == true */\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n#if defined(MBEDTLS_PSA_BUILTIN_MAC)\n            /* Fell through, meaning no accelerator supports this operation */\n            status = mbedtls_psa_mac_compute(\n                attributes, key_buffer, key_buffer_size, alg,\n                input, input_length,\n                mac, mac_size, mac_length );\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* MBEDTLS_PSA_BUILTIN_MAC */\n            return( PSA_ERROR_NOT_SUPPORTED );\n\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            status = mbedtls_test_opaque_mac_compute(\n                attributes, key_buffer, key_buffer_size, alg,\n                input, input_length,\n                mac, mac_size, mac_length );\n            return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void) key_buffer;\n            (void) key_buffer_size;\n            (void) alg;\n            (void) input;\n            (void) input_length;\n            (void) mac;\n            (void) mac_size;\n            (void) mac_length;\n            (void) status;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_mac_sign_setup(\n    psa_mac_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_mac_sign_setup(\n                &operation->ctx.transparent_test_driver_ctx,\n                attributes,\n                key_buffer, key_buffer_size,\n                alg );\n            /* Declared with fallback == true */\n            if( status == PSA_SUCCESS )\n                operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;\n\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n#if defined(MBEDTLS_PSA_BUILTIN_MAC)\n            /* Fell through, meaning no accelerator supports this operation */\n            status = mbedtls_psa_mac_sign_setup( &operation->ctx.mbedtls_ctx,\n                                                 attributes,\n                                                 key_buffer, key_buffer_size,\n                                                 alg );\n            if( status == PSA_SUCCESS )\n                operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;\n\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* MBEDTLS_PSA_BUILTIN_MAC */\n            return( PSA_ERROR_NOT_SUPPORTED );\n\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            status = mbedtls_test_opaque_mac_sign_setup(\n                &operation->ctx.opaque_test_driver_ctx,\n                attributes,\n                key_buffer, key_buffer_size,\n                alg );\n\n            if( status == PSA_SUCCESS )\n                operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID;\n\n            return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void) status;\n            (void) operation;\n            (void) key_buffer;\n            (void) key_buffer_size;\n            (void) alg;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_mac_verify_setup(\n    psa_mac_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_mac_verify_setup(\n                &operation->ctx.transparent_test_driver_ctx,\n                attributes,\n                key_buffer, key_buffer_size,\n                alg );\n            /* Declared with fallback == true */\n            if( status == PSA_SUCCESS )\n                operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;\n\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n#if defined(MBEDTLS_PSA_BUILTIN_MAC)\n            /* Fell through, meaning no accelerator supports this operation */\n            status = mbedtls_psa_mac_verify_setup( &operation->ctx.mbedtls_ctx,\n                                                   attributes,\n                                                   key_buffer, key_buffer_size,\n                                                   alg );\n            if( status == PSA_SUCCESS )\n                operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;\n\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* MBEDTLS_PSA_BUILTIN_MAC */\n            return( PSA_ERROR_NOT_SUPPORTED );\n\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            status = mbedtls_test_opaque_mac_verify_setup(\n                &operation->ctx.opaque_test_driver_ctx,\n                attributes,\n                key_buffer, key_buffer_size,\n                alg );\n\n            if( status == PSA_SUCCESS )\n                operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID;\n\n            return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void) status;\n            (void) operation;\n            (void) key_buffer;\n            (void) key_buffer_size;\n            (void) alg;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_mac_update(\n    psa_mac_operation_t *operation,\n    const uint8_t *input,\n    size_t input_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_MAC)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_mac_update( &operation->ctx.mbedtls_ctx,\n                                            input, input_length ) );\n#endif /* MBEDTLS_PSA_BUILTIN_MAC */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_mac_update(\n                        &operation->ctx.transparent_test_driver_ctx,\n                        input, input_length ) );\n\n        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:\n            return( mbedtls_test_opaque_mac_update(\n                        &operation->ctx.opaque_test_driver_ctx,\n                        input, input_length ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            (void) input;\n            (void) input_length;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_mac_sign_finish(\n    psa_mac_operation_t *operation,\n    uint8_t *mac,\n    size_t mac_size,\n    size_t *mac_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_MAC)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_mac_sign_finish( &operation->ctx.mbedtls_ctx,\n                                                 mac, mac_size, mac_length ) );\n#endif /* MBEDTLS_PSA_BUILTIN_MAC */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_mac_sign_finish(\n                        &operation->ctx.transparent_test_driver_ctx,\n                        mac, mac_size, mac_length ) );\n\n        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:\n            return( mbedtls_test_opaque_mac_sign_finish(\n                        &operation->ctx.opaque_test_driver_ctx,\n                        mac, mac_size, mac_length ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            (void) mac;\n            (void) mac_size;\n            (void) mac_length;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_mac_verify_finish(\n    psa_mac_operation_t *operation,\n    const uint8_t *mac,\n    size_t mac_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_MAC)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_mac_verify_finish( &operation->ctx.mbedtls_ctx,\n                                                   mac, mac_length ) );\n#endif /* MBEDTLS_PSA_BUILTIN_MAC */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_mac_verify_finish(\n                        &operation->ctx.transparent_test_driver_ctx,\n                        mac, mac_length ) );\n\n        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:\n            return( mbedtls_test_opaque_mac_verify_finish(\n                        &operation->ctx.opaque_test_driver_ctx,\n                        mac, mac_length ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            (void) mac;\n            (void) mac_length;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_mac_abort(\n    psa_mac_operation_t *operation )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_MAC)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_mac_abort( &operation->ctx.mbedtls_ctx ) );\n#endif /* MBEDTLS_PSA_BUILTIN_MAC */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_mac_abort(\n                        &operation->ctx.transparent_test_driver_ctx ) );\n        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:\n            return( mbedtls_test_opaque_mac_abort(\n                        &operation->ctx.opaque_test_driver_ctx ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\n/*\n * Asymmetric cryptography\n */\nstatic inline psa_status_t psa_driver_wrapper_asymmetric_encrypt(\n    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,\n    size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input,\n    size_t input_length, const uint8_t *salt, size_t salt_length,\n    uint8_t *output, size_t output_size, size_t *output_length )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_asymmetric_encrypt( attributes,\n                        key_buffer, key_buffer_size, alg, input, input_length,\n                        salt, salt_length, output, output_size,\n                        output_length );\n            /* Declared with fallback == true */\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n            return( mbedtls_psa_asymmetric_encrypt( attributes,\n                        key_buffer, key_buffer_size, alg, input, input_length,\n                        salt, salt_length, output, output_size, output_length )\n                  );\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            return( mbedtls_test_opaque_asymmetric_encrypt( attributes,\n                        key_buffer, key_buffer_size, alg, input, input_length,\n                        salt, salt_length, output, output_size, output_length )\n                  );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void)status;\n            (void)key_buffer;\n            (void)key_buffer_size;\n            (void)alg;\n            (void)input;\n            (void)input_length;\n            (void)salt;\n            (void)salt_length;\n            (void)output;\n            (void)output_size;\n            (void)output_length;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_asymmetric_decrypt(\n    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,\n    size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input,\n    size_t input_length, const uint8_t *salt, size_t salt_length,\n    uint8_t *output, size_t output_size, size_t *output_length )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_asymmetric_decrypt( attributes,\n                        key_buffer, key_buffer_size, alg, input, input_length,\n                        salt, salt_length, output, output_size,\n                        output_length );\n            /* Declared with fallback == true */\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n            return( mbedtls_psa_asymmetric_decrypt( attributes,\n                        key_buffer, key_buffer_size, alg,input, input_length,\n                        salt, salt_length, output, output_size,\n                        output_length ) );\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            return( mbedtls_test_opaque_asymmetric_decrypt( attributes,\n                        key_buffer, key_buffer_size, alg, input, input_length,\n                        salt, salt_length, output, output_size,\n                        output_length ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void)status;\n            (void)key_buffer;\n            (void)key_buffer_size;\n            (void)alg;\n            (void)input;\n            (void)input_length;\n            (void)salt;\n            (void)salt_length;\n            (void)output;\n            (void)output_size;\n            (void)output_length;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_key_agreement(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *peer_key,\n    size_t peer_key_length,\n    uint8_t *shared_secret,\n    size_t shared_secret_size,\n    size_t *shared_secret_length\n )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_location_t location =\n        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status =\n                mbedtls_test_transparent_key_agreement( attributes,\n                        key_buffer, key_buffer_size, alg, peer_key,\n                        peer_key_length, shared_secret, shared_secret_size,\n                        shared_secret_length );\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)\n            if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) &&\n                PSA_ALG_IS_ECDH(alg) &&\n                PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(attributes)) == PSA_ECC_FAMILY_SECP_R1 &&\n                psa_get_key_bits(attributes) == 256 )\n            {\n                status = p256_transparent_key_agreement( attributes,\n                                                         key_buffer,\n                                                         key_buffer_size,\n                                                         alg,\n                                                         peer_key,\n                                                         peer_key_length,\n                                                         shared_secret,\n                                                         shared_secret_size,\n                                                         shared_secret_length );\n                if( status != PSA_ERROR_NOT_SUPPORTED)\n                    return( status );\n            }\n#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n            /* Software Fallback */\n            status = psa_key_agreement_raw_builtin( attributes,\n                                                    key_buffer,\n                                                    key_buffer_size,\n                                                    alg,\n                                                    peer_key,\n                                                    peer_key_length,\n                                                    shared_secret,\n                                                    shared_secret_size,\n                                                    shared_secret_length );\n            return( status );\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n            return( mbedtls_test_opaque_key_agreement( attributes,\n                        key_buffer, key_buffer_size, alg, peer_key,\n                        peer_key_length, shared_secret, shared_secret_size,\n                        shared_secret_length ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n\n        default:\n            (void) attributes;\n            (void) key_buffer;\n            (void) key_buffer_size;\n            (void) peer_key;\n            (void) peer_key_length;\n            (void) shared_secret;\n            (void) shared_secret_size;\n            (void) shared_secret_length;\n            return( PSA_ERROR_NOT_SUPPORTED );\n\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_pake_setup(\n    psa_pake_operation_t *operation,\n    const psa_crypto_driver_pake_inputs_t *inputs )\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    psa_key_location_t location =\n            PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( &inputs->attributes ) );\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n            status = PSA_ERROR_NOT_SUPPORTED;\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n            status = mbedtls_test_transparent_pake_setup(\n                        &operation->data.ctx.transparent_test_driver_ctx,\n                        inputs );\n            if( status == PSA_SUCCESS )\n                operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;\n            /* Declared with fallback == true */\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n#if defined(MBEDTLS_PSA_BUILTIN_PAKE)\n            status = mbedtls_psa_pake_setup( &operation->data.ctx.mbedtls_ctx,\n                        inputs );\n            if( status == PSA_SUCCESS )\n                operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;\n#endif\n            return status;\n        /* Add cases for opaque driver here */\n        default:\n            /* Key is declared with a lifetime not known to us */\n            (void)operation;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_pake_output(\n    psa_pake_operation_t *operation,\n    psa_crypto_driver_pake_step_t step,\n    uint8_t *output,\n    size_t output_size,\n    size_t *output_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_PAKE)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_pake_output( &operation->data.ctx.mbedtls_ctx, step,\n                                             output, output_size, output_length ) );\n#endif /* MBEDTLS_PSA_BUILTIN_PAKE */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_pake_output(\n                        &operation->data.ctx.transparent_test_driver_ctx,\n                        step, output, output_size, output_length ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            (void) step;\n            (void) output;\n            (void) output_size;\n            (void) output_length;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_pake_input(\n    psa_pake_operation_t *operation,\n    psa_crypto_driver_pake_step_t step,\n    const uint8_t *input,\n    size_t input_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_PAKE)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_pake_input( &operation->data.ctx.mbedtls_ctx,\n                                            step, input,\n                                            input_length ) );\n#endif /* MBEDTLS_PSA_BUILTIN_PAKE */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_pake_input(\n                        &operation->data.ctx.transparent_test_driver_ctx,\n                        step,\n                        input, input_length ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            (void) step;\n            (void) input;\n            (void) input_length;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_pake_get_implicit_key(\n    psa_pake_operation_t *operation,\n    uint8_t *output, size_t output_size,\n    size_t *output_length )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_PAKE)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_pake_get_implicit_key( &operation->data.ctx.mbedtls_ctx,\n                                                       output, output_size, output_length ) );\n#endif /* MBEDTLS_PSA_BUILTIN_PAKE */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_pake_get_implicit_key(\n                        &operation->data.ctx.transparent_test_driver_ctx,\n                        output, output_size, output_length ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            (void) output;\n            (void) output_size;\n            (void) output_length;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\nstatic inline psa_status_t psa_driver_wrapper_pake_abort(\n    psa_pake_operation_t * operation )\n{\n    switch( operation->id )\n    {\n#if defined(MBEDTLS_PSA_BUILTIN_PAKE)\n        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:\n            return( mbedtls_psa_pake_abort( &operation->data.ctx.mbedtls_ctx ) );\n#endif /* MBEDTLS_PSA_BUILTIN_PAKE */\n\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:\n            return( mbedtls_test_transparent_pake_abort(\n                        &operation->data.ctx.transparent_test_driver_ctx ) );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_driver_wrappers_no_static.c",
    "content": "/*\n *  Functions to delegate cryptographic operations to an available\n *  and appropriate accelerator.\n *  Warning: This file is now auto-generated.\n */\n/*  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n\n/* BEGIN-common headers */\n#include \"common.h\"\n#include \"psa_crypto_aead.h\"\n#include \"psa_crypto_cipher.h\"\n#include \"psa_crypto_core.h\"\n#include \"psa_crypto_driver_wrappers_no_static.h\"\n#include \"psa_crypto_hash.h\"\n#include \"psa_crypto_mac.h\"\n#include \"psa_crypto_pake.h\"\n#include \"psa_crypto_rsa.h\"\n\n#include \"mbedtls/platform.h\"\n/* END-common headers */\n\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n\n/* BEGIN-driver headers */\n/* Headers for mbedtls_test opaque driver */\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n#include \"test/drivers/test_driver.h\"\n\n#endif\n/* Headers for mbedtls_test transparent driver */\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n#include \"test/drivers/test_driver.h\"\n\n#endif\n/* Headers for p256 transparent driver */\n#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)\n#include \"../3rdparty/p256-m/p256-m_driver_entrypoints.h\"\n\n#endif\n\n/* END-driver headers */\n\n/* Auto-generated values depending on which drivers are registered.\n * ID 0 is reserved for unallocated operations.\n * ID 1 is reserved for the Mbed TLS software driver. */\n/* BEGIN-driver id definition */\n#define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1)\n#define MBEDTLS_TEST_OPAQUE_DRIVER_ID (2)\n#define MBEDTLS_TEST_TRANSPARENT_DRIVER_ID (3)\n#define P256_TRANSPARENT_DRIVER_ID (4)\n\n/* END-driver id */\n\n/* BEGIN-Common Macro definitions */\n\n/* END-Common Macro definitions */\n\n/* Support the 'old' SE interface when asked to */\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style\n * SE driver is present, to avoid unused argument errors at compile time. */\n#ifndef PSA_CRYPTO_DRIVER_PRESENT\n#define PSA_CRYPTO_DRIVER_PRESENT\n#endif\n#include \"psa_crypto_se.h\"\n#endif\n\n/** Get the key buffer size required to store the key material of a key\n *  associated with an opaque driver.\n *\n * \\param[in] attributes  The key attributes.\n * \\param[out] key_buffer_size  Minimum buffer size to contain the key material\n *\n * \\retval #PSA_SUCCESS\n *         The minimum size for a buffer to contain the key material has been\n *         returned successfully.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         The type and/or the size in bits of the key or the combination of\n *         the two is not supported.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The key is declared with a lifetime not known to us.\n */\npsa_status_t psa_driver_wrapper_get_key_buffer_size(\n    const psa_key_attributes_t *attributes,\n    size_t *key_buffer_size )\n{\n    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n    psa_key_type_t key_type = psa_get_key_type(attributes);\n    size_t key_bits = psa_get_key_bits(attributes);\n\n    *key_buffer_size = 0;\n    switch( location )\n    {\n#if defined(PSA_CRYPTO_DRIVER_TEST)\n        case PSA_CRYPTO_TEST_DRIVER_LOCATION:\n#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)\n            /* Emulate property 'builtin_key_size' */\n            if( psa_key_id_is_builtin(\n                    MBEDTLS_SVC_KEY_ID_GET_KEY_ID(\n                        psa_get_key_id( attributes ) ) ) )\n            {\n                *key_buffer_size = sizeof( psa_drv_slot_number_t );\n                return( PSA_SUCCESS );\n            }\n#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */\n            *key_buffer_size = mbedtls_test_opaque_size_function( key_type,\n                                                                  key_bits );\n            return( ( *key_buffer_size != 0 ) ?\n                    PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED );\n#endif /* PSA_CRYPTO_DRIVER_TEST */\n\n        default:\n            (void)key_type;\n            (void)key_bits;\n            return( PSA_ERROR_INVALID_ARGUMENT );\n    }\n}\n\npsa_status_t psa_driver_wrapper_export_public_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    uint8_t *data, size_t data_size, size_t *data_length )\n\n{\n\n    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;\n    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(\n                                      psa_get_key_lifetime( attributes ) );\n\n    /* Try dynamically-registered SE interface first */\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    const psa_drv_se_t *drv;\n    psa_drv_se_context_t *drv_context;\n\n    if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )\n    {\n        if( ( drv->key_management == NULL ) ||\n            ( drv->key_management->p_export_public == NULL ) )\n        {\n            return( PSA_ERROR_NOT_SUPPORTED );\n        }\n\n        return( drv->key_management->p_export_public(\n                    drv_context,\n                    *( (psa_key_slot_number_t *)key_buffer ),\n                    data, data_size, data_length ) );\n    }\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n    switch( location )\n    {\n        case PSA_KEY_LOCATION_LOCAL_STORAGE:\n            /* Key is stored in the slot in export representation, so\n             * cycle through all known transparent accelerators */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n\n#if (defined(PSA_CRYPTO_DRIVER_TEST) )\n            status = mbedtls_test_transparent_export_public_key\n                (attributes,\n                                key_buffer,\n                                key_buffer_size,\n                                data,\n                                data_size,\n                                data_length\n            );\n\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif\n\n#if (defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) )\n            status = p256_transparent_export_public_key\n                (attributes,\n                                key_buffer,\n                                key_buffer_size,\n                                data,\n                                data_size,\n                                data_length\n            );\n\n            if( status != PSA_ERROR_NOT_SUPPORTED )\n                return( status );\n#endif\n\n\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n            /* Fell through, meaning no accelerator supports this operation */\n            return( psa_export_public_key_internal( attributes,\n                                                    key_buffer,\n                                                    key_buffer_size,\n                                                    data,\n                                                    data_size,\n                                                    data_length ) );\n\n        /* Add cases for opaque driver here */\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n\n#if (defined(PSA_CRYPTO_DRIVER_TEST) )\n        case 0x7fffff:\n            return( mbedtls_test_opaque_export_public_key\n            (attributes,\n                            key_buffer,\n                            key_buffer_size,\n                            data,\n                            data_size,\n                            data_length\n        ));\n#endif\n\n\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            /* Key is declared with a lifetime not known to us */\n            return( status );\n    }\n\n}\n\npsa_status_t psa_driver_wrapper_get_builtin_key(\n    psa_drv_slot_number_t slot_number,\n    psa_key_attributes_t *attributes,\n    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )\n{\n\n    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );\n    switch( location )\n    {\n#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)\n\n#if (defined(PSA_CRYPTO_DRIVER_TEST) )\n        case 0x7fffff:\n            return( mbedtls_test_opaque_get_builtin_key\n            (slot_number,\n                            attributes,\n                            key_buffer,\n                            key_buffer_size,\n                            key_buffer_length\n        ));\n#endif\n\n\n#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */\n        default:\n            (void) slot_number;\n            (void) key_buffer;\n            (void) key_buffer_size;\n            (void) key_buffer_length;\n            return( PSA_ERROR_DOES_NOT_EXIST );\n    }\n\n}\n\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_driver_wrappers_no_static.h",
    "content": "/*\n *  Function signatures for functionality that can be provided by\n *  cryptographic accelerators.\n */\n/*  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H\n#define PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H\n\n#include \"psa/crypto.h\"\n#include \"psa/crypto_driver_common.h\"\n\npsa_status_t psa_driver_wrapper_export_public_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    uint8_t *data, size_t data_size, size_t *data_length);\n\npsa_status_t psa_driver_wrapper_get_key_buffer_size(\n    const psa_key_attributes_t *attributes,\n    size_t *key_buffer_size);\n\npsa_status_t psa_driver_wrapper_get_builtin_key(\n    psa_drv_slot_number_t slot_number,\n    psa_key_attributes_t *attributes,\n    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);\n\n#endif /* PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H */\n\n/* End of automatically generated file. */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_ecp.c",
    "content": "/*\n *  PSA ECP layer on top of Mbed TLS crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n\n#include <psa/crypto.h>\n#include \"psa_crypto_core.h\"\n#include \"psa_crypto_ecp.h\"\n#include \"psa_crypto_random_impl.h\"\n#include \"mbedtls/psa_util.h\"\n\n#include <stdlib.h>\n#include <string.h>\n#include \"mbedtls/platform.h\"\n\n#include <mbedtls/ecdsa.h>\n#include <mbedtls/ecdh.h>\n#include <mbedtls/ecp.h>\n#include <mbedtls/error.h>\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)\n/* Helper function to verify if the provided EC's family and key bit size are valid.\n *\n * Note: \"bits\" parameter is used both as input and output and it might be updated\n *       in case provided input value is not multiple of 8 (\"sloppy\" bits).\n */\nstatic int check_ecc_parameters(psa_ecc_family_t family, size_t *bits)\n{\n    switch (family) {\n        case PSA_ECC_FAMILY_SECP_R1:\n            switch (*bits) {\n                case 192:\n                case 224:\n                case 256:\n                case 384:\n                case 521:\n                    return PSA_SUCCESS;\n                case 528:\n                    *bits = 521;\n                    return PSA_SUCCESS;\n            }\n            break;\n\n        case PSA_ECC_FAMILY_BRAINPOOL_P_R1:\n            switch (*bits) {\n                case 256:\n                case 384:\n                case 512:\n                    return PSA_SUCCESS;\n            }\n            break;\n\n        case PSA_ECC_FAMILY_MONTGOMERY:\n            switch (*bits) {\n                case 448:\n                case 255:\n                    return PSA_SUCCESS;\n                case 256:\n                    *bits = 255;\n                    return PSA_SUCCESS;\n            }\n            break;\n\n        case PSA_ECC_FAMILY_SECP_K1:\n            switch (*bits) {\n                case 192:\n                /* secp224k1 is not and will not be supported in PSA (#3541). */\n                case 256:\n                    return PSA_SUCCESS;\n            }\n            break;\n    }\n\n    return PSA_ERROR_INVALID_ARGUMENT;\n}\n\npsa_status_t mbedtls_psa_ecp_load_representation(\n    psa_key_type_t type, size_t curve_bits,\n    const uint8_t *data, size_t data_length,\n    mbedtls_ecp_keypair **p_ecp)\n{\n    mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;\n    psa_status_t status;\n    mbedtls_ecp_keypair *ecp = NULL;\n    size_t curve_bytes = data_length;\n    int explicit_bits = (curve_bits != 0);\n\n    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) &&\n        PSA_KEY_TYPE_ECC_GET_FAMILY(type) != PSA_ECC_FAMILY_MONTGOMERY) {\n        /* A Weierstrass public key is represented as:\n         * - The byte 0x04;\n         * - `x_P` as a `ceiling(m/8)`-byte string, big-endian;\n         * - `y_P` as a `ceiling(m/8)`-byte string, big-endian.\n         * So its data length is 2m+1 where m is the curve size in bits.\n         */\n        if ((data_length & 1) == 0) {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n        curve_bytes = data_length / 2;\n\n        /* Montgomery public keys are represented in compressed format, meaning\n         * their curve_bytes is equal to the amount of input. */\n\n        /* Private keys are represented in uncompressed private random integer\n         * format, meaning their curve_bytes is equal to the amount of input. */\n    }\n\n    if (explicit_bits) {\n        /* With an explicit bit-size, the data must have the matching length. */\n        if (curve_bytes != PSA_BITS_TO_BYTES(curve_bits)) {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n    } else {\n        /* We need to infer the bit-size from the data. Since the only\n         * information we have is the length in bytes, the value of curve_bits\n         * at this stage is rounded up to the nearest multiple of 8. */\n        curve_bits = PSA_BYTES_TO_BITS(curve_bytes);\n    }\n\n    /* Allocate and initialize a key representation. */\n    ecp = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair));\n    if (ecp == NULL) {\n        return PSA_ERROR_INSUFFICIENT_MEMORY;\n    }\n    mbedtls_ecp_keypair_init(ecp);\n\n    status = check_ecc_parameters(PSA_KEY_TYPE_ECC_GET_FAMILY(type), &curve_bits);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    /* Load the group. */\n    grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type),\n                                        curve_bits);\n    if (grp_id == MBEDTLS_ECP_DP_NONE) {\n        status = PSA_ERROR_NOT_SUPPORTED;\n        goto exit;\n    }\n\n    status = mbedtls_to_psa_error(\n        mbedtls_ecp_group_load(&ecp->grp, grp_id));\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    /* Load the key material. */\n    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {\n        /* Load the public value. */\n        status = mbedtls_to_psa_error(\n            mbedtls_ecp_point_read_binary(&ecp->grp, &ecp->Q,\n                                          data,\n                                          data_length));\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n\n        /* Check that the point is on the curve. */\n        status = mbedtls_to_psa_error(\n            mbedtls_ecp_check_pubkey(&ecp->grp, &ecp->Q));\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n    } else {\n        /* Load and validate the secret value. */\n        status = mbedtls_to_psa_error(\n            mbedtls_ecp_read_key(ecp->grp.id,\n                                 ecp,\n                                 data,\n                                 data_length));\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n    }\n\n    *p_ecp = ecp;\nexit:\n    if (status != PSA_SUCCESS) {\n        mbedtls_ecp_keypair_free(ecp);\n        mbedtls_free(ecp);\n    }\n\n    return status;\n}\n#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)\n\npsa_status_t mbedtls_psa_ecp_import_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *data, size_t data_length,\n    uint8_t *key_buffer, size_t key_buffer_size,\n    size_t *key_buffer_length, size_t *bits)\n{\n    psa_status_t status;\n    mbedtls_ecp_keypair *ecp = NULL;\n\n    /* Parse input */\n    status = mbedtls_psa_ecp_load_representation(attributes->type,\n                                                 attributes->bits,\n                                                 data,\n                                                 data_length,\n                                                 &ecp);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type) ==\n        PSA_ECC_FAMILY_MONTGOMERY) {\n        *bits = ecp->grp.nbits + 1;\n    } else {\n        *bits = ecp->grp.nbits;\n    }\n\n    /* Re-export the data to PSA export format. There is currently no support\n     * for other input formats then the export format, so this is a 1-1\n     * copy operation. */\n    status = mbedtls_psa_ecp_export_key(attributes->type,\n                                        ecp,\n                                        key_buffer,\n                                        key_buffer_size,\n                                        key_buffer_length);\nexit:\n    /* Always free the PK object (will also free contained ECP context) */\n    mbedtls_ecp_keypair_free(ecp);\n    mbedtls_free(ecp);\n\n    return status;\n}\n\npsa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type,\n                                        mbedtls_ecp_keypair *ecp,\n                                        uint8_t *data,\n                                        size_t data_size,\n                                        size_t *data_length)\n{\n    psa_status_t status;\n\n    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {\n        /* Check whether the public part is loaded */\n        if (mbedtls_ecp_is_zero(&ecp->Q)) {\n            /* Calculate the public key */\n            status = mbedtls_to_psa_error(\n                mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,\n                                mbedtls_psa_get_random,\n                                MBEDTLS_PSA_RANDOM_STATE));\n            if (status != PSA_SUCCESS) {\n                return status;\n            }\n        }\n\n        status = mbedtls_to_psa_error(\n            mbedtls_ecp_point_write_binary(&ecp->grp, &ecp->Q,\n                                           MBEDTLS_ECP_PF_UNCOMPRESSED,\n                                           data_length,\n                                           data,\n                                           data_size));\n        if (status != PSA_SUCCESS) {\n            memset(data, 0, data_size);\n        }\n\n        return status;\n    } else {\n        status = mbedtls_to_psa_error(\n            mbedtls_ecp_write_key_ext(ecp, data_length, data, data_size));\n        return status;\n    }\n}\n\npsa_status_t mbedtls_psa_ecp_export_public_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    uint8_t *data, size_t data_size, size_t *data_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_keypair *ecp = NULL;\n\n    status = mbedtls_psa_ecp_load_representation(\n        attributes->type, attributes->bits,\n        key_buffer, key_buffer_size, &ecp);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    status = mbedtls_psa_ecp_export_key(\n        PSA_KEY_TYPE_ECC_PUBLIC_KEY(\n            PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type)),\n        ecp, data, data_size, data_length);\n\n    mbedtls_ecp_keypair_free(ecp);\n    mbedtls_free(ecp);\n\n    return status;\n}\n#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE)\npsa_status_t mbedtls_psa_ecp_generate_key(\n    const psa_key_attributes_t *attributes,\n    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)\n{\n    psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(\n        attributes->type);\n    mbedtls_ecp_group_id grp_id =\n        mbedtls_ecc_group_from_psa(curve, attributes->bits);\n    if (grp_id == MBEDTLS_ECP_DP_NONE) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    mbedtls_ecp_keypair ecp;\n    mbedtls_ecp_keypair_init(&ecp);\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    ret = mbedtls_ecp_group_load(&ecp.grp, grp_id);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    ret = mbedtls_ecp_gen_privkey(&ecp.grp, &ecp.d,\n                                  mbedtls_psa_get_random,\n                                  MBEDTLS_PSA_RANDOM_STATE);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    ret = mbedtls_ecp_write_key_ext(&ecp, key_buffer_length,\n                                    key_buffer, key_buffer_size);\n\nexit:\n    mbedtls_ecp_keypair_free(&ecp);\n    return mbedtls_to_psa_error(ret);\n}\n#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */\n\n/****************************************************************/\n/* ECDSA sign/verify */\n/****************************************************************/\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)\npsa_status_t mbedtls_psa_ecdsa_sign_hash(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,\n    uint8_t *signature, size_t signature_size, size_t *signature_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_keypair *ecp = NULL;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t curve_bytes;\n    mbedtls_mpi r, s;\n\n    status = mbedtls_psa_ecp_load_representation(attributes->type,\n                                                 attributes->bits,\n                                                 key_buffer,\n                                                 key_buffer_size,\n                                                 &ecp);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);\n    mbedtls_mpi_init(&r);\n    mbedtls_mpi_init(&s);\n\n    if (signature_size < 2 * curve_bytes) {\n        ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;\n        goto cleanup;\n    }\n\n    if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)\n        psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);\n        mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg);\n        MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_ext(\n                            &ecp->grp, &r, &s,\n                            &ecp->d, hash,\n                            hash_length, md_alg,\n                            mbedtls_psa_get_random,\n                            MBEDTLS_PSA_RANDOM_STATE));\n#else\n        ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;\n        goto cleanup;\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */\n    } else {\n        (void) alg;\n        MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ecp->grp, &r, &s, &ecp->d,\n                                           hash, hash_length,\n                                           mbedtls_psa_get_random,\n                                           MBEDTLS_PSA_RANDOM_STATE));\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&r,\n                                             signature,\n                                             curve_bytes));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&s,\n                                             signature + curve_bytes,\n                                             curve_bytes));\ncleanup:\n    mbedtls_mpi_free(&r);\n    mbedtls_mpi_free(&s);\n    if (ret == 0) {\n        *signature_length = 2 * curve_bytes;\n    }\n\n    mbedtls_ecp_keypair_free(ecp);\n    mbedtls_free(ecp);\n\n    return mbedtls_to_psa_error(ret);\n}\n\npsa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp)\n{\n    int ret = 0;\n\n    /* Check whether the public part is loaded. If not, load it. */\n    if (mbedtls_ecp_is_zero(&ecp->Q)) {\n        ret = mbedtls_ecp_mul(&ecp->grp, &ecp->Q,\n                              &ecp->d, &ecp->grp.G,\n                              mbedtls_psa_get_random,\n                              MBEDTLS_PSA_RANDOM_STATE);\n    }\n\n    return mbedtls_to_psa_error(ret);\n}\n\npsa_status_t mbedtls_psa_ecdsa_verify_hash(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,\n    const uint8_t *signature, size_t signature_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ecp_keypair *ecp = NULL;\n    size_t curve_bytes;\n    mbedtls_mpi r, s;\n\n    (void) alg;\n\n    status = mbedtls_psa_ecp_load_representation(attributes->type,\n                                                 attributes->bits,\n                                                 key_buffer,\n                                                 key_buffer_size,\n                                                 &ecp);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);\n    mbedtls_mpi_init(&r);\n    mbedtls_mpi_init(&s);\n\n    if (signature_length != 2 * curve_bytes) {\n        status = PSA_ERROR_INVALID_SIGNATURE;\n        goto cleanup;\n    }\n\n    status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&r,\n                                                          signature,\n                                                          curve_bytes));\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&s,\n                                                          signature + curve_bytes,\n                                                          curve_bytes));\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    status = mbedtls_psa_ecp_load_public_part(ecp);\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    status = mbedtls_to_psa_error(mbedtls_ecdsa_verify(&ecp->grp, hash,\n                                                       hash_length, &ecp->Q,\n                                                       &r, &s));\ncleanup:\n    mbedtls_mpi_free(&r);\n    mbedtls_mpi_free(&s);\n    mbedtls_ecp_keypair_free(ecp);\n    mbedtls_free(ecp);\n\n    return status;\n}\n\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \\\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */\n\n/****************************************************************/\n/* ECDH Key Agreement */\n/****************************************************************/\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)\npsa_status_t mbedtls_psa_key_agreement_ecdh(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length,\n    uint8_t *shared_secret, size_t shared_secret_size,\n    size_t *shared_secret_length)\n{\n    psa_status_t status;\n    if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->type) ||\n        !PSA_ALG_IS_ECDH(alg)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n    mbedtls_ecp_keypair *ecp = NULL;\n    status = mbedtls_psa_ecp_load_representation(\n        attributes->type,\n        attributes->bits,\n        key_buffer,\n        key_buffer_size,\n        &ecp);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n    mbedtls_ecp_keypair *their_key = NULL;\n    mbedtls_ecdh_context ecdh;\n    size_t bits = 0;\n    psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ecp->grp.id, &bits);\n    mbedtls_ecdh_init(&ecdh);\n\n    status = mbedtls_psa_ecp_load_representation(\n        PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve),\n        bits,\n        peer_key,\n        peer_key_length,\n        &their_key);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = mbedtls_to_psa_error(\n        mbedtls_ecdh_get_params(&ecdh, their_key, MBEDTLS_ECDH_THEIRS));\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n    status = mbedtls_to_psa_error(\n        mbedtls_ecdh_get_params(&ecdh, ecp, MBEDTLS_ECDH_OURS));\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = mbedtls_to_psa_error(\n        mbedtls_ecdh_calc_secret(&ecdh,\n                                 shared_secret_length,\n                                 shared_secret, shared_secret_size,\n                                 mbedtls_psa_get_random,\n                                 MBEDTLS_PSA_RANDOM_STATE));\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n    if (PSA_BITS_TO_BYTES(bits) != *shared_secret_length) {\n        status = PSA_ERROR_CORRUPTION_DETECTED;\n    }\nexit:\n    if (status != PSA_SUCCESS) {\n        mbedtls_platform_zeroize(shared_secret, shared_secret_size);\n    }\n    mbedtls_ecdh_free(&ecdh);\n    mbedtls_ecp_keypair_free(their_key);\n    mbedtls_free(their_key);\n    mbedtls_ecp_keypair_free(ecp);\n    mbedtls_free(ecp);\n    return status;\n}\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */\n\n\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_ecp.h",
    "content": "/*\n *  PSA ECP layer on top of Mbed TLS crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_ECP_H\n#define PSA_CRYPTO_ECP_H\n\n#include <psa/crypto.h>\n#include <mbedtls/ecp.h>\n\n/** Load the contents of a key buffer into an internal ECP representation\n *\n * \\param[in] type          The type of key contained in \\p data.\n * \\param[in] curve_bits    The nominal bit-size of the curve.\n *                          It must be consistent with the representation\n *                          passed in \\p data.\n *                          This can be 0, in which case the bit-size\n *                          is inferred from \\p data_length (which is possible\n *                          for all key types and representation formats\n *                          formats that are currently supported or will\n *                          be in the foreseeable future).\n * \\param[in] data          The buffer from which to load the representation.\n * \\param[in] data_length   The size in bytes of \\p data.\n * \\param[out] p_ecp        Returns a pointer to an ECP context on success.\n *                          The caller is responsible for freeing both the\n *                          contents of the context and the context itself\n *                          when done.\n */\npsa_status_t mbedtls_psa_ecp_load_representation(psa_key_type_t type,\n                                                 size_t curve_bits,\n                                                 const uint8_t *data,\n                                                 size_t data_length,\n                                                 mbedtls_ecp_keypair **p_ecp);\n\n/** Load the public part of an internal ECP, if required.\n *\n * \\param ecp               The ECP context to load the public part for.\n *\n * \\return PSA_SUCCESS on success, otherwise an MPI error.\n */\n\npsa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp);\n\n/** Import an ECP key in binary format.\n *\n * \\note The signature of this function is that of a PSA driver\n *       import_key entry point. This function behaves as an import_key\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in]  attributes       The attributes for the key to import.\n * \\param[in]  data             The buffer containing the key data in import\n *                              format.\n * \\param[in]  data_length      Size of the \\p data buffer in bytes.\n * \\param[out] key_buffer       The buffer containing the key data in output\n *                              format.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes. This\n *                              size is greater or equal to \\p data_length.\n * \\param[out] key_buffer_length  The length of the data written in \\p\n *                                key_buffer in bytes.\n * \\param[out] bits             The key size in number of bits.\n *\n * \\retval #PSA_SUCCESS  The ECP key was imported successfully.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The key data is not correctly formatted.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_ecp_import_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *data, size_t data_length,\n    uint8_t *key_buffer, size_t key_buffer_size,\n    size_t *key_buffer_length, size_t *bits);\n\n/** Export an ECP key to export representation\n *\n * \\param[in] type          The type of key (public/private) to export\n * \\param[in] ecp           The internal ECP representation from which to export\n * \\param[out] data         The buffer to export to\n * \\param[in] data_size     The length of the buffer to export to\n * \\param[out] data_length  The amount of bytes written to \\p data\n */\npsa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type,\n                                        mbedtls_ecp_keypair *ecp,\n                                        uint8_t *data,\n                                        size_t data_size,\n                                        size_t *data_length);\n\n/** Export an ECP public key or the public part of an ECP key pair in binary\n *  format.\n *\n * \\note The signature of this function is that of a PSA driver\n *       export_public_key entry point. This function behaves as an\n *       export_public_key entry point as defined in the PSA driver interface\n *       specification.\n *\n * \\param[in]  attributes       The attributes for the key to export.\n * \\param[in]  key_buffer       Material or context of the key to export.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[out] data             Buffer where the key data is to be written.\n * \\param[in]  data_size        Size of the \\p data buffer in bytes.\n * \\param[out] data_length      On success, the number of bytes written in\n *                              \\p data\n *\n * \\retval #PSA_SUCCESS  The ECP public key was exported successfully.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n */\npsa_status_t mbedtls_psa_ecp_export_public_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    uint8_t *data, size_t data_size, size_t *data_length);\n\n/**\n * \\brief Generate an ECP key.\n *\n * \\note The signature of the function is that of a PSA driver generate_key\n *       entry point.\n *\n * \\param[in]  attributes         The attributes for the ECP key to generate.\n * \\param[out] key_buffer         Buffer where the key data is to be written.\n * \\param[in]  key_buffer_size    Size of \\p key_buffer in bytes.\n * \\param[out] key_buffer_length  On success, the number of bytes written in\n *                                \\p key_buffer.\n *\n * \\retval #PSA_SUCCESS\n *         The key was successfully generated.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         Key length or type not supported.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of \\p key_buffer is too small.\n */\npsa_status_t mbedtls_psa_ecp_generate_key(\n    const psa_key_attributes_t *attributes,\n    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);\n\n/** Sign an already-calculated hash with ECDSA.\n *\n * \\note The signature of this function is that of a PSA driver\n *       sign_hash entry point. This function behaves as a sign_hash\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in]  attributes       The attributes of the ECC key to use for the\n *                              operation.\n * \\param[in]  key_buffer       The buffer containing the ECC key context.\n *                              format.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[in]  alg              Randomized or deterministic ECDSA algorithm.\n * \\param[in]  hash             The hash or message to sign.\n * \\param[in]  hash_length      Size of the \\p hash buffer in bytes.\n * \\param[out] signature        Buffer where the signature is to be written.\n * \\param[in]  signature_size   Size of the \\p signature buffer in bytes.\n * \\param[out] signature_length On success, the number of bytes\n *                              that make up the returned signature value.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p signature buffer is too small. You can\n *         determine a sufficient buffer size by calling\n *         #PSA_SIGN_OUTPUT_SIZE(\\c PSA_KEY_TYPE_ECC_KEY_PAIR, \\c key_bits,\n *         \\p alg) where \\c key_bits is the bit-size of the ECC key.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n */\npsa_status_t mbedtls_psa_ecdsa_sign_hash(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,\n    uint8_t *signature, size_t signature_size, size_t *signature_length);\n\n/**\n * \\brief Verify an ECDSA hash or short message signature.\n *\n * \\note The signature of this function is that of a PSA driver\n *       verify_hash entry point. This function behaves as a verify_hash\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in]  attributes       The attributes of the ECC key to use for the\n *                              operation.\n * \\param[in]  key_buffer       The buffer containing the ECC key context.\n *                              format.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[in]  alg              Randomized or deterministic ECDSA algorithm.\n * \\param[in]  hash             The hash or message whose signature is to be\n *                              verified.\n * \\param[in]  hash_length      Size of the \\p hash buffer in bytes.\n * \\param[in]  signature        Buffer containing the signature to verify.\n * \\param[in]  signature_length Size of the \\p signature buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         The signature is valid.\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The calculation was performed successfully, but the passed\n *         signature is not a valid signature.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n */\npsa_status_t mbedtls_psa_ecdsa_verify_hash(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,\n    const uint8_t *signature, size_t signature_length);\n\n\n/** Perform a key agreement and return the raw ECDH shared secret.\n *\n * \\note The signature of this function is that of a PSA driver\n *       key_agreement entry point. This function behaves as a key_agreement\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in]  attributes           The attributes of the key to use for the\n *                                  operation.\n * \\param[in]  key_buffer           The buffer containing the private key\n *                                  context.\n * \\param[in]  key_buffer_size      Size of the \\p key_buffer buffer in\n *                                  bytes.\n * \\param[in]  alg                  A key agreement algorithm that is\n *                                  compatible with the type of the key.\n * \\param[in]  peer_key             The buffer containing the key context\n *                                  of the peer's public key.\n * \\param[in]  peer_key_length      Size of the \\p peer_key buffer in\n *                                  bytes.\n * \\param[out] shared_secret        The buffer to which the shared secret\n *                                  is to be written.\n * \\param[in]  shared_secret_size   Size of the \\p shared_secret buffer in\n *                                  bytes.\n * \\param[out] shared_secret_length On success, the number of bytes that make\n *                                  up the returned shared secret.\n * \\retval #PSA_SUCCESS\n *         Success. Shared secret successfully calculated.\n * \\retval #PSA_ERROR_INVALID_HANDLE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p alg is not a key agreement algorithm, or\n *         \\p private_key is not compatible with \\p alg,\n *         or \\p peer_key is not valid for \\p alg or not compatible with\n *         \\p private_key.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         \\p shared_secret_size is too small\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not a supported key agreement algorithm.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_key_agreement_ecdh(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length,\n    uint8_t *shared_secret, size_t shared_secret_size,\n    size_t *shared_secret_length);\n#endif /* PSA_CRYPTO_ECP_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_ffdh.c",
    "content": "/*\n *  PSA FFDH layer on top of Mbed TLS crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n\n/* This header is only needed because it defines\n * MBEDTLS_DHM_RFC7919_FFDHEXXXX_[P|G]_BIN symbols that are used in\n * mbedtls_psa_ffdh_set_prime_generator(). Apart from that, this module\n * only uses bignum functions for arithmetic. */\n#include <mbedtls/dhm.h>\n\n#include <psa/crypto.h>\n#include \"psa_crypto_core.h\"\n#include \"psa_crypto_ffdh.h\"\n#include \"psa_crypto_random_impl.h\"\n#include \"mbedtls/platform.h\"\n#include \"mbedtls/error.h\"\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) ||   \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) ||   \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH)\nstatic psa_status_t mbedtls_psa_ffdh_set_prime_generator(size_t key_size,\n                                                         mbedtls_mpi *P,\n                                                         mbedtls_mpi *G)\n{\n    const unsigned char *dhm_P = NULL;\n    const unsigned char *dhm_G = NULL;\n    size_t dhm_size_P = 0;\n    size_t dhm_size_G = 0;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (P == NULL && G == NULL) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048)\n    static const unsigned char dhm_P_2048[] =\n        MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN;\n    static const unsigned char dhm_G_2048[] =\n        MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN;\n#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */\n#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072)\n    static const unsigned char dhm_P_3072[] =\n        MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN;\n    static const unsigned char dhm_G_3072[] =\n        MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN;\n#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */\n#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096)\n    static const unsigned char dhm_P_4096[] =\n        MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN;\n    static const unsigned char dhm_G_4096[] =\n        MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN;\n#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */\n#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144)\n    static const unsigned char dhm_P_6144[] =\n        MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN;\n    static const unsigned char dhm_G_6144[] =\n        MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN;\n#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */\n#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192)\n    static const unsigned char dhm_P_8192[] =\n        MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN;\n    static const unsigned char dhm_G_8192[] =\n        MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN;\n#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */\n\n    switch (key_size) {\n#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048)\n        case sizeof(dhm_P_2048):\n            dhm_P = dhm_P_2048;\n            dhm_G = dhm_G_2048;\n            dhm_size_P = sizeof(dhm_P_2048);\n            dhm_size_G = sizeof(dhm_G_2048);\n            break;\n#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */\n#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072)\n        case sizeof(dhm_P_3072):\n            dhm_P = dhm_P_3072;\n            dhm_G = dhm_G_3072;\n            dhm_size_P = sizeof(dhm_P_3072);\n            dhm_size_G = sizeof(dhm_G_3072);\n            break;\n#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */\n#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096)\n        case sizeof(dhm_P_4096):\n            dhm_P = dhm_P_4096;\n            dhm_G = dhm_G_4096;\n            dhm_size_P = sizeof(dhm_P_4096);\n            dhm_size_G = sizeof(dhm_G_4096);\n            break;\n#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */\n#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144)\n        case sizeof(dhm_P_6144):\n            dhm_P = dhm_P_6144;\n            dhm_G = dhm_G_6144;\n            dhm_size_P = sizeof(dhm_P_6144);\n            dhm_size_G = sizeof(dhm_G_6144);\n            break;\n#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */\n#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192)\n        case sizeof(dhm_P_8192):\n            dhm_P = dhm_P_8192;\n            dhm_G = dhm_G_8192;\n            dhm_size_P = sizeof(dhm_P_8192);\n            dhm_size_G = sizeof(dhm_G_8192);\n            break;\n#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */\n        default:\n            return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    if (P != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(P, dhm_P,\n                                                dhm_size_P));\n    }\n    if (G != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(G, dhm_G,\n                                                dhm_size_G));\n    }\n\ncleanup:\n    if (ret != 0) {\n        return mbedtls_to_psa_error(ret);\n    }\n\n    return PSA_SUCCESS;\n}\n#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT ||\n          MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE ||\n          MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY ||\n          MBEDTLS_PSA_BUILTIN_ALG_FFDH */\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY)\npsa_status_t mbedtls_psa_ffdh_export_public_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    uint8_t *data,\n    size_t data_size,\n    size_t *data_length)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi GX, G, X, P;\n    psa_key_type_t type = attributes->type;\n\n    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {\n        if (key_buffer_size > data_size) {\n            return PSA_ERROR_BUFFER_TOO_SMALL;\n        }\n        memcpy(data, key_buffer, key_buffer_size);\n        memset(data + key_buffer_size, 0,\n               data_size - key_buffer_size);\n        *data_length = key_buffer_size;\n        return PSA_SUCCESS;\n    }\n\n    mbedtls_mpi_init(&GX); mbedtls_mpi_init(&G);\n    mbedtls_mpi_init(&X); mbedtls_mpi_init(&P);\n\n    size_t key_len = PSA_BITS_TO_BYTES(attributes->bits);\n\n    status = mbedtls_psa_ffdh_set_prime_generator(key_len, &P, &G);\n\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer,\n                                            key_buffer_size));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&GX, &G, &X, &P, NULL));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&GX, data, key_len));\n\n    *data_length = key_len;\n\n    ret = 0;\ncleanup:\n    mbedtls_mpi_free(&P); mbedtls_mpi_free(&G);\n    mbedtls_mpi_free(&X); mbedtls_mpi_free(&GX);\n\n    if (status == PSA_SUCCESS && ret != 0) {\n        status = mbedtls_to_psa_error(ret);\n    }\n\n    return status;\n}\n#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT ||\n          MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY */\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE)\npsa_status_t mbedtls_psa_ffdh_generate_key(\n    const psa_key_attributes_t *attributes,\n    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)\n{\n    mbedtls_mpi X, P;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi_init(&P); mbedtls_mpi_init(&X);\n    (void) attributes;\n\n    status = mbedtls_psa_ffdh_set_prime_generator(key_buffer_size, &P, NULL);\n\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    /* RFC7919: Traditional finite field Diffie-Hellman has each peer choose their\n        secret exponent from the range [2, P-2].\n        Select random value in range [3, P-1] and decrease it by 1. */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_random(&X, 3, &P, mbedtls_psa_get_random,\n                                       MBEDTLS_PSA_RANDOM_STATE));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&X, &X, 1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&X, key_buffer, key_buffer_size));\n    *key_buffer_length = key_buffer_size;\n\ncleanup:\n    mbedtls_mpi_free(&P); mbedtls_mpi_free(&X);\n    if (status == PSA_SUCCESS && ret != 0) {\n        return mbedtls_to_psa_error(ret);\n    }\n\n    return status;\n}\n#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE */\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT)\npsa_status_t mbedtls_psa_ffdh_import_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *data, size_t data_length,\n    uint8_t *key_buffer, size_t key_buffer_size,\n    size_t *key_buffer_length, size_t *bits)\n{\n    (void) attributes;\n\n    if (key_buffer_size < data_length) {\n        return PSA_ERROR_BUFFER_TOO_SMALL;\n    }\n    memcpy(key_buffer, data, data_length);\n    *key_buffer_length = data_length;\n    *bits = PSA_BYTES_TO_BITS(data_length);\n\n    return PSA_SUCCESS;\n}\n#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT */\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH)\npsa_status_t mbedtls_psa_ffdh_key_agreement(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *peer_key,\n    size_t peer_key_length,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    uint8_t *shared_secret,\n    size_t shared_secret_size,\n    size_t *shared_secret_length)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi P, G, X, GY, K;\n    const size_t calculated_shared_secret_size = peer_key_length;\n\n    if (peer_key_length != key_buffer_size ||\n        calculated_shared_secret_size > shared_secret_size) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    if (!PSA_KEY_TYPE_IS_DH_KEY_PAIR(psa_get_key_type(attributes))) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    mbedtls_mpi_init(&P); mbedtls_mpi_init(&G);\n    mbedtls_mpi_init(&X); mbedtls_mpi_init(&GY);\n    mbedtls_mpi_init(&K);\n\n    status = mbedtls_psa_ffdh_set_prime_generator(\n        PSA_BITS_TO_BYTES(attributes->bits), &P, &G);\n\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer,\n                                            key_buffer_size));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&GY, peer_key,\n                                            peer_key_length));\n\n    /* Calculate shared secret public key: K = G^(XY) mod P = GY^X mod P */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &GY, &X, &P, NULL));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K, shared_secret,\n                                             calculated_shared_secret_size));\n\n    *shared_secret_length = calculated_shared_secret_size;\n\n    ret = 0;\n\ncleanup:\n    mbedtls_mpi_free(&P); mbedtls_mpi_free(&G);\n    mbedtls_mpi_free(&X); mbedtls_mpi_free(&GY);\n    mbedtls_mpi_free(&K);\n\n    if (status == PSA_SUCCESS && ret != 0) {\n        status = mbedtls_to_psa_error(ret);\n    }\n\n    return status;\n}\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */\n\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_ffdh.h",
    "content": "/*\n *  PSA FFDH layer on top of Mbed TLS crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_FFDH_H\n#define PSA_CRYPTO_FFDH_H\n\n#include <psa/crypto.h>\n\n/** Perform a key agreement and return the FFDH shared secret.\n *\n * \\param[in]  attributes           The attributes of the key to use for the\n *                                  operation.\n * \\param[in]  peer_key             The buffer containing the key context\n *                                  of the peer's public key.\n * \\param[in]  peer_key_length      Size of the \\p peer_key buffer in\n *                                  bytes.\n * \\param[in]  key_buffer           The buffer containing the private key\n *                                  context.\n * \\param[in]  key_buffer_size      Size of the \\p key_buffer buffer in\n *                                  bytes.\n * \\param[out] shared_secret        The buffer to which the shared secret\n *                                  is to be written.\n * \\param[in]  shared_secret_size   Size of the \\p shared_secret buffer in\n *                                  bytes.\n * \\param[out] shared_secret_length On success, the number of bytes that make\n *                                  up the returned shared secret.\n * \\retval #PSA_SUCCESS\n *         Success. Shared secret successfully calculated.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         \\p key_buffer_size, \\p peer_key_length, \\p shared_secret_size\n *         do not match\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY   \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED   \\emptydescription\n */\npsa_status_t mbedtls_psa_ffdh_key_agreement(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *peer_key,\n    size_t peer_key_length,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    uint8_t *shared_secret,\n    size_t shared_secret_size,\n    size_t *shared_secret_length);\n\n/** Export a public key or the public part of a DH key pair in binary format.\n *\n * \\param[in]  attributes       The attributes for the key to export.\n * \\param[in]  key_buffer       Material or context of the key to export.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[out] data             Buffer where the key data is to be written.\n * \\param[in]  data_size        Size of the \\p data buffer in bytes.\n * \\param[out] data_length      On success, the number of bytes written in\n *                              \\p data\n *\n * \\retval #PSA_SUCCESS  The public key was exported successfully.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of \\p key_buffer is too small.\n * \\retval #PSA_ERROR_NOT_PERMITTED         \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY   \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED   \\emptydescription\n */\npsa_status_t mbedtls_psa_ffdh_export_public_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    uint8_t *data,\n    size_t data_size,\n    size_t *data_length);\n\n/**\n * \\brief Generate DH key.\n *\n * \\note The signature of the function is that of a PSA driver generate_key\n *       entry point.\n *\n * \\param[in]  attributes         The attributes for the key to generate.\n * \\param[out] key_buffer         Buffer where the key data is to be written.\n * \\param[in]  key_buffer_size    Size of \\p key_buffer in bytes.\n * \\param[out] key_buffer_length  On success, the number of bytes written in\n *                                \\p key_buffer.\n *\n * \\retval #PSA_SUCCESS\n *         The key was generated successfully.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         Key size in bits is invalid.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of \\p key_buffer is too small.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY   \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED   \\emptydescription\n */\npsa_status_t mbedtls_psa_ffdh_generate_key(\n    const psa_key_attributes_t *attributes,\n    uint8_t *key_buffer,\n    size_t key_buffer_size,\n    size_t *key_buffer_length);\n\n/**\n * \\brief Import DH key.\n *\n * \\note The signature of the function is that of a PSA driver import_key\n *       entry point.\n *\n * \\param[in]  attributes       The attributes for the key to import.\n * \\param[in]  data             The buffer containing the key data in import\n *                              format.\n * \\param[in]  data_length      Size of the \\p data buffer in bytes.\n * \\param[out] key_buffer       The buffer containing the key data in output\n *                              format.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes. This\n *                              size is greater or equal to \\p data_length.\n * \\param[out] key_buffer_length  The length of the data written in \\p\n *                                key_buffer in bytes.\n * \\param[out] bits             The key size in number of bits.\n *\n * \\retval #PSA_SUCCESS\n *         The key was generated successfully.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of \\p key_buffer is too small.\n */\npsa_status_t mbedtls_psa_ffdh_import_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *data, size_t data_length,\n    uint8_t *key_buffer, size_t key_buffer_size,\n    size_t *key_buffer_length, size_t *bits);\n\n#endif /* PSA_CRYPTO_FFDH_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_hash.c",
    "content": "/*\n *  PSA hashing layer on top of Mbed TLS software crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n\n#include <psa/crypto.h>\n#include \"psa_crypto_core.h\"\n#include \"psa_crypto_hash.h\"\n\n#include <mbedtls/error.h>\n#include <string.h>\n\n#if defined(MBEDTLS_PSA_BUILTIN_HASH)\npsa_status_t mbedtls_psa_hash_abort(\n    mbedtls_psa_hash_operation_t *operation)\n{\n    switch (operation->alg) {\n        case 0:\n            /* The object has (apparently) been initialized but it is not\n             * in use. It's ok to call abort on such an object, and there's\n             * nothing to do. */\n            break;\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)\n        case PSA_ALG_MD5:\n            mbedtls_md5_free(&operation->ctx.md5);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)\n        case PSA_ALG_RIPEMD160:\n            mbedtls_ripemd160_free(&operation->ctx.ripemd160);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)\n        case PSA_ALG_SHA_1:\n            mbedtls_sha1_free(&operation->ctx.sha1);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)\n        case PSA_ALG_SHA_224:\n            mbedtls_sha256_free(&operation->ctx.sha256);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)\n        case PSA_ALG_SHA_256:\n            mbedtls_sha256_free(&operation->ctx.sha256);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)\n        case PSA_ALG_SHA_384:\n            mbedtls_sha512_free(&operation->ctx.sha512);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)\n        case PSA_ALG_SHA_512:\n            mbedtls_sha512_free(&operation->ctx.sha512);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224)\n        case PSA_ALG_SHA3_224:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256)\n        case PSA_ALG_SHA3_256:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384)\n        case PSA_ALG_SHA3_384:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)\n        case PSA_ALG_SHA3_512:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \\\n            defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \\\n            defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \\\n            defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)\n            mbedtls_sha3_free(&operation->ctx.sha3);\n            break;\n#endif\n        default:\n            return PSA_ERROR_BAD_STATE;\n    }\n    operation->alg = 0;\n    return PSA_SUCCESS;\n}\n\npsa_status_t mbedtls_psa_hash_setup(\n    mbedtls_psa_hash_operation_t *operation,\n    psa_algorithm_t alg)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* A context must be freshly initialized before it can be set up. */\n    if (operation->alg != 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    switch (alg) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)\n        case PSA_ALG_MD5:\n            mbedtls_md5_init(&operation->ctx.md5);\n            ret = mbedtls_md5_starts(&operation->ctx.md5);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)\n        case PSA_ALG_RIPEMD160:\n            mbedtls_ripemd160_init(&operation->ctx.ripemd160);\n            ret = mbedtls_ripemd160_starts(&operation->ctx.ripemd160);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)\n        case PSA_ALG_SHA_1:\n            mbedtls_sha1_init(&operation->ctx.sha1);\n            ret = mbedtls_sha1_starts(&operation->ctx.sha1);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)\n        case PSA_ALG_SHA_224:\n            mbedtls_sha256_init(&operation->ctx.sha256);\n            ret = mbedtls_sha256_starts(&operation->ctx.sha256, 1);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)\n        case PSA_ALG_SHA_256:\n            mbedtls_sha256_init(&operation->ctx.sha256);\n            ret = mbedtls_sha256_starts(&operation->ctx.sha256, 0);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)\n        case PSA_ALG_SHA_384:\n            mbedtls_sha512_init(&operation->ctx.sha512);\n            ret = mbedtls_sha512_starts(&operation->ctx.sha512, 1);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)\n        case PSA_ALG_SHA_512:\n            mbedtls_sha512_init(&operation->ctx.sha512);\n            ret = mbedtls_sha512_starts(&operation->ctx.sha512, 0);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224)\n        case PSA_ALG_SHA3_224:\n            mbedtls_sha3_init(&operation->ctx.sha3);\n            ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_224);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256)\n        case PSA_ALG_SHA3_256:\n            mbedtls_sha3_init(&operation->ctx.sha3);\n            ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_256);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384)\n        case PSA_ALG_SHA3_384:\n            mbedtls_sha3_init(&operation->ctx.sha3);\n            ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_384);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)\n        case PSA_ALG_SHA3_512:\n            mbedtls_sha3_init(&operation->ctx.sha3);\n            ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_512);\n            break;\n#endif\n        default:\n            return PSA_ALG_IS_HASH(alg) ?\n                   PSA_ERROR_NOT_SUPPORTED :\n                   PSA_ERROR_INVALID_ARGUMENT;\n    }\n    if (ret == 0) {\n        operation->alg = alg;\n    } else {\n        mbedtls_psa_hash_abort(operation);\n    }\n    return mbedtls_to_psa_error(ret);\n}\n\npsa_status_t mbedtls_psa_hash_clone(\n    const mbedtls_psa_hash_operation_t *source_operation,\n    mbedtls_psa_hash_operation_t *target_operation)\n{\n    switch (source_operation->alg) {\n        case 0:\n            return PSA_ERROR_BAD_STATE;\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)\n        case PSA_ALG_MD5:\n            mbedtls_md5_clone(&target_operation->ctx.md5,\n                              &source_operation->ctx.md5);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)\n        case PSA_ALG_RIPEMD160:\n            mbedtls_ripemd160_clone(&target_operation->ctx.ripemd160,\n                                    &source_operation->ctx.ripemd160);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)\n        case PSA_ALG_SHA_1:\n            mbedtls_sha1_clone(&target_operation->ctx.sha1,\n                               &source_operation->ctx.sha1);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)\n        case PSA_ALG_SHA_224:\n            mbedtls_sha256_clone(&target_operation->ctx.sha256,\n                                 &source_operation->ctx.sha256);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)\n        case PSA_ALG_SHA_256:\n            mbedtls_sha256_clone(&target_operation->ctx.sha256,\n                                 &source_operation->ctx.sha256);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)\n        case PSA_ALG_SHA_384:\n            mbedtls_sha512_clone(&target_operation->ctx.sha512,\n                                 &source_operation->ctx.sha512);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)\n        case PSA_ALG_SHA_512:\n            mbedtls_sha512_clone(&target_operation->ctx.sha512,\n                                 &source_operation->ctx.sha512);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224)\n        case PSA_ALG_SHA3_224:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256)\n        case PSA_ALG_SHA3_256:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384)\n        case PSA_ALG_SHA3_384:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)\n        case PSA_ALG_SHA3_512:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \\\n            defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \\\n            defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \\\n            defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)\n            mbedtls_sha3_clone(&target_operation->ctx.sha3,\n                               &source_operation->ctx.sha3);\n            break;\n#endif\n        default:\n            (void) source_operation;\n            (void) target_operation;\n            return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    target_operation->alg = source_operation->alg;\n    return PSA_SUCCESS;\n}\n\npsa_status_t mbedtls_psa_hash_update(\n    mbedtls_psa_hash_operation_t *operation,\n    const uint8_t *input,\n    size_t input_length)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    switch (operation->alg) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)\n        case PSA_ALG_MD5:\n            ret = mbedtls_md5_update(&operation->ctx.md5,\n                                     input, input_length);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)\n        case PSA_ALG_RIPEMD160:\n            ret = mbedtls_ripemd160_update(&operation->ctx.ripemd160,\n                                           input, input_length);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)\n        case PSA_ALG_SHA_1:\n            ret = mbedtls_sha1_update(&operation->ctx.sha1,\n                                      input, input_length);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)\n        case PSA_ALG_SHA_224:\n            ret = mbedtls_sha256_update(&operation->ctx.sha256,\n                                        input, input_length);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)\n        case PSA_ALG_SHA_256:\n            ret = mbedtls_sha256_update(&operation->ctx.sha256,\n                                        input, input_length);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)\n        case PSA_ALG_SHA_384:\n            ret = mbedtls_sha512_update(&operation->ctx.sha512,\n                                        input, input_length);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)\n        case PSA_ALG_SHA_512:\n            ret = mbedtls_sha512_update(&operation->ctx.sha512,\n                                        input, input_length);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224)\n        case PSA_ALG_SHA3_224:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256)\n        case PSA_ALG_SHA3_256:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384)\n        case PSA_ALG_SHA3_384:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)\n        case PSA_ALG_SHA3_512:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)\n    ret = mbedtls_sha3_update(&operation->ctx.sha3,\n                              input, input_length);\n    break;\n#endif\n        default:\n            (void) input;\n            (void) input_length;\n            return PSA_ERROR_BAD_STATE;\n    }\n\n    return mbedtls_to_psa_error(ret);\n}\n\npsa_status_t mbedtls_psa_hash_finish(\n    mbedtls_psa_hash_operation_t *operation,\n    uint8_t *hash,\n    size_t hash_size,\n    size_t *hash_length)\n{\n    psa_status_t status;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t actual_hash_length = PSA_HASH_LENGTH(operation->alg);\n\n    /* Fill the output buffer with something that isn't a valid hash\n     * (barring an attack on the hash and deliberately-crafted input),\n     * in case the caller doesn't check the return status properly. */\n    *hash_length = hash_size;\n    /* If hash_size is 0 then hash may be NULL and then the\n     * call to memset would have undefined behavior. */\n    if (hash_size != 0) {\n        memset(hash, '!', hash_size);\n    }\n\n    if (hash_size < actual_hash_length) {\n        status = PSA_ERROR_BUFFER_TOO_SMALL;\n        goto exit;\n    }\n\n    switch (operation->alg) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)\n        case PSA_ALG_MD5:\n            ret = mbedtls_md5_finish(&operation->ctx.md5, hash);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)\n        case PSA_ALG_RIPEMD160:\n            ret = mbedtls_ripemd160_finish(&operation->ctx.ripemd160, hash);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)\n        case PSA_ALG_SHA_1:\n            ret = mbedtls_sha1_finish(&operation->ctx.sha1, hash);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)\n        case PSA_ALG_SHA_224:\n            ret = mbedtls_sha256_finish(&operation->ctx.sha256, hash);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)\n        case PSA_ALG_SHA_256:\n            ret = mbedtls_sha256_finish(&operation->ctx.sha256, hash);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)\n        case PSA_ALG_SHA_384:\n            ret = mbedtls_sha512_finish(&operation->ctx.sha512, hash);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)\n        case PSA_ALG_SHA_512:\n            ret = mbedtls_sha512_finish(&operation->ctx.sha512, hash);\n            break;\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224)\n        case PSA_ALG_SHA3_224:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256)\n        case PSA_ALG_SHA3_256:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384)\n        case PSA_ALG_SHA3_384:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)\n        case PSA_ALG_SHA3_512:\n#endif\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)\n    ret = mbedtls_sha3_finish(&operation->ctx.sha3, hash, hash_size);\n    break;\n#endif\n        default:\n            (void) hash;\n            return PSA_ERROR_BAD_STATE;\n    }\n    status = mbedtls_to_psa_error(ret);\n\nexit:\n    if (status == PSA_SUCCESS) {\n        *hash_length = actual_hash_length;\n    }\n    return status;\n}\n\npsa_status_t mbedtls_psa_hash_compute(\n    psa_algorithm_t alg,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *hash,\n    size_t hash_size,\n    size_t *hash_length)\n{\n    mbedtls_psa_hash_operation_t operation = MBEDTLS_PSA_HASH_OPERATION_INIT;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    *hash_length = hash_size;\n    status = mbedtls_psa_hash_setup(&operation, alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n    status = mbedtls_psa_hash_update(&operation, input, input_length);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n    status = mbedtls_psa_hash_finish(&operation, hash, hash_size, hash_length);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\nexit:\n    abort_status = mbedtls_psa_hash_abort(&operation);\n    if (status == PSA_SUCCESS) {\n        return abort_status;\n    } else {\n        return status;\n    }\n\n}\n#endif /* MBEDTLS_PSA_BUILTIN_HASH */\n\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_hash.h",
    "content": "/*\n *  PSA hashing layer on top of Mbed TLS software crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_HASH_H\n#define PSA_CRYPTO_HASH_H\n\n#include <psa/crypto.h>\n\n/** Calculate the hash (digest) of a message using Mbed TLS routines.\n *\n * \\note The signature of this function is that of a PSA driver hash_compute\n *       entry point. This function behaves as a hash_compute entry point as\n *       defined in the PSA driver interface specification for transparent\n *       drivers.\n *\n * \\param alg               The hash algorithm to compute (\\c PSA_ALG_XXX value\n *                          such that #PSA_ALG_IS_HASH(\\p alg) is true).\n * \\param[in] input         Buffer containing the message to hash.\n * \\param input_length      Size of the \\p input buffer in bytes.\n * \\param[out] hash         Buffer where the hash is to be written.\n * \\param hash_size         Size of the \\p hash buffer in bytes.\n * \\param[out] hash_length  On success, the number of bytes\n *                          that make up the hash value. This is always\n *                          #PSA_HASH_LENGTH(\\p alg).\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         \\p hash_size is too small\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_hash_compute(\n    psa_algorithm_t alg,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *hash,\n    size_t hash_size,\n    size_t *hash_length);\n\n/** Set up a multipart hash operation using Mbed TLS routines.\n *\n * \\note The signature of this function is that of a PSA driver hash_setup\n *       entry point. This function behaves as a hash_setup entry point as\n *       defined in the PSA driver interface specification for transparent\n *       drivers.\n *\n * If an error occurs at any step after a call to mbedtls_psa_hash_setup(), the\n * operation will need to be reset by a call to mbedtls_psa_hash_abort(). The\n * core may call mbedtls_psa_hash_abort() at any time after the operation\n * has been initialized.\n *\n * After a successful call to mbedtls_psa_hash_setup(), the core must\n * eventually terminate the operation. The following events terminate an\n * operation:\n * - A successful call to mbedtls_psa_hash_finish() or mbedtls_psa_hash_verify().\n * - A call to mbedtls_psa_hash_abort().\n *\n * \\param[in,out] operation The operation object to set up. It must have\n *                          been initialized to all-zero and not yet be in use.\n * \\param alg               The hash algorithm to compute (\\c PSA_ALG_XXX value\n *                          such that #PSA_ALG_IS_HASH(\\p alg) is true).\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be inactive).\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_hash_setup(\n    mbedtls_psa_hash_operation_t *operation,\n    psa_algorithm_t alg);\n\n/** Clone an Mbed TLS hash operation.\n *\n * \\note The signature of this function is that of a PSA driver hash_clone\n *       entry point. This function behaves as a hash_clone entry point as\n *       defined in the PSA driver interface specification for transparent\n *       drivers.\n *\n * This function copies the state of an ongoing hash operation to\n * a new operation object. In other words, this function is equivalent\n * to calling mbedtls_psa_hash_setup() on \\p target_operation with the same\n * algorithm that \\p source_operation was set up for, then\n * mbedtls_psa_hash_update() on \\p target_operation with the same input that\n * that was passed to \\p source_operation. After this function returns, the\n * two objects are independent, i.e. subsequent calls involving one of\n * the objects do not affect the other object.\n *\n * \\param[in] source_operation      The active hash operation to clone.\n * \\param[in,out] target_operation  The operation object to set up.\n *                                  It must be initialized but not active.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The \\p source_operation state is not valid (it must be active).\n * \\retval #PSA_ERROR_BAD_STATE\n *         The \\p target_operation state is not valid (it must be inactive).\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n */\npsa_status_t mbedtls_psa_hash_clone(\n    const mbedtls_psa_hash_operation_t *source_operation,\n    mbedtls_psa_hash_operation_t *target_operation);\n\n/** Add a message fragment to a multipart Mbed TLS hash operation.\n *\n * \\note The signature of this function is that of a PSA driver hash_update\n *       entry point. This function behaves as a hash_update entry point as\n *       defined in the PSA driver interface specification for transparent\n *       drivers.\n *\n * The application must call mbedtls_psa_hash_setup() before calling this function.\n *\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling mbedtls_psa_hash_abort().\n *\n * \\param[in,out] operation Active hash operation.\n * \\param[in] input         Buffer containing the message fragment to hash.\n * \\param input_length      Size of the \\p input buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active).\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_hash_update(\n    mbedtls_psa_hash_operation_t *operation,\n    const uint8_t *input,\n    size_t input_length);\n\n/** Finish the calculation of the Mbed TLS-calculated hash of a message.\n *\n * \\note The signature of this function is that of a PSA driver hash_finish\n *       entry point. This function behaves as a hash_finish entry point as\n *       defined in the PSA driver interface specification for transparent\n *       drivers.\n *\n * The application must call mbedtls_psa_hash_setup() before calling this function.\n * This function calculates the hash of the message formed by concatenating\n * the inputs passed to preceding calls to mbedtls_psa_hash_update().\n *\n * When this function returns successfully, the operation becomes inactive.\n * If this function returns an error status, the operation enters an error\n * state and must be aborted by calling mbedtls_psa_hash_abort().\n *\n * \\param[in,out] operation     Active hash operation.\n * \\param[out] hash             Buffer where the hash is to be written.\n * \\param hash_size             Size of the \\p hash buffer in bytes.\n * \\param[out] hash_length      On success, the number of bytes\n *                              that make up the hash value. This is always\n *                              #PSA_HASH_LENGTH(\\c alg) where \\c alg is the\n *                              hash algorithm that is calculated.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active).\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p hash buffer is too small. You can determine a\n *         sufficient buffer size by calling #PSA_HASH_LENGTH(\\c alg)\n *         where \\c alg is the hash algorithm that is calculated.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_hash_finish(\n    mbedtls_psa_hash_operation_t *operation,\n    uint8_t *hash,\n    size_t hash_size,\n    size_t *hash_length);\n\n/** Abort an Mbed TLS hash operation.\n *\n * \\note The signature of this function is that of a PSA driver hash_abort\n *       entry point. This function behaves as a hash_abort entry point as\n *       defined in the PSA driver interface specification for transparent\n *       drivers.\n *\n * Aborting an operation frees all associated resources except for the\n * \\p operation structure itself. Once aborted, the operation object\n * can be reused for another operation by calling\n * mbedtls_psa_hash_setup() again.\n *\n * You may call this function any time after the operation object has\n * been initialized by one of the methods described in #psa_hash_operation_t.\n *\n * In particular, calling mbedtls_psa_hash_abort() after the operation has been\n * terminated by a call to mbedtls_psa_hash_abort(), mbedtls_psa_hash_finish() or\n * mbedtls_psa_hash_verify() is safe and has no effect.\n *\n * \\param[in,out] operation     Initialized hash operation.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_hash_abort(\n    mbedtls_psa_hash_operation_t *operation);\n\n#endif /* PSA_CRYPTO_HASH_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_invasive.h",
    "content": "/**\n * \\file psa_crypto_invasive.h\n *\n * \\brief PSA cryptography module: invasive interfaces for test only.\n *\n * The interfaces in this file are intended for testing purposes only.\n * They MUST NOT be made available to clients over IPC in integrations\n * with isolation, and they SHOULD NOT be made available in library\n * integrations except when building the library for testing.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_INVASIVE_H\n#define PSA_CRYPTO_INVASIVE_H\n\n/*\n * Include the build-time configuration information header. Here, we do not\n * include `\"mbedtls/build_info.h\"` directly but `\"psa/build_info.h\"`, which\n * is basically just an alias to it. This is to ease the maintenance of the\n * TF-PSA-Crypto repository which has a different build system and\n * configuration.\n */\n#include \"psa/build_info.h\"\n\n#include \"psa/crypto.h\"\n#include \"common.h\"\n\n#include \"mbedtls/entropy.h\"\n\n#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)\n/** \\brief Configure entropy sources.\n *\n * This function may only be called before a call to psa_crypto_init(),\n * or after a call to mbedtls_psa_crypto_free() and before any\n * subsequent call to psa_crypto_init().\n *\n * This function is only intended for test purposes. The functionality\n * it provides is also useful for system integrators, but\n * system integrators should configure entropy drivers instead of\n * breaking through to the Mbed TLS API.\n *\n * \\param entropy_init  Function to initialize the entropy context\n *                      and set up the desired entropy sources.\n *                      It is called by psa_crypto_init().\n *                      By default this is mbedtls_entropy_init().\n *                      This function cannot report failures directly.\n *                      To indicate a failure, set the entropy context\n *                      to a state where mbedtls_entropy_func() will\n *                      return an error.\n * \\param entropy_free  Function to free the entropy context\n *                      and associated resources.\n *                      It is called by mbedtls_psa_crypto_free().\n *                      By default this is mbedtls_entropy_free().\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The caller does not have the permission to configure\n *         entropy sources.\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has already been initialized.\n */\npsa_status_t mbedtls_psa_crypto_configure_entropy_sources(\n    void (* entropy_init)(mbedtls_entropy_context *ctx),\n    void (* entropy_free)(mbedtls_entropy_context *ctx));\n#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */\n\n#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C)\npsa_status_t psa_mac_key_can_do(\n    psa_algorithm_t algorithm,\n    psa_key_type_t key_type);\n\npsa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len,\n                                   uint8_t *input_copy, size_t input_copy_len);\n\npsa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len,\n                                    uint8_t *output, size_t output_len);\n\n/*\n * Test hooks to use for memory unpoisoning/poisoning in copy functions.\n */\nextern void (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len);\nextern void (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len);\nextern void (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len);\nextern void (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len);\n\n#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_PSA_CRYPTO_C */\n\n#endif /* PSA_CRYPTO_INVASIVE_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_its.h",
    "content": "/** \\file psa_crypto_its.h\n * \\brief Interface of trusted storage that crypto is built on.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_ITS_H\n#define PSA_CRYPTO_ITS_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include <psa/crypto_types.h>\n#include <psa/crypto_values.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** \\brief Flags used when creating a data entry\n */\ntypedef uint32_t psa_storage_create_flags_t;\n\n/** \\brief A type for UIDs used for identifying data\n */\ntypedef uint64_t psa_storage_uid_t;\n\n#define PSA_STORAGE_FLAG_NONE        0         /**< No flags to pass */\n#define PSA_STORAGE_FLAG_WRITE_ONCE (1 << 0) /**< The data associated with the uid will not be able to be modified or deleted. Intended to be used to set bits in `psa_storage_create_flags_t`*/\n\n/**\n * \\brief A container for metadata associated with a specific uid\n */\nstruct psa_storage_info_t {\n    uint32_t size;                  /**< The size of the data associated with a uid **/\n    psa_storage_create_flags_t flags;    /**< The flags set when the uid was created **/\n};\n\n/** Flag indicating that \\ref psa_storage_create and \\ref psa_storage_set_extended are supported */\n#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1 << 0)\n\n#define PSA_ITS_API_VERSION_MAJOR  1  /**< The major version number of the PSA ITS API. It will be incremented on significant updates that may include breaking changes */\n#define PSA_ITS_API_VERSION_MINOR  1  /**< The minor version number of the PSA ITS API. It will be incremented in small updates that are unlikely to include breaking changes */\n\n/**\n * \\brief create a new or modify an existing uid/value pair\n *\n * \\param[in] uid           the identifier for the data\n * \\param[in] data_length   The size in bytes of the data in `p_data`\n * \\param[in] p_data        A buffer containing the data\n * \\param[in] create_flags  The flags that the data will be stored with\n *\n * \\return      A status indicating the success/failure of the operation\n *\n * \\retval      #PSA_SUCCESS                     The operation completed successfully\n * \\retval      #PSA_ERROR_NOT_PERMITTED         The operation failed because the provided `uid` value was already created with PSA_STORAGE_FLAG_WRITE_ONCE\n * \\retval      #PSA_ERROR_NOT_SUPPORTED         The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid\n * \\retval      #PSA_ERROR_INSUFFICIENT_STORAGE  The operation failed because there was insufficient space on the storage medium\n * \\retval      #PSA_ERROR_STORAGE_FAILURE       The operation failed because the physical storage has failed (Fatal error)\n * \\retval      #PSA_ERROR_INVALID_ARGUMENT      The operation failed because one of the provided pointers(`p_data`)\n *                                               is invalid, for example is `NULL` or references memory the caller cannot access\n */\npsa_status_t psa_its_set(psa_storage_uid_t uid,\n                         uint32_t data_length,\n                         const void *p_data,\n                         psa_storage_create_flags_t create_flags);\n\n/**\n * \\brief Retrieve the value associated with a provided uid\n *\n * \\param[in] uid               The uid value\n * \\param[in] data_offset       The starting offset of the data requested\n * \\param[in] data_length       the amount of data requested (and the minimum allocated size of the `p_data` buffer)\n * \\param[out] p_data           The buffer where the data will be placed upon successful completion\n * \\param[out] p_data_length    The amount of data returned in the p_data buffer\n *\n *\n * \\return      A status indicating the success/failure of the operation\n *\n * \\retval      #PSA_SUCCESS                 The operation completed successfully\n * \\retval      #PSA_ERROR_DOES_NOT_EXIST    The operation failed because the provided `uid` value was not found in the storage\n * \\retval      #PSA_ERROR_STORAGE_FAILURE   The operation failed because the physical storage has failed (Fatal error)\n * \\retval      #PSA_ERROR_DATA_CORRUPT      The operation failed because stored data has been corrupted\n * \\retval      #PSA_ERROR_INVALID_ARGUMENT  The operation failed because one of the provided pointers(`p_data`, `p_data_length`)\n *                                           is invalid. For example is `NULL` or references memory the caller cannot access.\n *                                           In addition, this can also happen if an invalid offset was provided.\n */\npsa_status_t psa_its_get(psa_storage_uid_t uid,\n                         uint32_t data_offset,\n                         uint32_t data_length,\n                         void *p_data,\n                         size_t *p_data_length);\n\n/**\n * \\brief Retrieve the metadata about the provided uid\n *\n * \\param[in] uid           The uid value\n * \\param[out] p_info       A pointer to the `psa_storage_info_t` struct that will be populated with the metadata\n *\n * \\return      A status indicating the success/failure of the operation\n *\n * \\retval      #PSA_SUCCESS                 The operation completed successfully\n * \\retval      #PSA_ERROR_DOES_NOT_EXIST    The operation failed because the provided uid value was not found in the storage\n * \\retval      #PSA_ERROR_DATA_CORRUPT      The operation failed because stored data has been corrupted\n * \\retval      #PSA_ERROR_INVALID_ARGUMENT  The operation failed because one of the provided pointers(`p_info`)\n *                                           is invalid, for example is `NULL` or references memory the caller cannot access\n */\npsa_status_t psa_its_get_info(psa_storage_uid_t uid,\n                              struct psa_storage_info_t *p_info);\n\n/**\n * \\brief Remove the provided key and its associated data from the storage\n *\n * \\param[in] uid   The uid value\n *\n * \\return  A status indicating the success/failure of the operation\n *\n * \\retval      #PSA_SUCCESS                  The operation completed successfully\n * \\retval      #PSA_ERROR_DOES_NOT_EXIST     The operation failed because the provided key value was not found in the storage\n * \\retval      #PSA_ERROR_NOT_PERMITTED      The operation failed because the provided key value was created with PSA_STORAGE_FLAG_WRITE_ONCE\n * \\retval      #PSA_ERROR_STORAGE_FAILURE    The operation failed because the physical storage has failed (Fatal error)\n */\npsa_status_t psa_its_remove(psa_storage_uid_t uid);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* PSA_CRYPTO_ITS_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_mac.c",
    "content": "/*\n *  PSA MAC layer on top of Mbed TLS software crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n\n#include <psa/crypto.h>\n#include \"psa_crypto_core.h\"\n#include \"psa_crypto_cipher.h\"\n#include \"psa_crypto_mac.h\"\n#include <mbedtls/md.h>\n\n#include <mbedtls/error.h>\n#include \"mbedtls/constant_time.h\"\n#include <string.h>\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)\nstatic psa_status_t psa_hmac_abort_internal(\n    mbedtls_psa_hmac_operation_t *hmac)\n{\n    mbedtls_platform_zeroize(hmac->opad, sizeof(hmac->opad));\n    return psa_hash_abort(&hmac->hash_ctx);\n}\n\nstatic psa_status_t psa_hmac_setup_internal(\n    mbedtls_psa_hmac_operation_t *hmac,\n    const uint8_t *key,\n    size_t key_length,\n    psa_algorithm_t hash_alg)\n{\n    uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];\n    size_t i;\n    size_t hash_size = PSA_HASH_LENGTH(hash_alg);\n    size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);\n    psa_status_t status;\n\n    hmac->alg = hash_alg;\n\n    /* Sanity checks on block_size, to guarantee that there won't be a buffer\n     * overflow below. This should never trigger if the hash algorithm\n     * is implemented correctly. */\n    /* The size checks against the ipad and opad buffers cannot be written\n     * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )`\n     * because that triggers -Wlogical-op on GCC 7.3. */\n    if (block_size > sizeof(ipad)) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n    if (block_size > sizeof(hmac->opad)) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n    if (block_size < hash_size) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    if (key_length > block_size) {\n        status = psa_hash_compute(hash_alg, key, key_length,\n                                  ipad, sizeof(ipad), &key_length);\n        if (status != PSA_SUCCESS) {\n            goto cleanup;\n        }\n    }\n    /* A 0-length key is not commonly used in HMAC when used as a MAC,\n     * but it is permitted. It is common when HMAC is used in HKDF, for\n     * example. Don't call `memcpy` in the 0-length because `key` could be\n     * an invalid pointer which would make the behavior undefined. */\n    else if (key_length != 0) {\n        memcpy(ipad, key, key_length);\n    }\n\n    /* ipad contains the key followed by garbage. Xor and fill with 0x36\n     * to create the ipad value. */\n    for (i = 0; i < key_length; i++) {\n        ipad[i] ^= 0x36;\n    }\n    memset(ipad + key_length, 0x36, block_size - key_length);\n\n    /* Copy the key material from ipad to opad, flipping the requisite bits,\n     * and filling the rest of opad with the requisite constant. */\n    for (i = 0; i < key_length; i++) {\n        hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C;\n    }\n    memset(hmac->opad + key_length, 0x5C, block_size - key_length);\n\n    status = psa_hash_setup(&hmac->hash_ctx, hash_alg);\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    status = psa_hash_update(&hmac->hash_ctx, ipad, block_size);\n\ncleanup:\n    mbedtls_platform_zeroize(ipad, sizeof(ipad));\n\n    return status;\n}\n\nstatic psa_status_t psa_hmac_update_internal(\n    mbedtls_psa_hmac_operation_t *hmac,\n    const uint8_t *data,\n    size_t data_length)\n{\n    return psa_hash_update(&hmac->hash_ctx, data, data_length);\n}\n\nstatic psa_status_t psa_hmac_finish_internal(\n    mbedtls_psa_hmac_operation_t *hmac,\n    uint8_t *mac,\n    size_t mac_size)\n{\n    uint8_t tmp[PSA_HASH_MAX_SIZE];\n    psa_algorithm_t hash_alg = hmac->alg;\n    size_t hash_size = 0;\n    size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);\n    psa_status_t status;\n\n    status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n    /* From here on, tmp needs to be wiped. */\n\n    status = psa_hash_setup(&hmac->hash_ctx, hash_alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&hmac->hash_ctx, hmac->opad, block_size);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_update(&hmac->hash_ctx, tmp, hash_size);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    memcpy(mac, tmp, mac_size);\n\nexit:\n    mbedtls_platform_zeroize(tmp, hash_size);\n    return status;\n}\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)\nstatic psa_status_t cmac_setup(mbedtls_psa_mac_operation_t *operation,\n                               const psa_key_attributes_t *attributes,\n                               const uint8_t *key_buffer)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n#if defined(PSA_WANT_KEY_TYPE_DES)\n    /* Mbed TLS CMAC does not accept 3DES with only two keys, nor does it accept\n     * to do CMAC with pure DES, so return NOT_SUPPORTED here. */\n    if (psa_get_key_type(attributes) == PSA_KEY_TYPE_DES &&\n        (psa_get_key_bits(attributes) == 64 ||\n         psa_get_key_bits(attributes) == 128)) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n#endif\n\n    const mbedtls_cipher_info_t *cipher_info =\n        mbedtls_cipher_info_from_psa(\n            PSA_ALG_CMAC,\n            psa_get_key_type(attributes),\n            psa_get_key_bits(attributes),\n            NULL);\n\n    if (cipher_info == NULL) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    ret = mbedtls_cipher_setup(&operation->ctx.cmac, cipher_info);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    ret = mbedtls_cipher_cmac_starts(&operation->ctx.cmac,\n                                     key_buffer,\n                                     psa_get_key_bits(attributes));\nexit:\n    return mbedtls_to_psa_error(ret);\n}\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)\n\n/* Initialize this driver's MAC operation structure. Once this function has been\n * called, mbedtls_psa_mac_abort can run and will do the right thing. */\nstatic psa_status_t mac_init(\n    mbedtls_psa_mac_operation_t *operation,\n    psa_algorithm_t alg)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    operation->alg = alg;\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)\n    if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {\n        mbedtls_cipher_init(&operation->ctx.cmac);\n        status = PSA_SUCCESS;\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)\n    if (PSA_ALG_IS_HMAC(operation->alg)) {\n        /* We'll set up the hash operation later in psa_hmac_setup_internal. */\n        operation->ctx.hmac.alg = 0;\n        status = PSA_SUCCESS;\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */\n    {\n        (void) operation;\n        status = PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    if (status != PSA_SUCCESS) {\n        memset(operation, 0, sizeof(*operation));\n    }\n    return status;\n}\n\npsa_status_t mbedtls_psa_mac_abort(mbedtls_psa_mac_operation_t *operation)\n{\n    if (operation->alg == 0) {\n        /* The object has (apparently) been initialized but it is not\n         * in use. It's ok to call abort on such an object, and there's\n         * nothing to do. */\n        return PSA_SUCCESS;\n    } else\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)\n    if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {\n        mbedtls_cipher_free(&operation->ctx.cmac);\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)\n    if (PSA_ALG_IS_HMAC(operation->alg)) {\n        psa_hmac_abort_internal(&operation->ctx.hmac);\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */\n    {\n        /* Sanity check (shouldn't happen: operation->alg should\n         * always have been initialized to a valid value). */\n        goto bad_state;\n    }\n\n    operation->alg = 0;\n\n    return PSA_SUCCESS;\n\nbad_state:\n    /* If abort is called on an uninitialized object, we can't trust\n     * anything. Wipe the object in case it contains confidential data.\n     * This may result in a memory leak if a pointer gets overwritten,\n     * but it's too late to do anything about this. */\n    memset(operation, 0, sizeof(*operation));\n    return PSA_ERROR_BAD_STATE;\n}\n\nstatic psa_status_t psa_mac_setup(mbedtls_psa_mac_operation_t *operation,\n                                  const psa_key_attributes_t *attributes,\n                                  const uint8_t *key_buffer,\n                                  size_t key_buffer_size,\n                                  psa_algorithm_t alg)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    /* A context must be freshly initialized before it can be set up. */\n    if (operation->alg != 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    status = mac_init(operation, alg);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)\n    if (PSA_ALG_FULL_LENGTH_MAC(alg) == PSA_ALG_CMAC) {\n        /* Key buffer size for CMAC is dictated by the key bits set on the\n         * attributes, and previously validated by the core on key import. */\n        (void) key_buffer_size;\n        status = cmac_setup(operation, attributes, key_buffer);\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)\n    if (PSA_ALG_IS_HMAC(alg)) {\n        status = psa_hmac_setup_internal(&operation->ctx.hmac,\n                                         key_buffer,\n                                         key_buffer_size,\n                                         PSA_ALG_HMAC_GET_HASH(alg));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */\n    {\n        (void) attributes;\n        (void) key_buffer;\n        (void) key_buffer_size;\n        status = PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    if (status != PSA_SUCCESS) {\n        mbedtls_psa_mac_abort(operation);\n    }\n\n    return status;\n}\n\npsa_status_t mbedtls_psa_mac_sign_setup(\n    mbedtls_psa_mac_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg)\n{\n    return psa_mac_setup(operation, attributes,\n                         key_buffer, key_buffer_size, alg);\n}\n\npsa_status_t mbedtls_psa_mac_verify_setup(\n    mbedtls_psa_mac_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg)\n{\n    return psa_mac_setup(operation, attributes,\n                         key_buffer, key_buffer_size, alg);\n}\n\npsa_status_t mbedtls_psa_mac_update(\n    mbedtls_psa_mac_operation_t *operation,\n    const uint8_t *input,\n    size_t input_length)\n{\n    if (operation->alg == 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)\n    if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {\n        return mbedtls_to_psa_error(\n            mbedtls_cipher_cmac_update(&operation->ctx.cmac,\n                                       input, input_length));\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)\n    if (PSA_ALG_IS_HMAC(operation->alg)) {\n        return psa_hmac_update_internal(&operation->ctx.hmac,\n                                        input, input_length);\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */\n    {\n        /* This shouldn't happen if `operation` was initialized by\n         * a setup function. */\n        (void) input;\n        (void) input_length;\n        return PSA_ERROR_BAD_STATE;\n    }\n}\n\nstatic psa_status_t psa_mac_finish_internal(\n    mbedtls_psa_mac_operation_t *operation,\n    uint8_t *mac, size_t mac_size)\n{\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)\n    if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {\n        uint8_t tmp[PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE];\n        int ret = mbedtls_cipher_cmac_finish(&operation->ctx.cmac, tmp);\n        if (ret == 0) {\n            memcpy(mac, tmp, mac_size);\n        }\n        mbedtls_platform_zeroize(tmp, sizeof(tmp));\n        return mbedtls_to_psa_error(ret);\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)\n    if (PSA_ALG_IS_HMAC(operation->alg)) {\n        return psa_hmac_finish_internal(&operation->ctx.hmac,\n                                        mac, mac_size);\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */\n    {\n        /* This shouldn't happen if `operation` was initialized by\n         * a setup function. */\n        (void) operation;\n        (void) mac;\n        (void) mac_size;\n        return PSA_ERROR_BAD_STATE;\n    }\n}\n\npsa_status_t mbedtls_psa_mac_sign_finish(\n    mbedtls_psa_mac_operation_t *operation,\n    uint8_t *mac,\n    size_t mac_size,\n    size_t *mac_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    if (operation->alg == 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    status = psa_mac_finish_internal(operation, mac, mac_size);\n    if (status == PSA_SUCCESS) {\n        *mac_length = mac_size;\n    }\n\n    return status;\n}\n\npsa_status_t mbedtls_psa_mac_verify_finish(\n    mbedtls_psa_mac_operation_t *operation,\n    const uint8_t *mac,\n    size_t mac_length)\n{\n    uint8_t actual_mac[PSA_MAC_MAX_SIZE];\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    if (operation->alg == 0) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n    /* Consistency check: requested MAC length fits our local buffer */\n    if (mac_length > sizeof(actual_mac)) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    status = psa_mac_finish_internal(operation, actual_mac, mac_length);\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    if (mbedtls_ct_memcmp(mac, actual_mac, mac_length) != 0) {\n        status = PSA_ERROR_INVALID_SIGNATURE;\n    }\n\ncleanup:\n    mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac));\n\n    return status;\n}\n\npsa_status_t mbedtls_psa_mac_compute(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *mac,\n    size_t mac_size,\n    size_t *mac_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_psa_mac_operation_t operation = MBEDTLS_PSA_MAC_OPERATION_INIT;\n    /* Make sure the whole operation is zeroed.\n     * PSA_MAC_OPERATION_INIT does not necessarily do it fully,\n     * since one field is a union and initializing a union does not\n     * necessarily initialize all of its members.\n     * In multipart operations, this is done in the API functions,\n     * before driver dispatch, since it needs to be done before calling\n     * the driver entry point. Here, we bypass the multipart API,\n     * so it's our job. */\n    memset(&operation, 0, sizeof(operation));\n\n    status = psa_mac_setup(&operation,\n                           attributes, key_buffer, key_buffer_size,\n                           alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (input_length > 0) {\n        status = mbedtls_psa_mac_update(&operation, input, input_length);\n        if (status != PSA_SUCCESS) {\n            goto exit;\n        }\n    }\n\n    status = psa_mac_finish_internal(&operation, mac, mac_size);\n    if (status == PSA_SUCCESS) {\n        *mac_length = mac_size;\n    }\n\nexit:\n    mbedtls_psa_mac_abort(&operation);\n\n    return status;\n}\n\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC || MBEDTLS_PSA_BUILTIN_ALG_CMAC */\n\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_mac.h",
    "content": "/*\n *  PSA MAC layer on top of Mbed TLS software crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_MAC_H\n#define PSA_CRYPTO_MAC_H\n\n#include <psa/crypto.h>\n\n/** Calculate the MAC (message authentication code) of a message using Mbed TLS.\n *\n * \\note The signature of this function is that of a PSA driver mac_compute\n *       entry point. This function behaves as a mac_compute entry point as\n *       defined in the PSA driver interface specification for transparent\n *       drivers.\n *\n * \\param[in] attributes        The attributes of the key to use for the\n *                              operation.\n * \\param[in] key_buffer        The buffer containing the key to use for\n *                              computing the MAC. This buffer contains the key\n *                              in export representation as defined by\n *                              psa_export_key() (i.e. the raw key bytes).\n * \\param key_buffer_size       Size of the \\p key_buffer buffer in bytes.\n * \\param alg                   The MAC algorithm to use (\\c PSA_ALG_XXX value\n *                              such that #PSA_ALG_IS_MAC(\\p alg) is true).\n * \\param[in] input             Buffer containing the input message.\n * \\param input_length          Size of the \\p input buffer in bytes.\n * \\param[out] mac              Buffer where the MAC value is to be written.\n * \\param mac_size              Size of the \\p mac buffer in bytes.\n * \\param[out] mac_length       On success, the number of bytes\n *                              that make up the MAC value.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         \\p mac_size is too small\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_mac_compute(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg,\n    const uint8_t *input,\n    size_t input_length,\n    uint8_t *mac,\n    size_t mac_size,\n    size_t *mac_length);\n\n/** Set up a multipart MAC calculation operation using Mbed TLS.\n *\n * \\note The signature of this function is that of a PSA driver mac_sign_setup\n *       entry point. This function behaves as a mac_sign_setup entry point as\n *       defined in the PSA driver interface specification for transparent\n *       drivers.\n *\n * \\param[in,out] operation     The operation object to set up. It must have\n *                              been initialized and not yet in use.\n * \\param[in] attributes        The attributes of the key to use for the\n *                              operation.\n * \\param[in] key_buffer        The buffer containing the key to use for\n *                              computing the MAC. This buffer contains the key\n *                              in export representation as defined by\n *                              psa_export_key() (i.e. the raw key bytes).\n * \\param key_buffer_size       Size of the \\p key_buffer buffer in bytes.\n * \\param alg                   The MAC algorithm to use (\\c PSA_ALG_XXX value\n *                              such that #PSA_ALG_IS_MAC(\\p alg) is true).\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be inactive).\n */\npsa_status_t mbedtls_psa_mac_sign_setup(\n    mbedtls_psa_mac_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg);\n\n/** Set up a multipart MAC verification operation using Mbed TLS.\n *\n * \\note The signature of this function is that of a PSA driver mac_verify_setup\n *       entry point. This function behaves as a mac_verify_setup entry point as\n *       defined in the PSA driver interface specification for transparent\n *       drivers.\n *\n * \\param[in,out] operation     The operation object to set up. It must have\n *                              been initialized and not yet in use.\n * \\param[in] attributes        The attributes of the key to use for the\n *                              operation.\n * \\param[in] key_buffer        The buffer containing the key to use for\n *                              computing the MAC. This buffer contains the key\n *                              in export representation as defined by\n *                              psa_export_key() (i.e. the raw key bytes).\n * \\param key_buffer_size       Size of the \\p key_buffer buffer in bytes.\n * \\param alg                   The MAC algorithm to use (\\c PSA_ALG_XXX value\n *                              such that #PSA_ALG_IS_MAC(\\p alg) is true).\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         \\p alg is not supported.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be inactive).\n */\npsa_status_t mbedtls_psa_mac_verify_setup(\n    mbedtls_psa_mac_operation_t *operation,\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer,\n    size_t key_buffer_size,\n    psa_algorithm_t alg);\n\n/** Add a message fragment to a multipart MAC operation using Mbed TLS.\n *\n * \\note The signature of this function is that of a PSA driver mac_update\n *       entry point. This function behaves as a mac_update entry point as\n *       defined in the PSA driver interface specification for transparent\n *       drivers.\n *\n * The PSA core calls mbedtls_psa_mac_sign_setup() or\n * mbedtls_psa_mac_verify_setup() before calling this function.\n *\n * If this function returns an error status, the PSA core aborts the\n * operation by calling mbedtls_psa_mac_abort().\n *\n * \\param[in,out] operation Active MAC operation.\n * \\param[in] input         Buffer containing the message fragment to add to\n *                          the MAC calculation.\n * \\param input_length      Size of the \\p input buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be active).\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_mac_update(\n    mbedtls_psa_mac_operation_t *operation,\n    const uint8_t *input,\n    size_t input_length);\n\n/** Finish the calculation of the MAC of a message using Mbed TLS.\n *\n * \\note The signature of this function is that of a PSA driver mac_sign_finish\n *       entry point. This function behaves as a mac_sign_finish entry point as\n *       defined in the PSA driver interface specification for transparent\n *       drivers.\n *\n * The PSA core calls mbedtls_psa_mac_sign_setup() before calling this function.\n * This function calculates the MAC of the message formed by concatenating\n * the inputs passed to preceding calls to mbedtls_psa_mac_update().\n *\n * Whether this function returns successfully or not, the PSA core subsequently\n * aborts the operation by calling mbedtls_psa_mac_abort().\n *\n * \\param[in,out] operation Active MAC operation.\n * \\param[out] mac          Buffer where the MAC value is to be written.\n * \\param mac_size          Output size requested for the MAC algorithm. The PSA\n *                          core guarantees this is a valid MAC length for the\n *                          algorithm and key combination passed to\n *                          mbedtls_psa_mac_sign_setup(). It also guarantees the\n *                          \\p mac buffer is large enough to contain the\n *                          requested output size.\n * \\param[out] mac_length   On success, the number of bytes output to buffer\n *                          \\p mac, which will be equal to the requested length\n *                          \\p mac_size.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be an active mac sign\n *         operation).\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p mac buffer is too small. A sufficient buffer size\n *         can be determined by calling PSA_MAC_LENGTH().\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_mac_sign_finish(\n    mbedtls_psa_mac_operation_t *operation,\n    uint8_t *mac,\n    size_t mac_size,\n    size_t *mac_length);\n\n/** Finish the calculation of the MAC of a message and compare it with\n * an expected value using Mbed TLS.\n *\n * \\note The signature of this function is that of a PSA driver\n *       mac_verify_finish entry point. This function behaves as a\n *       mac_verify_finish entry point as defined in the PSA driver interface\n *       specification for transparent drivers.\n *\n * The PSA core calls mbedtls_psa_mac_verify_setup() before calling this\n * function. This function calculates the MAC of the message formed by\n * concatenating the inputs passed to preceding calls to\n * mbedtls_psa_mac_update(). It then compares the calculated MAC with the\n * expected MAC passed as a parameter to this function.\n *\n * Whether this function returns successfully or not, the PSA core subsequently\n * aborts the operation by calling mbedtls_psa_mac_abort().\n *\n * \\param[in,out] operation Active MAC operation.\n * \\param[in] mac           Buffer containing the expected MAC value.\n * \\param mac_length        Length in bytes of the expected MAC value. The PSA\n *                          core guarantees that this length is a valid MAC\n *                          length for the algorithm and key combination passed\n *                          to mbedtls_psa_mac_verify_setup().\n *\n * \\retval #PSA_SUCCESS\n *         The expected MAC is identical to the actual MAC of the message.\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The MAC of the message was calculated successfully, but it\n *         differs from the expected MAC.\n * \\retval #PSA_ERROR_BAD_STATE\n *         The operation state is not valid (it must be an active mac verify\n *         operation).\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_mac_verify_finish(\n    mbedtls_psa_mac_operation_t *operation,\n    const uint8_t *mac,\n    size_t mac_length);\n\n/** Abort a MAC operation using Mbed TLS.\n *\n * Aborting an operation frees all associated resources except for the\n * \\p operation structure itself. Once aborted, the operation object\n * can be reused for another operation by calling\n * mbedtls_psa_mac_sign_setup() or mbedtls_psa_mac_verify_setup() again.\n *\n * The PSA core may call this function any time after the operation object has\n * been initialized by one of the methods described in\n * #mbedtls_psa_mac_operation_t.\n *\n * In particular, calling mbedtls_psa_mac_abort() after the operation has been\n * terminated by a call to mbedtls_psa_mac_abort(),\n * mbedtls_psa_mac_sign_finish() or mbedtls_psa_mac_verify_finish() is safe and\n * has no effect.\n *\n * \\param[in,out] operation Initialized MAC operation.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_mac_abort(\n    mbedtls_psa_mac_operation_t *operation);\n\n#endif /* PSA_CRYPTO_MAC_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_pake.c",
    "content": "/*\n *  PSA PAKE layer on top of Mbed TLS software crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n\n#include <psa/crypto.h>\n#include \"psa_crypto_core.h\"\n#include \"psa_crypto_pake.h\"\n#include \"psa_crypto_slot_management.h\"\n\n#include <mbedtls/ecjpake.h>\n#include \"psa_util_internal.h\"\n\n#include <mbedtls/platform.h>\n#include <mbedtls/error.h>\n#include <string.h>\n\n/*\n * State sequence:\n *\n *   psa_pake_setup()\n *   |\n *   |-- In any order:\n *   |   | psa_pake_set_password_key()\n *   |   | psa_pake_set_user()\n *   |   | psa_pake_set_peer()\n *   |   | psa_pake_set_role()\n *   |\n *   |--- In any order: (First round input before or after first round output)\n *   |   |\n *   |   |------ In Order\n *   |   |       | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE)\n *   |   |       | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC)\n *   |   |       | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF)\n *   |   |       | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE)\n *   |   |       | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC)\n *   |   |       | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF)\n *   |   |\n *   |   |------ In Order:\n *   |           | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE)\n *   |           | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC)\n *   |           | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF)\n *   |           | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE)\n *   |           | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC)\n *   |           | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF)\n *   |\n *   |--- In any order: (Second round input before or after second round output)\n *   |   |\n *   |   |------ In Order\n *   |   |       | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE)\n *   |   |       | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC)\n *   |   |       | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF)\n *   |   |\n *   |   |------ In Order:\n *   |           | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE)\n *   |           | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC)\n *   |           | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF)\n *   |\n *   psa_pake_get_implicit_key()\n *   psa_pake_abort()\n */\n\n/*\n * Possible sequence of calls to implementation:\n *\n * |--- In any order:\n * |   |\n * |   |------ In Order\n * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_KEY_SHARE)\n * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PUBLIC)\n * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PROOF)\n * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_KEY_SHARE)\n * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PUBLIC)\n * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PROOF)\n * |   |\n * |   |------ In Order:\n * |           | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_KEY_SHARE)\n * |           | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PUBLIC)\n * |           | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PROOF)\n * |           | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_KEY_SHARE)\n * |           | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PUBLIC)\n * |           | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PROOF)\n * |\n * |--- In any order:\n * |   |\n * |   |------ In Order\n * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_KEY_SHARE)\n * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PUBLIC)\n * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PROOF)\n * |   |\n * |   |------ In Order:\n * |           | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_KEY_SHARE)\n * |           | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PUBLIC)\n * |           | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PROOF)\n */\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)\nstatic psa_status_t mbedtls_ecjpake_to_psa_error(int ret)\n{\n    switch (ret) {\n        case MBEDTLS_ERR_MPI_BAD_INPUT_DATA:\n        case MBEDTLS_ERR_ECP_BAD_INPUT_DATA:\n        case MBEDTLS_ERR_ECP_INVALID_KEY:\n        case MBEDTLS_ERR_ECP_VERIFY_FAILED:\n            return PSA_ERROR_DATA_INVALID;\n        case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL:\n        case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL:\n            return PSA_ERROR_BUFFER_TOO_SMALL;\n        case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE:\n            return PSA_ERROR_NOT_SUPPORTED;\n        case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED:\n            return PSA_ERROR_CORRUPTION_DETECTED;\n        default:\n            return PSA_ERROR_GENERIC_ERROR;\n    }\n}\n#endif\n\n#if defined(MBEDTLS_PSA_BUILTIN_PAKE)\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)\nstatic psa_status_t psa_pake_ecjpake_setup(mbedtls_psa_pake_operation_t *operation)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_ecjpake_init(&operation->ctx.jpake);\n\n    ret = mbedtls_ecjpake_setup(&operation->ctx.jpake,\n                                operation->role,\n                                MBEDTLS_MD_SHA256,\n                                MBEDTLS_ECP_DP_SECP256R1,\n                                operation->password,\n                                operation->password_len);\n\n    mbedtls_platform_zeroize(operation->password, operation->password_len);\n\n    if (ret != 0) {\n        return mbedtls_ecjpake_to_psa_error(ret);\n    }\n\n    return PSA_SUCCESS;\n}\n#endif\n\n/* The only two JPAKE user/peer identifiers supported in built-in implementation. */\nstatic const uint8_t jpake_server_id[] = { 's', 'e', 'r', 'v', 'e', 'r' };\nstatic const uint8_t jpake_client_id[] = { 'c', 'l', 'i', 'e', 'n', 't' };\n\npsa_status_t mbedtls_psa_pake_setup(mbedtls_psa_pake_operation_t *operation,\n                                    const psa_crypto_driver_pake_inputs_t *inputs)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t user_len = 0, peer_len = 0, password_len = 0;\n    uint8_t *peer = NULL, *user = NULL;\n    size_t actual_user_len = 0, actual_peer_len = 0, actual_password_len = 0;\n    psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();\n\n    status = psa_crypto_driver_pake_get_password_len(inputs, &password_len);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    status = psa_crypto_driver_pake_get_user_len(inputs, &user_len);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    status = psa_crypto_driver_pake_get_peer_len(inputs, &peer_len);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    status = psa_crypto_driver_pake_get_cipher_suite(inputs, &cipher_suite);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    operation->password = mbedtls_calloc(1, password_len);\n    if (operation->password == NULL) {\n        status = PSA_ERROR_INSUFFICIENT_MEMORY;\n        goto error;\n    }\n\n    user = mbedtls_calloc(1, user_len);\n    if (user == NULL) {\n        status = PSA_ERROR_INSUFFICIENT_MEMORY;\n        goto error;\n    }\n\n    peer = mbedtls_calloc(1, peer_len);\n    if (peer == NULL) {\n        status = PSA_ERROR_INSUFFICIENT_MEMORY;\n        goto error;\n    }\n\n    status = psa_crypto_driver_pake_get_password(inputs, operation->password,\n                                                 password_len, &actual_password_len);\n    if (status != PSA_SUCCESS) {\n        goto error;\n    }\n\n    status = psa_crypto_driver_pake_get_user(inputs, user,\n                                             user_len, &actual_user_len);\n    if (status != PSA_SUCCESS) {\n        goto error;\n    }\n\n    status = psa_crypto_driver_pake_get_peer(inputs, peer,\n                                             peer_len, &actual_peer_len);\n    if (status != PSA_SUCCESS) {\n        goto error;\n    }\n\n    operation->password_len = actual_password_len;\n    operation->alg = cipher_suite.algorithm;\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)\n    if (cipher_suite.algorithm == PSA_ALG_JPAKE) {\n        if (cipher_suite.type != PSA_PAKE_PRIMITIVE_TYPE_ECC ||\n            cipher_suite.family != PSA_ECC_FAMILY_SECP_R1 ||\n            cipher_suite.bits != 256 ||\n            cipher_suite.hash != PSA_ALG_SHA_256) {\n            status = PSA_ERROR_NOT_SUPPORTED;\n            goto error;\n        }\n\n        const size_t user_peer_len = sizeof(jpake_client_id); // client and server have the same length\n        if (actual_user_len != user_peer_len ||\n            actual_peer_len != user_peer_len) {\n            status = PSA_ERROR_NOT_SUPPORTED;\n            goto error;\n        }\n\n        if (memcmp(user, jpake_client_id, actual_user_len) == 0 &&\n            memcmp(peer, jpake_server_id, actual_peer_len) == 0) {\n            operation->role = MBEDTLS_ECJPAKE_CLIENT;\n        } else\n        if (memcmp(user, jpake_server_id, actual_user_len) == 0 &&\n            memcmp(peer, jpake_client_id, actual_peer_len) == 0) {\n            operation->role = MBEDTLS_ECJPAKE_SERVER;\n        } else {\n            status = PSA_ERROR_NOT_SUPPORTED;\n            goto error;\n        }\n\n        operation->buffer_length = 0;\n        operation->buffer_offset = 0;\n\n        status = psa_pake_ecjpake_setup(operation);\n        if (status != PSA_SUCCESS) {\n            goto error;\n        }\n\n        /* Role has been set, release user/peer buffers. */\n        mbedtls_free(user); mbedtls_free(peer);\n\n        return PSA_SUCCESS;\n    } else\n#else\n    (void) operation;\n    (void) inputs;\n#endif\n    { status = PSA_ERROR_NOT_SUPPORTED; }\n\nerror:\n    mbedtls_free(user); mbedtls_free(peer);\n    /* In case of failure of the setup of a multipart operation, the PSA driver interface\n     * specifies that the core does not call any other driver entry point thus does not\n     * call mbedtls_psa_pake_abort(). Therefore call it here to do the needed clean\n     * up like freeing the memory that may have been allocated to store the password.\n     */\n    mbedtls_psa_pake_abort(operation);\n    return status;\n}\n\nstatic psa_status_t mbedtls_psa_pake_output_internal(\n    mbedtls_psa_pake_operation_t *operation,\n    psa_crypto_driver_pake_step_t step,\n    uint8_t *output,\n    size_t output_size,\n    size_t *output_length)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t length;\n    (void) step; // Unused parameter\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)\n    /*\n     * The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different\n     * handling of output sequencing.\n     *\n     * The Mbed TLS JPAKE API outputs the whole X1+X2 and X2S steps data\n     * at once, on the other side the PSA CRYPTO PAKE api requires\n     * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X2S to be\n     * retrieved in sequence.\n     *\n     * In order to achieve API compatibility, the whole X1+X2 or X2S steps\n     * data is stored in an intermediate buffer at first step output call,\n     * and data is sliced down by parsing the ECPoint records in order\n     * to return the right parts on each step.\n     */\n    if (operation->alg == PSA_ALG_JPAKE) {\n        /* Initialize & write round on KEY_SHARE sequences */\n        if (step == PSA_JPAKE_X1_STEP_KEY_SHARE) {\n            ret = mbedtls_ecjpake_write_round_one(&operation->ctx.jpake,\n                                                  operation->buffer,\n                                                  sizeof(operation->buffer),\n                                                  &operation->buffer_length,\n                                                  mbedtls_psa_get_random,\n                                                  MBEDTLS_PSA_RANDOM_STATE);\n            if (ret != 0) {\n                return mbedtls_ecjpake_to_psa_error(ret);\n            }\n\n            operation->buffer_offset = 0;\n        } else if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE) {\n            ret = mbedtls_ecjpake_write_round_two(&operation->ctx.jpake,\n                                                  operation->buffer,\n                                                  sizeof(operation->buffer),\n                                                  &operation->buffer_length,\n                                                  mbedtls_psa_get_random,\n                                                  MBEDTLS_PSA_RANDOM_STATE);\n            if (ret != 0) {\n                return mbedtls_ecjpake_to_psa_error(ret);\n            }\n\n            operation->buffer_offset = 0;\n        }\n\n        /*\n         * mbedtls_ecjpake_write_round_xxx() outputs thing in the format\n         * defined by draft-cragie-tls-ecjpake-01 section 7. The summary is\n         * that the data for each step is prepended with a length byte, and\n         * then they're concatenated. Additionally, the server's second round\n         * output is prepended with a 3-bytes ECParameters structure.\n         *\n         * In PSA, we output each step separately, and don't prepend the\n         * output with a length byte, even less a curve identifier, as that\n         * information is already available.\n         */\n        if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE &&\n            operation->role == MBEDTLS_ECJPAKE_SERVER) {\n            /* Skip ECParameters, with is 3 bytes (RFC 8422) */\n            operation->buffer_offset += 3;\n        }\n\n        /* Read the length byte then move past it to the data */\n        length = operation->buffer[operation->buffer_offset];\n        operation->buffer_offset += 1;\n\n        if (operation->buffer_offset + length > operation->buffer_length) {\n            return PSA_ERROR_DATA_CORRUPT;\n        }\n\n        if (output_size < length) {\n            return PSA_ERROR_BUFFER_TOO_SMALL;\n        }\n\n        memcpy(output,\n               operation->buffer + operation->buffer_offset,\n               length);\n        *output_length = length;\n\n        operation->buffer_offset += length;\n\n        /* Reset buffer after ZK_PROOF sequence */\n        if ((step == PSA_JPAKE_X2_STEP_ZK_PROOF) ||\n            (step == PSA_JPAKE_X2S_STEP_ZK_PROOF)) {\n            mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));\n            operation->buffer_length = 0;\n            operation->buffer_offset = 0;\n        }\n\n        return PSA_SUCCESS;\n    } else\n#else\n    (void) step;\n    (void) output;\n    (void) output_size;\n    (void) output_length;\n#endif\n    { return PSA_ERROR_NOT_SUPPORTED; }\n}\n\npsa_status_t mbedtls_psa_pake_output(mbedtls_psa_pake_operation_t *operation,\n                                     psa_crypto_driver_pake_step_t step,\n                                     uint8_t *output,\n                                     size_t output_size,\n                                     size_t *output_length)\n{\n    psa_status_t status = mbedtls_psa_pake_output_internal(\n        operation, step, output, output_size, output_length);\n\n    return status;\n}\n\nstatic psa_status_t mbedtls_psa_pake_input_internal(\n    mbedtls_psa_pake_operation_t *operation,\n    psa_crypto_driver_pake_step_t step,\n    const uint8_t *input,\n    size_t input_length)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    (void) step; // Unused parameter\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)\n    /*\n     * The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different\n     * handling of input sequencing.\n     *\n     * The Mbed TLS JPAKE API takes the whole X1+X2 or X4S steps data\n     * at once as input, on the other side the PSA CRYPTO PAKE api requires\n     * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X4S to be\n     * given in sequence.\n     *\n     * In order to achieve API compatibility, each X1+X2 or X4S step data\n     * is stored sequentially in an intermediate buffer and given to the\n     * Mbed TLS JPAKE API on the last step.\n     *\n     * This causes any input error to be only detected on the last step.\n     */\n    if (operation->alg == PSA_ALG_JPAKE) {\n        /*\n         * Copy input to local buffer and format it as the Mbed TLS API\n         * expects, i.e. as defined by draft-cragie-tls-ecjpake-01 section 7.\n         * The summary is that the data for each step is prepended with a\n         * length byte, and then they're concatenated. Additionally, the\n         * server's second round output is prepended with a 3-bytes\n         * ECParameters structure - which means we have to prepend that when\n         * we're a client.\n         */\n        if (step == PSA_JPAKE_X4S_STEP_KEY_SHARE &&\n            operation->role == MBEDTLS_ECJPAKE_CLIENT) {\n            /* We only support secp256r1. */\n            /* This is the ECParameters structure defined by RFC 8422. */\n            unsigned char ecparameters[3] = {\n                3, /* named_curve */\n                0, 23 /* secp256r1 */\n            };\n\n            if (operation->buffer_length + sizeof(ecparameters) >\n                sizeof(operation->buffer)) {\n                return PSA_ERROR_BUFFER_TOO_SMALL;\n            }\n\n            memcpy(operation->buffer + operation->buffer_length,\n                   ecparameters, sizeof(ecparameters));\n            operation->buffer_length += sizeof(ecparameters);\n        }\n\n        /*\n         * The core checks that input_length is smaller than\n         * PSA_PAKE_INPUT_MAX_SIZE.\n         * Thus no risk of integer overflow here.\n         */\n        if (operation->buffer_length + input_length + 1 > sizeof(operation->buffer)) {\n            return PSA_ERROR_BUFFER_TOO_SMALL;\n        }\n\n        /* Write the length byte */\n        operation->buffer[operation->buffer_length] = (uint8_t) input_length;\n        operation->buffer_length += 1;\n\n        /* Finally copy the data */\n        memcpy(operation->buffer + operation->buffer_length,\n               input, input_length);\n        operation->buffer_length += input_length;\n\n        /* Load buffer at each last round ZK_PROOF */\n        if (step == PSA_JPAKE_X2_STEP_ZK_PROOF) {\n            ret = mbedtls_ecjpake_read_round_one(&operation->ctx.jpake,\n                                                 operation->buffer,\n                                                 operation->buffer_length);\n\n            mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));\n            operation->buffer_length = 0;\n\n            if (ret != 0) {\n                return mbedtls_ecjpake_to_psa_error(ret);\n            }\n        } else if (step == PSA_JPAKE_X4S_STEP_ZK_PROOF) {\n            ret = mbedtls_ecjpake_read_round_two(&operation->ctx.jpake,\n                                                 operation->buffer,\n                                                 operation->buffer_length);\n\n            mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));\n            operation->buffer_length = 0;\n\n            if (ret != 0) {\n                return mbedtls_ecjpake_to_psa_error(ret);\n            }\n        }\n\n        return PSA_SUCCESS;\n    } else\n#else\n    (void) step;\n    (void) input;\n    (void) input_length;\n#endif\n    { return PSA_ERROR_NOT_SUPPORTED; }\n}\n\npsa_status_t mbedtls_psa_pake_input(mbedtls_psa_pake_operation_t *operation,\n                                    psa_crypto_driver_pake_step_t step,\n                                    const uint8_t *input,\n                                    size_t input_length)\n{\n    psa_status_t status = mbedtls_psa_pake_input_internal(\n        operation, step, input, input_length);\n\n    return status;\n}\n\npsa_status_t mbedtls_psa_pake_get_implicit_key(\n    mbedtls_psa_pake_operation_t *operation,\n    uint8_t *output, size_t output_size,\n    size_t *output_length)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)\n    if (operation->alg == PSA_ALG_JPAKE) {\n        ret = mbedtls_ecjpake_write_shared_key(&operation->ctx.jpake,\n                                               output,\n                                               output_size,\n                                               output_length,\n                                               mbedtls_psa_get_random,\n                                               MBEDTLS_PSA_RANDOM_STATE);\n        if (ret != 0) {\n            return mbedtls_ecjpake_to_psa_error(ret);\n        }\n\n        return PSA_SUCCESS;\n    } else\n#else\n    (void) output;\n#endif\n    { return PSA_ERROR_NOT_SUPPORTED; }\n}\n\npsa_status_t mbedtls_psa_pake_abort(mbedtls_psa_pake_operation_t *operation)\n{\n    mbedtls_zeroize_and_free(operation->password, operation->password_len);\n    operation->password = NULL;\n    operation->password_len = 0;\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)\n    if (operation->alg == PSA_ALG_JPAKE) {\n        operation->role = MBEDTLS_ECJPAKE_NONE;\n        mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));\n        operation->buffer_length = 0;\n        operation->buffer_offset = 0;\n        mbedtls_ecjpake_free(&operation->ctx.jpake);\n    }\n#endif\n\n    operation->alg = PSA_ALG_NONE;\n\n    return PSA_SUCCESS;\n}\n\n#endif /* MBEDTLS_PSA_BUILTIN_PAKE */\n\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_pake.h",
    "content": "/*\n *  PSA PAKE layer on top of Mbed TLS software crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_PAKE_H\n#define PSA_CRYPTO_PAKE_H\n\n#include <psa/crypto.h>\n\n/** Set the session information for a password-authenticated key exchange.\n *\n * \\note The signature of this function is that of a PSA driver\n *       pake_setup entry point. This function behaves as a pake_setup\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in,out] operation     The operation object to set up. It must have\n *                              been initialized but not set up yet.\n * \\param[in] inputs            Inputs required for PAKE operation (role, password,\n *                              key lifetime, cipher suite)\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         The algorithm in \\p cipher_suite is not a supported PAKE algorithm,\n *         or the PAKE primitive in \\p cipher_suite is not supported or not\n *         compatible with the PAKE algorithm, or the hash algorithm in\n *         \\p cipher_suite is not supported or not compatible with the PAKE\n *         algorithm and primitive.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY   \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED   \\emptydescription\n */\npsa_status_t mbedtls_psa_pake_setup(mbedtls_psa_pake_operation_t *operation,\n                                    const psa_crypto_driver_pake_inputs_t *inputs);\n\n\n/** Get output for a step of a password-authenticated key exchange.\n *\n * \\note The signature of this function is that of a PSA driver\n *       pake_output entry point. This function behaves as a pake_output\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in,out] operation    Active PAKE operation.\n * \\param step                 The step of the algorithm for which the output is\n *                             requested.\n * \\param[out] output          Buffer where the output is to be written in the\n *                             format appropriate for this driver \\p step. Refer to\n *                             the documentation of psa_crypto_driver_pake_step_t for\n *                             more information.\n * \\param output_size          Size of the \\p output buffer in bytes. This must\n *                             be at least #PSA_PAKE_OUTPUT_SIZE(\\p alg, \\p\n *                             primitive, \\p step) where \\p alg and\n *                             \\p primitive are the PAKE algorithm and primitive\n *                             in the operation's cipher suite, and \\p step is\n *                             the output step.\n *\n * \\param[out] output_length   On success, the number of bytes of the returned\n *                             output.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p output buffer is too small.\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY  \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED   \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT          \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID          \\emptydescription\n */\npsa_status_t mbedtls_psa_pake_output(mbedtls_psa_pake_operation_t *operation,\n                                     psa_crypto_driver_pake_step_t step,\n                                     uint8_t *output,\n                                     size_t output_size,\n                                     size_t *output_length);\n\n/** Provide input for a step of a password-authenticated key exchange.\n *\n * \\note The signature of this function is that of a PSA driver\n *       pake_input entry point. This function behaves as a pake_input\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\note The core checks that input_length is smaller than PSA_PAKE_INPUT_MAX_SIZE.\n *\n * \\param[in,out] operation    Active PAKE operation.\n * \\param step                 The driver step for which the input is provided.\n * \\param[in] input            Buffer containing the input in the format\n *                             appropriate for this \\p step. Refer to the\n *                             documentation of psa_crypto_driver_pake_step_t\n *                             for more information.\n * \\param input_length         Size of the \\p input buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The verification fails for a zero-knowledge input step.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         the \\p input is not valid for the \\p operation's algorithm, cipher suite\n *         or \\p step.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         the \\p input is not supported for the \\p operation's algorithm, cipher\n *         suite or \\p step.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY   \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED   \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT          \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID          \\emptydescription\n */\npsa_status_t mbedtls_psa_pake_input(mbedtls_psa_pake_operation_t *operation,\n                                    psa_crypto_driver_pake_step_t step,\n                                    const uint8_t *input,\n                                    size_t input_length);\n\n/** Get implicitly confirmed shared secret from a PAKE.\n *\n * \\note The signature of this function is that of a PSA driver\n *       pake_get_implicit_key entry point. This function behaves as a\n *       pake_get_implicit_key entry point as defined in the PSA driver\n *       interface specification for transparent drivers.\n *\n * \\param[in,out] operation    Active PAKE operation.\n * \\param[out] output          Output buffer for implicit key.\n * \\param      output_size     Size of the output buffer in bytes.\n * \\param[out] output_length   On success, the number of bytes of the implicit key.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         Input from a PAKE is not supported by the algorithm in the \\p output\n *         key derivation operation.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY   \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED   \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT          \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID          \\emptydescription\n */\npsa_status_t mbedtls_psa_pake_get_implicit_key(\n    mbedtls_psa_pake_operation_t *operation,\n    uint8_t *output, size_t output_size,\n    size_t *output_length);\n\n/** Abort a PAKE operation.\n *\n * \\note The signature of this function is that of a PSA driver\n *       pake_abort entry point. This function behaves as a pake_abort\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in,out] operation    The operation to abort.\n *\n * \\retval #PSA_SUCCESS\n *         Success.\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED   \\emptydescription\n */\npsa_status_t mbedtls_psa_pake_abort(mbedtls_psa_pake_operation_t *operation);\n\n#endif /* PSA_CRYPTO_PAKE_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_random_impl.h",
    "content": "/** \\file psa_crypto_random_impl.h\n *\n * \\brief PSA crypto random generator implementation abstraction.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_RANDOM_IMPL_H\n#define PSA_CRYPTO_RANDOM_IMPL_H\n\n#include \"psa_util_internal.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)\n\ntypedef mbedtls_psa_external_random_context_t mbedtls_psa_random_context_t;\n\n#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */\n\n#include \"mbedtls/entropy.h\"\n\n/* Choose a DRBG based on configuration and availability */\n#if defined(MBEDTLS_CTR_DRBG_C)\n\n#include \"mbedtls/ctr_drbg.h\"\n#undef MBEDTLS_PSA_HMAC_DRBG_MD_TYPE\n\n#elif defined(MBEDTLS_HMAC_DRBG_C)\n\n#include \"mbedtls/hmac_drbg.h\"\n#if defined(MBEDTLS_MD_CAN_SHA512) && defined(MBEDTLS_MD_CAN_SHA256)\n#include <limits.h>\n#if SIZE_MAX > 0xffffffff\n/* Looks like a 64-bit system, so prefer SHA-512. */\n#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512\n#else\n/* Looks like a 32-bit system, so prefer SHA-256. */\n#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256\n#endif\n#elif defined(MBEDTLS_MD_CAN_SHA512)\n#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512\n#elif defined(MBEDTLS_MD_CAN_SHA256)\n#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256\n#else\n#error \"No hash algorithm available for HMAC_DBRG.\"\n#endif\n\n#else /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/\n\n#error \"No DRBG module available for the psa_crypto module.\"\n\n#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/\n\n/* The maximum number of bytes that mbedtls_psa_get_random() is expected to return. */\n#if defined(MBEDTLS_CTR_DRBG_C)\n#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST\n#elif defined(MBEDTLS_HMAC_DRBG_C)\n#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST\n#endif\n\n#if defined(MBEDTLS_CTR_DRBG_C)\ntypedef mbedtls_ctr_drbg_context            mbedtls_psa_drbg_context_t;\n#elif defined(MBEDTLS_HMAC_DRBG_C)\ntypedef mbedtls_hmac_drbg_context           mbedtls_psa_drbg_context_t;\n#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */\n\ntypedef struct {\n    void (* entropy_init)(mbedtls_entropy_context *ctx);\n    void (* entropy_free)(mbedtls_entropy_context *ctx);\n    mbedtls_entropy_context entropy;\n    mbedtls_psa_drbg_context_t drbg;\n} mbedtls_psa_random_context_t;\n\n/** Initialize the PSA DRBG.\n *\n * \\param p_rng        Pointer to the Mbed TLS DRBG state.\n */\nstatic inline void mbedtls_psa_drbg_init(mbedtls_psa_drbg_context_t *p_rng)\n{\n#if defined(MBEDTLS_CTR_DRBG_C)\n    mbedtls_ctr_drbg_init(p_rng);\n#elif defined(MBEDTLS_HMAC_DRBG_C)\n    mbedtls_hmac_drbg_init(p_rng);\n#endif\n}\n\n/** Deinitialize the PSA DRBG.\n *\n * \\param p_rng        Pointer to the Mbed TLS DRBG state.\n */\nstatic inline void mbedtls_psa_drbg_free(mbedtls_psa_drbg_context_t *p_rng)\n{\n#if defined(MBEDTLS_CTR_DRBG_C)\n    mbedtls_ctr_drbg_free(p_rng);\n#elif defined(MBEDTLS_HMAC_DRBG_C)\n    mbedtls_hmac_drbg_free(p_rng);\n#endif\n}\n\n/** Seed the PSA DRBG.\n *\n * \\param entropy       An entropy context to read the seed from.\n * \\param custom        The personalization string.\n *                      This can be \\c NULL, in which case the personalization\n *                      string is empty regardless of the value of \\p len.\n * \\param len           The length of the personalization string.\n *\n * \\return              \\c 0 on success.\n * \\return              An Mbed TLS error code (\\c MBEDTLS_ERR_xxx) on failure.\n */\nstatic inline int mbedtls_psa_drbg_seed(mbedtls_psa_drbg_context_t *drbg_ctx,\n                                        mbedtls_entropy_context *entropy,\n                                        const unsigned char *custom, size_t len)\n{\n#if defined(MBEDTLS_CTR_DRBG_C)\n    return mbedtls_ctr_drbg_seed(drbg_ctx, mbedtls_entropy_func, entropy, custom, len);\n#elif defined(MBEDTLS_HMAC_DRBG_C)\n    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE);\n    return mbedtls_hmac_drbg_seed(drbg_ctx, md_info, mbedtls_entropy_func, entropy, custom, len);\n#endif\n}\n\n#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */\n\n#endif /* PSA_CRYPTO_RANDOM_IMPL_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_rsa.c",
    "content": "/*\n *  PSA RSA layer on top of Mbed TLS crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n\n#include <psa/crypto.h>\n#include \"psa/crypto_values.h\"\n#include \"psa_crypto_core.h\"\n#include \"psa_crypto_random_impl.h\"\n#include \"psa_crypto_rsa.h\"\n#include \"psa_crypto_hash.h\"\n#include \"mbedtls/psa_util.h\"\n\n#include <stdlib.h>\n#include <string.h>\n#include \"mbedtls/platform.h\"\n\n#include <mbedtls/rsa.h>\n#include <mbedtls/error.h>\n#include \"rsa_internal.h\"\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)\n\n/* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes\n * that are not a multiple of 8) well. For example, there is only\n * mbedtls_rsa_get_len(), which returns a number of bytes, and no\n * way to return the exact bit size of a key.\n * To keep things simple, reject non-byte-aligned key sizes. */\nstatic psa_status_t psa_check_rsa_key_byte_aligned(\n    const mbedtls_rsa_context *rsa)\n{\n    mbedtls_mpi n;\n    psa_status_t status;\n    mbedtls_mpi_init(&n);\n    status = mbedtls_to_psa_error(\n        mbedtls_rsa_export(rsa, &n, NULL, NULL, NULL, NULL));\n    if (status == PSA_SUCCESS) {\n        if (mbedtls_mpi_bitlen(&n) % 8 != 0) {\n            status = PSA_ERROR_NOT_SUPPORTED;\n        }\n    }\n    mbedtls_mpi_free(&n);\n    return status;\n}\n\npsa_status_t mbedtls_psa_rsa_load_representation(\n    psa_key_type_t type, const uint8_t *data, size_t data_length,\n    mbedtls_rsa_context **p_rsa)\n{\n    psa_status_t status;\n    size_t bits;\n\n    *p_rsa = mbedtls_calloc(1, sizeof(mbedtls_rsa_context));\n    if (*p_rsa == NULL) {\n        return PSA_ERROR_INSUFFICIENT_MEMORY;\n    }\n    mbedtls_rsa_init(*p_rsa);\n\n    /* Parse the data. */\n    if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) {\n        status = mbedtls_to_psa_error(mbedtls_rsa_parse_key(*p_rsa, data, data_length));\n    } else {\n        status = mbedtls_to_psa_error(mbedtls_rsa_parse_pubkey(*p_rsa, data, data_length));\n    }\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    /* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS\n     * supports non-byte-aligned key sizes, but not well. For example,\n     * mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */\n    bits = PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(*p_rsa));\n    if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) {\n        status = PSA_ERROR_NOT_SUPPORTED;\n        goto exit;\n    }\n    status = psa_check_rsa_key_byte_aligned(*p_rsa);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\nexit:\n    return status;\n}\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */\n\n#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)\npsa_status_t mbedtls_psa_rsa_import_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *data, size_t data_length,\n    uint8_t *key_buffer, size_t key_buffer_size,\n    size_t *key_buffer_length, size_t *bits)\n{\n    psa_status_t status;\n    mbedtls_rsa_context *rsa = NULL;\n\n    /* Parse input */\n    status = mbedtls_psa_rsa_load_representation(attributes->type,\n                                                 data,\n                                                 data_length,\n                                                 &rsa);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    *bits = (psa_key_bits_t) PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(rsa));\n\n    /* Re-export the data to PSA export format, such that we can store export\n     * representation in the key slot. Export representation in case of RSA is\n     * the smallest representation that's allowed as input, so a straight-up\n     * allocation of the same size as the input buffer will be large enough. */\n    status = mbedtls_psa_rsa_export_key(attributes->type,\n                                        rsa,\n                                        key_buffer,\n                                        key_buffer_size,\n                                        key_buffer_length);\nexit:\n    /* Always free the RSA object */\n    mbedtls_rsa_free(rsa);\n    mbedtls_free(rsa);\n\n    return status;\n}\n#endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) &&\n        *  defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \\\n    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)\npsa_status_t mbedtls_psa_rsa_export_key(psa_key_type_t type,\n                                        mbedtls_rsa_context *rsa,\n                                        uint8_t *data,\n                                        size_t data_size,\n                                        size_t *data_length)\n{\n    int ret;\n    uint8_t *end = data + data_size;\n\n    /* PSA Crypto API defines the format of an RSA key as a DER-encoded\n     * representation of the non-encrypted PKCS#1 RSAPrivateKey for a\n     * private key and of the RFC3279 RSAPublicKey for a public key. */\n    if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) {\n        ret = mbedtls_rsa_write_key(rsa, data, &end);\n    } else {\n        ret = mbedtls_rsa_write_pubkey(rsa, data, &end);\n    }\n\n    if (ret < 0) {\n        /* Clean up in case pk_write failed halfway through. */\n        memset(data, 0, data_size);\n        return mbedtls_to_psa_error(ret);\n    }\n\n    /* The mbedtls_pk_xxx functions write to the end of the buffer.\n     * Move the data to the beginning and erase remaining data\n     * at the original location. */\n    if (2 * (size_t) ret <= data_size) {\n        memcpy(data, data + data_size - ret, ret);\n        memset(data + data_size - ret, 0, ret);\n    } else if ((size_t) ret < data_size) {\n        memmove(data, data + data_size - ret, ret);\n        memset(data + ret, 0, data_size - ret);\n    }\n\n    *data_length = ret;\n    return PSA_SUCCESS;\n}\n\npsa_status_t mbedtls_psa_rsa_export_public_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    uint8_t *data, size_t data_size, size_t *data_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_rsa_context *rsa = NULL;\n\n    status = mbedtls_psa_rsa_load_representation(\n        attributes->type, key_buffer, key_buffer_size, &rsa);\n    if (status == PSA_SUCCESS) {\n        status = mbedtls_psa_rsa_export_key(PSA_KEY_TYPE_RSA_PUBLIC_KEY,\n                                            rsa,\n                                            data,\n                                            data_size,\n                                            data_length);\n    }\n\n    mbedtls_rsa_free(rsa);\n    mbedtls_free(rsa);\n\n    return status;\n}\n#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */\n\n#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)\nstatic psa_status_t psa_rsa_read_exponent(const uint8_t *e_bytes,\n                                          size_t e_length,\n                                          int *exponent)\n{\n    size_t i;\n    uint32_t acc = 0;\n\n    /* Mbed TLS encodes the public exponent as an int. For simplicity, only\n     * support values that fit in a 32-bit integer, which is larger than\n     * int on just about every platform anyway. */\n    if (e_length > sizeof(acc)) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n    for (i = 0; i < e_length; i++) {\n        acc = (acc << 8) | e_bytes[i];\n    }\n    if (acc > INT_MAX) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n    *exponent = acc;\n    return PSA_SUCCESS;\n}\n\npsa_status_t mbedtls_psa_rsa_generate_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *custom_data, size_t custom_data_length,\n    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)\n{\n    psa_status_t status;\n    mbedtls_rsa_context rsa;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    int exponent = 65537;\n\n    if (custom_data_length != 0) {\n        status = psa_rsa_read_exponent(custom_data, custom_data_length,\n                                       &exponent);\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n    }\n\n    mbedtls_rsa_init(&rsa);\n    ret = mbedtls_rsa_gen_key(&rsa,\n                              mbedtls_psa_get_random,\n                              MBEDTLS_PSA_RANDOM_STATE,\n                              (unsigned int) attributes->bits,\n                              exponent);\n    if (ret != 0) {\n        mbedtls_rsa_free(&rsa);\n        return mbedtls_to_psa_error(ret);\n    }\n\n    status = mbedtls_psa_rsa_export_key(attributes->type,\n                                        &rsa, key_buffer, key_buffer_size,\n                                        key_buffer_length);\n    mbedtls_rsa_free(&rsa);\n\n    return status;\n}\n#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */\n\n/****************************************************************/\n/* Sign/verify hashes */\n/****************************************************************/\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \\\n    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)\n\n/* Decode the hash algorithm from alg and store the mbedtls encoding in\n * md_alg. Verify that the hash length is acceptable. */\nstatic psa_status_t psa_rsa_decode_md_type(psa_algorithm_t alg,\n                                           size_t hash_length,\n                                           mbedtls_md_type_t *md_alg)\n{\n    psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);\n    *md_alg = mbedtls_md_type_from_psa_alg(hash_alg);\n\n    /* The Mbed TLS RSA module uses an unsigned int for hash length\n     * parameters. Validate that it fits so that we don't risk an\n     * overflow later. */\n#if SIZE_MAX > UINT_MAX\n    if (hash_length > UINT_MAX) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n#endif\n\n    /* For signatures using a hash, the hash length must be correct. */\n    if (alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW) {\n        if (*md_alg == MBEDTLS_MD_NONE) {\n            return PSA_ERROR_NOT_SUPPORTED;\n        }\n        if (mbedtls_md_get_size_from_type(*md_alg) != hash_length) {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        }\n    }\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t mbedtls_psa_rsa_sign_hash(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,\n    uint8_t *signature, size_t signature_size, size_t *signature_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_rsa_context *rsa = NULL;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_md_type_t md_alg;\n\n    status = mbedtls_psa_rsa_load_representation(attributes->type,\n                                                 key_buffer,\n                                                 key_buffer_size,\n                                                 &rsa);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_rsa_decode_md_type(alg, hash_length, &md_alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (signature_size < mbedtls_rsa_get_len(rsa)) {\n        status = PSA_ERROR_BUFFER_TOO_SMALL;\n        goto exit;\n    }\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)\n    if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) {\n        ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15,\n                                      MBEDTLS_MD_NONE);\n        if (ret == 0) {\n            ret = mbedtls_rsa_pkcs1_sign(rsa,\n                                         mbedtls_psa_get_random,\n                                         MBEDTLS_PSA_RANDOM_STATE,\n                                         md_alg,\n                                         (unsigned int) hash_length,\n                                         hash,\n                                         signature);\n        }\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)\n    if (PSA_ALG_IS_RSA_PSS(alg)) {\n        ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg);\n\n        if (ret == 0) {\n            ret = mbedtls_rsa_rsassa_pss_sign(rsa,\n                                              mbedtls_psa_get_random,\n                                              MBEDTLS_PSA_RANDOM_STATE,\n                                              MBEDTLS_MD_NONE,\n                                              (unsigned int) hash_length,\n                                              hash,\n                                              signature);\n        }\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */\n    {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    if (ret == 0) {\n        *signature_length = mbedtls_rsa_get_len(rsa);\n    }\n    status = mbedtls_to_psa_error(ret);\n\nexit:\n    mbedtls_rsa_free(rsa);\n    mbedtls_free(rsa);\n\n    return status;\n}\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)\nstatic int rsa_pss_expected_salt_len(psa_algorithm_t alg,\n                                     const mbedtls_rsa_context *rsa,\n                                     size_t hash_length)\n{\n    if (PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)) {\n        return MBEDTLS_RSA_SALT_LEN_ANY;\n    }\n    /* Otherwise: standard salt length, i.e. largest possible salt length\n     * up to the hash length. */\n    int klen = (int) mbedtls_rsa_get_len(rsa);   // known to fit\n    int hlen = (int) hash_length; // known to fit\n    int room = klen - 2 - hlen;\n    if (room < 0) {\n        return 0;  // there is no valid signature in this case anyway\n    } else if (room > hlen) {\n        return hlen;\n    } else {\n        return room;\n    }\n}\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */\n\npsa_status_t mbedtls_psa_rsa_verify_hash(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,\n    const uint8_t *signature, size_t signature_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_rsa_context *rsa = NULL;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_md_type_t md_alg;\n\n    status = mbedtls_psa_rsa_load_representation(attributes->type,\n                                                 key_buffer,\n                                                 key_buffer_size,\n                                                 &rsa);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_rsa_decode_md_type(alg, hash_length, &md_alg);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (signature_length != mbedtls_rsa_get_len(rsa)) {\n        status = PSA_ERROR_INVALID_SIGNATURE;\n        goto exit;\n    }\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)\n    if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) {\n        ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15,\n                                      MBEDTLS_MD_NONE);\n        if (ret == 0) {\n            ret = mbedtls_rsa_pkcs1_verify(rsa,\n                                           md_alg,\n                                           (unsigned int) hash_length,\n                                           hash,\n                                           signature);\n        }\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)\n    if (PSA_ALG_IS_RSA_PSS(alg)) {\n        ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg);\n        if (ret == 0) {\n            int slen = rsa_pss_expected_salt_len(alg, rsa, hash_length);\n            ret = mbedtls_rsa_rsassa_pss_verify_ext(rsa,\n                                                    md_alg,\n                                                    (unsigned) hash_length,\n                                                    hash,\n                                                    md_alg,\n                                                    slen,\n                                                    signature);\n        }\n    } else\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */\n    {\n        status = PSA_ERROR_INVALID_ARGUMENT;\n        goto exit;\n    }\n\n    /* Mbed TLS distinguishes \"invalid padding\" from \"valid padding but\n     * the rest of the signature is invalid\". This has little use in\n     * practice and PSA doesn't report this distinction. */\n    status = (ret == MBEDTLS_ERR_RSA_INVALID_PADDING) ?\n             PSA_ERROR_INVALID_SIGNATURE :\n             mbedtls_to_psa_error(ret);\n\nexit:\n    mbedtls_rsa_free(rsa);\n    mbedtls_free(rsa);\n\n    return status;\n}\n\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */\n\n/****************************************************************/\n/* Asymmetric cryptography */\n/****************************************************************/\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)\nstatic int psa_rsa_oaep_set_padding_mode(psa_algorithm_t alg,\n                                         mbedtls_rsa_context *rsa)\n{\n    psa_algorithm_t hash_alg = PSA_ALG_RSA_OAEP_GET_HASH(alg);\n    mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg);\n\n    /* Just to get the error status right, as rsa_set_padding() doesn't\n     * distinguish between \"bad RSA algorithm\" and \"unknown hash\". */\n    if (mbedtls_md_info_from_type(md_alg) == NULL) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    return mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg);\n}\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */\n\npsa_status_t mbedtls_psa_asymmetric_encrypt(const psa_key_attributes_t *attributes,\n                                            const uint8_t *key_buffer,\n                                            size_t key_buffer_size,\n                                            psa_algorithm_t alg,\n                                            const uint8_t *input,\n                                            size_t input_length,\n                                            const uint8_t *salt,\n                                            size_t salt_length,\n                                            uint8_t *output,\n                                            size_t output_size,\n                                            size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    (void) key_buffer;\n    (void) key_buffer_size;\n    (void) input;\n    (void) input_length;\n    (void) salt;\n    (void) salt_length;\n    (void) output;\n    (void) output_size;\n    (void) output_length;\n\n    if (PSA_KEY_TYPE_IS_RSA(attributes->type)) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \\\n        defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)\n        mbedtls_rsa_context *rsa = NULL;\n        status = mbedtls_psa_rsa_load_representation(attributes->type,\n                                                     key_buffer,\n                                                     key_buffer_size,\n                                                     &rsa);\n        if (status != PSA_SUCCESS) {\n            goto rsa_exit;\n        }\n\n        if (output_size < mbedtls_rsa_get_len(rsa)) {\n            status = PSA_ERROR_BUFFER_TOO_SMALL;\n            goto rsa_exit;\n        }\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */\n        if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT)\n            status = mbedtls_to_psa_error(\n                mbedtls_rsa_pkcs1_encrypt(rsa,\n                                          mbedtls_psa_get_random,\n                                          MBEDTLS_PSA_RANDOM_STATE,\n                                          input_length,\n                                          input,\n                                          output));\n#else\n            status = PSA_ERROR_NOT_SUPPORTED;\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */\n        } else\n        if (PSA_ALG_IS_RSA_OAEP(alg)) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)\n            status = mbedtls_to_psa_error(\n                psa_rsa_oaep_set_padding_mode(alg, rsa));\n            if (status != PSA_SUCCESS) {\n                goto rsa_exit;\n            }\n\n            status = mbedtls_to_psa_error(\n                mbedtls_rsa_rsaes_oaep_encrypt(rsa,\n                                               mbedtls_psa_get_random,\n                                               MBEDTLS_PSA_RANDOM_STATE,\n                                               salt, salt_length,\n                                               input_length,\n                                               input,\n                                               output));\n#else\n            status = PSA_ERROR_NOT_SUPPORTED;\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */\n        } else {\n            status = PSA_ERROR_INVALID_ARGUMENT;\n        }\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \\\n        defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)\nrsa_exit:\n        if (status == PSA_SUCCESS) {\n            *output_length = mbedtls_rsa_get_len(rsa);\n        }\n\n        mbedtls_rsa_free(rsa);\n        mbedtls_free(rsa);\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */\n    } else {\n        status = PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    return status;\n}\n\npsa_status_t mbedtls_psa_asymmetric_decrypt(const psa_key_attributes_t *attributes,\n                                            const uint8_t *key_buffer,\n                                            size_t key_buffer_size,\n                                            psa_algorithm_t alg,\n                                            const uint8_t *input,\n                                            size_t input_length,\n                                            const uint8_t *salt,\n                                            size_t salt_length,\n                                            uint8_t *output,\n                                            size_t output_size,\n                                            size_t *output_length)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    (void) key_buffer;\n    (void) key_buffer_size;\n    (void) input;\n    (void) input_length;\n    (void) salt;\n    (void) salt_length;\n    (void) output;\n    (void) output_size;\n    (void) output_length;\n\n    *output_length = 0;\n\n    if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \\\n        defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)\n        mbedtls_rsa_context *rsa = NULL;\n        status = mbedtls_psa_rsa_load_representation(attributes->type,\n                                                     key_buffer,\n                                                     key_buffer_size,\n                                                     &rsa);\n        if (status != PSA_SUCCESS) {\n            goto rsa_exit;\n        }\n\n        if (input_length != mbedtls_rsa_get_len(rsa)) {\n            status = PSA_ERROR_INVALID_ARGUMENT;\n            goto rsa_exit;\n        }\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */\n\n        if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT)\n            status = mbedtls_to_psa_error(\n                mbedtls_rsa_pkcs1_decrypt(rsa,\n                                          mbedtls_psa_get_random,\n                                          MBEDTLS_PSA_RANDOM_STATE,\n                                          output_length,\n                                          input,\n                                          output,\n                                          output_size));\n#else\n            status = PSA_ERROR_NOT_SUPPORTED;\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */\n        } else\n        if (PSA_ALG_IS_RSA_OAEP(alg)) {\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)\n            status = mbedtls_to_psa_error(\n                psa_rsa_oaep_set_padding_mode(alg, rsa));\n            if (status != PSA_SUCCESS) {\n                goto rsa_exit;\n            }\n\n            status = mbedtls_to_psa_error(\n                mbedtls_rsa_rsaes_oaep_decrypt(rsa,\n                                               mbedtls_psa_get_random,\n                                               MBEDTLS_PSA_RANDOM_STATE,\n                                               salt, salt_length,\n                                               output_length,\n                                               input,\n                                               output,\n                                               output_size));\n#else\n            status = PSA_ERROR_NOT_SUPPORTED;\n#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */\n        } else {\n            status = PSA_ERROR_INVALID_ARGUMENT;\n        }\n\n#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \\\n        defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)\nrsa_exit:\n        mbedtls_rsa_free(rsa);\n        mbedtls_free(rsa);\n#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||\n        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */\n    } else {\n        status = PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    return status;\n}\n\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_rsa.h",
    "content": "/*\n *  PSA RSA layer on top of Mbed TLS crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_RSA_H\n#define PSA_CRYPTO_RSA_H\n\n#include <psa/crypto.h>\n#include <mbedtls/rsa.h>\n\n/** Load the contents of a key buffer into an internal RSA representation\n *\n * \\param[in] type          The type of key contained in \\p data.\n * \\param[in] data          The buffer from which to load the representation.\n * \\param[in] data_length   The size in bytes of \\p data.\n * \\param[out] p_rsa        Returns a pointer to an RSA context on success.\n *                          The caller is responsible for freeing both the\n *                          contents of the context and the context itself\n *                          when done.\n */\npsa_status_t mbedtls_psa_rsa_load_representation(psa_key_type_t type,\n                                                 const uint8_t *data,\n                                                 size_t data_length,\n                                                 mbedtls_rsa_context **p_rsa);\n\n/** Import an RSA key in binary format.\n *\n * \\note The signature of this function is that of a PSA driver\n *       import_key entry point. This function behaves as an import_key\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in]  attributes       The attributes for the key to import.\n * \\param[in]  data             The buffer containing the key data in import\n *                              format.\n * \\param[in]  data_length      Size of the \\p data buffer in bytes.\n * \\param[out] key_buffer       The buffer containing the key data in output\n *                              format.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes. This\n *                              size is greater or equal to \\p data_length.\n * \\param[out] key_buffer_length  The length of the data written in \\p\n *                                key_buffer in bytes.\n * \\param[out] bits             The key size in number of bits.\n *\n * \\retval #PSA_SUCCESS  The RSA key was imported successfully.\n * \\retval #PSA_ERROR_INVALID_ARGUMENT\n *         The key data is not correctly formatted.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n */\npsa_status_t mbedtls_psa_rsa_import_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *data, size_t data_length,\n    uint8_t *key_buffer, size_t key_buffer_size,\n    size_t *key_buffer_length, size_t *bits);\n\n/** Export an RSA key to export representation\n *\n * \\param[in] type          The type of key (public/private) to export\n * \\param[in] rsa           The internal RSA representation from which to export\n * \\param[out] data         The buffer to export to\n * \\param[in] data_size     The length of the buffer to export to\n * \\param[out] data_length  The amount of bytes written to \\p data\n */\npsa_status_t mbedtls_psa_rsa_export_key(psa_key_type_t type,\n                                        mbedtls_rsa_context *rsa,\n                                        uint8_t *data,\n                                        size_t data_size,\n                                        size_t *data_length);\n\n/** Export a public RSA key or the public part of an RSA key pair in binary\n *  format.\n *\n * \\note The signature of this function is that of a PSA driver\n *       export_public_key entry point. This function behaves as an\n *       export_public_key entry point as defined in the PSA driver interface\n *       specification.\n *\n * \\param[in]  attributes       The attributes for the key to export.\n * \\param[in]  key_buffer       Material or context of the key to export.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[out] data             Buffer where the key data is to be written.\n * \\param[in]  data_size        Size of the \\p data buffer in bytes.\n * \\param[out] data_length      On success, the number of bytes written in\n *                              \\p data.\n *\n * \\retval #PSA_SUCCESS  The RSA public key was exported successfully.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n */\npsa_status_t mbedtls_psa_rsa_export_public_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    uint8_t *data, size_t data_size, size_t *data_length);\n\n/**\n * \\brief Generate an RSA key.\n *\n * \\param[in]  attributes         The attributes for the RSA key to generate.\n * \\param[in]  custom_data        The public exponent to use.\n *                                This can be a null pointer if\n *                                \\c params_data_length is 0.\n * \\param custom_data_length      Length of \\p custom_data in bytes.\n *                                This can be 0, in which case the\n *                                public exponent will be 65537.\n * \\param[out] key_buffer         Buffer where the key data is to be written.\n * \\param[in]  key_buffer_size    Size of \\p key_buffer in bytes.\n * \\param[out] key_buffer_length  On success, the number of bytes written in\n *                                \\p key_buffer.\n *\n * \\retval #PSA_SUCCESS\n *         The key was successfully generated.\n * \\retval #PSA_ERROR_NOT_SUPPORTED\n *         Key length or type not supported.\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of \\p key_buffer is too small.\n */\npsa_status_t mbedtls_psa_rsa_generate_key(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *custom_data, size_t custom_data_length,\n    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);\n\n/** Sign an already-calculated hash with an RSA private key.\n *\n * \\note The signature of this function is that of a PSA driver\n *       sign_hash entry point. This function behaves as a sign_hash\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in]  attributes       The attributes of the RSA key to use for the\n *                              operation.\n * \\param[in]  key_buffer       The buffer containing the RSA key context.\n *                              format.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[in]  alg              A signature algorithm that is compatible with\n *                              an RSA key.\n * \\param[in]  hash             The hash or message to sign.\n * \\param[in]  hash_length      Size of the \\p hash buffer in bytes.\n * \\param[out] signature        Buffer where the signature is to be written.\n * \\param[in]  signature_size   Size of the \\p signature buffer in bytes.\n * \\param[out] signature_length On success, the number of bytes\n *                              that make up the returned signature value.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p signature buffer is too small. You can\n *         determine a sufficient buffer size by calling\n *         #PSA_SIGN_OUTPUT_SIZE(\\c PSA_KEY_TYPE_RSA_KEY_PAIR, \\c key_bits,\n *         \\p alg) where \\c key_bits is the bit-size of the RSA key.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n */\npsa_status_t mbedtls_psa_rsa_sign_hash(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,\n    uint8_t *signature, size_t signature_size, size_t *signature_length);\n\n/**\n * \\brief Verify the signature a hash or short message using a public RSA key.\n *\n * \\note The signature of this function is that of a PSA driver\n *       verify_hash entry point. This function behaves as a verify_hash\n *       entry point as defined in the PSA driver interface specification for\n *       transparent drivers.\n *\n * \\param[in]  attributes       The attributes of the RSA key to use for the\n *                              operation.\n * \\param[in]  key_buffer       The buffer containing the RSA key context.\n *                              format.\n * \\param[in]  key_buffer_size  Size of the \\p key_buffer buffer in bytes.\n * \\param[in]  alg              A signature algorithm that is compatible with\n *                              an RSA key.\n * \\param[in]  hash             The hash or message whose signature is to be\n *                              verified.\n * \\param[in]  hash_length      Size of the \\p hash buffer in bytes.\n * \\param[in]  signature        Buffer containing the signature to verify.\n * \\param[in]  signature_length Size of the \\p signature buffer in bytes.\n *\n * \\retval #PSA_SUCCESS\n *         The signature is valid.\n * \\retval #PSA_ERROR_INVALID_SIGNATURE\n *         The calculation was performed successfully, but the passed\n *         signature is not a valid signature.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n */\npsa_status_t mbedtls_psa_rsa_verify_hash(\n    const psa_key_attributes_t *attributes,\n    const uint8_t *key_buffer, size_t key_buffer_size,\n    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,\n    const uint8_t *signature, size_t signature_length);\n\n/**\n * \\brief Encrypt a short message with a public key.\n *\n * \\param attributes            The attributes for the key to import.\n * \\param key_buffer            Buffer where the key data is to be written.\n * \\param key_buffer_size       Size of the \\p key_buffer buffer in bytes.\n * \\param input_length          Size of the \\p input buffer in bytes.\n * \\param[in] salt              A salt or label, if supported by the\n *                              encryption algorithm.\n *                              If the algorithm does not support a\n *                              salt, pass \\c NULL.\n *                              If the algorithm supports an optional\n *                              salt and you do not want to pass a salt,\n *                              pass \\c NULL.\n *\n *                              - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is\n *                                supported.\n * \\param salt_length           Size of the \\p salt buffer in bytes.\n *                              If \\p salt is \\c NULL, pass 0.\n * \\param[out] output           Buffer where the encrypted message is to\n *                              be written.\n * \\param output_size           Size of the \\p output buffer in bytes.\n * \\param[out] output_length    On success, the number of bytes\n *                              that make up the returned output.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p output buffer is too small. You can\n *         determine a sufficient buffer size by calling\n *         #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\\c key_type, \\c key_bits, \\p alg)\n *         where \\c key_type and \\c key_bits are the type and bit-size\n *         respectively of \\p key.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t mbedtls_psa_asymmetric_encrypt(const psa_key_attributes_t *attributes,\n                                            const uint8_t *key_buffer,\n                                            size_t key_buffer_size,\n                                            psa_algorithm_t alg,\n                                            const uint8_t *input,\n                                            size_t input_length,\n                                            const uint8_t *salt,\n                                            size_t salt_length,\n                                            uint8_t *output,\n                                            size_t output_size,\n                                            size_t *output_length);\n\n/**\n * \\brief Decrypt a short message with a private key.\n *\n * \\param attributes            The attributes for the key to import.\n * \\param key_buffer            Buffer where the key data is to be written.\n * \\param key_buffer_size       Size of the \\p key_buffer buffer in bytes.\n * \\param[in] input             The message to decrypt.\n * \\param input_length          Size of the \\p input buffer in bytes.\n * \\param[in] salt              A salt or label, if supported by the\n *                              encryption algorithm.\n *                              If the algorithm does not support a\n *                              salt, pass \\c NULL.\n *                              If the algorithm supports an optional\n *                              salt and you do not want to pass a salt,\n *                              pass \\c NULL.\n *\n *                              - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is\n *                                supported.\n * \\param salt_length           Size of the \\p salt buffer in bytes.\n *                              If \\p salt is \\c NULL, pass 0.\n * \\param[out] output           Buffer where the decrypted message is to\n *                              be written.\n * \\param output_size           Size of the \\c output buffer in bytes.\n * \\param[out] output_length    On success, the number of bytes\n *                              that make up the returned output.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_BUFFER_TOO_SMALL\n *         The size of the \\p output buffer is too small. You can\n *         determine a sufficient buffer size by calling\n *         #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\\c key_type, \\c key_bits, \\p alg)\n *         where \\c key_type and \\c key_bits are the type and bit-size\n *         respectively of \\p key.\n * \\retval #PSA_ERROR_NOT_SUPPORTED \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_COMMUNICATION_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_HARDWARE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_ENTROPY \\emptydescription\n * \\retval #PSA_ERROR_INVALID_PADDING \\emptydescription\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been previously initialized by psa_crypto_init().\n *         It is implementation-dependent whether a failure to initialize\n *         results in this error code.\n */\npsa_status_t mbedtls_psa_asymmetric_decrypt(const psa_key_attributes_t *attributes,\n                                            const uint8_t *key_buffer,\n                                            size_t key_buffer_size,\n                                            psa_algorithm_t alg,\n                                            const uint8_t *input,\n                                            size_t input_length,\n                                            const uint8_t *salt,\n                                            size_t salt_length,\n                                            uint8_t *output,\n                                            size_t output_size,\n                                            size_t *output_length);\n\n#endif /* PSA_CRYPTO_RSA_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_se.c",
    "content": "/*\n *  PSA crypto support for secure element drivers\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n\n#include <stdint.h>\n#include <string.h>\n\n#include \"psa/crypto_se_driver.h\"\n\n#include \"psa_crypto_se.h\"\n\n#if defined(MBEDTLS_PSA_ITS_FILE_C)\n#include \"psa_crypto_its.h\"\n#else /* Native ITS implementation */\n#include \"psa/error.h\"\n#include \"psa/internal_trusted_storage.h\"\n#endif\n\n#include \"mbedtls/platform.h\"\n\n\n\n/****************************************************************/\n/* Driver lookup */\n/****************************************************************/\n\n/* This structure is identical to psa_drv_se_context_t declared in\n * `crypto_se_driver.h`, except that some parts are writable here\n * (non-const, or pointer to non-const). */\ntypedef struct {\n    void *persistent_data;\n    size_t persistent_data_size;\n    uintptr_t transient_data;\n} psa_drv_se_internal_context_t;\n\nstruct psa_se_drv_table_entry_s {\n    psa_key_location_t location;\n    const psa_drv_se_t *methods;\n    union {\n        psa_drv_se_internal_context_t internal;\n        psa_drv_se_context_t context;\n    } u;\n};\n\nstatic psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS];\n\npsa_se_drv_table_entry_t *psa_get_se_driver_entry(\n    psa_key_lifetime_t lifetime)\n{\n    size_t i;\n    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime);\n    /* In the driver table, location=0 means an entry that isn't used.\n     * No driver has a location of 0 because it's a reserved value\n     * (which designates transparent keys). Make sure we never return\n     * a driver entry for location 0. */\n    if (location == 0) {\n        return NULL;\n    }\n    for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {\n        if (driver_table[i].location == location) {\n            return &driver_table[i];\n        }\n    }\n    return NULL;\n}\n\nconst psa_drv_se_t *psa_get_se_driver_methods(\n    const psa_se_drv_table_entry_t *driver)\n{\n    return driver->methods;\n}\n\npsa_drv_se_context_t *psa_get_se_driver_context(\n    psa_se_drv_table_entry_t *driver)\n{\n    return &driver->u.context;\n}\n\nint psa_get_se_driver(psa_key_lifetime_t lifetime,\n                      const psa_drv_se_t **p_methods,\n                      psa_drv_se_context_t **p_drv_context)\n{\n    psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime);\n    if (p_methods != NULL) {\n        *p_methods = (driver ? driver->methods : NULL);\n    }\n    if (p_drv_context != NULL) {\n        *p_drv_context = (driver ? &driver->u.context : NULL);\n    }\n    return driver != NULL;\n}\n\n\n\n/****************************************************************/\n/* Persistent data management */\n/****************************************************************/\n\nstatic psa_status_t psa_get_se_driver_its_file_uid(\n    const psa_se_drv_table_entry_t *driver,\n    psa_storage_uid_t *uid)\n{\n    if (driver->location > PSA_MAX_SE_LOCATION) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    /* ITS file sizes are limited to 32 bits. */\n    if (driver->u.internal.persistent_data_size > UINT32_MAX) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */\n    *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->location;\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_load_se_persistent_data(\n    const psa_se_drv_table_entry_t *driver)\n{\n    psa_status_t status;\n    psa_storage_uid_t uid;\n    size_t length;\n\n    status = psa_get_se_driver_its_file_uid(driver, &uid);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    /* Read the amount of persistent data that the driver requests.\n     * If the data in storage is larger, it is truncated. If the data\n     * in storage is smaller, silently keep what is already at the end\n     * of the output buffer. */\n    /* psa_get_se_driver_its_file_uid ensures that the size_t\n     * persistent_data_size is in range, but compilers don't know that,\n     * so cast to reassure them. */\n    return psa_its_get(uid, 0,\n                       (uint32_t) driver->u.internal.persistent_data_size,\n                       driver->u.internal.persistent_data,\n                       &length);\n}\n\npsa_status_t psa_save_se_persistent_data(\n    const psa_se_drv_table_entry_t *driver)\n{\n    psa_status_t status;\n    psa_storage_uid_t uid;\n\n    status = psa_get_se_driver_its_file_uid(driver, &uid);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    /* psa_get_se_driver_its_file_uid ensures that the size_t\n     * persistent_data_size is in range, but compilers don't know that,\n     * so cast to reassure them. */\n    return psa_its_set(uid,\n                       (uint32_t) driver->u.internal.persistent_data_size,\n                       driver->u.internal.persistent_data,\n                       0);\n}\n\npsa_status_t psa_destroy_se_persistent_data(psa_key_location_t location)\n{\n    psa_storage_uid_t uid;\n    if (location > PSA_MAX_SE_LOCATION) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n    uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + location;\n    return psa_its_remove(uid);\n}\n\npsa_status_t psa_find_se_slot_for_key(\n    const psa_key_attributes_t *attributes,\n    psa_key_creation_method_t method,\n    psa_se_drv_table_entry_t *driver,\n    psa_key_slot_number_t *slot_number)\n{\n    psa_status_t status;\n    psa_key_location_t key_location =\n        PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes));\n\n    /* If the location is wrong, it's a bug in the library. */\n    if (driver->location != key_location) {\n        return PSA_ERROR_CORRUPTION_DETECTED;\n    }\n\n    /* If the driver doesn't support key creation in any way, give up now. */\n    if (driver->methods->key_management == NULL) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    if (psa_get_key_slot_number(attributes, slot_number) == PSA_SUCCESS) {\n        /* The application wants to use a specific slot. Allow it if\n         * the driver supports it. On a system with isolation,\n         * the crypto service must check that the application is\n         * permitted to request this slot. */\n        psa_drv_se_validate_slot_number_t p_validate_slot_number =\n            driver->methods->key_management->p_validate_slot_number;\n        if (p_validate_slot_number == NULL) {\n            return PSA_ERROR_NOT_SUPPORTED;\n        }\n        status = p_validate_slot_number(&driver->u.context,\n                                        driver->u.internal.persistent_data,\n                                        attributes, method,\n                                        *slot_number);\n    } else if (method == PSA_KEY_CREATION_REGISTER) {\n        /* The application didn't specify a slot number. This doesn't\n         * make sense when registering a slot. */\n        return PSA_ERROR_INVALID_ARGUMENT;\n    } else {\n        /* The application didn't tell us which slot to use. Let the driver\n         * choose. This is the normal case. */\n        psa_drv_se_allocate_key_t p_allocate =\n            driver->methods->key_management->p_allocate;\n        if (p_allocate == NULL) {\n            return PSA_ERROR_NOT_SUPPORTED;\n        }\n        status = p_allocate(&driver->u.context,\n                            driver->u.internal.persistent_data,\n                            attributes, method,\n                            slot_number);\n    }\n    return status;\n}\n\npsa_status_t psa_destroy_se_key(psa_se_drv_table_entry_t *driver,\n                                psa_key_slot_number_t slot_number)\n{\n    psa_status_t status;\n    psa_status_t storage_status;\n    /* Normally a missing method would mean that the action is not\n     * supported. But psa_destroy_key() is not supposed to return\n     * PSA_ERROR_NOT_SUPPORTED: if you can create a key, you should\n     * be able to destroy it. The only use case for a driver that\n     * does not have a way to destroy keys at all is if the keys are\n     * locked in a read-only state: we can use the keys but not\n     * destroy them. Hence, if the driver doesn't support destroying\n     * keys, it's really a lack of permission. */\n    if (driver->methods->key_management == NULL ||\n        driver->methods->key_management->p_destroy == NULL) {\n        return PSA_ERROR_NOT_PERMITTED;\n    }\n    status = driver->methods->key_management->p_destroy(\n        &driver->u.context,\n        driver->u.internal.persistent_data,\n        slot_number);\n    storage_status = psa_save_se_persistent_data(driver);\n    return status == PSA_SUCCESS ? storage_status : status;\n}\n\npsa_status_t psa_init_all_se_drivers(void)\n{\n    size_t i;\n    for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {\n        psa_se_drv_table_entry_t *driver = &driver_table[i];\n        if (driver->location == 0) {\n            continue; /* skipping unused entry */\n        }\n        const psa_drv_se_t *methods = psa_get_se_driver_methods(driver);\n        if (methods->p_init != NULL) {\n            psa_status_t status = methods->p_init(\n                &driver->u.context,\n                driver->u.internal.persistent_data,\n                driver->location);\n            if (status != PSA_SUCCESS) {\n                return status;\n            }\n            status = psa_save_se_persistent_data(driver);\n            if (status != PSA_SUCCESS) {\n                return status;\n            }\n        }\n    }\n    return PSA_SUCCESS;\n}\n\n\n\n/****************************************************************/\n/* Driver registration */\n/****************************************************************/\n\npsa_status_t psa_register_se_driver(\n    psa_key_location_t location,\n    const psa_drv_se_t *methods)\n{\n    size_t i;\n    psa_status_t status;\n\n    if (methods->hal_version != PSA_DRV_SE_HAL_VERSION) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n    /* Driver table entries are 0-initialized. 0 is not a valid driver\n     * location because it means a transparent key. */\n    MBEDTLS_STATIC_ASSERT(PSA_KEY_LOCATION_LOCAL_STORAGE == 0,\n                          \"Secure element support requires 0 to mean a local key\");\n\n    if (location == PSA_KEY_LOCATION_LOCAL_STORAGE) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n    if (location > PSA_MAX_SE_LOCATION) {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {\n        if (driver_table[i].location == 0) {\n            break;\n        }\n        /* Check that location isn't already in use up to the first free\n         * entry. Since entries are created in order and never deleted,\n         * there can't be a used entry after the first free entry. */\n        if (driver_table[i].location == location) {\n            return PSA_ERROR_ALREADY_EXISTS;\n        }\n    }\n    if (i == PSA_MAX_SE_DRIVERS) {\n        return PSA_ERROR_INSUFFICIENT_MEMORY;\n    }\n\n    driver_table[i].location = location;\n    driver_table[i].methods = methods;\n    driver_table[i].u.internal.persistent_data_size =\n        methods->persistent_data_size;\n\n    if (methods->persistent_data_size != 0) {\n        driver_table[i].u.internal.persistent_data =\n            mbedtls_calloc(1, methods->persistent_data_size);\n        if (driver_table[i].u.internal.persistent_data == NULL) {\n            status = PSA_ERROR_INSUFFICIENT_MEMORY;\n            goto error;\n        }\n        /* Load the driver's persistent data. On first use, the persistent\n         * data does not exist in storage, and is initialized to\n         * all-bits-zero by the calloc call just above. */\n        status = psa_load_se_persistent_data(&driver_table[i]);\n        if (status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST) {\n            goto error;\n        }\n    }\n\n    return PSA_SUCCESS;\n\nerror:\n    memset(&driver_table[i], 0, sizeof(driver_table[i]));\n    return status;\n}\n\nvoid psa_unregister_all_se_drivers(void)\n{\n    size_t i;\n    for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {\n        if (driver_table[i].u.internal.persistent_data != NULL) {\n            mbedtls_free(driver_table[i].u.internal.persistent_data);\n        }\n    }\n    memset(driver_table, 0, sizeof(driver_table));\n}\n\n\n\n/****************************************************************/\n/* The end */\n/****************************************************************/\n\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_se.h",
    "content": "/*\n *  PSA crypto support for secure element drivers\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_SE_H\n#define PSA_CRYPTO_SE_H\n\n/*\n * Include the build-time configuration information header. Here, we do not\n * include `\"mbedtls/build_info.h\"` directly but `\"psa/build_info.h\"`, which\n * is basically just an alias to it. This is to ease the maintenance of the\n * TF-PSA-Crypto repository which has a different build system and\n * configuration.\n */\n#include \"psa/build_info.h\"\n\n#include \"psa/crypto.h\"\n#include \"psa/crypto_se_driver.h\"\n\n/** The maximum location value that this implementation supports\n * for a secure element.\n *\n * This is not a characteristic that each PSA implementation has, but a\n * limitation of the current implementation due to the constraints imposed\n * by storage. See #PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE.\n *\n * The minimum location value for a secure element is 1, like on any\n * PSA implementation (0 means a transparent key).\n */\n#define PSA_MAX_SE_LOCATION 255\n\n/** The base of the range of ITS file identifiers for secure element\n * driver persistent data.\n *\n * We use a slice of the implementation reserved range 0xffff0000..0xffffffff,\n * specifically the range 0xfffffe00..0xfffffeff. The length of this range\n * drives the value of #PSA_MAX_SE_LOCATION. The identifier 0xfffffe00 is\n * actually not used since it corresponds to #PSA_KEY_LOCATION_LOCAL_STORAGE\n * which doesn't have a driver.\n */\n#define PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE ((psa_key_id_t) 0xfffffe00)\n\n/** The maximum number of registered secure element driver locations. */\n#define PSA_MAX_SE_DRIVERS 4\n\n/** Unregister all secure element drivers.\n *\n * \\warning Do not call this function while the library is in the initialized\n *          state. This function is only intended to be called at the end\n *          of mbedtls_psa_crypto_free().\n */\nvoid psa_unregister_all_se_drivers(void);\n\n/** Initialize all secure element drivers.\n *\n * Called from psa_crypto_init().\n */\npsa_status_t psa_init_all_se_drivers(void);\n\n/** A structure that describes a registered secure element driver.\n *\n * A secure element driver table entry contains a pointer to the\n * driver's method table as well as the driver context structure.\n */\ntypedef struct psa_se_drv_table_entry_s psa_se_drv_table_entry_t;\n\n/** Return the secure element driver information for a lifetime value.\n *\n * \\param lifetime              The lifetime value to query.\n * \\param[out] p_methods        On output, if there is a driver,\n *                              \\c *methods points to its method table.\n *                              Otherwise \\c *methods is \\c NULL.\n * \\param[out] p_drv_context    On output, if there is a driver,\n *                              \\c *drv_context points to its context\n *                              structure.\n *                              Otherwise \\c *drv_context is \\c NULL.\n *\n * \\retval 1\n *         \\p lifetime corresponds to a registered driver.\n * \\retval 0\n *         \\p lifetime does not correspond to a registered driver.\n */\nint psa_get_se_driver(psa_key_lifetime_t lifetime,\n                      const psa_drv_se_t **p_methods,\n                      psa_drv_se_context_t **p_drv_context);\n\n/** Return the secure element driver table entry for a lifetime value.\n *\n * \\param lifetime      The lifetime value to query.\n *\n * \\return The driver table entry for \\p lifetime, or\n *         \\p NULL if \\p lifetime does not correspond to a registered driver.\n */\npsa_se_drv_table_entry_t *psa_get_se_driver_entry(\n    psa_key_lifetime_t lifetime);\n\n/** Return the method table for a secure element driver.\n *\n * \\param[in] driver    The driver table entry to access, or \\c NULL.\n *\n * \\return The driver's method table.\n *         \\c NULL if \\p driver is \\c NULL.\n */\nconst psa_drv_se_t *psa_get_se_driver_methods(\n    const psa_se_drv_table_entry_t *driver);\n\n/** Return the context of a secure element driver.\n *\n * \\param[in] driver    The driver table entry to access, or \\c NULL.\n *\n * \\return A pointer to the driver context.\n *         \\c NULL if \\p driver is \\c NULL.\n */\npsa_drv_se_context_t *psa_get_se_driver_context(\n    psa_se_drv_table_entry_t *driver);\n\n/** Find a free slot for a key that is to be created.\n *\n * This function calls the relevant method in the driver to find a suitable\n * slot for a key with the given attributes.\n *\n * \\param[in] attributes    Metadata about the key that is about to be created.\n * \\param[in] driver        The driver table entry to query.\n * \\param[out] slot_number  On success, a slot number that is free in this\n *                          secure element.\n */\npsa_status_t psa_find_se_slot_for_key(\n    const psa_key_attributes_t *attributes,\n    psa_key_creation_method_t method,\n    psa_se_drv_table_entry_t *driver,\n    psa_key_slot_number_t *slot_number);\n\n/** Destroy a key in a secure element.\n *\n * This function calls the relevant driver method to destroy a key\n * and updates the driver's persistent data.\n */\npsa_status_t psa_destroy_se_key(psa_se_drv_table_entry_t *driver,\n                                psa_key_slot_number_t slot_number);\n\n/** Load the persistent data of a secure element driver.\n *\n * \\param driver        The driver table entry containing the persistent\n *                      data to load from storage.\n *\n * \\return #PSA_SUCCESS\n * \\return #PSA_ERROR_NOT_SUPPORTED\n * \\return #PSA_ERROR_DOES_NOT_EXIST\n * \\return #PSA_ERROR_STORAGE_FAILURE\n * \\return #PSA_ERROR_DATA_CORRUPT\n * \\return #PSA_ERROR_INVALID_ARGUMENT\n */\npsa_status_t psa_load_se_persistent_data(\n    const psa_se_drv_table_entry_t *driver);\n\n/** Save the persistent data of a secure element driver.\n *\n * \\param[in] driver    The driver table entry containing the persistent\n *                      data to save to storage.\n *\n * \\return #PSA_SUCCESS\n * \\return #PSA_ERROR_NOT_SUPPORTED\n * \\return #PSA_ERROR_NOT_PERMITTED\n * \\return #PSA_ERROR_NOT_SUPPORTED\n * \\return #PSA_ERROR_INSUFFICIENT_STORAGE\n * \\return #PSA_ERROR_STORAGE_FAILURE\n * \\return #PSA_ERROR_INVALID_ARGUMENT\n */\npsa_status_t psa_save_se_persistent_data(\n    const psa_se_drv_table_entry_t *driver);\n\n/** Destroy the persistent data of a secure element driver.\n *\n * This is currently only used for testing.\n *\n * \\param[in] location  The location identifier for the driver whose\n *                      persistent data is to be erased.\n */\npsa_status_t psa_destroy_se_persistent_data(psa_key_location_t location);\n\n\n/** The storage representation of a key whose data is in a secure element.\n */\ntypedef struct {\n    uint8_t slot_number[sizeof(psa_key_slot_number_t)];\n} psa_se_key_data_storage_t;\n\n#endif /* PSA_CRYPTO_SE_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_slot_management.c",
    "content": "/*\n *  PSA crypto layer on top of Mbed TLS crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n\n#include \"psa/crypto.h\"\n\n#include \"psa_crypto_core.h\"\n#include \"psa_crypto_driver_wrappers_no_static.h\"\n#include \"psa_crypto_slot_management.h\"\n#include \"psa_crypto_storage.h\"\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n#include \"psa_crypto_se.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include \"mbedtls/platform.h\"\n#if defined(MBEDTLS_THREADING_C)\n#include \"mbedtls/threading.h\"\n#endif\n\n\n\n/* Make sure we have distinct ranges of key identifiers for distinct\n * purposes. */\nMBEDTLS_STATIC_ASSERT(PSA_KEY_ID_USER_MIN < PSA_KEY_ID_USER_MAX,\n                      \"Empty user key ID range\");\nMBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN < PSA_KEY_ID_VENDOR_MAX,\n                      \"Empty vendor key ID range\");\nMBEDTLS_STATIC_ASSERT(MBEDTLS_PSA_KEY_ID_BUILTIN_MIN <= MBEDTLS_PSA_KEY_ID_BUILTIN_MAX,\n                      \"Empty builtin key ID range\");\nMBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VOLATILE_MIN <= PSA_KEY_ID_VOLATILE_MAX,\n                      \"Empty volatile key ID range\");\n\nMBEDTLS_STATIC_ASSERT(PSA_KEY_ID_USER_MAX < PSA_KEY_ID_VENDOR_MIN ||\n                      PSA_KEY_ID_VENDOR_MAX < PSA_KEY_ID_USER_MIN,\n                      \"Overlap between user key IDs and vendor key IDs\");\n\nMBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN <= MBEDTLS_PSA_KEY_ID_BUILTIN_MIN &&\n                      MBEDTLS_PSA_KEY_ID_BUILTIN_MAX <= PSA_KEY_ID_VENDOR_MAX,\n                      \"Builtin key identifiers are not in the vendor range\");\n\nMBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN <= PSA_KEY_ID_VOLATILE_MIN &&\n                      PSA_KEY_ID_VOLATILE_MAX <= PSA_KEY_ID_VENDOR_MAX,\n                      \"Volatile key identifiers are not in the vendor range\");\n\nMBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VOLATILE_MAX < MBEDTLS_PSA_KEY_ID_BUILTIN_MIN ||\n                      MBEDTLS_PSA_KEY_ID_BUILTIN_MAX < PSA_KEY_ID_VOLATILE_MIN,\n                      \"Overlap between builtin key IDs and volatile key IDs\");\n\n\n\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n\n/* Dynamic key store.\n *\n * The key store consists of multiple slices.\n *\n * The volatile keys are stored in variable-sized tables called slices.\n * Slices are allocated on demand and deallocated when possible.\n * The size of slices increases exponentially, so the average overhead\n * (number of slots that are allocated but not used) is roughly\n * proportional to the number of keys (with a factor that grows\n * when the key store is fragmented).\n *\n * One slice is dedicated to the cache of persistent and built-in keys.\n * For simplicity, they are separated from volatile keys. This cache\n * slice has a fixed size and has the slice index KEY_SLOT_CACHE_SLICE_INDEX,\n * located after the slices for volatile keys.\n */\n\n/* Size of the last slice containing the cache of persistent and built-in keys. */\n#define PERSISTENT_KEY_CACHE_COUNT MBEDTLS_PSA_KEY_SLOT_COUNT\n\n/* Volatile keys are stored in slices 0 through\n * (KEY_SLOT_VOLATILE_SLICE_COUNT - 1) inclusive.\n * Each slice is twice the size of the previous slice.\n * Volatile key identifiers encode the slice number as follows:\n *     bits 30..31:  0b10 (mandated by the PSA Crypto specification).\n *     bits 25..29:  slice index (0...KEY_SLOT_VOLATILE_SLICE_COUNT-1)\n *     bits 0..24:   slot index in slice\n */\n#define KEY_ID_SLOT_INDEX_WIDTH 25u\n#define KEY_ID_SLICE_INDEX_WIDTH 5u\n\n#define KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH 16u\n#define KEY_SLOT_VOLATILE_SLICE_COUNT 22u\n#define KEY_SLICE_COUNT (KEY_SLOT_VOLATILE_SLICE_COUNT + 1u)\n#define KEY_SLOT_CACHE_SLICE_INDEX KEY_SLOT_VOLATILE_SLICE_COUNT\n\n\n/* Check that the length of the largest slice (calculated as\n * KEY_SLICE_LENGTH_MAX below) does not overflow size_t. We use\n * an indirect method in case the calculation of KEY_SLICE_LENGTH_MAX\n * itself overflows uintmax_t: if (BASE_LENGTH << c)\n * overflows size_t then BASE_LENGTH > SIZE_MAX >> c.\n */\n#if (KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH >              \\\n     SIZE_MAX >> (KEY_SLOT_VOLATILE_SLICE_COUNT - 1))\n#error \"Maximum slice length overflows size_t\"\n#endif\n\n#if KEY_ID_SLICE_INDEX_WIDTH + KEY_ID_SLOT_INDEX_WIDTH > 30\n#error \"Not enough room in volatile key IDs for slice index and slot index\"\n#endif\n#if KEY_SLOT_VOLATILE_SLICE_COUNT > (1 << KEY_ID_SLICE_INDEX_WIDTH)\n#error \"Too many slices to fit the slice index in a volatile key ID\"\n#endif\n#define KEY_SLICE_LENGTH_MAX                                            \\\n    (KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH << (KEY_SLOT_VOLATILE_SLICE_COUNT - 1))\n#if KEY_SLICE_LENGTH_MAX > 1 << KEY_ID_SLOT_INDEX_WIDTH\n#error \"Not enough room in volatile key IDs for a slot index in the largest slice\"\n#endif\n#if KEY_ID_SLICE_INDEX_WIDTH > 8\n#error \"Slice index does not fit in uint8_t for psa_key_slot_t::slice_index\"\n#endif\n\n\n/* Calculate the volatile key id to use for a given slot.\n * This function assumes valid parameter values. */\nstatic psa_key_id_t volatile_key_id_of_index(size_t slice_idx,\n                                             size_t slot_idx)\n{\n    /* We assert above that the slice and slot indexes fit in separate\n     * bit-fields inside psa_key_id_t, which is a 32-bit type per the\n     * PSA Cryptography specification. */\n    return (psa_key_id_t) (0x40000000u |\n                           (slice_idx << KEY_ID_SLOT_INDEX_WIDTH) |\n                           slot_idx);\n}\n\n/* Calculate the slice containing the given volatile key.\n * This function assumes valid parameter values. */\nstatic size_t slice_index_of_volatile_key_id(psa_key_id_t key_id)\n{\n    size_t mask = (1LU << KEY_ID_SLICE_INDEX_WIDTH) - 1;\n    return (key_id >> KEY_ID_SLOT_INDEX_WIDTH) & mask;\n}\n\n/* Calculate the index of the slot containing the given volatile key.\n * This function assumes valid parameter values. */\nstatic size_t slot_index_of_volatile_key_id(psa_key_id_t key_id)\n{\n    return key_id & ((1LU << KEY_ID_SLOT_INDEX_WIDTH) - 1);\n}\n\n/* In global_data.first_free_slot_index, use this special value to\n * indicate that the slice is full. */\n#define FREE_SLOT_INDEX_NONE ((size_t) -1)\n\n#if defined(MBEDTLS_TEST_HOOKS)\nsize_t psa_key_slot_volatile_slice_count(void)\n{\n    return KEY_SLOT_VOLATILE_SLICE_COUNT;\n}\n#endif\n\n#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n\n/* Static key store.\n *\n * All the keys (volatile or persistent) are in a single slice.\n * We only use slices as a concept to allow some differences between\n * static and dynamic key store management to be buried in auxiliary\n * functions.\n */\n\n#define PERSISTENT_KEY_CACHE_COUNT MBEDTLS_PSA_KEY_SLOT_COUNT\n#define KEY_SLICE_COUNT 1u\n#define KEY_SLOT_CACHE_SLICE_INDEX 0\n\n#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n\n\ntypedef struct {\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n    psa_key_slot_t *key_slices[KEY_SLICE_COUNT];\n    size_t first_free_slot_index[KEY_SLOT_VOLATILE_SLICE_COUNT];\n#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n    psa_key_slot_t key_slots[MBEDTLS_PSA_KEY_SLOT_COUNT];\n#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n    uint8_t key_slots_initialized;\n} psa_global_data_t;\n\nstatic psa_global_data_t global_data;\n\nstatic uint8_t psa_get_key_slots_initialized(void)\n{\n    uint8_t initialized;\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n    initialized = global_data.key_slots_initialized;\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);\n#endif /* defined(MBEDTLS_THREADING_C) */\n\n    return initialized;\n}\n\n\n\n/** The length of the given slice in the key slot table.\n *\n * \\param slice_idx     The slice number. It must satisfy\n *                      0 <= slice_idx < KEY_SLICE_COUNT.\n *\n * \\return              The number of elements in the given slice.\n */\nstatic inline size_t key_slice_length(size_t slice_idx);\n\n/** Get a pointer to the slot where the given volatile key is located.\n *\n * \\param key_id        The key identifier. It must be a valid volatile key\n *                      identifier.\n * \\return              A pointer to the only slot that the given key\n *                      can be in. Note that the slot may be empty or\n *                      contain a different key.\n */\nstatic inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id);\n\n/** Get a pointer to an entry in the persistent key cache.\n *\n * \\param slot_idx      The index in the table. It must satisfy\n *                      0 <= slot_idx < PERSISTENT_KEY_CACHE_COUNT.\n * \\return              A pointer to the slot containing the given\n *                      persistent key cache entry.\n */\nstatic inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx);\n\n/** Get a pointer to a slot given by slice and index.\n *\n * \\param slice_idx     The slice number. It must satisfy\n *                      0 <= slice_idx < KEY_SLICE_COUNT.\n * \\param slot_idx      An index in the given slice. It must satisfy\n *                      0 <= slot_idx < key_slice_length(slice_idx).\n *\n * \\return              A pointer to the given slot.\n */\nstatic inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx);\n\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n\n#if defined(MBEDTLS_TEST_HOOKS)\nsize_t (*mbedtls_test_hook_psa_volatile_key_slice_length)(size_t slice_idx) = NULL;\n#endif\n\nstatic inline size_t key_slice_length(size_t slice_idx)\n{\n    if (slice_idx == KEY_SLOT_CACHE_SLICE_INDEX) {\n        return PERSISTENT_KEY_CACHE_COUNT;\n    } else {\n#if defined(MBEDTLS_TEST_HOOKS)\n        if (mbedtls_test_hook_psa_volatile_key_slice_length != NULL) {\n            return mbedtls_test_hook_psa_volatile_key_slice_length(slice_idx);\n        }\n#endif\n        return KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH << slice_idx;\n    }\n}\n\nstatic inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id)\n{\n    size_t slice_idx = slice_index_of_volatile_key_id(key_id);\n    if (slice_idx >= KEY_SLOT_VOLATILE_SLICE_COUNT) {\n        return NULL;\n    }\n    size_t slot_idx = slot_index_of_volatile_key_id(key_id);\n    if (slot_idx >= key_slice_length(slice_idx)) {\n        return NULL;\n    }\n    psa_key_slot_t *slice = global_data.key_slices[slice_idx];\n    if (slice == NULL) {\n        return NULL;\n    }\n    return &slice[slot_idx];\n}\n\nstatic inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx)\n{\n    return &global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX][slot_idx];\n}\n\nstatic inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx)\n{\n    return &global_data.key_slices[slice_idx][slot_idx];\n}\n\n#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n\nstatic inline size_t key_slice_length(size_t slice_idx)\n{\n    (void) slice_idx;\n    return ARRAY_LENGTH(global_data.key_slots);\n}\n\nstatic inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id)\n{\n    MBEDTLS_STATIC_ASSERT(ARRAY_LENGTH(global_data.key_slots) <=\n                          PSA_KEY_ID_VOLATILE_MAX - PSA_KEY_ID_VOLATILE_MIN + 1,\n                          \"The key slot array is larger than the volatile key ID range\");\n    return &global_data.key_slots[key_id - PSA_KEY_ID_VOLATILE_MIN];\n}\n\nstatic inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx)\n{\n    return &global_data.key_slots[slot_idx];\n}\n\nstatic inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx)\n{\n    (void) slice_idx;\n    return &global_data.key_slots[slot_idx];\n}\n\n#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n\n\n\nint psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok)\n{\n    psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);\n\n    if ((PSA_KEY_ID_USER_MIN <= key_id) &&\n        (key_id <= PSA_KEY_ID_USER_MAX)) {\n        return 1;\n    }\n\n    if (vendor_ok &&\n        (PSA_KEY_ID_VENDOR_MIN <= key_id) &&\n        (key_id <= PSA_KEY_ID_VENDOR_MAX)) {\n        return 1;\n    }\n\n    return 0;\n}\n\n/** Get the description in memory of a key given its identifier and lock it.\n *\n * The descriptions of volatile keys and loaded persistent keys are\n * stored in key slots. This function returns a pointer to the key slot\n * containing the description of a key given its identifier.\n *\n * The function searches the key slots containing the description of the key\n * with \\p key identifier. The function does only read accesses to the key\n * slots. The function does not load any persistent key thus does not access\n * any storage.\n *\n * For volatile key identifiers, only one key slot is queried as a volatile\n * key with identifier key_id can only be stored in slot of index\n * ( key_id - #PSA_KEY_ID_VOLATILE_MIN ).\n *\n * On success, the function locks the key slot. It is the responsibility of\n * the caller to unlock the key slot when it does not access it anymore.\n *\n * If multi-threading is enabled, the caller must hold the\n * global key slot mutex.\n *\n * \\param key           Key identifier to query.\n * \\param[out] p_slot   On success, `*p_slot` contains a pointer to the\n *                      key slot containing the description of the key\n *                      identified by \\p key.\n *\n * \\retval #PSA_SUCCESS\n *         The pointer to the key slot containing the description of the key\n *         identified by \\p key was returned.\n * \\retval #PSA_ERROR_INVALID_HANDLE\n *         \\p key is not a valid key identifier.\n * \\retval #PSA_ERROR_DOES_NOT_EXIST\n *         There is no key with key identifier \\p key in the key slots.\n */\nstatic psa_status_t psa_get_and_lock_key_slot_in_memory(\n    mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);\n    size_t slot_idx;\n    psa_key_slot_t *slot = NULL;\n\n    if (psa_key_id_is_volatile(key_id)) {\n        slot = get_volatile_key_slot(key_id);\n\n        /* Check if both the PSA key identifier key_id and the owner\n         * identifier of key match those of the key slot. */\n        if (slot != NULL &&\n            slot->state == PSA_SLOT_FULL &&\n            mbedtls_svc_key_id_equal(key, slot->attr.id)) {\n            status = PSA_SUCCESS;\n        } else {\n            status = PSA_ERROR_DOES_NOT_EXIST;\n        }\n    } else {\n        if (!psa_is_valid_key_id(key, 1)) {\n            return PSA_ERROR_INVALID_HANDLE;\n        }\n\n        for (slot_idx = 0; slot_idx < PERSISTENT_KEY_CACHE_COUNT; slot_idx++) {\n            slot = get_persistent_key_slot(slot_idx);\n            /* Only consider slots which are in a full state. */\n            if ((slot->state == PSA_SLOT_FULL) &&\n                (mbedtls_svc_key_id_equal(key, slot->attr.id))) {\n                break;\n            }\n        }\n        status = (slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT) ?\n                 PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST;\n    }\n\n    if (status == PSA_SUCCESS) {\n        status = psa_register_read(slot);\n        if (status == PSA_SUCCESS) {\n            *p_slot = slot;\n        }\n    }\n\n    return status;\n}\n\npsa_status_t psa_initialize_key_slots(void)\n{\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n    global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX] =\n        mbedtls_calloc(PERSISTENT_KEY_CACHE_COUNT,\n                       sizeof(*global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX]));\n    if (global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX] == NULL) {\n        return PSA_ERROR_INSUFFICIENT_MEMORY;\n    }\n#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n    /* Nothing to do: program startup and psa_wipe_all_key_slots() both\n     * guarantee that the key slots are initialized to all-zero, which\n     * means that all the key slots are in a valid, empty state. The global\n     * data mutex is already held when calling this function, so no need to\n     * lock it here, to set the flag. */\n#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n\n    global_data.key_slots_initialized = 1;\n    return PSA_SUCCESS;\n}\n\nvoid psa_wipe_all_key_slots(void)\n{\n    for (size_t slice_idx = 0; slice_idx < KEY_SLICE_COUNT; slice_idx++) {\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n        if (global_data.key_slices[slice_idx] == NULL) {\n            continue;\n        }\n#endif  /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n        for (size_t slot_idx = 0; slot_idx < key_slice_length(slice_idx); slot_idx++) {\n            psa_key_slot_t *slot = get_key_slot(slice_idx, slot_idx);\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n            /* When MBEDTLS_PSA_KEY_STORE_DYNAMIC is disabled, calling\n             * psa_wipe_key_slot() on an unused slot is useless, but it\n             * happens to work (because we flip the state to PENDING_DELETION).\n             *\n             * When MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled,\n             * psa_wipe_key_slot() needs to have a valid slice_index\n             * field, but that value might not be correct in a\n             * free slot, so we must not call it.\n             *\n             * Bypass the call to psa_wipe_key_slot() if the slot is empty,\n             * but only if MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled, to save\n             * a few bytes of code size otherwise.\n             */\n            if (slot->state == PSA_SLOT_EMPTY) {\n                continue;\n            }\n#endif\n            slot->var.occupied.registered_readers = 1;\n            slot->state = PSA_SLOT_PENDING_DELETION;\n            (void) psa_wipe_key_slot(slot);\n        }\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n        mbedtls_free(global_data.key_slices[slice_idx]);\n        global_data.key_slices[slice_idx] = NULL;\n#endif  /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n    }\n\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n    for (size_t slice_idx = 0; slice_idx < KEY_SLOT_VOLATILE_SLICE_COUNT; slice_idx++) {\n        global_data.first_free_slot_index[slice_idx] = 0;\n    }\n#endif  /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n\n    /* The global data mutex is already held when calling this function. */\n    global_data.key_slots_initialized = 0;\n}\n\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n\nstatic psa_status_t psa_allocate_volatile_key_slot(psa_key_id_t *key_id,\n                                                   psa_key_slot_t **p_slot)\n{\n    size_t slice_idx;\n    for (slice_idx = 0; slice_idx < KEY_SLOT_VOLATILE_SLICE_COUNT; slice_idx++) {\n        if (global_data.first_free_slot_index[slice_idx] != FREE_SLOT_INDEX_NONE) {\n            break;\n        }\n    }\n    if (slice_idx == KEY_SLOT_VOLATILE_SLICE_COUNT) {\n        return PSA_ERROR_INSUFFICIENT_MEMORY;\n    }\n\n    if (global_data.key_slices[slice_idx] == NULL) {\n        global_data.key_slices[slice_idx] =\n            mbedtls_calloc(key_slice_length(slice_idx),\n                           sizeof(psa_key_slot_t));\n        if (global_data.key_slices[slice_idx] == NULL) {\n            return PSA_ERROR_INSUFFICIENT_MEMORY;\n        }\n    }\n    psa_key_slot_t *slice = global_data.key_slices[slice_idx];\n\n    size_t slot_idx = global_data.first_free_slot_index[slice_idx];\n    *key_id = volatile_key_id_of_index(slice_idx, slot_idx);\n\n    psa_key_slot_t *slot = &slice[slot_idx];\n    size_t next_free = slot_idx + 1 + slot->var.free.next_free_relative_to_next;\n    if (next_free >= key_slice_length(slice_idx)) {\n        next_free = FREE_SLOT_INDEX_NONE;\n    }\n    global_data.first_free_slot_index[slice_idx] = next_free;\n    /* The .next_free field is not meaningful when the slot is not free,\n     * so give it the same content as freshly initialized memory. */\n    slot->var.free.next_free_relative_to_next = 0;\n\n    psa_status_t status = psa_key_slot_state_transition(slot,\n                                                        PSA_SLOT_EMPTY,\n                                                        PSA_SLOT_FILLING);\n    if (status != PSA_SUCCESS) {\n        /* The only reason for failure is if the slot state was not empty.\n         * This indicates that something has gone horribly wrong.\n         * In this case, we leave the slot out of the free list, and stop\n         * modifying it. This minimizes any further corruption. The slot\n         * is a memory leak, but that's a lesser evil. */\n        return status;\n    }\n\n    *p_slot = slot;\n    /* We assert at compile time that the slice index fits in uint8_t. */\n    slot->slice_index = (uint8_t) slice_idx;\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_free_key_slot(size_t slice_idx,\n                               psa_key_slot_t *slot)\n{\n\n    if (slice_idx == KEY_SLOT_CACHE_SLICE_INDEX) {\n        /* This is a cache entry. We don't maintain a free list, so\n         * there's nothing to do. */\n        return PSA_SUCCESS;\n    }\n    if (slice_idx >= KEY_SLOT_VOLATILE_SLICE_COUNT) {\n        return PSA_ERROR_CORRUPTION_DETECTED;\n    }\n\n    psa_key_slot_t *slice = global_data.key_slices[slice_idx];\n    psa_key_slot_t *slice_end = slice + key_slice_length(slice_idx);\n    if (slot < slice || slot >= slice_end) {\n        /* The slot isn't actually in the slice! We can't detect that\n         * condition for sure, because the pointer comparison itself is\n         * undefined behavior in that case. That same condition makes the\n         * subtraction to calculate the slot index also UB.\n         * Give up now to avoid causing further corruption.\n         */\n        return PSA_ERROR_CORRUPTION_DETECTED;\n    }\n    size_t slot_idx = slot - slice;\n\n    size_t next_free = global_data.first_free_slot_index[slice_idx];\n    if (next_free >= key_slice_length(slice_idx)) {\n        /* The slot was full. The newly freed slot thus becomes the\n         * end of the free list. */\n        next_free = key_slice_length(slice_idx);\n    }\n    global_data.first_free_slot_index[slice_idx] = slot_idx;\n    slot->var.free.next_free_relative_to_next =\n        (int32_t) next_free - (int32_t) slot_idx - 1;\n\n    return PSA_SUCCESS;\n}\n#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n\npsa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id,\n                                       psa_key_slot_t **p_slot)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t slot_idx;\n    psa_key_slot_t *selected_slot, *unused_persistent_key_slot;\n\n    if (!psa_get_key_slots_initialized()) {\n        status = PSA_ERROR_BAD_STATE;\n        goto error;\n    }\n\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n    if (volatile_key_id != NULL) {\n        return psa_allocate_volatile_key_slot(volatile_key_id, p_slot);\n    }\n#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n\n    /* With a dynamic key store, allocate an entry in the cache slice,\n     * applicable only to non-volatile keys that get cached in RAM.\n     * With a static key store, allocate an entry in the sole slice,\n     * applicable to all keys. */\n    selected_slot = unused_persistent_key_slot = NULL;\n    for (slot_idx = 0; slot_idx < PERSISTENT_KEY_CACHE_COUNT; slot_idx++) {\n        psa_key_slot_t *slot = get_key_slot(KEY_SLOT_CACHE_SLICE_INDEX, slot_idx);\n        if (slot->state == PSA_SLOT_EMPTY) {\n            selected_slot = slot;\n            break;\n        }\n\n        if ((unused_persistent_key_slot == NULL) &&\n            (slot->state == PSA_SLOT_FULL) &&\n            (!psa_key_slot_has_readers(slot)) &&\n            (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime))) {\n            unused_persistent_key_slot = slot;\n        }\n    }\n\n    /*\n     * If there is no unused key slot and there is at least one unlocked key\n     * slot containing the description of a persistent key, recycle the first\n     * such key slot we encountered. If we later need to operate on the\n     * persistent key we are evicting now, we will reload its description from\n     * storage.\n     */\n    if ((selected_slot == NULL) &&\n        (unused_persistent_key_slot != NULL)) {\n        selected_slot = unused_persistent_key_slot;\n        psa_register_read(selected_slot);\n        status = psa_wipe_key_slot(selected_slot);\n        if (status != PSA_SUCCESS) {\n            goto error;\n        }\n    }\n\n    if (selected_slot != NULL) {\n        status = psa_key_slot_state_transition(selected_slot, PSA_SLOT_EMPTY,\n                                               PSA_SLOT_FILLING);\n        if (status != PSA_SUCCESS) {\n            goto error;\n        }\n\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n        selected_slot->slice_index = KEY_SLOT_CACHE_SLICE_INDEX;\n#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n\n#if !defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n        if (volatile_key_id != NULL) {\n            /* Refresh slot_idx, for when the slot is not the original\n             * selected_slot but rather unused_persistent_key_slot.  */\n            slot_idx = selected_slot - global_data.key_slots;\n            *volatile_key_id = PSA_KEY_ID_VOLATILE_MIN + (psa_key_id_t) slot_idx;\n        }\n#endif\n        *p_slot = selected_slot;\n\n        return PSA_SUCCESS;\n    }\n    status = PSA_ERROR_INSUFFICIENT_MEMORY;\n\nerror:\n    *p_slot = NULL;\n\n    return status;\n}\n\n#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)\nstatic psa_status_t psa_load_persistent_key_into_slot(psa_key_slot_t *slot)\n{\n    psa_status_t status = PSA_SUCCESS;\n    uint8_t *key_data = NULL;\n    size_t key_data_length = 0;\n\n    status = psa_load_persistent_key(&slot->attr,\n                                     &key_data, &key_data_length);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    /* Special handling is required for loading keys associated with a\n     * dynamically registered SE interface. */\n    const psa_drv_se_t *drv;\n    psa_drv_se_context_t *drv_context;\n    if (psa_get_se_driver(slot->attr.lifetime, &drv, &drv_context)) {\n        psa_se_key_data_storage_t *data;\n\n        if (key_data_length != sizeof(*data)) {\n            status = PSA_ERROR_DATA_INVALID;\n            goto exit;\n        }\n        data = (psa_se_key_data_storage_t *) key_data;\n        status = psa_copy_key_material_into_slot(\n            slot, data->slot_number, sizeof(data->slot_number));\n        goto exit;\n    }\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n    status = psa_copy_key_material_into_slot(slot, key_data, key_data_length);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\nexit:\n    psa_free_persistent_key_data(key_data, key_data_length);\n    return status;\n}\n#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */\n\n#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)\n\nstatic psa_status_t psa_load_builtin_key_into_slot(psa_key_slot_t *slot)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_VOLATILE;\n    psa_drv_slot_number_t slot_number = 0;\n    size_t key_buffer_size = 0;\n    size_t key_buffer_length = 0;\n\n    if (!psa_key_id_is_builtin(\n            MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id))) {\n        return PSA_ERROR_DOES_NOT_EXIST;\n    }\n\n    /* Check the platform function to see whether this key actually exists */\n    status = mbedtls_psa_platform_get_builtin_key(\n        slot->attr.id, &lifetime, &slot_number);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    /* Set required key attributes to ensure get_builtin_key can retrieve the\n     * full attributes. */\n    psa_set_key_id(&attributes, slot->attr.id);\n    psa_set_key_lifetime(&attributes, lifetime);\n\n    /* Get the full key attributes from the driver in order to be able to\n     * calculate the required buffer size. */\n    status = psa_driver_wrapper_get_builtin_key(\n        slot_number, &attributes,\n        NULL, 0, NULL);\n    if (status != PSA_ERROR_BUFFER_TOO_SMALL) {\n        /* Builtin keys cannot be defined by the attributes alone */\n        if (status == PSA_SUCCESS) {\n            status = PSA_ERROR_CORRUPTION_DETECTED;\n        }\n        return status;\n    }\n\n    /* If the key should exist according to the platform, then ask the driver\n     * what its expected size is. */\n    status = psa_driver_wrapper_get_key_buffer_size(&attributes,\n                                                    &key_buffer_size);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    /* Allocate a buffer of the required size and load the builtin key directly\n     * into the (now properly sized) slot buffer. */\n    status = psa_allocate_buffer_to_slot(slot, key_buffer_size);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    status = psa_driver_wrapper_get_builtin_key(\n        slot_number, &attributes,\n        slot->key.data, slot->key.bytes, &key_buffer_length);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    /* Copy actual key length and core attributes into the slot on success */\n    slot->key.bytes = key_buffer_length;\n    slot->attr = attributes;\nexit:\n    if (status != PSA_SUCCESS) {\n        psa_remove_key_data_from_memory(slot);\n    }\n    return status;\n}\n#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */\n\npsa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key,\n                                       psa_key_slot_t **p_slot)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    *p_slot = NULL;\n    if (!psa_get_key_slots_initialized()) {\n        return PSA_ERROR_BAD_STATE;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    /* We need to set status as success, otherwise CORRUPTION_DETECTED\n     * would be returned if the lock fails. */\n    status = PSA_SUCCESS;\n    /* If the key is persistent and not loaded, we cannot unlock the mutex\n     * between checking if the key is loaded and setting the slot as FULL,\n     * as otherwise another thread may load and then destroy the key\n     * in the meantime. */\n    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(\n                              &mbedtls_threading_key_slot_mutex));\n#endif\n    /*\n     * On success, the pointer to the slot is passed directly to the caller\n     * thus no need to unlock the key slot here.\n     */\n    status = psa_get_and_lock_key_slot_in_memory(key, p_slot);\n    if (status != PSA_ERROR_DOES_NOT_EXIST) {\n#if defined(MBEDTLS_THREADING_C)\n        PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(\n                                  &mbedtls_threading_key_slot_mutex));\n#endif\n        return status;\n    }\n\n    /* Loading keys from storage requires support for such a mechanism */\n#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \\\n    defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)\n\n    status = psa_reserve_free_key_slot(NULL, p_slot);\n    if (status != PSA_SUCCESS) {\n#if defined(MBEDTLS_THREADING_C)\n        PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(\n                                  &mbedtls_threading_key_slot_mutex));\n#endif\n        return status;\n    }\n\n    (*p_slot)->attr.id = key;\n    (*p_slot)->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT;\n\n    status = PSA_ERROR_DOES_NOT_EXIST;\n#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)\n    /* Load keys in the 'builtin' range through their own interface */\n    status = psa_load_builtin_key_into_slot(*p_slot);\n#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */\n\n#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)\n    if (status == PSA_ERROR_DOES_NOT_EXIST) {\n        status = psa_load_persistent_key_into_slot(*p_slot);\n    }\n#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */\n\n    if (status != PSA_SUCCESS) {\n        psa_wipe_key_slot(*p_slot);\n\n        /* If the key does not exist, we need to return\n         * PSA_ERROR_INVALID_HANDLE. */\n        if (status == PSA_ERROR_DOES_NOT_EXIST) {\n            status = PSA_ERROR_INVALID_HANDLE;\n        }\n    } else {\n        /* Add implicit usage flags. */\n        psa_extend_key_usage_flags(&(*p_slot)->attr.policy.usage);\n\n        psa_key_slot_state_transition((*p_slot), PSA_SLOT_FILLING,\n                                      PSA_SLOT_FULL);\n        status = psa_register_read(*p_slot);\n    }\n\n#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */\n    status = PSA_ERROR_INVALID_HANDLE;\n#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */\n\n    if (status != PSA_SUCCESS) {\n        *p_slot = NULL;\n    }\n#if defined(MBEDTLS_THREADING_C)\n    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(\n                              &mbedtls_threading_key_slot_mutex));\n#endif\n    return status;\n}\n\npsa_status_t psa_unregister_read(psa_key_slot_t *slot)\n{\n    if (slot == NULL) {\n        return PSA_SUCCESS;\n    }\n    if ((slot->state != PSA_SLOT_FULL) &&\n        (slot->state != PSA_SLOT_PENDING_DELETION)) {\n        return PSA_ERROR_CORRUPTION_DETECTED;\n    }\n\n    /* If we are the last reader and the slot is marked for deletion,\n     * we must wipe the slot here. */\n    if ((slot->state == PSA_SLOT_PENDING_DELETION) &&\n        (slot->var.occupied.registered_readers == 1)) {\n        return psa_wipe_key_slot(slot);\n    }\n\n    if (psa_key_slot_has_readers(slot)) {\n        slot->var.occupied.registered_readers--;\n        return PSA_SUCCESS;\n    }\n\n    /*\n     * As the return error code may not be handled in case of multiple errors,\n     * do our best to report if there are no registered readers. Assert with\n     * MBEDTLS_TEST_HOOK_TEST_ASSERT that there are registered readers:\n     * if the MBEDTLS_TEST_HOOKS configuration option is enabled and\n     * the function is called as part of the execution of a test suite, the\n     * execution of the test suite is stopped in error if the assertion fails.\n     */\n    MBEDTLS_TEST_HOOK_TEST_ASSERT(psa_key_slot_has_readers(slot));\n    return PSA_ERROR_CORRUPTION_DETECTED;\n}\n\npsa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n#if defined(MBEDTLS_THREADING_C)\n    /* We need to set status as success, otherwise CORRUPTION_DETECTED\n     * would be returned if the lock fails. */\n    status = PSA_SUCCESS;\n    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(\n                              &mbedtls_threading_key_slot_mutex));\n#endif\n    status = psa_unregister_read(slot);\n#if defined(MBEDTLS_THREADING_C)\n    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(\n                              &mbedtls_threading_key_slot_mutex));\n#endif\n    return status;\n}\n\npsa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime,\n                                       psa_se_drv_table_entry_t **p_drv)\n{\n    if (psa_key_lifetime_is_external(lifetime)) {\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n        /* Check whether a driver is registered against this lifetime */\n        psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime);\n        if (driver != NULL) {\n            if (p_drv != NULL) {\n                *p_drv = driver;\n            }\n            return PSA_SUCCESS;\n        }\n#else /* MBEDTLS_PSA_CRYPTO_SE_C */\n        (void) p_drv;\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n\n        /* Key location for external keys gets checked by the wrapper */\n        return PSA_SUCCESS;\n    } else {\n        /* Local/internal keys are always valid */\n        return PSA_SUCCESS;\n    }\n}\n\npsa_status_t psa_validate_key_persistence(psa_key_lifetime_t lifetime)\n{\n    if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) {\n        /* Volatile keys are always supported */\n        return PSA_SUCCESS;\n    } else {\n        /* Persistent keys require storage support */\n#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)\n        if (PSA_KEY_LIFETIME_IS_READ_ONLY(lifetime)) {\n            return PSA_ERROR_INVALID_ARGUMENT;\n        } else {\n            return PSA_SUCCESS;\n        }\n#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */\n        return PSA_ERROR_NOT_SUPPORTED;\n#endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */\n    }\n}\n\npsa_status_t psa_open_key(mbedtls_svc_key_id_t key, psa_key_handle_t *handle)\n{\n#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \\\n    defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)\n    psa_status_t status;\n    psa_key_slot_t *slot;\n\n    status = psa_get_and_lock_key_slot(key, &slot);\n    if (status != PSA_SUCCESS) {\n        *handle = PSA_KEY_HANDLE_INIT;\n        if (status == PSA_ERROR_INVALID_HANDLE) {\n            status = PSA_ERROR_DOES_NOT_EXIST;\n        }\n\n        return status;\n    }\n\n    *handle = key;\n\n    return psa_unregister_read_under_mutex(slot);\n\n#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */\n    (void) key;\n    *handle = PSA_KEY_HANDLE_INIT;\n    return PSA_ERROR_NOT_SUPPORTED;\n#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */\n}\n\npsa_status_t psa_close_key(psa_key_handle_t handle)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n\n    if (psa_key_handle_is_null(handle)) {\n        return PSA_SUCCESS;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    /* We need to set status as success, otherwise CORRUPTION_DETECTED\n     * would be returned if the lock fails. */\n    status = PSA_SUCCESS;\n    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(\n                              &mbedtls_threading_key_slot_mutex));\n#endif\n    status = psa_get_and_lock_key_slot_in_memory(handle, &slot);\n    if (status != PSA_SUCCESS) {\n        if (status == PSA_ERROR_DOES_NOT_EXIST) {\n            status = PSA_ERROR_INVALID_HANDLE;\n        }\n#if defined(MBEDTLS_THREADING_C)\n        PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(\n                                  &mbedtls_threading_key_slot_mutex));\n#endif\n        return status;\n    }\n\n    if (slot->var.occupied.registered_readers == 1) {\n        status = psa_wipe_key_slot(slot);\n    } else {\n        status = psa_unregister_read(slot);\n    }\n#if defined(MBEDTLS_THREADING_C)\n    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(\n                              &mbedtls_threading_key_slot_mutex));\n#endif\n\n    return status;\n}\n\npsa_status_t psa_purge_key(mbedtls_svc_key_id_t key)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_slot_t *slot;\n\n#if defined(MBEDTLS_THREADING_C)\n    /* We need to set status as success, otherwise CORRUPTION_DETECTED\n     * would be returned if the lock fails. */\n    status = PSA_SUCCESS;\n    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(\n                              &mbedtls_threading_key_slot_mutex));\n#endif\n    status = psa_get_and_lock_key_slot_in_memory(key, &slot);\n    if (status != PSA_SUCCESS) {\n#if defined(MBEDTLS_THREADING_C)\n        PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(\n                                  &mbedtls_threading_key_slot_mutex));\n#endif\n        return status;\n    }\n\n    if ((!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) &&\n        (slot->var.occupied.registered_readers == 1)) {\n        status = psa_wipe_key_slot(slot);\n    } else {\n        status = psa_unregister_read(slot);\n    }\n#if defined(MBEDTLS_THREADING_C)\n    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(\n                              &mbedtls_threading_key_slot_mutex));\n#endif\n\n    return status;\n}\n\nvoid mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats)\n{\n    memset(stats, 0, sizeof(*stats));\n\n    for (size_t slice_idx = 0; slice_idx < KEY_SLICE_COUNT; slice_idx++) {\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n        if (global_data.key_slices[slice_idx] == NULL) {\n            continue;\n        }\n#endif  /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n        for (size_t slot_idx = 0; slot_idx < key_slice_length(slice_idx); slot_idx++) {\n            const psa_key_slot_t *slot = get_key_slot(slice_idx, slot_idx);\n            if (slot->state == PSA_SLOT_EMPTY) {\n                ++stats->empty_slots;\n                continue;\n            }\n            if (psa_key_slot_has_readers(slot)) {\n                ++stats->locked_slots;\n            }\n            if (PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {\n                ++stats->volatile_slots;\n            } else {\n                psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id);\n                ++stats->persistent_slots;\n                if (id > stats->max_open_internal_key_id) {\n                    stats->max_open_internal_key_id = id;\n                }\n            }\n            if (PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime) !=\n                PSA_KEY_LOCATION_LOCAL_STORAGE) {\n                psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id);\n                ++stats->external_slots;\n                if (id > stats->max_open_external_key_id) {\n                    stats->max_open_external_key_id = id;\n                }\n            }\n        }\n    }\n}\n\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_slot_management.h",
    "content": "/*\n *  PSA crypto layer on top of Mbed TLS crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_SLOT_MANAGEMENT_H\n#define PSA_CRYPTO_SLOT_MANAGEMENT_H\n\n#include \"psa/crypto.h\"\n#include \"psa_crypto_core.h\"\n#include \"psa_crypto_se.h\"\n\n/** Range of volatile key identifiers.\n *\n *  The first #MBEDTLS_PSA_KEY_SLOT_COUNT identifiers of the implementation\n *  range of key identifiers are reserved for volatile key identifiers.\n *\n *  If \\c id is a a volatile key identifier, #PSA_KEY_ID_VOLATILE_MIN - \\c id\n *  indicates the key slot containing the volatile key definition. See\n *  psa_crypto_slot_management.c for details.\n */\n\n/** The minimum value for a volatile key identifier.\n */\n#define PSA_KEY_ID_VOLATILE_MIN  PSA_KEY_ID_VENDOR_MIN\n\n/** The maximum value for a volatile key identifier.\n */\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n#define PSA_KEY_ID_VOLATILE_MAX (MBEDTLS_PSA_KEY_ID_BUILTIN_MIN - 1)\n#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n#define PSA_KEY_ID_VOLATILE_MAX                                 \\\n    (PSA_KEY_ID_VOLATILE_MIN + MBEDTLS_PSA_KEY_SLOT_COUNT - 1)\n#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n\n/** Test whether a key identifier is a volatile key identifier.\n *\n * \\param key_id  Key identifier to test.\n *\n * \\retval 1\n *         The key identifier is a volatile key identifier.\n * \\retval 0\n *         The key identifier is not a volatile key identifier.\n */\nstatic inline int psa_key_id_is_volatile(psa_key_id_t key_id)\n{\n    return (key_id >= PSA_KEY_ID_VOLATILE_MIN) &&\n           (key_id <= PSA_KEY_ID_VOLATILE_MAX);\n}\n\n/** Get the description of a key given its identifier and lock it.\n *\n * The descriptions of volatile keys and loaded persistent keys are stored in\n * key slots. This function returns a pointer to the key slot containing the\n * description of a key given its identifier.\n *\n * In case of a persistent key, the function loads the description of the key\n * into a key slot if not already done.\n *\n * On success, the returned key slot has been registered for reading.\n * It is the responsibility of the caller to call psa_unregister_read(slot)\n * when they have finished reading the contents of the slot.\n *\n * On failure, `*p_slot` is set to NULL. This ensures that it is always valid\n * to call psa_unregister_read on the returned slot.\n *\n * \\param key           Key identifier to query.\n * \\param[out] p_slot   On success, `*p_slot` contains a pointer to the\n *                      key slot containing the description of the key\n *                      identified by \\p key.\n *\n * \\retval #PSA_SUCCESS\n *         \\p *p_slot contains a pointer to the key slot containing the\n *         description of the key identified by \\p key.\n *         The key slot counter has been incremented.\n * \\retval #PSA_ERROR_BAD_STATE\n *         The library has not been initialized.\n * \\retval #PSA_ERROR_INVALID_HANDLE\n *         \\p key is not a valid key identifier.\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY\n *         \\p key is a persistent key identifier. The implementation does not\n *         have sufficient resources to load the persistent key. This can be\n *         due to a lack of empty key slot, or available memory.\n * \\retval #PSA_ERROR_DOES_NOT_EXIST\n *         There is no key with key identifier \\p key.\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n */\npsa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key,\n                                       psa_key_slot_t **p_slot);\n\n/** Initialize the key slot structures.\n *\n * \\retval #PSA_SUCCESS\n *         Currently this function always succeeds.\n */\npsa_status_t psa_initialize_key_slots(void);\n\n#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n/* Allow test code to customize the key slice length. We use this in tests\n * that exhaust the key store to reach a full key store in reasonable time\n * and memory.\n *\n * The length of each slice must be between 1 and\n * (1 << KEY_ID_SLOT_INDEX_WIDTH) inclusive.\n *\n * The length for a given slice index must not change while\n * the key store is initialized.\n */\nextern size_t (*mbedtls_test_hook_psa_volatile_key_slice_length)(\n    size_t slice_idx);\n\n/* The number of volatile key slices. */\nsize_t psa_key_slot_volatile_slice_count(void);\n#endif\n\n/** Delete all data from key slots in memory.\n * This function is not thread safe, it wipes every key slot regardless of\n * state and reader count. It should only be called when no slot is in use.\n *\n * This does not affect persistent storage. */\nvoid psa_wipe_all_key_slots(void);\n\n/** Find a free key slot and reserve it to be filled with a key.\n *\n * This function finds a key slot that is free,\n * sets its state to PSA_SLOT_FILLING and then returns the slot.\n *\n * On success, the key slot's state is PSA_SLOT_FILLING.\n * It is the responsibility of the caller to change the slot's state to\n * PSA_SLOT_EMPTY/FULL once key creation has finished.\n *\n * If multi-threading is enabled, the caller must hold the\n * global key slot mutex.\n *\n * \\param[out] volatile_key_id   - If null, reserve a cache slot for\n *                                 a persistent or built-in key.\n *                               - If non-null, allocate a slot for\n *                                 a volatile key. On success,\n *                                 \\p *volatile_key_id is the\n *                                 identifier corresponding to the\n *                                 returned slot. It is the caller's\n *                                 responsibility to set this key identifier\n *                                 in the attributes.\n * \\param[out] p_slot            On success, a pointer to the slot.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY\n *         There were no free key slots.\n *         When #MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled, there was not\n *         enough memory to allocate more slots.\n * \\retval #PSA_ERROR_BAD_STATE \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED\n *         This function attempted to operate on a key slot which was in an\n *         unexpected state.\n */\npsa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id,\n                                       psa_key_slot_t **p_slot);\n\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n/** Return a key slot to the free list.\n *\n * Call this function when a slot obtained from psa_reserve_free_key_slot()\n * is no longer in use.\n *\n * If multi-threading is enabled, the caller must hold the\n * global key slot mutex.\n *\n * \\param slice_idx             The slice containing the slot.\n *                              This is `slot->slice_index` when the slot\n *                              is obtained from psa_reserve_free_key_slot().\n * \\param slot                  The key slot.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED\n *         This function attempted to operate on a key slot which was in an\n *         unexpected state.\n */\npsa_status_t psa_free_key_slot(size_t slice_idx,\n                               psa_key_slot_t *slot);\n#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n\n/** Change the state of a key slot.\n *\n * This function changes the state of the key slot from expected_state to\n * new state. If the state of the slot was not expected_state, the state is\n * unchanged.\n *\n * If multi-threading is enabled, the caller must hold the\n * global key slot mutex.\n *\n * \\param[in] slot            The key slot.\n * \\param[in] expected_state  The current state of the slot.\n * \\param[in] new_state       The new state of the slot.\n *\n * \\retval #PSA_SUCCESS\n               The key slot's state variable is new_state.\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED\n *             The slot's state was not expected_state.\n */\nstatic inline psa_status_t psa_key_slot_state_transition(\n    psa_key_slot_t *slot, psa_key_slot_state_t expected_state,\n    psa_key_slot_state_t new_state)\n{\n    if (slot->state != expected_state) {\n        return PSA_ERROR_CORRUPTION_DETECTED;\n    }\n    slot->state = new_state;\n    return PSA_SUCCESS;\n}\n\n/** Register as a reader of a key slot.\n *\n * This function increments the key slot registered reader counter by one.\n * If multi-threading is enabled, the caller must hold the\n * global key slot mutex.\n *\n * \\param[in] slot  The key slot.\n *\n * \\retval #PSA_SUCCESS\n               The key slot registered reader counter was incremented.\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED\n *             The reader counter already reached its maximum value and was not\n *             increased, or the slot's state was not PSA_SLOT_FULL.\n */\nstatic inline psa_status_t psa_register_read(psa_key_slot_t *slot)\n{\n    if ((slot->state != PSA_SLOT_FULL) ||\n        (slot->var.occupied.registered_readers >= SIZE_MAX)) {\n        return PSA_ERROR_CORRUPTION_DETECTED;\n    }\n    slot->var.occupied.registered_readers++;\n\n    return PSA_SUCCESS;\n}\n\n/** Unregister from reading a key slot.\n *\n * This function decrements the key slot registered reader counter by one.\n * If the state of the slot is PSA_SLOT_PENDING_DELETION,\n * and there is only one registered reader (the caller),\n * this function will call psa_wipe_key_slot().\n * If multi-threading is enabled, the caller must hold the\n * global key slot mutex.\n *\n * \\note To ease the handling of errors in retrieving a key slot\n *       a NULL input pointer is valid, and the function returns\n *       successfully without doing anything in that case.\n *\n * \\param[in] slot  The key slot.\n * \\retval #PSA_SUCCESS\n *             \\p slot is NULL or the key slot reader counter has been\n *             decremented (and potentially wiped) successfully.\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED\n *             The slot's state was neither PSA_SLOT_FULL nor\n *             PSA_SLOT_PENDING_DELETION.\n *             Or a wipe was attempted and the slot's state was not\n *             PSA_SLOT_PENDING_DELETION.\n *             Or registered_readers was equal to 0.\n */\npsa_status_t psa_unregister_read(psa_key_slot_t *slot);\n\n/** Wrap a call to psa_unregister_read in the global key slot mutex.\n *\n * If threading is disabled, this simply calls psa_unregister_read.\n *\n * \\note To ease the handling of errors in retrieving a key slot\n *       a NULL input pointer is valid, and the function returns\n *       successfully without doing anything in that case.\n *\n * \\param[in] slot  The key slot.\n * \\retval #PSA_SUCCESS\n *             \\p slot is NULL or the key slot reader counter has been\n *             decremented (and potentially wiped) successfully.\n * \\retval #PSA_ERROR_CORRUPTION_DETECTED\n *             The slot's state was neither PSA_SLOT_FULL nor\n *             PSA_SLOT_PENDING_DELETION.\n *             Or a wipe was attempted and the slot's state was not\n *             PSA_SLOT_PENDING_DELETION.\n *             Or registered_readers was equal to 0.\n */\npsa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot);\n\n/** Test whether a lifetime designates a key in an external cryptoprocessor.\n *\n * \\param lifetime      The lifetime to test.\n *\n * \\retval 1\n *         The lifetime designates an external key. There should be a\n *         registered driver for this lifetime, otherwise the key cannot\n *         be created or manipulated.\n * \\retval 0\n *         The lifetime designates a key that is volatile or in internal\n *         storage.\n */\nstatic inline int psa_key_lifetime_is_external(psa_key_lifetime_t lifetime)\n{\n    return PSA_KEY_LIFETIME_GET_LOCATION(lifetime)\n           != PSA_KEY_LOCATION_LOCAL_STORAGE;\n}\n\n/** Validate a key's location.\n *\n * This function checks whether the key's attributes point to a location that\n * is known to the PSA Core, and returns the driver function table if the key\n * is to be found in an external location.\n *\n * \\param[in] lifetime      The key lifetime attribute.\n * \\param[out] p_drv        On success, when a key is located in external\n *                          storage, returns a pointer to the driver table\n *                          associated with the key's storage location.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n */\npsa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime,\n                                       psa_se_drv_table_entry_t **p_drv);\n\n/** Validate the persistence of a key.\n *\n * \\param[in] lifetime  The key lifetime attribute.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_NOT_SUPPORTED The key is persistent but persistent keys\n *             are not supported.\n */\npsa_status_t psa_validate_key_persistence(psa_key_lifetime_t lifetime);\n\n/** Validate a key identifier.\n *\n * \\param[in] key           The key identifier.\n * \\param[in] vendor_ok     Non-zero to indicate that key identifiers in the\n *                          vendor range are allowed, volatile key identifiers\n *                          excepted \\c 0 otherwise.\n *\n * \\retval <> 0 if the key identifier is valid, 0 otherwise.\n */\nint psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok);\n\n#endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_storage.c",
    "content": "/*\n *  PSA persistent key storage\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)\n\n#include <stdlib.h>\n#include <string.h>\n\n#include \"psa/crypto.h\"\n#include \"psa_crypto_storage.h\"\n#include \"mbedtls/platform_util.h\"\n\n#if defined(MBEDTLS_PSA_ITS_FILE_C)\n#include \"psa_crypto_its.h\"\n#else /* Native ITS implementation */\n#include \"psa/error.h\"\n#include \"psa/internal_trusted_storage.h\"\n#endif\n\n#include \"mbedtls/platform.h\"\n\n\n\n/****************************************************************/\n/* Key storage */\n/****************************************************************/\n\n/* Determine a file name (ITS file identifier) for the given key identifier.\n * The file name must be distinct from any file that is used for a purpose\n * other than storing a key. Currently, the only such file is the random seed\n * file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID and whose value is\n * 0xFFFFFF52. */\nstatic psa_storage_uid_t psa_its_identifier_of_slot(mbedtls_svc_key_id_t key)\n{\n#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)\n    /* Encode the owner in the upper 32 bits. This means that if\n     * owner values are nonzero (as they are on a PSA platform),\n     * no key file will ever have a value less than 0x100000000, so\n     * the whole range 0..0xffffffff is available for non-key files. */\n    uint32_t unsigned_owner_id = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(key);\n    return ((uint64_t) unsigned_owner_id << 32) |\n           MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);\n#else\n    /* Use the key id directly as a file name.\n     * psa_is_key_id_valid() in psa_crypto_slot_management.c\n     * is responsible for ensuring that key identifiers do not have a\n     * value that is reserved for non-key files. */\n    return key;\n#endif\n}\n\n/**\n * \\brief Load persistent data for the given key slot number.\n *\n * This function reads data from a storage backend and returns the data in a\n * buffer.\n *\n * \\param key               Persistent identifier of the key to be loaded. This\n *                          should be an occupied storage location.\n * \\param[out] data         Buffer where the data is to be written.\n * \\param data_size         Size of the \\c data buffer in bytes.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DOES_NOT_EXIST \\emptydescription\n */\nstatic psa_status_t psa_crypto_storage_load(\n    const mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size)\n{\n    psa_status_t status;\n    psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key);\n    struct psa_storage_info_t data_identifier_info;\n    size_t data_length = 0;\n\n    status = psa_its_get_info(data_identifier, &data_identifier_info);\n    if (status  != PSA_SUCCESS) {\n        return status;\n    }\n\n    status = psa_its_get(data_identifier, 0, (uint32_t) data_size, data, &data_length);\n    if (data_size  != data_length) {\n        return PSA_ERROR_DATA_INVALID;\n    }\n\n    return status;\n}\n\nint psa_is_key_present_in_storage(const mbedtls_svc_key_id_t key)\n{\n    psa_status_t ret;\n    psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key);\n    struct psa_storage_info_t data_identifier_info;\n\n    ret = psa_its_get_info(data_identifier, &data_identifier_info);\n\n    if (ret == PSA_ERROR_DOES_NOT_EXIST) {\n        return 0;\n    }\n    return 1;\n}\n\n/**\n * \\brief Store persistent data for the given key slot number.\n *\n * This function stores the given data buffer to a persistent storage.\n *\n * \\param key           Persistent identifier of the key to be stored. This\n *                      should be an unoccupied storage location.\n * \\param[in] data      Buffer containing the data to be stored.\n * \\param data_length   The number of bytes\n *                      that make up the data.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n * \\retval #PSA_ERROR_ALREADY_EXISTS \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n */\nstatic psa_status_t psa_crypto_storage_store(const mbedtls_svc_key_id_t key,\n                                             const uint8_t *data,\n                                             size_t data_length)\n{\n    psa_status_t status;\n    psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key);\n    struct psa_storage_info_t data_identifier_info;\n\n    if (psa_is_key_present_in_storage(key) == 1) {\n        return PSA_ERROR_ALREADY_EXISTS;\n    }\n\n    status = psa_its_set(data_identifier, (uint32_t) data_length, data, 0);\n    if (status != PSA_SUCCESS) {\n        return PSA_ERROR_DATA_INVALID;\n    }\n\n    status = psa_its_get_info(data_identifier, &data_identifier_info);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    if (data_identifier_info.size != data_length) {\n        status = PSA_ERROR_DATA_INVALID;\n        goto exit;\n    }\n\nexit:\n    if (status != PSA_SUCCESS) {\n        /* Remove the file in case we managed to create it but something\n         * went wrong. It's ok if the file doesn't exist. If the file exists\n         * but the removal fails, we're already reporting an error so there's\n         * nothing else we can do. */\n        (void) psa_its_remove(data_identifier);\n    }\n    return status;\n}\n\npsa_status_t psa_destroy_persistent_key(const mbedtls_svc_key_id_t key)\n{\n    psa_status_t ret;\n    psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key);\n    struct psa_storage_info_t data_identifier_info;\n\n    ret = psa_its_get_info(data_identifier, &data_identifier_info);\n    if (ret == PSA_ERROR_DOES_NOT_EXIST) {\n        return PSA_SUCCESS;\n    }\n\n    if (psa_its_remove(data_identifier) != PSA_SUCCESS) {\n        return PSA_ERROR_DATA_INVALID;\n    }\n\n    ret = psa_its_get_info(data_identifier, &data_identifier_info);\n    if (ret != PSA_ERROR_DOES_NOT_EXIST) {\n        return PSA_ERROR_DATA_INVALID;\n    }\n\n    return PSA_SUCCESS;\n}\n\n/**\n * \\brief Get data length for given key slot number.\n *\n * \\param key               Persistent identifier whose stored data length\n *                          is to be obtained.\n * \\param[out] data_length  The number of bytes that make up the data.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DOES_NOT_EXIST \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n */\nstatic psa_status_t psa_crypto_storage_get_data_length(\n    const mbedtls_svc_key_id_t key,\n    size_t *data_length)\n{\n    psa_status_t status;\n    psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key);\n    struct psa_storage_info_t data_identifier_info;\n\n    status = psa_its_get_info(data_identifier, &data_identifier_info);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    *data_length = (size_t) data_identifier_info.size;\n\n    return PSA_SUCCESS;\n}\n\n/**\n * Persistent key storage magic header.\n */\n#define PSA_KEY_STORAGE_MAGIC_HEADER \"PSA\\0KEY\"\n#define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH (sizeof(PSA_KEY_STORAGE_MAGIC_HEADER))\n\ntypedef struct {\n    uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH];\n    uint8_t version[4];\n    uint8_t lifetime[sizeof(psa_key_lifetime_t)];\n    uint8_t type[2];\n    uint8_t bits[2];\n    uint8_t policy[sizeof(psa_key_policy_t)];\n    uint8_t data_len[4];\n    uint8_t key_data[];\n} psa_persistent_key_storage_format;\n\nvoid psa_format_key_data_for_storage(const uint8_t *data,\n                                     const size_t data_length,\n                                     const psa_key_attributes_t *attr,\n                                     uint8_t *storage_data)\n{\n    psa_persistent_key_storage_format *storage_format =\n        (psa_persistent_key_storage_format *) storage_data;\n\n    memcpy(storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER,\n           PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH);\n    MBEDTLS_PUT_UINT32_LE(0, storage_format->version, 0);\n    MBEDTLS_PUT_UINT32_LE(attr->lifetime, storage_format->lifetime, 0);\n    MBEDTLS_PUT_UINT16_LE((uint16_t) attr->type, storage_format->type, 0);\n    MBEDTLS_PUT_UINT16_LE((uint16_t) attr->bits, storage_format->bits, 0);\n    MBEDTLS_PUT_UINT32_LE(attr->policy.usage, storage_format->policy, 0);\n    MBEDTLS_PUT_UINT32_LE(attr->policy.alg, storage_format->policy, sizeof(uint32_t));\n    MBEDTLS_PUT_UINT32_LE(attr->policy.alg2, storage_format->policy, 2 * sizeof(uint32_t));\n    MBEDTLS_PUT_UINT32_LE(data_length, storage_format->data_len, 0);\n    memcpy(storage_format->key_data, data, data_length);\n}\n\nstatic psa_status_t check_magic_header(const uint8_t *data)\n{\n    if (memcmp(data, PSA_KEY_STORAGE_MAGIC_HEADER,\n               PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH) != 0) {\n        return PSA_ERROR_DATA_INVALID;\n    }\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data,\n                                             size_t storage_data_length,\n                                             uint8_t **key_data,\n                                             size_t *key_data_length,\n                                             psa_key_attributes_t *attr)\n{\n    psa_status_t status;\n    const psa_persistent_key_storage_format *storage_format =\n        (const psa_persistent_key_storage_format *) storage_data;\n    uint32_t version;\n\n    if (storage_data_length < sizeof(*storage_format)) {\n        return PSA_ERROR_DATA_INVALID;\n    }\n\n    status = check_magic_header(storage_data);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    version = MBEDTLS_GET_UINT32_LE(storage_format->version, 0);\n    if (version != 0) {\n        return PSA_ERROR_DATA_INVALID;\n    }\n\n    *key_data_length = MBEDTLS_GET_UINT32_LE(storage_format->data_len, 0);\n    if (*key_data_length > (storage_data_length - sizeof(*storage_format)) ||\n        *key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE) {\n        return PSA_ERROR_DATA_INVALID;\n    }\n\n    if (*key_data_length == 0) {\n        *key_data = NULL;\n    } else {\n        *key_data = mbedtls_calloc(1, *key_data_length);\n        if (*key_data == NULL) {\n            return PSA_ERROR_INSUFFICIENT_MEMORY;\n        }\n        memcpy(*key_data, storage_format->key_data, *key_data_length);\n    }\n\n    attr->lifetime = MBEDTLS_GET_UINT32_LE(storage_format->lifetime, 0);\n    attr->type = MBEDTLS_GET_UINT16_LE(storage_format->type, 0);\n    attr->bits = MBEDTLS_GET_UINT16_LE(storage_format->bits, 0);\n    attr->policy.usage = MBEDTLS_GET_UINT32_LE(storage_format->policy, 0);\n    attr->policy.alg = MBEDTLS_GET_UINT32_LE(storage_format->policy, sizeof(uint32_t));\n    attr->policy.alg2 = MBEDTLS_GET_UINT32_LE(storage_format->policy, 2 * sizeof(uint32_t));\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr,\n                                     const uint8_t *data,\n                                     const size_t data_length)\n{\n    size_t storage_data_length;\n    uint8_t *storage_data;\n    psa_status_t status;\n\n    /* All keys saved to persistent storage always have a key context */\n    if (data == NULL || data_length == 0) {\n        return PSA_ERROR_INVALID_ARGUMENT;\n    }\n\n    if (data_length > PSA_CRYPTO_MAX_STORAGE_SIZE) {\n        return PSA_ERROR_INSUFFICIENT_STORAGE;\n    }\n    storage_data_length = data_length + sizeof(psa_persistent_key_storage_format);\n\n    storage_data = mbedtls_calloc(1, storage_data_length);\n    if (storage_data == NULL) {\n        return PSA_ERROR_INSUFFICIENT_MEMORY;\n    }\n\n    psa_format_key_data_for_storage(data, data_length, attr, storage_data);\n\n    status = psa_crypto_storage_store(attr->id,\n                                      storage_data, storage_data_length);\n\n    mbedtls_zeroize_and_free(storage_data, storage_data_length);\n\n    return status;\n}\n\nvoid psa_free_persistent_key_data(uint8_t *key_data, size_t key_data_length)\n{\n    mbedtls_zeroize_and_free(key_data, key_data_length);\n}\n\npsa_status_t psa_load_persistent_key(psa_key_attributes_t *attr,\n                                     uint8_t **data,\n                                     size_t *data_length)\n{\n    psa_status_t status = PSA_SUCCESS;\n    uint8_t *loaded_data;\n    size_t storage_data_length = 0;\n    mbedtls_svc_key_id_t key = attr->id;\n\n    status = psa_crypto_storage_get_data_length(key, &storage_data_length);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    loaded_data = mbedtls_calloc(1, storage_data_length);\n\n    if (loaded_data == NULL) {\n        return PSA_ERROR_INSUFFICIENT_MEMORY;\n    }\n\n    status = psa_crypto_storage_load(key, loaded_data, storage_data_length);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_parse_key_data_from_storage(loaded_data, storage_data_length,\n                                             data, data_length, attr);\n\n    /* All keys saved to persistent storage always have a key context */\n    if (status == PSA_SUCCESS &&\n        (*data == NULL || *data_length == 0)) {\n        status = PSA_ERROR_STORAGE_FAILURE;\n    }\n\nexit:\n    mbedtls_zeroize_and_free(loaded_data, storage_data_length);\n    return status;\n}\n\n\n\n/****************************************************************/\n/* Transactions */\n/****************************************************************/\n\n#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)\n\npsa_crypto_transaction_t psa_crypto_transaction;\n\npsa_status_t psa_crypto_save_transaction(void)\n{\n    struct psa_storage_info_t p_info;\n    psa_status_t status;\n    status = psa_its_get_info(PSA_CRYPTO_ITS_TRANSACTION_UID, &p_info);\n    if (status == PSA_SUCCESS) {\n        /* This shouldn't happen: we're trying to start a transaction while\n         * there is still a transaction that hasn't been replayed. */\n        return PSA_ERROR_CORRUPTION_DETECTED;\n    } else if (status != PSA_ERROR_DOES_NOT_EXIST) {\n        return status;\n    }\n    return psa_its_set(PSA_CRYPTO_ITS_TRANSACTION_UID,\n                       sizeof(psa_crypto_transaction),\n                       &psa_crypto_transaction,\n                       0);\n}\n\npsa_status_t psa_crypto_load_transaction(void)\n{\n    psa_status_t status;\n    size_t length;\n    status = psa_its_get(PSA_CRYPTO_ITS_TRANSACTION_UID, 0,\n                         sizeof(psa_crypto_transaction),\n                         &psa_crypto_transaction, &length);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n    if (length != sizeof(psa_crypto_transaction)) {\n        return PSA_ERROR_DATA_INVALID;\n    }\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_crypto_stop_transaction(void)\n{\n    psa_status_t status = psa_its_remove(PSA_CRYPTO_ITS_TRANSACTION_UID);\n    /* Whether or not updating the storage succeeded, the transaction is\n     * finished now. It's too late to go back, so zero out the in-memory\n     * data. */\n    memset(&psa_crypto_transaction, 0, sizeof(psa_crypto_transaction));\n    return status;\n}\n\n#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */\n\n\n\n/****************************************************************/\n/* Random generator state */\n/****************************************************************/\n\n#if defined(MBEDTLS_PSA_INJECT_ENTROPY)\npsa_status_t mbedtls_psa_storage_inject_entropy(const unsigned char *seed,\n                                                size_t seed_size)\n{\n    psa_status_t status;\n    struct psa_storage_info_t p_info;\n\n    status = psa_its_get_info(PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info);\n\n    if (PSA_ERROR_DOES_NOT_EXIST == status) { /* No seed exists */\n        status = psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0);\n    } else if (PSA_SUCCESS == status) {\n        /* You should not be here. Seed needs to be injected only once */\n        status = PSA_ERROR_NOT_PERMITTED;\n    }\n    return status;\n}\n#endif /* MBEDTLS_PSA_INJECT_ENTROPY */\n\n\n\n/****************************************************************/\n/* The end */\n/****************************************************************/\n\n#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_crypto_storage.h",
    "content": "/**\n * \\file psa_crypto_storage.h\n *\n * \\brief PSA cryptography module: Mbed TLS key storage\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef PSA_CRYPTO_STORAGE_H\n#define PSA_CRYPTO_STORAGE_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"psa/crypto.h\"\n#include \"psa/crypto_se_driver.h\"\n\n#include <stdint.h>\n#include <string.h>\n\n/* Limit the maximum key size in storage. */\n#if defined(MBEDTLS_PSA_STATIC_KEY_SLOTS)\n/* Reflect the maximum size for the key buffer. */\n#define PSA_CRYPTO_MAX_STORAGE_SIZE (MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE)\n#else\n/* Just set an upper boundary but it should have no effect since the key size\n * is limited in memory. */\n#define PSA_CRYPTO_MAX_STORAGE_SIZE (PSA_BITS_TO_BYTES(PSA_MAX_KEY_BITS))\n#endif\n\n/* Sanity check: a file size must fit in 32 bits. Allow a generous\n * 64kB of metadata. */\n#if PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000\n#error \"PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000\"\n#endif\n\n/** The maximum permitted persistent slot number.\n *\n * In Mbed Crypto 0.1.0b:\n * - Using the file backend, all key ids are ok except 0.\n * - Using the ITS backend, all key ids are ok except 0xFFFFFF52\n *   (#PSA_CRYPTO_ITS_RANDOM_SEED_UID) for which the file contains the\n *   device's random seed (if this feature is enabled).\n * - Only key ids from 1 to #MBEDTLS_PSA_KEY_SLOT_COUNT are actually used.\n *\n * Since we need to preserve the random seed, avoid using that key slot.\n * Reserve a whole range of key slots just in case something else comes up.\n *\n * This limitation will probably become moot when we implement client\n * separation for key storage.\n */\n#define PSA_MAX_PERSISTENT_KEY_IDENTIFIER PSA_KEY_ID_VENDOR_MAX\n\n/**\n * \\brief Checks if persistent data is stored for the given key slot number\n *\n * This function checks if any key data or metadata exists for the key slot in\n * the persistent storage.\n *\n * \\param key           Persistent identifier to check.\n *\n * \\retval 0\n *         No persistent data present for slot number\n * \\retval 1\n *         Persistent data present for slot number\n */\nint psa_is_key_present_in_storage(const mbedtls_svc_key_id_t key);\n\n/**\n * \\brief Format key data and metadata and save to a location for given key\n *        slot.\n *\n * This function formats the key data and metadata and saves it to a\n * persistent storage backend. The storage location corresponding to the\n * key slot must be empty, otherwise this function will fail. This function\n * should be called after loading the key into an internal slot to ensure the\n * persistent key is not saved into a storage location corresponding to an\n * already occupied non-persistent key, as well as ensuring the key data is\n * validated.\n *\n * Note: This function will only succeed for key buffers which are not\n * empty. If passed a NULL pointer or zero-length, the function will fail\n * with #PSA_ERROR_INVALID_ARGUMENT.\n *\n * \\param[in] attr          The attributes of the key to save.\n *                          The key identifier field in the attributes\n *                          determines the key's location.\n * \\param[in] data          Buffer containing the key data.\n * \\param data_length       The number of bytes that make up the key data.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INVALID_ARGUMENT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_ALREADY_EXISTS \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n */\npsa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr,\n                                     const uint8_t *data,\n                                     const size_t data_length);\n\n/**\n * \\brief Parses key data and metadata and load persistent key for given\n * key slot number.\n *\n * This function reads from a storage backend, parses the key data and\n * metadata and writes them to the appropriate output parameters.\n *\n * Note: This function allocates a buffer and returns a pointer to it through\n * the data parameter. On successful return, the pointer is guaranteed to be\n * valid and the buffer contains at least one byte of data.\n * psa_free_persistent_key_data() must be called on the data buffer\n * afterwards to zeroize and free this buffer.\n *\n * \\param[in,out] attr      On input, the key identifier field identifies\n *                          the key to load. Other fields are ignored.\n *                          On success, the attribute structure contains\n *                          the key metadata that was loaded from storage.\n * \\param[out] data         Pointer to an allocated key data buffer on return.\n * \\param[out] data_length  The number of bytes that make up the key data.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_DOES_NOT_EXIST \\emptydescription\n */\npsa_status_t psa_load_persistent_key(psa_key_attributes_t *attr,\n                                     uint8_t **data,\n                                     size_t *data_length);\n\n/**\n * \\brief Remove persistent data for the given key slot number.\n *\n * \\param key           Persistent identifier of the key to remove\n *                      from persistent storage.\n *\n * \\retval #PSA_SUCCESS\n *         The key was successfully removed,\n *         or the key did not exist.\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n */\npsa_status_t psa_destroy_persistent_key(const mbedtls_svc_key_id_t key);\n\n/**\n * \\brief Free the temporary buffer allocated by psa_load_persistent_key().\n *\n * This function must be called at some point after psa_load_persistent_key()\n * to zeroize and free the memory allocated to the buffer in that function.\n *\n * \\param key_data        Buffer for the key data.\n * \\param key_data_length Size of the key data buffer.\n *\n */\nvoid psa_free_persistent_key_data(uint8_t *key_data, size_t key_data_length);\n\n/**\n * \\brief Formats key data and metadata for persistent storage\n *\n * \\param[in] data          Buffer containing the key data.\n * \\param data_length       Length of the key data buffer.\n * \\param[in] attr          The core attributes of the key.\n * \\param[out] storage_data Output buffer for the formatted data.\n *\n */\nvoid psa_format_key_data_for_storage(const uint8_t *data,\n                                     const size_t data_length,\n                                     const psa_key_attributes_t *attr,\n                                     uint8_t *storage_data);\n\n/**\n * \\brief Parses persistent storage data into key data and metadata\n *\n * \\param[in] storage_data     Buffer for the storage data.\n * \\param storage_data_length  Length of the storage data buffer\n * \\param[out] key_data        On output, pointer to a newly allocated buffer\n *                             containing the key data. This must be freed\n *                             using psa_free_persistent_key_data()\n * \\param[out] key_data_length Length of the key data buffer\n * \\param[out] attr            On success, the attribute structure is filled\n *                             with the loaded key metadata.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_MEMORY \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n */\npsa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data,\n                                             size_t storage_data_length,\n                                             uint8_t **key_data,\n                                             size_t *key_data_length,\n                                             psa_key_attributes_t *attr);\n\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n/** This symbol is defined if transaction support is required. */\n#define PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS 1\n#endif\n\n#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)\n\n/** The type of transaction that is in progress.\n */\n/* This is an integer type rather than an enum for two reasons: to support\n * unknown values when loading a transaction file, and to ensure that the\n * type has a known size.\n */\ntypedef uint16_t psa_crypto_transaction_type_t;\n\n/** No transaction is in progress.\n *\n * This has the value 0, so zero-initialization sets a transaction's type to\n * this value.\n */\n#define PSA_CRYPTO_TRANSACTION_NONE             ((psa_crypto_transaction_type_t) 0x0000)\n\n/** A key creation transaction.\n *\n * This is only used for keys in an external cryptoprocessor (secure element).\n * Keys in RAM or in internal storage are created atomically in storage\n * (simple file creation), so they do not need a transaction mechanism.\n */\n#define PSA_CRYPTO_TRANSACTION_CREATE_KEY       ((psa_crypto_transaction_type_t) 0x0001)\n\n/** A key destruction transaction.\n *\n * This is only used for keys in an external cryptoprocessor (secure element).\n * Keys in RAM or in internal storage are destroyed atomically in storage\n * (simple file deletion), so they do not need a transaction mechanism.\n */\n#define PSA_CRYPTO_TRANSACTION_DESTROY_KEY      ((psa_crypto_transaction_type_t) 0x0002)\n\n/** Transaction data.\n *\n * This type is designed to be serialized by writing the memory representation\n * and reading it back on the same device.\n *\n * \\note The transaction mechanism is not thread-safe. There can only be one\n *       single active transaction at a time.\n *       The transaction object is #psa_crypto_transaction.\n *\n * \\note If an API call starts a transaction, it must complete this transaction\n *       before returning to the application.\n *\n * The lifetime of a transaction is the following (note that only one\n * transaction may be active at a time):\n *\n * -# Call psa_crypto_prepare_transaction() to initialize the transaction\n *    object in memory and declare the type of transaction that is starting.\n * -# Fill in the type-specific fields of #psa_crypto_transaction.\n * -# Call psa_crypto_save_transaction() to start the transaction. This\n *    saves the transaction data to internal storage.\n * -# Perform the work of the transaction by modifying files, contacting\n *    external entities, or whatever needs doing. Note that the transaction\n *    may be interrupted by a power failure, so you need to have a way\n *    recover from interruptions either by undoing what has been done\n *    so far or by resuming where you left off.\n * -# If there are intermediate stages in the transaction, update\n *    the fields of #psa_crypto_transaction and call\n *    psa_crypto_save_transaction() again when each stage is reached.\n * -# When the transaction is over, call psa_crypto_stop_transaction() to\n *    remove the transaction data in storage and in memory.\n *\n * If the system crashes while a transaction is in progress, psa_crypto_init()\n * calls psa_crypto_load_transaction() and takes care of completing or\n * rewinding the transaction. This is done in psa_crypto_recover_transaction()\n * in psa_crypto.c. If you add a new type of transaction, be\n * sure to add code for it in psa_crypto_recover_transaction().\n */\ntypedef union {\n    /* Each element of this union must have the following properties\n     * to facilitate serialization and deserialization:\n     *\n     * - The element is a struct.\n     * - The first field of the struct is `psa_crypto_transaction_type_t type`.\n     * - Elements of the struct are arranged such a way that there is\n     *   no padding.\n     */\n    struct psa_crypto_transaction_unknown_s {\n        psa_crypto_transaction_type_t type;\n        uint16_t unused1;\n        uint32_t unused2;\n        uint64_t unused3;\n        uint64_t unused4;\n    } unknown;\n    /* ::type is #PSA_CRYPTO_TRANSACTION_CREATE_KEY or\n     * #PSA_CRYPTO_TRANSACTION_DESTROY_KEY. */\n    struct psa_crypto_transaction_key_s {\n        psa_crypto_transaction_type_t type;\n        uint16_t unused1;\n        psa_key_lifetime_t lifetime;\n        psa_key_slot_number_t slot;\n        mbedtls_svc_key_id_t id;\n    } key;\n} psa_crypto_transaction_t;\n\n/** The single active transaction.\n */\nextern psa_crypto_transaction_t psa_crypto_transaction;\n\n/** Prepare for a transaction.\n *\n * There must not be an ongoing transaction.\n *\n * \\param type          The type of transaction to start.\n */\nstatic inline void psa_crypto_prepare_transaction(\n    psa_crypto_transaction_type_t type)\n{\n    psa_crypto_transaction.unknown.type = type;\n}\n\n/** Save the transaction data to storage.\n *\n * You may call this function multiple times during a transaction to\n * atomically update the transaction state.\n *\n * \\retval #PSA_SUCCESS \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n */\npsa_status_t psa_crypto_save_transaction(void);\n\n/** Load the transaction data from storage, if any.\n *\n * This function is meant to be called from psa_crypto_init() to recover\n * in case a transaction was interrupted by a system crash.\n *\n * \\retval #PSA_SUCCESS\n *         The data about the ongoing transaction has been loaded to\n *         #psa_crypto_transaction.\n * \\retval #PSA_ERROR_DOES_NOT_EXIST\n *         There is no ongoing transaction.\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_DATA_INVALID \\emptydescription\n * \\retval #PSA_ERROR_DATA_CORRUPT \\emptydescription\n */\npsa_status_t psa_crypto_load_transaction(void);\n\n/** Indicate that the current transaction is finished.\n *\n * Call this function at the very end of transaction processing.\n * This function does not \"commit\" or \"abort\" the transaction: the storage\n * subsystem has no concept of \"commit\" and \"abort\", just saving and\n * removing the transaction information in storage.\n *\n * This function erases the transaction data in storage (if any) and\n * resets the transaction data in memory.\n *\n * \\retval #PSA_SUCCESS\n *         There was transaction data in storage.\n * \\retval #PSA_ERROR_DOES_NOT_EXIST\n *         There was no transaction data in storage.\n * \\retval #PSA_ERROR_STORAGE_FAILURE\n *         It was impossible to determine whether there was transaction data\n *         in storage, or the transaction data could not be erased.\n */\npsa_status_t psa_crypto_stop_transaction(void);\n\n/** The ITS file identifier for the transaction data.\n *\n * 0xffffffNN = special file; 0x74 = 't' for transaction.\n */\n#define PSA_CRYPTO_ITS_TRANSACTION_UID ((psa_key_id_t) 0xffffff74)\n\n#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */\n\n#if defined(MBEDTLS_PSA_INJECT_ENTROPY)\n/** Backend side of mbedtls_psa_inject_entropy().\n *\n * This function stores the supplied data into the entropy seed file.\n *\n * \\retval #PSA_SUCCESS\n *         Success\n * \\retval #PSA_ERROR_STORAGE_FAILURE \\emptydescription\n * \\retval #PSA_ERROR_INSUFFICIENT_STORAGE \\emptydescription\n * \\retval #PSA_ERROR_NOT_PERMITTED\n *         The entropy seed file already exists.\n */\npsa_status_t mbedtls_psa_storage_inject_entropy(const unsigned char *seed,\n                                                size_t seed_size);\n#endif /* MBEDTLS_PSA_INJECT_ENTROPY */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* PSA_CRYPTO_STORAGE_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_its_file.c",
    "content": "/*\n *  PSA ITS simulator over stdio files.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_PSA_ITS_FILE_C)\n\n#include \"mbedtls/platform.h\"\n\n#if defined(_WIN32)\n#include <windows.h>\n#endif\n\n#include \"psa_crypto_its.h\"\n\n#include <limits.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n\n#if !defined(PSA_ITS_STORAGE_PREFIX)\n#define PSA_ITS_STORAGE_PREFIX \"\"\n#endif\n\n#define PSA_ITS_STORAGE_FILENAME_PATTERN \"%08x%08x\"\n#define PSA_ITS_STORAGE_SUFFIX \".psa_its\"\n#define PSA_ITS_STORAGE_FILENAME_LENGTH         \\\n    (sizeof(PSA_ITS_STORAGE_PREFIX) - 1 +    /*prefix without terminating 0*/ \\\n     16 +  /*UID (64-bit number in hex)*/                               \\\n     sizeof(PSA_ITS_STORAGE_SUFFIX) - 1 +    /*suffix without terminating 0*/ \\\n     1 /*terminating null byte*/)\n#define PSA_ITS_STORAGE_TEMP \\\n    PSA_ITS_STORAGE_PREFIX \"tempfile\" PSA_ITS_STORAGE_SUFFIX\n\n/* The maximum value of psa_storage_info_t.size */\n#define PSA_ITS_MAX_SIZE 0xffffffff\n\n#define PSA_ITS_MAGIC_STRING \"PSA\\0ITS\\0\"\n#define PSA_ITS_MAGIC_LENGTH 8\n\n/* As rename fails on Windows if the new filepath already exists,\n * use MoveFileExA with the MOVEFILE_REPLACE_EXISTING flag instead.\n * Returns 0 on success, nonzero on failure. */\n#if defined(_WIN32)\n#define rename_replace_existing(oldpath, newpath) \\\n    (!MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))\n#else\n#define rename_replace_existing(oldpath, newpath) rename(oldpath, newpath)\n#endif\n\ntypedef struct {\n    uint8_t magic[PSA_ITS_MAGIC_LENGTH];\n    uint8_t size[sizeof(uint32_t)];\n    uint8_t flags[sizeof(psa_storage_create_flags_t)];\n} psa_its_file_header_t;\n\nstatic void psa_its_fill_filename(psa_storage_uid_t uid, char *filename)\n{\n    /* Break up the UID into two 32-bit pieces so as not to rely on\n     * long long support in snprintf. */\n    mbedtls_snprintf(filename, PSA_ITS_STORAGE_FILENAME_LENGTH,\n                     \"%s\" PSA_ITS_STORAGE_FILENAME_PATTERN \"%s\",\n                     PSA_ITS_STORAGE_PREFIX,\n                     (unsigned) (uid >> 32),\n                     (unsigned) (uid & 0xffffffff),\n                     PSA_ITS_STORAGE_SUFFIX);\n}\n\nstatic psa_status_t psa_its_read_file(psa_storage_uid_t uid,\n                                      struct psa_storage_info_t *p_info,\n                                      FILE **p_stream)\n{\n    char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];\n    psa_its_file_header_t header;\n    size_t n;\n\n    *p_stream = NULL;\n    psa_its_fill_filename(uid, filename);\n    *p_stream = fopen(filename, \"rb\");\n    if (*p_stream == NULL) {\n        return PSA_ERROR_DOES_NOT_EXIST;\n    }\n\n    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */\n    mbedtls_setbuf(*p_stream, NULL);\n\n    n = fread(&header, 1, sizeof(header), *p_stream);\n    if (n != sizeof(header)) {\n        return PSA_ERROR_DATA_CORRUPT;\n    }\n    if (memcmp(header.magic, PSA_ITS_MAGIC_STRING,\n               PSA_ITS_MAGIC_LENGTH) != 0) {\n        return PSA_ERROR_DATA_CORRUPT;\n    }\n\n    p_info->size  = MBEDTLS_GET_UINT32_LE(header.size, 0);\n    p_info->flags = MBEDTLS_GET_UINT32_LE(header.flags, 0);\n\n    return PSA_SUCCESS;\n}\n\npsa_status_t psa_its_get_info(psa_storage_uid_t uid,\n                              struct psa_storage_info_t *p_info)\n{\n    psa_status_t status;\n    FILE *stream = NULL;\n    status = psa_its_read_file(uid, p_info, &stream);\n    if (stream != NULL) {\n        fclose(stream);\n    }\n    return status;\n}\n\npsa_status_t psa_its_get(psa_storage_uid_t uid,\n                         uint32_t data_offset,\n                         uint32_t data_length,\n                         void *p_data,\n                         size_t *p_data_length)\n{\n    psa_status_t status;\n    FILE *stream = NULL;\n    size_t n;\n    struct psa_storage_info_t info;\n\n    status = psa_its_read_file(uid, &info, &stream);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n    status = PSA_ERROR_INVALID_ARGUMENT;\n    if (data_offset + data_length < data_offset) {\n        goto exit;\n    }\n#if SIZE_MAX < 0xffffffff\n    if (data_offset + data_length > SIZE_MAX) {\n        goto exit;\n    }\n#endif\n    if (data_offset + data_length > info.size) {\n        goto exit;\n    }\n\n    status = PSA_ERROR_STORAGE_FAILURE;\n#if LONG_MAX < 0xffffffff\n    while (data_offset > LONG_MAX) {\n        if (fseek(stream, LONG_MAX, SEEK_CUR) != 0) {\n            goto exit;\n        }\n        data_offset -= LONG_MAX;\n    }\n#endif\n    if (fseek(stream, data_offset, SEEK_CUR) != 0) {\n        goto exit;\n    }\n    n = fread(p_data, 1, data_length, stream);\n    if (n != data_length) {\n        goto exit;\n    }\n    status = PSA_SUCCESS;\n    if (p_data_length != NULL) {\n        *p_data_length = n;\n    }\n\nexit:\n    if (stream != NULL) {\n        fclose(stream);\n    }\n    return status;\n}\n\npsa_status_t psa_its_set(psa_storage_uid_t uid,\n                         uint32_t data_length,\n                         const void *p_data,\n                         psa_storage_create_flags_t create_flags)\n{\n    if (uid == 0) {\n        return PSA_ERROR_INVALID_HANDLE;\n    }\n\n    psa_status_t status = PSA_ERROR_STORAGE_FAILURE;\n    char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];\n    FILE *stream = NULL;\n    psa_its_file_header_t header;\n    size_t n;\n\n    memcpy(header.magic, PSA_ITS_MAGIC_STRING, PSA_ITS_MAGIC_LENGTH);\n    MBEDTLS_PUT_UINT32_LE(data_length, header.size, 0);\n    MBEDTLS_PUT_UINT32_LE(create_flags, header.flags, 0);\n\n    psa_its_fill_filename(uid, filename);\n    stream = fopen(PSA_ITS_STORAGE_TEMP, \"wb\");\n\n    if (stream == NULL) {\n        goto exit;\n    }\n\n    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */\n    mbedtls_setbuf(stream, NULL);\n\n    status = PSA_ERROR_INSUFFICIENT_STORAGE;\n    n = fwrite(&header, 1, sizeof(header), stream);\n    if (n != sizeof(header)) {\n        goto exit;\n    }\n    if (data_length != 0) {\n        n = fwrite(p_data, 1, data_length, stream);\n        if (n != data_length) {\n            goto exit;\n        }\n    }\n    status = PSA_SUCCESS;\n\nexit:\n    if (stream != NULL) {\n        int ret = fclose(stream);\n        if (status == PSA_SUCCESS && ret != 0) {\n            status = PSA_ERROR_INSUFFICIENT_STORAGE;\n        }\n    }\n    if (status == PSA_SUCCESS) {\n        if (rename_replace_existing(PSA_ITS_STORAGE_TEMP, filename) != 0) {\n            status = PSA_ERROR_STORAGE_FAILURE;\n        }\n    }\n    /* The temporary file may still exist, but only in failure cases where\n     * we're already reporting an error. So there's nothing we can do on\n     * failure. If the function succeeded, and in some error cases, the\n     * temporary file doesn't exist and so remove() is expected to fail.\n     * Thus we just ignore the return status of remove(). */\n    (void) remove(PSA_ITS_STORAGE_TEMP);\n    return status;\n}\n\npsa_status_t psa_its_remove(psa_storage_uid_t uid)\n{\n    char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];\n    FILE *stream;\n    psa_its_fill_filename(uid, filename);\n    stream = fopen(filename, \"rb\");\n    if (stream == NULL) {\n        return PSA_ERROR_DOES_NOT_EXIST;\n    }\n    fclose(stream);\n    if (remove(filename) != 0) {\n        return PSA_ERROR_STORAGE_FAILURE;\n    }\n    return PSA_SUCCESS;\n}\n\n#endif /* MBEDTLS_PSA_ITS_FILE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_util.c",
    "content": "/*\n *  PSA hashing layer on top of Mbed TLS software crypto\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n/* This is needed for MBEDTLS_ERR_XXX macros */\n#include <mbedtls/error.h>\n\n#if defined(MBEDTLS_ASN1_WRITE_C)\n#include <mbedtls/asn1write.h>\n#include <psa/crypto_sizes.h>\n#endif\n\n#include \"psa_util_internal.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)\n\n#include <psa/crypto.h>\n\n#if defined(MBEDTLS_MD_LIGHT)\n#include <mbedtls/md.h>\n#endif\n#if defined(MBEDTLS_LMS_C)\n#include <mbedtls/lms.h>\n#endif\n#if defined(MBEDTLS_SSL_TLS_C) && \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3))\n#include <mbedtls/ssl.h>\n#endif\n#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ||    \\\n    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)\n#include <mbedtls/rsa.h>\n#endif\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && \\\n    defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)\n#include <mbedtls/ecp.h>\n#endif\n#if defined(MBEDTLS_PK_C)\n#include <mbedtls/pk.h>\n#endif\n#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)\n#include <mbedtls/cipher.h>\n#endif\n#include <mbedtls/entropy.h>\n\n/* PSA_SUCCESS is kept at the top of each error table since\n * it's the most common status when everything functions properly. */\n#if defined(MBEDTLS_MD_LIGHT)\nconst mbedtls_error_pair_t psa_to_md_errors[] =\n{\n    { PSA_SUCCESS,                     0 },\n    { PSA_ERROR_NOT_SUPPORTED,         MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE },\n    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_MD_BAD_INPUT_DATA },\n    { PSA_ERROR_INSUFFICIENT_MEMORY,   MBEDTLS_ERR_MD_ALLOC_FAILED }\n};\n#endif\n\n#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)\nconst mbedtls_error_pair_t psa_to_cipher_errors[] =\n{\n    { PSA_SUCCESS,                     0 },\n    { PSA_ERROR_NOT_SUPPORTED,         MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE },\n    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA },\n    { PSA_ERROR_INSUFFICIENT_MEMORY,   MBEDTLS_ERR_CIPHER_ALLOC_FAILED }\n};\n#endif\n\n#if defined(MBEDTLS_LMS_C)\nconst mbedtls_error_pair_t psa_to_lms_errors[] =\n{\n    { PSA_SUCCESS,                     0 },\n    { PSA_ERROR_BUFFER_TOO_SMALL,      MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL },\n    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_LMS_BAD_INPUT_DATA }\n};\n#endif\n\n#if defined(MBEDTLS_SSL_TLS_C) && \\\n    (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3))\nconst mbedtls_error_pair_t psa_to_ssl_errors[] =\n{\n    { PSA_SUCCESS,                     0 },\n    { PSA_ERROR_INSUFFICIENT_MEMORY,   MBEDTLS_ERR_SSL_ALLOC_FAILED },\n    { PSA_ERROR_NOT_SUPPORTED,         MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE },\n    { PSA_ERROR_INVALID_SIGNATURE,     MBEDTLS_ERR_SSL_INVALID_MAC },\n    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_SSL_BAD_INPUT_DATA },\n    { PSA_ERROR_BAD_STATE,             MBEDTLS_ERR_SSL_INTERNAL_ERROR },\n    { PSA_ERROR_BUFFER_TOO_SMALL,      MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL }\n};\n#endif\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ||    \\\n    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)\nconst mbedtls_error_pair_t psa_to_pk_rsa_errors[] =\n{\n    { PSA_SUCCESS,                     0 },\n    { PSA_ERROR_NOT_PERMITTED,         MBEDTLS_ERR_RSA_BAD_INPUT_DATA },\n    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_RSA_BAD_INPUT_DATA },\n    { PSA_ERROR_INVALID_HANDLE,        MBEDTLS_ERR_RSA_BAD_INPUT_DATA },\n    { PSA_ERROR_BUFFER_TOO_SMALL,      MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE },\n    { PSA_ERROR_INSUFFICIENT_ENTROPY,  MBEDTLS_ERR_RSA_RNG_FAILED },\n    { PSA_ERROR_INVALID_SIGNATURE,     MBEDTLS_ERR_RSA_VERIFY_FAILED },\n    { PSA_ERROR_INVALID_PADDING,       MBEDTLS_ERR_RSA_INVALID_PADDING }\n};\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && \\\n    defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)\nconst mbedtls_error_pair_t psa_to_pk_ecdsa_errors[] =\n{\n    { PSA_SUCCESS,                     0 },\n    { PSA_ERROR_NOT_PERMITTED,         MBEDTLS_ERR_ECP_BAD_INPUT_DATA },\n    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_ECP_BAD_INPUT_DATA },\n    { PSA_ERROR_INVALID_HANDLE,        MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE },\n    { PSA_ERROR_BUFFER_TOO_SMALL,      MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL },\n    { PSA_ERROR_INSUFFICIENT_ENTROPY,  MBEDTLS_ERR_ECP_RANDOM_FAILED },\n    { PSA_ERROR_INVALID_SIGNATURE,     MBEDTLS_ERR_ECP_VERIFY_FAILED }\n};\n#endif\n\nint psa_generic_status_to_mbedtls(psa_status_t status)\n{\n    switch (status) {\n        case PSA_SUCCESS:\n            return 0;\n        case PSA_ERROR_NOT_SUPPORTED:\n            return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;\n        case PSA_ERROR_CORRUPTION_DETECTED:\n            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n        case PSA_ERROR_COMMUNICATION_FAILURE:\n        case PSA_ERROR_HARDWARE_FAILURE:\n            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;\n        case PSA_ERROR_NOT_PERMITTED:\n        default:\n            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;\n    }\n}\n\nint psa_status_to_mbedtls(psa_status_t status,\n                          const mbedtls_error_pair_t *local_translations,\n                          size_t local_errors_num,\n                          int (*fallback_f)(psa_status_t))\n{\n    for (size_t i = 0; i < local_errors_num; i++) {\n        if (status == local_translations[i].psa_status) {\n            return local_translations[i].mbedtls_error;\n        }\n    }\n    return fallback_f(status);\n}\n\n#if defined(MBEDTLS_PK_C)\nint psa_pk_status_to_mbedtls(psa_status_t status)\n{\n    switch (status) {\n        case PSA_ERROR_INVALID_HANDLE:\n            return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;\n        case PSA_ERROR_BUFFER_TOO_SMALL:\n            return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;\n        case PSA_ERROR_NOT_SUPPORTED:\n            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;\n        case PSA_ERROR_INVALID_ARGUMENT:\n            return MBEDTLS_ERR_PK_INVALID_ALG;\n        case PSA_ERROR_NOT_PERMITTED:\n            return MBEDTLS_ERR_PK_TYPE_MISMATCH;\n        case PSA_ERROR_INSUFFICIENT_MEMORY:\n            return MBEDTLS_ERR_PK_ALLOC_FAILED;\n        case PSA_ERROR_BAD_STATE:\n            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n        case PSA_ERROR_DATA_CORRUPT:\n        case PSA_ERROR_DATA_INVALID:\n        case PSA_ERROR_STORAGE_FAILURE:\n            return MBEDTLS_ERR_PK_FILE_IO_ERROR;\n        default:\n            return psa_generic_status_to_mbedtls(status);\n    }\n}\n#endif /* MBEDTLS_PK_C */\n\n/****************************************************************/\n/* Key management */\n/****************************************************************/\n\n#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)\npsa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid,\n                                          size_t *bits)\n{\n    switch (grpid) {\n#if defined(MBEDTLS_ECP_HAVE_SECP192R1)\n        case MBEDTLS_ECP_DP_SECP192R1:\n            *bits = 192;\n            return PSA_ECC_FAMILY_SECP_R1;\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP224R1)\n        case MBEDTLS_ECP_DP_SECP224R1:\n            *bits = 224;\n            return PSA_ECC_FAMILY_SECP_R1;\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP256R1)\n        case MBEDTLS_ECP_DP_SECP256R1:\n            *bits = 256;\n            return PSA_ECC_FAMILY_SECP_R1;\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP384R1)\n        case MBEDTLS_ECP_DP_SECP384R1:\n            *bits = 384;\n            return PSA_ECC_FAMILY_SECP_R1;\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP521R1)\n        case MBEDTLS_ECP_DP_SECP521R1:\n            *bits = 521;\n            return PSA_ECC_FAMILY_SECP_R1;\n#endif\n#if defined(MBEDTLS_ECP_HAVE_BP256R1)\n        case MBEDTLS_ECP_DP_BP256R1:\n            *bits = 256;\n            return PSA_ECC_FAMILY_BRAINPOOL_P_R1;\n#endif\n#if defined(MBEDTLS_ECP_HAVE_BP384R1)\n        case MBEDTLS_ECP_DP_BP384R1:\n            *bits = 384;\n            return PSA_ECC_FAMILY_BRAINPOOL_P_R1;\n#endif\n#if defined(MBEDTLS_ECP_HAVE_BP512R1)\n        case MBEDTLS_ECP_DP_BP512R1:\n            *bits = 512;\n            return PSA_ECC_FAMILY_BRAINPOOL_P_R1;\n#endif\n#if defined(MBEDTLS_ECP_HAVE_CURVE25519)\n        case MBEDTLS_ECP_DP_CURVE25519:\n            *bits = 255;\n            return PSA_ECC_FAMILY_MONTGOMERY;\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP192K1)\n        case MBEDTLS_ECP_DP_SECP192K1:\n            *bits = 192;\n            return PSA_ECC_FAMILY_SECP_K1;\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP224K1)\n    /* secp224k1 is not and will not be supported in PSA (#3541). */\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP256K1)\n        case MBEDTLS_ECP_DP_SECP256K1:\n            *bits = 256;\n            return PSA_ECC_FAMILY_SECP_K1;\n#endif\n#if defined(MBEDTLS_ECP_HAVE_CURVE448)\n        case MBEDTLS_ECP_DP_CURVE448:\n            *bits = 448;\n            return PSA_ECC_FAMILY_MONTGOMERY;\n#endif\n        default:\n            *bits = 0;\n            return 0;\n    }\n}\n\nmbedtls_ecp_group_id mbedtls_ecc_group_from_psa(psa_ecc_family_t family,\n                                                size_t bits)\n{\n    switch (family) {\n        case PSA_ECC_FAMILY_SECP_R1:\n            switch (bits) {\n#if defined(PSA_WANT_ECC_SECP_R1_192)\n                case 192:\n                    return MBEDTLS_ECP_DP_SECP192R1;\n#endif\n#if defined(PSA_WANT_ECC_SECP_R1_224)\n                case 224:\n                    return MBEDTLS_ECP_DP_SECP224R1;\n#endif\n#if defined(PSA_WANT_ECC_SECP_R1_256)\n                case 256:\n                    return MBEDTLS_ECP_DP_SECP256R1;\n#endif\n#if defined(PSA_WANT_ECC_SECP_R1_384)\n                case 384:\n                    return MBEDTLS_ECP_DP_SECP384R1;\n#endif\n#if defined(PSA_WANT_ECC_SECP_R1_521)\n                case 521:\n                    return MBEDTLS_ECP_DP_SECP521R1;\n#endif\n            }\n            break;\n\n        case PSA_ECC_FAMILY_BRAINPOOL_P_R1:\n            switch (bits) {\n#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)\n                case 256:\n                    return MBEDTLS_ECP_DP_BP256R1;\n#endif\n#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)\n                case 384:\n                    return MBEDTLS_ECP_DP_BP384R1;\n#endif\n#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)\n                case 512:\n                    return MBEDTLS_ECP_DP_BP512R1;\n#endif\n            }\n            break;\n\n        case PSA_ECC_FAMILY_MONTGOMERY:\n            switch (bits) {\n#if defined(PSA_WANT_ECC_MONTGOMERY_255)\n                case 255:\n                    return MBEDTLS_ECP_DP_CURVE25519;\n#endif\n#if defined(PSA_WANT_ECC_MONTGOMERY_448)\n                case 448:\n                    return MBEDTLS_ECP_DP_CURVE448;\n#endif\n            }\n            break;\n\n        case PSA_ECC_FAMILY_SECP_K1:\n            switch (bits) {\n#if defined(PSA_WANT_ECC_SECP_K1_192)\n                case 192:\n                    return MBEDTLS_ECP_DP_SECP192K1;\n#endif\n#if defined(PSA_WANT_ECC_SECP_K1_224)\n            /* secp224k1 is not and will not be supported in PSA (#3541). */\n#endif\n#if defined(PSA_WANT_ECC_SECP_K1_256)\n                case 256:\n                    return MBEDTLS_ECP_DP_SECP256K1;\n#endif\n            }\n            break;\n    }\n\n    return MBEDTLS_ECP_DP_NONE;\n}\n#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */\n\n/* Wrapper function allowing the classic API to use the PSA RNG.\n *\n * `mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, ...)` calls\n * `psa_generate_random(...)`. The state parameter is ignored since the\n * PSA API doesn't support passing an explicit state.\n */\nint mbedtls_psa_get_random(void *p_rng,\n                           unsigned char *output,\n                           size_t output_size)\n{\n    /* This function takes a pointer to the RNG state because that's what\n     * classic mbedtls functions using an RNG expect. The PSA RNG manages\n     * its own state internally and doesn't let the caller access that state.\n     * So we just ignore the state parameter, and in practice we'll pass\n     * NULL. */\n    (void) p_rng;\n    psa_status_t status = psa_generate_random(output, output_size);\n    if (status == PSA_SUCCESS) {\n        return 0;\n    } else {\n        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;\n    }\n}\n\n#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */\n\n#if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)\n\n/**\n * \\brief  Convert a single raw coordinate to DER ASN.1 format. The output der\n *         buffer is filled backward (i.e. starting from its end).\n *\n * \\param raw_buf           Buffer containing the raw coordinate to be\n *                          converted.\n * \\param raw_len           Length of raw_buf in bytes. This must be > 0.\n * \\param der_buf_start     Pointer to the beginning of the buffer which\n *                          will be filled with the DER converted data.\n * \\param der_buf_end       End of the buffer used to store the DER output.\n *\n * \\return                  On success, the amount of data (in bytes) written to\n *                          the DER buffer.\n * \\return                  MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if the provided der\n *                          buffer is too small to contain all the converted data.\n * \\return                  MBEDTLS_ERR_ASN1_INVALID_DATA if the input raw\n *                          coordinate is null (i.e. all zeros).\n *\n * \\warning                 Raw and der buffer must not be overlapping.\n */\nstatic int convert_raw_to_der_single_int(const unsigned char *raw_buf, size_t raw_len,\n                                         unsigned char *der_buf_start,\n                                         unsigned char *der_buf_end)\n{\n    unsigned char *p = der_buf_end;\n    int len;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* ASN.1 DER encoding requires minimal length, so skip leading 0s.\n     * Provided input MPIs should not be 0, but as a failsafe measure, still\n     * detect that and return error in case. */\n    while (*raw_buf == 0x00) {\n        ++raw_buf;\n        --raw_len;\n        if (raw_len == 0) {\n            return MBEDTLS_ERR_ASN1_INVALID_DATA;\n        }\n    }\n    len = (int) raw_len;\n\n    /* Copy the raw coordinate to the end of der_buf. */\n    if ((p - der_buf_start) < len) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n    p -= len;\n    memcpy(p, raw_buf, len);\n\n    /* If MSb is 1, ASN.1 requires that we prepend a 0. */\n    if (*p & 0x80) {\n        if ((p - der_buf_start) < 1) {\n            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n        }\n        --p;\n        *p = 0x00;\n        ++len;\n    }\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der_buf_start, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der_buf_start, MBEDTLS_ASN1_INTEGER));\n\n    return len;\n}\n\nint mbedtls_ecdsa_raw_to_der(size_t bits, const unsigned char *raw, size_t raw_len,\n                             unsigned char *der, size_t der_size, size_t *der_len)\n{\n    unsigned char r[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];\n    unsigned char s[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];\n    const size_t coordinate_len = PSA_BITS_TO_BYTES(bits);\n    size_t len = 0;\n    unsigned char *p = der + der_size;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (bits == 0) {\n        return MBEDTLS_ERR_ASN1_INVALID_DATA;\n    }\n    if (raw_len != (2 * coordinate_len)) {\n        return MBEDTLS_ERR_ASN1_INVALID_DATA;\n    }\n    if (coordinate_len > sizeof(r)) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n\n    /* Since raw and der buffers might overlap, dump r and s before starting\n     * the conversion. */\n    memcpy(r, raw, coordinate_len);\n    memcpy(s, raw + coordinate_len, coordinate_len);\n\n    /* der buffer will initially be written starting from its end so we pick s\n     * first and then r. */\n    ret = convert_raw_to_der_single_int(s, coordinate_len, der, p);\n    if (ret < 0) {\n        return ret;\n    }\n    p -= ret;\n    len += ret;\n\n    ret = convert_raw_to_der_single_int(r, coordinate_len, der, p);\n    if (ret < 0) {\n        return ret;\n    }\n    p -= ret;\n    len += ret;\n\n    /* Add ASN.1 header (len + tag). */\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der,\n                                                     MBEDTLS_ASN1_CONSTRUCTED |\n                                                     MBEDTLS_ASN1_SEQUENCE));\n\n    /* memmove the content of der buffer to its beginnig. */\n    memmove(der, p, len);\n    *der_len = len;\n\n    return 0;\n}\n\n/**\n * \\brief Convert a single integer from ASN.1 DER format to raw.\n *\n * \\param der               Buffer containing the DER integer value to be\n *                          converted.\n * \\param der_len           Length of the der buffer in bytes.\n * \\param raw               Output buffer that will be filled with the\n *                          converted data. This should be at least\n *                          coordinate_size bytes and it must be zeroed before\n *                          calling this function.\n * \\param coordinate_size   Size (in bytes) of a single coordinate in raw\n *                          format.\n *\n * \\return                  On success, the amount of DER data parsed from the\n *                          provided der buffer.\n * \\return                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the integer tag\n *                          is missing in the der buffer.\n * \\return                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the integer\n *                          is null (i.e. all zeros) or if the output raw buffer\n *                          is too small to contain the converted raw value.\n *\n * \\warning                 Der and raw buffers must not be overlapping.\n */\nstatic int convert_der_to_raw_single_int(unsigned char *der, size_t der_len,\n                                         unsigned char *raw, size_t coordinate_size)\n{\n    unsigned char *p = der;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t unpadded_len, padding_len = 0;\n\n    /* Get the length of ASN.1 element (i.e. the integer we need to parse). */\n    ret = mbedtls_asn1_get_tag(&p, p + der_len, &unpadded_len,\n                               MBEDTLS_ASN1_INTEGER);\n    if (ret != 0) {\n        return ret;\n    }\n\n    /* It's invalid to have:\n     * - unpadded_len == 0.\n     * - MSb set without a leading 0x00 (leading 0x00 is checked below). */\n    if (((unpadded_len == 0) || (*p & 0x80) != 0)) {\n        return MBEDTLS_ERR_ASN1_INVALID_DATA;\n    }\n\n    /* Skip possible leading zero */\n    if (*p == 0x00) {\n        p++;\n        unpadded_len--;\n        /* It is not allowed to have more than 1 leading zero.\n         * Ignore the case in which unpadded_len = 0 because that's a 0 encoded\n         * in ASN.1 format (i.e. 020100). */\n        if ((unpadded_len > 0) && (*p == 0x00)) {\n            return MBEDTLS_ERR_ASN1_INVALID_DATA;\n        }\n    }\n\n    if (unpadded_len > coordinate_size) {\n        /* Parsed number is longer than the maximum expected value. */\n        return MBEDTLS_ERR_ASN1_INVALID_DATA;\n    }\n    padding_len = coordinate_size - unpadded_len;\n    /* raw buffer was already zeroed by the calling function so zero-padding\n     * operation is skipped here. */\n    memcpy(raw + padding_len, p, unpadded_len);\n    p += unpadded_len;\n\n    return (int) (p - der);\n}\n\nint mbedtls_ecdsa_der_to_raw(size_t bits, const unsigned char *der, size_t der_len,\n                             unsigned char *raw, size_t raw_size, size_t *raw_len)\n{\n    unsigned char raw_tmp[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE];\n    unsigned char *p = (unsigned char *) der;\n    size_t data_len;\n    size_t coordinate_size = PSA_BITS_TO_BYTES(bits);\n    int ret;\n\n    if (bits == 0) {\n        return MBEDTLS_ERR_ASN1_INVALID_DATA;\n    }\n    /* The output raw buffer should be at least twice the size of a raw\n     * coordinate in order to store r and s. */\n    if (raw_size < coordinate_size * 2) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n    if (2 * coordinate_size > sizeof(raw_tmp)) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n\n    /* Check that the provided input DER buffer has the right header. */\n    ret = mbedtls_asn1_get_tag(&p, der + der_len, &data_len,\n                               MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);\n    if (ret != 0) {\n        return ret;\n    }\n\n    memset(raw_tmp, 0, 2 * coordinate_size);\n\n    /* Extract r */\n    ret = convert_der_to_raw_single_int(p, data_len, raw_tmp, coordinate_size);\n    if (ret < 0) {\n        return ret;\n    }\n    p += ret;\n    data_len -= ret;\n\n    /* Extract s */\n    ret = convert_der_to_raw_single_int(p, data_len, raw_tmp + coordinate_size,\n                                        coordinate_size);\n    if (ret < 0) {\n        return ret;\n    }\n    p += ret;\n    data_len -= ret;\n\n    /* Check that we consumed all the input der data. */\n    if ((size_t) (p - der) != der_len) {\n        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;\n    }\n\n    memcpy(raw, raw_tmp, 2 * coordinate_size);\n    *raw_len = 2 * coordinate_size;\n\n    return 0;\n}\n\n#endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/psa_util_internal.h",
    "content": "/**\n * \\file psa_util_internal.h\n *\n * \\brief Internal utility functions for use of PSA Crypto.\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_PSA_UTIL_INTERNAL_H\n#define MBEDTLS_PSA_UTIL_INTERNAL_H\n\n/* Include the public header so that users only need one include. */\n#include \"mbedtls/psa_util.h\"\n\n#include \"psa/crypto.h\"\n\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)\n\n/*************************************************************************\n * FFDH\n ************************************************************************/\n\n#define MBEDTLS_PSA_MAX_FFDH_PUBKEY_LENGTH \\\n    PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS)\n\n/*************************************************************************\n * ECC\n ************************************************************************/\n\n#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH \\\n    PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)\n\n#define MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH \\\n    PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)\n\n/*************************************************************************\n * Error translation\n ************************************************************************/\n\ntypedef struct {\n    /* Error codes used by PSA crypto are in -255..-128, fitting in 16 bits. */\n    int16_t psa_status;\n    /* Error codes used by Mbed TLS are in one of the ranges\n     * -127..-1 (low-level) or -32767..-4096 (high-level with a low-level\n     * code optionally added), fitting in 16 bits. */\n    int16_t mbedtls_error;\n} mbedtls_error_pair_t;\n\n#if defined(MBEDTLS_MD_LIGHT)\nextern const mbedtls_error_pair_t psa_to_md_errors[4];\n#endif\n\n#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)\nextern const mbedtls_error_pair_t psa_to_cipher_errors[4];\n#endif\n\n#if defined(MBEDTLS_LMS_C)\nextern const mbedtls_error_pair_t psa_to_lms_errors[3];\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)\nextern const mbedtls_error_pair_t psa_to_ssl_errors[7];\n#endif\n\n#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ||    \\\n    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)\nextern const mbedtls_error_pair_t psa_to_pk_rsa_errors[8];\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && \\\n    defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)\nextern const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[7];\n#endif\n\n/* Generic fallback function for error translation,\n * when the received state was not module-specific. */\nint psa_generic_status_to_mbedtls(psa_status_t status);\n\n/* This function iterates over provided local error translations,\n * and if no match was found - calls the fallback error translation function. */\nint psa_status_to_mbedtls(psa_status_t status,\n                          const mbedtls_error_pair_t *local_translations,\n                          size_t local_errors_num,\n                          int (*fallback_f)(psa_status_t));\n\n/* The second out of three-stage error handling functions of the pk module,\n * acts as a fallback after RSA / ECDSA error translation, and if no match\n * is found, it itself calls psa_generic_status_to_mbedtls. */\nint psa_pk_status_to_mbedtls(psa_status_t status);\n\n/* Utility macro to shorten the defines of error translator in modules. */\n#define PSA_TO_MBEDTLS_ERR_LIST(status, error_list, fallback_f)       \\\n    psa_status_to_mbedtls(status, error_list,                         \\\n                          sizeof(error_list)/sizeof(error_list[0]),   \\\n                          fallback_f)\n\n#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */\n#endif /* MBEDTLS_PSA_UTIL_INTERNAL_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ripemd160.c",
    "content": "/*\n *  RIPE MD-160 implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n *  The RIPEMD-160 algorithm was designed by RIPE in 1996\n *  http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html\n *  http://ehash.iaik.tugraz.at/wiki/RIPEMD-160\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_RIPEMD160_C)\n\n#include \"mbedtls/ripemd160.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#if !defined(MBEDTLS_RIPEMD160_ALT)\n\nvoid mbedtls_ripemd160_init(mbedtls_ripemd160_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_ripemd160_context));\n}\n\nvoid mbedtls_ripemd160_free(mbedtls_ripemd160_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ripemd160_context));\n}\n\nvoid mbedtls_ripemd160_clone(mbedtls_ripemd160_context *dst,\n                             const mbedtls_ripemd160_context *src)\n{\n    *dst = *src;\n}\n\n/*\n * RIPEMD-160 context setup\n */\nint mbedtls_ripemd160_starts(mbedtls_ripemd160_context *ctx)\n{\n    ctx->total[0] = 0;\n    ctx->total[1] = 0;\n\n    ctx->state[0] = 0x67452301;\n    ctx->state[1] = 0xEFCDAB89;\n    ctx->state[2] = 0x98BADCFE;\n    ctx->state[3] = 0x10325476;\n    ctx->state[4] = 0xC3D2E1F0;\n\n    return 0;\n}\n\n#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT)\n/*\n * Process one block\n */\nint mbedtls_internal_ripemd160_process(mbedtls_ripemd160_context *ctx,\n                                       const unsigned char data[64])\n{\n    struct {\n        uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16];\n    } local;\n\n    local.X[0] = MBEDTLS_GET_UINT32_LE(data,  0);\n    local.X[1] = MBEDTLS_GET_UINT32_LE(data,  4);\n    local.X[2] = MBEDTLS_GET_UINT32_LE(data,  8);\n    local.X[3] = MBEDTLS_GET_UINT32_LE(data, 12);\n    local.X[4] = MBEDTLS_GET_UINT32_LE(data, 16);\n    local.X[5] = MBEDTLS_GET_UINT32_LE(data, 20);\n    local.X[6] = MBEDTLS_GET_UINT32_LE(data, 24);\n    local.X[7] = MBEDTLS_GET_UINT32_LE(data, 28);\n    local.X[8] = MBEDTLS_GET_UINT32_LE(data, 32);\n    local.X[9] = MBEDTLS_GET_UINT32_LE(data, 36);\n    local.X[10] = MBEDTLS_GET_UINT32_LE(data, 40);\n    local.X[11] = MBEDTLS_GET_UINT32_LE(data, 44);\n    local.X[12] = MBEDTLS_GET_UINT32_LE(data, 48);\n    local.X[13] = MBEDTLS_GET_UINT32_LE(data, 52);\n    local.X[14] = MBEDTLS_GET_UINT32_LE(data, 56);\n    local.X[15] = MBEDTLS_GET_UINT32_LE(data, 60);\n\n    local.A = local.Ap = ctx->state[0];\n    local.B = local.Bp = ctx->state[1];\n    local.C = local.Cp = ctx->state[2];\n    local.D = local.Dp = ctx->state[3];\n    local.E = local.Ep = ctx->state[4];\n\n#define F1(x, y, z)   ((x) ^ (y) ^ (z))\n#define F2(x, y, z)   (((x) & (y)) | (~(x) & (z)))\n#define F3(x, y, z)   (((x) | ~(y)) ^ (z))\n#define F4(x, y, z)   (((x) & (z)) | ((y) & ~(z)))\n#define F5(x, y, z)   ((x) ^ ((y) | ~(z)))\n\n#define S(x, n) (((x) << (n)) | ((x) >> (32 - (n))))\n\n#define P(a, b, c, d, e, r, s, f, k)                      \\\n    do                                                      \\\n    {                                                       \\\n        (a) += f((b), (c), (d)) + local.X[r] + (k);       \\\n        (a) = S((a), (s)) + (e);                          \\\n        (c) = S((c), 10);                                 \\\n    } while (0)\n\n#define P2(a, b, c, d, e, r, s, rp, sp)                               \\\n    do                                                                  \\\n    {                                                                   \\\n        P((a), (b), (c), (d), (e), (r), (s), F, K);                   \\\n        P(a ## p, b ## p, c ## p, d ## p, e ## p,                      \\\n          (rp), (sp), Fp, Kp);                                        \\\n    } while (0)\n\n#define F   F1\n#define K   0x00000000\n#define Fp  F5\n#define Kp  0x50A28BE6\n    P2(local.A, local.B, local.C, local.D, local.E,  0, 11,  5,  8);\n    P2(local.E, local.A, local.B, local.C, local.D,  1, 14, 14,  9);\n    P2(local.D, local.E, local.A, local.B, local.C,  2, 15,  7,  9);\n    P2(local.C, local.D, local.E, local.A, local.B,  3, 12,  0, 11);\n    P2(local.B, local.C, local.D, local.E, local.A,  4,  5,  9, 13);\n    P2(local.A, local.B, local.C, local.D, local.E,  5,  8,  2, 15);\n    P2(local.E, local.A, local.B, local.C, local.D,  6,  7, 11, 15);\n    P2(local.D, local.E, local.A, local.B, local.C,  7,  9,  4,  5);\n    P2(local.C, local.D, local.E, local.A, local.B,  8, 11, 13,  7);\n    P2(local.B, local.C, local.D, local.E, local.A,  9, 13,  6,  7);\n    P2(local.A, local.B, local.C, local.D, local.E, 10, 14, 15,  8);\n    P2(local.E, local.A, local.B, local.C, local.D, 11, 15,  8, 11);\n    P2(local.D, local.E, local.A, local.B, local.C, 12,  6,  1, 14);\n    P2(local.C, local.D, local.E, local.A, local.B, 13,  7, 10, 14);\n    P2(local.B, local.C, local.D, local.E, local.A, 14,  9,  3, 12);\n    P2(local.A, local.B, local.C, local.D, local.E, 15,  8, 12,  6);\n#undef F\n#undef K\n#undef Fp\n#undef Kp\n\n#define F   F2\n#define K   0x5A827999\n#define Fp  F4\n#define Kp  0x5C4DD124\n    P2(local.E, local.A, local.B, local.C, local.D,  7,  7,  6,  9);\n    P2(local.D, local.E, local.A, local.B, local.C,  4,  6, 11, 13);\n    P2(local.C, local.D, local.E, local.A, local.B, 13,  8,  3, 15);\n    P2(local.B, local.C, local.D, local.E, local.A,  1, 13,  7,  7);\n    P2(local.A, local.B, local.C, local.D, local.E, 10, 11,  0, 12);\n    P2(local.E, local.A, local.B, local.C, local.D,  6,  9, 13,  8);\n    P2(local.D, local.E, local.A, local.B, local.C, 15,  7,  5,  9);\n    P2(local.C, local.D, local.E, local.A, local.B,  3, 15, 10, 11);\n    P2(local.B, local.C, local.D, local.E, local.A, 12,  7, 14,  7);\n    P2(local.A, local.B, local.C, local.D, local.E,  0, 12, 15,  7);\n    P2(local.E, local.A, local.B, local.C, local.D,  9, 15,  8, 12);\n    P2(local.D, local.E, local.A, local.B, local.C,  5,  9, 12,  7);\n    P2(local.C, local.D, local.E, local.A, local.B,  2, 11,  4,  6);\n    P2(local.B, local.C, local.D, local.E, local.A, 14,  7,  9, 15);\n    P2(local.A, local.B, local.C, local.D, local.E, 11, 13,  1, 13);\n    P2(local.E, local.A, local.B, local.C, local.D,  8, 12,  2, 11);\n#undef F\n#undef K\n#undef Fp\n#undef Kp\n\n#define F   F3\n#define K   0x6ED9EBA1\n#define Fp  F3\n#define Kp  0x6D703EF3\n    P2(local.D, local.E, local.A, local.B, local.C,  3, 11, 15,  9);\n    P2(local.C, local.D, local.E, local.A, local.B, 10, 13,  5,  7);\n    P2(local.B, local.C, local.D, local.E, local.A, 14,  6,  1, 15);\n    P2(local.A, local.B, local.C, local.D, local.E,  4,  7,  3, 11);\n    P2(local.E, local.A, local.B, local.C, local.D,  9, 14,  7,  8);\n    P2(local.D, local.E, local.A, local.B, local.C, 15,  9, 14,  6);\n    P2(local.C, local.D, local.E, local.A, local.B,  8, 13,  6,  6);\n    P2(local.B, local.C, local.D, local.E, local.A,  1, 15,  9, 14);\n    P2(local.A, local.B, local.C, local.D, local.E,  2, 14, 11, 12);\n    P2(local.E, local.A, local.B, local.C, local.D,  7,  8,  8, 13);\n    P2(local.D, local.E, local.A, local.B, local.C,  0, 13, 12,  5);\n    P2(local.C, local.D, local.E, local.A, local.B,  6,  6,  2, 14);\n    P2(local.B, local.C, local.D, local.E, local.A, 13,  5, 10, 13);\n    P2(local.A, local.B, local.C, local.D, local.E, 11, 12,  0, 13);\n    P2(local.E, local.A, local.B, local.C, local.D,  5,  7,  4,  7);\n    P2(local.D, local.E, local.A, local.B, local.C, 12,  5, 13,  5);\n#undef F\n#undef K\n#undef Fp\n#undef Kp\n\n#define F   F4\n#define K   0x8F1BBCDC\n#define Fp  F2\n#define Kp  0x7A6D76E9\n    P2(local.C, local.D, local.E, local.A, local.B,  1, 11,  8, 15);\n    P2(local.B, local.C, local.D, local.E, local.A,  9, 12,  6,  5);\n    P2(local.A, local.B, local.C, local.D, local.E, 11, 14,  4,  8);\n    P2(local.E, local.A, local.B, local.C, local.D, 10, 15,  1, 11);\n    P2(local.D, local.E, local.A, local.B, local.C,  0, 14,  3, 14);\n    P2(local.C, local.D, local.E, local.A, local.B,  8, 15, 11, 14);\n    P2(local.B, local.C, local.D, local.E, local.A, 12,  9, 15,  6);\n    P2(local.A, local.B, local.C, local.D, local.E,  4,  8,  0, 14);\n    P2(local.E, local.A, local.B, local.C, local.D, 13,  9,  5,  6);\n    P2(local.D, local.E, local.A, local.B, local.C,  3, 14, 12,  9);\n    P2(local.C, local.D, local.E, local.A, local.B,  7,  5,  2, 12);\n    P2(local.B, local.C, local.D, local.E, local.A, 15,  6, 13,  9);\n    P2(local.A, local.B, local.C, local.D, local.E, 14,  8,  9, 12);\n    P2(local.E, local.A, local.B, local.C, local.D,  5,  6,  7,  5);\n    P2(local.D, local.E, local.A, local.B, local.C,  6,  5, 10, 15);\n    P2(local.C, local.D, local.E, local.A, local.B,  2, 12, 14,  8);\n#undef F\n#undef K\n#undef Fp\n#undef Kp\n\n#define F   F5\n#define K   0xA953FD4E\n#define Fp  F1\n#define Kp  0x00000000\n    P2(local.B, local.C, local.D, local.E, local.A,  4,  9, 12,  8);\n    P2(local.A, local.B, local.C, local.D, local.E,  0, 15, 15,  5);\n    P2(local.E, local.A, local.B, local.C, local.D,  5,  5, 10, 12);\n    P2(local.D, local.E, local.A, local.B, local.C,  9, 11,  4,  9);\n    P2(local.C, local.D, local.E, local.A, local.B,  7,  6,  1, 12);\n    P2(local.B, local.C, local.D, local.E, local.A, 12,  8,  5,  5);\n    P2(local.A, local.B, local.C, local.D, local.E,  2, 13,  8, 14);\n    P2(local.E, local.A, local.B, local.C, local.D, 10, 12,  7,  6);\n    P2(local.D, local.E, local.A, local.B, local.C, 14,  5,  6,  8);\n    P2(local.C, local.D, local.E, local.A, local.B,  1, 12,  2, 13);\n    P2(local.B, local.C, local.D, local.E, local.A,  3, 13, 13,  6);\n    P2(local.A, local.B, local.C, local.D, local.E,  8, 14, 14,  5);\n    P2(local.E, local.A, local.B, local.C, local.D, 11, 11,  0, 15);\n    P2(local.D, local.E, local.A, local.B, local.C,  6,  8,  3, 13);\n    P2(local.C, local.D, local.E, local.A, local.B, 15,  5,  9, 11);\n    P2(local.B, local.C, local.D, local.E, local.A, 13,  6, 11, 11);\n#undef F\n#undef K\n#undef Fp\n#undef Kp\n\n    local.C       = ctx->state[1] + local.C + local.Dp;\n    ctx->state[1] = ctx->state[2] + local.D + local.Ep;\n    ctx->state[2] = ctx->state[3] + local.E + local.Ap;\n    ctx->state[3] = ctx->state[4] + local.A + local.Bp;\n    ctx->state[4] = ctx->state[0] + local.B + local.Cp;\n    ctx->state[0] = local.C;\n\n    /* Zeroise variables to clear sensitive data from memory. */\n    mbedtls_platform_zeroize(&local, sizeof(local));\n\n    return 0;\n}\n\n#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */\n\n/*\n * RIPEMD-160 process buffer\n */\nint mbedtls_ripemd160_update(mbedtls_ripemd160_context *ctx,\n                             const unsigned char *input,\n                             size_t ilen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t fill;\n    uint32_t left;\n\n    if (ilen == 0) {\n        return 0;\n    }\n\n    left = ctx->total[0] & 0x3F;\n    fill = 64 - left;\n\n    ctx->total[0] += (uint32_t) ilen;\n    ctx->total[0] &= 0xFFFFFFFF;\n\n    if (ctx->total[0] < (uint32_t) ilen) {\n        ctx->total[1]++;\n    }\n\n    if (left && ilen >= fill) {\n        memcpy((void *) (ctx->buffer + left), input, fill);\n\n        if ((ret = mbedtls_internal_ripemd160_process(ctx, ctx->buffer)) != 0) {\n            return ret;\n        }\n\n        input += fill;\n        ilen  -= fill;\n        left = 0;\n    }\n\n    while (ilen >= 64) {\n        if ((ret = mbedtls_internal_ripemd160_process(ctx, input)) != 0) {\n            return ret;\n        }\n\n        input += 64;\n        ilen  -= 64;\n    }\n\n    if (ilen > 0) {\n        memcpy((void *) (ctx->buffer + left), input, ilen);\n    }\n\n    return 0;\n}\n\nstatic const unsigned char ripemd160_padding[64] =\n{\n    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n};\n\n/*\n * RIPEMD-160 final digest\n */\nint mbedtls_ripemd160_finish(mbedtls_ripemd160_context *ctx,\n                             unsigned char output[20])\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    uint32_t last, padn;\n    uint32_t high, low;\n    unsigned char msglen[8];\n\n    high = (ctx->total[0] >> 29)\n           | (ctx->total[1] <<  3);\n    low  = (ctx->total[0] <<  3);\n\n    MBEDTLS_PUT_UINT32_LE(low,  msglen, 0);\n    MBEDTLS_PUT_UINT32_LE(high, msglen, 4);\n\n    last = ctx->total[0] & 0x3F;\n    padn = (last < 56) ? (56 - last) : (120 - last);\n\n    ret = mbedtls_ripemd160_update(ctx, ripemd160_padding, padn);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    ret = mbedtls_ripemd160_update(ctx, msglen, 8);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    MBEDTLS_PUT_UINT32_LE(ctx->state[0], output,  0);\n    MBEDTLS_PUT_UINT32_LE(ctx->state[1], output,  4);\n    MBEDTLS_PUT_UINT32_LE(ctx->state[2], output,  8);\n    MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12);\n    MBEDTLS_PUT_UINT32_LE(ctx->state[4], output, 16);\n\n    ret = 0;\n\nexit:\n    mbedtls_ripemd160_free(ctx);\n    return ret;\n}\n\n#endif /* ! MBEDTLS_RIPEMD160_ALT */\n\n/*\n * output = RIPEMD-160( input buffer )\n */\nint mbedtls_ripemd160(const unsigned char *input,\n                      size_t ilen,\n                      unsigned char output[20])\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ripemd160_context ctx;\n\n    mbedtls_ripemd160_init(&ctx);\n\n    if ((ret = mbedtls_ripemd160_starts(&ctx)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_ripemd160_update(&ctx, input, ilen)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_ripemd160_finish(&ctx, output)) != 0) {\n        goto exit;\n    }\n\nexit:\n    mbedtls_ripemd160_free(&ctx);\n\n    return ret;\n}\n\n#if defined(MBEDTLS_SELF_TEST)\n/*\n * Test vectors from the RIPEMD-160 paper and\n * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC\n */\n#define TESTS   8\nstatic const unsigned char ripemd160_test_str[TESTS][81] =\n{\n    { \"\" },\n    { \"a\" },\n    { \"abc\" },\n    { \"message digest\" },\n    { \"abcdefghijklmnopqrstuvwxyz\" },\n    { \"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\" },\n    { \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" },\n    { \"12345678901234567890123456789012345678901234567890123456789012345678901234567890\" },\n};\n\nstatic const size_t ripemd160_test_strlen[TESTS] =\n{\n    0, 1, 3, 14, 26, 56, 62, 80\n};\n\nstatic const unsigned char ripemd160_test_md[TESTS][20] =\n{\n    { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28,\n      0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 },\n    { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae,\n      0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe },\n    { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04,\n      0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc },\n    { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8,\n      0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 },\n    { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb,\n      0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc },\n    { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05,\n      0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b },\n    { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed,\n      0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 },\n    { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb,\n      0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb },\n};\n\n/*\n * Checkup routine\n */\nint mbedtls_ripemd160_self_test(int verbose)\n{\n    int i, ret = 0;\n    unsigned char output[20];\n\n    memset(output, 0, sizeof(output));\n\n    for (i = 0; i < TESTS; i++) {\n        if (verbose != 0) {\n            mbedtls_printf(\"  RIPEMD-160 test #%d: \", i + 1);\n        }\n\n        ret = mbedtls_ripemd160(ripemd160_test_str[i],\n                                ripemd160_test_strlen[i], output);\n        if (ret != 0) {\n            goto fail;\n        }\n\n        if (memcmp(output, ripemd160_test_md[i], 20) != 0) {\n            ret = 1;\n            goto fail;\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    return 0;\n\nfail:\n    if (verbose != 0) {\n        mbedtls_printf(\"failed\\n\");\n    }\n\n    return ret;\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_RIPEMD160_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/rsa.c",
    "content": "/*\n *  The RSA public-key cryptosystem\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n *  The following sources were referenced in the design of this implementation\n *  of the RSA algorithm:\n *\n *  [1] A method for obtaining digital signatures and public-key cryptosystems\n *      R Rivest, A Shamir, and L Adleman\n *      http://people.csail.mit.edu/rivest/pubs.html#RSA78\n *\n *  [2] Handbook of Applied Cryptography - 1997, Chapter 8\n *      Menezes, van Oorschot and Vanstone\n *\n *  [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks\n *      Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and\n *      Stefan Mangard\n *      https://arxiv.org/abs/1702.08719v2\n *\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_RSA_C)\n\n#include \"mbedtls/rsa.h\"\n#include \"bignum_core.h\"\n#include \"bignum_internal.h\"\n#include \"rsa_alt_helpers.h\"\n#include \"rsa_internal.h\"\n#include \"mbedtls/oid.h\"\n#include \"mbedtls/asn1write.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n#include \"constant_time_internal.h\"\n#include \"mbedtls/constant_time.h\"\n#include \"md_psa.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) && !defined(__NetBSD__)\n#include <stdlib.h>\n#endif\n\n#include \"mbedtls/platform.h\"\n\n/*\n * Wrapper around mbedtls_asn1_get_mpi() that rejects zero.\n *\n * The value zero is:\n * - never a valid value for an RSA parameter\n * - interpreted as \"omitted, please reconstruct\" by mbedtls_rsa_complete().\n *\n * Since values can't be omitted in PKCS#1, passing a zero value to\n * rsa_complete() would be incorrect, so reject zero values early.\n */\nstatic int asn1_get_nonzero_mpi(unsigned char **p,\n                                const unsigned char *end,\n                                mbedtls_mpi *X)\n{\n    int ret;\n\n    ret = mbedtls_asn1_get_mpi(p, end, X);\n    if (ret != 0) {\n        return ret;\n    }\n\n    if (mbedtls_mpi_cmp_int(X, 0) == 0) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    return 0;\n}\n\nint mbedtls_rsa_parse_key(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen)\n{\n    int ret, version;\n    size_t len;\n    unsigned char *p, *end;\n\n    mbedtls_mpi T;\n    mbedtls_mpi_init(&T);\n\n    p = (unsigned char *) key;\n    end = p + keylen;\n\n    /*\n     * This function parses the RSAPrivateKey (PKCS#1)\n     *\n     *  RSAPrivateKey ::= SEQUENCE {\n     *      version           Version,\n     *      modulus           INTEGER,  -- n\n     *      publicExponent    INTEGER,  -- e\n     *      privateExponent   INTEGER,  -- d\n     *      prime1            INTEGER,  -- p\n     *      prime2            INTEGER,  -- q\n     *      exponent1         INTEGER,  -- d mod (p-1)\n     *      exponent2         INTEGER,  -- d mod (q-1)\n     *      coefficient       INTEGER,  -- (inverse of q) mod p\n     *      otherPrimeInfos   OtherPrimeInfos OPTIONAL\n     *  }\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return ret;\n    }\n\n    if (end != p + len) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {\n        return ret;\n    }\n\n    if (version != 0) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    /* Import N */\n    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||\n        (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL,\n                                  NULL, NULL)) != 0) {\n        goto cleanup;\n    }\n\n    /* Import E */\n    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||\n        (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,\n                                  NULL, &T)) != 0) {\n        goto cleanup;\n    }\n\n    /* Import D */\n    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||\n        (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,\n                                  &T, NULL)) != 0) {\n        goto cleanup;\n    }\n\n    /* Import P */\n    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||\n        (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL,\n                                  NULL, NULL)) != 0) {\n        goto cleanup;\n    }\n\n    /* Import Q */\n    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||\n        (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T,\n                                  NULL, NULL)) != 0) {\n        goto cleanup;\n    }\n\n#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT)\n    /*\n     * The RSA CRT parameters DP, DQ and QP are nominally redundant, in\n     * that they can be easily recomputed from D, P and Q. However by\n     * parsing them from the PKCS1 structure it is possible to avoid\n     * recalculating them which both reduces the overhead of loading\n     * RSA private keys into memory and also avoids side channels which\n     * can arise when computing those values, since all of D, P, and Q\n     * are secret. See https://eprint.iacr.org/2020/055 for a\n     * description of one such attack.\n     */\n\n    /* Import DP */\n    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||\n        (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) {\n        goto cleanup;\n    }\n\n    /* Import DQ */\n    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||\n        (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) {\n        goto cleanup;\n    }\n\n    /* Import QP */\n    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||\n        (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) {\n        goto cleanup;\n    }\n\n#else\n    /* Verify existence of the CRT params */\n    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||\n        (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||\n        (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) {\n        goto cleanup;\n    }\n#endif\n\n    /* rsa_complete() doesn't complete anything with the default\n     * implementation but is still called:\n     * - for the benefit of alternative implementation that may want to\n     *   pre-compute stuff beyond what's provided (eg Montgomery factors)\n     * - as is also sanity-checks the key\n     *\n     * Furthermore, we also check the public part for consistency with\n     * mbedtls_pk_parse_pubkey(), as it includes size minima for example.\n     */\n    if ((ret = mbedtls_rsa_complete(rsa)) != 0 ||\n        (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) {\n        goto cleanup;\n    }\n\n    if (p != end) {\n        ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;\n    }\n\ncleanup:\n\n    mbedtls_mpi_free(&T);\n\n    if (ret != 0) {\n        mbedtls_rsa_free(rsa);\n    }\n\n    return ret;\n}\n\nint mbedtls_rsa_parse_pubkey(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen)\n{\n    unsigned char *p = (unsigned char *) key;\n    unsigned char *end = (unsigned char *) (key + keylen);\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n\n    /*\n     *  RSAPublicKey ::= SEQUENCE {\n     *      modulus           INTEGER,  -- n\n     *      publicExponent    INTEGER   -- e\n     *  }\n     */\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return ret;\n    }\n\n    if (end != p + len) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    /* Import N */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_rsa_import_raw(rsa, p, len, NULL, 0, NULL, 0,\n                                      NULL, 0, NULL, 0)) != 0) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    p += len;\n\n    /* Import E */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0,\n                                      NULL, 0, p, len)) != 0) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    p += len;\n\n    if (mbedtls_rsa_complete(rsa) != 0 ||\n        mbedtls_rsa_check_pubkey(rsa) != 0) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    if (p != end) {\n        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;\n    }\n\n    return 0;\n}\n\nint mbedtls_rsa_write_key(const mbedtls_rsa_context *rsa, unsigned char *start,\n                          unsigned char **p)\n{\n    size_t len = 0;\n    int ret;\n\n    mbedtls_mpi T; /* Temporary holding the exported parameters */\n\n    /*\n     * Export the parameters one after another to avoid simultaneous copies.\n     */\n\n    mbedtls_mpi_init(&T);\n\n    /* Export QP */\n    if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 ||\n        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {\n        goto end_of_export;\n    }\n    len += ret;\n\n    /* Export DQ */\n    if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 ||\n        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {\n        goto end_of_export;\n    }\n    len += ret;\n\n    /* Export DP */\n    if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 ||\n        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {\n        goto end_of_export;\n    }\n    len += ret;\n\n    /* Export Q */\n    if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, &T, NULL, NULL)) != 0 ||\n        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {\n        goto end_of_export;\n    }\n    len += ret;\n\n    /* Export P */\n    if ((ret = mbedtls_rsa_export(rsa, NULL, &T, NULL, NULL, NULL)) != 0 ||\n        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {\n        goto end_of_export;\n    }\n    len += ret;\n\n    /* Export D */\n    if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, &T, NULL)) != 0 ||\n        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {\n        goto end_of_export;\n    }\n    len += ret;\n\n    /* Export E */\n    if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||\n        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {\n        goto end_of_export;\n    }\n    len += ret;\n\n    /* Export N */\n    if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||\n        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {\n        goto end_of_export;\n    }\n    len += ret;\n\nend_of_export:\n\n    mbedtls_mpi_free(&T);\n    if (ret < 0) {\n        return ret;\n    }\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, start, 0));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,\n                                                     MBEDTLS_ASN1_CONSTRUCTED |\n                                                     MBEDTLS_ASN1_SEQUENCE));\n\n    return (int) len;\n}\n\n/*\n *  RSAPublicKey ::= SEQUENCE {\n *      modulus           INTEGER,  -- n\n *      publicExponent    INTEGER   -- e\n *  }\n */\nint mbedtls_rsa_write_pubkey(const mbedtls_rsa_context *rsa, unsigned char *start,\n                             unsigned char **p)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n    mbedtls_mpi T;\n\n    mbedtls_mpi_init(&T);\n\n    /* Export E */\n    if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||\n        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {\n        goto end_of_export;\n    }\n    len += ret;\n\n    /* Export N */\n    if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||\n        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {\n        goto end_of_export;\n    }\n    len += ret;\n\nend_of_export:\n\n    mbedtls_mpi_free(&T);\n    if (ret < 0) {\n        return ret;\n    }\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |\n                                                     MBEDTLS_ASN1_SEQUENCE));\n\n    return (int) len;\n}\n\n#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)\n\n/** This function performs the unpadding part of a PKCS#1 v1.5 decryption\n *  operation (EME-PKCS1-v1_5 decoding).\n *\n * \\note The return value from this function is a sensitive value\n *       (this is unusual). #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE shouldn't happen\n *       in a well-written application, but 0 vs #MBEDTLS_ERR_RSA_INVALID_PADDING\n *       is often a situation that an attacker can provoke and leaking which\n *       one is the result is precisely the information the attacker wants.\n *\n * \\param input          The input buffer which is the payload inside PKCS#1v1.5\n *                       encryption padding, called the \"encoded message EM\"\n *                       by the terminology.\n * \\param ilen           The length of the payload in the \\p input buffer.\n * \\param output         The buffer for the payload, called \"message M\" by the\n *                       PKCS#1 terminology. This must be a writable buffer of\n *                       length \\p output_max_len bytes.\n * \\param olen           The address at which to store the length of\n *                       the payload. This must not be \\c NULL.\n * \\param output_max_len The length in bytes of the output buffer \\p output.\n *\n * \\return      \\c 0 on success.\n * \\return      #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE\n *              The output buffer is too small for the unpadded payload.\n * \\return      #MBEDTLS_ERR_RSA_INVALID_PADDING\n *              The input doesn't contain properly formatted padding.\n */\nstatic int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input,\n                                                size_t ilen,\n                                                unsigned char *output,\n                                                size_t output_max_len,\n                                                size_t *olen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t i, plaintext_max_size;\n\n    /* The following variables take sensitive values: their value must\n     * not leak into the observable behavior of the function other than\n     * the designated outputs (output, olen, return value). Otherwise\n     * this would open the execution of the function to\n     * side-channel-based variants of the Bleichenbacher padding oracle\n     * attack. Potential side channels include overall timing, memory\n     * access patterns (especially visible to an adversary who has access\n     * to a shared memory cache), and branches (especially visible to\n     * an adversary who has access to a shared code cache or to a shared\n     * branch predictor). */\n    size_t pad_count = 0;\n    mbedtls_ct_condition_t bad;\n    mbedtls_ct_condition_t pad_done;\n    size_t plaintext_size = 0;\n    mbedtls_ct_condition_t output_too_large;\n\n    plaintext_max_size = (output_max_len > ilen - 11) ? ilen - 11\n                                                        : output_max_len;\n\n    /* Check and get padding length in constant time and constant\n     * memory trace. The first byte must be 0. */\n    bad = mbedtls_ct_bool(input[0]);\n\n\n    /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00\n     * where PS must be at least 8 nonzero bytes. */\n    bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_ne(input[1], MBEDTLS_RSA_CRYPT));\n\n    /* Read the whole buffer. Set pad_done to nonzero if we find\n     * the 0x00 byte and remember the padding length in pad_count. */\n    pad_done = MBEDTLS_CT_FALSE;\n    for (i = 2; i < ilen; i++) {\n        mbedtls_ct_condition_t found = mbedtls_ct_uint_eq(input[i], 0);\n        pad_done   = mbedtls_ct_bool_or(pad_done, found);\n        pad_count += mbedtls_ct_uint_if_else_0(mbedtls_ct_bool_not(pad_done), 1);\n    }\n\n    /* If pad_done is still zero, there's no data, only unfinished padding. */\n    bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_not(pad_done));\n\n    /* There must be at least 8 bytes of padding. */\n    bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_gt(8, pad_count));\n\n    /* If the padding is valid, set plaintext_size to the number of\n     * remaining bytes after stripping the padding. If the padding\n     * is invalid, avoid leaking this fact through the size of the\n     * output: use the maximum message size that fits in the output\n     * buffer. Do it without branches to avoid leaking the padding\n     * validity through timing. RSA keys are small enough that all the\n     * size_t values involved fit in unsigned int. */\n    plaintext_size = mbedtls_ct_uint_if(\n        bad, (unsigned) plaintext_max_size,\n        (unsigned) (ilen - pad_count - 3));\n\n    /* Set output_too_large to 0 if the plaintext fits in the output\n     * buffer and to 1 otherwise. */\n    output_too_large = mbedtls_ct_uint_gt(plaintext_size,\n                                          plaintext_max_size);\n\n    /* Set ret without branches to avoid timing attacks. Return:\n     * - INVALID_PADDING if the padding is bad (bad != 0).\n     * - OUTPUT_TOO_LARGE if the padding is good but the decrypted\n     *   plaintext does not fit in the output buffer.\n     * - 0 if the padding is correct. */\n    ret = mbedtls_ct_error_if(\n        bad,\n        MBEDTLS_ERR_RSA_INVALID_PADDING,\n        mbedtls_ct_error_if_else_0(output_too_large, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE)\n        );\n\n    /* If the padding is bad or the plaintext is too large, zero the\n     * data that we're about to copy to the output buffer.\n     * We need to copy the same amount of data\n     * from the same buffer whether the padding is good or not to\n     * avoid leaking the padding validity through overall timing or\n     * through memory or cache access patterns. */\n    mbedtls_ct_zeroize_if(mbedtls_ct_bool_or(bad, output_too_large), input + 11, ilen - 11);\n\n    /* If the plaintext is too large, truncate it to the buffer size.\n     * Copy anyway to avoid revealing the length through timing, because\n     * revealing the length is as bad as revealing the padding validity\n     * for a Bleichenbacher attack. */\n    plaintext_size = mbedtls_ct_uint_if(output_too_large,\n                                        (unsigned) plaintext_max_size,\n                                        (unsigned) plaintext_size);\n\n    /* Move the plaintext to the leftmost position where it can start in\n     * the working buffer, i.e. make it start plaintext_max_size from\n     * the end of the buffer. Do this with a memory access trace that\n     * does not depend on the plaintext size. After this move, the\n     * starting location of the plaintext is no longer sensitive\n     * information. */\n    mbedtls_ct_memmove_left(input + ilen - plaintext_max_size,\n                            plaintext_max_size,\n                            plaintext_max_size - plaintext_size);\n\n    /* Finally copy the decrypted plaintext plus trailing zeros into the output\n     * buffer. If output_max_len is 0, then output may be an invalid pointer\n     * and the result of memcpy() would be undefined; prevent undefined\n     * behavior making sure to depend only on output_max_len (the size of the\n     * user-provided output buffer), which is independent from plaintext\n     * length, validity of padding, success of the decryption, and other\n     * secrets. */\n    if (output_max_len != 0) {\n        memcpy(output, input + ilen - plaintext_max_size, plaintext_max_size);\n    }\n\n    /* Report the amount of data we copied to the output buffer. In case\n     * of errors (bad padding or output too large), the value of *olen\n     * when this function returns is not specified. Making it equivalent\n     * to the good case limits the risks of leaking the padding validity. */\n    *olen = plaintext_size;\n\n    return ret;\n}\n\n#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */\n\n#if !defined(MBEDTLS_RSA_ALT)\n\nint mbedtls_rsa_import(mbedtls_rsa_context *ctx,\n                       const mbedtls_mpi *N,\n                       const mbedtls_mpi *P, const mbedtls_mpi *Q,\n                       const mbedtls_mpi *D, const mbedtls_mpi *E)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if ((N != NULL && (ret = mbedtls_mpi_copy(&ctx->N, N)) != 0) ||\n        (P != NULL && (ret = mbedtls_mpi_copy(&ctx->P, P)) != 0) ||\n        (Q != NULL && (ret = mbedtls_mpi_copy(&ctx->Q, Q)) != 0) ||\n        (D != NULL && (ret = mbedtls_mpi_copy(&ctx->D, D)) != 0) ||\n        (E != NULL && (ret = mbedtls_mpi_copy(&ctx->E, E)) != 0)) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);\n    }\n\n    if (N != NULL) {\n        ctx->len = mbedtls_mpi_size(&ctx->N);\n    }\n\n    return 0;\n}\n\nint mbedtls_rsa_import_raw(mbedtls_rsa_context *ctx,\n                           unsigned char const *N, size_t N_len,\n                           unsigned char const *P, size_t P_len,\n                           unsigned char const *Q, size_t Q_len,\n                           unsigned char const *D, size_t D_len,\n                           unsigned char const *E, size_t E_len)\n{\n    int ret = 0;\n\n    if (N != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->N, N, N_len));\n        ctx->len = mbedtls_mpi_size(&ctx->N);\n    }\n\n    if (P != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->P, P, P_len));\n    }\n\n    if (Q != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->Q, Q, Q_len));\n    }\n\n    if (D != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->D, D, D_len));\n    }\n\n    if (E != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->E, E, E_len));\n    }\n\ncleanup:\n\n    if (ret != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);\n    }\n\n    return 0;\n}\n\n/*\n * Checks whether the context fields are set in such a way\n * that the RSA primitives will be able to execute without error.\n * It does *not* make guarantees for consistency of the parameters.\n */\nstatic int rsa_check_context(mbedtls_rsa_context const *ctx, int is_priv,\n                             int blinding_needed)\n{\n#if !defined(MBEDTLS_RSA_NO_CRT)\n    /* blinding_needed is only used for NO_CRT to decide whether\n     * P,Q need to be present or not. */\n    ((void) blinding_needed);\n#endif\n\n    if (ctx->len != mbedtls_mpi_size(&ctx->N) ||\n        ctx->len > MBEDTLS_MPI_MAX_SIZE) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    /*\n     * 1. Modular exponentiation needs positive, odd moduli.\n     */\n\n    /* Modular exponentiation wrt. N is always used for\n     * RSA public key operations. */\n    if (mbedtls_mpi_cmp_int(&ctx->N, 0) <= 0 ||\n        mbedtls_mpi_get_bit(&ctx->N, 0) == 0) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n#if !defined(MBEDTLS_RSA_NO_CRT)\n    /* Modular exponentiation for P and Q is only\n     * used for private key operations and if CRT\n     * is used. */\n    if (is_priv &&\n        (mbedtls_mpi_cmp_int(&ctx->P, 0) <= 0 ||\n         mbedtls_mpi_get_bit(&ctx->P, 0) == 0 ||\n         mbedtls_mpi_cmp_int(&ctx->Q, 0) <= 0 ||\n         mbedtls_mpi_get_bit(&ctx->Q, 0) == 0)) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n#endif /* !MBEDTLS_RSA_NO_CRT */\n\n    /*\n     * 2. Exponents must be positive\n     */\n\n    /* Always need E for public key operations */\n    if (mbedtls_mpi_cmp_int(&ctx->E, 0) <= 0) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_RSA_NO_CRT)\n    /* For private key operations, use D or DP & DQ\n     * as (unblinded) exponents. */\n    if (is_priv && mbedtls_mpi_cmp_int(&ctx->D, 0) <= 0) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n#else\n    if (is_priv &&\n        (mbedtls_mpi_cmp_int(&ctx->DP, 0) <= 0 ||\n         mbedtls_mpi_cmp_int(&ctx->DQ, 0) <= 0)) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n#endif /* MBEDTLS_RSA_NO_CRT */\n\n    /* Blinding shouldn't make exponents negative either,\n     * so check that P, Q >= 1 if that hasn't yet been\n     * done as part of 1. */\n#if defined(MBEDTLS_RSA_NO_CRT)\n    if (is_priv && blinding_needed &&\n        (mbedtls_mpi_cmp_int(&ctx->P, 0) <= 0 ||\n         mbedtls_mpi_cmp_int(&ctx->Q, 0) <= 0)) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n#endif\n\n    /* It wouldn't lead to an error if it wasn't satisfied,\n     * but check for QP >= 1 nonetheless. */\n#if !defined(MBEDTLS_RSA_NO_CRT)\n    if (is_priv &&\n        mbedtls_mpi_cmp_int(&ctx->QP, 0) <= 0) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n#endif\n\n    return 0;\n}\n\nint mbedtls_rsa_complete(mbedtls_rsa_context *ctx)\n{\n    int ret = 0;\n    int have_N, have_P, have_Q, have_D, have_E;\n#if !defined(MBEDTLS_RSA_NO_CRT)\n    int have_DP, have_DQ, have_QP;\n#endif\n    int n_missing, pq_missing, d_missing, is_pub, is_priv;\n\n    have_N = (mbedtls_mpi_cmp_int(&ctx->N, 0) != 0);\n    have_P = (mbedtls_mpi_cmp_int(&ctx->P, 0) != 0);\n    have_Q = (mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0);\n    have_D = (mbedtls_mpi_cmp_int(&ctx->D, 0) != 0);\n    have_E = (mbedtls_mpi_cmp_int(&ctx->E, 0) != 0);\n\n#if !defined(MBEDTLS_RSA_NO_CRT)\n    have_DP = (mbedtls_mpi_cmp_int(&ctx->DP, 0) != 0);\n    have_DQ = (mbedtls_mpi_cmp_int(&ctx->DQ, 0) != 0);\n    have_QP = (mbedtls_mpi_cmp_int(&ctx->QP, 0) != 0);\n#endif\n\n    /*\n     * Check whether provided parameters are enough\n     * to deduce all others. The following incomplete\n     * parameter sets for private keys are supported:\n     *\n     * (1) P, Q missing.\n     * (2) D and potentially N missing.\n     *\n     */\n\n    n_missing  =              have_P &&  have_Q &&  have_D && have_E;\n    pq_missing =   have_N && !have_P && !have_Q &&  have_D && have_E;\n    d_missing  =              have_P &&  have_Q && !have_D && have_E;\n    is_pub     =   have_N && !have_P && !have_Q && !have_D && have_E;\n\n    /* These three alternatives are mutually exclusive */\n    is_priv = n_missing || pq_missing || d_missing;\n\n    if (!is_priv && !is_pub) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    /*\n     * Step 1: Deduce N if P, Q are provided.\n     */\n\n    if (!have_N && have_P && have_Q) {\n        if ((ret = mbedtls_mpi_mul_mpi(&ctx->N, &ctx->P,\n                                       &ctx->Q)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);\n        }\n\n        ctx->len = mbedtls_mpi_size(&ctx->N);\n    }\n\n    /*\n     * Step 2: Deduce and verify all remaining core parameters.\n     */\n\n    if (pq_missing) {\n        ret = mbedtls_rsa_deduce_primes(&ctx->N, &ctx->E, &ctx->D,\n                                        &ctx->P, &ctx->Q);\n        if (ret != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);\n        }\n\n    } else if (d_missing) {\n        if ((ret = mbedtls_rsa_deduce_private_exponent(&ctx->P,\n                                                       &ctx->Q,\n                                                       &ctx->E,\n                                                       &ctx->D)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);\n        }\n    }\n\n    /*\n     * Step 3: Deduce all additional parameters specific\n     *         to our current RSA implementation.\n     */\n\n#if !defined(MBEDTLS_RSA_NO_CRT)\n    if (is_priv && !(have_DP && have_DQ && have_QP)) {\n        ret = mbedtls_rsa_deduce_crt(&ctx->P,  &ctx->Q,  &ctx->D,\n                                     &ctx->DP, &ctx->DQ, &ctx->QP);\n        if (ret != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);\n        }\n    }\n#endif /* MBEDTLS_RSA_NO_CRT */\n\n    /*\n     * Step 3: Basic sanity checks\n     */\n\n    return rsa_check_context(ctx, is_priv, 1);\n}\n\nint mbedtls_rsa_export_raw(const mbedtls_rsa_context *ctx,\n                           unsigned char *N, size_t N_len,\n                           unsigned char *P, size_t P_len,\n                           unsigned char *Q, size_t Q_len,\n                           unsigned char *D, size_t D_len,\n                           unsigned char *E, size_t E_len)\n{\n    int ret = 0;\n    int is_priv;\n\n    /* Check if key is private or public */\n    is_priv =\n        mbedtls_mpi_cmp_int(&ctx->N, 0) != 0 &&\n        mbedtls_mpi_cmp_int(&ctx->P, 0) != 0 &&\n        mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0 &&\n        mbedtls_mpi_cmp_int(&ctx->D, 0) != 0 &&\n        mbedtls_mpi_cmp_int(&ctx->E, 0) != 0;\n\n    if (!is_priv) {\n        /* If we're trying to export private parameters for a public key,\n         * something must be wrong. */\n        if (P != NULL || Q != NULL || D != NULL) {\n            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n        }\n\n    }\n\n    if (N != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->N, N, N_len));\n    }\n\n    if (P != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->P, P, P_len));\n    }\n\n    if (Q != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->Q, Q, Q_len));\n    }\n\n    if (D != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->D, D, D_len));\n    }\n\n    if (E != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->E, E, E_len));\n    }\n\ncleanup:\n\n    return ret;\n}\n\nint mbedtls_rsa_export(const mbedtls_rsa_context *ctx,\n                       mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q,\n                       mbedtls_mpi *D, mbedtls_mpi *E)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    int is_priv;\n\n    /* Check if key is private or public */\n    is_priv =\n        mbedtls_mpi_cmp_int(&ctx->N, 0) != 0 &&\n        mbedtls_mpi_cmp_int(&ctx->P, 0) != 0 &&\n        mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0 &&\n        mbedtls_mpi_cmp_int(&ctx->D, 0) != 0 &&\n        mbedtls_mpi_cmp_int(&ctx->E, 0) != 0;\n\n    if (!is_priv) {\n        /* If we're trying to export private parameters for a public key,\n         * something must be wrong. */\n        if (P != NULL || Q != NULL || D != NULL) {\n            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n        }\n\n    }\n\n    /* Export all requested core parameters. */\n\n    if ((N != NULL && (ret = mbedtls_mpi_copy(N, &ctx->N)) != 0) ||\n        (P != NULL && (ret = mbedtls_mpi_copy(P, &ctx->P)) != 0) ||\n        (Q != NULL && (ret = mbedtls_mpi_copy(Q, &ctx->Q)) != 0) ||\n        (D != NULL && (ret = mbedtls_mpi_copy(D, &ctx->D)) != 0) ||\n        (E != NULL && (ret = mbedtls_mpi_copy(E, &ctx->E)) != 0)) {\n        return ret;\n    }\n\n    return 0;\n}\n\n/*\n * Export CRT parameters\n * This must also be implemented if CRT is not used, for being able to\n * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt\n * can be used in this case.\n */\nint mbedtls_rsa_export_crt(const mbedtls_rsa_context *ctx,\n                           mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    int is_priv;\n\n    /* Check if key is private or public */\n    is_priv =\n        mbedtls_mpi_cmp_int(&ctx->N, 0) != 0 &&\n        mbedtls_mpi_cmp_int(&ctx->P, 0) != 0 &&\n        mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0 &&\n        mbedtls_mpi_cmp_int(&ctx->D, 0) != 0 &&\n        mbedtls_mpi_cmp_int(&ctx->E, 0) != 0;\n\n    if (!is_priv) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n#if !defined(MBEDTLS_RSA_NO_CRT)\n    /* Export all requested blinding parameters. */\n    if ((DP != NULL && (ret = mbedtls_mpi_copy(DP, &ctx->DP)) != 0) ||\n        (DQ != NULL && (ret = mbedtls_mpi_copy(DQ, &ctx->DQ)) != 0) ||\n        (QP != NULL && (ret = mbedtls_mpi_copy(QP, &ctx->QP)) != 0)) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);\n    }\n#else\n    if ((ret = mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D,\n                                      DP, DQ, QP)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);\n    }\n#endif\n\n    return 0;\n}\n\n/*\n * Initialize an RSA context\n */\nvoid mbedtls_rsa_init(mbedtls_rsa_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_rsa_context));\n\n    ctx->padding = MBEDTLS_RSA_PKCS_V15;\n    ctx->hash_id = MBEDTLS_MD_NONE;\n\n#if defined(MBEDTLS_THREADING_C)\n    /* Set ctx->ver to nonzero to indicate that the mutex has been\n     * initialized and will need to be freed. */\n    ctx->ver = 1;\n    mbedtls_mutex_init(&ctx->mutex);\n#endif\n}\n\n/*\n * Set padding for an existing RSA context\n */\nint mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding,\n                            mbedtls_md_type_t hash_id)\n{\n    switch (padding) {\n#if defined(MBEDTLS_PKCS1_V15)\n        case MBEDTLS_RSA_PKCS_V15:\n            break;\n#endif\n\n#if defined(MBEDTLS_PKCS1_V21)\n        case MBEDTLS_RSA_PKCS_V21:\n            break;\n#endif\n        default:\n            return MBEDTLS_ERR_RSA_INVALID_PADDING;\n    }\n\n#if defined(MBEDTLS_PKCS1_V21)\n    if ((padding == MBEDTLS_RSA_PKCS_V21) &&\n        (hash_id != MBEDTLS_MD_NONE)) {\n        /* Just make sure this hash is supported in this build. */\n        if (mbedtls_md_info_from_type(hash_id) == NULL) {\n            return MBEDTLS_ERR_RSA_INVALID_PADDING;\n        }\n    }\n#endif /* MBEDTLS_PKCS1_V21 */\n\n    ctx->padding = padding;\n    ctx->hash_id = hash_id;\n\n    return 0;\n}\n\n/*\n * Get padding mode of initialized RSA context\n */\nint mbedtls_rsa_get_padding_mode(const mbedtls_rsa_context *ctx)\n{\n    return ctx->padding;\n}\n\n/*\n * Get hash identifier of mbedtls_md_type_t type\n */\nint mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx)\n{\n    return ctx->hash_id;\n}\n\n/*\n * Get length in bits of RSA modulus\n */\nsize_t mbedtls_rsa_get_bitlen(const mbedtls_rsa_context *ctx)\n{\n    return mbedtls_mpi_bitlen(&ctx->N);\n}\n\n/*\n * Get length in bytes of RSA modulus\n */\nsize_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx)\n{\n    return ctx->len;\n}\n\n#if defined(MBEDTLS_GENPRIME)\n\n/*\n * Generate an RSA keypair\n *\n * This generation method follows the RSA key pair generation procedure of\n * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072.\n */\nint mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx,\n                        int (*f_rng)(void *, unsigned char *, size_t),\n                        void *p_rng,\n                        unsigned int nbits, int exponent)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_mpi H;\n    int prime_quality = 0;\n\n    /*\n     * If the modulus is 1024 bit long or shorter, then the security strength of\n     * the RSA algorithm is less than or equal to 80 bits and therefore an error\n     * rate of 2^-80 is sufficient.\n     */\n    if (nbits > 1024) {\n        prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR;\n    }\n\n    mbedtls_mpi_init(&H);\n\n    if (exponent < 3 || nbits % 2 != 0) {\n        ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n\n    if (nbits < MBEDTLS_RSA_GEN_KEY_MIN_BITS) {\n        ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n\n    /*\n     * find primes P and Q with Q < P so that:\n     * 1.  |P-Q| > 2^( nbits / 2 - 100 )\n     * 2.  GCD( E, (P-1)*(Q-1) ) == 1\n     * 3.  E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 )\n     */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->E, exponent));\n\n    do {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_gen_prime(&ctx->P, nbits >> 1,\n                                              prime_quality, f_rng, p_rng));\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_gen_prime(&ctx->Q, nbits >> 1,\n                                              prime_quality, f_rng, p_rng));\n\n        /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&H, &ctx->P, &ctx->Q));\n        if (mbedtls_mpi_bitlen(&H) <= ((nbits >= 200) ? ((nbits >> 1) - 99) : 0)) {\n            continue;\n        }\n\n        /* not required by any standards, but some users rely on the fact that P > Q */\n        if (H.s < 0) {\n            mbedtls_mpi_swap(&ctx->P, &ctx->Q);\n        }\n\n        /* Compute D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b))\n         * if it exists (FIPS 186-4 §B.3.1 criterion 2(a)) */\n        ret = mbedtls_rsa_deduce_private_exponent(&ctx->P, &ctx->Q, &ctx->E, &ctx->D);\n        if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {\n            mbedtls_mpi_lset(&ctx->D, 0); /* needed for the next call */\n            continue;\n        }\n        if (ret != 0) {\n            goto cleanup;\n        }\n\n        /* (FIPS 186-4 §B.3.1 criterion 3(a)) */\n        if (mbedtls_mpi_bitlen(&ctx->D) <= ((nbits + 1) / 2)) {\n            continue;\n        }\n\n        break;\n    } while (1);\n\n\n    /* N = P * Q */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->N, &ctx->P, &ctx->Q));\n    ctx->len = mbedtls_mpi_size(&ctx->N);\n\n#if !defined(MBEDTLS_RSA_NO_CRT)\n    /*\n     * DP = D mod (P - 1)\n     * DQ = D mod (Q - 1)\n     * QP = Q^-1 mod P\n     */\n    MBEDTLS_MPI_CHK(mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D,\n                                           &ctx->DP, &ctx->DQ, &ctx->QP));\n#endif /* MBEDTLS_RSA_NO_CRT */\n\n    /* Double-check */\n    MBEDTLS_MPI_CHK(mbedtls_rsa_check_privkey(ctx));\n\ncleanup:\n\n    mbedtls_mpi_free(&H);\n\n    if (ret != 0) {\n        mbedtls_rsa_free(ctx);\n\n        if ((-ret & ~0x7f) == 0) {\n            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_KEY_GEN_FAILED, ret);\n        }\n        return ret;\n    }\n\n    return 0;\n}\n\n#endif /* MBEDTLS_GENPRIME */\n\n/*\n * Check a public RSA key\n */\nint mbedtls_rsa_check_pubkey(const mbedtls_rsa_context *ctx)\n{\n    if (rsa_check_context(ctx, 0 /* public */, 0 /* no blinding */) != 0) {\n        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n    }\n\n    if (mbedtls_mpi_bitlen(&ctx->N) < 128) {\n        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n    }\n\n    if (mbedtls_mpi_get_bit(&ctx->E, 0) == 0 ||\n        mbedtls_mpi_bitlen(&ctx->E)     < 2  ||\n        mbedtls_mpi_cmp_mpi(&ctx->E, &ctx->N) >= 0) {\n        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n    }\n\n    return 0;\n}\n\n/*\n * Check for the consistency of all fields in an RSA private key context\n */\nint mbedtls_rsa_check_privkey(const mbedtls_rsa_context *ctx)\n{\n    if (mbedtls_rsa_check_pubkey(ctx) != 0 ||\n        rsa_check_context(ctx, 1 /* private */, 1 /* blinding */) != 0) {\n        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n    }\n\n    if (mbedtls_rsa_validate_params(&ctx->N, &ctx->P, &ctx->Q,\n                                    &ctx->D, &ctx->E, NULL, NULL) != 0) {\n        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n    }\n\n#if !defined(MBEDTLS_RSA_NO_CRT)\n    else if (mbedtls_rsa_validate_crt(&ctx->P, &ctx->Q, &ctx->D,\n                                      &ctx->DP, &ctx->DQ, &ctx->QP) != 0) {\n        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n    }\n#endif\n\n    return 0;\n}\n\n/*\n * Check if contexts holding a public and private key match\n */\nint mbedtls_rsa_check_pub_priv(const mbedtls_rsa_context *pub,\n                               const mbedtls_rsa_context *prv)\n{\n    if (mbedtls_rsa_check_pubkey(pub)  != 0 ||\n        mbedtls_rsa_check_privkey(prv) != 0) {\n        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n    }\n\n    if (mbedtls_mpi_cmp_mpi(&pub->N, &prv->N) != 0 ||\n        mbedtls_mpi_cmp_mpi(&pub->E, &prv->E) != 0) {\n        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n    }\n\n    return 0;\n}\n\n/*\n * Do an RSA public key operation\n */\nint mbedtls_rsa_public(mbedtls_rsa_context *ctx,\n                       const unsigned char *input,\n                       unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t olen;\n    mbedtls_mpi T;\n\n    if (rsa_check_context(ctx, 0 /* public */, 0 /* no blinding */)) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    mbedtls_mpi_init(&T);\n\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {\n        return ret;\n    }\n#endif\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&T, input, ctx->len));\n\n    if (mbedtls_mpi_cmp_mpi(&T, &ctx->N) >= 0) {\n        ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n\n    olen = ctx->len;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod_unsafe(&T, &T, &ctx->E, &ctx->N, &ctx->RN));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen));\n\ncleanup:\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {\n        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n#endif\n\n    mbedtls_mpi_free(&T);\n\n    if (ret != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_PUBLIC_FAILED, ret);\n    }\n\n    return 0;\n}\n\n/*\n * Generate or update blinding values, see section 10 of:\n *  KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,\n *  DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer\n *  Berlin Heidelberg, 1996. p. 104-113.\n */\nstatic int rsa_prepare_blinding(mbedtls_rsa_context *ctx,\n                                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)\n{\n    int ret, count = 0;\n    mbedtls_mpi R;\n\n    mbedtls_mpi_init(&R);\n\n    if (ctx->Vf.p != NULL) {\n        /* We already have blinding values, just update them by squaring */\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->N));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->N));\n\n        goto cleanup;\n    }\n\n    /* Unblinding value: Vf = random number, invertible mod N */\n    mbedtls_mpi_lset(&R, 0);\n    do {\n        if (count++ > 10) {\n            ret = MBEDTLS_ERR_RSA_RNG_FAILED;\n            goto cleanup;\n        }\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_random(&ctx->Vf, 1, &ctx->N, f_rng, p_rng));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(&R, &ctx->Vi, &ctx->Vf, &ctx->N));\n    } while (mbedtls_mpi_cmp_int(&R, 1) != 0);\n\n    /* Blinding value: Vi = Vf^(-e) mod N\n     * (Vi already contains Vf^-1 at this point) */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN));\n\n\ncleanup:\n    mbedtls_mpi_free(&R);\n\n    return ret;\n}\n\n/*\n * Unblind\n * T = T * Vf mod N\n */\nstatic int rsa_unblind(mbedtls_mpi *T, mbedtls_mpi *Vf, const mbedtls_mpi *N)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p);\n    const size_t nlimbs = N->n;\n    const size_t tlimbs = mbedtls_mpi_core_montmul_working_limbs(nlimbs);\n    mbedtls_mpi RR, M_T;\n\n    mbedtls_mpi_init(&RR);\n    mbedtls_mpi_init(&M_T);\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&M_T, tlimbs));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(T, nlimbs));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Vf, nlimbs));\n\n    /* T = T * Vf mod N\n     * Reminder: montmul(A, B, N) = A * B * R^-1 mod N\n     * Usually both operands are multiplied by R mod N beforehand (by calling\n     * `to_mont_rep()` on them), yielding a result that's also * R mod N (aka\n     * \"in the Montgomery domain\"). Here we only multiply one operand by R mod\n     * N, so the result is directly what we want - no need to call\n     * `from_mont_rep()` on it. */\n    mbedtls_mpi_core_to_mont_rep(T->p, T->p, N->p, nlimbs, mm, RR.p, M_T.p);\n    mbedtls_mpi_core_montmul(T->p, T->p, Vf->p, nlimbs, N->p, nlimbs, mm, M_T.p);\n\ncleanup:\n\n    mbedtls_mpi_free(&RR);\n    mbedtls_mpi_free(&M_T);\n\n    return ret;\n}\n\n/*\n * Exponent blinding supposed to prevent side-channel attacks using multiple\n * traces of measurements to recover the RSA key. The more collisions are there,\n * the more bits of the key can be recovered. See [3].\n *\n * Collecting n collisions with m bit long blinding value requires 2^(m-m/n)\n * observations on average.\n *\n * For example with 28 byte blinding to achieve 2 collisions the adversary has\n * to make 2^112 observations on average.\n *\n * (With the currently (as of 2017 April) known best algorithms breaking 2048\n * bit RSA requires approximately as much time as trying out 2^112 random keys.\n * Thus in this sense with 28 byte blinding the security is not reduced by\n * side-channel attacks like the one in [3])\n *\n * This countermeasure does not help if the key recovery is possible with a\n * single trace.\n */\n#define RSA_EXPONENT_BLINDING 28\n\n/*\n * Do an RSA private key operation\n */\nint mbedtls_rsa_private(mbedtls_rsa_context *ctx,\n                        int (*f_rng)(void *, unsigned char *, size_t),\n                        void *p_rng,\n                        const unsigned char *input,\n                        unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t olen;\n\n    /* Temporary holding the result */\n    mbedtls_mpi T;\n\n    /* Temporaries holding P-1, Q-1 and the\n     * exponent blinding factor, respectively. */\n    mbedtls_mpi P1, Q1, R;\n\n#if !defined(MBEDTLS_RSA_NO_CRT)\n    /* Temporaries holding the results mod p resp. mod q. */\n    mbedtls_mpi TP, TQ;\n\n    /* Temporaries holding the blinded exponents for\n     * the mod p resp. mod q computation (if used). */\n    mbedtls_mpi DP_blind, DQ_blind;\n#else\n    /* Temporary holding the blinded exponent (if used). */\n    mbedtls_mpi D_blind;\n#endif /* MBEDTLS_RSA_NO_CRT */\n\n    /* Temporaries holding the initial input and the double\n     * checked result; should be the same in the end. */\n    mbedtls_mpi input_blinded, check_result_blinded;\n\n    if (f_rng == NULL) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    if (rsa_check_context(ctx, 1 /* private key checks */,\n                          1 /* blinding on        */) != 0) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {\n        return ret;\n    }\n#endif\n\n    /* MPI Initialization */\n    mbedtls_mpi_init(&T);\n\n    mbedtls_mpi_init(&P1);\n    mbedtls_mpi_init(&Q1);\n    mbedtls_mpi_init(&R);\n\n#if defined(MBEDTLS_RSA_NO_CRT)\n    mbedtls_mpi_init(&D_blind);\n#else\n    mbedtls_mpi_init(&DP_blind);\n    mbedtls_mpi_init(&DQ_blind);\n#endif\n\n#if !defined(MBEDTLS_RSA_NO_CRT)\n    mbedtls_mpi_init(&TP); mbedtls_mpi_init(&TQ);\n#endif\n\n    mbedtls_mpi_init(&input_blinded);\n    mbedtls_mpi_init(&check_result_blinded);\n\n    /* End of MPI initialization */\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&T, input, ctx->len));\n    if (mbedtls_mpi_cmp_mpi(&T, &ctx->N) >= 0) {\n        ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n\n    /*\n     * Blinding\n     * T = T * Vi mod N\n     */\n    MBEDTLS_MPI_CHK(rsa_prepare_blinding(ctx, f_rng, p_rng));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vi));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&input_blinded, &T));\n\n    /*\n     * Exponent blinding\n     */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&P1, &ctx->P, 1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&Q1, &ctx->Q, 1));\n\n#if defined(MBEDTLS_RSA_NO_CRT)\n    /*\n     * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D\n     */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING,\n                                            f_rng, p_rng));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &P1, &Q1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &D_blind, &R));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&D_blind, &D_blind, &ctx->D));\n#else\n    /*\n     * DP_blind = ( P - 1 ) * R + DP\n     */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING,\n                                            f_rng, p_rng));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DP_blind, &P1, &R));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DP_blind, &DP_blind,\n                                        &ctx->DP));\n\n    /*\n     * DQ_blind = ( Q - 1 ) * R + DQ\n     */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING,\n                                            f_rng, p_rng));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DQ_blind, &Q1, &R));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DQ_blind, &DQ_blind,\n                                        &ctx->DQ));\n#endif /* MBEDTLS_RSA_NO_CRT */\n\n#if defined(MBEDTLS_RSA_NO_CRT)\n    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, &D_blind, &ctx->N, &ctx->RN));\n#else\n    /*\n     * Faster decryption using the CRT\n     *\n     * TP = input ^ dP mod P\n     * TQ = input ^ dQ mod Q\n     */\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TP, &T, &DP_blind, &ctx->P, &ctx->RP));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TQ, &T, &DQ_blind, &ctx->Q, &ctx->RQ));\n\n    /*\n     * T = (TP - TQ) * (Q^-1 mod P) mod P\n     */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&T, &TP, &TQ));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&TP, &T, &ctx->QP));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &TP, &ctx->P));\n\n    /*\n     * T = TQ + T * Q\n     */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&TP, &T, &ctx->Q));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&T, &TQ, &TP));\n#endif /* MBEDTLS_RSA_NO_CRT */\n\n    /* Verify the result to prevent glitching attacks. */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&check_result_blinded, &T, &ctx->E,\n                                        &ctx->N, &ctx->RN));\n    if (mbedtls_mpi_cmp_mpi(&check_result_blinded, &input_blinded) != 0) {\n        ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;\n        goto cleanup;\n    }\n\n    /*\n     * Unblind\n     * T = T * Vf mod N\n     */\n    MBEDTLS_MPI_CHK(rsa_unblind(&T, &ctx->Vf, &ctx->N));\n\n    olen = ctx->len;\n    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen));\n\ncleanup:\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {\n        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n#endif\n\n    mbedtls_mpi_free(&P1);\n    mbedtls_mpi_free(&Q1);\n    mbedtls_mpi_free(&R);\n\n#if defined(MBEDTLS_RSA_NO_CRT)\n    mbedtls_mpi_free(&D_blind);\n#else\n    mbedtls_mpi_free(&DP_blind);\n    mbedtls_mpi_free(&DQ_blind);\n#endif\n\n    mbedtls_mpi_free(&T);\n\n#if !defined(MBEDTLS_RSA_NO_CRT)\n    mbedtls_mpi_free(&TP); mbedtls_mpi_free(&TQ);\n#endif\n\n    mbedtls_mpi_free(&check_result_blinded);\n    mbedtls_mpi_free(&input_blinded);\n\n    if (ret != 0 && ret >= -0x007f) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_PRIVATE_FAILED, ret);\n    }\n\n    return ret;\n}\n\n#if defined(MBEDTLS_PKCS1_V21)\n/**\n * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer.\n *\n * \\param dst       buffer to mask\n * \\param dlen      length of destination buffer\n * \\param src       source of the mask generation\n * \\param slen      length of the source buffer\n * \\param md_alg    message digest to use\n */\nstatic int mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src,\n                    size_t slen, mbedtls_md_type_t md_alg)\n{\n    unsigned char counter[4];\n    unsigned char *p;\n    unsigned int hlen;\n    size_t i, use_len;\n    unsigned char mask[MBEDTLS_MD_MAX_SIZE];\n    int ret = 0;\n    const mbedtls_md_info_t *md_info;\n    mbedtls_md_context_t md_ctx;\n\n    mbedtls_md_init(&md_ctx);\n    md_info = mbedtls_md_info_from_type(md_alg);\n    if (md_info == NULL) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    mbedtls_md_init(&md_ctx);\n    if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) {\n        goto exit;\n    }\n\n    hlen = mbedtls_md_get_size(md_info);\n\n    memset(mask, 0, sizeof(mask));\n    memset(counter, 0, 4);\n\n    /* Generate and apply dbMask */\n    p = dst;\n\n    while (dlen > 0) {\n        use_len = hlen;\n        if (dlen < hlen) {\n            use_len = dlen;\n        }\n\n        if ((ret = mbedtls_md_starts(&md_ctx)) != 0) {\n            goto exit;\n        }\n        if ((ret = mbedtls_md_update(&md_ctx, src, slen)) != 0) {\n            goto exit;\n        }\n        if ((ret = mbedtls_md_update(&md_ctx, counter, 4)) != 0) {\n            goto exit;\n        }\n        if ((ret = mbedtls_md_finish(&md_ctx, mask)) != 0) {\n            goto exit;\n        }\n\n        for (i = 0; i < use_len; ++i) {\n            *p++ ^= mask[i];\n        }\n\n        counter[3]++;\n\n        dlen -= use_len;\n    }\n\nexit:\n    mbedtls_platform_zeroize(mask, sizeof(mask));\n    mbedtls_md_free(&md_ctx);\n\n    return ret;\n}\n\n/**\n * Generate Hash(M') as in RFC 8017 page 43 points 5 and 6.\n *\n * \\param hash      the input hash\n * \\param hlen      length of the input hash\n * \\param salt      the input salt\n * \\param slen      length of the input salt\n * \\param out       the output buffer - must be large enough for \\p md_alg\n * \\param md_alg    message digest to use\n */\nstatic int hash_mprime(const unsigned char *hash, size_t hlen,\n                       const unsigned char *salt, size_t slen,\n                       unsigned char *out, mbedtls_md_type_t md_alg)\n{\n    const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };\n\n    mbedtls_md_context_t md_ctx;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg);\n    if (md_info == NULL) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    mbedtls_md_init(&md_ctx);\n    if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) {\n        goto exit;\n    }\n    if ((ret = mbedtls_md_starts(&md_ctx)) != 0) {\n        goto exit;\n    }\n    if ((ret = mbedtls_md_update(&md_ctx, zeros, sizeof(zeros))) != 0) {\n        goto exit;\n    }\n    if ((ret = mbedtls_md_update(&md_ctx, hash, hlen)) != 0) {\n        goto exit;\n    }\n    if ((ret = mbedtls_md_update(&md_ctx, salt, slen)) != 0) {\n        goto exit;\n    }\n    if ((ret = mbedtls_md_finish(&md_ctx, out)) != 0) {\n        goto exit;\n    }\n\nexit:\n    mbedtls_md_free(&md_ctx);\n\n    return ret;\n}\n\n/**\n * Compute a hash.\n *\n * \\param md_alg    algorithm to use\n * \\param input     input message to hash\n * \\param ilen      input length\n * \\param output    the output buffer - must be large enough for \\p md_alg\n */\nstatic int compute_hash(mbedtls_md_type_t md_alg,\n                        const unsigned char *input, size_t ilen,\n                        unsigned char *output)\n{\n    const mbedtls_md_info_t *md_info;\n\n    md_info = mbedtls_md_info_from_type(md_alg);\n    if (md_info == NULL) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    return mbedtls_md(md_info, input, ilen, output);\n}\n#endif /* MBEDTLS_PKCS1_V21 */\n\n#if defined(MBEDTLS_PKCS1_V21)\n/*\n * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function\n */\nint mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx,\n                                   int (*f_rng)(void *, unsigned char *, size_t),\n                                   void *p_rng,\n                                   const unsigned char *label, size_t label_len,\n                                   size_t ilen,\n                                   const unsigned char *input,\n                                   unsigned char *output)\n{\n    size_t olen;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = output;\n    unsigned int hlen;\n\n    if (f_rng == NULL) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    hlen = mbedtls_md_get_size_from_type((mbedtls_md_type_t) ctx->hash_id);\n    if (hlen == 0) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    olen = ctx->len;\n\n    /* first comparison checks for overflow */\n    if (ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    memset(output, 0, olen);\n\n    *p++ = 0;\n\n    /* Generate a random octet string seed */\n    if ((ret = f_rng(p_rng, p, hlen)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret);\n    }\n\n    p += hlen;\n\n    /* Construct DB */\n    ret = compute_hash((mbedtls_md_type_t) ctx->hash_id, label, label_len, p);\n    if (ret != 0) {\n        return ret;\n    }\n    p += hlen;\n    p += olen - 2 * hlen - 2 - ilen;\n    *p++ = 1;\n    if (ilen != 0) {\n        memcpy(p, input, ilen);\n    }\n\n    /* maskedDB: Apply dbMask to DB */\n    if ((ret = mgf_mask(output + hlen + 1, olen - hlen - 1, output + 1, hlen,\n                        (mbedtls_md_type_t) ctx->hash_id)) != 0) {\n        return ret;\n    }\n\n    /* maskedSeed: Apply seedMask to seed */\n    if ((ret = mgf_mask(output + 1, hlen, output + hlen + 1, olen - hlen - 1,\n                        (mbedtls_md_type_t) ctx->hash_id)) != 0) {\n        return ret;\n    }\n\n    return mbedtls_rsa_public(ctx, output, output);\n}\n#endif /* MBEDTLS_PKCS1_V21 */\n\n#if defined(MBEDTLS_PKCS1_V15)\n/*\n * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function\n */\nint mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx,\n                                        int (*f_rng)(void *, unsigned char *, size_t),\n                                        void *p_rng, size_t ilen,\n                                        const unsigned char *input,\n                                        unsigned char *output)\n{\n    size_t nb_pad, olen;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = output;\n\n    olen = ctx->len;\n\n    /* first comparison checks for overflow */\n    if (ilen + 11 < ilen || olen < ilen + 11) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    nb_pad = olen - 3 - ilen;\n\n    *p++ = 0;\n\n    if (f_rng == NULL) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    *p++ = MBEDTLS_RSA_CRYPT;\n\n    while (nb_pad-- > 0) {\n        int rng_dl = 100;\n\n        do {\n            ret = f_rng(p_rng, p, 1);\n        } while (*p == 0 && --rng_dl && ret == 0);\n\n        /* Check if RNG failed to generate data */\n        if (rng_dl == 0 || ret != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret);\n        }\n\n        p++;\n    }\n\n    *p++ = 0;\n    if (ilen != 0) {\n        memcpy(p, input, ilen);\n    }\n\n    return mbedtls_rsa_public(ctx, output, output);\n}\n#endif /* MBEDTLS_PKCS1_V15 */\n\n/*\n * Add the message padding, then do an RSA operation\n */\nint mbedtls_rsa_pkcs1_encrypt(mbedtls_rsa_context *ctx,\n                              int (*f_rng)(void *, unsigned char *, size_t),\n                              void *p_rng,\n                              size_t ilen,\n                              const unsigned char *input,\n                              unsigned char *output)\n{\n    switch (ctx->padding) {\n#if defined(MBEDTLS_PKCS1_V15)\n        case MBEDTLS_RSA_PKCS_V15:\n            return mbedtls_rsa_rsaes_pkcs1_v15_encrypt(ctx, f_rng, p_rng,\n                                                       ilen, input, output);\n#endif\n\n#if defined(MBEDTLS_PKCS1_V21)\n        case MBEDTLS_RSA_PKCS_V21:\n            return mbedtls_rsa_rsaes_oaep_encrypt(ctx, f_rng, p_rng, NULL, 0,\n                                                  ilen, input, output);\n#endif\n\n        default:\n            return MBEDTLS_ERR_RSA_INVALID_PADDING;\n    }\n}\n\n#if defined(MBEDTLS_PKCS1_V21)\n/*\n * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function\n */\nint mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx,\n                                   int (*f_rng)(void *, unsigned char *, size_t),\n                                   void *p_rng,\n                                   const unsigned char *label, size_t label_len,\n                                   size_t *olen,\n                                   const unsigned char *input,\n                                   unsigned char *output,\n                                   size_t output_max_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t ilen, i, pad_len;\n    unsigned char *p;\n    mbedtls_ct_condition_t bad, in_padding;\n    unsigned char buf[MBEDTLS_MPI_MAX_SIZE];\n    unsigned char lhash[MBEDTLS_MD_MAX_SIZE];\n    unsigned int hlen;\n\n    /*\n     * Parameters sanity checks\n     */\n    if (ctx->padding != MBEDTLS_RSA_PKCS_V21) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    ilen = ctx->len;\n\n    if (ilen < 16 || ilen > sizeof(buf)) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    hlen = mbedtls_md_get_size_from_type((mbedtls_md_type_t) ctx->hash_id);\n    if (hlen == 0) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    // checking for integer underflow\n    if (2 * hlen + 2 > ilen) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    /*\n     * RSA operation\n     */\n    ret = mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf);\n\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    /*\n     * Unmask data and generate lHash\n     */\n    /* seed: Apply seedMask to maskedSeed */\n    if ((ret = mgf_mask(buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,\n                        (mbedtls_md_type_t) ctx->hash_id)) != 0 ||\n        /* DB: Apply dbMask to maskedDB */\n        (ret = mgf_mask(buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,\n                        (mbedtls_md_type_t) ctx->hash_id)) != 0) {\n        goto cleanup;\n    }\n\n    /* Generate lHash */\n    ret = compute_hash((mbedtls_md_type_t) ctx->hash_id,\n                       label, label_len, lhash);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    /*\n     * Check contents, in \"constant-time\"\n     */\n    p = buf;\n\n    bad = mbedtls_ct_bool(*p++); /* First byte must be 0 */\n\n    p += hlen; /* Skip seed */\n\n    /* Check lHash */\n    bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool(mbedtls_ct_memcmp(lhash, p, hlen)));\n    p += hlen;\n\n    /* Get zero-padding len, but always read till end of buffer\n     * (minus one, for the 01 byte) */\n    pad_len = 0;\n    in_padding = MBEDTLS_CT_TRUE;\n    for (i = 0; i < ilen - 2 * hlen - 2; i++) {\n        in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_uint_eq(p[i], 0));\n        pad_len += mbedtls_ct_uint_if_else_0(in_padding, 1);\n    }\n\n    p += pad_len;\n    bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_ne(*p++, 0x01));\n\n    /*\n     * The only information \"leaked\" is whether the padding was correct or not\n     * (eg, no data is copied if it was not correct). This meets the\n     * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between\n     * the different error conditions.\n     */\n    if (bad != MBEDTLS_CT_FALSE) {\n        ret = MBEDTLS_ERR_RSA_INVALID_PADDING;\n        goto cleanup;\n    }\n\n    if (ilen - ((size_t) (p - buf)) > output_max_len) {\n        ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;\n        goto cleanup;\n    }\n\n    *olen = ilen - ((size_t) (p - buf));\n    if (*olen != 0) {\n        memcpy(output, p, *olen);\n    }\n    ret = 0;\n\ncleanup:\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n    mbedtls_platform_zeroize(lhash, sizeof(lhash));\n\n    return ret;\n}\n#endif /* MBEDTLS_PKCS1_V21 */\n\n#if defined(MBEDTLS_PKCS1_V15)\n/*\n * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function\n */\nint mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx,\n                                        int (*f_rng)(void *, unsigned char *, size_t),\n                                        void *p_rng,\n                                        size_t *olen,\n                                        const unsigned char *input,\n                                        unsigned char *output,\n                                        size_t output_max_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t ilen;\n    unsigned char buf[MBEDTLS_MPI_MAX_SIZE];\n\n    ilen = ctx->len;\n\n    if (ctx->padding != MBEDTLS_RSA_PKCS_V15) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    if (ilen < 16 || ilen > sizeof(buf)) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    ret = mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf);\n\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    ret = mbedtls_ct_rsaes_pkcs1_v15_unpadding(buf, ilen,\n                                               output, output_max_len, olen);\n\ncleanup:\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n\n    return ret;\n}\n#endif /* MBEDTLS_PKCS1_V15 */\n\n/*\n * Do an RSA operation, then remove the message padding\n */\nint mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx,\n                              int (*f_rng)(void *, unsigned char *, size_t),\n                              void *p_rng,\n                              size_t *olen,\n                              const unsigned char *input,\n                              unsigned char *output,\n                              size_t output_max_len)\n{\n    switch (ctx->padding) {\n#if defined(MBEDTLS_PKCS1_V15)\n        case MBEDTLS_RSA_PKCS_V15:\n            return mbedtls_rsa_rsaes_pkcs1_v15_decrypt(ctx, f_rng, p_rng, olen,\n                                                       input, output, output_max_len);\n#endif\n\n#if defined(MBEDTLS_PKCS1_V21)\n        case MBEDTLS_RSA_PKCS_V21:\n            return mbedtls_rsa_rsaes_oaep_decrypt(ctx, f_rng, p_rng, NULL, 0,\n                                                  olen, input, output,\n                                                  output_max_len);\n#endif\n\n        default:\n            return MBEDTLS_ERR_RSA_INVALID_PADDING;\n    }\n}\n\n#if defined(MBEDTLS_PKCS1_V21)\nstatic int rsa_rsassa_pss_sign_no_mode_check(mbedtls_rsa_context *ctx,\n                                             int (*f_rng)(void *, unsigned char *, size_t),\n                                             void *p_rng,\n                                             mbedtls_md_type_t md_alg,\n                                             unsigned int hashlen,\n                                             const unsigned char *hash,\n                                             int saltlen,\n                                             unsigned char *sig)\n{\n    size_t olen;\n    unsigned char *p = sig;\n    unsigned char *salt = NULL;\n    size_t slen, min_slen, hlen, offset = 0;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t msb;\n    mbedtls_md_type_t hash_id;\n\n    if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    if (f_rng == NULL) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    olen = ctx->len;\n\n    if (md_alg != MBEDTLS_MD_NONE) {\n        /* Gather length of hash to sign */\n        size_t exp_hashlen = mbedtls_md_get_size_from_type(md_alg);\n        if (exp_hashlen == 0) {\n            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n        }\n\n        if (hashlen != exp_hashlen) {\n            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n        }\n    }\n\n    hash_id = (mbedtls_md_type_t) ctx->hash_id;\n    if (hash_id == MBEDTLS_MD_NONE) {\n        hash_id = md_alg;\n    }\n    hlen = mbedtls_md_get_size_from_type(hash_id);\n    if (hlen == 0) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    if (saltlen == MBEDTLS_RSA_SALT_LEN_ANY) {\n        /* Calculate the largest possible salt length, up to the hash size.\n         * Normally this is the hash length, which is the maximum salt length\n         * according to FIPS 185-4 §5.5 (e) and common practice. If there is not\n         * enough room, use the maximum salt length that fits. The constraint is\n         * that the hash length plus the salt length plus 2 bytes must be at most\n         * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017\n         * (PKCS#1 v2.2) §9.1.1 step 3. */\n        min_slen = hlen - 2;\n        if (olen < hlen + min_slen + 2) {\n            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n        } else if (olen >= hlen + hlen + 2) {\n            slen = hlen;\n        } else {\n            slen = olen - hlen - 2;\n        }\n    } else if ((saltlen < 0) || (saltlen + hlen + 2 > olen)) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    } else {\n        slen = (size_t) saltlen;\n    }\n\n    memset(sig, 0, olen);\n\n    /* Note: EMSA-PSS encoding is over the length of N - 1 bits */\n    msb = mbedtls_mpi_bitlen(&ctx->N) - 1;\n    p += olen - hlen - slen - 2;\n    *p++ = 0x01;\n\n    /* Generate salt of length slen in place in the encoded message */\n    salt = p;\n    if ((ret = f_rng(p_rng, salt, slen)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret);\n    }\n\n    p += slen;\n\n    /* Generate H = Hash( M' ) */\n    ret = hash_mprime(hash, hashlen, salt, slen, p, hash_id);\n    if (ret != 0) {\n        return ret;\n    }\n\n    /* Compensate for boundary condition when applying mask */\n    if (msb % 8 == 0) {\n        offset = 1;\n    }\n\n    /* maskedDB: Apply dbMask to DB */\n    ret = mgf_mask(sig + offset, olen - hlen - 1 - offset, p, hlen, hash_id);\n    if (ret != 0) {\n        return ret;\n    }\n\n    msb = mbedtls_mpi_bitlen(&ctx->N) - 1;\n    sig[0] &= 0xFF >> (olen * 8 - msb);\n\n    p += hlen;\n    *p++ = 0xBC;\n\n    return mbedtls_rsa_private(ctx, f_rng, p_rng, sig, sig);\n}\n\nstatic int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,\n                               int (*f_rng)(void *, unsigned char *, size_t),\n                               void *p_rng,\n                               mbedtls_md_type_t md_alg,\n                               unsigned int hashlen,\n                               const unsigned char *hash,\n                               int saltlen,\n                               unsigned char *sig)\n{\n    if (ctx->padding != MBEDTLS_RSA_PKCS_V21) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n    if ((ctx->hash_id == MBEDTLS_MD_NONE) && (md_alg == MBEDTLS_MD_NONE)) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n    return rsa_rsassa_pss_sign_no_mode_check(ctx, f_rng, p_rng, md_alg, hashlen, hash, saltlen,\n                                             sig);\n}\n\nint mbedtls_rsa_rsassa_pss_sign_no_mode_check(mbedtls_rsa_context *ctx,\n                                              int (*f_rng)(void *, unsigned char *, size_t),\n                                              void *p_rng,\n                                              mbedtls_md_type_t md_alg,\n                                              unsigned int hashlen,\n                                              const unsigned char *hash,\n                                              unsigned char *sig)\n{\n    return rsa_rsassa_pss_sign_no_mode_check(ctx, f_rng, p_rng, md_alg,\n                                             hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig);\n}\n\n/*\n * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function with\n * the option to pass in the salt length.\n */\nint mbedtls_rsa_rsassa_pss_sign_ext(mbedtls_rsa_context *ctx,\n                                    int (*f_rng)(void *, unsigned char *, size_t),\n                                    void *p_rng,\n                                    mbedtls_md_type_t md_alg,\n                                    unsigned int hashlen,\n                                    const unsigned char *hash,\n                                    int saltlen,\n                                    unsigned char *sig)\n{\n    return rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg,\n                               hashlen, hash, saltlen, sig);\n}\n\n/*\n * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function\n */\nint mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,\n                                int (*f_rng)(void *, unsigned char *, size_t),\n                                void *p_rng,\n                                mbedtls_md_type_t md_alg,\n                                unsigned int hashlen,\n                                const unsigned char *hash,\n                                unsigned char *sig)\n{\n    return rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg,\n                               hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig);\n}\n#endif /* MBEDTLS_PKCS1_V21 */\n\n#if defined(MBEDTLS_PKCS1_V15)\n/*\n * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function\n */\n\n/* Construct a PKCS v1.5 encoding of a hashed message\n *\n * This is used both for signature generation and verification.\n *\n * Parameters:\n * - md_alg:  Identifies the hash algorithm used to generate the given hash;\n *            MBEDTLS_MD_NONE if raw data is signed.\n * - hashlen: Length of hash. Must match md_alg if that's not NONE.\n * - hash:    Buffer containing the hashed message or the raw data.\n * - dst_len: Length of the encoded message.\n * - dst:     Buffer to hold the encoded message.\n *\n * Assumptions:\n * - hash has size hashlen.\n * - dst points to a buffer of size at least dst_len.\n *\n */\nstatic int rsa_rsassa_pkcs1_v15_encode(mbedtls_md_type_t md_alg,\n                                       unsigned int hashlen,\n                                       const unsigned char *hash,\n                                       size_t dst_len,\n                                       unsigned char *dst)\n{\n    size_t oid_size  = 0;\n    size_t nb_pad    = dst_len;\n    unsigned char *p = dst;\n    const char *oid  = NULL;\n\n    /* Are we signing hashed or raw data? */\n    if (md_alg != MBEDTLS_MD_NONE) {\n        unsigned char md_size = mbedtls_md_get_size_from_type(md_alg);\n        if (md_size == 0) {\n            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n        }\n\n        if (mbedtls_oid_get_oid_by_md(md_alg, &oid, &oid_size) != 0) {\n            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n        }\n\n        if (hashlen != md_size) {\n            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n        }\n\n        /* Double-check that 8 + hashlen + oid_size can be used as a\n         * 1-byte ASN.1 length encoding and that there's no overflow. */\n        if (8 + hashlen + oid_size  >= 0x80         ||\n            10 + hashlen            <  hashlen      ||\n            10 + hashlen + oid_size <  10 + hashlen) {\n            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n        }\n\n        /*\n         * Static bounds check:\n         * - Need 10 bytes for five tag-length pairs.\n         *   (Insist on 1-byte length encodings to protect against variants of\n         *    Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification)\n         * - Need hashlen bytes for hash\n         * - Need oid_size bytes for hash alg OID.\n         */\n        if (nb_pad < 10 + hashlen + oid_size) {\n            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n        }\n        nb_pad -= 10 + hashlen + oid_size;\n    } else {\n        if (nb_pad < hashlen) {\n            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n        }\n\n        nb_pad -= hashlen;\n    }\n\n    /* Need space for signature header and padding delimiter (3 bytes),\n     * and 8 bytes for the minimal padding */\n    if (nb_pad < 3 + 8) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n    nb_pad -= 3;\n\n    /* Now nb_pad is the amount of memory to be filled\n     * with padding, and at least 8 bytes long. */\n\n    /* Write signature header and padding */\n    *p++ = 0;\n    *p++ = MBEDTLS_RSA_SIGN;\n    memset(p, 0xFF, nb_pad);\n    p += nb_pad;\n    *p++ = 0;\n\n    /* Are we signing raw data? */\n    if (md_alg == MBEDTLS_MD_NONE) {\n        memcpy(p, hash, hashlen);\n        return 0;\n    }\n\n    /* Signing hashed data, add corresponding ASN.1 structure\n     *\n     * DigestInfo ::= SEQUENCE {\n     *   digestAlgorithm DigestAlgorithmIdentifier,\n     *   digest Digest }\n     * DigestAlgorithmIdentifier ::= AlgorithmIdentifier\n     * Digest ::= OCTET STRING\n     *\n     * Schematic:\n     * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID  + LEN [ OID  ]\n     *                                 TAG-NULL + LEN [ NULL ] ]\n     *                 TAG-OCTET + LEN [ HASH ] ]\n     */\n    *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;\n    *p++ = (unsigned char) (0x08 + oid_size + hashlen);\n    *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;\n    *p++ = (unsigned char) (0x04 + oid_size);\n    *p++ = MBEDTLS_ASN1_OID;\n    *p++ = (unsigned char) oid_size;\n    memcpy(p, oid, oid_size);\n    p += oid_size;\n    *p++ = MBEDTLS_ASN1_NULL;\n    *p++ = 0x00;\n    *p++ = MBEDTLS_ASN1_OCTET_STRING;\n    *p++ = (unsigned char) hashlen;\n    memcpy(p, hash, hashlen);\n    p += hashlen;\n\n    /* Just a sanity-check, should be automatic\n     * after the initial bounds check. */\n    if (p != dst + dst_len) {\n        mbedtls_platform_zeroize(dst, dst_len);\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    return 0;\n}\n\n/*\n * Do an RSA operation to sign the message digest\n */\nint mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx,\n                                      int (*f_rng)(void *, unsigned char *, size_t),\n                                      void *p_rng,\n                                      mbedtls_md_type_t md_alg,\n                                      unsigned int hashlen,\n                                      const unsigned char *hash,\n                                      unsigned char *sig)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *sig_try = NULL, *verif = NULL;\n\n    if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    if (ctx->padding != MBEDTLS_RSA_PKCS_V15) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    /*\n     * Prepare PKCS1-v1.5 encoding (padding and hash identifier)\n     */\n\n    if ((ret = rsa_rsassa_pkcs1_v15_encode(md_alg, hashlen, hash,\n                                           ctx->len, sig)) != 0) {\n        return ret;\n    }\n\n    /* Private key operation\n     *\n     * In order to prevent Lenstra's attack, make the signature in a\n     * temporary buffer and check it before returning it.\n     */\n\n    sig_try = mbedtls_calloc(1, ctx->len);\n    if (sig_try == NULL) {\n        return MBEDTLS_ERR_MPI_ALLOC_FAILED;\n    }\n\n    verif = mbedtls_calloc(1, ctx->len);\n    if (verif == NULL) {\n        mbedtls_free(sig_try);\n        return MBEDTLS_ERR_MPI_ALLOC_FAILED;\n    }\n\n    MBEDTLS_MPI_CHK(mbedtls_rsa_private(ctx, f_rng, p_rng, sig, sig_try));\n    MBEDTLS_MPI_CHK(mbedtls_rsa_public(ctx, sig_try, verif));\n\n    if (mbedtls_ct_memcmp(verif, sig, ctx->len) != 0) {\n        ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED;\n        goto cleanup;\n    }\n\n    memcpy(sig, sig_try, ctx->len);\n\ncleanup:\n    mbedtls_zeroize_and_free(sig_try, ctx->len);\n    mbedtls_zeroize_and_free(verif, ctx->len);\n\n    if (ret != 0) {\n        memset(sig, '!', ctx->len);\n    }\n    return ret;\n}\n#endif /* MBEDTLS_PKCS1_V15 */\n\n/*\n * Do an RSA operation to sign the message digest\n */\nint mbedtls_rsa_pkcs1_sign(mbedtls_rsa_context *ctx,\n                           int (*f_rng)(void *, unsigned char *, size_t),\n                           void *p_rng,\n                           mbedtls_md_type_t md_alg,\n                           unsigned int hashlen,\n                           const unsigned char *hash,\n                           unsigned char *sig)\n{\n    if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    switch (ctx->padding) {\n#if defined(MBEDTLS_PKCS1_V15)\n        case MBEDTLS_RSA_PKCS_V15:\n            return mbedtls_rsa_rsassa_pkcs1_v15_sign(ctx, f_rng, p_rng,\n                                                     md_alg, hashlen, hash, sig);\n#endif\n\n#if defined(MBEDTLS_PKCS1_V21)\n        case MBEDTLS_RSA_PKCS_V21:\n            return mbedtls_rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg,\n                                               hashlen, hash, sig);\n#endif\n\n        default:\n            return MBEDTLS_ERR_RSA_INVALID_PADDING;\n    }\n}\n\n#if defined(MBEDTLS_PKCS1_V21)\n/*\n * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function\n */\nint mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx,\n                                      mbedtls_md_type_t md_alg,\n                                      unsigned int hashlen,\n                                      const unsigned char *hash,\n                                      mbedtls_md_type_t mgf1_hash_id,\n                                      int expected_salt_len,\n                                      const unsigned char *sig)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t siglen;\n    unsigned char *p;\n    unsigned char *hash_start;\n    unsigned char result[MBEDTLS_MD_MAX_SIZE];\n    unsigned int hlen;\n    size_t observed_salt_len, msb;\n    unsigned char buf[MBEDTLS_MPI_MAX_SIZE] = { 0 };\n\n    if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    siglen = ctx->len;\n\n    if (siglen < 16 || siglen > sizeof(buf)) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    ret = mbedtls_rsa_public(ctx, sig, buf);\n\n    if (ret != 0) {\n        return ret;\n    }\n\n    p = buf;\n\n    if (buf[siglen - 1] != 0xBC) {\n        return MBEDTLS_ERR_RSA_INVALID_PADDING;\n    }\n\n    if (md_alg != MBEDTLS_MD_NONE) {\n        /* Gather length of hash to sign */\n        size_t exp_hashlen = mbedtls_md_get_size_from_type(md_alg);\n        if (exp_hashlen == 0) {\n            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n        }\n\n        if (hashlen != exp_hashlen) {\n            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n        }\n    }\n\n    hlen = mbedtls_md_get_size_from_type(mgf1_hash_id);\n    if (hlen == 0) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    /*\n     * Note: EMSA-PSS verification is over the length of N - 1 bits\n     */\n    msb = mbedtls_mpi_bitlen(&ctx->N) - 1;\n\n    if (buf[0] >> (8 - siglen * 8 + msb)) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    /* Compensate for boundary condition when applying mask */\n    if (msb % 8 == 0) {\n        p++;\n        siglen -= 1;\n    }\n\n    if (siglen < hlen + 2) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n    hash_start = p + siglen - hlen - 1;\n\n    ret = mgf_mask(p, siglen - hlen - 1, hash_start, hlen, mgf1_hash_id);\n    if (ret != 0) {\n        return ret;\n    }\n\n    buf[0] &= 0xFF >> (siglen * 8 - msb);\n\n    while (p < hash_start - 1 && *p == 0) {\n        p++;\n    }\n\n    if (*p++ != 0x01) {\n        return MBEDTLS_ERR_RSA_INVALID_PADDING;\n    }\n\n    observed_salt_len = (size_t) (hash_start - p);\n\n    if (expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY &&\n        observed_salt_len != (size_t) expected_salt_len) {\n        return MBEDTLS_ERR_RSA_INVALID_PADDING;\n    }\n\n    /*\n     * Generate H = Hash( M' )\n     */\n    ret = hash_mprime(hash, hashlen, p, observed_salt_len,\n                      result, mgf1_hash_id);\n    if (ret != 0) {\n        return ret;\n    }\n\n    if (memcmp(hash_start, result, hlen) != 0) {\n        return MBEDTLS_ERR_RSA_VERIFY_FAILED;\n    }\n\n    return 0;\n}\n\n/*\n * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function\n */\nint mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context *ctx,\n                                  mbedtls_md_type_t md_alg,\n                                  unsigned int hashlen,\n                                  const unsigned char *hash,\n                                  const unsigned char *sig)\n{\n    mbedtls_md_type_t mgf1_hash_id;\n    if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    mgf1_hash_id = (ctx->hash_id != MBEDTLS_MD_NONE)\n                             ? (mbedtls_md_type_t) ctx->hash_id\n                             : md_alg;\n\n    return mbedtls_rsa_rsassa_pss_verify_ext(ctx,\n                                             md_alg, hashlen, hash,\n                                             mgf1_hash_id,\n                                             MBEDTLS_RSA_SALT_LEN_ANY,\n                                             sig);\n\n}\n#endif /* MBEDTLS_PKCS1_V21 */\n\n#if defined(MBEDTLS_PKCS1_V15)\n/*\n * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function\n */\nint mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx,\n                                        mbedtls_md_type_t md_alg,\n                                        unsigned int hashlen,\n                                        const unsigned char *hash,\n                                        const unsigned char *sig)\n{\n    int ret = 0;\n    size_t sig_len;\n    unsigned char *encoded = NULL, *encoded_expected = NULL;\n\n    if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    sig_len = ctx->len;\n\n    /*\n     * Prepare expected PKCS1 v1.5 encoding of hash.\n     */\n\n    if ((encoded          = mbedtls_calloc(1, sig_len)) == NULL ||\n        (encoded_expected = mbedtls_calloc(1, sig_len)) == NULL) {\n        ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;\n        goto cleanup;\n    }\n\n    if ((ret = rsa_rsassa_pkcs1_v15_encode(md_alg, hashlen, hash, sig_len,\n                                           encoded_expected)) != 0) {\n        goto cleanup;\n    }\n\n    /*\n     * Apply RSA primitive to get what should be PKCS1 encoded hash.\n     */\n\n    ret = mbedtls_rsa_public(ctx, sig, encoded);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    /*\n     * Compare\n     */\n\n    if ((ret = mbedtls_ct_memcmp(encoded, encoded_expected,\n                                 sig_len)) != 0) {\n        ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;\n        goto cleanup;\n    }\n\ncleanup:\n\n    if (encoded != NULL) {\n        mbedtls_zeroize_and_free(encoded, sig_len);\n    }\n\n    if (encoded_expected != NULL) {\n        mbedtls_zeroize_and_free(encoded_expected, sig_len);\n    }\n\n    return ret;\n}\n#endif /* MBEDTLS_PKCS1_V15 */\n\n/*\n * Do an RSA operation and check the message digest\n */\nint mbedtls_rsa_pkcs1_verify(mbedtls_rsa_context *ctx,\n                             mbedtls_md_type_t md_alg,\n                             unsigned int hashlen,\n                             const unsigned char *hash,\n                             const unsigned char *sig)\n{\n    if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {\n        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n    }\n\n    switch (ctx->padding) {\n#if defined(MBEDTLS_PKCS1_V15)\n        case MBEDTLS_RSA_PKCS_V15:\n            return mbedtls_rsa_rsassa_pkcs1_v15_verify(ctx, md_alg,\n                                                       hashlen, hash, sig);\n#endif\n\n#if defined(MBEDTLS_PKCS1_V21)\n        case MBEDTLS_RSA_PKCS_V21:\n            return mbedtls_rsa_rsassa_pss_verify(ctx, md_alg,\n                                                 hashlen, hash, sig);\n#endif\n\n        default:\n            return MBEDTLS_ERR_RSA_INVALID_PADDING;\n    }\n}\n\n/*\n * Copy the components of an RSA key\n */\nint mbedtls_rsa_copy(mbedtls_rsa_context *dst, const mbedtls_rsa_context *src)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    dst->len = src->len;\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->N, &src->N));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->E, &src->E));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->D, &src->D));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->P, &src->P));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->Q, &src->Q));\n\n#if !defined(MBEDTLS_RSA_NO_CRT)\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->DP, &src->DP));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->DQ, &src->DQ));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->QP, &src->QP));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->RP, &src->RP));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->RQ, &src->RQ));\n#endif\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->RN, &src->RN));\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->Vi, &src->Vi));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->Vf, &src->Vf));\n\n    dst->padding = src->padding;\n    dst->hash_id = src->hash_id;\n\ncleanup:\n    if (ret != 0) {\n        mbedtls_rsa_free(dst);\n    }\n\n    return ret;\n}\n\n/*\n * Free the components of an RSA key\n */\nvoid mbedtls_rsa_free(mbedtls_rsa_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_mpi_free(&ctx->Vi);\n    mbedtls_mpi_free(&ctx->Vf);\n    mbedtls_mpi_free(&ctx->RN);\n    mbedtls_mpi_free(&ctx->D);\n    mbedtls_mpi_free(&ctx->Q);\n    mbedtls_mpi_free(&ctx->P);\n    mbedtls_mpi_free(&ctx->E);\n    mbedtls_mpi_free(&ctx->N);\n\n#if !defined(MBEDTLS_RSA_NO_CRT)\n    mbedtls_mpi_free(&ctx->RQ);\n    mbedtls_mpi_free(&ctx->RP);\n    mbedtls_mpi_free(&ctx->QP);\n    mbedtls_mpi_free(&ctx->DQ);\n    mbedtls_mpi_free(&ctx->DP);\n#endif /* MBEDTLS_RSA_NO_CRT */\n\n#if defined(MBEDTLS_THREADING_C)\n    /* Free the mutex, but only if it hasn't been freed already. */\n    if (ctx->ver != 0) {\n        mbedtls_mutex_free(&ctx->mutex);\n        ctx->ver = 0;\n    }\n#endif\n}\n\n#endif /* !MBEDTLS_RSA_ALT */\n\n#if defined(MBEDTLS_SELF_TEST)\n\n\n/*\n * Example RSA-1024 keypair, for test purposes\n */\n#define KEY_LEN 128\n\n#define RSA_N   \"9292758453063D803DD603D5E777D788\" \\\n                \"8ED1D5BF35786190FA2F23EBC0848AEA\" \\\n                \"DDA92CA6C3D80B32C4D109BE0F36D6AE\" \\\n                \"7130B9CED7ACDF54CFC7555AC14EEBAB\" \\\n                \"93A89813FBF3C4F8066D2D800F7C38A8\" \\\n                \"1AE31942917403FF4946B0A83D3D3E05\" \\\n                \"EE57C6F5F5606FB5D4BC6CD34EE0801A\" \\\n                \"5E94BB77B07507233A0BC7BAC8F90F79\"\n\n#define RSA_E   \"10001\"\n\n#define RSA_D   \"24BF6185468786FDD303083D25E64EFC\" \\\n                \"66CA472BC44D253102F8B4A9D3BFA750\" \\\n                \"91386C0077937FE33FA3252D28855837\" \\\n                \"AE1B484A8A9A45F7EE8C0C634F99E8CD\" \\\n                \"DF79C5CE07EE72C7F123142198164234\" \\\n                \"CABB724CF78B8173B9F880FC86322407\" \\\n                \"AF1FEDFDDE2BEB674CA15F3E81A1521E\" \\\n                \"071513A1E85B5DFA031F21ECAE91A34D\"\n\n#define RSA_P   \"C36D0EB7FCD285223CFB5AABA5BDA3D8\" \\\n                \"2C01CAD19EA484A87EA4377637E75500\" \\\n                \"FCB2005C5C7DD6EC4AC023CDA285D796\" \\\n                \"C3D9E75E1EFC42488BB4F1D13AC30A57\"\n\n#define RSA_Q   \"C000DF51A7C77AE8D7C7370C1FF55B69\" \\\n                \"E211C2B9E5DB1ED0BF61D0D9899620F4\" \\\n                \"910E4168387E3C30AA1E00C339A79508\" \\\n                \"8452DD96A9A5EA5D9DCA68DA636032AF\"\n\n#define PT_LEN  24\n#define RSA_PT  \"\\xAA\\xBB\\xCC\\x03\\x02\\x01\\x00\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n                \"\\x11\\x22\\x33\\x0A\\x0B\\x0C\\xCC\\xDD\\xDD\\xDD\\xDD\\xDD\"\n\n#if defined(MBEDTLS_PKCS1_V15)\nstatic int myrand(void *rng_state, unsigned char *output, size_t len)\n{\n#if !defined(__OpenBSD__) && !defined(__NetBSD__)\n    size_t i;\n\n    if (rng_state != NULL) {\n        rng_state  = NULL;\n    }\n\n    for (i = 0; i < len; ++i) {\n        output[i] = rand();\n    }\n#else\n    if (rng_state != NULL) {\n        rng_state = NULL;\n    }\n\n    arc4random_buf(output, len);\n#endif /* !OpenBSD && !NetBSD */\n\n    return 0;\n}\n#endif /* MBEDTLS_PKCS1_V15 */\n\n/*\n * Checkup routine\n */\nint mbedtls_rsa_self_test(int verbose)\n{\n    int ret = 0;\n#if defined(MBEDTLS_PKCS1_V15)\n    size_t len;\n    mbedtls_rsa_context rsa;\n    unsigned char rsa_plaintext[PT_LEN];\n    unsigned char rsa_decrypted[PT_LEN];\n    unsigned char rsa_ciphertext[KEY_LEN];\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    unsigned char sha1sum[20];\n#endif\n\n    mbedtls_mpi K;\n\n    mbedtls_mpi_init(&K);\n    mbedtls_rsa_init(&rsa);\n\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_N));\n    MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, &K, NULL, NULL, NULL, NULL));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_P));\n    MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, &K, NULL, NULL, NULL));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_Q));\n    MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, NULL, &K, NULL, NULL));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_D));\n    MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, NULL, NULL, &K, NULL));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_E));\n    MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, NULL, NULL, NULL, &K));\n\n    MBEDTLS_MPI_CHK(mbedtls_rsa_complete(&rsa));\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  RSA key validation: \");\n    }\n\n    if (mbedtls_rsa_check_pubkey(&rsa) != 0 ||\n        mbedtls_rsa_check_privkey(&rsa) != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n\n        ret = 1;\n        goto cleanup;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n  PKCS#1 encryption : \");\n    }\n\n    memcpy(rsa_plaintext, RSA_PT, PT_LEN);\n\n    if (mbedtls_rsa_pkcs1_encrypt(&rsa, myrand, NULL,\n                                  PT_LEN, rsa_plaintext,\n                                  rsa_ciphertext) != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n\n        ret = 1;\n        goto cleanup;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n  PKCS#1 decryption : \");\n    }\n\n    if (mbedtls_rsa_pkcs1_decrypt(&rsa, myrand, NULL,\n                                  &len, rsa_ciphertext, rsa_decrypted,\n                                  sizeof(rsa_decrypted)) != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n\n        ret = 1;\n        goto cleanup;\n    }\n\n    if (memcmp(rsa_decrypted, rsa_plaintext, len) != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n\n        ret = 1;\n        goto cleanup;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    if (verbose != 0) {\n        mbedtls_printf(\"  PKCS#1 data sign  : \");\n    }\n\n    if (mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1),\n                   rsa_plaintext, PT_LEN, sha1sum) != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n\n        return 1;\n    }\n\n    if (mbedtls_rsa_pkcs1_sign(&rsa, myrand, NULL,\n                               MBEDTLS_MD_SHA1, 20,\n                               sha1sum, rsa_ciphertext) != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n\n        ret = 1;\n        goto cleanup;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n  PKCS#1 sig. verify: \");\n    }\n\n    if (mbedtls_rsa_pkcs1_verify(&rsa, MBEDTLS_MD_SHA1, 20,\n                                 sha1sum, rsa_ciphertext) != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n\n        ret = 1;\n        goto cleanup;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\ncleanup:\n    mbedtls_mpi_free(&K);\n    mbedtls_rsa_free(&rsa);\n#else /* MBEDTLS_PKCS1_V15 */\n    ((void) verbose);\n#endif /* MBEDTLS_PKCS1_V15 */\n    return ret;\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_RSA_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/rsa_alt_helpers.c",
    "content": "/*\n *  Helper functions for the RSA module\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n *\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_RSA_C)\n\n#include \"mbedtls/rsa.h\"\n#include \"mbedtls/bignum.h\"\n#include \"bignum_internal.h\"\n#include \"rsa_alt_helpers.h\"\n\n/*\n * Compute RSA prime factors from public and private exponents\n *\n * Summary of algorithm:\n * Setting F := lcm(P-1,Q-1), the idea is as follows:\n *\n * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2)\n *     is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the\n *     square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four\n *     possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1)\n *     or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime\n *     factors of N.\n *\n * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same\n *     construction still applies since (-)^K is the identity on the set of\n *     roots of 1 in Z/NZ.\n *\n * The public and private key primitives (-)^E and (-)^D are mutually inverse\n * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e.\n * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L.\n * Splitting L = 2^t * K with K odd, we have\n *\n *   DE - 1 = FL = (F/2) * (2^(t+1)) * K,\n *\n * so (F / 2) * K is among the numbers\n *\n *   (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord\n *\n * where ord is the order of 2 in (DE - 1).\n * We can therefore iterate through these numbers apply the construction\n * of (a) and (b) above to attempt to factor N.\n *\n */\nint mbedtls_rsa_deduce_primes(mbedtls_mpi const *N,\n                              mbedtls_mpi const *E, mbedtls_mpi const *D,\n                              mbedtls_mpi *P, mbedtls_mpi *Q)\n{\n    int ret = 0;\n\n    uint16_t attempt;  /* Number of current attempt  */\n    uint16_t iter;     /* Number of squares computed in the current attempt */\n\n    uint16_t order;    /* Order of 2 in DE - 1 */\n\n    mbedtls_mpi T;  /* Holds largest odd divisor of DE - 1     */\n    mbedtls_mpi K;  /* Temporary holding the current candidate */\n\n    const unsigned char primes[] = { 2,\n                                     3,    5,    7,   11,   13,   17,   19,   23,\n                                     29,   31,   37,   41,   43,   47,   53,   59,\n                                     61,   67,   71,   73,   79,   83,   89,   97,\n                                     101,  103,  107,  109,  113,  127,  131,  137,\n                                     139,  149,  151,  157,  163,  167,  173,  179,\n                                     181,  191,  193,  197,  199,  211,  223,  227,\n                                     229,  233,  239,  241,  251 };\n\n    const size_t num_primes = sizeof(primes) / sizeof(*primes);\n\n    if (P == NULL || Q == NULL || P->p != NULL || Q->p != NULL) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    if (mbedtls_mpi_cmp_int(N, 0) <= 0 ||\n        mbedtls_mpi_cmp_int(D, 1) <= 0 ||\n        mbedtls_mpi_cmp_mpi(D, N) >= 0 ||\n        mbedtls_mpi_cmp_int(E, 1) <= 0 ||\n        mbedtls_mpi_cmp_mpi(E, N) >= 0) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    /*\n     * Initializations and temporary changes\n     */\n\n    mbedtls_mpi_init(&K);\n    mbedtls_mpi_init(&T);\n\n    /* T := DE - 1 */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, D,  E));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&T, &T, 1));\n\n    if ((order = (uint16_t) mbedtls_mpi_lsb(&T)) == 0) {\n        ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n\n    /* After this operation, T holds the largest odd divisor of DE - 1. */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&T, order));\n\n    /*\n     * Actual work\n     */\n\n    /* Skip trying 2 if N == 1 mod 8 */\n    attempt = 0;\n    if (N->p[0] % 8 == 1) {\n        attempt = 1;\n    }\n\n    for (; attempt < num_primes; ++attempt) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&K, primes[attempt]));\n\n        /* Check if gcd(K,N) = 1 */\n        MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(P, NULL, &K, N));\n        if (mbedtls_mpi_cmp_int(P, 1) != 0) {\n            continue;\n        }\n\n        /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ...\n         * and check whether they have nontrivial GCD with N. */\n        MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &K, &T, N,\n                                            Q /* temporarily use Q for storing Montgomery\n                                               * multiplication helper values */));\n\n        for (iter = 1; iter <= order; ++iter) {\n            /* If we reach 1 prematurely, there's no point\n             * in continuing to square K */\n            if (mbedtls_mpi_cmp_int(&K, 1) == 0) {\n                break;\n            }\n\n            MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&K, &K, 1));\n            MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(P, NULL, &K, N));\n\n            if (mbedtls_mpi_cmp_int(P, 1) ==  1 &&\n                mbedtls_mpi_cmp_mpi(P, N) == -1) {\n                /*\n                 * Have found a nontrivial divisor P of N.\n                 * Set Q := N / P.\n                 */\n\n                MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(Q, NULL, N, P));\n                goto cleanup;\n            }\n\n            MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));\n            MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &K));\n            MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, N));\n        }\n\n        /*\n         * If we get here, then either we prematurely aborted the loop because\n         * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must\n         * be 1 if D,E,N were consistent.\n         * Check if that's the case and abort if not, to avoid very long,\n         * yet eventually failing, computations if N,D,E were not sane.\n         */\n        if (mbedtls_mpi_cmp_int(&K, 1) != 0) {\n            break;\n        }\n    }\n\n    ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n\ncleanup:\n\n    mbedtls_mpi_free(&K);\n    mbedtls_mpi_free(&T);\n    return ret;\n}\n\n/*\n * Given P, Q and the public exponent E, deduce D.\n * This is essentially a modular inversion.\n */\nint mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P,\n                                        mbedtls_mpi const *Q,\n                                        mbedtls_mpi const *E,\n                                        mbedtls_mpi *D)\n{\n    int ret = 0;\n    mbedtls_mpi K, L;\n\n    if (D == NULL || mbedtls_mpi_cmp_int(D, 0) != 0) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||\n        mbedtls_mpi_cmp_int(Q, 1) <= 0 ||\n        mbedtls_mpi_cmp_int(E, 0) == 0) {\n        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;\n    }\n\n    if (mbedtls_mpi_get_bit(E, 0) != 1) {\n        return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;\n    }\n\n    mbedtls_mpi_init(&K);\n    mbedtls_mpi_init(&L);\n\n    /* Temporarily put K := P-1 and L := Q-1 */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));\n\n    /* Temporarily put D := gcd(P-1, Q-1) */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(D, &K, &L));\n\n    /* K := LCM(P-1, Q-1) */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &L));\n    MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&K, NULL, &K, D));\n\n    /* Compute modular inverse of E mod LCM(P-1, Q-1)\n     * This is FIPS 186-4 §B.3.1 criterion 3(b).\n     * This will return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if E is not coprime to\n     * (P-1)(Q-1), also validating FIPS 186-4 §B.3.1 criterion 2(a). */\n    MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod_even_in_range(D, E, &K));\n\ncleanup:\n\n    mbedtls_mpi_free(&K);\n    mbedtls_mpi_free(&L);\n\n    return ret;\n}\n\nint mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,\n                           const mbedtls_mpi *D, mbedtls_mpi *DP,\n                           mbedtls_mpi *DQ, mbedtls_mpi *QP)\n{\n    int ret = 0;\n    mbedtls_mpi K;\n    mbedtls_mpi_init(&K);\n\n    /* DP = D mod P-1 */\n    if (DP != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DP, D, &K));\n    }\n\n    /* DQ = D mod Q-1 */\n    if (DQ != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DQ, D, &K));\n    }\n\n    /* QP = Q^{-1} mod P */\n    if (QP != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod_odd(QP, Q, P));\n    }\n\ncleanup:\n    mbedtls_mpi_free(&K);\n\n    return ret;\n}\n\n/*\n * Check that core RSA parameters are sane.\n */\nint mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P,\n                                const mbedtls_mpi *Q, const mbedtls_mpi *D,\n                                const mbedtls_mpi *E,\n                                int (*f_rng)(void *, unsigned char *, size_t),\n                                void *p_rng)\n{\n    int ret = 0;\n    mbedtls_mpi K, L;\n\n    mbedtls_mpi_init(&K);\n    mbedtls_mpi_init(&L);\n\n    /*\n     * Step 1: If PRNG provided, check that P and Q are prime\n     */\n\n#if defined(MBEDTLS_GENPRIME)\n    /*\n     * When generating keys, the strongest security we support aims for an error\n     * rate of at most 2^-100 and we are aiming for the same certainty here as\n     * well.\n     */\n    if (f_rng != NULL && P != NULL &&\n        (ret = mbedtls_mpi_is_prime_ext(P, 50, f_rng, p_rng)) != 0) {\n        ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n        goto cleanup;\n    }\n\n    if (f_rng != NULL && Q != NULL &&\n        (ret = mbedtls_mpi_is_prime_ext(Q, 50, f_rng, p_rng)) != 0) {\n        ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n        goto cleanup;\n    }\n#else\n    ((void) f_rng);\n    ((void) p_rng);\n#endif /* MBEDTLS_GENPRIME */\n\n    /*\n     * Step 2: Check that 1 < N = P * Q\n     */\n\n    if (P != NULL && Q != NULL && N != NULL) {\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, P, Q));\n        if (mbedtls_mpi_cmp_int(N, 1)  <= 0 ||\n            mbedtls_mpi_cmp_mpi(&K, N) != 0) {\n            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n            goto cleanup;\n        }\n    }\n\n    /*\n     * Step 3: Check and 1 < D, E < N if present.\n     */\n\n    if (N != NULL && D != NULL && E != NULL) {\n        if (mbedtls_mpi_cmp_int(D, 1) <= 0 ||\n            mbedtls_mpi_cmp_int(E, 1) <= 0 ||\n            mbedtls_mpi_cmp_mpi(D, N) >= 0 ||\n            mbedtls_mpi_cmp_mpi(E, N) >= 0) {\n            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n            goto cleanup;\n        }\n    }\n\n    /*\n     * Step 4: Check that D, E are inverse modulo P-1 and Q-1\n     */\n\n    if (P != NULL && Q != NULL && D != NULL && E != NULL) {\n        if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||\n            mbedtls_mpi_cmp_int(Q, 1) <= 0) {\n            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n            goto cleanup;\n        }\n\n        /* Compute DE-1 mod P-1 */\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, P, 1));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));\n        if (mbedtls_mpi_cmp_int(&K, 0) != 0) {\n            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n            goto cleanup;\n        }\n\n        /* Compute DE-1 mod Q-1 */\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));\n        if (mbedtls_mpi_cmp_int(&K, 0) != 0) {\n            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n            goto cleanup;\n        }\n    }\n\ncleanup:\n\n    mbedtls_mpi_free(&K);\n    mbedtls_mpi_free(&L);\n\n    /* Wrap MPI error codes by RSA check failure error code */\n    if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) {\n        ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n    }\n\n    return ret;\n}\n\n/*\n * Check that RSA CRT parameters are in accordance with core parameters.\n */\nint mbedtls_rsa_validate_crt(const mbedtls_mpi *P,  const mbedtls_mpi *Q,\n                             const mbedtls_mpi *D,  const mbedtls_mpi *DP,\n                             const mbedtls_mpi *DQ, const mbedtls_mpi *QP)\n{\n    int ret = 0;\n\n    mbedtls_mpi K, L;\n    mbedtls_mpi_init(&K);\n    mbedtls_mpi_init(&L);\n\n    /* Check that DP - D == 0 mod P - 1 */\n    if (DP != NULL) {\n        if (P == NULL) {\n            ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n            goto cleanup;\n        }\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DP, D));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));\n\n        if (mbedtls_mpi_cmp_int(&L, 0) != 0) {\n            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n            goto cleanup;\n        }\n    }\n\n    /* Check that DQ - D == 0 mod Q - 1 */\n    if (DQ != NULL) {\n        if (Q == NULL) {\n            ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n            goto cleanup;\n        }\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DQ, D));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));\n\n        if (mbedtls_mpi_cmp_int(&L, 0) != 0) {\n            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n            goto cleanup;\n        }\n    }\n\n    /* Check that QP * Q - 1 == 0 mod P */\n    if (QP != NULL) {\n        if (P == NULL || Q == NULL) {\n            ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;\n            goto cleanup;\n        }\n\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, QP, Q));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));\n        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, P));\n        if (mbedtls_mpi_cmp_int(&K, 0) != 0) {\n            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n            goto cleanup;\n        }\n    }\n\ncleanup:\n\n    /* Wrap MPI error codes by RSA check failure error code */\n    if (ret != 0 &&\n        ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&\n        ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) {\n        ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;\n    }\n\n    mbedtls_mpi_free(&K);\n    mbedtls_mpi_free(&L);\n\n    return ret;\n}\n\n#endif /* MBEDTLS_RSA_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/rsa_alt_helpers.h",
    "content": "/**\n * \\file rsa_alt_helpers.h\n *\n * \\brief Context-independent RSA helper functions\n *\n *  This module declares some RSA-related helper functions useful when\n *  implementing the RSA interface. These functions are provided in a separate\n *  compilation unit in order to make it easy for designers of alternative RSA\n *  implementations to use them in their own code, as it is conceived that the\n *  functionality they provide will be necessary for most complete\n *  implementations.\n *\n *  End-users of Mbed TLS who are not providing their own alternative RSA\n *  implementations should not use these functions directly, and should instead\n *  use only the functions declared in rsa.h.\n *\n *  The interface provided by this module will be maintained through LTS (Long\n *  Term Support) branches of Mbed TLS, but may otherwise be subject to change,\n *  and must be considered an internal interface of the library.\n *\n *  There are two classes of helper functions:\n *\n *  (1) Parameter-generating helpers. These are:\n *      - mbedtls_rsa_deduce_primes\n *      - mbedtls_rsa_deduce_private_exponent\n *      - mbedtls_rsa_deduce_crt\n *       Each of these functions takes a set of core RSA parameters and\n *       generates some other, or CRT related parameters.\n *\n *  (2) Parameter-checking helpers. These are:\n *      - mbedtls_rsa_validate_params\n *      - mbedtls_rsa_validate_crt\n *      They take a set of core or CRT related RSA parameters and check their\n *      validity.\n *\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_RSA_ALT_HELPERS_H\n#define MBEDTLS_RSA_ALT_HELPERS_H\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/bignum.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n/**\n * \\brief          Compute RSA prime moduli P, Q from public modulus N=PQ\n *                 and a pair of private and public key.\n *\n * \\note           This is a 'static' helper function not operating on\n *                 an RSA context. Alternative implementations need not\n *                 overwrite it.\n *\n * \\param N        RSA modulus N = PQ, with P, Q to be found\n * \\param E        RSA public exponent\n * \\param D        RSA private exponent\n * \\param P        Pointer to MPI holding first prime factor of N on success\n * \\param Q        Pointer to MPI holding second prime factor of N on success\n *\n * \\return\n *                 - 0 if successful. In this case, P and Q constitute a\n *                   factorization of N.\n *                 - A non-zero error code otherwise.\n *\n * \\note           It is neither checked that P, Q are prime nor that\n *                 D, E are modular inverses wrt. P-1 and Q-1. For that,\n *                 use the helper function \\c mbedtls_rsa_validate_params.\n *\n */\nint mbedtls_rsa_deduce_primes(mbedtls_mpi const *N, mbedtls_mpi const *E,\n                              mbedtls_mpi const *D,\n                              mbedtls_mpi *P, mbedtls_mpi *Q);\n\n/**\n * \\brief          Compute RSA private exponent from\n *                 prime moduli and public key.\n *\n * \\note           This is a 'static' helper function not operating on\n *                 an RSA context. Alternative implementations need not\n *                 overwrite it.\n *\n * \\param P        First prime factor of RSA modulus\n * \\param Q        Second prime factor of RSA modulus\n * \\param E        RSA public exponent\n * \\param D        Pointer to MPI holding the private exponent on success,\n *                 i.e. the modular inverse of E modulo LCM(P-1,Q-1).\n *\n * \\return         \\c 0 if successful.\n * \\return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.\n * \\return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if E is not coprime to P-1\n *                 and Q-1, that is, if GCD( E, (P-1)*(Q-1) ) != 1.\n * \\return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if inputs are otherwise\n *                 invalid.\n *\n * \\note           This function does not check whether P and Q are primes.\n *\n */\nint mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P,\n                                        mbedtls_mpi const *Q,\n                                        mbedtls_mpi const *E,\n                                        mbedtls_mpi *D);\n\n\n/**\n * \\brief          Generate RSA-CRT parameters\n *\n * \\note           This is a 'static' helper function not operating on\n *                 an RSA context. Alternative implementations need not\n *                 overwrite it.\n *\n * \\param P        First prime factor of N\n * \\param Q        Second prime factor of N\n * \\param D        RSA private exponent\n * \\param DP       Output variable for D modulo P-1\n * \\param DQ       Output variable for D modulo Q-1\n * \\param QP       Output variable for the modular inverse of Q modulo P.\n *\n * \\return         0 on success, non-zero error code otherwise.\n *\n * \\note           This function does not check whether P, Q are\n *                 prime and whether D is a valid private exponent.\n *\n */\nint mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,\n                           const mbedtls_mpi *D, mbedtls_mpi *DP,\n                           mbedtls_mpi *DQ, mbedtls_mpi *QP);\n\n\n/**\n * \\brief          Check validity of core RSA parameters\n *\n * \\note           This is a 'static' helper function not operating on\n *                 an RSA context. Alternative implementations need not\n *                 overwrite it.\n *\n * \\param N        RSA modulus N = PQ\n * \\param P        First prime factor of N\n * \\param Q        Second prime factor of N\n * \\param D        RSA private exponent\n * \\param E        RSA public exponent\n * \\param f_rng    PRNG to be used for primality check, or NULL\n * \\param p_rng    PRNG context for f_rng, or NULL\n *\n * \\return\n *                 - 0 if the following conditions are satisfied\n *                   if all relevant parameters are provided:\n *                    - P prime if f_rng != NULL (%)\n *                    - Q prime if f_rng != NULL (%)\n *                    - 1 < N = P * Q\n *                    - 1 < D, E < N\n *                    - D and E are modular inverses modulo P-1 and Q-1\n *                   (%) This is only done if MBEDTLS_GENPRIME is defined.\n *                 - A non-zero error code otherwise.\n *\n * \\note           The function can be used with a restricted set of arguments\n *                 to perform specific checks only. E.g., calling it with\n *                 (-,P,-,-,-) and a PRNG amounts to a primality check for P.\n */\nint mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P,\n                                const mbedtls_mpi *Q, const mbedtls_mpi *D,\n                                const mbedtls_mpi *E,\n                                int (*f_rng)(void *, unsigned char *, size_t),\n                                void *p_rng);\n\n/**\n * \\brief          Check validity of RSA CRT parameters\n *\n * \\note           This is a 'static' helper function not operating on\n *                 an RSA context. Alternative implementations need not\n *                 overwrite it.\n *\n * \\param P        First prime factor of RSA modulus\n * \\param Q        Second prime factor of RSA modulus\n * \\param D        RSA private exponent\n * \\param DP       MPI to check for D modulo P-1\n * \\param DQ       MPI to check for D modulo P-1\n * \\param QP       MPI to check for the modular inverse of Q modulo P.\n *\n * \\return\n *                 - 0 if the following conditions are satisfied:\n *                    - D = DP mod P-1 if P, D, DP != NULL\n *                    - Q = DQ mod P-1 if P, D, DQ != NULL\n *                    - QP = Q^-1 mod P if P, Q, QP != NULL\n *                 - \\c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed,\n *                   potentially including \\c MBEDTLS_ERR_MPI_XXX if some\n *                   MPI calculations failed.\n *                 - \\c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient\n *                   data was provided to check DP, DQ or QP.\n *\n * \\note           The function can be used with a restricted set of arguments\n *                 to perform specific checks only. E.g., calling it with the\n *                 parameters (P, -, D, DP, -, -) will check DP = D mod P-1.\n */\nint mbedtls_rsa_validate_crt(const mbedtls_mpi *P,  const mbedtls_mpi *Q,\n                             const mbedtls_mpi *D,  const mbedtls_mpi *DP,\n                             const mbedtls_mpi *DQ, const mbedtls_mpi *QP);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* rsa_alt_helpers.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/rsa_internal.h",
    "content": "/**\n * \\file rsa_internal.h\n *\n * \\brief Internal-only RSA public-key cryptosystem API.\n *\n * This file declares RSA-related functions that are to be used\n * only from within the Mbed TLS library itself.\n *\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_RSA_INTERNAL_H\n#define MBEDTLS_RSA_INTERNAL_H\n\n#include \"mbedtls/rsa.h\"\n#include \"mbedtls/asn1.h\"\n\n/**\n * \\brief           Parse a PKCS#1 (ASN.1) encoded private RSA key.\n *\n * \\param rsa       The RSA context where parsed data will be stored.\n * \\param key       The buffer that contains the key.\n * \\param keylen    The length of the key buffer in bytes.\n *\n * \\return          0 on success.\n * \\return          MBEDTLS_ERR_ASN1_xxx in case of ASN.1 parsing errors.\n * \\return          MBEDTLS_ERR_RSA_xxx in case of RSA internal failures while\n *                  parsing data.\n * \\return          MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if validity checks on the\n *                  provided key fail.\n */\nint mbedtls_rsa_parse_key(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen);\n\n/**\n * \\brief           Parse a PKCS#1 (ASN.1) encoded public RSA key.\n *\n * \\param rsa       The RSA context where parsed data will be stored.\n * \\param key       The buffer that contains the key.\n * \\param keylen    The length of the key buffer in bytes.\n *\n * \\return          0 on success.\n * \\return          MBEDTLS_ERR_ASN1_xxx in case of ASN.1 parsing errors.\n * \\return          MBEDTLS_ERR_RSA_xxx in case of RSA internal failures while\n *                  parsing data.\n * \\return          MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if validity checks on the\n *                  provided key fail.\n */\nint mbedtls_rsa_parse_pubkey(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen);\n\n/**\n * \\brief           Write a PKCS#1 (ASN.1) encoded private RSA key.\n *\n * \\param rsa       The RSA context which contains the data to be written.\n * \\param start     Beginning of the buffer that will be filled with the\n *                  private key.\n * \\param p         End of the buffer that will be filled with the private key.\n *                  On successful return, the referenced pointer will be\n *                  updated in order to point to the beginning of written data.\n *\n * \\return          On success, the number of bytes written to the output buffer\n *                  (i.e. a value > 0).\n * \\return          MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the RSA context does not\n *                  contain a valid key pair.\n * \\return          MBEDTLS_ERR_ASN1_xxx in case of failure while writing to the\n *                  output buffer.\n *\n * \\note            The output buffer is filled backward, i.e. starting from its\n *                  end and moving toward its start.\n */\nint mbedtls_rsa_write_key(const mbedtls_rsa_context *rsa, unsigned char *start,\n                          unsigned char **p);\n\n/**\n * \\brief           Parse a PKCS#1 (ASN.1) encoded public RSA key.\n *\n * \\param rsa       The RSA context which contains the data to be written.\n * \\param start     Beginning of the buffer that will be filled with the\n *                  private key.\n * \\param p         End of the buffer that will be filled with the private key.\n *                  On successful return, the referenced pointer will be\n *                  updated in order to point to the beginning of written data.\n *\n * \\return          On success, the number of bytes written to the output buffer\n *                  (i.e. a value > 0).\n * \\return          MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the RSA context does not\n *                  contain a valid public key.\n * \\return          MBEDTLS_ERR_ASN1_xxx in case of failure while writing to the\n *                  output buffer.\n *\n * \\note            The output buffer is filled backward, i.e. starting from its\n *                  end and moving toward its start.\n */\nint mbedtls_rsa_write_pubkey(const mbedtls_rsa_context *rsa, unsigned char *start,\n                             unsigned char **p);\n\n#if defined(MBEDTLS_PKCS1_V21)\n/**\n * \\brief This function is analogue to \\c mbedtls_rsa_rsassa_pss_sign().\n *        The only difference between them is that this function is more flexible\n *        on the parameters of \\p ctx that are set with \\c mbedtls_rsa_set_padding().\n *\n * \\note  Compared to its counterpart, this function:\n *        - does not check the padding setting of \\p ctx.\n *        - allows the hash_id of \\p ctx to be MBEDTLS_MD_NONE,\n *          in which case it uses \\p md_alg as the hash_id.\n *\n * \\note  Refer to \\c mbedtls_rsa_rsassa_pss_sign() for a description\n *        of the functioning and parameters of this function.\n */\nint mbedtls_rsa_rsassa_pss_sign_no_mode_check(mbedtls_rsa_context *ctx,\n                                              int (*f_rng)(void *, unsigned char *, size_t),\n                                              void *p_rng,\n                                              mbedtls_md_type_t md_alg,\n                                              unsigned int hashlen,\n                                              const unsigned char *hash,\n                                              unsigned char *sig);\n#endif /* MBEDTLS_PKCS1_V21 */\n\n#endif /* rsa_internal.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/sha1.c",
    "content": "/*\n *  FIPS-180-1 compliant SHA-1 implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  The SHA-1 standard was published by NIST in 1993.\n *\n *  http://www.itl.nist.gov/fipspubs/fip180-1.htm\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SHA1_C)\n\n#include \"mbedtls/sha1.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#if !defined(MBEDTLS_SHA1_ALT)\n\nvoid mbedtls_sha1_init(mbedtls_sha1_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_sha1_context));\n}\n\nvoid mbedtls_sha1_free(mbedtls_sha1_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha1_context));\n}\n\nvoid mbedtls_sha1_clone(mbedtls_sha1_context *dst,\n                        const mbedtls_sha1_context *src)\n{\n    *dst = *src;\n}\n\n/*\n * SHA-1 context setup\n */\nint mbedtls_sha1_starts(mbedtls_sha1_context *ctx)\n{\n    ctx->total[0] = 0;\n    ctx->total[1] = 0;\n\n    ctx->state[0] = 0x67452301;\n    ctx->state[1] = 0xEFCDAB89;\n    ctx->state[2] = 0x98BADCFE;\n    ctx->state[3] = 0x10325476;\n    ctx->state[4] = 0xC3D2E1F0;\n\n    return 0;\n}\n\n#if !defined(MBEDTLS_SHA1_PROCESS_ALT)\nint mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx,\n                                  const unsigned char data[64])\n{\n    struct {\n        uint32_t temp, W[16], A, B, C, D, E;\n    } local;\n\n    local.W[0] = MBEDTLS_GET_UINT32_BE(data,  0);\n    local.W[1] = MBEDTLS_GET_UINT32_BE(data,  4);\n    local.W[2] = MBEDTLS_GET_UINT32_BE(data,  8);\n    local.W[3] = MBEDTLS_GET_UINT32_BE(data, 12);\n    local.W[4] = MBEDTLS_GET_UINT32_BE(data, 16);\n    local.W[5] = MBEDTLS_GET_UINT32_BE(data, 20);\n    local.W[6] = MBEDTLS_GET_UINT32_BE(data, 24);\n    local.W[7] = MBEDTLS_GET_UINT32_BE(data, 28);\n    local.W[8] = MBEDTLS_GET_UINT32_BE(data, 32);\n    local.W[9] = MBEDTLS_GET_UINT32_BE(data, 36);\n    local.W[10] = MBEDTLS_GET_UINT32_BE(data, 40);\n    local.W[11] = MBEDTLS_GET_UINT32_BE(data, 44);\n    local.W[12] = MBEDTLS_GET_UINT32_BE(data, 48);\n    local.W[13] = MBEDTLS_GET_UINT32_BE(data, 52);\n    local.W[14] = MBEDTLS_GET_UINT32_BE(data, 56);\n    local.W[15] = MBEDTLS_GET_UINT32_BE(data, 60);\n\n#define S(x, n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))\n\n#define R(t)                                                    \\\n    (                                                           \\\n        local.temp = local.W[((t) -  3) & 0x0F] ^             \\\n                     local.W[((t) -  8) & 0x0F] ^             \\\n                     local.W[((t) - 14) & 0x0F] ^             \\\n                     local.W[(t)        & 0x0F],              \\\n        (local.W[(t) & 0x0F] = S(local.temp, 1))               \\\n    )\n\n#define P(a, b, c, d, e, x)                                          \\\n    do                                                          \\\n    {                                                           \\\n        (e) += S((a), 5) + F((b), (c), (d)) + K + (x);             \\\n        (b) = S((b), 30);                                        \\\n    } while (0)\n\n    local.A = ctx->state[0];\n    local.B = ctx->state[1];\n    local.C = ctx->state[2];\n    local.D = ctx->state[3];\n    local.E = ctx->state[4];\n\n#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))\n#define K 0x5A827999\n\n    P(local.A, local.B, local.C, local.D, local.E, local.W[0]);\n    P(local.E, local.A, local.B, local.C, local.D, local.W[1]);\n    P(local.D, local.E, local.A, local.B, local.C, local.W[2]);\n    P(local.C, local.D, local.E, local.A, local.B, local.W[3]);\n    P(local.B, local.C, local.D, local.E, local.A, local.W[4]);\n    P(local.A, local.B, local.C, local.D, local.E, local.W[5]);\n    P(local.E, local.A, local.B, local.C, local.D, local.W[6]);\n    P(local.D, local.E, local.A, local.B, local.C, local.W[7]);\n    P(local.C, local.D, local.E, local.A, local.B, local.W[8]);\n    P(local.B, local.C, local.D, local.E, local.A, local.W[9]);\n    P(local.A, local.B, local.C, local.D, local.E, local.W[10]);\n    P(local.E, local.A, local.B, local.C, local.D, local.W[11]);\n    P(local.D, local.E, local.A, local.B, local.C, local.W[12]);\n    P(local.C, local.D, local.E, local.A, local.B, local.W[13]);\n    P(local.B, local.C, local.D, local.E, local.A, local.W[14]);\n    P(local.A, local.B, local.C, local.D, local.E, local.W[15]);\n    P(local.E, local.A, local.B, local.C, local.D, R(16));\n    P(local.D, local.E, local.A, local.B, local.C, R(17));\n    P(local.C, local.D, local.E, local.A, local.B, R(18));\n    P(local.B, local.C, local.D, local.E, local.A, R(19));\n\n#undef K\n#undef F\n\n#define F(x, y, z) ((x) ^ (y) ^ (z))\n#define K 0x6ED9EBA1\n\n    P(local.A, local.B, local.C, local.D, local.E, R(20));\n    P(local.E, local.A, local.B, local.C, local.D, R(21));\n    P(local.D, local.E, local.A, local.B, local.C, R(22));\n    P(local.C, local.D, local.E, local.A, local.B, R(23));\n    P(local.B, local.C, local.D, local.E, local.A, R(24));\n    P(local.A, local.B, local.C, local.D, local.E, R(25));\n    P(local.E, local.A, local.B, local.C, local.D, R(26));\n    P(local.D, local.E, local.A, local.B, local.C, R(27));\n    P(local.C, local.D, local.E, local.A, local.B, R(28));\n    P(local.B, local.C, local.D, local.E, local.A, R(29));\n    P(local.A, local.B, local.C, local.D, local.E, R(30));\n    P(local.E, local.A, local.B, local.C, local.D, R(31));\n    P(local.D, local.E, local.A, local.B, local.C, R(32));\n    P(local.C, local.D, local.E, local.A, local.B, R(33));\n    P(local.B, local.C, local.D, local.E, local.A, R(34));\n    P(local.A, local.B, local.C, local.D, local.E, R(35));\n    P(local.E, local.A, local.B, local.C, local.D, R(36));\n    P(local.D, local.E, local.A, local.B, local.C, R(37));\n    P(local.C, local.D, local.E, local.A, local.B, R(38));\n    P(local.B, local.C, local.D, local.E, local.A, R(39));\n\n#undef K\n#undef F\n\n#define F(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))\n#define K 0x8F1BBCDC\n\n    P(local.A, local.B, local.C, local.D, local.E, R(40));\n    P(local.E, local.A, local.B, local.C, local.D, R(41));\n    P(local.D, local.E, local.A, local.B, local.C, R(42));\n    P(local.C, local.D, local.E, local.A, local.B, R(43));\n    P(local.B, local.C, local.D, local.E, local.A, R(44));\n    P(local.A, local.B, local.C, local.D, local.E, R(45));\n    P(local.E, local.A, local.B, local.C, local.D, R(46));\n    P(local.D, local.E, local.A, local.B, local.C, R(47));\n    P(local.C, local.D, local.E, local.A, local.B, R(48));\n    P(local.B, local.C, local.D, local.E, local.A, R(49));\n    P(local.A, local.B, local.C, local.D, local.E, R(50));\n    P(local.E, local.A, local.B, local.C, local.D, R(51));\n    P(local.D, local.E, local.A, local.B, local.C, R(52));\n    P(local.C, local.D, local.E, local.A, local.B, R(53));\n    P(local.B, local.C, local.D, local.E, local.A, R(54));\n    P(local.A, local.B, local.C, local.D, local.E, R(55));\n    P(local.E, local.A, local.B, local.C, local.D, R(56));\n    P(local.D, local.E, local.A, local.B, local.C, R(57));\n    P(local.C, local.D, local.E, local.A, local.B, R(58));\n    P(local.B, local.C, local.D, local.E, local.A, R(59));\n\n#undef K\n#undef F\n\n#define F(x, y, z) ((x) ^ (y) ^ (z))\n#define K 0xCA62C1D6\n\n    P(local.A, local.B, local.C, local.D, local.E, R(60));\n    P(local.E, local.A, local.B, local.C, local.D, R(61));\n    P(local.D, local.E, local.A, local.B, local.C, R(62));\n    P(local.C, local.D, local.E, local.A, local.B, R(63));\n    P(local.B, local.C, local.D, local.E, local.A, R(64));\n    P(local.A, local.B, local.C, local.D, local.E, R(65));\n    P(local.E, local.A, local.B, local.C, local.D, R(66));\n    P(local.D, local.E, local.A, local.B, local.C, R(67));\n    P(local.C, local.D, local.E, local.A, local.B, R(68));\n    P(local.B, local.C, local.D, local.E, local.A, R(69));\n    P(local.A, local.B, local.C, local.D, local.E, R(70));\n    P(local.E, local.A, local.B, local.C, local.D, R(71));\n    P(local.D, local.E, local.A, local.B, local.C, R(72));\n    P(local.C, local.D, local.E, local.A, local.B, R(73));\n    P(local.B, local.C, local.D, local.E, local.A, R(74));\n    P(local.A, local.B, local.C, local.D, local.E, R(75));\n    P(local.E, local.A, local.B, local.C, local.D, R(76));\n    P(local.D, local.E, local.A, local.B, local.C, R(77));\n    P(local.C, local.D, local.E, local.A, local.B, R(78));\n    P(local.B, local.C, local.D, local.E, local.A, R(79));\n\n#undef K\n#undef F\n\n    ctx->state[0] += local.A;\n    ctx->state[1] += local.B;\n    ctx->state[2] += local.C;\n    ctx->state[3] += local.D;\n    ctx->state[4] += local.E;\n\n    /* Zeroise buffers and variables to clear sensitive data from memory. */\n    mbedtls_platform_zeroize(&local, sizeof(local));\n\n    return 0;\n}\n\n#endif /* !MBEDTLS_SHA1_PROCESS_ALT */\n\n/*\n * SHA-1 process buffer\n */\nint mbedtls_sha1_update(mbedtls_sha1_context *ctx,\n                        const unsigned char *input,\n                        size_t ilen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t fill;\n    uint32_t left;\n\n    if (ilen == 0) {\n        return 0;\n    }\n\n    left = ctx->total[0] & 0x3F;\n    fill = 64 - left;\n\n    ctx->total[0] += (uint32_t) ilen;\n    ctx->total[0] &= 0xFFFFFFFF;\n\n    if (ctx->total[0] < (uint32_t) ilen) {\n        ctx->total[1]++;\n    }\n\n    if (left && ilen >= fill) {\n        memcpy((void *) (ctx->buffer + left), input, fill);\n\n        if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) {\n            return ret;\n        }\n\n        input += fill;\n        ilen  -= fill;\n        left = 0;\n    }\n\n    while (ilen >= 64) {\n        if ((ret = mbedtls_internal_sha1_process(ctx, input)) != 0) {\n            return ret;\n        }\n\n        input += 64;\n        ilen  -= 64;\n    }\n\n    if (ilen > 0) {\n        memcpy((void *) (ctx->buffer + left), input, ilen);\n    }\n\n    return 0;\n}\n\n/*\n * SHA-1 final digest\n */\nint mbedtls_sha1_finish(mbedtls_sha1_context *ctx,\n                        unsigned char output[20])\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    uint32_t used;\n    uint32_t high, low;\n\n    /*\n     * Add padding: 0x80 then 0x00 until 8 bytes remain for the length\n     */\n    used = ctx->total[0] & 0x3F;\n\n    ctx->buffer[used++] = 0x80;\n\n    if (used <= 56) {\n        /* Enough room for padding + length in current block */\n        memset(ctx->buffer + used, 0, 56 - used);\n    } else {\n        /* We'll need an extra block */\n        memset(ctx->buffer + used, 0, 64 - used);\n\n        if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) {\n            goto exit;\n        }\n\n        memset(ctx->buffer, 0, 56);\n    }\n\n    /*\n     * Add message length\n     */\n    high = (ctx->total[0] >> 29)\n           | (ctx->total[1] <<  3);\n    low  = (ctx->total[0] <<  3);\n\n    MBEDTLS_PUT_UINT32_BE(high, ctx->buffer, 56);\n    MBEDTLS_PUT_UINT32_BE(low,  ctx->buffer, 60);\n\n    if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) {\n        goto exit;\n    }\n\n    /*\n     * Output final state\n     */\n    MBEDTLS_PUT_UINT32_BE(ctx->state[0], output,  0);\n    MBEDTLS_PUT_UINT32_BE(ctx->state[1], output,  4);\n    MBEDTLS_PUT_UINT32_BE(ctx->state[2], output,  8);\n    MBEDTLS_PUT_UINT32_BE(ctx->state[3], output, 12);\n    MBEDTLS_PUT_UINT32_BE(ctx->state[4], output, 16);\n\n    ret = 0;\n\nexit:\n    mbedtls_sha1_free(ctx);\n    return ret;\n}\n\n#endif /* !MBEDTLS_SHA1_ALT */\n\n/*\n * output = SHA-1( input buffer )\n */\nint mbedtls_sha1(const unsigned char *input,\n                 size_t ilen,\n                 unsigned char output[20])\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_sha1_context ctx;\n\n    mbedtls_sha1_init(&ctx);\n\n    if ((ret = mbedtls_sha1_starts(&ctx)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_sha1_update(&ctx, input, ilen)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_sha1_finish(&ctx, output)) != 0) {\n        goto exit;\n    }\n\nexit:\n    mbedtls_sha1_free(&ctx);\n    return ret;\n}\n\n#if defined(MBEDTLS_SELF_TEST)\n/*\n * FIPS-180-1 test vectors\n */\nstatic const unsigned char sha1_test_buf[3][57] =\n{\n    { \"abc\" },\n    { \"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\" },\n    { \"\" }\n};\n\nstatic const size_t sha1_test_buflen[3] =\n{\n    3, 56, 1000\n};\n\nstatic const unsigned char sha1_test_sum[3][20] =\n{\n    { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,\n      0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },\n    { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,\n      0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },\n    { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,\n      0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }\n};\n\n/*\n * Checkup routine\n */\nint mbedtls_sha1_self_test(int verbose)\n{\n    int i, j, buflen, ret = 0;\n    unsigned char buf[1024];\n    unsigned char sha1sum[20];\n    mbedtls_sha1_context ctx;\n\n    mbedtls_sha1_init(&ctx);\n\n    /*\n     * SHA-1\n     */\n    for (i = 0; i < 3; i++) {\n        if (verbose != 0) {\n            mbedtls_printf(\"  SHA-1 test #%d: \", i + 1);\n        }\n\n        if ((ret = mbedtls_sha1_starts(&ctx)) != 0) {\n            goto fail;\n        }\n\n        if (i == 2) {\n            memset(buf, 'a', buflen = 1000);\n\n            for (j = 0; j < 1000; j++) {\n                ret = mbedtls_sha1_update(&ctx, buf, buflen);\n                if (ret != 0) {\n                    goto fail;\n                }\n            }\n        } else {\n            ret = mbedtls_sha1_update(&ctx, sha1_test_buf[i],\n                                      sha1_test_buflen[i]);\n            if (ret != 0) {\n                goto fail;\n            }\n        }\n\n        if ((ret = mbedtls_sha1_finish(&ctx, sha1sum)) != 0) {\n            goto fail;\n        }\n\n        if (memcmp(sha1sum, sha1_test_sum[i], 20) != 0) {\n            ret = 1;\n            goto fail;\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    goto exit;\n\nfail:\n    if (verbose != 0) {\n        mbedtls_printf(\"failed\\n\");\n    }\n\nexit:\n    mbedtls_sha1_free(&ctx);\n\n    return ret;\n}\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_SHA1_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/sha256.c",
    "content": "/*\n *  FIPS-180-2 compliant SHA-256 implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  The SHA-256 Secure Hash Standard was published by NIST in 2002.\n *\n *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf\n */\n\n#if defined(__clang__) &&  (__clang_major__ >= 4)\n\n/* Ideally, we would simply use MBEDTLS_ARCH_IS_ARMV8_A in the following #if,\n * but that is defined by build_info.h, and we need this block to happen first. */\n#if defined(__ARM_ARCH) && (__ARM_ARCH_PROFILE == 'A')\n#if __ARM_ARCH >= 8\n#define MBEDTLS_SHA256_ARCH_IS_ARMV8_A\n#endif\n#endif\n\n#if defined(MBEDTLS_SHA256_ARCH_IS_ARMV8_A) && !defined(__ARM_FEATURE_CRYPTO)\n/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged.\n *\n * The intrinsic declaration are guarded by predefined ACLE macros in clang:\n * these are normally only enabled by the -march option on the command line.\n * By defining the macros ourselves we gain access to those declarations without\n * requiring -march on the command line.\n *\n * `arm_neon.h` is included by common.h, so we put these defines\n * at the top of this file, before any includes.\n */\n#define __ARM_FEATURE_CRYPTO 1\n/* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions\n *\n * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it\n * for older compilers.\n */\n#define __ARM_FEATURE_SHA2   1\n#define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG\n#endif\n\n#endif /* defined(__clang__) &&  (__clang_major__ >= 4) */\n\n/* Ensure that SIG_SETMASK is defined when -std=c99 is used. */\n#if !defined(_GNU_SOURCE)\n#define _GNU_SOURCE\n#endif\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA224_C)\n\n#include \"mbedtls/sha256.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#if defined(MBEDTLS_ARCH_IS_ARMV8_A)\n\n#  if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \\\n    defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)\n#       if !defined(MBEDTLS_HAVE_NEON_INTRINSICS)\n#           if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)\n#               warning \"Target does not support NEON instructions\"\n#               undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT\n#           else\n#               error \"Target does not support NEON instructions\"\n#           endif\n#       endif\n#   endif\n\n#  if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \\\n    defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)\n/* *INDENT-OFF* */\n\n#   if !defined(__ARM_FEATURE_CRYPTO) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)\n#      if defined(__ARMCOMPILER_VERSION)\n#        if __ARMCOMPILER_VERSION <= 6090000\n#          error \"Must use minimum -march=armv8-a+crypto for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*\"\n#        endif\n#          pragma clang attribute push (__attribute__((target(\"sha2\"))), apply_to=function)\n#          define MBEDTLS_POP_TARGET_PRAGMA\n#      elif defined(__clang__)\n#        if __clang_major__ < 4\n#          error \"A more recent Clang is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*\"\n#        endif\n#        pragma clang attribute push (__attribute__((target(\"crypto\"))), apply_to=function)\n#        define MBEDTLS_POP_TARGET_PRAGMA\n#      elif defined(__GNUC__)\n         /* FIXME: GCC 5 claims to support Armv8 Crypto Extensions, but some\n          *        intrinsics are missing. Missing intrinsics could be worked around.\n          */\n#        if __GNUC__ < 6\n#          error \"A more recent GCC is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*\"\n#        else\n#          pragma GCC push_options\n#          pragma GCC target (\"arch=armv8-a+crypto\")\n#          define MBEDTLS_POP_TARGET_PRAGMA\n#        endif\n#      else\n#        error \"Only GCC and Clang supported for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*\"\n#      endif\n#    endif\n/* *INDENT-ON* */\n\n#  endif\n#  if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)\n#    if defined(__unix__)\n#      if defined(__linux__)\n/* Our preferred method of detection is getauxval() */\n#        include <sys/auxv.h>\n/* These are not always defined via sys/auxv.h */\n#        if !defined(HWCAP_SHA2)\n#          define HWCAP_SHA2  (1 << 6)\n#        endif\n#        if !defined(HWCAP2_SHA2)\n#          define HWCAP2_SHA2 (1 << 3)\n#        endif\n#      endif\n/* Use SIGILL on Unix, and fall back to it on Linux */\n#      include <signal.h>\n#    endif\n#  endif\n#elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)\n#  undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY\n#  undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT\n#endif\n\n#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)\n/*\n * Capability detection code comes early, so we can disable\n * MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT if no detection mechanism found\n */\n#if defined(MBEDTLS_ARCH_IS_ARM64) && defined(HWCAP_SHA2)\nstatic int mbedtls_a64_crypto_sha256_determine_support(void)\n{\n    return (getauxval(AT_HWCAP) & HWCAP_SHA2) ? 1 : 0;\n}\n#elif defined(MBEDTLS_ARCH_IS_ARM32) && defined(HWCAP2_SHA2)\nstatic int mbedtls_a64_crypto_sha256_determine_support(void)\n{\n    return (getauxval(AT_HWCAP2) & HWCAP2_SHA2) ? 1 : 0;\n}\n#elif defined(__APPLE__)\nstatic int mbedtls_a64_crypto_sha256_determine_support(void)\n{\n    return 1;\n}\n#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#include <Windows.h>\n#include <processthreadsapi.h>\n\nstatic int mbedtls_a64_crypto_sha256_determine_support(void)\n{\n    return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ?\n           1 : 0;\n}\n#elif defined(__unix__) && defined(SIG_SETMASK)\n/* Detection with SIGILL, setjmp() and longjmp() */\n#include <signal.h>\n#include <setjmp.h>\n\nstatic jmp_buf return_from_sigill;\n\n/*\n * Armv8-A SHA256 support detection via SIGILL\n */\nstatic void sigill_handler(int signal)\n{\n    (void) signal;\n    longjmp(return_from_sigill, 1);\n}\n\nstatic int mbedtls_a64_crypto_sha256_determine_support(void)\n{\n    struct sigaction old_action, new_action;\n\n    sigset_t old_mask;\n    if (sigprocmask(0, NULL, &old_mask)) {\n        return 0;\n    }\n\n    sigemptyset(&new_action.sa_mask);\n    new_action.sa_flags = 0;\n    new_action.sa_handler = sigill_handler;\n\n    sigaction(SIGILL, &new_action, &old_action);\n\n    static int ret = 0;\n\n    if (setjmp(return_from_sigill) == 0) {         /* First return only */\n        /* If this traps, we will return a second time from setjmp() with 1 */\n#if defined(MBEDTLS_ARCH_IS_ARM64)\n        asm volatile (\"sha256h q0, q0, v0.4s\" : : : \"v0\");\n#else\n        asm volatile (\"sha256h.32 q0, q0, q0\" : : : \"q0\");\n#endif\n        ret = 1;\n    }\n\n    sigaction(SIGILL, &old_action, NULL);\n    sigprocmask(SIG_SETMASK, &old_mask, NULL);\n\n    return ret;\n}\n#else\n#warning \"No mechanism to detect ARMV8_CRYPTO found, using C code only\"\n#undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT\n#endif  /* HWCAP_SHA2, __APPLE__, __unix__ && SIG_SETMASK */\n\n#endif  /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */\n\n#if !defined(MBEDTLS_SHA256_ALT)\n\n#define SHA256_BLOCK_SIZE 64\n\nvoid mbedtls_sha256_init(mbedtls_sha256_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_sha256_context));\n}\n\nvoid mbedtls_sha256_free(mbedtls_sha256_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha256_context));\n}\n\nvoid mbedtls_sha256_clone(mbedtls_sha256_context *dst,\n                          const mbedtls_sha256_context *src)\n{\n    *dst = *src;\n}\n\n/*\n * SHA-256 context setup\n */\nint mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224)\n{\n#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)\n    if (is224 != 0 && is224 != 1) {\n        return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;\n    }\n#elif defined(MBEDTLS_SHA256_C)\n    if (is224 != 0) {\n        return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;\n    }\n#else /* defined MBEDTLS_SHA224_C only */\n    if (is224 == 0) {\n        return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;\n    }\n#endif\n\n    ctx->total[0] = 0;\n    ctx->total[1] = 0;\n\n    if (is224 == 0) {\n#if defined(MBEDTLS_SHA256_C)\n        ctx->state[0] = 0x6A09E667;\n        ctx->state[1] = 0xBB67AE85;\n        ctx->state[2] = 0x3C6EF372;\n        ctx->state[3] = 0xA54FF53A;\n        ctx->state[4] = 0x510E527F;\n        ctx->state[5] = 0x9B05688C;\n        ctx->state[6] = 0x1F83D9AB;\n        ctx->state[7] = 0x5BE0CD19;\n#endif\n    } else {\n#if defined(MBEDTLS_SHA224_C)\n        ctx->state[0] = 0xC1059ED8;\n        ctx->state[1] = 0x367CD507;\n        ctx->state[2] = 0x3070DD17;\n        ctx->state[3] = 0xF70E5939;\n        ctx->state[4] = 0xFFC00B31;\n        ctx->state[5] = 0x68581511;\n        ctx->state[6] = 0x64F98FA7;\n        ctx->state[7] = 0xBEFA4FA4;\n#endif\n    }\n\n#if defined(MBEDTLS_SHA224_C)\n    ctx->is224 = is224;\n#endif\n\n    return 0;\n}\n\n#if !defined(MBEDTLS_SHA256_PROCESS_ALT)\nstatic const uint32_t K[] =\n{\n    0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,\n    0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,\n    0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,\n    0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,\n    0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,\n    0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,\n    0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,\n    0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,\n    0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,\n    0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,\n    0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,\n    0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,\n    0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,\n    0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,\n    0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,\n    0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,\n};\n\n#endif\n\n#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \\\n    defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)\n\n#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)\n#  define mbedtls_internal_sha256_process_many_a64_crypto mbedtls_internal_sha256_process_many\n#  define mbedtls_internal_sha256_process_a64_crypto      mbedtls_internal_sha256_process\n#endif\n\nstatic size_t mbedtls_internal_sha256_process_many_a64_crypto(\n    mbedtls_sha256_context *ctx, const uint8_t *msg, size_t len)\n{\n    uint32x4_t abcd = vld1q_u32(&ctx->state[0]);\n    uint32x4_t efgh = vld1q_u32(&ctx->state[4]);\n\n    size_t processed = 0;\n\n    for (;\n         len >= SHA256_BLOCK_SIZE;\n         processed += SHA256_BLOCK_SIZE,\n         msg += SHA256_BLOCK_SIZE,\n         len -= SHA256_BLOCK_SIZE) {\n        uint32x4_t tmp, abcd_prev;\n\n        uint32x4_t abcd_orig = abcd;\n        uint32x4_t efgh_orig = efgh;\n\n        uint32x4_t sched0 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 0));\n        uint32x4_t sched1 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 1));\n        uint32x4_t sched2 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 2));\n        uint32x4_t sched3 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 3));\n\n#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__  /* Will be true if not defined */\n                                               /* Untested on BE */\n        sched0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched0)));\n        sched1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched1)));\n        sched2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched2)));\n        sched3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched3)));\n#endif\n\n        /* Rounds 0 to 3 */\n        tmp = vaddq_u32(sched0, vld1q_u32(&K[0]));\n        abcd_prev = abcd;\n        abcd = vsha256hq_u32(abcd_prev, efgh, tmp);\n        efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);\n\n        /* Rounds 4 to 7 */\n        tmp = vaddq_u32(sched1, vld1q_u32(&K[4]));\n        abcd_prev = abcd;\n        abcd = vsha256hq_u32(abcd_prev, efgh, tmp);\n        efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);\n\n        /* Rounds 8 to 11 */\n        tmp = vaddq_u32(sched2, vld1q_u32(&K[8]));\n        abcd_prev = abcd;\n        abcd = vsha256hq_u32(abcd_prev, efgh, tmp);\n        efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);\n\n        /* Rounds 12 to 15 */\n        tmp = vaddq_u32(sched3, vld1q_u32(&K[12]));\n        abcd_prev = abcd;\n        abcd = vsha256hq_u32(abcd_prev, efgh, tmp);\n        efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);\n\n        for (int t = 16; t < 64; t += 16) {\n            /* Rounds t to t + 3 */\n            sched0 = vsha256su1q_u32(vsha256su0q_u32(sched0, sched1), sched2, sched3);\n            tmp = vaddq_u32(sched0, vld1q_u32(&K[t]));\n            abcd_prev = abcd;\n            abcd = vsha256hq_u32(abcd_prev, efgh, tmp);\n            efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);\n\n            /* Rounds t + 4 to t + 7 */\n            sched1 = vsha256su1q_u32(vsha256su0q_u32(sched1, sched2), sched3, sched0);\n            tmp = vaddq_u32(sched1, vld1q_u32(&K[t + 4]));\n            abcd_prev = abcd;\n            abcd = vsha256hq_u32(abcd_prev, efgh, tmp);\n            efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);\n\n            /* Rounds t + 8 to t + 11 */\n            sched2 = vsha256su1q_u32(vsha256su0q_u32(sched2, sched3), sched0, sched1);\n            tmp = vaddq_u32(sched2, vld1q_u32(&K[t + 8]));\n            abcd_prev = abcd;\n            abcd = vsha256hq_u32(abcd_prev, efgh, tmp);\n            efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);\n\n            /* Rounds t + 12 to t + 15 */\n            sched3 = vsha256su1q_u32(vsha256su0q_u32(sched3, sched0), sched1, sched2);\n            tmp = vaddq_u32(sched3, vld1q_u32(&K[t + 12]));\n            abcd_prev = abcd;\n            abcd = vsha256hq_u32(abcd_prev, efgh, tmp);\n            efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);\n        }\n\n        abcd = vaddq_u32(abcd, abcd_orig);\n        efgh = vaddq_u32(efgh, efgh_orig);\n    }\n\n    vst1q_u32(&ctx->state[0], abcd);\n    vst1q_u32(&ctx->state[4], efgh);\n\n    return processed;\n}\n\n#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)\n/*\n * This function is for internal use only if we are building both C and Armv8-A\n * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process()\n */\nstatic\n#endif\nint mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context *ctx,\n                                               const unsigned char data[SHA256_BLOCK_SIZE])\n{\n    return (mbedtls_internal_sha256_process_many_a64_crypto(ctx, data,\n                                                            SHA256_BLOCK_SIZE) ==\n            SHA256_BLOCK_SIZE) ? 0 : -1;\n}\n\n#endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT || MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */\n\n#if defined(MBEDTLS_POP_TARGET_PRAGMA)\n#if defined(__clang__)\n#pragma clang attribute pop\n#elif defined(__GNUC__)\n#pragma GCC pop_options\n#endif\n#undef MBEDTLS_POP_TARGET_PRAGMA\n#endif\n\n#if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)\n#define mbedtls_internal_sha256_process_many_c mbedtls_internal_sha256_process_many\n#define mbedtls_internal_sha256_process_c      mbedtls_internal_sha256_process\n#endif\n\n\n#if !defined(MBEDTLS_SHA256_PROCESS_ALT) && \\\n    !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)\n\n#define  SHR(x, n) (((x) & 0xFFFFFFFF) >> (n))\n#define ROTR(x, n) (SHR(x, n) | ((x) << (32 - (n))))\n\n#define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^  SHR(x, 3))\n#define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^  SHR(x, 10))\n\n#define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))\n#define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))\n\n#define F0(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))\n#define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))\n\n#define R(t)                                                        \\\n    (                                                               \\\n        local.W[t] = S1(local.W[(t) -  2]) + local.W[(t) -  7] +    \\\n                     S0(local.W[(t) - 15]) + local.W[(t) - 16]      \\\n    )\n\n#define P(a, b, c, d, e, f, g, h, x, K)                                      \\\n    do                                                              \\\n    {                                                               \\\n        local.temp1 = (h) + S3(e) + F1((e), (f), (g)) + (K) + (x);    \\\n        local.temp2 = S2(a) + F0((a), (b), (c));                      \\\n        (d) += local.temp1; (h) = local.temp1 + local.temp2;        \\\n    } while (0)\n\n#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)\n/*\n * This function is for internal use only if we are building both C and Armv8\n * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process()\n */\nstatic\n#endif\nint mbedtls_internal_sha256_process_c(mbedtls_sha256_context *ctx,\n                                      const unsigned char data[SHA256_BLOCK_SIZE])\n{\n    struct {\n        uint32_t temp1, temp2, W[64];\n        uint32_t A[8];\n    } local;\n\n    unsigned int i;\n\n    for (i = 0; i < 8; i++) {\n        local.A[i] = ctx->state[i];\n    }\n\n#if defined(MBEDTLS_SHA256_SMALLER)\n    for (i = 0; i < 64; i++) {\n        if (i < 16) {\n            local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i);\n        } else {\n            R(i);\n        }\n\n        P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],\n          local.A[5], local.A[6], local.A[7], local.W[i], K[i]);\n\n        local.temp1 = local.A[7]; local.A[7] = local.A[6];\n        local.A[6] = local.A[5]; local.A[5] = local.A[4];\n        local.A[4] = local.A[3]; local.A[3] = local.A[2];\n        local.A[2] = local.A[1]; local.A[1] = local.A[0];\n        local.A[0] = local.temp1;\n    }\n#else /* MBEDTLS_SHA256_SMALLER */\n    for (i = 0; i < 16; i++) {\n        local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i);\n    }\n\n    for (i = 0; i < 16; i += 8) {\n        P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],\n          local.A[5], local.A[6], local.A[7], local.W[i+0], K[i+0]);\n        P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],\n          local.A[4], local.A[5], local.A[6], local.W[i+1], K[i+1]);\n        P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],\n          local.A[3], local.A[4], local.A[5], local.W[i+2], K[i+2]);\n        P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],\n          local.A[2], local.A[3], local.A[4], local.W[i+3], K[i+3]);\n        P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],\n          local.A[1], local.A[2], local.A[3], local.W[i+4], K[i+4]);\n        P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],\n          local.A[0], local.A[1], local.A[2], local.W[i+5], K[i+5]);\n        P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],\n          local.A[7], local.A[0], local.A[1], local.W[i+6], K[i+6]);\n        P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],\n          local.A[6], local.A[7], local.A[0], local.W[i+7], K[i+7]);\n    }\n\n    for (i = 16; i < 64; i += 8) {\n        P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],\n          local.A[5], local.A[6], local.A[7], R(i+0), K[i+0]);\n        P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],\n          local.A[4], local.A[5], local.A[6], R(i+1), K[i+1]);\n        P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],\n          local.A[3], local.A[4], local.A[5], R(i+2), K[i+2]);\n        P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],\n          local.A[2], local.A[3], local.A[4], R(i+3), K[i+3]);\n        P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],\n          local.A[1], local.A[2], local.A[3], R(i+4), K[i+4]);\n        P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],\n          local.A[0], local.A[1], local.A[2], R(i+5), K[i+5]);\n        P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],\n          local.A[7], local.A[0], local.A[1], R(i+6), K[i+6]);\n        P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],\n          local.A[6], local.A[7], local.A[0], R(i+7), K[i+7]);\n    }\n#endif /* MBEDTLS_SHA256_SMALLER */\n\n    for (i = 0; i < 8; i++) {\n        ctx->state[i] += local.A[i];\n    }\n\n    /* Zeroise buffers and variables to clear sensitive data from memory. */\n    mbedtls_platform_zeroize(&local, sizeof(local));\n\n    return 0;\n}\n\n#endif /* !MBEDTLS_SHA256_PROCESS_ALT && !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */\n\n\n#if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)\n\nstatic size_t mbedtls_internal_sha256_process_many_c(\n    mbedtls_sha256_context *ctx, const uint8_t *data, size_t len)\n{\n    size_t processed = 0;\n\n    while (len >= SHA256_BLOCK_SIZE) {\n        if (mbedtls_internal_sha256_process_c(ctx, data) != 0) {\n            return 0;\n        }\n\n        data += SHA256_BLOCK_SIZE;\n        len  -= SHA256_BLOCK_SIZE;\n\n        processed += SHA256_BLOCK_SIZE;\n    }\n\n    return processed;\n}\n\n#endif /* !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */\n\n\n#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)\n\nstatic int mbedtls_a64_crypto_sha256_has_support(void)\n{\n    static int done = 0;\n    static int supported = 0;\n\n    if (!done) {\n        supported = mbedtls_a64_crypto_sha256_determine_support();\n        done = 1;\n    }\n\n    return supported;\n}\n\nstatic size_t mbedtls_internal_sha256_process_many(mbedtls_sha256_context *ctx,\n                                                   const uint8_t *msg, size_t len)\n{\n    if (mbedtls_a64_crypto_sha256_has_support()) {\n        return mbedtls_internal_sha256_process_many_a64_crypto(ctx, msg, len);\n    } else {\n        return mbedtls_internal_sha256_process_many_c(ctx, msg, len);\n    }\n}\n\nint mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx,\n                                    const unsigned char data[SHA256_BLOCK_SIZE])\n{\n    if (mbedtls_a64_crypto_sha256_has_support()) {\n        return mbedtls_internal_sha256_process_a64_crypto(ctx, data);\n    } else {\n        return mbedtls_internal_sha256_process_c(ctx, data);\n    }\n}\n\n#endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */\n\n\n/*\n * SHA-256 process buffer\n */\nint mbedtls_sha256_update(mbedtls_sha256_context *ctx,\n                          const unsigned char *input,\n                          size_t ilen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t fill;\n    uint32_t left;\n\n    if (ilen == 0) {\n        return 0;\n    }\n\n    left = ctx->total[0] & 0x3F;\n    fill = SHA256_BLOCK_SIZE - left;\n\n    ctx->total[0] += (uint32_t) ilen;\n    ctx->total[0] &= 0xFFFFFFFF;\n\n    if (ctx->total[0] < (uint32_t) ilen) {\n        ctx->total[1]++;\n    }\n\n    if (left && ilen >= fill) {\n        memcpy((void *) (ctx->buffer + left), input, fill);\n\n        if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {\n            return ret;\n        }\n\n        input += fill;\n        ilen  -= fill;\n        left = 0;\n    }\n\n    while (ilen >= SHA256_BLOCK_SIZE) {\n        size_t processed =\n            mbedtls_internal_sha256_process_many(ctx, input, ilen);\n        if (processed < SHA256_BLOCK_SIZE) {\n            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;\n        }\n\n        input += processed;\n        ilen  -= processed;\n    }\n\n    if (ilen > 0) {\n        memcpy((void *) (ctx->buffer + left), input, ilen);\n    }\n\n    return 0;\n}\n\n/*\n * SHA-256 final digest\n */\nint mbedtls_sha256_finish(mbedtls_sha256_context *ctx,\n                          unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    uint32_t used;\n    uint32_t high, low;\n    int truncated = 0;\n\n    /*\n     * Add padding: 0x80 then 0x00 until 8 bytes remain for the length\n     */\n    used = ctx->total[0] & 0x3F;\n\n    ctx->buffer[used++] = 0x80;\n\n    if (used <= 56) {\n        /* Enough room for padding + length in current block */\n        memset(ctx->buffer + used, 0, 56 - used);\n    } else {\n        /* We'll need an extra block */\n        memset(ctx->buffer + used, 0, SHA256_BLOCK_SIZE - used);\n\n        if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {\n            goto exit;\n        }\n\n        memset(ctx->buffer, 0, 56);\n    }\n\n    /*\n     * Add message length\n     */\n    high = (ctx->total[0] >> 29)\n           | (ctx->total[1] <<  3);\n    low  = (ctx->total[0] <<  3);\n\n    MBEDTLS_PUT_UINT32_BE(high, ctx->buffer, 56);\n    MBEDTLS_PUT_UINT32_BE(low,  ctx->buffer, 60);\n\n    if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {\n        goto exit;\n    }\n\n    /*\n     * Output final state\n     */\n    MBEDTLS_PUT_UINT32_BE(ctx->state[0], output,  0);\n    MBEDTLS_PUT_UINT32_BE(ctx->state[1], output,  4);\n    MBEDTLS_PUT_UINT32_BE(ctx->state[2], output,  8);\n    MBEDTLS_PUT_UINT32_BE(ctx->state[3], output, 12);\n    MBEDTLS_PUT_UINT32_BE(ctx->state[4], output, 16);\n    MBEDTLS_PUT_UINT32_BE(ctx->state[5], output, 20);\n    MBEDTLS_PUT_UINT32_BE(ctx->state[6], output, 24);\n\n#if defined(MBEDTLS_SHA224_C)\n    truncated = ctx->is224;\n#endif\n    if (!truncated) {\n        MBEDTLS_PUT_UINT32_BE(ctx->state[7], output, 28);\n    }\n\n    ret = 0;\n\nexit:\n    mbedtls_sha256_free(ctx);\n    return ret;\n}\n\n#endif /* !MBEDTLS_SHA256_ALT */\n\n/*\n * output = SHA-256( input buffer )\n */\nint mbedtls_sha256(const unsigned char *input,\n                   size_t ilen,\n                   unsigned char *output,\n                   int is224)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_sha256_context ctx;\n\n#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)\n    if (is224 != 0 && is224 != 1) {\n        return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;\n    }\n#elif defined(MBEDTLS_SHA256_C)\n    if (is224 != 0) {\n        return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;\n    }\n#else /* defined MBEDTLS_SHA224_C only */\n    if (is224 == 0) {\n        return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;\n    }\n#endif\n\n    mbedtls_sha256_init(&ctx);\n\n    if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_sha256_update(&ctx, input, ilen)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_sha256_finish(&ctx, output)) != 0) {\n        goto exit;\n    }\n\nexit:\n    mbedtls_sha256_free(&ctx);\n\n    return ret;\n}\n\n#if defined(MBEDTLS_SELF_TEST)\n/*\n * FIPS-180-2 test vectors\n */\nstatic const unsigned char sha_test_buf[3][57] =\n{\n    { \"abc\" },\n    { \"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\" },\n    { \"\" }\n};\n\nstatic const size_t sha_test_buflen[3] =\n{\n    3, 56, 1000\n};\n\ntypedef const unsigned char (sha_test_sum_t)[32];\n\n/*\n * SHA-224 test vectors\n */\n#if defined(MBEDTLS_SHA224_C)\nstatic sha_test_sum_t sha224_test_sum[] =\n{\n    { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,\n      0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,\n      0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,\n      0xE3, 0x6C, 0x9D, 0xA7 },\n    { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,\n      0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,\n      0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,\n      0x52, 0x52, 0x25, 0x25 },\n    { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,\n      0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,\n      0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,\n      0x4E, 0xE7, 0xAD, 0x67 }\n};\n#endif\n\n/*\n * SHA-256 test vectors\n */\n#if defined(MBEDTLS_SHA256_C)\nstatic sha_test_sum_t sha256_test_sum[] =\n{\n    { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,\n      0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,\n      0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,\n      0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },\n    { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,\n      0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,\n      0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,\n      0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },\n    { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,\n      0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,\n      0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,\n      0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }\n};\n#endif\n\n/*\n * Checkup routine\n */\nstatic int mbedtls_sha256_common_self_test(int verbose, int is224)\n{\n    int i, buflen, ret = 0;\n    unsigned char *buf;\n    unsigned char sha256sum[32];\n    mbedtls_sha256_context ctx;\n\n#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)\n    sha_test_sum_t *sha_test_sum = (is224) ? sha224_test_sum : sha256_test_sum;\n#elif defined(MBEDTLS_SHA256_C)\n    sha_test_sum_t *sha_test_sum = sha256_test_sum;\n#else\n    sha_test_sum_t *sha_test_sum = sha224_test_sum;\n#endif\n\n    buf = mbedtls_calloc(1024, sizeof(unsigned char));\n    if (NULL == buf) {\n        if (verbose != 0) {\n            mbedtls_printf(\"Buffer allocation failed\\n\");\n        }\n\n        return 1;\n    }\n\n    mbedtls_sha256_init(&ctx);\n\n    for (i = 0; i < 3; i++) {\n        if (verbose != 0) {\n            mbedtls_printf(\"  SHA-%d test #%d: \", 256 - is224 * 32, i + 1);\n        }\n\n        if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) {\n            goto fail;\n        }\n\n        if (i == 2) {\n            memset(buf, 'a', buflen = 1000);\n\n            for (int j = 0; j < 1000; j++) {\n                ret = mbedtls_sha256_update(&ctx, buf, buflen);\n                if (ret != 0) {\n                    goto fail;\n                }\n            }\n\n        } else {\n            ret = mbedtls_sha256_update(&ctx, sha_test_buf[i],\n                                        sha_test_buflen[i]);\n            if (ret != 0) {\n                goto fail;\n            }\n        }\n\n        if ((ret = mbedtls_sha256_finish(&ctx, sha256sum)) != 0) {\n            goto fail;\n        }\n\n\n        if (memcmp(sha256sum, sha_test_sum[i], 32 - is224 * 4) != 0) {\n            ret = 1;\n            goto fail;\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    goto exit;\n\nfail:\n    if (verbose != 0) {\n        mbedtls_printf(\"failed\\n\");\n    }\n\nexit:\n    mbedtls_sha256_free(&ctx);\n    mbedtls_free(buf);\n\n    return ret;\n}\n\n#if defined(MBEDTLS_SHA256_C)\nint mbedtls_sha256_self_test(int verbose)\n{\n    return mbedtls_sha256_common_self_test(verbose, 0);\n}\n#endif /* MBEDTLS_SHA256_C */\n\n#if defined(MBEDTLS_SHA224_C)\nint mbedtls_sha224_self_test(int verbose)\n{\n    return mbedtls_sha256_common_self_test(verbose, 1);\n}\n#endif /* MBEDTLS_SHA224_C */\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA224_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/sha3.c",
    "content": "/*\n *  FIPS-202 compliant SHA3 implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  The SHA-3 Secure Hash Standard was published by NIST in 2015.\n *\n *  https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SHA3_C)\n\n/*\n * These macros select manually unrolled implementations of parts of the main permutation function.\n *\n * Unrolling has a major impact on both performance and code size. gcc performance benefits a lot\n * from manually unrolling at higher optimisation levels.\n *\n * Depending on your size/perf priorities, compiler and target, it may be beneficial to adjust\n * these; the defaults here should give sensible trade-offs for gcc and clang on aarch64 and\n * x86-64.\n */\n#if !defined(MBEDTLS_SHA3_THETA_UNROLL)\n    #define MBEDTLS_SHA3_THETA_UNROLL 0 //no-check-names\n#endif\n#if !defined(MBEDTLS_SHA3_CHI_UNROLL)\n    #if defined(__OPTIMIZE_SIZE__)\n        #define MBEDTLS_SHA3_CHI_UNROLL 0 //no-check-names\n    #else\n        #define MBEDTLS_SHA3_CHI_UNROLL 1 //no-check-names\n    #endif\n#endif\n#if !defined(MBEDTLS_SHA3_PI_UNROLL)\n    #define MBEDTLS_SHA3_PI_UNROLL 1 //no-check-names\n#endif\n#if !defined(MBEDTLS_SHA3_RHO_UNROLL)\n    #define MBEDTLS_SHA3_RHO_UNROLL 1 //no-check-names\n#endif\n\n#include \"mbedtls/sha3.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_SELF_TEST)\n#include \"mbedtls/platform.h\"\n#endif /* MBEDTLS_SELF_TEST */\n\n#define XOR_BYTE 0x6\n\n/* Precomputed masks for the iota transform.\n *\n * Each round uses a 64-bit mask value. In each mask values, only\n * bits whose position is of the form 2^k-1 can be set, thus only\n * 7 of 64 bits of the mask need to be known for each mask value.\n *\n * We use a compressed encoding of the mask where bits 63, 31 and 15\n * are moved to bits 4-6. This allows us to make each mask value\n * 1 byte rather than 8 bytes, saving 7*24 = 168 bytes of data (with\n * perhaps a little variation due to alignment). Decompressing this\n * requires a little code, but much less than the savings on the table.\n *\n * The impact on performance depends on the platform and compiler.\n * There's a bit more computation, but less memory bandwidth. A quick\n * benchmark on x86_64 shows a 7% speed improvement with GCC and a\n * 5% speed penalty with Clang, compared to the naive uint64_t[24] table.\n * YMMV.\n */\n/* Helper macro to set the values of the higher bits in unused low positions */\n#define H(b63, b31, b15) (b63 << 6 | b31 << 5 | b15 << 4)\nstatic const uint8_t iota_r_packed[24] = {\n    H(0, 0, 0) | 0x01, H(0, 0, 1) | 0x82, H(1, 0, 1) | 0x8a, H(1, 1, 1) | 0x00,\n    H(0, 0, 1) | 0x8b, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x09,\n    H(0, 0, 0) | 0x8a, H(0, 0, 0) | 0x88, H(0, 1, 1) | 0x09, H(0, 1, 0) | 0x0a,\n    H(0, 1, 1) | 0x8b, H(1, 0, 0) | 0x8b, H(1, 0, 1) | 0x89, H(1, 0, 1) | 0x03,\n    H(1, 0, 1) | 0x02, H(1, 0, 0) | 0x80, H(0, 0, 1) | 0x0a, H(1, 1, 0) | 0x0a,\n    H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x80, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x08,\n};\n#undef H\n\nstatic const uint32_t rho[6] = {\n    0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832\n};\n\nstatic const uint32_t pi[6] = {\n    0x110b070a, 0x10050312, 0x04181508, 0x0d13170f, 0x0e14020c, 0x01060916\n};\n\n#define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right\n#define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \\\n} while (0)\n#define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3)))\n#define SWAP(x, y) do { uint64_t tmp = (x); (x) = (y); (y) = tmp; } while (0)\n\n/* The permutation function.  */\nstatic void keccak_f1600(mbedtls_sha3_context *ctx)\n{\n    uint64_t lane[5];\n    uint64_t *s = ctx->state;\n    int i;\n\n    for (int round = 0; round < 24; round++) {\n        uint64_t t;\n\n        /* Theta */\n#if MBEDTLS_SHA3_THETA_UNROLL == 0 //no-check-names\n        for (i = 0; i < 5; i++) {\n            lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];\n        }\n        for (i = 0; i < 5; i++) {\n            t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63);\n            s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t;\n        }\n#else\n        lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];\n        lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];\n        lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];\n        lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];\n        lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];\n\n        t = lane[4] ^ ROTR64(lane[1], 63);\n        s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t;\n\n        t = lane[0] ^ ROTR64(lane[2], 63);\n        s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t;\n\n        t = lane[1] ^ ROTR64(lane[3], 63);\n        s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t;\n\n        t = lane[2] ^ ROTR64(lane[4], 63);\n        s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t;\n\n        t = lane[3] ^ ROTR64(lane[0], 63);\n        s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t;\n#endif\n\n        /* Rho */\n        for (i = 1; i < 25; i += 4) {\n            uint32_t r = rho[(i - 1) >> 2];\n#if MBEDTLS_SHA3_RHO_UNROLL == 0\n            for (int j = i; j < i + 4; j++) {\n                uint8_t r8 = (uint8_t) (r >> 24);\n                r <<= 8;\n                s[j] = ROTR64(s[j], r8);\n            }\n#else\n            s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r));\n            s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r));\n            s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r));\n            s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r));\n#endif\n        }\n\n        /* Pi */\n        t = s[1];\n#if MBEDTLS_SHA3_PI_UNROLL == 0\n        for (i = 0; i < 24; i += 4) {\n            uint32_t p = pi[i >> 2];\n            for (unsigned j = 0; j < 4; j++) {\n                SWAP(s[p & 0xff], t);\n                p >>= 8;\n            }\n        }\n#else\n        uint32_t p = pi[0];\n        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);\n        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);\n        p = pi[1];\n        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);\n        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);\n        p = pi[2];\n        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);\n        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);\n        p = pi[3];\n        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);\n        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);\n        p = pi[4];\n        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);\n        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);\n        p = pi[5];\n        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);\n        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);\n#endif\n\n        /* Chi */\n#if MBEDTLS_SHA3_CHI_UNROLL == 0 //no-check-names\n        for (i = 0; i <= 20; i += 5) {\n            lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2];\n            lane[3] = s[i + 3]; lane[4] = s[i + 4];\n            s[i + 0] ^= (~lane[1]) & lane[2];\n            s[i + 1] ^= (~lane[2]) & lane[3];\n            s[i + 2] ^= (~lane[3]) & lane[4];\n            s[i + 3] ^= (~lane[4]) & lane[0];\n            s[i + 4] ^= (~lane[0]) & lane[1];\n        }\n#else\n        lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4];\n        s[0] ^= (~lane[1]) & lane[2];\n        s[1] ^= (~lane[2]) & lane[3];\n        s[2] ^= (~lane[3]) & lane[4];\n        s[3] ^= (~lane[4]) & lane[0];\n        s[4] ^= (~lane[0]) & lane[1];\n\n        lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9];\n        s[5] ^= (~lane[1]) & lane[2];\n        s[6] ^= (~lane[2]) & lane[3];\n        s[7] ^= (~lane[3]) & lane[4];\n        s[8] ^= (~lane[4]) & lane[0];\n        s[9] ^= (~lane[0]) & lane[1];\n\n        lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14];\n        s[10] ^= (~lane[1]) & lane[2];\n        s[11] ^= (~lane[2]) & lane[3];\n        s[12] ^= (~lane[3]) & lane[4];\n        s[13] ^= (~lane[4]) & lane[0];\n        s[14] ^= (~lane[0]) & lane[1];\n\n        lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19];\n        s[15] ^= (~lane[1]) & lane[2];\n        s[16] ^= (~lane[2]) & lane[3];\n        s[17] ^= (~lane[3]) & lane[4];\n        s[18] ^= (~lane[4]) & lane[0];\n        s[19] ^= (~lane[0]) & lane[1];\n\n        lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24];\n        s[20] ^= (~lane[1]) & lane[2];\n        s[21] ^= (~lane[2]) & lane[3];\n        s[22] ^= (~lane[3]) & lane[4];\n        s[23] ^= (~lane[4]) & lane[0];\n        s[24] ^= (~lane[0]) & lane[1];\n#endif\n\n        /* Iota */\n        /* Decompress the round masks (see definition of rc) */\n        s[0] ^= ((iota_r_packed[round] & 0x40ull) << 57 |\n                 (iota_r_packed[round] & 0x20ull) << 26 |\n                 (iota_r_packed[round] & 0x10ull) << 11 |\n                 (iota_r_packed[round] & 0x8f));\n    }\n}\n\nvoid mbedtls_sha3_init(mbedtls_sha3_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_sha3_context));\n}\n\nvoid mbedtls_sha3_free(mbedtls_sha3_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha3_context));\n}\n\nvoid mbedtls_sha3_clone(mbedtls_sha3_context *dst,\n                        const mbedtls_sha3_context *src)\n{\n    *dst = *src;\n}\n\n/*\n * SHA-3 context setup\n */\nint mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id)\n{\n    switch (id) {\n        case MBEDTLS_SHA3_224:\n            ctx->olen = 224 / 8;\n            ctx->max_block_size = 1152 / 8;\n            break;\n        case MBEDTLS_SHA3_256:\n            ctx->olen = 256 / 8;\n            ctx->max_block_size = 1088 / 8;\n            break;\n        case MBEDTLS_SHA3_384:\n            ctx->olen = 384 / 8;\n            ctx->max_block_size = 832 / 8;\n            break;\n        case MBEDTLS_SHA3_512:\n            ctx->olen = 512 / 8;\n            ctx->max_block_size = 576 / 8;\n            break;\n        default:\n            return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;\n    }\n\n    memset(ctx->state, 0, sizeof(ctx->state));\n    ctx->index = 0;\n\n    return 0;\n}\n\n/*\n * SHA-3 process buffer\n */\nint mbedtls_sha3_update(mbedtls_sha3_context *ctx,\n                        const uint8_t *input,\n                        size_t ilen)\n{\n    if (ilen >= 8) {\n        // 8-byte align index\n        int align_bytes = 8 - (ctx->index % 8);\n        if (align_bytes) {\n            for (; align_bytes > 0; align_bytes--) {\n                ABSORB(ctx, ctx->index, *input++);\n                ilen--;\n                ctx->index++;\n            }\n            if ((ctx->index = ctx->index % ctx->max_block_size) == 0) {\n                keccak_f1600(ctx);\n            }\n        }\n\n        // process input in 8-byte chunks\n        while (ilen >= 8) {\n            ABSORB(ctx, ctx->index, MBEDTLS_GET_UINT64_LE(input, 0));\n            input += 8;\n            ilen -= 8;\n            if ((ctx->index = (ctx->index + 8) % ctx->max_block_size) == 0) {\n                keccak_f1600(ctx);\n            }\n        }\n    }\n\n    // handle remaining bytes\n    while (ilen-- > 0) {\n        ABSORB(ctx, ctx->index, *input++);\n        if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {\n            keccak_f1600(ctx);\n        }\n    }\n\n    return 0;\n}\n\nint mbedtls_sha3_finish(mbedtls_sha3_context *ctx,\n                        uint8_t *output, size_t olen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* Catch SHA-3 families, with fixed output length */\n    if (ctx->olen > 0) {\n        if (ctx->olen > olen) {\n            ret = MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;\n            goto exit;\n        }\n        olen = ctx->olen;\n    }\n\n    ABSORB(ctx, ctx->index, XOR_BYTE);\n    ABSORB(ctx, ctx->max_block_size - 1, 0x80);\n    keccak_f1600(ctx);\n    ctx->index = 0;\n\n    while (olen-- > 0) {\n        *output++ = SQUEEZE(ctx, ctx->index);\n\n        if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {\n            keccak_f1600(ctx);\n        }\n    }\n\n    ret = 0;\n\nexit:\n    mbedtls_sha3_free(ctx);\n    return ret;\n}\n\n/*\n * output = SHA-3( input buffer )\n */\nint mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input,\n                 size_t ilen, uint8_t *output, size_t olen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_sha3_context ctx;\n\n    mbedtls_sha3_init(&ctx);\n\n    /* Sanity checks are performed in every mbedtls_sha3_xxx() */\n    if ((ret = mbedtls_sha3_starts(&ctx, id)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_sha3_update(&ctx, input, ilen)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_sha3_finish(&ctx, output, olen)) != 0) {\n        goto exit;\n    }\n\nexit:\n    mbedtls_sha3_free(&ctx);\n\n    return ret;\n}\n\n/**************** Self-tests ****************/\n\n#if defined(MBEDTLS_SELF_TEST)\n\nstatic const unsigned char test_data[2][4] =\n{\n    \"\",\n    \"abc\",\n};\n\nstatic const size_t test_data_len[2] =\n{\n    0, /* \"\" */\n    3  /* \"abc\" */\n};\n\nstatic const unsigned char test_hash_sha3_224[2][28] =\n{\n    { /* \"\" */\n        0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7,\n        0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB,\n        0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F,\n        0x5B, 0x5A, 0x6B, 0xC7\n    },\n    { /* \"abc\" */\n        0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A,\n        0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F,\n        0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD,\n        0x73, 0xB4, 0x6F, 0xDF\n    }\n};\n\nstatic const unsigned char test_hash_sha3_256[2][32] =\n{\n    { /* \"\" */\n        0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66,\n        0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62,\n        0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA,\n        0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A\n    },\n    { /* \"abc\" */\n        0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2,\n        0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD,\n        0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B,\n        0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32\n    }\n};\n\nstatic const unsigned char test_hash_sha3_384[2][48] =\n{\n    { /* \"\" */\n        0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D,\n        0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85,\n        0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61,\n        0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A,\n        0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47,\n        0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04\n    },\n    { /* \"abc\" */\n        0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9,\n        0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D,\n        0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25,\n        0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2,\n        0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5,\n        0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25\n    }\n};\n\nstatic const unsigned char test_hash_sha3_512[2][64] =\n{\n    { /* \"\" */\n        0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5,\n        0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E,\n        0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59,\n        0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6,\n        0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C,\n        0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58,\n        0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3,\n        0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26\n    },\n    { /* \"abc\" */\n        0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A,\n        0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E,\n        0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D,\n        0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E,\n        0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9,\n        0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40,\n        0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5,\n        0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0\n    }\n};\n\nstatic const unsigned char long_kat_hash_sha3_224[28] =\n{\n    0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E,\n    0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C,\n    0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7,\n    0xA7, 0xFD, 0x65, 0x3C\n};\n\nstatic const unsigned char long_kat_hash_sha3_256[32] =\n{\n    0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34,\n    0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6,\n    0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99,\n    0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1\n};\n\nstatic const unsigned char long_kat_hash_sha3_384[48] =\n{\n    0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53,\n    0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD,\n    0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E,\n    0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84,\n    0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42,\n    0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40\n};\n\nstatic const unsigned char long_kat_hash_sha3_512[64] =\n{\n    0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB,\n    0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E,\n    0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF,\n    0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59,\n    0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE,\n    0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66,\n    0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E,\n    0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87\n};\n\nstatic int mbedtls_sha3_kat_test(int verbose,\n                                 const char *type_name,\n                                 mbedtls_sha3_id id,\n                                 int test_num)\n{\n    uint8_t hash[64];\n    int result;\n\n    result = mbedtls_sha3(id,\n                          test_data[test_num], test_data_len[test_num],\n                          hash, sizeof(hash));\n    if (result != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"  %s test %d error code: %d\\n\",\n                           type_name, test_num, result);\n        }\n\n        return result;\n    }\n\n    switch (id) {\n        case MBEDTLS_SHA3_224:\n            result = memcmp(hash, test_hash_sha3_224[test_num], 28);\n            break;\n        case MBEDTLS_SHA3_256:\n            result = memcmp(hash, test_hash_sha3_256[test_num], 32);\n            break;\n        case MBEDTLS_SHA3_384:\n            result = memcmp(hash, test_hash_sha3_384[test_num], 48);\n            break;\n        case MBEDTLS_SHA3_512:\n            result = memcmp(hash, test_hash_sha3_512[test_num], 64);\n            break;\n        default:\n            break;\n    }\n\n    if (0 != result) {\n        if (verbose != 0) {\n            mbedtls_printf(\"  %s test %d failed\\n\", type_name, test_num);\n        }\n\n        return -1;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  %s test %d passed\\n\", type_name, test_num);\n    }\n\n    return 0;\n}\n\nstatic int mbedtls_sha3_long_kat_test(int verbose,\n                                      const char *type_name,\n                                      mbedtls_sha3_id id)\n{\n    mbedtls_sha3_context ctx;\n    unsigned char buffer[1000];\n    unsigned char hash[64];\n    int result = 0;\n\n    memset(buffer, 'a', 1000);\n\n    if (verbose != 0) {\n        mbedtls_printf(\"  %s long KAT test \", type_name);\n    }\n\n    mbedtls_sha3_init(&ctx);\n\n    result = mbedtls_sha3_starts(&ctx, id);\n    if (result != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"setup failed\\n \");\n        }\n    }\n\n    /* Process 1,000,000 (one million) 'a' characters */\n    for (int i = 0; i < 1000; i++) {\n        result = mbedtls_sha3_update(&ctx, buffer, 1000);\n        if (result != 0) {\n            if (verbose != 0) {\n                mbedtls_printf(\"update error code: %i\\n\", result);\n            }\n\n            goto cleanup;\n        }\n    }\n\n    result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash));\n    if (result != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"finish error code: %d\\n\", result);\n        }\n\n        goto cleanup;\n    }\n\n    switch (id) {\n        case MBEDTLS_SHA3_224:\n            result = memcmp(hash, long_kat_hash_sha3_224, 28);\n            break;\n        case MBEDTLS_SHA3_256:\n            result = memcmp(hash, long_kat_hash_sha3_256, 32);\n            break;\n        case MBEDTLS_SHA3_384:\n            result = memcmp(hash, long_kat_hash_sha3_384, 48);\n            break;\n        case MBEDTLS_SHA3_512:\n            result = memcmp(hash, long_kat_hash_sha3_512, 64);\n            break;\n        default:\n            break;\n    }\n\n    if (result != 0) {\n        if (verbose != 0) {\n            mbedtls_printf(\"failed\\n\");\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"passed\\n\");\n    }\n\ncleanup:\n    mbedtls_sha3_free(&ctx);\n    return result;\n}\n\nint mbedtls_sha3_self_test(int verbose)\n{\n    int i;\n\n    /* SHA-3 Known Answer Tests (KAT) */\n    for (i = 0; i < 2; i++) {\n        if (0 != mbedtls_sha3_kat_test(verbose,\n                                       \"SHA3-224\", MBEDTLS_SHA3_224, i)) {\n            return 1;\n        }\n\n        if (0 != mbedtls_sha3_kat_test(verbose,\n                                       \"SHA3-256\", MBEDTLS_SHA3_256, i)) {\n            return 1;\n        }\n\n        if (0 != mbedtls_sha3_kat_test(verbose,\n                                       \"SHA3-384\", MBEDTLS_SHA3_384, i)) {\n            return 1;\n        }\n\n        if (0 != mbedtls_sha3_kat_test(verbose,\n                                       \"SHA3-512\", MBEDTLS_SHA3_512, i)) {\n            return 1;\n        }\n    }\n\n    /* SHA-3 long KAT tests */\n    if (0 != mbedtls_sha3_long_kat_test(verbose,\n                                        \"SHA3-224\", MBEDTLS_SHA3_224)) {\n        return 1;\n    }\n\n    if (0 != mbedtls_sha3_long_kat_test(verbose,\n                                        \"SHA3-256\", MBEDTLS_SHA3_256)) {\n        return 1;\n    }\n\n    if (0 != mbedtls_sha3_long_kat_test(verbose,\n                                        \"SHA3-384\", MBEDTLS_SHA3_384)) {\n        return 1;\n    }\n\n    if (0 != mbedtls_sha3_long_kat_test(verbose,\n                                        \"SHA3-512\", MBEDTLS_SHA3_512)) {\n        return 1;\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_SHA3_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/sha512.c",
    "content": "/*\n *  FIPS-180-2 compliant SHA-384/512 implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  The SHA-512 Secure Hash Standard was published by NIST in 2002.\n *\n *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf\n */\n\n#if defined(__aarch64__) && !defined(__ARM_FEATURE_SHA512) && \\\n    defined(__clang__) && __clang_major__ >= 7\n/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged.\n *\n * The intrinsic declaration are guarded by predefined ACLE macros in clang:\n * these are normally only enabled by the -march option on the command line.\n * By defining the macros ourselves we gain access to those declarations without\n * requiring -march on the command line.\n *\n * `arm_neon.h` is included by common.h, so we put these defines\n * at the top of this file, before any includes.\n */\n#define __ARM_FEATURE_SHA512 1\n#define MBEDTLS_ENABLE_ARM_SHA3_EXTENSIONS_COMPILER_FLAG\n#endif\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA384_C)\n\n#include \"mbedtls/sha512.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/error.h\"\n\n#if defined(_MSC_VER) || defined(__WATCOMC__)\n  #define UL64(x) x##ui64\n#else\n  #define UL64(x) x##ULL\n#endif\n\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#if defined(__aarch64__)\n#  if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \\\n    defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)\n/* *INDENT-OFF* */\n#   if !defined(MBEDTLS_HAVE_NEON_INTRINSICS)\n#       error \"Target does not support NEON instructions\"\n#   endif\n/*\n * Best performance comes from most recent compilers, with intrinsics and -O3.\n * Must compile with -march=armv8.2-a+sha3, but we can't detect armv8.2-a, and\n * can't always detect __ARM_FEATURE_SHA512 (notably clang 7-12).\n *\n * GCC < 8 won't work at all (lacks the sha512 instructions)\n * GCC >= 8 uses intrinsics, sets __ARM_FEATURE_SHA512\n *\n * Clang < 7 won't work at all (lacks the sha512 instructions)\n * Clang 7-12 don't have intrinsics (but we work around that with inline\n *            assembler) or __ARM_FEATURE_SHA512\n * Clang == 13.0.0 same as clang 12 (only seen on macOS)\n * Clang >= 13.0.1 has __ARM_FEATURE_SHA512 and intrinsics\n */\n#    if !defined(__ARM_FEATURE_SHA512) || defined(MBEDTLS_ENABLE_ARM_SHA3_EXTENSIONS_COMPILER_FLAG)\n       /* Test Clang first, as it defines __GNUC__ */\n#      if defined(__ARMCOMPILER_VERSION)\n#        if __ARMCOMPILER_VERSION < 6090000\n#          error \"A more recent armclang is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*\"\n#        elif __ARMCOMPILER_VERSION == 6090000\n#          error \"Must use minimum -march=armv8.2-a+sha3 for MBEDTLS_SHA512_USE_A64_CRYPTO_*\"\n#        else\n#          pragma clang attribute push (__attribute__((target(\"sha3\"))), apply_to=function)\n#          define MBEDTLS_POP_TARGET_PRAGMA\n#        endif\n#      elif defined(__clang__)\n#        if __clang_major__ < 7\n#          error \"A more recent Clang is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*\"\n#        else\n#          pragma clang attribute push (__attribute__((target(\"sha3\"))), apply_to=function)\n#          define MBEDTLS_POP_TARGET_PRAGMA\n#        endif\n#      elif defined(__GNUC__)\n#        if __GNUC__ < 8\n#          error \"A more recent GCC is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*\"\n#        else\n#          pragma GCC push_options\n#          pragma GCC target (\"arch=armv8.2-a+sha3\")\n#          define MBEDTLS_POP_TARGET_PRAGMA\n#        endif\n#      else\n#        error \"Only GCC and Clang supported for MBEDTLS_SHA512_USE_A64_CRYPTO_*\"\n#      endif\n#    endif\n/* *INDENT-ON* */\n#  endif\n#  if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)\n#    if defined(__unix__)\n#      if defined(__linux__)\n/* Our preferred method of detection is getauxval() */\n#        include <sys/auxv.h>\n#        if !defined(HWCAP_SHA512)\n/* The same header that declares getauxval() should provide the HWCAP_xxx\n * constants to analyze its return value. However, the libc may be too\n * old to have the constant that we need. So if it's missing, assume that\n * the value is the same one used by the Linux kernel ABI.\n */\n#          define HWCAP_SHA512 (1 << 21)\n#        endif\n#      endif\n/* Use SIGILL on Unix, and fall back to it on Linux */\n#      include <signal.h>\n#    endif\n#  endif\n#elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)\n#  undef MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY\n#  undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT\n#endif\n\n#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)\n/*\n * Capability detection code comes early, so we can disable\n * MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT if no detection mechanism found\n */\n#if defined(HWCAP_SHA512)\nstatic int mbedtls_a64_crypto_sha512_determine_support(void)\n{\n    return (getauxval(AT_HWCAP) & HWCAP_SHA512) ? 1 : 0;\n}\n#elif defined(__APPLE__)\n#include <sys/types.h>\n#include <sys/sysctl.h>\n\nstatic int mbedtls_a64_crypto_sha512_determine_support(void)\n{\n    int value = 0;\n    size_t value_len = sizeof(value);\n\n    int ret = sysctlbyname(\"hw.optional.armv8_2_sha512\", &value, &value_len,\n                           NULL, 0);\n    return ret == 0 && value != 0;\n}\n#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)\n/*\n * As of March 2022, there don't appear to be any PF_ARM_V8_* flags\n * available to pass to IsProcessorFeaturePresent() to check for\n * SHA-512 support. So we fall back to the C code only.\n */\n#if defined(_MSC_VER)\n#pragma message \"No mechanism to detect A64_CRYPTO found, using C code only\"\n#else\n#warning \"No mechanism to detect A64_CRYPTO found, using C code only\"\n#endif\n#elif defined(__unix__) && defined(SIG_SETMASK)\n/* Detection with SIGILL, setjmp() and longjmp() */\n#include <signal.h>\n#include <setjmp.h>\n\nstatic jmp_buf return_from_sigill;\n\n/*\n * A64 SHA512 support detection via SIGILL\n */\nstatic void sigill_handler(int signal)\n{\n    (void) signal;\n    longjmp(return_from_sigill, 1);\n}\n\nstatic int mbedtls_a64_crypto_sha512_determine_support(void)\n{\n    struct sigaction old_action, new_action;\n\n    sigset_t old_mask;\n    if (sigprocmask(0, NULL, &old_mask)) {\n        return 0;\n    }\n\n    sigemptyset(&new_action.sa_mask);\n    new_action.sa_flags = 0;\n    new_action.sa_handler = sigill_handler;\n\n    sigaction(SIGILL, &new_action, &old_action);\n\n    static int ret = 0;\n\n    if (setjmp(return_from_sigill) == 0) {         /* First return only */\n        /* If this traps, we will return a second time from setjmp() with 1 */\n        asm (\"sha512h q0, q0, v0.2d\" : : : \"v0\");\n        ret = 1;\n    }\n\n    sigaction(SIGILL, &old_action, NULL);\n    sigprocmask(SIG_SETMASK, &old_mask, NULL);\n\n    return ret;\n}\n#else\n#warning \"No mechanism to detect A64_CRYPTO found, using C code only\"\n#undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT\n#endif  /* HWCAP_SHA512, __APPLE__, __unix__ && SIG_SETMASK */\n\n#endif  /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */\n\n#if !defined(MBEDTLS_SHA512_ALT)\n\n#define SHA512_BLOCK_SIZE 128\n\n#if defined(MBEDTLS_SHA512_SMALLER)\nstatic void sha512_put_uint64_be(uint64_t n, unsigned char *b, uint8_t i)\n{\n    MBEDTLS_PUT_UINT64_BE(n, b, i);\n}\n#else\n#define sha512_put_uint64_be    MBEDTLS_PUT_UINT64_BE\n#endif /* MBEDTLS_SHA512_SMALLER */\n\nvoid mbedtls_sha512_init(mbedtls_sha512_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_sha512_context));\n}\n\nvoid mbedtls_sha512_free(mbedtls_sha512_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha512_context));\n}\n\nvoid mbedtls_sha512_clone(mbedtls_sha512_context *dst,\n                          const mbedtls_sha512_context *src)\n{\n    *dst = *src;\n}\n\n/*\n * SHA-512 context setup\n */\nint mbedtls_sha512_starts(mbedtls_sha512_context *ctx, int is384)\n{\n#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C)\n    if (is384 != 0 && is384 != 1) {\n        return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;\n    }\n#elif defined(MBEDTLS_SHA512_C)\n    if (is384 != 0) {\n        return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;\n    }\n#else /* defined MBEDTLS_SHA384_C only */\n    if (is384 == 0) {\n        return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;\n    }\n#endif\n\n    ctx->total[0] = 0;\n    ctx->total[1] = 0;\n\n    if (is384 == 0) {\n#if defined(MBEDTLS_SHA512_C)\n        ctx->state[0] = UL64(0x6A09E667F3BCC908);\n        ctx->state[1] = UL64(0xBB67AE8584CAA73B);\n        ctx->state[2] = UL64(0x3C6EF372FE94F82B);\n        ctx->state[3] = UL64(0xA54FF53A5F1D36F1);\n        ctx->state[4] = UL64(0x510E527FADE682D1);\n        ctx->state[5] = UL64(0x9B05688C2B3E6C1F);\n        ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);\n        ctx->state[7] = UL64(0x5BE0CD19137E2179);\n#endif /* MBEDTLS_SHA512_C */\n    } else {\n#if defined(MBEDTLS_SHA384_C)\n        ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);\n        ctx->state[1] = UL64(0x629A292A367CD507);\n        ctx->state[2] = UL64(0x9159015A3070DD17);\n        ctx->state[3] = UL64(0x152FECD8F70E5939);\n        ctx->state[4] = UL64(0x67332667FFC00B31);\n        ctx->state[5] = UL64(0x8EB44A8768581511);\n        ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);\n        ctx->state[7] = UL64(0x47B5481DBEFA4FA4);\n#endif /* MBEDTLS_SHA384_C */\n    }\n\n#if defined(MBEDTLS_SHA384_C)\n    ctx->is384 = is384;\n#endif\n\n    return 0;\n}\n\n#if !defined(MBEDTLS_SHA512_PROCESS_ALT)\n\n/*\n * Round constants\n */\nstatic const uint64_t K[80] =\n{\n    UL64(0x428A2F98D728AE22),  UL64(0x7137449123EF65CD),\n    UL64(0xB5C0FBCFEC4D3B2F),  UL64(0xE9B5DBA58189DBBC),\n    UL64(0x3956C25BF348B538),  UL64(0x59F111F1B605D019),\n    UL64(0x923F82A4AF194F9B),  UL64(0xAB1C5ED5DA6D8118),\n    UL64(0xD807AA98A3030242),  UL64(0x12835B0145706FBE),\n    UL64(0x243185BE4EE4B28C),  UL64(0x550C7DC3D5FFB4E2),\n    UL64(0x72BE5D74F27B896F),  UL64(0x80DEB1FE3B1696B1),\n    UL64(0x9BDC06A725C71235),  UL64(0xC19BF174CF692694),\n    UL64(0xE49B69C19EF14AD2),  UL64(0xEFBE4786384F25E3),\n    UL64(0x0FC19DC68B8CD5B5),  UL64(0x240CA1CC77AC9C65),\n    UL64(0x2DE92C6F592B0275),  UL64(0x4A7484AA6EA6E483),\n    UL64(0x5CB0A9DCBD41FBD4),  UL64(0x76F988DA831153B5),\n    UL64(0x983E5152EE66DFAB),  UL64(0xA831C66D2DB43210),\n    UL64(0xB00327C898FB213F),  UL64(0xBF597FC7BEEF0EE4),\n    UL64(0xC6E00BF33DA88FC2),  UL64(0xD5A79147930AA725),\n    UL64(0x06CA6351E003826F),  UL64(0x142929670A0E6E70),\n    UL64(0x27B70A8546D22FFC),  UL64(0x2E1B21385C26C926),\n    UL64(0x4D2C6DFC5AC42AED),  UL64(0x53380D139D95B3DF),\n    UL64(0x650A73548BAF63DE),  UL64(0x766A0ABB3C77B2A8),\n    UL64(0x81C2C92E47EDAEE6),  UL64(0x92722C851482353B),\n    UL64(0xA2BFE8A14CF10364),  UL64(0xA81A664BBC423001),\n    UL64(0xC24B8B70D0F89791),  UL64(0xC76C51A30654BE30),\n    UL64(0xD192E819D6EF5218),  UL64(0xD69906245565A910),\n    UL64(0xF40E35855771202A),  UL64(0x106AA07032BBD1B8),\n    UL64(0x19A4C116B8D2D0C8),  UL64(0x1E376C085141AB53),\n    UL64(0x2748774CDF8EEB99),  UL64(0x34B0BCB5E19B48A8),\n    UL64(0x391C0CB3C5C95A63),  UL64(0x4ED8AA4AE3418ACB),\n    UL64(0x5B9CCA4F7763E373),  UL64(0x682E6FF3D6B2B8A3),\n    UL64(0x748F82EE5DEFB2FC),  UL64(0x78A5636F43172F60),\n    UL64(0x84C87814A1F0AB72),  UL64(0x8CC702081A6439EC),\n    UL64(0x90BEFFFA23631E28),  UL64(0xA4506CEBDE82BDE9),\n    UL64(0xBEF9A3F7B2C67915),  UL64(0xC67178F2E372532B),\n    UL64(0xCA273ECEEA26619C),  UL64(0xD186B8C721C0C207),\n    UL64(0xEADA7DD6CDE0EB1E),  UL64(0xF57D4F7FEE6ED178),\n    UL64(0x06F067AA72176FBA),  UL64(0x0A637DC5A2C898A6),\n    UL64(0x113F9804BEF90DAE),  UL64(0x1B710B35131C471B),\n    UL64(0x28DB77F523047D84),  UL64(0x32CAAB7B40C72493),\n    UL64(0x3C9EBE0A15C9BEBC),  UL64(0x431D67C49C100D4C),\n    UL64(0x4CC5D4BECB3E42B6),  UL64(0x597F299CFC657E2A),\n    UL64(0x5FCB6FAB3AD6FAEC),  UL64(0x6C44198C4A475817)\n};\n#endif\n\n#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \\\n    defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)\n\n#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)\n#  define mbedtls_internal_sha512_process_many_a64_crypto mbedtls_internal_sha512_process_many\n#  define mbedtls_internal_sha512_process_a64_crypto      mbedtls_internal_sha512_process\n#endif\n\n/* Accelerated SHA-512 implementation originally written by Simon Tatham for PuTTY,\n * under the MIT licence; dual-licensed as Apache 2 with his kind permission.\n */\n\n#if defined(__clang__) && \\\n    (__clang_major__ < 13 || \\\n     (__clang_major__ == 13 && __clang_minor__ == 0 && __clang_patchlevel__ == 0))\nstatic inline uint64x2_t vsha512su0q_u64(uint64x2_t x, uint64x2_t y)\n{\n    asm (\"sha512su0 %0.2D,%1.2D\" : \"+w\" (x) : \"w\" (y));\n    return x;\n}\nstatic inline uint64x2_t vsha512su1q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)\n{\n    asm (\"sha512su1 %0.2D,%1.2D,%2.2D\" : \"+w\" (x) : \"w\" (y), \"w\" (z));\n    return x;\n}\nstatic inline uint64x2_t vsha512hq_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)\n{\n    asm (\"sha512h %0,%1,%2.2D\" : \"+w\" (x) : \"w\" (y), \"w\" (z));\n    return x;\n}\nstatic inline uint64x2_t vsha512h2q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)\n{\n    asm (\"sha512h2 %0,%1,%2.2D\" : \"+w\" (x) : \"w\" (y), \"w\" (z));\n    return x;\n}\n#endif  /* __clang__ etc */\n\nstatic size_t mbedtls_internal_sha512_process_many_a64_crypto(\n    mbedtls_sha512_context *ctx, const uint8_t *msg, size_t len)\n{\n    uint64x2_t ab = vld1q_u64(&ctx->state[0]);\n    uint64x2_t cd = vld1q_u64(&ctx->state[2]);\n    uint64x2_t ef = vld1q_u64(&ctx->state[4]);\n    uint64x2_t gh = vld1q_u64(&ctx->state[6]);\n\n    size_t processed = 0;\n\n    for (;\n         len >= SHA512_BLOCK_SIZE;\n         processed += SHA512_BLOCK_SIZE,\n         msg += SHA512_BLOCK_SIZE,\n         len -= SHA512_BLOCK_SIZE) {\n        uint64x2_t initial_sum, sum, intermed;\n\n        uint64x2_t ab_orig = ab;\n        uint64x2_t cd_orig = cd;\n        uint64x2_t ef_orig = ef;\n        uint64x2_t gh_orig = gh;\n\n        uint64x2_t s0 = (uint64x2_t) vld1q_u8(msg + 16 * 0);\n        uint64x2_t s1 = (uint64x2_t) vld1q_u8(msg + 16 * 1);\n        uint64x2_t s2 = (uint64x2_t) vld1q_u8(msg + 16 * 2);\n        uint64x2_t s3 = (uint64x2_t) vld1q_u8(msg + 16 * 3);\n        uint64x2_t s4 = (uint64x2_t) vld1q_u8(msg + 16 * 4);\n        uint64x2_t s5 = (uint64x2_t) vld1q_u8(msg + 16 * 5);\n        uint64x2_t s6 = (uint64x2_t) vld1q_u8(msg + 16 * 6);\n        uint64x2_t s7 = (uint64x2_t) vld1q_u8(msg + 16 * 7);\n\n#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__  /* assume LE if these not defined; untested on BE */\n        s0 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s0)));\n        s1 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s1)));\n        s2 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s2)));\n        s3 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s3)));\n        s4 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s4)));\n        s5 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s5)));\n        s6 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s6)));\n        s7 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s7)));\n#endif\n\n        /* Rounds 0 and 1 */\n        initial_sum = vaddq_u64(s0, vld1q_u64(&K[0]));\n        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh);\n        intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1));\n        gh = vsha512h2q_u64(intermed, cd, ab);\n        cd = vaddq_u64(cd, intermed);\n\n        /* Rounds 2 and 3 */\n        initial_sum = vaddq_u64(s1, vld1q_u64(&K[2]));\n        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef);\n        intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1));\n        ef = vsha512h2q_u64(intermed, ab, gh);\n        ab = vaddq_u64(ab, intermed);\n\n        /* Rounds 4 and 5 */\n        initial_sum = vaddq_u64(s2, vld1q_u64(&K[4]));\n        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd);\n        intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1));\n        cd = vsha512h2q_u64(intermed, gh, ef);\n        gh = vaddq_u64(gh, intermed);\n\n        /* Rounds 6 and 7 */\n        initial_sum = vaddq_u64(s3, vld1q_u64(&K[6]));\n        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab);\n        intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1));\n        ab = vsha512h2q_u64(intermed, ef, cd);\n        ef = vaddq_u64(ef, intermed);\n\n        /* Rounds 8 and 9 */\n        initial_sum = vaddq_u64(s4, vld1q_u64(&K[8]));\n        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh);\n        intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1));\n        gh = vsha512h2q_u64(intermed, cd, ab);\n        cd = vaddq_u64(cd, intermed);\n\n        /* Rounds 10 and 11 */\n        initial_sum = vaddq_u64(s5, vld1q_u64(&K[10]));\n        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef);\n        intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1));\n        ef = vsha512h2q_u64(intermed, ab, gh);\n        ab = vaddq_u64(ab, intermed);\n\n        /* Rounds 12 and 13 */\n        initial_sum = vaddq_u64(s6, vld1q_u64(&K[12]));\n        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd);\n        intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1));\n        cd = vsha512h2q_u64(intermed, gh, ef);\n        gh = vaddq_u64(gh, intermed);\n\n        /* Rounds 14 and 15 */\n        initial_sum = vaddq_u64(s7, vld1q_u64(&K[14]));\n        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab);\n        intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1));\n        ab = vsha512h2q_u64(intermed, ef, cd);\n        ef = vaddq_u64(ef, intermed);\n\n        for (unsigned int t = 16; t < 80; t += 16) {\n            /* Rounds t and t + 1 */\n            s0 = vsha512su1q_u64(vsha512su0q_u64(s0, s1), s7, vextq_u64(s4, s5, 1));\n            initial_sum = vaddq_u64(s0, vld1q_u64(&K[t]));\n            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh);\n            intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1));\n            gh = vsha512h2q_u64(intermed, cd, ab);\n            cd = vaddq_u64(cd, intermed);\n\n            /* Rounds t + 2 and t + 3 */\n            s1 = vsha512su1q_u64(vsha512su0q_u64(s1, s2), s0, vextq_u64(s5, s6, 1));\n            initial_sum = vaddq_u64(s1, vld1q_u64(&K[t + 2]));\n            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef);\n            intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1));\n            ef = vsha512h2q_u64(intermed, ab, gh);\n            ab = vaddq_u64(ab, intermed);\n\n            /* Rounds t + 4 and t + 5 */\n            s2 = vsha512su1q_u64(vsha512su0q_u64(s2, s3), s1, vextq_u64(s6, s7, 1));\n            initial_sum = vaddq_u64(s2, vld1q_u64(&K[t + 4]));\n            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd);\n            intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1));\n            cd = vsha512h2q_u64(intermed, gh, ef);\n            gh = vaddq_u64(gh, intermed);\n\n            /* Rounds t + 6 and t + 7 */\n            s3 = vsha512su1q_u64(vsha512su0q_u64(s3, s4), s2, vextq_u64(s7, s0, 1));\n            initial_sum = vaddq_u64(s3, vld1q_u64(&K[t + 6]));\n            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab);\n            intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1));\n            ab = vsha512h2q_u64(intermed, ef, cd);\n            ef = vaddq_u64(ef, intermed);\n\n            /* Rounds t + 8 and t + 9 */\n            s4 = vsha512su1q_u64(vsha512su0q_u64(s4, s5), s3, vextq_u64(s0, s1, 1));\n            initial_sum = vaddq_u64(s4, vld1q_u64(&K[t + 8]));\n            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh);\n            intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1));\n            gh = vsha512h2q_u64(intermed, cd, ab);\n            cd = vaddq_u64(cd, intermed);\n\n            /* Rounds t + 10 and t + 11 */\n            s5 = vsha512su1q_u64(vsha512su0q_u64(s5, s6), s4, vextq_u64(s1, s2, 1));\n            initial_sum = vaddq_u64(s5, vld1q_u64(&K[t + 10]));\n            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef);\n            intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1));\n            ef = vsha512h2q_u64(intermed, ab, gh);\n            ab = vaddq_u64(ab, intermed);\n\n            /* Rounds t + 12 and t + 13 */\n            s6 = vsha512su1q_u64(vsha512su0q_u64(s6, s7), s5, vextq_u64(s2, s3, 1));\n            initial_sum = vaddq_u64(s6, vld1q_u64(&K[t + 12]));\n            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd);\n            intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1));\n            cd = vsha512h2q_u64(intermed, gh, ef);\n            gh = vaddq_u64(gh, intermed);\n\n            /* Rounds t + 14 and t + 15 */\n            s7 = vsha512su1q_u64(vsha512su0q_u64(s7, s0), s6, vextq_u64(s3, s4, 1));\n            initial_sum = vaddq_u64(s7, vld1q_u64(&K[t + 14]));\n            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab);\n            intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1));\n            ab = vsha512h2q_u64(intermed, ef, cd);\n            ef = vaddq_u64(ef, intermed);\n        }\n\n        ab = vaddq_u64(ab, ab_orig);\n        cd = vaddq_u64(cd, cd_orig);\n        ef = vaddq_u64(ef, ef_orig);\n        gh = vaddq_u64(gh, gh_orig);\n    }\n\n    vst1q_u64(&ctx->state[0], ab);\n    vst1q_u64(&ctx->state[2], cd);\n    vst1q_u64(&ctx->state[4], ef);\n    vst1q_u64(&ctx->state[6], gh);\n\n    return processed;\n}\n\n#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)\n/*\n * This function is for internal use only if we are building both C and A64\n * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process()\n */\nstatic\n#endif\nint mbedtls_internal_sha512_process_a64_crypto(mbedtls_sha512_context *ctx,\n                                               const unsigned char data[SHA512_BLOCK_SIZE])\n{\n    return (mbedtls_internal_sha512_process_many_a64_crypto(ctx, data,\n                                                            SHA512_BLOCK_SIZE) ==\n            SHA512_BLOCK_SIZE) ? 0 : -1;\n}\n\n#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */\n\n#if defined(MBEDTLS_POP_TARGET_PRAGMA)\n#if defined(__clang__)\n#pragma clang attribute pop\n#elif defined(__GNUC__)\n#pragma GCC pop_options\n#endif\n#undef MBEDTLS_POP_TARGET_PRAGMA\n#endif\n\n\n#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)\n#define mbedtls_internal_sha512_process_many_c mbedtls_internal_sha512_process_many\n#define mbedtls_internal_sha512_process_c      mbedtls_internal_sha512_process\n#endif\n\n\n#if !defined(MBEDTLS_SHA512_PROCESS_ALT) && !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)\n\n#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)\n/*\n * This function is for internal use only if we are building both C and A64\n * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process()\n */\nstatic\n#endif\nint mbedtls_internal_sha512_process_c(mbedtls_sha512_context *ctx,\n                                      const unsigned char data[SHA512_BLOCK_SIZE])\n{\n    int i;\n    struct {\n        uint64_t temp1, temp2, W[80];\n        uint64_t A[8];\n    } local;\n\n#define  SHR(x, n) ((x) >> (n))\n#define ROTR(x, n) (SHR((x), (n)) | ((x) << (64 - (n))))\n\n#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^  SHR(x, 7))\n#define S1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^  SHR(x, 6))\n\n#define S2(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))\n#define S3(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))\n\n#define F0(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))\n#define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))\n\n#define P(a, b, c, d, e, f, g, h, x, K)                                      \\\n    do                                                              \\\n    {                                                               \\\n        local.temp1 = (h) + S3(e) + F1((e), (f), (g)) + (K) + (x);    \\\n        local.temp2 = S2(a) + F0((a), (b), (c));                      \\\n        (d) += local.temp1; (h) = local.temp1 + local.temp2;        \\\n    } while (0)\n\n    for (i = 0; i < 8; i++) {\n        local.A[i] = ctx->state[i];\n    }\n\n#if defined(MBEDTLS_SHA512_SMALLER)\n    for (i = 0; i < 80; i++) {\n        if (i < 16) {\n            local.W[i] = MBEDTLS_GET_UINT64_BE(data, i << 3);\n        } else {\n            local.W[i] = S1(local.W[i -  2]) + local.W[i -  7] +\n                         S0(local.W[i - 15]) + local.W[i - 16];\n        }\n\n        P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],\n          local.A[5], local.A[6], local.A[7], local.W[i], K[i]);\n\n        local.temp1 = local.A[7]; local.A[7] = local.A[6];\n        local.A[6] = local.A[5]; local.A[5] = local.A[4];\n        local.A[4] = local.A[3]; local.A[3] = local.A[2];\n        local.A[2] = local.A[1]; local.A[1] = local.A[0];\n        local.A[0] = local.temp1;\n    }\n#else /* MBEDTLS_SHA512_SMALLER */\n    for (i = 0; i < 16; i++) {\n        local.W[i] = MBEDTLS_GET_UINT64_BE(data, i << 3);\n    }\n\n    for (; i < 80; i++) {\n        local.W[i] = S1(local.W[i -  2]) + local.W[i -  7] +\n                     S0(local.W[i - 15]) + local.W[i - 16];\n    }\n\n    i = 0;\n    do {\n        P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],\n          local.A[5], local.A[6], local.A[7], local.W[i], K[i]); i++;\n        P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],\n          local.A[4], local.A[5], local.A[6], local.W[i], K[i]); i++;\n        P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],\n          local.A[3], local.A[4], local.A[5], local.W[i], K[i]); i++;\n        P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],\n          local.A[2], local.A[3], local.A[4], local.W[i], K[i]); i++;\n        P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],\n          local.A[1], local.A[2], local.A[3], local.W[i], K[i]); i++;\n        P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],\n          local.A[0], local.A[1], local.A[2], local.W[i], K[i]); i++;\n        P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],\n          local.A[7], local.A[0], local.A[1], local.W[i], K[i]); i++;\n        P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],\n          local.A[6], local.A[7], local.A[0], local.W[i], K[i]); i++;\n    } while (i < 80);\n#endif /* MBEDTLS_SHA512_SMALLER */\n\n    for (i = 0; i < 8; i++) {\n        ctx->state[i] += local.A[i];\n    }\n\n    /* Zeroise buffers and variables to clear sensitive data from memory. */\n    mbedtls_platform_zeroize(&local, sizeof(local));\n\n    return 0;\n}\n\n#endif /* !MBEDTLS_SHA512_PROCESS_ALT && !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */\n\n\n#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)\n\nstatic size_t mbedtls_internal_sha512_process_many_c(\n    mbedtls_sha512_context *ctx, const uint8_t *data, size_t len)\n{\n    size_t processed = 0;\n\n    while (len >= SHA512_BLOCK_SIZE) {\n        if (mbedtls_internal_sha512_process_c(ctx, data) != 0) {\n            return 0;\n        }\n\n        data += SHA512_BLOCK_SIZE;\n        len  -= SHA512_BLOCK_SIZE;\n\n        processed += SHA512_BLOCK_SIZE;\n    }\n\n    return processed;\n}\n\n#endif /* !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */\n\n\n#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)\n\nstatic int mbedtls_a64_crypto_sha512_has_support(void)\n{\n    static int done = 0;\n    static int supported = 0;\n\n    if (!done) {\n        supported = mbedtls_a64_crypto_sha512_determine_support();\n        done = 1;\n    }\n\n    return supported;\n}\n\nstatic size_t mbedtls_internal_sha512_process_many(mbedtls_sha512_context *ctx,\n                                                   const uint8_t *msg, size_t len)\n{\n    if (mbedtls_a64_crypto_sha512_has_support()) {\n        return mbedtls_internal_sha512_process_many_a64_crypto(ctx, msg, len);\n    } else {\n        return mbedtls_internal_sha512_process_many_c(ctx, msg, len);\n    }\n}\n\nint mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx,\n                                    const unsigned char data[SHA512_BLOCK_SIZE])\n{\n    if (mbedtls_a64_crypto_sha512_has_support()) {\n        return mbedtls_internal_sha512_process_a64_crypto(ctx, data);\n    } else {\n        return mbedtls_internal_sha512_process_c(ctx, data);\n    }\n}\n\n#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */\n\n/*\n * SHA-512 process buffer\n */\nint mbedtls_sha512_update(mbedtls_sha512_context *ctx,\n                          const unsigned char *input,\n                          size_t ilen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t fill;\n    unsigned int left;\n\n    if (ilen == 0) {\n        return 0;\n    }\n\n    left = (unsigned int) (ctx->total[0] & 0x7F);\n    fill = SHA512_BLOCK_SIZE - left;\n\n    ctx->total[0] += (uint64_t) ilen;\n\n    if (ctx->total[0] < (uint64_t) ilen) {\n        ctx->total[1]++;\n    }\n\n    if (left && ilen >= fill) {\n        memcpy((void *) (ctx->buffer + left), input, fill);\n\n        if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) {\n            return ret;\n        }\n\n        input += fill;\n        ilen  -= fill;\n        left = 0;\n    }\n\n    while (ilen >= SHA512_BLOCK_SIZE) {\n        size_t processed =\n            mbedtls_internal_sha512_process_many(ctx, input, ilen);\n        if (processed < SHA512_BLOCK_SIZE) {\n            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;\n        }\n\n        input += processed;\n        ilen  -= processed;\n    }\n\n    if (ilen > 0) {\n        memcpy((void *) (ctx->buffer + left), input, ilen);\n    }\n\n    return 0;\n}\n\n/*\n * SHA-512 final digest\n */\nint mbedtls_sha512_finish(mbedtls_sha512_context *ctx,\n                          unsigned char *output)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned used;\n    uint64_t high, low;\n    int truncated = 0;\n\n    /*\n     * Add padding: 0x80 then 0x00 until 16 bytes remain for the length\n     */\n    used = ctx->total[0] & 0x7F;\n\n    ctx->buffer[used++] = 0x80;\n\n    if (used <= 112) {\n        /* Enough room for padding + length in current block */\n        memset(ctx->buffer + used, 0, 112 - used);\n    } else {\n        /* We'll need an extra block */\n        memset(ctx->buffer + used, 0, SHA512_BLOCK_SIZE - used);\n\n        if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) {\n            goto exit;\n        }\n\n        memset(ctx->buffer, 0, 112);\n    }\n\n    /*\n     * Add message length\n     */\n    high = (ctx->total[0] >> 61)\n           | (ctx->total[1] <<  3);\n    low  = (ctx->total[0] <<  3);\n\n    sha512_put_uint64_be(high, ctx->buffer, 112);\n    sha512_put_uint64_be(low,  ctx->buffer, 120);\n\n    if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) {\n        goto exit;\n    }\n\n    /*\n     * Output final state\n     */\n    sha512_put_uint64_be(ctx->state[0], output,  0);\n    sha512_put_uint64_be(ctx->state[1], output,  8);\n    sha512_put_uint64_be(ctx->state[2], output, 16);\n    sha512_put_uint64_be(ctx->state[3], output, 24);\n    sha512_put_uint64_be(ctx->state[4], output, 32);\n    sha512_put_uint64_be(ctx->state[5], output, 40);\n\n#if defined(MBEDTLS_SHA384_C)\n    truncated = ctx->is384;\n#endif\n    if (!truncated) {\n        sha512_put_uint64_be(ctx->state[6], output, 48);\n        sha512_put_uint64_be(ctx->state[7], output, 56);\n    }\n\n    ret = 0;\n\nexit:\n    mbedtls_sha512_free(ctx);\n    return ret;\n}\n\n#endif /* !MBEDTLS_SHA512_ALT */\n\n/*\n * output = SHA-512( input buffer )\n */\nint mbedtls_sha512(const unsigned char *input,\n                   size_t ilen,\n                   unsigned char *output,\n                   int is384)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_sha512_context ctx;\n\n#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C)\n    if (is384 != 0 && is384 != 1) {\n        return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;\n    }\n#elif defined(MBEDTLS_SHA512_C)\n    if (is384 != 0) {\n        return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;\n    }\n#else /* defined MBEDTLS_SHA384_C only */\n    if (is384 == 0) {\n        return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;\n    }\n#endif\n\n    mbedtls_sha512_init(&ctx);\n\n    if ((ret = mbedtls_sha512_starts(&ctx, is384)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_sha512_update(&ctx, input, ilen)) != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_sha512_finish(&ctx, output)) != 0) {\n        goto exit;\n    }\n\nexit:\n    mbedtls_sha512_free(&ctx);\n\n    return ret;\n}\n\n#if defined(MBEDTLS_SELF_TEST)\n\n/*\n * FIPS-180-2 test vectors\n */\nstatic const unsigned char sha_test_buf[3][113] =\n{\n    { \"abc\" },\n    {\n        \"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu\"\n    },\n    { \"\" }\n};\n\nstatic const size_t sha_test_buflen[3] =\n{\n    3, 112, 1000\n};\n\ntypedef const unsigned char (sha_test_sum_t)[64];\n\n/*\n * SHA-384 test vectors\n */\n#if defined(MBEDTLS_SHA384_C)\nstatic sha_test_sum_t sha384_test_sum[] =\n{\n    { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,\n      0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,\n      0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,\n      0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,\n      0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,\n      0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 },\n    { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,\n      0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,\n      0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,\n      0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,\n      0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,\n      0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 },\n    { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB,\n      0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C,\n      0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,\n      0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,\n      0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,\n      0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }\n};\n#endif /* MBEDTLS_SHA384_C */\n\n/*\n * SHA-512 test vectors\n */\n#if defined(MBEDTLS_SHA512_C)\nstatic sha_test_sum_t sha512_test_sum[] =\n{\n    { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,\n      0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,\n      0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,\n      0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,\n      0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,\n      0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,\n      0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,\n      0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F },\n    { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,\n      0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,\n      0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,\n      0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,\n      0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,\n      0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,\n      0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,\n      0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 },\n    { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,\n      0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,\n      0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,\n      0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,\n      0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,\n      0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,\n      0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,\n      0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }\n};\n#endif /* MBEDTLS_SHA512_C */\n\nstatic int mbedtls_sha512_common_self_test(int verbose, int is384)\n{\n    int i, buflen, ret = 0;\n    unsigned char *buf;\n    unsigned char sha512sum[64];\n    mbedtls_sha512_context ctx;\n\n#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C)\n    sha_test_sum_t *sha_test_sum = (is384) ? sha384_test_sum : sha512_test_sum;\n#elif defined(MBEDTLS_SHA512_C)\n    sha_test_sum_t *sha_test_sum = sha512_test_sum;\n#else\n    sha_test_sum_t *sha_test_sum = sha384_test_sum;\n#endif\n\n    buf = mbedtls_calloc(1024, sizeof(unsigned char));\n    if (NULL == buf) {\n        if (verbose != 0) {\n            mbedtls_printf(\"Buffer allocation failed\\n\");\n        }\n\n        return 1;\n    }\n\n    mbedtls_sha512_init(&ctx);\n\n    for (i = 0; i < 3; i++) {\n        if (verbose != 0) {\n            mbedtls_printf(\"  SHA-%d test #%d: \", 512 - is384 * 128, i + 1);\n        }\n\n        if ((ret = mbedtls_sha512_starts(&ctx, is384)) != 0) {\n            goto fail;\n        }\n\n        if (i == 2) {\n            memset(buf, 'a', buflen = 1000);\n\n            for (int j = 0; j < 1000; j++) {\n                ret = mbedtls_sha512_update(&ctx, buf, buflen);\n                if (ret != 0) {\n                    goto fail;\n                }\n            }\n        } else {\n            ret = mbedtls_sha512_update(&ctx, sha_test_buf[i],\n                                        sha_test_buflen[i]);\n            if (ret != 0) {\n                goto fail;\n            }\n        }\n\n        if ((ret = mbedtls_sha512_finish(&ctx, sha512sum)) != 0) {\n            goto fail;\n        }\n\n        if (memcmp(sha512sum, sha_test_sum[i], 64 - is384 * 16) != 0) {\n            ret = 1;\n            goto fail;\n        }\n\n        if (verbose != 0) {\n            mbedtls_printf(\"passed\\n\");\n        }\n    }\n\n    if (verbose != 0) {\n        mbedtls_printf(\"\\n\");\n    }\n\n    goto exit;\n\nfail:\n    if (verbose != 0) {\n        mbedtls_printf(\"failed\\n\");\n    }\n\nexit:\n    mbedtls_sha512_free(&ctx);\n    mbedtls_free(buf);\n\n    return ret;\n}\n\n#if defined(MBEDTLS_SHA512_C)\nint mbedtls_sha512_self_test(int verbose)\n{\n    return mbedtls_sha512_common_self_test(verbose, 0);\n}\n#endif /* MBEDTLS_SHA512_C */\n\n#if defined(MBEDTLS_SHA384_C)\nint mbedtls_sha384_self_test(int verbose)\n{\n    return mbedtls_sha512_common_self_test(verbose, 1);\n}\n#endif /* MBEDTLS_SHA384_C */\n\n#undef ARRAY_LENGTH\n\n#endif /* MBEDTLS_SELF_TEST */\n\n#endif /* MBEDTLS_SHA512_C || MBEDTLS_SHA384_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_cache.c",
    "content": "/*\n *  SSL session cache implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n * These session callbacks use a simple chained list\n * to store and retrieve the session information.\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_CACHE_C)\n\n#include \"mbedtls/platform.h\"\n\n#include \"mbedtls/ssl_cache.h\"\n#include \"ssl_misc.h\"\n#include \"mbedtls/error.h\"\n\n#include <string.h>\n\nvoid mbedtls_ssl_cache_init(mbedtls_ssl_cache_context *cache)\n{\n    memset(cache, 0, sizeof(mbedtls_ssl_cache_context));\n\n    cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT;\n    cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES;\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_init(&cache->mutex);\n#endif\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_cache_find_entry(mbedtls_ssl_cache_context *cache,\n                                unsigned char const *session_id,\n                                size_t session_id_len,\n                                mbedtls_ssl_cache_entry **dst)\n{\n    int ret = MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND;\n#if defined(MBEDTLS_HAVE_TIME)\n    mbedtls_time_t t = mbedtls_time(NULL);\n#endif\n    mbedtls_ssl_cache_entry *cur;\n\n    for (cur = cache->chain; cur != NULL; cur = cur->next) {\n#if defined(MBEDTLS_HAVE_TIME)\n        if (cache->timeout != 0 &&\n            (int) (t - cur->timestamp) > cache->timeout) {\n            continue;\n        }\n#endif\n\n        if (session_id_len != cur->session_id_len ||\n            memcmp(session_id, cur->session_id,\n                   cur->session_id_len) != 0) {\n            continue;\n        }\n\n        break;\n    }\n\n    if (cur != NULL) {\n        *dst = cur;\n        ret = 0;\n    }\n\n    return ret;\n}\n\n\nint mbedtls_ssl_cache_get(void *data,\n                          unsigned char const *session_id,\n                          size_t session_id_len,\n                          mbedtls_ssl_session *session)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;\n    mbedtls_ssl_cache_entry *entry;\n\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) {\n        return ret;\n    }\n#endif\n\n    ret = ssl_cache_find_entry(cache, session_id, session_id_len, &entry);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    ret = mbedtls_ssl_session_load(session,\n                                   entry->session,\n                                   entry->session_len);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    ret = 0;\n\nexit:\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&cache->mutex) != 0) {\n        ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n#endif\n\n    return ret;\n}\n\n/* zeroize a cache entry */\nstatic void ssl_cache_entry_zeroize(mbedtls_ssl_cache_entry *entry)\n{\n    if (entry == NULL) {\n        return;\n    }\n\n    /* zeroize and free session structure */\n    if (entry->session != NULL) {\n        mbedtls_zeroize_and_free(entry->session, entry->session_len);\n    }\n\n    /* zeroize the whole entry structure */\n    mbedtls_platform_zeroize(entry, sizeof(mbedtls_ssl_cache_entry));\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_cache_pick_writing_slot(mbedtls_ssl_cache_context *cache,\n                                       unsigned char const *session_id,\n                                       size_t session_id_len,\n                                       mbedtls_ssl_cache_entry **dst)\n{\n#if defined(MBEDTLS_HAVE_TIME)\n    mbedtls_time_t t = mbedtls_time(NULL), oldest = 0;\n#endif /* MBEDTLS_HAVE_TIME */\n\n    mbedtls_ssl_cache_entry *old = NULL;\n    int count = 0;\n    mbedtls_ssl_cache_entry *cur, *last;\n\n    /* Check 1: Is there already an entry with the given session ID?\n     *\n     * If yes, overwrite it.\n     *\n     * If not, `count` will hold the size of the session cache\n     * at the end of this loop, and `last` will point to the last\n     * entry, both of which will be used later. */\n\n    last = NULL;\n    for (cur = cache->chain; cur != NULL; cur = cur->next) {\n        count++;\n        if (session_id_len == cur->session_id_len &&\n            memcmp(session_id, cur->session_id, cur->session_id_len) == 0) {\n            goto found;\n        }\n        last = cur;\n    }\n\n    /* Check 2: Is there an outdated entry in the cache?\n     *\n     * If so, overwrite it.\n     *\n     * If not, remember the oldest entry in `old` for later.\n     */\n\n#if defined(MBEDTLS_HAVE_TIME)\n    for (cur = cache->chain; cur != NULL; cur = cur->next) {\n        if (cache->timeout != 0 &&\n            (int) (t - cur->timestamp) > cache->timeout) {\n            goto found;\n        }\n\n        if (oldest == 0 || cur->timestamp < oldest) {\n            oldest = cur->timestamp;\n            old = cur;\n        }\n    }\n#endif /* MBEDTLS_HAVE_TIME */\n\n    /* Check 3: Is there free space in the cache? */\n\n    if (count < cache->max_entries) {\n        /* Create new entry */\n        cur = mbedtls_calloc(1, sizeof(mbedtls_ssl_cache_entry));\n        if (cur == NULL) {\n            return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        }\n\n        /* Append to the end of the linked list. */\n        if (last == NULL) {\n            cache->chain = cur;\n        } else {\n            last->next = cur;\n        }\n\n        goto found;\n    }\n\n    /* Last resort: The cache is full and doesn't contain any outdated\n     * elements. In this case, we evict the oldest one, judged by timestamp\n     * (if present) or cache-order. */\n\n#if defined(MBEDTLS_HAVE_TIME)\n    if (old == NULL) {\n        /* This should only happen on an ill-configured cache\n         * with max_entries == 0. */\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n#else /* MBEDTLS_HAVE_TIME */\n    /* Reuse first entry in chain, but move to last place. */\n    if (cache->chain == NULL) {\n        /* This should never happen */\n        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    }\n\n    old = cache->chain;\n    cache->chain = old->next;\n    old->next = NULL;\n    last->next = old;\n#endif /* MBEDTLS_HAVE_TIME */\n\n    /* Now `old` points to the oldest entry to be overwritten. */\n    cur = old;\n\nfound:\n\n    /* If we're reusing an entry, free it first. */\n    if (cur->session != NULL) {\n        /* `ssl_cache_entry_zeroize` would break the chain,\n         * so we reuse `old` to record `next` temporarily. */\n        old = cur->next;\n        ssl_cache_entry_zeroize(cur);\n        cur->next = old;\n    }\n\n#if defined(MBEDTLS_HAVE_TIME)\n    cur->timestamp = t;\n#endif\n\n    *dst = cur;\n    return 0;\n}\n\nint mbedtls_ssl_cache_set(void *data,\n                          unsigned char const *session_id,\n                          size_t session_id_len,\n                          const mbedtls_ssl_session *session)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;\n    mbedtls_ssl_cache_entry *cur;\n\n    size_t session_serialized_len = 0;\n    unsigned char *session_serialized = NULL;\n\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) {\n        return ret;\n    }\n#endif\n\n    ret = ssl_cache_pick_writing_slot(cache,\n                                      session_id, session_id_len,\n                                      &cur);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    /* Check how much space we need to serialize the session\n     * and allocate a sufficiently large buffer. */\n    ret = mbedtls_ssl_session_save(session, NULL, 0, &session_serialized_len);\n    if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) {\n        goto exit;\n    }\n\n    session_serialized = mbedtls_calloc(1, session_serialized_len);\n    if (session_serialized == NULL) {\n        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        goto exit;\n    }\n\n    /* Now serialize the session into the allocated buffer. */\n    ret = mbedtls_ssl_session_save(session,\n                                   session_serialized,\n                                   session_serialized_len,\n                                   &session_serialized_len);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    if (session_id_len > sizeof(cur->session_id)) {\n        ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        goto exit;\n    }\n    cur->session_id_len = session_id_len;\n    memcpy(cur->session_id, session_id, session_id_len);\n\n    cur->session = session_serialized;\n    cur->session_len = session_serialized_len;\n    session_serialized = NULL;\n\n    ret = 0;\n\nexit:\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&cache->mutex) != 0) {\n        ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n#endif\n\n    if (session_serialized != NULL) {\n        mbedtls_zeroize_and_free(session_serialized, session_serialized_len);\n        session_serialized = NULL;\n    }\n\n    return ret;\n}\n\nint mbedtls_ssl_cache_remove(void *data,\n                             unsigned char const *session_id,\n                             size_t session_id_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;\n    mbedtls_ssl_cache_entry *entry;\n    mbedtls_ssl_cache_entry *prev;\n\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) {\n        return ret;\n    }\n#endif\n\n    ret = ssl_cache_find_entry(cache, session_id, session_id_len, &entry);\n    /* No valid entry found, exit with success */\n    if (ret != 0) {\n        ret = 0;\n        goto exit;\n    }\n\n    /* Now we remove the entry from the chain */\n    if (entry == cache->chain) {\n        cache->chain = entry->next;\n        goto free;\n    }\n    for (prev = cache->chain; prev->next != NULL; prev = prev->next) {\n        if (prev->next == entry) {\n            prev->next = entry->next;\n            break;\n        }\n    }\n\nfree:\n    ssl_cache_entry_zeroize(entry);\n    mbedtls_free(entry);\n    ret = 0;\n\nexit:\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&cache->mutex) != 0) {\n        ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n#endif\n\n    return ret;\n}\n\n#if defined(MBEDTLS_HAVE_TIME)\nvoid mbedtls_ssl_cache_set_timeout(mbedtls_ssl_cache_context *cache, int timeout)\n{\n    if (timeout < 0) {\n        timeout = 0;\n    }\n\n    cache->timeout = timeout;\n}\n#endif /* MBEDTLS_HAVE_TIME */\n\nvoid mbedtls_ssl_cache_set_max_entries(mbedtls_ssl_cache_context *cache, int max)\n{\n    if (max < 0) {\n        max = 0;\n    }\n\n    cache->max_entries = max;\n}\n\nvoid mbedtls_ssl_cache_free(mbedtls_ssl_cache_context *cache)\n{\n    mbedtls_ssl_cache_entry *cur, *prv;\n\n    cur = cache->chain;\n\n    while (cur != NULL) {\n        prv = cur;\n        cur = cur->next;\n\n        ssl_cache_entry_zeroize(prv);\n        mbedtls_free(prv);\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_free(&cache->mutex);\n#endif\n    cache->chain = NULL;\n}\n\n#endif /* MBEDTLS_SSL_CACHE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_ciphersuites.c",
    "content": "/**\n * \\file ssl_ciphersuites.c\n *\n * \\brief SSL ciphersuites for Mbed TLS\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_TLS_C)\n\n#include \"mbedtls/platform.h\"\n\n#include \"mbedtls/ssl_ciphersuites.h\"\n#include \"mbedtls/ssl.h\"\n#include \"ssl_misc.h\"\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"mbedtls/psa_util.h\"\n#endif\n\n#include <string.h>\n\n/*\n * Ordered from most preferred to least preferred in terms of security.\n *\n * Current rule (except weak and null which come last):\n * 1. By key exchange:\n *    Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK\n * 2. By key length and cipher:\n *    ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128\n * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8\n * 4. By hash function used when relevant\n * 5. By key exchange/auth again: EC > non-EC\n */\nstatic const int ciphersuite_preference[] =\n{\n#if defined(MBEDTLS_SSL_CIPHERSUITES)\n    MBEDTLS_SSL_CIPHERSUITES,\n#else\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    /* TLS 1.3 ciphersuites */\n    MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256,\n    MBEDTLS_TLS1_3_AES_256_GCM_SHA384,\n    MBEDTLS_TLS1_3_AES_128_GCM_SHA256,\n    MBEDTLS_TLS1_3_AES_128_CCM_SHA256,\n    MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256,\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n    /* Chacha-Poly ephemeral suites */\n    MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,\n    MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,\n\n    /* All AES-256 ephemeral suites */\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,\n    MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,\n    MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,\n    MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM,\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,\n    MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,\n    MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,\n    MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,\n    MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,\n    MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8,\n\n    /* All CAMELLIA-256 ephemeral suites */\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,\n    MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,\n    MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,\n    MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,\n    MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,\n    MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,\n\n    /* All ARIA-256 ephemeral suites */\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,\n    MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,\n    MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,\n    MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,\n    MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,\n\n    /* All AES-128 ephemeral suites */\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\n    MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,\n    MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,\n    MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM,\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,\n    MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,\n    MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,\n    MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,\n    MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,\n    MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8,\n\n    /* All CAMELLIA-128 ephemeral suites */\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,\n    MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,\n    MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,\n    MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,\n    MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,\n    MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,\n\n    /* All ARIA-128 ephemeral suites */\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,\n    MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,\n    MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,\n    MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,\n    MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,\n\n    /* The PSK ephemeral suites */\n    MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,\n    MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,\n    MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,\n    MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM,\n    MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,\n    MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,\n    MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,\n    MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,\n    MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384,\n    MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,\n    MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,\n    MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8,\n    MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,\n    MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,\n    MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,\n\n    MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,\n    MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM,\n    MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,\n    MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,\n    MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,\n    MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,\n    MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256,\n    MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,\n    MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,\n    MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8,\n    MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,\n    MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,\n    MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,\n\n    /* The ECJPAKE suite */\n    MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8,\n\n    /* All AES-256 suites */\n    MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384,\n    MBEDTLS_TLS_RSA_WITH_AES_256_CCM,\n    MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256,\n    MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA,\n    MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,\n    MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,\n    MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,\n    MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,\n    MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,\n    MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,\n    MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8,\n\n    /* All CAMELLIA-256 suites */\n    MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,\n    MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,\n    MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,\n    MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,\n    MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,\n    MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,\n    MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,\n\n    /* All ARIA-256 suites */\n    MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,\n    MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,\n    MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384,\n    MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,\n    MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,\n    MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384,\n\n    /* All AES-128 suites */\n    MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,\n    MBEDTLS_TLS_RSA_WITH_AES_128_CCM,\n    MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256,\n    MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,\n    MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,\n    MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,\n    MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,\n    MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,\n    MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,\n    MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,\n    MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8,\n\n    /* All CAMELLIA-128 suites */\n    MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,\n    MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,\n    MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,\n    MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,\n    MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,\n    MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,\n    MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,\n\n    /* All ARIA-128 suites */\n    MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,\n    MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,\n    MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256,\n    MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,\n    MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,\n    MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256,\n\n    /* The RSA PSK suites */\n    MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,\n    MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,\n    MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,\n    MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,\n    MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,\n    MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,\n    MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,\n    MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,\n\n    MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,\n    MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,\n    MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,\n    MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,\n    MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,\n    MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,\n    MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,\n\n    /* The PSK suites */\n    MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,\n    MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384,\n    MBEDTLS_TLS_PSK_WITH_AES_256_CCM,\n    MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384,\n    MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA,\n    MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,\n    MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,\n    MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8,\n    MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384,\n    MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384,\n\n    MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256,\n    MBEDTLS_TLS_PSK_WITH_AES_128_CCM,\n    MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256,\n    MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA,\n    MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,\n    MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,\n    MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8,\n    MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256,\n    MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256,\n\n    /* NULL suites */\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA,\n    MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA,\n    MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384,\n    MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256,\n    MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA,\n    MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384,\n    MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256,\n    MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA,\n\n    MBEDTLS_TLS_RSA_WITH_NULL_SHA256,\n    MBEDTLS_TLS_RSA_WITH_NULL_SHA,\n    MBEDTLS_TLS_RSA_WITH_NULL_MD5,\n    MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA,\n    MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA,\n    MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384,\n    MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256,\n    MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA,\n    MBEDTLS_TLS_PSK_WITH_NULL_SHA384,\n    MBEDTLS_TLS_PSK_WITH_NULL_SHA256,\n    MBEDTLS_TLS_PSK_WITH_NULL_SHA,\n\n#endif /* MBEDTLS_SSL_CIPHERSUITES */\n    0\n};\n\nstatic const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =\n{\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n#if defined(MBEDTLS_SSL_HAVE_AES)\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS1_3_AES_256_GCM_SHA384, \"TLS1-3-AES-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384,\n      MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS1_3_AES_128_GCM_SHA256, \"TLS1-3-AES-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256,\n      MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#if defined(MBEDTLS_SSL_HAVE_CCM) && defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS1_3_AES_128_CCM_SHA256, \"TLS1-3-AES-128-CCM-SHA256\",\n      MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256,\n      MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 },\n    { MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256, \"TLS1-3-AES-128-CCM-8-SHA256\",\n      MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256,\n      MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */\n      MBEDTLS_CIPHERSUITE_SHORT_TAG,\n      MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 },\n#endif /* MBEDTLS_MD_CAN_SHA256 && MBEDTLS_SSL_HAVE_CCM */\n#endif /* MBEDTLS_SSL_HAVE_AES */\n#if defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) && defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256,\n      \"TLS1-3-CHACHA20-POLY1305-SHA256\",\n      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,\n      MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 },\n#endif /* MBEDTLS_SSL_HAVE_CHACHAPOLY && MBEDTLS_MD_CAN_SHA256 */\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#if defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) && \\\n    defined(MBEDTLS_MD_CAN_SHA256) && \\\n    defined(MBEDTLS_SSL_PROTO_TLS1_2)\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,\n      \"TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256\",\n      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,\n      MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,\n      \"TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256\",\n      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,\n      MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)\n    { MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,\n      \"TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256\",\n      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,\n      MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)\n    { MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,\n      \"TLS-PSK-WITH-CHACHA20-POLY1305-SHA256\",\n      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,\n      MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)\n    { MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,\n      \"TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256\",\n      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,\n      MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)\n    { MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,\n      \"TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256\",\n      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,\n      MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)\n    { MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,\n      \"TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256\",\n      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,\n      MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#endif /* MBEDTLS_SSL_HAVE_CHACHAPOLY &&\n          MBEDTLS_MD_CAN_SHA256 &&\n          MBEDTLS_SSL_PROTO_TLS1_2 */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)\n#if defined(MBEDTLS_SSL_HAVE_AES)\n#if defined(MBEDTLS_MD_CAN_SHA1)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, \"TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, \"TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, \"TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, \"TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, \"TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \"TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#if defined(MBEDTLS_SSL_HAVE_CCM)\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, \"TLS-ECDHE-ECDSA-WITH-AES-256-CCM\",\n      MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, \"TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8\",\n      MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      MBEDTLS_CIPHERSUITE_SHORT_TAG,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, \"TLS-ECDHE-ECDSA-WITH-AES-128-CCM\",\n      MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, \"TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8\",\n      MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      MBEDTLS_CIPHERSUITE_SHORT_TAG,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CCM */\n#endif /* MBEDTLS_SSL_HAVE_AES */\n\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,\n      \"TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,\n      \"TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,\n      \"TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,\n      \"TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */\n\n#if defined(MBEDTLS_CIPHER_NULL_CIPHER)\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, \"TLS-ECDHE-ECDSA-WITH-NULL-SHA\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#endif /* MBEDTLS_CIPHER_NULL_CIPHER */\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)\n#if defined(MBEDTLS_SSL_HAVE_AES)\n#if defined(MBEDTLS_MD_CAN_SHA1)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, \"TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, \"TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, \"TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, \"TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, \"TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, \"TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_AES */\n\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,\n      \"TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,\n      \"TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,\n      \"TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,\n      \"TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */\n\n#if defined(MBEDTLS_CIPHER_NULL_CIPHER)\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, \"TLS-ECDHE-RSA-WITH-NULL-SHA\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#endif /* MBEDTLS_CIPHER_NULL_CIPHER */\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)\n#if defined(MBEDTLS_SSL_HAVE_AES)\n#if defined(MBEDTLS_MD_CAN_SHA384) && \\\n    defined(MBEDTLS_SSL_HAVE_GCM)\n    { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, \"TLS-DHE-RSA-WITH-AES-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 && MBEDTLS_SSL_HAVE_GCM */\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n    { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, \"TLS-DHE-RSA-WITH-AES-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n    { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, \"TLS-DHE-RSA-WITH-AES-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n\n    { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, \"TLS-DHE-RSA-WITH-AES-256-CBC-SHA256\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, \"TLS-DHE-RSA-WITH-AES-128-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n\n    { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, \"TLS-DHE-RSA-WITH-AES-256-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#if defined(MBEDTLS_SSL_HAVE_CCM)\n    { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, \"TLS-DHE-RSA-WITH-AES-256-CCM\",\n      MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, \"TLS-DHE-RSA-WITH-AES-256-CCM-8\",\n      MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      MBEDTLS_CIPHERSUITE_SHORT_TAG,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, \"TLS-DHE-RSA-WITH-AES-128-CCM\",\n      MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, \"TLS-DHE-RSA-WITH-AES-128-CCM-8\",\n      MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      MBEDTLS_CIPHERSUITE_SHORT_TAG,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CCM */\n#endif /* MBEDTLS_SSL_HAVE_AES */\n\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, \"TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n\n    { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, \"TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, \"TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA\",\n      MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n\n    { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, \"TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA\",\n      MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, \"TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, \"TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */\n\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)\n#if defined(MBEDTLS_SSL_HAVE_AES)\n#if defined(MBEDTLS_MD_CAN_SHA384) && \\\n    defined(MBEDTLS_SSL_HAVE_GCM)\n    { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, \"TLS-RSA-WITH-AES-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 && MBEDTLS_SSL_HAVE_GCM */\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n    { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, \"TLS-RSA-WITH-AES-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n    { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, \"TLS-RSA-WITH-AES-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n\n    { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, \"TLS-RSA-WITH-AES-256-CBC-SHA256\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA1)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n    { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, \"TLS-RSA-WITH-AES-128-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n\n    { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, \"TLS-RSA-WITH-AES-256-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#if defined(MBEDTLS_SSL_HAVE_CCM)\n    { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, \"TLS-RSA-WITH-AES-256-CCM\",\n      MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, \"TLS-RSA-WITH-AES-256-CCM-8\",\n      MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,\n      MBEDTLS_CIPHERSUITE_SHORT_TAG,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_RSA_WITH_AES_128_CCM, \"TLS-RSA-WITH-AES-128-CCM\",\n      MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, \"TLS-RSA-WITH-AES-128-CCM-8\",\n      MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,\n      MBEDTLS_CIPHERSUITE_SHORT_TAG,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CCM */\n#endif /* MBEDTLS_SSL_HAVE_AES */\n\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, \"TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n\n    { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, \"TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, \"TLS-RSA-WITH-CAMELLIA-128-CBC-SHA\",\n      MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n\n    { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, \"TLS-RSA-WITH-CAMELLIA-256-CBC-SHA\",\n      MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, \"TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, \"TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */\n\n#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)\n#if defined(MBEDTLS_SSL_HAVE_AES)\n#if defined(MBEDTLS_MD_CAN_SHA1)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n    { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, \"TLS-ECDH-RSA-WITH-AES-128-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, \"TLS-ECDH-RSA-WITH-AES-256-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n    { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, \"TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n    { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, \"TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n    { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, \"TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n    { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, \"TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_AES */\n\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,\n      \"TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,\n      \"TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,\n      \"TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,\n      \"TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */\n\n#if defined(MBEDTLS_CIPHER_NULL_CIPHER)\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, \"TLS-ECDH-RSA-WITH-NULL-SHA\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#endif /* MBEDTLS_CIPHER_NULL_CIPHER */\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)\n#if defined(MBEDTLS_SSL_HAVE_AES)\n#if defined(MBEDTLS_MD_CAN_SHA1)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n    { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, \"TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, \"TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n    { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, \"TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n    { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, \"TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n    { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, \"TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n    { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, \"TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_AES */\n\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,\n      \"TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,\n      \"TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,\n      \"TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,\n      \"TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */\n\n#if defined(MBEDTLS_CIPHER_NULL_CIPHER)\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, \"TLS-ECDH-ECDSA-WITH-NULL-SHA\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#endif /* MBEDTLS_CIPHER_NULL_CIPHER */\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)\n#if defined(MBEDTLS_SSL_HAVE_AES)\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, \"TLS-PSK-WITH-AES-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, \"TLS-PSK-WITH-AES-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, \"TLS-PSK-WITH-AES-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, \"TLS-PSK-WITH-AES-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, \"TLS-PSK-WITH-AES-128-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n\n    { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, \"TLS-PSK-WITH-AES-256-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#if defined(MBEDTLS_SSL_HAVE_CCM)\n    { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, \"TLS-PSK-WITH-AES-256-CCM\",\n      MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, \"TLS-PSK-WITH-AES-256-CCM-8\",\n      MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,\n      MBEDTLS_CIPHERSUITE_SHORT_TAG,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_PSK_WITH_AES_128_CCM, \"TLS-PSK-WITH-AES-128-CCM\",\n      MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, \"TLS-PSK-WITH-AES-128-CCM-8\",\n      MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,\n      MBEDTLS_CIPHERSUITE_SHORT_TAG,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CCM */\n#endif /* MBEDTLS_SSL_HAVE_AES */\n\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, \"TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, \"TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, \"TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, \"TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */\n\n#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)\n#if defined(MBEDTLS_SSL_HAVE_AES)\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, \"TLS-DHE-PSK-WITH-AES-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, \"TLS-DHE-PSK-WITH-AES-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, \"TLS-DHE-PSK-WITH-AES-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, \"TLS-DHE-PSK-WITH-AES-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, \"TLS-DHE-PSK-WITH-AES-128-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n\n    { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, \"TLS-DHE-PSK-WITH-AES-256-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#if defined(MBEDTLS_SSL_HAVE_CCM)\n    { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, \"TLS-DHE-PSK-WITH-AES-256-CCM\",\n      MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, \"TLS-DHE-PSK-WITH-AES-256-CCM-8\",\n      MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      MBEDTLS_CIPHERSUITE_SHORT_TAG,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, \"TLS-DHE-PSK-WITH-AES-128-CCM\",\n      MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n    { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, \"TLS-DHE-PSK-WITH-AES-128-CCM-8\",\n      MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      MBEDTLS_CIPHERSUITE_SHORT_TAG,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CCM */\n#endif /* MBEDTLS_SSL_HAVE_AES */\n\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, \"TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, \"TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, \"TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, \"TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */\n\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)\n#if defined(MBEDTLS_SSL_HAVE_AES)\n\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, \"TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, \"TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, \"TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n\n    { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, \"TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#endif /* MBEDTLS_SSL_HAVE_AES */\n\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,\n      \"TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,\n      \"TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */\n\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)\n#if defined(MBEDTLS_SSL_HAVE_AES)\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, \"TLS-RSA-PSK-WITH-AES-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, \"TLS-RSA-PSK-WITH-AES-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, \"TLS-RSA-PSK-WITH-AES-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, \"TLS-RSA-PSK-WITH-AES-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, \"TLS-RSA-PSK-WITH-AES-128-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n\n    { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, \"TLS-RSA-PSK-WITH-AES-256-CBC-SHA\",\n      MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n#endif /* MBEDTLS_SSL_HAVE_AES */\n\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, \"TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, \"TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_CBC */\n\n#if defined(MBEDTLS_SSL_HAVE_GCM)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, \"TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, \"TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_SSL_HAVE_GCM */\n#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */\n\n#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n#if defined(MBEDTLS_SSL_HAVE_AES)\n#if defined(MBEDTLS_SSL_HAVE_CCM)\n    { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, \"TLS-ECJPAKE-WITH-AES-128-CCM-8\",\n      MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE,\n      MBEDTLS_CIPHERSUITE_SHORT_TAG,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_SSL_HAVE_CCM */\n#endif /* MBEDTLS_SSL_HAVE_AES */\n#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_CIPHER_NULL_CIPHER)\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)\n#if defined(MBEDTLS_MD_CAN_MD5)\n    { MBEDTLS_TLS_RSA_WITH_NULL_MD5, \"TLS-RSA-WITH-NULL-MD5\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_RSA_WITH_NULL_SHA, \"TLS-RSA-WITH-NULL-SHA\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, \"TLS-RSA-WITH-NULL-SHA256\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_PSK_WITH_NULL_SHA, \"TLS-PSK-WITH-NULL-SHA\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, \"TLS-PSK-WITH-NULL-SHA256\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, \"TLS-PSK-WITH-NULL-SHA384\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, \"TLS-DHE-PSK-WITH-NULL-SHA\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, \"TLS-DHE-PSK-WITH-NULL-SHA256\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, \"TLS-DHE-PSK-WITH-NULL-SHA384\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, \"TLS-ECDHE-PSK-WITH-NULL-SHA\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, \"TLS-ECDHE-PSK-WITH-NULL-SHA256\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, \"TLS-ECDHE-PSK-WITH-NULL-SHA384\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)\n#if defined(MBEDTLS_MD_CAN_SHA1)\n    { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, \"TLS-RSA-PSK-WITH-NULL-SHA\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, \"TLS-RSA-PSK-WITH-NULL-SHA256\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, \"TLS-RSA-PSK-WITH-NULL-SHA384\",\n      MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      MBEDTLS_CIPHERSUITE_WEAK,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */\n#endif /* MBEDTLS_CIPHER_NULL_CIPHER */\n\n#if defined(MBEDTLS_SSL_HAVE_ARIA)\n\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)\n\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384,\n      \"TLS-RSA-WITH-ARIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384,\n      \"TLS-RSA-WITH-ARIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256,\n      \"TLS-RSA-WITH-ARIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256,\n      \"TLS-RSA-WITH-ARIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)\n\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,\n      \"TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,\n      \"TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,\n      \"TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,\n      \"TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)\n\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384,\n      \"TLS-PSK-WITH-ARIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384,\n      \"TLS-PSK-WITH-ARIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256,\n      \"TLS-PSK-WITH-ARIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256,\n      \"TLS-PSK-WITH-ARIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)\n\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,\n      \"TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,\n      \"TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,\n      \"TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,\n      \"TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)\n\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,\n      \"TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,\n      \"TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,\n      \"TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,\n      \"TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)\n\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,\n      \"TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,\n      \"TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)\n\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,\n      \"TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,\n      \"TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,\n      \"TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,\n      \"TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)\n\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,\n      \"TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,\n      \"TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,\n      \"TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,\n      \"TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)\n\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,\n      \"TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,\n      \"TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,\n      \"TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,\n      \"TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)\n\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,\n      \"TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA384))\n    { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,\n      \"TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384\",\n      MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,\n      \"TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n#if (defined(MBEDTLS_SSL_HAVE_CBC) && \\\n    defined(MBEDTLS_MD_CAN_SHA256))\n    { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,\n      \"TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256\",\n      MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,\n      0,\n      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },\n#endif\n\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */\n\n#endif /* MBEDTLS_SSL_HAVE_ARIA */\n\n\n    { 0, \"\",\n      MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE,\n      0, 0, 0 }\n};\n\n#if defined(MBEDTLS_SSL_CIPHERSUITES)\nconst int *mbedtls_ssl_list_ciphersuites(void)\n{\n    return ciphersuite_preference;\n}\n#else\n#define MAX_CIPHERSUITES    sizeof(ciphersuite_definitions) /         \\\n    sizeof(ciphersuite_definitions[0])\nstatic int supported_ciphersuites[MAX_CIPHERSUITES];\nstatic int supported_init = 0;\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ciphersuite_is_removed(const mbedtls_ssl_ciphersuite_t *cs_info)\n{\n    (void) cs_info;\n\n    return 0;\n}\n\nconst int *mbedtls_ssl_list_ciphersuites(void)\n{\n    /*\n     * On initial call filter out all ciphersuites not supported by current\n     * build based on presence in the ciphersuite_definitions.\n     */\n    if (supported_init == 0) {\n        const int *p;\n        int *q;\n\n        for (p = ciphersuite_preference, q = supported_ciphersuites;\n             *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1;\n             p++) {\n            const mbedtls_ssl_ciphersuite_t *cs_info;\n            if ((cs_info = mbedtls_ssl_ciphersuite_from_id(*p)) != NULL &&\n                !ciphersuite_is_removed(cs_info)) {\n                *(q++) = *p;\n            }\n        }\n        *q = 0;\n\n        supported_init = 1;\n    }\n\n    return supported_ciphersuites;\n}\n#endif /* MBEDTLS_SSL_CIPHERSUITES */\n\nconst mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string(\n    const char *ciphersuite_name)\n{\n    const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions;\n\n    if (NULL == ciphersuite_name) {\n        return NULL;\n    }\n\n    while (cur->id != 0) {\n        if (0 == strcmp(cur->name, ciphersuite_name)) {\n            return cur;\n        }\n\n        cur++;\n    }\n\n    return NULL;\n}\n\nconst mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id(int ciphersuite)\n{\n    const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions;\n\n    while (cur->id != 0) {\n        if (cur->id == ciphersuite) {\n            return cur;\n        }\n\n        cur++;\n    }\n\n    return NULL;\n}\n\nconst char *mbedtls_ssl_get_ciphersuite_name(const int ciphersuite_id)\n{\n    const mbedtls_ssl_ciphersuite_t *cur;\n\n    cur = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);\n\n    if (cur == NULL) {\n        return \"unknown\";\n    }\n\n    return cur->name;\n}\n\nint mbedtls_ssl_get_ciphersuite_id(const char *ciphersuite_name)\n{\n    const mbedtls_ssl_ciphersuite_t *cur;\n\n    cur = mbedtls_ssl_ciphersuite_from_string(ciphersuite_name);\n\n    if (cur == NULL) {\n        return 0;\n    }\n\n    return cur->id;\n}\n\nsize_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(const mbedtls_ssl_ciphersuite_t *info)\n{\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_type_t key_type;\n    psa_algorithm_t alg;\n    size_t key_bits;\n\n    status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) info->cipher,\n                                       info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16,\n                                       &alg, &key_type, &key_bits);\n\n    if (status != PSA_SUCCESS) {\n        return 0;\n    }\n\n    return key_bits;\n#else\n    const mbedtls_cipher_info_t * const cipher_info =\n        mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) info->cipher);\n\n    return mbedtls_cipher_info_get_key_bitlen(cipher_info);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n}\n\n#if defined(MBEDTLS_PK_C)\nmbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg(const mbedtls_ssl_ciphersuite_t *info)\n{\n    switch (info->key_exchange) {\n        case MBEDTLS_KEY_EXCHANGE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_RSA_PSK:\n            return MBEDTLS_PK_RSA;\n\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:\n            return MBEDTLS_PK_ECDSA;\n\n        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:\n            return MBEDTLS_PK_ECKEY;\n\n        default:\n            return MBEDTLS_PK_NONE;\n    }\n}\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\npsa_algorithm_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(const mbedtls_ssl_ciphersuite_t *info)\n{\n    switch (info->key_exchange) {\n        case MBEDTLS_KEY_EXCHANGE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_RSA_PSK:\n            return PSA_ALG_RSA_PKCS1V15_CRYPT;\n        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:\n            return PSA_ALG_RSA_PKCS1V15_SIGN(\n                mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac));\n\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:\n            return PSA_ALG_ECDSA(mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac));\n\n        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:\n            return PSA_ALG_ECDH;\n\n        default:\n            return PSA_ALG_NONE;\n    }\n}\n\npsa_key_usage_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(const mbedtls_ssl_ciphersuite_t *info)\n{\n    switch (info->key_exchange) {\n        case MBEDTLS_KEY_EXCHANGE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_RSA_PSK:\n            return PSA_KEY_USAGE_DECRYPT;\n        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:\n            return PSA_KEY_USAGE_SIGN_HASH;\n\n        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:\n            return PSA_KEY_USAGE_DERIVE;\n\n        default:\n            return 0;\n    }\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\nmbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersuite_t *info)\n{\n    switch (info->key_exchange) {\n        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:\n            return MBEDTLS_PK_RSA;\n\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:\n            return MBEDTLS_PK_ECDSA;\n\n        default:\n            return MBEDTLS_PK_NONE;\n    }\n}\n\n#endif /* MBEDTLS_PK_C */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\nint mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info)\n{\n    switch (info->key_exchange) {\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:\n        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:\n        case MBEDTLS_KEY_EXCHANGE_ECJPAKE:\n            return 1;\n\n        default:\n            return 0;\n    }\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED ||\n        * MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||\n        * MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)\nint mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info)\n{\n    switch (info->key_exchange) {\n        case MBEDTLS_KEY_EXCHANGE_PSK:\n        case MBEDTLS_KEY_EXCHANGE_RSA_PSK:\n        case MBEDTLS_KEY_EXCHANGE_DHE_PSK:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:\n            return 1;\n\n        default:\n            return 0;\n    }\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */\n\n#endif /* MBEDTLS_SSL_TLS_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_ciphersuites_internal.h",
    "content": "/**\n * \\file ssl_ciphersuites_internal.h\n *\n * \\brief Internal part of the public \"ssl_ciphersuites.h\".\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H\n#define MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H\n\n#include \"mbedtls/pk.h\"\n\n#if defined(MBEDTLS_PK_C)\nmbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg(const mbedtls_ssl_ciphersuite_t *info);\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\npsa_algorithm_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(const mbedtls_ssl_ciphersuite_t *info);\npsa_key_usage_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(const mbedtls_ssl_ciphersuite_t *info);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\nmbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersuite_t *info);\n#endif /* MBEDTLS_PK_C */\n\nint mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info);\nint mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info);\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED)\nstatic inline int mbedtls_ssl_ciphersuite_has_pfs(const mbedtls_ssl_ciphersuite_t *info)\n{\n    switch (info->MBEDTLS_PRIVATE(key_exchange)) {\n        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_DHE_PSK:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:\n        case MBEDTLS_KEY_EXCHANGE_ECJPAKE:\n            return 1;\n\n        default:\n            return 0;\n    }\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED)\nstatic inline int mbedtls_ssl_ciphersuite_no_pfs(const mbedtls_ssl_ciphersuite_t *info)\n{\n    switch (info->MBEDTLS_PRIVATE(key_exchange)) {\n        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:\n        case MBEDTLS_KEY_EXCHANGE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_PSK:\n        case MBEDTLS_KEY_EXCHANGE_RSA_PSK:\n            return 1;\n\n        default:\n            return 0;\n    }\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED)\nstatic inline int mbedtls_ssl_ciphersuite_uses_ecdh(const mbedtls_ssl_ciphersuite_t *info)\n{\n    switch (info->MBEDTLS_PRIVATE(key_exchange)) {\n        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:\n            return 1;\n\n        default:\n            return 0;\n    }\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */\n\nstatic inline int mbedtls_ssl_ciphersuite_cert_req_allowed(const mbedtls_ssl_ciphersuite_t *info)\n{\n    switch (info->MBEDTLS_PRIVATE(key_exchange)) {\n        case MBEDTLS_KEY_EXCHANGE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:\n            return 1;\n\n        default:\n            return 0;\n    }\n}\n\nstatic inline int mbedtls_ssl_ciphersuite_uses_srv_cert(const mbedtls_ssl_ciphersuite_t *info)\n{\n    switch (info->MBEDTLS_PRIVATE(key_exchange)) {\n        case MBEDTLS_KEY_EXCHANGE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_RSA_PSK:\n        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:\n            return 1;\n\n        default:\n            return 0;\n    }\n}\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED)\nstatic inline int mbedtls_ssl_ciphersuite_uses_dhe(const mbedtls_ssl_ciphersuite_t *info)\n{\n    switch (info->MBEDTLS_PRIVATE(key_exchange)) {\n        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_DHE_PSK:\n            return 1;\n\n        default:\n            return 0;\n    }\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)\nstatic inline int mbedtls_ssl_ciphersuite_uses_ecdhe(const mbedtls_ssl_ciphersuite_t *info)\n{\n    switch (info->MBEDTLS_PRIVATE(key_exchange)) {\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:\n            return 1;\n\n        default:\n            return 0;\n    }\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)\nstatic inline int mbedtls_ssl_ciphersuite_uses_server_signature(\n    const mbedtls_ssl_ciphersuite_t *info)\n{\n    switch (info->MBEDTLS_PRIVATE(key_exchange)) {\n        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:\n        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:\n            return 1;\n\n        default:\n            return 0;\n    }\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */\n\n#endif /* MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_client.c",
    "content": "/*\n *  TLS 1.2 and 1.3 client-side functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_CLI_C)\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) || defined(MBEDTLS_SSL_PROTO_TLS1_2)\n\n#include <string.h>\n\n#include \"debug_internal.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/platform.h\"\n\n#include \"ssl_client.h\"\n#include \"ssl_misc.h\"\n#include \"ssl_tls13_keys.h\"\n#include \"ssl_debug_helpers.h\"\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_hostname_ext(mbedtls_ssl_context *ssl,\n                                  unsigned char *buf,\n                                  const unsigned char *end,\n                                  size_t *olen)\n{\n    unsigned char *p = buf;\n    const char *hostname = mbedtls_ssl_get_hostname_pointer(ssl);\n    size_t hostname_len;\n\n    *olen = 0;\n\n    if (hostname == NULL) {\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"client hello, adding server name extension: %s\",\n                           hostname));\n\n    hostname_len = strlen(hostname);\n\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, hostname_len + 9);\n\n    /*\n     * Sect. 3, RFC 6066 (TLS Extensions Definitions)\n     *\n     * In order to provide any of the server names, clients MAY include an\n     * extension of type \"server_name\" in the (extended) client hello. The\n     * \"extension_data\" field of this extension SHALL contain\n     * \"ServerNameList\" where:\n     *\n     * struct {\n     *     NameType name_type;\n     *     select (name_type) {\n     *         case host_name: HostName;\n     *     } name;\n     * } ServerName;\n     *\n     * enum {\n     *     host_name(0), (255)\n     * } NameType;\n     *\n     * opaque HostName<1..2^16-1>;\n     *\n     * struct {\n     *     ServerName server_name_list<1..2^16-1>\n     * } ServerNameList;\n     *\n     */\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SERVERNAME, p, 0);\n    p += 2;\n\n    MBEDTLS_PUT_UINT16_BE(hostname_len + 5, p, 0);\n    p += 2;\n\n    MBEDTLS_PUT_UINT16_BE(hostname_len + 3, p, 0);\n    p += 2;\n\n    *p++ = MBEDTLS_BYTE_0(MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME);\n\n    MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0);\n    p += 2;\n\n    memcpy(p, hostname, hostname_len);\n\n    *olen = hostname_len + 9;\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_SERVERNAME);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n    return 0;\n}\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n#if defined(MBEDTLS_SSL_ALPN)\n/*\n * ssl_write_alpn_ext()\n *\n * Structure of the application_layer_protocol_negotiation extension in\n * ClientHello:\n *\n * opaque ProtocolName<1..2^8-1>;\n *\n * struct {\n *     ProtocolName protocol_name_list<2..2^16-1>\n * } ProtocolNameList;\n *\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_alpn_ext(mbedtls_ssl_context *ssl,\n                              unsigned char *buf,\n                              const unsigned char *end,\n                              size_t *out_len)\n{\n    unsigned char *p = buf;\n\n    *out_len = 0;\n\n    if (ssl->conf->alpn_list == NULL) {\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"client hello, adding alpn extension\"));\n\n\n    /* Check we have enough space for the extension type (2 bytes), the\n     * extension length (2 bytes) and the protocol_name_list length (2 bytes).\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ALPN, p, 0);\n    /* Skip writing extension and list length for now */\n    p += 6;\n\n    /*\n     * opaque ProtocolName<1..2^8-1>;\n     *\n     * struct {\n     *     ProtocolName protocol_name_list<2..2^16-1>\n     * } ProtocolNameList;\n     */\n    for (const char **cur = ssl->conf->alpn_list; *cur != NULL; cur++) {\n        /*\n         * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of\n         * protocol names is less than 255.\n         */\n        size_t protocol_name_len = strlen(*cur);\n\n        MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1 + protocol_name_len);\n        *p++ = (unsigned char) protocol_name_len;\n        memcpy(p, *cur, protocol_name_len);\n        p += protocol_name_len;\n    }\n\n    *out_len = (size_t) (p - buf);\n\n    /* List length = *out_len - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */\n    MBEDTLS_PUT_UINT16_BE(*out_len - 6, buf, 4);\n\n    /* Extension length = *out_len - 2 (ext_type) - 2 (ext_len) */\n    MBEDTLS_PUT_UINT16_BE(*out_len - 4, buf, 2);\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_ALPN);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n    return 0;\n}\n#endif /* MBEDTLS_SSL_ALPN */\n\n#if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) || \\\n    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)\n/*\n * Function for writing a supported groups (TLS 1.3) or supported elliptic\n * curves (TLS 1.2) extension.\n *\n * The \"extension_data\" field of a supported groups extension contains a\n * \"NamedGroupList\" value (TLS 1.3 RFC8446):\n *      enum {\n *          secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),\n *          x25519(0x001D), x448(0x001E),\n *          ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),\n *          ffdhe6144(0x0103), ffdhe8192(0x0104),\n *          ffdhe_private_use(0x01FC..0x01FF),\n *          ecdhe_private_use(0xFE00..0xFEFF),\n *          (0xFFFF)\n *      } NamedGroup;\n *      struct {\n *          NamedGroup named_group_list<2..2^16-1>;\n *      } NamedGroupList;\n *\n * The \"extension_data\" field of a supported elliptic curves extension contains\n * a \"NamedCurveList\" value (TLS 1.2 RFC 8422):\n * enum {\n *      deprecated(1..22),\n *      secp256r1 (23), secp384r1 (24), secp521r1 (25),\n *      x25519(29), x448(30),\n *      reserved (0xFE00..0xFEFF),\n *      deprecated(0xFF01..0xFF02),\n *      (0xFFFF)\n *  } NamedCurve;\n * struct {\n *      NamedCurve named_curve_list<2..2^16-1>\n *  } NamedCurveList;\n *\n * The TLS 1.3 supported groups extension was defined to be a compatible\n * generalization of the TLS 1.2 supported elliptic curves extension. They both\n * share the same extension identifier.\n *\n */\n#define SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG 1\n#define SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG 2\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_supported_groups_ext(mbedtls_ssl_context *ssl,\n                                          unsigned char *buf,\n                                          const unsigned char *end,\n                                          int flags,\n                                          size_t *out_len)\n{\n    unsigned char *p = buf;\n    unsigned char *named_group_list; /* Start of named_group_list */\n    size_t named_group_list_len;     /* Length of named_group_list */\n    const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);\n\n    *out_len = 0;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"client hello, adding supported_groups extension\"));\n\n    /* Check if we have space for header and length fields:\n     * - extension_type            (2 bytes)\n     * - extension_data_length     (2 bytes)\n     * - named_group_list_length   (2 bytes)\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);\n    p += 6;\n\n    named_group_list = p;\n\n    if (group_list == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_CONFIG;\n    }\n\n    for (; *group_list != 0; group_list++) {\n        int propose_group = 0;\n\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"got supported group(%04x)\", *group_list));\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)\n        if (flags & SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG) {\n#if defined(PSA_WANT_ALG_ECDH)\n            if (mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list) &&\n                (mbedtls_ssl_get_ecp_group_id_from_tls_id(*group_list) !=\n                 MBEDTLS_ECP_DP_NONE)) {\n                propose_group = 1;\n            }\n#endif\n#if defined(PSA_WANT_ALG_FFDH)\n            if (mbedtls_ssl_tls13_named_group_is_ffdh(*group_list)) {\n                propose_group = 1;\n            }\n#endif\n        }\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */\n\n#if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC)\n        if ((flags & SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG) &&\n            mbedtls_ssl_tls12_named_group_is_ecdhe(*group_list) &&\n            (mbedtls_ssl_get_ecp_group_id_from_tls_id(*group_list) !=\n             MBEDTLS_ECP_DP_NONE)) {\n            propose_group = 1;\n        }\n#endif /* MBEDTLS_SSL_TLS1_2_SOME_ECC */\n\n        if (propose_group) {\n            MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);\n            MBEDTLS_PUT_UINT16_BE(*group_list, p, 0);\n            p += 2;\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"NamedGroup: %s ( %x )\",\n                                      mbedtls_ssl_named_group_to_str(*group_list),\n                                      *group_list));\n        }\n    }\n\n    /* Length of named_group_list */\n    named_group_list_len = (size_t) (p - named_group_list);\n    if (named_group_list_len == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"No group available.\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    /* Write extension_type */\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_GROUPS, buf, 0);\n    /* Write extension_data_length */\n    MBEDTLS_PUT_UINT16_BE(named_group_list_len + 2, buf, 2);\n    /* Write length of named_group_list */\n    MBEDTLS_PUT_UINT16_BE(named_group_list_len, buf, 4);\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"Supported groups extension\",\n                          buf + 4, named_group_list_len + 2);\n\n    *out_len = (size_t) (p - buf);\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(\n        ssl, MBEDTLS_TLS_EXT_SUPPORTED_GROUPS);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_TLS1_2_SOME_ECC ||\n          MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_client_hello_cipher_suites(\n    mbedtls_ssl_context *ssl,\n    unsigned char *buf,\n    unsigned char *end,\n    int *tls12_uses_ec,\n    size_t *out_len)\n{\n    unsigned char *p = buf;\n    const int *ciphersuite_list;\n    unsigned char *cipher_suites; /* Start of the cipher_suites list */\n    size_t cipher_suites_len;\n\n    *tls12_uses_ec = 0;\n    *out_len = 0;\n\n    /*\n     * Ciphersuite list\n     *\n     * This is a list of the symmetric cipher options supported by\n     * the client, specifically the record protection algorithm\n     * ( including secret key length ) and a hash to be used with\n     * HKDF, in descending order of client preference.\n     */\n    ciphersuite_list = ssl->conf->ciphersuite_list;\n\n    /* Check there is space for the cipher suite list length (2 bytes). */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);\n    p += 2;\n\n    /* Write cipher_suites\n     * CipherSuite cipher_suites<2..2^16-2>;\n     */\n    cipher_suites = p;\n    for (size_t i = 0; ciphersuite_list[i] != 0; i++) {\n        int cipher_suite = ciphersuite_list[i];\n        const mbedtls_ssl_ciphersuite_t *ciphersuite_info;\n\n        ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite);\n\n        if (mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info,\n                                             ssl->handshake->min_tls_version,\n                                             ssl->tls_version) != 0) {\n            continue;\n        }\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \\\n        (defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \\\n        defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \\\n        defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED))\n        *tls12_uses_ec |= mbedtls_ssl_ciphersuite_uses_ec(ciphersuite_info);\n#endif\n\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"client hello, add ciphersuite: %04x, %s\",\n                                  (unsigned int) cipher_suite,\n                                  ciphersuite_info->name));\n\n        /* Check there is space for the cipher suite identifier (2 bytes). */\n        MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);\n        MBEDTLS_PUT_UINT16_BE(cipher_suite, p, 0);\n        p += 2;\n    }\n\n    /*\n     * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV\n     */\n    int renegotiating = 0;\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    renegotiating = (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE);\n#endif\n    if (!renegotiating) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"adding EMPTY_RENEGOTIATION_INFO_SCSV\"));\n        MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);\n        MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO, p, 0);\n        p += 2;\n    }\n\n    /* Write the cipher_suites length in number of bytes */\n    cipher_suites_len = (size_t) (p - cipher_suites);\n    MBEDTLS_PUT_UINT16_BE(cipher_suites_len, buf, 0);\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"client hello, got %\" MBEDTLS_PRINTF_SIZET \" cipher suites\",\n                           cipher_suites_len/2));\n\n    /* Output the total length of cipher_suites field. */\n    *out_len = (size_t) (p - buf);\n\n    return 0;\n}\n\n/*\n * Structure of the TLS 1.3 ClientHello message:\n *\n *    struct {\n *        ProtocolVersion legacy_version = 0x0303;    // TLS v1.2\n *        Random random;\n *        opaque legacy_session_id<0..32>;\n *        CipherSuite cipher_suites<2..2^16-2>;\n *        opaque legacy_compression_methods<1..2^8-1>;\n *        Extension extensions<8..2^16-1>;\n *    } ClientHello;\n *\n * Structure of the (D)TLS 1.2 ClientHello message:\n *\n * struct {\n *     ProtocolVersion client_version;\n *     Random random;\n *     SessionID session_id;\n *     opaque cookie<0..2^8-1>; // DTLS 1.2 ONLY\n *     CipherSuite cipher_suites<2..2^16-2>;\n *     CompressionMethod compression_methods<1..2^8-1>;\n *     select (extensions_present) {\n *         case false:\n *             struct {};\n *         case true:\n *             Extension extensions<0..2^16-1>;\n *     };\n * } ClientHello;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_client_hello_body(mbedtls_ssl_context *ssl,\n                                       unsigned char *buf,\n                                       unsigned char *end,\n                                       size_t *out_len,\n                                       size_t *binders_len)\n{\n    int ret;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n    unsigned char *p = buf;\n    unsigned char *p_extensions_len; /* Pointer to extensions length */\n    size_t output_len;               /* Length of buffer used by function */\n    size_t extensions_len;           /* Length of the list of extensions*/\n    int tls12_uses_ec = 0;\n\n    *out_len = 0;\n    *binders_len = 0;\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    unsigned char propose_tls12 =\n        (handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2)\n        &&\n        (MBEDTLS_SSL_VERSION_TLS1_2 <= ssl->tls_version);\n#endif\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    unsigned char propose_tls13 =\n        (handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3)\n        &&\n        (MBEDTLS_SSL_VERSION_TLS1_3 <= ssl->tls_version);\n#endif\n\n    /*\n     * Write client_version (TLS 1.2) or legacy_version (TLS 1.3)\n     *\n     * In all cases this is the TLS 1.2 version.\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);\n    mbedtls_ssl_write_version(p, ssl->conf->transport,\n                              MBEDTLS_SSL_VERSION_TLS1_2);\n    p += 2;\n\n    /* ...\n     * Random random;\n     * ...\n     *\n     * The random bytes have been prepared by ssl_prepare_client_hello() into\n     * the handshake->randbytes buffer and are copied here into the output\n     * buffer.\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, MBEDTLS_CLIENT_HELLO_RANDOM_LEN);\n    memcpy(p, handshake->randbytes, MBEDTLS_CLIENT_HELLO_RANDOM_LEN);\n    MBEDTLS_SSL_DEBUG_BUF(3, \"client hello, random bytes\",\n                          p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN);\n    p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN;\n\n    /* TLS 1.2:\n     * ...\n     * SessionID session_id;\n     * ...\n     * with\n     * opaque SessionID<0..32>;\n     *\n     * TLS 1.3:\n     * ...\n     * opaque legacy_session_id<0..32>;\n     * ...\n     *\n     * The (legacy) session identifier bytes have been prepared by\n     * ssl_prepare_client_hello() into the ssl->session_negotiate->id buffer\n     * and are copied here into the output buffer.\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, ssl->session_negotiate->id_len + 1);\n    *p++ = (unsigned char) ssl->session_negotiate->id_len;\n    memcpy(p, ssl->session_negotiate->id, ssl->session_negotiate->id_len);\n    p += ssl->session_negotiate->id_len;\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"session id\", ssl->session_negotiate->id,\n                          ssl->session_negotiate->id_len);\n\n    /* DTLS 1.2 ONLY\n     * ...\n     * opaque cookie<0..2^8-1>;\n     * ...\n     */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n#if !defined(MBEDTLS_SSL_PROTO_TLS1_3)\n        uint8_t cookie_len = 0;\n#else\n        uint16_t cookie_len = 0;\n#endif /* !MBEDTLS_SSL_PROTO_TLS1_3 */\n\n        if (handshake->cookie != NULL) {\n            MBEDTLS_SSL_DEBUG_BUF(3, \"client hello, cookie\",\n                                  handshake->cookie,\n                                  handshake->cookie_len);\n            cookie_len = handshake->cookie_len;\n        }\n\n        MBEDTLS_SSL_CHK_BUF_PTR(p, end, cookie_len + 1);\n        *p++ = (unsigned char) cookie_len;\n        if (cookie_len > 0) {\n            memcpy(p, handshake->cookie, cookie_len);\n            p += cookie_len;\n        }\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_DTLS */\n\n    /* Write cipher_suites */\n    ret = ssl_write_client_hello_cipher_suites(ssl, p, end,\n                                               &tls12_uses_ec,\n                                               &output_len);\n    if (ret != 0) {\n        return ret;\n    }\n    p += output_len;\n\n    /* Write legacy_compression_methods (TLS 1.3) or\n     * compression_methods (TLS 1.2)\n     *\n     * For every TLS 1.3 ClientHello, this vector MUST contain exactly\n     * one byte set to zero, which corresponds to the 'null' compression\n     * method in prior versions of TLS.\n     *\n     * For TLS 1.2 ClientHello, for security reasons we do not support\n     * compression anymore, thus also just the 'null' compression method.\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);\n    *p++ = 1;\n    *p++ = MBEDTLS_SSL_COMPRESS_NULL;\n\n    /* Write extensions */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    /* Keeping track of the included extensions */\n    handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE;\n#endif\n\n    /* First write extensions, then the total length */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);\n    p_extensions_len = p;\n    p += 2;\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    /* Write server name extension */\n    ret = ssl_write_hostname_ext(ssl, p, end, &output_len);\n    if (ret != 0) {\n        return ret;\n    }\n    p += output_len;\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n#if defined(MBEDTLS_SSL_ALPN)\n    ret = ssl_write_alpn_ext(ssl, p, end, &output_len);\n    if (ret != 0) {\n        return ret;\n    }\n    p += output_len;\n#endif /* MBEDTLS_SSL_ALPN */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    if (propose_tls13) {\n        ret = mbedtls_ssl_tls13_write_client_hello_exts(ssl, p, end,\n                                                        &output_len);\n        if (ret != 0) {\n            return ret;\n        }\n        p += output_len;\n    }\n#endif\n\n#if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) || \\\n    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)\n    {\n        int ssl_write_supported_groups_ext_flags = 0;\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)\n        if (propose_tls13 && mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) {\n            ssl_write_supported_groups_ext_flags |=\n                SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG;\n        }\n#endif\n#if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC)\n        if (propose_tls12 && tls12_uses_ec) {\n            ssl_write_supported_groups_ext_flags |=\n                SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG;\n        }\n#endif\n        if (ssl_write_supported_groups_ext_flags != 0) {\n            ret = ssl_write_supported_groups_ext(ssl, p, end,\n                                                 ssl_write_supported_groups_ext_flags,\n                                                 &output_len);\n            if (ret != 0) {\n                return ret;\n            }\n            p += output_len;\n        }\n    }\n#endif /* MBEDTLS_SSL_TLS1_2_SOME_ECC ||\n          MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n    int write_sig_alg_ext = 0;\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    write_sig_alg_ext = write_sig_alg_ext ||\n                        (propose_tls13 && mbedtls_ssl_conf_tls13_is_ephemeral_enabled(ssl));\n#endif\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    write_sig_alg_ext = write_sig_alg_ext || propose_tls12;\n#endif\n\n    if (write_sig_alg_ext) {\n        ret = mbedtls_ssl_write_sig_alg_ext(ssl, p, end, &output_len);\n        if (ret != 0) {\n            return ret;\n        }\n        p += output_len;\n    }\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    if (propose_tls12) {\n        ret = mbedtls_ssl_tls12_write_client_hello_exts(ssl, p, end,\n                                                        tls12_uses_ec,\n                                                        &output_len);\n        if (ret != 0) {\n            return ret;\n        }\n        p += output_len;\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n    /* The \"pre_shared_key\" extension (RFC 8446 Section 4.2.11)\n     * MUST be the last extension in the ClientHello.\n     */\n    if (propose_tls13 && mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl)) {\n        ret = mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext(\n            ssl, p, end, &output_len, binders_len);\n        if (ret != 0) {\n            return ret;\n        }\n        p += output_len;\n    }\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */\n\n    /* Write the length of the list of extensions. */\n    extensions_len = (size_t) (p - p_extensions_len) - 2;\n\n    if (extensions_len == 0) {\n        p = p_extensions_len;\n    } else {\n        MBEDTLS_PUT_UINT16_BE(extensions_len, p_extensions_len, 0);\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"client hello, total extension length: %\" \\\n                                  MBEDTLS_PRINTF_SIZET, extensions_len));\n        MBEDTLS_SSL_DEBUG_BUF(3, \"client hello extensions\",\n                              p_extensions_len, extensions_len);\n    }\n\n    *out_len = (size_t) (p - buf);\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_generate_random(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *randbytes = ssl->handshake->randbytes;\n    size_t gmt_unix_time_len = 0;\n\n    /*\n     * Generate the random bytes\n     *\n     * TLS 1.2 case:\n     * struct {\n     *     uint32 gmt_unix_time;\n     *     opaque random_bytes[28];\n     * } Random;\n     *\n     * TLS 1.3 case:\n     * opaque Random[32];\n     */\n    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {\n#if defined(MBEDTLS_HAVE_TIME)\n        mbedtls_time_t gmt_unix_time = mbedtls_time(NULL);\n        MBEDTLS_PUT_UINT32_BE(gmt_unix_time, randbytes, 0);\n        gmt_unix_time_len = 4;\n\n        MBEDTLS_SSL_DEBUG_MSG(3,\n                              (\"client hello, current time: %\" MBEDTLS_PRINTF_LONGLONG,\n                               (long long) gmt_unix_time));\n#endif /* MBEDTLS_HAVE_TIME */\n    }\n\n    ret = ssl->conf->f_rng(ssl->conf->p_rng,\n                           randbytes + gmt_unix_time_len,\n                           MBEDTLS_CLIENT_HELLO_RANDOM_LEN - gmt_unix_time_len);\n    return ret;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_prepare_client_hello(mbedtls_ssl_context *ssl)\n{\n    int ret;\n    size_t session_id_len;\n    mbedtls_ssl_session *session_negotiate = ssl->session_negotiate;\n\n    if (session_negotiate == NULL) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \\\n    defined(MBEDTLS_SSL_SESSION_TICKETS) && \\\n    defined(MBEDTLS_HAVE_TIME)\n\n    /* Check if a tls13 ticket has been configured. */\n    if (ssl->handshake->resume != 0 &&\n        session_negotiate->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 &&\n        session_negotiate->ticket != NULL) {\n        mbedtls_ms_time_t now = mbedtls_ms_time();\n        mbedtls_ms_time_t age = now - session_negotiate->ticket_reception_time;\n        if (age < 0 ||\n            age > (mbedtls_ms_time_t) session_negotiate->ticket_lifetime * 1000) {\n            /* Without valid ticket, disable session resumption.*/\n            MBEDTLS_SSL_DEBUG_MSG(\n                3, (\"Ticket expired, disable session resumption\"));\n            ssl->handshake->resume = 0;\n        }\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 &&\n          MBEDTLS_SSL_SESSION_TICKETS &&\n          MBEDTLS_HAVE_TIME */\n\n    /* Bet on the highest configured version if we are not in a TLS 1.2\n     * renegotiation or session resumption.\n     */\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {\n        ssl->handshake->min_tls_version = ssl->tls_version;\n    } else\n#endif\n    {\n        if (ssl->handshake->resume) {\n            ssl->tls_version = session_negotiate->tls_version;\n            ssl->handshake->min_tls_version = ssl->tls_version;\n        } else {\n            ssl->handshake->min_tls_version = ssl->conf->min_tls_version;\n        }\n    }\n\n    /*\n     * Generate the random bytes, except when responding to a verify request\n     * where we MUST reuse the previously generated random bytes\n     * (RFC 6347 4.2.1).\n     */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||\n        (ssl->handshake->cookie == NULL))\n#endif\n    {\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n        if (!ssl->handshake->hello_retry_request_flag)\n#endif\n        {\n            ret = ssl_generate_random(ssl);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"Random bytes generation failed\", ret);\n                return ret;\n            }\n        }\n    }\n\n    /*\n     * Prepare session identifier. At that point, the length of the session\n     * identifier in the SSL context `ssl->session_negotiate->id_len` is equal\n     * to zero, except in the case of a TLS 1.2 session renegotiation or\n     * session resumption.\n     */\n    session_id_len = session_negotiate->id_len;\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {\n        if (session_id_len < 16 || session_id_len > 32 ||\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n            ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ||\n#endif\n            ssl->handshake->resume == 0) {\n            session_id_len = 0;\n        }\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n        /*\n         * RFC 5077 section 3.4: \"When presenting a ticket, the client MAY\n         * generate and include a Session ID in the TLS ClientHello.\"\n         */\n        int renegotiating = 0;\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n        if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {\n            renegotiating = 1;\n        }\n#endif\n        if (!renegotiating) {\n            if ((session_negotiate->ticket != NULL) &&\n                (session_negotiate->ticket_len != 0)) {\n                session_id_len = 32;\n            }\n        }\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)\n    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {\n        /*\n         * Create a legacy session identifier for the purpose of middlebox\n         * compatibility only if one has not been created already, which is\n         * the case if we are here for the TLS 1.3 second ClientHello.\n         *\n         * Versions of TLS before TLS 1.3 supported a \"session resumption\"\n         * feature which has been merged with pre-shared keys in TLS 1.3\n         * version. A client which has a cached session ID set by a pre-TLS 1.3\n         * server SHOULD set this field to that value. In compatibility mode,\n         * this field MUST be non-empty, so a client not offering a pre-TLS 1.3\n         * session MUST generate a new 32-byte value. This value need not be\n         * random but SHOULD be unpredictable to avoid implementations fixating\n         * on a specific value (also known as ossification). Otherwise, it MUST\n         * be set as a zero-length vector ( i.e., a zero-valued single byte\n         * length field ).\n         */\n        session_id_len = 32;\n    }\n#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */\n\n    if (session_id_len != session_negotiate->id_len) {\n        session_negotiate->id_len = session_id_len;\n        if (session_id_len > 0) {\n            ret = ssl->conf->f_rng(ssl->conf->p_rng,\n                                   session_negotiate->id,\n                                   session_id_len);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"creating session id failed\", ret);\n                return ret;\n            }\n        }\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \\\n    defined(MBEDTLS_SSL_SESSION_TICKETS) && \\\n    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    const char *context_hostname = mbedtls_ssl_get_hostname_pointer(ssl);\n    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3  &&\n        ssl->handshake->resume) {\n        int hostname_mismatch = context_hostname != NULL ||\n                                session_negotiate->hostname != NULL;\n        if (context_hostname != NULL && session_negotiate->hostname != NULL) {\n            hostname_mismatch = strcmp(\n                context_hostname, session_negotiate->hostname) != 0;\n        }\n\n        if (hostname_mismatch) {\n            MBEDTLS_SSL_DEBUG_MSG(\n                1, (\"Hostname mismatch the session ticket, \"\n                    \"disable session resumption.\"));\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n    } else {\n        return mbedtls_ssl_session_set_hostname(session_negotiate,\n                                                context_hostname);\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 &&\n          MBEDTLS_SSL_SESSION_TICKETS &&\n          MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n    return 0;\n}\n/*\n * Write ClientHello handshake message.\n * Handler for MBEDTLS_SSL_CLIENT_HELLO\n */\nint mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl)\n{\n    int ret = 0;\n    unsigned char *buf;\n    size_t buf_len, msg_len, binders_len;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write client hello\"));\n\n    MBEDTLS_SSL_PROC_CHK(ssl_prepare_client_hello(ssl));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(\n                             ssl, MBEDTLS_SSL_HS_CLIENT_HELLO,\n                             &buf, &buf_len));\n\n    MBEDTLS_SSL_PROC_CHK(ssl_write_client_hello_body(ssl, buf,\n                                                     buf + buf_len,\n                                                     &msg_len,\n                                                     &binders_len));\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        ssl->out_msglen = msg_len + 4;\n        mbedtls_ssl_send_flight_completed(ssl);\n\n        /*\n         * The two functions below may try to send data on the network and\n         * can return with the MBEDTLS_ERR_SSL_WANT_READ error code when they\n         * fail to do so and the transmission has to be retried later. In that\n         * case as in fatal error cases, we return immediately. But we must have\n         * set the handshake state to the next state at that point to ensure\n         * that we will not write and send again a ClientHello when we\n         * eventually succeed in sending the pending data.\n         */\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO);\n\n        if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_write_handshake_msg\", ret);\n            return ret;\n        }\n\n        if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_flight_transmit\", ret);\n            return ret;\n        }\n    } else\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_DTLS */\n    {\n\n        ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl,\n                                                 MBEDTLS_SSL_HS_CLIENT_HELLO,\n                                                 msg_len);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_add_hs_hdr_to_checksum\", ret);\n            return ret;\n        }\n        ret = ssl->handshake->update_checksum(ssl, buf, msg_len - binders_len);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"update_checksum\", ret);\n            return ret;\n        }\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n        if (binders_len > 0) {\n            MBEDTLS_SSL_PROC_CHK(\n                mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext(\n                    ssl, buf + msg_len - binders_len, buf + msg_len));\n            ret = ssl->handshake->update_checksum(ssl, buf + msg_len - binders_len,\n                                                  binders_len);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"update_checksum\", ret);\n                return ret;\n            }\n        }\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */\n\n        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl,\n                                                              buf_len,\n                                                              msg_len));\n\n        /*\n         * Set next state. Note that if TLS 1.3 is proposed, this may be\n         * overwritten by mbedtls_ssl_tls13_finalize_client_hello().\n         */\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO);\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n        if (ssl->handshake->min_tls_version <=  MBEDTLS_SSL_VERSION_TLS1_3 &&\n            MBEDTLS_SSL_VERSION_TLS1_3 <= ssl->tls_version) {\n            ret = mbedtls_ssl_tls13_finalize_client_hello(ssl);\n        }\n#endif\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    MBEDTLS_SSL_PRINT_EXTS(\n        3, MBEDTLS_SSL_HS_CLIENT_HELLO, ssl->handshake->sent_extensions);\n#endif\n\ncleanup:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write client hello\"));\n    return ret;\n}\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 || MBEDTLS_SSL_PROTO_TLS1_2 */\n#endif /* MBEDTLS_SSL_CLI_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_client.h",
    "content": "/**\n *  TLS 1.2 and 1.3 client-side functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_SSL_CLIENT_H\n#define MBEDTLS_SSL_CLIENT_H\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_TLS_C)\n#include \"ssl_misc.h\"\n#endif\n\n#include <stddef.h>\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl);\n\n#endif /* MBEDTLS_SSL_CLIENT_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_cookie.c",
    "content": "/*\n *  DTLS cookie callbacks implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n * These session callbacks use a simple chained list\n * to store and retrieve the session information.\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_COOKIE_C)\n\n#include \"mbedtls/platform.h\"\n\n#include \"mbedtls/ssl_cookie.h\"\n#include \"ssl_misc.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/constant_time.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"mbedtls/psa_util.h\"\n/* Define a local translating function to save code size by not using too many\n * arguments in each translating place. */\nstatic int local_err_translation(psa_status_t status)\n{\n    return psa_status_to_mbedtls(status, psa_to_ssl_errors,\n                                 ARRAY_LENGTH(psa_to_ssl_errors),\n                                 psa_generic_status_to_mbedtls);\n}\n#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)\n#endif\n\n/*\n * If DTLS is in use, then at least one of SHA-256 or SHA-384 is\n * available. Try SHA-256 first as 384 wastes resources\n */\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#define COOKIE_MD           MBEDTLS_MD_SHA256\n#define COOKIE_MD_OUTLEN    32\n#define COOKIE_HMAC_LEN     28\n#elif defined(MBEDTLS_MD_CAN_SHA384)\n#define COOKIE_MD           MBEDTLS_MD_SHA384\n#define COOKIE_MD_OUTLEN    48\n#define COOKIE_HMAC_LEN     28\n#else\n#error \"DTLS hello verify needs SHA-256 or SHA-384\"\n#endif\n\n/*\n * Cookies are formed of a 4-bytes timestamp (or serial number) and\n * an HMAC of timestamp and client ID.\n */\n#define COOKIE_LEN      (4 + COOKIE_HMAC_LEN)\n\nvoid mbedtls_ssl_cookie_init(mbedtls_ssl_cookie_ctx *ctx)\n{\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    ctx->psa_hmac_key = MBEDTLS_SVC_KEY_ID_INIT;\n#else\n    mbedtls_md_init(&ctx->hmac_ctx);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#if !defined(MBEDTLS_HAVE_TIME)\n    ctx->serial = 0;\n#endif\n    ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT;\n\n#if !defined(MBEDTLS_USE_PSA_CRYPTO)\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_init(&ctx->mutex);\n#endif\n#endif /* !MBEDTLS_USE_PSA_CRYPTO */\n}\n\nvoid mbedtls_ssl_cookie_set_timeout(mbedtls_ssl_cookie_ctx *ctx, unsigned long delay)\n{\n    ctx->timeout = delay;\n}\n\nvoid mbedtls_ssl_cookie_free(mbedtls_ssl_cookie_ctx *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_destroy_key(ctx->psa_hmac_key);\n#else\n    mbedtls_md_free(&ctx->hmac_ctx);\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_free(&ctx->mutex);\n#endif\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_cookie_ctx));\n}\n\nint mbedtls_ssl_cookie_setup(mbedtls_ssl_cookie_ctx *ctx,\n                             int (*f_rng)(void *, unsigned char *, size_t),\n                             void *p_rng)\n{\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_algorithm_t alg;\n\n    (void) f_rng;\n    (void) p_rng;\n\n    alg = mbedtls_md_psa_alg_from_type(COOKIE_MD);\n    if (alg == 0) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    ctx->psa_hmac_alg = PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(alg),\n                                              COOKIE_HMAC_LEN);\n\n    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_MESSAGE |\n                            PSA_KEY_USAGE_SIGN_MESSAGE);\n    psa_set_key_algorithm(&attributes, ctx->psa_hmac_alg);\n    psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);\n    psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(COOKIE_MD_OUTLEN));\n\n    if ((status = psa_generate_key(&attributes,\n                                   &ctx->psa_hmac_key)) != PSA_SUCCESS) {\n        return PSA_TO_MBEDTLS_ERR(status);\n    }\n#else\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char key[COOKIE_MD_OUTLEN];\n\n    if ((ret = f_rng(p_rng, key, sizeof(key))) != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_md_setup(&ctx->hmac_ctx, mbedtls_md_info_from_type(COOKIE_MD), 1);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_md_hmac_starts(&ctx->hmac_ctx, key, sizeof(key));\n    if (ret != 0) {\n        return ret;\n    }\n\n    mbedtls_platform_zeroize(key, sizeof(key));\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    return 0;\n}\n\n#if !defined(MBEDTLS_USE_PSA_CRYPTO)\n/*\n * Generate the HMAC part of a cookie\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_cookie_hmac(mbedtls_md_context_t *hmac_ctx,\n                           const unsigned char time[4],\n                           unsigned char **p, unsigned char *end,\n                           const unsigned char *cli_id, size_t cli_id_len)\n{\n    unsigned char hmac_out[COOKIE_MD_OUTLEN];\n\n    MBEDTLS_SSL_CHK_BUF_PTR(*p, end, COOKIE_HMAC_LEN);\n\n    if (mbedtls_md_hmac_reset(hmac_ctx) != 0 ||\n        mbedtls_md_hmac_update(hmac_ctx, time, 4) != 0 ||\n        mbedtls_md_hmac_update(hmac_ctx, cli_id, cli_id_len) != 0 ||\n        mbedtls_md_hmac_finish(hmac_ctx, hmac_out) != 0) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    memcpy(*p, hmac_out, COOKIE_HMAC_LEN);\n    *p += COOKIE_HMAC_LEN;\n\n    return 0;\n}\n#endif /* !MBEDTLS_USE_PSA_CRYPTO */\n\n/*\n * Generate cookie for DTLS ClientHello verification\n */\nint mbedtls_ssl_cookie_write(void *p_ctx,\n                             unsigned char **p, unsigned char *end,\n                             const unsigned char *cli_id, size_t cli_id_len)\n{\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t sign_mac_length = 0;\n#endif\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx;\n    unsigned long t;\n\n    if (ctx == NULL || cli_id == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    MBEDTLS_SSL_CHK_BUF_PTR(*p, end, COOKIE_LEN);\n\n#if defined(MBEDTLS_HAVE_TIME)\n    t = (unsigned long) mbedtls_time(NULL);\n#else\n    t = ctx->serial++;\n#endif\n\n    MBEDTLS_PUT_UINT32_BE(t, *p, 0);\n    *p += 4;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    status = psa_mac_sign_setup(&operation, ctx->psa_hmac_key,\n                                ctx->psa_hmac_alg);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        goto exit;\n    }\n\n    status = psa_mac_update(&operation, *p - 4, 4);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        goto exit;\n    }\n\n    status = psa_mac_update(&operation, cli_id, cli_id_len);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        goto exit;\n    }\n\n    status = psa_mac_sign_finish(&operation, *p, COOKIE_MD_OUTLEN,\n                                 &sign_mac_length);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        goto exit;\n    }\n\n    *p += COOKIE_HMAC_LEN;\n\n    ret = 0;\n#else\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret);\n    }\n#endif\n\n    ret = ssl_cookie_hmac(&ctx->hmac_ctx, *p - 4,\n                          p, end, cli_id, cli_id_len);\n\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR,\n                                 MBEDTLS_ERR_THREADING_MUTEX_ERROR);\n    }\n#endif\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nexit:\n    status = psa_mac_abort(&operation);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    return ret;\n}\n\n/*\n * Check a cookie\n */\nint mbedtls_ssl_cookie_check(void *p_ctx,\n                             const unsigned char *cookie, size_t cookie_len,\n                             const unsigned char *cli_id, size_t cli_id_len)\n{\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n#else\n    unsigned char ref_hmac[COOKIE_HMAC_LEN];\n    unsigned char *p = ref_hmac;\n#endif\n    int ret = 0;\n    mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx;\n    unsigned long cur_time, cookie_time;\n\n    if (ctx == NULL || cli_id == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if (cookie_len != COOKIE_LEN) {\n        return -1;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    status = psa_mac_verify_setup(&operation, ctx->psa_hmac_key,\n                                  ctx->psa_hmac_alg);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        goto exit;\n    }\n\n    status = psa_mac_update(&operation, cookie, 4);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        goto exit;\n    }\n\n    status = psa_mac_update(&operation, cli_id,\n                            cli_id_len);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        goto exit;\n    }\n\n    status = psa_mac_verify_finish(&operation, cookie + 4,\n                                   COOKIE_HMAC_LEN);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        goto exit;\n    }\n\n    ret = 0;\n#else\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret);\n    }\n#endif\n\n    if (ssl_cookie_hmac(&ctx->hmac_ctx, cookie,\n                        &p, p + sizeof(ref_hmac),\n                        cli_id, cli_id_len) != 0) {\n        ret = -1;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {\n        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR,\n                                MBEDTLS_ERR_THREADING_MUTEX_ERROR);\n    }\n#endif\n\n    if (ret != 0) {\n        goto exit;\n    }\n\n    if (mbedtls_ct_memcmp(cookie + 4, ref_hmac, sizeof(ref_hmac)) != 0) {\n        ret = -1;\n        goto exit;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_HAVE_TIME)\n    cur_time = (unsigned long) mbedtls_time(NULL);\n#else\n    cur_time = ctx->serial;\n#endif\n\n    cookie_time = (unsigned long) MBEDTLS_GET_UINT32_BE(cookie, 0);\n\n    if (ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout) {\n        ret = -1;\n        goto exit;\n    }\n\nexit:\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    status = psa_mac_abort(&operation);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n    }\n#else\n    mbedtls_platform_zeroize(ref_hmac, sizeof(ref_hmac));\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    return ret;\n}\n#endif /* MBEDTLS_SSL_COOKIE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_debug_helpers.h",
    "content": "/**\n * \\file ssl_debug_helpers.h\n *\n * \\brief Automatically generated helper functions for debugging\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_SSL_DEBUG_HELPERS_H\n#define MBEDTLS_SSL_DEBUG_HELPERS_H\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_DEBUG_C)\n\n#include \"mbedtls/ssl.h\"\n#include \"ssl_misc.h\"\n\n\nconst char *mbedtls_ssl_states_str(mbedtls_ssl_states in);\n\n#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)\nconst char *mbedtls_ssl_early_data_status_str(mbedtls_ssl_early_data_status in);\nconst char *mbedtls_ssl_early_data_state_str(mbedtls_ssl_early_data_state in);\n#endif\n\nconst char *mbedtls_ssl_protocol_version_str(mbedtls_ssl_protocol_version in);\n\nconst char *mbedtls_tls_prf_types_str(mbedtls_tls_prf_types in);\n\nconst char *mbedtls_ssl_key_export_type_str(mbedtls_ssl_key_export_type in);\n\nconst char *mbedtls_ssl_sig_alg_to_str(uint16_t in);\n\nconst char *mbedtls_ssl_named_group_to_str(uint16_t in);\n\nconst char *mbedtls_ssl_get_extension_name(unsigned int extension_type);\n\nvoid mbedtls_ssl_print_extensions(const mbedtls_ssl_context *ssl,\n                                  int level, const char *file, int line,\n                                  int hs_msg_type, uint32_t extensions_mask,\n                                  const char *extra);\n\nvoid mbedtls_ssl_print_extension(const mbedtls_ssl_context *ssl,\n                                 int level, const char *file, int line,\n                                 int hs_msg_type, unsigned int extension_type,\n                                 const char *extra_msg0, const char *extra_msg1);\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)\nvoid mbedtls_ssl_print_ticket_flags(const mbedtls_ssl_context *ssl,\n                                    int level, const char *file, int line,\n                                    unsigned int flags);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */\n\n#define MBEDTLS_SSL_PRINT_EXTS(level, hs_msg_type, extensions_mask)            \\\n    mbedtls_ssl_print_extensions(ssl, level, __FILE__, __LINE__,       \\\n                                 hs_msg_type, extensions_mask, NULL)\n\n#define MBEDTLS_SSL_PRINT_EXT(level, hs_msg_type, extension_type, extra)      \\\n    mbedtls_ssl_print_extension(ssl, level, __FILE__, __LINE__,        \\\n                                hs_msg_type, extension_type,           \\\n                                extra, NULL)\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)\n#define MBEDTLS_SSL_PRINT_TICKET_FLAGS(level, flags)             \\\n    mbedtls_ssl_print_ticket_flags(ssl, level, __FILE__, __LINE__, flags)\n#endif\n\n#else\n\n#define MBEDTLS_SSL_PRINT_EXTS(level, hs_msg_type, extension_mask)\n\n#define MBEDTLS_SSL_PRINT_EXT(level, hs_msg_type, extension_type, extra)\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)\n#define MBEDTLS_SSL_PRINT_TICKET_FLAGS(level, flags)\n#endif\n\n#endif /* MBEDTLS_DEBUG_C */\n\n#endif /* MBEDTLS_SSL_DEBUG_HELPERS_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_debug_helpers_generated.c",
    "content": "/* Automatically generated by generate_ssl_debug_helpers.py. DO NOT EDIT. */\n\n/**\n * \\file ssl_debug_helpers_generated.c\n *\n * \\brief Automatically generated helper functions for debugging\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n *\n */\n\n#include \"ssl_misc.h\"\n\n#if defined(MBEDTLS_DEBUG_C)\n\n#include \"ssl_debug_helpers.h\"\n\n\nconst char *mbedtls_ssl_named_group_to_str( uint16_t in )\n{\n    switch( in )\n    {\n    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1:\n        return \"secp192k1\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1:\n        return \"secp192r1\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1:\n        return \"secp224k1\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1:\n        return \"secp224r1\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1:\n        return \"secp256k1\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1:\n        return \"secp256r1\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1:\n        return \"secp384r1\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1:\n        return \"secp521r1\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1:\n        return \"bp256r1\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1:\n        return \"bp384r1\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1:\n        return \"bp512r1\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_X25519:\n        return \"x25519\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_X448:\n        return \"x448\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048:\n        return \"ffdhe2048\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072:\n        return \"ffdhe3072\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096:\n        return \"ffdhe4096\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144:\n        return \"ffdhe6144\";\n    case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192:\n        return \"ffdhe8192\";\n    };\n\n    return \"UNKNOWN\";\n}\nconst char *mbedtls_ssl_sig_alg_to_str( uint16_t in )\n{\n    switch( in )\n    {\n    case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256:\n        return \"rsa_pkcs1_sha256\";\n    case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384:\n        return \"rsa_pkcs1_sha384\";\n    case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512:\n        return \"rsa_pkcs1_sha512\";\n    case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256:\n        return \"ecdsa_secp256r1_sha256\";\n    case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384:\n        return \"ecdsa_secp384r1_sha384\";\n    case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512:\n        return \"ecdsa_secp521r1_sha512\";\n    case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256:\n        return \"rsa_pss_rsae_sha256\";\n    case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384:\n        return \"rsa_pss_rsae_sha384\";\n    case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512:\n        return \"rsa_pss_rsae_sha512\";\n    case MBEDTLS_TLS1_3_SIG_ED25519:\n        return \"ed25519\";\n    case MBEDTLS_TLS1_3_SIG_ED448:\n        return \"ed448\";\n    case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA256:\n        return \"rsa_pss_pss_sha256\";\n    case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA384:\n        return \"rsa_pss_pss_sha384\";\n    case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA512:\n        return \"rsa_pss_pss_sha512\";\n    case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA1:\n        return \"rsa_pkcs1_sha1\";\n    case MBEDTLS_TLS1_3_SIG_ECDSA_SHA1:\n        return \"ecdsa_sha1\";\n    case MBEDTLS_TLS1_3_SIG_NONE:\n        return \"none\";\n    };\n\n    return \"UNKNOWN\";\n}\nconst char *mbedtls_ssl_states_str( mbedtls_ssl_states in )\n{\n    switch (in) {\n        case MBEDTLS_SSL_HELLO_REQUEST:\n            return \"MBEDTLS_SSL_HELLO_REQUEST\";\n        case MBEDTLS_SSL_CLIENT_HELLO:\n            return \"MBEDTLS_SSL_CLIENT_HELLO\";\n        case MBEDTLS_SSL_SERVER_HELLO:\n            return \"MBEDTLS_SSL_SERVER_HELLO\";\n        case MBEDTLS_SSL_SERVER_CERTIFICATE:\n            return \"MBEDTLS_SSL_SERVER_CERTIFICATE\";\n        case MBEDTLS_SSL_SERVER_KEY_EXCHANGE:\n            return \"MBEDTLS_SSL_SERVER_KEY_EXCHANGE\";\n        case MBEDTLS_SSL_CERTIFICATE_REQUEST:\n            return \"MBEDTLS_SSL_CERTIFICATE_REQUEST\";\n        case MBEDTLS_SSL_SERVER_HELLO_DONE:\n            return \"MBEDTLS_SSL_SERVER_HELLO_DONE\";\n        case MBEDTLS_SSL_CLIENT_CERTIFICATE:\n            return \"MBEDTLS_SSL_CLIENT_CERTIFICATE\";\n        case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:\n            return \"MBEDTLS_SSL_CLIENT_KEY_EXCHANGE\";\n        case MBEDTLS_SSL_CERTIFICATE_VERIFY:\n            return \"MBEDTLS_SSL_CERTIFICATE_VERIFY\";\n        case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC:\n            return \"MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC\";\n        case MBEDTLS_SSL_CLIENT_FINISHED:\n            return \"MBEDTLS_SSL_CLIENT_FINISHED\";\n        case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC:\n            return \"MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC\";\n        case MBEDTLS_SSL_SERVER_FINISHED:\n            return \"MBEDTLS_SSL_SERVER_FINISHED\";\n        case MBEDTLS_SSL_FLUSH_BUFFERS:\n            return \"MBEDTLS_SSL_FLUSH_BUFFERS\";\n        case MBEDTLS_SSL_HANDSHAKE_WRAPUP:\n            return \"MBEDTLS_SSL_HANDSHAKE_WRAPUP\";\n        case MBEDTLS_SSL_NEW_SESSION_TICKET:\n            return \"MBEDTLS_SSL_NEW_SESSION_TICKET\";\n        case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT:\n            return \"MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT\";\n        case MBEDTLS_SSL_HELLO_RETRY_REQUEST:\n            return \"MBEDTLS_SSL_HELLO_RETRY_REQUEST\";\n        case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS:\n            return \"MBEDTLS_SSL_ENCRYPTED_EXTENSIONS\";\n        case MBEDTLS_SSL_END_OF_EARLY_DATA:\n            return \"MBEDTLS_SSL_END_OF_EARLY_DATA\";\n        case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY:\n            return \"MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY\";\n        case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED:\n            return \"MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED\";\n        case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO:\n            return \"MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO\";\n        case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO:\n            return \"MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO\";\n        case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO:\n            return \"MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO\";\n        case MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST:\n            return \"MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST\";\n        case MBEDTLS_SSL_HANDSHAKE_OVER:\n            return \"MBEDTLS_SSL_HANDSHAKE_OVER\";\n        case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET:\n            return \"MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET\";\n        case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH:\n            return \"MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH\";\n        default:\n            return \"UNKNOWN_VALUE\";\n    }\n}\n\n#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)\nconst char *mbedtls_ssl_early_data_status_str( mbedtls_ssl_early_data_status in )\n{\n    switch (in) {\n        case MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED:\n            return \"MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED\";\n        case MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED:\n            return \"MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED\";\n        case MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED:\n            return \"MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED\";\n        default:\n            return \"UNKNOWN_VALUE\";\n    }\n}\n\n#endif /* defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) */\nconst char *mbedtls_ssl_protocol_version_str( mbedtls_ssl_protocol_version in )\n{\n    switch (in) {\n        case MBEDTLS_SSL_VERSION_UNKNOWN:\n            return \"MBEDTLS_SSL_VERSION_UNKNOWN\";\n        case MBEDTLS_SSL_VERSION_TLS1_2:\n            return \"MBEDTLS_SSL_VERSION_TLS1_2\";\n        case MBEDTLS_SSL_VERSION_TLS1_3:\n            return \"MBEDTLS_SSL_VERSION_TLS1_3\";\n        default:\n            return \"UNKNOWN_VALUE\";\n    }\n}\n\nconst char *mbedtls_tls_prf_types_str( mbedtls_tls_prf_types in )\n{\n    switch (in) {\n        case MBEDTLS_SSL_TLS_PRF_NONE:\n            return \"MBEDTLS_SSL_TLS_PRF_NONE\";\n        case MBEDTLS_SSL_TLS_PRF_SHA384:\n            return \"MBEDTLS_SSL_TLS_PRF_SHA384\";\n        case MBEDTLS_SSL_TLS_PRF_SHA256:\n            return \"MBEDTLS_SSL_TLS_PRF_SHA256\";\n        case MBEDTLS_SSL_HKDF_EXPAND_SHA384:\n            return \"MBEDTLS_SSL_HKDF_EXPAND_SHA384\";\n        case MBEDTLS_SSL_HKDF_EXPAND_SHA256:\n            return \"MBEDTLS_SSL_HKDF_EXPAND_SHA256\";\n        default:\n            return \"UNKNOWN_VALUE\";\n    }\n}\n\nconst char *mbedtls_ssl_key_export_type_str( mbedtls_ssl_key_export_type in )\n{\n    switch (in) {\n        case MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET:\n            return \"MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET\";\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n        case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET:\n            return \"MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET\";\n        case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET:\n            return \"MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET\";\n        case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET:\n            return \"MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET\";\n        case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET:\n            return \"MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET\";\n        case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET:\n            return \"MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET\";\n        case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET:\n            return \"MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET\";\n#endif\n        default:\n            return \"UNKNOWN_VALUE\";\n    }\n}\n\n\n\n#endif /* MBEDTLS_DEBUG_C */\n/* End of automatically generated file. */\n\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_misc.h",
    "content": "/**\n * \\file ssl_misc.h\n *\n * \\brief Internal functions shared by the SSL modules\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_SSL_MISC_H\n#define MBEDTLS_SSL_MISC_H\n\n#include \"mbedtls/build_info.h\"\n#include \"common.h\"\n\n#include \"mbedtls/error.h\"\n\n#include \"mbedtls/ssl.h\"\n#include \"mbedtls/debug.h\"\n#include \"debug_internal.h\"\n\n#include \"mbedtls/cipher.h\"\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)\n#include \"psa/crypto.h\"\n#include \"psa_util_internal.h\"\n#endif\n\n#if defined(MBEDTLS_MD_CAN_MD5)\n#include \"mbedtls/md5.h\"\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA1)\n#include \"mbedtls/sha1.h\"\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#include \"mbedtls/sha256.h\"\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA512)\n#include \"mbedtls/sha512.h\"\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \\\n    !defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"mbedtls/ecjpake.h\"\n#endif\n\n#include \"mbedtls/pk.h\"\n#include \"ssl_ciphersuites_internal.h\"\n#include \"x509_internal.h\"\n#include \"pk_internal.h\"\n\n\n/* Shorthand for restartable ECC */\n#if defined(MBEDTLS_ECP_RESTARTABLE) && \\\n    defined(MBEDTLS_SSL_CLI_C) && \\\n    defined(MBEDTLS_SSL_PROTO_TLS1_2) && \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)\n#define MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED\n#endif\n\n#define MBEDTLS_SSL_INITIAL_HANDSHAKE           0\n#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS   1   /* In progress */\n#define MBEDTLS_SSL_RENEGOTIATION_DONE          2   /* Done or aborted */\n#define MBEDTLS_SSL_RENEGOTIATION_PENDING       3   /* Requested (server only) */\n\n/* Faked handshake message identity for HelloRetryRequest. */\n#define MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST (-MBEDTLS_SSL_HS_SERVER_HELLO)\n\n/*\n * Internal identity of handshake extensions\n */\n#define MBEDTLS_SSL_EXT_ID_UNRECOGNIZED                0\n#define MBEDTLS_SSL_EXT_ID_SERVERNAME                  1\n#define MBEDTLS_SSL_EXT_ID_SERVERNAME_HOSTNAME         1\n#define MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH         2\n#define MBEDTLS_SSL_EXT_ID_STATUS_REQUEST              3\n#define MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS            4\n#define MBEDTLS_SSL_EXT_ID_SUPPORTED_ELLIPTIC_CURVES   4\n#define MBEDTLS_SSL_EXT_ID_SIG_ALG                     5\n#define MBEDTLS_SSL_EXT_ID_USE_SRTP                    6\n#define MBEDTLS_SSL_EXT_ID_HEARTBEAT                   7\n#define MBEDTLS_SSL_EXT_ID_ALPN                        8\n#define MBEDTLS_SSL_EXT_ID_SCT                         9\n#define MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE              10\n#define MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE             11\n#define MBEDTLS_SSL_EXT_ID_PADDING                    12\n#define MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY             13\n#define MBEDTLS_SSL_EXT_ID_EARLY_DATA                 14\n#define MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS         15\n#define MBEDTLS_SSL_EXT_ID_COOKIE                     16\n#define MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES     17\n#define MBEDTLS_SSL_EXT_ID_CERT_AUTH                  18\n#define MBEDTLS_SSL_EXT_ID_OID_FILTERS                19\n#define MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH        20\n#define MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT               21\n#define MBEDTLS_SSL_EXT_ID_KEY_SHARE                  22\n#define MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC             23\n#define MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS    24\n#define MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC           25\n#define MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET     26\n#define MBEDTLS_SSL_EXT_ID_SESSION_TICKET             27\n#define MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT          28\n\n/* Utility for translating IANA extension type. */\nuint32_t mbedtls_ssl_get_extension_id(unsigned int extension_type);\nuint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type);\n/* Macros used to define mask constants */\n#define MBEDTLS_SSL_EXT_MASK(id)       (1ULL << (MBEDTLS_SSL_EXT_ID_##id))\n/* Reset value of extension mask */\n#define MBEDTLS_SSL_EXT_MASK_NONE                                              0\n\n/* In messages containing extension requests, we should ignore unrecognized\n * extensions. In messages containing extension responses, unrecognized\n * extensions should result in handshake abortion. Messages containing\n * extension requests include ClientHello, CertificateRequest and\n * NewSessionTicket. Messages containing extension responses include\n * ServerHello, HelloRetryRequest, EncryptedExtensions and Certificate.\n *\n * RFC 8446 section 4.1.3\n *\n * The ServerHello MUST only include extensions which are required to establish\n * the cryptographic context and negotiate the protocol version.\n *\n * RFC 8446 section 4.2\n *\n * If an implementation receives an extension which it recognizes and which is\n * not specified for the message in which it appears, it MUST abort the handshake\n * with an \"illegal_parameter\" alert.\n */\n\n/* Extensions that are not recognized by TLS 1.3 */\n#define MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED                               \\\n    (MBEDTLS_SSL_EXT_MASK(SUPPORTED_POINT_FORMATS)                | \\\n     MBEDTLS_SSL_EXT_MASK(ENCRYPT_THEN_MAC)                       | \\\n     MBEDTLS_SSL_EXT_MASK(EXTENDED_MASTER_SECRET)                 | \\\n     MBEDTLS_SSL_EXT_MASK(SESSION_TICKET)                         | \\\n     MBEDTLS_SSL_EXT_MASK(TRUNCATED_HMAC)                         | \\\n     MBEDTLS_SSL_EXT_MASK(UNRECOGNIZED))\n\n/* RFC 8446 section 4.2. Allowed extensions for ClientHello */\n#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH                                  \\\n    (MBEDTLS_SSL_EXT_MASK(SERVERNAME)                             | \\\n     MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH)                    | \\\n     MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST)                         | \\\n     MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS)                       | \\\n     MBEDTLS_SSL_EXT_MASK(SIG_ALG)                                | \\\n     MBEDTLS_SSL_EXT_MASK(USE_SRTP)                               | \\\n     MBEDTLS_SSL_EXT_MASK(HEARTBEAT)                              | \\\n     MBEDTLS_SSL_EXT_MASK(ALPN)                                   | \\\n     MBEDTLS_SSL_EXT_MASK(SCT)                                    | \\\n     MBEDTLS_SSL_EXT_MASK(CLI_CERT_TYPE)                          | \\\n     MBEDTLS_SSL_EXT_MASK(SERV_CERT_TYPE)                         | \\\n     MBEDTLS_SSL_EXT_MASK(PADDING)                                | \\\n     MBEDTLS_SSL_EXT_MASK(KEY_SHARE)                              | \\\n     MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)                         | \\\n     MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)                 | \\\n     MBEDTLS_SSL_EXT_MASK(EARLY_DATA)                             | \\\n     MBEDTLS_SSL_EXT_MASK(COOKIE)                                 | \\\n     MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS)                     | \\\n     MBEDTLS_SSL_EXT_MASK(CERT_AUTH)                              | \\\n     MBEDTLS_SSL_EXT_MASK(POST_HANDSHAKE_AUTH)                    | \\\n     MBEDTLS_SSL_EXT_MASK(SIG_ALG_CERT)                           | \\\n     MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)                      | \\\n     MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED)\n\n/* RFC 8446 section 4.2. Allowed extensions for EncryptedExtensions */\n#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_EE                                  \\\n    (MBEDTLS_SSL_EXT_MASK(SERVERNAME)                             | \\\n     MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH)                    | \\\n     MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS)                       | \\\n     MBEDTLS_SSL_EXT_MASK(USE_SRTP)                               | \\\n     MBEDTLS_SSL_EXT_MASK(HEARTBEAT)                              | \\\n     MBEDTLS_SSL_EXT_MASK(ALPN)                                   | \\\n     MBEDTLS_SSL_EXT_MASK(CLI_CERT_TYPE)                          | \\\n     MBEDTLS_SSL_EXT_MASK(SERV_CERT_TYPE)                         | \\\n     MBEDTLS_SSL_EXT_MASK(EARLY_DATA)                             | \\\n     MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT))\n\n/* RFC 8446 section 4.2. Allowed extensions for CertificateRequest */\n#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CR                                  \\\n    (MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST)                         | \\\n     MBEDTLS_SSL_EXT_MASK(SIG_ALG)                                | \\\n     MBEDTLS_SSL_EXT_MASK(SCT)                                    | \\\n     MBEDTLS_SSL_EXT_MASK(CERT_AUTH)                              | \\\n     MBEDTLS_SSL_EXT_MASK(OID_FILTERS)                            | \\\n     MBEDTLS_SSL_EXT_MASK(SIG_ALG_CERT)                           | \\\n     MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED)\n\n/* RFC 8446 section 4.2. Allowed extensions for Certificate */\n#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CT                                  \\\n    (MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST)                         | \\\n     MBEDTLS_SSL_EXT_MASK(SCT))\n\n/* RFC 8446 section 4.2. Allowed extensions for ServerHello */\n#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_SH                                  \\\n    (MBEDTLS_SSL_EXT_MASK(KEY_SHARE)                              | \\\n     MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)                         | \\\n     MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS))\n\n/* RFC 8446 section 4.2. Allowed extensions for HelloRetryRequest */\n#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_HRR                                 \\\n    (MBEDTLS_SSL_EXT_MASK(KEY_SHARE)                              | \\\n     MBEDTLS_SSL_EXT_MASK(COOKIE)                                 | \\\n     MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS))\n\n/* RFC 8446 section 4.2. Allowed extensions for NewSessionTicket */\n#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_NST                                 \\\n    (MBEDTLS_SSL_EXT_MASK(EARLY_DATA)                             | \\\n     MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED)\n\n/*\n * Helper macros for function call with return check.\n */\n/*\n * Exit when return non-zero value\n */\n#define MBEDTLS_SSL_PROC_CHK(f)                               \\\n    do {                                                        \\\n        ret = (f);                                            \\\n        if (ret != 0)                                          \\\n        {                                                       \\\n            goto cleanup;                                       \\\n        }                                                       \\\n    } while (0)\n/*\n * Exit when return negative value\n */\n#define MBEDTLS_SSL_PROC_CHK_NEG(f)                           \\\n    do {                                                        \\\n        ret = (f);                                            \\\n        if (ret < 0)                                           \\\n        {                                                       \\\n            goto cleanup;                                       \\\n        }                                                       \\\n    } while (0)\n\n/*\n * DTLS retransmission states, see RFC 6347 4.2.4\n *\n * The SENDING state is merged in PREPARING for initial sends,\n * but is distinct for resends.\n *\n * Note: initial state is wrong for server, but is not used anyway.\n */\n#define MBEDTLS_SSL_RETRANS_PREPARING       0\n#define MBEDTLS_SSL_RETRANS_SENDING         1\n#define MBEDTLS_SSL_RETRANS_WAITING         2\n#define MBEDTLS_SSL_RETRANS_FINISHED        3\n\n/*\n * Allow extra bytes for record, authentication and encryption overhead:\n * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256).\n */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n\n/* This macro determines whether CBC is supported. */\n#if defined(MBEDTLS_SSL_HAVE_CBC)      &&                                  \\\n    (defined(MBEDTLS_SSL_HAVE_AES)     ||                                  \\\n    defined(MBEDTLS_SSL_HAVE_CAMELLIA) ||                                  \\\n    defined(MBEDTLS_SSL_HAVE_ARIA))\n#define MBEDTLS_SSL_SOME_SUITES_USE_CBC\n#endif\n\n/* This macro determines whether a ciphersuite using a\n * stream cipher can be used. */\n#if defined(MBEDTLS_CIPHER_NULL_CIPHER)\n#define MBEDTLS_SSL_SOME_SUITES_USE_STREAM\n#endif\n\n/* This macro determines whether the CBC construct used in TLS 1.2 is supported. */\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \\\n    defined(MBEDTLS_SSL_PROTO_TLS1_2)\n#define MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC\n#endif\n\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) || \\\n    defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC)\n#define MBEDTLS_SSL_SOME_SUITES_USE_MAC\n#endif\n\n/* This macro determines whether a ciphersuite uses Encrypt-then-MAC with CBC */\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \\\n    defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n#define MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM\n#endif\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)\n/* Ciphersuites using HMAC */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n#define MBEDTLS_SSL_MAC_ADD                 48  /* SHA-384 used for HMAC */\n#elif defined(MBEDTLS_MD_CAN_SHA256)\n#define MBEDTLS_SSL_MAC_ADD                 32  /* SHA-256 used for HMAC */\n#else\n#define MBEDTLS_SSL_MAC_ADD                 20  /* SHA-1   used for HMAC */\n#endif\n#else /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */\n/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */\n#define MBEDTLS_SSL_MAC_ADD                 16\n#endif\n\n#if defined(MBEDTLS_SSL_HAVE_CBC)\n#define MBEDTLS_SSL_PADDING_ADD            256\n#else\n#define MBEDTLS_SSL_PADDING_ADD              0\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n#define MBEDTLS_SSL_MAX_CID_EXPANSION      MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY\n#else\n#define MBEDTLS_SSL_MAX_CID_EXPANSION        0\n#endif\n\n#define MBEDTLS_SSL_PAYLOAD_OVERHEAD (MBEDTLS_MAX_IV_LENGTH +          \\\n                                      MBEDTLS_SSL_MAC_ADD +            \\\n                                      MBEDTLS_SSL_PADDING_ADD +        \\\n                                      MBEDTLS_SSL_MAX_CID_EXPANSION    \\\n                                      )\n\n#define MBEDTLS_SSL_IN_PAYLOAD_LEN (MBEDTLS_SSL_PAYLOAD_OVERHEAD + \\\n                                    (MBEDTLS_SSL_IN_CONTENT_LEN))\n\n#define MBEDTLS_SSL_OUT_PAYLOAD_LEN (MBEDTLS_SSL_PAYLOAD_OVERHEAD + \\\n                                     (MBEDTLS_SSL_OUT_CONTENT_LEN))\n\n/* The maximum number of buffered handshake messages. */\n#define MBEDTLS_SSL_MAX_BUFFERED_HS 4\n\n/* Maximum length we can advertise as our max content length for\n   RFC 6066 max_fragment_length extension negotiation purposes\n   (the lesser of both sizes, if they are unequal.)\n */\n#define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN (                            \\\n        (MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN)   \\\n        ? (MBEDTLS_SSL_OUT_CONTENT_LEN)                            \\\n        : (MBEDTLS_SSL_IN_CONTENT_LEN)                             \\\n        )\n\n/* Maximum size in bytes of list in signature algorithms ext., RFC 5246/8446 */\n#define MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN       65534\n\n/* Minimum size in bytes of list in signature algorithms ext., RFC 5246/8446 */\n#define MBEDTLS_SSL_MIN_SIG_ALG_LIST_LEN       2\n\n/* Maximum size in bytes of list in supported elliptic curve ext., RFC 4492 */\n#define MBEDTLS_SSL_MAX_CURVE_LIST_LEN         65535\n\n#define MBEDTLS_RECEIVED_SIG_ALGS_SIZE         20\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n\n#define MBEDTLS_TLS_SIG_NONE MBEDTLS_TLS1_3_SIG_NONE\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n#define MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(sig, hash) ((hash << 8) | sig)\n#define MBEDTLS_SSL_TLS12_SIG_ALG_FROM_SIG_AND_HASH_ALG(alg) (alg & 0xFF)\n#define MBEDTLS_SSL_TLS12_HASH_ALG_FROM_SIG_AND_HASH_ALG(alg) (alg >> 8)\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n/*\n * Check that we obey the standard's message size bounds\n */\n\n#if MBEDTLS_SSL_IN_CONTENT_LEN > 16384\n#error \"Bad configuration - incoming record content too large.\"\n#endif\n\n#if MBEDTLS_SSL_OUT_CONTENT_LEN > 16384\n#error \"Bad configuration - outgoing record content too large.\"\n#endif\n\n#if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_IN_CONTENT_LEN + 2048\n#error \"Bad configuration - incoming protected record payload too large.\"\n#endif\n\n#if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN + 2048\n#error \"Bad configuration - outgoing protected record payload too large.\"\n#endif\n\n/* Calculate buffer sizes */\n\n/* Note: Even though the TLS record header is only 5 bytes\n   long, we're internally using 8 bytes to store the\n   implicit sequence number. */\n#define MBEDTLS_SSL_HEADER_LEN 13\n\n#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n#define MBEDTLS_SSL_IN_BUFFER_LEN  \\\n    ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_IN_PAYLOAD_LEN))\n#else\n#define MBEDTLS_SSL_IN_BUFFER_LEN  \\\n    ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_IN_PAYLOAD_LEN) \\\n     + (MBEDTLS_SSL_CID_IN_LEN_MAX))\n#endif\n\n#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n#define MBEDTLS_SSL_OUT_BUFFER_LEN  \\\n    ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_OUT_PAYLOAD_LEN))\n#else\n#define MBEDTLS_SSL_OUT_BUFFER_LEN                               \\\n    ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_OUT_PAYLOAD_LEN)    \\\n     + (MBEDTLS_SSL_CID_OUT_LEN_MAX))\n#endif\n\n#define MBEDTLS_CLIENT_HELLO_RANDOM_LEN 32\n#define MBEDTLS_SERVER_HELLO_RANDOM_LEN 32\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n/**\n * \\brief          Return the maximum fragment length (payload, in bytes) for\n *                 the output buffer. For the client, this is the configured\n *                 value. For the server, it is the minimum of two - the\n *                 configured value and the negotiated one.\n *\n * \\sa             mbedtls_ssl_conf_max_frag_len()\n * \\sa             mbedtls_ssl_get_max_out_record_payload()\n *\n * \\param ssl      SSL context\n *\n * \\return         Current maximum fragment length for the output buffer.\n */\nsize_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl);\n\n/**\n * \\brief          Return the maximum fragment length (payload, in bytes) for\n *                 the input buffer. This is the negotiated maximum fragment\n *                 length, or, if there is none, MBEDTLS_SSL_IN_CONTENT_LEN.\n *                 If it is not defined either, the value is 2^14. This function\n *                 works as its predecessor, \\c mbedtls_ssl_get_max_frag_len().\n *\n * \\sa             mbedtls_ssl_conf_max_frag_len()\n * \\sa             mbedtls_ssl_get_max_in_record_payload()\n *\n * \\param ssl      SSL context\n *\n * \\return         Current maximum fragment length for the output buffer.\n */\nsize_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl);\n#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */\n\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n/**\n * \\brief    Get the size limit in bytes for the protected outgoing records\n *           as defined in RFC 8449\n *\n * \\param ssl      SSL context\n *\n * \\return         The size limit in bytes for the protected outgoing\n *                 records as defined in RFC 8449.\n */\nsize_t mbedtls_ssl_get_output_record_size_limit(const mbedtls_ssl_context *ssl);\n#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */\n\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\nstatic inline size_t mbedtls_ssl_get_output_buflen(const mbedtls_ssl_context *ctx)\n{\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    return mbedtls_ssl_get_output_max_frag_len(ctx)\n           + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD\n           + MBEDTLS_SSL_CID_OUT_LEN_MAX;\n#else\n    return mbedtls_ssl_get_output_max_frag_len(ctx)\n           + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD;\n#endif\n}\n\nstatic inline size_t mbedtls_ssl_get_input_buflen(const mbedtls_ssl_context *ctx)\n{\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    return mbedtls_ssl_get_input_max_frag_len(ctx)\n           + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD\n           + MBEDTLS_SSL_CID_IN_LEN_MAX;\n#else\n    return mbedtls_ssl_get_input_max_frag_len(ctx)\n           + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD;\n#endif\n}\n#endif\n\n/*\n * TLS extension flags (for extensions with outgoing ServerHello content\n * that need it (e.g. for RENEGOTIATION_INFO the server already knows because\n * of state of the renegotiation flag, so no indicator is required)\n */\n#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0)\n#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK                 (1 << 1)\n\n/**\n * \\brief        This function checks if the remaining size in a buffer is\n *               greater or equal than a needed space.\n *\n * \\param cur    Pointer to the current position in the buffer.\n * \\param end    Pointer to one past the end of the buffer.\n * \\param need   Needed space in bytes.\n *\n * \\return       Zero if the needed space is available in the buffer, non-zero\n *               otherwise.\n */\n#if !defined(MBEDTLS_TEST_HOOKS)\nstatic inline int mbedtls_ssl_chk_buf_ptr(const uint8_t *cur,\n                                          const uint8_t *end, size_t need)\n{\n    return (cur > end) || (need > (size_t) (end - cur));\n}\n#else\ntypedef struct {\n    const uint8_t *cur;\n    const uint8_t *end;\n    size_t need;\n} mbedtls_ssl_chk_buf_ptr_args;\n\nvoid mbedtls_ssl_set_chk_buf_ptr_fail_args(\n    const uint8_t *cur, const uint8_t *end, size_t need);\nvoid mbedtls_ssl_reset_chk_buf_ptr_fail_args(void);\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_cmp_chk_buf_ptr_fail_args(mbedtls_ssl_chk_buf_ptr_args *args);\n\nstatic inline int mbedtls_ssl_chk_buf_ptr(const uint8_t *cur,\n                                          const uint8_t *end, size_t need)\n{\n    if ((cur > end) || (need > (size_t) (end - cur))) {\n        mbedtls_ssl_set_chk_buf_ptr_fail_args(cur, end, need);\n        return 1;\n    }\n    return 0;\n}\n#endif /* MBEDTLS_TEST_HOOKS */\n\n/**\n * \\brief        This macro checks if the remaining size in a buffer is\n *               greater or equal than a needed space. If it is not the case,\n *               it returns an SSL_BUFFER_TOO_SMALL error.\n *\n * \\param cur    Pointer to the current position in the buffer.\n * \\param end    Pointer to one past the end of the buffer.\n * \\param need   Needed space in bytes.\n *\n */\n#define MBEDTLS_SSL_CHK_BUF_PTR(cur, end, need)                        \\\n    do {                                                                 \\\n        if (mbedtls_ssl_chk_buf_ptr((cur), (end), (need)) != 0) \\\n        {                                                                \\\n            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;                  \\\n        }                                                                \\\n    } while (0)\n\n/**\n * \\brief        This macro checks if the remaining length in an input buffer is\n *               greater or equal than a needed length. If it is not the case, it\n *               returns #MBEDTLS_ERR_SSL_DECODE_ERROR error and pends a\n *               #MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR alert message.\n *\n *               This is a function-like macro. It is guaranteed to evaluate each\n *               argument exactly once.\n *\n * \\param cur    Pointer to the current position in the buffer.\n * \\param end    Pointer to one past the end of the buffer.\n * \\param need   Needed length in bytes.\n *\n */\n#define MBEDTLS_SSL_CHK_BUF_READ_PTR(cur, end, need)                          \\\n    do {                                                                        \\\n        if (mbedtls_ssl_chk_buf_ptr((cur), (end), (need)) != 0)        \\\n        {                                                                       \\\n            MBEDTLS_SSL_DEBUG_MSG(1,                                           \\\n                                  (\"missing input data in %s\", __func__));  \\\n            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,   \\\n                                         MBEDTLS_ERR_SSL_DECODE_ERROR);       \\\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;                             \\\n        }                                                                       \\\n    } while (0)\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef int  mbedtls_ssl_tls_prf_cb(const unsigned char *secret, size_t slen,\n                                    const char *label,\n                                    const unsigned char *random, size_t rlen,\n                                    unsigned char *dstbuf, size_t dlen);\n\n/* cipher.h exports the maximum IV, key and block length from\n * all ciphers enabled in the config, regardless of whether those\n * ciphers are actually usable in SSL/TLS. Notably, XTS is enabled\n * in the default configuration and uses 64 Byte keys, but it is\n * not used for record protection in SSL/TLS.\n *\n * In order to prevent unnecessary inflation of key structures,\n * we introduce SSL-specific variants of the max-{key,block,IV}\n * macros here which are meant to only take those ciphers into\n * account which can be negotiated in SSL/TLS.\n *\n * Since the current definitions of MBEDTLS_MAX_{KEY|BLOCK|IV}_LENGTH\n * in cipher.h are rough overapproximations of the real maxima, here\n * we content ourselves with replicating those overapproximations\n * for the maximum block and IV length, and excluding XTS from the\n * computation of the maximum key length. */\n#define MBEDTLS_SSL_MAX_BLOCK_LENGTH 16\n#define MBEDTLS_SSL_MAX_IV_LENGTH    16\n#define MBEDTLS_SSL_MAX_KEY_LENGTH   32\n\n/**\n * \\brief   The data structure holding the cryptographic material (key and IV)\n *          used for record protection in TLS 1.3.\n */\nstruct mbedtls_ssl_key_set {\n    /*! The key for client->server records. */\n    unsigned char client_write_key[MBEDTLS_SSL_MAX_KEY_LENGTH];\n    /*! The key for server->client records. */\n    unsigned char server_write_key[MBEDTLS_SSL_MAX_KEY_LENGTH];\n    /*! The IV  for client->server records. */\n    unsigned char client_write_iv[MBEDTLS_SSL_MAX_IV_LENGTH];\n    /*! The IV  for server->client records. */\n    unsigned char server_write_iv[MBEDTLS_SSL_MAX_IV_LENGTH];\n\n    size_t key_len; /*!< The length of client_write_key and\n                     *   server_write_key, in Bytes. */\n    size_t iv_len;  /*!< The length of client_write_iv and\n                     *   server_write_iv, in Bytes. */\n};\ntypedef struct mbedtls_ssl_key_set mbedtls_ssl_key_set;\n\ntypedef struct {\n    unsigned char binder_key[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    unsigned char client_early_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    unsigned char early_exporter_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n} mbedtls_ssl_tls13_early_secrets;\n\ntypedef struct {\n    unsigned char client_handshake_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    unsigned char server_handshake_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n} mbedtls_ssl_tls13_handshake_secrets;\n\n/*\n * This structure contains the parameters only needed during handshake.\n */\nstruct mbedtls_ssl_handshake_params {\n    /* Frequently-used boolean or byte fields (placed early to take\n     * advantage of smaller code size for indirect access on Arm Thumb) */\n    uint8_t resume;                     /*!<  session resume indicator*/\n    uint8_t cli_exts;                   /*!< client extension presence*/\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    uint8_t sni_authmode;               /*!< authmode from SNI callback     */\n#endif\n\n#if defined(MBEDTLS_SSL_SRV_C)\n    /* Flag indicating if a CertificateRequest message has been sent\n     * to the client or not. */\n    uint8_t certificate_request_sent;\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    /* Flag indicating if the server has accepted early data or not. */\n    uint8_t early_data_accepted;\n#endif\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n    uint8_t new_session_ticket;         /*!< use NewSessionTicket?    */\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n#if defined(MBEDTLS_SSL_CLI_C)\n    /** Minimum TLS version to be negotiated.\n     *\n     * It is set up in the ClientHello writing preparation stage and used\n     * throughout the ClientHello writing. Not relevant anymore as soon as\n     * the protocol version has been negotiated thus as soon as the\n     * ServerHello is received.\n     * For a fresh handshake not linked to any previous handshake, it is\n     * equal to the configured minimum minor version to be negotiated. When\n     * renegotiating or resuming a session, it is equal to the previously\n     * negotiated minor version.\n     *\n     * There is no maximum TLS version field in this handshake context.\n     * From the start of the handshake, we need to define a current protocol\n     * version for the record layer which we define as the maximum TLS\n     * version to be negotiated. The `tls_version` field of the SSL context is\n     * used to store this maximum value until it contains the actual\n     * negotiated value.\n     */\n    mbedtls_ssl_protocol_version min_tls_version;\n#endif\n\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\n    uint8_t extended_ms;                /*!< use Extended Master Secret? */\n#endif\n\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)\n    uint8_t async_in_progress; /*!< an asynchronous operation is in progress */\n#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    unsigned char retransmit_state;     /*!<  Retransmission state           */\n#endif\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n    unsigned char group_list_heap_allocated;\n    unsigned char sig_algs_heap_allocated;\n#endif\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n    uint8_t ecrs_enabled;               /*!< Handshake supports EC restart? */\n    enum { /* this complements ssl->state with info on intra-state operations */\n        ssl_ecrs_none = 0,              /*!< nothing going on (yet)         */\n        ssl_ecrs_crt_verify,            /*!< Certificate: crt_verify()      */\n        ssl_ecrs_ske_start_processing,  /*!< ServerKeyExchange: pk_verify() */\n        ssl_ecrs_cke_ecdh_calc_secret,  /*!< ClientKeyExchange: ECDH step 2 */\n        ssl_ecrs_crt_vrfy_sign,         /*!< CertificateVerify: pk_sign()   */\n    } ecrs_state;                       /*!< current (or last) operation    */\n    mbedtls_x509_crt *ecrs_peer_cert;   /*!< The peer's CRT chain.          */\n    size_t ecrs_n;                      /*!< place for saving a length      */\n#endif\n\n    mbedtls_ssl_ciphersuite_t const *ciphersuite_info;\n\n    MBEDTLS_CHECK_RETURN_CRITICAL\n    int (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t);\n    MBEDTLS_CHECK_RETURN_CRITICAL\n    int (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *);\n    MBEDTLS_CHECK_RETURN_CRITICAL\n    int (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int);\n    mbedtls_ssl_tls_prf_cb *tls_prf;\n\n    /*\n     * Handshake specific crypto variables\n     */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    uint8_t key_exchange_mode; /*!< Selected key exchange mode */\n\n    /**\n     * Flag indicating if, in the course of the current handshake, an\n     * HelloRetryRequest message has been sent by the server or received by\n     * the client (<> 0) or not (0).\n     */\n    uint8_t hello_retry_request_flag;\n\n#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)\n    /**\n     * Flag indicating if, in the course of the current handshake, a dummy\n     * change_cipher_spec (CCS) record has already been sent. Used to send only\n     * one CCS per handshake while not complicating the handshake state\n     * transitions for that purpose.\n     */\n    uint8_t ccs_sent;\n#endif\n\n#if defined(MBEDTLS_SSL_SRV_C)\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n    uint8_t tls13_kex_modes; /*!< Key exchange modes supported by the client */\n#endif\n    /** selected_group of key_share extension in HelloRetryRequest message. */\n    uint16_t hrr_selected_group;\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n    uint16_t new_session_tickets_count;         /*!< number of session tickets */\n#endif\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n    uint16_t received_sig_algs[MBEDTLS_RECEIVED_SIG_ALGS_SIZE];\n#endif\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n    const uint16_t *group_list;\n    const uint16_t *sig_algs;\n#endif\n\n#if defined(MBEDTLS_DHM_C)\n    mbedtls_dhm_context dhm_ctx;                /*!<  DHM key exchange        */\n#endif\n\n#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \\\n    defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED)\n    mbedtls_ecdh_context ecdh_ctx;              /*!<  ECDH key exchange       */\n#endif /* !MBEDTLS_USE_PSA_CRYPTO &&\n          MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED)\n    psa_key_type_t xxdh_psa_type;\n    size_t xxdh_psa_bits;\n    mbedtls_svc_key_id_t xxdh_psa_privkey;\n    uint8_t xxdh_psa_privkey_is_external;\n    unsigned char xxdh_psa_peerkey[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];\n    size_t xxdh_psa_peerkey_len;\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_pake_operation_t psa_pake_ctx;        /*!< EC J-PAKE key exchange */\n    mbedtls_svc_key_id_t psa_pake_password;\n    uint8_t psa_pake_ctx_is_ok;\n#else\n    mbedtls_ecjpake_context ecjpake_ctx;        /*!< EC J-PAKE key exchange */\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#if defined(MBEDTLS_SSL_CLI_C)\n    unsigned char *ecjpake_cache;               /*!< Cache for ClientHello ext */\n    size_t ecjpake_cache_len;                   /*!< Length of cached data */\n#endif\n#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n    uint16_t *curves_tls_id;      /*!<  List of TLS IDs of supported elliptic curves */\n#endif\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    mbedtls_svc_key_id_t psk_opaque;            /*!< Opaque PSK from the callback   */\n    uint8_t psk_opaque_is_internal;\n#else\n    unsigned char *psk;                 /*!<  PSK from the callback         */\n    size_t psk_len;                     /*!<  Length of PSK from callback   */\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    uint16_t    selected_identity;\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n    mbedtls_x509_crt_restart_ctx ecrs_ctx;  /*!< restart context            */\n#endif\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n    mbedtls_ssl_key_cert *key_cert;     /*!< chosen key/cert pair (server)  */\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI         */\n    mbedtls_x509_crt *sni_ca_chain;     /*!< trusted CAs from SNI callback  */\n    mbedtls_x509_crl *sni_ca_crl;       /*!< trusted CAs CRLs from SNI      */\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C) &&        \\\n    !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    mbedtls_pk_context peer_pubkey;     /*!< The public key from the peer.  */\n#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n\n    struct {\n        size_t total_bytes_buffered; /*!< Cumulative size of heap allocated\n                                      *   buffers used for message buffering. */\n\n        uint8_t seen_ccs;               /*!< Indicates if a CCS message has\n                                         *   been seen in the current flight. */\n\n        struct mbedtls_ssl_hs_buffer {\n            unsigned is_valid      : 1;\n            unsigned is_fragmented : 1;\n            unsigned is_complete   : 1;\n            unsigned char *data;\n            size_t data_len;\n        } hs[MBEDTLS_SSL_MAX_BUFFERED_HS];\n\n        struct {\n            unsigned char *data;\n            size_t len;\n            unsigned epoch;\n        } future_record;\n\n    } buffering;\n\n#if defined(MBEDTLS_SSL_CLI_C) && \\\n    (defined(MBEDTLS_SSL_PROTO_DTLS) || \\\n    defined(MBEDTLS_SSL_PROTO_TLS1_3))\n    unsigned char *cookie;              /*!< HelloVerifyRequest cookie for DTLS\n                                         *   HelloRetryRequest cookie for TLS 1.3 */\n#if !defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    /* RFC 6347 page 15\n       ...\n       opaque cookie<0..2^8-1>;\n       ...\n     */\n    uint8_t cookie_len;\n#else\n    /* RFC 8446 page 39\n       ...\n       opaque cookie<0..2^16-1>;\n       ...\n       If TLS1_3 is enabled, the max length is 2^16 - 1\n     */\n    uint16_t cookie_len;                /*!< DTLS: HelloVerifyRequest cookie length\n                                         *   TLS1_3: HelloRetryRequest cookie length */\n#endif\n#endif /* MBEDTLS_SSL_CLI_C &&\n          ( MBEDTLS_SSL_PROTO_DTLS ||\n            MBEDTLS_SSL_PROTO_TLS1_3 ) */\n#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_DTLS)\n    unsigned char cookie_verify_result; /*!< Srv: flag for sending a cookie */\n#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_DTLS */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    unsigned int out_msg_seq;           /*!<  Outgoing handshake sequence number */\n    unsigned int in_msg_seq;            /*!<  Incoming handshake sequence number */\n\n    uint32_t retransmit_timeout;        /*!<  Current value of timeout       */\n    mbedtls_ssl_flight_item *flight;    /*!<  Current outgoing flight        */\n    mbedtls_ssl_flight_item *cur_msg;   /*!<  Current message in flight      */\n    unsigned char *cur_msg_p;           /*!<  Position in current message    */\n    unsigned int in_flight_start_seq;   /*!<  Minimum message sequence in the\n                                              flight being received          */\n    mbedtls_ssl_transform *alt_transform_out;   /*!<  Alternative transform for\n                                                   resending messages             */\n    unsigned char alt_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!<  Alternative record epoch/counter\n                                                                      for resending messages         */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    /* The state of CID configuration in this handshake. */\n\n    uint8_t cid_in_use; /*!< This indicates whether the use of the CID extension\n                         *   has been negotiated. Possible values are\n                         *   #MBEDTLS_SSL_CID_ENABLED and\n                         *   #MBEDTLS_SSL_CID_DISABLED. */\n    unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX];   /*! The peer's CID */\n    uint8_t peer_cid_len;                                  /*!< The length of\n                                                            *   \\c peer_cid.  */\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n    uint16_t mtu;                       /*!<  Handshake mtu, used to fragment outgoing messages */\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    /*\n     * Checksum contexts\n     */\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_hash_operation_t fin_sha256_psa;\n#else\n    mbedtls_md_context_t fin_sha256;\n#endif\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA384)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_hash_operation_t fin_sha384_psa;\n#else\n    mbedtls_md_context_t fin_sha384;\n#endif\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    uint16_t offered_group_id; /* The NamedGroup value for the group\n                                * that is being used for ephemeral\n                                * key exchange.\n                                *\n                                * On the client: Defaults to the first\n                                * entry in the client's group list,\n                                * but can be overwritten by the HRR. */\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#if defined(MBEDTLS_SSL_CLI_C)\n    uint8_t client_auth;       /*!< used to check if CertificateRequest has been\n                                    received from server side. If CertificateRequest\n                                    has been received, Certificate and CertificateVerify\n                                    should be sent to server */\n#endif /* MBEDTLS_SSL_CLI_C */\n    /*\n     * State-local variables used during the processing\n     * of a specific handshake state.\n     */\n    union {\n        /* Outgoing Finished message */\n        struct {\n            uint8_t preparation_done;\n\n            /* Buffer holding digest of the handshake up to\n             * but excluding the outgoing finished message. */\n            unsigned char digest[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n            size_t digest_len;\n        } finished_out;\n\n        /* Incoming Finished message */\n        struct {\n            uint8_t preparation_done;\n\n            /* Buffer holding digest of the handshake up to but\n             * excluding the peer's incoming finished message. */\n            unsigned char digest[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n            size_t digest_len;\n        } finished_in;\n\n    } state_local;\n\n    /* End of state-local variables. */\n\n    unsigned char randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN +\n                            MBEDTLS_SERVER_HELLO_RANDOM_LEN];\n    /*!<  random bytes            */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    unsigned char premaster[MBEDTLS_PREMASTER_SIZE];\n    /*!<  premaster secret        */\n    size_t pmslen;                      /*!<  premaster length        */\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    uint32_t sent_extensions;       /*!< extensions sent by endpoint */\n    uint32_t received_extensions;   /*!< extensions received by endpoint */\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n    unsigned char certificate_request_context_len;\n    unsigned char *certificate_request_context;\n#endif\n\n    /** TLS 1.3 transform for encrypted handshake messages. */\n    mbedtls_ssl_transform *transform_handshake;\n    union {\n        unsigned char early[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n        unsigned char handshake[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n        unsigned char app[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    } tls13_master_secrets;\n\n    mbedtls_ssl_tls13_handshake_secrets tls13_hs_secrets;\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    /** TLS 1.3 transform for early data and handshake messages. */\n    mbedtls_ssl_transform *transform_earlydata;\n#endif\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)\n    /** Asynchronous operation context. This field is meant for use by the\n     * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start,\n     * mbedtls_ssl_config::f_async_decrypt_start,\n     * mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel).\n     * The library does not use it internally. */\n    void *user_async_ctx;\n#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    const unsigned char *sni_name;      /*!< raw SNI                        */\n    size_t sni_name_len;                /*!< raw SNI len                    */\n#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)\n    const mbedtls_x509_crt *dn_hints;   /*!< acceptable client cert issuers */\n#endif\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n};\n\ntypedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer;\n\n/*\n * Representation of decryption/encryption transformations on records\n *\n * There are the following general types of record transformations:\n * - Stream transformations (TLS versions == 1.2 only)\n *   Transformation adding a MAC and applying a stream-cipher\n *   to the authenticated message.\n * - CBC block cipher transformations ([D]TLS versions == 1.2 only)\n *   For TLS 1.2, no IV is generated at key extraction time, but every\n *   encrypted record is explicitly prefixed by the IV with which it was\n *   encrypted.\n * - AEAD transformations ([D]TLS versions == 1.2 only)\n *   These come in two fundamentally different versions, the first one\n *   used in TLS 1.2, excluding ChaChaPoly ciphersuites, and the second\n *   one used for ChaChaPoly ciphersuites in TLS 1.2 as well as for TLS 1.3.\n *   In the first transformation, the IV to be used for a record is obtained\n *   as the concatenation of an explicit, static 4-byte IV and the 8-byte\n *   record sequence number, and explicitly prepending this sequence number\n *   to the encrypted record. In contrast, in the second transformation\n *   the IV is obtained by XOR'ing a static IV obtained at key extraction\n *   time with the 8-byte record sequence number, without prepending the\n *   latter to the encrypted record.\n *\n * Additionally, DTLS 1.2 + CID as well as TLS 1.3 use an inner plaintext\n * which allows to add flexible length padding and to hide a record's true\n * content type.\n *\n * In addition to type and version, the following parameters are relevant:\n * - The symmetric cipher algorithm to be used.\n * - The (static) encryption/decryption keys for the cipher.\n * - For stream/CBC, the type of message digest to be used.\n * - For stream/CBC, (static) encryption/decryption keys for the digest.\n * - For AEAD transformations, the size (potentially 0) of an explicit,\n *   random initialization vector placed in encrypted records.\n * - For some transformations (currently AEAD) an implicit IV. It is static\n *   and (if present) is combined with the explicit IV in a transformation-\n *   -dependent way (e.g. appending in TLS 1.2 and XOR'ing in TLS 1.3).\n * - For stream/CBC, a flag determining the order of encryption and MAC.\n * - The details of the transformation depend on the SSL/TLS version.\n * - The length of the authentication tag.\n *\n * The struct below refines this abstract view as follows:\n * - The cipher underlying the transformation is managed in\n *   cipher contexts cipher_ctx_{enc/dec}, which must have the\n *   same cipher type. The mode of these cipher contexts determines\n *   the type of the transformation in the sense above: e.g., if\n *   the type is MBEDTLS_CIPHER_AES_256_CBC resp. MBEDTLS_CIPHER_AES_192_GCM\n *   then the transformation has type CBC resp. AEAD.\n * - The cipher keys are never stored explicitly but\n *   are maintained within cipher_ctx_{enc/dec}.\n * - For stream/CBC transformations, the message digest contexts\n *   used for the MAC's are stored in md_ctx_{enc/dec}. These contexts\n *   are unused for AEAD transformations.\n * - For stream/CBC transformations, the MAC keys are not stored explicitly\n *   but maintained within md_ctx_{enc/dec}.\n * - The mac_enc and mac_dec fields are unused for EAD transformations.\n * - For transformations using an implicit IV maintained within\n *   the transformation context, its contents are stored within\n *   iv_{enc/dec}.\n * - The value of ivlen indicates the length of the IV.\n *   This is redundant in case of stream/CBC transformations\n *   which always use 0 resp. the cipher's block length as the\n *   IV length, but is needed for AEAD ciphers and may be\n *   different from the underlying cipher's block length\n *   in this case.\n * - The field fixed_ivlen is nonzero for AEAD transformations only\n *   and indicates the length of the static part of the IV which is\n *   constant throughout the communication, and which is stored in\n *   the first fixed_ivlen bytes of the iv_{enc/dec} arrays.\n * - tls_version denotes the 2-byte TLS version\n * - For stream/CBC transformations, maclen denotes the length of the\n *   authentication tag, while taglen is unused and 0.\n * - For AEAD transformations, taglen denotes the length of the\n *   authentication tag, while maclen is unused and 0.\n * - For CBC transformations, encrypt_then_mac determines the\n *   order of encryption and authentication. This field is unused\n *   in other transformations.\n *\n */\nstruct mbedtls_ssl_transform {\n    /*\n     * Session specific crypto layer\n     */\n    size_t minlen;                      /*!<  min. ciphertext length  */\n    size_t ivlen;                       /*!<  IV length               */\n    size_t fixed_ivlen;                 /*!<  Fixed part of IV (AEAD) */\n    size_t maclen;                      /*!<  MAC(CBC) len            */\n    size_t taglen;                      /*!<  TAG(AEAD) len           */\n\n    unsigned char iv_enc[16];           /*!<  IV (encryption)         */\n    unsigned char iv_dec[16];           /*!<  IV (decryption)         */\n\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    mbedtls_svc_key_id_t psa_mac_enc;           /*!<  MAC (encryption)        */\n    mbedtls_svc_key_id_t psa_mac_dec;           /*!<  MAC (decryption)        */\n    psa_algorithm_t psa_mac_alg;                /*!<  psa MAC algorithm       */\n#else\n    mbedtls_md_context_t md_ctx_enc;            /*!<  MAC (encryption)        */\n    mbedtls_md_context_t md_ctx_dec;            /*!<  MAC (decryption)        */\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n    int encrypt_then_mac;       /*!< flag for EtM activation                */\n#endif\n\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */\n\n    mbedtls_ssl_protocol_version tls_version;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    mbedtls_svc_key_id_t psa_key_enc;           /*!<  psa encryption key      */\n    mbedtls_svc_key_id_t psa_key_dec;           /*!<  psa decryption key      */\n    psa_algorithm_t psa_alg;                    /*!<  psa algorithm           */\n#else\n    mbedtls_cipher_context_t cipher_ctx_enc;    /*!<  encryption context      */\n    mbedtls_cipher_context_t cipher_ctx_dec;    /*!<  decryption context      */\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    uint8_t in_cid_len;\n    uint8_t out_cid_len;\n    unsigned char in_cid[MBEDTLS_SSL_CID_IN_LEN_MAX];\n    unsigned char out_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX];\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n#if defined(MBEDTLS_SSL_KEEP_RANDBYTES)\n    /* We need the Hello random bytes in order to re-derive keys from the\n     * Master Secret and other session info and for the keying material\n     * exporter in TLS 1.2.\n     * See ssl_tls12_populate_transform() */\n    unsigned char randbytes[MBEDTLS_SERVER_HELLO_RANDOM_LEN +\n                            MBEDTLS_CLIENT_HELLO_RANDOM_LEN];\n    /*!< ServerHello.random+ClientHello.random */\n#endif /* defined(MBEDTLS_SSL_KEEP_RANDBYTES) */\n};\n\n/*\n * Return 1 if the transform uses an AEAD cipher, 0 otherwise.\n * Equivalently, return 0 if a separate MAC is used, 1 otherwise.\n */\nstatic inline int mbedtls_ssl_transform_uses_aead(\n    const mbedtls_ssl_transform *transform)\n{\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)\n    return transform->maclen == 0 && transform->taglen != 0;\n#else\n    (void) transform;\n    return 1;\n#endif\n}\n\n/*\n * Internal representation of record frames\n *\n * Instances come in two flavors:\n * (1) Encrypted\n *     These always have data_offset = 0\n * (2) Unencrypted\n *     These have data_offset set to the amount of\n *     pre-expansion during record protection. Concretely,\n *     this is the length of the fixed part of the explicit IV\n *     used for encryption, or 0 if no explicit IV is used\n *     (e.g. for stream ciphers).\n *\n * The reason for the data_offset in the unencrypted case\n * is to allow for in-place conversion of an unencrypted to\n * an encrypted record. If the offset wasn't included, the\n * encrypted content would need to be shifted afterwards to\n * make space for the fixed IV.\n *\n */\n#if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX\n#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_OUT_LEN_MAX\n#else\n#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_IN_LEN_MAX\n#endif\n\ntypedef struct {\n    uint8_t ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN];  /* In TLS:  The implicit record sequence number.\n                                                    * In DTLS: The 2-byte epoch followed by\n                                                    *          the 6-byte sequence number.\n                                                    * This is stored as a raw big endian byte array\n                                                    * as opposed to a uint64_t because we rarely\n                                                    * need to perform arithmetic on this, but do\n                                                    * need it as a Byte array for the purpose of\n                                                    * MAC computations.                             */\n    uint8_t type;           /* The record content type.                      */\n    uint8_t ver[2];         /* SSL/TLS version as present on the wire.\n                             * Convert to internal presentation of versions\n                             * using mbedtls_ssl_read_version() and\n                             * mbedtls_ssl_write_version().\n                             * Keep wire-format for MAC computations.        */\n\n    unsigned char *buf;     /* Memory buffer enclosing the record content    */\n    size_t buf_len;         /* Buffer length                                 */\n    size_t data_offset;     /* Offset of record content                      */\n    size_t data_len;        /* Length of record content                      */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    uint8_t cid_len;        /* Length of the CID (0 if not present)          */\n    unsigned char cid[MBEDTLS_SSL_CID_LEN_MAX];   /* The CID                 */\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n} mbedtls_record;\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n/*\n * List of certificate + private key pairs\n */\nstruct mbedtls_ssl_key_cert {\n    mbedtls_x509_crt *cert;                 /*!< cert                       */\n    mbedtls_pk_context *key;                /*!< private key                */\n    mbedtls_ssl_key_cert *next;             /*!< next key/cert pair         */\n};\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n/*\n * List of handshake messages kept around for resending\n */\nstruct mbedtls_ssl_flight_item {\n    unsigned char *p;       /*!< message, including handshake headers   */\n    size_t len;             /*!< length of p                            */\n    unsigned char type;     /*!< type of the message: handshake or CCS  */\n    mbedtls_ssl_flight_item *next;  /*!< next handshake message(s)              */\n};\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n/**\n * \\brief Given an SSL context and its associated configuration, write the TLS\n *        1.2 specific extensions of the ClientHello message.\n *\n * \\param[in]   ssl     SSL context\n * \\param[in]   buf     Base address of the buffer where to write the extensions\n * \\param[in]   end     End address of the buffer where to write the extensions\n * \\param       uses_ec Whether one proposed ciphersuite uses an elliptic curve\n *                      (<> 0) or not ( 0 ).\n * \\param[out]  out_len Length of the data written into the buffer \\p buf\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls12_write_client_hello_exts(mbedtls_ssl_context *ssl,\n                                              unsigned char *buf,\n                                              const unsigned char *end,\n                                              int uses_ec,\n                                              size_t *out_len);\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \\\n    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)\n\n/**\n * \\brief Find the preferred hash for a given signature algorithm.\n *\n * \\param[in]   ssl     SSL context\n * \\param[in]   sig_alg A signature algorithm identifier as defined in the\n *                      TLS 1.2 SignatureAlgorithm enumeration.\n *\n * \\return  The preferred hash algorithm for \\p sig_alg. It is a hash algorithm\n *          identifier as defined in the TLS 1.2 HashAlgorithm enumeration.\n */\nunsigned int mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg(\n    mbedtls_ssl_context *ssl,\n    unsigned int sig_alg);\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&\n          MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */\n\n/**\n * \\brief           Free referenced items in an SSL transform context and clear\n *                  memory\n *\n * \\param transform SSL transform context\n */\nvoid mbedtls_ssl_transform_free(mbedtls_ssl_transform *transform);\n\n/**\n * \\brief           Free referenced items in an SSL handshake context and clear\n *                  memory\n *\n * \\param ssl       SSL context\n */\nvoid mbedtls_ssl_handshake_free(mbedtls_ssl_context *ssl);\n\n/* set inbound transform of ssl context */\nvoid mbedtls_ssl_set_inbound_transform(mbedtls_ssl_context *ssl,\n                                       mbedtls_ssl_transform *transform);\n\n/* set outbound transform of ssl context */\nvoid mbedtls_ssl_set_outbound_transform(mbedtls_ssl_context *ssl,\n                                        mbedtls_ssl_transform *transform);\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl);\nvoid mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl);\n\n#if defined(MBEDTLS_DEBUG_C)\n/* Declared in \"ssl_debug_helpers.h\". We can't include this file from\n * \"ssl_misc.h\" because it includes \"ssl_misc.h\" because it needs some\n * type definitions. TODO: split the type definitions and the helper\n * functions into different headers.\n */\nconst char *mbedtls_ssl_states_str(mbedtls_ssl_states state);\n#endif\n\nstatic inline void mbedtls_ssl_handshake_set_state(mbedtls_ssl_context *ssl,\n                                                   mbedtls_ssl_states state)\n{\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"handshake state: %d (%s) -> %d (%s)\",\n                              ssl->state, mbedtls_ssl_states_str(ssl->state),\n                              (int) state, mbedtls_ssl_states_str(state)));\n    ssl->state = (int) state;\n}\n\nstatic inline void mbedtls_ssl_handshake_increment_state(mbedtls_ssl_context *ssl)\n{\n    mbedtls_ssl_handshake_set_state(ssl, ssl->state + 1);\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_send_fatal_handshake_failure(mbedtls_ssl_context *ssl);\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl);\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2  */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl);\n\n/**\n * \\brief       Update record layer\n *\n *              This function roughly separates the implementation\n *              of the logic of (D)TLS from the implementation\n *              of the secure transport.\n *\n * \\param  ssl              The SSL context to use.\n * \\param  update_hs_digest This indicates if the handshake digest\n *                          should be automatically updated in case\n *                          a handshake message is found.\n *\n * \\return      0 or non-zero error code.\n *\n * \\note        A clarification on what is called 'record layer' here\n *              is in order, as many sensible definitions are possible:\n *\n *              The record layer takes as input an untrusted underlying\n *              transport (stream or datagram) and transforms it into\n *              a serially multiplexed, secure transport, which\n *              conceptually provides the following:\n *\n *              (1) Three datagram based, content-agnostic transports\n *                  for handshake, alert and CCS messages.\n *              (2) One stream- or datagram-based transport\n *                  for application data.\n *              (3) Functionality for changing the underlying transform\n *                  securing the contents.\n *\n *              The interface to this functionality is given as follows:\n *\n *              a Updating\n *                [Currently implemented by mbedtls_ssl_read_record]\n *\n *                Check if and on which of the four 'ports' data is pending:\n *                Nothing, a controlling datagram of type (1), or application\n *                data (2). In any case data is present, internal buffers\n *                provide access to the data for the user to process it.\n *                Consumption of type (1) datagrams is done automatically\n *                on the next update, invalidating that the internal buffers\n *                for previous datagrams, while consumption of application\n *                data (2) is user-controlled.\n *\n *              b Reading of application data\n *                [Currently manual adaption of ssl->in_offt pointer]\n *\n *                As mentioned in the last paragraph, consumption of data\n *                is different from the automatic consumption of control\n *                datagrams (1) because application data is treated as a stream.\n *\n *              c Tracking availability of application data\n *                [Currently manually through decreasing ssl->in_msglen]\n *\n *                For efficiency and to retain datagram semantics for\n *                application data in case of DTLS, the record layer\n *                provides functionality for checking how much application\n *                data is still available in the internal buffer.\n *\n *              d Changing the transformation securing the communication.\n *\n *              Given an opaque implementation of the record layer in the\n *              above sense, it should be possible to implement the logic\n *              of (D)TLS on top of it without the need to know anything\n *              about the record layer's internals. This is done e.g.\n *              in all the handshake handling functions, and in the\n *              application data reading function mbedtls_ssl_read.\n *\n * \\note        The above tries to give a conceptual picture of the\n *              record layer, but the current implementation deviates\n *              from it in some places. For example, our implementation of\n *              the update functionality through mbedtls_ssl_read_record\n *              discards datagrams depending on the current state, which\n *              wouldn't fall under the record layer's responsibility\n *              following the above definition.\n *\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_read_record(mbedtls_ssl_context *ssl,\n                            unsigned update_hs_digest);\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want);\n\n/*\n * Write handshake message header\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned char hs_type,\n                                    unsigned char **buf, size_t *buf_len);\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_write_handshake_msg_ext(mbedtls_ssl_context *ssl,\n                                        int update_checksum,\n                                        int force_flush);\nstatic inline int mbedtls_ssl_write_handshake_msg(mbedtls_ssl_context *ssl)\n{\n    return mbedtls_ssl_write_handshake_msg_ext(ssl, 1 /* update checksum */, 1 /* force flush */);\n}\n\n/*\n * Write handshake message tail\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_finish_handshake_msg(mbedtls_ssl_context *ssl,\n                                     size_t buf_len, size_t msg_len);\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, int force_flush);\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_flush_output(mbedtls_ssl_context *ssl);\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl);\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_write_change_cipher_spec(mbedtls_ssl_context *ssl);\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl);\n\nvoid mbedtls_ssl_optimize_checksum(mbedtls_ssl_context *ssl,\n                                   const mbedtls_ssl_ciphersuite_t *ciphersuite_info);\n\n/*\n * Update checksum of handshake messages.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl,\n                                       unsigned hs_type,\n                                       unsigned char const *msg,\n                                       size_t msg_len);\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl,\n                                       unsigned hs_type,\n                                       size_t total_hs_len);\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)\n#if !defined(MBEDTLS_USE_PSA_CRYPTO)\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl,\n                                     mbedtls_key_exchange_type_t key_ex);\n#endif /* !MBEDTLS_USE_PSA_CRYPTO */\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)\n#if defined(MBEDTLS_SSL_CLI_C) || defined(MBEDTLS_SSL_SRV_C)\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_conf_has_static_psk(mbedtls_ssl_config const *conf);\n#endif\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n/**\n * Get the first defined opaque PSK by order of precedence:\n * 1. handshake PSK set by \\c mbedtls_ssl_set_hs_psk_opaque() in the PSK\n *    callback\n * 2. static PSK configured by \\c mbedtls_ssl_conf_psk_opaque()\n * Return an opaque PSK\n */\nstatic inline mbedtls_svc_key_id_t mbedtls_ssl_get_opaque_psk(\n    const mbedtls_ssl_context *ssl)\n{\n    if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) {\n        return ssl->handshake->psk_opaque;\n    }\n\n    if (!mbedtls_svc_key_id_is_null(ssl->conf->psk_opaque)) {\n        return ssl->conf->psk_opaque;\n    }\n\n    return MBEDTLS_SVC_KEY_ID_INIT;\n}\n#else\n/**\n * Get the first defined PSK by order of precedence:\n * 1. handshake PSK set by \\c mbedtls_ssl_set_hs_psk() in the PSK callback\n * 2. static PSK configured by \\c mbedtls_ssl_conf_psk()\n * Return a code and update the pair (PSK, PSK length) passed to this function\n */\nstatic inline int mbedtls_ssl_get_psk(const mbedtls_ssl_context *ssl,\n                                      const unsigned char **psk, size_t *psk_len)\n{\n    if (ssl->handshake->psk != NULL && ssl->handshake->psk_len > 0) {\n        *psk = ssl->handshake->psk;\n        *psk_len = ssl->handshake->psk_len;\n    } else if (ssl->conf->psk != NULL && ssl->conf->psk_len > 0) {\n        *psk = ssl->conf->psk;\n        *psk_len = ssl->conf->psk_len;\n    } else {\n        *psk = NULL;\n        *psk_len = 0;\n        return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */\n\n#if defined(MBEDTLS_PK_C)\nunsigned char mbedtls_ssl_sig_from_pk(mbedtls_pk_context *pk);\nunsigned char mbedtls_ssl_sig_from_pk_alg(mbedtls_pk_type_t type);\nmbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig(unsigned char sig);\n#endif\n\nmbedtls_md_type_t mbedtls_ssl_md_alg_from_hash(unsigned char hash);\nunsigned char mbedtls_ssl_hash_from_md_alg(int md);\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md);\n#endif\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id);\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id);\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n/**\n * \\brief Return PSA EC info for the specified TLS ID.\n *\n * \\param tls_id    The TLS ID to look for\n * \\param type      If the TLD ID is supported, then proper \\c psa_key_type_t\n *                  value is returned here. Can be NULL.\n * \\param bits      If the TLD ID is supported, then proper bit size is returned\n *                  here. Can be NULL.\n * \\return          PSA_SUCCESS if the TLS ID is supported,\n *                  PSA_ERROR_NOT_SUPPORTED otherwise\n *\n * \\note            If either \\c family or \\c bits parameters are NULL, then\n *                  the corresponding value is not returned.\n *                  The function can be called with both parameters as NULL\n *                  simply to check if a specific TLS ID is supported.\n */\nint mbedtls_ssl_get_psa_curve_info_from_tls_id(uint16_t tls_id,\n                                               psa_key_type_t *type,\n                                               size_t *bits);\n\n/**\n * \\brief Return \\c mbedtls_ecp_group_id for the specified TLS ID.\n *\n * \\param tls_id    The TLS ID to look for\n * \\return          Proper \\c mbedtls_ecp_group_id if the TLS ID is supported,\n *                  or MBEDTLS_ECP_DP_NONE otherwise\n */\nmbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id(uint16_t tls_id);\n\n/**\n * \\brief Return TLS ID for the specified \\c mbedtls_ecp_group_id.\n *\n * \\param grp_id    The \\c mbedtls_ecp_group_id ID to look for\n * \\return          Proper TLS ID if the \\c mbedtls_ecp_group_id is supported,\n *                  or 0 otherwise\n */\nuint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id);\n\n#if defined(MBEDTLS_DEBUG_C)\n/**\n * \\brief Return EC's name for the specified TLS ID.\n *\n * \\param tls_id    The TLS ID to look for\n * \\return          A pointer to a const string with the proper name. If TLS\n *                  ID is not supported, a NULL pointer is returned instead.\n */\nconst char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id);\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\nstatic inline mbedtls_ssl_srtp_profile mbedtls_ssl_check_srtp_profile_value\n    (const uint16_t srtp_profile_value)\n{\n    switch (srtp_profile_value) {\n        case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80:\n        case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32:\n        case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80:\n        case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32:\n            return srtp_profile_value;\n        default: break;\n    }\n    return MBEDTLS_TLS_SRTP_UNSET;\n}\n#endif\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\nstatic inline mbedtls_pk_context *mbedtls_ssl_own_key(mbedtls_ssl_context *ssl)\n{\n    mbedtls_ssl_key_cert *key_cert;\n\n    if (ssl == NULL) return NULL;\n    if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) {\n        key_cert = ssl->handshake->key_cert;\n    } else {\n        if (ssl->conf == NULL) return NULL;\n        key_cert = ssl->conf->key_cert;\n    }\n    if (key_cert == NULL) return NULL;\n    return key_cert->key;\n}\n\nstatic inline mbedtls_x509_crt *mbedtls_ssl_own_cert(mbedtls_ssl_context *ssl)\n{\n    mbedtls_ssl_key_cert *key_cert;\n\n    if (ssl == NULL) return NULL;\n    if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) {\n        key_cert = ssl->handshake->key_cert;\n    } else {\n        if (ssl->conf == NULL) return NULL;\n        key_cert = ssl->conf->key_cert;\n    }\n    if (key_cert == NULL) return NULL;\n    return key_cert->cert;\n}\n\n/*\n * Verify a certificate.\n *\n * [in/out] ssl: misc. things read\n *               ssl->session_negotiate->verify_result updated\n * [in] authmode: one of MBEDTLS_SSL_VERIFY_{NONE,OPTIONAL,REQUIRED}\n * [in] chain: the certificate chain to verify (ie the peer's chain)\n * [in] ciphersuite_info: For TLS 1.2, this session's ciphersuite;\n *                        for TLS 1.3, may be left NULL.\n * [in] rs_ctx: restart context if restartable ECC is in use;\n *              leave NULL for no restartable behaviour.\n *\n * Return:\n * - 0 if the handshake should continue. Depending on the\n *   authmode it means:\n *   - REQUIRED: the certificate was found to be valid, trusted & acceptable.\n *     ssl->session_negotiate->verify_result is 0.\n *   - OPTIONAL: the certificate may or may not be acceptable, but\n *     ssl->session_negotiate->verify_result was updated with the result.\n *   - NONE: the certificate wasn't even checked.\n * - MBEDTLS_ERR_X509_CERT_VERIFY_FAILED or MBEDTLS_ERR_SSL_BAD_CERTIFICATE if\n *   the certificate was found to be invalid/untrusted/unacceptable and the\n *   handshake should be aborted (can only happen with REQUIRED).\n * - another error code if another error happened (out-of-memory, etc.)\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_verify_certificate(mbedtls_ssl_context *ssl,\n                                   int authmode,\n                                   mbedtls_x509_crt *chain,\n                                   const mbedtls_ssl_ciphersuite_t *ciphersuite_info,\n                                   void *rs_ctx);\n\n/*\n * Check usage of a certificate wrt usage extensions:\n * keyUsage and extendedKeyUsage.\n * (Note: nSCertType is deprecated and not standard, we don't check it.)\n *\n * Note: if tls_version is 1.3, ciphersuite is ignored and can be NULL.\n *\n * Note: recv_endpoint is the receiver's endpoint.\n *\n * Return 0 if everything is OK, -1 if not.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert,\n                                 const mbedtls_ssl_ciphersuite_t *ciphersuite,\n                                 int recv_endpoint,\n                                 mbedtls_ssl_protocol_version tls_version,\n                                 uint32_t *flags);\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\nvoid mbedtls_ssl_write_version(unsigned char version[2], int transport,\n                               mbedtls_ssl_protocol_version tls_version);\nuint16_t mbedtls_ssl_read_version(const unsigned char version[2],\n                                  int transport);\n\nstatic inline size_t mbedtls_ssl_in_hdr_len(const mbedtls_ssl_context *ssl)\n{\n#if !defined(MBEDTLS_SSL_PROTO_DTLS)\n    ((void) ssl);\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        return 13;\n    } else\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n    {\n        return 5;\n    }\n}\n\nstatic inline size_t mbedtls_ssl_out_hdr_len(const mbedtls_ssl_context *ssl)\n{\n    return (size_t) (ssl->out_iv - ssl->out_hdr);\n}\n\nstatic inline size_t mbedtls_ssl_hs_hdr_len(const mbedtls_ssl_context *ssl)\n{\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        return 12;\n    }\n#else\n    ((void) ssl);\n#endif\n    return 4;\n}\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\nvoid mbedtls_ssl_send_flight_completed(mbedtls_ssl_context *ssl);\nvoid mbedtls_ssl_recv_flight_completed(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_resend(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_flight_transmit(mbedtls_ssl_context *ssl);\n#endif\n\n/* Visible for testing purposes only */\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_dtls_replay_check(mbedtls_ssl_context const *ssl);\nvoid mbedtls_ssl_dtls_replay_update(mbedtls_ssl_context *ssl);\n#endif\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_session_copy(mbedtls_ssl_session *dst,\n                             const mbedtls_ssl_session *src);\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n/* The hash buffer must have at least MBEDTLS_MD_MAX_SIZE bytes of length. */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl,\n                                           unsigned char *hash, size_t *hashlen,\n                                           unsigned char *data, size_t data_len,\n                                           mbedtls_md_type_t md_alg);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n#ifdef __cplusplus\n}\n#endif\n\nvoid mbedtls_ssl_transform_init(mbedtls_ssl_transform *transform);\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl,\n                            mbedtls_ssl_transform *transform,\n                            mbedtls_record *rec,\n                            int (*f_rng)(void *, unsigned char *, size_t),\n                            void *p_rng);\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl,\n                            mbedtls_ssl_transform *transform,\n                            mbedtls_record *rec);\n\n/* Length of the \"epoch\" field in the record header */\nstatic inline size_t mbedtls_ssl_ep_len(const mbedtls_ssl_context *ssl)\n{\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        return 2;\n    }\n#else\n    ((void) ssl);\n#endif\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_resend_hello_request(mbedtls_ssl_context *ssl);\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\nvoid mbedtls_ssl_set_timer(mbedtls_ssl_context *ssl, uint32_t millisecs);\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_check_timer(mbedtls_ssl_context *ssl);\n\nvoid mbedtls_ssl_reset_in_pointers(mbedtls_ssl_context *ssl);\nvoid mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl);\nvoid mbedtls_ssl_reset_out_pointers(mbedtls_ssl_context *ssl);\nvoid mbedtls_ssl_update_out_pointers(mbedtls_ssl_context *ssl,\n                                     mbedtls_ssl_transform *transform);\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial);\nvoid mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl,\n                                         int partial);\n\n/*\n * Send pending alert\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_handle_pending_alert(mbedtls_ssl_context *ssl);\n\n/*\n * Set pending fatal alert flag.\n */\nvoid mbedtls_ssl_pend_fatal_alert(mbedtls_ssl_context *ssl,\n                                  unsigned char alert_type,\n                                  int alert_reason);\n\n/* Alias of mbedtls_ssl_pend_fatal_alert */\n#define MBEDTLS_SSL_PEND_FATAL_ALERT(type, user_return_value)         \\\n    mbedtls_ssl_pend_fatal_alert(ssl, type, user_return_value)\n\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\nvoid mbedtls_ssl_dtls_replay_reset(mbedtls_ssl_context *ssl);\n#endif\n\nvoid mbedtls_ssl_handshake_wrapup_free_hs_transform(mbedtls_ssl_context *ssl);\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_start_renegotiation(mbedtls_ssl_context *ssl);\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\nsize_t mbedtls_ssl_get_current_mtu(const mbedtls_ssl_context *ssl);\nvoid mbedtls_ssl_buffering_free(mbedtls_ssl_context *ssl);\nvoid mbedtls_ssl_flight_free(mbedtls_ssl_flight_item *flight);\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n/**\n * ssl utils functions for checking configuration.\n */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\nstatic inline int mbedtls_ssl_conf_is_tls13_only(const mbedtls_ssl_config *conf)\n{\n    return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 &&\n           conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3;\n}\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\nstatic inline int mbedtls_ssl_conf_is_tls12_only(const mbedtls_ssl_config *conf)\n{\n    return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&\n           conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_2;\n}\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\nstatic inline int mbedtls_ssl_conf_is_tls13_enabled(const mbedtls_ssl_config *conf)\n{\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    return conf->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3 &&\n           conf->max_tls_version >= MBEDTLS_SSL_VERSION_TLS1_3;\n#else\n    ((void) conf);\n    return 0;\n#endif\n}\n\nstatic inline int mbedtls_ssl_conf_is_tls12_enabled(const mbedtls_ssl_config *conf)\n{\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    return conf->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2 &&\n           conf->max_tls_version >= MBEDTLS_SSL_VERSION_TLS1_2;\n#else\n    ((void) conf);\n    return 0;\n#endif\n}\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3)\nstatic inline int mbedtls_ssl_conf_is_hybrid_tls12_tls13(const mbedtls_ssl_config *conf)\n{\n    return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&\n           conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3;\n}\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n\n/** \\brief Initialize the PSA crypto subsystem if necessary.\n *\n * Call this function before doing any cryptography in a TLS 1.3 handshake.\n *\n * This is necessary in Mbed TLS 3.x for backward compatibility.\n * Up to Mbed TLS 3.5, in the default configuration, you could perform\n * a TLS connection with default parameters without having called\n * psa_crypto_init(), since the TLS layer only supported TLS 1.2 and\n * did not use PSA crypto. (TLS 1.2 only uses PSA crypto if\n * MBEDTLS_USE_PSA_CRYPTO is enabled, which is not the case in the default\n * configuration.) Starting with Mbed TLS 3.6.0, TLS 1.3 is enabled\n * by default, and the TLS 1.3 layer uses PSA crypto. This means that\n * applications that are not otherwise using PSA crypto and that worked\n * with Mbed TLS 3.5 started failing in TLS 3.6.0 if they connected to\n * a peer that supports TLS 1.3. See\n * https://github.com/Mbed-TLS/mbedtls/issues/9072\n */\nint mbedtls_ssl_tls13_crypto_init(mbedtls_ssl_context *ssl);\n\nextern const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[\n    MBEDTLS_SERVER_HELLO_RANDOM_LEN];\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_process_finished_message(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_write_finished_message(mbedtls_ssl_context *ssl);\nvoid mbedtls_ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl);\n\n/**\n * \\brief Given an SSL context and its associated configuration, write the TLS\n *        1.3 specific extensions of the ClientHello message.\n *\n * \\param[in]   ssl     SSL context\n * \\param[in]   buf     Base address of the buffer where to write the extensions\n * \\param[in]   end     End address of the buffer where to write the extensions\n * \\param[out]  out_len Length of the data written into the buffer \\p buf\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl,\n                                              unsigned char *buf,\n                                              unsigned char *end,\n                                              size_t *out_len);\n\n/**\n * \\brief           TLS 1.3 client side state machine entry\n *\n * \\param ssl       SSL context\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl);\n\n/**\n * \\brief           TLS 1.3 server side state machine entry\n *\n * \\param ssl       SSL context\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl);\n\n\n/*\n * Helper functions around key exchange modes.\n */\nstatic inline int mbedtls_ssl_conf_tls13_is_kex_mode_enabled(mbedtls_ssl_context *ssl,\n                                                             int kex_mode_mask)\n{\n    return (ssl->conf->tls13_kex_modes & kex_mode_mask) != 0;\n}\n\nstatic inline int mbedtls_ssl_conf_tls13_is_psk_enabled(mbedtls_ssl_context *ssl)\n{\n    return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl,\n                                                      MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK);\n}\n\nstatic inline int mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(mbedtls_ssl_context *ssl)\n{\n    return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl,\n                                                      MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL);\n}\n\nstatic inline int mbedtls_ssl_conf_tls13_is_ephemeral_enabled(mbedtls_ssl_context *ssl)\n{\n    return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl,\n                                                      MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL);\n}\n\nstatic inline int mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(mbedtls_ssl_context *ssl)\n{\n    return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl,\n                                                      MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL);\n}\n\nstatic inline int mbedtls_ssl_conf_tls13_is_some_psk_enabled(mbedtls_ssl_context *ssl)\n{\n    return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl,\n                                                      MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL);\n}\n\n#if defined(MBEDTLS_SSL_SRV_C) && \\\n    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n/**\n * Given a list of key exchange modes, check if at least one of them is\n * supported by peer.\n *\n * \\param[in] ssl  SSL context\n * \\param kex_modes_mask  Mask of the key exchange modes to check\n *\n * \\return Non-zero if at least one of the key exchange modes is supported by\n *         the peer, otherwise \\c 0.\n */\nstatic inline int mbedtls_ssl_tls13_is_kex_mode_supported(mbedtls_ssl_context *ssl,\n                                                          int kex_modes_mask)\n{\n    return (ssl->handshake->tls13_kex_modes & kex_modes_mask) != 0;\n}\n\nstatic inline int mbedtls_ssl_tls13_is_psk_supported(mbedtls_ssl_context *ssl)\n{\n    return mbedtls_ssl_tls13_is_kex_mode_supported(ssl,\n                                                   MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK);\n}\n\nstatic inline int mbedtls_ssl_tls13_is_psk_ephemeral_supported(\n    mbedtls_ssl_context *ssl)\n{\n    return mbedtls_ssl_tls13_is_kex_mode_supported(ssl,\n                                                   MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL);\n}\n\nstatic inline int mbedtls_ssl_tls13_is_ephemeral_supported(mbedtls_ssl_context *ssl)\n{\n    return mbedtls_ssl_tls13_is_kex_mode_supported(ssl,\n                                                   MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL);\n}\n\nstatic inline int mbedtls_ssl_tls13_is_some_ephemeral_supported(mbedtls_ssl_context *ssl)\n{\n    return mbedtls_ssl_tls13_is_kex_mode_supported(ssl,\n                                                   MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL);\n}\n\nstatic inline int mbedtls_ssl_tls13_is_some_psk_supported(mbedtls_ssl_context *ssl)\n{\n    return mbedtls_ssl_tls13_is_kex_mode_supported(ssl,\n                                                   MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL);\n}\n#endif /* MBEDTLS_SSL_SRV_C &&\n          MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */\n\n/*\n * Helper functions for extensions checking.\n */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_check_received_extension(\n    mbedtls_ssl_context *ssl,\n    int hs_msg_type,\n    unsigned int received_extension_type,\n    uint32_t hs_msg_allowed_extensions_mask);\n\nstatic inline void mbedtls_ssl_tls13_set_hs_sent_ext_mask(\n    mbedtls_ssl_context *ssl, unsigned int extension_type)\n{\n    ssl->handshake->sent_extensions |=\n        mbedtls_ssl_get_extension_mask(extension_type);\n}\n\n/*\n * Helper functions to check the selected key exchange mode.\n */\nstatic inline int mbedtls_ssl_tls13_key_exchange_mode_check(\n    mbedtls_ssl_context *ssl, int kex_mask)\n{\n    return (ssl->handshake->key_exchange_mode & kex_mask) != 0;\n}\n\nstatic inline int mbedtls_ssl_tls13_key_exchange_mode_with_psk(\n    mbedtls_ssl_context *ssl)\n{\n    return mbedtls_ssl_tls13_key_exchange_mode_check(ssl,\n                                                     MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL);\n}\n\nstatic inline int mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(\n    mbedtls_ssl_context *ssl)\n{\n    return mbedtls_ssl_tls13_key_exchange_mode_check(ssl,\n                                                     MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL);\n}\n\n/*\n * Fetch TLS 1.3 handshake message header\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl,\n                                          unsigned hs_type,\n                                          unsigned char **buf,\n                                          size_t *buf_len);\n\n/**\n * \\brief Detect if a list of extensions contains a supported_versions\n *        extension or not.\n *\n * \\param[in] ssl  SSL context\n * \\param[in] buf  Address of the first byte of the extensions vector.\n * \\param[in] end  End of the buffer containing the list of extensions.\n * \\param[out] supported_versions_data  If the extension is present, address of\n *                                      its first byte of data, NULL otherwise.\n * \\param[out] supported_versions_data_end  If the extension is present, address\n *                                          of the first byte immediately\n *                                          following the extension data, NULL\n *                                          otherwise.\n * \\return 0  if the list of extensions does not contain a supported_versions\n *            extension.\n * \\return 1  if the list of extensions contains a supported_versions\n *            extension.\n * \\return    A negative value if an error occurred while parsing the\n *            extensions.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts(\n    mbedtls_ssl_context *ssl,\n    const unsigned char *buf, const unsigned char *end,\n    const unsigned char **supported_versions_data,\n    const unsigned char **supported_versions_data_end);\n\n/*\n * Handler of TLS 1.3 server certificate message\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_process_certificate(mbedtls_ssl_context *ssl);\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n/*\n * Handler of TLS 1.3 write Certificate message\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_write_certificate(mbedtls_ssl_context *ssl);\n\n/*\n * Handler of TLS 1.3 write Certificate Verify message\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl);\n\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\n/*\n * Generic handler of Certificate Verify\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl);\n\n/*\n * Write of dummy-CCS's for middlebox compatibility\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl);\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl);\n\n#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange(\n    mbedtls_ssl_context *ssl,\n    uint16_t named_group,\n    unsigned char *buf,\n    unsigned char *end,\n    size_t *out_len);\n#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\nint mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl,\n                                           int in_new_session_ticket,\n                                           unsigned char *buf,\n                                           const unsigned char *end,\n                                           size_t *out_len);\n\nint mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl,\n                                           size_t early_data_len);\n\ntypedef enum {\n/*\n * The client has not sent the first ClientHello yet, the negotiation of early\n * data has not started yet.\n */\n    MBEDTLS_SSL_EARLY_DATA_STATE_IDLE,\n\n/*\n * In its ClientHello, the client has not included an early data indication\n * extension.\n */\n    MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT,\n\n/*\n * The client has sent an early data indication extension in its first\n * ClientHello, it has not received the response (ServerHello or\n * HelloRetryRequest) from the server yet. The transform to protect early data\n * is not set either as for middlebox compatibility a dummy CCS may have to be\n * sent in clear. Early data cannot be sent to the server yet.\n */\n    MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT,\n\n/*\n * The client has sent an early data indication extension in its first\n * ClientHello, it has not received the response (ServerHello or\n * HelloRetryRequest) from the server yet. The transform to protect early data\n * has been set and early data can be written now.\n */\n    MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE,\n\n/*\n * The client has indicated the use of early data and the server has accepted\n * it.\n */\n    MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED,\n\n/*\n * The client has indicated the use of early data but the server has rejected\n * it.\n */\n    MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED,\n\n/*\n * The client has sent an early data indication extension in its first\n * ClientHello, the server has accepted them and the client has received the\n * server Finished message. It cannot send early data to the server anymore.\n */\n    MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED,\n\n} mbedtls_ssl_early_data_state;\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n/*\n * Write Signature Algorithm extension\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_write_sig_alg_ext(mbedtls_ssl_context *ssl, unsigned char *buf,\n                                  const unsigned char *end, size_t *out_len);\n/*\n * Parse TLS Signature Algorithm extension\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_parse_sig_alg_ext(mbedtls_ssl_context *ssl,\n                                  const unsigned char *buf,\n                                  const unsigned char *end);\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n/* Get handshake transcript */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl,\n                                         const mbedtls_md_type_t md,\n                                         unsigned char *dst,\n                                         size_t dst_len,\n                                         size_t *olen);\n\n/*\n * Return supported groups.\n *\n * In future, invocations can be changed to ssl->conf->group_list\n * when mbedtls_ssl_conf_curves() is deleted.\n *\n * ssl->handshake->group_list is either a translation of curve_list to IANA TLS group\n * identifiers when mbedtls_ssl_conf_curves() has been used, or a pointer to\n * ssl->conf->group_list when mbedtls_ssl_conf_groups() has been more recently invoked.\n *\n */\nstatic inline const void *mbedtls_ssl_get_groups(const mbedtls_ssl_context *ssl)\n{\n    #if defined(MBEDTLS_DEPRECATED_REMOVED) || !defined(MBEDTLS_ECP_C)\n    return ssl->conf->group_list;\n    #else\n    if ((ssl->handshake != NULL) && (ssl->handshake->group_list != NULL)) {\n        return ssl->handshake->group_list;\n    } else {\n        return ssl->conf->group_list;\n    }\n    #endif\n}\n\n/*\n * Helper functions for NamedGroup.\n */\nstatic inline int mbedtls_ssl_tls12_named_group_is_ecdhe(uint16_t named_group)\n{\n    /*\n     * RFC 8422 section 5.1.1\n     */\n    return named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X25519    ||\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1   ||\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1   ||\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1   ||\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X448      ||\n           /* Below deprecated curves should be removed with notice to users */\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1 ||\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1 ||\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1 ||\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1 ||\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1 ||\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 ||\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 ||\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1;\n}\n\nstatic inline int mbedtls_ssl_tls13_named_group_is_ecdhe(uint16_t named_group)\n{\n    return named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X25519    ||\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 ||\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 ||\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1 ||\n           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X448;\n}\n\nstatic inline int mbedtls_ssl_tls13_named_group_is_ffdh(uint16_t named_group)\n{\n    return named_group >= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048 &&\n           named_group <= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192;\n}\n\nstatic inline int mbedtls_ssl_named_group_is_offered(\n    const mbedtls_ssl_context *ssl, uint16_t named_group)\n{\n    const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);\n\n    if (group_list == NULL) {\n        return 0;\n    }\n\n    for (; *group_list != 0; group_list++) {\n        if (*group_list == named_group) {\n            return 1;\n        }\n    }\n\n    return 0;\n}\n\nstatic inline int mbedtls_ssl_named_group_is_supported(uint16_t named_group)\n{\n#if defined(PSA_WANT_ALG_ECDH)\n    if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group)) {\n        if (mbedtls_ssl_get_ecp_group_id_from_tls_id(named_group) !=\n            MBEDTLS_ECP_DP_NONE) {\n            return 1;\n        }\n    }\n#endif\n#if defined(PSA_WANT_ALG_FFDH)\n    if (mbedtls_ssl_tls13_named_group_is_ffdh(named_group)) {\n        return 1;\n    }\n#endif\n#if !defined(PSA_WANT_ALG_ECDH) && !defined(PSA_WANT_ALG_FFDH)\n    (void) named_group;\n#endif\n    return 0;\n}\n\n/*\n * Return supported signature algorithms.\n *\n * In future, invocations can be changed to ssl->conf->sig_algs when\n * mbedtls_ssl_conf_sig_hashes() is deleted.\n *\n * ssl->handshake->sig_algs is either a translation of sig_hashes to IANA TLS\n * signature algorithm identifiers when mbedtls_ssl_conf_sig_hashes() has been\n * used, or a pointer to ssl->conf->sig_algs when mbedtls_ssl_conf_sig_algs() has\n * been more recently invoked.\n *\n */\nstatic inline const void *mbedtls_ssl_get_sig_algs(\n    const mbedtls_ssl_context *ssl)\n{\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ssl->handshake != NULL &&\n        ssl->handshake->sig_algs_heap_allocated == 1 &&\n        ssl->handshake->sig_algs != NULL) {\n        return ssl->handshake->sig_algs;\n    }\n#endif\n    return ssl->conf->sig_algs;\n\n#else /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n    ((void) ssl);\n    return NULL;\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n}\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\nstatic inline int mbedtls_ssl_sig_alg_is_received(const mbedtls_ssl_context *ssl,\n                                                  uint16_t own_sig_alg)\n{\n    const uint16_t *sig_alg = ssl->handshake->received_sig_algs;\n    if (sig_alg == NULL) {\n        return 0;\n    }\n\n    for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) {\n        if (*sig_alg == own_sig_alg) {\n            return 1;\n        }\n    }\n    return 0;\n}\n\nstatic inline int mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(\n    const uint16_t sig_alg)\n{\n    switch (sig_alg) {\n#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)\n#if defined(PSA_WANT_ALG_SHA_256) && defined(PSA_WANT_ECC_SECP_R1_256)\n        case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256:\n            break;\n#endif /* PSA_WANT_ALG_SHA_256 && MBEDTLS_ECP_DP_SECP256R1_ENABLED */\n#if defined(PSA_WANT_ALG_SHA_384) && defined(PSA_WANT_ECC_SECP_R1_384)\n        case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384:\n            break;\n#endif /* PSA_WANT_ALG_SHA_384 && MBEDTLS_ECP_DP_SECP384R1_ENABLED */\n#if defined(PSA_WANT_ALG_SHA_512) && defined(PSA_WANT_ECC_SECP_R1_521)\n        case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512:\n            break;\n#endif /* PSA_WANT_ALG_SHA_512 && MBEDTLS_ECP_DP_SECP521R1_ENABLED */\n#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */\n\n#if defined(MBEDTLS_PKCS1_V21)\n#if defined(PSA_WANT_ALG_SHA_256)\n        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256:\n            break;\n#endif /* PSA_WANT_ALG_SHA_256  */\n#if defined(PSA_WANT_ALG_SHA_384)\n        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384:\n            break;\n#endif /* PSA_WANT_ALG_SHA_384 */\n#if defined(PSA_WANT_ALG_SHA_512)\n        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512:\n            break;\n#endif /* PSA_WANT_ALG_SHA_512 */\n#endif /* MBEDTLS_PKCS1_V21 */\n        default:\n            return 0;\n    }\n    return 1;\n\n}\n\nstatic inline int mbedtls_ssl_tls13_sig_alg_is_supported(\n    const uint16_t sig_alg)\n{\n    switch (sig_alg) {\n#if defined(MBEDTLS_PKCS1_V15)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n        case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256:\n            break;\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n        case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384:\n            break;\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#if defined(MBEDTLS_MD_CAN_SHA512)\n        case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512:\n            break;\n#endif /* MBEDTLS_MD_CAN_SHA512 */\n#endif /* MBEDTLS_PKCS1_V15 */\n        default:\n            return mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(\n                sig_alg);\n    }\n    return 1;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_check_sig_alg_cert_key_match(uint16_t sig_alg,\n                                                   mbedtls_pk_context *key);\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\nstatic inline int mbedtls_ssl_sig_alg_is_offered(const mbedtls_ssl_context *ssl,\n                                                 uint16_t proposed_sig_alg)\n{\n    const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl);\n    if (sig_alg == NULL) {\n        return 0;\n    }\n\n    for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) {\n        if (*sig_alg == proposed_sig_alg) {\n            return 1;\n        }\n    }\n    return 0;\n}\n\nstatic inline int mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg(\n    uint16_t sig_alg, mbedtls_pk_type_t *pk_type, mbedtls_md_type_t *md_alg)\n{\n    *pk_type = mbedtls_ssl_pk_alg_from_sig(sig_alg & 0xff);\n    *md_alg = mbedtls_ssl_md_alg_from_hash((sig_alg >> 8) & 0xff);\n\n    if (*pk_type != MBEDTLS_PK_NONE && *md_alg != MBEDTLS_MD_NONE) {\n        return 0;\n    }\n\n    switch (sig_alg) {\n#if defined(MBEDTLS_PKCS1_V21)\n#if defined(MBEDTLS_MD_CAN_SHA256)\n        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256:\n            *md_alg = MBEDTLS_MD_SHA256;\n            *pk_type = MBEDTLS_PK_RSASSA_PSS;\n            break;\n#endif /* MBEDTLS_MD_CAN_SHA256  */\n#if defined(MBEDTLS_MD_CAN_SHA384)\n        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384:\n            *md_alg = MBEDTLS_MD_SHA384;\n            *pk_type = MBEDTLS_PK_RSASSA_PSS;\n            break;\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n#if defined(MBEDTLS_MD_CAN_SHA512)\n        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512:\n            *md_alg = MBEDTLS_MD_SHA512;\n            *pk_type = MBEDTLS_PK_RSASSA_PSS;\n            break;\n#endif /* MBEDTLS_MD_CAN_SHA512 */\n#endif /* MBEDTLS_PKCS1_V21 */\n        default:\n            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    }\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\nstatic inline int mbedtls_ssl_tls12_sig_alg_is_supported(\n    const uint16_t sig_alg)\n{\n    /* High byte is hash */\n    unsigned char hash = MBEDTLS_BYTE_1(sig_alg);\n    unsigned char sig = MBEDTLS_BYTE_0(sig_alg);\n\n    switch (hash) {\n#if defined(MBEDTLS_MD_CAN_MD5)\n        case MBEDTLS_SSL_HASH_MD5:\n            break;\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA1)\n        case MBEDTLS_SSL_HASH_SHA1:\n            break;\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA224)\n        case MBEDTLS_SSL_HASH_SHA224:\n            break;\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n        case MBEDTLS_SSL_HASH_SHA256:\n            break;\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n        case MBEDTLS_SSL_HASH_SHA384:\n            break;\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA512)\n        case MBEDTLS_SSL_HASH_SHA512:\n            break;\n#endif\n\n        default:\n            return 0;\n    }\n\n    switch (sig) {\n#if defined(MBEDTLS_RSA_C)\n        case MBEDTLS_SSL_SIG_RSA:\n            break;\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)\n        case MBEDTLS_SSL_SIG_ECDSA:\n            break;\n#endif\n\n        default:\n            return 0;\n    }\n\n    return 1;\n}\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\nstatic inline int mbedtls_ssl_sig_alg_is_supported(\n    const mbedtls_ssl_context *ssl,\n    const uint16_t sig_alg)\n{\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {\n        return mbedtls_ssl_tls12_sig_alg_is_supported(sig_alg);\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {\n        return mbedtls_ssl_tls13_sig_alg_is_supported(sig_alg);\n    }\n#endif\n    ((void) ssl);\n    ((void) sig_alg);\n    return 0;\n}\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)\n/* Corresponding PSA algorithm for MBEDTLS_CIPHER_NULL.\n * Same value is used for PSA_ALG_CATEGORY_CIPHER, hence it is\n * guaranteed to not be a valid PSA algorithm identifier.\n */\n#define MBEDTLS_SSL_NULL_CIPHER 0x04000000\n\n/**\n * \\brief       Translate mbedtls cipher type/taglen pair to psa:\n *              algorithm, key type and key size.\n *\n * \\param  mbedtls_cipher_type [in] given mbedtls cipher type\n * \\param  taglen              [in] given tag length\n *                                  0 - default tag length\n * \\param  alg                 [out] corresponding PSA alg\n *                                   There is no corresponding PSA\n *                                   alg for MBEDTLS_CIPHER_NULL, so\n *                                   in this case MBEDTLS_SSL_NULL_CIPHER\n *                                   is returned via this parameter\n * \\param  key_type            [out] corresponding PSA key type\n * \\param  key_size            [out] corresponding PSA key size\n *\n * \\return                     PSA_SUCCESS on success or PSA_ERROR_NOT_SUPPORTED if\n *                             conversion is not supported.\n */\npsa_status_t mbedtls_ssl_cipher_to_psa(mbedtls_cipher_type_t mbedtls_cipher_type,\n                                       size_t taglen,\n                                       psa_algorithm_t *alg,\n                                       psa_key_type_t *key_type,\n                                       size_t *key_size);\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n/**\n * \\brief       Convert given PSA status to mbedtls error code.\n *\n * \\param  status      [in] given PSA status\n *\n * \\return             corresponding mbedtls error code\n */\nstatic inline MBEDTLS_DEPRECATED int psa_ssl_status_to_mbedtls(psa_status_t status)\n{\n    switch (status) {\n        case PSA_SUCCESS:\n            return 0;\n        case PSA_ERROR_INSUFFICIENT_MEMORY:\n            return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        case PSA_ERROR_NOT_SUPPORTED:\n            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n        case PSA_ERROR_INVALID_SIGNATURE:\n            return MBEDTLS_ERR_SSL_INVALID_MAC;\n        case PSA_ERROR_INVALID_ARGUMENT:\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        case PSA_ERROR_BAD_STATE:\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        case PSA_ERROR_BUFFER_TOO_SMALL:\n            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n        default:\n            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;\n    }\n}\n#endif /* !MBEDTLS_DEPRECATED_REMOVED */\n#endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \\\n    defined(MBEDTLS_USE_PSA_CRYPTO)\n\ntypedef enum {\n    MBEDTLS_ECJPAKE_ROUND_ONE,\n    MBEDTLS_ECJPAKE_ROUND_TWO\n} mbedtls_ecjpake_rounds_t;\n\n/**\n * \\brief       Parse the provided input buffer for getting the first round\n *              of key exchange. This code is common between server and client\n *\n * \\param  pake_ctx [in] the PAKE's operation/context structure\n * \\param  buf      [in] input buffer to parse\n * \\param  len      [in] length of the input buffer\n * \\param  round    [in] either MBEDTLS_ECJPAKE_ROUND_ONE or\n *                       MBEDTLS_ECJPAKE_ROUND_TWO\n *\n * \\return               0 on success or a negative error code in case of failure\n */\nint mbedtls_psa_ecjpake_read_round(\n    psa_pake_operation_t *pake_ctx,\n    const unsigned char *buf,\n    size_t len, mbedtls_ecjpake_rounds_t round);\n\n/**\n * \\brief       Write the first round of key exchange into the provided output\n *              buffer. This code is common between server and client\n *\n * \\param  pake_ctx [in] the PAKE's operation/context structure\n * \\param  buf      [out] the output buffer in which data will be written to\n * \\param  len      [in] length of the output buffer\n * \\param  olen     [out] the length of the data really written on the buffer\n * \\param  round    [in] either MBEDTLS_ECJPAKE_ROUND_ONE or\n *                       MBEDTLS_ECJPAKE_ROUND_TWO\n *\n * \\return               0 on success or a negative error code in case of failure\n */\nint mbedtls_psa_ecjpake_write_round(\n    psa_pake_operation_t *pake_ctx,\n    unsigned char *buf,\n    size_t len, size_t *olen,\n    mbedtls_ecjpake_rounds_t round);\n\n#endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO\n\n/**\n * \\brief       TLS record protection modes\n */\ntypedef enum {\n    MBEDTLS_SSL_MODE_STREAM = 0,\n    MBEDTLS_SSL_MODE_CBC,\n    MBEDTLS_SSL_MODE_CBC_ETM,\n    MBEDTLS_SSL_MODE_AEAD\n} mbedtls_ssl_mode_t;\n\nmbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_transform(\n    const mbedtls_ssl_transform *transform);\n\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)\nmbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite(\n    int encrypt_then_mac,\n    const mbedtls_ssl_ciphersuite_t *suite);\n#else\nmbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite(\n    const mbedtls_ssl_ciphersuite_t *suite);\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */\n\n#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_read_public_xxdhe_share(mbedtls_ssl_context *ssl,\n                                              const unsigned char *buf,\n                                              size_t buf_len);\n\n#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */\n\nstatic inline int mbedtls_ssl_tls13_cipher_suite_is_offered(\n    mbedtls_ssl_context *ssl, int cipher_suite)\n{\n    const int *ciphersuite_list = ssl->conf->ciphersuite_list;\n\n    /* Check whether we have offered this ciphersuite */\n    for (size_t i = 0; ciphersuite_list[i] != 0; i++) {\n        if (ciphersuite_list[i] == cipher_suite) {\n            return 1;\n        }\n    }\n    return 0;\n}\n\n/**\n * \\brief Validate cipher suite against config in SSL context.\n *\n * \\param ssl              SSL context\n * \\param suite_info       Cipher suite to validate\n * \\param min_tls_version  Minimal TLS version to accept a cipher suite\n * \\param max_tls_version  Maximal TLS version to accept a cipher suite\n *\n * \\return 0 if valid, negative value otherwise.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_validate_ciphersuite(\n    const mbedtls_ssl_context *ssl,\n    const mbedtls_ssl_ciphersuite_t *suite_info,\n    mbedtls_ssl_protocol_version min_tls_version,\n    mbedtls_ssl_protocol_version max_tls_version);\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_parse_server_name_ext(mbedtls_ssl_context *ssl,\n                                      const unsigned char *buf,\n                                      const unsigned char *end);\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n#define MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH (2)\n#define MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN (64)      /* As defined in RFC 8449 */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl,\n                                                  const unsigned char *buf,\n                                                  const unsigned char *end);\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_write_record_size_limit_ext(mbedtls_ssl_context *ssl,\n                                                  unsigned char *buf,\n                                                  const unsigned char *end,\n                                                  size_t *out_len);\n#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */\n\n#if defined(MBEDTLS_SSL_ALPN)\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_parse_alpn_ext(mbedtls_ssl_context *ssl,\n                               const unsigned char *buf,\n                               const unsigned char *end);\n\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_write_alpn_ext(mbedtls_ssl_context *ssl,\n                               unsigned char *buf,\n                               unsigned char *end,\n                               size_t *out_len);\n#endif /* MBEDTLS_SSL_ALPN */\n\n#if defined(MBEDTLS_TEST_HOOKS)\nint mbedtls_ssl_check_dtls_clihlo_cookie(\n    mbedtls_ssl_context *ssl,\n    const unsigned char *cli_id, size_t cli_id_len,\n    const unsigned char *in, size_t in_len,\n    unsigned char *obuf, size_t buf_len, size_t *olen);\n#endif\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n/**\n * \\brief Given an SSL context and its associated configuration, write the TLS\n *        1.3 specific Pre-Shared key extension.\n *\n * \\param[in]   ssl     SSL context\n * \\param[in]   buf     Base address of the buffer where to write the extension\n * \\param[in]   end     End address of the buffer where to write the extension\n * \\param[out]  out_len Length in bytes of the Pre-Shared key extension: data\n *                      written into the buffer \\p buf by this function plus\n *                      the length of the binders to be written.\n * \\param[out]  binders_len Length of the binders to be written at the end of\n *                          the extension.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext(\n    mbedtls_ssl_context *ssl,\n    unsigned char *buf, unsigned char *end,\n    size_t *out_len, size_t *binders_len);\n\n/**\n * \\brief Given an SSL context and its associated configuration, write the TLS\n *        1.3 specific Pre-Shared key extension binders at the end of the\n *        ClientHello.\n *\n * \\param[in]   ssl     SSL context\n * \\param[in]   buf     Base address of the buffer where to write the binders\n * \\param[in]   end     End address of the buffer where to write the binders\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext(\n    mbedtls_ssl_context *ssl,\n    unsigned char *buf, unsigned char *end);\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n/** Get the host name from the SSL context.\n *\n * \\param[in]   ssl     SSL context\n *\n * \\return The \\p hostname pointer from the SSL context.\n *         \\c NULL if mbedtls_ssl_set_hostname() has never been called on\n *         \\p ssl or if it was last called with \\p NULL.\n */\nconst char *mbedtls_ssl_get_hostname_pointer(const mbedtls_ssl_context *ssl);\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \\\n    defined(MBEDTLS_SSL_SESSION_TICKETS) && \\\n    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \\\n    defined(MBEDTLS_SSL_CLI_C)\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session,\n                                     const char *hostname);\n#endif\n\n#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) && \\\n    defined(MBEDTLS_SSL_ALPN)\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session,\n                                        const char *alpn);\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)\n\n#define MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME (604800)\n\nstatic inline unsigned int mbedtls_ssl_tls13_session_get_ticket_flags(\n    mbedtls_ssl_session *session, unsigned int flags)\n{\n    return session->ticket_flags &\n           (flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);\n}\n\n/**\n * Check if at least one of the given flags is set in\n * the session ticket. See the definition of\n * `MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK` to get all\n * permitted flags.\n */\nstatic inline int mbedtls_ssl_tls13_session_ticket_has_flags(\n    mbedtls_ssl_session *session, unsigned int flags)\n{\n    return mbedtls_ssl_tls13_session_get_ticket_flags(session, flags) != 0;\n}\n\nstatic inline int mbedtls_ssl_tls13_session_ticket_allow_psk(\n    mbedtls_ssl_session *session)\n{\n    return mbedtls_ssl_tls13_session_ticket_has_flags(\n        session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_RESUMPTION);\n}\n\nstatic inline int mbedtls_ssl_tls13_session_ticket_allow_psk_ephemeral(\n    mbedtls_ssl_session *session)\n{\n    return mbedtls_ssl_tls13_session_ticket_has_flags(\n        session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION);\n}\n\nstatic inline unsigned int mbedtls_ssl_tls13_session_ticket_allow_early_data(\n    mbedtls_ssl_session *session)\n{\n    return mbedtls_ssl_tls13_session_ticket_has_flags(\n        session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA);\n}\n\nstatic inline void mbedtls_ssl_tls13_session_set_ticket_flags(\n    mbedtls_ssl_session *session, unsigned int flags)\n{\n    session->ticket_flags |= (flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);\n}\n\nstatic inline void mbedtls_ssl_tls13_session_clear_ticket_flags(\n    mbedtls_ssl_session *session, unsigned int flags)\n{\n    session->ticket_flags &= ~(flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);\n}\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)\n#define MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_BIT 0\n#define MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_BIT 1\n\n#define MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_MASK \\\n    (1 << MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_BIT)\n#define MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_MASK \\\n    (1 << MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_BIT)\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\nstatic inline int mbedtls_ssl_conf_get_session_tickets(\n    const mbedtls_ssl_config *conf)\n{\n    return conf->session_tickets & MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_MASK ?\n           MBEDTLS_SSL_SESSION_TICKETS_ENABLED :\n           MBEDTLS_SSL_SESSION_TICKETS_DISABLED;\n}\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\nstatic inline int mbedtls_ssl_conf_is_signal_new_session_tickets_enabled(\n    const mbedtls_ssl_config *conf)\n{\n    return conf->session_tickets & MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_MASK ?\n           MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED :\n           MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED;\n}\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */\n\n#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3)\nint mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl);\n#endif\n\n#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)\n\n/** Compute the HMAC of variable-length data with constant flow.\n *\n * This function computes the HMAC of the concatenation of \\p add_data and \\p\n * data, and does with a code flow and memory access pattern that does not\n * depend on \\p data_len_secret, but only on \\p min_data_len and \\p\n * max_data_len. In particular, this function always reads exactly \\p\n * max_data_len bytes from \\p data.\n *\n * \\param ctx               The HMAC context. It must have keys configured\n *                          with mbedtls_md_hmac_starts() and use one of the\n *                          following hashes: SHA-384, SHA-256, SHA-1 or MD-5.\n *                          It is reset using mbedtls_md_hmac_reset() after\n *                          the computation is complete to prepare for the\n *                          next computation.\n * \\param add_data          The first part of the message whose HMAC is being\n *                          calculated. This must point to a readable buffer\n *                          of \\p add_data_len bytes.\n * \\param add_data_len      The length of \\p add_data in bytes.\n * \\param data              The buffer containing the second part of the\n *                          message. This must point to a readable buffer\n *                          of \\p max_data_len bytes.\n * \\param data_len_secret   The length of the data to process in \\p data.\n *                          This must be no less than \\p min_data_len and no\n *                          greater than \\p max_data_len.\n * \\param min_data_len      The minimal length of the second part of the\n *                          message, read from \\p data.\n * \\param max_data_len      The maximal length of the second part of the\n *                          message, read from \\p data.\n * \\param output            The HMAC will be written here. This must point to\n *                          a writable buffer of sufficient size to hold the\n *                          HMAC value.\n *\n * \\retval 0 on success.\n * \\retval #MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED\n *         The hardware accelerator failed.\n */\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nint mbedtls_ct_hmac(mbedtls_svc_key_id_t key,\n                    psa_algorithm_t mac_alg,\n                    const unsigned char *add_data,\n                    size_t add_data_len,\n                    const unsigned char *data,\n                    size_t data_len_secret,\n                    size_t min_data_len,\n                    size_t max_data_len,\n                    unsigned char *output);\n#else\nint mbedtls_ct_hmac(mbedtls_md_context_t *ctx,\n                    const unsigned char *add_data,\n                    size_t add_data_len,\n                    const unsigned char *data,\n                    size_t data_len_secret,\n                    size_t min_data_len,\n                    size_t max_data_len,\n                    unsigned char *output);\n#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */\n#endif /* MBEDTLS_TEST_HOOKS && defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) */\n\n#endif /* ssl_misc.h */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_msg.c",
    "content": "/*\n *  Generic SSL/TLS messaging layer functions\n *  (record layer + retransmission state machine)\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  http://www.ietf.org/rfc/rfc2246.txt\n *  http://www.ietf.org/rfc/rfc4346.txt\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_TLS_C)\n\n#include \"mbedtls/platform.h\"\n\n#include \"mbedtls/ssl.h\"\n#include \"ssl_misc.h\"\n#include \"debug_internal.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/version.h\"\n#include \"constant_time_internal.h\"\n#include \"mbedtls/constant_time.h\"\n\n#include <limits.h>\n#include <string.h>\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"psa_util_internal.h\"\n#include \"psa/crypto.h\"\n#endif\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n#include \"mbedtls/oid.h\"\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n/* Define a local translating function to save code size by not using too many\n * arguments in each translating place. */\nstatic int local_err_translation(psa_status_t status)\n{\n    return psa_status_to_mbedtls(status, psa_to_ssl_errors,\n                                 ARRAY_LENGTH(psa_to_ssl_errors),\n                                 psa_generic_status_to_mbedtls);\n}\n#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)\n#endif\n\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n\n#if defined(PSA_WANT_ALG_SHA_384)\n#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_384)\n#elif defined(PSA_WANT_ALG_SHA_256)\n#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_256)\n#else /* See check_config.h */\n#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_1)\n#endif\n\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ct_hmac(mbedtls_svc_key_id_t key,\n                    psa_algorithm_t mac_alg,\n                    const unsigned char *add_data,\n                    size_t add_data_len,\n                    const unsigned char *data,\n                    size_t data_len_secret,\n                    size_t min_data_len,\n                    size_t max_data_len,\n                    unsigned char *output)\n{\n    /*\n     * This function breaks the HMAC abstraction and uses psa_hash_clone()\n     * extension in order to get constant-flow behaviour.\n     *\n     * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means\n     * concatenation, and okey/ikey are the XOR of the key with some fixed bit\n     * patterns (see RFC 2104, sec. 2).\n     *\n     * We'll first compute ikey/okey, then inner_hash = HASH(ikey + msg) by\n     * hashing up to minlen, then cloning the context, and for each byte up\n     * to maxlen finishing up the hash computation, keeping only the\n     * correct result.\n     *\n     * Then we only need to compute HASH(okey + inner_hash) and we're done.\n     */\n    psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH(mac_alg);\n    const size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);\n    unsigned char key_buf[MAX_HASH_BLOCK_LENGTH];\n    const size_t hash_size = PSA_HASH_LENGTH(hash_alg);\n    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;\n    size_t hash_length;\n\n    unsigned char aux_out[PSA_HASH_MAX_SIZE];\n    psa_hash_operation_t aux_operation = PSA_HASH_OPERATION_INIT;\n    size_t offset;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    size_t mac_key_length;\n    size_t i;\n\n#define PSA_CHK(func_call)        \\\n    do {                            \\\n        status = (func_call);       \\\n        if (status != PSA_SUCCESS) \\\n        goto cleanup;           \\\n    } while (0)\n\n    /* Export MAC key\n     * We assume key length is always exactly the output size\n     * which is never more than the block size, thus we use block_size\n     * as the key buffer size.\n     */\n    PSA_CHK(psa_export_key(key, key_buf, block_size, &mac_key_length));\n\n    /* Calculate ikey */\n    for (i = 0; i < mac_key_length; i++) {\n        key_buf[i] = (unsigned char) (key_buf[i] ^ 0x36);\n    }\n    for (; i < block_size; ++i) {\n        key_buf[i] = 0x36;\n    }\n\n    PSA_CHK(psa_hash_setup(&operation, hash_alg));\n\n    /* Now compute inner_hash = HASH(ikey + msg) */\n    PSA_CHK(psa_hash_update(&operation, key_buf, block_size));\n    PSA_CHK(psa_hash_update(&operation, add_data, add_data_len));\n    PSA_CHK(psa_hash_update(&operation, data, min_data_len));\n\n    /* Fill the hash buffer in advance with something that is\n     * not a valid hash (barring an attack on the hash and\n     * deliberately-crafted input), in case the caller doesn't\n     * check the return status properly. */\n    memset(output, '!', hash_size);\n\n    /* For each possible length, compute the hash up to that point */\n    for (offset = min_data_len; offset <= max_data_len; offset++) {\n        PSA_CHK(psa_hash_clone(&operation, &aux_operation));\n        PSA_CHK(psa_hash_finish(&aux_operation, aux_out,\n                                PSA_HASH_MAX_SIZE, &hash_length));\n        /* Keep only the correct inner_hash in the output buffer */\n        mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offset, data_len_secret),\n                             output, aux_out, NULL, hash_size);\n\n        if (offset < max_data_len) {\n            PSA_CHK(psa_hash_update(&operation, data + offset, 1));\n        }\n    }\n\n    /* Abort current operation to prepare for final operation */\n    PSA_CHK(psa_hash_abort(&operation));\n\n    /* Calculate okey */\n    for (i = 0; i < mac_key_length; i++) {\n        key_buf[i] = (unsigned char) ((key_buf[i] ^ 0x36) ^ 0x5C);\n    }\n    for (; i < block_size; ++i) {\n        key_buf[i] = 0x5C;\n    }\n\n    /* Now compute HASH(okey + inner_hash) */\n    PSA_CHK(psa_hash_setup(&operation, hash_alg));\n    PSA_CHK(psa_hash_update(&operation, key_buf, block_size));\n    PSA_CHK(psa_hash_update(&operation, output, hash_size));\n    PSA_CHK(psa_hash_finish(&operation, output, hash_size, &hash_length));\n\n#undef PSA_CHK\n\ncleanup:\n    mbedtls_platform_zeroize(key_buf, MAX_HASH_BLOCK_LENGTH);\n    mbedtls_platform_zeroize(aux_out, PSA_HASH_MAX_SIZE);\n\n    psa_hash_abort(&operation);\n    psa_hash_abort(&aux_operation);\n    return PSA_TO_MBEDTLS_ERR(status);\n}\n\n#undef MAX_HASH_BLOCK_LENGTH\n\n#else\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ct_hmac(mbedtls_md_context_t *ctx,\n                    const unsigned char *add_data,\n                    size_t add_data_len,\n                    const unsigned char *data,\n                    size_t data_len_secret,\n                    size_t min_data_len,\n                    size_t max_data_len,\n                    unsigned char *output)\n{\n    /*\n     * This function breaks the HMAC abstraction and uses the md_clone()\n     * extension to the MD API in order to get constant-flow behaviour.\n     *\n     * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means\n     * concatenation, and okey/ikey are the XOR of the key with some fixed bit\n     * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx.\n     *\n     * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to\n     * minlen, then cloning the context, and for each byte up to maxlen\n     * finishing up the hash computation, keeping only the correct result.\n     *\n     * Then we only need to compute HASH(okey + inner_hash) and we're done.\n     */\n    const mbedtls_md_type_t md_alg = mbedtls_md_get_type(ctx->md_info);\n    /* TLS 1.2 only supports SHA-384, SHA-256, SHA-1, MD-5,\n     * all of which have the same block size except SHA-384. */\n    const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64;\n    const unsigned char * const ikey = ctx->hmac_ctx;\n    const unsigned char * const okey = ikey + block_size;\n    const size_t hash_size = mbedtls_md_get_size(ctx->md_info);\n\n    unsigned char aux_out[MBEDTLS_MD_MAX_SIZE];\n    mbedtls_md_context_t aux;\n    size_t offset;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_md_init(&aux);\n\n#define MD_CHK(func_call) \\\n    do {                    \\\n        ret = (func_call);  \\\n        if (ret != 0)      \\\n        goto cleanup;   \\\n    } while (0)\n\n    MD_CHK(mbedtls_md_setup(&aux, ctx->md_info, 0));\n\n    /* After hmac_start() of hmac_reset(), ikey has already been hashed,\n     * so we can start directly with the message */\n    MD_CHK(mbedtls_md_update(ctx, add_data, add_data_len));\n    MD_CHK(mbedtls_md_update(ctx, data, min_data_len));\n\n    /* Fill the hash buffer in advance with something that is\n     * not a valid hash (barring an attack on the hash and\n     * deliberately-crafted input), in case the caller doesn't\n     * check the return status properly. */\n    memset(output, '!', hash_size);\n\n    /* For each possible length, compute the hash up to that point */\n    for (offset = min_data_len; offset <= max_data_len; offset++) {\n        MD_CHK(mbedtls_md_clone(&aux, ctx));\n        MD_CHK(mbedtls_md_finish(&aux, aux_out));\n        /* Keep only the correct inner_hash in the output buffer */\n        mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offset, data_len_secret),\n                             output, aux_out, NULL, hash_size);\n\n        if (offset < max_data_len) {\n            MD_CHK(mbedtls_md_update(ctx, data + offset, 1));\n        }\n    }\n\n    /* The context needs to finish() before it starts() again */\n    MD_CHK(mbedtls_md_finish(ctx, aux_out));\n\n    /* Now compute HASH(okey + inner_hash) */\n    MD_CHK(mbedtls_md_starts(ctx));\n    MD_CHK(mbedtls_md_update(ctx, okey, block_size));\n    MD_CHK(mbedtls_md_update(ctx, output, hash_size));\n    MD_CHK(mbedtls_md_finish(ctx, output));\n\n    /* Done, get ready for next time */\n    MD_CHK(mbedtls_md_hmac_reset(ctx));\n\n#undef MD_CHK\n\ncleanup:\n    mbedtls_md_free(&aux);\n    return ret;\n}\n\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */\n\nstatic uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl);\n\n/*\n * Start a timer.\n * Passing millisecs = 0 cancels a running timer.\n */\nvoid mbedtls_ssl_set_timer(mbedtls_ssl_context *ssl, uint32_t millisecs)\n{\n    if (ssl->f_set_timer == NULL) {\n        return;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"set_timer to %d ms\", (int) millisecs));\n    ssl->f_set_timer(ssl->p_timer, millisecs / 4, millisecs);\n}\n\n/*\n * Return -1 is timer is expired, 0 if it isn't.\n */\nint mbedtls_ssl_check_timer(mbedtls_ssl_context *ssl)\n{\n    if (ssl->f_get_timer == NULL) {\n        return 0;\n    }\n\n    if (ssl->f_get_timer(ssl->p_timer) == 2) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"timer expired\"));\n        return -1;\n    }\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_record_header(mbedtls_ssl_context const *ssl,\n                                   unsigned char *buf,\n                                   size_t len,\n                                   mbedtls_record *rec);\n\nint mbedtls_ssl_check_record(mbedtls_ssl_context const *ssl,\n                             unsigned char *buf,\n                             size_t buflen)\n{\n    int ret = 0;\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"=> mbedtls_ssl_check_record\"));\n    MBEDTLS_SSL_DEBUG_BUF(3, \"record buffer\", buf, buflen);\n\n    /* We don't support record checking in TLS because\n     * there doesn't seem to be a usecase for it.\n     */\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM) {\n        ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n        goto exit;\n    }\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    else {\n        mbedtls_record rec;\n\n        ret = ssl_parse_record_header(ssl, buf, buflen, &rec);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(3, \"ssl_parse_record_header\", ret);\n            goto exit;\n        }\n\n        if (ssl->transform_in != NULL) {\n            ret = mbedtls_ssl_decrypt_buf(ssl, ssl->transform_in, &rec);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(3, \"mbedtls_ssl_decrypt_buf\", ret);\n                goto exit;\n            }\n        }\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\nexit:\n    /* On success, we have decrypted the buffer in-place, so make\n     * sure we don't leak any plaintext data. */\n    mbedtls_platform_zeroize(buf, buflen);\n\n    /* For the purpose of this API, treat messages with unexpected CID\n     * as well as such from future epochs as unexpected. */\n    if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID ||\n        ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE) {\n        ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"<= mbedtls_ssl_check_record\"));\n    return ret;\n}\n\n#define SSL_DONT_FORCE_FLUSH 0\n#define SSL_FORCE_FLUSH      1\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n\n/* Forward declarations for functions related to message buffering. */\nstatic void ssl_buffering_free_slot(mbedtls_ssl_context *ssl,\n                                    uint8_t slot);\nstatic void ssl_free_buffered_record(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_load_buffered_message(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_load_buffered_record(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_buffer_message(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_buffer_future_record(mbedtls_ssl_context *ssl,\n                                    mbedtls_record const *rec);\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_next_record_is_in_datagram(mbedtls_ssl_context *ssl);\n\nstatic size_t ssl_get_maximum_datagram_size(mbedtls_ssl_context const *ssl)\n{\n    size_t mtu = mbedtls_ssl_get_current_mtu(ssl);\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n    size_t out_buf_len = ssl->out_buf_len;\n#else\n    size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;\n#endif\n\n    if (mtu != 0 && mtu < out_buf_len) {\n        return mtu;\n    }\n\n    return out_buf_len;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_get_remaining_space_in_datagram(mbedtls_ssl_context const *ssl)\n{\n    size_t const bytes_written = ssl->out_left;\n    size_t const mtu           = ssl_get_maximum_datagram_size(ssl);\n\n    /* Double-check that the write-index hasn't gone\n     * past what we can transmit in a single datagram. */\n    if (bytes_written > mtu) {\n        /* Should never happen... */\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    return (int) (mtu - bytes_written);\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_get_remaining_payload_in_datagram(mbedtls_ssl_context const *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t remaining, expansion;\n    size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n    const size_t mfl = mbedtls_ssl_get_output_max_frag_len(ssl);\n\n    if (max_len > mfl) {\n        max_len = mfl;\n    }\n\n    /* By the standard (RFC 6066 Sect. 4), the MFL extension\n     * only limits the maximum record payload size, so in theory\n     * we would be allowed to pack multiple records of payload size\n     * MFL into a single datagram. However, this would mean that there's\n     * no way to explicitly communicate MTU restrictions to the peer.\n     *\n     * The following reduction of max_len makes sure that we never\n     * write datagrams larger than MFL + Record Expansion Overhead.\n     */\n    if (max_len <= ssl->out_left) {\n        return 0;\n    }\n\n    max_len -= ssl->out_left;\n#endif\n\n    ret = ssl_get_remaining_space_in_datagram(ssl);\n    if (ret < 0) {\n        return ret;\n    }\n    remaining = (size_t) ret;\n\n    ret = mbedtls_ssl_get_record_expansion(ssl);\n    if (ret < 0) {\n        return ret;\n    }\n    expansion = (size_t) ret;\n\n    if (remaining <= expansion) {\n        return 0;\n    }\n\n    remaining -= expansion;\n    if (remaining >= max_len) {\n        remaining = max_len;\n    }\n\n    return (int) remaining;\n}\n\n/*\n * Double the retransmit timeout value, within the allowed range,\n * returning -1 if the maximum value has already been reached.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_double_retransmit_timeout(mbedtls_ssl_context *ssl)\n{\n    uint32_t new_timeout;\n\n    if (ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max) {\n        return -1;\n    }\n\n    /* Implement the final paragraph of RFC 6347 section 4.1.1.1\n     * in the following way: after the initial transmission and a first\n     * retransmission, back off to a temporary estimated MTU of 508 bytes.\n     * This value is guaranteed to be deliverable (if not guaranteed to be\n     * delivered) of any compliant IPv4 (and IPv6) network, and should work\n     * on most non-IP stacks too. */\n    if (ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min) {\n        ssl->handshake->mtu = 508;\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"mtu autoreduction to %d bytes\", ssl->handshake->mtu));\n    }\n\n    new_timeout = 2 * ssl->handshake->retransmit_timeout;\n\n    /* Avoid arithmetic overflow and range overflow */\n    if (new_timeout < ssl->handshake->retransmit_timeout ||\n        new_timeout > ssl->conf->hs_timeout_max) {\n        new_timeout = ssl->conf->hs_timeout_max;\n    }\n\n    ssl->handshake->retransmit_timeout = new_timeout;\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"update timeout value to %lu millisecs\",\n                              (unsigned long) ssl->handshake->retransmit_timeout));\n\n    return 0;\n}\n\nstatic void ssl_reset_retransmit_timeout(mbedtls_ssl_context *ssl)\n{\n    ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min;\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"update timeout value to %lu millisecs\",\n                              (unsigned long) ssl->handshake->retransmit_timeout));\n}\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n/*\n * Encryption/decryption functions\n */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) || defined(MBEDTLS_SSL_PROTO_TLS1_3)\n\nstatic size_t ssl_compute_padding_length(size_t len,\n                                         size_t granularity)\n{\n    return (granularity - (len + 1) % granularity) % granularity;\n}\n\n/* This functions transforms a (D)TLS plaintext fragment and a record content\n * type into an instance of the (D)TLSInnerPlaintext structure. This is used\n * in DTLS 1.2 + CID and within TLS 1.3 to allow flexible padding and to protect\n * a record's content type.\n *\n *        struct {\n *            opaque content[DTLSPlaintext.length];\n *            ContentType real_type;\n *            uint8 zeros[length_of_padding];\n *        } (D)TLSInnerPlaintext;\n *\n *  Input:\n *  - `content`: The beginning of the buffer holding the\n *               plaintext to be wrapped.\n *  - `*content_size`: The length of the plaintext in Bytes.\n *  - `max_len`: The number of Bytes available starting from\n *               `content`. This must be `>= *content_size`.\n *  - `rec_type`: The desired record content type.\n *\n *  Output:\n *  - `content`: The beginning of the resulting (D)TLSInnerPlaintext structure.\n *  - `*content_size`: The length of the resulting (D)TLSInnerPlaintext structure.\n *\n *  Returns:\n *  - `0` on success.\n *  - A negative error code if `max_len` didn't offer enough space\n *    for the expansion.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_build_inner_plaintext(unsigned char *content,\n                                     size_t *content_size,\n                                     size_t remaining,\n                                     uint8_t rec_type,\n                                     size_t pad)\n{\n    size_t len = *content_size;\n\n    /* Write real content type */\n    if (remaining == 0) {\n        return -1;\n    }\n    content[len] = rec_type;\n    len++;\n    remaining--;\n\n    if (remaining < pad) {\n        return -1;\n    }\n    memset(content + len, 0, pad);\n    len += pad;\n    remaining -= pad;\n\n    *content_size = len;\n    return 0;\n}\n\n/* This function parses a (D)TLSInnerPlaintext structure.\n * See ssl_build_inner_plaintext() for details. */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_inner_plaintext(unsigned char const *content,\n                                     size_t *content_size,\n                                     uint8_t *rec_type)\n{\n    size_t remaining = *content_size;\n\n    /* Determine length of padding by skipping zeroes from the back. */\n    do {\n        if (remaining == 0) {\n            return -1;\n        }\n        remaining--;\n    } while (content[remaining] == 0);\n\n    *content_size = remaining;\n    *rec_type = content[remaining];\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID || MBEDTLS_SSL_PROTO_TLS1_3 */\n\n/* The size of the `add_data` structure depends on various\n * factors, namely\n *\n * 1) CID functionality disabled\n *\n * additional_data =\n *    8:                    seq_num +\n *    1:                       type +\n *    2:                    version +\n *    2:  length of inner plaintext +\n *\n * size = 13 bytes\n *\n * 2) CID functionality based on RFC 9146 enabled\n *\n * size = 8 + 1 + 1 + 1 + 2 + 2 + 6 + 2 + CID-length\n *      = 23 + CID-length\n *\n * 3) CID functionality based on legacy CID version\n    according to draft-ietf-tls-dtls-connection-id-05\n *  https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05\n *\n * size = 13 + 1 + CID-length\n *\n * More information about the CID usage:\n *\n * Per Section 5.3 of draft-ietf-tls-dtls-connection-id-05 the\n * size of the additional data structure is calculated as:\n *\n * additional_data =\n *    8:                    seq_num +\n *    1:                  tls12_cid +\n *    2:     DTLSCipherText.version +\n *    n:                        cid +\n *    1:                 cid_length +\n *    2: length_of_DTLSInnerPlaintext\n *\n * Per RFC 9146 the size of the add_data structure is calculated as:\n *\n * additional_data =\n *    8:        seq_num_placeholder +\n *    1:                  tls12_cid +\n *    1:                 cid_length +\n *    1:                  tls12_cid +\n *    2:     DTLSCiphertext.version +\n *    2:                      epoch +\n *    6:            sequence_number +\n *    n:                        cid +\n *    2: length_of_DTLSInnerPlaintext\n *\n */\nstatic void ssl_extract_add_data_from_record(unsigned char *add_data,\n                                             size_t *add_data_len,\n                                             mbedtls_record *rec,\n                                             mbedtls_ssl_protocol_version\n                                             tls_version,\n                                             size_t taglen)\n{\n    /* Several types of ciphers have been defined for use with TLS and DTLS,\n     * and the MAC calculations for those ciphers differ slightly. Further\n     * variants were added when the CID functionality was added with RFC 9146.\n     * This implementations also considers the use of a legacy version of the\n     * CID specification published in draft-ietf-tls-dtls-connection-id-05,\n     * which is used in deployments.\n     *\n     * We will distinguish between the non-CID and the CID cases below.\n     *\n     * --- Non-CID cases ---\n     *\n     * Quoting RFC 5246 (TLS 1.2):\n     *\n     *    additional_data = seq_num + TLSCompressed.type +\n     *                      TLSCompressed.version + TLSCompressed.length;\n     *\n     * For TLS 1.3, the record sequence number is dropped from the AAD\n     * and encoded within the nonce of the AEAD operation instead.\n     * Moreover, the additional data involves the length of the TLS\n     * ciphertext, not the TLS plaintext as in earlier versions.\n     * Quoting RFC 8446 (TLS 1.3):\n     *\n     *      additional_data = TLSCiphertext.opaque_type ||\n     *                        TLSCiphertext.legacy_record_version ||\n     *                        TLSCiphertext.length\n     *\n     * We pass the tag length to this function in order to compute the\n     * ciphertext length from the inner plaintext length rec->data_len via\n     *\n     *     TLSCiphertext.length = TLSInnerPlaintext.length + taglen.\n     *\n     * --- CID cases ---\n     *\n     * RFC 9146 uses a common pattern when constructing the data\n     * passed into a MAC / AEAD cipher.\n     *\n     * Data concatenation for MACs used with block ciphers with\n     * Encrypt-then-MAC Processing (with CID):\n     *\n     *  data = seq_num_placeholder +\n     *         tls12_cid +\n     *         cid_length +\n     *         tls12_cid +\n     *         DTLSCiphertext.version +\n     *         epoch +\n     *         sequence_number +\n     *         cid +\n     *         DTLSCiphertext.length +\n     *         IV +\n     *         ENC(content + padding + padding_length)\n     *\n     * Data concatenation for MACs used with block ciphers (with CID):\n     *\n     *  data =  seq_num_placeholder +\n     *          tls12_cid +\n     *          cid_length +\n     *          tls12_cid +\n     *          DTLSCiphertext.version +\n     *          epoch +\n     *          sequence_number +\n     *          cid +\n     *          length_of_DTLSInnerPlaintext +\n     *          DTLSInnerPlaintext.content +\n     *          DTLSInnerPlaintext.real_type +\n     *          DTLSInnerPlaintext.zeros\n     *\n     * AEAD ciphers use the following additional data calculation (with CIDs):\n     *\n     *     additional_data = seq_num_placeholder +\n     *                tls12_cid +\n     *                cid_length +\n     *                tls12_cid +\n     *                DTLSCiphertext.version +\n     *                epoch +\n     *                sequence_number +\n     *                cid +\n     *                length_of_DTLSInnerPlaintext\n     *\n     * Section 5.3 of draft-ietf-tls-dtls-connection-id-05 (for legacy CID use)\n     * defines the additional data calculation as follows:\n     *\n     *     additional_data = seq_num +\n     *                tls12_cid +\n     *                DTLSCipherText.version +\n     *                cid +\n     *                cid_length +\n     *                length_of_DTLSInnerPlaintext\n     */\n\n    unsigned char *cur = add_data;\n    size_t ad_len_field = rec->data_len;\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \\\n    MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0\n    const unsigned char seq_num_placeholder[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {\n        /* In TLS 1.3, the AAD contains the length of the TLSCiphertext,\n         * which differs from the length of the TLSInnerPlaintext\n         * by the length of the authentication tag. */\n        ad_len_field += taglen;\n    } else\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n    {\n        ((void) tls_version);\n        ((void) taglen);\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \\\n        MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0\n        if (rec->cid_len != 0) {\n            // seq_num_placeholder\n            memcpy(cur, seq_num_placeholder, sizeof(seq_num_placeholder));\n            cur += sizeof(seq_num_placeholder);\n\n            // tls12_cid type\n            *cur = rec->type;\n            cur++;\n\n            // cid_length\n            *cur = rec->cid_len;\n            cur++;\n        } else\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n        {\n            // epoch + sequence number\n            memcpy(cur, rec->ctr, sizeof(rec->ctr));\n            cur += sizeof(rec->ctr);\n        }\n    }\n\n    // type\n    *cur = rec->type;\n    cur++;\n\n    // version\n    memcpy(cur, rec->ver, sizeof(rec->ver));\n    cur += sizeof(rec->ver);\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \\\n    MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 1\n\n    if (rec->cid_len != 0) {\n        // CID\n        memcpy(cur, rec->cid, rec->cid_len);\n        cur += rec->cid_len;\n\n        // cid_length\n        *cur = rec->cid_len;\n        cur++;\n\n        // length of inner plaintext\n        MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0);\n        cur += 2;\n    } else\n#elif defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \\\n    MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0\n\n    if (rec->cid_len != 0) {\n        // epoch + sequence number\n        memcpy(cur, rec->ctr, sizeof(rec->ctr));\n        cur += sizeof(rec->ctr);\n\n        // CID\n        memcpy(cur, rec->cid, rec->cid_len);\n        cur += rec->cid_len;\n\n        // length of inner plaintext\n        MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0);\n        cur += 2;\n    } else\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n    {\n        MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0);\n        cur += 2;\n    }\n\n    *add_data_len = (size_t) (cur - add_data);\n}\n\n#if defined(MBEDTLS_SSL_HAVE_AEAD)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_transform_aead_dynamic_iv_is_explicit(\n    mbedtls_ssl_transform const *transform)\n{\n    return transform->ivlen != transform->fixed_ivlen;\n}\n\n/* Compute IV := ( fixed_iv || 0 ) XOR ( 0 || dynamic_IV )\n *\n * Concretely, this occurs in two variants:\n *\n * a) Fixed and dynamic IV lengths add up to total IV length, giving\n *       IV = fixed_iv || dynamic_iv\n *\n *    This variant is used in TLS 1.2 when used with GCM or CCM.\n *\n * b) Fixed IV lengths matches total IV length, giving\n *       IV = fixed_iv XOR ( 0 || dynamic_iv )\n *\n *    This variant occurs in TLS 1.3 and for TLS 1.2 when using ChaChaPoly.\n *\n * See also the documentation of mbedtls_ssl_transform.\n *\n * This function has the precondition that\n *\n *     dst_iv_len >= max( fixed_iv_len, dynamic_iv_len )\n *\n * which has to be ensured by the caller. If this precondition\n * violated, the behavior of this function is undefined.\n */\nstatic void ssl_build_record_nonce(unsigned char *dst_iv,\n                                   size_t dst_iv_len,\n                                   unsigned char const *fixed_iv,\n                                   size_t fixed_iv_len,\n                                   unsigned char const *dynamic_iv,\n                                   size_t dynamic_iv_len)\n{\n    /* Start with Fixed IV || 0 */\n    memset(dst_iv, 0, dst_iv_len);\n    memcpy(dst_iv, fixed_iv, fixed_iv_len);\n\n    dst_iv += dst_iv_len - dynamic_iv_len;\n    mbedtls_xor(dst_iv, dst_iv, dynamic_iv, dynamic_iv_len);\n}\n#endif /* MBEDTLS_SSL_HAVE_AEAD */\n\nint mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl,\n                            mbedtls_ssl_transform *transform,\n                            mbedtls_record *rec,\n                            int (*f_rng)(void *, unsigned char *, size_t),\n                            void *p_rng)\n{\n    mbedtls_ssl_mode_t ssl_mode;\n    int auth_done = 0;\n    unsigned char *data;\n    /* For an explanation of the additional data length see\n     * the description of ssl_extract_add_data_from_record().\n     */\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    unsigned char add_data[23 + MBEDTLS_SSL_CID_OUT_LEN_MAX];\n#else\n    unsigned char add_data[13];\n#endif\n    size_t add_data_len;\n    size_t post_avail;\n\n    /* The SSL context is only used for debugging purposes! */\n#if !defined(MBEDTLS_DEBUG_C)\n    ssl = NULL; /* make sure we don't use it except for debug */\n    ((void) ssl);\n#endif\n\n    /* The PRNG is used for dynamic IV generation that's used\n     * for CBC transformations in TLS 1.2. */\n#if !(defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \\\n    defined(MBEDTLS_SSL_PROTO_TLS1_2))\n    ((void) f_rng);\n    ((void) p_rng);\n#endif\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> encrypt buf\"));\n\n    if (transform == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"no transform provided to encrypt_buf\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n    if (rec == NULL\n        || rec->buf == NULL\n        || rec->buf_len < rec->data_offset\n        || rec->buf_len - rec->data_offset < rec->data_len\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n        || rec->cid_len != 0\n#endif\n        ) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad record structure provided to encrypt_buf\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    ssl_mode = mbedtls_ssl_get_mode_from_transform(transform);\n\n    data = rec->buf + rec->data_offset;\n    post_avail = rec->buf_len - (rec->data_len + rec->data_offset);\n    MBEDTLS_SSL_DEBUG_BUF(4, \"before encrypt: output payload\",\n                          data, rec->data_len);\n\n    if (rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Record content %\" MBEDTLS_PRINTF_SIZET\n                                  \" too large, maximum %\" MBEDTLS_PRINTF_SIZET,\n                                  rec->data_len,\n                                  (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    /* The following two code paths implement the (D)TLSInnerPlaintext\n     * structure present in TLS 1.3 and DTLS 1.2 + CID.\n     *\n     * See ssl_build_inner_plaintext() for more information.\n     *\n     * Note that this changes `rec->data_len`, and hence\n     * `post_avail` needs to be recalculated afterwards.\n     *\n     * Note also that the two code paths cannot occur simultaneously\n     * since they apply to different versions of the protocol. There\n     * is hence no risk of double-addition of the inner plaintext.\n     */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    if (transform->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {\n        size_t padding =\n            ssl_compute_padding_length(rec->data_len,\n                                       MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY);\n        if (ssl_build_inner_plaintext(data,\n                                      &rec->data_len,\n                                      post_avail,\n                                      rec->type,\n                                      padding) != 0) {\n            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n        }\n\n        rec->type = MBEDTLS_SSL_MSG_APPLICATION_DATA;\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    /*\n     * Add CID information\n     */\n    rec->cid_len = transform->out_cid_len;\n    memcpy(rec->cid, transform->out_cid, transform->out_cid_len);\n    MBEDTLS_SSL_DEBUG_BUF(3, \"CID\", rec->cid, rec->cid_len);\n\n    if (rec->cid_len != 0) {\n        size_t padding =\n            ssl_compute_padding_length(rec->data_len,\n                                       MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY);\n        /*\n         * Wrap plaintext into DTLSInnerPlaintext structure.\n         * See ssl_build_inner_plaintext() for more information.\n         *\n         * Note that this changes `rec->data_len`, and hence\n         * `post_avail` needs to be recalculated afterwards.\n         */\n        if (ssl_build_inner_plaintext(data,\n                                      &rec->data_len,\n                                      post_avail,\n                                      rec->type,\n                                      padding) != 0) {\n            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n        }\n\n        rec->type = MBEDTLS_SSL_MSG_CID;\n    }\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n    post_avail = rec->buf_len - (rec->data_len + rec->data_offset);\n\n    /*\n     * Add MAC before if needed\n     */\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)\n    if (ssl_mode == MBEDTLS_SSL_MODE_STREAM ||\n        ssl_mode == MBEDTLS_SSL_MODE_CBC) {\n        if (post_avail < transform->maclen) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"Buffer provided for encrypted record not large enough\"));\n            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n        }\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        unsigned char mac[MBEDTLS_SSL_MAC_ADD];\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;\n        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n        size_t sign_mac_length = 0;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        ssl_extract_add_data_from_record(add_data, &add_data_len, rec,\n                                         transform->tls_version,\n                                         transform->taglen);\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        status = psa_mac_sign_setup(&operation, transform->psa_mac_enc,\n                                    transform->psa_mac_alg);\n        if (status != PSA_SUCCESS) {\n            goto hmac_failed_etm_disabled;\n        }\n\n        status = psa_mac_update(&operation, add_data, add_data_len);\n        if (status != PSA_SUCCESS) {\n            goto hmac_failed_etm_disabled;\n        }\n\n        status = psa_mac_update(&operation, data, rec->data_len);\n        if (status != PSA_SUCCESS) {\n            goto hmac_failed_etm_disabled;\n        }\n\n        status = psa_mac_sign_finish(&operation, mac, MBEDTLS_SSL_MAC_ADD,\n                                     &sign_mac_length);\n        if (status != PSA_SUCCESS) {\n            goto hmac_failed_etm_disabled;\n        }\n#else\n        ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, add_data,\n                                     add_data_len);\n        if (ret != 0) {\n            goto hmac_failed_etm_disabled;\n        }\n        ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, data, rec->data_len);\n        if (ret != 0) {\n            goto hmac_failed_etm_disabled;\n        }\n        ret = mbedtls_md_hmac_finish(&transform->md_ctx_enc, mac);\n        if (ret != 0) {\n            goto hmac_failed_etm_disabled;\n        }\n        ret = mbedtls_md_hmac_reset(&transform->md_ctx_enc);\n        if (ret != 0) {\n            goto hmac_failed_etm_disabled;\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        memcpy(data + rec->data_len, mac, transform->maclen);\n#endif\n\n        MBEDTLS_SSL_DEBUG_BUF(4, \"computed mac\", data + rec->data_len,\n                              transform->maclen);\n\n        rec->data_len += transform->maclen;\n        post_avail -= transform->maclen;\n        auth_done++;\n\nhmac_failed_etm_disabled:\n        mbedtls_platform_zeroize(mac, transform->maclen);\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        status = psa_mac_abort(&operation);\n        if (ret == 0 && status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_md_hmac_xxx\", ret);\n            return ret;\n        }\n    }\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */\n\n    /*\n     * Encrypt\n     */\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM)\n    if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"before encrypt: msglen = %\" MBEDTLS_PRINTF_SIZET \", \"\n                                                                                    \"including %d bytes of padding\",\n                                  rec->data_len, 0));\n\n        /* The only supported stream cipher is \"NULL\",\n         * so there's nothing to do here.*/\n    } else\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */\n\n#if defined(MBEDTLS_SSL_HAVE_AEAD)\n    if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) {\n        unsigned char iv[12];\n        unsigned char *dynamic_iv;\n        size_t dynamic_iv_len;\n        int dynamic_iv_is_explicit =\n            ssl_transform_aead_dynamic_iv_is_explicit(transform);\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n        /* Check that there's space for the authentication tag. */\n        if (post_avail < transform->taglen) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"Buffer provided for encrypted record not large enough\"));\n            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n        }\n\n        /*\n         * Build nonce for AEAD encryption.\n         *\n         * Note: In the case of CCM and GCM in TLS 1.2, the dynamic\n         *       part of the IV is prepended to the ciphertext and\n         *       can be chosen freely - in particular, it need not\n         *       agree with the record sequence number.\n         *       However, since ChaChaPoly as well as all AEAD modes\n         *       in TLS 1.3 use the record sequence number as the\n         *       dynamic part of the nonce, we uniformly use the\n         *       record sequence number here in all cases.\n         */\n        dynamic_iv     = rec->ctr;\n        dynamic_iv_len = sizeof(rec->ctr);\n\n        ssl_build_record_nonce(iv, sizeof(iv),\n                               transform->iv_enc,\n                               transform->fixed_ivlen,\n                               dynamic_iv,\n                               dynamic_iv_len);\n\n        /*\n         * Build additional data for AEAD encryption.\n         * This depends on the TLS version.\n         */\n        ssl_extract_add_data_from_record(add_data, &add_data_len, rec,\n                                         transform->tls_version,\n                                         transform->taglen);\n\n        MBEDTLS_SSL_DEBUG_BUF(4, \"IV used (internal)\",\n                              iv, transform->ivlen);\n        MBEDTLS_SSL_DEBUG_BUF(4, \"IV used (transmitted)\",\n                              dynamic_iv,\n                              dynamic_iv_is_explicit ? dynamic_iv_len : 0);\n        MBEDTLS_SSL_DEBUG_BUF(4, \"additional data used for AEAD\",\n                              add_data, add_data_len);\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"before encrypt: msglen = %\" MBEDTLS_PRINTF_SIZET \", \"\n                                                                                    \"including 0 bytes of padding\",\n                                  rec->data_len));\n\n        /*\n         * Encrypt and authenticate\n         */\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        status = psa_aead_encrypt(transform->psa_key_enc,\n                                  transform->psa_alg,\n                                  iv, transform->ivlen,\n                                  add_data, add_data_len,\n                                  data, rec->data_len,\n                                  data, rec->buf_len - (data - rec->buf),\n                                  &rec->data_len);\n\n        if (status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_encrypt_buf\", ret);\n            return ret;\n        }\n#else\n        if ((ret = mbedtls_cipher_auth_encrypt_ext(&transform->cipher_ctx_enc,\n                                                   iv, transform->ivlen,\n                                                   add_data, add_data_len,\n                                                   data, rec->data_len, /* src */\n                                                   data, rec->buf_len - (size_t) (data - rec->buf), /* dst */\n                                                   &rec->data_len,\n                                                   transform->taglen)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_cipher_auth_encrypt_ext\", ret);\n            return ret;\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        MBEDTLS_SSL_DEBUG_BUF(4, \"after encrypt: tag\",\n                              data + rec->data_len - transform->taglen,\n                              transform->taglen);\n        /* Account for authentication tag. */\n        post_avail -= transform->taglen;\n\n        /*\n         * Prefix record content with dynamic IV in case it is explicit.\n         */\n        if (dynamic_iv_is_explicit != 0) {\n            if (rec->data_offset < dynamic_iv_len) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"Buffer provided for encrypted record not large enough\"));\n                return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n            }\n\n            memcpy(data - dynamic_iv_len, dynamic_iv, dynamic_iv_len);\n            rec->data_offset -= dynamic_iv_len;\n            rec->data_len    += dynamic_iv_len;\n        }\n\n        auth_done++;\n    } else\n#endif /* MBEDTLS_SSL_HAVE_AEAD */\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC)\n    if (ssl_mode == MBEDTLS_SSL_MODE_CBC ||\n        ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n        size_t padlen, i;\n        size_t olen;\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n        size_t part_len;\n        psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        /* Currently we're always using minimal padding\n         * (up to 255 bytes would be allowed). */\n        padlen = transform->ivlen - (rec->data_len + 1) % transform->ivlen;\n        if (padlen == transform->ivlen) {\n            padlen = 0;\n        }\n\n        /* Check there's enough space in the buffer for the padding. */\n        if (post_avail < padlen + 1) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"Buffer provided for encrypted record not large enough\"));\n            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n        }\n\n        for (i = 0; i <= padlen; i++) {\n            data[rec->data_len + i] = (unsigned char) padlen;\n        }\n\n        rec->data_len += padlen + 1;\n        post_avail -= padlen + 1;\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        /*\n         * Prepend per-record IV for block cipher in TLS v1.2 as per\n         * Method 1 (6.2.3.2. in RFC4346 and RFC5246)\n         */\n        if (f_rng == NULL) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"No PRNG provided to encrypt_record routine\"));\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        if (rec->data_offset < transform->ivlen) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"Buffer provided for encrypted record not large enough\"));\n            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n        }\n\n        /*\n         * Generate IV\n         */\n        ret = f_rng(p_rng, transform->iv_enc, transform->ivlen);\n        if (ret != 0) {\n            return ret;\n        }\n\n        memcpy(data - transform->ivlen, transform->iv_enc, transform->ivlen);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"before encrypt: msglen = %\" MBEDTLS_PRINTF_SIZET \", \"\n                                                                                    \"including %\"\n                                  MBEDTLS_PRINTF_SIZET\n                                  \" bytes of IV and %\" MBEDTLS_PRINTF_SIZET \" bytes of padding\",\n                                  rec->data_len, transform->ivlen,\n                                  padlen + 1));\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        status = psa_cipher_encrypt_setup(&cipher_op,\n                                          transform->psa_key_enc, transform->psa_alg);\n\n        if (status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_cipher_encrypt_setup\", ret);\n            return ret;\n        }\n\n        status = psa_cipher_set_iv(&cipher_op, transform->iv_enc, transform->ivlen);\n\n        if (status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_cipher_set_iv\", ret);\n            return ret;\n\n        }\n\n        status = psa_cipher_update(&cipher_op,\n                                   data, rec->data_len,\n                                   data, rec->data_len, &olen);\n\n        if (status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_cipher_update\", ret);\n            return ret;\n\n        }\n\n        status = psa_cipher_finish(&cipher_op,\n                                   data + olen, rec->data_len - olen,\n                                   &part_len);\n\n        if (status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_cipher_finish\", ret);\n            return ret;\n\n        }\n\n        olen += part_len;\n#else\n        if ((ret = mbedtls_cipher_crypt(&transform->cipher_ctx_enc,\n                                        transform->iv_enc,\n                                        transform->ivlen,\n                                        data, rec->data_len,\n                                        data, &olen)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_cipher_crypt\", ret);\n            return ret;\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        if (rec->data_len != olen) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        data             -= transform->ivlen;\n        rec->data_offset -= transform->ivlen;\n        rec->data_len    += transform->ivlen;\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n        if (auth_done == 0) {\n            unsigned char mac[MBEDTLS_SSL_MAC_ADD];\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n            psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;\n            size_t sign_mac_length = 0;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n            /* MAC(MAC_write_key, add_data, IV, ENC(content + padding + padding_length))\n             */\n\n            if (post_avail < transform->maclen) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"Buffer provided for encrypted record not large enough\"));\n                return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n            }\n\n            ssl_extract_add_data_from_record(add_data, &add_data_len,\n                                             rec, transform->tls_version,\n                                             transform->taglen);\n\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"using encrypt then mac\"));\n            MBEDTLS_SSL_DEBUG_BUF(4, \"MAC'd meta-data\", add_data,\n                                  add_data_len);\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n            status = psa_mac_sign_setup(&operation, transform->psa_mac_enc,\n                                        transform->psa_mac_alg);\n            if (status != PSA_SUCCESS) {\n                goto hmac_failed_etm_enabled;\n            }\n\n            status = psa_mac_update(&operation, add_data, add_data_len);\n            if (status != PSA_SUCCESS) {\n                goto hmac_failed_etm_enabled;\n            }\n\n            status = psa_mac_update(&operation, data, rec->data_len);\n            if (status != PSA_SUCCESS) {\n                goto hmac_failed_etm_enabled;\n            }\n\n            status = psa_mac_sign_finish(&operation, mac, MBEDTLS_SSL_MAC_ADD,\n                                         &sign_mac_length);\n            if (status != PSA_SUCCESS) {\n                goto hmac_failed_etm_enabled;\n            }\n#else\n\n            ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, add_data,\n                                         add_data_len);\n            if (ret != 0) {\n                goto hmac_failed_etm_enabled;\n            }\n            ret = mbedtls_md_hmac_update(&transform->md_ctx_enc,\n                                         data, rec->data_len);\n            if (ret != 0) {\n                goto hmac_failed_etm_enabled;\n            }\n            ret = mbedtls_md_hmac_finish(&transform->md_ctx_enc, mac);\n            if (ret != 0) {\n                goto hmac_failed_etm_enabled;\n            }\n            ret = mbedtls_md_hmac_reset(&transform->md_ctx_enc);\n            if (ret != 0) {\n                goto hmac_failed_etm_enabled;\n            }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n            memcpy(data + rec->data_len, mac, transform->maclen);\n\n            rec->data_len += transform->maclen;\n            post_avail -= transform->maclen;\n            auth_done++;\n\nhmac_failed_etm_enabled:\n            mbedtls_platform_zeroize(mac, transform->maclen);\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            status = psa_mac_abort(&operation);\n            if (ret == 0 && status != PSA_SUCCESS) {\n                ret = PSA_TO_MBEDTLS_ERR(status);\n            }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"HMAC calculation failed\", ret);\n                return ret;\n            }\n        }\n#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */\n    } else\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC) */\n    {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    /* Make extra sure authentication was performed, exactly once */\n    if (auth_done != 1) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= encrypt buf\"));\n\n    return 0;\n}\n\nint mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl,\n                            mbedtls_ssl_transform *transform,\n                            mbedtls_record *rec)\n{\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) || defined(MBEDTLS_SSL_HAVE_AEAD)\n    size_t olen;\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC || MBEDTLS_SSL_HAVE_AEAD */\n    mbedtls_ssl_mode_t ssl_mode;\n    int ret;\n\n    int auth_done = 0;\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)\n    size_t padlen = 0;\n    mbedtls_ct_condition_t correct = MBEDTLS_CT_TRUE;\n#endif\n    unsigned char *data;\n    /* For an explanation of the additional data length see\n     * the description of ssl_extract_add_data_from_record().\n     */\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    unsigned char add_data[23 + MBEDTLS_SSL_CID_IN_LEN_MAX];\n#else\n    unsigned char add_data[13];\n#endif\n    size_t add_data_len;\n\n#if !defined(MBEDTLS_DEBUG_C)\n    ssl = NULL; /* make sure we don't use it except for debug */\n    ((void) ssl);\n#endif\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> decrypt buf\"));\n    if (rec == NULL                     ||\n        rec->buf == NULL                ||\n        rec->buf_len < rec->data_offset ||\n        rec->buf_len - rec->data_offset < rec->data_len) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad record structure provided to decrypt_buf\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    data = rec->buf + rec->data_offset;\n    ssl_mode = mbedtls_ssl_get_mode_from_transform(transform);\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    /*\n     * Match record's CID with incoming CID.\n     */\n    if (rec->cid_len != transform->in_cid_len ||\n        memcmp(rec->cid, transform->in_cid, rec->cid_len) != 0) {\n        return MBEDTLS_ERR_SSL_UNEXPECTED_CID;\n    }\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM)\n    if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) {\n        if (rec->data_len < transform->maclen) {\n            MBEDTLS_SSL_DEBUG_MSG(1,\n                                  (\"Record too short for MAC:\"\n                                   \" %\" MBEDTLS_PRINTF_SIZET \" < %\" MBEDTLS_PRINTF_SIZET,\n                                   rec->data_len, transform->maclen));\n            return MBEDTLS_ERR_SSL_INVALID_MAC;\n        }\n\n        /* The only supported stream cipher is \"NULL\",\n         * so there's no encryption to do here.*/\n    } else\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */\n#if defined(MBEDTLS_SSL_HAVE_AEAD)\n    if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) {\n        unsigned char iv[12];\n        unsigned char *dynamic_iv;\n        size_t dynamic_iv_len;\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        /*\n         * Extract dynamic part of nonce for AEAD decryption.\n         *\n         * Note: In the case of CCM and GCM in TLS 1.2, the dynamic\n         *       part of the IV is prepended to the ciphertext and\n         *       can be chosen freely - in particular, it need not\n         *       agree with the record sequence number.\n         */\n        dynamic_iv_len = sizeof(rec->ctr);\n        if (ssl_transform_aead_dynamic_iv_is_explicit(transform) == 1) {\n            if (rec->data_len < dynamic_iv_len) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"msglen (%\" MBEDTLS_PRINTF_SIZET\n                                          \" ) < explicit_iv_len (%\" MBEDTLS_PRINTF_SIZET \") \",\n                                          rec->data_len,\n                                          dynamic_iv_len));\n                return MBEDTLS_ERR_SSL_INVALID_MAC;\n            }\n            dynamic_iv = data;\n\n            data += dynamic_iv_len;\n            rec->data_offset += dynamic_iv_len;\n            rec->data_len    -= dynamic_iv_len;\n        } else {\n            dynamic_iv = rec->ctr;\n        }\n\n        /* Check that there's space for the authentication tag. */\n        if (rec->data_len < transform->taglen) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"msglen (%\" MBEDTLS_PRINTF_SIZET\n                                      \") < taglen (%\" MBEDTLS_PRINTF_SIZET \") \",\n                                      rec->data_len,\n                                      transform->taglen));\n            return MBEDTLS_ERR_SSL_INVALID_MAC;\n        }\n        rec->data_len -= transform->taglen;\n\n        /*\n         * Prepare nonce from dynamic and static parts.\n         */\n        ssl_build_record_nonce(iv, sizeof(iv),\n                               transform->iv_dec,\n                               transform->fixed_ivlen,\n                               dynamic_iv,\n                               dynamic_iv_len);\n\n        /*\n         * Build additional data for AEAD encryption.\n         * This depends on the TLS version.\n         */\n        ssl_extract_add_data_from_record(add_data, &add_data_len, rec,\n                                         transform->tls_version,\n                                         transform->taglen);\n        MBEDTLS_SSL_DEBUG_BUF(4, \"additional data used for AEAD\",\n                              add_data, add_data_len);\n\n        /* Because of the check above, we know that there are\n         * explicit_iv_len Bytes preceding data, and taglen\n         * bytes following data + data_len. This justifies\n         * the debug message and the invocation of\n         * mbedtls_cipher_auth_decrypt_ext() below. */\n\n        MBEDTLS_SSL_DEBUG_BUF(4, \"IV used\", iv, transform->ivlen);\n        MBEDTLS_SSL_DEBUG_BUF(4, \"TAG used\", data + rec->data_len,\n                              transform->taglen);\n\n        /*\n         * Decrypt and authenticate\n         */\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        status = psa_aead_decrypt(transform->psa_key_dec,\n                                  transform->psa_alg,\n                                  iv, transform->ivlen,\n                                  add_data, add_data_len,\n                                  data, rec->data_len + transform->taglen,\n                                  data, rec->buf_len - (data - rec->buf),\n                                  &olen);\n\n        if (status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_aead_decrypt\", ret);\n            return ret;\n        }\n#else\n        if ((ret = mbedtls_cipher_auth_decrypt_ext\n                       (&transform->cipher_ctx_dec,\n                       iv, transform->ivlen,\n                       add_data, add_data_len,\n                       data, rec->data_len + transform->taglen, /* src */\n                       data, rec->buf_len - (size_t) (data - rec->buf), &olen, /* dst */\n                       transform->taglen)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_cipher_auth_decrypt_ext\", ret);\n\n            if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) {\n                return MBEDTLS_ERR_SSL_INVALID_MAC;\n            }\n\n            return ret;\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        auth_done++;\n\n        /* Double-check that AEAD decryption doesn't change content length. */\n        if (olen != rec->data_len) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n    } else\n#endif /* MBEDTLS_SSL_HAVE_AEAD */\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC)\n    if (ssl_mode == MBEDTLS_SSL_MODE_CBC ||\n        ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {\n        size_t minlen = 0;\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n        size_t part_len;\n        psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        /*\n         * Check immediate ciphertext sanity\n         */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        /* The ciphertext is prefixed with the CBC IV. */\n        minlen += transform->ivlen;\n#endif\n\n        /* Size considerations:\n         *\n         * - The CBC cipher text must not be empty and hence\n         *   at least of size transform->ivlen.\n         *\n         * Together with the potential IV-prefix, this explains\n         * the first of the two checks below.\n         *\n         * - The record must contain a MAC, either in plain or\n         *   encrypted, depending on whether Encrypt-then-MAC\n         *   is used or not.\n         *   - If it is, the message contains the IV-prefix,\n         *     the CBC ciphertext, and the MAC.\n         *   - If it is not, the padded plaintext, and hence\n         *     the CBC ciphertext, has at least length maclen + 1\n         *     because there is at least the padding length byte.\n         *\n         * As the CBC ciphertext is not empty, both cases give the\n         * lower bound minlen + maclen + 1 on the record size, which\n         * we test for in the second check below.\n         */\n        if (rec->data_len < minlen + transform->ivlen ||\n            rec->data_len < minlen + transform->maclen + 1) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"msglen (%\" MBEDTLS_PRINTF_SIZET\n                                      \") < max( ivlen(%\" MBEDTLS_PRINTF_SIZET\n                                      \"), maclen (%\" MBEDTLS_PRINTF_SIZET \") \"\n                                                                          \"+ 1 ) ( + expl IV )\",\n                                      rec->data_len,\n                                      transform->ivlen,\n                                      transform->maclen));\n            return MBEDTLS_ERR_SSL_INVALID_MAC;\n        }\n\n        /*\n         * Authenticate before decrypt if enabled\n         */\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n        if (ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n            psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;\n#else\n            unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD];\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"using encrypt then mac\"));\n\n            /* Update data_len in tandem with add_data.\n             *\n             * The subtraction is safe because of the previous check\n             * data_len >= minlen + maclen + 1.\n             *\n             * Afterwards, we know that data + data_len is followed by at\n             * least maclen Bytes, which justifies the call to\n             * mbedtls_ct_memcmp() below.\n             *\n             * Further, we still know that data_len > minlen */\n            rec->data_len -= transform->maclen;\n            ssl_extract_add_data_from_record(add_data, &add_data_len, rec,\n                                             transform->tls_version,\n                                             transform->taglen);\n\n            /* Calculate expected MAC. */\n            MBEDTLS_SSL_DEBUG_BUF(4, \"MAC'd meta-data\", add_data,\n                                  add_data_len);\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n            status = psa_mac_verify_setup(&operation, transform->psa_mac_dec,\n                                          transform->psa_mac_alg);\n            if (status != PSA_SUCCESS) {\n                goto hmac_failed_etm_enabled;\n            }\n\n            status = psa_mac_update(&operation, add_data, add_data_len);\n            if (status != PSA_SUCCESS) {\n                goto hmac_failed_etm_enabled;\n            }\n\n            status = psa_mac_update(&operation, data, rec->data_len);\n            if (status != PSA_SUCCESS) {\n                goto hmac_failed_etm_enabled;\n            }\n\n            /* Compare expected MAC with MAC at the end of the record. */\n            status = psa_mac_verify_finish(&operation, data + rec->data_len,\n                                           transform->maclen);\n            if (status != PSA_SUCCESS) {\n                goto hmac_failed_etm_enabled;\n            }\n#else\n            ret = mbedtls_md_hmac_update(&transform->md_ctx_dec, add_data,\n                                         add_data_len);\n            if (ret != 0) {\n                goto hmac_failed_etm_enabled;\n            }\n            ret = mbedtls_md_hmac_update(&transform->md_ctx_dec,\n                                         data, rec->data_len);\n            if (ret != 0) {\n                goto hmac_failed_etm_enabled;\n            }\n            ret = mbedtls_md_hmac_finish(&transform->md_ctx_dec, mac_expect);\n            if (ret != 0) {\n                goto hmac_failed_etm_enabled;\n            }\n            ret = mbedtls_md_hmac_reset(&transform->md_ctx_dec);\n            if (ret != 0) {\n                goto hmac_failed_etm_enabled;\n            }\n\n            MBEDTLS_SSL_DEBUG_BUF(4, \"message  mac\", data + rec->data_len,\n                                  transform->maclen);\n            MBEDTLS_SSL_DEBUG_BUF(4, \"expected mac\", mac_expect,\n                                  transform->maclen);\n\n            /* Compare expected MAC with MAC at the end of the record. */\n            if (mbedtls_ct_memcmp(data + rec->data_len, mac_expect,\n                                  transform->maclen) != 0) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"message mac does not match\"));\n                ret = MBEDTLS_ERR_SSL_INVALID_MAC;\n                goto hmac_failed_etm_enabled;\n            }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n            auth_done++;\n\nhmac_failed_etm_enabled:\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            status = psa_mac_abort(&operation);\n            if (ret == 0 && status != PSA_SUCCESS) {\n                ret = PSA_TO_MBEDTLS_ERR(status);\n            }\n#else\n            mbedtls_platform_zeroize(mac_expect, transform->maclen);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n            if (ret != 0) {\n                if (ret != MBEDTLS_ERR_SSL_INVALID_MAC) {\n                    MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_hmac_xxx\", ret);\n                }\n                return ret;\n            }\n        }\n#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */\n\n        /*\n         * Check length sanity\n         */\n\n        /* We know from above that data_len > minlen >= 0,\n         * so the following check in particular implies that\n         * data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */\n        if (rec->data_len % transform->ivlen != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"msglen (%\" MBEDTLS_PRINTF_SIZET\n                                      \") %% ivlen (%\" MBEDTLS_PRINTF_SIZET \") != 0\",\n                                      rec->data_len, transform->ivlen));\n            return MBEDTLS_ERR_SSL_INVALID_MAC;\n        }\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        /*\n         * Initialize for prepended IV for block cipher in TLS v1.2\n         */\n        /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */\n        memcpy(transform->iv_dec, data, transform->ivlen);\n\n        data += transform->ivlen;\n        rec->data_offset += transform->ivlen;\n        rec->data_len -= transform->ivlen;\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n        /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        status = psa_cipher_decrypt_setup(&cipher_op,\n                                          transform->psa_key_dec, transform->psa_alg);\n\n        if (status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_cipher_decrypt_setup\", ret);\n            return ret;\n        }\n\n        status = psa_cipher_set_iv(&cipher_op, transform->iv_dec, transform->ivlen);\n\n        if (status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_cipher_set_iv\", ret);\n            return ret;\n        }\n\n        status = psa_cipher_update(&cipher_op,\n                                   data, rec->data_len,\n                                   data, rec->data_len, &olen);\n\n        if (status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_cipher_update\", ret);\n            return ret;\n        }\n\n        status = psa_cipher_finish(&cipher_op,\n                                   data + olen, rec->data_len - olen,\n                                   &part_len);\n\n        if (status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_cipher_finish\", ret);\n            return ret;\n        }\n\n        olen += part_len;\n#else\n\n        if ((ret = mbedtls_cipher_crypt(&transform->cipher_ctx_dec,\n                                        transform->iv_dec, transform->ivlen,\n                                        data, rec->data_len, data, &olen)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_cipher_crypt\", ret);\n            return ret;\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        /* Double-check that length hasn't changed during decryption. */\n        if (rec->data_len != olen) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        /* Safe since data_len >= minlen + maclen + 1, so after having\n         * subtracted at most minlen and maclen up to this point,\n         * data_len > 0 (because of data_len % ivlen == 0, it's actually\n         * >= ivlen ). */\n        padlen = data[rec->data_len - 1];\n\n        if (auth_done == 1) {\n            const mbedtls_ct_condition_t ge = mbedtls_ct_uint_ge(\n                rec->data_len,\n                padlen + 1);\n            correct = mbedtls_ct_bool_and(ge, correct);\n            padlen  = mbedtls_ct_size_if_else_0(ge, padlen);\n        } else {\n#if defined(MBEDTLS_SSL_DEBUG_ALL)\n            if (rec->data_len < transform->maclen + padlen + 1) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"msglen (%\" MBEDTLS_PRINTF_SIZET\n                                          \") < maclen (%\" MBEDTLS_PRINTF_SIZET\n                                          \") + padlen (%\" MBEDTLS_PRINTF_SIZET \")\",\n                                          rec->data_len,\n                                          transform->maclen,\n                                          padlen + 1));\n            }\n#endif\n            const mbedtls_ct_condition_t ge = mbedtls_ct_uint_ge(\n                rec->data_len,\n                transform->maclen + padlen + 1);\n            correct = mbedtls_ct_bool_and(ge, correct);\n            padlen  = mbedtls_ct_size_if_else_0(ge, padlen);\n        }\n\n        padlen++;\n\n        /* Regardless of the validity of the padding,\n         * we have data_len >= padlen here. */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        /* The padding check involves a series of up to 256\n         * consecutive memory reads at the end of the record\n         * plaintext buffer. In order to hide the length and\n         * validity of the padding, always perform exactly\n         * `min(256,plaintext_len)` reads (but take into account\n         * only the last `padlen` bytes for the padding check). */\n        size_t pad_count = 0;\n        volatile unsigned char * const check = data;\n\n        /* Index of first padding byte; it has been ensured above\n         * that the subtraction is safe. */\n        size_t const padding_idx = rec->data_len - padlen;\n        size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256;\n        size_t const start_idx = rec->data_len - num_checks;\n        size_t idx;\n\n        for (idx = start_idx; idx < rec->data_len; idx++) {\n            /* pad_count += (idx >= padding_idx) &&\n             *              (check[idx] == padlen - 1);\n             */\n            const mbedtls_ct_condition_t a = mbedtls_ct_uint_ge(idx, padding_idx);\n            size_t increment = mbedtls_ct_size_if_else_0(a, 1);\n            const mbedtls_ct_condition_t b = mbedtls_ct_uint_eq(check[idx], padlen - 1);\n            increment = mbedtls_ct_size_if_else_0(b, increment);\n            pad_count += increment;\n        }\n        correct = mbedtls_ct_bool_and(mbedtls_ct_uint_eq(pad_count, padlen), correct);\n\n#if defined(MBEDTLS_SSL_DEBUG_ALL)\n        if (padlen > 0 && correct == MBEDTLS_CT_FALSE) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad padding byte detected\"));\n        }\n#endif\n        padlen = mbedtls_ct_size_if_else_0(correct, padlen);\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n        /* If the padding was found to be invalid, padlen == 0\n         * and the subtraction is safe. If the padding was found valid,\n         * padlen hasn't been changed and the previous assertion\n         * data_len >= padlen still holds. */\n        rec->data_len -= padlen;\n    } else\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC */\n    {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n#if defined(MBEDTLS_SSL_DEBUG_ALL)\n    MBEDTLS_SSL_DEBUG_BUF(4, \"raw buffer after decryption\",\n                          data, rec->data_len);\n#endif\n\n    /*\n     * Authenticate if not done yet.\n     * Compute the MAC regardless of the padding result (RFC4346, CBCTIME).\n     */\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)\n    if (auth_done == 0) {\n        unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD] = { 0 };\n        unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD] = { 0 };\n\n        /* For CBC+MAC, If the initial value of padlen was such that\n         * data_len < maclen + padlen + 1, then padlen\n         * got reset to 1, and the initial check\n         * data_len >= minlen + maclen + 1\n         * guarantees that at this point we still\n         * have at least data_len >= maclen.\n         *\n         * If the initial value of padlen was such that\n         * data_len >= maclen + padlen + 1, then we have\n         * subtracted either padlen + 1 (if the padding was correct)\n         * or 0 (if the padding was incorrect) since then,\n         * hence data_len >= maclen in any case.\n         *\n         * For stream ciphers, we checked above that\n         * data_len >= maclen.\n         */\n        rec->data_len -= transform->maclen;\n        ssl_extract_add_data_from_record(add_data, &add_data_len, rec,\n                                         transform->tls_version,\n                                         transform->taglen);\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        /*\n         * The next two sizes are the minimum and maximum values of\n         * data_len over all padlen values.\n         *\n         * They're independent of padlen, since we previously did\n         * data_len -= padlen.\n         *\n         * Note that max_len + maclen is never more than the buffer\n         * length, as we previously did in_msglen -= maclen too.\n         */\n        const size_t max_len = rec->data_len + padlen;\n        const size_t min_len = (max_len > 256) ? max_len - 256 : 0;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        ret = mbedtls_ct_hmac(transform->psa_mac_dec,\n                              transform->psa_mac_alg,\n                              add_data, add_data_len,\n                              data, rec->data_len, min_len, max_len,\n                              mac_expect);\n#else\n        ret = mbedtls_ct_hmac(&transform->md_ctx_dec,\n                              add_data, add_data_len,\n                              data, rec->data_len, min_len, max_len,\n                              mac_expect);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ct_hmac\", ret);\n            goto hmac_failed_etm_disabled;\n        }\n\n        mbedtls_ct_memcpy_offset(mac_peer, data,\n                                 rec->data_len,\n                                 min_len, max_len,\n                                 transform->maclen);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n#if defined(MBEDTLS_SSL_DEBUG_ALL)\n        MBEDTLS_SSL_DEBUG_BUF(4, \"expected mac\", mac_expect, transform->maclen);\n        MBEDTLS_SSL_DEBUG_BUF(4, \"message  mac\", mac_peer, transform->maclen);\n#endif\n\n        if (mbedtls_ct_memcmp(mac_peer, mac_expect,\n                              transform->maclen) != 0) {\n#if defined(MBEDTLS_SSL_DEBUG_ALL)\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"message mac does not match\"));\n#endif\n            correct = MBEDTLS_CT_FALSE;\n        }\n        auth_done++;\n\nhmac_failed_etm_disabled:\n        mbedtls_platform_zeroize(mac_peer, transform->maclen);\n        mbedtls_platform_zeroize(mac_expect, transform->maclen);\n        if (ret != 0) {\n            return ret;\n        }\n    }\n\n    /*\n     * Finally check the correct flag\n     */\n    if (correct == MBEDTLS_CT_FALSE) {\n        return MBEDTLS_ERR_SSL_INVALID_MAC;\n    }\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */\n\n    /* Make extra sure authentication was performed, exactly once */\n    if (auth_done != 1) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    if (transform->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {\n        /* Remove inner padding and infer true content type. */\n        ret = ssl_parse_inner_plaintext(data, &rec->data_len,\n                                        &rec->type);\n\n        if (ret != 0) {\n            return MBEDTLS_ERR_SSL_INVALID_RECORD;\n        }\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    if (rec->cid_len != 0) {\n        ret = ssl_parse_inner_plaintext(data, &rec->data_len,\n                                        &rec->type);\n        if (ret != 0) {\n            return MBEDTLS_ERR_SSL_INVALID_RECORD;\n        }\n    }\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= decrypt buf\"));\n\n    return 0;\n}\n\n#undef MAC_NONE\n#undef MAC_PLAINTEXT\n#undef MAC_CIPHERTEXT\n\n/*\n * Fill the input message buffer by appending data to it.\n * The amount of data already fetched is in ssl->in_left.\n *\n * If we return 0, is it guaranteed that (at least) nb_want bytes are\n * available (from this read and/or a previous one). Otherwise, an error code\n * is returned (possibly EOF or WANT_READ).\n *\n * With stream transport (TLS) on success ssl->in_left == nb_want, but\n * with datagram transport (DTLS) on success ssl->in_left >= nb_want,\n * since we always read a whole datagram at once.\n *\n * For DTLS, it is up to the caller to set ssl->next_record_offset when\n * they're done reading a record.\n */\nint mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n    size_t in_buf_len = ssl->in_buf_len;\n#else\n    size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;\n#endif\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> fetch input\"));\n\n    if (ssl->f_recv == NULL && ssl->f_recv_timeout == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Bad usage of mbedtls_ssl_set_bio() \"));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if (nb_want > in_buf_len - (size_t) (ssl->in_hdr - ssl->in_buf)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"requesting more data than fits\"));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        uint32_t timeout;\n\n        /*\n         * The point is, we need to always read a full datagram at once, so we\n         * sometimes read more then requested, and handle the additional data.\n         * It could be the rest of the current record (while fetching the\n         * header) and/or some other records in the same datagram.\n         */\n\n        /*\n         * Move to the next record in the already read datagram if applicable\n         */\n        if (ssl->next_record_offset != 0) {\n            if (ssl->in_left < ssl->next_record_offset) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n            }\n\n            ssl->in_left -= ssl->next_record_offset;\n\n            if (ssl->in_left != 0) {\n                MBEDTLS_SSL_DEBUG_MSG(2, (\"next record in same datagram, offset: %\"\n                                          MBEDTLS_PRINTF_SIZET,\n                                          ssl->next_record_offset));\n                memmove(ssl->in_hdr,\n                        ssl->in_hdr + ssl->next_record_offset,\n                        ssl->in_left);\n            }\n\n            ssl->next_record_offset = 0;\n        }\n\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"in_left: %\" MBEDTLS_PRINTF_SIZET\n                                  \", nb_want: %\" MBEDTLS_PRINTF_SIZET,\n                                  ssl->in_left, nb_want));\n\n        /*\n         * Done if we already have enough data.\n         */\n        if (nb_want <= ssl->in_left) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"<= fetch input\"));\n            return 0;\n        }\n\n        /*\n         * A record can't be split across datagrams. If we need to read but\n         * are not at the beginning of a new record, the caller did something\n         * wrong.\n         */\n        if (ssl->in_left != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        /*\n         * Don't even try to read if time's out already.\n         * This avoids by-passing the timer when repeatedly receiving messages\n         * that will end up being dropped.\n         */\n        if (mbedtls_ssl_check_timer(ssl) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"timer has expired\"));\n            ret = MBEDTLS_ERR_SSL_TIMEOUT;\n        } else {\n            len = in_buf_len - (size_t) (ssl->in_hdr - ssl->in_buf);\n\n            if (mbedtls_ssl_is_handshake_over(ssl) == 0) {\n                timeout = ssl->handshake->retransmit_timeout;\n            } else {\n                timeout = ssl->conf->read_timeout;\n            }\n\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"f_recv_timeout: %lu ms\", (unsigned long) timeout));\n\n            if (ssl->f_recv_timeout != NULL) {\n                ret = ssl->f_recv_timeout(ssl->p_bio, ssl->in_hdr, len,\n                                          timeout);\n            } else {\n                ret = ssl->f_recv(ssl->p_bio, ssl->in_hdr, len);\n            }\n\n            MBEDTLS_SSL_DEBUG_RET(2, \"ssl->f_recv(_timeout)\", ret);\n\n            if (ret == 0) {\n                return MBEDTLS_ERR_SSL_CONN_EOF;\n            }\n        }\n\n        if (ret == MBEDTLS_ERR_SSL_TIMEOUT) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"timeout\"));\n            mbedtls_ssl_set_timer(ssl, 0);\n\n            if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) {\n                if (ssl_double_retransmit_timeout(ssl) != 0) {\n                    MBEDTLS_SSL_DEBUG_MSG(1, (\"handshake timeout\"));\n                    return MBEDTLS_ERR_SSL_TIMEOUT;\n                }\n\n                if ((ret = mbedtls_ssl_resend(ssl)) != 0) {\n                    MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_resend\", ret);\n                    return ret;\n                }\n\n                return MBEDTLS_ERR_SSL_WANT_READ;\n            }\n#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)\n            else if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&\n                     ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) {\n                if ((ret = mbedtls_ssl_resend_hello_request(ssl)) != 0) {\n                    MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_resend_hello_request\",\n                                          ret);\n                    return ret;\n                }\n\n                return MBEDTLS_ERR_SSL_WANT_READ;\n            }\n#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */\n        }\n\n        if (ret < 0) {\n            return ret;\n        }\n\n        ssl->in_left = ret;\n    } else\n#endif\n    {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"in_left: %\" MBEDTLS_PRINTF_SIZET\n                                  \", nb_want: %\" MBEDTLS_PRINTF_SIZET,\n                                  ssl->in_left, nb_want));\n\n        while (ssl->in_left < nb_want) {\n            len = nb_want - ssl->in_left;\n\n            if (mbedtls_ssl_check_timer(ssl) != 0) {\n                ret = MBEDTLS_ERR_SSL_TIMEOUT;\n            } else {\n                if (ssl->f_recv_timeout != NULL) {\n                    ret = ssl->f_recv_timeout(ssl->p_bio,\n                                              ssl->in_hdr + ssl->in_left, len,\n                                              ssl->conf->read_timeout);\n                } else {\n                    ret = ssl->f_recv(ssl->p_bio,\n                                      ssl->in_hdr + ssl->in_left, len);\n                }\n            }\n\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"in_left: %\" MBEDTLS_PRINTF_SIZET\n                                      \", nb_want: %\" MBEDTLS_PRINTF_SIZET,\n                                      ssl->in_left, nb_want));\n            MBEDTLS_SSL_DEBUG_RET(2, \"ssl->f_recv(_timeout)\", ret);\n\n            if (ret == 0) {\n                return MBEDTLS_ERR_SSL_CONN_EOF;\n            }\n\n            if (ret < 0) {\n                return ret;\n            }\n\n            if ((size_t) ret > len) {\n                MBEDTLS_SSL_DEBUG_MSG(1,\n                                      (\"f_recv returned %d bytes but only %\" MBEDTLS_PRINTF_SIZET\n                                       \" were requested\",\n                                       ret, len));\n                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n            }\n\n            ssl->in_left += ret;\n        }\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= fetch input\"));\n\n    return 0;\n}\n\n/*\n * Flush any data not yet written\n */\nint mbedtls_ssl_flush_output(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *buf;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> flush output\"));\n\n    if (ssl->f_send == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Bad usage of mbedtls_ssl_set_bio() \"));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    /* Avoid incrementing counter if data is flushed */\n    if (ssl->out_left == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= flush output\"));\n        return 0;\n    }\n\n    while (ssl->out_left > 0) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"message length: %\" MBEDTLS_PRINTF_SIZET\n                                  \", out_left: %\" MBEDTLS_PRINTF_SIZET,\n                                  mbedtls_ssl_out_hdr_len(ssl) + ssl->out_msglen, ssl->out_left));\n\n        buf = ssl->out_hdr - ssl->out_left;\n        ret = ssl->f_send(ssl->p_bio, buf, ssl->out_left);\n\n        MBEDTLS_SSL_DEBUG_RET(2, \"ssl->f_send\", ret);\n\n        if (ret <= 0) {\n            return ret;\n        }\n\n        if ((size_t) ret > ssl->out_left) {\n            MBEDTLS_SSL_DEBUG_MSG(1,\n                                  (\"f_send returned %d bytes but only %\" MBEDTLS_PRINTF_SIZET\n                                   \" bytes were sent\",\n                                   ret, ssl->out_left));\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        ssl->out_left -= ret;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        ssl->out_hdr = ssl->out_buf;\n    } else\n#endif\n    {\n        ssl->out_hdr = ssl->out_buf + 8;\n    }\n    mbedtls_ssl_update_out_pointers(ssl, ssl->transform_out);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= flush output\"));\n\n    return 0;\n}\n\n/*\n * Functions to handle the DTLS retransmission state machine\n */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n/*\n * Append current handshake message to current outgoing flight\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_flight_append(mbedtls_ssl_context *ssl)\n{\n    mbedtls_ssl_flight_item *msg;\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> ssl_flight_append\"));\n    MBEDTLS_SSL_DEBUG_BUF(4, \"message appended to flight\",\n                          ssl->out_msg, ssl->out_msglen);\n\n    /* Allocate space for current message */\n    if ((msg = mbedtls_calloc(1, sizeof(mbedtls_ssl_flight_item))) == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"alloc %\" MBEDTLS_PRINTF_SIZET \" bytes failed\",\n                                  sizeof(mbedtls_ssl_flight_item)));\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n    if ((msg->p = mbedtls_calloc(1, ssl->out_msglen)) == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"alloc %\" MBEDTLS_PRINTF_SIZET \" bytes failed\",\n                                  ssl->out_msglen));\n        mbedtls_free(msg);\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n    /* Copy current handshake message with headers */\n    memcpy(msg->p, ssl->out_msg, ssl->out_msglen);\n    msg->len = ssl->out_msglen;\n    msg->type = ssl->out_msgtype;\n    msg->next = NULL;\n\n    /* Append to the current flight */\n    if (ssl->handshake->flight == NULL) {\n        ssl->handshake->flight = msg;\n    } else {\n        mbedtls_ssl_flight_item *cur = ssl->handshake->flight;\n        while (cur->next != NULL) {\n            cur = cur->next;\n        }\n        cur->next = msg;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= ssl_flight_append\"));\n    return 0;\n}\n\n/*\n * Free the current flight of handshake messages\n */\nvoid mbedtls_ssl_flight_free(mbedtls_ssl_flight_item *flight)\n{\n    mbedtls_ssl_flight_item *cur = flight;\n    mbedtls_ssl_flight_item *next;\n\n    while (cur != NULL) {\n        next = cur->next;\n\n        mbedtls_free(cur->p);\n        mbedtls_free(cur);\n\n        cur = next;\n    }\n}\n\n/*\n * Swap transform_out and out_ctr with the alternative ones\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_swap_epochs(mbedtls_ssl_context *ssl)\n{\n    mbedtls_ssl_transform *tmp_transform;\n    unsigned char tmp_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN];\n\n    if (ssl->transform_out == ssl->handshake->alt_transform_out) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"skip swap epochs\"));\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"swap epochs\"));\n\n    /* Swap transforms */\n    tmp_transform                     = ssl->transform_out;\n    ssl->transform_out                = ssl->handshake->alt_transform_out;\n    ssl->handshake->alt_transform_out = tmp_transform;\n\n    /* Swap epoch + sequence_number */\n    memcpy(tmp_out_ctr, ssl->cur_out_ctr, sizeof(tmp_out_ctr));\n    memcpy(ssl->cur_out_ctr, ssl->handshake->alt_out_ctr,\n           sizeof(ssl->cur_out_ctr));\n    memcpy(ssl->handshake->alt_out_ctr, tmp_out_ctr,\n           sizeof(ssl->handshake->alt_out_ctr));\n\n    /* Adjust to the newly activated transform */\n    mbedtls_ssl_update_out_pointers(ssl, ssl->transform_out);\n\n    return 0;\n}\n\n/*\n * Retransmit the current flight of messages.\n */\nint mbedtls_ssl_resend(mbedtls_ssl_context *ssl)\n{\n    int ret = 0;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> mbedtls_ssl_resend\"));\n\n    ret = mbedtls_ssl_flight_transmit(ssl);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= mbedtls_ssl_resend\"));\n\n    return ret;\n}\n\n/*\n * Transmit or retransmit the current flight of messages.\n *\n * Need to remember the current message in case flush_output returns\n * WANT_WRITE, causing us to exit this function and come back later.\n * This function must be called until state is no longer SENDING.\n */\nint mbedtls_ssl_flight_transmit(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> mbedtls_ssl_flight_transmit\"));\n\n    if (ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"initialise flight transmission\"));\n\n        ssl->handshake->cur_msg = ssl->handshake->flight;\n        ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12;\n        ret = ssl_swap_epochs(ssl);\n        if (ret != 0) {\n            return ret;\n        }\n\n        ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING;\n    }\n\n    while (ssl->handshake->cur_msg != NULL) {\n        size_t max_frag_len;\n        const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg;\n\n        int const is_finished =\n            (cur->type == MBEDTLS_SSL_MSG_HANDSHAKE &&\n             cur->p[0] == MBEDTLS_SSL_HS_FINISHED);\n\n        int const force_flush = ssl->disable_datagram_packing == 1 ?\n                                SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH;\n\n        /* Swap epochs before sending Finished: we can't do it after\n         * sending ChangeCipherSpec, in case write returns WANT_READ.\n         * Must be done before copying, may change out_msg pointer */\n        if (is_finished && ssl->handshake->cur_msg_p == (cur->p + 12)) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"swap epochs to send finished message\"));\n            ret = ssl_swap_epochs(ssl);\n            if (ret != 0) {\n                return ret;\n            }\n        }\n\n        ret = ssl_get_remaining_payload_in_datagram(ssl);\n        if (ret < 0) {\n            return ret;\n        }\n        max_frag_len = (size_t) ret;\n\n        /* CCS is copied as is, while HS messages may need fragmentation */\n        if (cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) {\n            if (max_frag_len == 0) {\n                if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) {\n                    return ret;\n                }\n\n                continue;\n            }\n\n            memcpy(ssl->out_msg, cur->p, cur->len);\n            ssl->out_msglen  = cur->len;\n            ssl->out_msgtype = cur->type;\n\n            /* Update position inside current message */\n            ssl->handshake->cur_msg_p += cur->len;\n        } else {\n            const unsigned char * const p = ssl->handshake->cur_msg_p;\n            const size_t hs_len = cur->len - 12;\n            const size_t frag_off = (size_t) (p - (cur->p + 12));\n            const size_t rem_len = hs_len - frag_off;\n            size_t cur_hs_frag_len, max_hs_frag_len;\n\n            if ((max_frag_len < 12) || (max_frag_len == 12 && hs_len != 0)) {\n                if (is_finished) {\n                    ret = ssl_swap_epochs(ssl);\n                    if (ret != 0) {\n                        return ret;\n                    }\n                }\n\n                if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) {\n                    return ret;\n                }\n\n                continue;\n            }\n            max_hs_frag_len = max_frag_len - 12;\n\n            cur_hs_frag_len = rem_len > max_hs_frag_len ?\n                              max_hs_frag_len : rem_len;\n\n            if (frag_off == 0 && cur_hs_frag_len != hs_len) {\n                MBEDTLS_SSL_DEBUG_MSG(2, (\"fragmenting handshake message (%u > %u)\",\n                                          (unsigned) cur_hs_frag_len,\n                                          (unsigned) max_hs_frag_len));\n            }\n\n            /* Messages are stored with handshake headers as if not fragmented,\n             * copy beginning of headers then fill fragmentation fields.\n             * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */\n            memcpy(ssl->out_msg, cur->p, 6);\n\n            ssl->out_msg[6] = MBEDTLS_BYTE_2(frag_off);\n            ssl->out_msg[7] = MBEDTLS_BYTE_1(frag_off);\n            ssl->out_msg[8] = MBEDTLS_BYTE_0(frag_off);\n\n            ssl->out_msg[9] = MBEDTLS_BYTE_2(cur_hs_frag_len);\n            ssl->out_msg[10] = MBEDTLS_BYTE_1(cur_hs_frag_len);\n            ssl->out_msg[11] = MBEDTLS_BYTE_0(cur_hs_frag_len);\n\n            MBEDTLS_SSL_DEBUG_BUF(3, \"handshake header\", ssl->out_msg, 12);\n\n            /* Copy the handshake message content and set records fields */\n            memcpy(ssl->out_msg + 12, p, cur_hs_frag_len);\n            ssl->out_msglen = cur_hs_frag_len + 12;\n            ssl->out_msgtype = cur->type;\n\n            /* Update position inside current message */\n            ssl->handshake->cur_msg_p += cur_hs_frag_len;\n        }\n\n        /* If done with the current message move to the next one if any */\n        if (ssl->handshake->cur_msg_p >= cur->p + cur->len) {\n            if (cur->next != NULL) {\n                ssl->handshake->cur_msg = cur->next;\n                ssl->handshake->cur_msg_p = cur->next->p + 12;\n            } else {\n                ssl->handshake->cur_msg = NULL;\n                ssl->handshake->cur_msg_p = NULL;\n            }\n        }\n\n        /* Actually send the message out */\n        if ((ret = mbedtls_ssl_write_record(ssl, force_flush)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_write_record\", ret);\n            return ret;\n        }\n    }\n\n    if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) {\n        return ret;\n    }\n\n    /* Update state and set timer */\n    if (mbedtls_ssl_is_handshake_over(ssl) == 1) {\n        ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;\n    } else {\n        ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;\n        mbedtls_ssl_set_timer(ssl, ssl->handshake->retransmit_timeout);\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= mbedtls_ssl_flight_transmit\"));\n\n    return 0;\n}\n\n/*\n * To be called when the last message of an incoming flight is received.\n */\nvoid mbedtls_ssl_recv_flight_completed(mbedtls_ssl_context *ssl)\n{\n    /* We won't need to resend that one any more */\n    mbedtls_ssl_flight_free(ssl->handshake->flight);\n    ssl->handshake->flight = NULL;\n    ssl->handshake->cur_msg = NULL;\n\n    /* The next incoming flight will start with this msg_seq */\n    ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq;\n\n    /* We don't want to remember CCS's across flight boundaries. */\n    ssl->handshake->buffering.seen_ccs = 0;\n\n    /* Clear future message buffering structure. */\n    mbedtls_ssl_buffering_free(ssl);\n\n    /* Cancel timer */\n    mbedtls_ssl_set_timer(ssl, 0);\n\n    if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&\n        ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED) {\n        ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;\n    } else {\n        ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING;\n    }\n}\n\n/*\n * To be called when the last message of an outgoing flight is send.\n */\nvoid mbedtls_ssl_send_flight_completed(mbedtls_ssl_context *ssl)\n{\n    ssl_reset_retransmit_timeout(ssl);\n    mbedtls_ssl_set_timer(ssl, ssl->handshake->retransmit_timeout);\n\n    if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&\n        ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED) {\n        ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;\n    } else {\n        ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;\n    }\n}\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n/*\n * Handshake layer functions\n */\nint mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned char hs_type,\n                                    unsigned char **buf, size_t *buf_len)\n{\n    /*\n     * Reserve 4 bytes for handshake header. ( Section 4,RFC 8446 )\n     *    ...\n     *    HandshakeType msg_type;\n     *    uint24 length;\n     *    ...\n     */\n    *buf = ssl->out_msg + 4;\n    *buf_len = MBEDTLS_SSL_OUT_CONTENT_LEN - 4;\n\n    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;\n    ssl->out_msg[0]  = hs_type;\n\n    return 0;\n}\n\n/*\n * Write (DTLS: or queue) current handshake (including CCS) message.\n *\n *  - fill in handshake headers\n *  - update handshake checksum\n *  - DTLS: save message for resending\n *  - then pass to the record layer\n *\n * DTLS: except for HelloRequest, messages are only queued, and will only be\n * actually sent when calling flight_transmit() or resend().\n *\n * Inputs:\n *  - ssl->out_msglen: 4 + actual handshake message len\n *      (4 is the size of handshake headers for TLS)\n *  - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc)\n *  - ssl->out_msg + 4: the handshake message body\n *\n * Outputs, ie state before passing to flight_append() or write_record():\n *   - ssl->out_msglen: the length of the record contents\n *      (including handshake headers but excluding record headers)\n *   - ssl->out_msg: the record contents (handshake headers + content)\n */\nint mbedtls_ssl_write_handshake_msg_ext(mbedtls_ssl_context *ssl,\n                                        int update_checksum,\n                                        int force_flush)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const size_t hs_len = ssl->out_msglen - 4;\n    const unsigned char hs_type = ssl->out_msg[0];\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write handshake message\"));\n\n    /*\n     * Sanity checks\n     */\n    if (ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE          &&\n        ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    /* Whenever we send anything different from a\n     * HelloRequest we should be in a handshake - double check. */\n    if (!(ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&\n          hs_type          == MBEDTLS_SSL_HS_HELLO_REQUEST) &&\n        ssl->handshake == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n        ssl->handshake != NULL &&\n        ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n#endif\n\n    /* Double-check that we did not exceed the bounds\n     * of the outgoing record buffer.\n     * This should never fail as the various message\n     * writing functions must obey the bounds of the\n     * outgoing record buffer, but better be safe.\n     *\n     * Note: We deliberately do not check for the MTU or MFL here.\n     */\n    if (ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Record too large: \"\n                                  \"size %\" MBEDTLS_PRINTF_SIZET\n                                  \", maximum %\" MBEDTLS_PRINTF_SIZET,\n                                  ssl->out_msglen,\n                                  (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    /*\n     * Fill handshake headers\n     */\n    if (ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) {\n        ssl->out_msg[1] = MBEDTLS_BYTE_2(hs_len);\n        ssl->out_msg[2] = MBEDTLS_BYTE_1(hs_len);\n        ssl->out_msg[3] = MBEDTLS_BYTE_0(hs_len);\n\n        /*\n         * DTLS has additional fields in the Handshake layer,\n         * between the length field and the actual payload:\n         *      uint16 message_seq;\n         *      uint24 fragment_offset;\n         *      uint24 fragment_length;\n         */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n            /* Make room for the additional DTLS fields */\n            if (MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"DTLS handshake message too large: \"\n                                          \"size %\" MBEDTLS_PRINTF_SIZET \", maximum %\"\n                                          MBEDTLS_PRINTF_SIZET,\n                                          hs_len,\n                                          (size_t) (MBEDTLS_SSL_OUT_CONTENT_LEN - 12)));\n                return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n            }\n\n            memmove(ssl->out_msg + 12, ssl->out_msg + 4, hs_len);\n            ssl->out_msglen += 8;\n\n            /* Write message_seq and update it, except for HelloRequest */\n            if (hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST) {\n                MBEDTLS_PUT_UINT16_BE(ssl->handshake->out_msg_seq, ssl->out_msg, 4);\n                ++(ssl->handshake->out_msg_seq);\n            } else {\n                ssl->out_msg[4] = 0;\n                ssl->out_msg[5] = 0;\n            }\n\n            /* Handshake hashes are computed without fragmentation,\n             * so set frag_offset = 0 and frag_len = hs_len for now */\n            memset(ssl->out_msg + 6, 0x00, 3);\n            memcpy(ssl->out_msg + 9, ssl->out_msg + 1, 3);\n        }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n        /* Update running hashes of handshake messages seen */\n        if (hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST && update_checksum != 0) {\n            ret = ssl->handshake->update_checksum(ssl, ssl->out_msg,\n                                                  ssl->out_msglen);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"update_checksum\", ret);\n                return ret;\n            }\n        }\n    }\n\n    /* Either send now, or just save to be sent (and resent) later */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n        !(ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&\n          hs_type          == MBEDTLS_SSL_HS_HELLO_REQUEST)) {\n        if ((ret = ssl_flight_append(ssl)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"ssl_flight_append\", ret);\n            return ret;\n        }\n    } else\n#endif\n    {\n        if ((ret = mbedtls_ssl_write_record(ssl, force_flush)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"ssl_write_record\", ret);\n            return ret;\n        }\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write handshake message\"));\n\n    return 0;\n}\n\nint mbedtls_ssl_finish_handshake_msg(mbedtls_ssl_context *ssl,\n                                     size_t buf_len, size_t msg_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t msg_with_header_len;\n    ((void) buf_len);\n\n    /* Add reserved 4 bytes for handshake header */\n    msg_with_header_len = msg_len + 4;\n    ssl->out_msglen = msg_with_header_len;\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_handshake_msg_ext(ssl, 0, 0));\n\ncleanup:\n    return ret;\n}\n\n/*\n * Record layer functions\n */\n\n/*\n * Write current record.\n *\n * Uses:\n *  - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS)\n *  - ssl->out_msglen: length of the record content (excl headers)\n *  - ssl->out_msg: record content\n */\nint mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, int force_flush)\n{\n    int ret, done = 0;\n    size_t len = ssl->out_msglen;\n    int flush = force_flush;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write record\"));\n\n    if (!done) {\n        unsigned i;\n        size_t protected_record_size;\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n        size_t out_buf_len = ssl->out_buf_len;\n#else\n        size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;\n#endif\n        /* Skip writing the record content type to after the encryption,\n         * as it may change when using the CID extension. */\n        mbedtls_ssl_protocol_version tls_ver = ssl->tls_version;\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n        /* TLS 1.3 still uses the TLS 1.2 version identifier\n         * for backwards compatibility. */\n        if (tls_ver == MBEDTLS_SSL_VERSION_TLS1_3) {\n            tls_ver = MBEDTLS_SSL_VERSION_TLS1_2;\n        }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n        mbedtls_ssl_write_version(ssl->out_hdr + 1, ssl->conf->transport,\n                                  tls_ver);\n\n        memcpy(ssl->out_ctr, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN);\n        MBEDTLS_PUT_UINT16_BE(len, ssl->out_len, 0);\n\n        if (ssl->transform_out != NULL) {\n            mbedtls_record rec;\n\n            rec.buf         = ssl->out_iv;\n            rec.buf_len     = out_buf_len - (size_t) (ssl->out_iv - ssl->out_buf);\n            rec.data_len    = ssl->out_msglen;\n            rec.data_offset = (size_t) (ssl->out_msg - rec.buf);\n\n            memcpy(&rec.ctr[0], ssl->out_ctr, sizeof(rec.ctr));\n            mbedtls_ssl_write_version(rec.ver, ssl->conf->transport, tls_ver);\n            rec.type = ssl->out_msgtype;\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n            /* The CID is set by mbedtls_ssl_encrypt_buf(). */\n            rec.cid_len = 0;\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n            if ((ret = mbedtls_ssl_encrypt_buf(ssl, ssl->transform_out, &rec,\n                                               ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"ssl_encrypt_buf\", ret);\n                return ret;\n            }\n\n            if (rec.data_offset != 0) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n            }\n\n            /* Update the record content type and CID. */\n            ssl->out_msgtype = rec.type;\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n            memcpy(ssl->out_cid, rec.cid, rec.cid_len);\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n            ssl->out_msglen = len = rec.data_len;\n            MBEDTLS_PUT_UINT16_BE(rec.data_len, ssl->out_len, 0);\n        }\n\n        protected_record_size = len + mbedtls_ssl_out_hdr_len(ssl);\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n        /* In case of DTLS, double-check that we don't exceed\n         * the remaining space in the datagram. */\n        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n            ret = ssl_get_remaining_space_in_datagram(ssl);\n            if (ret < 0) {\n                return ret;\n            }\n\n            if (protected_record_size > (size_t) ret) {\n                /* Should never happen */\n                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n            }\n        }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n        /* Now write the potentially updated record content type. */\n        ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;\n\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"output record: msgtype = %u, \"\n                                  \"version = [%u:%u], msglen = %\" MBEDTLS_PRINTF_SIZET,\n                                  ssl->out_hdr[0], ssl->out_hdr[1],\n                                  ssl->out_hdr[2], len));\n\n        MBEDTLS_SSL_DEBUG_BUF(4, \"output record sent to network\",\n                              ssl->out_hdr, protected_record_size);\n\n        ssl->out_left += protected_record_size;\n        ssl->out_hdr  += protected_record_size;\n        mbedtls_ssl_update_out_pointers(ssl, ssl->transform_out);\n\n        for (i = 8; i > mbedtls_ssl_ep_len(ssl); i--) {\n            if (++ssl->cur_out_ctr[i - 1] != 0) {\n                break;\n            }\n        }\n\n        /* The loop goes to its end if the counter is wrapping */\n        if (i == mbedtls_ssl_ep_len(ssl)) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"outgoing message counter would wrap\"));\n            return MBEDTLS_ERR_SSL_COUNTER_WRAPPING;\n        }\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n        flush == SSL_DONT_FORCE_FLUSH) {\n        size_t remaining;\n        ret = ssl_get_remaining_payload_in_datagram(ssl);\n        if (ret < 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"ssl_get_remaining_payload_in_datagram\",\n                                  ret);\n            return ret;\n        }\n\n        remaining = (size_t) ret;\n        if (remaining == 0) {\n            flush = SSL_FORCE_FLUSH;\n        } else {\n            MBEDTLS_SSL_DEBUG_MSG(2,\n                                  (\"Still %u bytes available in current datagram\",\n                                   (unsigned) remaining));\n        }\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    if ((flush == SSL_FORCE_FLUSH) &&\n        (ret = mbedtls_ssl_flush_output(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_flush_output\", ret);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write record\"));\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_hs_is_proper_fragment(mbedtls_ssl_context *ssl)\n{\n    if (ssl->in_msglen < ssl->in_hslen ||\n        memcmp(ssl->in_msg + 6, \"\\0\\0\\0\",        3) != 0 ||\n        memcmp(ssl->in_msg + 9, ssl->in_msg + 1, 3) != 0) {\n        return 1;\n    }\n    return 0;\n}\n\nstatic uint32_t ssl_get_hs_frag_len(mbedtls_ssl_context const *ssl)\n{\n    return MBEDTLS_GET_UINT24_BE(ssl->in_msg, 9);\n}\n\nstatic uint32_t ssl_get_hs_frag_off(mbedtls_ssl_context const *ssl)\n{\n    return MBEDTLS_GET_UINT24_BE(ssl->in_msg, 6);\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_check_hs_header(mbedtls_ssl_context const *ssl)\n{\n    uint32_t msg_len, frag_off, frag_len;\n\n    msg_len  = ssl_get_hs_total_len(ssl);\n    frag_off = ssl_get_hs_frag_off(ssl);\n    frag_len = ssl_get_hs_frag_len(ssl);\n\n    if (frag_off > msg_len) {\n        return -1;\n    }\n\n    if (frag_len > msg_len - frag_off) {\n        return -1;\n    }\n\n    if (frag_len + 12 > ssl->in_msglen) {\n        return -1;\n    }\n\n    return 0;\n}\n\n/*\n * Mark bits in bitmask (used for DTLS HS reassembly)\n */\nstatic void ssl_bitmask_set(unsigned char *mask, size_t offset, size_t len)\n{\n    unsigned int start_bits, end_bits;\n\n    start_bits = 8 - (offset % 8);\n    if (start_bits != 8) {\n        size_t first_byte_idx = offset / 8;\n\n        /* Special case */\n        if (len <= start_bits) {\n            for (; len != 0; len--) {\n                mask[first_byte_idx] |= 1 << (start_bits - len);\n            }\n\n            /* Avoid potential issues with offset or len becoming invalid */\n            return;\n        }\n\n        offset += start_bits; /* Now offset % 8 == 0 */\n        len -= start_bits;\n\n        for (; start_bits != 0; start_bits--) {\n            mask[first_byte_idx] |= 1 << (start_bits - 1);\n        }\n    }\n\n    end_bits = len % 8;\n    if (end_bits != 0) {\n        size_t last_byte_idx = (offset + len) / 8;\n\n        len -= end_bits; /* Now len % 8 == 0 */\n\n        for (; end_bits != 0; end_bits--) {\n            mask[last_byte_idx] |= 1 << (8 - end_bits);\n        }\n    }\n\n    memset(mask + offset / 8, 0xFF, len / 8);\n}\n\n/*\n * Check that bitmask is full\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_bitmask_check(unsigned char *mask, size_t len)\n{\n    size_t i;\n\n    for (i = 0; i < len / 8; i++) {\n        if (mask[i] != 0xFF) {\n            return -1;\n        }\n    }\n\n    for (i = 0; i < len % 8; i++) {\n        if ((mask[len / 8] & (1 << (7 - i))) == 0) {\n            return -1;\n        }\n    }\n\n    return 0;\n}\n\n/* msg_len does not include the handshake header */\nstatic size_t ssl_get_reassembly_buffer_size(size_t msg_len,\n                                             unsigned add_bitmap)\n{\n    size_t alloc_len;\n\n    alloc_len  = 12;                                 /* Handshake header */\n    alloc_len += msg_len;                            /* Content buffer   */\n\n    if (add_bitmap) {\n        alloc_len += msg_len / 8 + (msg_len % 8 != 0);   /* Bitmap       */\n\n    }\n    return alloc_len;\n}\n\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\nstatic uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl)\n{\n    return MBEDTLS_GET_UINT24_BE(ssl->in_msg, 1);\n}\n\nint mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)\n{\n    if (ssl->badmac_seen_or_in_hsfraglen == 0) {\n        /* The handshake message must at least include the header.\n         * We may not have the full message yet in case of fragmentation.\n         * To simplify the code, we insist on having the header (and in\n         * particular the handshake message length) in the first\n         * fragment. */\n        if (ssl->in_msglen < mbedtls_ssl_hs_hdr_len(ssl)) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"handshake message too short: %\" MBEDTLS_PRINTF_SIZET,\n                                      ssl->in_msglen));\n            return MBEDTLS_ERR_SSL_INVALID_RECORD;\n        }\n\n        ssl->in_hslen = mbedtls_ssl_hs_hdr_len(ssl) + ssl_get_hs_total_len(ssl);\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"handshake message: msglen =\"\n                              \" %\" MBEDTLS_PRINTF_SIZET \", type = %u, hslen = %\"\n                              MBEDTLS_PRINTF_SIZET,\n                              ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen));\n\n    if (ssl->transform_in != NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"decrypted handshake message:\"\n                                  \" iv-buf=%d hdr-buf=%d hdr-buf=%d\",\n                                  (int) (ssl->in_iv - ssl->in_buf),\n                                  (int) (ssl->in_hdr - ssl->in_buf),\n                                  (int) (ssl->in_msg - ssl->in_buf)));\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n        unsigned int recv_msg_seq = MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4);\n\n        if (ssl_check_hs_header(ssl) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"invalid handshake header\"));\n            return MBEDTLS_ERR_SSL_INVALID_RECORD;\n        }\n\n        if (ssl->handshake != NULL &&\n            ((mbedtls_ssl_is_handshake_over(ssl) == 0 &&\n              recv_msg_seq != ssl->handshake->in_msg_seq) ||\n             (mbedtls_ssl_is_handshake_over(ssl) == 1 &&\n              ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO))) {\n            if (recv_msg_seq > ssl->handshake->in_msg_seq) {\n                MBEDTLS_SSL_DEBUG_MSG(2,\n                                      (\n                                          \"received future handshake message of sequence number %u (next %u)\",\n                                          recv_msg_seq,\n                                          ssl->handshake->in_msg_seq));\n                return MBEDTLS_ERR_SSL_EARLY_MESSAGE;\n            }\n\n            /* Retransmit only on last message from previous flight, to avoid\n             * too many retransmissions.\n             * Besides, No sane server ever retransmits HelloVerifyRequest */\n            if (recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 &&\n                ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST) {\n                MBEDTLS_SSL_DEBUG_MSG(2, (\"received message from last flight, \"\n                                          \"message_seq = %u, start_of_flight = %u\",\n                                          recv_msg_seq,\n                                          ssl->handshake->in_flight_start_seq));\n\n                if ((ret = mbedtls_ssl_resend(ssl)) != 0) {\n                    MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_resend\", ret);\n                    return ret;\n                }\n            } else {\n                MBEDTLS_SSL_DEBUG_MSG(2, (\"dropping out-of-sequence message: \"\n                                          \"message_seq = %u, expected = %u\",\n                                          recv_msg_seq,\n                                          ssl->handshake->in_msg_seq));\n            }\n\n            return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;\n        }\n        /* Wait until message completion to increment in_msg_seq */\n\n        /* Message reassembly is handled alongside buffering of future\n         * messages; the commonality is that both handshake fragments and\n         * future messages cannot be forwarded immediately to the\n         * handshake logic layer. */\n        if (ssl_hs_is_proper_fragment(ssl) == 1) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"found fragmented DTLS handshake message\"));\n            return MBEDTLS_ERR_SSL_EARLY_MESSAGE;\n        }\n    } else\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n    {\n        unsigned char *const reassembled_record_start =\n            ssl->in_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;\n        unsigned char *const payload_start =\n            reassembled_record_start + mbedtls_ssl_in_hdr_len(ssl);\n        unsigned char *payload_end = payload_start + ssl->badmac_seen_or_in_hsfraglen;\n        /* How many more bytes we want to have a complete handshake message. */\n        const size_t hs_remain = ssl->in_hslen - ssl->badmac_seen_or_in_hsfraglen;\n        /* How many bytes of the current record are part of the first\n         * handshake message. There may be more handshake messages (possibly\n         * incomplete) in the same record; if so, we leave them after the\n         * current record, and ssl_consume_current_message() will take\n         * care of consuming the next handshake message. */\n        const size_t hs_this_fragment_len =\n            ssl->in_msglen > hs_remain ? hs_remain : ssl->in_msglen;\n        (void) hs_this_fragment_len;\n\n        MBEDTLS_SSL_DEBUG_MSG(3,\n                              (\"%s handshake fragment: %\" MBEDTLS_PRINTF_SIZET\n                               \", %u..%u of %\" MBEDTLS_PRINTF_SIZET,\n                               (ssl->badmac_seen_or_in_hsfraglen != 0 ?\n                                \"subsequent\" :\n                                hs_this_fragment_len == ssl->in_hslen ?\n                                \"sole\" :\n                                \"initial\"),\n                               ssl->in_msglen,\n                               ssl->badmac_seen_or_in_hsfraglen,\n                               ssl->badmac_seen_or_in_hsfraglen +\n                               (unsigned) hs_this_fragment_len,\n                               ssl->in_hslen));\n\n        /* Move the received handshake fragment to have the whole message\n         * (at least the part received so far) in a single segment at a\n         * known offset in the input buffer.\n         * - When receiving a non-initial handshake fragment, append it to\n         *   the initial segment.\n         * - Even the initial handshake fragment is moved, if it was\n         *   encrypted with an explicit IV: decryption leaves the payload\n         *   after the explicit IV, but here we move it to start where the\n         *   IV was.\n         */\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n        size_t const in_buf_len = ssl->in_buf_len;\n#else\n        size_t const in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;\n#endif\n        if (payload_end + ssl->in_msglen > ssl->in_buf + in_buf_len) {\n            MBEDTLS_SSL_DEBUG_MSG(1,\n                                  (\"Shouldn't happen: no room to move handshake fragment %\"\n                                   MBEDTLS_PRINTF_SIZET \" from %p to %p (buf=%p len=%\"\n                                   MBEDTLS_PRINTF_SIZET \")\",\n                                   ssl->in_msglen,\n                                   (void *) ssl->in_msg, (void *) payload_end,\n                                   (void *) ssl->in_buf, in_buf_len));\n            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n        }\n        memmove(payload_end, ssl->in_msg, ssl->in_msglen);\n\n        ssl->badmac_seen_or_in_hsfraglen += (unsigned) ssl->in_msglen;\n        payload_end += ssl->in_msglen;\n\n        if (ssl->badmac_seen_or_in_hsfraglen < ssl->in_hslen) {\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"Prepare: waiting for more handshake fragments \"\n                                      \"%u/%\" MBEDTLS_PRINTF_SIZET,\n                                      ssl->badmac_seen_or_in_hsfraglen, ssl->in_hslen));\n            ssl->in_hdr = payload_end;\n            ssl->in_msglen = 0;\n            mbedtls_ssl_update_in_pointers(ssl);\n            return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;\n        } else {\n            ssl->in_msglen = ssl->badmac_seen_or_in_hsfraglen;\n            ssl->badmac_seen_or_in_hsfraglen = 0;\n            ssl->in_hdr = reassembled_record_start;\n            mbedtls_ssl_update_in_pointers(ssl);\n\n            /* Update the record length in the fully reassembled record */\n            if (ssl->in_msglen > 0xffff) {\n                MBEDTLS_SSL_DEBUG_MSG(1,\n                                      (\"Shouldn't happen: in_msglen=%\"\n                                       MBEDTLS_PRINTF_SIZET \" > 0xffff\",\n                                       ssl->in_msglen));\n                return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n            }\n            MBEDTLS_PUT_UINT16_BE(ssl->in_msglen, ssl->in_len, 0);\n\n            size_t record_len = mbedtls_ssl_in_hdr_len(ssl) + ssl->in_msglen;\n            (void) record_len;\n            MBEDTLS_SSL_DEBUG_BUF(4, \"reassembled record\",\n                                  ssl->in_hdr, record_len);\n            if (ssl->in_hslen < ssl->in_msglen) {\n                MBEDTLS_SSL_DEBUG_MSG(3,\n                                      (\"More handshake messages in the record: \"\n                                       \"%\" MBEDTLS_PRINTF_SIZET \" + %\" MBEDTLS_PRINTF_SIZET,\n                                       ssl->in_hslen,\n                                       ssl->in_msglen - ssl->in_hslen));\n            }\n        }\n    }\n\n    return 0;\n}\n\nint mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_handshake_params * const hs = ssl->handshake;\n\n    if (mbedtls_ssl_is_handshake_over(ssl) == 0 && hs != NULL) {\n        ret = ssl->handshake->update_checksum(ssl, ssl->in_msg, ssl->in_hslen);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"update_checksum\", ret);\n            return ret;\n        }\n    }\n\n    /* Handshake message is complete, increment counter */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n        ssl->handshake != NULL) {\n        unsigned offset;\n        mbedtls_ssl_hs_buffer *hs_buf;\n\n        /* Increment handshake sequence number */\n        hs->in_msg_seq++;\n\n        /*\n         * Clear up handshake buffering and reassembly structure.\n         */\n\n        /* Free first entry */\n        ssl_buffering_free_slot(ssl, 0);\n\n        /* Shift all other entries */\n        for (offset = 0, hs_buf = &hs->buffering.hs[0];\n             offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS;\n             offset++, hs_buf++) {\n            *hs_buf = *(hs_buf + 1);\n        }\n\n        /* Create a fresh last entry */\n        memset(hs_buf, 0, sizeof(mbedtls_ssl_hs_buffer));\n    }\n#endif\n    return 0;\n}\n\n/*\n * DTLS anti-replay: RFC 6347 4.1.2.6\n *\n * in_window is a field of bits numbered from 0 (lsb) to 63 (msb).\n * Bit n is set iff record number in_window_top - n has been seen.\n *\n * Usually, in_window_top is the last record number seen and the lsb of\n * in_window is set. The only exception is the initial state (record number 0\n * not seen yet).\n */\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\nvoid mbedtls_ssl_dtls_replay_reset(mbedtls_ssl_context *ssl)\n{\n    ssl->in_window_top = 0;\n    ssl->in_window = 0;\n}\n\nstatic inline uint64_t ssl_load_six_bytes(unsigned char *buf)\n{\n    return ((uint64_t) buf[0] << 40) |\n           ((uint64_t) buf[1] << 32) |\n           ((uint64_t) buf[2] << 24) |\n           ((uint64_t) buf[3] << 16) |\n           ((uint64_t) buf[4] <<  8) |\n           ((uint64_t) buf[5]);\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int mbedtls_ssl_dtls_record_replay_check(mbedtls_ssl_context *ssl, uint8_t *record_in_ctr)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *original_in_ctr;\n\n    // save original in_ctr\n    original_in_ctr = ssl->in_ctr;\n\n    // use counter from record\n    ssl->in_ctr = record_in_ctr;\n\n    ret = mbedtls_ssl_dtls_replay_check((mbedtls_ssl_context const *) ssl);\n\n    // restore the counter\n    ssl->in_ctr = original_in_ctr;\n\n    return ret;\n}\n\n/*\n * Return 0 if sequence number is acceptable, -1 otherwise\n */\nint mbedtls_ssl_dtls_replay_check(mbedtls_ssl_context const *ssl)\n{\n    uint64_t rec_seqnum = ssl_load_six_bytes(ssl->in_ctr + 2);\n    uint64_t bit;\n\n    if (ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED) {\n        return 0;\n    }\n\n    if (rec_seqnum > ssl->in_window_top) {\n        return 0;\n    }\n\n    bit = ssl->in_window_top - rec_seqnum;\n\n    if (bit >= 64) {\n        return -1;\n    }\n\n    if ((ssl->in_window & ((uint64_t) 1 << bit)) != 0) {\n        return -1;\n    }\n\n    return 0;\n}\n\n/*\n * Update replay window on new validated record\n */\nvoid mbedtls_ssl_dtls_replay_update(mbedtls_ssl_context *ssl)\n{\n    uint64_t rec_seqnum = ssl_load_six_bytes(ssl->in_ctr + 2);\n\n    if (ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED) {\n        return;\n    }\n\n    if (rec_seqnum > ssl->in_window_top) {\n        /* Update window_top and the contents of the window */\n        uint64_t shift = rec_seqnum - ssl->in_window_top;\n\n        if (shift >= 64) {\n            ssl->in_window = 1;\n        } else {\n            ssl->in_window <<= shift;\n            ssl->in_window |= 1;\n        }\n\n        ssl->in_window_top = rec_seqnum;\n    } else {\n        /* Mark that number as seen in the current window */\n        uint64_t bit = ssl->in_window_top - rec_seqnum;\n\n        if (bit < 64) { /* Always true, but be extra sure */\n            ssl->in_window |= (uint64_t) 1 << bit;\n        }\n    }\n}\n#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */\n\n#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)\n/*\n * Check if a datagram looks like a ClientHello with a valid cookie,\n * and if it doesn't, generate a HelloVerifyRequest message.\n * Both input and output include full DTLS headers.\n *\n * - if cookie is valid, return 0\n * - if ClientHello looks superficially valid but cookie is not,\n *   fill obuf and set olen, then\n *   return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED\n * - otherwise return a specific error code\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ssl_check_dtls_clihlo_cookie(\n    mbedtls_ssl_context *ssl,\n    const unsigned char *cli_id, size_t cli_id_len,\n    const unsigned char *in, size_t in_len,\n    unsigned char *obuf, size_t buf_len, size_t *olen)\n{\n    size_t sid_len, cookie_len, epoch, fragment_offset;\n    unsigned char *p;\n\n    /*\n     * Structure of ClientHello with record and handshake headers,\n     * and expected values. We don't need to check a lot, more checks will be\n     * done when actually parsing the ClientHello - skipping those checks\n     * avoids code duplication and does not make cookie forging any easier.\n     *\n     *  0-0  ContentType type;                  copied, must be handshake\n     *  1-2  ProtocolVersion version;           copied\n     *  3-4  uint16 epoch;                      copied, must be 0\n     *  5-10 uint48 sequence_number;            copied\n     * 11-12 uint16 length;                     (ignored)\n     *\n     * 13-13 HandshakeType msg_type;            (ignored)\n     * 14-16 uint24 length;                     (ignored)\n     * 17-18 uint16 message_seq;                copied\n     * 19-21 uint24 fragment_offset;            copied, must be 0\n     * 22-24 uint24 fragment_length;            (ignored)\n     *\n     * 25-26 ProtocolVersion client_version;    (ignored)\n     * 27-58 Random random;                     (ignored)\n     * 59-xx SessionID session_id;              1 byte len + sid_len content\n     * 60+   opaque cookie<0..2^8-1>;           1 byte len + content\n     *       ...\n     *\n     * Minimum length is 61 bytes.\n     */\n    MBEDTLS_SSL_DEBUG_MSG(4, (\"check cookie: in_len=%u\",\n                              (unsigned) in_len));\n    MBEDTLS_SSL_DEBUG_BUF(4, \"cli_id\", cli_id, cli_id_len);\n    if (in_len < 61) {\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"check cookie: record too short\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    epoch = MBEDTLS_GET_UINT16_BE(in, 3);\n    fragment_offset = MBEDTLS_GET_UINT24_BE(in, 19);\n\n    if (in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || epoch != 0 ||\n        fragment_offset != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"check cookie: not a good ClientHello\"));\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"    type=%u epoch=%u fragment_offset=%u\",\n                                  in[0], (unsigned) epoch,\n                                  (unsigned) fragment_offset));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    sid_len = in[59];\n    if (59 + 1 + sid_len + 1 > in_len) {\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"check cookie: sid_len=%u > %u\",\n                                  (unsigned) sid_len,\n                                  (unsigned) in_len - 61));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n    MBEDTLS_SSL_DEBUG_BUF(4, \"sid received from network\",\n                          in + 60, sid_len);\n\n    cookie_len = in[60 + sid_len];\n    if (59 + 1 + sid_len + 1 + cookie_len > in_len) {\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"check cookie: cookie_len=%u > %u\",\n                                  (unsigned) cookie_len,\n                                  (unsigned) (in_len - sid_len - 61)));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"cookie received from network\",\n                          in + sid_len + 61, cookie_len);\n    if (ssl->conf->f_cookie_check(ssl->conf->p_cookie,\n                                  in + sid_len + 61, cookie_len,\n                                  cli_id, cli_id_len) == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"check cookie: valid\"));\n        return 0;\n    }\n\n    /*\n     * If we get here, we've got an invalid cookie, let's prepare HVR.\n     *\n     *  0-0  ContentType type;                  copied\n     *  1-2  ProtocolVersion version;           copied\n     *  3-4  uint16 epoch;                      copied\n     *  5-10 uint48 sequence_number;            copied\n     * 11-12 uint16 length;                     olen - 13\n     *\n     * 13-13 HandshakeType msg_type;            hello_verify_request\n     * 14-16 uint24 length;                     olen - 25\n     * 17-18 uint16 message_seq;                copied\n     * 19-21 uint24 fragment_offset;            copied\n     * 22-24 uint24 fragment_length;            olen - 25\n     *\n     * 25-26 ProtocolVersion server_version;    0xfe 0xff\n     * 27-27 opaque cookie<0..2^8-1>;           cookie_len = olen - 27, cookie\n     *\n     * Minimum length is 28.\n     */\n    if (buf_len < 28) {\n        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n    }\n\n    /* Copy most fields and adapt others */\n    memcpy(obuf, in, 25);\n    obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST;\n    obuf[25] = 0xfe;\n    obuf[26] = 0xff;\n\n    /* Generate and write actual cookie */\n    p = obuf + 28;\n    if (ssl->conf->f_cookie_write(ssl->conf->p_cookie,\n                                  &p, obuf + buf_len,\n                                  cli_id, cli_id_len) != 0) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    *olen = (size_t) (p - obuf);\n\n    /* Go back and fill length fields */\n    obuf[27] = (unsigned char) (*olen - 28);\n\n    obuf[14] = obuf[22] = MBEDTLS_BYTE_2(*olen - 25);\n    obuf[15] = obuf[23] = MBEDTLS_BYTE_1(*olen - 25);\n    obuf[16] = obuf[24] = MBEDTLS_BYTE_0(*olen - 25);\n\n    MBEDTLS_PUT_UINT16_BE(*olen - 13, obuf, 11);\n\n    return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED;\n}\n\n/*\n * Handle possible client reconnect with the same UDP quadruplet\n * (RFC 6347 Section 4.2.8).\n *\n * Called by ssl_parse_record_header() in case we receive an epoch 0 record\n * that looks like a ClientHello.\n *\n * - if the input looks like a ClientHello without cookies,\n *   send back HelloVerifyRequest, then return 0\n * - if the input looks like a ClientHello with a valid cookie,\n *   reset the session of the current context, and\n *   return MBEDTLS_ERR_SSL_CLIENT_RECONNECT\n * - if anything goes wrong, return a specific error code\n *\n * This function is called (through ssl_check_client_reconnect()) when an\n * unexpected record is found in ssl_get_next_record(), which will discard the\n * record if we return 0, and bubble up the return value otherwise (this\n * includes the case of MBEDTLS_ERR_SSL_CLIENT_RECONNECT and of unexpected\n * errors, and is the right thing to do in both cases).\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_handle_possible_reconnect(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n\n    if (ssl->conf->f_cookie_write == NULL ||\n        ssl->conf->f_cookie_check == NULL) {\n        /* If we can't use cookies to verify reachability of the peer,\n         * drop the record. */\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"no cookie callbacks, \"\n                                  \"can't check reconnect validity\"));\n        return 0;\n    }\n\n    ret = mbedtls_ssl_check_dtls_clihlo_cookie(\n        ssl,\n        ssl->cli_id, ssl->cli_id_len,\n        ssl->in_buf, ssl->in_left,\n        ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len);\n\n    MBEDTLS_SSL_DEBUG_RET(2, \"mbedtls_ssl_check_dtls_clihlo_cookie\", ret);\n\n    if (ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) {\n        int send_ret;\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"sending HelloVerifyRequest\"));\n        MBEDTLS_SSL_DEBUG_BUF(4, \"output record sent to network\",\n                              ssl->out_buf, len);\n        /* Don't check write errors as we can't do anything here.\n         * If the error is permanent we'll catch it later,\n         * if it's not, then hopefully it'll work next time. */\n        send_ret = ssl->f_send(ssl->p_bio, ssl->out_buf, len);\n        MBEDTLS_SSL_DEBUG_RET(2, \"ssl->f_send\", send_ret);\n        (void) send_ret;\n\n        return 0;\n    }\n\n    if (ret == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"cookie is valid, resetting context\"));\n        if ((ret = mbedtls_ssl_session_reset_int(ssl, 1)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"reset\", ret);\n            return ret;\n        }\n\n        return MBEDTLS_ERR_SSL_CLIENT_RECONNECT;\n    }\n\n    return ret;\n}\n#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_check_record_type(uint8_t record_type)\n{\n    if (record_type != MBEDTLS_SSL_MSG_HANDSHAKE &&\n        record_type != MBEDTLS_SSL_MSG_ALERT &&\n        record_type != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&\n        record_type != MBEDTLS_SSL_MSG_APPLICATION_DATA) {\n        return MBEDTLS_ERR_SSL_INVALID_RECORD;\n    }\n\n    return 0;\n}\n\n/*\n * ContentType type;\n * ProtocolVersion version;\n * uint16 epoch;            // DTLS only\n * uint48 sequence_number;  // DTLS only\n * uint16 length;\n *\n * Return 0 if header looks sane (and, for DTLS, the record is expected)\n * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad,\n * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected.\n *\n * With DTLS, mbedtls_ssl_read_record() will:\n * 1. proceed with the record if this function returns 0\n * 2. drop only the current record if this function returns UNEXPECTED_RECORD\n * 3. return CLIENT_RECONNECT if this function return that value\n * 4. drop the whole datagram if this function returns anything else.\n * Point 2 is needed when the peer is resending, and we have already received\n * the first record from a datagram but are still waiting for the others.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_record_header(mbedtls_ssl_context const *ssl,\n                                   unsigned char *buf,\n                                   size_t len,\n                                   mbedtls_record *rec)\n{\n    mbedtls_ssl_protocol_version tls_version;\n\n    size_t const rec_hdr_type_offset    = 0;\n    size_t const rec_hdr_type_len       = 1;\n\n    size_t const rec_hdr_version_offset = rec_hdr_type_offset +\n                                          rec_hdr_type_len;\n    size_t const rec_hdr_version_len    = 2;\n\n    size_t const rec_hdr_ctr_len        = 8;\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    uint32_t     rec_epoch;\n    size_t const rec_hdr_ctr_offset     = rec_hdr_version_offset +\n                                          rec_hdr_version_len;\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    size_t const rec_hdr_cid_offset     = rec_hdr_ctr_offset +\n                                          rec_hdr_ctr_len;\n    size_t       rec_hdr_cid_len        = 0;\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    size_t       rec_hdr_len_offset; /* To be determined */\n    size_t const rec_hdr_len_len    = 2;\n\n    /*\n     * Check minimum lengths for record header.\n     */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        rec_hdr_len_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len;\n    } else\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n    {\n        rec_hdr_len_offset = rec_hdr_version_offset + rec_hdr_version_len;\n    }\n\n    if (len < rec_hdr_len_offset + rec_hdr_len_len) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\n                                  \"datagram of length %u too small to hold DTLS record header of length %u\",\n                                  (unsigned) len,\n                                  (unsigned) (rec_hdr_len_len + rec_hdr_len_len)));\n        return MBEDTLS_ERR_SSL_INVALID_RECORD;\n    }\n\n    /*\n     * Parse and validate record content type\n     */\n\n    rec->type = buf[rec_hdr_type_offset];\n\n    /* Check record content type */\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    rec->cid_len = 0;\n\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n        ssl->conf->cid_len != 0                                &&\n        rec->type == MBEDTLS_SSL_MSG_CID) {\n        /* Shift pointers to account for record header including CID\n         * struct {\n         *   ContentType outer_type = tls12_cid;\n         *   ProtocolVersion version;\n         *   uint16 epoch;\n         *   uint48 sequence_number;\n         *   opaque cid[cid_length]; // Additional field compared to\n         *                           // default DTLS record format\n         *   uint16 length;\n         *   opaque enc_content[DTLSCiphertext.length];\n         * } DTLSCiphertext;\n         */\n\n        /* So far, we only support static CID lengths\n         * fixed in the configuration. */\n        rec_hdr_cid_len = ssl->conf->cid_len;\n        rec_hdr_len_offset += rec_hdr_cid_len;\n\n        if (len < rec_hdr_len_offset + rec_hdr_len_len) {\n            MBEDTLS_SSL_DEBUG_MSG(1,\n                                  (\n                                      \"datagram of length %u too small to hold DTLS record header including CID, length %u\",\n                                      (unsigned) len,\n                                      (unsigned) (rec_hdr_len_offset + rec_hdr_len_len)));\n            return MBEDTLS_ERR_SSL_INVALID_RECORD;\n        }\n\n        /* configured CID len is guaranteed at most 255, see\n         * MBEDTLS_SSL_CID_OUT_LEN_MAX in check_config.h */\n        rec->cid_len = (uint8_t) rec_hdr_cid_len;\n        memcpy(rec->cid, buf + rec_hdr_cid_offset, rec_hdr_cid_len);\n    } else\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n    {\n        if (ssl_check_record_type(rec->type)) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"unknown record type %u\",\n                                      (unsigned) rec->type));\n            return MBEDTLS_ERR_SSL_INVALID_RECORD;\n        }\n    }\n\n    /*\n     * Parse and validate record version\n     */\n    rec->ver[0] = buf[rec_hdr_version_offset + 0];\n    rec->ver[1] = buf[rec_hdr_version_offset + 1];\n    tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(\n        buf + rec_hdr_version_offset,\n        ssl->conf->transport);\n\n    if (tls_version > ssl->conf->max_tls_version) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"TLS version mismatch: got %u, expected max %u\",\n                                  (unsigned) tls_version,\n                                  (unsigned) ssl->conf->max_tls_version));\n\n        return MBEDTLS_ERR_SSL_INVALID_RECORD;\n    }\n    /*\n     * Parse/Copy record sequence number.\n     */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        /* Copy explicit record sequence number from input buffer. */\n        memcpy(&rec->ctr[0], buf + rec_hdr_ctr_offset,\n               rec_hdr_ctr_len);\n    } else\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n    {\n        /* Copy implicit record sequence number from SSL context structure. */\n        memcpy(&rec->ctr[0], ssl->in_ctr, rec_hdr_ctr_len);\n    }\n\n    /*\n     * Parse record length.\n     */\n\n    rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len;\n    rec->data_len    = MBEDTLS_GET_UINT16_BE(buf, rec_hdr_len_offset);\n    MBEDTLS_SSL_DEBUG_BUF(4, \"input record header\", buf, rec->data_offset);\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"input record: msgtype = %u, \"\n                              \"version = [0x%x], msglen = %\" MBEDTLS_PRINTF_SIZET,\n                              rec->type, (unsigned) tls_version, rec->data_len));\n\n    rec->buf     = buf;\n    rec->buf_len = rec->data_offset + rec->data_len;\n\n    if (rec->data_len == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"rejecting empty record\"));\n        return MBEDTLS_ERR_SSL_INVALID_RECORD;\n    }\n\n    /*\n     * DTLS-related tests.\n     * Check epoch before checking length constraint because\n     * the latter varies with the epoch. E.g., if a ChangeCipherSpec\n     * message gets duplicated before the corresponding Finished message,\n     * the second ChangeCipherSpec should be discarded because it belongs\n     * to an old epoch, but not because its length is shorter than\n     * the minimum record length for packets using the new record transform.\n     * Note that these two kinds of failures are handled differently,\n     * as an unexpected record is silently skipped but an invalid\n     * record leads to the entire datagram being dropped.\n     */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        rec_epoch = MBEDTLS_GET_UINT16_BE(rec->ctr, 0);\n\n        /* Check that the datagram is large enough to contain a record\n         * of the advertised length. */\n        if (len < rec->data_offset + rec->data_len) {\n            MBEDTLS_SSL_DEBUG_MSG(1,\n                                  (\n                                      \"Datagram of length %u too small to contain record of advertised length %u.\",\n                                      (unsigned) len,\n                                      (unsigned) (rec->data_offset + rec->data_len)));\n            return MBEDTLS_ERR_SSL_INVALID_RECORD;\n        }\n\n        /* Records from other, non-matching epochs are silently discarded.\n         * (The case of same-port Client reconnects must be considered in\n         *  the caller). */\n        if (rec_epoch != ssl->in_epoch) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"record from another epoch: \"\n                                      \"expected %u, received %lu\",\n                                      ssl->in_epoch, (unsigned long) rec_epoch));\n\n            /* Records from the next epoch are considered for buffering\n             * (concretely: early Finished messages). */\n            if (rec_epoch == (unsigned) ssl->in_epoch + 1) {\n                MBEDTLS_SSL_DEBUG_MSG(2, (\"Consider record for buffering\"));\n                return MBEDTLS_ERR_SSL_EARLY_MESSAGE;\n            }\n\n            return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;\n        }\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\n        /* For records from the correct epoch, check whether their\n         * sequence number has been seen before. */\n        else if (mbedtls_ssl_dtls_record_replay_check((mbedtls_ssl_context *) ssl,\n                                                      &rec->ctr[0]) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"replayed record\"));\n            return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;\n        }\n#endif\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    return 0;\n}\n\n\n#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_check_client_reconnect(mbedtls_ssl_context *ssl)\n{\n    unsigned int rec_epoch = MBEDTLS_GET_UINT16_BE(ssl->in_ctr, 0);\n\n    /*\n     * Check for an epoch 0 ClientHello. We can't use in_msg here to\n     * access the first byte of record content (handshake type), as we\n     * have an active transform (possibly iv_len != 0), so use the\n     * fact that the record header len is 13 instead.\n     */\n    if (rec_epoch == 0 &&\n        ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&\n        mbedtls_ssl_is_handshake_over(ssl) == 1 &&\n        ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&\n        ssl->in_left > 13 &&\n        ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"possible client reconnect \"\n                                  \"from the same port\"));\n        return ssl_handle_possible_reconnect(ssl);\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */\n\n/*\n * If applicable, decrypt record content\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_prepare_record_content(mbedtls_ssl_context *ssl,\n                                      mbedtls_record *rec)\n{\n    int ret, done = 0;\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"input record from network\",\n                          rec->buf, rec->buf_len);\n\n    /*\n     * In TLS 1.3, always treat ChangeCipherSpec records\n     * as unencrypted. The only thing we do with them is\n     * check the length and content and ignore them.\n     */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    if (ssl->transform_in != NULL &&\n        ssl->transform_in->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {\n        if (rec->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) {\n            done = 1;\n        }\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n    if (!done && ssl->transform_in != NULL) {\n        unsigned char const old_msg_type = rec->type;\n\n        if ((ret = mbedtls_ssl_decrypt_buf(ssl, ssl->transform_in,\n                                           rec)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"ssl_decrypt_buf\", ret);\n\n#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C)\n            /*\n             * Although the server rejected early data, it might receive early\n             * data as long as it has not received the client Finished message.\n             * It is encrypted with early keys and should be ignored as stated\n             * in section 4.2.10 of RFC 8446:\n             *\n             * \"Ignore the extension and return a regular 1-RTT response. The\n             * server then skips past early data by attempting to deprotect\n             * received records using the handshake traffic key, discarding\n             * records which fail deprotection (up to the configured\n             * max_early_data_size). Once a record is deprotected successfully,\n             * it is treated as the start of the client's second flight and the\n             * server proceeds as with an ordinary 1-RTT handshake.\"\n             */\n            if ((old_msg_type == MBEDTLS_SSL_MSG_APPLICATION_DATA) &&\n                (ssl->discard_early_data_record ==\n                 MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD)) {\n                MBEDTLS_SSL_DEBUG_MSG(\n                    3, (\"EarlyData: deprotect and discard app data records.\"));\n\n                ret = mbedtls_ssl_tls13_check_early_data_len(ssl, rec->data_len);\n                if (ret != 0) {\n                    return ret;\n                }\n                ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;\n            }\n#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n            if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID &&\n                ssl->conf->ignore_unexpected_cid\n                == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE) {\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"ignoring unexpected CID\"));\n                ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;\n            }\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n            /*\n             * The decryption of the record failed, no reason to ignore it,\n             * return in error with the decryption error code.\n             */\n            return ret;\n        }\n\n#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C)\n        /*\n         * If the server were discarding protected records that it fails to\n         * deprotect because it has rejected early data, as we have just\n         * deprotected successfully a record, the server has to resume normal\n         * operation and fail the connection if the deprotection of a record\n         * fails.\n         */\n        if (ssl->discard_early_data_record ==\n            MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD) {\n            ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD;\n        }\n#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */\n\n        if (old_msg_type != rec->type) {\n            MBEDTLS_SSL_DEBUG_MSG(4, (\"record type after decrypt (before %d): %d\",\n                                      old_msg_type, rec->type));\n        }\n\n        MBEDTLS_SSL_DEBUG_BUF(4, \"input payload after decrypt\",\n                              rec->buf + rec->data_offset, rec->data_len);\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n        /* We have already checked the record content type\n         * in ssl_parse_record_header(), failing or silently\n         * dropping the record in the case of an unknown type.\n         *\n         * Since with the use of CIDs, the record content type\n         * might change during decryption, re-check the record\n         * content type, but treat a failure as fatal this time. */\n        if (ssl_check_record_type(rec->type)) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"unknown record type\"));\n            return MBEDTLS_ERR_SSL_INVALID_RECORD;\n        }\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n        if (rec->data_len == 0) {\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n            if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2\n                && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA) {\n                /* TLS v1.2 explicitly disallows zero-length messages which are not application data */\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"invalid zero-length message type: %d\", ssl->in_msgtype));\n                return MBEDTLS_ERR_SSL_INVALID_RECORD;\n            }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n            ssl->nb_zero++;\n\n            /*\n             * Three or more empty messages may be a DoS attack\n             * (excessive CPU consumption).\n             */\n            if (ssl->nb_zero > 3) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"received four consecutive empty \"\n                                          \"messages, possible DoS attack\"));\n                /* Treat the records as if they were not properly authenticated,\n                 * thereby failing the connection if we see more than allowed\n                 * by the configured bad MAC threshold. */\n                return MBEDTLS_ERR_SSL_INVALID_MAC;\n            }\n        } else {\n            ssl->nb_zero = 0;\n        }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n            ; /* in_ctr read from peer, not maintained internally */\n        } else\n#endif\n        {\n            unsigned i;\n            for (i = MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;\n                 i > mbedtls_ssl_ep_len(ssl); i--) {\n                if (++ssl->in_ctr[i - 1] != 0) {\n                    break;\n                }\n            }\n\n            /* The loop goes to its end iff the counter is wrapping */\n            if (i == mbedtls_ssl_ep_len(ssl)) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"incoming message counter would wrap\"));\n                return MBEDTLS_ERR_SSL_COUNTER_WRAPPING;\n            }\n        }\n\n    }\n\n#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C)\n    /*\n     * Although the server rejected early data because it needed to send an\n     * HelloRetryRequest message, it might receive early data as long as it has\n     * not received the client Finished message.\n     * The early data is encrypted with early keys and should be ignored as\n     * stated in section 4.2.10 of RFC 8446 (second case):\n     *\n     * \"The server then ignores early data by skipping all records with an\n     * external content type of \"application_data\" (indicating that they are\n     * encrypted), up to the configured max_early_data_size. Ignore application\n     * data message before 2nd ClientHello when early_data was received in 1st\n     * ClientHello.\"\n     */\n    if (ssl->discard_early_data_record == MBEDTLS_SSL_EARLY_DATA_DISCARD) {\n        if (rec->type == MBEDTLS_SSL_MSG_APPLICATION_DATA) {\n\n            ret = mbedtls_ssl_tls13_check_early_data_len(ssl, rec->data_len);\n            if (ret != 0) {\n                return ret;\n            }\n\n            MBEDTLS_SSL_DEBUG_MSG(\n                3, (\"EarlyData: Ignore application message before 2nd ClientHello\"));\n\n            return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;\n        } else if (rec->type == MBEDTLS_SSL_MSG_HANDSHAKE) {\n            ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD;\n        }\n    }\n#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        mbedtls_ssl_dtls_replay_update(ssl);\n    }\n#endif\n\n    /* Check actual (decrypted) record content length against\n     * configured maximum. */\n    if (rec->data_len > MBEDTLS_SSL_IN_CONTENT_LEN) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad message length\"));\n        return MBEDTLS_ERR_SSL_INVALID_RECORD;\n    }\n\n    return 0;\n}\n\n/*\n * Read a record.\n *\n * Silently ignore non-fatal alert (and for DTLS, invalid records as well,\n * RFC 6347 4.1.2.7) and continue reading until a valid record is found.\n *\n */\n\n/* Helper functions for mbedtls_ssl_read_record(). */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_consume_current_message(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_get_next_record(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_record_is_in_progress(mbedtls_ssl_context *ssl);\n\nint mbedtls_ssl_read_record(mbedtls_ssl_context *ssl,\n                            unsigned update_hs_digest)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> read record\"));\n\n    if (ssl->keep_current_message == 0) {\n        do {\n\n            ret = ssl_consume_current_message(ssl);\n            if (ret != 0) {\n                return ret;\n            }\n\n            if (ssl_record_is_in_progress(ssl) == 0) {\n                int dtls_have_buffered = 0;\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n\n                /* We only check for buffered messages if the\n                 * current datagram is fully consumed. */\n                if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n                    ssl_next_record_is_in_datagram(ssl) == 0) {\n                    if (ssl_load_buffered_message(ssl) == 0) {\n                        dtls_have_buffered = 1;\n                    }\n                }\n\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n                if (dtls_have_buffered == 0) {\n                    ret = ssl_get_next_record(ssl);\n                    if (ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) {\n                        continue;\n                    }\n\n                    if (ret != 0) {\n                        MBEDTLS_SSL_DEBUG_RET(1, (\"ssl_get_next_record\"), ret);\n                        return ret;\n                    }\n                }\n            }\n\n            ret = mbedtls_ssl_handle_message_type(ssl);\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n            if (ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE) {\n                /* Buffer future message */\n                ret = ssl_buffer_message(ssl);\n                if (ret != 0) {\n                    return ret;\n                }\n\n                ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;\n            }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n        } while (MBEDTLS_ERR_SSL_NON_FATAL           == ret  ||\n                 MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret);\n\n        if (0 != ret) {\n            MBEDTLS_SSL_DEBUG_RET(1, (\"mbedtls_ssl_handle_message_type\"), ret);\n            return ret;\n        }\n\n        if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&\n            update_hs_digest == 1) {\n            ret = mbedtls_ssl_update_handshake_status(ssl);\n            if (0 != ret) {\n                MBEDTLS_SSL_DEBUG_RET(1, (\"mbedtls_ssl_update_handshake_status\"), ret);\n                return ret;\n            }\n        }\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"reuse previously read message\"));\n        ssl->keep_current_message = 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= read record\"));\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_next_record_is_in_datagram(mbedtls_ssl_context *ssl)\n{\n    if (ssl->in_left > ssl->next_record_offset) {\n        return 1;\n    }\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_load_buffered_message(mbedtls_ssl_context *ssl)\n{\n    mbedtls_ssl_handshake_params * const hs = ssl->handshake;\n    mbedtls_ssl_hs_buffer *hs_buf;\n    int ret = 0;\n\n    if (hs == NULL) {\n        return -1;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> ssl_load_buffered_message\"));\n\n    if (ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC ||\n        ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC) {\n        /* Check if we have seen a ChangeCipherSpec before.\n         * If yes, synthesize a CCS record. */\n        if (!hs->buffering.seen_ccs) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"CCS not seen in the current flight\"));\n            ret = -1;\n            goto exit;\n        }\n\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"Injecting buffered CCS message\"));\n        ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;\n        ssl->in_msglen = 1;\n        ssl->in_msg[0] = 1;\n\n        /* As long as they are equal, the exact value doesn't matter. */\n        ssl->in_left            = 0;\n        ssl->next_record_offset = 0;\n\n        hs->buffering.seen_ccs = 0;\n        goto exit;\n    }\n\n#if defined(MBEDTLS_DEBUG_C)\n    /* Debug only */\n    {\n        unsigned offset;\n        for (offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++) {\n            hs_buf = &hs->buffering.hs[offset];\n            if (hs_buf->is_valid == 1) {\n                MBEDTLS_SSL_DEBUG_MSG(2, (\"Future message with sequence number %u %s buffered.\",\n                                          hs->in_msg_seq + offset,\n                                          hs_buf->is_complete ? \"fully\" : \"partially\"));\n            }\n        }\n    }\n#endif /* MBEDTLS_DEBUG_C */\n\n    /* Check if we have buffered and/or fully reassembled the\n     * next handshake message. */\n    hs_buf = &hs->buffering.hs[0];\n    if ((hs_buf->is_valid == 1) && (hs_buf->is_complete == 1)) {\n        /* Synthesize a record containing the buffered HS message. */\n        size_t msg_len = MBEDTLS_GET_UINT24_BE(hs_buf->data, 1);\n\n        /* Double-check that we haven't accidentally buffered\n         * a message that doesn't fit into the input buffer. */\n        if (msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"Next handshake message has been buffered - load\"));\n        MBEDTLS_SSL_DEBUG_BUF(3, \"Buffered handshake message (incl. header)\",\n                              hs_buf->data, msg_len + 12);\n\n        ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;\n        ssl->in_hslen   = msg_len + 12;\n        ssl->in_msglen  = msg_len + 12;\n        memcpy(ssl->in_msg, hs_buf->data, ssl->in_hslen);\n\n        ret = 0;\n        goto exit;\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"Next handshake message %u not or only partially buffered\",\n                                  hs->in_msg_seq));\n    }\n\n    ret = -1;\n\nexit:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= ssl_load_buffered_message\"));\n    return ret;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_buffer_make_space(mbedtls_ssl_context *ssl,\n                                 size_t desired)\n{\n    int offset;\n    mbedtls_ssl_handshake_params * const hs = ssl->handshake;\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"Attempt to free buffered messages to have %u bytes available\",\n                              (unsigned) desired));\n\n    /* Get rid of future records epoch first, if such exist. */\n    ssl_free_buffered_record(ssl);\n\n    /* Check if we have enough space available now. */\n    if (desired <= (MBEDTLS_SSL_DTLS_MAX_BUFFERING -\n                    hs->buffering.total_bytes_buffered)) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"Enough space available after freeing future epoch record\"));\n        return 0;\n    }\n\n    /* We don't have enough space to buffer the next expected handshake\n     * message. Remove buffers used for future messages to gain space,\n     * starting with the most distant one. */\n    for (offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1;\n         offset >= 0; offset--) {\n        MBEDTLS_SSL_DEBUG_MSG(2,\n                              (\n                                  \"Free buffering slot %d to make space for reassembly of next handshake message\",\n                                  offset));\n\n        ssl_buffering_free_slot(ssl, (uint8_t) offset);\n\n        /* Check if we have enough space available now. */\n        if (desired <= (MBEDTLS_SSL_DTLS_MAX_BUFFERING -\n                        hs->buffering.total_bytes_buffered)) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"Enough space available after freeing buffered HS messages\"));\n            return 0;\n        }\n    }\n\n    return -1;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_buffer_message(mbedtls_ssl_context *ssl)\n{\n    int ret = 0;\n    mbedtls_ssl_handshake_params * const hs = ssl->handshake;\n\n    if (hs == NULL) {\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> ssl_buffer_message\"));\n\n    switch (ssl->in_msgtype) {\n        case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC:\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"Remember CCS message\"));\n\n            hs->buffering.seen_ccs = 1;\n            break;\n\n        case MBEDTLS_SSL_MSG_HANDSHAKE:\n        {\n            unsigned recv_msg_seq_offset;\n            unsigned recv_msg_seq = MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4);\n            mbedtls_ssl_hs_buffer *hs_buf;\n            size_t msg_len = ssl->in_hslen - 12;\n\n            /* We should never receive an old handshake\n             * message - double-check nonetheless. */\n            if (recv_msg_seq < ssl->handshake->in_msg_seq) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n            }\n\n            recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq;\n            if (recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS) {\n                /* Silently ignore -- message too far in the future */\n                MBEDTLS_SSL_DEBUG_MSG(2,\n                                      (\"Ignore future HS message with sequence number %u, \"\n                                       \"buffering window %u - %u\",\n                                       recv_msg_seq, ssl->handshake->in_msg_seq,\n                                       ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS -\n                                       1));\n\n                goto exit;\n            }\n\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"Buffering HS message with sequence number %u, offset %u \",\n                                      recv_msg_seq, recv_msg_seq_offset));\n\n            hs_buf = &hs->buffering.hs[recv_msg_seq_offset];\n\n            /* Check if the buffering for this seq nr has already commenced. */\n            if (!hs_buf->is_valid) {\n                size_t reassembly_buf_sz;\n\n                hs_buf->is_fragmented =\n                    (ssl_hs_is_proper_fragment(ssl) == 1);\n\n                /* We copy the message back into the input buffer\n                 * after reassembly, so check that it's not too large.\n                 * This is an implementation-specific limitation\n                 * and not one from the standard, hence it is not\n                 * checked in ssl_check_hs_header(). */\n                if (msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN) {\n                    /* Ignore message */\n                    goto exit;\n                }\n\n                /* Check if we have enough space to buffer the message. */\n                if (hs->buffering.total_bytes_buffered >\n                    MBEDTLS_SSL_DTLS_MAX_BUFFERING) {\n                    MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n                    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n                }\n\n                reassembly_buf_sz = ssl_get_reassembly_buffer_size(msg_len,\n                                                                   hs_buf->is_fragmented);\n\n                if (reassembly_buf_sz > (MBEDTLS_SSL_DTLS_MAX_BUFFERING -\n                                         hs->buffering.total_bytes_buffered)) {\n                    if (recv_msg_seq_offset > 0) {\n                        /* If we can't buffer a future message because\n                         * of space limitations -- ignore. */\n                        MBEDTLS_SSL_DEBUG_MSG(2,\n                                              (\"Buffering of future message of size %\"\n                                               MBEDTLS_PRINTF_SIZET\n                                               \" would exceed the compile-time limit %\"\n                                               MBEDTLS_PRINTF_SIZET\n                                               \" (already %\" MBEDTLS_PRINTF_SIZET\n                                               \" bytes buffered) -- ignore\\n\",\n                                               msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,\n                                               hs->buffering.total_bytes_buffered));\n                        goto exit;\n                    } else {\n                        MBEDTLS_SSL_DEBUG_MSG(2,\n                                              (\"Buffering of future message of size %\"\n                                               MBEDTLS_PRINTF_SIZET\n                                               \" would exceed the compile-time limit %\"\n                                               MBEDTLS_PRINTF_SIZET\n                                               \" (already %\" MBEDTLS_PRINTF_SIZET\n                                               \" bytes buffered) -- attempt to make space by freeing buffered future messages\\n\",\n                                               msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,\n                                               hs->buffering.total_bytes_buffered));\n                    }\n\n                    if (ssl_buffer_make_space(ssl, reassembly_buf_sz) != 0) {\n                        MBEDTLS_SSL_DEBUG_MSG(2,\n                                              (\"Reassembly of next message of size %\"\n                                               MBEDTLS_PRINTF_SIZET\n                                               \" (%\" MBEDTLS_PRINTF_SIZET\n                                               \" with bitmap) would exceed\"\n                                               \" the compile-time limit %\"\n                                               MBEDTLS_PRINTF_SIZET\n                                               \" (already %\" MBEDTLS_PRINTF_SIZET\n                                               \" bytes buffered) -- fail\\n\",\n                                               msg_len,\n                                               reassembly_buf_sz,\n                                               (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,\n                                               hs->buffering.total_bytes_buffered));\n                        ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n                        goto exit;\n                    }\n                }\n\n                MBEDTLS_SSL_DEBUG_MSG(2,\n                                      (\"initialize reassembly, total length = %\"\n                                       MBEDTLS_PRINTF_SIZET,\n                                       msg_len));\n\n                hs_buf->data = mbedtls_calloc(1, reassembly_buf_sz);\n                if (hs_buf->data == NULL) {\n                    ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;\n                    goto exit;\n                }\n                hs_buf->data_len = reassembly_buf_sz;\n\n                /* Prepare final header: copy msg_type, length and message_seq,\n                 * then add standardised fragment_offset and fragment_length */\n                memcpy(hs_buf->data, ssl->in_msg, 6);\n                memset(hs_buf->data + 6, 0, 3);\n                memcpy(hs_buf->data + 9, hs_buf->data + 1, 3);\n\n                hs_buf->is_valid = 1;\n\n                hs->buffering.total_bytes_buffered += reassembly_buf_sz;\n            } else {\n                /* Make sure msg_type and length are consistent */\n                if (memcmp(hs_buf->data, ssl->in_msg, 4) != 0) {\n                    MBEDTLS_SSL_DEBUG_MSG(1, (\"Fragment header mismatch - ignore\"));\n                    /* Ignore */\n                    goto exit;\n                }\n            }\n\n            if (!hs_buf->is_complete) {\n                size_t frag_len, frag_off;\n                unsigned char * const msg = hs_buf->data + 12;\n\n                /*\n                 * Check and copy current fragment\n                 */\n\n                /* Validation of header fields already done in\n                 * mbedtls_ssl_prepare_handshake_record(). */\n                frag_off = ssl_get_hs_frag_off(ssl);\n                frag_len = ssl_get_hs_frag_len(ssl);\n\n                MBEDTLS_SSL_DEBUG_MSG(2, (\"adding fragment, offset = %\" MBEDTLS_PRINTF_SIZET\n                                          \", length = %\" MBEDTLS_PRINTF_SIZET,\n                                          frag_off, frag_len));\n                memcpy(msg + frag_off, ssl->in_msg + 12, frag_len);\n\n                if (hs_buf->is_fragmented) {\n                    unsigned char * const bitmask = msg + msg_len;\n                    ssl_bitmask_set(bitmask, frag_off, frag_len);\n                    hs_buf->is_complete = (ssl_bitmask_check(bitmask,\n                                                             msg_len) == 0);\n                } else {\n                    hs_buf->is_complete = 1;\n                }\n\n                MBEDTLS_SSL_DEBUG_MSG(2, (\"message %scomplete\",\n                                          hs_buf->is_complete ? \"\" : \"not yet \"));\n            }\n\n            break;\n        }\n\n        default:\n            /* We don't buffer other types of messages. */\n            break;\n    }\n\nexit:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= ssl_buffer_message\"));\n    return ret;\n}\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_consume_current_message(mbedtls_ssl_context *ssl)\n{\n    /*\n     * Consume last content-layer message and potentially\n     * update in_msglen which keeps track of the contents'\n     * consumption state.\n     *\n     * (1) Handshake messages:\n     *     Remove last handshake message, move content\n     *     and adapt in_msglen.\n     *\n     * (2) Alert messages:\n     *     Consume whole record content, in_msglen = 0.\n     *\n     * (3) Change cipher spec:\n     *     Consume whole record content, in_msglen = 0.\n     *\n     * (4) Application data:\n     *     Don't do anything - the record layer provides\n     *     the application data as a stream transport\n     *     and consumes through mbedtls_ssl_read only.\n     *\n     */\n\n    /* Case (1): Handshake messages */\n    if (ssl->in_hslen != 0) {\n        /* Hard assertion to be sure that no application data\n         * is in flight, as corrupting ssl->in_msglen during\n         * ssl->in_offt != NULL is fatal. */\n        if (ssl->in_offt != NULL) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        if (ssl->badmac_seen_or_in_hsfraglen != 0) {\n            /* Not all handshake fragments have arrived, do not consume. */\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"Consume: waiting for more handshake fragments \"\n                                      \"%u/%\" MBEDTLS_PRINTF_SIZET,\n                                      ssl->badmac_seen_or_in_hsfraglen, ssl->in_hslen));\n            return 0;\n        }\n\n        /*\n         * Get next Handshake message in the current record\n         */\n\n        /* Notes:\n         * (1) in_hslen is not necessarily the size of the\n         *     current handshake content: If DTLS handshake\n         *     fragmentation is used, that's the fragment\n         *     size instead. Using the total handshake message\n         *     size here is faulty and should be changed at\n         *     some point.\n         * (2) While it doesn't seem to cause problems, one\n         *     has to be very careful not to assume that in_hslen\n         *     is always <= in_msglen in a sensible communication.\n         *     Again, it's wrong for DTLS handshake fragmentation.\n         *     The following check is therefore mandatory, and\n         *     should not be treated as a silently corrected assertion.\n         *     Additionally, ssl->in_hslen might be arbitrarily out of\n         *     bounds after handling a DTLS message with an unexpected\n         *     sequence number, see mbedtls_ssl_prepare_handshake_record.\n         */\n        if (ssl->in_hslen < ssl->in_msglen) {\n            ssl->in_msglen -= ssl->in_hslen;\n            memmove(ssl->in_msg, ssl->in_msg + ssl->in_hslen,\n                    ssl->in_msglen);\n            MBEDTLS_PUT_UINT16_BE(ssl->in_msglen, ssl->in_len, 0);\n\n            MBEDTLS_SSL_DEBUG_BUF(4, \"remaining content in record\",\n                                  ssl->in_msg, ssl->in_msglen);\n        } else {\n            ssl->in_msglen = 0;\n        }\n\n        ssl->in_hslen   = 0;\n    }\n    /* Case (4): Application data */\n    else if (ssl->in_offt != NULL) {\n        return 0;\n    }\n    /* Everything else (CCS & Alerts) */\n    else {\n        ssl->in_msglen = 0;\n    }\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_record_is_in_progress(mbedtls_ssl_context *ssl)\n{\n    if (ssl->in_msglen > 0) {\n        return 1;\n    }\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n\nstatic void ssl_free_buffered_record(mbedtls_ssl_context *ssl)\n{\n    mbedtls_ssl_handshake_params * const hs = ssl->handshake;\n    if (hs == NULL) {\n        return;\n    }\n\n    if (hs->buffering.future_record.data != NULL) {\n        hs->buffering.total_bytes_buffered -=\n            hs->buffering.future_record.len;\n\n        mbedtls_free(hs->buffering.future_record.data);\n        hs->buffering.future_record.data = NULL;\n    }\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_load_buffered_record(mbedtls_ssl_context *ssl)\n{\n    mbedtls_ssl_handshake_params * const hs = ssl->handshake;\n    unsigned char *rec;\n    size_t rec_len;\n    unsigned rec_epoch;\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n    size_t in_buf_len = ssl->in_buf_len;\n#else\n    size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;\n#endif\n    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        return 0;\n    }\n\n    if (hs == NULL) {\n        return 0;\n    }\n\n    rec       = hs->buffering.future_record.data;\n    rec_len   = hs->buffering.future_record.len;\n    rec_epoch = hs->buffering.future_record.epoch;\n\n    if (rec == NULL) {\n        return 0;\n    }\n\n    /* Only consider loading future records if the\n     * input buffer is empty. */\n    if (ssl_next_record_is_in_datagram(ssl) == 1) {\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> ssl_load_buffered_record\"));\n\n    if (rec_epoch != ssl->in_epoch) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"Buffered record not from current epoch.\"));\n        goto exit;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"Found buffered record from current epoch - load\"));\n\n    /* Double-check that the record is not too large */\n    if (rec_len > in_buf_len - (size_t) (ssl->in_hdr - ssl->in_buf)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    memcpy(ssl->in_hdr, rec, rec_len);\n    ssl->in_left = rec_len;\n    ssl->next_record_offset = 0;\n\n    ssl_free_buffered_record(ssl);\n\nexit:\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= ssl_load_buffered_record\"));\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_buffer_future_record(mbedtls_ssl_context *ssl,\n                                    mbedtls_record const *rec)\n{\n    mbedtls_ssl_handshake_params * const hs = ssl->handshake;\n\n    /* Don't buffer future records outside handshakes. */\n    if (hs == NULL) {\n        return 0;\n    }\n\n    /* Only buffer handshake records (we are only interested\n     * in Finished messages). */\n    if (rec->type != MBEDTLS_SSL_MSG_HANDSHAKE) {\n        return 0;\n    }\n\n    /* Don't buffer more than one future epoch record. */\n    if (hs->buffering.future_record.data != NULL) {\n        return 0;\n    }\n\n    /* Don't buffer record if there's not enough buffering space remaining. */\n    if (rec->buf_len > (MBEDTLS_SSL_DTLS_MAX_BUFFERING -\n                        hs->buffering.total_bytes_buffered)) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"Buffering of future epoch record of size %\" MBEDTLS_PRINTF_SIZET\n                                  \" would exceed the compile-time limit %\" MBEDTLS_PRINTF_SIZET\n                                  \" (already %\" MBEDTLS_PRINTF_SIZET\n                                  \" bytes buffered) -- ignore\\n\",\n                                  rec->buf_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,\n                                  hs->buffering.total_bytes_buffered));\n        return 0;\n    }\n\n    /* Buffer record */\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"Buffer record from epoch %u\",\n                              ssl->in_epoch + 1U));\n    MBEDTLS_SSL_DEBUG_BUF(3, \"Buffered record\", rec->buf, rec->buf_len);\n\n    /* ssl_parse_record_header() only considers records\n     * of the next epoch as candidates for buffering. */\n    hs->buffering.future_record.epoch = ssl->in_epoch + 1;\n    hs->buffering.future_record.len   = rec->buf_len;\n\n    hs->buffering.future_record.data =\n        mbedtls_calloc(1, hs->buffering.future_record.len);\n    if (hs->buffering.future_record.data == NULL) {\n        /* If we run out of RAM trying to buffer a\n         * record from the next epoch, just ignore. */\n        return 0;\n    }\n\n    memcpy(hs->buffering.future_record.data, rec->buf, rec->buf_len);\n\n    hs->buffering.total_bytes_buffered += rec->buf_len;\n    return 0;\n}\n\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_get_next_record(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_record rec;\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    /* We might have buffered a future record; if so,\n     * and if the epoch matches now, load it.\n     * On success, this call will set ssl->in_left to\n     * the length of the buffered record, so that\n     * the calls to ssl_fetch_input() below will\n     * essentially be no-ops. */\n    ret = ssl_load_buffered_record(ssl);\n    if (ret != 0) {\n        return ret;\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    /* Ensure that we have enough space available for the default form\n     * of TLS / DTLS record headers (5 Bytes for TLS, 13 Bytes for DTLS,\n     * with no space for CIDs counted in). */\n    ret = mbedtls_ssl_fetch_input(ssl, mbedtls_ssl_in_hdr_len(ssl));\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_fetch_input\", ret);\n        return ret;\n    }\n\n    ret = ssl_parse_record_header(ssl, ssl->in_hdr, ssl->in_left, &rec);\n    if (ret != 0) {\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n            if (ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE) {\n                ret = ssl_buffer_future_record(ssl, &rec);\n                if (ret != 0) {\n                    return ret;\n                }\n\n                /* Fall through to handling of unexpected records */\n                ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;\n            }\n\n            if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) {\n#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)\n                /* Reset in pointers to default state for TLS/DTLS records,\n                 * assuming no CID and no offset between record content and\n                 * record plaintext. */\n                mbedtls_ssl_update_in_pointers(ssl);\n\n                /* Setup internal message pointers from record structure. */\n                ssl->in_msgtype = rec.type;\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n                ssl->in_len = ssl->in_cid + rec.cid_len;\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n                ssl->in_iv  = ssl->in_msg = ssl->in_len + 2;\n                ssl->in_msglen = rec.data_len;\n\n                ret = ssl_check_client_reconnect(ssl);\n                MBEDTLS_SSL_DEBUG_RET(2, \"ssl_check_client_reconnect\", ret);\n                if (ret != 0) {\n                    return ret;\n                }\n#endif\n\n                /* Skip unexpected record (but not whole datagram) */\n                ssl->next_record_offset = rec.buf_len;\n\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"discarding unexpected record \"\n                                          \"(header)\"));\n            } else {\n                /* Skip invalid record and the rest of the datagram */\n                ssl->next_record_offset = 0;\n                ssl->in_left = 0;\n\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"discarding invalid record \"\n                                          \"(header)\"));\n            }\n\n            /* Get next record */\n            return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;\n        } else\n#endif\n        {\n            return ret;\n        }\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        /* Remember offset of next record within datagram. */\n        ssl->next_record_offset = rec.buf_len;\n        if (ssl->next_record_offset < ssl->in_left) {\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"more than one record within datagram\"));\n        }\n    } else\n#endif\n    {\n        /*\n         * Fetch record contents from underlying transport.\n         */\n        ret = mbedtls_ssl_fetch_input(ssl, rec.buf_len);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_fetch_input\", ret);\n            return ret;\n        }\n\n        ssl->in_left = 0;\n    }\n\n    /*\n     * Decrypt record contents.\n     */\n\n    if ((ret = ssl_prepare_record_content(ssl, &rec)) != 0) {\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n            /* Silently discard invalid records */\n            if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) {\n                /* Except when waiting for Finished as a bad mac here\n                 * probably means something went wrong in the handshake\n                 * (eg wrong psk used, mitm downgrade attempt, etc.) */\n                if (ssl->state == MBEDTLS_SSL_CLIENT_FINISHED ||\n                    ssl->state == MBEDTLS_SSL_SERVER_FINISHED) {\n#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)\n                    if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) {\n                        mbedtls_ssl_send_alert_message(ssl,\n                                                       MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                                       MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC);\n                    }\n#endif\n                    return ret;\n                }\n\n                if (ssl->conf->badmac_limit != 0) {\n                    ++ssl->badmac_seen_or_in_hsfraglen;\n                    if (ssl->badmac_seen_or_in_hsfraglen >= ssl->conf->badmac_limit) {\n                        MBEDTLS_SSL_DEBUG_MSG(1, (\"too many records with bad MAC\"));\n                        return MBEDTLS_ERR_SSL_INVALID_MAC;\n                    }\n                }\n\n                /* As above, invalid records cause\n                 * dismissal of the whole datagram. */\n\n                ssl->next_record_offset = 0;\n                ssl->in_left = 0;\n\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"discarding invalid record (mac)\"));\n                return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;\n            }\n\n            return ret;\n        } else\n#endif\n        {\n            /* Error out (and send alert) on invalid records */\n#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)\n            if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) {\n                mbedtls_ssl_send_alert_message(ssl,\n                                               MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                               MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC);\n            }\n#endif\n            return ret;\n        }\n    }\n\n\n    /* Reset in pointers to default state for TLS/DTLS records,\n     * assuming no CID and no offset between record content and\n     * record plaintext. */\n    mbedtls_ssl_update_in_pointers(ssl);\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    ssl->in_len = ssl->in_cid + rec.cid_len;\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n    ssl->in_iv  = ssl->in_len + 2;\n\n    /* The record content type may change during decryption,\n     * so re-read it. */\n    ssl->in_msgtype = rec.type;\n    /* Also update the input buffer, because unfortunately\n     * the server-side ssl_parse_client_hello() reparses the\n     * record header when receiving a ClientHello initiating\n     * a renegotiation. */\n    ssl->in_hdr[0] = rec.type;\n    ssl->in_msg    = rec.buf + rec.data_offset;\n    ssl->in_msglen = rec.data_len;\n    MBEDTLS_PUT_UINT16_BE(rec.data_len, ssl->in_len, 0);\n\n    return 0;\n}\n\nint mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* If we're in the middle of a fragmented TLS handshake message,\n     * we don't accept any other message type. For TLS 1.3, the spec forbids\n     * interleaving other message types between handshake fragments. For TLS\n     * 1.2, the spec does not forbid it but we do. */\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM &&\n        ssl->badmac_seen_or_in_hsfraglen != 0 &&\n        ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"non-handshake message in the middle\"\n                                  \" of a fragmented handshake message\"));\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n    /*\n     * Handle particular types of records\n     */\n    if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) {\n        if ((ret = mbedtls_ssl_prepare_handshake_record(ssl)) != 0) {\n            return ret;\n        }\n    }\n\n    if (ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) {\n        if (ssl->in_msglen != 1) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"invalid CCS message, len: %\" MBEDTLS_PRINTF_SIZET,\n                                      ssl->in_msglen));\n            return MBEDTLS_ERR_SSL_INVALID_RECORD;\n        }\n\n        if (ssl->in_msg[0] != 1) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"invalid CCS message, content: %02x\",\n                                      ssl->in_msg[0]));\n            return MBEDTLS_ERR_SSL_INVALID_RECORD;\n        }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n            ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC    &&\n            ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC) {\n            if (ssl->handshake == NULL) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"dropping ChangeCipherSpec outside handshake\"));\n                return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;\n            }\n\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"received out-of-order ChangeCipherSpec - remember\"));\n            return MBEDTLS_ERR_SSL_EARLY_MESSAGE;\n        }\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n        if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {\n            MBEDTLS_SSL_DEBUG_MSG(2,\n                                  (\"Ignore ChangeCipherSpec in TLS 1.3 compatibility mode\"));\n            return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;\n        }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n    }\n\n    if (ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT) {\n        if (ssl->in_msglen != 2) {\n            /* Note: Standard allows for more than one 2 byte alert\n               to be packed in a single message, but Mbed TLS doesn't\n               currently support this. */\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"invalid alert message, len: %\" MBEDTLS_PRINTF_SIZET,\n                                      ssl->in_msglen));\n            return MBEDTLS_ERR_SSL_INVALID_RECORD;\n        }\n\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"got an alert message, type: [%u:%u]\",\n                                  ssl->in_msg[0], ssl->in_msg[1]));\n\n        /*\n         * Ignore non-fatal alerts, except close_notify and no_renegotiation\n         */\n        if (ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"is a fatal alert message (msg %d)\",\n                                      ssl->in_msg[1]));\n            return MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE;\n        }\n\n        if (ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&\n            ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"is a close notify message\"));\n            return MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY;\n        }\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED)\n        if (ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&\n            ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"is a no renegotiation alert\"));\n            /* Will be handled when trying to parse ServerHello */\n            return 0;\n        }\n#endif\n        /* Silently ignore: fetch new message */\n        return MBEDTLS_ERR_SSL_NON_FATAL;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        /* Drop unexpected ApplicationData records,\n         * except at the beginning of renegotiations */\n        if (ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&\n            mbedtls_ssl_is_handshake_over(ssl) == 0\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n            && !(ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&\n                 ssl->state == MBEDTLS_SSL_SERVER_HELLO)\n#endif\n            ) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"dropping unexpected ApplicationData\"));\n            return MBEDTLS_ERR_SSL_NON_FATAL;\n        }\n\n        if (ssl->handshake != NULL &&\n            mbedtls_ssl_is_handshake_over(ssl) == 1) {\n            mbedtls_ssl_handshake_wrapup_free_hs_transform(ssl);\n        }\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    return 0;\n}\n\nint mbedtls_ssl_send_fatal_handshake_failure(mbedtls_ssl_context *ssl)\n{\n    return mbedtls_ssl_send_alert_message(ssl,\n                                          MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                          MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n}\n\nint mbedtls_ssl_send_alert_message(mbedtls_ssl_context *ssl,\n                                   unsigned char level,\n                                   unsigned char message)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (ssl == NULL || ssl->conf == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if (ssl->out_left != 0) {\n        return mbedtls_ssl_flush_output(ssl);\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> send alert message\"));\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"send alert level=%u message=%u\", level, message));\n\n    ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT;\n    ssl->out_msglen = 2;\n    ssl->out_msg[0] = level;\n    ssl->out_msg[1] = message;\n\n    if ((ret = mbedtls_ssl_write_record(ssl, SSL_FORCE_FLUSH)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_write_record\", ret);\n        return ret;\n    }\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= send alert message\"));\n\n    return 0;\n}\n\nint mbedtls_ssl_write_change_cipher_spec(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write change cipher spec\"));\n\n    ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;\n    ssl->out_msglen  = 1;\n    ssl->out_msg[0]  = 1;\n\n    mbedtls_ssl_handshake_increment_state(ssl);\n\n    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_write_handshake_msg\", ret);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write change cipher spec\"));\n\n    return 0;\n}\n\nint mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse change cipher spec\"));\n\n    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_read_record\", ret);\n        return ret;\n    }\n\n    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad change cipher spec message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n    /* CCS records are only accepted if they have length 1 and content '1',\n     * so we don't need to check this here. */\n\n    /*\n     * Switch to our negotiated transform and session parameters for inbound\n     * data.\n     */\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"switching to new transform spec for inbound data\"));\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    ssl->transform_in = ssl->transform_negotiate;\n#endif\n    ssl->session_in = ssl->session_negotiate;\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\n        mbedtls_ssl_dtls_replay_reset(ssl);\n#endif\n\n        /* Increment epoch */\n        if (++ssl->in_epoch == 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"DTLS epoch would wrap\"));\n            /* This is highly unlikely to happen for legitimate reasons, so\n               treat it as an attack and don't send an alert. */\n            return MBEDTLS_ERR_SSL_COUNTER_WRAPPING;\n        }\n    } else\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n    memset(ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN);\n\n    mbedtls_ssl_update_in_pointers(ssl);\n\n    mbedtls_ssl_handshake_increment_state(ssl);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse change cipher spec\"));\n\n    return 0;\n}\n\n/* Once ssl->out_hdr as the address of the beginning of the\n * next outgoing record is set, deduce the other pointers.\n *\n * Note: For TLS, we save the implicit record sequence number\n *       (entering MAC computation) in the 8 bytes before ssl->out_hdr,\n *       and the caller has to make sure there's space for this.\n */\n\nstatic size_t ssl_transform_get_explicit_iv_len(\n    mbedtls_ssl_transform const *transform)\n{\n    return transform->ivlen - transform->fixed_ivlen;\n}\n\nvoid mbedtls_ssl_update_out_pointers(mbedtls_ssl_context *ssl,\n                                     mbedtls_ssl_transform *transform)\n{\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        ssl->out_ctr = ssl->out_hdr +  3;\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n        ssl->out_cid = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;\n        ssl->out_len = ssl->out_cid;\n        if (transform != NULL) {\n            ssl->out_len += transform->out_cid_len;\n        }\n#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n        ssl->out_len = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n        ssl->out_iv  = ssl->out_len + 2;\n    } else\n#endif\n    {\n        ssl->out_len = ssl->out_hdr + 3;\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n        ssl->out_cid = ssl->out_len;\n#endif\n        ssl->out_iv  = ssl->out_hdr + 5;\n    }\n\n    ssl->out_msg = ssl->out_iv;\n    /* Adjust out_msg to make space for explicit IV, if used. */\n    if (transform != NULL) {\n        ssl->out_msg += ssl_transform_get_explicit_iv_len(transform);\n    }\n}\n\n/* Once ssl->in_hdr as the address of the beginning of the\n * next incoming record is set, deduce the other pointers.\n *\n * Note: For TLS, we save the implicit record sequence number\n *       (entering MAC computation) in the 8 bytes before ssl->in_hdr,\n *       and the caller has to make sure there's space for this.\n */\n\nvoid mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl)\n{\n    /* This function sets the pointers to match the case\n     * of unprotected TLS/DTLS records, with both  ssl->in_iv\n     * and ssl->in_msg pointing to the beginning of the record\n     * content.\n     *\n     * When decrypting a protected record, ssl->in_msg\n     * will be shifted to point to the beginning of the\n     * record plaintext.\n     */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        /* This sets the header pointers to match records\n         * without CID. When we receive a record containing\n         * a CID, the fields are shifted accordingly in\n         * ssl_parse_record_header(). */\n        ssl->in_ctr = ssl->in_hdr +  3;\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n        ssl->in_cid = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;\n        ssl->in_len = ssl->in_cid; /* Default: no CID */\n#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n        ssl->in_len = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n        ssl->in_iv  = ssl->in_len + 2;\n    } else\n#endif\n    {\n        ssl->in_ctr = ssl->in_buf;\n        ssl->in_len = ssl->in_hdr + 3;\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n        ssl->in_cid = ssl->in_len;\n#endif\n        ssl->in_iv  = ssl->in_hdr + 5;\n    }\n\n    /* This will be adjusted at record decryption time. */\n    ssl->in_msg = ssl->in_iv;\n}\n\n/*\n * Setup an SSL context\n */\n\nvoid mbedtls_ssl_reset_in_pointers(mbedtls_ssl_context *ssl)\n{\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        ssl->in_hdr = ssl->in_buf;\n    } else\n#endif  /* MBEDTLS_SSL_PROTO_DTLS */\n    {\n        ssl->in_hdr = ssl->in_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;\n    }\n\n    /* Derive other internal pointers. */\n    mbedtls_ssl_update_in_pointers(ssl);\n}\n\nvoid mbedtls_ssl_reset_out_pointers(mbedtls_ssl_context *ssl)\n{\n    /* Set the incoming and outgoing record pointers. */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        ssl->out_hdr = ssl->out_buf;\n    } else\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n    {\n        ssl->out_ctr = ssl->out_buf;\n        ssl->out_hdr = ssl->out_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;\n    }\n    /* Derive other internal pointers. */\n    mbedtls_ssl_update_out_pointers(ssl, NULL /* no transform enabled */);\n}\n\n/*\n * SSL get accessors\n */\nsize_t mbedtls_ssl_get_bytes_avail(const mbedtls_ssl_context *ssl)\n{\n    return ssl->in_offt == NULL ? 0 : ssl->in_msglen;\n}\n\nint mbedtls_ssl_check_pending(const mbedtls_ssl_context *ssl)\n{\n    /*\n     * Case A: We're currently holding back\n     * a message for further processing.\n     */\n\n    if (ssl->keep_current_message == 1) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"ssl_check_pending: record held back for processing\"));\n        return 1;\n    }\n\n    /*\n     * Case B: Further records are pending in the current datagram.\n     */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n        ssl->in_left > ssl->next_record_offset) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"ssl_check_pending: more records within current datagram\"));\n        return 1;\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    /*\n     * Case C: A handshake message is being processed.\n     */\n\n    if (ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen) {\n        MBEDTLS_SSL_DEBUG_MSG(3,\n                              (\"ssl_check_pending: more handshake messages within current record\"));\n        return 1;\n    }\n\n    /*\n     * Case D: An application data message is being processed\n     */\n    if (ssl->in_offt != NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"ssl_check_pending: application data record is being processed\"));\n        return 1;\n    }\n\n    /*\n     * In all other cases, the rest of the message can be dropped.\n     * As in ssl_get_next_record, this needs to be adapted if\n     * we implement support for multiple alerts in single records.\n     */\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"ssl_check_pending: nothing pending\"));\n    return 0;\n}\n\n\nint mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl)\n{\n    size_t transform_expansion = 0;\n    const mbedtls_ssl_transform *transform = ssl->transform_out;\n    unsigned block_size;\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;\n    psa_key_type_t key_type;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    size_t out_hdr_len = mbedtls_ssl_out_hdr_len(ssl);\n\n    if (transform == NULL) {\n        return (int) out_hdr_len;\n    }\n\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (transform->psa_alg == PSA_ALG_GCM ||\n        transform->psa_alg == PSA_ALG_CCM ||\n        transform->psa_alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 8) ||\n        transform->psa_alg == PSA_ALG_CHACHA20_POLY1305 ||\n        transform->psa_alg == MBEDTLS_SSL_NULL_CIPHER) {\n        transform_expansion = transform->minlen;\n    } else if (transform->psa_alg == PSA_ALG_CBC_NO_PADDING) {\n        (void) psa_get_key_attributes(transform->psa_key_enc, &attr);\n        key_type = psa_get_key_type(&attr);\n\n        block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type);\n\n        /* Expansion due to the addition of the MAC. */\n        transform_expansion += transform->maclen;\n\n        /* Expansion due to the addition of CBC padding;\n         * Theoretically up to 256 bytes, but we never use\n         * more than the block size of the underlying cipher. */\n        transform_expansion += block_size;\n\n        /* For TLS 1.2 or higher, an explicit IV is added\n         * after the record header. */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        transform_expansion += block_size;\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"Unsupported psa_alg spotted in mbedtls_ssl_get_record_expansion()\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n#else\n    switch (mbedtls_cipher_get_cipher_mode(&transform->cipher_ctx_enc)) {\n        case MBEDTLS_MODE_GCM:\n        case MBEDTLS_MODE_CCM:\n        case MBEDTLS_MODE_CHACHAPOLY:\n        case MBEDTLS_MODE_STREAM:\n            transform_expansion = transform->minlen;\n            break;\n\n        case MBEDTLS_MODE_CBC:\n\n            block_size = mbedtls_cipher_get_block_size(\n                &transform->cipher_ctx_enc);\n\n            /* Expansion due to the addition of the MAC. */\n            transform_expansion += transform->maclen;\n\n            /* Expansion due to the addition of CBC padding;\n             * Theoretically up to 256 bytes, but we never use\n             * more than the block size of the underlying cipher. */\n            transform_expansion += block_size;\n\n            /* For TLS 1.2 or higher, an explicit IV is added\n             * after the record header. */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n            transform_expansion += block_size;\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n            break;\n\n        default:\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    if (transform->out_cid_len != 0) {\n        transform_expansion += MBEDTLS_SSL_MAX_CID_EXPANSION;\n    }\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n    return (int) (out_hdr_len + transform_expansion);\n}\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n/*\n * Check record counters and renegotiate if they're above the limit.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_check_ctr_renegotiate(mbedtls_ssl_context *ssl)\n{\n    size_t ep_len = mbedtls_ssl_ep_len(ssl);\n    int in_ctr_cmp;\n    int out_ctr_cmp;\n\n    if (mbedtls_ssl_is_handshake_over(ssl) == 0 ||\n        ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ||\n        ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED) {\n        return 0;\n    }\n\n    in_ctr_cmp = memcmp(ssl->in_ctr + ep_len,\n                        &ssl->conf->renego_period[ep_len],\n                        MBEDTLS_SSL_SEQUENCE_NUMBER_LEN - ep_len);\n    out_ctr_cmp = memcmp(&ssl->cur_out_ctr[ep_len],\n                         &ssl->conf->renego_period[ep_len],\n                         sizeof(ssl->cur_out_ctr) - ep_len);\n\n    if (in_ctr_cmp <= 0 && out_ctr_cmp <= 0) {\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"record counter limit reached: renegotiate\"));\n    return mbedtls_ssl_renegotiate(ssl);\n}\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n\n#if defined(MBEDTLS_SSL_CLI_C)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_is_new_session_ticket(mbedtls_ssl_context *ssl)\n{\n\n    if ((ssl->in_hslen == mbedtls_ssl_hs_hdr_len(ssl)) ||\n        (ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET)) {\n        return 0;\n    }\n\n    return 1;\n}\n#endif /* MBEDTLS_SSL_CLI_C */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl)\n{\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"received post-handshake message\"));\n\n#if defined(MBEDTLS_SSL_CLI_C)\n    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {\n        if (ssl_tls13_is_new_session_ticket(ssl)) {\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"NewSessionTicket received\"));\n            if (mbedtls_ssl_conf_is_signal_new_session_tickets_enabled(ssl->conf) ==\n                MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED) {\n                ssl->keep_current_message = 1;\n\n                mbedtls_ssl_handshake_set_state(ssl,\n                                                MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);\n                return MBEDTLS_ERR_SSL_WANT_READ;\n            } else {\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"Ignoring NewSessionTicket, handling disabled.\"));\n                return 0;\n            }\n#else\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"Ignoring NewSessionTicket, not supported.\"));\n            return 0;\n#endif\n        }\n    }\n#endif /* MBEDTLS_SSL_CLI_C */\n\n    /* Fail in all other cases. */\n    return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n}\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n/* This function is called from mbedtls_ssl_read() when a handshake message is\n * received after the initial handshake. In this context, handshake messages\n * may only be sent for the purpose of initiating renegotiations.\n *\n * This function is introduced as a separate helper since the handling\n * of post-handshake handshake messages changes significantly in TLS 1.3,\n * and having a helper function allows to distinguish between TLS <= 1.2 and\n * TLS 1.3 in the future without bloating the logic of mbedtls_ssl_read().\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls12_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /*\n     * - For client-side, expect SERVER_HELLO_REQUEST.\n     * - For server-side, expect CLIENT_HELLO.\n     * - Fail (TLS) or silently drop record (DTLS) in other cases.\n     */\n\n#if defined(MBEDTLS_SSL_CLI_C)\n    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&\n        (ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST ||\n         ssl->in_hslen  != mbedtls_ssl_hs_hdr_len(ssl))) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"handshake received (not HelloRequest)\"));\n\n        /* With DTLS, drop the packet (probably from last handshake) */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n            return 0;\n        }\n#endif\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n#endif /* MBEDTLS_SSL_CLI_C */\n\n#if defined(MBEDTLS_SSL_SRV_C)\n    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&\n        ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"handshake received (not ClientHello)\"));\n\n        /* With DTLS, drop the packet (probably from last handshake) */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n            return 0;\n        }\n#endif\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    /* Determine whether renegotiation attempt should be accepted */\n    if (!(ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ||\n          (ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&\n           ssl->conf->allow_legacy_renegotiation ==\n           MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION))) {\n        /*\n         * Accept renegotiation request\n         */\n\n        /* DTLS clients need to know renego is server-initiated */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n            ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {\n            ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;\n        }\n#endif\n        ret = mbedtls_ssl_start_renegotiation(ssl);\n        if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&\n            ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_start_renegotiation\",\n                                  ret);\n            return ret;\n        }\n    } else\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n    {\n        /*\n         * Refuse renegotiation\n         */\n\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"refusing renegotiation, sending alert\"));\n\n        if ((ret = mbedtls_ssl_send_alert_message(ssl,\n                                                  MBEDTLS_SSL_ALERT_LEVEL_WARNING,\n                                                  MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION)) != 0) {\n            return ret;\n        }\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl)\n{\n    /* Check protocol version and dispatch accordingly. */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {\n        return ssl_tls13_handle_hs_message_post_handshake(ssl);\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    if (ssl->tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) {\n        return ssl_tls12_handle_hs_message_post_handshake(ssl);\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n    /* Should never happen */\n    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n}\n\n/*\n * brief          Read at most 'len' application data bytes from the input\n *                buffer.\n *\n * param ssl      SSL context:\n *                - First byte of application data not read yet in the input\n *                  buffer located at address `in_offt`.\n *                - The number of bytes of data not read yet is `in_msglen`.\n * param buf      buffer that will hold the data\n * param len      maximum number of bytes to read\n *\n * note           The function updates the fields `in_offt` and `in_msglen`\n *                according to the number of bytes read.\n *\n * return         The number of bytes read.\n */\nstatic int ssl_read_application_data(\n    mbedtls_ssl_context *ssl, unsigned char *buf, size_t len)\n{\n    size_t n = (len < ssl->in_msglen) ? len : ssl->in_msglen;\n\n    if (len != 0) {\n        memcpy(buf, ssl->in_offt, n);\n        ssl->in_msglen -= n;\n    }\n\n    /* Zeroising the plaintext buffer to erase unused application data\n       from the memory. */\n    mbedtls_platform_zeroize(ssl->in_offt, n);\n\n    if (ssl->in_msglen == 0) {\n        /* all bytes consumed */\n        ssl->in_offt = NULL;\n        ssl->keep_current_message = 0;\n    } else {\n        /* more data available */\n        ssl->in_offt += n;\n    }\n\n    return (int) n;\n}\n\n/*\n * Receive application data decrypted from the SSL layer\n */\nint mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (ssl == NULL || ssl->conf == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> read\"));\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) {\n            return ret;\n        }\n\n        if (ssl->handshake != NULL &&\n            ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) {\n            if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {\n                return ret;\n            }\n        }\n    }\n#endif\n\n    /*\n     * Check if renegotiation is necessary and/or handshake is\n     * in process. If yes, perform/continue, and fall through\n     * if an unexpected packet is received while the client\n     * is waiting for the ServerHello.\n     *\n     * (There is no equivalent to the last condition on\n     *  the server-side as it is not treated as within\n     *  a handshake while waiting for the ClientHello\n     *  after a renegotiation request.)\n     */\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    ret = ssl_check_ctr_renegotiate(ssl);\n    if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&\n        ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_check_ctr_renegotiate\", ret);\n        return ret;\n    }\n#endif\n\n    if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) {\n        ret = mbedtls_ssl_handshake(ssl);\n        if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&\n            ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_handshake\", ret);\n            return ret;\n        }\n    }\n\n    /* Loop as long as no application data record is available */\n    while (ssl->in_offt == NULL) {\n        /* Start timer if not already running */\n        if (ssl->f_get_timer != NULL &&\n            ssl->f_get_timer(ssl->p_timer) == -1) {\n            mbedtls_ssl_set_timer(ssl, ssl->conf->read_timeout);\n        }\n\n        if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {\n            if (ret == MBEDTLS_ERR_SSL_CONN_EOF) {\n                return 0;\n            }\n\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_read_record\", ret);\n            return ret;\n        }\n\n        if (ssl->in_msglen  == 0 &&\n            ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA) {\n            /*\n             * OpenSSL sends empty messages to randomize the IV\n             */\n            if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {\n                if (ret == MBEDTLS_ERR_SSL_CONN_EOF) {\n                    return 0;\n                }\n\n                MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_read_record\", ret);\n                return ret;\n            }\n        }\n\n        if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) {\n            ret = ssl_handle_hs_message_post_handshake(ssl);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"ssl_handle_hs_message_post_handshake\",\n                                      ret);\n                return ret;\n            }\n\n            /* At this point, we don't know whether the renegotiation triggered\n             * by the post-handshake message has been completed or not. The cases\n             * to consider are the following:\n             * 1) The renegotiation is complete. In this case, no new record\n             *    has been read yet.\n             * 2) The renegotiation is incomplete because the client received\n             *    an application data record while awaiting the ServerHello.\n             * 3) The renegotiation is incomplete because the client received\n             *    a non-handshake, non-application data message while awaiting\n             *    the ServerHello.\n             *\n             * In each of these cases, looping will be the proper action:\n             * - For 1), the next iteration will read a new record and check\n             *   if it's application data.\n             * - For 2), the loop condition isn't satisfied as application data\n             *   is present, hence continue is the same as break\n             * - For 3), the loop condition is satisfied and read_record\n             *   will re-deliver the message that was held back by the client\n             *   when expecting the ServerHello.\n             */\n\n            continue;\n        }\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n        else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) {\n            if (ssl->conf->renego_max_records >= 0) {\n                if (++ssl->renego_records_seen > ssl->conf->renego_max_records) {\n                    MBEDTLS_SSL_DEBUG_MSG(1, (\"renegotiation requested, \"\n                                              \"but not honored by client\"));\n                    return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n                }\n            }\n        }\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n\n        /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */\n        if (ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"ignoring non-fatal non-closure alert\"));\n            return MBEDTLS_ERR_SSL_WANT_READ;\n        }\n\n        if (ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad application data message\"));\n            return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n        }\n\n        ssl->in_offt = ssl->in_msg;\n\n        /* We're going to return something now, cancel timer,\n         * except if handshake (renegotiation) is in progress */\n        if (mbedtls_ssl_is_handshake_over(ssl) == 1) {\n            mbedtls_ssl_set_timer(ssl, 0);\n        }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n        /* If we requested renego but received AppData, resend HelloRequest.\n         * Do it now, after setting in_offt, to avoid taking this branch\n         * again if ssl_write_hello_request() returns WANT_WRITE */\n#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)\n        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&\n            ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) {\n            if ((ret = mbedtls_ssl_resend_hello_request(ssl)) != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_resend_hello_request\",\n                                      ret);\n                return ret;\n            }\n        }\n#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n    }\n\n    ret = ssl_read_application_data(ssl, buf, len);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= read\"));\n\n    return ret;\n}\n\n#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA)\nint mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl,\n                                unsigned char *buf, size_t len)\n{\n    if (ssl == NULL || (ssl->conf == NULL)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    /*\n     * The server may receive early data only while waiting for the End of\n     * Early Data handshake message.\n     */\n    if ((ssl->state != MBEDTLS_SSL_END_OF_EARLY_DATA) ||\n        (ssl->in_offt == NULL)) {\n        return MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA;\n    }\n\n    return ssl_read_application_data(ssl, buf, len);\n}\n#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA */\n\n/*\n * Send application data to be encrypted by the SSL layer, taking care of max\n * fragment length and buffer size.\n *\n * According to RFC 5246 Section 6.2.1:\n *\n *      Zero-length fragments of Application data MAY be sent as they are\n *      potentially useful as a traffic analysis countermeasure.\n *\n * Therefore, it is possible that the input message length is 0 and the\n * corresponding return code is 0 on success.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_real(mbedtls_ssl_context *ssl,\n                          const unsigned char *buf, size_t len)\n{\n    int ret = mbedtls_ssl_get_max_out_record_payload(ssl);\n    const size_t max_len = (size_t) ret;\n\n    if (ret < 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_get_max_out_record_payload\", ret);\n        return ret;\n    }\n\n    if (len > max_len) {\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"fragment larger than the (negotiated) \"\n                                      \"maximum fragment length: %\" MBEDTLS_PRINTF_SIZET\n                                      \" > %\" MBEDTLS_PRINTF_SIZET,\n                                      len, max_len));\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        } else\n#endif\n        len = max_len;\n    }\n\n    if (ssl->out_left != 0) {\n        /*\n         * The user has previously tried to send the data and\n         * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially\n         * written. In this case, we expect the high-level write function\n         * (e.g. mbedtls_ssl_write()) to be called with the same parameters\n         */\n        if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_flush_output\", ret);\n            return ret;\n        }\n    } else {\n        /*\n         * The user is trying to send a message the first time, so we need to\n         * copy the data into the internal buffers and setup the data structure\n         * to keep track of partial writes\n         */\n        ssl->out_msglen  = len;\n        ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA;\n        if (len > 0) {\n            memcpy(ssl->out_msg, buf, len);\n        }\n\n        if ((ret = mbedtls_ssl_write_record(ssl, SSL_FORCE_FLUSH)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_write_record\", ret);\n            return ret;\n        }\n    }\n\n    return (int) len;\n}\n\n/*\n * Write application data (public-facing wrapper)\n */\nint mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write\"));\n\n    if (ssl == NULL || ssl->conf == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    if ((ret = ssl_check_ctr_renegotiate(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_check_ctr_renegotiate\", ret);\n        return ret;\n    }\n#endif\n\n    if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) {\n        if ((ret = mbedtls_ssl_handshake(ssl)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_handshake\", ret);\n            return ret;\n        }\n    }\n\n    ret = ssl_write_real(ssl, buf, len);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write\"));\n\n    return ret;\n}\n\n#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)\nint mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl,\n                                 const unsigned char *buf, size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const struct mbedtls_ssl_config *conf;\n    uint32_t remaining;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write early_data\"));\n\n    if (ssl == NULL || (conf = ssl->conf) == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if (conf->endpoint != MBEDTLS_SSL_IS_CLIENT) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if ((!mbedtls_ssl_conf_is_tls13_enabled(conf)) ||\n        (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||\n        (conf->early_data_enabled != MBEDTLS_SSL_EARLY_DATA_ENABLED)) {\n        return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;\n    }\n\n    if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) {\n        return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;\n    }\n\n    /*\n     * If we are at the beginning of the handshake, the early data state being\n     * equal to MBEDTLS_SSL_EARLY_DATA_STATE_IDLE or\n     * MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT advance the handshake just\n     * enough to be able to send early data if possible. That way, we can\n     * guarantee that when starting the handshake with this function we will\n     * send at least one record of early data. Note that when the state is\n     * MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT and not yet\n     * MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE, we cannot send early data\n     * as the early data outbound transform has not been set as we may have to\n     * first send a dummy CCS in clear.\n     */\n    if ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) ||\n        (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) {\n        while ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) ||\n               (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) {\n            ret = mbedtls_ssl_handshake_step(ssl);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_handshake_step\", ret);\n                return ret;\n            }\n\n            ret = mbedtls_ssl_flush_output(ssl);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_flush_output\", ret);\n                return ret;\n            }\n        }\n        remaining = ssl->session_negotiate->max_early_data_size;\n    } else {\n        /*\n         * If we are past the point where we can send early data or we have\n         * already reached the maximum early data size, return immediately.\n         * Otherwise, progress the handshake as much as possible to not delay\n         * it too much. If we reach a point where we can still send early data,\n         * then we will send some.\n         */\n        if ((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) &&\n            (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED)) {\n            return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;\n        }\n\n        remaining = ssl->session_negotiate->max_early_data_size -\n                    ssl->total_early_data_size;\n\n        if (remaining == 0) {\n            return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;\n        }\n\n        ret = mbedtls_ssl_handshake(ssl);\n        if ((ret != 0) && (ret != MBEDTLS_ERR_SSL_WANT_READ)) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_handshake\", ret);\n            return ret;\n        }\n    }\n\n    if (((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) &&\n         (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED))\n        || (remaining == 0)) {\n        return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;\n    }\n\n    if (len > remaining) {\n        len = remaining;\n    }\n\n    ret = ssl_write_real(ssl, buf, len);\n    if (ret >= 0) {\n        ssl->total_early_data_size += ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write early_data, ret=%d\", ret));\n\n    return ret;\n}\n#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */\n\n/*\n * Notify the peer that the connection is being closed\n */\nint mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (ssl == NULL || ssl->conf == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write close notify\"));\n\n    if (mbedtls_ssl_is_handshake_over(ssl) == 1) {\n        if ((ret = mbedtls_ssl_send_alert_message(ssl,\n                                                  MBEDTLS_SSL_ALERT_LEVEL_WARNING,\n                                                  MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_send_alert_message\", ret);\n            return ret;\n        }\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write close notify\"));\n\n    return 0;\n}\n\nvoid mbedtls_ssl_transform_free(mbedtls_ssl_transform *transform)\n{\n    if (transform == NULL) {\n        return;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_destroy_key(transform->psa_key_enc);\n    psa_destroy_key(transform->psa_key_dec);\n#else\n    mbedtls_cipher_free(&transform->cipher_ctx_enc);\n    mbedtls_cipher_free(&transform->cipher_ctx_dec);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_destroy_key(transform->psa_mac_enc);\n    psa_destroy_key(transform->psa_mac_dec);\n#else\n    mbedtls_md_free(&transform->md_ctx_enc);\n    mbedtls_md_free(&transform->md_ctx_dec);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#endif\n\n    mbedtls_platform_zeroize(transform, sizeof(mbedtls_ssl_transform));\n}\n\nvoid mbedtls_ssl_set_inbound_transform(mbedtls_ssl_context *ssl,\n                                       mbedtls_ssl_transform *transform)\n{\n    ssl->transform_in = transform;\n    memset(ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN);\n}\n\nvoid mbedtls_ssl_set_outbound_transform(mbedtls_ssl_context *ssl,\n                                        mbedtls_ssl_transform *transform)\n{\n    ssl->transform_out = transform;\n    memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr));\n}\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n\nvoid mbedtls_ssl_buffering_free(mbedtls_ssl_context *ssl)\n{\n    unsigned offset;\n    mbedtls_ssl_handshake_params * const hs = ssl->handshake;\n\n    if (hs == NULL) {\n        return;\n    }\n\n    ssl_free_buffered_record(ssl);\n\n    for (offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++) {\n        ssl_buffering_free_slot(ssl, offset);\n    }\n}\n\nstatic void ssl_buffering_free_slot(mbedtls_ssl_context *ssl,\n                                    uint8_t slot)\n{\n    mbedtls_ssl_handshake_params * const hs = ssl->handshake;\n    mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot];\n\n    if (slot >= MBEDTLS_SSL_MAX_BUFFERED_HS) {\n        return;\n    }\n\n    if (hs_buf->is_valid == 1) {\n        hs->buffering.total_bytes_buffered -= hs_buf->data_len;\n        mbedtls_zeroize_and_free(hs_buf->data, hs_buf->data_len);\n        memset(hs_buf, 0, sizeof(mbedtls_ssl_hs_buffer));\n    }\n}\n\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n/*\n * Convert version numbers to/from wire format\n * and, for DTLS, to/from TLS equivalent.\n *\n * For TLS this is the identity.\n * For DTLS, map as follows, then use 1's complement (v -> ~v):\n * 1.x <-> 3.x+1    for x != 0 (DTLS 1.2 based on TLS 1.2)\n *                  DTLS 1.0 is stored as TLS 1.1 internally\n */\nvoid mbedtls_ssl_write_version(unsigned char version[2], int transport,\n                               mbedtls_ssl_protocol_version tls_version)\n{\n    uint16_t tls_version_formatted;\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        tls_version_formatted =\n            ~(tls_version - (tls_version == 0x0302 ? 0x0202 : 0x0201));\n    } else\n#else\n    ((void) transport);\n#endif\n    {\n        tls_version_formatted = (uint16_t) tls_version;\n    }\n    MBEDTLS_PUT_UINT16_BE(tls_version_formatted, version, 0);\n}\n\nuint16_t mbedtls_ssl_read_version(const unsigned char version[2],\n                                  int transport)\n{\n    uint16_t tls_version = MBEDTLS_GET_UINT16_BE(version, 0);\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        tls_version =\n            ~(tls_version - (tls_version == 0xfeff ? 0x0202 : 0x0201));\n    }\n#else\n    ((void) transport);\n#endif\n    return tls_version;\n}\n\n/*\n * Send pending fatal alert.\n * 0,   No alert message.\n * !0,  if mbedtls_ssl_send_alert_message() returned in error, the error code it\n *      returned, ssl->alert_reason otherwise.\n */\nint mbedtls_ssl_handle_pending_alert(mbedtls_ssl_context *ssl)\n{\n    int ret;\n\n    /* No pending alert, return success*/\n    if (ssl->send_alert == 0) {\n        return 0;\n    }\n\n    ret = mbedtls_ssl_send_alert_message(ssl,\n                                         MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                         ssl->alert_type);\n\n    /* If mbedtls_ssl_send_alert_message() returned with MBEDTLS_ERR_SSL_WANT_WRITE,\n     * do not clear the alert to be able to send it later.\n     */\n    if (ret != MBEDTLS_ERR_SSL_WANT_WRITE) {\n        ssl->send_alert = 0;\n    }\n\n    if (ret != 0) {\n        return ret;\n    }\n\n    return ssl->alert_reason;\n}\n\n/*\n * Set pending fatal alert flag.\n */\nvoid mbedtls_ssl_pend_fatal_alert(mbedtls_ssl_context *ssl,\n                                  unsigned char alert_type,\n                                  int alert_reason)\n{\n    ssl->send_alert = 1;\n    ssl->alert_type = alert_type;\n    ssl->alert_reason = alert_reason;\n}\n\n#endif /* MBEDTLS_SSL_TLS_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_ticket.c",
    "content": "/*\n *  TLS server tickets callbacks implementation\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_TICKET_C)\n\n#include \"mbedtls/platform.h\"\n\n#include \"ssl_misc.h\"\n#include \"mbedtls/ssl_ticket.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n/* Define a local translating function to save code size by not using too many\n * arguments in each translating place. */\nstatic int local_err_translation(psa_status_t status)\n{\n    return psa_status_to_mbedtls(status, psa_to_ssl_errors,\n                                 ARRAY_LENGTH(psa_to_ssl_errors),\n                                 psa_generic_status_to_mbedtls);\n}\n#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)\n#endif\n\n/*\n * Initialize context\n */\nvoid mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_ssl_ticket_context));\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_init(&ctx->mutex);\n#endif\n}\n\n#define MAX_KEY_BYTES           MBEDTLS_SSL_TICKET_MAX_KEY_BYTES\n\n#define TICKET_KEY_NAME_BYTES   MBEDTLS_SSL_TICKET_KEY_NAME_BYTES\n#define TICKET_IV_BYTES         12\n#define TICKET_CRYPT_LEN_BYTES   2\n#define TICKET_AUTH_TAG_BYTES   16\n\n#define TICKET_MIN_LEN (TICKET_KEY_NAME_BYTES  +        \\\n                        TICKET_IV_BYTES        +        \\\n                        TICKET_CRYPT_LEN_BYTES +        \\\n                        TICKET_AUTH_TAG_BYTES)\n#define TICKET_ADD_DATA_LEN (TICKET_KEY_NAME_BYTES  +        \\\n                             TICKET_IV_BYTES        +        \\\n                             TICKET_CRYPT_LEN_BYTES)\n\n/*\n * Generate/update a key\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_ticket_gen_key(mbedtls_ssl_ticket_context *ctx,\n                              unsigned char index)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char buf[MAX_KEY_BYTES] = { 0 };\n    mbedtls_ssl_ticket_key *key = ctx->keys + index;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n#endif\n\n#if defined(MBEDTLS_HAVE_TIME)\n    key->generation_time = mbedtls_time(NULL);\n#endif\n    /* The lifetime of a key is the configured lifetime of the tickets when\n     * the key is created.\n     */\n    key->lifetime = ctx->ticket_lifetime;\n\n    if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) {\n        return ret;\n    }\n\n    if ((ret = ctx->f_rng(ctx->p_rng, buf, sizeof(buf))) != 0) {\n        return ret;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_set_key_usage_flags(&attributes,\n                            PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);\n    psa_set_key_algorithm(&attributes, key->alg);\n    psa_set_key_type(&attributes, key->key_type);\n    psa_set_key_bits(&attributes, key->key_bits);\n\n    ret = PSA_TO_MBEDTLS_ERR(\n        psa_import_key(&attributes, buf,\n                       PSA_BITS_TO_BYTES(key->key_bits),\n                       &key->key));\n#else\n    /* With GCM and CCM, same context can encrypt & decrypt */\n    ret = mbedtls_cipher_setkey(&key->ctx, buf,\n                                mbedtls_cipher_get_key_bitlen(&key->ctx),\n                                MBEDTLS_ENCRYPT);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n\n    return ret;\n}\n\n/*\n * Rotate/generate keys if necessary\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_ticket_update_keys(mbedtls_ssl_ticket_context *ctx)\n{\n#if !defined(MBEDTLS_HAVE_TIME)\n    ((void) ctx);\n#else\n    mbedtls_ssl_ticket_key * const key = ctx->keys + ctx->active;\n    if (key->lifetime != 0) {\n        mbedtls_time_t current_time = mbedtls_time(NULL);\n        mbedtls_time_t key_time = key->generation_time;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n#endif\n\n        if (current_time >= key_time &&\n            (uint64_t) (current_time - key_time) < key->lifetime) {\n            return 0;\n        }\n\n        ctx->active = 1 - ctx->active;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        if ((status = psa_destroy_key(ctx->keys[ctx->active].key)) != PSA_SUCCESS) {\n            return PSA_TO_MBEDTLS_ERR(status);\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        return ssl_ticket_gen_key(ctx, ctx->active);\n    } else\n#endif /* MBEDTLS_HAVE_TIME */\n    return 0;\n}\n\n/*\n * Rotate active session ticket encryption key\n */\nint mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx,\n                              const unsigned char *name, size_t nlength,\n                              const unsigned char *k, size_t klength,\n                              uint32_t lifetime)\n{\n    const unsigned char idx = 1 - ctx->active;\n    mbedtls_ssl_ticket_key * const key = ctx->keys + idx;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    const size_t bitlen = key->key_bits;\n#else\n    const int bitlen = mbedtls_cipher_get_key_bitlen(&key->ctx);\n#endif\n\n    if (nlength < TICKET_KEY_NAME_BYTES || klength * 8 < (size_t) bitlen) {\n        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if ((status = psa_destroy_key(key->key)) != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        return ret;\n    }\n\n    psa_set_key_usage_flags(&attributes,\n                            PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);\n    psa_set_key_algorithm(&attributes, key->alg);\n    psa_set_key_type(&attributes, key->key_type);\n    psa_set_key_bits(&attributes, key->key_bits);\n\n    if ((status = psa_import_key(&attributes, k,\n                                 PSA_BITS_TO_BYTES(key->key_bits),\n                                 &key->key)) != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        return ret;\n    }\n#else\n    ret = mbedtls_cipher_setkey(&key->ctx, k, bitlen, MBEDTLS_ENCRYPT);\n    if (ret != 0) {\n        return ret;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    ctx->active = idx;\n    ctx->ticket_lifetime = lifetime;\n    memcpy(key->name, name, TICKET_KEY_NAME_BYTES);\n#if defined(MBEDTLS_HAVE_TIME)\n    key->generation_time = mbedtls_time(NULL);\n#endif\n    key->lifetime = lifetime;\n\n    return 0;\n}\n\n/*\n * Setup context for actual use\n */\nint mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx,\n                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,\n                             mbedtls_cipher_type_t cipher,\n                             uint32_t lifetime)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t key_bits;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_algorithm_t alg;\n    psa_key_type_t key_type;\n#else\n    const mbedtls_cipher_info_t *cipher_info;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (mbedtls_ssl_cipher_to_psa(cipher, TICKET_AUTH_TAG_BYTES,\n                                  &alg, &key_type, &key_bits) != PSA_SUCCESS) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if (PSA_ALG_IS_AEAD(alg) == 0) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n#else\n    cipher_info = mbedtls_cipher_info_from_type(cipher);\n\n    if (mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_GCM &&\n        mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CCM &&\n        mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CHACHAPOLY) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    key_bits = mbedtls_cipher_info_get_key_bitlen(cipher_info);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    if (key_bits > 8 * MAX_KEY_BYTES) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    ctx->f_rng = f_rng;\n    ctx->p_rng = p_rng;\n\n    ctx->ticket_lifetime = lifetime;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    ctx->keys[0].alg = alg;\n    ctx->keys[0].key_type = key_type;\n    ctx->keys[0].key_bits = key_bits;\n\n    ctx->keys[1].alg = alg;\n    ctx->keys[1].key_type = key_type;\n    ctx->keys[1].key_bits = key_bits;\n#else\n    if ((ret = mbedtls_cipher_setup(&ctx->keys[0].ctx, cipher_info)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_cipher_setup(&ctx->keys[1].ctx, cipher_info)) != 0) {\n        return ret;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    if ((ret = ssl_ticket_gen_key(ctx, 0)) != 0 ||\n        (ret = ssl_ticket_gen_key(ctx, 1)) != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\n/*\n * Create session ticket, with the following structure:\n *\n *    struct {\n *        opaque key_name[4];\n *        opaque iv[12];\n *        opaque encrypted_state<0..2^16-1>;\n *        opaque tag[16];\n *    } ticket;\n *\n * The key_name, iv, and length of encrypted_state are the additional\n * authenticated data.\n */\n\nint mbedtls_ssl_ticket_write(void *p_ticket,\n                             const mbedtls_ssl_session *session,\n                             unsigned char *start,\n                             const unsigned char *end,\n                             size_t *tlen,\n                             uint32_t *ticket_lifetime)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_ticket_context *ctx = p_ticket;\n    mbedtls_ssl_ticket_key *key;\n    unsigned char *key_name = start;\n    unsigned char *iv = start + TICKET_KEY_NAME_BYTES;\n    unsigned char *state_len_bytes = iv + TICKET_IV_BYTES;\n    unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES;\n    size_t clear_len, ciph_len;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n#endif\n\n    *tlen = 0;\n\n    if (ctx == NULL || ctx->f_rng == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag,\n     * in addition to session itself, that will be checked when writing it. */\n    MBEDTLS_SSL_CHK_BUF_PTR(start, end, TICKET_MIN_LEN);\n\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {\n        return ret;\n    }\n#endif\n\n    if ((ret = ssl_ticket_update_keys(ctx)) != 0) {\n        goto cleanup;\n    }\n\n    key = &ctx->keys[ctx->active];\n\n    *ticket_lifetime = key->lifetime;\n\n    memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES);\n\n    if ((ret = ctx->f_rng(ctx->p_rng, iv, TICKET_IV_BYTES)) != 0) {\n        goto cleanup;\n    }\n\n    /* Dump session state */\n    if ((ret = mbedtls_ssl_session_save(session,\n                                        state, (size_t) (end - state),\n                                        &clear_len)) != 0 ||\n        (unsigned long) clear_len > 65535) {\n        goto cleanup;\n    }\n    MBEDTLS_PUT_UINT16_BE(clear_len, state_len_bytes, 0);\n\n    /* Encrypt and authenticate */\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if ((status = psa_aead_encrypt(key->key, key->alg, iv, TICKET_IV_BYTES,\n                                   key_name, TICKET_ADD_DATA_LEN,\n                                   state, clear_len,\n                                   state, end - state,\n                                   &ciph_len)) != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        goto cleanup;\n    }\n#else\n    if ((ret = mbedtls_cipher_auth_encrypt_ext(&key->ctx,\n                                               iv, TICKET_IV_BYTES,\n                                               /* Additional data: key name, IV and length */\n                                               key_name, TICKET_ADD_DATA_LEN,\n                                               state, clear_len,\n                                               state, (size_t) (end - state), &ciph_len,\n                                               TICKET_AUTH_TAG_BYTES)) != 0) {\n        goto cleanup;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    if (ciph_len != clear_len + TICKET_AUTH_TAG_BYTES) {\n        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        goto cleanup;\n    }\n\n    *tlen = TICKET_MIN_LEN + ciph_len - TICKET_AUTH_TAG_BYTES;\n\ncleanup:\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {\n        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n#endif\n\n    return ret;\n}\n\n/*\n * Select key based on name\n */\nstatic mbedtls_ssl_ticket_key *ssl_ticket_select_key(\n    mbedtls_ssl_ticket_context *ctx,\n    const unsigned char name[4])\n{\n    unsigned char i;\n\n    for (i = 0; i < sizeof(ctx->keys) / sizeof(*ctx->keys); i++) {\n        if (memcmp(name, ctx->keys[i].name, 4) == 0) {\n            return &ctx->keys[i];\n        }\n    }\n\n    return NULL;\n}\n\n/*\n * Load session ticket (see mbedtls_ssl_ticket_write for structure)\n */\nint mbedtls_ssl_ticket_parse(void *p_ticket,\n                             mbedtls_ssl_session *session,\n                             unsigned char *buf,\n                             size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_ticket_context *ctx = p_ticket;\n    mbedtls_ssl_ticket_key *key;\n    unsigned char *key_name = buf;\n    unsigned char *iv = buf + TICKET_KEY_NAME_BYTES;\n    unsigned char *enc_len_p = iv + TICKET_IV_BYTES;\n    unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES;\n    size_t enc_len, clear_len;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n#endif\n\n    if (ctx == NULL || ctx->f_rng == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if (len < TICKET_MIN_LEN) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {\n        return ret;\n    }\n#endif\n\n    if ((ret = ssl_ticket_update_keys(ctx)) != 0) {\n        goto cleanup;\n    }\n\n    enc_len = MBEDTLS_GET_UINT16_BE(enc_len_p, 0);\n\n    if (len != TICKET_MIN_LEN + enc_len) {\n        ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        goto cleanup;\n    }\n\n    /* Select key */\n    if ((key = ssl_ticket_select_key(ctx, key_name)) == NULL) {\n        /* We can't know for sure but this is a likely option unless we're\n         * under attack - this is only informative anyway */\n        ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;\n        goto cleanup;\n    }\n\n    /* Decrypt and authenticate */\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if ((status = psa_aead_decrypt(key->key, key->alg, iv, TICKET_IV_BYTES,\n                                   key_name, TICKET_ADD_DATA_LEN,\n                                   ticket, enc_len + TICKET_AUTH_TAG_BYTES,\n                                   ticket, enc_len, &clear_len)) != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        goto cleanup;\n    }\n#else\n    if ((ret = mbedtls_cipher_auth_decrypt_ext(&key->ctx,\n                                               iv, TICKET_IV_BYTES,\n                                               /* Additional data: key name, IV and length */\n                                               key_name, TICKET_ADD_DATA_LEN,\n                                               ticket, enc_len + TICKET_AUTH_TAG_BYTES,\n                                               ticket, enc_len, &clear_len,\n                                               TICKET_AUTH_TAG_BYTES)) != 0) {\n        if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) {\n            ret = MBEDTLS_ERR_SSL_INVALID_MAC;\n        }\n\n        goto cleanup;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    if (clear_len != enc_len) {\n        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        goto cleanup;\n    }\n\n    /* Actually load session */\n    if ((ret = mbedtls_ssl_session_load(session, ticket, clear_len)) != 0) {\n        goto cleanup;\n    }\n\n#if defined(MBEDTLS_HAVE_TIME)\n    mbedtls_ms_time_t ticket_creation_time, ticket_age;\n    mbedtls_ms_time_t ticket_lifetime =\n        (mbedtls_ms_time_t) key->lifetime * 1000;\n\n    ret = mbedtls_ssl_session_get_ticket_creation_time(session,\n                                                       &ticket_creation_time);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    ticket_age = mbedtls_ms_time() - ticket_creation_time;\n    if (ticket_age < 0 || ticket_age > ticket_lifetime) {\n        ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;\n        goto cleanup;\n    }\n#endif\n\ncleanup:\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {\n        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n#endif\n\n    return ret;\n}\n\n/*\n * Free context\n */\nvoid mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_destroy_key(ctx->keys[0].key);\n    psa_destroy_key(ctx->keys[1].key);\n#else\n    mbedtls_cipher_free(&ctx->keys[0].ctx);\n    mbedtls_cipher_free(&ctx->keys[1].ctx);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_THREADING_C)\n    mbedtls_mutex_free(&ctx->mutex);\n#endif\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_ticket_context));\n}\n\n#endif /* MBEDTLS_SSL_TICKET_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_tls.c",
    "content": "/*\n *  TLS shared functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  http://www.ietf.org/rfc/rfc2246.txt\n *  http://www.ietf.org/rfc/rfc4346.txt\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_TLS_C)\n\n#include \"mbedtls/platform.h\"\n\n#include \"mbedtls/ssl.h\"\n#include \"ssl_client.h\"\n#include \"ssl_debug_helpers.h\"\n#include \"ssl_misc.h\"\n#include \"ssl_tls13_keys.h\"\n\n#include \"debug_internal.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/version.h\"\n#include \"mbedtls/constant_time.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"mbedtls/psa_util.h\"\n#include \"md_psa.h\"\n#include \"psa_util_internal.h\"\n#include \"psa/crypto.h\"\n#endif\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n#include \"mbedtls/oid.h\"\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n/* Define local translating functions to save code size by not using too many\n * arguments in each translating place. */\nstatic int local_err_translation(psa_status_t status)\n{\n    return psa_status_to_mbedtls(status, psa_to_ssl_errors,\n                                 ARRAY_LENGTH(psa_to_ssl_errors),\n                                 psa_generic_status_to_mbedtls);\n}\n#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)\n#endif\n\n#if defined(MBEDTLS_TEST_HOOKS)\nstatic mbedtls_ssl_chk_buf_ptr_args chk_buf_ptr_fail_args;\n\nvoid mbedtls_ssl_set_chk_buf_ptr_fail_args(\n    const uint8_t *cur, const uint8_t *end, size_t need)\n{\n    chk_buf_ptr_fail_args.cur = cur;\n    chk_buf_ptr_fail_args.end = end;\n    chk_buf_ptr_fail_args.need = need;\n}\n\nvoid mbedtls_ssl_reset_chk_buf_ptr_fail_args(void)\n{\n    memset(&chk_buf_ptr_fail_args, 0, sizeof(chk_buf_ptr_fail_args));\n}\n\nint mbedtls_ssl_cmp_chk_buf_ptr_fail_args(mbedtls_ssl_chk_buf_ptr_args *args)\n{\n    return (chk_buf_ptr_fail_args.cur  != args->cur) ||\n           (chk_buf_ptr_fail_args.end  != args->end) ||\n           (chk_buf_ptr_fail_args.need != args->need);\n}\n#endif /* MBEDTLS_TEST_HOOKS */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n/* Top-level Connection ID API */\n\nint mbedtls_ssl_conf_cid(mbedtls_ssl_config *conf,\n                         size_t len,\n                         int ignore_other_cid)\n{\n    if (len > MBEDTLS_SSL_CID_IN_LEN_MAX) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if (ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_FAIL &&\n        ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_IGNORE) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    conf->ignore_unexpected_cid = ignore_other_cid;\n    conf->cid_len = len;\n    return 0;\n}\n\nint mbedtls_ssl_set_cid(mbedtls_ssl_context *ssl,\n                        int enable,\n                        unsigned char const *own_cid,\n                        size_t own_cid_len)\n{\n    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    ssl->negotiate_cid = enable;\n    if (enable == MBEDTLS_SSL_CID_DISABLED) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"Disable use of CID extension.\"));\n        return 0;\n    }\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"Enable use of CID extension.\"));\n    MBEDTLS_SSL_DEBUG_BUF(3, \"Own CID\", own_cid, own_cid_len);\n\n    if (own_cid_len != ssl->conf->cid_len) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"CID length %u does not match CID length %u in config\",\n                                  (unsigned) own_cid_len,\n                                  (unsigned) ssl->conf->cid_len));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    memcpy(ssl->own_cid, own_cid, own_cid_len);\n    /* Truncation is not an issue here because\n     * MBEDTLS_SSL_CID_IN_LEN_MAX at most 255. */\n    ssl->own_cid_len = (uint8_t) own_cid_len;\n\n    return 0;\n}\n\nint mbedtls_ssl_get_own_cid(mbedtls_ssl_context *ssl,\n                            int *enabled,\n                            unsigned char own_cid[MBEDTLS_SSL_CID_IN_LEN_MAX],\n                            size_t *own_cid_len)\n{\n    *enabled = MBEDTLS_SSL_CID_DISABLED;\n\n    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    /* We report MBEDTLS_SSL_CID_DISABLED in case the CID length is\n     * zero as this is indistinguishable from not requesting to use\n     * the CID extension. */\n    if (ssl->own_cid_len == 0 || ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) {\n        return 0;\n    }\n\n    if (own_cid_len != NULL) {\n        *own_cid_len = ssl->own_cid_len;\n        if (own_cid != NULL) {\n            memcpy(own_cid, ssl->own_cid, ssl->own_cid_len);\n        }\n    }\n\n    *enabled = MBEDTLS_SSL_CID_ENABLED;\n\n    return 0;\n}\n\nint mbedtls_ssl_get_peer_cid(mbedtls_ssl_context *ssl,\n                             int *enabled,\n                             unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX],\n                             size_t *peer_cid_len)\n{\n    *enabled = MBEDTLS_SSL_CID_DISABLED;\n\n    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||\n        mbedtls_ssl_is_handshake_over(ssl) == 0) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    /* We report MBEDTLS_SSL_CID_DISABLED in case the CID extensions\n     * were used, but client and server requested the empty CID.\n     * This is indistinguishable from not using the CID extension\n     * in the first place. */\n    if (ssl->transform_in->in_cid_len  == 0 &&\n        ssl->transform_in->out_cid_len == 0) {\n        return 0;\n    }\n\n    if (peer_cid_len != NULL) {\n        *peer_cid_len = ssl->transform_in->out_cid_len;\n        if (peer_cid != NULL) {\n            memcpy(peer_cid, ssl->transform_in->out_cid,\n                   ssl->transform_in->out_cid_len);\n        }\n    }\n\n    *enabled = MBEDTLS_SSL_CID_ENABLED;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n/*\n * Convert max_fragment_length codes to length.\n * RFC 6066 says:\n *    enum{\n *        2^9(1), 2^10(2), 2^11(3), 2^12(4), (255)\n *    } MaxFragmentLength;\n * and we add 0 -> extension unused\n */\nstatic unsigned int ssl_mfl_code_to_length(int mfl)\n{\n    switch (mfl) {\n        case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:\n            return MBEDTLS_TLS_EXT_ADV_CONTENT_LEN;\n        case MBEDTLS_SSL_MAX_FRAG_LEN_512:\n            return 512;\n        case MBEDTLS_SSL_MAX_FRAG_LEN_1024:\n            return 1024;\n        case MBEDTLS_SSL_MAX_FRAG_LEN_2048:\n            return 2048;\n        case MBEDTLS_SSL_MAX_FRAG_LEN_4096:\n            return 4096;\n        default:\n            return MBEDTLS_TLS_EXT_ADV_CONTENT_LEN;\n    }\n}\n#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */\n\nint mbedtls_ssl_session_copy(mbedtls_ssl_session *dst,\n                             const mbedtls_ssl_session *src)\n{\n    mbedtls_ssl_session_free(dst);\n    memcpy(dst, src, sizeof(mbedtls_ssl_session));\n#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)\n    dst->ticket = NULL;\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \\\n    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    dst->hostname = NULL;\n#endif\n#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */\n\n#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN) && \\\n    defined(MBEDTLS_SSL_EARLY_DATA)\n    dst->ticket_alpn = NULL;\n#endif\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    if (src->peer_cert != NULL) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n        dst->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));\n        if (dst->peer_cert == NULL) {\n            return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        }\n\n        mbedtls_x509_crt_init(dst->peer_cert);\n\n        if ((ret = mbedtls_x509_crt_parse_der(dst->peer_cert, src->peer_cert->raw.p,\n                                              src->peer_cert->raw.len)) != 0) {\n            mbedtls_free(dst->peer_cert);\n            dst->peer_cert = NULL;\n            return ret;\n        }\n    }\n#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n    if (src->peer_cert_digest != NULL) {\n        dst->peer_cert_digest =\n            mbedtls_calloc(1, src->peer_cert_digest_len);\n        if (dst->peer_cert_digest == NULL) {\n            return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        }\n\n        memcpy(dst->peer_cert_digest, src->peer_cert_digest,\n               src->peer_cert_digest_len);\n        dst->peer_cert_digest_type = src->peer_cert_digest_type;\n        dst->peer_cert_digest_len = src->peer_cert_digest_len;\n    }\n#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN) && \\\n    defined(MBEDTLS_SSL_EARLY_DATA)\n    {\n        int ret = mbedtls_ssl_session_set_ticket_alpn(dst, src->ticket_alpn);\n        if (ret != 0) {\n            return ret;\n        }\n    }\n#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_ALPN && MBEDTLS_SSL_EARLY_DATA */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)\n    if (src->ticket != NULL) {\n        dst->ticket = mbedtls_calloc(1, src->ticket_len);\n        if (dst->ticket == NULL) {\n            return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        }\n\n        memcpy(dst->ticket, src->ticket, src->ticket_len);\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \\\n    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    if (src->endpoint == MBEDTLS_SSL_IS_CLIENT) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n        ret = mbedtls_ssl_session_set_hostname(dst, src->hostname);\n        if (ret != 0) {\n            return ret;\n        }\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 &&\n          MBEDTLS_SSL_SERVER_NAME_INDICATION */\n#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int resize_buffer(unsigned char **buffer, size_t len_new, size_t *len_old)\n{\n    unsigned char *resized_buffer = mbedtls_calloc(1, len_new);\n    if (resized_buffer == NULL) {\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n    /* We want to copy len_new bytes when downsizing the buffer, and\n     * len_old bytes when upsizing, so we choose the smaller of two sizes,\n     * to fit one buffer into another. Size checks, ensuring that no data is\n     * lost, are done outside of this function. */\n    memcpy(resized_buffer, *buffer,\n           (len_new < *len_old) ? len_new : *len_old);\n    mbedtls_zeroize_and_free(*buffer, *len_old);\n\n    *buffer = resized_buffer;\n    *len_old = len_new;\n\n    return 0;\n}\n\nstatic void handle_buffer_resizing(mbedtls_ssl_context *ssl, int downsizing,\n                                   size_t in_buf_new_len,\n                                   size_t out_buf_new_len)\n{\n    int modified = 0;\n    size_t written_in = 0, iv_offset_in = 0, len_offset_in = 0, hdr_in = 0;\n    size_t written_out = 0, iv_offset_out = 0, len_offset_out = 0;\n    if (ssl->in_buf != NULL) {\n        written_in = ssl->in_msg - ssl->in_buf;\n        iv_offset_in = ssl->in_iv - ssl->in_buf;\n        len_offset_in = ssl->in_len - ssl->in_buf;\n        hdr_in = ssl->in_hdr - ssl->in_buf;\n        if (downsizing ?\n            ssl->in_buf_len > in_buf_new_len && ssl->in_left < in_buf_new_len :\n            ssl->in_buf_len < in_buf_new_len) {\n            if (resize_buffer(&ssl->in_buf, in_buf_new_len, &ssl->in_buf_len) != 0) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"input buffer resizing failed - out of memory\"));\n            } else {\n                MBEDTLS_SSL_DEBUG_MSG(2, (\"Reallocating in_buf to %\" MBEDTLS_PRINTF_SIZET,\n                                          in_buf_new_len));\n                modified = 1;\n            }\n        }\n    }\n\n    if (ssl->out_buf != NULL) {\n        written_out = ssl->out_msg - ssl->out_buf;\n        iv_offset_out = ssl->out_iv - ssl->out_buf;\n        len_offset_out = ssl->out_len - ssl->out_buf;\n        if (downsizing ?\n            ssl->out_buf_len > out_buf_new_len && ssl->out_left < out_buf_new_len :\n            ssl->out_buf_len < out_buf_new_len) {\n            if (resize_buffer(&ssl->out_buf, out_buf_new_len, &ssl->out_buf_len) != 0) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"output buffer resizing failed - out of memory\"));\n            } else {\n                MBEDTLS_SSL_DEBUG_MSG(2, (\"Reallocating out_buf to %\" MBEDTLS_PRINTF_SIZET,\n                                          out_buf_new_len));\n                modified = 1;\n            }\n        }\n    }\n    if (modified) {\n        /* Update pointers here to avoid doing it twice. */\n        ssl->in_hdr = ssl->in_buf + hdr_in;\n        mbedtls_ssl_update_in_pointers(ssl);\n        mbedtls_ssl_reset_out_pointers(ssl);\n\n        /* Fields below might not be properly updated with record\n         * splitting or with CID, so they are manually updated here. */\n        ssl->out_msg = ssl->out_buf + written_out;\n        ssl->out_len = ssl->out_buf + len_offset_out;\n        ssl->out_iv = ssl->out_buf + iv_offset_out;\n\n        ssl->in_msg = ssl->in_buf + written_in;\n        ssl->in_len = ssl->in_buf + len_offset_in;\n        ssl->in_iv = ssl->in_buf + iv_offset_in;\n    }\n}\n#endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n\n#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)\ntypedef int (*tls_prf_fn)(const unsigned char *secret, size_t slen,\n                          const char *label,\n                          const unsigned char *random, size_t rlen,\n                          unsigned char *dstbuf, size_t dlen);\n\nstatic tls_prf_fn ssl_tls12prf_from_cs(int ciphersuite_id);\n\n#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */\n\n/* Type for the TLS PRF */\ntypedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *,\n                          const unsigned char *, size_t,\n                          unsigned char *, size_t);\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform,\n                                        int ciphersuite,\n                                        const unsigned char master[48],\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)\n                                        int encrypt_then_mac,\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */\n                                        ssl_tls_prf_t tls_prf,\n                                        const unsigned char randbytes[64],\n                                        mbedtls_ssl_protocol_version tls_version,\n                                        unsigned endpoint,\n                                        const mbedtls_ssl_context *ssl);\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int tls_prf_sha256(const unsigned char *secret, size_t slen,\n                          const char *label,\n                          const unsigned char *random, size_t rlen,\n                          unsigned char *dstbuf, size_t dlen);\nstatic int ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *, unsigned char *, size_t *);\nstatic int ssl_calc_finished_tls_sha256(mbedtls_ssl_context *, unsigned char *, int);\n\n#endif /* MBEDTLS_MD_CAN_SHA256*/\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int tls_prf_sha384(const unsigned char *secret, size_t slen,\n                          const char *label,\n                          const unsigned char *random, size_t rlen,\n                          unsigned char *dstbuf, size_t dlen);\n\nstatic int ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *, unsigned char *, size_t *);\nstatic int ssl_calc_finished_tls_sha384(mbedtls_ssl_context *, unsigned char *, int);\n#endif /* MBEDTLS_MD_CAN_SHA384*/\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls12_session_load(mbedtls_ssl_session *session,\n                                  const unsigned char *buf,\n                                  size_t len);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\nstatic int ssl_update_checksum_start(mbedtls_ssl_context *, const unsigned char *, size_t);\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\nstatic int ssl_update_checksum_sha256(mbedtls_ssl_context *, const unsigned char *, size_t);\n#endif /* MBEDTLS_MD_CAN_SHA256*/\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\nstatic int ssl_update_checksum_sha384(mbedtls_ssl_context *, const unsigned char *, size_t);\n#endif /* MBEDTLS_MD_CAN_SHA384*/\n\nint  mbedtls_ssl_tls_prf(const mbedtls_tls_prf_types prf,\n                         const unsigned char *secret, size_t slen,\n                         const char *label,\n                         const unsigned char *random, size_t rlen,\n                         unsigned char *dstbuf, size_t dlen)\n{\n    mbedtls_ssl_tls_prf_cb *tls_prf = NULL;\n\n    switch (prf) {\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n#if defined(MBEDTLS_MD_CAN_SHA384)\n        case MBEDTLS_SSL_TLS_PRF_SHA384:\n            tls_prf = tls_prf_sha384;\n            break;\n#endif /* MBEDTLS_MD_CAN_SHA384*/\n#if defined(MBEDTLS_MD_CAN_SHA256)\n        case MBEDTLS_SSL_TLS_PRF_SHA256:\n            tls_prf = tls_prf_sha256;\n            break;\n#endif /* MBEDTLS_MD_CAN_SHA256*/\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n        default:\n            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    }\n\n    return tls_prf(secret, slen, label, random, rlen, dstbuf, dlen);\n}\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\nstatic void ssl_clear_peer_cert(mbedtls_ssl_session *session)\n{\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    if (session->peer_cert != NULL) {\n        mbedtls_x509_crt_free(session->peer_cert);\n        mbedtls_free(session->peer_cert);\n        session->peer_cert = NULL;\n    }\n#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n    if (session->peer_cert_digest != NULL) {\n        /* Zeroization is not necessary. */\n        mbedtls_free(session->peer_cert_digest);\n        session->peer_cert_digest      = NULL;\n        session->peer_cert_digest_type = MBEDTLS_MD_NONE;\n        session->peer_cert_digest_len  = 0;\n    }\n#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n}\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\nuint32_t mbedtls_ssl_get_extension_id(unsigned int extension_type)\n{\n    switch (extension_type) {\n        case MBEDTLS_TLS_EXT_SERVERNAME:\n            return MBEDTLS_SSL_EXT_ID_SERVERNAME;\n\n        case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH:\n            return MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH;\n\n        case MBEDTLS_TLS_EXT_STATUS_REQUEST:\n            return MBEDTLS_SSL_EXT_ID_STATUS_REQUEST;\n\n        case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS:\n            return MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS;\n\n        case MBEDTLS_TLS_EXT_SIG_ALG:\n            return MBEDTLS_SSL_EXT_ID_SIG_ALG;\n\n        case MBEDTLS_TLS_EXT_USE_SRTP:\n            return MBEDTLS_SSL_EXT_ID_USE_SRTP;\n\n        case MBEDTLS_TLS_EXT_HEARTBEAT:\n            return MBEDTLS_SSL_EXT_ID_HEARTBEAT;\n\n        case MBEDTLS_TLS_EXT_ALPN:\n            return MBEDTLS_SSL_EXT_ID_ALPN;\n\n        case MBEDTLS_TLS_EXT_SCT:\n            return MBEDTLS_SSL_EXT_ID_SCT;\n\n        case MBEDTLS_TLS_EXT_CLI_CERT_TYPE:\n            return MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE;\n\n        case MBEDTLS_TLS_EXT_SERV_CERT_TYPE:\n            return MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE;\n\n        case MBEDTLS_TLS_EXT_PADDING:\n            return MBEDTLS_SSL_EXT_ID_PADDING;\n\n        case MBEDTLS_TLS_EXT_PRE_SHARED_KEY:\n            return MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY;\n\n        case MBEDTLS_TLS_EXT_EARLY_DATA:\n            return MBEDTLS_SSL_EXT_ID_EARLY_DATA;\n\n        case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS:\n            return MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS;\n\n        case MBEDTLS_TLS_EXT_COOKIE:\n            return MBEDTLS_SSL_EXT_ID_COOKIE;\n\n        case MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES:\n            return MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES;\n\n        case MBEDTLS_TLS_EXT_CERT_AUTH:\n            return MBEDTLS_SSL_EXT_ID_CERT_AUTH;\n\n        case MBEDTLS_TLS_EXT_OID_FILTERS:\n            return MBEDTLS_SSL_EXT_ID_OID_FILTERS;\n\n        case MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH:\n            return MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH;\n\n        case MBEDTLS_TLS_EXT_SIG_ALG_CERT:\n            return MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT;\n\n        case MBEDTLS_TLS_EXT_KEY_SHARE:\n            return MBEDTLS_SSL_EXT_ID_KEY_SHARE;\n\n        case MBEDTLS_TLS_EXT_TRUNCATED_HMAC:\n            return MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC;\n\n        case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS:\n            return MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS;\n\n        case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC:\n            return MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC;\n\n        case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET:\n            return MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET;\n\n        case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT:\n            return MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT;\n\n        case MBEDTLS_TLS_EXT_SESSION_TICKET:\n            return MBEDTLS_SSL_EXT_ID_SESSION_TICKET;\n\n    }\n\n    return MBEDTLS_SSL_EXT_ID_UNRECOGNIZED;\n}\n\nuint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type)\n{\n    return 1 << mbedtls_ssl_get_extension_id(extension_type);\n}\n\n#if defined(MBEDTLS_DEBUG_C)\nstatic const char *extension_name_table[] = {\n    [MBEDTLS_SSL_EXT_ID_UNRECOGNIZED] = \"unrecognized\",\n    [MBEDTLS_SSL_EXT_ID_SERVERNAME] = \"server_name\",\n    [MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH] = \"max_fragment_length\",\n    [MBEDTLS_SSL_EXT_ID_STATUS_REQUEST] = \"status_request\",\n    [MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS] = \"supported_groups\",\n    [MBEDTLS_SSL_EXT_ID_SIG_ALG] = \"signature_algorithms\",\n    [MBEDTLS_SSL_EXT_ID_USE_SRTP] = \"use_srtp\",\n    [MBEDTLS_SSL_EXT_ID_HEARTBEAT] = \"heartbeat\",\n    [MBEDTLS_SSL_EXT_ID_ALPN] = \"application_layer_protocol_negotiation\",\n    [MBEDTLS_SSL_EXT_ID_SCT] = \"signed_certificate_timestamp\",\n    [MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE] = \"client_certificate_type\",\n    [MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE] = \"server_certificate_type\",\n    [MBEDTLS_SSL_EXT_ID_PADDING] = \"padding\",\n    [MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY] = \"pre_shared_key\",\n    [MBEDTLS_SSL_EXT_ID_EARLY_DATA] = \"early_data\",\n    [MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS] = \"supported_versions\",\n    [MBEDTLS_SSL_EXT_ID_COOKIE] = \"cookie\",\n    [MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES] = \"psk_key_exchange_modes\",\n    [MBEDTLS_SSL_EXT_ID_CERT_AUTH] = \"certificate_authorities\",\n    [MBEDTLS_SSL_EXT_ID_OID_FILTERS] = \"oid_filters\",\n    [MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH] = \"post_handshake_auth\",\n    [MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT] = \"signature_algorithms_cert\",\n    [MBEDTLS_SSL_EXT_ID_KEY_SHARE] = \"key_share\",\n    [MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC] = \"truncated_hmac\",\n    [MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS] = \"supported_point_formats\",\n    [MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC] = \"encrypt_then_mac\",\n    [MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET] = \"extended_master_secret\",\n    [MBEDTLS_SSL_EXT_ID_SESSION_TICKET] = \"session_ticket\",\n    [MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT] = \"record_size_limit\"\n};\n\nstatic const unsigned int extension_type_table[] = {\n    [MBEDTLS_SSL_EXT_ID_UNRECOGNIZED] = 0xff,\n    [MBEDTLS_SSL_EXT_ID_SERVERNAME] = MBEDTLS_TLS_EXT_SERVERNAME,\n    [MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH] = MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH,\n    [MBEDTLS_SSL_EXT_ID_STATUS_REQUEST] = MBEDTLS_TLS_EXT_STATUS_REQUEST,\n    [MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS] = MBEDTLS_TLS_EXT_SUPPORTED_GROUPS,\n    [MBEDTLS_SSL_EXT_ID_SIG_ALG] = MBEDTLS_TLS_EXT_SIG_ALG,\n    [MBEDTLS_SSL_EXT_ID_USE_SRTP] = MBEDTLS_TLS_EXT_USE_SRTP,\n    [MBEDTLS_SSL_EXT_ID_HEARTBEAT] = MBEDTLS_TLS_EXT_HEARTBEAT,\n    [MBEDTLS_SSL_EXT_ID_ALPN] = MBEDTLS_TLS_EXT_ALPN,\n    [MBEDTLS_SSL_EXT_ID_SCT] = MBEDTLS_TLS_EXT_SCT,\n    [MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE] = MBEDTLS_TLS_EXT_CLI_CERT_TYPE,\n    [MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE] = MBEDTLS_TLS_EXT_SERV_CERT_TYPE,\n    [MBEDTLS_SSL_EXT_ID_PADDING] = MBEDTLS_TLS_EXT_PADDING,\n    [MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY] = MBEDTLS_TLS_EXT_PRE_SHARED_KEY,\n    [MBEDTLS_SSL_EXT_ID_EARLY_DATA] = MBEDTLS_TLS_EXT_EARLY_DATA,\n    [MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS] = MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS,\n    [MBEDTLS_SSL_EXT_ID_COOKIE] = MBEDTLS_TLS_EXT_COOKIE,\n    [MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES] = MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES,\n    [MBEDTLS_SSL_EXT_ID_CERT_AUTH] = MBEDTLS_TLS_EXT_CERT_AUTH,\n    [MBEDTLS_SSL_EXT_ID_OID_FILTERS] = MBEDTLS_TLS_EXT_OID_FILTERS,\n    [MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH] = MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH,\n    [MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT] = MBEDTLS_TLS_EXT_SIG_ALG_CERT,\n    [MBEDTLS_SSL_EXT_ID_KEY_SHARE] = MBEDTLS_TLS_EXT_KEY_SHARE,\n    [MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC] = MBEDTLS_TLS_EXT_TRUNCATED_HMAC,\n    [MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS] = MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS,\n    [MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC] = MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC,\n    [MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET] = MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET,\n    [MBEDTLS_SSL_EXT_ID_SESSION_TICKET] = MBEDTLS_TLS_EXT_SESSION_TICKET,\n    [MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT] = MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT\n};\n\nconst char *mbedtls_ssl_get_extension_name(unsigned int extension_type)\n{\n    return extension_name_table[\n        mbedtls_ssl_get_extension_id(extension_type)];\n}\n\nstatic const char *ssl_tls13_get_hs_msg_name(int hs_msg_type)\n{\n    switch (hs_msg_type) {\n        case MBEDTLS_SSL_HS_CLIENT_HELLO:\n            return \"ClientHello\";\n        case MBEDTLS_SSL_HS_SERVER_HELLO:\n            return \"ServerHello\";\n        case MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST:\n            return \"HelloRetryRequest\";\n        case MBEDTLS_SSL_HS_NEW_SESSION_TICKET:\n            return \"NewSessionTicket\";\n        case MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS:\n            return \"EncryptedExtensions\";\n        case MBEDTLS_SSL_HS_CERTIFICATE:\n            return \"Certificate\";\n        case MBEDTLS_SSL_HS_CERTIFICATE_REQUEST:\n            return \"CertificateRequest\";\n    }\n    return \"Unknown\";\n}\n\nvoid mbedtls_ssl_print_extension(const mbedtls_ssl_context *ssl,\n                                 int level, const char *file, int line,\n                                 int hs_msg_type, unsigned int extension_type,\n                                 const char *extra_msg0, const char *extra_msg1)\n{\n    const char *extra_msg;\n    if (extra_msg0 && extra_msg1) {\n        mbedtls_debug_print_msg(\n            ssl, level, file, line,\n            \"%s: %s(%u) extension %s %s.\",\n            ssl_tls13_get_hs_msg_name(hs_msg_type),\n            mbedtls_ssl_get_extension_name(extension_type),\n            extension_type,\n            extra_msg0, extra_msg1);\n        return;\n    }\n\n    extra_msg = extra_msg0 ? extra_msg0 : extra_msg1;\n    if (extra_msg) {\n        mbedtls_debug_print_msg(\n            ssl, level, file, line,\n            \"%s: %s(%u) extension %s.\", ssl_tls13_get_hs_msg_name(hs_msg_type),\n            mbedtls_ssl_get_extension_name(extension_type), extension_type,\n            extra_msg);\n        return;\n    }\n\n    mbedtls_debug_print_msg(\n        ssl, level, file, line,\n        \"%s: %s(%u) extension.\", ssl_tls13_get_hs_msg_name(hs_msg_type),\n        mbedtls_ssl_get_extension_name(extension_type), extension_type);\n}\n\nvoid mbedtls_ssl_print_extensions(const mbedtls_ssl_context *ssl,\n                                  int level, const char *file, int line,\n                                  int hs_msg_type, uint32_t extensions_mask,\n                                  const char *extra)\n{\n\n    for (unsigned i = 0;\n         i < sizeof(extension_name_table) / sizeof(extension_name_table[0]);\n         i++) {\n        mbedtls_ssl_print_extension(\n            ssl, level, file, line, hs_msg_type, extension_type_table[i],\n            extensions_mask & (1 << i) ? \"exists\" : \"does not exist\", extra);\n    }\n}\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)\nstatic const char *ticket_flag_name_table[] =\n{\n    [0] = \"ALLOW_PSK_RESUMPTION\",\n    [2] = \"ALLOW_PSK_EPHEMERAL_RESUMPTION\",\n    [3] = \"ALLOW_EARLY_DATA\",\n};\n\nvoid mbedtls_ssl_print_ticket_flags(const mbedtls_ssl_context *ssl,\n                                    int level, const char *file, int line,\n                                    unsigned int flags)\n{\n    size_t i;\n\n    mbedtls_debug_print_msg(ssl, level, file, line,\n                            \"print ticket_flags (0x%02x)\", flags);\n\n    flags = flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK;\n\n    for (i = 0; i < ARRAY_LENGTH(ticket_flag_name_table); i++) {\n        if ((flags & (1 << i))) {\n            mbedtls_debug_print_msg(ssl, level, file, line, \"- %s is set.\",\n                                    ticket_flag_name_table[i]);\n        }\n    }\n}\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */\n\n#endif /* MBEDTLS_DEBUG_C */\n\nvoid mbedtls_ssl_optimize_checksum(mbedtls_ssl_context *ssl,\n                                   const mbedtls_ssl_ciphersuite_t *ciphersuite_info)\n{\n    ((void) ciphersuite_info);\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    if (ciphersuite_info->mac == MBEDTLS_MD_SHA384) {\n        ssl->handshake->update_checksum = ssl_update_checksum_sha384;\n    } else\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    if (ciphersuite_info->mac != MBEDTLS_MD_SHA384) {\n        ssl->handshake->update_checksum = ssl_update_checksum_sha256;\n    } else\n#endif\n    {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return;\n    }\n}\n\nint mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl,\n                                       unsigned hs_type,\n                                       size_t total_hs_len)\n{\n    unsigned char hs_hdr[4];\n\n    /* Build HS header for checksum update. */\n    hs_hdr[0] = MBEDTLS_BYTE_0(hs_type);\n    hs_hdr[1] = MBEDTLS_BYTE_2(total_hs_len);\n    hs_hdr[2] = MBEDTLS_BYTE_1(total_hs_len);\n    hs_hdr[3] = MBEDTLS_BYTE_0(total_hs_len);\n\n    return ssl->handshake->update_checksum(ssl, hs_hdr, sizeof(hs_hdr));\n}\n\nint mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl,\n                                       unsigned hs_type,\n                                       unsigned char const *msg,\n                                       size_t msg_len)\n{\n    int ret;\n    ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl, hs_type, msg_len);\n    if (ret != 0) {\n        return ret;\n    }\n    return ssl->handshake->update_checksum(ssl, msg, msg_len);\n}\n\nint mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl)\n{\n#if defined(MBEDTLS_MD_CAN_SHA256) || \\\n    defined(MBEDTLS_MD_CAN_SHA384)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_status_t status;\n#else\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n#endif\n#else /* SHA-256 or SHA-384 */\n    ((void) ssl);\n#endif /* SHA-256 or SHA-384 */\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    status = psa_hash_abort(&ssl->handshake->fin_sha256_psa);\n    if (status != PSA_SUCCESS) {\n        return mbedtls_md_error_from_psa(status);\n    }\n    status = psa_hash_setup(&ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256);\n    if (status != PSA_SUCCESS) {\n        return mbedtls_md_error_from_psa(status);\n    }\n#else\n    mbedtls_md_free(&ssl->handshake->fin_sha256);\n    mbedtls_md_init(&ssl->handshake->fin_sha256);\n    ret = mbedtls_md_setup(&ssl->handshake->fin_sha256,\n                           mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),\n                           0);\n    if (ret != 0) {\n        return ret;\n    }\n    ret = mbedtls_md_starts(&ssl->handshake->fin_sha256);\n    if (ret != 0) {\n        return ret;\n    }\n#endif\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA384)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    status = psa_hash_abort(&ssl->handshake->fin_sha384_psa);\n    if (status != PSA_SUCCESS) {\n        return mbedtls_md_error_from_psa(status);\n    }\n    status = psa_hash_setup(&ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384);\n    if (status != PSA_SUCCESS) {\n        return mbedtls_md_error_from_psa(status);\n    }\n#else\n    mbedtls_md_free(&ssl->handshake->fin_sha384);\n    mbedtls_md_init(&ssl->handshake->fin_sha384);\n    ret = mbedtls_md_setup(&ssl->handshake->fin_sha384,\n                           mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0);\n    if (ret != 0) {\n        return ret;\n    }\n    ret = mbedtls_md_starts(&ssl->handshake->fin_sha384);\n    if (ret != 0) {\n        return ret;\n    }\n#endif\n#endif\n    return 0;\n}\n\nstatic int ssl_update_checksum_start(mbedtls_ssl_context *ssl,\n                                     const unsigned char *buf, size_t len)\n{\n#if defined(MBEDTLS_MD_CAN_SHA256) || \\\n    defined(MBEDTLS_MD_CAN_SHA384)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_status_t status;\n#else\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n#endif\n#else /* SHA-256 or SHA-384 */\n    ((void) ssl);\n    (void) buf;\n    (void) len;\n#endif /* SHA-256 or SHA-384 */\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    status = psa_hash_update(&ssl->handshake->fin_sha256_psa, buf, len);\n    if (status != PSA_SUCCESS) {\n        return mbedtls_md_error_from_psa(status);\n    }\n#else\n    ret = mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len);\n    if (ret != 0) {\n        return ret;\n    }\n#endif\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA384)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    status = psa_hash_update(&ssl->handshake->fin_sha384_psa, buf, len);\n    if (status != PSA_SUCCESS) {\n        return mbedtls_md_error_from_psa(status);\n    }\n#else\n    ret = mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len);\n    if (ret != 0) {\n        return ret;\n    }\n#endif\n#endif\n    return 0;\n}\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\nstatic int ssl_update_checksum_sha256(mbedtls_ssl_context *ssl,\n                                      const unsigned char *buf, size_t len)\n{\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    return mbedtls_md_error_from_psa(psa_hash_update(\n                                         &ssl->handshake->fin_sha256_psa, buf, len));\n#else\n    return mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len);\n#endif\n}\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\nstatic int ssl_update_checksum_sha384(mbedtls_ssl_context *ssl,\n                                      const unsigned char *buf, size_t len)\n{\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    return mbedtls_md_error_from_psa(psa_hash_update(\n                                         &ssl->handshake->fin_sha384_psa, buf, len));\n#else\n    return mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len);\n#endif\n}\n#endif\n\nstatic void ssl_handshake_params_init(mbedtls_ssl_handshake_params *handshake)\n{\n    memset(handshake, 0, sizeof(mbedtls_ssl_handshake_params));\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    handshake->fin_sha256_psa = psa_hash_operation_init();\n#else\n    mbedtls_md_init(&handshake->fin_sha256);\n#endif\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA384)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    handshake->fin_sha384_psa = psa_hash_operation_init();\n#else\n    mbedtls_md_init(&handshake->fin_sha384);\n#endif\n#endif\n\n    handshake->update_checksum = ssl_update_checksum_start;\n\n#if defined(MBEDTLS_DHM_C)\n    mbedtls_dhm_init(&handshake->dhm_ctx);\n#endif\n#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \\\n    defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED)\n    mbedtls_ecdh_init(&handshake->ecdh_ctx);\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    handshake->psa_pake_ctx = psa_pake_operation_init();\n    handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT;\n#else\n    mbedtls_ecjpake_init(&handshake->ecjpake_ctx);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#if defined(MBEDTLS_SSL_CLI_C)\n    handshake->ecjpake_cache = NULL;\n    handshake->ecjpake_cache_len = 0;\n#endif\n#endif\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n    mbedtls_x509_crt_restart_init(&handshake->ecrs_ctx);\n#endif\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET;\n#endif\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C) && \\\n    !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    mbedtls_pk_init(&handshake->peer_pubkey);\n#endif\n}\n\nvoid mbedtls_ssl_transform_init(mbedtls_ssl_transform *transform)\n{\n    memset(transform, 0, sizeof(mbedtls_ssl_transform));\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    transform->psa_key_enc = MBEDTLS_SVC_KEY_ID_INIT;\n    transform->psa_key_dec = MBEDTLS_SVC_KEY_ID_INIT;\n#else\n    mbedtls_cipher_init(&transform->cipher_ctx_enc);\n    mbedtls_cipher_init(&transform->cipher_ctx_dec);\n#endif\n\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    transform->psa_mac_enc = MBEDTLS_SVC_KEY_ID_INIT;\n    transform->psa_mac_dec = MBEDTLS_SVC_KEY_ID_INIT;\n#else\n    mbedtls_md_init(&transform->md_ctx_enc);\n    mbedtls_md_init(&transform->md_ctx_dec);\n#endif\n#endif\n}\n\nvoid mbedtls_ssl_session_init(mbedtls_ssl_session *session)\n{\n    memset(session, 0, sizeof(mbedtls_ssl_session));\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_handshake_init(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* Clear old handshake information if present */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    if (ssl->transform_negotiate) {\n        mbedtls_ssl_transform_free(ssl->transform_negotiate);\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n    if (ssl->session_negotiate) {\n        mbedtls_ssl_session_free(ssl->session_negotiate);\n    }\n    if (ssl->handshake) {\n        mbedtls_ssl_handshake_free(ssl);\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    /*\n     * Either the pointers are now NULL or cleared properly and can be freed.\n     * Now allocate missing structures.\n     */\n    if (ssl->transform_negotiate == NULL) {\n        ssl->transform_negotiate = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform));\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n    if (ssl->session_negotiate == NULL) {\n        ssl->session_negotiate = mbedtls_calloc(1, sizeof(mbedtls_ssl_session));\n    }\n\n    if (ssl->handshake == NULL) {\n        ssl->handshake = mbedtls_calloc(1, sizeof(mbedtls_ssl_handshake_params));\n    }\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n    /* If the buffers are too small - reallocate */\n\n    handle_buffer_resizing(ssl, 0, MBEDTLS_SSL_IN_BUFFER_LEN,\n                           MBEDTLS_SSL_OUT_BUFFER_LEN);\n#endif\n\n    /* All pointers should exist and can be directly freed without issue */\n    if (ssl->handshake           == NULL ||\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        ssl->transform_negotiate == NULL ||\n#endif\n        ssl->session_negotiate   == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"alloc() of ssl sub-contexts failed\"));\n\n        mbedtls_free(ssl->handshake);\n        ssl->handshake = NULL;\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        mbedtls_free(ssl->transform_negotiate);\n        ssl->transform_negotiate = NULL;\n#endif\n\n        mbedtls_free(ssl->session_negotiate);\n        ssl->session_negotiate = NULL;\n\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n#if defined(MBEDTLS_SSL_CLI_C)\n    ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_IDLE;\n#endif\n#if defined(MBEDTLS_SSL_SRV_C)\n    ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD;\n#endif\n    ssl->total_early_data_size = 0;\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n    /* Initialize structures */\n    mbedtls_ssl_session_init(ssl->session_negotiate);\n    ssl_handshake_params_init(ssl->handshake);\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    mbedtls_ssl_transform_init(ssl->transform_negotiate);\n#endif\n\n    /* Setup handshake checksums */\n    ret = mbedtls_ssl_reset_checksum(ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_reset_checksum\", ret);\n        return ret;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \\\n    defined(MBEDTLS_SSL_SRV_C) && \\\n    defined(MBEDTLS_SSL_SESSION_TICKETS)\n    ssl->handshake->new_session_tickets_count =\n        ssl->conf->new_session_tickets_count;\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        ssl->handshake->alt_transform_out = ssl->transform_out;\n\n        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {\n            ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING;\n        } else {\n            ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;\n        }\n\n        mbedtls_ssl_set_timer(ssl, 0);\n    }\n#endif\n\n/*\n * curve_list is translated to IANA TLS group identifiers here because\n * mbedtls_ssl_conf_curves returns void and so can't return\n * any error codes.\n */\n#if defined(MBEDTLS_ECP_C)\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n    /* Heap allocate and translate curve_list from internal to IANA group ids */\n    if (ssl->conf->curve_list != NULL) {\n        size_t length;\n        const mbedtls_ecp_group_id *curve_list = ssl->conf->curve_list;\n\n        for (length = 0;  (curve_list[length] != MBEDTLS_ECP_DP_NONE); length++) {\n        }\n\n        /* Leave room for zero termination */\n        uint16_t *group_list = mbedtls_calloc(length + 1, sizeof(uint16_t));\n        if (group_list == NULL) {\n            return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        }\n\n        for (size_t i = 0; i < length; i++) {\n            uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(\n                curve_list[i]);\n            if (tls_id == 0) {\n                mbedtls_free(group_list);\n                return MBEDTLS_ERR_SSL_BAD_CONFIG;\n            }\n            group_list[i] = tls_id;\n        }\n\n        group_list[length] = 0;\n\n        ssl->handshake->group_list = group_list;\n        ssl->handshake->group_list_heap_allocated = 1;\n    } else {\n        ssl->handshake->group_list = ssl->conf->group_list;\n        ssl->handshake->group_list_heap_allocated = 0;\n    }\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n#endif /* MBEDTLS_ECP_C */\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    /* Heap allocate and translate sig_hashes from internal hash identifiers to\n       signature algorithms IANA identifiers.  */\n    if (mbedtls_ssl_conf_is_tls12_only(ssl->conf) &&\n        ssl->conf->sig_hashes != NULL) {\n        const int *md;\n        const int *sig_hashes = ssl->conf->sig_hashes;\n        size_t sig_algs_len = 0;\n        uint16_t *p;\n\n        MBEDTLS_STATIC_ASSERT(MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN\n                              <= (SIZE_MAX - (2 * sizeof(uint16_t))),\n                              \"MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN too big\");\n\n        for (md = sig_hashes; *md != MBEDTLS_MD_NONE; md++) {\n            if (mbedtls_ssl_hash_from_md_alg(*md) == MBEDTLS_SSL_HASH_NONE) {\n                continue;\n            }\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)\n            sig_algs_len += sizeof(uint16_t);\n#endif\n\n#if defined(MBEDTLS_RSA_C)\n            sig_algs_len += sizeof(uint16_t);\n#endif\n            if (sig_algs_len > MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN) {\n                return MBEDTLS_ERR_SSL_BAD_CONFIG;\n            }\n        }\n\n        if (sig_algs_len < MBEDTLS_SSL_MIN_SIG_ALG_LIST_LEN) {\n            return MBEDTLS_ERR_SSL_BAD_CONFIG;\n        }\n\n        ssl->handshake->sig_algs = mbedtls_calloc(1, sig_algs_len +\n                                                  sizeof(uint16_t));\n        if (ssl->handshake->sig_algs == NULL) {\n            return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        }\n\n        p = (uint16_t *) ssl->handshake->sig_algs;\n        for (md = sig_hashes; *md != MBEDTLS_MD_NONE; md++) {\n            unsigned char hash = mbedtls_ssl_hash_from_md_alg(*md);\n            if (hash == MBEDTLS_SSL_HASH_NONE) {\n                continue;\n            }\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)\n            *p = ((hash << 8) | MBEDTLS_SSL_SIG_ECDSA);\n            p++;\n#endif\n#if defined(MBEDTLS_RSA_C)\n            *p = ((hash << 8) | MBEDTLS_SSL_SIG_RSA);\n            p++;\n#endif\n        }\n        *p = MBEDTLS_TLS_SIG_NONE;\n        ssl->handshake->sig_algs_heap_allocated = 1;\n    } else\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n    {\n        ssl->handshake->sig_algs_heap_allocated = 0;\n    }\n#endif /* !MBEDTLS_DEPRECATED_REMOVED */\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)\n/* Dummy cookie callbacks for defaults */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_cookie_write_dummy(void *ctx,\n                                  unsigned char **p, unsigned char *end,\n                                  const unsigned char *cli_id, size_t cli_id_len)\n{\n    ((void) ctx);\n    ((void) p);\n    ((void) end);\n    ((void) cli_id);\n    ((void) cli_id_len);\n\n    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_cookie_check_dummy(void *ctx,\n                                  const unsigned char *cookie, size_t cookie_len,\n                                  const unsigned char *cli_id, size_t cli_id_len)\n{\n    ((void) ctx);\n    ((void) cookie);\n    ((void) cookie_len);\n    ((void) cli_id);\n    ((void) cli_id_len);\n\n    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n}\n#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */\n\n/*\n * Initialize an SSL context\n */\nvoid mbedtls_ssl_init(mbedtls_ssl_context *ssl)\n{\n    memset(ssl, 0, sizeof(mbedtls_ssl_context));\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_conf_version_check(const mbedtls_ssl_context *ssl)\n{\n    const mbedtls_ssl_config *conf = ssl->conf;\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    if (mbedtls_ssl_conf_is_tls13_only(conf)) {\n        if (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"DTLS 1.3 is not yet supported.\"));\n            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n        }\n\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"The SSL configuration is tls13 only.\"));\n        return 0;\n    }\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    if (mbedtls_ssl_conf_is_tls12_only(conf)) {\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"The SSL configuration is tls12 only.\"));\n        return 0;\n    }\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    if (mbedtls_ssl_conf_is_hybrid_tls12_tls13(conf)) {\n        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"DTLS not yet supported in Hybrid TLS 1.3 + TLS 1.2\"));\n            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n        }\n\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"The SSL configuration is TLS 1.3 or TLS 1.2.\"));\n        return 0;\n    }\n#endif\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"The SSL configuration is invalid.\"));\n    return MBEDTLS_ERR_SSL_BAD_CONFIG;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_conf_check(const mbedtls_ssl_context *ssl)\n{\n    int ret;\n    ret = ssl_conf_version_check(ssl);\n    if (ret != 0) {\n        return ret;\n    }\n\n    if (ssl->conf->f_rng == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"no RNG provided\"));\n        return MBEDTLS_ERR_SSL_NO_RNG;\n    }\n\n    /* Space for further checks */\n\n    return 0;\n}\n\n/*\n * Setup an SSL context\n */\n\nint mbedtls_ssl_setup(mbedtls_ssl_context *ssl,\n                      const mbedtls_ssl_config *conf)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;\n    size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;\n\n    ssl->conf = conf;\n\n    if ((ret = ssl_conf_check(ssl)) != 0) {\n        return ret;\n    }\n    ssl->tls_version = ssl->conf->max_tls_version;\n\n    /*\n     * Prepare base structures\n     */\n\n    /* Set to NULL in case of an error condition */\n    ssl->out_buf = NULL;\n\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n    ssl->in_buf_len = in_buf_len;\n#endif\n    ssl->in_buf = mbedtls_calloc(1, in_buf_len);\n    if (ssl->in_buf == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"alloc(%\" MBEDTLS_PRINTF_SIZET \" bytes) failed\", in_buf_len));\n        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        goto error;\n    }\n\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n    ssl->out_buf_len = out_buf_len;\n#endif\n    ssl->out_buf = mbedtls_calloc(1, out_buf_len);\n    if (ssl->out_buf == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"alloc(%\" MBEDTLS_PRINTF_SIZET \" bytes) failed\", out_buf_len));\n        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        goto error;\n    }\n\n    mbedtls_ssl_reset_in_pointers(ssl);\n    mbedtls_ssl_reset_out_pointers(ssl);\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\n    memset(&ssl->dtls_srtp_info, 0, sizeof(ssl->dtls_srtp_info));\n#endif\n\n    if ((ret = ssl_handshake_init(ssl)) != 0) {\n        goto error;\n    }\n\n    return 0;\n\nerror:\n    mbedtls_free(ssl->in_buf);\n    mbedtls_free(ssl->out_buf);\n\n    ssl->conf = NULL;\n\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n    ssl->in_buf_len = 0;\n    ssl->out_buf_len = 0;\n#endif\n    ssl->in_buf = NULL;\n    ssl->out_buf = NULL;\n\n    ssl->in_hdr = NULL;\n    ssl->in_ctr = NULL;\n    ssl->in_len = NULL;\n    ssl->in_iv = NULL;\n    ssl->in_msg = NULL;\n\n    ssl->out_hdr = NULL;\n    ssl->out_ctr = NULL;\n    ssl->out_len = NULL;\n    ssl->out_iv = NULL;\n    ssl->out_msg = NULL;\n\n    return ret;\n}\n\n/*\n * Reset an initialized and used SSL context for re-use while retaining\n * all application-set variables, function pointers and data.\n *\n * If partial is non-zero, keep data in the input buffer and client ID.\n * (Use when a DTLS client reconnects from the same port.)\n */\nvoid mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl,\n                                         int partial)\n{\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n    size_t in_buf_len = ssl->in_buf_len;\n    size_t out_buf_len = ssl->out_buf_len;\n#else\n    size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;\n    size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;\n#endif\n\n#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || !defined(MBEDTLS_SSL_SRV_C)\n    partial = 0;\n#endif\n\n    /* Cancel any possibly running timer */\n    mbedtls_ssl_set_timer(ssl, 0);\n\n    mbedtls_ssl_reset_in_pointers(ssl);\n    mbedtls_ssl_reset_out_pointers(ssl);\n\n    /* Reset incoming message parsing */\n    ssl->in_offt    = NULL;\n    ssl->nb_zero    = 0;\n    ssl->in_msgtype = 0;\n    ssl->in_msglen  = 0;\n    ssl->in_hslen   = 0;\n    ssl->keep_current_message = 0;\n    ssl->transform_in  = NULL;\n\n    /* TLS: reset in_hsfraglen, which is part of message parsing.\n     * DTLS: on a client reconnect, don't reset badmac_seen. */\n    if (!partial) {\n        ssl->badmac_seen_or_in_hsfraglen = 0;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    ssl->next_record_offset = 0;\n    ssl->in_epoch = 0;\n#endif\n\n    /* Keep current datagram if partial == 1 */\n    if (partial == 0) {\n        ssl->in_left = 0;\n        memset(ssl->in_buf, 0, in_buf_len);\n    }\n\n    ssl->send_alert = 0;\n\n    /* Reset outgoing message writing */\n    ssl->out_msgtype = 0;\n    ssl->out_msglen  = 0;\n    ssl->out_left    = 0;\n    memset(ssl->out_buf, 0, out_buf_len);\n    memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr));\n    ssl->transform_out = NULL;\n\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\n    mbedtls_ssl_dtls_replay_reset(ssl);\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    if (ssl->transform) {\n        mbedtls_ssl_transform_free(ssl->transform);\n        mbedtls_free(ssl->transform);\n        ssl->transform = NULL;\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    mbedtls_ssl_transform_free(ssl->transform_application);\n    mbedtls_free(ssl->transform_application);\n    ssl->transform_application = NULL;\n\n    if (ssl->handshake != NULL) {\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n        mbedtls_ssl_transform_free(ssl->handshake->transform_earlydata);\n        mbedtls_free(ssl->handshake->transform_earlydata);\n        ssl->handshake->transform_earlydata = NULL;\n#endif\n\n        mbedtls_ssl_transform_free(ssl->handshake->transform_handshake);\n        mbedtls_free(ssl->handshake->transform_handshake);\n        ssl->handshake->transform_handshake = NULL;\n    }\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n}\n\nint mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HELLO_REQUEST);\n    ssl->tls_version = ssl->conf->max_tls_version;\n\n    mbedtls_ssl_session_reset_msg_layer(ssl, partial);\n\n    /* Reset renegotiation state */\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE;\n    ssl->renego_records_seen = 0;\n\n    ssl->verify_data_len = 0;\n    memset(ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN);\n    memset(ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN);\n#endif\n    ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION;\n\n    ssl->session_in  = NULL;\n    ssl->session_out = NULL;\n    if (ssl->session) {\n        mbedtls_ssl_session_free(ssl->session);\n        mbedtls_free(ssl->session);\n        ssl->session = NULL;\n    }\n\n#if defined(MBEDTLS_SSL_ALPN)\n    ssl->alpn_chosen = NULL;\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)\n    int free_cli_id = 1;\n#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE)\n    free_cli_id = (partial == 0);\n#endif\n    if (free_cli_id) {\n        mbedtls_free(ssl->cli_id);\n        ssl->cli_id = NULL;\n        ssl->cli_id_len = 0;\n    }\n#endif\n\n    if ((ret = ssl_handshake_init(ssl)) != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\n/*\n * Reset an initialized and used SSL context for re-use while retaining\n * all application-set variables, function pointers and data.\n */\nint mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl)\n{\n    return mbedtls_ssl_session_reset_int(ssl, 0);\n}\n\n/*\n * SSL set accessors\n */\nvoid mbedtls_ssl_conf_endpoint(mbedtls_ssl_config *conf, int endpoint)\n{\n    conf->endpoint   = endpoint;\n}\n\nvoid mbedtls_ssl_conf_transport(mbedtls_ssl_config *conf, int transport)\n{\n    conf->transport = transport;\n}\n\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\nvoid mbedtls_ssl_conf_dtls_anti_replay(mbedtls_ssl_config *conf, char mode)\n{\n    conf->anti_replay = mode;\n}\n#endif\n\nvoid mbedtls_ssl_conf_dtls_badmac_limit(mbedtls_ssl_config *conf, unsigned limit)\n{\n    conf->badmac_limit = limit;\n}\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n\nvoid mbedtls_ssl_set_datagram_packing(mbedtls_ssl_context *ssl,\n                                      unsigned allow_packing)\n{\n    ssl->disable_datagram_packing = !allow_packing;\n}\n\nvoid mbedtls_ssl_conf_handshake_timeout(mbedtls_ssl_config *conf,\n                                        uint32_t min, uint32_t max)\n{\n    conf->hs_timeout_min = min;\n    conf->hs_timeout_max = max;\n}\n#endif\n\nvoid mbedtls_ssl_conf_authmode(mbedtls_ssl_config *conf, int authmode)\n{\n    conf->authmode   = authmode;\n}\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\nvoid mbedtls_ssl_conf_verify(mbedtls_ssl_config *conf,\n                             int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),\n                             void *p_vrfy)\n{\n    conf->f_vrfy      = f_vrfy;\n    conf->p_vrfy      = p_vrfy;\n}\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\nvoid mbedtls_ssl_conf_rng(mbedtls_ssl_config *conf,\n                          int (*f_rng)(void *, unsigned char *, size_t),\n                          void *p_rng)\n{\n    conf->f_rng      = f_rng;\n    conf->p_rng      = p_rng;\n}\n\nvoid mbedtls_ssl_conf_dbg(mbedtls_ssl_config *conf,\n                          void (*f_dbg)(void *, int, const char *, int, const char *),\n                          void  *p_dbg)\n{\n    conf->f_dbg      = f_dbg;\n    conf->p_dbg      = p_dbg;\n}\n\nvoid mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl,\n                         void *p_bio,\n                         mbedtls_ssl_send_t *f_send,\n                         mbedtls_ssl_recv_t *f_recv,\n                         mbedtls_ssl_recv_timeout_t *f_recv_timeout)\n{\n    ssl->p_bio          = p_bio;\n    ssl->f_send         = f_send;\n    ssl->f_recv         = f_recv;\n    ssl->f_recv_timeout = f_recv_timeout;\n}\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\nvoid mbedtls_ssl_set_mtu(mbedtls_ssl_context *ssl, uint16_t mtu)\n{\n    ssl->mtu = mtu;\n}\n#endif\n\nvoid mbedtls_ssl_conf_read_timeout(mbedtls_ssl_config *conf, uint32_t timeout)\n{\n    conf->read_timeout   = timeout;\n}\n\nvoid mbedtls_ssl_set_timer_cb(mbedtls_ssl_context *ssl,\n                              void *p_timer,\n                              mbedtls_ssl_set_timer_t *f_set_timer,\n                              mbedtls_ssl_get_timer_t *f_get_timer)\n{\n    ssl->p_timer        = p_timer;\n    ssl->f_set_timer    = f_set_timer;\n    ssl->f_get_timer    = f_get_timer;\n\n    /* Make sure we start with no timer running */\n    mbedtls_ssl_set_timer(ssl, 0);\n}\n\n#if defined(MBEDTLS_SSL_SRV_C)\nvoid mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf,\n                                    void *p_cache,\n                                    mbedtls_ssl_cache_get_t *f_get_cache,\n                                    mbedtls_ssl_cache_set_t *f_set_cache)\n{\n    conf->p_cache = p_cache;\n    conf->f_get_cache = f_get_cache;\n    conf->f_set_cache = f_set_cache;\n}\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_SSL_CLI_C)\nint mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (ssl == NULL ||\n        session == NULL ||\n        ssl->session_negotiate == NULL ||\n        ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if (ssl->handshake->resume == 1) {\n        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n        const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n            mbedtls_ssl_ciphersuite_from_id(session->ciphersuite);\n\n        if (mbedtls_ssl_validate_ciphersuite(\n                ssl, ciphersuite_info, MBEDTLS_SSL_VERSION_TLS1_3,\n                MBEDTLS_SSL_VERSION_TLS1_3) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(4, (\"%d is not a valid TLS 1.3 ciphersuite.\",\n                                      session->ciphersuite));\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n#else\n        /*\n         * If session tickets are not enabled, it is not possible to resume a\n         * TLS 1.3 session, thus do not make any change to the SSL context in\n         * the first place.\n         */\n        return 0;\n#endif\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n    if ((ret = mbedtls_ssl_session_copy(ssl->session_negotiate,\n                                        session)) != 0) {\n        return ret;\n    }\n\n    ssl->handshake->resume = 1;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_CLI_C */\n\nvoid mbedtls_ssl_conf_ciphersuites(mbedtls_ssl_config *conf,\n                                   const int *ciphersuites)\n{\n    conf->ciphersuite_list = ciphersuites;\n}\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\nvoid mbedtls_ssl_conf_tls13_key_exchange_modes(mbedtls_ssl_config *conf,\n                                               const int kex_modes)\n{\n    conf->tls13_kex_modes = kex_modes & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL;\n}\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\nvoid mbedtls_ssl_conf_early_data(mbedtls_ssl_config *conf,\n                                 int early_data_enabled)\n{\n    conf->early_data_enabled = early_data_enabled;\n}\n\n#if defined(MBEDTLS_SSL_SRV_C)\nvoid mbedtls_ssl_conf_max_early_data_size(\n    mbedtls_ssl_config *conf, uint32_t max_early_data_size)\n{\n    conf->max_early_data_size = max_early_data_size;\n}\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\nvoid mbedtls_ssl_conf_cert_profile(mbedtls_ssl_config *conf,\n                                   const mbedtls_x509_crt_profile *profile)\n{\n    conf->cert_profile = profile;\n}\n\nstatic void ssl_key_cert_free(mbedtls_ssl_key_cert *key_cert)\n{\n    mbedtls_ssl_key_cert *cur = key_cert, *next;\n\n    while (cur != NULL) {\n        next = cur->next;\n        mbedtls_free(cur);\n        cur = next;\n    }\n}\n\n/* Append a new keycert entry to a (possibly empty) list */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_append_key_cert(mbedtls_ssl_key_cert **head,\n                               mbedtls_x509_crt *cert,\n                               mbedtls_pk_context *key)\n{\n    mbedtls_ssl_key_cert *new_cert;\n\n    if (cert == NULL) {\n        /* Free list if cert is null */\n        ssl_key_cert_free(*head);\n        *head = NULL;\n        return 0;\n    }\n\n    new_cert = mbedtls_calloc(1, sizeof(mbedtls_ssl_key_cert));\n    if (new_cert == NULL) {\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n    new_cert->cert = cert;\n    new_cert->key  = key;\n    new_cert->next = NULL;\n\n    /* Update head if the list was null, else add to the end */\n    if (*head == NULL) {\n        *head = new_cert;\n    } else {\n        mbedtls_ssl_key_cert *cur = *head;\n        while (cur->next != NULL) {\n            cur = cur->next;\n        }\n        cur->next = new_cert;\n    }\n\n    return 0;\n}\n\nint mbedtls_ssl_conf_own_cert(mbedtls_ssl_config *conf,\n                              mbedtls_x509_crt *own_cert,\n                              mbedtls_pk_context *pk_key)\n{\n    return ssl_append_key_cert(&conf->key_cert, own_cert, pk_key);\n}\n\nvoid mbedtls_ssl_conf_ca_chain(mbedtls_ssl_config *conf,\n                               mbedtls_x509_crt *ca_chain,\n                               mbedtls_x509_crl *ca_crl)\n{\n    conf->ca_chain   = ca_chain;\n    conf->ca_crl     = ca_crl;\n\n#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)\n    /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb()\n     * cannot be used together. */\n    conf->f_ca_cb = NULL;\n    conf->p_ca_cb = NULL;\n#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */\n}\n\n#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)\nvoid mbedtls_ssl_conf_ca_cb(mbedtls_ssl_config *conf,\n                            mbedtls_x509_crt_ca_cb_t f_ca_cb,\n                            void *p_ca_cb)\n{\n    conf->f_ca_cb = f_ca_cb;\n    conf->p_ca_cb = p_ca_cb;\n\n    /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb()\n     * cannot be used together. */\n    conf->ca_chain   = NULL;\n    conf->ca_crl     = NULL;\n}\n#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\nconst unsigned char *mbedtls_ssl_get_hs_sni(mbedtls_ssl_context *ssl,\n                                            size_t *name_len)\n{\n    *name_len = ssl->handshake->sni_name_len;\n    return ssl->handshake->sni_name;\n}\n\nint mbedtls_ssl_set_hs_own_cert(mbedtls_ssl_context *ssl,\n                                mbedtls_x509_crt *own_cert,\n                                mbedtls_pk_context *pk_key)\n{\n    return ssl_append_key_cert(&ssl->handshake->sni_key_cert,\n                               own_cert, pk_key);\n}\n\nvoid mbedtls_ssl_set_hs_ca_chain(mbedtls_ssl_context *ssl,\n                                 mbedtls_x509_crt *ca_chain,\n                                 mbedtls_x509_crl *ca_crl)\n{\n    ssl->handshake->sni_ca_chain   = ca_chain;\n    ssl->handshake->sni_ca_crl     = ca_crl;\n}\n\n#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)\nvoid mbedtls_ssl_set_hs_dn_hints(mbedtls_ssl_context *ssl,\n                                 const mbedtls_x509_crt *crt)\n{\n    ssl->handshake->dn_hints = crt;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */\n\nvoid mbedtls_ssl_set_hs_authmode(mbedtls_ssl_context *ssl,\n                                 int authmode)\n{\n    ssl->handshake->sni_authmode = authmode;\n}\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\nvoid mbedtls_ssl_set_verify(mbedtls_ssl_context *ssl,\n                            int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),\n                            void *p_vrfy)\n{\n    ssl->f_vrfy = f_vrfy;\n    ssl->p_vrfy = p_vrfy;\n}\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nstatic const uint8_t jpake_server_id[] = { 's', 'e', 'r', 'v', 'e', 'r' };\nstatic const uint8_t jpake_client_id[] = { 'c', 'l', 'i', 'e', 'n', 't' };\n\nstatic psa_status_t mbedtls_ssl_set_hs_ecjpake_password_common(\n    mbedtls_ssl_context *ssl,\n    mbedtls_svc_key_id_t pwd)\n{\n    psa_status_t status;\n    psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();\n    const uint8_t *user = NULL;\n    size_t user_len = 0;\n    const uint8_t *peer = NULL;\n    size_t peer_len = 0;\n    psa_pake_cs_set_algorithm(&cipher_suite, PSA_ALG_JPAKE);\n    psa_pake_cs_set_primitive(&cipher_suite,\n                              PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC,\n                                                 PSA_ECC_FAMILY_SECP_R1,\n                                                 256));\n    psa_pake_cs_set_hash(&cipher_suite, PSA_ALG_SHA_256);\n\n    status = psa_pake_setup(&ssl->handshake->psa_pake_ctx, &cipher_suite);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {\n        user = jpake_server_id;\n        user_len = sizeof(jpake_server_id);\n        peer = jpake_client_id;\n        peer_len = sizeof(jpake_client_id);\n    } else {\n        user = jpake_client_id;\n        user_len = sizeof(jpake_client_id);\n        peer = jpake_server_id;\n        peer_len = sizeof(jpake_server_id);\n    }\n\n    status = psa_pake_set_user(&ssl->handshake->psa_pake_ctx, user, user_len);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    status = psa_pake_set_peer(&ssl->handshake->psa_pake_ctx, peer, peer_len);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    status = psa_pake_set_password_key(&ssl->handshake->psa_pake_ctx, pwd);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    ssl->handshake->psa_pake_ctx_is_ok = 1;\n\n    return PSA_SUCCESS;\n}\n\nint mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl,\n                                        const unsigned char *pw,\n                                        size_t pw_len)\n{\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    psa_status_t status;\n\n    if (ssl->handshake == NULL || ssl->conf == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    /* Empty password is not valid  */\n    if ((pw == NULL) || (pw_len == 0)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);\n    psa_set_key_algorithm(&attributes, PSA_ALG_JPAKE);\n    psa_set_key_type(&attributes, PSA_KEY_TYPE_PASSWORD);\n\n    status = psa_import_key(&attributes, pw, pw_len,\n                            &ssl->handshake->psa_pake_password);\n    if (status != PSA_SUCCESS) {\n        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n    }\n\n    status = mbedtls_ssl_set_hs_ecjpake_password_common(ssl,\n                                                        ssl->handshake->psa_pake_password);\n    if (status != PSA_SUCCESS) {\n        psa_destroy_key(ssl->handshake->psa_pake_password);\n        psa_pake_abort(&ssl->handshake->psa_pake_ctx);\n        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n    }\n\n    return 0;\n}\n\nint mbedtls_ssl_set_hs_ecjpake_password_opaque(mbedtls_ssl_context *ssl,\n                                               mbedtls_svc_key_id_t pwd)\n{\n    psa_status_t status;\n\n    if (ssl->handshake == NULL || ssl->conf == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if (mbedtls_svc_key_id_is_null(pwd)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    status = mbedtls_ssl_set_hs_ecjpake_password_common(ssl, pwd);\n    if (status != PSA_SUCCESS) {\n        psa_pake_abort(&ssl->handshake->psa_pake_ctx);\n        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n    }\n\n    return 0;\n}\n#else /* MBEDTLS_USE_PSA_CRYPTO */\nint mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl,\n                                        const unsigned char *pw,\n                                        size_t pw_len)\n{\n    mbedtls_ecjpake_role role;\n\n    if (ssl->handshake == NULL || ssl->conf == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    /* Empty password is not valid  */\n    if ((pw == NULL) || (pw_len == 0)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {\n        role = MBEDTLS_ECJPAKE_SERVER;\n    } else {\n        role = MBEDTLS_ECJPAKE_CLIENT;\n    }\n\n    return mbedtls_ecjpake_setup(&ssl->handshake->ecjpake_ctx,\n                                 role,\n                                 MBEDTLS_MD_SHA256,\n                                 MBEDTLS_ECP_DP_SECP256R1,\n                                 pw, pw_len);\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)\nint mbedtls_ssl_conf_has_static_psk(mbedtls_ssl_config const *conf)\n{\n    if (conf->psk_identity     == NULL ||\n        conf->psk_identity_len == 0) {\n        return 0;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) {\n        return 1;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    if (conf->psk != NULL && conf->psk_len != 0) {\n        return 1;\n    }\n\n    return 0;\n}\n\nstatic void ssl_conf_remove_psk(mbedtls_ssl_config *conf)\n{\n    /* Remove reference to existing PSK, if any. */\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) {\n        /* The maintenance of the PSK key slot is the\n         * user's responsibility. */\n        conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    if (conf->psk != NULL) {\n        mbedtls_zeroize_and_free(conf->psk, conf->psk_len);\n        conf->psk = NULL;\n        conf->psk_len = 0;\n    }\n\n    /* Remove reference to PSK identity, if any. */\n    if (conf->psk_identity != NULL) {\n        mbedtls_free(conf->psk_identity);\n        conf->psk_identity = NULL;\n        conf->psk_identity_len = 0;\n    }\n}\n\n/* This function assumes that PSK identity in the SSL config is unset.\n * It checks that the provided identity is well-formed and attempts\n * to make a copy of it in the SSL config.\n * On failure, the PSK identity in the config remains unset. */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_conf_set_psk_identity(mbedtls_ssl_config *conf,\n                                     unsigned char const *psk_identity,\n                                     size_t psk_identity_len)\n{\n    /* Identity len will be encoded on two bytes */\n    if (psk_identity               == NULL ||\n        psk_identity_len           == 0    ||\n        (psk_identity_len >> 16) != 0    ||\n        psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    conf->psk_identity = mbedtls_calloc(1, psk_identity_len);\n    if (conf->psk_identity == NULL) {\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n    conf->psk_identity_len = psk_identity_len;\n    memcpy(conf->psk_identity, psk_identity, conf->psk_identity_len);\n\n    return 0;\n}\n\nint mbedtls_ssl_conf_psk(mbedtls_ssl_config *conf,\n                         const unsigned char *psk, size_t psk_len,\n                         const unsigned char *psk_identity, size_t psk_identity_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* We currently only support one PSK, raw or opaque. */\n    if (mbedtls_ssl_conf_has_static_psk(conf)) {\n        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    }\n\n    /* Check and set raw PSK */\n    if (psk == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    if (psk_len == 0) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    if (psk_len > MBEDTLS_PSK_MAX_LEN) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if ((conf->psk = mbedtls_calloc(1, psk_len)) == NULL) {\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n    conf->psk_len = psk_len;\n    memcpy(conf->psk, psk, conf->psk_len);\n\n    /* Check and set PSK Identity */\n    ret = ssl_conf_set_psk_identity(conf, psk_identity, psk_identity_len);\n    if (ret != 0) {\n        ssl_conf_remove_psk(conf);\n    }\n\n    return ret;\n}\n\nstatic void ssl_remove_psk(mbedtls_ssl_context *ssl)\n{\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) {\n        /* The maintenance of the external PSK key slot is the\n         * user's responsibility. */\n        if (ssl->handshake->psk_opaque_is_internal) {\n            psa_destroy_key(ssl->handshake->psk_opaque);\n            ssl->handshake->psk_opaque_is_internal = 0;\n        }\n        ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT;\n    }\n#else\n    if (ssl->handshake->psk != NULL) {\n        mbedtls_zeroize_and_free(ssl->handshake->psk,\n                                 ssl->handshake->psk_len);\n        ssl->handshake->psk_len = 0;\n        ssl->handshake->psk = NULL;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n}\n\nint mbedtls_ssl_set_hs_psk(mbedtls_ssl_context *ssl,\n                           const unsigned char *psk, size_t psk_len)\n{\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_key_attributes_t key_attributes = psa_key_attributes_init();\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_algorithm_t alg = PSA_ALG_NONE;\n    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    if (psk == NULL || ssl->handshake == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if (psk_len > MBEDTLS_PSK_MAX_LEN) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    ssl_remove_psk(ssl);\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {\n        if (ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384) {\n            alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384);\n        } else {\n            alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256);\n        }\n        psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {\n        alg = PSA_ALG_HKDF_EXTRACT(PSA_ALG_ANY_HASH);\n        psa_set_key_usage_flags(&key_attributes,\n                                PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT);\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n    psa_set_key_algorithm(&key_attributes, alg);\n    psa_set_key_type(&key_attributes, PSA_KEY_TYPE_DERIVE);\n\n    status = psa_import_key(&key_attributes, psk, psk_len, &key);\n    if (status != PSA_SUCCESS) {\n        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n    }\n\n    /* Allow calling psa_destroy_key() on psk remove */\n    ssl->handshake->psk_opaque_is_internal = 1;\n    return mbedtls_ssl_set_hs_psk_opaque(ssl, key);\n#else\n    if ((ssl->handshake->psk = mbedtls_calloc(1, psk_len)) == NULL) {\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n    ssl->handshake->psk_len = psk_len;\n    memcpy(ssl->handshake->psk, psk, ssl->handshake->psk_len);\n\n    return 0;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n}\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nint mbedtls_ssl_conf_psk_opaque(mbedtls_ssl_config *conf,\n                                mbedtls_svc_key_id_t psk,\n                                const unsigned char *psk_identity,\n                                size_t psk_identity_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* We currently only support one PSK, raw or opaque. */\n    if (mbedtls_ssl_conf_has_static_psk(conf)) {\n        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    }\n\n    /* Check and set opaque PSK */\n    if (mbedtls_svc_key_id_is_null(psk)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    conf->psk_opaque = psk;\n\n    /* Check and set PSK Identity */\n    ret = ssl_conf_set_psk_identity(conf, psk_identity,\n                                    psk_identity_len);\n    if (ret != 0) {\n        ssl_conf_remove_psk(conf);\n    }\n\n    return ret;\n}\n\nint mbedtls_ssl_set_hs_psk_opaque(mbedtls_ssl_context *ssl,\n                                  mbedtls_svc_key_id_t psk)\n{\n    if ((mbedtls_svc_key_id_is_null(psk)) ||\n        (ssl->handshake == NULL)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    ssl_remove_psk(ssl);\n    ssl->handshake->psk_opaque = psk;\n    return 0;\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_SSL_SRV_C)\nvoid mbedtls_ssl_conf_psk_cb(mbedtls_ssl_config *conf,\n                             int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *,\n                                          size_t),\n                             void *p_psk)\n{\n    conf->f_psk = f_psk;\n    conf->p_psk = p_psk;\n}\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nstatic mbedtls_ssl_mode_t mbedtls_ssl_get_base_mode(\n    psa_algorithm_t alg)\n{\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)\n    if (alg == PSA_ALG_CBC_NO_PADDING) {\n        return MBEDTLS_SSL_MODE_CBC;\n    }\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */\n    if (PSA_ALG_IS_AEAD(alg)) {\n        return MBEDTLS_SSL_MODE_AEAD;\n    }\n    return MBEDTLS_SSL_MODE_STREAM;\n}\n\n#else /* MBEDTLS_USE_PSA_CRYPTO */\n\nstatic mbedtls_ssl_mode_t mbedtls_ssl_get_base_mode(\n    mbedtls_cipher_mode_t mode)\n{\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)\n    if (mode == MBEDTLS_MODE_CBC) {\n        return MBEDTLS_SSL_MODE_CBC;\n    }\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */\n\n#if defined(MBEDTLS_GCM_C) || \\\n    defined(MBEDTLS_CCM_C) || \\\n    defined(MBEDTLS_CHACHAPOLY_C)\n    if (mode == MBEDTLS_MODE_GCM ||\n        mode == MBEDTLS_MODE_CCM ||\n        mode == MBEDTLS_MODE_CHACHAPOLY) {\n        return MBEDTLS_SSL_MODE_AEAD;\n    }\n#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */\n\n    return MBEDTLS_SSL_MODE_STREAM;\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\nstatic mbedtls_ssl_mode_t mbedtls_ssl_get_actual_mode(\n    mbedtls_ssl_mode_t base_mode,\n    int encrypt_then_mac)\n{\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)\n    if (encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED &&\n        base_mode == MBEDTLS_SSL_MODE_CBC) {\n        return MBEDTLS_SSL_MODE_CBC_ETM;\n    }\n#else\n    (void) encrypt_then_mac;\n#endif\n    return base_mode;\n}\n\nmbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_transform(\n    const mbedtls_ssl_transform *transform)\n{\n    mbedtls_ssl_mode_t base_mode = mbedtls_ssl_get_base_mode(\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        transform->psa_alg\n#else\n        mbedtls_cipher_get_cipher_mode(&transform->cipher_ctx_enc)\n#endif\n        );\n\n    int encrypt_then_mac = 0;\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)\n    encrypt_then_mac = transform->encrypt_then_mac;\n#endif\n    return mbedtls_ssl_get_actual_mode(base_mode, encrypt_then_mac);\n}\n\nmbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite(\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)\n    int encrypt_then_mac,\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */\n    const mbedtls_ssl_ciphersuite_t *suite)\n{\n    mbedtls_ssl_mode_t base_mode = MBEDTLS_SSL_MODE_STREAM;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_status_t status;\n    psa_algorithm_t alg;\n    psa_key_type_t type;\n    size_t size;\n    status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) suite->cipher,\n                                       0, &alg, &type, &size);\n    if (status == PSA_SUCCESS) {\n        base_mode = mbedtls_ssl_get_base_mode(alg);\n    }\n#else\n    const mbedtls_cipher_info_t *cipher =\n        mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) suite->cipher);\n    if (cipher != NULL) {\n        base_mode =\n            mbedtls_ssl_get_base_mode(\n                mbedtls_cipher_info_get_mode(cipher));\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if !defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)\n    int encrypt_then_mac = 0;\n#endif\n    return mbedtls_ssl_get_actual_mode(base_mode, encrypt_then_mac);\n}\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)\n\npsa_status_t mbedtls_ssl_cipher_to_psa(mbedtls_cipher_type_t mbedtls_cipher_type,\n                                       size_t taglen,\n                                       psa_algorithm_t *alg,\n                                       psa_key_type_t *key_type,\n                                       size_t *key_size)\n{\n#if !defined(MBEDTLS_SSL_HAVE_CCM)\n    (void) taglen;\n#endif\n    switch (mbedtls_cipher_type) {\n#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CBC)\n        case MBEDTLS_CIPHER_AES_128_CBC:\n            *alg = PSA_ALG_CBC_NO_PADDING;\n            *key_type = PSA_KEY_TYPE_AES;\n            *key_size = 128;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CCM)\n        case MBEDTLS_CIPHER_AES_128_CCM:\n            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;\n            *key_type = PSA_KEY_TYPE_AES;\n            *key_size = 128;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM)\n        case MBEDTLS_CIPHER_AES_128_GCM:\n            *alg = PSA_ALG_GCM;\n            *key_type = PSA_KEY_TYPE_AES;\n            *key_size = 128;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CCM)\n        case MBEDTLS_CIPHER_AES_192_CCM:\n            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;\n            *key_type = PSA_KEY_TYPE_AES;\n            *key_size = 192;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM)\n        case MBEDTLS_CIPHER_AES_192_GCM:\n            *alg = PSA_ALG_GCM;\n            *key_type = PSA_KEY_TYPE_AES;\n            *key_size = 192;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CBC)\n        case MBEDTLS_CIPHER_AES_256_CBC:\n            *alg = PSA_ALG_CBC_NO_PADDING;\n            *key_type = PSA_KEY_TYPE_AES;\n            *key_size = 256;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CCM)\n        case MBEDTLS_CIPHER_AES_256_CCM:\n            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;\n            *key_type = PSA_KEY_TYPE_AES;\n            *key_size = 256;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM)\n        case MBEDTLS_CIPHER_AES_256_GCM:\n            *alg = PSA_ALG_GCM;\n            *key_type = PSA_KEY_TYPE_AES;\n            *key_size = 256;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CBC)\n        case MBEDTLS_CIPHER_ARIA_128_CBC:\n            *alg = PSA_ALG_CBC_NO_PADDING;\n            *key_type = PSA_KEY_TYPE_ARIA;\n            *key_size = 128;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CCM)\n        case MBEDTLS_CIPHER_ARIA_128_CCM:\n            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;\n            *key_type = PSA_KEY_TYPE_ARIA;\n            *key_size = 128;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_GCM)\n        case MBEDTLS_CIPHER_ARIA_128_GCM:\n            *alg = PSA_ALG_GCM;\n            *key_type = PSA_KEY_TYPE_ARIA;\n            *key_size = 128;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CCM)\n        case MBEDTLS_CIPHER_ARIA_192_CCM:\n            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;\n            *key_type = PSA_KEY_TYPE_ARIA;\n            *key_size = 192;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_GCM)\n        case MBEDTLS_CIPHER_ARIA_192_GCM:\n            *alg = PSA_ALG_GCM;\n            *key_type = PSA_KEY_TYPE_ARIA;\n            *key_size = 192;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CBC)\n        case MBEDTLS_CIPHER_ARIA_256_CBC:\n            *alg = PSA_ALG_CBC_NO_PADDING;\n            *key_type = PSA_KEY_TYPE_ARIA;\n            *key_size = 256;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CCM)\n        case MBEDTLS_CIPHER_ARIA_256_CCM:\n            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;\n            *key_type = PSA_KEY_TYPE_ARIA;\n            *key_size = 256;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_GCM)\n        case MBEDTLS_CIPHER_ARIA_256_GCM:\n            *alg = PSA_ALG_GCM;\n            *key_type = PSA_KEY_TYPE_ARIA;\n            *key_size = 256;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CBC)\n        case MBEDTLS_CIPHER_CAMELLIA_128_CBC:\n            *alg = PSA_ALG_CBC_NO_PADDING;\n            *key_type = PSA_KEY_TYPE_CAMELLIA;\n            *key_size = 128;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CCM)\n        case MBEDTLS_CIPHER_CAMELLIA_128_CCM:\n            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;\n            *key_type = PSA_KEY_TYPE_CAMELLIA;\n            *key_size = 128;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_GCM)\n        case MBEDTLS_CIPHER_CAMELLIA_128_GCM:\n            *alg = PSA_ALG_GCM;\n            *key_type = PSA_KEY_TYPE_CAMELLIA;\n            *key_size = 128;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CCM)\n        case MBEDTLS_CIPHER_CAMELLIA_192_CCM:\n            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;\n            *key_type = PSA_KEY_TYPE_CAMELLIA;\n            *key_size = 192;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_GCM)\n        case MBEDTLS_CIPHER_CAMELLIA_192_GCM:\n            *alg = PSA_ALG_GCM;\n            *key_type = PSA_KEY_TYPE_CAMELLIA;\n            *key_size = 192;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CBC)\n        case MBEDTLS_CIPHER_CAMELLIA_256_CBC:\n            *alg = PSA_ALG_CBC_NO_PADDING;\n            *key_type = PSA_KEY_TYPE_CAMELLIA;\n            *key_size = 256;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CCM)\n        case MBEDTLS_CIPHER_CAMELLIA_256_CCM:\n            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;\n            *key_type = PSA_KEY_TYPE_CAMELLIA;\n            *key_size = 256;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_GCM)\n        case MBEDTLS_CIPHER_CAMELLIA_256_GCM:\n            *alg = PSA_ALG_GCM;\n            *key_type = PSA_KEY_TYPE_CAMELLIA;\n            *key_size = 256;\n            break;\n#endif\n#if defined(MBEDTLS_SSL_HAVE_CHACHAPOLY)\n        case MBEDTLS_CIPHER_CHACHA20_POLY1305:\n            *alg = PSA_ALG_CHACHA20_POLY1305;\n            *key_type = PSA_KEY_TYPE_CHACHA20;\n            *key_size = 256;\n            break;\n#endif\n        case MBEDTLS_CIPHER_NULL:\n            *alg = MBEDTLS_SSL_NULL_CIPHER;\n            *key_type = 0;\n            *key_size = 0;\n            break;\n        default:\n            return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    return PSA_SUCCESS;\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)\nint mbedtls_ssl_conf_dh_param_bin(mbedtls_ssl_config *conf,\n                                  const unsigned char *dhm_P, size_t P_len,\n                                  const unsigned char *dhm_G, size_t G_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_mpi_free(&conf->dhm_P);\n    mbedtls_mpi_free(&conf->dhm_G);\n\n    if ((ret = mbedtls_mpi_read_binary(&conf->dhm_P, dhm_P, P_len)) != 0 ||\n        (ret = mbedtls_mpi_read_binary(&conf->dhm_G, dhm_G, G_len)) != 0) {\n        mbedtls_mpi_free(&conf->dhm_P);\n        mbedtls_mpi_free(&conf->dhm_G);\n        return ret;\n    }\n\n    return 0;\n}\n\nint mbedtls_ssl_conf_dh_param_ctx(mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_mpi_free(&conf->dhm_P);\n    mbedtls_mpi_free(&conf->dhm_G);\n\n    if ((ret = mbedtls_dhm_get_value(dhm_ctx, MBEDTLS_DHM_PARAM_P,\n                                     &conf->dhm_P)) != 0 ||\n        (ret = mbedtls_dhm_get_value(dhm_ctx, MBEDTLS_DHM_PARAM_G,\n                                     &conf->dhm_G)) != 0) {\n        mbedtls_mpi_free(&conf->dhm_P);\n        mbedtls_mpi_free(&conf->dhm_G);\n        return ret;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C)\n/*\n * Set the minimum length for Diffie-Hellman parameters\n */\nvoid mbedtls_ssl_conf_dhm_min_bitlen(mbedtls_ssl_config *conf,\n                                     unsigned int bitlen)\n{\n    conf->dhm_min_bitlen = bitlen;\n}\n#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n#if !defined(MBEDTLS_DEPRECATED_REMOVED) && defined(MBEDTLS_SSL_PROTO_TLS1_2)\n/*\n * Set allowed/preferred hashes for handshake signatures\n */\nvoid mbedtls_ssl_conf_sig_hashes(mbedtls_ssl_config *conf,\n                                 const int *hashes)\n{\n    conf->sig_hashes = hashes;\n}\n#endif /* !MBEDTLS_DEPRECATED_REMOVED && MBEDTLS_SSL_PROTO_TLS1_2 */\n\n/* Configure allowed signature algorithms for handshake */\nvoid mbedtls_ssl_conf_sig_algs(mbedtls_ssl_config *conf,\n                               const uint16_t *sig_algs)\n{\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n    conf->sig_hashes = NULL;\n#endif /* !MBEDTLS_DEPRECATED_REMOVED */\n    conf->sig_algs = sig_algs;\n}\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n#if defined(MBEDTLS_ECP_C)\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n/*\n * Set the allowed elliptic curves\n *\n * mbedtls_ssl_setup() takes the provided list\n * and translates it to a list of IANA TLS group identifiers,\n * stored in ssl->handshake->group_list.\n *\n */\nvoid mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf,\n                             const mbedtls_ecp_group_id *curve_list)\n{\n    conf->curve_list = curve_list;\n    conf->group_list = NULL;\n}\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n#endif /* MBEDTLS_ECP_C */\n\n/*\n * Set the allowed groups\n */\nvoid mbedtls_ssl_conf_groups(mbedtls_ssl_config *conf,\n                             const uint16_t *group_list)\n{\n#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n    conf->curve_list = NULL;\n#endif\n    conf->group_list = group_list;\n}\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n\n/* A magic value for `ssl->hostname` indicating that\n * mbedtls_ssl_set_hostname() has been called with `NULL`.\n * If mbedtls_ssl_set_hostname() has never been called on `ssl`, then\n * `ssl->hostname == NULL`. */\nstatic const char *const ssl_hostname_skip_cn_verification = \"\";\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n/** Whether mbedtls_ssl_set_hostname() has been called.\n *\n * \\param[in]   ssl     SSL context\n *\n * \\return \\c 1 if mbedtls_ssl_set_hostname() has been called on \\p ssl\n *         (including `mbedtls_ssl_set_hostname(ssl, NULL)`),\n *         otherwise \\c 0.\n */\nstatic int mbedtls_ssl_has_set_hostname_been_called(\n    const mbedtls_ssl_context *ssl)\n{\n    return ssl->hostname != NULL;\n}\n#endif\n\n/* Micro-optimization: don't export this function if it isn't needed outside\n * of this source file. */\n#if !defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\nstatic\n#endif\nconst char *mbedtls_ssl_get_hostname_pointer(const mbedtls_ssl_context *ssl)\n{\n    if (ssl->hostname == ssl_hostname_skip_cn_verification) {\n        return NULL;\n    }\n    return ssl->hostname;\n}\n\nstatic void mbedtls_ssl_free_hostname(mbedtls_ssl_context *ssl)\n{\n    if (ssl->hostname != NULL &&\n        ssl->hostname != ssl_hostname_skip_cn_verification) {\n        mbedtls_zeroize_and_free(ssl->hostname, strlen(ssl->hostname));\n    }\n    ssl->hostname = NULL;\n}\n\nint mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname)\n{\n    /* Initialize to suppress unnecessary compiler warning */\n    size_t hostname_len = 0;\n\n    /* Check if new hostname is valid before\n     * making any change to current one */\n    if (hostname != NULL) {\n        hostname_len = strlen(hostname);\n\n        if (hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n    }\n\n    /* Now it's clear that we will overwrite the old hostname,\n     * so we can free it safely */\n    mbedtls_ssl_free_hostname(ssl);\n\n    if (hostname == NULL) {\n        /* Passing NULL as hostname clears the old one, but leaves a\n         * special marker to indicate that mbedtls_ssl_set_hostname()\n         * has been called. */\n        /* ssl->hostname should be const, but isn't. We won't actually\n         * write to the buffer, so it's ok to cast away the const. */\n        ssl->hostname = (char *) ssl_hostname_skip_cn_verification;\n    } else {\n        ssl->hostname = mbedtls_calloc(1, hostname_len + 1);\n        if (ssl->hostname == NULL) {\n            /* mbedtls_ssl_set_hostname() has been called, but unsuccessfully.\n             * Leave ssl->hostname in the same state as if the function had\n             * not been called, i.e. a null pointer. */\n            return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        }\n\n        memcpy(ssl->hostname, hostname, hostname_len);\n\n        ssl->hostname[hostname_len] = '\\0';\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\nvoid mbedtls_ssl_conf_sni(mbedtls_ssl_config *conf,\n                          int (*f_sni)(void *, mbedtls_ssl_context *,\n                                       const unsigned char *, size_t),\n                          void *p_sni)\n{\n    conf->f_sni = f_sni;\n    conf->p_sni = p_sni;\n}\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n#if defined(MBEDTLS_SSL_ALPN)\nint mbedtls_ssl_conf_alpn_protocols(mbedtls_ssl_config *conf, const char **protos)\n{\n    size_t cur_len, tot_len;\n    const char **p;\n\n    /*\n     * RFC 7301 3.1: \"Empty strings MUST NOT be included and byte strings\n     * MUST NOT be truncated.\"\n     * We check lengths now rather than later.\n     */\n    tot_len = 0;\n    for (p = protos; *p != NULL; p++) {\n        cur_len = strlen(*p);\n        tot_len += cur_len;\n\n        if ((cur_len == 0) ||\n            (cur_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN) ||\n            (tot_len > MBEDTLS_SSL_MAX_ALPN_LIST_LEN)) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n    }\n\n    conf->alpn_list = protos;\n\n    return 0;\n}\n\nconst char *mbedtls_ssl_get_alpn_protocol(const mbedtls_ssl_context *ssl)\n{\n    return ssl->alpn_chosen;\n}\n#endif /* MBEDTLS_SSL_ALPN */\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\nvoid mbedtls_ssl_conf_srtp_mki_value_supported(mbedtls_ssl_config *conf,\n                                               int support_mki_value)\n{\n    conf->dtls_srtp_mki_support = support_mki_value;\n}\n\nint mbedtls_ssl_dtls_srtp_set_mki_value(mbedtls_ssl_context *ssl,\n                                        unsigned char *mki_value,\n                                        uint16_t mki_len)\n{\n    if (mki_len > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED) {\n        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    }\n\n    memcpy(ssl->dtls_srtp_info.mki_value, mki_value, mki_len);\n    ssl->dtls_srtp_info.mki_len = mki_len;\n    return 0;\n}\n\nint mbedtls_ssl_conf_dtls_srtp_protection_profiles(mbedtls_ssl_config *conf,\n                                                   const mbedtls_ssl_srtp_profile *profiles)\n{\n    const mbedtls_ssl_srtp_profile *p;\n    size_t list_size = 0;\n\n    /* check the profiles list: all entry must be valid,\n     * its size cannot be more than the total number of supported profiles, currently 4 */\n    for (p = profiles; *p != MBEDTLS_TLS_SRTP_UNSET &&\n         list_size <= MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH;\n         p++) {\n        if (mbedtls_ssl_check_srtp_profile_value(*p) != MBEDTLS_TLS_SRTP_UNSET) {\n            list_size++;\n        } else {\n            /* unsupported value, stop parsing and set the size to an error value */\n            list_size = MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH + 1;\n        }\n    }\n\n    if (list_size > MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH) {\n        conf->dtls_srtp_profile_list = NULL;\n        conf->dtls_srtp_profile_list_len = 0;\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    conf->dtls_srtp_profile_list = profiles;\n    conf->dtls_srtp_profile_list_len = list_size;\n\n    return 0;\n}\n\nvoid mbedtls_ssl_get_dtls_srtp_negotiation_result(const mbedtls_ssl_context *ssl,\n                                                  mbedtls_dtls_srtp_info *dtls_srtp_info)\n{\n    dtls_srtp_info->chosen_dtls_srtp_profile = ssl->dtls_srtp_info.chosen_dtls_srtp_profile;\n    /* do not copy the mki value if there is no chosen profile */\n    if (dtls_srtp_info->chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET) {\n        dtls_srtp_info->mki_len = 0;\n    } else {\n        dtls_srtp_info->mki_len = ssl->dtls_srtp_info.mki_len;\n        memcpy(dtls_srtp_info->mki_value, ssl->dtls_srtp_info.mki_value,\n               ssl->dtls_srtp_info.mki_len);\n    }\n}\n#endif /* MBEDTLS_SSL_DTLS_SRTP */\n\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\nvoid mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, int minor)\n{\n    conf->max_tls_version = (mbedtls_ssl_protocol_version) ((major << 8) | minor);\n}\n\nvoid mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, int major, int minor)\n{\n    conf->min_tls_version = (mbedtls_ssl_protocol_version) ((major << 8) | minor);\n}\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n\n#if defined(MBEDTLS_SSL_SRV_C)\nvoid mbedtls_ssl_conf_cert_req_ca_list(mbedtls_ssl_config *conf,\n                                       char cert_req_ca_list)\n{\n    conf->cert_req_ca_list = cert_req_ca_list;\n}\n#endif\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\nvoid mbedtls_ssl_conf_encrypt_then_mac(mbedtls_ssl_config *conf, char etm)\n{\n    conf->encrypt_then_mac = etm;\n}\n#endif\n\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\nvoid mbedtls_ssl_conf_extended_master_secret(mbedtls_ssl_config *conf, char ems)\n{\n    conf->extended_ms = ems;\n}\n#endif\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\nint mbedtls_ssl_conf_max_frag_len(mbedtls_ssl_config *conf, unsigned char mfl_code)\n{\n    if (mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ||\n        ssl_mfl_code_to_length(mfl_code) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    conf->mfl_code = mfl_code;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */\n\nvoid mbedtls_ssl_conf_legacy_renegotiation(mbedtls_ssl_config *conf, int allow_legacy)\n{\n    conf->allow_legacy_renegotiation = allow_legacy;\n}\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\nvoid mbedtls_ssl_conf_renegotiation(mbedtls_ssl_config *conf, int renegotiation)\n{\n    conf->disable_renegotiation = renegotiation;\n}\n\nvoid mbedtls_ssl_conf_renegotiation_enforced(mbedtls_ssl_config *conf, int max_records)\n{\n    conf->renego_max_records = max_records;\n}\n\nvoid mbedtls_ssl_conf_renegotiation_period(mbedtls_ssl_config *conf,\n                                           const unsigned char period[8])\n{\n    memcpy(conf->renego_period, period, 8);\n}\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n#if defined(MBEDTLS_SSL_CLI_C)\n\nvoid mbedtls_ssl_conf_session_tickets(mbedtls_ssl_config *conf, int use_tickets)\n{\n    conf->session_tickets &= ~MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_MASK;\n    conf->session_tickets |= (use_tickets != 0) <<\n                             MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_BIT;\n}\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\nvoid mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(\n    mbedtls_ssl_config *conf, int signal_new_session_tickets)\n{\n    conf->session_tickets &= ~MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_MASK;\n    conf->session_tickets |= (signal_new_session_tickets != 0) <<\n                             MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_BIT;\n}\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n#endif /* MBEDTLS_SSL_CLI_C */\n\n#if defined(MBEDTLS_SSL_SRV_C)\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)\nvoid mbedtls_ssl_conf_new_session_tickets(mbedtls_ssl_config *conf,\n                                          uint16_t num_tickets)\n{\n    conf->new_session_tickets_count = num_tickets;\n}\n#endif\n\nvoid mbedtls_ssl_conf_session_tickets_cb(mbedtls_ssl_config *conf,\n                                         mbedtls_ssl_ticket_write_t *f_ticket_write,\n                                         mbedtls_ssl_ticket_parse_t *f_ticket_parse,\n                                         void *p_ticket)\n{\n    conf->f_ticket_write = f_ticket_write;\n    conf->f_ticket_parse = f_ticket_parse;\n    conf->p_ticket       = p_ticket;\n}\n#endif\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\nvoid mbedtls_ssl_set_export_keys_cb(mbedtls_ssl_context *ssl,\n                                    mbedtls_ssl_export_keys_t *f_export_keys,\n                                    void *p_export_keys)\n{\n    ssl->f_export_keys = f_export_keys;\n    ssl->p_export_keys = p_export_keys;\n}\n\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)\nvoid mbedtls_ssl_conf_async_private_cb(\n    mbedtls_ssl_config *conf,\n    mbedtls_ssl_async_sign_t *f_async_sign,\n    mbedtls_ssl_async_decrypt_t *f_async_decrypt,\n    mbedtls_ssl_async_resume_t *f_async_resume,\n    mbedtls_ssl_async_cancel_t *f_async_cancel,\n    void *async_config_data)\n{\n    conf->f_async_sign_start = f_async_sign;\n    conf->f_async_decrypt_start = f_async_decrypt;\n    conf->f_async_resume = f_async_resume;\n    conf->f_async_cancel = f_async_cancel;\n    conf->p_async_config_data = async_config_data;\n}\n\nvoid *mbedtls_ssl_conf_get_async_config_data(const mbedtls_ssl_config *conf)\n{\n    return conf->p_async_config_data;\n}\n\nvoid *mbedtls_ssl_get_async_operation_data(const mbedtls_ssl_context *ssl)\n{\n    if (ssl->handshake == NULL) {\n        return NULL;\n    } else {\n        return ssl->handshake->user_async_ctx;\n    }\n}\n\nvoid mbedtls_ssl_set_async_operation_data(mbedtls_ssl_context *ssl,\n                                          void *ctx)\n{\n    if (ssl->handshake != NULL) {\n        ssl->handshake->user_async_ctx = ctx;\n    }\n}\n#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */\n\n/*\n * SSL get accessors\n */\nuint32_t mbedtls_ssl_get_verify_result(const mbedtls_ssl_context *ssl)\n{\n    if (ssl->session != NULL) {\n        return ssl->session->verify_result;\n    }\n\n    if (ssl->session_negotiate != NULL) {\n        return ssl->session_negotiate->verify_result;\n    }\n\n    return 0xFFFFFFFF;\n}\n\nint mbedtls_ssl_get_ciphersuite_id_from_ssl(const mbedtls_ssl_context *ssl)\n{\n    if (ssl == NULL || ssl->session == NULL) {\n        return 0;\n    }\n\n    return ssl->session->ciphersuite;\n}\n\nconst char *mbedtls_ssl_get_ciphersuite(const mbedtls_ssl_context *ssl)\n{\n    if (ssl == NULL || ssl->session == NULL) {\n        return NULL;\n    }\n\n    return mbedtls_ssl_get_ciphersuite_name(ssl->session->ciphersuite);\n}\n\nconst char *mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl)\n{\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        switch (ssl->tls_version) {\n            case MBEDTLS_SSL_VERSION_TLS1_2:\n                return \"DTLSv1.2\";\n            default:\n                return \"unknown (DTLS)\";\n        }\n    }\n#endif\n\n    switch (ssl->tls_version) {\n        case MBEDTLS_SSL_VERSION_TLS1_2:\n            return \"TLSv1.2\";\n        case MBEDTLS_SSL_VERSION_TLS1_3:\n            return \"TLSv1.3\";\n        default:\n            return \"unknown\";\n    }\n}\n\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n\nsize_t mbedtls_ssl_get_output_record_size_limit(const mbedtls_ssl_context *ssl)\n{\n    const size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;\n    size_t record_size_limit = max_len;\n\n    if (ssl->session != NULL &&\n        ssl->session->record_size_limit >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN &&\n        ssl->session->record_size_limit < max_len) {\n        record_size_limit = ssl->session->record_size_limit;\n    }\n\n    // TODO: this is currently untested\n    /* During a handshake, use the value being negotiated */\n    if (ssl->session_negotiate != NULL &&\n        ssl->session_negotiate->record_size_limit >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN &&\n        ssl->session_negotiate->record_size_limit < max_len) {\n        record_size_limit = ssl->session_negotiate->record_size_limit;\n    }\n\n    return record_size_limit;\n}\n#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\nsize_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl)\n{\n    size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN;\n    size_t read_mfl;\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    /* Use the configured MFL for the client if we're past SERVER_HELLO_DONE */\n    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&\n        ssl->state >= MBEDTLS_SSL_SERVER_HELLO_DONE) {\n        return ssl_mfl_code_to_length(ssl->conf->mfl_code);\n    }\n#endif\n\n    /* Check if a smaller max length was negotiated */\n    if (ssl->session_out != NULL) {\n        read_mfl = ssl_mfl_code_to_length(ssl->session_out->mfl_code);\n        if (read_mfl < max_len) {\n            max_len = read_mfl;\n        }\n    }\n\n    /* During a handshake, use the value being negotiated */\n    if (ssl->session_negotiate != NULL) {\n        read_mfl = ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code);\n        if (read_mfl < max_len) {\n            max_len = read_mfl;\n        }\n    }\n\n    return max_len;\n}\n\nsize_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl)\n{\n    size_t max_len;\n\n    /*\n     * Assume mfl_code is correct since it was checked when set\n     */\n    max_len = ssl_mfl_code_to_length(ssl->conf->mfl_code);\n\n    /* Check if a smaller max length was negotiated */\n    if (ssl->session_out != NULL &&\n        ssl_mfl_code_to_length(ssl->session_out->mfl_code) < max_len) {\n        max_len = ssl_mfl_code_to_length(ssl->session_out->mfl_code);\n    }\n\n    /* During a handshake, use the value being negotiated */\n    if (ssl->session_negotiate != NULL &&\n        ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code) < max_len) {\n        max_len = ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code);\n    }\n\n    return max_len;\n}\n#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\nsize_t mbedtls_ssl_get_current_mtu(const mbedtls_ssl_context *ssl)\n{\n    /* Return unlimited mtu for client hello messages to avoid fragmentation. */\n    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&\n        (ssl->state == MBEDTLS_SSL_CLIENT_HELLO ||\n         ssl->state == MBEDTLS_SSL_SERVER_HELLO)) {\n        return 0;\n    }\n\n    if (ssl->handshake == NULL || ssl->handshake->mtu == 0) {\n        return ssl->mtu;\n    }\n\n    if (ssl->mtu == 0) {\n        return ssl->handshake->mtu;\n    }\n\n    return ssl->mtu < ssl->handshake->mtu ?\n           ssl->mtu : ssl->handshake->mtu;\n}\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\nint mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl)\n{\n    size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;\n\n#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \\\n    !defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) && \\\n    !defined(MBEDTLS_SSL_PROTO_DTLS)\n    (void) ssl;\n#endif\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n    const size_t mfl = mbedtls_ssl_get_output_max_frag_len(ssl);\n\n    if (max_len > mfl) {\n        max_len = mfl;\n    }\n#endif\n\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n    const size_t record_size_limit = mbedtls_ssl_get_output_record_size_limit(ssl);\n\n    if (max_len > record_size_limit) {\n        max_len = record_size_limit;\n    }\n#endif\n\n    if (ssl->transform_out != NULL &&\n        ssl->transform_out->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {\n        /*\n         * In TLS 1.3 case, when records are protected, `max_len` as computed\n         * above is the maximum length of the TLSInnerPlaintext structure that\n         * along the plaintext payload contains the inner content type (one byte)\n         * and some zero padding. Given the algorithm used for padding\n         * in mbedtls_ssl_encrypt_buf(), compute the maximum length for\n         * the plaintext payload. Round down to a multiple of\n         * MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY and\n         * subtract 1.\n         */\n        max_len = ((max_len / MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY) *\n                   MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY) - 1;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (mbedtls_ssl_get_current_mtu(ssl) != 0) {\n        const size_t mtu = mbedtls_ssl_get_current_mtu(ssl);\n        const int ret = mbedtls_ssl_get_record_expansion(ssl);\n        const size_t overhead = (size_t) ret;\n\n        if (ret < 0) {\n            return ret;\n        }\n\n        if (mtu <= overhead) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"MTU too low for record expansion\"));\n            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n        }\n\n        if (max_len > mtu - overhead) {\n            max_len = mtu - overhead;\n        }\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) &&        \\\n    !defined(MBEDTLS_SSL_PROTO_DTLS) &&                 \\\n    !defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n    ((void) ssl);\n#endif\n\n    return (int) max_len;\n}\n\nint mbedtls_ssl_get_max_in_record_payload(const mbedtls_ssl_context *ssl)\n{\n    size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN;\n\n#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n    (void) ssl;\n#endif\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n    const size_t mfl = mbedtls_ssl_get_input_max_frag_len(ssl);\n\n    if (max_len > mfl) {\n        max_len = mfl;\n    }\n#endif\n\n    return (int) max_len;\n}\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\nconst mbedtls_x509_crt *mbedtls_ssl_get_peer_cert(const mbedtls_ssl_context *ssl)\n{\n    if (ssl == NULL || ssl->session == NULL) {\n        return NULL;\n    }\n\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    return ssl->session->peer_cert;\n#else\n    return NULL;\n#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n}\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n#if defined(MBEDTLS_SSL_CLI_C)\nint mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl,\n                            mbedtls_ssl_session *dst)\n{\n    int ret;\n\n    if (ssl == NULL ||\n        dst == NULL ||\n        ssl->session == NULL ||\n        ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    /* Since Mbed TLS 3.0, mbedtls_ssl_get_session() is no longer\n     * idempotent: Each session can only be exported once.\n     *\n     * (This is in preparation for TLS 1.3 support where we will\n     * need the ability to export multiple sessions (aka tickets),\n     * which will be achieved by calling mbedtls_ssl_get_session()\n     * multiple times until it fails.)\n     *\n     * Check whether we have already exported the current session,\n     * and fail if so.\n     */\n    if (ssl->session->exported == 1) {\n        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    }\n\n    ret = mbedtls_ssl_session_copy(dst, ssl->session);\n    if (ret != 0) {\n        return ret;\n    }\n\n    /* Remember that we've exported the session. */\n    ssl->session->exported = 1;\n    return 0;\n}\n#endif /* MBEDTLS_SSL_CLI_C */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n\n/* Serialization of TLS 1.2 sessions\n *\n * For more detail, see the description of ssl_session_save().\n */\nstatic size_t ssl_tls12_session_save(const mbedtls_ssl_session *session,\n                                     unsigned char *buf,\n                                     size_t buf_len)\n{\n    unsigned char *p = buf;\n    size_t used = 0;\n\n#if defined(MBEDTLS_HAVE_TIME)\n    uint64_t start;\n#endif\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    size_t cert_len;\n#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n    /*\n     * Time\n     */\n#if defined(MBEDTLS_HAVE_TIME)\n    used += 8;\n\n    if (used <= buf_len) {\n        start = (uint64_t) session->start;\n\n        MBEDTLS_PUT_UINT64_BE(start, p, 0);\n        p += 8;\n    }\n#endif /* MBEDTLS_HAVE_TIME */\n\n    /*\n     * Basic mandatory fields\n     */\n    used += 1 /* id_len */\n            + sizeof(session->id)\n            + sizeof(session->master)\n            + 4; /* verify_result */\n\n    if (used <= buf_len) {\n        *p++ = MBEDTLS_BYTE_0(session->id_len);\n        memcpy(p, session->id, 32);\n        p += 32;\n\n        memcpy(p, session->master, 48);\n        p += 48;\n\n        MBEDTLS_PUT_UINT32_BE(session->verify_result, p, 0);\n        p += 4;\n    }\n\n    /*\n     * Peer's end-entity certificate\n     */\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    if (session->peer_cert == NULL) {\n        cert_len = 0;\n    } else {\n        cert_len = session->peer_cert->raw.len;\n    }\n\n    used += 3 + cert_len;\n\n    if (used <= buf_len) {\n        *p++ = MBEDTLS_BYTE_2(cert_len);\n        *p++ = MBEDTLS_BYTE_1(cert_len);\n        *p++ = MBEDTLS_BYTE_0(cert_len);\n\n        if (session->peer_cert != NULL) {\n            memcpy(p, session->peer_cert->raw.p, cert_len);\n            p += cert_len;\n        }\n    }\n#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n    if (session->peer_cert_digest != NULL) {\n        used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len;\n        if (used <= buf_len) {\n            *p++ = (unsigned char) session->peer_cert_digest_type;\n            *p++ = (unsigned char) session->peer_cert_digest_len;\n            memcpy(p, session->peer_cert_digest,\n                   session->peer_cert_digest_len);\n            p += session->peer_cert_digest_len;\n        }\n    } else {\n        used += 2;\n        if (used <= buf_len) {\n            *p++ = (unsigned char) MBEDTLS_MD_NONE;\n            *p++ = 0;\n        }\n    }\n#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n    /*\n     * Session ticket if any, plus associated data\n     */\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n#if defined(MBEDTLS_SSL_CLI_C)\n    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {\n        used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */\n\n        if (used <= buf_len) {\n            *p++ = MBEDTLS_BYTE_2(session->ticket_len);\n            *p++ = MBEDTLS_BYTE_1(session->ticket_len);\n            *p++ = MBEDTLS_BYTE_0(session->ticket_len);\n\n            if (session->ticket != NULL) {\n                memcpy(p, session->ticket, session->ticket_len);\n                p += session->ticket_len;\n            }\n\n            MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0);\n            p += 4;\n        }\n    }\n#endif /* MBEDTLS_SSL_CLI_C */\n#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)\n    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {\n        used += 8;\n\n        if (used <= buf_len) {\n            MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0);\n            p += 8;\n        }\n    }\n#endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_SRV_C */\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n    /*\n     * Misc extension-related info\n     */\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n    used += 1;\n\n    if (used <= buf_len) {\n        *p++ = session->mfl_code;\n    }\n#endif\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n    used += 1;\n\n    if (used <= buf_len) {\n        *p++ = MBEDTLS_BYTE_0(session->encrypt_then_mac);\n    }\n#endif\n\n    return used;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls12_session_load(mbedtls_ssl_session *session,\n                                  const unsigned char *buf,\n                                  size_t len)\n{\n#if defined(MBEDTLS_HAVE_TIME)\n    uint64_t start;\n#endif\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    size_t cert_len;\n#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n    const unsigned char *p = buf;\n    const unsigned char * const end = buf + len;\n\n    /*\n     * Time\n     */\n#if defined(MBEDTLS_HAVE_TIME)\n    if (8 > (size_t) (end - p)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    start = MBEDTLS_GET_UINT64_BE(p, 0);\n    p += 8;\n\n    session->start = (mbedtls_time_t) start;\n#endif /* MBEDTLS_HAVE_TIME */\n\n    /*\n     * Basic mandatory fields\n     */\n    if (1 + 32 + 48 + 4 > (size_t) (end - p)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    session->id_len = *p++;\n    memcpy(session->id, p, 32);\n    p += 32;\n\n    memcpy(session->master, p, 48);\n    p += 48;\n\n    session->verify_result = MBEDTLS_GET_UINT32_BE(p, 0);\n    p += 4;\n\n    /* Immediately clear invalid pointer values that have been read, in case\n     * we exit early before we replaced them with valid ones. */\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    session->peer_cert = NULL;\n#else\n    session->peer_cert_digest = NULL;\n#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)\n    session->ticket = NULL;\n#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */\n\n    /*\n     * Peer certificate\n     */\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    /* Deserialize CRT from the end of the ticket. */\n    if (3 > (size_t) (end - p)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    cert_len = MBEDTLS_GET_UINT24_BE(p, 0);\n    p += 3;\n\n    if (cert_len != 0) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n        if (cert_len > (size_t) (end - p)) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        session->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));\n\n        if (session->peer_cert == NULL) {\n            return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        }\n\n        mbedtls_x509_crt_init(session->peer_cert);\n\n        if ((ret = mbedtls_x509_crt_parse_der(session->peer_cert,\n                                              p, cert_len)) != 0) {\n            mbedtls_x509_crt_free(session->peer_cert);\n            mbedtls_free(session->peer_cert);\n            session->peer_cert = NULL;\n            return ret;\n        }\n\n        p += cert_len;\n    }\n#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n    /* Deserialize CRT digest from the end of the ticket. */\n    if (2 > (size_t) (end - p)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    session->peer_cert_digest_type = (mbedtls_md_type_t) *p++;\n    session->peer_cert_digest_len  = (size_t) *p++;\n\n    if (session->peer_cert_digest_len != 0) {\n        const mbedtls_md_info_t *md_info =\n            mbedtls_md_info_from_type(session->peer_cert_digest_type);\n        if (md_info == NULL) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n        if (session->peer_cert_digest_len != mbedtls_md_get_size(md_info)) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        if (session->peer_cert_digest_len > (size_t) (end - p)) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        session->peer_cert_digest =\n            mbedtls_calloc(1, session->peer_cert_digest_len);\n        if (session->peer_cert_digest == NULL) {\n            return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        }\n\n        memcpy(session->peer_cert_digest, p,\n               session->peer_cert_digest_len);\n        p += session->peer_cert_digest_len;\n    }\n#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n    /*\n     * Session ticket and associated data\n     */\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n#if defined(MBEDTLS_SSL_CLI_C)\n    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {\n        if (3 > (size_t) (end - p)) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        session->ticket_len = MBEDTLS_GET_UINT24_BE(p, 0);\n        p += 3;\n\n        if (session->ticket_len != 0) {\n            if (session->ticket_len > (size_t) (end - p)) {\n                return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n            }\n\n            session->ticket = mbedtls_calloc(1, session->ticket_len);\n            if (session->ticket == NULL) {\n                return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n            }\n\n            memcpy(session->ticket, p, session->ticket_len);\n            p += session->ticket_len;\n        }\n\n        if (4 > (size_t) (end - p)) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0);\n        p += 4;\n    }\n#endif /* MBEDTLS_SSL_CLI_C */\n#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)\n    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {\n        if (8 > (size_t) (end - p)) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n        session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0);\n        p += 8;\n    }\n#endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_SRV_C */\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n    /*\n     * Misc extension-related info\n     */\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n    if (1 > (size_t) (end - p)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    session->mfl_code = *p++;\n#endif\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n    if (1 > (size_t) (end - p)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    session->encrypt_then_mac = *p++;\n#endif\n\n    /* Done, should have consumed entire buffer */\n    if (p != end) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    return 0;\n}\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n/* Serialization of TLS 1.3 sessions:\n *\n * For more detail, see the description of ssl_session_save().\n */\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_session_save(const mbedtls_ssl_session *session,\n                                  unsigned char *buf,\n                                  size_t buf_len,\n                                  size_t *olen)\n{\n    unsigned char *p = buf;\n#if defined(MBEDTLS_SSL_CLI_C) && \\\n    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    size_t hostname_len = (session->hostname == NULL) ?\n                          0 : strlen(session->hostname) + 1;\n#endif\n\n#if defined(MBEDTLS_SSL_SRV_C) && \\\n    defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)\n    const size_t alpn_len = (session->ticket_alpn == NULL) ?\n                            0 : strlen(session->ticket_alpn) + 1;\n#endif\n    size_t needed =   4  /* ticket_age_add */\n                    + 1  /* ticket_flags */\n                    + 1; /* resumption_key length */\n\n    *olen = 0;\n\n    if (session->resumption_key_len > MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    needed += session->resumption_key_len;  /* resumption_key */\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    needed += 4;                            /* max_early_data_size */\n#endif\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n    needed += 2;                            /* record_size_limit */\n#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */\n\n#if defined(MBEDTLS_HAVE_TIME)\n    needed += 8; /* ticket_creation_time or ticket_reception_time */\n#endif\n\n#if defined(MBEDTLS_SSL_SRV_C)\n    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {\n#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)\n        needed +=   2                         /* alpn_len */\n                  + alpn_len;                 /* alpn */\n#endif\n    }\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_SSL_CLI_C)\n    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n        needed +=  2                        /* hostname_len */\n                  + hostname_len;           /* hostname */\n#endif\n\n        needed +=   4                       /* ticket_lifetime */\n                  + 2;                      /* ticket_len */\n\n        /* Check size_t overflow */\n        if (session->ticket_len > SIZE_MAX - needed) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        needed += session->ticket_len;      /* ticket */\n    }\n#endif /* MBEDTLS_SSL_CLI_C */\n\n    *olen = needed;\n    if (needed > buf_len) {\n        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n    }\n\n    MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 0);\n    p[4] = session->ticket_flags;\n\n    /* save resumption_key */\n    p[5] = session->resumption_key_len;\n    p += 6;\n    memcpy(p, session->resumption_key, session->resumption_key_len);\n    p += session->resumption_key_len;\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    MBEDTLS_PUT_UINT32_BE(session->max_early_data_size, p, 0);\n    p += 4;\n#endif\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n    MBEDTLS_PUT_UINT16_BE(session->record_size_limit, p, 0);\n    p += 2;\n#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */\n\n#if defined(MBEDTLS_SSL_SRV_C)\n    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {\n#if defined(MBEDTLS_HAVE_TIME)\n        MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0);\n        p += 8;\n#endif /* MBEDTLS_HAVE_TIME */\n\n#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)\n        MBEDTLS_PUT_UINT16_BE(alpn_len, p, 0);\n        p += 2;\n\n        if (alpn_len > 0) {\n            /* save chosen alpn */\n            memcpy(p, session->ticket_alpn, alpn_len);\n            p += alpn_len;\n        }\n#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */\n    }\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_SSL_CLI_C)\n    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n        MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0);\n        p += 2;\n        if (hostname_len > 0) {\n            /* save host name */\n            memcpy(p, session->hostname, hostname_len);\n            p += hostname_len;\n        }\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n#if defined(MBEDTLS_HAVE_TIME)\n        MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_reception_time, p, 0);\n        p += 8;\n#endif\n        MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0);\n        p += 4;\n\n        MBEDTLS_PUT_UINT16_BE(session->ticket_len, p, 0);\n        p += 2;\n\n        if (session->ticket != NULL && session->ticket_len > 0) {\n            memcpy(p, session->ticket, session->ticket_len);\n            p += session->ticket_len;\n        }\n    }\n#endif /* MBEDTLS_SSL_CLI_C */\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_session_load(mbedtls_ssl_session *session,\n                                  const unsigned char *buf,\n                                  size_t len)\n{\n    const unsigned char *p = buf;\n    const unsigned char *end = buf + len;\n\n    if (end - p < 6) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 0);\n    session->ticket_flags = p[4];\n\n    /* load resumption_key */\n    session->resumption_key_len = p[5];\n    p += 6;\n\n    if (end - p < session->resumption_key_len) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if (sizeof(session->resumption_key) < session->resumption_key_len) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    memcpy(session->resumption_key, p, session->resumption_key_len);\n    p += session->resumption_key_len;\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    if (end - p < 4) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    session->max_early_data_size = MBEDTLS_GET_UINT32_BE(p, 0);\n    p += 4;\n#endif\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n    if (end - p < 2) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    session->record_size_limit = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */\n\n#if  defined(MBEDTLS_SSL_SRV_C)\n    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {\n#if defined(MBEDTLS_HAVE_TIME)\n        if (end - p < 8) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n        session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0);\n        p += 8;\n#endif /* MBEDTLS_HAVE_TIME */\n\n#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)\n        size_t alpn_len;\n\n        if (end - p < 2) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        alpn_len = MBEDTLS_GET_UINT16_BE(p, 0);\n        p += 2;\n\n        if (end - p < (long int) alpn_len) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        if (alpn_len > 0) {\n            int ret = mbedtls_ssl_session_set_ticket_alpn(session, (char *) p);\n            if (ret != 0) {\n                return ret;\n            }\n            p += alpn_len;\n        }\n#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */\n    }\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_SSL_CLI_C)\n    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n        size_t hostname_len;\n        /* load host name */\n        if (end - p < 2) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n        hostname_len = MBEDTLS_GET_UINT16_BE(p, 0);\n        p += 2;\n\n        if (end - p < (long int) hostname_len) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n        if (hostname_len > 0) {\n            session->hostname = mbedtls_calloc(1, hostname_len);\n            if (session->hostname == NULL) {\n                return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n            }\n            memcpy(session->hostname, p, hostname_len);\n            p += hostname_len;\n        }\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n#if defined(MBEDTLS_HAVE_TIME)\n        if (end - p < 8) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n        session->ticket_reception_time = MBEDTLS_GET_UINT64_BE(p, 0);\n        p += 8;\n#endif\n        if (end - p < 4) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n        session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0);\n        p += 4;\n\n        if (end - p <  2) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n        session->ticket_len = MBEDTLS_GET_UINT16_BE(p, 0);\n        p += 2;\n\n        if (end - p < (long int) session->ticket_len) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n        if (session->ticket_len > 0) {\n            session->ticket = mbedtls_calloc(1, session->ticket_len);\n            if (session->ticket == NULL) {\n                return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n            }\n            memcpy(session->ticket, p, session->ticket_len);\n            p += session->ticket_len;\n        }\n    }\n#endif /* MBEDTLS_SSL_CLI_C */\n\n    return 0;\n\n}\n#else /* MBEDTLS_SSL_SESSION_TICKETS */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_session_save(const mbedtls_ssl_session *session,\n                                  unsigned char *buf,\n                                  size_t buf_len,\n                                  size_t *olen)\n{\n    ((void) session);\n    ((void) buf);\n    ((void) buf_len);\n    *olen = 0;\n    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n}\n\nstatic int ssl_tls13_session_load(const mbedtls_ssl_session *session,\n                                  const unsigned char *buf,\n                                  size_t buf_len)\n{\n    ((void) session);\n    ((void) buf);\n    ((void) buf_len);\n    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n}\n#endif /* !MBEDTLS_SSL_SESSION_TICKETS */\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n/*\n * Define ticket header determining Mbed TLS version\n * and structure of the ticket.\n */\n\n/*\n * Define bitflag determining compile-time settings influencing\n * structure of serialized SSL sessions.\n */\n\n#if defined(MBEDTLS_HAVE_TIME)\n#define SSL_SERIALIZED_SESSION_CONFIG_TIME 1\n#else\n#define SSL_SERIALIZED_SESSION_CONFIG_TIME 0\n#endif /* MBEDTLS_HAVE_TIME */\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n#define SSL_SERIALIZED_SESSION_CONFIG_CRT 1\n#else\n#define SSL_SERIALIZED_SESSION_CONFIG_CRT 0\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT 1\n#else\n#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT 0\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS)\n#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 1\n#else\n#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 0\n#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SESSION_TICKETS */\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n#define SSL_SERIALIZED_SESSION_CONFIG_MFL 1\n#else\n#define SSL_SERIALIZED_SESSION_CONFIG_MFL 0\n#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n#define SSL_SERIALIZED_SESSION_CONFIG_ETM 1\n#else\n#define SSL_SERIALIZED_SESSION_CONFIG_ETM 0\n#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 1\n#else\n#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n#define SSL_SERIALIZED_SESSION_CONFIG_SNI 1\n#else\n#define SSL_SERIALIZED_SESSION_CONFIG_SNI 0\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n#define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA 1\n#else\n#define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA 0\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n#define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE 1\n#else\n#define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE 0\n#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */\n\n#if defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C) && \\\n    defined(MBEDTLS_SSL_EARLY_DATA)\n#define SSL_SERIALIZED_SESSION_CONFIG_ALPN 1\n#else\n#define SSL_SERIALIZED_SESSION_CONFIG_ALPN 0\n#endif /* MBEDTLS_SSL_ALPN */\n\n#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT          0\n#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT           1\n#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2\n#define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT           3\n#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT           4\n#define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT        5\n#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT_BIT 6\n#define SSL_SERIALIZED_SESSION_CONFIG_SNI_BIT           7\n#define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT    8\n#define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT   9\n#define SSL_SERIALIZED_SESSION_CONFIG_ALPN_BIT          10\n\n#define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG                           \\\n    ((uint16_t) (                                                      \\\n         (SSL_SERIALIZED_SESSION_CONFIG_TIME << SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT) | \\\n         (SSL_SERIALIZED_SESSION_CONFIG_CRT << SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT) | \\\n         (SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET << \\\n             SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT) | \\\n         (SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT) | \\\n         (SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT) | \\\n         (SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT) | \\\n         (SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT << \\\n             SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT_BIT) | \\\n         (SSL_SERIALIZED_SESSION_CONFIG_SNI << SSL_SERIALIZED_SESSION_CONFIG_SNI_BIT) | \\\n         (SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA << \\\n             SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT) | \\\n         (SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE << \\\n             SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT) | \\\n         (SSL_SERIALIZED_SESSION_CONFIG_ALPN << \\\n             SSL_SERIALIZED_SESSION_CONFIG_ALPN_BIT)))\n\nstatic const unsigned char ssl_serialized_session_header[] = {\n    MBEDTLS_VERSION_MAJOR,\n    MBEDTLS_VERSION_MINOR,\n    MBEDTLS_VERSION_PATCH,\n    MBEDTLS_BYTE_1(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG),\n    MBEDTLS_BYTE_0(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG),\n};\n\n/*\n * Serialize a session in the following format:\n * (in the presentation language of TLS, RFC 8446 section 3)\n *\n * TLS 1.2 session:\n *\n * struct {\n * #if defined(MBEDTLS_SSL_SESSION_TICKETS)\n *    opaque ticket<0..2^24-1>;       // length 0 means no ticket\n *    uint32 ticket_lifetime;\n * #endif\n * } ClientOnlyData;\n *\n * struct {\n * #if defined(MBEDTLS_HAVE_TIME)\n *    uint64 start_time;\n * #endif\n *     uint8 session_id_len;           // at most 32\n *     opaque session_id[32];\n *     opaque master[48];              // fixed length in the standard\n *     uint32 verify_result;\n * #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n *    opaque peer_cert<0..2^24-1>;    // length 0 means no peer cert\n * #else\n *    uint8 peer_cert_digest_type;\n *    opaque peer_cert_digest<0..2^8-1>\n * #endif\n *     select (endpoint) {\n *         case client: ClientOnlyData;\n *         case server: uint64 ticket_creation_time;\n *     };\n * #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n *    uint8 mfl_code;                 // up to 255 according to standard\n * #endif\n * #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n *    uint8 encrypt_then_mac;         // 0 or 1\n * #endif\n * } serialized_session_tls12;\n *\n *\n * TLS 1.3 Session:\n *\n * struct {\n * #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n *    opaque hostname<0..2^16-1>;\n * #endif\n * #if defined(MBEDTLS_HAVE_TIME)\n *    uint64 ticket_reception_time;\n * #endif\n *    uint32 ticket_lifetime;\n *    opaque ticket<1..2^16-1>;\n * } ClientOnlyData;\n *\n * struct {\n *    uint32 ticket_age_add;\n *    uint8 ticket_flags;\n *    opaque resumption_key<0..255>;\n * #if defined(MBEDTLS_SSL_EARLY_DATA)\n *    uint32 max_early_data_size;\n * #endif\n * #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n *    uint16 record_size_limit;\n * #endif\n *    select ( endpoint ) {\n *         case client: ClientOnlyData;\n *         case server:\n * #if defined(MBEDTLS_HAVE_TIME)\n *                      uint64 ticket_creation_time;\n * #endif\n * #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)\n *                      opaque ticket_alpn<0..256>;\n * #endif\n *     };\n * } serialized_session_tls13;\n *\n *\n * SSL session:\n *\n * struct {\n *\n *    opaque mbedtls_version[3];   // library version: major, minor, patch\n *    opaque session_format[2];    // library-version specific 16-bit field\n *                                 // determining the format of the remaining\n *                                 // serialized data.\n *\n *          Note: When updating the format, remember to keep\n *          these version+format bytes.\n *\n *                                 // In this version, `session_format` determines\n *                                 // the setting of those compile-time\n *                                 // configuration options which influence\n *                                 // the structure of mbedtls_ssl_session.\n *\n *    uint8_t minor_ver;           // Protocol minor version. Possible values:\n *                                 // - TLS 1.2 (0x0303)\n *                                 // - TLS 1.3 (0x0304)\n *    uint8_t endpoint;\n *    uint16_t ciphersuite;\n *\n *    select (serialized_session.tls_version) {\n *\n *      case MBEDTLS_SSL_VERSION_TLS1_2:\n *        serialized_session_tls12 data;\n *      case MBEDTLS_SSL_VERSION_TLS1_3:\n *        serialized_session_tls13 data;\n *\n *   };\n *\n * } serialized_session;\n *\n */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_session_save(const mbedtls_ssl_session *session,\n                            unsigned char omit_header,\n                            unsigned char *buf,\n                            size_t buf_len,\n                            size_t *olen)\n{\n    unsigned char *p = buf;\n    size_t used = 0;\n    size_t remaining_len;\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    size_t out_len;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n#endif\n    if (session == NULL) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    if (!omit_header) {\n        /*\n         * Add Mbed TLS version identifier\n         */\n        used += sizeof(ssl_serialized_session_header);\n\n        if (used <= buf_len) {\n            memcpy(p, ssl_serialized_session_header,\n                   sizeof(ssl_serialized_session_header));\n            p += sizeof(ssl_serialized_session_header);\n        }\n    }\n\n    /*\n     * TLS version identifier, endpoint, ciphersuite\n     */\n    used += 1    /* TLS version */\n            + 1  /* endpoint */\n            + 2; /* ciphersuite */\n    if (used <= buf_len) {\n        *p++ = MBEDTLS_BYTE_0(session->tls_version);\n        *p++ = session->endpoint;\n        MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 0);\n        p += 2;\n    }\n\n    /* Forward to version-specific serialization routine. */\n    remaining_len = (buf_len >= used) ? buf_len - used : 0;\n    switch (session->tls_version) {\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        case MBEDTLS_SSL_VERSION_TLS1_2:\n            used += ssl_tls12_session_save(session, p, remaining_len);\n            break;\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n        case MBEDTLS_SSL_VERSION_TLS1_3:\n            ret = ssl_tls13_session_save(session, p, remaining_len, &out_len);\n            if (ret != 0 && ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) {\n                return ret;\n            }\n            used += out_len;\n            break;\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n        default:\n            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    }\n\n    *olen = used;\n    if (used > buf_len) {\n        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n    }\n\n    return 0;\n}\n\n/*\n * Public wrapper for ssl_session_save()\n */\nint mbedtls_ssl_session_save(const mbedtls_ssl_session *session,\n                             unsigned char *buf,\n                             size_t buf_len,\n                             size_t *olen)\n{\n    return ssl_session_save(session, 0, buf, buf_len, olen);\n}\n\n/*\n * Deserialize session, see mbedtls_ssl_session_save() for format.\n *\n * This internal version is wrapped by a public function that cleans up in\n * case of error, and has an extra option omit_header.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_session_load(mbedtls_ssl_session *session,\n                            unsigned char omit_header,\n                            const unsigned char *buf,\n                            size_t len)\n{\n    const unsigned char *p = buf;\n    const unsigned char * const end = buf + len;\n    size_t remaining_len;\n\n\n    if (session == NULL) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    if (!omit_header) {\n        /*\n         * Check Mbed TLS version identifier\n         */\n\n        if ((size_t) (end - p) < sizeof(ssl_serialized_session_header)) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        if (memcmp(p, ssl_serialized_session_header,\n                   sizeof(ssl_serialized_session_header)) != 0) {\n            return MBEDTLS_ERR_SSL_VERSION_MISMATCH;\n        }\n        p += sizeof(ssl_serialized_session_header);\n    }\n\n    /*\n     * TLS version identifier, endpoint, ciphersuite\n     */\n    if (4 > (size_t) (end - p)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    session->tls_version = (mbedtls_ssl_protocol_version) (0x0300 | *p++);\n    session->endpoint = *p++;\n    session->ciphersuite = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n\n    /* Dispatch according to TLS version. */\n    remaining_len = (size_t) (end - p);\n    switch (session->tls_version) {\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        case MBEDTLS_SSL_VERSION_TLS1_2:\n            return ssl_tls12_session_load(session, p, remaining_len);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n        case MBEDTLS_SSL_VERSION_TLS1_3:\n            return ssl_tls13_session_load(session, p, remaining_len);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n        default:\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n}\n\n/*\n * Deserialize session: public wrapper for error cleaning\n */\nint mbedtls_ssl_session_load(mbedtls_ssl_session *session,\n                             const unsigned char *buf,\n                             size_t len)\n{\n    int ret = ssl_session_load(session, 0, buf, len);\n\n    if (ret != 0) {\n        mbedtls_ssl_session_free(session);\n    }\n\n    return ret;\n}\n\n/*\n * Perform a single step of the SSL handshake\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_prepare_handshake_step(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /*\n     * We may have not been able to send to the peer all the handshake data\n     * that were written into the output buffer by the previous handshake step,\n     * if the write to the network callback returned with the\n     * #MBEDTLS_ERR_SSL_WANT_WRITE error code.\n     * We proceed to the next handshake step only when all data from the\n     * previous one have been sent to the peer, thus we make sure that this is\n     * the case here by calling `mbedtls_ssl_flush_output()`. The function may\n     * return with the #MBEDTLS_ERR_SSL_WANT_WRITE error code in which case\n     * we have to wait before to go ahead.\n     * In the case of TLS 1.3, handshake step handlers do not send data to the\n     * peer. Data are only sent here and through\n     * `mbedtls_ssl_handle_pending_alert` in case an error that triggered an\n     * alert occurred.\n     */\n    if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) {\n        return ret;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n        ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) {\n        if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {\n            return ret;\n        }\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    return ret;\n}\n\nint mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (ssl == NULL) return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    if (ssl->conf      == NULL                       ||\n        ssl->handshake == NULL                       ||\n        ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    ret = ssl_prepare_handshake_step(ssl);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_ssl_handle_pending_alert(ssl);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    /* If ssl->conf->endpoint is not one of MBEDTLS_SSL_IS_CLIENT or\n     * MBEDTLS_SSL_IS_SERVER, this is the return code we give */\n    ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n\n#if defined(MBEDTLS_SSL_CLI_C)\n    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"client state: %s\",\n                                  mbedtls_ssl_states_str((mbedtls_ssl_states) ssl->state)));\n\n        switch (ssl->state) {\n            case MBEDTLS_SSL_HELLO_REQUEST:\n                mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);\n                ret = 0;\n                break;\n\n            case MBEDTLS_SSL_CLIENT_HELLO:\n                ret = mbedtls_ssl_write_client_hello(ssl);\n                break;\n\n            default:\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3)\n                if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {\n                    ret = mbedtls_ssl_tls13_handshake_client_step(ssl);\n                } else {\n                    ret = mbedtls_ssl_handshake_client_step(ssl);\n                }\n#elif defined(MBEDTLS_SSL_PROTO_TLS1_2)\n                ret = mbedtls_ssl_handshake_client_step(ssl);\n#else\n                ret = mbedtls_ssl_tls13_handshake_client_step(ssl);\n#endif\n        }\n    }\n#endif /* MBEDTLS_SSL_CLI_C */\n\n#if defined(MBEDTLS_SSL_SRV_C)\n    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3)\n        if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {\n            ret = mbedtls_ssl_tls13_handshake_server_step(ssl);\n        } else {\n            ret = mbedtls_ssl_handshake_server_step(ssl);\n        }\n#elif defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        ret = mbedtls_ssl_handshake_server_step(ssl);\n#else\n        ret = mbedtls_ssl_tls13_handshake_server_step(ssl);\n#endif\n    }\n#endif /* MBEDTLS_SSL_SRV_C */\n\n    if (ret != 0) {\n        /* handshake_step return error. And it is same\n         * with alert_reason.\n         */\n        if (ssl->send_alert) {\n            ret = mbedtls_ssl_handle_pending_alert(ssl);\n            goto cleanup;\n        }\n    }\n\ncleanup:\n    return ret;\n}\n\n/*\n * Perform the SSL handshake\n */\nint mbedtls_ssl_handshake(mbedtls_ssl_context *ssl)\n{\n    int ret = 0;\n\n    /* Sanity checks */\n    if (ssl == NULL) return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    if (ssl->conf == NULL) return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n        (ssl->f_set_timer == NULL || ssl->f_get_timer == NULL)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"You must use \"\n                                  \"mbedtls_ssl_set_timer_cb() for DTLS\"));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> handshake\"));\n\n    /* Main handshake loop */\n    while (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) {\n        ret = mbedtls_ssl_handshake_step(ssl);\n\n        if (ret != 0) {\n            break;\n        }\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= handshake\"));\n\n    return ret;\n}\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n#if defined(MBEDTLS_SSL_SRV_C)\n/*\n * Write HelloRequest to request renegotiation on server\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_hello_request(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write hello request\"));\n\n    ssl->out_msglen  = 4;\n    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;\n    ssl->out_msg[0]  = MBEDTLS_SSL_HS_HELLO_REQUEST;\n\n    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_write_handshake_msg\", ret);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write hello request\"));\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_SRV_C */\n\n/*\n * Actually renegotiate current connection, triggered by either:\n * - any side: calling mbedtls_ssl_renegotiate(),\n * - client: receiving a HelloRequest during mbedtls_ssl_read(),\n * - server: receiving any handshake message on server during mbedtls_ssl_read() after\n *   the initial handshake is completed.\n * If the handshake doesn't complete due to waiting for I/O, it will continue\n * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively.\n */\nint mbedtls_ssl_start_renegotiation(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> renegotiate\"));\n\n    if ((ret = ssl_handshake_init(ssl)) != 0) {\n        return ret;\n    }\n\n    /* RFC 6347 4.2.2: \"[...] the HelloRequest will have message_seq = 0 and\n     * the ServerHello will have message_seq = 1\" */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n        ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) {\n        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {\n            ssl->handshake->out_msg_seq = 1;\n        } else {\n            ssl->handshake->in_msg_seq = 1;\n        }\n    }\n#endif\n\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HELLO_REQUEST);\n    ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS;\n\n    if ((ret = mbedtls_ssl_handshake(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_handshake\", ret);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= renegotiate\"));\n\n    return 0;\n}\n\n/*\n * Renegotiate current connection on client,\n * or request renegotiation on server\n */\nint mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n\n    if (ssl == NULL || ssl->conf == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_SSL_SRV_C)\n    /* On server, just send the request */\n    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {\n        if (mbedtls_ssl_is_handshake_over(ssl) == 0) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;\n\n        /* Did we already try/start sending HelloRequest? */\n        if (ssl->out_left != 0) {\n            return mbedtls_ssl_flush_output(ssl);\n        }\n\n        return ssl_write_hello_request(ssl);\n    }\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_SSL_CLI_C)\n    /*\n     * On client, either start the renegotiation process or,\n     * if already in progress, continue the handshake\n     */\n    if (ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {\n        if (mbedtls_ssl_is_handshake_over(ssl) == 0) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        if ((ret = mbedtls_ssl_start_renegotiation(ssl)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_start_renegotiation\", ret);\n            return ret;\n        }\n    } else {\n        if ((ret = mbedtls_ssl_handshake(ssl)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_handshake\", ret);\n            return ret;\n        }\n    }\n#endif /* MBEDTLS_SSL_CLI_C */\n\n    return ret;\n}\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n\nvoid mbedtls_ssl_handshake_free(mbedtls_ssl_context *ssl)\n{\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n    if (handshake == NULL) {\n        return;\n    }\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ssl->handshake->group_list_heap_allocated) {\n        mbedtls_free((void *) handshake->group_list);\n    }\n    handshake->group_list = NULL;\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n#if !defined(MBEDTLS_DEPRECATED_REMOVED)\n    if (ssl->handshake->sig_algs_heap_allocated) {\n        mbedtls_free((void *) handshake->sig_algs);\n    }\n    handshake->sig_algs = NULL;\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    if (ssl->handshake->certificate_request_context) {\n        mbedtls_free((void *) handshake->certificate_request_context);\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)\n    if (ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0) {\n        ssl->conf->f_async_cancel(ssl);\n        handshake->async_in_progress = 0;\n    }\n#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_hash_abort(&handshake->fin_sha256_psa);\n#else\n    mbedtls_md_free(&handshake->fin_sha256);\n#endif\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA384)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_hash_abort(&handshake->fin_sha384_psa);\n#else\n    mbedtls_md_free(&handshake->fin_sha384);\n#endif\n#endif\n\n#if defined(MBEDTLS_DHM_C)\n    mbedtls_dhm_free(&handshake->dhm_ctx);\n#endif\n#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \\\n    defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED)\n    mbedtls_ecdh_free(&handshake->ecdh_ctx);\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_pake_abort(&handshake->psa_pake_ctx);\n    /*\n     * Opaque keys are not stored in the handshake's data and it's the user\n     * responsibility to destroy them. Clear ones, instead, are created by\n     * the TLS library and should be destroyed at the same level\n     */\n    if (!mbedtls_svc_key_id_is_null(handshake->psa_pake_password)) {\n        psa_destroy_key(handshake->psa_pake_password);\n    }\n    handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT;\n#else\n    mbedtls_ecjpake_free(&handshake->ecjpake_ctx);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#if defined(MBEDTLS_SSL_CLI_C)\n    mbedtls_free(handshake->ecjpake_cache);\n    handshake->ecjpake_cache = NULL;\n    handshake->ecjpake_cache_len = 0;\n#endif\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_WITH_ECDSA_ANY_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n    /* explicit void pointer cast for buggy MS compiler */\n    mbedtls_free((void *) handshake->curves_tls_id);\n#endif\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) {\n        /* The maintenance of the external PSK key slot is the\n         * user's responsibility. */\n        if (ssl->handshake->psk_opaque_is_internal) {\n            psa_destroy_key(ssl->handshake->psk_opaque);\n            ssl->handshake->psk_opaque_is_internal = 0;\n        }\n        ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT;\n    }\n#else\n    if (handshake->psk != NULL) {\n        mbedtls_zeroize_and_free(handshake->psk, handshake->psk_len);\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C) && \\\n    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    /*\n     * Free only the linked list wrapper, not the keys themselves\n     * since the belong to the SNI callback\n     */\n    ssl_key_cert_free(handshake->sni_key_cert);\n#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n    mbedtls_x509_crt_restart_free(&handshake->ecrs_ctx);\n    if (handshake->ecrs_peer_cert != NULL) {\n        mbedtls_x509_crt_free(handshake->ecrs_peer_cert);\n        mbedtls_free(handshake->ecrs_peer_cert);\n    }\n#endif\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C) &&        \\\n    !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    mbedtls_pk_free(&handshake->peer_pubkey);\n#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n\n#if defined(MBEDTLS_SSL_CLI_C) && \\\n    (defined(MBEDTLS_SSL_PROTO_DTLS) || defined(MBEDTLS_SSL_PROTO_TLS1_3))\n    mbedtls_free(handshake->cookie);\n#endif /* MBEDTLS_SSL_CLI_C &&\n          ( MBEDTLS_SSL_PROTO_DTLS || MBEDTLS_SSL_PROTO_TLS1_3 ) */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    mbedtls_ssl_flight_free(handshake->flight);\n    mbedtls_ssl_buffering_free(ssl);\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED)\n    if (handshake->xxdh_psa_privkey_is_external == 0) {\n        psa_destroy_key(handshake->xxdh_psa_privkey);\n    }\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    mbedtls_ssl_transform_free(handshake->transform_handshake);\n    mbedtls_free(handshake->transform_handshake);\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    mbedtls_ssl_transform_free(handshake->transform_earlydata);\n    mbedtls_free(handshake->transform_earlydata);\n#endif\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n    /* If the buffers are too big - reallocate. Because of the way Mbed TLS\n     * processes datagrams and the fact that a datagram is allowed to have\n     * several records in it, it is possible that the I/O buffers are not\n     * empty at this stage */\n    handle_buffer_resizing(ssl, 1, mbedtls_ssl_get_input_buflen(ssl),\n                           mbedtls_ssl_get_output_buflen(ssl));\n#endif\n\n    /* mbedtls_platform_zeroize MUST be last one in this function */\n    mbedtls_platform_zeroize(handshake,\n                             sizeof(mbedtls_ssl_handshake_params));\n}\n\nvoid mbedtls_ssl_session_free(mbedtls_ssl_session *session)\n{\n    if (session == NULL) {\n        return;\n    }\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n    ssl_clear_peer_cert(session);\n#endif\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \\\n    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    mbedtls_free(session->hostname);\n#endif\n    mbedtls_free(session->ticket);\n#endif\n\n#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) && \\\n    defined(MBEDTLS_SSL_SRV_C)\n    mbedtls_free(session->ticket_alpn);\n#endif\n\n    mbedtls_platform_zeroize(session, sizeof(mbedtls_ssl_session));\n}\n\n#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 1u\n#else\n#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 0u\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 1u\n\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\n#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 1u\n#else\n#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 0u\n#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */\n\n#if defined(MBEDTLS_SSL_ALPN)\n#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 1u\n#else\n#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 0u\n#endif /* MBEDTLS_SSL_ALPN */\n\n#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT    0\n#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT     1\n#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT      2\n#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT                  3\n\n#define SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG   \\\n    ((uint32_t) (                              \\\n         (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID << \\\n             SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT) | \\\n         (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT << \\\n             SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT) | \\\n         (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY << \\\n             SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT) | \\\n         (SSL_SERIALIZED_CONTEXT_CONFIG_ALPN << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT) | \\\n         0u))\n\nstatic const unsigned char ssl_serialized_context_header[] = {\n    MBEDTLS_VERSION_MAJOR,\n    MBEDTLS_VERSION_MINOR,\n    MBEDTLS_VERSION_PATCH,\n    MBEDTLS_BYTE_1(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG),\n    MBEDTLS_BYTE_0(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG),\n    MBEDTLS_BYTE_2(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG),\n    MBEDTLS_BYTE_1(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG),\n    MBEDTLS_BYTE_0(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG),\n};\n\n/*\n * Serialize a full SSL context\n *\n * The format of the serialized data is:\n * (in the presentation language of TLS, RFC 8446 section 3)\n *\n *  // header\n *  opaque mbedtls_version[3];   // major, minor, patch\n *  opaque context_format[5];    // version-specific field determining\n *                               // the format of the remaining\n *                               // serialized data.\n *  Note: When updating the format, remember to keep these\n *        version+format bytes. (We may make their size part of the API.)\n *\n *  // session sub-structure\n *  opaque session<1..2^32-1>;  // see mbedtls_ssl_session_save()\n *  // transform sub-structure\n *  uint8 random[64];           // ServerHello.random+ClientHello.random\n *  uint8 in_cid<0..2^8-1>      // Connection ID: expected incoming value\n *  uint8 out_cid<0..2^8-1>     // Connection ID: outgoing value to use\n *  // fields from ssl_context\n *  uint32 badmac_seen_or_in_hsfraglen;         // DTLS: number of records with failing MAC\n *  uint64 in_window_top;       // DTLS: last validated record seq_num\n *  uint64 in_window;           // DTLS: bitmask for replay protection\n *  uint8 disable_datagram_packing; // DTLS: only one record per datagram\n *  uint64 cur_out_ctr;         // Record layer: outgoing sequence number\n *  uint16 mtu;                 // DTLS: path mtu (max outgoing fragment size)\n *  uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol\n *\n * Note that many fields of the ssl_context or sub-structures are not\n * serialized, as they fall in one of the following categories:\n *\n *  1. forced value (eg in_left must be 0)\n *  2. pointer to dynamically-allocated memory (eg session, transform)\n *  3. value can be re-derived from other data (eg session keys from MS)\n *  4. value was temporary (eg content of input buffer)\n *  5. value will be provided by the user again (eg I/O callbacks and context)\n */\nint mbedtls_ssl_context_save(mbedtls_ssl_context *ssl,\n                             unsigned char *buf,\n                             size_t buf_len,\n                             size_t *olen)\n{\n    unsigned char *p = buf;\n    size_t used = 0;\n    size_t session_len;\n    int ret = 0;\n\n    /*\n     * Enforce usage restrictions, see \"return BAD_INPUT_DATA\" in\n     * this function's documentation.\n     *\n     * These are due to assumptions/limitations in the implementation. Some of\n     * them are likely to stay (no handshake in progress) some might go away\n     * (only DTLS) but are currently used to simplify the implementation.\n     */\n    /* The initial handshake must be over */\n    if (mbedtls_ssl_is_handshake_over(ssl) == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Initial handshake isn't over\"));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    if (ssl->handshake != NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Handshake isn't completed\"));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    /* Double-check that sub-structures are indeed ready */\n    if (ssl->transform == NULL || ssl->session == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Serialised structures aren't ready\"));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    /* There must be no pending incoming or outgoing data */\n    if (mbedtls_ssl_check_pending(ssl) != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"There is pending incoming data\"));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    if (ssl->out_left != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"There is pending outgoing data\"));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    /* Protocol must be DTLS, not TLS */\n    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Only DTLS is supported\"));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    /* Version must be 1.2 */\n    if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Only version 1.2 supported\"));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    /* We must be using an AEAD ciphersuite */\n    if (mbedtls_ssl_transform_uses_aead(ssl->transform) != 1) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Only AEAD ciphersuites supported\"));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    /* Renegotiation must not be enabled */\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    if (ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Renegotiation must not be enabled\"));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n#endif\n\n    /*\n     * Version and format identifier\n     */\n    used += sizeof(ssl_serialized_context_header);\n\n    if (used <= buf_len) {\n        memcpy(p, ssl_serialized_context_header,\n               sizeof(ssl_serialized_context_header));\n        p += sizeof(ssl_serialized_context_header);\n    }\n\n    /*\n     * Session (length + data)\n     */\n    ret = ssl_session_save(ssl->session, 1, NULL, 0, &session_len);\n    if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) {\n        return ret;\n    }\n\n    used += 4 + session_len;\n    if (used <= buf_len) {\n        MBEDTLS_PUT_UINT32_BE(session_len, p, 0);\n        p += 4;\n\n        ret = ssl_session_save(ssl->session, 1,\n                               p, session_len, &session_len);\n        if (ret != 0) {\n            return ret;\n        }\n\n        p += session_len;\n    }\n\n    /*\n     * Transform\n     */\n    used += sizeof(ssl->transform->randbytes);\n    if (used <= buf_len) {\n        memcpy(p, ssl->transform->randbytes,\n               sizeof(ssl->transform->randbytes));\n        p += sizeof(ssl->transform->randbytes);\n    }\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    used += 2U + ssl->transform->in_cid_len + ssl->transform->out_cid_len;\n    if (used <= buf_len) {\n        *p++ = ssl->transform->in_cid_len;\n        memcpy(p, ssl->transform->in_cid, ssl->transform->in_cid_len);\n        p += ssl->transform->in_cid_len;\n\n        *p++ = ssl->transform->out_cid_len;\n        memcpy(p, ssl->transform->out_cid, ssl->transform->out_cid_len);\n        p += ssl->transform->out_cid_len;\n    }\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n    /*\n     * Saved fields from top-level ssl_context structure\n     */\n    used += 4;\n    if (used <= buf_len) {\n        MBEDTLS_PUT_UINT32_BE(ssl->badmac_seen_or_in_hsfraglen, p, 0);\n        p += 4;\n    }\n\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\n    used += 16;\n    if (used <= buf_len) {\n        MBEDTLS_PUT_UINT64_BE(ssl->in_window_top, p, 0);\n        p += 8;\n\n        MBEDTLS_PUT_UINT64_BE(ssl->in_window, p, 0);\n        p += 8;\n    }\n#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    used += 1;\n    if (used <= buf_len) {\n        *p++ = ssl->disable_datagram_packing;\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    used += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;\n    if (used <= buf_len) {\n        memcpy(p, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN);\n        p += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    used += 2;\n    if (used <= buf_len) {\n        MBEDTLS_PUT_UINT16_BE(ssl->mtu, p, 0);\n        p += 2;\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n#if defined(MBEDTLS_SSL_ALPN)\n    {\n        const uint8_t alpn_len = ssl->alpn_chosen\n                               ? (uint8_t) strlen(ssl->alpn_chosen)\n                               : 0;\n\n        used += 1 + alpn_len;\n        if (used <= buf_len) {\n            *p++ = alpn_len;\n\n            if (ssl->alpn_chosen != NULL) {\n                memcpy(p, ssl->alpn_chosen, alpn_len);\n                p += alpn_len;\n            }\n        }\n    }\n#endif /* MBEDTLS_SSL_ALPN */\n\n    /*\n     * Done\n     */\n    *olen = used;\n\n    if (used > buf_len) {\n        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"saved context\", buf, used);\n\n    return mbedtls_ssl_session_reset_int(ssl, 0);\n}\n\n/*\n * Deserialize context, see mbedtls_ssl_context_save() for format.\n *\n * This internal version is wrapped by a public function that cleans up in\n * case of error.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_context_load(mbedtls_ssl_context *ssl,\n                            const unsigned char *buf,\n                            size_t len)\n{\n    const unsigned char *p = buf;\n    const unsigned char * const end = buf + len;\n    size_t session_len;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    tls_prf_fn prf_func = NULL;\n#endif\n\n    /*\n     * The context should have been freshly setup or reset.\n     * Give the user an error in case of obvious misuse.\n     * (Checking session is useful because it won't be NULL if we're\n     * renegotiating, or if the user mistakenly loaded a session first.)\n     */\n    if (ssl->state != MBEDTLS_SSL_HELLO_REQUEST ||\n        ssl->session != NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    /*\n     * We can't check that the config matches the initial one, but we can at\n     * least check it matches the requirements for serializing.\n     */\n    if (\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n        ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED ||\n#endif\n        ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||\n        ssl->conf->max_tls_version < MBEDTLS_SSL_VERSION_TLS1_2 ||\n        ssl->conf->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2\n        ) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"context to load\", buf, len);\n\n    /*\n     * Check version identifier\n     */\n    if ((size_t) (end - p) < sizeof(ssl_serialized_context_header)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if (memcmp(p, ssl_serialized_context_header,\n               sizeof(ssl_serialized_context_header)) != 0) {\n        return MBEDTLS_ERR_SSL_VERSION_MISMATCH;\n    }\n    p += sizeof(ssl_serialized_context_header);\n\n    /*\n     * Session\n     */\n    if ((size_t) (end - p) < 4) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    session_len = MBEDTLS_GET_UINT32_BE(p, 0);\n    p += 4;\n\n    /* This has been allocated by ssl_handshake_init(), called by\n     * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */\n    ssl->session = ssl->session_negotiate;\n    ssl->session_in = ssl->session;\n    ssl->session_out = ssl->session;\n    ssl->session_negotiate = NULL;\n\n    if ((size_t) (end - p) < session_len) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    ret = ssl_session_load(ssl->session, 1, p, session_len);\n    if (ret != 0) {\n        mbedtls_ssl_session_free(ssl->session);\n        return ret;\n    }\n\n    p += session_len;\n\n    /*\n     * Transform\n     */\n\n    /* This has been allocated by ssl_handshake_init(), called by\n     * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    ssl->transform = ssl->transform_negotiate;\n    ssl->transform_in = ssl->transform;\n    ssl->transform_out = ssl->transform;\n    ssl->transform_negotiate = NULL;\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    prf_func = ssl_tls12prf_from_cs(ssl->session->ciphersuite);\n    if (prf_func == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    /* Read random bytes and populate structure */\n    if ((size_t) (end - p) < sizeof(ssl->transform->randbytes)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    ret = ssl_tls12_populate_transform(ssl->transform,\n                                       ssl->session->ciphersuite,\n                                       ssl->session->master,\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)\n                                       ssl->session->encrypt_then_mac,\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */\n                                       prf_func,\n                                       p, /* currently pointing to randbytes */\n                                       MBEDTLS_SSL_VERSION_TLS1_2, /* (D)TLS 1.2 is forced */\n                                       ssl->conf->endpoint,\n                                       ssl);\n    if (ret != 0) {\n        return ret;\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n    p += sizeof(ssl->transform->randbytes);\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    /* Read connection IDs and store them */\n    if ((size_t) (end - p) < 1) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    ssl->transform->in_cid_len = *p++;\n\n    if ((size_t) (end - p) < ssl->transform->in_cid_len + 1u) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    memcpy(ssl->transform->in_cid, p, ssl->transform->in_cid_len);\n    p += ssl->transform->in_cid_len;\n\n    ssl->transform->out_cid_len = *p++;\n\n    if ((size_t) (end - p) < ssl->transform->out_cid_len) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    memcpy(ssl->transform->out_cid, p, ssl->transform->out_cid_len);\n    p += ssl->transform->out_cid_len;\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n    /*\n     * Saved fields from top-level ssl_context structure\n     */\n    if ((size_t) (end - p) < 4) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    ssl->badmac_seen_or_in_hsfraglen = MBEDTLS_GET_UINT32_BE(p, 0);\n    p += 4;\n\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\n    if ((size_t) (end - p) < 16) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    ssl->in_window_top = MBEDTLS_GET_UINT64_BE(p, 0);\n    p += 8;\n\n    ssl->in_window = MBEDTLS_GET_UINT64_BE(p, 0);\n    p += 8;\n#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if ((size_t) (end - p) < 1) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    ssl->disable_datagram_packing = *p++;\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    if ((size_t) (end - p) < sizeof(ssl->cur_out_ctr)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n    memcpy(ssl->cur_out_ctr, p, sizeof(ssl->cur_out_ctr));\n    p += sizeof(ssl->cur_out_ctr);\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if ((size_t) (end - p) < 2) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    ssl->mtu = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n#if defined(MBEDTLS_SSL_ALPN)\n    {\n        uint8_t alpn_len;\n        const char **cur;\n\n        if ((size_t) (end - p) < 1) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        alpn_len = *p++;\n\n        if (alpn_len != 0 && ssl->conf->alpn_list != NULL) {\n            /* alpn_chosen should point to an item in the configured list */\n            for (cur = ssl->conf->alpn_list; *cur != NULL; cur++) {\n                if (strlen(*cur) == alpn_len &&\n                    memcmp(p, *cur, alpn_len) == 0) {\n                    ssl->alpn_chosen = *cur;\n                    break;\n                }\n            }\n        }\n\n        /* can only happen on conf mismatch */\n        if (alpn_len != 0 && ssl->alpn_chosen == NULL) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        p += alpn_len;\n    }\n#endif /* MBEDTLS_SSL_ALPN */\n\n    /*\n     * Forced fields from top-level ssl_context structure\n     *\n     * Most of them already set to the correct value by mbedtls_ssl_init() and\n     * mbedtls_ssl_reset(), so we only need to set the remaining ones.\n     */\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);\n    ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2;\n\n    /* Adjust pointers for header fields of outgoing records to\n     * the given transform, accounting for explicit IV and CID. */\n    mbedtls_ssl_update_out_pointers(ssl, ssl->transform);\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    ssl->in_epoch = 1;\n#endif\n\n    /* mbedtls_ssl_reset() leaves the handshake sub-structure allocated,\n     * which we don't want - otherwise we'd end up freeing the wrong transform\n     * by calling mbedtls_ssl_handshake_wrapup_free_hs_transform()\n     * inappropriately. */\n    if (ssl->handshake != NULL) {\n        mbedtls_ssl_handshake_free(ssl);\n        mbedtls_free(ssl->handshake);\n        ssl->handshake = NULL;\n    }\n\n    /*\n     * Done - should have consumed entire buffer\n     */\n    if (p != end) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    return 0;\n}\n\n/*\n * Deserialize context: public wrapper for error cleaning\n */\nint mbedtls_ssl_context_load(mbedtls_ssl_context *context,\n                             const unsigned char *buf,\n                             size_t len)\n{\n    int ret = ssl_context_load(context, buf, len);\n\n    if (ret != 0) {\n        mbedtls_ssl_free(context);\n    }\n\n    return ret;\n}\n#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */\n\n/*\n * Free an SSL context\n */\nvoid mbedtls_ssl_free(mbedtls_ssl_context *ssl)\n{\n    if (ssl == NULL) {\n        return;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> free\"));\n\n    if (ssl->out_buf != NULL) {\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n        size_t out_buf_len = ssl->out_buf_len;\n#else\n        size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;\n#endif\n\n        mbedtls_zeroize_and_free(ssl->out_buf, out_buf_len);\n        ssl->out_buf = NULL;\n    }\n\n    if (ssl->in_buf != NULL) {\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n        size_t in_buf_len = ssl->in_buf_len;\n#else\n        size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;\n#endif\n\n        mbedtls_zeroize_and_free(ssl->in_buf, in_buf_len);\n        ssl->in_buf = NULL;\n    }\n\n    if (ssl->transform) {\n        mbedtls_ssl_transform_free(ssl->transform);\n        mbedtls_free(ssl->transform);\n    }\n\n    if (ssl->handshake) {\n        mbedtls_ssl_handshake_free(ssl);\n        mbedtls_free(ssl->handshake);\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        mbedtls_ssl_transform_free(ssl->transform_negotiate);\n        mbedtls_free(ssl->transform_negotiate);\n#endif\n\n        mbedtls_ssl_session_free(ssl->session_negotiate);\n        mbedtls_free(ssl->session_negotiate);\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    mbedtls_ssl_transform_free(ssl->transform_application);\n    mbedtls_free(ssl->transform_application);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n    if (ssl->session) {\n        mbedtls_ssl_session_free(ssl->session);\n        mbedtls_free(ssl->session);\n    }\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n    mbedtls_ssl_free_hostname(ssl);\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)\n    mbedtls_free(ssl->cli_id);\n#endif\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= free\"));\n\n    /* Actually clear after last debug message */\n    mbedtls_platform_zeroize(ssl, sizeof(mbedtls_ssl_context));\n}\n\n/*\n * Initialize mbedtls_ssl_config\n */\nvoid mbedtls_ssl_config_init(mbedtls_ssl_config *conf)\n{\n    memset(conf, 0, sizeof(mbedtls_ssl_config));\n}\n\n/* The selection should be the same as mbedtls_x509_crt_profile_default in\n * x509_crt.c, plus Montgomery curves for ECDHE. Here, the order matters:\n * curves with a lower resource usage come first.\n * See the documentation of mbedtls_ssl_conf_curves() for what we promise\n * about this list.\n */\nstatic const uint16_t ssl_preset_default_groups[] = {\n#if defined(MBEDTLS_ECP_HAVE_CURVE25519)\n    MBEDTLS_SSL_IANA_TLS_GROUP_X25519,\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP256R1)\n    MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1,\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP384R1)\n    MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1,\n#endif\n#if defined(MBEDTLS_ECP_HAVE_CURVE448)\n    MBEDTLS_SSL_IANA_TLS_GROUP_X448,\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP521R1)\n    MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1,\n#endif\n#if defined(MBEDTLS_ECP_HAVE_BP256R1)\n    MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1,\n#endif\n#if defined(MBEDTLS_ECP_HAVE_BP384R1)\n    MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1,\n#endif\n#if defined(MBEDTLS_ECP_HAVE_BP512R1)\n    MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1,\n#endif\n#if defined(PSA_WANT_ALG_FFDH)\n    MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048,\n    MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072,\n    MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096,\n    MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144,\n    MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192,\n#endif\n    MBEDTLS_SSL_IANA_TLS_GROUP_NONE\n};\n\nstatic const int ssl_preset_suiteb_ciphersuites[] = {\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\n    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,\n    0\n};\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n\n/* NOTICE:\n *   For ssl_preset_*_sig_algs and ssl_tls12_preset_*_sig_algs, the following\n *   rules SHOULD be upheld.\n *   - No duplicate entries.\n *   - But if there is a good reason, do not change the order of the algorithms.\n *   - ssl_tls12_preset* is for TLS 1.2 use only.\n *   - ssl_preset_* is for TLS 1.3 only or hybrid TLS 1.3/1.2 handshakes.\n */\nstatic const uint16_t ssl_preset_default_sig_algs[] = {\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \\\n    defined(MBEDTLS_MD_CAN_SHA256) && \\\n    defined(PSA_WANT_ECC_SECP_R1_256)\n    MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256,\n    // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256)\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \\\n    defined(MBEDTLS_MD_CAN_SHA384) && \\\n    defined(PSA_WANT_ECC_SECP_R1_384)\n    MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384,\n    // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384)\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \\\n    defined(MBEDTLS_MD_CAN_SHA512) && \\\n    defined(PSA_WANT_ECC_SECP_R1_521)\n    MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512,\n    // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512)\n#endif\n\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_MD_CAN_SHA512)\n    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512,\n#endif\n\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_MD_CAN_SHA384)\n    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384,\n#endif\n\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_MD_CAN_SHA256)\n    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,\n#endif\n\n#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA512)\n    MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512,\n#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA512 */\n\n#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA384)\n    MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384,\n#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA384 */\n\n#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA256)\n    MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256,\n#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA256 */\n\n    MBEDTLS_TLS_SIG_NONE\n};\n\n/* NOTICE: see above */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\nstatic const uint16_t ssl_tls12_preset_default_sig_algs[] = {\n\n#if defined(MBEDTLS_MD_CAN_SHA512)\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)\n    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512),\n#endif\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)\n    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512,\n#endif\n#if defined(MBEDTLS_RSA_C)\n    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA512),\n#endif\n#endif /* MBEDTLS_MD_CAN_SHA512 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)\n    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384),\n#endif\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)\n    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384,\n#endif\n#if defined(MBEDTLS_RSA_C)\n    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA384),\n#endif\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)\n    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256),\n#endif\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)\n    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,\n#endif\n#if defined(MBEDTLS_RSA_C)\n    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA256),\n#endif\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n    MBEDTLS_TLS_SIG_NONE\n};\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n/* NOTICE: see above */\nstatic const uint16_t ssl_preset_suiteb_sig_algs[] = {\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \\\n    defined(MBEDTLS_MD_CAN_SHA256) && \\\n    defined(MBEDTLS_ECP_HAVE_SECP256R1)\n    MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256,\n    // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256)\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \\\n    defined(MBEDTLS_MD_CAN_SHA384) && \\\n    defined(MBEDTLS_ECP_HAVE_SECP384R1)\n    MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384,\n    // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384)\n#endif\n\n    MBEDTLS_TLS_SIG_NONE\n};\n\n/* NOTICE: see above */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\nstatic const uint16_t ssl_tls12_preset_suiteb_sig_algs[] = {\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)\n    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256),\n#endif\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)\n    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384),\n#endif\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n\n    MBEDTLS_TLS_SIG_NONE\n};\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\nstatic const uint16_t ssl_preset_suiteb_groups[] = {\n#if defined(MBEDTLS_ECP_HAVE_SECP256R1)\n    MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1,\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP384R1)\n    MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1,\n#endif\n    MBEDTLS_SSL_IANA_TLS_GROUP_NONE\n};\n\n#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n/* Function for checking `ssl_preset_*_sig_algs` and `ssl_tls12_preset_*_sig_algs`\n * to make sure there are no duplicated signature algorithm entries. */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_check_no_sig_alg_duplication(const uint16_t *sig_algs)\n{\n    size_t i, j;\n    int ret = 0;\n\n    for (i = 0; sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) {\n        for (j = 0; j < i; j++) {\n            if (sig_algs[i] != sig_algs[j]) {\n                continue;\n            }\n            mbedtls_printf(\" entry(%04x,%\" MBEDTLS_PRINTF_SIZET\n                           \") is duplicated at %\" MBEDTLS_PRINTF_SIZET \"\\n\",\n                           sig_algs[i], j, i);\n            ret = -1;\n        }\n    }\n    return ret;\n}\n\n#endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n/*\n * Load default in mbedtls_ssl_config\n */\nint mbedtls_ssl_config_defaults(mbedtls_ssl_config *conf,\n                                int endpoint, int transport, int preset)\n{\n#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n#endif\n\n#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n    if (ssl_check_no_sig_alg_duplication(ssl_preset_suiteb_sig_algs)) {\n        mbedtls_printf(\"ssl_preset_suiteb_sig_algs has duplicated entries\\n\");\n        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    }\n\n    if (ssl_check_no_sig_alg_duplication(ssl_preset_default_sig_algs)) {\n        mbedtls_printf(\"ssl_preset_default_sig_algs has duplicated entries\\n\");\n        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_suiteb_sig_algs)) {\n        mbedtls_printf(\"ssl_tls12_preset_suiteb_sig_algs has duplicated entries\\n\");\n        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    }\n\n    if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_default_sig_algs)) {\n        mbedtls_printf(\"ssl_tls12_preset_default_sig_algs has duplicated entries\\n\");\n        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n#endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n    /* Use the functions here so that they are covered in tests,\n     * but otherwise access member directly for efficiency */\n    mbedtls_ssl_conf_endpoint(conf, endpoint);\n    mbedtls_ssl_conf_transport(conf, transport);\n\n    /*\n     * Things that are common to all presets\n     */\n#if defined(MBEDTLS_SSL_CLI_C)\n    if (endpoint == MBEDTLS_SSL_IS_CLIENT) {\n        conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED;\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n        mbedtls_ssl_conf_session_tickets(conf, MBEDTLS_SSL_SESSION_TICKETS_ENABLED);\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n        /* Contrary to TLS 1.2 tickets, TLS 1.3 NewSessionTicket message\n         * handling is disabled by default in Mbed TLS 3.6.x for backward\n         * compatibility with client applications developed using Mbed TLS 3.5\n         * or earlier with the default configuration.\n         *\n         * Up to Mbed TLS 3.5, in the default configuration TLS 1.3 was\n         * disabled, and a Mbed TLS client with the default configuration would\n         * establish a TLS 1.2 connection with a TLS 1.2 and TLS 1.3 capable\n         * server.\n         *\n         * Starting with Mbed TLS 3.6.0, TLS 1.3 is enabled by default, and thus\n         * an Mbed TLS client with the default configuration establishes a\n         * TLS 1.3 connection with a TLS 1.2 and TLS 1.3 capable server. If\n         * following the handshake the TLS 1.3 server sends NewSessionTicket\n         * messages and the Mbed TLS client processes them, this results in\n         * Mbed TLS high level APIs (mbedtls_ssl_read(),\n         * mbedtls_ssl_handshake(), ...) to eventually return an\n         * #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET non fatal error code\n         * (see the documentation of mbedtls_ssl_read() for more information on\n         * that error code). Applications unaware of that TLS 1.3 specific non\n         * fatal error code are then failing.\n         */\n        mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(\n            conf, MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED);\n#endif\n#endif\n    }\n#endif\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n    conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED;\n#endif\n\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\n    conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)\n    conf->f_cookie_write = ssl_cookie_write_dummy;\n    conf->f_cookie_check = ssl_cookie_check_dummy;\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\n    conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED;\n#endif\n\n#if defined(MBEDTLS_SSL_SRV_C)\n    conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED;\n    conf->respect_cli_pref = MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER;\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN;\n    conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX;\n#endif\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT;\n    memset(conf->renego_period,     0x00, 2);\n    memset(conf->renego_period + 2, 0xFF, 6);\n#endif\n\n#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)\n    if (endpoint == MBEDTLS_SSL_IS_SERVER) {\n        const unsigned char dhm_p[] =\n            MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN;\n        const unsigned char dhm_g[] =\n            MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN;\n\n        if ((ret = mbedtls_ssl_conf_dh_param_bin(conf,\n                                                 dhm_p, sizeof(dhm_p),\n                                                 dhm_g, sizeof(dhm_g))) != 0) {\n            return ret;\n        }\n    }\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    mbedtls_ssl_conf_early_data(conf, MBEDTLS_SSL_EARLY_DATA_DISABLED);\n#if defined(MBEDTLS_SSL_SRV_C)\n    mbedtls_ssl_conf_max_early_data_size(conf, MBEDTLS_SSL_MAX_EARLY_DATA_SIZE);\n#endif\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS)\n    mbedtls_ssl_conf_new_session_tickets(\n        conf, MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS);\n#endif\n    /*\n     * Allow all TLS 1.3 key exchange modes by default.\n     */\n    conf->tls13_kex_modes = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL;\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n    if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;\n        conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;\n#else\n        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n#endif\n    } else {\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3)\n        conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;\n        conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3;\n#elif defined(MBEDTLS_SSL_PROTO_TLS1_3)\n        conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_3;\n        conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3;\n#elif defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;\n        conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;\n#else\n        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n#endif\n    }\n\n    /*\n     * Preset-specific defaults\n     */\n    switch (preset) {\n        /*\n         * NSA Suite B\n         */\n        case MBEDTLS_SSL_PRESET_SUITEB:\n\n            conf->ciphersuite_list = ssl_preset_suiteb_ciphersuites;\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n            conf->cert_profile = &mbedtls_x509_crt_profile_suiteb;\n#endif\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n            if (mbedtls_ssl_conf_is_tls12_only(conf)) {\n                conf->sig_algs = ssl_tls12_preset_suiteb_sig_algs;\n            } else\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n            conf->sig_algs = ssl_preset_suiteb_sig_algs;\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n            conf->curve_list = NULL;\n#endif\n            conf->group_list = ssl_preset_suiteb_groups;\n            break;\n\n        /*\n         * Default\n         */\n        default:\n\n            conf->ciphersuite_list = mbedtls_ssl_list_ciphersuites();\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n            conf->cert_profile = &mbedtls_x509_crt_profile_default;\n#endif\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n            if (mbedtls_ssl_conf_is_tls12_only(conf)) {\n                conf->sig_algs = ssl_tls12_preset_default_sig_algs;\n            } else\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n            conf->sig_algs = ssl_preset_default_sig_algs;\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)\n            conf->curve_list = NULL;\n#endif\n            conf->group_list = ssl_preset_default_groups;\n\n#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C)\n            conf->dhm_min_bitlen = 1024;\n#endif\n    }\n\n    return 0;\n}\n\n/*\n * Free mbedtls_ssl_config\n */\nvoid mbedtls_ssl_config_free(mbedtls_ssl_config *conf)\n{\n    if (conf == NULL) {\n        return;\n    }\n\n#if defined(MBEDTLS_DHM_C)\n    mbedtls_mpi_free(&conf->dhm_P);\n    mbedtls_mpi_free(&conf->dhm_G);\n#endif\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) {\n        conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    if (conf->psk != NULL) {\n        mbedtls_zeroize_and_free(conf->psk, conf->psk_len);\n        conf->psk = NULL;\n        conf->psk_len = 0;\n    }\n\n    if (conf->psk_identity != NULL) {\n        mbedtls_zeroize_and_free(conf->psk_identity, conf->psk_identity_len);\n        conf->psk_identity = NULL;\n        conf->psk_identity_len = 0;\n    }\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n    ssl_key_cert_free(conf->key_cert);\n#endif\n\n    mbedtls_platform_zeroize(conf, sizeof(mbedtls_ssl_config));\n}\n\n#if defined(MBEDTLS_PK_C) && \\\n    (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED))\n/*\n * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX\n */\nunsigned char mbedtls_ssl_sig_from_pk(mbedtls_pk_context *pk)\n{\n#if defined(MBEDTLS_RSA_C)\n    if (mbedtls_pk_can_do(pk, MBEDTLS_PK_RSA)) {\n        return MBEDTLS_SSL_SIG_RSA;\n    }\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED)\n    if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECDSA)) {\n        return MBEDTLS_SSL_SIG_ECDSA;\n    }\n#endif\n    return MBEDTLS_SSL_SIG_ANON;\n}\n\nunsigned char mbedtls_ssl_sig_from_pk_alg(mbedtls_pk_type_t type)\n{\n    switch (type) {\n        case MBEDTLS_PK_RSA:\n            return MBEDTLS_SSL_SIG_RSA;\n        case MBEDTLS_PK_ECDSA:\n        case MBEDTLS_PK_ECKEY:\n            return MBEDTLS_SSL_SIG_ECDSA;\n        default:\n            return MBEDTLS_SSL_SIG_ANON;\n    }\n}\n\nmbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig(unsigned char sig)\n{\n    switch (sig) {\n#if defined(MBEDTLS_RSA_C)\n        case MBEDTLS_SSL_SIG_RSA:\n            return MBEDTLS_PK_RSA;\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED)\n        case MBEDTLS_SSL_SIG_ECDSA:\n            return MBEDTLS_PK_ECDSA;\n#endif\n        default:\n            return MBEDTLS_PK_NONE;\n    }\n}\n#endif /* MBEDTLS_PK_C &&\n          ( MBEDTLS_RSA_C || MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED ) */\n\n/*\n * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX\n */\nmbedtls_md_type_t mbedtls_ssl_md_alg_from_hash(unsigned char hash)\n{\n    switch (hash) {\n#if defined(MBEDTLS_MD_CAN_MD5)\n        case MBEDTLS_SSL_HASH_MD5:\n            return MBEDTLS_MD_MD5;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA1)\n        case MBEDTLS_SSL_HASH_SHA1:\n            return MBEDTLS_MD_SHA1;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA224)\n        case MBEDTLS_SSL_HASH_SHA224:\n            return MBEDTLS_MD_SHA224;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA256)\n        case MBEDTLS_SSL_HASH_SHA256:\n            return MBEDTLS_MD_SHA256;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA384)\n        case MBEDTLS_SSL_HASH_SHA384:\n            return MBEDTLS_MD_SHA384;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA512)\n        case MBEDTLS_SSL_HASH_SHA512:\n            return MBEDTLS_MD_SHA512;\n#endif\n        default:\n            return MBEDTLS_MD_NONE;\n    }\n}\n\n/*\n * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX\n */\nunsigned char mbedtls_ssl_hash_from_md_alg(int md)\n{\n    switch (md) {\n#if defined(MBEDTLS_MD_CAN_MD5)\n        case MBEDTLS_MD_MD5:\n            return MBEDTLS_SSL_HASH_MD5;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA1)\n        case MBEDTLS_MD_SHA1:\n            return MBEDTLS_SSL_HASH_SHA1;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA224)\n        case MBEDTLS_MD_SHA224:\n            return MBEDTLS_SSL_HASH_SHA224;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA256)\n        case MBEDTLS_MD_SHA256:\n            return MBEDTLS_SSL_HASH_SHA256;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA384)\n        case MBEDTLS_MD_SHA384:\n            return MBEDTLS_SSL_HASH_SHA384;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA512)\n        case MBEDTLS_MD_SHA512:\n            return MBEDTLS_SSL_HASH_SHA512;\n#endif\n        default:\n            return MBEDTLS_SSL_HASH_NONE;\n    }\n}\n\n/*\n * Check if a curve proposed by the peer is in our list.\n * Return 0 if we're willing to use it, -1 otherwise.\n */\nint mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id)\n{\n    const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);\n\n    if (group_list == NULL) {\n        return -1;\n    }\n\n    for (; *group_list != 0; group_list++) {\n        if (*group_list == tls_id) {\n            return 0;\n        }\n    }\n\n    return -1;\n}\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n/*\n * Same as mbedtls_ssl_check_curve_tls_id() but with a mbedtls_ecp_group_id.\n */\nint mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id)\n{\n    uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id);\n\n    if (tls_id == 0) {\n        return -1;\n    }\n\n    return mbedtls_ssl_check_curve_tls_id(ssl, tls_id);\n}\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\nstatic const struct {\n    uint16_t tls_id;\n    mbedtls_ecp_group_id ecp_group_id;\n    psa_ecc_family_t psa_family;\n    uint16_t bits;\n} tls_id_match_table[] =\n{\n#if defined(MBEDTLS_ECP_HAVE_SECP521R1)\n    { 25, MBEDTLS_ECP_DP_SECP521R1, PSA_ECC_FAMILY_SECP_R1, 521 },\n#endif\n#if defined(MBEDTLS_ECP_HAVE_BP512R1)\n    { 28, MBEDTLS_ECP_DP_BP512R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 512 },\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP384R1)\n    { 24, MBEDTLS_ECP_DP_SECP384R1, PSA_ECC_FAMILY_SECP_R1, 384 },\n#endif\n#if defined(MBEDTLS_ECP_HAVE_BP384R1)\n    { 27, MBEDTLS_ECP_DP_BP384R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 384 },\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP256R1)\n    { 23, MBEDTLS_ECP_DP_SECP256R1, PSA_ECC_FAMILY_SECP_R1, 256 },\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP256K1)\n    { 22, MBEDTLS_ECP_DP_SECP256K1, PSA_ECC_FAMILY_SECP_K1, 256 },\n#endif\n#if defined(MBEDTLS_ECP_HAVE_BP256R1)\n    { 26, MBEDTLS_ECP_DP_BP256R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 256 },\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP224R1)\n    { 21, MBEDTLS_ECP_DP_SECP224R1, PSA_ECC_FAMILY_SECP_R1, 224 },\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP224K1)\n    { 20, MBEDTLS_ECP_DP_SECP224K1, PSA_ECC_FAMILY_SECP_K1, 224 },\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP192R1)\n    { 19, MBEDTLS_ECP_DP_SECP192R1, PSA_ECC_FAMILY_SECP_R1, 192 },\n#endif\n#if defined(MBEDTLS_ECP_HAVE_SECP192K1)\n    { 18, MBEDTLS_ECP_DP_SECP192K1, PSA_ECC_FAMILY_SECP_K1, 192 },\n#endif\n#if defined(MBEDTLS_ECP_HAVE_CURVE25519)\n    { 29, MBEDTLS_ECP_DP_CURVE25519, PSA_ECC_FAMILY_MONTGOMERY, 255 },\n#endif\n#if defined(MBEDTLS_ECP_HAVE_CURVE448)\n    { 30, MBEDTLS_ECP_DP_CURVE448, PSA_ECC_FAMILY_MONTGOMERY, 448 },\n#endif\n    { 0, MBEDTLS_ECP_DP_NONE, 0, 0 },\n};\n\nint mbedtls_ssl_get_psa_curve_info_from_tls_id(uint16_t tls_id,\n                                               psa_key_type_t *type,\n                                               size_t *bits)\n{\n    for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) {\n        if (tls_id_match_table[i].tls_id == tls_id) {\n            if (type != NULL) {\n                *type = PSA_KEY_TYPE_ECC_KEY_PAIR(tls_id_match_table[i].psa_family);\n            }\n            if (bits != NULL) {\n                *bits = tls_id_match_table[i].bits;\n            }\n            return PSA_SUCCESS;\n        }\n    }\n\n    return PSA_ERROR_NOT_SUPPORTED;\n}\n\nmbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id(uint16_t tls_id)\n{\n    for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) {\n        if (tls_id_match_table[i].tls_id == tls_id) {\n            return tls_id_match_table[i].ecp_group_id;\n        }\n    }\n\n    return MBEDTLS_ECP_DP_NONE;\n}\n\nuint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id)\n{\n    for (int i = 0; tls_id_match_table[i].ecp_group_id != MBEDTLS_ECP_DP_NONE;\n         i++) {\n        if (tls_id_match_table[i].ecp_group_id == grp_id) {\n            return tls_id_match_table[i].tls_id;\n        }\n    }\n\n    return 0;\n}\n\n#if defined(MBEDTLS_DEBUG_C)\nstatic const struct {\n    uint16_t tls_id;\n    const char *name;\n} tls_id_curve_name_table[] =\n{\n    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1, \"secp521r1\" },\n    { MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1, \"brainpoolP512r1\" },\n    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, \"secp384r1\" },\n    { MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1, \"brainpoolP384r1\" },\n    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, \"secp256r1\" },\n    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1, \"secp256k1\" },\n    { MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1, \"brainpoolP256r1\" },\n    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1, \"secp224r1\" },\n    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1, \"secp224k1\" },\n    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1, \"secp192r1\" },\n    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1, \"secp192k1\" },\n    { MBEDTLS_SSL_IANA_TLS_GROUP_X25519, \"x25519\" },\n    { MBEDTLS_SSL_IANA_TLS_GROUP_X448, \"x448\" },\n    { 0, NULL },\n};\n\nconst char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id)\n{\n    for (int i = 0; tls_id_curve_name_table[i].tls_id != 0; i++) {\n        if (tls_id_curve_name_table[i].tls_id == tls_id) {\n            return tls_id_curve_name_table[i].name;\n        }\n    }\n\n    return NULL;\n}\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nint mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl,\n                                         const mbedtls_md_type_t md,\n                                         unsigned char *dst,\n                                         size_t dst_len,\n                                         size_t *olen)\n{\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_hash_operation_t *hash_operation_to_clone;\n    psa_hash_operation_t hash_operation = psa_hash_operation_init();\n\n    *olen = 0;\n\n    switch (md) {\n#if defined(MBEDTLS_MD_CAN_SHA384)\n        case MBEDTLS_MD_SHA384:\n            hash_operation_to_clone = &ssl->handshake->fin_sha384_psa;\n            break;\n#endif\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n        case MBEDTLS_MD_SHA256:\n            hash_operation_to_clone = &ssl->handshake->fin_sha256_psa;\n            break;\n#endif\n\n        default:\n            goto exit;\n    }\n\n    status = psa_hash_clone(hash_operation_to_clone, &hash_operation);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_finish(&hash_operation, dst, dst_len, olen);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\nexit:\n#if !defined(MBEDTLS_MD_CAN_SHA384) && \\\n    !defined(MBEDTLS_MD_CAN_SHA256)\n    (void) ssl;\n#endif\n    return PSA_TO_MBEDTLS_ERR(status);\n}\n#else /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_get_handshake_transcript_sha384(mbedtls_ssl_context *ssl,\n                                               unsigned char *dst,\n                                               size_t dst_len,\n                                               size_t *olen)\n{\n    int ret;\n    mbedtls_md_context_t sha384;\n\n    if (dst_len < 48) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    mbedtls_md_init(&sha384);\n    ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0);\n    if (ret != 0) {\n        goto exit;\n    }\n    ret = mbedtls_md_clone(&sha384, &ssl->handshake->fin_sha384);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_md_finish(&sha384, dst)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_md_finish\", ret);\n        goto exit;\n    }\n\n    *olen = 48;\n\nexit:\n\n    mbedtls_md_free(&sha384);\n    return ret;\n}\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_get_handshake_transcript_sha256(mbedtls_ssl_context *ssl,\n                                               unsigned char *dst,\n                                               size_t dst_len,\n                                               size_t *olen)\n{\n    int ret;\n    mbedtls_md_context_t sha256;\n\n    if (dst_len < 32) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    mbedtls_md_init(&sha256);\n    ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0);\n    if (ret != 0) {\n        goto exit;\n    }\n    ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    if ((ret = mbedtls_md_finish(&sha256, dst)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_md_finish\", ret);\n        goto exit;\n    }\n\n    *olen = 32;\n\nexit:\n\n    mbedtls_md_free(&sha256);\n    return ret;\n}\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\nint mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl,\n                                         const mbedtls_md_type_t md,\n                                         unsigned char *dst,\n                                         size_t dst_len,\n                                         size_t *olen)\n{\n    switch (md) {\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\n        case MBEDTLS_MD_SHA384:\n            return ssl_get_handshake_transcript_sha384(ssl, dst, dst_len, olen);\n#endif /* MBEDTLS_MD_CAN_SHA384*/\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\n        case MBEDTLS_MD_SHA256:\n            return ssl_get_handshake_transcript_sha256(ssl, dst, dst_len, olen);\n#endif /* MBEDTLS_MD_CAN_SHA256*/\n\n        default:\n#if !defined(MBEDTLS_MD_CAN_SHA384) && \\\n            !defined(MBEDTLS_MD_CAN_SHA256)\n            (void) ssl;\n            (void) dst;\n            (void) dst_len;\n            (void) olen;\n#endif\n            break;\n    }\n    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n}\n\n#endif /* !MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n/* mbedtls_ssl_parse_sig_alg_ext()\n *\n * The `extension_data` field of signature algorithm contains  a `SignatureSchemeList`\n * value (TLS 1.3 RFC8446):\n *      enum {\n *         ....\n *        ecdsa_secp256r1_sha256( 0x0403 ),\n *        ecdsa_secp384r1_sha384( 0x0503 ),\n *        ecdsa_secp521r1_sha512( 0x0603 ),\n *         ....\n *      } SignatureScheme;\n *\n *      struct {\n *         SignatureScheme supported_signature_algorithms<2..2^16-2>;\n *      } SignatureSchemeList;\n *\n * The `extension_data` field of signature algorithm contains a `SignatureAndHashAlgorithm`\n * value (TLS 1.2 RFC5246):\n *      enum {\n *          none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),\n *          sha512(6), (255)\n *      } HashAlgorithm;\n *\n *      enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }\n *        SignatureAlgorithm;\n *\n *      struct {\n *          HashAlgorithm hash;\n *          SignatureAlgorithm signature;\n *      } SignatureAndHashAlgorithm;\n *\n *      SignatureAndHashAlgorithm\n *        supported_signature_algorithms<2..2^16-2>;\n *\n * The TLS 1.3 signature algorithm extension was defined to be a compatible\n * generalization of the TLS 1.2 signature algorithm extension.\n * `SignatureAndHashAlgorithm` field of TLS 1.2 can be represented by\n * `SignatureScheme` field of TLS 1.3\n *\n */\nint mbedtls_ssl_parse_sig_alg_ext(mbedtls_ssl_context *ssl,\n                                  const unsigned char *buf,\n                                  const unsigned char *end)\n{\n    const unsigned char *p = buf;\n    size_t supported_sig_algs_len = 0;\n    const unsigned char *supported_sig_algs_end;\n    uint16_t sig_alg;\n    uint32_t common_idx = 0;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    supported_sig_algs_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n\n    memset(ssl->handshake->received_sig_algs, 0,\n           sizeof(ssl->handshake->received_sig_algs));\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, supported_sig_algs_len);\n    supported_sig_algs_end = p + supported_sig_algs_len;\n    while (p < supported_sig_algs_end) {\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, supported_sig_algs_end, 2);\n        sig_alg = MBEDTLS_GET_UINT16_BE(p, 0);\n        p += 2;\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"received signature algorithm: 0x%x %s\",\n                                  sig_alg,\n                                  mbedtls_ssl_sig_alg_to_str(sig_alg)));\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&\n            (!(mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg) &&\n               mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg)))) {\n            continue;\n        }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"valid signature algorithm: %s\",\n                                  mbedtls_ssl_sig_alg_to_str(sig_alg)));\n\n        if (common_idx + 1 < MBEDTLS_RECEIVED_SIG_ALGS_SIZE) {\n            ssl->handshake->received_sig_algs[common_idx] = sig_alg;\n            common_idx += 1;\n        }\n    }\n    /* Check that we consumed all the message. */\n    if (p != end) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"Signature algorithms extension length misaligned\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,\n                                     MBEDTLS_ERR_SSL_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    if (common_idx == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"no signature algorithm in common\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,\n                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    ssl->handshake->received_sig_algs[common_idx] = MBEDTLS_TLS_SIG_NONE;\n    return 0;\n}\n\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n\nstatic psa_status_t setup_psa_key_derivation(psa_key_derivation_operation_t *derivation,\n                                             mbedtls_svc_key_id_t key,\n                                             psa_algorithm_t alg,\n                                             const unsigned char *raw_psk, size_t raw_psk_length,\n                                             const unsigned char *seed, size_t seed_length,\n                                             const unsigned char *label, size_t label_length,\n                                             const unsigned char *other_secret,\n                                             size_t other_secret_length,\n                                             size_t capacity)\n{\n    psa_status_t status;\n\n    status = psa_key_derivation_setup(derivation, alg);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    if (PSA_ALG_IS_TLS12_PRF(alg) || PSA_ALG_IS_TLS12_PSK_TO_MS(alg)) {\n        status = psa_key_derivation_input_bytes(derivation,\n                                                PSA_KEY_DERIVATION_INPUT_SEED,\n                                                seed, seed_length);\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n\n        if (other_secret != NULL) {\n            status = psa_key_derivation_input_bytes(derivation,\n                                                    PSA_KEY_DERIVATION_INPUT_OTHER_SECRET,\n                                                    other_secret, other_secret_length);\n            if (status != PSA_SUCCESS) {\n                return status;\n            }\n        }\n\n        if (mbedtls_svc_key_id_is_null(key)) {\n            status = psa_key_derivation_input_bytes(\n                derivation, PSA_KEY_DERIVATION_INPUT_SECRET,\n                raw_psk, raw_psk_length);\n        } else {\n            status = psa_key_derivation_input_key(\n                derivation, PSA_KEY_DERIVATION_INPUT_SECRET, key);\n        }\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n\n        status = psa_key_derivation_input_bytes(derivation,\n                                                PSA_KEY_DERIVATION_INPUT_LABEL,\n                                                label, label_length);\n        if (status != PSA_SUCCESS) {\n            return status;\n        }\n    } else {\n        return PSA_ERROR_NOT_SUPPORTED;\n    }\n\n    status = psa_key_derivation_set_capacity(derivation, capacity);\n    if (status != PSA_SUCCESS) {\n        return status;\n    }\n\n    return PSA_SUCCESS;\n}\n\n#if defined(PSA_WANT_ALG_SHA_384) || \\\n    defined(PSA_WANT_ALG_SHA_256)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int tls_prf_generic(mbedtls_md_type_t md_type,\n                           const unsigned char *secret, size_t slen,\n                           const char *label, size_t label_len,\n                           const unsigned char *random, size_t rlen,\n                           unsigned char *dstbuf, size_t dlen)\n{\n    psa_status_t status;\n    psa_algorithm_t alg;\n    mbedtls_svc_key_id_t master_key = MBEDTLS_SVC_KEY_ID_INIT;\n    psa_key_derivation_operation_t derivation =\n        PSA_KEY_DERIVATION_OPERATION_INIT;\n\n    if (md_type == MBEDTLS_MD_SHA384) {\n        alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384);\n    } else {\n        alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256);\n    }\n\n    /* Normally a \"secret\" should be long enough to be impossible to\n     * find by brute force, and in particular should not be empty. But\n     * this PRF is also used to derive an IV, in particular in EAP-TLS,\n     * and for this use case it makes sense to have a 0-length \"secret\".\n     * Since the key API doesn't allow importing a key of length 0,\n     * keep master_key=0, which setup_psa_key_derivation() understands\n     * to mean a 0-length \"secret\" input. */\n    if (slen != 0) {\n        psa_key_attributes_t key_attributes = psa_key_attributes_init();\n        psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);\n        psa_set_key_algorithm(&key_attributes, alg);\n        psa_set_key_type(&key_attributes, PSA_KEY_TYPE_DERIVE);\n\n        status = psa_import_key(&key_attributes, secret, slen, &master_key);\n        if (status != PSA_SUCCESS) {\n            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n        }\n    }\n\n    status = setup_psa_key_derivation(&derivation,\n                                      master_key, alg,\n                                      NULL, 0,\n                                      random, rlen,\n                                      (unsigned char const *) label,\n                                      label_len,\n                                      NULL, 0,\n                                      dlen);\n    if (status != PSA_SUCCESS) {\n        psa_key_derivation_abort(&derivation);\n        psa_destroy_key(master_key);\n        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n    }\n\n    status = psa_key_derivation_output_bytes(&derivation, dstbuf, dlen);\n    if (status != PSA_SUCCESS) {\n        psa_key_derivation_abort(&derivation);\n        psa_destroy_key(master_key);\n        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n    }\n\n    status = psa_key_derivation_abort(&derivation);\n    if (status != PSA_SUCCESS) {\n        psa_destroy_key(master_key);\n        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n    }\n\n    if (!mbedtls_svc_key_id_is_null(master_key)) {\n        status = psa_destroy_key(master_key);\n    }\n    if (status != PSA_SUCCESS) {\n        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n    }\n\n    return 0;\n}\n#endif /* PSA_WANT_ALG_SHA_256 || PSA_WANT_ALG_SHA_384 */\n#else /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_MD_C) &&       \\\n    (defined(MBEDTLS_MD_CAN_SHA256) || \\\n    defined(MBEDTLS_MD_CAN_SHA384))\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int tls_prf_generic(mbedtls_md_type_t md_type,\n                           const unsigned char *secret, size_t slen,\n                           const char *label, size_t label_len,\n                           const unsigned char *random, size_t rlen,\n                           unsigned char *dstbuf, size_t dlen)\n{\n    size_t nb;\n    size_t i, j, k, md_len;\n    unsigned char *tmp;\n    size_t tmp_len = 0;\n    unsigned char h_i[MBEDTLS_MD_MAX_SIZE];\n    const mbedtls_md_info_t *md_info;\n    mbedtls_md_context_t md_ctx;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_md_init(&md_ctx);\n\n    if ((md_info = mbedtls_md_info_from_type(md_type)) == NULL) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    md_len = mbedtls_md_get_size(md_info);\n\n    tmp_len = md_len + label_len + rlen;\n    tmp = mbedtls_calloc(1, tmp_len);\n    if (tmp == NULL) {\n        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        goto exit;\n    }\n\n    nb = label_len;\n    memcpy(tmp + md_len, label, nb);\n    memcpy(tmp + md_len + nb, random, rlen);\n    nb += rlen;\n\n    /*\n     * Compute P_<hash>(secret, label + random)[0..dlen]\n     */\n    if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) {\n        goto exit;\n    }\n\n    ret = mbedtls_md_hmac_starts(&md_ctx, secret, slen);\n    if (ret != 0) {\n        goto exit;\n    }\n    ret = mbedtls_md_hmac_update(&md_ctx, tmp + md_len, nb);\n    if (ret != 0) {\n        goto exit;\n    }\n    ret = mbedtls_md_hmac_finish(&md_ctx, tmp);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    for (i = 0; i < dlen; i += md_len) {\n        ret = mbedtls_md_hmac_reset(&md_ctx);\n        if (ret != 0) {\n            goto exit;\n        }\n        ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len + nb);\n        if (ret != 0) {\n            goto exit;\n        }\n        ret = mbedtls_md_hmac_finish(&md_ctx, h_i);\n        if (ret != 0) {\n            goto exit;\n        }\n\n        ret = mbedtls_md_hmac_reset(&md_ctx);\n        if (ret != 0) {\n            goto exit;\n        }\n        ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len);\n        if (ret != 0) {\n            goto exit;\n        }\n        ret = mbedtls_md_hmac_finish(&md_ctx, tmp);\n        if (ret != 0) {\n            goto exit;\n        }\n\n        k = (i + md_len > dlen) ? dlen % md_len : md_len;\n\n        for (j = 0; j < k; j++) {\n            dstbuf[i + j]  = h_i[j];\n        }\n    }\n\nexit:\n    mbedtls_md_free(&md_ctx);\n\n    if (tmp != NULL) {\n        mbedtls_platform_zeroize(tmp, tmp_len);\n    }\n\n    mbedtls_platform_zeroize(h_i, sizeof(h_i));\n\n    mbedtls_free(tmp);\n\n    return ret;\n}\n#endif /* MBEDTLS_MD_C && ( MBEDTLS_MD_CAN_SHA256 || MBEDTLS_MD_CAN_SHA384 ) */\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int tls_prf_sha256(const unsigned char *secret, size_t slen,\n                          const char *label,\n                          const unsigned char *random, size_t rlen,\n                          unsigned char *dstbuf, size_t dlen)\n{\n    return tls_prf_generic(MBEDTLS_MD_SHA256, secret, slen,\n                           label, strlen(label), random, rlen, dstbuf, dlen);\n}\n#endif /* MBEDTLS_MD_CAN_SHA256*/\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int tls_prf_sha384(const unsigned char *secret, size_t slen,\n                          const char *label,\n                          const unsigned char *random, size_t rlen,\n                          unsigned char *dstbuf, size_t dlen)\n{\n    return tls_prf_generic(MBEDTLS_MD_SHA384, secret, slen,\n                           label, strlen(label), random, rlen, dstbuf, dlen);\n}\n#endif /* MBEDTLS_MD_CAN_SHA384*/\n\n/*\n * Set appropriate PRF function and other SSL / TLS1.2 functions\n *\n * Inputs:\n * - hash associated with the ciphersuite (only used by TLS 1.2)\n *\n * Outputs:\n * - the tls_prf, calc_verify and calc_finished members of handshake structure\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_set_handshake_prfs(mbedtls_ssl_handshake_params *handshake,\n                                  mbedtls_md_type_t hash)\n{\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    if (hash == MBEDTLS_MD_SHA384) {\n        handshake->tls_prf = tls_prf_sha384;\n        handshake->calc_verify = ssl_calc_verify_tls_sha384;\n        handshake->calc_finished = ssl_calc_finished_tls_sha384;\n    } else\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    {\n        (void) hash;\n        handshake->tls_prf = tls_prf_sha256;\n        handshake->calc_verify = ssl_calc_verify_tls_sha256;\n        handshake->calc_finished = ssl_calc_finished_tls_sha256;\n    }\n#else\n    {\n        (void) handshake;\n        (void) hash;\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n#endif\n\n    return 0;\n}\n\n/*\n * Compute master secret if needed\n *\n * Parameters:\n * [in/out] handshake\n *          [in] resume, premaster, extended_ms, calc_verify, tls_prf\n *               (PSA-PSK) ciphersuite_info, psk_opaque\n *          [out] premaster (cleared)\n * [out] master\n * [in] ssl: optionally used for debugging, EMS and PSA-PSK\n *      debug: conf->f_dbg, conf->p_dbg\n *      EMS: passed to calc_verify (debug + session_negotiate)\n *      PSA-PSA: conf\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_compute_master(mbedtls_ssl_handshake_params *handshake,\n                              unsigned char *master,\n                              const mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* cf. RFC 5246, Section 8.1:\n     * \"The master secret is always exactly 48 bytes in length.\" */\n    size_t const master_secret_len = 48;\n\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\n    unsigned char session_hash[48];\n#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */\n\n    /* The label for the KDF used for key expansion.\n     * This is either \"master secret\" or \"extended master secret\"\n     * depending on whether the Extended Master Secret extension\n     * is used. */\n    char const *lbl = \"master secret\";\n\n    /* The seed for the KDF used for key expansion.\n     * - If the Extended Master Secret extension is not used,\n     *   this is ClientHello.Random + ServerHello.Random\n     *   (see Sect. 8.1 in RFC 5246).\n     * - If the Extended Master Secret extension is used,\n     *   this is the transcript of the handshake so far.\n     *   (see Sect. 4 in RFC 7627). */\n    unsigned char const *seed = handshake->randbytes;\n    size_t seed_len = 64;\n\n#if !defined(MBEDTLS_DEBUG_C) &&                    \\\n    !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \\\n    !(defined(MBEDTLS_USE_PSA_CRYPTO) &&            \\\n    defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED))\n    ssl = NULL; /* make sure we don't use it except for those cases */\n    (void) ssl;\n#endif\n\n    if (handshake->resume != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"no premaster (session resumed)\"));\n        return 0;\n    }\n\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\n    if (handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) {\n        lbl  = \"extended master secret\";\n        seed = session_hash;\n        ret = handshake->calc_verify(ssl, session_hash, &seed_len);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"calc_verify\", ret);\n        }\n\n        MBEDTLS_SSL_DEBUG_BUF(3, \"session hash for extended master secret\",\n                              session_hash, seed_len);\n    }\n#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO) &&                   \\\n    defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)\n    if (mbedtls_ssl_ciphersuite_uses_psk(handshake->ciphersuite_info) == 1) {\n        /* Perform PSK-to-MS expansion in a single step. */\n        psa_status_t status;\n        psa_algorithm_t alg;\n        mbedtls_svc_key_id_t psk;\n        psa_key_derivation_operation_t derivation =\n            PSA_KEY_DERIVATION_OPERATION_INIT;\n        mbedtls_md_type_t hash_alg = (mbedtls_md_type_t) handshake->ciphersuite_info->mac;\n\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"perform PSA-based PSK-to-MS expansion\"));\n\n        psk = mbedtls_ssl_get_opaque_psk(ssl);\n\n        if (hash_alg == MBEDTLS_MD_SHA384) {\n            alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384);\n        } else {\n            alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256);\n        }\n\n        size_t other_secret_len = 0;\n        unsigned char *other_secret = NULL;\n\n        switch (handshake->ciphersuite_info->key_exchange) {\n            /* Provide other secret.\n             * Other secret is stored in premaster, where first 2 bytes hold the\n             * length of the other key.\n             */\n            case MBEDTLS_KEY_EXCHANGE_RSA_PSK:\n                /* For RSA-PSK other key length is always 48 bytes. */\n                other_secret_len = 48;\n                other_secret = handshake->premaster + 2;\n                break;\n            case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:\n            case MBEDTLS_KEY_EXCHANGE_DHE_PSK:\n                other_secret_len = MBEDTLS_GET_UINT16_BE(handshake->premaster, 0);\n                other_secret = handshake->premaster + 2;\n                break;\n            default:\n                break;\n        }\n\n        status = setup_psa_key_derivation(&derivation, psk, alg,\n                                          ssl->conf->psk, ssl->conf->psk_len,\n                                          seed, seed_len,\n                                          (unsigned char const *) lbl,\n                                          (size_t) strlen(lbl),\n                                          other_secret, other_secret_len,\n                                          master_secret_len);\n        if (status != PSA_SUCCESS) {\n            psa_key_derivation_abort(&derivation);\n            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n        }\n\n        status = psa_key_derivation_output_bytes(&derivation,\n                                                 master,\n                                                 master_secret_len);\n        if (status != PSA_SUCCESS) {\n            psa_key_derivation_abort(&derivation);\n            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n        }\n\n        status = psa_key_derivation_abort(&derivation);\n        if (status != PSA_SUCCESS) {\n            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n        }\n    } else\n#endif\n    {\n#if defined(MBEDTLS_USE_PSA_CRYPTO) &&                              \\\n        defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n        if (handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {\n            psa_status_t status;\n            psa_algorithm_t alg = PSA_ALG_TLS12_ECJPAKE_TO_PMS;\n            psa_key_derivation_operation_t derivation =\n                PSA_KEY_DERIVATION_OPERATION_INIT;\n\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"perform PSA-based PMS KDF for ECJPAKE\"));\n\n            handshake->pmslen = PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE;\n\n            status = psa_key_derivation_setup(&derivation, alg);\n            if (status != PSA_SUCCESS) {\n                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n            }\n\n            status = psa_key_derivation_set_capacity(&derivation,\n                                                     PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE);\n            if (status != PSA_SUCCESS) {\n                psa_key_derivation_abort(&derivation);\n                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n            }\n\n            status = psa_pake_get_implicit_key(&handshake->psa_pake_ctx,\n                                               &derivation);\n            if (status != PSA_SUCCESS) {\n                psa_key_derivation_abort(&derivation);\n                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n            }\n\n            status = psa_key_derivation_output_bytes(&derivation,\n                                                     handshake->premaster,\n                                                     handshake->pmslen);\n            if (status != PSA_SUCCESS) {\n                psa_key_derivation_abort(&derivation);\n                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n            }\n\n            status = psa_key_derivation_abort(&derivation);\n            if (status != PSA_SUCCESS) {\n                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n            }\n        }\n#endif\n        ret = handshake->tls_prf(handshake->premaster, handshake->pmslen,\n                                 lbl, seed, seed_len,\n                                 master,\n                                 master_secret_len);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"prf\", ret);\n            return ret;\n        }\n\n        MBEDTLS_SSL_DEBUG_BUF(3, \"premaster secret\",\n                              handshake->premaster,\n                              handshake->pmslen);\n\n        mbedtls_platform_zeroize(handshake->premaster,\n                                 sizeof(handshake->premaster));\n    }\n\n    return 0;\n}\n\nint mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> derive keys\"));\n\n    /* Set PRF, calc_verify and calc_finished function pointers */\n    ret = ssl_set_handshake_prfs(ssl->handshake,\n                                 (mbedtls_md_type_t) ciphersuite_info->mac);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_set_handshake_prfs\", ret);\n        return ret;\n    }\n\n    /* Compute master secret if needed */\n    ret = ssl_compute_master(ssl->handshake,\n                             ssl->session_negotiate->master,\n                             ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_compute_master\", ret);\n        return ret;\n    }\n\n    /* Swap the client and server random values:\n     * - MS derivation wanted client+server (RFC 5246 8.1)\n     * - key derivation wants server+client (RFC 5246 6.3) */\n    {\n        unsigned char tmp[64];\n        memcpy(tmp, ssl->handshake->randbytes, 64);\n        memcpy(ssl->handshake->randbytes, tmp + 32, 32);\n        memcpy(ssl->handshake->randbytes + 32, tmp, 32);\n        mbedtls_platform_zeroize(tmp, sizeof(tmp));\n    }\n\n    /* Populate transform structure */\n    ret = ssl_tls12_populate_transform(ssl->transform_negotiate,\n                                       ssl->session_negotiate->ciphersuite,\n                                       ssl->session_negotiate->master,\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)\n                                       ssl->session_negotiate->encrypt_then_mac,\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */\n                                       ssl->handshake->tls_prf,\n                                       ssl->handshake->randbytes,\n                                       ssl->tls_version,\n                                       ssl->conf->endpoint,\n                                       ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_tls12_populate_transform\", ret);\n        return ret;\n    }\n\n    /* We no longer need Server/ClientHello.random values */\n    mbedtls_platform_zeroize(ssl->handshake->randbytes,\n                             sizeof(ssl->handshake->randbytes));\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= derive keys\"));\n\n    return 0;\n}\n\nint mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md)\n{\n    switch (md) {\n#if defined(MBEDTLS_MD_CAN_SHA384)\n        case MBEDTLS_SSL_HASH_SHA384:\n            ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384;\n            break;\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA256)\n        case MBEDTLS_SSL_HASH_SHA256:\n            ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256;\n            break;\n#endif\n        default:\n            return -1;\n    }\n#if !defined(MBEDTLS_MD_CAN_SHA384) && \\\n    !defined(MBEDTLS_MD_CAN_SHA256)\n    (void) ssl;\n#endif\n    return 0;\n}\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nstatic int ssl_calc_verify_tls_psa(const mbedtls_ssl_context *ssl,\n                                   const psa_hash_operation_t *hs_op,\n                                   size_t buffer_size,\n                                   unsigned char *hash,\n                                   size_t *hlen)\n{\n    psa_status_t status;\n    psa_hash_operation_t cloned_op = psa_hash_operation_init();\n\n#if !defined(MBEDTLS_DEBUG_C)\n    (void) ssl;\n#endif\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> PSA calc verify\"));\n    status = psa_hash_clone(hs_op, &cloned_op);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_finish(&cloned_op, hash, buffer_size, hlen);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"PSA calculated verify result\", hash, *hlen);\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= PSA calc verify\"));\n\nexit:\n    psa_hash_abort(&cloned_op);\n    return mbedtls_md_error_from_psa(status);\n}\n#else\nstatic int ssl_calc_verify_tls_legacy(const mbedtls_ssl_context *ssl,\n                                      const mbedtls_md_context_t *hs_ctx,\n                                      unsigned char *hash,\n                                      size_t *hlen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_md_context_t cloned_ctx;\n\n    mbedtls_md_init(&cloned_ctx);\n\n#if !defined(MBEDTLS_DEBUG_C)\n    (void) ssl;\n#endif\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> calc verify\"));\n\n    ret = mbedtls_md_setup(&cloned_ctx, mbedtls_md_info_from_ctx(hs_ctx), 0);\n    if (ret != 0) {\n        goto exit;\n    }\n    ret = mbedtls_md_clone(&cloned_ctx, hs_ctx);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    ret = mbedtls_md_finish(&cloned_ctx, hash);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    *hlen = mbedtls_md_get_size(mbedtls_md_info_from_ctx(hs_ctx));\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"calculated verify result\", hash, *hlen);\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= calc verify\"));\n\nexit:\n    mbedtls_md_free(&cloned_ctx);\n    return ret;\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\nint ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *ssl,\n                               unsigned char *hash,\n                               size_t *hlen)\n{\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    return ssl_calc_verify_tls_psa(ssl, &ssl->handshake->fin_sha256_psa, 32,\n                                   hash, hlen);\n#else\n    return ssl_calc_verify_tls_legacy(ssl, &ssl->handshake->fin_sha256,\n                                      hash, hlen);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n}\n#endif /* MBEDTLS_MD_CAN_SHA256 */\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\nint ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *ssl,\n                               unsigned char *hash,\n                               size_t *hlen)\n{\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    return ssl_calc_verify_tls_psa(ssl, &ssl->handshake->fin_sha384_psa, 48,\n                                   hash, hlen);\n#else\n    return ssl_calc_verify_tls_legacy(ssl, &ssl->handshake->fin_sha384,\n                                      hash, hlen);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n}\n#endif /* MBEDTLS_MD_CAN_SHA384 */\n\n#if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                      \\\n    defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)\nint mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex)\n{\n    unsigned char *p = ssl->handshake->premaster;\n    unsigned char *end = p + sizeof(ssl->handshake->premaster);\n    const unsigned char *psk = NULL;\n    size_t psk_len = 0;\n    int psk_ret = mbedtls_ssl_get_psk(ssl, &psk, &psk_len);\n\n    if (psk_ret == MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) {\n        /*\n         * This should never happen because the existence of a PSK is always\n         * checked before calling this function.\n         *\n         * The exception is opaque DHE-PSK. For DHE-PSK fill premaster with\n         * the shared secret without PSK.\n         */\n        if (key_ex != MBEDTLS_KEY_EXCHANGE_DHE_PSK) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n    }\n\n    /*\n     * PMS = struct {\n     *     opaque other_secret<0..2^16-1>;\n     *     opaque psk<0..2^16-1>;\n     * };\n     * with \"other_secret\" depending on the particular key exchange\n     */\n#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)\n    if (key_ex == MBEDTLS_KEY_EXCHANGE_PSK) {\n        if (end - p < 2) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        MBEDTLS_PUT_UINT16_BE(psk_len, p, 0);\n        p += 2;\n\n        if (end < p || (size_t) (end - p) < psk_len) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        memset(p, 0, psk_len);\n        p += psk_len;\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)\n    if (key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {\n        /*\n         * other_secret already set by the ClientKeyExchange message,\n         * and is 48 bytes long\n         */\n        if (end - p < 2) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        *p++ = 0;\n        *p++ = 48;\n        p += 48;\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)\n    if (key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n        size_t len;\n\n        /* Write length only when we know the actual value */\n        if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx,\n                                           p + 2, (size_t) (end - (p + 2)), &len,\n                                           ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_dhm_calc_secret\", ret);\n            return ret;\n        }\n        MBEDTLS_PUT_UINT16_BE(len, p, 0);\n        p += 2 + len;\n\n        MBEDTLS_SSL_DEBUG_MPI(3, \"DHM: K \", &ssl->handshake->dhm_ctx.K);\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)\n    if (key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n        size_t zlen;\n\n        if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx, &zlen,\n                                            p + 2, (size_t) (end - (p + 2)),\n                                            ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecdh_calc_secret\", ret);\n            return ret;\n        }\n\n        MBEDTLS_PUT_UINT16_BE(zlen, p, 0);\n        p += 2 + zlen;\n\n        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,\n                               MBEDTLS_DEBUG_ECDH_Z);\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */\n    {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    /* opaque psk<0..2^16-1>; */\n    if (end - p < 2) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    MBEDTLS_PUT_UINT16_BE(psk_len, p, 0);\n    p += 2;\n\n    if (end < p || (size_t) (end - p) < psk_len) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    memcpy(p, psk, psk_len);\n    p += psk_len;\n\n    ssl->handshake->pmslen = (size_t) (p - ssl->handshake->premaster);\n\n    return 0;\n}\n#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */\n\n#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_hello_request(mbedtls_ssl_context *ssl);\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\nint mbedtls_ssl_resend_hello_request(mbedtls_ssl_context *ssl)\n{\n    /* If renegotiation is not enforced, retransmit until we would reach max\n     * timeout if we were using the usual handshake doubling scheme */\n    if (ssl->conf->renego_max_records < 0) {\n        uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1;\n        unsigned char doublings = 1;\n\n        while (ratio != 0) {\n            ++doublings;\n            ratio >>= 1;\n        }\n\n        if (++ssl->renego_records_seen > doublings) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"no longer retransmitting hello request\"));\n            return 0;\n        }\n    }\n\n    return ssl_write_hello_request(ssl);\n}\n#endif\n#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */\n\n/*\n * Handshake functions\n */\n#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)\n/* No certificate support -> dummy functions */\nint mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl)\n{\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write certificate\"));\n\n    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip write certificate\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n}\n\nint mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl)\n{\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse certificate\"));\n\n    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip parse certificate\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n}\n\n#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */\n/* Some certificate support -> implement write and parse */\n\nint mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    size_t i, n;\n    const mbedtls_x509_crt *crt;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write certificate\"));\n\n    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip write certificate\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n\n#if defined(MBEDTLS_SSL_CLI_C)\n    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {\n        if (ssl->handshake->client_auth == 0) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip write certificate\"));\n            mbedtls_ssl_handshake_increment_state(ssl);\n            return 0;\n        }\n    }\n#endif /* MBEDTLS_SSL_CLI_C */\n#if defined(MBEDTLS_SSL_SRV_C)\n    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {\n        if (mbedtls_ssl_own_cert(ssl) == NULL) {\n            /* Should never happen because we shouldn't have picked the\n             * ciphersuite if we don't have a certificate. */\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n    }\n#endif\n\n    MBEDTLS_SSL_DEBUG_CRT(3, \"own certificate\", mbedtls_ssl_own_cert(ssl));\n\n    /*\n     *     0  .  0    handshake type\n     *     1  .  3    handshake length\n     *     4  .  6    length of all certs\n     *     7  .  9    length of cert. 1\n     *    10  . n-1   peer certificate\n     *     n  . n+2   length of cert. 2\n     *    n+3 . ...   upper level cert, etc.\n     */\n    i = 7;\n    crt = mbedtls_ssl_own_cert(ssl);\n\n    while (crt != NULL) {\n        n = crt->raw.len;\n        if (n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"certificate too large, %\" MBEDTLS_PRINTF_SIZET\n                                      \" > %\" MBEDTLS_PRINTF_SIZET,\n                                      i + 3 + n, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN));\n            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n        }\n\n        ssl->out_msg[i] = MBEDTLS_BYTE_2(n);\n        ssl->out_msg[i + 1] = MBEDTLS_BYTE_1(n);\n        ssl->out_msg[i + 2] = MBEDTLS_BYTE_0(n);\n\n        i += 3; memcpy(ssl->out_msg + i, crt->raw.p, n);\n        i += n; crt = crt->next;\n    }\n\n    ssl->out_msg[4]  = MBEDTLS_BYTE_2(i - 7);\n    ssl->out_msg[5]  = MBEDTLS_BYTE_1(i - 7);\n    ssl->out_msg[6]  = MBEDTLS_BYTE_0(i - 7);\n\n    ssl->out_msglen  = i;\n    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;\n    ssl->out_msg[0]  = MBEDTLS_SSL_HS_CERTIFICATE;\n\n    mbedtls_ssl_handshake_increment_state(ssl);\n\n    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_write_handshake_msg\", ret);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write certificate\"));\n\n    return ret;\n}\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)\n\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl,\n                                        unsigned char *crt_buf,\n                                        size_t crt_buf_len)\n{\n    mbedtls_x509_crt const * const peer_crt = ssl->session->peer_cert;\n\n    if (peer_crt == NULL) {\n        return -1;\n    }\n\n    if (peer_crt->raw.len != crt_buf_len) {\n        return -1;\n    }\n\n    return memcmp(peer_crt->raw.p, crt_buf, peer_crt->raw.len);\n}\n#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl,\n                                        unsigned char *crt_buf,\n                                        size_t crt_buf_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char const * const peer_cert_digest =\n        ssl->session->peer_cert_digest;\n    mbedtls_md_type_t const peer_cert_digest_type =\n        ssl->session->peer_cert_digest_type;\n    mbedtls_md_info_t const * const digest_info =\n        mbedtls_md_info_from_type(peer_cert_digest_type);\n    unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN];\n    size_t digest_len;\n\n    if (peer_cert_digest == NULL || digest_info == NULL) {\n        return -1;\n    }\n\n    digest_len = mbedtls_md_get_size(digest_info);\n    if (digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN) {\n        return -1;\n    }\n\n    ret = mbedtls_md(digest_info, crt_buf, crt_buf_len, tmp_digest);\n    if (ret != 0) {\n        return -1;\n    }\n\n    return memcmp(tmp_digest, peer_cert_digest, digest_len);\n}\n#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */\n\n/*\n * Once the certificate message is read, parse it into a cert chain and\n * perform basic checks, but leave actual verification to the caller\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_certificate_chain(mbedtls_ssl_context *ssl,\n                                       mbedtls_x509_crt *chain)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)\n    int crt_cnt = 0;\n#endif\n    size_t i, n;\n    uint8_t alert;\n\n    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n    if (ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE) {\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n    if (ssl->in_hslen < mbedtls_ssl_hs_hdr_len(ssl) + 3 + 3) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    i = mbedtls_ssl_hs_hdr_len(ssl);\n\n    /*\n     * Same message structure as in mbedtls_ssl_write_certificate()\n     */\n    n = MBEDTLS_GET_UINT16_BE(ssl->in_msg, i + 1);\n\n    if (ssl->in_msg[i] != 0 ||\n        ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len(ssl)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */\n    i += 3;\n\n    /* Iterate through and parse the CRTs in the provided chain. */\n    while (i < ssl->in_hslen) {\n        /* Check that there's room for the next CRT's length fields. */\n        if (i + 3 > ssl->in_hslen) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate message\"));\n            mbedtls_ssl_send_alert_message(ssl,\n                                           MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n        /* In theory, the CRT can be up to 2**24 Bytes, but we don't support\n         * anything beyond 2**16 ~ 64K. */\n        if (ssl->in_msg[i] != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate message\"));\n            mbedtls_ssl_send_alert_message(ssl,\n                                           MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                           MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT);\n            return MBEDTLS_ERR_SSL_BAD_CERTIFICATE;\n        }\n\n        /* Read length of the next CRT in the chain. */\n        n = MBEDTLS_GET_UINT16_BE(ssl->in_msg, i + 1);\n        i += 3;\n\n        if (n < 128 || i + n > ssl->in_hslen) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate message\"));\n            mbedtls_ssl_send_alert_message(ssl,\n                                           MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n\n        /* Check if we're handling the first CRT in the chain. */\n#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)\n        if (crt_cnt++ == 0 &&\n            ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&\n            ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {\n            /* During client-side renegotiation, check that the server's\n             * end-CRTs hasn't changed compared to the initial handshake,\n             * mitigating the triple handshake attack. On success, reuse\n             * the original end-CRT instead of parsing it again. */\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"Check that peer CRT hasn't changed during renegotiation\"));\n            if (ssl_check_peer_crt_unchanged(ssl,\n                                             &ssl->in_msg[i],\n                                             n) != 0) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"new server cert during renegotiation\"));\n                mbedtls_ssl_send_alert_message(ssl,\n                                               MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                               MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED);\n                return MBEDTLS_ERR_SSL_BAD_CERTIFICATE;\n            }\n\n            /* Now we can safely free the original chain. */\n            ssl_clear_peer_cert(ssl->session);\n        }\n#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */\n\n        /* Parse the next certificate in the chain. */\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n        ret = mbedtls_x509_crt_parse_der(chain, ssl->in_msg + i, n);\n#else\n        /* If we don't need to store the CRT chain permanently, parse\n         * it in-place from the input buffer instead of making a copy. */\n        ret = mbedtls_x509_crt_parse_der_nocopy(chain, ssl->in_msg + i, n);\n#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n        switch (ret) {\n            case 0: /*ok*/\n            case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND:\n                /* Ignore certificate with an unknown algorithm: maybe a\n                   prior certificate was already trusted. */\n                break;\n\n            case MBEDTLS_ERR_X509_ALLOC_FAILED:\n                alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR;\n                goto crt_parse_der_failed;\n\n            case MBEDTLS_ERR_X509_UNKNOWN_VERSION:\n                alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;\n                goto crt_parse_der_failed;\n\n            default:\n                alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;\ncrt_parse_der_failed:\n                mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert);\n                MBEDTLS_SSL_DEBUG_RET(1, \" mbedtls_x509_crt_parse_der\", ret);\n                return ret;\n        }\n\n        i += n;\n    }\n\n    MBEDTLS_SSL_DEBUG_CRT(3, \"peer certificate\", chain);\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_SRV_C)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_srv_check_client_no_crt_notification(mbedtls_ssl_context *ssl)\n{\n    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {\n        return -1;\n    }\n\n    if (ssl->in_hslen   == 3 + mbedtls_ssl_hs_hdr_len(ssl) &&\n        ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE    &&\n        ssl->in_msg[0]  == MBEDTLS_SSL_HS_CERTIFICATE   &&\n        memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl), \"\\0\\0\\0\", 3) == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"peer has no certificate\"));\n        return 0;\n    }\n    return -1;\n}\n#endif /* MBEDTLS_SSL_SRV_C */\n\n/* Check if a certificate message is expected.\n * Return either\n * - SSL_CERTIFICATE_EXPECTED, or\n * - SSL_CERTIFICATE_SKIP\n * indicating whether a Certificate message is expected or not.\n */\n#define SSL_CERTIFICATE_EXPECTED 0\n#define SSL_CERTIFICATE_SKIP     1\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_certificate_coordinate(mbedtls_ssl_context *ssl,\n                                            int authmode)\n{\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n\n    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {\n        return SSL_CERTIFICATE_SKIP;\n    }\n\n#if defined(MBEDTLS_SSL_SRV_C)\n    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {\n        if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {\n            return SSL_CERTIFICATE_SKIP;\n        }\n\n        if (authmode == MBEDTLS_SSL_VERIFY_NONE) {\n            ssl->session_negotiate->verify_result =\n                MBEDTLS_X509_BADCERT_SKIP_VERIFY;\n            return SSL_CERTIFICATE_SKIP;\n        }\n    }\n#else\n    ((void) authmode);\n#endif /* MBEDTLS_SSL_SRV_C */\n\n    return SSL_CERTIFICATE_EXPECTED;\n}\n\n#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_remember_peer_crt_digest(mbedtls_ssl_context *ssl,\n                                        unsigned char *start, size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    /* Remember digest of the peer's end-CRT. */\n    ssl->session_negotiate->peer_cert_digest =\n        mbedtls_calloc(1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN);\n    if (ssl->session_negotiate->peer_cert_digest == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"alloc(%d bytes) failed\",\n                                  MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN));\n        mbedtls_ssl_send_alert_message(ssl,\n                                       MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);\n\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n    ret = mbedtls_md(mbedtls_md_info_from_type(\n                         MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE),\n                     start, len,\n                     ssl->session_negotiate->peer_cert_digest);\n\n    ssl->session_negotiate->peer_cert_digest_type =\n        MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE;\n    ssl->session_negotiate->peer_cert_digest_len =\n        MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN;\n\n    return ret;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_remember_peer_pubkey(mbedtls_ssl_context *ssl,\n                                    unsigned char *start, size_t len)\n{\n    unsigned char *end = start + len;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /* Make a copy of the peer's raw public key. */\n    mbedtls_pk_init(&ssl->handshake->peer_pubkey);\n    ret = mbedtls_pk_parse_subpubkey(&start, end,\n                                     &ssl->handshake->peer_pubkey);\n    if (ret != 0) {\n        /* We should have parsed the public key before. */\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    return 0;\n}\n#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n\nint mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl)\n{\n    int ret = 0;\n    int crt_expected;\n    /* Authmode: precedence order is SNI if used else configuration */\n#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET\n                       ? ssl->handshake->sni_authmode\n                       : ssl->conf->authmode;\n#else\n    const int authmode = ssl->conf->authmode;\n#endif\n    void *rs_ctx = NULL;\n    mbedtls_x509_crt *chain = NULL;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse certificate\"));\n\n    crt_expected = ssl_parse_certificate_coordinate(ssl, authmode);\n    if (crt_expected == SSL_CERTIFICATE_SKIP) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip parse certificate\"));\n        goto exit;\n    }\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n    if (ssl->handshake->ecrs_enabled &&\n        ssl->handshake->ecrs_state == ssl_ecrs_crt_verify) {\n        chain = ssl->handshake->ecrs_peer_cert;\n        ssl->handshake->ecrs_peer_cert = NULL;\n        goto crt_verify;\n    }\n#endif\n\n    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {\n        /* mbedtls_ssl_read_record may have sent an alert already. We\n           let it decide whether to alert. */\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_read_record\", ret);\n        goto exit;\n    }\n\n#if defined(MBEDTLS_SSL_SRV_C)\n    if (ssl_srv_check_client_no_crt_notification(ssl) == 0) {\n        ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;\n\n        if (authmode != MBEDTLS_SSL_VERIFY_OPTIONAL) {\n            ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE;\n        }\n\n        goto exit;\n    }\n#endif /* MBEDTLS_SSL_SRV_C */\n\n    /* Clear existing peer CRT structure in case we tried to\n     * reuse a session but it failed, and allocate a new one. */\n    ssl_clear_peer_cert(ssl->session_negotiate);\n\n    chain = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));\n    if (chain == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"alloc(%\" MBEDTLS_PRINTF_SIZET \" bytes) failed\",\n                                  sizeof(mbedtls_x509_crt)));\n        mbedtls_ssl_send_alert_message(ssl,\n                                       MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);\n\n        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        goto exit;\n    }\n    mbedtls_x509_crt_init(chain);\n\n    ret = ssl_parse_certificate_chain(ssl, chain);\n    if (ret != 0) {\n        goto exit;\n    }\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n    if (ssl->handshake->ecrs_enabled) {\n        ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;\n    }\n\ncrt_verify:\n    if (ssl->handshake->ecrs_enabled) {\n        rs_ctx = &ssl->handshake->ecrs_ctx;\n    }\n#endif\n\n    ret = mbedtls_ssl_verify_certificate(ssl, authmode, chain,\n                                         ssl->handshake->ciphersuite_info,\n                                         rs_ctx);\n    if (ret != 0) {\n        goto exit;\n    }\n\n#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    {\n        unsigned char *crt_start, *pk_start;\n        size_t crt_len, pk_len;\n\n        /* We parse the CRT chain without copying, so\n         * these pointers point into the input buffer,\n         * and are hence still valid after freeing the\n         * CRT chain. */\n\n        crt_start = chain->raw.p;\n        crt_len   = chain->raw.len;\n\n        pk_start = chain->pk_raw.p;\n        pk_len   = chain->pk_raw.len;\n\n        /* Free the CRT structures before computing\n         * digest and copying the peer's public key. */\n        mbedtls_x509_crt_free(chain);\n        mbedtls_free(chain);\n        chain = NULL;\n\n        ret = ssl_remember_peer_crt_digest(ssl, crt_start, crt_len);\n        if (ret != 0) {\n            goto exit;\n        }\n\n        ret = ssl_remember_peer_pubkey(ssl, pk_start, pk_len);\n        if (ret != 0) {\n            goto exit;\n        }\n    }\n#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n    /* Pass ownership to session structure. */\n    ssl->session_negotiate->peer_cert = chain;\n    chain = NULL;\n#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse certificate\"));\n\nexit:\n\n    if (ret == 0) {\n        mbedtls_ssl_handshake_increment_state(ssl);\n    }\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n    if (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) {\n        ssl->handshake->ecrs_peer_cert = chain;\n        chain = NULL;\n    }\n#endif\n\n    if (chain != NULL) {\n        mbedtls_x509_crt_free(chain);\n        mbedtls_free(chain);\n    }\n\n    return ret;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */\n\nstatic int ssl_calc_finished_tls_generic(mbedtls_ssl_context *ssl, void *ctx,\n                                         unsigned char *padbuf, size_t hlen,\n                                         unsigned char *buf, int from)\n{\n    unsigned int len = 12;\n    const char *sender;\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_status_t status;\n    psa_hash_operation_t *hs_op = ctx;\n    psa_hash_operation_t cloned_op = PSA_HASH_OPERATION_INIT;\n    size_t hash_size;\n#else\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_md_context_t *hs_ctx = ctx;\n    mbedtls_md_context_t cloned_ctx;\n    mbedtls_md_init(&cloned_ctx);\n#endif\n\n    mbedtls_ssl_session *session = ssl->session_negotiate;\n    if (!session) {\n        session = ssl->session;\n    }\n\n    sender = (from == MBEDTLS_SSL_IS_CLIENT)\n             ? \"client finished\"\n             : \"server finished\";\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> calc PSA finished tls\"));\n\n    status = psa_hash_clone(hs_op, &cloned_op);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n\n    status = psa_hash_finish(&cloned_op, padbuf, hlen, &hash_size);\n    if (status != PSA_SUCCESS) {\n        goto exit;\n    }\n    MBEDTLS_SSL_DEBUG_BUF(3, \"PSA calculated padbuf\", padbuf, hlen);\n#else\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> calc finished tls\"));\n\n    ret = mbedtls_md_setup(&cloned_ctx, mbedtls_md_info_from_ctx(hs_ctx), 0);\n    if (ret != 0) {\n        goto exit;\n    }\n    ret = mbedtls_md_clone(&cloned_ctx, hs_ctx);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    ret = mbedtls_md_finish(&cloned_ctx, padbuf);\n    if (ret != 0) {\n        goto exit;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"finished output\", padbuf, hlen);\n\n    /*\n     * TLSv1.2:\n     *   hash = PRF( master, finished_label,\n     *               Hash( handshake ) )[0.11]\n     */\n    ssl->handshake->tls_prf(session->master, 48, sender,\n                            padbuf, hlen, buf, len);\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"calc finished result\", buf, len);\n\n    mbedtls_platform_zeroize(padbuf, hlen);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= calc finished\"));\n\nexit:\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_hash_abort(&cloned_op);\n    return mbedtls_md_error_from_psa(status);\n#else\n    mbedtls_md_free(&cloned_ctx);\n    return ret;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n}\n\n#if defined(MBEDTLS_MD_CAN_SHA256)\nstatic int ssl_calc_finished_tls_sha256(\n    mbedtls_ssl_context *ssl, unsigned char *buf, int from)\n{\n    unsigned char padbuf[32];\n    return ssl_calc_finished_tls_generic(ssl,\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n                                         &ssl->handshake->fin_sha256_psa,\n#else\n                                         &ssl->handshake->fin_sha256,\n#endif\n                                         padbuf, sizeof(padbuf),\n                                         buf, from);\n}\n#endif /* MBEDTLS_MD_CAN_SHA256*/\n\n\n#if defined(MBEDTLS_MD_CAN_SHA384)\nstatic int ssl_calc_finished_tls_sha384(\n    mbedtls_ssl_context *ssl, unsigned char *buf, int from)\n{\n    unsigned char padbuf[48];\n    return ssl_calc_finished_tls_generic(ssl,\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n                                         &ssl->handshake->fin_sha384_psa,\n#else\n                                         &ssl->handshake->fin_sha384,\n#endif\n                                         padbuf, sizeof(padbuf),\n                                         buf, from);\n}\n#endif /* MBEDTLS_MD_CAN_SHA384*/\n\nvoid mbedtls_ssl_handshake_wrapup_free_hs_transform(mbedtls_ssl_context *ssl)\n{\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"=> handshake wrapup: final free\"));\n\n    /*\n     * Free our handshake params\n     */\n    mbedtls_ssl_handshake_free(ssl);\n    mbedtls_free(ssl->handshake);\n    ssl->handshake = NULL;\n\n    /*\n     * Free the previous transform and switch in the current one\n     */\n    if (ssl->transform) {\n        mbedtls_ssl_transform_free(ssl->transform);\n        mbedtls_free(ssl->transform);\n    }\n    ssl->transform = ssl->transform_negotiate;\n    ssl->transform_negotiate = NULL;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"<= handshake wrapup: final free\"));\n}\n\nvoid mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl)\n{\n    int resume = ssl->handshake->resume;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"=> handshake wrapup\"));\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {\n        ssl->renego_status =  MBEDTLS_SSL_RENEGOTIATION_DONE;\n        ssl->renego_records_seen = 0;\n    }\n#endif\n\n    /*\n     * Free the previous session and switch in the current one\n     */\n    if (ssl->session) {\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n        /* RFC 7366 3.1: keep the EtM state */\n        ssl->session_negotiate->encrypt_then_mac =\n            ssl->session->encrypt_then_mac;\n#endif\n\n        mbedtls_ssl_session_free(ssl->session);\n        mbedtls_free(ssl->session);\n    }\n    ssl->session = ssl->session_negotiate;\n    ssl->session_negotiate = NULL;\n\n    /*\n     * Add cache entry\n     */\n    if (ssl->conf->f_set_cache != NULL &&\n        ssl->session->id_len != 0 &&\n        resume == 0) {\n        if (ssl->conf->f_set_cache(ssl->conf->p_cache,\n                                   ssl->session->id,\n                                   ssl->session->id_len,\n                                   ssl->session) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"cache did not store session\"));\n        }\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n        ssl->handshake->flight != NULL) {\n        /* Cancel handshake timer */\n        mbedtls_ssl_set_timer(ssl, 0);\n\n        /* Keep last flight around in case we need to resend it:\n         * we need the handshake and transform structures for that */\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"skip freeing handshake and transform\"));\n    } else\n#endif\n    mbedtls_ssl_handshake_wrapup_free_hs_transform(ssl);\n\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"<= handshake wrapup\"));\n}\n\nint mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl)\n{\n    int ret;\n    unsigned int hash_len;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write finished\"));\n\n    mbedtls_ssl_update_out_pointers(ssl, ssl->transform_negotiate);\n\n    ret = ssl->handshake->calc_finished(ssl, ssl->out_msg + 4, ssl->conf->endpoint);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"calc_finished\", ret);\n        return ret;\n    }\n\n    /*\n     * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites\n     * may define some other value. Currently (early 2016), no defined\n     * ciphersuite does this (and this is unlikely to change as activity has\n     * moved to TLS 1.3 now) so we can keep the hardcoded 12 here.\n     */\n    hash_len = 12;\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    ssl->verify_data_len = hash_len;\n    memcpy(ssl->own_verify_data, ssl->out_msg + 4, hash_len);\n#endif\n\n    ssl->out_msglen  = 4 + hash_len;\n    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;\n    ssl->out_msg[0]  = MBEDTLS_SSL_HS_FINISHED;\n\n    /*\n     * In case of session resuming, invert the client and server\n     * ChangeCipherSpec messages order.\n     */\n    if (ssl->handshake->resume != 0) {\n#if defined(MBEDTLS_SSL_CLI_C)\n        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {\n            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP);\n        }\n#endif\n#if defined(MBEDTLS_SSL_SRV_C)\n        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {\n            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC);\n        }\n#endif\n    } else {\n        mbedtls_ssl_handshake_increment_state(ssl);\n    }\n\n    /*\n     * Switch to our negotiated transform and session parameters for outbound\n     * data.\n     */\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"switching to new transform spec for outbound data\"));\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        unsigned char i;\n\n        /* Remember current epoch settings for resending */\n        ssl->handshake->alt_transform_out = ssl->transform_out;\n        memcpy(ssl->handshake->alt_out_ctr, ssl->cur_out_ctr,\n               sizeof(ssl->handshake->alt_out_ctr));\n\n        /* Set sequence_number to zero */\n        memset(&ssl->cur_out_ctr[2], 0, sizeof(ssl->cur_out_ctr) - 2);\n\n\n        /* Increment epoch */\n        for (i = 2; i > 0; i--) {\n            if (++ssl->cur_out_ctr[i - 1] != 0) {\n                break;\n            }\n        }\n\n        /* The loop goes to its end iff the counter is wrapping */\n        if (i == 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"DTLS epoch would wrap\"));\n            return MBEDTLS_ERR_SSL_COUNTER_WRAPPING;\n        }\n    } else\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n    memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr));\n\n    ssl->transform_out = ssl->transform_negotiate;\n    ssl->session_out = ssl->session_negotiate;\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        mbedtls_ssl_send_flight_completed(ssl);\n    }\n#endif\n\n    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_write_handshake_msg\", ret);\n        return ret;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n        (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_flight_transmit\", ret);\n        return ret;\n    }\n#endif\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write finished\"));\n\n    return 0;\n}\n\n#define SSL_MAX_HASH_LEN 12\n\nint mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned int hash_len = 12;\n    unsigned char buf[SSL_MAX_HASH_LEN];\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse finished\"));\n\n    ret = ssl->handshake->calc_finished(ssl, buf, ssl->conf->endpoint ^ 1);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"calc_finished\", ret);\n        return ret;\n    }\n\n    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_read_record\", ret);\n        goto exit;\n    }\n\n    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad finished message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);\n        ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n        goto exit;\n    }\n\n    if (ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED) {\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);\n        ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n        goto exit;\n    }\n\n    if (ssl->in_hslen  != mbedtls_ssl_hs_hdr_len(ssl) + hash_len) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad finished message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        ret = MBEDTLS_ERR_SSL_DECODE_ERROR;\n        goto exit;\n    }\n\n    if (mbedtls_ct_memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl),\n                          buf, hash_len) != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad finished message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR);\n        ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n        goto exit;\n    }\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    ssl->verify_data_len = hash_len;\n    memcpy(ssl->peer_verify_data, buf, hash_len);\n#endif\n\n    if (ssl->handshake->resume != 0) {\n#if defined(MBEDTLS_SSL_CLI_C)\n        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {\n            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC);\n        }\n#endif\n#if defined(MBEDTLS_SSL_SRV_C)\n        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {\n            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP);\n        }\n#endif\n    } else {\n        mbedtls_ssl_handshake_increment_state(ssl);\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        mbedtls_ssl_recv_flight_completed(ssl);\n    }\n#endif\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse finished\"));\n\nexit:\n    mbedtls_platform_zeroize(buf, hash_len);\n    return ret;\n}\n\n#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)\n/*\n * Helper to get TLS 1.2 PRF from ciphersuite\n * (Duplicates bits of logic from ssl_set_handshake_prfs().)\n */\nstatic tls_prf_fn ssl_tls12prf_from_cs(int ciphersuite_id)\n{\n    const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =\n        mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA384) {\n        return tls_prf_sha384;\n    } else\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    {\n        if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA256) {\n            return tls_prf_sha256;\n        }\n    }\n#endif\n#if !defined(MBEDTLS_MD_CAN_SHA384) && \\\n    !defined(MBEDTLS_MD_CAN_SHA256)\n    (void) ciphersuite_info;\n#endif\n\n    return NULL;\n}\n#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */\n\nstatic mbedtls_tls_prf_types tls_prf_get_type(mbedtls_ssl_tls_prf_cb *tls_prf)\n{\n    ((void) tls_prf);\n#if defined(MBEDTLS_MD_CAN_SHA384)\n    if (tls_prf == tls_prf_sha384) {\n        return MBEDTLS_SSL_TLS_PRF_SHA384;\n    } else\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA256)\n    if (tls_prf == tls_prf_sha256) {\n        return MBEDTLS_SSL_TLS_PRF_SHA256;\n    } else\n#endif\n    return MBEDTLS_SSL_TLS_PRF_NONE;\n}\n\n/*\n * Populate a transform structure with session keys and all the other\n * necessary information.\n *\n * Parameters:\n * - [in/out]: transform: structure to populate\n *      [in] must be just initialised with mbedtls_ssl_transform_init()\n *      [out] fully populated, ready for use by mbedtls_ssl_{en,de}crypt_buf()\n * - [in] ciphersuite\n * - [in] master\n * - [in] encrypt_then_mac\n * - [in] tls_prf: pointer to PRF to use for key derivation\n * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random\n * - [in] tls_version: TLS version\n * - [in] endpoint: client or server\n * - [in] ssl: used for:\n *        - ssl->conf->{f,p}_export_keys\n *      [in] optionally used for:\n *        - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform,\n                                        int ciphersuite,\n                                        const unsigned char master[48],\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)\n                                        int encrypt_then_mac,\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */\n                                        ssl_tls_prf_t tls_prf,\n                                        const unsigned char randbytes[64],\n                                        mbedtls_ssl_protocol_version tls_version,\n                                        unsigned endpoint,\n                                        const mbedtls_ssl_context *ssl)\n{\n    int ret = 0;\n    unsigned char keyblk[256];\n    unsigned char *key1;\n    unsigned char *key2;\n    unsigned char *mac_enc;\n    unsigned char *mac_dec;\n    size_t mac_key_len = 0;\n    size_t iv_copy_len;\n    size_t keylen;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;\n    mbedtls_ssl_mode_t ssl_mode;\n#if !defined(MBEDTLS_USE_PSA_CRYPTO)\n    const mbedtls_cipher_info_t *cipher_info;\n    const mbedtls_md_info_t *md_info;\n#endif /* !MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_key_type_t key_type;\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    psa_algorithm_t alg;\n    psa_algorithm_t mac_alg = 0;\n    size_t key_bits;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n#endif\n\n    /*\n     * Some data just needs copying into the structure\n     */\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)\n    transform->encrypt_then_mac = encrypt_then_mac;\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */\n    transform->tls_version = tls_version;\n\n#if defined(MBEDTLS_SSL_KEEP_RANDBYTES)\n    memcpy(transform->randbytes, randbytes, sizeof(transform->randbytes));\n#endif\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {\n        /* At the moment, we keep TLS <= 1.2 and TLS 1.3 transform\n         * generation separate. This should never happen. */\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n    /*\n     * Get various info structures\n     */\n    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite);\n    if (ciphersuite_info == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"ciphersuite info for %d not found\",\n                                  ciphersuite));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    ssl_mode = mbedtls_ssl_get_mode_from_ciphersuite(\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)\n        encrypt_then_mac,\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */\n        ciphersuite_info);\n\n    if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) {\n        transform->taglen =\n            ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if ((status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) ciphersuite_info->cipher,\n                                            transform->taglen,\n                                            &alg,\n                                            &key_type,\n                                            &key_bits)) != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_cipher_to_psa\", ret);\n        goto end;\n    }\n#else\n    cipher_info = mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) ciphersuite_info->cipher);\n    if (cipher_info == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"cipher info for %u not found\",\n                                  ciphersuite_info->cipher));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    mac_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac);\n    if (mac_alg == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"mbedtls_md_psa_alg_from_type for %u not found\",\n                                  (unsigned) ciphersuite_info->mac));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n#else\n    md_info = mbedtls_md_info_from_type((mbedtls_md_type_t) ciphersuite_info->mac);\n    if (md_info == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"mbedtls_md info for %u not found\",\n                                  (unsigned) ciphersuite_info->mac));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    /* Copy own and peer's CID if the use of the CID\n     * extension has been negotiated. */\n    if (ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_ENABLED) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"Copy CIDs into SSL transform\"));\n\n        transform->in_cid_len = ssl->own_cid_len;\n        memcpy(transform->in_cid, ssl->own_cid, ssl->own_cid_len);\n        MBEDTLS_SSL_DEBUG_BUF(3, \"Incoming CID\", transform->in_cid,\n                              transform->in_cid_len);\n\n        transform->out_cid_len = ssl->handshake->peer_cid_len;\n        memcpy(transform->out_cid, ssl->handshake->peer_cid,\n               ssl->handshake->peer_cid_len);\n        MBEDTLS_SSL_DEBUG_BUF(3, \"Outgoing CID\", transform->out_cid,\n                              transform->out_cid_len);\n    }\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n    /*\n     * Compute key block using the PRF\n     */\n    ret = tls_prf(master, 48, \"key expansion\", randbytes, 64, keyblk, 256);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"prf\", ret);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"ciphersuite = %s\",\n                              mbedtls_ssl_get_ciphersuite_name(ciphersuite)));\n    MBEDTLS_SSL_DEBUG_BUF(3, \"master secret\", master, 48);\n    MBEDTLS_SSL_DEBUG_BUF(4, \"random bytes\", randbytes, 64);\n    MBEDTLS_SSL_DEBUG_BUF(4, \"key block\", keyblk, 256);\n\n    /*\n     * Determine the appropriate key, IV and MAC length.\n     */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    keylen = PSA_BITS_TO_BYTES(key_bits);\n#else\n    keylen = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;\n#endif\n\n#if defined(MBEDTLS_SSL_HAVE_AEAD)\n    if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) {\n        size_t explicit_ivlen;\n\n        transform->maclen = 0;\n        mac_key_len = 0;\n\n        /* All modes haves 96-bit IVs, but the length of the static parts vary\n         * with mode and version:\n         * - For GCM and CCM in TLS 1.2, there's a static IV of 4 Bytes\n         *   (to be concatenated with a dynamically chosen IV of 8 Bytes)\n         * - For ChaChaPoly in TLS 1.2, and all modes in TLS 1.3, there's\n         *   a static IV of 12 Bytes (to be XOR'ed with the 8 Byte record\n         *   sequence number).\n         */\n        transform->ivlen = 12;\n\n        int is_chachapoly = 0;\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        is_chachapoly = (key_type == PSA_KEY_TYPE_CHACHA20);\n#else\n        is_chachapoly = (mbedtls_cipher_info_get_mode(cipher_info)\n                         == MBEDTLS_MODE_CHACHAPOLY);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        if (is_chachapoly) {\n            transform->fixed_ivlen = 12;\n        } else {\n            transform->fixed_ivlen = 4;\n        }\n\n        /* Minimum length of encrypted record */\n        explicit_ivlen = transform->ivlen - transform->fixed_ivlen;\n        transform->minlen = explicit_ivlen + transform->taglen;\n    } else\n#endif /* MBEDTLS_SSL_HAVE_AEAD */\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)\n    if (ssl_mode == MBEDTLS_SSL_MODE_STREAM ||\n        ssl_mode == MBEDTLS_SSL_MODE_CBC ||\n        ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        size_t block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type);\n#else\n        size_t block_size = mbedtls_cipher_info_get_block_size(cipher_info);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        /* Get MAC length */\n        mac_key_len = PSA_HASH_LENGTH(mac_alg);\n#else\n        /* Initialize HMAC contexts */\n        if ((ret = mbedtls_md_setup(&transform->md_ctx_enc, md_info, 1)) != 0 ||\n            (ret = mbedtls_md_setup(&transform->md_ctx_dec, md_info, 1)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_md_setup\", ret);\n            goto end;\n        }\n\n        /* Get MAC length */\n        mac_key_len = mbedtls_md_get_size(md_info);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n        transform->maclen = mac_key_len;\n\n        /* IV length */\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        transform->ivlen = PSA_CIPHER_IV_LENGTH(key_type, alg);\n#else\n        transform->ivlen = mbedtls_cipher_info_get_iv_size(cipher_info);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        /* Minimum length */\n        if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) {\n            transform->minlen = transform->maclen;\n        } else {\n            /*\n             * GenericBlockCipher:\n             * 1. if EtM is in use: one block plus MAC\n             *    otherwise: * first multiple of blocklen greater than maclen\n             * 2. IV\n             */\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n            if (ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {\n                transform->minlen = transform->maclen\n                                    + block_size;\n            } else\n#endif\n            {\n                transform->minlen = transform->maclen\n                                    + block_size\n                                    - transform->maclen % block_size;\n            }\n\n            if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {\n                transform->minlen += transform->ivlen;\n            } else {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n                ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n                goto end;\n            }\n        }\n    } else\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */\n    {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"keylen: %u, minlen: %u, ivlen: %u, maclen: %u\",\n                              (unsigned) keylen,\n                              (unsigned) transform->minlen,\n                              (unsigned) transform->ivlen,\n                              (unsigned) transform->maclen));\n\n    /*\n     * Finally setup the cipher contexts, IVs and MAC secrets.\n     */\n#if defined(MBEDTLS_SSL_CLI_C)\n    if (endpoint == MBEDTLS_SSL_IS_CLIENT) {\n        key1 = keyblk + mac_key_len * 2;\n        key2 = keyblk + mac_key_len * 2 + keylen;\n\n        mac_enc = keyblk;\n        mac_dec = keyblk + mac_key_len;\n\n        iv_copy_len = (transform->fixed_ivlen) ?\n                      transform->fixed_ivlen : transform->ivlen;\n        memcpy(transform->iv_enc, key2 + keylen,  iv_copy_len);\n        memcpy(transform->iv_dec, key2 + keylen + iv_copy_len,\n               iv_copy_len);\n    } else\n#endif /* MBEDTLS_SSL_CLI_C */\n#if defined(MBEDTLS_SSL_SRV_C)\n    if (endpoint == MBEDTLS_SSL_IS_SERVER) {\n        key1 = keyblk + mac_key_len * 2 + keylen;\n        key2 = keyblk + mac_key_len * 2;\n\n        mac_enc = keyblk + mac_key_len;\n        mac_dec = keyblk;\n\n        iv_copy_len = (transform->fixed_ivlen) ?\n                      transform->fixed_ivlen : transform->ivlen;\n        memcpy(transform->iv_dec, key1 + keylen,  iv_copy_len);\n        memcpy(transform->iv_enc, key1 + keylen + iv_copy_len,\n               iv_copy_len);\n    } else\n#endif /* MBEDTLS_SSL_SRV_C */\n    {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        goto end;\n    }\n\n    if (ssl->f_export_keys != NULL) {\n        ssl->f_export_keys(ssl->p_export_keys,\n                           MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET,\n                           master, 48,\n                           randbytes + 32,\n                           randbytes,\n                           tls_prf_get_type(tls_prf));\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    transform->psa_alg = alg;\n\n    if (alg != MBEDTLS_SSL_NULL_CIPHER) {\n        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);\n        psa_set_key_algorithm(&attributes, alg);\n        psa_set_key_type(&attributes, key_type);\n\n        if ((status = psa_import_key(&attributes,\n                                     key1,\n                                     PSA_BITS_TO_BYTES(key_bits),\n                                     &transform->psa_key_enc)) != PSA_SUCCESS) {\n            MBEDTLS_SSL_DEBUG_RET(3, \"psa_import_key\", (int) status);\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_import_key\", ret);\n            goto end;\n        }\n\n        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);\n\n        if ((status = psa_import_key(&attributes,\n                                     key2,\n                                     PSA_BITS_TO_BYTES(key_bits),\n                                     &transform->psa_key_dec)) != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_import_key\", ret);\n            goto end;\n        }\n    }\n#else\n    if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_enc,\n                                    cipher_info)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_cipher_setup\", ret);\n        goto end;\n    }\n\n    if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_dec,\n                                    cipher_info)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_cipher_setup\", ret);\n        goto end;\n    }\n\n    if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_enc, key1,\n                                     (int) mbedtls_cipher_info_get_key_bitlen(cipher_info),\n                                     MBEDTLS_ENCRYPT)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_cipher_setkey\", ret);\n        goto end;\n    }\n\n    if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec, key2,\n                                     (int) mbedtls_cipher_info_get_key_bitlen(cipher_info),\n                                     MBEDTLS_DECRYPT)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_cipher_setkey\", ret);\n        goto end;\n    }\n\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    if (mbedtls_cipher_info_get_mode(cipher_info) == MBEDTLS_MODE_CBC) {\n        if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_enc,\n                                                   MBEDTLS_PADDING_NONE)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_cipher_set_padding_mode\", ret);\n            goto end;\n        }\n\n        if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_dec,\n                                                   MBEDTLS_PADDING_NONE)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_cipher_set_padding_mode\", ret);\n            goto end;\n        }\n    }\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)\n    /* For HMAC-based ciphersuites, initialize the HMAC transforms.\n       For AEAD-based ciphersuites, there is nothing to do here. */\n    if (mac_key_len != 0) {\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        transform->psa_mac_alg = PSA_ALG_HMAC(mac_alg);\n\n        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);\n        psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(mac_alg));\n        psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);\n\n        if ((status = psa_import_key(&attributes,\n                                     mac_enc, mac_key_len,\n                                     &transform->psa_mac_enc)) != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_import_mac_key\", ret);\n            goto end;\n        }\n\n        if ((transform->psa_alg == MBEDTLS_SSL_NULL_CIPHER) ||\n            ((transform->psa_alg == PSA_ALG_CBC_NO_PADDING)\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)\n             && (transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED)\n#endif\n            )) {\n            /* mbedtls_ct_hmac() requires the key to be exportable */\n            psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT |\n                                    PSA_KEY_USAGE_VERIFY_HASH);\n        } else {\n            psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);\n        }\n\n        if ((status = psa_import_key(&attributes,\n                                     mac_dec, mac_key_len,\n                                     &transform->psa_mac_dec)) != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_import_mac_key\", ret);\n            goto end;\n        }\n#else\n        ret = mbedtls_md_hmac_starts(&transform->md_ctx_enc, mac_enc, mac_key_len);\n        if (ret != 0) {\n            goto end;\n        }\n        ret = mbedtls_md_hmac_starts(&transform->md_ctx_dec, mac_dec, mac_key_len);\n        if (ret != 0) {\n            goto end;\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    }\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */\n\n    ((void) mac_dec);\n    ((void) mac_enc);\n\nend:\n    mbedtls_platform_zeroize(keyblk, sizeof(keyblk));\n    return ret;\n}\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \\\n    defined(MBEDTLS_USE_PSA_CRYPTO)\nint mbedtls_psa_ecjpake_read_round(\n    psa_pake_operation_t *pake_ctx,\n    const unsigned char *buf,\n    size_t len, mbedtls_ecjpake_rounds_t round)\n{\n    psa_status_t status;\n    size_t input_offset = 0;\n    /*\n     * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice\n     * At round two perform a single cycle\n     */\n    unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1;\n\n    for (; remaining_steps > 0; remaining_steps--) {\n        for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE;\n             step <= PSA_PAKE_STEP_ZK_PROOF;\n             ++step) {\n            /* Length is stored at the first byte */\n            size_t length = buf[input_offset];\n            input_offset += 1;\n\n            if (input_offset + length > len) {\n                return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n            }\n\n            status = psa_pake_input(pake_ctx, step,\n                                    buf + input_offset, length);\n            if (status != PSA_SUCCESS) {\n                return PSA_TO_MBEDTLS_ERR(status);\n            }\n\n            input_offset += length;\n        }\n    }\n\n    if (input_offset != len) {\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    return 0;\n}\n\nint mbedtls_psa_ecjpake_write_round(\n    psa_pake_operation_t *pake_ctx,\n    unsigned char *buf,\n    size_t len, size_t *olen,\n    mbedtls_ecjpake_rounds_t round)\n{\n    psa_status_t status;\n    size_t output_offset = 0;\n    size_t output_len;\n    /*\n     * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice\n     * At round two perform a single cycle\n     */\n    unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1;\n\n    for (; remaining_steps > 0; remaining_steps--) {\n        for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE;\n             step <= PSA_PAKE_STEP_ZK_PROOF;\n             ++step) {\n            /*\n             * For each step, prepend 1 byte with the length of the data as\n             * given by psa_pake_output().\n             */\n            status = psa_pake_output(pake_ctx, step,\n                                     buf + output_offset + 1,\n                                     len - output_offset - 1,\n                                     &output_len);\n            if (status != PSA_SUCCESS) {\n                return PSA_TO_MBEDTLS_ERR(status);\n            }\n\n            *(buf + output_offset) = (uint8_t) output_len;\n\n            output_offset += output_len + 1;\n        }\n    }\n\n    *olen = output_offset;\n\n    return 0;\n}\n#endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nint mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl,\n                                           unsigned char *hash, size_t *hashlen,\n                                           unsigned char *data, size_t data_len,\n                                           mbedtls_md_type_t md_alg)\n{\n    psa_status_t status;\n    psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT;\n    psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(md_alg);\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"Perform PSA-based computation of digest of ServerKeyExchange\"));\n\n    if ((status = psa_hash_setup(&hash_operation,\n                                 hash_alg)) != PSA_SUCCESS) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"psa_hash_setup\", status);\n        goto exit;\n    }\n\n    if ((status = psa_hash_update(&hash_operation, ssl->handshake->randbytes,\n                                  64)) != PSA_SUCCESS) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"psa_hash_update\", status);\n        goto exit;\n    }\n\n    if ((status = psa_hash_update(&hash_operation,\n                                  data, data_len)) != PSA_SUCCESS) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"psa_hash_update\", status);\n        goto exit;\n    }\n\n    if ((status = psa_hash_finish(&hash_operation, hash, PSA_HASH_MAX_SIZE,\n                                  hashlen)) != PSA_SUCCESS) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"psa_hash_finish\", status);\n        goto exit;\n    }\n\nexit:\n    if (status != PSA_SUCCESS) {\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);\n        switch (status) {\n            case PSA_ERROR_NOT_SUPPORTED:\n                return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;\n            case PSA_ERROR_BAD_STATE: /* Intentional fallthrough */\n            case PSA_ERROR_BUFFER_TOO_SMALL:\n                return MBEDTLS_ERR_MD_BAD_INPUT_DATA;\n            case PSA_ERROR_INSUFFICIENT_MEMORY:\n                return MBEDTLS_ERR_MD_ALLOC_FAILED;\n            default:\n                return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;\n        }\n    }\n    return 0;\n}\n\n#else\n\nint mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl,\n                                           unsigned char *hash, size_t *hashlen,\n                                           unsigned char *data, size_t data_len,\n                                           mbedtls_md_type_t md_alg)\n{\n    int ret = 0;\n    mbedtls_md_context_t ctx;\n    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg);\n    *hashlen = mbedtls_md_get_size(md_info);\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"Perform mbedtls-based computation of digest of ServerKeyExchange\"));\n\n    mbedtls_md_init(&ctx);\n\n    /*\n     * digitally-signed struct {\n     *     opaque client_random[32];\n     *     opaque server_random[32];\n     *     ServerDHParams params;\n     * };\n     */\n    if ((ret = mbedtls_md_setup(&ctx, md_info, 0)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_md_setup\", ret);\n        goto exit;\n    }\n    if ((ret = mbedtls_md_starts(&ctx)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_md_starts\", ret);\n        goto exit;\n    }\n    if ((ret = mbedtls_md_update(&ctx, ssl->handshake->randbytes, 64)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_md_update\", ret);\n        goto exit;\n    }\n    if ((ret = mbedtls_md_update(&ctx, data, data_len)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_md_update\", ret);\n        goto exit;\n    }\n    if ((ret = mbedtls_md_finish(&ctx, hash)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_md_finish\", ret);\n        goto exit;\n    }\n\nexit:\n    mbedtls_md_free(&ctx);\n\n    if (ret != 0) {\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);\n    }\n\n    return ret;\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)\n\n/* Find the preferred hash for a given signature algorithm. */\nunsigned int mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg(\n    mbedtls_ssl_context *ssl,\n    unsigned int sig_alg)\n{\n    unsigned int i;\n    uint16_t *received_sig_algs = ssl->handshake->received_sig_algs;\n\n    if (sig_alg == MBEDTLS_SSL_SIG_ANON) {\n        return MBEDTLS_SSL_HASH_NONE;\n    }\n\n    for (i = 0; received_sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) {\n        unsigned int hash_alg_received =\n            MBEDTLS_SSL_TLS12_HASH_ALG_FROM_SIG_AND_HASH_ALG(\n                received_sig_algs[i]);\n        unsigned int sig_alg_received =\n            MBEDTLS_SSL_TLS12_SIG_ALG_FROM_SIG_AND_HASH_ALG(\n                received_sig_algs[i]);\n\n        mbedtls_md_type_t md_alg =\n            mbedtls_ssl_md_alg_from_hash((unsigned char) hash_alg_received);\n        if (md_alg == MBEDTLS_MD_NONE) {\n            continue;\n        }\n\n        if (sig_alg == sig_alg_received) {\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n            if (ssl->handshake->key_cert && ssl->handshake->key_cert->key) {\n                psa_algorithm_t psa_hash_alg =\n                    mbedtls_md_psa_alg_from_type(md_alg);\n\n                if (sig_alg_received == MBEDTLS_SSL_SIG_ECDSA &&\n                    !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key,\n                                           PSA_ALG_ECDSA(psa_hash_alg),\n                                           PSA_KEY_USAGE_SIGN_HASH)) {\n                    continue;\n                }\n\n                if (sig_alg_received == MBEDTLS_SSL_SIG_RSA &&\n                    !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key,\n                                           PSA_ALG_RSA_PKCS1V15_SIGN(\n                                               psa_hash_alg),\n                                           PSA_KEY_USAGE_SIGN_HASH)) {\n                    continue;\n                }\n            }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n            return hash_alg_received;\n        }\n    }\n\n    return MBEDTLS_SSL_HASH_NONE;\n}\n\n#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\nint mbedtls_ssl_validate_ciphersuite(\n    const mbedtls_ssl_context *ssl,\n    const mbedtls_ssl_ciphersuite_t *suite_info,\n    mbedtls_ssl_protocol_version min_tls_version,\n    mbedtls_ssl_protocol_version max_tls_version)\n{\n    (void) ssl;\n\n    if (suite_info == NULL) {\n        return -1;\n    }\n\n    if ((suite_info->min_tls_version > max_tls_version) ||\n        (suite_info->max_tls_version < min_tls_version)) {\n        return -1;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_CLI_C)\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE &&\n        ssl->handshake->psa_pake_ctx_is_ok != 1)\n#else\n    if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE &&\n        mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0)\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    {\n        return -1;\n    }\n#endif\n\n    /* Don't suggest PSK-based ciphersuite if no PSK is available. */\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)\n    if (mbedtls_ssl_ciphersuite_uses_psk(suite_info) &&\n        mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) {\n        return -1;\n    }\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\n/*\n * Function for writing a signature algorithm extension.\n *\n * The `extension_data` field of signature algorithm contains  a `SignatureSchemeList`\n * value (TLS 1.3 RFC8446):\n *      enum {\n *         ....\n *        ecdsa_secp256r1_sha256( 0x0403 ),\n *        ecdsa_secp384r1_sha384( 0x0503 ),\n *        ecdsa_secp521r1_sha512( 0x0603 ),\n *         ....\n *      } SignatureScheme;\n *\n *      struct {\n *         SignatureScheme supported_signature_algorithms<2..2^16-2>;\n *      } SignatureSchemeList;\n *\n * The `extension_data` field of signature algorithm contains a `SignatureAndHashAlgorithm`\n * value (TLS 1.2 RFC5246):\n *      enum {\n *          none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),\n *          sha512(6), (255)\n *      } HashAlgorithm;\n *\n *      enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }\n *        SignatureAlgorithm;\n *\n *      struct {\n *          HashAlgorithm hash;\n *          SignatureAlgorithm signature;\n *      } SignatureAndHashAlgorithm;\n *\n *      SignatureAndHashAlgorithm\n *        supported_signature_algorithms<2..2^16-2>;\n *\n * The TLS 1.3 signature algorithm extension was defined to be a compatible\n * generalization of the TLS 1.2 signature algorithm extension.\n * `SignatureAndHashAlgorithm` field of TLS 1.2 can be represented by\n * `SignatureScheme` field of TLS 1.3\n *\n */\nint mbedtls_ssl_write_sig_alg_ext(mbedtls_ssl_context *ssl, unsigned char *buf,\n                                  const unsigned char *end, size_t *out_len)\n{\n    unsigned char *p = buf;\n    unsigned char *supported_sig_alg; /* Start of supported_signature_algorithms */\n    size_t supported_sig_alg_len = 0; /* Length of supported_signature_algorithms */\n\n    *out_len = 0;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"adding signature_algorithms extension\"));\n\n    /* Check if we have space for header and length field:\n     * - extension_type         (2 bytes)\n     * - extension_data_length  (2 bytes)\n     * - supported_signature_algorithms_length   (2 bytes)\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);\n    p += 6;\n\n    /*\n     * Write supported_signature_algorithms\n     */\n    supported_sig_alg = p;\n    const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl);\n    if (sig_alg == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_CONFIG;\n    }\n\n    for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"got signature scheme [%x] %s\",\n                                  *sig_alg,\n                                  mbedtls_ssl_sig_alg_to_str(*sig_alg)));\n        if (!mbedtls_ssl_sig_alg_is_supported(ssl, *sig_alg)) {\n            continue;\n        }\n        MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);\n        MBEDTLS_PUT_UINT16_BE(*sig_alg, p, 0);\n        p += 2;\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"sent signature scheme [%x] %s\",\n                                  *sig_alg,\n                                  mbedtls_ssl_sig_alg_to_str(*sig_alg)));\n    }\n\n    /* Length of supported_signature_algorithms */\n    supported_sig_alg_len = (size_t) (p - supported_sig_alg);\n    if (supported_sig_alg_len == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"No signature algorithms defined.\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SIG_ALG, buf, 0);\n    MBEDTLS_PUT_UINT16_BE(supported_sig_alg_len + 2, buf, 2);\n    MBEDTLS_PUT_UINT16_BE(supported_sig_alg_len, buf, 4);\n\n    *out_len = (size_t) (p - buf);\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_SIG_ALG);\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n/*\n * mbedtls_ssl_parse_server_name_ext\n *\n * Structure of server_name extension:\n *\n *  enum {\n *        host_name(0), (255)\n *     } NameType;\n *  opaque HostName<1..2^16-1>;\n *\n *  struct {\n *          NameType name_type;\n *          select (name_type) {\n *             case host_name: HostName;\n *           } name;\n *     } ServerName;\n *  struct {\n *          ServerName server_name_list<1..2^16-1>\n *     } ServerNameList;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_parse_server_name_ext(mbedtls_ssl_context *ssl,\n                                      const unsigned char *buf,\n                                      const unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const unsigned char *p = buf;\n    size_t server_name_list_len, hostname_len;\n    const unsigned char *server_name_list_end;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"parse ServerName extension\"));\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    server_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, server_name_list_len);\n    server_name_list_end = p + server_name_list_len;\n    while (p < server_name_list_end) {\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, server_name_list_end, 3);\n        hostname_len = MBEDTLS_GET_UINT16_BE(p, 1);\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, server_name_list_end,\n                                     hostname_len + 3);\n\n        if (p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME) {\n            /* sni_name is intended to be used only during the parsing of the\n             * ClientHello message (it is reset to NULL before the end of\n             * the message parsing). Thus it is ok to just point to the\n             * reception buffer and not make a copy of it.\n             */\n            ssl->handshake->sni_name = p + 3;\n            ssl->handshake->sni_name_len = hostname_len;\n            if (ssl->conf->f_sni == NULL) {\n                return 0;\n            }\n            ret = ssl->conf->f_sni(ssl->conf->p_sni,\n                                   ssl, p + 3, hostname_len);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"ssl_sni_wrapper\", ret);\n                MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME,\n                                             MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME);\n                return MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME;\n            }\n            return 0;\n        }\n\n        p += hostname_len + 3;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n#if defined(MBEDTLS_SSL_ALPN)\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_parse_alpn_ext(mbedtls_ssl_context *ssl,\n                               const unsigned char *buf,\n                               const unsigned char *end)\n{\n    const unsigned char *p = buf;\n    size_t protocol_name_list_len;\n    const unsigned char *protocol_name_list;\n    const unsigned char *protocol_name_list_end;\n    size_t protocol_name_len;\n\n    /* If ALPN not configured, just ignore the extension */\n    if (ssl->conf->alpn_list == NULL) {\n        return 0;\n    }\n\n    /*\n     * RFC7301, section 3.1\n     *      opaque ProtocolName<1..2^8-1>;\n     *\n     *      struct {\n     *          ProtocolName protocol_name_list<2..2^16-1>\n     *      } ProtocolNameList;\n     */\n\n    /*\n     * protocol_name_list_len    2 bytes\n     * protocol_name_len         1 bytes\n     * protocol_name             >=1 byte\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4);\n\n    protocol_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, protocol_name_list_len);\n    protocol_name_list = p;\n    protocol_name_list_end = p + protocol_name_list_len;\n\n    /* Validate peer's list (lengths) */\n    while (p < protocol_name_list_end) {\n        protocol_name_len = *p++;\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end,\n                                     protocol_name_len);\n        if (protocol_name_len == 0) {\n            MBEDTLS_SSL_PEND_FATAL_ALERT(\n                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n                MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n        }\n\n        p += protocol_name_len;\n    }\n\n    /* Use our order of preference */\n    for (const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++) {\n        size_t const alpn_len = strlen(*alpn);\n        p = protocol_name_list;\n        while (p < protocol_name_list_end) {\n            protocol_name_len = *p++;\n            if (protocol_name_len == alpn_len &&\n                memcmp(p, *alpn, alpn_len) == 0) {\n                ssl->alpn_chosen = *alpn;\n                return 0;\n            }\n\n            p += protocol_name_len;\n        }\n    }\n\n    /* If we get here, no match was found */\n    MBEDTLS_SSL_PEND_FATAL_ALERT(\n        MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL,\n        MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL);\n    return MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL;\n}\n\nint mbedtls_ssl_write_alpn_ext(mbedtls_ssl_context *ssl,\n                               unsigned char *buf,\n                               unsigned char *end,\n                               size_t *out_len)\n{\n    unsigned char *p = buf;\n    size_t protocol_name_len;\n    *out_len = 0;\n\n    if (ssl->alpn_chosen == NULL) {\n        return 0;\n    }\n\n    protocol_name_len = strlen(ssl->alpn_chosen);\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 7 + protocol_name_len);\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server side, adding alpn extension\"));\n    /*\n     * 0 . 1    ext identifier\n     * 2 . 3    ext length\n     * 4 . 5    protocol list length\n     * 6 . 6    protocol name length\n     * 7 . 7+n  protocol name\n     */\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ALPN, p, 0);\n\n    *out_len = 7 + protocol_name_len;\n\n    MBEDTLS_PUT_UINT16_BE(protocol_name_len + 3, p, 2);\n    MBEDTLS_PUT_UINT16_BE(protocol_name_len + 1, p, 4);\n    /* Note: the length of the chosen protocol has been checked to be less\n     * than 255 bytes in `mbedtls_ssl_conf_alpn_protocols`.\n     */\n    p[6] = MBEDTLS_BYTE_0(protocol_name_len);\n\n    memcpy(p + 7, ssl->alpn_chosen, protocol_name_len);\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_ALPN);\n#endif\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_ALPN */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \\\n    defined(MBEDTLS_SSL_SESSION_TICKETS) && \\\n    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \\\n    defined(MBEDTLS_SSL_CLI_C)\nint mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session,\n                                     const char *hostname)\n{\n    /* Initialize to suppress unnecessary compiler warning */\n    size_t hostname_len = 0;\n\n    /* Check if new hostname is valid before\n     * making any change to current one */\n    if (hostname != NULL) {\n        hostname_len = strlen(hostname);\n\n        if (hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n    }\n\n    /* Now it's clear that we will overwrite the old hostname,\n     * so we can free it safely */\n    if (session->hostname != NULL) {\n        mbedtls_zeroize_and_free(session->hostname,\n                                 strlen(session->hostname));\n    }\n\n    /* Passing NULL as hostname shall clear the old one */\n    if (hostname == NULL) {\n        session->hostname = NULL;\n    } else {\n        session->hostname = mbedtls_calloc(1, hostname_len + 1);\n        if (session->hostname == NULL) {\n            return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        }\n\n        memcpy(session->hostname, hostname, hostname_len);\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 &&\n          MBEDTLS_SSL_SESSION_TICKETS &&\n          MBEDTLS_SSL_SERVER_NAME_INDICATION &&\n          MBEDTLS_SSL_CLI_C */\n\n#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) && \\\n    defined(MBEDTLS_SSL_ALPN)\nint mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session,\n                                        const char *alpn)\n{\n    size_t alpn_len = 0;\n\n    if (alpn != NULL) {\n        alpn_len = strlen(alpn);\n\n        if (alpn_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n    }\n\n    if (session->ticket_alpn != NULL) {\n        mbedtls_zeroize_and_free(session->ticket_alpn,\n                                 strlen(session->ticket_alpn));\n        session->ticket_alpn = NULL;\n    }\n\n    if (alpn != NULL) {\n        session->ticket_alpn = mbedtls_calloc(alpn_len + 1, 1);\n        if (session->ticket_alpn == NULL) {\n            return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        }\n        memcpy(session->ticket_alpn, alpn, alpn_len);\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */\n\n/*\n * The following functions are used by 1.2 and 1.3, client and server.\n */\n#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)\nint mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert,\n                                 const mbedtls_ssl_ciphersuite_t *ciphersuite,\n                                 int recv_endpoint,\n                                 mbedtls_ssl_protocol_version tls_version,\n                                 uint32_t *flags)\n{\n    int ret = 0;\n    unsigned int usage = 0;\n    const char *ext_oid;\n    size_t ext_len;\n\n    /*\n     * keyUsage\n     */\n\n    /* Note: don't guard this with MBEDTLS_SSL_CLI_C because the server wants\n     * to check what a compliant client will think while choosing which cert\n     * to send to the client. */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&\n        recv_endpoint == MBEDTLS_SSL_IS_CLIENT) {\n        /* TLS 1.2 server part of the key exchange */\n        switch (ciphersuite->key_exchange) {\n            case MBEDTLS_KEY_EXCHANGE_RSA:\n            case MBEDTLS_KEY_EXCHANGE_RSA_PSK:\n                usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT;\n                break;\n\n            case MBEDTLS_KEY_EXCHANGE_DHE_RSA:\n            case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:\n            case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:\n                usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;\n                break;\n\n            case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:\n            case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:\n                usage = MBEDTLS_X509_KU_KEY_AGREEMENT;\n                break;\n\n            /* Don't use default: we want warnings when adding new values */\n            case MBEDTLS_KEY_EXCHANGE_NONE:\n            case MBEDTLS_KEY_EXCHANGE_PSK:\n            case MBEDTLS_KEY_EXCHANGE_DHE_PSK:\n            case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:\n            case MBEDTLS_KEY_EXCHANGE_ECJPAKE:\n                usage = 0;\n        }\n    } else\n#endif\n    {\n        /* This is either TLS 1.3 authentication, which always uses signatures,\n         * or 1.2 client auth: rsa_sign and mbedtls_ecdsa_sign are the only\n         * options we implement, both using signatures. */\n        (void) tls_version;\n        (void) ciphersuite;\n        usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;\n    }\n\n    if (mbedtls_x509_crt_check_key_usage(cert, usage) != 0) {\n        *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE;\n        ret = -1;\n    }\n\n    /*\n     * extKeyUsage\n     */\n\n    if (recv_endpoint == MBEDTLS_SSL_IS_CLIENT) {\n        ext_oid = MBEDTLS_OID_SERVER_AUTH;\n        ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH);\n    } else {\n        ext_oid = MBEDTLS_OID_CLIENT_AUTH;\n        ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH);\n    }\n\n    if (mbedtls_x509_crt_check_extended_key_usage(cert, ext_oid, ext_len) != 0) {\n        *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE;\n        ret = -1;\n    }\n\n    return ret;\n}\n\nstatic int get_hostname_for_verification(mbedtls_ssl_context *ssl,\n                                         const char **hostname)\n{\n    if (!mbedtls_ssl_has_set_hostname_been_called(ssl)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Certificate verification without having set hostname\"));\n#if !defined(MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME)\n        if (mbedtls_ssl_conf_get_endpoint(ssl->conf) == MBEDTLS_SSL_IS_CLIENT &&\n            ssl->conf->authmode == MBEDTLS_SSL_VERIFY_REQUIRED) {\n            return MBEDTLS_ERR_SSL_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME;\n        }\n#endif\n    }\n\n    *hostname = mbedtls_ssl_get_hostname_pointer(ssl);\n    if (*hostname == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"Certificate verification without CN verification\"));\n    }\n\n    return 0;\n}\n\nint mbedtls_ssl_verify_certificate(mbedtls_ssl_context *ssl,\n                                   int authmode,\n                                   mbedtls_x509_crt *chain,\n                                   const mbedtls_ssl_ciphersuite_t *ciphersuite_info,\n                                   void *rs_ctx)\n{\n    if (authmode == MBEDTLS_SSL_VERIFY_NONE) {\n        return 0;\n    }\n\n    /*\n     * Primary check: use the appropriate X.509 verification function\n     */\n    int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);\n    void *p_vrfy;\n    if (ssl->f_vrfy != NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"Use context-specific verification callback\"));\n        f_vrfy = ssl->f_vrfy;\n        p_vrfy = ssl->p_vrfy;\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"Use configuration-specific verification callback\"));\n        f_vrfy = ssl->conf->f_vrfy;\n        p_vrfy = ssl->conf->p_vrfy;\n    }\n\n    const char *hostname = \"\";\n    int ret = get_hostname_for_verification(ssl, &hostname);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"get_hostname_for_verification\", ret);\n        return ret;\n    }\n\n    int have_ca_chain_or_callback = 0;\n#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)\n    if (ssl->conf->f_ca_cb != NULL) {\n        ((void) rs_ctx);\n        have_ca_chain_or_callback = 1;\n\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"use CA callback for X.509 CRT verification\"));\n        ret = mbedtls_x509_crt_verify_with_ca_cb(\n            chain,\n            ssl->conf->f_ca_cb,\n            ssl->conf->p_ca_cb,\n            ssl->conf->cert_profile,\n            hostname,\n            &ssl->session_negotiate->verify_result,\n            f_vrfy, p_vrfy);\n    } else\n#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */\n    {\n        mbedtls_x509_crt *ca_chain;\n        mbedtls_x509_crl *ca_crl;\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n        if (ssl->handshake->sni_ca_chain != NULL) {\n            ca_chain = ssl->handshake->sni_ca_chain;\n            ca_crl   = ssl->handshake->sni_ca_crl;\n        } else\n#endif\n        {\n            ca_chain = ssl->conf->ca_chain;\n            ca_crl   = ssl->conf->ca_crl;\n        }\n\n        if (ca_chain != NULL) {\n            have_ca_chain_or_callback = 1;\n        }\n\n        ret = mbedtls_x509_crt_verify_restartable(\n            chain,\n            ca_chain, ca_crl,\n            ssl->conf->cert_profile,\n            hostname,\n            &ssl->session_negotiate->verify_result,\n            f_vrfy, p_vrfy, rs_ctx);\n    }\n\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"x509_verify_cert\", ret);\n    }\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n    if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {\n        return MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;\n    }\n#endif\n\n    /*\n     * Secondary checks: always done, but change 'ret' only if it was 0\n     */\n\n    /* With TLS 1.2 and ECC certs, check that the curve used by the\n     * certificate is on our list of acceptable curves.\n     *\n     * With TLS 1.3 this is not needed because the curve is part of the\n     * signature algorithm (eg ecdsa_secp256r1_sha256) which is checked when\n     * we validate the signature made with the key associated to this cert.\n     */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \\\n    defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&\n        mbedtls_pk_can_do(&chain->pk, MBEDTLS_PK_ECKEY)) {\n        if (mbedtls_ssl_check_curve(ssl, mbedtls_pk_get_ec_group_id(&chain->pk)) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate (EC key curve)\"));\n            ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY;\n            if (ret == 0) {\n                ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;\n            }\n        }\n    }\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_PK_HAVE_ECC_KEYS */\n\n    /* Check X.509 usage extensions (keyUsage, extKeyUsage) */\n    if (mbedtls_ssl_check_cert_usage(chain,\n                                     ciphersuite_info,\n                                     ssl->conf->endpoint,\n                                     ssl->tls_version,\n                                     &ssl->session_negotiate->verify_result) != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate (usage extensions)\"));\n        if (ret == 0) {\n            ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;\n        }\n    }\n\n    /* With authmode optional, we want to keep going if the certificate was\n     * unacceptable, but still fail on other errors (out of memory etc),\n     * including fatal errors from the f_vrfy callback.\n     *\n     * The only acceptable errors are:\n     * - MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: cert rejected by primary check;\n     * - MBEDTLS_ERR_SSL_BAD_CERTIFICATE: cert rejected by secondary checks.\n     * Anything else is a fatal error. */\n    if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&\n        (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||\n         ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE)) {\n        ret = 0;\n    }\n\n    /* Return a specific error as this is a user error: inconsistent\n     * configuration - can't verify without trust anchors. */\n    if (have_ca_chain_or_callback == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"got no CA chain\"));\n        ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;\n    }\n\n    if (ret != 0) {\n        uint8_t alert;\n\n        /* The certificate may have been rejected for several reasons.\n           Pick one and send the corresponding alert. Which alert to send\n           may be a subject of debate in some cases. */\n        if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER) {\n            alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED;\n        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) {\n            alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;\n        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE) {\n            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;\n        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE) {\n            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;\n        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK) {\n            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;\n        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY) {\n            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;\n        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED) {\n            alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED;\n        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED) {\n            alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED;\n        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {\n            alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA;\n        } else {\n            alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN;\n        }\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       alert);\n    }\n\n#if defined(MBEDTLS_DEBUG_C)\n    if (ssl->session_negotiate->verify_result != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"! Certificate verification flags %08x\",\n                                  (unsigned int) ssl->session_negotiate->verify_result));\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"Certificate verification flags clear\"));\n    }\n#endif /* MBEDTLS_DEBUG_C */\n\n    return ret;\n}\n#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */\n\n#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT)\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\nstatic int mbedtls_ssl_tls12_export_keying_material(const mbedtls_ssl_context *ssl,\n                                                    const mbedtls_md_type_t hash_alg,\n                                                    uint8_t *out,\n                                                    const size_t key_len,\n                                                    const char *label,\n                                                    const size_t label_len,\n                                                    const unsigned char *context,\n                                                    const size_t context_len,\n                                                    const int use_context)\n{\n    int ret = 0;\n    unsigned char *prf_input = NULL;\n\n    /* The input to the PRF is client_random, then server_random.\n     * If a context is provided, this is then followed by the context length\n     * as a 16-bit big-endian integer, and then the context itself. */\n    const size_t randbytes_len = MBEDTLS_CLIENT_HELLO_RANDOM_LEN + MBEDTLS_SERVER_HELLO_RANDOM_LEN;\n    size_t prf_input_len = randbytes_len;\n    if (use_context) {\n        if (context_len > UINT16_MAX) {\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        /* This does not overflow a 32-bit size_t because the current value of\n         * prf_input_len is 64 (length of client_random + server_random) and\n         * context_len fits into two bytes (checked above). */\n        prf_input_len += sizeof(uint16_t) + context_len;\n    }\n\n    prf_input = mbedtls_calloc(prf_input_len, sizeof(unsigned char));\n    if (prf_input == NULL) {\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n    memcpy(prf_input,\n           ssl->transform->randbytes + MBEDTLS_SERVER_HELLO_RANDOM_LEN,\n           MBEDTLS_CLIENT_HELLO_RANDOM_LEN);\n    memcpy(prf_input + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,\n           ssl->transform->randbytes,\n           MBEDTLS_SERVER_HELLO_RANDOM_LEN);\n    if (use_context) {\n        MBEDTLS_PUT_UINT16_BE(context_len, prf_input, randbytes_len);\n        memcpy(prf_input + randbytes_len + sizeof(uint16_t), context, context_len);\n    }\n    ret = tls_prf_generic(hash_alg, ssl->session->master, sizeof(ssl->session->master),\n                          label, label_len,\n                          prf_input, prf_input_len,\n                          out, key_len);\n    mbedtls_free(prf_input);\n    return ret;\n}\n#endif /* defined(MBEDTLS_SSL_PROTO_TLS1_2) */\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\nstatic int mbedtls_ssl_tls13_export_keying_material(mbedtls_ssl_context *ssl,\n                                                    const mbedtls_md_type_t hash_alg,\n                                                    uint8_t *out,\n                                                    const size_t key_len,\n                                                    const char *label,\n                                                    const size_t label_len,\n                                                    const unsigned char *context,\n                                                    const size_t context_len)\n{\n    const psa_algorithm_t psa_hash_alg = mbedtls_md_psa_alg_from_type(hash_alg);\n    const size_t hash_len = PSA_HASH_LENGTH(hash_alg);\n    const unsigned char *secret = ssl->session->app_secrets.exporter_master_secret;\n\n    /* The length of the label must be at most 249 bytes to fit into the HkdfLabel\n     * struct as defined in RFC 8446, Section 7.1.\n     *\n     * The length of the context is unlimited even though the context field in the\n     * struct can only hold up to 255 bytes. This is because we place a *hash* of\n     * the context in the field. */\n    if (label_len > 249) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    return mbedtls_ssl_tls13_exporter(psa_hash_alg, secret, hash_len,\n                                      (const unsigned char *) label, label_len,\n                                      context, context_len, out, key_len);\n}\n#endif /* defined(MBEDTLS_SSL_PROTO_TLS1_3) */\n\nint mbedtls_ssl_export_keying_material(mbedtls_ssl_context *ssl,\n                                       uint8_t *out, const size_t key_len,\n                                       const char *label, const size_t label_len,\n                                       const unsigned char *context, const size_t context_len,\n                                       const int use_context)\n{\n    if (!mbedtls_ssl_is_handshake_over(ssl)) {\n        /* TODO: Change this to a more appropriate error code when one is available. */\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    if (key_len > MBEDTLS_SSL_EXPORT_MAX_KEY_LEN) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    int ciphersuite_id = mbedtls_ssl_get_ciphersuite_id_from_ssl(ssl);\n    const mbedtls_ssl_ciphersuite_t *ciphersuite = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);\n    const mbedtls_md_type_t hash_alg = ciphersuite->mac;\n\n    switch (mbedtls_ssl_get_version_number(ssl)) {\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n        case MBEDTLS_SSL_VERSION_TLS1_2:\n            return mbedtls_ssl_tls12_export_keying_material(ssl, hash_alg, out, key_len,\n                                                            label, label_len,\n                                                            context, context_len, use_context);\n#endif\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n        case MBEDTLS_SSL_VERSION_TLS1_3:\n            return mbedtls_ssl_tls13_export_keying_material(ssl,\n                                                            hash_alg,\n                                                            out,\n                                                            key_len,\n                                                            label,\n                                                            label_len,\n                                                            use_context ? context : NULL,\n                                                            use_context ? context_len : 0);\n#endif\n        default:\n            return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;\n    }\n}\n\n#endif /* defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) */\n\n#endif /* MBEDTLS_SSL_TLS_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_tls12_client.c",
    "content": "/*\n *  TLS client-side functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_2)\n\n#include \"mbedtls/platform.h\"\n\n#include \"mbedtls/ssl.h\"\n#include \"ssl_client.h\"\n#include \"ssl_misc.h\"\n#include \"debug_internal.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/constant_time.h\"\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"psa_util_internal.h\"\n#include \"psa/crypto.h\"\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)\n/* Define a local translating function to save code size by not using too many\n * arguments in each translating place. */\nstatic int local_err_translation(psa_status_t status)\n{\n    return psa_status_to_mbedtls(status, psa_to_ssl_errors,\n                                 ARRAY_LENGTH(psa_to_ssl_errors),\n                                 psa_generic_status_to_mbedtls);\n}\n#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#include <string.h>\n\n#include <stdint.h>\n\n#if defined(MBEDTLS_HAVE_TIME)\n#include \"mbedtls/platform_time.h\"\n#endif\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n#include \"mbedtls/platform_util.h\"\n#endif\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_renegotiation_ext(mbedtls_ssl_context *ssl,\n                                       unsigned char *buf,\n                                       const unsigned char *end,\n                                       size_t *olen)\n{\n    unsigned char *p = buf;\n\n    *olen = 0;\n\n    /* We're always including a TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the\n     * initial ClientHello, in which case also adding the renegotiation\n     * info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */\n    if (ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"client hello, adding renegotiation extension\"));\n\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 5 + ssl->verify_data_len);\n\n    /*\n     * Secure renegotiation\n     */\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0);\n    p += 2;\n\n    *p++ = 0x00;\n    *p++ = MBEDTLS_BYTE_0(ssl->verify_data_len + 1);\n    *p++ = MBEDTLS_BYTE_0(ssl->verify_data_len);\n\n    memcpy(p, ssl->own_verify_data, ssl->verify_data_len);\n\n    *olen = 5 + ssl->verify_data_len;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl,\n                                                 unsigned char *buf,\n                                                 const unsigned char *end,\n                                                 size_t *olen)\n{\n    unsigned char *p = buf;\n    (void) ssl; /* ssl used for debugging only */\n\n    *olen = 0;\n\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"client hello, adding supported_point_formats extension\"));\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0);\n    p += 2;\n\n    *p++ = 0x00;\n    *p++ = 2;\n\n    *p++ = 1;\n    *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED;\n\n    *olen = 6;\n\n    return 0;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl,\n                                      unsigned char *buf,\n                                      const unsigned char *end,\n                                      size_t *olen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = buf;\n    size_t kkpp_len = 0;\n\n    *olen = 0;\n\n    /* Skip costly extension if we can't use EC J-PAKE anyway */\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (ssl->handshake->psa_pake_ctx_is_ok != 1) {\n        return 0;\n    }\n#else\n    if (mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) {\n        return 0;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"client hello, adding ecjpake_kkpp extension\"));\n\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4);\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0);\n    p += 2;\n\n    /*\n     * We may need to send ClientHello multiple times for Hello verification.\n     * We don't want to compute fresh values every time (both for performance\n     * and consistency reasons), so cache the extension content.\n     */\n    if (ssl->handshake->ecjpake_cache == NULL ||\n        ssl->handshake->ecjpake_cache_len == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"generating new ecjpake parameters\"));\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx,\n                                              p + 2, end - p - 2, &kkpp_len,\n                                              MBEDTLS_ECJPAKE_ROUND_ONE);\n        if (ret != 0) {\n            psa_destroy_key(ssl->handshake->psa_pake_password);\n            psa_pake_abort(&ssl->handshake->psa_pake_ctx);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_pake_output\", ret);\n            return ret;\n        }\n#else\n        ret = mbedtls_ecjpake_write_round_one(&ssl->handshake->ecjpake_ctx,\n                                              p + 2, end - p - 2, &kkpp_len,\n                                              ssl->conf->f_rng, ssl->conf->p_rng);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1,\n                                  \"mbedtls_ecjpake_write_round_one\", ret);\n            return ret;\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        ssl->handshake->ecjpake_cache = mbedtls_calloc(1, kkpp_len);\n        if (ssl->handshake->ecjpake_cache == NULL) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"allocation failed\"));\n            return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        }\n\n        memcpy(ssl->handshake->ecjpake_cache, p + 2, kkpp_len);\n        ssl->handshake->ecjpake_cache_len = kkpp_len;\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"re-using cached ecjpake parameters\"));\n\n        kkpp_len = ssl->handshake->ecjpake_cache_len;\n        MBEDTLS_SSL_CHK_BUF_PTR(p + 2, end, kkpp_len);\n\n        memcpy(p + 2, ssl->handshake->ecjpake_cache, kkpp_len);\n    }\n\n    MBEDTLS_PUT_UINT16_BE(kkpp_len, p, 0);\n    p += 2;\n\n    *olen = kkpp_len + 4;\n\n    return 0;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_cid_ext(mbedtls_ssl_context *ssl,\n                             unsigned char *buf,\n                             const unsigned char *end,\n                             size_t *olen)\n{\n    unsigned char *p = buf;\n    size_t ext_len;\n\n    /*\n     *   struct {\n     *      opaque cid<0..2^8-1>;\n     *   } ConnectionId;\n     */\n\n    *olen = 0;\n    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||\n        ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) {\n        return 0;\n    }\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"client hello, adding CID extension\"));\n\n    /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX\n     * which is at most 255, so the increment cannot overflow. */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, (unsigned) (ssl->own_cid_len + 5));\n\n    /* Add extension ID + size */\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_CID, p, 0);\n    p += 2;\n    ext_len = (size_t) ssl->own_cid_len + 1;\n    MBEDTLS_PUT_UINT16_BE(ext_len, p, 0);\n    p += 2;\n\n    *p++ = (uint8_t) ssl->own_cid_len;\n    memcpy(p, ssl->own_cid, ssl->own_cid_len);\n\n    *olen = ssl->own_cid_len + 5;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_max_fragment_length_ext(mbedtls_ssl_context *ssl,\n                                             unsigned char *buf,\n                                             const unsigned char *end,\n                                             size_t *olen)\n{\n    unsigned char *p = buf;\n\n    *olen = 0;\n\n    if (ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE) {\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"client hello, adding max_fragment_length extension\"));\n\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 5);\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0);\n    p += 2;\n\n    *p++ = 0x00;\n    *p++ = 1;\n\n    *p++ = ssl->conf->mfl_code;\n\n    *olen = 5;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_encrypt_then_mac_ext(mbedtls_ssl_context *ssl,\n                                          unsigned char *buf,\n                                          const unsigned char *end,\n                                          size_t *olen)\n{\n    unsigned char *p = buf;\n\n    *olen = 0;\n\n    if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED) {\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"client hello, adding encrypt_then_mac extension\"));\n\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4);\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0);\n    p += 2;\n\n    *p++ = 0x00;\n    *p++ = 0x00;\n\n    *olen = 4;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */\n\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_extended_ms_ext(mbedtls_ssl_context *ssl,\n                                     unsigned char *buf,\n                                     const unsigned char *end,\n                                     size_t *olen)\n{\n    unsigned char *p = buf;\n\n    *olen = 0;\n\n    if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED) {\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"client hello, adding extended_master_secret extension\"));\n\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4);\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0);\n    p += 2;\n\n    *p++ = 0x00;\n    *p++ = 0x00;\n\n    *olen = 4;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_session_ticket_ext(mbedtls_ssl_context *ssl,\n                                        unsigned char *buf,\n                                        const unsigned char *end,\n                                        size_t *olen)\n{\n    unsigned char *p = buf;\n    size_t tlen = ssl->session_negotiate->ticket_len;\n\n    *olen = 0;\n\n    if (mbedtls_ssl_conf_get_session_tickets(ssl->conf) ==\n        MBEDTLS_SSL_SESSION_TICKETS_DISABLED) {\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"client hello, adding session ticket extension\"));\n\n    /* The addition is safe here since the ticket length is 16 bit. */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4 + tlen);\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0);\n    p += 2;\n\n    MBEDTLS_PUT_UINT16_BE(tlen, p, 0);\n    p += 2;\n\n    *olen = 4;\n\n    if (ssl->session_negotiate->ticket == NULL || tlen == 0) {\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"sending session ticket of length %\" MBEDTLS_PRINTF_SIZET, tlen));\n\n    memcpy(p, ssl->session_negotiate->ticket, tlen);\n\n    *olen += tlen;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_use_srtp_ext(mbedtls_ssl_context *ssl,\n                                  unsigned char *buf,\n                                  const unsigned char *end,\n                                  size_t *olen)\n{\n    unsigned char *p = buf;\n    size_t protection_profiles_index = 0, ext_len = 0;\n    uint16_t mki_len = 0, profile_value = 0;\n\n    *olen = 0;\n\n    if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||\n        (ssl->conf->dtls_srtp_profile_list == NULL) ||\n        (ssl->conf->dtls_srtp_profile_list_len == 0)) {\n        return 0;\n    }\n\n    /* RFC 5764 section 4.1.1\n     * uint8 SRTPProtectionProfile[2];\n     *\n     * struct {\n     *   SRTPProtectionProfiles SRTPProtectionProfiles;\n     *   opaque srtp_mki<0..255>;\n     * } UseSRTPData;\n     * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;\n     */\n    if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED) {\n        mki_len = ssl->dtls_srtp_info.mki_len;\n    }\n    /* Extension length = 2 bytes for profiles length,\n     *                    ssl->conf->dtls_srtp_profile_list_len * 2 (each profile is 2 bytes length ),\n     *                    1 byte for srtp_mki vector length and the mki_len value\n     */\n    ext_len = 2 + 2 * (ssl->conf->dtls_srtp_profile_list_len) + 1 + mki_len;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"client hello, adding use_srtp extension\"));\n\n    /* Check there is room in the buffer for the extension + 4 bytes\n     * - the extension tag (2 bytes)\n     * - the extension length (2 bytes)\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, ext_len + 4);\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_USE_SRTP, p, 0);\n    p += 2;\n\n    MBEDTLS_PUT_UINT16_BE(ext_len, p, 0);\n    p += 2;\n\n    /* protection profile length: 2*(ssl->conf->dtls_srtp_profile_list_len) */\n    /* micro-optimization:\n     * the list size is limited to MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH\n     * which is lower than 127, so the upper byte of the length is always 0\n     * For the documentation, the more generic code is left in comments\n     * *p++ = (unsigned char)( ( ( 2 * ssl->conf->dtls_srtp_profile_list_len )\n     *                        >> 8 ) & 0xFF );\n     */\n    *p++ = 0;\n    *p++ = MBEDTLS_BYTE_0(2 * ssl->conf->dtls_srtp_profile_list_len);\n\n    for (protection_profiles_index = 0;\n         protection_profiles_index < ssl->conf->dtls_srtp_profile_list_len;\n         protection_profiles_index++) {\n        profile_value = mbedtls_ssl_check_srtp_profile_value\n                            (ssl->conf->dtls_srtp_profile_list[protection_profiles_index]);\n        if (profile_value != MBEDTLS_TLS_SRTP_UNSET) {\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"ssl_write_use_srtp_ext, add profile: %04x\",\n                                      profile_value));\n            MBEDTLS_PUT_UINT16_BE(profile_value, p, 0);\n            p += 2;\n        } else {\n            /*\n             * Note: we shall never arrive here as protection profiles\n             * is checked by mbedtls_ssl_conf_dtls_srtp_protection_profiles function\n             */\n            MBEDTLS_SSL_DEBUG_MSG(3,\n                                  (\"client hello, \"\n                                   \"illegal DTLS-SRTP protection profile %d\",\n                                   ssl->conf->dtls_srtp_profile_list[protection_profiles_index]\n                                  ));\n            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n        }\n    }\n\n    *p++ = mki_len & 0xFF;\n\n    if (mki_len != 0) {\n        memcpy(p, ssl->dtls_srtp_info.mki_value, mki_len);\n        /*\n         * Increment p to point to the current position.\n         */\n        p += mki_len;\n        MBEDTLS_SSL_DEBUG_BUF(3, \"sending mki\",  ssl->dtls_srtp_info.mki_value,\n                              ssl->dtls_srtp_info.mki_len);\n    }\n\n    /*\n     * total extension length: extension type (2 bytes)\n     *                         + extension length (2 bytes)\n     *                         + protection profile length (2 bytes)\n     *                         + 2 * number of protection profiles\n     *                         + srtp_mki vector length(1 byte)\n     *                         + mki value\n     */\n    *olen = p - buf;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_DTLS_SRTP */\n\nint mbedtls_ssl_tls12_write_client_hello_exts(mbedtls_ssl_context *ssl,\n                                              unsigned char *buf,\n                                              const unsigned char *end,\n                                              int uses_ec,\n                                              size_t *out_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = buf;\n    size_t ext_len = 0;\n\n    (void) ssl;\n    (void) end;\n    (void) uses_ec;\n    (void) ret;\n    (void) ext_len;\n\n    *out_len = 0;\n\n    /* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added\n     * even if MBEDTLS_SSL_RENEGOTIATION is not defined. */\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    if ((ret = ssl_write_renegotiation_ext(ssl, p, end, &ext_len)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_write_renegotiation_ext\", ret);\n        return ret;\n    }\n    p += ext_len;\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n    if (uses_ec) {\n        if ((ret = ssl_write_supported_point_formats_ext(ssl, p, end,\n                                                         &ext_len)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"ssl_write_supported_point_formats_ext\", ret);\n            return ret;\n        }\n        p += ext_len;\n    }\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n    if ((ret = ssl_write_ecjpake_kkpp_ext(ssl, p, end, &ext_len)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_write_ecjpake_kkpp_ext\", ret);\n        return ret;\n    }\n    p += ext_len;\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    if ((ret = ssl_write_cid_ext(ssl, p, end, &ext_len)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_write_cid_ext\", ret);\n        return ret;\n    }\n    p += ext_len;\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n    if ((ret = ssl_write_max_fragment_length_ext(ssl, p, end,\n                                                 &ext_len)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_write_max_fragment_length_ext\", ret);\n        return ret;\n    }\n    p += ext_len;\n#endif\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n    if ((ret = ssl_write_encrypt_then_mac_ext(ssl, p, end, &ext_len)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_write_encrypt_then_mac_ext\", ret);\n        return ret;\n    }\n    p += ext_len;\n#endif\n\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\n    if ((ret = ssl_write_extended_ms_ext(ssl, p, end, &ext_len)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_write_extended_ms_ext\", ret);\n        return ret;\n    }\n    p += ext_len;\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\n    if ((ret = ssl_write_use_srtp_ext(ssl, p, end, &ext_len)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_write_use_srtp_ext\", ret);\n        return ret;\n    }\n    p += ext_len;\n#endif\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n    if ((ret = ssl_write_session_ticket_ext(ssl, p, end, &ext_len)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_write_session_ticket_ext\", ret);\n        return ret;\n    }\n    p += ext_len;\n#endif\n\n    *out_len = (size_t) (p - buf);\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl,\n                                        const unsigned char *buf,\n                                        size_t len)\n{\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {\n        /* Check verify-data in constant-time. The length OTOH is no secret */\n        if (len    != 1 + ssl->verify_data_len * 2 ||\n            buf[0] !=     ssl->verify_data_len * 2 ||\n            mbedtls_ct_memcmp(buf + 1,\n                              ssl->own_verify_data, ssl->verify_data_len) != 0 ||\n            mbedtls_ct_memcmp(buf + 1 + ssl->verify_data_len,\n                              ssl->peer_verify_data, ssl->verify_data_len) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"non-matching renegotiation info\"));\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n        }\n    } else\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n    {\n        if (len != 1 || buf[0] != 0x00) {\n            MBEDTLS_SSL_DEBUG_MSG(1,\n                                  (\"non-zero length renegotiation info\"));\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n        }\n\n        ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;\n    }\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_max_fragment_length_ext(mbedtls_ssl_context *ssl,\n                                             const unsigned char *buf,\n                                             size_t len)\n{\n    /*\n     * server should use the extension only if we did,\n     * and if so the server's value should match ours (and len is always 1)\n     */\n    if (ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ||\n        len != 1 ||\n        buf[0] != ssl->conf->mfl_code) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"non-matching max fragment length extension\"));\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_cid_ext(mbedtls_ssl_context *ssl,\n                             const unsigned char *buf,\n                             size_t len)\n{\n    size_t peer_cid_len;\n\n    if ( /* CID extension only makes sense in DTLS */\n        ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||\n        /* The server must only send the CID extension if we have offered it. */\n        ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"CID extension unexpected\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT);\n        return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;\n    }\n\n    if (len == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"CID extension invalid\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    peer_cid_len = *buf++;\n    len--;\n\n    if (peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"CID extension invalid\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    if (len != peer_cid_len) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"CID extension invalid\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED;\n    ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len;\n    memcpy(ssl->handshake->peer_cid, buf, peer_cid_len);\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"Use of CID extension negotiated\"));\n    MBEDTLS_SSL_DEBUG_BUF(3, \"Server CID\", buf, peer_cid_len);\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_encrypt_then_mac_ext(mbedtls_ssl_context *ssl,\n                                          const unsigned char *buf,\n                                          size_t len)\n{\n    if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED ||\n        len != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"non-matching encrypt-then-MAC extension\"));\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT);\n        return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;\n    }\n\n    ((void) buf);\n\n    ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */\n\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_extended_ms_ext(mbedtls_ssl_context *ssl,\n                                     const unsigned char *buf,\n                                     size_t len)\n{\n    if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED ||\n        len != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"non-matching extended master secret extension\"));\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT);\n        return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;\n    }\n\n    ((void) buf);\n\n    ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_session_ticket_ext(mbedtls_ssl_context *ssl,\n                                        const unsigned char *buf,\n                                        size_t len)\n{\n    if ((mbedtls_ssl_conf_get_session_tickets(ssl->conf) ==\n         MBEDTLS_SSL_SESSION_TICKETS_DISABLED) ||\n        len != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"non-matching session ticket extension\"));\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT);\n        return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;\n    }\n\n    ((void) buf);\n\n    ssl->handshake->new_session_ticket = 1;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_supported_point_formats_ext(mbedtls_ssl_context *ssl,\n                                                 const unsigned char *buf,\n                                                 size_t len)\n{\n    size_t list_size;\n    const unsigned char *p;\n\n    if (len == 0 || (size_t) (buf[0] + 1) != len) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n    list_size = buf[0];\n\n    p = buf + 1;\n    while (list_size > 0) {\n        if (p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED ||\n            p[0] == MBEDTLS_ECP_PF_COMPRESSED) {\n#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \\\n            defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED)\n            ssl->handshake->ecdh_ctx.point_format = p[0];\n#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED */\n#if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                             \\\n            defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n            mbedtls_ecjpake_set_point_format(&ssl->handshake->ecjpake_ctx,\n                                             p[0]);\n#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n            MBEDTLS_SSL_DEBUG_MSG(4, (\"point format selected: %d\", p[0]));\n            return 0;\n        }\n\n        list_size--;\n        p++;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"no point format in common\"));\n    mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                   MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n    return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_ecjpake_kkpp(mbedtls_ssl_context *ssl,\n                                  const unsigned char *buf,\n                                  size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (ssl->handshake->ciphersuite_info->key_exchange !=\n        MBEDTLS_KEY_EXCHANGE_ECJPAKE) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"skip ecjpake kkpp extension\"));\n        return 0;\n    }\n\n    /* If we got here, we no longer need our cached extension */\n    mbedtls_free(ssl->handshake->ecjpake_cache);\n    ssl->handshake->ecjpake_cache = NULL;\n    ssl->handshake->ecjpake_cache_len = 0;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if ((ret = mbedtls_psa_ecjpake_read_round(\n             &ssl->handshake->psa_pake_ctx, buf, len,\n             MBEDTLS_ECJPAKE_ROUND_ONE)) != 0) {\n        psa_destroy_key(ssl->handshake->psa_pake_password);\n        psa_pake_abort(&ssl->handshake->psa_pake_ctx);\n\n        MBEDTLS_SSL_DEBUG_RET(1, \"psa_pake_input round one\", ret);\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n        return ret;\n    }\n\n    return 0;\n#else\n    if ((ret = mbedtls_ecjpake_read_round_one(&ssl->handshake->ecjpake_ctx,\n                                              buf, len)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecjpake_read_round_one\", ret);\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n        return ret;\n    }\n\n    return 0;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_SSL_ALPN)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_alpn_ext(mbedtls_ssl_context *ssl,\n                              const unsigned char *buf, size_t len)\n{\n    size_t list_len, name_len;\n    const char **p;\n\n    /* If we didn't send it, the server shouldn't send it */\n    if (ssl->conf->alpn_list == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"non-matching ALPN extension\"));\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT);\n        return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;\n    }\n\n    /*\n     * opaque ProtocolName<1..2^8-1>;\n     *\n     * struct {\n     *     ProtocolName protocol_name_list<2..2^16-1>\n     * } ProtocolNameList;\n     *\n     * the \"ProtocolNameList\" MUST contain exactly one \"ProtocolName\"\n     */\n\n    /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */\n    if (len < 4) {\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    list_len = MBEDTLS_GET_UINT16_BE(buf, 0);\n    if (list_len != len - 2) {\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    name_len = buf[2];\n    if (name_len != list_len - 1) {\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /* Check that the server chosen protocol was in our list and save it */\n    for (p = ssl->conf->alpn_list; *p != NULL; p++) {\n        if (name_len == strlen(*p) &&\n            memcmp(buf + 3, *p, name_len) == 0) {\n            ssl->alpn_chosen = *p;\n            return 0;\n        }\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"ALPN extension: no matching protocol\"));\n    mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                   MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n    return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n}\n#endif /* MBEDTLS_SSL_ALPN */\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl,\n                                  const unsigned char *buf,\n                                  size_t len)\n{\n    mbedtls_ssl_srtp_profile server_protection = MBEDTLS_TLS_SRTP_UNSET;\n    size_t i, mki_len = 0;\n    uint16_t server_protection_profile_value = 0;\n\n    /* If use_srtp is not configured, just ignore the extension */\n    if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||\n        (ssl->conf->dtls_srtp_profile_list == NULL) ||\n        (ssl->conf->dtls_srtp_profile_list_len == 0)) {\n        return 0;\n    }\n\n    /* RFC 5764 section 4.1.1\n     * uint8 SRTPProtectionProfile[2];\n     *\n     * struct {\n     *   SRTPProtectionProfiles SRTPProtectionProfiles;\n     *   opaque srtp_mki<0..255>;\n     * } UseSRTPData;\n\n     * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;\n     *\n     */\n    if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED) {\n        mki_len = ssl->dtls_srtp_info.mki_len;\n    }\n\n    /*\n     * Length is 5 + optional mki_value : one protection profile length (2 bytes)\n     *                                      + protection profile (2 bytes)\n     *                                      + mki_len(1 byte)\n     *                                      and optional srtp_mki\n     */\n    if ((len < 5) || (len != (buf[4] + 5u))) {\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /*\n     * get the server protection profile\n     */\n\n    /*\n     * protection profile length must be 0x0002 as we must have only\n     * one protection profile in server Hello\n     */\n    if ((buf[0] != 0) || (buf[1] != 2)) {\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    server_protection_profile_value = (buf[2] << 8) | buf[3];\n    server_protection = mbedtls_ssl_check_srtp_profile_value(\n        server_protection_profile_value);\n    if (server_protection != MBEDTLS_TLS_SRTP_UNSET) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"found srtp profile: %s\",\n                                  mbedtls_ssl_get_srtp_profile_as_string(\n                                      server_protection)));\n    }\n\n    ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET;\n\n    /*\n     * Check we have the server profile in our list\n     */\n    for (i = 0; i < ssl->conf->dtls_srtp_profile_list_len; i++) {\n        if (server_protection == ssl->conf->dtls_srtp_profile_list[i]) {\n            ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i];\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"selected srtp profile: %s\",\n                                      mbedtls_ssl_get_srtp_profile_as_string(\n                                          server_protection)));\n            break;\n        }\n    }\n\n    /* If no match was found : server problem, it shall never answer with incompatible profile */\n    if (ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET) {\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    /* If server does not use mki in its reply, make sure the client won't keep\n     * one as negotiated */\n    if (len == 5) {\n        ssl->dtls_srtp_info.mki_len = 0;\n    }\n\n    /*\n     * RFC5764:\n     *  If the client detects a nonzero-length MKI in the server's response\n     *  that is different than the one the client offered, then the client\n     *  MUST abort the handshake and SHOULD send an invalid_parameter alert.\n     */\n    if (len > 5  && (buf[4] != mki_len ||\n                     (memcmp(ssl->dtls_srtp_info.mki_value, &buf[5], mki_len)))) {\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n#if defined(MBEDTLS_DEBUG_C)\n    if (len > 5) {\n        MBEDTLS_SSL_DEBUG_BUF(3, \"received mki\", ssl->dtls_srtp_info.mki_value,\n                              ssl->dtls_srtp_info.mki_len);\n    }\n#endif\n    return 0;\n}\n#endif /* MBEDTLS_SSL_DTLS_SRTP */\n\n/*\n * Parse HelloVerifyRequest.  Only called after verifying the HS type.\n */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_hello_verify_request(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl);\n    uint16_t dtls_legacy_version;\n\n#if !defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    uint8_t cookie_len;\n#else\n    uint16_t cookie_len;\n#endif\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse hello verify request\"));\n\n    /* Check that there is enough room for:\n     * - 2 bytes of version\n     * - 1 byte of cookie_len\n     */\n    if (mbedtls_ssl_hs_hdr_len(ssl) + 3 > ssl->in_msglen) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"incoming HelloVerifyRequest message is too short\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /*\n     * struct {\n     *   ProtocolVersion server_version;\n     *   opaque cookie<0..2^8-1>;\n     * } HelloVerifyRequest;\n     */\n    MBEDTLS_SSL_DEBUG_BUF(3, \"server version\", p, 2);\n    dtls_legacy_version = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n\n    /*\n     * Since the RFC is not clear on this point, accept DTLS 1.0 (0xfeff)\n     * The DTLS 1.3 (current draft) renames ProtocolVersion server_version to\n     * legacy_version and locks the value of legacy_version to 0xfefd (DTLS 1.2)\n     */\n    if (dtls_legacy_version != 0xfefd && dtls_legacy_version != 0xfeff) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server version\"));\n\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION);\n\n        return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;\n    }\n\n    cookie_len = *p++;\n    if ((ssl->in_msg + ssl->in_msglen) - p < cookie_len) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"cookie length does not match incoming message size\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n    MBEDTLS_SSL_DEBUG_BUF(3, \"cookie\", p, cookie_len);\n\n    mbedtls_free(ssl->handshake->cookie);\n\n    ssl->handshake->cookie = mbedtls_calloc(1, cookie_len);\n    if (ssl->handshake->cookie  == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"alloc failed (%d bytes)\", cookie_len));\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n    memcpy(ssl->handshake->cookie, p, cookie_len);\n    ssl->handshake->cookie_len = cookie_len;\n\n    /* Start over at ClientHello */\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);\n    ret = mbedtls_ssl_reset_checksum(ssl);\n    if (0 != ret) {\n        MBEDTLS_SSL_DEBUG_RET(1, (\"mbedtls_ssl_reset_checksum\"), ret);\n        return ret;\n    }\n\n    mbedtls_ssl_recv_flight_completed(ssl);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse hello verify request\"));\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_server_hello(mbedtls_ssl_context *ssl)\n{\n    int ret, i;\n    size_t n;\n    size_t ext_len;\n    unsigned char *buf, *ext;\n    unsigned char comp;\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    int renegotiation_info_seen = 0;\n#endif\n    int handshake_failure = 0;\n    const mbedtls_ssl_ciphersuite_t *suite_info;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse server hello\"));\n\n    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {\n        /* No alert on a read error. */\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_read_record\", ret);\n        return ret;\n    }\n\n    buf = ssl->in_msg;\n\n    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n        if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {\n            ssl->renego_records_seen++;\n\n            if (ssl->conf->renego_max_records >= 0 &&\n                ssl->renego_records_seen > ssl->conf->renego_max_records) {\n                MBEDTLS_SSL_DEBUG_MSG(1,\n                                      (\"renegotiation requested, but not honored by server\"));\n                return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n            }\n\n            MBEDTLS_SSL_DEBUG_MSG(1,\n                                  (\"non-handshake message during renegotiation\"));\n\n            ssl->keep_current_message = 1;\n            return MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO;\n        }\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server hello message\"));\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        if (buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"received hello verify request\"));\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse server hello\"));\n            return ssl_parse_hello_verify_request(ssl);\n        } else {\n            /* We made it through the verification process */\n            mbedtls_free(ssl->handshake->cookie);\n            ssl->handshake->cookie = NULL;\n            ssl->handshake->cookie_len = 0;\n        }\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    if (ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len(ssl) ||\n        buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /*\n     *  0   .  1    server_version\n     *  2   . 33    random (maybe including 4 bytes of Unix time)\n     * 34   . 34    session_id length = n\n     * 35   . 34+n  session_id\n     * 35+n . 36+n  cipher_suite\n     * 37+n . 37+n  compression_method\n     *\n     * 38+n . 39+n  extensions length (optional)\n     * 40+n .  ..   extensions\n     */\n    buf += mbedtls_ssl_hs_hdr_len(ssl);\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"server hello, version\", buf, 2);\n    ssl->tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(buf,\n                                                                               ssl->conf->transport);\n    ssl->session_negotiate->tls_version = ssl->tls_version;\n    ssl->session_negotiate->endpoint = ssl->conf->endpoint;\n\n    if (ssl->tls_version < ssl->conf->min_tls_version ||\n        ssl->tls_version > ssl->conf->max_tls_version) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\n                                  \"server version out of bounds -  min: [0x%x], server: [0x%x], max: [0x%x]\",\n                                  (unsigned) ssl->conf->min_tls_version,\n                                  (unsigned) ssl->tls_version,\n                                  (unsigned) ssl->conf->max_tls_version));\n\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION);\n\n        return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, current time: %lu\",\n                              ((unsigned long) buf[2] << 24) |\n                              ((unsigned long) buf[3] << 16) |\n                              ((unsigned long) buf[4] <<  8) |\n                              ((unsigned long) buf[5])));\n\n    memcpy(ssl->handshake->randbytes + 32, buf + 2, 32);\n\n    n = buf[34];\n\n    MBEDTLS_SSL_DEBUG_BUF(3,   \"server hello, random bytes\", buf + 2, 32);\n\n    if (n > 32) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    if (ssl->in_hslen > mbedtls_ssl_hs_hdr_len(ssl) + 39 + n) {\n        ext_len = MBEDTLS_GET_UINT16_BE(buf, 38 + n);\n\n        if ((ext_len > 0 && ext_len < 4) ||\n            ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + 40 + n + ext_len) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server hello message\"));\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n    } else if (ssl->in_hslen == mbedtls_ssl_hs_hdr_len(ssl) + 38 + n) {\n        ext_len = 0;\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /* ciphersuite (used later) */\n    i = (int) MBEDTLS_GET_UINT16_BE(buf, n + 35);\n\n    /*\n     * Read and check compression\n     */\n    comp = buf[37 + n];\n\n    if (comp != MBEDTLS_SSL_COMPRESS_NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"server hello, bad compression: %d\", comp));\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    }\n\n    /*\n     * Initialize update checksum functions\n     */\n    ssl->handshake->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(i);\n    if (ssl->handshake->ciphersuite_info == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"ciphersuite info for %04x not found\", (unsigned int) i));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    mbedtls_ssl_optimize_checksum(ssl, ssl->handshake->ciphersuite_info);\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, session id len.: %\" MBEDTLS_PRINTF_SIZET, n));\n    MBEDTLS_SSL_DEBUG_BUF(3,   \"server hello, session id\", buf + 35, n);\n\n    /*\n     * Check if the session can be resumed\n     */\n    if (ssl->handshake->resume == 0 || n == 0 ||\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n        ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ||\n#endif\n        ssl->session_negotiate->ciphersuite != i ||\n        ssl->session_negotiate->id_len != n ||\n        memcmp(ssl->session_negotiate->id, buf + 35, n) != 0) {\n        mbedtls_ssl_handshake_increment_state(ssl);\n        ssl->handshake->resume = 0;\n#if defined(MBEDTLS_HAVE_TIME)\n        ssl->session_negotiate->start = mbedtls_time(NULL);\n#endif\n        ssl->session_negotiate->ciphersuite = i;\n        ssl->session_negotiate->id_len = n;\n        memcpy(ssl->session_negotiate->id, buf + 35, n);\n    } else {\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC);\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"%s session has been resumed\",\n                              ssl->handshake->resume ? \"a\" : \"no\"));\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, chosen ciphersuite: %04x\", (unsigned) i));\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, compress alg.: %d\",\n                              buf[37 + n]));\n\n    /*\n     * Perform cipher suite validation in same way as in ssl_write_client_hello.\n     */\n    i = 0;\n    while (1) {\n        if (ssl->conf->ciphersuite_list[i] == 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server hello message\"));\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);\n            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n        }\n\n        if (ssl->conf->ciphersuite_list[i++] ==\n            ssl->session_negotiate->ciphersuite) {\n            break;\n        }\n    }\n\n    suite_info = mbedtls_ssl_ciphersuite_from_id(\n        ssl->session_negotiate->ciphersuite);\n    if (mbedtls_ssl_validate_ciphersuite(ssl, suite_info, ssl->tls_version,\n                                         ssl->tls_version) != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server hello message\"));\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"server hello, chosen ciphersuite: %s\", suite_info->name));\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n    if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA &&\n        ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {\n        ssl->handshake->ecrs_enabled = 1;\n    }\n#endif\n\n    if (comp != MBEDTLS_SSL_COMPRESS_NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server hello message\"));\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    ext = buf + 40 + n;\n\n    MBEDTLS_SSL_DEBUG_MSG(2,\n                          (\"server hello, total extension length: %\" MBEDTLS_PRINTF_SIZET,\n                           ext_len));\n\n    while (ext_len) {\n        unsigned int ext_id   = MBEDTLS_GET_UINT16_BE(ext, 0);\n        unsigned int ext_size = MBEDTLS_GET_UINT16_BE(ext, 2);\n\n        if (ext_size + 4 > ext_len) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server hello message\"));\n            mbedtls_ssl_send_alert_message(\n                ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n\n        switch (ext_id) {\n            case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found renegotiation extension\"));\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n                renegotiation_info_seen = 1;\n#endif\n\n                if ((ret = ssl_parse_renegotiation_info(ssl, ext + 4,\n                                                        ext_size)) != 0) {\n                    return ret;\n                }\n\n                break;\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n            case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH:\n                MBEDTLS_SSL_DEBUG_MSG(3,\n                                      (\"found max_fragment_length extension\"));\n\n                if ((ret = ssl_parse_max_fragment_length_ext(ssl,\n                                                             ext + 4, ext_size)) != 0) {\n                    return ret;\n                }\n\n                break;\n#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n            case MBEDTLS_TLS_EXT_CID:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found CID extension\"));\n\n                if ((ret = ssl_parse_cid_ext(ssl,\n                                             ext + 4,\n                                             ext_size)) != 0) {\n                    return ret;\n                }\n\n                break;\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n            case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found encrypt_then_mac extension\"));\n\n                if ((ret = ssl_parse_encrypt_then_mac_ext(ssl,\n                                                          ext + 4, ext_size)) != 0) {\n                    return ret;\n                }\n\n                break;\n#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */\n\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\n            case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET:\n                MBEDTLS_SSL_DEBUG_MSG(3,\n                                      (\"found extended_master_secret extension\"));\n\n                if ((ret = ssl_parse_extended_ms_ext(ssl,\n                                                     ext + 4, ext_size)) != 0) {\n                    return ret;\n                }\n\n                break;\n#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n            case MBEDTLS_TLS_EXT_SESSION_TICKET:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found session_ticket extension\"));\n\n                if ((ret = ssl_parse_session_ticket_ext(ssl,\n                                                        ext + 4, ext_size)) != 0) {\n                    return ret;\n                }\n\n                break;\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \\\n                defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \\\n                defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n            case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS:\n                MBEDTLS_SSL_DEBUG_MSG(3,\n                                      (\"found supported_point_formats extension\"));\n\n                if ((ret = ssl_parse_supported_point_formats_ext(ssl,\n                                                                 ext + 4, ext_size)) != 0) {\n                    return ret;\n                }\n\n                break;\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n            case MBEDTLS_TLS_EXT_ECJPAKE_KKPP:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found ecjpake_kkpp extension\"));\n\n                if ((ret = ssl_parse_ecjpake_kkpp(ssl,\n                                                  ext + 4, ext_size)) != 0) {\n                    return ret;\n                }\n\n                break;\n#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_SSL_ALPN)\n            case MBEDTLS_TLS_EXT_ALPN:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found alpn extension\"));\n\n                if ((ret = ssl_parse_alpn_ext(ssl, ext + 4, ext_size)) != 0) {\n                    return ret;\n                }\n\n                break;\n#endif /* MBEDTLS_SSL_ALPN */\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\n            case MBEDTLS_TLS_EXT_USE_SRTP:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found use_srtp extension\"));\n\n                if ((ret = ssl_parse_use_srtp_ext(ssl, ext + 4, ext_size)) != 0) {\n                    return ret;\n                }\n\n                break;\n#endif /* MBEDTLS_SSL_DTLS_SRTP */\n\n            default:\n                MBEDTLS_SSL_DEBUG_MSG(3,\n                                      (\"unknown extension found: %u (ignoring)\", ext_id));\n        }\n\n        ext_len -= 4 + ext_size;\n        ext += 4 + ext_size;\n\n        if (ext_len > 0 && ext_len < 4) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server hello message\"));\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n    }\n\n    /*\n     * mbedtls_ssl_derive_keys() has to be called after the parsing of the\n     * extensions. It sets the transform data for the resumed session which in\n     * case of DTLS includes the server CID extracted from the CID extension.\n     */\n    if (ssl->handshake->resume) {\n        if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_derive_keys\", ret);\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);\n            return ret;\n        }\n    }\n\n    /*\n     * Renegotiation security checks\n     */\n    if (ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&\n        ssl->conf->allow_legacy_renegotiation ==\n        MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"legacy renegotiation, breaking off handshake\"));\n        handshake_failure = 1;\n    }\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&\n             ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION &&\n             renegotiation_info_seen == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"renegotiation_info extension missing (secure)\"));\n        handshake_failure = 1;\n    } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&\n               ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&\n               ssl->conf->allow_legacy_renegotiation ==\n               MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"legacy renegotiation not allowed\"));\n        handshake_failure = 1;\n    } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&\n               ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&\n               renegotiation_info_seen == 1) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"renegotiation_info extension present (legacy)\"));\n        handshake_failure = 1;\n    }\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n\n    if (handshake_failure == 1) {\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse server hello\"));\n\n    return 0;\n}\n\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \\\n    defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_server_dh_params(mbedtls_ssl_context *ssl,\n                                      unsigned char **p,\n                                      unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    size_t dhm_actual_bitlen;\n\n    /*\n     * Ephemeral DH parameters:\n     *\n     * struct {\n     *     opaque dh_p<1..2^16-1>;\n     *     opaque dh_g<1..2^16-1>;\n     *     opaque dh_Ys<1..2^16-1>;\n     * } ServerDHParams;\n     */\n    if ((ret = mbedtls_dhm_read_params(&ssl->handshake->dhm_ctx,\n                                       p, end)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(2, (\"mbedtls_dhm_read_params\"), ret);\n        return ret;\n    }\n\n    dhm_actual_bitlen = mbedtls_dhm_get_bitlen(&ssl->handshake->dhm_ctx);\n    if (dhm_actual_bitlen < ssl->conf->dhm_min_bitlen) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"DHM prime too short: %\" MBEDTLS_PRINTF_SIZET \" < %u\",\n                                  dhm_actual_bitlen,\n                                  ssl->conf->dhm_min_bitlen));\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    MBEDTLS_SSL_DEBUG_MPI(3, \"DHM: P \", &ssl->handshake->dhm_ctx.P);\n    MBEDTLS_SSL_DEBUG_MPI(3, \"DHM: G \", &ssl->handshake->dhm_ctx.G);\n    MBEDTLS_SSL_DEBUG_MPI(3, \"DHM: GY\", &ssl->handshake->dhm_ctx.GY);\n\n    return ret;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)   ||   \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)   ||   \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl,\n                                        unsigned char **p,\n                                        unsigned char *end)\n{\n    uint16_t tls_id;\n    size_t ecpoint_len;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n    psa_key_type_t key_type = PSA_KEY_TYPE_NONE;\n    size_t ec_bits = 0;\n\n    /*\n     * struct {\n     *     ECParameters curve_params;\n     *     ECPoint      public;\n     * } ServerECDHParams;\n     *\n     *  1       curve_type (must be \"named_curve\")\n     *  2..3    NamedCurve\n     *  4       ECPoint.len\n     *  5+      ECPoint contents\n     */\n    if (end - *p < 4) {\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /* First byte is curve_type; only named_curve is handled */\n    if (*(*p)++ != MBEDTLS_ECP_TLS_NAMED_CURVE) {\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    /* Next two bytes are the namedcurve value */\n    tls_id = MBEDTLS_GET_UINT16_BE(*p, 0);\n    *p += 2;\n\n    /* Check it's a curve we offered */\n    if (mbedtls_ssl_check_curve_tls_id(ssl, tls_id) != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(2,\n                              (\"bad server key exchange message (ECDHE curve): %u\",\n                               (unsigned) tls_id));\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    /* Convert EC's TLS ID to PSA key type. */\n    if (mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type,\n                                                   &ec_bits) == PSA_ERROR_NOT_SUPPORTED) {\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n    handshake->xxdh_psa_type = key_type;\n    handshake->xxdh_psa_bits = ec_bits;\n\n    /* Keep a copy of the peer's public key */\n    ecpoint_len = *(*p)++;\n    if ((size_t) (end - *p) < ecpoint_len) {\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    if (ecpoint_len > sizeof(handshake->xxdh_psa_peerkey)) {\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    memcpy(handshake->xxdh_psa_peerkey, *p, ecpoint_len);\n    handshake->xxdh_psa_peerkey_len = ecpoint_len;\n    *p += ecpoint_len;\n\n    return 0;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED   ||\n          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED   ||\n          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */\n#else\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)   ||   \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)    ||   \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)   ||   \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||   \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_check_server_ecdh_params(const mbedtls_ssl_context *ssl)\n{\n    uint16_t tls_id;\n    mbedtls_ecp_group_id grp_id;\n#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)\n    grp_id = ssl->handshake->ecdh_ctx.grp.id;\n#else\n    grp_id = ssl->handshake->ecdh_ctx.grp_id;\n#endif\n\n    tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id);\n    if (tls_id == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"ECDH curve: %s\",\n                              mbedtls_ssl_get_curve_name_from_tls_id(tls_id)));\n\n    if (mbedtls_ssl_check_curve(ssl, grp_id) != 0) {\n        return -1;\n    }\n\n    MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,\n                           MBEDTLS_DEBUG_ECDH_QP);\n\n    return 0;\n}\n\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED   ||\n          MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED    ||\n          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED   ||\n          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||     \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||     \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl,\n                                        unsigned char **p,\n                                        unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n\n    /*\n     * Ephemeral ECDH parameters:\n     *\n     * struct {\n     *     ECParameters curve_params;\n     *     ECPoint      public;\n     * } ServerECDHParams;\n     */\n    if ((ret = mbedtls_ecdh_read_params(&ssl->handshake->ecdh_ctx,\n                                        (const unsigned char **) p, end)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, (\"mbedtls_ecdh_read_params\"), ret);\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n        if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {\n            ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;\n        }\n#endif\n        return ret;\n    }\n\n    if (ssl_check_server_ecdh_params(ssl) != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"bad server key exchange message (ECDHE curve)\"));\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    return ret;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || \\\n          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || \\\n          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */\n#endif /* !MBEDTLS_USE_PSA_CRYPTO */\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_server_psk_hint(mbedtls_ssl_context *ssl,\n                                     unsigned char **p,\n                                     unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    uint16_t  len;\n    ((void) ssl);\n\n    /*\n     * PSK parameters:\n     *\n     * opaque psk_identity_hint<0..2^16-1>;\n     */\n    if (end - (*p) < 2) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"bad server key exchange message (psk_identity_hint length)\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n    len = MBEDTLS_GET_UINT16_BE(*p, 0);\n    *p += 2;\n\n    if (end - (*p) < len) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"bad server key exchange message (psk_identity_hint length)\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /*\n     * Note: we currently ignore the PSK identity hint, as we only allow one\n     * PSK to be provisioned on the client. This could be changed later if\n     * someone needs that feature.\n     */\n    *p += len;\n    ret = 0;\n\n    return ret;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) ||                           \\\n    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)\n/*\n * Generate a pre-master secret and encrypt it with the server's RSA key\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_encrypted_pms(mbedtls_ssl_context *ssl,\n                                   size_t offset, size_t *olen,\n                                   size_t pms_offset)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len_bytes = 2;\n    unsigned char *p = ssl->handshake->premaster + pms_offset;\n    mbedtls_pk_context *peer_pk;\n\n    if (offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"buffer too small for encrypted pms\"));\n        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n    }\n\n    /*\n     * Generate (part of) the pre-master as\n     *  struct {\n     *      ProtocolVersion client_version;\n     *      opaque random[46];\n     *  } PreMasterSecret;\n     */\n    mbedtls_ssl_write_version(p, ssl->conf->transport,\n                              MBEDTLS_SSL_VERSION_TLS1_2);\n\n    if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p + 2, 46)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"f_rng\", ret);\n        return ret;\n    }\n\n    ssl->handshake->pmslen = 48;\n\n#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    peer_pk = &ssl->handshake->peer_pubkey;\n#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n    if (ssl->session_negotiate->peer_cert == NULL) {\n        /* Should never happen */\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n    peer_pk = &ssl->session_negotiate->peer_cert->pk;\n#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n\n    /*\n     * Now write it out, encrypted\n     */\n    if (!mbedtls_pk_can_do(peer_pk, MBEDTLS_PK_RSA)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"certificate key type mismatch\"));\n        return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;\n    }\n\n    if ((ret = mbedtls_pk_encrypt(peer_pk,\n                                  p, ssl->handshake->pmslen,\n                                  ssl->out_msg + offset + len_bytes, olen,\n                                  MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes,\n                                  ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_pk_encrypt\", ret);\n        return ret;\n    }\n\n    if (len_bytes == 2) {\n        MBEDTLS_PUT_UINT16_BE(*olen, ssl->out_msg, offset);\n        *olen += 2;\n    }\n\n#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    /* We don't need the peer's public key anymore. Free it. */\n    mbedtls_pk_free(peer_pk);\n#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n    return 0;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_pk_context *peer_pk;\n\n#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    peer_pk = &ssl->handshake->peer_pubkey;\n#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n    if (ssl->session_negotiate->peer_cert == NULL) {\n        /* Should never happen */\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n    peer_pk = &ssl->session_negotiate->peer_cert->pk;\n#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n\n    /* This is a public key, so it can't be opaque, so can_do() is a good\n     * enough check to ensure pk_ec() is safe to use below. */\n    if (!mbedtls_pk_can_do(peer_pk, MBEDTLS_PK_ECKEY)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"server key not ECDH capable\"));\n        return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;\n    }\n\n#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n    const mbedtls_ecp_keypair *peer_key = mbedtls_pk_ec_ro(*peer_pk);\n#endif /* !defined(MBEDTLS_PK_USE_PSA_EC_DATA) */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    uint16_t tls_id = 0;\n    psa_key_type_t key_type = PSA_KEY_TYPE_NONE;\n    mbedtls_ecp_group_id grp_id = mbedtls_pk_get_ec_group_id(peer_pk);\n\n    if (mbedtls_ssl_check_curve(ssl, grp_id) != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server certificate (ECDH curve)\"));\n        return MBEDTLS_ERR_SSL_BAD_CERTIFICATE;\n    }\n\n    tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id);\n    if (tls_id == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"ECC group %u not supported\",\n                                  grp_id));\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    /* If the above conversion to TLS ID was fine, then also this one will be,\n       so there is no need to check the return value here */\n    mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type,\n                                               &ssl->handshake->xxdh_psa_bits);\n\n    ssl->handshake->xxdh_psa_type = key_type;\n\n    /* Store peer's public key in psa format. */\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n    memcpy(ssl->handshake->xxdh_psa_peerkey, peer_pk->pub_raw, peer_pk->pub_raw_len);\n    ssl->handshake->xxdh_psa_peerkey_len = peer_pk->pub_raw_len;\n    ret = 0;\n#else /* MBEDTLS_PK_USE_PSA_EC_DATA */\n    size_t olen = 0;\n    ret = mbedtls_ecp_point_write_binary(&peer_key->grp, &peer_key->Q,\n                                         MBEDTLS_ECP_PF_UNCOMPRESSED, &olen,\n                                         ssl->handshake->xxdh_psa_peerkey,\n                                         sizeof(ssl->handshake->xxdh_psa_peerkey));\n\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, (\"mbedtls_ecp_point_write_binary\"), ret);\n        return ret;\n    }\n    ssl->handshake->xxdh_psa_peerkey_len = olen;\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n#else /* MBEDTLS_USE_PSA_CRYPTO */\n    if ((ret = mbedtls_ecdh_get_params(&ssl->handshake->ecdh_ctx, peer_key,\n                                       MBEDTLS_ECDH_THEIRS)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, (\"mbedtls_ecdh_get_params\"), ret);\n        return ret;\n    }\n\n    if (ssl_check_server_ecdh_params(ssl) != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server certificate (ECDH curve)\"));\n        return MBEDTLS_ERR_SSL_BAD_CERTIFICATE;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    /* We don't need the peer's public key anymore. Free it,\n     * so that more RAM is available for upcoming expensive\n     * operations like ECDHE. */\n    mbedtls_pk_free(peer_pk);\n#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n\n    return ret;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||\n          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n    unsigned char *p = NULL, *end = NULL;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse server key exchange\"));\n\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip parse server key exchange\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n    ((void) p);\n    ((void) end);\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA ||\n        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA) {\n        if ((ret = ssl_get_ecdh_params_from_cert(ssl)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"ssl_get_ecdh_params_from_cert\", ret);\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n            return ret;\n        }\n\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip parse server key exchange\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n    ((void) p);\n    ((void) end);\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n    if (ssl->handshake->ecrs_enabled &&\n        ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing) {\n        goto start_processing;\n    }\n#endif\n\n    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_read_record\", ret);\n        return ret;\n    }\n\n    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server key exchange message\"));\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n    /*\n     * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server\n     * doesn't use a psk_identity_hint\n     */\n    if (ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE) {\n        if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||\n            ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {\n            /* Current message is probably either\n             * CertificateRequest or ServerHelloDone */\n            ssl->keep_current_message = 1;\n            goto exit;\n        }\n\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"server key exchange message must not be skipped\"));\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);\n\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n    if (ssl->handshake->ecrs_enabled) {\n        ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing;\n    }\n\nstart_processing:\n#endif\n    p   = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl);\n    end = ssl->in_msg + ssl->in_hslen;\n    MBEDTLS_SSL_DEBUG_BUF(3,   \"server key exchange\", p, (size_t) (end - p));\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||\n        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||\n        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||\n        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) {\n        if (ssl_parse_server_psk_hint(ssl, &p, end) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server key exchange message\"));\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n    } /* FALLTHROUGH */\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) ||                       \\\n    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||\n        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {\n        ; /* nothing more to do */\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \\\n    defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ||\n        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK) {\n        if (ssl_parse_server_dh_params(ssl, &p, end) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server key exchange message\"));\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);\n            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n        }\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||     \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||     \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||\n        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||\n        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA) {\n        if (ssl_parse_server_ecdh_params(ssl, &p, end) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server key exchange message\"));\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);\n            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n        }\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        /*\n         * The first 3 bytes are:\n         * [0] MBEDTLS_ECP_TLS_NAMED_CURVE\n         * [1, 2] elliptic curve's TLS ID\n         *\n         * However since we only support secp256r1 for now, we check only\n         * that TLS ID here\n         */\n        uint16_t read_tls_id = MBEDTLS_GET_UINT16_BE(p, 1);\n        uint16_t exp_tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(\n            MBEDTLS_ECP_DP_SECP256R1);\n\n        if (exp_tls_id == 0) {\n            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n        }\n\n        if ((*p != MBEDTLS_ECP_TLS_NAMED_CURVE) ||\n            (read_tls_id != exp_tls_id)) {\n            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n        }\n\n        p += 3;\n\n        if ((ret = mbedtls_psa_ecjpake_read_round(\n                 &ssl->handshake->psa_pake_ctx, p, end - p,\n                 MBEDTLS_ECJPAKE_ROUND_TWO)) != 0) {\n            psa_destroy_key(ssl->handshake->psa_pake_password);\n            psa_pake_abort(&ssl->handshake->psa_pake_ctx);\n\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_pake_input round two\", ret);\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n        }\n#else\n        ret = mbedtls_ecjpake_read_round_two(&ssl->handshake->ecjpake_ctx,\n                                             p, end - p);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecjpake_read_round_two\", ret);\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n    {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)\n    if (mbedtls_ssl_ciphersuite_uses_server_signature(ciphersuite_info)) {\n        size_t sig_len, hashlen;\n        unsigned char hash[MBEDTLS_MD_MAX_SIZE];\n\n        mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;\n        mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;\n        unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl);\n        size_t params_len = (size_t) (p - params);\n        void *rs_ctx = NULL;\n        uint16_t sig_alg;\n\n        mbedtls_pk_context *peer_pk;\n\n#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n        peer_pk = &ssl->handshake->peer_pubkey;\n#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n        if (ssl->session_negotiate->peer_cert == NULL) {\n            /* Should never happen */\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n        peer_pk = &ssl->session_negotiate->peer_cert->pk;\n#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n\n        /*\n         * Handle the digitally-signed structure\n         */\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n        sig_alg = MBEDTLS_GET_UINT16_BE(p, 0);\n        if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg(\n                sig_alg, &pk_alg, &md_alg) != 0 &&\n            !mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg) &&\n            !mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg)) {\n            MBEDTLS_SSL_DEBUG_MSG(1,\n                                  (\"bad server key exchange message\"));\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);\n            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n        }\n        p += 2;\n\n        if (!mbedtls_pk_can_do(peer_pk, pk_alg)) {\n            MBEDTLS_SSL_DEBUG_MSG(1,\n                                  (\"bad server key exchange message\"));\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);\n            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n        }\n\n        /*\n         * Read signature\n         */\n\n        if (p > end - 2) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server key exchange message\"));\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n        sig_len = MBEDTLS_GET_UINT16_BE(p, 0);\n        p += 2;\n\n        if (p != end - sig_len) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server key exchange message\"));\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n\n        MBEDTLS_SSL_DEBUG_BUF(3, \"signature\", p, sig_len);\n\n        /*\n         * Compute the hash that has been signed\n         */\n        if (md_alg != MBEDTLS_MD_NONE) {\n            ret = mbedtls_ssl_get_key_exchange_md_tls1_2(ssl, hash, &hashlen,\n                                                         params, params_len,\n                                                         md_alg);\n            if (ret != 0) {\n                return ret;\n            }\n        } else {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        MBEDTLS_SSL_DEBUG_BUF(3, \"parameters hash\", hash, hashlen);\n\n        /*\n         * Verify signature\n         */\n        if (!mbedtls_pk_can_do(peer_pk, pk_alg)) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server key exchange message\"));\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n            return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;\n        }\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n        if (ssl->handshake->ecrs_enabled) {\n            rs_ctx = &ssl->handshake->ecrs_ctx.pk;\n        }\n#endif\n\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)\n        if (pk_alg == MBEDTLS_PK_RSASSA_PSS) {\n            mbedtls_pk_rsassa_pss_options rsassa_pss_options;\n            rsassa_pss_options.mgf1_hash_id = md_alg;\n            rsassa_pss_options.expected_salt_len =\n                mbedtls_md_get_size_from_type(md_alg);\n            if (rsassa_pss_options.expected_salt_len == 0) {\n                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n            }\n\n            ret = mbedtls_pk_verify_ext(pk_alg, &rsassa_pss_options,\n                                        peer_pk,\n                                        md_alg, hash, hashlen,\n                                        p, sig_len);\n        } else\n#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */\n        ret = mbedtls_pk_verify_restartable(peer_pk,\n                                            md_alg, hash, hashlen, p, sig_len, rs_ctx);\n\n        if (ret != 0) {\n            int send_alert_msg = 1;\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n            send_alert_msg = (ret != MBEDTLS_ERR_ECP_IN_PROGRESS);\n#endif\n            if (send_alert_msg) {\n                mbedtls_ssl_send_alert_message(\n                    ssl,\n                    MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                    MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR);\n            }\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_pk_verify\", ret);\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n            if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {\n                ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;\n            }\n#endif\n            return ret;\n        }\n\n#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n        /* We don't need the peer's public key anymore. Free it,\n         * so that more RAM is available for upcoming expensive\n         * operations like ECDHE. */\n        mbedtls_pk_free(peer_pk);\n#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n    }\n#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */\n\nexit:\n    mbedtls_ssl_handshake_increment_state(ssl);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse server key exchange\"));\n\n    return 0;\n}\n\n#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_certificate_request(mbedtls_ssl_context *ssl)\n{\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse certificate request\"));\n\n    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip parse certificate request\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n}\n#else /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_certificate_request(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *buf;\n    size_t n = 0;\n    size_t cert_type_len = 0, dn_len = 0;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n    size_t sig_alg_len;\n#if defined(MBEDTLS_DEBUG_C)\n    unsigned char *sig_alg;\n    unsigned char *dn;\n#endif\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse certificate request\"));\n\n    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip parse certificate request\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n\n    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_read_record\", ret);\n        return ret;\n    }\n\n    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate request message\"));\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n    mbedtls_ssl_handshake_increment_state(ssl);\n    ssl->handshake->client_auth =\n        (ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST);\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"got %s certificate request\",\n                              ssl->handshake->client_auth ? \"a\" : \"no\"));\n\n    if (ssl->handshake->client_auth == 0) {\n        /* Current message is probably the ServerHelloDone */\n        ssl->keep_current_message = 1;\n        goto exit;\n    }\n\n    /*\n     *  struct {\n     *      ClientCertificateType certificate_types<1..2^8-1>;\n     *      SignatureAndHashAlgorithm\n     *        supported_signature_algorithms<2^16-1>; -- TLS 1.2 only\n     *      DistinguishedName certificate_authorities<0..2^16-1>;\n     *  } CertificateRequest;\n     *\n     *  Since we only support a single certificate on clients, let's just\n     *  ignore all the information that's supposed to help us pick a\n     *  certificate.\n     *\n     *  We could check that our certificate matches the request, and bail out\n     *  if it doesn't, but it's simpler to just send the certificate anyway,\n     *  and give the server the opportunity to decide if it should terminate\n     *  the connection when it doesn't like our certificate.\n     *\n     *  Same goes for the hash in TLS 1.2's signature_algorithms: at this\n     *  point we only have one hash available (see comments in\n     *  write_certificate_verify), so let's just use what we have.\n     *\n     *  However, we still minimally parse the message to check it is at least\n     *  superficially sane.\n     */\n    buf = ssl->in_msg;\n\n    /* certificate_types */\n    if (ssl->in_hslen <= mbedtls_ssl_hs_hdr_len(ssl)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate request message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n    cert_type_len = buf[mbedtls_ssl_hs_hdr_len(ssl)];\n    n = cert_type_len;\n\n    /*\n     * In the subsequent code there are two paths that read from buf:\n     *     * the length of the signature algorithms field (if minor version of\n     *       SSL is 3),\n     *     * distinguished name length otherwise.\n     * Both reach at most the index:\n     *    ...hdr_len + 2 + n,\n     * therefore the buffer length at this point must be greater than that\n     * regardless of the actual code path.\n     */\n    if (ssl->in_hslen <= mbedtls_ssl_hs_hdr_len(ssl) + 2 + n) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate request message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /* supported_signature_algorithms */\n    sig_alg_len = MBEDTLS_GET_UINT16_BE(buf, mbedtls_ssl_hs_hdr_len(ssl) + 1 + n);\n\n    /*\n     * The furthest access in buf is in the loop few lines below:\n     *     sig_alg[i + 1],\n     * where:\n     *     sig_alg = buf + ...hdr_len + 3 + n,\n     *     max(i) = sig_alg_len - 1.\n     * Therefore the furthest access is:\n     *     buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1],\n     * which reduces to:\n     *     buf[...hdr_len + 3 + n + sig_alg_len],\n     * which is one less than we need the buf to be.\n     */\n    if (ssl->in_hslen <= mbedtls_ssl_hs_hdr_len(ssl) + 3 + n + sig_alg_len) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate request message\"));\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n#if defined(MBEDTLS_DEBUG_C)\n    sig_alg = buf + mbedtls_ssl_hs_hdr_len(ssl) + 3 + n;\n    for (size_t i = 0; i < sig_alg_len; i += 2) {\n        MBEDTLS_SSL_DEBUG_MSG(3,\n                              (\"Supported Signature Algorithm found: %02x %02x\",\n                               sig_alg[i], sig_alg[i + 1]));\n    }\n#endif\n\n    n += 2 + sig_alg_len;\n\n    /* certificate_authorities */\n    dn_len = MBEDTLS_GET_UINT16_BE(buf, mbedtls_ssl_hs_hdr_len(ssl) + 1 + n);\n\n    n += dn_len;\n    if (ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + 3 + n) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate request message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n#if defined(MBEDTLS_DEBUG_C)\n    dn = buf + mbedtls_ssl_hs_hdr_len(ssl) + 3 + n - dn_len;\n    for (size_t i = 0, dni_len = 0; i < dn_len; i += 2 + dni_len) {\n        unsigned char *p = dn + i + 2;\n        mbedtls_x509_name name;\n        size_t asn1_len;\n        char s[MBEDTLS_X509_MAX_DN_NAME_SIZE];\n        memset(&name, 0, sizeof(name));\n        dni_len = MBEDTLS_GET_UINT16_BE(dn + i, 0);\n        if (dni_len > dn_len - i - 2 ||\n            mbedtls_asn1_get_tag(&p, p + dni_len, &asn1_len,\n                                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0 ||\n            mbedtls_x509_get_name(&p, p + asn1_len, &name) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate request message\"));\n            mbedtls_ssl_send_alert_message(\n                ssl,\n                MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n        MBEDTLS_SSL_DEBUG_MSG(3,\n                              (\"DN hint: %.*s\",\n                               mbedtls_x509_dn_gets(s, sizeof(s), &name), s));\n        mbedtls_asn1_free_named_data_list_shallow(name.next);\n    }\n#endif\n\nexit:\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse certificate request\"));\n\n    return 0;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_server_hello_done(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse server hello done\"));\n\n    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_read_record\", ret);\n        return ret;\n    }\n\n    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server hello done message\"));\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n    if (ssl->in_hslen  != mbedtls_ssl_hs_hdr_len(ssl) ||\n        ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad server hello done message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    mbedtls_ssl_handshake_increment_state(ssl);\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        mbedtls_ssl_recv_flight_completed(ssl);\n    }\n#endif\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse server hello done\"));\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    size_t header_len;\n    size_t content_len;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write client key exchange\"));\n\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA) {\n        /*\n         * DHM key exchange -- send G^X mod P\n         */\n        content_len = mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx);\n\n        MBEDTLS_PUT_UINT16_BE(content_len, ssl->out_msg, 4);\n        header_len = 6;\n\n        ret = mbedtls_dhm_make_public(&ssl->handshake->dhm_ctx,\n                                      (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx),\n                                      &ssl->out_msg[header_len], content_len,\n                                      ssl->conf->f_rng, ssl->conf->p_rng);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_dhm_make_public\", ret);\n            return ret;\n        }\n\n        MBEDTLS_SSL_DEBUG_MPI(3, \"DHM: X \", &ssl->handshake->dhm_ctx.X);\n        MBEDTLS_SSL_DEBUG_MPI(3, \"DHM: GX\", &ssl->handshake->dhm_ctx.GX);\n\n        if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx,\n                                           ssl->handshake->premaster,\n                                           MBEDTLS_PREMASTER_SIZE,\n                                           &ssl->handshake->pmslen,\n                                           ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_dhm_calc_secret\", ret);\n            return ret;\n        }\n\n        MBEDTLS_SSL_DEBUG_MPI(3, \"DHM: K \", &ssl->handshake->dhm_ctx.K);\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||\n        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ||\n        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA ||\n        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA) {\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n        psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED;\n        psa_key_attributes_t key_attributes;\n\n        mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n        header_len = 4;\n\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Perform PSA-based ECDH computation.\"));\n\n        /*\n         * Generate EC private key for ECDHE exchange.\n         */\n\n        /* The master secret is obtained from the shared ECDH secret by\n         * applying the TLS 1.2 PRF with a specific salt and label. While\n         * the PSA Crypto API encourages combining key agreement schemes\n         * such as ECDH with fixed KDFs such as TLS 1.2 PRF, it does not\n         * yet support the provisioning of salt + label to the KDF.\n         * For the time being, we therefore need to split the computation\n         * of the ECDH secret and the application of the TLS 1.2 PRF. */\n        key_attributes = psa_key_attributes_init();\n        psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);\n        psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);\n        psa_set_key_type(&key_attributes, handshake->xxdh_psa_type);\n        psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits);\n\n        /* Generate ECDH private key. */\n        status = psa_generate_key(&key_attributes,\n                                  &handshake->xxdh_psa_privkey);\n        if (status != PSA_SUCCESS) {\n            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n        }\n\n        /* Export the public part of the ECDH private key from PSA.\n         * The export format is an ECPoint structure as expected by TLS,\n         * but we just need to add a length byte before that. */\n        unsigned char *own_pubkey = ssl->out_msg + header_len + 1;\n        unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;\n        size_t own_pubkey_max_len = (size_t) (end - own_pubkey);\n        size_t own_pubkey_len;\n\n        status = psa_export_public_key(handshake->xxdh_psa_privkey,\n                                       own_pubkey, own_pubkey_max_len,\n                                       &own_pubkey_len);\n        if (status != PSA_SUCCESS) {\n            psa_destroy_key(handshake->xxdh_psa_privkey);\n            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;\n            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n        }\n\n        ssl->out_msg[header_len] = (unsigned char) own_pubkey_len;\n        content_len = own_pubkey_len + 1;\n\n        /* The ECDH secret is the premaster secret used for key derivation. */\n\n        /* Compute ECDH shared secret. */\n        status = psa_raw_key_agreement(PSA_ALG_ECDH,\n                                       handshake->xxdh_psa_privkey,\n                                       handshake->xxdh_psa_peerkey,\n                                       handshake->xxdh_psa_peerkey_len,\n                                       ssl->handshake->premaster,\n                                       sizeof(ssl->handshake->premaster),\n                                       &ssl->handshake->pmslen);\n\n        destruction_status = psa_destroy_key(handshake->xxdh_psa_privkey);\n        handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;\n\n        if (status != PSA_SUCCESS || destruction_status != PSA_SUCCESS) {\n            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;\n        }\n#else\n        /*\n         * ECDH key exchange -- send client public value\n         */\n        header_len = 4;\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n        if (ssl->handshake->ecrs_enabled) {\n            if (ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret) {\n                goto ecdh_calc_secret;\n            }\n\n            mbedtls_ecdh_enable_restart(&ssl->handshake->ecdh_ctx);\n        }\n#endif\n\n        ret = mbedtls_ecdh_make_public(&ssl->handshake->ecdh_ctx,\n                                       &content_len,\n                                       &ssl->out_msg[header_len], 1000,\n                                       ssl->conf->f_rng, ssl->conf->p_rng);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecdh_make_public\", ret);\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n            if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {\n                ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;\n            }\n#endif\n            return ret;\n        }\n\n        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,\n                               MBEDTLS_DEBUG_ECDH_Q);\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n        if (ssl->handshake->ecrs_enabled) {\n            ssl->handshake->ecrs_n = content_len;\n            ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret;\n        }\n\necdh_calc_secret:\n        if (ssl->handshake->ecrs_enabled) {\n            content_len = ssl->handshake->ecrs_n;\n        }\n#endif\n        if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx,\n                                            &ssl->handshake->pmslen,\n                                            ssl->handshake->premaster,\n                                            MBEDTLS_MPI_MAX_SIZE,\n                                            ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecdh_calc_secret\", ret);\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n            if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {\n                ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;\n            }\n#endif\n            return ret;\n        }\n\n        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,\n                               MBEDTLS_DEBUG_ECDH_Z);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */\n#if defined(MBEDTLS_USE_PSA_CRYPTO) &&                           \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) {\n        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n        psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED;\n        psa_key_attributes_t key_attributes;\n\n        mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n        /*\n         * opaque psk_identity<0..2^16-1>;\n         */\n        if (mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) {\n            /* We don't offer PSK suites if we don't have a PSK,\n             * and we check that the server's choice is among the\n             * ciphersuites we offered, so this should never happen. */\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        /* uint16 to store content length */\n        const size_t content_len_size = 2;\n\n        header_len = 4;\n\n        if (header_len + content_len_size + ssl->conf->psk_identity_len\n            > MBEDTLS_SSL_OUT_CONTENT_LEN) {\n            MBEDTLS_SSL_DEBUG_MSG(1,\n                                  (\"psk identity too long or SSL buffer too short\"));\n            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n        }\n\n        unsigned char *p = ssl->out_msg + header_len;\n\n        *p++ = MBEDTLS_BYTE_1(ssl->conf->psk_identity_len);\n        *p++ = MBEDTLS_BYTE_0(ssl->conf->psk_identity_len);\n        header_len += content_len_size;\n\n        memcpy(p, ssl->conf->psk_identity,\n               ssl->conf->psk_identity_len);\n        p += ssl->conf->psk_identity_len;\n\n        header_len += ssl->conf->psk_identity_len;\n\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Perform PSA-based ECDH computation.\"));\n\n        /*\n         * Generate EC private key for ECDHE exchange.\n         */\n\n        /* The master secret is obtained from the shared ECDH secret by\n         * applying the TLS 1.2 PRF with a specific salt and label. While\n         * the PSA Crypto API encourages combining key agreement schemes\n         * such as ECDH with fixed KDFs such as TLS 1.2 PRF, it does not\n         * yet support the provisioning of salt + label to the KDF.\n         * For the time being, we therefore need to split the computation\n         * of the ECDH secret and the application of the TLS 1.2 PRF. */\n        key_attributes = psa_key_attributes_init();\n        psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);\n        psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);\n        psa_set_key_type(&key_attributes, handshake->xxdh_psa_type);\n        psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits);\n\n        /* Generate ECDH private key. */\n        status = psa_generate_key(&key_attributes,\n                                  &handshake->xxdh_psa_privkey);\n        if (status != PSA_SUCCESS) {\n            return PSA_TO_MBEDTLS_ERR(status);\n        }\n\n        /* Export the public part of the ECDH private key from PSA.\n         * The export format is an ECPoint structure as expected by TLS,\n         * but we just need to add a length byte before that. */\n        unsigned char *own_pubkey = p + 1;\n        unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;\n        size_t own_pubkey_max_len = (size_t) (end - own_pubkey);\n        size_t own_pubkey_len = 0;\n\n        status = psa_export_public_key(handshake->xxdh_psa_privkey,\n                                       own_pubkey, own_pubkey_max_len,\n                                       &own_pubkey_len);\n        if (status != PSA_SUCCESS) {\n            psa_destroy_key(handshake->xxdh_psa_privkey);\n            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;\n            return PSA_TO_MBEDTLS_ERR(status);\n        }\n\n        *p = (unsigned char) own_pubkey_len;\n        content_len = own_pubkey_len + 1;\n\n        /* As RFC 5489 section 2, the premaster secret is formed as follows:\n         * - a uint16 containing the length (in octets) of the ECDH computation\n         * - the octet string produced by the ECDH computation\n         * - a uint16 containing the length (in octets) of the PSK\n         * - the PSK itself\n         */\n        unsigned char *pms = ssl->handshake->premaster;\n        const unsigned char * const pms_end = pms +\n                                              sizeof(ssl->handshake->premaster);\n        /* uint16 to store length (in octets) of the ECDH computation */\n        const size_t zlen_size = 2;\n        size_t zlen = 0;\n\n        /* Perform ECDH computation after the uint16 reserved for the length */\n        status = psa_raw_key_agreement(PSA_ALG_ECDH,\n                                       handshake->xxdh_psa_privkey,\n                                       handshake->xxdh_psa_peerkey,\n                                       handshake->xxdh_psa_peerkey_len,\n                                       pms + zlen_size,\n                                       pms_end - (pms + zlen_size),\n                                       &zlen);\n\n        destruction_status = psa_destroy_key(handshake->xxdh_psa_privkey);\n        handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;\n\n        if (status != PSA_SUCCESS) {\n            return PSA_TO_MBEDTLS_ERR(status);\n        } else if (destruction_status != PSA_SUCCESS) {\n            return PSA_TO_MBEDTLS_ERR(destruction_status);\n        }\n\n        /* Write the ECDH computation length before the ECDH computation */\n        MBEDTLS_PUT_UINT16_BE(zlen, pms, 0);\n        pms += zlen_size + zlen;\n    } else\n#endif /* MBEDTLS_USE_PSA_CRYPTO &&\n          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)\n    if (mbedtls_ssl_ciphersuite_uses_psk(ciphersuite_info)) {\n        /*\n         * opaque psk_identity<0..2^16-1>;\n         */\n        if (mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) {\n            /* We don't offer PSK suites if we don't have a PSK,\n             * and we check that the server's choice is among the\n             * ciphersuites we offered, so this should never happen. */\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        header_len = 4;\n        content_len = ssl->conf->psk_identity_len;\n\n        if (header_len + 2 + content_len > MBEDTLS_SSL_OUT_CONTENT_LEN) {\n            MBEDTLS_SSL_DEBUG_MSG(1,\n                                  (\"psk identity too long or SSL buffer too short\"));\n            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n        }\n\n        ssl->out_msg[header_len++] = MBEDTLS_BYTE_1(content_len);\n        ssl->out_msg[header_len++] = MBEDTLS_BYTE_0(content_len);\n\n        memcpy(ssl->out_msg + header_len,\n               ssl->conf->psk_identity,\n               ssl->conf->psk_identity_len);\n        header_len += ssl->conf->psk_identity_len;\n\n#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)\n        if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK) {\n            content_len = 0;\n        } else\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)\n        if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {\n            if ((ret = ssl_write_encrypted_pms(ssl, header_len,\n                                               &content_len, 2)) != 0) {\n                return ret;\n            }\n        } else\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)\n        if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK) {\n            /*\n             * ClientDiffieHellmanPublic public (DHM send G^X mod P)\n             */\n            content_len = mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx);\n\n            if (header_len + 2 + content_len >\n                MBEDTLS_SSL_OUT_CONTENT_LEN) {\n                MBEDTLS_SSL_DEBUG_MSG(1,\n                                      (\"psk identity or DHM size too long or SSL buffer too short\"));\n                return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n            }\n\n            ssl->out_msg[header_len++] = MBEDTLS_BYTE_1(content_len);\n            ssl->out_msg[header_len++] = MBEDTLS_BYTE_0(content_len);\n\n            ret = mbedtls_dhm_make_public(&ssl->handshake->dhm_ctx,\n                                          (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx),\n                                          &ssl->out_msg[header_len], content_len,\n                                          ssl->conf->f_rng, ssl->conf->p_rng);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_dhm_make_public\", ret);\n                return ret;\n            }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n            unsigned char *pms = ssl->handshake->premaster;\n            unsigned char *pms_end = pms + sizeof(ssl->handshake->premaster);\n            size_t pms_len;\n\n            /* Write length only when we know the actual value */\n            if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx,\n                                               pms + 2, pms_end - (pms + 2), &pms_len,\n                                               ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_dhm_calc_secret\", ret);\n                return ret;\n            }\n            MBEDTLS_PUT_UINT16_BE(pms_len, pms, 0);\n            pms += 2 + pms_len;\n\n            MBEDTLS_SSL_DEBUG_MPI(3, \"DHM: K \", &ssl->handshake->dhm_ctx.K);\n#endif\n        } else\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */\n#if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                             \\\n        defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)\n        if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) {\n            /*\n             * ClientECDiffieHellmanPublic public;\n             */\n            ret = mbedtls_ecdh_make_public(&ssl->handshake->ecdh_ctx,\n                                           &content_len,\n                                           &ssl->out_msg[header_len],\n                                           MBEDTLS_SSL_OUT_CONTENT_LEN - header_len,\n                                           ssl->conf->f_rng, ssl->conf->p_rng);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecdh_make_public\", ret);\n                return ret;\n            }\n\n            MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,\n                                   MBEDTLS_DEBUG_ECDH_Q);\n        } else\n#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */\n        {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n#if !defined(MBEDTLS_USE_PSA_CRYPTO)\n        if ((ret = mbedtls_ssl_psk_derive_premaster(ssl,\n                                                    (mbedtls_key_exchange_type_t) ciphersuite_info->\n                                                    key_exchange)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1,\n                                  \"mbedtls_ssl_psk_derive_premaster\", ret);\n            return ret;\n        }\n#endif /* !MBEDTLS_USE_PSA_CRYPTO */\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) {\n        header_len = 4;\n        if ((ret = ssl_write_encrypted_pms(ssl, header_len,\n                                           &content_len, 0)) != 0) {\n            return ret;\n        }\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {\n        header_len = 4;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        unsigned char *out_p = ssl->out_msg + header_len;\n        unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN -\n                               header_len;\n        ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx,\n                                              out_p, end_p - out_p, &content_len,\n                                              MBEDTLS_ECJPAKE_ROUND_TWO);\n        if (ret != 0) {\n            psa_destroy_key(ssl->handshake->psa_pake_password);\n            psa_pake_abort(&ssl->handshake->psa_pake_ctx);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_pake_output\", ret);\n            return ret;\n        }\n#else\n        ret = mbedtls_ecjpake_write_round_two(&ssl->handshake->ecjpake_ctx,\n                                              ssl->out_msg + header_len,\n                                              MBEDTLS_SSL_OUT_CONTENT_LEN - header_len,\n                                              &content_len,\n                                              ssl->conf->f_rng, ssl->conf->p_rng);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecjpake_write_round_two\", ret);\n            return ret;\n        }\n\n        ret = mbedtls_ecjpake_derive_secret(&ssl->handshake->ecjpake_ctx,\n                                            ssl->handshake->premaster, 32, &ssl->handshake->pmslen,\n                                            ssl->conf->f_rng, ssl->conf->p_rng);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecjpake_derive_secret\", ret);\n            return ret;\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */\n    {\n        ((void) ciphersuite_info);\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    ssl->out_msglen  = header_len + content_len;\n    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;\n    ssl->out_msg[0]  = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE;\n\n    mbedtls_ssl_handshake_increment_state(ssl);\n\n    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_write_handshake_msg\", ret);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write client key exchange\"));\n\n    return 0;\n}\n\n#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_certificate_verify(mbedtls_ssl_context *ssl)\n{\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write certificate verify\"));\n\n    if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_derive_keys\", ret);\n        return ret;\n    }\n\n    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip write certificate verify\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n}\n#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_certificate_verify(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n    size_t n = 0, offset = 0;\n    unsigned char hash[48];\n    unsigned char *hash_start = hash;\n    mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;\n    size_t hashlen;\n    void *rs_ctx = NULL;\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n    size_t out_buf_len = ssl->out_buf_len - (size_t) (ssl->out_msg - ssl->out_buf);\n#else\n    size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (size_t) (ssl->out_msg - ssl->out_buf);\n#endif\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write certificate verify\"));\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n    if (ssl->handshake->ecrs_enabled &&\n        ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign) {\n        goto sign;\n    }\n#endif\n\n    if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_derive_keys\", ret);\n        return ret;\n    }\n\n    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip write certificate verify\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n\n    if (ssl->handshake->client_auth == 0 ||\n        mbedtls_ssl_own_cert(ssl) == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip write certificate verify\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n\n    if (mbedtls_ssl_own_key(ssl) == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"got no private key for certificate\"));\n        return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED;\n    }\n\n    /*\n     * Make a signature of the handshake digests\n     */\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n    if (ssl->handshake->ecrs_enabled) {\n        ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign;\n    }\n\nsign:\n#endif\n\n    ret = ssl->handshake->calc_verify(ssl, hash, &hashlen);\n    if (0 != ret) {\n        MBEDTLS_SSL_DEBUG_RET(1, (\"calc_verify\"), ret);\n        return ret;\n    }\n\n    /*\n     * digitally-signed struct {\n     *     opaque handshake_messages[handshake_messages_length];\n     * };\n     *\n     * Taking shortcut here. We assume that the server always allows the\n     * PRF Hash function and has sent it in the allowed signature\n     * algorithms list received in the Certificate Request message.\n     *\n     * Until we encounter a server that does not, we will take this\n     * shortcut.\n     *\n     * Reason: Otherwise we should have running hashes for SHA512 and\n     *         SHA224 in order to satisfy 'weird' needs from the server\n     *         side.\n     */\n    if (ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384) {\n        md_alg = MBEDTLS_MD_SHA384;\n        ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384;\n    } else {\n        md_alg = MBEDTLS_MD_SHA256;\n        ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256;\n    }\n    ssl->out_msg[5] = mbedtls_ssl_sig_from_pk(mbedtls_ssl_own_key(ssl));\n\n    /* Info from md_alg will be used instead */\n    hashlen = 0;\n    offset = 2;\n\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n    if (ssl->handshake->ecrs_enabled) {\n        rs_ctx = &ssl->handshake->ecrs_ctx.pk;\n    }\n#endif\n\n    if ((ret = mbedtls_pk_sign_restartable(mbedtls_ssl_own_key(ssl),\n                                           md_alg, hash_start, hashlen,\n                                           ssl->out_msg + 6 + offset,\n                                           out_buf_len - 6 - offset,\n                                           &n,\n                                           ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_pk_sign\", ret);\n#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)\n        if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {\n            ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;\n        }\n#endif\n        return ret;\n    }\n\n    MBEDTLS_PUT_UINT16_BE(n, ssl->out_msg, offset + 4);\n\n    ssl->out_msglen  = 6 + n + offset;\n    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;\n    ssl->out_msg[0]  = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY;\n\n    mbedtls_ssl_handshake_increment_state(ssl);\n\n    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_write_handshake_msg\", ret);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write certificate verify\"));\n\n    return ret;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_new_session_ticket(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    uint32_t lifetime;\n    size_t ticket_len;\n    unsigned char *ticket;\n    const unsigned char *msg;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse new session ticket\"));\n\n    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_read_record\", ret);\n        return ret;\n    }\n\n    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad new session ticket message\"));\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n    /*\n     * struct {\n     *     uint32 ticket_lifetime_hint;\n     *     opaque ticket<0..2^16-1>;\n     * } NewSessionTicket;\n     *\n     * 0  .  3   ticket_lifetime_hint\n     * 4  .  5   ticket_len (n)\n     * 6  .  5+n ticket content\n     */\n    if (ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET ||\n        ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len(ssl)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad new session ticket message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl);\n\n    lifetime = MBEDTLS_GET_UINT32_BE(msg, 0);\n\n    ticket_len = MBEDTLS_GET_UINT16_BE(msg, 4);\n\n    if (ticket_len + 6 + mbedtls_ssl_hs_hdr_len(ssl) != ssl->in_hslen) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad new session ticket message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"ticket length: %\" MBEDTLS_PRINTF_SIZET, ticket_len));\n\n    /* We're not waiting for a NewSessionTicket message any more */\n    ssl->handshake->new_session_ticket = 0;\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC);\n\n    /*\n     * Zero-length ticket means the server changed his mind and doesn't want\n     * to send a ticket after all, so just forget it\n     */\n    if (ticket_len == 0) {\n        return 0;\n    }\n\n    if (ssl->session != NULL && ssl->session->ticket != NULL) {\n        mbedtls_zeroize_and_free(ssl->session->ticket,\n                                 ssl->session->ticket_len);\n        ssl->session->ticket = NULL;\n        ssl->session->ticket_len = 0;\n    }\n\n    mbedtls_zeroize_and_free(ssl->session_negotiate->ticket,\n                             ssl->session_negotiate->ticket_len);\n    ssl->session_negotiate->ticket = NULL;\n    ssl->session_negotiate->ticket_len = 0;\n\n    if ((ticket = mbedtls_calloc(1, ticket_len)) == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"ticket alloc failed\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n    memcpy(ticket, msg + 6, ticket_len);\n\n    ssl->session_negotiate->ticket = ticket;\n    ssl->session_negotiate->ticket_len = ticket_len;\n    ssl->session_negotiate->ticket_lifetime = lifetime;\n\n    /*\n     * RFC 5077 section 3.4:\n     * \"If the client receives a session ticket from the server, then it\n     * discards any Session ID that was sent in the ServerHello.\"\n     */\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"ticket in use, discarding session id\"));\n    ssl->session_negotiate->id_len = 0;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse new session ticket\"));\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n/*\n * SSL handshake -- client side -- single step\n */\nint mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl)\n{\n    int ret = 0;\n\n    /* Change state now, so that it is right in mbedtls_ssl_read_record(), used\n     * by DTLS for dropping out-of-sequence ChangeCipherSpec records */\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n    if (ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC &&\n        ssl->handshake->new_session_ticket != 0) {\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_NEW_SESSION_TICKET);\n    }\n#endif\n\n    switch (ssl->state) {\n        case MBEDTLS_SSL_HELLO_REQUEST:\n            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);\n            break;\n\n        /*\n         *  ==>   ClientHello\n         */\n        case MBEDTLS_SSL_CLIENT_HELLO:\n            ret = mbedtls_ssl_write_client_hello(ssl);\n            break;\n\n        /*\n         *  <==   ServerHello\n         *        Certificate\n         *      ( ServerKeyExchange  )\n         *      ( CertificateRequest )\n         *        ServerHelloDone\n         */\n        case MBEDTLS_SSL_SERVER_HELLO:\n            ret = ssl_parse_server_hello(ssl);\n            break;\n\n        case MBEDTLS_SSL_SERVER_CERTIFICATE:\n            ret = mbedtls_ssl_parse_certificate(ssl);\n            break;\n\n        case MBEDTLS_SSL_SERVER_KEY_EXCHANGE:\n            ret = ssl_parse_server_key_exchange(ssl);\n            break;\n\n        case MBEDTLS_SSL_CERTIFICATE_REQUEST:\n            ret = ssl_parse_certificate_request(ssl);\n            break;\n\n        case MBEDTLS_SSL_SERVER_HELLO_DONE:\n            ret = ssl_parse_server_hello_done(ssl);\n            break;\n\n        /*\n         *  ==> ( Certificate/Alert  )\n         *        ClientKeyExchange\n         *      ( CertificateVerify  )\n         *        ChangeCipherSpec\n         *        Finished\n         */\n        case MBEDTLS_SSL_CLIENT_CERTIFICATE:\n            ret = mbedtls_ssl_write_certificate(ssl);\n            break;\n\n        case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:\n            ret = ssl_write_client_key_exchange(ssl);\n            break;\n\n        case MBEDTLS_SSL_CERTIFICATE_VERIFY:\n            ret = ssl_write_certificate_verify(ssl);\n            break;\n\n        case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC:\n            ret = mbedtls_ssl_write_change_cipher_spec(ssl);\n            break;\n\n        case MBEDTLS_SSL_CLIENT_FINISHED:\n            ret = mbedtls_ssl_write_finished(ssl);\n            break;\n\n            /*\n             *  <==   ( NewSessionTicket )\n             *        ChangeCipherSpec\n             *        Finished\n             */\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n        case MBEDTLS_SSL_NEW_SESSION_TICKET:\n            ret = ssl_parse_new_session_ticket(ssl);\n            break;\n#endif\n\n        case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC:\n            ret = mbedtls_ssl_parse_change_cipher_spec(ssl);\n            break;\n\n        case MBEDTLS_SSL_SERVER_FINISHED:\n            ret = mbedtls_ssl_parse_finished(ssl);\n            break;\n\n        case MBEDTLS_SSL_FLUSH_BUFFERS:\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"handshake: done\"));\n            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP);\n            break;\n\n        case MBEDTLS_SSL_HANDSHAKE_WRAPUP:\n            mbedtls_ssl_handshake_wrapup(ssl);\n            break;\n\n        default:\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"invalid state %d\", ssl->state));\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    return ret;\n}\n\n#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_TLS1_2 */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_tls12_server.c",
    "content": "/*\n *  TLS server-side functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_TLS1_2)\n\n#include \"mbedtls/platform.h\"\n\n#include \"mbedtls/ssl.h\"\n#include \"ssl_misc.h\"\n#include \"debug_internal.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"constant_time_internal.h\"\n#include \"mbedtls/constant_time.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n/* Define a local translating function to save code size by not using too many\n * arguments in each translating place. */\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)\nstatic int local_err_translation(psa_status_t status)\n{\n    return psa_status_to_mbedtls(status, psa_to_ssl_errors,\n                                 ARRAY_LENGTH(psa_to_ssl_errors),\n                                 psa_generic_status_to_mbedtls);\n}\n#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)\n#endif\n#endif\n\n#if defined(MBEDTLS_ECP_C)\n#include \"mbedtls/ecp.h\"\n#endif\n\n#if defined(MBEDTLS_HAVE_TIME)\n#include \"mbedtls/platform_time.h\"\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)\nint mbedtls_ssl_set_client_transport_id(mbedtls_ssl_context *ssl,\n                                        const unsigned char *info,\n                                        size_t ilen)\n{\n    if (ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    mbedtls_free(ssl->cli_id);\n\n    if ((ssl->cli_id = mbedtls_calloc(1, ilen)) == NULL) {\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n    memcpy(ssl->cli_id, info, ilen);\n    ssl->cli_id_len = ilen;\n\n    return 0;\n}\n\nvoid mbedtls_ssl_conf_dtls_cookies(mbedtls_ssl_config *conf,\n                                   mbedtls_ssl_cookie_write_t *f_cookie_write,\n                                   mbedtls_ssl_cookie_check_t *f_cookie_check,\n                                   void *p_cookie)\n{\n    conf->f_cookie_write = f_cookie_write;\n    conf->f_cookie_check = f_cookie_check;\n    conf->p_cookie       = p_cookie;\n}\n#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_conf_has_psk_or_cb(mbedtls_ssl_config const *conf)\n{\n    if (conf->f_psk != NULL) {\n        return 1;\n    }\n\n    if (conf->psk_identity_len == 0 || conf->psk_identity == NULL) {\n        return 0;\n    }\n\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) {\n        return 1;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    if (conf->psk != NULL && conf->psk_len != 0) {\n        return 1;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl,\n                                        const unsigned char *buf,\n                                        size_t len)\n{\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {\n        /* Check verify-data in constant-time. The length OTOH is no secret */\n        if (len    != 1 + ssl->verify_data_len ||\n            buf[0] !=     ssl->verify_data_len ||\n            mbedtls_ct_memcmp(buf + 1, ssl->peer_verify_data,\n                              ssl->verify_data_len) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"non-matching renegotiation info\"));\n            mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                           MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n        }\n    } else\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n    {\n        if (len != 1 || buf[0] != 0x0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"non-zero length renegotiation info\"));\n            mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                           MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n        }\n\n        ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;\n    }\n\n    return 0;\n}\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n/*\n * Function for parsing a supported groups (TLS 1.3) or supported elliptic\n * curves (TLS 1.2) extension.\n *\n * The \"extension_data\" field of a supported groups extension contains a\n * \"NamedGroupList\" value (TLS 1.3 RFC8446):\n *      enum {\n *          secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),\n *          x25519(0x001D), x448(0x001E),\n *          ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),\n *          ffdhe6144(0x0103), ffdhe8192(0x0104),\n *          ffdhe_private_use(0x01FC..0x01FF),\n *          ecdhe_private_use(0xFE00..0xFEFF),\n *          (0xFFFF)\n *      } NamedGroup;\n *      struct {\n *          NamedGroup named_group_list<2..2^16-1>;\n *      } NamedGroupList;\n *\n * The \"extension_data\" field of a supported elliptic curves extension contains\n * a \"NamedCurveList\" value (TLS 1.2 RFC 8422):\n * enum {\n *      deprecated(1..22),\n *      secp256r1 (23), secp384r1 (24), secp521r1 (25),\n *      x25519(29), x448(30),\n *      reserved (0xFE00..0xFEFF),\n *      deprecated(0xFF01..0xFF02),\n *      (0xFFFF)\n *  } NamedCurve;\n * struct {\n *      NamedCurve named_curve_list<2..2^16-1>\n *  } NamedCurveList;\n *\n * The TLS 1.3 supported groups extension was defined to be a compatible\n * generalization of the TLS 1.2 supported elliptic curves extension. They both\n * share the same extension identifier.\n *\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_supported_groups_ext(mbedtls_ssl_context *ssl,\n                                          const unsigned char *buf,\n                                          size_t len)\n{\n    size_t list_size, our_size;\n    const unsigned char *p;\n    uint16_t *curves_tls_id;\n\n    if (len < 2) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n    list_size = MBEDTLS_GET_UINT16_BE(buf, 0);\n    if (list_size + 2 != len ||\n        list_size % 2 != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /* Should never happen unless client duplicates the extension */\n    if (ssl->handshake->curves_tls_id != NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    /* Don't allow our peer to make us allocate too much memory,\n     * and leave room for a final 0 */\n    our_size = list_size / 2 + 1;\n    if (our_size > MBEDTLS_ECP_DP_MAX) {\n        our_size = MBEDTLS_ECP_DP_MAX;\n    }\n\n    if ((curves_tls_id = mbedtls_calloc(our_size,\n                                        sizeof(*curves_tls_id))) == NULL) {\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n    ssl->handshake->curves_tls_id = curves_tls_id;\n\n    p = buf + 2;\n    while (list_size > 0 && our_size > 1) {\n        uint16_t curr_tls_id = MBEDTLS_GET_UINT16_BE(p, 0);\n\n        if (mbedtls_ssl_get_ecp_group_id_from_tls_id(curr_tls_id) !=\n            MBEDTLS_ECP_DP_NONE) {\n            *curves_tls_id++ = curr_tls_id;\n            our_size--;\n        }\n\n        list_size -= 2;\n        p += 2;\n    }\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_supported_point_formats(mbedtls_ssl_context *ssl,\n                                             const unsigned char *buf,\n                                             size_t len)\n{\n    size_t list_size;\n    const unsigned char *p;\n\n    if (len == 0 || (size_t) (buf[0] + 1) != len) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n    list_size = buf[0];\n\n    p = buf + 1;\n    while (list_size > 0) {\n        if (p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED ||\n            p[0] == MBEDTLS_ECP_PF_COMPRESSED) {\n#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \\\n            defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED)\n            ssl->handshake->ecdh_ctx.point_format = p[0];\n#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED */\n#if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                             \\\n            defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n            mbedtls_ecjpake_set_point_format(&ssl->handshake->ecjpake_ctx,\n                                             p[0]);\n#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n            MBEDTLS_SSL_DEBUG_MSG(4, (\"point format selected: %d\", p[0]));\n            return 0;\n        }\n\n        list_size--;\n        p++;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_ecjpake_kkpp(mbedtls_ssl_context *ssl,\n                                  const unsigned char *buf,\n                                  size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (ssl->handshake->psa_pake_ctx_is_ok != 1)\n#else\n    if (mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0)\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"skip ecjpake kkpp extension\"));\n        return 0;\n    }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if ((ret = mbedtls_psa_ecjpake_read_round(\n             &ssl->handshake->psa_pake_ctx, buf, len,\n             MBEDTLS_ECJPAKE_ROUND_ONE)) != 0) {\n        psa_destroy_key(ssl->handshake->psa_pake_password);\n        psa_pake_abort(&ssl->handshake->psa_pake_ctx);\n\n        MBEDTLS_SSL_DEBUG_RET(1, \"psa_pake_input round one\", ret);\n        mbedtls_ssl_send_alert_message(\n            ssl,\n            MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n\n        return ret;\n    }\n#else\n    if ((ret = mbedtls_ecjpake_read_round_one(&ssl->handshake->ecjpake_ctx,\n                                              buf, len)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecjpake_read_round_one\", ret);\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);\n        return ret;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    /* Only mark the extension as OK when we're sure it is */\n    ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK;\n\n    return 0;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_max_fragment_length_ext(mbedtls_ssl_context *ssl,\n                                             const unsigned char *buf,\n                                             size_t len)\n{\n    if (len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    ssl->session_negotiate->mfl_code = buf[0];\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_cid_ext(mbedtls_ssl_context *ssl,\n                             const unsigned char *buf,\n                             size_t len)\n{\n    size_t peer_cid_len;\n\n    /* CID extension only makes sense in DTLS */\n    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    /*\n     *   struct {\n     *      opaque cid<0..2^8-1>;\n     *   } ConnectionId;\n     */\n\n    if (len < 1) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    peer_cid_len = *buf++;\n    len--;\n\n    if (len != peer_cid_len) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /* Ignore CID if the user has disabled its use. */\n    if (ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) {\n        /* Leave ssl->handshake->cid_in_use in its default\n         * value of MBEDTLS_SSL_CID_DISABLED. */\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"Client sent CID extension, but CID disabled\"));\n        return 0;\n    }\n\n    if (peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED;\n    ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len;\n    memcpy(ssl->handshake->peer_cid, buf, peer_cid_len);\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"Use of CID extension negotiated\"));\n    MBEDTLS_SSL_DEBUG_BUF(3, \"Client CID\", buf, peer_cid_len);\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_encrypt_then_mac_ext(mbedtls_ssl_context *ssl,\n                                          const unsigned char *buf,\n                                          size_t len)\n{\n    if (len != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    ((void) buf);\n\n    if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED) {\n        ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */\n\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_extended_ms_ext(mbedtls_ssl_context *ssl,\n                                     const unsigned char *buf,\n                                     size_t len)\n{\n    if (len != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    ((void) buf);\n\n    if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) {\n        ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_session_ticket_ext(mbedtls_ssl_context *ssl,\n                                        unsigned char *buf,\n                                        size_t len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_session session;\n\n    mbedtls_ssl_session_init(&session);\n\n    if (ssl->conf->f_ticket_parse == NULL ||\n        ssl->conf->f_ticket_write == NULL) {\n        return 0;\n    }\n\n    /* Remember the client asked us to send a new ticket */\n    ssl->handshake->new_session_ticket = 1;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"ticket length: %\" MBEDTLS_PRINTF_SIZET, len));\n\n    if (len == 0) {\n        return 0;\n    }\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"ticket rejected: renegotiating\"));\n        return 0;\n    }\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n\n    /*\n     * Failures are ok: just ignore the ticket and proceed.\n     */\n    if ((ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket, &session,\n                                         buf, len)) != 0) {\n        mbedtls_ssl_session_free(&session);\n\n        if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) {\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"ticket is not authentic\"));\n        } else if (ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) {\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"ticket is expired\"));\n        } else {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_ticket_parse\", ret);\n        }\n\n        return 0;\n    }\n\n    /*\n     * Keep the session ID sent by the client, since we MUST send it back to\n     * inform them we're accepting the ticket  (RFC 5077 section 3.4)\n     */\n    session.id_len = ssl->session_negotiate->id_len;\n    memcpy(&session.id, ssl->session_negotiate->id, session.id_len);\n\n    mbedtls_ssl_session_free(ssl->session_negotiate);\n    memcpy(ssl->session_negotiate, &session, sizeof(mbedtls_ssl_session));\n\n    /* Zeroize instead of free as we copied the content */\n    mbedtls_platform_zeroize(&session, sizeof(mbedtls_ssl_session));\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"session successfully restored from ticket\"));\n\n    ssl->handshake->resume = 1;\n\n    /* Don't send a new ticket after all, this one is OK */\n    ssl->handshake->new_session_ticket = 0;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl,\n                                  const unsigned char *buf,\n                                  size_t len)\n{\n    mbedtls_ssl_srtp_profile client_protection = MBEDTLS_TLS_SRTP_UNSET;\n    size_t i, j;\n    size_t profile_length;\n    uint16_t mki_length;\n    /*! 2 bytes for profile length and 1 byte for mki len */\n    const size_t size_of_lengths = 3;\n\n    /* If use_srtp is not configured, just ignore the extension */\n    if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||\n        (ssl->conf->dtls_srtp_profile_list == NULL) ||\n        (ssl->conf->dtls_srtp_profile_list_len == 0)) {\n        return 0;\n    }\n\n    /* RFC5764 section 4.1.1\n     * uint8 SRTPProtectionProfile[2];\n     *\n     * struct {\n     *   SRTPProtectionProfiles SRTPProtectionProfiles;\n     *   opaque srtp_mki<0..255>;\n     * } UseSRTPData;\n\n     * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;\n     */\n\n    /*\n     * Min length is 5: at least one protection profile(2 bytes)\n     *                  and length(2 bytes) + srtp_mki length(1 byte)\n     * Check here that we have at least 2 bytes of protection profiles length\n     * and one of srtp_mki length\n     */\n    if (len < size_of_lengths) {\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET;\n\n    /* first 2 bytes are protection profile length(in bytes) */\n    profile_length = (buf[0] << 8) | buf[1];\n    buf += 2;\n\n    /* The profile length cannot be bigger than input buffer size - lengths fields */\n    if (profile_length > len - size_of_lengths ||\n        profile_length % 2 != 0) { /* profiles are 2 bytes long, so the length must be even */\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n    /*\n     * parse the extension list values are defined in\n     * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml\n     */\n    for (j = 0; j < profile_length; j += 2) {\n        uint16_t protection_profile_value = buf[j] << 8 | buf[j + 1];\n        client_protection = mbedtls_ssl_check_srtp_profile_value(protection_profile_value);\n\n        if (client_protection != MBEDTLS_TLS_SRTP_UNSET) {\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"found srtp profile: %s\",\n                                      mbedtls_ssl_get_srtp_profile_as_string(\n                                          client_protection)));\n        } else {\n            continue;\n        }\n        /* check if suggested profile is in our list */\n        for (i = 0; i < ssl->conf->dtls_srtp_profile_list_len; i++) {\n            if (client_protection == ssl->conf->dtls_srtp_profile_list[i]) {\n                ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i];\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"selected srtp profile: %s\",\n                                          mbedtls_ssl_get_srtp_profile_as_string(\n                                              client_protection)));\n                break;\n            }\n        }\n        if (ssl->dtls_srtp_info.chosen_dtls_srtp_profile != MBEDTLS_TLS_SRTP_UNSET) {\n            break;\n        }\n    }\n    buf += profile_length; /* buf points to the mki length */\n    mki_length = *buf;\n    buf++;\n\n    if (mki_length > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH ||\n        mki_length + profile_length + size_of_lengths != len) {\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /* Parse the mki only if present and mki is supported locally */\n    if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED &&\n        mki_length > 0) {\n        ssl->dtls_srtp_info.mki_len = mki_length;\n\n        memcpy(ssl->dtls_srtp_info.mki_value, buf, mki_length);\n\n        MBEDTLS_SSL_DEBUG_BUF(3, \"using mki\",  ssl->dtls_srtp_info.mki_value,\n                              ssl->dtls_srtp_info.mki_len);\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_DTLS_SRTP */\n\n/*\n * Auxiliary functions for ServerHello parsing and related actions\n */\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n/*\n * Return 0 if the given key uses one of the acceptable curves, -1 otherwise\n */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_check_key_curve(mbedtls_pk_context *pk,\n                               uint16_t *curves_tls_id)\n{\n    uint16_t *curr_tls_id = curves_tls_id;\n    mbedtls_ecp_group_id grp_id = mbedtls_pk_get_ec_group_id(pk);\n    mbedtls_ecp_group_id curr_grp_id;\n\n    while (*curr_tls_id != 0) {\n        curr_grp_id = mbedtls_ssl_get_ecp_group_id_from_tls_id(*curr_tls_id);\n        if (curr_grp_id == grp_id) {\n            return 0;\n        }\n        curr_tls_id++;\n    }\n\n    return -1;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED */\n\n/*\n * Try picking a certificate for this ciphersuite,\n * return 0 on success and -1 on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_pick_cert(mbedtls_ssl_context *ssl,\n                         const mbedtls_ssl_ciphersuite_t *ciphersuite_info)\n{\n    mbedtls_ssl_key_cert *cur, *list;\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_algorithm_t pk_alg =\n        mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(ciphersuite_info);\n    psa_key_usage_t pk_usage =\n        mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(ciphersuite_info);\n#else\n    mbedtls_pk_type_t pk_alg =\n        mbedtls_ssl_get_ciphersuite_sig_pk_alg(ciphersuite_info);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    uint32_t flags;\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    if (ssl->handshake->sni_key_cert != NULL) {\n        list = ssl->handshake->sni_key_cert;\n    } else\n#endif\n    list = ssl->conf->key_cert;\n\n    int pk_alg_is_none = 0;\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    pk_alg_is_none = (pk_alg == PSA_ALG_NONE);\n#else\n    pk_alg_is_none = (pk_alg == MBEDTLS_PK_NONE);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    if (pk_alg_is_none) {\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"ciphersuite requires certificate\"));\n\n    if (list == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"server has no certificate\"));\n        return -1;\n    }\n\n    for (cur = list; cur != NULL; cur = cur->next) {\n        flags = 0;\n        MBEDTLS_SSL_DEBUG_CRT(3, \"candidate certificate chain, certificate\",\n                              cur->cert);\n\n        int key_type_matches = 0;\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)\n        key_type_matches = ((ssl->conf->f_async_sign_start != NULL ||\n                             ssl->conf->f_async_decrypt_start != NULL ||\n                             mbedtls_pk_can_do_ext(cur->key, pk_alg, pk_usage)) &&\n                            mbedtls_pk_can_do_ext(&cur->cert->pk, pk_alg, pk_usage));\n#else\n        key_type_matches = (\n            mbedtls_pk_can_do_ext(cur->key, pk_alg, pk_usage));\n#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */\n#else\n        key_type_matches = mbedtls_pk_can_do(&cur->cert->pk, pk_alg);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n        if (!key_type_matches) {\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"certificate mismatch: key type\"));\n            continue;\n        }\n\n        /*\n         * This avoids sending the client a cert it'll reject based on\n         * keyUsage or other extensions.\n         *\n         * It also allows the user to provision different certificates for\n         * different uses based on keyUsage, eg if they want to avoid signing\n         * and decrypting with the same RSA key.\n         */\n        if (mbedtls_ssl_check_cert_usage(cur->cert, ciphersuite_info,\n                                         MBEDTLS_SSL_IS_CLIENT,\n                                         MBEDTLS_SSL_VERSION_TLS1_2,\n                                         &flags) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"certificate mismatch: \"\n                                      \"(extended) key usage extension\"));\n            continue;\n        }\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)\n        if (pk_alg == MBEDTLS_PK_ECDSA &&\n            ssl_check_key_curve(&cur->cert->pk,\n                                ssl->handshake->curves_tls_id) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"certificate mismatch: elliptic curve\"));\n            continue;\n        }\n#endif\n\n        /* If we get there, we got a winner */\n        break;\n    }\n\n    /* Do not update ssl->handshake->key_cert unless there is a match */\n    if (cur != NULL) {\n        ssl->handshake->key_cert = cur;\n        MBEDTLS_SSL_DEBUG_CRT(3, \"selected certificate chain, certificate\",\n                              ssl->handshake->key_cert->cert);\n        return 0;\n    }\n\n    return -1;\n}\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n/*\n * Check if a given ciphersuite is suitable for use with our config/keys/etc\n * Sets ciphersuite_info only if the suite matches.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_ciphersuite_match(mbedtls_ssl_context *ssl, int suite_id,\n                                 const mbedtls_ssl_ciphersuite_t **ciphersuite_info)\n{\n    const mbedtls_ssl_ciphersuite_t *suite_info;\n\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)\n    mbedtls_pk_type_t sig_type;\n#endif\n\n    suite_info = mbedtls_ssl_ciphersuite_from_id(suite_id);\n    if (suite_info == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"trying ciphersuite: %#04x (%s)\",\n                              (unsigned int) suite_id, suite_info->name));\n\n    if (suite_info->min_tls_version > ssl->tls_version ||\n        suite_info->max_tls_version < ssl->tls_version) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"ciphersuite mismatch: version\"));\n        return 0;\n    }\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n    if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE &&\n        (ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK) == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"ciphersuite mismatch: ecjpake \"\n                                  \"not configured or ext missing\"));\n        return 0;\n    }\n#endif\n\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)\n    if (mbedtls_ssl_ciphersuite_uses_ec(suite_info) &&\n        (ssl->handshake->curves_tls_id == NULL ||\n         ssl->handshake->curves_tls_id[0] == 0)) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"ciphersuite mismatch: \"\n                                  \"no common elliptic curve\"));\n        return 0;\n    }\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)\n    /* If the ciphersuite requires a pre-shared key and we don't\n     * have one, skip it now rather than failing later */\n    if (mbedtls_ssl_ciphersuite_uses_psk(suite_info) &&\n        ssl_conf_has_psk_or_cb(ssl->conf) == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"ciphersuite mismatch: no pre-shared key\"));\n        return 0;\n    }\n#endif\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n    /*\n     * Final check: if ciphersuite requires us to have a\n     * certificate/key of a particular type:\n     * - select the appropriate certificate if we have one, or\n     * - try the next ciphersuite if we don't\n     * This must be done last since we modify the key_cert list.\n     */\n    if (ssl_pick_cert(ssl, suite_info) != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"ciphersuite mismatch: \"\n                                  \"no suitable certificate\"));\n        return 0;\n    }\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)\n    /* If the ciphersuite requires signing, check whether\n     * a suitable hash algorithm is present. */\n    sig_type = mbedtls_ssl_get_ciphersuite_sig_alg(suite_info);\n    if (sig_type != MBEDTLS_PK_NONE &&\n        mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg(\n            ssl, mbedtls_ssl_sig_from_pk_alg(sig_type)) == MBEDTLS_SSL_HASH_NONE) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"ciphersuite mismatch: no suitable hash algorithm \"\n                                  \"for signature algorithm %u\", (unsigned) sig_type));\n        return 0;\n    }\n\n#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */\n\n    *ciphersuite_info = suite_info;\n    return 0;\n}\n\n/* This function doesn't alert on errors that happen early during\n   ClientHello parsing because they might indicate that the client is\n   not talking SSL/TLS at all and would not understand our alert. */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_client_hello(mbedtls_ssl_context *ssl)\n{\n    int ret, got_common_suite;\n    size_t i, j;\n    size_t ciph_offset, comp_offset, ext_offset;\n    size_t msg_len, ciph_len, sess_len, comp_len, ext_len;\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    size_t cookie_offset, cookie_len;\n#endif\n    unsigned char *buf, *p, *ext;\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    int renegotiation_info_seen = 0;\n#endif\n    int handshake_failure = 0;\n    const int *ciphersuites;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;\n\n    /* If there is no signature-algorithm extension present,\n     * we need to fall back to the default values for allowed\n     * signature-hash pairs. */\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)\n    int sig_hash_alg_ext_present = 0;\n#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse client hello\"));\n\n    int renegotiating;\n\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\nread_record_header:\n#endif\n    /*\n     * If renegotiating, then the input was read with mbedtls_ssl_read_record(),\n     * otherwise read it ourselves manually in order to support SSLv2\n     * ClientHello, which doesn't use the same record layer format.\n     * Otherwise in a scenario of TLS 1.3/TLS 1.2 version negotiation, the\n     * ClientHello has been already fully fetched by the TLS 1.3 code and the\n     * flag ssl->keep_current_message is raised.\n     */\n    renegotiating = 0;\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    renegotiating = (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE);\n#endif\n    if (!renegotiating && !ssl->keep_current_message) {\n        if ((ret = mbedtls_ssl_fetch_input(ssl, 5)) != 0) {\n            /* No alert on a read error. */\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_fetch_input\", ret);\n            return ret;\n        }\n    }\n\n    buf = ssl->in_hdr;\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"record header\", buf, mbedtls_ssl_in_hdr_len(ssl));\n\n    /*\n     * TLS Client Hello\n     *\n     * Record layer:\n     *     0  .   0   message type\n     *     1  .   2   protocol version\n     *     3  .   11  DTLS: epoch + record sequence number\n     *     3  .   4   message length\n     */\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"client hello, message type: %d\",\n                              buf[0]));\n\n    if (buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"client hello, message len.: %d\",\n                              MBEDTLS_GET_UINT16_BE(ssl->in_len, 0)));\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"client hello, protocol version: [%d:%d]\",\n                              buf[1], buf[2]));\n\n    /* For DTLS if this is the initial handshake, remember the client sequence\n     * number to use it in our next message (RFC 6347 4.2.1) */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n        && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE\n#endif\n        ) {\n        /* Epoch should be 0 for initial handshakes */\n        if (ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n        }\n\n        memcpy(&ssl->cur_out_ctr[2], ssl->in_ctr + 2,\n               sizeof(ssl->cur_out_ctr) - 2);\n\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\n        if (mbedtls_ssl_dtls_replay_check(ssl) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"replayed record, discarding\"));\n            ssl->next_record_offset = 0;\n            ssl->in_left = 0;\n            goto read_record_header;\n        }\n\n        /* No MAC to check yet, so we can update right now */\n        mbedtls_ssl_dtls_replay_update(ssl);\n#endif\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    msg_len = MBEDTLS_GET_UINT16_BE(ssl->in_len, 0);\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {\n        /* Set by mbedtls_ssl_read_record() */\n        msg_len = ssl->in_hslen;\n    } else\n#endif\n    {\n        if (ssl->keep_current_message) {\n            ssl->keep_current_message = 0;\n        } else {\n            if (msg_len > MBEDTLS_SSL_IN_CONTENT_LEN) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n                return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n            }\n\n            if ((ret = mbedtls_ssl_fetch_input(ssl,\n                                               mbedtls_ssl_in_hdr_len(ssl) + msg_len)) != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_fetch_input\", ret);\n                return ret;\n            }\n\n            /* Done reading this record, get ready for the next one */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n            if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n                ssl->next_record_offset = msg_len + mbedtls_ssl_in_hdr_len(ssl);\n            } else\n#endif\n            ssl->in_left = 0;\n        }\n    }\n\n    buf = ssl->in_msg;\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"record contents\", buf, msg_len);\n\n    ret = ssl->handshake->update_checksum(ssl, buf, msg_len);\n    if (0 != ret) {\n        MBEDTLS_SSL_DEBUG_RET(1, (\"update_checksum\"), ret);\n        return ret;\n    }\n\n    /*\n     * Handshake layer:\n     *     0  .   0   handshake type\n     *     1  .   3   handshake length\n     *     4  .   5   DTLS only: message sequence number\n     *     6  .   8   DTLS only: fragment offset\n     *     9  .  11   DTLS only: fragment length\n     */\n    if (msg_len < mbedtls_ssl_hs_hdr_len(ssl)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"client hello v3, handshake type: %d\", buf[0]));\n\n    if (buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        /*\n         * Copy the client's handshake message_seq on initial handshakes,\n         * check sequence number on renego.\n         */\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n        if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {\n            /* This couldn't be done in ssl_prepare_handshake_record() */\n            unsigned int cli_msg_seq = (unsigned int) MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4);\n            if (cli_msg_seq != ssl->handshake->in_msg_seq) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message_seq: \"\n                                          \"%u (expected %u)\", cli_msg_seq,\n                                          ssl->handshake->in_msg_seq));\n                return MBEDTLS_ERR_SSL_DECODE_ERROR;\n            }\n\n            ssl->handshake->in_msg_seq++;\n        } else\n#endif\n        {\n            unsigned int cli_msg_seq = (unsigned int) MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4);\n            ssl->handshake->out_msg_seq = cli_msg_seq;\n            ssl->handshake->in_msg_seq  = cli_msg_seq + 1;\n        }\n        {\n            /*\n             * For now we don't support fragmentation, so make sure\n             * fragment_offset == 0 and fragment_length == length\n             */\n            size_t fragment_offset, fragment_length, length;\n            fragment_offset = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 6);\n            fragment_length = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 9);\n            length = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 1);\n            MBEDTLS_SSL_DEBUG_MSG(\n                4, (\"fragment_offset=%u fragment_length=%u length=%u\",\n                    (unsigned) fragment_offset, (unsigned) fragment_length,\n                    (unsigned) length));\n            if (fragment_offset != 0 || length != fragment_length) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"ClientHello fragmentation not supported\"));\n                return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n            }\n        }\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    buf += mbedtls_ssl_hs_hdr_len(ssl);\n    msg_len -= mbedtls_ssl_hs_hdr_len(ssl);\n\n    /*\n     * ClientHello layout:\n     *     0  .   1   protocol version\n     *     2  .  33   random bytes (starting with 4 bytes of Unix time)\n     *    34  .  34   session id length (1 byte)\n     *    35  . 34+x  session id, where x = session id length from byte 34\n     *   35+x . 35+x  DTLS only: cookie length (1 byte)\n     *   36+x .  ..   DTLS only: cookie\n     *    ..  .  ..   ciphersuite list length (2 bytes)\n     *    ..  .  ..   ciphersuite list\n     *    ..  .  ..   compression alg. list length (1 byte)\n     *    ..  .  ..   compression alg. list\n     *    ..  .  ..   extensions length (2 bytes, optional)\n     *    ..  .  ..   extensions (optional)\n     */\n\n    /*\n     * Minimal length (with everything empty and extensions omitted) is\n     * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can\n     * read at least up to session id length without worrying.\n     */\n    if (msg_len < 38) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /*\n     * Check and save the protocol version\n     */\n    MBEDTLS_SSL_DEBUG_BUF(3, \"client hello, version\", buf, 2);\n\n    ssl->tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(buf,\n                                                                               ssl->conf->transport);\n    ssl->session_negotiate->tls_version = ssl->tls_version;\n    ssl->session_negotiate->endpoint = ssl->conf->endpoint;\n\n    if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"server only supports TLS 1.2\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION);\n        return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;\n    }\n\n    /*\n     * Save client random (inc. Unix time)\n     */\n    MBEDTLS_SSL_DEBUG_BUF(3, \"client hello, random bytes\", buf + 2, 32);\n\n    memcpy(ssl->handshake->randbytes, buf + 2, 32);\n\n    /*\n     * Check the session ID length and save session ID\n     */\n    sess_len = buf[34];\n\n    if (sess_len > sizeof(ssl->session_negotiate->id) ||\n        sess_len + 34 + 2 > msg_len) { /* 2 for cipherlist length field */\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"client hello, session id\", buf + 35, sess_len);\n\n    ssl->session_negotiate->id_len = sess_len;\n    memset(ssl->session_negotiate->id, 0,\n           sizeof(ssl->session_negotiate->id));\n    memcpy(ssl->session_negotiate->id, buf + 35,\n           ssl->session_negotiate->id_len);\n\n    /*\n     * Check the cookie length and content\n     */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        cookie_offset = 35 + sess_len;\n        cookie_len = buf[cookie_offset];\n\n        if (cookie_offset + 1 + cookie_len + 2 > msg_len) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n            mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n\n        MBEDTLS_SSL_DEBUG_BUF(3, \"client hello, cookie\",\n                              buf + cookie_offset + 1, cookie_len);\n\n#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)\n        if (ssl->conf->f_cookie_check != NULL\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n            && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE\n#endif\n            ) {\n            if (ssl->conf->f_cookie_check(ssl->conf->p_cookie,\n                                          buf + cookie_offset + 1, cookie_len,\n                                          ssl->cli_id, ssl->cli_id_len) != 0) {\n                MBEDTLS_SSL_DEBUG_MSG(2, (\"cookie verification failed\"));\n                ssl->handshake->cookie_verify_result = 1;\n            } else {\n                MBEDTLS_SSL_DEBUG_MSG(2, (\"cookie verification passed\"));\n                ssl->handshake->cookie_verify_result = 0;\n            }\n        } else\n#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */\n        {\n            /* We know we didn't send a cookie, so it should be empty */\n            if (cookie_len != 0) {\n                /* This may be an attacker's probe, so don't send an alert */\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n                return MBEDTLS_ERR_SSL_DECODE_ERROR;\n            }\n\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"cookie verification skipped\"));\n        }\n\n        /*\n         * Check the ciphersuitelist length (will be parsed later)\n         */\n        ciph_offset = cookie_offset + 1 + cookie_len;\n    } else\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n    ciph_offset = 35 + sess_len;\n\n    ciph_len = MBEDTLS_GET_UINT16_BE(buf, ciph_offset);\n\n    if (ciph_len < 2 ||\n        ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */\n        (ciph_len % 2) != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"client hello, ciphersuitelist\",\n                          buf + ciph_offset + 2,  ciph_len);\n\n    /*\n     * Check the compression algorithm's length.\n     * The list contents are ignored because implementing\n     * MBEDTLS_SSL_COMPRESS_NULL is mandatory and is the only\n     * option supported by Mbed TLS.\n     */\n    comp_offset = ciph_offset + 2 + ciph_len;\n\n    comp_len = buf[comp_offset];\n\n    if (comp_len < 1 ||\n        comp_len > 16 ||\n        comp_len + comp_offset + 1 > msg_len) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"client hello, compression\",\n                          buf + comp_offset + 1, comp_len);\n\n    /*\n     * Check the extension length\n     */\n    ext_offset = comp_offset + 1 + comp_len;\n    if (msg_len > ext_offset) {\n        if (msg_len < ext_offset + 2) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n            mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n\n        ext_len = MBEDTLS_GET_UINT16_BE(buf, ext_offset);\n\n        if (msg_len != ext_offset + 2 + ext_len) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n            mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n    } else {\n        ext_len = 0;\n    }\n\n    ext = buf + ext_offset + 2;\n    MBEDTLS_SSL_DEBUG_BUF(3, \"client hello extensions\", ext, ext_len);\n\n    while (ext_len != 0) {\n        unsigned int ext_id;\n        unsigned int ext_size;\n        if (ext_len < 4) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n            mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n        ext_id   = MBEDTLS_GET_UINT16_BE(ext, 0);\n        ext_size = MBEDTLS_GET_UINT16_BE(ext, 2);\n\n        if (ext_size + 4 > ext_len) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n            mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n        switch (ext_id) {\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n            case MBEDTLS_TLS_EXT_SERVERNAME:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found ServerName extension\"));\n                ret = mbedtls_ssl_parse_server_name_ext(ssl, ext + 4,\n                                                        ext + 4 + ext_size);\n                if (ret != 0) {\n                    return ret;\n                }\n                break;\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n            case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found renegotiation extension\"));\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n                renegotiation_info_seen = 1;\n#endif\n\n                ret = ssl_parse_renegotiation_info(ssl, ext + 4, ext_size);\n                if (ret != 0) {\n                    return ret;\n                }\n                break;\n\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)\n            case MBEDTLS_TLS_EXT_SIG_ALG:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found signature_algorithms extension\"));\n\n                ret = mbedtls_ssl_parse_sig_alg_ext(ssl, ext + 4, ext + 4 + ext_size);\n                if (ret != 0) {\n                    return ret;\n                }\n\n                sig_hash_alg_ext_present = 1;\n                break;\n#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \\\n                defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \\\n                defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n            case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found supported elliptic curves extension\"));\n\n                ret = ssl_parse_supported_groups_ext(ssl, ext + 4, ext_size);\n                if (ret != 0) {\n                    return ret;\n                }\n                break;\n\n            case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found supported point formats extension\"));\n                ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT;\n\n                ret = ssl_parse_supported_point_formats(ssl, ext + 4, ext_size);\n                if (ret != 0) {\n                    return ret;\n                }\n                break;\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || \\\n          MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n            case MBEDTLS_TLS_EXT_ECJPAKE_KKPP:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found ecjpake kkpp extension\"));\n\n                ret = ssl_parse_ecjpake_kkpp(ssl, ext + 4, ext_size);\n                if (ret != 0) {\n                    return ret;\n                }\n                break;\n#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n            case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found max fragment length extension\"));\n\n                ret = ssl_parse_max_fragment_length_ext(ssl, ext + 4, ext_size);\n                if (ret != 0) {\n                    return ret;\n                }\n                break;\n#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n            case MBEDTLS_TLS_EXT_CID:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found CID extension\"));\n\n                ret = ssl_parse_cid_ext(ssl, ext + 4, ext_size);\n                if (ret != 0) {\n                    return ret;\n                }\n                break;\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n            case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found encrypt then mac extension\"));\n\n                ret = ssl_parse_encrypt_then_mac_ext(ssl, ext + 4, ext_size);\n                if (ret != 0) {\n                    return ret;\n                }\n                break;\n#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */\n\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\n            case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found extended master secret extension\"));\n\n                ret = ssl_parse_extended_ms_ext(ssl, ext + 4, ext_size);\n                if (ret != 0) {\n                    return ret;\n                }\n                break;\n#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n            case MBEDTLS_TLS_EXT_SESSION_TICKET:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found session ticket extension\"));\n\n                ret = ssl_parse_session_ticket_ext(ssl, ext + 4, ext_size);\n                if (ret != 0) {\n                    return ret;\n                }\n                break;\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n#if defined(MBEDTLS_SSL_ALPN)\n            case MBEDTLS_TLS_EXT_ALPN:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found alpn extension\"));\n\n                ret = mbedtls_ssl_parse_alpn_ext(ssl, ext + 4,\n                                                 ext + 4 + ext_size);\n                if (ret != 0) {\n                    return ret;\n                }\n                break;\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\n            case MBEDTLS_TLS_EXT_USE_SRTP:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found use_srtp extension\"));\n\n                ret = ssl_parse_use_srtp_ext(ssl, ext + 4, ext_size);\n                if (ret != 0) {\n                    return ret;\n                }\n                break;\n#endif /* MBEDTLS_SSL_DTLS_SRTP */\n\n            default:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"unknown extension found: %u (ignoring)\",\n                                          ext_id));\n        }\n\n        ext_len -= 4 + ext_size;\n        ext += 4 + ext_size;\n    }\n\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)\n\n    /*\n     * Try to fall back to default hash SHA1 if the client\n     * hasn't provided any preferred signature-hash combinations.\n     */\n    if (!sig_hash_alg_ext_present) {\n        uint16_t *received_sig_algs = ssl->handshake->received_sig_algs;\n        const uint16_t default_sig_algs[] = {\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)\n            MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA,\n                                               MBEDTLS_SSL_HASH_SHA1),\n#endif\n#if defined(MBEDTLS_RSA_C)\n            MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA,\n                                               MBEDTLS_SSL_HASH_SHA1),\n#endif\n            MBEDTLS_TLS_SIG_NONE\n        };\n\n        MBEDTLS_STATIC_ASSERT(sizeof(default_sig_algs) / sizeof(default_sig_algs[0])\n                              <= MBEDTLS_RECEIVED_SIG_ALGS_SIZE,\n                              \"default_sig_algs is too big\");\n\n        memcpy(received_sig_algs, default_sig_algs, sizeof(default_sig_algs));\n    }\n\n#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */\n\n    /*\n     * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV\n     */\n    for (i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2) {\n        if (p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO) {\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"received TLS_EMPTY_RENEGOTIATION_INFO \"));\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n            if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"received RENEGOTIATION SCSV \"\n                                          \"during renegotiation\"));\n                mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                               MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n                return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n            }\n#endif\n            ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;\n            break;\n        }\n    }\n\n    /*\n     * Renegotiation security checks\n     */\n    if (ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION &&\n        ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"legacy renegotiation, breaking off handshake\"));\n        handshake_failure = 1;\n    }\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&\n             ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION &&\n             renegotiation_info_seen == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"renegotiation_info extension missing (secure)\"));\n        handshake_failure = 1;\n    } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&\n               ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&\n               ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"legacy renegotiation not allowed\"));\n        handshake_failure = 1;\n    } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&\n               ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&\n               renegotiation_info_seen == 1) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"renegotiation_info extension present (legacy)\"));\n        handshake_failure = 1;\n    }\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n\n    if (handshake_failure == 1) {\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    /*\n     * Server certification selection (after processing TLS extensions)\n     */\n    if (ssl->conf->f_cert_cb && (ret = ssl->conf->f_cert_cb(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"f_cert_cb\", ret);\n        return ret;\n    }\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    ssl->handshake->sni_name = NULL;\n    ssl->handshake->sni_name_len = 0;\n#endif\n\n    /*\n     * Search for a matching ciphersuite\n     * (At the end because we need information from the EC-based extensions\n     * and certificate from the SNI callback triggered by the SNI extension\n     * or certificate from server certificate selection callback.)\n     */\n    got_common_suite = 0;\n    ciphersuites = ssl->conf->ciphersuite_list;\n    ciphersuite_info = NULL;\n\n    if (ssl->conf->respect_cli_pref == MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT) {\n        for (j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2) {\n            for (i = 0; ciphersuites[i] != 0; i++) {\n                if (MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i]) {\n                    continue;\n                }\n\n                got_common_suite = 1;\n\n                if ((ret = ssl_ciphersuite_match(ssl, ciphersuites[i],\n                                                 &ciphersuite_info)) != 0) {\n                    return ret;\n                }\n\n                if (ciphersuite_info != NULL) {\n                    goto have_ciphersuite;\n                }\n            }\n        }\n    } else {\n        for (i = 0; ciphersuites[i] != 0; i++) {\n            for (j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2) {\n                if (MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i]) {\n                    continue;\n                }\n\n                got_common_suite = 1;\n\n                if ((ret = ssl_ciphersuite_match(ssl, ciphersuites[i],\n                                                 &ciphersuite_info)) != 0) {\n                    return ret;\n                }\n\n                if (ciphersuite_info != NULL) {\n                    goto have_ciphersuite;\n                }\n            }\n        }\n    }\n\n    if (got_common_suite) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"got ciphersuites in common, \"\n                                  \"but none of them usable\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"got no ciphersuites in common\"));\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\nhave_ciphersuite:\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"selected ciphersuite: %s\", ciphersuite_info->name));\n\n    ssl->session_negotiate->ciphersuite = ciphersuites[i];\n    ssl->handshake->ciphersuite_info = ciphersuite_info;\n\n    mbedtls_ssl_handshake_increment_state(ssl);\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        mbedtls_ssl_recv_flight_completed(ssl);\n    }\n#endif\n\n    /* Debugging-only output for testsuite */\n#if defined(MBEDTLS_DEBUG_C)                         && \\\n    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)\n    mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg(ciphersuite_info);\n    if (sig_alg != MBEDTLS_PK_NONE) {\n        unsigned int sig_hash = mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg(\n            ssl, mbedtls_ssl_sig_from_pk_alg(sig_alg));\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"client hello v3, signature_algorithm ext: %u\",\n                                  sig_hash));\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"no hash algorithm for signature algorithm \"\n                                  \"%u - should not happen\", (unsigned) sig_alg));\n    }\n#endif\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse client hello\"));\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\nstatic void ssl_write_cid_ext(mbedtls_ssl_context *ssl,\n                              unsigned char *buf,\n                              size_t *olen)\n{\n    unsigned char *p = buf;\n    size_t ext_len;\n    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;\n\n    *olen = 0;\n\n    /* Skip writing the extension if we don't want to use it or if\n     * the client hasn't offered it. */\n    if (ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_DISABLED) {\n        return;\n    }\n\n    /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX\n     * which is at most 255, so the increment cannot overflow. */\n    if (end < p || (size_t) (end - p) < (unsigned) (ssl->own_cid_len + 5)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"buffer too small\"));\n        return;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, adding CID extension\"));\n\n    /*\n     *   struct {\n     *      opaque cid<0..2^8-1>;\n     *   } ConnectionId;\n     */\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_CID, p, 0);\n    p += 2;\n    ext_len = (size_t) ssl->own_cid_len + 1;\n    MBEDTLS_PUT_UINT16_BE(ext_len, p, 0);\n    p += 2;\n\n    *p++ = (uint8_t) ssl->own_cid_len;\n    memcpy(p, ssl->own_cid, ssl->own_cid_len);\n\n    *olen = ssl->own_cid_len + 5;\n}\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)\nstatic void ssl_write_encrypt_then_mac_ext(mbedtls_ssl_context *ssl,\n                                           unsigned char *buf,\n                                           size_t *olen)\n{\n    unsigned char *p = buf;\n    const mbedtls_ssl_ciphersuite_t *suite = NULL;\n\n    /*\n     * RFC 7366: \"If a server receives an encrypt-then-MAC request extension\n     * from a client and then selects a stream or Authenticated Encryption\n     * with Associated Data (AEAD) ciphersuite, it MUST NOT send an\n     * encrypt-then-MAC response extension back to the client.\"\n     */\n    suite = mbedtls_ssl_ciphersuite_from_id(\n        ssl->session_negotiate->ciphersuite);\n    if (suite == NULL) {\n        ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED;\n    } else {\n        mbedtls_ssl_mode_t ssl_mode =\n            mbedtls_ssl_get_mode_from_ciphersuite(\n                ssl->session_negotiate->encrypt_then_mac,\n                suite);\n\n        if (ssl_mode != MBEDTLS_SSL_MODE_CBC_ETM) {\n            ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED;\n        }\n    }\n\n    if (ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED) {\n        *olen = 0;\n        return;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, adding encrypt then mac extension\"));\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0);\n    p += 2;\n\n    *p++ = 0x00;\n    *p++ = 0x00;\n\n    *olen = 4;\n}\n#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */\n\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\nstatic void ssl_write_extended_ms_ext(mbedtls_ssl_context *ssl,\n                                      unsigned char *buf,\n                                      size_t *olen)\n{\n    unsigned char *p = buf;\n\n    if (ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED) {\n        *olen = 0;\n        return;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, adding extended master secret \"\n                              \"extension\"));\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0);\n    p += 2;\n\n    *p++ = 0x00;\n    *p++ = 0x00;\n\n    *olen = 4;\n}\n#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\nstatic void ssl_write_session_ticket_ext(mbedtls_ssl_context *ssl,\n                                         unsigned char *buf,\n                                         size_t *olen)\n{\n    unsigned char *p = buf;\n\n    if (ssl->handshake->new_session_ticket == 0) {\n        *olen = 0;\n        return;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, adding session ticket extension\"));\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0);\n    p += 2;\n\n    *p++ = 0x00;\n    *p++ = 0x00;\n\n    *olen = 4;\n}\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\nstatic void ssl_write_renegotiation_ext(mbedtls_ssl_context *ssl,\n                                        unsigned char *buf,\n                                        size_t *olen)\n{\n    unsigned char *p = buf;\n\n    if (ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION) {\n        *olen = 0;\n        return;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, secure renegotiation extension\"));\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0);\n    p += 2;\n\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {\n        *p++ = 0x00;\n        *p++ = (ssl->verify_data_len * 2 + 1) & 0xFF;\n        *p++ = ssl->verify_data_len * 2 & 0xFF;\n\n        memcpy(p, ssl->peer_verify_data, ssl->verify_data_len);\n        p += ssl->verify_data_len;\n        memcpy(p, ssl->own_verify_data, ssl->verify_data_len);\n        p += ssl->verify_data_len;\n    } else\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n    {\n        *p++ = 0x00;\n        *p++ = 0x01;\n        *p++ = 0x00;\n    }\n\n    *olen = (size_t) (p - buf);\n}\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\nstatic void ssl_write_max_fragment_length_ext(mbedtls_ssl_context *ssl,\n                                              unsigned char *buf,\n                                              size_t *olen)\n{\n    unsigned char *p = buf;\n\n    if (ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE) {\n        *olen = 0;\n        return;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, max_fragment_length extension\"));\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0);\n    p += 2;\n\n    *p++ = 0x00;\n    *p++ = 1;\n\n    *p++ = ssl->session_negotiate->mfl_code;\n\n    *olen = 5;\n}\n#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\nstatic void ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl,\n                                                  unsigned char *buf,\n                                                  size_t *olen)\n{\n    unsigned char *p = buf;\n    ((void) ssl);\n\n    if ((ssl->handshake->cli_exts &\n         MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT) == 0) {\n        *olen = 0;\n        return;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, supported_point_formats extension\"));\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0);\n    p += 2;\n\n    *p++ = 0x00;\n    *p++ = 2;\n\n    *p++ = 1;\n    *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED;\n\n    *olen = 6;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\nstatic void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl,\n                                       unsigned char *buf,\n                                       size_t *olen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = buf;\n    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;\n    size_t kkpp_len;\n\n    *olen = 0;\n\n    /* Skip costly computation if not needed */\n    if (ssl->handshake->ciphersuite_info->key_exchange !=\n        MBEDTLS_KEY_EXCHANGE_ECJPAKE) {\n        return;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, ecjpake kkpp extension\"));\n\n    if (end - p < 4) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"buffer too small\"));\n        return;\n    }\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0);\n    p += 2;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx,\n                                          p + 2, (size_t) (end - p - 2), &kkpp_len,\n                                          MBEDTLS_ECJPAKE_ROUND_ONE);\n    if (ret != 0) {\n        psa_destroy_key(ssl->handshake->psa_pake_password);\n        psa_pake_abort(&ssl->handshake->psa_pake_ctx);\n        MBEDTLS_SSL_DEBUG_RET(1, \"psa_pake_output\", ret);\n        return;\n    }\n#else\n    ret = mbedtls_ecjpake_write_round_one(&ssl->handshake->ecjpake_ctx,\n                                          p + 2, (size_t) (end - p - 2), &kkpp_len,\n                                          ssl->conf->f_rng, ssl->conf->p_rng);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecjpake_write_round_one\", ret);\n        return;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    MBEDTLS_PUT_UINT16_BE(kkpp_len, p, 0);\n    p += 2;\n\n    *olen = kkpp_len + 4;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP) && defined(MBEDTLS_SSL_PROTO_DTLS)\nstatic void ssl_write_use_srtp_ext(mbedtls_ssl_context *ssl,\n                                   unsigned char *buf,\n                                   size_t *olen)\n{\n    size_t mki_len = 0, ext_len = 0;\n    uint16_t profile_value = 0;\n    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;\n\n    *olen = 0;\n\n    if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||\n        (ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET)) {\n        return;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, adding use_srtp extension\"));\n\n    if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED) {\n        mki_len = ssl->dtls_srtp_info.mki_len;\n    }\n\n    /* The extension total size is 9 bytes :\n     * - 2 bytes for the extension tag\n     * - 2 bytes for the total size\n     * - 2 bytes for the protection profile length\n     * - 2 bytes for the protection profile\n     * - 1 byte for the mki length\n     * +  the actual mki length\n     * Check we have enough room in the output buffer */\n    if ((size_t) (end - buf) < mki_len + 9) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"buffer too small\"));\n        return;\n    }\n\n    /* extension */\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_USE_SRTP, buf, 0);\n    /*\n     * total length 5 and mki value: only one profile(2 bytes)\n     *              and length(2 bytes) and srtp_mki  )\n     */\n    ext_len = 5 + mki_len;\n    MBEDTLS_PUT_UINT16_BE(ext_len, buf, 2);\n\n    /* protection profile length: 2 */\n    buf[4] = 0x00;\n    buf[5] = 0x02;\n    profile_value = mbedtls_ssl_check_srtp_profile_value(\n        ssl->dtls_srtp_info.chosen_dtls_srtp_profile);\n    if (profile_value != MBEDTLS_TLS_SRTP_UNSET) {\n        MBEDTLS_PUT_UINT16_BE(profile_value, buf, 6);\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"use_srtp extension invalid profile\"));\n        return;\n    }\n\n    buf[8] = mki_len & 0xFF;\n    memcpy(&buf[9], ssl->dtls_srtp_info.mki_value, mki_len);\n\n    *olen = 9 + mki_len;\n}\n#endif /* MBEDTLS_SSL_DTLS_SRTP */\n\n#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_hello_verify_request(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = ssl->out_msg + 4;\n    unsigned char *cookie_len_byte;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write hello verify request\"));\n\n    /*\n     * struct {\n     *   ProtocolVersion server_version;\n     *   opaque cookie<0..2^8-1>;\n     * } HelloVerifyRequest;\n     */\n\n    /* The RFC is not clear on this point, but sending the actual negotiated\n     * version looks like the most interoperable thing to do. */\n    mbedtls_ssl_write_version(p, ssl->conf->transport, ssl->tls_version);\n    MBEDTLS_SSL_DEBUG_BUF(3, \"server version\", p, 2);\n    p += 2;\n\n    /* If we get here, f_cookie_check is not null */\n    if (ssl->conf->f_cookie_write == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"inconsistent cookie callbacks\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    /* Skip length byte until we know the length */\n    cookie_len_byte = p++;\n\n    if ((ret = ssl->conf->f_cookie_write(ssl->conf->p_cookie,\n                                         &p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN,\n                                         ssl->cli_id, ssl->cli_id_len)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"f_cookie_write\", ret);\n        return ret;\n    }\n\n    *cookie_len_byte = (unsigned char) (p - (cookie_len_byte + 1));\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"cookie sent\", cookie_len_byte + 1, *cookie_len_byte);\n\n    ssl->out_msglen  = (size_t) (p - ssl->out_msg);\n    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;\n    ssl->out_msg[0]  = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST;\n\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT);\n\n    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_write_handshake_msg\", ret);\n        return ret;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n        (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_flight_transmit\", ret);\n        return ret;\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write hello verify request\"));\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */\n\nstatic void ssl_handle_id_based_session_resumption(mbedtls_ssl_context *ssl)\n{\n    int ret;\n    mbedtls_ssl_session session_tmp;\n    mbedtls_ssl_session * const session = ssl->session_negotiate;\n\n    /* Resume is 0  by default, see ssl_handshake_init().\n     * It may be already set to 1 by ssl_parse_session_ticket_ext(). */\n    if (ssl->handshake->resume == 1) {\n        return;\n    }\n    if (session->id_len == 0) {\n        return;\n    }\n    if (ssl->conf->f_get_cache == NULL) {\n        return;\n    }\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {\n        return;\n    }\n#endif\n\n    mbedtls_ssl_session_init(&session_tmp);\n\n    ret = ssl->conf->f_get_cache(ssl->conf->p_cache,\n                                 session->id,\n                                 session->id_len,\n                                 &session_tmp);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    if (session->ciphersuite != session_tmp.ciphersuite) {\n        /* Mismatch between cached and negotiated session */\n        goto exit;\n    }\n\n    /* Move semantics */\n    mbedtls_ssl_session_free(session);\n    *session = session_tmp;\n    memset(&session_tmp, 0, sizeof(session_tmp));\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"session successfully restored from cache\"));\n    ssl->handshake->resume = 1;\n\nexit:\n\n    mbedtls_ssl_session_free(&session_tmp);\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_server_hello(mbedtls_ssl_context *ssl)\n{\n#if defined(MBEDTLS_HAVE_TIME)\n    mbedtls_time_t t;\n#endif\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t olen, ext_len = 0, n;\n    unsigned char *buf, *p;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write server hello\"));\n\n#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n        ssl->handshake->cookie_verify_result != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"client hello was not authenticated\"));\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write server hello\"));\n\n        return ssl_write_hello_verify_request(ssl);\n    }\n#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */\n\n    /*\n     *     0  .   0   handshake type\n     *     1  .   3   handshake length\n     *     4  .   5   protocol version\n     *     6  .   9   UNIX time()\n     *    10  .  37   random bytes\n     */\n    buf = ssl->out_msg;\n    p = buf + 4;\n\n    mbedtls_ssl_write_version(p, ssl->conf->transport, ssl->tls_version);\n    p += 2;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, chosen version: [%d:%d]\",\n                              buf[4], buf[5]));\n\n#if defined(MBEDTLS_HAVE_TIME)\n    t = mbedtls_time(NULL);\n    MBEDTLS_PUT_UINT32_BE(t, p, 0);\n    p += 4;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, current time: %\" MBEDTLS_PRINTF_LONGLONG,\n                              (long long) t));\n#else\n    if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 4)) != 0) {\n        return ret;\n    }\n\n    p += 4;\n#endif /* MBEDTLS_HAVE_TIME */\n\n    if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 20)) != 0) {\n        return ret;\n    }\n    p += 20;\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    /*\n     * RFC 8446\n     * TLS 1.3 has a downgrade protection mechanism embedded in the server's\n     * random value. TLS 1.3 servers which negotiate TLS 1.2 or below in\n     * response to a ClientHello MUST set the last 8 bytes of their Random\n     * value specially in their ServerHello.\n     */\n    if (mbedtls_ssl_conf_is_tls13_enabled(ssl->conf)) {\n        static const unsigned char magic_tls12_downgrade_string[] =\n        { 'D', 'O', 'W', 'N', 'G', 'R', 'D', 1 };\n\n        MBEDTLS_STATIC_ASSERT(\n            sizeof(magic_tls12_downgrade_string) == 8,\n            \"magic_tls12_downgrade_string does not have the expected size\");\n\n        memcpy(p, magic_tls12_downgrade_string,\n               sizeof(magic_tls12_downgrade_string));\n    } else\n#endif\n    {\n        if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 8)) != 0) {\n            return ret;\n        }\n    }\n    p += 8;\n\n    memcpy(ssl->handshake->randbytes + 32, buf + 6, 32);\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"server hello, random bytes\", buf + 6, 32);\n\n    ssl_handle_id_based_session_resumption(ssl);\n\n    if (ssl->handshake->resume == 0) {\n        /*\n         * New session, create a new session id,\n         * unless we're about to issue a session ticket\n         */\n        mbedtls_ssl_handshake_increment_state(ssl);\n\n#if defined(MBEDTLS_HAVE_TIME)\n        ssl->session_negotiate->start = mbedtls_time(NULL);\n#endif\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n        if (ssl->handshake->new_session_ticket != 0) {\n            ssl->session_negotiate->id_len = n = 0;\n            memset(ssl->session_negotiate->id, 0, 32);\n        } else\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n        {\n            ssl->session_negotiate->id_len = n = 32;\n            if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, ssl->session_negotiate->id,\n                                        n)) != 0) {\n                return ret;\n            }\n        }\n    } else {\n        /*\n         * Resuming a session\n         */\n        n = ssl->session_negotiate->id_len;\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC);\n\n        if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_derive_keys\", ret);\n            return ret;\n        }\n    }\n\n    /*\n     *    38  .  38     session id length\n     *    39  . 38+n    session id\n     *   39+n . 40+n    chosen ciphersuite\n     *   41+n . 41+n    chosen compression alg.\n     *   42+n . 43+n    extensions length\n     *   44+n . 43+n+m  extensions\n     */\n    *p++ = (unsigned char) ssl->session_negotiate->id_len;\n    memcpy(p, ssl->session_negotiate->id, ssl->session_negotiate->id_len);\n    p += ssl->session_negotiate->id_len;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, session id len.: %\" MBEDTLS_PRINTF_SIZET, n));\n    MBEDTLS_SSL_DEBUG_BUF(3,   \"server hello, session id\", buf + 39, n);\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"%s session has been resumed\",\n                              ssl->handshake->resume ? \"a\" : \"no\"));\n\n    MBEDTLS_PUT_UINT16_BE(ssl->session_negotiate->ciphersuite, p, 0);\n    p += 2;\n    *p++ = MBEDTLS_BYTE_0(MBEDTLS_SSL_COMPRESS_NULL);\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, chosen ciphersuite: %s\",\n                              mbedtls_ssl_get_ciphersuite_name(ssl->session_negotiate->ciphersuite)));\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, compress alg.: 0x%02X\",\n                              (unsigned int) MBEDTLS_SSL_COMPRESS_NULL));\n\n    /*\n     *  First write extensions, then the total length\n     */\n    ssl_write_renegotiation_ext(ssl, p + 2 + ext_len, &olen);\n    ext_len += olen;\n\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n    ssl_write_max_fragment_length_ext(ssl, p + 2 + ext_len, &olen);\n    ext_len += olen;\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    ssl_write_cid_ext(ssl, p + 2 + ext_len, &olen);\n    ext_len += olen;\n#endif\n\n#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)\n    ssl_write_encrypt_then_mac_ext(ssl, p + 2 + ext_len, &olen);\n    ext_len += olen;\n#endif\n\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\n    ssl_write_extended_ms_ext(ssl, p + 2 + ext_len, &olen);\n    ext_len += olen;\n#endif\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n    ssl_write_session_ticket_ext(ssl, p + 2 + ext_len, &olen);\n    ext_len += olen;\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n    const mbedtls_ssl_ciphersuite_t *suite =\n        mbedtls_ssl_ciphersuite_from_id(ssl->session_negotiate->ciphersuite);\n    if (suite != NULL && mbedtls_ssl_ciphersuite_uses_ec(suite)) {\n        ssl_write_supported_point_formats_ext(ssl, p + 2 + ext_len, &olen);\n        ext_len += olen;\n    }\n#endif\n\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n    ssl_write_ecjpake_kkpp_ext(ssl, p + 2 + ext_len, &olen);\n    ext_len += olen;\n#endif\n\n#if defined(MBEDTLS_SSL_ALPN)\n    unsigned char *end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN - 4;\n    if ((ret = mbedtls_ssl_write_alpn_ext(ssl, p + 2 + ext_len, end, &olen))\n        != 0) {\n        return ret;\n    }\n\n    ext_len += olen;\n#endif\n\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\n    ssl_write_use_srtp_ext(ssl, p + 2 + ext_len, &olen);\n    ext_len += olen;\n#endif\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, total extension length: %\" MBEDTLS_PRINTF_SIZET,\n                              ext_len));\n\n    if (ext_len > 0) {\n        MBEDTLS_PUT_UINT16_BE(ext_len, p, 0);\n        p += 2 + ext_len;\n    }\n\n    ssl->out_msglen  = (size_t) (p - buf);\n    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;\n    ssl->out_msg[0]  = MBEDTLS_SSL_HS_SERVER_HELLO;\n\n    ret = mbedtls_ssl_write_handshake_msg(ssl);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write server hello\"));\n\n    return ret;\n}\n\n#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_certificate_request(mbedtls_ssl_context *ssl)\n{\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write certificate request\"));\n\n    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip write certificate request\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n}\n#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_certificate_request(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n    uint16_t dn_size, total_dn_size; /* excluding length bytes */\n    size_t ct_len, sa_len; /* including length bytes */\n    unsigned char *buf, *p;\n    const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;\n    const mbedtls_x509_crt *crt;\n    int authmode;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write certificate request\"));\n\n    mbedtls_ssl_handshake_increment_state(ssl);\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) {\n        authmode = ssl->handshake->sni_authmode;\n    } else\n#endif\n    authmode = ssl->conf->authmode;\n\n    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info) ||\n        authmode == MBEDTLS_SSL_VERIFY_NONE) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip write certificate request\"));\n        return 0;\n    }\n\n    /*\n     *     0  .   0   handshake type\n     *     1  .   3   handshake length\n     *     4  .   4   cert type count\n     *     5  .. m-1  cert types\n     *     m  .. m+1  sig alg length (TLS 1.2 only)\n     *    m+1 .. n-1  SignatureAndHashAlgorithms (TLS 1.2 only)\n     *     n  .. n+1  length of all DNs\n     *    n+2 .. n+3  length of DN 1\n     *    n+4 .. ...  Distinguished Name #1\n     *    ... .. ...  length of DN 2, etc.\n     */\n    buf = ssl->out_msg;\n    p = buf + 4;\n\n    /*\n     * Supported certificate types\n     *\n     *     ClientCertificateType certificate_types<1..2^8-1>;\n     *     enum { (255) } ClientCertificateType;\n     */\n    ct_len = 0;\n\n#if defined(MBEDTLS_RSA_C)\n    p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN;\n#endif\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)\n    p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN;\n#endif\n\n    p[0] = (unsigned char) ct_len++;\n    p += ct_len;\n\n    sa_len = 0;\n\n    /*\n     * Add signature_algorithms for verify (TLS 1.2)\n     *\n     *     SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>;\n     *\n     *     struct {\n     *           HashAlgorithm hash;\n     *           SignatureAlgorithm signature;\n     *     } SignatureAndHashAlgorithm;\n     *\n     *     enum { (255) } HashAlgorithm;\n     *     enum { (255) } SignatureAlgorithm;\n     */\n    const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl);\n    if (sig_alg == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_CONFIG;\n    }\n\n    for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) {\n        unsigned char hash = MBEDTLS_BYTE_1(*sig_alg);\n\n        if (mbedtls_ssl_set_calc_verify_md(ssl, hash)) {\n            continue;\n        }\n        if (!mbedtls_ssl_sig_alg_is_supported(ssl, *sig_alg)) {\n            continue;\n        }\n\n        /* Write elements at offsets starting from 1 (offset 0 is for the\n         * length). Thus the offset of each element is the length of the\n         * partial list including that element. */\n        sa_len += 2;\n        MBEDTLS_PUT_UINT16_BE(*sig_alg, p, sa_len);\n\n    }\n\n    /* Fill in list length. */\n    MBEDTLS_PUT_UINT16_BE(sa_len, p, 0);\n    sa_len += 2;\n    p += sa_len;\n\n    /*\n     * DistinguishedName certificate_authorities<0..2^16-1>;\n     * opaque DistinguishedName<1..2^16-1>;\n     */\n    p += 2;\n\n    total_dn_size = 0;\n\n    if (ssl->conf->cert_req_ca_list ==  MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED) {\n        /* NOTE: If trusted certificates are provisioned\n         *       via a CA callback (configured through\n         *       `mbedtls_ssl_conf_ca_cb()`, then the\n         *       CertificateRequest is currently left empty. */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n        if (ssl->handshake->dn_hints != NULL) {\n            crt = ssl->handshake->dn_hints;\n        } else\n#endif\n        if (ssl->conf->dn_hints != NULL) {\n            crt = ssl->conf->dn_hints;\n        } else\n#endif\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n        if (ssl->handshake->sni_ca_chain != NULL) {\n            crt = ssl->handshake->sni_ca_chain;\n        } else\n#endif\n        crt = ssl->conf->ca_chain;\n\n        while (crt != NULL && crt->version != 0) {\n            /* It follows from RFC 5280 A.1 that this length\n             * can be represented in at most 11 bits. */\n            dn_size = (uint16_t) crt->subject_raw.len;\n\n            if (end < p || (size_t) (end - p) < 2 + (size_t) dn_size) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"skipping CAs: buffer too short\"));\n                break;\n            }\n\n            MBEDTLS_PUT_UINT16_BE(dn_size, p, 0);\n            p += 2;\n            memcpy(p, crt->subject_raw.p, dn_size);\n            p += dn_size;\n\n            MBEDTLS_SSL_DEBUG_BUF(3, \"requested DN\", p - dn_size, dn_size);\n\n            total_dn_size += (unsigned short) (2 + dn_size);\n            crt = crt->next;\n        }\n    }\n\n    ssl->out_msglen  = (size_t) (p - buf);\n    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;\n    ssl->out_msg[0]  = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST;\n    MBEDTLS_PUT_UINT16_BE(total_dn_size, ssl->out_msg, 4 + ct_len + sa_len);\n\n    ret = mbedtls_ssl_write_handshake_msg(ssl);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write certificate request\"));\n\n    return ret;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */\n\n#if (defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED))\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    mbedtls_pk_context *pk;\n    mbedtls_pk_type_t pk_type;\n    psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;\n    unsigned char buf[PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)];\n    size_t key_len;\n#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n    uint16_t tls_id = 0;\n    psa_key_type_t key_type = PSA_KEY_TYPE_NONE;\n    mbedtls_ecp_group_id grp_id;\n    mbedtls_ecp_keypair *key;\n#endif /* !MBEDTLS_PK_USE_PSA_EC_DATA */\n\n    pk = mbedtls_ssl_own_key(ssl);\n\n    if (pk == NULL) {\n        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n    }\n\n    pk_type = mbedtls_pk_get_type(pk);\n\n    switch (pk_type) {\n        case MBEDTLS_PK_OPAQUE:\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n        case MBEDTLS_PK_ECKEY:\n        case MBEDTLS_PK_ECKEY_DH:\n        case MBEDTLS_PK_ECDSA:\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n            if (!mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY)) {\n                return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;\n            }\n\n            /* Get the attributes of the key previously parsed by PK module in\n             * order to extract its type and length (in bits). */\n            status = psa_get_key_attributes(pk->priv_id, &key_attributes);\n            if (status != PSA_SUCCESS) {\n                ret = PSA_TO_MBEDTLS_ERR(status);\n                goto exit;\n            }\n            ssl->handshake->xxdh_psa_type = psa_get_key_type(&key_attributes);\n            ssl->handshake->xxdh_psa_bits = psa_get_key_bits(&key_attributes);\n\n#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n            if (pk_type != MBEDTLS_PK_OPAQUE) {\n                /* PK_ECKEY[_DH] and PK_ECDSA instead as parsed from the PK\n                 * module and only have ECDSA capabilities. Since we need\n                 * them for ECDH later, we export and then re-import them with\n                 * proper flags and algorithm. Of course We also set key's type\n                 * and bits that we just got above. */\n                key_attributes = psa_key_attributes_init();\n                psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);\n                psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);\n                psa_set_key_type(&key_attributes,\n                                 PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->xxdh_psa_type));\n                psa_set_key_bits(&key_attributes, ssl->handshake->xxdh_psa_bits);\n\n                status = psa_export_key(pk->priv_id, buf, sizeof(buf), &key_len);\n                if (status != PSA_SUCCESS) {\n                    ret = PSA_TO_MBEDTLS_ERR(status);\n                    goto exit;\n                }\n                status = psa_import_key(&key_attributes, buf, key_len,\n                                        &ssl->handshake->xxdh_psa_privkey);\n                if (status != PSA_SUCCESS) {\n                    ret = PSA_TO_MBEDTLS_ERR(status);\n                    goto exit;\n                }\n\n                /* Set this key as owned by the TLS library: it will be its duty\n                 * to clear it exit. */\n                ssl->handshake->xxdh_psa_privkey_is_external = 0;\n\n                ret = 0;\n                break;\n            }\n#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */\n\n            /* Opaque key is created by the user (externally from Mbed TLS)\n             * so we assume it already has the right algorithm and flags\n             * set. Just copy its ID as reference. */\n            ssl->handshake->xxdh_psa_privkey = pk->priv_id;\n            ssl->handshake->xxdh_psa_privkey_is_external = 1;\n            ret = 0;\n            break;\n\n#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA)\n        case MBEDTLS_PK_ECKEY:\n        case MBEDTLS_PK_ECKEY_DH:\n        case MBEDTLS_PK_ECDSA:\n            key = mbedtls_pk_ec_rw(*pk);\n            grp_id = mbedtls_pk_get_ec_group_id(pk);\n            if (grp_id == MBEDTLS_ECP_DP_NONE) {\n                return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;\n            }\n            tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id);\n            if (tls_id == 0) {\n                /* This elliptic curve is not supported */\n                return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n            }\n\n            /* If the above conversion to TLS ID was fine, then also this one will\n               be, so there is no need to check the return value here */\n            mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type,\n                                                       &ssl->handshake->xxdh_psa_bits);\n\n            ssl->handshake->xxdh_psa_type = key_type;\n\n            key_attributes = psa_key_attributes_init();\n            psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);\n            psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);\n            psa_set_key_type(&key_attributes,\n                             PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->xxdh_psa_type));\n            psa_set_key_bits(&key_attributes, ssl->handshake->xxdh_psa_bits);\n\n            ret = mbedtls_ecp_write_key_ext(key, &key_len, buf, sizeof(buf));\n            if (ret != 0) {\n                mbedtls_platform_zeroize(buf, sizeof(buf));\n                break;\n            }\n\n            status = psa_import_key(&key_attributes, buf, key_len,\n                                    &ssl->handshake->xxdh_psa_privkey);\n            if (status != PSA_SUCCESS) {\n                ret = PSA_TO_MBEDTLS_ERR(status);\n                mbedtls_platform_zeroize(buf, sizeof(buf));\n                break;\n            }\n\n            mbedtls_platform_zeroize(buf, sizeof(buf));\n            ret = 0;\n            break;\n#endif /* !MBEDTLS_PK_USE_PSA_EC_DATA */\n        default:\n            ret = MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;\n    }\n\nexit:\n    psa_reset_key_attributes(&key_attributes);\n    mbedtls_platform_zeroize(buf, sizeof(buf));\n\n    return ret;\n}\n#else /* MBEDTLS_USE_PSA_CRYPTO */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    const mbedtls_pk_context *private_key = mbedtls_ssl_own_key(ssl);\n    if (private_key == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"got no server private key\"));\n        return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED;\n    }\n\n    if (!mbedtls_pk_can_do(private_key, MBEDTLS_PK_ECKEY)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"server key not ECDH capable\"));\n        return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;\n    }\n\n    if ((ret = mbedtls_ecdh_get_params(&ssl->handshake->ecdh_ctx,\n                                       mbedtls_pk_ec_ro(*mbedtls_ssl_own_key(ssl)),\n                                       MBEDTLS_ECDH_OURS)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, (\"mbedtls_ecdh_get_params\"), ret);\n        return ret;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||\n          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \\\n    defined(MBEDTLS_SSL_ASYNC_PRIVATE)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_resume_server_key_exchange(mbedtls_ssl_context *ssl,\n                                          size_t *signature_len)\n{\n    /* Append the signature to ssl->out_msg, leaving 2 bytes for the\n     * signature length which will be added in ssl_write_server_key_exchange\n     * after the call to ssl_prepare_server_key_exchange.\n     * ssl_write_server_key_exchange also takes care of incrementing\n     * ssl->out_msglen. */\n    unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2;\n    size_t sig_max_len = (ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN\n                          - sig_start);\n    int ret = ssl->conf->f_async_resume(ssl,\n                                        sig_start, signature_len, sig_max_len);\n    if (ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) {\n        ssl->handshake->async_in_progress = 0;\n        mbedtls_ssl_set_async_operation_data(ssl, NULL);\n    }\n    MBEDTLS_SSL_DEBUG_RET(2, \"ssl_resume_server_key_exchange\", ret);\n    return ret;\n}\n#endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) &&\n          defined(MBEDTLS_SSL_ASYNC_PRIVATE) */\n\n/* Prepare the ServerKeyExchange message, up to and including\n * calculating the signature if any, but excluding formatting the\n * signature and sending the message. */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl,\n                                           size_t *signature_len)\n{\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED)\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)\n    unsigned char *dig_signed = NULL;\n#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */\n\n    (void) ciphersuite_info; /* unused in some configurations */\n#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)\n    (void) signature_len;\n#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n    size_t out_buf_len = ssl->out_buf_len - (size_t) (ssl->out_msg - ssl->out_buf);\n#else\n    size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (size_t) (ssl->out_msg - ssl->out_buf);\n#endif\n#endif\n\n    ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */\n\n    /*\n     *\n     * Part 1: Provide key exchange parameters for chosen ciphersuite.\n     *\n     */\n\n    /*\n     * - ECJPAKE key exchanges\n     */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        unsigned char *out_p = ssl->out_msg + ssl->out_msglen;\n        unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN -\n                               ssl->out_msglen;\n        size_t output_offset = 0;\n        size_t output_len = 0;\n\n        /*\n         * The first 3 bytes are:\n         * [0] MBEDTLS_ECP_TLS_NAMED_CURVE\n         * [1, 2] elliptic curve's TLS ID\n         *\n         * However since we only support secp256r1 for now, we hardcode its\n         * TLS ID here\n         */\n        uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(\n            MBEDTLS_ECP_DP_SECP256R1);\n        if (tls_id == 0) {\n            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n        }\n        *out_p = MBEDTLS_ECP_TLS_NAMED_CURVE;\n        MBEDTLS_PUT_UINT16_BE(tls_id, out_p, 1);\n        output_offset += 3;\n\n        ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx,\n                                              out_p + output_offset,\n                                              end_p - out_p - output_offset, &output_len,\n                                              MBEDTLS_ECJPAKE_ROUND_TWO);\n        if (ret != 0) {\n            psa_destroy_key(ssl->handshake->psa_pake_password);\n            psa_pake_abort(&ssl->handshake->psa_pake_ctx);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_pake_output\", ret);\n            return ret;\n        }\n\n        output_offset += output_len;\n        ssl->out_msglen += output_offset;\n#else\n        size_t len = 0;\n\n        ret = mbedtls_ecjpake_write_round_two(\n            &ssl->handshake->ecjpake_ctx,\n            ssl->out_msg + ssl->out_msglen,\n            MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len,\n            ssl->conf->f_rng, ssl->conf->p_rng);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecjpake_write_round_two\", ret);\n            return ret;\n        }\n\n        ssl->out_msglen += len;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    }\n#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n\n    /*\n     * For (EC)DHE key exchanges with PSK, parameters are prefixed by support\n     * identity hint (RFC 4279, Sec. 3). Until someone needs this feature,\n     * we use empty support identity hints here.\n     **/\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)   || \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||\n        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) {\n        ssl->out_msg[ssl->out_msglen++] = 0x00;\n        ssl->out_msg[ssl->out_msglen++] = 0x00;\n    }\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */\n\n    /*\n     * - DHE key exchanges\n     */\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED)\n    if (mbedtls_ssl_ciphersuite_uses_dhe(ciphersuite_info)) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n        size_t len = 0;\n\n        if (ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"no DH parameters set\"));\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n        }\n\n        /*\n         * Ephemeral DH parameters:\n         *\n         * struct {\n         *     opaque dh_p<1..2^16-1>;\n         *     opaque dh_g<1..2^16-1>;\n         *     opaque dh_Ys<1..2^16-1>;\n         * } ServerDHParams;\n         */\n        if ((ret = mbedtls_dhm_set_group(&ssl->handshake->dhm_ctx,\n                                         &ssl->conf->dhm_P,\n                                         &ssl->conf->dhm_G)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_dhm_set_group\", ret);\n            return ret;\n        }\n\n        if ((ret = mbedtls_dhm_make_params(\n                 &ssl->handshake->dhm_ctx,\n                 (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx),\n                 ssl->out_msg + ssl->out_msglen, &len,\n                 ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_dhm_make_params\", ret);\n            return ret;\n        }\n\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)\n        dig_signed = ssl->out_msg + ssl->out_msglen;\n#endif\n\n        ssl->out_msglen += len;\n\n        MBEDTLS_SSL_DEBUG_MPI(3, \"DHM: X \", &ssl->handshake->dhm_ctx.X);\n        MBEDTLS_SSL_DEBUG_MPI(3, \"DHM: P \", &ssl->handshake->dhm_ctx.P);\n        MBEDTLS_SSL_DEBUG_MPI(3, \"DHM: G \", &ssl->handshake->dhm_ctx.G);\n        MBEDTLS_SSL_DEBUG_MPI(3, \"DHM: GX\", &ssl->handshake->dhm_ctx.GX);\n    }\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED */\n\n    /*\n     * - ECDHE key exchanges\n     */\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)\n    if (mbedtls_ssl_ciphersuite_uses_ecdhe(ciphersuite_info)) {\n        /*\n         * Ephemeral ECDH parameters:\n         *\n         * struct {\n         *     ECParameters curve_params;\n         *     ECPoint      public;\n         * } ServerECDHParams;\n         */\n        uint16_t *curr_tls_id = ssl->handshake->curves_tls_id;\n        const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n        size_t len = 0;\n\n        /* Match our preference list against the offered curves */\n        if ((group_list == NULL) || (curr_tls_id == NULL)) {\n            return MBEDTLS_ERR_SSL_BAD_CONFIG;\n        }\n        for (; *group_list != 0; group_list++) {\n            for (curr_tls_id = ssl->handshake->curves_tls_id;\n                 *curr_tls_id != 0; curr_tls_id++) {\n                if (*curr_tls_id == *group_list) {\n                    goto curve_matching_done;\n                }\n            }\n        }\n\ncurve_matching_done:\n        if (*curr_tls_id == 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"no matching curve for ECDHE\"));\n            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n        }\n\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"ECDHE curve: %s\",\n                                  mbedtls_ssl_get_curve_name_from_tls_id(*curr_tls_id)));\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        psa_status_t status = PSA_ERROR_GENERIC_ERROR;\n        psa_key_attributes_t key_attributes;\n        mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n        uint8_t *p = ssl->out_msg + ssl->out_msglen;\n        const size_t header_size = 4; // curve_type(1), namedcurve(2),\n                                      // data length(1)\n        const size_t data_length_size = 1;\n        psa_key_type_t key_type = PSA_KEY_TYPE_NONE;\n        size_t ec_bits = 0;\n\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Perform PSA-based ECDH computation.\"));\n\n        /* Convert EC's TLS ID to PSA key type. */\n        if (mbedtls_ssl_get_psa_curve_info_from_tls_id(*curr_tls_id,\n                                                       &key_type,\n                                                       &ec_bits) == PSA_ERROR_NOT_SUPPORTED) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"Invalid ecc group parse.\"));\n            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n        }\n        handshake->xxdh_psa_type = key_type;\n        handshake->xxdh_psa_bits = ec_bits;\n\n        key_attributes = psa_key_attributes_init();\n        psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);\n        psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);\n        psa_set_key_type(&key_attributes, handshake->xxdh_psa_type);\n        psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits);\n\n        /*\n         * ECParameters curve_params\n         *\n         * First byte is curve_type, always named_curve\n         */\n        *p++ = MBEDTLS_ECP_TLS_NAMED_CURVE;\n\n        /*\n         * Next two bytes are the namedcurve value\n         */\n        MBEDTLS_PUT_UINT16_BE(*curr_tls_id, p, 0);\n        p += 2;\n\n        /* Generate ECDH private key. */\n        status = psa_generate_key(&key_attributes,\n                                  &handshake->xxdh_psa_privkey);\n        if (status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_generate_key\", ret);\n            return ret;\n        }\n\n        /*\n         * ECPoint  public\n         *\n         * First byte is data length.\n         * It will be filled later. p holds now the data length location.\n         */\n\n        /* Export the public part of the ECDH private key from PSA.\n         * Make one byte space for the length.\n         */\n        unsigned char *own_pubkey = p + data_length_size;\n\n        size_t own_pubkey_max_len = (size_t) (MBEDTLS_SSL_OUT_CONTENT_LEN\n                                              - (own_pubkey - ssl->out_msg));\n\n        status = psa_export_public_key(handshake->xxdh_psa_privkey,\n                                       own_pubkey, own_pubkey_max_len,\n                                       &len);\n        if (status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_export_public_key\", ret);\n            (void) psa_destroy_key(handshake->xxdh_psa_privkey);\n            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;\n            return ret;\n        }\n\n        /* Store the length of the exported public key. */\n        *p = (uint8_t) len;\n\n        /* Determine full message length. */\n        len += header_size;\n#else\n        mbedtls_ecp_group_id curr_grp_id =\n            mbedtls_ssl_get_ecp_group_id_from_tls_id(*curr_tls_id);\n\n        if ((ret = mbedtls_ecdh_setup(&ssl->handshake->ecdh_ctx,\n                                      curr_grp_id)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecp_group_load\", ret);\n            return ret;\n        }\n\n        if ((ret = mbedtls_ecdh_make_params(\n                 &ssl->handshake->ecdh_ctx, &len,\n                 ssl->out_msg + ssl->out_msglen,\n                 MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen,\n                 ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecdh_make_params\", ret);\n            return ret;\n        }\n\n        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,\n                               MBEDTLS_DEBUG_ECDH_Q);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)\n        dig_signed = ssl->out_msg + ssl->out_msglen;\n#endif\n\n        ssl->out_msglen += len;\n    }\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */\n\n    /*\n     *\n     * Part 2: For key exchanges involving the server signing the\n     *         exchange parameters, compute and add the signature here.\n     *\n     */\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)\n    if (mbedtls_ssl_ciphersuite_uses_server_signature(ciphersuite_info)) {\n        if (dig_signed == NULL) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        size_t dig_signed_len = (size_t) (ssl->out_msg + ssl->out_msglen - dig_signed);\n        size_t hashlen = 0;\n        unsigned char hash[MBEDTLS_MD_MAX_SIZE];\n\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n        /*\n         * 2.1: Choose hash algorithm:\n         *      For TLS 1.2, obey signature-hash-algorithm extension\n         *      to choose appropriate hash.\n         */\n\n        mbedtls_pk_type_t sig_alg =\n            mbedtls_ssl_get_ciphersuite_sig_pk_alg(ciphersuite_info);\n\n        unsigned char sig_hash =\n            (unsigned char) mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg(\n                ssl, mbedtls_ssl_sig_from_pk_alg(sig_alg));\n\n        mbedtls_md_type_t md_alg = mbedtls_ssl_md_alg_from_hash(sig_hash);\n\n        /*    For TLS 1.2, obey signature-hash-algorithm extension\n         *    (RFC 5246, Sec. 7.4.1.4.1). */\n        if (sig_alg == MBEDTLS_PK_NONE || md_alg == MBEDTLS_MD_NONE) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n            /* (... because we choose a cipher suite\n             *      only if there is a matching hash.) */\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"pick hash algorithm %u for signing\", (unsigned) md_alg));\n\n        /*\n         * 2.2: Compute the hash to be signed\n         */\n        if (md_alg != MBEDTLS_MD_NONE) {\n            ret = mbedtls_ssl_get_key_exchange_md_tls1_2(ssl, hash, &hashlen,\n                                                         dig_signed,\n                                                         dig_signed_len,\n                                                         md_alg);\n            if (ret != 0) {\n                return ret;\n            }\n        } else {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        MBEDTLS_SSL_DEBUG_BUF(3, \"parameters hash\", hash, hashlen);\n\n        /*\n         * 2.3: Compute and add the signature\n         */\n        /*\n         * We need to specify signature and hash algorithm explicitly through\n         * a prefix to the signature.\n         *\n         * struct {\n         *    HashAlgorithm hash;\n         *    SignatureAlgorithm signature;\n         * } SignatureAndHashAlgorithm;\n         *\n         * struct {\n         *    SignatureAndHashAlgorithm algorithm;\n         *    opaque signature<0..2^16-1>;\n         * } DigitallySigned;\n         *\n         */\n\n        ssl->out_msg[ssl->out_msglen++] = mbedtls_ssl_hash_from_md_alg(md_alg);\n        ssl->out_msg[ssl->out_msglen++] = mbedtls_ssl_sig_from_pk_alg(sig_alg);\n\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)\n        if (ssl->conf->f_async_sign_start != NULL) {\n            ret = ssl->conf->f_async_sign_start(ssl,\n                                                mbedtls_ssl_own_cert(ssl),\n                                                md_alg, hash, hashlen);\n            switch (ret) {\n                case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH:\n                    /* act as if f_async_sign was null */\n                    break;\n                case 0:\n                    ssl->handshake->async_in_progress = 1;\n                    return ssl_resume_server_key_exchange(ssl, signature_len);\n                case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:\n                    ssl->handshake->async_in_progress = 1;\n                    return MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS;\n                default:\n                    MBEDTLS_SSL_DEBUG_RET(1, \"f_async_sign_start\", ret);\n                    return ret;\n            }\n        }\n#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */\n\n        if (mbedtls_ssl_own_key(ssl) == NULL) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"got no private key\"));\n            return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED;\n        }\n\n        /* Append the signature to ssl->out_msg, leaving 2 bytes for the\n         * signature length which will be added in ssl_write_server_key_exchange\n         * after the call to ssl_prepare_server_key_exchange.\n         * ssl_write_server_key_exchange also takes care of incrementing\n         * ssl->out_msglen. */\n        if ((ret = mbedtls_pk_sign(mbedtls_ssl_own_key(ssl),\n                                   md_alg, hash, hashlen,\n                                   ssl->out_msg + ssl->out_msglen + 2,\n                                   out_buf_len - ssl->out_msglen - 2,\n                                   signature_len,\n                                   ssl->conf->f_rng,\n                                   ssl->conf->p_rng)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_pk_sign\", ret);\n            return ret;\n        }\n    }\n#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */\n\n    return 0;\n}\n\n/* Prepare the ServerKeyExchange message and send it. For ciphersuites\n * that do not include a ServerKeyExchange message, do nothing. Either\n * way, if successful, move on to the next step in the SSL state\n * machine. */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_server_key_exchange(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t signature_len = 0;\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED)\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write server key exchange\"));\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED)\n    /* Extract static ECDH parameters and abort if ServerKeyExchange\n     * is not needed. */\n    if (mbedtls_ssl_ciphersuite_no_pfs(ciphersuite_info)) {\n        /* For suites involving ECDH, extract DH parameters\n         * from certificate at this point. */\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED)\n        if (mbedtls_ssl_ciphersuite_uses_ecdh(ciphersuite_info)) {\n            ret = ssl_get_ecdh_params_from_cert(ssl);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"ssl_get_ecdh_params_from_cert\", ret);\n                return ret;\n            }\n        }\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */\n\n        /* Key exchanges not involving ephemeral keys don't use\n         * ServerKeyExchange, so end here. */\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip write server key exchange\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \\\n    defined(MBEDTLS_SSL_ASYNC_PRIVATE)\n    /* If we have already prepared the message and there is an ongoing\n     * signature operation, resume signing. */\n    if (ssl->handshake->async_in_progress != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"resuming signature operation\"));\n        ret = ssl_resume_server_key_exchange(ssl, &signature_len);\n    } else\n#endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) &&\n          defined(MBEDTLS_SSL_ASYNC_PRIVATE) */\n    {\n        /* ServerKeyExchange is needed. Prepare the message. */\n        ret = ssl_prepare_server_key_exchange(ssl, &signature_len);\n    }\n\n    if (ret != 0) {\n        /* If we're starting to write a new message, set ssl->out_msglen\n         * to 0. But if we're resuming after an asynchronous message,\n         * out_msglen is the amount of data written so far and mst be\n         * preserved. */\n        if (ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write server key exchange (pending)\"));\n        } else {\n            ssl->out_msglen = 0;\n        }\n        return ret;\n    }\n\n    /* If there is a signature, write its length.\n     * ssl_prepare_server_key_exchange already wrote the signature\n     * itself at its proper place in the output buffer. */\n#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)\n    if (signature_len != 0) {\n        ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_1(signature_len);\n        ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_0(signature_len);\n\n        MBEDTLS_SSL_DEBUG_BUF(3, \"my signature\",\n                              ssl->out_msg + ssl->out_msglen,\n                              signature_len);\n\n        /* Skip over the already-written signature */\n        ssl->out_msglen += signature_len;\n    }\n#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */\n\n    /* Add header and send. */\n    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;\n    ssl->out_msg[0]  = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE;\n\n    mbedtls_ssl_handshake_increment_state(ssl);\n\n    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_write_handshake_msg\", ret);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write server key exchange\"));\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_server_hello_done(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write server hello done\"));\n\n    ssl->out_msglen  = 4;\n    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;\n    ssl->out_msg[0]  = MBEDTLS_SSL_HS_SERVER_HELLO_DONE;\n\n    mbedtls_ssl_handshake_increment_state(ssl);\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {\n        mbedtls_ssl_send_flight_completed(ssl);\n    }\n#endif\n\n    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_write_handshake_msg\", ret);\n        return ret;\n    }\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n        (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_flight_transmit\", ret);\n        return ret;\n    }\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write server hello done\"));\n\n    return 0;\n}\n\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \\\n    defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_client_dh_public(mbedtls_ssl_context *ssl, unsigned char **p,\n                                      const unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    size_t n;\n\n    /*\n     * Receive G^Y mod P, premaster = (G^Y)^X mod P\n     */\n    if (*p + 2 > end) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client key exchange message\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    n = MBEDTLS_GET_UINT16_BE(*p, 0);\n    *p += 2;\n\n    if (*p + n > end) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client key exchange message\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    if ((ret = mbedtls_dhm_read_public(&ssl->handshake->dhm_ctx, *p, n)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_dhm_read_public\", ret);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    *p += n;\n\n    MBEDTLS_SSL_DEBUG_MPI(3, \"DHM: GY\", &ssl->handshake->dhm_ctx.GY);\n\n    return ret;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) ||                           \\\n    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)\n\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_resume_decrypt_pms(mbedtls_ssl_context *ssl,\n                                  unsigned char *peer_pms,\n                                  size_t *peer_pmslen,\n                                  size_t peer_pmssize)\n{\n    int ret = ssl->conf->f_async_resume(ssl,\n                                        peer_pms, peer_pmslen, peer_pmssize);\n    if (ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) {\n        ssl->handshake->async_in_progress = 0;\n        mbedtls_ssl_set_async_operation_data(ssl, NULL);\n    }\n    MBEDTLS_SSL_DEBUG_RET(2, \"ssl_decrypt_encrypted_pms\", ret);\n    return ret;\n}\n#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_decrypt_encrypted_pms(mbedtls_ssl_context *ssl,\n                                     const unsigned char *p,\n                                     const unsigned char *end,\n                                     unsigned char *peer_pms,\n                                     size_t *peer_pmslen,\n                                     size_t peer_pmssize)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_x509_crt *own_cert = mbedtls_ssl_own_cert(ssl);\n    if (own_cert == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"got no local certificate\"));\n        return MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE;\n    }\n    mbedtls_pk_context *public_key = &own_cert->pk;\n    mbedtls_pk_context *private_key = mbedtls_ssl_own_key(ssl);\n    size_t len = mbedtls_pk_get_len(public_key);\n\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)\n    /* If we have already started decoding the message and there is an ongoing\n     * decryption operation, resume signing. */\n    if (ssl->handshake->async_in_progress != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"resuming decryption operation\"));\n        return ssl_resume_decrypt_pms(ssl,\n                                      peer_pms, peer_pmslen, peer_pmssize);\n    }\n#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */\n\n    /*\n     * Prepare to decrypt the premaster using own private RSA key\n     */\n    if (p + 2 > end) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client key exchange message\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n    if (*p++ != MBEDTLS_BYTE_1(len) ||\n        *p++ != MBEDTLS_BYTE_0(len)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client key exchange message\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    if (p + len != end) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client key exchange message\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /*\n     * Decrypt the premaster secret\n     */\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)\n    if (ssl->conf->f_async_decrypt_start != NULL) {\n        ret = ssl->conf->f_async_decrypt_start(ssl,\n                                               mbedtls_ssl_own_cert(ssl),\n                                               p, len);\n        switch (ret) {\n            case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH:\n                /* act as if f_async_decrypt_start was null */\n                break;\n            case 0:\n                ssl->handshake->async_in_progress = 1;\n                return ssl_resume_decrypt_pms(ssl,\n                                              peer_pms,\n                                              peer_pmslen,\n                                              peer_pmssize);\n            case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:\n                ssl->handshake->async_in_progress = 1;\n                return MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS;\n            default:\n                MBEDTLS_SSL_DEBUG_RET(1, \"f_async_decrypt_start\", ret);\n                return ret;\n        }\n    }\n#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */\n\n    if (!mbedtls_pk_can_do(private_key, MBEDTLS_PK_RSA)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"got no RSA private key\"));\n        return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED;\n    }\n\n    ret = mbedtls_pk_decrypt(private_key, p, len,\n                             peer_pms, peer_pmslen, peer_pmssize,\n                             ssl->conf->f_rng, ssl->conf->p_rng);\n    return ret;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl,\n                                   const unsigned char *p,\n                                   const unsigned char *end,\n                                   size_t pms_offset)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *pms = ssl->handshake->premaster + pms_offset;\n    unsigned char ver[2];\n    unsigned char fake_pms[48], peer_pms[48];\n    size_t peer_pmslen;\n    mbedtls_ct_condition_t diff;\n\n    /* In case of a failure in decryption, the decryption may write less than\n     * 2 bytes of output, but we always read the first two bytes. It doesn't\n     * matter in the end because diff will be nonzero in that case due to\n     * ret being nonzero, and we only care whether diff is 0.\n     * But do initialize peer_pms and peer_pmslen for robustness anyway. This\n     * also makes memory analyzers happy (don't access uninitialized memory,\n     * even if it's an unsigned char). */\n    peer_pms[0] = peer_pms[1] = ~0;\n    peer_pmslen = 0;\n\n    ret = ssl_decrypt_encrypted_pms(ssl, p, end,\n                                    peer_pms,\n                                    &peer_pmslen,\n                                    sizeof(peer_pms));\n\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)\n    if (ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) {\n        return ret;\n    }\n#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */\n\n    mbedtls_ssl_write_version(ver, ssl->conf->transport,\n                              ssl->session_negotiate->tls_version);\n\n    /* Avoid data-dependent branches while checking for invalid\n     * padding, to protect against timing-based Bleichenbacher-type\n     * attacks. */\n    diff = mbedtls_ct_bool(ret);\n    diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pmslen, 48));\n    diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pms[0], ver[0]));\n    diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pms[1], ver[1]));\n\n    /*\n     * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding\n     * must not cause the connection to end immediately; instead, send a\n     * bad_record_mac later in the handshake.\n     * To protect against timing-based variants of the attack, we must\n     * not have any branch that depends on whether the decryption was\n     * successful. In particular, always generate the fake premaster secret,\n     * regardless of whether it will ultimately influence the output or not.\n     */\n    ret = ssl->conf->f_rng(ssl->conf->p_rng, fake_pms, sizeof(fake_pms));\n    if (ret != 0) {\n        /* It's ok to abort on an RNG failure, since this does not reveal\n         * anything about the RSA decryption. */\n        return ret;\n    }\n\n#if defined(MBEDTLS_SSL_DEBUG_ALL)\n    if (diff != MBEDTLS_CT_FALSE) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client key exchange message\"));\n    }\n#endif\n\n    if (sizeof(ssl->handshake->premaster) < pms_offset ||\n        sizeof(ssl->handshake->premaster) - pms_offset < 48) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n    ssl->handshake->pmslen = 48;\n\n    /* Set pms to either the true or the fake PMS, without\n     * data-dependent branches. */\n    mbedtls_ct_memcpy_if(diff, pms, fake_pms, peer_pms, ssl->handshake->pmslen);\n\n    return 0;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */\n\n#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_client_psk_identity(mbedtls_ssl_context *ssl, unsigned char **p,\n                                         const unsigned char *end)\n{\n    int ret = 0;\n    uint16_t n;\n\n    if (ssl_conf_has_psk_or_cb(ssl->conf) == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"got no pre-shared key\"));\n        return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED;\n    }\n\n    /*\n     * Receive client pre-shared key identity name\n     */\n    if (end - *p < 2) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client key exchange message\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    n = MBEDTLS_GET_UINT16_BE(*p, 0);\n    *p += 2;\n\n    if (n == 0 || n > end - *p) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client key exchange message\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    if (ssl->conf->f_psk != NULL) {\n        if (ssl->conf->f_psk(ssl->conf->p_psk, ssl, *p, n) != 0) {\n            ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;\n        }\n    } else {\n        /* Identity is not a big secret since clients send it in the clear,\n         * but treat it carefully anyway, just in case */\n        if (n != ssl->conf->psk_identity_len ||\n            mbedtls_ct_memcmp(ssl->conf->psk_identity, *p, n) != 0) {\n            ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;\n        }\n    }\n\n    if (ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) {\n        MBEDTLS_SSL_DEBUG_BUF(3, \"Unknown PSK identity\", *p, n);\n        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,\n                                       MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY);\n        return MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;\n    }\n\n    *p += n;\n\n    return 0;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;\n    unsigned char *p, *end;\n\n    ciphersuite_info = ssl->handshake->ciphersuite_info;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse client key exchange\"));\n\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \\\n    (defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \\\n    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED))\n    if ((ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||\n         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) &&\n        (ssl->handshake->async_in_progress != 0)) {\n        /* We've already read a record and there is an asynchronous\n         * operation in progress to decrypt it. So skip reading the\n         * record. */\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"will resume decryption of previously-read record\"));\n    } else\n#endif\n    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_read_record\", ret);\n        return ret;\n    }\n\n    p = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl);\n    end = ssl->in_msg + ssl->in_hslen;\n\n    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client key exchange message\"));\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n    if (ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client key exchange message\"));\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA) {\n        if ((ret = ssl_parse_client_dh_public(ssl, &p, end)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, (\"ssl_parse_client_dh_public\"), ret);\n            return ret;\n        }\n\n        if (p != end) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client key exchange\"));\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n\n        if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx,\n                                           ssl->handshake->premaster,\n                                           MBEDTLS_PREMASTER_SIZE,\n                                           &ssl->handshake->pmslen,\n                                           ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_dhm_calc_secret\", ret);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n\n        MBEDTLS_SSL_DEBUG_MPI(3, \"DHM: K \", &ssl->handshake->dhm_ctx.K);\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \\\n    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||\n        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ||\n        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA ||\n        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA) {\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        size_t data_len = (size_t) (*p++);\n        size_t buf_len = (size_t) (end - p);\n        psa_status_t status = PSA_ERROR_GENERIC_ERROR;\n        mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"Read the peer's public key.\"));\n\n        /*\n         * We must have at least two bytes (1 for length, at least 1 for data)\n         */\n        if (buf_len < 2) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"Invalid buffer length: %\" MBEDTLS_PRINTF_SIZET,\n                                      buf_len));\n            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n        }\n\n        if (data_len < 1 || data_len > buf_len) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"Invalid data length: %\" MBEDTLS_PRINTF_SIZET\n                                      \" > %\" MBEDTLS_PRINTF_SIZET,\n                                      data_len, buf_len));\n            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n        }\n\n        /* Store peer's ECDH public key. */\n        if (data_len > sizeof(handshake->xxdh_psa_peerkey)) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"Invalid public key length: %\" MBEDTLS_PRINTF_SIZET\n                                      \" > %\" MBEDTLS_PRINTF_SIZET,\n                                      data_len,\n                                      sizeof(handshake->xxdh_psa_peerkey)));\n            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n        }\n        memcpy(handshake->xxdh_psa_peerkey, p, data_len);\n        handshake->xxdh_psa_peerkey_len = data_len;\n\n        /* Compute ECDH shared secret. */\n        status = psa_raw_key_agreement(\n            PSA_ALG_ECDH, handshake->xxdh_psa_privkey,\n            handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len,\n            handshake->premaster, sizeof(handshake->premaster),\n            &handshake->pmslen);\n        if (status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_raw_key_agreement\", ret);\n            if (handshake->xxdh_psa_privkey_is_external == 0) {\n                (void) psa_destroy_key(handshake->xxdh_psa_privkey);\n            }\n            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;\n            return ret;\n        }\n\n        if (handshake->xxdh_psa_privkey_is_external == 0) {\n            status = psa_destroy_key(handshake->xxdh_psa_privkey);\n\n            if (status != PSA_SUCCESS) {\n                ret = PSA_TO_MBEDTLS_ERR(status);\n                MBEDTLS_SSL_DEBUG_RET(1, \"psa_destroy_key\", ret);\n                return ret;\n            }\n        }\n        handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;\n#else\n        if ((ret = mbedtls_ecdh_read_public(&ssl->handshake->ecdh_ctx,\n                                            p, (size_t) (end - p))) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecdh_read_public\", ret);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n\n        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,\n                               MBEDTLS_DEBUG_ECDH_QP);\n\n        if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx,\n                                            &ssl->handshake->pmslen,\n                                            ssl->handshake->premaster,\n                                            MBEDTLS_MPI_MAX_SIZE,\n                                            ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecdh_calc_secret\", ret);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n\n        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,\n                               MBEDTLS_DEBUG_ECDH_Z);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||\n          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK) {\n        if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, (\"ssl_parse_client_psk_identity\"), ret);\n            return ret;\n        }\n\n        if (p != end) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client key exchange\"));\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n\n#if !defined(MBEDTLS_USE_PSA_CRYPTO)\n        if ((ret = mbedtls_ssl_psk_derive_premaster(ssl,\n                                                    (mbedtls_key_exchange_type_t) ciphersuite_info->\n                                                    key_exchange)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_psk_derive_premaster\", ret);\n            return ret;\n        }\n#endif /* !MBEDTLS_USE_PSA_CRYPTO */\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)\n        if (ssl->handshake->async_in_progress != 0) {\n            /* There is an asynchronous operation in progress to\n             * decrypt the encrypted premaster secret, so skip\n             * directly to resuming this operation. */\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"PSK identity already parsed\"));\n            /* Update p to skip the PSK identity. ssl_parse_encrypted_pms\n             * won't actually use it, but maintain p anyway for robustness. */\n            p += ssl->conf->psk_identity_len + 2;\n        } else\n#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */\n        if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, (\"ssl_parse_client_psk_identity\"), ret);\n            return ret;\n        }\n\n        if ((ret = ssl_parse_encrypted_pms(ssl, p, end, 2)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, (\"ssl_parse_encrypted_pms\"), ret);\n            return ret;\n        }\n\n#if !defined(MBEDTLS_USE_PSA_CRYPTO)\n        if ((ret = mbedtls_ssl_psk_derive_premaster(ssl,\n                                                    (mbedtls_key_exchange_type_t) ciphersuite_info->\n                                                    key_exchange)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_psk_derive_premaster\", ret);\n            return ret;\n        }\n#endif /* !MBEDTLS_USE_PSA_CRYPTO */\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK) {\n        if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, (\"ssl_parse_client_psk_identity\"), ret);\n            return ret;\n        }\n        if ((ret = ssl_parse_client_dh_public(ssl, &p, end)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, (\"ssl_parse_client_dh_public\"), ret);\n            return ret;\n        }\n\n        if (p != end) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client key exchange\"));\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        unsigned char *pms = ssl->handshake->premaster;\n        unsigned char *pms_end = pms + sizeof(ssl->handshake->premaster);\n        size_t pms_len;\n\n        /* Write length only when we know the actual value */\n        if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx,\n                                           pms + 2, pms_end - (pms + 2), &pms_len,\n                                           ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_dhm_calc_secret\", ret);\n            return ret;\n        }\n        MBEDTLS_PUT_UINT16_BE(pms_len, pms, 0);\n        pms += 2 + pms_len;\n\n        MBEDTLS_SSL_DEBUG_MPI(3, \"DHM: K \", &ssl->handshake->dhm_ctx.K);\n#else\n        if ((ret = mbedtls_ssl_psk_derive_premaster(ssl,\n                                                    (mbedtls_key_exchange_type_t) ciphersuite_info->\n                                                    key_exchange)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_psk_derive_premaster\", ret);\n            return ret;\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) {\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n        psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED;\n        size_t ecpoint_len;\n\n        mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n        if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, (\"ssl_parse_client_psk_identity\"), ret);\n            psa_destroy_key(handshake->xxdh_psa_privkey);\n            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;\n            return ret;\n        }\n\n        /* Keep a copy of the peer's public key */\n        if (p >= end) {\n            psa_destroy_key(handshake->xxdh_psa_privkey);\n            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n\n        ecpoint_len = *(p++);\n        if ((size_t) (end - p) < ecpoint_len) {\n            psa_destroy_key(handshake->xxdh_psa_privkey);\n            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n\n        /* When FFDH is enabled, the array handshake->xxdh_psa_peer_key size takes into account\n           the sizes of the FFDH keys which are at least 2048 bits.\n           The size of the array is thus greater than 256 bytes which is greater than any\n           possible value of ecpoint_len (type uint8_t) and the check below can be skipped.*/\n#if !defined(PSA_WANT_ALG_FFDH)\n        if (ecpoint_len > sizeof(handshake->xxdh_psa_peerkey)) {\n            psa_destroy_key(handshake->xxdh_psa_privkey);\n            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;\n            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n        }\n#else\n        MBEDTLS_STATIC_ASSERT(sizeof(handshake->xxdh_psa_peerkey) >= UINT8_MAX,\n                              \"peer key buffer too small\");\n#endif\n\n        memcpy(handshake->xxdh_psa_peerkey, p, ecpoint_len);\n        handshake->xxdh_psa_peerkey_len = ecpoint_len;\n        p += ecpoint_len;\n\n        /* As RFC 5489 section 2, the premaster secret is formed as follows:\n         * - a uint16 containing the length (in octets) of the ECDH computation\n         * - the octet string produced by the ECDH computation\n         * - a uint16 containing the length (in octets) of the PSK\n         * - the PSK itself\n         */\n        unsigned char *psm = ssl->handshake->premaster;\n        const unsigned char * const psm_end =\n            psm + sizeof(ssl->handshake->premaster);\n        /* uint16 to store length (in octets) of the ECDH computation */\n        const size_t zlen_size = 2;\n        size_t zlen = 0;\n\n        /* Compute ECDH shared secret. */\n        status = psa_raw_key_agreement(PSA_ALG_ECDH,\n                                       handshake->xxdh_psa_privkey,\n                                       handshake->xxdh_psa_peerkey,\n                                       handshake->xxdh_psa_peerkey_len,\n                                       psm + zlen_size,\n                                       psm_end - (psm + zlen_size),\n                                       &zlen);\n\n        destruction_status = psa_destroy_key(handshake->xxdh_psa_privkey);\n        handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;\n\n        if (status != PSA_SUCCESS) {\n            return PSA_TO_MBEDTLS_ERR(status);\n        } else if (destruction_status != PSA_SUCCESS) {\n            return PSA_TO_MBEDTLS_ERR(destruction_status);\n        }\n\n        /* Write the ECDH computation length before the ECDH computation */\n        MBEDTLS_PUT_UINT16_BE(zlen, psm, 0);\n        psm += zlen_size + zlen;\n\n#else /* MBEDTLS_USE_PSA_CRYPTO */\n        if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, (\"ssl_parse_client_psk_identity\"), ret);\n            return ret;\n        }\n\n        if ((ret = mbedtls_ecdh_read_public(&ssl->handshake->ecdh_ctx,\n                                            p, (size_t) (end - p))) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecdh_read_public\", ret);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n\n        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,\n                               MBEDTLS_DEBUG_ECDH_QP);\n\n        if ((ret = mbedtls_ssl_psk_derive_premaster(ssl,\n                                                    (mbedtls_key_exchange_type_t) ciphersuite_info->\n                                                    key_exchange)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_psk_derive_premaster\", ret);\n            return ret;\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) {\n        if ((ret = ssl_parse_encrypted_pms(ssl, p, end, 0)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, (\"ssl_parse_parse_encrypted_pms_secret\"), ret);\n            return ret;\n        }\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        if ((ret = mbedtls_psa_ecjpake_read_round(\n                 &ssl->handshake->psa_pake_ctx, p, (size_t) (end - p),\n                 MBEDTLS_ECJPAKE_ROUND_TWO)) != 0) {\n            psa_destroy_key(ssl->handshake->psa_pake_password);\n            psa_pake_abort(&ssl->handshake->psa_pake_ctx);\n\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_pake_input round two\", ret);\n            return ret;\n        }\n#else\n        ret = mbedtls_ecjpake_read_round_two(&ssl->handshake->ecjpake_ctx,\n                                             p, (size_t) (end - p));\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecjpake_read_round_two\", ret);\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        ret = mbedtls_ecjpake_derive_secret(&ssl->handshake->ecjpake_ctx,\n                                            ssl->handshake->premaster, 32, &ssl->handshake->pmslen,\n                                            ssl->conf->f_rng, ssl->conf->p_rng);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ecjpake_derive_secret\", ret);\n            return ret;\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    } else\n#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n    {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_derive_keys\", ret);\n        return ret;\n    }\n\n    mbedtls_ssl_handshake_increment_state(ssl);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse client key exchange\"));\n\n    return 0;\n}\n\n#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl)\n{\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse certificate verify\"));\n\n    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip parse certificate verify\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n}\n#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    size_t i, sig_len;\n    unsigned char hash[48];\n    unsigned char *hash_start = hash;\n    size_t hashlen;\n    mbedtls_pk_type_t pk_alg;\n    mbedtls_md_type_t md_alg;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n    mbedtls_pk_context *peer_pk;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse certificate verify\"));\n\n    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip parse certificate verify\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    if (ssl->session_negotiate->peer_cert == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip parse certificate verify\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n    if (ssl->session_negotiate->peer_cert_digest == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip parse certificate verify\"));\n        mbedtls_ssl_handshake_increment_state(ssl);\n        return 0;\n    }\n#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n\n    /* Read the message without adding it to the checksum */\n    ret = mbedtls_ssl_read_record(ssl, 0 /* no checksum update */);\n    if (0 != ret) {\n        MBEDTLS_SSL_DEBUG_RET(1, (\"mbedtls_ssl_read_record\"), ret);\n        return ret;\n    }\n\n    mbedtls_ssl_handshake_increment_state(ssl);\n\n    /* Process the message contents */\n    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ||\n        ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate verify message\"));\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n    i = mbedtls_ssl_hs_hdr_len(ssl);\n\n#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    peer_pk = &ssl->handshake->peer_pubkey;\n#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n    if (ssl->session_negotiate->peer_cert == NULL) {\n        /* Should never happen */\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n    peer_pk = &ssl->session_negotiate->peer_cert->pk;\n#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n\n    /*\n     *  struct {\n     *     SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only\n     *     opaque signature<0..2^16-1>;\n     *  } DigitallySigned;\n     */\n    if (i + 2 > ssl->in_hslen) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate verify message\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /*\n     * Hash\n     */\n    md_alg = mbedtls_ssl_md_alg_from_hash(ssl->in_msg[i]);\n\n    if (md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md(ssl, ssl->in_msg[i])) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"peer not adhering to requested sig_alg\"\n                                  \" for verify message\"));\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n#if !defined(MBEDTLS_MD_SHA1)\n    if (MBEDTLS_MD_SHA1 == md_alg) {\n        hash_start += 16;\n    }\n#endif\n\n    /* Info from md_alg will be used instead */\n    hashlen = 0;\n\n    i++;\n\n    /*\n     * Signature\n     */\n    if ((pk_alg = mbedtls_ssl_pk_alg_from_sig(ssl->in_msg[i]))\n        == MBEDTLS_PK_NONE) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"peer not adhering to requested sig_alg\"\n                                  \" for verify message\"));\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    /*\n     * Check the certificate's key type matches the signature alg\n     */\n    if (!mbedtls_pk_can_do(peer_pk, pk_alg)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"sig_alg doesn't match cert key\"));\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    i++;\n\n    if (i + 2 > ssl->in_hslen) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate verify message\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    sig_len = MBEDTLS_GET_UINT16_BE(ssl->in_msg, i);\n    i += 2;\n\n    if (i + sig_len != ssl->in_hslen) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate verify message\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /* Calculate hash and verify signature */\n    {\n        size_t dummy_hlen;\n        ret = ssl->handshake->calc_verify(ssl, hash, &dummy_hlen);\n        if (0 != ret) {\n            MBEDTLS_SSL_DEBUG_RET(1, (\"calc_verify\"), ret);\n            return ret;\n        }\n    }\n\n    if ((ret = mbedtls_pk_verify(peer_pk,\n                                 md_alg, hash_start, hashlen,\n                                 ssl->in_msg + i, sig_len)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_pk_verify\", ret);\n        return ret;\n    }\n\n    ret = mbedtls_ssl_update_handshake_status(ssl);\n    if (0 != ret) {\n        MBEDTLS_SSL_DEBUG_RET(1, (\"mbedtls_ssl_update_handshake_status\"), ret);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse certificate verify\"));\n\n    return ret;\n}\n#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_write_new_session_ticket(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t tlen;\n    uint32_t lifetime;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write new session ticket\"));\n\n    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;\n    ssl->out_msg[0]  = MBEDTLS_SSL_HS_NEW_SESSION_TICKET;\n\n    /*\n     * struct {\n     *     uint32 ticket_lifetime_hint;\n     *     opaque ticket<0..2^16-1>;\n     * } NewSessionTicket;\n     *\n     * 4  .  7   ticket_lifetime_hint (0 = unspecified)\n     * 8  .  9   ticket_len (n)\n     * 10 .  9+n ticket content\n     */\n\n#if defined(MBEDTLS_HAVE_TIME)\n    ssl->session_negotiate->ticket_creation_time = mbedtls_ms_time();\n#endif\n    if ((ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket,\n                                         ssl->session_negotiate,\n                                         ssl->out_msg + 10,\n                                         ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN,\n                                         &tlen, &lifetime)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_ticket_write\", ret);\n        tlen = 0;\n    }\n\n    MBEDTLS_PUT_UINT32_BE(lifetime, ssl->out_msg, 4);\n    MBEDTLS_PUT_UINT16_BE(tlen, ssl->out_msg, 8);\n    ssl->out_msglen = 10 + tlen;\n\n    /*\n     * Morally equivalent to updating ssl->state, but NewSessionTicket and\n     * ChangeCipherSpec share the same state.\n     */\n    ssl->handshake->new_session_ticket = 0;\n\n    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_write_handshake_msg\", ret);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write new session ticket\"));\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n/*\n * SSL handshake -- server side -- single step\n */\nint mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl)\n{\n    int ret = 0;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"server state: %d\", ssl->state));\n\n    switch (ssl->state) {\n        case MBEDTLS_SSL_HELLO_REQUEST:\n            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);\n            break;\n\n        /*\n         *  <==   ClientHello\n         */\n        case MBEDTLS_SSL_CLIENT_HELLO:\n            ret = ssl_parse_client_hello(ssl);\n            break;\n\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n        case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT:\n            return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED;\n#endif\n\n        /*\n         *  ==>   ServerHello\n         *        Certificate\n         *      ( ServerKeyExchange  )\n         *      ( CertificateRequest )\n         *        ServerHelloDone\n         */\n        case MBEDTLS_SSL_SERVER_HELLO:\n            ret = ssl_write_server_hello(ssl);\n            break;\n\n        case MBEDTLS_SSL_SERVER_CERTIFICATE:\n            ret = mbedtls_ssl_write_certificate(ssl);\n            break;\n\n        case MBEDTLS_SSL_SERVER_KEY_EXCHANGE:\n            ret = ssl_write_server_key_exchange(ssl);\n            break;\n\n        case MBEDTLS_SSL_CERTIFICATE_REQUEST:\n            ret = ssl_write_certificate_request(ssl);\n            break;\n\n        case MBEDTLS_SSL_SERVER_HELLO_DONE:\n            ret = ssl_write_server_hello_done(ssl);\n            break;\n\n        /*\n         *  <== ( Certificate/Alert  )\n         *        ClientKeyExchange\n         *      ( CertificateVerify  )\n         *        ChangeCipherSpec\n         *        Finished\n         */\n        case MBEDTLS_SSL_CLIENT_CERTIFICATE:\n            ret = mbedtls_ssl_parse_certificate(ssl);\n            break;\n\n        case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:\n            ret = ssl_parse_client_key_exchange(ssl);\n            break;\n\n        case MBEDTLS_SSL_CERTIFICATE_VERIFY:\n            ret = ssl_parse_certificate_verify(ssl);\n            break;\n\n        case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC:\n            ret = mbedtls_ssl_parse_change_cipher_spec(ssl);\n            break;\n\n        case MBEDTLS_SSL_CLIENT_FINISHED:\n            ret = mbedtls_ssl_parse_finished(ssl);\n            break;\n\n        /*\n         *  ==> ( NewSessionTicket )\n         *        ChangeCipherSpec\n         *        Finished\n         */\n        case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC:\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n            if (ssl->handshake->new_session_ticket != 0) {\n                ret = ssl_write_new_session_ticket(ssl);\n            } else\n#endif\n            ret = mbedtls_ssl_write_change_cipher_spec(ssl);\n            break;\n\n        case MBEDTLS_SSL_SERVER_FINISHED:\n            ret = mbedtls_ssl_write_finished(ssl);\n            break;\n\n        case MBEDTLS_SSL_FLUSH_BUFFERS:\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"handshake: done\"));\n            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP);\n            break;\n\n        case MBEDTLS_SSL_HANDSHAKE_WRAPUP:\n            mbedtls_ssl_handshake_wrapup(ssl);\n            break;\n\n        default:\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"invalid state %d\", ssl->state));\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    return ret;\n}\n\nvoid mbedtls_ssl_conf_preference_order(mbedtls_ssl_config *conf, int order)\n{\n    conf->respect_cli_pref = order;\n}\n\n#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_TLS1_2 */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_tls13_client.c",
    "content": "/*\n *  TLS 1.3 client-side functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3)\n\n#include <string.h>\n\n#include \"debug_internal.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/platform.h\"\n\n#include \"ssl_misc.h\"\n#include \"ssl_client.h\"\n#include \"ssl_tls13_keys.h\"\n#include \"ssl_debug_helpers.h\"\n#include \"mbedtls/psa_util.h\"\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)\n/* Define a local translating function to save code size by not using too many\n * arguments in each translating place. */\nstatic int local_err_translation(psa_status_t status)\n{\n    return psa_status_to_mbedtls(status, psa_to_ssl_errors,\n                                 ARRAY_LENGTH(psa_to_ssl_errors),\n                                 psa_generic_status_to_mbedtls);\n}\n#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)\n#endif\n\n/* Write extensions */\n\n/*\n * ssl_tls13_write_supported_versions_ext():\n *\n * struct {\n *      ProtocolVersion versions<2..254>;\n * } SupportedVersions;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_supported_versions_ext(mbedtls_ssl_context *ssl,\n                                                  unsigned char *buf,\n                                                  unsigned char *end,\n                                                  size_t *out_len)\n{\n    unsigned char *p = buf;\n    unsigned char versions_len = (ssl->handshake->min_tls_version <=\n                                  MBEDTLS_SSL_VERSION_TLS1_2) ? 4 : 2;\n\n    *out_len = 0;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"client hello, adding supported versions extension\"));\n\n    /* Check if we have space to write the extension:\n     * - extension_type         (2 bytes)\n     * - extension_data_length  (2 bytes)\n     * - versions_length        (1 byte )\n     * - versions               (2 or 4 bytes)\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 5 + versions_len);\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, p, 0);\n    MBEDTLS_PUT_UINT16_BE(versions_len + 1, p, 2);\n    p += 4;\n\n    /* Length of versions */\n    *p++ = versions_len;\n\n    /* Write values of supported versions.\n     * They are defined by the configuration.\n     * Currently, we advertise only TLS 1.3 or both TLS 1.3 and TLS 1.2.\n     */\n    mbedtls_ssl_write_version(p, MBEDTLS_SSL_TRANSPORT_STREAM,\n                              MBEDTLS_SSL_VERSION_TLS1_3);\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"supported version: [3:4]\"));\n\n\n    if (ssl->handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) {\n        mbedtls_ssl_write_version(p + 2, MBEDTLS_SSL_TRANSPORT_STREAM,\n                                  MBEDTLS_SSL_VERSION_TLS1_2);\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"supported version: [3:3]\"));\n    }\n\n    *out_len = 5 + versions_len;\n\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(\n        ssl, MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS);\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_supported_versions_ext(mbedtls_ssl_context *ssl,\n                                                  const unsigned char *buf,\n                                                  const unsigned char *end)\n{\n    ((void) ssl);\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 2);\n    if (mbedtls_ssl_read_version(buf, ssl->conf->transport) !=\n        MBEDTLS_SSL_VERSION_TLS1_3) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"unexpected version\"));\n\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    if (&buf[2] != end) {\n        MBEDTLS_SSL_DEBUG_MSG(\n            1, (\"supported_versions ext data length incorrect\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,\n                                     MBEDTLS_ERR_SSL_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_ALPN)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_alpn_ext(mbedtls_ssl_context *ssl,\n                                    const unsigned char *buf, size_t len)\n{\n    const unsigned char *p = buf;\n    const unsigned char *end = buf + len;\n    size_t protocol_name_list_len, protocol_name_len;\n    const unsigned char *protocol_name_list_end;\n\n    /* If we didn't send it, the server shouldn't send it */\n    if (ssl->conf->alpn_list == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    /*\n     * opaque ProtocolName<1..2^8-1>;\n     *\n     * struct {\n     *     ProtocolName protocol_name_list<2..2^16-1>\n     * } ProtocolNameList;\n     *\n     * the \"ProtocolNameList\" MUST contain exactly one \"ProtocolName\"\n     */\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    protocol_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, protocol_name_list_len);\n    protocol_name_list_end = p + protocol_name_list_len;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, 1);\n    protocol_name_len = *p++;\n\n    /* Check that the server chosen protocol was in our list and save it */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, protocol_name_len);\n    for (const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++) {\n        if (protocol_name_len == strlen(*alpn) &&\n            memcmp(p, *alpn, protocol_name_len) == 0) {\n            ssl->alpn_chosen = *alpn;\n            return 0;\n        }\n    }\n\n    return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n}\n#endif /* MBEDTLS_SSL_ALPN */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_reset_key_share(mbedtls_ssl_context *ssl)\n{\n    uint16_t group_id = ssl->handshake->offered_group_id;\n\n    if (group_id == 0) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)\n    if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) ||\n        mbedtls_ssl_tls13_named_group_is_ffdh(group_id)) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n        /* Destroy generated private key. */\n        status = psa_destroy_key(ssl->handshake->xxdh_psa_privkey);\n        if (status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            MBEDTLS_SSL_DEBUG_RET(1, \"psa_destroy_key\", ret);\n            return ret;\n        }\n\n        ssl->handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;\n        return 0;\n    } else\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */\n    if (0 /* other KEMs? */) {\n        /* Do something */\n    }\n\n    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n}\n\n/*\n * Functions for writing key_share extension.\n */\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_get_default_group_id(mbedtls_ssl_context *ssl,\n                                          uint16_t *group_id)\n{\n    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n\n\n#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)\n    const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);\n    /* Pick first available ECDHE group compatible with TLS 1.3 */\n    if (group_list == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_CONFIG;\n    }\n\n    for (; *group_list != 0; group_list++) {\n#if defined(PSA_WANT_ALG_ECDH)\n        if ((mbedtls_ssl_get_psa_curve_info_from_tls_id(\n                 *group_list, NULL, NULL) == PSA_SUCCESS) &&\n            mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) {\n            *group_id = *group_list;\n            return 0;\n        }\n#endif\n#if defined(PSA_WANT_ALG_FFDH)\n        if (mbedtls_ssl_tls13_named_group_is_ffdh(*group_list)) {\n            *group_id = *group_list;\n            return 0;\n        }\n#endif\n    }\n#else\n    ((void) ssl);\n    ((void) group_id);\n#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */\n\n    return ret;\n}\n\n/*\n * ssl_tls13_write_key_share_ext\n *\n * Structure of key_share extension in ClientHello:\n *\n *  struct {\n *          NamedGroup group;\n *          opaque key_exchange<1..2^16-1>;\n *      } KeyShareEntry;\n *  struct {\n *          KeyShareEntry client_shares<0..2^16-1>;\n *      } KeyShareClientHello;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl,\n                                         unsigned char *buf,\n                                         unsigned char *end,\n                                         size_t *out_len)\n{\n    unsigned char *p = buf;\n    unsigned char *client_shares; /* Start of client_shares */\n    size_t client_shares_len;     /* Length of client_shares */\n    uint16_t group_id;\n    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n\n    *out_len = 0;\n\n    /* Check if we have space for header and length fields:\n     * - extension_type         (2 bytes)\n     * - extension_data_length  (2 bytes)\n     * - client_shares_length   (2 bytes)\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);\n    p += 6;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"client hello: adding key share extension\"));\n\n    /* HRR could already have requested something else. */\n    group_id = ssl->handshake->offered_group_id;\n    if (!mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) &&\n        !mbedtls_ssl_tls13_named_group_is_ffdh(group_id)) {\n        MBEDTLS_SSL_PROC_CHK(ssl_tls13_get_default_group_id(ssl,\n                                                            &group_id));\n    }\n\n    /*\n     * Dispatch to type-specific key generation function.\n     *\n     * So far, we're only supporting ECDHE. With the introduction\n     * of PQC KEMs, we'll want to have multiple branches, one per\n     * type of KEM, and dispatch to the corresponding crypto. And\n     * only one key share entry is allowed.\n     */\n    client_shares = p;\n#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)\n    if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) ||\n        mbedtls_ssl_tls13_named_group_is_ffdh(group_id)) {\n        /* Pointer to group */\n        unsigned char *group = p;\n        /* Length of key_exchange */\n        size_t key_exchange_len = 0;\n\n        /* Check there is space for header of KeyShareEntry\n         * - group                  (2 bytes)\n         * - key_exchange_length    (2 bytes)\n         */\n        MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4);\n        p += 4;\n        ret = mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange(\n            ssl, group_id, p, end, &key_exchange_len);\n        p += key_exchange_len;\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"client hello: failed generating xxdh key exchange\"));\n            return ret;\n        }\n\n        /* Write group */\n        MBEDTLS_PUT_UINT16_BE(group_id, group, 0);\n        /* Write key_exchange_length */\n        MBEDTLS_PUT_UINT16_BE(key_exchange_len, group, 2);\n    } else\n#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */\n    if (0 /* other KEMs? */) {\n        /* Do something */\n    } else {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    /* Length of client_shares */\n    client_shares_len = p - client_shares;\n    if (client_shares_len == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"No key share defined.\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n    /* Write extension_type */\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0);\n    /* Write extension_data_length */\n    MBEDTLS_PUT_UINT16_BE(client_shares_len + 2, buf, 2);\n    /* Write client_shares_length */\n    MBEDTLS_PUT_UINT16_BE(client_shares_len, buf, 4);\n\n    /* Update offered_group_id field */\n    ssl->handshake->offered_group_id = group_id;\n\n    /* Output the total length of key_share extension. */\n    *out_len = p - buf;\n\n    MBEDTLS_SSL_DEBUG_BUF(\n        3, \"client hello, key_share extension\", buf, *out_len);\n\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE);\n\ncleanup:\n\n    return ret;\n}\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */\n\n/*\n * ssl_tls13_parse_hrr_key_share_ext()\n *      Parse key_share extension in Hello Retry Request\n *\n * struct {\n *        NamedGroup selected_group;\n * } KeyShareHelloRetryRequest;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_hrr_key_share_ext(mbedtls_ssl_context *ssl,\n                                             const unsigned char *buf,\n                                             const unsigned char *end)\n{\n#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)\n    const unsigned char *p = buf;\n    int selected_group;\n    int found = 0;\n\n    const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);\n    if (group_list == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_CONFIG;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"key_share extension\", p, end - buf);\n\n    /* Read selected_group */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    selected_group = MBEDTLS_GET_UINT16_BE(p, 0);\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"selected_group ( %d )\", selected_group));\n\n    /* Upon receipt of this extension in a HelloRetryRequest, the client\n     * MUST first verify that the selected_group field corresponds to a\n     * group which was provided in the \"supported_groups\" extension in the\n     * original ClientHello.\n     * The supported_group was based on the info in ssl->conf->group_list.\n     *\n     * If the server provided a key share that was not sent in the ClientHello\n     * then the client MUST abort the handshake with an \"illegal_parameter\" alert.\n     */\n    for (; *group_list != 0; group_list++) {\n#if defined(PSA_WANT_ALG_ECDH)\n        if (mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) {\n            if ((mbedtls_ssl_get_psa_curve_info_from_tls_id(\n                     *group_list, NULL, NULL) == PSA_ERROR_NOT_SUPPORTED) ||\n                *group_list != selected_group) {\n                found = 1;\n                break;\n            }\n        }\n#endif /* PSA_WANT_ALG_ECDH */\n#if defined(PSA_WANT_ALG_FFDH)\n        if (mbedtls_ssl_tls13_named_group_is_ffdh(*group_list)) {\n            found = 1;\n            break;\n        }\n#endif /* PSA_WANT_ALG_FFDH */\n    }\n\n    /* Client MUST verify that the selected_group field does not\n     * correspond to a group which was provided in the \"key_share\"\n     * extension in the original ClientHello. If the server sent an\n     * HRR message with a key share already provided in the\n     * ClientHello then the client MUST abort the handshake with\n     * an \"illegal_parameter\" alert.\n     */\n    if (found == 0 || selected_group == ssl->handshake->offered_group_id) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Invalid key share in HRR\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(\n            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n            MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    /* Remember server's preference for next ClientHello */\n    ssl->handshake->offered_group_id = selected_group;\n\n    return 0;\n#else /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */\n    (void) ssl;\n    (void) buf;\n    (void) end;\n    return MBEDTLS_ERR_SSL_BAD_CONFIG;\n#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */\n}\n\n/*\n * ssl_tls13_parse_key_share_ext()\n *      Parse key_share extension in Server Hello\n *\n * struct {\n *        KeyShareEntry server_share;\n * } KeyShareServerHello;\n * struct {\n *        NamedGroup group;\n *        opaque key_exchange<1..2^16-1>;\n * } KeyShareEntry;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_key_share_ext(mbedtls_ssl_context *ssl,\n                                         const unsigned char *buf,\n                                         const unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const unsigned char *p = buf;\n    uint16_t group, offered_group;\n\n    /* ...\n     * NamedGroup group; (2 bytes)\n     * ...\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    group = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n\n    /* Check that the chosen group matches the one we offered. */\n    offered_group = ssl->handshake->offered_group_id;\n    if (offered_group != group) {\n        MBEDTLS_SSL_DEBUG_MSG(\n            1, (\"Invalid server key share, our group %u, their group %u\",\n                (unsigned) offered_group, (unsigned) group));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,\n                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)\n    if (mbedtls_ssl_tls13_named_group_is_ecdhe(group) ||\n        mbedtls_ssl_tls13_named_group_is_ffdh(group)) {\n        MBEDTLS_SSL_DEBUG_MSG(2,\n                              (\"DHE group name: %s\", mbedtls_ssl_named_group_to_str(group)));\n        ret = mbedtls_ssl_tls13_read_public_xxdhe_share(ssl, p, end - p);\n        if (ret != 0) {\n            return ret;\n        }\n    } else\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */\n    if (0 /* other KEMs? */) {\n        /* Do something */\n    } else {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    return ret;\n}\n\n/*\n * ssl_tls13_parse_cookie_ext()\n *      Parse cookie extension in Hello Retry Request\n *\n * struct {\n *        opaque cookie<1..2^16-1>;\n * } Cookie;\n *\n * When sending a HelloRetryRequest, the server MAY provide a \"cookie\"\n * extension to the client (this is an exception to the usual rule that\n * the only extensions that may be sent are those that appear in the\n * ClientHello).  When sending the new ClientHello, the client MUST copy\n * the contents of the extension received in the HelloRetryRequest into\n * a \"cookie\" extension in the new ClientHello.  Clients MUST NOT use\n * cookies in their initial ClientHello in subsequent connections.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_cookie_ext(mbedtls_ssl_context *ssl,\n                                      const unsigned char *buf,\n                                      const unsigned char *end)\n{\n    uint16_t cookie_len;\n    const unsigned char *p = buf;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n    /* Retrieve length field of cookie */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    cookie_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cookie_len);\n    MBEDTLS_SSL_DEBUG_BUF(3, \"cookie extension\", p, cookie_len);\n\n    mbedtls_free(handshake->cookie);\n    handshake->cookie_len = 0;\n    handshake->cookie = mbedtls_calloc(1, cookie_len);\n    if (handshake->cookie == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"alloc failed ( %ud bytes )\",\n                               cookie_len));\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n    memcpy(handshake->cookie, p, cookie_len);\n    handshake->cookie_len = cookie_len;\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_cookie_ext(mbedtls_ssl_context *ssl,\n                                      unsigned char *buf,\n                                      unsigned char *end,\n                                      size_t *out_len)\n{\n    unsigned char *p = buf;\n    *out_len = 0;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n    if (handshake->cookie == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"no cookie to send; skip extension\"));\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"client hello, cookie\",\n                          handshake->cookie,\n                          handshake->cookie_len);\n\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, handshake->cookie_len + 6);\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"client hello, adding cookie extension\"));\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_COOKIE, p, 0);\n    MBEDTLS_PUT_UINT16_BE(handshake->cookie_len + 2, p, 2);\n    MBEDTLS_PUT_UINT16_BE(handshake->cookie_len, p, 4);\n    p += 6;\n\n    /* Cookie */\n    memcpy(p, handshake->cookie, handshake->cookie_len);\n\n    *out_len = handshake->cookie_len + 6;\n\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_COOKIE);\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n/*\n * ssl_tls13_write_psk_key_exchange_modes_ext() structure:\n *\n * enum { psk_ke( 0 ), psk_dhe_ke( 1 ), ( 255 ) } PskKeyExchangeMode;\n *\n * struct {\n *     PskKeyExchangeMode ke_modes<1..255>;\n * } PskKeyExchangeModes;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_psk_key_exchange_modes_ext(mbedtls_ssl_context *ssl,\n                                                      unsigned char *buf,\n                                                      unsigned char *end,\n                                                      size_t *out_len)\n{\n    unsigned char *p = buf;\n    int ke_modes_len = 0;\n\n    ((void) ke_modes_len);\n    *out_len = 0;\n\n    /* Skip writing extension if no PSK key exchange mode\n     * is enabled in the config.\n     */\n    if (!mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl)) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"skip psk_key_exchange_modes extension\"));\n        return 0;\n    }\n\n    /* Require 7 bytes of data, otherwise fail,\n     * even if extension might be shorter.\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 7);\n    MBEDTLS_SSL_DEBUG_MSG(\n        3, (\"client hello, adding psk_key_exchange_modes extension\"));\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES, p, 0);\n\n    /* Skip extension length (2 bytes) and\n     * ke_modes length (1 byte) for now.\n     */\n    p += 5;\n\n    if (mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(ssl)) {\n        *p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE;\n        ke_modes_len++;\n\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"Adding PSK-ECDHE key exchange mode\"));\n    }\n\n    if (mbedtls_ssl_conf_tls13_is_psk_enabled(ssl)) {\n        *p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE;\n        ke_modes_len++;\n\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"Adding pure PSK key exchange mode\"));\n    }\n\n    /* Now write the extension and ke_modes length */\n    MBEDTLS_PUT_UINT16_BE(ke_modes_len + 1, buf, 2);\n    buf[4] = ke_modes_len;\n\n    *out_len = p - buf;\n\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(\n        ssl, MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES);\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\nstatic psa_algorithm_t ssl_tls13_get_ciphersuite_hash_alg(int ciphersuite)\n{\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info = NULL;\n    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite);\n\n    if (ciphersuite_info != NULL) {\n        return mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac);\n    }\n\n    return PSA_ALG_NONE;\n}\n\nstatic int ssl_tls13_has_configured_ticket(mbedtls_ssl_context *ssl)\n{\n    mbedtls_ssl_session *session = ssl->session_negotiate;\n    return ssl->handshake->resume &&\n           session != NULL && session->ticket != NULL &&\n           mbedtls_ssl_conf_tls13_is_kex_mode_enabled(\n        ssl, mbedtls_ssl_tls13_session_get_ticket_flags(\n            session, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL));\n}\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\nstatic int ssl_tls13_early_data_has_valid_ticket(mbedtls_ssl_context *ssl)\n{\n    mbedtls_ssl_session *session = ssl->session_negotiate;\n    return ssl->handshake->resume &&\n           session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 &&\n           mbedtls_ssl_tls13_session_ticket_allow_early_data(session) &&\n           mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, session->ciphersuite);\n}\n#endif\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_ticket_get_identity(mbedtls_ssl_context *ssl,\n                                         psa_algorithm_t *hash_alg,\n                                         const unsigned char **identity,\n                                         size_t *identity_len)\n{\n    mbedtls_ssl_session *session = ssl->session_negotiate;\n\n    if (!ssl_tls13_has_configured_ticket(ssl)) {\n        return -1;\n    }\n\n    *hash_alg = ssl_tls13_get_ciphersuite_hash_alg(session->ciphersuite);\n    *identity = session->ticket;\n    *identity_len = session->ticket_len;\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_ticket_get_psk(mbedtls_ssl_context *ssl,\n                                    psa_algorithm_t *hash_alg,\n                                    const unsigned char **psk,\n                                    size_t *psk_len)\n{\n\n    mbedtls_ssl_session *session = ssl->session_negotiate;\n\n    if (!ssl_tls13_has_configured_ticket(ssl)) {\n        return -1;\n    }\n\n    *hash_alg = ssl_tls13_get_ciphersuite_hash_alg(session->ciphersuite);\n    *psk = session->resumption_key;\n    *psk_len = session->resumption_key_len;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_psk_get_identity(mbedtls_ssl_context *ssl,\n                                      psa_algorithm_t *hash_alg,\n                                      const unsigned char **identity,\n                                      size_t *identity_len)\n{\n\n    if (!mbedtls_ssl_conf_has_static_psk(ssl->conf)) {\n        return -1;\n    }\n\n    *hash_alg = PSA_ALG_SHA_256;\n    *identity = ssl->conf->psk_identity;\n    *identity_len = ssl->conf->psk_identity_len;\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_psk_get_psk(mbedtls_ssl_context *ssl,\n                                 psa_algorithm_t *hash_alg,\n                                 const unsigned char **psk,\n                                 size_t *psk_len)\n{\n\n    if (!mbedtls_ssl_conf_has_static_psk(ssl->conf)) {\n        return -1;\n    }\n\n    *hash_alg = PSA_ALG_SHA_256;\n    *psk = ssl->conf->psk;\n    *psk_len = ssl->conf->psk_len;\n    return 0;\n}\n\nstatic int ssl_tls13_get_configured_psk_count(mbedtls_ssl_context *ssl)\n{\n    int configured_psk_count = 0;\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n    if (ssl_tls13_has_configured_ticket(ssl)) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"Ticket is configured\"));\n        configured_psk_count++;\n    }\n#endif\n    if (mbedtls_ssl_conf_has_static_psk(ssl->conf)) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"PSK is configured\"));\n        configured_psk_count++;\n    }\n    return configured_psk_count;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_identity(mbedtls_ssl_context *ssl,\n                                    unsigned char *buf,\n                                    unsigned char *end,\n                                    const unsigned char *identity,\n                                    size_t identity_len,\n                                    uint32_t obfuscated_ticket_age,\n                                    size_t *out_len)\n{\n    ((void) ssl);\n    *out_len = 0;\n\n    /*\n     * - identity_len           (2 bytes)\n     * - identity               (psk_identity_len bytes)\n     * - obfuscated_ticket_age  (4 bytes)\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6 + identity_len);\n\n    MBEDTLS_PUT_UINT16_BE(identity_len, buf, 0);\n    memcpy(buf + 2, identity, identity_len);\n    MBEDTLS_PUT_UINT32_BE(obfuscated_ticket_age, buf, 2 + identity_len);\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"write identity\", buf, 6 + identity_len);\n\n    *out_len = 6 + identity_len;\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_binder(mbedtls_ssl_context *ssl,\n                                  unsigned char *buf,\n                                  unsigned char *end,\n                                  int psk_type,\n                                  psa_algorithm_t hash_alg,\n                                  const unsigned char *psk,\n                                  size_t psk_len,\n                                  size_t *out_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char binder_len;\n    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    size_t transcript_len = 0;\n\n    *out_len = 0;\n\n    binder_len = PSA_HASH_LENGTH(hash_alg);\n\n    /*\n     * - binder_len           (1 bytes)\n     * - binder               (binder_len bytes)\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 1 + binder_len);\n\n    buf[0] = binder_len;\n\n    /* Get current state of handshake transcript. */\n    ret = mbedtls_ssl_get_handshake_transcript(\n        ssl, mbedtls_md_type_from_psa_alg(hash_alg),\n        transcript, sizeof(transcript), &transcript_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_ssl_tls13_create_psk_binder(ssl, hash_alg,\n                                              psk, psk_len, psk_type,\n                                              transcript, buf + 1);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_create_psk_binder\", ret);\n        return ret;\n    }\n    MBEDTLS_SSL_DEBUG_BUF(4, \"write binder\", buf, 1 + binder_len);\n\n    *out_len = 1 + binder_len;\n\n    return 0;\n}\n\n/*\n * mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext() structure:\n *\n * struct {\n *   opaque identity<1..2^16-1>;\n *   uint32 obfuscated_ticket_age;\n * } PskIdentity;\n *\n * opaque PskBinderEntry<32..255>;\n *\n * struct {\n *   PskIdentity identities<7..2^16-1>;\n *   PskBinderEntry binders<33..2^16-1>;\n * } OfferedPsks;\n *\n * struct {\n *   select (Handshake.msg_type) {\n *      case client_hello: OfferedPsks;\n *      ...\n *   };\n * } PreSharedKeyExtension;\n *\n */\nint mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext(\n    mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end,\n    size_t *out_len, size_t *binders_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    int configured_psk_count = 0;\n    unsigned char *p = buf;\n    psa_algorithm_t hash_alg = PSA_ALG_NONE;\n    const unsigned char *identity;\n    size_t identity_len;\n    size_t l_binders_len = 0;\n    size_t output_len;\n\n    *out_len = 0;\n    *binders_len = 0;\n\n    /* Check if we have any PSKs to offer. If no, skip pre_shared_key */\n    configured_psk_count = ssl_tls13_get_configured_psk_count(ssl);\n    if (configured_psk_count == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"skip pre_shared_key extensions\"));\n        return 0;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(4, (\"Pre-configured PSK number = %d\",\n                              configured_psk_count));\n\n    /* Check if we have space to write the extension, binders included.\n     * - extension_type         (2 bytes)\n     * - extension_data_len     (2 bytes)\n     * - identities_len         (2 bytes)\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);\n    p += 6;\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n    if (ssl_tls13_ticket_get_identity(\n            ssl, &hash_alg, &identity, &identity_len) == 0) {\n#if defined(MBEDTLS_HAVE_TIME)\n        mbedtls_ms_time_t now = mbedtls_ms_time();\n        mbedtls_ssl_session *session = ssl->session_negotiate;\n        /* The ticket age has been checked to be smaller than the\n         * `ticket_lifetime` in ssl_prepare_client_hello() which is smaller than\n         * 7 days (enforced in ssl_tls13_parse_new_session_ticket()) . Thus the\n         * cast to `uint32_t` of the ticket age is safe. */\n        uint32_t obfuscated_ticket_age =\n            (uint32_t) (now - session->ticket_reception_time);\n        obfuscated_ticket_age += session->ticket_age_add;\n\n        ret = ssl_tls13_write_identity(ssl, p, end,\n                                       identity, identity_len,\n                                       obfuscated_ticket_age,\n                                       &output_len);\n#else\n        ret = ssl_tls13_write_identity(ssl, p, end, identity, identity_len,\n                                       0, &output_len);\n#endif /* MBEDTLS_HAVE_TIME */\n        if (ret != 0) {\n            return ret;\n        }\n\n        p += output_len;\n        l_binders_len += 1 + PSA_HASH_LENGTH(hash_alg);\n    }\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n    if (ssl_tls13_psk_get_identity(\n            ssl, &hash_alg, &identity, &identity_len) == 0) {\n\n        ret = ssl_tls13_write_identity(ssl, p, end, identity, identity_len, 0,\n                                       &output_len);\n        if (ret != 0) {\n            return ret;\n        }\n\n        p += output_len;\n        l_binders_len += 1 + PSA_HASH_LENGTH(hash_alg);\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"client hello, adding pre_shared_key extension, \"\n                           \"omitting PSK binder list\"));\n\n    /* Take into account the two bytes for the length of the binders. */\n    l_binders_len += 2;\n    /* Check if there is enough space for binders */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, l_binders_len);\n\n    /*\n     * - extension_type         (2 bytes)\n     * - extension_data_len     (2 bytes)\n     * - identities_len         (2 bytes)\n     */\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PRE_SHARED_KEY, buf, 0);\n    MBEDTLS_PUT_UINT16_BE(p - buf - 4 + l_binders_len, buf, 2);\n    MBEDTLS_PUT_UINT16_BE(p - buf - 6, buf, 4);\n\n    *out_len = (p - buf) + l_binders_len;\n    *binders_len = l_binders_len;\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"pre_shared_key identities\", buf, p - buf);\n\n    return 0;\n}\n\nint mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext(\n    mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = buf;\n    psa_algorithm_t hash_alg = PSA_ALG_NONE;\n    const unsigned char *psk;\n    size_t psk_len;\n    size_t output_len;\n\n    /* Check if we have space to write binders_len.\n     * - binders_len         (2 bytes)\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);\n    p += 2;\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n    if (ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len) == 0) {\n\n        ret = ssl_tls13_write_binder(ssl, p, end,\n                                     MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION,\n                                     hash_alg, psk, psk_len,\n                                     &output_len);\n        if (ret != 0) {\n            return ret;\n        }\n        p += output_len;\n    }\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n    if (ssl_tls13_psk_get_psk(ssl, &hash_alg, &psk, &psk_len) == 0) {\n\n        ret = ssl_tls13_write_binder(ssl, p, end,\n                                     MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL,\n                                     hash_alg, psk, psk_len,\n                                     &output_len);\n        if (ret != 0) {\n            return ret;\n        }\n        p += output_len;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"client hello, adding PSK binder list.\"));\n\n    /*\n     * - binders_len         (2 bytes)\n     */\n    MBEDTLS_PUT_UINT16_BE(p - buf - 2, buf, 0);\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"pre_shared_key binders\", buf, p - buf);\n\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(\n        ssl, MBEDTLS_TLS_EXT_PRE_SHARED_KEY);\n\n    return 0;\n}\n\n/*\n * struct {\n *   opaque identity<1..2^16-1>;\n *   uint32 obfuscated_ticket_age;\n * } PskIdentity;\n *\n * opaque PskBinderEntry<32..255>;\n *\n * struct {\n *\n *   select (Handshake.msg_type) {\n *         ...\n *         case server_hello: uint16 selected_identity;\n *   };\n *\n * } PreSharedKeyExtension;\n *\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_server_pre_shared_key_ext(mbedtls_ssl_context *ssl,\n                                                     const unsigned char *buf,\n                                                     const unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    int selected_identity;\n    const unsigned char *psk;\n    size_t psk_len;\n    psa_algorithm_t hash_alg;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 2);\n    selected_identity = MBEDTLS_GET_UINT16_BE(buf, 0);\n    ssl->handshake->selected_identity = (uint16_t) selected_identity;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"selected_identity = %d\", selected_identity));\n\n    if (selected_identity >= ssl_tls13_get_configured_psk_count(ssl)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Invalid PSK identity.\"));\n\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n    if (selected_identity == 0 && ssl_tls13_has_configured_ticket(ssl)) {\n        ret = ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len);\n    } else\n#endif\n    if (mbedtls_ssl_conf_has_static_psk(ssl->conf)) {\n        ret = ssl_tls13_psk_get_psk(ssl, &hash_alg, &psk, &psk_len);\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n    if (ret != 0) {\n        return ret;\n    }\n\n    if (mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac)\n        != hash_alg) {\n        MBEDTLS_SSL_DEBUG_MSG(\n            1, (\"Invalid ciphersuite for external psk.\"));\n\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    ret = mbedtls_ssl_set_hs_psk(ssl, psk, psk_len);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_set_hs_psk\", ret);\n        return ret;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */\n\nint mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl,\n                                              unsigned char *buf,\n                                              unsigned char *end,\n                                              size_t *out_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = buf;\n    size_t ext_len;\n\n    *out_len = 0;\n\n    ret = mbedtls_ssl_tls13_crypto_init(ssl);\n    if (ret != 0) {\n        return ret;\n    }\n\n    /* Write supported_versions extension\n     *\n     * Supported Versions Extension is mandatory with TLS 1.3.\n     */\n    ret = ssl_tls13_write_supported_versions_ext(ssl, p, end, &ext_len);\n    if (ret != 0) {\n        return ret;\n    }\n    p += ext_len;\n\n    /* Echo the cookie if the server provided one in its preceding\n     * HelloRetryRequest message.\n     */\n    ret = ssl_tls13_write_cookie_ext(ssl, p, end, &ext_len);\n    if (ret != 0) {\n        return ret;\n    }\n    p += ext_len;\n\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n    ret = mbedtls_ssl_tls13_write_record_size_limit_ext(\n        ssl, p, end, &ext_len);\n    if (ret != 0) {\n        return ret;\n    }\n    p += ext_len;\n#endif\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)\n    if (mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) {\n        ret = ssl_tls13_write_key_share_ext(ssl, p, end, &ext_len);\n        if (ret != 0) {\n            return ret;\n        }\n        p += ext_len;\n    }\n#endif\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    /* In the first ClientHello, write the early data indication extension if\n     * necessary and update the early data state.\n     * If an HRR has been received and thus we are currently writing the\n     * second ClientHello, the second ClientHello must not contain an early\n     * data extension and the early data state must stay as it is:\n     * MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT or\n     * MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED.\n     */\n    if (!ssl->handshake->hello_retry_request_flag) {\n        if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) &&\n            ssl_tls13_early_data_has_valid_ticket(ssl) &&\n            ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) {\n            ret = mbedtls_ssl_tls13_write_early_data_ext(\n                ssl, 0, p, end, &ext_len);\n            if (ret != 0) {\n                return ret;\n            }\n            p += ext_len;\n\n            ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT;\n        } else {\n            ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT;\n        }\n    }\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n    /* For PSK-based key exchange we need the pre_shared_key extension\n     * and the psk_key_exchange_modes extension.\n     *\n     * The pre_shared_key extension MUST be the last extension in the\n     * ClientHello. Servers MUST check that it is the last extension and\n     * otherwise fail the handshake with an \"illegal_parameter\" alert.\n     *\n     * Add the psk_key_exchange_modes extension.\n     */\n    ret = ssl_tls13_write_psk_key_exchange_modes_ext(ssl, p, end, &ext_len);\n    if (ret != 0) {\n        return ret;\n    }\n    p += ext_len;\n#endif\n\n    *out_len = p - buf;\n\n    return 0;\n}\n\nint mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl)\n{\n    ((void) ssl);\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    psa_algorithm_t hash_alg = PSA_ALG_NONE;\n    const unsigned char *psk;\n    size_t psk_len;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;\n\n    if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT) {\n        MBEDTLS_SSL_DEBUG_MSG(\n            1, (\"Set hs psk for early data when writing the first psk\"));\n\n        ret = ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(\n                1, \"ssl_tls13_ticket_get_psk\", ret);\n            return ret;\n        }\n\n        ret = mbedtls_ssl_set_hs_psk(ssl, psk, psk_len);\n        if (ret  != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_set_hs_psk\", ret);\n            return ret;\n        }\n\n        /*\n         * Early data are going to be encrypted using the ciphersuite\n         * associated with the pre-shared key used for the handshake.\n         * Note that if the server rejects early data, the handshake\n         * based on the pre-shared key may complete successfully\n         * with a selected ciphersuite different from the ciphersuite\n         * associated with the pre-shared key. Only the hashes of the\n         * two ciphersuites have to be the same. In that case, the\n         * encrypted handshake data and application data are\n         * encrypted using a different ciphersuite than the one used for\n         * the rejected early data.\n         */\n        ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(\n            ssl->session_negotiate->ciphersuite);\n        ssl->handshake->ciphersuite_info = ciphersuite_info;\n\n        /* Enable psk and psk_ephemeral to make stage early happy */\n        ssl->handshake->key_exchange_mode =\n            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL;\n\n        /* Start the TLS 1.3 key schedule:\n         *     Set the PSK and derive early secret.\n         */\n        ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(\n                1, \"mbedtls_ssl_tls13_key_schedule_stage_early\", ret);\n            return ret;\n        }\n\n        /* Derive early data key material */\n        ret = mbedtls_ssl_tls13_compute_early_transform(ssl);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(\n                1, \"mbedtls_ssl_tls13_compute_early_transform\", ret);\n            return ret;\n        }\n\n#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)\n        mbedtls_ssl_handshake_set_state(\n            ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO);\n#else\n        MBEDTLS_SSL_DEBUG_MSG(\n            1, (\"Switch to early data keys for outbound traffic\"));\n        mbedtls_ssl_set_outbound_transform(\n            ssl, ssl->handshake->transform_earlydata);\n        ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE;\n#endif\n    }\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n    return 0;\n}\n/*\n * Functions for parsing and processing Server Hello\n */\n\n/**\n * \\brief Detect if the ServerHello contains a supported_versions extension\n *        or not.\n *\n * \\param[in] ssl  SSL context\n * \\param[in] buf  Buffer containing the ServerHello message\n * \\param[in] end  End of the buffer containing the ServerHello message\n *\n * \\return 0 if the ServerHello does not contain a supported_versions extension\n * \\return 1 if the ServerHello contains a supported_versions extension\n * \\return A negative value if an error occurred while parsing the ServerHello.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_is_supported_versions_ext_present(\n    mbedtls_ssl_context *ssl,\n    const unsigned char *buf,\n    const unsigned char *end)\n{\n    const unsigned char *p = buf;\n    size_t legacy_session_id_echo_len;\n    const unsigned char *supported_versions_data;\n    const unsigned char *supported_versions_data_end;\n\n    /*\n     * Check there is enough data to access the legacy_session_id_echo vector\n     * length:\n     * - legacy_version                 2 bytes\n     * - random                         MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes\n     * - legacy_session_id_echo length  1 byte\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 3);\n    p += MBEDTLS_SERVER_HELLO_RANDOM_LEN + 2;\n    legacy_session_id_echo_len = *p;\n\n    /*\n     * Jump to the extensions, jumping over:\n     * - legacy_session_id_echo     (legacy_session_id_echo_len + 1) bytes\n     * - cipher_suite               2 bytes\n     * - legacy_compression_method  1 byte\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_echo_len + 4);\n    p += legacy_session_id_echo_len + 4;\n\n    return mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts(\n        ssl, p, end,\n        &supported_versions_data, &supported_versions_data_end);\n}\n\n/* Returns a negative value on failure, and otherwise\n * - 1 if the last eight bytes of the ServerHello random bytes indicate that\n *     the server is TLS 1.3 capable but negotiating TLS 1.2 or below.\n * - 0 otherwise\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_is_downgrade_negotiation(mbedtls_ssl_context *ssl,\n                                              const unsigned char *buf,\n                                              const unsigned char *end)\n{\n    /* First seven bytes of the magic downgrade strings, see RFC 8446 4.1.3 */\n    static const unsigned char magic_downgrade_string[] =\n    { 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44 };\n    const unsigned char *last_eight_bytes_of_random;\n    unsigned char last_byte_of_random;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 2);\n    last_eight_bytes_of_random = buf + 2 + MBEDTLS_SERVER_HELLO_RANDOM_LEN - 8;\n\n    if (memcmp(last_eight_bytes_of_random,\n               magic_downgrade_string,\n               sizeof(magic_downgrade_string)) == 0) {\n        last_byte_of_random = last_eight_bytes_of_random[7];\n        return last_byte_of_random == 0 ||\n               last_byte_of_random == 1;\n    }\n\n    return 0;\n}\n\n/* Returns a negative value on failure, and otherwise\n * - SSL_SERVER_HELLO or\n * - SSL_SERVER_HELLO_HRR\n * to indicate which message is expected and to be parsed next.\n */\n#define SSL_SERVER_HELLO 0\n#define SSL_SERVER_HELLO_HRR 1\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_server_hello_is_hrr(mbedtls_ssl_context *ssl,\n                                   const unsigned char *buf,\n                                   const unsigned char *end)\n{\n\n    /* Check whether this message is a HelloRetryRequest ( HRR ) message.\n     *\n     * Server Hello and HRR are only distinguished by Random set to the\n     * special value of the SHA-256 of \"HelloRetryRequest\".\n     *\n     * struct {\n     *    ProtocolVersion legacy_version = 0x0303;\n     *    Random random;\n     *    opaque legacy_session_id_echo<0..32>;\n     *    CipherSuite cipher_suite;\n     *    uint8 legacy_compression_method = 0;\n     *    Extension extensions<6..2^16-1>;\n     * } ServerHello;\n     *\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(\n        buf, end, 2 + sizeof(mbedtls_ssl_tls13_hello_retry_request_magic));\n\n    if (memcmp(buf + 2, mbedtls_ssl_tls13_hello_retry_request_magic,\n               sizeof(mbedtls_ssl_tls13_hello_retry_request_magic)) == 0) {\n        return SSL_SERVER_HELLO_HRR;\n    }\n\n    return SSL_SERVER_HELLO;\n}\n\n/*\n * Returns a negative value on failure, and otherwise\n * - SSL_SERVER_HELLO or\n * - SSL_SERVER_HELLO_HRR or\n * - SSL_SERVER_HELLO_TLS1_2\n */\n#define SSL_SERVER_HELLO_TLS1_2 2\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl,\n                                             const unsigned char *buf,\n                                             const unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n    MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_is_supported_versions_ext_present(\n                                 ssl, buf, end));\n\n    if (ret == 0) {\n        MBEDTLS_SSL_PROC_CHK_NEG(\n            ssl_tls13_is_downgrade_negotiation(ssl, buf, end));\n\n        /* If the server is negotiating TLS 1.2 or below and:\n         * . we did not propose TLS 1.2 or\n         * . the server responded it is TLS 1.3 capable but negotiating a lower\n         *   version of the protocol and thus we are under downgrade attack\n         * abort the handshake with an \"illegal parameter\" alert.\n         */\n        if (handshake->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 || ret) {\n            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n                                         MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n        }\n\n        /*\n         * Version 1.2 of the protocol has been negotiated, set the\n         * ssl->keep_current_message flag for the ServerHello to be kept and\n         * parsed as a TLS 1.2 ServerHello. We also change ssl->tls_version to\n         * MBEDTLS_SSL_VERSION_TLS1_2 thus from now on mbedtls_ssl_handshake_step()\n         * will dispatch to the TLS 1.2 state machine.\n         */\n        ssl->keep_current_message = 1;\n        ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2;\n        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(\n                                 ssl, MBEDTLS_SSL_HS_SERVER_HELLO,\n                                 buf, (size_t) (end - buf)));\n\n        if (mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) {\n            ret = ssl_tls13_reset_key_share(ssl);\n            if (ret != 0) {\n                return ret;\n            }\n        }\n\n        return SSL_SERVER_HELLO_TLS1_2;\n    }\n\n    ssl->session_negotiate->tls_version = ssl->tls_version;\n    ssl->session_negotiate->endpoint = ssl->conf->endpoint;\n\n    handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;\n\n    ret = ssl_server_hello_is_hrr(ssl, buf, end);\n    switch (ret) {\n        case SSL_SERVER_HELLO:\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"received ServerHello message\"));\n            break;\n        case SSL_SERVER_HELLO_HRR:\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"received HelloRetryRequest message\"));\n            /* If a client receives a second HelloRetryRequest in the same\n             * connection (i.e., where the ClientHello was itself in response\n             * to a HelloRetryRequest), it MUST abort the handshake with an\n             * \"unexpected_message\" alert.\n             */\n            if (handshake->hello_retry_request_flag) {\n                MBEDTLS_SSL_DEBUG_MSG(1, (\"Multiple HRRs received\"));\n                MBEDTLS_SSL_PEND_FATAL_ALERT(\n                    MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,\n                    MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE);\n                return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n            }\n            /*\n             * Clients must abort the handshake with an \"illegal_parameter\"\n             * alert if the HelloRetryRequest would not result in any change\n             * in the ClientHello.\n             * In a PSK only key exchange that what we expect.\n             */\n            if (!mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) {\n                MBEDTLS_SSL_DEBUG_MSG(1,\n                                      (\"Unexpected HRR in pure PSK key exchange.\"));\n                MBEDTLS_SSL_PEND_FATAL_ALERT(\n                    MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n                    MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n                return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n            }\n\n            handshake->hello_retry_request_flag = 1;\n\n            break;\n    }\n\ncleanup:\n\n    return ret;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_check_server_hello_session_id_echo(mbedtls_ssl_context *ssl,\n                                                        const unsigned char **buf,\n                                                        const unsigned char *end)\n{\n    const unsigned char *p = *buf;\n    size_t legacy_session_id_echo_len;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1);\n    legacy_session_id_echo_len = *p++;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_echo_len);\n\n    /* legacy_session_id_echo */\n    if (ssl->session_negotiate->id_len != legacy_session_id_echo_len ||\n        memcmp(ssl->session_negotiate->id, p, legacy_session_id_echo_len) != 0) {\n        MBEDTLS_SSL_DEBUG_BUF(3, \"Expected Session ID\",\n                              ssl->session_negotiate->id,\n                              ssl->session_negotiate->id_len);\n        MBEDTLS_SSL_DEBUG_BUF(3, \"Received Session ID\", p,\n                              legacy_session_id_echo_len);\n\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    p += legacy_session_id_echo_len;\n    *buf = p;\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"Session ID\", ssl->session_negotiate->id,\n                          ssl->session_negotiate->id_len);\n    return 0;\n}\n\n/* Parse ServerHello message and configure context\n *\n * struct {\n *    ProtocolVersion legacy_version = 0x0303; // TLS 1.2\n *    Random random;\n *    opaque legacy_session_id_echo<0..32>;\n *    CipherSuite cipher_suite;\n *    uint8 legacy_compression_method = 0;\n *    Extension extensions<6..2^16-1>;\n * } ServerHello;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_server_hello(mbedtls_ssl_context *ssl,\n                                        const unsigned char *buf,\n                                        const unsigned char *end,\n                                        int is_hrr)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const unsigned char *p = buf;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n    size_t extensions_len;\n    const unsigned char *extensions_end;\n    uint16_t cipher_suite;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;\n    int fatal_alert = 0;\n    uint32_t allowed_extensions_mask;\n    int hs_msg_type = is_hrr ? MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST :\n                      MBEDTLS_SSL_HS_SERVER_HELLO;\n\n    /*\n     * Check there is space for minimal fields\n     *\n     * - legacy_version             ( 2 bytes)\n     * - random                     (MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes)\n     * - legacy_session_id_echo     ( 1 byte ), minimum size\n     * - cipher_suite               ( 2 bytes)\n     * - legacy_compression_method  ( 1 byte )\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 6);\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"server hello\", p, end - p);\n    MBEDTLS_SSL_DEBUG_BUF(3, \"server hello, version\", p, 2);\n\n    /* ...\n     * ProtocolVersion legacy_version = 0x0303; // TLS 1.2\n     * ...\n     * with ProtocolVersion defined as:\n     * uint16 ProtocolVersion;\n     */\n    if (mbedtls_ssl_read_version(p, ssl->conf->transport) !=\n        MBEDTLS_SSL_VERSION_TLS1_2) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Unsupported version of TLS.\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION,\n                                     MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION);\n        ret = MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;\n        goto cleanup;\n    }\n    p += 2;\n\n    /* ...\n     * Random random;\n     * ...\n     * with Random defined as:\n     * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN];\n     */\n    if (!is_hrr) {\n        memcpy(&handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN], p,\n               MBEDTLS_SERVER_HELLO_RANDOM_LEN);\n        MBEDTLS_SSL_DEBUG_BUF(3, \"server hello, random bytes\",\n                              p, MBEDTLS_SERVER_HELLO_RANDOM_LEN);\n    }\n    p += MBEDTLS_SERVER_HELLO_RANDOM_LEN;\n\n    /* ...\n     * opaque legacy_session_id_echo<0..32>;\n     * ...\n     */\n    if (ssl_tls13_check_server_hello_session_id_echo(ssl, &p, end) != 0) {\n        fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER;\n        goto cleanup;\n    }\n\n    /* ...\n     * CipherSuite cipher_suite;\n     * ...\n     * with CipherSuite defined as:\n     * uint8 CipherSuite[2];\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n\n\n    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite);\n    /*\n     * Check whether this ciphersuite is valid and offered.\n     */\n    if ((mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info,\n                                          ssl->tls_version,\n                                          ssl->tls_version) != 0) ||\n        !mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, cipher_suite)) {\n        fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER;\n    }\n    /*\n     * If we received an HRR before and that the proposed selected\n     * ciphersuite in this server hello is not the same as the one\n     * proposed in the HRR, we abort the handshake and send an\n     * \"illegal_parameter\" alert.\n     */\n    else if ((!is_hrr) && handshake->hello_retry_request_flag &&\n             (cipher_suite != ssl->session_negotiate->ciphersuite)) {\n        fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER;\n    }\n\n    if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"invalid ciphersuite(%04x) parameter\",\n                                  cipher_suite));\n        goto cleanup;\n    }\n\n    /* Configure ciphersuites */\n    mbedtls_ssl_optimize_checksum(ssl, ciphersuite_info);\n\n    handshake->ciphersuite_info = ciphersuite_info;\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, chosen ciphersuite: ( %04x ) - %s\",\n                              cipher_suite, ciphersuite_info->name));\n\n#if defined(MBEDTLS_HAVE_TIME)\n    ssl->session_negotiate->start = mbedtls_time(NULL);\n#endif /* MBEDTLS_HAVE_TIME */\n\n    /* ...\n     * uint8 legacy_compression_method = 0;\n     * ...\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1);\n    if (p[0] != MBEDTLS_SSL_COMPRESS_NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad legacy compression method\"));\n        fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER;\n        goto cleanup;\n    }\n    p++;\n\n    /* ...\n     * Extension extensions<6..2^16-1>;\n     * ...\n     * struct {\n     *      ExtensionType extension_type; (2 bytes)\n     *      opaque extension_data<0..2^16-1>;\n     * } Extension;\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n\n    /* Check extensions do not go beyond the buffer of data. */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);\n    extensions_end = p + extensions_len;\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"server hello extensions\", p, extensions_len);\n\n    handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;\n    allowed_extensions_mask = is_hrr ?\n                              MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_HRR :\n                              MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_SH;\n\n    while (p < extensions_end) {\n        unsigned int extension_type;\n        size_t extension_data_len;\n        const unsigned char *extension_data_end;\n\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);\n        extension_type = MBEDTLS_GET_UINT16_BE(p, 0);\n        extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);\n        p += 4;\n\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);\n        extension_data_end = p + extension_data_len;\n\n        ret = mbedtls_ssl_tls13_check_received_extension(\n            ssl, hs_msg_type, extension_type, allowed_extensions_mask);\n        if (ret != 0) {\n            return ret;\n        }\n\n        switch (extension_type) {\n            case MBEDTLS_TLS_EXT_COOKIE:\n\n                ret = ssl_tls13_parse_cookie_ext(ssl,\n                                                 p, extension_data_end);\n                if (ret != 0) {\n                    MBEDTLS_SSL_DEBUG_RET(1,\n                                          \"ssl_tls13_parse_cookie_ext\",\n                                          ret);\n                    goto cleanup;\n                }\n                break;\n\n            case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS:\n                ret = ssl_tls13_parse_supported_versions_ext(ssl,\n                                                             p,\n                                                             extension_data_end);\n                if (ret != 0) {\n                    goto cleanup;\n                }\n                break;\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n            case MBEDTLS_TLS_EXT_PRE_SHARED_KEY:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found pre_shared_key extension\"));\n\n                if ((ret = ssl_tls13_parse_server_pre_shared_key_ext(\n                         ssl, p, extension_data_end)) != 0) {\n                    MBEDTLS_SSL_DEBUG_RET(\n                        1, (\"ssl_tls13_parse_server_pre_shared_key_ext\"), ret);\n                    return ret;\n                }\n                break;\n#endif\n\n            case MBEDTLS_TLS_EXT_KEY_SHARE:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found key_shares extension\"));\n                if (!mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) {\n                    fatal_alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT;\n                    goto cleanup;\n                }\n\n                if (is_hrr) {\n                    ret = ssl_tls13_parse_hrr_key_share_ext(ssl,\n                                                            p, extension_data_end);\n                } else {\n                    ret = ssl_tls13_parse_key_share_ext(ssl,\n                                                        p, extension_data_end);\n                }\n                if (ret != 0) {\n                    MBEDTLS_SSL_DEBUG_RET(1,\n                                          \"ssl_tls13_parse_key_share_ext\",\n                                          ret);\n                    goto cleanup;\n                }\n                break;\n\n            default:\n                ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n                goto cleanup;\n        }\n\n        p += extension_data_len;\n    }\n\n    MBEDTLS_SSL_PRINT_EXTS(3, hs_msg_type, handshake->received_extensions);\n\ncleanup:\n\n    if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT) {\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT,\n                                     MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION);\n        ret = MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;\n    } else if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER) {\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n        ret = MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n    return ret;\n}\n\n#if defined(MBEDTLS_DEBUG_C)\nstatic const char *ssl_tls13_get_kex_mode_str(int mode)\n{\n    switch (mode) {\n        case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK:\n            return \"psk\";\n        case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL:\n            return \"ephemeral\";\n        case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL:\n            return \"psk_ephemeral\";\n        default:\n            return \"unknown mode\";\n    }\n}\n#endif /* MBEDTLS_DEBUG_C */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_postprocess_server_hello(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n    /* Determine the key exchange mode:\n     * 1) If both the pre_shared_key and key_share extensions were received\n     *    then the key exchange mode is PSK with EPHEMERAL.\n     * 2) If only the pre_shared_key extension was received then the key\n     *    exchange mode is PSK-only.\n     * 3) If only the key_share extension was received then the key\n     *    exchange mode is EPHEMERAL-only.\n     */\n    switch (handshake->received_extensions &\n            (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) |\n             MBEDTLS_SSL_EXT_MASK(KEY_SHARE))) {\n        /* Only the pre_shared_key extension was received */\n        case MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY):\n            handshake->key_exchange_mode =\n                MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;\n            break;\n\n        /* Only the key_share extension was received */\n        case MBEDTLS_SSL_EXT_MASK(KEY_SHARE):\n            handshake->key_exchange_mode =\n                MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL;\n            break;\n\n        /* Both the pre_shared_key and key_share extensions were received */\n        case (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) |\n              MBEDTLS_SSL_EXT_MASK(KEY_SHARE)):\n            handshake->key_exchange_mode =\n                MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;\n            break;\n\n        /* Neither pre_shared_key nor key_share extension was received */\n        default:\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"Unknown key exchange.\"));\n            ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n            goto cleanup;\n    }\n\n    if (!mbedtls_ssl_conf_tls13_is_kex_mode_enabled(\n            ssl, handshake->key_exchange_mode)) {\n        ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n        MBEDTLS_SSL_DEBUG_MSG(\n            2, (\"Key exchange mode(%s) is not supported.\",\n                ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode)));\n        goto cleanup;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(\n        3, (\"Selected key exchange mode: %s\",\n            ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode)));\n\n    /* Start the TLS 1.3 key scheduling if not already done.\n     *\n     * If we proposed early data then we have already derived an\n     * early secret using the selected PSK and its associated hash.\n     * It means that if the negotiated key exchange mode is psk or\n     * psk_ephemeral, we have already correctly computed the\n     * early secret and thus we do not do it again. In all other\n     * cases we compute it here.\n     */\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT ||\n        handshake->key_exchange_mode ==\n        MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL)\n#endif\n    {\n        ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(\n                1, \"mbedtls_ssl_tls13_key_schedule_stage_early\", ret);\n            goto cleanup;\n        }\n    }\n\n    ret = mbedtls_ssl_tls13_compute_handshake_transform(ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1,\n                              \"mbedtls_ssl_tls13_compute_handshake_transform\",\n                              ret);\n        goto cleanup;\n    }\n\n    mbedtls_ssl_set_inbound_transform(ssl, handshake->transform_handshake);\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"Switch to handshake keys for inbound traffic\"));\n    ssl->session_in = ssl->session_negotiate;\n\ncleanup:\n    if (ret != 0) {\n        MBEDTLS_SSL_PEND_FATAL_ALERT(\n            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,\n            MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);\n    }\n\n    return ret;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_postprocess_hrr(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    mbedtls_ssl_session_reset_msg_layer(ssl, 0);\n\n    /*\n     * We are going to re-generate a shared secret corresponding to the group\n     * selected by the server, which is different from the group for which we\n     * generated a shared secret in the first client hello.\n     * Thus, reset the shared secret.\n     */\n    ret = ssl_tls13_reset_key_share(ssl);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ssl->session_negotiate->ciphersuite = ssl->handshake->ciphersuite_info->id;\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    if (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT) {\n        ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED;\n    }\n#endif\n\n    return 0;\n}\n\n/*\n * Wait and parse ServerHello handshake message.\n * Handler for MBEDTLS_SSL_SERVER_HELLO\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_process_server_hello(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *buf = NULL;\n    size_t buf_len = 0;\n    int is_hrr = 0;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> %s\", __func__));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(\n                             ssl, MBEDTLS_SSL_HS_SERVER_HELLO, &buf, &buf_len));\n\n    ret = ssl_tls13_preprocess_server_hello(ssl, buf, buf + buf_len);\n    if (ret < 0) {\n        goto cleanup;\n    } else {\n        is_hrr = (ret == SSL_SERVER_HELLO_HRR);\n    }\n\n    if (ret == SSL_SERVER_HELLO_TLS1_2) {\n        ret = 0;\n        goto cleanup;\n    }\n\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_server_hello(ssl, buf,\n                                                      buf + buf_len,\n                                                      is_hrr));\n    if (is_hrr) {\n        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_reset_transcript_for_hrr(ssl));\n    }\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(\n                             ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, buf_len));\n\n    if (is_hrr) {\n        MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_hrr(ssl));\n#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)\n        /* If not offering early data, the client sends a dummy CCS record\n         * immediately before its second flight. This may either be before\n         * its second ClientHello or before its encrypted handshake flight.\n         */\n        mbedtls_ssl_handshake_set_state(\n            ssl, MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO);\n#else\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);\n#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */\n    } else {\n        MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_server_hello(ssl));\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);\n    }\n\ncleanup:\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= %s ( %s )\", __func__,\n                              is_hrr ? \"HelloRetryRequest\" : \"ServerHello\"));\n    return ret;\n}\n\n/*\n *\n * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS\n *\n * The EncryptedExtensions message contains any extensions which\n * should be protected, i.e., any which are not needed to establish\n * the cryptographic context.\n */\n\n/* Parse EncryptedExtensions message\n * struct {\n *     Extension extensions<0..2^16-1>;\n * } EncryptedExtensions;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_encrypted_extensions(mbedtls_ssl_context *ssl,\n                                                const unsigned char *buf,\n                                                const unsigned char *end)\n{\n    int ret = 0;\n    size_t extensions_len;\n    const unsigned char *p = buf;\n    const unsigned char *extensions_end;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);\n    extensions_end = p + extensions_len;\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"encrypted extensions\", p, extensions_len);\n\n    handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;\n\n    while (p < extensions_end) {\n        unsigned int extension_type;\n        size_t extension_data_len;\n\n        /*\n         * struct {\n         *     ExtensionType extension_type; (2 bytes)\n         *     opaque extension_data<0..2^16-1>;\n         * } Extension;\n         */\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);\n        extension_type = MBEDTLS_GET_UINT16_BE(p, 0);\n        extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);\n        p += 4;\n\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);\n\n        ret = mbedtls_ssl_tls13_check_received_extension(\n            ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, extension_type,\n            MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_EE);\n        if (ret != 0) {\n            return ret;\n        }\n\n        switch (extension_type) {\n#if defined(MBEDTLS_SSL_ALPN)\n            case MBEDTLS_TLS_EXT_ALPN:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found alpn extension\"));\n\n                if ((ret = ssl_tls13_parse_alpn_ext(\n                         ssl, p, (size_t) extension_data_len)) != 0) {\n                    return ret;\n                }\n\n                break;\n#endif /* MBEDTLS_SSL_ALPN */\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n            case MBEDTLS_TLS_EXT_EARLY_DATA:\n\n                if (extension_data_len != 0) {\n                    /* The message must be empty. */\n                    MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,\n                                                 MBEDTLS_ERR_SSL_DECODE_ERROR);\n                    return MBEDTLS_ERR_SSL_DECODE_ERROR;\n                }\n\n                break;\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n            case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found record_size_limit extension\"));\n\n                ret = mbedtls_ssl_tls13_parse_record_size_limit_ext(\n                    ssl, p, p + extension_data_len);\n                if (ret != 0) {\n                    MBEDTLS_SSL_DEBUG_RET(\n                        1, (\"mbedtls_ssl_tls13_parse_record_size_limit_ext\"), ret);\n                    return ret;\n                }\n                break;\n#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */\n\n            default:\n                MBEDTLS_SSL_PRINT_EXT(\n                    3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,\n                    extension_type, \"( ignored )\");\n                break;\n        }\n\n        p += extension_data_len;\n    }\n\n    if ((handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)) &&\n        (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH))) {\n        MBEDTLS_SSL_DEBUG_MSG(3,\n                              (\n                                  \"Record size limit extension cannot be used with max fragment length extension\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(\n            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n            MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,\n                           handshake->received_extensions);\n\n    /* Check that we consumed all the message. */\n    if (p != end) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"EncryptedExtension lengths misaligned\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,\n                                     MBEDTLS_ERR_SSL_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    return ret;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_process_encrypted_extensions(mbedtls_ssl_context *ssl)\n{\n    int ret;\n    unsigned char *buf;\n    size_t buf_len;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse encrypted extensions\"));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(\n                             ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,\n                             &buf, &buf_len));\n\n    /* Process the message contents */\n    MBEDTLS_SSL_PROC_CHK(\n        ssl_tls13_parse_encrypted_extensions(ssl, buf, buf + buf_len));\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) {\n        /* RFC8446 4.2.11\n         * If the server supplies an \"early_data\" extension, the\n         * client MUST verify that the server's selected_identity\n         * is 0. If any other value is returned, the client MUST\n         * abort the handshake with an \"illegal_parameter\" alert.\n         *\n         * RFC 8446 4.2.10\n         * In order to accept early data, the server MUST have accepted a PSK\n         * cipher suite and selected the first key offered in the client's\n         * \"pre_shared_key\" extension. In addition, it MUST verify that the\n         * following values are the same as those associated with the\n         * selected PSK:\n         * - The TLS version number\n         * - The selected cipher suite\n         * - The selected ALPN [RFC7301] protocol, if any\n         *\n         * The server has sent an early data extension in its Encrypted\n         * Extension message thus accepted to receive early data. We\n         * check here that the additional constraints on the handshake\n         * parameters, when early data are exchanged, are met,\n         * namely:\n         * - a PSK has been selected for the handshake\n         * - the selected PSK for the handshake was the first one proposed\n         *   by the client.\n         * - the selected ciphersuite for the handshake is the ciphersuite\n         *   associated with the selected PSK.\n         */\n        if ((!mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) ||\n            handshake->selected_identity != 0 ||\n            handshake->ciphersuite_info->id !=\n            ssl->session_negotiate->ciphersuite) {\n\n            MBEDTLS_SSL_PEND_FATAL_ALERT(\n                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n                MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n        }\n\n        ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED;\n    } else if (ssl->early_data_state !=\n               MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT) {\n        ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED;\n    }\n#endif\n\n    /*\n     * In case the client has proposed a PSK associated with a ticket,\n     * `ssl->session_negotiate->ciphersuite` still contains at this point the\n     * identifier of the ciphersuite associated with the ticket. This is that\n     * way because, if an exchange of early data is agreed upon, we need\n     * it to check that the ciphersuite selected for the handshake is the\n     * ticket ciphersuite (see above). This information is not needed\n     * anymore thus we can now set it to the identifier of the ciphersuite\n     * used in this session under negotiation.\n     */\n    ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id;\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(\n                             ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,\n                             buf, buf_len));\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n    if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) {\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED);\n    } else {\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST);\n    }\n#else\n    ((void) ssl);\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED);\n#endif\n\ncleanup:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse encrypted extensions\"));\n    return ret;\n\n}\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n/*\n * Handler for MBEDTLS_SSL_END_OF_EARLY_DATA\n *\n * RFC 8446 section 4.5\n *\n * struct {} EndOfEarlyData;\n *\n * If the server sent an \"early_data\" extension in EncryptedExtensions, the\n * client MUST send an EndOfEarlyData message after receiving the server\n * Finished. Otherwise, the client MUST NOT send an EndOfEarlyData message.\n */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_end_of_early_data(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *buf = NULL;\n    size_t buf_len;\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write EndOfEarlyData\"));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(\n                             ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA,\n                             &buf, &buf_len));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_hdr_to_checksum(\n                             ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, 0));\n\n    MBEDTLS_SSL_PROC_CHK(\n        mbedtls_ssl_finish_handshake_msg(ssl, buf_len, 0));\n\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);\n\ncleanup:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write EndOfEarlyData\"));\n    return ret;\n}\n\nint mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl)\n{\n    if ((ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) ||\n        (!mbedtls_ssl_is_handshake_over(ssl))) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    switch (ssl->early_data_state) {\n        case MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT:\n            return MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED;\n            break;\n\n        case MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED:\n            return MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;\n            break;\n\n        case MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED:\n            return MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED;\n            break;\n\n        default:\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n}\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n/*\n * STATE HANDLING: CertificateRequest\n *\n */\n#define SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST 0\n#define SSL_CERTIFICATE_REQUEST_SKIP           1\n/* Coordination:\n * Deals with the ambiguity of not knowing if a CertificateRequest\n * will be sent. Returns a negative code on failure, or\n * - SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST\n * - SSL_CERTIFICATE_REQUEST_SKIP\n * indicating if a Certificate Request is expected or not.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_certificate_request_coordinate(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_read_record\", ret);\n        return ret;\n    }\n    ssl->keep_current_message = 1;\n\n    if ((ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) &&\n        (ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST)) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"got a certificate request\"));\n        return SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"got no certificate request\"));\n\n    return SSL_CERTIFICATE_REQUEST_SKIP;\n}\n\n/*\n * ssl_tls13_parse_certificate_request()\n *     Parse certificate request\n * struct {\n *   opaque certificate_request_context<0..2^8-1>;\n *   Extension extensions<2..2^16-1>;\n * } CertificateRequest;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_certificate_request(mbedtls_ssl_context *ssl,\n                                               const unsigned char *buf,\n                                               const unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const unsigned char *p = buf;\n    size_t certificate_request_context_len = 0;\n    size_t extensions_len = 0;\n    const unsigned char *extensions_end;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n    /* ...\n     * opaque certificate_request_context<0..2^8-1>\n     * ...\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1);\n    certificate_request_context_len = (size_t) p[0];\n    p += 1;\n\n    if (certificate_request_context_len > 0) {\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, certificate_request_context_len);\n        MBEDTLS_SSL_DEBUG_BUF(3, \"Certificate Request Context\",\n                              p, certificate_request_context_len);\n\n        handshake->certificate_request_context =\n            mbedtls_calloc(1, certificate_request_context_len);\n        if (handshake->certificate_request_context == NULL) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"buffer too small\"));\n            return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        }\n        memcpy(handshake->certificate_request_context, p,\n               certificate_request_context_len);\n        p += certificate_request_context_len;\n    }\n\n    /* ...\n     * Extension extensions<2..2^16-1>;\n     * ...\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);\n    extensions_end = p + extensions_len;\n\n    handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;\n\n    while (p < extensions_end) {\n        unsigned int extension_type;\n        size_t extension_data_len;\n\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);\n        extension_type = MBEDTLS_GET_UINT16_BE(p, 0);\n        extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);\n        p += 4;\n\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);\n\n        ret = mbedtls_ssl_tls13_check_received_extension(\n            ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, extension_type,\n            MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CR);\n        if (ret != 0) {\n            return ret;\n        }\n\n        switch (extension_type) {\n            case MBEDTLS_TLS_EXT_SIG_ALG:\n                MBEDTLS_SSL_DEBUG_MSG(3,\n                                      (\"found signature algorithms extension\"));\n                ret = mbedtls_ssl_parse_sig_alg_ext(ssl, p,\n                                                    p + extension_data_len);\n                if (ret != 0) {\n                    return ret;\n                }\n\n                break;\n\n            default:\n                MBEDTLS_SSL_PRINT_EXT(\n                    3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,\n                    extension_type, \"( ignored )\");\n                break;\n        }\n\n        p += extension_data_len;\n    }\n\n    MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,\n                           handshake->received_extensions);\n\n    /* Check that we consumed all the message. */\n    if (p != end) {\n        MBEDTLS_SSL_DEBUG_MSG(1,\n                              (\"CertificateRequest misaligned\"));\n        goto decode_error;\n    }\n\n    /* RFC 8446 section 4.3.2\n     *\n     * The \"signature_algorithms\" extension MUST be specified\n     */\n    if ((handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(SIG_ALG)) == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(3,\n                              (\"no signature algorithms extension found\"));\n        goto decode_error;\n    }\n\n    ssl->handshake->client_auth = 1;\n    return 0;\n\ndecode_error:\n    MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,\n                                 MBEDTLS_ERR_SSL_DECODE_ERROR);\n    return MBEDTLS_ERR_SSL_DECODE_ERROR;\n}\n\n/*\n * Handler for  MBEDTLS_SSL_CERTIFICATE_REQUEST\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_process_certificate_request(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse certificate request\"));\n\n    MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_certificate_request_coordinate(ssl));\n\n    if (ret == SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST) {\n        unsigned char *buf;\n        size_t buf_len;\n\n        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(\n                                 ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,\n                                 &buf, &buf_len));\n\n        MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_request(\n                                 ssl, buf, buf + buf_len));\n\n        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(\n                                 ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,\n                                 buf, buf_len));\n    } else if (ret == SSL_CERTIFICATE_REQUEST_SKIP) {\n        ret = 0;\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        goto cleanup;\n    }\n\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CERTIFICATE);\n\ncleanup:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse certificate request\"));\n    return ret;\n}\n\n/*\n * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_process_server_certificate(mbedtls_ssl_context *ssl)\n{\n    int ret;\n\n    ret = mbedtls_ssl_tls13_process_certificate(ssl);\n    if (ret != 0) {\n        return ret;\n    }\n\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY);\n    return 0;\n}\n\n/*\n * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl)\n{\n    int ret;\n\n    ret = mbedtls_ssl_tls13_process_certificate_verify(ssl);\n    if (ret != 0) {\n        return ret;\n    }\n\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED);\n    return 0;\n}\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\n/*\n * Handler for MBEDTLS_SSL_SERVER_FINISHED\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_process_server_finished(mbedtls_ssl_context *ssl)\n{\n    int ret;\n\n    ret = mbedtls_ssl_tls13_process_finished_message(ssl);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_ssl_tls13_compute_application_transform(ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_PEND_FATAL_ALERT(\n            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,\n            MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);\n        return ret;\n    }\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED) {\n        ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED;\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA);\n    } else\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n    {\n#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)\n        mbedtls_ssl_handshake_set_state(\n            ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED);\n#else\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);\n#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */\n    }\n\n    return 0;\n}\n\n/*\n * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_client_certificate(mbedtls_ssl_context *ssl)\n{\n    int non_empty_certificate_msg = 0;\n\n    MBEDTLS_SSL_DEBUG_MSG(1,\n                          (\"Switch to handshake traffic keys for outbound traffic\"));\n    mbedtls_ssl_set_outbound_transform(ssl, ssl->handshake->transform_handshake);\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n    if (ssl->handshake->client_auth) {\n        int ret = mbedtls_ssl_tls13_write_certificate(ssl);\n        if (ret != 0) {\n            return ret;\n        }\n\n        if (mbedtls_ssl_own_cert(ssl) != NULL) {\n            non_empty_certificate_msg = 1;\n        }\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"skip write certificate\"));\n    }\n#endif\n\n    if (non_empty_certificate_msg) {\n        mbedtls_ssl_handshake_set_state(ssl,\n                                        MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY);\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"skip write certificate verify\"));\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED);\n    }\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n/*\n * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_client_certificate_verify(mbedtls_ssl_context *ssl)\n{\n    int ret = mbedtls_ssl_tls13_write_certificate_verify(ssl);\n\n    if (ret == 0) {\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED);\n    }\n\n    return ret;\n}\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\n/*\n * Handler for MBEDTLS_SSL_CLIENT_FINISHED\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_client_finished(mbedtls_ssl_context *ssl)\n{\n    int ret;\n\n    ret = mbedtls_ssl_tls13_write_finished_message(ssl);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_ssl_tls13_compute_resumption_master_secret(ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(\n            1, \"mbedtls_ssl_tls13_compute_resumption_master_secret \", ret);\n        return ret;\n    }\n\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_FLUSH_BUFFERS);\n    return 0;\n}\n\n/*\n * Handler for MBEDTLS_SSL_FLUSH_BUFFERS\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_flush_buffers(mbedtls_ssl_context *ssl)\n{\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"handshake: done\"));\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP);\n    return 0;\n}\n\n/*\n * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl)\n{\n\n    mbedtls_ssl_tls13_handshake_wrapup(ssl);\n\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n/* From RFC 8446 section 4.2.10\n *\n * struct {\n *     select (Handshake.msg_type) {\n *         case new_session_ticket:   uint32 max_early_data_size;\n *         ...\n *     };\n * } EarlyDataIndication;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_new_session_ticket_early_data_ext(\n    mbedtls_ssl_context *ssl,\n    const unsigned char *buf,\n    const unsigned char *end)\n{\n    mbedtls_ssl_session *session = ssl->session;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 4);\n\n    session->max_early_data_size = MBEDTLS_GET_UINT32_BE(buf, 0);\n    mbedtls_ssl_tls13_session_set_ticket_flags(\n        session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA);\n    MBEDTLS_SSL_DEBUG_MSG(\n        3, (\"received max_early_data_size: %u\",\n            (unsigned int) session->max_early_data_size));\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_new_session_ticket_exts(mbedtls_ssl_context *ssl,\n                                                   const unsigned char *buf,\n                                                   const unsigned char *end)\n{\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n    const unsigned char *p = buf;\n\n\n    handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;\n\n    while (p < end) {\n        unsigned int extension_type;\n        size_t extension_data_len;\n        int ret;\n\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4);\n        extension_type = MBEDTLS_GET_UINT16_BE(p, 0);\n        extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);\n        p += 4;\n\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extension_data_len);\n\n        ret = mbedtls_ssl_tls13_check_received_extension(\n            ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, extension_type,\n            MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_NST);\n        if (ret != 0) {\n            return ret;\n        }\n\n        switch (extension_type) {\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n            case MBEDTLS_TLS_EXT_EARLY_DATA:\n                ret = ssl_tls13_parse_new_session_ticket_early_data_ext(\n                    ssl, p, p + extension_data_len);\n                if (ret != 0) {\n                    MBEDTLS_SSL_DEBUG_RET(\n                        1, \"ssl_tls13_parse_new_session_ticket_early_data_ext\",\n                        ret);\n                }\n                break;\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n            default:\n                MBEDTLS_SSL_PRINT_EXT(\n                    3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET,\n                    extension_type, \"( ignored )\");\n                break;\n        }\n\n        p +=  extension_data_len;\n    }\n\n    MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET,\n                           handshake->received_extensions);\n\n    return 0;\n}\n\n/*\n * From RFC8446, page 74\n *\n * struct {\n *    uint32 ticket_lifetime;\n *    uint32 ticket_age_add;\n *    opaque ticket_nonce<0..255>;\n *    opaque ticket<1..2^16-1>;\n *    Extension extensions<0..2^16-2>;\n * } NewSessionTicket;\n *\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_new_session_ticket(mbedtls_ssl_context *ssl,\n                                              unsigned char *buf,\n                                              unsigned char *end,\n                                              unsigned char **ticket_nonce,\n                                              size_t *ticket_nonce_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = buf;\n    mbedtls_ssl_session *session = ssl->session;\n    size_t ticket_len;\n    unsigned char *ticket;\n    size_t extensions_len;\n\n    *ticket_nonce = NULL;\n    *ticket_nonce_len = 0;\n    /*\n     *    ticket_lifetime   4 bytes\n     *    ticket_age_add    4 bytes\n     *    ticket_nonce_len  1 byte\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 9);\n\n    session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0);\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"ticket_lifetime: %u\",\n                           (unsigned int) session->ticket_lifetime));\n    if (session->ticket_lifetime >\n        MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"ticket_lifetime exceeds 7 days.\"));\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 4);\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"ticket_age_add: %u\",\n                           (unsigned int) session->ticket_age_add));\n\n    *ticket_nonce_len = p[8];\n    p += 9;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, *ticket_nonce_len);\n    *ticket_nonce = p;\n    MBEDTLS_SSL_DEBUG_BUF(3, \"ticket_nonce:\", *ticket_nonce, *ticket_nonce_len);\n    p += *ticket_nonce_len;\n\n    /* Ticket */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    ticket_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, ticket_len);\n    MBEDTLS_SSL_DEBUG_BUF(3, \"received ticket\", p, ticket_len);\n\n    /* Check if we previously received a ticket already. */\n    if (session->ticket != NULL || session->ticket_len > 0) {\n        mbedtls_free(session->ticket);\n        session->ticket = NULL;\n        session->ticket_len = 0;\n    }\n\n    if ((ticket = mbedtls_calloc(1, ticket_len)) == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"ticket alloc failed\"));\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n    memcpy(ticket, p, ticket_len);\n    p += ticket_len;\n    session->ticket = ticket;\n    session->ticket_len = ticket_len;\n\n    /* Clear all flags in ticket_flags */\n    mbedtls_ssl_tls13_session_clear_ticket_flags(\n        session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"ticket extension\", p, extensions_len);\n\n    ret = ssl_tls13_parse_new_session_ticket_exts(ssl, p, p + extensions_len);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1,\n                              \"ssl_tls13_parse_new_session_ticket_exts\",\n                              ret);\n        return ret;\n    }\n\n    return 0;\n}\n\n/* Non negative return values for ssl_tls13_postprocess_new_session_ticket().\n * - POSTPROCESS_NEW_SESSION_TICKET_SIGNAL, all good, we have to signal the\n *   application that a valid ticket has been received.\n * - POSTPROCESS_NEW_SESSION_TICKET_DISCARD, no fatal error, we keep the\n *   connection alive but we do not signal the ticket to the application.\n */\n#define POSTPROCESS_NEW_SESSION_TICKET_SIGNAL 0\n#define POSTPROCESS_NEW_SESSION_TICKET_DISCARD 1\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_postprocess_new_session_ticket(mbedtls_ssl_context *ssl,\n                                                    unsigned char *ticket_nonce,\n                                                    size_t ticket_nonce_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_session *session = ssl->session;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;\n    psa_algorithm_t psa_hash_alg;\n    int hash_length;\n\n    if (session->ticket_lifetime == 0) {\n        return POSTPROCESS_NEW_SESSION_TICKET_DISCARD;\n    }\n\n#if defined(MBEDTLS_HAVE_TIME)\n    /* Store ticket creation time */\n    session->ticket_reception_time = mbedtls_ms_time();\n#endif\n\n    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(session->ciphersuite);\n    if (ciphersuite_info == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    psa_hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac);\n    hash_length = PSA_HASH_LENGTH(psa_hash_alg);\n    if (hash_length == -1 ||\n        (size_t) hash_length > sizeof(session->resumption_key)) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"resumption_master_secret\",\n                          session->app_secrets.resumption_master_secret,\n                          hash_length);\n\n    /* Compute resumption key\n     *\n     *  HKDF-Expand-Label( resumption_master_secret,\n     *                    \"resumption\", ticket_nonce, Hash.length )\n     */\n    ret = mbedtls_ssl_tls13_hkdf_expand_label(\n        psa_hash_alg,\n        session->app_secrets.resumption_master_secret,\n        hash_length,\n        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(resumption),\n        ticket_nonce,\n        ticket_nonce_len,\n        session->resumption_key,\n        hash_length);\n\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(2,\n                              \"Creating the ticket-resumed PSK failed\",\n                              ret);\n        return ret;\n    }\n\n    session->resumption_key_len = hash_length;\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"Ticket-resumed PSK\",\n                          session->resumption_key,\n                          session->resumption_key_len);\n\n    /* Set ticket_flags depends on the selected key exchange modes */\n    mbedtls_ssl_tls13_session_set_ticket_flags(\n        session, ssl->conf->tls13_kex_modes);\n    MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags);\n\n    return POSTPROCESS_NEW_SESSION_TICKET_SIGNAL;\n}\n\n/*\n * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_process_new_session_ticket(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *buf;\n    size_t buf_len;\n    unsigned char *ticket_nonce;\n    size_t ticket_nonce_len;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse new session ticket\"));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(\n                             ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET,\n                             &buf, &buf_len));\n\n    /*\n     * We are about to update (maybe only partially) ticket data thus block\n     * any session export for the time being.\n     */\n    ssl->session->exported = 1;\n\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_new_session_ticket(\n                             ssl, buf, buf + buf_len,\n                             &ticket_nonce, &ticket_nonce_len));\n\n    MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_postprocess_new_session_ticket(\n                                 ssl, ticket_nonce, ticket_nonce_len));\n\n    switch (ret) {\n        case POSTPROCESS_NEW_SESSION_TICKET_SIGNAL:\n            /*\n             * All good, we have received a new valid ticket, session data can\n             * be exported now and we signal the ticket to the application.\n             */\n            ssl->session->exported = 0;\n            ret = MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET;\n            break;\n\n        case POSTPROCESS_NEW_SESSION_TICKET_DISCARD:\n            ret = 0;\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"Discard new session ticket\"));\n            break;\n\n        default:\n            ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);\n\ncleanup:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse new session ticket\"));\n    return ret;\n}\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\nint mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl)\n{\n    int ret = 0;\n\n    switch (ssl->state) {\n        case MBEDTLS_SSL_HELLO_REQUEST:\n            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);\n            break;\n\n        case MBEDTLS_SSL_CLIENT_HELLO:\n            ret = mbedtls_ssl_write_client_hello(ssl);\n            break;\n\n        case MBEDTLS_SSL_SERVER_HELLO:\n            ret = ssl_tls13_process_server_hello(ssl);\n            break;\n\n        case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS:\n            ret = ssl_tls13_process_encrypted_extensions(ssl);\n            break;\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n        case MBEDTLS_SSL_CERTIFICATE_REQUEST:\n            ret = ssl_tls13_process_certificate_request(ssl);\n            break;\n\n        case MBEDTLS_SSL_SERVER_CERTIFICATE:\n            ret = ssl_tls13_process_server_certificate(ssl);\n            break;\n\n        case MBEDTLS_SSL_CERTIFICATE_VERIFY:\n            ret = ssl_tls13_process_certificate_verify(ssl);\n            break;\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\n        case MBEDTLS_SSL_SERVER_FINISHED:\n            ret = ssl_tls13_process_server_finished(ssl);\n            break;\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n        case MBEDTLS_SSL_END_OF_EARLY_DATA:\n            ret = ssl_tls13_write_end_of_early_data(ssl);\n            break;\n#endif\n\n        case MBEDTLS_SSL_CLIENT_CERTIFICATE:\n            ret = ssl_tls13_write_client_certificate(ssl);\n            break;\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n        case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY:\n            ret = ssl_tls13_write_client_certificate_verify(ssl);\n            break;\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\n        case MBEDTLS_SSL_CLIENT_FINISHED:\n            ret = ssl_tls13_write_client_finished(ssl);\n            break;\n\n        case MBEDTLS_SSL_FLUSH_BUFFERS:\n            ret = ssl_tls13_flush_buffers(ssl);\n            break;\n\n        case MBEDTLS_SSL_HANDSHAKE_WRAPUP:\n            ret = ssl_tls13_handshake_wrapup(ssl);\n            break;\n\n            /*\n             * Injection of dummy-CCS's for middlebox compatibility\n             */\n#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)\n        case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO:\n            ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);\n            if (ret != 0) {\n                break;\n            }\n            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);\n            break;\n\n        case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED:\n            ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);\n            if (ret != 0) {\n                break;\n            }\n            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);\n            break;\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n        case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO:\n            ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);\n            if (ret == 0) {\n                mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO);\n\n                MBEDTLS_SSL_DEBUG_MSG(\n                    1, (\"Switch to early data keys for outbound traffic\"));\n                mbedtls_ssl_set_outbound_transform(\n                    ssl, ssl->handshake->transform_earlydata);\n                ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE;\n            }\n            break;\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n        case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET:\n            ret = ssl_tls13_process_new_session_ticket(ssl);\n            break;\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n        default:\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"invalid state %d\", ssl->state));\n            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    return ret;\n}\n\n#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_TLS1_3 */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_tls13_generic.c",
    "content": "/*\n *  TLS 1.3 functionality shared between client and server\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_TLS_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3)\n\n#include <string.h>\n\n#include \"mbedtls/error.h\"\n#include \"debug_internal.h\"\n#include \"mbedtls/oid.h\"\n#include \"mbedtls/platform.h\"\n#include \"mbedtls/constant_time.h\"\n#include \"psa/crypto.h\"\n#include \"mbedtls/psa_util.h\"\n\n#include \"ssl_misc.h\"\n#include \"ssl_tls13_invasive.h\"\n#include \"ssl_tls13_keys.h\"\n#include \"ssl_debug_helpers.h\"\n\n#include \"psa/crypto.h\"\n#include \"psa_util_internal.h\"\n\n/* Define a local translating function to save code size by not using too many\n * arguments in each translating place. */\nstatic int local_err_translation(psa_status_t status)\n{\n    return psa_status_to_mbedtls(status, psa_to_ssl_errors,\n                                 ARRAY_LENGTH(psa_to_ssl_errors),\n                                 psa_generic_status_to_mbedtls);\n}\n#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)\n\nint mbedtls_ssl_tls13_crypto_init(mbedtls_ssl_context *ssl)\n{\n    psa_status_t status = psa_crypto_init();\n    if (status != PSA_SUCCESS) {\n        (void) ssl; // unused when debugging is disabled\n        MBEDTLS_SSL_DEBUG_RET(1, \"psa_crypto_init\", status);\n    }\n    return PSA_TO_MBEDTLS_ERR(status);\n}\n\nconst uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[\n    MBEDTLS_SERVER_HELLO_RANDOM_LEN] =\n{ 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,\n  0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,\n  0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,\n  0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C };\n\nint mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl,\n                                          unsigned hs_type,\n                                          unsigned char **buf,\n                                          size_t *buf_len)\n{\n    int ret;\n\n    if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_read_record\", ret);\n        goto cleanup;\n    }\n\n    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ||\n        ssl->in_msg[0]  != hs_type) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Receive unexpected handshake message.\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,\n                                     MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE);\n        ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n        goto cleanup;\n    }\n\n    /*\n     * Jump handshake header (4 bytes, see Section 4 of RFC 8446).\n     *    ...\n     *    HandshakeType msg_type;\n     *    uint24 length;\n     *    ...\n     */\n    *buf = ssl->in_msg   + 4;\n    *buf_len = ssl->in_hslen - 4;\n\ncleanup:\n\n    return ret;\n}\n\nint mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts(\n    mbedtls_ssl_context *ssl,\n    const unsigned char *buf, const unsigned char *end,\n    const unsigned char **supported_versions_data,\n    const unsigned char **supported_versions_data_end)\n{\n    const unsigned char *p = buf;\n    size_t extensions_len;\n    const unsigned char *extensions_end;\n\n    *supported_versions_data = NULL;\n    *supported_versions_data_end = NULL;\n\n    /* Case of no extension */\n    if (p == end) {\n        return 0;\n    }\n\n    /* ...\n     * Extension extensions<x..2^16-1>;\n     * ...\n     * struct {\n     *      ExtensionType extension_type; (2 bytes)\n     *      opaque extension_data<0..2^16-1>;\n     * } Extension;\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n\n    /* Check extensions do not go beyond the buffer of data. */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);\n    extensions_end = p + extensions_len;\n\n    while (p < extensions_end) {\n        unsigned int extension_type;\n        size_t extension_data_len;\n\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);\n        extension_type = MBEDTLS_GET_UINT16_BE(p, 0);\n        extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);\n        p += 4;\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);\n\n        if (extension_type == MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS) {\n            *supported_versions_data = p;\n            *supported_versions_data_end = p + extension_data_len;\n            return 1;\n        }\n        p += extension_data_len;\n    }\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n/*\n * STATE HANDLING: Read CertificateVerify\n */\n/* Macro to express the maximum length of the verify structure.\n *\n * The structure is computed per TLS 1.3 specification as:\n *   - 64 bytes of octet 32,\n *   - 33 bytes for the context string\n *        (which is either \"TLS 1.3, client CertificateVerify\"\n *         or \"TLS 1.3, server CertificateVerify\"),\n *   - 1 byte for the octet 0x0, which serves as a separator,\n *   - 32 or 48 bytes for the Transcript-Hash(Handshake Context, Certificate)\n *     (depending on the size of the transcript_hash)\n *\n * This results in a total size of\n * - 130 bytes for a SHA256-based transcript hash, or\n *   (64 + 33 + 1 + 32 bytes)\n * - 146 bytes for a SHA384-based transcript hash.\n *   (64 + 33 + 1 + 48 bytes)\n *\n */\n#define SSL_VERIFY_STRUCT_MAX_SIZE  (64 +                          \\\n                                     33 +                          \\\n                                     1 +                          \\\n                                     MBEDTLS_TLS1_3_MD_MAX_SIZE    \\\n                                     )\n\n/*\n * The ssl_tls13_create_verify_structure() creates the verify structure.\n * As input, it requires the transcript hash.\n *\n * The caller has to ensure that the buffer has size at least\n * SSL_VERIFY_STRUCT_MAX_SIZE bytes.\n */\nstatic void ssl_tls13_create_verify_structure(const unsigned char *transcript_hash,\n                                              size_t transcript_hash_len,\n                                              unsigned char *verify_buffer,\n                                              size_t *verify_buffer_len,\n                                              int from)\n{\n    size_t idx;\n\n    /* RFC 8446, Section 4.4.3:\n     *\n     * The digital signature [in the CertificateVerify message] is then\n     * computed over the concatenation of:\n     * -  A string that consists of octet 32 (0x20) repeated 64 times\n     * -  The context string\n     * -  A single 0 byte which serves as the separator\n     * -  The content to be signed\n     */\n    memset(verify_buffer, 0x20, 64);\n    idx = 64;\n\n    if (from == MBEDTLS_SSL_IS_CLIENT) {\n        memcpy(verify_buffer + idx, mbedtls_ssl_tls13_labels.client_cv,\n               MBEDTLS_SSL_TLS1_3_LBL_LEN(client_cv));\n        idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(client_cv);\n    } else { /* from == MBEDTLS_SSL_IS_SERVER */\n        memcpy(verify_buffer + idx, mbedtls_ssl_tls13_labels.server_cv,\n               MBEDTLS_SSL_TLS1_3_LBL_LEN(server_cv));\n        idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(server_cv);\n    }\n\n    verify_buffer[idx++] = 0x0;\n\n    memcpy(verify_buffer + idx, transcript_hash, transcript_hash_len);\n    idx += transcript_hash_len;\n\n    *verify_buffer_len = idx;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_certificate_verify(mbedtls_ssl_context *ssl,\n                                              const unsigned char *buf,\n                                              const unsigned char *end,\n                                              const unsigned char *verify_buffer,\n                                              size_t verify_buffer_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    const unsigned char *p = buf;\n    uint16_t algorithm;\n    size_t signature_len;\n    mbedtls_pk_type_t sig_alg;\n    mbedtls_md_type_t md_alg;\n    psa_algorithm_t hash_alg = PSA_ALG_NONE;\n    unsigned char verify_hash[PSA_HASH_MAX_SIZE];\n    size_t verify_hash_len;\n\n    void const *options = NULL;\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)\n    mbedtls_pk_rsassa_pss_options rsassa_pss_options;\n#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */\n\n    /*\n     * struct {\n     *     SignatureScheme algorithm;\n     *     opaque signature<0..2^16-1>;\n     * } CertificateVerify;\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    algorithm = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n\n    /* RFC 8446 section 4.4.3\n     *\n     * If the CertificateVerify message is sent by a server, the signature\n     * algorithm MUST be one offered in the client's \"signature_algorithms\"\n     * extension unless no valid certificate chain can be produced without\n     * unsupported algorithms\n     *\n     * RFC 8446 section 4.4.2.2\n     *\n     * If the client cannot construct an acceptable chain using the provided\n     * certificates and decides to abort the handshake, then it MUST abort the\n     * handshake with an appropriate certificate-related alert\n     * (by default, \"unsupported_certificate\").\n     *\n     * Check if algorithm is an offered signature algorithm.\n     */\n    if (!mbedtls_ssl_sig_alg_is_offered(ssl, algorithm)) {\n        /* algorithm not in offered signature algorithms list */\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Received signature algorithm(%04x) is not \"\n                                  \"offered.\",\n                                  (unsigned int) algorithm));\n        goto error;\n    }\n\n    if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg(\n            algorithm, &sig_alg, &md_alg) != 0) {\n        goto error;\n    }\n\n    hash_alg = mbedtls_md_psa_alg_from_type(md_alg);\n    if (hash_alg == 0) {\n        goto error;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"Certificate Verify: Signature algorithm ( %04x )\",\n                              (unsigned int) algorithm));\n\n    /*\n     * Check the certificate's key type matches the signature alg\n     */\n    if (!mbedtls_pk_can_do(&ssl->session_negotiate->peer_cert->pk, sig_alg)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"signature algorithm doesn't match cert key\"));\n        goto error;\n    }\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    signature_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, signature_len);\n\n    status = psa_hash_compute(hash_alg,\n                              verify_buffer,\n                              verify_buffer_len,\n                              verify_hash,\n                              sizeof(verify_hash),\n                              &verify_hash_len);\n    if (status != PSA_SUCCESS) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"hash computation PSA error\", status);\n        goto error;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"verify hash\", verify_hash, verify_hash_len);\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)\n    if (sig_alg == MBEDTLS_PK_RSASSA_PSS) {\n        rsassa_pss_options.mgf1_hash_id = md_alg;\n\n        rsassa_pss_options.expected_salt_len = PSA_HASH_LENGTH(hash_alg);\n        options = (const void *) &rsassa_pss_options;\n    }\n#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */\n\n    if ((ret = mbedtls_pk_verify_ext(sig_alg, options,\n                                     &ssl->session_negotiate->peer_cert->pk,\n                                     md_alg, verify_hash, verify_hash_len,\n                                     p, signature_len)) == 0) {\n        return 0;\n    }\n    MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_pk_verify_ext\", ret);\n\nerror:\n    /* RFC 8446 section 4.4.3\n     *\n     * If the verification fails, the receiver MUST terminate the handshake\n     * with a \"decrypt_error\" alert.\n     */\n    MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR,\n                                 MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);\n    return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n\n}\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\nint mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl)\n{\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char verify_buffer[SSL_VERIFY_STRUCT_MAX_SIZE];\n    size_t verify_buffer_len;\n    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    size_t transcript_len;\n    unsigned char *buf;\n    size_t buf_len;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse certificate verify\"));\n\n    MBEDTLS_SSL_PROC_CHK(\n        mbedtls_ssl_tls13_fetch_handshake_msg(\n            ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf, &buf_len));\n\n    /* Need to calculate the hash of the transcript first\n     * before reading the message since otherwise it gets\n     * included in the transcript\n     */\n    ret = mbedtls_ssl_get_handshake_transcript(\n        ssl,\n        (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac,\n        transcript, sizeof(transcript),\n        &transcript_len);\n    if (ret != 0) {\n        MBEDTLS_SSL_PEND_FATAL_ALERT(\n            MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR,\n            MBEDTLS_ERR_SSL_INTERNAL_ERROR);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"handshake hash\", transcript, transcript_len);\n\n    /* Create verify structure */\n    ssl_tls13_create_verify_structure(transcript,\n                                      transcript_len,\n                                      verify_buffer,\n                                      &verify_buffer_len,\n                                      (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) ?\n                                      MBEDTLS_SSL_IS_SERVER :\n                                      MBEDTLS_SSL_IS_CLIENT);\n\n    /* Process the message contents */\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_verify(\n                             ssl, buf, buf + buf_len,\n                             verify_buffer, verify_buffer_len));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(\n                             ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY,\n                             buf, buf_len));\n\ncleanup:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse certificate verify\"));\n    MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_process_certificate_verify\", ret);\n    return ret;\n#else\n    ((void) ssl);\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n}\n\n/*\n *\n * STATE HANDLING: Incoming Certificate.\n *\n */\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n/*\n * Structure of Certificate message:\n *\n * enum {\n *     X509(0),\n *     RawPublicKey(2),\n *     (255)\n * } CertificateType;\n *\n * struct {\n *     select (certificate_type) {\n *         case RawPublicKey:\n *           * From RFC 7250 ASN.1_subjectPublicKeyInfo *\n *           opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;\n *         case X509:\n *           opaque cert_data<1..2^24-1>;\n *     };\n *     Extension extensions<0..2^16-1>;\n * } CertificateEntry;\n *\n * struct {\n *     opaque certificate_request_context<0..2^8-1>;\n *     CertificateEntry certificate_list<0..2^24-1>;\n * } Certificate;\n *\n */\n\n/* Parse certificate chain send by the server. */\nMBEDTLS_CHECK_RETURN_CRITICAL\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl,\n                                        const unsigned char *buf,\n                                        const unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t certificate_request_context_len = 0;\n    size_t certificate_list_len = 0;\n    const unsigned char *p = buf;\n    const unsigned char *certificate_list_end;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4);\n    certificate_request_context_len = p[0];\n    certificate_list_len = MBEDTLS_GET_UINT24_BE(p, 1);\n    p += 4;\n\n    /* In theory, the certificate list can be up to 2^24 Bytes, but we don't\n     * support anything beyond 2^16 = 64K.\n     */\n    if ((certificate_request_context_len != 0) ||\n        (certificate_list_len >= 0x10000)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad certificate message\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,\n                                     MBEDTLS_ERR_SSL_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /* In case we tried to reuse a session but it failed */\n    if (ssl->session_negotiate->peer_cert != NULL) {\n        mbedtls_x509_crt_free(ssl->session_negotiate->peer_cert);\n        mbedtls_free(ssl->session_negotiate->peer_cert);\n    }\n\n    /* This is used by ssl_tls13_validate_certificate() */\n    if (certificate_list_len == 0) {\n        ssl->session_negotiate->peer_cert = NULL;\n        ret = 0;\n        goto exit;\n    }\n\n    if ((ssl->session_negotiate->peer_cert =\n             mbedtls_calloc(1, sizeof(mbedtls_x509_crt))) == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"alloc( %\" MBEDTLS_PRINTF_SIZET \" bytes ) failed\",\n                                  sizeof(mbedtls_x509_crt)));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR,\n                                     MBEDTLS_ERR_SSL_ALLOC_FAILED);\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n    mbedtls_x509_crt_init(ssl->session_negotiate->peer_cert);\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, certificate_list_len);\n    certificate_list_end = p + certificate_list_len;\n    while (p < certificate_list_end) {\n        size_t cert_data_len, extensions_len;\n        const unsigned char *extensions_end;\n\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, 3);\n        cert_data_len = MBEDTLS_GET_UINT24_BE(p, 0);\n        p += 3;\n\n        /* In theory, the CRT can be up to 2^24 Bytes, but we don't support\n         * anything beyond 2^16 = 64K. Otherwise as in the TLS 1.2 code,\n         * check that we have a minimum of 128 bytes of data, this is not\n         * clear why we need that though.\n         */\n        if ((cert_data_len < 128) || (cert_data_len >= 0x10000)) {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"bad Certificate message\"));\n            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,\n                                         MBEDTLS_ERR_SSL_DECODE_ERROR);\n            return MBEDTLS_ERR_SSL_DECODE_ERROR;\n        }\n\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, cert_data_len);\n        ret = mbedtls_x509_crt_parse_der(ssl->session_negotiate->peer_cert,\n                                         p, cert_data_len);\n\n        switch (ret) {\n            case 0: /*ok*/\n                break;\n            case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND:\n                /* Ignore certificate with an unknown algorithm: maybe a\n                   prior certificate was already trusted. */\n                break;\n\n            case MBEDTLS_ERR_X509_ALLOC_FAILED:\n                MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR,\n                                             MBEDTLS_ERR_X509_ALLOC_FAILED);\n                MBEDTLS_SSL_DEBUG_RET(1, \" mbedtls_x509_crt_parse_der\", ret);\n                return ret;\n\n            case MBEDTLS_ERR_X509_UNKNOWN_VERSION:\n                MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT,\n                                             MBEDTLS_ERR_X509_UNKNOWN_VERSION);\n                MBEDTLS_SSL_DEBUG_RET(1, \" mbedtls_x509_crt_parse_der\", ret);\n                return ret;\n\n            default:\n                MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_BAD_CERT,\n                                             ret);\n                MBEDTLS_SSL_DEBUG_RET(1, \" mbedtls_x509_crt_parse_der\", ret);\n                return ret;\n        }\n\n        p += cert_data_len;\n\n        /* Certificate extensions length */\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, 2);\n        extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);\n        p += 2;\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, extensions_len);\n\n        extensions_end = p + extensions_len;\n        handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;\n\n        while (p < extensions_end) {\n            unsigned int extension_type;\n            size_t extension_data_len;\n\n            /*\n             * struct {\n             *     ExtensionType extension_type; (2 bytes)\n             *     opaque extension_data<0..2^16-1>;\n             * } Extension;\n             */\n            MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);\n            extension_type = MBEDTLS_GET_UINT16_BE(p, 0);\n            extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);\n            p += 4;\n\n            MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);\n\n            ret = mbedtls_ssl_tls13_check_received_extension(\n                ssl, MBEDTLS_SSL_HS_CERTIFICATE, extension_type,\n                MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CT);\n            if (ret != 0) {\n                return ret;\n            }\n\n            switch (extension_type) {\n                default:\n                    MBEDTLS_SSL_PRINT_EXT(\n                        3, MBEDTLS_SSL_HS_CERTIFICATE,\n                        extension_type, \"( ignored )\");\n                    break;\n            }\n\n            p += extension_data_len;\n        }\n\n        MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CERTIFICATE,\n                               handshake->received_extensions);\n    }\n\nexit:\n    /* Check that all the message is consumed. */\n    if (p != end) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad Certificate message\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,\n                                     MBEDTLS_ERR_SSL_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    MBEDTLS_SSL_DEBUG_CRT(3, \"peer certificate\",\n                          ssl->session_negotiate->peer_cert);\n\n    return ret;\n}\n#else\nMBEDTLS_CHECK_RETURN_CRITICAL\nMBEDTLS_STATIC_TESTABLE\nint mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl,\n                                        const unsigned char *buf,\n                                        const unsigned char *end)\n{\n    ((void) ssl);\n    ((void) buf);\n    ((void) end);\n    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n}\n#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n/* Validate certificate chain sent by the server. */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl)\n{\n    /* Authmode: precedence order is SNI if used else configuration */\n#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET\n                       ? ssl->handshake->sni_authmode\n                       : ssl->conf->authmode;\n#else\n    const int authmode = ssl->conf->authmode;\n#endif\n\n    /*\n     * If the peer hasn't sent a certificate ( i.e. it sent\n     * an empty certificate chain ), this is reflected in the peer CRT\n     * structure being unset.\n     * Check for that and handle it depending on the\n     * authentication mode.\n     */\n    if (ssl->session_negotiate->peer_cert == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"peer has no certificate\"));\n\n#if defined(MBEDTLS_SSL_SRV_C)\n        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {\n            /* The client was asked for a certificate but didn't send\n             * one. The client should know what's going on, so we\n             * don't send an alert.\n             */\n            ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;\n            if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL) {\n                return 0;\n            } else {\n                MBEDTLS_SSL_PEND_FATAL_ALERT(\n                    MBEDTLS_SSL_ALERT_MSG_NO_CERT,\n                    MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE);\n                return MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE;\n            }\n        }\n#endif /* MBEDTLS_SSL_SRV_C */\n\n#if defined(MBEDTLS_SSL_CLI_C)\n        /* Regardless of authmode, the server is not allowed to send an empty\n         * certificate chain. (Last paragraph before 4.4.2.1 in RFC 8446: \"The\n         * server's certificate_list MUST always be non-empty.\") With authmode\n         * optional/none, we continue the handshake if we can't validate the\n         * server's cert, but we still break it if no certificate was sent. */\n        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {\n            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_NO_CERT,\n                                         MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE);\n            return MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE;\n        }\n#endif /* MBEDTLS_SSL_CLI_C */\n    }\n\n    return mbedtls_ssl_verify_certificate(ssl, authmode,\n                                          ssl->session_negotiate->peer_cert,\n                                          NULL, NULL);\n}\n#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl)\n{\n    ((void) ssl);\n    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n}\n#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\nint mbedtls_ssl_tls13_process_certificate(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse certificate\"));\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n    unsigned char *buf;\n    size_t buf_len;\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(\n                             ssl, MBEDTLS_SSL_HS_CERTIFICATE,\n                             &buf, &buf_len));\n\n    /* Parse the certificate chain sent by the peer. */\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_parse_certificate(ssl, buf,\n                                                             buf + buf_len));\n    /* Validate the certificate chain and set the verification results. */\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_validate_certificate(ssl));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(\n                             ssl, MBEDTLS_SSL_HS_CERTIFICATE, buf, buf_len));\n\ncleanup:\n#else /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n    (void) ssl;\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse certificate\"));\n    return ret;\n}\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n/*\n *  enum {\n *        X509(0),\n *        RawPublicKey(2),\n *        (255)\n *    } CertificateType;\n *\n *    struct {\n *        select (certificate_type) {\n *            case RawPublicKey:\n *              // From RFC 7250 ASN.1_subjectPublicKeyInfo\n *              opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;\n *\n *            case X509:\n *              opaque cert_data<1..2^24-1>;\n *        };\n *        Extension extensions<0..2^16-1>;\n *    } CertificateEntry;\n *\n *    struct {\n *        opaque certificate_request_context<0..2^8-1>;\n *        CertificateEntry certificate_list<0..2^24-1>;\n *    } Certificate;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_certificate_body(mbedtls_ssl_context *ssl,\n                                            unsigned char *buf,\n                                            unsigned char *end,\n                                            size_t *out_len)\n{\n    const mbedtls_x509_crt *crt = mbedtls_ssl_own_cert(ssl);\n    unsigned char *p = buf;\n    unsigned char *certificate_request_context =\n        ssl->handshake->certificate_request_context;\n    unsigned char certificate_request_context_len =\n        ssl->handshake->certificate_request_context_len;\n    unsigned char *p_certificate_list_len;\n\n\n    /* ...\n     * opaque certificate_request_context<0..2^8-1>;\n     * ...\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, certificate_request_context_len + 1);\n    *p++ = certificate_request_context_len;\n    if (certificate_request_context_len > 0) {\n        memcpy(p, certificate_request_context, certificate_request_context_len);\n        p += certificate_request_context_len;\n    }\n\n    /* ...\n     * CertificateEntry certificate_list<0..2^24-1>;\n     * ...\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 3);\n    p_certificate_list_len = p;\n    p += 3;\n\n    MBEDTLS_SSL_DEBUG_CRT(3, \"own certificate\", crt);\n\n    while (crt != NULL) {\n        size_t cert_data_len = crt->raw.len;\n\n        MBEDTLS_SSL_CHK_BUF_PTR(p, end, cert_data_len + 3 + 2);\n        MBEDTLS_PUT_UINT24_BE(cert_data_len, p, 0);\n        p += 3;\n\n        memcpy(p, crt->raw.p, cert_data_len);\n        p += cert_data_len;\n        crt = crt->next;\n\n        /* Currently, we don't have any certificate extensions defined.\n         * Hence, we are sending an empty extension with length zero.\n         */\n        MBEDTLS_PUT_UINT16_BE(0, p, 0);\n        p += 2;\n    }\n\n    MBEDTLS_PUT_UINT24_BE(p - p_certificate_list_len - 3,\n                          p_certificate_list_len, 0);\n\n    *out_len = p - buf;\n\n    MBEDTLS_SSL_PRINT_EXTS(\n        3, MBEDTLS_SSL_HS_CERTIFICATE, ssl->handshake->sent_extensions);\n\n    return 0;\n}\n\nint mbedtls_ssl_tls13_write_certificate(mbedtls_ssl_context *ssl)\n{\n    int ret;\n    unsigned char *buf;\n    size_t buf_len, msg_len;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write certificate\"));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(\n                             ssl, MBEDTLS_SSL_HS_CERTIFICATE, &buf, &buf_len));\n\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_body(ssl,\n                                                          buf,\n                                                          buf + buf_len,\n                                                          &msg_len));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(\n                             ssl, MBEDTLS_SSL_HS_CERTIFICATE, buf, msg_len));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(\n                             ssl, buf_len, msg_len));\ncleanup:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write certificate\"));\n    return ret;\n}\n\n/*\n * STATE HANDLING: Output Certificate Verify\n */\nint mbedtls_ssl_tls13_check_sig_alg_cert_key_match(uint16_t sig_alg,\n                                                   mbedtls_pk_context *key)\n{\n    mbedtls_pk_type_t pk_type = (mbedtls_pk_type_t) mbedtls_ssl_sig_from_pk(key);\n    size_t key_size = mbedtls_pk_get_bitlen(key);\n\n    switch (pk_type) {\n        case MBEDTLS_SSL_SIG_ECDSA:\n            switch (key_size) {\n                case 256:\n                    return\n                        sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256;\n\n                case 384:\n                    return\n                        sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384;\n\n                case 521:\n                    return\n                        sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512;\n                default:\n                    break;\n            }\n            break;\n\n        case MBEDTLS_SSL_SIG_RSA:\n            switch (sig_alg) {\n                case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: /* Intentional fallthrough */\n                case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: /* Intentional fallthrough */\n                case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512:\n                    return 1;\n\n                default:\n                    break;\n            }\n            break;\n\n        default:\n            break;\n    }\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_certificate_verify_body(mbedtls_ssl_context *ssl,\n                                                   unsigned char *buf,\n                                                   unsigned char *end,\n                                                   size_t *out_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = buf;\n    mbedtls_pk_context *own_key;\n\n    unsigned char handshake_hash[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    size_t handshake_hash_len;\n    unsigned char verify_buffer[SSL_VERIFY_STRUCT_MAX_SIZE];\n    size_t verify_buffer_len;\n\n    uint16_t *sig_alg = ssl->handshake->received_sig_algs;\n    size_t signature_len = 0;\n\n    *out_len = 0;\n\n    own_key = mbedtls_ssl_own_key(ssl);\n    if (own_key == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    ret = mbedtls_ssl_get_handshake_transcript(\n        ssl, (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac,\n        handshake_hash, sizeof(handshake_hash), &handshake_hash_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"handshake hash\",\n                          handshake_hash,\n                          handshake_hash_len);\n\n    ssl_tls13_create_verify_structure(handshake_hash, handshake_hash_len,\n                                      verify_buffer, &verify_buffer_len,\n                                      ssl->conf->endpoint);\n\n    /*\n     *  struct {\n     *    SignatureScheme algorithm;\n     *    opaque signature<0..2^16-1>;\n     *  } CertificateVerify;\n     */\n    /* Check there is space for the algorithm identifier (2 bytes) and the\n     * signature length (2 bytes).\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4);\n\n    for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) {\n        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n        mbedtls_pk_type_t pk_type = MBEDTLS_PK_NONE;\n        mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;\n        psa_algorithm_t psa_algorithm = PSA_ALG_NONE;\n        unsigned char verify_hash[PSA_HASH_MAX_SIZE];\n        size_t verify_hash_len;\n\n        if (!mbedtls_ssl_sig_alg_is_offered(ssl, *sig_alg)) {\n            continue;\n        }\n\n        if (!mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(*sig_alg)) {\n            continue;\n        }\n\n        if (!mbedtls_ssl_tls13_check_sig_alg_cert_key_match(*sig_alg, own_key)) {\n            continue;\n        }\n\n        if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg(\n                *sig_alg, &pk_type, &md_alg) != 0) {\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        /* Hash verify buffer with indicated hash function */\n        psa_algorithm = mbedtls_md_psa_alg_from_type(md_alg);\n        status = psa_hash_compute(psa_algorithm,\n                                  verify_buffer,\n                                  verify_buffer_len,\n                                  verify_hash, sizeof(verify_hash),\n                                  &verify_hash_len);\n        if (status != PSA_SUCCESS) {\n            return PSA_TO_MBEDTLS_ERR(status);\n        }\n\n        MBEDTLS_SSL_DEBUG_BUF(3, \"verify hash\", verify_hash, verify_hash_len);\n\n        if ((ret = mbedtls_pk_sign_ext(pk_type, own_key,\n                                       md_alg, verify_hash, verify_hash_len,\n                                       p + 4, (size_t) (end - (p + 4)), &signature_len,\n                                       ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"CertificateVerify signature failed with %s\",\n                                      mbedtls_ssl_sig_alg_to_str(*sig_alg)));\n            MBEDTLS_SSL_DEBUG_RET(2, \"mbedtls_pk_sign_ext\", ret);\n\n            /* The signature failed. This is possible if the private key\n             * was not suitable for the signature operation as purposely we\n             * did not check its suitability completely. Let's try with\n             * another signature algorithm.\n             */\n            continue;\n        }\n\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"CertificateVerify signature with %s\",\n                                  mbedtls_ssl_sig_alg_to_str(*sig_alg)));\n\n        break;\n    }\n\n    if (*sig_alg == MBEDTLS_TLS1_3_SIG_NONE) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"no suitable signature algorithm\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,\n                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    MBEDTLS_PUT_UINT16_BE(*sig_alg, p, 0);\n    MBEDTLS_PUT_UINT16_BE(signature_len, p, 2);\n\n    *out_len = 4 + signature_len;\n\n    return 0;\n}\n\nint mbedtls_ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl)\n{\n    int ret = 0;\n    unsigned char *buf;\n    size_t buf_len, msg_len;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write certificate verify\"));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(\n                             ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY,\n                             &buf, &buf_len));\n\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_verify_body(\n                             ssl, buf, buf + buf_len, &msg_len));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(\n                             ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY,\n                             buf, msg_len));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(\n                             ssl, buf_len, msg_len));\n\ncleanup:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write certificate verify\"));\n    return ret;\n}\n\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\n/*\n *\n * STATE HANDLING: Incoming Finished message.\n */\n/*\n * Implementation\n */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_preprocess_finished_message(mbedtls_ssl_context *ssl)\n{\n    int ret;\n\n    ret = mbedtls_ssl_tls13_calculate_verify_data(\n        ssl,\n        ssl->handshake->state_local.finished_in.digest,\n        sizeof(ssl->handshake->state_local.finished_in.digest),\n        &ssl->handshake->state_local.finished_in.digest_len,\n        ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ?\n        MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_calculate_verify_data\", ret);\n        return ret;\n    }\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_finished_message(mbedtls_ssl_context *ssl,\n                                            const unsigned char *buf,\n                                            const unsigned char *end)\n{\n    /*\n     * struct {\n     *     opaque verify_data[Hash.length];\n     * } Finished;\n     */\n    const unsigned char *expected_verify_data =\n        ssl->handshake->state_local.finished_in.digest;\n    size_t expected_verify_data_len =\n        ssl->handshake->state_local.finished_in.digest_len;\n    /* Structural validation */\n    if ((size_t) (end - buf) != expected_verify_data_len) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad finished message\"));\n\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,\n                                     MBEDTLS_ERR_SSL_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"verify_data (self-computed):\",\n                          expected_verify_data,\n                          expected_verify_data_len);\n    MBEDTLS_SSL_DEBUG_BUF(4, \"verify_data (received message):\", buf,\n                          expected_verify_data_len);\n\n    /* Semantic validation */\n    if (mbedtls_ct_memcmp(buf,\n                          expected_verify_data,\n                          expected_verify_data_len) != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad finished message\"));\n\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR,\n                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n    return 0;\n}\n\nint mbedtls_ssl_tls13_process_finished_message(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *buf;\n    size_t buf_len;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse finished message\"));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(\n                             ssl, MBEDTLS_SSL_HS_FINISHED, &buf, &buf_len));\n\n    /* Preprocessing step: Compute handshake digest */\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_preprocess_finished_message(ssl));\n\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_finished_message(\n                             ssl, buf, buf + buf_len));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(\n                             ssl, MBEDTLS_SSL_HS_FINISHED, buf, buf_len));\n\ncleanup:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse finished message\"));\n    return ret;\n}\n\n/*\n *\n * STATE HANDLING: Write and send Finished message.\n *\n */\n/*\n * Implement\n */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_prepare_finished_message(mbedtls_ssl_context *ssl)\n{\n    int ret;\n\n    /* Compute transcript of handshake up to now. */\n    ret = mbedtls_ssl_tls13_calculate_verify_data(ssl,\n                                                  ssl->handshake->state_local.finished_out.digest,\n                                                  sizeof(ssl->handshake->state_local.finished_out.\n                                                         digest),\n                                                  &ssl->handshake->state_local.finished_out.digest_len,\n                                                  ssl->conf->endpoint);\n\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"calculate_verify_data failed\", ret);\n        return ret;\n    }\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_finished_message_body(mbedtls_ssl_context *ssl,\n                                                 unsigned char *buf,\n                                                 unsigned char *end,\n                                                 size_t *out_len)\n{\n    size_t verify_data_len = ssl->handshake->state_local.finished_out.digest_len;\n    /*\n     * struct {\n     *     opaque verify_data[Hash.length];\n     * } Finished;\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(buf, end, verify_data_len);\n\n    memcpy(buf, ssl->handshake->state_local.finished_out.digest,\n           verify_data_len);\n\n    *out_len = verify_data_len;\n    return 0;\n}\n\n/* Main entry point: orchestrates the other functions */\nint mbedtls_ssl_tls13_write_finished_message(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *buf;\n    size_t buf_len, msg_len;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write finished message\"));\n\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_finished_message(ssl));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl,\n                                                         MBEDTLS_SSL_HS_FINISHED, &buf, &buf_len));\n\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_finished_message_body(\n                             ssl, buf, buf + buf_len, &msg_len));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,\n                                                            MBEDTLS_SSL_HS_FINISHED, buf, msg_len));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(\n                             ssl, buf_len, msg_len));\ncleanup:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write finished message\"));\n    return ret;\n}\n\nvoid mbedtls_ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl)\n{\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"=> handshake wrapup\"));\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"Switch to application keys for inbound traffic\"));\n    mbedtls_ssl_set_inbound_transform(ssl, ssl->transform_application);\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"Switch to application keys for outbound traffic\"));\n    mbedtls_ssl_set_outbound_transform(ssl, ssl->transform_application);\n\n    /*\n     * Free the previous session and switch to the current one.\n     */\n    if (ssl->session) {\n        mbedtls_ssl_session_free(ssl->session);\n        mbedtls_free(ssl->session);\n    }\n    ssl->session = ssl->session_negotiate;\n    ssl->session_negotiate = NULL;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"<= handshake wrapup\"));\n}\n\n/*\n *\n * STATE HANDLING: Write ChangeCipherSpec\n *\n */\n#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_change_cipher_spec_body(mbedtls_ssl_context *ssl,\n                                                   unsigned char *buf,\n                                                   unsigned char *end,\n                                                   size_t *olen)\n{\n    ((void) ssl);\n\n    MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 1);\n    buf[0] = 1;\n    *olen = 1;\n\n    return 0;\n}\n\nint mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write change cipher spec\"));\n\n    /* Only one CCS to send. */\n    if (ssl->handshake->ccs_sent) {\n        ret = 0;\n        goto cleanup;\n    }\n\n    /* Write CCS message */\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_change_cipher_spec_body(\n                             ssl, ssl->out_msg,\n                             ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN,\n                             &ssl->out_msglen));\n\n    ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;\n\n    /* Dispatch message */\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_record(ssl, 0));\n\n    ssl->handshake->ccs_sent = 1;\n\ncleanup:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write change cipher spec\"));\n    return ret;\n}\n\n#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */\n\n/* Early Data Indication Extension\n *\n * struct {\n *   select ( Handshake.msg_type ) {\n *     case new_session_ticket:   uint32 max_early_data_size;\n *     case client_hello:         Empty;\n *     case encrypted_extensions: Empty;\n *   };\n * } EarlyDataIndication;\n */\n#if defined(MBEDTLS_SSL_EARLY_DATA)\nint mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl,\n                                           int in_new_session_ticket,\n                                           unsigned char *buf,\n                                           const unsigned char *end,\n                                           size_t *out_len)\n{\n    unsigned char *p = buf;\n\n#if defined(MBEDTLS_SSL_SRV_C)\n    const size_t needed = in_new_session_ticket ? 8 : 4;\n#else\n    const size_t needed = 4;\n    ((void) in_new_session_ticket);\n#endif\n\n    *out_len = 0;\n\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, needed);\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EARLY_DATA, p, 0);\n    MBEDTLS_PUT_UINT16_BE(needed - 4, p, 2);\n\n#if defined(MBEDTLS_SSL_SRV_C)\n    if (in_new_session_ticket) {\n        MBEDTLS_PUT_UINT32_BE(ssl->conf->max_early_data_size, p, 4);\n        MBEDTLS_SSL_DEBUG_MSG(\n            4, (\"Sent max_early_data_size=%u\",\n                (unsigned int) ssl->conf->max_early_data_size));\n    }\n#endif\n\n    *out_len = needed;\n\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_EARLY_DATA);\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_SRV_C)\nint mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl,\n                                           size_t early_data_len)\n{\n    /*\n     * This function should be called only while an handshake is in progress\n     * and thus a session under negotiation. Add a sanity check to detect a\n     * misuse.\n     */\n    if (ssl->session_negotiate == NULL) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    /* RFC 8446 section 4.6.1\n     *\n     * A server receiving more than max_early_data_size bytes of 0-RTT data\n     * SHOULD terminate the connection with an \"unexpected_message\" alert.\n     * Note that if it is still possible to send early_data_len bytes of early\n     * data, it means that early_data_len is smaller than max_early_data_size\n     * (type uint32_t) and can fit in an uint32_t. We use this further\n     * down.\n     */\n    if (early_data_len >\n        (ssl->session_negotiate->max_early_data_size -\n         ssl->total_early_data_size)) {\n\n        MBEDTLS_SSL_DEBUG_MSG(\n            2, (\"EarlyData: Too much early data received, \"\n                \"%lu + %\" MBEDTLS_PRINTF_SIZET \" > %lu\",\n                (unsigned long) ssl->total_early_data_size,\n                early_data_len,\n                (unsigned long) ssl->session_negotiate->max_early_data_size));\n\n        MBEDTLS_SSL_PEND_FATAL_ALERT(\n            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,\n            MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE);\n        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n    }\n\n    /*\n     * early_data_len has been checked to be less than max_early_data_size\n     * that is uint32_t. Its cast to an uint32_t below is thus safe. We need\n     * the cast to appease some compilers.\n     */\n    ssl->total_early_data_size += (uint32_t) early_data_len;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_SRV_C */\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n/* Reset SSL context and update hash for handling HRR.\n *\n * Replace Transcript-Hash(X) by\n * Transcript-Hash( message_hash     ||\n *                 00 00 Hash.length ||\n *                 X )\n * A few states of the handshake are preserved, including:\n *   - session ID\n *   - session ticket\n *   - negotiated ciphersuite\n */\nint mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char hash_transcript[PSA_HASH_MAX_SIZE + 4];\n    size_t hash_len;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        ssl->handshake->ciphersuite_info;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"Reset SSL session for HRR\"));\n\n    ret = mbedtls_ssl_get_handshake_transcript(ssl, (mbedtls_md_type_t) ciphersuite_info->mac,\n                                               hash_transcript + 4,\n                                               PSA_HASH_MAX_SIZE,\n                                               &hash_len);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_get_handshake_transcript\", ret);\n        return ret;\n    }\n\n    hash_transcript[0] = MBEDTLS_SSL_HS_MESSAGE_HASH;\n    hash_transcript[1] = 0;\n    hash_transcript[2] = 0;\n    hash_transcript[3] = (unsigned char) hash_len;\n\n    hash_len += 4;\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"Truncated handshake transcript\",\n                          hash_transcript, hash_len);\n\n    /* Reset running hash and replace it with a hash of the transcript */\n    ret = mbedtls_ssl_reset_checksum(ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_reset_checksum\", ret);\n        return ret;\n    }\n    ret = ssl->handshake->update_checksum(ssl, hash_transcript, hash_len);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"update_checksum\", ret);\n        return ret;\n    }\n\n    return ret;\n}\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)\n\nint mbedtls_ssl_tls13_read_public_xxdhe_share(mbedtls_ssl_context *ssl,\n                                              const unsigned char *buf,\n                                              size_t buf_len)\n{\n    uint8_t *p = (uint8_t *) buf;\n    const uint8_t *end = buf + buf_len;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n    /* Get size of the TLS opaque key_exchange field of the KeyShareEntry struct. */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    uint16_t peerkey_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n\n    /* Check if key size is consistent with given buffer length. */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, peerkey_len);\n\n    /* Store peer's ECDH/FFDH public key. */\n    if (peerkey_len > sizeof(handshake->xxdh_psa_peerkey)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Invalid public key length: %u > %\" MBEDTLS_PRINTF_SIZET,\n                                  (unsigned) peerkey_len,\n                                  sizeof(handshake->xxdh_psa_peerkey)));\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n    memcpy(handshake->xxdh_psa_peerkey, p, peerkey_len);\n    handshake->xxdh_psa_peerkey_len = peerkey_len;\n\n    return 0;\n}\n\n#if defined(PSA_WANT_ALG_FFDH)\nstatic psa_status_t  mbedtls_ssl_get_psa_ffdh_info_from_tls_id(\n    uint16_t tls_id, size_t *bits, psa_key_type_t *key_type)\n{\n    switch (tls_id) {\n#if defined(PSA_WANT_DH_RFC7919_2048)\n        case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048:\n            *bits = 2048;\n            *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);\n            return PSA_SUCCESS;\n#endif /* PSA_WANT_DH_RFC7919_2048 */\n#if defined(PSA_WANT_DH_RFC7919_3072)\n        case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072:\n            *bits = 3072;\n            *key_type =  PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);\n            return PSA_SUCCESS;\n#endif /* PSA_WANT_DH_RFC7919_3072 */\n#if defined(PSA_WANT_DH_RFC7919_4096)\n        case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096:\n            *bits = 4096;\n            *key_type =  PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);\n            return PSA_SUCCESS;\n#endif /* PSA_WANT_DH_RFC7919_4096 */\n#if defined(PSA_WANT_DH_RFC7919_6144)\n        case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144:\n            *bits = 6144;\n            *key_type =  PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);\n            return PSA_SUCCESS;\n#endif /* PSA_WANT_DH_RFC7919_6144 */\n#if defined(PSA_WANT_DH_RFC7919_8192)\n        case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192:\n            *bits = 8192;\n            *key_type =  PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);\n            return PSA_SUCCESS;\n#endif /* PSA_WANT_DH_RFC7919_8192 */\n        default:\n            return PSA_ERROR_NOT_SUPPORTED;\n    }\n}\n#endif /* PSA_WANT_ALG_FFDH */\n\nint mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange(\n    mbedtls_ssl_context *ssl,\n    uint16_t named_group,\n    unsigned char *buf,\n    unsigned char *end,\n    size_t *out_len)\n{\n    psa_status_t status = PSA_ERROR_GENERIC_ERROR;\n    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    psa_key_attributes_t key_attributes;\n    size_t own_pubkey_len;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n    size_t bits = 0;\n    psa_key_type_t key_type = PSA_KEY_TYPE_NONE;\n    psa_algorithm_t alg = PSA_ALG_NONE;\n    size_t buf_size = (size_t) (end - buf);\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"Perform PSA-based ECDH/FFDH computation.\"));\n\n    /* Convert EC's TLS ID to PSA key type. */\n#if defined(PSA_WANT_ALG_ECDH)\n    if (mbedtls_ssl_get_psa_curve_info_from_tls_id(\n            named_group, &key_type, &bits) == PSA_SUCCESS) {\n        alg = PSA_ALG_ECDH;\n    }\n#endif\n#if defined(PSA_WANT_ALG_FFDH)\n    if (mbedtls_ssl_get_psa_ffdh_info_from_tls_id(named_group, &bits,\n                                                  &key_type) == PSA_SUCCESS) {\n        alg = PSA_ALG_FFDH;\n    }\n#endif\n\n    if (key_type == PSA_KEY_TYPE_NONE) {\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    if (buf_size < PSA_BITS_TO_BYTES(bits)) {\n        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n    }\n\n    handshake->xxdh_psa_type = key_type;\n    ssl->handshake->xxdh_psa_bits = bits;\n\n    key_attributes = psa_key_attributes_init();\n    psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);\n    psa_set_key_algorithm(&key_attributes, alg);\n    psa_set_key_type(&key_attributes, handshake->xxdh_psa_type);\n    psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits);\n\n    /* Generate ECDH/FFDH private key. */\n    status = psa_generate_key(&key_attributes,\n                              &handshake->xxdh_psa_privkey);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        MBEDTLS_SSL_DEBUG_RET(1, \"psa_generate_key\", ret);\n        return ret;\n\n    }\n\n    /* Export the public part of the ECDH/FFDH private key from PSA. */\n    status = psa_export_public_key(handshake->xxdh_psa_privkey,\n                                   buf, buf_size,\n                                   &own_pubkey_len);\n\n    if (status != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        MBEDTLS_SSL_DEBUG_RET(1, \"psa_export_public_key\", ret);\n        return ret;\n    }\n\n    *out_len = own_pubkey_len;\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */\n\n/* RFC 8446 section 4.2\n *\n * If an implementation receives an extension which it recognizes and which is\n * not specified for the message in which it appears, it MUST abort the handshake\n * with an \"illegal_parameter\" alert.\n *\n */\nint mbedtls_ssl_tls13_check_received_extension(\n    mbedtls_ssl_context *ssl,\n    int hs_msg_type,\n    unsigned int received_extension_type,\n    uint32_t hs_msg_allowed_extensions_mask)\n{\n    uint32_t extension_mask = mbedtls_ssl_get_extension_mask(\n        received_extension_type);\n\n    MBEDTLS_SSL_PRINT_EXT(\n        3, hs_msg_type, received_extension_type, \"received\");\n\n    if ((extension_mask & hs_msg_allowed_extensions_mask) == 0) {\n        MBEDTLS_SSL_PRINT_EXT(\n            3, hs_msg_type, received_extension_type, \"is illegal\");\n        MBEDTLS_SSL_PEND_FATAL_ALERT(\n            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n            MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    ssl->handshake->received_extensions |= extension_mask;\n    /*\n     * If it is a message containing extension responses, check that we\n     * previously sent the extension.\n     */\n    switch (hs_msg_type) {\n        case MBEDTLS_SSL_HS_SERVER_HELLO:\n        case MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST:\n        case MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS:\n        case MBEDTLS_SSL_HS_CERTIFICATE:\n            /* Check if the received extension is sent by peer message.*/\n            if ((ssl->handshake->sent_extensions & extension_mask) != 0) {\n                return 0;\n            }\n            break;\n        default:\n            return 0;\n    }\n\n    MBEDTLS_SSL_PRINT_EXT(\n        3, hs_msg_type, received_extension_type, \"is unsupported\");\n    MBEDTLS_SSL_PEND_FATAL_ALERT(\n        MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT,\n        MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION);\n    return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;\n}\n\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n\n/* RFC 8449, section 4:\n *\n * The ExtensionData of the \"record_size_limit\" extension is\n * RecordSizeLimit:\n *     uint16 RecordSizeLimit;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl,\n                                                  const unsigned char *buf,\n                                                  const unsigned char *end)\n{\n    const unsigned char *p = buf;\n    uint16_t record_size_limit;\n    const size_t extension_data_len = end - buf;\n\n    if (extension_data_len !=\n        MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH) {\n        MBEDTLS_SSL_DEBUG_MSG(2,\n                              (\"record_size_limit extension has invalid length: %\"\n                               MBEDTLS_PRINTF_SIZET \" Bytes\",\n                               extension_data_len));\n\n        MBEDTLS_SSL_PEND_FATAL_ALERT(\n            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n            MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    record_size_limit = MBEDTLS_GET_UINT16_BE(p, 0);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"RecordSizeLimit: %u Bytes\", record_size_limit));\n\n    /* RFC 8449, section 4:\n     *\n     * Endpoints MUST NOT send a \"record_size_limit\" extension with a value\n     * smaller than 64.  An endpoint MUST treat receipt of a smaller value\n     * as a fatal error and generate an \"illegal_parameter\" alert.\n     */\n    if (record_size_limit < MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Invalid record size limit : %u Bytes\",\n                                  record_size_limit));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(\n            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n            MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n    ssl->session_negotiate->record_size_limit = record_size_limit;\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_write_record_size_limit_ext(mbedtls_ssl_context *ssl,\n                                                  unsigned char *buf,\n                                                  const unsigned char *end,\n                                                  size_t *out_len)\n{\n    unsigned char *p = buf;\n    *out_len = 0;\n\n    MBEDTLS_STATIC_ASSERT(MBEDTLS_SSL_IN_CONTENT_LEN >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN,\n                          \"MBEDTLS_SSL_IN_CONTENT_LEN is less than the \"\n                          \"minimum record size limit\");\n\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT, p, 0);\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH,\n                          p, 2);\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_IN_CONTENT_LEN, p, 4);\n\n    *out_len = 6;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"Sent RecordSizeLimit: %d Bytes\",\n                              MBEDTLS_SSL_IN_CONTENT_LEN));\n\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT);\n\n    return 0;\n}\n\n#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */\n\n#endif /* MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_PROTO_TLS1_3 */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_tls13_invasive.h",
    "content": "/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_SSL_TLS13_INVASIVE_H\n#define MBEDTLS_SSL_TLS13_INVASIVE_H\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n\n#include \"psa/crypto.h\"\n\n#if defined(MBEDTLS_TEST_HOOKS)\nint mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl,\n                                        const unsigned char *buf,\n                                        const unsigned char *end);\n#endif /* MBEDTLS_TEST_HOOKS */\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#endif /* MBEDTLS_SSL_TLS13_INVASIVE_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_tls13_keys.c",
    "content": "/*\n *  TLS 1.3 key schedule\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n\n#include <stdint.h>\n#include <string.h>\n\n#include \"mbedtls/hkdf.h\"\n#include \"debug_internal.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/platform.h\"\n\n#include \"ssl_misc.h\"\n#include \"ssl_tls13_keys.h\"\n#include \"ssl_tls13_invasive.h\"\n\n#include \"psa/crypto.h\"\n#include \"mbedtls/psa_util.h\"\n\n/* Define a local translating function to save code size by not using too many\n * arguments in each translating place. */\nstatic int local_err_translation(psa_status_t status)\n{\n    return psa_status_to_mbedtls(status, psa_to_ssl_errors,\n                                 ARRAY_LENGTH(psa_to_ssl_errors),\n                                 psa_generic_status_to_mbedtls);\n}\n#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)\n\n#define MBEDTLS_SSL_TLS1_3_LABEL(name, string)       \\\n    .name = string,\n\nstruct mbedtls_ssl_tls13_labels_struct const mbedtls_ssl_tls13_labels =\n{\n    /* This seems to work in C, despite the string literal being one\n     * character too long due to the 0-termination. */\n    MBEDTLS_SSL_TLS1_3_LABEL_LIST\n};\n\n#undef MBEDTLS_SSL_TLS1_3_LABEL\n\n/*\n * This function creates a HkdfLabel structure used in the TLS 1.3 key schedule.\n *\n * The HkdfLabel is specified in RFC 8446 as follows:\n *\n * struct HkdfLabel {\n *   uint16 length;            // Length of expanded key material\n *   opaque label<7..255>;     // Always prefixed by \"tls13 \"\n *   opaque context<0..255>;   // Usually a communication transcript hash\n * };\n *\n * Parameters:\n * - desired_length: Length of expanded key material.\n *                   The length field can hold numbers up to 2**16, but HKDF\n *                   can only generate outputs of up to 255 * HASH_LEN bytes.\n *                   It is the caller's responsibility to ensure that this\n *                   limit is not exceeded. In TLS 1.3, SHA256 is the hash\n *                   function with the smallest block size, so a length\n *                   <= 255 * 32 = 8160 is always safe.\n * - (label, label_len): label + label length, without \"tls13 \" prefix\n *                       The label length MUST be less than or equal to\n *                       MBEDTLS_SSL_TLS1_3_HKDF_LABEL_MAX_LABEL_LEN.\n *                       It is the caller's responsibility to ensure this.\n *                       All (label, label length) pairs used in TLS 1.3\n *                       can be obtained via MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN().\n * - (ctx, ctx_len): context + context length\n *                   The context length MUST be less than or equal to\n *                   MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN\n *                   It is the caller's responsibility to ensure this.\n * - dst: Target buffer for HkdfLabel structure,\n *        This MUST be a writable buffer of size\n *        at least SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN Bytes.\n * - dst_len: Pointer at which to store the actual length of\n *            the HkdfLabel structure on success.\n */\n\n/* We need to tell the compiler that we meant to leave out the null character. */\nstatic const char tls13_label_prefix[6] MBEDTLS_ATTRIBUTE_UNTERMINATED_STRING = \"tls13 \";\n\n#define SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(label_len, context_len) \\\n    (2                     /* expansion length           */ \\\n     + 1                   /* label length               */ \\\n     + label_len                                           \\\n     + 1                   /* context length             */ \\\n     + context_len)\n\n#define SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN                      \\\n    SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(                             \\\n        sizeof(tls13_label_prefix) +                       \\\n        MBEDTLS_SSL_TLS1_3_HKDF_LABEL_MAX_LABEL_LEN,       \\\n        MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN)\n\nstatic void ssl_tls13_hkdf_encode_label(\n    size_t desired_length,\n    const unsigned char *label, size_t label_len,\n    const unsigned char *ctx, size_t ctx_len,\n    unsigned char *dst, size_t *dst_len)\n{\n    size_t total_label_len =\n        sizeof(tls13_label_prefix) + label_len;\n    size_t total_hkdf_lbl_len =\n        SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(total_label_len, ctx_len);\n\n    unsigned char *p = dst;\n\n    /* Add the size of the expanded key material. */\n#if MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN > UINT16_MAX\n#error \"The desired key length must fit into an uint16 but \\\n    MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN is greater than UINT16_MAX\"\n#endif\n\n    *p++ = MBEDTLS_BYTE_1(desired_length);\n    *p++ = MBEDTLS_BYTE_0(desired_length);\n\n    /* Add label incl. prefix */\n    *p++ = MBEDTLS_BYTE_0(total_label_len);\n    memcpy(p, tls13_label_prefix, sizeof(tls13_label_prefix));\n    p += sizeof(tls13_label_prefix);\n    memcpy(p, label, label_len);\n    p += label_len;\n\n    /* Add context value */\n    *p++ = MBEDTLS_BYTE_0(ctx_len);\n    if (ctx_len != 0) {\n        memcpy(p, ctx, ctx_len);\n    }\n\n    /* Return total length to the caller.  */\n    *dst_len = total_hkdf_lbl_len;\n}\n\nint mbedtls_ssl_tls13_hkdf_expand_label(\n    psa_algorithm_t hash_alg,\n    const unsigned char *secret, size_t secret_len,\n    const unsigned char *label, size_t label_len,\n    const unsigned char *ctx, size_t ctx_len,\n    unsigned char *buf, size_t buf_len)\n{\n    unsigned char hkdf_label[SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN];\n    size_t hkdf_label_len = 0;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_key_derivation_operation_t operation =\n        PSA_KEY_DERIVATION_OPERATION_INIT;\n\n    if (label_len > MBEDTLS_SSL_TLS1_3_HKDF_LABEL_MAX_LABEL_LEN) {\n        /* Should never happen since this is an internal\n         * function, and we know statically which labels\n         * are allowed. */\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    if (ctx_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN) {\n        /* Should not happen, as above. */\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    if (buf_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN) {\n        /* Should not happen, as above. */\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    if (!PSA_ALG_IS_HASH(hash_alg)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    ssl_tls13_hkdf_encode_label(buf_len,\n                                label, label_len,\n                                ctx, ctx_len,\n                                hkdf_label,\n                                &hkdf_label_len);\n\n    status = psa_key_derivation_setup(&operation, PSA_ALG_HKDF_EXPAND(hash_alg));\n\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    status = psa_key_derivation_input_bytes(&operation,\n                                            PSA_KEY_DERIVATION_INPUT_SECRET,\n                                            secret,\n                                            secret_len);\n\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    status = psa_key_derivation_input_bytes(&operation,\n                                            PSA_KEY_DERIVATION_INPUT_INFO,\n                                            hkdf_label,\n                                            hkdf_label_len);\n\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    status = psa_key_derivation_output_bytes(&operation,\n                                             buf,\n                                             buf_len);\n\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\ncleanup:\n    abort_status = psa_key_derivation_abort(&operation);\n    status = (status == PSA_SUCCESS ? abort_status : status);\n    mbedtls_platform_zeroize(hkdf_label, hkdf_label_len);\n    return PSA_TO_MBEDTLS_ERR(status);\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_make_traffic_key(\n    psa_algorithm_t hash_alg,\n    const unsigned char *secret, size_t secret_len,\n    unsigned char *key, size_t key_len,\n    unsigned char *iv, size_t iv_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    ret = mbedtls_ssl_tls13_hkdf_expand_label(\n        hash_alg,\n        secret, secret_len,\n        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(key),\n        NULL, 0,\n        key, key_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_ssl_tls13_hkdf_expand_label(\n        hash_alg,\n        secret, secret_len,\n        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(iv),\n        NULL, 0,\n        iv, iv_len);\n    return ret;\n}\n\n/*\n * The traffic keying material is generated from the following inputs:\n *\n *  - One secret value per sender.\n *  - A purpose value indicating the specific value being generated\n *  - The desired lengths of key and IV.\n *\n * The expansion itself is based on HKDF:\n *\n *   [sender]_write_key = HKDF-Expand-Label( Secret, \"key\", \"\", key_length )\n *   [sender]_write_iv  = HKDF-Expand-Label( Secret, \"iv\" , \"\", iv_length )\n *\n * [sender] denotes the sending side and the Secret value is provided\n * by the function caller. Note that we generate server and client side\n * keys in a single function call.\n */\nint mbedtls_ssl_tls13_make_traffic_keys(\n    psa_algorithm_t hash_alg,\n    const unsigned char *client_secret,\n    const unsigned char *server_secret, size_t secret_len,\n    size_t key_len, size_t iv_len,\n    mbedtls_ssl_key_set *keys)\n{\n    int ret = 0;\n\n    ret = ssl_tls13_make_traffic_key(\n        hash_alg, client_secret, secret_len,\n        keys->client_write_key, key_len,\n        keys->client_write_iv, iv_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = ssl_tls13_make_traffic_key(\n        hash_alg, server_secret, secret_len,\n        keys->server_write_key, key_len,\n        keys->server_write_iv, iv_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    keys->key_len = key_len;\n    keys->iv_len = iv_len;\n\n    return 0;\n}\n\nint mbedtls_ssl_tls13_derive_secret(\n    psa_algorithm_t hash_alg,\n    const unsigned char *secret, size_t secret_len,\n    const unsigned char *label, size_t label_len,\n    const unsigned char *ctx, size_t ctx_len,\n    int ctx_hashed,\n    unsigned char *dstbuf, size_t dstbuf_len)\n{\n    int ret;\n    unsigned char hashed_context[PSA_HASH_MAX_SIZE];\n    if (ctx_hashed == MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED) {\n        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n        status = psa_hash_compute(hash_alg, ctx, ctx_len, hashed_context,\n                                  PSA_HASH_LENGTH(hash_alg), &ctx_len);\n        if (status != PSA_SUCCESS) {\n            ret = PSA_TO_MBEDTLS_ERR(status);\n            return ret;\n        }\n    } else {\n        if (ctx_len > sizeof(hashed_context)) {\n            /* This should never happen since this function is internal\n             * and the code sets `ctx_hashed` correctly.\n             * Let's double-check nonetheless to not run at the risk\n             * of getting a stack overflow. */\n            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        memcpy(hashed_context, ctx, ctx_len);\n    }\n\n    return mbedtls_ssl_tls13_hkdf_expand_label(hash_alg,\n                                               secret, secret_len,\n                                               label, label_len,\n                                               hashed_context, ctx_len,\n                                               dstbuf, dstbuf_len);\n\n}\n\nint mbedtls_ssl_tls13_evolve_secret(\n    psa_algorithm_t hash_alg,\n    const unsigned char *secret_old,\n    const unsigned char *input, size_t input_len,\n    unsigned char *secret_new)\n{\n    int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t hlen;\n    unsigned char tmp_secret[PSA_MAC_MAX_SIZE] = { 0 };\n    const unsigned char all_zeroes_input[MBEDTLS_TLS1_3_MD_MAX_SIZE] = { 0 };\n    const unsigned char *l_input = NULL;\n    size_t l_input_len;\n\n    psa_key_derivation_operation_t operation =\n        PSA_KEY_DERIVATION_OPERATION_INIT;\n\n    if (!PSA_ALG_IS_HASH(hash_alg)) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    hlen = PSA_HASH_LENGTH(hash_alg);\n\n    /* For non-initial runs, call Derive-Secret( ., \"derived\", \"\")\n     * on the old secret. */\n    if (secret_old != NULL) {\n        ret = mbedtls_ssl_tls13_derive_secret(\n            hash_alg,\n            secret_old, hlen,\n            MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(derived),\n            NULL, 0,        /* context */\n            MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,\n            tmp_secret, hlen);\n        if (ret != 0) {\n            goto cleanup;\n        }\n    }\n\n    ret = 0;\n\n    if (input != NULL && input_len != 0) {\n        l_input = input;\n        l_input_len = input_len;\n    } else {\n        l_input = all_zeroes_input;\n        l_input_len = hlen;\n    }\n\n    status = psa_key_derivation_setup(&operation,\n                                      PSA_ALG_HKDF_EXTRACT(hash_alg));\n\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    status = psa_key_derivation_input_bytes(&operation,\n                                            PSA_KEY_DERIVATION_INPUT_SALT,\n                                            tmp_secret,\n                                            hlen);\n\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    status = psa_key_derivation_input_bytes(&operation,\n                                            PSA_KEY_DERIVATION_INPUT_SECRET,\n                                            l_input, l_input_len);\n\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\n    status = psa_key_derivation_output_bytes(&operation,\n                                             secret_new,\n                                             PSA_HASH_LENGTH(hash_alg));\n\n    if (status != PSA_SUCCESS) {\n        goto cleanup;\n    }\n\ncleanup:\n    abort_status = psa_key_derivation_abort(&operation);\n    status = (status == PSA_SUCCESS ? abort_status : status);\n    ret = (ret == 0 ? PSA_TO_MBEDTLS_ERR(status) : ret);\n    mbedtls_platform_zeroize(tmp_secret, sizeof(tmp_secret));\n    return ret;\n}\n\nint mbedtls_ssl_tls13_derive_early_secrets(\n    psa_algorithm_t hash_alg,\n    unsigned char const *early_secret,\n    unsigned char const *transcript, size_t transcript_len,\n    mbedtls_ssl_tls13_early_secrets *derived)\n{\n    int ret;\n    size_t const hash_len = PSA_HASH_LENGTH(hash_alg);\n\n    /* We should never call this function with an unknown hash,\n     * but add an assertion anyway. */\n    if (!PSA_ALG_IS_HASH(hash_alg)) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    /*\n     *            0\n     *            |\n     *            v\n     *  PSK ->  HKDF-Extract = Early Secret\n     *            |\n     *            +-----> Derive-Secret(., \"c e traffic\", ClientHello)\n     *            |                     = client_early_traffic_secret\n     *            |\n     *            +-----> Derive-Secret(., \"e exp master\", ClientHello)\n     *            |                     = early_exporter_master_secret\n     *            v\n     */\n\n    /* Create client_early_traffic_secret */\n    ret = mbedtls_ssl_tls13_derive_secret(\n        hash_alg,\n        early_secret, hash_len,\n        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_e_traffic),\n        transcript, transcript_len,\n        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,\n        derived->client_early_traffic_secret,\n        hash_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    /* Create early exporter */\n    ret = mbedtls_ssl_tls13_derive_secret(\n        hash_alg,\n        early_secret, hash_len,\n        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(e_exp_master),\n        transcript, transcript_len,\n        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,\n        derived->early_exporter_master_secret,\n        hash_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\nint mbedtls_ssl_tls13_derive_handshake_secrets(\n    psa_algorithm_t hash_alg,\n    unsigned char const *handshake_secret,\n    unsigned char const *transcript, size_t transcript_len,\n    mbedtls_ssl_tls13_handshake_secrets *derived)\n{\n    int ret;\n    size_t const hash_len = PSA_HASH_LENGTH(hash_alg);\n\n    /* We should never call this function with an unknown hash,\n     * but add an assertion anyway. */\n    if (!PSA_ALG_IS_HASH(hash_alg)) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    /*\n     *\n     * Handshake Secret\n     * |\n     * +-----> Derive-Secret( ., \"c hs traffic\",\n     * |                     ClientHello...ServerHello )\n     * |                     = client_handshake_traffic_secret\n     * |\n     * +-----> Derive-Secret( ., \"s hs traffic\",\n     * |                     ClientHello...ServerHello )\n     * |                     = server_handshake_traffic_secret\n     *\n     */\n\n    /*\n     * Compute client_handshake_traffic_secret with\n     * Derive-Secret( ., \"c hs traffic\", ClientHello...ServerHello )\n     */\n\n    ret = mbedtls_ssl_tls13_derive_secret(\n        hash_alg,\n        handshake_secret, hash_len,\n        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_hs_traffic),\n        transcript, transcript_len,\n        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,\n        derived->client_handshake_traffic_secret,\n        hash_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    /*\n     * Compute server_handshake_traffic_secret with\n     * Derive-Secret( ., \"s hs traffic\", ClientHello...ServerHello )\n     */\n\n    ret = mbedtls_ssl_tls13_derive_secret(\n        hash_alg,\n        handshake_secret, hash_len,\n        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_hs_traffic),\n        transcript, transcript_len,\n        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,\n        derived->server_handshake_traffic_secret,\n        hash_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\nint mbedtls_ssl_tls13_derive_application_secrets(\n    psa_algorithm_t hash_alg,\n    unsigned char const *application_secret,\n    unsigned char const *transcript, size_t transcript_len,\n    mbedtls_ssl_tls13_application_secrets *derived)\n{\n    int ret;\n    size_t const hash_len = PSA_HASH_LENGTH(hash_alg);\n\n    /* We should never call this function with an unknown hash,\n     * but add an assertion anyway. */\n    if (!PSA_ALG_IS_HASH(hash_alg)) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    /* Generate {client,server}_application_traffic_secret_0\n     *\n     * Master Secret\n     * |\n     * +-----> Derive-Secret( ., \"c ap traffic\",\n     * |                      ClientHello...server Finished )\n     * |                      = client_application_traffic_secret_0\n     * |\n     * +-----> Derive-Secret( ., \"s ap traffic\",\n     * |                      ClientHello...Server Finished )\n     * |                      = server_application_traffic_secret_0\n     * |\n     * +-----> Derive-Secret( ., \"exp master\",\n     * |                      ClientHello...server Finished)\n     * |                      = exporter_master_secret\n     *\n     */\n\n    ret = mbedtls_ssl_tls13_derive_secret(\n        hash_alg,\n        application_secret, hash_len,\n        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_ap_traffic),\n        transcript, transcript_len,\n        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,\n        derived->client_application_traffic_secret_N,\n        hash_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_ssl_tls13_derive_secret(\n        hash_alg,\n        application_secret, hash_len,\n        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_ap_traffic),\n        transcript, transcript_len,\n        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,\n        derived->server_application_traffic_secret_N,\n        hash_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_ssl_tls13_derive_secret(\n        hash_alg,\n        application_secret, hash_len,\n        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(exp_master),\n        transcript, transcript_len,\n        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,\n        derived->exporter_master_secret,\n        hash_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\n/* Generate resumption_master_secret for use with the ticket exchange.\n *\n * This is not integrated with mbedtls_ssl_tls13_derive_application_secrets()\n * because it uses the transcript hash up to and including ClientFinished. */\nint mbedtls_ssl_tls13_derive_resumption_master_secret(\n    psa_algorithm_t hash_alg,\n    unsigned char const *application_secret,\n    unsigned char const *transcript, size_t transcript_len,\n    mbedtls_ssl_tls13_application_secrets *derived)\n{\n    int ret;\n    size_t const hash_len = PSA_HASH_LENGTH(hash_alg);\n\n    /* We should never call this function with an unknown hash,\n     * but add an assertion anyway. */\n    if (!PSA_ALG_IS_HASH(hash_alg)) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    ret = mbedtls_ssl_tls13_derive_secret(\n        hash_alg,\n        application_secret, hash_len,\n        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_master),\n        transcript, transcript_len,\n        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,\n        derived->resumption_master_secret,\n        hash_len);\n\n    if (ret != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\n/**\n * \\brief Transition into application stage of TLS 1.3 key schedule.\n *\n *        The TLS 1.3 key schedule can be viewed as a simple state machine\n *        with states Initial -> Early -> Handshake -> Application, and\n *        this function represents the Handshake -> Application transition.\n *\n *        In the handshake stage, ssl_tls13_generate_application_keys()\n *        can be used to derive the handshake traffic keys.\n *\n * \\param ssl  The SSL context to operate on. This must be in key schedule\n *             stage \\c Handshake.\n *\n * \\returns    \\c 0 on success.\n * \\returns    A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_key_schedule_stage_application(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n    psa_algorithm_t const hash_alg = mbedtls_md_psa_alg_from_type(\n        (mbedtls_md_type_t) handshake->ciphersuite_info->mac);\n\n    /*\n     * Compute MasterSecret\n     */\n    ret = mbedtls_ssl_tls13_evolve_secret(\n        hash_alg,\n        handshake->tls13_master_secrets.handshake,\n        NULL, 0,\n        handshake->tls13_master_secrets.app);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_evolve_secret\", ret);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(\n        4, \"Master secret\",\n        handshake->tls13_master_secrets.app, PSA_HASH_LENGTH(hash_alg));\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_calc_finished_core(psa_algorithm_t hash_alg,\n                                        unsigned char const *base_key,\n                                        unsigned char const *transcript,\n                                        unsigned char *dst,\n                                        size_t *dst_len)\n{\n    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t hash_len = PSA_HASH_LENGTH(hash_alg);\n    unsigned char finished_key[PSA_MAC_MAX_SIZE];\n    int ret;\n    psa_algorithm_t alg;\n\n    /* We should never call this function with an unknown hash,\n     * but add an assertion anyway. */\n    if (!PSA_ALG_IS_HASH(hash_alg)) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    /* TLS 1.3 Finished message\n     *\n     * struct {\n     *     opaque verify_data[Hash.length];\n     * } Finished;\n     *\n     * verify_data =\n     *     HMAC( finished_key,\n     *            Hash( Handshake Context +\n     *                  Certificate*      +\n     *                  CertificateVerify* )\n     *    )\n     *\n     * finished_key =\n     *    HKDF-Expand-Label( BaseKey, \"finished\", \"\", Hash.length )\n     */\n\n    ret = mbedtls_ssl_tls13_hkdf_expand_label(\n        hash_alg, base_key, hash_len,\n        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(finished),\n        NULL, 0,\n        finished_key, hash_len);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    alg = PSA_ALG_HMAC(hash_alg);\n    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);\n    psa_set_key_algorithm(&attributes, alg);\n    psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);\n\n    status = psa_import_key(&attributes, finished_key, hash_len, &key);\n    if (status != PSA_SUCCESS) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n        goto exit;\n    }\n\n    status = psa_mac_compute(key, alg, transcript, hash_len,\n                             dst, hash_len, dst_len);\n    ret = PSA_TO_MBEDTLS_ERR(status);\n\nexit:\n\n    status = psa_destroy_key(key);\n    if (ret == 0) {\n        ret = PSA_TO_MBEDTLS_ERR(status);\n    }\n\n    mbedtls_platform_zeroize(finished_key, sizeof(finished_key));\n\n    return ret;\n}\n\nint mbedtls_ssl_tls13_calculate_verify_data(mbedtls_ssl_context *ssl,\n                                            unsigned char *dst,\n                                            size_t dst_len,\n                                            size_t *actual_len,\n                                            int from)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    size_t transcript_len;\n\n    unsigned char *base_key = NULL;\n    size_t base_key_len = 0;\n    mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets =\n        &ssl->handshake->tls13_hs_secrets;\n\n    mbedtls_md_type_t const md_type = (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac;\n\n    psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(\n        (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac);\n    size_t const hash_len = PSA_HASH_LENGTH(hash_alg);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> mbedtls_ssl_tls13_calculate_verify_data\"));\n\n    if (from == MBEDTLS_SSL_IS_CLIENT) {\n        base_key = tls13_hs_secrets->client_handshake_traffic_secret;\n        base_key_len = sizeof(tls13_hs_secrets->client_handshake_traffic_secret);\n    } else {\n        base_key = tls13_hs_secrets->server_handshake_traffic_secret;\n        base_key_len = sizeof(tls13_hs_secrets->server_handshake_traffic_secret);\n    }\n\n    if (dst_len < hash_len) {\n        ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;\n        goto exit;\n    }\n\n    ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type,\n                                               transcript, sizeof(transcript),\n                                               &transcript_len);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_get_handshake_transcript\", ret);\n        goto exit;\n    }\n    MBEDTLS_SSL_DEBUG_BUF(4, \"handshake hash\", transcript, transcript_len);\n\n    ret = ssl_tls13_calc_finished_core(hash_alg, base_key,\n                                       transcript, dst, actual_len);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"verify_data for finished message\", dst, hash_len);\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= mbedtls_ssl_tls13_calculate_verify_data\"));\n\nexit:\n    /* Erase handshake secrets */\n    mbedtls_platform_zeroize(base_key, base_key_len);\n    mbedtls_platform_zeroize(transcript, sizeof(transcript));\n    return ret;\n}\n\nint mbedtls_ssl_tls13_create_psk_binder(mbedtls_ssl_context *ssl,\n                                        const psa_algorithm_t hash_alg,\n                                        unsigned char const *psk, size_t psk_len,\n                                        int psk_type,\n                                        unsigned char const *transcript,\n                                        unsigned char *result)\n{\n    int ret = 0;\n    unsigned char binder_key[PSA_MAC_MAX_SIZE];\n    unsigned char early_secret[PSA_MAC_MAX_SIZE];\n    size_t const hash_len = PSA_HASH_LENGTH(hash_alg);\n    size_t actual_len;\n\n#if !defined(MBEDTLS_DEBUG_C)\n    ssl = NULL; /* make sure we don't use it except for debug */\n    ((void) ssl);\n#endif\n\n    /* We should never call this function with an unknown hash,\n     * but add an assertion anyway. */\n    if (!PSA_ALG_IS_HASH(hash_alg)) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    /*\n     *            0\n     *            |\n     *            v\n     *  PSK ->  HKDF-Extract = Early Secret\n     *            |\n     *            +-----> Derive-Secret(., \"ext binder\" | \"res binder\", \"\")\n     *            |                     = binder_key\n     *            v\n     */\n\n    ret = mbedtls_ssl_tls13_evolve_secret(hash_alg,\n                                          NULL,           /* Old secret */\n                                          psk, psk_len,   /* Input      */\n                                          early_secret);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_evolve_secret\", ret);\n        goto exit;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"mbedtls_ssl_tls13_create_psk_binder\",\n                          early_secret, hash_len);\n\n    if (psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {\n        ret = mbedtls_ssl_tls13_derive_secret(\n            hash_alg,\n            early_secret, hash_len,\n            MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_binder),\n            NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,\n            binder_key, hash_len);\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"Derive Early Secret with 'res binder'\"));\n    } else {\n        ret = mbedtls_ssl_tls13_derive_secret(\n            hash_alg,\n            early_secret, hash_len,\n            MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(ext_binder),\n            NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,\n            binder_key, hash_len);\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"Derive Early Secret with 'ext binder'\"));\n    }\n\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_derive_secret\", ret);\n        goto exit;\n    }\n\n    /*\n     * The binding_value is computed in the same way as the Finished message\n     * but with the BaseKey being the binder_key.\n     */\n\n    ret = ssl_tls13_calc_finished_core(hash_alg, binder_key, transcript,\n                                       result, &actual_len);\n    if (ret != 0) {\n        goto exit;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"psk binder\", result, actual_len);\n\nexit:\n\n    mbedtls_platform_zeroize(early_secret, sizeof(early_secret));\n    mbedtls_platform_zeroize(binder_key,   sizeof(binder_key));\n    return ret;\n}\n\nint mbedtls_ssl_tls13_populate_transform(\n    mbedtls_ssl_transform *transform,\n    int endpoint, int ciphersuite,\n    mbedtls_ssl_key_set const *traffic_keys,\n    mbedtls_ssl_context *ssl /* DEBUG ONLY */)\n{\n#if !defined(MBEDTLS_USE_PSA_CRYPTO)\n    int ret;\n    mbedtls_cipher_info_t const *cipher_info;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;\n    unsigned char const *key_enc;\n    unsigned char const *iv_enc;\n    unsigned char const *key_dec;\n    unsigned char const *iv_dec;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_key_type_t key_type;\n    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;\n    psa_algorithm_t alg;\n    size_t key_bits;\n    psa_status_t status = PSA_SUCCESS;\n#endif\n\n#if !defined(MBEDTLS_DEBUG_C)\n    ssl = NULL; /* make sure we don't use it except for those cases */\n    (void) ssl;\n#endif\n\n    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite);\n    if (ciphersuite_info == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"ciphersuite info for %d not found\",\n                                  ciphersuite));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n#if !defined(MBEDTLS_USE_PSA_CRYPTO)\n    cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->cipher);\n    if (cipher_info == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"cipher info for %u not found\",\n                                  ciphersuite_info->cipher));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    /*\n     * Setup cipher contexts in target transform\n     */\n    if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_enc,\n                                    cipher_info)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_cipher_setup\", ret);\n        return ret;\n    }\n\n    if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_dec,\n                                    cipher_info)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_cipher_setup\", ret);\n        return ret;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#if defined(MBEDTLS_SSL_SRV_C)\n    if (endpoint == MBEDTLS_SSL_IS_SERVER) {\n        key_enc = traffic_keys->server_write_key;\n        key_dec = traffic_keys->client_write_key;\n        iv_enc = traffic_keys->server_write_iv;\n        iv_dec = traffic_keys->client_write_iv;\n    } else\n#endif /* MBEDTLS_SSL_SRV_C */\n#if defined(MBEDTLS_SSL_CLI_C)\n    if (endpoint == MBEDTLS_SSL_IS_CLIENT) {\n        key_enc = traffic_keys->client_write_key;\n        key_dec = traffic_keys->server_write_key;\n        iv_enc = traffic_keys->client_write_iv;\n        iv_dec = traffic_keys->server_write_iv;\n    } else\n#endif /* MBEDTLS_SSL_CLI_C */\n    {\n        /* should not happen */\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    memcpy(transform->iv_enc, iv_enc, traffic_keys->iv_len);\n    memcpy(transform->iv_dec, iv_dec, traffic_keys->iv_len);\n\n#if !defined(MBEDTLS_USE_PSA_CRYPTO)\n    if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_enc,\n                                     key_enc, (int) mbedtls_cipher_info_get_key_bitlen(cipher_info),\n                                     MBEDTLS_ENCRYPT)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_cipher_setkey\", ret);\n        return ret;\n    }\n\n    if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec,\n                                     key_dec, (int) mbedtls_cipher_info_get_key_bitlen(cipher_info),\n                                     MBEDTLS_DECRYPT)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_cipher_setkey\", ret);\n        return ret;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    /*\n     * Setup other fields in SSL transform\n     */\n\n    if ((ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG) != 0) {\n        transform->taglen  = 8;\n    } else {\n        transform->taglen  = 16;\n    }\n\n    transform->ivlen       = traffic_keys->iv_len;\n    transform->maclen      = 0;\n    transform->fixed_ivlen = transform->ivlen;\n    transform->tls_version = MBEDTLS_SSL_VERSION_TLS1_3;\n\n    /* We add the true record content type (1 Byte) to the plaintext and\n     * then pad to the configured granularity. The minimum length of the\n     * type-extended and padded plaintext is therefore the padding\n     * granularity. */\n    transform->minlen =\n        transform->taglen + MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY;\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    /*\n     * Setup psa keys and alg\n     */\n    if ((status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) ciphersuite_info->cipher,\n                                            transform->taglen,\n                                            &alg,\n                                            &key_type,\n                                            &key_bits)) != PSA_SUCCESS) {\n        MBEDTLS_SSL_DEBUG_RET(\n            1, \"mbedtls_ssl_cipher_to_psa\", PSA_TO_MBEDTLS_ERR(status));\n        return PSA_TO_MBEDTLS_ERR(status);\n    }\n\n    transform->psa_alg = alg;\n\n    if (alg != MBEDTLS_SSL_NULL_CIPHER) {\n        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);\n        psa_set_key_algorithm(&attributes, alg);\n        psa_set_key_type(&attributes, key_type);\n\n        if ((status = psa_import_key(&attributes,\n                                     key_enc,\n                                     PSA_BITS_TO_BYTES(key_bits),\n                                     &transform->psa_key_enc)) != PSA_SUCCESS) {\n            MBEDTLS_SSL_DEBUG_RET(\n                1, \"psa_import_key\", PSA_TO_MBEDTLS_ERR(status));\n            return PSA_TO_MBEDTLS_ERR(status);\n        }\n\n        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);\n\n        if ((status = psa_import_key(&attributes,\n                                     key_dec,\n                                     PSA_BITS_TO_BYTES(key_bits),\n                                     &transform->psa_key_dec)) != PSA_SUCCESS) {\n            MBEDTLS_SSL_DEBUG_RET(\n                1, \"psa_import_key\", PSA_TO_MBEDTLS_ERR(status));\n            return PSA_TO_MBEDTLS_ERR(status);\n        }\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_get_cipher_key_info(\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info,\n    size_t *key_len, size_t *iv_len)\n{\n    psa_key_type_t key_type;\n    psa_algorithm_t alg;\n    size_t taglen;\n    size_t key_bits;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    if (ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG) {\n        taglen = 8;\n    } else {\n        taglen = 16;\n    }\n\n    status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) ciphersuite_info->cipher, taglen,\n                                       &alg, &key_type, &key_bits);\n    if (status != PSA_SUCCESS) {\n        return PSA_TO_MBEDTLS_ERR(status);\n    }\n\n    *key_len = PSA_BITS_TO_BYTES(key_bits);\n\n    /* TLS 1.3 only have AEAD ciphers, IV length is unconditionally 12 bytes */\n    *iv_len = 12;\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n/*\n * ssl_tls13_generate_early_key() generates the key necessary for protecting\n * the early application data and handshake messages as described in section 7\n * of RFC 8446.\n *\n * NOTE: Only one key is generated, the key for the traffic from the client to\n *       the server. The TLS 1.3 specification does not define a secret and thus\n *       a key for server early traffic.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_generate_early_key(mbedtls_ssl_context *ssl,\n                                        mbedtls_ssl_key_set *traffic_keys)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_md_type_t md_type;\n    psa_algorithm_t hash_alg;\n    size_t hash_len;\n    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    size_t transcript_len;\n    size_t key_len = 0;\n    size_t iv_len = 0;\n    mbedtls_ssl_tls13_early_secrets tls13_early_secrets;\n\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        handshake->ciphersuite_info;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> ssl_tls13_generate_early_key\"));\n\n    ret = ssl_tls13_get_cipher_key_info(ciphersuite_info, &key_len, &iv_len);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_tls13_get_cipher_key_info\", ret);\n        goto cleanup;\n    }\n\n    md_type = (mbedtls_md_type_t) ciphersuite_info->mac;\n\n    hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac);\n    hash_len = PSA_HASH_LENGTH(hash_alg);\n\n    ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type,\n                                               transcript,\n                                               sizeof(transcript),\n                                               &transcript_len);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1,\n                              \"mbedtls_ssl_get_handshake_transcript\",\n                              ret);\n        goto cleanup;\n    }\n\n    ret = mbedtls_ssl_tls13_derive_early_secrets(\n        hash_alg, handshake->tls13_master_secrets.early,\n        transcript, transcript_len, &tls13_early_secrets);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(\n            1, \"mbedtls_ssl_tls13_derive_early_secrets\", ret);\n        goto cleanup;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(\n        4, \"Client early traffic secret\",\n        tls13_early_secrets.client_early_traffic_secret, hash_len);\n\n    /*\n     * Export client handshake traffic secret\n     */\n    if (ssl->f_export_keys != NULL) {\n        ssl->f_export_keys(\n            ssl->p_export_keys,\n            MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET,\n            tls13_early_secrets.client_early_traffic_secret,\n            hash_len,\n            handshake->randbytes,\n            handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,\n            MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */);\n    }\n\n    ret = ssl_tls13_make_traffic_key(\n        hash_alg,\n        tls13_early_secrets.client_early_traffic_secret,\n        hash_len, traffic_keys->client_write_key, key_len,\n        traffic_keys->client_write_iv, iv_len);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_tls13_make_traffic_key\", ret);\n        goto cleanup;\n    }\n    traffic_keys->key_len = key_len;\n    traffic_keys->iv_len = iv_len;\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"client early write_key\",\n                          traffic_keys->client_write_key,\n                          traffic_keys->key_len);\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"client early write_iv\",\n                          traffic_keys->client_write_iv,\n                          traffic_keys->iv_len);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= ssl_tls13_generate_early_key\"));\n\ncleanup:\n    /* Erase early secrets and transcript */\n    mbedtls_platform_zeroize(\n        &tls13_early_secrets, sizeof(mbedtls_ssl_tls13_early_secrets));\n    mbedtls_platform_zeroize(transcript, sizeof(transcript));\n    return ret;\n}\n\nint mbedtls_ssl_tls13_compute_early_transform(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_key_set traffic_keys;\n    mbedtls_ssl_transform *transform_earlydata = NULL;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n    /* Next evolution in key schedule: Establish early_data secret and\n     * key material. */\n    ret = ssl_tls13_generate_early_key(ssl, &traffic_keys);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_tls13_generate_early_key\",\n                              ret);\n        goto cleanup;\n    }\n\n    transform_earlydata = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform));\n    if (transform_earlydata == NULL) {\n        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        goto cleanup;\n    }\n\n    ret = mbedtls_ssl_tls13_populate_transform(\n        transform_earlydata,\n        ssl->conf->endpoint,\n        handshake->ciphersuite_info->id,\n        &traffic_keys,\n        ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_populate_transform\", ret);\n        goto cleanup;\n    }\n    handshake->transform_earlydata = transform_earlydata;\n\ncleanup:\n    mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys));\n    if (ret != 0) {\n        mbedtls_free(transform_earlydata);\n    }\n\n    return ret;\n}\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\nint mbedtls_ssl_tls13_key_schedule_stage_early(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    psa_algorithm_t hash_alg;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n    unsigned char *psk = NULL;\n    size_t psk_len = 0;\n\n    if (handshake->ciphersuite_info == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"cipher suite info not found\"));\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) handshake->ciphersuite_info->mac);\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n    if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) {\n        ret = mbedtls_ssl_tls13_export_handshake_psk(ssl, &psk, &psk_len);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_export_handshake_psk\",\n                                  ret);\n            return ret;\n        }\n    }\n#endif\n\n    ret = mbedtls_ssl_tls13_evolve_secret(hash_alg, NULL, psk, psk_len,\n                                          handshake->tls13_master_secrets.early);\n#if defined(MBEDTLS_USE_PSA_CRYPTO) && \\\n    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n    mbedtls_free((void *) psk);\n#endif\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_evolve_secret\", ret);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"mbedtls_ssl_tls13_key_schedule_stage_early\",\n                          handshake->tls13_master_secrets.early,\n                          PSA_HASH_LENGTH(hash_alg));\n    return 0;\n}\n\n/**\n * \\brief Compute TLS 1.3 handshake traffic keys.\n *\n *        ssl_tls13_generate_handshake_keys() generates keys necessary for\n *        protecting the handshake messages, as described in Section 7 of\n *        RFC 8446.\n *\n * \\param ssl  The SSL context to operate on. This must be in\n *             key schedule stage \\c Handshake, see\n *             ssl_tls13_key_schedule_stage_handshake().\n * \\param traffic_keys The address at which to store the handshake traffic\n *                     keys. This must be writable but may be uninitialized.\n *\n * \\returns    \\c 0 on success.\n * \\returns    A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_generate_handshake_keys(mbedtls_ssl_context *ssl,\n                                             mbedtls_ssl_key_set *traffic_keys)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_md_type_t md_type;\n    psa_algorithm_t hash_alg;\n    size_t hash_len;\n    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    size_t transcript_len;\n    size_t key_len = 0;\n    size_t iv_len = 0;\n\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =\n        handshake->ciphersuite_info;\n    mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets =\n        &handshake->tls13_hs_secrets;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> ssl_tls13_generate_handshake_keys\"));\n\n    ret = ssl_tls13_get_cipher_key_info(ciphersuite_info, &key_len, &iv_len);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_tls13_get_cipher_key_info\", ret);\n        return ret;\n    }\n\n    md_type = (mbedtls_md_type_t) ciphersuite_info->mac;\n\n    hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac);\n    hash_len = PSA_HASH_LENGTH(hash_alg);\n\n    ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type,\n                                               transcript,\n                                               sizeof(transcript),\n                                               &transcript_len);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1,\n                              \"mbedtls_ssl_get_handshake_transcript\",\n                              ret);\n        return ret;\n    }\n\n    ret = mbedtls_ssl_tls13_derive_handshake_secrets(\n        hash_alg, handshake->tls13_master_secrets.handshake,\n        transcript, transcript_len, tls13_hs_secrets);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_derive_handshake_secrets\",\n                              ret);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"Client handshake traffic secret\",\n                          tls13_hs_secrets->client_handshake_traffic_secret,\n                          hash_len);\n    MBEDTLS_SSL_DEBUG_BUF(4, \"Server handshake traffic secret\",\n                          tls13_hs_secrets->server_handshake_traffic_secret,\n                          hash_len);\n\n    /*\n     * Export client handshake traffic secret\n     */\n    if (ssl->f_export_keys != NULL) {\n        ssl->f_export_keys(\n            ssl->p_export_keys,\n            MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET,\n            tls13_hs_secrets->client_handshake_traffic_secret,\n            hash_len,\n            handshake->randbytes,\n            handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,\n            MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */);\n\n        ssl->f_export_keys(\n            ssl->p_export_keys,\n            MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET,\n            tls13_hs_secrets->server_handshake_traffic_secret,\n            hash_len,\n            handshake->randbytes,\n            handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,\n            MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */);\n    }\n\n    ret = mbedtls_ssl_tls13_make_traffic_keys(\n        hash_alg,\n        tls13_hs_secrets->client_handshake_traffic_secret,\n        tls13_hs_secrets->server_handshake_traffic_secret,\n        hash_len, key_len, iv_len, traffic_keys);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_make_traffic_keys\", ret);\n        goto exit;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"client_handshake write_key\",\n                          traffic_keys->client_write_key,\n                          traffic_keys->key_len);\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"server_handshake write_key\",\n                          traffic_keys->server_write_key,\n                          traffic_keys->key_len);\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"client_handshake write_iv\",\n                          traffic_keys->client_write_iv,\n                          traffic_keys->iv_len);\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"server_handshake write_iv\",\n                          traffic_keys->server_write_iv,\n                          traffic_keys->iv_len);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= ssl_tls13_generate_handshake_keys\"));\n\nexit:\n\n    return ret;\n}\n\n/**\n * \\brief Transition into handshake stage of TLS 1.3 key schedule.\n *\n *        The TLS 1.3 key schedule can be viewed as a simple state machine\n *        with states Initial -> Early -> Handshake -> Application, and\n *        this function represents the Early -> Handshake transition.\n *\n *        In the handshake stage, ssl_tls13_generate_handshake_keys()\n *        can be used to derive the handshake traffic keys.\n *\n * \\param ssl  The SSL context to operate on. This must be in key schedule\n *             stage \\c Early.\n *\n * \\returns    \\c 0 on success.\n * \\returns    A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_key_schedule_stage_handshake(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n    psa_algorithm_t const hash_alg = mbedtls_md_psa_alg_from_type(\n        (mbedtls_md_type_t) handshake->ciphersuite_info->mac);\n    unsigned char *shared_secret = NULL;\n    size_t shared_secret_len = 0;\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)\n    /*\n     * Compute ECDHE secret used to compute the handshake secret from which\n     * client_handshake_traffic_secret and server_handshake_traffic_secret\n     * are derived in the handshake secret derivation stage.\n     */\n    if (mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) {\n        if (mbedtls_ssl_tls13_named_group_is_ecdhe(handshake->offered_group_id) ||\n            mbedtls_ssl_tls13_named_group_is_ffdh(handshake->offered_group_id)) {\n#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)\n            psa_algorithm_t alg =\n                mbedtls_ssl_tls13_named_group_is_ecdhe(handshake->offered_group_id) ?\n                PSA_ALG_ECDH : PSA_ALG_FFDH;\n\n            /* Compute ECDH shared secret. */\n            psa_status_t status = PSA_ERROR_GENERIC_ERROR;\n            psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;\n\n            status = psa_get_key_attributes(handshake->xxdh_psa_privkey,\n                                            &key_attributes);\n            if (status != PSA_SUCCESS) {\n                ret = PSA_TO_MBEDTLS_ERR(status);\n            }\n\n            shared_secret_len = PSA_BITS_TO_BYTES(\n                psa_get_key_bits(&key_attributes));\n            shared_secret = mbedtls_calloc(1, shared_secret_len);\n            if (shared_secret == NULL) {\n                return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n            }\n\n            status = psa_raw_key_agreement(\n                alg, handshake->xxdh_psa_privkey,\n                handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len,\n                shared_secret, shared_secret_len, &shared_secret_len);\n            if (status != PSA_SUCCESS) {\n                ret = PSA_TO_MBEDTLS_ERR(status);\n                MBEDTLS_SSL_DEBUG_RET(1, \"psa_raw_key_agreement\", ret);\n                goto cleanup;\n            }\n\n            status = psa_destroy_key(handshake->xxdh_psa_privkey);\n            if (status != PSA_SUCCESS) {\n                ret = PSA_TO_MBEDTLS_ERR(status);\n                MBEDTLS_SSL_DEBUG_RET(1, \"psa_destroy_key\", ret);\n                goto cleanup;\n            }\n\n            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;\n#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */\n        } else {\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"Group not supported.\"));\n            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n        }\n    }\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */\n\n    /*\n     * Compute the Handshake Secret\n     */\n    ret = mbedtls_ssl_tls13_evolve_secret(\n        hash_alg, handshake->tls13_master_secrets.early,\n        shared_secret, shared_secret_len,\n        handshake->tls13_master_secrets.handshake);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_evolve_secret\", ret);\n        goto cleanup;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"Handshake secret\",\n                          handshake->tls13_master_secrets.handshake,\n                          PSA_HASH_LENGTH(hash_alg));\n\ncleanup:\n    if (shared_secret != NULL) {\n        mbedtls_zeroize_and_free(shared_secret, shared_secret_len);\n    }\n\n    return ret;\n}\n\n/**\n * \\brief Compute TLS 1.3 application traffic keys.\n *\n *        ssl_tls13_generate_application_keys() generates application traffic\n *        keys, since any record following a 1-RTT Finished message MUST be\n *        encrypted under the application traffic key.\n *\n * \\param ssl  The SSL context to operate on. This must be in\n *             key schedule stage \\c Application, see\n *             ssl_tls13_key_schedule_stage_application().\n * \\param traffic_keys The address at which to store the application traffic\n *                     keys. This must be writable but may be uninitialized.\n *\n * \\returns    \\c 0 on success.\n * \\returns    A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_generate_application_keys(\n    mbedtls_ssl_context *ssl,\n    mbedtls_ssl_key_set *traffic_keys)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n    /* Address at which to store the application secrets */\n    mbedtls_ssl_tls13_application_secrets * const app_secrets =\n        &ssl->session_negotiate->app_secrets;\n\n    /* Holding the transcript up to and including the ServerFinished */\n    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    size_t transcript_len;\n\n    /* Variables relating to the hash for the chosen ciphersuite. */\n    mbedtls_md_type_t md_type;\n\n    psa_algorithm_t hash_alg;\n    size_t hash_len;\n\n    /* Variables relating to the cipher for the chosen ciphersuite. */\n    size_t key_len = 0, iv_len = 0;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> derive application traffic keys\"));\n\n    /* Extract basic information about hash and ciphersuite */\n\n    ret = ssl_tls13_get_cipher_key_info(handshake->ciphersuite_info,\n                                        &key_len, &iv_len);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_tls13_get_cipher_key_info\", ret);\n        goto cleanup;\n    }\n\n    md_type = (mbedtls_md_type_t) handshake->ciphersuite_info->mac;\n\n    hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) handshake->ciphersuite_info->mac);\n    hash_len = PSA_HASH_LENGTH(hash_alg);\n\n    /* Compute current handshake transcript. It's the caller's responsibility\n     * to call this at the right time, that is, after the ServerFinished. */\n\n    ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type,\n                                               transcript, sizeof(transcript),\n                                               &transcript_len);\n    if (ret != 0) {\n        goto cleanup;\n    }\n\n    /* Compute application secrets from master secret and transcript hash. */\n\n    ret = mbedtls_ssl_tls13_derive_application_secrets(\n        hash_alg, handshake->tls13_master_secrets.app,\n        transcript, transcript_len, app_secrets);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(\n            1, \"mbedtls_ssl_tls13_derive_application_secrets\", ret);\n        goto cleanup;\n    }\n\n    /* Derive first epoch of IV + Key for application traffic. */\n\n    ret = mbedtls_ssl_tls13_make_traffic_keys(\n        hash_alg,\n        app_secrets->client_application_traffic_secret_N,\n        app_secrets->server_application_traffic_secret_N,\n        hash_len, key_len, iv_len, traffic_keys);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_make_traffic_keys\", ret);\n        goto cleanup;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"Client application traffic secret\",\n                          app_secrets->client_application_traffic_secret_N,\n                          hash_len);\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"Server application traffic secret\",\n                          app_secrets->server_application_traffic_secret_N,\n                          hash_len);\n\n    /*\n     * Export client/server application traffic secret 0\n     */\n    if (ssl->f_export_keys != NULL) {\n        ssl->f_export_keys(\n            ssl->p_export_keys,\n            MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET,\n            app_secrets->client_application_traffic_secret_N, hash_len,\n            handshake->randbytes,\n            handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,\n            MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by\n                                        a new constant for TLS 1.3! */);\n\n        ssl->f_export_keys(\n            ssl->p_export_keys,\n            MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET,\n            app_secrets->server_application_traffic_secret_N, hash_len,\n            handshake->randbytes,\n            handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,\n            MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by\n                                        a new constant for TLS 1.3! */);\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"client application_write_key:\",\n                          traffic_keys->client_write_key, key_len);\n    MBEDTLS_SSL_DEBUG_BUF(4, \"server application write key\",\n                          traffic_keys->server_write_key, key_len);\n    MBEDTLS_SSL_DEBUG_BUF(4, \"client application write IV\",\n                          traffic_keys->client_write_iv, iv_len);\n    MBEDTLS_SSL_DEBUG_BUF(4, \"server application write IV\",\n                          traffic_keys->server_write_iv, iv_len);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= derive application traffic keys\"));\n\ncleanup:\n    /* randbytes is not used again */\n    mbedtls_platform_zeroize(ssl->handshake->randbytes,\n                             sizeof(ssl->handshake->randbytes));\n\n    mbedtls_platform_zeroize(transcript, sizeof(transcript));\n    return ret;\n}\n\nint mbedtls_ssl_tls13_compute_handshake_transform(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_key_set traffic_keys;\n    mbedtls_ssl_transform *transform_handshake = NULL;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n    /* Compute handshake secret */\n    ret = ssl_tls13_key_schedule_stage_handshake(ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_derive_master_secret\", ret);\n        goto cleanup;\n    }\n\n    /* Next evolution in key schedule: Establish handshake secret and\n     * key material. */\n    ret = ssl_tls13_generate_handshake_keys(ssl, &traffic_keys);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"ssl_tls13_generate_handshake_keys\",\n                              ret);\n        goto cleanup;\n    }\n\n    transform_handshake = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform));\n    if (transform_handshake == NULL) {\n        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        goto cleanup;\n    }\n\n    ret = mbedtls_ssl_tls13_populate_transform(\n        transform_handshake,\n        ssl->conf->endpoint,\n        handshake->ciphersuite_info->id,\n        &traffic_keys,\n        ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_populate_transform\", ret);\n        goto cleanup;\n    }\n    handshake->transform_handshake = transform_handshake;\n\ncleanup:\n    mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys));\n    if (ret != 0) {\n        mbedtls_free(transform_handshake);\n    }\n\n    return ret;\n}\n\nint mbedtls_ssl_tls13_compute_resumption_master_secret(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_md_type_t md_type;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    size_t transcript_len;\n\n    MBEDTLS_SSL_DEBUG_MSG(\n        2, (\"=> mbedtls_ssl_tls13_compute_resumption_master_secret\"));\n\n    md_type = (mbedtls_md_type_t) handshake->ciphersuite_info->mac;\n\n    ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type,\n                                               transcript, sizeof(transcript),\n                                               &transcript_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_ssl_tls13_derive_resumption_master_secret(\n        mbedtls_md_psa_alg_from_type(md_type),\n        handshake->tls13_master_secrets.app,\n        transcript, transcript_len,\n        &ssl->session_negotiate->app_secrets);\n    if (ret != 0) {\n        return ret;\n    }\n\n    /* Erase master secrets */\n    mbedtls_platform_zeroize(&handshake->tls13_master_secrets,\n                             sizeof(handshake->tls13_master_secrets));\n\n    MBEDTLS_SSL_DEBUG_BUF(\n        4, \"Resumption master secret\",\n        ssl->session_negotiate->app_secrets.resumption_master_secret,\n        PSA_HASH_LENGTH(mbedtls_md_psa_alg_from_type(md_type)));\n\n    MBEDTLS_SSL_DEBUG_MSG(\n        2, (\"<= mbedtls_ssl_tls13_compute_resumption_master_secret\"));\n    return 0;\n}\n\nint mbedtls_ssl_tls13_compute_application_transform(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_key_set traffic_keys;\n    mbedtls_ssl_transform *transform_application = NULL;\n\n    ret = ssl_tls13_key_schedule_stage_application(ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1,\n                              \"ssl_tls13_key_schedule_stage_application\", ret);\n        goto cleanup;\n    }\n\n    ret = ssl_tls13_generate_application_keys(ssl, &traffic_keys);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1,\n                              \"ssl_tls13_generate_application_keys\", ret);\n        goto cleanup;\n    }\n\n    transform_application =\n        mbedtls_calloc(1, sizeof(mbedtls_ssl_transform));\n    if (transform_application == NULL) {\n        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;\n        goto cleanup;\n    }\n\n    ret = mbedtls_ssl_tls13_populate_transform(\n        transform_application,\n        ssl->conf->endpoint,\n        ssl->handshake->ciphersuite_info->id,\n        &traffic_keys,\n        ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_tls13_populate_transform\", ret);\n        goto cleanup;\n    }\n\n    ssl->transform_application = transform_application;\n\ncleanup:\n\n    mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys));\n    if (ret != 0) {\n        mbedtls_free(transform_application);\n    }\n    return ret;\n}\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\nint mbedtls_ssl_tls13_export_handshake_psk(mbedtls_ssl_context *ssl,\n                                           unsigned char **psk,\n                                           size_t *psk_len)\n{\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    *psk_len = 0;\n    *psk = NULL;\n\n    if (mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    status = psa_get_key_attributes(ssl->handshake->psk_opaque, &key_attributes);\n    if (status != PSA_SUCCESS) {\n        return PSA_TO_MBEDTLS_ERR(status);\n    }\n\n    *psk_len = PSA_BITS_TO_BYTES(psa_get_key_bits(&key_attributes));\n    *psk = mbedtls_calloc(1, *psk_len);\n    if (*psk == NULL) {\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n\n    status = psa_export_key(ssl->handshake->psk_opaque,\n                            (uint8_t *) *psk, *psk_len, psk_len);\n    if (status != PSA_SUCCESS) {\n        mbedtls_free((void *) *psk);\n        *psk = NULL;\n        return PSA_TO_MBEDTLS_ERR(status);\n    }\n    return 0;\n#else\n    *psk = ssl->handshake->psk;\n    *psk_len = ssl->handshake->psk_len;\n    if (*psk == NULL) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n    return 0;\n#endif /* !MBEDTLS_USE_PSA_CRYPTO */\n}\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */\n\n#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT)\nint mbedtls_ssl_tls13_exporter(const psa_algorithm_t hash_alg,\n                               const unsigned char *secret, const size_t secret_len,\n                               const unsigned char *label, const size_t label_len,\n                               const unsigned char *context_value, const size_t context_len,\n                               unsigned char *out, const size_t out_len)\n{\n    size_t hash_len = PSA_HASH_LENGTH(hash_alg);\n    unsigned char hkdf_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE];\n    int ret = 0;\n\n    ret = mbedtls_ssl_tls13_derive_secret(hash_alg, secret, secret_len, label, label_len, NULL, 0,\n                                          MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, hkdf_secret,\n                                          hash_len);\n    if (ret != 0) {\n        goto exit;\n    }\n    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,\n                                          hkdf_secret,\n                                          hash_len,\n                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(exporter),\n                                          context_value,\n                                          context_len,\n                                          MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,\n                                          out,\n                                          out_len);\n\nexit:\n    mbedtls_platform_zeroize(hkdf_secret, sizeof(hkdf_secret));\n    return ret;\n}\n#endif /* defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) */\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_tls13_keys.h",
    "content": "/*\n *  TLS 1.3 key schedule\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#if !defined(MBEDTLS_SSL_TLS1_3_KEYS_H)\n#define MBEDTLS_SSL_TLS1_3_KEYS_H\n\n/* This requires MBEDTLS_SSL_TLS1_3_LABEL( idx, name, string ) to be defined at\n * the point of use. See e.g. the definition of mbedtls_ssl_tls13_labels_union\n * below. */\n#define MBEDTLS_SSL_TLS1_3_LABEL_LIST                                             \\\n    MBEDTLS_SSL_TLS1_3_LABEL(finished, \"finished\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(resumption, \"resumption\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(traffic_upd, \"traffic upd\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(exporter, \"exporter\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(key, \"key\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(iv, \"iv\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(c_hs_traffic, \"c hs traffic\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(c_ap_traffic, \"c ap traffic\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(c_e_traffic, \"c e traffic\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(s_hs_traffic, \"s hs traffic\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(s_ap_traffic, \"s ap traffic\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(s_e_traffic, \"s e traffic\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(e_exp_master, \"e exp master\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(res_master, \"res master\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(exp_master, \"exp master\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(ext_binder, \"ext binder\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(res_binder, \"res binder\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(derived, \"derived\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(client_cv, \"TLS 1.3, client CertificateVerify\") \\\n    MBEDTLS_SSL_TLS1_3_LABEL(server_cv, \"TLS 1.3, server CertificateVerify\")\n\n#define MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED 0\n#define MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED   1\n\n#define MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL   0\n#define MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION 1\n\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n\n/* We need to tell the compiler that we meant to leave out the null character. */\n#define MBEDTLS_SSL_TLS1_3_LABEL(name, string)       \\\n    const unsigned char name    [sizeof(string) - 1] MBEDTLS_ATTRIBUTE_UNTERMINATED_STRING;\n\nunion mbedtls_ssl_tls13_labels_union {\n    MBEDTLS_SSL_TLS1_3_LABEL_LIST\n};\nstruct mbedtls_ssl_tls13_labels_struct {\n    MBEDTLS_SSL_TLS1_3_LABEL_LIST\n};\n#undef MBEDTLS_SSL_TLS1_3_LABEL\n\nextern const struct mbedtls_ssl_tls13_labels_struct mbedtls_ssl_tls13_labels;\n\n#define MBEDTLS_SSL_TLS1_3_LBL_LEN(LABEL)  \\\n    sizeof(mbedtls_ssl_tls13_labels.LABEL)\n\n#define MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(LABEL)  \\\n    mbedtls_ssl_tls13_labels.LABEL,              \\\n    MBEDTLS_SSL_TLS1_3_LBL_LEN(LABEL)\n\n/* Maximum length of the label field in the HkdfLabel struct defined in\n * RFC 8446, Section 7.1, excluding the \"tls13 \" prefix. */\n#define MBEDTLS_SSL_TLS1_3_HKDF_LABEL_MAX_LABEL_LEN 249\n\n/* The maximum length of HKDF contexts used in the TLS 1.3 standard.\n * Since contexts are always hashes of message transcripts, this can\n * be approximated from above by the maximum hash size. */\n#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN  \\\n    PSA_HASH_MAX_SIZE\n\n/* Maximum desired length for expanded key material generated\n * by HKDF-Expand-Label. This algorithm can output up to 255 * hash_size\n * bytes of key material where hash_size is the output size of the\n * underlying hash function. */\n#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN \\\n    (255 * MBEDTLS_TLS1_3_MD_MAX_SIZE)\n\n/**\n * \\brief            The \\c HKDF-Expand-Label function from\n *                   the TLS 1.3 standard RFC 8446.\n *\n * <tt>\n *                   HKDF-Expand-Label( Secret, Label, Context, Length ) =\n *                       HKDF-Expand( Secret, HkdfLabel, Length )\n * </tt>\n *\n * \\param hash_alg   The identifier for the hash algorithm to use.\n * \\param secret     The \\c Secret argument to \\c HKDF-Expand-Label.\n *                   This must be a readable buffer of length\n *                   \\p secret_len Bytes.\n * \\param secret_len The length of \\p secret in Bytes.\n * \\param label      The \\c Label argument to \\c HKDF-Expand-Label.\n *                   This must be a readable buffer of length\n *                   \\p label_len Bytes.\n * \\param label_len  The length of \\p label in Bytes.\n * \\param ctx        The \\c Context argument to \\c HKDF-Expand-Label.\n *                   This must be a readable buffer of length \\p ctx_len Bytes.\n * \\param ctx_len    The length of \\p context in Bytes.\n * \\param buf        The destination buffer to hold the expanded secret.\n *                   This must be a writable buffer of length \\p buf_len Bytes.\n * \\param buf_len    The desired size of the expanded secret in Bytes.\n *\n * \\returns          \\c 0 on success.\n * \\return           A negative error code on failure.\n */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_hkdf_expand_label(\n    psa_algorithm_t hash_alg,\n    const unsigned char *secret, size_t secret_len,\n    const unsigned char *label, size_t label_len,\n    const unsigned char *ctx, size_t ctx_len,\n    unsigned char *buf, size_t buf_len);\n\n/**\n * \\brief           This function is part of the TLS 1.3 key schedule.\n *                  It extracts key and IV for the actual client/server traffic\n *                  from the client/server traffic secrets.\n *\n * From RFC 8446:\n *\n * <tt>\n *   [sender]_write_key = HKDF-Expand-Label(Secret, \"key\", \"\", key_length)\n *   [sender]_write_iv  = HKDF-Expand-Label(Secret, \"iv\", \"\", iv_length)*\n * </tt>\n *\n * \\param hash_alg      The identifier for the hash algorithm to be used\n *                      for the HKDF-based expansion of the secret.\n * \\param client_secret The client traffic secret.\n *                      This must be a readable buffer of size\n *                      \\p secret_len Bytes\n * \\param server_secret The server traffic secret.\n *                      This must be a readable buffer of size\n *                      \\p secret_len Bytes\n * \\param secret_len    Length of the secrets \\p client_secret and\n *                      \\p server_secret in Bytes.\n * \\param key_len       The desired length of the key to be extracted in Bytes.\n * \\param iv_len        The desired length of the IV to be extracted in Bytes.\n * \\param keys          The address of the structure holding the generated\n *                      keys and IVs.\n *\n * \\returns             \\c 0 on success.\n * \\returns             A negative error code on failure.\n */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_make_traffic_keys(\n    psa_algorithm_t hash_alg,\n    const unsigned char *client_secret,\n    const unsigned char *server_secret, size_t secret_len,\n    size_t key_len, size_t iv_len,\n    mbedtls_ssl_key_set *keys);\n\n/**\n * \\brief The \\c Derive-Secret function from the TLS 1.3 standard RFC 8446.\n *\n * <tt>\n *   Derive-Secret( Secret, Label, Messages ) =\n *      HKDF-Expand-Label( Secret, Label,\n *                         Hash( Messages ),\n *                         Hash.Length ) )\n * </tt>\n *\n * \\param hash_alg   The identifier for the hash function used for the\n *                   applications of HKDF.\n * \\param secret     The \\c Secret argument to the \\c Derive-Secret function.\n *                   This must be a readable buffer of length\n *                   \\p secret_len Bytes.\n * \\param secret_len The length of \\p secret in Bytes.\n * \\param label      The \\c Label argument to the \\c Derive-Secret function.\n *                   This must be a readable buffer of length\n *                   \\p label_len Bytes.\n * \\param label_len  The length of \\p label in Bytes.\n * \\param ctx        The hash of the \\c Messages argument to the\n *                   \\c Derive-Secret function, or the \\c Messages argument\n *                   itself, depending on \\p ctx_hashed.\n * \\param ctx_len    The length of \\p ctx in Bytes.\n * \\param ctx_hashed This indicates whether the \\p ctx contains the hash of\n *                   the \\c Messages argument in the application of the\n *                   \\c Derive-Secret function\n *                   (value MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED), or whether\n *                   it is the content of \\c Messages itself, in which case\n *                   the function takes care of the hashing\n *                   (value MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED).\n * \\param dstbuf     The target buffer to write the output of\n *                   \\c Derive-Secret to. This must be a writable buffer of\n *                   size \\p dtsbuf_len Bytes.\n * \\param dstbuf_len The length of \\p dstbuf in Bytes.\n *\n * \\returns        \\c 0 on success.\n * \\returns        A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_derive_secret(\n    psa_algorithm_t hash_alg,\n    const unsigned char *secret, size_t secret_len,\n    const unsigned char *label, size_t label_len,\n    const unsigned char *ctx, size_t ctx_len,\n    int ctx_hashed,\n    unsigned char *dstbuf, size_t dstbuf_len);\n\n/**\n * \\brief Derive TLS 1.3 early data key material from early secret.\n *\n *        This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret()\n *        with the appropriate labels.\n *\n * <tt>\n *        Early Secret\n *             |\n *             +-----> Derive-Secret(., \"c e traffic\", ClientHello)\n *             |                      = client_early_traffic_secret\n *             |\n *             +-----> Derive-Secret(., \"e exp master\", ClientHello)\n *             .                      = early_exporter_master_secret\n *             .\n *             .\n * </tt>\n *\n * \\note  To obtain the actual key and IV for the early data traffic,\n *        the client secret derived by this function need to be\n *        further processed by mbedtls_ssl_tls13_make_traffic_keys().\n *\n * \\note  The binder key, which is also generated from the early secret,\n *        is omitted here. Its calculation is part of the separate routine\n *        mbedtls_ssl_tls13_create_psk_binder().\n *\n * \\param hash_alg     The hash algorithm associated with the PSK for which\n *                     early data key material is being derived.\n * \\param early_secret The early secret from which the early data key material\n *                     should be derived. This must be a readable buffer whose\n *                     length is the digest size of the hash algorithm\n *                     represented by \\p md_size.\n * \\param transcript   The transcript of the handshake so far, calculated with\n *                     respect to \\p hash_alg. This must be a readable buffer\n *                     whose length is the digest size of the hash algorithm\n *                     represented by \\p md_size.\n * \\param derived      The address of the structure in which to store\n *                     the early data key material.\n *\n * \\returns        \\c 0 on success.\n * \\returns        A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_derive_early_secrets(\n    psa_algorithm_t hash_alg,\n    unsigned char const *early_secret,\n    unsigned char const *transcript, size_t transcript_len,\n    mbedtls_ssl_tls13_early_secrets *derived);\n\n/**\n * \\brief Derive TLS 1.3 handshake key material from the handshake secret.\n *\n *        This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret()\n *        with the appropriate labels from the standard.\n *\n * <tt>\n *        Handshake Secret\n *              |\n *              +-----> Derive-Secret( ., \"c hs traffic\",\n *              |                      ClientHello...ServerHello )\n *              |                      = client_handshake_traffic_secret\n *              |\n *              +-----> Derive-Secret( ., \"s hs traffic\",\n *              .                      ClientHello...ServerHello )\n *              .                      = server_handshake_traffic_secret\n *              .\n * </tt>\n *\n * \\note  To obtain the actual key and IV for the encrypted handshake traffic,\n *        the client and server secret derived by this function need to be\n *        further processed by mbedtls_ssl_tls13_make_traffic_keys().\n *\n * \\param hash_alg          The hash algorithm associated with the ciphersuite\n *                          that's being used for the connection.\n * \\param handshake_secret  The handshake secret from which the handshake key\n *                          material should be derived. This must be a readable\n *                          buffer whose length is the digest size of the hash\n *                          algorithm represented by \\p md_size.\n * \\param transcript        The transcript of the handshake so far, calculated\n *                          with respect to \\p hash_alg. This must be a readable\n *                          buffer whose length is the digest size of the hash\n *                          algorithm represented by \\p md_size.\n * \\param derived           The address of the structure in which to\n *                          store the handshake key material.\n *\n * \\returns        \\c 0 on success.\n * \\returns        A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_derive_handshake_secrets(\n    psa_algorithm_t hash_alg,\n    unsigned char const *handshake_secret,\n    unsigned char const *transcript, size_t transcript_len,\n    mbedtls_ssl_tls13_handshake_secrets *derived);\n\n/**\n * \\brief Derive TLS 1.3 application key material from the master secret.\n *\n *        This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret()\n *        with the appropriate labels from the standard.\n *\n * <tt>\n *        Master Secret\n *              |\n *              +-----> Derive-Secret( ., \"c ap traffic\",\n *              |                      ClientHello...server Finished )\n *              |                      = client_application_traffic_secret_0\n *              |\n *              +-----> Derive-Secret( ., \"s ap traffic\",\n *              |                      ClientHello...Server Finished )\n *              |                      = server_application_traffic_secret_0\n *              |\n *              +-----> Derive-Secret( ., \"exp master\",\n *              .                      ClientHello...server Finished)\n *              .                      = exporter_master_secret\n *              .\n * </tt>\n *\n * \\note  To obtain the actual key and IV for the (0-th) application traffic,\n *        the client and server secret derived by this function need to be\n *        further processed by mbedtls_ssl_tls13_make_traffic_keys().\n *\n * \\param hash_alg          The hash algorithm associated with the ciphersuite\n *                          that's being used for the connection.\n * \\param master_secret     The master secret from which the application key\n *                          material should be derived. This must be a readable\n *                          buffer whose length is the digest size of the hash\n *                          algorithm represented by \\p md_size.\n * \\param transcript        The transcript of the handshake up to and including\n *                          the ServerFinished message, calculated with respect\n *                          to \\p hash_alg. This must be a readable buffer whose\n *                          length is the digest size of the hash algorithm\n *                          represented by \\p hash_alg.\n * \\param derived           The address of the structure in which to\n *                          store the application key material.\n *\n * \\returns        \\c 0 on success.\n * \\returns        A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_derive_application_secrets(\n    psa_algorithm_t hash_alg,\n    unsigned char const *master_secret,\n    unsigned char const *transcript, size_t transcript_len,\n    mbedtls_ssl_tls13_application_secrets *derived);\n\n/**\n * \\brief Derive TLS 1.3 resumption master secret from the master secret.\n *\n *        This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret()\n *        with the appropriate labels from the standard.\n *\n * \\param hash_alg          The hash algorithm used in the application for which\n *                          key material is being derived.\n * \\param application_secret The application secret from which the resumption master\n *                          secret should be derived. This must be a readable\n *                          buffer whose length is the digest size of the hash\n *                          algorithm represented by \\p md_size.\n * \\param transcript        The transcript of the handshake up to and including\n *                          the ClientFinished message, calculated with respect\n *                          to \\p hash_alg. This must be a readable buffer whose\n *                          length is the digest size of the hash algorithm\n *                          represented by \\p hash_alg.\n * \\param transcript_len    The length of \\p transcript in Bytes.\n * \\param derived           The address of the structure in which to\n *                          store the resumption master secret.\n *\n * \\returns        \\c 0 on success.\n * \\returns        A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_derive_resumption_master_secret(\n    psa_algorithm_t hash_alg,\n    unsigned char const *application_secret,\n    unsigned char const *transcript, size_t transcript_len,\n    mbedtls_ssl_tls13_application_secrets *derived);\n\n/**\n * \\brief Compute the next secret in the TLS 1.3 key schedule\n *\n * The TLS 1.3 key schedule proceeds as follows to compute\n * the three main secrets during the handshake: The early\n * secret for early data, the handshake secret for all\n * other encrypted handshake messages, and the master\n * secret for all application traffic.\n *\n * <tt>\n *                    0\n *                    |\n *                    v\n *     PSK ->  HKDF-Extract = Early Secret\n *                    |\n *                    v\n *     Derive-Secret( ., \"derived\", \"\" )\n *                    |\n *                    v\n *  (EC)DHE -> HKDF-Extract = Handshake Secret\n *                    |\n *                    v\n *     Derive-Secret( ., \"derived\", \"\" )\n *                    |\n *                    v\n *     0 -> HKDF-Extract = Master Secret\n * </tt>\n *\n * Each of the three secrets in turn is the basis for further\n * key derivations, such as the derivation of traffic keys and IVs;\n * see e.g. mbedtls_ssl_tls13_make_traffic_keys().\n *\n * This function implements one step in this evolution of secrets:\n *\n * <tt>\n *                old_secret\n *                    |\n *                    v\n *     Derive-Secret( ., \"derived\", \"\" )\n *                    |\n *                    v\n *     input -> HKDF-Extract = new_secret\n * </tt>\n *\n * \\param hash_alg    The identifier for the hash function used for the\n *                    applications of HKDF.\n * \\param secret_old  The address of the buffer holding the old secret\n *                    on function entry. If not \\c NULL, this must be a\n *                    readable buffer whose size matches the output size\n *                    of the hash function represented by \\p hash_alg.\n *                    If \\c NULL, an all \\c 0 array will be used instead.\n * \\param input       The address of the buffer holding the additional\n *                    input for the key derivation (e.g., the PSK or the\n *                    ephemeral (EC)DH secret). If not \\c NULL, this must be\n *                    a readable buffer whose size \\p input_len Bytes.\n *                    If \\c NULL, an all \\c 0 array will be used instead.\n * \\param input_len   The length of \\p input in Bytes.\n * \\param secret_new  The address of the buffer holding the new secret\n *                    on function exit. This must be a writable buffer\n *                    whose size matches the output size of the hash\n *                    function represented by \\p hash_alg.\n *                    This may be the same as \\p secret_old.\n *\n * \\returns           \\c 0 on success.\n * \\returns           A negative error code on failure.\n */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_evolve_secret(\n    psa_algorithm_t hash_alg,\n    const unsigned char *secret_old,\n    const unsigned char *input, size_t input_len,\n    unsigned char *secret_new);\n\n/**\n * \\brief             Calculate a TLS 1.3 PSK binder.\n *\n * \\param ssl         The SSL context. This is used for debugging only and may\n *                    be \\c NULL if MBEDTLS_DEBUG_C is disabled.\n * \\param hash_alg    The hash algorithm associated to the PSK \\p psk.\n * \\param psk         The buffer holding the PSK for which to create a binder.\n * \\param psk_len     The size of \\p psk in bytes.\n * \\param psk_type    This indicates whether the PSK \\p psk is externally\n *                    provisioned (#MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL) or a\n *                    resumption PSK (#MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION).\n * \\param transcript  The handshake transcript up to the point where the\n *                    PSK binder calculation happens. This must be readable,\n *                    and its size must be equal to the digest size of\n *                    the hash algorithm represented by \\p hash_alg.\n * \\param result      The address at which to store the PSK binder on success.\n *                    This must be writable, and its size must be equal to the\n *                    digest size of  the hash algorithm represented by\n *                    \\p hash_alg.\n *\n * \\returns           \\c 0 on success.\n * \\returns           A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_create_psk_binder(mbedtls_ssl_context *ssl,\n                                        const psa_algorithm_t hash_alg,\n                                        unsigned char const *psk, size_t psk_len,\n                                        int psk_type,\n                                        unsigned char const *transcript,\n                                        unsigned char *result);\n\n/**\n * \\bref Setup an SSL transform structure representing the\n *       record protection mechanism used by TLS 1.3\n *\n * \\param transform    The SSL transform structure to be created. This must have\n *                     been initialized through mbedtls_ssl_transform_init() and\n *                     not used in any other way prior to calling this function.\n *                     In particular, this function does not clean up the\n *                     transform structure prior to installing the new keys.\n * \\param endpoint     Indicates whether the transform is for the client\n *                     (value #MBEDTLS_SSL_IS_CLIENT) or the server\n *                     (value #MBEDTLS_SSL_IS_SERVER).\n * \\param ciphersuite  The numerical identifier for the ciphersuite to use.\n *                     This must be one of the identifiers listed in\n *                     ssl_ciphersuites.h.\n * \\param traffic_keys The key material to use. No reference is stored in\n *                     the SSL transform being generated, and the caller\n *                     should destroy the key material afterwards.\n * \\param ssl          (Debug-only) The SSL context to use for debug output\n *                     in case of failure. This parameter is only needed if\n *                     #MBEDTLS_DEBUG_C is set, and is ignored otherwise.\n *\n * \\return             \\c 0 on success. In this case, \\p transform is ready to\n *                     be used with mbedtls_ssl_transform_decrypt() and\n *                     mbedtls_ssl_transform_encrypt().\n * \\return             A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_populate_transform(mbedtls_ssl_transform *transform,\n                                         int endpoint,\n                                         int ciphersuite,\n                                         mbedtls_ssl_key_set const *traffic_keys,\n                                         mbedtls_ssl_context *ssl);\n\n/*\n * TLS 1.3 key schedule evolutions\n *\n *   Early -> Handshake -> Application\n *\n * Small wrappers around mbedtls_ssl_tls13_evolve_secret().\n */\n\n/**\n * \\brief Begin TLS 1.3 key schedule by calculating early secret.\n *\n *        The TLS 1.3 key schedule can be viewed as a simple state machine\n *        with states Initial -> Early -> Handshake -> Application, and\n *        this function represents the Initial -> Early transition.\n *\n * \\param ssl  The SSL context to operate on.\n *\n * \\returns    \\c 0 on success.\n * \\returns    A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_key_schedule_stage_early(mbedtls_ssl_context *ssl);\n\n/**\n * \\brief Compute TLS 1.3 resumption master secret.\n *\n * \\param ssl  The SSL context to operate on. This must be in\n *             key schedule stage \\c Application, see\n *             mbedtls_ssl_tls13_key_schedule_stage_application().\n *\n * \\returns    \\c 0 on success.\n * \\returns    A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_compute_resumption_master_secret(mbedtls_ssl_context *ssl);\n\n/**\n * \\brief Calculate the verify_data value for the client or server TLS 1.3\n * Finished message.\n *\n * \\param ssl  The SSL context to operate on. This must be in\n *             key schedule stage \\c Handshake, see\n *             mbedtls_ssl_tls13_key_schedule_stage_application().\n * \\param dst        The address at which to write the verify_data value.\n * \\param dst_len    The size of \\p dst in bytes.\n * \\param actual_len The address at which to store the amount of data\n *                   actually written to \\p dst upon success.\n * \\param which      The message to calculate the `verify_data` for:\n *                   - #MBEDTLS_SSL_IS_CLIENT for the Client's Finished message\n *                   - #MBEDTLS_SSL_IS_SERVER for the Server's Finished message\n *\n * \\note       Both client and server call this function twice, once to\n *             generate their own Finished message, and once to verify the\n *             peer's Finished message.\n\n * \\returns    \\c 0 on success.\n * \\returns    A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_calculate_verify_data(mbedtls_ssl_context *ssl,\n                                            unsigned char *dst,\n                                            size_t dst_len,\n                                            size_t *actual_len,\n                                            int which);\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n/**\n * \\brief Compute TLS 1.3 early transform\n *\n * \\param ssl  The SSL context to operate on.\n *\n * \\returns    \\c 0 on success.\n * \\returns    A negative error code on failure.\n *\n * \\warning    The function does not compute the early master secret. Call\n *             mbedtls_ssl_tls13_key_schedule_stage_early() before to\n *             call this function to generate the early master secret.\n * \\note       For a client/server endpoint, the function computes only the\n *             encryption/decryption part of the transform as the decryption/\n *             encryption part is not defined by the specification (no early\n *             traffic from the server to the client).\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_compute_early_transform(mbedtls_ssl_context *ssl);\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n/**\n * \\brief Compute TLS 1.3 handshake transform\n *\n * \\param ssl  The SSL context to operate on. The early secret must have been\n *             computed.\n *\n * \\returns    \\c 0 on success.\n * \\returns    A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_compute_handshake_transform(mbedtls_ssl_context *ssl);\n\n/**\n * \\brief Compute TLS 1.3 application transform\n *\n * \\param ssl  The SSL context to operate on. The early secret must have been\n *             computed.\n *\n * \\returns    \\c 0 on success.\n * \\returns    A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_compute_application_transform(mbedtls_ssl_context *ssl);\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n/**\n * \\brief Export TLS 1.3 PSK from handshake context\n *\n * \\param[in]   ssl  The SSL context to operate on.\n * \\param[out]  psk  PSK output pointer.\n * \\param[out]  psk_len Length of PSK.\n *\n * \\returns     \\c 0 if there is a configured PSK and it was exported\n *              successfully.\n * \\returns     A negative error code on failure.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nint mbedtls_ssl_tls13_export_handshake_psk(mbedtls_ssl_context *ssl,\n                                           unsigned char **psk,\n                                           size_t *psk_len);\n#endif\n\n/**\n * \\brief Calculate TLS-Exporter function as defined in RFC 8446, Section 7.5.\n *\n * \\param[in]   hash_alg  The hash algorithm.\n * \\param[in]   secret  The secret to use. (Should be the exporter master secret.)\n * \\param[in]   secret_len  Length of secret.\n * \\param[in]   label  The label of the exported key.\n * \\param[in]   label_len  The length of label.\n * \\param[out]  out  The output buffer for the exported key. Must have room for at least out_len bytes.\n * \\param[in]   out_len  Length of the key to generate.\n */\nint mbedtls_ssl_tls13_exporter(const psa_algorithm_t hash_alg,\n                               const unsigned char *secret, const size_t secret_len,\n                               const unsigned char *label, const size_t label_len,\n                               const unsigned char *context_value, const size_t context_len,\n                               uint8_t *out, const size_t out_len);\n\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n\n#endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/ssl_tls13_server.c",
    "content": "/*\n *  TLS 1.3 server-side functions\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3)\n\n#include \"debug_internal.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/platform.h\"\n#include \"mbedtls/constant_time.h\"\n#include \"mbedtls/oid.h\"\n#include \"mbedtls/psa_util.h\"\n\n#include \"ssl_misc.h\"\n#include \"ssl_tls13_keys.h\"\n#include \"ssl_debug_helpers.h\"\n\n\nstatic const mbedtls_ssl_ciphersuite_t *ssl_tls13_validate_peer_ciphersuite(\n    mbedtls_ssl_context *ssl,\n    unsigned int cipher_suite)\n{\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;\n    if (!mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, cipher_suite)) {\n        return NULL;\n    }\n\n    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite);\n    if ((mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info,\n                                          ssl->tls_version,\n                                          ssl->tls_version) != 0)) {\n        return NULL;\n    }\n    return ciphersuite_info;\n}\n\nstatic void ssl_tls13_select_ciphersuite(\n    mbedtls_ssl_context *ssl,\n    const unsigned char *cipher_suites,\n    const unsigned char *cipher_suites_end,\n    int psk_ciphersuite_id,\n    psa_algorithm_t psk_hash_alg,\n    const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info)\n{\n    *selected_ciphersuite_info = NULL;\n\n    /*\n     * In a compliant ClientHello the byte-length of the list of ciphersuites\n     * is even and this function relies on this fact. This should have been\n     * checked in the main ClientHello parsing function. Double check here.\n     */\n    if ((cipher_suites_end - cipher_suites) & 1) {\n        return;\n    }\n\n    for (const unsigned char *p = cipher_suites;\n         p < cipher_suites_end; p += 2) {\n        /*\n         * \"cipher_suites_end - p is even\" is an invariant of the loop. As\n         * cipher_suites_end - p > 0, we have cipher_suites_end - p >= 2 and it\n         * is thus safe to read two bytes.\n         */\n        uint16_t id = MBEDTLS_GET_UINT16_BE(p, 0);\n\n        const mbedtls_ssl_ciphersuite_t *info =\n            ssl_tls13_validate_peer_ciphersuite(ssl, id);\n        if (info == NULL) {\n            continue;\n        }\n\n        /*\n         * If a valid PSK ciphersuite identifier has been passed in, we want\n         * an exact match.\n         */\n        if (psk_ciphersuite_id != 0) {\n            if (id != psk_ciphersuite_id) {\n                continue;\n            }\n        } else if (psk_hash_alg != PSA_ALG_NONE) {\n            if (mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac) !=\n                psk_hash_alg) {\n                continue;\n            }\n        }\n\n        *selected_ciphersuite_info = info;\n        return;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"No matched ciphersuite, psk_ciphersuite_id=%x, psk_hash_alg=%lx\",\n                              (unsigned) psk_ciphersuite_id,\n                              (unsigned long) psk_hash_alg));\n}\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n/* From RFC 8446:\n *\n *   enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode;\n *   struct {\n *       PskKeyExchangeMode ke_modes<1..255>;\n *   } PskKeyExchangeModes;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_key_exchange_modes_ext(mbedtls_ssl_context *ssl,\n                                                  const unsigned char *buf,\n                                                  const unsigned char *end)\n{\n    const unsigned char *p = buf;\n    size_t ke_modes_len;\n    int ke_modes = 0;\n\n    /* Read ke_modes length (1 Byte) */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1);\n    ke_modes_len = *p++;\n    /* Currently, there are only two PSK modes, so even without looking\n     * at the content, something's wrong if the list has more than 2 items. */\n    if (ke_modes_len > 2) {\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, ke_modes_len);\n\n    while (ke_modes_len-- != 0) {\n        switch (*p++) {\n            case MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE:\n                ke_modes |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"Found PSK KEX MODE\"));\n                break;\n            case MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE:\n                ke_modes |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"Found PSK_EPHEMERAL KEX MODE\"));\n                break;\n            default:\n                MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n                                             MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n                return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n        }\n    }\n\n    ssl->handshake->tls13_kex_modes = ke_modes;\n    return 0;\n}\n\n/*\n * Non-error return values of\n * ssl_tls13_offered_psks_check_identity_match_ticket() and\n * ssl_tls13_offered_psks_check_identity_match(). They are positive to\n * not collide with error codes that are negative. Zero\n * (SSL_TLS1_3_PSK_IDENTITY_MATCH) in case of success as it may be propagated\n * up by the callers of this function as a generic success condition.\n *\n * The return value SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE means\n * that the pre-shared-key identity matches that of a ticket or an externally-\n * provisioned pre-shared-key. We have thus been able to retrieve the\n * attributes of the pre-shared-key but at least one of them does not meet\n * some criteria and the pre-shared-key cannot be used. For example, a ticket\n * is expired or its version is not TLS 1.3. Note eventually that the return\n * value SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE does not have\n * anything to do with binder check. A binder check is done only when a\n * suitable pre-shared-key has been selected and only for that selected\n * pre-shared-key: if the binder check fails, we fail the handshake and we do\n * not try to find another pre-shared-key for which the binder check would\n * succeed as recommended by the specification.\n */\n#define SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH 2\n#define SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE 1\n#define SSL_TLS1_3_PSK_IDENTITY_MATCH 0\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl);\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl);\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_offered_psks_check_identity_match_ticket(\n    mbedtls_ssl_context *ssl,\n    const unsigned char *identity,\n    size_t identity_len,\n    uint32_t obfuscated_ticket_age,\n    mbedtls_ssl_session *session)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *ticket_buffer;\n#if defined(MBEDTLS_HAVE_TIME)\n    mbedtls_ms_time_t now;\n    mbedtls_ms_time_t server_age;\n    uint32_t client_age;\n    mbedtls_ms_time_t age_diff;\n#endif\n\n    ((void) obfuscated_ticket_age);\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> check_identity_match_ticket\"));\n\n    /* Ticket parser is not configured, Skip */\n    if (ssl->conf->f_ticket_parse == NULL || identity_len == 0) {\n        return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;\n    }\n\n    /* We create a copy of the encrypted ticket since the ticket parsing\n     * function is allowed to use its input buffer as an output buffer\n     * (in-place decryption). We do, however, need the original buffer for\n     * computing the PSK binder value.\n     */\n    ticket_buffer = mbedtls_calloc(1, identity_len);\n    if (ticket_buffer == NULL) {\n        return MBEDTLS_ERR_SSL_ALLOC_FAILED;\n    }\n    memcpy(ticket_buffer, identity, identity_len);\n\n    ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket,\n                                    session,\n                                    ticket_buffer, identity_len);\n    switch (ret) {\n        case 0:\n            ret = SSL_TLS1_3_PSK_IDENTITY_MATCH;\n            break;\n\n        case MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED:\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"ticket is expired\"));\n            ret = SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE;\n            break;\n\n        case MBEDTLS_ERR_SSL_INVALID_MAC:\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"ticket is not authentic\"));\n            ret = SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;\n            break;\n\n        default:\n            MBEDTLS_SSL_DEBUG_RET(1, \"ticket_parse\", ret);\n            ret = SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;\n    }\n\n    /* We delete the temporary buffer */\n    mbedtls_free(ticket_buffer);\n\n    if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) {\n        goto exit;\n    }\n\n    /*\n     * The identity matches that of a ticket. Now check that it has suitable\n     * attributes and bet it will not be the case.\n     */\n    ret = SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE;\n\n    if (session->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"Ticket TLS version is not 1.3.\"));\n        goto exit;\n    }\n\n#if defined(MBEDTLS_HAVE_TIME)\n    now = mbedtls_ms_time();\n\n    if (now < session->ticket_creation_time) {\n        MBEDTLS_SSL_DEBUG_MSG(\n            3, (\"Invalid ticket creation time ( now = %\" MBEDTLS_PRINTF_MS_TIME\n                \", creation_time = %\" MBEDTLS_PRINTF_MS_TIME \" )\",\n                now, session->ticket_creation_time));\n        goto exit;\n    }\n\n    server_age = now - session->ticket_creation_time;\n\n    /* RFC 8446 section 4.6.1\n     *\n     * Servers MUST NOT use any value greater than 604800 seconds (7 days).\n     *\n     * RFC 8446 section 4.2.11.1\n     *\n     * Clients MUST NOT attempt to use tickets which have ages greater than\n     * the \"ticket_lifetime\" value which was provided with the ticket.\n     *\n     */\n    if (server_age > MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME * 1000) {\n        MBEDTLS_SSL_DEBUG_MSG(\n            3, (\"Ticket age exceeds limitation ticket_age = %\" MBEDTLS_PRINTF_MS_TIME,\n                server_age));\n        goto exit;\n    }\n\n    /* RFC 8446 section 4.2.10\n     *\n     * For PSKs provisioned via NewSessionTicket, a server MUST validate that\n     * the ticket age for the selected PSK identity (computed by subtracting\n     * ticket_age_add from PskIdentity.obfuscated_ticket_age modulo 2^32) is\n     * within a small tolerance of the time since the ticket was issued.\n     *\n     * NOTE: The typical accuracy of an RTC crystal is ±100 to ±20 parts per\n     *       million (360 to 72 milliseconds per hour). Default tolerance\n     *       window is 6s, thus in the worst case clients and servers must\n     *       sync up their system time every 6000/360/2~=8 hours.\n     */\n    client_age = obfuscated_ticket_age - session->ticket_age_add;\n    age_diff = server_age - (mbedtls_ms_time_t) client_age;\n    if (age_diff < -MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE ||\n        age_diff > MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE) {\n        MBEDTLS_SSL_DEBUG_MSG(\n            3, (\"Ticket age outside tolerance window ( diff = %\"\n                MBEDTLS_PRINTF_MS_TIME \")\",\n                age_diff));\n        goto exit;\n    }\n#endif /* MBEDTLS_HAVE_TIME */\n\n    /*\n     * All good, we have found a suitable ticket.\n     */\n    ret = SSL_TLS1_3_PSK_IDENTITY_MATCH;\n\nexit:\n    if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) {\n        mbedtls_ssl_session_free(session);\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= check_identity_match_ticket\"));\n    return ret;\n}\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_offered_psks_check_identity_match(\n    mbedtls_ssl_context *ssl,\n    const unsigned char *identity,\n    size_t identity_len,\n    uint32_t obfuscated_ticket_age,\n    int *psk_type,\n    mbedtls_ssl_session *session)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    ((void) session);\n    ((void) obfuscated_ticket_age);\n    *psk_type = MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL;\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"identity\", identity, identity_len);\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n    ret = ssl_tls13_offered_psks_check_identity_match_ticket(\n        ssl, identity, identity_len, obfuscated_ticket_age, session);\n    if (ret == SSL_TLS1_3_PSK_IDENTITY_MATCH) {\n        *psk_type = MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION;\n        ret = mbedtls_ssl_set_hs_psk(ssl,\n                                     session->resumption_key,\n                                     session->resumption_key_len);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_set_hs_psk\", ret);\n            return ret;\n        }\n\n        MBEDTLS_SSL_DEBUG_BUF(4, \"Ticket-resumed PSK:\",\n                              session->resumption_key,\n                              session->resumption_key_len);\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"ticket: obfuscated_ticket_age: %u\",\n                                  (unsigned) obfuscated_ticket_age));\n        return SSL_TLS1_3_PSK_IDENTITY_MATCH;\n    } else if (ret == SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE) {\n        return SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE;\n    }\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n    /* Check identity with external configured function */\n    if (ssl->conf->f_psk != NULL) {\n        if (ssl->conf->f_psk(\n                ssl->conf->p_psk, ssl, identity, identity_len) == 0) {\n            return SSL_TLS1_3_PSK_IDENTITY_MATCH;\n        }\n        return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(5, \"identity\", identity, identity_len);\n    /* Check identity with pre-configured psk */\n    if (ssl->conf->psk_identity != NULL &&\n        identity_len == ssl->conf->psk_identity_len &&\n        mbedtls_ct_memcmp(ssl->conf->psk_identity,\n                          identity, identity_len) == 0) {\n        ret = mbedtls_ssl_set_hs_psk(ssl, ssl->conf->psk, ssl->conf->psk_len);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_set_hs_psk\", ret);\n            return ret;\n        }\n        return SSL_TLS1_3_PSK_IDENTITY_MATCH;\n    }\n\n    return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;\n}\n\n/*\n * Non-error return values of ssl_tls13_offered_psks_check_binder_match().\n * They are positive to not collide with error codes that are negative. Zero\n * (SSL_TLS1_3_BINDER_MATCH) in case of success as it may be propagated up\n * by the callers of this function as a generic success condition.\n */\n#define SSL_TLS1_3_BINDER_DOES_NOT_MATCH 1\n#define SSL_TLS1_3_BINDER_MATCH 0\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_offered_psks_check_binder_match(\n    mbedtls_ssl_context *ssl,\n    const unsigned char *binder, size_t binder_len,\n    int psk_type, psa_algorithm_t psk_hash_alg)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    unsigned char transcript[PSA_HASH_MAX_SIZE];\n    size_t transcript_len;\n    unsigned char *psk;\n    size_t psk_len;\n    unsigned char server_computed_binder[PSA_HASH_MAX_SIZE];\n\n    if (binder_len != PSA_HASH_LENGTH(psk_hash_alg)) {\n        return SSL_TLS1_3_BINDER_DOES_NOT_MATCH;\n    }\n\n    /* Get current state of handshake transcript. */\n    ret = mbedtls_ssl_get_handshake_transcript(\n        ssl, mbedtls_md_type_from_psa_alg(psk_hash_alg),\n        transcript, sizeof(transcript), &transcript_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_ssl_tls13_export_handshake_psk(ssl, &psk, &psk_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_ssl_tls13_create_psk_binder(ssl, psk_hash_alg,\n                                              psk, psk_len, psk_type,\n                                              transcript,\n                                              server_computed_binder);\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    mbedtls_free((void *) psk);\n#endif\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"PSK binder calculation failed.\"));\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"psk binder ( computed ): \",\n                          server_computed_binder, transcript_len);\n    MBEDTLS_SSL_DEBUG_BUF(3, \"psk binder ( received ): \", binder, binder_len);\n\n    if (mbedtls_ct_memcmp(server_computed_binder,\n                          binder,\n                          PSA_HASH_LENGTH(psk_hash_alg)) == 0) {\n        return SSL_TLS1_3_BINDER_MATCH;\n    }\n\n    mbedtls_platform_zeroize(server_computed_binder,\n                             sizeof(server_computed_binder));\n    return SSL_TLS1_3_BINDER_DOES_NOT_MATCH;\n}\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_session_copy_ticket(mbedtls_ssl_session *dst,\n                                         const mbedtls_ssl_session *src)\n{\n    dst->ticket_age_add = src->ticket_age_add;\n    dst->ticket_flags = src->ticket_flags;\n    dst->resumption_key_len = src->resumption_key_len;\n    if (src->resumption_key_len == 0) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n    memcpy(dst->resumption_key, src->resumption_key, src->resumption_key_len);\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    dst->max_early_data_size = src->max_early_data_size;\n\n#if defined(MBEDTLS_SSL_ALPN)\n    int ret = mbedtls_ssl_session_set_ticket_alpn(dst, src->ticket_alpn);\n    if (ret != 0) {\n        return ret;\n    }\n#endif /* MBEDTLS_SSL_ALPN */\n#endif /* MBEDTLS_SSL_EARLY_DATA*/\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\nstruct psk_attributes {\n    int type;\n    int key_exchange_mode;\n    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;\n};\n#define PSK_ATTRIBUTES_INIT { 0, 0, NULL }\n\n/* Parser for pre_shared_key extension in client hello\n *    struct {\n *        opaque identity<1..2^16-1>;\n *        uint32 obfuscated_ticket_age;\n *    } PskIdentity;\n *\n *    opaque PskBinderEntry<32..255>;\n *\n *    struct {\n *        PskIdentity identities<7..2^16-1>;\n *        PskBinderEntry binders<33..2^16-1>;\n *    } OfferedPsks;\n *\n *    struct {\n *        select (Handshake.msg_type) {\n *            case client_hello: OfferedPsks;\n *            ....\n *        };\n *    } PreSharedKeyExtension;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_pre_shared_key_ext(\n    mbedtls_ssl_context *ssl,\n    const unsigned char *pre_shared_key_ext,\n    const unsigned char *pre_shared_key_ext_end,\n    const unsigned char *ciphersuites,\n    const unsigned char *ciphersuites_end,\n    struct psk_attributes *psk)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const unsigned char *identities = pre_shared_key_ext;\n    const unsigned char *p_identity_len;\n    size_t identities_len;\n    const unsigned char *identities_end;\n    const unsigned char *binders;\n    const unsigned char *p_binder_len;\n    size_t binders_len;\n    const unsigned char *binders_end;\n    int matched_identity = -1;\n    int identity_id = -1;\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"pre_shared_key extension\",\n                          pre_shared_key_ext,\n                          pre_shared_key_ext_end - pre_shared_key_ext);\n\n    /* identities_len       2 bytes\n     * identities_data   >= 7 bytes\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(identities, pre_shared_key_ext_end, 7 + 2);\n    identities_len = MBEDTLS_GET_UINT16_BE(identities, 0);\n    p_identity_len = identities + 2;\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p_identity_len, pre_shared_key_ext_end,\n                                 identities_len);\n    identities_end = p_identity_len + identities_len;\n\n    /* binders_len     2  bytes\n     * binders      >= 33 bytes\n     */\n    binders = identities_end;\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(binders, pre_shared_key_ext_end, 33 + 2);\n    binders_len = MBEDTLS_GET_UINT16_BE(binders, 0);\n    p_binder_len = binders + 2;\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p_binder_len, pre_shared_key_ext_end, binders_len);\n    binders_end = p_binder_len + binders_len;\n\n    ret = ssl->handshake->update_checksum(ssl, pre_shared_key_ext,\n                                          identities_end - pre_shared_key_ext);\n    if (0 != ret) {\n        MBEDTLS_SSL_DEBUG_RET(1, (\"update_checksum\"), ret);\n        return ret;\n    }\n\n    while (p_identity_len < identities_end && p_binder_len < binders_end) {\n        const unsigned char *identity;\n        size_t identity_len;\n        uint32_t obfuscated_ticket_age;\n        const unsigned char *binder;\n        size_t binder_len;\n        int psk_ciphersuite_id;\n        psa_algorithm_t psk_hash_alg;\n        int allowed_key_exchange_modes;\n\n        mbedtls_ssl_session session;\n        mbedtls_ssl_session_init(&session);\n\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p_identity_len, identities_end, 2 + 1 + 4);\n        identity_len = MBEDTLS_GET_UINT16_BE(p_identity_len, 0);\n        identity = p_identity_len + 2;\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(identity, identities_end, identity_len + 4);\n        obfuscated_ticket_age = MBEDTLS_GET_UINT32_BE(identity, identity_len);\n        p_identity_len += identity_len + 6;\n\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p_binder_len, binders_end, 1 + 32);\n        binder_len = *p_binder_len;\n        binder = p_binder_len + 1;\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(binder, binders_end, binder_len);\n        p_binder_len += binder_len + 1;\n\n        identity_id++;\n        if (matched_identity != -1) {\n            continue;\n        }\n\n        ret = ssl_tls13_offered_psks_check_identity_match(\n            ssl, identity, identity_len, obfuscated_ticket_age,\n            &psk->type, &session);\n        if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) {\n            continue;\n        }\n\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"found matched identity\"));\n\n        switch (psk->type) {\n            case MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL:\n                psk_ciphersuite_id = 0;\n                psk_hash_alg = PSA_ALG_SHA_256;\n                allowed_key_exchange_modes =\n                    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL;\n                break;\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n            case MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION:\n                psk_ciphersuite_id = session.ciphersuite;\n                psk_hash_alg = PSA_ALG_NONE;\n                ssl->session_negotiate->ticket_flags = session.ticket_flags;\n                allowed_key_exchange_modes =\n                    session.ticket_flags &\n                    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL;\n                break;\n#endif\n            default:\n                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        }\n\n        psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE;\n\n        if ((allowed_key_exchange_modes &\n             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) &&\n            ssl_tls13_key_exchange_is_psk_ephemeral_available(ssl)) {\n            psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;\n        } else if ((allowed_key_exchange_modes &\n                    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) &&\n                   ssl_tls13_key_exchange_is_psk_available(ssl)) {\n            psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;\n        }\n\n        if (psk->key_exchange_mode == MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE) {\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"No suitable PSK key exchange mode\"));\n            continue;\n        }\n\n        ssl_tls13_select_ciphersuite(ssl, ciphersuites, ciphersuites_end,\n                                     psk_ciphersuite_id, psk_hash_alg,\n                                     &psk->ciphersuite_info);\n\n        if (psk->ciphersuite_info == NULL) {\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n            mbedtls_ssl_session_free(&session);\n#endif\n            /*\n             * We consider finding a ciphersuite suitable for the PSK as part\n             * of the validation of its binder. Thus if we do not find one, we\n             * abort the handshake with a decrypt_error alert.\n             */\n            MBEDTLS_SSL_PEND_FATAL_ALERT(\n                MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR,\n                MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);\n            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n        }\n\n        ret = ssl_tls13_offered_psks_check_binder_match(\n            ssl, binder, binder_len, psk->type,\n            mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) psk->ciphersuite_info->mac));\n        if (ret != SSL_TLS1_3_BINDER_MATCH) {\n            /* For security reasons, the handshake should be aborted when we\n             * fail to validate a binder value. See RFC 8446 section 4.2.11.2\n             * and appendix E.6. */\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n            mbedtls_ssl_session_free(&session);\n#endif\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"Invalid binder.\"));\n            MBEDTLS_SSL_DEBUG_RET(\n                1, \"ssl_tls13_offered_psks_check_binder_match\", ret);\n            MBEDTLS_SSL_PEND_FATAL_ALERT(\n                MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR,\n                MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);\n            return ret;\n        }\n\n        matched_identity = identity_id;\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n        if (psk->type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {\n            ret = ssl_tls13_session_copy_ticket(ssl->session_negotiate,\n                                                &session);\n            mbedtls_ssl_session_free(&session);\n            if (ret != 0) {\n                return ret;\n            }\n        }\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n    }\n\n    if (p_identity_len != identities_end || p_binder_len != binders_end) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"pre_shared_key extension decode error\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,\n                                     MBEDTLS_ERR_SSL_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /* Update the handshake transcript with the binder list. */\n    ret = ssl->handshake->update_checksum(\n        ssl, identities_end, (size_t) (binders_end - identities_end));\n    if (0 != ret) {\n        MBEDTLS_SSL_DEBUG_RET(1, (\"update_checksum\"), ret);\n        return ret;\n    }\n    if (matched_identity == -1) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"No usable PSK or ticket.\"));\n        return MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;\n    }\n\n    ssl->handshake->selected_identity = (uint16_t) matched_identity;\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"Pre shared key found\"));\n\n    return 0;\n}\n\n/*\n * struct {\n *   select ( Handshake.msg_type ) {\n *      ....\n *      case server_hello:\n *          uint16 selected_identity;\n *   }\n * } PreSharedKeyExtension;\n */\nstatic int ssl_tls13_write_server_pre_shared_key_ext(mbedtls_ssl_context *ssl,\n                                                     unsigned char *buf,\n                                                     unsigned char *end,\n                                                     size_t *olen)\n{\n    unsigned char *p = (unsigned char *) buf;\n\n    *olen = 0;\n\n    int not_using_psk = 0;\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    not_using_psk = (mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque));\n#else\n    not_using_psk = (ssl->handshake->psk == NULL);\n#endif\n    if (not_using_psk) {\n        /* We shouldn't have called this extension writer unless we've\n         * chosen to use a PSK. */\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, adding pre_shared_key extension\"));\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PRE_SHARED_KEY, p, 0);\n    MBEDTLS_PUT_UINT16_BE(2, p, 2);\n\n    MBEDTLS_PUT_UINT16_BE(ssl->handshake->selected_identity, p, 4);\n\n    *olen = 6;\n\n    MBEDTLS_SSL_DEBUG_MSG(4, (\"sent selected_identity: %u\",\n                              ssl->handshake->selected_identity));\n\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_PRE_SHARED_KEY);\n\n    return 0;\n}\n\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */\n\n/* From RFC 8446:\n *   struct {\n *          ProtocolVersion versions<2..254>;\n *   } SupportedVersions;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_supported_versions_ext(mbedtls_ssl_context *ssl,\n                                                  const unsigned char *buf,\n                                                  const unsigned char *end)\n{\n    const unsigned char *p = buf;\n    size_t versions_len;\n    const unsigned char *versions_end;\n    uint16_t tls_version;\n    int found_supported_version = 0;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1);\n    versions_len = p[0];\n    p += 1;\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, versions_len);\n    versions_end = p + versions_len;\n    while (p < versions_end) {\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, versions_end, 2);\n        tls_version = mbedtls_ssl_read_version(p, ssl->conf->transport);\n        p += 2;\n\n        if (MBEDTLS_SSL_VERSION_TLS1_3 == tls_version) {\n            found_supported_version = 1;\n            break;\n        }\n\n        if ((MBEDTLS_SSL_VERSION_TLS1_2 == tls_version) &&\n            mbedtls_ssl_conf_is_tls12_enabled(ssl->conf)) {\n            found_supported_version = 1;\n            break;\n        }\n    }\n\n    if (!found_supported_version) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"No supported version found.\"));\n\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION,\n                                     MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION);\n        return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(1, (\"Negotiated version: [%04x]\",\n                              (unsigned int) tls_version));\n\n    return (int) tls_version;\n}\n\n#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)\n/*\n *\n * From RFC 8446:\n *   enum {\n *       ... (0xFFFF)\n *   } NamedGroup;\n *   struct {\n *       NamedGroup named_group_list<2..2^16-1>;\n *   } NamedGroupList;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_supported_groups_ext(mbedtls_ssl_context *ssl,\n                                                const unsigned char *buf,\n                                                const unsigned char *end)\n{\n    const unsigned char *p = buf;\n    size_t named_group_list_len;\n    const unsigned char *named_group_list_end;\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"supported_groups extension\", p, end - buf);\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    named_group_list_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, named_group_list_len);\n    named_group_list_end = p + named_group_list_len;\n    ssl->handshake->hrr_selected_group = 0;\n\n    while (p < named_group_list_end) {\n        uint16_t named_group;\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, named_group_list_end, 2);\n        named_group = MBEDTLS_GET_UINT16_BE(p, 0);\n        p += 2;\n\n        MBEDTLS_SSL_DEBUG_MSG(2,\n                              (\"got named group: %s(%04x)\",\n                               mbedtls_ssl_named_group_to_str(named_group),\n                               named_group));\n\n        if (!mbedtls_ssl_named_group_is_offered(ssl, named_group) ||\n            !mbedtls_ssl_named_group_is_supported(named_group) ||\n            ssl->handshake->hrr_selected_group != 0) {\n            continue;\n        }\n\n        MBEDTLS_SSL_DEBUG_MSG(2,\n                              (\"add named group %s(%04x) into received list.\",\n                               mbedtls_ssl_named_group_to_str(named_group),\n                               named_group));\n\n        ssl->handshake->hrr_selected_group = named_group;\n    }\n\n    return 0;\n\n}\n#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */\n\n#define SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH 1\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)\n/*\n *  ssl_tls13_parse_key_shares_ext() verifies whether the information in the\n *  extension is correct and stores the first acceptable key share and its\n *  associated group.\n *\n *  Possible return values are:\n *  - 0: Successful processing of the client provided key share extension.\n *  - SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH: The key shares provided by\n *    the client does not match a group supported by the server. A\n *    HelloRetryRequest will be needed.\n *  - A negative value for fatal errors.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_key_shares_ext(mbedtls_ssl_context *ssl,\n                                          const unsigned char *buf,\n                                          const unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char const *p = buf;\n    unsigned char const *client_shares_end;\n    size_t client_shares_len;\n\n    /* From RFC 8446:\n     *\n     * struct {\n     *     KeyShareEntry client_shares<0..2^16-1>;\n     * } KeyShareClientHello;\n     *\n     */\n\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);\n    client_shares_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, client_shares_len);\n\n    ssl->handshake->offered_group_id = 0;\n    client_shares_end = p + client_shares_len;\n\n    /* We try to find a suitable key share entry and copy it to the\n     * handshake context. Later, we have to find out whether we can do\n     * something with the provided key share or whether we have to\n     * dismiss it and send a HelloRetryRequest message.\n     */\n\n    while (p < client_shares_end) {\n        uint16_t group;\n        size_t key_exchange_len;\n        const unsigned char *key_exchange;\n\n        /*\n         * struct {\n         *    NamedGroup group;\n         *    opaque key_exchange<1..2^16-1>;\n         * } KeyShareEntry;\n         */\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, client_shares_end, 4);\n        group = MBEDTLS_GET_UINT16_BE(p, 0);\n        key_exchange_len = MBEDTLS_GET_UINT16_BE(p, 2);\n        p += 4;\n        key_exchange = p;\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, client_shares_end, key_exchange_len);\n        p += key_exchange_len;\n\n        /* Continue parsing even if we have already found a match,\n         * for input validation purposes.\n         */\n        if (!mbedtls_ssl_named_group_is_offered(ssl, group) ||\n            !mbedtls_ssl_named_group_is_supported(group) ||\n            ssl->handshake->offered_group_id != 0) {\n            continue;\n        }\n\n        /*\n         * ECDHE and FFDHE groups are supported\n         */\n        if (mbedtls_ssl_tls13_named_group_is_ecdhe(group) ||\n            mbedtls_ssl_tls13_named_group_is_ffdh(group)) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"ECDH/FFDH group: %s (%04x)\",\n                                      mbedtls_ssl_named_group_to_str(group),\n                                      group));\n            ret = mbedtls_ssl_tls13_read_public_xxdhe_share(\n                ssl, key_exchange - 2, key_exchange_len + 2);\n            if (ret != 0) {\n                return ret;\n            }\n\n        } else {\n            MBEDTLS_SSL_DEBUG_MSG(4, (\"Unrecognized NamedGroup %u\",\n                                      (unsigned) group));\n            continue;\n        }\n\n        ssl->handshake->offered_group_id = group;\n    }\n\n\n    if (ssl->handshake->offered_group_id == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"no matching key share\"));\n        return SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH;\n    }\n    return 0;\n}\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_client_hello_has_exts(mbedtls_ssl_context *ssl,\n                                           int exts_mask)\n{\n    int masked = ssl->handshake->received_extensions & exts_mask;\n    return masked == exts_mask;\n}\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange(\n    mbedtls_ssl_context *ssl)\n{\n    return ssl_tls13_client_hello_has_exts(\n        ssl,\n        MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) |\n        MBEDTLS_SSL_EXT_MASK(KEY_SHARE)        |\n        MBEDTLS_SSL_EXT_MASK(SIG_ALG));\n}\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_client_hello_has_exts_for_psk_key_exchange(\n    mbedtls_ssl_context *ssl)\n{\n    return ssl_tls13_client_hello_has_exts(\n        ssl,\n        MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)          |\n        MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES));\n}\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED */\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange(\n    mbedtls_ssl_context *ssl)\n{\n    return ssl_tls13_client_hello_has_exts(\n        ssl,\n        MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS)        |\n        MBEDTLS_SSL_EXT_MASK(KEY_SHARE)               |\n        MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)          |\n        MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES));\n}\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED */\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl)\n{\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED)\n    return mbedtls_ssl_conf_tls13_is_psk_enabled(ssl) &&\n           mbedtls_ssl_tls13_is_psk_supported(ssl) &&\n           ssl_tls13_client_hello_has_exts_for_psk_key_exchange(ssl);\n#else\n    ((void) ssl);\n    return 0;\n#endif\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl)\n{\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)\n    return mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(ssl) &&\n           mbedtls_ssl_tls13_is_psk_ephemeral_supported(ssl) &&\n           ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange(ssl);\n#else\n    ((void) ssl);\n    return 0;\n#endif\n}\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_key_exchange_is_ephemeral_available(mbedtls_ssl_context *ssl)\n{\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n    return mbedtls_ssl_conf_tls13_is_ephemeral_enabled(ssl) &&\n           ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange(ssl);\n#else\n    ((void) ssl);\n    return 0;\n#endif\n}\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C) && \\\n    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\nstatic psa_algorithm_t ssl_tls13_iana_sig_alg_to_psa_alg(uint16_t sig_alg)\n{\n    switch (sig_alg) {\n        case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256:\n            return PSA_ALG_ECDSA(PSA_ALG_SHA_256);\n        case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384:\n            return PSA_ALG_ECDSA(PSA_ALG_SHA_384);\n        case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512:\n            return PSA_ALG_ECDSA(PSA_ALG_SHA_512);\n        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256:\n            return PSA_ALG_RSA_PSS(PSA_ALG_SHA_256);\n        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384:\n            return PSA_ALG_RSA_PSS(PSA_ALG_SHA_384);\n        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512:\n            return PSA_ALG_RSA_PSS(PSA_ALG_SHA_512);\n        case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256:\n            return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256);\n        case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384:\n            return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_384);\n        case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512:\n            return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_512);\n        default:\n            return PSA_ALG_NONE;\n    }\n}\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n/*\n * Pick best ( private key, certificate chain ) pair based on the signature\n * algorithms supported by the client.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_pick_key_cert(mbedtls_ssl_context *ssl)\n{\n    mbedtls_ssl_key_cert *key_cert, *key_cert_list;\n    const uint16_t *sig_alg = ssl->handshake->received_sig_algs;\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    if (ssl->handshake->sni_key_cert != NULL) {\n        key_cert_list = ssl->handshake->sni_key_cert;\n    } else\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n    key_cert_list = ssl->conf->key_cert;\n\n    if (key_cert_list == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"server has no certificate\"));\n        return -1;\n    }\n\n    for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) {\n        if (!mbedtls_ssl_sig_alg_is_offered(ssl, *sig_alg)) {\n            continue;\n        }\n\n        if (!mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(*sig_alg)) {\n            continue;\n        }\n\n        for (key_cert = key_cert_list; key_cert != NULL;\n             key_cert = key_cert->next) {\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n            psa_algorithm_t psa_alg = PSA_ALG_NONE;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n            MBEDTLS_SSL_DEBUG_CRT(3, \"certificate (chain) candidate\",\n                                  key_cert->cert);\n\n            /*\n             * This avoids sending the client a cert it'll reject based on\n             * keyUsage or other extensions.\n             */\n            if (mbedtls_x509_crt_check_key_usage(\n                    key_cert->cert, MBEDTLS_X509_KU_DIGITAL_SIGNATURE) != 0 ||\n                mbedtls_x509_crt_check_extended_key_usage(\n                    key_cert->cert, MBEDTLS_OID_SERVER_AUTH,\n                    MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH)) != 0) {\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"certificate mismatch: \"\n                                          \"(extended) key usage extension\"));\n                continue;\n            }\n\n            MBEDTLS_SSL_DEBUG_MSG(3,\n                                  (\"ssl_tls13_pick_key_cert:\"\n                                   \"check signature algorithm %s [%04x]\",\n                                   mbedtls_ssl_sig_alg_to_str(*sig_alg),\n                                   *sig_alg));\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n            psa_alg = ssl_tls13_iana_sig_alg_to_psa_alg(*sig_alg);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n            if (mbedtls_ssl_tls13_check_sig_alg_cert_key_match(\n                    *sig_alg, &key_cert->cert->pk)\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n                && psa_alg != PSA_ALG_NONE &&\n                mbedtls_pk_can_do_ext(&key_cert->cert->pk, psa_alg,\n                                      PSA_KEY_USAGE_SIGN_HASH) == 1\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n                ) {\n                ssl->handshake->key_cert = key_cert;\n                MBEDTLS_SSL_DEBUG_MSG(3,\n                                      (\"ssl_tls13_pick_key_cert:\"\n                                       \"selected signature algorithm\"\n                                       \" %s [%04x]\",\n                                       mbedtls_ssl_sig_alg_to_str(*sig_alg),\n                                       *sig_alg));\n                MBEDTLS_SSL_DEBUG_CRT(\n                    3, \"selected certificate (chain)\",\n                    ssl->handshake->key_cert->cert);\n                return 0;\n            }\n        }\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"ssl_tls13_pick_key_cert:\"\n                              \"no suitable certificate found\"));\n    return -1;\n}\n#endif /* MBEDTLS_X509_CRT_PARSE_C &&\n          MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\n/*\n *\n * STATE HANDLING: ClientHello\n *\n * There are three possible classes of outcomes when parsing the ClientHello:\n *\n * 1) The ClientHello was well-formed and matched the server's configuration.\n *\n *    In this case, the server progresses to sending its ServerHello.\n *\n * 2) The ClientHello was well-formed but didn't match the server's\n *    configuration.\n *\n *    For example, the client might not have offered a key share which\n *    the server supports, or the server might require a cookie.\n *\n *    In this case, the server sends a HelloRetryRequest.\n *\n * 3) The ClientHello was ill-formed\n *\n *    In this case, we abort the handshake.\n *\n */\n\n/*\n * Structure of this message:\n *\n * uint16 ProtocolVersion;\n * opaque Random[32];\n * uint8 CipherSuite[2];    // Cryptographic suite selector\n *\n * struct {\n *      ProtocolVersion legacy_version = 0x0303;    // TLS v1.2\n *      Random random;\n *      opaque legacy_session_id<0..32>;\n *      CipherSuite cipher_suites<2..2^16-2>;\n *      opaque legacy_compression_methods<1..2^8-1>;\n *      Extension extensions<8..2^16-1>;\n * } ClientHello;\n */\n\n#define SSL_CLIENT_HELLO_OK           0\n#define SSL_CLIENT_HELLO_HRR_REQUIRED 1\n#define SSL_CLIENT_HELLO_TLS1_2       2\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,\n                                        const unsigned char *buf,\n                                        const unsigned char *end)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const unsigned char *p = buf;\n    const unsigned char *random;\n    size_t legacy_session_id_len;\n    const unsigned char *legacy_session_id;\n    size_t cipher_suites_len;\n    const unsigned char *cipher_suites;\n    const unsigned char *cipher_suites_end;\n    size_t extensions_len;\n    const unsigned char *extensions_end;\n    const unsigned char *supported_versions_data;\n    const unsigned char *supported_versions_data_end;\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n    int hrr_required = 0;\n    int no_usable_share_for_key_agreement = 0;\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n    int got_psk = 0;\n    struct psk_attributes psk = PSK_ATTRIBUTES_INIT;\n    const unsigned char *pre_shared_key_ext = NULL;\n    const unsigned char *pre_shared_key_ext_end = NULL;\n#endif\n\n    /*\n     * ClientHello layout:\n     *     0  .   1   protocol version\n     *     2  .  33   random bytes\n     *    34  .  34   session id length ( 1 byte )\n     *    35  . 34+x  session id\n     *    ..  .  ..   ciphersuite list length ( 2 bytes )\n     *    ..  .  ..   ciphersuite list\n     *    ..  .  ..   compression alg. list length ( 1 byte )\n     *    ..  .  ..   compression alg. list\n     *    ..  .  ..   extensions length ( 2 bytes, optional )\n     *    ..  .  ..   extensions ( optional )\n     */\n\n    /*\n     * Minimal length ( with everything empty and extensions omitted ) is\n     * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can\n     * read at least up to session id length without worrying.\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 38);\n\n    /* ...\n     * ProtocolVersion legacy_version = 0x0303; // TLS 1.2\n     * ...\n     * with ProtocolVersion defined as:\n     * uint16 ProtocolVersion;\n     */\n    if (mbedtls_ssl_read_version(p, ssl->conf->transport) !=\n        MBEDTLS_SSL_VERSION_TLS1_2) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Unsupported version of TLS.\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION,\n                                     MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION);\n        return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;\n    }\n    p += 2;\n\n    /* ...\n     * Random random;\n     * ...\n     * with Random defined as:\n     * opaque Random[32];\n     */\n    random = p;\n    p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN;\n\n    /* ...\n     * opaque legacy_session_id<0..32>;\n     * ...\n     */\n    legacy_session_id_len = *(p++);\n    legacy_session_id = p;\n\n    /*\n     * Check we have enough data for the legacy session identifier\n     * and the ciphersuite list length.\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_len + 2);\n    p += legacy_session_id_len;\n\n    /* ...\n     * CipherSuite cipher_suites<2..2^16-2>;\n     * ...\n     * with CipherSuite defined as:\n     * uint8 CipherSuite[2];\n     */\n    cipher_suites_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n    cipher_suites = p;\n\n    /*\n     * The length of the ciphersuite list has to be even.\n     */\n    if (cipher_suites_len & 1) {\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,\n                                     MBEDTLS_ERR_SSL_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n\n    /* Check we have enough data for the ciphersuite list, the legacy\n     * compression methods and the length of the extensions.\n     *\n     * cipher_suites                cipher_suites_len bytes\n     * legacy_compression_methods length            1 byte\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cipher_suites_len + 1);\n    p += cipher_suites_len;\n    cipher_suites_end = p;\n\n    /* Check if we have enough data for legacy_compression_methods\n     * and the length of the extensions (2 bytes).\n     */\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p + 1, end, p[0] + 2);\n\n    /*\n     * Search for the supported versions extension and parse it to determine\n     * if the client supports TLS 1.3.\n     */\n    ret = mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts(\n        ssl, p + 1 + p[0], end,\n        &supported_versions_data, &supported_versions_data_end);\n    if (ret < 0) {\n        MBEDTLS_SSL_DEBUG_RET(1,\n                              (\"mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts\"), ret);\n        return ret;\n    }\n\n    if (ret == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"no supported_versions extension\"));\n        return SSL_CLIENT_HELLO_TLS1_2;\n    }\n\n    if (ret == 1) {\n        ret = ssl_tls13_parse_supported_versions_ext(ssl,\n                                                     supported_versions_data,\n                                                     supported_versions_data_end);\n        if (ret < 0) {\n            MBEDTLS_SSL_DEBUG_RET(1,\n                                  (\"ssl_tls13_parse_supported_versions_ext\"), ret);\n            return ret;\n        }\n\n        /*\n         * The supported versions extension was parsed successfully as the\n         * value returned by ssl_tls13_parse_supported_versions_ext() is\n         * positive. The return value is then equal to\n         * MBEDTLS_SSL_VERSION_TLS1_2 or MBEDTLS_SSL_VERSION_TLS1_3, defining\n         * the TLS version to negotiate.\n         */\n        if (MBEDTLS_SSL_VERSION_TLS1_2 == ret) {\n            MBEDTLS_SSL_DEBUG_MSG(2, (\"supported_versions without 1.3\"));\n            return SSL_CLIENT_HELLO_TLS1_2;\n        }\n    }\n\n    /*\n     * We negotiate TLS 1.3.\n     */\n    ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_3;\n    ssl->session_negotiate->tls_version = MBEDTLS_SSL_VERSION_TLS1_3;\n    ssl->session_negotiate->endpoint = ssl->conf->endpoint;\n\n    /* Before doing any crypto, make sure we can. */\n    ret = mbedtls_ssl_tls13_crypto_init(ssl);\n    if (ret != 0) {\n        return ret;\n    }\n\n    /*\n     * We are negotiating the version 1.3 of the protocol. Do what we have\n     * postponed: copy of the client random bytes, copy of the legacy session\n     * identifier and selection of the TLS 1.3 cipher suite.\n     */\n    MBEDTLS_SSL_DEBUG_BUF(3, \"client hello, random bytes\",\n                          random, MBEDTLS_CLIENT_HELLO_RANDOM_LEN);\n    memcpy(&handshake->randbytes[0], random, MBEDTLS_CLIENT_HELLO_RANDOM_LEN);\n\n    if (legacy_session_id_len > sizeof(ssl->session_negotiate->id)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad client hello message\"));\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n    ssl->session_negotiate->id_len = legacy_session_id_len;\n    MBEDTLS_SSL_DEBUG_BUF(3, \"client hello, session id\",\n                          legacy_session_id, legacy_session_id_len);\n    memcpy(&ssl->session_negotiate->id[0],\n           legacy_session_id, legacy_session_id_len);\n\n    /*\n     * Search for a matching ciphersuite\n     */\n    MBEDTLS_SSL_DEBUG_BUF(3, \"client hello, list of cipher suites\",\n                          cipher_suites, cipher_suites_len);\n\n    ssl_tls13_select_ciphersuite(ssl, cipher_suites, cipher_suites_end,\n                                 0, PSA_ALG_NONE, &handshake->ciphersuite_info);\n\n    if (handshake->ciphersuite_info == NULL) {\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,\n                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n    ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"selected ciphersuite: %04x - %s\",\n                              ((unsigned) handshake->ciphersuite_info->id),\n                              handshake->ciphersuite_info->name));\n\n    /* ...\n     * opaque legacy_compression_methods<1..2^8-1>;\n     * ...\n     */\n    if (p[0] != 1 || p[1] != MBEDTLS_SSL_COMPRESS_NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"bad legacy compression method\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n    p += 2;\n\n    /* ...\n     * Extension extensions<8..2^16-1>;\n     * ...\n     * with Extension defined as:\n     * struct {\n     *    ExtensionType extension_type;\n     *    opaque extension_data<0..2^16-1>;\n     * } Extension;\n     */\n    extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);\n    p += 2;\n    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);\n    extensions_end = p + extensions_len;\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"client hello extensions\", p, extensions_len);\n    handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;\n\n    while (p < extensions_end) {\n        unsigned int extension_type;\n        size_t extension_data_len;\n        const unsigned char *extension_data_end;\n        uint32_t allowed_exts = MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH;\n\n        if (ssl->handshake->hello_retry_request_flag) {\n            /* Do not accept early data extension in 2nd ClientHello */\n            allowed_exts &= ~MBEDTLS_SSL_EXT_MASK(EARLY_DATA);\n        }\n\n        /* RFC 8446, section 4.2.11\n         *\n         * The \"pre_shared_key\" extension MUST be the last extension in the\n         * ClientHello (this facilitates implementation as described below).\n         * Servers MUST check that it is the last extension and otherwise fail\n         * the handshake with an \"illegal_parameter\" alert.\n         */\n        if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)) {\n            MBEDTLS_SSL_DEBUG_MSG(\n                3, (\"pre_shared_key is not last extension.\"));\n            MBEDTLS_SSL_PEND_FATAL_ALERT(\n                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n                MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n        }\n\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);\n        extension_type = MBEDTLS_GET_UINT16_BE(p, 0);\n        extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);\n        p += 4;\n\n        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);\n        extension_data_end = p + extension_data_len;\n\n        ret = mbedtls_ssl_tls13_check_received_extension(\n            ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, extension_type,\n            allowed_exts);\n        if (ret != 0) {\n            return ret;\n        }\n\n        switch (extension_type) {\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n            case MBEDTLS_TLS_EXT_SERVERNAME:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found ServerName extension\"));\n                ret = mbedtls_ssl_parse_server_name_ext(ssl, p,\n                                                        extension_data_end);\n                if (ret != 0) {\n                    MBEDTLS_SSL_DEBUG_RET(\n                        1, \"mbedtls_ssl_parse_servername_ext\", ret);\n                    return ret;\n                }\n                break;\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)\n            case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found supported group extension\"));\n\n                /* Supported Groups Extension\n                 *\n                 * When sent by the client, the \"supported_groups\" extension\n                 * indicates the named groups which the client supports,\n                 * ordered from most preferred to least preferred.\n                 */\n                ret = ssl_tls13_parse_supported_groups_ext(\n                    ssl, p, extension_data_end);\n                if (ret != 0) {\n                    MBEDTLS_SSL_DEBUG_RET(\n                        1, \"ssl_tls13_parse_supported_groups_ext\", ret);\n                    return ret;\n                }\n\n                break;\n#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH*/\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)\n            case MBEDTLS_TLS_EXT_KEY_SHARE:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found key share extension\"));\n\n                /*\n                 * Key Share Extension\n                 *\n                 * When sent by the client, the \"key_share\" extension\n                 * contains the endpoint's cryptographic parameters for\n                 * ECDHE/DHE key establishment methods.\n                 */\n                ret = ssl_tls13_parse_key_shares_ext(\n                    ssl, p, extension_data_end);\n                if (ret == SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH) {\n                    MBEDTLS_SSL_DEBUG_MSG(2, (\"No usable share for key agreement.\"));\n                    no_usable_share_for_key_agreement = 1;\n                }\n\n                if (ret < 0) {\n                    MBEDTLS_SSL_DEBUG_RET(\n                        1, \"ssl_tls13_parse_key_shares_ext\", ret);\n                    return ret;\n                }\n\n                break;\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */\n\n            case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS:\n                /* Already parsed */\n                break;\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n            case MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES:\n                MBEDTLS_SSL_DEBUG_MSG(\n                    3, (\"found psk key exchange modes extension\"));\n\n                ret = ssl_tls13_parse_key_exchange_modes_ext(\n                    ssl, p, extension_data_end);\n                if (ret != 0) {\n                    MBEDTLS_SSL_DEBUG_RET(\n                        1, \"ssl_tls13_parse_key_exchange_modes_ext\", ret);\n                    return ret;\n                }\n\n                break;\n#endif\n\n            case MBEDTLS_TLS_EXT_PRE_SHARED_KEY:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found pre_shared_key extension\"));\n                if ((handshake->received_extensions &\n                     MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)) == 0) {\n                    MBEDTLS_SSL_PEND_FATAL_ALERT(\n                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,\n                        MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n                    return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n                }\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n                /* Delay processing of the PSK identity once we have\n                 * found out which algorithms to use. We keep a pointer\n                 * to the buffer and the size for later processing.\n                 */\n                pre_shared_key_ext = p;\n                pre_shared_key_ext_end = extension_data_end;\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */\n                break;\n\n#if defined(MBEDTLS_SSL_ALPN)\n            case MBEDTLS_TLS_EXT_ALPN:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found alpn extension\"));\n\n                ret = mbedtls_ssl_parse_alpn_ext(ssl, p, extension_data_end);\n                if (ret != 0) {\n                    MBEDTLS_SSL_DEBUG_RET(\n                        1, (\"mbedtls_ssl_parse_alpn_ext\"), ret);\n                    return ret;\n                }\n                break;\n#endif /* MBEDTLS_SSL_ALPN */\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n            case MBEDTLS_TLS_EXT_SIG_ALG:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found signature_algorithms extension\"));\n\n                ret = mbedtls_ssl_parse_sig_alg_ext(\n                    ssl, p, extension_data_end);\n                if (ret != 0) {\n                    MBEDTLS_SSL_DEBUG_RET(\n                        1, \"mbedtls_ssl_parse_sig_alg_ext\", ret);\n                    return ret;\n                }\n                break;\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n            case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT:\n                MBEDTLS_SSL_DEBUG_MSG(3, (\"found record_size_limit extension\"));\n\n                ret = mbedtls_ssl_tls13_parse_record_size_limit_ext(\n                    ssl, p, extension_data_end);\n                if (ret != 0) {\n                    MBEDTLS_SSL_DEBUG_RET(\n                        1, (\"mbedtls_ssl_tls13_parse_record_size_limit_ext\"), ret);\n                    return ret;\n                }\n                break;\n#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */\n\n            default:\n                MBEDTLS_SSL_PRINT_EXT(\n                    3, MBEDTLS_SSL_HS_CLIENT_HELLO,\n                    extension_type, \"( ignored )\");\n                break;\n        }\n\n        p += extension_data_len;\n    }\n\n    MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CLIENT_HELLO,\n                           handshake->received_extensions);\n\n    ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl,\n                                             MBEDTLS_SSL_HS_CLIENT_HELLO,\n                                             p - buf);\n    if (0 != ret) {\n        MBEDTLS_SSL_DEBUG_RET(1, (\"mbedtls_ssl_add_hs_hdr_to_checksum\"), ret);\n        return ret;\n    }\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n    /* Update checksum with either\n     * - The entire content of the CH message, if no PSK extension is present\n     * - The content up to but excluding the PSK extension, if present.\n     * Always parse the pre-shared-key extension when present in the\n     * ClientHello even if some pre-requisites for PSK key exchange modes are\n     * not met. That way we always validate the syntax of the extension.\n     */\n    if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)) {\n        ret = handshake->update_checksum(ssl, buf,\n                                         pre_shared_key_ext - buf);\n        if (0 != ret) {\n            MBEDTLS_SSL_DEBUG_RET(1, (\"update_checksum\"), ret);\n            return ret;\n        }\n        ret = ssl_tls13_parse_pre_shared_key_ext(ssl,\n                                                 pre_shared_key_ext,\n                                                 pre_shared_key_ext_end,\n                                                 cipher_suites,\n                                                 cipher_suites_end,\n                                                 &psk);\n        if (ret == 0) {\n            got_psk = 1;\n        } else if (ret != MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) {\n            MBEDTLS_SSL_DEBUG_RET(\n                1, \"ssl_tls13_parse_pre_shared_key_ext\", ret);\n            return ret;\n        }\n    } else\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */\n    {\n        ret = handshake->update_checksum(ssl, buf, p - buf);\n        if (0 != ret) {\n            MBEDTLS_SSL_DEBUG_RET(1, (\"update_checksum\"), ret);\n            return ret;\n        }\n    }\n\n    /*\n     * Determine the key exchange algorithm to use.\n     * There are three types of key exchanges supported in TLS 1.3:\n     * - (EC)DH with ECDSA,\n     * - (EC)DH with PSK,\n     * - plain PSK.\n     *\n     * The PSK-based key exchanges may additionally be used with 0-RTT.\n     *\n     * Our built-in order of preference is\n     *  1 ) (EC)DHE-PSK Mode ( psk_ephemeral )\n     *  2 ) Certificate Mode ( ephemeral )\n     *  3 ) Plain PSK Mode ( psk )\n     */\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n    if (got_psk && (psk.key_exchange_mode ==\n                    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL)) {\n        handshake->key_exchange_mode =\n            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"key exchange mode: psk_ephemeral\"));\n\n    } else\n#endif\n    if (ssl_tls13_key_exchange_is_ephemeral_available(ssl)) {\n        handshake->key_exchange_mode =\n            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL;\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"key exchange mode: ephemeral\"));\n\n    }\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n    else if (got_psk && (psk.key_exchange_mode ==\n                         MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK)) {\n        handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"key exchange mode: psk\"));\n    }\n#endif\n    else {\n        MBEDTLS_SSL_DEBUG_MSG(\n            1,\n            (\"ClientHello message misses mandatory extensions.\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION,\n                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);\n        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;\n    }\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n    if (handshake->key_exchange_mode &\n        MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL) {\n        handshake->ciphersuite_info = psk.ciphersuite_info;\n        ssl->session_negotiate->ciphersuite = psk.ciphersuite_info->id;\n\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"Select PSK ciphersuite: %04x - %s\",\n                                  ((unsigned) psk.ciphersuite_info->id),\n                                  psk.ciphersuite_info->name));\n\n        if (psk.type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {\n            handshake->resume = 1;\n        }\n    }\n#endif\n\n    if (handshake->key_exchange_mode !=\n        MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) {\n        hrr_required = (no_usable_share_for_key_agreement != 0);\n    }\n\n    mbedtls_ssl_optimize_checksum(ssl, handshake->ciphersuite_info);\n\n    return hrr_required ? SSL_CLIENT_HELLO_HRR_REQUIRED : SSL_CLIENT_HELLO_OK;\n}\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\nstatic int ssl_tls13_check_early_data_requirements(mbedtls_ssl_context *ssl)\n{\n    mbedtls_ssl_handshake_params *handshake = ssl->handshake;\n\n    if (ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_DISABLED) {\n        MBEDTLS_SSL_DEBUG_MSG(\n            1,\n            (\"EarlyData: rejected, feature disabled in server configuration.\"));\n        return -1;\n    }\n\n    if (!handshake->resume) {\n        /* We currently support early data only in the case of PSKs established\n           via a NewSessionTicket message thus in the case of a session\n           resumption. */\n        MBEDTLS_SSL_DEBUG_MSG(\n            1, (\"EarlyData: rejected, not a session resumption.\"));\n        return -1;\n    }\n\n    /* RFC 8446 4.2.10\n     *\n     * In order to accept early data, the server MUST have accepted a PSK cipher\n     * suite and selected the first key offered in the client's \"pre_shared_key\"\n     * extension. In addition, it MUST verify that the following values are the\n     * same as those associated with the selected PSK:\n     * - The TLS version number\n     * - The selected cipher suite\n     * - The selected ALPN [RFC7301] protocol, if any\n     *\n     * NOTE:\n     *  - The TLS version number is checked in\n     *    ssl_tls13_offered_psks_check_identity_match_ticket().\n     */\n\n    if (handshake->selected_identity != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(\n            1, (\"EarlyData: rejected, the selected key in \"\n                \"`pre_shared_key` is not the first one.\"));\n        return -1;\n    }\n\n    if (handshake->ciphersuite_info->id !=\n        ssl->session_negotiate->ciphersuite) {\n        MBEDTLS_SSL_DEBUG_MSG(\n            1, (\"EarlyData: rejected, the selected ciphersuite is not the one \"\n                \"of the selected pre-shared key.\"));\n        return -1;\n\n    }\n\n    if (!mbedtls_ssl_tls13_session_ticket_allow_early_data(ssl->session_negotiate)) {\n        MBEDTLS_SSL_DEBUG_MSG(\n            1,\n            (\"EarlyData: rejected, early_data not allowed in ticket \"\n             \"permission bits.\"));\n        return -1;\n    }\n\n#if defined(MBEDTLS_SSL_ALPN)\n    const char *alpn = mbedtls_ssl_get_alpn_protocol(ssl);\n    size_t alpn_len;\n\n    if (alpn == NULL && ssl->session_negotiate->ticket_alpn == NULL) {\n        return 0;\n    }\n\n    if (alpn != NULL) {\n        alpn_len = strlen(alpn);\n    }\n\n    if (alpn == NULL ||\n        ssl->session_negotiate->ticket_alpn == NULL ||\n        alpn_len != strlen(ssl->session_negotiate->ticket_alpn) ||\n        (memcmp(alpn, ssl->session_negotiate->ticket_alpn, alpn_len) != 0)) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"EarlyData: rejected, the selected ALPN is different \"\n                                  \"from the one associated with the pre-shared key.\"));\n        return -1;\n    }\n#endif\n\n    return 0;\n}\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n/* Update the handshake state machine */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_postprocess_client_hello(mbedtls_ssl_context *ssl,\n                                              int hrr_required)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    /*\n     * Server certificate selection\n     */\n    if (ssl->conf->f_cert_cb && (ret = ssl->conf->f_cert_cb(ssl)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"f_cert_cb\", ret);\n        return ret;\n    }\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    ssl->handshake->sni_name = NULL;\n    ssl->handshake->sni_name_len = 0;\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n\n    ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1,\n                              \"mbedtls_ssl_tls1_3_key_schedule_stage_early\", ret);\n        return ret;\n    }\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    if (ssl->handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) {\n        ssl->handshake->early_data_accepted =\n            (!hrr_required) && (ssl_tls13_check_early_data_requirements(ssl) == 0);\n\n        if (ssl->handshake->early_data_accepted) {\n            ret = mbedtls_ssl_tls13_compute_early_transform(ssl);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(\n                    1, \"mbedtls_ssl_tls13_compute_early_transform\", ret);\n                return ret;\n            }\n        } else {\n            ssl->discard_early_data_record =\n                hrr_required ?\n                MBEDTLS_SSL_EARLY_DATA_DISCARD :\n                MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD;\n        }\n    }\n#else\n    ((void) hrr_required);\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n    return 0;\n}\n\n/*\n * Main entry point from the state machine; orchestrates the otherfunctions.\n */\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_process_client_hello(mbedtls_ssl_context *ssl)\n{\n\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *buf = NULL;\n    size_t buflen = 0;\n    int parse_client_hello_ret;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> parse client hello\"));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(\n                             ssl, MBEDTLS_SSL_HS_CLIENT_HELLO,\n                             &buf, &buflen));\n\n    MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_parse_client_hello(ssl, buf,\n                                                          buf + buflen));\n    parse_client_hello_ret = ret; /* Store positive return value of\n                                   * parse_client_hello,\n                                   * as negative error codes are handled\n                                   * by MBEDTLS_SSL_PROC_CHK_NEG. */\n\n    /*\n     * Version 1.2 of the protocol has to be used for the handshake.\n     * If TLS 1.2 is not supported, abort the handshake. Otherwise, set the\n     * ssl->keep_current_message flag for the ClientHello to be kept and parsed\n     * as a TLS 1.2 ClientHello. We also change ssl->tls_version to\n     * MBEDTLS_SSL_VERSION_TLS1_2 thus from now on mbedtls_ssl_handshake_step()\n     * will dispatch to the TLS 1.2 state machine.\n     */\n    if (SSL_CLIENT_HELLO_TLS1_2 == parse_client_hello_ret) {\n        /* Check if server supports TLS 1.2 */\n        if (!mbedtls_ssl_conf_is_tls12_enabled(ssl->conf)) {\n            MBEDTLS_SSL_DEBUG_MSG(\n                1, (\"TLS 1.2 not supported.\"));\n            MBEDTLS_SSL_PEND_FATAL_ALERT(\n                MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION,\n                MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION);\n            return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;\n        }\n        ssl->keep_current_message = 1;\n        ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2;\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"non-1.3 ClientHello left for later processing\"));\n        return 0;\n    }\n\n    MBEDTLS_SSL_PROC_CHK(\n        ssl_tls13_postprocess_client_hello(ssl, parse_client_hello_ret ==\n                                           SSL_CLIENT_HELLO_HRR_REQUIRED));\n\n    if (SSL_CLIENT_HELLO_OK == parse_client_hello_ret) {\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO);\n    } else {\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HELLO_RETRY_REQUEST);\n    }\n\ncleanup:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= parse client hello\"));\n    return ret;\n}\n\n/*\n * Handler for MBEDTLS_SSL_SERVER_HELLO\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_prepare_server_hello(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *server_randbytes =\n        ssl->handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN;\n\n    if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, server_randbytes,\n                                MBEDTLS_SERVER_HELLO_RANDOM_LEN)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"f_rng\", ret);\n        return ret;\n    }\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"server hello, random bytes\", server_randbytes,\n                          MBEDTLS_SERVER_HELLO_RANDOM_LEN);\n\n#if defined(MBEDTLS_HAVE_TIME)\n    ssl->session_negotiate->start = mbedtls_time(NULL);\n#endif /* MBEDTLS_HAVE_TIME */\n\n    return ret;\n}\n\n/*\n * ssl_tls13_write_server_hello_supported_versions_ext ():\n *\n * struct {\n *      ProtocolVersion selected_version;\n * } SupportedVersions;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_server_hello_supported_versions_ext(\n    mbedtls_ssl_context *ssl,\n    unsigned char *buf,\n    unsigned char *end,\n    size_t *out_len)\n{\n    *out_len = 0;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, write selected version\"));\n\n    /* Check if we have space to write the extension:\n     * - extension_type         (2 bytes)\n     * - extension_data_length  (2 bytes)\n     * - selected_version       (2 bytes)\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6);\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, buf, 0);\n\n    MBEDTLS_PUT_UINT16_BE(2, buf, 2);\n\n    mbedtls_ssl_write_version(buf + 4,\n                              ssl->conf->transport,\n                              ssl->tls_version);\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"supported version: [%04x]\",\n                              ssl->tls_version));\n\n    *out_len = 6;\n\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(\n        ssl, MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS);\n\n    return 0;\n}\n\n\n\n/* Generate and export a single key share. For hybrid KEMs, this can\n * be called multiple times with the different components of the hybrid. */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_generate_and_write_key_share(mbedtls_ssl_context *ssl,\n                                                  uint16_t named_group,\n                                                  unsigned char *buf,\n                                                  unsigned char *end,\n                                                  size_t *out_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    *out_len = 0;\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)\n    if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group) ||\n        mbedtls_ssl_tls13_named_group_is_ffdh(named_group)) {\n        ret = mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange(\n            ssl, named_group, buf, end, out_len);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(\n                1, \"mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange\",\n                ret);\n            return ret;\n        }\n    } else\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */\n    if (0 /* Other kinds of KEMs */) {\n    } else {\n        ((void) ssl);\n        ((void) named_group);\n        ((void) buf);\n        ((void) end);\n        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    return ret;\n}\n\n/*\n * ssl_tls13_write_key_share_ext\n *\n * Structure of key_share extension in ServerHello:\n *\n * struct {\n *     NamedGroup group;\n *     opaque key_exchange<1..2^16-1>;\n * } KeyShareEntry;\n * struct {\n *     KeyShareEntry server_share;\n * } KeyShareServerHello;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl,\n                                         unsigned char *buf,\n                                         unsigned char *end,\n                                         size_t *out_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = buf;\n    uint16_t group = ssl->handshake->offered_group_id;\n    unsigned char *server_share = buf + 4;\n    size_t key_exchange_length;\n\n    *out_len = 0;\n\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"server hello, adding key share extension\"));\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"server hello, write selected_group: %s (%04x)\",\n                              mbedtls_ssl_named_group_to_str(group),\n                              group));\n\n    /* Check if we have space for header and length fields:\n     * - extension_type         (2 bytes)\n     * - extension_data_length  (2 bytes)\n     * - group                  (2 bytes)\n     * - key_exchange_length    (2 bytes)\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 8);\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, p, 0);\n    MBEDTLS_PUT_UINT16_BE(group, server_share, 0);\n    p += 8;\n\n    /* When we introduce PQC-ECDHE hybrids, we'll want to call this\n     * function multiple times. */\n    ret = ssl_tls13_generate_and_write_key_share(\n        ssl, group, server_share + 4, end, &key_exchange_length);\n    if (ret != 0) {\n        return ret;\n    }\n    p += key_exchange_length;\n\n    MBEDTLS_PUT_UINT16_BE(key_exchange_length, server_share + 2, 0);\n\n    MBEDTLS_PUT_UINT16_BE(p - server_share, buf, 2);\n\n    *out_len = p - buf;\n\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE);\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_hrr_key_share_ext(mbedtls_ssl_context *ssl,\n                                             unsigned char *buf,\n                                             unsigned char *end,\n                                             size_t *out_len)\n{\n    uint16_t selected_group = ssl->handshake->hrr_selected_group;\n    /* key_share Extension\n     *\n     *  struct {\n     *    select (Handshake.msg_type) {\n     *      ...\n     *      case hello_retry_request:\n     *          NamedGroup selected_group;\n     *      ...\n     *    };\n     * } KeyShare;\n     */\n\n    *out_len = 0;\n\n    /*\n     * For a pure PSK key exchange, there is no group to agree upon. The purpose\n     * of the HRR is then to transmit a cookie to force the client to demonstrate\n     * reachability at their apparent network address (primarily useful for DTLS).\n     */\n    if (!mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) {\n        return 0;\n    }\n\n    /* We should only send the key_share extension if the client's initial\n     * key share was not acceptable. */\n    if (ssl->handshake->offered_group_id != 0) {\n        MBEDTLS_SSL_DEBUG_MSG(4, (\"Skip key_share extension in HRR\"));\n        return 0;\n    }\n\n    if (selected_group == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"no matching named group found\"));\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    /* Check if we have enough space:\n     * - extension_type         (2 bytes)\n     * - extension_data_length  (2 bytes)\n     * - selected_group         (2 bytes)\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6);\n\n    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0);\n    MBEDTLS_PUT_UINT16_BE(2, buf, 2);\n    MBEDTLS_PUT_UINT16_BE(selected_group, buf, 4);\n\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"HRR selected_group: %s (%x)\",\n                           mbedtls_ssl_named_group_to_str(selected_group),\n                           selected_group));\n\n    *out_len = 6;\n\n    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE);\n\n    return 0;\n}\n\n/*\n * Structure of ServerHello message:\n *\n *     struct {\n *        ProtocolVersion legacy_version = 0x0303;    // TLS v1.2\n *        Random random;\n *        opaque legacy_session_id_echo<0..32>;\n *        CipherSuite cipher_suite;\n *        uint8 legacy_compression_method = 0;\n *        Extension extensions<6..2^16-1>;\n *    } ServerHello;\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_server_hello_body(mbedtls_ssl_context *ssl,\n                                             unsigned char *buf,\n                                             unsigned char *end,\n                                             size_t *out_len,\n                                             int is_hrr)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = buf;\n    unsigned char *p_extensions_len;\n    size_t output_len;\n\n    *out_len = 0;\n    ssl->handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE;\n\n    /* ...\n     * ProtocolVersion legacy_version = 0x0303; // TLS 1.2\n     * ...\n     * with ProtocolVersion defined as:\n     * uint16 ProtocolVersion;\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);\n    MBEDTLS_PUT_UINT16_BE(0x0303, p, 0);\n    p += 2;\n\n    /* ...\n     * Random random;\n     * ...\n     * with Random defined as:\n     * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN];\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN);\n    if (is_hrr) {\n        memcpy(p, mbedtls_ssl_tls13_hello_retry_request_magic,\n               MBEDTLS_SERVER_HELLO_RANDOM_LEN);\n    } else {\n        memcpy(p, &ssl->handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN],\n               MBEDTLS_SERVER_HELLO_RANDOM_LEN);\n    }\n    MBEDTLS_SSL_DEBUG_BUF(3, \"server hello, random bytes\",\n                          p, MBEDTLS_SERVER_HELLO_RANDOM_LEN);\n    p += MBEDTLS_SERVER_HELLO_RANDOM_LEN;\n\n    /* ...\n     * opaque legacy_session_id_echo<0..32>;\n     * ...\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1 + ssl->session_negotiate->id_len);\n    *p++ = (unsigned char) ssl->session_negotiate->id_len;\n    if (ssl->session_negotiate->id_len > 0) {\n        memcpy(p, &ssl->session_negotiate->id[0],\n               ssl->session_negotiate->id_len);\n        p += ssl->session_negotiate->id_len;\n\n        MBEDTLS_SSL_DEBUG_BUF(3, \"session id\", ssl->session_negotiate->id,\n                              ssl->session_negotiate->id_len);\n    }\n\n    /* ...\n     * CipherSuite cipher_suite;\n     * ...\n     * with CipherSuite defined as:\n     * uint8 CipherSuite[2];\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);\n    MBEDTLS_PUT_UINT16_BE(ssl->session_negotiate->ciphersuite, p, 0);\n    p += 2;\n    MBEDTLS_SSL_DEBUG_MSG(3,\n                          (\"server hello, chosen ciphersuite: %s ( id=%d )\",\n                           mbedtls_ssl_get_ciphersuite_name(\n                               ssl->session_negotiate->ciphersuite),\n                           ssl->session_negotiate->ciphersuite));\n\n    /* ...\n     * uint8 legacy_compression_method = 0;\n     * ...\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1);\n    *p++ = MBEDTLS_SSL_COMPRESS_NULL;\n\n    /* ...\n     * Extension extensions<6..2^16-1>;\n     * ...\n     * struct {\n     *      ExtensionType extension_type; (2 bytes)\n     *      opaque extension_data<0..2^16-1>;\n     * } Extension;\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);\n    p_extensions_len = p;\n    p += 2;\n\n    if ((ret = ssl_tls13_write_server_hello_supported_versions_ext(\n             ssl, p, end, &output_len)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(\n            1, \"ssl_tls13_write_server_hello_supported_versions_ext\", ret);\n        return ret;\n    }\n    p += output_len;\n\n    if (mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) {\n        if (is_hrr) {\n            ret = ssl_tls13_write_hrr_key_share_ext(ssl, p, end, &output_len);\n        } else {\n            ret = ssl_tls13_write_key_share_ext(ssl, p, end, &output_len);\n        }\n        if (ret != 0) {\n            return ret;\n        }\n        p += output_len;\n    }\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n    if (!is_hrr && mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) {\n        ret = ssl_tls13_write_server_pre_shared_key_ext(ssl, p, end, &output_len);\n        if (ret != 0) {\n            MBEDTLS_SSL_DEBUG_RET(1, \"ssl_tls13_write_server_pre_shared_key_ext\",\n                                  ret);\n            return ret;\n        }\n        p += output_len;\n    }\n#endif\n\n    MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0);\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"server hello extensions\",\n                          p_extensions_len, p - p_extensions_len);\n\n    *out_len = p - buf;\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"server hello\", buf, *out_len);\n\n    MBEDTLS_SSL_PRINT_EXTS(\n        3, is_hrr ? MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST :\n        MBEDTLS_SSL_HS_SERVER_HELLO,\n        ssl->handshake->sent_extensions);\n\n    return ret;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_finalize_server_hello(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    ret = mbedtls_ssl_tls13_compute_handshake_transform(ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1,\n                              \"mbedtls_ssl_tls13_compute_handshake_transform\",\n                              ret);\n        return ret;\n    }\n\n    return ret;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_server_hello(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *buf;\n    size_t buf_len, msg_len;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write server hello\"));\n\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_server_hello(ssl));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(\n                             ssl, MBEDTLS_SSL_HS_SERVER_HELLO, &buf, &buf_len));\n\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_server_hello_body(ssl, buf,\n                                                           buf + buf_len,\n                                                           &msg_len,\n                                                           0));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(\n                             ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(\n                             ssl, buf_len, msg_len));\n\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_finalize_server_hello(ssl));\n\n#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)\n    /* The server sends a dummy change_cipher_spec record immediately\n     * after its first handshake message. This may either be after\n     * a ServerHello or a HelloRetryRequest.\n     */\n    mbedtls_ssl_handshake_set_state(\n        ssl, MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO);\n#else\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);\n#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */\n\ncleanup:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write server hello\"));\n    return ret;\n}\n\n\n/*\n * Handler for MBEDTLS_SSL_HELLO_RETRY_REQUEST\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_prepare_hello_retry_request(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    if (ssl->handshake->hello_retry_request_flag) {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"Too many HRRs\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,\n                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n\n    /*\n     * Create stateless transcript hash for HRR\n     */\n    MBEDTLS_SSL_DEBUG_MSG(4, (\"Reset transcript for HRR\"));\n    ret = mbedtls_ssl_reset_transcript_for_hrr(ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_reset_transcript_for_hrr\", ret);\n        return ret;\n    }\n    mbedtls_ssl_session_reset_msg_layer(ssl, 0);\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_hello_retry_request(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *buf;\n    size_t buf_len, msg_len;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write hello retry request\"));\n\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_hello_retry_request(ssl));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(\n                             ssl, MBEDTLS_SSL_HS_SERVER_HELLO,\n                             &buf, &buf_len));\n\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_server_hello_body(ssl, buf,\n                                                           buf + buf_len,\n                                                           &msg_len,\n                                                           1));\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(\n                             ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len));\n\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, buf_len,\n                                                          msg_len));\n\n    ssl->handshake->hello_retry_request_flag = 1;\n\n#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)\n    /* The server sends a dummy change_cipher_spec record immediately\n     * after its first handshake message. This may either be after\n     * a ServerHello or a HelloRetryRequest.\n     */\n    mbedtls_ssl_handshake_set_state(\n        ssl, MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST);\n#else\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);\n#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */\n\ncleanup:\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write hello retry request\"));\n    return ret;\n}\n\n/*\n * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS\n */\n\n/*\n * struct {\n *    Extension extensions<0..2 ^ 16 - 1>;\n * } EncryptedExtensions;\n *\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_encrypted_extensions_body(mbedtls_ssl_context *ssl,\n                                                     unsigned char *buf,\n                                                     unsigned char *end,\n                                                     size_t *out_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = buf;\n    size_t extensions_len = 0;\n    unsigned char *p_extensions_len;\n    size_t output_len;\n\n    *out_len = 0;\n\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);\n    p_extensions_len = p;\n    p += 2;\n\n    ((void) ssl);\n    ((void) ret);\n    ((void) output_len);\n\n#if defined(MBEDTLS_SSL_ALPN)\n    ret = mbedtls_ssl_write_alpn_ext(ssl, p, end, &output_len);\n    if (ret != 0) {\n        return ret;\n    }\n    p += output_len;\n#endif /* MBEDTLS_SSL_ALPN */\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    if (ssl->handshake->early_data_accepted) {\n        ret = mbedtls_ssl_tls13_write_early_data_ext(\n            ssl, 0, p, end, &output_len);\n        if (ret != 0) {\n            return ret;\n        }\n        p += output_len;\n    }\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n    if (ssl->handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)) {\n        ret = mbedtls_ssl_tls13_write_record_size_limit_ext(\n            ssl, p, end, &output_len);\n        if (ret != 0) {\n            return ret;\n        }\n        p += output_len;\n    }\n#endif\n\n    extensions_len = (p - p_extensions_len) - 2;\n    MBEDTLS_PUT_UINT16_BE(extensions_len, p_extensions_len, 0);\n\n    *out_len = p - buf;\n\n    MBEDTLS_SSL_DEBUG_BUF(4, \"encrypted extensions\", buf, *out_len);\n\n    MBEDTLS_SSL_PRINT_EXTS(\n        3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, ssl->handshake->sent_extensions);\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_encrypted_extensions(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *buf;\n    size_t buf_len, msg_len;\n\n    mbedtls_ssl_set_outbound_transform(ssl,\n                                       ssl->handshake->transform_handshake);\n    MBEDTLS_SSL_DEBUG_MSG(\n        3, (\"switching to handshake transform for outbound data\"));\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write encrypted extensions\"));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(\n                             ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,\n                             &buf, &buf_len));\n\n    MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_encrypted_extensions_body(\n                             ssl, buf, buf + buf_len, &msg_len));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(\n                             ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,\n                             buf, msg_len));\n\n    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(\n                             ssl, buf_len, msg_len));\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n    if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) {\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED);\n    } else {\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST);\n    }\n#else\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED);\n#endif\n\ncleanup:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write encrypted extensions\"));\n    return ret;\n}\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n#define SSL_CERTIFICATE_REQUEST_SEND_REQUEST 0\n#define SSL_CERTIFICATE_REQUEST_SKIP         1\n/* Coordination:\n * Check whether a CertificateRequest message should be written.\n * Returns a negative code on failure, or\n * - SSL_CERTIFICATE_REQUEST_SEND_REQUEST\n * - SSL_CERTIFICATE_REQUEST_SKIP\n * indicating if the writing of the CertificateRequest\n * should be skipped or not.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_certificate_request_coordinate(mbedtls_ssl_context *ssl)\n{\n    int authmode;\n\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) {\n        authmode = ssl->handshake->sni_authmode;\n    } else\n#endif\n    authmode = ssl->conf->authmode;\n\n    if (authmode == MBEDTLS_SSL_VERIFY_NONE) {\n        ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY;\n        return SSL_CERTIFICATE_REQUEST_SKIP;\n    }\n\n    ssl->handshake->certificate_request_sent = 1;\n\n    return SSL_CERTIFICATE_REQUEST_SEND_REQUEST;\n}\n\n/*\n * struct {\n *   opaque certificate_request_context<0..2^8-1>;\n *   Extension extensions<2..2^16-1>;\n * } CertificateRequest;\n *\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_certificate_request_body(mbedtls_ssl_context *ssl,\n                                                    unsigned char *buf,\n                                                    const unsigned char *end,\n                                                    size_t *out_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = buf;\n    size_t output_len = 0;\n    unsigned char *p_extensions_len;\n\n    *out_len = 0;\n\n    /* Check if we have enough space:\n     * - certificate_request_context (1 byte)\n     * - extensions length           (2 bytes)\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 3);\n\n    /*\n     * Write certificate_request_context\n     */\n    /*\n     * We use a zero length context for the normal handshake\n     * messages. For post-authentication handshake messages\n     * this request context would be set to a non-zero value.\n     */\n    *p++ = 0x0;\n\n    /*\n     * Write extensions\n     */\n    /* The extensions must contain the signature_algorithms. */\n    p_extensions_len = p;\n    p += 2;\n    ret = mbedtls_ssl_write_sig_alg_ext(ssl, p, end, &output_len);\n    if (ret != 0) {\n        return ret;\n    }\n\n    p += output_len;\n    MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0);\n\n    *out_len = p - buf;\n\n    MBEDTLS_SSL_PRINT_EXTS(\n        3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, ssl->handshake->sent_extensions);\n\n    return 0;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_certificate_request(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write certificate request\"));\n\n    MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_certificate_request_coordinate(ssl));\n\n    if (ret == SSL_CERTIFICATE_REQUEST_SEND_REQUEST) {\n        unsigned char *buf;\n        size_t buf_len, msg_len;\n\n        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(\n                                 ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,\n                                 &buf, &buf_len));\n\n        MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_request_body(\n                                 ssl, buf, buf + buf_len, &msg_len));\n\n        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(\n                                 ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,\n                                 buf, msg_len));\n\n        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(\n                                 ssl, buf_len, msg_len));\n    } else if (ret == SSL_CERTIFICATE_REQUEST_SKIP) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"<= skip write certificate request\"));\n        ret = 0;\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        goto cleanup;\n    }\n\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CERTIFICATE);\ncleanup:\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write certificate request\"));\n    return ret;\n}\n\n/*\n * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_server_certificate(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n    if ((ssl_tls13_pick_key_cert(ssl) != 0) ||\n        mbedtls_ssl_own_cert(ssl) == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"No certificate available.\"));\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,\n                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);\n        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;\n    }\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n\n    ret = mbedtls_ssl_tls13_write_certificate(ssl);\n    if (ret != 0) {\n        return ret;\n    }\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY);\n    return 0;\n}\n\n/*\n * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl)\n{\n    int ret = mbedtls_ssl_tls13_write_certificate_verify(ssl);\n    if (ret != 0) {\n        return ret;\n    }\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED);\n    return 0;\n}\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\n/*\n * RFC 8446 section A.2\n *\n *                                | Send ServerHello\n *                                | K_send = handshake\n *                                | Send EncryptedExtensions\n *                                | [Send CertificateRequest]\n * Can send                       | [Send Certificate + CertificateVerify]\n * app data                       | Send Finished\n * after   -->                    | K_send = application\n * here                  +--------+--------+\n *              No 0-RTT |                 | 0-RTT\n *                       |                 |\n *   K_recv = handshake  |                 | K_recv = early data\n * [Skip decrypt errors] |    +------> WAIT_EOED -+\n *                       |    |       Recv |      | Recv EndOfEarlyData\n *                       |    | early data |      | K_recv = handshake\n *                       |    +------------+      |\n *                       |                        |\n *                       +> WAIT_FLIGHT2 <--------+\n *                                |\n *                       +--------+--------+\n *               No auth |                 | Client auth\n *                       |                 |\n *                       |                 v\n *                       |             WAIT_CERT\n *                       |        Recv |       | Recv Certificate\n *                       |       empty |       v\n *                       | Certificate |    WAIT_CV\n *                       |             |       | Recv\n *                       |             v       | CertificateVerify\n *                       +-> WAIT_FINISHED <---+\n *                                | Recv Finished\n *\n *\n * The following function handles the state changes after WAIT_FLIGHT2 in the\n * above diagram. We are not going to receive early data related messages\n * anymore, prepare to receive the first handshake message of the client\n * second flight.\n */\nstatic void ssl_tls13_prepare_for_handshake_second_flight(\n    mbedtls_ssl_context *ssl)\n{\n    if (ssl->handshake->certificate_request_sent) {\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"skip parse certificate\"));\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"skip parse certificate verify\"));\n\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED);\n    }\n}\n\n/*\n * Handler for MBEDTLS_SSL_SERVER_FINISHED\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_server_finished(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    ret = mbedtls_ssl_tls13_write_finished_message(ssl);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_ssl_tls13_compute_application_transform(ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_PEND_FATAL_ALERT(\n            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,\n            MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);\n        return ret;\n    }\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    if (ssl->handshake->early_data_accepted) {\n        /* See RFC 8446 section A.2 for more information */\n        MBEDTLS_SSL_DEBUG_MSG(\n            1, (\"Switch to early keys for inbound traffic. \"\n                \"( K_recv = early data )\"));\n        mbedtls_ssl_set_inbound_transform(\n            ssl, ssl->handshake->transform_earlydata);\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA);\n        return 0;\n    }\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n    MBEDTLS_SSL_DEBUG_MSG(\n        1, (\"Switch to handshake keys for inbound traffic \"\n            \"( K_recv = handshake )\"));\n    mbedtls_ssl_set_inbound_transform(ssl, ssl->handshake->transform_handshake);\n\n    ssl_tls13_prepare_for_handshake_second_flight(ssl);\n\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n/*\n * Handler for MBEDTLS_SSL_END_OF_EARLY_DATA\n */\n#define SSL_GOT_END_OF_EARLY_DATA      0\n#define SSL_GOT_EARLY_DATA             1\n/* Coordination:\n * Deals with the ambiguity of not knowing if the next message is an\n * EndOfEarlyData message or an application message containing early data.\n * Returns a negative code on failure, or\n * - SSL_GOT_END_OF_EARLY_DATA\n * - SSL_GOT_EARLY_DATA\n * indicating which message is received.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_end_of_early_data_coordinate(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"mbedtls_ssl_read_record\", ret);\n        return ret;\n    }\n    ssl->keep_current_message = 1;\n\n    if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE        &&\n        ssl->in_msg[0]  == MBEDTLS_SSL_HS_END_OF_EARLY_DATA) {\n        MBEDTLS_SSL_DEBUG_MSG(3, (\"Received an end_of_early_data message.\"));\n        return SSL_GOT_END_OF_EARLY_DATA;\n    }\n\n    if (ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA) {\n        if (ssl->in_offt == NULL) {\n            MBEDTLS_SSL_DEBUG_MSG(3, (\"Received early data\"));\n            /* Set the reading pointer */\n            ssl->in_offt = ssl->in_msg;\n            ret = mbedtls_ssl_tls13_check_early_data_len(ssl, ssl->in_msglen);\n            if (ret != 0) {\n                return ret;\n            }\n        }\n        return SSL_GOT_EARLY_DATA;\n    }\n\n    MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,\n                                 MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE);\n    return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_parse_end_of_early_data(mbedtls_ssl_context *ssl,\n                                             const unsigned char *buf,\n                                             const unsigned char *end)\n{\n    /* RFC 8446 section 4.5\n     *\n     * struct {} EndOfEarlyData;\n     */\n    if (buf != end) {\n        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,\n                                     MBEDTLS_ERR_SSL_DECODE_ERROR);\n        return MBEDTLS_ERR_SSL_DECODE_ERROR;\n    }\n    return 0;\n}\n\n/*\n * RFC 8446 section A.2\n *\n *                                | Send ServerHello\n *                                | K_send = handshake\n *                                | Send EncryptedExtensions\n *                                | [Send CertificateRequest]\n * Can send                       | [Send Certificate + CertificateVerify]\n * app data                       | Send Finished\n * after   -->                    | K_send = application\n * here                  +--------+--------+\n *              No 0-RTT |                 | 0-RTT\n *                       |                 |\n *   K_recv = handshake  |                 | K_recv = early data\n * [Skip decrypt errors] |    +------> WAIT_EOED -+\n *                       |    |       Recv |      | Recv EndOfEarlyData\n *                       |    | early data |      | K_recv = handshake\n *                       |    +------------+      |\n *                       |                        |\n *                       +> WAIT_FLIGHT2 <--------+\n *                                |\n *                       +--------+--------+\n *               No auth |                 | Client auth\n *                       |                 |\n *                       |                 v\n *                       |             WAIT_CERT\n *                       |        Recv |       | Recv Certificate\n *                       |       empty |       v\n *                       | Certificate |    WAIT_CV\n *                       |             |       | Recv\n *                       |             v       | CertificateVerify\n *                       +-> WAIT_FINISHED <---+\n *                                | Recv Finished\n *\n * The function handles actions and state changes from 0-RTT to WAIT_FLIGHT2 in\n * the above diagram.\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_process_end_of_early_data(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> ssl_tls13_process_end_of_early_data\"));\n\n    MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_end_of_early_data_coordinate(ssl));\n\n    if (ret == SSL_GOT_END_OF_EARLY_DATA) {\n        unsigned char *buf;\n        size_t buf_len;\n\n        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(\n                                 ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA,\n                                 &buf, &buf_len));\n\n        MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_end_of_early_data(\n                                 ssl, buf, buf + buf_len));\n\n        MBEDTLS_SSL_DEBUG_MSG(\n            1, (\"Switch to handshake keys for inbound traffic\"\n                \"( K_recv = handshake )\"));\n        mbedtls_ssl_set_inbound_transform(\n            ssl, ssl->handshake->transform_handshake);\n\n        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(\n                                 ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA,\n                                 buf, buf_len));\n\n        ssl_tls13_prepare_for_handshake_second_flight(ssl);\n\n    } else if (ret == SSL_GOT_EARLY_DATA) {\n        ret = MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA;\n        goto cleanup;\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(1, (\"should never happen\"));\n        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n        goto cleanup;\n    }\n\ncleanup:\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= ssl_tls13_process_end_of_early_data\"));\n    return ret;\n}\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n/*\n * Handler for MBEDTLS_SSL_CLIENT_FINISHED\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_process_client_finished(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    ret = mbedtls_ssl_tls13_process_finished_message(ssl);\n    if (ret != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_ssl_tls13_compute_resumption_master_secret(ssl);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(\n            1, \"mbedtls_ssl_tls13_compute_resumption_master_secret\", ret);\n    }\n\n    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP);\n    return 0;\n}\n\n/*\n * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl)\n{\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"handshake: done\"));\n\n    mbedtls_ssl_tls13_handshake_wrapup(ssl);\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \\\n    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n/* TODO: Remove the check of SOME_PSK_ENABLED since SESSION_TICKETS requires\n *       SOME_PSK_ENABLED to be enabled. Here is just to make CI happy. It is\n *       expected to be resolved with issue#6395.\n */\n    /* Sent NewSessionTicket message only when client supports PSK */\n    if (mbedtls_ssl_tls13_is_some_psk_supported(ssl)) {\n        mbedtls_ssl_handshake_set_state(\n            ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);\n    } else\n#endif\n    {\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);\n    }\n    return 0;\n}\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n/*\n * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET\n */\n#define SSL_NEW_SESSION_TICKET_SKIP  0\n#define SSL_NEW_SESSION_TICKET_WRITE 1\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_new_session_ticket_coordinate(mbedtls_ssl_context *ssl)\n{\n    /* Check whether the use of session tickets is enabled */\n    if (ssl->conf->f_ticket_write == NULL) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"NewSessionTicket: disabled,\"\n                                  \" callback is not set\"));\n        return SSL_NEW_SESSION_TICKET_SKIP;\n    }\n    if (ssl->conf->new_session_tickets_count == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"NewSessionTicket: disabled,\"\n                                  \" configured count is zero\"));\n        return SSL_NEW_SESSION_TICKET_SKIP;\n    }\n\n    if (ssl->handshake->new_session_tickets_count == 0) {\n        MBEDTLS_SSL_DEBUG_MSG(2, (\"NewSessionTicket: all tickets have \"\n                                  \"been sent.\"));\n        return SSL_NEW_SESSION_TICKET_SKIP;\n    }\n\n    return SSL_NEW_SESSION_TICKET_WRITE;\n}\n\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl,\n                                                unsigned char *ticket_nonce,\n                                                size_t ticket_nonce_size)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_ssl_session *session = ssl->session;\n    mbedtls_ssl_ciphersuite_t *ciphersuite_info;\n    psa_algorithm_t psa_hash_alg;\n    int hash_length;\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> prepare NewSessionTicket msg\"));\n\n    /* Set ticket_flags depends on the advertised psk key exchange mode */\n    mbedtls_ssl_tls13_session_clear_ticket_flags(\n        session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)\n    mbedtls_ssl_tls13_session_set_ticket_flags(\n        session, ssl->handshake->tls13_kex_modes);\n#endif\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    if (ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED &&\n        ssl->conf->max_early_data_size > 0) {\n        mbedtls_ssl_tls13_session_set_ticket_flags(\n            session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA);\n        session->max_early_data_size = ssl->conf->max_early_data_size;\n    }\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n    MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags);\n\n#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)\n    if (session->ticket_alpn == NULL) {\n        ret = mbedtls_ssl_session_set_ticket_alpn(session, ssl->alpn_chosen);\n        if (ret != 0) {\n            return ret;\n        }\n    }\n#endif\n\n    /* Generate ticket_age_add */\n    if ((ret = ssl->conf->f_rng(ssl->conf->p_rng,\n                                (unsigned char *) &session->ticket_age_add,\n                                sizeof(session->ticket_age_add)) != 0)) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"generate_ticket_age_add\", ret);\n        return ret;\n    }\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"ticket_age_add: %u\",\n                              (unsigned int) session->ticket_age_add));\n\n    /* Generate ticket_nonce */\n    ret = ssl->conf->f_rng(ssl->conf->p_rng, ticket_nonce, ticket_nonce_size);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"generate_ticket_nonce\", ret);\n        return ret;\n    }\n    MBEDTLS_SSL_DEBUG_BUF(3, \"ticket_nonce:\",\n                          ticket_nonce, ticket_nonce_size);\n\n    ciphersuite_info =\n        (mbedtls_ssl_ciphersuite_t *) ssl->handshake->ciphersuite_info;\n    psa_hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac);\n    hash_length = PSA_HASH_LENGTH(psa_hash_alg);\n    if (hash_length == -1 ||\n        (size_t) hash_length > sizeof(session->resumption_key)) {\n        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;\n    }\n\n    /* In this code the psk key length equals the length of the hash */\n    session->resumption_key_len = hash_length;\n    session->ciphersuite = ciphersuite_info->id;\n\n    /* Compute resumption key\n     *\n     *  HKDF-Expand-Label( resumption_master_secret,\n     *                    \"resumption\", ticket_nonce, Hash.length )\n     */\n    ret = mbedtls_ssl_tls13_hkdf_expand_label(\n        psa_hash_alg,\n        session->app_secrets.resumption_master_secret,\n        hash_length,\n        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(resumption),\n        ticket_nonce,\n        ticket_nonce_size,\n        session->resumption_key,\n        hash_length);\n\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(2,\n                              \"Creating the ticket-resumed PSK failed\",\n                              ret);\n        return ret;\n    }\n    MBEDTLS_SSL_DEBUG_BUF(3, \"Ticket-resumed PSK\",\n                          session->resumption_key,\n                          session->resumption_key_len);\n\n    MBEDTLS_SSL_DEBUG_BUF(3, \"resumption_master_secret\",\n                          session->app_secrets.resumption_master_secret,\n                          hash_length);\n\n    return 0;\n}\n\n/* This function creates a NewSessionTicket message in the following format:\n *\n * struct {\n *    uint32 ticket_lifetime;\n *    uint32 ticket_age_add;\n *    opaque ticket_nonce<0..255>;\n *    opaque ticket<1..2^16-1>;\n *    Extension extensions<0..2^16-2>;\n * } NewSessionTicket;\n *\n * The ticket inside the NewSessionTicket message is an encrypted container\n * carrying the necessary information so that the server is later able to\n * re-start the communication.\n *\n * The following fields are placed inside the ticket by the\n * f_ticket_write() function:\n *\n *  - creation time (ticket_creation_time)\n *  - flags (ticket_flags)\n *  - age add (ticket_age_add)\n *  - key (resumption_key)\n *  - key length (resumption_key_len)\n *  - ciphersuite (ciphersuite)\n *  - max_early_data_size (max_early_data_size)\n */\nMBEDTLS_CHECK_RETURN_CRITICAL\nstatic int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl,\n                                                   unsigned char *buf,\n                                                   unsigned char *end,\n                                                   size_t *out_len,\n                                                   unsigned char *ticket_nonce,\n                                                   size_t ticket_nonce_size)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p = buf;\n    mbedtls_ssl_session *session = ssl->session;\n    size_t ticket_len;\n    uint32_t ticket_lifetime;\n    unsigned char *p_extensions_len;\n\n    *out_len = 0;\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"=> write NewSessionTicket msg\"));\n\n    /*\n     *    ticket_lifetime   4 bytes\n     *    ticket_age_add    4 bytes\n     *    ticket_nonce      1 + ticket_nonce_size bytes\n     *    ticket            >=2 bytes\n     */\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4 + 4 + 1 + ticket_nonce_size + 2);\n\n    /* Generate ticket and ticket_lifetime */\n#if defined(MBEDTLS_HAVE_TIME)\n    session->ticket_creation_time = mbedtls_ms_time();\n#endif\n    ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket,\n                                    session,\n                                    p + 9 + ticket_nonce_size + 2,\n                                    end,\n                                    &ticket_len,\n                                    &ticket_lifetime);\n    if (ret != 0) {\n        MBEDTLS_SSL_DEBUG_RET(1, \"write_ticket\", ret);\n        return ret;\n    }\n\n    /* RFC 8446 section 4.6.1\n     *\n     *  ticket_lifetime:  Indicates the lifetime in seconds as a 32-bit\n     *     unsigned integer in network byte order from the time of ticket\n     *     issuance.  Servers MUST NOT use any value greater than\n     *     604800 seconds (7 days) ...\n     */\n    if (ticket_lifetime > MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME) {\n        MBEDTLS_SSL_DEBUG_MSG(\n            1, (\"Ticket lifetime (%u) is greater than 7 days.\",\n                (unsigned int) ticket_lifetime));\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    MBEDTLS_PUT_UINT32_BE(ticket_lifetime, p, 0);\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"ticket_lifetime: %u\",\n                              (unsigned int) ticket_lifetime));\n\n    /* Write ticket_age_add */\n    MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 4);\n    MBEDTLS_SSL_DEBUG_MSG(3, (\"ticket_age_add: %u\",\n                              (unsigned int) session->ticket_age_add));\n\n    /* Write ticket_nonce */\n    p[8] = (unsigned char) ticket_nonce_size;\n    if (ticket_nonce_size > 0) {\n        memcpy(p + 9, ticket_nonce, ticket_nonce_size);\n    }\n    p += 9 + ticket_nonce_size;\n\n    /* Write ticket */\n    MBEDTLS_PUT_UINT16_BE(ticket_len, p, 0);\n    p += 2;\n    MBEDTLS_SSL_DEBUG_BUF(4, \"ticket\", p, ticket_len);\n    p += ticket_len;\n\n    /* Ticket Extensions\n     *\n     * Extension extensions<0..2^16-2>;\n     */\n    ssl->handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE;\n\n    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);\n    p_extensions_len = p;\n    p += 2;\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    if (mbedtls_ssl_tls13_session_ticket_allow_early_data(session)) {\n        size_t output_len;\n\n        if ((ret = mbedtls_ssl_tls13_write_early_data_ext(\n                 ssl, 1, p, end, &output_len)) != 0) {\n            MBEDTLS_SSL_DEBUG_RET(\n                1, \"mbedtls_ssl_tls13_write_early_data_ext\", ret);\n            return ret;\n        }\n        p += output_len;\n    } else {\n        MBEDTLS_SSL_DEBUG_MSG(\n            4, (\"early_data not allowed, \"\n                \"skip early_data extension in NewSessionTicket\"));\n    }\n\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n    MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0);\n\n    *out_len = p - buf;\n    MBEDTLS_SSL_DEBUG_BUF(4, \"ticket\", buf, *out_len);\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"<= write new session ticket\"));\n\n    MBEDTLS_SSL_PRINT_EXTS(\n        3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, ssl->handshake->sent_extensions);\n\n    return 0;\n}\n\n/*\n * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET\n */\nstatic int ssl_tls13_write_new_session_ticket(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_write_new_session_ticket_coordinate(ssl));\n\n    if (ret == SSL_NEW_SESSION_TICKET_WRITE) {\n        unsigned char ticket_nonce[MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH];\n        unsigned char *buf;\n        size_t buf_len, msg_len;\n\n        MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_new_session_ticket(\n                                 ssl, ticket_nonce, sizeof(ticket_nonce)));\n\n        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(\n                                 ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET,\n                                 &buf, &buf_len));\n\n        MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_new_session_ticket_body(\n                                 ssl, buf, buf + buf_len, &msg_len,\n                                 ticket_nonce, sizeof(ticket_nonce)));\n\n        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(\n                                 ssl, buf_len, msg_len));\n\n        /* Limit session tickets count to one when resumption connection.\n         *\n         * See document of mbedtls_ssl_conf_new_session_tickets.\n         */\n        if (ssl->handshake->resume == 1) {\n            ssl->handshake->new_session_tickets_count = 0;\n        } else {\n            ssl->handshake->new_session_tickets_count--;\n        }\n\n        mbedtls_ssl_handshake_set_state(\n            ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH);\n    } else {\n        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);\n    }\n\ncleanup:\n\n    return ret;\n}\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n/*\n * TLS 1.3 State Machine -- server side\n */\nint mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL) {\n        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n    }\n\n    MBEDTLS_SSL_DEBUG_MSG(2, (\"tls13 server state: %s(%d)\",\n                              mbedtls_ssl_states_str((mbedtls_ssl_states) ssl->state),\n                              ssl->state));\n\n    switch (ssl->state) {\n        /* start state */\n        case MBEDTLS_SSL_HELLO_REQUEST:\n            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);\n            ret = 0;\n            break;\n\n        case MBEDTLS_SSL_CLIENT_HELLO:\n            ret = ssl_tls13_process_client_hello(ssl);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"ssl_tls13_process_client_hello\", ret);\n            }\n            break;\n\n        case MBEDTLS_SSL_HELLO_RETRY_REQUEST:\n            ret = ssl_tls13_write_hello_retry_request(ssl);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"ssl_tls13_write_hello_retry_request\", ret);\n                return ret;\n            }\n            break;\n\n        case MBEDTLS_SSL_SERVER_HELLO:\n            ret = ssl_tls13_write_server_hello(ssl);\n            break;\n\n        case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS:\n            ret = ssl_tls13_write_encrypted_extensions(ssl);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1, \"ssl_tls13_write_encrypted_extensions\", ret);\n                return ret;\n            }\n            break;\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n        case MBEDTLS_SSL_CERTIFICATE_REQUEST:\n            ret = ssl_tls13_write_certificate_request(ssl);\n            break;\n\n        case MBEDTLS_SSL_SERVER_CERTIFICATE:\n            ret = ssl_tls13_write_server_certificate(ssl);\n            break;\n\n        case MBEDTLS_SSL_CERTIFICATE_VERIFY:\n            ret = ssl_tls13_write_certificate_verify(ssl);\n            break;\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\n            /*\n             * Injection of dummy-CCS's for middlebox compatibility\n             */\n#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)\n        case MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST:\n            ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);\n            if (ret == 0) {\n                mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);\n            }\n            break;\n\n        case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO:\n            ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);\n            if (ret != 0) {\n                break;\n            }\n            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);\n            break;\n#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */\n\n        case MBEDTLS_SSL_SERVER_FINISHED:\n            ret = ssl_tls13_write_server_finished(ssl);\n            break;\n\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n        case MBEDTLS_SSL_END_OF_EARLY_DATA:\n            ret = ssl_tls13_process_end_of_early_data(ssl);\n            break;\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n\n        case MBEDTLS_SSL_CLIENT_FINISHED:\n            ret = ssl_tls13_process_client_finished(ssl);\n            break;\n\n        case MBEDTLS_SSL_HANDSHAKE_WRAPUP:\n            ret = ssl_tls13_handshake_wrapup(ssl);\n            break;\n\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n        case MBEDTLS_SSL_CLIENT_CERTIFICATE:\n            ret = mbedtls_ssl_tls13_process_certificate(ssl);\n            if (ret == 0) {\n                if (ssl->session_negotiate->peer_cert != NULL) {\n                    mbedtls_ssl_handshake_set_state(\n                        ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY);\n                } else {\n                    MBEDTLS_SSL_DEBUG_MSG(2, (\"skip parse certificate verify\"));\n                    mbedtls_ssl_handshake_set_state(\n                        ssl, MBEDTLS_SSL_CLIENT_FINISHED);\n                }\n            }\n            break;\n\n        case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY:\n            ret = mbedtls_ssl_tls13_process_certificate_verify(ssl);\n            if (ret == 0) {\n                mbedtls_ssl_handshake_set_state(\n                    ssl, MBEDTLS_SSL_CLIENT_FINISHED);\n            }\n            break;\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n        case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET:\n            ret = ssl_tls13_write_new_session_ticket(ssl);\n            if (ret != 0) {\n                MBEDTLS_SSL_DEBUG_RET(1,\n                                      \"ssl_tls13_write_new_session_ticket \",\n                                      ret);\n            }\n            break;\n        case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH:\n            /* This state is necessary to do the flush of the New Session\n             * Ticket message written in MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET\n             * as part of ssl_prepare_handshake_step.\n             */\n            ret = 0;\n\n            if (ssl->handshake->new_session_tickets_count == 0) {\n                mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);\n            } else {\n                mbedtls_ssl_handshake_set_state(\n                    ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);\n            }\n            break;\n\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n\n        default:\n            MBEDTLS_SSL_DEBUG_MSG(1, (\"invalid state %d\", ssl->state));\n            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;\n    }\n\n    return ret;\n}\n\n#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_TLS1_3 */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/threading.c",
    "content": "/*\n *  Threading abstraction layer\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n/*\n * Ensure gmtime_r is available even with -std=c99; must be defined before\n * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms.\n */\n#if !defined(_POSIX_C_SOURCE)\n#define _POSIX_C_SOURCE 200112L\n#endif\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_THREADING_C)\n\n#include \"threading_internal.h\"\n\n#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)\n\n#if !defined(_WIN32) && (defined(unix) || \\\n    defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \\\n    defined(__MACH__)))\n#include <unistd.h>\n#endif /* !_WIN32 && (unix || __unix || __unix__ ||\n        * (__APPLE__ && __MACH__)) */\n\n#if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) ||     \\\n    (defined(_POSIX_THREAD_SAFE_FUNCTIONS) &&                     \\\n    _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L))\n/*\n * This is a convenience shorthand macro to avoid checking the long\n * preprocessor conditions above. Ideally, we could expose this macro in\n * platform_util.h and simply use it in platform_util.c, threading.c and\n * threading.h. However, this macro is not part of the Mbed TLS public API, so\n * we keep it private by only defining it in this file\n */\n\n#if !(defined(_WIN32) && !defined(EFIX64) && !defined(EFI32))\n#define THREADING_USE_GMTIME\n#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */\n\n#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \\\n             ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \\\n                _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */\n\n#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */\n\n#if defined(MBEDTLS_THREADING_PTHREAD)\nstatic void threading_mutex_init_pthread(mbedtls_threading_mutex_t *mutex)\n{\n    if (mutex == NULL) {\n        return;\n    }\n\n    /* One problem here is that calling lock on a pthread mutex without first\n     * having initialised it is undefined behaviour. Obviously we cannot check\n     * this here in a thread safe manner without a significant performance\n     * hit, so state transitions are checked in tests only via the state\n     * variable. Please make sure any new mutex that gets added is exercised in\n     * tests; see framework/tests/src/threading_helpers.c for more details. */\n    (void) pthread_mutex_init(&mutex->mutex, NULL);\n}\n\nstatic void threading_mutex_free_pthread(mbedtls_threading_mutex_t *mutex)\n{\n    if (mutex == NULL) {\n        return;\n    }\n\n    (void) pthread_mutex_destroy(&mutex->mutex);\n}\n\nstatic int threading_mutex_lock_pthread(mbedtls_threading_mutex_t *mutex)\n{\n    if (mutex == NULL) {\n        return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA;\n    }\n\n    if (pthread_mutex_lock(&mutex->mutex) != 0) {\n        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n\n    return 0;\n}\n\nstatic int threading_mutex_unlock_pthread(mbedtls_threading_mutex_t *mutex)\n{\n    if (mutex == NULL) {\n        return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA;\n    }\n\n    if (pthread_mutex_unlock(&mutex->mutex) != 0) {\n        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n\n    return 0;\n}\n\nvoid (*mbedtls_mutex_init)(mbedtls_threading_mutex_t *) = threading_mutex_init_pthread;\nvoid (*mbedtls_mutex_free)(mbedtls_threading_mutex_t *) = threading_mutex_free_pthread;\nint (*mbedtls_mutex_lock)(mbedtls_threading_mutex_t *) = threading_mutex_lock_pthread;\nint (*mbedtls_mutex_unlock)(mbedtls_threading_mutex_t *) = threading_mutex_unlock_pthread;\n\n/*\n * With pthreads we can statically initialize mutexes\n */\n#define MUTEX_INIT  = { PTHREAD_MUTEX_INITIALIZER, 1 }\n\n#endif /* MBEDTLS_THREADING_PTHREAD */\n\n#if defined(MBEDTLS_THREADING_ALT)\nstatic int threading_mutex_fail(mbedtls_threading_mutex_t *mutex)\n{\n    ((void) mutex);\n    return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA;\n}\nstatic void threading_mutex_dummy(mbedtls_threading_mutex_t *mutex)\n{\n    ((void) mutex);\n    return;\n}\n\nvoid (*mbedtls_mutex_init)(mbedtls_threading_mutex_t *) = threading_mutex_dummy;\nvoid (*mbedtls_mutex_free)(mbedtls_threading_mutex_t *) = threading_mutex_dummy;\nint (*mbedtls_mutex_lock)(mbedtls_threading_mutex_t *) = threading_mutex_fail;\nint (*mbedtls_mutex_unlock)(mbedtls_threading_mutex_t *) = threading_mutex_fail;\n\n/*\n * Set functions pointers and initialize global mutexes\n */\nvoid mbedtls_threading_set_alt(void (*mutex_init)(mbedtls_threading_mutex_t *),\n                               void (*mutex_free)(mbedtls_threading_mutex_t *),\n                               int (*mutex_lock)(mbedtls_threading_mutex_t *),\n                               int (*mutex_unlock)(mbedtls_threading_mutex_t *))\n{\n    mbedtls_mutex_init = mutex_init;\n    mbedtls_mutex_free = mutex_free;\n    mbedtls_mutex_lock = mutex_lock;\n    mbedtls_mutex_unlock = mutex_unlock;\n\n#if defined(MBEDTLS_FS_IO)\n    mbedtls_mutex_init(&mbedtls_threading_readdir_mutex);\n#endif\n#if defined(THREADING_USE_GMTIME)\n    mbedtls_mutex_init(&mbedtls_threading_gmtime_mutex);\n#endif\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n    mbedtls_mutex_init(&mbedtls_threading_key_slot_mutex);\n    mbedtls_mutex_init(&mbedtls_threading_psa_globaldata_mutex);\n    mbedtls_mutex_init(&mbedtls_threading_psa_rngdata_mutex);\n#endif\n}\n\n/*\n * Free global mutexes\n */\nvoid mbedtls_threading_free_alt(void)\n{\n#if defined(MBEDTLS_FS_IO)\n    mbedtls_mutex_free(&mbedtls_threading_readdir_mutex);\n#endif\n#if defined(THREADING_USE_GMTIME)\n    mbedtls_mutex_free(&mbedtls_threading_gmtime_mutex);\n#endif\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n    mbedtls_mutex_free(&mbedtls_threading_key_slot_mutex);\n    mbedtls_mutex_free(&mbedtls_threading_psa_globaldata_mutex);\n    mbedtls_mutex_free(&mbedtls_threading_psa_rngdata_mutex);\n#endif\n}\n#endif /* MBEDTLS_THREADING_ALT */\n\n/*\n * Define global mutexes\n */\n#ifndef MUTEX_INIT\n#define MUTEX_INIT\n#endif\n#if defined(MBEDTLS_FS_IO)\nmbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT;\n#endif\n#if defined(THREADING_USE_GMTIME)\nmbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT;\n#endif\n#if defined(MBEDTLS_PSA_CRYPTO_C)\nmbedtls_threading_mutex_t mbedtls_threading_key_slot_mutex MUTEX_INIT;\nmbedtls_threading_mutex_t mbedtls_threading_psa_globaldata_mutex MUTEX_INIT;\nmbedtls_threading_mutex_t mbedtls_threading_psa_rngdata_mutex MUTEX_INIT;\n#endif\n\n#endif /* MBEDTLS_THREADING_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/threading_internal.h",
    "content": "/**\n * \\file threading_internal.h\n *\n * \\brief Threading interfaces used by the test framework\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#ifndef MBEDTLS_THREADING_INTERNAL_H\n#define MBEDTLS_THREADING_INTERNAL_H\n\n#include \"common.h\"\n\n#include <mbedtls/threading.h>\n\n/* A version number for the internal threading interface.\n * This is meant to allow the framework to remain compatible with\n * multiple versions, to facilitate transitions.\n *\n * Conventionally, this is the Mbed TLS version number when the\n * threading interface was last changed in a way that may impact the\n * test framework, with the lower byte incremented as necessary\n * if multiple changes happened between releases. */\n#define MBEDTLS_THREADING_INTERNAL_VERSION 0x03060000\n\n#endif /* MBEDTLS_THREADING_INTERNAL_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/timing.c",
    "content": "/*\n *  Portable interface to the CPU cycle counter\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_TIMING_C)\n\n#include \"mbedtls/timing.h\"\n\n#if !defined(MBEDTLS_TIMING_ALT)\n\n#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \\\n    !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \\\n    !defined(__HAIKU__) && !defined(__midipix__)\n#error \"This module only works on Unix and Windows, see MBEDTLS_TIMING_C in mbedtls_config.h\"\n#endif\n\n#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)\n\n#include <windows.h>\n#include <process.h>\n\nstruct _hr_time {\n    LARGE_INTEGER start;\n};\n\n#else\n\n#include <unistd.h>\n#include <sys/types.h>\n#include <signal.h>\n/* time.h should be included independently of MBEDTLS_HAVE_TIME. If the\n * platform matches the ifdefs above, it will be used. */\n#include <time.h>\n#include <sys/time.h>\nstruct _hr_time {\n    struct timeval start;\n};\n#endif /* _WIN32 && !EFIX64 && !EFI32 */\n\n/**\n * \\brief          Return the elapsed time in milliseconds\n *\n * \\warning        May change without notice\n *\n * \\param val      points to a timer structure\n * \\param reset    If 0, query the elapsed time. Otherwise (re)start the timer.\n *\n * \\return         Elapsed time since the previous reset in ms. When\n *                 restarting, this is always 0.\n *\n * \\note           To initialize a timer, call this function with reset=1.\n *\n *                 Determining the elapsed time and resetting the timer is not\n *                 atomic on all platforms, so after the sequence\n *                 `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 =\n *                 get_timer(0) }` the value time1+time2 is only approximately\n *                 the delay since the first reset.\n */\n#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)\n\nunsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset)\n{\n    struct _hr_time *t = (struct _hr_time *) val;\n\n    if (reset) {\n        QueryPerformanceCounter(&t->start);\n        return 0;\n    } else {\n        unsigned long delta;\n        LARGE_INTEGER now, hfreq;\n        QueryPerformanceCounter(&now);\n        QueryPerformanceFrequency(&hfreq);\n        delta = (unsigned long) ((now.QuadPart - t->start.QuadPart) * 1000ul\n                                 / hfreq.QuadPart);\n        return delta;\n    }\n}\n\n#else /* _WIN32 && !EFIX64 && !EFI32 */\n\nunsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset)\n{\n    struct _hr_time *t = (struct _hr_time *) val;\n\n    if (reset) {\n        gettimeofday(&t->start, NULL);\n        return 0;\n    } else {\n        unsigned long delta;\n        struct timeval now;\n        gettimeofday(&now, NULL);\n        delta = (now.tv_sec  - t->start.tv_sec) * 1000ul\n                + (now.tv_usec - t->start.tv_usec) / 1000;\n        return delta;\n    }\n}\n\n#endif /* _WIN32 && !EFIX64 && !EFI32 */\n\n/*\n * Set delays to watch\n */\nvoid mbedtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms)\n{\n    mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data;\n\n    ctx->int_ms = int_ms;\n    ctx->fin_ms = fin_ms;\n\n    if (fin_ms != 0) {\n        (void) mbedtls_timing_get_timer(&ctx->timer, 1);\n    }\n}\n\n/*\n * Get number of delays expired\n */\nint mbedtls_timing_get_delay(void *data)\n{\n    mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data;\n    unsigned long elapsed_ms;\n\n    if (ctx->fin_ms == 0) {\n        return -1;\n    }\n\n    elapsed_ms = mbedtls_timing_get_timer(&ctx->timer, 0);\n\n    if (elapsed_ms >= ctx->fin_ms) {\n        return 2;\n    }\n\n    if (elapsed_ms >= ctx->int_ms) {\n        return 1;\n    }\n\n    return 0;\n}\n\n/*\n * Get the final delay.\n */\nuint32_t mbedtls_timing_get_final_delay(\n    const mbedtls_timing_delay_context *data)\n{\n    return data->fin_ms;\n}\n#endif /* !MBEDTLS_TIMING_ALT */\n#endif /* MBEDTLS_TIMING_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/version.c",
    "content": "/*\n *  Version information\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_VERSION_C)\n\n#include \"mbedtls/version.h\"\n#include <string.h>\n\nunsigned int mbedtls_version_get_number(void)\n{\n    return MBEDTLS_VERSION_NUMBER;\n}\n\nvoid mbedtls_version_get_string(char *string)\n{\n    memcpy(string, MBEDTLS_VERSION_STRING,\n           sizeof(MBEDTLS_VERSION_STRING));\n}\n\nvoid mbedtls_version_get_string_full(char *string)\n{\n    memcpy(string, MBEDTLS_VERSION_STRING_FULL,\n           sizeof(MBEDTLS_VERSION_STRING_FULL));\n}\n\n#endif /* MBEDTLS_VERSION_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/version_features.c",
    "content": "/*\n *  Version feature information\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_VERSION_C)\n\n#include \"mbedtls/version.h\"\n\n#include <string.h>\n\nstatic const char * const features[] = {\n#if defined(MBEDTLS_VERSION_FEATURES)\n    #if defined(MBEDTLS_HAVE_ASM)\n    \"HAVE_ASM\", //no-check-names\n#endif /* MBEDTLS_HAVE_ASM */\n#if defined(MBEDTLS_NO_UDBL_DIVISION)\n    \"NO_UDBL_DIVISION\", //no-check-names\n#endif /* MBEDTLS_NO_UDBL_DIVISION */\n#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION)\n    \"NO_64BIT_MULTIPLICATION\", //no-check-names\n#endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */\n#if defined(MBEDTLS_HAVE_SSE2)\n    \"HAVE_SSE2\", //no-check-names\n#endif /* MBEDTLS_HAVE_SSE2 */\n#if defined(MBEDTLS_HAVE_TIME)\n    \"HAVE_TIME\", //no-check-names\n#endif /* MBEDTLS_HAVE_TIME */\n#if defined(MBEDTLS_HAVE_TIME_DATE)\n    \"HAVE_TIME_DATE\", //no-check-names\n#endif /* MBEDTLS_HAVE_TIME_DATE */\n#if defined(MBEDTLS_PLATFORM_MEMORY)\n    \"PLATFORM_MEMORY\", //no-check-names\n#endif /* MBEDTLS_PLATFORM_MEMORY */\n#if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS)\n    \"PLATFORM_NO_STD_FUNCTIONS\", //no-check-names\n#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */\n#if defined(MBEDTLS_PLATFORM_SETBUF_ALT)\n    \"PLATFORM_SETBUF_ALT\", //no-check-names\n#endif /* MBEDTLS_PLATFORM_SETBUF_ALT */\n#if defined(MBEDTLS_PLATFORM_EXIT_ALT)\n    \"PLATFORM_EXIT_ALT\", //no-check-names\n#endif /* MBEDTLS_PLATFORM_EXIT_ALT */\n#if defined(MBEDTLS_PLATFORM_TIME_ALT)\n    \"PLATFORM_TIME_ALT\", //no-check-names\n#endif /* MBEDTLS_PLATFORM_TIME_ALT */\n#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT)\n    \"PLATFORM_FPRINTF_ALT\", //no-check-names\n#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */\n#if defined(MBEDTLS_PLATFORM_PRINTF_ALT)\n    \"PLATFORM_PRINTF_ALT\", //no-check-names\n#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */\n#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)\n    \"PLATFORM_SNPRINTF_ALT\", //no-check-names\n#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */\n#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT)\n    \"PLATFORM_VSNPRINTF_ALT\", //no-check-names\n#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */\n#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT)\n    \"PLATFORM_NV_SEED_ALT\", //no-check-names\n#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */\n#if defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT)\n    \"PLATFORM_SETUP_TEARDOWN_ALT\", //no-check-names\n#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */\n#if defined(MBEDTLS_PLATFORM_MS_TIME_ALT)\n    \"PLATFORM_MS_TIME_ALT\", //no-check-names\n#endif /* MBEDTLS_PLATFORM_MS_TIME_ALT */\n#if defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)\n    \"PLATFORM_GMTIME_R_ALT\", //no-check-names\n#endif /* MBEDTLS_PLATFORM_GMTIME_R_ALT */\n#if defined(MBEDTLS_PLATFORM_ZEROIZE_ALT)\n    \"PLATFORM_ZEROIZE_ALT\", //no-check-names\n#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */\n#if defined(MBEDTLS_DEPRECATED_WARNING)\n    \"DEPRECATED_WARNING\", //no-check-names\n#endif /* MBEDTLS_DEPRECATED_WARNING */\n#if defined(MBEDTLS_DEPRECATED_REMOVED)\n    \"DEPRECATED_REMOVED\", //no-check-names\n#endif /* MBEDTLS_DEPRECATED_REMOVED */\n#if defined(MBEDTLS_TIMING_ALT)\n    \"TIMING_ALT\", //no-check-names\n#endif /* MBEDTLS_TIMING_ALT */\n#if defined(MBEDTLS_AES_ALT)\n    \"AES_ALT\", //no-check-names\n#endif /* MBEDTLS_AES_ALT */\n#if defined(MBEDTLS_ARIA_ALT)\n    \"ARIA_ALT\", //no-check-names\n#endif /* MBEDTLS_ARIA_ALT */\n#if defined(MBEDTLS_CAMELLIA_ALT)\n    \"CAMELLIA_ALT\", //no-check-names\n#endif /* MBEDTLS_CAMELLIA_ALT */\n#if defined(MBEDTLS_CCM_ALT)\n    \"CCM_ALT\", //no-check-names\n#endif /* MBEDTLS_CCM_ALT */\n#if defined(MBEDTLS_CHACHA20_ALT)\n    \"CHACHA20_ALT\", //no-check-names\n#endif /* MBEDTLS_CHACHA20_ALT */\n#if defined(MBEDTLS_CHACHAPOLY_ALT)\n    \"CHACHAPOLY_ALT\", //no-check-names\n#endif /* MBEDTLS_CHACHAPOLY_ALT */\n#if defined(MBEDTLS_CMAC_ALT)\n    \"CMAC_ALT\", //no-check-names\n#endif /* MBEDTLS_CMAC_ALT */\n#if defined(MBEDTLS_DES_ALT)\n    \"DES_ALT\", //no-check-names\n#endif /* MBEDTLS_DES_ALT */\n#if defined(MBEDTLS_DHM_ALT)\n    \"DHM_ALT\", //no-check-names\n#endif /* MBEDTLS_DHM_ALT */\n#if defined(MBEDTLS_ECJPAKE_ALT)\n    \"ECJPAKE_ALT\", //no-check-names\n#endif /* MBEDTLS_ECJPAKE_ALT */\n#if defined(MBEDTLS_GCM_ALT)\n    \"GCM_ALT\", //no-check-names\n#endif /* MBEDTLS_GCM_ALT */\n#if defined(MBEDTLS_NIST_KW_ALT)\n    \"NIST_KW_ALT\", //no-check-names\n#endif /* MBEDTLS_NIST_KW_ALT */\n#if defined(MBEDTLS_MD5_ALT)\n    \"MD5_ALT\", //no-check-names\n#endif /* MBEDTLS_MD5_ALT */\n#if defined(MBEDTLS_POLY1305_ALT)\n    \"POLY1305_ALT\", //no-check-names\n#endif /* MBEDTLS_POLY1305_ALT */\n#if defined(MBEDTLS_RIPEMD160_ALT)\n    \"RIPEMD160_ALT\", //no-check-names\n#endif /* MBEDTLS_RIPEMD160_ALT */\n#if defined(MBEDTLS_RSA_ALT)\n    \"RSA_ALT\", //no-check-names\n#endif /* MBEDTLS_RSA_ALT */\n#if defined(MBEDTLS_SHA1_ALT)\n    \"SHA1_ALT\", //no-check-names\n#endif /* MBEDTLS_SHA1_ALT */\n#if defined(MBEDTLS_SHA256_ALT)\n    \"SHA256_ALT\", //no-check-names\n#endif /* MBEDTLS_SHA256_ALT */\n#if defined(MBEDTLS_SHA512_ALT)\n    \"SHA512_ALT\", //no-check-names\n#endif /* MBEDTLS_SHA512_ALT */\n#if defined(MBEDTLS_ECP_ALT)\n    \"ECP_ALT\", //no-check-names\n#endif /* MBEDTLS_ECP_ALT */\n#if defined(MBEDTLS_MD5_PROCESS_ALT)\n    \"MD5_PROCESS_ALT\", //no-check-names\n#endif /* MBEDTLS_MD5_PROCESS_ALT */\n#if defined(MBEDTLS_RIPEMD160_PROCESS_ALT)\n    \"RIPEMD160_PROCESS_ALT\", //no-check-names\n#endif /* MBEDTLS_RIPEMD160_PROCESS_ALT */\n#if defined(MBEDTLS_SHA1_PROCESS_ALT)\n    \"SHA1_PROCESS_ALT\", //no-check-names\n#endif /* MBEDTLS_SHA1_PROCESS_ALT */\n#if defined(MBEDTLS_SHA256_PROCESS_ALT)\n    \"SHA256_PROCESS_ALT\", //no-check-names\n#endif /* MBEDTLS_SHA256_PROCESS_ALT */\n#if defined(MBEDTLS_SHA512_PROCESS_ALT)\n    \"SHA512_PROCESS_ALT\", //no-check-names\n#endif /* MBEDTLS_SHA512_PROCESS_ALT */\n#if defined(MBEDTLS_DES_SETKEY_ALT)\n    \"DES_SETKEY_ALT\", //no-check-names\n#endif /* MBEDTLS_DES_SETKEY_ALT */\n#if defined(MBEDTLS_DES_CRYPT_ECB_ALT)\n    \"DES_CRYPT_ECB_ALT\", //no-check-names\n#endif /* MBEDTLS_DES_CRYPT_ECB_ALT */\n#if defined(MBEDTLS_DES3_CRYPT_ECB_ALT)\n    \"DES3_CRYPT_ECB_ALT\", //no-check-names\n#endif /* MBEDTLS_DES3_CRYPT_ECB_ALT */\n#if defined(MBEDTLS_AES_SETKEY_ENC_ALT)\n    \"AES_SETKEY_ENC_ALT\", //no-check-names\n#endif /* MBEDTLS_AES_SETKEY_ENC_ALT */\n#if defined(MBEDTLS_AES_SETKEY_DEC_ALT)\n    \"AES_SETKEY_DEC_ALT\", //no-check-names\n#endif /* MBEDTLS_AES_SETKEY_DEC_ALT */\n#if defined(MBEDTLS_AES_ENCRYPT_ALT)\n    \"AES_ENCRYPT_ALT\", //no-check-names\n#endif /* MBEDTLS_AES_ENCRYPT_ALT */\n#if defined(MBEDTLS_AES_DECRYPT_ALT)\n    \"AES_DECRYPT_ALT\", //no-check-names\n#endif /* MBEDTLS_AES_DECRYPT_ALT */\n#if defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)\n    \"ECDH_GEN_PUBLIC_ALT\", //no-check-names\n#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */\n#if defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)\n    \"ECDH_COMPUTE_SHARED_ALT\", //no-check-names\n#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */\n#if defined(MBEDTLS_ECDSA_VERIFY_ALT)\n    \"ECDSA_VERIFY_ALT\", //no-check-names\n#endif /* MBEDTLS_ECDSA_VERIFY_ALT */\n#if defined(MBEDTLS_ECDSA_SIGN_ALT)\n    \"ECDSA_SIGN_ALT\", //no-check-names\n#endif /* MBEDTLS_ECDSA_SIGN_ALT */\n#if defined(MBEDTLS_ECDSA_GENKEY_ALT)\n    \"ECDSA_GENKEY_ALT\", //no-check-names\n#endif /* MBEDTLS_ECDSA_GENKEY_ALT */\n#if defined(MBEDTLS_ECP_INTERNAL_ALT)\n    \"ECP_INTERNAL_ALT\", //no-check-names\n#endif /* MBEDTLS_ECP_INTERNAL_ALT */\n#if defined(MBEDTLS_ECP_NO_FALLBACK)\n    \"ECP_NO_FALLBACK\", //no-check-names\n#endif /* MBEDTLS_ECP_NO_FALLBACK */\n#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)\n    \"ECP_RANDOMIZE_JAC_ALT\", //no-check-names\n#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */\n#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)\n    \"ECP_ADD_MIXED_ALT\", //no-check-names\n#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */\n#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)\n    \"ECP_DOUBLE_JAC_ALT\", //no-check-names\n#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */\n#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)\n    \"ECP_NORMALIZE_JAC_MANY_ALT\", //no-check-names\n#endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */\n#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)\n    \"ECP_NORMALIZE_JAC_ALT\", //no-check-names\n#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */\n#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)\n    \"ECP_DOUBLE_ADD_MXZ_ALT\", //no-check-names\n#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */\n#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)\n    \"ECP_RANDOMIZE_MXZ_ALT\", //no-check-names\n#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */\n#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)\n    \"ECP_NORMALIZE_MXZ_ALT\", //no-check-names\n#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */\n#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)\n    \"ENTROPY_HARDWARE_ALT\", //no-check-names\n#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */\n#if defined(MBEDTLS_AES_ROM_TABLES)\n    \"AES_ROM_TABLES\", //no-check-names\n#endif /* MBEDTLS_AES_ROM_TABLES */\n#if defined(MBEDTLS_AES_FEWER_TABLES)\n    \"AES_FEWER_TABLES\", //no-check-names\n#endif /* MBEDTLS_AES_FEWER_TABLES */\n#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)\n    \"AES_ONLY_128_BIT_KEY_LENGTH\", //no-check-names\n#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */\n#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY)\n    \"AES_USE_HARDWARE_ONLY\", //no-check-names\n#endif /* MBEDTLS_AES_USE_HARDWARE_ONLY */\n#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY)\n    \"CAMELLIA_SMALL_MEMORY\", //no-check-names\n#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */\n#if defined(MBEDTLS_CHECK_RETURN_WARNING)\n    \"CHECK_RETURN_WARNING\", //no-check-names\n#endif /* MBEDTLS_CHECK_RETURN_WARNING */\n#if defined(MBEDTLS_CIPHER_MODE_CBC)\n    \"CIPHER_MODE_CBC\", //no-check-names\n#endif /* MBEDTLS_CIPHER_MODE_CBC */\n#if defined(MBEDTLS_CIPHER_MODE_CFB)\n    \"CIPHER_MODE_CFB\", //no-check-names\n#endif /* MBEDTLS_CIPHER_MODE_CFB */\n#if defined(MBEDTLS_CIPHER_MODE_CTR)\n    \"CIPHER_MODE_CTR\", //no-check-names\n#endif /* MBEDTLS_CIPHER_MODE_CTR */\n#if defined(MBEDTLS_CIPHER_MODE_OFB)\n    \"CIPHER_MODE_OFB\", //no-check-names\n#endif /* MBEDTLS_CIPHER_MODE_OFB */\n#if defined(MBEDTLS_CIPHER_MODE_XTS)\n    \"CIPHER_MODE_XTS\", //no-check-names\n#endif /* MBEDTLS_CIPHER_MODE_XTS */\n#if defined(MBEDTLS_CIPHER_NULL_CIPHER)\n    \"CIPHER_NULL_CIPHER\", //no-check-names\n#endif /* MBEDTLS_CIPHER_NULL_CIPHER */\n#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)\n    \"CIPHER_PADDING_PKCS7\", //no-check-names\n#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */\n#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)\n    \"CIPHER_PADDING_ONE_AND_ZEROS\", //no-check-names\n#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */\n#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)\n    \"CIPHER_PADDING_ZEROS_AND_LEN\", //no-check-names\n#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */\n#if defined(MBEDTLS_CIPHER_PADDING_ZEROS)\n    \"CIPHER_PADDING_ZEROS\", //no-check-names\n#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */\n#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)\n    \"CTR_DRBG_USE_128_BIT_KEY\", //no-check-names\n#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */\n#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)\n    \"ECDH_VARIANT_EVEREST_ENABLED\", //no-check-names\n#endif /* MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED */\n#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)\n    \"ECP_DP_SECP192R1_ENABLED\", //no-check-names\n#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */\n#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)\n    \"ECP_DP_SECP224R1_ENABLED\", //no-check-names\n#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */\n#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)\n    \"ECP_DP_SECP256R1_ENABLED\", //no-check-names\n#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */\n#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)\n    \"ECP_DP_SECP384R1_ENABLED\", //no-check-names\n#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */\n#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)\n    \"ECP_DP_SECP521R1_ENABLED\", //no-check-names\n#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */\n#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)\n    \"ECP_DP_SECP192K1_ENABLED\", //no-check-names\n#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */\n#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)\n    \"ECP_DP_SECP224K1_ENABLED\", //no-check-names\n#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */\n#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)\n    \"ECP_DP_SECP256K1_ENABLED\", //no-check-names\n#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */\n#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)\n    \"ECP_DP_BP256R1_ENABLED\", //no-check-names\n#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */\n#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)\n    \"ECP_DP_BP384R1_ENABLED\", //no-check-names\n#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */\n#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)\n    \"ECP_DP_BP512R1_ENABLED\", //no-check-names\n#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */\n#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)\n    \"ECP_DP_CURVE25519_ENABLED\", //no-check-names\n#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */\n#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)\n    \"ECP_DP_CURVE448_ENABLED\", //no-check-names\n#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */\n#if defined(MBEDTLS_ECP_NIST_OPTIM)\n    \"ECP_NIST_OPTIM\", //no-check-names\n#endif /* MBEDTLS_ECP_NIST_OPTIM */\n#if defined(MBEDTLS_ECP_RESTARTABLE)\n    \"ECP_RESTARTABLE\", //no-check-names\n#endif /* MBEDTLS_ECP_RESTARTABLE */\n#if defined(MBEDTLS_ECP_WITH_MPI_UINT)\n    \"ECP_WITH_MPI_UINT\", //no-check-names\n#endif /* MBEDTLS_ECP_WITH_MPI_UINT */\n#if defined(MBEDTLS_ECDSA_DETERMINISTIC)\n    \"ECDSA_DETERMINISTIC\", //no-check-names\n#endif /* MBEDTLS_ECDSA_DETERMINISTIC */\n#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)\n    \"KEY_EXCHANGE_PSK_ENABLED\", //no-check-names\n#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)\n    \"KEY_EXCHANGE_DHE_PSK_ENABLED\", //no-check-names\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)\n    \"KEY_EXCHANGE_ECDHE_PSK_ENABLED\", //no-check-names\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)\n    \"KEY_EXCHANGE_RSA_PSK_ENABLED\", //no-check-names\n#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)\n    \"KEY_EXCHANGE_RSA_ENABLED\", //no-check-names\n#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)\n    \"KEY_EXCHANGE_DHE_RSA_ENABLED\", //no-check-names\n#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)\n    \"KEY_EXCHANGE_ECDHE_RSA_ENABLED\", //no-check-names\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)\n    \"KEY_EXCHANGE_ECDHE_ECDSA_ENABLED\", //no-check-names\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)\n    \"KEY_EXCHANGE_ECDH_ECDSA_ENABLED\", //no-check-names\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)\n    \"KEY_EXCHANGE_ECDH_RSA_ENABLED\", //no-check-names\n#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */\n#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)\n    \"KEY_EXCHANGE_ECJPAKE_ENABLED\", //no-check-names\n#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */\n#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)\n    \"PK_PARSE_EC_EXTENDED\", //no-check-names\n#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */\n#if defined(MBEDTLS_PK_PARSE_EC_COMPRESSED)\n    \"PK_PARSE_EC_COMPRESSED\", //no-check-names\n#endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */\n#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)\n    \"ERROR_STRERROR_DUMMY\", //no-check-names\n#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */\n#if defined(MBEDTLS_GENPRIME)\n    \"GENPRIME\", //no-check-names\n#endif /* MBEDTLS_GENPRIME */\n#if defined(MBEDTLS_FS_IO)\n    \"FS_IO\", //no-check-names\n#endif /* MBEDTLS_FS_IO */\n#if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)\n    \"NO_DEFAULT_ENTROPY_SOURCES\", //no-check-names\n#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */\n#if defined(MBEDTLS_NO_PLATFORM_ENTROPY)\n    \"NO_PLATFORM_ENTROPY\", //no-check-names\n#endif /* MBEDTLS_NO_PLATFORM_ENTROPY */\n#if defined(MBEDTLS_ENTROPY_FORCE_SHA256)\n    \"ENTROPY_FORCE_SHA256\", //no-check-names\n#endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */\n#if defined(MBEDTLS_ENTROPY_NV_SEED)\n    \"ENTROPY_NV_SEED\", //no-check-names\n#endif /* MBEDTLS_ENTROPY_NV_SEED */\n#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)\n    \"PSA_CRYPTO_KEY_ID_ENCODES_OWNER\", //no-check-names\n#endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */\n#if defined(MBEDTLS_MEMORY_DEBUG)\n    \"MEMORY_DEBUG\", //no-check-names\n#endif /* MBEDTLS_MEMORY_DEBUG */\n#if defined(MBEDTLS_MEMORY_BACKTRACE)\n    \"MEMORY_BACKTRACE\", //no-check-names\n#endif /* MBEDTLS_MEMORY_BACKTRACE */\n#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)\n    \"PK_RSA_ALT_SUPPORT\", //no-check-names\n#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */\n#if defined(MBEDTLS_PKCS1_V15)\n    \"PKCS1_V15\", //no-check-names\n#endif /* MBEDTLS_PKCS1_V15 */\n#if defined(MBEDTLS_PKCS1_V21)\n    \"PKCS1_V21\", //no-check-names\n#endif /* MBEDTLS_PKCS1_V21 */\n#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)\n    \"PSA_CRYPTO_BUILTIN_KEYS\", //no-check-names\n#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */\n#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)\n    \"PSA_CRYPTO_CLIENT\", //no-check-names\n#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */\n#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)\n    \"PSA_CRYPTO_EXTERNAL_RNG\", //no-check-names\n#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */\n#if defined(MBEDTLS_PSA_CRYPTO_SPM)\n    \"PSA_CRYPTO_SPM\", //no-check-names\n#endif /* MBEDTLS_PSA_CRYPTO_SPM */\n#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)\n    \"PSA_KEY_STORE_DYNAMIC\", //no-check-names\n#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */\n#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)\n    \"PSA_P256M_DRIVER_ENABLED\", //no-check-names\n#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */\n#if defined(MBEDTLS_PSA_INJECT_ENTROPY)\n    \"PSA_INJECT_ENTROPY\", //no-check-names\n#endif /* MBEDTLS_PSA_INJECT_ENTROPY */\n#if defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\n    \"PSA_ASSUME_EXCLUSIVE_BUFFERS\", //no-check-names\n#endif /* MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */\n#if defined(MBEDTLS_RSA_NO_CRT)\n    \"RSA_NO_CRT\", //no-check-names\n#endif /* MBEDTLS_RSA_NO_CRT */\n#if defined(MBEDTLS_SELF_TEST)\n    \"SELF_TEST\", //no-check-names\n#endif /* MBEDTLS_SELF_TEST */\n#if defined(MBEDTLS_SHA256_SMALLER)\n    \"SHA256_SMALLER\", //no-check-names\n#endif /* MBEDTLS_SHA256_SMALLER */\n#if defined(MBEDTLS_SHA512_SMALLER)\n    \"SHA512_SMALLER\", //no-check-names\n#endif /* MBEDTLS_SHA512_SMALLER */\n#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)\n    \"SSL_ALL_ALERT_MESSAGES\", //no-check-names\n#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)\n    \"SSL_DTLS_CONNECTION_ID\", //no-check-names\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */\n#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT)\n    \"SSL_DTLS_CONNECTION_ID_COMPAT\", //no-check-names\n#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT */\n#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)\n    \"SSL_ASYNC_PRIVATE\", //no-check-names\n#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */\n#if defined(MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME)\n    \"SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME\", //no-check-names\n#endif /* MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME */\n#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)\n    \"SSL_CONTEXT_SERIALIZATION\", //no-check-names\n#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */\n#if defined(MBEDTLS_SSL_DEBUG_ALL)\n    \"SSL_DEBUG_ALL\", //no-check-names\n#endif /* MBEDTLS_SSL_DEBUG_ALL */\n#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)\n    \"SSL_ENCRYPT_THEN_MAC\", //no-check-names\n#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */\n#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)\n    \"SSL_EXTENDED_MASTER_SECRET\", //no-check-names\n#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */\n#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\n    \"SSL_KEEP_PEER_CERTIFICATE\", //no-check-names\n#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\n#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT)\n    \"SSL_KEYING_MATERIAL_EXPORT\", //no-check-names\n#endif /* MBEDTLS_SSL_KEYING_MATERIAL_EXPORT */\n#if defined(MBEDTLS_SSL_RENEGOTIATION)\n    \"SSL_RENEGOTIATION\", //no-check-names\n#endif /* MBEDTLS_SSL_RENEGOTIATION */\n#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)\n    \"SSL_MAX_FRAGMENT_LENGTH\", //no-check-names\n#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */\n#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)\n    \"SSL_RECORD_SIZE_LIMIT\", //no-check-names\n#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_2)\n    \"SSL_PROTO_TLS1_2\", //no-check-names\n#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */\n#if defined(MBEDTLS_SSL_PROTO_TLS1_3)\n    \"SSL_PROTO_TLS1_3\", //no-check-names\n#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */\n#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)\n    \"SSL_TLS1_3_COMPATIBILITY_MODE\", //no-check-names\n#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED)\n    \"SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED\", //no-check-names\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED */\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)\n    \"SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED\", //no-check-names\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */\n#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)\n    \"SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED\", //no-check-names\n#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED */\n#if defined(MBEDTLS_SSL_EARLY_DATA)\n    \"SSL_EARLY_DATA\", //no-check-names\n#endif /* MBEDTLS_SSL_EARLY_DATA */\n#if defined(MBEDTLS_SSL_PROTO_DTLS)\n    \"SSL_PROTO_DTLS\", //no-check-names\n#endif /* MBEDTLS_SSL_PROTO_DTLS */\n#if defined(MBEDTLS_SSL_ALPN)\n    \"SSL_ALPN\", //no-check-names\n#endif /* MBEDTLS_SSL_ALPN */\n#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)\n    \"SSL_DTLS_ANTI_REPLAY\", //no-check-names\n#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */\n#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)\n    \"SSL_DTLS_HELLO_VERIFY\", //no-check-names\n#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */\n#if defined(MBEDTLS_SSL_DTLS_SRTP)\n    \"SSL_DTLS_SRTP\", //no-check-names\n#endif /* MBEDTLS_SSL_DTLS_SRTP */\n#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE)\n    \"SSL_DTLS_CLIENT_PORT_REUSE\", //no-check-names\n#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */\n#if defined(MBEDTLS_SSL_SESSION_TICKETS)\n    \"SSL_SESSION_TICKETS\", //no-check-names\n#endif /* MBEDTLS_SSL_SESSION_TICKETS */\n#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)\n    \"SSL_SERVER_NAME_INDICATION\", //no-check-names\n#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */\n#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)\n    \"SSL_VARIABLE_BUFFER_LENGTH\", //no-check-names\n#endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */\n#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN)\n    \"TEST_CONSTANT_FLOW_MEMSAN\", //no-check-names\n#endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */\n#if defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND)\n    \"TEST_CONSTANT_FLOW_VALGRIND\", //no-check-names\n#endif /* MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND */\n#if defined(MBEDTLS_TEST_HOOKS)\n    \"TEST_HOOKS\", //no-check-names\n#endif /* MBEDTLS_TEST_HOOKS */\n#if defined(MBEDTLS_THREADING_ALT)\n    \"THREADING_ALT\", //no-check-names\n#endif /* MBEDTLS_THREADING_ALT */\n#if defined(MBEDTLS_THREADING_PTHREAD)\n    \"THREADING_PTHREAD\", //no-check-names\n#endif /* MBEDTLS_THREADING_PTHREAD */\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    \"USE_PSA_CRYPTO\", //no-check-names\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)\n    \"PSA_CRYPTO_CONFIG\", //no-check-names\n#endif /* MBEDTLS_PSA_CRYPTO_CONFIG */\n#if defined(MBEDTLS_VERSION_FEATURES)\n    \"VERSION_FEATURES\", //no-check-names\n#endif /* MBEDTLS_VERSION_FEATURES */\n#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)\n    \"X509_TRUSTED_CERTIFICATE_CALLBACK\", //no-check-names\n#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */\n#if defined(MBEDTLS_X509_REMOVE_INFO)\n    \"X509_REMOVE_INFO\", //no-check-names\n#endif /* MBEDTLS_X509_REMOVE_INFO */\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)\n    \"X509_RSASSA_PSS_SUPPORT\", //no-check-names\n#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */\n#if defined(MBEDTLS_AESNI_C)\n    \"AESNI_C\", //no-check-names\n#endif /* MBEDTLS_AESNI_C */\n#if defined(MBEDTLS_AESCE_C)\n    \"AESCE_C\", //no-check-names\n#endif /* MBEDTLS_AESCE_C */\n#if defined(MBEDTLS_AES_C)\n    \"AES_C\", //no-check-names\n#endif /* MBEDTLS_AES_C */\n#if defined(MBEDTLS_ASN1_PARSE_C)\n    \"ASN1_PARSE_C\", //no-check-names\n#endif /* MBEDTLS_ASN1_PARSE_C */\n#if defined(MBEDTLS_ASN1_WRITE_C)\n    \"ASN1_WRITE_C\", //no-check-names\n#endif /* MBEDTLS_ASN1_WRITE_C */\n#if defined(MBEDTLS_BASE64_C)\n    \"BASE64_C\", //no-check-names\n#endif /* MBEDTLS_BASE64_C */\n#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)\n    \"BLOCK_CIPHER_NO_DECRYPT\", //no-check-names\n#endif /* MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */\n#if defined(MBEDTLS_BIGNUM_C)\n    \"BIGNUM_C\", //no-check-names\n#endif /* MBEDTLS_BIGNUM_C */\n#if defined(MBEDTLS_CAMELLIA_C)\n    \"CAMELLIA_C\", //no-check-names\n#endif /* MBEDTLS_CAMELLIA_C */\n#if defined(MBEDTLS_ARIA_C)\n    \"ARIA_C\", //no-check-names\n#endif /* MBEDTLS_ARIA_C */\n#if defined(MBEDTLS_CCM_C)\n    \"CCM_C\", //no-check-names\n#endif /* MBEDTLS_CCM_C */\n#if defined(MBEDTLS_CHACHA20_C)\n    \"CHACHA20_C\", //no-check-names\n#endif /* MBEDTLS_CHACHA20_C */\n#if defined(MBEDTLS_CHACHAPOLY_C)\n    \"CHACHAPOLY_C\", //no-check-names\n#endif /* MBEDTLS_CHACHAPOLY_C */\n#if defined(MBEDTLS_CIPHER_C)\n    \"CIPHER_C\", //no-check-names\n#endif /* MBEDTLS_CIPHER_C */\n#if defined(MBEDTLS_CMAC_C)\n    \"CMAC_C\", //no-check-names\n#endif /* MBEDTLS_CMAC_C */\n#if defined(MBEDTLS_CTR_DRBG_C)\n    \"CTR_DRBG_C\", //no-check-names\n#endif /* MBEDTLS_CTR_DRBG_C */\n#if defined(MBEDTLS_DEBUG_C)\n    \"DEBUG_C\", //no-check-names\n#endif /* MBEDTLS_DEBUG_C */\n#if defined(MBEDTLS_DES_C)\n    \"DES_C\", //no-check-names\n#endif /* MBEDTLS_DES_C */\n#if defined(MBEDTLS_DHM_C)\n    \"DHM_C\", //no-check-names\n#endif /* MBEDTLS_DHM_C */\n#if defined(MBEDTLS_ECDH_C)\n    \"ECDH_C\", //no-check-names\n#endif /* MBEDTLS_ECDH_C */\n#if defined(MBEDTLS_ECDSA_C)\n    \"ECDSA_C\", //no-check-names\n#endif /* MBEDTLS_ECDSA_C */\n#if defined(MBEDTLS_ECJPAKE_C)\n    \"ECJPAKE_C\", //no-check-names\n#endif /* MBEDTLS_ECJPAKE_C */\n#if defined(MBEDTLS_ECP_C)\n    \"ECP_C\", //no-check-names\n#endif /* MBEDTLS_ECP_C */\n#if defined(MBEDTLS_ENTROPY_C)\n    \"ENTROPY_C\", //no-check-names\n#endif /* MBEDTLS_ENTROPY_C */\n#if defined(MBEDTLS_ERROR_C)\n    \"ERROR_C\", //no-check-names\n#endif /* MBEDTLS_ERROR_C */\n#if defined(MBEDTLS_GCM_C)\n    \"GCM_C\", //no-check-names\n#endif /* MBEDTLS_GCM_C */\n#if defined(MBEDTLS_GCM_LARGE_TABLE)\n    \"GCM_LARGE_TABLE\", //no-check-names\n#endif /* MBEDTLS_GCM_LARGE_TABLE */\n#if defined(MBEDTLS_HKDF_C)\n    \"HKDF_C\", //no-check-names\n#endif /* MBEDTLS_HKDF_C */\n#if defined(MBEDTLS_HMAC_DRBG_C)\n    \"HMAC_DRBG_C\", //no-check-names\n#endif /* MBEDTLS_HMAC_DRBG_C */\n#if defined(MBEDTLS_LMS_C)\n    \"LMS_C\", //no-check-names\n#endif /* MBEDTLS_LMS_C */\n#if defined(MBEDTLS_LMS_PRIVATE)\n    \"LMS_PRIVATE\", //no-check-names\n#endif /* MBEDTLS_LMS_PRIVATE */\n#if defined(MBEDTLS_NIST_KW_C)\n    \"NIST_KW_C\", //no-check-names\n#endif /* MBEDTLS_NIST_KW_C */\n#if defined(MBEDTLS_MD_C)\n    \"MD_C\", //no-check-names\n#endif /* MBEDTLS_MD_C */\n#if defined(MBEDTLS_MD5_C)\n    \"MD5_C\", //no-check-names\n#endif /* MBEDTLS_MD5_C */\n#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)\n    \"MEMORY_BUFFER_ALLOC_C\", //no-check-names\n#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */\n#if defined(MBEDTLS_NET_C)\n    \"NET_C\", //no-check-names\n#endif /* MBEDTLS_NET_C */\n#if defined(MBEDTLS_OID_C)\n    \"OID_C\", //no-check-names\n#endif /* MBEDTLS_OID_C */\n#if defined(MBEDTLS_PADLOCK_C)\n    \"PADLOCK_C\", //no-check-names\n#endif /* MBEDTLS_PADLOCK_C */\n#if defined(MBEDTLS_PEM_PARSE_C)\n    \"PEM_PARSE_C\", //no-check-names\n#endif /* MBEDTLS_PEM_PARSE_C */\n#if defined(MBEDTLS_PEM_WRITE_C)\n    \"PEM_WRITE_C\", //no-check-names\n#endif /* MBEDTLS_PEM_WRITE_C */\n#if defined(MBEDTLS_PK_C)\n    \"PK_C\", //no-check-names\n#endif /* MBEDTLS_PK_C */\n#if defined(MBEDTLS_PK_PARSE_C)\n    \"PK_PARSE_C\", //no-check-names\n#endif /* MBEDTLS_PK_PARSE_C */\n#if defined(MBEDTLS_PK_WRITE_C)\n    \"PK_WRITE_C\", //no-check-names\n#endif /* MBEDTLS_PK_WRITE_C */\n#if defined(MBEDTLS_PKCS5_C)\n    \"PKCS5_C\", //no-check-names\n#endif /* MBEDTLS_PKCS5_C */\n#if defined(MBEDTLS_PKCS7_C)\n    \"PKCS7_C\", //no-check-names\n#endif /* MBEDTLS_PKCS7_C */\n#if defined(MBEDTLS_PKCS12_C)\n    \"PKCS12_C\", //no-check-names\n#endif /* MBEDTLS_PKCS12_C */\n#if defined(MBEDTLS_PLATFORM_C)\n    \"PLATFORM_C\", //no-check-names\n#endif /* MBEDTLS_PLATFORM_C */\n#if defined(MBEDTLS_POLY1305_C)\n    \"POLY1305_C\", //no-check-names\n#endif /* MBEDTLS_POLY1305_C */\n#if defined(MBEDTLS_PSA_CRYPTO_C)\n    \"PSA_CRYPTO_C\", //no-check-names\n#endif /* MBEDTLS_PSA_CRYPTO_C */\n#if defined(MBEDTLS_PSA_CRYPTO_SE_C)\n    \"PSA_CRYPTO_SE_C\", //no-check-names\n#endif /* MBEDTLS_PSA_CRYPTO_SE_C */\n#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)\n    \"PSA_CRYPTO_STORAGE_C\", //no-check-names\n#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */\n#if defined(MBEDTLS_PSA_ITS_FILE_C)\n    \"PSA_ITS_FILE_C\", //no-check-names\n#endif /* MBEDTLS_PSA_ITS_FILE_C */\n#if defined(MBEDTLS_PSA_STATIC_KEY_SLOTS)\n    \"PSA_STATIC_KEY_SLOTS\", //no-check-names\n#endif /* MBEDTLS_PSA_STATIC_KEY_SLOTS */\n#if defined(MBEDTLS_RIPEMD160_C)\n    \"RIPEMD160_C\", //no-check-names\n#endif /* MBEDTLS_RIPEMD160_C */\n#if defined(MBEDTLS_RSA_C)\n    \"RSA_C\", //no-check-names\n#endif /* MBEDTLS_RSA_C */\n#if defined(MBEDTLS_SHA1_C)\n    \"SHA1_C\", //no-check-names\n#endif /* MBEDTLS_SHA1_C */\n#if defined(MBEDTLS_SHA224_C)\n    \"SHA224_C\", //no-check-names\n#endif /* MBEDTLS_SHA224_C */\n#if defined(MBEDTLS_SHA256_C)\n    \"SHA256_C\", //no-check-names\n#endif /* MBEDTLS_SHA256_C */\n#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)\n    \"SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT\", //no-check-names\n#endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */\n#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)\n    \"SHA256_USE_A64_CRYPTO_IF_PRESENT\", //no-check-names\n#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */\n#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)\n    \"SHA256_USE_ARMV8_A_CRYPTO_ONLY\", //no-check-names\n#endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */\n#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)\n    \"SHA256_USE_A64_CRYPTO_ONLY\", //no-check-names\n#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */\n#if defined(MBEDTLS_SHA384_C)\n    \"SHA384_C\", //no-check-names\n#endif /* MBEDTLS_SHA384_C */\n#if defined(MBEDTLS_SHA512_C)\n    \"SHA512_C\", //no-check-names\n#endif /* MBEDTLS_SHA512_C */\n#if defined(MBEDTLS_SHA3_C)\n    \"SHA3_C\", //no-check-names\n#endif /* MBEDTLS_SHA3_C */\n#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)\n    \"SHA512_USE_A64_CRYPTO_IF_PRESENT\", //no-check-names\n#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */\n#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)\n    \"SHA512_USE_A64_CRYPTO_ONLY\", //no-check-names\n#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */\n#if defined(MBEDTLS_SSL_CACHE_C)\n    \"SSL_CACHE_C\", //no-check-names\n#endif /* MBEDTLS_SSL_CACHE_C */\n#if defined(MBEDTLS_SSL_COOKIE_C)\n    \"SSL_COOKIE_C\", //no-check-names\n#endif /* MBEDTLS_SSL_COOKIE_C */\n#if defined(MBEDTLS_SSL_TICKET_C)\n    \"SSL_TICKET_C\", //no-check-names\n#endif /* MBEDTLS_SSL_TICKET_C */\n#if defined(MBEDTLS_SSL_CLI_C)\n    \"SSL_CLI_C\", //no-check-names\n#endif /* MBEDTLS_SSL_CLI_C */\n#if defined(MBEDTLS_SSL_SRV_C)\n    \"SSL_SRV_C\", //no-check-names\n#endif /* MBEDTLS_SSL_SRV_C */\n#if defined(MBEDTLS_SSL_TLS_C)\n    \"SSL_TLS_C\", //no-check-names\n#endif /* MBEDTLS_SSL_TLS_C */\n#if defined(MBEDTLS_THREADING_C)\n    \"THREADING_C\", //no-check-names\n#endif /* MBEDTLS_THREADING_C */\n#if defined(MBEDTLS_TIMING_C)\n    \"TIMING_C\", //no-check-names\n#endif /* MBEDTLS_TIMING_C */\n#if defined(MBEDTLS_VERSION_C)\n    \"VERSION_C\", //no-check-names\n#endif /* MBEDTLS_VERSION_C */\n#if defined(MBEDTLS_X509_USE_C)\n    \"X509_USE_C\", //no-check-names\n#endif /* MBEDTLS_X509_USE_C */\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n    \"X509_CRT_PARSE_C\", //no-check-names\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n#if defined(MBEDTLS_X509_CRL_PARSE_C)\n    \"X509_CRL_PARSE_C\", //no-check-names\n#endif /* MBEDTLS_X509_CRL_PARSE_C */\n#if defined(MBEDTLS_X509_CSR_PARSE_C)\n    \"X509_CSR_PARSE_C\", //no-check-names\n#endif /* MBEDTLS_X509_CSR_PARSE_C */\n#if defined(MBEDTLS_X509_CREATE_C)\n    \"X509_CREATE_C\", //no-check-names\n#endif /* MBEDTLS_X509_CREATE_C */\n#if defined(MBEDTLS_X509_CRT_WRITE_C)\n    \"X509_CRT_WRITE_C\", //no-check-names\n#endif /* MBEDTLS_X509_CRT_WRITE_C */\n#if defined(MBEDTLS_X509_CSR_WRITE_C)\n    \"X509_CSR_WRITE_C\", //no-check-names\n#endif /* MBEDTLS_X509_CSR_WRITE_C */\n#endif /* MBEDTLS_VERSION_FEATURES */\n    NULL\n};\n\nint mbedtls_version_check_feature(const char *feature)\n{\n    const char * const *idx = features;\n\n    if (*idx == NULL) {\n        return -2;\n    }\n\n    if (feature == NULL) {\n        return -1;\n    }\n\n    if (strncmp(feature, \"MBEDTLS_\", 8)) {\n        return -1;\n    }\n\n    feature += 8;\n\n    while (*idx != NULL) {\n        if (!strcmp(*idx, feature)) {\n            return 0;\n        }\n        idx++;\n    }\n    return -1;\n}\n\n#endif /* MBEDTLS_VERSION_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/x509.c",
    "content": "/*\n *  X.509 common functions for parsing and verification\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  The ITU-T X.509 standard defines a certificate format for PKI.\n *\n *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)\n *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)\n *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)\n *\n *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf\n *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_X509_USE_C)\n\n#include \"x509_internal.h\"\n#include \"mbedtls/asn1.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/oid.h\"\n\n#include <stdio.h>\n#include <string.h>\n\n#if defined(MBEDTLS_PEM_PARSE_C)\n#include \"mbedtls/pem.h\"\n#endif\n\n#include \"mbedtls/asn1write.h\"\n\n#include \"mbedtls/platform.h\"\n\n#if defined(MBEDTLS_HAVE_TIME)\n#include \"mbedtls/platform_time.h\"\n#endif\n#if defined(MBEDTLS_HAVE_TIME_DATE)\n#include \"mbedtls/platform_util.h\"\n#include <time.h>\n#endif\n\n#define CHECK(code)                                     \\\n    do {                                                \\\n        if ((ret = (code)) != 0) {                      \\\n            return ret;                                 \\\n        }                                               \\\n    } while (0)\n\n#define CHECK_RANGE(min, max, val)                      \\\n    do {                                                \\\n        if ((val) < (min) || (val) > (max)) {           \\\n            return ret;                                 \\\n        }                                               \\\n    } while (0)\n\n/*\n *  CertificateSerialNumber  ::=  INTEGER\n */\nint mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end,\n                            mbedtls_x509_buf *serial)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if ((end - *p) < 1) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL,\n                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);\n    }\n\n    if (**p != (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2) &&\n        **p !=   MBEDTLS_ASN1_INTEGER) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL,\n                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);\n    }\n\n    serial->tag = *(*p)++;\n\n    if ((ret = mbedtls_asn1_get_len(p, end, &serial->len)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, ret);\n    }\n\n    serial->p = *p;\n    *p += serial->len;\n\n    return 0;\n}\n\n/* Get an algorithm identifier without parameters (eg for signatures)\n *\n *  AlgorithmIdentifier  ::=  SEQUENCE  {\n *       algorithm               OBJECT IDENTIFIER,\n *       parameters              ANY DEFINED BY algorithm OPTIONAL  }\n */\nint mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end,\n                              mbedtls_x509_buf *alg)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);\n    }\n\n    return 0;\n}\n\n/*\n * Parse an algorithm identifier with (optional) parameters\n */\nint mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end,\n                         mbedtls_x509_buf *alg, mbedtls_x509_buf *params)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if ((ret = mbedtls_asn1_get_alg(p, end, alg, params)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);\n    }\n\n    return 0;\n}\n\n/*\n * Convert md type to string\n */\n#if !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)\n\nstatic inline const char *md_type_to_string(mbedtls_md_type_t md_alg)\n{\n    switch (md_alg) {\n#if defined(MBEDTLS_MD_CAN_MD5)\n        case MBEDTLS_MD_MD5:\n            return \"MD5\";\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA1)\n        case MBEDTLS_MD_SHA1:\n            return \"SHA1\";\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA224)\n        case MBEDTLS_MD_SHA224:\n            return \"SHA224\";\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA256)\n        case MBEDTLS_MD_SHA256:\n            return \"SHA256\";\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA384)\n        case MBEDTLS_MD_SHA384:\n            return \"SHA384\";\n#endif\n#if defined(MBEDTLS_MD_CAN_SHA512)\n        case MBEDTLS_MD_SHA512:\n            return \"SHA512\";\n#endif\n#if defined(MBEDTLS_MD_CAN_RIPEMD160)\n        case MBEDTLS_MD_RIPEMD160:\n            return \"RIPEMD160\";\n#endif\n        case MBEDTLS_MD_NONE:\n            return NULL;\n        default:\n            return NULL;\n    }\n}\n\n#endif /* !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) */\n\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)\n/*\n * HashAlgorithm ::= AlgorithmIdentifier\n *\n * AlgorithmIdentifier  ::=  SEQUENCE  {\n *      algorithm               OBJECT IDENTIFIER,\n *      parameters              ANY DEFINED BY algorithm OPTIONAL  }\n *\n * For HashAlgorithm, parameters MUST be NULL or absent.\n */\nstatic int x509_get_hash_alg(const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p;\n    const unsigned char *end;\n    mbedtls_x509_buf md_oid;\n    size_t len;\n\n    /* Make sure we got a SEQUENCE and setup bounds */\n    if (alg->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,\n                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);\n    }\n\n    p = alg->p;\n    end = p + alg->len;\n\n    if (p >= end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,\n                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);\n    }\n\n    /* Parse md_oid */\n    md_oid.tag = *p;\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &md_oid.len, MBEDTLS_ASN1_OID)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);\n    }\n\n    md_oid.p = p;\n    p += md_oid.len;\n\n    /* Get md_alg from md_oid */\n    if ((ret = mbedtls_oid_get_md_alg(&md_oid, md_alg)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);\n    }\n\n    /* Make sure params is absent of NULL */\n    if (p == end) {\n        return 0;\n    }\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_NULL)) != 0 || len != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);\n    }\n\n    if (p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n/*\n *    RSASSA-PSS-params  ::=  SEQUENCE  {\n *       hashAlgorithm     [0] HashAlgorithm DEFAULT sha1Identifier,\n *       maskGenAlgorithm  [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,\n *       saltLength        [2] INTEGER DEFAULT 20,\n *       trailerField      [3] INTEGER DEFAULT 1  }\n *    -- Note that the tags in this Sequence are explicit.\n *\n * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value\n * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other\n * option. Enforce this at parsing time.\n */\nint mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params,\n                                       mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,\n                                       int *salt_len)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char *p;\n    const unsigned char *end, *end2;\n    size_t len;\n    mbedtls_x509_buf alg_id, alg_params;\n\n    /* First set everything to defaults */\n    *md_alg = MBEDTLS_MD_SHA1;\n    *mgf_md = MBEDTLS_MD_SHA1;\n    *salt_len = 20;\n\n    /* Make sure params is a SEQUENCE and setup bounds */\n    if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,\n                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);\n    }\n\n    p = (unsigned char *) params->p;\n    end = p + params->len;\n\n    if (p == end) {\n        return 0;\n    }\n\n    /*\n     * HashAlgorithm\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |\n                                    0)) == 0) {\n        end2 = p + len;\n\n        /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */\n        if ((ret = mbedtls_x509_get_alg_null(&p, end2, &alg_id)) != 0) {\n            return ret;\n        }\n\n        if ((ret = mbedtls_oid_get_md_alg(&alg_id, md_alg)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);\n        }\n\n        if (p != end2) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,\n                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n        }\n    } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);\n    }\n\n    if (p == end) {\n        return 0;\n    }\n\n    /*\n     * MaskGenAlgorithm\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |\n                                    1)) == 0) {\n        end2 = p + len;\n\n        /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */\n        if ((ret = mbedtls_x509_get_alg(&p, end2, &alg_id, &alg_params)) != 0) {\n            return ret;\n        }\n\n        /* Only MFG1 is recognised for now */\n        if (MBEDTLS_OID_CMP(MBEDTLS_OID_MGF1, &alg_id) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE,\n                                     MBEDTLS_ERR_OID_NOT_FOUND);\n        }\n\n        /* Parse HashAlgorithm */\n        if ((ret = x509_get_hash_alg(&alg_params, mgf_md)) != 0) {\n            return ret;\n        }\n\n        if (p != end2) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,\n                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n        }\n    } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);\n    }\n\n    if (p == end) {\n        return 0;\n    }\n\n    /*\n     * salt_len\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |\n                                    2)) == 0) {\n        end2 = p + len;\n\n        if ((ret = mbedtls_asn1_get_int(&p, end2, salt_len)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);\n        }\n\n        if (p != end2) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,\n                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n        }\n    } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);\n    }\n\n    if (p == end) {\n        return 0;\n    }\n\n    /*\n     * trailer_field (if present, must be 1)\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |\n                                    3)) == 0) {\n        int trailer_field;\n\n        end2 = p + len;\n\n        if ((ret = mbedtls_asn1_get_int(&p, end2, &trailer_field)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);\n        }\n\n        if (p != end2) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,\n                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n        }\n\n        if (trailer_field != 1) {\n            return MBEDTLS_ERR_X509_INVALID_ALG;\n        }\n    } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);\n    }\n\n    if (p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */\n\n/*\n *  AttributeTypeAndValue ::= SEQUENCE {\n *    type     AttributeType,\n *    value    AttributeValue }\n *\n *  AttributeType ::= OBJECT IDENTIFIER\n *\n *  AttributeValue ::= ANY DEFINED BY AttributeType\n */\nstatic int x509_get_attr_type_value(unsigned char **p,\n                                    const unsigned char *end,\n                                    mbedtls_x509_name *cur)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n    mbedtls_x509_buf *oid;\n    mbedtls_x509_buf *val;\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);\n    }\n\n    end = *p + len;\n\n    if ((end - *p) < 1) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,\n                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);\n    }\n\n    oid = &cur->oid;\n    oid->tag = **p;\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &oid->len, MBEDTLS_ASN1_OID)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);\n    }\n\n    oid->p = *p;\n    *p += oid->len;\n\n    if ((end - *p) < 1) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,\n                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);\n    }\n\n    if (**p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING      &&\n        **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING &&\n        **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING &&\n        **p != MBEDTLS_ASN1_BIT_STRING) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,\n                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);\n    }\n\n    val = &cur->val;\n    val->tag = *(*p)++;\n\n    if ((ret = mbedtls_asn1_get_len(p, end, &val->len)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);\n    }\n\n    val->p = *p;\n    *p += val->len;\n\n    if (*p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    cur->next = NULL;\n\n    return 0;\n}\n\n/*\n *  Name ::= CHOICE { -- only one possibility for now --\n *       rdnSequence  RDNSequence }\n *\n *  RDNSequence ::= SEQUENCE OF RelativeDistinguishedName\n *\n *  RelativeDistinguishedName ::=\n *    SET OF AttributeTypeAndValue\n *\n *  AttributeTypeAndValue ::= SEQUENCE {\n *    type     AttributeType,\n *    value    AttributeValue }\n *\n *  AttributeType ::= OBJECT IDENTIFIER\n *\n *  AttributeValue ::= ANY DEFINED BY AttributeType\n *\n * The data structure is optimized for the common case where each RDN has only\n * one element, which is represented as a list of AttributeTypeAndValue.\n * For the general case we still use a flat list, but we mark elements of the\n * same set so that they are \"merged\" together in the functions that consume\n * this list, eg mbedtls_x509_dn_gets().\n *\n * On success, this function may allocate a linked list starting at cur->next\n * that must later be free'd by the caller using mbedtls_free(). In error\n * cases, this function frees all allocated memory internally and the caller\n * has no freeing responsibilities.\n */\nint mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,\n                          mbedtls_x509_name *cur)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t set_len;\n    const unsigned char *end_set;\n    mbedtls_x509_name *head = cur;\n\n    /* don't use recursion, we'd risk stack overflow if not optimized */\n    while (1) {\n        /*\n         * parse SET\n         */\n        if ((ret = mbedtls_asn1_get_tag(p, end, &set_len,\n                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) {\n            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);\n            goto error;\n        }\n\n        end_set  = *p + set_len;\n\n        while (1) {\n            if ((ret = x509_get_attr_type_value(p, end_set, cur)) != 0) {\n                goto error;\n            }\n\n            if (*p == end_set) {\n                break;\n            }\n\n            /* Mark this item as being no the only one in a set */\n            cur->next_merged = 1;\n\n            cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name));\n\n            if (cur->next == NULL) {\n                ret = MBEDTLS_ERR_X509_ALLOC_FAILED;\n                goto error;\n            }\n\n            cur = cur->next;\n        }\n\n        /*\n         * continue until end of SEQUENCE is reached\n         */\n        if (*p == end) {\n            return 0;\n        }\n\n        cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name));\n\n        if (cur->next == NULL) {\n            ret = MBEDTLS_ERR_X509_ALLOC_FAILED;\n            goto error;\n        }\n\n        cur = cur->next;\n    }\n\nerror:\n    /* Skip the first element as we did not allocate it */\n    mbedtls_asn1_free_named_data_list_shallow(head->next);\n    head->next = NULL;\n\n    return ret;\n}\n\nstatic int x509_date_is_valid(const mbedtls_x509_time *t)\n{\n    unsigned int month_days;\n    unsigned int year;\n    switch (t->mon) {\n        case 1: case 3: case 5: case 7: case 8: case 10: case 12:\n            month_days = 31;\n            break;\n        case 4: case 6: case 9: case 11:\n            month_days = 30;\n            break;\n        case 2:\n            year = (unsigned int) t->year;\n            month_days = ((year & 3) || (!(year % 100)\n                                         && (year % 400)))\n                          ? 28 : 29;\n            break;\n        default:\n            return MBEDTLS_ERR_X509_INVALID_DATE;\n    }\n\n    if ((unsigned int) (t->day - 1) >= month_days ||      /* (1 - days in month) */\n        /* (unsigned int) (t->mon - 1) >= 12 || */  /* (1 - 12) checked above */\n        (unsigned int) t->year > 9999 ||         /* (0 - 9999) */\n        (unsigned int) t->hour > 23 ||           /* (0 - 23) */\n        (unsigned int) t->min  > 59 ||           /* (0 - 59) */\n        (unsigned int) t->sec  > 59) {           /* (0 - 59) */\n        return MBEDTLS_ERR_X509_INVALID_DATE;\n    }\n\n    return 0;\n}\n\nstatic int x509_parse2_int(const unsigned char *p)\n{\n    uint32_t d1 = p[0] - '0';\n    uint32_t d2 = p[1] - '0';\n    return (d1 < 10 && d2 < 10) ? (int) (d1 * 10 + d2) : -1;\n}\n\n/*\n * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4)\n * field.\n */\nstatic int x509_parse_time(const unsigned char *p, mbedtls_x509_time *tm,\n                           size_t yearlen)\n{\n    int x;\n\n    /*\n     * Parse year, month, day, hour, minute, second\n     */\n    tm->year = x509_parse2_int(p);\n    if (tm->year < 0) {\n        return MBEDTLS_ERR_X509_INVALID_DATE;\n    }\n\n    if (4 == yearlen) {\n        x = tm->year * 100;\n        p += 2;\n        tm->year = x509_parse2_int(p);\n        if (tm->year < 0) {\n            return MBEDTLS_ERR_X509_INVALID_DATE;\n        }\n    } else {\n        x = (tm->year < 50) ? 2000 : 1900;\n    }\n    tm->year += x;\n\n    tm->mon  = x509_parse2_int(p + 2);\n    tm->day  = x509_parse2_int(p + 4);\n    tm->hour = x509_parse2_int(p + 6);\n    tm->min  = x509_parse2_int(p + 8);\n    tm->sec  = x509_parse2_int(p + 10);\n\n    return x509_date_is_valid(tm);\n}\n\n/*\n *  Time ::= CHOICE {\n *       utcTime        UTCTime,\n *       generalTime    GeneralizedTime }\n */\nint mbedtls_x509_get_time(unsigned char **p, const unsigned char *end,\n                          mbedtls_x509_time *tm)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len, year_len;\n    unsigned char tag;\n\n    if ((end - *p) < 1) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,\n                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);\n    }\n\n    tag = **p;\n\n    if (tag == MBEDTLS_ASN1_UTC_TIME) {\n        year_len = 2;\n    } else if (tag == MBEDTLS_ASN1_GENERALIZED_TIME) {\n        year_len = 4;\n    } else {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,\n                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);\n    }\n\n    (*p)++;\n    ret = mbedtls_asn1_get_len(p, end, &len);\n\n    if (ret != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret);\n    }\n\n    /* len is 12 or 14 depending on year_len, plus optional trailing 'Z' */\n    if (len != year_len + 10 &&\n        !(len == year_len + 11 && (*p)[(len - 1)] == 'Z')) {\n        return MBEDTLS_ERR_X509_INVALID_DATE;\n    }\n\n    (*p) += len;\n    return x509_parse_time(*p - len, tm, year_len);\n}\n\nint mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n    int tag_type;\n\n    if ((end - *p) < 1) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE,\n                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);\n    }\n\n    tag_type = **p;\n\n    if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret);\n    }\n\n    sig->tag = tag_type;\n    sig->len = len;\n    sig->p = *p;\n\n    *p += len;\n\n    return 0;\n}\n\n/*\n * Get signature algorithm from alg OID and optional parameters\n */\nint mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,\n                             mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,\n                             void **sig_opts)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (*sig_opts != NULL) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    if ((ret = mbedtls_oid_get_sig_alg(sig_oid, md_alg, pk_alg)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret);\n    }\n\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)\n    if (*pk_alg == MBEDTLS_PK_RSASSA_PSS) {\n        mbedtls_pk_rsassa_pss_options *pss_opts;\n\n        pss_opts = mbedtls_calloc(1, sizeof(mbedtls_pk_rsassa_pss_options));\n        if (pss_opts == NULL) {\n            return MBEDTLS_ERR_X509_ALLOC_FAILED;\n        }\n\n        ret = mbedtls_x509_get_rsassa_pss_params(sig_params,\n                                                 md_alg,\n                                                 &pss_opts->mgf1_hash_id,\n                                                 &pss_opts->expected_salt_len);\n        if (ret != 0) {\n            mbedtls_free(pss_opts);\n            return ret;\n        }\n\n        *sig_opts = (void *) pss_opts;\n    } else\n#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */\n    {\n        /* Make sure parameters are absent or NULL */\n        if ((sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0) ||\n            sig_params->len != 0) {\n            return MBEDTLS_ERR_X509_INVALID_ALG;\n        }\n    }\n\n    return 0;\n}\n\n/*\n * X.509 Extensions (No parsing of extensions, pointer should\n * be either manually updated or extensions should be parsed!)\n */\nint mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end,\n                         mbedtls_x509_buf *ext, int tag)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n\n    /* Extension structure use EXPLICIT tagging. That is, the actual\n     * `Extensions` structure is wrapped by a tag-length pair using\n     * the respective context-specific tag. */\n    ret = mbedtls_asn1_get_tag(p, end, &ext->len,\n                               MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag);\n    if (ret != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag;\n    ext->p   = *p;\n    end      = *p + ext->len;\n\n    /*\n     * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension\n     */\n    if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    if (end != *p + len) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\nstatic char nibble_to_hex_digit(int i)\n{\n    return (i < 10) ? (i + '0') : (i - 10 + 'A');\n}\n\n/*\n * Store the name in printable form into buf; no more\n * than size characters will be written\n */\nint mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t i, j, n, asn1_len_size, asn1_tag_size, asn1_tag_len_buf_start;\n    /* 6 is enough as our asn1 write functions only write one byte for the tag and at most five bytes for the length*/\n    unsigned char asn1_tag_len_buf[6];\n    unsigned char *asn1_len_p;\n    unsigned char c, merge = 0;\n    const mbedtls_x509_name *name;\n    const char *short_name = NULL;\n    char lowbits, highbits;\n    char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p;\n    int print_hexstring;\n\n    memset(s, 0, sizeof(s));\n\n    name = dn;\n    p = buf;\n    n = size;\n\n    while (name != NULL) {\n        if (!name->oid.p) {\n            name = name->next;\n            continue;\n        }\n\n        if (name != dn) {\n            ret = mbedtls_snprintf(p, n, merge ? \" + \" : \", \");\n            MBEDTLS_X509_SAFE_SNPRINTF;\n        }\n\n        print_hexstring = (name->val.tag != MBEDTLS_ASN1_UTF8_STRING) &&\n                          (name->val.tag != MBEDTLS_ASN1_PRINTABLE_STRING) &&\n                          (name->val.tag != MBEDTLS_ASN1_IA5_STRING);\n\n        if ((ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name)) == 0) {\n            ret = mbedtls_snprintf(p, n, \"%s=\", short_name);\n        } else {\n            if ((ret = mbedtls_oid_get_numeric_string(p, n, &name->oid)) > 0) {\n                n -= ret;\n                p += ret;\n                ret = mbedtls_snprintf(p, n, \"=\");\n                print_hexstring = 1;\n            } else if (ret == MBEDTLS_ERR_OID_BUF_TOO_SMALL) {\n                return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;\n            } else {\n                ret = mbedtls_snprintf(p, n, \"\\?\\?=\");\n            }\n        }\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        if (print_hexstring) {\n            s[0] = '#';\n\n            asn1_len_p = asn1_tag_len_buf + sizeof(asn1_tag_len_buf);\n            if ((ret = mbedtls_asn1_write_len(&asn1_len_p, asn1_tag_len_buf, name->val.len)) < 0) {\n                return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n            }\n            asn1_len_size = ret;\n            if ((ret = mbedtls_asn1_write_tag(&asn1_len_p, asn1_tag_len_buf, name->val.tag)) < 0) {\n                return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n            }\n            asn1_tag_size = ret;\n            asn1_tag_len_buf_start = sizeof(asn1_tag_len_buf) - asn1_len_size - asn1_tag_size;\n            for (i = 0, j = 1; i < asn1_len_size + asn1_tag_size; i++) {\n                if (j + 1 >= sizeof(s) - 1) {\n                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;\n                }\n                c = asn1_tag_len_buf[asn1_tag_len_buf_start+i];\n                lowbits = (c & 0x0F);\n                highbits = c >> 4;\n                s[j++] = nibble_to_hex_digit(highbits);\n                s[j++] = nibble_to_hex_digit(lowbits);\n            }\n            for (i = 0; i < name->val.len; i++) {\n                if (j + 1 >= sizeof(s) - 1) {\n                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;\n                }\n                c = name->val.p[i];\n                lowbits = (c & 0x0F);\n                highbits = c >> 4;\n                s[j++] = nibble_to_hex_digit(highbits);\n                s[j++] = nibble_to_hex_digit(lowbits);\n            }\n        } else {\n            for (i = 0, j = 0; i < name->val.len; i++, j++) {\n                if (j >= sizeof(s) - 1) {\n                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;\n                }\n\n                c = name->val.p[i];\n                // Special characters requiring escaping, RFC 4514 Section 2.4\n                if (c == '\\0') {\n                    return MBEDTLS_ERR_X509_INVALID_NAME;\n                } else {\n                    if (strchr(\",=+<>;\\\"\\\\\", c) ||\n                        ((i == 0) && strchr(\"# \", c)) ||\n                        ((i == name->val.len-1) && (c == ' '))) {\n                        if (j + 1 >= sizeof(s) - 1) {\n                            return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;\n                        }\n                        s[j++] = '\\\\';\n                    }\n                }\n                if (c < 32 || c >= 127) {\n                    if (j + 3 >= sizeof(s) - 1) {\n                        return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;\n                    }\n                    s[j++] = '\\\\';\n                    lowbits = (c & 0x0F);\n                    highbits = c >> 4;\n                    s[j++] = nibble_to_hex_digit(highbits);\n                    s[j] = nibble_to_hex_digit(lowbits);\n                } else {\n                    s[j] = c;\n                }\n            }\n        }\n        s[j] = '\\0';\n        ret = mbedtls_snprintf(p, n, \"%s\", s);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        merge = name->next_merged;\n        name = name->next;\n    }\n\n    return (int) (size - n);\n}\n\n/*\n * Store the serial in printable form into buf; no more\n * than size characters will be written\n */\nint mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t i, n, nr;\n    char *p;\n\n    p = buf;\n    n = size;\n\n    nr = (serial->len <= 32)\n        ? serial->len  : 28;\n\n    for (i = 0; i < nr; i++) {\n        if (i == 0 && nr > 1 && serial->p[i] == 0x0) {\n            continue;\n        }\n\n        ret = mbedtls_snprintf(p, n, \"%02X%s\",\n                               serial->p[i], (i < nr - 1) ? \":\" : \"\");\n        MBEDTLS_X509_SAFE_SNPRINTF;\n    }\n\n    if (nr != serial->len) {\n        ret = mbedtls_snprintf(p, n, \"....\");\n        MBEDTLS_X509_SAFE_SNPRINTF;\n    }\n\n    return (int) (size - n);\n}\n\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\n/*\n * Helper for writing signature algorithms\n */\nint mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid,\n                              mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,\n                              const void *sig_opts)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    char *p = buf;\n    size_t n = size;\n    const char *desc = NULL;\n\n    ret = mbedtls_oid_get_sig_alg_desc(sig_oid, &desc);\n    if (ret != 0) {\n        ret = mbedtls_snprintf(p, n, \"???\");\n    } else {\n        ret = mbedtls_snprintf(p, n, \"%s\", desc);\n    }\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)\n    if (pk_alg == MBEDTLS_PK_RSASSA_PSS) {\n        const mbedtls_pk_rsassa_pss_options *pss_opts;\n\n        pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts;\n\n        const char *name = md_type_to_string(md_alg);\n        const char *mgf_name = md_type_to_string(pss_opts->mgf1_hash_id);\n\n        ret = mbedtls_snprintf(p, n, \" (%s, MGF1-%s, 0x%02X)\",\n                               name ? name : \"???\",\n                               mgf_name ? mgf_name : \"???\",\n                               (unsigned int) pss_opts->expected_salt_len);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n    }\n#else\n    ((void) pk_alg);\n    ((void) md_alg);\n    ((void) sig_opts);\n#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */\n\n    return (int) (size - n);\n}\n#endif /* MBEDTLS_X509_REMOVE_INFO */\n\n/*\n * Helper for writing \"RSA key size\", \"EC key size\", etc\n */\nint mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name)\n{\n    char *p = buf;\n    size_t n = buf_size;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    ret = mbedtls_snprintf(p, n, \"%s key size\", name);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    return 0;\n}\n\nint mbedtls_x509_time_cmp(const mbedtls_x509_time *t1,\n                          const mbedtls_x509_time *t2)\n{\n    int x;\n\n    x = (((t1->year << 9) | (t1->mon << 5) | (t1->day)) -\n         ((t2->year << 9) | (t2->mon << 5) | (t2->day)));\n    if (x != 0) {\n        return x;\n    }\n\n    x = (((t1->hour << 12) | (t1->min << 6) | (t1->sec)) -\n         ((t2->hour << 12) | (t2->min << 6) | (t2->sec)));\n    return x;\n}\n\n#if defined(MBEDTLS_HAVE_TIME_DATE)\nint mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now)\n{\n    struct tm tm;\n\n    if (mbedtls_platform_gmtime_r(&tt, &tm) == NULL) {\n        return -1;\n    }\n\n    now->year = tm.tm_year + 1900;\n    now->mon  = tm.tm_mon  + 1;\n    now->day  = tm.tm_mday;\n    now->hour = tm.tm_hour;\n    now->min  = tm.tm_min;\n    now->sec  = tm.tm_sec;\n    return 0;\n}\n\nstatic int x509_get_current_time(mbedtls_x509_time *now)\n{\n    return mbedtls_x509_time_gmtime(mbedtls_time(NULL), now);\n}\n\nint mbedtls_x509_time_is_past(const mbedtls_x509_time *to)\n{\n    mbedtls_x509_time now;\n\n    if (x509_get_current_time(&now) != 0) {\n        return 1;\n    }\n\n    return mbedtls_x509_time_cmp(to, &now) < 0;\n}\n\nint mbedtls_x509_time_is_future(const mbedtls_x509_time *from)\n{\n    mbedtls_x509_time now;\n\n    if (x509_get_current_time(&now) != 0) {\n        return 1;\n    }\n\n    return mbedtls_x509_time_cmp(from, &now) > 0;\n}\n\n#else  /* MBEDTLS_HAVE_TIME_DATE */\n\nint mbedtls_x509_time_is_past(const mbedtls_x509_time *to)\n{\n    ((void) to);\n    return 0;\n}\n\nint mbedtls_x509_time_is_future(const mbedtls_x509_time *from)\n{\n    ((void) from);\n    return 0;\n}\n#endif /* MBEDTLS_HAVE_TIME_DATE */\n\n/* Common functions for parsing CRT and CSR. */\n#if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(MBEDTLS_X509_CSR_PARSE_C)\n/*\n * OtherName ::= SEQUENCE {\n *      type-id    OBJECT IDENTIFIER,\n *      value      [0] EXPLICIT ANY DEFINED BY type-id }\n *\n * HardwareModuleName ::= SEQUENCE {\n *                           hwType OBJECT IDENTIFIER,\n *                           hwSerialNum OCTET STRING }\n *\n * NOTE: we currently only parse and use otherName of type HwModuleName,\n * as defined in RFC 4108.\n */\nstatic int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name,\n                               mbedtls_x509_san_other_name *other_name)\n{\n    int ret = 0;\n    size_t len;\n    unsigned char *p = subject_alt_name->p;\n    const unsigned char *end = p + subject_alt_name->len;\n    mbedtls_x509_buf cur_oid;\n\n    if ((subject_alt_name->tag &\n         (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) !=\n        (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) {\n        /*\n         * The given subject alternative name is not of type \"othername\".\n         */\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_OID)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    cur_oid.tag = MBEDTLS_ASN1_OID;\n    cur_oid.p = p;\n    cur_oid.len = len;\n\n    /*\n     * Only HwModuleName is currently supported.\n     */\n    if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) {\n        return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;\n    }\n    other_name->type_id = cur_oid;\n\n    p += len;\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=\n        0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    if (end != p + len) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    if (end != p + len) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID;\n    other_name->value.hardware_module_name.oid.p = p;\n    other_name->value.hardware_module_name.oid.len = len;\n\n    p += len;\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_OCTET_STRING)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;\n    other_name->value.hardware_module_name.val.p = p;\n    other_name->value.hardware_module_name.val.len = len;\n    p += len;\n    if (p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n    return 0;\n}\n\n/* Check mbedtls_x509_get_subject_alt_name for detailed description.\n *\n * In some cases while parsing subject alternative names the sequence tag is optional\n * (e.g. CertSerialNumber). This function is designed to handle such case.\n */\nint mbedtls_x509_get_subject_alt_name_ext(unsigned char **p,\n                                          const unsigned char *end,\n                                          mbedtls_x509_sequence *subject_alt_name)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t tag_len;\n    mbedtls_asn1_sequence *cur = subject_alt_name;\n\n    while (*p < end) {\n        mbedtls_x509_subject_alternative_name tmp_san_name;\n        mbedtls_x509_buf tmp_san_buf;\n        memset(&tmp_san_name, 0, sizeof(tmp_san_name));\n\n        tmp_san_buf.tag = **p;\n        (*p)++;\n\n        if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        tmp_san_buf.p = *p;\n        tmp_san_buf.len = tag_len;\n\n        if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) !=\n            MBEDTLS_ASN1_CONTEXT_SPECIFIC) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                     MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);\n        }\n\n        /*\n         * Check that the SAN is structured correctly by parsing it.\n         * The SAN structure is discarded afterwards.\n         */\n        ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &tmp_san_name);\n        /*\n         * In case the extension is malformed, return an error,\n         * and clear the allocated sequences.\n         */\n        if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {\n            mbedtls_asn1_sequence_free(subject_alt_name->next);\n            subject_alt_name->next = NULL;\n            return ret;\n        }\n\n        mbedtls_x509_free_subject_alt_name(&tmp_san_name);\n        /* Allocate and assign next pointer */\n        if (cur->buf.p != NULL) {\n            if (cur->next != NULL) {\n                return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;\n            }\n\n            cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));\n\n            if (cur->next == NULL) {\n                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                         MBEDTLS_ERR_ASN1_ALLOC_FAILED);\n            }\n\n            cur = cur->next;\n        }\n\n        cur->buf = tmp_san_buf;\n        *p += tmp_san_buf.len;\n    }\n\n    /* Set final sequence entry's next pointer to NULL */\n    cur->next = NULL;\n\n    if (*p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n/*\n * SubjectAltName ::= GeneralNames\n *\n * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName\n *\n * GeneralName ::= CHOICE {\n *      otherName                       [0]     OtherName,\n *      rfc822Name                      [1]     IA5String,\n *      dNSName                         [2]     IA5String,\n *      x400Address                     [3]     ORAddress,\n *      directoryName                   [4]     Name,\n *      ediPartyName                    [5]     EDIPartyName,\n *      uniformResourceIdentifier       [6]     IA5String,\n *      iPAddress                       [7]     OCTET STRING,\n *      registeredID                    [8]     OBJECT IDENTIFIER }\n *\n * OtherName ::= SEQUENCE {\n *      type-id    OBJECT IDENTIFIER,\n *      value      [0] EXPLICIT ANY DEFINED BY type-id }\n *\n * EDIPartyName ::= SEQUENCE {\n *      nameAssigner            [0]     DirectoryString OPTIONAL,\n *      partyName               [1]     DirectoryString }\n *\n * We list all types, but use the following GeneralName types from RFC 5280:\n * \"dnsName\", \"uniformResourceIdentifier\" and \"hardware_module_name\"\n * of type \"otherName\", as defined in RFC 4108.\n */\nint mbedtls_x509_get_subject_alt_name(unsigned char **p,\n                                      const unsigned char *end,\n                                      mbedtls_x509_sequence *subject_alt_name)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n\n    /* Get main sequence tag */\n    if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    if (*p + len != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return mbedtls_x509_get_subject_alt_name_ext(p, end, subject_alt_name);\n}\n\nint mbedtls_x509_get_ns_cert_type(unsigned char **p,\n                                  const unsigned char *end,\n                                  unsigned char *ns_cert_type)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_x509_bitstring bs = { 0, 0, NULL };\n\n    if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    /* A bitstring with no flags set is still technically valid, as it will mean\n       that the certificate has no designated purpose at the time of creation. */\n    if (bs.len == 0) {\n        *ns_cert_type = 0;\n        return 0;\n    }\n\n    if (bs.len != 1) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_INVALID_LENGTH);\n    }\n\n    /* Get actual bitstring */\n    *ns_cert_type = *bs.p;\n    return 0;\n}\n\nint mbedtls_x509_get_key_usage(unsigned char **p,\n                               const unsigned char *end,\n                               unsigned int *key_usage)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t i;\n    mbedtls_x509_bitstring bs = { 0, 0, NULL };\n\n    if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    /* A bitstring with no flags set is still technically valid, as it will mean\n       that the certificate has no designated purpose at the time of creation. */\n    if (bs.len == 0) {\n        *key_usage = 0;\n        return 0;\n    }\n\n    /* Get actual bitstring */\n    *key_usage = 0;\n    for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) {\n        *key_usage |= (unsigned int) bs.p[i] << (8*i);\n    }\n\n    return 0;\n}\n\nint mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,\n                                        mbedtls_x509_subject_alternative_name *san)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    switch (san_buf->tag &\n            (MBEDTLS_ASN1_TAG_CLASS_MASK |\n             MBEDTLS_ASN1_TAG_VALUE_MASK)) {\n        /*\n         * otherName\n         */\n        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME):\n        {\n            mbedtls_x509_san_other_name other_name;\n\n            ret = x509_get_other_name(san_buf, &other_name);\n            if (ret != 0) {\n                return ret;\n            }\n\n            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));\n            san->type = MBEDTLS_X509_SAN_OTHER_NAME;\n            memcpy(&san->san.other_name,\n                   &other_name, sizeof(other_name));\n\n        }\n        break;\n        /*\n         * uniformResourceIdentifier\n         */\n        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER):\n        {\n            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));\n            san->type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER;\n\n            memcpy(&san->san.unstructured_name,\n                   san_buf, sizeof(*san_buf));\n\n        }\n        break;\n        /*\n         * dNSName\n         */\n        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME):\n        {\n            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));\n            san->type = MBEDTLS_X509_SAN_DNS_NAME;\n\n            memcpy(&san->san.unstructured_name,\n                   san_buf, sizeof(*san_buf));\n        }\n        break;\n        /*\n         * IP address\n         */\n        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_IP_ADDRESS):\n        {\n            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));\n            san->type = MBEDTLS_X509_SAN_IP_ADDRESS;\n            // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported\n            if (san_buf->len == 4 || san_buf->len == 16) {\n                memcpy(&san->san.unstructured_name,\n                       san_buf, sizeof(*san_buf));\n            } else {\n                return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n            }\n        }\n        break;\n        /*\n         * rfc822Name\n         */\n        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_RFC822_NAME):\n        {\n            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));\n            san->type = MBEDTLS_X509_SAN_RFC822_NAME;\n            memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf));\n        }\n        break;\n        /*\n         * directoryName\n         */\n        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DIRECTORY_NAME):\n        {\n            size_t name_len;\n            unsigned char *p = san_buf->p;\n            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));\n            san->type = MBEDTLS_X509_SAN_DIRECTORY_NAME;\n\n            ret = mbedtls_asn1_get_tag(&p, p + san_buf->len, &name_len,\n                                       MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);\n\n            if (ret != 0) {\n                return ret;\n            }\n\n            if ((ret = mbedtls_x509_get_name(&p, p + name_len,\n                                             &san->san.directory_name)) != 0) {\n                return ret;\n            }\n        }\n        break;\n        /*\n         * Type not supported\n         */\n        default:\n            return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;\n    }\n    return 0;\n}\n\nvoid mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san)\n{\n    if (san->type == MBEDTLS_X509_SAN_DIRECTORY_NAME) {\n        mbedtls_asn1_free_named_data_list_shallow(san->san.directory_name.next);\n    }\n}\n\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\nint mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,\n                                       const mbedtls_x509_sequence\n                                       *subject_alt_name,\n                                       const char *prefix)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t i;\n    size_t n = *size;\n    char *p = *buf;\n    const mbedtls_x509_sequence *cur = subject_alt_name;\n    mbedtls_x509_subject_alternative_name san;\n    int parse_ret;\n\n    while (cur != NULL) {\n        memset(&san, 0, sizeof(san));\n        parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san);\n        if (parse_ret != 0) {\n            if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {\n                ret = mbedtls_snprintf(p, n, \"\\n%s    <unsupported>\", prefix);\n                MBEDTLS_X509_SAFE_SNPRINTF;\n            } else {\n                ret = mbedtls_snprintf(p, n, \"\\n%s    <malformed>\", prefix);\n                MBEDTLS_X509_SAFE_SNPRINTF;\n            }\n            cur = cur->next;\n            continue;\n        }\n\n        switch (san.type) {\n            /*\n             * otherName\n             */\n            case MBEDTLS_X509_SAN_OTHER_NAME:\n            {\n                mbedtls_x509_san_other_name *other_name = &san.san.other_name;\n\n                ret = mbedtls_snprintf(p, n, \"\\n%s    otherName :\", prefix);\n                MBEDTLS_X509_SAFE_SNPRINTF;\n\n                if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME,\n                                    &other_name->type_id) == 0) {\n                    ret = mbedtls_snprintf(p, n, \"\\n%s        hardware module name :\", prefix);\n                    MBEDTLS_X509_SAFE_SNPRINTF;\n                    ret =\n                        mbedtls_snprintf(p, n, \"\\n%s            hardware type          : \", prefix);\n                    MBEDTLS_X509_SAFE_SNPRINTF;\n\n                    ret = mbedtls_oid_get_numeric_string(p,\n                                                         n,\n                                                         &other_name->value.hardware_module_name.oid);\n                    MBEDTLS_X509_SAFE_SNPRINTF;\n\n                    ret =\n                        mbedtls_snprintf(p, n, \"\\n%s            hardware serial number : \", prefix);\n                    MBEDTLS_X509_SAFE_SNPRINTF;\n\n                    for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) {\n                        ret = mbedtls_snprintf(p,\n                                               n,\n                                               \"%02X\",\n                                               other_name->value.hardware_module_name.val.p[i]);\n                        MBEDTLS_X509_SAFE_SNPRINTF;\n                    }\n                }/* MBEDTLS_OID_ON_HW_MODULE_NAME */\n            }\n            break;\n            /*\n             * uniformResourceIdentifier\n             */\n            case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:\n            {\n                ret = mbedtls_snprintf(p, n, \"\\n%s    uniformResourceIdentifier : \", prefix);\n                MBEDTLS_X509_SAFE_SNPRINTF;\n                if (san.san.unstructured_name.len >= n) {\n                    if (n > 0) {\n                        *p = '\\0';\n                    }\n                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;\n                }\n\n                memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);\n                p += san.san.unstructured_name.len;\n                n -= san.san.unstructured_name.len;\n            }\n            break;\n            /*\n             * dNSName\n             * RFC822 Name\n             */\n            case MBEDTLS_X509_SAN_DNS_NAME:\n            case MBEDTLS_X509_SAN_RFC822_NAME:\n            {\n                const char *dns_name = \"dNSName\";\n                const char *rfc822_name = \"rfc822Name\";\n\n                ret = mbedtls_snprintf(p, n,\n                                       \"\\n%s    %s : \",\n                                       prefix,\n                                       san.type ==\n                                       MBEDTLS_X509_SAN_DNS_NAME ? dns_name : rfc822_name);\n                MBEDTLS_X509_SAFE_SNPRINTF;\n                if (san.san.unstructured_name.len >= n) {\n                    if (n > 0) {\n                        *p = '\\0';\n                    }\n                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;\n                }\n\n                memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);\n                p += san.san.unstructured_name.len;\n                n -= san.san.unstructured_name.len;\n            }\n            break;\n            /*\n             * iPAddress\n             */\n            case MBEDTLS_X509_SAN_IP_ADDRESS:\n            {\n                ret = mbedtls_snprintf(p, n, \"\\n%s    %s : \",\n                                       prefix, \"iPAddress\");\n                MBEDTLS_X509_SAFE_SNPRINTF;\n                if (san.san.unstructured_name.len >= n) {\n                    if (n > 0) {\n                        *p = '\\0';\n                    }\n                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;\n                }\n\n                unsigned char *ip = san.san.unstructured_name.p;\n                // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported\n                if (san.san.unstructured_name.len == 4) {\n                    ret = mbedtls_snprintf(p, n, \"%u.%u.%u.%u\", ip[0], ip[1], ip[2], ip[3]);\n                    MBEDTLS_X509_SAFE_SNPRINTF;\n                } else if (san.san.unstructured_name.len == 16) {\n                    ret = mbedtls_snprintf(p, n,\n                                           \"%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X\",\n                                           ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6],\n                                           ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13],\n                                           ip[14], ip[15]);\n                    MBEDTLS_X509_SAFE_SNPRINTF;\n                } else {\n                    if (n > 0) {\n                        *p = '\\0';\n                    }\n                    return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n                }\n            }\n            break;\n            /*\n             * directoryName\n             */\n            case MBEDTLS_X509_SAN_DIRECTORY_NAME:\n            {\n                ret = mbedtls_snprintf(p, n, \"\\n%s    directoryName : \", prefix);\n                if (ret < 0 || (size_t) ret >= n) {\n                    mbedtls_x509_free_subject_alt_name(&san);\n                }\n\n                MBEDTLS_X509_SAFE_SNPRINTF;\n                ret = mbedtls_x509_dn_gets(p, n, &san.san.directory_name);\n\n                if (ret < 0) {\n                    mbedtls_x509_free_subject_alt_name(&san);\n                    if (n > 0) {\n                        *p = '\\0';\n                    }\n                    return ret;\n                }\n\n                p += ret;\n                n -= ret;\n            }\n            break;\n            /*\n             * Type not supported, skip item.\n             */\n            default:\n                ret = mbedtls_snprintf(p, n, \"\\n%s    <unsupported>\", prefix);\n                MBEDTLS_X509_SAFE_SNPRINTF;\n                break;\n        }\n\n        /* So far memory is freed only in the case of directoryName\n         * parsing succeeding, as mbedtls_x509_get_name allocates memory. */\n        mbedtls_x509_free_subject_alt_name(&san);\n        cur = cur->next;\n    }\n\n    *p = '\\0';\n\n    *size = n;\n    *buf = p;\n\n    return 0;\n}\n\n#define PRINT_ITEM(i)                                   \\\n    do {                                                \\\n        ret = mbedtls_snprintf(p, n, \"%s\" i, sep);      \\\n        MBEDTLS_X509_SAFE_SNPRINTF;                     \\\n        sep = \", \";                                     \\\n    } while (0)\n\n#define CERT_TYPE(type, name)                           \\\n    do {                                                \\\n        if (ns_cert_type & (type)) {                    \\\n            PRINT_ITEM(name);                           \\\n        }                                               \\\n    } while (0)\n\nint mbedtls_x509_info_cert_type(char **buf, size_t *size,\n                                unsigned char ns_cert_type)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t n = *size;\n    char *p = *buf;\n    const char *sep = \"\";\n\n    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT,         \"SSL Client\");\n    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER,         \"SSL Server\");\n    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL,              \"Email\");\n    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING,     \"Object Signing\");\n    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED,           \"Reserved\");\n    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA,             \"SSL CA\");\n    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA,           \"Email CA\");\n    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA,  \"Object Signing CA\");\n\n    *size = n;\n    *buf = p;\n\n    return 0;\n}\n\n#define KEY_USAGE(code, name)       \\\n    do {                            \\\n        if ((key_usage) & (code)) { \\\n            PRINT_ITEM(name);       \\\n        }                           \\\n    } while (0)\n\nint mbedtls_x509_info_key_usage(char **buf, size_t *size,\n                                unsigned int key_usage)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t n = *size;\n    char *p = *buf;\n    const char *sep = \"\";\n\n    KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE,    \"Digital Signature\");\n    KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION,      \"Non Repudiation\");\n    KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT,     \"Key Encipherment\");\n    KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT,    \"Data Encipherment\");\n    KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT,        \"Key Agreement\");\n    KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN,        \"Key Cert Sign\");\n    KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN,             \"CRL Sign\");\n    KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY,        \"Encipher Only\");\n    KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY,        \"Decipher Only\");\n\n    *size = n;\n    *buf = p;\n\n    return 0;\n}\n#endif /* MBEDTLS_X509_REMOVE_INFO */\n#endif /* MBEDTLS_X509_CRT_PARSE_C || MBEDTLS_X509_CSR_PARSE_C */\n#endif /* MBEDTLS_X509_USE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/x509_create.c",
    "content": "/*\n *  X.509 base functions for creating certificates / CSRs\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_X509_CREATE_C)\n\n#include \"x509_internal.h\"\n#include \"mbedtls/asn1write.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/oid.h\"\n\n#include <string.h>\n\n#include \"mbedtls/platform.h\"\n\n#include \"mbedtls/asn1.h\"\n\n/* Structure linking OIDs for X.509 DN AttributeTypes to their\n * string representations and default string encodings used by Mbed TLS. */\ntypedef struct {\n    const char *name; /* String representation of AttributeType, e.g.\n                       * \"CN\" or \"emailAddress\". */\n    size_t name_len; /* Length of 'name', without trailing 0 byte. */\n    const char *oid; /* String representation of OID of AttributeType,\n                      * as per RFC 5280, Appendix A.1. encoded as per\n                      * X.690 */\n    int default_tag; /* The default character encoding used for the\n                      * given attribute type, e.g.\n                      * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */\n} x509_attr_descriptor_t;\n\n#define ADD_STRLEN(s)     s, sizeof(s) - 1\n\n/* X.509 DN attributes from RFC 5280, Appendix A.1. */\nstatic const x509_attr_descriptor_t x509_attrs[] =\n{\n    { ADD_STRLEN(\"CN\"),\n      MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"commonName\"),\n      MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"C\"),\n      MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING },\n    { ADD_STRLEN(\"countryName\"),\n      MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING },\n    { ADD_STRLEN(\"O\"),\n      MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"organizationName\"),\n      MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"L\"),\n      MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"locality\"),\n      MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"R\"),\n      MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING },\n    { ADD_STRLEN(\"OU\"),\n      MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"organizationalUnitName\"),\n      MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"ST\"),\n      MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"stateOrProvinceName\"),\n      MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"emailAddress\"),\n      MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING },\n    { ADD_STRLEN(\"serialNumber\"),\n      MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING },\n    { ADD_STRLEN(\"postalAddress\"),\n      MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING },\n    { ADD_STRLEN(\"postalCode\"),\n      MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING },\n    { ADD_STRLEN(\"dnQualifier\"),\n      MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING },\n    { ADD_STRLEN(\"title\"),\n      MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"surName\"),\n      MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"SN\"),\n      MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"givenName\"),\n      MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"GN\"),\n      MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"initials\"),\n      MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"pseudonym\"),\n      MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"generationQualifier\"),\n      MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING },\n    { ADD_STRLEN(\"domainComponent\"),\n      MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING },\n    { ADD_STRLEN(\"DC\"),\n      MBEDTLS_OID_DOMAIN_COMPONENT,   MBEDTLS_ASN1_IA5_STRING },\n    { NULL, 0, NULL, MBEDTLS_ASN1_NULL }\n};\n\nstatic const x509_attr_descriptor_t *x509_attr_descr_from_name(const char *name, size_t name_len)\n{\n    const x509_attr_descriptor_t *cur;\n\n    for (cur = x509_attrs; cur->name != NULL; cur++) {\n        if (cur->name_len == name_len &&\n            strncmp(cur->name, name, name_len) == 0) {\n            break;\n        }\n    }\n\n    if (cur->name == NULL) {\n        return NULL;\n    }\n\n    return cur;\n}\n\nstatic int hex_to_int(char c)\n{\n    return ('0' <= c && c <= '9') ? (c - '0') :\n           ('a' <= c && c <= 'f') ? (c - 'a' + 10) :\n           ('A' <= c && c <= 'F') ? (c - 'A' + 10) : -1;\n}\n\nstatic int hexpair_to_int(const char *hexpair)\n{\n    int n1 = hex_to_int(*hexpair);\n    int n2 = hex_to_int(*(hexpair + 1));\n\n    if (n1 != -1 && n2 != -1) {\n        return (n1 << 4) | n2;\n    } else {\n        return -1;\n    }\n}\n\nstatic int parse_attribute_value_string(const char *s,\n                                        int len,\n                                        unsigned char *data,\n                                        size_t *data_len)\n{\n    const char *c;\n    const char *end = s + len;\n    unsigned char *d = data;\n    int n;\n\n    for (c = s; c < end; c++) {\n        if (*c == '\\\\') {\n            c++;\n\n            /* Check for valid escaped characters as per RFC 4514 Section 3 */\n            if (c + 1 < end && (n = hexpair_to_int(c)) != -1) {\n                if (n == 0) {\n                    return MBEDTLS_ERR_X509_INVALID_NAME;\n                }\n                *(d++) = n;\n                c++;\n            } else if (c < end && strchr(\" ,=+<>#;\\\"\\\\\", *c)) {\n                *(d++) = *c;\n            } else {\n                return MBEDTLS_ERR_X509_INVALID_NAME;\n            }\n        } else {\n            *(d++) = *c;\n        }\n\n        if (d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE) {\n            return MBEDTLS_ERR_X509_INVALID_NAME;\n        }\n    }\n    *data_len = (size_t) (d - data);\n    return 0;\n}\n\n/** Parse a hexstring containing a DER-encoded string.\n *\n * \\param s         A string of \\p len bytes hexadecimal digits.\n * \\param len       Number of bytes to read from \\p s.\n * \\param data      Output buffer of size \\p data_size.\n *                  On success, it contains the payload that's DER-encoded\n *                  in the input (content without the tag and length).\n *                  If the DER tag is a string tag, the payload is guaranteed\n *                  not to contain null bytes.\n * \\param data_size Length of the \\p data buffer.\n * \\param data_len  On success, the length of the parsed string.\n *                  It is guaranteed to be less than\n *                  #MBEDTLS_X509_MAX_DN_NAME_SIZE.\n * \\param tag       The ASN.1 tag that the payload in \\p data is encoded in.\n *\n * \\retval          0 on success.\n * \\retval          #MBEDTLS_ERR_X509_INVALID_NAME if \\p s does not contain\n *                  a valid hexstring,\n *                  or if the decoded hexstring is not valid DER,\n *                  or if the payload does not fit in \\p data,\n *                  or if the payload is more than\n *                  #MBEDTLS_X509_MAX_DN_NAME_SIZE bytes,\n *                  of if \\p *tag is an ASN.1 string tag and the payload\n *                  contains a null byte.\n * \\retval          #MBEDTLS_ERR_X509_ALLOC_FAILED on low memory.\n */\nstatic int parse_attribute_value_hex_der_encoded(const char *s,\n                                                 size_t len,\n                                                 unsigned char *data,\n                                                 size_t data_size,\n                                                 size_t *data_len,\n                                                 int *tag)\n{\n    /* Step 1: preliminary length checks. */\n    /* Each byte is encoded by exactly two hexadecimal digits. */\n    if (len % 2 != 0) {\n        /* Odd number of hex digits */\n        return MBEDTLS_ERR_X509_INVALID_NAME;\n    }\n    size_t const der_length = len / 2;\n    if (der_length > MBEDTLS_X509_MAX_DN_NAME_SIZE + 4) {\n        /* The payload would be more than MBEDTLS_X509_MAX_DN_NAME_SIZE\n         * (after subtracting the ASN.1 tag and length). Reject this early\n         * to avoid allocating a large intermediate buffer. */\n        return MBEDTLS_ERR_X509_INVALID_NAME;\n    }\n    if (der_length < 1) {\n        /* Avoid empty-buffer shenanigans. A valid DER encoding is never\n         * empty. */\n        return MBEDTLS_ERR_X509_INVALID_NAME;\n    }\n\n    /* Step 2: Decode the hex string into an intermediate buffer. */\n    unsigned char *der = mbedtls_calloc(1, der_length);\n    if (der == NULL) {\n        return MBEDTLS_ERR_X509_ALLOC_FAILED;\n    }\n    /* Beyond this point, der needs to be freed on exit. */\n    for (size_t i = 0; i < der_length; i++) {\n        int c = hexpair_to_int(s + 2 * i);\n        if (c < 0) {\n            goto error;\n        }\n        der[i] = c;\n    }\n\n    /* Step 3: decode the DER. */\n    /* We've checked that der_length >= 1 above. */\n    *tag = der[0];\n    {\n        unsigned char *p = der + 1;\n        if (mbedtls_asn1_get_len(&p, der + der_length, data_len) != 0) {\n            goto error;\n        }\n        /* Now p points to the first byte of the payload inside der,\n         * and *data_len is the length of the payload. */\n\n        /* Step 4: payload validation */\n        if (*data_len > MBEDTLS_X509_MAX_DN_NAME_SIZE) {\n            goto error;\n        }\n        /* Strings must not contain null bytes. */\n        if (MBEDTLS_ASN1_IS_STRING_TAG(*tag)) {\n            for (size_t i = 0; i < *data_len; i++) {\n                if (p[i] == 0) {\n                    goto error;\n                }\n            }\n        }\n\n        /* Step 5: output the payload. */\n        if (*data_len > data_size) {\n            goto error;\n        }\n        memcpy(data, p, *data_len);\n    }\n    mbedtls_free(der);\n\n    return 0;\n\nerror:\n    mbedtls_free(der);\n    return MBEDTLS_ERR_X509_INVALID_NAME;\n}\n\nint mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name)\n{\n    int ret = MBEDTLS_ERR_X509_INVALID_NAME;\n    int parse_ret = 0;\n    const char *s = name, *c = s;\n    const char *end = s + strlen(s);\n    mbedtls_asn1_buf oid = { .p = NULL, .len = 0, .tag = MBEDTLS_ASN1_NULL };\n    const x509_attr_descriptor_t *attr_descr = NULL;\n    int in_attr_type = 1;\n    int tag;\n    int numericoid = 0;\n    unsigned char data[MBEDTLS_X509_MAX_DN_NAME_SIZE];\n    size_t data_len = 0;\n\n    /* Ensure the output parameter is not already populated.\n     * (If it were, overwriting it would likely cause a memory leak.)\n     */\n    if (*head != NULL) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    while (c <= end) {\n        if (in_attr_type && *c == '=') {\n            if ((attr_descr = x509_attr_descr_from_name(s, (size_t) (c - s))) == NULL) {\n                if ((mbedtls_oid_from_numeric_string(&oid, s, (size_t) (c - s))) != 0) {\n                    return MBEDTLS_ERR_X509_INVALID_NAME;\n                } else {\n                    numericoid = 1;\n                }\n            } else {\n                oid.len = strlen(attr_descr->oid);\n                oid.p = mbedtls_calloc(1, oid.len);\n                memcpy(oid.p, attr_descr->oid, oid.len);\n                numericoid = 0;\n            }\n\n            s = c + 1;\n            in_attr_type = 0;\n        }\n\n        if (!in_attr_type && ((*c == ',' && *(c-1) != '\\\\') || c == end)) {\n            if (s == c) {\n                mbedtls_free(oid.p);\n                return MBEDTLS_ERR_X509_INVALID_NAME;\n            } else if (*s == '#') {\n                /* We know that c >= s (loop invariant) and c != s (in this\n                 * else branch), hence c - s - 1 >= 0. */\n                parse_ret = parse_attribute_value_hex_der_encoded(\n                    s + 1, (size_t) (c - s) - 1,\n                    data, sizeof(data), &data_len, &tag);\n                if (parse_ret != 0) {\n                    mbedtls_free(oid.p);\n                    return parse_ret;\n                }\n            } else {\n                if (numericoid) {\n                    mbedtls_free(oid.p);\n                    return MBEDTLS_ERR_X509_INVALID_NAME;\n                } else {\n                    if ((parse_ret =\n                             parse_attribute_value_string(s, (int) (c - s), data,\n                                                          &data_len)) != 0) {\n                        mbedtls_free(oid.p);\n                        return parse_ret;\n                    }\n                    tag = attr_descr->default_tag;\n                }\n            }\n\n            mbedtls_asn1_named_data *cur =\n                mbedtls_asn1_store_named_data(head, (char *) oid.p, oid.len,\n                                              (unsigned char *) data,\n                                              data_len);\n            mbedtls_free(oid.p);\n            oid.p = NULL;\n            if (cur == NULL) {\n                return MBEDTLS_ERR_X509_ALLOC_FAILED;\n            }\n\n            // set tagType\n            cur->val.tag = tag;\n\n            while (c < end && *(c + 1) == ' ') {\n                c++;\n            }\n\n            s = c + 1;\n            in_attr_type = 1;\n\n            /* Successfully parsed one name, update ret to success */\n            ret = 0;\n        }\n        c++;\n    }\n    if (oid.p != NULL) {\n        mbedtls_free(oid.p);\n    }\n    return ret;\n}\n\n/* The first byte of the value in the mbedtls_asn1_named_data structure is reserved\n * to store the critical boolean for us\n */\nint mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len,\n                               int critical, const unsigned char *val, size_t val_len)\n{\n    mbedtls_asn1_named_data *cur;\n\n    if (val_len > (SIZE_MAX  - 1)) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    if ((cur = mbedtls_asn1_store_named_data(head, oid, oid_len,\n                                             NULL, val_len + 1)) == NULL) {\n        return MBEDTLS_ERR_X509_ALLOC_FAILED;\n    }\n\n    cur->val.p[0] = critical;\n    memcpy(cur->val.p + 1, val, val_len);\n\n    return 0;\n}\n\n/*\n *  RelativeDistinguishedName ::=\n *    SET OF AttributeTypeAndValue\n *\n *  AttributeTypeAndValue ::= SEQUENCE {\n *    type     AttributeType,\n *    value    AttributeValue }\n *\n *  AttributeType ::= OBJECT IDENTIFIER\n *\n *  AttributeValue ::= ANY DEFINED BY AttributeType\n */\nstatic int x509_write_name(unsigned char **p,\n                           unsigned char *start,\n                           mbedtls_asn1_named_data *cur_name)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n    const char *oid             = (const char *) cur_name->oid.p;\n    size_t oid_len              = cur_name->oid.len;\n    const unsigned char *name   = cur_name->val.p;\n    size_t name_len             = cur_name->val.len;\n\n    // Write correct string tag and value\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tagged_string(p, start,\n                                                               cur_name->val.tag,\n                                                               (const char *) name,\n                                                               name_len));\n    // Write OID\n    //\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid,\n                                                     oid_len));\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,\n                                                     MBEDTLS_ASN1_CONSTRUCTED |\n                                                     MBEDTLS_ASN1_SEQUENCE));\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,\n                                                     MBEDTLS_ASN1_CONSTRUCTED |\n                                                     MBEDTLS_ASN1_SET));\n\n    return (int) len;\n}\n\nint mbedtls_x509_write_names(unsigned char **p, unsigned char *start,\n                             mbedtls_asn1_named_data *first)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n    mbedtls_asn1_named_data *cur = first;\n\n    while (cur != NULL) {\n        MBEDTLS_ASN1_CHK_ADD(len, x509_write_name(p, start, cur));\n        cur = cur->next;\n    }\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |\n                                                     MBEDTLS_ASN1_SEQUENCE));\n\n    return (int) len;\n}\n\nint mbedtls_x509_write_sig(unsigned char **p, unsigned char *start,\n                           const char *oid, size_t oid_len,\n                           unsigned char *sig, size_t size,\n                           mbedtls_pk_type_t pk_alg)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    int write_null_par;\n    size_t len = 0;\n\n    if (*p < start || (size_t) (*p - start) < size) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n\n    len = size;\n    (*p) -= len;\n    memcpy(*p, sig, len);\n\n    if (*p - start < 1) {\n        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;\n    }\n\n    *--(*p) = 0;\n    len += 1;\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BIT_STRING));\n\n    // Write OID\n    //\n    if (pk_alg == MBEDTLS_PK_ECDSA) {\n        /*\n         * The AlgorithmIdentifier's parameters field must be absent for DSA/ECDSA signature\n         * algorithms, see https://www.rfc-editor.org/rfc/rfc5480#page-17 and\n         * https://www.rfc-editor.org/rfc/rfc5758#section-3.\n         */\n        write_null_par = 0;\n    } else {\n        write_null_par = 1;\n    }\n    MBEDTLS_ASN1_CHK_ADD(len,\n                         mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len,\n                                                                     0, write_null_par));\n\n    return (int) len;\n}\n\nstatic int x509_write_extension(unsigned char **p, unsigned char *start,\n                                mbedtls_asn1_named_data *ext)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, ext->val.p + 1,\n                                                            ext->val.len - 1));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, ext->val.len - 1));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OCTET_STRING));\n\n    if (ext->val.p[0] != 0) {\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_bool(p, start, 1));\n    }\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, ext->oid.p,\n                                                            ext->oid.len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, ext->oid.len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OID));\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |\n                                                     MBEDTLS_ASN1_SEQUENCE));\n\n    return (int) len;\n}\n\n/*\n * Extension  ::=  SEQUENCE  {\n *     extnID      OBJECT IDENTIFIER,\n *     critical    BOOLEAN DEFAULT FALSE,\n *     extnValue   OCTET STRING\n *                 -- contains the DER encoding of an ASN.1 value\n *                 -- corresponding to the extension type identified\n *                 -- by extnID\n *     }\n */\nint mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start,\n                                  mbedtls_asn1_named_data *first)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n    mbedtls_asn1_named_data *cur_ext = first;\n\n    while (cur_ext != NULL) {\n        MBEDTLS_ASN1_CHK_ADD(len, x509_write_extension(p, start, cur_ext));\n        cur_ext = cur_ext->next;\n    }\n\n    return (int) len;\n}\n\n#endif /* MBEDTLS_X509_CREATE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/x509_crl.c",
    "content": "/*\n *  X.509 Certificate Revocation List (CRL) parsing\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  The ITU-T X.509 standard defines a certificate format for PKI.\n *\n *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)\n *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)\n *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)\n *\n *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf\n *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_X509_CRL_PARSE_C)\n\n#include \"mbedtls/x509_crl.h\"\n#include \"x509_internal.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/oid.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_PEM_PARSE_C)\n#include \"mbedtls/pem.h\"\n#endif\n\n#include \"mbedtls/platform.h\"\n\n#if defined(MBEDTLS_HAVE_TIME)\n#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)\n#include <windows.h>\n#else\n#include <time.h>\n#endif\n#endif\n\n#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)\n#include <stdio.h>\n#endif\n\n/*\n *  Version  ::=  INTEGER  {  v1(0), v2(1)  }\n */\nstatic int x509_crl_get_version(unsigned char **p,\n                                const unsigned char *end,\n                                int *ver)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) {\n        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n            *ver = 0;\n            return 0;\n        }\n\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret);\n    }\n\n    return 0;\n}\n\n/*\n * X.509 CRL v2 extensions\n *\n * We currently don't parse any extension's content, but we do check that the\n * list of extensions is well-formed and abort on critical extensions (that\n * are unsupported as we don't support any extension so far)\n */\nstatic int x509_get_crl_ext(unsigned char **p,\n                            const unsigned char *end,\n                            mbedtls_x509_buf *ext)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (*p == end) {\n        return 0;\n    }\n\n    /*\n     * crlExtensions           [0]  EXPLICIT Extensions OPTIONAL\n     *                              -- if present, version MUST be v2\n     */\n    if ((ret = mbedtls_x509_get_ext(p, end, ext, 0)) != 0) {\n        return ret;\n    }\n\n    end = ext->p + ext->len;\n\n    while (*p < end) {\n        /*\n         * Extension  ::=  SEQUENCE  {\n         *      extnID      OBJECT IDENTIFIER,\n         *      critical    BOOLEAN DEFAULT FALSE,\n         *      extnValue   OCTET STRING  }\n         */\n        int is_critical = 0;\n        const unsigned char *end_ext_data;\n        size_t len;\n\n        /* Get enclosing sequence tag */\n        if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        end_ext_data = *p + len;\n\n        /* Get OID (currently ignored) */\n        if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,\n                                        MBEDTLS_ASN1_OID)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n        *p += len;\n\n        /* Get optional critical */\n        if ((ret = mbedtls_asn1_get_bool(p, end_ext_data,\n                                         &is_critical)) != 0 &&\n            (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        /* Data should be octet string type */\n        if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,\n                                        MBEDTLS_ASN1_OCTET_STRING)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        /* Ignore data so far and just check its length */\n        *p += len;\n        if (*p != end_ext_data) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n        }\n\n        /* Abort on (unsupported) critical extensions */\n        if (is_critical) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                     MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);\n        }\n    }\n\n    if (*p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n/*\n * X.509 CRL v2 entry extensions (no extensions parsed yet.)\n */\nstatic int x509_get_crl_entry_ext(unsigned char **p,\n                                  const unsigned char *end,\n                                  mbedtls_x509_buf *ext)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n\n    /* OPTIONAL */\n    if (end <= *p) {\n        return 0;\n    }\n\n    ext->tag = **p;\n    ext->p = *p;\n\n    /*\n     * Get CRL-entry extension sequence header\n     * crlEntryExtensions      Extensions OPTIONAL  -- if present, MUST be v2\n     */\n    if ((ret = mbedtls_asn1_get_tag(p, end, &ext->len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n            ext->p = NULL;\n            return 0;\n        }\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    end = *p + ext->len;\n\n    if (end != *p + ext->len) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    while (*p < end) {\n        if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        *p += len;\n    }\n\n    if (*p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n/*\n * X.509 CRL Entries\n */\nstatic int x509_get_entries(unsigned char **p,\n                            const unsigned char *end,\n                            mbedtls_x509_crl_entry *entry)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t entry_len;\n    mbedtls_x509_crl_entry *cur_entry = entry;\n\n    if (*p == end) {\n        return 0;\n    }\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &entry_len,\n                                    MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {\n        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n            return 0;\n        }\n\n        return ret;\n    }\n\n    end = *p + entry_len;\n\n    while (*p < end) {\n        size_t len2;\n        const unsigned char *end2;\n\n        cur_entry->raw.tag = **p;\n        if ((ret = mbedtls_asn1_get_tag(p, end, &len2,\n                                        MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {\n            return ret;\n        }\n\n        cur_entry->raw.p = *p;\n        cur_entry->raw.len = len2;\n        end2 = *p + len2;\n\n        if ((ret = mbedtls_x509_get_serial(p, end2, &cur_entry->serial)) != 0) {\n            return ret;\n        }\n\n        if ((ret = mbedtls_x509_get_time(p, end2,\n                                         &cur_entry->revocation_date)) != 0) {\n            return ret;\n        }\n\n        if ((ret = x509_get_crl_entry_ext(p, end2,\n                                          &cur_entry->entry_ext)) != 0) {\n            return ret;\n        }\n\n        if (*p < end) {\n            cur_entry->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crl_entry));\n\n            if (cur_entry->next == NULL) {\n                return MBEDTLS_ERR_X509_ALLOC_FAILED;\n            }\n\n            cur_entry = cur_entry->next;\n        }\n    }\n\n    return 0;\n}\n\n/*\n * Parse one  CRLs in DER format and append it to the chained list\n */\nint mbedtls_x509_crl_parse_der(mbedtls_x509_crl *chain,\n                               const unsigned char *buf, size_t buflen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n    unsigned char *p = NULL, *end = NULL;\n    mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;\n    mbedtls_x509_crl *crl = chain;\n\n    /*\n     * Check for valid input\n     */\n    if (crl == NULL || buf == NULL) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    memset(&sig_params1, 0, sizeof(mbedtls_x509_buf));\n    memset(&sig_params2, 0, sizeof(mbedtls_x509_buf));\n    memset(&sig_oid2, 0, sizeof(mbedtls_x509_buf));\n\n    /*\n     * Add new CRL on the end of the chain if needed.\n     */\n    while (crl->version != 0 && crl->next != NULL) {\n        crl = crl->next;\n    }\n\n    if (crl->version != 0 && crl->next == NULL) {\n        crl->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crl));\n\n        if (crl->next == NULL) {\n            mbedtls_x509_crl_free(crl);\n            return MBEDTLS_ERR_X509_ALLOC_FAILED;\n        }\n\n        mbedtls_x509_crl_init(crl->next);\n        crl = crl->next;\n    }\n\n    /*\n     * Copy raw DER-encoded CRL\n     */\n    if (buflen == 0) {\n        return MBEDTLS_ERR_X509_INVALID_FORMAT;\n    }\n\n    p = mbedtls_calloc(1, buflen);\n    if (p == NULL) {\n        return MBEDTLS_ERR_X509_ALLOC_FAILED;\n    }\n\n    memcpy(p, buf, buflen);\n\n    crl->raw.p = p;\n    crl->raw.len = buflen;\n\n    end = p + buflen;\n\n    /*\n     * CertificateList  ::=  SEQUENCE  {\n     *      tbsCertList          TBSCertList,\n     *      signatureAlgorithm   AlgorithmIdentifier,\n     *      signatureValue       BIT STRING  }\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        mbedtls_x509_crl_free(crl);\n        return MBEDTLS_ERR_X509_INVALID_FORMAT;\n    }\n\n    if (len != (size_t) (end - p)) {\n        mbedtls_x509_crl_free(crl);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    /*\n     * TBSCertList  ::=  SEQUENCE  {\n     */\n    crl->tbs.p = p;\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        mbedtls_x509_crl_free(crl);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);\n    }\n\n    end = p + len;\n    crl->tbs.len = (size_t) (end - crl->tbs.p);\n\n    /*\n     * Version  ::=  INTEGER  OPTIONAL {  v1(0), v2(1)  }\n     *               -- if present, MUST be v2\n     *\n     * signature            AlgorithmIdentifier\n     */\n    if ((ret = x509_crl_get_version(&p, end, &crl->version)) != 0 ||\n        (ret = mbedtls_x509_get_alg(&p, end, &crl->sig_oid, &sig_params1)) != 0) {\n        mbedtls_x509_crl_free(crl);\n        return ret;\n    }\n\n    if (crl->version < 0 || crl->version > 1) {\n        mbedtls_x509_crl_free(crl);\n        return MBEDTLS_ERR_X509_UNKNOWN_VERSION;\n    }\n\n    crl->version++;\n\n    if ((ret = mbedtls_x509_get_sig_alg(&crl->sig_oid, &sig_params1,\n                                        &crl->sig_md, &crl->sig_pk,\n                                        &crl->sig_opts)) != 0) {\n        mbedtls_x509_crl_free(crl);\n        return MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG;\n    }\n\n    /*\n     * issuer               Name\n     */\n    crl->issuer_raw.p = p;\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        mbedtls_x509_crl_free(crl);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);\n    }\n\n    if ((ret = mbedtls_x509_get_name(&p, p + len, &crl->issuer)) != 0) {\n        mbedtls_x509_crl_free(crl);\n        return ret;\n    }\n\n    crl->issuer_raw.len = (size_t) (p - crl->issuer_raw.p);\n\n    /*\n     * thisUpdate          Time\n     * nextUpdate          Time OPTIONAL\n     */\n    if ((ret = mbedtls_x509_get_time(&p, end, &crl->this_update)) != 0) {\n        mbedtls_x509_crl_free(crl);\n        return ret;\n    }\n\n    if ((ret = mbedtls_x509_get_time(&p, end, &crl->next_update)) != 0) {\n        if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,\n                                      MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) &&\n            ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,\n                                      MBEDTLS_ERR_ASN1_OUT_OF_DATA))) {\n            mbedtls_x509_crl_free(crl);\n            return ret;\n        }\n    }\n\n    /*\n     * revokedCertificates    SEQUENCE OF SEQUENCE   {\n     *      userCertificate        CertificateSerialNumber,\n     *      revocationDate         Time,\n     *      crlEntryExtensions     Extensions OPTIONAL\n     *                                   -- if present, MUST be v2\n     *                        } OPTIONAL\n     */\n    if ((ret = x509_get_entries(&p, end, &crl->entry)) != 0) {\n        mbedtls_x509_crl_free(crl);\n        return ret;\n    }\n\n    /*\n     * crlExtensions          EXPLICIT Extensions OPTIONAL\n     *                              -- if present, MUST be v2\n     */\n    if (crl->version == 2) {\n        ret = x509_get_crl_ext(&p, end, &crl->crl_ext);\n\n        if (ret != 0) {\n            mbedtls_x509_crl_free(crl);\n            return ret;\n        }\n    }\n\n    if (p != end) {\n        mbedtls_x509_crl_free(crl);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    end = crl->raw.p + crl->raw.len;\n\n    /*\n     *  signatureAlgorithm   AlgorithmIdentifier,\n     *  signatureValue       BIT STRING\n     */\n    if ((ret = mbedtls_x509_get_alg(&p, end, &sig_oid2, &sig_params2)) != 0) {\n        mbedtls_x509_crl_free(crl);\n        return ret;\n    }\n\n    if (crl->sig_oid.len != sig_oid2.len ||\n        memcmp(crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len) != 0 ||\n        sig_params1.len != sig_params2.len ||\n        (sig_params1.len != 0 &&\n         memcmp(sig_params1.p, sig_params2.p, sig_params1.len) != 0)) {\n        mbedtls_x509_crl_free(crl);\n        return MBEDTLS_ERR_X509_SIG_MISMATCH;\n    }\n\n    if ((ret = mbedtls_x509_get_sig(&p, end, &crl->sig)) != 0) {\n        mbedtls_x509_crl_free(crl);\n        return ret;\n    }\n\n    if (p != end) {\n        mbedtls_x509_crl_free(crl);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n/*\n * Parse one or more CRLs and add them to the chained list\n */\nint mbedtls_x509_crl_parse(mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen)\n{\n#if defined(MBEDTLS_PEM_PARSE_C)\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t use_len = 0;\n    mbedtls_pem_context pem;\n    int is_pem = 0;\n\n    if (chain == NULL || buf == NULL) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    do {\n        mbedtls_pem_init(&pem);\n\n        // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated\n        // string\n        if (buflen == 0 || buf[buflen - 1] != '\\0') {\n            ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;\n        } else {\n            ret = mbedtls_pem_read_buffer(&pem,\n                                          \"-----BEGIN X509 CRL-----\",\n                                          \"-----END X509 CRL-----\",\n                                          buf, NULL, 0, &use_len);\n        }\n\n        if (ret == 0) {\n            /*\n             * Was PEM encoded\n             */\n            is_pem = 1;\n\n            buflen -= use_len;\n            buf += use_len;\n\n            if ((ret = mbedtls_x509_crl_parse_der(chain,\n                                                  pem.buf, pem.buflen)) != 0) {\n                mbedtls_pem_free(&pem);\n                return ret;\n            }\n        } else if (is_pem) {\n            mbedtls_pem_free(&pem);\n            return ret;\n        }\n\n        mbedtls_pem_free(&pem);\n    }\n    /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte.\n     * And a valid CRL cannot be less than 1 byte anyway. */\n    while (is_pem && buflen > 1);\n\n    if (is_pem) {\n        return 0;\n    } else\n#endif /* MBEDTLS_PEM_PARSE_C */\n    return mbedtls_x509_crl_parse_der(chain, buf, buflen);\n}\n\n#if defined(MBEDTLS_FS_IO)\n/*\n * Load one or more CRLs and add them to the chained list\n */\nint mbedtls_x509_crl_parse_file(mbedtls_x509_crl *chain, const char *path)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t n;\n    unsigned char *buf;\n\n    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_x509_crl_parse(chain, buf, n);\n\n    mbedtls_zeroize_and_free(buf, n);\n\n    return ret;\n}\n#endif /* MBEDTLS_FS_IO */\n\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\n/*\n * Return an informational string about the certificate.\n */\n#define BEFORE_COLON    14\n#define BC              \"14\"\n/*\n * Return an informational string about the CRL.\n */\nint mbedtls_x509_crl_info(char *buf, size_t size, const char *prefix,\n                          const mbedtls_x509_crl *crl)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t n;\n    char *p;\n    const mbedtls_x509_crl_entry *entry;\n\n    p = buf;\n    n = size;\n\n    ret = mbedtls_snprintf(p, n, \"%sCRL version   : %d\",\n                           prefix, crl->version);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    ret = mbedtls_snprintf(p, n, \"\\n%sissuer name   : \", prefix);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n    ret = mbedtls_x509_dn_gets(p, n, &crl->issuer);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    ret = mbedtls_snprintf(p, n, \"\\n%sthis update   : \" \\\n                                 \"%04d-%02d-%02d %02d:%02d:%02d\", prefix,\n                           crl->this_update.year, crl->this_update.mon,\n                           crl->this_update.day,  crl->this_update.hour,\n                           crl->this_update.min,  crl->this_update.sec);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    ret = mbedtls_snprintf(p, n, \"\\n%snext update   : \" \\\n                                 \"%04d-%02d-%02d %02d:%02d:%02d\", prefix,\n                           crl->next_update.year, crl->next_update.mon,\n                           crl->next_update.day,  crl->next_update.hour,\n                           crl->next_update.min,  crl->next_update.sec);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    entry = &crl->entry;\n\n    ret = mbedtls_snprintf(p, n, \"\\n%sRevoked certificates:\",\n                           prefix);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    while (entry != NULL && entry->raw.len != 0) {\n        ret = mbedtls_snprintf(p, n, \"\\n%sserial number: \",\n                               prefix);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        ret = mbedtls_x509_serial_gets(p, n, &entry->serial);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        ret = mbedtls_snprintf(p, n, \" revocation date: \" \\\n                                     \"%04d-%02d-%02d %02d:%02d:%02d\",\n                               entry->revocation_date.year, entry->revocation_date.mon,\n                               entry->revocation_date.day,  entry->revocation_date.hour,\n                               entry->revocation_date.min,  entry->revocation_date.sec);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        entry = entry->next;\n    }\n\n    ret = mbedtls_snprintf(p, n, \"\\n%ssigned using  : \", prefix);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    ret = mbedtls_x509_sig_alg_gets(p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md,\n                                    crl->sig_opts);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    ret = mbedtls_snprintf(p, n, \"\\n\");\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    return (int) (size - n);\n}\n#endif /* MBEDTLS_X509_REMOVE_INFO */\n\n/*\n * Initialize a CRL chain\n */\nvoid mbedtls_x509_crl_init(mbedtls_x509_crl *crl)\n{\n    memset(crl, 0, sizeof(mbedtls_x509_crl));\n}\n\n/*\n * Unallocate all CRL data\n */\nvoid mbedtls_x509_crl_free(mbedtls_x509_crl *crl)\n{\n    mbedtls_x509_crl *crl_cur = crl;\n    mbedtls_x509_crl *crl_prv;\n    mbedtls_x509_crl_entry *entry_cur;\n    mbedtls_x509_crl_entry *entry_prv;\n\n    while (crl_cur != NULL) {\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)\n        mbedtls_free(crl_cur->sig_opts);\n#endif\n\n        mbedtls_asn1_free_named_data_list_shallow(crl_cur->issuer.next);\n\n        entry_cur = crl_cur->entry.next;\n        while (entry_cur != NULL) {\n            entry_prv = entry_cur;\n            entry_cur = entry_cur->next;\n            mbedtls_zeroize_and_free(entry_prv,\n                                     sizeof(mbedtls_x509_crl_entry));\n        }\n\n        if (crl_cur->raw.p != NULL) {\n            mbedtls_zeroize_and_free(crl_cur->raw.p, crl_cur->raw.len);\n        }\n\n        crl_prv = crl_cur;\n        crl_cur = crl_cur->next;\n\n        mbedtls_platform_zeroize(crl_prv, sizeof(mbedtls_x509_crl));\n        if (crl_prv != crl) {\n            mbedtls_free(crl_prv);\n        }\n    }\n}\n\n#endif /* MBEDTLS_X509_CRL_PARSE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/x509_crt.c",
    "content": "/*\n *  X.509 certificate parsing and verification\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  The ITU-T X.509 standard defines a certificate format for PKI.\n *\n *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)\n *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)\n *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)\n *\n *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf\n *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf\n *\n *  [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_X509_CRT_PARSE_C)\n\n#include \"mbedtls/x509_crt.h\"\n#include \"x509_internal.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/oid.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_PEM_PARSE_C)\n#include \"mbedtls/pem.h\"\n#endif\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"psa/crypto.h\"\n#include \"psa_util_internal.h\"\n#include \"mbedtls/psa_util.h\"\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n#include \"pk_internal.h\"\n\n#include \"mbedtls/platform.h\"\n\n#if defined(MBEDTLS_THREADING_C)\n#include \"mbedtls/threading.h\"\n#endif\n\n#if defined(MBEDTLS_HAVE_TIME)\n#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#include <windows.h>\n#else\n#include <time.h>\n#endif\n#endif\n\n#if defined(MBEDTLS_FS_IO)\n#include <stdio.h>\n#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32)\n#include <sys/types.h>\n#include <sys/stat.h>\n#if defined(__MBED__)\n#include <platform/mbed_retarget.h>\n#else\n#include <dirent.h>\n#endif /* __MBED__ */\n#include <errno.h>\n#endif /* !_WIN32 || EFIX64 || EFI32 */\n#endif\n\n/*\n * Item in a verification chain: cert and flags for it\n */\ntypedef struct {\n    mbedtls_x509_crt *crt;\n    uint32_t flags;\n} x509_crt_verify_chain_item;\n\n/*\n * Max size of verification chain: end-entity + intermediates + trusted root\n */\n#define X509_MAX_VERIFY_CHAIN_SIZE    (MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2)\n\n/* Default profile. Do not remove items unless there are serious security\n * concerns. */\nconst mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =\n{\n    /* Hashes from SHA-256 and above. Note that this selection\n     * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),\n    0xFFFFFFF, /* Any PK alg    */\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    /* Curves at or above 128-bit security level. Note that this selection\n     * should be aligned with ssl_preset_default_curves in ssl_tls.c. */\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) |\n    0,\n#else /* MBEDTLS_PK_HAVE_ECC_KEYS */\n    0,\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n    2048,\n};\n\n/* Next-generation profile. Currently identical to the default, but may\n * be tightened at any time. */\nconst mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next =\n{\n    /* Hashes from SHA-256 and above. */\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),\n    0xFFFFFFF, /* Any PK alg    */\n#if defined(MBEDTLS_ECP_C)\n    /* Curves at or above 128-bit security level. */\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256K1),\n#else\n    0,\n#endif\n    2048,\n};\n\n/*\n * NSA Suite B Profile\n */\nconst mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =\n{\n    /* Only SHA-256 and 384 */\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384),\n    /* Only ECDSA */\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY),\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    /* Only NIST P-256 and P-384 */\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) |\n    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1),\n#else /* MBEDTLS_PK_HAVE_ECC_KEYS */\n    0,\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n    0,\n};\n\n/*\n * Empty / all-forbidden profile\n */\nconst mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none =\n{\n    0,\n    0,\n    0,\n    (uint32_t) -1,\n};\n\n/*\n * Check md_alg against profile\n * Return 0 if md_alg is acceptable for this profile, -1 otherwise\n */\nstatic int x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile,\n                                     mbedtls_md_type_t md_alg)\n{\n    if (md_alg == MBEDTLS_MD_NONE) {\n        return -1;\n    }\n\n    if ((profile->allowed_mds & MBEDTLS_X509_ID_FLAG(md_alg)) != 0) {\n        return 0;\n    }\n\n    return -1;\n}\n\n/*\n * Check pk_alg against profile\n * Return 0 if pk_alg is acceptable for this profile, -1 otherwise\n */\nstatic int x509_profile_check_pk_alg(const mbedtls_x509_crt_profile *profile,\n                                     mbedtls_pk_type_t pk_alg)\n{\n    if (pk_alg == MBEDTLS_PK_NONE) {\n        return -1;\n    }\n\n    if ((profile->allowed_pks & MBEDTLS_X509_ID_FLAG(pk_alg)) != 0) {\n        return 0;\n    }\n\n    return -1;\n}\n\n/*\n * Check key against profile\n * Return 0 if pk is acceptable for this profile, -1 otherwise\n */\nstatic int x509_profile_check_key(const mbedtls_x509_crt_profile *profile,\n                                  const mbedtls_pk_context *pk)\n{\n    const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type(pk);\n\n#if defined(MBEDTLS_RSA_C)\n    if (pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS) {\n        if (mbedtls_pk_get_bitlen(pk) >= profile->rsa_min_bitlen) {\n            return 0;\n        }\n\n        return -1;\n    }\n#endif /* MBEDTLS_RSA_C */\n\n#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)\n    if (pk_alg == MBEDTLS_PK_ECDSA ||\n        pk_alg == MBEDTLS_PK_ECKEY ||\n        pk_alg == MBEDTLS_PK_ECKEY_DH) {\n        const mbedtls_ecp_group_id gid = mbedtls_pk_get_ec_group_id(pk);\n\n        if (gid == MBEDTLS_ECP_DP_NONE) {\n            return -1;\n        }\n\n        if ((profile->allowed_curves & MBEDTLS_X509_ID_FLAG(gid)) != 0) {\n            return 0;\n        }\n\n        return -1;\n    }\n#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */\n\n    return -1;\n}\n\n/*\n * Like memcmp, but case-insensitive and always returns -1 if different\n */\nstatic int x509_memcasecmp(const void *s1, const void *s2, size_t len)\n{\n    size_t i;\n    unsigned char diff;\n    const unsigned char *n1 = s1, *n2 = s2;\n\n    for (i = 0; i < len; i++) {\n        diff = n1[i] ^ n2[i];\n\n        if (diff == 0) {\n            continue;\n        }\n\n        if (diff == 32 &&\n            ((n1[i] >= 'a' && n1[i] <= 'z') ||\n             (n1[i] >= 'A' && n1[i] <= 'Z'))) {\n            continue;\n        }\n\n        return -1;\n    }\n\n    return 0;\n}\n\n/*\n * Return 0 if name matches wildcard, -1 otherwise\n */\nstatic int x509_check_wildcard(const char *cn, const mbedtls_x509_buf *name)\n{\n    size_t i;\n    size_t cn_idx = 0, cn_len = strlen(cn);\n\n    /* We can't have a match if there is no wildcard to match */\n    if (name->len < 3 || name->p[0] != '*' || name->p[1] != '.') {\n        return -1;\n    }\n\n    for (i = 0; i < cn_len; ++i) {\n        if (cn[i] == '.') {\n            cn_idx = i;\n            break;\n        }\n    }\n\n    if (cn_idx == 0) {\n        return -1;\n    }\n\n    if (cn_len - cn_idx == name->len - 1 &&\n        x509_memcasecmp(name->p + 1, cn + cn_idx, name->len - 1) == 0) {\n        return 0;\n    }\n\n    return -1;\n}\n\n/*\n * Compare two X.509 strings, case-insensitive, and allowing for some encoding\n * variations (but not all).\n *\n * Return 0 if equal, -1 otherwise.\n */\nstatic int x509_string_cmp(const mbedtls_x509_buf *a, const mbedtls_x509_buf *b)\n{\n    if (a->tag == b->tag &&\n        a->len == b->len &&\n        memcmp(a->p, b->p, b->len) == 0) {\n        return 0;\n    }\n\n    if ((a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING) &&\n        (b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING) &&\n        a->len == b->len &&\n        x509_memcasecmp(a->p, b->p, b->len) == 0) {\n        return 0;\n    }\n\n    return -1;\n}\n\n/*\n * Compare two X.509 Names (aka rdnSequence).\n *\n * See RFC 5280 section 7.1, though we don't implement the whole algorithm:\n * we sometimes return unequal when the full algorithm would return equal,\n * but never the other way. (In particular, we don't do Unicode normalisation\n * or space folding.)\n *\n * Return 0 if equal, -1 otherwise.\n */\nstatic int x509_name_cmp(const mbedtls_x509_name *a, const mbedtls_x509_name *b)\n{\n    /* Avoid recursion, it might not be optimised by the compiler */\n    while (a != NULL || b != NULL) {\n        if (a == NULL || b == NULL) {\n            return -1;\n        }\n\n        /* type */\n        if (a->oid.tag != b->oid.tag ||\n            a->oid.len != b->oid.len ||\n            memcmp(a->oid.p, b->oid.p, b->oid.len) != 0) {\n            return -1;\n        }\n\n        /* value */\n        if (x509_string_cmp(&a->val, &b->val) != 0) {\n            return -1;\n        }\n\n        /* structure of the list of sets */\n        if (a->next_merged != b->next_merged) {\n            return -1;\n        }\n\n        a = a->next;\n        b = b->next;\n    }\n\n    /* a == NULL == b */\n    return 0;\n}\n\n/*\n * Reset (init or clear) a verify_chain\n */\nstatic void x509_crt_verify_chain_reset(\n    mbedtls_x509_crt_verify_chain *ver_chain)\n{\n    size_t i;\n\n    for (i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++) {\n        ver_chain->items[i].crt = NULL;\n        ver_chain->items[i].flags = (uint32_t) -1;\n    }\n\n    ver_chain->len = 0;\n\n#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)\n    ver_chain->trust_ca_cb_result = NULL;\n#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */\n}\n\n/*\n *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }\n */\nstatic int x509_get_version(unsigned char **p,\n                            const unsigned char *end,\n                            int *ver)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |\n                                    0)) != 0) {\n        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n            *ver = 0;\n            return 0;\n        }\n\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);\n    }\n\n    end = *p + len;\n\n    if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret);\n    }\n\n    if (*p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n/*\n *  Validity ::= SEQUENCE {\n *       notBefore      Time,\n *       notAfter       Time }\n */\nstatic int x509_get_dates(unsigned char **p,\n                          const unsigned char *end,\n                          mbedtls_x509_time *from,\n                          mbedtls_x509_time *to)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret);\n    }\n\n    end = *p + len;\n\n    if ((ret = mbedtls_x509_get_time(p, end, from)) != 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_x509_get_time(p, end, to)) != 0) {\n        return ret;\n    }\n\n    if (*p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n/*\n * X.509 v2/v3 unique identifier (not parsed)\n */\nstatic int x509_get_uid(unsigned char **p,\n                        const unsigned char *end,\n                        mbedtls_x509_buf *uid, int n)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if (*p == end) {\n        return 0;\n    }\n\n    uid->tag = **p;\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &uid->len,\n                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |\n                                    n)) != 0) {\n        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n            return 0;\n        }\n\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);\n    }\n\n    uid->p = *p;\n    *p += uid->len;\n\n    return 0;\n}\n\nstatic int x509_get_basic_constraints(unsigned char **p,\n                                      const unsigned char *end,\n                                      int *ca_istrue,\n                                      int *max_pathlen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n\n    /*\n     * BasicConstraints ::= SEQUENCE {\n     *      cA                      BOOLEAN DEFAULT FALSE,\n     *      pathLenConstraint       INTEGER (0..MAX) OPTIONAL }\n     */\n    *ca_istrue = 0; /* DEFAULT FALSE */\n    *max_pathlen = 0; /* endless */\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    if (*p == end) {\n        return 0;\n    }\n\n    if ((ret = mbedtls_asn1_get_bool(p, end, ca_istrue)) != 0) {\n        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n            ret = mbedtls_asn1_get_int(p, end, ca_istrue);\n        }\n\n        if (ret != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        if (*ca_istrue != 0) {\n            *ca_istrue = 1;\n        }\n    }\n\n    if (*p == end) {\n        return 0;\n    }\n\n    if ((ret = mbedtls_asn1_get_int(p, end, max_pathlen)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    if (*p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer\n     * overflow, which is an undefined behavior. */\n    if (*max_pathlen == INT_MAX) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_INVALID_LENGTH);\n    }\n\n    (*max_pathlen)++;\n\n    return 0;\n}\n\n/*\n * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId\n *\n * KeyPurposeId ::= OBJECT IDENTIFIER\n */\nstatic int x509_get_ext_key_usage(unsigned char **p,\n                                  const unsigned char *end,\n                                  mbedtls_x509_sequence *ext_key_usage)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if ((ret = mbedtls_asn1_get_sequence_of(p, end, ext_key_usage, MBEDTLS_ASN1_OID)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    /* Sequence length must be >= 1 */\n    if (ext_key_usage->buf.p == NULL) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_INVALID_LENGTH);\n    }\n\n    return 0;\n}\n\n/*\n * SubjectKeyIdentifier ::= KeyIdentifier\n *\n * KeyIdentifier ::= OCTET STRING\n */\nstatic int x509_get_subject_key_id(unsigned char **p,\n                                   const unsigned char *end,\n                                   mbedtls_x509_buf *subject_key_id)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0u;\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                    MBEDTLS_ASN1_OCTET_STRING)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    subject_key_id->len = len;\n    subject_key_id->tag = MBEDTLS_ASN1_OCTET_STRING;\n    subject_key_id->p = *p;\n    *p += len;\n\n    if (*p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n/*\n * AuthorityKeyIdentifier ::= SEQUENCE {\n *        keyIdentifier [0] KeyIdentifier OPTIONAL,\n *        authorityCertIssuer [1] GeneralNames OPTIONAL,\n *        authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }\n *\n *    KeyIdentifier ::= OCTET STRING\n */\nstatic int x509_get_authority_key_id(unsigned char **p,\n                                     unsigned char *end,\n                                     mbedtls_x509_authority *authority_key_id)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0u;\n\n    if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    if (*p + len != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    ret = mbedtls_asn1_get_tag(p, end, &len,\n                               MBEDTLS_ASN1_CONTEXT_SPECIFIC);\n\n    /* KeyIdentifier is an OPTIONAL field */\n    if (ret == 0) {\n        authority_key_id->keyIdentifier.len = len;\n        authority_key_id->keyIdentifier.p = *p;\n        /* Setting tag of the keyIdentfier intentionally to 0x04.\n         * Although the .keyIdentfier field is CONTEXT_SPECIFIC ([0] OPTIONAL),\n         * its tag with the content is the payload of on OCTET STRING primitive */\n        authority_key_id->keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING;\n\n        *p += len;\n    } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    if (*p < end) {\n        /* Getting authorityCertIssuer using the required specific class tag [1] */\n        if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                        MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |\n                                        1)) != 0) {\n            /* authorityCertIssuer and authorityCertSerialNumber MUST both\n               be present or both be absent. At this point we expect to have both. */\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n        /* \"end\" also includes the CertSerialNumber field so \"len\" shall be used */\n        ret = mbedtls_x509_get_subject_alt_name_ext(p,\n                                                    (*p+len),\n                                                    &authority_key_id->authorityCertIssuer);\n        if (ret != 0) {\n            return ret;\n        }\n\n        /* Getting authorityCertSerialNumber using the required specific class tag [2] */\n        if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                        MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n        authority_key_id->authorityCertSerialNumber.len = len;\n        authority_key_id->authorityCertSerialNumber.p = *p;\n        authority_key_id->authorityCertSerialNumber.tag = MBEDTLS_ASN1_INTEGER;\n        *p += len;\n    }\n\n    if (*p != end) {\n        return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +\n               MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;\n    }\n\n    return 0;\n}\n\n/*\n * id-ce-certificatePolicies OBJECT IDENTIFIER ::=  { id-ce 32 }\n *\n * anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 }\n *\n * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation\n *\n * PolicyInformation ::= SEQUENCE {\n *     policyIdentifier   CertPolicyId,\n *     policyQualifiers   SEQUENCE SIZE (1..MAX) OF\n *                             PolicyQualifierInfo OPTIONAL }\n *\n * CertPolicyId ::= OBJECT IDENTIFIER\n *\n * PolicyQualifierInfo ::= SEQUENCE {\n *      policyQualifierId  PolicyQualifierId,\n *      qualifier          ANY DEFINED BY policyQualifierId }\n *\n * -- policyQualifierIds for Internet policy qualifiers\n *\n * id-qt          OBJECT IDENTIFIER ::=  { id-pkix 2 }\n * id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }\n * id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }\n *\n * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )\n *\n * Qualifier ::= CHOICE {\n *      cPSuri           CPSuri,\n *      userNotice       UserNotice }\n *\n * CPSuri ::= IA5String\n *\n * UserNotice ::= SEQUENCE {\n *      noticeRef        NoticeReference OPTIONAL,\n *      explicitText     DisplayText OPTIONAL }\n *\n * NoticeReference ::= SEQUENCE {\n *      organization     DisplayText,\n *      noticeNumbers    SEQUENCE OF INTEGER }\n *\n * DisplayText ::= CHOICE {\n *      ia5String        IA5String      (SIZE (1..200)),\n *      visibleString    VisibleString  (SIZE (1..200)),\n *      bmpString        BMPString      (SIZE (1..200)),\n *      utf8String       UTF8String     (SIZE (1..200)) }\n *\n * NOTE: we only parse and use anyPolicy without qualifiers at this point\n * as defined in RFC 5280.\n */\nstatic int x509_get_certificate_policies(unsigned char **p,\n                                         const unsigned char *end,\n                                         mbedtls_x509_sequence *certificate_policies)\n{\n    int ret, parse_ret = 0;\n    size_t len;\n    mbedtls_asn1_buf *buf;\n    mbedtls_asn1_sequence *cur = certificate_policies;\n\n    /* Get main sequence tag */\n    ret = mbedtls_asn1_get_tag(p, end, &len,\n                               MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);\n    if (ret != 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n    }\n\n    if (*p + len != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    /*\n     * Cannot be an empty sequence.\n     */\n    if (len == 0) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    while (*p < end) {\n        mbedtls_x509_buf policy_oid;\n        const unsigned char *policy_end;\n\n        /*\n         * Get the policy sequence\n         */\n        if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        policy_end = *p + len;\n\n        if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len,\n                                        MBEDTLS_ASN1_OID)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        policy_oid.tag = MBEDTLS_ASN1_OID;\n        policy_oid.len = len;\n        policy_oid.p = *p;\n\n        /*\n         * Only AnyPolicy is currently supported when enforcing policy.\n         */\n        if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_POLICY, &policy_oid) != 0) {\n            /*\n             * Set the parsing return code but continue parsing, in case this\n             * extension is critical.\n             */\n            parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;\n        }\n\n        /* Allocate and assign next pointer */\n        if (cur->buf.p != NULL) {\n            if (cur->next != NULL) {\n                return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;\n            }\n\n            cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));\n\n            if (cur->next == NULL) {\n                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                         MBEDTLS_ERR_ASN1_ALLOC_FAILED);\n            }\n\n            cur = cur->next;\n        }\n\n        buf = &(cur->buf);\n        buf->tag = policy_oid.tag;\n        buf->p = policy_oid.p;\n        buf->len = policy_oid.len;\n\n        *p += len;\n\n        /*\n         * If there is an optional qualifier, then *p < policy_end\n         * Check the Qualifier len to verify it doesn't exceed policy_end.\n         */\n        if (*p < policy_end) {\n            if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len,\n                                            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) !=\n                0) {\n                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n            }\n            /*\n             * Skip the optional policy qualifiers.\n             */\n            *p += len;\n        }\n\n        if (*p != policy_end) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n        }\n    }\n\n    /* Set final sequence entry's next pointer to NULL */\n    cur->next = NULL;\n\n    if (*p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return parse_ret;\n}\n\n/*\n * X.509 v3 extensions\n *\n */\nstatic int x509_get_crt_ext(unsigned char **p,\n                            const unsigned char *end,\n                            mbedtls_x509_crt *crt,\n                            mbedtls_x509_crt_ext_cb_t cb,\n                            void *p_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n    unsigned char *end_ext_data, *start_ext_octet, *end_ext_octet;\n\n    if (*p == end) {\n        return 0;\n    }\n\n    if ((ret = mbedtls_x509_get_ext(p, end, &crt->v3_ext, 3)) != 0) {\n        return ret;\n    }\n\n    end = crt->v3_ext.p + crt->v3_ext.len;\n    while (*p < end) {\n        /*\n         * Extension  ::=  SEQUENCE  {\n         *      extnID      OBJECT IDENTIFIER,\n         *      critical    BOOLEAN DEFAULT FALSE,\n         *      extnValue   OCTET STRING  }\n         */\n        mbedtls_x509_buf extn_oid = { 0, 0, NULL };\n        int is_critical = 0; /* DEFAULT FALSE */\n        int ext_type = 0;\n\n        if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        end_ext_data = *p + len;\n\n        /* Get extension ID */\n        if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len,\n                                        MBEDTLS_ASN1_OID)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        extn_oid.tag = MBEDTLS_ASN1_OID;\n        extn_oid.p = *p;\n        *p += extn_oid.len;\n\n        /* Get optional critical */\n        if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 &&\n            (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        /* Data should be octet string type */\n        if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,\n                                        MBEDTLS_ASN1_OCTET_STRING)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        start_ext_octet = *p;\n        end_ext_octet = *p + len;\n\n        if (end_ext_octet != end_ext_data) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n        }\n\n        /*\n         * Detect supported extensions\n         */\n        ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type);\n\n        if (ret != 0) {\n            /* Give the callback (if any) a chance to handle the extension */\n            if (cb != NULL) {\n                ret = cb(p_ctx, crt, &extn_oid, is_critical, *p, end_ext_octet);\n                if (ret != 0 && is_critical) {\n                    return ret;\n                }\n                *p = end_ext_octet;\n                continue;\n            }\n\n            /* No parser found, skip extension */\n            *p = end_ext_octet;\n\n            if (is_critical) {\n                /* Data is marked as critical: fail */\n                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                         MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);\n            }\n            continue;\n        }\n\n        /* Forbid repeated extensions */\n        if ((crt->ext_types & ext_type) != 0) {\n            return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;\n        }\n\n        crt->ext_types |= ext_type;\n\n        switch (ext_type) {\n            case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS:\n                /* Parse basic constraints */\n                if ((ret = x509_get_basic_constraints(p, end_ext_octet,\n                                                      &crt->ca_istrue, &crt->max_pathlen)) != 0) {\n                    return ret;\n                }\n                break;\n\n            case MBEDTLS_X509_EXT_KEY_USAGE:\n                /* Parse key usage */\n                if ((ret = mbedtls_x509_get_key_usage(p, end_ext_octet,\n                                                      &crt->key_usage)) != 0) {\n                    return ret;\n                }\n                break;\n\n            case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE:\n                /* Parse extended key usage */\n                if ((ret = x509_get_ext_key_usage(p, end_ext_octet,\n                                                  &crt->ext_key_usage)) != 0) {\n                    return ret;\n                }\n                break;\n\n            case MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER:\n                /* Parse subject key identifier */\n                if ((ret = x509_get_subject_key_id(p, end_ext_data,\n                                                   &crt->subject_key_id)) != 0) {\n                    return ret;\n                }\n                break;\n\n            case MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER:\n                /* Parse authority key identifier */\n                if ((ret = x509_get_authority_key_id(p, end_ext_octet,\n                                                     &crt->authority_key_id)) != 0) {\n                    return ret;\n                }\n                break;\n            case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:\n                /* Parse subject alt name\n                 * SubjectAltName ::= GeneralNames\n                 */\n                if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_octet,\n                                                             &crt->subject_alt_names)) != 0) {\n                    return ret;\n                }\n                break;\n\n            case MBEDTLS_X509_EXT_NS_CERT_TYPE:\n                /* Parse netscape certificate type */\n                if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_octet,\n                                                         &crt->ns_cert_type)) != 0) {\n                    return ret;\n                }\n                break;\n\n            case MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES:\n                /* Parse certificate policies type */\n                if ((ret = x509_get_certificate_policies(p, end_ext_octet,\n                                                         &crt->certificate_policies)) != 0) {\n                    /* Give the callback (if any) a chance to handle the extension\n                     * if it contains unsupported policies */\n                    if (ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE && cb != NULL &&\n                        cb(p_ctx, crt, &extn_oid, is_critical,\n                           start_ext_octet, end_ext_octet) == 0) {\n                        break;\n                    }\n\n                    if (is_critical) {\n                        return ret;\n                    } else\n                    /*\n                     * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we\n                     * cannot interpret or enforce the policy. However, it is up to\n                     * the user to choose how to enforce the policies,\n                     * unless the extension is critical.\n                     */\n                    if (ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {\n                        return ret;\n                    }\n                }\n                break;\n\n            default:\n                /*\n                 * If this is a non-critical extension, which the oid layer\n                 * supports, but there isn't an x509 parser for it,\n                 * skip the extension.\n                 */\n                if (is_critical) {\n                    return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;\n                } else {\n                    *p = end_ext_octet;\n                }\n        }\n    }\n\n    if (*p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n/*\n * Parse and fill a single X.509 certificate in DER format\n */\nstatic int x509_crt_parse_der_core(mbedtls_x509_crt *crt,\n                                   const unsigned char *buf,\n                                   size_t buflen,\n                                   int make_copy,\n                                   mbedtls_x509_crt_ext_cb_t cb,\n                                   void *p_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n    unsigned char *p, *end, *crt_end;\n    mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;\n\n    memset(&sig_params1, 0, sizeof(mbedtls_x509_buf));\n    memset(&sig_params2, 0, sizeof(mbedtls_x509_buf));\n    memset(&sig_oid2, 0, sizeof(mbedtls_x509_buf));\n\n    /*\n     * Check for valid input\n     */\n    if (crt == NULL || buf == NULL) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    /* Use the original buffer until we figure out actual length. */\n    p = (unsigned char *) buf;\n    len = buflen;\n    end = p + len;\n\n    /*\n     * Certificate  ::=  SEQUENCE  {\n     *      tbsCertificate       TBSCertificate,\n     *      signatureAlgorithm   AlgorithmIdentifier,\n     *      signatureValue       BIT STRING  }\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        mbedtls_x509_crt_free(crt);\n        return MBEDTLS_ERR_X509_INVALID_FORMAT;\n    }\n\n    end = crt_end = p + len;\n    crt->raw.len = (size_t) (crt_end - buf);\n    if (make_copy != 0) {\n        /* Create and populate a new buffer for the raw field. */\n        crt->raw.p = p = mbedtls_calloc(1, crt->raw.len);\n        if (crt->raw.p == NULL) {\n            return MBEDTLS_ERR_X509_ALLOC_FAILED;\n        }\n\n        memcpy(crt->raw.p, buf, crt->raw.len);\n        crt->own_buffer = 1;\n\n        p += crt->raw.len - len;\n        end = crt_end = p + len;\n    } else {\n        crt->raw.p = (unsigned char *) buf;\n        crt->own_buffer = 0;\n    }\n\n    /*\n     * TBSCertificate  ::=  SEQUENCE  {\n     */\n    crt->tbs.p = p;\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        mbedtls_x509_crt_free(crt);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);\n    }\n\n    end = p + len;\n    crt->tbs.len = (size_t) (end - crt->tbs.p);\n\n    /*\n     * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }\n     *\n     * CertificateSerialNumber  ::=  INTEGER\n     *\n     * signature            AlgorithmIdentifier\n     */\n    if ((ret = x509_get_version(&p, end, &crt->version)) != 0 ||\n        (ret = mbedtls_x509_get_serial(&p, end, &crt->serial)) != 0 ||\n        (ret = mbedtls_x509_get_alg(&p, end, &crt->sig_oid,\n                                    &sig_params1)) != 0) {\n        mbedtls_x509_crt_free(crt);\n        return ret;\n    }\n\n    if (crt->version < 0 || crt->version > 2) {\n        mbedtls_x509_crt_free(crt);\n        return MBEDTLS_ERR_X509_UNKNOWN_VERSION;\n    }\n\n    crt->version++;\n\n    if ((ret = mbedtls_x509_get_sig_alg(&crt->sig_oid, &sig_params1,\n                                        &crt->sig_md, &crt->sig_pk,\n                                        &crt->sig_opts)) != 0) {\n        mbedtls_x509_crt_free(crt);\n        return ret;\n    }\n\n    /*\n     * issuer               Name\n     */\n    crt->issuer_raw.p = p;\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        mbedtls_x509_crt_free(crt);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);\n    }\n\n    if ((ret = mbedtls_x509_get_name(&p, p + len, &crt->issuer)) != 0) {\n        mbedtls_x509_crt_free(crt);\n        return ret;\n    }\n\n    crt->issuer_raw.len = (size_t) (p - crt->issuer_raw.p);\n\n    /*\n     * Validity ::= SEQUENCE {\n     *      notBefore      Time,\n     *      notAfter       Time }\n     *\n     */\n    if ((ret = x509_get_dates(&p, end, &crt->valid_from,\n                              &crt->valid_to)) != 0) {\n        mbedtls_x509_crt_free(crt);\n        return ret;\n    }\n\n    /*\n     * subject              Name\n     */\n    crt->subject_raw.p = p;\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        mbedtls_x509_crt_free(crt);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);\n    }\n\n    if (len && (ret = mbedtls_x509_get_name(&p, p + len, &crt->subject)) != 0) {\n        mbedtls_x509_crt_free(crt);\n        return ret;\n    }\n\n    crt->subject_raw.len = (size_t) (p - crt->subject_raw.p);\n\n    /*\n     * SubjectPublicKeyInfo\n     */\n    crt->pk_raw.p = p;\n    if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &crt->pk)) != 0) {\n        mbedtls_x509_crt_free(crt);\n        return ret;\n    }\n    crt->pk_raw.len = (size_t) (p - crt->pk_raw.p);\n\n    /*\n     *  issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,\n     *                       -- If present, version shall be v2 or v3\n     *  subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,\n     *                       -- If present, version shall be v2 or v3\n     *  extensions      [3]  EXPLICIT Extensions OPTIONAL\n     *                       -- If present, version shall be v3\n     */\n    if (crt->version == 2 || crt->version == 3) {\n        ret = x509_get_uid(&p, end, &crt->issuer_id,  1);\n        if (ret != 0) {\n            mbedtls_x509_crt_free(crt);\n            return ret;\n        }\n    }\n\n    if (crt->version == 2 || crt->version == 3) {\n        ret = x509_get_uid(&p, end, &crt->subject_id,  2);\n        if (ret != 0) {\n            mbedtls_x509_crt_free(crt);\n            return ret;\n        }\n    }\n\n    if (crt->version == 3) {\n        ret = x509_get_crt_ext(&p, end, crt, cb, p_ctx);\n        if (ret != 0) {\n            mbedtls_x509_crt_free(crt);\n            return ret;\n        }\n    }\n\n    if (p != end) {\n        mbedtls_x509_crt_free(crt);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    end = crt_end;\n\n    /*\n     *  }\n     *  -- end of TBSCertificate\n     *\n     *  signatureAlgorithm   AlgorithmIdentifier,\n     *  signatureValue       BIT STRING\n     */\n    if ((ret = mbedtls_x509_get_alg(&p, end, &sig_oid2, &sig_params2)) != 0) {\n        mbedtls_x509_crt_free(crt);\n        return ret;\n    }\n\n    if (crt->sig_oid.len != sig_oid2.len ||\n        memcmp(crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len) != 0 ||\n        sig_params1.tag != sig_params2.tag ||\n        sig_params1.len != sig_params2.len ||\n        (sig_params1.len != 0 &&\n         memcmp(sig_params1.p, sig_params2.p, sig_params1.len) != 0)) {\n        mbedtls_x509_crt_free(crt);\n        return MBEDTLS_ERR_X509_SIG_MISMATCH;\n    }\n\n    if ((ret = mbedtls_x509_get_sig(&p, end, &crt->sig)) != 0) {\n        mbedtls_x509_crt_free(crt);\n        return ret;\n    }\n\n    if (p != end) {\n        mbedtls_x509_crt_free(crt);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n/*\n * Parse one X.509 certificate in DER format from a buffer and add them to a\n * chained list\n */\nstatic int mbedtls_x509_crt_parse_der_internal(mbedtls_x509_crt *chain,\n                                               const unsigned char *buf,\n                                               size_t buflen,\n                                               int make_copy,\n                                               mbedtls_x509_crt_ext_cb_t cb,\n                                               void *p_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_x509_crt *crt = chain, *prev = NULL;\n\n    /*\n     * Check for valid input\n     */\n    if (crt == NULL || buf == NULL) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    while (crt->version != 0 && crt->next != NULL) {\n        prev = crt;\n        crt = crt->next;\n    }\n\n    /*\n     * Add new certificate on the end of the chain if needed.\n     */\n    if (crt->version != 0 && crt->next == NULL) {\n        crt->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));\n\n        if (crt->next == NULL) {\n            return MBEDTLS_ERR_X509_ALLOC_FAILED;\n        }\n\n        prev = crt;\n        mbedtls_x509_crt_init(crt->next);\n        crt = crt->next;\n    }\n\n    ret = x509_crt_parse_der_core(crt, buf, buflen, make_copy, cb, p_ctx);\n    if (ret != 0) {\n        if (prev) {\n            prev->next = NULL;\n        }\n\n        if (crt != chain) {\n            mbedtls_free(crt);\n        }\n\n        return ret;\n    }\n\n    return 0;\n}\n\nint mbedtls_x509_crt_parse_der_nocopy(mbedtls_x509_crt *chain,\n                                      const unsigned char *buf,\n                                      size_t buflen)\n{\n    return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 0, NULL, NULL);\n}\n\nint mbedtls_x509_crt_parse_der_with_ext_cb(mbedtls_x509_crt *chain,\n                                           const unsigned char *buf,\n                                           size_t buflen,\n                                           int make_copy,\n                                           mbedtls_x509_crt_ext_cb_t cb,\n                                           void *p_ctx)\n{\n    return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, make_copy, cb, p_ctx);\n}\n\nint mbedtls_x509_crt_parse_der(mbedtls_x509_crt *chain,\n                               const unsigned char *buf,\n                               size_t buflen)\n{\n    return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 1, NULL, NULL);\n}\n\n/*\n * Parse one or more PEM certificates from a buffer and add them to the chained\n * list\n */\nint mbedtls_x509_crt_parse(mbedtls_x509_crt *chain,\n                           const unsigned char *buf,\n                           size_t buflen)\n{\n#if defined(MBEDTLS_PEM_PARSE_C)\n    int success = 0, first_error = 0, total_failed = 0;\n    int buf_format = MBEDTLS_X509_FORMAT_DER;\n#endif\n\n    /*\n     * Check for valid input\n     */\n    if (chain == NULL || buf == NULL) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    /*\n     * Determine buffer content. Buffer contains either one DER certificate or\n     * one or more PEM certificates.\n     */\n#if defined(MBEDTLS_PEM_PARSE_C)\n    if (buflen != 0 && buf[buflen - 1] == '\\0' &&\n        strstr((const char *) buf, \"-----BEGIN CERTIFICATE-----\") != NULL) {\n        buf_format = MBEDTLS_X509_FORMAT_PEM;\n    }\n\n    if (buf_format == MBEDTLS_X509_FORMAT_DER) {\n        return mbedtls_x509_crt_parse_der(chain, buf, buflen);\n    }\n#else\n    return mbedtls_x509_crt_parse_der(chain, buf, buflen);\n#endif\n\n#if defined(MBEDTLS_PEM_PARSE_C)\n    if (buf_format == MBEDTLS_X509_FORMAT_PEM) {\n        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n        mbedtls_pem_context pem;\n\n        /* 1 rather than 0 since the terminating NULL byte is counted in */\n        while (buflen > 1) {\n            size_t use_len;\n            mbedtls_pem_init(&pem);\n\n            /* If we get there, we know the string is null-terminated */\n            ret = mbedtls_pem_read_buffer(&pem,\n                                          \"-----BEGIN CERTIFICATE-----\",\n                                          \"-----END CERTIFICATE-----\",\n                                          buf, NULL, 0, &use_len);\n\n            if (ret == 0) {\n                /*\n                 * Was PEM encoded\n                 */\n                buflen -= use_len;\n                buf += use_len;\n            } else if (ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA) {\n                return ret;\n            } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {\n                mbedtls_pem_free(&pem);\n\n                /*\n                 * PEM header and footer were found\n                 */\n                buflen -= use_len;\n                buf += use_len;\n\n                if (first_error == 0) {\n                    first_error = ret;\n                }\n\n                total_failed++;\n                continue;\n            } else {\n                break;\n            }\n\n            ret = mbedtls_x509_crt_parse_der(chain, pem.buf, pem.buflen);\n\n            mbedtls_pem_free(&pem);\n\n            if (ret != 0) {\n                /*\n                 * Quit parsing on a memory error\n                 */\n                if (ret == MBEDTLS_ERR_X509_ALLOC_FAILED) {\n                    return ret;\n                }\n\n                if (first_error == 0) {\n                    first_error = ret;\n                }\n\n                total_failed++;\n                continue;\n            }\n\n            success = 1;\n        }\n    }\n\n    if (success) {\n        return total_failed;\n    } else if (first_error) {\n        return first_error;\n    } else {\n        return MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;\n    }\n#endif /* MBEDTLS_PEM_PARSE_C */\n}\n\n#if defined(MBEDTLS_FS_IO)\n/*\n * Load one or more certificates and add them to the chained list\n */\nint mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t n;\n    unsigned char *buf;\n\n    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_x509_crt_parse(chain, buf, n);\n\n    mbedtls_zeroize_and_free(buf, n);\n\n    return ret;\n}\n\nint mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path)\n{\n    int ret = 0;\n#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)\n    int w_ret;\n    WCHAR szDir[MAX_PATH];\n    char filename[MAX_PATH];\n    char *p;\n    size_t len = strlen(path);\n\n    WIN32_FIND_DATAW file_data;\n    HANDLE hFind;\n\n    if (len > MAX_PATH - 3) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    memset(szDir, 0, sizeof(szDir));\n    memset(filename, 0, MAX_PATH);\n    memcpy(filename, path, len);\n    filename[len++] = '\\\\';\n    p = filename + len;\n    filename[len++] = '*';\n\n    /*\n     * Note this function uses the code page CP_ACP which is the system default\n     * ANSI codepage. The input string is always described in BYTES and the\n     * output length is described in WCHARs.\n     */\n    w_ret = MultiByteToWideChar(CP_ACP, 0, filename, (int) len, szDir,\n                                MAX_PATH - 3);\n    if (w_ret == 0) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    hFind = FindFirstFileW(szDir, &file_data);\n    if (hFind == INVALID_HANDLE_VALUE) {\n        return MBEDTLS_ERR_X509_FILE_IO_ERROR;\n    }\n\n    len = MAX_PATH - len;\n    do {\n        memset(p, 0, len);\n\n        if (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {\n            continue;\n        }\n        w_ret = WideCharToMultiByte(CP_ACP, 0, file_data.cFileName,\n                                    -1, p, (int) len, NULL, NULL);\n        if (w_ret == 0) {\n            ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;\n            goto cleanup;\n        }\n\n        w_ret = mbedtls_x509_crt_parse_file(chain, filename);\n        if (w_ret < 0) {\n            ret++;\n        } else {\n            ret += w_ret;\n        }\n    } while (FindNextFileW(hFind, &file_data) != 0);\n\n    if (GetLastError() != ERROR_NO_MORE_FILES) {\n        ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;\n    }\n\ncleanup:\n    FindClose(hFind);\n#else /* _WIN32 */\n    int t_ret;\n    int snp_ret;\n    struct stat sb;\n    struct dirent *entry;\n    char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN];\n    DIR *dir = opendir(path);\n\n    if (dir == NULL) {\n        return MBEDTLS_ERR_X509_FILE_IO_ERROR;\n    }\n\n#if defined(MBEDTLS_THREADING_C)\n    if ((ret = mbedtls_mutex_lock(&mbedtls_threading_readdir_mutex)) != 0) {\n        closedir(dir);\n        return ret;\n    }\n#endif /* MBEDTLS_THREADING_C */\n\n    memset(&sb, 0, sizeof(sb));\n\n    while ((entry = readdir(dir)) != NULL) {\n        snp_ret = mbedtls_snprintf(entry_name, sizeof(entry_name),\n                                   \"%s/%s\", path, entry->d_name);\n\n        if (snp_ret < 0 || (size_t) snp_ret >= sizeof(entry_name)) {\n            ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;\n            goto cleanup;\n        } else if (stat(entry_name, &sb) == -1) {\n            if (errno == ENOENT) {\n                /* Broken symbolic link - ignore this entry.\n                    stat(2) will return this error for either (a) a dangling\n                    symlink or (b) a missing file.\n                    Given that we have just obtained the filename from readdir,\n                    assume that it does exist and therefore treat this as a\n                    dangling symlink. */\n                continue;\n            } else {\n                /* Some other file error; report the error. */\n                ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;\n                goto cleanup;\n            }\n        }\n\n        if (!S_ISREG(sb.st_mode)) {\n            continue;\n        }\n\n        // Ignore parse errors\n        //\n        t_ret = mbedtls_x509_crt_parse_file(chain, entry_name);\n        if (t_ret < 0) {\n            ret++;\n        } else {\n            ret += t_ret;\n        }\n    }\n\ncleanup:\n    closedir(dir);\n\n#if defined(MBEDTLS_THREADING_C)\n    if (mbedtls_mutex_unlock(&mbedtls_threading_readdir_mutex) != 0) {\n        ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;\n    }\n#endif /* MBEDTLS_THREADING_C */\n\n#endif /* _WIN32 */\n\n    return ret;\n}\n#endif /* MBEDTLS_FS_IO */\n\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\n#define PRINT_ITEM(i)                               \\\n    do {                                            \\\n        ret = mbedtls_snprintf(p, n, \"%s\" i, sep);  \\\n        MBEDTLS_X509_SAFE_SNPRINTF;                 \\\n        sep = \", \";                                 \\\n    } while (0)\n\n#define CERT_TYPE(type, name)          \\\n    do {                               \\\n        if (ns_cert_type & (type)) {   \\\n            PRINT_ITEM(name);          \\\n        }                              \\\n    } while (0)\n\n#define KEY_USAGE(code, name)      \\\n    do {                           \\\n        if (key_usage & (code)) {  \\\n            PRINT_ITEM(name);      \\\n        }                          \\\n    } while (0)\n\nstatic int x509_info_ext_key_usage(char **buf, size_t *size,\n                                   const mbedtls_x509_sequence *extended_key_usage)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const char *desc;\n    size_t n = *size;\n    char *p = *buf;\n    const mbedtls_x509_sequence *cur = extended_key_usage;\n    const char *sep = \"\";\n\n    while (cur != NULL) {\n        if (mbedtls_oid_get_extended_key_usage(&cur->buf, &desc) != 0) {\n            desc = \"???\";\n        }\n\n        ret = mbedtls_snprintf(p, n, \"%s%s\", sep, desc);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        sep = \", \";\n\n        cur = cur->next;\n    }\n\n    *size = n;\n    *buf = p;\n\n    return 0;\n}\n\nstatic int x509_info_cert_policies(char **buf, size_t *size,\n                                   const mbedtls_x509_sequence *certificate_policies)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const char *desc;\n    size_t n = *size;\n    char *p = *buf;\n    const mbedtls_x509_sequence *cur = certificate_policies;\n    const char *sep = \"\";\n\n    while (cur != NULL) {\n        if (mbedtls_oid_get_certificate_policies(&cur->buf, &desc) != 0) {\n            desc = \"???\";\n        }\n\n        ret = mbedtls_snprintf(p, n, \"%s%s\", sep, desc);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        sep = \", \";\n\n        cur = cur->next;\n    }\n\n    *size = n;\n    *buf = p;\n\n    return 0;\n}\n\n/*\n * Return an informational string about the certificate.\n */\n#define BEFORE_COLON    18\n#define BC              \"18\"\nint mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix,\n                          const mbedtls_x509_crt *crt)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t n;\n    char *p;\n    char key_size_str[BEFORE_COLON];\n\n    p = buf;\n    n = size;\n\n    if (NULL == crt) {\n        ret = mbedtls_snprintf(p, n, \"\\nCertificate is uninitialised!\\n\");\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        return (int) (size - n);\n    }\n\n    ret = mbedtls_snprintf(p, n, \"%scert. version     : %d\\n\",\n                           prefix, crt->version);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n    ret = mbedtls_snprintf(p, n, \"%sserial number     : \",\n                           prefix);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    ret = mbedtls_x509_serial_gets(p, n, &crt->serial);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    ret = mbedtls_snprintf(p, n, \"\\n%sissuer name       : \", prefix);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n    ret = mbedtls_x509_dn_gets(p, n, &crt->issuer);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    ret = mbedtls_snprintf(p, n, \"\\n%ssubject name      : \", prefix);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n    ret = mbedtls_x509_dn_gets(p, n, &crt->subject);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    ret = mbedtls_snprintf(p, n, \"\\n%sissued  on        : \" \\\n                                 \"%04d-%02d-%02d %02d:%02d:%02d\", prefix,\n                           crt->valid_from.year, crt->valid_from.mon,\n                           crt->valid_from.day,  crt->valid_from.hour,\n                           crt->valid_from.min,  crt->valid_from.sec);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    ret = mbedtls_snprintf(p, n, \"\\n%sexpires on        : \" \\\n                                 \"%04d-%02d-%02d %02d:%02d:%02d\", prefix,\n                           crt->valid_to.year, crt->valid_to.mon,\n                           crt->valid_to.day,  crt->valid_to.hour,\n                           crt->valid_to.min,  crt->valid_to.sec);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    ret = mbedtls_snprintf(p, n, \"\\n%ssigned using      : \", prefix);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    ret = mbedtls_x509_sig_alg_gets(p, n, &crt->sig_oid, crt->sig_pk,\n                                    crt->sig_md, crt->sig_opts);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    /* Key size */\n    if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON,\n                                            mbedtls_pk_get_name(&crt->pk))) != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_snprintf(p, n, \"\\n%s%-\" BC \"s: %d bits\", prefix, key_size_str,\n                           (int) mbedtls_pk_get_bitlen(&crt->pk));\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    /*\n     * Optional extensions\n     */\n\n    if (crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) {\n        ret = mbedtls_snprintf(p, n, \"\\n%sbasic constraints : CA=%s\", prefix,\n                               crt->ca_istrue ? \"true\" : \"false\");\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        if (crt->max_pathlen > 0) {\n            ret = mbedtls_snprintf(p, n, \", max_pathlen=%d\", crt->max_pathlen - 1);\n            MBEDTLS_X509_SAFE_SNPRINTF;\n        }\n    }\n\n    if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {\n        ret = mbedtls_snprintf(p, n, \"\\n%ssubject alt name  :\", prefix);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n,\n                                                      &crt->subject_alt_names,\n                                                      prefix)) != 0) {\n            return ret;\n        }\n    }\n\n    if (crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) {\n        ret = mbedtls_snprintf(p, n, \"\\n%scert. type        : \", prefix);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        if ((ret = mbedtls_x509_info_cert_type(&p, &n, crt->ns_cert_type)) != 0) {\n            return ret;\n        }\n    }\n\n    if (crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) {\n        ret = mbedtls_snprintf(p, n, \"\\n%skey usage         : \", prefix);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        if ((ret = mbedtls_x509_info_key_usage(&p, &n, crt->key_usage)) != 0) {\n            return ret;\n        }\n    }\n\n    if (crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) {\n        ret = mbedtls_snprintf(p, n, \"\\n%sext key usage     : \", prefix);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        if ((ret = x509_info_ext_key_usage(&p, &n,\n                                           &crt->ext_key_usage)) != 0) {\n            return ret;\n        }\n    }\n\n    if (crt->ext_types & MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES) {\n        ret = mbedtls_snprintf(p, n, \"\\n%scertificate policies : \", prefix);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        if ((ret = x509_info_cert_policies(&p, &n,\n                                           &crt->certificate_policies)) != 0) {\n            return ret;\n        }\n    }\n\n    ret = mbedtls_snprintf(p, n, \"\\n\");\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    return (int) (size - n);\n}\n\nstruct x509_crt_verify_string {\n    int code;\n    const char *string;\n};\n\n#define X509_CRT_ERROR_INFO(err, err_str, info) { err, info },\nstatic const struct x509_crt_verify_string x509_crt_verify_strings[] = {\n    MBEDTLS_X509_CRT_ERROR_INFO_LIST\n    { 0, NULL }\n};\n#undef X509_CRT_ERROR_INFO\n\nint mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix,\n                                 uint32_t flags)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const struct x509_crt_verify_string *cur;\n    char *p = buf;\n    size_t n = size;\n\n    for (cur = x509_crt_verify_strings; cur->string != NULL; cur++) {\n        if ((flags & cur->code) == 0) {\n            continue;\n        }\n\n        ret = mbedtls_snprintf(p, n, \"%s%s\\n\", prefix, cur->string);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n        flags ^= cur->code;\n    }\n\n    if (flags != 0) {\n        ret = mbedtls_snprintf(p, n, \"%sUnknown reason \"\n                                     \"(this should not happen)\\n\", prefix);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n    }\n\n    return (int) (size - n);\n}\n#endif /* MBEDTLS_X509_REMOVE_INFO */\n\nint mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt,\n                                     unsigned int usage)\n{\n    unsigned int usage_must, usage_may;\n    unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY\n                            | MBEDTLS_X509_KU_DECIPHER_ONLY;\n\n    if ((crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) == 0) {\n        return 0;\n    }\n\n    usage_must = usage & ~may_mask;\n\n    if (((crt->key_usage & ~may_mask) & usage_must) != usage_must) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    usage_may = usage & may_mask;\n\n    if (((crt->key_usage & may_mask) | usage_may) != usage_may) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    return 0;\n}\n\nint mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt *crt,\n                                              const char *usage_oid,\n                                              size_t usage_len)\n{\n    const mbedtls_x509_sequence *cur;\n\n    /* Extension is not mandatory, absent means no restriction */\n    if ((crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) == 0) {\n        return 0;\n    }\n\n    /*\n     * Look for the requested usage (or wildcard ANY) in our list\n     */\n    for (cur = &crt->ext_key_usage; cur != NULL; cur = cur->next) {\n        const mbedtls_x509_buf *cur_oid = &cur->buf;\n\n        if (cur_oid->len == usage_len &&\n            memcmp(cur_oid->p, usage_oid, usage_len) == 0) {\n            return 0;\n        }\n\n        if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid) == 0) {\n            return 0;\n        }\n    }\n\n    return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n}\n\n#if defined(MBEDTLS_X509_CRL_PARSE_C)\n/*\n * Return 1 if the certificate is revoked, or 0 otherwise.\n */\nint mbedtls_x509_crt_is_revoked(const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl)\n{\n    const mbedtls_x509_crl_entry *cur = &crl->entry;\n\n    while (cur != NULL && cur->serial.len != 0) {\n        if (crt->serial.len == cur->serial.len &&\n            memcmp(crt->serial.p, cur->serial.p, crt->serial.len) == 0) {\n            return 1;\n        }\n\n        cur = cur->next;\n    }\n\n    return 0;\n}\n\n/*\n * Check that the given certificate is not revoked according to the CRL.\n * Skip validation if no CRL for the given CA is present.\n */\nstatic int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,\n                              mbedtls_x509_crl *crl_list,\n                              const mbedtls_x509_crt_profile *profile,\n                              const mbedtls_x509_time *now)\n{\n    int flags = 0;\n    unsigned char hash[MBEDTLS_MD_MAX_SIZE];\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_algorithm_t psa_algorithm;\n#else\n    const mbedtls_md_info_t *md_info;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    size_t hash_length;\n\n    if (ca == NULL) {\n        return flags;\n    }\n\n    while (crl_list != NULL) {\n        if (crl_list->version == 0 ||\n            x509_name_cmp(&crl_list->issuer, &ca->subject) != 0) {\n            crl_list = crl_list->next;\n            continue;\n        }\n\n        /*\n         * Check if the CA is configured to sign CRLs\n         */\n        if (mbedtls_x509_crt_check_key_usage(ca,\n                                             MBEDTLS_X509_KU_CRL_SIGN) != 0) {\n            flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;\n            break;\n        }\n\n        /*\n         * Check if CRL is correctly signed by the trusted CA\n         */\n        if (x509_profile_check_md_alg(profile, crl_list->sig_md) != 0) {\n            flags |= MBEDTLS_X509_BADCRL_BAD_MD;\n        }\n\n        if (x509_profile_check_pk_alg(profile, crl_list->sig_pk) != 0) {\n            flags |= MBEDTLS_X509_BADCRL_BAD_PK;\n        }\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n        psa_algorithm = mbedtls_md_psa_alg_from_type(crl_list->sig_md);\n        if (psa_hash_compute(psa_algorithm,\n                             crl_list->tbs.p,\n                             crl_list->tbs.len,\n                             hash,\n                             sizeof(hash),\n                             &hash_length) != PSA_SUCCESS) {\n            /* Note: this can't happen except after an internal error */\n            flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;\n            break;\n        }\n#else\n        md_info = mbedtls_md_info_from_type(crl_list->sig_md);\n        hash_length = mbedtls_md_get_size(md_info);\n        if (mbedtls_md(md_info,\n                       crl_list->tbs.p,\n                       crl_list->tbs.len,\n                       hash) != 0) {\n            /* Note: this can't happen except after an internal error */\n            flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;\n            break;\n        }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n        if (x509_profile_check_key(profile, &ca->pk) != 0) {\n            flags |= MBEDTLS_X509_BADCERT_BAD_KEY;\n        }\n\n        if (mbedtls_pk_verify_ext(crl_list->sig_pk, crl_list->sig_opts, &ca->pk,\n                                  crl_list->sig_md, hash, hash_length,\n                                  crl_list->sig.p, crl_list->sig.len) != 0) {\n            flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;\n            break;\n        }\n\n#if defined(MBEDTLS_HAVE_TIME_DATE)\n        /*\n         * Check for validity of CRL (Do not drop out)\n         */\n        if (mbedtls_x509_time_cmp(&crl_list->next_update, now) < 0) {\n            flags |= MBEDTLS_X509_BADCRL_EXPIRED;\n        }\n\n        if (mbedtls_x509_time_cmp(&crl_list->this_update, now) > 0) {\n            flags |= MBEDTLS_X509_BADCRL_FUTURE;\n        }\n#else\n        ((void) now);\n#endif\n\n        /*\n         * Check if certificate is revoked\n         */\n        if (mbedtls_x509_crt_is_revoked(crt, crl_list)) {\n            flags |= MBEDTLS_X509_BADCERT_REVOKED;\n            break;\n        }\n\n        crl_list = crl_list->next;\n    }\n\n    return flags;\n}\n#endif /* MBEDTLS_X509_CRL_PARSE_C */\n\n/*\n * Check the signature of a certificate by its parent\n */\nstatic int x509_crt_check_signature(const mbedtls_x509_crt *child,\n                                    mbedtls_x509_crt *parent,\n                                    mbedtls_x509_crt_restart_ctx *rs_ctx)\n{\n    size_t hash_len;\n    unsigned char hash[MBEDTLS_MD_MAX_SIZE];\n#if !defined(MBEDTLS_USE_PSA_CRYPTO)\n    const mbedtls_md_info_t *md_info;\n    md_info = mbedtls_md_info_from_type(child->sig_md);\n    hash_len = mbedtls_md_get_size(md_info);\n\n    /* Note: hash errors can happen only after an internal error */\n    if (mbedtls_md(md_info, child->tbs.p, child->tbs.len, hash) != 0) {\n        return -1;\n    }\n#else\n    psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(child->sig_md);\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n\n    status = psa_hash_compute(hash_alg,\n                              child->tbs.p,\n                              child->tbs.len,\n                              hash,\n                              sizeof(hash),\n                              &hash_len);\n    if (status != PSA_SUCCESS) {\n        return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;\n    }\n\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n    /* Skip expensive computation on obvious mismatch */\n    if (!mbedtls_pk_can_do(&parent->pk, child->sig_pk)) {\n        return -1;\n    }\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA) {\n        return mbedtls_pk_verify_restartable(&parent->pk,\n                                             child->sig_md, hash, hash_len,\n                                             child->sig.p, child->sig.len, &rs_ctx->pk);\n    }\n#else\n    (void) rs_ctx;\n#endif\n\n    return mbedtls_pk_verify_ext(child->sig_pk, child->sig_opts, &parent->pk,\n                                 child->sig_md, hash, hash_len,\n                                 child->sig.p, child->sig.len);\n}\n\n/*\n * Check if 'parent' is a suitable parent (signing CA) for 'child'.\n * Return 0 if yes, -1 if not.\n *\n * top means parent is a locally-trusted certificate\n */\nstatic int x509_crt_check_parent(const mbedtls_x509_crt *child,\n                                 const mbedtls_x509_crt *parent,\n                                 int top)\n{\n    int need_ca_bit;\n\n    /* Parent must be the issuer */\n    if (x509_name_cmp(&child->issuer, &parent->subject) != 0) {\n        return -1;\n    }\n\n    /* Parent must have the basicConstraints CA bit set as a general rule */\n    need_ca_bit = 1;\n\n    /* Exception: v1/v2 certificates that are locally trusted. */\n    if (top && parent->version < 3) {\n        need_ca_bit = 0;\n    }\n\n    if (need_ca_bit && !parent->ca_istrue) {\n        return -1;\n    }\n\n    if (need_ca_bit &&\n        mbedtls_x509_crt_check_key_usage(parent, MBEDTLS_X509_KU_KEY_CERT_SIGN) != 0) {\n        return -1;\n    }\n\n    return 0;\n}\n\n/*\n * Find a suitable parent for child in candidates, or return NULL.\n *\n * Here suitable is defined as:\n *  1. subject name matches child's issuer\n *  2. if necessary, the CA bit is set and key usage allows signing certs\n *  3. for trusted roots, the signature is correct\n *     (for intermediates, the signature is checked and the result reported)\n *  4. pathlen constraints are satisfied\n *\n * If there's a suitable candidate which is also time-valid, return the first\n * such. Otherwise, return the first suitable candidate (or NULL if there is\n * none).\n *\n * The rationale for this rule is that someone could have a list of trusted\n * roots with two versions on the same root with different validity periods.\n * (At least one user reported having such a list and wanted it to just work.)\n * The reason we don't just require time-validity is that generally there is\n * only one version, and if it's expired we want the flags to state that\n * rather than NOT_TRUSTED, as would be the case if we required it here.\n *\n * The rationale for rule 3 (signature for trusted roots) is that users might\n * have two versions of the same CA with different keys in their list, and the\n * way we select the correct one is by checking the signature (as we don't\n * rely on key identifier extensions). (This is one way users might choose to\n * handle key rollover, another relies on self-issued certs, see [SIRO].)\n *\n * Arguments:\n *  - [in] child: certificate for which we're looking for a parent\n *  - [in] candidates: chained list of potential parents\n *  - [out] r_parent: parent found (or NULL)\n *  - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0\n *  - [in] top: 1 if candidates consists of trusted roots, ie we're at the top\n *         of the chain, 0 otherwise\n *  - [in] path_cnt: number of intermediates seen so far\n *  - [in] self_cnt: number of self-signed intermediates seen so far\n *         (will never be greater than path_cnt)\n *  - [in-out] rs_ctx: context for restarting operations\n *\n * Return value:\n *  - 0 on success\n *  - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise\n */\nstatic int x509_crt_find_parent_in(\n    mbedtls_x509_crt *child,\n    mbedtls_x509_crt *candidates,\n    mbedtls_x509_crt **r_parent,\n    int *r_signature_is_good,\n    int top,\n    unsigned path_cnt,\n    unsigned self_cnt,\n    mbedtls_x509_crt_restart_ctx *rs_ctx,\n    const mbedtls_x509_time *now)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_x509_crt *parent, *fallback_parent;\n    int signature_is_good = 0, fallback_signature_is_good;\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    /* did we have something in progress? */\n    if (rs_ctx != NULL && rs_ctx->parent != NULL) {\n        /* restore saved state */\n        parent = rs_ctx->parent;\n        fallback_parent = rs_ctx->fallback_parent;\n        fallback_signature_is_good = rs_ctx->fallback_signature_is_good;\n\n        /* clear saved state */\n        rs_ctx->parent = NULL;\n        rs_ctx->fallback_parent = NULL;\n        rs_ctx->fallback_signature_is_good = 0;\n\n        /* resume where we left */\n        goto check_signature;\n    }\n#endif\n\n    fallback_parent = NULL;\n    fallback_signature_is_good = 0;\n\n    for (parent = candidates; parent != NULL; parent = parent->next) {\n        /* basic parenting skills (name, CA bit, key usage) */\n        if (x509_crt_check_parent(child, parent, top) != 0) {\n            continue;\n        }\n\n        /* +1 because stored max_pathlen is 1 higher that the actual value */\n        if (parent->max_pathlen > 0 &&\n            (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt) {\n            continue;\n        }\n\n        /* Signature */\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\ncheck_signature:\n#endif\n        ret = x509_crt_check_signature(child, parent, rs_ctx);\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n        if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {\n            /* save state */\n            rs_ctx->parent = parent;\n            rs_ctx->fallback_parent = fallback_parent;\n            rs_ctx->fallback_signature_is_good = fallback_signature_is_good;\n\n            return ret;\n        }\n#else\n        (void) ret;\n#endif\n\n        signature_is_good = ret == 0;\n        if (top && !signature_is_good) {\n            continue;\n        }\n\n#if defined(MBEDTLS_HAVE_TIME_DATE)\n        /* optional time check */\n        if (mbedtls_x509_time_cmp(&parent->valid_to, now) < 0 ||    /* past */\n            mbedtls_x509_time_cmp(&parent->valid_from, now) > 0) {  /* future */\n            if (fallback_parent == NULL) {\n                fallback_parent = parent;\n                fallback_signature_is_good = signature_is_good;\n            }\n\n            continue;\n        }\n#else\n        ((void) now);\n#endif\n\n        *r_parent = parent;\n        *r_signature_is_good = signature_is_good;\n\n        break;\n    }\n\n    if (parent == NULL) {\n        *r_parent = fallback_parent;\n        *r_signature_is_good = fallback_signature_is_good;\n    }\n\n    return 0;\n}\n\n/*\n * Find a parent in trusted CAs or the provided chain, or return NULL.\n *\n * Searches in trusted CAs first, and return the first suitable parent found\n * (see find_parent_in() for definition of suitable).\n *\n * Arguments:\n *  - [in] child: certificate for which we're looking for a parent, followed\n *         by a chain of possible intermediates\n *  - [in] trust_ca: list of locally trusted certificates\n *  - [out] parent: parent found (or NULL)\n *  - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0\n *  - [out] signature_is_good: 1 if child signature by parent is valid, or 0\n *  - [in] path_cnt: number of links in the chain so far (EE -> ... -> child)\n *  - [in] self_cnt: number of self-signed certs in the chain so far\n *         (will always be no greater than path_cnt)\n *  - [in-out] rs_ctx: context for restarting operations\n *\n * Return value:\n *  - 0 on success\n *  - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise\n */\nstatic int x509_crt_find_parent(\n    mbedtls_x509_crt *child,\n    mbedtls_x509_crt *trust_ca,\n    mbedtls_x509_crt **parent,\n    int *parent_is_trusted,\n    int *signature_is_good,\n    unsigned path_cnt,\n    unsigned self_cnt,\n    mbedtls_x509_crt_restart_ctx *rs_ctx,\n    const mbedtls_x509_time *now)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_x509_crt *search_list;\n\n    *parent_is_trusted = 1;\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    /* restore then clear saved state if we have some stored */\n    if (rs_ctx != NULL && rs_ctx->parent_is_trusted != -1) {\n        *parent_is_trusted = rs_ctx->parent_is_trusted;\n        rs_ctx->parent_is_trusted = -1;\n    }\n#endif\n\n    while (1) {\n        search_list = *parent_is_trusted ? trust_ca : child->next;\n\n        ret = x509_crt_find_parent_in(child, search_list,\n                                      parent, signature_is_good,\n                                      *parent_is_trusted,\n                                      path_cnt, self_cnt, rs_ctx, now);\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n        if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {\n            /* save state */\n            rs_ctx->parent_is_trusted = *parent_is_trusted;\n            return ret;\n        }\n#else\n        (void) ret;\n#endif\n\n        /* stop here if found or already in second iteration */\n        if (*parent != NULL || *parent_is_trusted == 0) {\n            break;\n        }\n\n        /* prepare second iteration */\n        *parent_is_trusted = 0;\n    }\n\n    /* extra precaution against mistakes in the caller */\n    if (*parent == NULL) {\n        *parent_is_trusted = 0;\n        *signature_is_good = 0;\n    }\n\n    return 0;\n}\n\n/*\n * Check if an end-entity certificate is locally trusted\n *\n * Currently we require such certificates to be self-signed (actually only\n * check for self-issued as self-signatures are not checked)\n */\nstatic int x509_crt_check_ee_locally_trusted(\n    mbedtls_x509_crt *crt,\n    mbedtls_x509_crt *trust_ca)\n{\n    mbedtls_x509_crt *cur;\n\n    /* must be self-issued */\n    if (x509_name_cmp(&crt->issuer, &crt->subject) != 0) {\n        return -1;\n    }\n\n    /* look for an exact match with trusted cert */\n    for (cur = trust_ca; cur != NULL; cur = cur->next) {\n        if (crt->raw.len == cur->raw.len &&\n            memcmp(crt->raw.p, cur->raw.p, crt->raw.len) == 0) {\n            return 0;\n        }\n    }\n\n    /* too bad */\n    return -1;\n}\n\n/*\n * Build and verify a certificate chain\n *\n * Given a peer-provided list of certificates EE, C1, ..., Cn and\n * a list of trusted certs R1, ... Rp, try to build and verify a chain\n *      EE, Ci1, ... Ciq [, Rj]\n * such that every cert in the chain is a child of the next one,\n * jumping to a trusted root as early as possible.\n *\n * Verify that chain and return it with flags for all issues found.\n *\n * Special cases:\n * - EE == Rj -> return a one-element list containing it\n * - EE, Ci1, ..., Ciq cannot be continued with a trusted root\n *   -> return that chain with NOT_TRUSTED set on Ciq\n *\n * Tests for (aspects of) this function should include at least:\n * - trusted EE\n * - EE -> trusted root\n * - EE -> intermediate CA -> trusted root\n * - if relevant: EE untrusted\n * - if relevant: EE -> intermediate, untrusted\n * with the aspect under test checked at each relevant level (EE, int, root).\n * For some aspects longer chains are required, but usually length 2 is\n * enough (but length 1 is not in general).\n *\n * Arguments:\n *  - [in] crt: the cert list EE, C1, ..., Cn\n *  - [in] trust_ca: the trusted list R1, ..., Rp\n *  - [in] ca_crl, profile: as in verify_with_profile()\n *  - [out] ver_chain: the built and verified chain\n *      Only valid when return value is 0, may contain garbage otherwise!\n *      Restart note: need not be the same when calling again to resume.\n *  - [in-out] rs_ctx: context for restarting operations\n *\n * Return value:\n *  - non-zero if the chain could not be fully built and examined\n *  - 0 is the chain was successfully built and examined,\n *      even if it was found to be invalid\n */\nstatic int x509_crt_verify_chain(\n    mbedtls_x509_crt *crt,\n    mbedtls_x509_crt *trust_ca,\n    mbedtls_x509_crl *ca_crl,\n    mbedtls_x509_crt_ca_cb_t f_ca_cb,\n    void *p_ca_cb,\n    const mbedtls_x509_crt_profile *profile,\n    mbedtls_x509_crt_verify_chain *ver_chain,\n    mbedtls_x509_crt_restart_ctx *rs_ctx)\n{\n    /* Don't initialize any of those variables here, so that the compiler can\n     * catch potential issues with jumping ahead when restarting */\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    uint32_t *flags;\n    mbedtls_x509_crt_verify_chain_item *cur;\n    mbedtls_x509_crt *child;\n    mbedtls_x509_crt *parent;\n    int parent_is_trusted;\n    int child_is_trusted;\n    int signature_is_good;\n    unsigned self_cnt;\n    mbedtls_x509_crt *cur_trust_ca = NULL;\n    mbedtls_x509_time now;\n\n#if defined(MBEDTLS_HAVE_TIME_DATE)\n    if (mbedtls_x509_time_gmtime(mbedtls_time(NULL), &now) != 0) {\n        return MBEDTLS_ERR_X509_FATAL_ERROR;\n    }\n#endif\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    /* resume if we had an operation in progress */\n    if (rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent) {\n        /* restore saved state */\n        *ver_chain = rs_ctx->ver_chain; /* struct copy */\n        self_cnt = rs_ctx->self_cnt;\n\n        /* restore derived state */\n        cur = &ver_chain->items[ver_chain->len - 1];\n        child = cur->crt;\n        flags = &cur->flags;\n\n        goto find_parent;\n    }\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n\n    child = crt;\n    self_cnt = 0;\n    parent_is_trusted = 0;\n    child_is_trusted = 0;\n\n    while (1) {\n        /* Add certificate to the verification chain */\n        cur = &ver_chain->items[ver_chain->len];\n        cur->crt = child;\n        cur->flags = 0;\n        ver_chain->len++;\n        flags = &cur->flags;\n\n#if defined(MBEDTLS_HAVE_TIME_DATE)\n        /* Check time-validity (all certificates) */\n        if (mbedtls_x509_time_cmp(&child->valid_to, &now) < 0) {\n            *flags |= MBEDTLS_X509_BADCERT_EXPIRED;\n        }\n\n        if (mbedtls_x509_time_cmp(&child->valid_from, &now) > 0) {\n            *flags |= MBEDTLS_X509_BADCERT_FUTURE;\n        }\n#endif\n\n        /* Stop here for trusted roots (but not for trusted EE certs) */\n        if (child_is_trusted) {\n            return 0;\n        }\n\n        /* Check signature algorithm: MD & PK algs */\n        if (x509_profile_check_md_alg(profile, child->sig_md) != 0) {\n            *flags |= MBEDTLS_X509_BADCERT_BAD_MD;\n        }\n\n        if (x509_profile_check_pk_alg(profile, child->sig_pk) != 0) {\n            *flags |= MBEDTLS_X509_BADCERT_BAD_PK;\n        }\n\n        /* Special case: EE certs that are locally trusted */\n        if (ver_chain->len == 1 &&\n            x509_crt_check_ee_locally_trusted(child, trust_ca) == 0) {\n            return 0;\n        }\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\nfind_parent:\n#endif\n\n        /* Obtain list of potential trusted signers from CA callback,\n         * or use statically provided list. */\n#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)\n        if (f_ca_cb != NULL) {\n            mbedtls_x509_crt_free(ver_chain->trust_ca_cb_result);\n            mbedtls_free(ver_chain->trust_ca_cb_result);\n            ver_chain->trust_ca_cb_result = NULL;\n\n            ret = f_ca_cb(p_ca_cb, child, &ver_chain->trust_ca_cb_result);\n            if (ret != 0) {\n                return MBEDTLS_ERR_X509_FATAL_ERROR;\n            }\n\n            cur_trust_ca = ver_chain->trust_ca_cb_result;\n        } else\n#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */\n        {\n            ((void) f_ca_cb);\n            ((void) p_ca_cb);\n            cur_trust_ca = trust_ca;\n        }\n\n        /* Look for a parent in trusted CAs or up the chain */\n        ret = x509_crt_find_parent(child, cur_trust_ca, &parent,\n                                   &parent_is_trusted, &signature_is_good,\n                                   ver_chain->len - 1, self_cnt, rs_ctx,\n                                   &now);\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n        if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {\n            /* save state */\n            rs_ctx->in_progress = x509_crt_rs_find_parent;\n            rs_ctx->self_cnt = self_cnt;\n            rs_ctx->ver_chain = *ver_chain; /* struct copy */\n\n            return ret;\n        }\n#else\n        (void) ret;\n#endif\n\n        /* No parent? We're done here */\n        if (parent == NULL) {\n            *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;\n            return 0;\n        }\n\n        /* Count intermediate self-issued (not necessarily self-signed) certs.\n         * These can occur with some strategies for key rollover, see [SIRO],\n         * and should be excluded from max_pathlen checks. */\n        if (ver_chain->len != 1 &&\n            x509_name_cmp(&child->issuer, &child->subject) == 0) {\n            self_cnt++;\n        }\n\n        /* path_cnt is 0 for the first intermediate CA,\n         * and if parent is trusted it's not an intermediate CA */\n        if (!parent_is_trusted &&\n            ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA) {\n            /* return immediately to avoid overflow the chain array */\n            return MBEDTLS_ERR_X509_FATAL_ERROR;\n        }\n\n        /* signature was checked while searching parent */\n        if (!signature_is_good) {\n            *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;\n        }\n\n        /* check size of signing key */\n        if (x509_profile_check_key(profile, &parent->pk) != 0) {\n            *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;\n        }\n\n#if defined(MBEDTLS_X509_CRL_PARSE_C)\n        /* Check trusted CA's CRL for the given crt */\n        *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile, &now);\n#else\n        (void) ca_crl;\n#endif\n\n        /* prepare for next iteration */\n        child = parent;\n        parent = NULL;\n        child_is_trusted = parent_is_trusted;\n        signature_is_good = 0;\n    }\n}\n\n#ifdef _WIN32\n#ifdef _MSC_VER\n#pragma comment(lib, \"ws2_32.lib\")\n#include <winsock2.h>\n#include <ws2tcpip.h>\n#elif (defined(__MINGW32__) || defined(__MINGW64__)) && _WIN32_WINNT >= 0x0600\n#include <winsock2.h>\n#include <ws2tcpip.h>\n#else\n/* inet_pton() is not supported, fallback to software version */\n#define MBEDTLS_TEST_SW_INET_PTON\n#endif\n#elif defined(__sun)\n/* Solaris requires -lsocket -lnsl for inet_pton() */\n#elif defined(__has_include)\n#if __has_include(<sys/socket.h>)\n#include <sys/socket.h>\n#endif\n#if __has_include(<arpa/inet.h>)\n#include <arpa/inet.h>\n#endif\n#endif\n\n/* Use whether or not AF_INET6 is defined to indicate whether or not to use\n * the platform inet_pton() or a local implementation (below).  The local\n * implementation may be used even in cases where the platform provides\n * inet_pton(), e.g. when there are different includes required and/or the\n * platform implementation requires dependencies on additional libraries.\n * Specifically, Windows requires custom includes and additional link\n * dependencies, and Solaris requires additional link dependencies.\n * Also, as a coarse heuristic, use the local implementation if the compiler\n * does not support __has_include(), or if the definition of AF_INET6 is not\n * provided by headers included (or not) via __has_include() above.\n * MBEDTLS_TEST_SW_INET_PTON is a bypass define to force testing of this code //no-check-names\n * despite having a platform that has inet_pton. */\n#if !defined(AF_INET6) || defined(MBEDTLS_TEST_SW_INET_PTON) //no-check-names\n/* Definition located further below to possibly reduce compiler inlining */\nstatic int x509_inet_pton_ipv4(const char *src, void *dst);\n\n#define li_cton(c, n) \\\n    (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))\n\nstatic int x509_inet_pton_ipv6(const char *src, void *dst)\n{\n    const unsigned char *p = (const unsigned char *) src;\n    int nonzero_groups = 0, num_digits, zero_group_start = -1;\n    uint16_t addr[8];\n    do {\n        /* note: allows excess leading 0's, e.g. 1:0002:3:... */\n        uint16_t group = num_digits = 0;\n        for (uint8_t digit; num_digits < 4; num_digits++) {\n            if (li_cton(*p, digit) == 0) {\n                break;\n            }\n            group = (group << 4) | digit;\n            p++;\n        }\n        if (num_digits != 0) {\n            MBEDTLS_PUT_UINT16_BE(group, addr, nonzero_groups);\n            nonzero_groups++;\n            if (*p == '\\0') {\n                break;\n            } else if (*p == '.') {\n                /* Don't accept IPv4 too early or late */\n                if ((nonzero_groups == 0 && zero_group_start == -1) ||\n                    nonzero_groups >= 7) {\n                    break;\n                }\n\n                /* Walk back to prior ':', then parse as IPv4-mapped */\n                int steps = 4;\n                do {\n                    p--;\n                    steps--;\n                } while (*p != ':' && steps > 0);\n\n                if (*p != ':') {\n                    break;\n                }\n                p++;\n                nonzero_groups--;\n                if (x509_inet_pton_ipv4((const char *) p,\n                                        addr + nonzero_groups) != 0) {\n                    break;\n                }\n\n                nonzero_groups += 2;\n                p = (const unsigned char *) \"\";\n                break;\n            } else if (*p != ':') {\n                return -1;\n            }\n        } else {\n            /* Don't accept a second zero group or an invalid delimiter */\n            if (zero_group_start != -1 || *p != ':') {\n                return -1;\n            }\n            zero_group_start = nonzero_groups;\n\n            /* Accept a zero group at start, but it has to be a double colon */\n            if (zero_group_start == 0 && *++p != ':') {\n                return -1;\n            }\n\n            if (p[1] == '\\0') {\n                ++p;\n                break;\n            }\n        }\n        ++p;\n    } while (nonzero_groups < 8);\n\n    if (*p != '\\0') {\n        return -1;\n    }\n\n    if (zero_group_start != -1) {\n        if (nonzero_groups > 6) {\n            return -1;\n        }\n        int zero_groups = 8 - nonzero_groups;\n        int groups_after_zero = nonzero_groups - zero_group_start;\n\n        /* Move the non-zero part to after the zeroes */\n        if (groups_after_zero) {\n            memmove(addr + zero_group_start + zero_groups,\n                    addr + zero_group_start,\n                    groups_after_zero * sizeof(*addr));\n        }\n        memset(addr + zero_group_start, 0, zero_groups * sizeof(*addr));\n    } else {\n        if (nonzero_groups != 8) {\n            return -1;\n        }\n    }\n    memcpy(dst, addr, sizeof(addr));\n    return 0;\n}\n\nstatic int x509_inet_pton_ipv4(const char *src, void *dst)\n{\n    const unsigned char *p = (const unsigned char *) src;\n    uint8_t *res = (uint8_t *) dst;\n    uint8_t digit, num_digits = 0;\n    uint8_t num_octets = 0;\n    uint16_t octet;\n\n    do {\n        octet = num_digits = 0;\n        do {\n            digit = *p - '0';\n            if (digit > 9) {\n                break;\n            }\n\n            /* Don't allow leading zeroes. These might mean octal format,\n             * which this implementation does not support. */\n            if (octet == 0 && num_digits > 0) {\n                return -1;\n            }\n\n            octet = octet * 10 + digit;\n            num_digits++;\n            p++;\n        } while (num_digits < 3);\n\n        if (octet >= 256 || num_digits > 3 || num_digits == 0) {\n            return -1;\n        }\n        *res++ = (uint8_t) octet;\n        num_octets++;\n    } while (num_octets < 4 && *p++ == '.');\n    return num_octets == 4 && *p == '\\0' ? 0 : -1;\n}\n\n#else\n\nstatic int x509_inet_pton_ipv6(const char *src, void *dst)\n{\n    return inet_pton(AF_INET6, src, dst) == 1 ? 0 : -1;\n}\n\nstatic int x509_inet_pton_ipv4(const char *src, void *dst)\n{\n    return inet_pton(AF_INET, src, dst) == 1 ? 0 : -1;\n}\n\n#endif /* !AF_INET6 || MBEDTLS_TEST_SW_INET_PTON */ //no-check-names\n\nsize_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst)\n{\n    return strchr(cn, ':') == NULL\n            ? x509_inet_pton_ipv4(cn, dst) == 0 ? 4 : 0\n            : x509_inet_pton_ipv6(cn, dst) == 0 ? 16 : 0;\n}\n\n/*\n * Check for CN match\n */\nstatic int x509_crt_check_cn(const mbedtls_x509_buf *name,\n                             const char *cn, size_t cn_len)\n{\n    /* try exact match */\n    if (name->len == cn_len &&\n        x509_memcasecmp(cn, name->p, cn_len) == 0) {\n        return 0;\n    }\n\n    /* try wildcard match */\n    if (x509_check_wildcard(cn, name) == 0) {\n        return 0;\n    }\n\n    return -1;\n}\n\nstatic int x509_crt_check_san_ip(const mbedtls_x509_sequence *san,\n                                 const char *cn, size_t cn_len)\n{\n    uint32_t ip[4];\n    cn_len = mbedtls_x509_crt_parse_cn_inet_pton(cn, ip);\n    if (cn_len == 0) {\n        return -1;\n    }\n\n    for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) {\n        const unsigned char san_type = (unsigned char) cur->buf.tag &\n                                       MBEDTLS_ASN1_TAG_VALUE_MASK;\n        if (san_type == MBEDTLS_X509_SAN_IP_ADDRESS &&\n            cur->buf.len == cn_len && memcmp(cur->buf.p, ip, cn_len) == 0) {\n            return 0;\n        }\n    }\n\n    return -1;\n}\n\nstatic int x509_crt_check_san_uri(const mbedtls_x509_sequence *san,\n                                  const char *cn, size_t cn_len)\n{\n    for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) {\n        const unsigned char san_type = (unsigned char) cur->buf.tag &\n                                       MBEDTLS_ASN1_TAG_VALUE_MASK;\n        if (san_type == MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER &&\n            cur->buf.len == cn_len && memcmp(cur->buf.p, cn, cn_len) == 0) {\n            return 0;\n        }\n    }\n\n    return -1;\n}\n\n/*\n * Check for SAN match, see RFC 5280 Section 4.2.1.6\n */\nstatic int x509_crt_check_san(const mbedtls_x509_sequence *san,\n                              const char *cn, size_t cn_len)\n{\n    int san_ip = 0;\n    int san_uri = 0;\n    /* Prioritize DNS name over other subtypes due to popularity */\n    for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) {\n        switch ((unsigned char) cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK) {\n            case MBEDTLS_X509_SAN_DNS_NAME:\n                if (x509_crt_check_cn(&cur->buf, cn, cn_len) == 0) {\n                    return 0;\n                }\n                break;\n            case MBEDTLS_X509_SAN_IP_ADDRESS:\n                san_ip = 1;\n                break;\n            case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:\n                san_uri = 1;\n                break;\n            /* (We may handle other types here later.) */\n            default: /* Unrecognized type */\n                break;\n        }\n    }\n    if (san_ip) {\n        if (x509_crt_check_san_ip(san, cn, cn_len) == 0) {\n            return 0;\n        }\n    }\n    if (san_uri) {\n        if (x509_crt_check_san_uri(san, cn, cn_len) == 0) {\n            return 0;\n        }\n    }\n\n    return -1;\n}\n\n/*\n * Verify the requested CN - only call this if cn is not NULL!\n */\nstatic void x509_crt_verify_name(const mbedtls_x509_crt *crt,\n                                 const char *cn,\n                                 uint32_t *flags)\n{\n    const mbedtls_x509_name *name;\n    size_t cn_len = strlen(cn);\n\n    if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {\n        if (x509_crt_check_san(&crt->subject_alt_names, cn, cn_len) == 0) {\n            return;\n        }\n    } else {\n        for (name = &crt->subject; name != NULL; name = name->next) {\n            if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0 &&\n                x509_crt_check_cn(&name->val, cn, cn_len) == 0) {\n                return;\n            }\n        }\n\n    }\n\n    *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;\n}\n\n/*\n * Merge the flags for all certs in the chain, after calling callback\n */\nstatic int x509_crt_merge_flags_with_cb(\n    uint32_t *flags,\n    const mbedtls_x509_crt_verify_chain *ver_chain,\n    int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),\n    void *p_vrfy)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned i;\n    uint32_t cur_flags;\n    const mbedtls_x509_crt_verify_chain_item *cur;\n\n    for (i = ver_chain->len; i != 0; --i) {\n        cur = &ver_chain->items[i-1];\n        cur_flags = cur->flags;\n\n        if (NULL != f_vrfy) {\n            if ((ret = f_vrfy(p_vrfy, cur->crt, (int) i-1, &cur_flags)) != 0) {\n                return ret;\n            }\n        }\n\n        *flags |= cur_flags;\n    }\n\n    return 0;\n}\n\n/*\n * Verify the certificate validity, with profile, restartable version\n *\n * This function:\n *  - checks the requested CN (if any)\n *  - checks the type and size of the EE cert's key,\n *    as that isn't done as part of chain building/verification currently\n *  - builds and verifies the chain\n *  - then calls the callback and merges the flags\n *\n * The parameters pairs `trust_ca`, `ca_crl` and `f_ca_cb`, `p_ca_cb`\n * are mutually exclusive: If `f_ca_cb != NULL`, it will be used by the\n * verification routine to search for trusted signers, and CRLs will\n * be disabled. Otherwise, `trust_ca` will be used as the static list\n * of trusted signers, and `ca_crl` will be use as the static list\n * of CRLs.\n */\nstatic int x509_crt_verify_restartable_ca_cb(mbedtls_x509_crt *crt,\n                                             mbedtls_x509_crt *trust_ca,\n                                             mbedtls_x509_crl *ca_crl,\n                                             mbedtls_x509_crt_ca_cb_t f_ca_cb,\n                                             void *p_ca_cb,\n                                             const mbedtls_x509_crt_profile *profile,\n                                             const char *cn, uint32_t *flags,\n                                             int (*f_vrfy)(void *,\n                                                           mbedtls_x509_crt *,\n                                                           int,\n                                                           uint32_t *),\n                                             void *p_vrfy,\n                                             mbedtls_x509_crt_restart_ctx *rs_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    mbedtls_pk_type_t pk_type;\n    mbedtls_x509_crt_verify_chain ver_chain;\n    uint32_t ee_flags;\n\n    *flags = 0;\n    ee_flags = 0;\n    x509_crt_verify_chain_reset(&ver_chain);\n\n    if (profile == NULL) {\n        ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n        goto exit;\n    }\n\n    /* check name if requested */\n    if (cn != NULL) {\n        x509_crt_verify_name(crt, cn, &ee_flags);\n    }\n\n    /* Check the type and size of the key */\n    pk_type = mbedtls_pk_get_type(&crt->pk);\n\n    if (x509_profile_check_pk_alg(profile, pk_type) != 0) {\n        ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;\n    }\n\n    if (x509_profile_check_key(profile, &crt->pk) != 0) {\n        ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;\n    }\n\n    /* Check the chain */\n    ret = x509_crt_verify_chain(crt, trust_ca, ca_crl,\n                                f_ca_cb, p_ca_cb, profile,\n                                &ver_chain, rs_ctx);\n\n    if (ret != 0) {\n        goto exit;\n    }\n\n    /* Merge end-entity flags */\n    ver_chain.items[0].flags |= ee_flags;\n\n    /* Build final flags, calling callback on the way if any */\n    ret = x509_crt_merge_flags_with_cb(flags, &ver_chain, f_vrfy, p_vrfy);\n\nexit:\n\n#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)\n    mbedtls_x509_crt_free(ver_chain.trust_ca_cb_result);\n    mbedtls_free(ver_chain.trust_ca_cb_result);\n    ver_chain.trust_ca_cb_result = NULL;\n#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n    if (rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS) {\n        mbedtls_x509_crt_restart_free(rs_ctx);\n    }\n#endif\n\n    /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by\n     * the SSL module for authmode optional, but non-zero return from the\n     * callback means a fatal error so it shouldn't be ignored */\n    if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {\n        ret = MBEDTLS_ERR_X509_FATAL_ERROR;\n    }\n\n    if (ret != 0) {\n        *flags = (uint32_t) -1;\n        return ret;\n    }\n\n    if (*flags != 0) {\n        return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;\n    }\n\n    return 0;\n}\n\n\n/*\n * Verify the certificate validity (default profile, not restartable)\n */\nint mbedtls_x509_crt_verify(mbedtls_x509_crt *crt,\n                            mbedtls_x509_crt *trust_ca,\n                            mbedtls_x509_crl *ca_crl,\n                            const char *cn, uint32_t *flags,\n                            int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),\n                            void *p_vrfy)\n{\n    return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl,\n                                             NULL, NULL,\n                                             &mbedtls_x509_crt_profile_default,\n                                             cn, flags,\n                                             f_vrfy, p_vrfy, NULL);\n}\n\n/*\n * Verify the certificate validity (user-chosen profile, not restartable)\n */\nint mbedtls_x509_crt_verify_with_profile(mbedtls_x509_crt *crt,\n                                         mbedtls_x509_crt *trust_ca,\n                                         mbedtls_x509_crl *ca_crl,\n                                         const mbedtls_x509_crt_profile *profile,\n                                         const char *cn, uint32_t *flags,\n                                         int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),\n                                         void *p_vrfy)\n{\n    return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl,\n                                             NULL, NULL,\n                                             profile, cn, flags,\n                                             f_vrfy, p_vrfy, NULL);\n}\n\n#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)\n/*\n * Verify the certificate validity (user-chosen profile, CA callback,\n *                                  not restartable).\n */\nint mbedtls_x509_crt_verify_with_ca_cb(mbedtls_x509_crt *crt,\n                                       mbedtls_x509_crt_ca_cb_t f_ca_cb,\n                                       void *p_ca_cb,\n                                       const mbedtls_x509_crt_profile *profile,\n                                       const char *cn, uint32_t *flags,\n                                       int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),\n                                       void *p_vrfy)\n{\n    return x509_crt_verify_restartable_ca_cb(crt, NULL, NULL,\n                                             f_ca_cb, p_ca_cb,\n                                             profile, cn, flags,\n                                             f_vrfy, p_vrfy, NULL);\n}\n#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */\n\nint mbedtls_x509_crt_verify_restartable(mbedtls_x509_crt *crt,\n                                        mbedtls_x509_crt *trust_ca,\n                                        mbedtls_x509_crl *ca_crl,\n                                        const mbedtls_x509_crt_profile *profile,\n                                        const char *cn, uint32_t *flags,\n                                        int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),\n                                        void *p_vrfy,\n                                        mbedtls_x509_crt_restart_ctx *rs_ctx)\n{\n    return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl,\n                                             NULL, NULL,\n                                             profile, cn, flags,\n                                             f_vrfy, p_vrfy, rs_ctx);\n}\n\n\n/*\n * Initialize a certificate chain\n */\nvoid mbedtls_x509_crt_init(mbedtls_x509_crt *crt)\n{\n    memset(crt, 0, sizeof(mbedtls_x509_crt));\n}\n\n/*\n * Unallocate all certificate data\n */\nvoid mbedtls_x509_crt_free(mbedtls_x509_crt *crt)\n{\n    mbedtls_x509_crt *cert_cur = crt;\n    mbedtls_x509_crt *cert_prv;\n\n    while (cert_cur != NULL) {\n        mbedtls_pk_free(&cert_cur->pk);\n\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)\n        mbedtls_free(cert_cur->sig_opts);\n#endif\n\n        mbedtls_asn1_free_named_data_list_shallow(cert_cur->issuer.next);\n        mbedtls_asn1_free_named_data_list_shallow(cert_cur->subject.next);\n        mbedtls_asn1_sequence_free(cert_cur->ext_key_usage.next);\n        mbedtls_asn1_sequence_free(cert_cur->subject_alt_names.next);\n        mbedtls_asn1_sequence_free(cert_cur->certificate_policies.next);\n        mbedtls_asn1_sequence_free(cert_cur->authority_key_id.authorityCertIssuer.next);\n\n        if (cert_cur->raw.p != NULL && cert_cur->own_buffer) {\n            mbedtls_zeroize_and_free(cert_cur->raw.p, cert_cur->raw.len);\n        }\n\n        cert_prv = cert_cur;\n        cert_cur = cert_cur->next;\n\n        mbedtls_platform_zeroize(cert_prv, sizeof(mbedtls_x509_crt));\n        if (cert_prv != crt) {\n            mbedtls_free(cert_prv);\n        }\n    }\n}\n\n#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)\n/*\n * Initialize a restart context\n */\nvoid mbedtls_x509_crt_restart_init(mbedtls_x509_crt_restart_ctx *ctx)\n{\n    mbedtls_pk_restart_init(&ctx->pk);\n\n    ctx->parent = NULL;\n    ctx->fallback_parent = NULL;\n    ctx->fallback_signature_is_good = 0;\n\n    ctx->parent_is_trusted = -1;\n\n    ctx->in_progress = x509_crt_rs_none;\n    ctx->self_cnt = 0;\n    x509_crt_verify_chain_reset(&ctx->ver_chain);\n}\n\n/*\n * Free the components of a restart context\n */\nvoid mbedtls_x509_crt_restart_free(mbedtls_x509_crt_restart_ctx *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_pk_restart_free(&ctx->pk);\n    mbedtls_x509_crt_restart_init(ctx);\n}\n#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */\n\nint mbedtls_x509_crt_get_ca_istrue(const mbedtls_x509_crt *crt)\n{\n    if ((crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) != 0) {\n        return crt->MBEDTLS_PRIVATE(ca_istrue);\n    }\n    return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;\n}\n\n#endif /* MBEDTLS_X509_CRT_PARSE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/x509_csr.c",
    "content": "/*\n *  X.509 Certificate Signing Request (CSR) parsing\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n *  The ITU-T X.509 standard defines a certificate format for PKI.\n *\n *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)\n *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)\n *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)\n *\n *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf\n *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_X509_CSR_PARSE_C)\n\n#include \"mbedtls/x509_csr.h\"\n#include \"x509_internal.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/oid.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include <string.h>\n\n#if defined(MBEDTLS_PEM_PARSE_C)\n#include \"mbedtls/pem.h\"\n#endif\n\n#include \"mbedtls/platform.h\"\n\n#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)\n#include <stdio.h>\n#endif\n\n/*\n *  Version  ::=  INTEGER  {  v1(0)  }\n */\nstatic int x509_csr_get_version(unsigned char **p,\n                                const unsigned char *end,\n                                int *ver)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) {\n        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {\n            *ver = 0;\n            return 0;\n        }\n\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret);\n    }\n\n    return 0;\n}\n\n/*\n * Parse CSR extension requests in DER format\n */\nstatic int x509_csr_parse_extensions(mbedtls_x509_csr *csr,\n                                     unsigned char **p, const unsigned char *end,\n                                     mbedtls_x509_csr_ext_cb_t cb,\n                                     void *p_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n    unsigned char *end_ext_data, *end_ext_octet;\n\n    while (*p < end) {\n        mbedtls_x509_buf extn_oid = { 0, 0, NULL };\n        int is_critical = 0; /* DEFAULT FALSE */\n        int ext_type = 0;\n\n        /* Read sequence tag */\n        if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        end_ext_data = *p + len;\n\n        /* Get extension ID */\n        if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len,\n                                        MBEDTLS_ASN1_OID)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        extn_oid.tag = MBEDTLS_ASN1_OID;\n        extn_oid.p = *p;\n        *p += extn_oid.len;\n\n        /* Get optional critical */\n        if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 &&\n            (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        /* Data should be octet string type */\n        if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,\n                                        MBEDTLS_ASN1_OCTET_STRING)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        end_ext_octet = *p + len;\n\n        if (end_ext_octet != end_ext_data) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n        }\n\n        /*\n         * Detect supported extensions and skip unsupported extensions\n         */\n        ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type);\n\n        if (ret != 0) {\n            /* Give the callback (if any) a chance to handle the extension */\n            if (cb != NULL) {\n                ret = cb(p_ctx, csr, &extn_oid, is_critical, *p, end_ext_octet);\n                if (ret != 0 && is_critical) {\n                    return ret;\n                }\n                *p = end_ext_octet;\n                continue;\n            }\n\n            /* No parser found, skip extension */\n            *p = end_ext_octet;\n\n            if (is_critical) {\n                /* Data is marked as critical: fail */\n                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                         MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);\n            }\n            continue;\n        }\n\n        /* Forbid repeated extensions */\n        if ((csr->ext_types & ext_type) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                     MBEDTLS_ERR_ASN1_INVALID_DATA);\n        }\n\n        csr->ext_types |= ext_type;\n\n        switch (ext_type) {\n            case MBEDTLS_X509_EXT_KEY_USAGE:\n                /* Parse key usage */\n                if ((ret = mbedtls_x509_get_key_usage(p, end_ext_data,\n                                                      &csr->key_usage)) != 0) {\n                    return ret;\n                }\n                break;\n\n            case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:\n                /* Parse subject alt name */\n                if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_data,\n                                                             &csr->subject_alt_names)) != 0) {\n                    return ret;\n                }\n                break;\n\n            case MBEDTLS_X509_EXT_NS_CERT_TYPE:\n                /* Parse netscape certificate type */\n                if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_data,\n                                                         &csr->ns_cert_type)) != 0) {\n                    return ret;\n                }\n                break;\n            default:\n                /*\n                 * If this is a non-critical extension, which the oid layer\n                 * supports, but there isn't an x509 parser for it,\n                 * skip the extension.\n                 */\n                if (is_critical) {\n                    return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;\n                } else {\n                    *p = end_ext_octet;\n                }\n        }\n    }\n\n    if (*p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n/*\n * Parse CSR attributes in DER format\n */\nstatic int x509_csr_parse_attributes(mbedtls_x509_csr *csr,\n                                     const unsigned char *start, const unsigned char *end,\n                                     mbedtls_x509_csr_ext_cb_t cb,\n                                     void *p_ctx)\n{\n    int ret;\n    size_t len;\n    unsigned char *end_attr_data;\n    unsigned char **p = (unsigned char **) &start;\n\n    while (*p < end) {\n        mbedtls_x509_buf attr_oid = { 0, 0, NULL };\n\n        if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n        end_attr_data = *p + len;\n\n        /* Get attribute ID */\n        if ((ret = mbedtls_asn1_get_tag(p, end_attr_data, &attr_oid.len,\n                                        MBEDTLS_ASN1_OID)) != 0) {\n            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n        }\n\n        attr_oid.tag = MBEDTLS_ASN1_OID;\n        attr_oid.p = *p;\n        *p += attr_oid.len;\n\n        /* Check that this is an extension-request attribute */\n        if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_CSR_EXT_REQ, &attr_oid) == 0) {\n            if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) {\n                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n            }\n\n            if ((ret = mbedtls_asn1_get_tag(p, end, &len,\n                                            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) !=\n                0) {\n                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);\n            }\n\n            if ((ret = x509_csr_parse_extensions(csr, p, *p + len, cb, p_ctx)) != 0) {\n                return ret;\n            }\n\n            if (*p != end_attr_data) {\n                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                         MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n            }\n        }\n\n        *p = end_attr_data;\n    }\n\n    if (*p != end) {\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n/*\n * Parse a CSR in DER format\n */\nstatic int mbedtls_x509_csr_parse_der_internal(mbedtls_x509_csr *csr,\n                                               const unsigned char *buf, size_t buflen,\n                                               mbedtls_x509_csr_ext_cb_t cb,\n                                               void *p_ctx)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len;\n    unsigned char *p, *end;\n    mbedtls_x509_buf sig_params;\n\n    memset(&sig_params, 0, sizeof(mbedtls_x509_buf));\n\n    /*\n     * Check for valid input\n     */\n    if (csr == NULL || buf == NULL || buflen == 0) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    mbedtls_x509_csr_init(csr);\n\n    /*\n     * first copy the raw DER data\n     */\n    p = mbedtls_calloc(1, len = buflen);\n\n    if (p == NULL) {\n        return MBEDTLS_ERR_X509_ALLOC_FAILED;\n    }\n\n    memcpy(p, buf, buflen);\n\n    csr->raw.p = p;\n    csr->raw.len = len;\n    end = p + len;\n\n    /*\n     *  CertificationRequest ::= SEQUENCE {\n     *       certificationRequestInfo CertificationRequestInfo,\n     *       signatureAlgorithm AlgorithmIdentifier,\n     *       signature          BIT STRING\n     *  }\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        mbedtls_x509_csr_free(csr);\n        return MBEDTLS_ERR_X509_INVALID_FORMAT;\n    }\n\n    if (len != (size_t) (end - p)) {\n        mbedtls_x509_csr_free(csr);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    /*\n     *  CertificationRequestInfo ::= SEQUENCE {\n     */\n    csr->cri.p = p;\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        mbedtls_x509_csr_free(csr);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);\n    }\n\n    end = p + len;\n    csr->cri.len = (size_t) (end - csr->cri.p);\n\n    /*\n     *  Version  ::=  INTEGER {  v1(0) }\n     */\n    if ((ret = x509_csr_get_version(&p, end, &csr->version)) != 0) {\n        mbedtls_x509_csr_free(csr);\n        return ret;\n    }\n\n    if (csr->version != 0) {\n        mbedtls_x509_csr_free(csr);\n        return MBEDTLS_ERR_X509_UNKNOWN_VERSION;\n    }\n\n    csr->version++;\n\n    /*\n     *  subject               Name\n     */\n    csr->subject_raw.p = p;\n\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {\n        mbedtls_x509_csr_free(csr);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);\n    }\n\n    if ((ret = mbedtls_x509_get_name(&p, p + len, &csr->subject)) != 0) {\n        mbedtls_x509_csr_free(csr);\n        return ret;\n    }\n\n    csr->subject_raw.len = (size_t) (p - csr->subject_raw.p);\n\n    /*\n     *  subjectPKInfo SubjectPublicKeyInfo\n     */\n    if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &csr->pk)) != 0) {\n        mbedtls_x509_csr_free(csr);\n        return ret;\n    }\n\n    /*\n     *  attributes    [0] Attributes\n     *\n     *  The list of possible attributes is open-ended, though RFC 2985\n     *  (PKCS#9) defines a few in section 5.4. We currently don't support any,\n     *  so we just ignore them. This is a safe thing to do as the worst thing\n     *  that could happen is that we issue a certificate that does not match\n     *  the requester's expectations - this cannot cause a violation of our\n     *  signature policies.\n     */\n    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,\n                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=\n        0) {\n        mbedtls_x509_csr_free(csr);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);\n    }\n\n    if ((ret = x509_csr_parse_attributes(csr, p, p + len, cb, p_ctx)) != 0) {\n        mbedtls_x509_csr_free(csr);\n        return ret;\n    }\n\n    p += len;\n\n    end = csr->raw.p + csr->raw.len;\n\n    /*\n     *  signatureAlgorithm   AlgorithmIdentifier,\n     *  signature            BIT STRING\n     */\n    if ((ret = mbedtls_x509_get_alg(&p, end, &csr->sig_oid, &sig_params)) != 0) {\n        mbedtls_x509_csr_free(csr);\n        return ret;\n    }\n\n    if ((ret = mbedtls_x509_get_sig_alg(&csr->sig_oid, &sig_params,\n                                        &csr->sig_md, &csr->sig_pk,\n                                        &csr->sig_opts)) != 0) {\n        mbedtls_x509_csr_free(csr);\n        return MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG;\n    }\n\n    if ((ret = mbedtls_x509_get_sig(&p, end, &csr->sig)) != 0) {\n        mbedtls_x509_csr_free(csr);\n        return ret;\n    }\n\n    if (p != end) {\n        mbedtls_x509_csr_free(csr);\n        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,\n                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);\n    }\n\n    return 0;\n}\n\n/*\n * Parse a CSR in DER format\n */\nint mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,\n                               const unsigned char *buf, size_t buflen)\n{\n    return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, NULL, NULL);\n}\n\n/*\n * Parse a CSR in DER format with callback for unknown extensions\n */\nint mbedtls_x509_csr_parse_der_with_ext_cb(mbedtls_x509_csr *csr,\n                                           const unsigned char *buf, size_t buflen,\n                                           mbedtls_x509_csr_ext_cb_t cb,\n                                           void *p_ctx)\n{\n    return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, cb, p_ctx);\n}\n\n/*\n * Parse a CSR, allowing for PEM or raw DER encoding\n */\nint mbedtls_x509_csr_parse(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen)\n{\n#if defined(MBEDTLS_PEM_PARSE_C)\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t use_len;\n    mbedtls_pem_context pem;\n#endif\n\n    /*\n     * Check for valid input\n     */\n    if (csr == NULL || buf == NULL || buflen == 0) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n#if defined(MBEDTLS_PEM_PARSE_C)\n    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */\n    if (buf[buflen - 1] == '\\0') {\n        mbedtls_pem_init(&pem);\n        ret = mbedtls_pem_read_buffer(&pem,\n                                      \"-----BEGIN CERTIFICATE REQUEST-----\",\n                                      \"-----END CERTIFICATE REQUEST-----\",\n                                      buf, NULL, 0, &use_len);\n        if (ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {\n            ret = mbedtls_pem_read_buffer(&pem,\n                                          \"-----BEGIN NEW CERTIFICATE REQUEST-----\",\n                                          \"-----END NEW CERTIFICATE REQUEST-----\",\n                                          buf, NULL, 0, &use_len);\n        }\n\n        if (ret == 0) {\n            /*\n             * Was PEM encoded, parse the result\n             */\n            ret = mbedtls_x509_csr_parse_der(csr, pem.buf, pem.buflen);\n        }\n\n        mbedtls_pem_free(&pem);\n        if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {\n            return ret;\n        }\n    }\n#endif /* MBEDTLS_PEM_PARSE_C */\n    return mbedtls_x509_csr_parse_der(csr, buf, buflen);\n}\n\n#if defined(MBEDTLS_FS_IO)\n/*\n * Load a CSR into the structure\n */\nint mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t n;\n    unsigned char *buf;\n\n    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_x509_csr_parse(csr, buf, n);\n\n    mbedtls_zeroize_and_free(buf, n);\n\n    return ret;\n}\n#endif /* MBEDTLS_FS_IO */\n\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\n#define BEFORE_COLON    14\n#define BC              \"14\"\n/*\n * Return an informational string about the CSR.\n */\nint mbedtls_x509_csr_info(char *buf, size_t size, const char *prefix,\n                          const mbedtls_x509_csr *csr)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t n;\n    char *p;\n    char key_size_str[BEFORE_COLON];\n\n    p = buf;\n    n = size;\n\n    ret = mbedtls_snprintf(p, n, \"%sCSR version   : %d\",\n                           prefix, csr->version);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    ret = mbedtls_snprintf(p, n, \"\\n%ssubject name  : \", prefix);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n    ret = mbedtls_x509_dn_gets(p, n, &csr->subject);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    ret = mbedtls_snprintf(p, n, \"\\n%ssigned using  : \", prefix);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    ret = mbedtls_x509_sig_alg_gets(p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md,\n                                    csr->sig_opts);\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON,\n                                            mbedtls_pk_get_name(&csr->pk))) != 0) {\n        return ret;\n    }\n\n    ret = mbedtls_snprintf(p, n, \"\\n%s%-\" BC \"s: %d bits\\n\", prefix, key_size_str,\n                           (int) mbedtls_pk_get_bitlen(&csr->pk));\n    MBEDTLS_X509_SAFE_SNPRINTF;\n\n    /*\n     * Optional extensions\n     */\n\n    if (csr->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {\n        ret = mbedtls_snprintf(p, n, \"\\n%ssubject alt name  :\", prefix);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n,\n                                                      &csr->subject_alt_names,\n                                                      prefix)) != 0) {\n            return ret;\n        }\n    }\n\n    if (csr->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) {\n        ret = mbedtls_snprintf(p, n, \"\\n%scert. type        : \", prefix);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        if ((ret = mbedtls_x509_info_cert_type(&p, &n, csr->ns_cert_type)) != 0) {\n            return ret;\n        }\n    }\n\n    if (csr->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) {\n        ret = mbedtls_snprintf(p, n, \"\\n%skey usage         : \", prefix);\n        MBEDTLS_X509_SAFE_SNPRINTF;\n\n        if ((ret = mbedtls_x509_info_key_usage(&p, &n, csr->key_usage)) != 0) {\n            return ret;\n        }\n    }\n\n    if (csr->ext_types != 0) {\n        ret = mbedtls_snprintf(p, n, \"\\n\");\n        MBEDTLS_X509_SAFE_SNPRINTF;\n    }\n\n    return (int) (size - n);\n}\n#endif /* MBEDTLS_X509_REMOVE_INFO */\n\n/*\n * Initialize a CSR\n */\nvoid mbedtls_x509_csr_init(mbedtls_x509_csr *csr)\n{\n    memset(csr, 0, sizeof(mbedtls_x509_csr));\n}\n\n/*\n * Unallocate all CSR data\n */\nvoid mbedtls_x509_csr_free(mbedtls_x509_csr *csr)\n{\n    if (csr == NULL) {\n        return;\n    }\n\n    mbedtls_pk_free(&csr->pk);\n\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)\n    mbedtls_free(csr->sig_opts);\n#endif\n\n    mbedtls_asn1_free_named_data_list_shallow(csr->subject.next);\n    mbedtls_asn1_sequence_free(csr->subject_alt_names.next);\n\n    if (csr->raw.p != NULL) {\n        mbedtls_zeroize_and_free(csr->raw.p, csr->raw.len);\n    }\n\n    mbedtls_platform_zeroize(csr, sizeof(mbedtls_x509_csr));\n}\n\n#endif /* MBEDTLS_X509_CSR_PARSE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/x509_internal.h",
    "content": "/**\n * \\file x509.h\n *\n * \\brief Internal part of the public \"x509.h\".\n */\n/*\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#ifndef MBEDTLS_X509_INTERNAL_H\n#define MBEDTLS_X509_INTERNAL_H\n#include \"mbedtls/private_access.h\"\n\n#include \"mbedtls/build_info.h\"\n\n#include \"mbedtls/x509.h\"\n#include \"mbedtls/asn1.h\"\n#include \"pk_internal.h\"\n\n#if defined(MBEDTLS_RSA_C)\n#include \"mbedtls/rsa.h\"\n#endif\n\nint mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,\n                          mbedtls_x509_name *cur);\nint mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end,\n                              mbedtls_x509_buf *alg);\nint mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end,\n                         mbedtls_x509_buf *alg, mbedtls_x509_buf *params);\n#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)\nint mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params,\n                                       mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,\n                                       int *salt_len);\n#endif\nint mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig);\nint mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,\n                             mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,\n                             void **sig_opts);\nint mbedtls_x509_get_time(unsigned char **p, const unsigned char *end,\n                          mbedtls_x509_time *t);\nint mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end,\n                            mbedtls_x509_buf *serial);\nint mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end,\n                         mbedtls_x509_buf *ext, int tag);\n#if !defined(MBEDTLS_X509_REMOVE_INFO)\nint mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid,\n                              mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,\n                              const void *sig_opts);\n#endif\nint mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name);\nint mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len,\n                               int critical, const unsigned char *val,\n                               size_t val_len);\nint mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start,\n                                  mbedtls_asn1_named_data *first);\nint mbedtls_x509_write_names(unsigned char **p, unsigned char *start,\n                             mbedtls_asn1_named_data *first);\nint mbedtls_x509_write_sig(unsigned char **p, unsigned char *start,\n                           const char *oid, size_t oid_len,\n                           unsigned char *sig, size_t size,\n                           mbedtls_pk_type_t pk_alg);\nint mbedtls_x509_get_ns_cert_type(unsigned char **p,\n                                  const unsigned char *end,\n                                  unsigned char *ns_cert_type);\nint mbedtls_x509_get_key_usage(unsigned char **p,\n                               const unsigned char *end,\n                               unsigned int *key_usage);\nint mbedtls_x509_get_subject_alt_name(unsigned char **p,\n                                      const unsigned char *end,\n                                      mbedtls_x509_sequence *subject_alt_name);\nint mbedtls_x509_get_subject_alt_name_ext(unsigned char **p,\n                                          const unsigned char *end,\n                                          mbedtls_x509_sequence *subject_alt_name);\nint mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,\n                                       const mbedtls_x509_sequence\n                                       *subject_alt_name,\n                                       const char *prefix);\nint mbedtls_x509_info_cert_type(char **buf, size_t *size,\n                                unsigned char ns_cert_type);\nint mbedtls_x509_info_key_usage(char **buf, size_t *size,\n                                unsigned int key_usage);\n\nint mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions,\n                                      const mbedtls_x509_san_list *san_list);\n\n#endif /* MBEDTLS_X509_INTERNAL_H */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/x509write.c",
    "content": "/*\n *  X.509 internal, common functions for writing\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n#include \"common.h\"\n#if defined(MBEDTLS_X509_CSR_WRITE_C) || defined(MBEDTLS_X509_CRT_WRITE_C)\n\n#include \"mbedtls/x509_crt.h\"\n#include \"x509_internal.h\"\n#include \"mbedtls/asn1write.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/oid.h\"\n#include \"mbedtls/platform.h\"\n#include \"mbedtls/platform_util.h\"\n\n#include <string.h>\n#include <stdint.h>\n\n#if defined(MBEDTLS_PEM_WRITE_C)\n#include \"mbedtls/pem.h\"\n#endif /* MBEDTLS_PEM_WRITE_C */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"psa/crypto.h\"\n#include \"mbedtls/psa_util.h\"\n#include \"md_psa.h\"\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#define CHECK_OVERFLOW_ADD(a, b) \\\n    do                         \\\n    {                           \\\n        if (a > SIZE_MAX - (b)) \\\n        { \\\n            return MBEDTLS_ERR_X509_BAD_INPUT_DATA; \\\n        }                            \\\n        a += b; \\\n    } while (0)\n\nint mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions,\n                                      const mbedtls_x509_san_list *san_list)\n{\n    int ret = 0;\n    const mbedtls_x509_san_list *cur;\n    unsigned char *buf;\n    unsigned char *p;\n    size_t len;\n    size_t buflen = 0;\n\n    /* Determine the maximum size of the SubjectAltName list */\n    for (cur = san_list; cur != NULL; cur = cur->next) {\n        /* Calculate size of the required buffer */\n        switch (cur->node.type) {\n            case MBEDTLS_X509_SAN_DNS_NAME:\n            case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:\n            case MBEDTLS_X509_SAN_IP_ADDRESS:\n            case MBEDTLS_X509_SAN_RFC822_NAME:\n                /* length of value for each name entry,\n                 * maximum 4 bytes for the length field,\n                 * 1 byte for the tag/type.\n                 */\n                CHECK_OVERFLOW_ADD(buflen, cur->node.san.unstructured_name.len);\n                CHECK_OVERFLOW_ADD(buflen, 4 + 1);\n                break;\n            case MBEDTLS_X509_SAN_DIRECTORY_NAME:\n            {\n                const mbedtls_asn1_named_data *chunk = &cur->node.san.directory_name;\n                while (chunk != NULL) {\n                    // Max 4 bytes for length, +1 for tag,\n                    // additional 4 max for length, +1 for tag.\n                    // See x509_write_name for more information.\n                    CHECK_OVERFLOW_ADD(buflen, 4 + 1 + 4 + 1);\n                    CHECK_OVERFLOW_ADD(buflen, chunk->oid.len);\n                    CHECK_OVERFLOW_ADD(buflen, chunk->val.len);\n                    chunk = chunk->next;\n                }\n                CHECK_OVERFLOW_ADD(buflen, 4 + 1);\n                break;\n            }\n            default:\n                /* Not supported - return. */\n                return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;\n        }\n    }\n\n    /* Add the extra length field and tag */\n    CHECK_OVERFLOW_ADD(buflen, 4 + 1);\n\n    /* Allocate buffer */\n    buf = mbedtls_calloc(1, buflen);\n    if (buf == NULL) {\n        return MBEDTLS_ERR_ASN1_ALLOC_FAILED;\n    }\n    p = buf + buflen;\n\n    /* Write ASN.1-based structure */\n    cur = san_list;\n    len = 0;\n    while (cur != NULL) {\n        size_t single_san_len = 0;\n        switch (cur->node.type) {\n            case MBEDTLS_X509_SAN_DNS_NAME:\n            case MBEDTLS_X509_SAN_RFC822_NAME:\n            case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:\n            case MBEDTLS_X509_SAN_IP_ADDRESS:\n            {\n                const unsigned char *unstructured_name =\n                    (const unsigned char *) cur->node.san.unstructured_name.p;\n                size_t unstructured_name_len = cur->node.san.unstructured_name.len;\n\n                MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len,\n                                             mbedtls_asn1_write_raw_buffer(\n                                                 &p, buf,\n                                                 unstructured_name, unstructured_name_len));\n                MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_asn1_write_len(\n                                                 &p, buf, unstructured_name_len));\n                MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len,\n                                             mbedtls_asn1_write_tag(\n                                                 &p, buf,\n                                                 MBEDTLS_ASN1_CONTEXT_SPECIFIC | cur->node.type));\n            }\n            break;\n            case MBEDTLS_X509_SAN_DIRECTORY_NAME:\n                MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len,\n                                             mbedtls_x509_write_names(&p, buf,\n                                                                      (mbedtls_asn1_named_data *) &\n                                                                      cur->node\n                                                                      .san.directory_name));\n                MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len,\n                                             mbedtls_asn1_write_len(&p, buf, single_san_len));\n                MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len,\n                                             mbedtls_asn1_write_tag(&p, buf,\n                                                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC |\n                                                                    MBEDTLS_ASN1_CONSTRUCTED |\n                                                                    MBEDTLS_X509_SAN_DIRECTORY_NAME));\n                break;\n            default:\n                /* Error out on an unsupported SAN */\n                ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;\n                goto cleanup;\n        }\n        cur = cur->next;\n        /* check for overflow */\n        if (len > SIZE_MAX - single_san_len) {\n            ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n            goto cleanup;\n        }\n        len += single_san_len;\n    }\n\n    MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&p, buf, len));\n    MBEDTLS_ASN1_CHK_CLEANUP_ADD(len,\n                                 mbedtls_asn1_write_tag(&p, buf,\n                                                        MBEDTLS_ASN1_CONSTRUCTED |\n                                                        MBEDTLS_ASN1_SEQUENCE));\n\n    ret = mbedtls_x509_set_extension(extensions,\n                                     MBEDTLS_OID_SUBJECT_ALT_NAME,\n                                     MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME),\n                                     0,\n                                     buf + buflen - len, len);\n\n    /* If we exceeded the allocated buffer it means that maximum size of the SubjectAltName list\n     * was incorrectly calculated and memory is corrupted. */\n    if (p < buf) {\n        ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;\n    }\ncleanup:\n    mbedtls_free(buf);\n    return ret;\n}\n\n#endif /* MBEDTLS_X509_CSR_WRITE_C || MBEDTLS_X509_CRT_WRITE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/x509write_crt.c",
    "content": "/*\n *  X.509 certificate writing\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n * References:\n * - certificates: RFC 5280, updated by RFC 6818\n * - CSRs: PKCS#10 v1.7 aka RFC 2986\n * - attributes: PKCS#9 v2.0 aka RFC 2985\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_X509_CRT_WRITE_C)\n\n#include \"mbedtls/x509_crt.h\"\n#include \"x509_internal.h\"\n#include \"mbedtls/asn1write.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/oid.h\"\n#include \"mbedtls/platform.h\"\n#include \"mbedtls/platform_util.h\"\n#include \"mbedtls/md.h\"\n\n#include <string.h>\n#include <stdint.h>\n\n#if defined(MBEDTLS_PEM_WRITE_C)\n#include \"mbedtls/pem.h\"\n#endif /* MBEDTLS_PEM_WRITE_C */\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"psa/crypto.h\"\n#include \"psa_util_internal.h\"\n#include \"mbedtls/psa_util.h\"\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\nvoid mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_x509write_cert));\n\n    ctx->version = MBEDTLS_X509_CRT_VERSION_3;\n}\n\nvoid mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_asn1_free_named_data_list(&ctx->subject);\n    mbedtls_asn1_free_named_data_list(&ctx->issuer);\n    mbedtls_asn1_free_named_data_list(&ctx->extensions);\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_cert));\n}\n\nvoid mbedtls_x509write_crt_set_version(mbedtls_x509write_cert *ctx,\n                                       int version)\n{\n    ctx->version = version;\n}\n\nvoid mbedtls_x509write_crt_set_md_alg(mbedtls_x509write_cert *ctx,\n                                      mbedtls_md_type_t md_alg)\n{\n    ctx->md_alg = md_alg;\n}\n\nvoid mbedtls_x509write_crt_set_subject_key(mbedtls_x509write_cert *ctx,\n                                           mbedtls_pk_context *key)\n{\n    ctx->subject_key = key;\n}\n\nvoid mbedtls_x509write_crt_set_issuer_key(mbedtls_x509write_cert *ctx,\n                                          mbedtls_pk_context *key)\n{\n    ctx->issuer_key = key;\n}\n\nint mbedtls_x509write_crt_set_subject_name(mbedtls_x509write_cert *ctx,\n                                           const char *subject_name)\n{\n    mbedtls_asn1_free_named_data_list(&ctx->subject);\n    return mbedtls_x509_string_to_names(&ctx->subject, subject_name);\n}\n\nint mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert *ctx,\n                                          const char *issuer_name)\n{\n    mbedtls_asn1_free_named_data_list(&ctx->issuer);\n    return mbedtls_x509_string_to_names(&ctx->issuer, issuer_name);\n}\n\n#if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)\nint mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert *ctx,\n                                     const mbedtls_mpi *serial)\n{\n    int ret;\n    size_t tmp_len;\n\n    /* Ensure that the MPI value fits into the buffer */\n    tmp_len = mbedtls_mpi_size(serial);\n    if (tmp_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    ctx->serial_len = tmp_len;\n\n    ret = mbedtls_mpi_write_binary(serial, ctx->serial, tmp_len);\n    if (ret < 0) {\n        return ret;\n    }\n\n    return 0;\n}\n#endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED\n\nint mbedtls_x509write_crt_set_serial_raw(mbedtls_x509write_cert *ctx,\n                                         unsigned char *serial, size_t serial_len)\n{\n    if (serial_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    ctx->serial_len = serial_len;\n    memcpy(ctx->serial, serial, serial_len);\n\n    return 0;\n}\n\nint mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx,\n                                       const char *not_before,\n                                       const char *not_after)\n{\n    if (strlen(not_before) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ||\n        strlen(not_after)  != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n    strncpy(ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN);\n    strncpy(ctx->not_after, not_after, MBEDTLS_X509_RFC5280_UTC_TIME_LEN);\n    ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';\n    ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';\n\n    return 0;\n}\n\nint mbedtls_x509write_crt_set_subject_alternative_name(mbedtls_x509write_cert *ctx,\n                                                       const mbedtls_x509_san_list *san_list)\n{\n    return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list);\n}\n\n\nint mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert *ctx,\n                                        const char *oid, size_t oid_len,\n                                        int critical,\n                                        const unsigned char *val, size_t val_len)\n{\n    return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len,\n                                      critical, val, val_len);\n}\n\nint mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert *ctx,\n                                                int is_ca, int max_pathlen)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char buf[9];\n    unsigned char *c = buf + sizeof(buf);\n    size_t len = 0;\n\n    memset(buf, 0, sizeof(buf));\n\n    if (is_ca && max_pathlen > 127) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    if (is_ca) {\n        if (max_pathlen >= 0) {\n            MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf,\n                                                             max_pathlen));\n        }\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_bool(&c, buf, 1));\n    }\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf,\n                                                     MBEDTLS_ASN1_CONSTRUCTED |\n                                                     MBEDTLS_ASN1_SEQUENCE));\n\n    return\n        mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,\n                                            MBEDTLS_OID_SIZE(MBEDTLS_OID_BASIC_CONSTRAINTS),\n                                            is_ca, buf + sizeof(buf) - len, len);\n}\n\n#if defined(MBEDTLS_MD_CAN_SHA1)\nstatic int mbedtls_x509write_crt_set_key_identifier(mbedtls_x509write_cert *ctx,\n                                                    int is_ca,\n                                                    unsigned char tag)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */\n    unsigned char *c = buf + sizeof(buf);\n    size_t len = 0;\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    size_t hash_length;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    memset(buf, 0, sizeof(buf));\n    MBEDTLS_ASN1_CHK_ADD(len,\n                         mbedtls_pk_write_pubkey(&c,\n                                                 buf,\n                                                 is_ca ?\n                                                 ctx->issuer_key :\n                                                 ctx->subject_key));\n\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    status = psa_hash_compute(PSA_ALG_SHA_1,\n                              buf + sizeof(buf) - len,\n                              len,\n                              buf + sizeof(buf) - 20,\n                              20,\n                              &hash_length);\n    if (status != PSA_SUCCESS) {\n        return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;\n    }\n#else\n    ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1),\n                     buf + sizeof(buf) - len, len,\n                     buf + sizeof(buf) - 20);\n    if (ret != 0) {\n        return ret;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    c = buf + sizeof(buf) - 20;\n    len = 20;\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, tag));\n\n    if (is_ca) { // writes AuthorityKeyIdentifier sequence\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));\n        MBEDTLS_ASN1_CHK_ADD(len,\n                             mbedtls_asn1_write_tag(&c,\n                                                    buf,\n                                                    MBEDTLS_ASN1_CONSTRUCTED |\n                                                    MBEDTLS_ASN1_SEQUENCE));\n    }\n\n    if (is_ca) {\n        return mbedtls_x509write_crt_set_extension(ctx,\n                                                   MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,\n                                                   MBEDTLS_OID_SIZE(\n                                                       MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER),\n                                                   0, buf + sizeof(buf) - len, len);\n    } else {\n        return mbedtls_x509write_crt_set_extension(ctx,\n                                                   MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,\n                                                   MBEDTLS_OID_SIZE(\n                                                       MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER),\n                                                   0, buf + sizeof(buf) - len, len);\n    }\n}\n\nint mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx)\n{\n    return mbedtls_x509write_crt_set_key_identifier(ctx,\n                                                    0,\n                                                    MBEDTLS_ASN1_OCTET_STRING);\n}\n\nint mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx)\n{\n    return mbedtls_x509write_crt_set_key_identifier(ctx,\n                                                    1,\n                                                    (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0));\n}\n#endif /* MBEDTLS_MD_CAN_SHA1 */\n\nint mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert *ctx,\n                                        unsigned int key_usage)\n{\n    unsigned char buf[5] = { 0 }, ku[2] = { 0 };\n    unsigned char *c;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |\n                                      MBEDTLS_X509_KU_NON_REPUDIATION   |\n                                      MBEDTLS_X509_KU_KEY_ENCIPHERMENT  |\n                                      MBEDTLS_X509_KU_DATA_ENCIPHERMENT |\n                                      MBEDTLS_X509_KU_KEY_AGREEMENT     |\n                                      MBEDTLS_X509_KU_KEY_CERT_SIGN     |\n                                      MBEDTLS_X509_KU_CRL_SIGN          |\n                                      MBEDTLS_X509_KU_ENCIPHER_ONLY     |\n                                      MBEDTLS_X509_KU_DECIPHER_ONLY;\n\n    /* Check that nothing other than the allowed flags is set */\n    if ((key_usage & ~allowed_bits) != 0) {\n        return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;\n    }\n\n    c = buf + 5;\n    MBEDTLS_PUT_UINT16_LE(key_usage, ku, 0);\n    ret = mbedtls_asn1_write_named_bitstring(&c, buf, ku, 9);\n\n    if (ret < 0) {\n        return ret;\n    } else if (ret < 3 || ret > 5) {\n        return MBEDTLS_ERR_X509_INVALID_FORMAT;\n    }\n\n    ret = mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_KEY_USAGE,\n                                              MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE),\n                                              1, c, (size_t) ret);\n    if (ret != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\nint mbedtls_x509write_crt_set_ext_key_usage(mbedtls_x509write_cert *ctx,\n                                            const mbedtls_asn1_sequence *exts)\n{\n    unsigned char buf[256];\n    unsigned char *c = buf + sizeof(buf);\n    int ret;\n    size_t len = 0;\n    const mbedtls_asn1_sequence *last_ext = NULL;\n    const mbedtls_asn1_sequence *ext;\n\n    memset(buf, 0, sizeof(buf));\n\n    /* We need at least one extension: SEQUENCE SIZE (1..MAX) OF KeyPurposeId */\n    if (exts == NULL) {\n        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n    }\n\n    /* Iterate over exts backwards, so we write them out in the requested order */\n    while (last_ext != exts) {\n        for (ext = exts; ext->next != last_ext; ext = ext->next) {\n        }\n        if (ext->buf.tag != MBEDTLS_ASN1_OID) {\n            return MBEDTLS_ERR_X509_BAD_INPUT_DATA;\n        }\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf, ext->buf.p, ext->buf.len));\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, ext->buf.len));\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_OID));\n        last_ext = ext;\n    }\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));\n    MBEDTLS_ASN1_CHK_ADD(len,\n                         mbedtls_asn1_write_tag(&c, buf,\n                                                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));\n\n    return mbedtls_x509write_crt_set_extension(ctx,\n                                               MBEDTLS_OID_EXTENDED_KEY_USAGE,\n                                               MBEDTLS_OID_SIZE(MBEDTLS_OID_EXTENDED_KEY_USAGE),\n                                               1, c, len);\n}\n\nint mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert *ctx,\n                                           unsigned char ns_cert_type)\n{\n    unsigned char buf[4] = { 0 };\n    unsigned char *c;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    c = buf + 4;\n\n    ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8);\n    if (ret < 3 || ret > 4) {\n        return ret;\n    }\n\n    ret = mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE,\n                                              MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE),\n                                              0, c, (size_t) ret);\n    if (ret != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\nstatic int x509_write_time(unsigned char **p, unsigned char *start,\n                           const char *t, size_t size)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t len = 0;\n\n    /*\n     * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)\n     */\n    if (t[0] < '2' || (t[0] == '2' && t[1] == '0' && t[2] < '5')) {\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,\n                                                                (const unsigned char *) t + 2,\n                                                                size - 2));\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,\n                                                         MBEDTLS_ASN1_UTC_TIME));\n    } else {\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,\n                                                                (const unsigned char *) t,\n                                                                size));\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,\n                                                         MBEDTLS_ASN1_GENERALIZED_TIME));\n    }\n\n    return (int) len;\n}\n\nint mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx,\n                              unsigned char *buf, size_t size,\n                              int (*f_rng)(void *, unsigned char *, size_t),\n                              void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const char *sig_oid;\n    size_t sig_oid_len = 0;\n    unsigned char *c, *c2;\n    unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE];\n    size_t hash_length = 0;\n    unsigned char hash[MBEDTLS_MD_MAX_SIZE];\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;\n    psa_algorithm_t psa_algorithm;\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;\n    size_t len = 0;\n    mbedtls_pk_type_t pk_alg;\n    int write_sig_null_par;\n\n    /*\n     * Prepare data to be signed at the end of the target buffer\n     */\n    c = buf + size;\n\n    /* Signature algorithm needed in TBS, and later for actual signature */\n\n    /* There's no direct way of extracting a signature algorithm\n     * (represented as an element of mbedtls_pk_type_t) from a PK instance. */\n    if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_RSA)) {\n        pk_alg = MBEDTLS_PK_RSA;\n    } else if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_ECDSA)) {\n        pk_alg = MBEDTLS_PK_ECDSA;\n    } else {\n        return MBEDTLS_ERR_X509_INVALID_ALG;\n    }\n\n    if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg,\n                                              &sig_oid, &sig_oid_len)) != 0) {\n        return ret;\n    }\n\n    /*\n     *  Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension\n     */\n\n    /* Only for v3 */\n    if (ctx->version == MBEDTLS_X509_CRT_VERSION_3) {\n        MBEDTLS_ASN1_CHK_ADD(len,\n                             mbedtls_x509_write_extensions(&c,\n                                                           buf, ctx->extensions));\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));\n        MBEDTLS_ASN1_CHK_ADD(len,\n                             mbedtls_asn1_write_tag(&c, buf,\n                                                    MBEDTLS_ASN1_CONSTRUCTED |\n                                                    MBEDTLS_ASN1_SEQUENCE));\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));\n        MBEDTLS_ASN1_CHK_ADD(len,\n                             mbedtls_asn1_write_tag(&c, buf,\n                                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC |\n                                                    MBEDTLS_ASN1_CONSTRUCTED | 3));\n    }\n\n    /*\n     *  SubjectPublicKeyInfo\n     */\n    MBEDTLS_ASN1_CHK_ADD(pub_len,\n                         mbedtls_pk_write_pubkey_der(ctx->subject_key,\n                                                     buf, (size_t) (c - buf)));\n    c -= pub_len;\n    len += pub_len;\n\n    /*\n     *  Subject  ::=  Name\n     */\n    MBEDTLS_ASN1_CHK_ADD(len,\n                         mbedtls_x509_write_names(&c, buf,\n                                                  ctx->subject));\n\n    /*\n     *  Validity ::= SEQUENCE {\n     *       notBefore      Time,\n     *       notAfter       Time }\n     */\n    sub_len = 0;\n\n    MBEDTLS_ASN1_CHK_ADD(sub_len,\n                         x509_write_time(&c, buf, ctx->not_after,\n                                         MBEDTLS_X509_RFC5280_UTC_TIME_LEN));\n\n    MBEDTLS_ASN1_CHK_ADD(sub_len,\n                         x509_write_time(&c, buf, ctx->not_before,\n                                         MBEDTLS_X509_RFC5280_UTC_TIME_LEN));\n\n    len += sub_len;\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, sub_len));\n    MBEDTLS_ASN1_CHK_ADD(len,\n                         mbedtls_asn1_write_tag(&c, buf,\n                                                MBEDTLS_ASN1_CONSTRUCTED |\n                                                MBEDTLS_ASN1_SEQUENCE));\n\n    /*\n     *  Issuer  ::=  Name\n     */\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf,\n                                                       ctx->issuer));\n\n    /*\n     *  Signature   ::=  AlgorithmIdentifier\n     */\n    if (pk_alg == MBEDTLS_PK_ECDSA) {\n        /*\n         * The AlgorithmIdentifier's parameters field must be absent for DSA/ECDSA signature\n         * algorithms, see https://www.rfc-editor.org/rfc/rfc5480#page-17 and\n         * https://www.rfc-editor.org/rfc/rfc5758#section-3.\n         */\n        write_sig_null_par = 0;\n    } else {\n        write_sig_null_par = 1;\n    }\n    MBEDTLS_ASN1_CHK_ADD(len,\n                         mbedtls_asn1_write_algorithm_identifier_ext(&c, buf,\n                                                                     sig_oid, strlen(sig_oid),\n                                                                     0, write_sig_null_par));\n\n    /*\n     *  Serial   ::=  INTEGER\n     *\n     * Written data is:\n     * - \"ctx->serial_len\" bytes for the raw serial buffer\n     *   - if MSb of \"serial\" is 1, then prepend an extra 0x00 byte\n     * - 1 byte for the length\n     * - 1 byte for the TAG\n     */\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf,\n                                                            ctx->serial, ctx->serial_len));\n    if (*c & 0x80) {\n        if (c - buf < 1) {\n            return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;\n        }\n        *(--c) = 0x0;\n        len++;\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf,\n                                                         ctx->serial_len + 1));\n    } else {\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf,\n                                                         ctx->serial_len));\n    }\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf,\n                                                     MBEDTLS_ASN1_INTEGER));\n\n    /*\n     *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }\n     */\n\n    /* Can be omitted for v1 */\n    if (ctx->version != MBEDTLS_X509_CRT_VERSION_1) {\n        sub_len = 0;\n        MBEDTLS_ASN1_CHK_ADD(sub_len,\n                             mbedtls_asn1_write_int(&c, buf, ctx->version));\n        len += sub_len;\n        MBEDTLS_ASN1_CHK_ADD(len,\n                             mbedtls_asn1_write_len(&c, buf, sub_len));\n        MBEDTLS_ASN1_CHK_ADD(len,\n                             mbedtls_asn1_write_tag(&c, buf,\n                                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC |\n                                                    MBEDTLS_ASN1_CONSTRUCTED | 0));\n    }\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));\n    MBEDTLS_ASN1_CHK_ADD(len,\n                         mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |\n                                                MBEDTLS_ASN1_SEQUENCE));\n\n    /*\n     * Make signature\n     */\n\n    /* Compute hash of CRT. */\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    psa_algorithm = mbedtls_md_psa_alg_from_type(ctx->md_alg);\n\n    status = psa_hash_compute(psa_algorithm,\n                              c,\n                              len,\n                              hash,\n                              sizeof(hash),\n                              &hash_length);\n    if (status != PSA_SUCCESS) {\n        return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;\n    }\n#else\n    if ((ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c,\n                          len, hash)) != 0) {\n        return ret;\n    }\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n\n    if ((ret = mbedtls_pk_sign(ctx->issuer_key, ctx->md_alg,\n                               hash, hash_length, sig, sizeof(sig), &sig_len,\n                               f_rng, p_rng)) != 0) {\n        return ret;\n    }\n\n    /* Move CRT to the front of the buffer to have space\n     * for the signature. */\n    memmove(buf, c, len);\n    c = buf + len;\n\n    /* Add signature at the end of the buffer,\n     * making sure that it doesn't underflow\n     * into the CRT buffer. */\n    c2 = buf + size;\n    MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, mbedtls_x509_write_sig(&c2, c,\n                                                                 sig_oid, sig_oid_len,\n                                                                 sig, sig_len, pk_alg));\n\n    /*\n     * Memory layout after this step:\n     *\n     * buf       c=buf+len                c2            buf+size\n     * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm]\n     */\n\n    /* Move raw CRT to just before the signature. */\n    c = c2 - len;\n    memmove(c, buf, len);\n\n    len += sig_and_oid_len;\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf,\n                                                     MBEDTLS_ASN1_CONSTRUCTED |\n                                                     MBEDTLS_ASN1_SEQUENCE));\n\n    return (int) len;\n}\n\n#define PEM_BEGIN_CRT           \"-----BEGIN CERTIFICATE-----\\n\"\n#define PEM_END_CRT             \"-----END CERTIFICATE-----\\n\"\n\n#if defined(MBEDTLS_PEM_WRITE_C)\nint mbedtls_x509write_crt_pem(mbedtls_x509write_cert *crt,\n                              unsigned char *buf, size_t size,\n                              int (*f_rng)(void *, unsigned char *, size_t),\n                              void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t olen;\n\n    if ((ret = mbedtls_x509write_crt_der(crt, buf, size,\n                                         f_rng, p_rng)) < 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CRT, PEM_END_CRT,\n                                        buf + size - ret, ret,\n                                        buf, size, &olen)) != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_PEM_WRITE_C */\n\n#endif /* MBEDTLS_X509_CRT_WRITE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/library/x509write_csr.c",
    "content": "/*\n *  X.509 Certificate Signing Request writing\n *\n *  Copyright The Mbed TLS Contributors\n *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later\n */\n/*\n * References:\n * - CSRs: PKCS#10 v1.7 aka RFC 2986\n * - attributes: PKCS#9 v2.0 aka RFC 2985\n */\n\n#include \"common.h\"\n\n#if defined(MBEDTLS_X509_CSR_WRITE_C)\n\n#include \"x509_internal.h\"\n#include \"mbedtls/x509_csr.h\"\n#include \"mbedtls/asn1write.h\"\n#include \"mbedtls/error.h\"\n#include \"mbedtls/oid.h\"\n#include \"mbedtls/platform_util.h\"\n\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n#include \"psa/crypto.h\"\n#include \"psa_util_internal.h\"\n#include \"mbedtls/psa_util.h\"\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n#include <string.h>\n#include <stdlib.h>\n\n#if defined(MBEDTLS_PEM_WRITE_C)\n#include \"mbedtls/pem.h\"\n#endif\n\n#include \"mbedtls/platform.h\"\n\nvoid mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx)\n{\n    memset(ctx, 0, sizeof(mbedtls_x509write_csr));\n}\n\nvoid mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx)\n{\n    if (ctx == NULL) {\n        return;\n    }\n\n    mbedtls_asn1_free_named_data_list(&ctx->subject);\n    mbedtls_asn1_free_named_data_list(&ctx->extensions);\n\n    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_csr));\n}\n\nvoid mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg)\n{\n    ctx->md_alg = md_alg;\n}\n\nvoid mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, mbedtls_pk_context *key)\n{\n    ctx->key = key;\n}\n\nint mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx,\n                                           const char *subject_name)\n{\n    mbedtls_asn1_free_named_data_list(&ctx->subject);\n    return mbedtls_x509_string_to_names(&ctx->subject, subject_name);\n}\n\nint mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx,\n                                        const char *oid, size_t oid_len,\n                                        int critical,\n                                        const unsigned char *val, size_t val_len)\n{\n    return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len,\n                                      critical, val, val_len);\n}\n\nint mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx,\n                                                       const mbedtls_x509_san_list *san_list)\n{\n    return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list);\n}\n\nint mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage)\n{\n    unsigned char buf[4] = { 0 };\n    unsigned char *c;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    c = buf + 4;\n\n    ret = mbedtls_asn1_write_named_bitstring(&c, buf, &key_usage, 8);\n    if (ret < 3 || ret > 4) {\n        return ret;\n    }\n\n    ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_KEY_USAGE,\n                                              MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE),\n                                              0, c, (size_t) ret);\n    if (ret != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\nint mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx,\n                                           unsigned char ns_cert_type)\n{\n    unsigned char buf[4] = { 0 };\n    unsigned char *c;\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n\n    c = buf + 4;\n\n    ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8);\n    if (ret < 3 || ret > 4) {\n        return ret;\n    }\n\n    ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE,\n                                              MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE),\n                                              0, c, (size_t) ret);\n    if (ret != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n\nstatic int x509write_csr_der_internal(mbedtls_x509write_csr *ctx,\n                                      unsigned char *buf,\n                                      size_t size,\n                                      unsigned char *sig, size_t sig_size,\n                                      int (*f_rng)(void *, unsigned char *, size_t),\n                                      void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    const char *sig_oid;\n    size_t sig_oid_len = 0;\n    unsigned char *c, *c2;\n    unsigned char hash[MBEDTLS_MD_MAX_SIZE];\n    size_t pub_len = 0, sig_and_oid_len = 0, sig_len;\n    size_t len = 0;\n    mbedtls_pk_type_t pk_alg;\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    size_t hash_len;\n    psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(ctx->md_alg);\n#endif /* MBEDTLS_USE_PSA_CRYPTO */\n\n    /* Write the CSR backwards starting from the end of buf */\n    c = buf + size;\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf,\n                                                            ctx->extensions));\n\n    if (len) {\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));\n        MBEDTLS_ASN1_CHK_ADD(len,\n                             mbedtls_asn1_write_tag(\n                                 &c, buf,\n                                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));\n\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));\n        MBEDTLS_ASN1_CHK_ADD(len,\n                             mbedtls_asn1_write_tag(\n                                 &c, buf,\n                                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET));\n\n        MBEDTLS_ASN1_CHK_ADD(len,\n                             mbedtls_asn1_write_oid(\n                                 &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ,\n                                 MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ)));\n\n        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));\n        MBEDTLS_ASN1_CHK_ADD(len,\n                             mbedtls_asn1_write_tag(\n                                 &c, buf,\n                                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));\n    }\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));\n    MBEDTLS_ASN1_CHK_ADD(len,\n                         mbedtls_asn1_write_tag(\n                             &c, buf,\n                             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC));\n\n    MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->key,\n                                                              buf, (size_t) (c - buf)));\n    c -= pub_len;\n    len += pub_len;\n\n    /*\n     *  Subject  ::=  Name\n     */\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf,\n                                                       ctx->subject));\n\n    /*\n     *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }\n     */\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0));\n\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));\n    MBEDTLS_ASN1_CHK_ADD(len,\n                         mbedtls_asn1_write_tag(\n                             &c, buf,\n                             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));\n\n    /*\n     * Sign the written CSR data into the sig buffer\n     * Note: hash errors can happen only after an internal error\n     */\n#if defined(MBEDTLS_USE_PSA_CRYPTO)\n    if (psa_hash_compute(hash_alg,\n                         c,\n                         len,\n                         hash,\n                         sizeof(hash),\n                         &hash_len) != PSA_SUCCESS) {\n        return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;\n    }\n#else /* MBEDTLS_USE_PSA_CRYPTO */\n    ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash);\n    if (ret != 0) {\n        return ret;\n    }\n#endif\n    if ((ret = mbedtls_pk_sign(ctx->key, ctx->md_alg, hash, 0,\n                               sig, sig_size, &sig_len,\n                               f_rng, p_rng)) != 0) {\n        return ret;\n    }\n\n    if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_RSA)) {\n        pk_alg = MBEDTLS_PK_RSA;\n    } else if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_ECDSA)) {\n        pk_alg = MBEDTLS_PK_ECDSA;\n    } else {\n        return MBEDTLS_ERR_X509_INVALID_ALG;\n    }\n\n    if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg,\n                                              &sig_oid, &sig_oid_len)) != 0) {\n        return ret;\n    }\n\n    /*\n     * Move the written CSR data to the start of buf to create space for\n     * writing the signature into buf.\n     */\n    memmove(buf, c, len);\n\n    /*\n     * Write sig and its OID into buf backwards from the end of buf.\n     * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len\n     * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed.\n     */\n    c2 = buf + size;\n    MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len,\n                         mbedtls_x509_write_sig(&c2, buf + len, sig_oid, sig_oid_len,\n                                                sig, sig_len, pk_alg));\n\n    /*\n     * Compact the space between the CSR data and signature by moving the\n     * CSR data to the start of the signature.\n     */\n    c2 -= len;\n    memmove(c2, buf, len);\n\n    /* ASN encode the total size and tag the CSR data with it. */\n    len += sig_and_oid_len;\n    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c2, buf, len));\n    MBEDTLS_ASN1_CHK_ADD(len,\n                         mbedtls_asn1_write_tag(\n                             &c2, buf,\n                             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));\n\n    /* Zero the unused bytes at the start of buf */\n    memset(buf, 0, (size_t) (c2 - buf));\n\n    return (int) len;\n}\n\nint mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf,\n                              size_t size,\n                              int (*f_rng)(void *, unsigned char *, size_t),\n                              void *p_rng)\n{\n    int ret;\n    unsigned char *sig;\n\n    if ((sig = mbedtls_calloc(1, MBEDTLS_PK_SIGNATURE_MAX_SIZE)) == NULL) {\n        return MBEDTLS_ERR_X509_ALLOC_FAILED;\n    }\n\n    ret = x509write_csr_der_internal(ctx, buf, size,\n                                     sig, MBEDTLS_PK_SIGNATURE_MAX_SIZE,\n                                     f_rng, p_rng);\n\n    mbedtls_free(sig);\n\n    return ret;\n}\n\n#define PEM_BEGIN_CSR           \"-----BEGIN CERTIFICATE REQUEST-----\\n\"\n#define PEM_END_CSR             \"-----END CERTIFICATE REQUEST-----\\n\"\n\n#if defined(MBEDTLS_PEM_WRITE_C)\nint mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,\n                              int (*f_rng)(void *, unsigned char *, size_t),\n                              void *p_rng)\n{\n    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n    size_t olen = 0;\n\n    if ((ret = mbedtls_x509write_csr_der(ctx, buf, size,\n                                         f_rng, p_rng)) < 0) {\n        return ret;\n    }\n\n    if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CSR, PEM_END_CSR,\n                                        buf + size - ret,\n                                        ret, buf, size, &olen)) != 0) {\n        return ret;\n    }\n\n    return 0;\n}\n#endif /* MBEDTLS_PEM_WRITE_C */\n\n#endif /* MBEDTLS_X509_CSR_WRITE_C */\n"
  },
  {
    "path": "thirdparty/mbedtls/mbedtls.patch",
    "content": "diff -ur mbedtls.orig/include/mbedtls/check_config.h mbedtls/include/mbedtls/check_config.h\n--- mbedtls.orig/include/mbedtls/check_config.h\t2026-01-15 22:33:48.318284760 +0300\n+++ mbedtls/include/mbedtls/check_config.h\t2026-01-15 22:34:04.062379589 +0300\n@@ -247,9 +247,10 @@\n #if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) &&  !defined(MBEDTLS_HAS_MEMSAN)\n #error \"MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer\"\n #endif\n-#if defined(MBEDTLS_HAS_MEMSAN) && defined(MBEDTLS_HAVE_ASM)\n-#error \"MemorySanitizer does not support assembly implementation\"\n-#endif\n+// skip this check for now because V test-self need a `fsanitizer`\n+//#if defined(MBEDTLS_HAS_MEMSAN) && defined(MBEDTLS_HAVE_ASM)\n+//#error \"MemorySanitizer does not support assembly implementation\"\n+//#endif\n #undef MBEDTLS_HAS_MEMSAN // temporary macro defined above\n \n #if defined(MBEDTLS_CCM_C) && \\\ndiff -ur mbedtls.orig/include/mbedtls/mbedtls_config.h mbedtls/include/mbedtls/mbedtls_config.h\n--- mbedtls.orig/include/mbedtls/mbedtls_config.h\t2026-01-15 22:33:48.318683074 +0300\n+++ mbedtls/include/mbedtls/mbedtls_config.h\t2026-01-15 22:34:04.062667214 +0300\n@@ -4390,3 +4390,22 @@\n //#define MBEDTLS_X509_MAX_FILE_PATH_LEN     512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\\0'). */\n \n /** \\} name SECTION: Module configuration options */\n+\n+\n+#if defined(__TINYC__)\n+#undef MBEDTLS_HAVE_ASM\n+#undef MBEDTLS_AESNI_C\n+#undef MBEDTLS_PADLOCK_C\n+#else // __TINYC__\n+#define MBEDTLS_HAVE_ASM\n+#define MBEDTLS_AESNI_C\n+#define MBEDTLS_PADLOCK_C\n+#endif // __TINYC__\n+\n+#if ( defined(__linux__) || defined(__FreeBSD__) ) || defined (__OpenBSD__)\n+#define MBEDTLS_THREADING_PTHREAD\n+#define MBEDTLS_THREADING_C\n+#else\n+#undef MBEDTLS_THREADING_PTHREAD\n+#undef MBEDTLS_THREADING_C\n+#endif\ndiff -ur mbedtls.orig/library/entropy_poll.c mbedtls/library/entropy_poll.c\n--- mbedtls.orig/library/entropy_poll.c\t2026-01-15 22:33:48.325682810 +0300\n+++ mbedtls/library/entropy_poll.c\t2026-01-15 22:34:04.062930810 +0300\n@@ -38,35 +38,36 @@\n \n #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)\n \n+// fallback to 3.3.0 implmentation, as 3.6.5 need a high version of Windows SDK\n+#if !defined(_WIN32_WINNT)\n+#define _WIN32_WINNT 0x0400\n+#endif\n #include <windows.h>\n-#include <bcrypt.h>\n-#include <intsafe.h>\n+#include <wincrypt.h>\n \n-int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len,\n-                                  size_t *olen)\n+int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len,\n+                           size_t *olen )\n {\n+    HCRYPTPROV provider;\n     ((void) data);\n     *olen = 0;\n \n-    /*\n-     * BCryptGenRandom takes ULONG for size, which is smaller than size_t on\n-     * 64-bit Windows platforms. Extract entropy in chunks of len (dependent\n-     * on ULONG_MAX) size.\n-     */\n-    while (len != 0) {\n-        unsigned long ulong_bytes =\n-            (len > ULONG_MAX) ? ULONG_MAX : (unsigned long) len;\n-\n-        if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, output, ulong_bytes,\n-                                            BCRYPT_USE_SYSTEM_PREFERRED_RNG))) {\n-            return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;\n-        }\n+    if( CryptAcquireContext( &provider, NULL, NULL,\n+                              PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )\n+    {\n+        return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );\n+    }\n \n-        *olen += ulong_bytes;\n-        len -= ulong_bytes;\n+    if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE )\n+    {\n+        CryptReleaseContext( provider, 0 );\n+        return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );\n     }\n \n-    return 0;\n+    CryptReleaseContext( provider, 0 );\n+    *olen = len;\n+\n+    return( 0 );\n }\n #else /* _WIN32 && !EFIX64 && !EFI32 */\n \ndiff -ur mbedtls.orig/library/pk.c mbedtls/library/pk.c\n--- mbedtls.orig/library/pk.c\t2026-01-15 22:33:48.326682772 +0300\n+++ mbedtls/library/pk.c\t2026-01-15 22:34:04.063036079 +0300\n@@ -1237,6 +1237,7 @@\n         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n     }\n \n+    if (ctx == NULL) return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n     if (ctx->pk_info == NULL || pk_hashlen_helper(md_alg, &hash_len) != 0) {\n         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;\n     }\ndiff -ur mbedtls.orig/library/platform_util.c mbedtls/library/platform_util.c\n--- mbedtls.orig/library/platform_util.c\t2026-01-15 22:33:48.326682772 +0300\n+++ mbedtls/library/platform_util.c\t2026-01-15 22:34:04.063089145 +0300\n@@ -87,7 +87,7 @@\n  */\n #if !defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) && !(defined(__STDC_LIB_EXT1__) && \\\n     !defined(__IAR_SYSTEMS_ICC__)) \\\n-    && !defined(_WIN32)\n+    && !(defined(_WIN32) && !defined(__TINYC__))\n static void *(*const volatile memset_func)(void *, int, size_t) = memset;\n #endif\n \n@@ -107,7 +107,8 @@\n #endif\n #elif defined(__STDC_LIB_EXT1__) && !defined(__IAR_SYSTEMS_ICC__)\n         memset_s(buf, len, 0, len);\n-#elif defined(_WIN32)\n+#elif defined(_WIN32) && !defined(__TINYC__)\n+        /* tcc has a bad implementation of `SecureZeroMemory` */\n         SecureZeroMemory(buf, len);\n #else\n         memset_func(buf, 0, len);\ndiff -ur mbedtls.orig/library/ssl_misc.h mbedtls/library/ssl_misc.h\n--- mbedtls.orig/library/ssl_misc.h\t2026-01-15 22:33:48.329682659 +0300\n+++ mbedtls/library/ssl_misc.h\t2026-01-15 22:34:04.063263675 +0300\n@@ -1674,26 +1674,30 @@\n {\n     mbedtls_ssl_key_cert *key_cert;\n \n+    if (ssl == NULL) return NULL;\n     if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) {\n         key_cert = ssl->handshake->key_cert;\n     } else {\n+        if (ssl->conf == NULL) return NULL;\n         key_cert = ssl->conf->key_cert;\n     }\n-\n-    return key_cert == NULL ? NULL : key_cert->key;\n+    if (key_cert == NULL) return NULL;\n+    return key_cert->key;\n }\n \n static inline mbedtls_x509_crt *mbedtls_ssl_own_cert(mbedtls_ssl_context *ssl)\n {\n     mbedtls_ssl_key_cert *key_cert;\n \n+    if (ssl == NULL) return NULL;\n     if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) {\n         key_cert = ssl->handshake->key_cert;\n     } else {\n+        if (ssl->conf == NULL) return NULL;\n         key_cert = ssl->conf->key_cert;\n     }\n-\n-    return key_cert == NULL ? NULL : key_cert->cert;\n+    if (key_cert == NULL) return NULL;\n+    return key_cert->cert;\n }\n \n /*\ndiff -ur mbedtls.orig/library/ssl_tls.c mbedtls/library/ssl_tls.c\n--- mbedtls.orig/library/ssl_tls.c\t2026-01-15 22:33:48.329682659 +0300\n+++ mbedtls/library/ssl_tls.c\t2026-01-15 22:34:04.063744568 +0300\n@@ -4560,8 +4560,8 @@\n {\n     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;\n \n-    if (ssl            == NULL                       ||\n-        ssl->conf      == NULL                       ||\n+    if (ssl == NULL) return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n+    if (ssl->conf      == NULL                       ||\n         ssl->handshake == NULL                       ||\n         ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER) {\n         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n@@ -4650,10 +4650,8 @@\n     int ret = 0;\n \n     /* Sanity checks */\n-\n-    if (ssl == NULL || ssl->conf == NULL) {\n-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n-    }\n+    if (ssl == NULL) return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n+    if (ssl->conf == NULL) return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;\n \n #if defined(MBEDTLS_SSL_PROTO_DTLS)\n     if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&\n"
  },
  {
    "path": "thirdparty/mbedtls/update.vsh",
    "content": "// This script can be used to update the thirdparty/mbedtls/ folder to a future version of mbedtls.\nimport os\n\nconst version = 'v3.6.5'\n\nfn do(cmd string) {\n\tprintln(cmd)\n\tres := os.system(cmd)\n\tif res != 0 {\n\t\tpanic('failed at: `${cmd}`')\n\t}\n}\n\nos.chdir(os.dir(@VEXE))!\n\ndo('rm -rf mbedtls/')\ndo('git clone --depth=1 --recursive --shallow-submodules --single-branch --branch ${version} https://github.com/Mbed-TLS/mbedtls.git mbedtls/')\ndo('rsync -a --delete mbedtls/include/  thirdparty/mbedtls/include/')\ndo('rsync -a --delete mbedtls/library/  thirdparty/mbedtls/library/')\ndo('rsync -a --delete mbedtls/3rdparty/ thirdparty/mbedtls/3rdparty/')\ndo('rsync -a          mbedtls/LICENSE   thirdparty/mbedtls/LICENSE')\ndo('rsync -a          mbedtls/README.md thirdparty/mbedtls/README.md')\ndo(\"find thirdparty/mbedtls/ -name '*.txt' -or -name '*.inc' -or -name '.gitignore' -or -name 'Makefile' |xargs rm -f\")\n\ndo('pushd .; cd thirdparty/mbedtls/; patch -p1 < ./mbedtls.patch')\n\ndo('rm -rf mbedtls/')\n"
  },
  {
    "path": "thirdparty/mssql/include/.gitignore",
    "content": "*\n\n!.gitignore\n!mssql.h"
  },
  {
    "path": "thirdparty/mssql/include/mssql.h",
    "content": "// Hacking some headers in windows.\n// sql headers using UNICODE to change function signatures.\n// Currently Linux bindings do not use unicode SQL C bindings,\n// So we turn off the UNICODE to make it compile on windows.\n// For future Unicode support, please raise a issue.\n\n#include <windows.h>\n#include <sal.h>\n\n#ifdef UNICODE\n// Turn off unicode macro and turn back on, so it only affects sql headers\n#undef UNICODE\n#include <sql.h>\n#include <sqlext.h>\n#define UNICODE\n\n#else\n#include <sql.h>\n#include <sqlext.h>\n#endif"
  },
  {
    "path": "thirdparty/photon/photonwrapper.h",
    "content": "#ifndef C_PHOTONWRAPPER_H_\n#define C_PHOTONWRAPPER_H_\n\n#include <sys/socket.h>\n\n\n#ifdef __cplusplus\n\n#include <fcntl.h>\n//#include <vector>\n\n#include <photon/thread/std-compat.h>\n#include <photon/common/alog.h>\n#include <photon/common/iovector.h>\n#include <photon/fs/localfs.h>\n#include <photon/net/socket.h>\n#include <photon/net/basic_socket.h>\n#include <photon/thread/workerpool.h>\n#include <iostream>\n\nextern \"C\" {\n\n// WorkPool* work_pool;\nphoton::WorkPool* work_pool;\n\n// using namespace photon;\n// typedef WorkPool PhotonWorkPool;\n// typedef photon::WorkPool PhotonWorkPool1;\n#else\n#endif\n\nvoid* new_photon_work_pool(size_t);\n// void delete_photon_work_pool(void*);\nvoid delete_photon_work_pool();\n// custom v functions\nvoid init_photon_work_pool(size_t);\n// void photon_thread_migrate();\n// void photon_thread_migrate(void*);\nvoid photon_thread_create_and_migrate_to_work_pool(void* (* f)(void*), void* arg);\n// void photon_thread_create_and_migrate_to_work_pool(void*, void* (* f)(void*), void* arg);\nint photon_join_current_thread_into_workpool();\nvoid photon_set_log_output_stdout();\nvoid photon_set_log_output_stderr();\nvoid photon_set_log_output_null();\n// direct wrappers to photon functions\nint photon_init_default();\nvoid photon_thread_create(void* (* f)(void*), void* arg);\nvoid photon_sleep_s(int n);\nvoid photon_sleep_ms(int n);\n\nvoid* default_photon_thread_stack_alloc(void*, size_t size);\nvoid default_photon_thread_stack_dealloc(void*, void* ptr, size_t size);\nvoid set_photon_thread_stack_allocator(\n    void* (*alloc_func)(void*, size_t),\n    void (*dealloc_func)(void*, void*, size_t)\n);\n\nint photon_socket(int domain, int type, int protocol);\nint photon_connect(int fd, const struct sockaddr *addr, socklen_t addrlen, uint64_t timeout);\nint photon_accept(int fd, struct sockaddr *addr, socklen_t *addrlen, uint64_t timeout);\nssize_t photon_send(int fd, const void* buf, size_t len, int flags, uint64_t timeout);\n// ssize_t photon_sendmsg(int fd, const struct msghdr* msg, int flags, uint64_t timeout);\nssize_t photon_recv(int fd, void* buf, size_t count, int flags, uint64_t timeout);\n// ssize_t photon_recvmsg(int fd, struct msghdr* msg, int flags, uint64_t timeout);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n#endif\n"
  },
  {
    "path": "thirdparty/picoev/picoev.c",
    "content": "#ifdef __linux__\n\t#include \"src/picoev_epoll.c\"\n#elif __APPLE__\n\t#include \"src/picoev_kqueue.c\"\n#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)\n\t#include \"src/picoev_kqueue.c\"\n#else\n\t#include \"src/picoev_select.c\"\n#endif\n"
  },
  {
    "path": "thirdparty/picoev/src/README.md",
    "content": "picoev\n======\n\nA *tiny*, *lightning fast* event loop for network applications\n\nThe text below is copied from the [original publication](http://developer.cybozu.co.jp/archives/kazuho/2009/08/picoev-a-tiny-e.html)\n\nI am sure many programmers writing network applications have their own abstracting layers hiding the differences between various I/O multiplex APIs, like select(2), poll(2), epoll(2), ... And of course, I am one among them.  While writing mycached ([see Mycached: memcached protocol support for MySQL for more information](http://developer.cybozu.co.jp/archives/kazuho/2009/08/mycached-memcac.html)), I was at first considering of using [libev](http://software.schmorp.de/pkg/libev.html) for multiplexing socket I/Os. [Libevent](http://www.monkey.org/~provos/libevent/) was not an option since it does not (yet) provide multithreading support.\n\nBut it was a great pain for me to learn how to use libev.  I do not mean that its is an ugly product.  In fact, I think that it is a very well written, excellent library.  However, for me it was too much a boring task to learn how the things are abstracted, already being familiar with the problems it tries to hide.\n\nSo instead I thought it might be a good occasion to write my own library that could be used in any programs I may write in the future.  The result is picoev, and it is faster than libevent or libev!  The benchmark used is a re-modified version taken from libev.schmorp.de/bench.html and can be found [here](http://coderepos.org/share/browser/lang/c/picoev/trunk/example/bench.c).\n![setup time](http://developer.cybozu.co.jp/archives/kazuho/files/picoev_setup.png)\n![event processing time](http://developer.cybozu.co.jp/archives/kazuho/files/picoev_event.png)\n\nWhy is it faster?  It is because it uses an array and a ring buffer of bit vectors as its internal structure.  Libevent and libev seem to use some kind of sorted tree to represent file descriptors.  However, if we concentrate on Un*x systems, there is a guarantee that the descriptors will be a small positive integer.  Picoev utilizes the fact and stores information related to file descriptors (such as pointers to callback functions or callback arguments) in an array, resulting in a faster manipulation of socket states.\n\nAnother optimization technique used by picoev is not to use an ordered tree for keeping timeout information.  Generally speaking, most network applications do not require accurate timeouts.  Thus it is possible to use a ring buffer (a sliding array) of bit vectors for the purpose.  Each bit vector represents a set of file descriptors that time-outs at a given time.  Picoev uses 128 of bit vectors to represent timeouts, for example, the first bit vector represents the sockets that timeout a second after, the second bit vector representing them of two seconds after..., and the bit vectors slide every second.  If the maximum timeout required by the web application is greater than 128, the minimum granurality of timeout becomes two seconds.\n\nI would like to reiterate that both libevent and libev are great libraries.  Picoev is not at comparable to them especially in maturity and the number of features.  It only supports select(2), epoll(2), and kqueue(2) for the time being.  However the design is simple than the other two, and I think it will be a good starting point to write network applications, or to use as a basis for writing one's own network libraries.\n\n"
  },
  {
    "path": "thirdparty/picoev/src/picoev.h",
    "content": "/*\n * Copyright (c) 2009, Cybozu Labs, Inc.\n * All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n * \n * * Redistributions of source code must retain the above copyright notice,\n *   this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright notice,\n *   this list of conditions and the following disclaimer in the documentation\n *   and/or other materials provided with the distribution.\n * * Neither the name of the <ORGANIZATION> nor the names of its contributors\n *   may be used to endorse or promote products derived from this software\n *   without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef picoev_h\n#define picoev_h\n\n#ifdef __cplusplus\nextern \"C\" {\n# define PICOEV_INLINE inline\n#else\n# define PICOEV_INLINE static __inline__\n#endif\n\n#include <assert.h>\n#include <limits.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#define PICOEV_IS_INITED (picoev.max_fd != 0)  \n#define PICOEV_IS_INITED_AND_FD_IN_RANGE(fd) \\\n  (((unsigned)fd) < (unsigned)picoev.max_fd)\n#define PICOEV_TOO_MANY_LOOPS (picoev.num_loops != 0) /* use after ++ */\n#define PICOEV_FD_BELONGS_TO_LOOP(loop, fd) \\\n  ((loop)->loop_id == picoev.fds[fd].loop_id)\n\n#define PICOEV_TIMEOUT_VEC_OF(loop, idx) \\\n  ((loop)->timeout.vec + (idx) * picoev.timeout_vec_size)\n#define PICOEV_TIMEOUT_VEC_OF_VEC_OF(loop, idx) \\\n  ((loop)->timeout.vec_of_vec + (idx) * picoev.timeout_vec_of_vec_size)\n#define PICOEV_RND_UP(v, d) (((v) + (d) - 1) / (d) * (d))\n\n#define PICOEV_PAGE_SIZE 4096\n#define PICOEV_CACHE_LINE_SIZE 32 /* in bytes, ok if greater than the actual */\n#define PICOEV_SIMD_BITS 128\n#define PICOEV_TIMEOUT_VEC_SIZE 128\n#define PICOEV_SHORT_BITS (sizeof(short) * 8)\n\n#define PICOEV_READ 1\n#define PICOEV_WRITE 2\n#define PICOEV_TIMEOUT 4\n#define PICOEV_ADD 0x40000000\n#define PICOEV_DEL 0x20000000\n#define PICOEV_READWRITE (PICOEV_READ | PICOEV_WRITE)\n  \n#define PICOEV_TIMEOUT_IDX_UNUSED (UCHAR_MAX)\n  \n  typedef unsigned short picoev_loop_id_t;\n  \n  typedef struct picoev_loop_st picoev_loop;\n  \n  typedef void picoev_handler(picoev_loop* loop, int fd, int revents,\n\t\t\t      void* cb_arg);\n  \n  typedef struct picoev_fd_st {\n    /* use accessors! */\n    /* TODO adjust the size to match that of a cache line */\n    picoev_handler* callback;\n    void* cb_arg;\n    picoev_loop_id_t loop_id;\n    char events;\n    unsigned char timeout_idx; /* PICOEV_TIMEOUT_IDX_UNUSED if not used */\n    int _backend; /* can be used by backends (never modified by core) */\n  } picoev_fd;\n  \n  struct picoev_loop_st {\n    /* read only */\n    picoev_loop_id_t loop_id;\n    struct {\n      short* vec;\n      short* vec_of_vec;\n      size_t base_idx;\n      time_t base_time;\n      int resolution;\n      void* _free_addr;\n    } timeout;\n    time_t now;\n  };\n  \n  typedef struct picoev_globals_st {\n    /* read only */\n    picoev_fd* fds;\n    void* _fds_free_addr;\n    int max_fd;\n    int num_loops;\n    size_t timeout_vec_size; /* # of elements in picoev_loop.timeout.vec[0] */\n    size_t timeout_vec_of_vec_size; /* ... in timeout.vec_of_vec[0] */\n  } picoev_globals;\n  \n  extern picoev_globals picoev;\n  \n  /* creates a new event loop (defined by each backend) */\n  picoev_loop* picoev_create_loop(int max_timeout);\n  \n  /* destroys a loop (defined by each backend) */\n  int picoev_destroy_loop(picoev_loop* loop);\n  \n  /* internal: updates events to be watched (defined by each backend) */\n  int picoev_update_events_internal(picoev_loop* loop, int fd, int events);\n  \n  /* internal: poll once and call the handlers (defined by each backend) */\n  int picoev_poll_once_internal(picoev_loop* loop, int max_wait);\n  \n  /* internal, aligned allocator with address scrambling to avoid cache\n     line contention */\n  PICOEV_INLINE\n  void* picoev_memalign(size_t sz, void** orig_addr, int clear) {\n    sz = sz + PICOEV_PAGE_SIZE + PICOEV_CACHE_LINE_SIZE;\n    if ((*orig_addr = malloc(sz)) == NULL) {\n      return NULL;\n    }\n    if (clear != 0) {\n      memset(*orig_addr, 0, sz);\n    }\n    return\n      (void*)PICOEV_RND_UP((unsigned long)*orig_addr\n\t\t\t   + (rand() % PICOEV_PAGE_SIZE),\n\t\t\t   PICOEV_CACHE_LINE_SIZE);\n  }\n  \n  /* initializes picoev */\n  PICOEV_INLINE\n  int picoev_init(int max_fd) {\n    assert(! PICOEV_IS_INITED);\n    assert(max_fd > 0);\n    if ((picoev.fds = (picoev_fd*)picoev_memalign(sizeof(picoev_fd) * max_fd,\n\t\t\t\t\t\t  &picoev._fds_free_addr, 1))\n\t== NULL) {\n      return -1;\n    }\n    picoev.max_fd = max_fd;\n    picoev.num_loops = 0;\n    picoev.timeout_vec_size\n      = PICOEV_RND_UP(picoev.max_fd, PICOEV_SIMD_BITS) / PICOEV_SHORT_BITS;\n    picoev.timeout_vec_of_vec_size\n      = PICOEV_RND_UP(picoev.timeout_vec_size, PICOEV_SIMD_BITS)\n      / PICOEV_SHORT_BITS;\n    return 0;\n  }\n  \n  /* deinitializes picoev */\n  PICOEV_INLINE\n  int picoev_deinit(void) {\n    assert(PICOEV_IS_INITED);\n    free(picoev._fds_free_addr);\n    picoev.fds = NULL;\n    picoev._fds_free_addr = NULL;\n    picoev.max_fd = 0;\n    picoev.num_loops = 0;\n    return 0;\n  }\n  \n  /* updates timeout */\n  PICOEV_INLINE\n  void picoev_set_timeout(picoev_loop* loop, int fd, int secs) {\n    picoev_fd* target;\n    short* vec, * vec_of_vec;\n    size_t vi = fd / PICOEV_SHORT_BITS, delta;\n    assert(PICOEV_IS_INITED_AND_FD_IN_RANGE(fd));\n    assert(PICOEV_FD_BELONGS_TO_LOOP(loop, fd));\n    target = picoev.fds + fd;\n    /* clear timeout */\n    if (target->timeout_idx != PICOEV_TIMEOUT_IDX_UNUSED) {\n      vec = PICOEV_TIMEOUT_VEC_OF(loop, target->timeout_idx);\n      if ((vec[vi] &= ~((unsigned short)SHRT_MIN >> (fd % PICOEV_SHORT_BITS)))\n\t  == 0) {\n\tvec_of_vec = PICOEV_TIMEOUT_VEC_OF_VEC_OF(loop, target->timeout_idx);\n\tvec_of_vec[vi / PICOEV_SHORT_BITS]\n\t  &= ~((unsigned short)SHRT_MIN >> (vi % PICOEV_SHORT_BITS));\n      }\n      target->timeout_idx = PICOEV_TIMEOUT_IDX_UNUSED;\n    }\n    if (secs != 0) {\n      delta = (loop->now + secs - loop->timeout.base_time)\n\t/ loop->timeout.resolution;\n      if (delta >= PICOEV_TIMEOUT_VEC_SIZE) {\n\tdelta = PICOEV_TIMEOUT_VEC_SIZE - 1;\n      }\n      target->timeout_idx =\n\t(loop->timeout.base_idx + delta) % PICOEV_TIMEOUT_VEC_SIZE;\n      vec = PICOEV_TIMEOUT_VEC_OF(loop, target->timeout_idx);\n      vec[vi] |= (unsigned short)SHRT_MIN >> (fd % PICOEV_SHORT_BITS);\n      vec_of_vec = PICOEV_TIMEOUT_VEC_OF_VEC_OF(loop, target->timeout_idx);\n      vec_of_vec[vi / PICOEV_SHORT_BITS]\n\t|= (unsigned short)SHRT_MIN >> (vi % PICOEV_SHORT_BITS);\n    }\n  }\n  \n  /* registers a file descriptor and callback argument to a event loop */\n  PICOEV_INLINE\n  int picoev_add(picoev_loop* loop, int fd, int events, int timeout_in_secs,\n\t\t picoev_handler* callback, void* cb_arg) {\n    picoev_fd* target;\n    if (!PICOEV_IS_INITED_AND_FD_IN_RANGE(fd)) { return -1; }\n    target = picoev.fds + fd;\n    assert(target->loop_id == 0);\n    target->callback = callback;\n    target->cb_arg = cb_arg;\n    target->loop_id = loop->loop_id;\n    target->events = 0;\n    target->timeout_idx = PICOEV_TIMEOUT_IDX_UNUSED;\n    if (picoev_update_events_internal(loop, fd, events | PICOEV_ADD) != 0) {\n      target->loop_id = 0;\n      return -1;\n    }\n    picoev_set_timeout(loop, fd, timeout_in_secs);\n    return 0;\n  }\n  \n  /* unregisters a file descriptor from event loop */\n  PICOEV_INLINE\n  int picoev_del(picoev_loop* loop, int fd) {\n    picoev_fd* target;\n    assert(PICOEV_IS_INITED_AND_FD_IN_RANGE(fd));\n    target = picoev.fds + fd;\n    if (picoev_update_events_internal(loop, fd, PICOEV_DEL) != 0) {\n      return -1;\n    }\n    picoev_set_timeout(loop, fd, 0);\n    target->loop_id = 0;\n    return 0;\n  }\n  \n  /* check if fd is registered (checks all loops if loop == NULL) */\n  PICOEV_INLINE\n  int picoev_is_active(picoev_loop* loop, int fd) {\n    assert(PICOEV_IS_INITED_AND_FD_IN_RANGE(fd));\n    return loop != NULL\n      ? picoev.fds[fd].loop_id == loop->loop_id\n      : picoev.fds[fd].loop_id != 0;\n  }\n  \n  /* returns events being watched for given descriptor */\n  PICOEV_INLINE\n  int picoev_get_events(picoev_loop* loop __attribute__((unused)), int fd) {\n    assert(PICOEV_IS_INITED_AND_FD_IN_RANGE(fd));\n    return picoev.fds[fd].events & PICOEV_READWRITE;\n  }\n  \n  /* sets events to be watched for given desriptor */\n  PICOEV_INLINE\n  int picoev_set_events(picoev_loop* loop, int fd, int events) {\n    assert(PICOEV_IS_INITED_AND_FD_IN_RANGE(fd));\n    if (picoev.fds[fd].events != events\n\t&& picoev_update_events_internal(loop, fd, events) != 0) {\n      return -1;\n    }\n    return 0;\n  }\n  \n  /* returns callback for given descriptor */\n  PICOEV_INLINE\n  picoev_handler* picoev_get_callback(picoev_loop* loop __attribute__((unused)),\n\t\t\t\t      int fd, void** cb_arg) {\n    assert(PICOEV_IS_INITED_AND_FD_IN_RANGE(fd));\n    if (cb_arg != NULL) {\n      *cb_arg = picoev.fds[fd].cb_arg;\n    }\n    return picoev.fds[fd].callback;\n  }\n  \n  /* sets callback for given descriptor */\n  PICOEV_INLINE\n  void picoev_set_callback(picoev_loop* loop __attribute__((unused)), int fd,\n\t\t\t   picoev_handler* callback, void** cb_arg) {\n    assert(PICOEV_IS_INITED_AND_FD_IN_RANGE(fd));\n    if (cb_arg != NULL) {\n      picoev.fds[fd].cb_arg = *cb_arg;\n    }\n    picoev.fds[fd].callback = callback;\n  }\n  \n  /* function to iterate registered information. To start iteration, set curfd\n     to -1 and call the function until -1 is returned */\n  PICOEV_INLINE\n  int picoev_next_fd(picoev_loop* loop, int curfd) {\n    if (curfd != -1) {\n      assert(PICOEV_IS_INITED_AND_FD_IN_RANGE(curfd));\n    }\n    while (++curfd < picoev.max_fd) {\n      if (loop->loop_id == picoev.fds[curfd].loop_id) {\n\treturn curfd;\n      }\n    }\n    return -1;\n  }\n  \n  /* internal function */\n  PICOEV_INLINE\n  int picoev_init_loop_internal(picoev_loop* loop, int max_timeout) {\n    loop->loop_id = ++picoev.num_loops;\n    assert(PICOEV_TOO_MANY_LOOPS);\n    if ((loop->timeout.vec_of_vec\n\t = (short*)picoev_memalign((picoev.timeout_vec_of_vec_size\n\t\t\t\t    + picoev.timeout_vec_size)\n\t\t\t\t   * sizeof(short) * PICOEV_TIMEOUT_VEC_SIZE,\n\t\t\t\t   &loop->timeout._free_addr, 1))\n\t== NULL) {\n      --picoev.num_loops;\n      return -1;\n    }\n    loop->timeout.vec = loop->timeout.vec_of_vec\n      + picoev.timeout_vec_of_vec_size * PICOEV_TIMEOUT_VEC_SIZE;\n    loop->timeout.base_idx = 0;\n    loop->timeout.base_time = time(NULL);\n    loop->timeout.resolution\n      = PICOEV_RND_UP(max_timeout, PICOEV_TIMEOUT_VEC_SIZE)\n      / PICOEV_TIMEOUT_VEC_SIZE;\n    return 0;\n  }\n  \n  /* internal function */\n  PICOEV_INLINE\n  void picoev_deinit_loop_internal(picoev_loop* loop) {\n    free(loop->timeout._free_addr);\n  }\n  \n  /* internal function */\n  PICOEV_INLINE\n  void picoev_handle_timeout_internal(picoev_loop* loop) {\n    size_t i, j, k;\n    for (;\n\t loop->timeout.base_time <= loop->now - loop->timeout.resolution; \n\t loop->timeout.base_idx\n\t   = (loop->timeout.base_idx + 1) % PICOEV_TIMEOUT_VEC_SIZE,\n\t   loop->timeout.base_time += loop->timeout.resolution) {\n      /* TODO use SIMD instructions */\n      short* vec = PICOEV_TIMEOUT_VEC_OF(loop, loop->timeout.base_idx);\n      short* vec_of_vec\n\t= PICOEV_TIMEOUT_VEC_OF_VEC_OF(loop, loop->timeout.base_idx);\n      for (i = 0; i < picoev.timeout_vec_of_vec_size; ++i) {\n\tshort vv = vec_of_vec[i];\n\tif (vv != 0) {\n\t  for (j = i * PICOEV_SHORT_BITS; vv != 0; j++, vv <<= 1) {\n\t    if (vv < 0) {\n\t      short v = vec[j];\n\t      assert(v != 0);\n\t      for (k = j * PICOEV_SHORT_BITS; v != 0; k++, v <<= 1) {\n\t\tif (v < 0) {\n\t\t  picoev_fd* fd = picoev.fds + k;\n\t\t  assert(fd->loop_id == loop->loop_id);\n\t\t  fd->timeout_idx = PICOEV_TIMEOUT_IDX_UNUSED;\n\t\t  (*fd->callback)(loop, k, PICOEV_TIMEOUT, fd->cb_arg);\n\t\t}\n\t      }\n\t      vec[j] = 0;\n\t    }\n\t  }\n\t  vec_of_vec[i] = 0;\n\t}\n      }\n    }\n  }\n  \n  /* loop once */\n  PICOEV_INLINE\n  int picoev_loop_once(picoev_loop* loop, int max_wait) {\n    loop->now = time(NULL);\n    if (max_wait > loop->timeout.resolution) {\n      max_wait = loop->timeout.resolution;\n    }\n    if (picoev_poll_once_internal(loop, max_wait) != 0) {\n      return -1;\n    }\n    if (max_wait != 0) {\n      loop->now = time(NULL);\n    }\n    picoev_handle_timeout_internal(loop);\n    return 0;\n  }\n  \n#undef PICOEV_INLINE\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/picoev/src/picoev_epoll.c",
    "content": "/*\n * Copyright (c) 2009, Cybozu Labs, Inc.\n * All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n * \n * * Redistributions of source code must retain the above copyright notice,\n *   this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright notice,\n *   this list of conditions and the following disclaimer in the documentation\n *   and/or other materials provided with the distribution.\n * * Neither the name of the <ORGANIZATION> nor the names of its contributors\n *   may be used to endorse or promote products derived from this software\n *   without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <errno.h>\n\n// tcc needs the pragmas, because it does not support yet\n// the __EPOLL_PACKED macro, defined to be __attribute__ ((__packed__))\n#pragma pack(push, 1)\n#include <sys/epoll.h>\n#pragma pack(pop)\n\n#include <unistd.h>\n#include \"picoev.h\"\n\n#ifndef PICOEV_EPOLL_DEFER_DELETES\n# define PICOEV_EPOLL_DEFER_DELETES 1\n#endif\n\ntypedef struct picoev_loop_epoll_st {\n  picoev_loop loop;\n  int epfd;\n  struct epoll_event events[1024];\n} picoev_loop_epoll;\n\npicoev_globals picoev;\n\npicoev_loop* picoev_create_loop(int max_timeout)\n{\n  picoev_loop_epoll* loop;\n  \n  /* init parent */\n  assert(PICOEV_IS_INITED);\n  if ((loop = (picoev_loop_epoll*)malloc(sizeof(picoev_loop_epoll))) == NULL) {\n    return NULL;\n  }\n  if (picoev_init_loop_internal(&loop->loop, max_timeout) != 0) {\n    free(loop);\n    return NULL;\n  }\n  \n  /* init myself */\n  if ((loop->epfd = epoll_create(picoev.max_fd)) == -1) {\n    picoev_deinit_loop_internal(&loop->loop);\n    free(loop);\n    return NULL;\n  }\n  \n  loop->loop.now = time(NULL);\n  return &loop->loop;\n}\n\nint picoev_destroy_loop(picoev_loop* _loop)\n{\n  picoev_loop_epoll* loop = (picoev_loop_epoll*)_loop;\n  \n  if (close(loop->epfd) != 0) {\n    return -1;\n  }\n  picoev_deinit_loop_internal(&loop->loop);\n  free(loop);\n  return 0;\n}\n\nint picoev_update_events_internal(picoev_loop* _loop, int fd, int events)\n{\n  picoev_loop_epoll* loop = (picoev_loop_epoll*)_loop;\n  picoev_fd* target = picoev.fds + fd;\n  struct epoll_event ev;\n  int epoll_ret;\n  \n  memset( &ev, 0, sizeof( ev ) );\n  assert(PICOEV_FD_BELONGS_TO_LOOP(&loop->loop, fd));\n  \n  if ((events & PICOEV_READWRITE) == target->events) {\n    return 0;\n  }\n  \n  ev.events = ((events & PICOEV_READ) != 0 ? EPOLLIN : 0)\n    | ((events & PICOEV_WRITE) != 0 ? EPOLLOUT : 0);\n  ev.data.fd = fd;\n  \n#define SET(op, check_error) do {\t\t    \\\n    epoll_ret = epoll_ctl(loop->epfd, op, fd, &ev); \\\n    assert(! check_error || epoll_ret == 0);\t    \\\n  } while (0)\n  \n#if PICOEV_EPOLL_DEFER_DELETES\n  \n  if ((events & PICOEV_DEL) != 0) {\n    /* nothing to do */\n  } else if ((events & PICOEV_READWRITE) == 0) {\n    SET(EPOLL_CTL_DEL, 1);\n  } else {\n    SET(EPOLL_CTL_MOD, 0);\n    if (epoll_ret != 0) {\n      assert(errno == ENOENT);\n      SET(EPOLL_CTL_ADD, 1);\n    }\n  }\n  \n#else\n  \n  if ((events & PICOEV_READWRITE) == 0) {\n    SET(EPOLL_CTL_DEL, 1);\n  } else {\n    SET(target->events == 0 ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, 1);\n  }\n  \n#endif\n  \n#undef SET\n  \n  target->events = events;\n  \n  return 0;\n}\n\nint picoev_poll_once_internal(picoev_loop* _loop, int max_wait)\n{\n  picoev_loop_epoll* loop = (picoev_loop_epoll*)_loop;\n  int i, nevents;\n  \n  nevents = epoll_wait(loop->epfd, loop->events,\n\t\t       sizeof(loop->events) / sizeof(loop->events[0]),\n\t\t       max_wait * 1000);\n  if (nevents == -1) {\n    return -1;\n  }\n  for (i = 0; i < nevents; ++i) {\n    struct epoll_event* event = loop->events + i;\n    picoev_fd* target = picoev.fds + event->data.fd;\n    if (loop->loop.loop_id == target->loop_id\n\t&& (target->events & PICOEV_READWRITE) != 0) {\n      int revents = ((event->events & EPOLLIN) != 0 ? PICOEV_READ : 0)\n\t| ((event->events & EPOLLOUT) != 0 ? PICOEV_WRITE : 0);\n      if (revents != 0) {\n\t(*target->callback)(&loop->loop, event->data.fd, revents,\n\t\t\t    target->cb_arg);\n      }\n    } else {\n#if PICOEV_EPOLL_DEFER_DELETES\n      event->events = 0;\n      epoll_ctl(loop->epfd, EPOLL_CTL_DEL, event->data.fd, event);\n#endif\n    }\n  }\n  return 0;\n}\n"
  },
  {
    "path": "thirdparty/picoev/src/picoev_kqueue.c",
    "content": "/*\n * Copyright (c) 2009, Cybozu Labs, Inc.\n * All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n * \n * * Redistributions of source code must retain the above copyright notice,\n *   this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright notice,\n *   this list of conditions and the following disclaimer in the documentation\n *   and/or other materials provided with the distribution.\n * * Neither the name of the <ORGANIZATION> nor the names of its contributors\n *   may be used to endorse or promote products derived from this software\n *   without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <errno.h>\n#include <sys/types.h>\n#include <sys/event.h>\n#include <sys/time.h>\n#include <unistd.h>\n#include \"picoev.h\"\n\n#define EV_QUEUE_SZ 128\n\n#define BACKEND_BUILD(next_fd, events)\t\\\n  ((unsigned)((next_fd << 8) | (events & 0xff)))\n#define BACKEND_GET_NEXT_FD(backend) ((int)(backend) >> 8)\n#define BACKEND_GET_OLD_EVENTS(backend) ((int)(backend) & 0xff)\n\ntypedef struct picoev_loop_kqueue_st {\n  picoev_loop loop;\n  int kq;\n  int changed_fds; /* link list using picoev_fd::_backend, -1 if not changed */\n  struct kevent events[1024];\n  struct kevent changelist[256];\n} picoev_loop_kqueue;\n\npicoev_globals picoev;\n\nstatic int apply_pending_changes(picoev_loop_kqueue* loop, int apply_all)\n{\n#define SET(op, events)\t\t\t\t\t\t\\\n  EV_SET(loop->changelist + cl_off++, loop->changed_fds,\t\\\n\t (((events) & PICOEV_READ) != 0 ? EVFILT_READ : 0)\t\\\n\t | (((events) & PICOEV_WRITE) != 0 ? EVFILT_WRITE : 0), \\\n\t (op), 0, 0, NULL)\n  \n  int cl_off = 0, nevents;\n  \n  while (loop->changed_fds != -1) {\n    picoev_fd* changed = picoev.fds + loop->changed_fds;\n    int old_events = BACKEND_GET_OLD_EVENTS(changed->_backend);\n    if (changed->events != old_events) {\n      if (old_events != 0) {\n\tSET(EV_DISABLE, old_events);\n      }\n      if (changed->events != 0) {\n\tSET(EV_ADD | EV_ENABLE, changed->events);\n      }\n      if ((size_t)cl_off + 1\n\t  >= sizeof(loop->changelist) / sizeof(loop->changelist[0])) {\n\tnevents = kevent(loop->kq, loop->changelist, cl_off, NULL, 0, NULL);\n\tassert(nevents == 0);\n\tcl_off = 0;\n      }\n    }\n    loop->changed_fds = BACKEND_GET_NEXT_FD(changed->_backend);\n    changed->_backend = -1;\n  }\n  \n  if (apply_all && cl_off != 0) {\n    nevents = kevent(loop->kq, loop->changelist, cl_off, NULL, 0, NULL);\n    assert(nevents == 0);\n    cl_off = 0;\n  }\n  \n  return cl_off;\n  \n#undef SET\n}\n\npicoev_loop* picoev_create_loop(int max_timeout)\n{\n  picoev_loop_kqueue* loop;\n  \n  /* init parent */\n  assert(PICOEV_IS_INITED);\n  if ((loop = (picoev_loop_kqueue*)malloc(sizeof(picoev_loop_kqueue)))\n      == NULL) {\n    return NULL;\n  }\n  if (picoev_init_loop_internal(&loop->loop, max_timeout) != 0) {\n    free(loop);\n    return NULL;\n  }\n  \n  /* init kqueue */\n  if ((loop->kq = kqueue()) == -1) {\n    picoev_deinit_loop_internal(&loop->loop);\n    free(loop);\n    return NULL;\n  }\n  loop->changed_fds = -1;\n  \n  loop->loop.now = time(NULL);\n  return &loop->loop;\n}\n\nint picoev_destroy_loop(picoev_loop* _loop)\n{\n  picoev_loop_kqueue* loop = (picoev_loop_kqueue*)_loop;\n  \n  if (close(loop->kq) != 0) {\n    return -1;\n  }\n  picoev_deinit_loop_internal(&loop->loop);\n  free(loop);\n  return 0;\n}\n\nint picoev_update_events_internal(picoev_loop* _loop, int fd, int events)\n{\n  picoev_loop_kqueue* loop = (picoev_loop_kqueue*)_loop;\n  picoev_fd* target = picoev.fds + fd;\n  \n  assert(PICOEV_FD_BELONGS_TO_LOOP(&loop->loop, fd));\n  \n  /* initialize if adding the fd */\n  if ((events & PICOEV_ADD) != 0) {\n    target->_backend = -1;\n  }\n  /* return if nothing to do */\n  if (events == PICOEV_DEL\n      ? target->_backend == -1\n      : (events & PICOEV_READWRITE) == target->events) {\n    return 0;\n  }\n  /* add to changed list if not yet being done */\n  if (target->_backend == -1) {\n    target->_backend = BACKEND_BUILD(loop->changed_fds, target->events);\n    loop->changed_fds = fd;\n  }\n  /* update events */\n  target->events = events & PICOEV_READWRITE;\n  /* apply immediately if is a DELETE */\n  if ((events & PICOEV_DEL) != 0) {\n    apply_pending_changes(loop, 1);\n  }\n  \n  return 0;\n}\n\nint picoev_poll_once_internal(picoev_loop* _loop, int max_wait)\n{\n  picoev_loop_kqueue* loop = (picoev_loop_kqueue*)_loop;\n  struct timespec ts;\n  int cl_off = 0, nevents, i;\n  \n  /* apply pending changes, with last changes stored to loop->changelist */\n  cl_off = apply_pending_changes(loop, 0);\n  \n  ts.tv_sec = max_wait;\n  ts.tv_nsec = 0;\n  nevents = kevent(loop->kq, loop->changelist, cl_off, loop->events,\n\t\t   sizeof(loop->events) / sizeof(loop->events[0]), &ts);\n  if (nevents == -1) {\n    /* the errors we can only rescue */\n    assert(errno == EACCES || errno == EFAULT || errno == EINTR);\n    return -1;\n  }\n  for (i = 0; i < nevents; ++i) {\n    struct kevent* event = loop->events + i;\n    picoev_fd* target = picoev.fds + event->ident;\n    assert((event->flags & EV_ERROR) == 0); /* changelist errors are fatal */\n    if (loop->loop.loop_id == target->loop_id\n\t&& (event->filter & (EVFILT_READ | EVFILT_WRITE)) != 0) {\n      int revents;\n      switch (event->filter) {\n      case EVFILT_READ:\n\trevents = PICOEV_READ;\n\tbreak;\n      case EVFILT_WRITE:\n\trevents = PICOEV_WRITE;\n\tbreak;\n      default:\n\tassert(0);\n\trevents = 0; // suppress compiler warning\n\tbreak;\n      }\n      (*target->callback)(&loop->loop, event->ident, revents, target->cb_arg);\n    }\n  }\n  \n  return 0;\n}\n"
  },
  {
    "path": "thirdparty/picoev/src/picoev_select.c",
    "content": "/*\n * Copyright (c) 2009, Cybozu Labs, Inc.\n * All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n * \n * * Redistributions of source code must retain the above copyright notice,\n *   this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright notice,\n *   this list of conditions and the following disclaimer in the documentation\n *   and/or other materials provided with the distribution.\n * * Neither the name of the <ORGANIZATION> nor the names of its contributors\n *   may be used to endorse or promote products derived from this software\n *   without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _WIN32\n# include <sys/select.h>\n#else\n# include <ws2tcpip.h>\n#endif\n\n#include \"picoev.h\"\n\n#ifdef _WIN32\n# define PICOEV_W32_INTERNAL\n# include \"picoev_w32.h\"\n# define PICOEV_FD_SET(x, y) FD_SET(picoev_w32_fd2sock(x), y)\n# define PICOEV_FD_ISSET(x, y) FD_ISSET(picoev_w32_fd2sock(x), y)\n\ntypedef struct picoev_w32_globals_st {\n  int* fds;\n  void* _fds_free_addr;\n} picoev_w32_globals;\n\npicoev_w32_globals picoev_w32;\n\nint picoev_w32_sock2fd(int sock) {\n  int i;\n  for (i = 0; i < picoev.max_fd && picoev_w32.fds[i]; ++i)\n    if (picoev_w32.fds[i] == sock) return i;\n  assert(PICOEV_IS_INITED_AND_FD_IN_RANGE(i));\n  picoev_w32.fds[i] = sock;\n  return i;\n}\n\nint picoev_w32_fd2sock(int fd) {\n  assert(PICOEV_IS_INITED_AND_FD_IN_RANGE(fd));\n  return picoev_w32.fds[fd];\n}\n\nextern int picoev_w32_deinit(void);\n\nint picoev_w32_init(int max_fd) {\n  int r = picoev_init(max_fd);\n  if ((picoev_w32.fds = (int*)picoev_memalign(sizeof(int) * max_fd,\n\t\t\t\t\t\t&picoev_w32._fds_free_addr, 1))\n\t== NULL) {\n    picoev_deinit();\n    return -1;\n  }\n}\n\nint picoev_w32_deinit(void) {\n  free(picoev_w32._fds_free_addr);\n  picoev_w32.fds = NULL;\n  picoev_w32._fds_free_addr = NULL;\n  return picoev_deinit();\n}\n\n#else\n# define PICOEV_FD_SET(x, y) FD_SET(x, y)\n# define PICOEV_FD_ISSET(x, y) FD_ISSET(x, y)\n#endif\n\npicoev_globals picoev;\n\npicoev_loop* picoev_create_loop(int max_timeout)\n{\n  picoev_loop* loop;\n  \n  assert(PICOEV_IS_INITED);\n  if ((loop = (picoev_loop*)malloc(sizeof(picoev_loop))) == NULL) {\n    return NULL;\n  }\n  if (picoev_init_loop_internal(loop, max_timeout) != 0) {\n    free(loop);\n    return NULL;\n  }\n  \n  loop->now = time(NULL);\n  return loop;\n}\n\nint picoev_destroy_loop(picoev_loop* loop)\n{\n  picoev_deinit_loop_internal(loop);\n  free(loop);\n  return 0;\n}\n\nint picoev_update_events_internal(picoev_loop* loop, int fd, int events)\n{\n  picoev.fds[fd].events = events & PICOEV_READWRITE;\n  return 0;\n}\n\nint picoev_poll_once_internal(picoev_loop* loop, int max_wait)\n{\n  fd_set readfds, writefds, errorfds;\n  struct timeval tv;\n  int i, r, maxfd = 0;\n  \n  /* setup */\n  FD_ZERO(&readfds);\n  FD_ZERO(&writefds);\n  FD_ZERO(&errorfds);\n  for (i = 0; i < picoev.max_fd; ++i) {\n    picoev_fd* fd = picoev.fds + i;\n    if (fd->loop_id == loop->loop_id) {\n      if ((fd->events & PICOEV_READ) != 0) {\n\tPICOEV_FD_SET(i, &readfds);\n\tif (maxfd < i) {\n\t  maxfd = i;\n\t}\n      }\n      if ((fd->events & PICOEV_WRITE) != 0) {\n\tPICOEV_FD_SET(i, &writefds);\n\tif (maxfd < i) {\n\t  maxfd = i;\n\t}\n      }\n    }\n  }\n  \n  /* select and handle if any */\n  tv.tv_sec = max_wait;\n  tv.tv_usec = 0;\n  r = select(maxfd + 1, &readfds, &writefds, &errorfds, &tv);\n  if (r == -1) {\n    return -1;\n  } else if (r > 0) {\n    for (i = 0; i < picoev.max_fd; ++i) {\n      picoev_fd* target = picoev.fds + i;\n      if (target->loop_id == loop->loop_id) {\n\tint revents = (PICOEV_FD_ISSET(i, &readfds) ? PICOEV_READ : 0)\n\t  | (PICOEV_FD_ISSET(i, &writefds) ? PICOEV_WRITE : 0);\n\tif (revents != 0) {\n\t  (*target->callback)(loop, i, revents, target->cb_arg);\n\t}\n      }\n    }\n  }\n  \n  return 0;\n}\n"
  },
  {
    "path": "thirdparty/picoev/src/picoev_w32.h",
    "content": "#ifndef picoev_w32_h\n#define picoev_w32_h\n\n#include \"picoev.h\"\n\n#ifndef PICOEV_W32_INTERNAL\nextern int picoev_w32_init(int);\nextern int picoev_w32_deinit(void);\nextern int picoev_w32_sock2fd(int);\nextern int picoev_w32_fd2sock(int);\n# define picoev_init picoev_w32_init\n# define picoev_deinit picoev_w32_deinit\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/picohttpparser/README.md",
    "content": "# [h2o/picohttpparser](https://github.com/h2o/picohttpparser)\n\nPicoHTTPParser is a tiny, primitive, fast HTTP request/response parser.\n\n## License\n\n> Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase, Shigeo Mitsunari\n>\n> The software is dual-licensed under the Perl License or the MIT License.\n"
  },
  {
    "path": "thirdparty/picohttpparser/picohttpparser.c",
    "content": "#include \"src/picohttpparser.c\"\n\n#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))\n#define __WINDOWS__\n#endif\n\n// date\n#include <time.h>\n\nconst char* get_date() {\n\ttime_t t;\n\tstruct tm tm;\n\tstatic const char *days[] = {\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"};\n\tstatic const char *months[] = {\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"};\n\tstatic char date[30] = \"Thu, 01 Jan 1970 00:00:00 GMT\";\n\n\ttime(&t);\n\t#ifdef __WINDOWS__\n\t\tgmtime_s(&t, &tm);\n\t#else\n\t\tgmtime_r(&t, &tm);\n\t#endif\n\tstrftime(date, 30, \"---, %d --- %Y %H:%M:%S GMT\", &tm);\n\tmemcpy(date, days[tm.tm_wday], 3);\n\tmemcpy(date + 8, months[tm.tm_mon], 3);\n\n\treturn date;\n}\n"
  },
  {
    "path": "thirdparty/picohttpparser/picohttpparser.h",
    "content": "\ntypedef struct phr_header phr_header_t;\n\n#include \"src/picohttpparser.h\"\n#include <stdint.h>\n\n#define ADVANCE_TOKEN2(buf, tok, toklen, max_len) \\\n\tdo {\\\n\t\tfor (u32 i = 0; i < max_len; i++) {\\\n\t\t\tif (buf[i] == ' ') {\\\n\t\t\t\ttok = buf;\\\n\t\t\t\ttoklen = i++;\\\n\t\t\t\twhile (buf[i] == ' ') i++;\\\n\t\t\t\tbuf += i;\\\n\t\t\t\tbreak;\\\n\t\t\t}\\\n\t\t}\\\n\t} while (0)\n\nstatic inline int phr_parse_request_path(const char *buf_start, size_t len, const char **method, size_t *method_len, const char **path, size_t *path_len) {\n\tif (len < 14) return -2;\n\tconst char *buf = buf_start, *buf_end = buf_start + len;\n\n\tADVANCE_TOKEN2(buf, *method, *method_len, 9);\n\tlen -= buf-buf_start;\n\tADVANCE_TOKEN2(buf, *path, *path_len, len);\n\tif (*method_len == 0 || *path_len == 0) return -1;\n\n\treturn buf-buf_start;\n}\n\nstatic inline int phr_parse_request_path_pipeline(const char *buf_start, size_t len, const char **method, size_t *method_len, const char **path, size_t *path_len) {\n\tif (len < 14) return -2;\n\tconst char *buf = buf_start, *buf_end = buf_start + len;\n\n\tADVANCE_TOKEN2(buf, *method, *method_len, 9);\n\tlen -= buf-buf_start;\n\tADVANCE_TOKEN2(buf, *path, *path_len, len);\n\tif (*method_len == 0 || *path_len == 0) return -1;\n\n\twhile (buf < buf_end) {\n\t\t++buf;\n\t\tif (*(uint32_t*)buf == 0x0a0d0a0d) {\n\t\t\tbuf += 4;\n\t\t\treturn (int)(buf - buf_start);\n\t\t}\n\t};\n\n\treturn -1;\n}\n\n// date\nconst char* get_date();\n\n// branchlut\nconst char gDigitsLut[200] = {\n\t'0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',\n\t'1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',\n\t'2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',\n\t'3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',\n\t'4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',\n\t'5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',\n\t'6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',\n\t'7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',\n\t'8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',\n\t'9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'\n};\n\nstatic inline int u64toa(char* buf, uint64_t value) {\n\tconst char* b = buf;\n\tif (value < 100000000) {\n\t\tuint32_t v = (uint32_t)(value);\n\t\tif (v < 10000) {\n\t\t\tconst uint32_t d1 = (v / 100) << 1;\n\t\t\tconst uint32_t d2 = (v % 100) << 1;\n\n\t\t\tif (v >= 1000)\n\t\t\t\t*buf++ = gDigitsLut[d1];\n\t\t\tif (v >= 100)\n\t\t\t\t*buf++ = gDigitsLut[d1 + 1];\n\t\t\tif (v >= 10)\n\t\t\t\t*buf++ = gDigitsLut[d2];\n\t\t\t*buf++ = gDigitsLut[d2 + 1];\n\t\t}\n\t\telse {\n\t\t\t// value = bbbbcccc\n\t\t\tconst uint32_t b = v / 10000;\n\t\t\tconst uint32_t c = v % 10000;\n\n\t\t\tconst uint32_t d1 = (b / 100) << 1;\n\t\t\tconst uint32_t d2 = (b % 100) << 1;\n\n\t\t\tconst uint32_t d3 = (c / 100) << 1;\n\t\t\tconst uint32_t d4 = (c % 100) << 1;\n\n\t\t\tif (value >= 10000000)\n\t\t\t\t*buf++ = gDigitsLut[d1];\n\t\t\tif (value >= 1000000)\n\t\t\t\t*buf++ = gDigitsLut[d1 + 1];\n\t\t\tif (value >= 100000)\n\t\t\t\t*buf++ = gDigitsLut[d2];\n\t\t\t*buf++ = gDigitsLut[d2 + 1];\n\n\t\t\t*buf++ = gDigitsLut[d3];\n\t\t\t*buf++ = gDigitsLut[d3 + 1];\n\t\t\t*buf++ = gDigitsLut[d4];\n\t\t\t*buf++ = gDigitsLut[d4 + 1];\n\t\t}\n\t}\n\t// *buf = '\\0';\n\treturn buf - b;\n}\n"
  },
  {
    "path": "thirdparty/picohttpparser/src/README.md",
    "content": "PicoHTTPParser\n=============\n\nCopyright (c) 2009-2014 [Kazuho Oku](https://github.com/kazuho), [Tokuhiro Matsuno](https://github.com/tokuhirom), [Daisuke Murase](https://github.com/typester), [Shigeo Mitsunari](https://github.com/herumi)\n\nPicoHTTPParser is a tiny, primitive, fast HTTP request/response parser.\n\nUnlike most parsers, it is stateless and does not allocate memory by itself.\nAll it does is accept pointer to buffer and the output structure, and setups the pointers in the latter to point at the necessary portions of the buffer.\n\nThe code is widely deployed within Perl applications through popular modules that use it, including [Plack](https://metacpan.org/pod/Plack), [Starman](https://metacpan.org/pod/Starman), [Starlet](https://metacpan.org/pod/Starlet), [Furl](https://metacpan.org/pod/Furl).  It is also the HTTP/1 parser of [H2O](https://github.com/h2o/h2o).\n\nCheck out [test.c] to find out how to use the parser.\n\nThe software is dual-licensed under the Perl License or the MIT License.\n\nUsage\n-----\n\nThe library exposes four functions: `phr_parse_request`, `phr_parse_response`, `phr_parse_headers`, `phr_decode_chunked`.\n\n### phr_parse_request\n\nThe example below reads an HTTP request from socket `sock` using `read(2)`, parses it using `phr_parse_request`, and prints the details.\n\n```c\nchar buf[4096], *method, *path;\nint pret, minor_version;\nstruct phr_header headers[100];\nsize_t buflen = 0, prevbuflen = 0, method_len, path_len, num_headers;\nssize_t rret;\n\nwhile (1) {\n    /* read the request */\n    while ((rret = read(sock, buf + buflen, sizeof(buf) - buflen)) == -1 && errno == EINTR)\n        ;\n    if (rret <= 0)\n        return IOError;\n    prevbuflen = buflen;\n    buflen += rret;\n    /* parse the request */\n    num_headers = sizeof(headers) / sizeof(headers[0]);\n    pret = phr_parse_request(buf, buflen, &method, &method_len, &path, &path_len,\n                             &minor_version, headers, &num_headers, prevbuflen);\n    if (pret > 0)\n        break; /* successfully parsed the request */\n    else if (pret == -1)\n        return ParseError;\n    /* request is incomplete, continue the loop */\n    assert(pret == -2);\n    if (buflen == sizeof(buf))\n        return RequestIsTooLongError;\n}\n\nprintf(\"request is %d bytes long\\n\", pret);\nprintf(\"method is %.*s\\n\", (int)method_len, method);\nprintf(\"path is %.*s\\n\", (int)path_len, path);\nprintf(\"HTTP version is 1.%d\\n\", minor_version);\nprintf(\"headers:\\n\");\nfor (i = 0; i != num_headers; ++i) {\n    printf(\"%.*s: %.*s\\n\", (int)headers[i].name_len, headers[i].name,\n           (int)headers[i].value_len, headers[i].value);\n}\n```\n\n### phr_parse_response, phr_parse_headers\n\n`phr_parse_response` and `phr_parse_headers` provide similar interfaces as `phr_parse_request`.  `phr_parse_response` parses an HTTP response, and `phr_parse_headers` parses the headers only.\n\n### phr_decode_chunked\n\nThe example below decodes incoming data in chunked-encoding.  The data is decoded in-place.\n\n```c\nstruct phr_chunked_decoder decoder = {}; /* zero-clear */\nchar *buf = malloc(4096);\nsize_t size = 0, capacity = 4096, rsize;\nssize_t rret, pret;\n\n/* set consume_trailer to 1 to discard the trailing header, or the application\n * should call phr_parse_headers to parse the trailing header */\ndecoder.consume_trailer = 1;\n\ndo {\n    /* expand the buffer if necessary */\n    if (size == capacity) {\n        capacity *= 2;\n        buf = realloc(buf, capacity);\n        assert(buf != NULL);\n    }\n    /* read */\n    while ((rret = read(sock, buf + size, capacity - size)) == -1 && errno == EINTR)\n        ;\n    if (rret <= 0)\n        return IOError;\n    /* decode */\n    rsize = rret;\n    pret = phr_decode_chunked(&decoder, buf + size, &rsize);\n    if (pret == -1)\n        return ParseError;\n    size += rsize;\n} while (pret == -2);\n\n/* successfully decoded the chunked data */\nassert(pret >= 0);\nprintf(\"decoded data is at %p (%zu bytes)\\n\", buf, size);\n```\n\nBenchmark\n---------\n\n![benchmark results](http://i.gyazo.com/a85c18d3162dfb46b485bb41e0ad443a.png)\n\nThe benchmark code is from [fukamachi/fast-http@6b91103](https://github.com/fukamachi/fast-http/tree/6b9110347c7a3407310c08979aefd65078518478).\n\nThe internals of picohttpparser has been described to some extent in [my blog entry]( http://blog.kazuhooku.com/2014/11/the-internals-h2o-or-how-to-write-fast.html).\n"
  },
  {
    "path": "thirdparty/picohttpparser/src/picohttpparser.c",
    "content": "/*\n * Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,\n *                         Shigeo Mitsunari\n *\n * The software is licensed under either the MIT License (below) or the Perl\n * license.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n#include <assert.h>\n#include <stddef.h>\n#include <string.h>\n#ifdef __SSE4_2__\n#ifdef _MSC_VER\n#include <nmmintrin.h>\n#else\n#include <x86intrin.h>\n#endif\n#endif\n#include \"picohttpparser.h\"\n\n#if __GNUC__ >= 3\n#define likely(x) __builtin_expect(!!(x), 1)\n#define unlikely(x) __builtin_expect(!!(x), 0)\n#else\n#define likely(x) (x)\n#define unlikely(x) (x)\n#endif\n\n#ifdef _MSC_VER\n#define ALIGNED(n) _declspec(align(n))\n#else\n#define ALIGNED(n) __attribute__((aligned(n)))\n#endif\n\n#define IS_PRINTABLE_ASCII(c) ((unsigned char)(c)-040u < 0137u)\n\n#define CHECK_EOF()                                                                                                                \\\n    if (buf == buf_end) {                                                                                                          \\\n        *ret = -2;                                                                                                                 \\\n        return NULL;                                                                                                               \\\n    }\n\n#define EXPECT_CHAR_NO_CHECK(ch)                                                                                                   \\\n    if (*buf++ != ch) {                                                                                                            \\\n        *ret = -1;                                                                                                                 \\\n        return NULL;                                                                                                               \\\n    }\n\n#define EXPECT_CHAR(ch)                                                                                                            \\\n    CHECK_EOF();                                                                                                                   \\\n    EXPECT_CHAR_NO_CHECK(ch);\n\n#define ADVANCE_TOKEN(tok, toklen)                                                                                                 \\\n    do {                                                                                                                           \\\n        const char *tok_start = buf;                                                                                               \\\n        static const char ALIGNED(16) ranges2[16] = \"\\000\\040\\177\\177\";                                                            \\\n        int found2;                                                                                                                \\\n        buf = findchar_fast(buf, buf_end, ranges2, 4, &found2);                                                                    \\\n        if (!found2) {                                                                                                             \\\n            CHECK_EOF();                                                                                                           \\\n        }                                                                                                                          \\\n        while (1) {                                                                                                                \\\n            if (*buf == ' ') {                                                                                                     \\\n                break;                                                                                                             \\\n            } else if (unlikely(!IS_PRINTABLE_ASCII(*buf))) {                                                                      \\\n                if ((unsigned char)*buf < '\\040' || *buf == '\\177') {                                                              \\\n                    *ret = -1;                                                                                                     \\\n                    return NULL;                                                                                                   \\\n                }                                                                                                                  \\\n            }                                                                                                                      \\\n            ++buf;                                                                                                                 \\\n            CHECK_EOF();                                                                                                           \\\n        }                                                                                                                          \\\n        tok = tok_start;                                                                                                           \\\n        toklen = buf - tok_start;                                                                                                  \\\n    } while (0)\n\nstatic const char *token_char_map = \"\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\"\n                                    \"\\0\\1\\0\\1\\1\\1\\1\\1\\0\\0\\1\\1\\0\\1\\1\\0\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\0\\0\\0\\0\\0\\0\"\n                                    \"\\0\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\0\\0\\0\\1\\1\"\n                                    \"\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1\\0\\1\\0\\1\\0\"\n                                    \"\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\"\n                                    \"\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\"\n                                    \"\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\"\n                                    \"\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\";\n\nstatic const char *findchar_fast(const char *buf, const char *buf_end, const char *ranges, size_t ranges_size, int *found)\n{\n    *found = 0;\n#if __SSE4_2__\n    if (likely(buf_end - buf >= 16)) {\n        __m128i ranges16 = _mm_loadu_si128((const __m128i *)ranges);\n\n        size_t left = (buf_end - buf) & ~15;\n        do {\n            __m128i b16 = _mm_loadu_si128((const __m128i *)buf);\n            int r = _mm_cmpestri(ranges16, ranges_size, b16, 16, _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS);\n            if (unlikely(r != 16)) {\n                buf += r;\n                *found = 1;\n                break;\n            }\n            buf += 16;\n            left -= 16;\n        } while (likely(left != 0));\n    }\n#else\n    /* suppress unused parameter warning */\n    (void)buf_end;\n    (void)ranges;\n    (void)ranges_size;\n#endif\n    return buf;\n}\n\nstatic const char *get_token_to_eol(const char *buf, const char *buf_end, const char **token, size_t *token_len, int *ret)\n{\n    const char *token_start = buf;\n\n#ifdef __SSE4_2__\n    static const char ALIGNED(16) ranges1[16] = \"\\0\\010\"    /* allow HT */\n                                                \"\\012\\037\"  /* allow SP and up to but not including DEL */\n                                                \"\\177\\177\"; /* allow chars w. MSB set */\n    int found;\n    buf = findchar_fast(buf, buf_end, ranges1, 6, &found);\n    if (found)\n        goto FOUND_CTL;\n#else\n    /* find non-printable char within the next 8 bytes, this is the hottest code; manually inlined */\n    while (likely(buf_end - buf >= 8)) {\n#define DOIT()                                                                                                                     \\\n    do {                                                                                                                           \\\n        if (unlikely(!IS_PRINTABLE_ASCII(*buf)))                                                                                   \\\n            goto NonPrintable;                                                                                                     \\\n        ++buf;                                                                                                                     \\\n    } while (0)\n        DOIT();\n        DOIT();\n        DOIT();\n        DOIT();\n        DOIT();\n        DOIT();\n        DOIT();\n        DOIT();\n#undef DOIT\n        continue;\n    NonPrintable:\n        if ((likely((unsigned char)*buf < '\\040') && likely(*buf != '\\011')) || unlikely(*buf == '\\177')) {\n            goto FOUND_CTL;\n        }\n        ++buf;\n    }\n#endif\n    for (;; ++buf) {\n        CHECK_EOF();\n        if (unlikely(!IS_PRINTABLE_ASCII(*buf))) {\n            if ((likely((unsigned char)*buf < '\\040') && likely(*buf != '\\011')) || unlikely(*buf == '\\177')) {\n                goto FOUND_CTL;\n            }\n        }\n    }\nFOUND_CTL:\n    if (likely(*buf == '\\015')) {\n        ++buf;\n        EXPECT_CHAR('\\012');\n        *token_len = buf - 2 - token_start;\n    } else if (*buf == '\\012') {\n        *token_len = buf - token_start;\n        ++buf;\n    } else {\n        *ret = -1;\n        return NULL;\n    }\n    *token = token_start;\n\n    return buf;\n}\n\nstatic const char *is_complete(const char *buf, const char *buf_end, size_t last_len, int *ret)\n{\n    int ret_cnt = 0;\n    buf = last_len < 3 ? buf : buf + last_len - 3;\n\n    while (1) {\n        CHECK_EOF();\n        if (*buf == '\\015') {\n            ++buf;\n            CHECK_EOF();\n            EXPECT_CHAR('\\012');\n            ++ret_cnt;\n        } else if (*buf == '\\012') {\n            ++buf;\n            ++ret_cnt;\n        } else {\n            ++buf;\n            ret_cnt = 0;\n        }\n        if (ret_cnt == 2) {\n            return buf;\n        }\n    }\n\n    *ret = -2;\n    return NULL;\n}\n\n#define PARSE_INT(valp_, mul_)                                                                                                     \\\n    if (*buf < '0' || '9' < *buf) {                                                                                                \\\n        buf++;                                                                                                                     \\\n        *ret = -1;                                                                                                                 \\\n        return NULL;                                                                                                               \\\n    }                                                                                                                              \\\n    *(valp_) = (mul_) * (*buf++ - '0');\n\n#define PARSE_INT_3(valp_)                                                                                                         \\\n    do {                                                                                                                           \\\n        int res_ = 0;                                                                                                              \\\n        PARSE_INT(&res_, 100)                                                                                                      \\\n        *valp_ = res_;                                                                                                             \\\n        PARSE_INT(&res_, 10)                                                                                                       \\\n        *valp_ += res_;                                                                                                            \\\n        PARSE_INT(&res_, 1)                                                                                                        \\\n        *valp_ += res_;                                                                                                            \\\n    } while (0)\n\n/* returned pointer is always within [buf, buf_end), or null */\nstatic const char *parse_token(const char *buf, const char *buf_end, const char **token, size_t *token_len, char next_char,\n                               int *ret)\n{\n    /* We use pcmpestri to detect non-token characters. This instruction can take no more than eight character ranges (8*2*8=128\n     * bits that is the size of a SSE register). Due to this restriction, characters `|` and `~` are handled in the slow loop. */\n    static const char ALIGNED(16) ranges[] = \"\\x00 \"  /* control chars and up to SP */\n                                             \"\\\"\\\"\"   /* 0x22 */\n                                             \"()\"     /* 0x28,0x29 */\n                                             \",,\"     /* 0x2c */\n                                             \"//\"     /* 0x2f */\n                                             \":@\"     /* 0x3a-0x40 */\n                                             \"[]\"     /* 0x5b-0x5d */\n                                             \"{\\xff\"; /* 0x7b-0xff */\n    const char *buf_start = buf;\n    int found;\n    buf = findchar_fast(buf, buf_end, ranges, sizeof(ranges) - 1, &found);\n    if (!found) {\n        CHECK_EOF();\n    }\n    while (1) {\n        if (*buf == next_char) {\n            break;\n        } else if (!token_char_map[(unsigned char)*buf]) {\n            *ret = -1;\n            return NULL;\n        }\n        ++buf;\n        CHECK_EOF();\n    }\n    *token = buf_start;\n    *token_len = buf - buf_start;\n    return buf;\n}\n\n/* returned pointer is always within [buf, buf_end), or null */\nstatic const char *parse_http_version(const char *buf, const char *buf_end, int *minor_version, int *ret)\n{\n    /* we want at least [HTTP/1.<two chars>] to try to parse */\n    if (buf_end - buf < 9) {\n        *ret = -2;\n        return NULL;\n    }\n    EXPECT_CHAR_NO_CHECK('H');\n    EXPECT_CHAR_NO_CHECK('T');\n    EXPECT_CHAR_NO_CHECK('T');\n    EXPECT_CHAR_NO_CHECK('P');\n    EXPECT_CHAR_NO_CHECK('/');\n    EXPECT_CHAR_NO_CHECK('1');\n    EXPECT_CHAR_NO_CHECK('.');\n    PARSE_INT(minor_version, 1);\n    return buf;\n}\n\nstatic const char *parse_headers(const char *buf, const char *buf_end, struct phr_header *headers, size_t *num_headers,\n                                 size_t max_headers, int *ret)\n{\n    for (;; ++*num_headers) {\n        CHECK_EOF();\n        if (*buf == '\\015') {\n            ++buf;\n            EXPECT_CHAR('\\012');\n            break;\n        } else if (*buf == '\\012') {\n            ++buf;\n            break;\n        }\n        if (*num_headers == max_headers) {\n            *ret = -1;\n            return NULL;\n        }\n        if (!(*num_headers != 0 && (*buf == ' ' || *buf == '\\t'))) {\n            /* parsing name, but do not discard SP before colon, see\n             * http://www.mozilla.org/security/announce/2006/mfsa2006-33.html */\n            if ((buf = parse_token(buf, buf_end, &headers[*num_headers].name, &headers[*num_headers].name_len, ':', ret)) == NULL) {\n                return NULL;\n            }\n            if (headers[*num_headers].name_len == 0) {\n                *ret = -1;\n                return NULL;\n            }\n            ++buf;\n            for (;; ++buf) {\n                CHECK_EOF();\n                if (!(*buf == ' ' || *buf == '\\t')) {\n                    break;\n                }\n            }\n        } else {\n            headers[*num_headers].name = NULL;\n            headers[*num_headers].name_len = 0;\n        }\n        const char *value;\n        size_t value_len;\n        if ((buf = get_token_to_eol(buf, buf_end, &value, &value_len, ret)) == NULL) {\n            return NULL;\n        }\n        /* remove trailing SPs and HTABs */\n        const char *value_end = value + value_len;\n        for (; value_end != value; --value_end) {\n            const char c = *(value_end - 1);\n            if (!(c == ' ' || c == '\\t')) {\n                break;\n            }\n        }\n        headers[*num_headers].value = value;\n        headers[*num_headers].value_len = value_end - value;\n    }\n    return buf;\n}\n\nstatic const char *parse_request(const char *buf, const char *buf_end, const char **method, size_t *method_len, const char **path,\n                                 size_t *path_len, int *minor_version, struct phr_header *headers, size_t *num_headers,\n                                 size_t max_headers, int *ret)\n{\n    /* skip first empty line (some clients add CRLF after POST content) */\n    CHECK_EOF();\n    if (*buf == '\\015') {\n        ++buf;\n        EXPECT_CHAR('\\012');\n    } else if (*buf == '\\012') {\n        ++buf;\n    }\n\n    /* parse request line */\n    if ((buf = parse_token(buf, buf_end, method, method_len, ' ', ret)) == NULL) {\n        return NULL;\n    }\n    do {\n        ++buf;\n        CHECK_EOF();\n    } while (*buf == ' ');\n    ADVANCE_TOKEN(*path, *path_len);\n    do {\n        ++buf;\n        CHECK_EOF();\n    } while (*buf == ' ');\n    if (*method_len == 0 || *path_len == 0) {\n        *ret = -1;\n        return NULL;\n    }\n    if ((buf = parse_http_version(buf, buf_end, minor_version, ret)) == NULL) {\n        return NULL;\n    }\n    if (*buf == '\\015') {\n        ++buf;\n        EXPECT_CHAR('\\012');\n    } else if (*buf == '\\012') {\n        ++buf;\n    } else {\n        *ret = -1;\n        return NULL;\n    }\n\n    return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);\n}\n\nint phr_parse_request(const char *buf_start, size_t len, const char **method, size_t *method_len, const char **path,\n                      size_t *path_len, int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len)\n{\n    const char *buf = buf_start, *buf_end = buf_start + len;\n    size_t max_headers = *num_headers;\n    int r;\n\n    *method = NULL;\n    *method_len = 0;\n    *path = NULL;\n    *path_len = 0;\n    *minor_version = -1;\n    *num_headers = 0;\n\n    /* if last_len != 0, check if the request is complete (a fast countermeasure\n       againt slowloris */\n    if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {\n        return r;\n    }\n\n    if ((buf = parse_request(buf, buf_end, method, method_len, path, path_len, minor_version, headers, num_headers, max_headers,\n                             &r)) == NULL) {\n        return r;\n    }\n\n    return (int)(buf - buf_start);\n}\n\nstatic const char *parse_response(const char *buf, const char *buf_end, int *minor_version, int *status, const char **msg,\n                                  size_t *msg_len, struct phr_header *headers, size_t *num_headers, size_t max_headers, int *ret)\n{\n    /* parse \"HTTP/1.x\" */\n    if ((buf = parse_http_version(buf, buf_end, minor_version, ret)) == NULL) {\n        return NULL;\n    }\n    /* skip space */\n    if (*buf != ' ') {\n        *ret = -1;\n        return NULL;\n    }\n    do {\n        ++buf;\n        CHECK_EOF();\n    } while (*buf == ' ');\n    /* parse status code, we want at least [:digit:][:digit:][:digit:]<other char> to try to parse */\n    if (buf_end - buf < 4) {\n        *ret = -2;\n        return NULL;\n    }\n    PARSE_INT_3(status);\n\n    /* get message including preceding space */\n    if ((buf = get_token_to_eol(buf, buf_end, msg, msg_len, ret)) == NULL) {\n        return NULL;\n    }\n    if (*msg_len == 0) {\n        /* ok */\n    } else if (**msg == ' ') {\n        /* Remove preceding space. Successful return from `get_token_to_eol` guarantees that we would hit something other than SP\n         * before running past the end of the given buffer. */\n        do {\n            ++*msg;\n            --*msg_len;\n        } while (**msg == ' ');\n    } else {\n        /* garbage found after status code */\n        *ret = -1;\n        return NULL;\n    }\n\n    return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);\n}\n\nint phr_parse_response(const char *buf_start, size_t len, int *minor_version, int *status, const char **msg, size_t *msg_len,\n                       struct phr_header *headers, size_t *num_headers, size_t last_len)\n{\n    const char *buf = buf_start, *buf_end = buf + len;\n    size_t max_headers = *num_headers;\n    int r;\n\n    *minor_version = -1;\n    *status = 0;\n    *msg = NULL;\n    *msg_len = 0;\n    *num_headers = 0;\n\n    /* if last_len != 0, check if the response is complete (a fast countermeasure\n       against slowloris */\n    if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {\n        return r;\n    }\n\n    if ((buf = parse_response(buf, buf_end, minor_version, status, msg, msg_len, headers, num_headers, max_headers, &r)) == NULL) {\n        return r;\n    }\n\n    return (int)(buf - buf_start);\n}\n\nint phr_parse_headers(const char *buf_start, size_t len, struct phr_header *headers, size_t *num_headers, size_t last_len)\n{\n    const char *buf = buf_start, *buf_end = buf + len;\n    size_t max_headers = *num_headers;\n    int r;\n\n    *num_headers = 0;\n\n    /* if last_len != 0, check if the response is complete (a fast countermeasure\n       against slowloris */\n    if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {\n        return r;\n    }\n\n    if ((buf = parse_headers(buf, buf_end, headers, num_headers, max_headers, &r)) == NULL) {\n        return r;\n    }\n\n    return (int)(buf - buf_start);\n}\n\nenum {\n    CHUNKED_IN_CHUNK_SIZE,\n    CHUNKED_IN_CHUNK_EXT,\n    CHUNKED_IN_CHUNK_DATA,\n    CHUNKED_IN_CHUNK_CRLF,\n    CHUNKED_IN_TRAILERS_LINE_HEAD,\n    CHUNKED_IN_TRAILERS_LINE_MIDDLE\n};\n\nstatic int decode_hex(int ch)\n{\n    if ('0' <= ch && ch <= '9') {\n        return ch - '0';\n    } else if ('A' <= ch && ch <= 'F') {\n        return ch - 'A' + 0xa;\n    } else if ('a' <= ch && ch <= 'f') {\n        return ch - 'a' + 0xa;\n    } else {\n        return -1;\n    }\n}\n\nssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_t *_bufsz)\n{\n    size_t dst = 0, src = 0, bufsz = *_bufsz;\n    ssize_t ret = -2; /* incomplete */\n\n    decoder->_total_read += bufsz;\n\n    while (1) {\n        switch (decoder->_state) {\n        case CHUNKED_IN_CHUNK_SIZE:\n            for (;; ++src) {\n                int v;\n                if (src == bufsz)\n                    goto Exit;\n                if ((v = decode_hex(buf[src])) == -1) {\n                    if (decoder->_hex_count == 0) {\n                        ret = -1;\n                        goto Exit;\n                    }\n                    /* the only characters that may appear after the chunk size are BWS, semicolon, or CRLF */\n                    switch (buf[src]) {\n                    case ' ':\n                    case '\\011':\n                    case ';':\n                    case '\\012':\n                    case '\\015':\n                        break;\n                    default:\n                        ret = -1;\n                        goto Exit;\n                    }\n                    break;\n                }\n                if (decoder->_hex_count == sizeof(size_t) * 2) {\n                    ret = -1;\n                    goto Exit;\n                }\n                decoder->bytes_left_in_chunk = decoder->bytes_left_in_chunk * 16 + v;\n                ++decoder->_hex_count;\n            }\n            decoder->_hex_count = 0;\n            decoder->_state = CHUNKED_IN_CHUNK_EXT;\n        /* fallthru */\n        case CHUNKED_IN_CHUNK_EXT:\n            /* RFC 7230 A.2 \"Line folding in chunk extensions is disallowed\" */\n            for (;; ++src) {\n                if (src == bufsz)\n                    goto Exit;\n                if (buf[src] == '\\012')\n                    break;\n            }\n            ++src;\n            if (decoder->bytes_left_in_chunk == 0) {\n                if (decoder->consume_trailer) {\n                    decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD;\n                    break;\n                } else {\n                    goto Complete;\n                }\n            }\n            decoder->_state = CHUNKED_IN_CHUNK_DATA;\n        /* fallthru */\n        case CHUNKED_IN_CHUNK_DATA: {\n            size_t avail = bufsz - src;\n            if (avail < decoder->bytes_left_in_chunk) {\n                if (dst != src)\n                    memmove(buf + dst, buf + src, avail);\n                src += avail;\n                dst += avail;\n                decoder->bytes_left_in_chunk -= avail;\n                goto Exit;\n            }\n            if (dst != src)\n                memmove(buf + dst, buf + src, decoder->bytes_left_in_chunk);\n            src += decoder->bytes_left_in_chunk;\n            dst += decoder->bytes_left_in_chunk;\n            decoder->bytes_left_in_chunk = 0;\n            decoder->_state = CHUNKED_IN_CHUNK_CRLF;\n        }\n        /* fallthru */\n        case CHUNKED_IN_CHUNK_CRLF:\n            for (;; ++src) {\n                if (src == bufsz)\n                    goto Exit;\n                if (buf[src] != '\\015')\n                    break;\n            }\n            if (buf[src] != '\\012') {\n                ret = -1;\n                goto Exit;\n            }\n            ++src;\n            decoder->_state = CHUNKED_IN_CHUNK_SIZE;\n            break;\n        case CHUNKED_IN_TRAILERS_LINE_HEAD:\n            for (;; ++src) {\n                if (src == bufsz)\n                    goto Exit;\n                if (buf[src] != '\\015')\n                    break;\n            }\n            if (buf[src++] == '\\012')\n                goto Complete;\n            decoder->_state = CHUNKED_IN_TRAILERS_LINE_MIDDLE;\n        /* fallthru */\n        case CHUNKED_IN_TRAILERS_LINE_MIDDLE:\n            for (;; ++src) {\n                if (src == bufsz)\n                    goto Exit;\n                if (buf[src] == '\\012')\n                    break;\n            }\n            ++src;\n            decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD;\n            break;\n        default:\n            assert(!\"decoder is corrupt\");\n        }\n    }\n\nComplete:\n    ret = bufsz - src;\nExit:\n    if (dst != src)\n        memmove(buf + dst, buf + src, bufsz - src);\n    *_bufsz = dst;\n    /* if incomplete but the overhead of the chunked encoding is >=100KB and >80%, signal an error */\n    if (ret == -2) {\n        decoder->_total_overhead += bufsz - dst;\n        if (decoder->_total_overhead >= 100 * 1024 && decoder->_total_read - decoder->_total_overhead < decoder->_total_read / 4)\n            ret = -1;\n    }\n    return ret;\n}\n\nint phr_decode_chunked_is_in_data(struct phr_chunked_decoder *decoder)\n{\n    return decoder->_state == CHUNKED_IN_CHUNK_DATA;\n}\n\n#undef CHECK_EOF\n#undef EXPECT_CHAR\n#undef ADVANCE_TOKEN\n"
  },
  {
    "path": "thirdparty/picohttpparser/src/picohttpparser.h",
    "content": "/*\n * Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,\n *                         Shigeo Mitsunari\n *\n * The software is licensed under either the MIT License (below) or the Perl\n * license.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n#ifndef picohttpparser_h\n#define picohttpparser_h\n\n#include <stdint.h>\n#include <sys/types.h>\n\n#ifdef _MSC_VER\n#define ssize_t intptr_t\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* contains name and value of a header (name == NULL if is a continuing line\n * of a multiline header */\nstruct phr_header {\n    const char *name;\n    size_t name_len;\n    const char *value;\n    size_t value_len;\n};\n\n/* returns number of bytes consumed if successful, -2 if request is partial,\n * -1 if failed */\nint phr_parse_request(const char *buf, size_t len, const char **method, size_t *method_len, const char **path, size_t *path_len,\n                      int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len);\n\n/* ditto */\nint phr_parse_response(const char *_buf, size_t len, int *minor_version, int *status, const char **msg, size_t *msg_len,\n                       struct phr_header *headers, size_t *num_headers, size_t last_len);\n\n/* ditto */\nint phr_parse_headers(const char *buf, size_t len, struct phr_header *headers, size_t *num_headers, size_t last_len);\n\n/* should be zero-filled before start */\nstruct phr_chunked_decoder {\n    size_t bytes_left_in_chunk; /* number of bytes left in current chunk */\n    char consume_trailer;       /* if trailing headers should be consumed */\n    char _hex_count;\n    char _state;\n    uint64_t _total_read;\n    uint64_t _total_overhead;\n};\n\n/* the function rewrites the buffer given as (buf, bufsz) removing the chunked-\n * encoding headers.  When the function returns without an error, bufsz is\n * updated to the length of the decoded data available.  Applications should\n * repeatedly call the function while it returns -2 (incomplete) every time\n * supplying newly arrived data.  If the end of the chunked-encoded data is\n * found, the function returns a non-negative number indicating the number of\n * octets left undecoded, that starts from the offset returned by `*bufsz`.\n * Returns -1 on error.\n */\nssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_t *bufsz);\n\n/* returns if the chunked decoder is in middle of chunked data */\nint phr_decode_chunked_is_in_data(struct phr_chunked_decoder *decoder);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/sokol/README.md",
    "content": "# [floooh/sokol](https://github.com/floooh/sokol)\n\nMinimal cross-platform standalone C headers.\n\n## ZLib License\n\n```\nCopyright (c) 2018 Andre Weissflog\n\nThis software is provided 'as-is', without any express or implied warranty.\nIn no event will the authors be held liable for any damages arising from the\nuse of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n    1. The origin of this software must not be misrepresented; you must not\n    claim that you wrote the original software. If you use this software in a\n    product, an acknowledgment in the product documentation would be\n    appreciated but is not required.\n\n    2. Altered source versions must be plainly marked as such, and must not\n    be misrepresented as being the original software.\n\n    3. This notice may not be removed or altered from any source\n    distribution.\n```\n"
  },
  {
    "path": "thirdparty/sokol/cursor-shape-v1-client-protocol.h",
    "content": "/* Generated by wayland-scanner 1.24.0 */\n\n#ifndef CURSOR_SHAPE_V1_CLIENT_PROTOCOL_H\n#define CURSOR_SHAPE_V1_CLIENT_PROTOCOL_H\n\n#include <stdint.h>\n#include <stddef.h>\n#include \"wayland-client.h\"\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * @page page_cursor_shape_v1 The cursor_shape_v1 protocol\n * @section page_ifaces_cursor_shape_v1 Interfaces\n * - @subpage page_iface_wp_cursor_shape_manager_v1 - cursor shape manager\n * - @subpage page_iface_wp_cursor_shape_device_v1 - cursor shape for a device\n * @section page_copyright_cursor_shape_v1 Copyright\n * <pre>\n *\n * Copyright 2018 The Chromium Authors\n * Copyright 2023 Simon Ser\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n * The above copyright notice and this permission notice (including the next\n * paragraph) shall be included in all copies or substantial portions of the\n * Software.\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n * </pre>\n */\nstruct wl_pointer;\nstruct wp_cursor_shape_device_v1;\nstruct wp_cursor_shape_manager_v1;\nstruct zwp_tablet_tool_v2;\n\n#ifndef WP_CURSOR_SHAPE_MANAGER_V1_INTERFACE\n#define WP_CURSOR_SHAPE_MANAGER_V1_INTERFACE\n/**\n * @page page_iface_wp_cursor_shape_manager_v1 wp_cursor_shape_manager_v1\n * @section page_iface_wp_cursor_shape_manager_v1_desc Description\n *\n * This global offers an alternative, optional way to set cursor images. This\n * new way uses enumerated cursors instead of a wl_surface like\n * wl_pointer.set_cursor does.\n *\n * Warning! The protocol described in this file is currently in the testing\n * phase. Backward compatible changes may be added together with the\n * corresponding interface version bump. Backward incompatible changes can\n * only be done by creating a new major version of the extension.\n * @section page_iface_wp_cursor_shape_manager_v1_api API\n * See @ref iface_wp_cursor_shape_manager_v1.\n */\n/**\n * @defgroup iface_wp_cursor_shape_manager_v1 The wp_cursor_shape_manager_v1 interface\n *\n * This global offers an alternative, optional way to set cursor images. This\n * new way uses enumerated cursors instead of a wl_surface like\n * wl_pointer.set_cursor does.\n *\n * Warning! The protocol described in this file is currently in the testing\n * phase. Backward compatible changes may be added together with the\n * corresponding interface version bump. Backward incompatible changes can\n * only be done by creating a new major version of the extension.\n */\nextern const struct wl_interface wp_cursor_shape_manager_v1_interface;\n#endif\n#ifndef WP_CURSOR_SHAPE_DEVICE_V1_INTERFACE\n#define WP_CURSOR_SHAPE_DEVICE_V1_INTERFACE\n/**\n * @page page_iface_wp_cursor_shape_device_v1 wp_cursor_shape_device_v1\n * @section page_iface_wp_cursor_shape_device_v1_desc Description\n *\n * This interface allows clients to set the cursor shape.\n * @section page_iface_wp_cursor_shape_device_v1_api API\n * See @ref iface_wp_cursor_shape_device_v1.\n */\n/**\n * @defgroup iface_wp_cursor_shape_device_v1 The wp_cursor_shape_device_v1 interface\n *\n * This interface allows clients to set the cursor shape.\n */\nextern const struct wl_interface wp_cursor_shape_device_v1_interface;\n#endif\n\n#define WP_CURSOR_SHAPE_MANAGER_V1_DESTROY 0\n#define WP_CURSOR_SHAPE_MANAGER_V1_GET_POINTER 1\n#define WP_CURSOR_SHAPE_MANAGER_V1_GET_TABLET_TOOL_V2 2\n\n\n/**\n * @ingroup iface_wp_cursor_shape_manager_v1\n */\n#define WP_CURSOR_SHAPE_MANAGER_V1_DESTROY_SINCE_VERSION 1\n/**\n * @ingroup iface_wp_cursor_shape_manager_v1\n */\n#define WP_CURSOR_SHAPE_MANAGER_V1_GET_POINTER_SINCE_VERSION 1\n/**\n * @ingroup iface_wp_cursor_shape_manager_v1\n */\n#define WP_CURSOR_SHAPE_MANAGER_V1_GET_TABLET_TOOL_V2_SINCE_VERSION 1\n\n/** @ingroup iface_wp_cursor_shape_manager_v1 */\nstatic inline void\nwp_cursor_shape_manager_v1_set_user_data(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) wp_cursor_shape_manager_v1, user_data);\n}\n\n/** @ingroup iface_wp_cursor_shape_manager_v1 */\nstatic inline void *\nwp_cursor_shape_manager_v1_get_user_data(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) wp_cursor_shape_manager_v1);\n}\n\nstatic inline uint32_t\nwp_cursor_shape_manager_v1_get_version(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_manager_v1);\n}\n\n/**\n * @ingroup iface_wp_cursor_shape_manager_v1\n *\n * Destroy the cursor shape manager.\n */\nstatic inline void\nwp_cursor_shape_manager_v1_destroy(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) wp_cursor_shape_manager_v1,\n\t\t\t WP_CURSOR_SHAPE_MANAGER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_manager_v1), WL_MARSHAL_FLAG_DESTROY);\n}\n\n/**\n * @ingroup iface_wp_cursor_shape_manager_v1\n *\n * Obtain a wp_cursor_shape_device_v1 for a wl_pointer object.\n *\n * When the pointer capability is removed from the wl_seat, the\n * wp_cursor_shape_device_v1 object becomes inert.\n */\nstatic inline struct wp_cursor_shape_device_v1 *\nwp_cursor_shape_manager_v1_get_pointer(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1, struct wl_pointer *pointer)\n{\n\tstruct wl_proxy *cursor_shape_device;\n\n\tcursor_shape_device = wl_proxy_marshal_flags((struct wl_proxy *) wp_cursor_shape_manager_v1,\n\t\t\t WP_CURSOR_SHAPE_MANAGER_V1_GET_POINTER, &wp_cursor_shape_device_v1_interface, wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_manager_v1), 0, NULL, pointer);\n\n\treturn (struct wp_cursor_shape_device_v1 *) cursor_shape_device;\n}\n\n/**\n * @ingroup iface_wp_cursor_shape_manager_v1\n *\n * Obtain a wp_cursor_shape_device_v1 for a zwp_tablet_tool_v2 object.\n *\n * When the zwp_tablet_tool_v2 is removed, the wp_cursor_shape_device_v1\n * object becomes inert.\n */\nstatic inline struct wp_cursor_shape_device_v1 *\nwp_cursor_shape_manager_v1_get_tablet_tool_v2(struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager_v1, struct zwp_tablet_tool_v2 *tablet_tool)\n{\n\tstruct wl_proxy *cursor_shape_device;\n\n\tcursor_shape_device = wl_proxy_marshal_flags((struct wl_proxy *) wp_cursor_shape_manager_v1,\n\t\t\t WP_CURSOR_SHAPE_MANAGER_V1_GET_TABLET_TOOL_V2, &wp_cursor_shape_device_v1_interface, wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_manager_v1), 0, NULL, tablet_tool);\n\n\treturn (struct wp_cursor_shape_device_v1 *) cursor_shape_device;\n}\n\n#ifndef WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ENUM\n#define WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ENUM\n/**\n * @ingroup iface_wp_cursor_shape_device_v1\n * cursor shapes\n *\n * This enum describes cursor shapes.\n *\n * The names are taken from the CSS W3C specification:\n * https://w3c.github.io/csswg-drafts/css-ui/#cursor\n * with a few additions.\n *\n * Note that there are some groups of cursor shapes that are related:\n * The first group is drag-and-drop cursors which are used to indicate\n * the selected action during dnd operations. The second group is resize\n * cursors which are used to indicate resizing and moving possibilities\n * on window borders. It is recommended that the shapes in these groups\n * should use visually compatible images and metaphors.\n */\nenum wp_cursor_shape_device_v1_shape {\n\t/**\n\t * default cursor\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT = 1,\n\t/**\n\t * a context menu is available for the object under the cursor\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CONTEXT_MENU = 2,\n\t/**\n\t * help is available for the object under the cursor\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_HELP = 3,\n\t/**\n\t * pointer that indicates a link or another interactive element\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER = 4,\n\t/**\n\t * progress indicator\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_PROGRESS = 5,\n\t/**\n\t * program is busy, user should wait\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_WAIT = 6,\n\t/**\n\t * a cell or set of cells may be selected\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CELL = 7,\n\t/**\n\t * simple crosshair\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CROSSHAIR = 8,\n\t/**\n\t * text may be selected\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT = 9,\n\t/**\n\t * vertical text may be selected\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_VERTICAL_TEXT = 10,\n\t/**\n\t * drag-and-drop: alias of/shortcut to something is to be created\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALIAS = 11,\n\t/**\n\t * drag-and-drop: something is to be copied\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COPY = 12,\n\t/**\n\t * drag-and-drop: something is to be moved\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE = 13,\n\t/**\n\t * drag-and-drop: the dragged item cannot be dropped at the current cursor location\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NO_DROP = 14,\n\t/**\n\t * drag-and-drop: the requested action will not be carried out\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NOT_ALLOWED = 15,\n\t/**\n\t * drag-and-drop: something can be grabbed\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRAB = 16,\n\t/**\n\t * drag-and-drop: something is being grabbed\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRABBING = 17,\n\t/**\n\t * resizing: the east border is to be moved\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_E_RESIZE = 18,\n\t/**\n\t * resizing: the north border is to be moved\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_N_RESIZE = 19,\n\t/**\n\t * resizing: the north-east corner is to be moved\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NE_RESIZE = 20,\n\t/**\n\t * resizing: the north-west corner is to be moved\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NW_RESIZE = 21,\n\t/**\n\t * resizing: the south border is to be moved\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_S_RESIZE = 22,\n\t/**\n\t * resizing: the south-east corner is to be moved\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SE_RESIZE = 23,\n\t/**\n\t * resizing: the south-west corner is to be moved\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SW_RESIZE = 24,\n\t/**\n\t * resizing: the west border is to be moved\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_W_RESIZE = 25,\n\t/**\n\t * resizing: the east and west borders are to be moved\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_EW_RESIZE = 26,\n\t/**\n\t * resizing: the north and south borders are to be moved\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NS_RESIZE = 27,\n\t/**\n\t * resizing: the north-east and south-west corners are to be moved\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NESW_RESIZE = 28,\n\t/**\n\t * resizing: the north-west and south-east corners are to be moved\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NWSE_RESIZE = 29,\n\t/**\n\t * resizing: that the item/column can be resized horizontally\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COL_RESIZE = 30,\n\t/**\n\t * resizing: that the item/row can be resized vertically\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ROW_RESIZE = 31,\n\t/**\n\t * something can be scrolled in any direction\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_SCROLL = 32,\n\t/**\n\t * something can be zoomed in\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_IN = 33,\n\t/**\n\t * something can be zoomed out\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_OUT = 34,\n\t/**\n\t * drag-and-drop: the user will select which action will be carried out (non-css value)\n\t * @since 2\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DND_ASK = 35,\n\t/**\n\t * resizing: something can be moved or resized in any direction (non-css value)\n\t * @since 2\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_RESIZE = 36,\n};\n/**\n * @ingroup iface_wp_cursor_shape_device_v1\n */\n#define WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DND_ASK_SINCE_VERSION 2\n/**\n * @ingroup iface_wp_cursor_shape_device_v1\n */\n#define WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_RESIZE_SINCE_VERSION 2\n#endif /* WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ENUM */\n\n#ifndef WP_CURSOR_SHAPE_DEVICE_V1_ERROR_ENUM\n#define WP_CURSOR_SHAPE_DEVICE_V1_ERROR_ENUM\nenum wp_cursor_shape_device_v1_error {\n\t/**\n\t * the specified shape value is invalid\n\t */\n\tWP_CURSOR_SHAPE_DEVICE_V1_ERROR_INVALID_SHAPE = 1,\n};\n#endif /* WP_CURSOR_SHAPE_DEVICE_V1_ERROR_ENUM */\n\n#define WP_CURSOR_SHAPE_DEVICE_V1_DESTROY 0\n#define WP_CURSOR_SHAPE_DEVICE_V1_SET_SHAPE 1\n\n\n/**\n * @ingroup iface_wp_cursor_shape_device_v1\n */\n#define WP_CURSOR_SHAPE_DEVICE_V1_DESTROY_SINCE_VERSION 1\n/**\n * @ingroup iface_wp_cursor_shape_device_v1\n */\n#define WP_CURSOR_SHAPE_DEVICE_V1_SET_SHAPE_SINCE_VERSION 1\n\n/** @ingroup iface_wp_cursor_shape_device_v1 */\nstatic inline void\nwp_cursor_shape_device_v1_set_user_data(struct wp_cursor_shape_device_v1 *wp_cursor_shape_device_v1, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) wp_cursor_shape_device_v1, user_data);\n}\n\n/** @ingroup iface_wp_cursor_shape_device_v1 */\nstatic inline void *\nwp_cursor_shape_device_v1_get_user_data(struct wp_cursor_shape_device_v1 *wp_cursor_shape_device_v1)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) wp_cursor_shape_device_v1);\n}\n\nstatic inline uint32_t\nwp_cursor_shape_device_v1_get_version(struct wp_cursor_shape_device_v1 *wp_cursor_shape_device_v1)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_device_v1);\n}\n\n/**\n * @ingroup iface_wp_cursor_shape_device_v1\n *\n * Destroy the cursor shape device.\n *\n * The device cursor shape remains unchanged.\n */\nstatic inline void\nwp_cursor_shape_device_v1_destroy(struct wp_cursor_shape_device_v1 *wp_cursor_shape_device_v1)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) wp_cursor_shape_device_v1,\n\t\t\t WP_CURSOR_SHAPE_DEVICE_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_device_v1), WL_MARSHAL_FLAG_DESTROY);\n}\n\n/**\n * @ingroup iface_wp_cursor_shape_device_v1\n *\n * Sets the device cursor to the specified shape. The compositor will\n * change the cursor image based on the specified shape.\n *\n * The cursor actually changes only if the input device focus is one of\n * the requesting client's surfaces. If any, the previous cursor image\n * (surface or shape) is replaced.\n *\n * The \"shape\" argument must be a valid enum entry, otherwise the\n * invalid_shape protocol error is raised.\n *\n * This is similar to the wl_pointer.set_cursor and\n * zwp_tablet_tool_v2.set_cursor requests, but this request accepts a\n * shape instead of contents in the form of a surface. Clients can mix\n * set_cursor and set_shape requests.\n *\n * The serial parameter must match the latest wl_pointer.enter or\n * zwp_tablet_tool_v2.proximity_in serial number sent to the client.\n * Otherwise the request will be ignored.\n */\nstatic inline void\nwp_cursor_shape_device_v1_set_shape(struct wp_cursor_shape_device_v1 *wp_cursor_shape_device_v1, uint32_t serial, uint32_t shape)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) wp_cursor_shape_device_v1,\n\t\t\t WP_CURSOR_SHAPE_DEVICE_V1_SET_SHAPE, NULL, wl_proxy_get_version((struct wl_proxy *) wp_cursor_shape_device_v1), 0, serial, shape);\n}\n\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/sokol/cursor-shape-v1-protocol.c",
    "content": "/* Generated by wayland-scanner 1.24.0 */\n\n/*\n * Copyright 2018 The Chromium Authors\n * Copyright 2023 Simon Ser\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n * The above copyright notice and this permission notice (including the next\n * paragraph) shall be included in all copies or substantial portions of the\n * Software.\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include \"wayland-util.h\"\n\n#ifndef __has_attribute\n# define __has_attribute(x) 0  /* Compatibility with non-clang compilers. */\n#endif\n\n#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)\n#define WL_PRIVATE __attribute__ ((visibility(\"hidden\")))\n#else\n#define WL_PRIVATE\n#endif\n\nextern const struct wl_interface wl_pointer_interface;\nextern const struct wl_interface wp_cursor_shape_device_v1_interface;\nextern const struct wl_interface zwp_tablet_tool_v2_interface;\n\nstatic const struct wl_interface *cursor_shape_v1_types[] = {\n\tNULL,\n\tNULL,\n\t&wp_cursor_shape_device_v1_interface,\n\t&wl_pointer_interface,\n\t&wp_cursor_shape_device_v1_interface,\n\t&zwp_tablet_tool_v2_interface,\n};\n\nstatic const struct wl_message wp_cursor_shape_manager_v1_requests[] = {\n\t{ \"destroy\", \"\", cursor_shape_v1_types + 0 },\n\t{ \"get_pointer\", \"no\", cursor_shape_v1_types + 2 },\n\t{ \"get_tablet_tool_v2\", \"no\", cursor_shape_v1_types + 4 },\n};\n\nWL_PRIVATE const struct wl_interface wp_cursor_shape_manager_v1_interface = {\n\t\"wp_cursor_shape_manager_v1\", 2,\n\t3, wp_cursor_shape_manager_v1_requests,\n\t0, NULL,\n};\n\nstatic const struct wl_message wp_cursor_shape_device_v1_requests[] = {\n\t{ \"destroy\", \"\", cursor_shape_v1_types + 0 },\n\t{ \"set_shape\", \"uu\", cursor_shape_v1_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface wp_cursor_shape_device_v1_interface = {\n\t\"wp_cursor_shape_device_v1\", 2,\n\t2, wp_cursor_shape_device_v1_requests,\n\t0, NULL,\n};\n\n"
  },
  {
    "path": "thirdparty/sokol/fractional-scale-v1-client-protocol.h",
    "content": "/* Generated by wayland-scanner 1.24.0 */\n\n#ifndef FRACTIONAL_SCALE_V1_CLIENT_PROTOCOL_H\n#define FRACTIONAL_SCALE_V1_CLIENT_PROTOCOL_H\n\n#include <stdint.h>\n#include <stddef.h>\n#include \"wayland-client.h\"\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * @page page_fractional_scale_v1 The fractional_scale_v1 protocol\n * Protocol for requesting fractional surface scales\n *\n * @section page_desc_fractional_scale_v1 Description\n *\n * This protocol allows a compositor to suggest for surfaces to render at\n * fractional scales.\n *\n * A client can submit scaled content by utilizing wp_viewport. This is done by\n * creating a wp_viewport object for the surface and setting the destination\n * rectangle to the surface size before the scale factor is applied.\n *\n * The buffer size is calculated by multiplying the surface size by the\n * intended scale.\n *\n * The wl_surface buffer scale should remain set to 1.\n *\n * If a surface has a surface-local size of 100 px by 50 px and wishes to\n * submit buffers with a scale of 1.5, then a buffer of 150px by 75 px should\n * be used and the wp_viewport destination rectangle should be 100 px by 50 px.\n *\n * For toplevel surfaces, the size is rounded halfway away from zero. The\n * rounding algorithm for subsurface position and size is not defined.\n *\n * @section page_ifaces_fractional_scale_v1 Interfaces\n * - @subpage page_iface_wp_fractional_scale_manager_v1 - fractional surface scale information\n * - @subpage page_iface_wp_fractional_scale_v1 - fractional scale interface to a wl_surface\n * @section page_copyright_fractional_scale_v1 Copyright\n * <pre>\n *\n * Copyright © 2022 Kenny Levinsen\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice (including the next\n * paragraph) shall be included in all copies or substantial portions of the\n * Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n * </pre>\n */\nstruct wl_surface;\nstruct wp_fractional_scale_manager_v1;\nstruct wp_fractional_scale_v1;\n\n#ifndef WP_FRACTIONAL_SCALE_MANAGER_V1_INTERFACE\n#define WP_FRACTIONAL_SCALE_MANAGER_V1_INTERFACE\n/**\n * @page page_iface_wp_fractional_scale_manager_v1 wp_fractional_scale_manager_v1\n * @section page_iface_wp_fractional_scale_manager_v1_desc Description\n *\n * A global interface for requesting surfaces to use fractional scales.\n * @section page_iface_wp_fractional_scale_manager_v1_api API\n * See @ref iface_wp_fractional_scale_manager_v1.\n */\n/**\n * @defgroup iface_wp_fractional_scale_manager_v1 The wp_fractional_scale_manager_v1 interface\n *\n * A global interface for requesting surfaces to use fractional scales.\n */\nextern const struct wl_interface wp_fractional_scale_manager_v1_interface;\n#endif\n#ifndef WP_FRACTIONAL_SCALE_V1_INTERFACE\n#define WP_FRACTIONAL_SCALE_V1_INTERFACE\n/**\n * @page page_iface_wp_fractional_scale_v1 wp_fractional_scale_v1\n * @section page_iface_wp_fractional_scale_v1_desc Description\n *\n * An additional interface to a wl_surface object which allows the compositor\n * to inform the client of the preferred scale.\n * @section page_iface_wp_fractional_scale_v1_api API\n * See @ref iface_wp_fractional_scale_v1.\n */\n/**\n * @defgroup iface_wp_fractional_scale_v1 The wp_fractional_scale_v1 interface\n *\n * An additional interface to a wl_surface object which allows the compositor\n * to inform the client of the preferred scale.\n */\nextern const struct wl_interface wp_fractional_scale_v1_interface;\n#endif\n\n#ifndef WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_ENUM\n#define WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_ENUM\nenum wp_fractional_scale_manager_v1_error {\n\t/**\n\t * the surface already has a fractional_scale object associated\n\t */\n\tWP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_FRACTIONAL_SCALE_EXISTS = 0,\n};\n#endif /* WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_ENUM */\n\n#define WP_FRACTIONAL_SCALE_MANAGER_V1_DESTROY 0\n#define WP_FRACTIONAL_SCALE_MANAGER_V1_GET_FRACTIONAL_SCALE 1\n\n\n/**\n * @ingroup iface_wp_fractional_scale_manager_v1\n */\n#define WP_FRACTIONAL_SCALE_MANAGER_V1_DESTROY_SINCE_VERSION 1\n/**\n * @ingroup iface_wp_fractional_scale_manager_v1\n */\n#define WP_FRACTIONAL_SCALE_MANAGER_V1_GET_FRACTIONAL_SCALE_SINCE_VERSION 1\n\n/** @ingroup iface_wp_fractional_scale_manager_v1 */\nstatic inline void\nwp_fractional_scale_manager_v1_set_user_data(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) wp_fractional_scale_manager_v1, user_data);\n}\n\n/** @ingroup iface_wp_fractional_scale_manager_v1 */\nstatic inline void *\nwp_fractional_scale_manager_v1_get_user_data(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) wp_fractional_scale_manager_v1);\n}\n\nstatic inline uint32_t\nwp_fractional_scale_manager_v1_get_version(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_manager_v1);\n}\n\n/**\n * @ingroup iface_wp_fractional_scale_manager_v1\n *\n * Informs the server that the client will not be using this protocol\n * object anymore. This does not affect any other objects,\n * wp_fractional_scale_v1 objects included.\n */\nstatic inline void\nwp_fractional_scale_manager_v1_destroy(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) wp_fractional_scale_manager_v1,\n\t\t\t WP_FRACTIONAL_SCALE_MANAGER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_manager_v1), WL_MARSHAL_FLAG_DESTROY);\n}\n\n/**\n * @ingroup iface_wp_fractional_scale_manager_v1\n *\n * Create an add-on object for the the wl_surface to let the compositor\n * request fractional scales. If the given wl_surface already has a\n * wp_fractional_scale_v1 object associated, the fractional_scale_exists\n * protocol error is raised.\n */\nstatic inline struct wp_fractional_scale_v1 *\nwp_fractional_scale_manager_v1_get_fractional_scale(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1, struct wl_surface *surface)\n{\n\tstruct wl_proxy *id;\n\n\tid = wl_proxy_marshal_flags((struct wl_proxy *) wp_fractional_scale_manager_v1,\n\t\t\t WP_FRACTIONAL_SCALE_MANAGER_V1_GET_FRACTIONAL_SCALE, &wp_fractional_scale_v1_interface, wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_manager_v1), 0, NULL, surface);\n\n\treturn (struct wp_fractional_scale_v1 *) id;\n}\n\n/**\n * @ingroup iface_wp_fractional_scale_v1\n * @struct wp_fractional_scale_v1_listener\n */\nstruct wp_fractional_scale_v1_listener {\n\t/**\n\t * notify of new preferred scale\n\t *\n\t * Notification of a new preferred scale for this surface that\n\t * the compositor suggests that the client should use.\n\t *\n\t * The sent scale is the numerator of a fraction with a denominator\n\t * of 120.\n\t * @param scale the new preferred scale\n\t */\n\tvoid (*preferred_scale)(void *data,\n\t\t\t\tstruct wp_fractional_scale_v1 *wp_fractional_scale_v1,\n\t\t\t\tuint32_t scale);\n};\n\n/**\n * @ingroup iface_wp_fractional_scale_v1\n */\nstatic inline int\nwp_fractional_scale_v1_add_listener(struct wp_fractional_scale_v1 *wp_fractional_scale_v1,\n\t\t\t\t    const struct wp_fractional_scale_v1_listener *listener, void *data)\n{\n\treturn wl_proxy_add_listener((struct wl_proxy *) wp_fractional_scale_v1,\n\t\t\t\t     (void (**)(void)) listener, data);\n}\n\n#define WP_FRACTIONAL_SCALE_V1_DESTROY 0\n\n/**\n * @ingroup iface_wp_fractional_scale_v1\n */\n#define WP_FRACTIONAL_SCALE_V1_PREFERRED_SCALE_SINCE_VERSION 1\n\n/**\n * @ingroup iface_wp_fractional_scale_v1\n */\n#define WP_FRACTIONAL_SCALE_V1_DESTROY_SINCE_VERSION 1\n\n/** @ingroup iface_wp_fractional_scale_v1 */\nstatic inline void\nwp_fractional_scale_v1_set_user_data(struct wp_fractional_scale_v1 *wp_fractional_scale_v1, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) wp_fractional_scale_v1, user_data);\n}\n\n/** @ingroup iface_wp_fractional_scale_v1 */\nstatic inline void *\nwp_fractional_scale_v1_get_user_data(struct wp_fractional_scale_v1 *wp_fractional_scale_v1)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) wp_fractional_scale_v1);\n}\n\nstatic inline uint32_t\nwp_fractional_scale_v1_get_version(struct wp_fractional_scale_v1 *wp_fractional_scale_v1)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_v1);\n}\n\n/**\n * @ingroup iface_wp_fractional_scale_v1\n *\n * Destroy the fractional scale object. When this object is destroyed,\n * preferred_scale events will no longer be sent.\n */\nstatic inline void\nwp_fractional_scale_v1_destroy(struct wp_fractional_scale_v1 *wp_fractional_scale_v1)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) wp_fractional_scale_v1,\n\t\t\t WP_FRACTIONAL_SCALE_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_v1), WL_MARSHAL_FLAG_DESTROY);\n}\n\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/sokol/fractional-scale-v1-protocol.c",
    "content": "/* Generated by wayland-scanner 1.24.0 */\n\n/*\n * Copyright © 2022 Kenny Levinsen\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice (including the next\n * paragraph) shall be included in all copies or substantial portions of the\n * Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include \"wayland-util.h\"\n\n#ifndef __has_attribute\n# define __has_attribute(x) 0  /* Compatibility with non-clang compilers. */\n#endif\n\n#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)\n#define WL_PRIVATE __attribute__ ((visibility(\"hidden\")))\n#else\n#define WL_PRIVATE\n#endif\n\nextern const struct wl_interface wl_surface_interface;\nextern const struct wl_interface wp_fractional_scale_v1_interface;\n\nstatic const struct wl_interface *fractional_scale_v1_types[] = {\n\tNULL,\n\t&wp_fractional_scale_v1_interface,\n\t&wl_surface_interface,\n};\n\nstatic const struct wl_message wp_fractional_scale_manager_v1_requests[] = {\n\t{ \"destroy\", \"\", fractional_scale_v1_types + 0 },\n\t{ \"get_fractional_scale\", \"no\", fractional_scale_v1_types + 1 },\n};\n\nWL_PRIVATE const struct wl_interface wp_fractional_scale_manager_v1_interface = {\n\t\"wp_fractional_scale_manager_v1\", 1,\n\t2, wp_fractional_scale_manager_v1_requests,\n\t0, NULL,\n};\n\nstatic const struct wl_message wp_fractional_scale_v1_requests[] = {\n\t{ \"destroy\", \"\", fractional_scale_v1_types + 0 },\n};\n\nstatic const struct wl_message wp_fractional_scale_v1_events[] = {\n\t{ \"preferred_scale\", \"u\", fractional_scale_v1_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface wp_fractional_scale_v1_interface = {\n\t\"wp_fractional_scale_v1\", 1,\n\t1, wp_fractional_scale_v1_requests,\n\t1, wp_fractional_scale_v1_events,\n};\n\n"
  },
  {
    "path": "thirdparty/sokol/gen_wayland_protocols.vsh",
    "content": "#!/usr/bin/env -S v\n\nimport log\n\nfn sh(cmd string) {\n\tlog.info('Executing: ❯ ${cmd}')\n\tprint(execute_or_exit(cmd).output)\n}\n\nfn gen_protocol(protocols_dir string, output_dir string, name string, path string) {\n\tlog.info('Generating protocol: ${name}')\n\tsh('wayland-scanner client-header ${protocols_dir}/${path} ${output_dir}/${name}-client-protocol.h')\n\tsh('wayland-scanner private-code ${protocols_dir}/${path} ${output_dir}/${name}-protocol.c')\n}\n\nprotocols_dir := '/usr/share/wayland-protocols'\noutput_dir := '.'\nprotocols := {\n\t'xdg-shell':                       '/stable/xdg-shell/xdg-shell.xml'\n\t'viewporter':                      '/stable/viewporter/viewporter.xml'\n\t'fractional-scale-v1':             '/staging/fractional-scale/fractional-scale-v1.xml'\n\t'cursor-shape-v1':                 '/staging/cursor-shape/cursor-shape-v1.xml'\n\t'xdg-toplevel-icon-v1':            '/staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml'\n\t'tablet-unstable-v2':              '/unstable/tablet/tablet-unstable-v2.xml'\n\t'pointer-constraints-unstable-v1': '/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'\n\t'relative-pointer-unstable-v1':    '/unstable/relative-pointer/relative-pointer-unstable-v1.xml'\n\t'xdg-decoration-unstable-v1':      '/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'\n}\n\nfor protocol, path in protocols {\n\tgen_protocol(protocols_dir, output_dir, protocol, path)\n}\n"
  },
  {
    "path": "thirdparty/sokol/pointer-constraints-unstable-v1-client-protocol.h",
    "content": "/* Generated by wayland-scanner 1.24.0 */\n\n#ifndef POINTER_CONSTRAINTS_UNSTABLE_V1_CLIENT_PROTOCOL_H\n#define POINTER_CONSTRAINTS_UNSTABLE_V1_CLIENT_PROTOCOL_H\n\n#include <stdint.h>\n#include <stddef.h>\n#include \"wayland-client.h\"\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * @page page_pointer_constraints_unstable_v1 The pointer_constraints_unstable_v1 protocol\n * protocol for constraining pointer motions\n *\n * @section page_desc_pointer_constraints_unstable_v1 Description\n *\n * This protocol specifies a set of interfaces used for adding constraints to\n * the motion of a pointer. Possible constraints include confining pointer\n * motions to a given region, or locking it to its current position.\n *\n * In order to constrain the pointer, a client must first bind the global\n * interface \"wp_pointer_constraints\" which, if a compositor supports pointer\n * constraints, is exposed by the registry. Using the bound global object, the\n * client uses the request that corresponds to the type of constraint it wants\n * to make. See wp_pointer_constraints for more details.\n *\n * Warning! The protocol described in this file is experimental and backward\n * incompatible changes may be made. Backward compatible changes may be added\n * together with the corresponding interface version bump. Backward\n * incompatible changes are done by bumping the version number in the protocol\n * and interface names and resetting the interface version. Once the protocol\n * is to be declared stable, the 'z' prefix and the version number in the\n * protocol and interface names are removed and the interface version number is\n * reset.\n *\n * @section page_ifaces_pointer_constraints_unstable_v1 Interfaces\n * - @subpage page_iface_zwp_pointer_constraints_v1 - constrain the movement of a pointer\n * - @subpage page_iface_zwp_locked_pointer_v1 - receive relative pointer motion events\n * - @subpage page_iface_zwp_confined_pointer_v1 - confined pointer object\n * @section page_copyright_pointer_constraints_unstable_v1 Copyright\n * <pre>\n *\n * Copyright © 2014      Jonas Ådahl\n * Copyright © 2015      Red Hat Inc.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice (including the next\n * paragraph) shall be included in all copies or substantial portions of the\n * Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n * </pre>\n */\nstruct wl_pointer;\nstruct wl_region;\nstruct wl_surface;\nstruct zwp_confined_pointer_v1;\nstruct zwp_locked_pointer_v1;\nstruct zwp_pointer_constraints_v1;\n\n#ifndef ZWP_POINTER_CONSTRAINTS_V1_INTERFACE\n#define ZWP_POINTER_CONSTRAINTS_V1_INTERFACE\n/**\n * @page page_iface_zwp_pointer_constraints_v1 zwp_pointer_constraints_v1\n * @section page_iface_zwp_pointer_constraints_v1_desc Description\n *\n * The global interface exposing pointer constraining functionality. It\n * exposes two requests: lock_pointer for locking the pointer to its\n * position, and confine_pointer for locking the pointer to a region.\n *\n * The lock_pointer and confine_pointer requests create the objects\n * wp_locked_pointer and wp_confined_pointer respectively, and the client can\n * use these objects to interact with the lock.\n *\n * For any surface, only one lock or confinement may be active across all\n * wl_pointer objects of the same seat. If a lock or confinement is requested\n * when another lock or confinement is active or requested on the same surface\n * and with any of the wl_pointer objects of the same seat, an\n * 'already_constrained' error will be raised.\n * @section page_iface_zwp_pointer_constraints_v1_api API\n * See @ref iface_zwp_pointer_constraints_v1.\n */\n/**\n * @defgroup iface_zwp_pointer_constraints_v1 The zwp_pointer_constraints_v1 interface\n *\n * The global interface exposing pointer constraining functionality. It\n * exposes two requests: lock_pointer for locking the pointer to its\n * position, and confine_pointer for locking the pointer to a region.\n *\n * The lock_pointer and confine_pointer requests create the objects\n * wp_locked_pointer and wp_confined_pointer respectively, and the client can\n * use these objects to interact with the lock.\n *\n * For any surface, only one lock or confinement may be active across all\n * wl_pointer objects of the same seat. If a lock or confinement is requested\n * when another lock or confinement is active or requested on the same surface\n * and with any of the wl_pointer objects of the same seat, an\n * 'already_constrained' error will be raised.\n */\nextern const struct wl_interface zwp_pointer_constraints_v1_interface;\n#endif\n#ifndef ZWP_LOCKED_POINTER_V1_INTERFACE\n#define ZWP_LOCKED_POINTER_V1_INTERFACE\n/**\n * @page page_iface_zwp_locked_pointer_v1 zwp_locked_pointer_v1\n * @section page_iface_zwp_locked_pointer_v1_desc Description\n *\n * The wp_locked_pointer interface represents a locked pointer state.\n *\n * While the lock of this object is active, the wl_pointer objects of the\n * associated seat will not emit any wl_pointer.motion events.\n *\n * This object will send the event 'locked' when the lock is activated.\n * Whenever the lock is activated, it is guaranteed that the locked surface\n * will already have received pointer focus and that the pointer will be\n * within the region passed to the request creating this object.\n *\n * To unlock the pointer, send the destroy request. This will also destroy\n * the wp_locked_pointer object.\n *\n * If the compositor decides to unlock the pointer the unlocked event is\n * sent. See wp_locked_pointer.unlock for details.\n *\n * When unlocking, the compositor may warp the cursor position to the set\n * cursor position hint. If it does, it will not result in any relative\n * motion events emitted via wp_relative_pointer.\n *\n * If the surface the lock was requested on is destroyed and the lock is not\n * yet activated, the wp_locked_pointer object is now defunct and must be\n * destroyed.\n * @section page_iface_zwp_locked_pointer_v1_api API\n * See @ref iface_zwp_locked_pointer_v1.\n */\n/**\n * @defgroup iface_zwp_locked_pointer_v1 The zwp_locked_pointer_v1 interface\n *\n * The wp_locked_pointer interface represents a locked pointer state.\n *\n * While the lock of this object is active, the wl_pointer objects of the\n * associated seat will not emit any wl_pointer.motion events.\n *\n * This object will send the event 'locked' when the lock is activated.\n * Whenever the lock is activated, it is guaranteed that the locked surface\n * will already have received pointer focus and that the pointer will be\n * within the region passed to the request creating this object.\n *\n * To unlock the pointer, send the destroy request. This will also destroy\n * the wp_locked_pointer object.\n *\n * If the compositor decides to unlock the pointer the unlocked event is\n * sent. See wp_locked_pointer.unlock for details.\n *\n * When unlocking, the compositor may warp the cursor position to the set\n * cursor position hint. If it does, it will not result in any relative\n * motion events emitted via wp_relative_pointer.\n *\n * If the surface the lock was requested on is destroyed and the lock is not\n * yet activated, the wp_locked_pointer object is now defunct and must be\n * destroyed.\n */\nextern const struct wl_interface zwp_locked_pointer_v1_interface;\n#endif\n#ifndef ZWP_CONFINED_POINTER_V1_INTERFACE\n#define ZWP_CONFINED_POINTER_V1_INTERFACE\n/**\n * @page page_iface_zwp_confined_pointer_v1 zwp_confined_pointer_v1\n * @section page_iface_zwp_confined_pointer_v1_desc Description\n *\n * The wp_confined_pointer interface represents a confined pointer state.\n *\n * This object will send the event 'confined' when the confinement is\n * activated. Whenever the confinement is activated, it is guaranteed that\n * the surface the pointer is confined to will already have received pointer\n * focus and that the pointer will be within the region passed to the request\n * creating this object. It is up to the compositor to decide whether this\n * requires some user interaction and if the pointer will warp to within the\n * passed region if outside.\n *\n * To unconfine the pointer, send the destroy request. This will also destroy\n * the wp_confined_pointer object.\n *\n * If the compositor decides to unconfine the pointer the unconfined event is\n * sent. The wp_confined_pointer object is at this point defunct and should\n * be destroyed.\n * @section page_iface_zwp_confined_pointer_v1_api API\n * See @ref iface_zwp_confined_pointer_v1.\n */\n/**\n * @defgroup iface_zwp_confined_pointer_v1 The zwp_confined_pointer_v1 interface\n *\n * The wp_confined_pointer interface represents a confined pointer state.\n *\n * This object will send the event 'confined' when the confinement is\n * activated. Whenever the confinement is activated, it is guaranteed that\n * the surface the pointer is confined to will already have received pointer\n * focus and that the pointer will be within the region passed to the request\n * creating this object. It is up to the compositor to decide whether this\n * requires some user interaction and if the pointer will warp to within the\n * passed region if outside.\n *\n * To unconfine the pointer, send the destroy request. This will also destroy\n * the wp_confined_pointer object.\n *\n * If the compositor decides to unconfine the pointer the unconfined event is\n * sent. The wp_confined_pointer object is at this point defunct and should\n * be destroyed.\n */\nextern const struct wl_interface zwp_confined_pointer_v1_interface;\n#endif\n\n#ifndef ZWP_POINTER_CONSTRAINTS_V1_ERROR_ENUM\n#define ZWP_POINTER_CONSTRAINTS_V1_ERROR_ENUM\n/**\n * @ingroup iface_zwp_pointer_constraints_v1\n * wp_pointer_constraints error values\n *\n * These errors can be emitted in response to wp_pointer_constraints\n * requests.\n */\nenum zwp_pointer_constraints_v1_error {\n\t/**\n\t * pointer constraint already requested on that surface\n\t */\n\tZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED = 1,\n};\n#endif /* ZWP_POINTER_CONSTRAINTS_V1_ERROR_ENUM */\n\n#ifndef ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ENUM\n#define ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ENUM\n/**\n * @ingroup iface_zwp_pointer_constraints_v1\n * constraint lifetime\n *\n * These values represent different lifetime semantics. They are passed\n * as arguments to the factory requests to specify how the constraint\n * lifetimes should be managed.\n */\nenum zwp_pointer_constraints_v1_lifetime {\n\t/**\n\t * the pointer constraint is defunct once deactivated\n\t *\n\t * A oneshot pointer constraint will never reactivate once it has\n\t * been deactivated. See the corresponding deactivation event\n\t * (wp_locked_pointer.unlocked and wp_confined_pointer.unconfined)\n\t * for details.\n\t */\n\tZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT = 1,\n\t/**\n\t * the pointer constraint may reactivate\n\t *\n\t * A persistent pointer constraint may again reactivate once it\n\t * has been deactivated. See the corresponding deactivation event\n\t * (wp_locked_pointer.unlocked and wp_confined_pointer.unconfined)\n\t * for details.\n\t */\n\tZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT = 2,\n};\n#endif /* ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ENUM */\n\n#define ZWP_POINTER_CONSTRAINTS_V1_DESTROY 0\n#define ZWP_POINTER_CONSTRAINTS_V1_LOCK_POINTER 1\n#define ZWP_POINTER_CONSTRAINTS_V1_CONFINE_POINTER 2\n\n\n/**\n * @ingroup iface_zwp_pointer_constraints_v1\n */\n#define ZWP_POINTER_CONSTRAINTS_V1_DESTROY_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_pointer_constraints_v1\n */\n#define ZWP_POINTER_CONSTRAINTS_V1_LOCK_POINTER_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_pointer_constraints_v1\n */\n#define ZWP_POINTER_CONSTRAINTS_V1_CONFINE_POINTER_SINCE_VERSION 1\n\n/** @ingroup iface_zwp_pointer_constraints_v1 */\nstatic inline void\nzwp_pointer_constraints_v1_set_user_data(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) zwp_pointer_constraints_v1, user_data);\n}\n\n/** @ingroup iface_zwp_pointer_constraints_v1 */\nstatic inline void *\nzwp_pointer_constraints_v1_get_user_data(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) zwp_pointer_constraints_v1);\n}\n\nstatic inline uint32_t\nzwp_pointer_constraints_v1_get_version(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) zwp_pointer_constraints_v1);\n}\n\n/**\n * @ingroup iface_zwp_pointer_constraints_v1\n *\n * Used by the client to notify the server that it will no longer use this\n * pointer constraints object.\n */\nstatic inline void\nzwp_pointer_constraints_v1_destroy(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_pointer_constraints_v1,\n\t\t\t ZWP_POINTER_CONSTRAINTS_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_pointer_constraints_v1), WL_MARSHAL_FLAG_DESTROY);\n}\n\n/**\n * @ingroup iface_zwp_pointer_constraints_v1\n *\n * The lock_pointer request lets the client request to disable movements of\n * the virtual pointer (i.e. the cursor), effectively locking the pointer\n * to a position. This request may not take effect immediately; in the\n * future, when the compositor deems implementation-specific constraints\n * are satisfied, the pointer lock will be activated and the compositor\n * sends a locked event.\n *\n * The protocol provides no guarantee that the constraints are ever\n * satisfied, and does not require the compositor to send an error if the\n * constraints cannot ever be satisfied. It is thus possible to request a\n * lock that will never activate.\n *\n * There may not be another pointer constraint of any kind requested or\n * active on the surface for any of the wl_pointer objects of the seat of\n * the passed pointer when requesting a lock. If there is, an error will be\n * raised. See general pointer lock documentation for more details.\n *\n * The intersection of the region passed with this request and the input\n * region of the surface is used to determine where the pointer must be\n * in order for the lock to activate. It is up to the compositor whether to\n * warp the pointer or require some kind of user interaction for the lock\n * to activate. If the region is null the surface input region is used.\n *\n * A surface may receive pointer focus without the lock being activated.\n *\n * The request creates a new object wp_locked_pointer which is used to\n * interact with the lock as well as receive updates about its state. See\n * the the description of wp_locked_pointer for further information.\n *\n * Note that while a pointer is locked, the wl_pointer objects of the\n * corresponding seat will not emit any wl_pointer.motion events, but\n * relative motion events will still be emitted via wp_relative_pointer\n * objects of the same seat. wl_pointer.axis and wl_pointer.button events\n * are unaffected.\n */\nstatic inline struct zwp_locked_pointer_v1 *\nzwp_pointer_constraints_v1_lock_pointer(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1, struct wl_surface *surface, struct wl_pointer *pointer, struct wl_region *region, uint32_t lifetime)\n{\n\tstruct wl_proxy *id;\n\n\tid = wl_proxy_marshal_flags((struct wl_proxy *) zwp_pointer_constraints_v1,\n\t\t\t ZWP_POINTER_CONSTRAINTS_V1_LOCK_POINTER, &zwp_locked_pointer_v1_interface, wl_proxy_get_version((struct wl_proxy *) zwp_pointer_constraints_v1), 0, NULL, surface, pointer, region, lifetime);\n\n\treturn (struct zwp_locked_pointer_v1 *) id;\n}\n\n/**\n * @ingroup iface_zwp_pointer_constraints_v1\n *\n * The confine_pointer request lets the client request to confine the\n * pointer cursor to a given region. This request may not take effect\n * immediately; in the future, when the compositor deems implementation-\n * specific constraints are satisfied, the pointer confinement will be\n * activated and the compositor sends a confined event.\n *\n * The intersection of the region passed with this request and the input\n * region of the surface is used to determine where the pointer must be\n * in order for the confinement to activate. It is up to the compositor\n * whether to warp the pointer or require some kind of user interaction for\n * the confinement to activate. If the region is null the surface input\n * region is used.\n *\n * The request will create a new object wp_confined_pointer which is used\n * to interact with the confinement as well as receive updates about its\n * state. See the the description of wp_confined_pointer for further\n * information.\n */\nstatic inline struct zwp_confined_pointer_v1 *\nzwp_pointer_constraints_v1_confine_pointer(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1, struct wl_surface *surface, struct wl_pointer *pointer, struct wl_region *region, uint32_t lifetime)\n{\n\tstruct wl_proxy *id;\n\n\tid = wl_proxy_marshal_flags((struct wl_proxy *) zwp_pointer_constraints_v1,\n\t\t\t ZWP_POINTER_CONSTRAINTS_V1_CONFINE_POINTER, &zwp_confined_pointer_v1_interface, wl_proxy_get_version((struct wl_proxy *) zwp_pointer_constraints_v1), 0, NULL, surface, pointer, region, lifetime);\n\n\treturn (struct zwp_confined_pointer_v1 *) id;\n}\n\n/**\n * @ingroup iface_zwp_locked_pointer_v1\n * @struct zwp_locked_pointer_v1_listener\n */\nstruct zwp_locked_pointer_v1_listener {\n\t/**\n\t * lock activation event\n\t *\n\t * Notification that the pointer lock of the seat's pointer is\n\t * activated.\n\t */\n\tvoid (*locked)(void *data,\n\t\t       struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1);\n\t/**\n\t * lock deactivation event\n\t *\n\t * Notification that the pointer lock of the seat's pointer is no\n\t * longer active. If this is a oneshot pointer lock (see\n\t * wp_pointer_constraints.lifetime) this object is now defunct and\n\t * should be destroyed. If this is a persistent pointer lock (see\n\t * wp_pointer_constraints.lifetime) this pointer lock may again\n\t * reactivate in the future.\n\t */\n\tvoid (*unlocked)(void *data,\n\t\t\t struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1);\n};\n\n/**\n * @ingroup iface_zwp_locked_pointer_v1\n */\nstatic inline int\nzwp_locked_pointer_v1_add_listener(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1,\n\t\t\t\t   const struct zwp_locked_pointer_v1_listener *listener, void *data)\n{\n\treturn wl_proxy_add_listener((struct wl_proxy *) zwp_locked_pointer_v1,\n\t\t\t\t     (void (**)(void)) listener, data);\n}\n\n#define ZWP_LOCKED_POINTER_V1_DESTROY 0\n#define ZWP_LOCKED_POINTER_V1_SET_CURSOR_POSITION_HINT 1\n#define ZWP_LOCKED_POINTER_V1_SET_REGION 2\n\n/**\n * @ingroup iface_zwp_locked_pointer_v1\n */\n#define ZWP_LOCKED_POINTER_V1_LOCKED_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_locked_pointer_v1\n */\n#define ZWP_LOCKED_POINTER_V1_UNLOCKED_SINCE_VERSION 1\n\n/**\n * @ingroup iface_zwp_locked_pointer_v1\n */\n#define ZWP_LOCKED_POINTER_V1_DESTROY_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_locked_pointer_v1\n */\n#define ZWP_LOCKED_POINTER_V1_SET_CURSOR_POSITION_HINT_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_locked_pointer_v1\n */\n#define ZWP_LOCKED_POINTER_V1_SET_REGION_SINCE_VERSION 1\n\n/** @ingroup iface_zwp_locked_pointer_v1 */\nstatic inline void\nzwp_locked_pointer_v1_set_user_data(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) zwp_locked_pointer_v1, user_data);\n}\n\n/** @ingroup iface_zwp_locked_pointer_v1 */\nstatic inline void *\nzwp_locked_pointer_v1_get_user_data(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) zwp_locked_pointer_v1);\n}\n\nstatic inline uint32_t\nzwp_locked_pointer_v1_get_version(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) zwp_locked_pointer_v1);\n}\n\n/**\n * @ingroup iface_zwp_locked_pointer_v1\n *\n * Destroy the locked pointer object. If applicable, the compositor will\n * unlock the pointer.\n */\nstatic inline void\nzwp_locked_pointer_v1_destroy(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_locked_pointer_v1,\n\t\t\t ZWP_LOCKED_POINTER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_locked_pointer_v1), WL_MARSHAL_FLAG_DESTROY);\n}\n\n/**\n * @ingroup iface_zwp_locked_pointer_v1\n *\n * Set the cursor position hint relative to the top left corner of the\n * surface.\n *\n * If the client is drawing its own cursor, it should update the position\n * hint to the position of its own cursor. A compositor may use this\n * information to warp the pointer upon unlock in order to avoid pointer\n * jumps.\n *\n * The cursor position hint is double-buffered state, see\n * wl_surface.commit.\n */\nstatic inline void\nzwp_locked_pointer_v1_set_cursor_position_hint(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1, wl_fixed_t surface_x, wl_fixed_t surface_y)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_locked_pointer_v1,\n\t\t\t ZWP_LOCKED_POINTER_V1_SET_CURSOR_POSITION_HINT, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_locked_pointer_v1), 0, surface_x, surface_y);\n}\n\n/**\n * @ingroup iface_zwp_locked_pointer_v1\n *\n * Set a new region used to lock the pointer.\n *\n * The new lock region is double-buffered, see wl_surface.commit.\n *\n * For details about the lock region, see wp_locked_pointer.\n */\nstatic inline void\nzwp_locked_pointer_v1_set_region(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1, struct wl_region *region)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_locked_pointer_v1,\n\t\t\t ZWP_LOCKED_POINTER_V1_SET_REGION, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_locked_pointer_v1), 0, region);\n}\n\n/**\n * @ingroup iface_zwp_confined_pointer_v1\n * @struct zwp_confined_pointer_v1_listener\n */\nstruct zwp_confined_pointer_v1_listener {\n\t/**\n\t * pointer confined\n\t *\n\t * Notification that the pointer confinement of the seat's\n\t * pointer is activated.\n\t */\n\tvoid (*confined)(void *data,\n\t\t\t struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1);\n\t/**\n\t * pointer unconfined\n\t *\n\t * Notification that the pointer confinement of the seat's\n\t * pointer is no longer active. If this is a oneshot pointer\n\t * confinement (see wp_pointer_constraints.lifetime) this object is\n\t * now defunct and should be destroyed. If this is a persistent\n\t * pointer confinement (see wp_pointer_constraints.lifetime) this\n\t * pointer confinement may again reactivate in the future.\n\t */\n\tvoid (*unconfined)(void *data,\n\t\t\t   struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1);\n};\n\n/**\n * @ingroup iface_zwp_confined_pointer_v1\n */\nstatic inline int\nzwp_confined_pointer_v1_add_listener(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1,\n\t\t\t\t     const struct zwp_confined_pointer_v1_listener *listener, void *data)\n{\n\treturn wl_proxy_add_listener((struct wl_proxy *) zwp_confined_pointer_v1,\n\t\t\t\t     (void (**)(void)) listener, data);\n}\n\n#define ZWP_CONFINED_POINTER_V1_DESTROY 0\n#define ZWP_CONFINED_POINTER_V1_SET_REGION 1\n\n/**\n * @ingroup iface_zwp_confined_pointer_v1\n */\n#define ZWP_CONFINED_POINTER_V1_CONFINED_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_confined_pointer_v1\n */\n#define ZWP_CONFINED_POINTER_V1_UNCONFINED_SINCE_VERSION 1\n\n/**\n * @ingroup iface_zwp_confined_pointer_v1\n */\n#define ZWP_CONFINED_POINTER_V1_DESTROY_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_confined_pointer_v1\n */\n#define ZWP_CONFINED_POINTER_V1_SET_REGION_SINCE_VERSION 1\n\n/** @ingroup iface_zwp_confined_pointer_v1 */\nstatic inline void\nzwp_confined_pointer_v1_set_user_data(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) zwp_confined_pointer_v1, user_data);\n}\n\n/** @ingroup iface_zwp_confined_pointer_v1 */\nstatic inline void *\nzwp_confined_pointer_v1_get_user_data(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) zwp_confined_pointer_v1);\n}\n\nstatic inline uint32_t\nzwp_confined_pointer_v1_get_version(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) zwp_confined_pointer_v1);\n}\n\n/**\n * @ingroup iface_zwp_confined_pointer_v1\n *\n * Destroy the confined pointer object. If applicable, the compositor will\n * unconfine the pointer.\n */\nstatic inline void\nzwp_confined_pointer_v1_destroy(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_confined_pointer_v1,\n\t\t\t ZWP_CONFINED_POINTER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_confined_pointer_v1), WL_MARSHAL_FLAG_DESTROY);\n}\n\n/**\n * @ingroup iface_zwp_confined_pointer_v1\n *\n * Set a new region used to confine the pointer.\n *\n * The new confine region is double-buffered, see wl_surface.commit.\n *\n * If the confinement is active when the new confinement region is applied\n * and the pointer ends up outside of newly applied region, the pointer may\n * warped to a position within the new confinement region. If warped, a\n * wl_pointer.motion event will be emitted, but no\n * wp_relative_pointer.relative_motion event.\n *\n * The compositor may also, instead of using the new region, unconfine the\n * pointer.\n *\n * For details about the confine region, see wp_confined_pointer.\n */\nstatic inline void\nzwp_confined_pointer_v1_set_region(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1, struct wl_region *region)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_confined_pointer_v1,\n\t\t\t ZWP_CONFINED_POINTER_V1_SET_REGION, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_confined_pointer_v1), 0, region);\n}\n\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/sokol/pointer-constraints-unstable-v1-protocol.c",
    "content": "/* Generated by wayland-scanner 1.24.0 */\n\n/*\n * Copyright © 2014      Jonas Ådahl\n * Copyright © 2015      Red Hat Inc.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice (including the next\n * paragraph) shall be included in all copies or substantial portions of the\n * Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include \"wayland-util.h\"\n\n#ifndef __has_attribute\n# define __has_attribute(x) 0  /* Compatibility with non-clang compilers. */\n#endif\n\n#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)\n#define WL_PRIVATE __attribute__ ((visibility(\"hidden\")))\n#else\n#define WL_PRIVATE\n#endif\n\nextern const struct wl_interface wl_pointer_interface;\nextern const struct wl_interface wl_region_interface;\nextern const struct wl_interface wl_surface_interface;\nextern const struct wl_interface zwp_confined_pointer_v1_interface;\nextern const struct wl_interface zwp_locked_pointer_v1_interface;\n\nstatic const struct wl_interface *pointer_constraints_unstable_v1_types[] = {\n\tNULL,\n\tNULL,\n\t&zwp_locked_pointer_v1_interface,\n\t&wl_surface_interface,\n\t&wl_pointer_interface,\n\t&wl_region_interface,\n\tNULL,\n\t&zwp_confined_pointer_v1_interface,\n\t&wl_surface_interface,\n\t&wl_pointer_interface,\n\t&wl_region_interface,\n\tNULL,\n\t&wl_region_interface,\n\t&wl_region_interface,\n};\n\nstatic const struct wl_message zwp_pointer_constraints_v1_requests[] = {\n\t{ \"destroy\", \"\", pointer_constraints_unstable_v1_types + 0 },\n\t{ \"lock_pointer\", \"noo?ou\", pointer_constraints_unstable_v1_types + 2 },\n\t{ \"confine_pointer\", \"noo?ou\", pointer_constraints_unstable_v1_types + 7 },\n};\n\nWL_PRIVATE const struct wl_interface zwp_pointer_constraints_v1_interface = {\n\t\"zwp_pointer_constraints_v1\", 1,\n\t3, zwp_pointer_constraints_v1_requests,\n\t0, NULL,\n};\n\nstatic const struct wl_message zwp_locked_pointer_v1_requests[] = {\n\t{ \"destroy\", \"\", pointer_constraints_unstable_v1_types + 0 },\n\t{ \"set_cursor_position_hint\", \"ff\", pointer_constraints_unstable_v1_types + 0 },\n\t{ \"set_region\", \"?o\", pointer_constraints_unstable_v1_types + 12 },\n};\n\nstatic const struct wl_message zwp_locked_pointer_v1_events[] = {\n\t{ \"locked\", \"\", pointer_constraints_unstable_v1_types + 0 },\n\t{ \"unlocked\", \"\", pointer_constraints_unstable_v1_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface zwp_locked_pointer_v1_interface = {\n\t\"zwp_locked_pointer_v1\", 1,\n\t3, zwp_locked_pointer_v1_requests,\n\t2, zwp_locked_pointer_v1_events,\n};\n\nstatic const struct wl_message zwp_confined_pointer_v1_requests[] = {\n\t{ \"destroy\", \"\", pointer_constraints_unstable_v1_types + 0 },\n\t{ \"set_region\", \"?o\", pointer_constraints_unstable_v1_types + 13 },\n};\n\nstatic const struct wl_message zwp_confined_pointer_v1_events[] = {\n\t{ \"confined\", \"\", pointer_constraints_unstable_v1_types + 0 },\n\t{ \"unconfined\", \"\", pointer_constraints_unstable_v1_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface zwp_confined_pointer_v1_interface = {\n\t\"zwp_confined_pointer_v1\", 1,\n\t2, zwp_confined_pointer_v1_requests,\n\t2, zwp_confined_pointer_v1_events,\n};\n\n"
  },
  {
    "path": "thirdparty/sokol/relative-pointer-unstable-v1-client-protocol.h",
    "content": "/* Generated by wayland-scanner 1.24.0 */\n\n#ifndef RELATIVE_POINTER_UNSTABLE_V1_CLIENT_PROTOCOL_H\n#define RELATIVE_POINTER_UNSTABLE_V1_CLIENT_PROTOCOL_H\n\n#include <stdint.h>\n#include <stddef.h>\n#include \"wayland-client.h\"\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * @page page_relative_pointer_unstable_v1 The relative_pointer_unstable_v1 protocol\n * protocol for relative pointer motion events\n *\n * @section page_desc_relative_pointer_unstable_v1 Description\n *\n * This protocol specifies a set of interfaces used for making clients able to\n * receive relative pointer events not obstructed by barriers (such as the\n * monitor edge or other pointer barriers).\n *\n * To start receiving relative pointer events, a client must first bind the\n * global interface \"wp_relative_pointer_manager\" which, if a compositor\n * supports relative pointer motion events, is exposed by the registry. After\n * having created the relative pointer manager proxy object, the client uses\n * it to create the actual relative pointer object using the\n * \"get_relative_pointer\" request given a wl_pointer. The relative pointer\n * motion events will then, when applicable, be transmitted via the proxy of\n * the newly created relative pointer object. See the documentation of the\n * relative pointer interface for more details.\n *\n * Warning! The protocol described in this file is experimental and backward\n * incompatible changes may be made. Backward compatible changes may be added\n * together with the corresponding interface version bump. Backward\n * incompatible changes are done by bumping the version number in the protocol\n * and interface names and resetting the interface version. Once the protocol\n * is to be declared stable, the 'z' prefix and the version number in the\n * protocol and interface names are removed and the interface version number is\n * reset.\n *\n * @section page_ifaces_relative_pointer_unstable_v1 Interfaces\n * - @subpage page_iface_zwp_relative_pointer_manager_v1 - get relative pointer objects\n * - @subpage page_iface_zwp_relative_pointer_v1 - relative pointer object\n * @section page_copyright_relative_pointer_unstable_v1 Copyright\n * <pre>\n *\n * Copyright © 2014      Jonas Ådahl\n * Copyright © 2015      Red Hat Inc.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice (including the next\n * paragraph) shall be included in all copies or substantial portions of the\n * Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n * </pre>\n */\nstruct wl_pointer;\nstruct zwp_relative_pointer_manager_v1;\nstruct zwp_relative_pointer_v1;\n\n#ifndef ZWP_RELATIVE_POINTER_MANAGER_V1_INTERFACE\n#define ZWP_RELATIVE_POINTER_MANAGER_V1_INTERFACE\n/**\n * @page page_iface_zwp_relative_pointer_manager_v1 zwp_relative_pointer_manager_v1\n * @section page_iface_zwp_relative_pointer_manager_v1_desc Description\n *\n * A global interface used for getting the relative pointer object for a\n * given pointer.\n * @section page_iface_zwp_relative_pointer_manager_v1_api API\n * See @ref iface_zwp_relative_pointer_manager_v1.\n */\n/**\n * @defgroup iface_zwp_relative_pointer_manager_v1 The zwp_relative_pointer_manager_v1 interface\n *\n * A global interface used for getting the relative pointer object for a\n * given pointer.\n */\nextern const struct wl_interface zwp_relative_pointer_manager_v1_interface;\n#endif\n#ifndef ZWP_RELATIVE_POINTER_V1_INTERFACE\n#define ZWP_RELATIVE_POINTER_V1_INTERFACE\n/**\n * @page page_iface_zwp_relative_pointer_v1 zwp_relative_pointer_v1\n * @section page_iface_zwp_relative_pointer_v1_desc Description\n *\n * A wp_relative_pointer object is an extension to the wl_pointer interface\n * used for emitting relative pointer events. It shares the same focus as\n * wl_pointer objects of the same seat and will only emit events when it has\n * focus.\n * @section page_iface_zwp_relative_pointer_v1_api API\n * See @ref iface_zwp_relative_pointer_v1.\n */\n/**\n * @defgroup iface_zwp_relative_pointer_v1 The zwp_relative_pointer_v1 interface\n *\n * A wp_relative_pointer object is an extension to the wl_pointer interface\n * used for emitting relative pointer events. It shares the same focus as\n * wl_pointer objects of the same seat and will only emit events when it has\n * focus.\n */\nextern const struct wl_interface zwp_relative_pointer_v1_interface;\n#endif\n\n#define ZWP_RELATIVE_POINTER_MANAGER_V1_DESTROY 0\n#define ZWP_RELATIVE_POINTER_MANAGER_V1_GET_RELATIVE_POINTER 1\n\n\n/**\n * @ingroup iface_zwp_relative_pointer_manager_v1\n */\n#define ZWP_RELATIVE_POINTER_MANAGER_V1_DESTROY_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_relative_pointer_manager_v1\n */\n#define ZWP_RELATIVE_POINTER_MANAGER_V1_GET_RELATIVE_POINTER_SINCE_VERSION 1\n\n/** @ingroup iface_zwp_relative_pointer_manager_v1 */\nstatic inline void\nzwp_relative_pointer_manager_v1_set_user_data(struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) zwp_relative_pointer_manager_v1, user_data);\n}\n\n/** @ingroup iface_zwp_relative_pointer_manager_v1 */\nstatic inline void *\nzwp_relative_pointer_manager_v1_get_user_data(struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) zwp_relative_pointer_manager_v1);\n}\n\nstatic inline uint32_t\nzwp_relative_pointer_manager_v1_get_version(struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) zwp_relative_pointer_manager_v1);\n}\n\n/**\n * @ingroup iface_zwp_relative_pointer_manager_v1\n *\n * Used by the client to notify the server that it will no longer use this\n * relative pointer manager object.\n */\nstatic inline void\nzwp_relative_pointer_manager_v1_destroy(struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_relative_pointer_manager_v1,\n\t\t\t ZWP_RELATIVE_POINTER_MANAGER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_relative_pointer_manager_v1), WL_MARSHAL_FLAG_DESTROY);\n}\n\n/**\n * @ingroup iface_zwp_relative_pointer_manager_v1\n *\n * Create a relative pointer interface given a wl_pointer object. See the\n * wp_relative_pointer interface for more details.\n */\nstatic inline struct zwp_relative_pointer_v1 *\nzwp_relative_pointer_manager_v1_get_relative_pointer(struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1, struct wl_pointer *pointer)\n{\n\tstruct wl_proxy *id;\n\n\tid = wl_proxy_marshal_flags((struct wl_proxy *) zwp_relative_pointer_manager_v1,\n\t\t\t ZWP_RELATIVE_POINTER_MANAGER_V1_GET_RELATIVE_POINTER, &zwp_relative_pointer_v1_interface, wl_proxy_get_version((struct wl_proxy *) zwp_relative_pointer_manager_v1), 0, NULL, pointer);\n\n\treturn (struct zwp_relative_pointer_v1 *) id;\n}\n\n/**\n * @ingroup iface_zwp_relative_pointer_v1\n * @struct zwp_relative_pointer_v1_listener\n */\nstruct zwp_relative_pointer_v1_listener {\n\t/**\n\t * relative pointer motion\n\t *\n\t * Relative x/y pointer motion from the pointer of the seat\n\t * associated with this object.\n\t *\n\t * A relative motion is in the same dimension as regular wl_pointer\n\t * motion events, except they do not represent an absolute\n\t * position. For example, moving a pointer from (x, y) to (x', y')\n\t * would have the equivalent relative motion (x' - x, y' - y). If a\n\t * pointer motion caused the absolute pointer position to be\n\t * clipped by for example the edge of the monitor, the relative\n\t * motion is unaffected by the clipping and will represent the\n\t * unclipped motion.\n\t *\n\t * This event also contains non-accelerated motion deltas. The\n\t * non-accelerated delta is, when applicable, the regular pointer\n\t * motion delta as it was before having applied motion acceleration\n\t * and other transformations such as normalization.\n\t *\n\t * Note that the non-accelerated delta does not represent 'raw'\n\t * events as they were read from some device. Pointer motion\n\t * acceleration is device- and configuration-specific and\n\t * non-accelerated deltas and accelerated deltas may have the same\n\t * value on some devices.\n\t *\n\t * Relative motions are not coupled to wl_pointer.motion events,\n\t * and can be sent in combination with such events, but also\n\t * independently. There may also be scenarios where\n\t * wl_pointer.motion is sent, but there is no relative motion. The\n\t * order of an absolute and relative motion event originating from\n\t * the same physical motion is not guaranteed.\n\t *\n\t * If the client needs button events or focus state, it can receive\n\t * them from a wl_pointer object of the same seat that the\n\t * wp_relative_pointer object is associated with.\n\t * @param utime_hi high 32 bits of a 64 bit timestamp with microsecond granularity\n\t * @param utime_lo low 32 bits of a 64 bit timestamp with microsecond granularity\n\t * @param dx the x component of the motion vector\n\t * @param dy the y component of the motion vector\n\t * @param dx_unaccel the x component of the unaccelerated motion vector\n\t * @param dy_unaccel the y component of the unaccelerated motion vector\n\t */\n\tvoid (*relative_motion)(void *data,\n\t\t\t\tstruct zwp_relative_pointer_v1 *zwp_relative_pointer_v1,\n\t\t\t\tuint32_t utime_hi,\n\t\t\t\tuint32_t utime_lo,\n\t\t\t\twl_fixed_t dx,\n\t\t\t\twl_fixed_t dy,\n\t\t\t\twl_fixed_t dx_unaccel,\n\t\t\t\twl_fixed_t dy_unaccel);\n};\n\n/**\n * @ingroup iface_zwp_relative_pointer_v1\n */\nstatic inline int\nzwp_relative_pointer_v1_add_listener(struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1,\n\t\t\t\t     const struct zwp_relative_pointer_v1_listener *listener, void *data)\n{\n\treturn wl_proxy_add_listener((struct wl_proxy *) zwp_relative_pointer_v1,\n\t\t\t\t     (void (**)(void)) listener, data);\n}\n\n#define ZWP_RELATIVE_POINTER_V1_DESTROY 0\n\n/**\n * @ingroup iface_zwp_relative_pointer_v1\n */\n#define ZWP_RELATIVE_POINTER_V1_RELATIVE_MOTION_SINCE_VERSION 1\n\n/**\n * @ingroup iface_zwp_relative_pointer_v1\n */\n#define ZWP_RELATIVE_POINTER_V1_DESTROY_SINCE_VERSION 1\n\n/** @ingroup iface_zwp_relative_pointer_v1 */\nstatic inline void\nzwp_relative_pointer_v1_set_user_data(struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) zwp_relative_pointer_v1, user_data);\n}\n\n/** @ingroup iface_zwp_relative_pointer_v1 */\nstatic inline void *\nzwp_relative_pointer_v1_get_user_data(struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) zwp_relative_pointer_v1);\n}\n\nstatic inline uint32_t\nzwp_relative_pointer_v1_get_version(struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) zwp_relative_pointer_v1);\n}\n\n/**\n * @ingroup iface_zwp_relative_pointer_v1\n */\nstatic inline void\nzwp_relative_pointer_v1_destroy(struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_relative_pointer_v1,\n\t\t\t ZWP_RELATIVE_POINTER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_relative_pointer_v1), WL_MARSHAL_FLAG_DESTROY);\n}\n\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/sokol/relative-pointer-unstable-v1-protocol.c",
    "content": "/* Generated by wayland-scanner 1.24.0 */\n\n/*\n * Copyright © 2014      Jonas Ådahl\n * Copyright © 2015      Red Hat Inc.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice (including the next\n * paragraph) shall be included in all copies or substantial portions of the\n * Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include \"wayland-util.h\"\n\n#ifndef __has_attribute\n# define __has_attribute(x) 0  /* Compatibility with non-clang compilers. */\n#endif\n\n#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)\n#define WL_PRIVATE __attribute__ ((visibility(\"hidden\")))\n#else\n#define WL_PRIVATE\n#endif\n\nextern const struct wl_interface wl_pointer_interface;\nextern const struct wl_interface zwp_relative_pointer_v1_interface;\n\nstatic const struct wl_interface *relative_pointer_unstable_v1_types[] = {\n\tNULL,\n\tNULL,\n\tNULL,\n\tNULL,\n\tNULL,\n\tNULL,\n\t&zwp_relative_pointer_v1_interface,\n\t&wl_pointer_interface,\n};\n\nstatic const struct wl_message zwp_relative_pointer_manager_v1_requests[] = {\n\t{ \"destroy\", \"\", relative_pointer_unstable_v1_types + 0 },\n\t{ \"get_relative_pointer\", \"no\", relative_pointer_unstable_v1_types + 6 },\n};\n\nWL_PRIVATE const struct wl_interface zwp_relative_pointer_manager_v1_interface = {\n\t\"zwp_relative_pointer_manager_v1\", 1,\n\t2, zwp_relative_pointer_manager_v1_requests,\n\t0, NULL,\n};\n\nstatic const struct wl_message zwp_relative_pointer_v1_requests[] = {\n\t{ \"destroy\", \"\", relative_pointer_unstable_v1_types + 0 },\n};\n\nstatic const struct wl_message zwp_relative_pointer_v1_events[] = {\n\t{ \"relative_motion\", \"uuffff\", relative_pointer_unstable_v1_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface zwp_relative_pointer_v1_interface = {\n\t\"zwp_relative_pointer_v1\", 1,\n\t1, zwp_relative_pointer_v1_requests,\n\t1, zwp_relative_pointer_v1_events,\n};\n\n"
  },
  {
    "path": "thirdparty/sokol/sokol_audio.h",
    "content": "#if defined(SOKOL_IMPL) && !defined(SOKOL_AUDIO_IMPL)\n#define SOKOL_AUDIO_IMPL\n#endif\n#ifndef SOKOL_AUDIO_INCLUDED\n/*\n    sokol_audio.h -- cross-platform audio-streaming API\n\n    Project URL: https://github.com/floooh/sokol\n\n    Do this:\n        #define SOKOL_IMPL or\n        #define SOKOL_AUDIO_IMPL\n    before you include this file in *one* C or C++ file to create the\n    implementation.\n\n    Optionally provide the following defines with your own implementations:\n\n    SOKOL_DUMMY_BACKEND - use a dummy backend\n    SOKOL_ASSERT(c)     - your own assert macro (default: assert(c))\n    SOKOL_AUDIO_API_DECL- public function declaration prefix (default: extern)\n    SOKOL_API_DECL      - same as SOKOL_AUDIO_API_DECL\n    SOKOL_API_IMPL      - public function implementation prefix (default: -)\n\n    SAUDIO_RING_MAX_SLOTS           - max number of slots in the push-audio ring buffer (default 1024)\n    SAUDIO_OSX_USE_SYSTEM_HEADERS   - define this to force inclusion of system headers on\n                                      macOS instead of using embedded CoreAudio declarations\n    SAUDIO_ANDROID_AAUDIO           - on Android, select the AAudio backend (default)\n    SAUDIO_ANDROID_SLES             - on Android, select the OpenSLES backend\n\n    If sokol_audio.h is compiled as a DLL, define the following before\n    including the declaration or implementation:\n\n    SOKOL_DLL\n\n    On Windows, SOKOL_DLL will define SOKOL_AUDIO_API_DECL as __declspec(dllexport)\n    or __declspec(dllimport) as needed.\n\n    Link with the following libraries:\n\n    - on macOS: AudioToolbox\n    - on iOS: AudioToolbox, AVFoundation\n    - on FreeBSD: asound\n    - on Linux: asound\n    - on Android: link with OpenSLES or aaudio\n    - on Windows with MSVC or Clang toolchain: no action needed, libs are defined in-source via pragma-comment-lib\n    - on Windows with MINGW/MSYS2 gcc: compile with '-mwin32' and link with -lole32\n\n    FEATURE OVERVIEW\n    ================\n    You provide a mono- or stereo-stream of 32-bit float samples, which\n    Sokol Audio feeds into platform-specific audio backends:\n\n    - Windows: WASAPI\n    - Linux: ALSA\n    - FreeBSD: ALSA\n    - macOS: CoreAudio\n    - iOS: CoreAudio+AVAudioSession\n    - emscripten: WebAudio with ScriptProcessorNode\n    - Android: AAudio (default) or OpenSLES, select at build time\n\n    Sokol Audio will not do any buffer mixing or volume control, if you have\n    multiple independent input streams of sample data you need to perform the\n    mixing yourself before forwarding the data to Sokol Audio.\n\n    There are two mutually exclusive ways to provide the sample data:\n\n    1. Callback model: You provide a callback function, which will be called\n       when Sokol Audio needs new samples. On all platforms except emscripten,\n       this function is called from a separate thread.\n    2. Push model: Your code pushes small blocks of sample data from your\n       main loop or a thread you created. The pushed data is stored in\n       a ring buffer where it is pulled by the backend code when\n       needed.\n\n    The callback model is preferred because it is the most direct way to\n    feed sample data into the audio backends and also has less moving parts\n    (there is no ring buffer between your code and the audio backend).\n\n    Sometimes it is not possible to generate the audio stream directly in a\n    callback function running in a separate thread, for such cases Sokol Audio\n    provides the push-model as a convenience.\n\n    SOKOL AUDIO, SOLOUD AND MINIAUDIO\n    =================================\n    The WASAPI, ALSA, OpenSLES and CoreAudio backend code has been taken from the\n    SoLoud library (with some modifications, so any bugs in there are most\n    likely my fault). If you need a more fully-featured audio solution, check\n    out SoLoud, it's excellent:\n\n        https://github.com/jarikomppa/soloud\n\n    Another alternative which feature-wise is somewhere inbetween SoLoud and\n    sokol-audio might be MiniAudio:\n\n        https://github.com/mackron/miniaudio\n\n    GLOSSARY\n    ========\n    - stream buffer:\n        The internal audio data buffer, usually provided by the backend API. The\n        size of the stream buffer defines the base latency, smaller buffers have\n        lower latency but may cause audio glitches. Bigger buffers reduce or\n        eliminate glitches, but have a higher base latency.\n\n    - stream callback:\n        Optional callback function which is called by Sokol Audio when it\n        needs new samples. On Windows, macOS/iOS and Linux, this is called in\n        a separate thread, on WebAudio, this is called per-frame in the\n        browser thread.\n\n    - channel:\n        A discrete track of audio data, currently 1-channel (mono) and\n        2-channel (stereo) is supported and tested.\n\n    - sample:\n        The magnitude of an audio signal on one channel at a given time. In\n        Sokol Audio, samples are 32-bit float numbers in the range -1.0 to\n        +1.0.\n\n    - frame:\n        The tightly packed set of samples for all channels at a given time.\n        For mono 1 frame is 1 sample. For stereo, 1 frame is 2 samples.\n\n    - packet:\n        In Sokol Audio, a small chunk of audio data that is moved from the\n        main thread to the audio streaming thread in order to decouple the\n        rate at which the main thread provides new audio data, and the\n        streaming thread consuming audio data.\n\n    WORKING WITH SOKOL AUDIO\n    ========================\n    First call saudio_setup() with your preferred audio playback options.\n    In most cases you can stick with the default values, these provide\n    a good balance between low-latency and glitch-free playback\n    on all audio backends.\n\n    You should always provide a logging callback to be aware of any\n    warnings and errors. The easiest way is to use sokol_log.h for this:\n\n        #include \"sokol_log.h\"\n        // ...\n        saudio_setup(&(saudio_desc){\n            .logger = {\n                .func = slog_func,\n            }\n        });\n\n    If you want to use the callback-model, you need to provide a stream\n    callback function either in saudio_desc.stream_cb or saudio_desc.stream_userdata_cb,\n    otherwise keep both function pointers zero-initialized.\n\n    Use push model and default playback parameters:\n\n        saudio_setup(&(saudio_desc){ .logger.func = slog_func });\n\n    Use stream callback model and default playback parameters:\n\n        saudio_setup(&(saudio_desc){\n            .stream_cb = my_stream_callback\n            .logger.func = slog_func,\n        });\n\n    The standard stream callback doesn't have a user data argument, if you want\n    that, use the alternative stream_userdata_cb and also set the user_data pointer:\n\n        saudio_setup(&(saudio_desc){\n            .stream_userdata_cb = my_stream_callback,\n            .user_data = &my_data\n            .logger.func = slog_func,\n        });\n\n    The following playback parameters can be provided through the\n    saudio_desc struct:\n\n    General parameters (both for stream-callback and push-model):\n\n        int sample_rate     -- the sample rate in Hz, default: 44100\n        int num_channels    -- number of channels, default: 1 (mono)\n        int buffer_frames   -- number of frames in streaming buffer, default: 2048\n\n    The stream callback prototype (either with or without userdata):\n\n        void (*stream_cb)(float* buffer, int num_frames, int num_channels)\n        void (*stream_userdata_cb)(float* buffer, int num_frames, int num_channels, void* user_data)\n            Function pointer to the user-provide stream callback.\n\n    Push-model parameters:\n\n        int packet_frames   -- number of frames in a packet, default: 128\n        int num_packets     -- number of packets in ring buffer, default: 64\n\n    The sample_rate and num_channels parameters are only hints for the audio\n    backend, it isn't guaranteed that those are the values used for actual\n    playback.\n\n    To get the actual parameters, call the following functions after\n    saudio_setup():\n\n        int saudio_sample_rate(void)\n        int saudio_channels(void);\n\n    It's unlikely that the number of channels will be different than requested,\n    but a different sample rate isn't uncommon.\n\n    (NOTE: there's an yet unsolved issue when an audio backend might switch\n    to a different sample rate when switching output devices, for instance\n    plugging in a bluetooth headset, this case is currently not handled in\n    Sokol Audio).\n\n    You can check if audio initialization was successful with\n    saudio_isvalid(). If backend initialization failed for some reason\n    (for instance when there's no audio device in the machine), this\n    will return false. Not checking for success won't do any harm, all\n    Sokol Audio function will silently fail when called after initialization\n    has failed, so apart from missing audio output, nothing bad will happen.\n\n    Before your application exits, you should call\n\n        saudio_shutdown();\n\n    This stops the audio thread (on Linux, Windows and macOS/iOS) and\n    properly shuts down the audio backend.\n\n    THE STREAM CALLBACK MODEL\n    =========================\n    To use Sokol Audio in stream-callback-mode, provide a callback function\n    like this in the saudio_desc struct when calling saudio_setup():\n\n    void stream_cb(float* buffer, int num_frames, int num_channels) {\n        ...\n    }\n\n    Or the alternative version with a user-data argument:\n\n    void stream_userdata_cb(float* buffer, int num_frames, int num_channels, void* user_data) {\n        my_data_t* my_data = (my_data_t*) user_data;\n        ...\n    }\n\n    The job of the callback function is to fill the *buffer* with 32-bit\n    float sample values.\n\n    To output silence, fill the buffer with zeros:\n\n        void stream_cb(float* buffer, int num_frames, int num_channels) {\n            const int num_samples = num_frames * num_channels;\n            for (int i = 0; i < num_samples; i++) {\n                buffer[i] = 0.0f;\n            }\n        }\n\n    For stereo output (num_channels == 2), the samples for the left\n    and right channel are interleaved:\n\n        void stream_cb(float* buffer, int num_frames, int num_channels) {\n            assert(2 == num_channels);\n            for (int i = 0; i < num_frames; i++) {\n                buffer[2*i + 0] = ...;  // left channel\n                buffer[2*i + 1] = ...;  // right channel\n            }\n        }\n\n    Please keep in mind that the stream callback function is running in a\n    separate thread, if you need to share data with the main thread you need\n    to take care yourself to make the access to the shared data thread-safe!\n\n    THE PUSH MODEL\n    ==============\n    To use the push-model for providing audio data, simply don't set (keep\n    zero-initialized) the stream_cb field in the saudio_desc struct when\n    calling saudio_setup().\n\n    To provide sample data with the push model, call the saudio_push()\n    function at regular intervals (for instance once per frame). You can\n    call the saudio_expect() function to ask Sokol Audio how much room is\n    in the ring buffer, but if you provide a continuous stream of data\n    at the right sample rate, saudio_expect() isn't required (it's a simple\n    way to sync/throttle your sample generation code with the playback\n    rate though).\n\n    With saudio_push() you may need to maintain your own intermediate sample\n    buffer, since pushing individual sample values isn't very efficient.\n    The following example is from the MOD player sample in\n    sokol-samples (https://github.com/floooh/sokol-samples):\n\n        const int num_frames = saudio_expect();\n        if (num_frames > 0) {\n            const int num_samples = num_frames * saudio_channels();\n            read_samples(flt_buf, num_samples);\n            saudio_push(flt_buf, num_frames);\n        }\n\n    Another option is to ignore saudio_expect(), and just push samples as they\n    are generated in small batches. In this case you *need* to generate the\n    samples at the right sample rate:\n\n    The following example is taken from the Tiny Emulators project\n    (https://github.com/floooh/chips-test), this is for mono playback,\n    so (num_samples == num_frames):\n\n        // tick the sound generator\n        if (ay38910_tick(&sys->psg)) {\n            // new sample is ready\n            sys->sample_buffer[sys->sample_pos++] = sys->psg.sample;\n            if (sys->sample_pos == sys->num_samples) {\n                // new sample packet is ready\n                saudio_push(sys->sample_buffer, sys->num_samples);\n                sys->sample_pos = 0;\n            }\n        }\n\n    THE WEBAUDIO BACKEND\n    ====================\n    The WebAudio backend is currently using a ScriptProcessorNode callback to\n    feed the sample data into WebAudio. ScriptProcessorNode has been\n    deprecated for a while because it is running from the main thread, with\n    the default initialization parameters it works 'pretty well' though.\n    Ultimately Sokol Audio will use Audio Worklets, but this requires a few\n    more things to fall into place (Audio Worklets implemented everywhere,\n    SharedArrayBuffers enabled again, and I need to figure out a 'low-cost'\n    solution in terms of implementation effort, since Audio Worklets are\n    a lot more complex than ScriptProcessorNode if the audio data needs to come\n    from the main thread).\n\n    The WebAudio backend is automatically selected when compiling for\n    emscripten (__EMSCRIPTEN__ define exists).\n\n    https://developers.google.com/web/updates/2017/12/audio-worklet\n    https://developers.google.com/web/updates/2018/06/audio-worklet-design-pattern\n\n    \"Blob URLs\": https://www.html5rocks.com/en/tutorials/workers/basics/\n\n    Also see: https://blog.paul.cx/post/a-wait-free-spsc-ringbuffer-for-the-web/\n\n    THE COREAUDIO BACKEND\n    =====================\n    The CoreAudio backend is selected on macOS and iOS (__APPLE__ is defined).\n    Since the CoreAudio API is implemented in C (not Objective-C) on macOS the\n    implementation part of Sokol Audio can be included into a C source file.\n\n    However on iOS, Sokol Audio must be compiled as Objective-C due to it's\n    reliance on the AVAudioSession object. The iOS code path support both\n    being compiled with or without ARC (Automatic Reference Counting).\n\n    For thread synchronisation, the CoreAudio backend will use the\n    pthread_mutex_* functions.\n\n    The incoming floating point samples will be directly forwarded to\n    CoreAudio without further conversion.\n\n    macOS and iOS applications that use Sokol Audio need to link with\n    the AudioToolbox framework.\n\n    THE WASAPI BACKEND\n    ==================\n    The WASAPI backend is automatically selected when compiling on Windows\n    (_WIN32 is defined).\n\n    For thread synchronisation a Win32 critical section is used.\n\n    WASAPI may use a different size for its own streaming buffer then requested,\n    so the base latency may be slightly bigger. The current backend implementation\n    converts the incoming floating point sample values to signed 16-bit\n    integers.\n\n    The required Windows system DLLs are linked with #pragma comment(lib, ...),\n    so you shouldn't need to add additional linker libs in the build process\n    (otherwise this is a bug which should be fixed in sokol_audio.h).\n\n    THE ALSA BACKEND\n    ================\n    The ALSA backend is automatically selected when compiling on Linux\n    ('linux' is defined).\n\n    For thread synchronisation, the pthread_mutex_* functions are used.\n\n    Samples are directly forwarded to ALSA in 32-bit float format, no\n    further conversion is taking place.\n\n    You need to link with the 'asound' library, and the <alsa/asoundlib.h>\n    header must be present (usually both are installed with some sort\n    of ALSA development package).\n\n\n    MEMORY ALLOCATION OVERRIDE\n    ==========================\n    You can override the memory allocation functions at initialization time\n    like this:\n\n        void* my_alloc(size_t size, void* user_data) {\n            return malloc(size);\n        }\n\n        void my_free(void* ptr, void* user_data) {\n            free(ptr);\n        }\n\n        ...\n            saudio_setup(&(saudio_desc){\n                // ...\n                .allocator = {\n                    .alloc_fn = my_alloc,\n                    .free_fn = my_free,\n                    .user_data = ...,\n                }\n            });\n        ...\n\n    If no overrides are provided, malloc and free will be used.\n\n    This only affects memory allocation calls done by sokol_audio.h\n    itself though, not any allocations in OS libraries.\n\n    Memory allocation will only happen on the same thread where saudio_setup()\n    was called, so you don't need to worry about thread-safety.\n\n\n    ERROR REPORTING AND LOGGING\n    ===========================\n    To get any logging information at all you need to provide a logging callback in the setup call\n    the easiest way is to use sokol_log.h:\n\n        #include \"sokol_log.h\"\n\n        saudio_setup(&(saudio_desc){ .logger.func = slog_func });\n\n    To override logging with your own callback, first write a logging function like this:\n\n        void my_log(const char* tag,                // e.g. 'saudio'\n                    uint32_t log_level,             // 0=panic, 1=error, 2=warn, 3=info\n                    uint32_t log_item_id,           // SAUDIO_LOGITEM_*\n                    const char* message_or_null,    // a message string, may be nullptr in release mode\n                    uint32_t line_nr,               // line number in sokol_audio.h\n                    const char* filename_or_null,   // source filename, may be nullptr in release mode\n                    void* user_data)\n        {\n            ...\n        }\n\n    ...and then setup sokol-audio like this:\n\n        saudio_setup(&(saudio_desc){\n            .logger = {\n                .func = my_log,\n                .user_data = my_user_data,\n            }\n        });\n\n    The provided logging function must be reentrant (e.g. be callable from\n    different threads).\n\n    If you don't want to provide your own custom logger it is highly recommended to use\n    the standard logger in sokol_log.h instead, otherwise you won't see any warnings or\n    errors.\n\n    LICENSE\n    =======\n\n    zlib/libpng license\n\n    Copyright (c) 2018 Andre Weissflog\n\n    This software is provided 'as-is', without any express or implied warranty.\n    In no event will the authors be held liable for any damages arising from the\n    use of this software.\n\n    Permission is granted to anyone to use this software for any purpose,\n    including commercial applications, and to alter it and redistribute it\n    freely, subject to the following restrictions:\n\n        1. The origin of this software must not be misrepresented; you must not\n        claim that you wrote the original software. If you use this software in a\n        product, an acknowledgment in the product documentation would be\n        appreciated but is not required.\n\n        2. Altered source versions must be plainly marked as such, and must not\n        be misrepresented as being the original software.\n\n        3. This notice may not be removed or altered from any source\n        distribution.\n*/\n#define SOKOL_AUDIO_INCLUDED (1)\n#include <stddef.h> // size_t\n#include <stdint.h>\n#include <stdbool.h>\n\n#if defined(SOKOL_API_DECL) && !defined(SOKOL_AUDIO_API_DECL)\n#define SOKOL_AUDIO_API_DECL SOKOL_API_DECL\n#endif\n#ifndef SOKOL_AUDIO_API_DECL\n#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_AUDIO_IMPL)\n#define SOKOL_AUDIO_API_DECL __declspec(dllexport)\n#elif defined(_WIN32) && defined(SOKOL_DLL)\n#define SOKOL_AUDIO_API_DECL __declspec(dllimport)\n#else\n#define SOKOL_AUDIO_API_DECL extern\n#endif\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n    saudio_log_item\n\n    Log items are defined via X-Macros, and expanded to an\n    enum 'saudio_log_item', and in debug mode only,\n    corresponding strings.\n\n    Used as parameter in the logging callback.\n*/\n#define _SAUDIO_LOG_ITEMS \\\n    _SAUDIO_LOGITEM_XMACRO(OK, \"Ok\") \\\n    _SAUDIO_LOGITEM_XMACRO(MALLOC_FAILED, \"memory allocation failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(ALSA_SND_PCM_OPEN_FAILED, \"snd_pcm_open() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(ALSA_FLOAT_SAMPLES_NOT_SUPPORTED, \"floating point sample format not supported\") \\\n    _SAUDIO_LOGITEM_XMACRO(ALSA_REQUESTED_BUFFER_SIZE_NOT_SUPPORTED, \"requested buffer size not supported\") \\\n    _SAUDIO_LOGITEM_XMACRO(ALSA_REQUESTED_CHANNEL_COUNT_NOT_SUPPORTED, \"requested channel count not supported\") \\\n    _SAUDIO_LOGITEM_XMACRO(ALSA_SND_PCM_HW_PARAMS_SET_RATE_NEAR_FAILED, \"snd_pcm_hw_params_set_rate_near() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(ALSA_SND_PCM_HW_PARAMS_FAILED, \"snd_pcm_hw_params() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(ALSA_PTHREAD_CREATE_FAILED, \"pthread_create() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(WASAPI_CREATE_EVENT_FAILED, \"CreateEvent() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(WASAPI_CREATE_DEVICE_ENUMERATOR_FAILED, \"CoCreateInstance() for IMMDeviceEnumerator failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(WASAPI_GET_DEFAULT_AUDIO_ENDPOINT_FAILED, \"IMMDeviceEnumerator.GetDefaultAudioEndpoint() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(WASAPI_DEVICE_ACTIVATE_FAILED, \"IMMDevice.Activate() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(WASAPI_AUDIO_CLIENT_INITIALIZE_FAILED, \"IAudioClient.Initialize() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(WASAPI_AUDIO_CLIENT_GET_BUFFER_SIZE_FAILED, \"IAudioClient.GetBufferSize() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(WASAPI_AUDIO_CLIENT_GET_SERVICE_FAILED, \"IAudioClient.GetService() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(WASAPI_AUDIO_CLIENT_SET_EVENT_HANDLE_FAILED, \"IAudioClient.SetEventHandle() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(WASAPI_CREATE_THREAD_FAILED, \"CreateThread() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(AAUDIO_STREAMBUILDER_OPEN_STREAM_FAILED, \"AAudioStreamBuilder_openStream() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(AAUDIO_PTHREAD_CREATE_FAILED, \"pthread_create() failed after AAUDIO_ERROR_DISCONNECTED\") \\\n    _SAUDIO_LOGITEM_XMACRO(AAUDIO_RESTARTING_STREAM_AFTER_ERROR, \"restarting AAudio stream after error\") \\\n    _SAUDIO_LOGITEM_XMACRO(USING_AAUDIO_BACKEND, \"using AAudio backend\") \\\n    _SAUDIO_LOGITEM_XMACRO(AAUDIO_CREATE_STREAMBUILDER_FAILED, \"AAudio_createStreamBuilder() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(USING_SLES_BACKEND, \"using OpenSLES backend\") \\\n    _SAUDIO_LOGITEM_XMACRO(SLES_CREATE_ENGINE_FAILED, \"slCreateEngine() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(SLES_ENGINE_GET_ENGINE_INTERFACE_FAILED, \"GetInterface() for SL_IID_ENGINE failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(SLES_CREATE_OUTPUT_MIX_FAILED, \"CreateOutputMix() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(SLES_MIXER_GET_VOLUME_INTERFACE_FAILED, \"GetInterface() for SL_IID_VOLUME failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(SLES_ENGINE_CREATE_AUDIO_PLAYER_FAILED, \"CreateAudioPlayer() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(SLES_PLAYER_GET_PLAY_INTERFACE_FAILED, \"GetInterface() for SL_IID_PLAY failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(SLES_PLAYER_GET_VOLUME_INTERFACE_FAILED, \"GetInterface() for SL_IID_VOLUME failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(SLES_PLAYER_GET_BUFFERQUEUE_INTERFACE_FAILED, \"GetInterface() for SL_IID_ANDROIDSIMPLEBUFFERQUEUE failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(COREAUDIO_NEW_OUTPUT_FAILED, \"AudioQueueNewOutput() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(COREAUDIO_ALLOCATE_BUFFER_FAILED, \"AudioQueueAllocateBuffer() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(COREAUDIO_START_FAILED, \"AudioQueueStart() failed\") \\\n    _SAUDIO_LOGITEM_XMACRO(BACKEND_BUFFER_SIZE_ISNT_MULTIPLE_OF_PACKET_SIZE, \"backend buffer size isn't multiple of packet size\") \\\n\n#define _SAUDIO_LOGITEM_XMACRO(item,msg) SAUDIO_LOGITEM_##item,\ntypedef enum saudio_log_item {\n    _SAUDIO_LOG_ITEMS\n} saudio_log_item;\n#undef _SAUDIO_LOGITEM_XMACRO\n\n/*\n    saudio_logger\n\n    Used in saudio_desc to provide a custom logging and error reporting\n    callback to sokol-audio.\n*/\ntypedef struct saudio_logger {\n    void (*func)(\n        const char* tag,                // always \"saudio\"\n        uint32_t log_level,             // 0=panic, 1=error, 2=warning, 3=info\n        uint32_t log_item_id,           // SAUDIO_LOGITEM_*\n        const char* message_or_null,    // a message string, may be nullptr in release mode\n        uint32_t line_nr,               // line number in sokol_audio.h\n        const char* filename_or_null,   // source filename, may be nullptr in release mode\n        void* user_data);\n    void* user_data;\n} saudio_logger;\n\n/*\n    saudio_allocator\n\n    Used in saudio_desc to provide custom memory-alloc and -free functions\n    to sokol_audio.h. If memory management should be overridden, both the\n    alloc_fn and free_fn function must be provided (e.g. it's not valid to\n    override one function but not the other).\n*/\ntypedef struct saudio_allocator {\n    void* (*alloc_fn)(size_t size, void* user_data);\n    void (*free_fn)(void* ptr, void* user_data);\n    void* user_data;\n} saudio_allocator;\n\ntypedef struct saudio_desc {\n    int sample_rate;        // requested sample rate\n    int num_channels;       // number of channels, default: 1 (mono)\n    int buffer_frames;      // number of frames in streaming buffer\n    int packet_frames;      // number of frames in a packet\n    int num_packets;        // number of packets in packet queue\n    void (*stream_cb)(float* buffer, int num_frames, int num_channels);  // optional streaming callback (no user data)\n    void (*stream_userdata_cb)(float* buffer, int num_frames, int num_channels, void* user_data); //... and with user data\n    void* user_data;        // optional user data argument for stream_userdata_cb\n    saudio_allocator allocator;     // optional allocation override functions\n    saudio_logger logger;           // optional logging function (default: NO LOGGING!)\n} saudio_desc;\n\n/* setup sokol-audio */\nSOKOL_AUDIO_API_DECL void saudio_setup(const saudio_desc* desc);\n/* shutdown sokol-audio */\nSOKOL_AUDIO_API_DECL void saudio_shutdown(void);\n/* true after setup if audio backend was successfully initialized */\nSOKOL_AUDIO_API_DECL bool saudio_isvalid(void);\n/* return the saudio_desc.user_data pointer */\nSOKOL_AUDIO_API_DECL void* saudio_userdata(void);\n/* return a copy of the original saudio_desc struct */\nSOKOL_AUDIO_API_DECL saudio_desc saudio_query_desc(void);\n/* actual sample rate */\nSOKOL_AUDIO_API_DECL int saudio_sample_rate(void);\n/* return actual backend buffer size in number of frames */\nSOKOL_AUDIO_API_DECL int saudio_buffer_frames(void);\n/* actual number of channels */\nSOKOL_AUDIO_API_DECL int saudio_channels(void);\n/* return true if audio context is currently suspended (only in WebAudio backend, all other backends return false) */\nSOKOL_AUDIO_API_DECL bool saudio_suspended(void);\n/* get current number of frames to fill packet queue */\nSOKOL_AUDIO_API_DECL int saudio_expect(void);\n/* push sample frames from main thread, returns number of frames actually pushed */\nSOKOL_AUDIO_API_DECL int saudio_push(const float* frames, int num_frames);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n\n/* reference-based equivalents for c++ */\ninline void saudio_setup(const saudio_desc& desc) { return saudio_setup(&desc); }\n\n#endif\n#endif // SOKOL_AUDIO_INCLUDED\n\n// ██ ███    ███ ██████  ██      ███████ ███    ███ ███████ ███    ██ ████████  █████  ████████ ██  ██████  ███    ██\n// ██ ████  ████ ██   ██ ██      ██      ████  ████ ██      ████   ██    ██    ██   ██    ██    ██ ██    ██ ████   ██\n// ██ ██ ████ ██ ██████  ██      █████   ██ ████ ██ █████   ██ ██  ██    ██    ███████    ██    ██ ██    ██ ██ ██  ██\n// ██ ██  ██  ██ ██      ██      ██      ██  ██  ██ ██      ██  ██ ██    ██    ██   ██    ██    ██ ██    ██ ██  ██ ██\n// ██ ██      ██ ██      ███████ ███████ ██      ██ ███████ ██   ████    ██    ██   ██    ██    ██  ██████  ██   ████\n//\n// >>implementation\n#ifdef SOKOL_AUDIO_IMPL\n#define SOKOL_AUDIO_IMPL_INCLUDED (1)\n\n#if defined(SOKOL_MALLOC) || defined(SOKOL_CALLOC) || defined(SOKOL_FREE)\n#error \"SOKOL_MALLOC/CALLOC/FREE macros are no longer supported, please use saudio_desc.allocator to override memory allocation functions\"\n#endif\n\n#include <stdlib.h> // alloc, free\n#include <string.h> // memset, memcpy\n#include <stddef.h> // size_t\n\n#ifndef SOKOL_API_IMPL\n    #define SOKOL_API_IMPL\n#endif\n#ifndef SOKOL_DEBUG\n    #ifndef NDEBUG\n        #define SOKOL_DEBUG\n    #endif\n#endif\n#ifndef SOKOL_ASSERT\n    #include <assert.h>\n    #define SOKOL_ASSERT(c) assert(c)\n#endif\n\n#ifndef _SOKOL_PRIVATE\n    #if defined(__GNUC__) || defined(__clang__)\n        #define _SOKOL_PRIVATE __attribute__((unused)) static\n    #else\n        #define _SOKOL_PRIVATE static\n    #endif\n#endif\n\n#ifndef _SOKOL_UNUSED\n    #define _SOKOL_UNUSED(x) (void)(x)\n#endif\n\n// platform detection defines\n#if defined(SOKOL_DUMMY_BACKEND)\n    // nothing\n#elif defined(__APPLE__)\n    #define _SAUDIO_APPLE (1)\n    #include <TargetConditionals.h>\n    #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE\n        #define _SAUDIO_IOS (1)\n    #else\n        #define _SAUDIO_MACOS (1)\n    #endif\n#elif defined(__EMSCRIPTEN__)\n    #define _SAUDIO_EMSCRIPTEN (1)\n#elif defined(_WIN32)\n    #define _SAUDIO_WINDOWS (1)\n    #include <winapifamily.h>\n    #if (defined(WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))\n        #error \"sokol_audio.h no longer supports UWP\"\n    #endif\n#elif defined(__ANDROID__)\n    #define _SAUDIO_ANDROID (1)\n    #if !defined(SAUDIO_ANDROID_SLES) && !defined(SAUDIO_ANDROID_AAUDIO)\n        #define SAUDIO_ANDROID_AAUDIO (1)\n    #endif\n#elif defined(__linux__) || defined(__unix__)\n    #define _SAUDIO_LINUX (1)\n#else\n#error \"sokol_audio.h: Unknown platform\"\n#endif\n\n// platform-specific headers and definitions\n#if defined(SOKOL_DUMMY_BACKEND)\n    #define _SAUDIO_NOTHREADS (1)\n#elif defined(_SAUDIO_WINDOWS)\n    #define _SAUDIO_WINTHREADS (1)\n    #ifndef WIN32_LEAN_AND_MEAN\n    #define WIN32_LEAN_AND_MEAN\n    #endif\n    #ifndef NOMINMAX\n    #define NOMINMAX\n    #endif\n    #include <windows.h>\n    #include <synchapi.h>\n    #pragma comment (lib, \"kernel32\")\n    #pragma comment (lib, \"ole32\")\n    #ifndef CINTERFACE\n    #define CINTERFACE\n    #endif\n    #ifndef COBJMACROS\n    #define COBJMACROS\n    #endif\n    #ifndef CONST_VTABLE\n    #define CONST_VTABLE\n    #endif\n    #include <mmdeviceapi.h>\n    #include <audioclient.h>\n    static const IID _saudio_IID_IAudioClient                               = { 0x1cb9ad4c, 0xdbfa, 0x4c32, {0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2} };\n    static const IID _saudio_IID_IMMDeviceEnumerator                        = { 0xa95664d2, 0x9614, 0x4f35, {0xa7, 0x46, 0xde, 0x8d, 0xb6, 0x36, 0x17, 0xe6} };\n    static const CLSID _saudio_CLSID_IMMDeviceEnumerator                    = { 0xbcde0395, 0xe52f, 0x467c, {0x8e, 0x3d, 0xc4, 0x57, 0x92, 0x91, 0x69, 0x2e} };\n    static const IID _saudio_IID_IAudioRenderClient                         = { 0xf294acfc, 0x3146, 0x4483, {0xa7, 0xbf, 0xad, 0xdc, 0xa7, 0xc2, 0x60, 0xe2} };\n    static const IID _saudio_IID_Devinterface_Audio_Render                  = { 0xe6327cad, 0xdcec, 0x4949, {0xae, 0x8a, 0x99, 0x1e, 0x97, 0x6a, 0x79, 0xd2} };\n    static const IID _saudio_IID_IActivateAudioInterface_Completion_Handler = { 0x94ea2b94, 0xe9cc, 0x49e0, {0xc0, 0xff, 0xee, 0x64, 0xca, 0x8f, 0x5b, 0x90} };\n    static const GUID _saudio_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT               = { 0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} };\n    #if defined(__cplusplus)\n    #define _SOKOL_AUDIO_WIN32COM_ID(x) (x)\n    #else\n    #define _SOKOL_AUDIO_WIN32COM_ID(x) (&x)\n    #endif\n    /* fix for Visual Studio 2015 SDKs */\n    #ifndef AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM\n    #define AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM 0x80000000\n    #endif\n    #ifndef AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY\n    #define AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY 0x08000000\n    #endif\n    #ifdef _MSC_VER\n        #pragma warning(push)\n        #pragma warning(disable:4505)   /* unreferenced local function has been removed */\n    #endif\n#elif defined(_SAUDIO_APPLE)\n    #define _SAUDIO_PTHREADS (1)\n    #include <pthread.h>\n    #if defined(_SAUDIO_IOS)\n        // always use system headers on iOS (for now at least)\n        #if !defined(SAUDIO_OSX_USE_SYSTEM_HEADERS)\n            #define SAUDIO_OSX_USE_SYSTEM_HEADERS (1)\n        #endif\n        #if !defined(__cplusplus)\n            #if __has_feature(objc_arc) && !__has_feature(objc_arc_fields)\n                #error \"sokol_audio.h on iOS requires __has_feature(objc_arc_field) if ARC is enabled (use a more recent compiler version)\"\n            #endif\n        #endif\n        #include <AudioToolbox/AudioToolbox.h>\n        #include <AVFoundation/AVFoundation.h>\n    #else\n        #if defined(SAUDIO_OSX_USE_SYSTEM_HEADERS)\n            #include <AudioToolbox/AudioToolbox.h>\n        #endif\n    #endif\n#elif defined(_SAUDIO_ANDROID)\n    #define _SAUDIO_PTHREADS (1)\n    #include <pthread.h>\n    #if defined(SAUDIO_ANDROID_SLES)\n        #include \"SLES/OpenSLES_Android.h\"\n    #elif defined(SAUDIO_ANDROID_AAUDIO)\n        #include \"aaudio/AAudio.h\"\n    #endif\n#elif defined(_SAUDIO_LINUX)\n    #if !defined(__FreeBSD__)\n        #include <alloca.h>\n    #endif\n    #define _SAUDIO_PTHREADS (1)\n    #include <pthread.h>\n    #define ALSA_PCM_NEW_HW_PARAMS_API\n    #include <alsa/asoundlib.h>\n#elif defined(__EMSCRIPTEN__)\n    #define _SAUDIO_NOTHREADS (1)\n    #include <emscripten/emscripten.h>\n#endif\n\n#define _saudio_def(val, def) (((val) == 0) ? (def) : (val))\n#define _saudio_def_flt(val, def) (((val) == 0.0f) ? (def) : (val))\n\n#define _SAUDIO_DEFAULT_SAMPLE_RATE (44100)\n#define _SAUDIO_DEFAULT_BUFFER_FRAMES (2048)\n#define _SAUDIO_DEFAULT_PACKET_FRAMES (128)\n#define _SAUDIO_DEFAULT_NUM_PACKETS ((_SAUDIO_DEFAULT_BUFFER_FRAMES/_SAUDIO_DEFAULT_PACKET_FRAMES)*4)\n\n#ifndef SAUDIO_RING_MAX_SLOTS\n#define SAUDIO_RING_MAX_SLOTS (1024)\n#endif\n\n// ███████ ████████ ██████  ██    ██  ██████ ████████ ███████\n// ██         ██    ██   ██ ██    ██ ██         ██    ██\n// ███████    ██    ██████  ██    ██ ██         ██    ███████\n//      ██    ██    ██   ██ ██    ██ ██         ██         ██\n// ███████    ██    ██   ██  ██████   ██████    ██    ███████\n//\n// >>structs\n#if defined(_SAUDIO_PTHREADS)\n\ntypedef struct {\n    pthread_mutex_t mutex;\n} _saudio_mutex_t;\n\n#elif defined(_SAUDIO_WINTHREADS)\n\ntypedef struct {\n    CRITICAL_SECTION critsec;\n} _saudio_mutex_t;\n\n#elif defined(_SAUDIO_NOTHREADS)\n\ntypedef struct {\n    int dummy_mutex;\n} _saudio_mutex_t;\n\n#endif\n\n#if defined(SOKOL_DUMMY_BACKEND)\n\ntypedef struct {\n    int dummy;\n} _saudio_dummy_backend_t;\n\n#elif defined(_SAUDIO_APPLE)\n\n#if defined(SAUDIO_OSX_USE_SYSTEM_HEADERS)\n\ntypedef AudioQueueRef _saudio_AudioQueueRef;\ntypedef AudioQueueBufferRef _saudio_AudioQueueBufferRef;\ntypedef AudioStreamBasicDescription _saudio_AudioStreamBasicDescription;\ntypedef OSStatus _saudio_OSStatus;\n\n#define _saudio_kAudioFormatLinearPCM (kAudioFormatLinearPCM)\n#define _saudio_kLinearPCMFormatFlagIsFloat (kLinearPCMFormatFlagIsFloat)\n#define _saudio_kAudioFormatFlagIsPacked (kAudioFormatFlagIsPacked)\n\n#else\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// embedded AudioToolbox declarations\ntypedef uint32_t _saudio_AudioFormatID;\ntypedef uint32_t _saudio_AudioFormatFlags;\ntypedef int32_t _saudio_OSStatus;\ntypedef uint32_t _saudio_SMPTETimeType;\ntypedef uint32_t _saudio_SMPTETimeFlags;\ntypedef uint32_t _saudio_AudioTimeStampFlags;\ntypedef void* _saudio_CFRunLoopRef;\ntypedef void* _saudio_CFStringRef;\ntypedef void* _saudio_AudioQueueRef;\n\n#define _saudio_kAudioFormatLinearPCM ('lpcm')\n#define _saudio_kLinearPCMFormatFlagIsFloat (1U << 0)\n#define _saudio_kAudioFormatFlagIsPacked (1U << 3)\n\ntypedef struct _saudio_AudioStreamBasicDescription {\n    double mSampleRate;\n    _saudio_AudioFormatID mFormatID;\n    _saudio_AudioFormatFlags mFormatFlags;\n    uint32_t mBytesPerPacket;\n    uint32_t mFramesPerPacket;\n    uint32_t mBytesPerFrame;\n    uint32_t mChannelsPerFrame;\n    uint32_t mBitsPerChannel;\n    uint32_t mReserved;\n} _saudio_AudioStreamBasicDescription;\n\ntypedef struct _saudio_AudioStreamPacketDescription {\n    int64_t mStartOffset;\n    uint32_t mVariableFramesInPacket;\n    uint32_t mDataByteSize;\n} _saudio_AudioStreamPacketDescription;\n\ntypedef struct _saudio_SMPTETime {\n    int16_t mSubframes;\n    int16_t mSubframeDivisor;\n    uint32_t mCounter;\n    _saudio_SMPTETimeType mType;\n    _saudio_SMPTETimeFlags mFlags;\n    int16_t mHours;\n    int16_t mMinutes;\n    int16_t mSeconds;\n    int16_t mFrames;\n} _saudio_SMPTETime;\n\ntypedef struct _saudio_AudioTimeStamp {\n    double mSampleTime;\n    uint64_t mHostTime;\n    double mRateScalar;\n    uint64_t mWordClockTime;\n    _saudio_SMPTETime mSMPTETime;\n    _saudio_AudioTimeStampFlags mFlags;\n    uint32_t mReserved;\n} _saudio_AudioTimeStamp;\n\ntypedef struct _saudio_AudioQueueBuffer {\n    const uint32_t mAudioDataBytesCapacity;\n    void* const mAudioData;\n    uint32_t mAudioDataByteSize;\n    void * mUserData;\n    const uint32_t mPacketDescriptionCapacity;\n    _saudio_AudioStreamPacketDescription* const mPacketDescriptions;\n    uint32_t mPacketDescriptionCount;\n} _saudio_AudioQueueBuffer;\ntypedef _saudio_AudioQueueBuffer* _saudio_AudioQueueBufferRef;\n\ntypedef void (*_saudio_AudioQueueOutputCallback)(void* user_data, _saudio_AudioQueueRef inAQ, _saudio_AudioQueueBufferRef inBuffer);\n\nextern _saudio_OSStatus AudioQueueNewOutput(const _saudio_AudioStreamBasicDescription* inFormat, _saudio_AudioQueueOutputCallback inCallbackProc, void* inUserData, _saudio_CFRunLoopRef inCallbackRunLoop, _saudio_CFStringRef inCallbackRunLoopMode, uint32_t inFlags, _saudio_AudioQueueRef* outAQ);\nextern _saudio_OSStatus AudioQueueDispose(_saudio_AudioQueueRef inAQ, bool inImmediate);\nextern _saudio_OSStatus AudioQueueAllocateBuffer(_saudio_AudioQueueRef inAQ, uint32_t inBufferByteSize, _saudio_AudioQueueBufferRef* outBuffer);\nextern _saudio_OSStatus AudioQueueEnqueueBuffer(_saudio_AudioQueueRef inAQ, _saudio_AudioQueueBufferRef inBuffer, uint32_t inNumPacketDescs, const _saudio_AudioStreamPacketDescription* inPacketDescs);\nextern _saudio_OSStatus AudioQueueStart(_saudio_AudioQueueRef inAQ, const _saudio_AudioTimeStamp * inStartTime);\nextern _saudio_OSStatus AudioQueueStop(_saudio_AudioQueueRef inAQ, bool inImmediate);\n\n#ifdef __cplusplus\n} // extern \"C\"\n#endif\n\n#endif // SAUDIO_OSX_USE_SYSTEM_HEADERS\n\ntypedef struct {\n    _saudio_AudioQueueRef ca_audio_queue;\n    #if defined(_SAUDIO_IOS)\n    id ca_interruption_handler;\n    #endif\n} _saudio_apple_backend_t;\n\n#elif defined(_SAUDIO_LINUX)\n\ntypedef struct {\n    snd_pcm_t* device;\n    float* buffer;\n    int buffer_byte_size;\n    int buffer_frames;\n    pthread_t thread;\n    bool thread_stop;\n} _saudio_alsa_backend_t;\n\n#elif defined(SAUDIO_ANDROID_SLES)\n\n#define SAUDIO_SLES_NUM_BUFFERS (2)\n\ntypedef struct {\n    pthread_mutex_t mutex;\n    pthread_cond_t cond;\n    int count;\n} _saudio_sles_semaphore_t;\n\ntypedef struct {\n    SLObjectItf engine_obj;\n    SLEngineItf engine;\n    SLObjectItf output_mix_obj;\n    SLVolumeItf output_mix_vol;\n    SLDataLocator_OutputMix out_locator;\n    SLDataSink dst_data_sink;\n    SLObjectItf player_obj;\n    SLPlayItf player;\n    SLVolumeItf player_vol;\n    SLAndroidSimpleBufferQueueItf player_buffer_queue;\n\n    int16_t* output_buffers[SAUDIO_SLES_NUM_BUFFERS];\n    float* src_buffer;\n    int active_buffer;\n    _saudio_sles_semaphore_t buffer_sem;\n    pthread_t thread;\n    volatile int thread_stop;\n    SLDataLocator_AndroidSimpleBufferQueue in_locator;\n} _saudio_sles_backend_t;\n\n#elif defined(SAUDIO_ANDROID_AAUDIO)\n\ntypedef struct {\n    AAudioStreamBuilder* builder;\n    AAudioStream* stream;\n    pthread_t thread;\n    pthread_mutex_t mutex;\n} _saudio_aaudio_backend_t;\n\n#elif defined(_SAUDIO_WINDOWS)\n\ntypedef struct {\n    HANDLE thread_handle;\n    HANDLE buffer_end_event;\n    bool stop;\n    UINT32 dst_buffer_frames;\n    int src_buffer_frames;\n    int src_buffer_byte_size;\n    int src_buffer_pos;\n    float* src_buffer;\n} _saudio_wasapi_thread_data_t;\n\ntypedef struct {\n    IMMDeviceEnumerator* device_enumerator;\n    IMMDevice* device;\n    IAudioClient* audio_client;\n    IAudioRenderClient* render_client;\n    _saudio_wasapi_thread_data_t thread;\n} _saudio_wasapi_backend_t;\n\n#elif defined(_SAUDIO_EMSCRIPTEN)\n\ntypedef struct {\n    uint8_t* buffer;\n} _saudio_web_backend_t;\n\n#else\n#error \"unknown platform\"\n#endif\n\n#if defined(SOKOL_DUMMY_BACKEND)\ntypedef _saudio_dummy_backend_t _saudio_backend_t;\n#elif defined(_SAUDIO_APPLE)\ntypedef _saudio_apple_backend_t _saudio_backend_t;\n#elif defined(_SAUDIO_EMSCRIPTEN)\ntypedef _saudio_web_backend_t _saudio_backend_t;\n#elif defined(_SAUDIO_WINDOWS)\ntypedef _saudio_wasapi_backend_t _saudio_backend_t;\n#elif defined(SAUDIO_ANDROID_SLES)\ntypedef _saudio_sles_backend_t _saudio_backend_t;\n#elif defined(SAUDIO_ANDROID_AAUDIO)\ntypedef _saudio_aaudio_backend_t _saudio_backend_t;\n#elif defined(_SAUDIO_LINUX)\ntypedef _saudio_alsa_backend_t _saudio_backend_t;\n#endif\n\n/* a ringbuffer structure */\ntypedef struct {\n    int head;  // next slot to write to\n    int tail;  // next slot to read from\n    int num;   // number of slots in queue\n    int queue[SAUDIO_RING_MAX_SLOTS];\n} _saudio_ring_t;\n\n/* a packet FIFO structure */\ntypedef struct {\n    bool valid;\n    int packet_size;            /* size of a single packets in bytes(!) */\n    int num_packets;            /* number of packet in fifo */\n    uint8_t* base_ptr;          /* packet memory chunk base pointer (dynamically allocated) */\n    int cur_packet;             /* current write-packet */\n    int cur_offset;             /* current byte-offset into current write packet */\n    _saudio_mutex_t mutex;      /* mutex for thread-safe access */\n    _saudio_ring_t read_queue;  /* buffers with data, ready to be streamed */\n    _saudio_ring_t write_queue; /* empty buffers, ready to be pushed to */\n} _saudio_fifo_t;\n\n/* sokol-audio state */\ntypedef struct {\n    bool valid;\n    bool setup_called;\n    void (*stream_cb)(float* buffer, int num_frames, int num_channels);\n    void (*stream_userdata_cb)(float* buffer, int num_frames, int num_channels, void* user_data);\n    void* user_data;\n    int sample_rate;            /* sample rate */\n    int buffer_frames;          /* number of frames in streaming buffer */\n    int bytes_per_frame;        /* filled by backend */\n    int packet_frames;          /* number of frames in a packet */\n    int num_packets;            /* number of packets in packet queue */\n    int num_channels;           /* actual number of channels */\n    saudio_desc desc;\n    _saudio_fifo_t fifo;\n    _saudio_backend_t backend;\n} _saudio_state_t;\n\n_SOKOL_PRIVATE _saudio_state_t _saudio;\n\n_SOKOL_PRIVATE bool _saudio_has_callback(void) {\n    return (_saudio.stream_cb || _saudio.stream_userdata_cb);\n}\n\n_SOKOL_PRIVATE void _saudio_stream_callback(float* buffer, int num_frames, int num_channels) {\n    if (_saudio.stream_cb) {\n        _saudio.stream_cb(buffer, num_frames, num_channels);\n    }\n    else if (_saudio.stream_userdata_cb) {\n        _saudio.stream_userdata_cb(buffer, num_frames, num_channels, _saudio.user_data);\n    }\n}\n\n// ██       ██████   ██████   ██████  ██ ███    ██  ██████\n// ██      ██    ██ ██       ██       ██ ████   ██ ██\n// ██      ██    ██ ██   ███ ██   ███ ██ ██ ██  ██ ██   ███\n// ██      ██    ██ ██    ██ ██    ██ ██ ██  ██ ██ ██    ██\n// ███████  ██████   ██████   ██████  ██ ██   ████  ██████\n//\n// >>logging\n#if defined(SOKOL_DEBUG)\n#define _SAUDIO_LOGITEM_XMACRO(item,msg) #item \": \" msg,\nstatic const char* _saudio_log_messages[] = {\n    _SAUDIO_LOG_ITEMS\n};\n#undef _SAUDIO_LOGITEM_XMACRO\n#endif // SOKOL_DEBUG\n\n#define _SAUDIO_PANIC(code) _saudio_log(SAUDIO_LOGITEM_ ##code, 0, __LINE__)\n#define _SAUDIO_ERROR(code) _saudio_log(SAUDIO_LOGITEM_ ##code, 1, __LINE__)\n#define _SAUDIO_WARN(code) _saudio_log(SAUDIO_LOGITEM_ ##code, 2, __LINE__)\n#define _SAUDIO_INFO(code) _saudio_log(SAUDIO_LOGITEM_ ##code, 3, __LINE__)\n\nstatic void _saudio_log(saudio_log_item log_item, uint32_t log_level, uint32_t line_nr) {\n    if (_saudio.desc.logger.func) {\n        #if defined(SOKOL_DEBUG)\n            const char* filename = __FILE__;\n            const char* message = _saudio_log_messages[log_item];\n        #else\n            const char* filename = 0;\n            const char* message = 0;\n        #endif\n        _saudio.desc.logger.func(\"saudio\", log_level, log_item, message, line_nr, filename, _saudio.desc.logger.user_data);\n    }\n    else {\n        // for log level PANIC it would be 'undefined behaviour' to continue\n        if (log_level == 0) {\n            abort();\n        }\n    }\n}\n\n// ███    ███ ███████ ███    ███  ██████  ██████  ██    ██\n// ████  ████ ██      ████  ████ ██    ██ ██   ██  ██  ██\n// ██ ████ ██ █████   ██ ████ ██ ██    ██ ██████    ████\n// ██  ██  ██ ██      ██  ██  ██ ██    ██ ██   ██    ██\n// ██      ██ ███████ ██      ██  ██████  ██   ██    ██\n//\n// >>memory\n_SOKOL_PRIVATE void _saudio_clear(void* ptr, size_t size) {\n    SOKOL_ASSERT(ptr && (size > 0));\n    memset(ptr, 0, size);\n}\n\n_SOKOL_PRIVATE void* _saudio_malloc(size_t size) {\n    SOKOL_ASSERT(size > 0);\n    void* ptr;\n    if (_saudio.desc.allocator.alloc_fn) {\n        ptr = _saudio.desc.allocator.alloc_fn(size, _saudio.desc.allocator.user_data);\n    } else {\n        ptr = malloc(size);\n    }\n    if (0 == ptr) {\n        _SAUDIO_PANIC(MALLOC_FAILED);\n    }\n    return ptr;\n}\n\n_SOKOL_PRIVATE void* _saudio_malloc_clear(size_t size) {\n    void* ptr = _saudio_malloc(size);\n    _saudio_clear(ptr, size);\n    return ptr;\n}\n\n_SOKOL_PRIVATE void _saudio_free(void* ptr) {\n    if (_saudio.desc.allocator.free_fn) {\n        _saudio.desc.allocator.free_fn(ptr, _saudio.desc.allocator.user_data);\n    } else {\n        free(ptr);\n    }\n}\n\n// ███    ███ ██    ██ ████████ ███████ ██   ██\n// ████  ████ ██    ██    ██    ██       ██ ██\n// ██ ████ ██ ██    ██    ██    █████     ███\n// ██  ██  ██ ██    ██    ██    ██       ██ ██\n// ██      ██  ██████     ██    ███████ ██   ██\n//\n// >>mutex\n#if defined(_SAUDIO_NOTHREADS)\n\n_SOKOL_PRIVATE void _saudio_mutex_init(_saudio_mutex_t* m) { (void)m; }\n_SOKOL_PRIVATE void _saudio_mutex_destroy(_saudio_mutex_t* m) { (void)m; }\n_SOKOL_PRIVATE void _saudio_mutex_lock(_saudio_mutex_t* m) { (void)m; }\n_SOKOL_PRIVATE void _saudio_mutex_unlock(_saudio_mutex_t* m) { (void)m; }\n\n#elif defined(_SAUDIO_PTHREADS)\n\n_SOKOL_PRIVATE void _saudio_mutex_init(_saudio_mutex_t* m) {\n    pthread_mutexattr_t attr;\n    pthread_mutexattr_init(&attr);\n    pthread_mutex_init(&m->mutex, &attr);\n}\n\n_SOKOL_PRIVATE void _saudio_mutex_destroy(_saudio_mutex_t* m) {\n    pthread_mutex_destroy(&m->mutex);\n}\n\n_SOKOL_PRIVATE void _saudio_mutex_lock(_saudio_mutex_t* m) {\n    pthread_mutex_lock(&m->mutex);\n}\n\n_SOKOL_PRIVATE void _saudio_mutex_unlock(_saudio_mutex_t* m) {\n    pthread_mutex_unlock(&m->mutex);\n}\n\n#elif defined(_SAUDIO_WINTHREADS)\n\n_SOKOL_PRIVATE void _saudio_mutex_init(_saudio_mutex_t* m) {\n    InitializeCriticalSection(&m->critsec);\n}\n\n_SOKOL_PRIVATE void _saudio_mutex_destroy(_saudio_mutex_t* m) {\n    DeleteCriticalSection(&m->critsec);\n}\n\n_SOKOL_PRIVATE void _saudio_mutex_lock(_saudio_mutex_t* m) {\n    EnterCriticalSection(&m->critsec);\n}\n\n_SOKOL_PRIVATE void _saudio_mutex_unlock(_saudio_mutex_t* m) {\n    LeaveCriticalSection(&m->critsec);\n}\n#else\n#error \"sokol_audio.h: unknown platform!\"\n#endif\n\n// ██████  ██ ███    ██  ██████  ██████  ██    ██ ███████ ███████ ███████ ██████\n// ██   ██ ██ ████   ██ ██       ██   ██ ██    ██ ██      ██      ██      ██   ██\n// ██████  ██ ██ ██  ██ ██   ███ ██████  ██    ██ █████   █████   █████   ██████\n// ██   ██ ██ ██  ██ ██ ██    ██ ██   ██ ██    ██ ██      ██      ██      ██   ██\n// ██   ██ ██ ██   ████  ██████  ██████   ██████  ██      ██      ███████ ██   ██\n//\n// >>ringbuffer\n_SOKOL_PRIVATE int _saudio_ring_idx(_saudio_ring_t* ring, int i) {\n    return (i % ring->num);\n}\n\n_SOKOL_PRIVATE void _saudio_ring_init(_saudio_ring_t* ring, int num_slots) {\n    SOKOL_ASSERT((num_slots + 1) <= SAUDIO_RING_MAX_SLOTS);\n    ring->head = 0;\n    ring->tail = 0;\n    /* one slot reserved to detect 'full' vs 'empty' */\n    ring->num = num_slots + 1;\n}\n\n_SOKOL_PRIVATE bool _saudio_ring_full(_saudio_ring_t* ring) {\n    return _saudio_ring_idx(ring, ring->head + 1) == ring->tail;\n}\n\n_SOKOL_PRIVATE bool _saudio_ring_empty(_saudio_ring_t* ring) {\n    return ring->head == ring->tail;\n}\n\n_SOKOL_PRIVATE int _saudio_ring_count(_saudio_ring_t* ring) {\n    int count;\n    if (ring->head >= ring->tail) {\n        count = ring->head - ring->tail;\n    }\n    else {\n        count = (ring->head + ring->num) - ring->tail;\n    }\n    SOKOL_ASSERT(count < ring->num);\n    return count;\n}\n\n_SOKOL_PRIVATE void _saudio_ring_enqueue(_saudio_ring_t* ring, int val) {\n    SOKOL_ASSERT(!_saudio_ring_full(ring));\n    ring->queue[ring->head] = val;\n    ring->head = _saudio_ring_idx(ring, ring->head + 1);\n}\n\n_SOKOL_PRIVATE int _saudio_ring_dequeue(_saudio_ring_t* ring) {\n    SOKOL_ASSERT(!_saudio_ring_empty(ring));\n    int val = ring->queue[ring->tail];\n    ring->tail = _saudio_ring_idx(ring, ring->tail + 1);\n    return val;\n}\n\n// ███████ ██ ███████  ██████\n// ██      ██ ██      ██    ██\n// █████   ██ █████   ██    ██\n// ██      ██ ██      ██    ██\n// ██      ██ ██       ██████\n//\n// >>fifo\n_SOKOL_PRIVATE void _saudio_fifo_init_mutex(_saudio_fifo_t* fifo) {\n    /* this must be called before initializing both the backend and the fifo itself! */\n    _saudio_mutex_init(&fifo->mutex);\n}\n\n_SOKOL_PRIVATE void _saudio_fifo_destroy_mutex(_saudio_fifo_t* fifo) {\n    _saudio_mutex_destroy(&fifo->mutex);\n}\n\n_SOKOL_PRIVATE void _saudio_fifo_init(_saudio_fifo_t* fifo, int packet_size, int num_packets) {\n    /* NOTE: there's a chicken-egg situation during the init phase where the\n        streaming thread must be started before the fifo is actually initialized,\n        thus the fifo init must already be protected from access by the fifo_read() func.\n    */\n    _saudio_mutex_lock(&fifo->mutex);\n    SOKOL_ASSERT((packet_size > 0) && (num_packets > 0));\n    fifo->packet_size = packet_size;\n    fifo->num_packets = num_packets;\n    fifo->base_ptr = (uint8_t*) _saudio_malloc((size_t)(packet_size * num_packets));\n    fifo->cur_packet = -1;\n    fifo->cur_offset = 0;\n    _saudio_ring_init(&fifo->read_queue, num_packets);\n    _saudio_ring_init(&fifo->write_queue, num_packets);\n    for (int i = 0; i < num_packets; i++) {\n        _saudio_ring_enqueue(&fifo->write_queue, i);\n    }\n    SOKOL_ASSERT(_saudio_ring_full(&fifo->write_queue));\n    SOKOL_ASSERT(_saudio_ring_count(&fifo->write_queue) == num_packets);\n    SOKOL_ASSERT(_saudio_ring_empty(&fifo->read_queue));\n    SOKOL_ASSERT(_saudio_ring_count(&fifo->read_queue) == 0);\n    fifo->valid = true;\n    _saudio_mutex_unlock(&fifo->mutex);\n}\n\n_SOKOL_PRIVATE void _saudio_fifo_shutdown(_saudio_fifo_t* fifo) {\n    SOKOL_ASSERT(fifo->base_ptr);\n    _saudio_free(fifo->base_ptr);\n    fifo->base_ptr = 0;\n    fifo->valid = false;\n}\n\n_SOKOL_PRIVATE int _saudio_fifo_writable_bytes(_saudio_fifo_t* fifo) {\n    _saudio_mutex_lock(&fifo->mutex);\n    int num_bytes = (_saudio_ring_count(&fifo->write_queue) * fifo->packet_size);\n    if (fifo->cur_packet != -1) {\n        num_bytes += fifo->packet_size - fifo->cur_offset;\n    }\n    _saudio_mutex_unlock(&fifo->mutex);\n    SOKOL_ASSERT((num_bytes >= 0) && (num_bytes <= (fifo->num_packets * fifo->packet_size)));\n    return num_bytes;\n}\n\n/* write new data to the write queue, this is called from main thread */\n_SOKOL_PRIVATE int _saudio_fifo_write(_saudio_fifo_t* fifo, const uint8_t* ptr, int num_bytes) {\n    /* returns the number of bytes written, this will be smaller then requested\n        if the write queue runs full\n    */\n    int all_to_copy = num_bytes;\n    while (all_to_copy > 0) {\n        /* need to grab a new packet? */\n        if (fifo->cur_packet == -1) {\n            _saudio_mutex_lock(&fifo->mutex);\n            if (!_saudio_ring_empty(&fifo->write_queue)) {\n                fifo->cur_packet = _saudio_ring_dequeue(&fifo->write_queue);\n            }\n            _saudio_mutex_unlock(&fifo->mutex);\n            SOKOL_ASSERT(fifo->cur_offset == 0);\n        }\n        /* append data to current write packet */\n        if (fifo->cur_packet != -1) {\n            int to_copy = all_to_copy;\n            const int max_copy = fifo->packet_size - fifo->cur_offset;\n            if (to_copy > max_copy) {\n                to_copy = max_copy;\n            }\n            uint8_t* dst = fifo->base_ptr + fifo->cur_packet * fifo->packet_size + fifo->cur_offset;\n            memcpy(dst, ptr, (size_t)to_copy);\n            ptr += to_copy;\n            fifo->cur_offset += to_copy;\n            all_to_copy -= to_copy;\n            SOKOL_ASSERT(fifo->cur_offset <= fifo->packet_size);\n            SOKOL_ASSERT(all_to_copy >= 0);\n        }\n        else {\n            /* early out if we're starving */\n            int bytes_copied = num_bytes - all_to_copy;\n            SOKOL_ASSERT((bytes_copied >= 0) && (bytes_copied < num_bytes));\n            return bytes_copied;\n        }\n        /* if write packet is full, push to read queue */\n        if (fifo->cur_offset == fifo->packet_size) {\n            _saudio_mutex_lock(&fifo->mutex);\n            _saudio_ring_enqueue(&fifo->read_queue, fifo->cur_packet);\n            _saudio_mutex_unlock(&fifo->mutex);\n            fifo->cur_packet = -1;\n            fifo->cur_offset = 0;\n        }\n    }\n    SOKOL_ASSERT(all_to_copy == 0);\n    return num_bytes;\n}\n\n/* read queued data, this is called form the stream callback (maybe separate thread) */\n_SOKOL_PRIVATE int _saudio_fifo_read(_saudio_fifo_t* fifo, uint8_t* ptr, int num_bytes) {\n    /* NOTE: fifo_read might be called before the fifo is properly initialized */\n    _saudio_mutex_lock(&fifo->mutex);\n    int num_bytes_copied = 0;\n    if (fifo->valid) {\n        SOKOL_ASSERT(0 == (num_bytes % fifo->packet_size));\n        SOKOL_ASSERT(num_bytes <= (fifo->packet_size * fifo->num_packets));\n        const int num_packets_needed = num_bytes / fifo->packet_size;\n        uint8_t* dst = ptr;\n        /* either pull a full buffer worth of data, or nothing */\n        if (_saudio_ring_count(&fifo->read_queue) >= num_packets_needed) {\n            for (int i = 0; i < num_packets_needed; i++) {\n                int packet_index = _saudio_ring_dequeue(&fifo->read_queue);\n                _saudio_ring_enqueue(&fifo->write_queue, packet_index);\n                const uint8_t* src = fifo->base_ptr + packet_index * fifo->packet_size;\n                memcpy(dst, src, (size_t)fifo->packet_size);\n                dst += fifo->packet_size;\n                num_bytes_copied += fifo->packet_size;\n            }\n            SOKOL_ASSERT(num_bytes == num_bytes_copied);\n        }\n    }\n    _saudio_mutex_unlock(&fifo->mutex);\n    return num_bytes_copied;\n}\n\n// ██████  ██    ██ ███    ███ ███    ███ ██    ██\n// ██   ██ ██    ██ ████  ████ ████  ████  ██  ██\n// ██   ██ ██    ██ ██ ████ ██ ██ ████ ██   ████\n// ██   ██ ██    ██ ██  ██  ██ ██  ██  ██    ██\n// ██████   ██████  ██      ██ ██      ██    ██\n//\n// >>dummy\n#if defined(SOKOL_DUMMY_BACKEND)\n_SOKOL_PRIVATE bool _saudio_dummy_backend_init(void) {\n    _saudio.bytes_per_frame = _saudio.num_channels * (int)sizeof(float);\n    return true;\n};\n_SOKOL_PRIVATE void _saudio_dummy_backend_shutdown(void) { };\n\n//  █████  ██      ███████  █████\n// ██   ██ ██      ██      ██   ██\n// ███████ ██      ███████ ███████\n// ██   ██ ██           ██ ██   ██\n// ██   ██ ███████ ███████ ██   ██\n//\n// >>alsa\n#elif defined(_SAUDIO_LINUX)\n\n/* the streaming callback runs in a separate thread */\n_SOKOL_PRIVATE void* _saudio_alsa_cb(void* param) {\n    _SOKOL_UNUSED(param);\n    while (!_saudio.backend.thread_stop) {\n        /* snd_pcm_writei() will be blocking until it needs data */\n        int write_res = snd_pcm_writei(_saudio.backend.device, _saudio.backend.buffer, (snd_pcm_uframes_t)_saudio.backend.buffer_frames);\n        if (write_res < 0) {\n            /* underrun occurred */\n            snd_pcm_prepare(_saudio.backend.device);\n        }\n        else {\n            /* fill the streaming buffer with new data */\n            if (_saudio_has_callback()) {\n                _saudio_stream_callback(_saudio.backend.buffer, _saudio.backend.buffer_frames, _saudio.num_channels);\n            }\n            else {\n                if (0 == _saudio_fifo_read(&_saudio.fifo, (uint8_t*)_saudio.backend.buffer, _saudio.backend.buffer_byte_size)) {\n                    /* not enough read data available, fill the entire buffer with silence */\n                    _saudio_clear(_saudio.backend.buffer, (size_t)_saudio.backend.buffer_byte_size);\n                }\n            }\n        }\n    }\n    return 0;\n}\n\n_SOKOL_PRIVATE bool _saudio_alsa_backend_init(void) {\n    int dir; uint32_t rate;\n    int rc = snd_pcm_open(&_saudio.backend.device, \"default\", SND_PCM_STREAM_PLAYBACK, 0);\n    if (rc < 0) {\n        _SAUDIO_ERROR(ALSA_SND_PCM_OPEN_FAILED);\n        return false;\n    }\n\n    /* configuration works by restricting the 'configuration space' step\n       by step, we require all parameters except the sample rate to\n       match perfectly\n    */\n    snd_pcm_hw_params_t* params = 0;\n    snd_pcm_hw_params_alloca(&params);\n    snd_pcm_hw_params_any(_saudio.backend.device, params);\n    snd_pcm_hw_params_set_access(_saudio.backend.device, params, SND_PCM_ACCESS_RW_INTERLEAVED);\n    if (0 > snd_pcm_hw_params_set_format(_saudio.backend.device, params, SND_PCM_FORMAT_FLOAT_LE)) {\n        _SAUDIO_ERROR(ALSA_FLOAT_SAMPLES_NOT_SUPPORTED);\n        goto error;\n    }\n    if (0 > snd_pcm_hw_params_set_buffer_size(_saudio.backend.device, params, (snd_pcm_uframes_t)_saudio.buffer_frames)) {\n        _SAUDIO_ERROR(ALSA_REQUESTED_BUFFER_SIZE_NOT_SUPPORTED);\n        goto error;\n    }\n    if (0 > snd_pcm_hw_params_set_channels(_saudio.backend.device, params, (uint32_t)_saudio.num_channels)) {\n        _SAUDIO_ERROR(ALSA_REQUESTED_CHANNEL_COUNT_NOT_SUPPORTED);\n        goto error;\n    }\n    /* let ALSA pick a nearby sampling rate */\n    rate = (uint32_t) _saudio.sample_rate;\n    dir = 0;\n    if (0 > snd_pcm_hw_params_set_rate_near(_saudio.backend.device, params, &rate, &dir)) {\n        _SAUDIO_ERROR(ALSA_SND_PCM_HW_PARAMS_SET_RATE_NEAR_FAILED);\n        goto error;\n    }\n    if (0 > snd_pcm_hw_params(_saudio.backend.device, params)) {\n        _SAUDIO_ERROR(ALSA_SND_PCM_HW_PARAMS_FAILED);\n        goto error;\n    }\n\n    /* read back actual sample rate and channels */\n    _saudio.sample_rate = (int)rate;\n    _saudio.bytes_per_frame = _saudio.num_channels * (int)sizeof(float);\n\n    /* allocate the streaming buffer */\n    _saudio.backend.buffer_byte_size = _saudio.buffer_frames * _saudio.bytes_per_frame;\n    _saudio.backend.buffer_frames = _saudio.buffer_frames;\n    _saudio.backend.buffer = (float*) _saudio_malloc_clear((size_t)_saudio.backend.buffer_byte_size);\n\n    /* create the buffer-streaming start thread */\n    if (0 != pthread_create(&_saudio.backend.thread, 0, _saudio_alsa_cb, 0)) {\n        _SAUDIO_ERROR(ALSA_PTHREAD_CREATE_FAILED);\n        goto error;\n    }\n\n    return true;\nerror:\n    if (_saudio.backend.device) {\n        snd_pcm_close(_saudio.backend.device);\n        _saudio.backend.device = 0;\n    }\n    return false;\n};\n\n_SOKOL_PRIVATE void _saudio_alsa_backend_shutdown(void) {\n    SOKOL_ASSERT(_saudio.backend.device);\n    _saudio.backend.thread_stop = true;\n    pthread_join(_saudio.backend.thread, 0);\n    snd_pcm_drain(_saudio.backend.device);\n    snd_pcm_close(_saudio.backend.device);\n    _saudio_free(_saudio.backend.buffer);\n};\n\n// ██     ██  █████  ███████  █████  ██████  ██\n// ██     ██ ██   ██ ██      ██   ██ ██   ██ ██\n// ██  █  ██ ███████ ███████ ███████ ██████  ██\n// ██ ███ ██ ██   ██      ██ ██   ██ ██      ██\n//  ███ ███  ██   ██ ███████ ██   ██ ██      ██\n//\n// >>wasapi\n#elif defined(_SAUDIO_WINDOWS)\n\n/* fill intermediate buffer with new data and reset buffer_pos */\n_SOKOL_PRIVATE void _saudio_wasapi_fill_buffer(void) {\n    if (_saudio_has_callback()) {\n        _saudio_stream_callback(_saudio.backend.thread.src_buffer, _saudio.backend.thread.src_buffer_frames, _saudio.num_channels);\n    }\n    else {\n        if (0 == _saudio_fifo_read(&_saudio.fifo, (uint8_t*)_saudio.backend.thread.src_buffer, _saudio.backend.thread.src_buffer_byte_size)) {\n            /* not enough read data available, fill the entire buffer with silence */\n            _saudio_clear(_saudio.backend.thread.src_buffer, (size_t)_saudio.backend.thread.src_buffer_byte_size);\n        }\n    }\n}\n\n_SOKOL_PRIVATE int _saudio_wasapi_min(int a, int b) {\n    return (a < b) ? a : b;\n}\n\n_SOKOL_PRIVATE void _saudio_wasapi_submit_buffer(int num_frames) {\n    BYTE* wasapi_buffer = 0;\n    if (FAILED(IAudioRenderClient_GetBuffer(_saudio.backend.render_client, num_frames, &wasapi_buffer))) {\n        return;\n    }\n    SOKOL_ASSERT(wasapi_buffer);\n\n    /* copy samples to WASAPI buffer, refill source buffer if needed */\n    int num_remaining_samples = num_frames * _saudio.num_channels;\n    int buffer_pos = _saudio.backend.thread.src_buffer_pos;\n    const int buffer_size_in_samples = _saudio.backend.thread.src_buffer_byte_size / (int)sizeof(float);\n    float* dst = (float*)wasapi_buffer;\n    const float* dst_end = dst + num_remaining_samples;\n    _SOKOL_UNUSED(dst_end); // suppress unused warning in release mode\n    const float* src = _saudio.backend.thread.src_buffer;\n\n    while (num_remaining_samples > 0) {\n        if (0 == buffer_pos) {\n            _saudio_wasapi_fill_buffer();\n        }\n        const int samples_to_copy = _saudio_wasapi_min(num_remaining_samples, buffer_size_in_samples - buffer_pos);\n        SOKOL_ASSERT((buffer_pos + samples_to_copy) <= buffer_size_in_samples);\n        SOKOL_ASSERT((dst + samples_to_copy) <= dst_end);\n        memcpy(dst, &src[buffer_pos], (size_t)samples_to_copy * sizeof(float));\n        num_remaining_samples -= samples_to_copy;\n        SOKOL_ASSERT(num_remaining_samples >= 0);\n        buffer_pos += samples_to_copy;\n        dst += samples_to_copy;\n\n        SOKOL_ASSERT(buffer_pos <= buffer_size_in_samples);\n        if (buffer_pos == buffer_size_in_samples) {\n            buffer_pos = 0;\n        }\n    }\n    _saudio.backend.thread.src_buffer_pos = buffer_pos;\n    IAudioRenderClient_ReleaseBuffer(_saudio.backend.render_client, num_frames, 0);\n}\n\n_SOKOL_PRIVATE DWORD WINAPI _saudio_wasapi_thread_fn(LPVOID param) {\n    (void)param;\n    _saudio_wasapi_submit_buffer(_saudio.backend.thread.src_buffer_frames);\n    IAudioClient_Start(_saudio.backend.audio_client);\n    while (!_saudio.backend.thread.stop) {\n        WaitForSingleObject(_saudio.backend.thread.buffer_end_event, INFINITE);\n        UINT32 padding = 0;\n        if (FAILED(IAudioClient_GetCurrentPadding(_saudio.backend.audio_client, &padding))) {\n            continue;\n        }\n        SOKOL_ASSERT(_saudio.backend.thread.dst_buffer_frames >= padding);\n        int num_frames = (int)_saudio.backend.thread.dst_buffer_frames - (int)padding;\n        if (num_frames > 0) {\n            _saudio_wasapi_submit_buffer(num_frames);\n        }\n    }\n    return 0;\n}\n\n_SOKOL_PRIVATE void _saudio_wasapi_release(void) {\n    if (_saudio.backend.thread.src_buffer) {\n        _saudio_free(_saudio.backend.thread.src_buffer);\n        _saudio.backend.thread.src_buffer = 0;\n    }\n    if (_saudio.backend.render_client) {\n        IAudioRenderClient_Release(_saudio.backend.render_client);\n        _saudio.backend.render_client = 0;\n    }\n    if (_saudio.backend.audio_client) {\n        IAudioClient_Release(_saudio.backend.audio_client);\n        _saudio.backend.audio_client = 0;\n    }\n    if (_saudio.backend.device) {\n        IMMDevice_Release(_saudio.backend.device);\n        _saudio.backend.device = 0;\n    }\n    if (_saudio.backend.device_enumerator) {\n        IMMDeviceEnumerator_Release(_saudio.backend.device_enumerator);\n        _saudio.backend.device_enumerator = 0;\n    }\n    if (0 != _saudio.backend.thread.buffer_end_event) {\n        CloseHandle(_saudio.backend.thread.buffer_end_event);\n        _saudio.backend.thread.buffer_end_event = 0;\n    }\n}\n\n_SOKOL_PRIVATE bool _saudio_wasapi_backend_init(void) {\n    REFERENCE_TIME dur;\n    /* CoInitializeEx could have been called elsewhere already, in which\n        case the function returns with S_FALSE (thus it does not make much\n        sense to check the result)\n    */\n    HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);\n    _SOKOL_UNUSED(hr);\n    _saudio.backend.thread.buffer_end_event = CreateEvent(0, FALSE, FALSE, 0);\n    if (0 == _saudio.backend.thread.buffer_end_event) {\n        _SAUDIO_ERROR(WASAPI_CREATE_EVENT_FAILED);\n        goto error;\n    }\n    if (FAILED(CoCreateInstance(_SOKOL_AUDIO_WIN32COM_ID(_saudio_CLSID_IMMDeviceEnumerator),\n        0, CLSCTX_ALL,\n        _SOKOL_AUDIO_WIN32COM_ID(_saudio_IID_IMMDeviceEnumerator),\n        (void**)&_saudio.backend.device_enumerator)))\n    {\n        _SAUDIO_ERROR(WASAPI_CREATE_DEVICE_ENUMERATOR_FAILED);\n        goto error;\n    }\n    if (FAILED(IMMDeviceEnumerator_GetDefaultAudioEndpoint(_saudio.backend.device_enumerator,\n        eRender, eConsole,\n        &_saudio.backend.device)))\n    {\n        _SAUDIO_ERROR(WASAPI_GET_DEFAULT_AUDIO_ENDPOINT_FAILED);\n        goto error;\n    }\n    if (FAILED(IMMDevice_Activate(_saudio.backend.device,\n        _SOKOL_AUDIO_WIN32COM_ID(_saudio_IID_IAudioClient),\n        CLSCTX_ALL, 0,\n        (void**)&_saudio.backend.audio_client)))\n    {\n        _SAUDIO_ERROR(WASAPI_DEVICE_ACTIVATE_FAILED);\n        goto error;\n    }\n\n    WAVEFORMATEXTENSIBLE fmtex;\n    _saudio_clear(&fmtex, sizeof(fmtex));\n    fmtex.Format.nChannels = (WORD)_saudio.num_channels;\n    fmtex.Format.nSamplesPerSec = (DWORD)_saudio.sample_rate;\n    fmtex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;\n    fmtex.Format.wBitsPerSample = 32;\n    fmtex.Format.nBlockAlign = (fmtex.Format.nChannels * fmtex.Format.wBitsPerSample) / 8;\n    fmtex.Format.nAvgBytesPerSec = fmtex.Format.nSamplesPerSec * fmtex.Format.nBlockAlign;\n    fmtex.Format.cbSize = 22;   /* WORD + DWORD + GUID */\n    fmtex.Samples.wValidBitsPerSample = 32;\n    if (_saudio.num_channels == 1) {\n        fmtex.dwChannelMask = SPEAKER_FRONT_CENTER;\n    }\n    else {\n        fmtex.dwChannelMask = SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT;\n    }\n    fmtex.SubFormat = _saudio_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;\n    dur = (REFERENCE_TIME)\n        (((double)_saudio.buffer_frames) / (((double)_saudio.sample_rate) * (1.0/10000000.0)));\n    if (FAILED(IAudioClient_Initialize(_saudio.backend.audio_client,\n        AUDCLNT_SHAREMODE_SHARED,\n        AUDCLNT_STREAMFLAGS_EVENTCALLBACK|AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM|AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY,\n        dur, 0, (WAVEFORMATEX*)&fmtex, 0)))\n    {\n        _SAUDIO_ERROR(WASAPI_AUDIO_CLIENT_INITIALIZE_FAILED);\n        goto error;\n    }\n    if (FAILED(IAudioClient_GetBufferSize(_saudio.backend.audio_client, &_saudio.backend.thread.dst_buffer_frames))) {\n        _SAUDIO_ERROR(WASAPI_AUDIO_CLIENT_GET_BUFFER_SIZE_FAILED);\n        goto error;\n    }\n    if (FAILED(IAudioClient_GetService(_saudio.backend.audio_client,\n        _SOKOL_AUDIO_WIN32COM_ID(_saudio_IID_IAudioRenderClient),\n        (void**)&_saudio.backend.render_client)))\n    {\n        _SAUDIO_ERROR(WASAPI_AUDIO_CLIENT_GET_SERVICE_FAILED);\n        goto error;\n    }\n    if (FAILED(IAudioClient_SetEventHandle(_saudio.backend.audio_client, _saudio.backend.thread.buffer_end_event))) {\n        _SAUDIO_ERROR(WASAPI_AUDIO_CLIENT_SET_EVENT_HANDLE_FAILED);\n        goto error;\n    }\n    _saudio.bytes_per_frame = _saudio.num_channels * (int)sizeof(float);\n    _saudio.backend.thread.src_buffer_frames = _saudio.buffer_frames;\n    _saudio.backend.thread.src_buffer_byte_size = _saudio.backend.thread.src_buffer_frames * _saudio.bytes_per_frame;\n\n    /* allocate an intermediate buffer for sample format conversion */\n    _saudio.backend.thread.src_buffer = (float*) _saudio_malloc((size_t)_saudio.backend.thread.src_buffer_byte_size);\n\n    /* create streaming thread */\n    _saudio.backend.thread.thread_handle = CreateThread(NULL, 0, _saudio_wasapi_thread_fn, 0, 0, 0);\n    if (0 == _saudio.backend.thread.thread_handle) {\n        _SAUDIO_ERROR(WASAPI_CREATE_THREAD_FAILED);\n        goto error;\n    }\n    return true;\nerror:\n    _saudio_wasapi_release();\n    return false;\n}\n\n_SOKOL_PRIVATE void _saudio_wasapi_backend_shutdown(void) {\n    if (_saudio.backend.thread.thread_handle) {\n        _saudio.backend.thread.stop = true;\n        SetEvent(_saudio.backend.thread.buffer_end_event);\n        WaitForSingleObject(_saudio.backend.thread.thread_handle, INFINITE);\n        CloseHandle(_saudio.backend.thread.thread_handle);\n        _saudio.backend.thread.thread_handle = 0;\n    }\n    if (_saudio.backend.audio_client) {\n        IAudioClient_Stop(_saudio.backend.audio_client);\n    }\n    _saudio_wasapi_release();\n    CoUninitialize();\n}\n\n// ██     ██ ███████ ██████   █████  ██    ██ ██████  ██  ██████\n// ██     ██ ██      ██   ██ ██   ██ ██    ██ ██   ██ ██ ██    ██\n// ██  █  ██ █████   ██████  ███████ ██    ██ ██   ██ ██ ██    ██\n// ██ ███ ██ ██      ██   ██ ██   ██ ██    ██ ██   ██ ██ ██    ██\n//  ███ ███  ███████ ██████  ██   ██  ██████  ██████  ██  ██████\n//\n// >>webaudio\n#elif defined(_SAUDIO_EMSCRIPTEN)\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nEMSCRIPTEN_KEEPALIVE int _saudio_emsc_pull(int num_frames) {\n    SOKOL_ASSERT(_saudio.backend.buffer);\n    if (num_frames == _saudio.buffer_frames) {\n        if (_saudio_has_callback()) {\n            _saudio_stream_callback((float*)_saudio.backend.buffer, num_frames, _saudio.num_channels);\n        }\n        else {\n            const int num_bytes = num_frames * _saudio.bytes_per_frame;\n            if (0 == _saudio_fifo_read(&_saudio.fifo, _saudio.backend.buffer, num_bytes)) {\n                /* not enough read data available, fill the entire buffer with silence */\n                _saudio_clear(_saudio.backend.buffer, (size_t)num_bytes);\n            }\n        }\n        int res = (int) _saudio.backend.buffer;\n        return res;\n    }\n    else {\n        return 0;\n    }\n}\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n/* setup the WebAudio context and attach a ScriptProcessorNode */\nEM_JS(int, saudio_js_init, (int sample_rate, int num_channels, int buffer_size), {\n    Module._saudio_context = null;\n    Module._saudio_node = null;\n    if (typeof AudioContext !== 'undefined') {\n        Module._saudio_context = new AudioContext({\n            sampleRate: sample_rate,\n            latencyHint: 'interactive',\n        });\n    }\n    else {\n        Module._saudio_context = null;\n        console.log('sokol_audio.h: no WebAudio support');\n    }\n    if (Module._saudio_context) {\n        console.log('sokol_audio.h: sample rate ', Module._saudio_context.sampleRate);\n        Module._saudio_node = Module._saudio_context.createScriptProcessor(buffer_size, 0, num_channels);\n        Module._saudio_node.onaudioprocess = (event) => {\n            const num_frames = event.outputBuffer.length;\n            const ptr = __saudio_emsc_pull(num_frames);\n            if (ptr) {\n                const num_channels = event.outputBuffer.numberOfChannels;\n                for (let chn = 0; chn < num_channels; chn++) {\n                    const chan = event.outputBuffer.getChannelData(chn);\n                    for (let i = 0; i < num_frames; i++) {\n                        chan[i] = HEAPF32[(ptr>>2) + ((num_channels*i)+chn)]\n                    }\n                }\n            }\n        };\n        Module._saudio_node.connect(Module._saudio_context.destination);\n\n        // in some browsers, WebAudio needs to be activated on a user action\n        const resume_webaudio = () => {\n            if (Module._saudio_context) {\n                if (Module._saudio_context.state === 'suspended') {\n                    Module._saudio_context.resume();\n                }\n            }\n        };\n        document.addEventListener('click', resume_webaudio, {once:true});\n        document.addEventListener('touchend', resume_webaudio, {once:true});\n        document.addEventListener('keydown', resume_webaudio, {once:true});\n        return 1;\n    }\n    else {\n        return 0;\n    }\n});\n\n/* shutdown the WebAudioContext and ScriptProcessorNode */\nEM_JS(void, saudio_js_shutdown, (void), {\n    \\x2F\\x2A\\x2A @suppress {missingProperties} \\x2A\\x2F\n    const ctx = Module._saudio_context;\n    if (ctx !== null) {\n        if (Module._saudio_node) {\n            Module._saudio_node.disconnect();\n        }\n        ctx.close();\n        Module._saudio_context = null;\n        Module._saudio_node = null;\n    }\n});\n\n/* get the actual sample rate back from the WebAudio context */\nEM_JS(int, saudio_js_sample_rate, (void), {\n    if (Module._saudio_context) {\n        return Module._saudio_context.sampleRate;\n    }\n    else {\n        return 0;\n    }\n});\n\n/* get the actual buffer size in number of frames */\nEM_JS(int, saudio_js_buffer_frames, (void), {\n    if (Module._saudio_node) {\n        return Module._saudio_node.bufferSize;\n    }\n    else {\n        return 0;\n    }\n});\n\n/* return 1 if the WebAudio context is currently suspended, else 0 */\nEM_JS(int, saudio_js_suspended, (void), {\n    if (Module._saudio_context) {\n        if (Module._saudio_context.state === 'suspended') {\n            return 1;\n        }\n        else {\n            return 0;\n        }\n    }\n});\n\n_SOKOL_PRIVATE bool _saudio_webaudio_backend_init(void) {\n    if (saudio_js_init(_saudio.sample_rate, _saudio.num_channels, _saudio.buffer_frames)) {\n        _saudio.bytes_per_frame = (int)sizeof(float) * _saudio.num_channels;\n        _saudio.sample_rate = saudio_js_sample_rate();\n        _saudio.buffer_frames = saudio_js_buffer_frames();\n        const size_t buf_size = (size_t) (_saudio.buffer_frames * _saudio.bytes_per_frame);\n        _saudio.backend.buffer = (uint8_t*) _saudio_malloc(buf_size);\n        return true;\n    }\n    else {\n        return false;\n    }\n}\n\n_SOKOL_PRIVATE void _saudio_webaudio_backend_shutdown(void) {\n    saudio_js_shutdown();\n    if (_saudio.backend.buffer) {\n        _saudio_free(_saudio.backend.buffer);\n        _saudio.backend.buffer = 0;\n    }\n}\n\n//  █████   █████  ██    ██ ██████  ██  ██████\n// ██   ██ ██   ██ ██    ██ ██   ██ ██ ██    ██\n// ███████ ███████ ██    ██ ██   ██ ██ ██    ██\n// ██   ██ ██   ██ ██    ██ ██   ██ ██ ██    ██\n// ██   ██ ██   ██  ██████  ██████  ██  ██████\n//\n// >>aaudio\n#elif defined(SAUDIO_ANDROID_AAUDIO)\n\n_SOKOL_PRIVATE aaudio_data_callback_result_t _saudio_aaudio_data_callback(AAudioStream* stream, void* user_data, void* audio_data, int32_t num_frames) {\n    _SOKOL_UNUSED(user_data);\n    _SOKOL_UNUSED(stream);\n    if (_saudio_has_callback()) {\n        _saudio_stream_callback((float*)audio_data, (int)num_frames, _saudio.num_channels);\n    }\n    else {\n        uint8_t* ptr = (uint8_t*)audio_data;\n        int num_bytes = _saudio.bytes_per_frame * num_frames;\n        if (0 == _saudio_fifo_read(&_saudio.fifo, ptr, num_bytes)) {\n            // not enough read data available, fill the entire buffer with silence\n            memset(ptr, 0, (size_t)num_bytes);\n        }\n    }\n    return AAUDIO_CALLBACK_RESULT_CONTINUE;\n}\n\n_SOKOL_PRIVATE bool _saudio_aaudio_start_stream(void) {\n    if (AAudioStreamBuilder_openStream(_saudio.backend.builder, &_saudio.backend.stream) != AAUDIO_OK) {\n        _SAUDIO_ERROR(AAUDIO_STREAMBUILDER_OPEN_STREAM_FAILED);\n        return false;\n    }\n    AAudioStream_requestStart(_saudio.backend.stream);\n    return true;\n}\n\n_SOKOL_PRIVATE void _saudio_aaudio_stop_stream(void) {\n    if (_saudio.backend.stream) {\n        AAudioStream_requestStop(_saudio.backend.stream);\n        AAudioStream_close(_saudio.backend.stream);\n        _saudio.backend.stream = 0;\n    }\n}\n\n_SOKOL_PRIVATE void* _saudio_aaudio_restart_stream_thread_fn(void* param) {\n    _SOKOL_UNUSED(param);\n    _SAUDIO_WARN(AAUDIO_RESTARTING_STREAM_AFTER_ERROR);\n    pthread_mutex_lock(&_saudio.backend.mutex);\n    _saudio_aaudio_stop_stream();\n    _saudio_aaudio_start_stream();\n    pthread_mutex_unlock(&_saudio.backend.mutex);\n    return 0;\n}\n\n_SOKOL_PRIVATE void _saudio_aaudio_error_callback(AAudioStream* stream, void* user_data, aaudio_result_t error) {\n    _SOKOL_UNUSED(stream);\n    _SOKOL_UNUSED(user_data);\n    if (error == AAUDIO_ERROR_DISCONNECTED) {\n        if (0 != pthread_create(&_saudio.backend.thread, 0, _saudio_aaudio_restart_stream_thread_fn, 0)) {\n            _SAUDIO_ERROR(AAUDIO_PTHREAD_CREATE_FAILED);\n        }\n    }\n}\n\n_SOKOL_PRIVATE void _saudio_aaudio_backend_shutdown(void) {\n    pthread_mutex_lock(&_saudio.backend.mutex);\n    _saudio_aaudio_stop_stream();\n    pthread_mutex_unlock(&_saudio.backend.mutex);\n    if (_saudio.backend.builder) {\n        AAudioStreamBuilder_delete(_saudio.backend.builder);\n        _saudio.backend.builder = 0;\n    }\n    pthread_mutex_destroy(&_saudio.backend.mutex);\n}\n\n_SOKOL_PRIVATE bool _saudio_aaudio_backend_init(void) {\n    _SAUDIO_INFO(USING_AAUDIO_BACKEND);\n\n    _saudio.bytes_per_frame = _saudio.num_channels * (int)sizeof(float);\n\n    pthread_mutexattr_t attr;\n    pthread_mutexattr_init(&attr);\n    pthread_mutex_init(&_saudio.backend.mutex, &attr);\n\n    if (AAudio_createStreamBuilder(&_saudio.backend.builder) != AAUDIO_OK) {\n        _SAUDIO_ERROR(AAUDIO_CREATE_STREAMBUILDER_FAILED);\n        _saudio_aaudio_backend_shutdown();\n        return false;\n    }\n\n    AAudioStreamBuilder_setFormat(_saudio.backend.builder, AAUDIO_FORMAT_PCM_FLOAT);\n    AAudioStreamBuilder_setSampleRate(_saudio.backend.builder, _saudio.sample_rate);\n    AAudioStreamBuilder_setChannelCount(_saudio.backend.builder, _saudio.num_channels);\n    AAudioStreamBuilder_setBufferCapacityInFrames(_saudio.backend.builder, _saudio.buffer_frames * 2);\n    AAudioStreamBuilder_setFramesPerDataCallback(_saudio.backend.builder, _saudio.buffer_frames);\n    AAudioStreamBuilder_setDataCallback(_saudio.backend.builder, _saudio_aaudio_data_callback, 0);\n    AAudioStreamBuilder_setErrorCallback(_saudio.backend.builder, _saudio_aaudio_error_callback, 0);\n\n    if (!_saudio_aaudio_start_stream()) {\n        _saudio_aaudio_backend_shutdown();\n        return false;\n    }\n\n    return true;\n}\n\n//  ██████  ██████  ███████ ███    ██ ███████ ██      ███████ ███████\n// ██    ██ ██   ██ ██      ████   ██ ██      ██      ██      ██\n// ██    ██ ██████  █████   ██ ██  ██ ███████ ██      █████   ███████\n// ██    ██ ██      ██      ██  ██ ██      ██ ██      ██           ██\n//  ██████  ██      ███████ ██   ████ ███████ ███████ ███████ ███████\n//\n//  >>opensles\n//  >>sles\n#elif defined(SAUDIO_ANDROID_SLES)\n\n_SOKOL_PRIVATE void _saudio_sles_semaphore_init(_saudio_sles_semaphore_t* sem) {\n    sem->count = 0;\n    int r = pthread_mutex_init(&sem->mutex, NULL);\n    SOKOL_ASSERT(r == 0);\n    r = pthread_cond_init(&sem->cond, NULL);\n    SOKOL_ASSERT(r == 0);\n    (void)(r);\n}\n\n_SOKOL_PRIVATE void _saudio_sles_semaphore_destroy(_saudio_sles_semaphore_t* sem) {\n    pthread_cond_destroy(&sem->cond);\n    pthread_mutex_destroy(&sem->mutex);\n}\n\n_SOKOL_PRIVATE void _saudio_sles_semaphore_post(_saudio_sles_semaphore_t* sem, int count) {\n    int r = pthread_mutex_lock(&sem->mutex);\n    SOKOL_ASSERT(r == 0);\n    for (int ii = 0; ii < count; ii++) {\n        r = pthread_cond_signal(&sem->cond);\n        SOKOL_ASSERT(r == 0);\n    }\n    sem->count += count;\n    r = pthread_mutex_unlock(&sem->mutex);\n    SOKOL_ASSERT(r == 0);\n    (void)(r);\n}\n\n_SOKOL_PRIVATE bool _saudio_sles_semaphore_wait(_saudio_sles_semaphore_t* sem) {\n    int r = pthread_mutex_lock(&sem->mutex);\n    SOKOL_ASSERT(r == 0);\n    while (r == 0 && sem->count <= 0) {\n        r = pthread_cond_wait(&sem->cond, &sem->mutex);\n    }\n    bool ok = (r == 0);\n    if (ok) {\n        --sem->count;\n    }\n    r = pthread_mutex_unlock(&sem->mutex);\n    (void)(r);\n    return ok;\n}\n\n/* fill intermediate buffer with new data and reset buffer_pos */\n_SOKOL_PRIVATE void _saudio_sles_fill_buffer(void) {\n    int src_buffer_frames = _saudio.buffer_frames;\n    if (_saudio_has_callback()) {\n        _saudio_stream_callback(_saudio.backend.src_buffer, src_buffer_frames, _saudio.num_channels);\n    }\n    else {\n        const int src_buffer_byte_size = src_buffer_frames * _saudio.num_channels * (int)sizeof(float);\n        if (0 == _saudio_fifo_read(&_saudio.fifo, (uint8_t*)_saudio.backend.src_buffer, src_buffer_byte_size)) {\n            /* not enough read data available, fill the entire buffer with silence */\n            _saudio_clear(_saudio.backend.src_buffer, (size_t)src_buffer_byte_size);\n        }\n    }\n}\n\n_SOKOL_PRIVATE void SLAPIENTRY _saudio_sles_play_cb(SLPlayItf player, void *context, SLuint32 event) {\n    _SOKOL_UNUSED(context);\n    _SOKOL_UNUSED(player);\n    if (event & SL_PLAYEVENT_HEADATEND) {\n        _saudio_sles_semaphore_post(&_saudio.backend.buffer_sem, 1);\n    }\n}\n\n_SOKOL_PRIVATE void* _saudio_sles_thread_fn(void* param) {\n    _SOKOL_UNUSED(param);\n    while (!_saudio.backend.thread_stop)  {\n        /* get next output buffer, advance, next buffer. */\n        int16_t* out_buffer = _saudio.backend.output_buffers[_saudio.backend.active_buffer];\n        _saudio.backend.active_buffer = (_saudio.backend.active_buffer + 1) % SAUDIO_SLES_NUM_BUFFERS;\n        int16_t* next_buffer = _saudio.backend.output_buffers[_saudio.backend.active_buffer];\n\n        /* queue this buffer */\n        const int buffer_size_bytes = _saudio.buffer_frames * _saudio.num_channels * (int)sizeof(short);\n        (*_saudio.backend.player_buffer_queue)->Enqueue(_saudio.backend.player_buffer_queue, out_buffer, (SLuint32)buffer_size_bytes);\n\n        /* fill the next buffer */\n        _saudio_sles_fill_buffer();\n        const int num_samples = _saudio.num_channels * _saudio.buffer_frames;\n        for (int i = 0; i < num_samples; ++i) {\n            next_buffer[i] = (int16_t) (_saudio.backend.src_buffer[i] * 0x7FFF);\n        }\n\n        _saudio_sles_semaphore_wait(&_saudio.backend.buffer_sem);\n    }\n\n    return 0;\n}\n\n_SOKOL_PRIVATE void _saudio_sles_backend_shutdown(void) {\n    _saudio.backend.thread_stop = 1;\n    pthread_join(_saudio.backend.thread, 0);\n\n    if (_saudio.backend.player_obj) {\n        (*_saudio.backend.player_obj)->Destroy(_saudio.backend.player_obj);\n    }\n\n    if (_saudio.backend.output_mix_obj) {\n        (*_saudio.backend.output_mix_obj)->Destroy(_saudio.backend.output_mix_obj);\n    }\n\n    if (_saudio.backend.engine_obj) {\n        (*_saudio.backend.engine_obj)->Destroy(_saudio.backend.engine_obj);\n    }\n\n    for (int i = 0; i < SAUDIO_SLES_NUM_BUFFERS; i++) {\n        _saudio_free(_saudio.backend.output_buffers[i]);\n    }\n    _saudio_free(_saudio.backend.src_buffer);\n}\n\n_SOKOL_PRIVATE bool _saudio_sles_backend_init(void) {\n    _SAUDIO_INFO(USING_SLES_BACKEND);\n\n    _saudio.bytes_per_frame = (int)sizeof(float) * _saudio.num_channels;\n\n    for (int i = 0; i < SAUDIO_SLES_NUM_BUFFERS; ++i) {\n        const int buffer_size_bytes = (int)sizeof(int16_t) * _saudio.num_channels * _saudio.buffer_frames;\n        _saudio.backend.output_buffers[i] = (int16_t*) _saudio_malloc_clear((size_t)buffer_size_bytes);\n    }\n\n    {\n        const int buffer_size_bytes = _saudio.bytes_per_frame * _saudio.buffer_frames;\n        _saudio.backend.src_buffer = (float*) _saudio_malloc_clear((size_t)buffer_size_bytes);\n    }\n\n    /* Create engine */\n    const SLEngineOption opts[] = { { SL_ENGINEOPTION_THREADSAFE, SL_BOOLEAN_TRUE } };\n    if (slCreateEngine(&_saudio.backend.engine_obj, 1, opts, 0, NULL, NULL ) != SL_RESULT_SUCCESS) {\n        _SAUDIO_ERROR(SLES_CREATE_ENGINE_FAILED);\n        _saudio_sles_backend_shutdown();\n        return false;\n    }\n\n    (*_saudio.backend.engine_obj)->Realize(_saudio.backend.engine_obj, SL_BOOLEAN_FALSE);\n    if ((*_saudio.backend.engine_obj)->GetInterface(_saudio.backend.engine_obj, SL_IID_ENGINE, &_saudio.backend.engine) != SL_RESULT_SUCCESS) {\n        _SAUDIO_ERROR(SLES_ENGINE_GET_ENGINE_INTERFACE_FAILED);\n        _saudio_sles_backend_shutdown();\n        return false;\n    }\n\n    /* Create output mix. */\n    {\n        const SLInterfaceID ids[] = { SL_IID_VOLUME };\n        const SLboolean req[] = { SL_BOOLEAN_FALSE };\n\n        if ((*_saudio.backend.engine)->CreateOutputMix(_saudio.backend.engine, &_saudio.backend.output_mix_obj, 1, ids, req) != SL_RESULT_SUCCESS) {\n            _SAUDIO_ERROR(SLES_CREATE_OUTPUT_MIX_FAILED);\n            _saudio_sles_backend_shutdown();\n            return false;\n        }\n        (*_saudio.backend.output_mix_obj)->Realize(_saudio.backend.output_mix_obj, SL_BOOLEAN_FALSE);\n\n        if ((*_saudio.backend.output_mix_obj)->GetInterface(_saudio.backend.output_mix_obj, SL_IID_VOLUME, &_saudio.backend.output_mix_vol) != SL_RESULT_SUCCESS) {\n            _SAUDIO_WARN(SLES_MIXER_GET_VOLUME_INTERFACE_FAILED);\n        }\n    }\n\n    /* android buffer queue */\n    _saudio.backend.in_locator.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;\n    _saudio.backend.in_locator.numBuffers = SAUDIO_SLES_NUM_BUFFERS;\n\n    /* data format */\n    SLDataFormat_PCM format;\n    format.formatType = SL_DATAFORMAT_PCM;\n    format.numChannels = (SLuint32)_saudio.num_channels;\n    format.samplesPerSec = (SLuint32) (_saudio.sample_rate * 1000);\n    format.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;\n    format.containerSize = 16;\n    format.endianness = SL_BYTEORDER_LITTLEENDIAN;\n\n    if (_saudio.num_channels == 2) {\n        format.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;\n    } else {\n        format.channelMask = SL_SPEAKER_FRONT_CENTER;\n    }\n\n    SLDataSource src;\n    src.pLocator = &_saudio.backend.in_locator;\n    src.pFormat = &format;\n\n    /* Output mix. */\n    _saudio.backend.out_locator.locatorType = SL_DATALOCATOR_OUTPUTMIX;\n    _saudio.backend.out_locator.outputMix = _saudio.backend.output_mix_obj;\n\n    _saudio.backend.dst_data_sink.pLocator = &_saudio.backend.out_locator;\n    _saudio.backend.dst_data_sink.pFormat = NULL;\n\n    /* setup player */\n    {\n        const SLInterfaceID ids[] = { SL_IID_VOLUME, SL_IID_ANDROIDSIMPLEBUFFERQUEUE };\n        const SLboolean req[] = { SL_BOOLEAN_FALSE, SL_BOOLEAN_TRUE };\n\n        if ((*_saudio.backend.engine)->CreateAudioPlayer(_saudio.backend.engine, &_saudio.backend.player_obj, &src, &_saudio.backend.dst_data_sink, sizeof(ids) / sizeof(ids[0]), ids, req) != SL_RESULT_SUCCESS)\n        {\n            _SAUDIO_ERROR(SLES_ENGINE_CREATE_AUDIO_PLAYER_FAILED);\n            _saudio_sles_backend_shutdown();\n            return false;\n        }\n        (*_saudio.backend.player_obj)->Realize(_saudio.backend.player_obj, SL_BOOLEAN_FALSE);\n\n        if ((*_saudio.backend.player_obj)->GetInterface(_saudio.backend.player_obj, SL_IID_PLAY, &_saudio.backend.player) != SL_RESULT_SUCCESS) {\n            _SAUDIO_ERROR(SLES_PLAYER_GET_PLAY_INTERFACE_FAILED);\n            _saudio_sles_backend_shutdown();\n            return false;\n        }\n        if ((*_saudio.backend.player_obj)->GetInterface(_saudio.backend.player_obj, SL_IID_VOLUME, &_saudio.backend.player_vol) != SL_RESULT_SUCCESS) {\n            _SAUDIO_ERROR(SLES_PLAYER_GET_VOLUME_INTERFACE_FAILED);\n        }\n        if ((*_saudio.backend.player_obj)->GetInterface(_saudio.backend.player_obj, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &_saudio.backend.player_buffer_queue) != SL_RESULT_SUCCESS) {\n            _SAUDIO_ERROR(SLES_PLAYER_GET_BUFFERQUEUE_INTERFACE_FAILED);\n            _saudio_sles_backend_shutdown();\n            return false;\n        }\n    }\n\n    /* begin */\n    {\n        const int buffer_size_bytes = (int)sizeof(int16_t) * _saudio.num_channels * _saudio.buffer_frames;\n        (*_saudio.backend.player_buffer_queue)->Enqueue(_saudio.backend.player_buffer_queue, _saudio.backend.output_buffers[0], (SLuint32)buffer_size_bytes);\n        _saudio.backend.active_buffer = (_saudio.backend.active_buffer + 1) % SAUDIO_SLES_NUM_BUFFERS;\n\n        (*_saudio.backend.player)->RegisterCallback(_saudio.backend.player, _saudio_sles_play_cb, NULL);\n        (*_saudio.backend.player)->SetCallbackEventsMask(_saudio.backend.player, SL_PLAYEVENT_HEADATEND);\n        (*_saudio.backend.player)->SetPlayState(_saudio.backend.player, SL_PLAYSTATE_PLAYING);\n    }\n\n    /* create the buffer-streaming start thread */\n    if (0 != pthread_create(&_saudio.backend.thread, 0, _saudio_sles_thread_fn, 0)) {\n        _saudio_sles_backend_shutdown();\n        return false;\n    }\n\n    return true;\n}\n\n//  ██████  ██████  ██████  ███████  █████  ██    ██ ██████  ██  ██████\n// ██      ██    ██ ██   ██ ██      ██   ██ ██    ██ ██   ██ ██ ██    ██\n// ██      ██    ██ ██████  █████   ███████ ██    ██ ██   ██ ██ ██    ██\n// ██      ██    ██ ██   ██ ██      ██   ██ ██    ██ ██   ██ ██ ██    ██\n//  ██████  ██████  ██   ██ ███████ ██   ██  ██████  ██████  ██  ██████\n//\n// >>coreaudio\n#elif defined(_SAUDIO_APPLE)\n\n#if defined(_SAUDIO_IOS)\n#if __has_feature(objc_arc)\n#define _SAUDIO_OBJC_RELEASE(obj) { obj = nil; }\n#else\n#define _SAUDIO_OBJC_RELEASE(obj) { [obj release]; obj = nil; }\n#endif\n\n@interface _saudio_interruption_handler : NSObject { }\n@end\n\n@implementation _saudio_interruption_handler\n-(id)init {\n    self = [super init];\n    AVAudioSession* session = [AVAudioSession sharedInstance];\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handle_interruption:) name:AVAudioSessionInterruptionNotification object:session];\n    return self;\n}\n\n-(void)dealloc {\n    [self remove_handler];\n    #if !__has_feature(objc_arc)\n    [super dealloc];\n    #endif\n}\n\n-(void)remove_handler {\n    [[NSNotificationCenter defaultCenter] removeObserver:self name:@\"AVAudioSessionInterruptionNotification\" object:nil];\n}\n\n-(void)handle_interruption:(NSNotification*)notification {\n    AVAudioSession* session = [AVAudioSession sharedInstance];\n    SOKOL_ASSERT(session);\n    NSDictionary* dict = notification.userInfo;\n    SOKOL_ASSERT(dict);\n    NSInteger type = [[dict valueForKey:AVAudioSessionInterruptionTypeKey] integerValue];\n    switch (type) {\n        case AVAudioSessionInterruptionTypeBegan:\n            if (_saudio.backend.ca_audio_queue) {\n                AudioQueuePause(_saudio.backend.ca_audio_queue);\n            }\n            [session setActive:false error:nil];\n            break;\n        case AVAudioSessionInterruptionTypeEnded:\n            [session setActive:true error:nil];\n            if (_saudio.backend.ca_audio_queue) {\n                AudioQueueStart(_saudio.backend.ca_audio_queue, NULL);\n            }\n            break;\n        default:\n            break;\n    }\n}\n@end\n#endif // _SAUDIO_IOS\n\n/* NOTE: the buffer data callback is called on a separate thread! */\n_SOKOL_PRIVATE void _saudio_coreaudio_callback(void* user_data, _saudio_AudioQueueRef queue, _saudio_AudioQueueBufferRef buffer) {\n    _SOKOL_UNUSED(user_data);\n    if (_saudio_has_callback()) {\n        const int num_frames = (int)buffer->mAudioDataByteSize / _saudio.bytes_per_frame;\n        const int num_channels = _saudio.num_channels;\n        _saudio_stream_callback((float*)buffer->mAudioData, num_frames, num_channels);\n    }\n    else {\n        uint8_t* ptr = (uint8_t*)buffer->mAudioData;\n        int num_bytes = (int) buffer->mAudioDataByteSize;\n        if (0 == _saudio_fifo_read(&_saudio.fifo, ptr, num_bytes)) {\n            /* not enough read data available, fill the entire buffer with silence */\n            _saudio_clear(ptr, (size_t)num_bytes);\n        }\n    }\n    AudioQueueEnqueueBuffer(queue, buffer, 0, NULL);\n}\n\n_SOKOL_PRIVATE void _saudio_coreaudio_backend_shutdown(void) {\n    if (_saudio.backend.ca_audio_queue) {\n        AudioQueueStop(_saudio.backend.ca_audio_queue, true);\n        AudioQueueDispose(_saudio.backend.ca_audio_queue, false);\n        _saudio.backend.ca_audio_queue = 0;\n    }\n    #if defined(_SAUDIO_IOS)\n        /* remove interruption handler */\n        if (_saudio.backend.ca_interruption_handler != nil) {\n            [_saudio.backend.ca_interruption_handler remove_handler];\n            _SAUDIO_OBJC_RELEASE(_saudio.backend.ca_interruption_handler);\n        }\n        /* deactivate audio session */\n        AVAudioSession* session = [AVAudioSession sharedInstance];\n        SOKOL_ASSERT(session);\n        [session setActive:false error:nil];;\n    #endif // _SAUDIO_IOS\n}\n\n_SOKOL_PRIVATE bool _saudio_coreaudio_backend_init(void) {\n    SOKOL_ASSERT(0 == _saudio.backend.ca_audio_queue);\n\n    #if defined(_SAUDIO_IOS)\n        /* activate audio session */\n        AVAudioSession* session = [AVAudioSession sharedInstance];\n        SOKOL_ASSERT(session != nil);\n        [session setCategory: AVAudioSessionCategoryPlayback error:nil];\n        [session setActive:true error:nil];\n\n        /* create interruption handler */\n        _saudio.backend.ca_interruption_handler = [[_saudio_interruption_handler alloc] init];\n    #endif\n\n    /* create an audio queue with fp32 samples */\n    _saudio_AudioStreamBasicDescription fmt;\n    _saudio_clear(&fmt, sizeof(fmt));\n    fmt.mSampleRate = (double) _saudio.sample_rate;\n    fmt.mFormatID = _saudio_kAudioFormatLinearPCM;\n    fmt.mFormatFlags = _saudio_kLinearPCMFormatFlagIsFloat | _saudio_kAudioFormatFlagIsPacked;\n    fmt.mFramesPerPacket = 1;\n    fmt.mChannelsPerFrame = (uint32_t) _saudio.num_channels;\n    fmt.mBytesPerFrame = (uint32_t)sizeof(float) * (uint32_t)_saudio.num_channels;\n    fmt.mBytesPerPacket = fmt.mBytesPerFrame;\n    fmt.mBitsPerChannel = 32;\n    _saudio_OSStatus res = AudioQueueNewOutput(&fmt, _saudio_coreaudio_callback, 0, NULL, NULL, 0, &_saudio.backend.ca_audio_queue);\n    if (0 != res) {\n        _SAUDIO_ERROR(COREAUDIO_NEW_OUTPUT_FAILED);\n        return false;\n    }\n    SOKOL_ASSERT(_saudio.backend.ca_audio_queue);\n\n    /* create 2 audio buffers */\n    for (int i = 0; i < 2; i++) {\n        _saudio_AudioQueueBufferRef buf = NULL;\n        const uint32_t buf_byte_size = (uint32_t)_saudio.buffer_frames * fmt.mBytesPerFrame;\n        res = AudioQueueAllocateBuffer(_saudio.backend.ca_audio_queue, buf_byte_size, &buf);\n        if (0 != res) {\n            _SAUDIO_ERROR(COREAUDIO_ALLOCATE_BUFFER_FAILED);\n            _saudio_coreaudio_backend_shutdown();\n            return false;\n        }\n        buf->mAudioDataByteSize = buf_byte_size;\n        _saudio_clear(buf->mAudioData, buf->mAudioDataByteSize);\n        AudioQueueEnqueueBuffer(_saudio.backend.ca_audio_queue, buf, 0, NULL);\n    }\n\n    /* init or modify actual playback parameters */\n    _saudio.bytes_per_frame = (int)fmt.mBytesPerFrame;\n\n    /* ...and start playback */\n    res = AudioQueueStart(_saudio.backend.ca_audio_queue, NULL);\n    if (0 != res) {\n        _SAUDIO_ERROR(COREAUDIO_START_FAILED);\n        _saudio_coreaudio_backend_shutdown();\n        return false;\n    }\n    return true;\n}\n\n#else\n#error \"unsupported platform\"\n#endif\n\nbool _saudio_backend_init(void) {\n    #if defined(SOKOL_DUMMY_BACKEND)\n        return _saudio_dummy_backend_init();\n    #elif defined(_SAUDIO_LINUX)\n        return _saudio_alsa_backend_init();\n    #elif defined(_SAUDIO_WINDOWS)\n        return _saudio_wasapi_backend_init();\n    #elif defined(_SAUDIO_EMSCRIPTEN)\n        return _saudio_webaudio_backend_init();\n    #elif defined(SAUDIO_ANDROID_AAUDIO)\n        return _saudio_aaudio_backend_init();\n    #elif defined(SAUDIO_ANDROID_SLES)\n        return _saudio_sles_backend_init();\n    #elif defined(_SAUDIO_APPLE)\n        return _saudio_coreaudio_backend_init();\n    #else\n    #error \"unknown platform\"\n    #endif\n}\n\nvoid _saudio_backend_shutdown(void) {\n    #if defined(SOKOL_DUMMY_BACKEND)\n        _saudio_dummy_backend_shutdown();\n    #elif defined(_SAUDIO_LINUX)\n        _saudio_alsa_backend_shutdown();\n    #elif defined(_SAUDIO_WINDOWS)\n        _saudio_wasapi_backend_shutdown();\n    #elif defined(_SAUDIO_EMSCRIPTEN)\n        _saudio_webaudio_backend_shutdown();\n    #elif defined(SAUDIO_ANDROID_AAUDIO)\n        _saudio_aaudio_backend_shutdown();\n    #elif defined(SAUDIO_ANDROID_SLES)\n        _saudio_sles_backend_shutdown();\n    #elif defined(_SAUDIO_APPLE)\n        return _saudio_coreaudio_backend_shutdown();\n    #else\n    #error \"unknown platform\"\n    #endif\n}\n\n// ██████  ██    ██ ██████  ██      ██  ██████\n// ██   ██ ██    ██ ██   ██ ██      ██ ██\n// ██████  ██    ██ ██████  ██      ██ ██\n// ██      ██    ██ ██   ██ ██      ██ ██\n// ██       ██████  ██████  ███████ ██  ██████\n//\n// >>public\nSOKOL_API_IMPL void saudio_setup(const saudio_desc* desc) {\n    SOKOL_ASSERT(!_saudio.valid);\n    SOKOL_ASSERT(!_saudio.setup_called);\n    SOKOL_ASSERT(desc);\n    SOKOL_ASSERT((desc->allocator.alloc_fn && desc->allocator.free_fn) || (!desc->allocator.alloc_fn && !desc->allocator.free_fn));\n    _saudio_clear(&_saudio, sizeof(_saudio));\n    _saudio.setup_called = true;\n    _saudio.desc = *desc;\n    _saudio.stream_cb = desc->stream_cb;\n    _saudio.stream_userdata_cb = desc->stream_userdata_cb;\n    _saudio.user_data = desc->user_data;\n    _saudio.sample_rate = _saudio_def(_saudio.desc.sample_rate, _SAUDIO_DEFAULT_SAMPLE_RATE);\n    _saudio.buffer_frames = _saudio_def(_saudio.desc.buffer_frames, _SAUDIO_DEFAULT_BUFFER_FRAMES);\n    _saudio.packet_frames = _saudio_def(_saudio.desc.packet_frames, _SAUDIO_DEFAULT_PACKET_FRAMES);\n    _saudio.num_packets = _saudio_def(_saudio.desc.num_packets, _SAUDIO_DEFAULT_NUM_PACKETS);\n    _saudio.num_channels = _saudio_def(_saudio.desc.num_channels, 1);\n    _saudio_fifo_init_mutex(&_saudio.fifo);\n    if (_saudio_backend_init()) {\n        /* the backend might not support the requested exact buffer size,\n           make sure the actual buffer size is still a multiple of\n           the requested packet size\n        */\n        if (0 != (_saudio.buffer_frames % _saudio.packet_frames)) {\n            _SAUDIO_ERROR(BACKEND_BUFFER_SIZE_ISNT_MULTIPLE_OF_PACKET_SIZE);\n            _saudio_backend_shutdown();\n            return;\n        }\n        SOKOL_ASSERT(_saudio.bytes_per_frame > 0);\n        _saudio_fifo_init(&_saudio.fifo, _saudio.packet_frames * _saudio.bytes_per_frame, _saudio.num_packets);\n        _saudio.valid = true;\n    }\n    else {\n        _saudio_fifo_destroy_mutex(&_saudio.fifo);\n    }\n}\n\nSOKOL_API_IMPL void saudio_shutdown(void) {\n    SOKOL_ASSERT(_saudio.setup_called);\n    _saudio.setup_called = false;\n    if (_saudio.valid) {\n        _saudio_backend_shutdown();\n        _saudio_fifo_shutdown(&_saudio.fifo);\n        _saudio_fifo_destroy_mutex(&_saudio.fifo);\n        _saudio.valid = false;\n    }\n}\n\nSOKOL_API_IMPL bool saudio_isvalid(void) {\n    return _saudio.valid;\n}\n\nSOKOL_API_IMPL void* saudio_userdata(void) {\n    SOKOL_ASSERT(_saudio.setup_called);\n    return _saudio.desc.user_data;\n}\n\nSOKOL_API_IMPL saudio_desc saudio_query_desc(void) {\n    SOKOL_ASSERT(_saudio.setup_called);\n    return _saudio.desc;\n}\n\nSOKOL_API_IMPL int saudio_sample_rate(void) {\n    SOKOL_ASSERT(_saudio.setup_called);\n    return _saudio.sample_rate;\n}\n\nSOKOL_API_IMPL int saudio_buffer_frames(void) {\n    SOKOL_ASSERT(_saudio.setup_called);\n    return _saudio.buffer_frames;\n}\n\nSOKOL_API_IMPL int saudio_channels(void) {\n    SOKOL_ASSERT(_saudio.setup_called);\n    return _saudio.num_channels;\n}\n\nSOKOL_API_IMPL bool saudio_suspended(void) {\n    SOKOL_ASSERT(_saudio.setup_called);\n    #if defined(_SAUDIO_EMSCRIPTEN)\n        if (_saudio.valid) {\n            return 1 == saudio_js_suspended();\n        }\n        else {\n            return false;\n        }\n    #else\n        return false;\n    #endif\n}\n\nSOKOL_API_IMPL int saudio_expect(void) {\n    SOKOL_ASSERT(_saudio.setup_called);\n    if (_saudio.valid) {\n        const int num_frames = _saudio_fifo_writable_bytes(&_saudio.fifo) / _saudio.bytes_per_frame;\n        return num_frames;\n    }\n    else {\n        return 0;\n    }\n}\n\nSOKOL_API_IMPL int saudio_push(const float* frames, int num_frames) {\n    SOKOL_ASSERT(_saudio.setup_called);\n    SOKOL_ASSERT(frames && (num_frames > 0));\n    if (_saudio.valid) {\n        const int num_bytes = num_frames * _saudio.bytes_per_frame;\n        const int num_written = _saudio_fifo_write(&_saudio.fifo, (const uint8_t*)frames, num_bytes);\n        return num_written / _saudio.bytes_per_frame;\n    }\n    else {\n        return 0;\n    }\n}\n\n#undef _saudio_def\n#undef _saudio_def_flt\n\n#if defined(_SAUDIO_WINDOWS)\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n#endif\n\n#endif /* SOKOL_AUDIO_IMPL */\n"
  },
  {
    "path": "thirdparty/sokol/sokol_gfx.h",
    "content": "#if defined(SOKOL_IMPL) && !defined(SOKOL_GFX_IMPL)\n#define SOKOL_GFX_IMPL\n#endif\n#ifndef SOKOL_GFX_INCLUDED\n/*\n    sokol_gfx.h -- simple 3D API wrapper\n\n    Project URL: https://github.com/floooh/sokol\n\n    Example code: https://github.com/floooh/sokol-samples\n\n    Do this:\n        #define SOKOL_IMPL or\n        #define SOKOL_GFX_IMPL\n    before you include this file in *one* C or C++ file to create the\n    implementation.\n\n    In the same place define one of the following to select the rendering\n    backend:\n        #define SOKOL_GLCORE\n        #define SOKOL_GLES3\n        #define SOKOL_D3D11\n        #define SOKOL_METAL\n        #define SOKOL_WGPU\n        #define SOKOL_DUMMY_BACKEND\n\n    I.e. for the desktop GL it should look like this:\n\n    #include ...\n    #include ...\n    #define SOKOL_IMPL\n    #define SOKOL_GLCORE\n    #include \"sokol_gfx.h\"\n\n    The dummy backend replaces the platform-specific backend code with empty\n    stub functions. This is useful for writing tests that need to run on the\n    command line.\n\n    Optionally provide the following defines with your own implementations:\n\n    SOKOL_ASSERT(c)             - your own assert macro (default: assert(c))\n    SOKOL_UNREACHABLE()         - a guard macro for unreachable code (default: assert(false))\n    SOKOL_GFX_API_DECL          - public function declaration prefix (default: extern)\n    SOKOL_API_DECL              - same as SOKOL_GFX_API_DECL\n    SOKOL_API_IMPL              - public function implementation prefix (default: -)\n    SOKOL_TRACE_HOOKS           - enable trace hook callbacks (search below for TRACE HOOKS)\n    SOKOL_EXTERNAL_GL_LOADER    - indicates that you're using your own GL loader, in this case\n                                  sokol_gfx.h will not include any platform GL headers and disable\n                                  the integrated Win32 GL loader\n\n    If sokol_gfx.h is compiled as a DLL, define the following before\n    including the declaration or implementation:\n\n    SOKOL_DLL\n\n    On Windows, SOKOL_DLL will define SOKOL_GFX_API_DECL as __declspec(dllexport)\n    or __declspec(dllimport) as needed.\n\n    If you want to compile without deprecated structs and functions,\n    define:\n\n    SOKOL_NO_DEPRECATED\n\n    Optionally define the following to force debug checks and validations\n    even in release mode:\n\n    SOKOL_DEBUG         - by default this is defined if _DEBUG is defined\n\n    sokol_gfx DOES NOT:\n    ===================\n    - create a window, swapchain or the 3D-API context/device, you must do this\n      before sokol_gfx is initialized, and pass any required information\n      (like 3D device pointers) to the sokol_gfx initialization call\n\n    - present the rendered frame, how this is done exactly usually depends\n      on how the window and 3D-API context/device was created\n\n    - provide a unified shader language, instead 3D-API-specific shader\n      source-code or shader-bytecode must be provided (for the \"official\"\n      offline shader cross-compiler, see here:\n      https://github.com/floooh/sokol-tools/blob/master/docs/sokol-shdc.md)\n\n\n    STEP BY STEP\n    ============\n    --- to initialize sokol_gfx, after creating a window and a 3D-API\n        context/device, call:\n\n            sg_setup(const sg_desc*)\n\n        Depending on the selected 3D backend, sokol-gfx requires some\n        information, like a device pointer, default swapchain pixel formats\n        and so on. If you are using sokol_app.h for the window system\n        glue, you can use a helper function provided in the sokol_glue.h\n        header:\n\n            #include \"sokol_gfx.h\"\n            #include \"sokol_app.h\"\n            #include \"sokol_glue.h\"\n            //...\n            sg_setup(&(sg_desc){\n                .environment = sglue_environment(),\n            });\n\n        To get any logging output for errors and from the validation layer, you\n        need to provide a logging callback. Easiest way is through sokol_log.h:\n\n            #include \"sokol_log.h\"\n            //...\n            sg_setup(&(sg_desc){\n                //...\n                .logger.func = slog_func,\n            });\n\n    --- create resource objects (at least buffers, shaders and pipelines,\n        and optionally images, samplers and render-pass-attachments):\n\n            sg_buffer sg_make_buffer(const sg_buffer_desc*)\n            sg_image sg_make_image(const sg_image_desc*)\n            sg_sampler sg_make_sampler(const sg_sampler_desc*)\n            sg_shader sg_make_shader(const sg_shader_desc*)\n            sg_pipeline sg_make_pipeline(const sg_pipeline_desc*)\n            sg_attachments sg_make_attachments(const sg_attachments_desc*)\n\n    --- start a render pass:\n\n            sg_begin_pass(const sg_pass* pass);\n\n        Typically, passes render into an externally provided swapchain which\n        presents the rendering result on the display. Such a 'swapchain pass'\n        is started like this:\n\n            sg_begin_pass(&(sg_pass){ .action = { ... }, .swapchain = sglue_swapchain() })\n\n        ...where .action is an sg_pass_action struct containing actions to be performed\n        at the start and end of a render pass (such as clearing the render surfaces to\n        a specific color), and .swapchain is an sg_swapchain\n        struct all the required information to render into the swapchain's surfaces.\n\n        To start an 'offscreen pass' into sokol-gfx image objects, an sg_attachment\n        object handle is required instead of an sg_swapchain struct. An offscreen\n        pass is started like this (assuming attachments is an sg_attachments handle):\n\n            sg_begin_pass(&(sg_pass){ .action = { ... }, .attachments = attachments });\n\n    --- set the render pipeline state for the next draw call with:\n\n            sg_apply_pipeline(sg_pipeline pip)\n\n    --- fill an sg_bindings struct with the resource bindings for the next\n        draw call (0..N vertex buffers, 0 or 1 index buffer, 0..N image-objects,\n        samplers and storage-buffers), and call:\n\n            sg_apply_bindings(const sg_bindings* bindings)\n\n        to update the resource bindings\n\n    --- optionally update shader uniform data with:\n\n            sg_apply_uniforms(sg_shader_stage stage, int ub_index, const sg_range* data)\n\n        Read the section 'UNIFORM DATA LAYOUT' to learn about the expected memory layout\n        of the uniform data passed into sg_apply_uniforms().\n\n    --- kick off a draw call with:\n\n            sg_draw(int base_element, int num_elements, int num_instances)\n\n        The sg_draw() function unifies all the different ways to render primitives\n        in a single call (indexed vs non-indexed rendering, and instanced vs non-instanced\n        rendering). In case of indexed rendering, base_element and num_element specify\n        indices in the currently bound index buffer. In case of non-indexed rendering\n        base_element and num_elements specify vertices in the currently bound\n        vertex-buffer(s). To perform instanced rendering, the rendering pipeline\n        must be setup for instancing (see sg_pipeline_desc below), a separate vertex buffer\n        containing per-instance data must be bound, and the num_instances parameter\n        must be > 1.\n\n    --- finish the current rendering pass with:\n\n            sg_end_pass()\n\n    --- when done with the current frame, call\n\n            sg_commit()\n\n    --- at the end of your program, shutdown sokol_gfx with:\n\n            sg_shutdown()\n\n    --- if you need to destroy resources before sg_shutdown(), call:\n\n            sg_destroy_buffer(sg_buffer buf)\n            sg_destroy_image(sg_image img)\n            sg_destroy_sampler(sg_sampler smp)\n            sg_destroy_shader(sg_shader shd)\n            sg_destroy_pipeline(sg_pipeline pip)\n            sg_destroy_attachments(sg_attachments atts)\n\n    --- to set a new viewport rectangle, call\n\n            sg_apply_viewport(int x, int y, int width, int height, bool origin_top_left)\n\n        ...or if you want to specify the viewport rectangle with float values:\n\n            sg_apply_viewportf(float x, float y, float width, float height, bool origin_top_left)\n\n    --- to set a new scissor rect, call:\n\n            sg_apply_scissor_rect(int x, int y, int width, int height, bool origin_top_left)\n\n        ...or with float values:\n\n            sg_apply_scissor_rectf(float x, float y, float width, float height, bool origin_top_left)\n\n        Both sg_apply_viewport() and sg_apply_scissor_rect() must be called\n        inside a rendering pass\n\n        Note that sg_begin_default_pass() and sg_begin_pass() will reset both the\n        viewport and scissor rectangles to cover the entire framebuffer.\n\n    --- to update (overwrite) the content of buffer and image resources, call:\n\n            sg_update_buffer(sg_buffer buf, const sg_range* data)\n            sg_update_image(sg_image img, const sg_image_data* data)\n\n        Buffers and images to be updated must have been created with\n        SG_USAGE_DYNAMIC or SG_USAGE_STREAM\n\n        Only one update per frame is allowed for buffer and image resources when\n        using the sg_update_*() functions. The rationale is to have a simple\n        countermeasure to avoid the CPU scribbling over data the GPU is currently\n        using, or the CPU having to wait for the GPU\n\n        Buffer and image updates can be partial, as long as a rendering\n        operation only references the valid (updated) data in the\n        buffer or image.\n\n    --- to append a chunk of data to a buffer resource, call:\n\n            int sg_append_buffer(sg_buffer buf, const sg_range* data)\n\n        The difference to sg_update_buffer() is that sg_append_buffer()\n        can be called multiple times per frame to append new data to the\n        buffer piece by piece, optionally interleaved with draw calls referencing\n        the previously written data.\n\n        sg_append_buffer() returns a byte offset to the start of the\n        written data, this offset can be assigned to\n        sg_bindings.vertex_buffer_offsets[n] or\n        sg_bindings.index_buffer_offset\n\n        Code example:\n\n        for (...) {\n            const void* data = ...;\n            const int num_bytes = ...;\n            int offset = sg_append_buffer(buf, &(sg_range) { .ptr=data, .size=num_bytes });\n            bindings.vertex_buffer_offsets[0] = offset;\n            sg_apply_pipeline(pip);\n            sg_apply_bindings(&bindings);\n            sg_apply_uniforms(...);\n            sg_draw(...);\n        }\n\n        A buffer to be used with sg_append_buffer() must have been created\n        with SG_USAGE_DYNAMIC or SG_USAGE_STREAM.\n\n        If the application appends more data to the buffer then fits into\n        the buffer, the buffer will go into the \"overflow\" state for the\n        rest of the frame.\n\n        Any draw calls attempting to render an overflown buffer will be\n        silently dropped (in debug mode this will also result in a\n        validation error).\n\n        You can also check manually if a buffer is in overflow-state by calling\n\n            bool sg_query_buffer_overflow(sg_buffer buf)\n\n        You can manually check to see if an overflow would occur before adding\n        any data to a buffer by calling\n\n            bool sg_query_buffer_will_overflow(sg_buffer buf, size_t size)\n\n        NOTE: Due to restrictions in underlying 3D-APIs, appended chunks of\n        data will be 4-byte aligned in the destination buffer. This means\n        that there will be gaps in index buffers containing 16-bit indices\n        when the number of indices in a call to sg_append_buffer() is\n        odd. This isn't a problem when each call to sg_append_buffer()\n        is associated with one draw call, but will be problematic when\n        a single indexed draw call spans several appended chunks of indices.\n\n    --- to check at runtime for optional features, limits and pixelformat support,\n        call:\n\n            sg_features sg_query_features()\n            sg_limits sg_query_limits()\n            sg_pixelformat_info sg_query_pixelformat(sg_pixel_format fmt)\n\n    --- if you need to call into the underlying 3D-API directly, you must call:\n\n            sg_reset_state_cache()\n\n        ...before calling sokol_gfx functions again\n\n    --- you can inspect the original sg_desc structure handed to sg_setup()\n        by calling sg_query_desc(). This will return an sg_desc struct with\n        the default values patched in instead of any zero-initialized values\n\n    --- you can get a desc struct matching the creation attributes of a\n        specific resource object via:\n\n            sg_buffer_desc sg_query_buffer_desc(sg_buffer buf)\n            sg_image_desc sg_query_image_desc(sg_image img)\n            sg_sampler_desc sg_query_sampler_desc(sg_sampler smp)\n            sg_shader_desc sq_query_shader_desc(sg_shader shd)\n            sg_pipeline_desc sg_query_pipeline_desc(sg_pipeline pip)\n            sg_attachments_desc sg_query_attachments_desc(sg_attachments atts)\n\n        ...but NOTE that the returned desc structs may be incomplete, only\n        creation attributes that are kept around internally after resource\n        creation will be filled in, and in some cases (like shaders) that's\n        very little. Any missing attributes will be set to zero. The returned\n        desc structs might still be useful as partial blueprint for creating\n        similar resources if filled up with the missing attributes.\n\n        Calling the query-desc functions on an invalid resource will return\n        completely zeroed structs (it makes sense to check  the resource state\n        with sg_query_*_state() first)\n\n    --- you can query the default resource creation parameters through the functions\n\n            sg_buffer_desc sg_query_buffer_defaults(const sg_buffer_desc* desc)\n            sg_image_desc sg_query_image_defaults(const sg_image_desc* desc)\n            sg_sampler_desc sg_query_sampler_defaults(const sg_sampler_desc* desc)\n            sg_shader_desc sg_query_shader_defaults(const sg_shader_desc* desc)\n            sg_pipeline_desc sg_query_pipeline_defaults(const sg_pipeline_desc* desc)\n            sg_attachments_desc sg_query_attachments_defaults(const sg_attachments_desc* desc)\n\n        These functions take a pointer to a desc structure which may contain\n        zero-initialized items for default values. These zero-init values\n        will be replaced with their concrete values in the returned desc\n        struct.\n\n    --- you can inspect various internal resource runtime values via:\n\n            sg_buffer_info sg_query_buffer_info(sg_buffer buf)\n            sg_image_info sg_query_image_info(sg_image img)\n            sg_sampler_info sg_query_sampler_info(sg_sampler smp)\n            sg_shader_info sg_query_shader_info(sg_shader shd)\n            sg_pipeline_info sg_query_pipeline_info(sg_pipeline pip)\n            sg_attachments_info sg_query_attachments_info(sg_attachments atts)\n\n        ...please note that the returned info-structs are tied quite closely\n        to sokol_gfx.h internals, and may change more often than other\n        public API functions and structs.\n\n    --- you can query frame stats and control stats collection via:\n\n            sg_query_frame_stats()\n            sg_enable_frame_stats()\n            sg_disable_frame_stats()\n            sg_frame_stats_enabled()\n\n    --- you can ask at runtime what backend sokol_gfx.h has been compiled for:\n\n            sg_backend sg_query_backend(void)\n\n    --- call the following helper functions to compute the number of\n        bytes in a texture row or surface for a specific pixel format.\n        These functions might be helpful when preparing image data for consumption\n        by sg_make_image() or sg_update_image():\n\n            int sg_query_row_pitch(sg_pixel_format fmt, int width, int int row_align_bytes);\n            int sg_query_surface_pitch(sg_pixel_format fmt, int width, int height, int row_align_bytes);\n\n        Width and height are generally in number pixels, but note that 'row' has different meaning\n        for uncompressed vs compressed pixel formats: for uncompressed formats, a row is identical\n        with a single line if pixels, while in compressed formats, one row is a line of *compression blocks*.\n\n        This is why calling sg_query_surface_pitch() for a compressed pixel format and height\n        N, N+1, N+2, ... may return the same result.\n\n        The row_align_bytes parammeter is for added flexibility. For image data that goes into\n        the sg_make_image() or sg_update_image() this should generally be 1, because these\n        functions take tightly packed image data as input no matter what alignment restrictions\n        exist in the backend 3D APIs.\n\n    ON INITIALIZATION:\n    ==================\n    When calling sg_setup(), a pointer to an sg_desc struct must be provided\n    which contains initialization options. These options provide two types\n    of information to sokol-gfx:\n\n        (1) upper bounds and limits needed to allocate various internal\n            data structures:\n                - the max number of resources of each type that can\n                  be alive at the same time, this is used for allocating\n                  internal pools\n                - the max overall size of uniform data that can be\n                  updated per frame, including a worst-case alignment\n                  per uniform update (this worst-case alignment is 256 bytes)\n                - the max size of all dynamic resource updates (sg_update_buffer,\n                  sg_append_buffer and sg_update_image) per frame\n            Not all of those limit values are used by all backends, but it is\n            good practice to provide them none-the-less.\n\n        (2) 3D backend \"environment information\" in a nested sg_environment struct:\n            - pointers to backend-specific context- or device-objects (for instance\n              the D3D11, WebGPU or Metal device objects)\n            - defaults for external swapchain pixel formats and sample counts,\n              these will be used as default values in image and pipeline objects,\n              and the sg_swapchain struct passed into sg_begin_pass()\n            Usually you provide a complete sg_environment struct through\n            a helper function, as an example look at the sglue_environment()\n            function in the sokol_glue.h header.\n\n    See the documentation block of the sg_desc struct below for more information.\n\n\n    ON RENDER PASSES\n    ================\n    Relevant samples:\n        - https://floooh.github.io/sokol-html5/offscreen-sapp.html\n        - https://floooh.github.io/sokol-html5/offscreen-msaa-sapp.html\n        - https://floooh.github.io/sokol-html5/mrt-sapp.html\n        - https://floooh.github.io/sokol-html5/mrt-pixelformats-sapp.html\n\n    A render pass groups rendering commands into a set of render target images\n    (called 'pass attachments'). Render target images can be used in subsequent\n    passes as textures (it is invalid to use the same image both as render target\n    and as texture in the same pass).\n\n    The following sokol-gfx functions must only be called inside a render pass:\n\n        sg_apply_viewport(f)\n        sg_apply_scissor_rect(f)\n        sg_apply_pipeline\n        sg_apply_bindings\n        sg_apply_uniforms\n        sg_draw\n\n    A frame must have at least one 'swapchain render pass' which renders into an\n    externally provided swapchain provided as an sg_swapchain struct to the\n    sg_begin_pass() function. The sg_swapchain struct must contain the\n    following information:\n\n        - the color pixel-format of the swapchain's render surface\n        - an optional depth/stencil pixel format if the swapchain\n          has a depth/stencil buffer\n        - an optional sample-count for MSAA rendering\n        - NOTE: the above three values can be zero-initialized, in that\n          case the defaults from the sg_environment struct will be used that\n          had been passed to the sg_setup() function.\n        - a number of backend specific objects:\n            - GL/GLES3: just a GL framebuffer handle\n            - D3D11:\n                - an ID3D11RenderTargetView for the rendering surface\n                - if MSAA is used, an ID3D11RenderTargetView as\n                  MSAA resolve-target\n                - an optional ID3D11DepthStencilView for the\n                  depth/stencil buffer\n            - WebGPU\n                - a WGPUTextureView object for the rendering surface\n                - if MSAA is used, a WGPUTextureView object as MSAA resolve target\n                - an optional WGPUTextureView for the\n            - Metal (NOTE that the roles of provided surfaces is slightly\n              different in Metal than in D3D11 or WebGPU, notably, the\n              CAMetalDrawable is either rendered to directly, or serves\n              as MSAA resolve target):\n                - a CAMetalDrawable object which is either rendered\n                  into directly, or in case of MSAA rendering, serves\n                  as MSAA-resolve-target\n                - if MSAA is used, an multisampled MTLTexture where\n                  rendering goes into\n                - an optional MTLTexture for the depth/stencil buffer\n\n    It's recommended that you create a helper function which returns an\n    initialized sg_swapchain struct by value. This can then be directly plugged\n    into the sg_begin_pass function like this:\n\n        sg_begin_pass(&(sg_pass){ .swapchain = sglue_swapchain() });\n\n    As an example for such a helper function check out the function sglue_swapchain()\n    in the sokol_glue.h header.\n\n    For offscreen render passes, the render target images used in a render pass\n    are baked into an immutable sg_attachments object.\n\n    For a simple offscreen scenario with one color-, one depth-stencil-render\n    target and without multisampling, creating an attachment object looks like this:\n\n    First create two render target images, one with a color pixel format,\n    and one with the depth- or depth-stencil pixel format. Both images\n    must have the same dimensions:\n\n        const sg_image color_img = sg_make_image(&(sg_image_desc){\n            .render_target = true,\n            .width = 256,\n            .height = 256,\n            .pixel_format = SG_PIXELFORMAT_RGBA8,\n            .sample_count = 1,\n        });\n        const sg_image depth_img = sg_make_image(&(sg_image_desc){\n            .render_target = true,\n            .width = 256,\n            .height = 256,\n            .pixel_format = SG_PIXELFORMAT_DEPTH,\n            .sample_count = 1,\n        });\n\n    NOTE: when creating render target images, have in mind that some default values\n    are aligned with the default environment attributes in the sg_environment struct\n    that was passed into the sg_setup() call:\n\n        - the default value for sg_image_desc.pixel_format is taken from\n          sg_environment.defaults.color_format\n        - the default value for sg_image_desc.sample_count is taken from\n          sg_environment.defaults.sample_count\n        - the default value for sg_image_desc.num_mipmaps is always 1\n\n    Next create an attachments object:\n\n        const sg_attachments atts = sg_make_attachments(&(sg_attachments_desc){\n            .colors[0].image = color_img,\n            .depth_stencil.image = depth_img,\n        });\n\n    This attachments object is then passed into the sg_begin_pass() function\n    in place of the swapchain struct:\n\n        sg_begin_pass(&(sg_pass){ .attachments = atts });\n\n    Swapchain and offscreen passes form dependency trees each with a swapchain\n    pass at the root, offscreen passes as nodes, and render target images as\n    dependencies between passes.\n\n    sg_pass_action structs are used to define actions that should happen at the\n    start and end of rendering passes (such as clearing pass attachments to a\n    specific color or depth-value, or performing an MSAA resolve operation at\n    the end of a pass).\n\n    A typical sg_pass_action object which clears the color attachment to black\n    might look like this:\n\n        const sg_pass_action = {\n            .colors[0] = {\n                .load_action = SG_LOADACTION_CLEAR,\n                .clear_value = { 0.0f, 0.0f, 0.0f, 1.0f }\n            }\n        };\n\n    This omits the defaults for the color attachment store action, and\n    the depth-stencil-attachments actions. The same pass action with the\n    defaults explicitly filled in would look like this:\n\n        const sg_pass_action pass_action = {\n            .colors[0] = {\n                .load_action = SG_LOADACTION_CLEAR,\n                .store_action = SG_STOREACTION_STORE,\n                .clear_value = { 0.0f, 0.0f, 0.0f, 1.0f }\n            },\n            .depth = = {\n                .load_action = SG_LOADACTION_CLEAR,\n                .store_action = SG_STOREACTION_DONTCARE,\n                .clear_value = 1.0f,\n            },\n            .stencil = {\n                .load_action = SG_LOADACTION_CLEAR,\n                .store_action = SG_STOREACTION_DONTCARE,\n                .clear_value = 0\n            }\n        };\n\n    With the sg_pass object and sg_pass_action struct in place everything\n    is ready now for the actual render pass:\n\n    Using such this prepared sg_pass_action in a swapchain pass looks like\n    this:\n\n        sg_begin_pass(&(sg_pass){\n            .action = pass_action,\n            .swapchain = sglue_swapchain()\n        });\n        ...\n        sg_end_pass();\n\n    ...of alternatively in one offscreen pass:\n\n        sg_begin_pass(&(sg_pass){\n            .action = pass_action,\n            .attachments = attachments,\n        });\n        ...\n        sg_end_pass();\n\n    Offscreen rendering can also go into a mipmap, or a slice/face of\n    a cube-, array- or 3d-image (which some restrictions, for instance\n    it's not possible to create a 3D image with a depth/stencil pixel format,\n    these exceptions are generally caught by the sokol-gfx validation layer).\n\n    The mipmap/slice selection happens at attachments creation time, for instance\n    to render into mipmap 2 of slice 3 of an array texture:\n\n        const sg_attachments atts = sg_make_attachments(&(sg_attachments_desc){\n            .colors[0] = {\n                .image = color_img,\n                .mip_level = 2,\n                .slice = 3,\n            },\n            .depth_stencil.image = depth_img,\n        });\n\n    If MSAA offscreen rendering is desired, the multi-sample rendering result\n    must be 'resolved' into a separate 'resolve image', before that image can\n    be used as texture.\n\n    NOTE: currently multisample-images cannot be bound as textures.\n\n    Creating a simple attachments object for multisampled rendering requires\n    3 attachment images: the color attachment image which has a sample\n    count > 1, a resolve attachment image of the same size and pixel format\n    but a sample count == 1, and a depth/stencil attachment image with\n    the same size and sample count as the color attachment image:\n\n        const sg_image color_img = sg_make_image(&(sg_image_desc){\n            .render_target = true,\n            .width = 256,\n            .height = 256,\n            .pixel_format = SG_PIXELFORMAT_RGBA8,\n            .sample_count = 4,\n        });\n        const sg_image resolve_img = sg_make_image(&(sg_image_desc){\n            .render_target = true,\n            .width = 256,\n            .height = 256,\n            .pixel_format = SG_PIXELFORMAT_RGBA8,\n            .sample_count = 1,\n        });\n        const sg_image depth_img = sg_make_image(&(sg_image_desc){\n            .render_target = true,\n            .width = 256,\n            .height = 256,\n            .pixel_format = SG_PIXELFORMAT_DEPTH,\n            .sample_count = 4,\n        });\n\n    ...create the attachments object:\n\n        const sg_attachments atts = sg_make_attachments(&(sg_attachments_desc){\n            .colors[0].image = color_img,\n            .resolves[0].image = resolve_img,\n            .depth_stencil.image = depth_img,\n        });\n\n    If an attachments object defines a resolve image in a specific resolve attachment slot,\n    an 'msaa resolve operation' will happen in sg_end_pass().\n\n    In this scenario, the content of the MSAA color attachment doesn't need to be\n    preserved (since it's only needed inside sg_end_pass for the msaa-resolve), so\n    the .store_action should be set to \"don't care\":\n\n        const sg_pass_action = {\n            .colors[0] = {\n                .load_action = SG_LOADACTION_CLEAR,\n                .store_action = SG_STOREACTION_DONTCARE,\n                .clear_value = { 0.0f, 0.0f, 0.0f, 1.0f }\n            }\n        };\n\n    The actual render pass looks as usual:\n\n        sg_begin_pass(&(sg_pass){ .action = pass_action, .attachments = atts });\n        ...\n        sg_end_pass();\n\n    ...after sg_end_pass() the only difference to the non-msaa scenario is that the\n    rendering result which is going to be used as texture in a followup pass is\n    in 'resolve_img', not in 'color_img' (in fact, trying to bind color_img as a\n    texture would result in a validation error).\n\n\n    ON SHADER CREATION\n    ==================\n    sokol-gfx doesn't come with an integrated shader cross-compiler, instead\n    backend-specific shader sources or binary blobs need to be provided when\n    creating a shader object, along with information about the shader resource\n    binding interface needed in the sokol-gfx validation layer and to properly\n    bind shader resources on the CPU-side to be consumable by the GPU-side.\n\n    The easiest way to provide all this shader creation data is to use the\n    sokol-shdc shader compiler tool to compile shaders from a common\n    GLSL syntax into backend-specific sources or binary blobs, along with\n    shader interface information and uniform blocks mapped to C structs.\n\n    To create a shader using a C header which has been code-generated by sokol-shdc:\n\n        // include the C header code-generated by sokol-shdc:\n        #include \"myshader.glsl.h\"\n        ...\n\n        // create shader using a code-generated helper function from the C header:\n        sg_shader shd = sg_make_shader(myshader_shader_desc(sg_query_backend()));\n\n    The samples in the 'sapp' subdirectory of the sokol-samples project\n    also use the sokol-shdc approach:\n\n        https://github.com/floooh/sokol-samples/tree/master/sapp\n\n    If you're planning to use sokol-shdc, you can stop reading here, instead\n    continue with the sokol-shdc documentation:\n\n        https://github.com/floooh/sokol-tools/blob/master/docs/sokol-shdc.md\n\n    To create shaders with backend-specific shader code or binary blobs,\n    the sg_make_shader() function requires the following information:\n\n    - Shader code or shader binary blobs for the vertex- and fragment- shader-stage:\n        - for the desktop GL backend, source code can be provided in '#version 410' or\n          '#version 430', version 430 is required for storage buffer support, but note\n          that this is not available on macOS\n        - for the GLES3 backend, source code must be provided in '#version 300 es' syntax\n        - for the D3D11 backend, shaders can be provided as source or binary blobs, the\n          source code should be in HLSL4.0 (for best compatibility) or alternatively\n          in HLSL5.0 syntax (other versions may work but are not tested), NOTE: when\n          shader source code is provided for the D3D11 backend, sokol-gfx will dynamically\n          load 'd3dcompiler_47.dll'\n        - for the Metal backends, shaders can be provided as source or binary blobs, the\n          MSL version should be in 'metal-1.1' (other versions may work but are not tested)\n        - for the WebGPU backend, shader must be provided as WGSL source code\n        - optionally the following shader-code related attributes can be provided:\n            - an entry function name (only on D3D11 or Metal, but not OpenGL)\n            - on D3D11 only, a compilation target (default is \"vs_4_0\" and \"ps_4_0\")\n\n    - Depending on backend, information about the input vertex attributes used by the\n      vertex shader:\n        - Metal: no information needed since vertex attributes are always bound\n          by their attribute location defined in the shader via '[[attribute(N)]]'\n        - WebGPU: no information needed since vertex attributes are always\n          bound by their attribute location defined in the shader via `@location(N)`\n        - GLSL: vertex attribute names can be optionally provided, in that case their\n          location will be looked up by name, otherwise, the vertex attribute location\n          can be defined with 'layout(location = N)', PLEASE NOTE that the name-lookup method\n          may be removed at some point\n        - D3D11: a 'semantic name' and 'semantic index' must be provided for each vertex\n          attribute, e.g. if the vertex attribute is defined as 'TEXCOORD1' in the shader,\n          the semantic name would be 'TEXCOORD', and the semantic index would be '1'\n\n    - Information about each uniform block used in the shader:\n        - The size of the uniform block in number of bytes.\n        - A memory layout hint (currently 'native' or 'std140') where 'native' defines a\n          backend-specific memory layout which shouldn't be used for cross-platform code.\n          Only std140 guarantees a backend-agnostic memory layout.\n        - For GLSL only: a description of the internal uniform block layout, which maps\n          member types and their offsets on the CPU side to uniform variable names\n          in the GLSL shader\n        - please also NOTE the documentation sections about UNIFORM DATA LAYOUT\n          and CROSS-BACKEND COMMON UNIFORM DATA LAYOUT below!\n\n    - A description of each storage buffer used in the shader:\n        - a boolean 'readonly' flag, note that currently only\n          readonly storage buffers are supported\n        - note that storage buffers are not supported on all backends\n          and platforms\n\n    - A description of each texture/image used in the shader:\n        - the expected image type:\n            - SG_IMAGETYPE_2D\n            - SG_IMAGETYPE_CUBE\n            - SG_IMAGETYPE_3D\n            - SG_IMAGETYPE_ARRAY\n        - the expected 'image sample type':\n            - SG_IMAGESAMPLETYPE_FLOAT\n            - SG_IMAGESAMPLETYPE_DEPTH\n            - SG_IMAGESAMPLETYPE_SINT\n            - SG_IMAGESAMPLETYPE_UINT\n            - SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT\n        - a flag whether the texture is expected to be multisampled\n          (currently it's not supported to fetch data from multisampled\n          textures in shaders, but this is planned for a later time)\n\n    - A description of each texture sampler used in the shader:\n        - SG_SAMPLERTYPE_FILTERING,\n        - SG_SAMPLERTYPE_NONFILTERING,\n        - SG_SAMPLERTYPE_COMPARISON,\n\n    - An array of 'image-sampler-pairs' used by the shader to sample textures,\n      for D3D11, Metal and WebGPU this is used for validation purposes to check\n      whether the texture and sampler are compatible with each other (especially\n      WebGPU is very picky about combining the correct\n      texture-sample-type with the correct sampler-type). For GLSL an\n      additional 'combined-image-sampler name' must be provided because 'OpenGL\n      style GLSL' cannot handle separate texture and sampler objects, but still\n      groups them into a traditional GLSL 'sampler object'.\n\n    Compatibility rules for image-sample-type vs sampler-type are as follows:\n\n        - SG_IMAGESAMPLETYPE_FLOAT => (SG_SAMPLERTYPE_FILTERING or SG_SAMPLERTYPE_NONFILTERING)\n        - SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT => SG_SAMPLERTYPE_NONFILTERING\n        - SG_IMAGESAMPLETYPE_SINT => SG_SAMPLERTYPE_NONFILTERING\n        - SG_IMAGESAMPLETYPE_UINT => SG_SAMPLERTYPE_NONFILTERING\n        - SG_IMAGESAMPLETYPE_DEPTH => SG_SAMPLERTYPE_COMPARISON\n\n    For example code of how to create backend-specific shader objects,\n    please refer to the following samples:\n\n        - for D3D11:    https://github.com/floooh/sokol-samples/tree/master/d3d11\n        - for Metal:    https://github.com/floooh/sokol-samples/tree/master/metal\n        - for OpenGL:   https://github.com/floooh/sokol-samples/tree/master/glfw\n        - for GLES3:    https://github.com/floooh/sokol-samples/tree/master/html5\n        - for WebGPI:   https://github.com/floooh/sokol-samples/tree/master/wgpu\n\n\n    ON SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT AND SG_SAMPLERTYPE_NONFILTERING\n    ========================================================================\n    The WebGPU backend introduces the concept of 'unfilterable-float' textures,\n    which can only be combined with 'nonfiltering' samplers (this is a restriction\n    specific to WebGPU, but since the same sokol-gfx code should work across\n    all backend, the sokol-gfx validation layer also enforces this restriction\n    - the alternative would be undefined behaviour in some backend APIs on\n    some devices).\n\n    The background is that some mobile devices (most notably iOS devices) can\n    not perform linear filtering when sampling textures with certain pixel\n    formats, most notable the 32F formats:\n\n        - SG_PIXELFORMAT_R32F\n        - SG_PIXELFORMAT_RG32F\n        - SG_PIXELFORMAT_RGBA32F\n\n    The information of whether a shader is going to be used with such an\n    unfilterable-float texture must already be provided in the sg_shader_desc\n    struct when creating the shader (see the above section \"ON SHADER CREATION\").\n\n    If you are using the sokol-shdc shader compiler, the information whether a\n    texture/sampler binding expects an 'unfilterable-float/nonfiltering'\n    texture/sampler combination cannot be inferred from the shader source\n    alone, you'll need to provide this hint via annotation-tags. For instance\n    here is an example from the ozz-skin-sapp.c sample shader which samples an\n    RGBA32F texture with skinning matrices in the vertex shader:\n\n    ```glsl\n    @image_sample_type joint_tex unfilterable_float\n    uniform texture2D joint_tex;\n    @sampler_type smp nonfiltering\n    uniform sampler smp;\n    ```\n\n    This will result in SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT and\n    SG_SAMPLERTYPE_NONFILTERING being written to the code-generated\n    sg_shader_desc struct.\n\n\n    UNIFORM DATA LAYOUT:\n    ====================\n    NOTE: if you use the sokol-shdc shader compiler tool, you don't need to worry\n    about the following details.\n\n    The data that's passed into the sg_apply_uniforms() function must adhere to\n    specific layout rules so that the GPU shader finds the uniform block\n    items at the right offset.\n\n    For the D3D11 and Metal backends, sokol-gfx only cares about the size of uniform\n    blocks, but not about the internal layout. The data will just be copied into\n    a uniform/constant buffer in a single operation and it's up you to arrange the\n    CPU-side layout so that it matches the GPU side layout. This also means that with\n    the D3D11 and Metal backends you are not limited to a 'cross-platform' subset\n    of uniform variable types.\n\n    If you ever only use one of the D3D11, Metal *or* WebGPU backend, you can stop reading here.\n\n    For the GL backends, the internal layout of uniform blocks matters though,\n    and you are limited to a small number of uniform variable types. This is\n    because sokol-gfx must be able to locate the uniform block members in order\n    to upload them to the GPU with glUniformXXX() calls.\n\n    To describe the uniform block layout to sokol-gfx, the following information\n    must be passed to the sg_make_shader() call in the sg_shader_desc struct:\n\n        - a hint about the used packing rule (either SG_UNIFORMLAYOUT_NATIVE or\n          SG_UNIFORMLAYOUT_STD140)\n        - a list of the uniform block members types in the correct order they\n          appear on the CPU side\n\n    For example if the GLSL shader has the following uniform declarations:\n\n        uniform mat4 mvp;\n        uniform vec2 offset0;\n        uniform vec2 offset1;\n        uniform vec2 offset2;\n\n    ...and on the CPU side, there's a similar C struct:\n\n        typedef struct {\n            float mvp[16];\n            float offset0[2];\n            float offset1[2];\n            float offset2[2];\n        } params_t;\n\n    ...the uniform block description in the sg_shader_desc must look like this:\n\n        sg_shader_desc desc = {\n            .vs.uniform_blocks[0] = {\n                .size = sizeof(params_t),\n                .layout = SG_UNIFORMLAYOUT_NATIVE,  // this is the default and can be omitted\n                .uniforms = {\n                    // order must be the same as in 'params_t':\n                    [0] = { .name = \"mvp\", .type = SG_UNIFORMTYPE_MAT4 },\n                    [1] = { .name = \"offset0\", .type = SG_UNIFORMTYPE_VEC2 },\n                    [2] = { .name = \"offset1\", .type = SG_UNIFORMTYPE_VEC2 },\n                    [3] = { .name = \"offset2\", .type = SG_UNIFORMTYPE_VEC2 },\n                }\n            }\n        };\n\n    With this information sokol-gfx can now compute the correct offsets of the data items\n    within the uniform block struct.\n\n    The SG_UNIFORMLAYOUT_NATIVE packing rule works fine if only the GL backends are used,\n    but for proper D3D11/Metal/GL a subset of the std140 layout must be used which is\n    described in the next section:\n\n\n    CROSS-BACKEND COMMON UNIFORM DATA LAYOUT\n    ========================================\n    For cross-platform / cross-3D-backend code it is important that the same uniform block\n    layout on the CPU side can be used for all sokol-gfx backends. To achieve this,\n    a common subset of the std140 layout must be used:\n\n    - The uniform block layout hint in sg_shader_desc must be explicitly set to\n      SG_UNIFORMLAYOUT_STD140.\n    - Only the following GLSL uniform types can be used (with their associated sokol-gfx enums):\n        - float => SG_UNIFORMTYPE_FLOAT\n        - vec2  => SG_UNIFORMTYPE_FLOAT2\n        - vec3  => SG_UNIFORMTYPE_FLOAT3\n        - vec4  => SG_UNIFORMTYPE_FLOAT4\n        - int   => SG_UNIFORMTYPE_INT\n        - ivec2 => SG_UNIFORMTYPE_INT2\n        - ivec3 => SG_UNIFORMTYPE_INT3\n        - ivec4 => SG_UNIFORMTYPE_INT4\n        - mat4  => SG_UNIFORMTYPE_MAT4\n    - Alignment for those types must be as follows (in bytes):\n        - float => 4\n        - vec2  => 8\n        - vec3  => 16\n        - vec4  => 16\n        - int   => 4\n        - ivec2 => 8\n        - ivec3 => 16\n        - ivec4 => 16\n        - mat4  => 16\n    - Arrays are only allowed for the following types: vec4, int4, mat4.\n\n    Note that the HLSL cbuffer layout rules are slightly different from the\n    std140 layout rules, this means that the cbuffer declarations in HLSL code\n    must be tweaked so that the layout is compatible with std140.\n\n    The by far easiest way to tackle the common uniform block layout problem is\n    to use the sokol-shdc shader cross-compiler tool!\n\n    ON STORAGE BUFFERS\n    ==================\n    Storage buffers can be used to pass large amounts of random access structured\n    data fromt the CPU side to the shaders. They are similar to data textures, but are\n    more convenient to use both on the CPU and shader side since they can be accessed\n    in shaders as as a 1-dimensional array of struct items.\n\n    Storage buffers are *NOT* supported on the following platform/backend combos:\n\n    - macOS+GL (because storage buffers require GL 4.3, while macOS only goes up to GL 4.1)\n    - all GLES3 platforms (WebGL2, iOS, Android - with the option that support on\n      Android may be added at a later point)\n\n    Currently only 'readonly' storage buffers are supported (meaning it's not possible\n    to write to storage buffers from shaders).\n\n    To use storage buffers, the following steps are required:\n\n        - write a shader which uses storage buffers (also see the example links below)\n        - create one or more storage buffers via sg_make_buffer() with the\n          buffer type SG_BUFFERTYPE_STORAGEBUFFER\n        - when creating a shader via sg_make_shader(), populate the sg_shader_desc\n          struct with binding info (when using sokol-shdc, this step will be taken care\n          of automatically)\n            - which storage buffer bind slots on the vertex- and fragment-stage\n              are occupied\n            - whether the storage buffer on that bind slot is readonly (this is currently required\n              to be true)\n        - when calling sg_apply_bindings(), apply the matching bind slots with the previously\n          created storage buffers\n        - ...and that's it.\n\n    For more details, see the following backend-agnostic sokol samples:\n\n    - simple vertex pulling from a storage buffer:\n        - C code: https://github.com/floooh/sokol-samples/blob/master/sapp/vertexpull-sapp.c\n        - shader: https://github.com/floooh/sokol-samples/blob/master/sapp/vertexpull-sapp.glsl\n    - instanced rendering via storage buffers (vertex- and instance-pulling):\n        - C code: https://github.com/floooh/sokol-samples/blob/master/sapp/instancing-pull-sapp.c\n        - shader: https://github.com/floooh/sokol-samples/blob/master/sapp/instancing-pull-sapp.glsl\n    - storage buffers both on the vertex- and fragment-stage:\n        - C code: https://github.com/floooh/sokol-samples/blob/master/sapp/sbuftex-sapp.c\n        - shader: https://github.com/floooh/sokol-samples/blob/master/sapp/sbuftex-sapp.glsl\n    - the Ozz animation sample rewritten to pull all rendering data from storage buffers:\n        - C code: https://github.com/floooh/sokol-samples/blob/master/sapp/ozz-storagebuffer-sapp.cc\n        - shader: https://github.com/floooh/sokol-samples/blob/master/sapp/ozz-storagebuffer-sapp.glsl\n\n    ...also see the following backend-specific vertex pulling samples (those also don't use sokol-shdc):\n\n    - D3D11: https://github.com/floooh/sokol-samples/blob/master/d3d11/vertexpulling-d3d11.c\n    - desktop GL: https://github.com/floooh/sokol-samples/blob/master/glfw/vertexpulling-glfw.c\n    - Metal: https://github.com/floooh/sokol-samples/blob/master/metal/vertexpulling-metal.c\n    - WebGPU: https://github.com/floooh/sokol-samples/blob/master/wgpu/vertexpulling-wgpu.c\n\n    Storage buffer shader authoring caveats when using sokol-shdc:\n\n        - declare a storage buffer interface block with `readonly buffer [name] { ... }`\n        - do NOT annotate storage buffers with `layout(...)`, sokol-shdc will take care of that\n        - declare a struct which describes a single array item in the storage buffer interface block\n        - only put a single flexible array member into the storage buffer interface block\n\n        E.g. a complete example in 'sokol-shdc GLSL':\n\n        ```glsl\n        // declare a struct:\n        struct sb_vertex {\n            vec3 pos;\n            vec4 color;\n        }\n        // declare a buffer interface block with a single flexible struct array:\n        readonly buffer vertices {\n            sb_vertex vtx[];\n        }\n        // in the shader function, access the storage buffer like this:\n        void main() {\n            vec3 pos = vtx[gl_VertexIndex].pos;\n            ...\n        }\n        ```\n\n    Backend-specific storage-buffer caveats (not relevant when using sokol-shdc):\n\n        D3D11:\n            - storage buffers are created as 'raw' Byte Address Buffers\n              (https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-resources-intro#raw-views-of-buffers)\n            - in HLSL, use a ByteAddressBuffer to access the buffer content\n              (https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-byteaddressbuffer)\n            - in D3D11, storage buffers and textures share the same bind slots, sokol-gfx reserves\n              shader resource slots 0..15 for textures and 16..23 for storage buffers.\n            - e.g. in HLSL, storage buffer bindings start at register(t16) no matter the shader stage\n\n        Metal:\n            - in Metal there is no internal difference between vertex-, uniform- and\n              storage-buffers, all are bound to the same 'buffer bind slots' with the\n              following reserved ranges:\n                - vertex shader stage:\n                    - uniform buffers (internal): slots 0..3\n                    - vertex buffers: slots 4..11\n                    - storage buffers: slots 12..19\n                - fragment shader stage:\n                    - uniform buffers (internal): slots 0..3\n                    - storage buffers: slots 4..11\n            - this means in MSL, storage buffer bindings start at [[buffer(12)]] in the vertex\n              shaders, and at [[buffer(4)]] in fragment shaders\n\n        GL:\n            - the GL backend doesn't use name-lookup to find storage buffer bindings, this\n              means you must annotate buffers with `layout(std430, binding=N)` in GLSL\n            - ...where N is 0..7 in the vertex shader, and 8..15 in the fragment shader\n\n        WebGPU:\n            - in WGSL, use the following bind locations for the various shader resource types:\n            - vertex shader stage:\n                - textures `@group(1) @binding(0..15)`\n                - samplers `@group(1) @binding(16..31)`\n                - storage buffers `@group(1) @binding(32..47)`\n            - fragment shader stage:\n                - textures `@group(1) @binding(48..63)`\n                - samplers `@group(1) @binding(64..79)`\n                - storage buffers `@group(1) @binding(80..95)`\n\n    TRACE HOOKS:\n    ============\n    sokol_gfx.h optionally allows to install \"trace hook\" callbacks for\n    each public API functions. When a public API function is called, and\n    a trace hook callback has been installed for this function, the\n    callback will be invoked with the parameters and result of the function.\n    This is useful for things like debugging- and profiling-tools, or\n    keeping track of resource creation and destruction.\n\n    To use the trace hook feature:\n\n    --- Define SOKOL_TRACE_HOOKS before including the implementation.\n\n    --- Setup an sg_trace_hooks structure with your callback function\n        pointers (keep all function pointers you're not interested\n        in zero-initialized), optionally set the user_data member\n        in the sg_trace_hooks struct.\n\n    --- Install the trace hooks by calling sg_install_trace_hooks(),\n        the return value of this function is another sg_trace_hooks\n        struct which contains the previously set of trace hooks.\n        You should keep this struct around, and call those previous\n        functions pointers from your own trace callbacks for proper\n        chaining.\n\n    As an example of how trace hooks are used, have a look at the\n    imgui/sokol_gfx_imgui.h header which implements a realtime\n    debugging UI for sokol_gfx.h on top of Dear ImGui.\n\n\n    A NOTE ON PORTABLE PACKED VERTEX FORMATS:\n    =========================================\n    There are two things to consider when using packed\n    vertex formats like UBYTE4, SHORT2, etc which need to work\n    across all backends:\n\n    - D3D11 can only convert *normalized* vertex formats to\n      floating point during vertex fetch, normalized formats\n      have a trailing 'N', and are \"normalized\" to a range\n      -1.0..+1.0 (for the signed formats) or 0.0..1.0 (for the\n      unsigned formats):\n\n        - SG_VERTEXFORMAT_BYTE4N\n        - SG_VERTEXFORMAT_UBYTE4N\n        - SG_VERTEXFORMAT_SHORT2N\n        - SG_VERTEXFORMAT_USHORT2N\n        - SG_VERTEXFORMAT_SHORT4N\n        - SG_VERTEXFORMAT_USHORT4N\n\n      D3D11 will not convert *non-normalized* vertex formats to floating point\n      vertex shader inputs, those can only be uses with the *ivecn* vertex shader\n      input types when D3D11 is used as backend (GL and Metal can use both formats)\n\n        - SG_VERTEXFORMAT_BYTE4,\n        - SG_VERTEXFORMAT_UBYTE4\n        - SG_VERTEXFORMAT_SHORT2\n        - SG_VERTEXFORMAT_SHORT4\n\n    For a vertex input layout which works on all platforms, only use the following\n    vertex formats, and if needed \"expand\" the normalized vertex shader\n    inputs in the vertex shader by multiplying with 127.0, 255.0, 32767.0 or\n    65535.0:\n\n        - SG_VERTEXFORMAT_FLOAT,\n        - SG_VERTEXFORMAT_FLOAT2,\n        - SG_VERTEXFORMAT_FLOAT3,\n        - SG_VERTEXFORMAT_FLOAT4,\n        - SG_VERTEXFORMAT_BYTE4N,\n        - SG_VERTEXFORMAT_UBYTE4N,\n        - SG_VERTEXFORMAT_SHORT2N,\n        - SG_VERTEXFORMAT_USHORT2N\n        - SG_VERTEXFORMAT_SHORT4N,\n        - SG_VERTEXFORMAT_USHORT4N\n        - SG_VERTEXFORMAT_UINT10_N2\n        - SG_VERTEXFORMAT_HALF2\n        - SG_VERTEXFORMAT_HALF4\n\n\n    MEMORY ALLOCATION OVERRIDE\n    ==========================\n    You can override the memory allocation functions at initialization time\n    like this:\n\n        void* my_alloc(size_t size, void* user_data) {\n            return malloc(size);\n        }\n\n        void my_free(void* ptr, void* user_data) {\n            free(ptr);\n        }\n\n        ...\n            sg_setup(&(sg_desc){\n                // ...\n                .allocator = {\n                    .alloc_fn = my_alloc,\n                    .free_fn = my_free,\n                    .user_data = ...,\n                }\n            });\n        ...\n\n    If no overrides are provided, malloc and free will be used.\n\n    This only affects memory allocation calls done by sokol_gfx.h\n    itself though, not any allocations in OS libraries.\n\n\n    ERROR REPORTING AND LOGGING\n    ===========================\n    To get any logging information at all you need to provide a logging callback in the setup call\n    the easiest way is to use sokol_log.h:\n\n        #include \"sokol_log.h\"\n\n        sg_setup(&(sg_desc){ .logger.func = slog_func });\n\n    To override logging with your own callback, first write a logging function like this:\n\n        void my_log(const char* tag,                // e.g. 'sg'\n                    uint32_t log_level,             // 0=panic, 1=error, 2=warn, 3=info\n                    uint32_t log_item_id,           // SG_LOGITEM_*\n                    const char* message_or_null,    // a message string, may be nullptr in release mode\n                    uint32_t line_nr,               // line number in sokol_gfx.h\n                    const char* filename_or_null,   // source filename, may be nullptr in release mode\n                    void* user_data)\n        {\n            ...\n        }\n\n    ...and then setup sokol-gfx like this:\n\n        sg_setup(&(sg_desc){\n            .logger = {\n                .func = my_log,\n                .user_data = my_user_data,\n            }\n        });\n\n    The provided logging function must be reentrant (e.g. be callable from\n    different threads).\n\n    If you don't want to provide your own custom logger it is highly recommended to use\n    the standard logger in sokol_log.h instead, otherwise you won't see any warnings or\n    errors.\n\n\n    COMMIT LISTENERS\n    ================\n    It's possible to hook callback functions into sokol-gfx which are called from\n    inside sg_commit() in unspecified order. This is mainly useful for libraries\n    that build on top of sokol_gfx.h to be notified about the end/start of a frame.\n\n    To add a commit listener, call:\n\n        static void my_commit_listener(void* user_data) {\n            ...\n        }\n\n        bool success = sg_add_commit_listener((sg_commit_listener){\n            .func = my_commit_listener,\n            .user_data = ...,\n        });\n\n    The function returns false if the internal array of commit listeners is full,\n    or the same commit listener had already been added.\n\n    If the function returns true, my_commit_listener() will be called each frame\n    from inside sg_commit().\n\n    By default, 1024 distinct commit listeners can be added, but this number\n    can be tweaked in the sg_setup() call:\n\n        sg_setup(&(sg_desc){\n            .max_commit_listeners = 2048,\n        });\n\n    An sg_commit_listener item is equal to another if both the function\n    pointer and user_data field are equal.\n\n    To remove a commit listener:\n\n        bool success = sg_remove_commit_listener((sg_commit_listener){\n            .func = my_commit_listener,\n            .user_data = ...,\n        });\n\n    ...where the .func and .user_data field are equal to a previous\n    sg_add_commit_listener() call. The function returns true if the commit\n    listener item was found and removed, and false otherwise.\n\n\n    RESOURCE CREATION AND DESTRUCTION IN DETAIL\n    ===========================================\n    The 'vanilla' way to create resource objects is with the 'make functions':\n\n        sg_buffer sg_make_buffer(const sg_buffer_desc* desc)\n        sg_image sg_make_image(const sg_image_desc* desc)\n        sg_sampler sg_make_sampler(const sg_sampler_desc* desc)\n        sg_shader sg_make_shader(const sg_shader_desc* desc)\n        sg_pipeline sg_make_pipeline(const sg_pipeline_desc* desc)\n        sg_attachments sg_make_attachments(const sg_attachments_desc* desc)\n\n    This will result in one of three cases:\n\n        1. The returned handle is invalid. This happens when there are no more\n           free slots in the resource pool for this resource type. An invalid\n           handle is associated with the INVALID resource state, for instance:\n\n                sg_buffer buf = sg_make_buffer(...)\n                if (sg_query_buffer_state(buf) == SG_RESOURCESTATE_INVALID) {\n                    // buffer pool is exhausted\n                }\n\n        2. The returned handle is valid, but creating the underlying resource\n           has failed for some reason. This results in a resource object in the\n           FAILED state. The reason *why* resource creation has failed differ\n           by resource type. Look for log messages with more details. A failed\n           resource state can be checked with:\n\n                sg_buffer buf = sg_make_buffer(...)\n                if (sg_query_buffer_state(buf) == SG_RESOURCESTATE_FAILED) {\n                    // creating the resource has failed\n                }\n\n        3. And finally, if everything goes right, the returned resource is\n           in resource state VALID and ready to use. This can be checked\n           with:\n\n                sg_buffer buf = sg_make_buffer(...)\n                if (sg_query_buffer_state(buf) == SG_RESOURCESTATE_VALID) {\n                    // creating the resource has failed\n                }\n\n    When calling the 'make functions', the created resource goes through a number\n    of states:\n\n        - INITIAL: the resource slot associated with the new resource is currently\n          free (technically, there is no resource yet, just an empty pool slot)\n        - ALLOC: a handle for the new resource has been allocated, this just means\n          a pool slot has been reserved.\n        - VALID or FAILED: in VALID state any 3D API backend resource objects have\n          been successfully created, otherwise if anything went wrong, the resource\n          will be in FAILED state.\n\n    Sometimes it makes sense to first grab a handle, but initialize the\n    underlying resource at a later time. For instance when loading data\n    asynchronously from a slow data source, you may know what buffers and\n    textures are needed at an early stage of the loading process, but actually\n    loading the buffer or texture content can only be completed at a later time.\n\n    For such situations, sokol-gfx resource objects can be created in two steps.\n    You can allocate a handle upfront with one of the 'alloc functions':\n\n        sg_buffer sg_alloc_buffer(void)\n        sg_image sg_alloc_image(void)\n        sg_sampler sg_alloc_sampler(void)\n        sg_shader sg_alloc_shader(void)\n        sg_pipeline sg_alloc_pipeline(void)\n        sg_attachments sg_alloc_attachments(void)\n\n    This will return a handle with the underlying resource object in the\n    ALLOC state:\n\n        sg_image img = sg_alloc_image();\n        if (sg_query_image_state(img) == SG_RESOURCESTATE_ALLOC) {\n            // allocating an image handle has succeeded, otherwise\n            // the image pool is full\n        }\n\n    Such an 'incomplete' handle can be used in most sokol-gfx rendering functions\n    without doing any harm, sokol-gfx will simply skip any rendering operation\n    that involve resources which are not in VALID state.\n\n    At a later time (for instance once the texture has completed loading\n    asynchronously), the resource creation can be completed by calling one of\n    the 'init functions', those functions take an existing resource handle and\n    'desc struct':\n\n        void sg_init_buffer(sg_buffer buf, const sg_buffer_desc* desc)\n        void sg_init_image(sg_image img, const sg_image_desc* desc)\n        void sg_init_sampler(sg_sampler smp, const sg_sampler_desc* desc)\n        void sg_init_shader(sg_shader shd, const sg_shader_desc* desc)\n        void sg_init_pipeline(sg_pipeline pip, const sg_pipeline_desc* desc)\n        void sg_init_attachments(sg_attachments atts, const sg_attachments_desc* desc)\n\n    The init functions expect a resource in ALLOC state, and after the function\n    returns, the resource will be either in VALID or FAILED state. Calling\n    an 'alloc function' followed by the matching 'init function' is fully\n    equivalent with calling the 'make function' alone.\n\n    Destruction can also happen as a two-step process. The 'uninit functions'\n    will put a resource object from the VALID or FAILED state back into the\n    ALLOC state:\n\n        void sg_uninit_buffer(sg_buffer buf)\n        void sg_uninit_image(sg_image img)\n        void sg_uninit_sampler(sg_sampler smp)\n        void sg_uninit_shader(sg_shader shd)\n        void sg_uninit_pipeline(sg_pipeline pip)\n        void sg_uninit_attachments(sg_attachments pass)\n\n    Calling the 'uninit functions' with a resource that is not in the VALID or\n    FAILED state is a no-op.\n\n    To finally free the pool slot for recycling call the 'dealloc functions':\n\n        void sg_dealloc_buffer(sg_buffer buf)\n        void sg_dealloc_image(sg_image img)\n        void sg_dealloc_sampler(sg_sampler smp)\n        void sg_dealloc_shader(sg_shader shd)\n        void sg_dealloc_pipeline(sg_pipeline pip)\n        void sg_dealloc_attachments(sg_attachments atts)\n\n    Calling the 'dealloc functions' on a resource that's not in ALLOC state is\n    a no-op, but will generate a warning log message.\n\n    Calling an 'uninit function' and 'dealloc function' in sequence is equivalent\n    with calling the associated 'destroy function':\n\n        void sg_destroy_buffer(sg_buffer buf)\n        void sg_destroy_image(sg_image img)\n        void sg_destroy_sampler(sg_sampler smp)\n        void sg_destroy_shader(sg_shader shd)\n        void sg_destroy_pipeline(sg_pipeline pip)\n        void sg_destroy_attachments(sg_attachments atts)\n\n    The 'destroy functions' can be called on resources in any state and generally\n    do the right thing (for instance if the resource is in ALLOC state, the destroy\n    function will be equivalent to the 'dealloc function' and skip the 'uninit part').\n\n    And finally to close the circle, the 'fail functions' can be called to manually\n    put a resource in ALLOC state into the FAILED state:\n\n        sg_fail_buffer(sg_buffer buf)\n        sg_fail_image(sg_image img)\n        sg_fail_sampler(sg_sampler smp)\n        sg_fail_shader(sg_shader shd)\n        sg_fail_pipeline(sg_pipeline pip)\n        sg_fail_attachments(sg_attachments atts)\n\n    This is recommended if anything went wrong outside of sokol-gfx during asynchronous\n    resource setup (for instance a file loading operation failed). In this case,\n    the 'fail function' should be called instead of the 'init function'.\n\n    Calling a 'fail function' on a resource that's not in ALLOC state is a no-op,\n    but will generate a warning log message.\n\n    NOTE: that two-step resource creation usually only makes sense for buffers\n    and images, but not for samplers, shaders, pipelines or attachments. Most notably, trying\n    to create a pipeline object with a shader that's not in VALID state will\n    trigger a validation layer error, or if the validation layer is disabled,\n    result in a pipeline object in FAILED state. Same when trying to create\n    an attachments object with invalid image objects.\n\n\n    WEBGPU CAVEATS\n    ==============\n    For a general overview and design notes of the WebGPU backend see:\n\n        https://floooh.github.io/2023/10/16/sokol-webgpu.html\n\n    In general, don't expect an automatic speedup when switching from the WebGL2\n    backend to the WebGPU backend. Some WebGPU functions currently actually\n    have a higher CPU overhead than similar WebGL2 functions, leading to the\n    paradoxical situation that some WebGPU code may be slower than similar WebGL2\n    code.\n\n    - when writing WGSL shader code by hand, a specific bind-slot convention\n      must be used:\n\n      All uniform block structs must use `@group(0)`, with up to\n      4 uniform blocks per shader stage.\n        - Vertex shader uniform block bindings must start at `@group(0) @binding(0)`\n        - Fragment shader uniform blocks bindings must start at `@group(0) @binding(4)`\n\n      All textures and samplers must use `@group(1)` and start at specific\n      offsets depending on resource type and shader stage.\n        - Vertex shader textures must start at `@group(1) @binding(0)`\n        - Vertex shader samplers must start at `@group(1) @binding(16)`\n        - Vertex shader storage buffers must start at `@group(1) @binding(32)`\n        - Fragment shader textures must start at `@group(1) @binding(48)`\n        - Fragment shader samplers must start at `@group(1) @binding(64)`\n        - Fragment shader storage buffers must start at `@group(1) @binding(80)`\n\n      Note that the actual number of allowed per-stage texture- and sampler-bindings\n      in sokol-gfx is currently lower than the above ranges (currently only up to\n      12 textures, 8 samplers and 8 storage buffers are allowed per shader stage).\n\n      If you use sokol-shdc to generate WGSL shader code, you don't need to worry\n      about the above binding convention since sokol-shdc assigns bind slots\n      automatically.\n\n    - The sokol-gfx WebGPU backend uses the sg_desc.uniform_buffer_size item\n      to allocate a single per-frame uniform buffer which must be big enough\n      to hold all data written by sg_apply_uniforms() during a single frame,\n      including a worst-case 256-byte alignment (e.g. each sg_apply_uniform\n      call will cost 256 bytes of uniform buffer size). The default size\n      is 4 MB, which is enough for 16384 sg_apply_uniform() calls per\n      frame (assuming the uniform data 'payload' is less than 256 bytes\n      per call). These rules are the same as for the Metal backend, so if\n      you are already using the Metal backend you'll be fine.\n\n    - sg_apply_bindings(): the sokol-gfx WebGPU backend implements a bindgroup\n      cache to prevent excessive creation and destruction of BindGroup objects\n      when calling sg_apply_bindings(). The number of slots in the bindgroups\n      cache is defined in sg_desc.wgpu_bindgroups_cache_size when calling\n      sg_setup. The cache size must be a power-of-2 number, with the default being\n      1024. The bindgroups cache behaviour can be observed by calling the new\n      function sg_query_frame_stats(), where the following struct items are\n      of interest:\n\n        .wgpu.num_bindgroup_cache_hits\n        .wgpu.num_bindgroup_cache_misses\n        .wgpu.num_bindgroup_cache_collisions\n        .wgpu.num_bindgroup_cache_vs_hash_key_mismatch\n\n      The value to pay attention to is `.wgpu.num_bindgroup_cache_collisions`,\n      if this number if consistently higher than a few percent of the\n      .wgpu.num_set_bindgroup value, it might be a good idea to bump the\n      bindgroups cache size to the next power-of-2.\n\n    - sg_apply_viewport(): WebGPU currently has a unique restriction that viewport\n      rectangles must be contained entirely within the framebuffer. As a shitty\n      workaround sokol_gfx.h will clip incoming viewport rectangles against\n      the framebuffer, but this will distort the clipspace-to-screenspace mapping.\n      There's no proper way to handle this inside sokol_gfx.h, this must be fixed\n      in a future WebGPU update.\n\n    - The sokol shader compiler generally adds `diagnostic(off, derivative_uniformity);`\n      into the WGSL output. Currently only the Chrome WebGPU implementation seems\n      to recognize this.\n\n    - The vertex format SG_VERTEXFORMAT_UINT10_N2 is currently not supported because\n      WebGPU lacks a matching vertex format (this is currently being worked on though,\n      as soon as the vertex format shows up in webgpu.h, sokol_gfx.h will add support.\n\n    - Likewise, the following sokol-gfx vertex formats are not supported in WebGPU:\n      R16, R16SN, RG16, RG16SN, RGBA16, RGBA16SN and all PVRTC compressed format.\n      Unlike unsupported vertex formats, unsupported pixel formats can be queried\n      in cross-backend code via sg_query_pixel_format() though.\n\n    - The Emscripten WebGPU shim currently doesn't support the Closure minification\n      post-link-step (e.g. currently the emcc argument '--closure 1' or '--closure 2'\n      will generate broken Javascript code.\n\n    - sokol-gfx requires the WebGPU device feature `depth32float-stencil8` to be enabled\n      (this should be widely supported)\n\n    - sokol-gfx expects that the WebGPU device feature `float32-filterable` to *not* be\n      enabled (since this would exclude all iOS devices)\n\n\n    LICENSE\n    =======\n    zlib/libpng license\n\n    Copyright (c) 2018 Andre Weissflog\n\n    This software is provided 'as-is', without any express or implied warranty.\n    In no event will the authors be held liable for any damages arising from the\n    use of this software.\n\n    Permission is granted to anyone to use this software for any purpose,\n    including commercial applications, and to alter it and redistribute it\n    freely, subject to the following restrictions:\n\n        1. The origin of this software must not be misrepresented; you must not\n        claim that you wrote the original software. If you use this software in a\n        product, an acknowledgment in the product documentation would be\n        appreciated but is not required.\n\n        2. Altered source versions must be plainly marked as such, and must not\n        be misrepresented as being the original software.\n\n        3. This notice may not be removed or altered from any source\n        distribution.\n*/\n#define SOKOL_GFX_INCLUDED (1)\n#include <stddef.h>     // size_t\n#include <stdint.h>\n#include <stdbool.h>\n\n#if defined(SOKOL_API_DECL) && !defined(SOKOL_GFX_API_DECL)\n#define SOKOL_GFX_API_DECL SOKOL_API_DECL\n#endif\n#ifndef SOKOL_GFX_API_DECL\n#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_GFX_IMPL)\n#define SOKOL_GFX_API_DECL __declspec(dllexport)\n#elif defined(_WIN32) && defined(SOKOL_DLL)\n#define SOKOL_GFX_API_DECL __declspec(dllimport)\n#else\n#define SOKOL_GFX_API_DECL extern\n#endif\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n    Resource id typedefs:\n\n    sg_buffer:      vertex- and index-buffers\n    sg_image:       images used as textures and render targets\n    sg_sampler      sampler object describing how a texture is sampled in a shader\n    sg_shader:      vertex- and fragment-shaders and shader interface information\n    sg_pipeline:    associated shader and vertex-layouts, and render states\n    sg_attachments: a baked collection of render pass attachment images\n\n    Instead of pointers, resource creation functions return a 32-bit\n    number which uniquely identifies the resource object.\n\n    The 32-bit resource id is split into a 16-bit pool index in the lower bits,\n    and a 16-bit 'generation counter' in the upper bits. The index allows fast\n    pool lookups, and combined with the generation-counter it allows to detect\n    'dangling accesses' (trying to use an object which no longer exists, and\n    its pool slot has been reused for a new object)\n\n    The resource ids are wrapped into a strongly-typed struct so that\n    trying to pass an incompatible resource id is a compile error.\n*/\ntypedef struct sg_buffer        { uint32_t id; } sg_buffer;\ntypedef struct sg_image         { uint32_t id; } sg_image;\ntypedef struct sg_sampler       { uint32_t id; } sg_sampler;\ntypedef struct sg_shader        { uint32_t id; } sg_shader;\ntypedef struct sg_pipeline      { uint32_t id; } sg_pipeline;\ntypedef struct sg_attachments   { uint32_t id; } sg_attachments;\n\n/*\n    sg_range is a pointer-size-pair struct used to pass memory blobs into\n    sokol-gfx. When initialized from a value type (array or struct), you can\n    use the SG_RANGE() macro to build an sg_range struct. For functions which\n    take either a sg_range pointer, or a (C++) sg_range reference, use the\n    SG_RANGE_REF macro as a solution which compiles both in C and C++.\n*/\ntypedef struct sg_range {\n    const void* ptr;\n    size_t size;\n} sg_range;\n\n// disabling this for every includer isn't great, but the warnings are also quite pointless\n#if defined(_MSC_VER)\n#pragma warning(disable:4221)   // /W4 only: nonstandard extension used: 'x': cannot be initialized using address of automatic variable 'y'\n#pragma warning(disable:4204)   // VS2015: nonstandard extension used: non-constant aggregate initializer\n#endif\n#if defined(__cplusplus)\n#define SG_RANGE(x) sg_range{ &x, sizeof(x) }\n#define SG_RANGE_REF(x) sg_range{ &x, sizeof(x) }\n#else\n#define SG_RANGE(x) (sg_range){ &x, sizeof(x) }\n#define SG_RANGE_REF(x) &(sg_range){ &x, sizeof(x) }\n#endif\n\n//  various compile-time constants\nenum {\n    SG_INVALID_ID = 0,\n    SG_NUM_SHADER_STAGES = 2,\n    SG_NUM_INFLIGHT_FRAMES = 2,\n    SG_MAX_COLOR_ATTACHMENTS = 4,\n    SG_MAX_VERTEX_BUFFERS = 8,\n    SG_MAX_SHADERSTAGE_IMAGES = 12,\n    SG_MAX_SHADERSTAGE_SAMPLERS = 8,\n    SG_MAX_SHADERSTAGE_IMAGESAMPLERPAIRS = 12,\n    SG_MAX_SHADERSTAGE_STORAGEBUFFERS = 8,\n    SG_MAX_SHADERSTAGE_UBS = 4,\n    SG_MAX_UB_MEMBERS = 16,\n    SG_MAX_VERTEX_ATTRIBUTES = 16,\n    SG_MAX_MIPMAPS = 16,\n    SG_MAX_TEXTUREARRAY_LAYERS = 128\n};\n\n/*\n    sg_color\n\n    An RGBA color value.\n*/\ntypedef struct sg_color { float r, g, b, a; } sg_color;\n\n/*\n    sg_backend\n\n    The active 3D-API backend, use the function sg_query_backend()\n    to get the currently active backend.\n*/\ntypedef enum sg_backend {\n    SG_BACKEND_GLCORE,\n    SG_BACKEND_GLES3,\n    SG_BACKEND_D3D11,\n    SG_BACKEND_METAL_IOS,\n    SG_BACKEND_METAL_MACOS,\n    SG_BACKEND_METAL_SIMULATOR,\n    SG_BACKEND_WGPU,\n    SG_BACKEND_DUMMY,\n} sg_backend;\n\n/*\n    sg_pixel_format\n\n    sokol_gfx.h basically uses the same pixel formats as WebGPU, since these\n    are supported on most newer GPUs.\n\n    A pixelformat name consist of three parts:\n\n        - components (R, RG, RGB or RGBA)\n        - bit width per component (8, 16 or 32)\n        - component data type:\n            - unsigned normalized (no postfix)\n            - signed normalized (SN postfix)\n            - unsigned integer (UI postfix)\n            - signed integer (SI postfix)\n            - float (F postfix)\n\n    Not all pixel formats can be used for everything, call sg_query_pixelformat()\n    to inspect the capabilities of a given pixelformat. The function returns\n    an sg_pixelformat_info struct with the following members:\n\n        - sample: the pixelformat can be sampled as texture at least with\n                  nearest filtering\n        - filter: the pixelformat can be samples as texture with linear\n                  filtering\n        - render: the pixelformat can be used for render targets\n        - blend:  blending is supported when using the pixelformat for\n                  render targets\n        - msaa:   multisample-antialiasing is supported when using the\n                  pixelformat for render targets\n        - depth:  the pixelformat can be used for depth-stencil attachments\n        - compressed: this is a block-compressed format\n        - bytes_per_pixel: the numbers of bytes in a pixel (0 for compressed formats)\n\n    The default pixel format for texture images is SG_PIXELFORMAT_RGBA8.\n\n    The default pixel format for render target images is platform-dependent\n    and taken from the sg_environment struct passed into sg_setup(). Typically\n    the default formats are:\n\n        - for the Metal, D3D11 and WebGPU backends: SG_PIXELFORMAT_BGRA8\n        - for GL backends: SG_PIXELFORMAT_RGBA8\n*/\ntypedef enum sg_pixel_format {\n    _SG_PIXELFORMAT_DEFAULT,    // value 0 reserved for default-init\n    SG_PIXELFORMAT_NONE,\n\n    SG_PIXELFORMAT_R8,\n    SG_PIXELFORMAT_R8SN,\n    SG_PIXELFORMAT_R8UI,\n    SG_PIXELFORMAT_R8SI,\n\n    SG_PIXELFORMAT_R16,\n    SG_PIXELFORMAT_R16SN,\n    SG_PIXELFORMAT_R16UI,\n    SG_PIXELFORMAT_R16SI,\n    SG_PIXELFORMAT_R16F,\n    SG_PIXELFORMAT_RG8,\n    SG_PIXELFORMAT_RG8SN,\n    SG_PIXELFORMAT_RG8UI,\n    SG_PIXELFORMAT_RG8SI,\n\n    SG_PIXELFORMAT_R32UI,\n    SG_PIXELFORMAT_R32SI,\n    SG_PIXELFORMAT_R32F,\n    SG_PIXELFORMAT_RG16,\n    SG_PIXELFORMAT_RG16SN,\n    SG_PIXELFORMAT_RG16UI,\n    SG_PIXELFORMAT_RG16SI,\n    SG_PIXELFORMAT_RG16F,\n    SG_PIXELFORMAT_RGBA8,\n    SG_PIXELFORMAT_SRGB8A8,\n    SG_PIXELFORMAT_RGBA8SN,\n    SG_PIXELFORMAT_RGBA8UI,\n    SG_PIXELFORMAT_RGBA8SI,\n    SG_PIXELFORMAT_BGRA8,\n    SG_PIXELFORMAT_RGB10A2,\n    SG_PIXELFORMAT_RG11B10F,\n    SG_PIXELFORMAT_RGB9E5,\n\n    SG_PIXELFORMAT_RG32UI,\n    SG_PIXELFORMAT_RG32SI,\n    SG_PIXELFORMAT_RG32F,\n    SG_PIXELFORMAT_RGBA16,\n    SG_PIXELFORMAT_RGBA16SN,\n    SG_PIXELFORMAT_RGBA16UI,\n    SG_PIXELFORMAT_RGBA16SI,\n    SG_PIXELFORMAT_RGBA16F,\n\n    SG_PIXELFORMAT_RGBA32UI,\n    SG_PIXELFORMAT_RGBA32SI,\n    SG_PIXELFORMAT_RGBA32F,\n\n    // NOTE: when adding/removing pixel formats before DEPTH, also update sokol_app.h/_SAPP_PIXELFORMAT_*\n    SG_PIXELFORMAT_DEPTH,\n    SG_PIXELFORMAT_DEPTH_STENCIL,\n\n    // NOTE: don't put any new compressed format in front of here\n    SG_PIXELFORMAT_BC1_RGBA,\n    SG_PIXELFORMAT_BC2_RGBA,\n    SG_PIXELFORMAT_BC3_RGBA,\n    SG_PIXELFORMAT_BC3_SRGBA,\n    SG_PIXELFORMAT_BC4_R,\n    SG_PIXELFORMAT_BC4_RSN,\n    SG_PIXELFORMAT_BC5_RG,\n    SG_PIXELFORMAT_BC5_RGSN,\n    SG_PIXELFORMAT_BC6H_RGBF,\n    SG_PIXELFORMAT_BC6H_RGBUF,\n    SG_PIXELFORMAT_BC7_RGBA,\n    SG_PIXELFORMAT_BC7_SRGBA,\n    SG_PIXELFORMAT_PVRTC_RGB_2BPP,      // FIXME: deprecated\n    SG_PIXELFORMAT_PVRTC_RGB_4BPP,      // FIXME: deprecated\n    SG_PIXELFORMAT_PVRTC_RGBA_2BPP,     // FIXME: deprecated\n    SG_PIXELFORMAT_PVRTC_RGBA_4BPP,     // FIXME: deprecated\n    SG_PIXELFORMAT_ETC2_RGB8,\n    SG_PIXELFORMAT_ETC2_SRGB8,\n    SG_PIXELFORMAT_ETC2_RGB8A1,\n    SG_PIXELFORMAT_ETC2_RGBA8,\n    SG_PIXELFORMAT_ETC2_SRGB8A8,\n    SG_PIXELFORMAT_EAC_R11,\n    SG_PIXELFORMAT_EAC_R11SN,\n    SG_PIXELFORMAT_EAC_RG11,\n    SG_PIXELFORMAT_EAC_RG11SN,\n\n    SG_PIXELFORMAT_ASTC_4x4_RGBA,\n    SG_PIXELFORMAT_ASTC_4x4_SRGBA,\n\n    _SG_PIXELFORMAT_NUM,\n    _SG_PIXELFORMAT_FORCE_U32 = 0x7FFFFFFF\n} sg_pixel_format;\n\n/*\n    Runtime information about a pixel format, returned\n    by sg_query_pixelformat().\n*/\ntypedef struct sg_pixelformat_info {\n    bool sample;            // pixel format can be sampled in shaders at least with nearest filtering\n    bool filter;            // pixel format can be sampled with linear filtering\n    bool render;            // pixel format can be used as render target\n    bool blend;             // alpha-blending is supported\n    bool msaa;              // pixel format can be used as MSAA render target\n    bool depth;             // pixel format is a depth format\n    bool compressed;        // true if this is a hardware-compressed format\n    int bytes_per_pixel;    // NOTE: this is 0 for compressed formats, use sg_query_row_pitch() / sg_query_surface_pitch() as alternative\n} sg_pixelformat_info;\n\n/*\n    Runtime information about available optional features,\n    returned by sg_query_features()\n*/\ntypedef struct sg_features {\n    bool origin_top_left;               // framebuffer and texture origin is in top left corner\n    bool image_clamp_to_border;         // border color and clamp-to-border UV-wrap mode is supported\n    bool mrt_independent_blend_state;   // multiple-render-target rendering can use per-render-target blend state\n    bool mrt_independent_write_mask;    // multiple-render-target rendering can use per-render-target color write masks\n    bool storage_buffer;                // storage buffers are supported\n} sg_features;\n\n/*\n    Runtime information about resource limits, returned by sg_query_limit()\n*/\ntypedef struct sg_limits {\n    int max_image_size_2d;          // max width/height of SG_IMAGETYPE_2D images\n    int max_image_size_cube;        // max width/height of SG_IMAGETYPE_CUBE images\n    int max_image_size_3d;          // max width/height/depth of SG_IMAGETYPE_3D images\n    int max_image_size_array;       // max width/height of SG_IMAGETYPE_ARRAY images\n    int max_image_array_layers;     // max number of layers in SG_IMAGETYPE_ARRAY images\n    int max_vertex_attrs;           // max number of vertex attributes, clamped to SG_MAX_VERTEX_ATTRIBUTES\n    int gl_max_vertex_uniform_components;    // <= GL_MAX_VERTEX_UNIFORM_COMPONENTS (only on GL backends)\n    int gl_max_combined_texture_image_units; // <= GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (only on GL backends)\n} sg_limits;\n\n/*\n    sg_resource_state\n\n    The current state of a resource in its resource pool.\n    Resources start in the INITIAL state, which means the\n    pool slot is unoccupied and can be allocated. When a resource is\n    created, first an id is allocated, and the resource pool slot\n    is set to state ALLOC. After allocation, the resource is\n    initialized, which may result in the VALID or FAILED state. The\n    reason why allocation and initialization are separate is because\n    some resource types (e.g. buffers and images) might be asynchronously\n    initialized by the user application. If a resource which is not\n    in the VALID state is attempted to be used for rendering, rendering\n    operations will silently be dropped.\n\n    The special INVALID state is returned in sg_query_xxx_state() if no\n    resource object exists for the provided resource id.\n*/\ntypedef enum sg_resource_state {\n    SG_RESOURCESTATE_INITIAL,\n    SG_RESOURCESTATE_ALLOC,\n    SG_RESOURCESTATE_VALID,\n    SG_RESOURCESTATE_FAILED,\n    SG_RESOURCESTATE_INVALID,\n    _SG_RESOURCESTATE_FORCE_U32 = 0x7FFFFFFF\n} sg_resource_state;\n\n/*\n    sg_usage\n\n    A resource usage hint describing the update strategy of\n    buffers and images. This is used in the sg_buffer_desc.usage\n    and sg_image_desc.usage members when creating buffers\n    and images:\n\n    SG_USAGE_IMMUTABLE:     the resource will never be updated with\n                            new data, instead the content of the\n                            resource must be provided on creation\n    SG_USAGE_DYNAMIC:       the resource will be updated infrequently\n                            with new data (this could range from \"once\n                            after creation\", to \"quite often but not\n                            every frame\")\n    SG_USAGE_STREAM:        the resource will be updated each frame\n                            with new content\n\n    The rendering backends use this hint to prevent that the\n    CPU needs to wait for the GPU when attempting to update\n    a resource that might be currently accessed by the GPU.\n\n    Resource content is updated with the functions sg_update_buffer() or\n    sg_append_buffer() for buffer objects, and sg_update_image() for image\n    objects. For the sg_update_*() functions, only one update is allowed per\n    frame and resource object, while sg_append_buffer() can be called\n    multiple times per frame on the same buffer. The application must update\n    all data required for rendering (this means that the update data can be\n    smaller than the resource size, if only a part of the overall resource\n    size is used for rendering, you only need to make sure that the data that\n    *is* used is valid).\n\n    The default usage is SG_USAGE_IMMUTABLE.\n*/\ntypedef enum sg_usage {\n    _SG_USAGE_DEFAULT,      // value 0 reserved for default-init\n    SG_USAGE_IMMUTABLE,\n    SG_USAGE_DYNAMIC,\n    SG_USAGE_STREAM,\n    _SG_USAGE_NUM,\n    _SG_USAGE_FORCE_U32 = 0x7FFFFFFF\n} sg_usage;\n\n/*\n    sg_buffer_type\n\n    Indicates whether a buffer will be bound as vertex-,\n    index- or storage-buffer.\n\n    Used in the sg_buffer_desc.type member when creating a buffer.\n\n    The default value is SG_BUFFERTYPE_VERTEXBUFFER.\n*/\ntypedef enum sg_buffer_type {\n    _SG_BUFFERTYPE_DEFAULT,         // value 0 reserved for default-init\n    SG_BUFFERTYPE_VERTEXBUFFER,\n    SG_BUFFERTYPE_INDEXBUFFER,\n    SG_BUFFERTYPE_STORAGEBUFFER,\n    _SG_BUFFERTYPE_NUM,\n    _SG_BUFFERTYPE_FORCE_U32 = 0x7FFFFFFF\n} sg_buffer_type;\n\n/*\n    sg_index_type\n\n    Indicates whether indexed rendering (fetching vertex-indices from an\n    index buffer) is used, and if yes, the index data type (16- or 32-bits).\n    This is used in the sg_pipeline_desc.index_type member when creating a\n    pipeline object.\n\n    The default index type is SG_INDEXTYPE_NONE.\n*/\ntypedef enum sg_index_type {\n    _SG_INDEXTYPE_DEFAULT,   // value 0 reserved for default-init\n    SG_INDEXTYPE_NONE,\n    SG_INDEXTYPE_UINT16,\n    SG_INDEXTYPE_UINT32,\n    _SG_INDEXTYPE_NUM,\n    _SG_INDEXTYPE_FORCE_U32 = 0x7FFFFFFF\n} sg_index_type;\n\n/*\n    sg_image_type\n\n    Indicates the basic type of an image object (2D-texture, cubemap,\n    3D-texture or 2D-array-texture). Used in the sg_image_desc.type member when\n    creating an image, and in sg_shader_image_desc to describe a sampled texture\n    in the shader (both must match and will be checked in the validation layer\n    when calling sg_apply_bindings).\n\n    The default image type when creating an image is SG_IMAGETYPE_2D.\n*/\ntypedef enum sg_image_type {\n    _SG_IMAGETYPE_DEFAULT,  // value 0 reserved for default-init\n    SG_IMAGETYPE_2D,\n    SG_IMAGETYPE_CUBE,\n    SG_IMAGETYPE_3D,\n    SG_IMAGETYPE_ARRAY,\n    _SG_IMAGETYPE_NUM,\n    _SG_IMAGETYPE_FORCE_U32 = 0x7FFFFFFF\n} sg_image_type;\n\n/*\n    sg_image_sample_type\n\n    The basic data type of a texture sample as expected by a shader.\n    Must be provided in sg_shader_image_desc and used by the validation\n    layer in sg_apply_bindings() to check if the provided image object\n    is compatible with what the shader expects. Apart from the sokol-gfx\n    validation layer, WebGPU is the only backend API which actually requires\n    matching texture and sampler type to be provided upfront for validation\n    (other 3D APIs treat texture/sampler type mismatches as undefined behaviour).\n\n    NOTE that the following texture pixel formats require the use\n    of SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT, combined with a sampler\n    of type SG_SAMPLERTYPE_NONFILTERING:\n\n    - SG_PIXELFORMAT_R32F\n    - SG_PIXELFORMAT_RG32F\n    - SG_PIXELFORMAT_RGBA32F\n\n    (when using sokol-shdc, also check out the meta tags `@image_sample_type`\n    and `@sampler_type`)\n*/\ntypedef enum sg_image_sample_type {\n    _SG_IMAGESAMPLETYPE_DEFAULT,  // value 0 reserved for default-init\n    SG_IMAGESAMPLETYPE_FLOAT,\n    SG_IMAGESAMPLETYPE_DEPTH,\n    SG_IMAGESAMPLETYPE_SINT,\n    SG_IMAGESAMPLETYPE_UINT,\n    SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT,\n    _SG_IMAGESAMPLETYPE_NUM,\n    _SG_IMAGESAMPLETYPE_FORCE_U32 = 0x7FFFFFFF\n} sg_image_sample_type;\n\n/*\n    sg_sampler_type\n\n    The basic type of a texture sampler (sampling vs comparison) as\n    defined in a shader. Must be provided in sg_shader_sampler_desc.\n\n    sg_image_sample_type and sg_sampler_type for a texture/sampler\n    pair must be compatible with each other, specifically only\n    the following pairs are allowed:\n\n    - SG_IMAGESAMPLETYPE_FLOAT => (SG_SAMPLERTYPE_FILTERING or SG_SAMPLERTYPE_NONFILTERING)\n    - SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT => SG_SAMPLERTYPE_NONFILTERING\n    - SG_IMAGESAMPLETYPE_SINT => SG_SAMPLERTYPE_NONFILTERING\n    - SG_IMAGESAMPLETYPE_UINT => SG_SAMPLERTYPE_NONFILTERING\n    - SG_IMAGESAMPLETYPE_DEPTH => SG_SAMPLERTYPE_COMPARISON\n*/\ntypedef enum sg_sampler_type {\n    _SG_SAMPLERTYPE_DEFAULT,\n    SG_SAMPLERTYPE_FILTERING,\n    SG_SAMPLERTYPE_NONFILTERING,\n    SG_SAMPLERTYPE_COMPARISON,\n    _SG_SAMPLERTYPE_NUM,\n    _SG_SAMPLERTYPE_FORCE_U32,\n} sg_sampler_type;\n\n/*\n    sg_cube_face\n\n    The cubemap faces. Use these as indices in the sg_image_desc.content\n    array.\n*/\ntypedef enum sg_cube_face {\n    SG_CUBEFACE_POS_X,\n    SG_CUBEFACE_NEG_X,\n    SG_CUBEFACE_POS_Y,\n    SG_CUBEFACE_NEG_Y,\n    SG_CUBEFACE_POS_Z,\n    SG_CUBEFACE_NEG_Z,\n    SG_CUBEFACE_NUM,\n    _SG_CUBEFACE_FORCE_U32 = 0x7FFFFFFF\n} sg_cube_face;\n\n/*\n    sg_shader_stage\n\n    There are 2 shader stages: vertex- and fragment-shader-stage.\n    Each shader stage\n\n    - SG_MAX_SHADERSTAGE_UBS slots for applying uniform data\n    - SG_MAX_SHADERSTAGE_IMAGES slots for images used as textures\n    - SG_MAX_SHADERSTAGE_SAMPLERS slots for texture samplers\n    - SG_MAX_SHADERSTAGE_STORAGEBUFFERS slots for storage buffer bindings\n*/\ntypedef enum sg_shader_stage {\n    SG_SHADERSTAGE_VS,\n    SG_SHADERSTAGE_FS,\n    _SG_SHADERSTAGE_FORCE_U32 = 0x7FFFFFFF\n} sg_shader_stage;\n\n/*\n    sg_primitive_type\n\n    This is the common subset of 3D primitive types supported across all 3D\n    APIs. This is used in the sg_pipeline_desc.primitive_type member when\n    creating a pipeline object.\n\n    The default primitive type is SG_PRIMITIVETYPE_TRIANGLES.\n*/\ntypedef enum sg_primitive_type {\n    _SG_PRIMITIVETYPE_DEFAULT,  // value 0 reserved for default-init\n    SG_PRIMITIVETYPE_POINTS,\n    SG_PRIMITIVETYPE_LINES,\n    SG_PRIMITIVETYPE_LINE_STRIP,\n    SG_PRIMITIVETYPE_TRIANGLES,\n    SG_PRIMITIVETYPE_TRIANGLE_STRIP,\n    _SG_PRIMITIVETYPE_NUM,\n    _SG_PRIMITIVETYPE_FORCE_U32 = 0x7FFFFFFF\n} sg_primitive_type;\n\n/*\n    sg_filter\n\n    The filtering mode when sampling a texture image. This is\n    used in the sg_sampler_desc.min_filter, sg_sampler_desc.mag_filter\n    and sg_sampler_desc.mipmap_filter members when creating a sampler object.\n\n    For min_filter and mag_filter the default is SG_FILTER_NEAREST.\n\n    For mipmap_filter the default is SG_FILTER_NONE.\n*/\ntypedef enum sg_filter {\n    _SG_FILTER_DEFAULT, // value 0 reserved for default-init\n    SG_FILTER_NONE,     // FIXME: deprecated\n    SG_FILTER_NEAREST,\n    SG_FILTER_LINEAR,\n    _SG_FILTER_NUM,\n    _SG_FILTER_FORCE_U32 = 0x7FFFFFFF\n} sg_filter;\n\n/*\n    sg_wrap\n\n    The texture coordinates wrapping mode when sampling a texture\n    image. This is used in the sg_image_desc.wrap_u, .wrap_v\n    and .wrap_w members when creating an image.\n\n    The default wrap mode is SG_WRAP_REPEAT.\n\n    NOTE: SG_WRAP_CLAMP_TO_BORDER is not supported on all backends\n    and platforms. To check for support, call sg_query_features()\n    and check the \"clamp_to_border\" boolean in the returned\n    sg_features struct.\n\n    Platforms which don't support SG_WRAP_CLAMP_TO_BORDER will silently fall back\n    to SG_WRAP_CLAMP_TO_EDGE without a validation error.\n*/\ntypedef enum sg_wrap {\n    _SG_WRAP_DEFAULT,   // value 0 reserved for default-init\n    SG_WRAP_REPEAT,\n    SG_WRAP_CLAMP_TO_EDGE,\n    SG_WRAP_CLAMP_TO_BORDER,\n    SG_WRAP_MIRRORED_REPEAT,\n    _SG_WRAP_NUM,\n    _SG_WRAP_FORCE_U32 = 0x7FFFFFFF\n} sg_wrap;\n\n/*\n    sg_border_color\n\n    The border color to use when sampling a texture, and the UV wrap\n    mode is SG_WRAP_CLAMP_TO_BORDER.\n\n    The default border color is SG_BORDERCOLOR_OPAQUE_BLACK\n*/\ntypedef enum sg_border_color {\n    _SG_BORDERCOLOR_DEFAULT,    // value 0 reserved for default-init\n    SG_BORDERCOLOR_TRANSPARENT_BLACK,\n    SG_BORDERCOLOR_OPAQUE_BLACK,\n    SG_BORDERCOLOR_OPAQUE_WHITE,\n    _SG_BORDERCOLOR_NUM,\n    _SG_BORDERCOLOR_FORCE_U32 = 0x7FFFFFFF\n} sg_border_color;\n\n/*\n    sg_vertex_format\n\n    The data type of a vertex component. This is used to describe\n    the layout of vertex data when creating a pipeline object.\n*/\ntypedef enum sg_vertex_format {\n    SG_VERTEXFORMAT_INVALID,\n    SG_VERTEXFORMAT_FLOAT,\n    SG_VERTEXFORMAT_FLOAT2,\n    SG_VERTEXFORMAT_FLOAT3,\n    SG_VERTEXFORMAT_FLOAT4,\n    SG_VERTEXFORMAT_BYTE4,\n    SG_VERTEXFORMAT_BYTE4N,\n    SG_VERTEXFORMAT_UBYTE4,\n    SG_VERTEXFORMAT_UBYTE4N,\n    SG_VERTEXFORMAT_SHORT2,\n    SG_VERTEXFORMAT_SHORT2N,\n    SG_VERTEXFORMAT_USHORT2N,\n    SG_VERTEXFORMAT_SHORT4,\n    SG_VERTEXFORMAT_SHORT4N,\n    SG_VERTEXFORMAT_USHORT4N,\n    SG_VERTEXFORMAT_UINT10_N2,\n    SG_VERTEXFORMAT_HALF2,\n    SG_VERTEXFORMAT_HALF4,\n    _SG_VERTEXFORMAT_NUM,\n    _SG_VERTEXFORMAT_FORCE_U32 = 0x7FFFFFFF\n} sg_vertex_format;\n\n/*\n    sg_vertex_step\n\n    Defines whether the input pointer of a vertex input stream is advanced\n    'per vertex' or 'per instance'. The default step-func is\n    SG_VERTEXSTEP_PER_VERTEX. SG_VERTEXSTEP_PER_INSTANCE is used with\n    instanced-rendering.\n\n    The vertex-step is part of the vertex-layout definition\n    when creating pipeline objects.\n*/\ntypedef enum sg_vertex_step {\n    _SG_VERTEXSTEP_DEFAULT,     // value 0 reserved for default-init\n    SG_VERTEXSTEP_PER_VERTEX,\n    SG_VERTEXSTEP_PER_INSTANCE,\n    _SG_VERTEXSTEP_NUM,\n    _SG_VERTEXSTEP_FORCE_U32 = 0x7FFFFFFF\n} sg_vertex_step;\n\n/*\n    sg_uniform_type\n\n    The data type of a uniform block member. This is used to\n    describe the internal layout of uniform blocks when creating\n    a shader object.\n*/\ntypedef enum sg_uniform_type {\n    SG_UNIFORMTYPE_INVALID,\n    SG_UNIFORMTYPE_FLOAT,\n    SG_UNIFORMTYPE_FLOAT2,\n    SG_UNIFORMTYPE_FLOAT3,\n    SG_UNIFORMTYPE_FLOAT4,\n    SG_UNIFORMTYPE_INT,\n    SG_UNIFORMTYPE_INT2,\n    SG_UNIFORMTYPE_INT3,\n    SG_UNIFORMTYPE_INT4,\n    SG_UNIFORMTYPE_MAT4,\n    _SG_UNIFORMTYPE_NUM,\n    _SG_UNIFORMTYPE_FORCE_U32 = 0x7FFFFFFF\n} sg_uniform_type;\n\n/*\n    sg_uniform_layout\n\n    A hint for the interior memory layout of uniform blocks. This is\n    only really relevant for the GL backend where the internal layout\n    of uniform blocks must be known to sokol-gfx. For all other backends the\n    internal memory layout of uniform blocks doesn't matter, sokol-gfx\n    will just pass uniform data as a single memory blob to the\n    3D backend.\n\n    SG_UNIFORMLAYOUT_NATIVE (default)\n        Native layout means that a 'backend-native' memory layout\n        is used. For the GL backend this means that uniforms\n        are packed tightly in memory (e.g. there are no padding\n        bytes).\n\n    SG_UNIFORMLAYOUT_STD140\n        The memory layout is a subset of std140. Arrays are only\n        allowed for the FLOAT4, INT4 and MAT4. Alignment is as\n        is as follows:\n\n            FLOAT, INT:         4 byte alignment\n            FLOAT2, INT2:       8 byte alignment\n            FLOAT3, INT3:       16 byte alignment(!)\n            FLOAT4, INT4:       16 byte alignment\n            MAT4:               16 byte alignment\n            FLOAT4[], INT4[]:   16 byte alignment\n\n        The overall size of the uniform block must be a multiple\n        of 16.\n\n    For more information search for 'UNIFORM DATA LAYOUT' in the documentation block\n    at the start of the header.\n*/\ntypedef enum sg_uniform_layout {\n    _SG_UNIFORMLAYOUT_DEFAULT,     // value 0 reserved for default-init\n    SG_UNIFORMLAYOUT_NATIVE,       // default: layout depends on currently active backend\n    SG_UNIFORMLAYOUT_STD140,       // std140: memory layout according to std140\n    _SG_UNIFORMLAYOUT_NUM,\n    _SG_UNIFORMLAYOUT_FORCE_U32 = 0x7FFFFFFF\n} sg_uniform_layout;\n\n/*\n    sg_cull_mode\n\n    The face-culling mode, this is used in the\n    sg_pipeline_desc.cull_mode member when creating a\n    pipeline object.\n\n    The default cull mode is SG_CULLMODE_NONE\n*/\ntypedef enum sg_cull_mode {\n    _SG_CULLMODE_DEFAULT,   // value 0 reserved for default-init\n    SG_CULLMODE_NONE,\n    SG_CULLMODE_FRONT,\n    SG_CULLMODE_BACK,\n    _SG_CULLMODE_NUM,\n    _SG_CULLMODE_FORCE_U32 = 0x7FFFFFFF\n} sg_cull_mode;\n\n/*\n    sg_face_winding\n\n    The vertex-winding rule that determines a front-facing primitive. This\n    is used in the member sg_pipeline_desc.face_winding\n    when creating a pipeline object.\n\n    The default winding is SG_FACEWINDING_CW (clockwise)\n*/\ntypedef enum sg_face_winding {\n    _SG_FACEWINDING_DEFAULT,    // value 0 reserved for default-init\n    SG_FACEWINDING_CCW,\n    SG_FACEWINDING_CW,\n    _SG_FACEWINDING_NUM,\n    _SG_FACEWINDING_FORCE_U32 = 0x7FFFFFFF\n} sg_face_winding;\n\n/*\n    sg_compare_func\n\n    The compare-function for configuring depth- and stencil-ref tests\n    in pipeline objects, and for texture samplers which perform a comparison\n    instead of regular sampling operation.\n\n    sg_pipeline_desc\n        .depth\n            .compare\n        .stencil\n            .front.compare\n            .back.compar\n\n    sg_sampler_desc\n        .compare\n\n    The default compare func for depth- and stencil-tests is\n    SG_COMPAREFUNC_ALWAYS.\n\n    The default compare func for sampler is SG_COMPAREFUNC_NEVER.\n*/\ntypedef enum sg_compare_func {\n    _SG_COMPAREFUNC_DEFAULT,    // value 0 reserved for default-init\n    SG_COMPAREFUNC_NEVER,\n    SG_COMPAREFUNC_LESS,\n    SG_COMPAREFUNC_EQUAL,\n    SG_COMPAREFUNC_LESS_EQUAL,\n    SG_COMPAREFUNC_GREATER,\n    SG_COMPAREFUNC_NOT_EQUAL,\n    SG_COMPAREFUNC_GREATER_EQUAL,\n    SG_COMPAREFUNC_ALWAYS,\n    _SG_COMPAREFUNC_NUM,\n    _SG_COMPAREFUNC_FORCE_U32 = 0x7FFFFFFF\n} sg_compare_func;\n\n/*\n    sg_stencil_op\n\n    The operation performed on a currently stored stencil-value when a\n    comparison test passes or fails. This is used when creating a pipeline\n    object in the members:\n\n    sg_pipeline_desc\n        .stencil\n            .front\n                .fail_op\n                .depth_fail_op\n                .pass_op\n            .back\n                .fail_op\n                .depth_fail_op\n                .pass_op\n\n    The default value is SG_STENCILOP_KEEP.\n*/\ntypedef enum sg_stencil_op {\n    _SG_STENCILOP_DEFAULT,      // value 0 reserved for default-init\n    SG_STENCILOP_KEEP,\n    SG_STENCILOP_ZERO,\n    SG_STENCILOP_REPLACE,\n    SG_STENCILOP_INCR_CLAMP,\n    SG_STENCILOP_DECR_CLAMP,\n    SG_STENCILOP_INVERT,\n    SG_STENCILOP_INCR_WRAP,\n    SG_STENCILOP_DECR_WRAP,\n    _SG_STENCILOP_NUM,\n    _SG_STENCILOP_FORCE_U32 = 0x7FFFFFFF\n} sg_stencil_op;\n\n/*\n    sg_blend_factor\n\n    The source and destination factors in blending operations.\n    This is used in the following members when creating a pipeline object:\n\n    sg_pipeline_desc\n        .colors[i]\n            .blend\n                .src_factor_rgb\n                .dst_factor_rgb\n                .src_factor_alpha\n                .dst_factor_alpha\n\n    The default value is SG_BLENDFACTOR_ONE for source\n    factors, and SG_BLENDFACTOR_ZERO for destination factors.\n*/\ntypedef enum sg_blend_factor {\n    _SG_BLENDFACTOR_DEFAULT,    // value 0 reserved for default-init\n    SG_BLENDFACTOR_ZERO,\n    SG_BLENDFACTOR_ONE,\n    SG_BLENDFACTOR_SRC_COLOR,\n    SG_BLENDFACTOR_ONE_MINUS_SRC_COLOR,\n    SG_BLENDFACTOR_SRC_ALPHA,\n    SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,\n    SG_BLENDFACTOR_DST_COLOR,\n    SG_BLENDFACTOR_ONE_MINUS_DST_COLOR,\n    SG_BLENDFACTOR_DST_ALPHA,\n    SG_BLENDFACTOR_ONE_MINUS_DST_ALPHA,\n    SG_BLENDFACTOR_SRC_ALPHA_SATURATED,\n    SG_BLENDFACTOR_BLEND_COLOR,\n    SG_BLENDFACTOR_ONE_MINUS_BLEND_COLOR,\n    SG_BLENDFACTOR_BLEND_ALPHA,\n    SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA,\n    _SG_BLENDFACTOR_NUM,\n    _SG_BLENDFACTOR_FORCE_U32 = 0x7FFFFFFF\n} sg_blend_factor;\n\n/*\n    sg_blend_op\n\n    Describes how the source and destination values are combined in the\n    fragment blending operation. It is used in the following members when\n    creating a pipeline object:\n\n    sg_pipeline_desc\n        .colors[i]\n            .blend\n                .op_rgb\n                .op_alpha\n\n    The default value is SG_BLENDOP_ADD.\n*/\ntypedef enum sg_blend_op {\n    _SG_BLENDOP_DEFAULT,    // value 0 reserved for default-init\n    SG_BLENDOP_ADD,\n    SG_BLENDOP_SUBTRACT,\n    SG_BLENDOP_REVERSE_SUBTRACT,\n    _SG_BLENDOP_NUM,\n    _SG_BLENDOP_FORCE_U32 = 0x7FFFFFFF\n} sg_blend_op;\n\n/*\n    sg_color_mask\n\n    Selects the active color channels when writing a fragment color to the\n    framebuffer. This is used in the members\n    sg_pipeline_desc.colors[i].write_mask when creating a pipeline object.\n\n    The default colormask is SG_COLORMASK_RGBA (write all colors channels)\n\n    NOTE: since the color mask value 0 is reserved for the default value\n    (SG_COLORMASK_RGBA), use SG_COLORMASK_NONE if all color channels\n    should be disabled.\n*/\ntypedef enum sg_color_mask {\n    _SG_COLORMASK_DEFAULT = 0,    // value 0 reserved for default-init\n    SG_COLORMASK_NONE   = 0x10,   // special value for 'all channels disabled\n    SG_COLORMASK_R      = 0x1,\n    SG_COLORMASK_G      = 0x2,\n    SG_COLORMASK_RG     = 0x3,\n    SG_COLORMASK_B      = 0x4,\n    SG_COLORMASK_RB     = 0x5,\n    SG_COLORMASK_GB     = 0x6,\n    SG_COLORMASK_RGB    = 0x7,\n    SG_COLORMASK_A      = 0x8,\n    SG_COLORMASK_RA     = 0x9,\n    SG_COLORMASK_GA     = 0xA,\n    SG_COLORMASK_RGA    = 0xB,\n    SG_COLORMASK_BA     = 0xC,\n    SG_COLORMASK_RBA    = 0xD,\n    SG_COLORMASK_GBA    = 0xE,\n    SG_COLORMASK_RGBA   = 0xF,\n    _SG_COLORMASK_FORCE_U32 = 0x7FFFFFFF\n} sg_color_mask;\n\n/*\n    sg_load_action\n\n    Defines the load action that should be performed at the start of a render pass:\n\n    SG_LOADACTION_CLEAR:        clear the render target\n    SG_LOADACTION_LOAD:         load the previous content of the render target\n    SG_LOADACTION_DONTCARE:     leave the render target in an undefined state\n\n    This is used in the sg_pass_action structure.\n\n    The default load action for all pass attachments is SG_LOADACTION_CLEAR,\n    with the values rgba = { 0.5f, 0.5f, 0.5f, 1.0f }, depth=1.0f and stencil=0.\n\n    If you want to override the default behaviour, it is important to not\n    only set the clear color, but the 'action' field as well (as long as this\n    is _SG_LOADACTION_DEFAULT, the value fields will be ignored).\n*/\ntypedef enum sg_load_action {\n    _SG_LOADACTION_DEFAULT,\n    SG_LOADACTION_CLEAR,\n    SG_LOADACTION_LOAD,\n    SG_LOADACTION_DONTCARE,\n    _SG_LOADACTION_FORCE_U32 = 0x7FFFFFFF\n} sg_load_action;\n\n/*\n    sg_store_action\n\n    Defines the store action that be performed at the end of a render pass:\n\n    SG_STOREACTION_STORE:       store the rendered content to the color attachment image\n    SG_STOREACTION_DONTCARE:    allows the GPU to discard the rendered content\n*/\ntypedef enum sg_store_action {\n    _SG_STOREACTION_DEFAULT,\n    SG_STOREACTION_STORE,\n    SG_STOREACTION_DONTCARE,\n    _SG_STOREACTION_FORCE_U32 = 0x7FFFFFFF\n} sg_store_action;\n\n\n/*\n    sg_pass_action\n\n    The sg_pass_action struct defines the actions to be performed\n    at the start and end of a render pass.\n\n    - at the start of the pass: whether the render targets should be cleared,\n      loaded with their previous content, or start in an undefined state\n    - for clear operations: the clear value (color, depth, or stencil values)\n    - at the end of the pass: whether the rendering result should be\n      stored back into the render target or discarded\n*/\ntypedef struct sg_color_attachment_action {\n    sg_load_action load_action;         // default: SG_LOADACTION_CLEAR\n    sg_store_action store_action;       // default: SG_STOREACTION_STORE\n    sg_color clear_value;               // default: { 0.5f, 0.5f, 0.5f, 1.0f }\n} sg_color_attachment_action;\n\ntypedef struct sg_depth_attachment_action {\n    sg_load_action load_action;         // default: SG_LOADACTION_CLEAR\n    sg_store_action store_action;       // default: SG_STOREACTION_DONTCARE\n    float clear_value;                  // default: 1.0\n} sg_depth_attachment_action;\n\ntypedef struct sg_stencil_attachment_action {\n    sg_load_action load_action;         // default: SG_LOADACTION_CLEAR\n    sg_store_action store_action;       // default: SG_STOREACTION_DONTCARE\n    uint8_t clear_value;                // default: 0\n} sg_stencil_attachment_action;\n\ntypedef struct sg_pass_action {\n    sg_color_attachment_action colors[SG_MAX_COLOR_ATTACHMENTS];\n    sg_depth_attachment_action depth;\n    sg_stencil_attachment_action stencil;\n} sg_pass_action;\n\n/*\n    sg_swapchain\n\n    Used in sg_begin_pass() to provide details about an external swapchain\n    (pixel formats, sample count and backend-API specific render surface objects).\n\n    The following information must be provided:\n\n    - the width and height of the swapchain surfaces in number of pixels,\n    - the pixel format of the render- and optional msaa-resolve-surface\n    - the pixel format of the optional depth- or depth-stencil-surface\n    - the MSAA sample count for the render and depth-stencil surface\n\n    If the pixel formats and MSAA sample counts are left zero-initialized,\n    their defaults are taken from the sg_environment struct provided in the\n    sg_setup() call.\n\n    The width and height *must* be > 0.\n\n    Additionally the following backend API specific objects must be passed in\n    as 'type erased' void pointers:\n\n    GL: on all GL backends, a GL framebuffer object must be provided. This\n    can be zero for the default framebuffer.\n\n    D3D11:\n        - an ID3D11RenderTargetView for the rendering surface, without\n          MSAA rendering this surface will also be displayed\n        - an optional ID3D11DepthStencilView for the depth- or depth/stencil\n          buffer surface\n        - when MSAA rendering is used, another ID3D11RenderTargetView\n          which serves as MSAA resolve target and will be displayed\n\n    WebGPU (same as D3D11, except different types)\n        - a WGPUTextureView for the rendering surface, without\n          MSAA rendering this surface will also be displayed\n        - an optional WGPUTextureView for the depth- or depth/stencil\n          buffer surface\n        - when MSAA rendering is used, another WGPUTextureView\n          which serves as MSAA resolve target and will be displayed\n\n    Metal (NOTE that the rolves of provided surfaces is slightly different\n    than on D3D11 or WebGPU in case of MSAA vs non-MSAA rendering):\n\n        - A current CAMetalDrawable (NOT an MTLDrawable!) which will be presented.\n          This will either be rendered to directly (if no MSAA is used), or serve\n          as MSAA-resolve target.\n        - an optional MTLTexture for the depth- or depth-stencil buffer\n        - an optional multisampled MTLTexture which serves as intermediate\n          rendering surface which will then be resolved into the\n          CAMetalDrawable.\n\n    NOTE that for Metal you must use an ObjC __bridge cast to\n    properly tunnel the ObjC object handle through a C void*, e.g.:\n\n        swapchain.metal.current_drawable = (__bridge const void*) [mtkView currentDrawable];\n\n    On all other backends you shouldn't need to mess with the reference count.\n\n    It's a good practice to write a helper function which returns an initialized\n    sg_swapchain structs, which can then be plugged directly into\n    sg_pass.swapchain. Look at the function sglue_swapchain() in the sokol_glue.h\n    as an example.\n*/\ntypedef struct sg_metal_swapchain {\n    const void* current_drawable;       // CAMetalDrawable (NOT MTLDrawable!!!)\n    const void* depth_stencil_texture;  // MTLTexture\n    const void* msaa_color_texture;     // MTLTexture\n} sg_metal_swapchain;\n\ntypedef struct sg_d3d11_swapchain {\n    const void* render_view;            // ID3D11RenderTargetView\n    const void* resolve_view;           // ID3D11RenderTargetView\n    const void* depth_stencil_view;     // ID3D11DepthStencilView\n} sg_d3d11_swapchain;\n\ntypedef struct sg_wgpu_swapchain {\n    const void* render_view;            // WGPUTextureView\n    const void* resolve_view;           // WGPUTextureView\n    const void* depth_stencil_view;     // WGPUTextureView\n} sg_wgpu_swapchain;\n\ntypedef struct sg_gl_swapchain {\n    uint32_t framebuffer;               // GL framebuffer object\n} sg_gl_swapchain;\n\ntypedef struct sg_swapchain {\n    int width;\n    int height;\n    int sample_count;\n    sg_pixel_format color_format;\n    sg_pixel_format depth_format;\n    sg_metal_swapchain metal;\n    sg_d3d11_swapchain d3d11;\n    sg_wgpu_swapchain wgpu;\n    sg_gl_swapchain gl;\n} sg_swapchain;\n\n/*\n    sg_pass\n\n    The sg_pass structure is passed as argument into the sg_begin_pass()\n    function.\n\n    For an offscreen rendering pass, an sg_pass_action struct and sg_attachments\n    object must be provided, and for swapchain passes, and sg_pass_action and\n    an sg_swapchain struct. It is an error to provide both an sg_attachments\n    handle and an initialized sg_swapchain struct in the same sg_begin_pass().\n\n    An sg_begin_pass() call for an offscreen pass would look like this (where\n    `attachments` is an sg_attachments handle):\n\n        sg_begin_pass(&(sg_pass){\n            .action = { ... },\n            .attachments = attachments,\n        });\n\n    ...and a swapchain render pass would look like this (using the sokol_glue.h\n    helper function sglue_swapchain() which gets the swapchain properties from\n    sokol_app.h):\n\n        sg_begin_pass(&(sg_pass){\n            .action = { ... },\n            .swapchain = sglue_swapchain(),\n        });\n\n    You can also omit the .action object to get default pass action behaviour\n    (clear to color=grey, depth=1 and stencil=0).\n*/\ntypedef struct sg_pass {\n    uint32_t _start_canary;\n    sg_pass_action action;\n    sg_attachments attachments;\n    sg_swapchain swapchain;\n    const char* label;\n    uint32_t _end_canary;\n} sg_pass;\n\n/*\n    sg_bindings\n\n    The sg_bindings structure defines the resource binding slots\n    of the sokol_gfx render pipeline, used as argument to the\n    sg_apply_bindings() function.\n\n    A resource binding struct contains:\n\n    - 1..N vertex buffers\n    - 0..N vertex buffer offsets\n    - 0..1 index buffers\n    - 0..1 index buffer offsets\n    - 0..N vertex shader stage images\n    - 0..N vertex shader stage samplers\n    - 0..N vertex shader storage buffers\n    - 0..N fragment shader stage images\n    - 0..N fragment shader stage samplers\n    - 0..N fragment shader storage buffers\n\n    For the max number of bindings, see the constant definitions:\n\n    - SG_MAX_VERTEX_BUFFERS\n    - SG_MAX_SHADERSTAGE_IMAGES\n    - SG_MAX_SHADERSTAGE_SAMPLERS\n    - SG_MAX_SHADERSTAGE_STORAGEBUFFERS\n\n    The optional buffer offsets can be used to put different unrelated\n    chunks of vertex- and/or index-data into the same buffer objects.\n*/\ntypedef struct sg_stage_bindings {\n    sg_image images[SG_MAX_SHADERSTAGE_IMAGES];\n    sg_sampler samplers[SG_MAX_SHADERSTAGE_SAMPLERS];\n    sg_buffer storage_buffers[SG_MAX_SHADERSTAGE_STORAGEBUFFERS];\n} sg_stage_bindings;\n\ntypedef struct sg_bindings {\n    uint32_t _start_canary;\n    sg_buffer vertex_buffers[SG_MAX_VERTEX_BUFFERS];\n    int vertex_buffer_offsets[SG_MAX_VERTEX_BUFFERS];\n    sg_buffer index_buffer;\n    int index_buffer_offset;\n    sg_stage_bindings vs;\n    sg_stage_bindings fs;\n    uint32_t _end_canary;\n} sg_bindings;\n\n/*\n    sg_buffer_desc\n\n    Creation parameters for sg_buffer objects, used in the\n    sg_make_buffer() call.\n\n    The default configuration is:\n\n    .size:      0       (*must* be >0 for buffers without data)\n    .type:      SG_BUFFERTYPE_VERTEXBUFFER\n    .usage:     SG_USAGE_IMMUTABLE\n    .data.ptr   0       (*must* be valid for immutable buffers)\n    .data.size  0       (*must* be > 0 for immutable buffers)\n    .label      0       (optional string label)\n\n    For immutable buffers which are initialized with initial data,\n    keep the .size item zero-initialized, and set the size together with the\n    pointer to the initial data in the .data item.\n\n    For mutable buffers without initial data, keep the .data item\n    zero-initialized, and set the buffer size in the .size item instead.\n\n    You can also set both size values, but currently both size values must\n    be identical (this may change in the future when the dynamic resource\n    management may become more flexible).\n\n    ADVANCED TOPIC: Injecting native 3D-API buffers:\n\n    The following struct members allow to inject your own GL, Metal\n    or D3D11 buffers into sokol_gfx:\n\n    .gl_buffers[SG_NUM_INFLIGHT_FRAMES]\n    .mtl_buffers[SG_NUM_INFLIGHT_FRAMES]\n    .d3d11_buffer\n\n    You must still provide all other struct items except the .data item, and\n    these must match the creation parameters of the native buffers you\n    provide. For SG_USAGE_IMMUTABLE, only provide a single native 3D-API\n    buffer, otherwise you need to provide SG_NUM_INFLIGHT_FRAMES buffers\n    (only for GL and Metal, not D3D11). Providing multiple buffers for GL and\n    Metal is necessary because sokol_gfx will rotate through them when\n    calling sg_update_buffer() to prevent lock-stalls.\n\n    Note that it is expected that immutable injected buffer have already been\n    initialized with content, and the .content member must be 0!\n\n    Also you need to call sg_reset_state_cache() after calling native 3D-API\n    functions, and before calling any sokol_gfx function.\n*/\ntypedef struct sg_buffer_desc {\n    uint32_t _start_canary;\n    size_t size;\n    sg_buffer_type type;\n    sg_usage usage;\n    sg_range data;\n    const char* label;\n    // optionally inject backend-specific resources\n    uint32_t gl_buffers[SG_NUM_INFLIGHT_FRAMES];\n    const void* mtl_buffers[SG_NUM_INFLIGHT_FRAMES];\n    const void* d3d11_buffer;\n    const void* wgpu_buffer;\n    uint32_t _end_canary;\n} sg_buffer_desc;\n\n/*\n    sg_image_data\n\n    Defines the content of an image through a 2D array of sg_range structs.\n    The first array dimension is the cubemap face, and the second array\n    dimension the mipmap level.\n*/\ntypedef struct sg_image_data {\n    sg_range subimage[SG_CUBEFACE_NUM][SG_MAX_MIPMAPS];\n} sg_image_data;\n\n/*\n    sg_image_desc\n\n    Creation parameters for sg_image objects, used in the sg_make_image() call.\n\n    The default configuration is:\n\n    .type:              SG_IMAGETYPE_2D\n    .render_target:     false\n    .width              0 (must be set to >0)\n    .height             0 (must be set to >0)\n    .num_slices         1 (3D textures: depth; array textures: number of layers)\n    .num_mipmaps:       1\n    .usage:             SG_USAGE_IMMUTABLE\n    .pixel_format:      SG_PIXELFORMAT_RGBA8 for textures, or sg_desc.environment.defaults.color_format for render targets\n    .sample_count:      1 for textures, or sg_desc.environment.defaults.sample_count for render targets\n    .data               an sg_image_data struct to define the initial content\n    .label              0 (optional string label for trace hooks)\n\n    Q: Why is the default sample_count for render targets identical with the\n    \"default sample count\" from sg_desc.environment.defaults.sample_count?\n\n    A: So that it matches the default sample count in pipeline objects. Even\n    though it is a bit strange/confusing that offscreen render targets by default\n    get the same sample count as 'default swapchains', but it's better that\n    an offscreen render target created with default parameters matches\n    a pipeline object created with default parameters.\n\n    NOTE:\n\n    Images with usage SG_USAGE_IMMUTABLE must be fully initialized by\n    providing a valid .data member which points to initialization data.\n\n    ADVANCED TOPIC: Injecting native 3D-API textures:\n\n    The following struct members allow to inject your own GL, Metal or D3D11\n    textures into sokol_gfx:\n\n    .gl_textures[SG_NUM_INFLIGHT_FRAMES]\n    .mtl_textures[SG_NUM_INFLIGHT_FRAMES]\n    .d3d11_texture\n    .d3d11_shader_resource_view\n    .wgpu_texture\n    .wgpu_texture_view\n\n    For GL, you can also specify the texture target or leave it empty to use\n    the default texture target for the image type (GL_TEXTURE_2D for\n    SG_IMAGETYPE_2D etc)\n\n    For D3D11 and WebGPU, either only provide a texture, or both a texture and\n    shader-resource-view / texture-view object. If you want to use access the\n    injected texture in a shader you *must* provide a shader-resource-view.\n\n    The same rules apply as for injecting native buffers (see sg_buffer_desc\n    documentation for more details).\n*/\ntypedef struct sg_image_desc {\n    uint32_t _start_canary;\n    sg_image_type type;\n    bool render_target;\n    int width;\n    int height;\n    int num_slices;\n    int num_mipmaps;\n    sg_usage usage;\n    sg_pixel_format pixel_format;\n    int sample_count;\n    sg_image_data data;\n    const char* label;\n    // optionally inject backend-specific resources\n    uint32_t gl_textures[SG_NUM_INFLIGHT_FRAMES];\n    uint32_t gl_texture_target;\n    const void* mtl_textures[SG_NUM_INFLIGHT_FRAMES];\n    const void* d3d11_texture;\n    const void* d3d11_shader_resource_view;\n    const void* wgpu_texture;\n    const void* wgpu_texture_view;\n    uint32_t _end_canary;\n} sg_image_desc;\n\n/*\n    sg_sampler_desc\n\n    Creation parameters for sg_sampler objects, used in the sg_make_sampler() call\n\n    .min_filter:        SG_FILTER_NEAREST\n    .mag_filter:        SG_FILTER_NEAREST\n    .mipmap_filter      SG_FILTER_NONE\n    .wrap_u:            SG_WRAP_REPEAT\n    .wrap_v:            SG_WRAP_REPEAT\n    .wrap_w:            SG_WRAP_REPEAT (only SG_IMAGETYPE_3D)\n    .min_lod            0.0f\n    .max_lod            FLT_MAX\n    .border_color       SG_BORDERCOLOR_OPAQUE_BLACK\n    .compare            SG_COMPAREFUNC_NEVER\n    .max_anisotropy     1 (must be 1..16)\n\n*/\ntypedef struct sg_sampler_desc {\n    uint32_t _start_canary;\n    sg_filter min_filter;\n    sg_filter mag_filter;\n    sg_filter mipmap_filter;\n    sg_wrap wrap_u;\n    sg_wrap wrap_v;\n    sg_wrap wrap_w;\n    float min_lod;\n    float max_lod;\n    sg_border_color border_color;\n    sg_compare_func compare;\n    uint32_t max_anisotropy;\n    const char* label;\n    // optionally inject backend-specific resources\n    uint32_t gl_sampler;\n    const void* mtl_sampler;\n    const void* d3d11_sampler;\n    const void* wgpu_sampler;\n    uint32_t _end_canary;\n} sg_sampler_desc;\n\n/*\n    sg_shader_desc\n\n    The structure sg_shader_desc defines all creation parameters for shader\n    programs, used as input to the sg_make_shader() function:\n\n    - reflection information for vertex attributes (vertex shader inputs):\n        - vertex attribute name (only optionally used by GLES3 and GL)\n        - a semantic name and index (required for D3D11)\n    - for each shader-stage (vertex and fragment):\n        - the shader source or bytecode\n        - an optional entry function name\n        - an optional compile target (only for D3D11 when source is provided,\n          defaults are \"vs_4_0\" and \"ps_4_0\")\n        - reflection info for each uniform block used by the shader stage:\n            - the size of the uniform block in bytes\n            - a memory layout hint (native vs std140, only required for GL backends)\n            - reflection info for each uniform block member (only required for GL backends):\n                - member name\n                - member type (SG_UNIFORMTYPE_xxx)\n                - if the member is an array, the number of array items\n        - reflection info for textures used in the shader stage:\n            - the image type (SG_IMAGETYPE_xxx)\n            - the image-sample type (SG_IMAGESAMPLETYPE_xxx, default is SG_IMAGESAMPLETYPE_FLOAT)\n            - whether the shader expects a multisampled texture\n        - reflection info for samplers used in the shader stage:\n            - the sampler type (SG_SAMPLERTYPE_xxx)\n        - reflection info for each image-sampler-pair used by the shader:\n            - the texture slot of the involved texture\n            - the sampler slot of the involved sampler\n            - for GLSL only: the name of the combined image-sampler object\n        - reflection info for each storage-buffer used by the shader:\n            - whether the storage buffer is readonly (currently this\n              must be true)\n\n    For all GL backends, shader source-code must be provided. For D3D11 and Metal,\n    either shader source-code or byte-code can be provided.\n\n    For D3D11, if source code is provided, the d3dcompiler_47.dll will be loaded\n    on demand. If this fails, shader creation will fail. When compiling HLSL\n    source code, you can provide an optional target string via\n    sg_shader_stage_desc.d3d11_target, the default target is \"vs_4_0\" for the\n    vertex shader stage and \"ps_4_0\" for the pixel shader stage.\n*/\ntypedef struct sg_shader_attr_desc {\n    const char* name;           // GLSL vertex attribute name (optional)\n    const char* sem_name;       // HLSL semantic name\n    int sem_index;              // HLSL semantic index\n} sg_shader_attr_desc;\n\ntypedef struct sg_shader_uniform_desc {\n    const char* name;\n    sg_uniform_type type;\n    int array_count;\n} sg_shader_uniform_desc;\n\ntypedef struct sg_shader_uniform_block_desc {\n    size_t size;\n    sg_uniform_layout layout;\n    sg_shader_uniform_desc uniforms[SG_MAX_UB_MEMBERS];\n} sg_shader_uniform_block_desc;\n\ntypedef struct sg_shader_storage_buffer_desc {\n    bool used;\n    bool readonly;\n} sg_shader_storage_buffer_desc;\n\ntypedef struct sg_shader_image_desc {\n    bool used;\n    bool multisampled;\n    sg_image_type image_type;\n    sg_image_sample_type sample_type;\n} sg_shader_image_desc;\n\ntypedef struct sg_shader_sampler_desc {\n    bool used;\n    sg_sampler_type sampler_type;\n} sg_shader_sampler_desc;\n\ntypedef struct sg_shader_image_sampler_pair_desc {\n    bool used;\n    int image_slot;\n    int sampler_slot;\n    const char* glsl_name;\n} sg_shader_image_sampler_pair_desc;\n\ntypedef struct sg_shader_stage_desc {\n    const char* source;\n    sg_range bytecode;\n    const char* entry;\n    const char* d3d11_target;\n    sg_shader_uniform_block_desc uniform_blocks[SG_MAX_SHADERSTAGE_UBS];\n    sg_shader_storage_buffer_desc storage_buffers[SG_MAX_SHADERSTAGE_STORAGEBUFFERS];\n    sg_shader_image_desc images[SG_MAX_SHADERSTAGE_IMAGES];\n    sg_shader_sampler_desc samplers[SG_MAX_SHADERSTAGE_SAMPLERS];\n    sg_shader_image_sampler_pair_desc image_sampler_pairs[SG_MAX_SHADERSTAGE_IMAGESAMPLERPAIRS];\n} sg_shader_stage_desc;\n\ntypedef struct sg_shader_desc {\n    uint32_t _start_canary;\n    sg_shader_attr_desc attrs[SG_MAX_VERTEX_ATTRIBUTES];\n    sg_shader_stage_desc vs;\n    sg_shader_stage_desc fs;\n    const char* label;\n    uint32_t _end_canary;\n} sg_shader_desc;\n\n/*\n    sg_pipeline_desc\n\n    The sg_pipeline_desc struct defines all creation parameters for an\n    sg_pipeline object, used as argument to the sg_make_pipeline() function:\n\n    - the vertex layout for all input vertex buffers\n    - a shader object\n    - the 3D primitive type (points, lines, triangles, ...)\n    - the index type (none, 16- or 32-bit)\n    - all the fixed-function-pipeline state (depth-, stencil-, blend-state, etc...)\n\n    If the vertex data has no gaps between vertex components, you can omit\n    the .layout.buffers[].stride and layout.attrs[].offset items (leave them\n    default-initialized to 0), sokol-gfx will then compute the offsets and\n    strides from the vertex component formats (.layout.attrs[].format).\n    Please note that ALL vertex attribute offsets must be 0 in order for the\n    automatic offset computation to kick in.\n\n    The default configuration is as follows:\n\n    .shader:            0 (must be initialized with a valid sg_shader id!)\n    .layout:\n        .buffers[]:         vertex buffer layouts\n            .stride:        0 (if no stride is given it will be computed)\n            .step_func      SG_VERTEXSTEP_PER_VERTEX\n            .step_rate      1\n        .attrs[]:           vertex attribute declarations\n            .buffer_index   0 the vertex buffer bind slot\n            .offset         0 (offsets can be omitted if the vertex layout has no gaps)\n            .format         SG_VERTEXFORMAT_INVALID (must be initialized!)\n    .depth:\n        .pixel_format:      sg_desc.context.depth_format\n        .compare:           SG_COMPAREFUNC_ALWAYS\n        .write_enabled:     false\n        .bias:              0.0f\n        .bias_slope_scale:  0.0f\n        .bias_clamp:        0.0f\n    .stencil:\n        .enabled:           false\n        .front/back:\n            .compare:       SG_COMPAREFUNC_ALWAYS\n            .fail_op:       SG_STENCILOP_KEEP\n            .depth_fail_op: SG_STENCILOP_KEEP\n            .pass_op:       SG_STENCILOP_KEEP\n        .read_mask:         0\n        .write_mask:        0\n        .ref:               0\n    .color_count            1\n    .colors[0..color_count]\n        .pixel_format       sg_desc.context.color_format\n        .write_mask:        SG_COLORMASK_RGBA\n        .blend:\n            .enabled:           false\n            .src_factor_rgb:    SG_BLENDFACTOR_ONE\n            .dst_factor_rgb:    SG_BLENDFACTOR_ZERO\n            .op_rgb:            SG_BLENDOP_ADD\n            .src_factor_alpha:  SG_BLENDFACTOR_ONE\n            .dst_factor_alpha:  SG_BLENDFACTOR_ZERO\n            .op_alpha:          SG_BLENDOP_ADD\n    .primitive_type:            SG_PRIMITIVETYPE_TRIANGLES\n    .index_type:                SG_INDEXTYPE_NONE\n    .cull_mode:                 SG_CULLMODE_NONE\n    .face_winding:              SG_FACEWINDING_CW\n    .sample_count:              sg_desc.context.sample_count\n    .blend_color:               (sg_color) { 0.0f, 0.0f, 0.0f, 0.0f }\n    .alpha_to_coverage_enabled: false\n    .label  0       (optional string label for trace hooks)\n*/\ntypedef struct sg_vertex_buffer_layout_state {\n    int stride;\n    sg_vertex_step step_func;\n    int step_rate;\n} sg_vertex_buffer_layout_state;\n\ntypedef struct sg_vertex_attr_state {\n    int buffer_index;\n    int offset;\n    sg_vertex_format format;\n} sg_vertex_attr_state;\n\ntypedef struct sg_vertex_layout_state {\n    sg_vertex_buffer_layout_state buffers[SG_MAX_VERTEX_BUFFERS];\n    sg_vertex_attr_state attrs[SG_MAX_VERTEX_ATTRIBUTES];\n} sg_vertex_layout_state;\n\ntypedef struct sg_stencil_face_state {\n    sg_compare_func compare;\n    sg_stencil_op fail_op;\n    sg_stencil_op depth_fail_op;\n    sg_stencil_op pass_op;\n} sg_stencil_face_state;\n\ntypedef struct sg_stencil_state {\n    bool enabled;\n    sg_stencil_face_state front;\n    sg_stencil_face_state back;\n    uint8_t read_mask;\n    uint8_t write_mask;\n    uint8_t ref;\n} sg_stencil_state;\n\ntypedef struct sg_depth_state {\n    sg_pixel_format pixel_format;\n    sg_compare_func compare;\n    bool write_enabled;\n    float bias;\n    float bias_slope_scale;\n    float bias_clamp;\n} sg_depth_state;\n\ntypedef struct sg_blend_state {\n    bool enabled;\n    sg_blend_factor src_factor_rgb;\n    sg_blend_factor dst_factor_rgb;\n    sg_blend_op op_rgb;\n    sg_blend_factor src_factor_alpha;\n    sg_blend_factor dst_factor_alpha;\n    sg_blend_op op_alpha;\n} sg_blend_state;\n\ntypedef struct sg_color_target_state {\n    sg_pixel_format pixel_format;\n    sg_color_mask write_mask;\n    sg_blend_state blend;\n} sg_color_target_state;\n\ntypedef struct sg_pipeline_desc {\n    uint32_t _start_canary;\n    sg_shader shader;\n    sg_vertex_layout_state layout;\n    sg_depth_state depth;\n    sg_stencil_state stencil;\n    int color_count;\n    sg_color_target_state colors[SG_MAX_COLOR_ATTACHMENTS];\n    sg_primitive_type primitive_type;\n    sg_index_type index_type;\n    sg_cull_mode cull_mode;\n    sg_face_winding face_winding;\n    int sample_count;\n    sg_color blend_color;\n    bool alpha_to_coverage_enabled;\n    const char* label;\n    uint32_t _end_canary;\n} sg_pipeline_desc;\n\n/*\n    sg_attachments_desc\n\n    Creation parameters for an sg_attachments object, used as argument to the\n    sg_make_attachments() function.\n\n    An attachments object bundles 0..4 color attachments, 0..4 msaa-resolve\n    attachments, and none or one depth-stencil attachmente for use\n    in a render pass. At least one color attachment or one depth-stencil\n    attachment must be provided (no color attachment and a depth-stencil\n    attachment is useful for a depth-only render pass).\n\n    Each attachment definition consists of an image object, and two additional indices\n    describing which subimage the pass will render into: one mipmap index, and if the image\n    is a cubemap, array-texture or 3D-texture, the face-index, array-layer or\n    depth-slice.\n\n    All attachments must have the same width and height.\n\n    All color attachments and the depth-stencil attachment must have the\n    same sample count.\n\n    If a resolve attachment is set, an MSAA-resolve operation from the\n    associated color attachment image into the resolve attachment image will take\n    place in the sg_end_pass() function. In this case, the color attachment\n    must have a (sample_count>1), and the resolve attachment a\n    (sample_count==1). The resolve attachment also must have the same pixel\n    format as the color attachment.\n\n    NOTE that MSAA depth-stencil attachments cannot be msaa-resolved!\n*/\ntypedef struct sg_attachment_desc {\n    sg_image image;\n    int mip_level;\n    int slice;      // cube texture: face; array texture: layer; 3D texture: slice\n} sg_attachment_desc;\n\ntypedef struct sg_attachments_desc {\n    uint32_t _start_canary;\n    sg_attachment_desc colors[SG_MAX_COLOR_ATTACHMENTS];\n    sg_attachment_desc resolves[SG_MAX_COLOR_ATTACHMENTS];\n    sg_attachment_desc depth_stencil;\n    const char* label;\n    uint32_t _end_canary;\n} sg_attachments_desc;\n\n/*\n    sg_trace_hooks\n\n    Installable callback functions to keep track of the sokol-gfx calls,\n    this is useful for debugging, or keeping track of resource creation\n    and destruction.\n\n    Trace hooks are installed with sg_install_trace_hooks(), this returns\n    another sg_trace_hooks struct with the previous set of\n    trace hook function pointers. These should be invoked by the\n    new trace hooks to form a proper call chain.\n*/\ntypedef struct sg_trace_hooks {\n    void* user_data;\n    void (*reset_state_cache)(void* user_data);\n    void (*make_buffer)(const sg_buffer_desc* desc, sg_buffer result, void* user_data);\n    void (*make_image)(const sg_image_desc* desc, sg_image result, void* user_data);\n    void (*make_sampler)(const sg_sampler_desc* desc, sg_sampler result, void* user_data);\n    void (*make_shader)(const sg_shader_desc* desc, sg_shader result, void* user_data);\n    void (*make_pipeline)(const sg_pipeline_desc* desc, sg_pipeline result, void* user_data);\n    void (*make_attachments)(const sg_attachments_desc* desc, sg_attachments result, void* user_data);\n    void (*destroy_buffer)(sg_buffer buf, void* user_data);\n    void (*destroy_image)(sg_image img, void* user_data);\n    void (*destroy_sampler)(sg_sampler smp, void* user_data);\n    void (*destroy_shader)(sg_shader shd, void* user_data);\n    void (*destroy_pipeline)(sg_pipeline pip, void* user_data);\n    void (*destroy_attachments)(sg_attachments atts, void* user_data);\n    void (*update_buffer)(sg_buffer buf, const sg_range* data, void* user_data);\n    void (*update_image)(sg_image img, const sg_image_data* data, void* user_data);\n    void (*append_buffer)(sg_buffer buf, const sg_range* data, int result, void* user_data);\n    void (*begin_pass)(const sg_pass* pass, void* user_data);\n    void (*apply_viewport)(int x, int y, int width, int height, bool origin_top_left, void* user_data);\n    void (*apply_scissor_rect)(int x, int y, int width, int height, bool origin_top_left, void* user_data);\n    void (*apply_pipeline)(sg_pipeline pip, void* user_data);\n    void (*apply_bindings)(const sg_bindings* bindings, void* user_data);\n    void (*apply_uniforms)(sg_shader_stage stage, int ub_index, const sg_range* data, void* user_data);\n    void (*draw)(int base_element, int num_elements, int num_instances, void* user_data);\n    void (*end_pass)(void* user_data);\n    void (*commit)(void* user_data);\n    void (*alloc_buffer)(sg_buffer result, void* user_data);\n    void (*alloc_image)(sg_image result, void* user_data);\n    void (*alloc_sampler)(sg_sampler result, void* user_data);\n    void (*alloc_shader)(sg_shader result, void* user_data);\n    void (*alloc_pipeline)(sg_pipeline result, void* user_data);\n    void (*alloc_attachments)(sg_attachments result, void* user_data);\n    void (*dealloc_buffer)(sg_buffer buf_id, void* user_data);\n    void (*dealloc_image)(sg_image img_id, void* user_data);\n    void (*dealloc_sampler)(sg_sampler smp_id, void* user_data);\n    void (*dealloc_shader)(sg_shader shd_id, void* user_data);\n    void (*dealloc_pipeline)(sg_pipeline pip_id, void* user_data);\n    void (*dealloc_attachments)(sg_attachments atts_id, void* user_data);\n    void (*init_buffer)(sg_buffer buf_id, const sg_buffer_desc* desc, void* user_data);\n    void (*init_image)(sg_image img_id, const sg_image_desc* desc, void* user_data);\n    void (*init_sampler)(sg_sampler smp_id, const sg_sampler_desc* desc, void* user_data);\n    void (*init_shader)(sg_shader shd_id, const sg_shader_desc* desc, void* user_data);\n    void (*init_pipeline)(sg_pipeline pip_id, const sg_pipeline_desc* desc, void* user_data);\n    void (*init_attachments)(sg_attachments atts_id, const sg_attachments_desc* desc, void* user_data);\n    void (*uninit_buffer)(sg_buffer buf_id, void* user_data);\n    void (*uninit_image)(sg_image img_id, void* user_data);\n    void (*uninit_sampler)(sg_sampler smp_id, void* user_data);\n    void (*uninit_shader)(sg_shader shd_id, void* user_data);\n    void (*uninit_pipeline)(sg_pipeline pip_id, void* user_data);\n    void (*uninit_attachments)(sg_attachments atts_id, void* user_data);\n    void (*fail_buffer)(sg_buffer buf_id, void* user_data);\n    void (*fail_image)(sg_image img_id, void* user_data);\n    void (*fail_sampler)(sg_sampler smp_id, void* user_data);\n    void (*fail_shader)(sg_shader shd_id, void* user_data);\n    void (*fail_pipeline)(sg_pipeline pip_id, void* user_data);\n    void (*fail_attachments)(sg_attachments atts_id, void* user_data);\n    void (*push_debug_group)(const char* name, void* user_data);\n    void (*pop_debug_group)(void* user_data);\n} sg_trace_hooks;\n\n/*\n    sg_buffer_info\n    sg_image_info\n    sg_sampler_info\n    sg_shader_info\n    sg_pipeline_info\n    sg_attachments_info\n\n    These structs contain various internal resource attributes which\n    might be useful for debug-inspection. Please don't rely on the\n    actual content of those structs too much, as they are quite closely\n    tied to sokol_gfx.h internals and may change more frequently than\n    the other public API elements.\n\n    The *_info structs are used as the return values of the following functions:\n\n    sg_query_buffer_info()\n    sg_query_image_info()\n    sg_query_sampler_info()\n    sg_query_shader_info()\n    sg_query_pipeline_info()\n    sg_query_pass_info()\n*/\ntypedef struct sg_slot_info {\n    sg_resource_state state;    // the current state of this resource slot\n    uint32_t res_id;            // type-neutral resource if (e.g. sg_buffer.id)\n} sg_slot_info;\n\ntypedef struct sg_buffer_info {\n    sg_slot_info slot;              // resource pool slot info\n    uint32_t update_frame_index;    // frame index of last sg_update_buffer()\n    uint32_t append_frame_index;    // frame index of last sg_append_buffer()\n    int append_pos;                 // current position in buffer for sg_append_buffer()\n    bool append_overflow;           // is buffer in overflow state (due to sg_append_buffer)\n    int num_slots;                  // number of renaming-slots for dynamically updated buffers\n    int active_slot;                // currently active write-slot for dynamically updated buffers\n} sg_buffer_info;\n\ntypedef struct sg_image_info {\n    sg_slot_info slot;              // resource pool slot info\n    uint32_t upd_frame_index;       // frame index of last sg_update_image()\n    int num_slots;                  // number of renaming-slots for dynamically updated images\n    int active_slot;                // currently active write-slot for dynamically updated images\n} sg_image_info;\n\ntypedef struct sg_sampler_info {\n    sg_slot_info slot;              // resource pool slot info\n} sg_sampler_info;\n\ntypedef struct sg_shader_info {\n    sg_slot_info slot;              // resource pool slot info\n} sg_shader_info;\n\ntypedef struct sg_pipeline_info {\n    sg_slot_info slot;              // resource pool slot info\n} sg_pipeline_info;\n\ntypedef struct sg_attachments_info {\n    sg_slot_info slot;              // resource pool slot info\n} sg_attachments_info;\n\n/*\n    sg_frame_stats\n\n    Allows to track generic and backend-specific stats about a\n    render frame. Obtained by calling sg_query_frame_stats(). The returned\n    struct contains information about the *previous* frame.\n*/\ntypedef struct sg_frame_stats_gl {\n    uint32_t num_bind_buffer;\n    uint32_t num_active_texture;\n    uint32_t num_bind_texture;\n    uint32_t num_bind_sampler;\n    uint32_t num_use_program;\n    uint32_t num_render_state;\n    uint32_t num_vertex_attrib_pointer;\n    uint32_t num_vertex_attrib_divisor;\n    uint32_t num_enable_vertex_attrib_array;\n    uint32_t num_disable_vertex_attrib_array;\n    uint32_t num_uniform;\n} sg_frame_stats_gl;\n\ntypedef struct sg_frame_stats_d3d11_pass {\n    uint32_t num_om_set_render_targets;\n    uint32_t num_clear_render_target_view;\n    uint32_t num_clear_depth_stencil_view;\n    uint32_t num_resolve_subresource;\n} sg_frame_stats_d3d11_pass;\n\ntypedef struct sg_frame_stats_d3d11_pipeline {\n    uint32_t num_rs_set_state;\n    uint32_t num_om_set_depth_stencil_state;\n    uint32_t num_om_set_blend_state;\n    uint32_t num_ia_set_primitive_topology;\n    uint32_t num_ia_set_input_layout;\n    uint32_t num_vs_set_shader;\n    uint32_t num_vs_set_constant_buffers;\n    uint32_t num_ps_set_shader;\n    uint32_t num_ps_set_constant_buffers;\n} sg_frame_stats_d3d11_pipeline;\n\ntypedef struct sg_frame_stats_d3d11_bindings {\n    uint32_t num_ia_set_vertex_buffers;\n    uint32_t num_ia_set_index_buffer;\n    uint32_t num_vs_set_shader_resources;\n    uint32_t num_ps_set_shader_resources;\n    uint32_t num_vs_set_samplers;\n    uint32_t num_ps_set_samplers;\n} sg_frame_stats_d3d11_bindings;\n\ntypedef struct sg_frame_stats_d3d11_uniforms {\n    uint32_t num_update_subresource;\n} sg_frame_stats_d3d11_uniforms;\n\ntypedef struct sg_frame_stats_d3d11_draw {\n    uint32_t num_draw_indexed_instanced;\n    uint32_t num_draw_indexed;\n    uint32_t num_draw_instanced;\n    uint32_t num_draw;\n} sg_frame_stats_d3d11_draw;\n\ntypedef struct sg_frame_stats_d3d11 {\n    sg_frame_stats_d3d11_pass pass;\n    sg_frame_stats_d3d11_pipeline pipeline;\n    sg_frame_stats_d3d11_bindings bindings;\n    sg_frame_stats_d3d11_uniforms uniforms;\n    sg_frame_stats_d3d11_draw draw;\n    uint32_t num_map;\n    uint32_t num_unmap;\n} sg_frame_stats_d3d11;\n\ntypedef struct sg_frame_stats_metal_idpool {\n    uint32_t num_added;\n    uint32_t num_released;\n    uint32_t num_garbage_collected;\n} sg_frame_stats_metal_idpool;\n\ntypedef struct sg_frame_stats_metal_pipeline {\n    uint32_t num_set_blend_color;\n    uint32_t num_set_cull_mode;\n    uint32_t num_set_front_facing_winding;\n    uint32_t num_set_stencil_reference_value;\n    uint32_t num_set_depth_bias;\n    uint32_t num_set_render_pipeline_state;\n    uint32_t num_set_depth_stencil_state;\n} sg_frame_stats_metal_pipeline;\n\ntypedef struct sg_frame_stats_metal_bindings {\n    uint32_t num_set_vertex_buffer;\n    uint32_t num_set_vertex_texture;\n    uint32_t num_set_vertex_sampler_state;\n    uint32_t num_set_fragment_buffer;\n    uint32_t num_set_fragment_texture;\n    uint32_t num_set_fragment_sampler_state;\n} sg_frame_stats_metal_bindings;\n\ntypedef struct sg_frame_stats_metal_uniforms {\n    uint32_t num_set_vertex_buffer_offset;\n    uint32_t num_set_fragment_buffer_offset;\n} sg_frame_stats_metal_uniforms;\n\ntypedef struct sg_frame_stats_metal {\n    sg_frame_stats_metal_idpool idpool;\n    sg_frame_stats_metal_pipeline pipeline;\n    sg_frame_stats_metal_bindings bindings;\n    sg_frame_stats_metal_uniforms uniforms;\n} sg_frame_stats_metal;\n\ntypedef struct sg_frame_stats_wgpu_uniforms {\n    uint32_t num_set_bindgroup;\n    uint32_t size_write_buffer;\n} sg_frame_stats_wgpu_uniforms;\n\ntypedef struct sg_frame_stats_wgpu_bindings {\n    uint32_t num_set_vertex_buffer;\n    uint32_t num_skip_redundant_vertex_buffer;\n    uint32_t num_set_index_buffer;\n    uint32_t num_skip_redundant_index_buffer;\n    uint32_t num_create_bindgroup;\n    uint32_t num_discard_bindgroup;\n    uint32_t num_set_bindgroup;\n    uint32_t num_skip_redundant_bindgroup;\n    uint32_t num_bindgroup_cache_hits;\n    uint32_t num_bindgroup_cache_misses;\n    uint32_t num_bindgroup_cache_collisions;\n    uint32_t num_bindgroup_cache_hash_vs_key_mismatch;\n} sg_frame_stats_wgpu_bindings;\n\ntypedef struct sg_frame_stats_wgpu {\n    sg_frame_stats_wgpu_uniforms uniforms;\n    sg_frame_stats_wgpu_bindings bindings;\n} sg_frame_stats_wgpu;\n\ntypedef struct sg_frame_stats {\n    uint32_t frame_index;   // current frame counter, starts at 0\n\n    uint32_t num_passes;\n    uint32_t num_apply_viewport;\n    uint32_t num_apply_scissor_rect;\n    uint32_t num_apply_pipeline;\n    uint32_t num_apply_bindings;\n    uint32_t num_apply_uniforms;\n    uint32_t num_draw;\n    uint32_t num_update_buffer;\n    uint32_t num_append_buffer;\n    uint32_t num_update_image;\n\n    uint32_t size_apply_uniforms;\n    uint32_t size_update_buffer;\n    uint32_t size_append_buffer;\n    uint32_t size_update_image;\n\n    sg_frame_stats_gl gl;\n    sg_frame_stats_d3d11 d3d11;\n    sg_frame_stats_metal metal;\n    sg_frame_stats_wgpu wgpu;\n} sg_frame_stats;\n\n/*\n    sg_log_item\n\n    An enum with a unique item for each log message, warning, error\n    and validation layer message.\n*/\n#define _SG_LOG_ITEMS \\\n    _SG_LOGITEM_XMACRO(OK, \"Ok\") \\\n    _SG_LOGITEM_XMACRO(MALLOC_FAILED, \"memory allocation failed\") \\\n    _SG_LOGITEM_XMACRO(GL_TEXTURE_FORMAT_NOT_SUPPORTED, \"pixel format not supported for texture (gl)\") \\\n    _SG_LOGITEM_XMACRO(GL_3D_TEXTURES_NOT_SUPPORTED, \"3d textures not supported (gl)\") \\\n    _SG_LOGITEM_XMACRO(GL_ARRAY_TEXTURES_NOT_SUPPORTED, \"array textures not supported (gl)\") \\\n    _SG_LOGITEM_XMACRO(GL_SHADER_COMPILATION_FAILED, \"shader compilation failed (gl)\") \\\n    _SG_LOGITEM_XMACRO(GL_SHADER_LINKING_FAILED, \"shader linking failed (gl)\") \\\n    _SG_LOGITEM_XMACRO(GL_VERTEX_ATTRIBUTE_NOT_FOUND_IN_SHADER, \"vertex attribute not found in shader (gl)\") \\\n    _SG_LOGITEM_XMACRO(GL_TEXTURE_NAME_NOT_FOUND_IN_SHADER, \"texture name not found in shader (gl)\") \\\n    _SG_LOGITEM_XMACRO(GL_FRAMEBUFFER_STATUS_UNDEFINED, \"framebuffer completeness check failed with GL_FRAMEBUFFER_UNDEFINED (gl)\") \\\n    _SG_LOGITEM_XMACRO(GL_FRAMEBUFFER_STATUS_INCOMPLETE_ATTACHMENT, \"framebuffer completeness check failed with GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT (gl)\") \\\n    _SG_LOGITEM_XMACRO(GL_FRAMEBUFFER_STATUS_INCOMPLETE_MISSING_ATTACHMENT, \"framebuffer completeness check failed with GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT (gl)\") \\\n    _SG_LOGITEM_XMACRO(GL_FRAMEBUFFER_STATUS_UNSUPPORTED, \"framebuffer completeness check failed with GL_FRAMEBUFFER_UNSUPPORTED (gl)\") \\\n    _SG_LOGITEM_XMACRO(GL_FRAMEBUFFER_STATUS_INCOMPLETE_MULTISAMPLE, \"framebuffer completeness check failed with GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE (gl)\") \\\n    _SG_LOGITEM_XMACRO(GL_FRAMEBUFFER_STATUS_UNKNOWN, \"framebuffer completeness check failed (unknown reason) (gl)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_BUFFER_FAILED, \"CreateBuffer() failed (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_BUFFER_SRV_FAILED, \"CreateShaderResourceView() failed for storage buffer (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_DEPTH_TEXTURE_UNSUPPORTED_PIXEL_FORMAT, \"pixel format not supported for depth-stencil texture (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_DEPTH_TEXTURE_FAILED, \"CreateTexture2D() failed for depth-stencil texture (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_2D_TEXTURE_UNSUPPORTED_PIXEL_FORMAT, \"pixel format not supported for 2d-, cube- or array-texture (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_2D_TEXTURE_FAILED, \"CreateTexture2D() failed for 2d-, cube- or array-texture (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_2D_SRV_FAILED, \"CreateShaderResourceView() failed for 2d-, cube- or array-texture (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_3D_TEXTURE_UNSUPPORTED_PIXEL_FORMAT, \"pixel format not supported for 3D texture (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_3D_TEXTURE_FAILED, \"CreateTexture3D() failed (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_3D_SRV_FAILED, \"CreateShaderResourceView() failed for 3d texture (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_MSAA_TEXTURE_FAILED, \"CreateTexture2D() failed for MSAA render target texture (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_SAMPLER_STATE_FAILED, \"CreateSamplerState() failed (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_LOAD_D3DCOMPILER_47_DLL_FAILED, \"loading d3dcompiler_47.dll failed (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_SHADER_COMPILATION_FAILED, \"shader compilation failed (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_SHADER_COMPILATION_OUTPUT, \"\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_CONSTANT_BUFFER_FAILED, \"CreateBuffer() failed for uniform constant buffer (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_INPUT_LAYOUT_FAILED, \"CreateInputLayout() failed (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_RASTERIZER_STATE_FAILED, \"CreateRasterizerState() failed (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_DEPTH_STENCIL_STATE_FAILED, \"CreateDepthStencilState() failed (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_BLEND_STATE_FAILED, \"CreateBlendState() failed (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_RTV_FAILED, \"CreateRenderTargetView() failed (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_CREATE_DSV_FAILED, \"CreateDepthStencilView() failed (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_MAP_FOR_UPDATE_BUFFER_FAILED, \"Map() failed when updating buffer (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_MAP_FOR_APPEND_BUFFER_FAILED, \"Map() failed when appending to buffer (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(D3D11_MAP_FOR_UPDATE_IMAGE_FAILED, \"Map() failed when updating image (d3d11)\") \\\n    _SG_LOGITEM_XMACRO(METAL_CREATE_BUFFER_FAILED, \"failed to create buffer object (metal)\") \\\n    _SG_LOGITEM_XMACRO(METAL_TEXTURE_FORMAT_NOT_SUPPORTED, \"pixel format not supported for texture (metal)\") \\\n    _SG_LOGITEM_XMACRO(METAL_CREATE_TEXTURE_FAILED, \"failed to create texture object (metal)\") \\\n    _SG_LOGITEM_XMACRO(METAL_CREATE_SAMPLER_FAILED, \"failed to create sampler object (metal)\") \\\n    _SG_LOGITEM_XMACRO(METAL_SHADER_COMPILATION_FAILED, \"shader compilation failed (metal)\") \\\n    _SG_LOGITEM_XMACRO(METAL_SHADER_CREATION_FAILED, \"shader creation failed (metal)\") \\\n    _SG_LOGITEM_XMACRO(METAL_SHADER_COMPILATION_OUTPUT, \"\") \\\n    _SG_LOGITEM_XMACRO(METAL_VERTEX_SHADER_ENTRY_NOT_FOUND, \"vertex shader entry function not found (metal)\") \\\n    _SG_LOGITEM_XMACRO(METAL_FRAGMENT_SHADER_ENTRY_NOT_FOUND, \"fragment shader entry not found (metal)\") \\\n    _SG_LOGITEM_XMACRO(METAL_CREATE_RPS_FAILED, \"failed to create render pipeline state (metal)\") \\\n    _SG_LOGITEM_XMACRO(METAL_CREATE_RPS_OUTPUT, \"\") \\\n    _SG_LOGITEM_XMACRO(METAL_CREATE_DSS_FAILED, \"failed to create depth stencil state (metal)\") \\\n    _SG_LOGITEM_XMACRO(WGPU_BINDGROUPS_POOL_EXHAUSTED, \"bindgroups pool exhausted (increase sg_desc.bindgroups_cache_size) (wgpu)\") \\\n    _SG_LOGITEM_XMACRO(WGPU_BINDGROUPSCACHE_SIZE_GREATER_ONE, \"sg_desc.wgpu_bindgroups_cache_size must be > 1 (wgpu)\") \\\n    _SG_LOGITEM_XMACRO(WGPU_BINDGROUPSCACHE_SIZE_POW2, \"sg_desc.wgpu_bindgroups_cache_size must be a power of 2 (wgpu)\") \\\n    _SG_LOGITEM_XMACRO(WGPU_CREATEBINDGROUP_FAILED, \"wgpuDeviceCreateBindGroup failed\") \\\n    _SG_LOGITEM_XMACRO(WGPU_CREATE_BUFFER_FAILED, \"wgpuDeviceCreateBuffer() failed\") \\\n    _SG_LOGITEM_XMACRO(WGPU_CREATE_TEXTURE_FAILED, \"wgpuDeviceCreateTexture() failed\") \\\n    _SG_LOGITEM_XMACRO(WGPU_CREATE_TEXTURE_VIEW_FAILED, \"wgpuTextureCreateView() failed\") \\\n    _SG_LOGITEM_XMACRO(WGPU_CREATE_SAMPLER_FAILED, \"wgpuDeviceCreateSampler() failed\") \\\n    _SG_LOGITEM_XMACRO(WGPU_CREATE_SHADER_MODULE_FAILED, \"wgpuDeviceCreateShaderModule() failed\") \\\n    _SG_LOGITEM_XMACRO(WGPU_SHADER_TOO_MANY_IMAGES, \"shader uses too many sampled images on shader stage (wgpu)\") \\\n    _SG_LOGITEM_XMACRO(WGPU_SHADER_TOO_MANY_SAMPLERS, \"shader uses too many samplers on shader stage (wgpu)\") \\\n    _SG_LOGITEM_XMACRO(WGPU_SHADER_TOO_MANY_STORAGEBUFFERS, \"shader uses too many storage buffer bindings on shader stage (wgpu)\") \\\n    _SG_LOGITEM_XMACRO(WGPU_SHADER_CREATE_BINDGROUP_LAYOUT_FAILED, \"wgpuDeviceCreateBindGroupLayout() for shader stage failed\") \\\n    _SG_LOGITEM_XMACRO(WGPU_CREATE_PIPELINE_LAYOUT_FAILED, \"wgpuDeviceCreatePipelineLayout() failed\") \\\n    _SG_LOGITEM_XMACRO(WGPU_CREATE_RENDER_PIPELINE_FAILED, \"wgpuDeviceCreateRenderPipeline() failed\") \\\n    _SG_LOGITEM_XMACRO(WGPU_ATTACHMENTS_CREATE_TEXTURE_VIEW_FAILED, \"wgpuTextureCreateView() failed in create attachments\") \\\n    _SG_LOGITEM_XMACRO(IDENTICAL_COMMIT_LISTENER, \"attempting to add identical commit listener\") \\\n    _SG_LOGITEM_XMACRO(COMMIT_LISTENER_ARRAY_FULL, \"commit listener array full\") \\\n    _SG_LOGITEM_XMACRO(TRACE_HOOKS_NOT_ENABLED, \"sg_install_trace_hooks() called, but SOKOL_TRACE_HOOKS is not defined\") \\\n    _SG_LOGITEM_XMACRO(DEALLOC_BUFFER_INVALID_STATE, \"sg_dealloc_buffer(): buffer must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(DEALLOC_IMAGE_INVALID_STATE, \"sg_dealloc_image(): image must be in alloc state\") \\\n    _SG_LOGITEM_XMACRO(DEALLOC_SAMPLER_INVALID_STATE, \"sg_dealloc_sampler(): sampler must be in alloc state\") \\\n    _SG_LOGITEM_XMACRO(DEALLOC_SHADER_INVALID_STATE, \"sg_dealloc_shader(): shader must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(DEALLOC_PIPELINE_INVALID_STATE, \"sg_dealloc_pipeline(): pipeline must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(DEALLOC_ATTACHMENTS_INVALID_STATE, \"sg_dealloc_attachments(): attachments must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(INIT_BUFFER_INVALID_STATE, \"sg_init_buffer(): buffer must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(INIT_IMAGE_INVALID_STATE, \"sg_init_image(): image must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(INIT_SAMPLER_INVALID_STATE, \"sg_init_sampler(): sampler must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(INIT_SHADER_INVALID_STATE, \"sg_init_shader(): shader must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(INIT_PIPELINE_INVALID_STATE, \"sg_init_pipeline(): pipeline must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(INIT_ATTACHMENTS_INVALID_STATE, \"sg_init_attachments(): pass must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(UNINIT_BUFFER_INVALID_STATE, \"sg_uninit_buffer(): buffer must be in VALID or FAILED state\") \\\n    _SG_LOGITEM_XMACRO(UNINIT_IMAGE_INVALID_STATE, \"sg_uninit_image(): image must be in VALID or FAILED state\") \\\n    _SG_LOGITEM_XMACRO(UNINIT_SAMPLER_INVALID_STATE, \"sg_uninit_sampler(): sampler must be in VALID or FAILED state\") \\\n    _SG_LOGITEM_XMACRO(UNINIT_SHADER_INVALID_STATE, \"sg_uninit_shader(): shader must be in VALID or FAILED state\") \\\n    _SG_LOGITEM_XMACRO(UNINIT_PIPELINE_INVALID_STATE, \"sg_uninit_pipeline(): pipeline must be in VALID or FAILED state\") \\\n    _SG_LOGITEM_XMACRO(UNINIT_ATTACHMENTS_INVALID_STATE, \"sg_uninit_attachments(): attachments must be in VALID or FAILED state\") \\\n    _SG_LOGITEM_XMACRO(FAIL_BUFFER_INVALID_STATE, \"sg_fail_buffer(): buffer must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(FAIL_IMAGE_INVALID_STATE, \"sg_fail_image(): image must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(FAIL_SAMPLER_INVALID_STATE, \"sg_fail_sampler(): sampler must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(FAIL_SHADER_INVALID_STATE, \"sg_fail_shader(): shader must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(FAIL_PIPELINE_INVALID_STATE, \"sg_fail_pipeline(): pipeline must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(FAIL_ATTACHMENTS_INVALID_STATE, \"sg_fail_attachments(): attachments must be in ALLOC state\") \\\n    _SG_LOGITEM_XMACRO(BUFFER_POOL_EXHAUSTED, \"buffer pool exhausted\") \\\n    _SG_LOGITEM_XMACRO(IMAGE_POOL_EXHAUSTED, \"image pool exhausted\") \\\n    _SG_LOGITEM_XMACRO(SAMPLER_POOL_EXHAUSTED, \"sampler pool exhausted\") \\\n    _SG_LOGITEM_XMACRO(SHADER_POOL_EXHAUSTED, \"shader pool exhausted\") \\\n    _SG_LOGITEM_XMACRO(PIPELINE_POOL_EXHAUSTED, \"pipeline pool exhausted\") \\\n    _SG_LOGITEM_XMACRO(PASS_POOL_EXHAUSTED, \"pass pool exhausted\") \\\n    _SG_LOGITEM_XMACRO(BEGINPASS_ATTACHMENT_INVALID, \"sg_begin_pass: an attachment was provided that no longer exists\") \\\n    _SG_LOGITEM_XMACRO(DRAW_WITHOUT_BINDINGS, \"attempting to draw without resource bindings\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BUFFERDESC_CANARY, \"sg_buffer_desc not initialized\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BUFFERDESC_SIZE, \"sg_buffer_desc.size and .data.size cannot both be 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BUFFERDESC_DATA, \"immutable buffers must be initialized with data (sg_buffer_desc.data.ptr and sg_buffer_desc.data.size)\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BUFFERDESC_DATA_SIZE, \"immutable buffer data size differs from buffer size\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BUFFERDESC_NO_DATA, \"dynamic/stream usage buffers cannot be initialized with data\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BUFFERDESC_STORAGEBUFFER_SUPPORTED, \"storage buffers not supported by the backend 3D API (requires OpenGL >= 4.3)\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BUFFERDESC_STORAGEBUFFER_SIZE_MULTIPLE_4, \"size of storage buffers must be a multiple of 4\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDATA_NODATA, \"sg_image_data: no data (.ptr and/or .size is zero)\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDATA_DATA_SIZE, \"sg_image_data: data size doesn't match expected surface size\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_CANARY, \"sg_image_desc not initialized\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_WIDTH, \"sg_image_desc.width must be > 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_HEIGHT, \"sg_image_desc.height must be > 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_RT_PIXELFORMAT, \"invalid pixel format for render-target image\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_NONRT_PIXELFORMAT, \"invalid pixel format for non-render-target image\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_MSAA_BUT_NO_RT, \"non-render-target images cannot be multisampled\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_NO_MSAA_RT_SUPPORT, \"MSAA not supported for this pixel format\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_MSAA_NUM_MIPMAPS, \"MSAA images must have num_mipmaps == 1\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_MSAA_3D_IMAGE, \"3D images cannot have a sample_count > 1\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_DEPTH_3D_IMAGE, \"3D images cannot have a depth/stencil image format\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_RT_IMMUTABLE, \"render target images must be SG_USAGE_IMMUTABLE\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_RT_NO_DATA, \"render target images cannot be initialized with data\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_INJECTED_NO_DATA, \"images with injected textures cannot be initialized with data\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_DYNAMIC_NO_DATA, \"dynamic/stream images cannot be initialized with data\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_IMAGEDESC_COMPRESSED_IMMUTABLE, \"compressed images must be immutable\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SAMPLERDESC_CANARY, \"sg_sampler_desc not initialized\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SAMPLERDESC_MINFILTER_NONE, \"sg_sampler_desc.min_filter cannot be SG_FILTER_NONE\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SAMPLERDESC_MAGFILTER_NONE, \"sg_sampler_desc.mag_filter cannot be SG_FILTER_NONE\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SAMPLERDESC_ANISTROPIC_REQUIRES_LINEAR_FILTERING, \"sg_sampler_desc.max_anisotropy > 1 requires min/mag/mipmap_filter to be SG_FILTER_LINEAR\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_CANARY, \"sg_shader_desc not initialized\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_SOURCE, \"shader source code required\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_BYTECODE, \"shader byte code required\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_SOURCE_OR_BYTECODE, \"shader source or byte code required\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_NO_BYTECODE_SIZE, \"shader byte code length (in bytes) required\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_NO_CONT_UBS, \"shader uniform blocks must occupy continuous slots\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_NO_CONT_UB_MEMBERS, \"uniform block members must occupy continuous slots\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_NO_UB_MEMBERS, \"GL backend requires uniform block member declarations\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_UB_MEMBER_NAME, \"uniform block member name missing\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_UB_SIZE_MISMATCH, \"size of uniform block members doesn't match uniform block size\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_UB_ARRAY_COUNT, \"uniform array count must be >= 1\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_UB_STD140_ARRAY_TYPE, \"uniform arrays only allowed for FLOAT4, INT4, MAT4 in std140 layout\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_NO_CONT_STORAGEBUFFERS, \"shader stage storage buffers must occupy continuous slots (sg_shader_desc.vs|fs.storage_buffers[])\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_STORAGEBUFFER_READONLY, \"shader stage storage buffers must be readonly (sg_shader_desc.vs|fs.storage_buffers[].readonly)\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_NO_CONT_IMAGES, \"shader stage images must occupy continuous slots (sg_shader_desc.vs|fs.images[])\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_NO_CONT_SAMPLERS, \"shader stage samplers must occupy continuous slots (sg_shader_desc.vs|fs.samplers[])\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_IMAGE_SLOT_OUT_OF_RANGE, \"shader stage: image-sampler-pair image slot index is out of range (sg_shader_desc.vs|fs.image_sampler_pairs[].image_slot)\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_SAMPLER_SLOT_OUT_OF_RANGE, \"shader stage: image-sampler-pair image slot index is out of range (sg_shader_desc.vs|fs.image_sampler_pairs[].sampler_slot)\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_NAME_REQUIRED_FOR_GL, \"shader stage: image-sampler-pairs must be named in GL (sg_shader_desc.vs|fs.image_sampler_pairs[].name)\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_HAS_NAME_BUT_NOT_USED, \"shader stage: image-sampler-pair has name but .used field not true\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_HAS_IMAGE_BUT_NOT_USED, \"shader stage: image-sampler-pair has .image_slot != 0 but .used field not true\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_HAS_SAMPLER_BUT_NOT_USED, \"shader stage: image-sampler-pair .sampler_slot != 0 but .used field not true\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_NONFILTERING_SAMPLER_REQUIRED, \"shader stage: image sample type UNFILTERABLE_FLOAT, UINT, SINT can only be used with NONFILTERING sampler\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_COMPARISON_SAMPLER_REQUIRED, \"shader stage: image sample type DEPTH can only be used with COMPARISON sampler\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_IMAGE_NOT_REFERENCED_BY_IMAGE_SAMPLER_PAIRS, \"shader stage: one or more images are note referenced by  (sg_shader_desc.vs|fs.image_sampler_pairs[].image_slot)\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_SAMPLER_NOT_REFERENCED_BY_IMAGE_SAMPLER_PAIRS, \"shader stage: one or more samplers are not referenced by image-sampler-pairs (sg_shader_desc.vs|fs.image_sampler_pairs[].sampler_slot)\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_NO_CONT_IMAGE_SAMPLER_PAIRS, \"shader stage image-sampler-pairs must occupy continuous slots (sg_shader_desc.vs|fs.image_samplers[])\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_ATTR_STRING_TOO_LONG, \"vertex attribute name/semantic string too long (max len 16)\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_PIPELINEDESC_CANARY, \"sg_pipeline_desc not initialized\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_PIPELINEDESC_SHADER, \"sg_pipeline_desc.shader missing or invalid\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_PIPELINEDESC_NO_CONT_ATTRS, \"sg_pipeline_desc.layout.attrs is not continuous\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_PIPELINEDESC_LAYOUT_STRIDE4, \"sg_pipeline_desc.layout.buffers[].stride must be multiple of 4\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_PIPELINEDESC_ATTR_SEMANTICS, \"D3D11 missing vertex attribute semantics in shader\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_CANARY, \"sg_attachments_desc not initialized\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_NO_ATTACHMENTS, \"sg_attachments_desc no color or depth-stencil attachments\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_NO_CONT_COLOR_ATTS, \"color attachments must occupy continuous slots\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_IMAGE, \"pass attachment image is not valid\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_MIPLEVEL, \"pass attachment mip level is bigger than image has mipmaps\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_FACE, \"pass attachment image is cubemap, but face index is too big\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_LAYER, \"pass attachment image is array texture, but layer index is too big\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_SLICE, \"pass attachment image is 3d texture, but slice value is too big\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_IMAGE_NO_RT, \"pass attachment image must be have render_target=true\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_COLOR_INV_PIXELFORMAT, \"pass color-attachment images must be renderable color pixel format\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_DEPTH_INV_PIXELFORMAT, \"pass depth-attachment image must be depth or depth-stencil pixel format\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_IMAGE_SIZES, \"all pass attachments must have the same size\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_IMAGE_SAMPLE_COUNTS, \"all pass attachments must have the same sample count\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_RESOLVE_COLOR_IMAGE_MSAA, \"pass resolve attachments must have a color attachment image with sample count > 1\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_RESOLVE_IMAGE, \"pass resolve attachment image not valid\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_RESOLVE_SAMPLE_COUNT, \"pass resolve attachment image sample count must be 1\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_RESOLVE_MIPLEVEL, \"pass resolve attachment mip level is bigger than image has mipmaps\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_RESOLVE_FACE, \"pass resolve attachment is cubemap, but face index is too big\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_RESOLVE_LAYER, \"pass resolve attachment is array texture, but layer index is too big\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_RESOLVE_SLICE, \"pass resolve attachment is 3d texture, but slice value is too big\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_RESOLVE_IMAGE_NO_RT, \"pass resolve attachment image must have render_target=true\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_RESOLVE_IMAGE_SIZES, \"pass resolve attachment size must match color attachment image size\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_RESOLVE_IMAGE_FORMAT, \"pass resolve attachment pixel format must match color attachment pixel format\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_DEPTH_IMAGE, \"pass depth attachment image is not valid\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_DEPTH_MIPLEVEL, \"pass depth attachment mip level is bigger than image has mipmaps\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_DEPTH_FACE, \"pass depth attachment image is cubemap, but face index is too big\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_DEPTH_LAYER, \"pass depth attachment image is array texture, but layer index is too big\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_DEPTH_SLICE, \"pass depth attachment image is 3d texture, but slice value is too big\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_DEPTH_IMAGE_NO_RT, \"pass depth attachment image must be have render_target=true\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_DEPTH_IMAGE_SIZES, \"pass depth attachment image size must match color attachment image size\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_DEPTH_IMAGE_SAMPLE_COUNT, \"pass depth attachment sample count must match color attachment sample count\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_CANARY, \"sg_begin_pass: pass struct not initialized\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_ATTACHMENTS_EXISTS, \"sg_begin_pass: attachments object no longer alive\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_ATTACHMENTS_VALID, \"sg_begin_pass: attachments object not in resource state VALID\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_COLOR_ATTACHMENT_IMAGE, \"sg_begin_pass: one or more color attachment images are not valid\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_RESOLVE_ATTACHMENT_IMAGE, \"sg_begin_pass: one or more resolve attachment images are not valid\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_DEPTHSTENCIL_ATTACHMENT_IMAGE, \"sg_begin_pass: one or more depth-stencil attachment images are not valid\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_WIDTH, \"sg_begin_pass: expected pass.swapchain.width > 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_WIDTH_NOTSET, \"sg_begin_pass: expected pass.swapchain.width == 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_HEIGHT, \"sg_begin_pass: expected pass.swapchain.height > 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_HEIGHT_NOTSET, \"sg_begin_pass: expected pass.swapchain.height == 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_SAMPLECOUNT, \"sg_begin_pass: expected pass.swapchain.sample_count > 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_SAMPLECOUNT_NOTSET, \"sg_begin_pass: expected pass.swapchain.sample_count == 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_COLORFORMAT, \"sg_begin_pass: expected pass.swapchain.color_format to be valid\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_COLORFORMAT_NOTSET, \"sg_begin_pass: expected pass.swapchain.color_format to be unset\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_DEPTHFORMAT_NOTSET, \"sg_begin_pass: expected pass.swapchain.depth_format to be unset\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_METAL_EXPECT_CURRENTDRAWABLE, \"sg_begin_pass: expected pass.swapchain.metal.current_drawable != 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_METAL_EXPECT_CURRENTDRAWABLE_NOTSET, \"sg_begin_pass: expected pass.swapchain.metal.current_drawable == 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_METAL_EXPECT_DEPTHSTENCILTEXTURE, \"sg_begin_pass: expected pass.swapchain.metal.depth_stencil_texture != 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_METAL_EXPECT_DEPTHSTENCILTEXTURE_NOTSET, \"sg_begin_pass: expected pass.swapchain.metal.depth_stencil_texture == 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_METAL_EXPECT_MSAACOLORTEXTURE, \"sg_begin_pass: expected pass.swapchain.metal.msaa_color_texture != 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_METAL_EXPECT_MSAACOLORTEXTURE_NOTSET, \"sg_begin_pass: expected pass.swapchain.metal.msaa_color_texture == 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_D3D11_EXPECT_RENDERVIEW, \"sg_begin_pass: expected pass.swapchain.d3d11.render_view != 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_D3D11_EXPECT_RENDERVIEW_NOTSET, \"sg_begin_pass: expected pass.swapchain.d3d11.render_view == 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_D3D11_EXPECT_RESOLVEVIEW, \"sg_begin_pass: expected pass.swapchain.d3d11.resolve_view != 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_D3D11_EXPECT_RESOLVEVIEW_NOTSET, \"sg_begin_pass: expected pass.swapchain.d3d11.resolve_view == 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_D3D11_EXPECT_DEPTHSTENCILVIEW, \"sg_begin_pass: expected pass.swapchain.d3d11.depth_stencil_view != 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_D3D11_EXPECT_DEPTHSTENCILVIEW_NOTSET, \"sg_begin_pass: expected pass.swapchain.d3d11.depth_stencil_view == 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_WGPU_EXPECT_RENDERVIEW, \"sg_begin_pass: expected pass.swapchain.wgpu.render_view != 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_WGPU_EXPECT_RENDERVIEW_NOTSET, \"sg_begin_pass: expected pass.swapchain.wgpu.render_view == 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_WGPU_EXPECT_RESOLVEVIEW, \"sg_begin_pass: expected pass.swapchain.wgpu.resolve_view != 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_WGPU_EXPECT_RESOLVEVIEW_NOTSET, \"sg_begin_pass: expected pass.swapchain.wgpu.resolve_view == 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_WGPU_EXPECT_DEPTHSTENCILVIEW, \"sg_begin_pass: expected pass.swapchain.wgpu.depth_stencil_view != 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_WGPU_EXPECT_DEPTHSTENCILVIEW_NOTSET, \"sg_begin_pass: expected pass.swapchain.wgpu.depth_stencil_view == 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_SWAPCHAIN_GL_EXPECT_FRAMEBUFFER_NOTSET, \"sg_begin_pass: expected pass.swapchain.gl.framebuffer == 0\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_APIP_PIPELINE_VALID_ID, \"sg_apply_pipeline: invalid pipeline id provided\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_APIP_PIPELINE_EXISTS, \"sg_apply_pipeline: pipeline object no longer alive\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_APIP_PIPELINE_VALID, \"sg_apply_pipeline: pipeline object not in valid state\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_APIP_SHADER_EXISTS, \"sg_apply_pipeline: shader object no longer alive\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_APIP_SHADER_VALID, \"sg_apply_pipeline: shader object not in valid state\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_APIP_CURPASS_ATTACHMENTS_EXISTS, \"sg_apply_pipeline: current pass attachments no longer alive\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_APIP_CURPASS_ATTACHMENTS_VALID, \"sg_apply_pipeline: current pass attachments not in valid state\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_APIP_ATT_COUNT, \"sg_apply_pipeline: number of pipeline color attachments doesn't match number of pass color attachments\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_APIP_COLOR_FORMAT, \"sg_apply_pipeline: pipeline color attachment pixel format doesn't match pass color attachment pixel format\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_APIP_DEPTH_FORMAT, \"sg_apply_pipeline: pipeline depth pixel_format doesn't match pass depth attachment pixel format\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_APIP_SAMPLE_COUNT, \"sg_apply_pipeline: pipeline MSAA sample count doesn't match render pass attachment sample count\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_PIPELINE, \"sg_apply_bindings: must be called after sg_apply_pipeline\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_PIPELINE_EXISTS, \"sg_apply_bindings: currently applied pipeline object no longer alive\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_PIPELINE_VALID, \"sg_apply_bindings: currently applied pipeline object not in valid state\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VBS, \"sg_apply_bindings: number of vertex buffers doesn't match number of pipeline vertex layouts\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VB_EXISTS, \"sg_apply_bindings: vertex buffer no longer alive\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VB_TYPE, \"sg_apply_bindings: buffer in vertex buffer slot is not a SG_BUFFERTYPE_VERTEXBUFFER\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VB_OVERFLOW, \"sg_apply_bindings: buffer in vertex buffer slot is overflown\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_NO_IB, \"sg_apply_bindings: pipeline object defines indexed rendering, but no index buffer provided\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_IB, \"sg_apply_bindings: pipeline object defines non-indexed rendering, but index buffer provided\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_IB_EXISTS, \"sg_apply_bindings: index buffer no longer alive\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_IB_TYPE, \"sg_apply_bindings: buffer in index buffer slot is not a SG_BUFFERTYPE_INDEXBUFFER\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_IB_OVERFLOW, \"sg_apply_bindings: buffer in index buffer slot is overflown\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_IMAGE_BINDING, \"sg_apply_bindings: image binding on vertex stage is missing or the image handle is invalid\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_IMG_EXISTS, \"sg_apply_bindings: image bound to vertex stage no longer alive\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_IMAGE_TYPE_MISMATCH, \"sg_apply_bindings: type of image bound to vertex stage doesn't match shader desc\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_IMAGE_MSAA, \"sg_apply_bindings: cannot bind image with sample_count>1 to vertex stage\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_FILTERABLE_IMAGE, \"sg_apply_bindings: filterable image expected on vertex stage\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_DEPTH_IMAGE, \"sg_apply_bindings: depth image expected on vertex stage\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_UNEXPECTED_IMAGE_BINDING, \"sg_apply_bindings: unexpected image binding on vertex stage\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_SAMPLER_BINDING, \"sg_apply_bindings: sampler binding on vertex stage is missing or the sampler handle is invalid\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_UNEXPECTED_SAMPLER_COMPARE_NEVER, \"sg_apply_bindings: shader expects SG_SAMPLERTYPE_COMPARISON on vertex stage but sampler has SG_COMPAREFUNC_NEVER\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_SAMPLER_COMPARE_NEVER, \"sg_apply_bindings: shader expects SG_SAMPLERTYPE_FILTERING or SG_SAMPLERTYPE_NONFILTERING on vertex stage but sampler doesn't have SG_COMPAREFUNC_NEVER\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_NONFILTERING_SAMPLER, \"sg_apply_bindings: shader expected SG_SAMPLERTYPE_NONFILTERING on vertex stage, but sampler has SG_FILTER_LINEAR filters\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_UNEXPECTED_SAMPLER_BINDING, \"sg_apply_bindings: unexpected sampler binding on vertex stage\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_SMP_EXISTS, \"sg_apply_bindings: sampler bound to vertex stage no longer alive\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_STORAGEBUFFER_BINDING, \"sg_apply_bindings: storage buffer binding on vertex stage is missing or the buffer handle is invalid\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_STORAGEBUFFER_EXISTS, \"sg_apply_bindings: storage buffer bound to vertex stage no longer alive\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_STORAGEBUFFER_BINDING_BUFFERTYPE, \"sg_apply_bindings: buffer bound to vertex stage storage buffer slot is not of type storage buffer\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_UNEXPECTED_STORAGEBUFFER_BINDING, \"sg_apply_bindings: unexpected storage buffer binding on vertex stage\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_EXPECTED_IMAGE_BINDING, \"sg_apply_bindings: image binding on fragment stage is missing or the image handle is invalid\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_IMG_EXISTS, \"sg_apply_bindings: image bound to fragment stage no longer alive\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_IMAGE_TYPE_MISMATCH, \"sg_apply_bindings: type of image bound to fragment stage doesn't match shader desc\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_IMAGE_MSAA, \"sg_apply_bindings: cannot bind image with sample_count>1 to fragment stage\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_EXPECTED_FILTERABLE_IMAGE, \"sg_apply_bindings: filterable image expected on fragment stage\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_EXPECTED_DEPTH_IMAGE, \"sg_apply_bindings: depth image expected on fragment stage\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_UNEXPECTED_IMAGE_BINDING, \"sg_apply_bindings: unexpected image binding on fragment stage\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_EXPECTED_SAMPLER_BINDING, \"sg_apply_bindings: sampler binding on fragment stage is missing or the sampler handle is invalid\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_UNEXPECTED_SAMPLER_COMPARE_NEVER, \"sg_apply_bindings: shader expects SG_SAMPLERTYPE_COMPARISON on fragment stage but sampler has SG_COMPAREFUNC_NEVER\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_EXPECTED_SAMPLER_COMPARE_NEVER, \"sg_apply_bindings: shader expects SG_SAMPLERTYPE_FILTERING on fragment stage but sampler doesn't have SG_COMPAREFUNC_NEVER\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_EXPECTED_NONFILTERING_SAMPLER, \"sg_apply_bindings: shader expected SG_SAMPLERTYPE_NONFILTERING on fragment stage, but sampler has SG_FILTER_LINEAR filters\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_UNEXPECTED_SAMPLER_BINDING, \"sg_apply_bindings: unexpected sampler binding on fragment stage\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_SMP_EXISTS, \"sg_apply_bindings: sampler bound to fragment stage no longer alive\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_EXPECTED_STORAGEBUFFER_BINDING, \"sg_apply_bindings: storage buffer binding on fragment stage is missing or the buffer handle is invalid\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_STORAGEBUFFER_EXISTS, \"sg_apply_bindings: storage buffer bound to fragment stage no longer alive\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_STORAGEBUFFER_BINDING_BUFFERTYPE, \"sg_apply_bindings: buffer bound to frahment stage storage buffer slot is not of type storage buffer\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_UNEXPECTED_STORAGEBUFFER_BINDING, \"sg_apply_bindings: unexpected storage buffer binding on fragment stage\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_AUB_NO_PIPELINE, \"sg_apply_uniforms: must be called after sg_apply_pipeline()\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_AUB_NO_UB_AT_SLOT, \"sg_apply_uniforms: no uniform block declaration at this shader stage UB slot\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_AUB_SIZE, \"sg_apply_uniforms: data size doesn't match declared uniform block size\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_UPDATEBUF_USAGE, \"sg_update_buffer: cannot update immutable buffer\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_UPDATEBUF_SIZE, \"sg_update_buffer: update size is bigger than buffer size\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_UPDATEBUF_ONCE, \"sg_update_buffer: only one update allowed per buffer and frame\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_UPDATEBUF_APPEND, \"sg_update_buffer: cannot call sg_update_buffer and sg_append_buffer in same frame\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_APPENDBUF_USAGE, \"sg_append_buffer: cannot append to immutable buffer\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_APPENDBUF_SIZE, \"sg_append_buffer: overall appended size is bigger than buffer size\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_APPENDBUF_UPDATE, \"sg_append_buffer: cannot call sg_append_buffer and sg_update_buffer in same frame\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_UPDIMG_USAGE, \"sg_update_image: cannot update immutable image\") \\\n    _SG_LOGITEM_XMACRO(VALIDATE_UPDIMG_ONCE, \"sg_update_image: only one update allowed per image and frame\") \\\n    _SG_LOGITEM_XMACRO(VALIDATION_FAILED, \"validation layer checks failed\") \\\n\n#define _SG_LOGITEM_XMACRO(item,msg) SG_LOGITEM_##item,\ntypedef enum sg_log_item {\n    _SG_LOG_ITEMS\n} sg_log_item;\n#undef _SG_LOGITEM_XMACRO\n\n/*\n    sg_desc\n\n    The sg_desc struct contains configuration values for sokol_gfx,\n    it is used as parameter to the sg_setup() call.\n\n    The default configuration is:\n\n    .buffer_pool_size       128\n    .image_pool_size        128\n    .sampler_pool_size      64\n    .shader_pool_size       32\n    .pipeline_pool_size     64\n    .pass_pool_size         16\n    .uniform_buffer_size    4 MB (4*1024*1024)\n    .max_commit_listeners   1024\n    .disable_validation     false\n    .mtl_force_managed_storage_mode false\n    .wgpu_disable_bindgroups_cache  false\n    .wgpu_bindgroups_cache_size     1024\n\n    .allocator.alloc_fn     0 (in this case, malloc() will be called)\n    .allocator.free_fn      0 (in this case, free() will be called)\n    .allocator.user_data    0\n\n    .environment.defaults.color_format: default value depends on selected backend:\n        all GL backends:    SG_PIXELFORMAT_RGBA8\n        Metal and D3D11:    SG_PIXELFORMAT_BGRA8\n        WebGPU:             *no default* (must be queried from WebGPU swapchain object)\n    .environment.defaults.depth_format: SG_PIXELFORMAT_DEPTH_STENCIL\n    .environment.defaults.sample_count: 1\n\n    Metal specific:\n        (NOTE: All Objective-C object references are transferred through\n        a bridged (const void*) to sokol_gfx, which will use a unretained\n        bridged cast (__bridged id<xxx>) to retrieve the Objective-C\n        references back. Since the bridge cast is unretained, the caller\n        must hold a strong reference to the Objective-C object for the\n        duration of the sokol_gfx call!\n\n        .mtl_force_managed_storage_mode\n            when enabled, Metal buffers and texture resources are created in managed storage\n            mode, otherwise sokol-gfx will decide whether to create buffers and\n            textures in managed or shared storage mode (this is mainly a debugging option)\n        .mtl_use_command_buffer_with_retained_references\n            when true, the sokol-gfx Metal backend will use Metal command buffers which\n            bump the reference count of resource objects as long as they are inflight,\n            this is slower than the default command-buffer-with-unretained-references\n            method, this may be a workaround when confronted with lifetime validation\n            errors from the Metal validation layer until a proper fix has been implemented\n        .environment.metal.device\n            a pointer to the MTLDevice object\n\n    D3D11 specific:\n        .environment.d3d11.device\n            a pointer to the ID3D11Device object, this must have been created\n            before sg_setup() is called\n        .environment.d3d11.device_context\n            a pointer to the ID3D11DeviceContext object\n\n    WebGPU specific:\n        .wgpu_disable_bindgroups_cache\n            When this is true, the WebGPU backend will create and immediately\n            release a BindGroup object in the sg_apply_bindings() call, only\n            use this for debugging purposes.\n        .wgpu_bindgroups_cache_size\n            The size of the bindgroups cache for re-using BindGroup objects\n            between sg_apply_bindings() calls. The smaller the cache size,\n            the more likely are cache slot collisions which will cause\n            a BindGroups object to be destroyed and a new one created.\n            Use the information returned by sg_query_stats() to check\n            if this is a frequent occurrence, and increase the cache size as\n            needed (the default is 1024).\n            NOTE: wgpu_bindgroups_cache_size must be a power-of-2 number!\n        .environment.wgpu.device\n            a WGPUDevice handle\n\n    When using sokol_gfx.h and sokol_app.h together, consider using the\n    helper function sglue_environment() in the sokol_glue.h header to\n    initialize the sg_desc.environment nested struct. sglue_environment() returns\n    a completely initialized sg_environment struct with information\n    provided by sokol_app.h.\n*/\ntypedef struct sg_environment_defaults {\n    sg_pixel_format color_format;\n    sg_pixel_format depth_format;\n    int sample_count;\n} sg_environment_defaults;\n\ntypedef struct sg_metal_environment {\n    const void* device;\n} sg_metal_environment;\n\ntypedef struct sg_d3d11_environment {\n    const void* device;\n    const void* device_context;\n} sg_d3d11_environment;\n\ntypedef struct sg_wgpu_environment {\n    const void* device;\n} sg_wgpu_environment;\n\ntypedef struct sg_environment {\n    sg_environment_defaults defaults;\n    sg_metal_environment metal;\n    sg_d3d11_environment d3d11;\n    sg_wgpu_environment wgpu;\n} sg_environment;\n\n/*\n    sg_commit_listener\n\n    Used with function sg_add_commit_listener() to add a callback\n    which will be called in sg_commit(). This is useful for libraries\n    building on top of sokol-gfx to be notified about when a frame\n    ends (instead of having to guess, or add a manual 'new-frame'\n    function.\n*/\ntypedef struct sg_commit_listener {\n    void (*func)(void* user_data);\n    void* user_data;\n} sg_commit_listener;\n\n/*\n    sg_allocator\n\n    Used in sg_desc to provide custom memory-alloc and -free functions\n    to sokol_gfx.h. If memory management should be overridden, both the\n    alloc_fn and free_fn function must be provided (e.g. it's not valid to\n    override one function but not the other).\n*/\ntypedef struct sg_allocator {\n    void* (*alloc_fn)(size_t size, void* user_data);\n    void (*free_fn)(void* ptr, void* user_data);\n    void* user_data;\n} sg_allocator;\n\n/*\n    sg_logger\n\n    Used in sg_desc to provide a logging function. Please be aware\n    that without logging function, sokol-gfx will be completely\n    silent, e.g. it will not report errors, warnings and\n    validation layer messages. For maximum error verbosity,\n    compile in debug mode (e.g. NDEBUG *not* defined) and provide a\n    compatible logger function in the sg_setup() call\n    (for instance the standard logging function from sokol_log.h).\n*/\ntypedef struct sg_logger {\n    void (*func)(\n        const char* tag,                // always \"sg\"\n        uint32_t log_level,             // 0=panic, 1=error, 2=warning, 3=info\n        uint32_t log_item_id,           // SG_LOGITEM_*\n        const char* message_or_null,    // a message string, may be nullptr in release mode\n        uint32_t line_nr,               // line number in sokol_gfx.h\n        const char* filename_or_null,   // source filename, may be nullptr in release mode\n        void* user_data);\n    void* user_data;\n} sg_logger;\n\ntypedef struct sg_desc {\n    uint32_t _start_canary;\n    int buffer_pool_size;\n    int image_pool_size;\n    int sampler_pool_size;\n    int shader_pool_size;\n    int pipeline_pool_size;\n    int attachments_pool_size;\n    int uniform_buffer_size;\n    int max_commit_listeners;\n    bool disable_validation;    // disable validation layer even in debug mode, useful for tests\n    bool mtl_force_managed_storage_mode; // for debugging: use Metal managed storage mode for resources even with UMA\n    bool mtl_use_command_buffer_with_retained_references;    // Metal: use a managed MTLCommandBuffer which ref-counts used resources\n    bool wgpu_disable_bindgroups_cache;  // set to true to disable the WebGPU backend BindGroup cache\n    int wgpu_bindgroups_cache_size;      // number of slots in the WebGPU bindgroup cache (must be 2^N)\n    sg_allocator allocator;\n    sg_logger logger; // optional log function override\n    sg_environment environment;\n    uint32_t _end_canary;\n} sg_desc;\n\n// setup and misc functions\nSOKOL_GFX_API_DECL void sg_setup(const sg_desc* desc);\nSOKOL_GFX_API_DECL void sg_shutdown(void);\nSOKOL_GFX_API_DECL bool sg_isvalid(void);\nSOKOL_GFX_API_DECL void sg_reset_state_cache(void);\nSOKOL_GFX_API_DECL sg_trace_hooks sg_install_trace_hooks(const sg_trace_hooks* trace_hooks);\nSOKOL_GFX_API_DECL void sg_push_debug_group(const char* name);\nSOKOL_GFX_API_DECL void sg_pop_debug_group(void);\nSOKOL_GFX_API_DECL bool sg_add_commit_listener(sg_commit_listener listener);\nSOKOL_GFX_API_DECL bool sg_remove_commit_listener(sg_commit_listener listener);\n\n// resource creation, destruction and updating\nSOKOL_GFX_API_DECL sg_buffer sg_make_buffer(const sg_buffer_desc* desc);\nSOKOL_GFX_API_DECL sg_image sg_make_image(const sg_image_desc* desc);\nSOKOL_GFX_API_DECL sg_sampler sg_make_sampler(const sg_sampler_desc* desc);\nSOKOL_GFX_API_DECL sg_shader sg_make_shader(const sg_shader_desc* desc);\nSOKOL_GFX_API_DECL sg_pipeline sg_make_pipeline(const sg_pipeline_desc* desc);\nSOKOL_GFX_API_DECL sg_attachments sg_make_attachments(const sg_attachments_desc* desc);\nSOKOL_GFX_API_DECL void sg_destroy_buffer(sg_buffer buf);\nSOKOL_GFX_API_DECL void sg_destroy_image(sg_image img);\nSOKOL_GFX_API_DECL void sg_destroy_sampler(sg_sampler smp);\nSOKOL_GFX_API_DECL void sg_destroy_shader(sg_shader shd);\nSOKOL_GFX_API_DECL void sg_destroy_pipeline(sg_pipeline pip);\nSOKOL_GFX_API_DECL void sg_destroy_attachments(sg_attachments atts);\nSOKOL_GFX_API_DECL void sg_update_buffer(sg_buffer buf, const sg_range* data);\nSOKOL_GFX_API_DECL void sg_update_image(sg_image img, const sg_image_data* data);\nSOKOL_GFX_API_DECL int sg_append_buffer(sg_buffer buf, const sg_range* data);\nSOKOL_GFX_API_DECL bool sg_query_buffer_overflow(sg_buffer buf);\nSOKOL_GFX_API_DECL bool sg_query_buffer_will_overflow(sg_buffer buf, size_t size);\n\n// rendering functions\nSOKOL_GFX_API_DECL void sg_begin_pass(const sg_pass* pass);\nSOKOL_GFX_API_DECL void sg_apply_viewport(int x, int y, int width, int height, bool origin_top_left);\nSOKOL_GFX_API_DECL void sg_apply_viewportf(float x, float y, float width, float height, bool origin_top_left);\nSOKOL_GFX_API_DECL void sg_apply_scissor_rect(int x, int y, int width, int height, bool origin_top_left);\nSOKOL_GFX_API_DECL void sg_apply_scissor_rectf(float x, float y, float width, float height, bool origin_top_left);\nSOKOL_GFX_API_DECL void sg_apply_pipeline(sg_pipeline pip);\nSOKOL_GFX_API_DECL void sg_apply_bindings(const sg_bindings* bindings);\nSOKOL_GFX_API_DECL void sg_apply_uniforms(sg_shader_stage stage, int ub_index, const sg_range* data);\nSOKOL_GFX_API_DECL void sg_draw(int base_element, int num_elements, int num_instances);\nSOKOL_GFX_API_DECL void sg_end_pass(void);\nSOKOL_GFX_API_DECL void sg_commit(void);\n\n// getting information\nSOKOL_GFX_API_DECL sg_desc sg_query_desc(void);\nSOKOL_GFX_API_DECL sg_backend sg_query_backend(void);\nSOKOL_GFX_API_DECL sg_features sg_query_features(void);\nSOKOL_GFX_API_DECL sg_limits sg_query_limits(void);\nSOKOL_GFX_API_DECL sg_pixelformat_info sg_query_pixelformat(sg_pixel_format fmt);\nSOKOL_GFX_API_DECL int sg_query_row_pitch(sg_pixel_format fmt, int width, int row_align_bytes);\nSOKOL_GFX_API_DECL int sg_query_surface_pitch(sg_pixel_format fmt, int width, int height, int row_align_bytes);\n// get current state of a resource (INITIAL, ALLOC, VALID, FAILED, INVALID)\nSOKOL_GFX_API_DECL sg_resource_state sg_query_buffer_state(sg_buffer buf);\nSOKOL_GFX_API_DECL sg_resource_state sg_query_image_state(sg_image img);\nSOKOL_GFX_API_DECL sg_resource_state sg_query_sampler_state(sg_sampler smp);\nSOKOL_GFX_API_DECL sg_resource_state sg_query_shader_state(sg_shader shd);\nSOKOL_GFX_API_DECL sg_resource_state sg_query_pipeline_state(sg_pipeline pip);\nSOKOL_GFX_API_DECL sg_resource_state sg_query_attachments_state(sg_attachments atts);\n// get runtime information about a resource\nSOKOL_GFX_API_DECL sg_buffer_info sg_query_buffer_info(sg_buffer buf);\nSOKOL_GFX_API_DECL sg_image_info sg_query_image_info(sg_image img);\nSOKOL_GFX_API_DECL sg_sampler_info sg_query_sampler_info(sg_sampler smp);\nSOKOL_GFX_API_DECL sg_shader_info sg_query_shader_info(sg_shader shd);\nSOKOL_GFX_API_DECL sg_pipeline_info sg_query_pipeline_info(sg_pipeline pip);\nSOKOL_GFX_API_DECL sg_attachments_info sg_query_attachments_info(sg_attachments atts);\n// get desc structs matching a specific resource (NOTE that not all creation attributes may be provided)\nSOKOL_GFX_API_DECL sg_buffer_desc sg_query_buffer_desc(sg_buffer buf);\nSOKOL_GFX_API_DECL sg_image_desc sg_query_image_desc(sg_image img);\nSOKOL_GFX_API_DECL sg_sampler_desc sg_query_sampler_desc(sg_sampler smp);\nSOKOL_GFX_API_DECL sg_shader_desc sg_query_shader_desc(sg_shader shd);\nSOKOL_GFX_API_DECL sg_pipeline_desc sg_query_pipeline_desc(sg_pipeline pip);\nSOKOL_GFX_API_DECL sg_attachments_desc sg_query_attachments_desc(sg_attachments atts);\n// get resource creation desc struct with their default values replaced\nSOKOL_GFX_API_DECL sg_buffer_desc sg_query_buffer_defaults(const sg_buffer_desc* desc);\nSOKOL_GFX_API_DECL sg_image_desc sg_query_image_defaults(const sg_image_desc* desc);\nSOKOL_GFX_API_DECL sg_sampler_desc sg_query_sampler_defaults(const sg_sampler_desc* desc);\nSOKOL_GFX_API_DECL sg_shader_desc sg_query_shader_defaults(const sg_shader_desc* desc);\nSOKOL_GFX_API_DECL sg_pipeline_desc sg_query_pipeline_defaults(const sg_pipeline_desc* desc);\nSOKOL_GFX_API_DECL sg_attachments_desc sg_query_attachments_defaults(const sg_attachments_desc* desc);\n\n// separate resource allocation and initialization (for async setup)\nSOKOL_GFX_API_DECL sg_buffer sg_alloc_buffer(void);\nSOKOL_GFX_API_DECL sg_image sg_alloc_image(void);\nSOKOL_GFX_API_DECL sg_sampler sg_alloc_sampler(void);\nSOKOL_GFX_API_DECL sg_shader sg_alloc_shader(void);\nSOKOL_GFX_API_DECL sg_pipeline sg_alloc_pipeline(void);\nSOKOL_GFX_API_DECL sg_attachments sg_alloc_attachments(void);\nSOKOL_GFX_API_DECL void sg_dealloc_buffer(sg_buffer buf);\nSOKOL_GFX_API_DECL void sg_dealloc_image(sg_image img);\nSOKOL_GFX_API_DECL void sg_dealloc_sampler(sg_sampler smp);\nSOKOL_GFX_API_DECL void sg_dealloc_shader(sg_shader shd);\nSOKOL_GFX_API_DECL void sg_dealloc_pipeline(sg_pipeline pip);\nSOKOL_GFX_API_DECL void sg_dealloc_attachments(sg_attachments attachments);\nSOKOL_GFX_API_DECL void sg_init_buffer(sg_buffer buf, const sg_buffer_desc* desc);\nSOKOL_GFX_API_DECL void sg_init_image(sg_image img, const sg_image_desc* desc);\nSOKOL_GFX_API_DECL void sg_init_sampler(sg_sampler smg, const sg_sampler_desc* desc);\nSOKOL_GFX_API_DECL void sg_init_shader(sg_shader shd, const sg_shader_desc* desc);\nSOKOL_GFX_API_DECL void sg_init_pipeline(sg_pipeline pip, const sg_pipeline_desc* desc);\nSOKOL_GFX_API_DECL void sg_init_attachments(sg_attachments attachments, const sg_attachments_desc* desc);\nSOKOL_GFX_API_DECL void sg_uninit_buffer(sg_buffer buf);\nSOKOL_GFX_API_DECL void sg_uninit_image(sg_image img);\nSOKOL_GFX_API_DECL void sg_uninit_sampler(sg_sampler smp);\nSOKOL_GFX_API_DECL void sg_uninit_shader(sg_shader shd);\nSOKOL_GFX_API_DECL void sg_uninit_pipeline(sg_pipeline pip);\nSOKOL_GFX_API_DECL void sg_uninit_attachments(sg_attachments atts);\nSOKOL_GFX_API_DECL void sg_fail_buffer(sg_buffer buf);\nSOKOL_GFX_API_DECL void sg_fail_image(sg_image img);\nSOKOL_GFX_API_DECL void sg_fail_sampler(sg_sampler smp);\nSOKOL_GFX_API_DECL void sg_fail_shader(sg_shader shd);\nSOKOL_GFX_API_DECL void sg_fail_pipeline(sg_pipeline pip);\nSOKOL_GFX_API_DECL void sg_fail_attachments(sg_attachments atts);\n\n// frame stats\nSOKOL_GFX_API_DECL void sg_enable_frame_stats(void);\nSOKOL_GFX_API_DECL void sg_disable_frame_stats(void);\nSOKOL_GFX_API_DECL bool sg_frame_stats_enabled(void);\nSOKOL_GFX_API_DECL sg_frame_stats sg_query_frame_stats(void);\n\n/* Backend-specific structs and functions, these may come in handy for mixing\n   sokol-gfx rendering with 'native backend' rendering functions.\n\n   This group of functions will be expanded as needed.\n*/\n\ntypedef struct sg_d3d11_buffer_info {\n    const void* buf;      // ID3D11Buffer*\n} sg_d3d11_buffer_info;\n\ntypedef struct sg_d3d11_image_info {\n    const void* tex2d;    // ID3D11Texture2D*\n    const void* tex3d;    // ID3D11Texture3D*\n    const void* res;      // ID3D11Resource* (either tex2d or tex3d)\n    const void* srv;      // ID3D11ShaderResourceView*\n} sg_d3d11_image_info;\n\ntypedef struct sg_d3d11_sampler_info {\n    const void* smp;      // ID3D11SamplerState*\n} sg_d3d11_sampler_info;\n\ntypedef struct sg_d3d11_shader_info {\n    const void* vs_cbufs[SG_MAX_SHADERSTAGE_UBS]; // ID3D11Buffer* (vertex stage constant buffers)\n    const void* fs_cbufs[SG_MAX_SHADERSTAGE_UBS]; // ID3D11Buffer* (fragment stage constant buffers)\n    const void* vs;   // ID3D11VertexShader*\n    const void* fs;   // ID3D11PixelShader*\n} sg_d3d11_shader_info;\n\ntypedef struct sg_d3d11_pipeline_info {\n    const void* il;   // ID3D11InputLayout*\n    const void* rs;   // ID3D11RasterizerState*\n    const void* dss;  // ID3D11DepthStencilState*\n    const void* bs;   // ID3D11BlendState*\n} sg_d3d11_pipeline_info;\n\ntypedef struct sg_d3d11_attachments_info {\n    const void* color_rtv[SG_MAX_COLOR_ATTACHMENTS];      // ID3D11RenderTargetView\n    const void* resolve_rtv[SG_MAX_COLOR_ATTACHMENTS];    // ID3D11RenderTargetView\n    const void* dsv;  // ID3D11DepthStencilView\n} sg_d3d11_attachments_info;\n\ntypedef struct sg_mtl_buffer_info {\n    const void* buf[SG_NUM_INFLIGHT_FRAMES];  // id<MTLBuffer>\n    int active_slot;\n} sg_mtl_buffer_info;\n\ntypedef struct sg_mtl_image_info {\n    const void* tex[SG_NUM_INFLIGHT_FRAMES]; // id<MTLTexture>\n    int active_slot;\n} sg_mtl_image_info;\n\ntypedef struct sg_mtl_sampler_info {\n    const void* smp;  // id<MTLSamplerState>\n} sg_mtl_sampler_info;\n\ntypedef struct sg_mtl_shader_info {\n    const void* vs_lib;   // id<MTLLibrary>\n    const void* fs_lib;   // id<MTLLibrary>\n    const void* vs_func;  // id<MTLFunction>\n    const void* fs_func;  // id<MTLFunction>\n} sg_mtl_shader_info;\n\ntypedef struct sg_mtl_pipeline_info {\n    const void* rps;      // id<MTLRenderPipelineState>\n    const void* dss;      // id<MTLDepthStencilState>\n} sg_mtl_pipeline_info;\n\ntypedef struct sg_wgpu_buffer_info {\n    const void* buf;  // WGPUBuffer\n} sg_wgpu_buffer_info;\n\ntypedef struct sg_wgpu_image_info {\n    const void* tex;  // WGPUTexture\n    const void* view; // WGPUTextureView\n} sg_wgpu_image_info;\n\ntypedef struct sg_wgpu_sampler_info {\n    const void* smp;  // WGPUSampler\n} sg_wgpu_sampler_info;\n\ntypedef struct sg_wgpu_shader_info {\n    const void* vs_mod;   // WGPUShaderModule\n    const void* fs_mod;   // WGPUShaderModule\n    const void* bgl;      // WGPUBindGroupLayout;\n} sg_wgpu_shader_info;\n\ntypedef struct sg_wgpu_pipeline_info {\n    const void* pip;      // WGPURenderPipeline\n} sg_wgpu_pipeline_info;\n\ntypedef struct sg_wgpu_attachments_info {\n    const void* color_view[SG_MAX_COLOR_ATTACHMENTS];     // WGPUTextureView\n    const void* resolve_view[SG_MAX_COLOR_ATTACHMENTS];    // WGPUTextureView\n    const void* ds_view;  // WGPUTextureView\n} sg_wgpu_attachments_info;\n\ntypedef struct sg_gl_buffer_info {\n    uint32_t buf[SG_NUM_INFLIGHT_FRAMES];\n    int active_slot;\n} sg_gl_buffer_info;\n\ntypedef struct sg_gl_image_info {\n    uint32_t tex[SG_NUM_INFLIGHT_FRAMES];\n    uint32_t tex_target;\n    uint32_t msaa_render_buffer;\n    int active_slot;\n} sg_gl_image_info;\n\ntypedef struct sg_gl_sampler_info {\n    uint32_t smp;\n} sg_gl_sampler_info;\n\ntypedef struct sg_gl_shader_info {\n    uint32_t prog;\n} sg_gl_shader_info;\n\ntypedef struct sg_gl_attachments_info {\n    uint32_t framebuffer;\n    uint32_t msaa_resolve_framebuffer[SG_MAX_COLOR_ATTACHMENTS];\n} sg_gl_attachments_info;\n\n// D3D11: return ID3D11Device\nSOKOL_GFX_API_DECL const void* sg_d3d11_device(void);\n// D3D11: return ID3D11DeviceContext\nSOKOL_GFX_API_DECL const void* sg_d3d11_device_context(void);\n// D3D11: get internal buffer resource objects\nSOKOL_GFX_API_DECL sg_d3d11_buffer_info sg_d3d11_query_buffer_info(sg_buffer buf);\n// D3D11: get internal image resource objects\nSOKOL_GFX_API_DECL sg_d3d11_image_info sg_d3d11_query_image_info(sg_image img);\n// D3D11: get internal sampler resource objects\nSOKOL_GFX_API_DECL sg_d3d11_sampler_info sg_d3d11_query_sampler_info(sg_sampler smp);\n// D3D11: get internal shader resource objects\nSOKOL_GFX_API_DECL sg_d3d11_shader_info sg_d3d11_query_shader_info(sg_shader shd);\n// D3D11: get internal pipeline resource objects\nSOKOL_GFX_API_DECL sg_d3d11_pipeline_info sg_d3d11_query_pipeline_info(sg_pipeline pip);\n// D3D11: get internal pass resource objects\nSOKOL_GFX_API_DECL sg_d3d11_attachments_info sg_d3d11_query_attachments_info(sg_attachments atts);\n\n// Metal: return __bridge-casted MTLDevice\nSOKOL_GFX_API_DECL const void* sg_mtl_device(void);\n// Metal: return __bridge-casted MTLRenderCommandEncoder in current pass (or zero if outside pass)\nSOKOL_GFX_API_DECL const void* sg_mtl_render_command_encoder(void);\n// Metal: get internal __bridge-casted buffer resource objects\nSOKOL_GFX_API_DECL sg_mtl_buffer_info sg_mtl_query_buffer_info(sg_buffer buf);\n// Metal: get internal __bridge-casted image resource objects\nSOKOL_GFX_API_DECL sg_mtl_image_info sg_mtl_query_image_info(sg_image img);\n// Metal: get internal __bridge-casted sampler resource objects\nSOKOL_GFX_API_DECL sg_mtl_sampler_info sg_mtl_query_sampler_info(sg_sampler smp);\n// Metal: get internal __bridge-casted shader resource objects\nSOKOL_GFX_API_DECL sg_mtl_shader_info sg_mtl_query_shader_info(sg_shader shd);\n// Metal: get internal __bridge-casted pipeline resource objects\nSOKOL_GFX_API_DECL sg_mtl_pipeline_info sg_mtl_query_pipeline_info(sg_pipeline pip);\n\n// WebGPU: return WGPUDevice object\nSOKOL_GFX_API_DECL const void* sg_wgpu_device(void);\n// WebGPU: return WGPUQueue object\nSOKOL_GFX_API_DECL const void* sg_wgpu_queue(void);\n// WebGPU: return this frame's WGPUCommandEncoder\nSOKOL_GFX_API_DECL const void* sg_wgpu_command_encoder(void);\n// WebGPU: return WGPURenderPassEncoder of current pass\nSOKOL_GFX_API_DECL const void* sg_wgpu_render_pass_encoder(void);\n// WebGPU: get internal buffer resource objects\nSOKOL_GFX_API_DECL sg_wgpu_buffer_info sg_wgpu_query_buffer_info(sg_buffer buf);\n// WebGPU: get internal image resource objects\nSOKOL_GFX_API_DECL sg_wgpu_image_info sg_wgpu_query_image_info(sg_image img);\n// WebGPU: get internal sampler resource objects\nSOKOL_GFX_API_DECL sg_wgpu_sampler_info sg_wgpu_query_sampler_info(sg_sampler smp);\n// WebGPU: get internal shader resource objects\nSOKOL_GFX_API_DECL sg_wgpu_shader_info sg_wgpu_query_shader_info(sg_shader shd);\n// WebGPU: get internal pipeline resource objects\nSOKOL_GFX_API_DECL sg_wgpu_pipeline_info sg_wgpu_query_pipeline_info(sg_pipeline pip);\n// WebGPU: get internal pass resource objects\nSOKOL_GFX_API_DECL sg_wgpu_attachments_info sg_wgpu_query_attachments_info(sg_attachments atts);\n\n// GL: get internal buffer resource objects\nSOKOL_GFX_API_DECL sg_gl_buffer_info sg_gl_query_buffer_info(sg_buffer buf);\n// GL: get internal image resource objects\nSOKOL_GFX_API_DECL sg_gl_image_info sg_gl_query_image_info(sg_image img);\n// GL: get internal sampler resource objects\nSOKOL_GFX_API_DECL sg_gl_sampler_info sg_gl_query_sampler_info(sg_sampler smp);\n// GL: get internal shader resource objects\nSOKOL_GFX_API_DECL sg_gl_shader_info sg_gl_query_shader_info(sg_shader shd);\n// GL: get internal pass resource objects\nSOKOL_GFX_API_DECL sg_gl_attachments_info sg_gl_query_attachments_info(sg_attachments atts);\n\n#ifdef __cplusplus\n} // extern \"C\"\n\n// reference-based equivalents for c++\ninline void sg_setup(const sg_desc& desc) { return sg_setup(&desc); }\n\ninline sg_buffer sg_make_buffer(const sg_buffer_desc& desc) { return sg_make_buffer(&desc); }\ninline sg_image sg_make_image(const sg_image_desc& desc) { return sg_make_image(&desc); }\ninline sg_sampler sg_make_sampler(const sg_sampler_desc& desc) { return sg_make_sampler(&desc); }\ninline sg_shader sg_make_shader(const sg_shader_desc& desc) { return sg_make_shader(&desc); }\ninline sg_pipeline sg_make_pipeline(const sg_pipeline_desc& desc) { return sg_make_pipeline(&desc); }\ninline sg_attachments sg_make_attachments(const sg_attachments_desc& desc) { return sg_make_attachments(&desc); }\ninline void sg_update_image(sg_image img, const sg_image_data& data) { return sg_update_image(img, &data); }\n\ninline void sg_begin_pass(const sg_pass& pass) { return sg_begin_pass(&pass); }\ninline void sg_apply_bindings(const sg_bindings& bindings) { return sg_apply_bindings(&bindings); }\ninline void sg_apply_uniforms(sg_shader_stage stage, int ub_index, const sg_range& data) { return sg_apply_uniforms(stage, ub_index, &data); }\n\ninline sg_buffer_desc sg_query_buffer_defaults(const sg_buffer_desc& desc) { return sg_query_buffer_defaults(&desc); }\ninline sg_image_desc sg_query_image_defaults(const sg_image_desc& desc) { return sg_query_image_defaults(&desc); }\ninline sg_sampler_desc sg_query_sampler_defaults(const sg_sampler_desc& desc) { return sg_query_sampler_defaults(&desc); }\ninline sg_shader_desc sg_query_shader_defaults(const sg_shader_desc& desc) { return sg_query_shader_defaults(&desc); }\ninline sg_pipeline_desc sg_query_pipeline_defaults(const sg_pipeline_desc& desc) { return sg_query_pipeline_defaults(&desc); }\ninline sg_attachments_desc sg_query_attachments_defaults(const sg_attachments_desc& desc) { return sg_query_attachments_defaults(&desc); }\n\ninline void sg_init_buffer(sg_buffer buf, const sg_buffer_desc& desc) { return sg_init_buffer(buf, &desc); }\ninline void sg_init_image(sg_image img, const sg_image_desc& desc) { return sg_init_image(img, &desc); }\ninline void sg_init_sampler(sg_sampler smp, const sg_sampler_desc& desc) { return sg_init_sampler(smp, &desc); }\ninline void sg_init_shader(sg_shader shd, const sg_shader_desc& desc) { return sg_init_shader(shd, &desc); }\ninline void sg_init_pipeline(sg_pipeline pip, const sg_pipeline_desc& desc) { return sg_init_pipeline(pip, &desc); }\ninline void sg_init_attachments(sg_attachments atts, const sg_attachments_desc& desc) { return sg_init_attachments(atts, &desc); }\n\ninline void sg_update_buffer(sg_buffer buf_id, const sg_range& data) { return sg_update_buffer(buf_id, &data); }\ninline int sg_append_buffer(sg_buffer buf_id, const sg_range& data) { return sg_append_buffer(buf_id, &data); }\n#endif\n#endif // SOKOL_GFX_INCLUDED\n\n// ██ ███    ███ ██████  ██      ███████ ███    ███ ███████ ███    ██ ████████  █████  ████████ ██  ██████  ███    ██\n// ██ ████  ████ ██   ██ ██      ██      ████  ████ ██      ████   ██    ██    ██   ██    ██    ██ ██    ██ ████   ██\n// ██ ██ ████ ██ ██████  ██      █████   ██ ████ ██ █████   ██ ██  ██    ██    ███████    ██    ██ ██    ██ ██ ██  ██\n// ██ ██  ██  ██ ██      ██      ██      ██  ██  ██ ██      ██  ██ ██    ██    ██   ██    ██    ██ ██    ██ ██  ██ ██\n// ██ ██      ██ ██      ███████ ███████ ██      ██ ███████ ██   ████    ██    ██   ██    ██    ██  ██████  ██   ████\n//\n// >>implementation\n#ifdef SOKOL_GFX_IMPL\n#define SOKOL_GFX_IMPL_INCLUDED (1)\n\n#if !(defined(SOKOL_GLCORE)||defined(SOKOL_GLES3)||defined(SOKOL_D3D11)||defined(SOKOL_METAL)||defined(SOKOL_WGPU)||defined(SOKOL_DUMMY_BACKEND))\n#error \"Please select a backend with SOKOL_GLCORE, SOKOL_GLES3, SOKOL_D3D11, SOKOL_METAL, SOKOL_WGPU or SOKOL_DUMMY_BACKEND\"\n#endif\n#if defined(SOKOL_MALLOC) || defined(SOKOL_CALLOC) || defined(SOKOL_FREE)\n#error \"SOKOL_MALLOC/CALLOC/FREE macros are no longer supported, please use sg_desc.allocator to override memory allocation functions\"\n#endif\n\n#include <stdlib.h> // malloc, free\n#include <string.h> // memset\n#include <float.h> // FLT_MAX\n\n#ifndef SOKOL_API_IMPL\n    #define SOKOL_API_IMPL\n#endif\n#ifndef SOKOL_DEBUG\n    #ifndef NDEBUG\n        #define SOKOL_DEBUG\n    #endif\n#endif\n#ifndef SOKOL_ASSERT\n    #include <assert.h>\n    #define SOKOL_ASSERT(c) assert(c)\n#endif\n#ifndef SOKOL_UNREACHABLE\n    #define SOKOL_UNREACHABLE SOKOL_ASSERT(false)\n#endif\n\n#ifndef _SOKOL_PRIVATE\n    #if defined(__GNUC__) || defined(__clang__)\n        #define _SOKOL_PRIVATE __attribute__((unused)) static\n    #else\n        #define _SOKOL_PRIVATE static\n    #endif\n#endif\n\n#ifndef _SOKOL_UNUSED\n    #define _SOKOL_UNUSED(x) (void)(x)\n#endif\n\n#if defined(SOKOL_TRACE_HOOKS)\n#define _SG_TRACE_ARGS(fn, ...) if (_sg.hooks.fn) { _sg.hooks.fn(__VA_ARGS__, _sg.hooks.user_data); }\n#define _SG_TRACE_NOARGS(fn) if (_sg.hooks.fn) { _sg.hooks.fn(_sg.hooks.user_data); }\n#else\n#define _SG_TRACE_ARGS(fn, ...)\n#define _SG_TRACE_NOARGS(fn)\n#endif\n\n// default clear values\n#ifndef SG_DEFAULT_CLEAR_RED\n#define SG_DEFAULT_CLEAR_RED (0.5f)\n#endif\n#ifndef SG_DEFAULT_CLEAR_GREEN\n#define SG_DEFAULT_CLEAR_GREEN (0.5f)\n#endif\n#ifndef SG_DEFAULT_CLEAR_BLUE\n#define SG_DEFAULT_CLEAR_BLUE (0.5f)\n#endif\n#ifndef SG_DEFAULT_CLEAR_ALPHA\n#define SG_DEFAULT_CLEAR_ALPHA (1.0f)\n#endif\n#ifndef SG_DEFAULT_CLEAR_DEPTH\n#define SG_DEFAULT_CLEAR_DEPTH (1.0f)\n#endif\n#ifndef SG_DEFAULT_CLEAR_STENCIL\n#define SG_DEFAULT_CLEAR_STENCIL (0)\n#endif\n\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable:4115)   // named type definition in parentheses\n#pragma warning(disable:4505)   // unreferenced local function has been removed\n#pragma warning(disable:4201)   // nonstandard extension used: nameless struct/union (needed by d3d11.h)\n#pragma warning(disable:4054)   // 'type cast': from function pointer\n#pragma warning(disable:4055)   // 'type cast': from data pointer\n#endif\n\n#if defined(SOKOL_D3D11)\n    #ifndef D3D11_NO_HELPERS\n    #define D3D11_NO_HELPERS\n    #endif\n    #ifndef WIN32_LEAN_AND_MEAN\n    #define WIN32_LEAN_AND_MEAN\n    #endif\n    #ifndef NOMINMAX\n    #define NOMINMAX\n    #endif\n    #include <d3d11.h>\n    #include <d3dcompiler.h>\n    #ifdef _MSC_VER\n    #pragma comment (lib, \"kernel32\")\n    #pragma comment (lib, \"user32\")\n    #pragma comment (lib, \"dxgi\")\n    #pragma comment (lib, \"d3d11\")\n    #endif\n#elif defined(SOKOL_METAL)\n    // see https://clang.llvm.org/docs/LanguageExtensions.html#automatic-reference-counting\n    #if !defined(__cplusplus)\n        #if __has_feature(objc_arc) && !__has_feature(objc_arc_fields)\n            #error \"sokol_gfx.h requires __has_feature(objc_arc_field) if ARC is enabled (use a more recent compiler version)\"\n        #endif\n    #endif\n    #include <TargetConditionals.h>\n    #include <AvailabilityMacros.h>\n    #if defined(TARGET_OS_IPHONE) && !TARGET_OS_IPHONE\n        #define _SG_TARGET_MACOS (1)\n    #else\n        #define _SG_TARGET_IOS (1)\n        #if defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR\n            #define _SG_TARGET_IOS_SIMULATOR (1)\n        #endif\n    #endif\n    #import <Metal/Metal.h>\n    #import <QuartzCore/CoreAnimation.h> // needed for CAMetalDrawable\n#elif defined(SOKOL_WGPU)\n    #include <webgpu/webgpu.h>\n    #if defined(__EMSCRIPTEN__)\n        #include <emscripten/emscripten.h>\n    #endif\n#elif defined(SOKOL_GLCORE) || defined(SOKOL_GLES3)\n    #define _SOKOL_ANY_GL (1)\n\n    // include platform specific GL headers (or on Win32: use an embedded GL loader)\n    #if !defined(SOKOL_EXTERNAL_GL_LOADER)\n        #if defined(_WIN32)\n            #if defined(SOKOL_GLCORE) && !defined(SOKOL_EXTERNAL_GL_LOADER)\n                #ifndef WIN32_LEAN_AND_MEAN\n                #define WIN32_LEAN_AND_MEAN\n                #endif\n                #ifndef NOMINMAX\n                #define NOMINMAX\n                #endif\n                #include <windows.h>\n                #define _SOKOL_USE_WIN32_GL_LOADER (1)\n                #pragma comment (lib, \"kernel32\")   // GetProcAddress()\n            #endif\n        #elif defined(__APPLE__)\n            #include <TargetConditionals.h>\n            #ifndef GL_SILENCE_DEPRECATION\n                #define GL_SILENCE_DEPRECATION\n            #endif\n            #if defined(TARGET_OS_IPHONE) && !TARGET_OS_IPHONE\n                #include <OpenGL/gl3.h>\n            #else\n                #include <OpenGLES/ES3/gl.h>\n                #include <OpenGLES/ES3/glext.h>\n            #endif\n        #elif defined(__EMSCRIPTEN__) || defined(__ANDROID__)\n            #if defined(SOKOL_GLES3)\n                #include <GLES3/gl3.h>\n            #endif\n        #elif defined(__linux__) || defined(__unix__)\n            #if defined(SOKOL_GLCORE)\n                #define GL_GLEXT_PROTOTYPES\n                #include <GL/gl.h>\n            #else\n                #include <GLES3/gl3.h>\n                #include <GLES3/gl3ext.h>\n            #endif\n        #endif\n    #endif\n\n    // optional GL loader definitions (only on Win32)\n    #if defined(_SOKOL_USE_WIN32_GL_LOADER)\n        #define __gl_h_ 1\n        #define __gl32_h_ 1\n        #define __gl31_h_ 1\n        #define __GL_H__ 1\n        #define __glext_h_ 1\n        #define __GLEXT_H_ 1\n        #define __gltypes_h_ 1\n        #define __glcorearb_h_ 1\n        #define __gl_glcorearb_h_ 1\n        #define GL_APIENTRY APIENTRY\n\n        typedef unsigned int  GLenum;\n        typedef unsigned int  GLuint;\n        typedef int  GLsizei;\n        typedef char  GLchar;\n        typedef ptrdiff_t  GLintptr;\n        typedef ptrdiff_t  GLsizeiptr;\n        typedef double  GLclampd;\n        typedef unsigned short  GLushort;\n        typedef unsigned char  GLubyte;\n        typedef unsigned char  GLboolean;\n        typedef uint64_t  GLuint64;\n        typedef double  GLdouble;\n        typedef unsigned short  GLhalf;\n        typedef float  GLclampf;\n        typedef unsigned int  GLbitfield;\n        typedef signed char  GLbyte;\n        typedef short  GLshort;\n        typedef void  GLvoid;\n        typedef int64_t  GLint64;\n        typedef float  GLfloat;\n        typedef int  GLint;\n        #define GL_INT_2_10_10_10_REV 0x8D9F\n        #define GL_R32F 0x822E\n        #define GL_PROGRAM_POINT_SIZE 0x8642\n        #define GL_DEPTH_ATTACHMENT 0x8D00\n        #define GL_DEPTH_STENCIL_ATTACHMENT 0x821A\n        #define GL_COLOR_ATTACHMENT2 0x8CE2\n        #define GL_COLOR_ATTACHMENT0 0x8CE0\n        #define GL_R16F 0x822D\n        #define GL_COLOR_ATTACHMENT22 0x8CF6\n        #define GL_DRAW_FRAMEBUFFER 0x8CA9\n        #define GL_FRAMEBUFFER_COMPLETE 0x8CD5\n        #define GL_NUM_EXTENSIONS 0x821D\n        #define GL_INFO_LOG_LENGTH 0x8B84\n        #define GL_VERTEX_SHADER 0x8B31\n        #define GL_INCR 0x1E02\n        #define GL_DYNAMIC_DRAW 0x88E8\n        #define GL_STATIC_DRAW 0x88E4\n        #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519\n        #define GL_TEXTURE_CUBE_MAP 0x8513\n        #define GL_FUNC_SUBTRACT 0x800A\n        #define GL_FUNC_REVERSE_SUBTRACT 0x800B\n        #define GL_CONSTANT_COLOR 0x8001\n        #define GL_DECR_WRAP 0x8508\n        #define GL_R8 0x8229\n        #define GL_LINEAR_MIPMAP_LINEAR 0x2703\n        #define GL_ELEMENT_ARRAY_BUFFER 0x8893\n        #define GL_SHORT 0x1402\n        #define GL_DEPTH_TEST 0x0B71\n        #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518\n        #define GL_LINK_STATUS 0x8B82\n        #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517\n        #define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E\n        #define GL_RGBA16F 0x881A\n        #define GL_CONSTANT_ALPHA 0x8003\n        #define GL_READ_FRAMEBUFFER 0x8CA8\n        #define GL_TEXTURE0 0x84C0\n        #define GL_TEXTURE_MIN_LOD 0x813A\n        #define GL_CLAMP_TO_EDGE 0x812F\n        #define GL_UNSIGNED_SHORT_5_6_5 0x8363\n        #define GL_TEXTURE_WRAP_R 0x8072\n        #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034\n        #define GL_NEAREST_MIPMAP_NEAREST 0x2700\n        #define GL_UNSIGNED_SHORT_4_4_4_4 0x8033\n        #define GL_SRC_ALPHA_SATURATE 0x0308\n        #define GL_STREAM_DRAW 0x88E0\n        #define GL_ONE 1\n        #define GL_NEAREST_MIPMAP_LINEAR 0x2702\n        #define GL_RGB10_A2 0x8059\n        #define GL_RGBA8 0x8058\n        #define GL_SRGB8_ALPHA8 0x8C43\n        #define GL_COLOR_ATTACHMENT1 0x8CE1\n        #define GL_RGBA4 0x8056\n        #define GL_RGB8 0x8051\n        #define GL_ARRAY_BUFFER 0x8892\n        #define GL_STENCIL 0x1802\n        #define GL_TEXTURE_2D 0x0DE1\n        #define GL_DEPTH 0x1801\n        #define GL_FRONT 0x0404\n        #define GL_STENCIL_BUFFER_BIT 0x00000400\n        #define GL_REPEAT 0x2901\n        #define GL_RGBA 0x1908\n        #define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515\n        #define GL_DECR 0x1E03\n        #define GL_FRAGMENT_SHADER 0x8B30\n        #define GL_FLOAT 0x1406\n        #define GL_TEXTURE_MAX_LOD 0x813B\n        #define GL_DEPTH_COMPONENT 0x1902\n        #define GL_ONE_MINUS_DST_ALPHA 0x0305\n        #define GL_COLOR 0x1800\n        #define GL_TEXTURE_2D_ARRAY 0x8C1A\n        #define GL_TRIANGLES 0x0004\n        #define GL_UNSIGNED_BYTE 0x1401\n        #define GL_TEXTURE_MAG_FILTER 0x2800\n        #define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004\n        #define GL_NONE 0\n        #define GL_SRC_COLOR 0x0300\n        #define GL_BYTE 0x1400\n        #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A\n        #define GL_LINE_STRIP 0x0003\n        #define GL_TEXTURE_3D 0x806F\n        #define GL_CW 0x0900\n        #define GL_LINEAR 0x2601\n        #define GL_RENDERBUFFER 0x8D41\n        #define GL_GEQUAL 0x0206\n        #define GL_COLOR_BUFFER_BIT 0x00004000\n        #define GL_RGBA32F 0x8814\n        #define GL_BLEND 0x0BE2\n        #define GL_ONE_MINUS_SRC_ALPHA 0x0303\n        #define GL_ONE_MINUS_CONSTANT_COLOR 0x8002\n        #define GL_TEXTURE_WRAP_T 0x2803\n        #define GL_TEXTURE_WRAP_S 0x2802\n        #define GL_TEXTURE_MIN_FILTER 0x2801\n        #define GL_LINEAR_MIPMAP_NEAREST 0x2701\n        #define GL_EXTENSIONS 0x1F03\n        #define GL_NO_ERROR 0\n        #define GL_REPLACE 0x1E01\n        #define GL_KEEP 0x1E00\n        #define GL_CCW 0x0901\n        #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516\n        #define GL_RGB 0x1907\n        #define GL_TRIANGLE_STRIP 0x0005\n        #define GL_FALSE 0\n        #define GL_ZERO 0\n        #define GL_CULL_FACE 0x0B44\n        #define GL_INVERT 0x150A\n        #define GL_INT 0x1404\n        #define GL_UNSIGNED_INT 0x1405\n        #define GL_UNSIGNED_SHORT 0x1403\n        #define GL_NEAREST 0x2600\n        #define GL_SCISSOR_TEST 0x0C11\n        #define GL_LEQUAL 0x0203\n        #define GL_STENCIL_TEST 0x0B90\n        #define GL_DITHER 0x0BD0\n        #define GL_DEPTH_COMPONENT32F 0x8CAC\n        #define GL_EQUAL 0x0202\n        #define GL_FRAMEBUFFER 0x8D40\n        #define GL_RGB5 0x8050\n        #define GL_LINES 0x0001\n        #define GL_DEPTH_BUFFER_BIT 0x00000100\n        #define GL_SRC_ALPHA 0x0302\n        #define GL_INCR_WRAP 0x8507\n        #define GL_LESS 0x0201\n        #define GL_MULTISAMPLE 0x809D\n        #define GL_FRAMEBUFFER_BINDING 0x8CA6\n        #define GL_BACK 0x0405\n        #define GL_ALWAYS 0x0207\n        #define GL_FUNC_ADD 0x8006\n        #define GL_ONE_MINUS_DST_COLOR 0x0307\n        #define GL_NOTEQUAL 0x0205\n        #define GL_DST_COLOR 0x0306\n        #define GL_COMPILE_STATUS 0x8B81\n        #define GL_RED 0x1903\n        #define GL_COLOR_ATTACHMENT3 0x8CE3\n        #define GL_DST_ALPHA 0x0304\n        #define GL_RGB5_A1 0x8057\n        #define GL_GREATER 0x0204\n        #define GL_POLYGON_OFFSET_FILL 0x8037\n        #define GL_TRUE 1\n        #define GL_NEVER 0x0200\n        #define GL_POINTS 0x0000\n        #define GL_ONE_MINUS_SRC_COLOR 0x0301\n        #define GL_MIRRORED_REPEAT 0x8370\n        #define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D\n        #define GL_R11F_G11F_B10F 0x8C3A\n        #define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B\n        #define GL_RGB9_E5 0x8C3D\n        #define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E\n        #define GL_RGBA32UI 0x8D70\n        #define GL_RGB32UI 0x8D71\n        #define GL_RGBA16UI 0x8D76\n        #define GL_RGB16UI 0x8D77\n        #define GL_RGBA8UI 0x8D7C\n        #define GL_RGB8UI 0x8D7D\n        #define GL_RGBA32I 0x8D82\n        #define GL_RGB32I 0x8D83\n        #define GL_RGBA16I 0x8D88\n        #define GL_RGB16I 0x8D89\n        #define GL_RGBA8I 0x8D8E\n        #define GL_RGB8I 0x8D8F\n        #define GL_RED_INTEGER 0x8D94\n        #define GL_RG 0x8227\n        #define GL_RG_INTEGER 0x8228\n        #define GL_R8 0x8229\n        #define GL_R16 0x822A\n        #define GL_RG8 0x822B\n        #define GL_RG16 0x822C\n        #define GL_R16F 0x822D\n        #define GL_R32F 0x822E\n        #define GL_RG16F 0x822F\n        #define GL_RG32F 0x8230\n        #define GL_R8I 0x8231\n        #define GL_R8UI 0x8232\n        #define GL_R16I 0x8233\n        #define GL_R16UI 0x8234\n        #define GL_R32I 0x8235\n        #define GL_R32UI 0x8236\n        #define GL_RG8I 0x8237\n        #define GL_RG8UI 0x8238\n        #define GL_RG16I 0x8239\n        #define GL_RG16UI 0x823A\n        #define GL_RG32I 0x823B\n        #define GL_RG32UI 0x823C\n        #define GL_RGBA_INTEGER 0x8D99\n        #define GL_R8_SNORM 0x8F94\n        #define GL_RG8_SNORM 0x8F95\n        #define GL_RGB8_SNORM 0x8F96\n        #define GL_RGBA8_SNORM 0x8F97\n        #define GL_R16_SNORM 0x8F98\n        #define GL_RG16_SNORM 0x8F99\n        #define GL_RGB16_SNORM 0x8F9A\n        #define GL_RGBA16_SNORM 0x8F9B\n        #define GL_RGBA16 0x805B\n        #define GL_MAX_TEXTURE_SIZE 0x0D33\n        #define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C\n        #define GL_MAX_3D_TEXTURE_SIZE 0x8073\n        #define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF\n        #define GL_MAX_VERTEX_ATTRIBS 0x8869\n        #define GL_CLAMP_TO_BORDER 0x812D\n        #define GL_TEXTURE_BORDER_COLOR 0x1004\n        #define GL_CURRENT_PROGRAM 0x8B8D\n        #define GL_MAX_VERTEX_UNIFORM_COMPONENTS  0x8B4A\n        #define GL_UNPACK_ALIGNMENT 0x0CF5\n        #define GL_FRAMEBUFFER_SRGB 0x8DB9\n        #define GL_TEXTURE_COMPARE_MODE 0x884C\n        #define GL_TEXTURE_COMPARE_FUNC 0x884D\n        #define GL_COMPARE_REF_TO_TEXTURE 0x884E\n        #define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F\n        #define GL_TEXTURE_MAX_LEVEL 0x813D\n        #define GL_FRAMEBUFFER_UNDEFINED 0x8219\n        #define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6\n        #define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7\n        #define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD\n        #define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56\n        #define GL_MAJOR_VERSION 0x821B\n        #define GL_MINOR_VERSION 0x821C\n    #endif\n\n    #ifndef GL_UNSIGNED_INT_2_10_10_10_REV\n    #define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368\n    #endif\n    #ifndef GL_UNSIGNED_INT_24_8\n    #define GL_UNSIGNED_INT_24_8 0x84FA\n    #endif\n    #ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT\n    #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE\n    #endif\n    #ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT\n    #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF\n    #endif\n    #ifndef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT\n    #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1\n    #endif\n    #ifndef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT\n    #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2\n    #endif\n    #ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT\n    #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3\n    #endif\n    #ifndef GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT\n    #define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F\n    #endif\n    #ifndef GL_COMPRESSED_RED_RGTC1\n    #define GL_COMPRESSED_RED_RGTC1 0x8DBB\n    #endif\n    #ifndef GL_COMPRESSED_SIGNED_RED_RGTC1\n    #define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC\n    #endif\n    #ifndef GL_COMPRESSED_RED_GREEN_RGTC2\n    #define GL_COMPRESSED_RED_GREEN_RGTC2 0x8DBD\n    #endif\n    #ifndef GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2\n    #define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2 0x8DBE\n    #endif\n    #ifndef GL_COMPRESSED_RGBA_BPTC_UNORM_ARB\n    #define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C\n    #endif\n    #ifndef GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB\n    #define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D\n    #endif\n    #ifndef GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB\n    #define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E\n    #endif\n    #ifndef GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB\n    #define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F\n    #endif\n    #ifndef GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG\n    #define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01\n    #endif\n    #ifndef GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG\n    #define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00\n    #endif\n    #ifndef GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG\n    #define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03\n    #endif\n    #ifndef GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG\n    #define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02\n    #endif\n    #ifndef GL_COMPRESSED_RGB8_ETC2\n    #define GL_COMPRESSED_RGB8_ETC2 0x9274\n    #endif\n    #ifndef GL_COMPRESSED_SRGB8_ETC2\n    #define GL_COMPRESSED_SRGB8_ETC2 0x9275\n    #endif\n    #ifndef GL_COMPRESSED_RGBA8_ETC2_EAC\n    #define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278\n    #endif\n    #ifndef GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC\n    #define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279\n    #endif\n    #ifndef GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2\n    #define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276\n    #endif\n    #ifndef GL_COMPRESSED_R11_EAC\n    #define GL_COMPRESSED_R11_EAC 0x9270\n    #endif\n    #ifndef GL_COMPRESSED_SIGNED_R11_EAC\n    #define GL_COMPRESSED_SIGNED_R11_EAC 0x9271\n    #endif\n    #ifndef GL_COMPRESSED_RG11_EAC\n    #define GL_COMPRESSED_RG11_EAC 0x9272\n    #endif\n    #ifndef GL_COMPRESSED_SIGNED_RG11_EAC\n    #define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273\n    #endif\n    #ifndef GL_COMPRESSED_RGBA_ASTC_4x4_KHR\n    #define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0\n    #endif\n    #ifndef GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR\n    #define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0\n    #endif\n    #ifndef GL_DEPTH24_STENCIL8\n    #define GL_DEPTH24_STENCIL8 0x88F0\n    #endif\n    #ifndef GL_HALF_FLOAT\n    #define GL_HALF_FLOAT 0x140B\n    #endif\n    #ifndef GL_DEPTH_STENCIL\n    #define GL_DEPTH_STENCIL 0x84F9\n    #endif\n    #ifndef GL_LUMINANCE\n    #define GL_LUMINANCE 0x1909\n    #endif\n    #ifndef _SG_GL_CHECK_ERROR\n\t// __v_ start\n\t#ifdef NDEBUG\n    #define _SG_GL_CHECK_ERROR() (void)(0)\n    #else \n    #define _SG_GL_CHECK_ERROR() { int glerr = glGetError(); if(glerr){ fprintf(stderr, \">> glGetError: %d\\n\", glerr); }; SOKOL_ASSERT(glerr == GL_NO_ERROR); }\n    #endif\n\t// __v_ end\n    #endif\n#endif\n\n#if defined(SOKOL_GLES3)\n    // on WebGL2, GL_FRAMEBUFFER_UNDEFINED technically doesn't exist (it is defined\n    // in the Emscripten headers, but may not exist in other WebGL2 shims)\n    // see: https://github.com/floooh/sokol/pull/933\n    #ifndef GL_FRAMEBUFFER_UNDEFINED\n    #define GL_FRAMEBUFFER_UNDEFINED 0x8219\n    #endif\n#endif\n\n// make some GL constants generally available to simplify compilation,\n// use of those constants will be filtered by runtime flags\n#ifndef GL_SHADER_STORAGE_BUFFER\n#define GL_SHADER_STORAGE_BUFFER 0x90D2\n#endif\n\n// ███████ ████████ ██████  ██    ██  ██████ ████████ ███████\n// ██         ██    ██   ██ ██    ██ ██         ██    ██\n// ███████    ██    ██████  ██    ██ ██         ██    ███████\n//      ██    ██    ██   ██ ██    ██ ██         ██         ██\n// ███████    ██    ██   ██  ██████   ██████    ██    ███████\n//\n// >>structs\n// resource pool slots\ntypedef struct {\n    uint32_t id;\n    sg_resource_state state;\n} _sg_slot_t;\n\n// resource pool housekeeping struct\ntypedef struct {\n    int size;\n    int queue_top;\n    uint32_t* gen_ctrs;\n    int* free_queue;\n} _sg_pool_t;\n\n_SOKOL_PRIVATE void _sg_init_pool(_sg_pool_t* pool, int num);\n_SOKOL_PRIVATE void _sg_discard_pool(_sg_pool_t* pool);\n_SOKOL_PRIVATE int _sg_pool_alloc_index(_sg_pool_t* pool);\n_SOKOL_PRIVATE void _sg_pool_free_index(_sg_pool_t* pool, int slot_index);\n_SOKOL_PRIVATE void _sg_reset_slot(_sg_slot_t* slot);\n_SOKOL_PRIVATE uint32_t _sg_slot_alloc(_sg_pool_t* pool, _sg_slot_t* slot, int slot_index);\n_SOKOL_PRIVATE int _sg_slot_index(uint32_t id);\n\n// constants\nenum {\n    _SG_STRING_SIZE = 32,\n    _SG_SLOT_SHIFT = 16,\n    _SG_SLOT_MASK = (1<<_SG_SLOT_SHIFT)-1,\n    _SG_MAX_POOL_SIZE = (1<<_SG_SLOT_SHIFT),\n    _SG_DEFAULT_BUFFER_POOL_SIZE = 128,\n    _SG_DEFAULT_IMAGE_POOL_SIZE = 128,\n    _SG_DEFAULT_SAMPLER_POOL_SIZE = 64,\n    _SG_DEFAULT_SHADER_POOL_SIZE = 32,\n    _SG_DEFAULT_PIPELINE_POOL_SIZE = 64,\n    _SG_DEFAULT_ATTACHMENTS_POOL_SIZE = 16,\n    _SG_DEFAULT_UB_SIZE = 4 * 1024 * 1024,\n    _SG_DEFAULT_MAX_COMMIT_LISTENERS = 1024,\n    _SG_DEFAULT_WGPU_BINDGROUP_CACHE_SIZE = 1024,\n};\n\n// fixed-size string\ntypedef struct {\n    char buf[_SG_STRING_SIZE];\n} _sg_str_t;\n\n// helper macros\n#define _sg_def(val, def) (((val) == 0) ? (def) : (val))\n#define _sg_def_flt(val, def) (((val) == 0.0f) ? (def) : (val))\n#define _sg_min(a,b) (((a)<(b))?(a):(b))\n#define _sg_max(a,b) (((a)>(b))?(a):(b))\n#define _sg_clamp(v,v0,v1) (((v)<(v0))?(v0):(((v)>(v1))?(v1):(v)))\n#define _sg_fequal(val,cmp,delta) ((((val)-(cmp))> -(delta))&&(((val)-(cmp))<(delta)))\n#define _sg_ispow2(val) ((val&(val-1))==0)\n#define _sg_stats_add(key,val) {if(_sg.stats_enabled){ _sg.stats.key+=val;}}\n\n_SOKOL_PRIVATE void* _sg_malloc_clear(size_t size);\n_SOKOL_PRIVATE void _sg_free(void* ptr);\n_SOKOL_PRIVATE void _sg_clear(void* ptr, size_t size);\n\ntypedef struct {\n    int size;\n    int append_pos;\n    bool append_overflow;\n    uint32_t update_frame_index;\n    uint32_t append_frame_index;\n    int num_slots;\n    int active_slot;\n    sg_buffer_type type;\n    sg_usage usage;\n} _sg_buffer_common_t;\n\n_SOKOL_PRIVATE void _sg_buffer_common_init(_sg_buffer_common_t* cmn, const sg_buffer_desc* desc) {\n    cmn->size = (int)desc->size;\n    cmn->append_pos = 0;\n    cmn->append_overflow = false;\n    cmn->update_frame_index = 0;\n    cmn->append_frame_index = 0;\n    cmn->num_slots = (desc->usage == SG_USAGE_IMMUTABLE) ? 1 : SG_NUM_INFLIGHT_FRAMES;\n    cmn->active_slot = 0;\n    cmn->type = desc->type;\n    cmn->usage = desc->usage;\n}\n\ntypedef struct {\n    uint32_t upd_frame_index;\n    int num_slots;\n    int active_slot;\n    sg_image_type type;\n    bool render_target;\n    int width;\n    int height;\n    int num_slices;\n    int num_mipmaps;\n    sg_usage usage;\n    sg_pixel_format pixel_format;\n    int sample_count;\n} _sg_image_common_t;\n\n_SOKOL_PRIVATE void _sg_image_common_init(_sg_image_common_t* cmn, const sg_image_desc* desc) {\n    cmn->upd_frame_index = 0;\n    cmn->num_slots = (desc->usage == SG_USAGE_IMMUTABLE) ? 1 : SG_NUM_INFLIGHT_FRAMES;\n    cmn->active_slot = 0;\n    cmn->type = desc->type;\n    cmn->render_target = desc->render_target;\n    cmn->width = desc->width;\n    cmn->height = desc->height;\n    cmn->num_slices = desc->num_slices;\n    cmn->num_mipmaps = desc->num_mipmaps;\n    cmn->usage = desc->usage;\n    cmn->pixel_format = desc->pixel_format;\n    cmn->sample_count = desc->sample_count;\n}\n\ntypedef struct {\n    sg_filter min_filter;\n    sg_filter mag_filter;\n    sg_filter mipmap_filter;\n    sg_wrap wrap_u;\n    sg_wrap wrap_v;\n    sg_wrap wrap_w;\n    float min_lod;\n    float max_lod;\n    sg_border_color border_color;\n    sg_compare_func compare;\n    uint32_t max_anisotropy;\n} _sg_sampler_common_t;\n\n_SOKOL_PRIVATE void _sg_sampler_common_init(_sg_sampler_common_t* cmn, const sg_sampler_desc* desc) {\n    cmn->min_filter = desc->min_filter;\n    cmn->mag_filter = desc->mag_filter;\n    cmn->mipmap_filter = desc->mipmap_filter;\n    cmn->wrap_u = desc->wrap_u;\n    cmn->wrap_v = desc->wrap_v;\n    cmn->wrap_w = desc->wrap_w;\n    cmn->min_lod = desc->min_lod;\n    cmn->max_lod = desc->max_lod;\n    cmn->border_color = desc->border_color;\n    cmn->compare = desc->compare;\n    cmn->max_anisotropy = desc->max_anisotropy;\n}\n\ntypedef struct {\n    size_t size;\n} _sg_shader_uniform_block_t;\n\ntypedef struct {\n    bool used;\n    bool readonly;\n} _sg_shader_storage_buffer_t;\n\ntypedef struct {\n    sg_image_type image_type;\n    sg_image_sample_type sample_type;\n    bool multisampled;\n} _sg_shader_image_t;\n\ntypedef struct {\n    sg_sampler_type sampler_type;\n} _sg_shader_sampler_t;\n\n// combined image sampler mappings, only needed on GL\ntypedef struct {\n    int image_slot;\n    int sampler_slot;\n} _sg_shader_image_sampler_t;\n\ntypedef struct {\n    int num_uniform_blocks;\n    int num_storage_buffers;\n    int num_images;\n    int num_samplers;\n    int num_image_samplers;\n    _sg_shader_uniform_block_t uniform_blocks[SG_MAX_SHADERSTAGE_UBS];\n    _sg_shader_storage_buffer_t storage_buffers[SG_MAX_SHADERSTAGE_STORAGEBUFFERS];\n    _sg_shader_image_t images[SG_MAX_SHADERSTAGE_IMAGES];\n    _sg_shader_sampler_t samplers[SG_MAX_SHADERSTAGE_SAMPLERS];\n    _sg_shader_image_sampler_t image_samplers[SG_MAX_SHADERSTAGE_IMAGESAMPLERPAIRS];\n} _sg_shader_stage_t;\n\ntypedef struct {\n    _sg_shader_stage_t stage[SG_NUM_SHADER_STAGES];\n} _sg_shader_common_t;\n\n_SOKOL_PRIVATE void _sg_shader_common_init(_sg_shader_common_t* cmn, const sg_shader_desc* desc) {\n    for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {\n        const sg_shader_stage_desc* stage_desc = (stage_index == SG_SHADERSTAGE_VS) ? &desc->vs : &desc->fs;\n        _sg_shader_stage_t* stage = &cmn->stage[stage_index];\n        SOKOL_ASSERT(stage->num_uniform_blocks == 0);\n        for (int ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) {\n            const sg_shader_uniform_block_desc* ub_desc = &stage_desc->uniform_blocks[ub_index];\n            if (0 == ub_desc->size) {\n                break;\n            }\n            stage->uniform_blocks[ub_index].size = ub_desc->size;\n            stage->num_uniform_blocks++;\n        }\n        SOKOL_ASSERT(stage->num_images == 0);\n        for (int img_index = 0; img_index < SG_MAX_SHADERSTAGE_IMAGES; img_index++) {\n            const sg_shader_image_desc* img_desc = &stage_desc->images[img_index];\n            if (!img_desc->used) {\n                break;\n            }\n            stage->images[img_index].multisampled = img_desc->multisampled;\n            stage->images[img_index].image_type = img_desc->image_type;\n            stage->images[img_index].sample_type = img_desc->sample_type;\n            stage->num_images++;\n        }\n        SOKOL_ASSERT(stage->num_samplers == 0);\n        for (int smp_index = 0; smp_index < SG_MAX_SHADERSTAGE_SAMPLERS; smp_index++) {\n            const sg_shader_sampler_desc* smp_desc = &stage_desc->samplers[smp_index];\n            if (!smp_desc->used) {\n                break;\n            }\n            stage->samplers[smp_index].sampler_type = smp_desc->sampler_type;\n            stage->num_samplers++;\n        }\n        SOKOL_ASSERT(stage->num_image_samplers == 0);\n        for (int img_smp_index = 0; img_smp_index < SG_MAX_SHADERSTAGE_IMAGESAMPLERPAIRS; img_smp_index++) {\n            const sg_shader_image_sampler_pair_desc* img_smp_desc = &stage_desc->image_sampler_pairs[img_smp_index];\n            if (!img_smp_desc->used) {\n                break;\n            }\n            SOKOL_ASSERT((img_smp_desc->image_slot >= 0) && (img_smp_desc->image_slot < stage->num_images));\n            stage->image_samplers[img_smp_index].image_slot = img_smp_desc->image_slot;\n            SOKOL_ASSERT((img_smp_desc->sampler_slot >= 0) && (img_smp_desc->sampler_slot < stage->num_samplers));\n            stage->image_samplers[img_smp_index].sampler_slot = img_smp_desc->sampler_slot;\n            stage->num_image_samplers++;\n        }\n        SOKOL_ASSERT(stage->num_storage_buffers == 0);\n        for (int sbuf_index = 0; sbuf_index < SG_MAX_SHADERSTAGE_STORAGEBUFFERS; sbuf_index++) {\n            const sg_shader_storage_buffer_desc* sbuf_desc = &stage_desc->storage_buffers[sbuf_index];\n            if (!sbuf_desc->used) {\n                break;\n            }\n            stage->storage_buffers[sbuf_index].used = sbuf_desc->used;\n            stage->storage_buffers[sbuf_index].readonly = sbuf_desc->readonly;\n            stage->num_storage_buffers++;\n        }\n    }\n}\n\ntypedef struct {\n    bool vertex_buffer_layout_active[SG_MAX_VERTEX_BUFFERS];\n    bool use_instanced_draw;\n    sg_shader shader_id;\n    sg_vertex_layout_state layout;\n    sg_depth_state depth;\n    sg_stencil_state stencil;\n    int color_count;\n    sg_color_target_state colors[SG_MAX_COLOR_ATTACHMENTS];\n    sg_primitive_type primitive_type;\n    sg_index_type index_type;\n    sg_cull_mode cull_mode;\n    sg_face_winding face_winding;\n    int sample_count;\n    sg_color blend_color;\n    bool alpha_to_coverage_enabled;\n} _sg_pipeline_common_t;\n\n_SOKOL_PRIVATE void _sg_pipeline_common_init(_sg_pipeline_common_t* cmn, const sg_pipeline_desc* desc) {\n    SOKOL_ASSERT((desc->color_count >= 0) && (desc->color_count <= SG_MAX_COLOR_ATTACHMENTS));\n    for (int i = 0; i < SG_MAX_VERTEX_BUFFERS; i++) {\n        cmn->vertex_buffer_layout_active[i] = false;\n    }\n    cmn->use_instanced_draw = false;\n    cmn->shader_id = desc->shader;\n    cmn->layout = desc->layout;\n    cmn->depth = desc->depth;\n    cmn->stencil = desc->stencil;\n    cmn->color_count = desc->color_count;\n    for (int i = 0; i < desc->color_count; i++) {\n        cmn->colors[i] = desc->colors[i];\n    }\n    cmn->primitive_type = desc->primitive_type;\n    cmn->index_type = desc->index_type;\n    cmn->cull_mode = desc->cull_mode;\n    cmn->face_winding = desc->face_winding;\n    cmn->sample_count = desc->sample_count;\n    cmn->blend_color = desc->blend_color;\n    cmn->alpha_to_coverage_enabled = desc->alpha_to_coverage_enabled;\n}\n\ntypedef struct {\n    sg_image image_id;\n    int mip_level;\n    int slice;\n} _sg_attachment_common_t;\n\ntypedef struct {\n    int width;\n    int height;\n    int num_colors;\n    _sg_attachment_common_t colors[SG_MAX_COLOR_ATTACHMENTS];\n    _sg_attachment_common_t resolves[SG_MAX_COLOR_ATTACHMENTS];\n    _sg_attachment_common_t depth_stencil;\n} _sg_attachments_common_t;\n\n_SOKOL_PRIVATE void _sg_attachment_common_init(_sg_attachment_common_t* cmn, const sg_attachment_desc* desc) {\n    cmn->image_id = desc->image;\n    cmn->mip_level = desc->mip_level;\n    cmn->slice = desc->slice;\n}\n\n_SOKOL_PRIVATE void _sg_attachments_common_init(_sg_attachments_common_t* cmn, const sg_attachments_desc* desc, int width, int height) {\n    SOKOL_ASSERT((width > 0) && (height > 0));\n    cmn->width = width;\n    cmn->height = height;\n    for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {\n        if (desc->colors[i].image.id != SG_INVALID_ID) {\n            cmn->num_colors++;\n            _sg_attachment_common_init(&cmn->colors[i], &desc->colors[i]);\n            _sg_attachment_common_init(&cmn->resolves[i], &desc->resolves[i]);\n        }\n    }\n    if (desc->depth_stencil.image.id != SG_INVALID_ID) {\n        _sg_attachment_common_init(&cmn->depth_stencil, &desc->depth_stencil);\n    }\n}\n\n#if defined(SOKOL_DUMMY_BACKEND)\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_buffer_common_t cmn;\n} _sg_dummy_buffer_t;\ntypedef _sg_dummy_buffer_t _sg_buffer_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_image_common_t cmn;\n} _sg_dummy_image_t;\ntypedef _sg_dummy_image_t _sg_image_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_sampler_common_t cmn;\n} _sg_dummy_sampler_t;\ntypedef _sg_dummy_sampler_t _sg_sampler_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_shader_common_t cmn;\n} _sg_dummy_shader_t;\ntypedef _sg_dummy_shader_t _sg_shader_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_shader_t* shader;\n    _sg_pipeline_common_t cmn;\n} _sg_dummy_pipeline_t;\ntypedef _sg_dummy_pipeline_t _sg_pipeline_t;\n\ntypedef struct {\n    _sg_image_t* image;\n} _sg_dummy_attachment_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_attachments_common_t cmn;\n    struct {\n        _sg_dummy_attachment_t colors[SG_MAX_COLOR_ATTACHMENTS];\n        _sg_dummy_attachment_t resolves[SG_MAX_COLOR_ATTACHMENTS];\n        _sg_dummy_attachment_t depth_stencil;\n    } dmy;\n} _sg_dummy_attachments_t;\ntypedef _sg_dummy_attachments_t _sg_attachments_t;\n\n#elif defined(_SOKOL_ANY_GL)\n\n#define _SG_GL_TEXTURE_SAMPLER_CACHE_SIZE (SG_MAX_SHADERSTAGE_IMAGESAMPLERPAIRS * SG_NUM_SHADER_STAGES)\n#define _SG_GL_STORAGEBUFFER_STAGE_INDEX_PITCH (SG_MAX_SHADERSTAGE_STORAGEBUFFERS)\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_buffer_common_t cmn;\n    struct {\n        GLuint buf[SG_NUM_INFLIGHT_FRAMES];\n        bool injected;  // if true, external buffers were injected with sg_buffer_desc.gl_buffers\n    } gl;\n} _sg_gl_buffer_t;\ntypedef _sg_gl_buffer_t _sg_buffer_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_image_common_t cmn;\n    struct {\n        GLenum target;\n        GLuint msaa_render_buffer;\n        GLuint tex[SG_NUM_INFLIGHT_FRAMES];\n        bool injected;  // if true, external textures were injected with sg_image_desc.gl_textures\n    } gl;\n} _sg_gl_image_t;\ntypedef _sg_gl_image_t _sg_image_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_sampler_common_t cmn;\n    struct {\n        GLuint smp;\n        bool injected;  // true if external sampler was injects in sg_sampler_desc.gl_sampler\n    } gl;\n} _sg_gl_sampler_t;\ntypedef _sg_gl_sampler_t _sg_sampler_t;\n\ntypedef struct {\n    GLint gl_loc;\n    sg_uniform_type type;\n    uint16_t count;\n    uint16_t offset;\n} _sg_gl_uniform_t;\n\ntypedef struct {\n    int num_uniforms;\n    _sg_gl_uniform_t uniforms[SG_MAX_UB_MEMBERS];\n} _sg_gl_uniform_block_t;\n\ntypedef struct {\n    int gl_tex_slot;\n} _sg_gl_shader_image_sampler_t;\n\ntypedef struct {\n    _sg_str_t name;\n} _sg_gl_shader_attr_t;\n\ntypedef struct {\n    _sg_gl_uniform_block_t uniform_blocks[SG_MAX_SHADERSTAGE_UBS];\n    _sg_gl_shader_image_sampler_t image_samplers[SG_MAX_SHADERSTAGE_IMAGESAMPLERPAIRS];\n} _sg_gl_shader_stage_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_shader_common_t cmn;\n    struct {\n        GLuint prog;\n        _sg_gl_shader_attr_t attrs[SG_MAX_VERTEX_ATTRIBUTES];\n        _sg_gl_shader_stage_t stage[SG_NUM_SHADER_STAGES];\n    } gl;\n} _sg_gl_shader_t;\ntypedef _sg_gl_shader_t _sg_shader_t;\n\ntypedef struct {\n    int8_t vb_index;        // -1 if attr is not enabled\n    int8_t divisor;         // -1 if not initialized\n    uint8_t stride;\n    uint8_t size;\n    uint8_t normalized;\n    int offset;\n    GLenum type;\n} _sg_gl_attr_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_pipeline_common_t cmn;\n    _sg_shader_t* shader;\n    struct {\n        _sg_gl_attr_t attrs[SG_MAX_VERTEX_ATTRIBUTES];\n        sg_depth_state depth;\n        sg_stencil_state stencil;\n        sg_primitive_type primitive_type;\n        sg_blend_state blend;\n        sg_color_mask color_write_mask[SG_MAX_COLOR_ATTACHMENTS];\n        sg_cull_mode cull_mode;\n        sg_face_winding face_winding;\n        int sample_count;\n        bool alpha_to_coverage_enabled;\n    } gl;\n} _sg_gl_pipeline_t;\ntypedef _sg_gl_pipeline_t _sg_pipeline_t;\n\ntypedef struct {\n    _sg_image_t* image;\n} _sg_gl_attachment_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_attachments_common_t cmn;\n    struct {\n        GLuint fb;\n        _sg_gl_attachment_t colors[SG_MAX_COLOR_ATTACHMENTS];\n        _sg_gl_attachment_t resolves[SG_MAX_COLOR_ATTACHMENTS];\n        _sg_gl_attachment_t depth_stencil;\n        GLuint msaa_resolve_framebuffer[SG_MAX_COLOR_ATTACHMENTS];\n    } gl;\n} _sg_gl_attachments_t;\ntypedef _sg_gl_attachments_t _sg_attachments_t;\n\ntypedef struct {\n    _sg_gl_attr_t gl_attr;\n    GLuint gl_vbuf;\n} _sg_gl_cache_attr_t;\n\ntypedef struct {\n    GLenum target;\n    GLuint texture;\n    GLuint sampler;\n} _sg_gl_cache_texture_sampler_bind_slot;\n\ntypedef struct {\n    sg_depth_state depth;\n    sg_stencil_state stencil;\n    sg_blend_state blend;\n    sg_color_mask color_write_mask[SG_MAX_COLOR_ATTACHMENTS];\n    sg_cull_mode cull_mode;\n    sg_face_winding face_winding;\n    bool polygon_offset_enabled;\n    int sample_count;\n    sg_color blend_color;\n    bool alpha_to_coverage_enabled;\n    _sg_gl_cache_attr_t attrs[SG_MAX_VERTEX_ATTRIBUTES];\n    GLuint vertex_buffer;\n    GLuint index_buffer;\n    GLuint storage_buffer;  // general bind point\n    GLuint stage_storage_buffers[SG_NUM_SHADER_STAGES][SG_MAX_SHADERSTAGE_STORAGEBUFFERS];\n    GLuint stored_vertex_buffer;\n    GLuint stored_index_buffer;\n    GLuint stored_storage_buffer;\n    GLuint prog;\n    _sg_gl_cache_texture_sampler_bind_slot texture_samplers[_SG_GL_TEXTURE_SAMPLER_CACHE_SIZE];\n    _sg_gl_cache_texture_sampler_bind_slot stored_texture_sampler;\n    int cur_ib_offset;\n    GLenum cur_primitive_type;\n    GLenum cur_index_type;\n    GLenum cur_active_texture;\n    _sg_pipeline_t* cur_pipeline;\n    sg_pipeline cur_pipeline_id;\n} _sg_gl_state_cache_t;\n\ntypedef struct {\n    bool valid;\n    GLuint vao;\n    _sg_gl_state_cache_t cache;\n    bool ext_anisotropic;\n    GLint max_anisotropy;\n    sg_store_action color_store_actions[SG_MAX_COLOR_ATTACHMENTS];\n    sg_store_action depth_store_action;\n    sg_store_action stencil_store_action;\n    #if _SOKOL_USE_WIN32_GL_LOADER\n    HINSTANCE opengl32_dll;\n    #endif\n} _sg_gl_backend_t;\n\n#elif defined(SOKOL_D3D11)\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_buffer_common_t cmn;\n    struct {\n        ID3D11Buffer* buf;\n        ID3D11ShaderResourceView* srv;\n    } d3d11;\n} _sg_d3d11_buffer_t;\ntypedef _sg_d3d11_buffer_t _sg_buffer_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_image_common_t cmn;\n    struct {\n        DXGI_FORMAT format;\n        ID3D11Texture2D* tex2d;\n        ID3D11Texture3D* tex3d;\n        ID3D11Resource* res;    // either tex2d or tex3d\n        ID3D11ShaderResourceView* srv;\n    } d3d11;\n} _sg_d3d11_image_t;\ntypedef _sg_d3d11_image_t _sg_image_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_sampler_common_t cmn;\n    struct {\n        ID3D11SamplerState* smp;\n    } d3d11;\n} _sg_d3d11_sampler_t;\ntypedef _sg_d3d11_sampler_t _sg_sampler_t;\n\ntypedef struct {\n    _sg_str_t sem_name;\n    int sem_index;\n} _sg_d3d11_shader_attr_t;\n\ntypedef struct {\n    ID3D11Buffer* cbufs[SG_MAX_SHADERSTAGE_UBS];\n} _sg_d3d11_shader_stage_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_shader_common_t cmn;\n    struct {\n        _sg_d3d11_shader_attr_t attrs[SG_MAX_VERTEX_ATTRIBUTES];\n        _sg_d3d11_shader_stage_t stage[SG_NUM_SHADER_STAGES];\n        ID3D11VertexShader* vs;\n        ID3D11PixelShader* fs;\n        void* vs_blob;\n        size_t vs_blob_length;\n    } d3d11;\n} _sg_d3d11_shader_t;\ntypedef _sg_d3d11_shader_t _sg_shader_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_pipeline_common_t cmn;\n    _sg_shader_t* shader;\n    struct {\n        UINT stencil_ref;\n        UINT vb_strides[SG_MAX_VERTEX_BUFFERS];\n        D3D_PRIMITIVE_TOPOLOGY topology;\n        DXGI_FORMAT index_format;\n        ID3D11InputLayout* il;\n        ID3D11RasterizerState* rs;\n        ID3D11DepthStencilState* dss;\n        ID3D11BlendState* bs;\n    } d3d11;\n} _sg_d3d11_pipeline_t;\ntypedef _sg_d3d11_pipeline_t _sg_pipeline_t;\n\ntypedef struct {\n    _sg_image_t* image;\n    union {\n        ID3D11RenderTargetView* rtv;\n        ID3D11DepthStencilView* dsv;\n    } view;\n} _sg_d3d11_attachment_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_attachments_common_t cmn;\n    struct {\n        _sg_d3d11_attachment_t colors[SG_MAX_COLOR_ATTACHMENTS];\n        _sg_d3d11_attachment_t resolves[SG_MAX_COLOR_ATTACHMENTS];\n        _sg_d3d11_attachment_t depth_stencil;\n    } d3d11;\n} _sg_d3d11_attachments_t;\ntypedef _sg_d3d11_attachments_t _sg_attachments_t;\n\ntypedef struct {\n    bool valid;\n    ID3D11Device* dev;\n    ID3D11DeviceContext* ctx;\n    bool use_indexed_draw;\n    bool use_instanced_draw;\n    _sg_pipeline_t* cur_pipeline;\n    sg_pipeline cur_pipeline_id;\n    struct {\n        ID3D11RenderTargetView* render_view;\n        ID3D11RenderTargetView* resolve_view;\n    } cur_pass;\n    // on-demand loaded d3dcompiler_47.dll handles\n    HINSTANCE d3dcompiler_dll;\n    bool d3dcompiler_dll_load_failed;\n    pD3DCompile D3DCompile_func;\n    // global subresourcedata array for texture updates\n    D3D11_SUBRESOURCE_DATA subres_data[SG_MAX_MIPMAPS * SG_MAX_TEXTUREARRAY_LAYERS];\n} _sg_d3d11_backend_t;\n\n#elif defined(SOKOL_METAL)\n\n#if defined(_SG_TARGET_MACOS) || defined(_SG_TARGET_IOS_SIMULATOR)\n#define _SG_MTL_UB_ALIGN (256)\n#else\n#define _SG_MTL_UB_ALIGN (16)\n#endif\n#define _SG_MTL_INVALID_SLOT_INDEX (0)\n\ntypedef struct {\n    uint32_t frame_index;   // frame index at which it is safe to release this resource\n    int slot_index;\n} _sg_mtl_release_item_t;\n\ntypedef struct {\n    NSMutableArray* pool;\n    int num_slots;\n    int free_queue_top;\n    int* free_queue;\n    int release_queue_front;\n    int release_queue_back;\n    _sg_mtl_release_item_t* release_queue;\n} _sg_mtl_idpool_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_buffer_common_t cmn;\n    struct {\n        int buf[SG_NUM_INFLIGHT_FRAMES];  // index into _sg_mtl_pool\n    } mtl;\n} _sg_mtl_buffer_t;\ntypedef _sg_mtl_buffer_t _sg_buffer_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_image_common_t cmn;\n    struct {\n        int tex[SG_NUM_INFLIGHT_FRAMES];\n    } mtl;\n} _sg_mtl_image_t;\ntypedef _sg_mtl_image_t _sg_image_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_sampler_common_t cmn;\n    struct {\n        int sampler_state;\n    } mtl;\n} _sg_mtl_sampler_t;\ntypedef _sg_mtl_sampler_t _sg_sampler_t;\n\ntypedef struct {\n    int mtl_lib;\n    int mtl_func;\n} _sg_mtl_shader_stage_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_shader_common_t cmn;\n    struct {\n        _sg_mtl_shader_stage_t stage[SG_NUM_SHADER_STAGES];\n    } mtl;\n} _sg_mtl_shader_t;\ntypedef _sg_mtl_shader_t _sg_shader_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_pipeline_common_t cmn;\n    _sg_shader_t* shader;\n    struct {\n        MTLPrimitiveType prim_type;\n        int index_size;\n        MTLIndexType index_type;\n        MTLCullMode cull_mode;\n        MTLWinding winding;\n        uint32_t stencil_ref;\n        int rps;\n        int dss;\n    } mtl;\n} _sg_mtl_pipeline_t;\ntypedef _sg_mtl_pipeline_t _sg_pipeline_t;\n\ntypedef struct {\n    _sg_image_t* image;\n} _sg_mtl_attachment_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_attachments_common_t cmn;\n    struct {\n        _sg_mtl_attachment_t colors[SG_MAX_COLOR_ATTACHMENTS];\n        _sg_mtl_attachment_t resolves[SG_MAX_COLOR_ATTACHMENTS];\n        _sg_mtl_attachment_t depth_stencil;\n    } mtl;\n} _sg_mtl_attachments_t;\ntypedef _sg_mtl_attachments_t _sg_attachments_t;\n\n// resource binding state cache\ntypedef struct {\n    const _sg_pipeline_t* cur_pipeline;\n    sg_pipeline cur_pipeline_id;\n    const _sg_buffer_t* cur_indexbuffer;\n    sg_buffer cur_indexbuffer_id;\n    int cur_indexbuffer_offset;\n    int cur_vertexbuffer_offsets[SG_MAX_VERTEX_BUFFERS];\n    sg_buffer cur_vertexbuffer_ids[SG_MAX_VERTEX_BUFFERS];\n    sg_image cur_vs_image_ids[SG_MAX_SHADERSTAGE_IMAGES];\n    sg_image cur_fs_image_ids[SG_MAX_SHADERSTAGE_IMAGES];\n    sg_sampler cur_vs_sampler_ids[SG_MAX_SHADERSTAGE_SAMPLERS];\n    sg_sampler cur_fs_sampler_ids[SG_MAX_SHADERSTAGE_SAMPLERS];\n    sg_buffer cur_vs_storagebuffer_ids[SG_MAX_SHADERSTAGE_STORAGEBUFFERS];\n    sg_buffer cur_fs_storagebuffer_ids[SG_MAX_SHADERSTAGE_STORAGEBUFFERS];\n} _sg_mtl_state_cache_t;\n\ntypedef struct {\n    bool valid;\n    bool use_shared_storage_mode;\n    uint32_t cur_frame_rotate_index;\n    int ub_size;\n    int cur_ub_offset;\n    uint8_t* cur_ub_base_ptr;\n    _sg_mtl_state_cache_t state_cache;\n    _sg_mtl_idpool_t idpool;\n    dispatch_semaphore_t sem;\n    id<MTLDevice> device;\n    id<MTLCommandQueue> cmd_queue;\n    id<MTLCommandBuffer> cmd_buffer;\n    id<MTLRenderCommandEncoder> cmd_encoder;\n    id<CAMetalDrawable> cur_drawable;\n    id<MTLBuffer> uniform_buffers[SG_NUM_INFLIGHT_FRAMES];\n} _sg_mtl_backend_t;\n\n#elif defined(SOKOL_WGPU)\n\n#define _SG_WGPU_ROWPITCH_ALIGN (256)\n#define _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE (1<<16) // also see WGPULimits.maxUniformBufferBindingSize\n#define _SG_WGPU_NUM_BINDGROUPS (2) // 0: uniforms, 1: images and sampler on both shader stages\n#define _SG_WGPU_UNIFORM_BINDGROUP_INDEX (0)\n#define _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX (1)\n#define _SG_WGPU_MAX_BINDGROUP_ENTRIES (SG_NUM_SHADER_STAGES * (SG_MAX_SHADERSTAGE_IMAGES + SG_MAX_SHADERSTAGE_SAMPLERS + SG_MAX_SHADERSTAGE_STORAGEBUFFERS))\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_buffer_common_t cmn;\n    struct {\n        WGPUBuffer buf;\n    } wgpu;\n} _sg_wgpu_buffer_t;\ntypedef _sg_wgpu_buffer_t _sg_buffer_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_image_common_t cmn;\n    struct {\n        WGPUTexture tex;\n        WGPUTextureView view;\n    } wgpu;\n} _sg_wgpu_image_t;\ntypedef _sg_wgpu_image_t _sg_image_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_sampler_common_t cmn;\n    struct {\n        WGPUSampler smp;\n    } wgpu;\n} _sg_wgpu_sampler_t;\ntypedef _sg_wgpu_sampler_t _sg_sampler_t;\n\ntypedef struct {\n    WGPUShaderModule module;\n    _sg_str_t entry;\n} _sg_wgpu_shader_stage_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_shader_common_t cmn;\n    struct {\n        _sg_wgpu_shader_stage_t stage[SG_NUM_SHADER_STAGES];\n        WGPUBindGroupLayout bind_group_layout;\n    } wgpu;\n} _sg_wgpu_shader_t;\ntypedef _sg_wgpu_shader_t _sg_shader_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_pipeline_common_t cmn;\n    _sg_shader_t* shader;\n    struct {\n        WGPURenderPipeline pip;\n        WGPUColor blend_color;\n    } wgpu;\n} _sg_wgpu_pipeline_t;\ntypedef _sg_wgpu_pipeline_t _sg_pipeline_t;\n\ntypedef struct {\n    _sg_image_t* image;\n    WGPUTextureView view;\n} _sg_wgpu_attachment_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    _sg_attachments_common_t cmn;\n    struct {\n        _sg_wgpu_attachment_t colors[SG_MAX_COLOR_ATTACHMENTS];\n        _sg_wgpu_attachment_t resolves[SG_MAX_COLOR_ATTACHMENTS];\n        _sg_wgpu_attachment_t depth_stencil;\n    } wgpu;\n} _sg_wgpu_attachments_t;\ntypedef _sg_wgpu_attachments_t _sg_attachments_t;\n\n// a pool of per-frame uniform buffers\ntypedef struct {\n    uint32_t num_bytes;\n    uint32_t offset;    // current offset into buf\n    uint8_t* staging;   // intermediate buffer for uniform data updates\n    WGPUBuffer buf;     // the GPU-side uniform buffer\n    struct {\n        WGPUBindGroupLayout group_layout;\n        WGPUBindGroup group;\n        uint32_t offsets[SG_NUM_SHADER_STAGES][SG_MAX_SHADERSTAGE_UBS];\n    } bind;\n} _sg_wgpu_uniform_buffer_t;\n\ntypedef struct {\n    uint32_t id;\n} _sg_wgpu_bindgroup_handle_t;\n\n#define _SG_WGPU_BINDGROUPSCACHE_NUM_ITEMS (1 + _SG_WGPU_MAX_BINDGROUP_ENTRIES)\ntypedef struct {\n    uint64_t hash;\n    uint32_t items[_SG_WGPU_BINDGROUPSCACHE_NUM_ITEMS];\n} _sg_wgpu_bindgroups_cache_key_t;\n\ntypedef struct {\n    uint32_t num;           // must be 2^n\n    uint32_t index_mask;    // mask to turn hash into valid index\n    _sg_wgpu_bindgroup_handle_t* items;\n} _sg_wgpu_bindgroups_cache_t;\n\ntypedef struct {\n    _sg_slot_t slot;\n    WGPUBindGroup bindgroup;\n    _sg_wgpu_bindgroups_cache_key_t key;\n} _sg_wgpu_bindgroup_t;\n\ntypedef struct {\n    _sg_pool_t pool;\n    _sg_wgpu_bindgroup_t* bindgroups;\n} _sg_wgpu_bindgroups_pool_t;\n\ntypedef struct {\n    struct {\n        sg_buffer buffer;\n        int offset;\n    } vbs[SG_MAX_VERTEX_BUFFERS];\n    struct {\n        sg_buffer buffer;\n        int offset;\n    } ib;\n    _sg_wgpu_bindgroup_handle_t bg;\n} _sg_wgpu_bindings_cache_t;\n\n// the WGPU backend state\ntypedef struct {\n    bool valid;\n    bool use_indexed_draw;\n    WGPUDevice dev;\n    WGPUSupportedLimits limits;\n    WGPUQueue queue;\n    WGPUCommandEncoder cmd_enc;\n    WGPURenderPassEncoder pass_enc;\n    WGPUBindGroup empty_bind_group;\n    const _sg_pipeline_t* cur_pipeline;\n    sg_pipeline cur_pipeline_id;\n    _sg_wgpu_uniform_buffer_t uniform;\n    _sg_wgpu_bindings_cache_t bindings_cache;\n    _sg_wgpu_bindgroups_cache_t bindgroups_cache;\n    _sg_wgpu_bindgroups_pool_t bindgroups_pool;\n} _sg_wgpu_backend_t;\n#endif\n\n// POOL STRUCTS\n\n// this *MUST* remain 0\n#define _SG_INVALID_SLOT_INDEX (0)\n\ntypedef struct {\n    _sg_pool_t buffer_pool;\n    _sg_pool_t image_pool;\n    _sg_pool_t sampler_pool;\n    _sg_pool_t shader_pool;\n    _sg_pool_t pipeline_pool;\n    _sg_pool_t attachments_pool;\n    _sg_buffer_t* buffers;\n    _sg_image_t* images;\n    _sg_sampler_t* samplers;\n    _sg_shader_t* shaders;\n    _sg_pipeline_t* pipelines;\n    _sg_attachments_t* attachments;\n} _sg_pools_t;\n\ntypedef struct {\n    int num;        // number of allocated commit listener items\n    int upper;      // the current upper index (no valid items past this point)\n    sg_commit_listener* items;\n} _sg_commit_listeners_t;\n\n// resolved resource bindings struct\ntypedef struct {\n    _sg_pipeline_t* pip;\n    int num_vbs;\n    int num_vs_imgs;\n    int num_vs_smps;\n    int num_vs_sbufs;\n    int num_fs_imgs;\n    int num_fs_smps;\n    int num_fs_sbufs;\n    int vb_offsets[SG_MAX_VERTEX_BUFFERS];\n    int ib_offset;\n    _sg_buffer_t* vbs[SG_MAX_VERTEX_BUFFERS];\n    _sg_buffer_t* ib;\n    _sg_image_t* vs_imgs[SG_MAX_SHADERSTAGE_IMAGES];\n    _sg_sampler_t* vs_smps[SG_MAX_SHADERSTAGE_SAMPLERS];\n    _sg_buffer_t* vs_sbufs[SG_MAX_SHADERSTAGE_STORAGEBUFFERS];\n    _sg_image_t* fs_imgs[SG_MAX_SHADERSTAGE_IMAGES];\n    _sg_sampler_t* fs_smps[SG_MAX_SHADERSTAGE_SAMPLERS];\n    _sg_buffer_t* fs_sbufs[SG_MAX_SHADERSTAGE_STORAGEBUFFERS];\n} _sg_bindings_t;\n\ntypedef struct {\n    bool sample;\n    bool filter;\n    bool render;\n    bool blend;\n    bool msaa;\n    bool depth;\n} _sg_pixelformat_info_t;\n\ntypedef struct {\n    bool valid;\n    sg_desc desc;       // original desc with default values patched in\n    uint32_t frame_index;\n    struct {\n        bool valid;\n        bool in_pass;\n        sg_attachments atts_id;     // SG_INVALID_ID in a swapchain pass\n        _sg_attachments_t* atts;    // 0 in a swapchain pass\n        int width;\n        int height;\n        struct {\n            sg_pixel_format color_fmt;\n            sg_pixel_format depth_fmt;\n            int sample_count;\n        } swapchain;\n    } cur_pass;\n    sg_pipeline cur_pipeline;\n    bool next_draw_valid;\n    #if defined(SOKOL_DEBUG)\n    sg_log_item validate_error;\n    #endif\n    _sg_pools_t pools;\n    sg_backend backend;\n    sg_features features;\n    sg_limits limits;\n    _sg_pixelformat_info_t formats[_SG_PIXELFORMAT_NUM];\n    bool stats_enabled;\n    sg_frame_stats stats;\n    sg_frame_stats prev_stats;\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_backend_t gl;\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_backend_t mtl;\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_backend_t d3d11;\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_backend_t wgpu;\n    #endif\n    #if defined(SOKOL_TRACE_HOOKS)\n    sg_trace_hooks hooks;\n    #endif\n    _sg_commit_listeners_t commit_listeners;\n} _sg_state_t;\nstatic _sg_state_t _sg;\n\n// ██       ██████   ██████   ██████  ██ ███    ██  ██████\n// ██      ██    ██ ██       ██       ██ ████   ██ ██\n// ██      ██    ██ ██   ███ ██   ███ ██ ██ ██  ██ ██   ███\n// ██      ██    ██ ██    ██ ██    ██ ██ ██  ██ ██ ██    ██\n// ███████  ██████   ██████   ██████  ██ ██   ████  ██████\n//\n// >>logging\n#if defined(SOKOL_DEBUG)\n#define _SG_LOGITEM_XMACRO(item,msg) #item \": \" msg,\nstatic const char* _sg_log_messages[] = {\n    _SG_LOG_ITEMS\n};\n#undef _SG_LOGITEM_XMACRO\n#endif // SOKOL_DEBUG\n\n#define _SG_PANIC(code) _sg_log(SG_LOGITEM_ ##code, 0, 0, __LINE__)\n#define _SG_ERROR(code) _sg_log(SG_LOGITEM_ ##code, 1, 0, __LINE__)\n#define _SG_WARN(code) _sg_log(SG_LOGITEM_ ##code, 2, 0, __LINE__)\n#define _SG_INFO(code) _sg_log(SG_LOGITEM_ ##code, 3, 0, __LINE__)\n#define _SG_LOGMSG(code,msg) _sg_log(SG_LOGITEM_ ##code, 3, msg, __LINE__)\n#define _SG_VALIDATE(cond,code) if (!(cond)){ _sg.validate_error = SG_LOGITEM_ ##code; _sg_log(SG_LOGITEM_ ##code, 1, 0, __LINE__); }\n\nstatic void _sg_log(sg_log_item log_item, uint32_t log_level, const char* msg, uint32_t line_nr) {\n    if (_sg.desc.logger.func) {\n        const char* filename = 0;\n        #if defined(SOKOL_DEBUG)\n            filename = __FILE__;\n            if (0 == msg) {\n                msg = _sg_log_messages[log_item];\n            }\n        #endif\n        _sg.desc.logger.func(\"sg\", log_level, log_item, msg, line_nr, filename, _sg.desc.logger.user_data);\n    } else {\n        // for log level PANIC it would be 'undefined behaviour' to continue\n        if (log_level == 0) {\n            abort();\n        }\n    }\n}\n\n// ███    ███ ███████ ███    ███  ██████  ██████  ██    ██\n// ████  ████ ██      ████  ████ ██    ██ ██   ██  ██  ██\n// ██ ████ ██ █████   ██ ████ ██ ██    ██ ██████    ████\n// ██  ██  ██ ██      ██  ██  ██ ██    ██ ██   ██    ██\n// ██      ██ ███████ ██      ██  ██████  ██   ██    ██\n//\n// >>memory\n\n// a helper macro to clear a struct with potentially ARC'ed ObjC references\n#if defined(SOKOL_METAL)\n    #if defined(__cplusplus)\n        #define _SG_CLEAR_ARC_STRUCT(type, item) { item = type(); }\n    #else\n        #define _SG_CLEAR_ARC_STRUCT(type, item) { item = (type) { 0 }; }\n    #endif\n#else\n    #define _SG_CLEAR_ARC_STRUCT(type, item) { _sg_clear(&item, sizeof(item)); }\n#endif\n\n_SOKOL_PRIVATE void _sg_clear(void* ptr, size_t size) {\n    SOKOL_ASSERT(ptr && (size > 0));\n    memset(ptr, 0, size);\n}\n\n_SOKOL_PRIVATE void* _sg_malloc(size_t size) {\n    SOKOL_ASSERT(size > 0);\n    void* ptr;\n    if (_sg.desc.allocator.alloc_fn) {\n        ptr = _sg.desc.allocator.alloc_fn(size, _sg.desc.allocator.user_data);\n    } else {\n        ptr = malloc(size);\n    }\n    if (0 == ptr) {\n        _SG_PANIC(MALLOC_FAILED);\n    }\n    return ptr;\n}\n\n_SOKOL_PRIVATE void* _sg_malloc_clear(size_t size) {\n    void* ptr = _sg_malloc(size);\n    _sg_clear(ptr, size);\n    return ptr;\n}\n\n_SOKOL_PRIVATE void _sg_free(void* ptr) {\n    if (_sg.desc.allocator.free_fn) {\n        _sg.desc.allocator.free_fn(ptr, _sg.desc.allocator.user_data);\n    } else {\n        free(ptr);\n    }\n}\n\n_SOKOL_PRIVATE bool _sg_strempty(const _sg_str_t* str) {\n    return 0 == str->buf[0];\n}\n\n_SOKOL_PRIVATE const char* _sg_strptr(const _sg_str_t* str) {\n    return &str->buf[0];\n}\n\n_SOKOL_PRIVATE void _sg_strcpy(_sg_str_t* dst, const char* src) {\n    SOKOL_ASSERT(dst);\n    if (src) {\n        #if defined(_MSC_VER)\n        strncpy_s(dst->buf, _SG_STRING_SIZE, src, (_SG_STRING_SIZE-1));\n        #else\n        strncpy(dst->buf, src, _SG_STRING_SIZE);\n        #endif\n        dst->buf[_SG_STRING_SIZE-1] = 0;\n    } else {\n        _sg_clear(dst->buf, _SG_STRING_SIZE);\n    }\n}\n\n// ██   ██ ███████ ██      ██████  ███████ ██████  ███████\n// ██   ██ ██      ██      ██   ██ ██      ██   ██ ██\n// ███████ █████   ██      ██████  █████   ██████  ███████\n// ██   ██ ██      ██      ██      ██      ██   ██      ██\n// ██   ██ ███████ ███████ ██      ███████ ██   ██ ███████\n//\n// >>helpers\n_SOKOL_PRIVATE uint32_t _sg_align_u32(uint32_t val, uint32_t align) {\n    SOKOL_ASSERT((align > 0) && ((align & (align - 1)) == 0));\n    return (val + (align - 1)) & ~(align - 1);\n}\n\ntypedef struct { int x, y, w, h; } _sg_recti_t;\n\n_SOKOL_PRIVATE _sg_recti_t _sg_clipi(int x, int y, int w, int h, int clip_width, int clip_height) {\n    x = _sg_min(_sg_max(0, x), clip_width-1);\n    y = _sg_min(_sg_max(0, y), clip_height-1);\n    if ((x + w) > clip_width) {\n        w = clip_width - x;\n    }\n    if ((y + h) > clip_height) {\n        h = clip_height - y;\n    }\n    w = _sg_max(w, 1);\n    h = _sg_max(h, 1);\n    const _sg_recti_t res = { x, y, w, h };\n    return res;\n}\n\n_SOKOL_PRIVATE int _sg_vertexformat_bytesize(sg_vertex_format fmt) {\n    switch (fmt) {\n        case SG_VERTEXFORMAT_FLOAT:     return 4;\n        case SG_VERTEXFORMAT_FLOAT2:    return 8;\n        case SG_VERTEXFORMAT_FLOAT3:    return 12;\n        case SG_VERTEXFORMAT_FLOAT4:    return 16;\n        case SG_VERTEXFORMAT_BYTE4:     return 4;\n        case SG_VERTEXFORMAT_BYTE4N:    return 4;\n        case SG_VERTEXFORMAT_UBYTE4:    return 4;\n        case SG_VERTEXFORMAT_UBYTE4N:   return 4;\n        case SG_VERTEXFORMAT_SHORT2:    return 4;\n        case SG_VERTEXFORMAT_SHORT2N:   return 4;\n        case SG_VERTEXFORMAT_USHORT2N:  return 4;\n        case SG_VERTEXFORMAT_SHORT4:    return 8;\n        case SG_VERTEXFORMAT_SHORT4N:   return 8;\n        case SG_VERTEXFORMAT_USHORT4N:  return 8;\n        case SG_VERTEXFORMAT_UINT10_N2: return 4;\n        case SG_VERTEXFORMAT_HALF2:     return 4;\n        case SG_VERTEXFORMAT_HALF4:     return 8;\n        case SG_VERTEXFORMAT_INVALID:   return 0;\n        default:\n            SOKOL_UNREACHABLE;\n            return -1;\n    }\n}\n\n_SOKOL_PRIVATE uint32_t _sg_uniform_alignment(sg_uniform_type type, int array_count, sg_uniform_layout ub_layout) {\n    if (ub_layout == SG_UNIFORMLAYOUT_NATIVE) {\n        return 1;\n    } else {\n        SOKOL_ASSERT(array_count > 0);\n        if (array_count == 1) {\n            switch (type) {\n                case SG_UNIFORMTYPE_FLOAT:\n                case SG_UNIFORMTYPE_INT:\n                    return 4;\n                case SG_UNIFORMTYPE_FLOAT2:\n                case SG_UNIFORMTYPE_INT2:\n                    return 8;\n                case SG_UNIFORMTYPE_FLOAT3:\n                case SG_UNIFORMTYPE_FLOAT4:\n                case SG_UNIFORMTYPE_INT3:\n                case SG_UNIFORMTYPE_INT4:\n                    return 16;\n                case SG_UNIFORMTYPE_MAT4:\n                    return 16;\n                default:\n                    SOKOL_UNREACHABLE;\n                    return 1;\n            }\n        } else {\n            return 16;\n        }\n    }\n}\n\n_SOKOL_PRIVATE uint32_t _sg_uniform_size(sg_uniform_type type, int array_count, sg_uniform_layout ub_layout) {\n    SOKOL_ASSERT(array_count > 0);\n    if (array_count == 1) {\n        switch (type) {\n            case SG_UNIFORMTYPE_FLOAT:\n            case SG_UNIFORMTYPE_INT:\n                return 4;\n            case SG_UNIFORMTYPE_FLOAT2:\n            case SG_UNIFORMTYPE_INT2:\n                return 8;\n            case SG_UNIFORMTYPE_FLOAT3:\n            case SG_UNIFORMTYPE_INT3:\n                return 12;\n            case SG_UNIFORMTYPE_FLOAT4:\n            case SG_UNIFORMTYPE_INT4:\n                return 16;\n            case SG_UNIFORMTYPE_MAT4:\n                return 64;\n            default:\n                SOKOL_UNREACHABLE;\n                return 0;\n        }\n    } else {\n        if (ub_layout == SG_UNIFORMLAYOUT_NATIVE) {\n            switch (type) {\n                case SG_UNIFORMTYPE_FLOAT:\n                case SG_UNIFORMTYPE_INT:\n                    return 4 * (uint32_t)array_count;\n                case SG_UNIFORMTYPE_FLOAT2:\n                case SG_UNIFORMTYPE_INT2:\n                    return 8 * (uint32_t)array_count;\n                case SG_UNIFORMTYPE_FLOAT3:\n                case SG_UNIFORMTYPE_INT3:\n                    return 12 * (uint32_t)array_count;\n                case SG_UNIFORMTYPE_FLOAT4:\n                case SG_UNIFORMTYPE_INT4:\n                    return 16 * (uint32_t)array_count;\n                case SG_UNIFORMTYPE_MAT4:\n                    return 64 * (uint32_t)array_count;\n                default:\n                    SOKOL_UNREACHABLE;\n                    return 0;\n            }\n        } else {\n            switch (type) {\n                case SG_UNIFORMTYPE_FLOAT:\n                case SG_UNIFORMTYPE_FLOAT2:\n                case SG_UNIFORMTYPE_FLOAT3:\n                case SG_UNIFORMTYPE_FLOAT4:\n                case SG_UNIFORMTYPE_INT:\n                case SG_UNIFORMTYPE_INT2:\n                case SG_UNIFORMTYPE_INT3:\n                case SG_UNIFORMTYPE_INT4:\n                    return 16 * (uint32_t)array_count;\n                case SG_UNIFORMTYPE_MAT4:\n                    return 64 * (uint32_t)array_count;\n                default:\n                    SOKOL_UNREACHABLE;\n                    return 0;\n            }\n        }\n    }\n}\n\n_SOKOL_PRIVATE bool _sg_is_compressed_pixel_format(sg_pixel_format fmt) {\n    switch (fmt) {\n        case SG_PIXELFORMAT_BC1_RGBA:\n        case SG_PIXELFORMAT_BC2_RGBA:\n        case SG_PIXELFORMAT_BC3_RGBA:\n        case SG_PIXELFORMAT_BC3_SRGBA:\n        case SG_PIXELFORMAT_BC4_R:\n        case SG_PIXELFORMAT_BC4_RSN:\n        case SG_PIXELFORMAT_BC5_RG:\n        case SG_PIXELFORMAT_BC5_RGSN:\n        case SG_PIXELFORMAT_BC6H_RGBF:\n        case SG_PIXELFORMAT_BC6H_RGBUF:\n        case SG_PIXELFORMAT_BC7_RGBA:\n        case SG_PIXELFORMAT_BC7_SRGBA:\n        case SG_PIXELFORMAT_PVRTC_RGB_2BPP:\n        case SG_PIXELFORMAT_PVRTC_RGB_4BPP:\n        case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:\n        case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:\n        case SG_PIXELFORMAT_ETC2_RGB8:\n        case SG_PIXELFORMAT_ETC2_SRGB8:\n        case SG_PIXELFORMAT_ETC2_RGB8A1:\n        case SG_PIXELFORMAT_ETC2_RGBA8:\n        case SG_PIXELFORMAT_ETC2_SRGB8A8:\n        case SG_PIXELFORMAT_EAC_R11:\n        case SG_PIXELFORMAT_EAC_R11SN:\n        case SG_PIXELFORMAT_EAC_RG11:\n        case SG_PIXELFORMAT_EAC_RG11SN:\n        case SG_PIXELFORMAT_ASTC_4x4_RGBA:\n        case SG_PIXELFORMAT_ASTC_4x4_SRGBA:\n            return true;\n        default:\n            return false;\n    }\n}\n\n_SOKOL_PRIVATE bool _sg_is_valid_rendertarget_color_format(sg_pixel_format fmt) {\n    const int fmt_index = (int) fmt;\n    SOKOL_ASSERT((fmt_index >= 0) && (fmt_index < _SG_PIXELFORMAT_NUM));\n    return _sg.formats[fmt_index].render && !_sg.formats[fmt_index].depth;\n}\n\n_SOKOL_PRIVATE bool _sg_is_valid_rendertarget_depth_format(sg_pixel_format fmt) {\n    const int fmt_index = (int) fmt;\n    SOKOL_ASSERT((fmt_index >= 0) && (fmt_index < _SG_PIXELFORMAT_NUM));\n    return _sg.formats[fmt_index].render && _sg.formats[fmt_index].depth;\n}\n\n_SOKOL_PRIVATE bool _sg_is_depth_or_depth_stencil_format(sg_pixel_format fmt) {\n    return (SG_PIXELFORMAT_DEPTH == fmt) || (SG_PIXELFORMAT_DEPTH_STENCIL == fmt);\n}\n\n_SOKOL_PRIVATE bool _sg_is_depth_stencil_format(sg_pixel_format fmt) {\n    return (SG_PIXELFORMAT_DEPTH_STENCIL == fmt);\n}\n\n_SOKOL_PRIVATE int _sg_pixelformat_bytesize(sg_pixel_format fmt) {\n    switch (fmt) {\n        case SG_PIXELFORMAT_R8:\n        case SG_PIXELFORMAT_R8SN:\n        case SG_PIXELFORMAT_R8UI:\n        case SG_PIXELFORMAT_R8SI:\n            return 1;\n        case SG_PIXELFORMAT_R16:\n        case SG_PIXELFORMAT_R16SN:\n        case SG_PIXELFORMAT_R16UI:\n        case SG_PIXELFORMAT_R16SI:\n        case SG_PIXELFORMAT_R16F:\n        case SG_PIXELFORMAT_RG8:\n        case SG_PIXELFORMAT_RG8SN:\n        case SG_PIXELFORMAT_RG8UI:\n        case SG_PIXELFORMAT_RG8SI:\n            return 2;\n        case SG_PIXELFORMAT_R32UI:\n        case SG_PIXELFORMAT_R32SI:\n        case SG_PIXELFORMAT_R32F:\n        case SG_PIXELFORMAT_RG16:\n        case SG_PIXELFORMAT_RG16SN:\n        case SG_PIXELFORMAT_RG16UI:\n        case SG_PIXELFORMAT_RG16SI:\n        case SG_PIXELFORMAT_RG16F:\n        case SG_PIXELFORMAT_RGBA8:\n        case SG_PIXELFORMAT_SRGB8A8:\n        case SG_PIXELFORMAT_RGBA8SN:\n        case SG_PIXELFORMAT_RGBA8UI:\n        case SG_PIXELFORMAT_RGBA8SI:\n        case SG_PIXELFORMAT_BGRA8:\n        case SG_PIXELFORMAT_RGB10A2:\n        case SG_PIXELFORMAT_RG11B10F:\n        case SG_PIXELFORMAT_RGB9E5:\n            return 4;\n        case SG_PIXELFORMAT_RG32UI:\n        case SG_PIXELFORMAT_RG32SI:\n        case SG_PIXELFORMAT_RG32F:\n        case SG_PIXELFORMAT_RGBA16:\n        case SG_PIXELFORMAT_RGBA16SN:\n        case SG_PIXELFORMAT_RGBA16UI:\n        case SG_PIXELFORMAT_RGBA16SI:\n        case SG_PIXELFORMAT_RGBA16F:\n            return 8;\n        case SG_PIXELFORMAT_RGBA32UI:\n        case SG_PIXELFORMAT_RGBA32SI:\n        case SG_PIXELFORMAT_RGBA32F:\n            return 16;\n        case SG_PIXELFORMAT_DEPTH:\n        case SG_PIXELFORMAT_DEPTH_STENCIL:\n            return 4;\n        default:\n            SOKOL_UNREACHABLE;\n            return 0;\n    }\n}\n\n_SOKOL_PRIVATE int _sg_roundup(int val, int round_to) {\n    return (val+(round_to-1)) & ~(round_to-1);\n}\n\n_SOKOL_PRIVATE uint32_t _sg_roundup_u32(uint32_t val, uint32_t round_to) {\n    return (val+(round_to-1)) & ~(round_to-1);\n}\n\n_SOKOL_PRIVATE uint64_t _sg_roundup_u64(uint64_t val, uint64_t round_to) {\n    return (val+(round_to-1)) & ~(round_to-1);\n}\n\n_SOKOL_PRIVATE bool _sg_multiple_u64(uint64_t val, uint64_t of) {\n    return (val & (of-1)) == 0;\n}\n\n/* return row pitch for an image\n\n    see ComputePitch in https://github.com/microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexUtil.cpp\n\n    For the special PVRTC pitch computation, see:\n    GL extension requirement (https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt)\n\n    Quote:\n\n    6) How is the imageSize argument calculated for the CompressedTexImage2D\n       and CompressedTexSubImage2D functions.\n\n       Resolution: For PVRTC 4BPP formats the imageSize is calculated as:\n          ( max(width, 8) * max(height, 8) * 4 + 7) / 8\n       For PVRTC 2BPP formats the imageSize is calculated as:\n          ( max(width, 16) * max(height, 8) * 2 + 7) / 8\n*/\n_SOKOL_PRIVATE int _sg_row_pitch(sg_pixel_format fmt, int width, int row_align) {\n    int pitch;\n    switch (fmt) {\n        case SG_PIXELFORMAT_BC1_RGBA:\n        case SG_PIXELFORMAT_BC4_R:\n        case SG_PIXELFORMAT_BC4_RSN:\n        case SG_PIXELFORMAT_ETC2_RGB8:\n        case SG_PIXELFORMAT_ETC2_SRGB8:\n        case SG_PIXELFORMAT_ETC2_RGB8A1:\n        case SG_PIXELFORMAT_EAC_R11:\n        case SG_PIXELFORMAT_EAC_R11SN:\n            pitch = ((width + 3) / 4) * 8;\n            pitch = pitch < 8 ? 8 : pitch;\n            break;\n        case SG_PIXELFORMAT_BC2_RGBA:\n        case SG_PIXELFORMAT_BC3_RGBA:\n        case SG_PIXELFORMAT_BC3_SRGBA:\n        case SG_PIXELFORMAT_BC5_RG:\n        case SG_PIXELFORMAT_BC5_RGSN:\n        case SG_PIXELFORMAT_BC6H_RGBF:\n        case SG_PIXELFORMAT_BC6H_RGBUF:\n        case SG_PIXELFORMAT_BC7_RGBA:\n        case SG_PIXELFORMAT_BC7_SRGBA:\n        case SG_PIXELFORMAT_ETC2_RGBA8:\n        case SG_PIXELFORMAT_ETC2_SRGB8A8:\n        case SG_PIXELFORMAT_EAC_RG11:\n        case SG_PIXELFORMAT_EAC_RG11SN:\n        case SG_PIXELFORMAT_ASTC_4x4_RGBA:\n        case SG_PIXELFORMAT_ASTC_4x4_SRGBA:\n            pitch = ((width + 3) / 4) * 16;\n            pitch = pitch < 16 ? 16 : pitch;\n            break;\n        case SG_PIXELFORMAT_PVRTC_RGB_4BPP:\n        case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:\n            pitch = (_sg_max(width, 8) * 4 + 7) / 8;\n            break;\n        case SG_PIXELFORMAT_PVRTC_RGB_2BPP:\n        case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:\n            pitch = (_sg_max(width, 16) * 2 + 7) / 8;\n            break;\n        default:\n            pitch = width * _sg_pixelformat_bytesize(fmt);\n            break;\n    }\n    pitch = _sg_roundup(pitch, row_align);\n    return pitch;\n}\n\n// compute the number of rows in a surface depending on pixel format\n_SOKOL_PRIVATE int _sg_num_rows(sg_pixel_format fmt, int height) {\n    int num_rows;\n    switch (fmt) {\n        case SG_PIXELFORMAT_BC1_RGBA:\n        case SG_PIXELFORMAT_BC4_R:\n        case SG_PIXELFORMAT_BC4_RSN:\n        case SG_PIXELFORMAT_ETC2_RGB8:\n        case SG_PIXELFORMAT_ETC2_SRGB8:\n        case SG_PIXELFORMAT_ETC2_RGB8A1:\n        case SG_PIXELFORMAT_ETC2_RGBA8:\n        case SG_PIXELFORMAT_ETC2_SRGB8A8:\n        case SG_PIXELFORMAT_EAC_R11:\n        case SG_PIXELFORMAT_EAC_R11SN:\n        case SG_PIXELFORMAT_EAC_RG11:\n        case SG_PIXELFORMAT_EAC_RG11SN:\n        case SG_PIXELFORMAT_BC2_RGBA:\n        case SG_PIXELFORMAT_BC3_RGBA:\n        case SG_PIXELFORMAT_BC3_SRGBA:\n        case SG_PIXELFORMAT_BC5_RG:\n        case SG_PIXELFORMAT_BC5_RGSN:\n        case SG_PIXELFORMAT_BC6H_RGBF:\n        case SG_PIXELFORMAT_BC6H_RGBUF:\n        case SG_PIXELFORMAT_BC7_RGBA:\n        case SG_PIXELFORMAT_BC7_SRGBA:\n        case SG_PIXELFORMAT_ASTC_4x4_RGBA:\n        case SG_PIXELFORMAT_ASTC_4x4_SRGBA:\n            num_rows = ((height + 3) / 4);\n            break;\n        case SG_PIXELFORMAT_PVRTC_RGB_4BPP:\n        case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:\n        case SG_PIXELFORMAT_PVRTC_RGB_2BPP:\n        case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:\n            /* NOTE: this is most likely not correct because it ignores any\n                PVCRTC block size, but multiplied with _sg_row_pitch()\n                it gives the correct surface pitch.\n\n                See: https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt\n            */\n            num_rows = ((_sg_max(height, 8) + 7) / 8) * 8;\n            break;\n        default:\n            num_rows = height;\n            break;\n    }\n    if (num_rows < 1) {\n        num_rows = 1;\n    }\n    return num_rows;\n}\n\n// return size of a mipmap level\n_SOKOL_PRIVATE int _sg_miplevel_dim(int base_dim, int mip_level) {\n    return _sg_max(base_dim >> mip_level, 1);\n}\n\n/* return pitch of a 2D subimage / texture slice\n    see ComputePitch in https://github.com/microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexUtil.cpp\n*/\n_SOKOL_PRIVATE int _sg_surface_pitch(sg_pixel_format fmt, int width, int height, int row_align) {\n    int num_rows = _sg_num_rows(fmt, height);\n    return num_rows * _sg_row_pitch(fmt, width, row_align);\n}\n\n// capability table pixel format helper functions\n_SOKOL_PRIVATE void _sg_pixelformat_all(_sg_pixelformat_info_t* pfi) {\n    pfi->sample = true;\n    pfi->filter = true;\n    pfi->blend = true;\n    pfi->render = true;\n    pfi->msaa = true;\n}\n\n_SOKOL_PRIVATE void _sg_pixelformat_s(_sg_pixelformat_info_t* pfi) {\n    pfi->sample = true;\n}\n\n_SOKOL_PRIVATE void _sg_pixelformat_sf(_sg_pixelformat_info_t* pfi) {\n    pfi->sample = true;\n    pfi->filter = true;\n}\n\n_SOKOL_PRIVATE void _sg_pixelformat_sr(_sg_pixelformat_info_t* pfi) {\n    pfi->sample = true;\n    pfi->render = true;\n}\n\n_SOKOL_PRIVATE void _sg_pixelformat_sfr(_sg_pixelformat_info_t* pfi) {\n    pfi->sample = true;\n    pfi->filter = true;\n    pfi->render = true;\n}\n\n_SOKOL_PRIVATE void _sg_pixelformat_srmd(_sg_pixelformat_info_t* pfi) {\n    pfi->sample = true;\n    pfi->render = true;\n    pfi->msaa = true;\n    pfi->depth = true;\n}\n\n_SOKOL_PRIVATE void _sg_pixelformat_srm(_sg_pixelformat_info_t* pfi) {\n    pfi->sample = true;\n    pfi->render = true;\n    pfi->msaa = true;\n}\n\n_SOKOL_PRIVATE void _sg_pixelformat_sfrm(_sg_pixelformat_info_t* pfi) {\n    pfi->sample = true;\n    pfi->filter = true;\n    pfi->render = true;\n    pfi->msaa = true;\n}\n_SOKOL_PRIVATE void _sg_pixelformat_sbrm(_sg_pixelformat_info_t* pfi) {\n    pfi->sample = true;\n    pfi->blend = true;\n    pfi->render = true;\n    pfi->msaa = true;\n}\n\n_SOKOL_PRIVATE void _sg_pixelformat_sbr(_sg_pixelformat_info_t* pfi) {\n    pfi->sample = true;\n    pfi->blend = true;\n    pfi->render = true;\n}\n\n_SOKOL_PRIVATE void _sg_pixelformat_sfbr(_sg_pixelformat_info_t* pfi) {\n    pfi->sample = true;\n    pfi->filter = true;\n    pfi->blend = true;\n    pfi->render = true;\n}\n\n_SOKOL_PRIVATE sg_pass_action _sg_pass_action_defaults(const sg_pass_action* action) {\n    SOKOL_ASSERT(action);\n    sg_pass_action res = *action;\n    for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {\n        if (res.colors[i].load_action == _SG_LOADACTION_DEFAULT) {\n            res.colors[i].load_action = SG_LOADACTION_CLEAR;\n            res.colors[i].clear_value.r = SG_DEFAULT_CLEAR_RED;\n            res.colors[i].clear_value.g = SG_DEFAULT_CLEAR_GREEN;\n            res.colors[i].clear_value.b = SG_DEFAULT_CLEAR_BLUE;\n            res.colors[i].clear_value.a = SG_DEFAULT_CLEAR_ALPHA;\n        }\n        if (res.colors[i].store_action == _SG_STOREACTION_DEFAULT) {\n            res.colors[i].store_action = SG_STOREACTION_STORE;\n        }\n    }\n    if (res.depth.load_action == _SG_LOADACTION_DEFAULT) {\n        res.depth.load_action = SG_LOADACTION_CLEAR;\n        res.depth.clear_value = SG_DEFAULT_CLEAR_DEPTH;\n    }\n    if (res.depth.store_action == _SG_STOREACTION_DEFAULT) {\n        res.depth.store_action = SG_STOREACTION_DONTCARE;\n    }\n    if (res.stencil.load_action == _SG_LOADACTION_DEFAULT) {\n        res.stencil.load_action = SG_LOADACTION_CLEAR;\n        res.stencil.clear_value = SG_DEFAULT_CLEAR_STENCIL;\n    }\n    if (res.stencil.store_action == _SG_STOREACTION_DEFAULT) {\n        res.stencil.store_action = SG_STOREACTION_DONTCARE;\n    }\n    return res;\n}\n\n// ██████  ██    ██ ███    ███ ███    ███ ██    ██     ██████   █████   ██████ ██   ██ ███████ ███    ██ ██████\n// ██   ██ ██    ██ ████  ████ ████  ████  ██  ██      ██   ██ ██   ██ ██      ██  ██  ██      ████   ██ ██   ██\n// ██   ██ ██    ██ ██ ████ ██ ██ ████ ██   ████       ██████  ███████ ██      █████   █████   ██ ██  ██ ██   ██\n// ██   ██ ██    ██ ██  ██  ██ ██  ██  ██    ██        ██   ██ ██   ██ ██      ██  ██  ██      ██  ██ ██ ██   ██\n// ██████   ██████  ██      ██ ██      ██    ██        ██████  ██   ██  ██████ ██   ██ ███████ ██   ████ ██████\n//\n// >>dummy backend\n#if defined(SOKOL_DUMMY_BACKEND)\n\n_SOKOL_PRIVATE void _sg_dummy_setup_backend(const sg_desc* desc) {\n    SOKOL_ASSERT(desc);\n    _SOKOL_UNUSED(desc);\n    _sg.backend = SG_BACKEND_DUMMY;\n    for (int i = SG_PIXELFORMAT_R8; i < SG_PIXELFORMAT_BC1_RGBA; i++) {\n        _sg.formats[i].sample = true;\n        _sg.formats[i].filter = true;\n        _sg.formats[i].render = true;\n        _sg.formats[i].blend = true;\n        _sg.formats[i].msaa = true;\n    }\n    _sg.formats[SG_PIXELFORMAT_DEPTH].depth = true;\n    _sg.formats[SG_PIXELFORMAT_DEPTH_STENCIL].depth = true;\n}\n\n_SOKOL_PRIVATE void _sg_dummy_discard_backend(void) {\n    // empty\n}\n\n_SOKOL_PRIVATE void _sg_dummy_reset_state_cache(void) {\n    // empty\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_dummy_create_buffer(_sg_buffer_t* buf, const sg_buffer_desc* desc) {\n    SOKOL_ASSERT(buf && desc);\n    _SOKOL_UNUSED(buf);\n    _SOKOL_UNUSED(desc);\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_dummy_discard_buffer(_sg_buffer_t* buf) {\n    SOKOL_ASSERT(buf);\n    _SOKOL_UNUSED(buf);\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_dummy_create_image(_sg_image_t* img, const sg_image_desc* desc) {\n    SOKOL_ASSERT(img && desc);\n    _SOKOL_UNUSED(img);\n    _SOKOL_UNUSED(desc);\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_dummy_discard_image(_sg_image_t* img) {\n    SOKOL_ASSERT(img);\n    _SOKOL_UNUSED(img);\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_dummy_create_sampler(_sg_sampler_t* smp, const sg_sampler_desc* desc) {\n    SOKOL_ASSERT(smp && desc);\n    _SOKOL_UNUSED(smp);\n    _SOKOL_UNUSED(desc);\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_dummy_discard_sampler(_sg_sampler_t* smp) {\n    SOKOL_ASSERT(smp);\n    _SOKOL_UNUSED(smp);\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_dummy_create_shader(_sg_shader_t* shd, const sg_shader_desc* desc) {\n    SOKOL_ASSERT(shd && desc);\n    _SOKOL_UNUSED(shd);\n    _SOKOL_UNUSED(desc);\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_dummy_discard_shader(_sg_shader_t* shd) {\n    SOKOL_ASSERT(shd);\n    _SOKOL_UNUSED(shd);\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_dummy_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) {\n    SOKOL_ASSERT(pip && desc);\n    pip->shader = shd;\n    for (int attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {\n        const sg_vertex_attr_state* a_state = &desc->layout.attrs[attr_index];\n        if (a_state->format == SG_VERTEXFORMAT_INVALID) {\n            break;\n        }\n        SOKOL_ASSERT(a_state->buffer_index < SG_MAX_VERTEX_BUFFERS);\n        pip->cmn.vertex_buffer_layout_active[a_state->buffer_index] = true;\n    }\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_dummy_discard_pipeline(_sg_pipeline_t* pip) {\n    SOKOL_ASSERT(pip);\n    _SOKOL_UNUSED(pip);\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_dummy_create_attachments(_sg_attachments_t* atts, _sg_image_t** color_images, _sg_image_t** resolve_images, _sg_image_t* ds_img, const sg_attachments_desc* desc) {\n    SOKOL_ASSERT(atts && desc);\n    SOKOL_ASSERT(color_images && resolve_images);\n\n    for (int i = 0; i < atts->cmn.num_colors; i++) {\n        const sg_attachment_desc* color_desc = &desc->colors[i];\n        _SOKOL_UNUSED(color_desc);\n        SOKOL_ASSERT(color_desc->image.id != SG_INVALID_ID);\n        SOKOL_ASSERT(0 == atts->dmy.colors[i].image);\n        SOKOL_ASSERT(color_images[i] && (color_images[i]->slot.id == color_desc->image.id));\n        SOKOL_ASSERT(_sg_is_valid_rendertarget_color_format(color_images[i]->cmn.pixel_format));\n        atts->dmy.colors[i].image = color_images[i];\n\n        const sg_attachment_desc* resolve_desc = &desc->resolves[i];\n        if (resolve_desc->image.id != SG_INVALID_ID) {\n            SOKOL_ASSERT(0 == atts->dmy.resolves[i].image);\n            SOKOL_ASSERT(resolve_images[i] && (resolve_images[i]->slot.id == resolve_desc->image.id));\n            SOKOL_ASSERT(color_images[i] && (color_images[i]->cmn.pixel_format == resolve_images[i]->cmn.pixel_format));\n            atts->dmy.resolves[i].image = resolve_images[i];\n        }\n    }\n\n    SOKOL_ASSERT(0 == atts->dmy.depth_stencil.image);\n    const sg_attachment_desc* ds_desc = &desc->depth_stencil;\n    if (ds_desc->image.id != SG_INVALID_ID) {\n        SOKOL_ASSERT(ds_img && (ds_img->slot.id == ds_desc->image.id));\n        SOKOL_ASSERT(_sg_is_valid_rendertarget_depth_format(ds_img->cmn.pixel_format));\n        atts->dmy.depth_stencil.image = ds_img;\n    }\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_dummy_discard_attachments(_sg_attachments_t* atts) {\n    SOKOL_ASSERT(atts);\n    _SOKOL_UNUSED(atts);\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_dummy_attachments_color_image(const _sg_attachments_t* atts, int index) {\n    SOKOL_ASSERT(atts && (index >= 0) && (index < SG_MAX_COLOR_ATTACHMENTS));\n    return atts->dmy.colors[index].image;\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_dummy_attachments_resolve_image(const _sg_attachments_t* atts, int index) {\n    SOKOL_ASSERT(atts && (index >= 0) && (index < SG_MAX_COLOR_ATTACHMENTS));\n    return atts->dmy.resolves[index].image;\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_dummy_attachments_ds_image(const _sg_attachments_t* atts) {\n    SOKOL_ASSERT(atts);\n    return atts->dmy.depth_stencil.image;\n}\n\n_SOKOL_PRIVATE void _sg_dummy_begin_pass(const sg_pass* pass) {\n    SOKOL_ASSERT(pass);\n    _SOKOL_UNUSED(pass);\n}\n\n_SOKOL_PRIVATE void _sg_dummy_end_pass(void) {\n    // empty\n}\n\n_SOKOL_PRIVATE void _sg_dummy_commit(void) {\n    // empty\n}\n\n_SOKOL_PRIVATE void _sg_dummy_apply_viewport(int x, int y, int w, int h, bool origin_top_left) {\n    _SOKOL_UNUSED(x);\n    _SOKOL_UNUSED(y);\n    _SOKOL_UNUSED(w);\n    _SOKOL_UNUSED(h);\n    _SOKOL_UNUSED(origin_top_left);\n}\n\n_SOKOL_PRIVATE void _sg_dummy_apply_scissor_rect(int x, int y, int w, int h, bool origin_top_left) {\n    _SOKOL_UNUSED(x);\n    _SOKOL_UNUSED(y);\n    _SOKOL_UNUSED(w);\n    _SOKOL_UNUSED(h);\n    _SOKOL_UNUSED(origin_top_left);\n}\n\n_SOKOL_PRIVATE void _sg_dummy_apply_pipeline(_sg_pipeline_t* pip) {\n    SOKOL_ASSERT(pip);\n    _SOKOL_UNUSED(pip);\n}\n\n_SOKOL_PRIVATE bool _sg_dummy_apply_bindings(_sg_bindings_t* bnd) {\n    SOKOL_ASSERT(bnd);\n    SOKOL_ASSERT(bnd->pip);\n    _SOKOL_UNUSED(bnd);\n    return true;\n}\n\n_SOKOL_PRIVATE void _sg_dummy_apply_uniforms(sg_shader_stage stage_index, int ub_index, const sg_range* data) {\n    _SOKOL_UNUSED(stage_index);\n    _SOKOL_UNUSED(ub_index);\n    _SOKOL_UNUSED(data);\n}\n\n_SOKOL_PRIVATE void _sg_dummy_draw(int base_element, int num_elements, int num_instances) {\n    _SOKOL_UNUSED(base_element);\n    _SOKOL_UNUSED(num_elements);\n    _SOKOL_UNUSED(num_instances);\n}\n\n_SOKOL_PRIVATE void _sg_dummy_update_buffer(_sg_buffer_t* buf, const sg_range* data) {\n    SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0));\n    _SOKOL_UNUSED(data);\n    if (++buf->cmn.active_slot >= buf->cmn.num_slots) {\n        buf->cmn.active_slot = 0;\n    }\n}\n\n_SOKOL_PRIVATE bool _sg_dummy_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) {\n    SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0));\n    _SOKOL_UNUSED(data);\n    if (new_frame) {\n        if (++buf->cmn.active_slot >= buf->cmn.num_slots) {\n            buf->cmn.active_slot = 0;\n        }\n    }\n    return true;\n}\n\n_SOKOL_PRIVATE void _sg_dummy_update_image(_sg_image_t* img, const sg_image_data* data) {\n    SOKOL_ASSERT(img && data);\n    _SOKOL_UNUSED(data);\n    if (++img->cmn.active_slot >= img->cmn.num_slots) {\n        img->cmn.active_slot = 0;\n    }\n}\n\n//  ██████  ██████  ███████ ███    ██  ██████  ██          ██████   █████   ██████ ██   ██ ███████ ███    ██ ██████\n// ██    ██ ██   ██ ██      ████   ██ ██       ██          ██   ██ ██   ██ ██      ██  ██  ██      ████   ██ ██   ██\n// ██    ██ ██████  █████   ██ ██  ██ ██   ███ ██          ██████  ███████ ██      █████   █████   ██ ██  ██ ██   ██\n// ██    ██ ██      ██      ██  ██ ██ ██    ██ ██          ██   ██ ██   ██ ██      ██  ██  ██      ██  ██ ██ ██   ██\n//  ██████  ██      ███████ ██   ████  ██████  ███████     ██████  ██   ██  ██████ ██   ██ ███████ ██   ████ ██████\n//\n// >>opengl backend\n#elif defined(_SOKOL_ANY_GL)\n\n// optional GL loader for win32\n#if defined(_SOKOL_USE_WIN32_GL_LOADER)\n\n#ifndef SG_GL_FUNCS_EXT\n#define SG_GL_FUNCS_EXT\n#endif\n\n// X Macro list of GL function names and signatures\n#define _SG_GL_FUNCS \\\n    SG_GL_FUNCS_EXT \\\n    _SG_XMACRO(glBindVertexArray,                 void, (GLuint array)) \\\n    _SG_XMACRO(glFramebufferTextureLayer,         void, (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)) \\\n    _SG_XMACRO(glGenFramebuffers,                 void, (GLsizei n, GLuint * framebuffers)) \\\n    _SG_XMACRO(glBindFramebuffer,                 void, (GLenum target, GLuint framebuffer)) \\\n    _SG_XMACRO(glBindRenderbuffer,                void, (GLenum target, GLuint renderbuffer)) \\\n    _SG_XMACRO(glGetStringi,                      const GLubyte *, (GLenum name, GLuint index)) \\\n    _SG_XMACRO(glClearBufferfi,                   void, (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)) \\\n    _SG_XMACRO(glClearBufferfv,                   void, (GLenum buffer, GLint drawbuffer, const GLfloat * value)) \\\n    _SG_XMACRO(glClearBufferuiv,                  void, (GLenum buffer, GLint drawbuffer, const GLuint * value)) \\\n    _SG_XMACRO(glClearBufferiv,                   void, (GLenum buffer, GLint drawbuffer, const GLint * value)) \\\n    _SG_XMACRO(glDeleteRenderbuffers,             void, (GLsizei n, const GLuint * renderbuffers)) \\\n    _SG_XMACRO(glUniform1fv,                      void, (GLint location, GLsizei count, const GLfloat * value)) \\\n    _SG_XMACRO(glUniform2fv,                      void, (GLint location, GLsizei count, const GLfloat * value)) \\\n    _SG_XMACRO(glUniform3fv,                      void, (GLint location, GLsizei count, const GLfloat * value)) \\\n    _SG_XMACRO(glUniform4fv,                      void, (GLint location, GLsizei count, const GLfloat * value)) \\\n    _SG_XMACRO(glUniform1iv,                      void, (GLint location, GLsizei count, const GLint * value)) \\\n    _SG_XMACRO(glUniform2iv,                      void, (GLint location, GLsizei count, const GLint * value)) \\\n    _SG_XMACRO(glUniform3iv,                      void, (GLint location, GLsizei count, const GLint * value)) \\\n    _SG_XMACRO(glUniform4iv,                      void, (GLint location, GLsizei count, const GLint * value)) \\\n    _SG_XMACRO(glUniformMatrix4fv,                void, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)) \\\n    _SG_XMACRO(glUseProgram,                      void, (GLuint program)) \\\n    _SG_XMACRO(glShaderSource,                    void, (GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length)) \\\n    _SG_XMACRO(glLinkProgram,                     void, (GLuint program)) \\\n    _SG_XMACRO(glGetUniformLocation,              GLint, (GLuint program, const GLchar * name)) \\\n    _SG_XMACRO(glGetShaderiv,                     void, (GLuint shader, GLenum pname, GLint * params)) \\\n    _SG_XMACRO(glGetProgramInfoLog,               void, (GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog)) \\\n    _SG_XMACRO(glGetAttribLocation,               GLint, (GLuint program, const GLchar * name)) \\\n    _SG_XMACRO(glDisableVertexAttribArray,        void, (GLuint index)) \\\n    _SG_XMACRO(glDeleteShader,                    void, (GLuint shader)) \\\n    _SG_XMACRO(glDeleteProgram,                   void, (GLuint program)) \\\n    _SG_XMACRO(glCompileShader,                   void, (GLuint shader)) \\\n    _SG_XMACRO(glStencilFuncSeparate,             void, (GLenum face, GLenum func, GLint ref, GLuint mask)) \\\n    _SG_XMACRO(glStencilOpSeparate,               void, (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass)) \\\n    _SG_XMACRO(glRenderbufferStorageMultisample,  void, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)) \\\n    _SG_XMACRO(glDrawBuffers,                     void, (GLsizei n, const GLenum * bufs)) \\\n    _SG_XMACRO(glVertexAttribDivisor,             void, (GLuint index, GLuint divisor)) \\\n    _SG_XMACRO(glBufferSubData,                   void, (GLenum target, GLintptr offset, GLsizeiptr size, const void * data)) \\\n    _SG_XMACRO(glGenBuffers,                      void, (GLsizei n, GLuint * buffers)) \\\n    _SG_XMACRO(glCheckFramebufferStatus,          GLenum, (GLenum target)) \\\n    _SG_XMACRO(glFramebufferRenderbuffer,         void, (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)) \\\n    _SG_XMACRO(glCompressedTexImage2D,            void, (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data)) \\\n    _SG_XMACRO(glCompressedTexImage3D,            void, (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data)) \\\n    _SG_XMACRO(glActiveTexture,                   void, (GLenum texture)) \\\n    _SG_XMACRO(glTexSubImage3D,                   void, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels)) \\\n    _SG_XMACRO(glRenderbufferStorage,             void, (GLenum target, GLenum internalformat, GLsizei width, GLsizei height)) \\\n    _SG_XMACRO(glGenTextures,                     void, (GLsizei n, GLuint * textures)) \\\n    _SG_XMACRO(glPolygonOffset,                   void, (GLfloat factor, GLfloat units)) \\\n    _SG_XMACRO(glDrawElements,                    void, (GLenum mode, GLsizei count, GLenum type, const void * indices)) \\\n    _SG_XMACRO(glDeleteFramebuffers,              void, (GLsizei n, const GLuint * framebuffers)) \\\n    _SG_XMACRO(glBlendEquationSeparate,           void, (GLenum modeRGB, GLenum modeAlpha)) \\\n    _SG_XMACRO(glDeleteTextures,                  void, (GLsizei n, const GLuint * textures)) \\\n    _SG_XMACRO(glGetProgramiv,                    void, (GLuint program, GLenum pname, GLint * params)) \\\n    _SG_XMACRO(glBindTexture,                     void, (GLenum target, GLuint texture)) \\\n    _SG_XMACRO(glTexImage3D,                      void, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels)) \\\n    _SG_XMACRO(glCreateShader,                    GLuint, (GLenum type)) \\\n    _SG_XMACRO(glTexSubImage2D,                   void, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels)) \\\n    _SG_XMACRO(glFramebufferTexture2D,            void, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)) \\\n    _SG_XMACRO(glCreateProgram,                   GLuint, (void)) \\\n    _SG_XMACRO(glViewport,                        void, (GLint x, GLint y, GLsizei width, GLsizei height)) \\\n    _SG_XMACRO(glDeleteBuffers,                   void, (GLsizei n, const GLuint * buffers)) \\\n    _SG_XMACRO(glDrawArrays,                      void, (GLenum mode, GLint first, GLsizei count)) \\\n    _SG_XMACRO(glDrawElementsInstanced,           void, (GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount)) \\\n    _SG_XMACRO(glVertexAttribPointer,             void, (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer)) \\\n    _SG_XMACRO(glUniform1i,                       void, (GLint location, GLint v0)) \\\n    _SG_XMACRO(glDisable,                         void, (GLenum cap)) \\\n    _SG_XMACRO(glColorMask,                       void, (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)) \\\n    _SG_XMACRO(glColorMaski,                      void, (GLuint buf, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)) \\\n    _SG_XMACRO(glBindBuffer,                      void, (GLenum target, GLuint buffer)) \\\n    _SG_XMACRO(glDeleteVertexArrays,              void, (GLsizei n, const GLuint * arrays)) \\\n    _SG_XMACRO(glDepthMask,                       void, (GLboolean flag)) \\\n    _SG_XMACRO(glDrawArraysInstanced,             void, (GLenum mode, GLint first, GLsizei count, GLsizei instancecount)) \\\n    _SG_XMACRO(glScissor,                         void, (GLint x, GLint y, GLsizei width, GLsizei height)) \\\n    _SG_XMACRO(glGenRenderbuffers,                void, (GLsizei n, GLuint * renderbuffers)) \\\n    _SG_XMACRO(glBufferData,                      void, (GLenum target, GLsizeiptr size, const void * data, GLenum usage)) \\\n    _SG_XMACRO(glBlendFuncSeparate,               void, (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)) \\\n    _SG_XMACRO(glTexParameteri,                   void, (GLenum target, GLenum pname, GLint param)) \\\n    _SG_XMACRO(glGetIntegerv,                     void, (GLenum pname, GLint * data)) \\\n    _SG_XMACRO(glEnable,                          void, (GLenum cap)) \\\n    _SG_XMACRO(glBlitFramebuffer,                 void, (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)) \\\n    _SG_XMACRO(glStencilMask,                     void, (GLuint mask)) \\\n    _SG_XMACRO(glAttachShader,                    void, (GLuint program, GLuint shader)) \\\n    _SG_XMACRO(glGetError,                        GLenum, (void)) \\\n    _SG_XMACRO(glBlendColor,                      void, (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)) \\\n    _SG_XMACRO(glTexParameterf,                   void, (GLenum target, GLenum pname, GLfloat param)) \\\n    _SG_XMACRO(glTexParameterfv,                  void, (GLenum target, GLenum pname, const GLfloat* params)) \\\n    _SG_XMACRO(glGetShaderInfoLog,                void, (GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog)) \\\n    _SG_XMACRO(glDepthFunc,                       void, (GLenum func)) \\\n    _SG_XMACRO(glStencilOp ,                      void, (GLenum fail, GLenum zfail, GLenum zpass)) \\\n    _SG_XMACRO(glStencilFunc,                     void, (GLenum func, GLint ref, GLuint mask)) \\\n    _SG_XMACRO(glEnableVertexAttribArray,         void, (GLuint index)) \\\n    _SG_XMACRO(glBlendFunc,                       void, (GLenum sfactor, GLenum dfactor)) \\\n    _SG_XMACRO(glReadBuffer,                      void, (GLenum src)) \\\n    _SG_XMACRO(glReadPixels,                      void, (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * data)) /* __v_ end */ \\\n    _SG_XMACRO(glTexImage2D,                      void, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels)) \\\n    _SG_XMACRO(glGenVertexArrays,                 void, (GLsizei n, GLuint * arrays)) \\\n    _SG_XMACRO(glFrontFace,                       void, (GLenum mode)) \\\n    _SG_XMACRO(glCullFace,                        void, (GLenum mode)) \\\n    _SG_XMACRO(glPixelStorei,                     void, (GLenum pname, GLint param)) \\\n    _SG_XMACRO(glBindSampler,                     void, (GLuint unit, GLuint sampler)) \\\n    _SG_XMACRO(glGenSamplers,                     void, (GLsizei n, GLuint* samplers)) \\\n    _SG_XMACRO(glSamplerParameteri,               void, (GLuint sampler, GLenum pname, GLint param)) \\\n    _SG_XMACRO(glSamplerParameterf,               void, (GLuint sampler, GLenum pname, GLfloat param)) \\\n    _SG_XMACRO(glSamplerParameterfv,              void, (GLuint sampler, GLenum pname, const GLfloat* params)) \\\n    _SG_XMACRO(glDeleteSamplers,                  void, (GLsizei n, const GLuint* samplers)) \\\n    _SG_XMACRO(glBindBufferBase,                  void, (GLenum target, GLuint index, GLuint buffer))\n\n// generate GL function pointer typedefs\n#define _SG_XMACRO(name, ret, args) typedef ret (GL_APIENTRY* PFN_ ## name) args;\n_SG_GL_FUNCS\n#undef _SG_XMACRO\n\n// generate GL function pointers\n#define _SG_XMACRO(name, ret, args) static PFN_ ## name name;\n_SG_GL_FUNCS\n#undef _SG_XMACRO\n\n// helper function to lookup GL functions in GL DLL\ntypedef PROC (WINAPI * _sg_wglGetProcAddress)(LPCSTR);\n_SOKOL_PRIVATE void* _sg_gl_getprocaddr(const char* name, _sg_wglGetProcAddress wgl_getprocaddress) {\n    void* proc_addr = (void*) wgl_getprocaddress(name);\n    if (0 == proc_addr) {\n        proc_addr = (void*) GetProcAddress(_sg.gl.opengl32_dll, name);\n    }\n    SOKOL_ASSERT(proc_addr);\n    return proc_addr;\n}\n\n// populate GL function pointers\n_SOKOL_PRIVATE  void _sg_gl_load_opengl(void) {\n    SOKOL_ASSERT(0 == _sg.gl.opengl32_dll);\n    _sg.gl.opengl32_dll = LoadLibraryA(\"opengl32.dll\");\n    SOKOL_ASSERT(_sg.gl.opengl32_dll);\n    _sg_wglGetProcAddress wgl_getprocaddress = (_sg_wglGetProcAddress) GetProcAddress(_sg.gl.opengl32_dll, \"wglGetProcAddress\");\n    SOKOL_ASSERT(wgl_getprocaddress);\n    #define _SG_XMACRO(name, ret, args) name = (PFN_ ## name) _sg_gl_getprocaddr(#name, wgl_getprocaddress);\n    _SG_GL_FUNCS\n    #undef _SG_XMACRO\n}\n\n_SOKOL_PRIVATE void _sg_gl_unload_opengl(void) {\n    SOKOL_ASSERT(_sg.gl.opengl32_dll);\n    FreeLibrary(_sg.gl.opengl32_dll);\n    _sg.gl.opengl32_dll = 0;\n}\n#endif // _SOKOL_USE_WIN32_GL_LOADER\n\n//-- type translation ----------------------------------------------------------\n_SOKOL_PRIVATE GLenum _sg_gl_buffer_target(sg_buffer_type t) {\n    switch (t) {\n        case SG_BUFFERTYPE_VERTEXBUFFER:    return GL_ARRAY_BUFFER;\n        case SG_BUFFERTYPE_INDEXBUFFER:     return GL_ELEMENT_ARRAY_BUFFER;\n        case SG_BUFFERTYPE_STORAGEBUFFER:   return GL_SHADER_STORAGE_BUFFER;\n        default: SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_texture_target(sg_image_type t) {\n    switch (t) {\n        case SG_IMAGETYPE_2D:   return GL_TEXTURE_2D;\n        case SG_IMAGETYPE_CUBE: return GL_TEXTURE_CUBE_MAP;\n        case SG_IMAGETYPE_3D:       return GL_TEXTURE_3D;\n        case SG_IMAGETYPE_ARRAY:    return GL_TEXTURE_2D_ARRAY;\n        default: SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_usage(sg_usage u) {\n    switch (u) {\n        case SG_USAGE_IMMUTABLE:    return GL_STATIC_DRAW;\n        case SG_USAGE_DYNAMIC:      return GL_DYNAMIC_DRAW;\n        case SG_USAGE_STREAM:       return GL_STREAM_DRAW;\n        default: SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_shader_stage(sg_shader_stage stage) {\n    switch (stage) {\n        case SG_SHADERSTAGE_VS:     return GL_VERTEX_SHADER;\n        case SG_SHADERSTAGE_FS:     return GL_FRAGMENT_SHADER;\n        default: SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLint _sg_gl_vertexformat_size(sg_vertex_format fmt) {\n    switch (fmt) {\n        case SG_VERTEXFORMAT_FLOAT:     return 1;\n        case SG_VERTEXFORMAT_FLOAT2:    return 2;\n        case SG_VERTEXFORMAT_FLOAT3:    return 3;\n        case SG_VERTEXFORMAT_FLOAT4:    return 4;\n        case SG_VERTEXFORMAT_BYTE4:     return 4;\n        case SG_VERTEXFORMAT_BYTE4N:    return 4;\n        case SG_VERTEXFORMAT_UBYTE4:    return 4;\n        case SG_VERTEXFORMAT_UBYTE4N:   return 4;\n        case SG_VERTEXFORMAT_SHORT2:    return 2;\n        case SG_VERTEXFORMAT_SHORT2N:   return 2;\n        case SG_VERTEXFORMAT_USHORT2N:  return 2;\n        case SG_VERTEXFORMAT_SHORT4:    return 4;\n        case SG_VERTEXFORMAT_SHORT4N:   return 4;\n        case SG_VERTEXFORMAT_USHORT4N:  return 4;\n        case SG_VERTEXFORMAT_UINT10_N2: return 4;\n        case SG_VERTEXFORMAT_HALF2:     return 2;\n        case SG_VERTEXFORMAT_HALF4:     return 4;\n        default: SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_vertexformat_type(sg_vertex_format fmt) {\n    switch (fmt) {\n        case SG_VERTEXFORMAT_FLOAT:\n        case SG_VERTEXFORMAT_FLOAT2:\n        case SG_VERTEXFORMAT_FLOAT3:\n        case SG_VERTEXFORMAT_FLOAT4:\n            return GL_FLOAT;\n        case SG_VERTEXFORMAT_BYTE4:\n        case SG_VERTEXFORMAT_BYTE4N:\n            return GL_BYTE;\n        case SG_VERTEXFORMAT_UBYTE4:\n        case SG_VERTEXFORMAT_UBYTE4N:\n            return GL_UNSIGNED_BYTE;\n        case SG_VERTEXFORMAT_SHORT2:\n        case SG_VERTEXFORMAT_SHORT2N:\n        case SG_VERTEXFORMAT_SHORT4:\n        case SG_VERTEXFORMAT_SHORT4N:\n            return GL_SHORT;\n        case SG_VERTEXFORMAT_USHORT2N:\n        case SG_VERTEXFORMAT_USHORT4N:\n            return GL_UNSIGNED_SHORT;\n        case SG_VERTEXFORMAT_UINT10_N2:\n            return GL_UNSIGNED_INT_2_10_10_10_REV;\n        case SG_VERTEXFORMAT_HALF2:\n        case SG_VERTEXFORMAT_HALF4:\n            return GL_HALF_FLOAT;\n        default:\n            SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLboolean _sg_gl_vertexformat_normalized(sg_vertex_format fmt) {\n    switch (fmt) {\n        case SG_VERTEXFORMAT_BYTE4N:\n        case SG_VERTEXFORMAT_UBYTE4N:\n        case SG_VERTEXFORMAT_SHORT2N:\n        case SG_VERTEXFORMAT_USHORT2N:\n        case SG_VERTEXFORMAT_SHORT4N:\n        case SG_VERTEXFORMAT_USHORT4N:\n        case SG_VERTEXFORMAT_UINT10_N2:\n            return GL_TRUE;\n        default:\n            return GL_FALSE;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_primitive_type(sg_primitive_type t) {\n    switch (t) {\n        case SG_PRIMITIVETYPE_POINTS:           return GL_POINTS;\n        case SG_PRIMITIVETYPE_LINES:            return GL_LINES;\n        case SG_PRIMITIVETYPE_LINE_STRIP:       return GL_LINE_STRIP;\n        case SG_PRIMITIVETYPE_TRIANGLES:        return GL_TRIANGLES;\n        case SG_PRIMITIVETYPE_TRIANGLE_STRIP:   return GL_TRIANGLE_STRIP;\n        default: SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_index_type(sg_index_type t) {\n    switch (t) {\n        case SG_INDEXTYPE_NONE:     return 0;\n        case SG_INDEXTYPE_UINT16:   return GL_UNSIGNED_SHORT;\n        case SG_INDEXTYPE_UINT32:   return GL_UNSIGNED_INT;\n        default: SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_compare_func(sg_compare_func cmp) {\n    switch (cmp) {\n        case SG_COMPAREFUNC_NEVER:          return GL_NEVER;\n        case SG_COMPAREFUNC_LESS:           return GL_LESS;\n        case SG_COMPAREFUNC_EQUAL:          return GL_EQUAL;\n        case SG_COMPAREFUNC_LESS_EQUAL:     return GL_LEQUAL;\n        case SG_COMPAREFUNC_GREATER:        return GL_GREATER;\n        case SG_COMPAREFUNC_NOT_EQUAL:      return GL_NOTEQUAL;\n        case SG_COMPAREFUNC_GREATER_EQUAL:  return GL_GEQUAL;\n        case SG_COMPAREFUNC_ALWAYS:         return GL_ALWAYS;\n        default: SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_stencil_op(sg_stencil_op op) {\n    switch (op) {\n        case SG_STENCILOP_KEEP:         return GL_KEEP;\n        case SG_STENCILOP_ZERO:         return GL_ZERO;\n        case SG_STENCILOP_REPLACE:      return GL_REPLACE;\n        case SG_STENCILOP_INCR_CLAMP:   return GL_INCR;\n        case SG_STENCILOP_DECR_CLAMP:   return GL_DECR;\n        case SG_STENCILOP_INVERT:       return GL_INVERT;\n        case SG_STENCILOP_INCR_WRAP:    return GL_INCR_WRAP;\n        case SG_STENCILOP_DECR_WRAP:    return GL_DECR_WRAP;\n        default: SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_blend_factor(sg_blend_factor f) {\n    switch (f) {\n        case SG_BLENDFACTOR_ZERO:                   return GL_ZERO;\n        case SG_BLENDFACTOR_ONE:                    return GL_ONE;\n        case SG_BLENDFACTOR_SRC_COLOR:              return GL_SRC_COLOR;\n        case SG_BLENDFACTOR_ONE_MINUS_SRC_COLOR:    return GL_ONE_MINUS_SRC_COLOR;\n        case SG_BLENDFACTOR_SRC_ALPHA:              return GL_SRC_ALPHA;\n        case SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:    return GL_ONE_MINUS_SRC_ALPHA;\n        case SG_BLENDFACTOR_DST_COLOR:              return GL_DST_COLOR;\n        case SG_BLENDFACTOR_ONE_MINUS_DST_COLOR:    return GL_ONE_MINUS_DST_COLOR;\n        case SG_BLENDFACTOR_DST_ALPHA:              return GL_DST_ALPHA;\n        case SG_BLENDFACTOR_ONE_MINUS_DST_ALPHA:    return GL_ONE_MINUS_DST_ALPHA;\n        case SG_BLENDFACTOR_SRC_ALPHA_SATURATED:    return GL_SRC_ALPHA_SATURATE;\n        case SG_BLENDFACTOR_BLEND_COLOR:            return GL_CONSTANT_COLOR;\n        case SG_BLENDFACTOR_ONE_MINUS_BLEND_COLOR:  return GL_ONE_MINUS_CONSTANT_COLOR;\n        case SG_BLENDFACTOR_BLEND_ALPHA:            return GL_CONSTANT_ALPHA;\n        case SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA:  return GL_ONE_MINUS_CONSTANT_ALPHA;\n        default: SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_blend_op(sg_blend_op op) {\n    switch (op) {\n        case SG_BLENDOP_ADD:                return GL_FUNC_ADD;\n        case SG_BLENDOP_SUBTRACT:           return GL_FUNC_SUBTRACT;\n        case SG_BLENDOP_REVERSE_SUBTRACT:   return GL_FUNC_REVERSE_SUBTRACT;\n        default: SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_min_filter(sg_filter min_f, sg_filter mipmap_f) {\n    if (min_f == SG_FILTER_NEAREST) {\n        switch (mipmap_f) {\n            case SG_FILTER_NONE:    return GL_NEAREST;\n            case SG_FILTER_NEAREST: return GL_NEAREST_MIPMAP_NEAREST;\n            case SG_FILTER_LINEAR:  return GL_NEAREST_MIPMAP_LINEAR;\n            default: SOKOL_UNREACHABLE; return (GLenum)0;\n        }\n    } else if (min_f == SG_FILTER_LINEAR) {\n        switch (mipmap_f) {\n            case SG_FILTER_NONE:    return GL_LINEAR;\n            case SG_FILTER_NEAREST: return GL_LINEAR_MIPMAP_NEAREST;\n            case SG_FILTER_LINEAR:  return GL_LINEAR_MIPMAP_LINEAR;\n            default: SOKOL_UNREACHABLE; return (GLenum)0;\n        }\n    } else {\n        SOKOL_UNREACHABLE; return (GLenum)0;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_mag_filter(sg_filter mag_f) {\n    if (mag_f == SG_FILTER_NEAREST) {\n        return GL_NEAREST;\n    } else {\n        return GL_LINEAR;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_wrap(sg_wrap w) {\n    switch (w) {\n        case SG_WRAP_CLAMP_TO_EDGE:     return GL_CLAMP_TO_EDGE;\n        #if defined(SOKOL_GLCORE)\n        case SG_WRAP_CLAMP_TO_BORDER:   return GL_CLAMP_TO_BORDER;\n        #else\n        case SG_WRAP_CLAMP_TO_BORDER:   return GL_CLAMP_TO_EDGE;\n        #endif\n        case SG_WRAP_REPEAT:            return GL_REPEAT;\n        case SG_WRAP_MIRRORED_REPEAT:   return GL_MIRRORED_REPEAT;\n        default: SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_teximage_type(sg_pixel_format fmt) {\n    switch (fmt) {\n        case SG_PIXELFORMAT_R8:\n        case SG_PIXELFORMAT_R8UI:\n        case SG_PIXELFORMAT_RG8:\n        case SG_PIXELFORMAT_RG8UI:\n        case SG_PIXELFORMAT_RGBA8:\n        case SG_PIXELFORMAT_SRGB8A8:\n        case SG_PIXELFORMAT_RGBA8UI:\n        case SG_PIXELFORMAT_BGRA8:\n            return GL_UNSIGNED_BYTE;\n        case SG_PIXELFORMAT_R8SN:\n        case SG_PIXELFORMAT_R8SI:\n        case SG_PIXELFORMAT_RG8SN:\n        case SG_PIXELFORMAT_RG8SI:\n        case SG_PIXELFORMAT_RGBA8SN:\n        case SG_PIXELFORMAT_RGBA8SI:\n            return GL_BYTE;\n        case SG_PIXELFORMAT_R16:\n        case SG_PIXELFORMAT_R16UI:\n        case SG_PIXELFORMAT_RG16:\n        case SG_PIXELFORMAT_RG16UI:\n        case SG_PIXELFORMAT_RGBA16:\n        case SG_PIXELFORMAT_RGBA16UI:\n            return GL_UNSIGNED_SHORT;\n        case SG_PIXELFORMAT_R16SN:\n        case SG_PIXELFORMAT_R16SI:\n        case SG_PIXELFORMAT_RG16SN:\n        case SG_PIXELFORMAT_RG16SI:\n        case SG_PIXELFORMAT_RGBA16SN:\n        case SG_PIXELFORMAT_RGBA16SI:\n            return GL_SHORT;\n        case SG_PIXELFORMAT_R16F:\n        case SG_PIXELFORMAT_RG16F:\n        case SG_PIXELFORMAT_RGBA16F:\n            return GL_HALF_FLOAT;\n        case SG_PIXELFORMAT_R32UI:\n        case SG_PIXELFORMAT_RG32UI:\n        case SG_PIXELFORMAT_RGBA32UI:\n            return GL_UNSIGNED_INT;\n        case SG_PIXELFORMAT_R32SI:\n        case SG_PIXELFORMAT_RG32SI:\n        case SG_PIXELFORMAT_RGBA32SI:\n            return GL_INT;\n        case SG_PIXELFORMAT_R32F:\n        case SG_PIXELFORMAT_RG32F:\n        case SG_PIXELFORMAT_RGBA32F:\n            return GL_FLOAT;\n        case SG_PIXELFORMAT_RGB10A2:\n            return GL_UNSIGNED_INT_2_10_10_10_REV;\n        case SG_PIXELFORMAT_RG11B10F:\n            return GL_UNSIGNED_INT_10F_11F_11F_REV;\n        case SG_PIXELFORMAT_RGB9E5:\n            return GL_UNSIGNED_INT_5_9_9_9_REV;\n        case SG_PIXELFORMAT_DEPTH:\n            return GL_FLOAT;\n        case SG_PIXELFORMAT_DEPTH_STENCIL:\n            return GL_UNSIGNED_INT_24_8;\n        default:\n            SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_teximage_format(sg_pixel_format fmt) {\n    switch (fmt) {\n        case SG_PIXELFORMAT_R8:\n        case SG_PIXELFORMAT_R8SN:\n        case SG_PIXELFORMAT_R16:\n        case SG_PIXELFORMAT_R16SN:\n        case SG_PIXELFORMAT_R16F:\n        case SG_PIXELFORMAT_R32F:\n            return GL_RED;\n        case SG_PIXELFORMAT_R8UI:\n        case SG_PIXELFORMAT_R8SI:\n        case SG_PIXELFORMAT_R16UI:\n        case SG_PIXELFORMAT_R16SI:\n        case SG_PIXELFORMAT_R32UI:\n        case SG_PIXELFORMAT_R32SI:\n            return GL_RED_INTEGER;\n        case SG_PIXELFORMAT_RG8:\n        case SG_PIXELFORMAT_RG8SN:\n        case SG_PIXELFORMAT_RG16:\n        case SG_PIXELFORMAT_RG16SN:\n        case SG_PIXELFORMAT_RG16F:\n        case SG_PIXELFORMAT_RG32F:\n            return GL_RG;\n        case SG_PIXELFORMAT_RG8UI:\n        case SG_PIXELFORMAT_RG8SI:\n        case SG_PIXELFORMAT_RG16UI:\n        case SG_PIXELFORMAT_RG16SI:\n        case SG_PIXELFORMAT_RG32UI:\n        case SG_PIXELFORMAT_RG32SI:\n            return GL_RG_INTEGER;\n        case SG_PIXELFORMAT_RGBA8:\n        case SG_PIXELFORMAT_SRGB8A8:\n        case SG_PIXELFORMAT_RGBA8SN:\n        case SG_PIXELFORMAT_RGBA16:\n        case SG_PIXELFORMAT_RGBA16SN:\n        case SG_PIXELFORMAT_RGBA16F:\n        case SG_PIXELFORMAT_RGBA32F:\n        case SG_PIXELFORMAT_RGB10A2:\n            return GL_RGBA;\n        case SG_PIXELFORMAT_RGBA8UI:\n        case SG_PIXELFORMAT_RGBA8SI:\n        case SG_PIXELFORMAT_RGBA16UI:\n        case SG_PIXELFORMAT_RGBA16SI:\n        case SG_PIXELFORMAT_RGBA32UI:\n        case SG_PIXELFORMAT_RGBA32SI:\n            return GL_RGBA_INTEGER;\n        case SG_PIXELFORMAT_RG11B10F:\n        case SG_PIXELFORMAT_RGB9E5:\n            return GL_RGB;\n        case SG_PIXELFORMAT_DEPTH:\n            return GL_DEPTH_COMPONENT;\n        case SG_PIXELFORMAT_DEPTH_STENCIL:\n            return GL_DEPTH_STENCIL;\n        case SG_PIXELFORMAT_BC1_RGBA:\n            return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;\n        case SG_PIXELFORMAT_BC2_RGBA:\n            return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;\n        case SG_PIXELFORMAT_BC3_RGBA:\n            return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;\n        case SG_PIXELFORMAT_BC3_SRGBA:\n            return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;\n        case SG_PIXELFORMAT_BC4_R:\n            return GL_COMPRESSED_RED_RGTC1;\n        case SG_PIXELFORMAT_BC4_RSN:\n            return GL_COMPRESSED_SIGNED_RED_RGTC1;\n        case SG_PIXELFORMAT_BC5_RG:\n            return GL_COMPRESSED_RED_GREEN_RGTC2;\n        case SG_PIXELFORMAT_BC5_RGSN:\n            return GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2;\n        case SG_PIXELFORMAT_BC6H_RGBF:\n            return GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB;\n        case SG_PIXELFORMAT_BC6H_RGBUF:\n            return GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB;\n        case SG_PIXELFORMAT_BC7_RGBA:\n            return GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;\n        case SG_PIXELFORMAT_BC7_SRGBA:\n            return GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB;\n        case SG_PIXELFORMAT_PVRTC_RGB_2BPP:\n            return GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;\n        case SG_PIXELFORMAT_PVRTC_RGB_4BPP:\n            return GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;\n        case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:\n            return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;\n        case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:\n            return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;\n        case SG_PIXELFORMAT_ETC2_RGB8:\n            return GL_COMPRESSED_RGB8_ETC2;\n        case SG_PIXELFORMAT_ETC2_SRGB8:\n            return GL_COMPRESSED_SRGB8_ETC2;\n        case SG_PIXELFORMAT_ETC2_RGB8A1:\n            return GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;\n        case SG_PIXELFORMAT_ETC2_RGBA8:\n            return GL_COMPRESSED_RGBA8_ETC2_EAC;\n        case SG_PIXELFORMAT_ETC2_SRGB8A8:\n            return GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;\n        case SG_PIXELFORMAT_EAC_R11:\n            return GL_COMPRESSED_R11_EAC;\n        case SG_PIXELFORMAT_EAC_R11SN:\n            return GL_COMPRESSED_SIGNED_R11_EAC;\n        case SG_PIXELFORMAT_EAC_RG11:\n            return GL_COMPRESSED_RG11_EAC;\n        case SG_PIXELFORMAT_EAC_RG11SN:\n            return GL_COMPRESSED_SIGNED_RG11_EAC;\n        case SG_PIXELFORMAT_ASTC_4x4_RGBA:\n            return GL_COMPRESSED_RGBA_ASTC_4x4_KHR;\n        case SG_PIXELFORMAT_ASTC_4x4_SRGBA:\n            return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR;\n        default:\n            SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_teximage_internal_format(sg_pixel_format fmt) {\n    switch (fmt) {\n        case SG_PIXELFORMAT_R8:         return GL_R8;\n        case SG_PIXELFORMAT_R8SN:       return GL_R8_SNORM;\n        case SG_PIXELFORMAT_R8UI:       return GL_R8UI;\n        case SG_PIXELFORMAT_R8SI:       return GL_R8I;\n        #if !defined(SOKOL_GLES3)\n            case SG_PIXELFORMAT_R16:        return GL_R16;\n            case SG_PIXELFORMAT_R16SN:      return GL_R16_SNORM;\n        #endif\n        case SG_PIXELFORMAT_R16UI:      return GL_R16UI;\n        case SG_PIXELFORMAT_R16SI:      return GL_R16I;\n        case SG_PIXELFORMAT_R16F:       return GL_R16F;\n        case SG_PIXELFORMAT_RG8:        return GL_RG8;\n        case SG_PIXELFORMAT_RG8SN:      return GL_RG8_SNORM;\n        case SG_PIXELFORMAT_RG8UI:      return GL_RG8UI;\n        case SG_PIXELFORMAT_RG8SI:      return GL_RG8I;\n        case SG_PIXELFORMAT_R32UI:      return GL_R32UI;\n        case SG_PIXELFORMAT_R32SI:      return GL_R32I;\n        case SG_PIXELFORMAT_R32F:       return GL_R32F;\n        #if !defined(SOKOL_GLES3)\n            case SG_PIXELFORMAT_RG16:       return GL_RG16;\n            case SG_PIXELFORMAT_RG16SN:     return GL_RG16_SNORM;\n        #endif\n        case SG_PIXELFORMAT_RG16UI:     return GL_RG16UI;\n        case SG_PIXELFORMAT_RG16SI:     return GL_RG16I;\n        case SG_PIXELFORMAT_RG16F:      return GL_RG16F;\n        case SG_PIXELFORMAT_RGBA8:      return GL_RGBA8;\n        case SG_PIXELFORMAT_SRGB8A8:    return GL_SRGB8_ALPHA8;\n        case SG_PIXELFORMAT_RGBA8SN:    return GL_RGBA8_SNORM;\n        case SG_PIXELFORMAT_RGBA8UI:    return GL_RGBA8UI;\n        case SG_PIXELFORMAT_RGBA8SI:    return GL_RGBA8I;\n        case SG_PIXELFORMAT_RGB10A2:    return GL_RGB10_A2;\n        case SG_PIXELFORMAT_RG11B10F:   return GL_R11F_G11F_B10F;\n        case SG_PIXELFORMAT_RGB9E5:     return GL_RGB9_E5;\n        case SG_PIXELFORMAT_RG32UI:     return GL_RG32UI;\n        case SG_PIXELFORMAT_RG32SI:     return GL_RG32I;\n        case SG_PIXELFORMAT_RG32F:      return GL_RG32F;\n        #if !defined(SOKOL_GLES3)\n            case SG_PIXELFORMAT_RGBA16:     return GL_RGBA16;\n            case SG_PIXELFORMAT_RGBA16SN:   return GL_RGBA16_SNORM;\n        #endif\n        case SG_PIXELFORMAT_RGBA16UI:   return GL_RGBA16UI;\n        case SG_PIXELFORMAT_RGBA16SI:   return GL_RGBA16I;\n        case SG_PIXELFORMAT_RGBA16F:    return GL_RGBA16F;\n        case SG_PIXELFORMAT_RGBA32UI:   return GL_RGBA32UI;\n        case SG_PIXELFORMAT_RGBA32SI:   return GL_RGBA32I;\n        case SG_PIXELFORMAT_RGBA32F:    return GL_RGBA32F;\n        case SG_PIXELFORMAT_DEPTH:      return GL_DEPTH_COMPONENT32F;\n        case SG_PIXELFORMAT_DEPTH_STENCIL:      return GL_DEPTH24_STENCIL8;\n        case SG_PIXELFORMAT_BC1_RGBA:           return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;\n        case SG_PIXELFORMAT_BC2_RGBA:           return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;\n        case SG_PIXELFORMAT_BC3_RGBA:           return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;\n        case SG_PIXELFORMAT_BC3_SRGBA:          return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;\n        case SG_PIXELFORMAT_BC4_R:              return GL_COMPRESSED_RED_RGTC1;\n        case SG_PIXELFORMAT_BC4_RSN:            return GL_COMPRESSED_SIGNED_RED_RGTC1;\n        case SG_PIXELFORMAT_BC5_RG:             return GL_COMPRESSED_RED_GREEN_RGTC2;\n        case SG_PIXELFORMAT_BC5_RGSN:           return GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2;\n        case SG_PIXELFORMAT_BC6H_RGBF:          return GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB;\n        case SG_PIXELFORMAT_BC6H_RGBUF:         return GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB;\n        case SG_PIXELFORMAT_BC7_RGBA:           return GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;\n        case SG_PIXELFORMAT_BC7_SRGBA:          return GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB;\n        case SG_PIXELFORMAT_PVRTC_RGB_2BPP:     return GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;\n        case SG_PIXELFORMAT_PVRTC_RGB_4BPP:     return GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;\n        case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:    return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;\n        case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:    return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;\n        case SG_PIXELFORMAT_ETC2_RGB8:          return GL_COMPRESSED_RGB8_ETC2;\n        case SG_PIXELFORMAT_ETC2_SRGB8:         return GL_COMPRESSED_SRGB8_ETC2;\n        case SG_PIXELFORMAT_ETC2_RGB8A1:        return GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;\n        case SG_PIXELFORMAT_ETC2_RGBA8:         return GL_COMPRESSED_RGBA8_ETC2_EAC;\n        case SG_PIXELFORMAT_ETC2_SRGB8A8:       return GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;\n        case SG_PIXELFORMAT_EAC_R11:            return GL_COMPRESSED_R11_EAC;\n        case SG_PIXELFORMAT_EAC_R11SN:          return GL_COMPRESSED_SIGNED_R11_EAC;\n        case SG_PIXELFORMAT_EAC_RG11:           return GL_COMPRESSED_RG11_EAC;\n        case SG_PIXELFORMAT_EAC_RG11SN:         return GL_COMPRESSED_SIGNED_RG11_EAC;\n        case SG_PIXELFORMAT_ASTC_4x4_RGBA:      return GL_COMPRESSED_RGBA_ASTC_4x4_KHR;\n        case SG_PIXELFORMAT_ASTC_4x4_SRGBA:     return GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR;\n        default: SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_cubeface_target(int face_index) {\n    switch (face_index) {\n        case 0: return GL_TEXTURE_CUBE_MAP_POSITIVE_X;\n        case 1: return GL_TEXTURE_CUBE_MAP_NEGATIVE_X;\n        case 2: return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;\n        case 3: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;\n        case 4: return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;\n        case 5: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;\n        default: SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n// see: https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml\n_SOKOL_PRIVATE void _sg_gl_init_pixelformats(bool has_bgra) {\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R8]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_R8SN]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R8UI]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R8SI]);\n    #if !defined(SOKOL_GLES3)\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16]);\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16SN]);\n    #endif\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R16UI]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R16SI]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG8]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RG8SN]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG8UI]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG8SI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32UI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32SI]);\n    #if !defined(SOKOL_GLES3)\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16]);\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16SN]);\n    #endif\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG16UI]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG16SI]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA8]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_SRGB8A8]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RGBA8SN]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA8UI]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA8SI]);\n    if (has_bgra) {\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_BGRA8]);\n    }\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGB10A2]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RG11B10F]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RGB9E5]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG32UI]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG32SI]);\n    #if !defined(SOKOL_GLES3)\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16]);\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16SN]);\n    #endif\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA16UI]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA16SI]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA32UI]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA32SI]);\n    _sg_pixelformat_srmd(&_sg.formats[SG_PIXELFORMAT_DEPTH]);\n    _sg_pixelformat_srmd(&_sg.formats[SG_PIXELFORMAT_DEPTH_STENCIL]);\n}\n\n// FIXME: OES_half_float_blend\n_SOKOL_PRIVATE void _sg_gl_init_pixelformats_half_float(bool has_colorbuffer_half_float) {\n    if (has_colorbuffer_half_float) {\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16F]);\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16F]);\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16F]);\n    } else {\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_R16F]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RG16F]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RGBA16F]);\n    }\n}\n\n_SOKOL_PRIVATE void _sg_gl_init_pixelformats_float(bool has_colorbuffer_float, bool has_texture_float_linear, bool has_float_blend) {\n    if (has_texture_float_linear) {\n        if (has_colorbuffer_float) {\n            if (has_float_blend) {\n                _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R32F]);\n                _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG32F]);\n                _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);\n            } else {\n                _sg_pixelformat_sfrm(&_sg.formats[SG_PIXELFORMAT_R32F]);\n                _sg_pixelformat_sfrm(&_sg.formats[SG_PIXELFORMAT_RG32F]);\n                _sg_pixelformat_sfrm(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);\n            }\n        } else {\n            _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_R32F]);\n            _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RG32F]);\n            _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);\n        }\n    } else {\n        if (has_colorbuffer_float) {\n            _sg_pixelformat_sbrm(&_sg.formats[SG_PIXELFORMAT_R32F]);\n            _sg_pixelformat_sbrm(&_sg.formats[SG_PIXELFORMAT_RG32F]);\n            _sg_pixelformat_sbrm(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);\n        } else {\n            _sg_pixelformat_s(&_sg.formats[SG_PIXELFORMAT_R32F]);\n            _sg_pixelformat_s(&_sg.formats[SG_PIXELFORMAT_RG32F]);\n            _sg_pixelformat_s(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);\n        }\n    }\n}\n\n_SOKOL_PRIVATE void _sg_gl_init_pixelformats_s3tc(void) {\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC1_RGBA]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC2_RGBA]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC3_RGBA]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC3_SRGBA]);\n}\n\n_SOKOL_PRIVATE void _sg_gl_init_pixelformats_rgtc(void) {\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC4_R]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC4_RSN]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC5_RG]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC5_RGSN]);\n}\n\n_SOKOL_PRIVATE void _sg_gl_init_pixelformats_bptc(void) {\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC6H_RGBF]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC6H_RGBUF]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC7_RGBA]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC7_SRGBA]);\n}\n\n_SOKOL_PRIVATE void _sg_gl_init_pixelformats_pvrtc(void) {\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGB_2BPP]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGB_4BPP]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGBA_2BPP]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGBA_4BPP]);\n}\n\n_SOKOL_PRIVATE void _sg_gl_init_pixelformats_etc2(void) {\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGB8]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_SRGB8]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGB8A1]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGBA8]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_SRGB8A8]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_EAC_R11]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_EAC_R11SN]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_EAC_RG11]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_EAC_RG11SN]);\n}\n\n_SOKOL_PRIVATE void _sg_gl_init_pixelformats_astc(void) {\n     _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ASTC_4x4_RGBA]);\n     _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ASTC_4x4_SRGBA]);\n }\n\n_SOKOL_PRIVATE void _sg_gl_init_limits(void) {\n    _SG_GL_CHECK_ERROR();\n    GLint gl_int;\n    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_int);\n    _SG_GL_CHECK_ERROR();\n    _sg.limits.max_image_size_2d = gl_int;\n    _sg.limits.max_image_size_array = gl_int;\n    glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &gl_int);\n    _SG_GL_CHECK_ERROR();\n    _sg.limits.max_image_size_cube = gl_int;\n    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &gl_int);\n    _SG_GL_CHECK_ERROR();\n    if (gl_int > SG_MAX_VERTEX_ATTRIBUTES) {\n        gl_int = SG_MAX_VERTEX_ATTRIBUTES;\n    }\n    _sg.limits.max_vertex_attrs = gl_int;\n    glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &gl_int);\n    _SG_GL_CHECK_ERROR();\n    _sg.limits.gl_max_vertex_uniform_components = gl_int;\n    glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &gl_int);\n    _SG_GL_CHECK_ERROR();\n    _sg.limits.max_image_size_3d = gl_int;\n    glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &gl_int);\n    _SG_GL_CHECK_ERROR();\n    _sg.limits.max_image_array_layers = gl_int;\n    if (_sg.gl.ext_anisotropic) {\n        glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_int);\n        _SG_GL_CHECK_ERROR();\n        _sg.gl.max_anisotropy = gl_int;\n    } else {\n        _sg.gl.max_anisotropy = 1;\n    }\n    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &gl_int);\n    _SG_GL_CHECK_ERROR();\n    _sg.limits.gl_max_combined_texture_image_units = gl_int;\n}\n\n#if defined(SOKOL_GLCORE)\n_SOKOL_PRIVATE void _sg_gl_init_caps_glcore(void) {\n    _sg.backend = SG_BACKEND_GLCORE;\n\n    GLint major_version = 0;\n    GLint minor_version = 0;\n    glGetIntegerv(GL_MAJOR_VERSION, &major_version);\n    glGetIntegerv(GL_MINOR_VERSION, &minor_version);\n    const int version = major_version * 100 + minor_version * 10;\n    _sg.features.origin_top_left = false;\n    _sg.features.image_clamp_to_border = true;\n    _sg.features.mrt_independent_blend_state = false;\n    _sg.features.mrt_independent_write_mask = true;\n    _sg.features.storage_buffer = version >= 430;\n\n    // scan extensions\n    bool has_s3tc = false;  // BC1..BC3\n    bool has_rgtc = false;  // BC4 and BC5\n    bool has_bptc = false;  // BC6H and BC7\n    bool has_pvrtc = false;\n    bool has_etc2 = false;\n    bool has_astc = false;\n    GLint num_ext = 0;\n    glGetIntegerv(GL_NUM_EXTENSIONS, &num_ext);\n    for (int i = 0; i < num_ext; i++) {\n        const char* ext = (const char*) glGetStringi(GL_EXTENSIONS, (GLuint)i);\n        if (ext) {\n            if (strstr(ext, \"_texture_compression_s3tc\")) {\n                has_s3tc = true;\n            } else if (strstr(ext, \"_texture_compression_rgtc\")) {\n                has_rgtc = true;\n            } else if (strstr(ext, \"_texture_compression_bptc\")) {\n                has_bptc = true;\n            } else if (strstr(ext, \"_texture_compression_pvrtc\")) {\n                has_pvrtc = true;\n            } else if (strstr(ext, \"_ES3_compatibility\")) {\n                has_etc2 = true;\n            } else if (strstr(ext, \"_texture_filter_anisotropic\")) {\n                _sg.gl.ext_anisotropic = true;\n            } else if (strstr(ext, \"_texture_compression_astc_ldr\")) {\n                has_astc = true;\n            }\n        }\n    }\n\n    // limits\n    _sg_gl_init_limits();\n\n    // pixel formats\n    const bool has_bgra = false;    // not a bug\n    const bool has_colorbuffer_float = true;\n    const bool has_colorbuffer_half_float = true;\n    const bool has_texture_float_linear = true; // FIXME???\n    const bool has_float_blend = true;\n    _sg_gl_init_pixelformats(has_bgra);\n    _sg_gl_init_pixelformats_float(has_colorbuffer_float, has_texture_float_linear, has_float_blend);\n    _sg_gl_init_pixelformats_half_float(has_colorbuffer_half_float);\n    if (has_s3tc) {\n        _sg_gl_init_pixelformats_s3tc();\n    }\n    if (has_rgtc) {\n        _sg_gl_init_pixelformats_rgtc();\n    }\n    if (has_bptc) {\n        _sg_gl_init_pixelformats_bptc();\n    }\n    if (has_pvrtc) {\n        _sg_gl_init_pixelformats_pvrtc();\n    }\n    if (has_etc2) {\n        _sg_gl_init_pixelformats_etc2();\n    }\n    if (has_astc) {\n        _sg_gl_init_pixelformats_astc();\n    }\n}\n#endif\n\n#if defined(SOKOL_GLES3)\n_SOKOL_PRIVATE void _sg_gl_init_caps_gles3(void) {\n    _sg.backend = SG_BACKEND_GLES3;\n\n    _sg.features.origin_top_left = false;\n    _sg.features.image_clamp_to_border = false;\n    _sg.features.mrt_independent_blend_state = false;\n    _sg.features.mrt_independent_write_mask = false;\n    _sg.features.storage_buffer = false;\n\n    bool has_s3tc = false;  // BC1..BC3\n    bool has_rgtc = false;  // BC4 and BC5\n    bool has_bptc = false;  // BC6H and BC7\n    bool has_pvrtc = false;\n    #if defined(__EMSCRIPTEN__)\n        bool has_etc2 = false;\n    #else\n        bool has_etc2 = true;\n    #endif\n    bool has_astc = false;\n    bool has_colorbuffer_float = false;\n    bool has_colorbuffer_half_float = false;\n    bool has_texture_float_linear = false;\n    bool has_float_blend = false;\n    GLint num_ext = 0;\n    glGetIntegerv(GL_NUM_EXTENSIONS, &num_ext);\n    for (int i = 0; i < num_ext; i++) {\n        const char* ext = (const char*) glGetStringi(GL_EXTENSIONS, (GLuint)i);\n        if (ext) {\n            if (strstr(ext, \"_texture_compression_s3tc\")) {\n                has_s3tc = true;\n            } else if (strstr(ext, \"_compressed_texture_s3tc\")) {\n                has_s3tc = true;\n            } else if (strstr(ext, \"_texture_compression_rgtc\")) {\n                has_rgtc = true;\n            } else if (strstr(ext, \"_texture_compression_bptc\")) {\n                has_bptc = true;\n            } else if (strstr(ext, \"_texture_compression_pvrtc\")) {\n                has_pvrtc = true;\n            } else if (strstr(ext, \"_compressed_texture_pvrtc\")) {\n                has_pvrtc = true;\n            } else if (strstr(ext, \"_compressed_texture_etc\")) {\n                has_etc2 = true;\n            } else if (strstr(ext, \"_compressed_texture_astc\")) {\n                has_astc = true;\n            } else if (strstr(ext, \"_color_buffer_float\")) {\n                has_colorbuffer_float = true;\n            } else if (strstr(ext, \"_color_buffer_half_float\")) {\n                has_colorbuffer_half_float = true;\n            } else if (strstr(ext, \"_texture_float_linear\")) {\n                has_texture_float_linear = true;\n            } else if (strstr(ext, \"_float_blend\")) {\n                has_float_blend = true;\n            } else if (strstr(ext, \"_texture_filter_anisotropic\")) {\n                _sg.gl.ext_anisotropic = true;\n            }\n        }\n    }\n\n    /* on WebGL2, color_buffer_float also includes 16-bit formats\n       see: https://developer.mozilla.org/en-US/docs/Web/API/EXT_color_buffer_float\n    */\n    #if defined(__EMSCRIPTEN__)\n    if (!has_colorbuffer_half_float && has_colorbuffer_float) {\n        has_colorbuffer_half_float = has_colorbuffer_float;\n    }\n    #endif\n\n    // limits\n    _sg_gl_init_limits();\n\n    // pixel formats\n    const bool has_bgra = false;    // not a bug\n    _sg_gl_init_pixelformats(has_bgra);\n    _sg_gl_init_pixelformats_float(has_colorbuffer_float, has_texture_float_linear, has_float_blend);\n    _sg_gl_init_pixelformats_half_float(has_colorbuffer_half_float);\n    if (has_s3tc) {\n        _sg_gl_init_pixelformats_s3tc();\n    }\n    if (has_rgtc) {\n        _sg_gl_init_pixelformats_rgtc();\n    }\n    if (has_bptc) {\n        _sg_gl_init_pixelformats_bptc();\n    }\n    if (has_pvrtc) {\n        _sg_gl_init_pixelformats_pvrtc();\n    }\n    if (has_etc2) {\n        _sg_gl_init_pixelformats_etc2();\n    }\n    if (has_astc) {\n        _sg_gl_init_pixelformats_astc();\n    }\n}\n#endif\n\n//-- state cache implementation ------------------------------------------------\n_SOKOL_PRIVATE GLuint _sg_gl_storagebuffer_bind_index(int stage, int slot) {\n    SOKOL_ASSERT((stage >= 0) && (stage < SG_NUM_SHADER_STAGES));\n    SOKOL_ASSERT((slot >= 0) && (slot < SG_MAX_SHADERSTAGE_STORAGEBUFFERS));\n    return (GLuint) (stage * _SG_GL_STORAGEBUFFER_STAGE_INDEX_PITCH + slot);\n}\n\n_SOKOL_PRIVATE void _sg_gl_cache_clear_buffer_bindings(bool force) {\n    if (force || (_sg.gl.cache.vertex_buffer != 0)) {\n        glBindBuffer(GL_ARRAY_BUFFER, 0);\n        _sg.gl.cache.vertex_buffer = 0;\n        _sg_stats_add(gl.num_bind_buffer, 1);\n    }\n    if (force || (_sg.gl.cache.index_buffer != 0)) {\n        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);\n        _sg.gl.cache.index_buffer = 0;\n        _sg_stats_add(gl.num_bind_buffer, 1);\n    }\n    if (force || (_sg.gl.cache.storage_buffer != 0)) {\n        if (_sg.features.storage_buffer) {\n            glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);\n        }\n        _sg.gl.cache.storage_buffer = 0;\n        _sg_stats_add(gl.num_bind_buffer, 1);\n    }\n    for (int stage = 0; stage < SG_NUM_SHADER_STAGES; stage++) {\n        for (int i = 0; i < SG_MAX_SHADERSTAGE_STORAGEBUFFERS; i++) {\n            if (force || (_sg.gl.cache.stage_storage_buffers[stage][i] != 0)) {\n                const GLuint bind_index = _sg_gl_storagebuffer_bind_index(stage, i);\n                if (_sg.features.storage_buffer) {\n                    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, bind_index, 0);\n                }\n                _sg.gl.cache.stage_storage_buffers[stage][i] = 0;\n                _sg_stats_add(gl.num_bind_buffer, 1);\n            }\n        }\n    }\n}\n\n_SOKOL_PRIVATE void _sg_gl_cache_bind_buffer(GLenum target, GLuint buffer) {\n    SOKOL_ASSERT((GL_ARRAY_BUFFER == target) || (GL_ELEMENT_ARRAY_BUFFER == target) || (GL_SHADER_STORAGE_BUFFER == target));\n    if (target == GL_ARRAY_BUFFER) {\n        if (_sg.gl.cache.vertex_buffer != buffer) {\n            _sg.gl.cache.vertex_buffer = buffer;\n            glBindBuffer(target, buffer);\n            _sg_stats_add(gl.num_bind_buffer, 1);\n        }\n    } else if (target == GL_ELEMENT_ARRAY_BUFFER) {\n        if (_sg.gl.cache.index_buffer != buffer) {\n            _sg.gl.cache.index_buffer = buffer;\n            glBindBuffer(target, buffer);\n            _sg_stats_add(gl.num_bind_buffer, 1);\n        }\n    } else if (target == GL_SHADER_STORAGE_BUFFER) {\n        if (_sg.gl.cache.storage_buffer != buffer) {\n            _sg.gl.cache.storage_buffer = buffer;\n            if (_sg.features.storage_buffer) {\n                glBindBuffer(target, buffer);\n            }\n            _sg_stats_add(gl.num_bind_buffer, 1);\n        }\n    } else {\n        SOKOL_UNREACHABLE;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_gl_cache_bind_storage_buffer(int stage, int slot, GLuint buffer) {\n    SOKOL_ASSERT((stage >= 0) && (stage < SG_NUM_SHADER_STAGES));\n    SOKOL_ASSERT((slot >= 0) && (slot < SG_MAX_SHADERSTAGE_STORAGEBUFFERS));\n    if (_sg.gl.cache.stage_storage_buffers[stage][slot] != buffer) {\n        _sg.gl.cache.stage_storage_buffers[stage][slot] = buffer;\n        _sg.gl.cache.storage_buffer = buffer; // not a bug\n        GLuint bind_index = _sg_gl_storagebuffer_bind_index(stage, slot);\n        if (_sg.features.storage_buffer) {\n            glBindBufferBase(GL_SHADER_STORAGE_BUFFER, bind_index, buffer);\n        }\n        _sg_stats_add(gl.num_bind_buffer, 1);\n    }\n}\n\n_SOKOL_PRIVATE void _sg_gl_cache_store_buffer_binding(GLenum target) {\n    if (target == GL_ARRAY_BUFFER) {\n        _sg.gl.cache.stored_vertex_buffer = _sg.gl.cache.vertex_buffer;\n    } else if (target == GL_ELEMENT_ARRAY_BUFFER) {\n        _sg.gl.cache.stored_index_buffer = _sg.gl.cache.index_buffer;\n    } else if (target == GL_SHADER_STORAGE_BUFFER) {\n        _sg.gl.cache.stored_storage_buffer = _sg.gl.cache.storage_buffer;\n    } else {\n        SOKOL_UNREACHABLE;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_gl_cache_restore_buffer_binding(GLenum target) {\n    if (target == GL_ARRAY_BUFFER) {\n        if (_sg.gl.cache.stored_vertex_buffer != 0) {\n            // we only care about restoring valid ids\n            _sg_gl_cache_bind_buffer(target, _sg.gl.cache.stored_vertex_buffer);\n            _sg.gl.cache.stored_vertex_buffer = 0;\n        }\n    } else if (target == GL_ELEMENT_ARRAY_BUFFER) {\n        if (_sg.gl.cache.stored_index_buffer != 0) {\n            // we only care about restoring valid ids\n            _sg_gl_cache_bind_buffer(target, _sg.gl.cache.stored_index_buffer);\n            _sg.gl.cache.stored_index_buffer = 0;\n        }\n    } else if (target == GL_SHADER_STORAGE_BUFFER) {\n        if (_sg.gl.cache.stored_storage_buffer != 0) {\n            // we only care about restoring valid ids\n            _sg_gl_cache_bind_buffer(target, _sg.gl.cache.stored_storage_buffer);\n            _sg.gl.cache.stored_storage_buffer = 0;\n        }\n    } else {\n        SOKOL_UNREACHABLE;\n    }\n}\n\n// called when _sg_gl_discard_buffer()\n_SOKOL_PRIVATE void _sg_gl_cache_invalidate_buffer(GLuint buf) {\n    if (buf == _sg.gl.cache.vertex_buffer) {\n        _sg.gl.cache.vertex_buffer = 0;\n        glBindBuffer(GL_ARRAY_BUFFER, 0);\n        _sg_stats_add(gl.num_bind_buffer, 1);\n    }\n    if (buf == _sg.gl.cache.index_buffer) {\n        _sg.gl.cache.index_buffer = 0;\n        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);\n        _sg_stats_add(gl.num_bind_buffer, 1);\n    }\n    if (buf == _sg.gl.cache.storage_buffer) {\n        _sg.gl.cache.storage_buffer = 0;\n        glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);\n        _sg_stats_add(gl.num_bind_buffer, 1);\n    }\n    for (int stage = 0; stage < SG_NUM_SHADER_STAGES; stage++) {\n        for (int i = 0; i < SG_MAX_SHADERSTAGE_STORAGEBUFFERS; i++) {\n            if (buf == _sg.gl.cache.stage_storage_buffers[stage][i]) {\n                _sg.gl.cache.stage_storage_buffers[stage][i] = 0;\n                _sg.gl.cache.storage_buffer = 0; // not a bug!\n                const GLuint bind_index = _sg_gl_storagebuffer_bind_index(stage, i);\n                glBindBufferBase(GL_SHADER_STORAGE_BUFFER, bind_index, 0);\n                _sg_stats_add(gl.num_bind_buffer, 1);\n            }\n        }\n    }\n    if (buf == _sg.gl.cache.stored_vertex_buffer) {\n        _sg.gl.cache.stored_vertex_buffer = 0;\n    }\n    if (buf == _sg.gl.cache.stored_index_buffer) {\n        _sg.gl.cache.stored_index_buffer = 0;\n    }\n    if (buf == _sg.gl.cache.stored_storage_buffer) {\n        _sg.gl.cache.stored_storage_buffer = 0;\n    }\n    for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {\n        if (buf == _sg.gl.cache.attrs[i].gl_vbuf) {\n            _sg.gl.cache.attrs[i].gl_vbuf = 0;\n        }\n    }\n}\n\n_SOKOL_PRIVATE void _sg_gl_cache_active_texture(GLenum texture) {\n    _SG_GL_CHECK_ERROR();\n    if (_sg.gl.cache.cur_active_texture != texture) {\n        _sg.gl.cache.cur_active_texture = texture;\n        glActiveTexture(texture);\n        _sg_stats_add(gl.num_active_texture, 1);\n    }\n    _SG_GL_CHECK_ERROR();\n}\n\n_SOKOL_PRIVATE void _sg_gl_cache_clear_texture_sampler_bindings(bool force) {\n    _SG_GL_CHECK_ERROR();\n    for (int i = 0; (i < _SG_GL_TEXTURE_SAMPLER_CACHE_SIZE) && (i < _sg.limits.gl_max_combined_texture_image_units); i++) {\n        if (force || (_sg.gl.cache.texture_samplers[i].texture != 0)) {\n            GLenum gl_texture_unit = (GLenum) (GL_TEXTURE0 + i);\n            glActiveTexture(gl_texture_unit);\n            _sg_stats_add(gl.num_active_texture, 1);\n            glBindTexture(GL_TEXTURE_2D, 0);\n            glBindTexture(GL_TEXTURE_CUBE_MAP, 0);\n            glBindTexture(GL_TEXTURE_3D, 0);\n            glBindTexture(GL_TEXTURE_2D_ARRAY, 0);\n            _sg_stats_add(gl.num_bind_texture, 4);\n            glBindSampler((GLuint)i, 0);\n            _sg_stats_add(gl.num_bind_sampler, 1);\n            _sg.gl.cache.texture_samplers[i].target = 0;\n            _sg.gl.cache.texture_samplers[i].texture = 0;\n            _sg.gl.cache.texture_samplers[i].sampler = 0;\n            _sg.gl.cache.cur_active_texture = gl_texture_unit;\n        }\n    }\n    _SG_GL_CHECK_ERROR();\n}\n\n_SOKOL_PRIVATE void _sg_gl_cache_bind_texture_sampler(int slot_index, GLenum target, GLuint texture, GLuint sampler) {\n    /* it's valid to call this function with target=0 and/or texture=0\n       target=0 will unbind the previous binding, texture=0 will clear\n       the new binding\n    */\n    SOKOL_ASSERT((slot_index >= 0) && (slot_index < _SG_GL_TEXTURE_SAMPLER_CACHE_SIZE));\n    if (slot_index >= _sg.limits.gl_max_combined_texture_image_units) {\n        return;\n    }\n    _SG_GL_CHECK_ERROR();\n    _sg_gl_cache_texture_sampler_bind_slot* slot = &_sg.gl.cache.texture_samplers[slot_index];\n    if ((slot->target != target) || (slot->texture != texture) || (slot->sampler != sampler)) {\n        _sg_gl_cache_active_texture((GLenum)(GL_TEXTURE0 + slot_index));\n        // if the target has changed, clear the previous binding on that target\n        if ((target != slot->target) && (slot->target != 0)) {\n            glBindTexture(slot->target, 0);\n            _SG_GL_CHECK_ERROR();\n            _sg_stats_add(gl.num_bind_texture, 1);\n        }\n        // apply new binding (can be 0 to unbind)\n        if (target != 0) {\n            glBindTexture(target, texture);\n            _SG_GL_CHECK_ERROR();\n            _sg_stats_add(gl.num_bind_texture, 1);\n        }\n        // apply new sampler (can be 0 to unbind)\n        glBindSampler((GLuint)slot_index, sampler);\n        _SG_GL_CHECK_ERROR();\n        _sg_stats_add(gl.num_bind_sampler, 1);\n\n        slot->target = target;\n        slot->texture = texture;\n        slot->sampler = sampler;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_gl_cache_store_texture_sampler_binding(int slot_index) {\n    SOKOL_ASSERT((slot_index >= 0) && (slot_index < _SG_GL_TEXTURE_SAMPLER_CACHE_SIZE));\n    _sg.gl.cache.stored_texture_sampler = _sg.gl.cache.texture_samplers[slot_index];\n}\n\n_SOKOL_PRIVATE void _sg_gl_cache_restore_texture_sampler_binding(int slot_index) {\n    SOKOL_ASSERT((slot_index >= 0) && (slot_index < _SG_GL_TEXTURE_SAMPLER_CACHE_SIZE));\n    _sg_gl_cache_texture_sampler_bind_slot* slot = &_sg.gl.cache.stored_texture_sampler;\n    if (slot->texture != 0) {\n        // we only care about restoring valid ids\n        SOKOL_ASSERT(slot->target != 0);\n        _sg_gl_cache_bind_texture_sampler(slot_index, slot->target, slot->texture, slot->sampler);\n        slot->target = 0;\n        slot->texture = 0;\n        slot->sampler = 0;\n    }\n}\n\n// called from _sg_gl_discard_texture() and _sg_gl_discard_sampler()\n_SOKOL_PRIVATE void _sg_gl_cache_invalidate_texture_sampler(GLuint tex, GLuint smp) {\n    _SG_GL_CHECK_ERROR();\n    for (int i = 0; i < _SG_GL_TEXTURE_SAMPLER_CACHE_SIZE; i++) {\n        _sg_gl_cache_texture_sampler_bind_slot* slot = &_sg.gl.cache.texture_samplers[i];\n        if ((0 != slot->target) && ((tex == slot->texture) || (smp == slot->sampler))) {\n            _sg_gl_cache_active_texture((GLenum)(GL_TEXTURE0 + i));\n            glBindTexture(slot->target, 0);\n            _SG_GL_CHECK_ERROR();\n            _sg_stats_add(gl.num_bind_texture, 1);\n            glBindSampler((GLuint)i, 0);\n            _SG_GL_CHECK_ERROR();\n            _sg_stats_add(gl.num_bind_sampler, 1);\n            slot->target = 0;\n            slot->texture = 0;\n            slot->sampler = 0;\n        }\n    }\n    if ((tex == _sg.gl.cache.stored_texture_sampler.texture) || (smp == _sg.gl.cache.stored_texture_sampler.sampler)) {\n        _sg.gl.cache.stored_texture_sampler.target = 0;\n        _sg.gl.cache.stored_texture_sampler.texture = 0;\n        _sg.gl.cache.stored_texture_sampler.sampler = 0;\n    }\n}\n\n// called from _sg_gl_discard_shader()\n_SOKOL_PRIVATE void _sg_gl_cache_invalidate_program(GLuint prog) {\n    if (prog == _sg.gl.cache.prog) {\n        _sg.gl.cache.prog = 0;\n        glUseProgram(0);\n        _sg_stats_add(gl.num_use_program, 1);\n    }\n}\n\n// called from _sg_gl_discard_pipeline()\n_SOKOL_PRIVATE void _sg_gl_cache_invalidate_pipeline(_sg_pipeline_t* pip) {\n    if (pip == _sg.gl.cache.cur_pipeline) {\n        _sg.gl.cache.cur_pipeline = 0;\n        _sg.gl.cache.cur_pipeline_id.id = SG_INVALID_ID;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_gl_reset_state_cache(void) {\n    _SG_GL_CHECK_ERROR();\n    glBindVertexArray(_sg.gl.vao);\n    _SG_GL_CHECK_ERROR();\n    _sg_clear(&_sg.gl.cache, sizeof(_sg.gl.cache));\n    _sg_gl_cache_clear_buffer_bindings(true);\n    _SG_GL_CHECK_ERROR();\n    _sg_gl_cache_clear_texture_sampler_bindings(true);\n    _SG_GL_CHECK_ERROR();\n    for (int i = 0; i < _sg.limits.max_vertex_attrs; i++) {\n        _sg_gl_attr_t* attr = &_sg.gl.cache.attrs[i].gl_attr;\n        attr->vb_index = -1;\n        attr->divisor = -1;\n        glDisableVertexAttribArray((GLuint)i);\n        _SG_GL_CHECK_ERROR();\n        _sg_stats_add(gl.num_disable_vertex_attrib_array, 1);\n    }\n    _sg.gl.cache.cur_primitive_type = GL_TRIANGLES;\n\n    // shader program\n    glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&_sg.gl.cache.prog);\n    _SG_GL_CHECK_ERROR();\n\n    // depth and stencil state\n    _sg.gl.cache.depth.compare = SG_COMPAREFUNC_ALWAYS;\n    _sg.gl.cache.stencil.front.compare = SG_COMPAREFUNC_ALWAYS;\n    _sg.gl.cache.stencil.front.fail_op = SG_STENCILOP_KEEP;\n    _sg.gl.cache.stencil.front.depth_fail_op = SG_STENCILOP_KEEP;\n    _sg.gl.cache.stencil.front.pass_op = SG_STENCILOP_KEEP;\n    _sg.gl.cache.stencil.back.compare = SG_COMPAREFUNC_ALWAYS;\n    _sg.gl.cache.stencil.back.fail_op = SG_STENCILOP_KEEP;\n    _sg.gl.cache.stencil.back.depth_fail_op = SG_STENCILOP_KEEP;\n    _sg.gl.cache.stencil.back.pass_op = SG_STENCILOP_KEEP;\n    glEnable(GL_DEPTH_TEST);\n    glDepthFunc(GL_ALWAYS);\n    glDepthMask(GL_FALSE);\n    glDisable(GL_STENCIL_TEST);\n    glStencilFunc(GL_ALWAYS, 0, 0);\n    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);\n    glStencilMask(0);\n    _sg_stats_add(gl.num_render_state, 7);\n\n    // blend state\n    _sg.gl.cache.blend.src_factor_rgb = SG_BLENDFACTOR_ONE;\n    _sg.gl.cache.blend.dst_factor_rgb = SG_BLENDFACTOR_ZERO;\n    _sg.gl.cache.blend.op_rgb = SG_BLENDOP_ADD;\n    _sg.gl.cache.blend.src_factor_alpha = SG_BLENDFACTOR_ONE;\n    _sg.gl.cache.blend.dst_factor_alpha = SG_BLENDFACTOR_ZERO;\n    _sg.gl.cache.blend.op_alpha = SG_BLENDOP_ADD;\n    glDisable(GL_BLEND);\n    glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO);\n    glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);\n    glBlendColor(0.0f, 0.0f, 0.0f, 0.0f);\n    _sg_stats_add(gl.num_render_state, 4);\n\n    // standalone state\n    for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {\n        _sg.gl.cache.color_write_mask[i] = SG_COLORMASK_RGBA;\n    }\n    _sg.gl.cache.cull_mode = SG_CULLMODE_NONE;\n    _sg.gl.cache.face_winding = SG_FACEWINDING_CW;\n    _sg.gl.cache.sample_count = 1;\n    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);\n    glPolygonOffset(0.0f, 0.0f);\n    glDisable(GL_POLYGON_OFFSET_FILL);\n    glDisable(GL_CULL_FACE);\n    glFrontFace(GL_CW);\n    glCullFace(GL_BACK);\n    glEnable(GL_SCISSOR_TEST);\n    glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);\n    glEnable(GL_DITHER);\n    glDisable(GL_POLYGON_OFFSET_FILL);\n    _sg_stats_add(gl.num_render_state, 10);\n    #if defined(SOKOL_GLCORE)\n        glEnable(GL_MULTISAMPLE);\n        glEnable(GL_PROGRAM_POINT_SIZE);\n        _sg_stats_add(gl.num_render_state, 2);\n    #endif\n}\n\n_SOKOL_PRIVATE void _sg_gl_setup_backend(const sg_desc* desc) {\n    _SOKOL_UNUSED(desc);\n\n    // assumes that _sg.gl is already zero-initialized\n    _sg.gl.valid = true;\n\n    #if defined(_SOKOL_USE_WIN32_GL_LOADER)\n    _sg_gl_load_opengl();\n    #endif\n\n    // clear initial GL error state\n    #if defined(SOKOL_DEBUG)\n        while (glGetError() != GL_NO_ERROR);\n    #endif\n    #if defined(SOKOL_GLCORE)\n        _sg_gl_init_caps_glcore();\n    #elif defined(SOKOL_GLES3)\n        _sg_gl_init_caps_gles3();\n    #endif\n\n    glGenVertexArrays(1, &_sg.gl.vao);\n    glBindVertexArray(_sg.gl.vao);\n    _SG_GL_CHECK_ERROR();\n    // incoming texture data is generally expected to be packed tightly\n    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);\n    #if defined(SOKOL_GLCORE)\n        // enable seamless cubemap sampling (only desktop GL)\n        glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);\n    #endif\n    _sg_gl_reset_state_cache();\n}\n\n_SOKOL_PRIVATE void _sg_gl_discard_backend(void) {\n    SOKOL_ASSERT(_sg.gl.valid);\n    if (_sg.gl.vao) {\n        glDeleteVertexArrays(1, &_sg.gl.vao);\n    }\n    #if defined(_SOKOL_USE_WIN32_GL_LOADER)\n    _sg_gl_unload_opengl();\n    #endif\n    _sg.gl.valid = false;\n}\n\n//-- GL backend resource creation and destruction ------------------------------\n_SOKOL_PRIVATE sg_resource_state _sg_gl_create_buffer(_sg_buffer_t* buf, const sg_buffer_desc* desc) {\n    SOKOL_ASSERT(buf && desc);\n    _SG_GL_CHECK_ERROR();\n    buf->gl.injected = (0 != desc->gl_buffers[0]);\n    const GLenum gl_target = _sg_gl_buffer_target(buf->cmn.type);\n    const GLenum gl_usage  = _sg_gl_usage(buf->cmn.usage);\n    for (int slot = 0; slot < buf->cmn.num_slots; slot++) {\n        GLuint gl_buf = 0;\n        if (buf->gl.injected) {\n            SOKOL_ASSERT(desc->gl_buffers[slot]);\n            gl_buf = desc->gl_buffers[slot];\n        } else {\n            glGenBuffers(1, &gl_buf);\n            SOKOL_ASSERT(gl_buf);\n            _sg_gl_cache_store_buffer_binding(gl_target);\n            _sg_gl_cache_bind_buffer(gl_target, gl_buf);\n            glBufferData(gl_target, buf->cmn.size, 0, gl_usage);\n            if (buf->cmn.usage == SG_USAGE_IMMUTABLE) {\n                SOKOL_ASSERT(desc->data.ptr);\n                glBufferSubData(gl_target, 0, buf->cmn.size, desc->data.ptr);\n            }\n            _sg_gl_cache_restore_buffer_binding(gl_target);\n        }\n        buf->gl.buf[slot] = gl_buf;\n    }\n    _SG_GL_CHECK_ERROR();\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_gl_discard_buffer(_sg_buffer_t* buf) {\n    SOKOL_ASSERT(buf);\n    _SG_GL_CHECK_ERROR();\n    for (int slot = 0; slot < buf->cmn.num_slots; slot++) {\n        if (buf->gl.buf[slot]) {\n            _sg_gl_cache_invalidate_buffer(buf->gl.buf[slot]);\n            if (!buf->gl.injected) {\n                glDeleteBuffers(1, &buf->gl.buf[slot]);\n            }\n        }\n    }\n    _SG_GL_CHECK_ERROR();\n}\n\n_SOKOL_PRIVATE bool _sg_gl_supported_texture_format(sg_pixel_format fmt) {\n    const int fmt_index = (int) fmt;\n    SOKOL_ASSERT((fmt_index > SG_PIXELFORMAT_NONE) && (fmt_index < _SG_PIXELFORMAT_NUM));\n    return _sg.formats[fmt_index].sample;\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_gl_create_image(_sg_image_t* img, const sg_image_desc* desc) {\n    SOKOL_ASSERT(img && desc);\n    _SG_GL_CHECK_ERROR();\n    img->gl.injected = (0 != desc->gl_textures[0]);\n\n    // check if texture format is support\n    if (!_sg_gl_supported_texture_format(img->cmn.pixel_format)) {\n        _SG_ERROR(GL_TEXTURE_FORMAT_NOT_SUPPORTED);\n        return SG_RESOURCESTATE_FAILED;\n    }\n    const GLenum gl_internal_format = _sg_gl_teximage_internal_format(img->cmn.pixel_format);\n\n    // if this is a MSAA render target, a render buffer object will be created instead of a regulat texture\n    // (since GLES3 has no multisampled texture objects)\n    if (img->cmn.render_target && (img->cmn.sample_count > 1)) {\n        glGenRenderbuffers(1, &img->gl.msaa_render_buffer);\n        glBindRenderbuffer(GL_RENDERBUFFER, img->gl.msaa_render_buffer);\n        glRenderbufferStorageMultisample(GL_RENDERBUFFER, img->cmn.sample_count, gl_internal_format, img->cmn.width, img->cmn.height);\n    } else if (img->gl.injected) {\n        img->gl.target = _sg_gl_texture_target(img->cmn.type);\n        // inject externally GL textures\n        for (int slot = 0; slot < img->cmn.num_slots; slot++) {\n            SOKOL_ASSERT(desc->gl_textures[slot]);\n            img->gl.tex[slot] = desc->gl_textures[slot];\n        }\n        if (desc->gl_texture_target) {\n            img->gl.target = (GLenum)desc->gl_texture_target;\n        }\n    } else {\n        // create our own GL texture(s)\n        img->gl.target = _sg_gl_texture_target(img->cmn.type);\n        const GLenum gl_format = _sg_gl_teximage_format(img->cmn.pixel_format);\n        const bool is_compressed = _sg_is_compressed_pixel_format(img->cmn.pixel_format);\n        for (int slot = 0; slot < img->cmn.num_slots; slot++) {\n            glGenTextures(1, &img->gl.tex[slot]);\n            SOKOL_ASSERT(img->gl.tex[slot]);\n            _sg_gl_cache_store_texture_sampler_binding(0);\n            _sg_gl_cache_bind_texture_sampler(0, img->gl.target, img->gl.tex[slot], 0);\n            glTexParameteri(img->gl.target, GL_TEXTURE_MAX_LEVEL, img->cmn.num_mipmaps - 1);\n\n            // NOTE: workaround for https://issues.chromium.org/issues/355605685\n            // FIXME: on GLES3 and GL 4.3 (e.g. not macOS) the texture initialization\n            // should be rewritten to use glTexStorage + glTexSubImage\n            bool tex_storage_allocated = false;\n            #if defined(__EMSCRIPTEN__)\n                if (desc->data.subimage[0][0].ptr == 0) {\n                    tex_storage_allocated = true;\n                    if ((SG_IMAGETYPE_2D == img->cmn.type) || (SG_IMAGETYPE_CUBE == img->cmn.type)) {\n                        glTexStorage2D(img->gl.target, img->cmn.num_mipmaps, gl_internal_format, img->cmn.width, img->cmn.height);\n                    } else if ((SG_IMAGETYPE_3D == img->cmn.type) || (SG_IMAGETYPE_ARRAY == img->cmn.type)) {\n                        glTexStorage3D(img->gl.target, img->cmn.num_mipmaps, gl_internal_format, img->cmn.width, img->cmn.height, img->cmn.num_slices);\n                    }\n                }\n            #endif\n            if (!tex_storage_allocated) {\n                const int num_faces = img->cmn.type == SG_IMAGETYPE_CUBE ? 6 : 1;\n                int data_index = 0;\n                for (int face_index = 0; face_index < num_faces; face_index++) {\n                    for (int mip_index = 0; mip_index < img->cmn.num_mipmaps; mip_index++, data_index++) {\n                        GLenum gl_img_target = img->gl.target;\n                        if (SG_IMAGETYPE_CUBE == img->cmn.type) {\n                            gl_img_target = _sg_gl_cubeface_target(face_index);\n                        }\n                        const GLvoid* data_ptr = desc->data.subimage[face_index][mip_index].ptr;\n                        const int mip_width = _sg_miplevel_dim(img->cmn.width, mip_index);\n                        const int mip_height = _sg_miplevel_dim(img->cmn.height, mip_index);\n                        if ((SG_IMAGETYPE_2D == img->cmn.type) || (SG_IMAGETYPE_CUBE == img->cmn.type)) {\n                            if (is_compressed) {\n                                const GLsizei data_size = (GLsizei) desc->data.subimage[face_index][mip_index].size;\n                                glCompressedTexImage2D(gl_img_target, mip_index, gl_internal_format,\n                                    mip_width, mip_height, 0, data_size, data_ptr);\n                            } else {\n                                const GLenum gl_type = _sg_gl_teximage_type(img->cmn.pixel_format);\n                                glTexImage2D(gl_img_target, mip_index, (GLint)gl_internal_format,\n                                    mip_width, mip_height, 0, gl_format, gl_type, data_ptr);\n                            }\n                        } else if ((SG_IMAGETYPE_3D == img->cmn.type) || (SG_IMAGETYPE_ARRAY == img->cmn.type)) {\n                            int mip_depth = img->cmn.num_slices;\n                            if (SG_IMAGETYPE_3D == img->cmn.type) {\n                                mip_depth = _sg_miplevel_dim(mip_depth, mip_index);\n                            }\n                            if (is_compressed) {\n                                const GLsizei data_size = (GLsizei) desc->data.subimage[face_index][mip_index].size;\n                                glCompressedTexImage3D(gl_img_target, mip_index, gl_internal_format,\n                                    mip_width, mip_height, mip_depth, 0, data_size, data_ptr);\n                            } else {\n                                const GLenum gl_type = _sg_gl_teximage_type(img->cmn.pixel_format);\n                                glTexImage3D(gl_img_target, mip_index, (GLint)gl_internal_format,\n                                    mip_width, mip_height, mip_depth, 0, gl_format, gl_type, data_ptr);\n                            }\n                        }\n                    }\n                }\n            }\n            _sg_gl_cache_restore_texture_sampler_binding(0);\n        }\n    }\n    _SG_GL_CHECK_ERROR();\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_gl_discard_image(_sg_image_t* img) {\n    SOKOL_ASSERT(img);\n    _SG_GL_CHECK_ERROR();\n    for (int slot = 0; slot < img->cmn.num_slots; slot++) {\n        if (img->gl.tex[slot]) {\n            _sg_gl_cache_invalidate_texture_sampler(img->gl.tex[slot], 0);\n            if (!img->gl.injected) {\n                glDeleteTextures(1, &img->gl.tex[slot]);\n            }\n        }\n    }\n    if (img->gl.msaa_render_buffer) {\n        glDeleteRenderbuffers(1, &img->gl.msaa_render_buffer);\n    }\n    _SG_GL_CHECK_ERROR();\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_gl_create_sampler(_sg_sampler_t* smp, const sg_sampler_desc* desc) {\n    SOKOL_ASSERT(smp && desc);\n    _SG_GL_CHECK_ERROR();\n    smp->gl.injected = (0 != desc->gl_sampler);\n    if (smp->gl.injected) {\n        smp->gl.smp = (GLuint) desc->gl_sampler;\n    } else {\n        glGenSamplers(1, &smp->gl.smp);\n        SOKOL_ASSERT(smp->gl.smp);\n\n        const GLenum gl_min_filter = _sg_gl_min_filter(smp->cmn.min_filter, smp->cmn.mipmap_filter);\n        const GLenum gl_mag_filter = _sg_gl_mag_filter(smp->cmn.mag_filter);\n        glSamplerParameteri(smp->gl.smp, GL_TEXTURE_MIN_FILTER, (GLint)gl_min_filter);\n        glSamplerParameteri(smp->gl.smp, GL_TEXTURE_MAG_FILTER, (GLint)gl_mag_filter);\n        // GL spec has strange defaults for mipmap min/max lod: -1000 to +1000\n        const float min_lod = _sg_clamp(desc->min_lod, 0.0f, 1000.0f);\n        const float max_lod = _sg_clamp(desc->max_lod, 0.0f, 1000.0f);\n        glSamplerParameterf(smp->gl.smp, GL_TEXTURE_MIN_LOD, min_lod);\n        glSamplerParameterf(smp->gl.smp, GL_TEXTURE_MAX_LOD, max_lod);\n        glSamplerParameteri(smp->gl.smp, GL_TEXTURE_WRAP_S, (GLint)_sg_gl_wrap(smp->cmn.wrap_u));\n        glSamplerParameteri(smp->gl.smp, GL_TEXTURE_WRAP_T, (GLint)_sg_gl_wrap(smp->cmn.wrap_v));\n        glSamplerParameteri(smp->gl.smp, GL_TEXTURE_WRAP_R, (GLint)_sg_gl_wrap(smp->cmn.wrap_w));\n        #if defined(SOKOL_GLCORE)\n        float border[4];\n        switch (smp->cmn.border_color) {\n            case SG_BORDERCOLOR_TRANSPARENT_BLACK:\n                border[0] = 0.0f; border[1] = 0.0f; border[2] = 0.0f; border[3] = 0.0f;\n                break;\n            case SG_BORDERCOLOR_OPAQUE_WHITE:\n                border[0] = 1.0f; border[1] = 1.0f; border[2] = 1.0f; border[3] = 1.0f;\n                break;\n            default:\n                border[0] = 0.0f; border[1] = 0.0f; border[2] = 0.0f; border[3] = 1.0f;\n                break;\n        }\n        glSamplerParameterfv(smp->gl.smp, GL_TEXTURE_BORDER_COLOR, border);\n        #endif\n        if (smp->cmn.compare != SG_COMPAREFUNC_NEVER) {\n            glSamplerParameteri(smp->gl.smp, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);\n            glSamplerParameteri(smp->gl.smp, GL_TEXTURE_COMPARE_FUNC, (GLint)_sg_gl_compare_func(smp->cmn.compare));\n        } else {\n            glSamplerParameteri(smp->gl.smp, GL_TEXTURE_COMPARE_MODE, GL_NONE);\n        }\n        if (_sg.gl.ext_anisotropic && (smp->cmn.max_anisotropy > 1)) {\n            GLint max_aniso = (GLint) smp->cmn.max_anisotropy;\n            if (max_aniso > _sg.gl.max_anisotropy) {\n                max_aniso = _sg.gl.max_anisotropy;\n            }\n            glSamplerParameteri(smp->gl.smp, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso);\n        }\n    }\n    _SG_GL_CHECK_ERROR();\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_gl_discard_sampler(_sg_sampler_t* smp) {\n    SOKOL_ASSERT(smp);\n    _SG_GL_CHECK_ERROR();\n    _sg_gl_cache_invalidate_texture_sampler(0, smp->gl.smp);\n    if (!smp->gl.injected) {\n        glDeleteSamplers(1, &smp->gl.smp);\n    }\n    _SG_GL_CHECK_ERROR();\n}\n\n_SOKOL_PRIVATE GLuint _sg_gl_compile_shader(sg_shader_stage stage, const char* src) {\n    SOKOL_ASSERT(src);\n    _SG_GL_CHECK_ERROR();\n    GLuint gl_shd = glCreateShader(_sg_gl_shader_stage(stage));\n    glShaderSource(gl_shd, 1, &src, 0);\n    glCompileShader(gl_shd);\n    GLint compile_status = 0;\n    glGetShaderiv(gl_shd, GL_COMPILE_STATUS, &compile_status);\n    if (!compile_status) {\n        // compilation failed, log error and delete shader\n        GLint log_len = 0;\n        glGetShaderiv(gl_shd, GL_INFO_LOG_LENGTH, &log_len);\n        if (log_len > 0) {\n            GLchar* log_buf = (GLchar*) _sg_malloc((size_t)log_len);\n            glGetShaderInfoLog(gl_shd, log_len, &log_len, log_buf);\n            _SG_ERROR(GL_SHADER_COMPILATION_FAILED);\n            _SG_LOGMSG(GL_SHADER_COMPILATION_FAILED, log_buf);\n            _sg_free(log_buf);\n        }\n        glDeleteShader(gl_shd);\n        gl_shd = 0;\n    }\n    _SG_GL_CHECK_ERROR();\n    return gl_shd;\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_gl_create_shader(_sg_shader_t* shd, const sg_shader_desc* desc) {\n    SOKOL_ASSERT(shd && desc);\n    SOKOL_ASSERT(!shd->gl.prog);\n    _SG_GL_CHECK_ERROR();\n\n    // copy the optional vertex attribute names over\n    for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {\n        _sg_strcpy(&shd->gl.attrs[i].name, desc->attrs[i].name);\n    }\n\n    GLuint gl_vs = _sg_gl_compile_shader(SG_SHADERSTAGE_VS, desc->vs.source);\n    GLuint gl_fs = _sg_gl_compile_shader(SG_SHADERSTAGE_FS, desc->fs.source);\n    if (!(gl_vs && gl_fs)) {\n        return SG_RESOURCESTATE_FAILED;\n    }\n    GLuint gl_prog = glCreateProgram();\n    glAttachShader(gl_prog, gl_vs);\n    glAttachShader(gl_prog, gl_fs);\n    glLinkProgram(gl_prog);\n    glDeleteShader(gl_vs);\n    glDeleteShader(gl_fs);\n    _SG_GL_CHECK_ERROR();\n\n    GLint link_status;\n    glGetProgramiv(gl_prog, GL_LINK_STATUS, &link_status);\n    if (!link_status) {\n        GLint log_len = 0;\n        glGetProgramiv(gl_prog, GL_INFO_LOG_LENGTH, &log_len);\n        if (log_len > 0) {\n            GLchar* log_buf = (GLchar*) _sg_malloc((size_t)log_len);\n            glGetProgramInfoLog(gl_prog, log_len, &log_len, log_buf);\n            _SG_ERROR(GL_SHADER_LINKING_FAILED);\n            _SG_LOGMSG(GL_SHADER_LINKING_FAILED, log_buf);\n            _sg_free(log_buf);\n        }\n        glDeleteProgram(gl_prog);\n        return SG_RESOURCESTATE_FAILED;\n    }\n    shd->gl.prog = gl_prog;\n\n    // resolve uniforms\n    _SG_GL_CHECK_ERROR();\n    for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {\n        const sg_shader_stage_desc* stage_desc = (stage_index == SG_SHADERSTAGE_VS)? &desc->vs : &desc->fs;\n        const _sg_shader_stage_t* stage = &shd->cmn.stage[stage_index];\n        _sg_gl_shader_stage_t* gl_stage = &shd->gl.stage[stage_index];\n        for (int ub_index = 0; ub_index < stage->num_uniform_blocks; ub_index++) {\n            const sg_shader_uniform_block_desc* ub_desc = &stage_desc->uniform_blocks[ub_index];\n            SOKOL_ASSERT(ub_desc->size > 0);\n            _sg_gl_uniform_block_t* ub = &gl_stage->uniform_blocks[ub_index];\n            SOKOL_ASSERT(ub->num_uniforms == 0);\n            uint32_t cur_uniform_offset = 0;\n            for (int u_index = 0; u_index < SG_MAX_UB_MEMBERS; u_index++) {\n                const sg_shader_uniform_desc* u_desc = &ub_desc->uniforms[u_index];\n                if (u_desc->type == SG_UNIFORMTYPE_INVALID) {\n                    break;\n                }\n                const uint32_t u_align = _sg_uniform_alignment(u_desc->type, u_desc->array_count, ub_desc->layout);\n                const uint32_t u_size = _sg_uniform_size(u_desc->type, u_desc->array_count, ub_desc->layout);\n                cur_uniform_offset = _sg_align_u32(cur_uniform_offset, u_align);\n                _sg_gl_uniform_t* u = &ub->uniforms[u_index];\n                u->type = u_desc->type;\n                u->count = (uint16_t) u_desc->array_count;\n                u->offset = (uint16_t) cur_uniform_offset;\n                cur_uniform_offset += u_size;\n                if (u_desc->name) {\n                    u->gl_loc = glGetUniformLocation(gl_prog, u_desc->name);\n                } else {\n                    u->gl_loc = u_index;\n                }\n                ub->num_uniforms++;\n            }\n            if (ub_desc->layout == SG_UNIFORMLAYOUT_STD140) {\n                cur_uniform_offset = _sg_align_u32(cur_uniform_offset, 16);\n            }\n            SOKOL_ASSERT(ub_desc->size == (size_t)cur_uniform_offset);\n            _SOKOL_UNUSED(cur_uniform_offset);\n        }\n    }\n\n    // resolve combined image samplers\n    _SG_GL_CHECK_ERROR();\n    GLuint cur_prog = 0;\n    glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&cur_prog);\n    glUseProgram(gl_prog);\n    int gl_tex_slot = 0;\n    for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {\n        const sg_shader_stage_desc* stage_desc = (stage_index == SG_SHADERSTAGE_VS)? &desc->vs : &desc->fs;\n        const _sg_shader_stage_t* stage = &shd->cmn.stage[stage_index];\n        _sg_gl_shader_stage_t* gl_stage = &shd->gl.stage[stage_index];\n        for (int img_smp_index = 0; img_smp_index < stage->num_image_samplers; img_smp_index++) {\n            const sg_shader_image_sampler_pair_desc* img_smp_desc = &stage_desc->image_sampler_pairs[img_smp_index];\n            _sg_gl_shader_image_sampler_t* gl_img_smp = &gl_stage->image_samplers[img_smp_index];\n            SOKOL_ASSERT(img_smp_desc->glsl_name);\n            GLint gl_loc = glGetUniformLocation(gl_prog, img_smp_desc->glsl_name);\n            if (gl_loc != -1) {\n                gl_img_smp->gl_tex_slot = gl_tex_slot++;\n                glUniform1i(gl_loc, gl_img_smp->gl_tex_slot);\n            } else {\n                gl_img_smp->gl_tex_slot = -1;\n                _SG_ERROR(GL_TEXTURE_NAME_NOT_FOUND_IN_SHADER);\n                _SG_LOGMSG(GL_TEXTURE_NAME_NOT_FOUND_IN_SHADER, img_smp_desc->glsl_name);\n            }\n        }\n    }\n    // it's legal to call glUseProgram with 0\n    glUseProgram(cur_prog);\n    _SG_GL_CHECK_ERROR();\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_gl_discard_shader(_sg_shader_t* shd) {\n    SOKOL_ASSERT(shd);\n    _SG_GL_CHECK_ERROR();\n    if (shd->gl.prog) {\n        _sg_gl_cache_invalidate_program(shd->gl.prog);\n        glDeleteProgram(shd->gl.prog);\n    }\n    _SG_GL_CHECK_ERROR();\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_gl_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) {\n    SOKOL_ASSERT(pip && shd && desc);\n    SOKOL_ASSERT((pip->shader == 0) && (pip->cmn.shader_id.id != SG_INVALID_ID));\n    SOKOL_ASSERT(desc->shader.id == shd->slot.id);\n    SOKOL_ASSERT(shd->gl.prog);\n    pip->shader = shd;\n    pip->gl.primitive_type = desc->primitive_type;\n    pip->gl.depth = desc->depth;\n    pip->gl.stencil = desc->stencil;\n    // FIXME: blend color and write mask per draw-buffer-attachment (requires GL4)\n    pip->gl.blend = desc->colors[0].blend;\n    for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {\n        pip->gl.color_write_mask[i] = desc->colors[i].write_mask;\n    }\n    pip->gl.cull_mode = desc->cull_mode;\n    pip->gl.face_winding = desc->face_winding;\n    pip->gl.sample_count = desc->sample_count;\n    pip->gl.alpha_to_coverage_enabled = desc->alpha_to_coverage_enabled;\n\n    // resolve vertex attributes\n    for (int attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {\n        pip->gl.attrs[attr_index].vb_index = -1;\n    }\n    for (int attr_index = 0; attr_index < _sg.limits.max_vertex_attrs; attr_index++) {\n        const sg_vertex_attr_state* a_state = &desc->layout.attrs[attr_index];\n        if (a_state->format == SG_VERTEXFORMAT_INVALID) {\n            break;\n        }\n        SOKOL_ASSERT(a_state->buffer_index < SG_MAX_VERTEX_BUFFERS);\n        const sg_vertex_buffer_layout_state* l_state = &desc->layout.buffers[a_state->buffer_index];\n        const sg_vertex_step step_func = l_state->step_func;\n        const int step_rate = l_state->step_rate;\n        GLint attr_loc = attr_index;\n        if (!_sg_strempty(&shd->gl.attrs[attr_index].name)) {\n            attr_loc = glGetAttribLocation(pip->shader->gl.prog, _sg_strptr(&shd->gl.attrs[attr_index].name));\n        }\n        SOKOL_ASSERT(attr_loc < (GLint)_sg.limits.max_vertex_attrs);\n        if (attr_loc != -1) {\n            _sg_gl_attr_t* gl_attr = &pip->gl.attrs[attr_loc];\n            SOKOL_ASSERT(gl_attr->vb_index == -1);\n            gl_attr->vb_index = (int8_t) a_state->buffer_index;\n            if (step_func == SG_VERTEXSTEP_PER_VERTEX) {\n                gl_attr->divisor = 0;\n            } else {\n                gl_attr->divisor = (int8_t) step_rate;\n                pip->cmn.use_instanced_draw = true;\n            }\n            SOKOL_ASSERT(l_state->stride > 0);\n            gl_attr->stride = (uint8_t) l_state->stride;\n            gl_attr->offset = a_state->offset;\n            gl_attr->size = (uint8_t) _sg_gl_vertexformat_size(a_state->format);\n            gl_attr->type = _sg_gl_vertexformat_type(a_state->format);\n            gl_attr->normalized = _sg_gl_vertexformat_normalized(a_state->format);\n            pip->cmn.vertex_buffer_layout_active[a_state->buffer_index] = true;\n        } else {\n            _SG_ERROR(GL_VERTEX_ATTRIBUTE_NOT_FOUND_IN_SHADER);\n            _SG_LOGMSG(GL_VERTEX_ATTRIBUTE_NOT_FOUND_IN_SHADER, _sg_strptr(&shd->gl.attrs[attr_index].name));\n        }\n    }\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_gl_discard_pipeline(_sg_pipeline_t* pip) {\n    SOKOL_ASSERT(pip);\n    _sg_gl_cache_invalidate_pipeline(pip);\n}\n\n_SOKOL_PRIVATE void _sg_gl_fb_attach_texture(const _sg_gl_attachment_t* gl_att, const _sg_attachment_common_t* cmn_att, GLenum gl_att_type) {\n    const _sg_image_t* img = gl_att->image;\n    SOKOL_ASSERT(img);\n    const GLuint gl_tex = img->gl.tex[0];\n    SOKOL_ASSERT(gl_tex);\n    const GLuint gl_target = img->gl.target;\n    SOKOL_ASSERT(gl_target);\n    const int mip_level = cmn_att->mip_level;\n    const int slice = cmn_att->slice;\n    switch (img->cmn.type) {\n        case SG_IMAGETYPE_2D:\n            glFramebufferTexture2D(GL_FRAMEBUFFER, gl_att_type, gl_target, gl_tex, mip_level);\n            break;\n        case SG_IMAGETYPE_CUBE:\n            glFramebufferTexture2D(GL_FRAMEBUFFER, gl_att_type, _sg_gl_cubeface_target(slice), gl_tex, mip_level);\n            break;\n        default:\n            glFramebufferTextureLayer(GL_FRAMEBUFFER, gl_att_type, gl_tex, mip_level, slice);\n            break;\n    }\n}\n\n_SOKOL_PRIVATE GLenum _sg_gl_depth_stencil_attachment_type(const _sg_gl_attachment_t* ds_att) {\n    const _sg_image_t* img = ds_att->image;\n    SOKOL_ASSERT(img);\n    if (_sg_is_depth_stencil_format(img->cmn.pixel_format)) {\n        return GL_DEPTH_STENCIL_ATTACHMENT;\n    } else {\n        return GL_DEPTH_ATTACHMENT;\n    }\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_gl_create_attachments(_sg_attachments_t* atts, _sg_image_t** color_images, _sg_image_t** resolve_images, _sg_image_t* ds_image, const sg_attachments_desc* desc) {\n    SOKOL_ASSERT(atts && desc);\n    SOKOL_ASSERT(color_images && resolve_images);\n    _SG_GL_CHECK_ERROR();\n\n    // copy image pointers\n    for (int i = 0; i < atts->cmn.num_colors; i++) {\n        const sg_attachment_desc* color_desc = &desc->colors[i];\n        _SOKOL_UNUSED(color_desc);\n        SOKOL_ASSERT(color_desc->image.id != SG_INVALID_ID);\n        SOKOL_ASSERT(0 == atts->gl.colors[i].image);\n        SOKOL_ASSERT(color_images[i] && (color_images[i]->slot.id == color_desc->image.id));\n        SOKOL_ASSERT(_sg_is_valid_rendertarget_color_format(color_images[i]->cmn.pixel_format));\n        atts->gl.colors[i].image = color_images[i];\n\n        const sg_attachment_desc* resolve_desc = &desc->resolves[i];\n        if (resolve_desc->image.id != SG_INVALID_ID) {\n            SOKOL_ASSERT(0 == atts->gl.resolves[i].image);\n            SOKOL_ASSERT(resolve_images[i] && (resolve_images[i]->slot.id == resolve_desc->image.id));\n            SOKOL_ASSERT(color_images[i] && (color_images[i]->cmn.pixel_format == resolve_images[i]->cmn.pixel_format));\n            atts->gl.resolves[i].image = resolve_images[i];\n        }\n    }\n    SOKOL_ASSERT(0 == atts->gl.depth_stencil.image);\n    const sg_attachment_desc* ds_desc = &desc->depth_stencil;\n    if (ds_desc->image.id != SG_INVALID_ID) {\n        SOKOL_ASSERT(ds_image && (ds_image->slot.id == ds_desc->image.id));\n        SOKOL_ASSERT(_sg_is_valid_rendertarget_depth_format(ds_image->cmn.pixel_format));\n        atts->gl.depth_stencil.image = ds_image;\n    }\n\n    // store current framebuffer binding (restored at end of function)\n    GLuint gl_orig_fb;\n    glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&gl_orig_fb);\n\n    // create a framebuffer object\n    glGenFramebuffers(1, &atts->gl.fb);\n    glBindFramebuffer(GL_FRAMEBUFFER, atts->gl.fb);\n\n    // attach color attachments to framebuffer\n    for (int i = 0; i < atts->cmn.num_colors; i++) {\n        const _sg_image_t* color_img = atts->gl.colors[i].image;\n        SOKOL_ASSERT(color_img);\n        const GLuint gl_msaa_render_buffer = color_img->gl.msaa_render_buffer;\n        if (gl_msaa_render_buffer) {\n            glFramebufferRenderbuffer(GL_FRAMEBUFFER, (GLenum)(GL_COLOR_ATTACHMENT0+i), GL_RENDERBUFFER, gl_msaa_render_buffer);\n        } else {\n            const GLenum gl_att_type = (GLenum)(GL_COLOR_ATTACHMENT0 + i);\n            _sg_gl_fb_attach_texture(&atts->gl.colors[i], &atts->cmn.colors[i], gl_att_type);\n        }\n    }\n    // attach depth-stencil attachment\n    if (atts->gl.depth_stencil.image) {\n        const GLenum gl_att = _sg_gl_depth_stencil_attachment_type(&atts->gl.depth_stencil);\n        const _sg_image_t* ds_img = atts->gl.depth_stencil.image;\n        const GLuint gl_msaa_render_buffer = ds_img->gl.msaa_render_buffer;\n        if (gl_msaa_render_buffer) {\n            glFramebufferRenderbuffer(GL_FRAMEBUFFER, gl_att, GL_RENDERBUFFER, gl_msaa_render_buffer);\n        } else {\n            const GLenum gl_att_type = _sg_gl_depth_stencil_attachment_type(&atts->gl.depth_stencil);\n            _sg_gl_fb_attach_texture(&atts->gl.depth_stencil, &atts->cmn.depth_stencil, gl_att_type);\n        }\n    }\n\n    // check if framebuffer is complete\n    {\n        const GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);\n        if (fb_status != GL_FRAMEBUFFER_COMPLETE) {\n            switch (fb_status) {\n                case GL_FRAMEBUFFER_UNDEFINED:\n                    _SG_ERROR(GL_FRAMEBUFFER_STATUS_UNDEFINED);\n                    break;\n                case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:\n                    _SG_ERROR(GL_FRAMEBUFFER_STATUS_INCOMPLETE_ATTACHMENT);\n                    break;\n                case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:\n                    _SG_ERROR(GL_FRAMEBUFFER_STATUS_INCOMPLETE_MISSING_ATTACHMENT);\n                    break;\n                case GL_FRAMEBUFFER_UNSUPPORTED:\n                    _SG_ERROR(GL_FRAMEBUFFER_STATUS_UNSUPPORTED);\n                    break;\n                case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:\n                    _SG_ERROR(GL_FRAMEBUFFER_STATUS_INCOMPLETE_MULTISAMPLE);\n                    break;\n                default:\n                    _SG_ERROR(GL_FRAMEBUFFER_STATUS_UNKNOWN);\n                    break;\n            }\n            return SG_RESOURCESTATE_FAILED;\n        }\n    }\n\n    // setup color attachments for the framebuffer\n    static const GLenum gl_draw_bufs[SG_MAX_COLOR_ATTACHMENTS] = {\n        GL_COLOR_ATTACHMENT0,\n        GL_COLOR_ATTACHMENT1,\n        GL_COLOR_ATTACHMENT2,\n        GL_COLOR_ATTACHMENT3\n    };\n    glDrawBuffers(atts->cmn.num_colors, gl_draw_bufs);\n\n    // create MSAA resolve framebuffers if necessary\n    for (int i = 0; i < atts->cmn.num_colors; i++) {\n        _sg_gl_attachment_t* gl_resolve_att = &atts->gl.resolves[i];\n        if (gl_resolve_att->image) {\n            _sg_attachment_common_t* cmn_resolve_att = &atts->cmn.resolves[i];\n            SOKOL_ASSERT(0 == atts->gl.msaa_resolve_framebuffer[i]);\n            glGenFramebuffers(1, &atts->gl.msaa_resolve_framebuffer[i]);\n            glBindFramebuffer(GL_FRAMEBUFFER, atts->gl.msaa_resolve_framebuffer[i]);\n            _sg_gl_fb_attach_texture(gl_resolve_att, cmn_resolve_att, GL_COLOR_ATTACHMENT0);\n            // check if framebuffer is complete\n            const GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);\n            if (fb_status != GL_FRAMEBUFFER_COMPLETE) {\n                switch (fb_status) {\n                    case GL_FRAMEBUFFER_UNDEFINED:\n                        _SG_ERROR(GL_FRAMEBUFFER_STATUS_UNDEFINED);\n                        break;\n                    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:\n                        _SG_ERROR(GL_FRAMEBUFFER_STATUS_INCOMPLETE_ATTACHMENT);\n                        break;\n                    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:\n                        _SG_ERROR(GL_FRAMEBUFFER_STATUS_INCOMPLETE_MISSING_ATTACHMENT);\n                        break;\n                    case GL_FRAMEBUFFER_UNSUPPORTED:\n                        _SG_ERROR(GL_FRAMEBUFFER_STATUS_UNSUPPORTED);\n                        break;\n                    case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:\n                        _SG_ERROR(GL_FRAMEBUFFER_STATUS_INCOMPLETE_MULTISAMPLE);\n                        break;\n                    default:\n                        _SG_ERROR(GL_FRAMEBUFFER_STATUS_UNKNOWN);\n                        break;\n                }\n                return SG_RESOURCESTATE_FAILED;\n            }\n            // setup color attachments for the framebuffer\n            glDrawBuffers(1, &gl_draw_bufs[0]);\n        }\n    }\n\n    // restore original framebuffer binding\n    glBindFramebuffer(GL_FRAMEBUFFER, gl_orig_fb);\n    _SG_GL_CHECK_ERROR();\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_gl_discard_attachments(_sg_attachments_t* atts) {\n    SOKOL_ASSERT(atts);\n    _SG_GL_CHECK_ERROR();\n    if (0 != atts->gl.fb) {\n        glDeleteFramebuffers(1, &atts->gl.fb);\n    }\n    for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {\n        if (atts->gl.msaa_resolve_framebuffer[i]) {\n            glDeleteFramebuffers(1, &atts->gl.msaa_resolve_framebuffer[i]);\n        }\n    }\n    _SG_GL_CHECK_ERROR();\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_gl_attachments_color_image(const _sg_attachments_t* atts, int index) {\n    SOKOL_ASSERT(atts && (index >= 0) && (index < SG_MAX_COLOR_ATTACHMENTS));\n    return atts->gl.colors[index].image;\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_gl_attachments_resolve_image(const _sg_attachments_t* atts, int index) {\n    SOKOL_ASSERT(atts && (index >= 0) && (index < SG_MAX_COLOR_ATTACHMENTS));\n    return atts->gl.resolves[index].image;\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_gl_attachments_ds_image(const _sg_attachments_t* atts) {\n    SOKOL_ASSERT(atts);\n    return atts->gl.depth_stencil.image;\n}\n\n_SOKOL_PRIVATE void _sg_gl_begin_pass(const sg_pass* pass) {\n    // FIXME: what if a texture used as render target is still bound, should we\n    // unbind all currently bound textures in begin pass?\n    SOKOL_ASSERT(pass);\n    _SG_GL_CHECK_ERROR();\n    const _sg_attachments_t* atts = _sg.cur_pass.atts;\n    const sg_swapchain* swapchain = &pass->swapchain;\n    const sg_pass_action* action = &pass->action;\n\n    // bind the render pass framebuffer\n    //\n    // FIXME: Disabling SRGB conversion for the default framebuffer is\n    // a crude hack to make behaviour for sRGB render target textures\n    // identical with the Metal and D3D11 swapchains created by sokol-app.\n    //\n    // This will need a cleaner solution (e.g. allowing to configure\n    // sokol_app.h with an sRGB or RGB framebuffer.\n    if (atts) {\n        // offscreen pass\n        SOKOL_ASSERT(atts->gl.fb);\n        #if defined(SOKOL_GLCORE)\n        glEnable(GL_FRAMEBUFFER_SRGB);\n        #endif\n        glBindFramebuffer(GL_FRAMEBUFFER, atts->gl.fb);\n    } else {\n        // default pass\n        #if defined(SOKOL_GLCORE)\n        glDisable(GL_FRAMEBUFFER_SRGB);\n        #endif\n        // NOTE: on some platforms, the default framebuffer of a context\n        // is null, so we can't actually assert here that the\n        // framebuffer has been provided\n        glBindFramebuffer(GL_FRAMEBUFFER, swapchain->gl.framebuffer);\n    }\n    glViewport(0, 0, _sg.cur_pass.width, _sg.cur_pass.height);\n    glScissor(0, 0, _sg.cur_pass.width, _sg.cur_pass.height);\n\n    // number of color attachments\n    const int num_color_atts = atts ? atts->cmn.num_colors : 1;\n\n    // clear color and depth-stencil attachments if needed\n    bool clear_any_color = false;\n    for (int i = 0; i < num_color_atts; i++) {\n        if (SG_LOADACTION_CLEAR == action->colors[i].load_action) {\n            clear_any_color = true;\n            break;\n        }\n    }\n    const bool clear_depth = (action->depth.load_action == SG_LOADACTION_CLEAR);\n    const bool clear_stencil = (action->stencil.load_action == SG_LOADACTION_CLEAR);\n\n    bool need_pip_cache_flush = false;\n    if (clear_any_color) {\n        bool need_color_mask_flush = false;\n        // NOTE: not a bug to iterate over all possible color attachments\n        for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {\n            if (SG_COLORMASK_RGBA != _sg.gl.cache.color_write_mask[i]) {\n                need_pip_cache_flush = true;\n                need_color_mask_flush = true;\n                _sg.gl.cache.color_write_mask[i] = SG_COLORMASK_RGBA;\n            }\n        }\n        if (need_color_mask_flush) {\n            glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);\n        }\n    }\n    if (clear_depth) {\n        if (!_sg.gl.cache.depth.write_enabled) {\n            need_pip_cache_flush = true;\n            _sg.gl.cache.depth.write_enabled = true;\n            glDepthMask(GL_TRUE);\n        }\n        if (_sg.gl.cache.depth.compare != SG_COMPAREFUNC_ALWAYS) {\n            need_pip_cache_flush = true;\n            _sg.gl.cache.depth.compare = SG_COMPAREFUNC_ALWAYS;\n            glDepthFunc(GL_ALWAYS);\n        }\n    }\n    if (clear_stencil) {\n        if (_sg.gl.cache.stencil.write_mask != 0xFF) {\n            need_pip_cache_flush = true;\n            _sg.gl.cache.stencil.write_mask = 0xFF;\n            glStencilMask(0xFF);\n        }\n    }\n    if (need_pip_cache_flush) {\n        // we messed with the state cache directly, need to clear cached\n        // pipeline to force re-evaluation in next sg_apply_pipeline()\n        _sg.gl.cache.cur_pipeline = 0;\n        _sg.gl.cache.cur_pipeline_id.id = SG_INVALID_ID;\n    }\n    for (int i = 0; i < num_color_atts; i++) {\n        if (action->colors[i].load_action == SG_LOADACTION_CLEAR) {\n            glClearBufferfv(GL_COLOR, i, &action->colors[i].clear_value.r);\n        }\n    }\n    if ((atts == 0) || (atts->gl.depth_stencil.image)) {\n        if (clear_depth && clear_stencil) {\n            glClearBufferfi(GL_DEPTH_STENCIL, 0, action->depth.clear_value, action->stencil.clear_value);\n        } else if (clear_depth) {\n            glClearBufferfv(GL_DEPTH, 0, &action->depth.clear_value);\n        } else if (clear_stencil) {\n            GLint val = (GLint) action->stencil.clear_value;\n            glClearBufferiv(GL_STENCIL, 0, &val);\n        }\n    }\n    // keep store actions for end-pass\n    for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {\n        _sg.gl.color_store_actions[i] = action->colors[i].store_action;\n    }\n    _sg.gl.depth_store_action = action->depth.store_action;\n    _sg.gl.stencil_store_action = action->stencil.store_action;\n\n    _SG_GL_CHECK_ERROR();\n}\n\n_SOKOL_PRIVATE void _sg_gl_end_pass(void) {\n    _SG_GL_CHECK_ERROR();\n\n    if (_sg.cur_pass.atts) {\n        const _sg_attachments_t* atts = _sg.cur_pass.atts;\n        SOKOL_ASSERT(atts->slot.id == _sg.cur_pass.atts_id.id);\n        bool fb_read_bound = false;\n        bool fb_draw_bound = false;\n        const int num_color_atts = atts->cmn.num_colors;\n        for (int i = 0; i < num_color_atts; i++) {\n            // perform MSAA resolve if needed\n            if (atts->gl.msaa_resolve_framebuffer[i] != 0) {\n                if (!fb_read_bound) {\n                    SOKOL_ASSERT(atts->gl.fb);\n                    glBindFramebuffer(GL_READ_FRAMEBUFFER, atts->gl.fb);\n                    fb_read_bound = true;\n                }\n                const int w = atts->gl.colors[i].image->cmn.width;\n                const int h = atts->gl.colors[i].image->cmn.height;\n                glBindFramebuffer(GL_DRAW_FRAMEBUFFER, atts->gl.msaa_resolve_framebuffer[i]);\n                glReadBuffer((GLenum)(GL_COLOR_ATTACHMENT0 + i));\n                glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);\n                fb_draw_bound = true;\n            }\n        }\n\n        // invalidate framebuffers\n        _SOKOL_UNUSED(fb_draw_bound);\n        #if defined(SOKOL_GLES3)\n        // need to restore framebuffer binding before invalidate if the MSAA resolve had changed the binding\n        if (fb_draw_bound) {\n            glBindFramebuffer(GL_FRAMEBUFFER, atts->gl.fb);\n        }\n        GLenum invalidate_atts[SG_MAX_COLOR_ATTACHMENTS + 2] = { 0 };\n        int att_index = 0;\n        for (int i = 0; i < num_color_atts; i++) {\n            if (_sg.gl.color_store_actions[i] == SG_STOREACTION_DONTCARE) {\n                invalidate_atts[att_index++] = (GLenum)(GL_COLOR_ATTACHMENT0 + i);\n            }\n        }\n        if ((_sg.gl.depth_store_action == SG_STOREACTION_DONTCARE) && (_sg.cur_pass.atts->cmn.depth_stencil.image_id.id != SG_INVALID_ID)) {\n            invalidate_atts[att_index++] = GL_DEPTH_ATTACHMENT;\n        }\n        if ((_sg.gl.stencil_store_action == SG_STOREACTION_DONTCARE) && (_sg.cur_pass.atts->cmn.depth_stencil.image_id.id != SG_INVALID_ID)) {\n            invalidate_atts[att_index++] = GL_STENCIL_ATTACHMENT;\n        }\n        if (att_index > 0) {\n            glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, att_index, invalidate_atts);\n        }\n        #endif\n    }\n    _SG_GL_CHECK_ERROR();\n}\n\n_SOKOL_PRIVATE void _sg_gl_apply_viewport(int x, int y, int w, int h, bool origin_top_left) {\n    y = origin_top_left ? (_sg.cur_pass.height - (y+h)) : y;\n    glViewport(x, y, w, h);\n}\n\n_SOKOL_PRIVATE void _sg_gl_apply_scissor_rect(int x, int y, int w, int h, bool origin_top_left) {\n    y = origin_top_left ? (_sg.cur_pass.height - (y+h)) : y;\n    glScissor(x, y, w, h);\n}\n\n_SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) {\n    SOKOL_ASSERT(pip);\n    SOKOL_ASSERT(pip->shader && (pip->cmn.shader_id.id == pip->shader->slot.id));\n    _SG_GL_CHECK_ERROR();\n    if ((_sg.gl.cache.cur_pipeline != pip) || (_sg.gl.cache.cur_pipeline_id.id != pip->slot.id)) {\n        _sg.gl.cache.cur_pipeline = pip;\n        _sg.gl.cache.cur_pipeline_id.id = pip->slot.id;\n        _sg.gl.cache.cur_primitive_type = _sg_gl_primitive_type(pip->gl.primitive_type);\n        _sg.gl.cache.cur_index_type = _sg_gl_index_type(pip->cmn.index_type);\n\n        // update depth state\n        {\n            const sg_depth_state* state_ds = &pip->gl.depth;\n            sg_depth_state* cache_ds = &_sg.gl.cache.depth;\n            if (state_ds->compare != cache_ds->compare) {\n                cache_ds->compare = state_ds->compare;\n                glDepthFunc(_sg_gl_compare_func(state_ds->compare));\n                _sg_stats_add(gl.num_render_state, 1);\n            }\n            if (state_ds->write_enabled != cache_ds->write_enabled) {\n                cache_ds->write_enabled = state_ds->write_enabled;\n                glDepthMask(state_ds->write_enabled);\n                _sg_stats_add(gl.num_render_state, 1);\n            }\n            if (!_sg_fequal(state_ds->bias, cache_ds->bias, 0.000001f) ||\n                !_sg_fequal(state_ds->bias_slope_scale, cache_ds->bias_slope_scale, 0.000001f))\n            {\n                /* according to ANGLE's D3D11 backend:\n                    D3D11 SlopeScaledDepthBias ==> GL polygonOffsetFactor\n                    D3D11 DepthBias ==> GL polygonOffsetUnits\n                    DepthBiasClamp has no meaning on GL\n                */\n                cache_ds->bias = state_ds->bias;\n                cache_ds->bias_slope_scale = state_ds->bias_slope_scale;\n                glPolygonOffset(state_ds->bias_slope_scale, state_ds->bias);\n                _sg_stats_add(gl.num_render_state, 1);\n                bool po_enabled = true;\n                if (_sg_fequal(state_ds->bias, 0.0f, 0.000001f) &&\n                    _sg_fequal(state_ds->bias_slope_scale, 0.0f, 0.000001f))\n                {\n                    po_enabled = false;\n                }\n                if (po_enabled != _sg.gl.cache.polygon_offset_enabled) {\n                    _sg.gl.cache.polygon_offset_enabled = po_enabled;\n                    if (po_enabled) {\n                        glEnable(GL_POLYGON_OFFSET_FILL);\n                    } else {\n                        glDisable(GL_POLYGON_OFFSET_FILL);\n                    }\n                    _sg_stats_add(gl.num_render_state, 1);\n                }\n            }\n        }\n\n        // update stencil state\n        {\n            const sg_stencil_state* state_ss = &pip->gl.stencil;\n            sg_stencil_state* cache_ss = &_sg.gl.cache.stencil;\n            if (state_ss->enabled != cache_ss->enabled) {\n                cache_ss->enabled = state_ss->enabled;\n                if (state_ss->enabled) {\n                    glEnable(GL_STENCIL_TEST);\n                } else {\n                    glDisable(GL_STENCIL_TEST);\n                }\n                _sg_stats_add(gl.num_render_state, 1);\n            }\n            if (state_ss->write_mask != cache_ss->write_mask) {\n                cache_ss->write_mask = state_ss->write_mask;\n                glStencilMask(state_ss->write_mask);\n                _sg_stats_add(gl.num_render_state, 1);\n            }\n            for (int i = 0; i < 2; i++) {\n                const sg_stencil_face_state* state_sfs = (i==0)? &state_ss->front : &state_ss->back;\n                sg_stencil_face_state* cache_sfs = (i==0)? &cache_ss->front : &cache_ss->back;\n                GLenum gl_face = (i==0)? GL_FRONT : GL_BACK;\n                if ((state_sfs->compare != cache_sfs->compare) ||\n                    (state_ss->read_mask != cache_ss->read_mask) ||\n                    (state_ss->ref != cache_ss->ref))\n                {\n                    cache_sfs->compare = state_sfs->compare;\n                    glStencilFuncSeparate(gl_face,\n                        _sg_gl_compare_func(state_sfs->compare),\n                        state_ss->ref,\n                        state_ss->read_mask);\n                    _sg_stats_add(gl.num_render_state, 1);\n                }\n                if ((state_sfs->fail_op != cache_sfs->fail_op) ||\n                    (state_sfs->depth_fail_op != cache_sfs->depth_fail_op) ||\n                    (state_sfs->pass_op != cache_sfs->pass_op))\n                {\n                    cache_sfs->fail_op = state_sfs->fail_op;\n                    cache_sfs->depth_fail_op = state_sfs->depth_fail_op;\n                    cache_sfs->pass_op = state_sfs->pass_op;\n                    glStencilOpSeparate(gl_face,\n                        _sg_gl_stencil_op(state_sfs->fail_op),\n                        _sg_gl_stencil_op(state_sfs->depth_fail_op),\n                        _sg_gl_stencil_op(state_sfs->pass_op));\n                    _sg_stats_add(gl.num_render_state, 1);\n                }\n            }\n            cache_ss->read_mask = state_ss->read_mask;\n            cache_ss->ref = state_ss->ref;\n        }\n\n        if (pip->cmn.color_count > 0) {\n            // update blend state\n            // FIXME: separate blend state per color attachment not support, needs GL4\n            const sg_blend_state* state_bs = &pip->gl.blend;\n            sg_blend_state* cache_bs = &_sg.gl.cache.blend;\n            if (state_bs->enabled != cache_bs->enabled) {\n                cache_bs->enabled = state_bs->enabled;\n                if (state_bs->enabled) {\n                    glEnable(GL_BLEND);\n                } else {\n                    glDisable(GL_BLEND);\n                }\n                _sg_stats_add(gl.num_render_state, 1);\n            }\n            if ((state_bs->src_factor_rgb != cache_bs->src_factor_rgb) ||\n                (state_bs->dst_factor_rgb != cache_bs->dst_factor_rgb) ||\n                (state_bs->src_factor_alpha != cache_bs->src_factor_alpha) ||\n                (state_bs->dst_factor_alpha != cache_bs->dst_factor_alpha))\n            {\n                cache_bs->src_factor_rgb = state_bs->src_factor_rgb;\n                cache_bs->dst_factor_rgb = state_bs->dst_factor_rgb;\n                cache_bs->src_factor_alpha = state_bs->src_factor_alpha;\n                cache_bs->dst_factor_alpha = state_bs->dst_factor_alpha;\n                glBlendFuncSeparate(_sg_gl_blend_factor(state_bs->src_factor_rgb),\n                    _sg_gl_blend_factor(state_bs->dst_factor_rgb),\n                    _sg_gl_blend_factor(state_bs->src_factor_alpha),\n                    _sg_gl_blend_factor(state_bs->dst_factor_alpha));\n                _sg_stats_add(gl.num_render_state, 1);\n            }\n            if ((state_bs->op_rgb != cache_bs->op_rgb) || (state_bs->op_alpha != cache_bs->op_alpha)) {\n                cache_bs->op_rgb = state_bs->op_rgb;\n                cache_bs->op_alpha = state_bs->op_alpha;\n                glBlendEquationSeparate(_sg_gl_blend_op(state_bs->op_rgb), _sg_gl_blend_op(state_bs->op_alpha));\n                _sg_stats_add(gl.num_render_state, 1);\n            }\n\n            // standalone color target state\n            for (GLuint i = 0; i < (GLuint)pip->cmn.color_count; i++) {\n                if (pip->gl.color_write_mask[i] != _sg.gl.cache.color_write_mask[i]) {\n                    const sg_color_mask cm = pip->gl.color_write_mask[i];\n                    _sg.gl.cache.color_write_mask[i] = cm;\n                    #ifdef SOKOL_GLCORE\n                        glColorMaski(i,\n                                    (cm & SG_COLORMASK_R) != 0,\n                                    (cm & SG_COLORMASK_G) != 0,\n                                    (cm & SG_COLORMASK_B) != 0,\n                                    (cm & SG_COLORMASK_A) != 0);\n                    #else\n                        if (0 == i) {\n                            glColorMask((cm & SG_COLORMASK_R) != 0,\n                                        (cm & SG_COLORMASK_G) != 0,\n                                        (cm & SG_COLORMASK_B) != 0,\n                                        (cm & SG_COLORMASK_A) != 0);\n                        }\n                    #endif\n                    _sg_stats_add(gl.num_render_state, 1);\n                }\n            }\n\n            if (!_sg_fequal(pip->cmn.blend_color.r, _sg.gl.cache.blend_color.r, 0.0001f) ||\n                !_sg_fequal(pip->cmn.blend_color.g, _sg.gl.cache.blend_color.g, 0.0001f) ||\n                !_sg_fequal(pip->cmn.blend_color.b, _sg.gl.cache.blend_color.b, 0.0001f) ||\n                !_sg_fequal(pip->cmn.blend_color.a, _sg.gl.cache.blend_color.a, 0.0001f))\n            {\n                sg_color c = pip->cmn.blend_color;\n                _sg.gl.cache.blend_color = c;\n                glBlendColor(c.r, c.g, c.b, c.a);\n                _sg_stats_add(gl.num_render_state, 1);\n            }\n        } // pip->cmn.color_count > 0\n\n        if (pip->gl.cull_mode != _sg.gl.cache.cull_mode) {\n            _sg.gl.cache.cull_mode = pip->gl.cull_mode;\n            if (SG_CULLMODE_NONE == pip->gl.cull_mode) {\n                glDisable(GL_CULL_FACE);\n                _sg_stats_add(gl.num_render_state, 1);\n            } else {\n                glEnable(GL_CULL_FACE);\n                GLenum gl_mode = (SG_CULLMODE_FRONT == pip->gl.cull_mode) ? GL_FRONT : GL_BACK;\n                glCullFace(gl_mode);\n                _sg_stats_add(gl.num_render_state, 2);\n            }\n        }\n        if (pip->gl.face_winding != _sg.gl.cache.face_winding) {\n            _sg.gl.cache.face_winding = pip->gl.face_winding;\n            GLenum gl_winding = (SG_FACEWINDING_CW == pip->gl.face_winding) ? GL_CW : GL_CCW;\n            glFrontFace(gl_winding);\n            _sg_stats_add(gl.num_render_state, 1);\n        }\n        if (pip->gl.alpha_to_coverage_enabled != _sg.gl.cache.alpha_to_coverage_enabled) {\n            _sg.gl.cache.alpha_to_coverage_enabled = pip->gl.alpha_to_coverage_enabled;\n            if (pip->gl.alpha_to_coverage_enabled) {\n                glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);\n            } else {\n                glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);\n            }\n            _sg_stats_add(gl.num_render_state, 1);\n        }\n        #ifdef SOKOL_GLCORE\n        if (pip->gl.sample_count != _sg.gl.cache.sample_count) {\n            _sg.gl.cache.sample_count = pip->gl.sample_count;\n            if (pip->gl.sample_count > 1) {\n                glEnable(GL_MULTISAMPLE);\n            } else {\n                glDisable(GL_MULTISAMPLE);\n            }\n            _sg_stats_add(gl.num_render_state, 1);\n        }\n        #endif\n\n        // bind shader program\n        if (pip->shader->gl.prog != _sg.gl.cache.prog) {\n            _sg.gl.cache.prog = pip->shader->gl.prog;\n            glUseProgram(pip->shader->gl.prog);\n            _sg_stats_add(gl.num_use_program, 1);\n        }\n    }\n    _SG_GL_CHECK_ERROR();\n}\n\n_SOKOL_PRIVATE bool _sg_gl_apply_bindings(_sg_bindings_t* bnd) {\n    SOKOL_ASSERT(bnd);\n    SOKOL_ASSERT(bnd->pip);\n    _SG_GL_CHECK_ERROR();\n\n    // bind combined image-samplers\n    _SG_GL_CHECK_ERROR();\n    for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {\n        const _sg_shader_stage_t* stage = &bnd->pip->shader->cmn.stage[stage_index];\n        const _sg_gl_shader_stage_t* gl_stage = &bnd->pip->shader->gl.stage[stage_index];\n        _sg_image_t** imgs = (stage_index == SG_SHADERSTAGE_VS) ? bnd->vs_imgs : bnd->fs_imgs;\n        _sg_sampler_t** smps = (stage_index == SG_SHADERSTAGE_VS) ? bnd->vs_smps : bnd->fs_smps;\n        const int num_imgs = (stage_index == SG_SHADERSTAGE_VS) ? bnd->num_vs_imgs : bnd->num_fs_imgs;\n        const int num_smps = (stage_index == SG_SHADERSTAGE_VS) ? bnd->num_vs_smps : bnd->num_fs_smps;\n        SOKOL_ASSERT(num_imgs == stage->num_images); _SOKOL_UNUSED(num_imgs);\n        SOKOL_ASSERT(num_smps == stage->num_samplers); _SOKOL_UNUSED(num_smps);\n        for (int img_smp_index = 0; img_smp_index < stage->num_image_samplers; img_smp_index++) {\n            const int gl_tex_slot = gl_stage->image_samplers[img_smp_index].gl_tex_slot;\n            if (gl_tex_slot != -1) {\n                const int img_index = stage->image_samplers[img_smp_index].image_slot;\n                const int smp_index = stage->image_samplers[img_smp_index].sampler_slot;\n                SOKOL_ASSERT(img_index < num_imgs);\n                SOKOL_ASSERT(smp_index < num_smps);\n                _sg_image_t* img = imgs[img_index];\n                _sg_sampler_t* smp = smps[smp_index];\n                const GLenum gl_tgt = img->gl.target;\n                const GLuint gl_tex = img->gl.tex[img->cmn.active_slot];\n                const GLuint gl_smp = smp->gl.smp;\n                _sg_gl_cache_bind_texture_sampler(gl_tex_slot, gl_tgt, gl_tex, gl_smp);\n            }\n        }\n    }\n    _SG_GL_CHECK_ERROR();\n\n    // bind storage buffers\n    for (int slot = 0; slot < bnd->num_vs_sbufs; slot++) {\n        _sg_buffer_t* sb = bnd->vs_sbufs[slot];\n        GLuint gl_sb = sb->gl.buf[sb->cmn.active_slot];\n        _sg_gl_cache_bind_storage_buffer(SG_SHADERSTAGE_VS, slot, gl_sb);\n    }\n    for (int slot = 0; slot < bnd->num_fs_sbufs; slot++) {\n        _sg_buffer_t* sb = bnd->fs_sbufs[slot];\n        GLuint gl_sb = sb->gl.buf[sb->cmn.active_slot];\n        _sg_gl_cache_bind_storage_buffer(SG_SHADERSTAGE_FS, slot, gl_sb);\n    }\n\n    // index buffer (can be 0)\n    const GLuint gl_ib = bnd->ib ? bnd->ib->gl.buf[bnd->ib->cmn.active_slot] : 0;\n    _sg_gl_cache_bind_buffer(GL_ELEMENT_ARRAY_BUFFER, gl_ib);\n    _sg.gl.cache.cur_ib_offset = bnd->ib_offset;\n\n    // vertex attributes\n    for (GLuint attr_index = 0; attr_index < (GLuint)_sg.limits.max_vertex_attrs; attr_index++) {\n        _sg_gl_attr_t* attr = &bnd->pip->gl.attrs[attr_index];\n        _sg_gl_cache_attr_t* cache_attr = &_sg.gl.cache.attrs[attr_index];\n        bool cache_attr_dirty = false;\n        int vb_offset = 0;\n        GLuint gl_vb = 0;\n        if (attr->vb_index >= 0) {\n            // attribute is enabled\n            SOKOL_ASSERT(attr->vb_index < bnd->num_vbs);\n            _sg_buffer_t* vb = bnd->vbs[attr->vb_index];\n            SOKOL_ASSERT(vb);\n            gl_vb = vb->gl.buf[vb->cmn.active_slot];\n            vb_offset = bnd->vb_offsets[attr->vb_index] + attr->offset;\n            if ((gl_vb != cache_attr->gl_vbuf) ||\n                (attr->size != cache_attr->gl_attr.size) ||\n                (attr->type != cache_attr->gl_attr.type) ||\n                (attr->normalized != cache_attr->gl_attr.normalized) ||\n                (attr->stride != cache_attr->gl_attr.stride) ||\n                (vb_offset != cache_attr->gl_attr.offset) ||\n                (cache_attr->gl_attr.divisor != attr->divisor))\n            {\n                _sg_gl_cache_bind_buffer(GL_ARRAY_BUFFER, gl_vb);\n                glVertexAttribPointer(attr_index, attr->size, attr->type, attr->normalized, attr->stride, (const GLvoid*)(GLintptr)vb_offset);\n                _sg_stats_add(gl.num_vertex_attrib_pointer, 1);\n                glVertexAttribDivisor(attr_index, (GLuint)attr->divisor);\n                _sg_stats_add(gl.num_vertex_attrib_divisor, 1);\n                cache_attr_dirty = true;\n            }\n            if (cache_attr->gl_attr.vb_index == -1) {\n                glEnableVertexAttribArray(attr_index);\n                _sg_stats_add(gl.num_enable_vertex_attrib_array, 1);\n                cache_attr_dirty = true;\n            }\n        } else {\n            // attribute is disabled\n            if (cache_attr->gl_attr.vb_index != -1) {\n                glDisableVertexAttribArray(attr_index);\n                _sg_stats_add(gl.num_disable_vertex_attrib_array, 1);\n                cache_attr_dirty = true;\n            }\n        }\n        if (cache_attr_dirty) {\n            cache_attr->gl_attr = *attr;\n            cache_attr->gl_attr.offset = vb_offset;\n            cache_attr->gl_vbuf = gl_vb;\n        }\n    }\n    _SG_GL_CHECK_ERROR();\n    return true;\n}\n\n_SOKOL_PRIVATE void _sg_gl_apply_uniforms(sg_shader_stage stage_index, int ub_index, const sg_range* data) {\n    SOKOL_ASSERT(_sg.gl.cache.cur_pipeline);\n    SOKOL_ASSERT(_sg.gl.cache.cur_pipeline->slot.id == _sg.gl.cache.cur_pipeline_id.id);\n    SOKOL_ASSERT(_sg.gl.cache.cur_pipeline->shader->slot.id == _sg.gl.cache.cur_pipeline->cmn.shader_id.id);\n    SOKOL_ASSERT(_sg.gl.cache.cur_pipeline->shader->cmn.stage[stage_index].num_uniform_blocks > ub_index);\n    SOKOL_ASSERT(_sg.gl.cache.cur_pipeline->shader->cmn.stage[stage_index].uniform_blocks[ub_index].size == data->size);\n    const _sg_gl_shader_stage_t* gl_stage = &_sg.gl.cache.cur_pipeline->shader->gl.stage[stage_index];\n    const _sg_gl_uniform_block_t* gl_ub = &gl_stage->uniform_blocks[ub_index];\n    for (int u_index = 0; u_index < gl_ub->num_uniforms; u_index++) {\n        const _sg_gl_uniform_t* u = &gl_ub->uniforms[u_index];\n        SOKOL_ASSERT(u->type != SG_UNIFORMTYPE_INVALID);\n        if (u->gl_loc == -1) {\n            continue;\n        }\n        _sg_stats_add(gl.num_uniform, 1);\n        GLfloat* fptr = (GLfloat*) (((uint8_t*)data->ptr) + u->offset);\n        GLint* iptr = (GLint*) (((uint8_t*)data->ptr) + u->offset);\n        switch (u->type) {\n            case SG_UNIFORMTYPE_INVALID:\n                break;\n            case SG_UNIFORMTYPE_FLOAT:\n                glUniform1fv(u->gl_loc, u->count, fptr);\n                break;\n            case SG_UNIFORMTYPE_FLOAT2:\n                glUniform2fv(u->gl_loc, u->count, fptr);\n                break;\n            case SG_UNIFORMTYPE_FLOAT3:\n                glUniform3fv(u->gl_loc, u->count, fptr);\n                break;\n            case SG_UNIFORMTYPE_FLOAT4:\n                glUniform4fv(u->gl_loc, u->count, fptr);\n                break;\n            case SG_UNIFORMTYPE_INT:\n                glUniform1iv(u->gl_loc, u->count, iptr);\n                break;\n            case SG_UNIFORMTYPE_INT2:\n                glUniform2iv(u->gl_loc, u->count, iptr);\n                break;\n            case SG_UNIFORMTYPE_INT3:\n                glUniform3iv(u->gl_loc, u->count, iptr);\n                break;\n            case SG_UNIFORMTYPE_INT4:\n                glUniform4iv(u->gl_loc, u->count, iptr);\n                break;\n            case SG_UNIFORMTYPE_MAT4:\n                glUniformMatrix4fv(u->gl_loc, u->count, GL_FALSE, fptr);\n                break;\n            default:\n                SOKOL_UNREACHABLE;\n                break;\n        }\n    }\n}\n\n_SOKOL_PRIVATE void _sg_gl_draw(int base_element, int num_elements, int num_instances) {\n    SOKOL_ASSERT(_sg.gl.cache.cur_pipeline);\n    const GLenum i_type = _sg.gl.cache.cur_index_type;\n    const GLenum p_type = _sg.gl.cache.cur_primitive_type;\n    const bool use_instanced_draw = (num_instances > 1) || (_sg.gl.cache.cur_pipeline->cmn.use_instanced_draw);\n    if (0 != i_type) {\n        // indexed rendering\n        const int i_size = (i_type == GL_UNSIGNED_SHORT) ? 2 : 4;\n        const int ib_offset = _sg.gl.cache.cur_ib_offset;\n        const GLvoid* indices = (const GLvoid*)(GLintptr)(base_element*i_size+ib_offset);\n        if (use_instanced_draw) {\n            glDrawElementsInstanced(p_type, num_elements, i_type, indices, num_instances);\n        } else {\n            glDrawElements(p_type, num_elements, i_type, indices);\n        }\n    } else {\n        // non-indexed rendering\n        if (use_instanced_draw) {\n            glDrawArraysInstanced(p_type, base_element, num_elements, num_instances);\n        } else {\n            glDrawArrays(p_type, base_element, num_elements);\n        }\n    }\n}\n\n_SOKOL_PRIVATE void _sg_gl_commit(void) {\n    // \"soft\" clear bindings (only those that are actually bound)\n    _sg_gl_cache_clear_buffer_bindings(false);\n    _sg_gl_cache_clear_texture_sampler_bindings(false);\n}\n\n_SOKOL_PRIVATE void _sg_gl_update_buffer(_sg_buffer_t* buf, const sg_range* data) {\n    SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0));\n    // only one update per buffer per frame allowed\n    if (++buf->cmn.active_slot >= buf->cmn.num_slots) {\n        buf->cmn.active_slot = 0;\n    }\n    GLenum gl_tgt = _sg_gl_buffer_target(buf->cmn.type);\n    SOKOL_ASSERT(buf->cmn.active_slot < SG_NUM_INFLIGHT_FRAMES);\n    GLuint gl_buf = buf->gl.buf[buf->cmn.active_slot];\n    SOKOL_ASSERT(gl_buf);\n    _SG_GL_CHECK_ERROR();\n    _sg_gl_cache_store_buffer_binding(gl_tgt);\n    _sg_gl_cache_bind_buffer(gl_tgt, gl_buf);\n    glBufferSubData(gl_tgt, 0, (GLsizeiptr)data->size, data->ptr);\n    _sg_gl_cache_restore_buffer_binding(gl_tgt);\n    _SG_GL_CHECK_ERROR();\n}\n\n_SOKOL_PRIVATE void _sg_gl_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) {\n    SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0));\n    if (new_frame) {\n        if (++buf->cmn.active_slot >= buf->cmn.num_slots) {\n            buf->cmn.active_slot = 0;\n        }\n    }\n    GLenum gl_tgt = _sg_gl_buffer_target(buf->cmn.type);\n    SOKOL_ASSERT(buf->cmn.active_slot < SG_NUM_INFLIGHT_FRAMES);\n    GLuint gl_buf = buf->gl.buf[buf->cmn.active_slot];\n    SOKOL_ASSERT(gl_buf);\n    _SG_GL_CHECK_ERROR();\n    _sg_gl_cache_store_buffer_binding(gl_tgt);\n    _sg_gl_cache_bind_buffer(gl_tgt, gl_buf);\n    glBufferSubData(gl_tgt, buf->cmn.append_pos, (GLsizeiptr)data->size, data->ptr);\n    _sg_gl_cache_restore_buffer_binding(gl_tgt);\n    _SG_GL_CHECK_ERROR();\n}\n\n_SOKOL_PRIVATE void _sg_gl_update_image(_sg_image_t* img, const sg_image_data* data) {\n    SOKOL_ASSERT(img && data);\n    // only one update per image per frame allowed\n    if (++img->cmn.active_slot >= img->cmn.num_slots) {\n        img->cmn.active_slot = 0;\n    }\n    SOKOL_ASSERT(img->cmn.active_slot < SG_NUM_INFLIGHT_FRAMES);\n    SOKOL_ASSERT(0 != img->gl.tex[img->cmn.active_slot]);\n    _sg_gl_cache_store_texture_sampler_binding(0);\n    _sg_gl_cache_bind_texture_sampler(0, img->gl.target, img->gl.tex[img->cmn.active_slot], 0);\n    const GLenum gl_img_format = _sg_gl_teximage_format(img->cmn.pixel_format);\n    const GLenum gl_img_type = _sg_gl_teximage_type(img->cmn.pixel_format);\n    const int num_faces = img->cmn.type == SG_IMAGETYPE_CUBE ? 6 : 1;\n    const int num_mips = img->cmn.num_mipmaps;\n    for (int face_index = 0; face_index < num_faces; face_index++) {\n        for (int mip_index = 0; mip_index < num_mips; mip_index++) {\n            GLenum gl_img_target = img->gl.target;\n            if (SG_IMAGETYPE_CUBE == img->cmn.type) {\n                gl_img_target = _sg_gl_cubeface_target(face_index);\n            }\n            const GLvoid* data_ptr = data->subimage[face_index][mip_index].ptr;\n            int mip_width = _sg_miplevel_dim(img->cmn.width, mip_index);\n            int mip_height = _sg_miplevel_dim(img->cmn.height, mip_index);\n            if ((SG_IMAGETYPE_2D == img->cmn.type) || (SG_IMAGETYPE_CUBE == img->cmn.type)) {\n                glTexSubImage2D(gl_img_target, mip_index,\n                    0, 0,\n                    mip_width, mip_height,\n                    gl_img_format, gl_img_type,\n                    data_ptr);\n            } else if ((SG_IMAGETYPE_3D == img->cmn.type) || (SG_IMAGETYPE_ARRAY == img->cmn.type)) {\n                int mip_depth = img->cmn.num_slices;\n                if (SG_IMAGETYPE_3D == img->cmn.type) {\n                    mip_depth = _sg_miplevel_dim(img->cmn.num_slices, mip_index);\n                }\n                glTexSubImage3D(gl_img_target, mip_index,\n                    0, 0, 0,\n                    mip_width, mip_height, mip_depth,\n                    gl_img_format, gl_img_type,\n                    data_ptr);\n\n            }\n        }\n    }\n    _sg_gl_cache_restore_texture_sampler_binding(0);\n}\n\n// ██████  ██████  ██████   ██  ██     ██████   █████   ██████ ██   ██ ███████ ███    ██ ██████\n// ██   ██      ██ ██   ██ ███ ███     ██   ██ ██   ██ ██      ██  ██  ██      ████   ██ ██   ██\n// ██   ██  █████  ██   ██  ██  ██     ██████  ███████ ██      █████   █████   ██ ██  ██ ██   ██\n// ██   ██      ██ ██   ██  ██  ██     ██   ██ ██   ██ ██      ██  ██  ██      ██  ██ ██ ██   ██\n// ██████  ██████  ██████   ██  ██     ██████  ██   ██  ██████ ██   ██ ███████ ██   ████ ██████\n//\n// >>d3d11 backend\n#elif defined(SOKOL_D3D11)\n\n#define _SG_D3D11_MAX_SHADERSTAGE_SRVS (32)\n#define _SG_D3D11_SHADERSTAGE_IMAGE_SRV_OFFSET (0)\n#define _SG_D3D11_SHADERSTAGE_BUFFER_SRV_OFFSET (16)\n\n#if defined(__cplusplus)\n#define _sg_d3d11_AddRef(self) (self)->AddRef()\n#else\n#define _sg_d3d11_AddRef(self) (self)->lpVtbl->AddRef(self)\n#endif\n\n#if defined(__cplusplus)\n#define _sg_d3d11_Release(self) (self)->Release()\n#else\n#define _sg_d3d11_Release(self) (self)->lpVtbl->Release(self)\n#endif\n\n// NOTE: This needs to be a macro since we can't use the polymorphism in C. It's called on many kinds of resources.\n// NOTE: Based on microsoft docs, it's fine to call this with pData=NULL if DataSize is also zero.\n#if defined(__cplusplus)\n#define _sg_d3d11_SetPrivateData(self, guid, DataSize, pData) (self)->SetPrivateData(guid, DataSize, pData)\n#else\n#define _sg_d3d11_SetPrivateData(self, guid, DataSize, pData) (self)->lpVtbl->SetPrivateData(self, guid, DataSize, pData)\n#endif\n\n#if defined(__cplusplus)\n#define _sg_win32_refguid(guid) guid\n#else\n#define _sg_win32_refguid(guid) &guid\n#endif\n\nstatic const GUID _sg_d3d11_WKPDID_D3DDebugObjectName = { 0x429b8c22,0x9188,0x4b0c, {0x87,0x42,0xac,0xb0,0xbf,0x85,0xc2,0x00} };\n\n#if defined(SOKOL_DEBUG)\n#define _sg_d3d11_setlabel(self, label) _sg_d3d11_SetPrivateData(self, _sg_win32_refguid(_sg_d3d11_WKPDID_D3DDebugObjectName), label ? (UINT)strlen(label) : 0, label)\n#else\n#define _sg_d3d11_setlabel(self, label)\n#endif\n\n\n//-- D3D11 C/C++ wrappers ------------------------------------------------------\nstatic inline HRESULT _sg_d3d11_CheckFormatSupport(ID3D11Device* self, DXGI_FORMAT Format, UINT* pFormatSupport) {\n    #if defined(__cplusplus)\n        return self->CheckFormatSupport(Format, pFormatSupport);\n    #else\n        return self->lpVtbl->CheckFormatSupport(self, Format, pFormatSupport);\n    #endif\n}\n\nstatic inline void _sg_d3d11_OMSetRenderTargets(ID3D11DeviceContext* self, UINT NumViews, ID3D11RenderTargetView* const* ppRenderTargetViews, ID3D11DepthStencilView *pDepthStencilView) {\n    #if defined(__cplusplus)\n        self->OMSetRenderTargets(NumViews, ppRenderTargetViews, pDepthStencilView);\n    #else\n        self->lpVtbl->OMSetRenderTargets(self, NumViews, ppRenderTargetViews, pDepthStencilView);\n    #endif\n}\n\nstatic inline void _sg_d3d11_RSSetState(ID3D11DeviceContext* self, ID3D11RasterizerState* pRasterizerState) {\n    #if defined(__cplusplus)\n        self->RSSetState(pRasterizerState);\n    #else\n        self->lpVtbl->RSSetState(self, pRasterizerState);\n    #endif\n}\n\nstatic inline void _sg_d3d11_OMSetDepthStencilState(ID3D11DeviceContext* self, ID3D11DepthStencilState* pDepthStencilState, UINT StencilRef) {\n    #if defined(__cplusplus)\n        self->OMSetDepthStencilState(pDepthStencilState, StencilRef);\n    #else\n        self->lpVtbl->OMSetDepthStencilState(self, pDepthStencilState, StencilRef);\n    #endif\n}\n\nstatic inline void _sg_d3d11_OMSetBlendState(ID3D11DeviceContext* self, ID3D11BlendState* pBlendState, const FLOAT BlendFactor[4], UINT SampleMask) {\n    #if defined(__cplusplus)\n        self->OMSetBlendState(pBlendState, BlendFactor, SampleMask);\n    #else\n        self->lpVtbl->OMSetBlendState(self, pBlendState, BlendFactor, SampleMask);\n    #endif\n}\n\nstatic inline void _sg_d3d11_IASetVertexBuffers(ID3D11DeviceContext* self, UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppVertexBuffers, const UINT* pStrides, const UINT* pOffsets) {\n    #if defined(__cplusplus)\n        self->IASetVertexBuffers(StartSlot, NumBuffers, ppVertexBuffers, pStrides, pOffsets);\n    #else\n        self->lpVtbl->IASetVertexBuffers(self, StartSlot, NumBuffers, ppVertexBuffers, pStrides, pOffsets);\n    #endif\n}\n\nstatic inline void _sg_d3d11_IASetIndexBuffer(ID3D11DeviceContext* self, ID3D11Buffer* pIndexBuffer, DXGI_FORMAT Format, UINT Offset) {\n    #if defined(__cplusplus)\n        self->IASetIndexBuffer(pIndexBuffer, Format, Offset);\n    #else\n        self->lpVtbl->IASetIndexBuffer(self, pIndexBuffer, Format, Offset);\n    #endif\n}\n\nstatic inline void _sg_d3d11_IASetInputLayout(ID3D11DeviceContext* self, ID3D11InputLayout* pInputLayout) {\n    #if defined(__cplusplus)\n        self->IASetInputLayout(pInputLayout);\n    #else\n        self->lpVtbl->IASetInputLayout(self, pInputLayout);\n    #endif\n}\n\nstatic inline void _sg_d3d11_VSSetShader(ID3D11DeviceContext* self, ID3D11VertexShader* pVertexShader, ID3D11ClassInstance* const* ppClassInstances, UINT NumClassInstances) {\n    #if defined(__cplusplus)\n        self->VSSetShader(pVertexShader, ppClassInstances, NumClassInstances);\n    #else\n        self->lpVtbl->VSSetShader(self, pVertexShader, ppClassInstances, NumClassInstances);\n    #endif\n}\n\nstatic inline void _sg_d3d11_PSSetShader(ID3D11DeviceContext* self, ID3D11PixelShader* pPixelShader, ID3D11ClassInstance* const* ppClassInstances, UINT NumClassInstances) {\n    #if defined(__cplusplus)\n        self->PSSetShader(pPixelShader, ppClassInstances, NumClassInstances);\n    #else\n        self->lpVtbl->PSSetShader(self, pPixelShader, ppClassInstances, NumClassInstances);\n    #endif\n}\n\nstatic inline void _sg_d3d11_VSSetConstantBuffers(ID3D11DeviceContext* self, UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers) {\n    #if defined(__cplusplus)\n        self->VSSetConstantBuffers(StartSlot, NumBuffers, ppConstantBuffers);\n    #else\n        self->lpVtbl->VSSetConstantBuffers(self, StartSlot, NumBuffers, ppConstantBuffers);\n    #endif\n}\n\nstatic inline void _sg_d3d11_PSSetConstantBuffers(ID3D11DeviceContext* self, UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers) {\n    #if defined(__cplusplus)\n        self->PSSetConstantBuffers(StartSlot, NumBuffers, ppConstantBuffers);\n    #else\n        self->lpVtbl->PSSetConstantBuffers(self, StartSlot, NumBuffers, ppConstantBuffers);\n    #endif\n}\n\nstatic inline void _sg_d3d11_VSSetShaderResources(ID3D11DeviceContext* self, UINT StartSlot, UINT NumViews, ID3D11ShaderResourceView* const* ppShaderResourceViews) {\n    #if defined(__cplusplus)\n        self->VSSetShaderResources(StartSlot, NumViews, ppShaderResourceViews);\n    #else\n        self->lpVtbl->VSSetShaderResources(self, StartSlot, NumViews, ppShaderResourceViews);\n    #endif\n}\n\nstatic inline void _sg_d3d11_PSSetShaderResources(ID3D11DeviceContext* self, UINT StartSlot, UINT NumViews, ID3D11ShaderResourceView* const* ppShaderResourceViews) {\n    #if defined(__cplusplus)\n        self->PSSetShaderResources(StartSlot, NumViews, ppShaderResourceViews);\n    #else\n        self->lpVtbl->PSSetShaderResources(self, StartSlot, NumViews, ppShaderResourceViews);\n    #endif\n}\n\nstatic inline void _sg_d3d11_VSSetSamplers(ID3D11DeviceContext* self, UINT StartSlot, UINT NumSamplers, ID3D11SamplerState* const* ppSamplers) {\n    #if defined(__cplusplus)\n        self->VSSetSamplers(StartSlot, NumSamplers, ppSamplers);\n    #else\n        self->lpVtbl->VSSetSamplers(self, StartSlot, NumSamplers, ppSamplers);\n    #endif\n}\n\nstatic inline void _sg_d3d11_PSSetSamplers(ID3D11DeviceContext* self, UINT StartSlot, UINT NumSamplers, ID3D11SamplerState* const* ppSamplers) {\n    #if defined(__cplusplus)\n        self->PSSetSamplers(StartSlot, NumSamplers, ppSamplers);\n    #else\n        self->lpVtbl->PSSetSamplers(self, StartSlot, NumSamplers, ppSamplers);\n    #endif\n}\n\nstatic inline HRESULT _sg_d3d11_CreateBuffer(ID3D11Device* self, const D3D11_BUFFER_DESC* pDesc, const D3D11_SUBRESOURCE_DATA* pInitialData, ID3D11Buffer** ppBuffer) {\n    #if defined(__cplusplus)\n        return self->CreateBuffer(pDesc, pInitialData, ppBuffer);\n    #else\n        return self->lpVtbl->CreateBuffer(self, pDesc, pInitialData, ppBuffer);\n    #endif\n}\n\nstatic inline HRESULT _sg_d3d11_CreateTexture2D(ID3D11Device* self, const D3D11_TEXTURE2D_DESC* pDesc, const D3D11_SUBRESOURCE_DATA* pInitialData, ID3D11Texture2D** ppTexture2D) {\n    #if defined(__cplusplus)\n        return self->CreateTexture2D(pDesc, pInitialData, ppTexture2D);\n    #else\n        return self->lpVtbl->CreateTexture2D(self, pDesc, pInitialData, ppTexture2D);\n    #endif\n}\n\nstatic inline HRESULT _sg_d3d11_CreateShaderResourceView(ID3D11Device* self, ID3D11Resource* pResource, const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, ID3D11ShaderResourceView** ppSRView) {\n    #if defined(__cplusplus)\n        return self->CreateShaderResourceView(pResource, pDesc, ppSRView);\n    #else\n        return self->lpVtbl->CreateShaderResourceView(self, pResource, pDesc, ppSRView);\n    #endif\n}\n\nstatic inline void _sg_d3d11_GetResource(ID3D11View* self, ID3D11Resource** ppResource) {\n    #if defined(__cplusplus)\n        self->GetResource(ppResource);\n    #else\n        self->lpVtbl->GetResource(self, ppResource);\n    #endif\n}\n\nstatic inline HRESULT _sg_d3d11_CreateTexture3D(ID3D11Device* self, const D3D11_TEXTURE3D_DESC* pDesc, const D3D11_SUBRESOURCE_DATA* pInitialData, ID3D11Texture3D** ppTexture3D) {\n    #if defined(__cplusplus)\n        return self->CreateTexture3D(pDesc, pInitialData, ppTexture3D);\n    #else\n        return self->lpVtbl->CreateTexture3D(self, pDesc, pInitialData, ppTexture3D);\n    #endif\n}\n\nstatic inline HRESULT _sg_d3d11_CreateSamplerState(ID3D11Device* self, const D3D11_SAMPLER_DESC* pSamplerDesc, ID3D11SamplerState** ppSamplerState) {\n    #if defined(__cplusplus)\n        return self->CreateSamplerState(pSamplerDesc, ppSamplerState);\n    #else\n        return self->lpVtbl->CreateSamplerState(self, pSamplerDesc, ppSamplerState);\n    #endif\n}\n\nstatic inline LPVOID _sg_d3d11_GetBufferPointer(ID3D10Blob* self) {\n    #if defined(__cplusplus)\n        return self->GetBufferPointer();\n    #else\n        return self->lpVtbl->GetBufferPointer(self);\n    #endif\n}\n\nstatic inline SIZE_T _sg_d3d11_GetBufferSize(ID3D10Blob* self) {\n    #if defined(__cplusplus)\n        return self->GetBufferSize();\n    #else\n        return self->lpVtbl->GetBufferSize(self);\n    #endif\n}\n\nstatic inline HRESULT _sg_d3d11_CreateVertexShader(ID3D11Device* self, const void* pShaderBytecode, SIZE_T BytecodeLength, ID3D11ClassLinkage* pClassLinkage, ID3D11VertexShader** ppVertexShader) {\n    #if defined(__cplusplus)\n        return self->CreateVertexShader(pShaderBytecode, BytecodeLength, pClassLinkage, ppVertexShader);\n    #else\n        return self->lpVtbl->CreateVertexShader(self, pShaderBytecode, BytecodeLength, pClassLinkage, ppVertexShader);\n    #endif\n}\n\nstatic inline HRESULT _sg_d3d11_CreatePixelShader(ID3D11Device* self, const void* pShaderBytecode, SIZE_T BytecodeLength, ID3D11ClassLinkage* pClassLinkage, ID3D11PixelShader** ppPixelShader) {\n    #if defined(__cplusplus)\n        return self->CreatePixelShader(pShaderBytecode, BytecodeLength, pClassLinkage, ppPixelShader);\n    #else\n        return self->lpVtbl->CreatePixelShader(self, pShaderBytecode, BytecodeLength, pClassLinkage, ppPixelShader);\n    #endif\n}\n\nstatic inline HRESULT _sg_d3d11_CreateInputLayout(ID3D11Device* self, const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs, UINT NumElements, const void* pShaderBytecodeWithInputSignature, SIZE_T BytecodeLength, ID3D11InputLayout **ppInputLayout) {\n    #if defined(__cplusplus)\n        return self->CreateInputLayout(pInputElementDescs, NumElements, pShaderBytecodeWithInputSignature, BytecodeLength, ppInputLayout);\n    #else\n        return self->lpVtbl->CreateInputLayout(self, pInputElementDescs, NumElements, pShaderBytecodeWithInputSignature, BytecodeLength, ppInputLayout);\n    #endif\n}\n\nstatic inline HRESULT _sg_d3d11_CreateRasterizerState(ID3D11Device* self, const D3D11_RASTERIZER_DESC* pRasterizerDesc, ID3D11RasterizerState** ppRasterizerState) {\n    #if defined(__cplusplus)\n        return self->CreateRasterizerState(pRasterizerDesc, ppRasterizerState);\n    #else\n        return self->lpVtbl->CreateRasterizerState(self, pRasterizerDesc, ppRasterizerState);\n    #endif\n}\n\nstatic inline HRESULT _sg_d3d11_CreateDepthStencilState(ID3D11Device* self, const D3D11_DEPTH_STENCIL_DESC* pDepthStencilDesc, ID3D11DepthStencilState** ppDepthStencilState) {\n    #if defined(__cplusplus)\n        return self->CreateDepthStencilState(pDepthStencilDesc, ppDepthStencilState);\n    #else\n        return self->lpVtbl->CreateDepthStencilState(self, pDepthStencilDesc, ppDepthStencilState);\n    #endif\n}\n\nstatic inline HRESULT _sg_d3d11_CreateBlendState(ID3D11Device* self, const D3D11_BLEND_DESC* pBlendStateDesc, ID3D11BlendState** ppBlendState) {\n    #if defined(__cplusplus)\n        return self->CreateBlendState(pBlendStateDesc, ppBlendState);\n    #else\n        return self->lpVtbl->CreateBlendState(self, pBlendStateDesc, ppBlendState);\n    #endif\n}\n\nstatic inline HRESULT _sg_d3d11_CreateRenderTargetView(ID3D11Device* self, ID3D11Resource *pResource, const D3D11_RENDER_TARGET_VIEW_DESC* pDesc, ID3D11RenderTargetView** ppRTView) {\n    #if defined(__cplusplus)\n        return self->CreateRenderTargetView(pResource, pDesc, ppRTView);\n    #else\n        return self->lpVtbl->CreateRenderTargetView(self, pResource, pDesc, ppRTView);\n    #endif\n}\n\nstatic inline HRESULT _sg_d3d11_CreateDepthStencilView(ID3D11Device* self, ID3D11Resource* pResource, const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc, ID3D11DepthStencilView** ppDepthStencilView) {\n    #if defined(__cplusplus)\n        return self->CreateDepthStencilView(pResource, pDesc, ppDepthStencilView);\n    #else\n        return self->lpVtbl->CreateDepthStencilView(self, pResource, pDesc, ppDepthStencilView);\n    #endif\n}\n\nstatic inline void _sg_d3d11_RSSetViewports(ID3D11DeviceContext* self, UINT NumViewports, const D3D11_VIEWPORT* pViewports) {\n    #if defined(__cplusplus)\n        self->RSSetViewports(NumViewports, pViewports);\n    #else\n        self->lpVtbl->RSSetViewports(self, NumViewports, pViewports);\n    #endif\n}\n\nstatic inline void _sg_d3d11_RSSetScissorRects(ID3D11DeviceContext* self, UINT NumRects, const D3D11_RECT* pRects) {\n    #if defined(__cplusplus)\n        self->RSSetScissorRects(NumRects, pRects);\n    #else\n        self->lpVtbl->RSSetScissorRects(self, NumRects, pRects);\n    #endif\n}\n\nstatic inline void _sg_d3d11_ClearRenderTargetView(ID3D11DeviceContext* self, ID3D11RenderTargetView* pRenderTargetView, const FLOAT ColorRGBA[4]) {\n    #if defined(__cplusplus)\n        self->ClearRenderTargetView(pRenderTargetView, ColorRGBA);\n    #else\n        self->lpVtbl->ClearRenderTargetView(self, pRenderTargetView, ColorRGBA);\n    #endif\n}\n\nstatic inline void _sg_d3d11_ClearDepthStencilView(ID3D11DeviceContext* self, ID3D11DepthStencilView* pDepthStencilView, UINT ClearFlags, FLOAT Depth, UINT8 Stencil) {\n    #if defined(__cplusplus)\n        self->ClearDepthStencilView(pDepthStencilView, ClearFlags, Depth, Stencil);\n    #else\n        self->lpVtbl->ClearDepthStencilView(self, pDepthStencilView, ClearFlags, Depth, Stencil);\n    #endif\n}\n\nstatic inline void _sg_d3d11_ResolveSubresource(ID3D11DeviceContext* self, ID3D11Resource* pDstResource, UINT DstSubresource, ID3D11Resource* pSrcResource, UINT SrcSubresource, DXGI_FORMAT Format) {\n    #if defined(__cplusplus)\n        self->ResolveSubresource(pDstResource, DstSubresource, pSrcResource, SrcSubresource, Format);\n    #else\n        self->lpVtbl->ResolveSubresource(self, pDstResource, DstSubresource, pSrcResource, SrcSubresource, Format);\n    #endif\n}\n\nstatic inline void _sg_d3d11_IASetPrimitiveTopology(ID3D11DeviceContext* self, D3D11_PRIMITIVE_TOPOLOGY Topology) {\n    #if defined(__cplusplus)\n        self->IASetPrimitiveTopology(Topology);\n    #else\n        self->lpVtbl->IASetPrimitiveTopology(self, Topology);\n    #endif\n}\n\nstatic inline void _sg_d3d11_UpdateSubresource(ID3D11DeviceContext* self, ID3D11Resource* pDstResource, UINT DstSubresource, const D3D11_BOX* pDstBox, const void* pSrcData, UINT SrcRowPitch, UINT SrcDepthPitch) {\n    #if defined(__cplusplus)\n        self->UpdateSubresource(pDstResource, DstSubresource, pDstBox, pSrcData, SrcRowPitch, SrcDepthPitch);\n    #else\n        self->lpVtbl->UpdateSubresource(self, pDstResource, DstSubresource, pDstBox, pSrcData, SrcRowPitch, SrcDepthPitch);\n    #endif\n}\n\nstatic inline void _sg_d3d11_DrawIndexed(ID3D11DeviceContext* self, UINT IndexCount, UINT StartIndexLocation, INT  BaseVertexLocation) {\n    #if defined(__cplusplus)\n        self->DrawIndexed(IndexCount, StartIndexLocation, BaseVertexLocation);\n    #else\n        self->lpVtbl->DrawIndexed(self, IndexCount, StartIndexLocation, BaseVertexLocation);\n    #endif\n}\n\nstatic inline void _sg_d3d11_DrawIndexedInstanced(ID3D11DeviceContext* self, UINT IndexCountPerInstance, UINT InstanceCount, UINT StartIndexLocation, INT BaseVertexLocation, UINT StartInstanceLocation) {\n    #if defined(__cplusplus)\n        self->DrawIndexedInstanced(IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation);\n    #else\n        self->lpVtbl->DrawIndexedInstanced(self, IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation);\n    #endif\n}\n\nstatic inline void _sg_d3d11_Draw(ID3D11DeviceContext* self, UINT VertexCount, UINT StartVertexLocation) {\n    #if defined(__cplusplus)\n        self->Draw(VertexCount, StartVertexLocation);\n    #else\n        self->lpVtbl->Draw(self, VertexCount, StartVertexLocation);\n    #endif\n}\n\nstatic inline void _sg_d3d11_DrawInstanced(ID3D11DeviceContext* self, UINT VertexCountPerInstance, UINT InstanceCount, UINT StartVertexLocation, UINT StartInstanceLocation) {\n    #if defined(__cplusplus)\n        self->DrawInstanced(VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation);\n    #else\n        self->lpVtbl->DrawInstanced(self, VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation);\n    #endif\n}\n\nstatic inline HRESULT _sg_d3d11_Map(ID3D11DeviceContext* self, ID3D11Resource* pResource, UINT Subresource, D3D11_MAP MapType, UINT MapFlags, D3D11_MAPPED_SUBRESOURCE* pMappedResource) {\n    #if defined(__cplusplus)\n        return self->Map(pResource, Subresource, MapType, MapFlags, pMappedResource);\n    #else\n        return self->lpVtbl->Map(self, pResource, Subresource, MapType, MapFlags, pMappedResource);\n    #endif\n}\n\nstatic inline void _sg_d3d11_Unmap(ID3D11DeviceContext* self, ID3D11Resource* pResource, UINT Subresource) {\n    #if defined(__cplusplus)\n        self->Unmap(pResource, Subresource);\n    #else\n        self->lpVtbl->Unmap(self, pResource, Subresource);\n    #endif\n}\n\nstatic inline void _sg_d3d11_ClearState(ID3D11DeviceContext* self) {\n    #if defined(__cplusplus)\n        self->ClearState();\n    #else\n        self->lpVtbl->ClearState(self);\n    #endif\n}\n\n//-- enum translation functions ------------------------------------------------\n_SOKOL_PRIVATE D3D11_USAGE _sg_d3d11_usage(sg_usage usg) {\n    switch (usg) {\n        case SG_USAGE_IMMUTABLE:\n            return D3D11_USAGE_IMMUTABLE;\n        case SG_USAGE_DYNAMIC:\n        case SG_USAGE_STREAM:\n            return D3D11_USAGE_DYNAMIC;\n        default:\n            SOKOL_UNREACHABLE;\n            return (D3D11_USAGE) 0;\n    }\n}\n\n_SOKOL_PRIVATE UINT _sg_d3d11_buffer_bind_flags(sg_buffer_type t) {\n    switch (t) {\n        case SG_BUFFERTYPE_VERTEXBUFFER:\n            return D3D11_BIND_VERTEX_BUFFER;\n        case SG_BUFFERTYPE_INDEXBUFFER:\n            return D3D11_BIND_INDEX_BUFFER;\n        case SG_BUFFERTYPE_STORAGEBUFFER:\n            // FIXME: for compute shaders we'd want UNORDERED_ACCESS?\n            return D3D11_BIND_SHADER_RESOURCE;\n        default:\n            SOKOL_UNREACHABLE;\n            return 0;\n    }\n}\n\n_SOKOL_PRIVATE UINT _sg_d3d11_buffer_misc_flags(sg_buffer_type t) {\n    switch (t) {\n        case SG_BUFFERTYPE_VERTEXBUFFER:\n        case SG_BUFFERTYPE_INDEXBUFFER:\n            return 0;\n        case SG_BUFFERTYPE_STORAGEBUFFER:\n            return D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;\n        default:\n            SOKOL_UNREACHABLE;\n            return 0;\n    }\n}\n\n_SOKOL_PRIVATE UINT _sg_d3d11_cpu_access_flags(sg_usage usg) {\n    switch (usg) {\n        case SG_USAGE_IMMUTABLE:\n            return 0;\n        case SG_USAGE_DYNAMIC:\n        case SG_USAGE_STREAM:\n            return D3D11_CPU_ACCESS_WRITE;\n        default:\n            SOKOL_UNREACHABLE;\n            return 0;\n    }\n}\n\n_SOKOL_PRIVATE DXGI_FORMAT _sg_d3d11_texture_pixel_format(sg_pixel_format fmt) {\n    switch (fmt) {\n        case SG_PIXELFORMAT_R8:             return DXGI_FORMAT_R8_UNORM;\n        case SG_PIXELFORMAT_R8SN:           return DXGI_FORMAT_R8_SNORM;\n        case SG_PIXELFORMAT_R8UI:           return DXGI_FORMAT_R8_UINT;\n        case SG_PIXELFORMAT_R8SI:           return DXGI_FORMAT_R8_SINT;\n        case SG_PIXELFORMAT_R16:            return DXGI_FORMAT_R16_UNORM;\n        case SG_PIXELFORMAT_R16SN:          return DXGI_FORMAT_R16_SNORM;\n        case SG_PIXELFORMAT_R16UI:          return DXGI_FORMAT_R16_UINT;\n        case SG_PIXELFORMAT_R16SI:          return DXGI_FORMAT_R16_SINT;\n        case SG_PIXELFORMAT_R16F:           return DXGI_FORMAT_R16_FLOAT;\n        case SG_PIXELFORMAT_RG8:            return DXGI_FORMAT_R8G8_UNORM;\n        case SG_PIXELFORMAT_RG8SN:          return DXGI_FORMAT_R8G8_SNORM;\n        case SG_PIXELFORMAT_RG8UI:          return DXGI_FORMAT_R8G8_UINT;\n        case SG_PIXELFORMAT_RG8SI:          return DXGI_FORMAT_R8G8_SINT;\n        case SG_PIXELFORMAT_R32UI:          return DXGI_FORMAT_R32_UINT;\n        case SG_PIXELFORMAT_R32SI:          return DXGI_FORMAT_R32_SINT;\n        case SG_PIXELFORMAT_R32F:           return DXGI_FORMAT_R32_FLOAT;\n        case SG_PIXELFORMAT_RG16:           return DXGI_FORMAT_R16G16_UNORM;\n        case SG_PIXELFORMAT_RG16SN:         return DXGI_FORMAT_R16G16_SNORM;\n        case SG_PIXELFORMAT_RG16UI:         return DXGI_FORMAT_R16G16_UINT;\n        case SG_PIXELFORMAT_RG16SI:         return DXGI_FORMAT_R16G16_SINT;\n        case SG_PIXELFORMAT_RG16F:          return DXGI_FORMAT_R16G16_FLOAT;\n        case SG_PIXELFORMAT_RGBA8:          return DXGI_FORMAT_R8G8B8A8_UNORM;\n        case SG_PIXELFORMAT_SRGB8A8:        return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;\n        case SG_PIXELFORMAT_RGBA8SN:        return DXGI_FORMAT_R8G8B8A8_SNORM;\n        case SG_PIXELFORMAT_RGBA8UI:        return DXGI_FORMAT_R8G8B8A8_UINT;\n        case SG_PIXELFORMAT_RGBA8SI:        return DXGI_FORMAT_R8G8B8A8_SINT;\n        case SG_PIXELFORMAT_BGRA8:          return DXGI_FORMAT_B8G8R8A8_UNORM;\n        case SG_PIXELFORMAT_RGB10A2:        return DXGI_FORMAT_R10G10B10A2_UNORM;\n        case SG_PIXELFORMAT_RG11B10F:       return DXGI_FORMAT_R11G11B10_FLOAT;\n        case SG_PIXELFORMAT_RGB9E5:         return DXGI_FORMAT_R9G9B9E5_SHAREDEXP;\n        case SG_PIXELFORMAT_RG32UI:         return DXGI_FORMAT_R32G32_UINT;\n        case SG_PIXELFORMAT_RG32SI:         return DXGI_FORMAT_R32G32_SINT;\n        case SG_PIXELFORMAT_RG32F:          return DXGI_FORMAT_R32G32_FLOAT;\n        case SG_PIXELFORMAT_RGBA16:         return DXGI_FORMAT_R16G16B16A16_UNORM;\n        case SG_PIXELFORMAT_RGBA16SN:       return DXGI_FORMAT_R16G16B16A16_SNORM;\n        case SG_PIXELFORMAT_RGBA16UI:       return DXGI_FORMAT_R16G16B16A16_UINT;\n        case SG_PIXELFORMAT_RGBA16SI:       return DXGI_FORMAT_R16G16B16A16_SINT;\n        case SG_PIXELFORMAT_RGBA16F:        return DXGI_FORMAT_R16G16B16A16_FLOAT;\n        case SG_PIXELFORMAT_RGBA32UI:       return DXGI_FORMAT_R32G32B32A32_UINT;\n        case SG_PIXELFORMAT_RGBA32SI:       return DXGI_FORMAT_R32G32B32A32_SINT;\n        case SG_PIXELFORMAT_RGBA32F:        return DXGI_FORMAT_R32G32B32A32_FLOAT;\n        case SG_PIXELFORMAT_DEPTH:          return DXGI_FORMAT_R32_TYPELESS;\n        case SG_PIXELFORMAT_DEPTH_STENCIL:  return DXGI_FORMAT_R24G8_TYPELESS;\n        case SG_PIXELFORMAT_BC1_RGBA:       return DXGI_FORMAT_BC1_UNORM;\n        case SG_PIXELFORMAT_BC2_RGBA:       return DXGI_FORMAT_BC2_UNORM;\n        case SG_PIXELFORMAT_BC3_RGBA:       return DXGI_FORMAT_BC3_UNORM;\n        case SG_PIXELFORMAT_BC3_SRGBA:      return DXGI_FORMAT_BC3_UNORM_SRGB;\n        case SG_PIXELFORMAT_BC4_R:          return DXGI_FORMAT_BC4_UNORM;\n        case SG_PIXELFORMAT_BC4_RSN:        return DXGI_FORMAT_BC4_SNORM;\n        case SG_PIXELFORMAT_BC5_RG:         return DXGI_FORMAT_BC5_UNORM;\n        case SG_PIXELFORMAT_BC5_RGSN:       return DXGI_FORMAT_BC5_SNORM;\n        case SG_PIXELFORMAT_BC6H_RGBF:      return DXGI_FORMAT_BC6H_SF16;\n        case SG_PIXELFORMAT_BC6H_RGBUF:     return DXGI_FORMAT_BC6H_UF16;\n        case SG_PIXELFORMAT_BC7_RGBA:       return DXGI_FORMAT_BC7_UNORM;\n        case SG_PIXELFORMAT_BC7_SRGBA:      return DXGI_FORMAT_BC7_UNORM_SRGB;\n        default:                            return DXGI_FORMAT_UNKNOWN;\n    };\n}\n\n_SOKOL_PRIVATE DXGI_FORMAT _sg_d3d11_srv_pixel_format(sg_pixel_format fmt) {\n    if (fmt == SG_PIXELFORMAT_DEPTH) {\n        return DXGI_FORMAT_R32_FLOAT;\n    } else if (fmt == SG_PIXELFORMAT_DEPTH_STENCIL) {\n        return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;\n    } else {\n        return _sg_d3d11_texture_pixel_format(fmt);\n    }\n}\n\n_SOKOL_PRIVATE DXGI_FORMAT _sg_d3d11_dsv_pixel_format(sg_pixel_format fmt) {\n    if (fmt == SG_PIXELFORMAT_DEPTH) {\n        return DXGI_FORMAT_D32_FLOAT;\n    } else if (fmt == SG_PIXELFORMAT_DEPTH_STENCIL) {\n        return DXGI_FORMAT_D24_UNORM_S8_UINT;\n    } else {\n        return _sg_d3d11_texture_pixel_format(fmt);\n    }\n}\n\n_SOKOL_PRIVATE DXGI_FORMAT _sg_d3d11_rtv_pixel_format(sg_pixel_format fmt) {\n    if (fmt == SG_PIXELFORMAT_DEPTH) {\n        return DXGI_FORMAT_R32_FLOAT;\n    } else if (fmt == SG_PIXELFORMAT_DEPTH_STENCIL) {\n        return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;\n    } else {\n        return _sg_d3d11_texture_pixel_format(fmt);\n    }\n}\n\n_SOKOL_PRIVATE D3D11_PRIMITIVE_TOPOLOGY _sg_d3d11_primitive_topology(sg_primitive_type prim_type) {\n    switch (prim_type) {\n        case SG_PRIMITIVETYPE_POINTS:           return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;\n        case SG_PRIMITIVETYPE_LINES:            return D3D11_PRIMITIVE_TOPOLOGY_LINELIST;\n        case SG_PRIMITIVETYPE_LINE_STRIP:       return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;\n        case SG_PRIMITIVETYPE_TRIANGLES:        return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;\n        case SG_PRIMITIVETYPE_TRIANGLE_STRIP:   return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;\n        default: SOKOL_UNREACHABLE; return (D3D11_PRIMITIVE_TOPOLOGY) 0;\n    }\n}\n\n_SOKOL_PRIVATE DXGI_FORMAT _sg_d3d11_index_format(sg_index_type index_type) {\n    switch (index_type) {\n        case SG_INDEXTYPE_NONE:     return DXGI_FORMAT_UNKNOWN;\n        case SG_INDEXTYPE_UINT16:   return DXGI_FORMAT_R16_UINT;\n        case SG_INDEXTYPE_UINT32:   return DXGI_FORMAT_R32_UINT;\n        default: SOKOL_UNREACHABLE; return (DXGI_FORMAT) 0;\n    }\n}\n\n_SOKOL_PRIVATE D3D11_FILTER _sg_d3d11_filter(sg_filter min_f, sg_filter mag_f, sg_filter mipmap_f, bool comparison, uint32_t max_anisotropy) {\n    uint32_t d3d11_filter = 0;\n    if (max_anisotropy > 1) {\n        // D3D11_FILTER_ANISOTROPIC = 0x55,\n        d3d11_filter |= 0x55;\n    } else {\n        // D3D11_FILTER_MIN_MAG_MIP_POINT = 0,\n        // D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR = 0x1,\n        // D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x4,\n        // D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR = 0x5,\n        // D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT = 0x10,\n        // D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x11,\n        // D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT = 0x14,\n        // D3D11_FILTER_MIN_MAG_MIP_LINEAR = 0x15,\n        if (mipmap_f == SG_FILTER_LINEAR) {\n            d3d11_filter |= 0x01;\n        }\n        if (mag_f == SG_FILTER_LINEAR) {\n            d3d11_filter |= 0x04;\n        }\n        if (min_f == SG_FILTER_LINEAR) {\n            d3d11_filter |= 0x10;\n        }\n    }\n    // D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT = 0x80,\n    // D3D11_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR = 0x81,\n    // D3D11_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x84,\n    // D3D11_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR = 0x85,\n    // D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT = 0x90,\n    // D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x91,\n    // D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT = 0x94,\n    // D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR = 0x95,\n    // D3D11_FILTER_COMPARISON_ANISOTROPIC = 0xd5,\n    if (comparison) {\n        d3d11_filter |= 0x80;\n    }\n    return (D3D11_FILTER)d3d11_filter;\n}\n\n_SOKOL_PRIVATE D3D11_TEXTURE_ADDRESS_MODE _sg_d3d11_address_mode(sg_wrap m) {\n    switch (m) {\n        case SG_WRAP_REPEAT:            return D3D11_TEXTURE_ADDRESS_WRAP;\n        case SG_WRAP_CLAMP_TO_EDGE:     return D3D11_TEXTURE_ADDRESS_CLAMP;\n        case SG_WRAP_CLAMP_TO_BORDER:   return D3D11_TEXTURE_ADDRESS_BORDER;\n        case SG_WRAP_MIRRORED_REPEAT:   return D3D11_TEXTURE_ADDRESS_MIRROR;\n        default: SOKOL_UNREACHABLE; return (D3D11_TEXTURE_ADDRESS_MODE) 0;\n    }\n}\n\n_SOKOL_PRIVATE DXGI_FORMAT _sg_d3d11_vertex_format(sg_vertex_format fmt) {\n    switch (fmt) {\n        case SG_VERTEXFORMAT_FLOAT:     return DXGI_FORMAT_R32_FLOAT;\n        case SG_VERTEXFORMAT_FLOAT2:    return DXGI_FORMAT_R32G32_FLOAT;\n        case SG_VERTEXFORMAT_FLOAT3:    return DXGI_FORMAT_R32G32B32_FLOAT;\n        case SG_VERTEXFORMAT_FLOAT4:    return DXGI_FORMAT_R32G32B32A32_FLOAT;\n        case SG_VERTEXFORMAT_BYTE4:     return DXGI_FORMAT_R8G8B8A8_SINT;\n        case SG_VERTEXFORMAT_BYTE4N:    return DXGI_FORMAT_R8G8B8A8_SNORM;\n        case SG_VERTEXFORMAT_UBYTE4:    return DXGI_FORMAT_R8G8B8A8_UINT;\n        case SG_VERTEXFORMAT_UBYTE4N:   return DXGI_FORMAT_R8G8B8A8_UNORM;\n        case SG_VERTEXFORMAT_SHORT2:    return DXGI_FORMAT_R16G16_SINT;\n        case SG_VERTEXFORMAT_SHORT2N:   return DXGI_FORMAT_R16G16_SNORM;\n        case SG_VERTEXFORMAT_USHORT2N:  return DXGI_FORMAT_R16G16_UNORM;\n        case SG_VERTEXFORMAT_SHORT4:    return DXGI_FORMAT_R16G16B16A16_SINT;\n        case SG_VERTEXFORMAT_SHORT4N:   return DXGI_FORMAT_R16G16B16A16_SNORM;\n        case SG_VERTEXFORMAT_USHORT4N:  return DXGI_FORMAT_R16G16B16A16_UNORM;\n        case SG_VERTEXFORMAT_UINT10_N2: return DXGI_FORMAT_R10G10B10A2_UNORM;\n        case SG_VERTEXFORMAT_HALF2:     return DXGI_FORMAT_R16G16_FLOAT;\n        case SG_VERTEXFORMAT_HALF4:     return DXGI_FORMAT_R16G16B16A16_FLOAT;\n        default: SOKOL_UNREACHABLE; return (DXGI_FORMAT) 0;\n    }\n}\n\n_SOKOL_PRIVATE D3D11_INPUT_CLASSIFICATION _sg_d3d11_input_classification(sg_vertex_step step) {\n    switch (step) {\n        case SG_VERTEXSTEP_PER_VERTEX:      return D3D11_INPUT_PER_VERTEX_DATA;\n        case SG_VERTEXSTEP_PER_INSTANCE:    return D3D11_INPUT_PER_INSTANCE_DATA;\n        default: SOKOL_UNREACHABLE; return (D3D11_INPUT_CLASSIFICATION) 0;\n    }\n}\n\n_SOKOL_PRIVATE D3D11_CULL_MODE _sg_d3d11_cull_mode(sg_cull_mode m) {\n    switch (m) {\n        case SG_CULLMODE_NONE:      return D3D11_CULL_NONE;\n        case SG_CULLMODE_FRONT:     return D3D11_CULL_FRONT;\n        case SG_CULLMODE_BACK:      return D3D11_CULL_BACK;\n        default: SOKOL_UNREACHABLE; return (D3D11_CULL_MODE) 0;\n    }\n}\n\n_SOKOL_PRIVATE D3D11_COMPARISON_FUNC _sg_d3d11_compare_func(sg_compare_func f) {\n    switch (f) {\n        case SG_COMPAREFUNC_NEVER:          return D3D11_COMPARISON_NEVER;\n        case SG_COMPAREFUNC_LESS:           return D3D11_COMPARISON_LESS;\n        case SG_COMPAREFUNC_EQUAL:          return D3D11_COMPARISON_EQUAL;\n        case SG_COMPAREFUNC_LESS_EQUAL:     return D3D11_COMPARISON_LESS_EQUAL;\n        case SG_COMPAREFUNC_GREATER:        return D3D11_COMPARISON_GREATER;\n        case SG_COMPAREFUNC_NOT_EQUAL:      return D3D11_COMPARISON_NOT_EQUAL;\n        case SG_COMPAREFUNC_GREATER_EQUAL:  return D3D11_COMPARISON_GREATER_EQUAL;\n        case SG_COMPAREFUNC_ALWAYS:         return D3D11_COMPARISON_ALWAYS;\n        default: SOKOL_UNREACHABLE; return (D3D11_COMPARISON_FUNC) 0;\n    }\n}\n\n_SOKOL_PRIVATE D3D11_STENCIL_OP _sg_d3d11_stencil_op(sg_stencil_op op) {\n    switch (op) {\n        case SG_STENCILOP_KEEP:         return D3D11_STENCIL_OP_KEEP;\n        case SG_STENCILOP_ZERO:         return D3D11_STENCIL_OP_ZERO;\n        case SG_STENCILOP_REPLACE:      return D3D11_STENCIL_OP_REPLACE;\n        case SG_STENCILOP_INCR_CLAMP:   return D3D11_STENCIL_OP_INCR_SAT;\n        case SG_STENCILOP_DECR_CLAMP:   return D3D11_STENCIL_OP_DECR_SAT;\n        case SG_STENCILOP_INVERT:       return D3D11_STENCIL_OP_INVERT;\n        case SG_STENCILOP_INCR_WRAP:    return D3D11_STENCIL_OP_INCR;\n        case SG_STENCILOP_DECR_WRAP:    return D3D11_STENCIL_OP_DECR;\n        default: SOKOL_UNREACHABLE; return (D3D11_STENCIL_OP) 0;\n    }\n}\n\n_SOKOL_PRIVATE D3D11_BLEND _sg_d3d11_blend_factor(sg_blend_factor f) {\n    switch (f) {\n        case SG_BLENDFACTOR_ZERO:                   return D3D11_BLEND_ZERO;\n        case SG_BLENDFACTOR_ONE:                    return D3D11_BLEND_ONE;\n        case SG_BLENDFACTOR_SRC_COLOR:              return D3D11_BLEND_SRC_COLOR;\n        case SG_BLENDFACTOR_ONE_MINUS_SRC_COLOR:    return D3D11_BLEND_INV_SRC_COLOR;\n        case SG_BLENDFACTOR_SRC_ALPHA:              return D3D11_BLEND_SRC_ALPHA;\n        case SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:    return D3D11_BLEND_INV_SRC_ALPHA;\n        case SG_BLENDFACTOR_DST_COLOR:              return D3D11_BLEND_DEST_COLOR;\n        case SG_BLENDFACTOR_ONE_MINUS_DST_COLOR:    return D3D11_BLEND_INV_DEST_COLOR;\n        case SG_BLENDFACTOR_DST_ALPHA:              return D3D11_BLEND_DEST_ALPHA;\n        case SG_BLENDFACTOR_ONE_MINUS_DST_ALPHA:    return D3D11_BLEND_INV_DEST_ALPHA;\n        case SG_BLENDFACTOR_SRC_ALPHA_SATURATED:    return D3D11_BLEND_SRC_ALPHA_SAT;\n        case SG_BLENDFACTOR_BLEND_COLOR:            return D3D11_BLEND_BLEND_FACTOR;\n        case SG_BLENDFACTOR_ONE_MINUS_BLEND_COLOR:  return D3D11_BLEND_INV_BLEND_FACTOR;\n        case SG_BLENDFACTOR_BLEND_ALPHA:            return D3D11_BLEND_BLEND_FACTOR;\n        case SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA:  return D3D11_BLEND_INV_BLEND_FACTOR;\n        default: SOKOL_UNREACHABLE; return (D3D11_BLEND) 0;\n    }\n}\n\n_SOKOL_PRIVATE D3D11_BLEND_OP _sg_d3d11_blend_op(sg_blend_op op) {\n    switch (op) {\n        case SG_BLENDOP_ADD:                return D3D11_BLEND_OP_ADD;\n        case SG_BLENDOP_SUBTRACT:           return D3D11_BLEND_OP_SUBTRACT;\n        case SG_BLENDOP_REVERSE_SUBTRACT:   return D3D11_BLEND_OP_REV_SUBTRACT;\n        default: SOKOL_UNREACHABLE; return (D3D11_BLEND_OP) 0;\n    }\n}\n\n_SOKOL_PRIVATE UINT8 _sg_d3d11_color_write_mask(sg_color_mask m) {\n    UINT8 res = 0;\n    if (m & SG_COLORMASK_R) {\n        res |= D3D11_COLOR_WRITE_ENABLE_RED;\n    }\n    if (m & SG_COLORMASK_G) {\n        res |= D3D11_COLOR_WRITE_ENABLE_GREEN;\n    }\n    if (m & SG_COLORMASK_B) {\n        res |= D3D11_COLOR_WRITE_ENABLE_BLUE;\n    }\n    if (m & SG_COLORMASK_A) {\n        res |= D3D11_COLOR_WRITE_ENABLE_ALPHA;\n    }\n    return res;\n}\n\n_SOKOL_PRIVATE UINT _sg_d3d11_dxgi_fmt_caps(DXGI_FORMAT dxgi_fmt) {\n    UINT dxgi_fmt_caps = 0;\n    if (dxgi_fmt != DXGI_FORMAT_UNKNOWN) {\n        HRESULT hr = _sg_d3d11_CheckFormatSupport(_sg.d3d11.dev, dxgi_fmt, &dxgi_fmt_caps);\n        SOKOL_ASSERT(SUCCEEDED(hr) || (E_FAIL == hr));\n        if (!SUCCEEDED(hr)) {\n            dxgi_fmt_caps = 0;\n        }\n    }\n    return dxgi_fmt_caps;\n}\n\n// see: https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-resources-limits#resource-limits-for-feature-level-11-hardware\n_SOKOL_PRIVATE void _sg_d3d11_init_caps(void) {\n    _sg.backend = SG_BACKEND_D3D11;\n\n    _sg.features.origin_top_left = true;\n    _sg.features.image_clamp_to_border = true;\n    _sg.features.mrt_independent_blend_state = true;\n    _sg.features.mrt_independent_write_mask = true;\n    _sg.features.storage_buffer = true;\n\n    _sg.limits.max_image_size_2d = 16 * 1024;\n    _sg.limits.max_image_size_cube = 16 * 1024;\n    _sg.limits.max_image_size_3d = 2 * 1024;\n    _sg.limits.max_image_size_array = 16 * 1024;\n    _sg.limits.max_image_array_layers = 2 * 1024;\n    _sg.limits.max_vertex_attrs = SG_MAX_VERTEX_ATTRIBUTES;\n\n    // see: https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_format_support\n    for (int fmt = (SG_PIXELFORMAT_NONE+1); fmt < _SG_PIXELFORMAT_NUM; fmt++) {\n        const UINT srv_dxgi_fmt_caps = _sg_d3d11_dxgi_fmt_caps(_sg_d3d11_srv_pixel_format((sg_pixel_format)fmt));\n        const UINT rtv_dxgi_fmt_caps = _sg_d3d11_dxgi_fmt_caps(_sg_d3d11_rtv_pixel_format((sg_pixel_format)fmt));\n        const UINT dsv_dxgi_fmt_caps = _sg_d3d11_dxgi_fmt_caps(_sg_d3d11_dsv_pixel_format((sg_pixel_format)fmt));\n        _sg_pixelformat_info_t* info = &_sg.formats[fmt];\n        const bool render = 0 != (rtv_dxgi_fmt_caps & D3D11_FORMAT_SUPPORT_RENDER_TARGET);\n        const bool depth  = 0 != (dsv_dxgi_fmt_caps & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL);\n        info->sample = 0 != (srv_dxgi_fmt_caps & D3D11_FORMAT_SUPPORT_TEXTURE2D);\n        info->filter = 0 != (srv_dxgi_fmt_caps & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE);\n        info->render = render || depth;\n        info->blend  = 0 != (rtv_dxgi_fmt_caps & D3D11_FORMAT_SUPPORT_BLENDABLE);\n        info->msaa   = 0 != (rtv_dxgi_fmt_caps & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET);\n        info->depth  = depth;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_setup_backend(const sg_desc* desc) {\n    // assume _sg.d3d11 already is zero-initialized\n    SOKOL_ASSERT(desc);\n    SOKOL_ASSERT(desc->environment.d3d11.device);\n    SOKOL_ASSERT(desc->environment.d3d11.device_context);\n    _sg.d3d11.valid = true;\n    _sg.d3d11.dev = (ID3D11Device*) desc->environment.d3d11.device;\n    _sg.d3d11.ctx = (ID3D11DeviceContext*) desc->environment.d3d11.device_context;\n    _sg_d3d11_init_caps();\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_discard_backend(void) {\n    SOKOL_ASSERT(_sg.d3d11.valid);\n    _sg.d3d11.valid = false;\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_clear_state(void) {\n    // clear all the device context state, so that resource refs don't keep stuck in the d3d device context\n    _sg_d3d11_ClearState(_sg.d3d11.ctx);\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_reset_state_cache(void) {\n    // just clear the d3d11 device context state\n    _sg_d3d11_clear_state();\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_buffer(_sg_buffer_t* buf, const sg_buffer_desc* desc) {\n    SOKOL_ASSERT(buf && desc);\n    SOKOL_ASSERT(!buf->d3d11.buf);\n    const bool injected = (0 != desc->d3d11_buffer);\n    if (injected) {\n        buf->d3d11.buf = (ID3D11Buffer*) desc->d3d11_buffer;\n        _sg_d3d11_AddRef(buf->d3d11.buf);\n        // FIXME: for storage buffers also need to inject resource view\n    } else {\n        D3D11_BUFFER_DESC d3d11_buf_desc;\n        _sg_clear(&d3d11_buf_desc, sizeof(d3d11_buf_desc));\n        d3d11_buf_desc.ByteWidth = (UINT)buf->cmn.size;\n        d3d11_buf_desc.Usage = _sg_d3d11_usage(buf->cmn.usage);\n        d3d11_buf_desc.BindFlags = _sg_d3d11_buffer_bind_flags(buf->cmn.type);\n        d3d11_buf_desc.CPUAccessFlags = _sg_d3d11_cpu_access_flags(buf->cmn.usage);\n        d3d11_buf_desc.MiscFlags = _sg_d3d11_buffer_misc_flags(buf->cmn.type);\n        D3D11_SUBRESOURCE_DATA* init_data_ptr = 0;\n        D3D11_SUBRESOURCE_DATA init_data;\n        _sg_clear(&init_data, sizeof(init_data));\n        if (buf->cmn.usage == SG_USAGE_IMMUTABLE) {\n            SOKOL_ASSERT(desc->data.ptr);\n            init_data.pSysMem = desc->data.ptr;\n            init_data_ptr = &init_data;\n        }\n        HRESULT hr = _sg_d3d11_CreateBuffer(_sg.d3d11.dev, &d3d11_buf_desc, init_data_ptr, &buf->d3d11.buf);\n        if (!(SUCCEEDED(hr) && buf->d3d11.buf)) {\n            _SG_ERROR(D3D11_CREATE_BUFFER_FAILED);\n            return SG_RESOURCESTATE_FAILED;\n        }\n\n        // for storage buffers need to create a view object\n        if (buf->cmn.type == SG_BUFFERTYPE_STORAGEBUFFER) {\n            // FIXME: currently only shader-resource-view, in future also UAV\n            // storage buffer size must be multiple of 4\n            SOKOL_ASSERT(_sg_multiple_u64(buf->cmn.size, 4));\n            D3D11_SHADER_RESOURCE_VIEW_DESC d3d11_srv_desc;\n            _sg_clear(&d3d11_srv_desc, sizeof(d3d11_srv_desc));\n            d3d11_srv_desc.Format = DXGI_FORMAT_R32_TYPELESS;\n            d3d11_srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;\n            d3d11_srv_desc.BufferEx.FirstElement = 0;\n            d3d11_srv_desc.BufferEx.NumElements = buf->cmn.size / 4;\n            d3d11_srv_desc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW;\n            hr = _sg_d3d11_CreateShaderResourceView(_sg.d3d11.dev, (ID3D11Resource*)buf->d3d11.buf, &d3d11_srv_desc, &buf->d3d11.srv);\n            if (!(SUCCEEDED(hr) && buf->d3d11.srv)) {\n                _SG_ERROR(D3D11_CREATE_BUFFER_SRV_FAILED);\n                return SG_RESOURCESTATE_FAILED;\n            }\n        }\n        _sg_d3d11_setlabel(buf->d3d11.buf, desc->label);\n    }\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_discard_buffer(_sg_buffer_t* buf) {\n    SOKOL_ASSERT(buf);\n    if (buf->d3d11.buf) {\n        _sg_d3d11_Release(buf->d3d11.buf);\n    }\n    if (buf->d3d11.srv) {\n        _sg_d3d11_Release(buf->d3d11.srv);\n    }\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_fill_subres_data(const _sg_image_t* img, const sg_image_data* data) {\n    const int num_faces = (img->cmn.type == SG_IMAGETYPE_CUBE) ? 6:1;\n    const int num_slices = (img->cmn.type == SG_IMAGETYPE_ARRAY) ? img->cmn.num_slices:1;\n    int subres_index = 0;\n    for (int face_index = 0; face_index < num_faces; face_index++) {\n        for (int slice_index = 0; slice_index < num_slices; slice_index++) {\n            for (int mip_index = 0; mip_index < img->cmn.num_mipmaps; mip_index++, subres_index++) {\n                SOKOL_ASSERT(subres_index < (SG_MAX_MIPMAPS * SG_MAX_TEXTUREARRAY_LAYERS));\n                D3D11_SUBRESOURCE_DATA* subres_data = &_sg.d3d11.subres_data[subres_index];\n                const int mip_width = _sg_miplevel_dim(img->cmn.width, mip_index);\n                const int mip_height = _sg_miplevel_dim(img->cmn.height, mip_index);\n                const sg_range* subimg_data = &(data->subimage[face_index][mip_index]);\n                const size_t slice_size = subimg_data->size / (size_t)num_slices;\n                const size_t slice_offset = slice_size * (size_t)slice_index;\n                const uint8_t* ptr = (const uint8_t*) subimg_data->ptr;\n                subres_data->pSysMem = ptr + slice_offset;\n                subres_data->SysMemPitch = (UINT)_sg_row_pitch(img->cmn.pixel_format, mip_width, 1);\n                if (img->cmn.type == SG_IMAGETYPE_3D) {\n                    // FIXME? const int mip_depth = _sg_miplevel_dim(img->depth, mip_index);\n                    subres_data->SysMemSlicePitch = (UINT)_sg_surface_pitch(img->cmn.pixel_format, mip_width, mip_height, 1);\n                } else {\n                    subres_data->SysMemSlicePitch = 0;\n                }\n            }\n        }\n    }\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const sg_image_desc* desc) {\n    SOKOL_ASSERT(img && desc);\n    SOKOL_ASSERT((0 == img->d3d11.tex2d) && (0 == img->d3d11.tex3d) && (0 == img->d3d11.res) && (0 == img->d3d11.srv));\n    HRESULT hr;\n\n    const bool injected = (0 != desc->d3d11_texture);\n    const bool msaa = (img->cmn.sample_count > 1);\n    img->d3d11.format = _sg_d3d11_texture_pixel_format(img->cmn.pixel_format);\n    if (img->d3d11.format == DXGI_FORMAT_UNKNOWN) {\n        _SG_ERROR(D3D11_CREATE_2D_TEXTURE_UNSUPPORTED_PIXEL_FORMAT);\n        return SG_RESOURCESTATE_FAILED;\n    }\n\n    // prepare initial content pointers\n    D3D11_SUBRESOURCE_DATA* init_data = 0;\n    if (!injected && (img->cmn.usage == SG_USAGE_IMMUTABLE) && !img->cmn.render_target) {\n        _sg_d3d11_fill_subres_data(img, &desc->data);\n        init_data = _sg.d3d11.subres_data;\n    }\n    if (img->cmn.type != SG_IMAGETYPE_3D) {\n        // 2D-, cube- or array-texture\n        // first check for injected texture and/or resource view\n        if (injected) {\n            img->d3d11.tex2d = (ID3D11Texture2D*) desc->d3d11_texture;\n            _sg_d3d11_AddRef(img->d3d11.tex2d);\n            img->d3d11.srv = (ID3D11ShaderResourceView*) desc->d3d11_shader_resource_view;\n            if (img->d3d11.srv) {\n                _sg_d3d11_AddRef(img->d3d11.srv);\n            }\n        } else {\n            // if not injected, create 2D texture\n            D3D11_TEXTURE2D_DESC d3d11_tex_desc;\n            _sg_clear(&d3d11_tex_desc, sizeof(d3d11_tex_desc));\n            d3d11_tex_desc.Width = (UINT)img->cmn.width;\n            d3d11_tex_desc.Height = (UINT)img->cmn.height;\n            d3d11_tex_desc.MipLevels = (UINT)img->cmn.num_mipmaps;\n            switch (img->cmn.type) {\n                case SG_IMAGETYPE_ARRAY:    d3d11_tex_desc.ArraySize = (UINT)img->cmn.num_slices; break;\n                case SG_IMAGETYPE_CUBE:     d3d11_tex_desc.ArraySize = 6; break;\n                default:                    d3d11_tex_desc.ArraySize = 1; break;\n            }\n            d3d11_tex_desc.Format = img->d3d11.format;\n            if (img->cmn.render_target) {\n                d3d11_tex_desc.Usage = D3D11_USAGE_DEFAULT;\n                if (_sg_is_depth_or_depth_stencil_format(img->cmn.pixel_format)) {\n                    d3d11_tex_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;\n                } else {\n                    d3d11_tex_desc.BindFlags = D3D11_BIND_RENDER_TARGET;\n                }\n                if (!msaa) {\n                    d3d11_tex_desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;\n                }\n                d3d11_tex_desc.CPUAccessFlags = 0;\n            } else {\n                d3d11_tex_desc.Usage = _sg_d3d11_usage(img->cmn.usage);\n                d3d11_tex_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;\n                d3d11_tex_desc.CPUAccessFlags = _sg_d3d11_cpu_access_flags(img->cmn.usage);\n            }\n            d3d11_tex_desc.SampleDesc.Count = (UINT)img->cmn.sample_count;\n            d3d11_tex_desc.SampleDesc.Quality = (UINT) (msaa ? D3D11_STANDARD_MULTISAMPLE_PATTERN : 0);\n            d3d11_tex_desc.MiscFlags = (img->cmn.type == SG_IMAGETYPE_CUBE) ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;\n\n            hr = _sg_d3d11_CreateTexture2D(_sg.d3d11.dev, &d3d11_tex_desc, init_data, &img->d3d11.tex2d);\n            if (!(SUCCEEDED(hr) && img->d3d11.tex2d)) {\n                _SG_ERROR(D3D11_CREATE_2D_TEXTURE_FAILED);\n                return SG_RESOURCESTATE_FAILED;\n            }\n            _sg_d3d11_setlabel(img->d3d11.tex2d, desc->label);\n\n            // create shader-resource-view for 2D texture\n            // FIXME: currently we don't support setting MSAA texture as shader resource\n            if (!msaa) {\n                D3D11_SHADER_RESOURCE_VIEW_DESC d3d11_srv_desc;\n                _sg_clear(&d3d11_srv_desc, sizeof(d3d11_srv_desc));\n                d3d11_srv_desc.Format = _sg_d3d11_srv_pixel_format(img->cmn.pixel_format);\n                switch (img->cmn.type) {\n                    case SG_IMAGETYPE_2D:\n                        d3d11_srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;\n                        d3d11_srv_desc.Texture2D.MipLevels = (UINT)img->cmn.num_mipmaps;\n                        break;\n                    case SG_IMAGETYPE_CUBE:\n                        d3d11_srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;\n                        d3d11_srv_desc.TextureCube.MipLevels = (UINT)img->cmn.num_mipmaps;\n                        break;\n                    case SG_IMAGETYPE_ARRAY:\n                        d3d11_srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;\n                        d3d11_srv_desc.Texture2DArray.MipLevels = (UINT)img->cmn.num_mipmaps;\n                        d3d11_srv_desc.Texture2DArray.ArraySize = (UINT)img->cmn.num_slices;\n                        break;\n                    default:\n                        SOKOL_UNREACHABLE; break;\n                }\n                hr = _sg_d3d11_CreateShaderResourceView(_sg.d3d11.dev, (ID3D11Resource*)img->d3d11.tex2d, &d3d11_srv_desc, &img->d3d11.srv);\n                if (!(SUCCEEDED(hr) && img->d3d11.srv)) {\n                    _SG_ERROR(D3D11_CREATE_2D_SRV_FAILED);\n                    return SG_RESOURCESTATE_FAILED;\n                }\n                _sg_d3d11_setlabel(img->d3d11.srv, desc->label);\n            }\n        }\n        SOKOL_ASSERT(img->d3d11.tex2d);\n        img->d3d11.res = (ID3D11Resource*)img->d3d11.tex2d;\n        _sg_d3d11_AddRef(img->d3d11.res);\n    } else {\n        // 3D texture - same procedure, first check if injected, than create non-injected\n        if (injected) {\n            img->d3d11.tex3d = (ID3D11Texture3D*) desc->d3d11_texture;\n            _sg_d3d11_AddRef(img->d3d11.tex3d);\n            img->d3d11.srv = (ID3D11ShaderResourceView*) desc->d3d11_shader_resource_view;\n            if (img->d3d11.srv) {\n                _sg_d3d11_AddRef(img->d3d11.srv);\n            }\n        } else {\n            // not injected, create 3d texture\n            D3D11_TEXTURE3D_DESC d3d11_tex_desc;\n            _sg_clear(&d3d11_tex_desc, sizeof(d3d11_tex_desc));\n            d3d11_tex_desc.Width = (UINT)img->cmn.width;\n            d3d11_tex_desc.Height = (UINT)img->cmn.height;\n            d3d11_tex_desc.Depth = (UINT)img->cmn.num_slices;\n            d3d11_tex_desc.MipLevels = (UINT)img->cmn.num_mipmaps;\n            d3d11_tex_desc.Format = img->d3d11.format;\n            if (img->cmn.render_target) {\n                d3d11_tex_desc.Usage = D3D11_USAGE_DEFAULT;\n                d3d11_tex_desc.BindFlags = D3D11_BIND_RENDER_TARGET;\n                d3d11_tex_desc.CPUAccessFlags = 0;\n            } else {\n                d3d11_tex_desc.Usage = _sg_d3d11_usage(img->cmn.usage);\n                d3d11_tex_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;\n                d3d11_tex_desc.CPUAccessFlags = _sg_d3d11_cpu_access_flags(img->cmn.usage);\n            }\n            if (img->d3d11.format == DXGI_FORMAT_UNKNOWN) {\n                _SG_ERROR(D3D11_CREATE_3D_TEXTURE_UNSUPPORTED_PIXEL_FORMAT);\n                return SG_RESOURCESTATE_FAILED;\n            }\n            hr = _sg_d3d11_CreateTexture3D(_sg.d3d11.dev, &d3d11_tex_desc, init_data, &img->d3d11.tex3d);\n            if (!(SUCCEEDED(hr) && img->d3d11.tex3d)) {\n                _SG_ERROR(D3D11_CREATE_3D_TEXTURE_FAILED);\n                return SG_RESOURCESTATE_FAILED;\n            }\n            _sg_d3d11_setlabel(img->d3d11.tex3d, desc->label);\n\n            // create shader-resource-view for 3D texture\n            if (!msaa) {\n                D3D11_SHADER_RESOURCE_VIEW_DESC d3d11_srv_desc;\n                _sg_clear(&d3d11_srv_desc, sizeof(d3d11_srv_desc));\n                d3d11_srv_desc.Format = _sg_d3d11_srv_pixel_format(img->cmn.pixel_format);\n                d3d11_srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;\n                d3d11_srv_desc.Texture3D.MipLevels = (UINT)img->cmn.num_mipmaps;\n                hr = _sg_d3d11_CreateShaderResourceView(_sg.d3d11.dev, (ID3D11Resource*)img->d3d11.tex3d, &d3d11_srv_desc, &img->d3d11.srv);\n                if (!(SUCCEEDED(hr) && img->d3d11.srv)) {\n                    _SG_ERROR(D3D11_CREATE_3D_SRV_FAILED);\n                    return SG_RESOURCESTATE_FAILED;\n                }\n                _sg_d3d11_setlabel(img->d3d11.srv, desc->label);\n            }\n        }\n        SOKOL_ASSERT(img->d3d11.tex3d);\n        img->d3d11.res = (ID3D11Resource*)img->d3d11.tex3d;\n        _sg_d3d11_AddRef(img->d3d11.res);\n    }\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_discard_image(_sg_image_t* img) {\n    SOKOL_ASSERT(img);\n    if (img->d3d11.tex2d) {\n        _sg_d3d11_Release(img->d3d11.tex2d);\n    }\n    if (img->d3d11.tex3d) {\n        _sg_d3d11_Release(img->d3d11.tex3d);\n    }\n    if (img->d3d11.res) {\n        _sg_d3d11_Release(img->d3d11.res);\n    }\n    if (img->d3d11.srv) {\n        _sg_d3d11_Release(img->d3d11.srv);\n    }\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_sampler(_sg_sampler_t* smp, const sg_sampler_desc* desc) {\n    SOKOL_ASSERT(smp && desc);\n    SOKOL_ASSERT(0 == smp->d3d11.smp);\n    const bool injected = (0 != desc->d3d11_sampler);\n    if (injected) {\n        smp->d3d11.smp = (ID3D11SamplerState*)desc->d3d11_sampler;\n        _sg_d3d11_AddRef(smp->d3d11.smp);\n    } else {\n        D3D11_SAMPLER_DESC d3d11_smp_desc;\n        _sg_clear(&d3d11_smp_desc, sizeof(d3d11_smp_desc));\n        d3d11_smp_desc.Filter = _sg_d3d11_filter(desc->min_filter, desc->mag_filter, desc->mipmap_filter, desc->compare != SG_COMPAREFUNC_NEVER, desc->max_anisotropy);\n        d3d11_smp_desc.AddressU = _sg_d3d11_address_mode(desc->wrap_u);\n        d3d11_smp_desc.AddressV = _sg_d3d11_address_mode(desc->wrap_v);\n        d3d11_smp_desc.AddressW = _sg_d3d11_address_mode(desc->wrap_w);\n        d3d11_smp_desc.MipLODBias = 0.0f; // FIXME?\n        switch (desc->border_color) {\n            case SG_BORDERCOLOR_TRANSPARENT_BLACK:\n                // all 0.0f\n                break;\n            case SG_BORDERCOLOR_OPAQUE_WHITE:\n                for (int i = 0; i < 4; i++) {\n                    d3d11_smp_desc.BorderColor[i] = 1.0f;\n                }\n                break;\n            default:\n                // opaque black\n                d3d11_smp_desc.BorderColor[3] = 1.0f;\n                break;\n        }\n        d3d11_smp_desc.MaxAnisotropy = desc->max_anisotropy;\n        d3d11_smp_desc.ComparisonFunc = _sg_d3d11_compare_func(desc->compare);\n        d3d11_smp_desc.MinLOD = desc->min_lod;\n        d3d11_smp_desc.MaxLOD = desc->max_lod;\n        HRESULT hr = _sg_d3d11_CreateSamplerState(_sg.d3d11.dev, &d3d11_smp_desc, &smp->d3d11.smp);\n        if (!(SUCCEEDED(hr) && smp->d3d11.smp)) {\n            _SG_ERROR(D3D11_CREATE_SAMPLER_STATE_FAILED);\n            return SG_RESOURCESTATE_FAILED;\n        }\n        _sg_d3d11_setlabel(smp->d3d11.smp, desc->label);\n    }\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_discard_sampler(_sg_sampler_t* smp) {\n    SOKOL_ASSERT(smp);\n    if (smp->d3d11.smp) {\n        _sg_d3d11_Release(smp->d3d11.smp);\n    }\n}\n\n_SOKOL_PRIVATE bool _sg_d3d11_load_d3dcompiler_dll(void) {\n    if ((0 == _sg.d3d11.d3dcompiler_dll) && !_sg.d3d11.d3dcompiler_dll_load_failed) {\n        _sg.d3d11.d3dcompiler_dll = LoadLibraryA(\"d3dcompiler_47.dll\");\n        if (0 == _sg.d3d11.d3dcompiler_dll) {\n            // don't attempt to load missing DLL in the future\n            _SG_ERROR(D3D11_LOAD_D3DCOMPILER_47_DLL_FAILED);\n            _sg.d3d11.d3dcompiler_dll_load_failed = true;\n            return false;\n        }\n        // look up function pointers\n        _sg.d3d11.D3DCompile_func = (pD3DCompile)(void*) GetProcAddress(_sg.d3d11.d3dcompiler_dll, \"D3DCompile\");\n        SOKOL_ASSERT(_sg.d3d11.D3DCompile_func);\n    }\n    return 0 != _sg.d3d11.d3dcompiler_dll;\n}\n\n_SOKOL_PRIVATE ID3DBlob* _sg_d3d11_compile_shader(const sg_shader_stage_desc* stage_desc) {\n    if (!_sg_d3d11_load_d3dcompiler_dll()) {\n        return NULL;\n    }\n    SOKOL_ASSERT(stage_desc->d3d11_target);\n    ID3DBlob* output = NULL;\n    ID3DBlob* errors_or_warnings = NULL;\n    HRESULT hr = _sg.d3d11.D3DCompile_func(\n        stage_desc->source,             // pSrcData\n        strlen(stage_desc->source),     // SrcDataSize\n        NULL,                           // pSourceName\n        NULL,                           // pDefines\n        NULL,                           // pInclude\n        stage_desc->entry ? stage_desc->entry : \"main\",     // pEntryPoint\n        stage_desc->d3d11_target,       // pTarget\n        D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR | D3DCOMPILE_OPTIMIZATION_LEVEL3,   // Flags1\n        0,          // Flags2\n        &output,    // ppCode\n        &errors_or_warnings);   // ppErrorMsgs\n    if (FAILED(hr)) {\n        _SG_ERROR(D3D11_SHADER_COMPILATION_FAILED);\n    }\n    if (errors_or_warnings) {\n        _SG_WARN(D3D11_SHADER_COMPILATION_OUTPUT);\n        _SG_LOGMSG(D3D11_SHADER_COMPILATION_OUTPUT, (LPCSTR)_sg_d3d11_GetBufferPointer(errors_or_warnings));\n        _sg_d3d11_Release(errors_or_warnings); errors_or_warnings = NULL;\n    }\n    if (FAILED(hr)) {\n        // just in case, usually output is NULL here\n        if (output) {\n            _sg_d3d11_Release(output);\n            output = NULL;\n        }\n    }\n    return output;\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_shader(_sg_shader_t* shd, const sg_shader_desc* desc) {\n    SOKOL_ASSERT(shd && desc);\n    SOKOL_ASSERT(!shd->d3d11.vs && !shd->d3d11.fs && !shd->d3d11.vs_blob);\n    HRESULT hr;\n\n    // copy vertex attribute semantic names and indices\n    for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {\n        _sg_strcpy(&shd->d3d11.attrs[i].sem_name, desc->attrs[i].sem_name);\n        shd->d3d11.attrs[i].sem_index = desc->attrs[i].sem_index;\n    }\n\n    // shader stage uniform blocks and image slots\n    for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {\n        _sg_shader_stage_t* cmn_stage = &shd->cmn.stage[stage_index];\n        _sg_d3d11_shader_stage_t* d3d11_stage = &shd->d3d11.stage[stage_index];\n        for (int ub_index = 0; ub_index < cmn_stage->num_uniform_blocks; ub_index++) {\n            const _sg_shader_uniform_block_t* ub = &cmn_stage->uniform_blocks[ub_index];\n\n            // create a D3D constant buffer for each uniform block\n            SOKOL_ASSERT(0 == d3d11_stage->cbufs[ub_index]);\n            D3D11_BUFFER_DESC cb_desc;\n            _sg_clear(&cb_desc, sizeof(cb_desc));\n            cb_desc.ByteWidth = (UINT)_sg_roundup((int)ub->size, 16);\n            cb_desc.Usage = D3D11_USAGE_DEFAULT;\n            cb_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;\n            hr = _sg_d3d11_CreateBuffer(_sg.d3d11.dev, &cb_desc, NULL, &d3d11_stage->cbufs[ub_index]);\n            if (!(SUCCEEDED(hr) && d3d11_stage->cbufs[ub_index])) {\n                _SG_ERROR(D3D11_CREATE_CONSTANT_BUFFER_FAILED);\n                return SG_RESOURCESTATE_FAILED;\n            }\n            _sg_d3d11_setlabel(d3d11_stage->cbufs[ub_index], desc->label);\n        }\n    }\n\n    const void* vs_ptr = 0, *fs_ptr = 0;\n    SIZE_T vs_length = 0, fs_length = 0;\n    ID3DBlob* vs_blob = 0, *fs_blob = 0;\n    if (desc->vs.bytecode.ptr && desc->fs.bytecode.ptr) {\n        // create from shader byte code\n        vs_ptr = desc->vs.bytecode.ptr;\n        fs_ptr = desc->fs.bytecode.ptr;\n        vs_length = desc->vs.bytecode.size;\n        fs_length = desc->fs.bytecode.size;\n    } else {\n        // compile from shader source code\n        vs_blob = _sg_d3d11_compile_shader(&desc->vs);\n        fs_blob = _sg_d3d11_compile_shader(&desc->fs);\n        if (vs_blob && fs_blob) {\n            vs_ptr = _sg_d3d11_GetBufferPointer(vs_blob);\n            vs_length = _sg_d3d11_GetBufferSize(vs_blob);\n            fs_ptr = _sg_d3d11_GetBufferPointer(fs_blob);\n            fs_length = _sg_d3d11_GetBufferSize(fs_blob);\n        }\n    }\n    sg_resource_state result = SG_RESOURCESTATE_FAILED;\n    if (vs_ptr && fs_ptr && (vs_length > 0) && (fs_length > 0)) {\n        // create the D3D vertex- and pixel-shader objects\n        hr = _sg_d3d11_CreateVertexShader(_sg.d3d11.dev, vs_ptr, vs_length, NULL, &shd->d3d11.vs);\n        bool vs_succeeded = SUCCEEDED(hr) && shd->d3d11.vs;\n        hr = _sg_d3d11_CreatePixelShader(_sg.d3d11.dev, fs_ptr, fs_length, NULL, &shd->d3d11.fs);\n        bool fs_succeeded = SUCCEEDED(hr) && shd->d3d11.fs;\n\n        // need to store the vertex shader byte code, this is needed later in sg_create_pipeline\n        if (vs_succeeded && fs_succeeded) {\n            shd->d3d11.vs_blob_length = vs_length;\n            shd->d3d11.vs_blob = _sg_malloc((size_t)vs_length);\n            SOKOL_ASSERT(shd->d3d11.vs_blob);\n            memcpy(shd->d3d11.vs_blob, vs_ptr, vs_length);\n            result = SG_RESOURCESTATE_VALID;\n            _sg_d3d11_setlabel(shd->d3d11.vs, desc->label);\n            _sg_d3d11_setlabel(shd->d3d11.fs, desc->label);\n        }\n    }\n    if (vs_blob) {\n        _sg_d3d11_Release(vs_blob); vs_blob = 0;\n    }\n    if (fs_blob) {\n        _sg_d3d11_Release(fs_blob); fs_blob = 0;\n    }\n    return result;\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_discard_shader(_sg_shader_t* shd) {\n    SOKOL_ASSERT(shd);\n    if (shd->d3d11.vs) {\n        _sg_d3d11_Release(shd->d3d11.vs);\n    }\n    if (shd->d3d11.fs) {\n        _sg_d3d11_Release(shd->d3d11.fs);\n    }\n    if (shd->d3d11.vs_blob) {\n        _sg_free(shd->d3d11.vs_blob);\n    }\n    for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {\n        _sg_shader_stage_t* cmn_stage = &shd->cmn.stage[stage_index];\n        _sg_d3d11_shader_stage_t* d3d11_stage = &shd->d3d11.stage[stage_index];\n        for (int ub_index = 0; ub_index < cmn_stage->num_uniform_blocks; ub_index++) {\n            if (d3d11_stage->cbufs[ub_index]) {\n                _sg_d3d11_Release(d3d11_stage->cbufs[ub_index]);\n            }\n        }\n    }\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) {\n    SOKOL_ASSERT(pip && shd && desc);\n    SOKOL_ASSERT(desc->shader.id == shd->slot.id);\n    SOKOL_ASSERT(shd->slot.state == SG_RESOURCESTATE_VALID);\n    SOKOL_ASSERT(shd->d3d11.vs_blob && shd->d3d11.vs_blob_length > 0);\n    SOKOL_ASSERT(!pip->d3d11.il && !pip->d3d11.rs && !pip->d3d11.dss && !pip->d3d11.bs);\n\n    pip->shader = shd;\n    pip->d3d11.index_format = _sg_d3d11_index_format(pip->cmn.index_type);\n    pip->d3d11.topology = _sg_d3d11_primitive_topology(desc->primitive_type);\n    pip->d3d11.stencil_ref = desc->stencil.ref;\n\n    // create input layout object\n    HRESULT hr;\n    D3D11_INPUT_ELEMENT_DESC d3d11_comps[SG_MAX_VERTEX_ATTRIBUTES];\n    _sg_clear(d3d11_comps, sizeof(d3d11_comps));\n    int attr_index = 0;\n    for (; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {\n        const sg_vertex_attr_state* a_state = &desc->layout.attrs[attr_index];\n        if (a_state->format == SG_VERTEXFORMAT_INVALID) {\n            break;\n        }\n        SOKOL_ASSERT(a_state->buffer_index < SG_MAX_VERTEX_BUFFERS);\n        const sg_vertex_buffer_layout_state* l_state = &desc->layout.buffers[a_state->buffer_index];\n        const sg_vertex_step step_func = l_state->step_func;\n        const int step_rate = l_state->step_rate;\n        D3D11_INPUT_ELEMENT_DESC* d3d11_comp = &d3d11_comps[attr_index];\n        d3d11_comp->SemanticName = _sg_strptr(&shd->d3d11.attrs[attr_index].sem_name);\n        d3d11_comp->SemanticIndex = (UINT)shd->d3d11.attrs[attr_index].sem_index;\n        d3d11_comp->Format = _sg_d3d11_vertex_format(a_state->format);\n        d3d11_comp->InputSlot = (UINT)a_state->buffer_index;\n        d3d11_comp->AlignedByteOffset = (UINT)a_state->offset;\n        d3d11_comp->InputSlotClass = _sg_d3d11_input_classification(step_func);\n        if (SG_VERTEXSTEP_PER_INSTANCE == step_func) {\n            d3d11_comp->InstanceDataStepRate = (UINT)step_rate;\n            pip->cmn.use_instanced_draw = true;\n        }\n        pip->cmn.vertex_buffer_layout_active[a_state->buffer_index] = true;\n    }\n    for (int layout_index = 0; layout_index < SG_MAX_VERTEX_BUFFERS; layout_index++) {\n        if (pip->cmn.vertex_buffer_layout_active[layout_index]) {\n            const sg_vertex_buffer_layout_state* l_state = &desc->layout.buffers[layout_index];\n            SOKOL_ASSERT(l_state->stride > 0);\n            pip->d3d11.vb_strides[layout_index] = (UINT)l_state->stride;\n        } else {\n            pip->d3d11.vb_strides[layout_index] = 0;\n        }\n    }\n    if (attr_index > 0) {\n        hr = _sg_d3d11_CreateInputLayout(_sg.d3d11.dev,\n            d3d11_comps,                // pInputElementDesc\n            (UINT)attr_index,           // NumElements\n            shd->d3d11.vs_blob,         // pShaderByteCodeWithInputSignature\n            shd->d3d11.vs_blob_length,  // BytecodeLength\n            &pip->d3d11.il);\n        if (!(SUCCEEDED(hr) && pip->d3d11.il)) {\n            _SG_ERROR(D3D11_CREATE_INPUT_LAYOUT_FAILED);\n            return SG_RESOURCESTATE_FAILED;\n        }\n        _sg_d3d11_setlabel(pip->d3d11.il, desc->label);\n    }\n\n    // create rasterizer state\n    D3D11_RASTERIZER_DESC rs_desc;\n    _sg_clear(&rs_desc, sizeof(rs_desc));\n    rs_desc.FillMode = D3D11_FILL_SOLID;\n    rs_desc.CullMode = _sg_d3d11_cull_mode(desc->cull_mode);\n    rs_desc.FrontCounterClockwise = desc->face_winding == SG_FACEWINDING_CCW;\n    rs_desc.DepthBias = (INT) pip->cmn.depth.bias;\n    rs_desc.DepthBiasClamp = pip->cmn.depth.bias_clamp;\n    rs_desc.SlopeScaledDepthBias = pip->cmn.depth.bias_slope_scale;\n    rs_desc.DepthClipEnable = TRUE;\n    rs_desc.ScissorEnable = TRUE;\n    rs_desc.MultisampleEnable = desc->sample_count > 1;\n    rs_desc.AntialiasedLineEnable = FALSE;\n    hr = _sg_d3d11_CreateRasterizerState(_sg.d3d11.dev, &rs_desc, &pip->d3d11.rs);\n    if (!(SUCCEEDED(hr) && pip->d3d11.rs)) {\n        _SG_ERROR(D3D11_CREATE_RASTERIZER_STATE_FAILED);\n        return SG_RESOURCESTATE_FAILED;\n    }\n    _sg_d3d11_setlabel(pip->d3d11.rs, desc->label);\n\n    // create depth-stencil state\n    D3D11_DEPTH_STENCIL_DESC dss_desc;\n    _sg_clear(&dss_desc, sizeof(dss_desc));\n    dss_desc.DepthEnable = TRUE;\n    dss_desc.DepthWriteMask = desc->depth.write_enabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;\n    dss_desc.DepthFunc = _sg_d3d11_compare_func(desc->depth.compare);\n    dss_desc.StencilEnable = desc->stencil.enabled;\n    dss_desc.StencilReadMask = desc->stencil.read_mask;\n    dss_desc.StencilWriteMask = desc->stencil.write_mask;\n    const sg_stencil_face_state* sf = &desc->stencil.front;\n    dss_desc.FrontFace.StencilFailOp = _sg_d3d11_stencil_op(sf->fail_op);\n    dss_desc.FrontFace.StencilDepthFailOp = _sg_d3d11_stencil_op(sf->depth_fail_op);\n    dss_desc.FrontFace.StencilPassOp = _sg_d3d11_stencil_op(sf->pass_op);\n    dss_desc.FrontFace.StencilFunc = _sg_d3d11_compare_func(sf->compare);\n    const sg_stencil_face_state* sb = &desc->stencil.back;\n    dss_desc.BackFace.StencilFailOp = _sg_d3d11_stencil_op(sb->fail_op);\n    dss_desc.BackFace.StencilDepthFailOp = _sg_d3d11_stencil_op(sb->depth_fail_op);\n    dss_desc.BackFace.StencilPassOp = _sg_d3d11_stencil_op(sb->pass_op);\n    dss_desc.BackFace.StencilFunc = _sg_d3d11_compare_func(sb->compare);\n    hr = _sg_d3d11_CreateDepthStencilState(_sg.d3d11.dev, &dss_desc, &pip->d3d11.dss);\n    if (!(SUCCEEDED(hr) && pip->d3d11.dss)) {\n        _SG_ERROR(D3D11_CREATE_DEPTH_STENCIL_STATE_FAILED);\n        return SG_RESOURCESTATE_FAILED;\n    }\n    _sg_d3d11_setlabel(pip->d3d11.dss, desc->label);\n\n    // create blend state\n    D3D11_BLEND_DESC bs_desc;\n    _sg_clear(&bs_desc, sizeof(bs_desc));\n    bs_desc.AlphaToCoverageEnable = desc->alpha_to_coverage_enabled;\n    bs_desc.IndependentBlendEnable = TRUE;\n    {\n        int i = 0;\n        for (i = 0; i < desc->color_count; i++) {\n            const sg_blend_state* src = &desc->colors[i].blend;\n            D3D11_RENDER_TARGET_BLEND_DESC* dst = &bs_desc.RenderTarget[i];\n            dst->BlendEnable = src->enabled;\n            dst->SrcBlend = _sg_d3d11_blend_factor(src->src_factor_rgb);\n            dst->DestBlend = _sg_d3d11_blend_factor(src->dst_factor_rgb);\n            dst->BlendOp = _sg_d3d11_blend_op(src->op_rgb);\n            dst->SrcBlendAlpha = _sg_d3d11_blend_factor(src->src_factor_alpha);\n            dst->DestBlendAlpha = _sg_d3d11_blend_factor(src->dst_factor_alpha);\n            dst->BlendOpAlpha = _sg_d3d11_blend_op(src->op_alpha);\n            dst->RenderTargetWriteMask = _sg_d3d11_color_write_mask(desc->colors[i].write_mask);\n        }\n        for (; i < 8; i++) {\n            D3D11_RENDER_TARGET_BLEND_DESC* dst = &bs_desc.RenderTarget[i];\n            dst->BlendEnable = FALSE;\n            dst->SrcBlend = dst->SrcBlendAlpha = D3D11_BLEND_ONE;\n            dst->DestBlend = dst->DestBlendAlpha = D3D11_BLEND_ZERO;\n            dst->BlendOp = dst->BlendOpAlpha = D3D11_BLEND_OP_ADD;\n            dst->RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;\n        }\n    }\n    hr = _sg_d3d11_CreateBlendState(_sg.d3d11.dev, &bs_desc, &pip->d3d11.bs);\n    if (!(SUCCEEDED(hr) && pip->d3d11.bs)) {\n        _SG_ERROR(D3D11_CREATE_BLEND_STATE_FAILED);\n        return SG_RESOURCESTATE_FAILED;\n    }\n    _sg_d3d11_setlabel(pip->d3d11.bs, desc->label);\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_discard_pipeline(_sg_pipeline_t* pip) {\n    SOKOL_ASSERT(pip);\n    if (pip == _sg.d3d11.cur_pipeline) {\n        _sg.d3d11.cur_pipeline = 0;\n        _sg.d3d11.cur_pipeline_id.id = SG_INVALID_ID;\n    }\n    if (pip->d3d11.il) {\n        _sg_d3d11_Release(pip->d3d11.il);\n    }\n    if (pip->d3d11.rs) {\n        _sg_d3d11_Release(pip->d3d11.rs);\n    }\n    if (pip->d3d11.dss) {\n        _sg_d3d11_Release(pip->d3d11.dss);\n    }\n    if (pip->d3d11.bs) {\n        _sg_d3d11_Release(pip->d3d11.bs);\n    }\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_attachments(_sg_attachments_t* atts, _sg_image_t** color_images, _sg_image_t** resolve_images, _sg_image_t* ds_img, const sg_attachments_desc* desc) {\n    SOKOL_ASSERT(atts && desc);\n    SOKOL_ASSERT(color_images && resolve_images);\n    SOKOL_ASSERT(_sg.d3d11.dev);\n\n    // copy image pointers\n    for (int i = 0; i < atts->cmn.num_colors; i++) {\n        const sg_attachment_desc* color_desc = &desc->colors[i];\n        _SOKOL_UNUSED(color_desc);\n        SOKOL_ASSERT(color_desc->image.id != SG_INVALID_ID);\n        SOKOL_ASSERT(0 == atts->d3d11.colors[i].image);\n        SOKOL_ASSERT(color_images[i] && (color_images[i]->slot.id == color_desc->image.id));\n        SOKOL_ASSERT(_sg_is_valid_rendertarget_color_format(color_images[i]->cmn.pixel_format));\n        atts->d3d11.colors[i].image = color_images[i];\n\n        const sg_attachment_desc* resolve_desc = &desc->resolves[i];\n        if (resolve_desc->image.id != SG_INVALID_ID) {\n            SOKOL_ASSERT(0 == atts->d3d11.resolves[i].image);\n            SOKOL_ASSERT(resolve_images[i] && (resolve_images[i]->slot.id == resolve_desc->image.id));\n            SOKOL_ASSERT(color_images[i] && (color_images[i]->cmn.pixel_format == resolve_images[i]->cmn.pixel_format));\n            atts->d3d11.resolves[i].image = resolve_images[i];\n        }\n    }\n    SOKOL_ASSERT(0 == atts->d3d11.depth_stencil.image);\n    const sg_attachment_desc* ds_desc = &desc->depth_stencil;\n    if (ds_desc->image.id != SG_INVALID_ID) {\n        SOKOL_ASSERT(ds_img && (ds_img->slot.id == ds_desc->image.id));\n        SOKOL_ASSERT(_sg_is_valid_rendertarget_depth_format(ds_img->cmn.pixel_format));\n        atts->d3d11.depth_stencil.image = ds_img;\n    }\n\n    // create render-target views\n    for (int i = 0; i < atts->cmn.num_colors; i++) {\n        const _sg_attachment_common_t* cmn_color_att = &atts->cmn.colors[i];\n        const _sg_image_t* color_img = color_images[i];\n        SOKOL_ASSERT(0 == atts->d3d11.colors[i].view.rtv);\n        const bool msaa = color_img->cmn.sample_count > 1;\n        D3D11_RENDER_TARGET_VIEW_DESC d3d11_rtv_desc;\n        _sg_clear(&d3d11_rtv_desc, sizeof(d3d11_rtv_desc));\n        d3d11_rtv_desc.Format = _sg_d3d11_rtv_pixel_format(color_img->cmn.pixel_format);\n        if (color_img->cmn.type == SG_IMAGETYPE_2D) {\n            if (msaa) {\n                d3d11_rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;\n            } else {\n                d3d11_rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;\n                d3d11_rtv_desc.Texture2D.MipSlice = (UINT)cmn_color_att->mip_level;\n            }\n        } else if ((color_img->cmn.type == SG_IMAGETYPE_CUBE) || (color_img->cmn.type == SG_IMAGETYPE_ARRAY)) {\n            if (msaa) {\n                d3d11_rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;\n                d3d11_rtv_desc.Texture2DMSArray.FirstArraySlice = (UINT)cmn_color_att->slice;\n                d3d11_rtv_desc.Texture2DMSArray.ArraySize = 1;\n            } else {\n                d3d11_rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;\n                d3d11_rtv_desc.Texture2DArray.MipSlice = (UINT)cmn_color_att->mip_level;\n                d3d11_rtv_desc.Texture2DArray.FirstArraySlice = (UINT)cmn_color_att->slice;\n                d3d11_rtv_desc.Texture2DArray.ArraySize = 1;\n            }\n        } else {\n            SOKOL_ASSERT(color_img->cmn.type == SG_IMAGETYPE_3D);\n            SOKOL_ASSERT(!msaa);\n            d3d11_rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;\n            d3d11_rtv_desc.Texture3D.MipSlice = (UINT)cmn_color_att->mip_level;\n            d3d11_rtv_desc.Texture3D.FirstWSlice = (UINT)cmn_color_att->slice;\n            d3d11_rtv_desc.Texture3D.WSize = 1;\n        }\n        SOKOL_ASSERT(color_img->d3d11.res);\n        HRESULT hr = _sg_d3d11_CreateRenderTargetView(_sg.d3d11.dev, color_img->d3d11.res, &d3d11_rtv_desc, &atts->d3d11.colors[i].view.rtv);\n        if (!(SUCCEEDED(hr) && atts->d3d11.colors[i].view.rtv)) {\n            _SG_ERROR(D3D11_CREATE_RTV_FAILED);\n            return SG_RESOURCESTATE_FAILED;\n        }\n        _sg_d3d11_setlabel(atts->d3d11.colors[i].view.rtv, desc->label);\n    }\n    SOKOL_ASSERT(0 == atts->d3d11.depth_stencil.view.dsv);\n    if (ds_desc->image.id != SG_INVALID_ID) {\n        const _sg_attachment_common_t* cmn_ds_att = &atts->cmn.depth_stencil;\n        const bool msaa = ds_img->cmn.sample_count > 1;\n        D3D11_DEPTH_STENCIL_VIEW_DESC d3d11_dsv_desc;\n        _sg_clear(&d3d11_dsv_desc, sizeof(d3d11_dsv_desc));\n        d3d11_dsv_desc.Format = _sg_d3d11_dsv_pixel_format(ds_img->cmn.pixel_format);\n        SOKOL_ASSERT(ds_img && ds_img->cmn.type != SG_IMAGETYPE_3D);\n        if (ds_img->cmn.type == SG_IMAGETYPE_2D) {\n            if (msaa) {\n                d3d11_dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;\n            } else {\n                d3d11_dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;\n                d3d11_dsv_desc.Texture2D.MipSlice = (UINT)cmn_ds_att->mip_level;\n            }\n        } else if ((ds_img->cmn.type == SG_IMAGETYPE_CUBE) || (ds_img->cmn.type == SG_IMAGETYPE_ARRAY)) {\n            if (msaa) {\n                d3d11_dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;\n                d3d11_dsv_desc.Texture2DMSArray.FirstArraySlice = (UINT)cmn_ds_att->slice;\n                d3d11_dsv_desc.Texture2DMSArray.ArraySize = 1;\n            } else {\n                d3d11_dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;\n                d3d11_dsv_desc.Texture2DArray.MipSlice = (UINT)cmn_ds_att->mip_level;\n                d3d11_dsv_desc.Texture2DArray.FirstArraySlice = (UINT)cmn_ds_att->slice;\n                d3d11_dsv_desc.Texture2DArray.ArraySize = 1;\n            }\n        }\n        SOKOL_ASSERT(ds_img->d3d11.res);\n        HRESULT hr = _sg_d3d11_CreateDepthStencilView(_sg.d3d11.dev, ds_img->d3d11.res, &d3d11_dsv_desc, &atts->d3d11.depth_stencil.view.dsv);\n        if (!(SUCCEEDED(hr) && atts->d3d11.depth_stencil.view.dsv)) {\n            _SG_ERROR(D3D11_CREATE_DSV_FAILED);\n            return SG_RESOURCESTATE_FAILED;\n        }\n        _sg_d3d11_setlabel(atts->d3d11.depth_stencil.view.dsv, desc->label);\n    }\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_discard_attachments(_sg_attachments_t* atts) {\n    SOKOL_ASSERT(atts);\n    for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {\n        if (atts->d3d11.colors[i].view.rtv) {\n            _sg_d3d11_Release(atts->d3d11.colors[i].view.rtv);\n        }\n        if (atts->d3d11.resolves[i].view.rtv) {\n            _sg_d3d11_Release(atts->d3d11.resolves[i].view.rtv);\n        }\n    }\n    if (atts->d3d11.depth_stencil.view.dsv) {\n        _sg_d3d11_Release(atts->d3d11.depth_stencil.view.dsv);\n    }\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_d3d11_attachments_color_image(const _sg_attachments_t* atts, int index) {\n    SOKOL_ASSERT(atts && (index >= 0) && (index < SG_MAX_COLOR_ATTACHMENTS));\n    return atts->d3d11.colors[index].image;\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_d3d11_attachments_resolve_image(const _sg_attachments_t* atts, int index) {\n    SOKOL_ASSERT(atts && (index >= 0) && (index < SG_MAX_COLOR_ATTACHMENTS));\n    return atts->d3d11.resolves[index].image;\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_d3d11_attachments_ds_image(const _sg_attachments_t* atts) {\n    SOKOL_ASSERT(atts);\n    return atts->d3d11.depth_stencil.image;\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_begin_pass(const sg_pass* pass) {\n    SOKOL_ASSERT(pass);\n\n    const _sg_attachments_t* atts = _sg.cur_pass.atts;\n    const sg_swapchain* swapchain = &pass->swapchain;\n    const sg_pass_action* action = &pass->action;\n\n    int num_rtvs = 0;\n    ID3D11RenderTargetView* rtvs[SG_MAX_COLOR_ATTACHMENTS] = { 0 };\n    ID3D11DepthStencilView* dsv = 0;\n    _sg.d3d11.cur_pass.render_view = 0;\n    _sg.d3d11.cur_pass.resolve_view = 0;\n    if (atts) {\n        num_rtvs = atts->cmn.num_colors;\n        for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {\n            rtvs[i] = atts->d3d11.colors[i].view.rtv;\n        }\n        dsv = atts->d3d11.depth_stencil.view.dsv;\n    } else {\n        // NOTE: depth-stencil-view is optional\n        SOKOL_ASSERT(swapchain->d3d11.render_view);\n        num_rtvs = 1;\n        rtvs[0] = (ID3D11RenderTargetView*) swapchain->d3d11.render_view;\n        dsv = (ID3D11DepthStencilView*) swapchain->d3d11.depth_stencil_view;\n        _sg.d3d11.cur_pass.render_view = (ID3D11RenderTargetView*) swapchain->d3d11.render_view;\n        _sg.d3d11.cur_pass.resolve_view = (ID3D11RenderTargetView*) swapchain->d3d11.resolve_view;\n    }\n    // apply the render-target- and depth-stencil-views\n    _sg_d3d11_OMSetRenderTargets(_sg.d3d11.ctx, SG_MAX_COLOR_ATTACHMENTS, rtvs, dsv);\n    _sg_stats_add(d3d11.pass.num_om_set_render_targets, 1);\n\n    // set viewport and scissor rect to cover whole screen\n    D3D11_VIEWPORT vp;\n    _sg_clear(&vp, sizeof(vp));\n    vp.Width = (FLOAT) _sg.cur_pass.width;\n    vp.Height = (FLOAT) _sg.cur_pass.height;\n    vp.MaxDepth = 1.0f;\n    _sg_d3d11_RSSetViewports(_sg.d3d11.ctx, 1, &vp);\n    D3D11_RECT rect;\n    rect.left = 0;\n    rect.top = 0;\n    rect.right = _sg.cur_pass.width;\n    rect.bottom = _sg.cur_pass.height;\n    _sg_d3d11_RSSetScissorRects(_sg.d3d11.ctx, 1, &rect);\n\n    // perform clear action\n    for (int i = 0; i < num_rtvs; i++) {\n        if (action->colors[i].load_action == SG_LOADACTION_CLEAR) {\n            _sg_d3d11_ClearRenderTargetView(_sg.d3d11.ctx, rtvs[i], (float*)&action->colors[i].clear_value);\n            _sg_stats_add(d3d11.pass.num_clear_render_target_view, 1);\n        }\n    }\n    UINT ds_flags = 0;\n    if (action->depth.load_action == SG_LOADACTION_CLEAR) {\n        ds_flags |= D3D11_CLEAR_DEPTH;\n    }\n    if (action->stencil.load_action == SG_LOADACTION_CLEAR) {\n        ds_flags |= D3D11_CLEAR_STENCIL;\n    }\n    if ((0 != ds_flags) && dsv) {\n        _sg_d3d11_ClearDepthStencilView(_sg.d3d11.ctx, dsv, ds_flags, action->depth.clear_value, action->stencil.clear_value);\n        _sg_stats_add(d3d11.pass.num_clear_depth_stencil_view, 1);\n    }\n}\n\n// D3D11CalcSubresource only exists for C++\n_SOKOL_PRIVATE UINT _sg_d3d11_calcsubresource(UINT mip_slice, UINT array_slice, UINT mip_levels) {\n    return mip_slice + array_slice * mip_levels;\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_end_pass(void) {\n    SOKOL_ASSERT(_sg.d3d11.ctx);\n\n    // need to resolve MSAA render attachments into texture?\n    if (_sg.cur_pass.atts_id.id != SG_INVALID_ID) {\n        // ...for offscreen pass...\n        SOKOL_ASSERT(_sg.cur_pass.atts && _sg.cur_pass.atts->slot.id == _sg.cur_pass.atts_id.id);\n        for (int i = 0; i < _sg.cur_pass.atts->cmn.num_colors; i++) {\n            const _sg_image_t* resolve_img = _sg.cur_pass.atts->d3d11.resolves[i].image;\n            if (resolve_img) {\n                const _sg_image_t* color_img = _sg.cur_pass.atts->d3d11.colors[i].image;\n                const _sg_attachment_common_t* cmn_color_att = &_sg.cur_pass.atts->cmn.colors[i];\n                const _sg_attachment_common_t* cmn_resolve_att = &_sg.cur_pass.atts->cmn.resolves[i];\n                SOKOL_ASSERT(resolve_img->slot.id == cmn_resolve_att->image_id.id);\n                SOKOL_ASSERT(color_img && (color_img->slot.id == cmn_color_att->image_id.id));\n                SOKOL_ASSERT(color_img->cmn.sample_count > 1);\n                SOKOL_ASSERT(resolve_img->cmn.sample_count == 1);\n                const UINT src_subres = _sg_d3d11_calcsubresource(\n                    (UINT)cmn_color_att->mip_level,\n                    (UINT)cmn_color_att->slice,\n                    (UINT)color_img->cmn.num_mipmaps);\n                const UINT dst_subres = _sg_d3d11_calcsubresource(\n                    (UINT)cmn_resolve_att->mip_level,\n                    (UINT)cmn_resolve_att->slice,\n                    (UINT)resolve_img->cmn.num_mipmaps);\n                _sg_d3d11_ResolveSubresource(_sg.d3d11.ctx,\n                    resolve_img->d3d11.res,\n                    dst_subres,\n                    color_img->d3d11.res,\n                    src_subres,\n                    color_img->d3d11.format);\n                _sg_stats_add(d3d11.pass.num_resolve_subresource, 1);\n            }\n        }\n    } else {\n        // ...for swapchain pass...\n        if (_sg.d3d11.cur_pass.resolve_view) {\n            SOKOL_ASSERT(_sg.d3d11.cur_pass.render_view);\n            SOKOL_ASSERT(_sg.cur_pass.swapchain.sample_count > 1);\n            SOKOL_ASSERT(_sg.cur_pass.swapchain.color_fmt > SG_PIXELFORMAT_NONE);\n            ID3D11Resource* d3d11_render_res = 0;\n            ID3D11Resource* d3d11_resolve_res = 0;\n            _sg_d3d11_GetResource((ID3D11View*)_sg.d3d11.cur_pass.render_view, &d3d11_render_res);\n            _sg_d3d11_GetResource((ID3D11View*)_sg.d3d11.cur_pass.resolve_view, &d3d11_resolve_res);\n            SOKOL_ASSERT(d3d11_render_res);\n            SOKOL_ASSERT(d3d11_resolve_res);\n            const sg_pixel_format color_fmt = _sg.cur_pass.swapchain.color_fmt;\n            _sg_d3d11_ResolveSubresource(_sg.d3d11.ctx, d3d11_resolve_res, 0, d3d11_render_res, 0, _sg_d3d11_rtv_pixel_format(color_fmt));\n            _sg_d3d11_Release(d3d11_render_res);\n            _sg_d3d11_Release(d3d11_resolve_res);\n            _sg_stats_add(d3d11.pass.num_resolve_subresource, 1);\n        }\n    }\n    _sg.d3d11.cur_pass.render_view = 0;\n    _sg.d3d11.cur_pass.resolve_view = 0;\n    _sg.d3d11.cur_pipeline = 0;\n    _sg.d3d11.cur_pipeline_id.id = SG_INVALID_ID;\n    _sg_d3d11_clear_state();\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_apply_viewport(int x, int y, int w, int h, bool origin_top_left) {\n    SOKOL_ASSERT(_sg.d3d11.ctx);\n    D3D11_VIEWPORT vp;\n    vp.TopLeftX = (FLOAT) x;\n    vp.TopLeftY = (FLOAT) (origin_top_left ? y : (_sg.cur_pass.height - (y + h)));\n    vp.Width = (FLOAT) w;\n    vp.Height = (FLOAT) h;\n    vp.MinDepth = 0.0f;\n    vp.MaxDepth = 1.0f;\n    _sg_d3d11_RSSetViewports(_sg.d3d11.ctx, 1, &vp);\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_apply_scissor_rect(int x, int y, int w, int h, bool origin_top_left) {\n    SOKOL_ASSERT(_sg.d3d11.ctx);\n    D3D11_RECT rect;\n    rect.left = x;\n    rect.top = (origin_top_left ? y : (_sg.cur_pass.height - (y + h)));\n    rect.right = x + w;\n    rect.bottom = origin_top_left ? (y + h) : (_sg.cur_pass.height - y);\n    _sg_d3d11_RSSetScissorRects(_sg.d3d11.ctx, 1, &rect);\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_apply_pipeline(_sg_pipeline_t* pip) {\n    SOKOL_ASSERT(pip);\n    SOKOL_ASSERT(pip->shader && (pip->cmn.shader_id.id == pip->shader->slot.id));\n    SOKOL_ASSERT(_sg.d3d11.ctx);\n    SOKOL_ASSERT(pip->d3d11.rs && pip->d3d11.bs && pip->d3d11.dss);\n\n    _sg.d3d11.cur_pipeline = pip;\n    _sg.d3d11.cur_pipeline_id.id = pip->slot.id;\n    _sg.d3d11.use_indexed_draw = (pip->d3d11.index_format != DXGI_FORMAT_UNKNOWN);\n    _sg.d3d11.use_instanced_draw = pip->cmn.use_instanced_draw;\n\n    _sg_d3d11_RSSetState(_sg.d3d11.ctx, pip->d3d11.rs);\n    _sg_d3d11_OMSetDepthStencilState(_sg.d3d11.ctx, pip->d3d11.dss, pip->d3d11.stencil_ref);\n    _sg_d3d11_OMSetBlendState(_sg.d3d11.ctx, pip->d3d11.bs, (float*)&pip->cmn.blend_color, 0xFFFFFFFF);\n    _sg_d3d11_IASetPrimitiveTopology(_sg.d3d11.ctx, pip->d3d11.topology);\n    _sg_d3d11_IASetInputLayout(_sg.d3d11.ctx, pip->d3d11.il);\n    _sg_d3d11_VSSetShader(_sg.d3d11.ctx, pip->shader->d3d11.vs, NULL, 0);\n    _sg_d3d11_VSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, pip->shader->d3d11.stage[SG_SHADERSTAGE_VS].cbufs);\n    _sg_d3d11_PSSetShader(_sg.d3d11.ctx, pip->shader->d3d11.fs, NULL, 0);\n    _sg_d3d11_PSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, pip->shader->d3d11.stage[SG_SHADERSTAGE_FS].cbufs);\n    _sg_stats_add(d3d11.pipeline.num_rs_set_state, 1);\n    _sg_stats_add(d3d11.pipeline.num_om_set_depth_stencil_state, 1);\n    _sg_stats_add(d3d11.pipeline.num_om_set_blend_state, 1);\n    _sg_stats_add(d3d11.pipeline.num_ia_set_primitive_topology, 1);\n    _sg_stats_add(d3d11.pipeline.num_ia_set_input_layout, 1);\n    _sg_stats_add(d3d11.pipeline.num_vs_set_shader, 1);\n    _sg_stats_add(d3d11.pipeline.num_vs_set_constant_buffers, 1);\n    _sg_stats_add(d3d11.pipeline.num_ps_set_shader, 1);\n    _sg_stats_add(d3d11.pipeline.num_ps_set_constant_buffers, 1);\n}\n\n_SOKOL_PRIVATE bool _sg_d3d11_apply_bindings(_sg_bindings_t* bnd) {\n    SOKOL_ASSERT(bnd);\n    SOKOL_ASSERT(bnd->pip);\n    SOKOL_ASSERT(_sg.d3d11.ctx);\n\n    // gather all the D3D11 resources into arrays\n    ID3D11Buffer* d3d11_ib = bnd->ib ? bnd->ib->d3d11.buf : 0;\n    ID3D11Buffer* d3d11_vbs[SG_MAX_VERTEX_BUFFERS] = {0};\n    UINT d3d11_vb_offsets[SG_MAX_VERTEX_BUFFERS] = {0};\n    ID3D11ShaderResourceView* d3d11_vs_srvs[_SG_D3D11_MAX_SHADERSTAGE_SRVS] = {0};\n    ID3D11ShaderResourceView* d3d11_fs_srvs[_SG_D3D11_MAX_SHADERSTAGE_SRVS] = {0};\n    ID3D11SamplerState* d3d11_vs_smps[SG_MAX_SHADERSTAGE_SAMPLERS] = {0};\n    ID3D11SamplerState* d3d11_fs_smps[SG_MAX_SHADERSTAGE_SAMPLERS] = {0};\n    for (int i = 0; i < bnd->num_vbs; i++) {\n        SOKOL_ASSERT(bnd->vbs[i]->d3d11.buf);\n        d3d11_vbs[i] = bnd->vbs[i]->d3d11.buf;\n        d3d11_vb_offsets[i] = (UINT)bnd->vb_offsets[i];\n    }\n    for (int i = 0; i < bnd->num_vs_imgs; i++) {\n        SOKOL_ASSERT(bnd->vs_imgs[i]->d3d11.srv);\n        d3d11_vs_srvs[_SG_D3D11_SHADERSTAGE_IMAGE_SRV_OFFSET + i] = bnd->vs_imgs[i]->d3d11.srv;\n    }\n    for (int i = 0; i < bnd->num_vs_sbufs; i++) {\n        SOKOL_ASSERT(bnd->vs_sbufs[i]->d3d11.srv);\n        d3d11_vs_srvs[_SG_D3D11_SHADERSTAGE_BUFFER_SRV_OFFSET + i] = bnd->vs_sbufs[i]->d3d11.srv;\n    }\n    for (int i = 0; i < bnd->num_fs_imgs; i++) {\n        SOKOL_ASSERT(bnd->fs_imgs[i]->d3d11.srv);\n        d3d11_fs_srvs[_SG_D3D11_SHADERSTAGE_IMAGE_SRV_OFFSET + i] = bnd->fs_imgs[i]->d3d11.srv;\n    }\n    for (int i = 0; i < bnd->num_fs_sbufs; i++) {\n        SOKOL_ASSERT(bnd->fs_sbufs[i]->d3d11.srv);\n        d3d11_fs_srvs[_SG_D3D11_SHADERSTAGE_BUFFER_SRV_OFFSET + i] = bnd->fs_sbufs[i]->d3d11.srv;\n    }\n    for (int i = 0; i < bnd->num_vs_smps; i++) {\n        SOKOL_ASSERT(bnd->vs_smps[i]->d3d11.smp);\n        d3d11_vs_smps[i] = bnd->vs_smps[i]->d3d11.smp;\n    }\n    for (int i = 0; i < bnd->num_fs_smps; i++) {\n        SOKOL_ASSERT(bnd->fs_smps[i]->d3d11.smp);\n        d3d11_fs_smps[i] = bnd->fs_smps[i]->d3d11.smp;\n    }\n    _sg_d3d11_IASetVertexBuffers(_sg.d3d11.ctx, 0, SG_MAX_VERTEX_BUFFERS, d3d11_vbs, bnd->pip->d3d11.vb_strides, d3d11_vb_offsets);\n    _sg_d3d11_IASetIndexBuffer(_sg.d3d11.ctx, d3d11_ib, bnd->pip->d3d11.index_format, (UINT)bnd->ib_offset);\n    _sg_d3d11_VSSetShaderResources(_sg.d3d11.ctx, 0, _SG_D3D11_MAX_SHADERSTAGE_SRVS, d3d11_vs_srvs);\n    _sg_d3d11_PSSetShaderResources(_sg.d3d11.ctx, 0, _SG_D3D11_MAX_SHADERSTAGE_SRVS, d3d11_fs_srvs);\n    _sg_d3d11_VSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_SAMPLERS, d3d11_vs_smps);\n    _sg_d3d11_PSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_SAMPLERS, d3d11_fs_smps);\n    _sg_stats_add(d3d11.bindings.num_ia_set_vertex_buffers, 1);\n    _sg_stats_add(d3d11.bindings.num_ia_set_index_buffer, 1);\n    _sg_stats_add(d3d11.bindings.num_vs_set_shader_resources, 1);\n    _sg_stats_add(d3d11.bindings.num_ps_set_shader_resources, 1);\n    _sg_stats_add(d3d11.bindings.num_vs_set_samplers, 1);\n    _sg_stats_add(d3d11.bindings.num_ps_set_samplers, 1);\n    return true;\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_apply_uniforms(sg_shader_stage stage_index, int ub_index, const sg_range* data) {\n    SOKOL_ASSERT(_sg.d3d11.ctx);\n    SOKOL_ASSERT(_sg.d3d11.cur_pipeline && _sg.d3d11.cur_pipeline->slot.id == _sg.d3d11.cur_pipeline_id.id);\n    SOKOL_ASSERT(_sg.d3d11.cur_pipeline->shader && _sg.d3d11.cur_pipeline->shader->slot.id == _sg.d3d11.cur_pipeline->cmn.shader_id.id);\n    SOKOL_ASSERT(ub_index < _sg.d3d11.cur_pipeline->shader->cmn.stage[stage_index].num_uniform_blocks);\n    SOKOL_ASSERT(data->size == _sg.d3d11.cur_pipeline->shader->cmn.stage[stage_index].uniform_blocks[ub_index].size);\n    ID3D11Buffer* cb = _sg.d3d11.cur_pipeline->shader->d3d11.stage[stage_index].cbufs[ub_index];\n    SOKOL_ASSERT(cb);\n    _sg_d3d11_UpdateSubresource(_sg.d3d11.ctx, (ID3D11Resource*)cb, 0, NULL, data->ptr, 0, 0);\n    _sg_stats_add(d3d11.uniforms.num_update_subresource, 1);\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_draw(int base_element, int num_elements, int num_instances) {\n    const bool use_instanced_draw = (num_instances > 1) || (_sg.d3d11.use_instanced_draw);\n    if (_sg.d3d11.use_indexed_draw) {\n        if (use_instanced_draw) {\n            _sg_d3d11_DrawIndexedInstanced(_sg.d3d11.ctx, (UINT)num_elements, (UINT)num_instances, (UINT)base_element, 0, 0);\n            _sg_stats_add(d3d11.draw.num_draw_indexed_instanced, 1);\n        } else {\n            _sg_d3d11_DrawIndexed(_sg.d3d11.ctx, (UINT)num_elements, (UINT)base_element, 0);\n            _sg_stats_add(d3d11.draw.num_draw_indexed, 1);\n        }\n    } else {\n        if (use_instanced_draw) {\n            _sg_d3d11_DrawInstanced(_sg.d3d11.ctx, (UINT)num_elements, (UINT)num_instances, (UINT)base_element, 0);\n            _sg_stats_add(d3d11.draw.num_draw_instanced, 1);\n        } else {\n            _sg_d3d11_Draw(_sg.d3d11.ctx, (UINT)num_elements, (UINT)base_element);\n            _sg_stats_add(d3d11.draw.num_draw, 1);\n        }\n    }\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_commit(void) {\n    // empty\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_update_buffer(_sg_buffer_t* buf, const sg_range* data) {\n    SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0));\n    SOKOL_ASSERT(_sg.d3d11.ctx);\n    SOKOL_ASSERT(buf->d3d11.buf);\n    D3D11_MAPPED_SUBRESOURCE d3d11_msr;\n    HRESULT hr = _sg_d3d11_Map(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr);\n    _sg_stats_add(d3d11.num_map, 1);\n    if (SUCCEEDED(hr)) {\n        memcpy(d3d11_msr.pData, data->ptr, data->size);\n        _sg_d3d11_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0);\n        _sg_stats_add(d3d11.num_unmap, 1);\n    } else {\n        _SG_ERROR(D3D11_MAP_FOR_UPDATE_BUFFER_FAILED);\n    }\n}\n\n_SOKOL_PRIVATE void _sg_d3d11_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) {\n    SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0));\n    SOKOL_ASSERT(_sg.d3d11.ctx);\n    SOKOL_ASSERT(buf->d3d11.buf);\n    D3D11_MAP map_type = new_frame ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE;\n    D3D11_MAPPED_SUBRESOURCE d3d11_msr;\n    HRESULT hr = _sg_d3d11_Map(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0, map_type, 0, &d3d11_msr);\n    _sg_stats_add(d3d11.num_map, 1);\n    if (SUCCEEDED(hr)) {\n        uint8_t* dst_ptr = (uint8_t*)d3d11_msr.pData + buf->cmn.append_pos;\n        memcpy(dst_ptr, data->ptr, data->size);\n        _sg_d3d11_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0);\n        _sg_stats_add(d3d11.num_unmap, 1);\n    } else {\n        _SG_ERROR(D3D11_MAP_FOR_APPEND_BUFFER_FAILED);\n    }\n}\n\n// see: https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-resources-subresources\n// also see: https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-d3d11calcsubresource\n_SOKOL_PRIVATE void _sg_d3d11_update_image(_sg_image_t* img, const sg_image_data* data) {\n    SOKOL_ASSERT(img && data);\n    SOKOL_ASSERT(_sg.d3d11.ctx);\n    SOKOL_ASSERT(img->d3d11.res);\n    const int num_faces = (img->cmn.type == SG_IMAGETYPE_CUBE) ? 6:1;\n    const int num_slices = (img->cmn.type == SG_IMAGETYPE_ARRAY) ? img->cmn.num_slices:1;\n    const int num_depth_slices = (img->cmn.type == SG_IMAGETYPE_3D) ? img->cmn.num_slices:1;\n    UINT subres_index = 0;\n    HRESULT hr;\n    D3D11_MAPPED_SUBRESOURCE d3d11_msr;\n    for (int face_index = 0; face_index < num_faces; face_index++) {\n        for (int slice_index = 0; slice_index < num_slices; slice_index++) {\n            for (int mip_index = 0; mip_index < img->cmn.num_mipmaps; mip_index++, subres_index++) {\n                SOKOL_ASSERT(subres_index < (SG_MAX_MIPMAPS * SG_MAX_TEXTUREARRAY_LAYERS));\n                const int mip_width = _sg_miplevel_dim(img->cmn.width, mip_index);\n                const int mip_height = _sg_miplevel_dim(img->cmn.height, mip_index);\n                const int src_row_pitch = _sg_row_pitch(img->cmn.pixel_format, mip_width, 1);\n                const int src_depth_pitch = _sg_surface_pitch(img->cmn.pixel_format, mip_width, mip_height, 1);\n                const sg_range* subimg_data = &(data->subimage[face_index][mip_index]);\n                const size_t slice_size = subimg_data->size / (size_t)num_slices;\n                SOKOL_ASSERT(slice_size == (size_t)(src_depth_pitch * num_depth_slices));\n                const size_t slice_offset = slice_size * (size_t)slice_index;\n                const uint8_t* slice_ptr = ((const uint8_t*)subimg_data->ptr) + slice_offset;\n                hr = _sg_d3d11_Map(_sg.d3d11.ctx, img->d3d11.res, subres_index, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr);\n                _sg_stats_add(d3d11.num_map, 1);\n                if (SUCCEEDED(hr)) {\n                    const uint8_t* src_ptr = slice_ptr;\n                    uint8_t* dst_ptr = (uint8_t*)d3d11_msr.pData;\n                    for (int depth_index = 0; depth_index < num_depth_slices; depth_index++) {\n                        if (src_row_pitch == (int)d3d11_msr.RowPitch) {\n                            const size_t copy_size = slice_size / (size_t)num_depth_slices;\n                            SOKOL_ASSERT((copy_size * (size_t)num_depth_slices) == slice_size);\n                            memcpy(dst_ptr, src_ptr, copy_size);\n                        } else {\n                            SOKOL_ASSERT(src_row_pitch < (int)d3d11_msr.RowPitch);\n                            const uint8_t* src_row_ptr = src_ptr;\n                            uint8_t* dst_row_ptr = dst_ptr;\n                            for (int row_index = 0; row_index < mip_height; row_index++) {\n                                memcpy(dst_row_ptr, src_row_ptr, (size_t)src_row_pitch);\n                                src_row_ptr += src_row_pitch;\n                                dst_row_ptr += d3d11_msr.RowPitch;\n                            }\n                        }\n                        src_ptr += src_depth_pitch;\n                        dst_ptr += d3d11_msr.DepthPitch;\n                    }\n                    _sg_d3d11_Unmap(_sg.d3d11.ctx, img->d3d11.res, subres_index);\n                    _sg_stats_add(d3d11.num_unmap, 1);\n                } else {\n                    _SG_ERROR(D3D11_MAP_FOR_UPDATE_IMAGE_FAILED);\n                }\n            }\n        }\n    }\n}\n\n// ███    ███ ███████ ████████  █████  ██          ██████   █████   ██████ ██   ██ ███████ ███    ██ ██████\n// ████  ████ ██         ██    ██   ██ ██          ██   ██ ██   ██ ██      ██  ██  ██      ████   ██ ██   ██\n// ██ ████ ██ █████      ██    ███████ ██          ██████  ███████ ██      █████   █████   ██ ██  ██ ██   ██\n// ██  ██  ██ ██         ██    ██   ██ ██          ██   ██ ██   ██ ██      ██  ██  ██      ██  ██ ██ ██   ██\n// ██      ██ ███████    ██    ██   ██ ███████     ██████  ██   ██  ██████ ██   ██ ███████ ██   ████ ██████\n//\n// >>metal backend\n#elif defined(SOKOL_METAL)\n\n#if __has_feature(objc_arc)\n#define _SG_OBJC_RETAIN(obj) { }\n#define _SG_OBJC_RELEASE(obj) { obj = nil; }\n#else\n#define _SG_OBJC_RETAIN(obj) { [obj retain]; }\n#define _SG_OBJC_RELEASE(obj) { [obj release]; obj = nil; }\n#endif\n\n//-- enum translation functions ------------------------------------------------\n_SOKOL_PRIVATE MTLLoadAction _sg_mtl_load_action(sg_load_action a) {\n    switch (a) {\n        case SG_LOADACTION_CLEAR:       return MTLLoadActionClear;\n        case SG_LOADACTION_LOAD:        return MTLLoadActionLoad;\n        case SG_LOADACTION_DONTCARE:    return MTLLoadActionDontCare;\n        default: SOKOL_UNREACHABLE;     return (MTLLoadAction)0;\n    }\n}\n\n_SOKOL_PRIVATE MTLStoreAction _sg_mtl_store_action(sg_store_action a, bool resolve) {\n    switch (a) {\n        case SG_STOREACTION_STORE:\n            if (resolve) {\n                return MTLStoreActionStoreAndMultisampleResolve;\n            } else {\n                return MTLStoreActionStore;\n            }\n            break;\n        case SG_STOREACTION_DONTCARE:\n            if (resolve) {\n                return MTLStoreActionMultisampleResolve;\n            } else {\n                return MTLStoreActionDontCare;\n            }\n            break;\n        default: SOKOL_UNREACHABLE; return (MTLStoreAction)0;\n    }\n}\n\n_SOKOL_PRIVATE MTLResourceOptions _sg_mtl_resource_options_storage_mode_managed_or_shared(void) {\n    #if defined(_SG_TARGET_MACOS)\n    if (_sg.mtl.use_shared_storage_mode) {\n        return MTLResourceStorageModeShared;\n    } else {\n        return MTLResourceStorageModeManaged;\n    }\n    #else\n        // MTLResourceStorageModeManaged is not even defined on iOS SDK\n        return MTLResourceStorageModeShared;\n    #endif\n}\n\n_SOKOL_PRIVATE MTLResourceOptions _sg_mtl_buffer_resource_options(sg_usage usg) {\n    switch (usg) {\n        case SG_USAGE_IMMUTABLE:\n            return _sg_mtl_resource_options_storage_mode_managed_or_shared();\n        case SG_USAGE_DYNAMIC:\n        case SG_USAGE_STREAM:\n            return MTLResourceCPUCacheModeWriteCombined | _sg_mtl_resource_options_storage_mode_managed_or_shared();\n        default:\n            SOKOL_UNREACHABLE;\n            return 0;\n    }\n}\n\n_SOKOL_PRIVATE MTLVertexStepFunction _sg_mtl_step_function(sg_vertex_step step) {\n    switch (step) {\n        case SG_VERTEXSTEP_PER_VERTEX:      return MTLVertexStepFunctionPerVertex;\n        case SG_VERTEXSTEP_PER_INSTANCE:    return MTLVertexStepFunctionPerInstance;\n        default: SOKOL_UNREACHABLE; return (MTLVertexStepFunction)0;\n    }\n}\n\n_SOKOL_PRIVATE MTLVertexFormat _sg_mtl_vertex_format(sg_vertex_format fmt) {\n    switch (fmt) {\n        case SG_VERTEXFORMAT_FLOAT:     return MTLVertexFormatFloat;\n        case SG_VERTEXFORMAT_FLOAT2:    return MTLVertexFormatFloat2;\n        case SG_VERTEXFORMAT_FLOAT3:    return MTLVertexFormatFloat3;\n        case SG_VERTEXFORMAT_FLOAT4:    return MTLVertexFormatFloat4;\n        case SG_VERTEXFORMAT_BYTE4:     return MTLVertexFormatChar4;\n        case SG_VERTEXFORMAT_BYTE4N:    return MTLVertexFormatChar4Normalized;\n        case SG_VERTEXFORMAT_UBYTE4:    return MTLVertexFormatUChar4;\n        case SG_VERTEXFORMAT_UBYTE4N:   return MTLVertexFormatUChar4Normalized;\n        case SG_VERTEXFORMAT_SHORT2:    return MTLVertexFormatShort2;\n        case SG_VERTEXFORMAT_SHORT2N:   return MTLVertexFormatShort2Normalized;\n        case SG_VERTEXFORMAT_USHORT2N:  return MTLVertexFormatUShort2Normalized;\n        case SG_VERTEXFORMAT_SHORT4:    return MTLVertexFormatShort4;\n        case SG_VERTEXFORMAT_SHORT4N:   return MTLVertexFormatShort4Normalized;\n        case SG_VERTEXFORMAT_USHORT4N:  return MTLVertexFormatUShort4Normalized;\n        case SG_VERTEXFORMAT_UINT10_N2: return MTLVertexFormatUInt1010102Normalized;\n        case SG_VERTEXFORMAT_HALF2:     return MTLVertexFormatHalf2;\n        case SG_VERTEXFORMAT_HALF4:     return MTLVertexFormatHalf4;\n        default: SOKOL_UNREACHABLE; return (MTLVertexFormat)0;\n    }\n}\n\n_SOKOL_PRIVATE MTLPrimitiveType _sg_mtl_primitive_type(sg_primitive_type t) {\n    switch (t) {\n        case SG_PRIMITIVETYPE_POINTS:           return MTLPrimitiveTypePoint;\n        case SG_PRIMITIVETYPE_LINES:            return MTLPrimitiveTypeLine;\n        case SG_PRIMITIVETYPE_LINE_STRIP:       return MTLPrimitiveTypeLineStrip;\n        case SG_PRIMITIVETYPE_TRIANGLES:        return MTLPrimitiveTypeTriangle;\n        case SG_PRIMITIVETYPE_TRIANGLE_STRIP:   return MTLPrimitiveTypeTriangleStrip;\n        default: SOKOL_UNREACHABLE; return (MTLPrimitiveType)0;\n    }\n}\n\n_SOKOL_PRIVATE MTLPixelFormat _sg_mtl_pixel_format(sg_pixel_format fmt) {\n    switch (fmt) {\n        case SG_PIXELFORMAT_R8:                     return MTLPixelFormatR8Unorm;\n        case SG_PIXELFORMAT_R8SN:                   return MTLPixelFormatR8Snorm;\n        case SG_PIXELFORMAT_R8UI:                   return MTLPixelFormatR8Uint;\n        case SG_PIXELFORMAT_R8SI:                   return MTLPixelFormatR8Sint;\n        case SG_PIXELFORMAT_R16:                    return MTLPixelFormatR16Unorm;\n        case SG_PIXELFORMAT_R16SN:                  return MTLPixelFormatR16Snorm;\n        case SG_PIXELFORMAT_R16UI:                  return MTLPixelFormatR16Uint;\n        case SG_PIXELFORMAT_R16SI:                  return MTLPixelFormatR16Sint;\n        case SG_PIXELFORMAT_R16F:                   return MTLPixelFormatR16Float;\n        case SG_PIXELFORMAT_RG8:                    return MTLPixelFormatRG8Unorm;\n        case SG_PIXELFORMAT_RG8SN:                  return MTLPixelFormatRG8Snorm;\n        case SG_PIXELFORMAT_RG8UI:                  return MTLPixelFormatRG8Uint;\n        case SG_PIXELFORMAT_RG8SI:                  return MTLPixelFormatRG8Sint;\n        case SG_PIXELFORMAT_R32UI:                  return MTLPixelFormatR32Uint;\n        case SG_PIXELFORMAT_R32SI:                  return MTLPixelFormatR32Sint;\n        case SG_PIXELFORMAT_R32F:                   return MTLPixelFormatR32Float;\n        case SG_PIXELFORMAT_RG16:                   return MTLPixelFormatRG16Unorm;\n        case SG_PIXELFORMAT_RG16SN:                 return MTLPixelFormatRG16Snorm;\n        case SG_PIXELFORMAT_RG16UI:                 return MTLPixelFormatRG16Uint;\n        case SG_PIXELFORMAT_RG16SI:                 return MTLPixelFormatRG16Sint;\n        case SG_PIXELFORMAT_RG16F:                  return MTLPixelFormatRG16Float;\n        case SG_PIXELFORMAT_RGBA8:                  return MTLPixelFormatRGBA8Unorm;\n        case SG_PIXELFORMAT_SRGB8A8:                return MTLPixelFormatRGBA8Unorm_sRGB;\n        case SG_PIXELFORMAT_RGBA8SN:                return MTLPixelFormatRGBA8Snorm;\n        case SG_PIXELFORMAT_RGBA8UI:                return MTLPixelFormatRGBA8Uint;\n        case SG_PIXELFORMAT_RGBA8SI:                return MTLPixelFormatRGBA8Sint;\n        case SG_PIXELFORMAT_BGRA8:                  return MTLPixelFormatBGRA8Unorm;\n        case SG_PIXELFORMAT_RGB10A2:                return MTLPixelFormatRGB10A2Unorm;\n        case SG_PIXELFORMAT_RG11B10F:               return MTLPixelFormatRG11B10Float;\n        case SG_PIXELFORMAT_RGB9E5:                 return MTLPixelFormatRGB9E5Float;\n        case SG_PIXELFORMAT_RG32UI:                 return MTLPixelFormatRG32Uint;\n        case SG_PIXELFORMAT_RG32SI:                 return MTLPixelFormatRG32Sint;\n        case SG_PIXELFORMAT_RG32F:                  return MTLPixelFormatRG32Float;\n        case SG_PIXELFORMAT_RGBA16:                 return MTLPixelFormatRGBA16Unorm;\n        case SG_PIXELFORMAT_RGBA16SN:               return MTLPixelFormatRGBA16Snorm;\n        case SG_PIXELFORMAT_RGBA16UI:               return MTLPixelFormatRGBA16Uint;\n        case SG_PIXELFORMAT_RGBA16SI:               return MTLPixelFormatRGBA16Sint;\n        case SG_PIXELFORMAT_RGBA16F:                return MTLPixelFormatRGBA16Float;\n        case SG_PIXELFORMAT_RGBA32UI:               return MTLPixelFormatRGBA32Uint;\n        case SG_PIXELFORMAT_RGBA32SI:               return MTLPixelFormatRGBA32Sint;\n        case SG_PIXELFORMAT_RGBA32F:                return MTLPixelFormatRGBA32Float;\n        case SG_PIXELFORMAT_DEPTH:                  return MTLPixelFormatDepth32Float;\n        case SG_PIXELFORMAT_DEPTH_STENCIL:          return MTLPixelFormatDepth32Float_Stencil8;\n        #if defined(_SG_TARGET_MACOS)\n        case SG_PIXELFORMAT_BC1_RGBA:               return MTLPixelFormatBC1_RGBA;\n        case SG_PIXELFORMAT_BC2_RGBA:               return MTLPixelFormatBC2_RGBA;\n        case SG_PIXELFORMAT_BC3_RGBA:               return MTLPixelFormatBC3_RGBA;\n        case SG_PIXELFORMAT_BC3_SRGBA:              return MTLPixelFormatBC3_RGBA_sRGB;\n        case SG_PIXELFORMAT_BC4_R:                  return MTLPixelFormatBC4_RUnorm;\n        case SG_PIXELFORMAT_BC4_RSN:                return MTLPixelFormatBC4_RSnorm;\n        case SG_PIXELFORMAT_BC5_RG:                 return MTLPixelFormatBC5_RGUnorm;\n        case SG_PIXELFORMAT_BC5_RGSN:               return MTLPixelFormatBC5_RGSnorm;\n        case SG_PIXELFORMAT_BC6H_RGBF:              return MTLPixelFormatBC6H_RGBFloat;\n        case SG_PIXELFORMAT_BC6H_RGBUF:             return MTLPixelFormatBC6H_RGBUfloat;\n        case SG_PIXELFORMAT_BC7_RGBA:               return MTLPixelFormatBC7_RGBAUnorm;\n        case SG_PIXELFORMAT_BC7_SRGBA:              return MTLPixelFormatBC7_RGBAUnorm_sRGB;\n        #else\n        case SG_PIXELFORMAT_PVRTC_RGB_2BPP:         return MTLPixelFormatPVRTC_RGB_2BPP;\n        case SG_PIXELFORMAT_PVRTC_RGB_4BPP:         return MTLPixelFormatPVRTC_RGB_4BPP;\n        case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:        return MTLPixelFormatPVRTC_RGBA_2BPP;\n        case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:        return MTLPixelFormatPVRTC_RGBA_4BPP;\n        case SG_PIXELFORMAT_ETC2_RGB8:              return MTLPixelFormatETC2_RGB8;\n        case SG_PIXELFORMAT_ETC2_SRGB8:             return MTLPixelFormatETC2_RGB8_sRGB;\n        case SG_PIXELFORMAT_ETC2_RGB8A1:            return MTLPixelFormatETC2_RGB8A1;\n        case SG_PIXELFORMAT_ETC2_RGBA8:             return MTLPixelFormatEAC_RGBA8;\n        case SG_PIXELFORMAT_ETC2_SRGB8A8:           return MTLPixelFormatEAC_RGBA8_sRGB;\n        case SG_PIXELFORMAT_EAC_R11:                return MTLPixelFormatEAC_R11Unorm;\n        case SG_PIXELFORMAT_EAC_R11SN:              return MTLPixelFormatEAC_R11Snorm;\n        case SG_PIXELFORMAT_EAC_RG11:               return MTLPixelFormatEAC_RG11Unorm;\n        case SG_PIXELFORMAT_EAC_RG11SN:             return MTLPixelFormatEAC_RG11Snorm;\n        case SG_PIXELFORMAT_ASTC_4x4_RGBA:          return MTLPixelFormatASTC_4x4_LDR;\n        case SG_PIXELFORMAT_ASTC_4x4_SRGBA:         return MTLPixelFormatASTC_4x4_sRGB;\n        #endif\n        default: return MTLPixelFormatInvalid;\n    }\n}\n\n_SOKOL_PRIVATE MTLColorWriteMask _sg_mtl_color_write_mask(sg_color_mask m) {\n    MTLColorWriteMask mtl_mask = MTLColorWriteMaskNone;\n    if (m & SG_COLORMASK_R) {\n        mtl_mask |= MTLColorWriteMaskRed;\n    }\n    if (m & SG_COLORMASK_G) {\n        mtl_mask |= MTLColorWriteMaskGreen;\n    }\n    if (m & SG_COLORMASK_B) {\n        mtl_mask |= MTLColorWriteMaskBlue;\n    }\n    if (m & SG_COLORMASK_A) {\n        mtl_mask |= MTLColorWriteMaskAlpha;\n    }\n    return mtl_mask;\n}\n\n_SOKOL_PRIVATE MTLBlendOperation _sg_mtl_blend_op(sg_blend_op op) {\n    switch (op) {\n        case SG_BLENDOP_ADD:                return MTLBlendOperationAdd;\n        case SG_BLENDOP_SUBTRACT:           return MTLBlendOperationSubtract;\n        case SG_BLENDOP_REVERSE_SUBTRACT:   return MTLBlendOperationReverseSubtract;\n        default: SOKOL_UNREACHABLE; return (MTLBlendOperation)0;\n    }\n}\n\n_SOKOL_PRIVATE MTLBlendFactor _sg_mtl_blend_factor(sg_blend_factor f) {\n    switch (f) {\n        case SG_BLENDFACTOR_ZERO:                   return MTLBlendFactorZero;\n        case SG_BLENDFACTOR_ONE:                    return MTLBlendFactorOne;\n        case SG_BLENDFACTOR_SRC_COLOR:              return MTLBlendFactorSourceColor;\n        case SG_BLENDFACTOR_ONE_MINUS_SRC_COLOR:    return MTLBlendFactorOneMinusSourceColor;\n        case SG_BLENDFACTOR_SRC_ALPHA:              return MTLBlendFactorSourceAlpha;\n        case SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:    return MTLBlendFactorOneMinusSourceAlpha;\n        case SG_BLENDFACTOR_DST_COLOR:              return MTLBlendFactorDestinationColor;\n        case SG_BLENDFACTOR_ONE_MINUS_DST_COLOR:    return MTLBlendFactorOneMinusDestinationColor;\n        case SG_BLENDFACTOR_DST_ALPHA:              return MTLBlendFactorDestinationAlpha;\n        case SG_BLENDFACTOR_ONE_MINUS_DST_ALPHA:    return MTLBlendFactorOneMinusDestinationAlpha;\n        case SG_BLENDFACTOR_SRC_ALPHA_SATURATED:    return MTLBlendFactorSourceAlphaSaturated;\n        case SG_BLENDFACTOR_BLEND_COLOR:            return MTLBlendFactorBlendColor;\n        case SG_BLENDFACTOR_ONE_MINUS_BLEND_COLOR:  return MTLBlendFactorOneMinusBlendColor;\n        case SG_BLENDFACTOR_BLEND_ALPHA:            return MTLBlendFactorBlendAlpha;\n        case SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA:  return MTLBlendFactorOneMinusBlendAlpha;\n        default: SOKOL_UNREACHABLE; return (MTLBlendFactor)0;\n    }\n}\n\n_SOKOL_PRIVATE MTLCompareFunction _sg_mtl_compare_func(sg_compare_func f) {\n    switch (f) {\n        case SG_COMPAREFUNC_NEVER:          return MTLCompareFunctionNever;\n        case SG_COMPAREFUNC_LESS:           return MTLCompareFunctionLess;\n        case SG_COMPAREFUNC_EQUAL:          return MTLCompareFunctionEqual;\n        case SG_COMPAREFUNC_LESS_EQUAL:     return MTLCompareFunctionLessEqual;\n        case SG_COMPAREFUNC_GREATER:        return MTLCompareFunctionGreater;\n        case SG_COMPAREFUNC_NOT_EQUAL:      return MTLCompareFunctionNotEqual;\n        case SG_COMPAREFUNC_GREATER_EQUAL:  return MTLCompareFunctionGreaterEqual;\n        case SG_COMPAREFUNC_ALWAYS:         return MTLCompareFunctionAlways;\n        default: SOKOL_UNREACHABLE; return (MTLCompareFunction)0;\n    }\n}\n\n_SOKOL_PRIVATE MTLStencilOperation _sg_mtl_stencil_op(sg_stencil_op op) {\n    switch (op) {\n        case SG_STENCILOP_KEEP:         return MTLStencilOperationKeep;\n        case SG_STENCILOP_ZERO:         return MTLStencilOperationZero;\n        case SG_STENCILOP_REPLACE:      return MTLStencilOperationReplace;\n        case SG_STENCILOP_INCR_CLAMP:   return MTLStencilOperationIncrementClamp;\n        case SG_STENCILOP_DECR_CLAMP:   return MTLStencilOperationDecrementClamp;\n        case SG_STENCILOP_INVERT:       return MTLStencilOperationInvert;\n        case SG_STENCILOP_INCR_WRAP:    return MTLStencilOperationIncrementWrap;\n        case SG_STENCILOP_DECR_WRAP:    return MTLStencilOperationDecrementWrap;\n        default: SOKOL_UNREACHABLE; return (MTLStencilOperation)0;\n    }\n}\n\n_SOKOL_PRIVATE MTLCullMode _sg_mtl_cull_mode(sg_cull_mode m) {\n    switch (m) {\n        case SG_CULLMODE_NONE:  return MTLCullModeNone;\n        case SG_CULLMODE_FRONT: return MTLCullModeFront;\n        case SG_CULLMODE_BACK:  return MTLCullModeBack;\n        default: SOKOL_UNREACHABLE; return (MTLCullMode)0;\n    }\n}\n\n_SOKOL_PRIVATE MTLWinding _sg_mtl_winding(sg_face_winding w) {\n    switch (w) {\n        case SG_FACEWINDING_CW:     return MTLWindingClockwise;\n        case SG_FACEWINDING_CCW:    return MTLWindingCounterClockwise;\n        default: SOKOL_UNREACHABLE; return (MTLWinding)0;\n    }\n}\n\n_SOKOL_PRIVATE MTLIndexType _sg_mtl_index_type(sg_index_type t) {\n    switch (t) {\n        case SG_INDEXTYPE_UINT16:   return MTLIndexTypeUInt16;\n        case SG_INDEXTYPE_UINT32:   return MTLIndexTypeUInt32;\n        default: SOKOL_UNREACHABLE; return (MTLIndexType)0;\n    }\n}\n\n_SOKOL_PRIVATE int _sg_mtl_index_size(sg_index_type t) {\n    switch (t) {\n        case SG_INDEXTYPE_NONE:     return 0;\n        case SG_INDEXTYPE_UINT16:   return 2;\n        case SG_INDEXTYPE_UINT32:   return 4;\n        default: SOKOL_UNREACHABLE; return 0;\n    }\n}\n\n_SOKOL_PRIVATE MTLTextureType _sg_mtl_texture_type(sg_image_type t) {\n    switch (t) {\n        case SG_IMAGETYPE_2D:       return MTLTextureType2D;\n        case SG_IMAGETYPE_CUBE:     return MTLTextureTypeCube;\n        case SG_IMAGETYPE_3D:       return MTLTextureType3D;\n        case SG_IMAGETYPE_ARRAY:    return MTLTextureType2DArray;\n        default: SOKOL_UNREACHABLE; return (MTLTextureType)0;\n    }\n}\n\n_SOKOL_PRIVATE bool _sg_mtl_is_pvrtc(sg_pixel_format fmt) {\n    switch (fmt) {\n        case SG_PIXELFORMAT_PVRTC_RGB_2BPP:\n        case SG_PIXELFORMAT_PVRTC_RGB_4BPP:\n        case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:\n        case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:\n            return true;\n        default:\n            return false;\n    }\n}\n\n_SOKOL_PRIVATE MTLSamplerAddressMode _sg_mtl_address_mode(sg_wrap w) {\n    if (_sg.features.image_clamp_to_border) {\n        if (@available(macOS 12.0, iOS 14.0, *)) {\n            // border color feature available\n            switch (w) {\n                case SG_WRAP_REPEAT:            return MTLSamplerAddressModeRepeat;\n                case SG_WRAP_CLAMP_TO_EDGE:     return MTLSamplerAddressModeClampToEdge;\n                case SG_WRAP_CLAMP_TO_BORDER:   return MTLSamplerAddressModeClampToBorderColor;\n                case SG_WRAP_MIRRORED_REPEAT:   return MTLSamplerAddressModeMirrorRepeat;\n                default: SOKOL_UNREACHABLE; return (MTLSamplerAddressMode)0;\n            }\n        }\n    }\n    // fallthrough: clamp to border no supported\n    switch (w) {\n        case SG_WRAP_REPEAT:            return MTLSamplerAddressModeRepeat;\n        case SG_WRAP_CLAMP_TO_EDGE:     return MTLSamplerAddressModeClampToEdge;\n        case SG_WRAP_CLAMP_TO_BORDER:   return MTLSamplerAddressModeClampToEdge;\n        case SG_WRAP_MIRRORED_REPEAT:   return MTLSamplerAddressModeMirrorRepeat;\n        default: SOKOL_UNREACHABLE; return (MTLSamplerAddressMode)0;\n    }\n}\n\n_SOKOL_PRIVATE API_AVAILABLE(ios(14.0), macos(12.0)) MTLSamplerBorderColor _sg_mtl_border_color(sg_border_color c) {\n    switch (c) {\n        case SG_BORDERCOLOR_TRANSPARENT_BLACK: return MTLSamplerBorderColorTransparentBlack;\n        case SG_BORDERCOLOR_OPAQUE_BLACK: return MTLSamplerBorderColorOpaqueBlack;\n        case SG_BORDERCOLOR_OPAQUE_WHITE: return MTLSamplerBorderColorOpaqueWhite;\n        default: SOKOL_UNREACHABLE; return (MTLSamplerBorderColor)0;\n    }\n}\n\n_SOKOL_PRIVATE MTLSamplerMinMagFilter _sg_mtl_minmag_filter(sg_filter f) {\n    switch (f) {\n        case SG_FILTER_NEAREST:\n            return MTLSamplerMinMagFilterNearest;\n        case SG_FILTER_LINEAR:\n            return MTLSamplerMinMagFilterLinear;\n        default:\n            SOKOL_UNREACHABLE; return (MTLSamplerMinMagFilter)0;\n    }\n}\n\n_SOKOL_PRIVATE MTLSamplerMipFilter _sg_mtl_mipmap_filter(sg_filter f) {\n    switch (f) {\n        case SG_FILTER_NONE:\n            return MTLSamplerMipFilterNotMipmapped;\n        case SG_FILTER_NEAREST:\n            return MTLSamplerMipFilterNearest;\n        case SG_FILTER_LINEAR:\n            return MTLSamplerMipFilterLinear;\n        default:\n            SOKOL_UNREACHABLE; return (MTLSamplerMipFilter)0;\n    }\n}\n\n//-- a pool for all Metal resource objects, with deferred release queue ---------\n_SOKOL_PRIVATE void _sg_mtl_init_pool(const sg_desc* desc) {\n    _sg.mtl.idpool.num_slots = 2 *\n        (\n            2 * desc->buffer_pool_size +\n            4 * desc->image_pool_size +\n            1 * desc->sampler_pool_size +\n            4 * desc->shader_pool_size +\n            2 * desc->pipeline_pool_size +\n            desc->attachments_pool_size +\n            128\n        );\n    _sg.mtl.idpool.pool = [NSMutableArray arrayWithCapacity:(NSUInteger)_sg.mtl.idpool.num_slots];\n    _SG_OBJC_RETAIN(_sg.mtl.idpool.pool);\n    NSNull* null = [NSNull null];\n    for (int i = 0; i < _sg.mtl.idpool.num_slots; i++) {\n        [_sg.mtl.idpool.pool addObject:null];\n    }\n    SOKOL_ASSERT([_sg.mtl.idpool.pool count] == (NSUInteger)_sg.mtl.idpool.num_slots);\n    // a queue of currently free slot indices\n    _sg.mtl.idpool.free_queue_top = 0;\n    _sg.mtl.idpool.free_queue = (int*)_sg_malloc_clear((size_t)_sg.mtl.idpool.num_slots * sizeof(int));\n    // pool slot 0 is reserved!\n    for (int i = _sg.mtl.idpool.num_slots-1; i >= 1; i--) {\n        _sg.mtl.idpool.free_queue[_sg.mtl.idpool.free_queue_top++] = i;\n    }\n    // a circular queue which holds release items (frame index when a resource is to be released, and the resource's pool index\n    _sg.mtl.idpool.release_queue_front = 0;\n    _sg.mtl.idpool.release_queue_back = 0;\n    _sg.mtl.idpool.release_queue = (_sg_mtl_release_item_t*)_sg_malloc_clear((size_t)_sg.mtl.idpool.num_slots * sizeof(_sg_mtl_release_item_t));\n    for (int i = 0; i < _sg.mtl.idpool.num_slots; i++) {\n        _sg.mtl.idpool.release_queue[i].frame_index = 0;\n        _sg.mtl.idpool.release_queue[i].slot_index = _SG_MTL_INVALID_SLOT_INDEX;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_mtl_destroy_pool(void) {\n    _sg_free(_sg.mtl.idpool.release_queue);  _sg.mtl.idpool.release_queue = 0;\n    _sg_free(_sg.mtl.idpool.free_queue);     _sg.mtl.idpool.free_queue = 0;\n    _SG_OBJC_RELEASE(_sg.mtl.idpool.pool);\n}\n\n// get a new free resource pool slot\n_SOKOL_PRIVATE int _sg_mtl_alloc_pool_slot(void) {\n    SOKOL_ASSERT(_sg.mtl.idpool.free_queue_top > 0);\n    const int slot_index = _sg.mtl.idpool.free_queue[--_sg.mtl.idpool.free_queue_top];\n    SOKOL_ASSERT((slot_index > 0) && (slot_index < _sg.mtl.idpool.num_slots));\n    return slot_index;\n}\n\n// put a free resource pool slot back into the free-queue\n_SOKOL_PRIVATE void _sg_mtl_free_pool_slot(int slot_index) {\n    SOKOL_ASSERT(_sg.mtl.idpool.free_queue_top < _sg.mtl.idpool.num_slots);\n    SOKOL_ASSERT((slot_index > 0) && (slot_index < _sg.mtl.idpool.num_slots));\n    _sg.mtl.idpool.free_queue[_sg.mtl.idpool.free_queue_top++] = slot_index;\n}\n\n// add an MTLResource to the pool, return pool index or 0 if input was 'nil'\n_SOKOL_PRIVATE int _sg_mtl_add_resource(id res) {\n    if (nil == res) {\n        return _SG_MTL_INVALID_SLOT_INDEX;\n    }\n    _sg_stats_add(metal.idpool.num_added, 1);\n    const int slot_index = _sg_mtl_alloc_pool_slot();\n    // NOTE: the NSMutableArray will take ownership of its items\n    SOKOL_ASSERT([NSNull null] == _sg.mtl.idpool.pool[(NSUInteger)slot_index]);\n    _sg.mtl.idpool.pool[(NSUInteger)slot_index] = res;\n    return slot_index;\n}\n\n/*  mark an MTLResource for release, this will put the resource into the\n    deferred-release queue, and the resource will then be released N frames later,\n    the special pool index 0 will be ignored (this means that a nil\n    value was provided to _sg_mtl_add_resource()\n*/\n_SOKOL_PRIVATE void _sg_mtl_release_resource(uint32_t frame_index, int slot_index) {\n    if (slot_index == _SG_MTL_INVALID_SLOT_INDEX) {\n        return;\n    }\n    _sg_stats_add(metal.idpool.num_released, 1);\n    SOKOL_ASSERT((slot_index > 0) && (slot_index < _sg.mtl.idpool.num_slots));\n    SOKOL_ASSERT([NSNull null] != _sg.mtl.idpool.pool[(NSUInteger)slot_index]);\n    int release_index = _sg.mtl.idpool.release_queue_front++;\n    if (_sg.mtl.idpool.release_queue_front >= _sg.mtl.idpool.num_slots) {\n        // wrap-around\n        _sg.mtl.idpool.release_queue_front = 0;\n    }\n    // release queue full?\n    SOKOL_ASSERT(_sg.mtl.idpool.release_queue_front != _sg.mtl.idpool.release_queue_back);\n    SOKOL_ASSERT(0 == _sg.mtl.idpool.release_queue[release_index].frame_index);\n    const uint32_t safe_to_release_frame_index = frame_index + SG_NUM_INFLIGHT_FRAMES + 1;\n    _sg.mtl.idpool.release_queue[release_index].frame_index = safe_to_release_frame_index;\n    _sg.mtl.idpool.release_queue[release_index].slot_index = slot_index;\n}\n\n// run garbage-collection pass on all resources in the release-queue\n_SOKOL_PRIVATE void _sg_mtl_garbage_collect(uint32_t frame_index) {\n    while (_sg.mtl.idpool.release_queue_back != _sg.mtl.idpool.release_queue_front) {\n        if (frame_index < _sg.mtl.idpool.release_queue[_sg.mtl.idpool.release_queue_back].frame_index) {\n            // don't need to check further, release-items past this are too young\n            break;\n        }\n        _sg_stats_add(metal.idpool.num_garbage_collected, 1);\n        // safe to release this resource\n        const int slot_index = _sg.mtl.idpool.release_queue[_sg.mtl.idpool.release_queue_back].slot_index;\n        SOKOL_ASSERT((slot_index > 0) && (slot_index < _sg.mtl.idpool.num_slots));\n        // note: the NSMutableArray takes ownership of its items, assigning an NSNull object will\n        // release the object, no matter if using ARC or not\n        SOKOL_ASSERT(_sg.mtl.idpool.pool[(NSUInteger)slot_index] != [NSNull null]);\n        _sg.mtl.idpool.pool[(NSUInteger)slot_index] = [NSNull null];\n        // put the now free pool index back on the free queue\n        _sg_mtl_free_pool_slot(slot_index);\n        // reset the release queue slot and advance the back index\n        _sg.mtl.idpool.release_queue[_sg.mtl.idpool.release_queue_back].frame_index = 0;\n        _sg.mtl.idpool.release_queue[_sg.mtl.idpool.release_queue_back].slot_index = _SG_MTL_INVALID_SLOT_INDEX;\n        _sg.mtl.idpool.release_queue_back++;\n        if (_sg.mtl.idpool.release_queue_back >= _sg.mtl.idpool.num_slots) {\n            // wrap-around\n            _sg.mtl.idpool.release_queue_back = 0;\n        }\n    }\n}\n\n_SOKOL_PRIVATE id _sg_mtl_id(int slot_index) {\n    return _sg.mtl.idpool.pool[(NSUInteger)slot_index];\n}\n\n_SOKOL_PRIVATE void _sg_mtl_clear_state_cache(void) {\n    _sg_clear(&_sg.mtl.state_cache, sizeof(_sg.mtl.state_cache));\n}\n\n// https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf\n_SOKOL_PRIVATE void _sg_mtl_init_caps(void) {\n    #if defined(_SG_TARGET_MACOS)\n        _sg.backend = SG_BACKEND_METAL_MACOS;\n    #elif defined(_SG_TARGET_IOS)\n        #if defined(_SG_TARGET_IOS_SIMULATOR)\n            _sg.backend = SG_BACKEND_METAL_SIMULATOR;\n        #else\n            _sg.backend = SG_BACKEND_METAL_IOS;\n        #endif\n    #endif\n    _sg.features.origin_top_left = true;\n    _sg.features.mrt_independent_blend_state = true;\n    _sg.features.mrt_independent_write_mask = true;\n    _sg.features.storage_buffer = true;\n\n    _sg.features.image_clamp_to_border = false;\n    #if (MAC_OS_X_VERSION_MAX_ALLOWED >= 120000) || (__IPHONE_OS_VERSION_MAX_ALLOWED >= 140000)\n    if (@available(macOS 12.0, iOS 14.0, *)) {\n        _sg.features.image_clamp_to_border = [_sg.mtl.device supportsFamily:MTLGPUFamilyApple7]\n                                             || [_sg.mtl.device supportsFamily:MTLGPUFamilyMac2];\n        #if (MAC_OS_X_VERSION_MAX_ALLOWED >= 130000) || (__IPHONE_OS_VERSION_MAX_ALLOWED >= 160000)\n        if (!_sg.features.image_clamp_to_border) {\n            if (@available(macOS 13.0, iOS 16.0, *)) {\n                _sg.features.image_clamp_to_border = [_sg.mtl.device supportsFamily:MTLGPUFamilyMetal3];\n            }\n        }\n        #endif\n    }\n    #endif\n\n    #if defined(_SG_TARGET_MACOS)\n        _sg.limits.max_image_size_2d = 16 * 1024;\n        _sg.limits.max_image_size_cube = 16 * 1024;\n        _sg.limits.max_image_size_3d = 2 * 1024;\n        _sg.limits.max_image_size_array = 16 * 1024;\n        _sg.limits.max_image_array_layers = 2 * 1024;\n    #else\n        // FIXME: newer iOS devices support 16k textures\n        _sg.limits.max_image_size_2d = 8 * 1024;\n        _sg.limits.max_image_size_cube = 8 * 1024;\n        _sg.limits.max_image_size_3d = 2 * 1024;\n        _sg.limits.max_image_size_array = 8 * 1024;\n        _sg.limits.max_image_array_layers = 2 * 1024;\n    #endif\n    _sg.limits.max_vertex_attrs = SG_MAX_VERTEX_ATTRIBUTES;\n\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R8]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R8SN]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R8UI]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R8SI]);\n    #if defined(_SG_TARGET_MACOS)\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16]);\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16SN]);\n    #else\n        _sg_pixelformat_sfbr(&_sg.formats[SG_PIXELFORMAT_R16]);\n        _sg_pixelformat_sfbr(&_sg.formats[SG_PIXELFORMAT_R16SN]);\n    #endif\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R16UI]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R16SI]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16F]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG8]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG8SN]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG8UI]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG8SI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32UI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32SI]);\n    #if defined(_SG_TARGET_MACOS)\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R32F]);\n    #else\n        _sg_pixelformat_sbr(&_sg.formats[SG_PIXELFORMAT_R32F]);\n    #endif\n    #if defined(_SG_TARGET_MACOS)\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16]);\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16SN]);\n    #else\n        _sg_pixelformat_sfbr(&_sg.formats[SG_PIXELFORMAT_RG16]);\n        _sg_pixelformat_sfbr(&_sg.formats[SG_PIXELFORMAT_RG16SN]);\n    #endif\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG16UI]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG16SI]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16F]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA8]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_SRGB8A8]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA8SN]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA8UI]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA8SI]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_BGRA8]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGB10A2]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG11B10F]);\n    #if defined(_SG_TARGET_MACOS)\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RGB9E5]);\n        _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG32UI]);\n        _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG32SI]);\n    #else\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGB9E5]);\n        _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG32UI]);\n        _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG32SI]);\n    #endif\n    #if defined(_SG_TARGET_MACOS)\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG32F]);\n    #else\n        _sg_pixelformat_sbr(&_sg.formats[SG_PIXELFORMAT_RG32F]);\n    #endif\n    #if defined(_SG_TARGET_MACOS)\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16]);\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16SN]);\n    #else\n        _sg_pixelformat_sfbr(&_sg.formats[SG_PIXELFORMAT_RGBA16]);\n        _sg_pixelformat_sfbr(&_sg.formats[SG_PIXELFORMAT_RGBA16SN]);\n    #endif\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA16UI]);\n    _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA16SI]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16F]);\n    #if defined(_SG_TARGET_MACOS)\n        _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA32UI]);\n        _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA32SI]);\n        _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);\n    #else\n        _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA32UI]);\n        _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA32SI]);\n        _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);\n    #endif\n    _sg_pixelformat_srmd(&_sg.formats[SG_PIXELFORMAT_DEPTH]);\n    _sg_pixelformat_srmd(&_sg.formats[SG_PIXELFORMAT_DEPTH_STENCIL]);\n    #if defined(_SG_TARGET_MACOS)\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC1_RGBA]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC2_RGBA]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC3_RGBA]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC3_SRGBA]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC4_R]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC4_RSN]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC5_RG]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC5_RGSN]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC6H_RGBF]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC6H_RGBUF]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC7_RGBA]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC7_SRGBA]);\n    #else\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGB_2BPP]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGB_4BPP]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGBA_2BPP]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_PVRTC_RGBA_4BPP]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGB8]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_SRGB8]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGB8A1]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGBA8]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_SRGB8A8]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_EAC_R11]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_EAC_R11SN]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_EAC_RG11]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_EAC_RG11SN]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ASTC_4x4_RGBA]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ASTC_4x4_SRGBA]);\n\n    #endif\n}\n\n//-- main Metal backend state and functions ------------------------------------\n_SOKOL_PRIVATE void _sg_mtl_setup_backend(const sg_desc* desc) {\n    // assume already zero-initialized\n    SOKOL_ASSERT(desc);\n    SOKOL_ASSERT(desc->environment.metal.device);\n    SOKOL_ASSERT(desc->uniform_buffer_size > 0);\n    _sg_mtl_init_pool(desc);\n    _sg_mtl_clear_state_cache();\n    _sg.mtl.valid = true;\n    _sg.mtl.ub_size = desc->uniform_buffer_size;\n    _sg.mtl.sem = dispatch_semaphore_create(SG_NUM_INFLIGHT_FRAMES);\n    _sg.mtl.device = (__bridge id<MTLDevice>) desc->environment.metal.device;\n    _sg.mtl.cmd_queue = [_sg.mtl.device newCommandQueue];\n\n    for (int i = 0; i < SG_NUM_INFLIGHT_FRAMES; i++) {\n        _sg.mtl.uniform_buffers[i] = [_sg.mtl.device\n            newBufferWithLength:(NSUInteger)_sg.mtl.ub_size\n            options:MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared\n        ];\n        #if defined(SOKOL_DEBUG)\n            _sg.mtl.uniform_buffers[i].label = [NSString stringWithFormat:@\"sg-uniform-buffer.%d\", i];\n        #endif\n    }\n\n    if (desc->mtl_force_managed_storage_mode) {\n        _sg.mtl.use_shared_storage_mode = false;\n    } else if (@available(macOS 10.15, iOS 13.0, *)) {\n        // on Intel Macs, always use managed resources even though the\n        // device says it supports unified memory (because of texture restrictions)\n        const bool is_apple_gpu = [_sg.mtl.device supportsFamily:MTLGPUFamilyApple1];\n        if (!is_apple_gpu) {\n            _sg.mtl.use_shared_storage_mode = false;\n        } else {\n            _sg.mtl.use_shared_storage_mode = true;\n        }\n    } else {\n        #if defined(_SG_TARGET_MACOS)\n            _sg.mtl.use_shared_storage_mode = false;\n        #else\n            _sg.mtl.use_shared_storage_mode = true;\n        #endif\n    }\n    _sg_mtl_init_caps();\n}\n\n_SOKOL_PRIVATE void _sg_mtl_discard_backend(void) {\n    SOKOL_ASSERT(_sg.mtl.valid);\n    // wait for the last frame to finish\n    for (int i = 0; i < SG_NUM_INFLIGHT_FRAMES; i++) {\n        dispatch_semaphore_wait(_sg.mtl.sem, DISPATCH_TIME_FOREVER);\n    }\n    // semaphore must be \"relinquished\" before destruction\n    for (int i = 0; i < SG_NUM_INFLIGHT_FRAMES; i++) {\n        dispatch_semaphore_signal(_sg.mtl.sem);\n    }\n    _sg_mtl_garbage_collect(_sg.frame_index + SG_NUM_INFLIGHT_FRAMES + 2);\n    _sg_mtl_destroy_pool();\n    _sg.mtl.valid = false;\n\n    _SG_OBJC_RELEASE(_sg.mtl.sem);\n    _SG_OBJC_RELEASE(_sg.mtl.device);\n    _SG_OBJC_RELEASE(_sg.mtl.cmd_queue);\n    for (int i = 0; i < SG_NUM_INFLIGHT_FRAMES; i++) {\n        _SG_OBJC_RELEASE(_sg.mtl.uniform_buffers[i]);\n    }\n    // NOTE: MTLCommandBuffer and MTLRenderCommandEncoder are auto-released\n    _sg.mtl.cmd_buffer = nil;\n    _sg.mtl.cmd_encoder = nil;\n}\n\n_SOKOL_PRIVATE void _sg_mtl_bind_uniform_buffers(void) {\n    SOKOL_ASSERT(nil != _sg.mtl.cmd_encoder);\n    for (int slot = 0; slot < SG_MAX_SHADERSTAGE_UBS; slot++) {\n        [_sg.mtl.cmd_encoder\n            setVertexBuffer:_sg.mtl.uniform_buffers[_sg.mtl.cur_frame_rotate_index]\n            offset:0\n            atIndex:(NSUInteger)slot];\n        [_sg.mtl.cmd_encoder\n            setFragmentBuffer:_sg.mtl.uniform_buffers[_sg.mtl.cur_frame_rotate_index]\n            offset:0\n            atIndex:(NSUInteger)slot];\n    }\n}\n\n_SOKOL_PRIVATE void _sg_mtl_reset_state_cache(void) {\n    _sg_mtl_clear_state_cache();\n    // need to restore the uniform buffer binding (normally happens in _sg_mtl_begin_pass()\n    if (nil != _sg.mtl.cmd_encoder) {\n        _sg_mtl_bind_uniform_buffers();\n    }\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_mtl_create_buffer(_sg_buffer_t* buf, const sg_buffer_desc* desc) {\n    SOKOL_ASSERT(buf && desc);\n    const bool injected = (0 != desc->mtl_buffers[0]);\n    MTLResourceOptions mtl_options = _sg_mtl_buffer_resource_options(buf->cmn.usage);\n    for (int slot = 0; slot < buf->cmn.num_slots; slot++) {\n        id<MTLBuffer> mtl_buf;\n        if (injected) {\n            SOKOL_ASSERT(desc->mtl_buffers[slot]);\n            mtl_buf = (__bridge id<MTLBuffer>) desc->mtl_buffers[slot];\n        } else {\n            if (buf->cmn.usage == SG_USAGE_IMMUTABLE) {\n                SOKOL_ASSERT(desc->data.ptr);\n                mtl_buf = [_sg.mtl.device newBufferWithBytes:desc->data.ptr length:(NSUInteger)buf->cmn.size options:mtl_options];\n            } else {\n                mtl_buf = [_sg.mtl.device newBufferWithLength:(NSUInteger)buf->cmn.size options:mtl_options];\n            }\n            if (nil == mtl_buf) {\n                _SG_ERROR(METAL_CREATE_BUFFER_FAILED);\n                return SG_RESOURCESTATE_FAILED;\n            }\n        }\n        #if defined(SOKOL_DEBUG)\n            if (desc->label) {\n                mtl_buf.label = [NSString stringWithFormat:@\"%s.%d\", desc->label, slot];\n            }\n        #endif\n        buf->mtl.buf[slot] = _sg_mtl_add_resource(mtl_buf);\n        _SG_OBJC_RELEASE(mtl_buf);\n    }\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_mtl_discard_buffer(_sg_buffer_t* buf) {\n    SOKOL_ASSERT(buf);\n    for (int slot = 0; slot < buf->cmn.num_slots; slot++) {\n        // it's valid to call release resource with '0'\n        _sg_mtl_release_resource(_sg.frame_index, buf->mtl.buf[slot]);\n    }\n}\n\n_SOKOL_PRIVATE void _sg_mtl_copy_image_data(const _sg_image_t* img, __unsafe_unretained id<MTLTexture> mtl_tex, const sg_image_data* data) {\n    const int num_faces = (img->cmn.type == SG_IMAGETYPE_CUBE) ? 6:1;\n    const int num_slices = (img->cmn.type == SG_IMAGETYPE_ARRAY) ? img->cmn.num_slices : 1;\n    for (int face_index = 0; face_index < num_faces; face_index++) {\n        for (int mip_index = 0; mip_index < img->cmn.num_mipmaps; mip_index++) {\n            SOKOL_ASSERT(data->subimage[face_index][mip_index].ptr);\n            SOKOL_ASSERT(data->subimage[face_index][mip_index].size > 0);\n            const uint8_t* data_ptr = (const uint8_t*)data->subimage[face_index][mip_index].ptr;\n            const int mip_width = _sg_miplevel_dim(img->cmn.width, mip_index);\n            const int mip_height = _sg_miplevel_dim(img->cmn.height, mip_index);\n            // special case PVRTC formats: bytePerRow and bytesPerImage must be 0\n            int bytes_per_row = 0;\n            int bytes_per_slice = 0;\n            if (!_sg_mtl_is_pvrtc(img->cmn.pixel_format)) {\n                bytes_per_row = _sg_row_pitch(img->cmn.pixel_format, mip_width, 1);\n                bytes_per_slice = _sg_surface_pitch(img->cmn.pixel_format, mip_width, mip_height, 1);\n            }\n            /* bytesPerImage special case: https://developer.apple.com/documentation/metal/mtltexture/1515679-replaceregion\n\n                \"Supply a nonzero value only when you copy data to a MTLTextureType3D type texture\"\n            */\n            MTLRegion region;\n            int bytes_per_image;\n            if (img->cmn.type == SG_IMAGETYPE_3D) {\n                const int mip_depth = _sg_miplevel_dim(img->cmn.num_slices, mip_index);\n                region = MTLRegionMake3D(0, 0, 0, (NSUInteger)mip_width, (NSUInteger)mip_height, (NSUInteger)mip_depth);\n                bytes_per_image = bytes_per_slice;\n                // FIXME: apparently the minimal bytes_per_image size for 3D texture is 4 KByte... somehow need to handle this\n            } else {\n                region = MTLRegionMake2D(0, 0, (NSUInteger)mip_width, (NSUInteger)mip_height);\n                bytes_per_image = 0;\n            }\n\n            for (int slice_index = 0; slice_index < num_slices; slice_index++) {\n                const int mtl_slice_index = (img->cmn.type == SG_IMAGETYPE_CUBE) ? face_index : slice_index;\n                const int slice_offset = slice_index * bytes_per_slice;\n                SOKOL_ASSERT((slice_offset + bytes_per_slice) <= (int)data->subimage[face_index][mip_index].size);\n                [mtl_tex replaceRegion:region\n                    mipmapLevel:(NSUInteger)mip_index\n                    slice:(NSUInteger)mtl_slice_index\n                    withBytes:data_ptr + slice_offset\n                    bytesPerRow:(NSUInteger)bytes_per_row\n                    bytesPerImage:(NSUInteger)bytes_per_image];\n            }\n        }\n    }\n}\n\n// initialize MTLTextureDescriptor with common attributes\n_SOKOL_PRIVATE bool _sg_mtl_init_texdesc_common(MTLTextureDescriptor* mtl_desc, _sg_image_t* img) {\n    mtl_desc.textureType = _sg_mtl_texture_type(img->cmn.type);\n    mtl_desc.pixelFormat = _sg_mtl_pixel_format(img->cmn.pixel_format);\n    if (MTLPixelFormatInvalid == mtl_desc.pixelFormat) {\n        _SG_ERROR(METAL_TEXTURE_FORMAT_NOT_SUPPORTED);\n        return false;\n    }\n    mtl_desc.width = (NSUInteger)img->cmn.width;\n    mtl_desc.height = (NSUInteger)img->cmn.height;\n    if (SG_IMAGETYPE_3D == img->cmn.type) {\n        mtl_desc.depth = (NSUInteger)img->cmn.num_slices;\n    } else {\n        mtl_desc.depth = 1;\n    }\n    mtl_desc.mipmapLevelCount = (NSUInteger)img->cmn.num_mipmaps;\n    if (SG_IMAGETYPE_ARRAY == img->cmn.type) {\n        mtl_desc.arrayLength = (NSUInteger)img->cmn.num_slices;\n    } else {\n        mtl_desc.arrayLength = 1;\n    }\n    mtl_desc.usage = MTLTextureUsageShaderRead;\n    MTLResourceOptions res_options = 0;\n    if (img->cmn.usage != SG_USAGE_IMMUTABLE) {\n        res_options |= MTLResourceCPUCacheModeWriteCombined;\n    }\n    res_options |= _sg_mtl_resource_options_storage_mode_managed_or_shared();\n    mtl_desc.resourceOptions = res_options;\n    return true;\n}\n\n// initialize MTLTextureDescriptor with rendertarget attributes\n_SOKOL_PRIVATE void _sg_mtl_init_texdesc_rt(MTLTextureDescriptor* mtl_desc, _sg_image_t* img) {\n    SOKOL_ASSERT(img->cmn.render_target);\n    _SOKOL_UNUSED(img);\n    mtl_desc.usage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget;\n    mtl_desc.resourceOptions = MTLResourceStorageModePrivate;\n}\n\n// initialize MTLTextureDescriptor with MSAA attributes\n_SOKOL_PRIVATE void _sg_mtl_init_texdesc_rt_msaa(MTLTextureDescriptor* mtl_desc, _sg_image_t* img) {\n    SOKOL_ASSERT(img->cmn.sample_count > 1);\n    mtl_desc.usage = MTLTextureUsageRenderTarget;\n    mtl_desc.resourceOptions = MTLResourceStorageModePrivate;\n    mtl_desc.textureType = MTLTextureType2DMultisample;\n    mtl_desc.sampleCount = (NSUInteger)img->cmn.sample_count;\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_mtl_create_image(_sg_image_t* img, const sg_image_desc* desc) {\n    SOKOL_ASSERT(img && desc);\n    const bool injected = (0 != desc->mtl_textures[0]);\n\n    // first initialize all Metal resource pool slots to 'empty'\n    for (int i = 0; i < SG_NUM_INFLIGHT_FRAMES; i++) {\n        img->mtl.tex[i] = _sg_mtl_add_resource(nil);\n    }\n\n    // initialize a Metal texture descriptor\n    MTLTextureDescriptor* mtl_desc = [[MTLTextureDescriptor alloc] init];\n    if (!_sg_mtl_init_texdesc_common(mtl_desc, img)) {\n        _SG_OBJC_RELEASE(mtl_desc);\n        return SG_RESOURCESTATE_FAILED;\n    }\n    if (img->cmn.render_target) {\n        if (img->cmn.sample_count > 1) {\n            _sg_mtl_init_texdesc_rt_msaa(mtl_desc, img);\n        } else {\n            _sg_mtl_init_texdesc_rt(mtl_desc, img);\n        }\n    }\n    for (int slot = 0; slot < img->cmn.num_slots; slot++) {\n        id<MTLTexture> mtl_tex;\n        if (injected) {\n            SOKOL_ASSERT(desc->mtl_textures[slot]);\n            mtl_tex = (__bridge id<MTLTexture>) desc->mtl_textures[slot];\n        } else {\n            mtl_tex = [_sg.mtl.device newTextureWithDescriptor:mtl_desc];\n            if (nil == mtl_tex) {\n                _SG_OBJC_RELEASE(mtl_desc);\n                _SG_ERROR(METAL_CREATE_TEXTURE_FAILED);\n                return SG_RESOURCESTATE_FAILED;\n            }\n            if ((img->cmn.usage == SG_USAGE_IMMUTABLE) && !img->cmn.render_target) {\n                _sg_mtl_copy_image_data(img, mtl_tex, &desc->data);\n            }\n        }\n        #if defined(SOKOL_DEBUG)\n            if (desc->label) {\n                mtl_tex.label = [NSString stringWithFormat:@\"%s.%d\", desc->label, slot];\n            }\n        #endif\n        img->mtl.tex[slot] = _sg_mtl_add_resource(mtl_tex);\n        _SG_OBJC_RELEASE(mtl_tex);\n    }\n    _SG_OBJC_RELEASE(mtl_desc);\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_mtl_discard_image(_sg_image_t* img) {\n    SOKOL_ASSERT(img);\n    // it's valid to call release resource with a 'null resource'\n    for (int slot = 0; slot < img->cmn.num_slots; slot++) {\n        _sg_mtl_release_resource(_sg.frame_index, img->mtl.tex[slot]);\n    }\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_mtl_create_sampler(_sg_sampler_t* smp, const sg_sampler_desc* desc) {\n    SOKOL_ASSERT(smp && desc);\n    id<MTLSamplerState> mtl_smp;\n    const bool injected = (0 != desc->mtl_sampler);\n    if (injected) {\n        SOKOL_ASSERT(desc->mtl_sampler);\n        mtl_smp = (__bridge id<MTLSamplerState>) desc->mtl_sampler;\n    } else {\n        MTLSamplerDescriptor* mtl_desc = [[MTLSamplerDescriptor alloc] init];\n        mtl_desc.sAddressMode = _sg_mtl_address_mode(desc->wrap_u);\n        mtl_desc.tAddressMode = _sg_mtl_address_mode(desc->wrap_v);\n        mtl_desc.rAddressMode = _sg_mtl_address_mode(desc->wrap_w);\n        if (_sg.features.image_clamp_to_border) {\n            if (@available(macOS 12.0, iOS 14.0, *)) {\n                mtl_desc.borderColor  = _sg_mtl_border_color(desc->border_color);\n            }\n        }\n        mtl_desc.minFilter = _sg_mtl_minmag_filter(desc->min_filter);\n        mtl_desc.magFilter = _sg_mtl_minmag_filter(desc->mag_filter);\n        mtl_desc.mipFilter = _sg_mtl_mipmap_filter(desc->mipmap_filter);\n        mtl_desc.lodMinClamp = desc->min_lod;\n        mtl_desc.lodMaxClamp = desc->max_lod;\n        // FIXME: lodAverage?\n        mtl_desc.maxAnisotropy = desc->max_anisotropy;\n        mtl_desc.normalizedCoordinates = YES;\n        mtl_desc.compareFunction = _sg_mtl_compare_func(desc->compare);\n        #if defined(SOKOL_DEBUG)\n            if (desc->label) {\n                mtl_desc.label = [NSString stringWithUTF8String:desc->label];\n            }\n        #endif\n        mtl_smp = [_sg.mtl.device newSamplerStateWithDescriptor:mtl_desc];\n        _SG_OBJC_RELEASE(mtl_desc);\n        if (nil == mtl_smp) {\n            _SG_ERROR(METAL_CREATE_SAMPLER_FAILED);\n            return SG_RESOURCESTATE_FAILED;\n        }\n    }\n    smp->mtl.sampler_state = _sg_mtl_add_resource(mtl_smp);\n    _SG_OBJC_RELEASE(mtl_smp);\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_mtl_discard_sampler(_sg_sampler_t* smp) {\n    SOKOL_ASSERT(smp);\n    // it's valid to call release resource with a 'null resource'\n    _sg_mtl_release_resource(_sg.frame_index, smp->mtl.sampler_state);\n}\n\n_SOKOL_PRIVATE id<MTLLibrary> _sg_mtl_compile_library(const char* src) {\n    NSError* err = NULL;\n    id<MTLLibrary> lib = [_sg.mtl.device\n        newLibraryWithSource:[NSString stringWithUTF8String:src]\n        options:nil\n        error:&err\n    ];\n    if (err) {\n        _SG_ERROR(METAL_SHADER_COMPILATION_FAILED);\n        _SG_LOGMSG(METAL_SHADER_COMPILATION_OUTPUT, [err.localizedDescription UTF8String]);\n    }\n    return lib;\n}\n\n_SOKOL_PRIVATE id<MTLLibrary> _sg_mtl_library_from_bytecode(const void* ptr, size_t num_bytes) {\n    NSError* err = NULL;\n    dispatch_data_t lib_data = dispatch_data_create(ptr, num_bytes, NULL, DISPATCH_DATA_DESTRUCTOR_DEFAULT);\n    id<MTLLibrary> lib = [_sg.mtl.device newLibraryWithData:lib_data error:&err];\n    if (err) {\n        _SG_ERROR(METAL_SHADER_CREATION_FAILED);\n        _SG_LOGMSG(METAL_SHADER_COMPILATION_OUTPUT, [err.localizedDescription UTF8String]);\n    }\n    _SG_OBJC_RELEASE(lib_data);\n    return lib;\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_mtl_create_shader(_sg_shader_t* shd, const sg_shader_desc* desc) {\n    SOKOL_ASSERT(shd && desc);\n\n    // create metal library objects and lookup entry functions\n    id<MTLLibrary> vs_lib = nil;\n    id<MTLLibrary> fs_lib = nil;\n    id<MTLFunction> vs_func = nil;\n    id<MTLFunction> fs_func = nil;\n    const char* vs_entry = desc->vs.entry;\n    const char* fs_entry = desc->fs.entry;\n    if (desc->vs.bytecode.ptr && desc->fs.bytecode.ptr) {\n        // separate byte code provided\n        vs_lib = _sg_mtl_library_from_bytecode(desc->vs.bytecode.ptr, desc->vs.bytecode.size);\n        fs_lib = _sg_mtl_library_from_bytecode(desc->fs.bytecode.ptr, desc->fs.bytecode.size);\n        if ((nil == vs_lib) || (nil == fs_lib)) {\n            goto failed;\n        }\n        vs_func = [vs_lib newFunctionWithName:[NSString stringWithUTF8String:vs_entry]];\n        fs_func = [fs_lib newFunctionWithName:[NSString stringWithUTF8String:fs_entry]];\n    } else if (desc->vs.source && desc->fs.source) {\n        // separate sources provided\n        vs_lib = _sg_mtl_compile_library(desc->vs.source);\n        fs_lib = _sg_mtl_compile_library(desc->fs.source);\n        if ((nil == vs_lib) || (nil == fs_lib)) {\n            goto failed;\n        }\n        vs_func = [vs_lib newFunctionWithName:[NSString stringWithUTF8String:vs_entry]];\n        fs_func = [fs_lib newFunctionWithName:[NSString stringWithUTF8String:fs_entry]];\n    } else {\n        goto failed;\n    }\n    if (nil == vs_func) {\n        _SG_ERROR(METAL_VERTEX_SHADER_ENTRY_NOT_FOUND);\n        goto failed;\n    }\n    if (nil == fs_func) {\n        _SG_ERROR(METAL_FRAGMENT_SHADER_ENTRY_NOT_FOUND);\n        goto failed;\n    }\n    #if defined(SOKOL_DEBUG)\n        if (desc->label) {\n            vs_lib.label = [NSString stringWithFormat:@\"%s.vs\", desc->label];\n            fs_lib.label = [NSString stringWithFormat:@\"%s.fs\", desc->label];\n        }\n    #endif\n    // it is legal to call _sg_mtl_add_resource with a nil value, this will return a special 0xFFFFFFFF index\n    shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_lib  = _sg_mtl_add_resource(vs_lib);\n    _SG_OBJC_RELEASE(vs_lib);\n    shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_lib  = _sg_mtl_add_resource(fs_lib);\n    _SG_OBJC_RELEASE(fs_lib);\n    shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_func = _sg_mtl_add_resource(vs_func);\n    _SG_OBJC_RELEASE(vs_func);\n    shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_func = _sg_mtl_add_resource(fs_func);\n    _SG_OBJC_RELEASE(fs_func);\n    return SG_RESOURCESTATE_VALID;\nfailed:\n    if (vs_lib != nil) {\n        _SG_OBJC_RELEASE(vs_lib);\n    }\n    if (fs_lib != nil) {\n        _SG_OBJC_RELEASE(fs_lib);\n    }\n    if (vs_func != nil) {\n        _SG_OBJC_RELEASE(vs_func);\n    }\n    if (fs_func != nil) {\n        _SG_OBJC_RELEASE(fs_func);\n    }\n    return SG_RESOURCESTATE_FAILED;\n}\n\n_SOKOL_PRIVATE void _sg_mtl_discard_shader(_sg_shader_t* shd) {\n    SOKOL_ASSERT(shd);\n    // it is valid to call _sg_mtl_release_resource with a 'null resource'\n    _sg_mtl_release_resource(_sg.frame_index, shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_func);\n    _sg_mtl_release_resource(_sg.frame_index, shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_lib);\n    _sg_mtl_release_resource(_sg.frame_index, shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_func);\n    _sg_mtl_release_resource(_sg.frame_index, shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_lib);\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_mtl_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) {\n    SOKOL_ASSERT(pip && shd && desc);\n    SOKOL_ASSERT(desc->shader.id == shd->slot.id);\n\n    pip->shader = shd;\n\n    sg_primitive_type prim_type = desc->primitive_type;\n    pip->mtl.prim_type = _sg_mtl_primitive_type(prim_type);\n    pip->mtl.index_size = _sg_mtl_index_size(pip->cmn.index_type);\n    if (SG_INDEXTYPE_NONE != pip->cmn.index_type) {\n        pip->mtl.index_type = _sg_mtl_index_type(pip->cmn.index_type);\n    }\n    pip->mtl.cull_mode = _sg_mtl_cull_mode(desc->cull_mode);\n    pip->mtl.winding = _sg_mtl_winding(desc->face_winding);\n    pip->mtl.stencil_ref = desc->stencil.ref;\n\n    // create vertex-descriptor\n    MTLVertexDescriptor* vtx_desc = [MTLVertexDescriptor vertexDescriptor];\n    for (NSUInteger attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {\n        const sg_vertex_attr_state* a_state = &desc->layout.attrs[attr_index];\n        if (a_state->format == SG_VERTEXFORMAT_INVALID) {\n            break;\n        }\n        SOKOL_ASSERT(a_state->buffer_index < SG_MAX_VERTEX_BUFFERS);\n        vtx_desc.attributes[attr_index].format = _sg_mtl_vertex_format(a_state->format);\n        vtx_desc.attributes[attr_index].offset = (NSUInteger)a_state->offset;\n        vtx_desc.attributes[attr_index].bufferIndex = (NSUInteger)(a_state->buffer_index + SG_MAX_SHADERSTAGE_UBS);\n        pip->cmn.vertex_buffer_layout_active[a_state->buffer_index] = true;\n    }\n    for (NSUInteger layout_index = 0; layout_index < SG_MAX_VERTEX_BUFFERS; layout_index++) {\n        if (pip->cmn.vertex_buffer_layout_active[layout_index]) {\n            const sg_vertex_buffer_layout_state* l_state = &desc->layout.buffers[layout_index];\n            const NSUInteger mtl_vb_slot = layout_index + SG_MAX_SHADERSTAGE_UBS;\n            SOKOL_ASSERT(l_state->stride > 0);\n            vtx_desc.layouts[mtl_vb_slot].stride = (NSUInteger)l_state->stride;\n            vtx_desc.layouts[mtl_vb_slot].stepFunction = _sg_mtl_step_function(l_state->step_func);\n            vtx_desc.layouts[mtl_vb_slot].stepRate = (NSUInteger)l_state->step_rate;\n            if (SG_VERTEXSTEP_PER_INSTANCE == l_state->step_func) {\n                // NOTE: not actually used in _sg_mtl_draw()\n                pip->cmn.use_instanced_draw = true;\n            }\n        }\n    }\n\n    // render-pipeline descriptor\n    MTLRenderPipelineDescriptor* rp_desc = [[MTLRenderPipelineDescriptor alloc] init];\n    rp_desc.vertexDescriptor = vtx_desc;\n    SOKOL_ASSERT(shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_func != _SG_MTL_INVALID_SLOT_INDEX);\n    rp_desc.vertexFunction = _sg_mtl_id(shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_func);\n    SOKOL_ASSERT(shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_func != _SG_MTL_INVALID_SLOT_INDEX);\n    rp_desc.fragmentFunction = _sg_mtl_id(shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_func);\n    rp_desc.rasterSampleCount = (NSUInteger)desc->sample_count;\n    rp_desc.alphaToCoverageEnabled = desc->alpha_to_coverage_enabled;\n    rp_desc.alphaToOneEnabled = NO;\n    rp_desc.rasterizationEnabled = YES;\n    rp_desc.depthAttachmentPixelFormat = _sg_mtl_pixel_format(desc->depth.pixel_format);\n    if (desc->depth.pixel_format == SG_PIXELFORMAT_DEPTH_STENCIL) {\n        rp_desc.stencilAttachmentPixelFormat = _sg_mtl_pixel_format(desc->depth.pixel_format);\n    }\n    if (@available(macOS 10.13, iOS 11.0, *)) {\n        for (NSUInteger i = 0; i < (SG_MAX_SHADERSTAGE_UBS+SG_MAX_VERTEX_BUFFERS); i++) {\n            rp_desc.vertexBuffers[i].mutability = MTLMutabilityImmutable;\n        }\n        for (NSUInteger i = 0; i < SG_MAX_SHADERSTAGE_UBS; i++) {\n            rp_desc.fragmentBuffers[i].mutability = MTLMutabilityImmutable;\n        }\n    }\n    for (NSUInteger i = 0; i < (NSUInteger)desc->color_count; i++) {\n        SOKOL_ASSERT(i < SG_MAX_COLOR_ATTACHMENTS);\n        const sg_color_target_state* cs = &desc->colors[i];\n        rp_desc.colorAttachments[i].pixelFormat = _sg_mtl_pixel_format(cs->pixel_format);\n        rp_desc.colorAttachments[i].writeMask = _sg_mtl_color_write_mask(cs->write_mask);\n        rp_desc.colorAttachments[i].blendingEnabled = cs->blend.enabled;\n        rp_desc.colorAttachments[i].alphaBlendOperation = _sg_mtl_blend_op(cs->blend.op_alpha);\n        rp_desc.colorAttachments[i].rgbBlendOperation = _sg_mtl_blend_op(cs->blend.op_rgb);\n        rp_desc.colorAttachments[i].destinationAlphaBlendFactor = _sg_mtl_blend_factor(cs->blend.dst_factor_alpha);\n        rp_desc.colorAttachments[i].destinationRGBBlendFactor = _sg_mtl_blend_factor(cs->blend.dst_factor_rgb);\n        rp_desc.colorAttachments[i].sourceAlphaBlendFactor = _sg_mtl_blend_factor(cs->blend.src_factor_alpha);\n        rp_desc.colorAttachments[i].sourceRGBBlendFactor = _sg_mtl_blend_factor(cs->blend.src_factor_rgb);\n    }\n    #if defined(SOKOL_DEBUG)\n        if (desc->label) {\n            rp_desc.label = [NSString stringWithFormat:@\"%s\", desc->label];\n        }\n    #endif\n    NSError* err = NULL;\n    id<MTLRenderPipelineState> mtl_rps = [_sg.mtl.device newRenderPipelineStateWithDescriptor:rp_desc error:&err];\n    _SG_OBJC_RELEASE(rp_desc);\n    if (nil == mtl_rps) {\n        SOKOL_ASSERT(err);\n        _SG_ERROR(METAL_CREATE_RPS_FAILED);\n        _SG_LOGMSG(METAL_CREATE_RPS_OUTPUT, [err.localizedDescription UTF8String]);\n        return SG_RESOURCESTATE_FAILED;\n    }\n    pip->mtl.rps = _sg_mtl_add_resource(mtl_rps);\n    _SG_OBJC_RELEASE(mtl_rps);\n\n    // depth-stencil-state\n    MTLDepthStencilDescriptor* ds_desc = [[MTLDepthStencilDescriptor alloc] init];\n    ds_desc.depthCompareFunction = _sg_mtl_compare_func(desc->depth.compare);\n    ds_desc.depthWriteEnabled = desc->depth.write_enabled;\n    if (desc->stencil.enabled) {\n        const sg_stencil_face_state* sb = &desc->stencil.back;\n        ds_desc.backFaceStencil = [[MTLStencilDescriptor alloc] init];\n        ds_desc.backFaceStencil.stencilFailureOperation = _sg_mtl_stencil_op(sb->fail_op);\n        ds_desc.backFaceStencil.depthFailureOperation = _sg_mtl_stencil_op(sb->depth_fail_op);\n        ds_desc.backFaceStencil.depthStencilPassOperation = _sg_mtl_stencil_op(sb->pass_op);\n        ds_desc.backFaceStencil.stencilCompareFunction = _sg_mtl_compare_func(sb->compare);\n        ds_desc.backFaceStencil.readMask = desc->stencil.read_mask;\n        ds_desc.backFaceStencil.writeMask = desc->stencil.write_mask;\n        const sg_stencil_face_state* sf = &desc->stencil.front;\n        ds_desc.frontFaceStencil = [[MTLStencilDescriptor alloc] init];\n        ds_desc.frontFaceStencil.stencilFailureOperation = _sg_mtl_stencil_op(sf->fail_op);\n        ds_desc.frontFaceStencil.depthFailureOperation = _sg_mtl_stencil_op(sf->depth_fail_op);\n        ds_desc.frontFaceStencil.depthStencilPassOperation = _sg_mtl_stencil_op(sf->pass_op);\n        ds_desc.frontFaceStencil.stencilCompareFunction = _sg_mtl_compare_func(sf->compare);\n        ds_desc.frontFaceStencil.readMask = desc->stencil.read_mask;\n        ds_desc.frontFaceStencil.writeMask = desc->stencil.write_mask;\n    }\n    #if defined(SOKOL_DEBUG)\n        if (desc->label) {\n            ds_desc.label = [NSString stringWithFormat:@\"%s.dss\", desc->label];\n        }\n    #endif\n    id<MTLDepthStencilState> mtl_dss = [_sg.mtl.device newDepthStencilStateWithDescriptor:ds_desc];\n    _SG_OBJC_RELEASE(ds_desc);\n    if (nil == mtl_dss) {\n        _SG_ERROR(METAL_CREATE_DSS_FAILED);\n        return SG_RESOURCESTATE_FAILED;\n    }\n    pip->mtl.dss = _sg_mtl_add_resource(mtl_dss);\n    _SG_OBJC_RELEASE(mtl_dss);\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_mtl_discard_pipeline(_sg_pipeline_t* pip) {\n    SOKOL_ASSERT(pip);\n    // it's valid to call release resource with a 'null resource'\n    _sg_mtl_release_resource(_sg.frame_index, pip->mtl.rps);\n    _sg_mtl_release_resource(_sg.frame_index, pip->mtl.dss);\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_mtl_create_attachments(_sg_attachments_t* atts, _sg_image_t** color_images, _sg_image_t** resolve_images, _sg_image_t* ds_img, const sg_attachments_desc* desc) {\n    SOKOL_ASSERT(atts && desc);\n    SOKOL_ASSERT(color_images && resolve_images);\n\n    // copy image pointers\n    for (int i = 0; i < atts->cmn.num_colors; i++) {\n        const sg_attachment_desc* color_desc = &desc->colors[i];\n        _SOKOL_UNUSED(color_desc);\n        SOKOL_ASSERT(color_desc->image.id != SG_INVALID_ID);\n        SOKOL_ASSERT(0 == atts->mtl.colors[i].image);\n        SOKOL_ASSERT(color_images[i] && (color_images[i]->slot.id == color_desc->image.id));\n        SOKOL_ASSERT(_sg_is_valid_rendertarget_color_format(color_images[i]->cmn.pixel_format));\n        atts->mtl.colors[i].image = color_images[i];\n\n        const sg_attachment_desc* resolve_desc = &desc->resolves[i];\n        if (resolve_desc->image.id != SG_INVALID_ID) {\n            SOKOL_ASSERT(0 == atts->mtl.resolves[i].image);\n            SOKOL_ASSERT(resolve_images[i] && (resolve_images[i]->slot.id == resolve_desc->image.id));\n            SOKOL_ASSERT(color_images[i] && (color_images[i]->cmn.pixel_format == resolve_images[i]->cmn.pixel_format));\n            atts->mtl.resolves[i].image = resolve_images[i];\n        }\n    }\n    SOKOL_ASSERT(0 == atts->mtl.depth_stencil.image);\n    const sg_attachment_desc* ds_desc = &desc->depth_stencil;\n    if (ds_desc->image.id != SG_INVALID_ID) {\n        SOKOL_ASSERT(ds_img && (ds_img->slot.id == ds_desc->image.id));\n        SOKOL_ASSERT(_sg_is_valid_rendertarget_depth_format(ds_img->cmn.pixel_format));\n        atts->mtl.depth_stencil.image = ds_img;\n    }\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_mtl_discard_attachments(_sg_attachments_t* atts) {\n    SOKOL_ASSERT(atts);\n    _SOKOL_UNUSED(atts);\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_mtl_attachments_color_image(const _sg_attachments_t* atts, int index) {\n    // NOTE: may return null\n    SOKOL_ASSERT(atts && (index >= 0) && (index < SG_MAX_COLOR_ATTACHMENTS));\n    return atts->mtl.colors[index].image;\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_mtl_attachments_resolve_image(const _sg_attachments_t* atts, int index) {\n    // NOTE: may return null\n    SOKOL_ASSERT(atts && (index >= 0) && (index < SG_MAX_COLOR_ATTACHMENTS));\n    return atts->mtl.resolves[index].image;\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_mtl_attachments_ds_image(const _sg_attachments_t* atts) {\n    // NOTE: may return null\n    SOKOL_ASSERT(atts);\n    return atts->mtl.depth_stencil.image;\n}\n\n_SOKOL_PRIVATE void _sg_mtl_begin_pass(const sg_pass* pass) {\n    SOKOL_ASSERT(pass);\n    SOKOL_ASSERT(_sg.mtl.cmd_queue);\n    SOKOL_ASSERT(nil == _sg.mtl.cmd_encoder);\n    SOKOL_ASSERT(nil == _sg.mtl.cur_drawable);\n    _sg_mtl_clear_state_cache();\n\n    const _sg_attachments_t* atts = _sg.cur_pass.atts;\n    const sg_swapchain* swapchain = &pass->swapchain;\n    const sg_pass_action* action = &pass->action;\n\n    /*\n        if this is the first pass in the frame, create command buffers\n\n        NOTE: we're creating two command buffers here, one with unretained references\n        for storing the regular commands, and one with retained references for\n        storing the presentDrawable call (this needs to hold on the drawable until\n        presentation has happened - and the easiest way to do this is to let the\n        command buffer manage the lifetime of the drawable).\n\n        Also see: https://github.com/floooh/sokol/issues/762\n    */\n    if (nil == _sg.mtl.cmd_buffer) {\n        // block until the oldest frame in flight has finished\n        dispatch_semaphore_wait(_sg.mtl.sem, DISPATCH_TIME_FOREVER);\n        if (_sg.desc.mtl_use_command_buffer_with_retained_references) {\n            _sg.mtl.cmd_buffer = [_sg.mtl.cmd_queue commandBuffer];\n        } else {\n            _sg.mtl.cmd_buffer = [_sg.mtl.cmd_queue commandBufferWithUnretainedReferences];\n        }\n        [_sg.mtl.cmd_buffer enqueue];\n        [_sg.mtl.cmd_buffer addCompletedHandler:^(id<MTLCommandBuffer> cmd_buf) {\n            // NOTE: this code is called on a different thread!\n            _SOKOL_UNUSED(cmd_buf);\n            dispatch_semaphore_signal(_sg.mtl.sem);\n        }];\n    }\n\n    // if this is first pass in frame, get uniform buffer base pointer\n    if (0 == _sg.mtl.cur_ub_base_ptr) {\n        _sg.mtl.cur_ub_base_ptr = (uint8_t*)[_sg.mtl.uniform_buffers[_sg.mtl.cur_frame_rotate_index] contents];\n    }\n\n    MTLRenderPassDescriptor* pass_desc = [MTLRenderPassDescriptor renderPassDescriptor];\n    SOKOL_ASSERT(pass_desc);\n    if (atts) {\n        // setup pass descriptor for offscreen rendering\n        SOKOL_ASSERT(atts->slot.state == SG_RESOURCESTATE_VALID);\n        for (NSUInteger i = 0; i < (NSUInteger)atts->cmn.num_colors; i++) {\n            const _sg_attachment_common_t* cmn_color_att = &atts->cmn.colors[i];\n            const _sg_mtl_attachment_t* mtl_color_att = &atts->mtl.colors[i];\n            const _sg_image_t* color_att_img = mtl_color_att->image;\n            const _sg_attachment_common_t* cmn_resolve_att = &atts->cmn.resolves[i];\n            const _sg_mtl_attachment_t* mtl_resolve_att = &atts->mtl.resolves[i];\n            const _sg_image_t* resolve_att_img = mtl_resolve_att->image;\n            SOKOL_ASSERT(color_att_img->slot.state == SG_RESOURCESTATE_VALID);\n            SOKOL_ASSERT(color_att_img->slot.id == cmn_color_att->image_id.id);\n            SOKOL_ASSERT(color_att_img->mtl.tex[color_att_img->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX);\n            pass_desc.colorAttachments[i].loadAction = _sg_mtl_load_action(action->colors[i].load_action);\n            pass_desc.colorAttachments[i].storeAction = _sg_mtl_store_action(action->colors[i].store_action, resolve_att_img != 0);\n            sg_color c = action->colors[i].clear_value;\n            pass_desc.colorAttachments[i].clearColor = MTLClearColorMake(c.r, c.g, c.b, c.a);\n            pass_desc.colorAttachments[i].texture = _sg_mtl_id(color_att_img->mtl.tex[color_att_img->cmn.active_slot]);\n            pass_desc.colorAttachments[i].level = (NSUInteger)cmn_color_att->mip_level;\n            switch (color_att_img->cmn.type) {\n                case SG_IMAGETYPE_CUBE:\n                case SG_IMAGETYPE_ARRAY:\n                    pass_desc.colorAttachments[i].slice = (NSUInteger)cmn_color_att->slice;\n                    break;\n                case SG_IMAGETYPE_3D:\n                    pass_desc.colorAttachments[i].depthPlane = (NSUInteger)cmn_color_att->slice;\n                    break;\n                default: break;\n            }\n            if (resolve_att_img) {\n                SOKOL_ASSERT(resolve_att_img->slot.state == SG_RESOURCESTATE_VALID);\n                SOKOL_ASSERT(resolve_att_img->slot.id == cmn_resolve_att->image_id.id);\n                SOKOL_ASSERT(resolve_att_img->mtl.tex[resolve_att_img->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX);\n                pass_desc.colorAttachments[i].resolveTexture = _sg_mtl_id(resolve_att_img->mtl.tex[resolve_att_img->cmn.active_slot]);\n                pass_desc.colorAttachments[i].resolveLevel = (NSUInteger)cmn_resolve_att->mip_level;\n                switch (resolve_att_img->cmn.type) {\n                    case SG_IMAGETYPE_CUBE:\n                    case SG_IMAGETYPE_ARRAY:\n                        pass_desc.colorAttachments[i].resolveSlice = (NSUInteger)cmn_resolve_att->slice;\n                        break;\n                    case SG_IMAGETYPE_3D:\n                        pass_desc.colorAttachments[i].resolveDepthPlane = (NSUInteger)cmn_resolve_att->slice;\n                        break;\n                    default: break;\n                }\n            }\n        }\n        const _sg_image_t* ds_att_img = atts->mtl.depth_stencil.image;\n        if (0 != ds_att_img) {\n            SOKOL_ASSERT(ds_att_img->slot.state == SG_RESOURCESTATE_VALID);\n            SOKOL_ASSERT(ds_att_img->slot.id == atts->cmn.depth_stencil.image_id.id);\n            SOKOL_ASSERT(ds_att_img->mtl.tex[ds_att_img->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX);\n            pass_desc.depthAttachment.texture = _sg_mtl_id(ds_att_img->mtl.tex[ds_att_img->cmn.active_slot]);\n            pass_desc.depthAttachment.loadAction = _sg_mtl_load_action(action->depth.load_action);\n            pass_desc.depthAttachment.storeAction = _sg_mtl_store_action(action->depth.store_action, false);\n            pass_desc.depthAttachment.clearDepth = action->depth.clear_value;\n            const _sg_attachment_common_t* cmn_ds_att = &atts->cmn.depth_stencil;\n            switch (ds_att_img->cmn.type) {\n                case SG_IMAGETYPE_CUBE:\n                case SG_IMAGETYPE_ARRAY:\n                    pass_desc.depthAttachment.slice = (NSUInteger)cmn_ds_att->slice;\n                    break;\n                case SG_IMAGETYPE_3D:\n                    pass_desc.depthAttachment.resolveDepthPlane = (NSUInteger)cmn_ds_att->slice;\n                    break;\n                default: break;\n            }\n            if (_sg_is_depth_stencil_format(ds_att_img->cmn.pixel_format)) {\n                pass_desc.stencilAttachment.texture = _sg_mtl_id(ds_att_img->mtl.tex[ds_att_img->cmn.active_slot]);\n                pass_desc.stencilAttachment.loadAction = _sg_mtl_load_action(action->stencil.load_action);\n                pass_desc.stencilAttachment.storeAction = _sg_mtl_store_action(action->depth.store_action, false);\n                pass_desc.stencilAttachment.clearStencil = action->stencil.clear_value;\n                switch (ds_att_img->cmn.type) {\n                    case SG_IMAGETYPE_CUBE:\n                    case SG_IMAGETYPE_ARRAY:\n                        pass_desc.stencilAttachment.slice = (NSUInteger)cmn_ds_att->slice;\n                        break;\n                    case SG_IMAGETYPE_3D:\n                        pass_desc.stencilAttachment.resolveDepthPlane = (NSUInteger)cmn_ds_att->slice;\n                        break;\n                    default: break;\n                }\n            }\n        }\n    } else {\n        // setup pass descriptor for swapchain rendering\n        //\n        // NOTE: at least in macOS Sonoma this no longer seems to be the case, the\n        // current drawable is also valid in a minimized window\n        // ===\n        // an MTKView current_drawable will not be valid if window is minimized, don't do any rendering in this case\n        if (0 == swapchain->metal.current_drawable) {\n            _sg.cur_pass.valid = false;\n            return;\n        }\n        // pin the swapchain resources into memory so that they outlive their command buffer\n        // (this is necessary because the command buffer doesn't retain references)\n        int pass_desc_ref = _sg_mtl_add_resource(pass_desc);\n        _sg_mtl_release_resource(_sg.frame_index, pass_desc_ref);\n\n        _sg.mtl.cur_drawable = (__bridge id<CAMetalDrawable>) swapchain->metal.current_drawable;\n        if (swapchain->sample_count > 1) {\n            // multi-sampling: render into msaa texture, resolve into drawable texture\n            id<MTLTexture> msaa_tex = (__bridge id<MTLTexture>) swapchain->metal.msaa_color_texture;\n            SOKOL_ASSERT(msaa_tex != nil);\n            pass_desc.colorAttachments[0].texture = msaa_tex;\n            pass_desc.colorAttachments[0].resolveTexture = _sg.mtl.cur_drawable.texture;\n            pass_desc.colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve;\n        } else {\n            // non-msaa: render into current_drawable\n            pass_desc.colorAttachments[0].texture = _sg.mtl.cur_drawable.texture;\n            pass_desc.colorAttachments[0].storeAction = MTLStoreActionStore;\n        }\n        pass_desc.colorAttachments[0].loadAction = _sg_mtl_load_action(action->colors[0].load_action);\n        const sg_color c = action->colors[0].clear_value;\n        pass_desc.colorAttachments[0].clearColor = MTLClearColorMake(c.r, c.g, c.b, c.a);\n\n        // optional depth-stencil texture\n        if (swapchain->metal.depth_stencil_texture) {\n            id<MTLTexture> ds_tex = (__bridge id<MTLTexture>) swapchain->metal.depth_stencil_texture;\n            SOKOL_ASSERT(ds_tex != nil);\n            pass_desc.depthAttachment.texture = ds_tex;\n            pass_desc.depthAttachment.storeAction = MTLStoreActionDontCare;\n            pass_desc.depthAttachment.loadAction = _sg_mtl_load_action(action->depth.load_action);\n            pass_desc.depthAttachment.clearDepth = action->depth.clear_value;\n            if (_sg_is_depth_stencil_format(swapchain->depth_format)) {\n                pass_desc.stencilAttachment.texture = ds_tex;\n                pass_desc.stencilAttachment.storeAction = MTLStoreActionDontCare;\n                pass_desc.stencilAttachment.loadAction = _sg_mtl_load_action(action->stencil.load_action);\n                pass_desc.stencilAttachment.clearStencil = action->stencil.clear_value;\n            }\n        }\n    }\n\n    // NOTE: at least in macOS Sonoma, the following is no longer the case, a valid\n    // render command encoder is also returned in a minimized window\n    // ===\n    // create a render command encoder, this might return nil if window is minimized\n    _sg.mtl.cmd_encoder = [_sg.mtl.cmd_buffer renderCommandEncoderWithDescriptor:pass_desc];\n    if (nil == _sg.mtl.cmd_encoder) {\n        _sg.cur_pass.valid = false;\n        return;\n    }\n\n    #if defined(SOKOL_DEBUG)\n        if (pass->label) {\n            _sg.mtl.cmd_encoder.label = [NSString stringWithUTF8String:pass->label];\n        }\n    #endif\n\n    // bind the global uniform buffer, this only happens once per pass\n    _sg_mtl_bind_uniform_buffers();\n}\n\n_SOKOL_PRIVATE void _sg_mtl_end_pass(void) {\n    if (nil != _sg.mtl.cmd_encoder) {\n        [_sg.mtl.cmd_encoder endEncoding];\n        // NOTE: MTLRenderCommandEncoder is autoreleased\n        _sg.mtl.cmd_encoder = nil;\n    }\n    // if this is a swapchain pass, present the drawable\n    if (nil != _sg.mtl.cur_drawable) {\n        [_sg.mtl.cmd_buffer presentDrawable:_sg.mtl.cur_drawable];\n        _sg.mtl.cur_drawable = nil;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_mtl_commit(void) {\n    SOKOL_ASSERT(nil == _sg.mtl.cmd_encoder);\n    SOKOL_ASSERT(nil != _sg.mtl.cmd_buffer);\n\n    // commit the frame's command buffer\n    [_sg.mtl.cmd_buffer commit];\n\n    // garbage-collect resources pending for release\n    _sg_mtl_garbage_collect(_sg.frame_index);\n\n    // rotate uniform buffer slot\n    if (++_sg.mtl.cur_frame_rotate_index >= SG_NUM_INFLIGHT_FRAMES) {\n        _sg.mtl.cur_frame_rotate_index = 0;\n    }\n    _sg.mtl.cur_ub_offset = 0;\n    _sg.mtl.cur_ub_base_ptr = 0;\n    // NOTE: MTLCommandBuffer is autoreleased\n    _sg.mtl.cmd_buffer = nil;\n}\n\n_SOKOL_PRIVATE void _sg_mtl_apply_viewport(int x, int y, int w, int h, bool origin_top_left) {\n    SOKOL_ASSERT(nil != _sg.mtl.cmd_encoder);\n    SOKOL_ASSERT(_sg.cur_pass.height > 0);\n    MTLViewport vp;\n    vp.originX = (double) x;\n    vp.originY = (double) (origin_top_left ? y : (_sg.cur_pass.height - (y + h)));\n    vp.width   = (double) w;\n    vp.height  = (double) h;\n    vp.znear   = 0.0;\n    vp.zfar    = 1.0;\n    [_sg.mtl.cmd_encoder setViewport:vp];\n}\n\n_SOKOL_PRIVATE void _sg_mtl_apply_scissor_rect(int x, int y, int w, int h, bool origin_top_left) {\n    SOKOL_ASSERT(nil != _sg.mtl.cmd_encoder);\n    SOKOL_ASSERT(_sg.cur_pass.width > 0);\n    SOKOL_ASSERT(_sg.cur_pass.height > 0);\n    // clip against framebuffer rect\n    const _sg_recti_t clip = _sg_clipi(x, y, w, h, _sg.cur_pass.width, _sg.cur_pass.height);\n    MTLScissorRect r;\n    r.x = (NSUInteger)clip.x;\n    r.y = (NSUInteger) (origin_top_left ? clip.y : (_sg.cur_pass.height - (clip.y + clip.h)));\n    r.width = (NSUInteger)clip.w;\n    r.height = (NSUInteger)clip.h;\n    [_sg.mtl.cmd_encoder setScissorRect:r];\n}\n\n_SOKOL_PRIVATE void _sg_mtl_apply_pipeline(_sg_pipeline_t* pip) {\n    SOKOL_ASSERT(pip);\n    SOKOL_ASSERT(pip->shader && (pip->cmn.shader_id.id == pip->shader->slot.id));\n    SOKOL_ASSERT(nil != _sg.mtl.cmd_encoder);\n\n    if (_sg.mtl.state_cache.cur_pipeline_id.id != pip->slot.id) {\n        _sg.mtl.state_cache.cur_pipeline = pip;\n        _sg.mtl.state_cache.cur_pipeline_id.id = pip->slot.id;\n        sg_color c = pip->cmn.blend_color;\n        [_sg.mtl.cmd_encoder setBlendColorRed:c.r green:c.g blue:c.b alpha:c.a];\n        _sg_stats_add(metal.pipeline.num_set_blend_color, 1);\n        [_sg.mtl.cmd_encoder setCullMode:pip->mtl.cull_mode];\n        _sg_stats_add(metal.pipeline.num_set_cull_mode, 1);\n        [_sg.mtl.cmd_encoder setFrontFacingWinding:pip->mtl.winding];\n        _sg_stats_add(metal.pipeline.num_set_front_facing_winding, 1);\n        [_sg.mtl.cmd_encoder setStencilReferenceValue:pip->mtl.stencil_ref];\n        _sg_stats_add(metal.pipeline.num_set_stencil_reference_value, 1);\n        [_sg.mtl.cmd_encoder setDepthBias:pip->cmn.depth.bias slopeScale:pip->cmn.depth.bias_slope_scale clamp:pip->cmn.depth.bias_clamp];\n        _sg_stats_add(metal.pipeline.num_set_depth_bias, 1);\n        SOKOL_ASSERT(pip->mtl.rps != _SG_MTL_INVALID_SLOT_INDEX);\n        [_sg.mtl.cmd_encoder setRenderPipelineState:_sg_mtl_id(pip->mtl.rps)];\n        _sg_stats_add(metal.pipeline.num_set_render_pipeline_state, 1);\n        SOKOL_ASSERT(pip->mtl.dss != _SG_MTL_INVALID_SLOT_INDEX);\n        [_sg.mtl.cmd_encoder setDepthStencilState:_sg_mtl_id(pip->mtl.dss)];\n        _sg_stats_add(metal.pipeline.num_set_depth_stencil_state, 1);\n    }\n}\n\n_SOKOL_PRIVATE bool _sg_mtl_apply_bindings(_sg_bindings_t* bnd) {\n    SOKOL_ASSERT(bnd);\n    SOKOL_ASSERT(bnd->pip);\n    SOKOL_ASSERT(nil != _sg.mtl.cmd_encoder);\n\n    // store index buffer binding, this will be needed later in sg_draw()\n    _sg.mtl.state_cache.cur_indexbuffer = bnd->ib;\n    _sg.mtl.state_cache.cur_indexbuffer_offset = bnd->ib_offset;\n    if (bnd->ib) {\n        SOKOL_ASSERT(bnd->pip->cmn.index_type != SG_INDEXTYPE_NONE);\n        _sg.mtl.state_cache.cur_indexbuffer_id.id = bnd->ib->slot.id;\n    } else {\n        SOKOL_ASSERT(bnd->pip->cmn.index_type == SG_INDEXTYPE_NONE);\n        _sg.mtl.state_cache.cur_indexbuffer_id.id = SG_INVALID_ID;\n    }\n\n    // apply vertex buffers\n    for (NSUInteger slot = 0; slot < (NSUInteger)bnd->num_vbs; slot++) {\n        const _sg_buffer_t* vb = bnd->vbs[slot];\n        const int vb_offset = bnd->vb_offsets[slot];\n        if ((_sg.mtl.state_cache.cur_vertexbuffer_ids[slot].id != vb->slot.id) ||\n            (_sg.mtl.state_cache.cur_vertexbuffer_offsets[slot] != vb_offset))\n        {\n            _sg.mtl.state_cache.cur_vertexbuffer_offsets[slot] = vb_offset;\n            const NSUInteger mtl_slot = SG_MAX_SHADERSTAGE_UBS + slot;\n            if (_sg.mtl.state_cache.cur_vertexbuffer_ids[slot].id != vb->slot.id) {\n                _sg.mtl.state_cache.cur_vertexbuffer_ids[slot].id = vb->slot.id;\n                SOKOL_ASSERT(vb->mtl.buf[vb->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX);\n                [_sg.mtl.cmd_encoder setVertexBuffer:_sg_mtl_id(vb->mtl.buf[vb->cmn.active_slot])\n                    offset:(NSUInteger)vb_offset\n                    atIndex:mtl_slot];\n            } else {\n                [_sg.mtl.cmd_encoder setVertexBufferOffset:(NSUInteger)vb_offset atIndex:mtl_slot];\n            }\n            _sg_stats_add(metal.bindings.num_set_vertex_buffer, 1);\n        }\n    }\n\n    // apply vertex stage images\n    for (NSUInteger slot = 0; slot < (NSUInteger)bnd->num_vs_imgs; slot++) {\n        const _sg_image_t* img = bnd->vs_imgs[slot];\n        if (_sg.mtl.state_cache.cur_vs_image_ids[slot].id != img->slot.id) {\n            _sg.mtl.state_cache.cur_vs_image_ids[slot].id = img->slot.id;\n            SOKOL_ASSERT(img->mtl.tex[img->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX);\n            [_sg.mtl.cmd_encoder setVertexTexture:_sg_mtl_id(img->mtl.tex[img->cmn.active_slot]) atIndex:slot];\n            _sg_stats_add(metal.bindings.num_set_vertex_texture, 1);\n        }\n    }\n\n    // apply vertex stage samplers\n    for (NSUInteger slot = 0; slot < (NSUInteger)bnd->num_vs_smps; slot++) {\n        const _sg_sampler_t* smp = bnd->vs_smps[slot];\n        if (_sg.mtl.state_cache.cur_vs_sampler_ids[slot].id != smp->slot.id) {\n            _sg.mtl.state_cache.cur_vs_sampler_ids[slot].id = smp->slot.id;\n            SOKOL_ASSERT(smp->mtl.sampler_state != _SG_MTL_INVALID_SLOT_INDEX);\n            [_sg.mtl.cmd_encoder setVertexSamplerState:_sg_mtl_id(smp->mtl.sampler_state) atIndex:slot];\n            _sg_stats_add(metal.bindings.num_set_vertex_sampler_state, 1);\n        }\n    }\n\n    // apply vertex stage storage buffers\n    for (NSUInteger slot = 0; slot < (NSUInteger)bnd->num_vs_sbufs; slot++) {\n        const _sg_buffer_t* sbuf = bnd->vs_sbufs[slot];\n        if (_sg.mtl.state_cache.cur_vs_storagebuffer_ids[slot].id != sbuf->slot.id) {\n            _sg.mtl.state_cache.cur_vs_storagebuffer_ids[slot].id = sbuf->slot.id;\n            SOKOL_ASSERT(sbuf->mtl.buf[sbuf->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX);\n            const NSUInteger mtl_slot = SG_MAX_SHADERSTAGE_UBS + SG_MAX_VERTEX_BUFFERS + slot;\n            [_sg.mtl.cmd_encoder setVertexBuffer:_sg_mtl_id(sbuf->mtl.buf[sbuf->cmn.active_slot]) offset:0 atIndex:mtl_slot];\n            _sg_stats_add(metal.bindings.num_set_vertex_buffer, 1);\n        }\n    }\n\n    // apply fragment stage images\n    for (NSUInteger slot = 0; slot < (NSUInteger)bnd->num_fs_imgs; slot++) {\n        const _sg_image_t* img = bnd->fs_imgs[slot];\n        if (_sg.mtl.state_cache.cur_fs_image_ids[slot].id != img->slot.id) {\n            _sg.mtl.state_cache.cur_fs_image_ids[slot].id = img->slot.id;\n            SOKOL_ASSERT(img->mtl.tex[img->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX);\n            [_sg.mtl.cmd_encoder setFragmentTexture:_sg_mtl_id(img->mtl.tex[img->cmn.active_slot]) atIndex:slot];\n            _sg_stats_add(metal.bindings.num_set_fragment_texture, 1);\n        }\n    }\n\n    // apply fragment stage samplers\n    for (NSUInteger slot = 0; slot < (NSUInteger)bnd->num_fs_smps; slot++) {\n        const _sg_sampler_t* smp = bnd->fs_smps[slot];\n        if (_sg.mtl.state_cache.cur_fs_sampler_ids[slot].id != smp->slot.id) {\n            _sg.mtl.state_cache.cur_fs_sampler_ids[slot].id = smp->slot.id;\n            SOKOL_ASSERT(smp->mtl.sampler_state != _SG_MTL_INVALID_SLOT_INDEX);\n            [_sg.mtl.cmd_encoder setFragmentSamplerState:_sg_mtl_id(smp->mtl.sampler_state) atIndex:slot];\n            _sg_stats_add(metal.bindings.num_set_fragment_sampler_state, 1);\n        }\n    }\n\n    // apply fragment stage storage buffers\n    for (NSUInteger slot = 0; slot < (NSUInteger)bnd->num_fs_sbufs; slot++) {\n        const _sg_buffer_t* sbuf = bnd->fs_sbufs[slot];\n        if (_sg.mtl.state_cache.cur_fs_storagebuffer_ids[slot].id != sbuf->slot.id) {\n            _sg.mtl.state_cache.cur_fs_storagebuffer_ids[slot].id = sbuf->slot.id;\n            SOKOL_ASSERT(sbuf->mtl.buf[sbuf->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX);\n            const NSUInteger mtl_slot = SG_MAX_SHADERSTAGE_UBS + slot;\n            [_sg.mtl.cmd_encoder setFragmentBuffer:_sg_mtl_id(sbuf->mtl.buf[sbuf->cmn.active_slot]) offset:0 atIndex:mtl_slot];\n            _sg_stats_add(metal.bindings.num_set_fragment_buffer, 1);\n        }\n    }\n\n    return true;\n}\n\n_SOKOL_PRIVATE void _sg_mtl_apply_uniforms(sg_shader_stage stage_index, int ub_index, const sg_range* data) {\n    SOKOL_ASSERT(nil != _sg.mtl.cmd_encoder);\n    SOKOL_ASSERT(((size_t)_sg.mtl.cur_ub_offset + data->size) <= (size_t)_sg.mtl.ub_size);\n    SOKOL_ASSERT((_sg.mtl.cur_ub_offset & (_SG_MTL_UB_ALIGN-1)) == 0);\n    SOKOL_ASSERT(_sg.mtl.state_cache.cur_pipeline && _sg.mtl.state_cache.cur_pipeline->shader);\n    SOKOL_ASSERT(_sg.mtl.state_cache.cur_pipeline->slot.id == _sg.mtl.state_cache.cur_pipeline_id.id);\n    SOKOL_ASSERT(_sg.mtl.state_cache.cur_pipeline->shader->slot.id == _sg.mtl.state_cache.cur_pipeline->cmn.shader_id.id);\n    SOKOL_ASSERT(ub_index < _sg.mtl.state_cache.cur_pipeline->shader->cmn.stage[stage_index].num_uniform_blocks);\n    SOKOL_ASSERT(data->size == _sg.mtl.state_cache.cur_pipeline->shader->cmn.stage[stage_index].uniform_blocks[ub_index].size);\n\n    // copy to global uniform buffer, record offset into cmd encoder, and advance offset\n    uint8_t* dst = &_sg.mtl.cur_ub_base_ptr[_sg.mtl.cur_ub_offset];\n    memcpy(dst, data->ptr, data->size);\n    if (stage_index == SG_SHADERSTAGE_VS) {\n        [_sg.mtl.cmd_encoder setVertexBufferOffset:(NSUInteger)_sg.mtl.cur_ub_offset atIndex:(NSUInteger)ub_index];\n        _sg_stats_add(metal.uniforms.num_set_vertex_buffer_offset, 1);\n    } else {\n        [_sg.mtl.cmd_encoder setFragmentBufferOffset:(NSUInteger)_sg.mtl.cur_ub_offset atIndex:(NSUInteger)ub_index];\n        _sg_stats_add(metal.uniforms.num_set_fragment_buffer_offset, 1);\n    }\n    _sg.mtl.cur_ub_offset = _sg_roundup(_sg.mtl.cur_ub_offset + (int)data->size, _SG_MTL_UB_ALIGN);\n}\n\n_SOKOL_PRIVATE void _sg_mtl_draw(int base_element, int num_elements, int num_instances) {\n    SOKOL_ASSERT(nil != _sg.mtl.cmd_encoder);\n    SOKOL_ASSERT(_sg.mtl.state_cache.cur_pipeline && (_sg.mtl.state_cache.cur_pipeline->slot.id == _sg.mtl.state_cache.cur_pipeline_id.id));\n    if (SG_INDEXTYPE_NONE != _sg.mtl.state_cache.cur_pipeline->cmn.index_type) {\n        // indexed rendering\n        SOKOL_ASSERT(_sg.mtl.state_cache.cur_indexbuffer && (_sg.mtl.state_cache.cur_indexbuffer->slot.id == _sg.mtl.state_cache.cur_indexbuffer_id.id));\n        const _sg_buffer_t* ib = _sg.mtl.state_cache.cur_indexbuffer;\n        SOKOL_ASSERT(ib->mtl.buf[ib->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX);\n        const NSUInteger index_buffer_offset = (NSUInteger) (_sg.mtl.state_cache.cur_indexbuffer_offset + base_element * _sg.mtl.state_cache.cur_pipeline->mtl.index_size);\n        [_sg.mtl.cmd_encoder drawIndexedPrimitives:_sg.mtl.state_cache.cur_pipeline->mtl.prim_type\n            indexCount:(NSUInteger)num_elements\n            indexType:_sg.mtl.state_cache.cur_pipeline->mtl.index_type\n            indexBuffer:_sg_mtl_id(ib->mtl.buf[ib->cmn.active_slot])\n            indexBufferOffset:index_buffer_offset\n            instanceCount:(NSUInteger)num_instances];\n    } else {\n        // non-indexed rendering\n        [_sg.mtl.cmd_encoder drawPrimitives:_sg.mtl.state_cache.cur_pipeline->mtl.prim_type\n            vertexStart:(NSUInteger)base_element\n            vertexCount:(NSUInteger)num_elements\n            instanceCount:(NSUInteger)num_instances];\n    }\n}\n\n_SOKOL_PRIVATE void _sg_mtl_update_buffer(_sg_buffer_t* buf, const sg_range* data) {\n    SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0));\n    if (++buf->cmn.active_slot >= buf->cmn.num_slots) {\n        buf->cmn.active_slot = 0;\n    }\n    __unsafe_unretained id<MTLBuffer> mtl_buf = _sg_mtl_id(buf->mtl.buf[buf->cmn.active_slot]);\n    void* dst_ptr = [mtl_buf contents];\n    memcpy(dst_ptr, data->ptr, data->size);\n    #if defined(_SG_TARGET_MACOS)\n    if (_sg_mtl_resource_options_storage_mode_managed_or_shared() == MTLResourceStorageModeManaged) {\n        [mtl_buf didModifyRange:NSMakeRange(0, data->size)];\n    }\n    #endif\n}\n\n_SOKOL_PRIVATE void _sg_mtl_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) {\n    SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0));\n    if (new_frame) {\n        if (++buf->cmn.active_slot >= buf->cmn.num_slots) {\n            buf->cmn.active_slot = 0;\n        }\n    }\n    __unsafe_unretained id<MTLBuffer> mtl_buf = _sg_mtl_id(buf->mtl.buf[buf->cmn.active_slot]);\n    uint8_t* dst_ptr = (uint8_t*) [mtl_buf contents];\n    dst_ptr += buf->cmn.append_pos;\n    memcpy(dst_ptr, data->ptr, data->size);\n    #if defined(_SG_TARGET_MACOS)\n    if (_sg_mtl_resource_options_storage_mode_managed_or_shared() == MTLResourceStorageModeManaged) {\n        [mtl_buf didModifyRange:NSMakeRange((NSUInteger)buf->cmn.append_pos, (NSUInteger)data->size)];\n    }\n    #endif\n}\n\n_SOKOL_PRIVATE void _sg_mtl_update_image(_sg_image_t* img, const sg_image_data* data) {\n    SOKOL_ASSERT(img && data);\n    if (++img->cmn.active_slot >= img->cmn.num_slots) {\n        img->cmn.active_slot = 0;\n    }\n    __unsafe_unretained id<MTLTexture> mtl_tex = _sg_mtl_id(img->mtl.tex[img->cmn.active_slot]);\n    _sg_mtl_copy_image_data(img, mtl_tex, data);\n}\n\n_SOKOL_PRIVATE void _sg_mtl_push_debug_group(const char* name) {\n    SOKOL_ASSERT(name);\n    if (_sg.mtl.cmd_encoder) {\n        [_sg.mtl.cmd_encoder pushDebugGroup:[NSString stringWithUTF8String:name]];\n    }\n}\n\n_SOKOL_PRIVATE void _sg_mtl_pop_debug_group(void) {\n    if (_sg.mtl.cmd_encoder) {\n        [_sg.mtl.cmd_encoder popDebugGroup];\n    }\n}\n\n// ██     ██ ███████ ██████   ██████  ██████  ██    ██     ██████   █████   ██████ ██   ██ ███████ ███    ██ ██████\n// ██     ██ ██      ██   ██ ██       ██   ██ ██    ██     ██   ██ ██   ██ ██      ██  ██  ██      ████   ██ ██   ██\n// ██  █  ██ █████   ██████  ██   ███ ██████  ██    ██     ██████  ███████ ██      █████   █████   ██ ██  ██ ██   ██\n// ██ ███ ██ ██      ██   ██ ██    ██ ██      ██    ██     ██   ██ ██   ██ ██      ██  ██  ██      ██  ██ ██ ██   ██\n//  ███ ███  ███████ ██████   ██████  ██       ██████      ██████  ██   ██  ██████ ██   ██ ███████ ██   ████ ██████\n//\n// >>webgpu\n// >>wgpu\n#elif defined(SOKOL_WGPU)\n\n_SOKOL_PRIVATE WGPUBufferUsageFlags _sg_wgpu_buffer_usage(sg_buffer_type t, sg_usage u) {\n    WGPUBufferUsageFlags res = 0;\n    if (SG_BUFFERTYPE_VERTEXBUFFER == t) {\n        res = WGPUBufferUsage_Vertex;\n    } else if (SG_BUFFERTYPE_STORAGEBUFFER == t) {\n        res = WGPUBufferUsage_Storage;\n    } else {\n        res = WGPUBufferUsage_Index;\n    }\n    if (SG_USAGE_IMMUTABLE != u) {\n        res |= WGPUBufferUsage_CopyDst;\n    }\n    return res;\n}\n\n_SOKOL_PRIVATE WGPULoadOp _sg_wgpu_load_op(WGPUTextureView view, sg_load_action a) {\n    if (0 == view) {\n        return WGPULoadOp_Undefined;\n    } else switch (a) {\n        case SG_LOADACTION_CLEAR:\n        case SG_LOADACTION_DONTCARE:\n            return WGPULoadOp_Clear;\n        case SG_LOADACTION_LOAD:\n            return WGPULoadOp_Load;\n        default:\n            SOKOL_UNREACHABLE;\n            return WGPULoadOp_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUStoreOp _sg_wgpu_store_op(WGPUTextureView view, sg_store_action a) {\n    if (0 == view) {\n        return WGPUStoreOp_Undefined;\n    } else switch (a) {\n        case SG_STOREACTION_STORE:\n            return WGPUStoreOp_Store;\n        case SG_STOREACTION_DONTCARE:\n            return WGPUStoreOp_Discard;\n        default:\n            SOKOL_UNREACHABLE;\n            return WGPUStoreOp_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUTextureViewDimension _sg_wgpu_texture_view_dimension(sg_image_type t) {\n    switch (t) {\n        case SG_IMAGETYPE_2D:       return WGPUTextureViewDimension_2D;\n        case SG_IMAGETYPE_CUBE:     return WGPUTextureViewDimension_Cube;\n        case SG_IMAGETYPE_3D:       return WGPUTextureViewDimension_3D;\n        case SG_IMAGETYPE_ARRAY:    return WGPUTextureViewDimension_2DArray;\n        default: SOKOL_UNREACHABLE; return WGPUTextureViewDimension_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUTextureDimension _sg_wgpu_texture_dimension(sg_image_type t) {\n    if (SG_IMAGETYPE_3D == t) {\n        return WGPUTextureDimension_3D;\n    } else {\n        return WGPUTextureDimension_2D;\n    }\n}\n\n_SOKOL_PRIVATE WGPUTextureSampleType _sg_wgpu_texture_sample_type(sg_image_sample_type t) {\n    switch (t) {\n        case SG_IMAGESAMPLETYPE_FLOAT:  return WGPUTextureSampleType_Float;\n        case SG_IMAGESAMPLETYPE_DEPTH:  return WGPUTextureSampleType_Depth;\n        case SG_IMAGESAMPLETYPE_SINT:   return WGPUTextureSampleType_Sint;\n        case SG_IMAGESAMPLETYPE_UINT:   return WGPUTextureSampleType_Uint;\n        case SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT: return WGPUTextureSampleType_UnfilterableFloat;\n        default: SOKOL_UNREACHABLE;     return WGPUTextureSampleType_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUSamplerBindingType _sg_wgpu_sampler_binding_type(sg_sampler_type t) {\n    switch (t) {\n        case SG_SAMPLERTYPE_FILTERING: return WGPUSamplerBindingType_Filtering;\n        case SG_SAMPLERTYPE_COMPARISON: return WGPUSamplerBindingType_Comparison;\n        case SG_SAMPLERTYPE_NONFILTERING: return WGPUSamplerBindingType_NonFiltering;\n        default: SOKOL_UNREACHABLE; return WGPUSamplerBindingType_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUAddressMode _sg_wgpu_sampler_address_mode(sg_wrap m) {\n    switch (m) {\n        case SG_WRAP_REPEAT:\n            return WGPUAddressMode_Repeat;\n        case SG_WRAP_CLAMP_TO_EDGE:\n        case SG_WRAP_CLAMP_TO_BORDER:\n            return WGPUAddressMode_ClampToEdge;\n        case SG_WRAP_MIRRORED_REPEAT:\n            return WGPUAddressMode_MirrorRepeat;\n        default:\n            SOKOL_UNREACHABLE;\n            return WGPUAddressMode_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUFilterMode _sg_wgpu_sampler_minmag_filter(sg_filter f) {\n    switch (f) {\n        case SG_FILTER_NEAREST:\n            return WGPUFilterMode_Nearest;\n        case SG_FILTER_LINEAR:\n            return WGPUFilterMode_Linear;\n        default:\n            SOKOL_UNREACHABLE;\n            return WGPUFilterMode_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUMipmapFilterMode _sg_wgpu_sampler_mipmap_filter(sg_filter f) {\n    switch (f) {\n        case SG_FILTER_NONE:\n        case SG_FILTER_NEAREST:\n            return WGPUMipmapFilterMode_Nearest;\n        case SG_FILTER_LINEAR:\n            return WGPUMipmapFilterMode_Linear;\n        default:\n            SOKOL_UNREACHABLE;\n            return WGPUMipmapFilterMode_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUIndexFormat _sg_wgpu_indexformat(sg_index_type t) {\n    // NOTE: there's no WGPUIndexFormat_None\n    return (t == SG_INDEXTYPE_UINT16) ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32;\n}\n\n_SOKOL_PRIVATE WGPUIndexFormat _sg_wgpu_stripindexformat(sg_primitive_type prim_type, sg_index_type idx_type) {\n    if (idx_type == SG_INDEXTYPE_NONE) {\n        return WGPUIndexFormat_Undefined;\n    } else if ((prim_type == SG_PRIMITIVETYPE_LINE_STRIP) || (prim_type == SG_PRIMITIVETYPE_TRIANGLE_STRIP)) {\n        return _sg_wgpu_indexformat(idx_type);\n    } else {\n        return WGPUIndexFormat_Undefined;\n    }\n}\n\n_SOKOL_PRIVATE WGPUVertexStepMode _sg_wgpu_stepmode(sg_vertex_step s) {\n    return (s == SG_VERTEXSTEP_PER_VERTEX) ? WGPUVertexStepMode_Vertex : WGPUVertexStepMode_Instance;\n}\n\n_SOKOL_PRIVATE WGPUVertexFormat _sg_wgpu_vertexformat(sg_vertex_format f) {\n    switch (f) {\n        case SG_VERTEXFORMAT_FLOAT:         return WGPUVertexFormat_Float32;\n        case SG_VERTEXFORMAT_FLOAT2:        return WGPUVertexFormat_Float32x2;\n        case SG_VERTEXFORMAT_FLOAT3:        return WGPUVertexFormat_Float32x3;\n        case SG_VERTEXFORMAT_FLOAT4:        return WGPUVertexFormat_Float32x4;\n        case SG_VERTEXFORMAT_BYTE4:         return WGPUVertexFormat_Sint8x4;\n        case SG_VERTEXFORMAT_BYTE4N:        return WGPUVertexFormat_Snorm8x4;\n        case SG_VERTEXFORMAT_UBYTE4:        return WGPUVertexFormat_Uint8x4;\n        case SG_VERTEXFORMAT_UBYTE4N:       return WGPUVertexFormat_Unorm8x4;\n        case SG_VERTEXFORMAT_SHORT2:        return WGPUVertexFormat_Sint16x2;\n        case SG_VERTEXFORMAT_SHORT2N:       return WGPUVertexFormat_Snorm16x2;\n        case SG_VERTEXFORMAT_USHORT2N:      return WGPUVertexFormat_Unorm16x2;\n        case SG_VERTEXFORMAT_SHORT4:        return WGPUVertexFormat_Sint16x4;\n        case SG_VERTEXFORMAT_SHORT4N:       return WGPUVertexFormat_Snorm16x4;\n        case SG_VERTEXFORMAT_USHORT4N:      return WGPUVertexFormat_Unorm16x4;\n        case SG_VERTEXFORMAT_HALF2:         return WGPUVertexFormat_Float16x2;\n        case SG_VERTEXFORMAT_HALF4:         return WGPUVertexFormat_Float16x4;\n        // FIXME! UINT10_N2 (see https://github.com/gpuweb/gpuweb/issues/4275)\n        case SG_VERTEXFORMAT_UINT10_N2:     return WGPUVertexFormat_Undefined;\n        default:\n            SOKOL_UNREACHABLE;\n            return WGPUVertexFormat_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUPrimitiveTopology _sg_wgpu_topology(sg_primitive_type t) {\n    switch (t) {\n        case SG_PRIMITIVETYPE_POINTS:           return WGPUPrimitiveTopology_PointList;\n        case SG_PRIMITIVETYPE_LINES:            return WGPUPrimitiveTopology_LineList;\n        case SG_PRIMITIVETYPE_LINE_STRIP:       return WGPUPrimitiveTopology_LineStrip;\n        case SG_PRIMITIVETYPE_TRIANGLES:        return WGPUPrimitiveTopology_TriangleList;\n        case SG_PRIMITIVETYPE_TRIANGLE_STRIP:   return WGPUPrimitiveTopology_TriangleStrip;\n        default:\n            SOKOL_UNREACHABLE;\n            return WGPUPrimitiveTopology_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUFrontFace _sg_wgpu_frontface(sg_face_winding fw) {\n    return (fw == SG_FACEWINDING_CCW) ? WGPUFrontFace_CCW : WGPUFrontFace_CW;\n}\n\n_SOKOL_PRIVATE WGPUCullMode _sg_wgpu_cullmode(sg_cull_mode cm) {\n    switch (cm) {\n        case SG_CULLMODE_NONE:      return WGPUCullMode_None;\n        case SG_CULLMODE_FRONT:     return WGPUCullMode_Front;\n        case SG_CULLMODE_BACK:      return WGPUCullMode_Back;\n        default:\n            SOKOL_UNREACHABLE;\n            return WGPUCullMode_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUTextureFormat _sg_wgpu_textureformat(sg_pixel_format p) {\n    switch (p) {\n        case SG_PIXELFORMAT_NONE:           return WGPUTextureFormat_Undefined;\n        case SG_PIXELFORMAT_R8:             return WGPUTextureFormat_R8Unorm;\n        case SG_PIXELFORMAT_R8SN:           return WGPUTextureFormat_R8Snorm;\n        case SG_PIXELFORMAT_R8UI:           return WGPUTextureFormat_R8Uint;\n        case SG_PIXELFORMAT_R8SI:           return WGPUTextureFormat_R8Sint;\n        case SG_PIXELFORMAT_R16UI:          return WGPUTextureFormat_R16Uint;\n        case SG_PIXELFORMAT_R16SI:          return WGPUTextureFormat_R16Sint;\n        case SG_PIXELFORMAT_R16F:           return WGPUTextureFormat_R16Float;\n        case SG_PIXELFORMAT_RG8:            return WGPUTextureFormat_RG8Unorm;\n        case SG_PIXELFORMAT_RG8SN:          return WGPUTextureFormat_RG8Snorm;\n        case SG_PIXELFORMAT_RG8UI:          return WGPUTextureFormat_RG8Uint;\n        case SG_PIXELFORMAT_RG8SI:          return WGPUTextureFormat_RG8Sint;\n        case SG_PIXELFORMAT_R32UI:          return WGPUTextureFormat_R32Uint;\n        case SG_PIXELFORMAT_R32SI:          return WGPUTextureFormat_R32Sint;\n        case SG_PIXELFORMAT_R32F:           return WGPUTextureFormat_R32Float;\n        case SG_PIXELFORMAT_RG16UI:         return WGPUTextureFormat_RG16Uint;\n        case SG_PIXELFORMAT_RG16SI:         return WGPUTextureFormat_RG16Sint;\n        case SG_PIXELFORMAT_RG16F:          return WGPUTextureFormat_RG16Float;\n        case SG_PIXELFORMAT_RGBA8:          return WGPUTextureFormat_RGBA8Unorm;\n        case SG_PIXELFORMAT_SRGB8A8:        return WGPUTextureFormat_RGBA8UnormSrgb;\n        case SG_PIXELFORMAT_RGBA8SN:        return WGPUTextureFormat_RGBA8Snorm;\n        case SG_PIXELFORMAT_RGBA8UI:        return WGPUTextureFormat_RGBA8Uint;\n        case SG_PIXELFORMAT_RGBA8SI:        return WGPUTextureFormat_RGBA8Sint;\n        case SG_PIXELFORMAT_BGRA8:          return WGPUTextureFormat_BGRA8Unorm;\n        case SG_PIXELFORMAT_RGB10A2:        return WGPUTextureFormat_RGB10A2Unorm;\n        case SG_PIXELFORMAT_RG11B10F:       return WGPUTextureFormat_RG11B10Ufloat;\n        case SG_PIXELFORMAT_RG32UI:         return WGPUTextureFormat_RG32Uint;\n        case SG_PIXELFORMAT_RG32SI:         return WGPUTextureFormat_RG32Sint;\n        case SG_PIXELFORMAT_RG32F:          return WGPUTextureFormat_RG32Float;\n        case SG_PIXELFORMAT_RGBA16UI:       return WGPUTextureFormat_RGBA16Uint;\n        case SG_PIXELFORMAT_RGBA16SI:       return WGPUTextureFormat_RGBA16Sint;\n        case SG_PIXELFORMAT_RGBA16F:        return WGPUTextureFormat_RGBA16Float;\n        case SG_PIXELFORMAT_RGBA32UI:       return WGPUTextureFormat_RGBA32Uint;\n        case SG_PIXELFORMAT_RGBA32SI:       return WGPUTextureFormat_RGBA32Sint;\n        case SG_PIXELFORMAT_RGBA32F:        return WGPUTextureFormat_RGBA32Float;\n        case SG_PIXELFORMAT_DEPTH:          return WGPUTextureFormat_Depth32Float;\n        case SG_PIXELFORMAT_DEPTH_STENCIL:  return WGPUTextureFormat_Depth32FloatStencil8;\n        case SG_PIXELFORMAT_BC1_RGBA:       return WGPUTextureFormat_BC1RGBAUnorm;\n        case SG_PIXELFORMAT_BC2_RGBA:       return WGPUTextureFormat_BC2RGBAUnorm;\n        case SG_PIXELFORMAT_BC3_RGBA:       return WGPUTextureFormat_BC3RGBAUnorm;\n        case SG_PIXELFORMAT_BC3_SRGBA:      return WGPUTextureFormat_BC3RGBAUnormSrgb;\n        case SG_PIXELFORMAT_BC4_R:          return WGPUTextureFormat_BC4RUnorm;\n        case SG_PIXELFORMAT_BC4_RSN:        return WGPUTextureFormat_BC4RSnorm;\n        case SG_PIXELFORMAT_BC5_RG:         return WGPUTextureFormat_BC5RGUnorm;\n        case SG_PIXELFORMAT_BC5_RGSN:       return WGPUTextureFormat_BC5RGSnorm;\n        case SG_PIXELFORMAT_BC6H_RGBF:      return WGPUTextureFormat_BC6HRGBFloat;\n        case SG_PIXELFORMAT_BC6H_RGBUF:     return WGPUTextureFormat_BC6HRGBUfloat;\n        case SG_PIXELFORMAT_BC7_RGBA:       return WGPUTextureFormat_BC7RGBAUnorm;\n        case SG_PIXELFORMAT_BC7_SRGBA:      return WGPUTextureFormat_BC7RGBAUnormSrgb;\n        case SG_PIXELFORMAT_ETC2_RGB8:      return WGPUTextureFormat_ETC2RGB8Unorm;\n        case SG_PIXELFORMAT_ETC2_RGB8A1:    return WGPUTextureFormat_ETC2RGB8A1Unorm;\n        case SG_PIXELFORMAT_ETC2_RGBA8:     return WGPUTextureFormat_ETC2RGBA8Unorm;\n        case SG_PIXELFORMAT_ETC2_SRGB8:     return WGPUTextureFormat_ETC2RGB8UnormSrgb;\n        case SG_PIXELFORMAT_ETC2_SRGB8A8:   return WGPUTextureFormat_ETC2RGBA8UnormSrgb;\n        case SG_PIXELFORMAT_EAC_R11:        return WGPUTextureFormat_EACR11Unorm;\n        case SG_PIXELFORMAT_EAC_R11SN:      return WGPUTextureFormat_EACR11Snorm;\n        case SG_PIXELFORMAT_EAC_RG11:       return WGPUTextureFormat_EACRG11Unorm;\n        case SG_PIXELFORMAT_EAC_RG11SN:     return WGPUTextureFormat_EACRG11Snorm;\n        case SG_PIXELFORMAT_RGB9E5:         return WGPUTextureFormat_RGB9E5Ufloat;\n        case SG_PIXELFORMAT_ASTC_4x4_RGBA:  return WGPUTextureFormat_ASTC4x4Unorm;\n        case SG_PIXELFORMAT_ASTC_4x4_SRGBA: return WGPUTextureFormat_ASTC4x4UnormSrgb;\n        // NOT SUPPORTED\n        case SG_PIXELFORMAT_R16:\n        case SG_PIXELFORMAT_R16SN:\n        case SG_PIXELFORMAT_RG16:\n        case SG_PIXELFORMAT_RG16SN:\n        case SG_PIXELFORMAT_RGBA16:\n        case SG_PIXELFORMAT_RGBA16SN:\n        case SG_PIXELFORMAT_PVRTC_RGB_2BPP:\n        case SG_PIXELFORMAT_PVRTC_RGB_4BPP:\n        case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:\n        case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:\n            return WGPUTextureFormat_Undefined;\n\n        default:\n            SOKOL_UNREACHABLE;\n            return WGPUTextureFormat_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUCompareFunction _sg_wgpu_comparefunc(sg_compare_func f) {\n    switch (f) {\n        case SG_COMPAREFUNC_NEVER:          return WGPUCompareFunction_Never;\n        case SG_COMPAREFUNC_LESS:           return WGPUCompareFunction_Less;\n        case SG_COMPAREFUNC_EQUAL:          return WGPUCompareFunction_Equal;\n        case SG_COMPAREFUNC_LESS_EQUAL:     return WGPUCompareFunction_LessEqual;\n        case SG_COMPAREFUNC_GREATER:        return WGPUCompareFunction_Greater;\n        case SG_COMPAREFUNC_NOT_EQUAL:      return WGPUCompareFunction_NotEqual;\n        case SG_COMPAREFUNC_GREATER_EQUAL:  return WGPUCompareFunction_GreaterEqual;\n        case SG_COMPAREFUNC_ALWAYS:         return WGPUCompareFunction_Always;\n        default:\n            SOKOL_UNREACHABLE;\n            return WGPUCompareFunction_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUStencilOperation _sg_wgpu_stencilop(sg_stencil_op op) {\n    switch (op) {\n        case SG_STENCILOP_KEEP:         return WGPUStencilOperation_Keep;\n        case SG_STENCILOP_ZERO:         return WGPUStencilOperation_Zero;\n        case SG_STENCILOP_REPLACE:      return WGPUStencilOperation_Replace;\n        case SG_STENCILOP_INCR_CLAMP:   return WGPUStencilOperation_IncrementClamp;\n        case SG_STENCILOP_DECR_CLAMP:   return WGPUStencilOperation_DecrementClamp;\n        case SG_STENCILOP_INVERT:       return WGPUStencilOperation_Invert;\n        case SG_STENCILOP_INCR_WRAP:    return WGPUStencilOperation_IncrementWrap;\n        case SG_STENCILOP_DECR_WRAP:    return WGPUStencilOperation_DecrementWrap;\n        default:\n            SOKOL_UNREACHABLE;\n            return WGPUStencilOperation_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUBlendOperation _sg_wgpu_blendop(sg_blend_op op) {\n    switch (op) {\n        case SG_BLENDOP_ADD:                return WGPUBlendOperation_Add;\n        case SG_BLENDOP_SUBTRACT:           return WGPUBlendOperation_Subtract;\n        case SG_BLENDOP_REVERSE_SUBTRACT:   return WGPUBlendOperation_ReverseSubtract;\n        default:\n            SOKOL_UNREACHABLE;\n            return WGPUBlendOperation_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUBlendFactor _sg_wgpu_blendfactor(sg_blend_factor f) {\n    switch (f) {\n        case SG_BLENDFACTOR_ZERO:                   return WGPUBlendFactor_Zero;\n        case SG_BLENDFACTOR_ONE:                    return WGPUBlendFactor_One;\n        case SG_BLENDFACTOR_SRC_COLOR:              return WGPUBlendFactor_Src;\n        case SG_BLENDFACTOR_ONE_MINUS_SRC_COLOR:    return WGPUBlendFactor_OneMinusSrc;\n        case SG_BLENDFACTOR_SRC_ALPHA:              return WGPUBlendFactor_SrcAlpha;\n        case SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:    return WGPUBlendFactor_OneMinusSrcAlpha;\n        case SG_BLENDFACTOR_DST_COLOR:              return WGPUBlendFactor_Dst;\n        case SG_BLENDFACTOR_ONE_MINUS_DST_COLOR:    return WGPUBlendFactor_OneMinusDst;\n        case SG_BLENDFACTOR_DST_ALPHA:              return WGPUBlendFactor_DstAlpha;\n        case SG_BLENDFACTOR_ONE_MINUS_DST_ALPHA:    return WGPUBlendFactor_OneMinusDstAlpha;\n        case SG_BLENDFACTOR_SRC_ALPHA_SATURATED:    return WGPUBlendFactor_SrcAlphaSaturated;\n        case SG_BLENDFACTOR_BLEND_COLOR:            return WGPUBlendFactor_Constant;\n        case SG_BLENDFACTOR_ONE_MINUS_BLEND_COLOR:  return WGPUBlendFactor_OneMinusConstant;\n        // FIXME: separate blend alpha value not supported?\n        case SG_BLENDFACTOR_BLEND_ALPHA:            return WGPUBlendFactor_Constant;\n        case SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA:  return WGPUBlendFactor_OneMinusConstant;\n        default:\n            SOKOL_UNREACHABLE;\n            return WGPUBlendFactor_Force32;\n    }\n}\n\n_SOKOL_PRIVATE WGPUColorWriteMaskFlags _sg_wgpu_colorwritemask(uint8_t m) {\n    WGPUColorWriteMaskFlags res = 0;\n    if (0 != (m & SG_COLORMASK_R)) {\n        res |= WGPUColorWriteMask_Red;\n    }\n    if (0 != (m & SG_COLORMASK_G)) {\n        res |= WGPUColorWriteMask_Green;\n    }\n    if (0 != (m & SG_COLORMASK_B)) {\n        res |= WGPUColorWriteMask_Blue;\n    }\n    if (0 != (m & SG_COLORMASK_A)) {\n        res |= WGPUColorWriteMask_Alpha;\n    }\n    return res;\n}\n\n// image/sampler binding on wgpu follows this convention:\n//\n//  - all images and sampler are in @group(1)\n//  - vertex stage images start at @binding(0)\n//  - vertex stage samplers start at @binding(16)\n//  - vertex stage storage buffers start at @binding(32)\n//  - fragment stage images start at @binding(48)\n//  - fragment stage samplers start at @binding(64)\n//  - fragment stage storage buffers start at @binding(80)\n//\n_SOKOL_PRIVATE uint32_t _sg_wgpu_image_binding(sg_shader_stage stage, int img_slot) {\n    SOKOL_ASSERT((img_slot >= 0) && (img_slot < 16));\n    if (SG_SHADERSTAGE_VS == stage) {\n        return 0 + (uint32_t)img_slot;\n    } else {\n        return 48 + (uint32_t)img_slot;\n    }\n}\n\n_SOKOL_PRIVATE uint32_t _sg_wgpu_sampler_binding(sg_shader_stage stage, int smp_slot) {\n    SOKOL_ASSERT((smp_slot >= 0) && (smp_slot < 16));\n    if (SG_SHADERSTAGE_VS == stage) {\n        return 16 + (uint32_t)smp_slot;\n    } else {\n        return 64 + (uint32_t)smp_slot;\n    }\n}\n\n_SOKOL_PRIVATE uint32_t _sg_wgpu_storagebuffer_binding(sg_shader_stage stage, int sbuf_slot) {\n    SOKOL_ASSERT((sbuf_slot >= 0) && (sbuf_slot < 16));\n    if (SG_SHADERSTAGE_VS == stage) {\n        return 32 + (uint32_t)sbuf_slot;\n    } else {\n        return 80 + (uint32_t)sbuf_slot;\n    }\n}\n\n_SOKOL_PRIVATE WGPUShaderStage _sg_wgpu_shader_stage(sg_shader_stage stage) {\n    switch (stage) {\n        case SG_SHADERSTAGE_VS: return WGPUShaderStage_Vertex;\n        case SG_SHADERSTAGE_FS: return WGPUShaderStage_Fragment;\n        default: SOKOL_UNREACHABLE; return WGPUShaderStage_None;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_init_caps(void) {\n    _sg.backend = SG_BACKEND_WGPU;\n    _sg.features.origin_top_left = true;\n    _sg.features.image_clamp_to_border = false;\n    _sg.features.mrt_independent_blend_state = true;\n    _sg.features.mrt_independent_write_mask = true;\n    _sg.features.storage_buffer = true;\n\n    wgpuDeviceGetLimits(_sg.wgpu.dev, &_sg.wgpu.limits);\n\n    const WGPULimits* l = &_sg.wgpu.limits.limits;\n    _sg.limits.max_image_size_2d = (int) l->maxTextureDimension2D;\n    _sg.limits.max_image_size_cube = (int) l->maxTextureDimension2D; // not a bug, see: https://github.com/gpuweb/gpuweb/issues/1327\n    _sg.limits.max_image_size_3d = (int) l->maxTextureDimension3D;\n    _sg.limits.max_image_size_array = (int) l->maxTextureDimension2D;\n    _sg.limits.max_image_array_layers = (int) l->maxTextureArrayLayers;\n    _sg.limits.max_vertex_attrs = SG_MAX_VERTEX_ATTRIBUTES;\n\n    // NOTE: no WGPUTextureFormat_R16Unorm\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R8]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG8]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA8]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_SRGB8A8]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_BGRA8]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16F]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16F]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16F]);\n    _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGB10A2]);\n\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_R8SN]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RG8SN]);\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RGBA8SN]);\n\n    // FIXME: can be made renderable via extension\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RG11B10F]);\n\n    // NOTE: msaa rendering is possible in WebGPU, but no resolve\n    // which is a combination that's not currently supported in sokol-gfx\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R8UI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R8SI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG8UI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG8SI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA8UI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA8SI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R16UI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R16SI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG16UI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG16SI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA16UI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA16SI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32UI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32SI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG32UI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG32SI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA32UI]);\n    _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA32SI]);\n\n    if (wgpuDeviceHasFeature(_sg.wgpu.dev, WGPUFeatureName_Float32Filterable)) {\n        _sg_pixelformat_sfr(&_sg.formats[SG_PIXELFORMAT_R32F]);\n        _sg_pixelformat_sfr(&_sg.formats[SG_PIXELFORMAT_RG32F]);\n        _sg_pixelformat_sfr(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);\n    } else {\n        _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32F]);\n        _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG32F]);\n        _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA32F]);\n    }\n\n    _sg_pixelformat_srmd(&_sg.formats[SG_PIXELFORMAT_DEPTH]);\n    _sg_pixelformat_srmd(&_sg.formats[SG_PIXELFORMAT_DEPTH_STENCIL]);\n\n    _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RGB9E5]);\n\n    if (wgpuDeviceHasFeature(_sg.wgpu.dev, WGPUFeatureName_TextureCompressionBC)) {\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC1_RGBA]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC2_RGBA]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC3_RGBA]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC3_SRGBA]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC4_R]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC4_RSN]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC5_RG]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC5_RGSN]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC6H_RGBF]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC6H_RGBUF]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC7_RGBA]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC7_SRGBA]);\n    }\n    if (wgpuDeviceHasFeature(_sg.wgpu.dev, WGPUFeatureName_TextureCompressionETC2)) {\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGB8]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_SRGB8]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGB8A1]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGBA8]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_SRGB8A8]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_EAC_R11]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_EAC_R11SN]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_EAC_RG11]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_EAC_RG11SN]);\n    }\n\n    if (wgpuDeviceHasFeature(_sg.wgpu.dev, WGPUFeatureName_TextureCompressionASTC)) {\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ASTC_4x4_RGBA]);\n        _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ASTC_4x4_SRGBA]);\n    }\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_init(const sg_desc* desc) {\n    SOKOL_ASSERT(0 == _sg.wgpu.uniform.staging);\n    SOKOL_ASSERT(0 == _sg.wgpu.uniform.buf);\n    SOKOL_ASSERT(0 == _sg.wgpu.uniform.bind.group_layout);\n    SOKOL_ASSERT(0 == _sg.wgpu.uniform.bind.group);\n\n    // Add the max-uniform-update size (64 KB) to the requested buffer size,\n    // this is to prevent validation errors in the WebGPU implementation\n    // if the entire buffer size is used per frame. 64 KB is the allowed\n    // max uniform update size on NVIDIA\n    //\n    // FIXME: is this still needed?\n    _sg.wgpu.uniform.num_bytes = (uint32_t)(desc->uniform_buffer_size + _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE);\n    _sg.wgpu.uniform.staging = (uint8_t*)_sg_malloc(_sg.wgpu.uniform.num_bytes);\n\n    WGPUBufferDescriptor ub_desc;\n    _sg_clear(&ub_desc, sizeof(ub_desc));\n    ub_desc.size = _sg.wgpu.uniform.num_bytes;\n    ub_desc.usage = WGPUBufferUsage_Uniform|WGPUBufferUsage_CopyDst;\n    _sg.wgpu.uniform.buf = wgpuDeviceCreateBuffer(_sg.wgpu.dev, &ub_desc);\n    SOKOL_ASSERT(_sg.wgpu.uniform.buf);\n\n    WGPUBindGroupLayoutEntry ub_bgle_desc[SG_NUM_SHADER_STAGES][SG_MAX_SHADERSTAGE_UBS];\n    _sg_clear(ub_bgle_desc, sizeof(ub_bgle_desc));\n    for (uint32_t stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {\n        WGPUShaderStage vis = (stage_index == SG_SHADERSTAGE_VS) ? WGPUShaderStage_Vertex : WGPUShaderStage_Fragment;\n        for (uint32_t ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) {\n            uint32_t bind_index = stage_index * SG_MAX_SHADERSTAGE_UBS + ub_index;\n            ub_bgle_desc[stage_index][ub_index].binding = bind_index;\n            ub_bgle_desc[stage_index][ub_index].visibility = vis;\n            ub_bgle_desc[stage_index][ub_index].buffer.type = WGPUBufferBindingType_Uniform;\n            ub_bgle_desc[stage_index][ub_index].buffer.hasDynamicOffset = true;\n        }\n    }\n\n    WGPUBindGroupLayoutDescriptor ub_bgl_desc;\n    _sg_clear(&ub_bgl_desc, sizeof(ub_bgl_desc));\n    ub_bgl_desc.entryCount = SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS;\n    ub_bgl_desc.entries = &ub_bgle_desc[0][0];\n    _sg.wgpu.uniform.bind.group_layout = wgpuDeviceCreateBindGroupLayout(_sg.wgpu.dev, &ub_bgl_desc);\n    SOKOL_ASSERT(_sg.wgpu.uniform.bind.group_layout);\n\n    WGPUBindGroupEntry ub_bge[SG_NUM_SHADER_STAGES][SG_MAX_SHADERSTAGE_UBS];\n    _sg_clear(ub_bge, sizeof(ub_bge));\n    for (uint32_t stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {\n        for (uint32_t ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) {\n            uint32_t bind_index = stage_index * SG_MAX_SHADERSTAGE_UBS + ub_index;\n            ub_bge[stage_index][ub_index].binding = bind_index;\n            ub_bge[stage_index][ub_index].buffer = _sg.wgpu.uniform.buf;\n            ub_bge[stage_index][ub_index].size = _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE;\n        }\n    }\n    WGPUBindGroupDescriptor bg_desc;\n    _sg_clear(&bg_desc, sizeof(bg_desc));\n    bg_desc.layout = _sg.wgpu.uniform.bind.group_layout;\n    bg_desc.entryCount = SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS;\n    bg_desc.entries = &ub_bge[0][0];\n    _sg.wgpu.uniform.bind.group = wgpuDeviceCreateBindGroup(_sg.wgpu.dev, &bg_desc);\n    SOKOL_ASSERT(_sg.wgpu.uniform.bind.group);\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_discard(void) {\n    if (_sg.wgpu.uniform.buf) {\n        wgpuBufferRelease(_sg.wgpu.uniform.buf);\n        _sg.wgpu.uniform.buf = 0;\n    }\n    if (_sg.wgpu.uniform.bind.group) {\n        wgpuBindGroupRelease(_sg.wgpu.uniform.bind.group);\n        _sg.wgpu.uniform.bind.group = 0;\n    }\n    if (_sg.wgpu.uniform.bind.group_layout) {\n        wgpuBindGroupLayoutRelease(_sg.wgpu.uniform.bind.group_layout);\n        _sg.wgpu.uniform.bind.group_layout = 0;\n    }\n    if (_sg.wgpu.uniform.staging) {\n        _sg_free(_sg.wgpu.uniform.staging);\n        _sg.wgpu.uniform.staging = 0;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_begin_pass(void) {\n    wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc,\n                                      0, // groupIndex 0 is reserved for uniform buffers\n                                      _sg.wgpu.uniform.bind.group,\n                                      SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS,\n                                      &_sg.wgpu.uniform.bind.offsets[0][0]);\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_commit(void) {\n    wgpuQueueWriteBuffer(_sg.wgpu.queue, _sg.wgpu.uniform.buf, 0, _sg.wgpu.uniform.staging, _sg.wgpu.uniform.offset);\n    _sg_stats_add(wgpu.uniforms.size_write_buffer, _sg.wgpu.uniform.offset);\n    _sg.wgpu.uniform.offset = 0;\n    _sg_clear(&_sg.wgpu.uniform.bind.offsets[0][0], sizeof(_sg.wgpu.uniform.bind.offsets));\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_bindgroups_pool_init(const sg_desc* desc) {\n    SOKOL_ASSERT((desc->wgpu_bindgroups_cache_size > 0) && (desc->wgpu_bindgroups_cache_size < _SG_MAX_POOL_SIZE));\n    _sg_wgpu_bindgroups_pool_t* p = &_sg.wgpu.bindgroups_pool;\n    SOKOL_ASSERT(0 == p->bindgroups);\n    const int pool_size = desc->wgpu_bindgroups_cache_size;\n    _sg_init_pool(&p->pool, pool_size);\n    size_t pool_byte_size = sizeof(_sg_wgpu_bindgroup_t) * (size_t)p->pool.size;\n    p->bindgroups = (_sg_wgpu_bindgroup_t*) _sg_malloc_clear(pool_byte_size);\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_bindgroups_pool_discard(void) {\n    _sg_wgpu_bindgroups_pool_t* p = &_sg.wgpu.bindgroups_pool;\n    SOKOL_ASSERT(p->bindgroups);\n    _sg_free(p->bindgroups); p->bindgroups = 0;\n    _sg_discard_pool(&p->pool);\n}\n\n_SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_bindgroup_at(uint32_t bg_id) {\n    SOKOL_ASSERT(SG_INVALID_ID != bg_id);\n    _sg_wgpu_bindgroups_pool_t* p = &_sg.wgpu.bindgroups_pool;\n    int slot_index = _sg_slot_index(bg_id);\n    SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < p->pool.size));\n    return &p->bindgroups[slot_index];\n}\n\n_SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_lookup_bindgroup(uint32_t bg_id) {\n    if (SG_INVALID_ID != bg_id) {\n        _sg_wgpu_bindgroup_t* bg = _sg_wgpu_bindgroup_at(bg_id);\n        if (bg->slot.id == bg_id) {\n            return bg;\n        }\n    }\n    return 0;\n}\n\n_SOKOL_PRIVATE _sg_wgpu_bindgroup_handle_t _sg_wgpu_alloc_bindgroup(void) {\n    _sg_wgpu_bindgroups_pool_t* p = &_sg.wgpu.bindgroups_pool;\n    _sg_wgpu_bindgroup_handle_t res;\n    int slot_index = _sg_pool_alloc_index(&p->pool);\n    if (_SG_INVALID_SLOT_INDEX != slot_index) {\n        res.id = _sg_slot_alloc(&p->pool, &p->bindgroups[slot_index].slot, slot_index);\n    } else {\n        res.id = SG_INVALID_ID;\n        _SG_ERROR(WGPU_BINDGROUPS_POOL_EXHAUSTED);\n    }\n    return res;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_dealloc_bindgroup(_sg_wgpu_bindgroup_t* bg) {\n    SOKOL_ASSERT(bg && (bg->slot.state == SG_RESOURCESTATE_ALLOC) && (bg->slot.id != SG_INVALID_ID));\n    _sg_wgpu_bindgroups_pool_t* p = &_sg.wgpu.bindgroups_pool;\n    _sg_pool_free_index(&p->pool, _sg_slot_index(bg->slot.id));\n    _sg_reset_slot(&bg->slot);\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_reset_bindgroup_to_alloc_state(_sg_wgpu_bindgroup_t* bg) {\n    SOKOL_ASSERT(bg);\n    _sg_slot_t slot = bg->slot;\n    _sg_clear(bg, sizeof(_sg_wgpu_bindgroup_t));\n    bg->slot = slot;\n    bg->slot.state = SG_RESOURCESTATE_ALLOC;\n}\n\n// MurmurHash64B (see: https://github.com/aappleby/smhasher/blob/61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash2.cpp#L142)\n_SOKOL_PRIVATE uint64_t _sg_wgpu_hash(const void* key, int len, uint64_t seed) {\n    const uint32_t m = 0x5bd1e995;\n    const int r = 24;\n    uint32_t h1 = (uint32_t)seed ^ (uint32_t)len;\n    uint32_t h2 = (uint32_t)(seed >> 32);\n    const uint32_t * data = (const uint32_t *)key;\n    while (len >= 8) {\n        uint32_t k1 = *data++;\n        k1 *= m; k1 ^= k1 >> r; k1 *= m;\n        h1 *= m; h1 ^= k1;\n        len -= 4;\n        uint32_t k2 = *data++;\n        k2 *= m; k2 ^= k2 >> r; k2 *= m;\n        h2 *= m; h2 ^= k2;\n        len -= 4;\n    }\n    if (len >= 4) {\n        uint32_t k1 = *data++;\n        k1 *= m; k1 ^= k1 >> r; k1 *= m;\n        h1 *= m; h1 ^= k1;\n        len -= 4;\n    }\n    switch(len) {\n        case 3: h2 ^= (uint32_t)(((unsigned char*)data)[2] << 16);\n        case 2: h2 ^= (uint32_t)(((unsigned char*)data)[1] << 8);\n        case 1: h2 ^= ((unsigned char*)data)[0];\n        h2 *= m;\n    };\n    h1 ^= h2 >> 18; h1 *= m;\n    h2 ^= h1 >> 22; h2 *= m;\n    h1 ^= h2 >> 17; h1 *= m;\n    h2 ^= h1 >> 19; h2 *= m;\n    uint64_t h = h1;\n    h = (h << 32) | h2;\n    return h;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_init_bindgroups_cache_key(_sg_wgpu_bindgroups_cache_key_t* key, const _sg_bindings_t* bnd) {\n    SOKOL_ASSERT(bnd);\n    SOKOL_ASSERT(bnd->pip);\n    SOKOL_ASSERT(bnd->num_vs_imgs <= SG_MAX_SHADERSTAGE_IMAGES);\n    SOKOL_ASSERT(bnd->num_vs_smps <= SG_MAX_SHADERSTAGE_SAMPLERS);\n    SOKOL_ASSERT(bnd->num_vs_sbufs <= SG_MAX_SHADERSTAGE_STORAGEBUFFERS);\n    SOKOL_ASSERT(bnd->num_fs_imgs <= SG_MAX_SHADERSTAGE_IMAGES);\n    SOKOL_ASSERT(bnd->num_fs_smps <= SG_MAX_SHADERSTAGE_SAMPLERS);\n    SOKOL_ASSERT(bnd->num_fs_sbufs <= SG_MAX_SHADERSTAGE_STORAGEBUFFERS);\n\n    _sg_clear(key->items, sizeof(key->items));\n    key->items[0] = bnd->pip->slot.id;\n    const int vs_imgs_offset = 1;\n    const int vs_smps_offset = vs_imgs_offset + SG_MAX_SHADERSTAGE_IMAGES;\n    const int vs_sbufs_offset = vs_smps_offset + SG_MAX_SHADERSTAGE_SAMPLERS;\n    const int fs_imgs_offset = vs_sbufs_offset + SG_MAX_SHADERSTAGE_STORAGEBUFFERS;\n    const int fs_smps_offset = fs_imgs_offset + SG_MAX_SHADERSTAGE_IMAGES;\n    const int fs_sbufs_offset = fs_smps_offset + SG_MAX_SHADERSTAGE_SAMPLERS;\n    SOKOL_ASSERT((fs_sbufs_offset + SG_MAX_SHADERSTAGE_STORAGEBUFFERS) == _SG_WGPU_BINDGROUPSCACHE_NUM_ITEMS);\n    for (int i = 0; i < bnd->num_vs_imgs; i++) {\n        SOKOL_ASSERT(bnd->vs_imgs[i]);\n        key->items[vs_imgs_offset + i] = bnd->vs_imgs[i]->slot.id;\n    }\n    for (int i = 0; i < bnd->num_vs_smps; i++) {\n        SOKOL_ASSERT(bnd->vs_smps[i]);\n        key->items[vs_smps_offset + i] = bnd->vs_smps[i]->slot.id;\n    }\n    for (int i = 0; i < bnd->num_vs_sbufs; i++) {\n        SOKOL_ASSERT(bnd->vs_sbufs[i]);\n        key->items[vs_sbufs_offset + i] = bnd->vs_sbufs[i]->slot.id;\n    }\n    for (int i = 0; i < bnd->num_fs_imgs; i++) {\n        SOKOL_ASSERT(bnd->fs_imgs[i]);\n        key->items[fs_imgs_offset + i] = bnd->fs_imgs[i]->slot.id;\n    }\n    for (int i = 0; i < bnd->num_fs_smps; i++) {\n        SOKOL_ASSERT(bnd->fs_smps[i]);\n        key->items[fs_smps_offset + i] = bnd->fs_smps[i]->slot.id;\n    }\n    for (int i = 0; i < bnd->num_fs_sbufs; i++) {\n        SOKOL_ASSERT(bnd->fs_sbufs[i]);\n        key->items[fs_sbufs_offset + i] = bnd->fs_sbufs[i]->slot.id;\n    }\n    key->hash = _sg_wgpu_hash(&key->items, (int)sizeof(key->items), 0x1234567887654321);\n}\n\n_SOKOL_PRIVATE bool _sg_wgpu_compare_bindgroups_cache_key(_sg_wgpu_bindgroups_cache_key_t* k0, _sg_wgpu_bindgroups_cache_key_t* k1) {\n    SOKOL_ASSERT(k0 && k1);\n    if (k0->hash != k1->hash) {\n        return false;\n    }\n    if (memcmp(&k0->items, &k1->items, sizeof(k0->items)) != 0) {\n        _sg_stats_add(wgpu.bindings.num_bindgroup_cache_hash_vs_key_mismatch, 1);\n        return false;\n    }\n    return true;\n}\n\n_SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_create_bindgroup(_sg_bindings_t* bnd) {\n    SOKOL_ASSERT(_sg.wgpu.dev);\n    SOKOL_ASSERT(bnd->pip);\n    SOKOL_ASSERT(bnd->pip->shader && (bnd->pip->cmn.shader_id.id == bnd->pip->shader->slot.id));\n    _sg_stats_add(wgpu.bindings.num_create_bindgroup, 1);\n    _sg_wgpu_bindgroup_handle_t bg_id = _sg_wgpu_alloc_bindgroup();\n    if (bg_id.id == SG_INVALID_ID) {\n        return 0;\n    }\n    _sg_wgpu_bindgroup_t* bg = _sg_wgpu_bindgroup_at(bg_id.id);\n    SOKOL_ASSERT(bg && (bg->slot.state == SG_RESOURCESTATE_ALLOC));\n\n    // create wgpu bindgroup object\n    WGPUBindGroupLayout bgl = bnd->pip->shader->wgpu.bind_group_layout;\n    SOKOL_ASSERT(bgl);\n    WGPUBindGroupEntry wgpu_entries[_SG_WGPU_MAX_BINDGROUP_ENTRIES];\n    _sg_clear(&wgpu_entries, sizeof(wgpu_entries));\n    int bge_index = 0;\n    for (int i = 0; i < bnd->num_vs_imgs; i++) {\n        WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++];\n        wgpu_entry->binding = _sg_wgpu_image_binding(SG_SHADERSTAGE_VS, i);\n        wgpu_entry->textureView = bnd->vs_imgs[i]->wgpu.view;\n    }\n    for (int i = 0; i < bnd->num_vs_smps; i++) {\n        WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++];\n        wgpu_entry->binding = _sg_wgpu_sampler_binding(SG_SHADERSTAGE_VS, i);\n        wgpu_entry->sampler = bnd->vs_smps[i]->wgpu.smp;\n    }\n    for (int i = 0; i < bnd->num_vs_sbufs; i++) {\n        WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++];\n        wgpu_entry->binding = _sg_wgpu_storagebuffer_binding(SG_SHADERSTAGE_VS, i);\n        wgpu_entry->buffer = bnd->vs_sbufs[i]->wgpu.buf;\n        wgpu_entry->size = (uint64_t) bnd->vs_sbufs[i]->cmn.size;\n    }\n    for (int i = 0; i < bnd->num_fs_imgs; i++) {\n        WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++];\n        wgpu_entry->binding = _sg_wgpu_image_binding(SG_SHADERSTAGE_FS, i);\n        wgpu_entry->textureView = bnd->fs_imgs[i]->wgpu.view;\n    }\n    for (int i = 0; i < bnd->num_fs_smps; i++) {\n        WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++];\n        wgpu_entry->binding = _sg_wgpu_sampler_binding(SG_SHADERSTAGE_FS, i);\n        wgpu_entry->sampler = bnd->fs_smps[i]->wgpu.smp;\n    }\n    for (int i = 0; i < bnd->num_fs_sbufs; i++) {\n        WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++];\n        wgpu_entry->binding = _sg_wgpu_storagebuffer_binding(SG_SHADERSTAGE_FS, i);\n        wgpu_entry->buffer = bnd->fs_sbufs[i]->wgpu.buf;\n        wgpu_entry->size = (uint64_t) bnd->fs_sbufs[i]->cmn.size;\n    }\n    WGPUBindGroupDescriptor bg_desc;\n    _sg_clear(&bg_desc, sizeof(bg_desc));\n    bg_desc.layout = bgl;\n    bg_desc.entryCount = (size_t)bge_index;\n    bg_desc.entries = &wgpu_entries[0];\n    bg->bindgroup = wgpuDeviceCreateBindGroup(_sg.wgpu.dev, &bg_desc);\n    if (bg->bindgroup == 0) {\n        _SG_ERROR(WGPU_CREATEBINDGROUP_FAILED);\n        bg->slot.state = SG_RESOURCESTATE_FAILED;\n        return bg;\n    }\n\n    _sg_wgpu_init_bindgroups_cache_key(&bg->key, bnd);\n\n    bg->slot.state = SG_RESOURCESTATE_VALID;\n    return bg;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_discard_bindgroup(_sg_wgpu_bindgroup_t* bg) {\n    SOKOL_ASSERT(bg);\n    _sg_stats_add(wgpu.bindings.num_discard_bindgroup, 1);\n    if (bg->slot.state == SG_RESOURCESTATE_VALID) {\n        if (bg->bindgroup) {\n            wgpuBindGroupRelease(bg->bindgroup);\n            bg->bindgroup = 0;\n        }\n        _sg_wgpu_reset_bindgroup_to_alloc_state(bg);\n        SOKOL_ASSERT(bg->slot.state == SG_RESOURCESTATE_ALLOC);\n    }\n    if (bg->slot.state == SG_RESOURCESTATE_ALLOC) {\n        _sg_wgpu_dealloc_bindgroup(bg);\n        SOKOL_ASSERT(bg->slot.state == SG_RESOURCESTATE_INITIAL);\n    }\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_discard_all_bindgroups(void) {\n    _sg_wgpu_bindgroups_pool_t* p = &_sg.wgpu.bindgroups_pool;\n    for (int i = 0; i < p->pool.size; i++) {\n        sg_resource_state state = p->bindgroups[i].slot.state;\n        if ((state == SG_RESOURCESTATE_VALID) || (state == SG_RESOURCESTATE_FAILED)) {\n            _sg_wgpu_discard_bindgroup(&p->bindgroups[i]);\n        }\n    }\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_bindgroups_cache_init(const sg_desc* desc) {\n    SOKOL_ASSERT(desc);\n    SOKOL_ASSERT(_sg.wgpu.bindgroups_cache.num == 0);\n    SOKOL_ASSERT(_sg.wgpu.bindgroups_cache.index_mask == 0);\n    SOKOL_ASSERT(_sg.wgpu.bindgroups_cache.items == 0);\n    const int num = desc->wgpu_bindgroups_cache_size;\n    if (num <= 1) {\n        _SG_PANIC(WGPU_BINDGROUPSCACHE_SIZE_GREATER_ONE);\n    }\n    if (!_sg_ispow2(num)) {\n        _SG_PANIC(WGPU_BINDGROUPSCACHE_SIZE_POW2);\n    }\n    _sg.wgpu.bindgroups_cache.num = (uint32_t)desc->wgpu_bindgroups_cache_size;\n    _sg.wgpu.bindgroups_cache.index_mask = _sg.wgpu.bindgroups_cache.num - 1;\n    size_t size_in_bytes = sizeof(_sg_wgpu_bindgroup_handle_t) * (size_t)num;\n    _sg.wgpu.bindgroups_cache.items = (_sg_wgpu_bindgroup_handle_t*)_sg_malloc_clear(size_in_bytes);\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_bindgroups_cache_discard(void) {\n    if (_sg.wgpu.bindgroups_cache.items) {\n        _sg_free(_sg.wgpu.bindgroups_cache.items);\n        _sg.wgpu.bindgroups_cache.items = 0;\n    }\n    _sg.wgpu.bindgroups_cache.num = 0;\n    _sg.wgpu.bindgroups_cache.index_mask = 0;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_bindgroups_cache_set(uint64_t hash, uint32_t bg_id) {\n    uint32_t index = hash & _sg.wgpu.bindgroups_cache.index_mask;\n    SOKOL_ASSERT(index < _sg.wgpu.bindgroups_cache.num);\n    SOKOL_ASSERT(_sg.wgpu.bindgroups_cache.items);\n    _sg.wgpu.bindgroups_cache.items[index].id = bg_id;\n}\n\n_SOKOL_PRIVATE uint32_t _sg_wgpu_bindgroups_cache_get(uint64_t hash) {\n    uint32_t index = hash & _sg.wgpu.bindgroups_cache.index_mask;\n    SOKOL_ASSERT(index < _sg.wgpu.bindgroups_cache.num);\n    SOKOL_ASSERT(_sg.wgpu.bindgroups_cache.items);\n    return _sg.wgpu.bindgroups_cache.items[index].id;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_bindings_cache_clear(void) {\n    memset(&_sg.wgpu.bindings_cache, 0, sizeof(_sg.wgpu.bindings_cache));\n}\n\n_SOKOL_PRIVATE bool _sg_wgpu_bindings_cache_vb_dirty(int index, const _sg_buffer_t* vb, int offset) {\n    SOKOL_ASSERT((index >= 0) && (index < SG_MAX_VERTEX_BUFFERS));\n    if (vb) {\n        return (_sg.wgpu.bindings_cache.vbs[index].buffer.id != vb->slot.id)\n            || (_sg.wgpu.bindings_cache.vbs[index].offset != offset);\n    } else {\n        return _sg.wgpu.bindings_cache.vbs[index].buffer.id != SG_INVALID_ID;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_bindings_cache_vb_update(int index, const _sg_buffer_t* vb, int offset) {\n    SOKOL_ASSERT((index >= 0) && (index < SG_MAX_VERTEX_BUFFERS));\n    if (vb) {\n        _sg.wgpu.bindings_cache.vbs[index].buffer.id = vb->slot.id;\n        _sg.wgpu.bindings_cache.vbs[index].offset = offset;\n    } else {\n        _sg.wgpu.bindings_cache.vbs[index].buffer.id = SG_INVALID_ID;\n        _sg.wgpu.bindings_cache.vbs[index].offset = 0;\n    }\n}\n\n_SOKOL_PRIVATE bool _sg_wgpu_bindings_cache_ib_dirty(const _sg_buffer_t* ib, int offset) {\n    if (ib) {\n        return (_sg.wgpu.bindings_cache.ib.buffer.id != ib->slot.id)\n            || (_sg.wgpu.bindings_cache.ib.offset != offset);\n    } else {\n        return _sg.wgpu.bindings_cache.ib.buffer.id != SG_INVALID_ID;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_bindings_cache_ib_update(const _sg_buffer_t* ib, int offset) {\n    if (ib) {\n        _sg.wgpu.bindings_cache.ib.buffer.id = ib->slot.id;\n        _sg.wgpu.bindings_cache.ib.offset = offset;\n    } else {\n        _sg.wgpu.bindings_cache.ib.buffer.id = SG_INVALID_ID;\n        _sg.wgpu.bindings_cache.ib.offset = 0;\n    }\n}\n\n_SOKOL_PRIVATE bool _sg_wgpu_bindings_cache_bg_dirty(const _sg_wgpu_bindgroup_t* bg) {\n    if (bg) {\n        return _sg.wgpu.bindings_cache.bg.id != bg->slot.id;\n    } else {\n        return _sg.wgpu.bindings_cache.bg.id != SG_INVALID_ID;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_bindings_cache_bg_update(const _sg_wgpu_bindgroup_t* bg) {\n    if (bg) {\n        _sg.wgpu.bindings_cache.bg.id = bg->slot.id;\n    } else {\n        _sg.wgpu.bindings_cache.bg.id = SG_INVALID_ID;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_set_bindings_bindgroup(_sg_wgpu_bindgroup_t* bg) {\n    if (_sg_wgpu_bindings_cache_bg_dirty(bg)) {\n        _sg_wgpu_bindings_cache_bg_update(bg);\n        _sg_stats_add(wgpu.bindings.num_set_bindgroup, 1);\n        if (bg) {\n            SOKOL_ASSERT(bg->slot.state == SG_RESOURCESTATE_VALID);\n            SOKOL_ASSERT(bg->bindgroup);\n            wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, bg->bindgroup, 0, 0);\n        } else {\n            // a nullptr bindgroup means setting the empty bindgroup\n            wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, _sg.wgpu.empty_bind_group, 0, 0);\n        }\n    } else {\n        _sg_stats_add(wgpu.bindings.num_skip_redundant_bindgroup, 1);\n    }\n}\n\n_SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) {\n    if ((bnd->num_vs_imgs + bnd->num_vs_smps + bnd->num_vs_sbufs + bnd->num_fs_imgs + bnd->num_fs_smps + bnd->num_fs_sbufs) > 0) {\n        if (!_sg.desc.wgpu_disable_bindgroups_cache) {\n            _sg_wgpu_bindgroup_t* bg = 0;\n            _sg_wgpu_bindgroups_cache_key_t key;\n            _sg_wgpu_init_bindgroups_cache_key(&key, bnd);\n            uint32_t bg_id = _sg_wgpu_bindgroups_cache_get(key.hash);\n            if (bg_id != SG_INVALID_ID) {\n                // potential cache hit\n                bg = _sg_wgpu_lookup_bindgroup(bg_id);\n                SOKOL_ASSERT(bg && (bg->slot.state == SG_RESOURCESTATE_VALID));\n                if (!_sg_wgpu_compare_bindgroups_cache_key(&key, &bg->key)) {\n                    // cache collision, need to delete cached bindgroup\n                    _sg_stats_add(wgpu.bindings.num_bindgroup_cache_collisions, 1);\n                    _sg_wgpu_discard_bindgroup(bg);\n                    _sg_wgpu_bindgroups_cache_set(key.hash, SG_INVALID_ID);\n                    bg = 0;\n                } else {\n                    _sg_stats_add(wgpu.bindings.num_bindgroup_cache_hits, 1);\n                }\n            } else {\n                _sg_stats_add(wgpu.bindings.num_bindgroup_cache_misses, 1);\n            }\n            if (bg == 0) {\n                // either no cache entry yet, or cache collision, create new bindgroup and store in cache\n                bg = _sg_wgpu_create_bindgroup(bnd);\n                _sg_wgpu_bindgroups_cache_set(key.hash, bg->slot.id);\n            }\n            if (bg && bg->slot.state == SG_RESOURCESTATE_VALID) {\n                _sg_wgpu_set_bindings_bindgroup(bg);\n            } else {\n                return false;\n            }\n        } else {\n            // bindgroups cache disabled, create and destroy bindgroup on the fly (expensive!)\n            _sg_wgpu_bindgroup_t* bg = _sg_wgpu_create_bindgroup(bnd);\n            if (bg) {\n                if (bg->slot.state == SG_RESOURCESTATE_VALID) {\n                    _sg_wgpu_set_bindings_bindgroup(bg);\n                }\n                _sg_wgpu_discard_bindgroup(bg);\n            } else {\n                return false;\n            }\n        }\n    } else {\n        _sg_wgpu_set_bindings_bindgroup(0);\n    }\n    return true;\n}\n\n_SOKOL_PRIVATE bool _sg_wgpu_apply_index_buffer(_sg_bindings_t* bnd) {\n    if (_sg_wgpu_bindings_cache_ib_dirty(bnd->ib, bnd->ib_offset)) {\n        _sg_wgpu_bindings_cache_ib_update(bnd->ib, bnd->ib_offset);\n        if (bnd->ib) {\n            const WGPUIndexFormat format = _sg_wgpu_indexformat(bnd->pip->cmn.index_type);\n            const uint64_t buf_size = (uint64_t)bnd->ib->cmn.size;\n            const uint64_t offset = (uint64_t)bnd->ib_offset;\n            SOKOL_ASSERT(buf_size > offset);\n            const uint64_t max_bytes = buf_size - offset;\n            wgpuRenderPassEncoderSetIndexBuffer(_sg.wgpu.pass_enc, bnd->ib->wgpu.buf, format, offset, max_bytes);\n            _sg_stats_add(wgpu.bindings.num_set_index_buffer, 1);\n        }\n        // FIXME: else-path should actually set a null index buffer (this was just recently implemented in WebGPU)\n    } else {\n        _sg_stats_add(wgpu.bindings.num_skip_redundant_index_buffer, 1);\n    }\n    return true;\n}\n\n_SOKOL_PRIVATE bool _sg_wgpu_apply_vertex_buffers(_sg_bindings_t* bnd) {\n    for (int slot = 0; slot < bnd->num_vbs; slot++) {\n        if (_sg_wgpu_bindings_cache_vb_dirty(slot, bnd->vbs[slot], bnd->vb_offsets[slot])) {\n            _sg_wgpu_bindings_cache_vb_update(slot, bnd->vbs[slot], bnd->vb_offsets[slot]);\n            const uint64_t buf_size = (uint64_t)bnd->vbs[slot]->cmn.size;\n            const uint64_t offset = (uint64_t)bnd->vb_offsets[slot];\n            SOKOL_ASSERT(buf_size > offset);\n            const uint64_t max_bytes = buf_size - offset;\n            wgpuRenderPassEncoderSetVertexBuffer(_sg.wgpu.pass_enc, (uint32_t)slot, bnd->vbs[slot]->wgpu.buf, offset, max_bytes);\n            _sg_stats_add(wgpu.bindings.num_set_vertex_buffer, 1);\n        } else {\n            _sg_stats_add(wgpu.bindings.num_skip_redundant_vertex_buffer, 1);\n        }\n    }\n    // FIXME: remaining vb slots should actually set a null vertex buffer (this was just recently implemented in WebGPU)\n    return true;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) {\n    SOKOL_ASSERT(desc);\n    SOKOL_ASSERT(desc->environment.wgpu.device);\n    SOKOL_ASSERT(desc->uniform_buffer_size > 0);\n    _sg.backend = SG_BACKEND_WGPU;\n    _sg.wgpu.valid = true;\n    _sg.wgpu.dev = (WGPUDevice) desc->environment.wgpu.device;\n    _sg.wgpu.queue = wgpuDeviceGetQueue(_sg.wgpu.dev);\n    SOKOL_ASSERT(_sg.wgpu.queue);\n\n    _sg_wgpu_init_caps();\n    _sg_wgpu_uniform_buffer_init(desc);\n    _sg_wgpu_bindgroups_pool_init(desc);\n    _sg_wgpu_bindgroups_cache_init(desc);\n    _sg_wgpu_bindings_cache_clear();\n\n    // create an empty bind group for shader stages without bound images\n    // FIXME: once WebGPU supports setting null objects, this can be removed\n    WGPUBindGroupLayoutDescriptor bgl_desc;\n    _sg_clear(&bgl_desc, sizeof(bgl_desc));\n    WGPUBindGroupLayout empty_bgl = wgpuDeviceCreateBindGroupLayout(_sg.wgpu.dev, &bgl_desc);\n    SOKOL_ASSERT(empty_bgl);\n    WGPUBindGroupDescriptor bg_desc;\n    _sg_clear(&bg_desc, sizeof(bg_desc));\n    bg_desc.layout = empty_bgl;\n    _sg.wgpu.empty_bind_group = wgpuDeviceCreateBindGroup(_sg.wgpu.dev, &bg_desc);\n    SOKOL_ASSERT(_sg.wgpu.empty_bind_group);\n    wgpuBindGroupLayoutRelease(empty_bgl);\n\n    // create initial per-frame command encoder\n    WGPUCommandEncoderDescriptor cmd_enc_desc;\n    _sg_clear(&cmd_enc_desc, sizeof(cmd_enc_desc));\n    _sg.wgpu.cmd_enc = wgpuDeviceCreateCommandEncoder(_sg.wgpu.dev, &cmd_enc_desc);\n    SOKOL_ASSERT(_sg.wgpu.cmd_enc);\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_discard_backend(void) {\n    SOKOL_ASSERT(_sg.wgpu.valid);\n    SOKOL_ASSERT(_sg.wgpu.cmd_enc);\n    _sg.wgpu.valid = false;\n    _sg_wgpu_discard_all_bindgroups();\n    _sg_wgpu_bindgroups_cache_discard();\n    _sg_wgpu_bindgroups_pool_discard();\n    _sg_wgpu_uniform_buffer_discard();\n    wgpuBindGroupRelease(_sg.wgpu.empty_bind_group); _sg.wgpu.empty_bind_group = 0;\n    wgpuCommandEncoderRelease(_sg.wgpu.cmd_enc); _sg.wgpu.cmd_enc = 0;\n    wgpuQueueRelease(_sg.wgpu.queue); _sg.wgpu.queue = 0;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_reset_state_cache(void) {\n    _sg_wgpu_bindings_cache_clear();\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_buffer(_sg_buffer_t* buf, const sg_buffer_desc* desc) {\n    SOKOL_ASSERT(buf && desc);\n    const bool injected = (0 != desc->wgpu_buffer);\n    if (injected) {\n        buf->wgpu.buf = (WGPUBuffer) desc->wgpu_buffer;\n        wgpuBufferReference(buf->wgpu.buf);\n    } else {\n        // buffer mapping size must be multiple of 4, so round up buffer size (only a problem\n        // with index buffers containing odd number of indices)\n        const uint64_t wgpu_buf_size = _sg_roundup_u64((uint64_t)buf->cmn.size, 4);\n        const bool map_at_creation = (SG_USAGE_IMMUTABLE == buf->cmn.usage);\n\n        WGPUBufferDescriptor wgpu_buf_desc;\n        _sg_clear(&wgpu_buf_desc, sizeof(wgpu_buf_desc));\n        wgpu_buf_desc.usage = _sg_wgpu_buffer_usage(buf->cmn.type, buf->cmn.usage);\n        wgpu_buf_desc.size = wgpu_buf_size;\n        wgpu_buf_desc.mappedAtCreation = map_at_creation;\n        wgpu_buf_desc.label = desc->label;\n        buf->wgpu.buf = wgpuDeviceCreateBuffer(_sg.wgpu.dev, &wgpu_buf_desc);\n        if (0 == buf->wgpu.buf) {\n            _SG_ERROR(WGPU_CREATE_BUFFER_FAILED);\n            return SG_RESOURCESTATE_FAILED;\n        }\n        if (map_at_creation) {\n            SOKOL_ASSERT(desc->data.ptr && (desc->data.size > 0));\n            SOKOL_ASSERT(desc->data.size <= (size_t)buf->cmn.size);\n            // FIXME: inefficient on WASM\n            void* ptr = wgpuBufferGetMappedRange(buf->wgpu.buf, 0, wgpu_buf_size);\n            SOKOL_ASSERT(ptr);\n            memcpy(ptr, desc->data.ptr, desc->data.size);\n            wgpuBufferUnmap(buf->wgpu.buf);\n        }\n    }\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_discard_buffer(_sg_buffer_t* buf) {\n    SOKOL_ASSERT(buf);\n    if (buf->wgpu.buf) {\n        wgpuBufferDestroy(buf->wgpu.buf);\n        wgpuBufferRelease(buf->wgpu.buf);\n    }\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_copy_buffer_data(const _sg_buffer_t* buf, uint64_t offset, const sg_range* data) {\n    SOKOL_ASSERT((offset + data->size) <= (size_t)buf->cmn.size);\n    // WebGPU's write-buffer requires the size to be a multiple of four, so we may need to split the copy\n    // operation into two writeBuffer calls\n    uint64_t clamped_size = data->size & ~3UL;\n    uint64_t extra_size = data->size & 3UL;\n    SOKOL_ASSERT(extra_size < 4);\n    wgpuQueueWriteBuffer(_sg.wgpu.queue, buf->wgpu.buf, offset, data->ptr, clamped_size);\n    if (extra_size > 0) {\n        const uint64_t extra_src_offset = clamped_size;\n        const uint64_t extra_dst_offset = offset + clamped_size;\n        uint8_t extra_data[4] = { 0 };\n        uint8_t* extra_src_ptr = ((uint8_t*)data->ptr) + extra_src_offset;\n        for (size_t i = 0; i < extra_size; i++) {\n            extra_data[i] = extra_src_ptr[i];\n        }\n        wgpuQueueWriteBuffer(_sg.wgpu.queue, buf->wgpu.buf, extra_dst_offset, extra_src_ptr, 4);\n    }\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_copy_image_data(const _sg_image_t* img, WGPUTexture wgpu_tex, const sg_image_data* data) {\n    WGPUTextureDataLayout wgpu_layout;\n    _sg_clear(&wgpu_layout, sizeof(wgpu_layout));\n    WGPUImageCopyTexture wgpu_copy_tex;\n    _sg_clear(&wgpu_copy_tex, sizeof(wgpu_copy_tex));\n    wgpu_copy_tex.texture = wgpu_tex;\n    wgpu_copy_tex.aspect = WGPUTextureAspect_All;\n    WGPUExtent3D wgpu_extent;\n    _sg_clear(&wgpu_extent, sizeof(wgpu_extent));\n    const int num_faces = (img->cmn.type == SG_IMAGETYPE_CUBE) ? 6 : 1;\n    for (int face_index = 0; face_index < num_faces; face_index++) {\n        for (int mip_index = 0; mip_index < img->cmn.num_mipmaps; mip_index++) {\n            wgpu_copy_tex.mipLevel = (uint32_t)mip_index;\n            wgpu_copy_tex.origin.z = (uint32_t)face_index;\n            int mip_width = _sg_miplevel_dim(img->cmn.width, mip_index);\n            int mip_height = _sg_miplevel_dim(img->cmn.height, mip_index);\n            int mip_slices;\n            switch (img->cmn.type) {\n                case SG_IMAGETYPE_CUBE:\n                    mip_slices = 1;\n                    break;\n                case SG_IMAGETYPE_3D:\n                    mip_slices = _sg_miplevel_dim(img->cmn.num_slices, mip_index);\n                    break;\n                default:\n                    mip_slices = img->cmn.num_slices;\n                    break;\n            }\n            const int row_pitch = _sg_row_pitch(img->cmn.pixel_format, mip_width, 1);\n            const int num_rows = _sg_num_rows(img->cmn.pixel_format, mip_height);\n            if (_sg_is_compressed_pixel_format(img->cmn.pixel_format)) {\n                mip_width = _sg_roundup(mip_width, 4);\n                mip_height = _sg_roundup(mip_height, 4);\n            }\n            wgpu_layout.offset = 0;\n            wgpu_layout.bytesPerRow = (uint32_t)row_pitch;\n            wgpu_layout.rowsPerImage = (uint32_t)num_rows;\n            wgpu_extent.width = (uint32_t)mip_width;\n            wgpu_extent.height = (uint32_t)mip_height;\n            wgpu_extent.depthOrArrayLayers = (uint32_t)mip_slices;\n            const sg_range* mip_data = &data->subimage[face_index][mip_index];\n            wgpuQueueWriteTexture(_sg.wgpu.queue, &wgpu_copy_tex, mip_data->ptr, mip_data->size, &wgpu_layout, &wgpu_extent);\n        }\n    }\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_image(_sg_image_t* img, const sg_image_desc* desc) {\n    SOKOL_ASSERT(img && desc);\n    const bool injected = (0 != desc->wgpu_texture);\n    if (injected) {\n        img->wgpu.tex = (WGPUTexture)desc->wgpu_texture;\n        wgpuTextureReference(img->wgpu.tex);\n        img->wgpu.view = (WGPUTextureView)desc->wgpu_texture_view;\n        if (img->wgpu.view) {\n            wgpuTextureViewReference(img->wgpu.view);\n        }\n    } else {\n        WGPUTextureDescriptor wgpu_tex_desc;\n        _sg_clear(&wgpu_tex_desc, sizeof(wgpu_tex_desc));\n        wgpu_tex_desc.label = desc->label;\n        wgpu_tex_desc.usage = WGPUTextureUsage_TextureBinding|WGPUTextureUsage_CopyDst;\n        if (desc->render_target) {\n            wgpu_tex_desc.usage |= WGPUTextureUsage_RenderAttachment;\n        }\n        wgpu_tex_desc.dimension = _sg_wgpu_texture_dimension(img->cmn.type);\n        wgpu_tex_desc.size.width = (uint32_t) img->cmn.width;\n        wgpu_tex_desc.size.height = (uint32_t) img->cmn.height;\n        if (desc->type == SG_IMAGETYPE_CUBE) {\n            wgpu_tex_desc.size.depthOrArrayLayers = 6;\n        } else {\n            wgpu_tex_desc.size.depthOrArrayLayers = (uint32_t) img->cmn.num_slices;\n        }\n        wgpu_tex_desc.format = _sg_wgpu_textureformat(img->cmn.pixel_format);\n        wgpu_tex_desc.mipLevelCount = (uint32_t) img->cmn.num_mipmaps;\n        wgpu_tex_desc.sampleCount = (uint32_t) img->cmn.sample_count;\n        img->wgpu.tex = wgpuDeviceCreateTexture(_sg.wgpu.dev, &wgpu_tex_desc);\n        if (0 == img->wgpu.tex) {\n            _SG_ERROR(WGPU_CREATE_TEXTURE_FAILED);\n            return SG_RESOURCESTATE_FAILED;\n        }\n        if ((img->cmn.usage == SG_USAGE_IMMUTABLE) && !img->cmn.render_target) {\n            _sg_wgpu_copy_image_data(img, img->wgpu.tex, &desc->data);\n        }\n        WGPUTextureViewDescriptor wgpu_texview_desc;\n        _sg_clear(&wgpu_texview_desc, sizeof(wgpu_texview_desc));\n        wgpu_texview_desc.label = desc->label;\n        wgpu_texview_desc.dimension = _sg_wgpu_texture_view_dimension(img->cmn.type);\n        wgpu_texview_desc.mipLevelCount = (uint32_t)img->cmn.num_mipmaps;\n        if (img->cmn.type == SG_IMAGETYPE_CUBE) {\n            wgpu_texview_desc.arrayLayerCount = 6;\n        } else if (img->cmn.type == SG_IMAGETYPE_ARRAY) {\n            wgpu_texview_desc.arrayLayerCount = (uint32_t)img->cmn.num_slices;\n        } else {\n            wgpu_texview_desc.arrayLayerCount = 1;\n        }\n        if (_sg_is_depth_or_depth_stencil_format(img->cmn.pixel_format)) {\n            wgpu_texview_desc.aspect = WGPUTextureAspect_DepthOnly;\n        } else {\n            wgpu_texview_desc.aspect = WGPUTextureAspect_All;\n        }\n        img->wgpu.view = wgpuTextureCreateView(img->wgpu.tex, &wgpu_texview_desc);\n        if (0 == img->wgpu.view) {\n            _SG_ERROR(WGPU_CREATE_TEXTURE_VIEW_FAILED);\n            return SG_RESOURCESTATE_FAILED;\n        }\n    }\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_discard_image(_sg_image_t* img) {\n    SOKOL_ASSERT(img);\n    if (img->wgpu.view) {\n        wgpuTextureViewRelease(img->wgpu.view);\n        img->wgpu.view = 0;\n    }\n    if (img->wgpu.tex) {\n        wgpuTextureDestroy(img->wgpu.tex);\n        wgpuTextureRelease(img->wgpu.tex);\n        img->wgpu.tex = 0;\n    }\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_sampler(_sg_sampler_t* smp, const sg_sampler_desc* desc) {\n    SOKOL_ASSERT(smp && desc);\n    SOKOL_ASSERT(_sg.wgpu.dev);\n    const bool injected = (0 != desc->wgpu_sampler);\n    if (injected) {\n        smp->wgpu.smp = (WGPUSampler) desc->wgpu_sampler;\n        wgpuSamplerReference(smp->wgpu.smp);\n    } else {\n        WGPUSamplerDescriptor wgpu_desc;\n        _sg_clear(&wgpu_desc, sizeof(wgpu_desc));\n        wgpu_desc.label = desc->label;\n        wgpu_desc.addressModeU = _sg_wgpu_sampler_address_mode(desc->wrap_u);\n        wgpu_desc.addressModeV = _sg_wgpu_sampler_address_mode(desc->wrap_v);\n        wgpu_desc.addressModeW = _sg_wgpu_sampler_address_mode(desc->wrap_w);\n        wgpu_desc.magFilter = _sg_wgpu_sampler_minmag_filter(desc->mag_filter);\n        wgpu_desc.minFilter = _sg_wgpu_sampler_minmag_filter(desc->min_filter);\n        wgpu_desc.mipmapFilter = _sg_wgpu_sampler_mipmap_filter(desc->mipmap_filter);\n        wgpu_desc.lodMinClamp = desc->min_lod;\n        wgpu_desc.lodMaxClamp = desc->max_lod;\n        wgpu_desc.compare = _sg_wgpu_comparefunc(desc->compare);\n        if (wgpu_desc.compare == WGPUCompareFunction_Never) {\n            wgpu_desc.compare = WGPUCompareFunction_Undefined;\n        }\n        wgpu_desc.maxAnisotropy = (uint16_t)desc->max_anisotropy;\n        smp->wgpu.smp = wgpuDeviceCreateSampler(_sg.wgpu.dev, &wgpu_desc);\n        if (0 == smp->wgpu.smp) {\n            _SG_ERROR(WGPU_CREATE_SAMPLER_FAILED);\n            return SG_RESOURCESTATE_FAILED;\n        }\n    }\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_discard_sampler(_sg_sampler_t* smp) {\n    SOKOL_ASSERT(smp);\n    if (smp->wgpu.smp) {\n        wgpuSamplerRelease(smp->wgpu.smp);\n        smp->wgpu.smp = 0;\n    }\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_shader(_sg_shader_t* shd, const sg_shader_desc* desc) {\n    SOKOL_ASSERT(shd && desc);\n    SOKOL_ASSERT(desc->vs.source && desc->fs.source);\n\n    WGPUBindGroupLayoutEntry wgpu_bgl_entries[_SG_WGPU_MAX_BINDGROUP_ENTRIES];\n    _sg_clear(wgpu_bgl_entries, sizeof(wgpu_bgl_entries));\n    int bgl_index = 0;\n    for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {\n        const sg_shader_stage_desc* stage_desc = (stage_index == SG_SHADERSTAGE_VS) ? &desc->vs : &desc->fs;\n\n        _sg_shader_stage_t* cmn_stage = &shd->cmn.stage[stage_index];\n        _sg_wgpu_shader_stage_t* wgpu_stage = &shd->wgpu.stage[stage_index];\n        _sg_strcpy(&wgpu_stage->entry, stage_desc->entry);\n\n        WGPUShaderModuleWGSLDescriptor wgpu_shdmod_wgsl_desc;\n        _sg_clear(&wgpu_shdmod_wgsl_desc, sizeof(wgpu_shdmod_wgsl_desc));\n        wgpu_shdmod_wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;\n        wgpu_shdmod_wgsl_desc.code = stage_desc->source;\n\n        WGPUShaderModuleDescriptor wgpu_shdmod_desc;\n        _sg_clear(&wgpu_shdmod_desc, sizeof(wgpu_shdmod_desc));\n        wgpu_shdmod_desc.nextInChain = &wgpu_shdmod_wgsl_desc.chain;\n        wgpu_shdmod_desc.label = desc->label;\n\n        wgpu_stage->module = wgpuDeviceCreateShaderModule(_sg.wgpu.dev, &wgpu_shdmod_desc);\n        if (0 == wgpu_stage->module) {\n            _SG_ERROR(WGPU_CREATE_SHADER_MODULE_FAILED);\n            return SG_RESOURCESTATE_FAILED;\n        }\n\n        const int num_images = cmn_stage->num_images;\n        if (num_images > (int)_sg.wgpu.limits.limits.maxSampledTexturesPerShaderStage) {\n            _SG_ERROR(WGPU_SHADER_TOO_MANY_IMAGES);\n            return SG_RESOURCESTATE_FAILED;\n        }\n        const int num_samplers = cmn_stage->num_samplers;\n        if (num_samplers > (int)_sg.wgpu.limits.limits.maxSamplersPerShaderStage) {\n            _SG_ERROR(WGPU_SHADER_TOO_MANY_SAMPLERS);\n            return SG_RESOURCESTATE_FAILED;\n        }\n        const int num_sbufs = cmn_stage->num_storage_buffers;\n        if  (num_sbufs > (int)_sg.wgpu.limits.limits.maxStorageBuffersPerShaderStage) {\n            _SG_ERROR(WGPU_SHADER_TOO_MANY_STORAGEBUFFERS);\n            return SG_RESOURCESTATE_FAILED;\n        }\n        for (int img_index = 0; img_index < num_images; img_index++) {\n            SOKOL_ASSERT(bgl_index < _SG_WGPU_MAX_BINDGROUP_ENTRIES);\n            WGPUBindGroupLayoutEntry* wgpu_bgl_entry = &wgpu_bgl_entries[bgl_index++];\n            const sg_shader_image_desc* img_desc = &stage_desc->images[img_index];\n            wgpu_bgl_entry->binding = _sg_wgpu_image_binding((sg_shader_stage)stage_index, img_index);\n            wgpu_bgl_entry->visibility = _sg_wgpu_shader_stage((sg_shader_stage)stage_index);\n            wgpu_bgl_entry->texture.viewDimension = _sg_wgpu_texture_view_dimension(img_desc->image_type);\n            wgpu_bgl_entry->texture.sampleType = _sg_wgpu_texture_sample_type(img_desc->sample_type);\n            wgpu_bgl_entry->texture.multisampled = img_desc->multisampled;\n        }\n        for (int smp_index = 0; smp_index < num_samplers; smp_index++) {\n            SOKOL_ASSERT(bgl_index < _SG_WGPU_MAX_BINDGROUP_ENTRIES);\n            WGPUBindGroupLayoutEntry* wgpu_bgl_entry = &wgpu_bgl_entries[bgl_index++];\n            const sg_shader_sampler_desc* smp_desc = &stage_desc->samplers[smp_index];\n            wgpu_bgl_entry->binding = _sg_wgpu_sampler_binding((sg_shader_stage)stage_index, smp_index);\n            wgpu_bgl_entry->visibility = _sg_wgpu_shader_stage((sg_shader_stage)stage_index);\n            wgpu_bgl_entry->sampler.type = _sg_wgpu_sampler_binding_type(smp_desc->sampler_type);\n        }\n        for (int sbuf_index = 0; sbuf_index < num_sbufs; sbuf_index++) {\n            SOKOL_ASSERT(bgl_index < _SG_WGPU_MAX_BINDGROUP_ENTRIES);\n            WGPUBindGroupLayoutEntry* wgpu_bgl_entry = &wgpu_bgl_entries[bgl_index++];\n            const sg_shader_storage_buffer_desc* sbuf_desc = &stage_desc->storage_buffers[sbuf_index];\n            wgpu_bgl_entry->binding = _sg_wgpu_storagebuffer_binding((sg_shader_stage)stage_index, sbuf_index);\n            wgpu_bgl_entry->visibility = _sg_wgpu_shader_stage((sg_shader_stage)stage_index);\n            wgpu_bgl_entry->buffer.type = sbuf_desc->readonly ? WGPUBufferBindingType_ReadOnlyStorage : WGPUBufferBindingType_Storage;\n        }\n    }\n\n    WGPUBindGroupLayoutDescriptor wgpu_bgl_desc;\n    _sg_clear(&wgpu_bgl_desc, sizeof(wgpu_bgl_desc));\n    wgpu_bgl_desc.entryCount = (size_t)bgl_index;\n    wgpu_bgl_desc.entries = &wgpu_bgl_entries[0];\n    shd->wgpu.bind_group_layout = wgpuDeviceCreateBindGroupLayout(_sg.wgpu.dev, &wgpu_bgl_desc);\n    if (shd->wgpu.bind_group_layout == 0) {\n        _SG_ERROR(WGPU_SHADER_CREATE_BINDGROUP_LAYOUT_FAILED);\n        return SG_RESOURCESTATE_FAILED;\n    }\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_discard_shader(_sg_shader_t* shd) {\n    SOKOL_ASSERT(shd);\n    if (shd->wgpu.bind_group_layout) {\n        wgpuBindGroupLayoutRelease(shd->wgpu.bind_group_layout);\n        shd->wgpu.bind_group_layout = 0;\n    }\n    for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {\n        _sg_wgpu_shader_stage_t* wgpu_stage = &shd->wgpu.stage[stage_index];\n        if (wgpu_stage->module) {\n            wgpuShaderModuleRelease(wgpu_stage->module);\n            wgpu_stage->module = 0;\n        }\n    }\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) {\n    SOKOL_ASSERT(pip && shd && desc);\n    SOKOL_ASSERT(desc->shader.id == shd->slot.id);\n    SOKOL_ASSERT(shd->wgpu.bind_group_layout);\n    pip->shader = shd;\n\n    pip->wgpu.blend_color.r = (double) desc->blend_color.r;\n    pip->wgpu.blend_color.g = (double) desc->blend_color.g;\n    pip->wgpu.blend_color.b = (double) desc->blend_color.b;\n    pip->wgpu.blend_color.a = (double) desc->blend_color.a;\n\n    // - @group(0) for uniform blocks\n    // - @group(1) for all image and sampler resources\n    WGPUBindGroupLayout wgpu_bgl[_SG_WGPU_NUM_BINDGROUPS];\n    _sg_clear(&wgpu_bgl, sizeof(wgpu_bgl));\n    wgpu_bgl[_SG_WGPU_UNIFORM_BINDGROUP_INDEX] = _sg.wgpu.uniform.bind.group_layout;\n    wgpu_bgl[_SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX] = shd->wgpu.bind_group_layout;\n    WGPUPipelineLayoutDescriptor wgpu_pl_desc;\n    _sg_clear(&wgpu_pl_desc, sizeof(wgpu_pl_desc));\n    wgpu_pl_desc.bindGroupLayoutCount = _SG_WGPU_NUM_BINDGROUPS;\n    wgpu_pl_desc.bindGroupLayouts = &wgpu_bgl[0];\n    const WGPUPipelineLayout wgpu_pip_layout = wgpuDeviceCreatePipelineLayout(_sg.wgpu.dev, &wgpu_pl_desc);\n    if (0 == wgpu_pip_layout) {\n        _SG_ERROR(WGPU_CREATE_PIPELINE_LAYOUT_FAILED);\n        return SG_RESOURCESTATE_FAILED;\n    }\n    SOKOL_ASSERT(wgpu_pip_layout);\n\n    WGPUVertexBufferLayout wgpu_vb_layouts[SG_MAX_VERTEX_BUFFERS];\n    _sg_clear(wgpu_vb_layouts, sizeof(wgpu_vb_layouts));\n    WGPUVertexAttribute wgpu_vtx_attrs[SG_MAX_VERTEX_BUFFERS][SG_MAX_VERTEX_ATTRIBUTES];\n    _sg_clear(wgpu_vtx_attrs, sizeof(wgpu_vtx_attrs));\n    int wgpu_vb_num = 0;\n    for (int vb_idx = 0; vb_idx < SG_MAX_VERTEX_BUFFERS; vb_idx++, wgpu_vb_num++) {\n        const sg_vertex_buffer_layout_state* vbl_state = &desc->layout.buffers[vb_idx];\n        if (0 == vbl_state->stride) {\n            break;\n        }\n        wgpu_vb_layouts[vb_idx].arrayStride = (uint64_t)vbl_state->stride;\n        wgpu_vb_layouts[vb_idx].stepMode = _sg_wgpu_stepmode(vbl_state->step_func);\n        wgpu_vb_layouts[vb_idx].attributes = &wgpu_vtx_attrs[vb_idx][0];\n    }\n    for (int va_idx = 0; va_idx < SG_MAX_VERTEX_ATTRIBUTES; va_idx++) {\n        const sg_vertex_attr_state* va_state = &desc->layout.attrs[va_idx];\n        if (SG_VERTEXFORMAT_INVALID == va_state->format) {\n            break;\n        }\n        const int vb_idx = va_state->buffer_index;\n        SOKOL_ASSERT(vb_idx < SG_MAX_VERTEX_BUFFERS);\n        pip->cmn.vertex_buffer_layout_active[vb_idx] = true;\n        const size_t wgpu_attr_idx = wgpu_vb_layouts[vb_idx].attributeCount;\n        wgpu_vb_layouts[vb_idx].attributeCount += 1;\n        wgpu_vtx_attrs[vb_idx][wgpu_attr_idx].format = _sg_wgpu_vertexformat(va_state->format);\n        wgpu_vtx_attrs[vb_idx][wgpu_attr_idx].offset = (uint64_t)va_state->offset;\n        wgpu_vtx_attrs[vb_idx][wgpu_attr_idx].shaderLocation = (uint32_t)va_idx;\n    }\n\n    WGPURenderPipelineDescriptor wgpu_pip_desc;\n    _sg_clear(&wgpu_pip_desc, sizeof(wgpu_pip_desc));\n    WGPUDepthStencilState wgpu_ds_state;\n    _sg_clear(&wgpu_ds_state, sizeof(wgpu_ds_state));\n    WGPUFragmentState wgpu_frag_state;\n    _sg_clear(&wgpu_frag_state, sizeof(wgpu_frag_state));\n    WGPUColorTargetState wgpu_ctgt_state[SG_MAX_COLOR_ATTACHMENTS];\n    _sg_clear(&wgpu_ctgt_state, sizeof(wgpu_ctgt_state));\n    WGPUBlendState wgpu_blend_state[SG_MAX_COLOR_ATTACHMENTS];\n    _sg_clear(&wgpu_blend_state, sizeof(wgpu_blend_state));\n    wgpu_pip_desc.label = desc->label;\n    wgpu_pip_desc.layout = wgpu_pip_layout;\n    wgpu_pip_desc.vertex.module = shd->wgpu.stage[SG_SHADERSTAGE_VS].module;\n    wgpu_pip_desc.vertex.entryPoint = shd->wgpu.stage[SG_SHADERSTAGE_VS].entry.buf;\n    wgpu_pip_desc.vertex.bufferCount = (size_t)wgpu_vb_num;\n    wgpu_pip_desc.vertex.buffers = &wgpu_vb_layouts[0];\n    wgpu_pip_desc.primitive.topology = _sg_wgpu_topology(desc->primitive_type);\n    wgpu_pip_desc.primitive.stripIndexFormat = _sg_wgpu_stripindexformat(desc->primitive_type, desc->index_type);\n    wgpu_pip_desc.primitive.frontFace = _sg_wgpu_frontface(desc->face_winding);\n    wgpu_pip_desc.primitive.cullMode = _sg_wgpu_cullmode(desc->cull_mode);\n    if (SG_PIXELFORMAT_NONE != desc->depth.pixel_format) {\n        wgpu_ds_state.format = _sg_wgpu_textureformat(desc->depth.pixel_format);\n        wgpu_ds_state.depthWriteEnabled = desc->depth.write_enabled;\n        wgpu_ds_state.depthCompare = _sg_wgpu_comparefunc(desc->depth.compare);\n        wgpu_ds_state.stencilFront.compare = _sg_wgpu_comparefunc(desc->stencil.front.compare);\n        wgpu_ds_state.stencilFront.failOp = _sg_wgpu_stencilop(desc->stencil.front.fail_op);\n        wgpu_ds_state.stencilFront.depthFailOp = _sg_wgpu_stencilop(desc->stencil.front.depth_fail_op);\n        wgpu_ds_state.stencilFront.passOp = _sg_wgpu_stencilop(desc->stencil.front.pass_op);\n        wgpu_ds_state.stencilBack.compare = _sg_wgpu_comparefunc(desc->stencil.back.compare);\n        wgpu_ds_state.stencilBack.failOp = _sg_wgpu_stencilop(desc->stencil.back.fail_op);\n        wgpu_ds_state.stencilBack.depthFailOp = _sg_wgpu_stencilop(desc->stencil.back.depth_fail_op);\n        wgpu_ds_state.stencilBack.passOp = _sg_wgpu_stencilop(desc->stencil.back.pass_op);\n        wgpu_ds_state.stencilReadMask = desc->stencil.read_mask;\n        wgpu_ds_state.stencilWriteMask = desc->stencil.write_mask;\n        wgpu_ds_state.depthBias = (int32_t)desc->depth.bias;\n        wgpu_ds_state.depthBiasSlopeScale = desc->depth.bias_slope_scale;\n        wgpu_ds_state.depthBiasClamp = desc->depth.bias_clamp;\n        wgpu_pip_desc.depthStencil = &wgpu_ds_state;\n    }\n    wgpu_pip_desc.multisample.count = (uint32_t)desc->sample_count;\n    wgpu_pip_desc.multisample.mask = 0xFFFFFFFF;\n    wgpu_pip_desc.multisample.alphaToCoverageEnabled = desc->alpha_to_coverage_enabled;\n    if (desc->color_count > 0) {\n        wgpu_frag_state.module = shd->wgpu.stage[SG_SHADERSTAGE_FS].module;\n        wgpu_frag_state.entryPoint = shd->wgpu.stage[SG_SHADERSTAGE_FS].entry.buf;\n        wgpu_frag_state.targetCount = (size_t)desc->color_count;\n        wgpu_frag_state.targets = &wgpu_ctgt_state[0];\n        for (int i = 0; i < desc->color_count; i++) {\n            SOKOL_ASSERT(i < SG_MAX_COLOR_ATTACHMENTS);\n            wgpu_ctgt_state[i].format = _sg_wgpu_textureformat(desc->colors[i].pixel_format);\n            wgpu_ctgt_state[i].writeMask = _sg_wgpu_colorwritemask(desc->colors[i].write_mask);\n            if (desc->colors[i].blend.enabled) {\n                wgpu_ctgt_state[i].blend = &wgpu_blend_state[i];\n                wgpu_blend_state[i].color.operation = _sg_wgpu_blendop(desc->colors[i].blend.op_rgb);\n                wgpu_blend_state[i].color.srcFactor = _sg_wgpu_blendfactor(desc->colors[i].blend.src_factor_rgb);\n                wgpu_blend_state[i].color.dstFactor = _sg_wgpu_blendfactor(desc->colors[i].blend.dst_factor_rgb);\n                wgpu_blend_state[i].alpha.operation = _sg_wgpu_blendop(desc->colors[i].blend.op_alpha);\n                wgpu_blend_state[i].alpha.srcFactor = _sg_wgpu_blendfactor(desc->colors[i].blend.src_factor_alpha);\n                wgpu_blend_state[i].alpha.dstFactor = _sg_wgpu_blendfactor(desc->colors[i].blend.dst_factor_alpha);\n            }\n        }\n        wgpu_pip_desc.fragment = &wgpu_frag_state;\n    }\n    pip->wgpu.pip = wgpuDeviceCreateRenderPipeline(_sg.wgpu.dev, &wgpu_pip_desc);\n    wgpuPipelineLayoutRelease(wgpu_pip_layout);\n    if (0 == pip->wgpu.pip) {\n        _SG_ERROR(WGPU_CREATE_RENDER_PIPELINE_FAILED);\n        return SG_RESOURCESTATE_FAILED;\n    }\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_discard_pipeline(_sg_pipeline_t* pip) {\n    SOKOL_ASSERT(pip);\n    if (pip == _sg.wgpu.cur_pipeline) {\n        _sg.wgpu.cur_pipeline = 0;\n        _sg.wgpu.cur_pipeline_id.id = SG_INVALID_ID;\n    }\n    if (pip->wgpu.pip) {\n        wgpuRenderPipelineRelease(pip->wgpu.pip);\n        pip->wgpu.pip = 0;\n    }\n}\n\n_SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_attachments(_sg_attachments_t* atts, _sg_image_t** color_images, _sg_image_t** resolve_images, _sg_image_t* ds_img, const sg_attachments_desc* desc) {\n    SOKOL_ASSERT(atts && desc);\n    SOKOL_ASSERT(color_images && resolve_images);\n\n    // copy image pointers and create renderable wgpu texture views\n    for (int i = 0; i < atts->cmn.num_colors; i++) {\n        const sg_attachment_desc* color_desc = &desc->colors[i];\n        _SOKOL_UNUSED(color_desc);\n        SOKOL_ASSERT(color_desc->image.id != SG_INVALID_ID);\n        SOKOL_ASSERT(0 == atts->wgpu.colors[i].image);\n        SOKOL_ASSERT(color_images[i] && (color_images[i]->slot.id == color_desc->image.id));\n        SOKOL_ASSERT(_sg_is_valid_rendertarget_color_format(color_images[i]->cmn.pixel_format));\n        SOKOL_ASSERT(color_images[i]->wgpu.tex);\n        atts->wgpu.colors[i].image = color_images[i];\n\n        WGPUTextureViewDescriptor wgpu_color_view_desc;\n        _sg_clear(&wgpu_color_view_desc, sizeof(wgpu_color_view_desc));\n        wgpu_color_view_desc.baseMipLevel = (uint32_t) color_desc->mip_level;\n        wgpu_color_view_desc.mipLevelCount = 1;\n        wgpu_color_view_desc.baseArrayLayer = (uint32_t) color_desc->slice;\n        wgpu_color_view_desc.arrayLayerCount = 1;\n        atts->wgpu.colors[i].view = wgpuTextureCreateView(color_images[i]->wgpu.tex, &wgpu_color_view_desc);\n        if (0 == atts->wgpu.colors[i].view) {\n            _SG_ERROR(WGPU_ATTACHMENTS_CREATE_TEXTURE_VIEW_FAILED);\n            return SG_RESOURCESTATE_FAILED;\n        }\n\n        const sg_attachment_desc* resolve_desc = &desc->resolves[i];\n        if (resolve_desc->image.id != SG_INVALID_ID) {\n            SOKOL_ASSERT(0 == atts->wgpu.resolves[i].image);\n            SOKOL_ASSERT(resolve_images[i] && (resolve_images[i]->slot.id == resolve_desc->image.id));\n            SOKOL_ASSERT(color_images[i] && (color_images[i]->cmn.pixel_format == resolve_images[i]->cmn.pixel_format));\n            SOKOL_ASSERT(resolve_images[i]->wgpu.tex);\n            atts->wgpu.resolves[i].image = resolve_images[i];\n\n            WGPUTextureViewDescriptor wgpu_resolve_view_desc;\n            _sg_clear(&wgpu_resolve_view_desc, sizeof(wgpu_resolve_view_desc));\n            wgpu_resolve_view_desc.baseMipLevel = (uint32_t) resolve_desc->mip_level;\n            wgpu_resolve_view_desc.mipLevelCount = 1;\n            wgpu_resolve_view_desc.baseArrayLayer = (uint32_t) resolve_desc->slice;\n            wgpu_resolve_view_desc.arrayLayerCount = 1;\n            atts->wgpu.resolves[i].view = wgpuTextureCreateView(resolve_images[i]->wgpu.tex, &wgpu_resolve_view_desc);\n            if (0 == atts->wgpu.resolves[i].view) {\n                _SG_ERROR(WGPU_ATTACHMENTS_CREATE_TEXTURE_VIEW_FAILED);\n                return SG_RESOURCESTATE_FAILED;\n            }\n        }\n    }\n    SOKOL_ASSERT(0 == atts->wgpu.depth_stencil.image);\n    const sg_attachment_desc* ds_desc = &desc->depth_stencil;\n    if (ds_desc->image.id != SG_INVALID_ID) {\n        SOKOL_ASSERT(ds_img && (ds_img->slot.id == ds_desc->image.id));\n        SOKOL_ASSERT(_sg_is_valid_rendertarget_depth_format(ds_img->cmn.pixel_format));\n        SOKOL_ASSERT(ds_img->wgpu.tex);\n        atts->wgpu.depth_stencil.image = ds_img;\n\n        WGPUTextureViewDescriptor wgpu_ds_view_desc;\n        _sg_clear(&wgpu_ds_view_desc, sizeof(wgpu_ds_view_desc));\n        wgpu_ds_view_desc.baseMipLevel = (uint32_t) ds_desc->mip_level;\n        wgpu_ds_view_desc.mipLevelCount = 1;\n        wgpu_ds_view_desc.baseArrayLayer = (uint32_t) ds_desc->slice;\n        wgpu_ds_view_desc.arrayLayerCount = 1;\n        atts->wgpu.depth_stencil.view = wgpuTextureCreateView(ds_img->wgpu.tex, &wgpu_ds_view_desc);\n        if (0 == atts->wgpu.depth_stencil.view) {\n            _SG_ERROR(WGPU_ATTACHMENTS_CREATE_TEXTURE_VIEW_FAILED);\n            return SG_RESOURCESTATE_FAILED;\n        }\n    }\n    return SG_RESOURCESTATE_VALID;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_discard_attachments(_sg_attachments_t* atts) {\n    SOKOL_ASSERT(atts);\n    for (int i = 0; i < atts->cmn.num_colors; i++) {\n        if (atts->wgpu.colors[i].view) {\n            wgpuTextureViewRelease(atts->wgpu.colors[i].view);\n            atts->wgpu.colors[i].view = 0;\n        }\n        if (atts->wgpu.resolves[i].view) {\n            wgpuTextureViewRelease(atts->wgpu.resolves[i].view);\n            atts->wgpu.resolves[i].view = 0;\n        }\n    }\n    if (atts->wgpu.depth_stencil.view) {\n        wgpuTextureViewRelease(atts->wgpu.depth_stencil.view);\n        atts->wgpu.depth_stencil.view = 0;\n    }\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_wgpu_attachments_color_image(const _sg_attachments_t* atts, int index) {\n    SOKOL_ASSERT(atts && (index >= 0) && (index < SG_MAX_COLOR_ATTACHMENTS));\n    // NOTE: may return null\n    return atts->wgpu.colors[index].image;\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_wgpu_attachments_resolve_image(const _sg_attachments_t* atts, int index) {\n    SOKOL_ASSERT(atts && (index >= 0) && (index < SG_MAX_COLOR_ATTACHMENTS));\n    // NOTE: may return null\n    return atts->wgpu.resolves[index].image;\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_wgpu_attachments_ds_image(const _sg_attachments_t* atts) {\n    // NOTE: may return null\n    SOKOL_ASSERT(atts);\n    return atts->wgpu.depth_stencil.image;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_init_color_att(WGPURenderPassColorAttachment* wgpu_att, const sg_color_attachment_action* action, WGPUTextureView color_view, WGPUTextureView resolve_view) {\n    wgpu_att->depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;\n    wgpu_att->view = color_view;\n    wgpu_att->resolveTarget = resolve_view;\n    wgpu_att->loadOp = _sg_wgpu_load_op(color_view, action->load_action);\n    wgpu_att->storeOp = _sg_wgpu_store_op(color_view, action->store_action);\n    wgpu_att->clearValue.r = action->clear_value.r;\n    wgpu_att->clearValue.g = action->clear_value.g;\n    wgpu_att->clearValue.b = action->clear_value.b;\n    wgpu_att->clearValue.a = action->clear_value.a;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_init_ds_att(WGPURenderPassDepthStencilAttachment* wgpu_att, const sg_pass_action* action, sg_pixel_format fmt, WGPUTextureView view) {\n    wgpu_att->view = view;\n    wgpu_att->depthLoadOp = _sg_wgpu_load_op(view, action->depth.load_action);\n    wgpu_att->depthStoreOp = _sg_wgpu_store_op(view, action->depth.store_action);\n    wgpu_att->depthClearValue = action->depth.clear_value;\n    wgpu_att->depthReadOnly = false;\n    if (_sg_is_depth_stencil_format(fmt)) {\n        wgpu_att->stencilLoadOp = _sg_wgpu_load_op(view, action->stencil.load_action);\n        wgpu_att->stencilStoreOp = _sg_wgpu_store_op(view, action->stencil.store_action);\n    } else {\n        wgpu_att->stencilLoadOp = WGPULoadOp_Undefined;\n        wgpu_att->stencilStoreOp = WGPUStoreOp_Undefined;\n    }\n    wgpu_att->stencilClearValue = action->stencil.clear_value;\n    wgpu_att->stencilReadOnly = false;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_begin_pass(const sg_pass* pass) {\n    SOKOL_ASSERT(pass);\n    SOKOL_ASSERT(_sg.wgpu.cmd_enc);\n    SOKOL_ASSERT(_sg.wgpu.dev);\n\n    const _sg_attachments_t* atts = _sg.cur_pass.atts;\n    const sg_swapchain* swapchain = &pass->swapchain;\n    const sg_pass_action* action = &pass->action;\n\n    _sg.wgpu.cur_pipeline = 0;\n    _sg.wgpu.cur_pipeline_id.id = SG_INVALID_ID;\n\n    WGPURenderPassDescriptor wgpu_pass_desc;\n    WGPURenderPassColorAttachment wgpu_color_att[SG_MAX_COLOR_ATTACHMENTS];\n    WGPURenderPassDepthStencilAttachment wgpu_ds_att;\n    _sg_clear(&wgpu_pass_desc, sizeof(wgpu_pass_desc));\n    _sg_clear(&wgpu_color_att, sizeof(wgpu_color_att));\n    _sg_clear(&wgpu_ds_att, sizeof(wgpu_ds_att));\n    wgpu_pass_desc.label = pass->label;\n    if (atts) {\n        SOKOL_ASSERT(atts->slot.state == SG_RESOURCESTATE_VALID);\n        for (int i = 0; i < atts->cmn.num_colors; i++) {\n            _sg_wgpu_init_color_att(&wgpu_color_att[i], &action->colors[i], atts->wgpu.colors[i].view, atts->wgpu.resolves[i].view);\n        }\n        wgpu_pass_desc.colorAttachmentCount = (size_t)atts->cmn.num_colors;\n        wgpu_pass_desc.colorAttachments = &wgpu_color_att[0];\n        if (atts->wgpu.depth_stencil.image) {\n            _sg_wgpu_init_ds_att(&wgpu_ds_att, action, atts->wgpu.depth_stencil.image->cmn.pixel_format, atts->wgpu.depth_stencil.view);\n            wgpu_pass_desc.depthStencilAttachment = &wgpu_ds_att;\n        }\n    } else {\n        WGPUTextureView wgpu_color_view = (WGPUTextureView) swapchain->wgpu.render_view;\n        WGPUTextureView wgpu_resolve_view = (WGPUTextureView) swapchain->wgpu.resolve_view;\n        WGPUTextureView wgpu_depth_stencil_view = (WGPUTextureView) swapchain->wgpu.depth_stencil_view;\n        _sg_wgpu_init_color_att(&wgpu_color_att[0], &action->colors[0], wgpu_color_view, wgpu_resolve_view);\n        wgpu_pass_desc.colorAttachmentCount = 1;\n        wgpu_pass_desc.colorAttachments = &wgpu_color_att[0];\n        if (wgpu_depth_stencil_view) {\n            SOKOL_ASSERT(swapchain->depth_format > SG_PIXELFORMAT_NONE);\n            _sg_wgpu_init_ds_att(&wgpu_ds_att, action, swapchain->depth_format, wgpu_depth_stencil_view);\n            wgpu_pass_desc.depthStencilAttachment = &wgpu_ds_att;\n        }\n    }\n    _sg.wgpu.pass_enc = wgpuCommandEncoderBeginRenderPass(_sg.wgpu.cmd_enc, &wgpu_pass_desc);\n    SOKOL_ASSERT(_sg.wgpu.pass_enc);\n\n    // clear bindings cache and apply an empty image-sampler bindgroup\n    _sg_wgpu_bindings_cache_clear();\n    wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, _sg.wgpu.empty_bind_group, 0, 0);\n    _sg_stats_add(wgpu.bindings.num_set_bindgroup, 1);\n\n    // initial uniform buffer binding (required even if no uniforms are set in the frame)\n    _sg_wgpu_uniform_buffer_on_begin_pass();\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_end_pass(void) {\n    if (_sg.wgpu.pass_enc) {\n        wgpuRenderPassEncoderEnd(_sg.wgpu.pass_enc);\n        wgpuRenderPassEncoderRelease(_sg.wgpu.pass_enc);\n        _sg.wgpu.pass_enc = 0;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_commit(void) {\n    SOKOL_ASSERT(_sg.wgpu.cmd_enc);\n\n    _sg_wgpu_uniform_buffer_on_commit();\n\n    WGPUCommandBufferDescriptor cmd_buf_desc;\n    _sg_clear(&cmd_buf_desc, sizeof(cmd_buf_desc));\n    WGPUCommandBuffer wgpu_cmd_buf = wgpuCommandEncoderFinish(_sg.wgpu.cmd_enc, &cmd_buf_desc);\n    SOKOL_ASSERT(wgpu_cmd_buf);\n    wgpuCommandEncoderRelease(_sg.wgpu.cmd_enc);\n    _sg.wgpu.cmd_enc = 0;\n\n    wgpuQueueSubmit(_sg.wgpu.queue, 1, &wgpu_cmd_buf);\n    wgpuCommandBufferRelease(wgpu_cmd_buf);\n\n    // create a new render-command-encoder for next frame\n    WGPUCommandEncoderDescriptor cmd_enc_desc;\n    _sg_clear(&cmd_enc_desc, sizeof(cmd_enc_desc));\n    _sg.wgpu.cmd_enc = wgpuDeviceCreateCommandEncoder(_sg.wgpu.dev, &cmd_enc_desc);\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_apply_viewport(int x, int y, int w, int h, bool origin_top_left) {\n    SOKOL_ASSERT(_sg.wgpu.pass_enc);\n    // FIXME FIXME FIXME: CLIPPING THE VIEWPORT HERE IS WRONG!!!\n    // (but currently required because WebGPU insists that the viewport rectangle must be\n    // fully contained inside the framebuffer, but this doesn't make any sense, and also\n    // isn't required by the backend APIs)\n    const _sg_recti_t clip = _sg_clipi(x, y, w, h, _sg.cur_pass.width, _sg.cur_pass.height);\n    float xf = (float) clip.x;\n    float yf = (float) (origin_top_left ? clip.y : (_sg.cur_pass.height - (clip.y + clip.h)));\n    float wf = (float) clip.w;\n    float hf = (float) clip.h;\n    wgpuRenderPassEncoderSetViewport(_sg.wgpu.pass_enc, xf, yf, wf, hf, 0.0f, 1.0f);\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_apply_scissor_rect(int x, int y, int w, int h, bool origin_top_left) {\n    SOKOL_ASSERT(_sg.wgpu.pass_enc);\n    const _sg_recti_t clip = _sg_clipi(x, y, w, h, _sg.cur_pass.width, _sg.cur_pass.height);\n    uint32_t sx = (uint32_t) clip.x;\n    uint32_t sy = (uint32_t) (origin_top_left ? clip.y : (_sg.cur_pass.height - (clip.y + clip.h)));\n    uint32_t sw = (uint32_t) clip.w;\n    uint32_t sh = (uint32_t) clip.h;\n    wgpuRenderPassEncoderSetScissorRect(_sg.wgpu.pass_enc, sx, sy, sw, sh);\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_apply_pipeline(_sg_pipeline_t* pip) {\n    SOKOL_ASSERT(pip);\n    SOKOL_ASSERT(pip->wgpu.pip);\n    SOKOL_ASSERT(_sg.wgpu.pass_enc);\n    _sg.wgpu.use_indexed_draw = (pip->cmn.index_type != SG_INDEXTYPE_NONE);\n    _sg.wgpu.cur_pipeline = pip;\n    _sg.wgpu.cur_pipeline_id.id = pip->slot.id;\n    wgpuRenderPassEncoderSetPipeline(_sg.wgpu.pass_enc, pip->wgpu.pip);\n    wgpuRenderPassEncoderSetBlendConstant(_sg.wgpu.pass_enc, &pip->wgpu.blend_color);\n    wgpuRenderPassEncoderSetStencilReference(_sg.wgpu.pass_enc, pip->cmn.stencil.ref);\n}\n\n_SOKOL_PRIVATE bool _sg_wgpu_apply_bindings(_sg_bindings_t* bnd) {\n    SOKOL_ASSERT(_sg.wgpu.pass_enc);\n    SOKOL_ASSERT(bnd);\n    SOKOL_ASSERT(bnd->pip->shader && (bnd->pip->cmn.shader_id.id == bnd->pip->shader->slot.id));\n    bool retval = true;\n    retval &= _sg_wgpu_apply_index_buffer(bnd);\n    retval &= _sg_wgpu_apply_vertex_buffers(bnd);\n    retval &= _sg_wgpu_apply_bindgroup(bnd);\n    return retval;\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_index, const sg_range* data) {\n    const uint32_t alignment = _sg.wgpu.limits.limits.minUniformBufferOffsetAlignment;\n    SOKOL_ASSERT(_sg.wgpu.pass_enc);\n    SOKOL_ASSERT(_sg.wgpu.uniform.staging);\n    SOKOL_ASSERT((_sg.wgpu.uniform.offset + data->size) <= _sg.wgpu.uniform.num_bytes);\n    SOKOL_ASSERT((_sg.wgpu.uniform.offset & (alignment - 1)) == 0);\n    SOKOL_ASSERT(_sg.wgpu.cur_pipeline && _sg.wgpu.cur_pipeline->shader);\n    SOKOL_ASSERT(_sg.wgpu.cur_pipeline->slot.id == _sg.wgpu.cur_pipeline_id.id);\n    SOKOL_ASSERT(_sg.wgpu.cur_pipeline->shader->slot.id == _sg.wgpu.cur_pipeline->cmn.shader_id.id);\n    SOKOL_ASSERT(ub_index < _sg.wgpu.cur_pipeline->shader->cmn.stage[stage_index].num_uniform_blocks);\n    SOKOL_ASSERT(data->size <= _sg.wgpu.cur_pipeline->shader->cmn.stage[stage_index].uniform_blocks[ub_index].size);\n    SOKOL_ASSERT(data->size <= _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE);\n\n    _sg_stats_add(wgpu.uniforms.num_set_bindgroup, 1);\n    memcpy(_sg.wgpu.uniform.staging + _sg.wgpu.uniform.offset, data->ptr, data->size);\n    _sg.wgpu.uniform.bind.offsets[stage_index][ub_index] = _sg.wgpu.uniform.offset;\n    _sg.wgpu.uniform.offset = _sg_roundup_u32(_sg.wgpu.uniform.offset + (uint32_t)data->size, alignment);\n    wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc,\n                                      _SG_WGPU_UNIFORM_BINDGROUP_INDEX,\n                                      _sg.wgpu.uniform.bind.group,\n                                      SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS,\n                                      &_sg.wgpu.uniform.bind.offsets[0][0]);\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_draw(int base_element, int num_elements, int num_instances) {\n    SOKOL_ASSERT(_sg.wgpu.pass_enc);\n    SOKOL_ASSERT(_sg.wgpu.cur_pipeline && (_sg.wgpu.cur_pipeline->slot.id == _sg.wgpu.cur_pipeline_id.id));\n    if (SG_INDEXTYPE_NONE != _sg.wgpu.cur_pipeline->cmn.index_type) {\n        wgpuRenderPassEncoderDrawIndexed(_sg.wgpu.pass_enc, (uint32_t)num_elements, (uint32_t)num_instances, (uint32_t)base_element, 0, 0);\n    } else {\n        wgpuRenderPassEncoderDraw(_sg.wgpu.pass_enc, (uint32_t)num_elements, (uint32_t)num_instances, (uint32_t)base_element, 0);\n    }\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_update_buffer(_sg_buffer_t* buf, const sg_range* data) {\n    SOKOL_ASSERT(data && data->ptr && (data->size > 0));\n    SOKOL_ASSERT(buf);\n    _sg_wgpu_copy_buffer_data(buf, 0, data);\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) {\n    SOKOL_ASSERT(data && data->ptr && (data->size > 0));\n    _SOKOL_UNUSED(new_frame);\n    _sg_wgpu_copy_buffer_data(buf, (uint64_t)buf->cmn.append_pos, data);\n}\n\n_SOKOL_PRIVATE void _sg_wgpu_update_image(_sg_image_t* img, const sg_image_data* data) {\n    SOKOL_ASSERT(img && data);\n    _sg_wgpu_copy_image_data(img, img->wgpu.tex, data);\n}\n#endif\n\n//  ██████  ███████ ███    ██ ███████ ██████  ██  ██████     ██████   █████   ██████ ██   ██ ███████ ███    ██ ██████\n// ██       ██      ████   ██ ██      ██   ██ ██ ██          ██   ██ ██   ██ ██      ██  ██  ██      ████   ██ ██   ██\n// ██   ███ █████   ██ ██  ██ █████   ██████  ██ ██          ██████  ███████ ██      █████   █████   ██ ██  ██ ██   ██\n// ██    ██ ██      ██  ██ ██ ██      ██   ██ ██ ██          ██   ██ ██   ██ ██      ██  ██  ██      ██  ██ ██ ██   ██\n//  ██████  ███████ ██   ████ ███████ ██   ██ ██  ██████     ██████  ██   ██  ██████ ██   ██ ███████ ██   ████ ██████\n//\n// >>generic backend\nstatic inline void _sg_setup_backend(const sg_desc* desc) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_setup_backend(desc);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_setup_backend(desc);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_setup_backend(desc);\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_setup_backend(desc);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_setup_backend(desc);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_discard_backend(void) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_discard_backend();\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_discard_backend();\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_discard_backend();\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_discard_backend();\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_discard_backend();\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_reset_state_cache(void) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_reset_state_cache();\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_reset_state_cache();\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_reset_state_cache();\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_reset_state_cache();\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_reset_state_cache();\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline sg_resource_state _sg_create_buffer(_sg_buffer_t* buf, const sg_buffer_desc* desc) {\n    #if defined(_SOKOL_ANY_GL)\n    return _sg_gl_create_buffer(buf, desc);\n    #elif defined(SOKOL_METAL)\n    return _sg_mtl_create_buffer(buf, desc);\n    #elif defined(SOKOL_D3D11)\n    return _sg_d3d11_create_buffer(buf, desc);\n    #elif defined(SOKOL_WGPU)\n    return _sg_wgpu_create_buffer(buf, desc);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    return _sg_dummy_create_buffer(buf, desc);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_discard_buffer(_sg_buffer_t* buf) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_discard_buffer(buf);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_discard_buffer(buf);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_discard_buffer(buf);\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_discard_buffer(buf);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_discard_buffer(buf);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline sg_resource_state _sg_create_image(_sg_image_t* img, const sg_image_desc* desc) {\n    #if defined(_SOKOL_ANY_GL)\n    return _sg_gl_create_image(img, desc);\n    #elif defined(SOKOL_METAL)\n    return _sg_mtl_create_image(img, desc);\n    #elif defined(SOKOL_D3D11)\n    return _sg_d3d11_create_image(img, desc);\n    #elif defined(SOKOL_WGPU)\n    return _sg_wgpu_create_image(img, desc);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    return _sg_dummy_create_image(img, desc);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_discard_image(_sg_image_t* img) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_discard_image(img);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_discard_image(img);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_discard_image(img);\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_discard_image(img);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_discard_image(img);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline sg_resource_state _sg_create_sampler(_sg_sampler_t* smp, const sg_sampler_desc* desc) {\n    #if defined(_SOKOL_ANY_GL)\n    return _sg_gl_create_sampler(smp, desc);\n    #elif defined(SOKOL_METAL)\n    return _sg_mtl_create_sampler(smp, desc);\n    #elif defined(SOKOL_D3D11)\n    return _sg_d3d11_create_sampler(smp, desc);\n    #elif defined(SOKOL_WGPU)\n    return _sg_wgpu_create_sampler(smp, desc);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    return _sg_dummy_create_sampler(smp, desc);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_discard_sampler(_sg_sampler_t* smp) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_discard_sampler(smp);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_discard_sampler(smp);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_discard_sampler(smp);\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_discard_sampler(smp);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_discard_sampler(smp);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline sg_resource_state _sg_create_shader(_sg_shader_t* shd, const sg_shader_desc* desc) {\n    #if defined(_SOKOL_ANY_GL)\n    return _sg_gl_create_shader(shd, desc);\n    #elif defined(SOKOL_METAL)\n    return _sg_mtl_create_shader(shd, desc);\n    #elif defined(SOKOL_D3D11)\n    return _sg_d3d11_create_shader(shd, desc);\n    #elif defined(SOKOL_WGPU)\n    return _sg_wgpu_create_shader(shd, desc);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    return _sg_dummy_create_shader(shd, desc);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_discard_shader(_sg_shader_t* shd) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_discard_shader(shd);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_discard_shader(shd);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_discard_shader(shd);\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_discard_shader(shd);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_discard_shader(shd);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline sg_resource_state _sg_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) {\n    #if defined(_SOKOL_ANY_GL)\n    return _sg_gl_create_pipeline(pip, shd, desc);\n    #elif defined(SOKOL_METAL)\n    return _sg_mtl_create_pipeline(pip, shd, desc);\n    #elif defined(SOKOL_D3D11)\n    return _sg_d3d11_create_pipeline(pip, shd, desc);\n    #elif defined(SOKOL_WGPU)\n    return _sg_wgpu_create_pipeline(pip, shd, desc);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    return _sg_dummy_create_pipeline(pip, shd, desc);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_discard_pipeline(_sg_pipeline_t* pip) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_discard_pipeline(pip);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_discard_pipeline(pip);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_discard_pipeline(pip);\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_discard_pipeline(pip);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_discard_pipeline(pip);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline sg_resource_state _sg_create_attachments(_sg_attachments_t* atts, _sg_image_t** color_images, _sg_image_t** resolve_images, _sg_image_t* ds_image, const sg_attachments_desc* desc) {\n    #if defined(_SOKOL_ANY_GL)\n    return _sg_gl_create_attachments(atts, color_images, resolve_images, ds_image, desc);\n    #elif defined(SOKOL_METAL)\n    return _sg_mtl_create_attachments(atts, color_images, resolve_images, ds_image, desc);\n    #elif defined(SOKOL_D3D11)\n    return _sg_d3d11_create_attachments(atts, color_images, resolve_images, ds_image, desc);\n    #elif defined(SOKOL_WGPU)\n    return _sg_wgpu_create_attachments(atts, color_images, resolve_images, ds_image, desc);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    return _sg_dummy_create_attachments(atts, color_images, resolve_images, ds_image, desc);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_discard_attachments(_sg_attachments_t* atts) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_discard_attachments(atts);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_discard_attachments(atts);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_discard_attachments(atts);\n    #elif defined(SOKOL_WGPU)\n    return _sg_wgpu_discard_attachments(atts);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_discard_attachments(atts);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline _sg_image_t* _sg_attachments_color_image(const _sg_attachments_t* atts, int index) {\n    #if defined(_SOKOL_ANY_GL)\n    return _sg_gl_attachments_color_image(atts, index);\n    #elif defined(SOKOL_METAL)\n    return _sg_mtl_attachments_color_image(atts, index);\n    #elif defined(SOKOL_D3D11)\n    return _sg_d3d11_attachments_color_image(atts, index);\n    #elif defined(SOKOL_WGPU)\n    return _sg_wgpu_attachments_color_image(atts, index);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    return _sg_dummy_attachments_color_image(atts, index);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline _sg_image_t* _sg_attachments_resolve_image(const _sg_attachments_t* atts, int index) {\n    #if defined(_SOKOL_ANY_GL)\n    return _sg_gl_attachments_resolve_image(atts, index);\n    #elif defined(SOKOL_METAL)\n    return _sg_mtl_attachments_resolve_image(atts, index);\n    #elif defined(SOKOL_D3D11)\n    return _sg_d3d11_attachments_resolve_image(atts, index);\n    #elif defined(SOKOL_WGPU)\n    return _sg_wgpu_attachments_resolve_image(atts, index);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    return _sg_dummy_attachments_resolve_image(atts, index);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline _sg_image_t* _sg_attachments_ds_image(const _sg_attachments_t* atts) {\n    #if defined(_SOKOL_ANY_GL)\n    return _sg_gl_attachments_ds_image(atts);\n    #elif defined(SOKOL_METAL)\n    return _sg_mtl_attachments_ds_image(atts);\n    #elif defined(SOKOL_D3D11)\n    return _sg_d3d11_attachments_ds_image(atts);\n    #elif defined(SOKOL_WGPU)\n    return _sg_wgpu_attachments_ds_image(atts);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    return _sg_dummy_attachments_ds_image(atts);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_begin_pass(const sg_pass* pass) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_begin_pass(pass);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_begin_pass(pass);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_begin_pass(pass);\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_begin_pass(pass);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_begin_pass(pass);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_end_pass(void) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_end_pass();\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_end_pass();\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_end_pass();\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_end_pass();\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_end_pass();\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_apply_viewport(int x, int y, int w, int h, bool origin_top_left) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_apply_viewport(x, y, w, h, origin_top_left);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_apply_viewport(x, y, w, h, origin_top_left);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_apply_viewport(x, y, w, h, origin_top_left);\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_apply_viewport(x, y, w, h, origin_top_left);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_apply_viewport(x, y, w, h, origin_top_left);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_apply_scissor_rect(int x, int y, int w, int h, bool origin_top_left) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_apply_scissor_rect(x, y, w, h, origin_top_left);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_apply_scissor_rect(x, y, w, h, origin_top_left);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_apply_scissor_rect(x, y, w, h, origin_top_left);\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_apply_scissor_rect(x, y, w, h, origin_top_left);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_apply_scissor_rect(x, y, w, h, origin_top_left);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_apply_pipeline(_sg_pipeline_t* pip) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_apply_pipeline(pip);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_apply_pipeline(pip);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_apply_pipeline(pip);\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_apply_pipeline(pip);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_apply_pipeline(pip);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline bool _sg_apply_bindings(_sg_bindings_t* bnd) {\n    #if defined(_SOKOL_ANY_GL)\n    return _sg_gl_apply_bindings(bnd);\n    #elif defined(SOKOL_METAL)\n    return _sg_mtl_apply_bindings(bnd);\n    #elif defined(SOKOL_D3D11)\n    return _sg_d3d11_apply_bindings(bnd);\n    #elif defined(SOKOL_WGPU)\n    return _sg_wgpu_apply_bindings(bnd);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    return _sg_dummy_apply_bindings(bnd);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_apply_uniforms(sg_shader_stage stage_index, int ub_index, const sg_range* data) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_apply_uniforms(stage_index, ub_index, data);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_apply_uniforms(stage_index, ub_index, data);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_apply_uniforms(stage_index, ub_index, data);\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_apply_uniforms(stage_index, ub_index, data);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_apply_uniforms(stage_index, ub_index, data);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_draw(int base_element, int num_elements, int num_instances) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_draw(base_element, num_elements, num_instances);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_draw(base_element, num_elements, num_instances);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_draw(base_element, num_elements, num_instances);\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_draw(base_element, num_elements, num_instances);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_draw(base_element, num_elements, num_instances);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_commit(void) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_commit();\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_commit();\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_commit();\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_commit();\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_commit();\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_update_buffer(_sg_buffer_t* buf, const sg_range* data) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_update_buffer(buf, data);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_update_buffer(buf, data);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_update_buffer(buf, data);\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_update_buffer(buf, data);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_update_buffer(buf, data);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_append_buffer(buf, data, new_frame);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_append_buffer(buf, data, new_frame);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_append_buffer(buf, data, new_frame);\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_append_buffer(buf, data, new_frame);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_append_buffer(buf, data, new_frame);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_update_image(_sg_image_t* img, const sg_image_data* data) {\n    #if defined(_SOKOL_ANY_GL)\n    _sg_gl_update_image(img, data);\n    #elif defined(SOKOL_METAL)\n    _sg_mtl_update_image(img, data);\n    #elif defined(SOKOL_D3D11)\n    _sg_d3d11_update_image(img, data);\n    #elif defined(SOKOL_WGPU)\n    _sg_wgpu_update_image(img, data);\n    #elif defined(SOKOL_DUMMY_BACKEND)\n    _sg_dummy_update_image(img, data);\n    #else\n    #error(\"INVALID BACKEND\");\n    #endif\n}\n\nstatic inline void _sg_push_debug_group(const char* name) {\n    #if defined(SOKOL_METAL)\n    _sg_mtl_push_debug_group(name);\n    #else\n    _SOKOL_UNUSED(name);\n    #endif\n}\n\nstatic inline void _sg_pop_debug_group(void) {\n    #if defined(SOKOL_METAL)\n    _sg_mtl_pop_debug_group();\n    #endif\n}\n\n// ██████   ██████   ██████  ██\n// ██   ██ ██    ██ ██    ██ ██\n// ██████  ██    ██ ██    ██ ██\n// ██      ██    ██ ██    ██ ██\n// ██       ██████   ██████  ███████\n//\n// >>pool\n_SOKOL_PRIVATE void _sg_init_pool(_sg_pool_t* pool, int num) {\n    SOKOL_ASSERT(pool && (num >= 1));\n    // slot 0 is reserved for the 'invalid id', so bump the pool size by 1\n    pool->size = num + 1;\n    pool->queue_top = 0;\n    // generation counters indexable by pool slot index, slot 0 is reserved\n    size_t gen_ctrs_size = sizeof(uint32_t) * (size_t)pool->size;\n    pool->gen_ctrs = (uint32_t*)_sg_malloc_clear(gen_ctrs_size);\n    // it's not a bug to only reserve 'num' here\n    pool->free_queue = (int*) _sg_malloc_clear(sizeof(int) * (size_t)num);\n    // never allocate the zero-th pool item since the invalid id is 0\n    for (int i = pool->size-1; i >= 1; i--) {\n        pool->free_queue[pool->queue_top++] = i;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_discard_pool(_sg_pool_t* pool) {\n    SOKOL_ASSERT(pool);\n    SOKOL_ASSERT(pool->free_queue);\n    _sg_free(pool->free_queue);\n    pool->free_queue = 0;\n    SOKOL_ASSERT(pool->gen_ctrs);\n    _sg_free(pool->gen_ctrs);\n    pool->gen_ctrs = 0;\n    pool->size = 0;\n    pool->queue_top = 0;\n}\n\n_SOKOL_PRIVATE int _sg_pool_alloc_index(_sg_pool_t* pool) {\n    SOKOL_ASSERT(pool);\n    SOKOL_ASSERT(pool->free_queue);\n    if (pool->queue_top > 0) {\n        int slot_index = pool->free_queue[--pool->queue_top];\n        SOKOL_ASSERT((slot_index > 0) && (slot_index < pool->size));\n        return slot_index;\n    } else {\n        // pool exhausted\n        return _SG_INVALID_SLOT_INDEX;\n    }\n}\n\n_SOKOL_PRIVATE void _sg_pool_free_index(_sg_pool_t* pool, int slot_index) {\n    SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < pool->size));\n    SOKOL_ASSERT(pool);\n    SOKOL_ASSERT(pool->free_queue);\n    SOKOL_ASSERT(pool->queue_top < pool->size);\n    #ifdef SOKOL_DEBUG\n    // debug check against double-free\n    for (int i = 0; i < pool->queue_top; i++) {\n        SOKOL_ASSERT(pool->free_queue[i] != slot_index);\n    }\n    #endif\n    pool->free_queue[pool->queue_top++] = slot_index;\n    SOKOL_ASSERT(pool->queue_top <= (pool->size-1));\n}\n\n_SOKOL_PRIVATE void _sg_reset_slot(_sg_slot_t* slot) {\n    SOKOL_ASSERT(slot);\n    _sg_clear(slot, sizeof(_sg_slot_t));\n}\n\n_SOKOL_PRIVATE void _sg_reset_buffer_to_alloc_state(_sg_buffer_t* buf) {\n    SOKOL_ASSERT(buf);\n    _sg_slot_t slot = buf->slot;\n    _sg_clear(buf, sizeof(*buf));\n    buf->slot = slot;\n    buf->slot.state = SG_RESOURCESTATE_ALLOC;\n}\n\n_SOKOL_PRIVATE void _sg_reset_image_to_alloc_state(_sg_image_t* img) {\n    SOKOL_ASSERT(img);\n    _sg_slot_t slot = img->slot;\n    _sg_clear(img, sizeof(*img));\n    img->slot = slot;\n    img->slot.state = SG_RESOURCESTATE_ALLOC;\n}\n\n_SOKOL_PRIVATE void _sg_reset_sampler_to_alloc_state(_sg_sampler_t* smp) {\n    SOKOL_ASSERT(smp);\n    _sg_slot_t slot = smp->slot;\n    _sg_clear(smp, sizeof(*smp));\n    smp->slot = slot;\n    smp->slot.state = SG_RESOURCESTATE_ALLOC;\n}\n\n_SOKOL_PRIVATE void _sg_reset_shader_to_alloc_state(_sg_shader_t* shd) {\n    SOKOL_ASSERT(shd);\n    _sg_slot_t slot = shd->slot;\n    _sg_clear(shd, sizeof(*shd));\n    shd->slot = slot;\n    shd->slot.state = SG_RESOURCESTATE_ALLOC;\n}\n\n_SOKOL_PRIVATE void _sg_reset_pipeline_to_alloc_state(_sg_pipeline_t* pip) {\n    SOKOL_ASSERT(pip);\n    _sg_slot_t slot = pip->slot;\n    _sg_clear(pip, sizeof(*pip));\n    pip->slot = slot;\n    pip->slot.state = SG_RESOURCESTATE_ALLOC;\n}\n\n_SOKOL_PRIVATE void _sg_reset_attachments_to_alloc_state(_sg_attachments_t* atts) {\n    SOKOL_ASSERT(atts);\n    _sg_slot_t slot = atts->slot;\n    _sg_clear(atts, sizeof(*atts));\n    atts->slot = slot;\n    atts->slot.state = SG_RESOURCESTATE_ALLOC;\n}\n\n_SOKOL_PRIVATE void _sg_setup_pools(_sg_pools_t* p, const sg_desc* desc) {\n    SOKOL_ASSERT(p);\n    SOKOL_ASSERT(desc);\n    // note: the pools here will have an additional item, since slot 0 is reserved\n    SOKOL_ASSERT((desc->buffer_pool_size > 0) && (desc->buffer_pool_size < _SG_MAX_POOL_SIZE));\n    _sg_init_pool(&p->buffer_pool, desc->buffer_pool_size);\n    size_t buffer_pool_byte_size = sizeof(_sg_buffer_t) * (size_t)p->buffer_pool.size;\n    p->buffers = (_sg_buffer_t*) _sg_malloc_clear(buffer_pool_byte_size);\n\n    SOKOL_ASSERT((desc->image_pool_size > 0) && (desc->image_pool_size < _SG_MAX_POOL_SIZE));\n    _sg_init_pool(&p->image_pool, desc->image_pool_size);\n    size_t image_pool_byte_size = sizeof(_sg_image_t) * (size_t)p->image_pool.size;\n    p->images = (_sg_image_t*) _sg_malloc_clear(image_pool_byte_size);\n\n    SOKOL_ASSERT((desc->sampler_pool_size > 0) && (desc->sampler_pool_size < _SG_MAX_POOL_SIZE));\n    _sg_init_pool(&p->sampler_pool, desc->sampler_pool_size);\n    size_t sampler_pool_byte_size = sizeof(_sg_sampler_t) * (size_t)p->sampler_pool.size;\n    p->samplers = (_sg_sampler_t*) _sg_malloc_clear(sampler_pool_byte_size);\n\n    SOKOL_ASSERT((desc->shader_pool_size > 0) && (desc->shader_pool_size < _SG_MAX_POOL_SIZE));\n    _sg_init_pool(&p->shader_pool, desc->shader_pool_size);\n    size_t shader_pool_byte_size = sizeof(_sg_shader_t) * (size_t)p->shader_pool.size;\n    p->shaders = (_sg_shader_t*) _sg_malloc_clear(shader_pool_byte_size);\n\n    SOKOL_ASSERT((desc->pipeline_pool_size > 0) && (desc->pipeline_pool_size < _SG_MAX_POOL_SIZE));\n    _sg_init_pool(&p->pipeline_pool, desc->pipeline_pool_size);\n    size_t pipeline_pool_byte_size = sizeof(_sg_pipeline_t) * (size_t)p->pipeline_pool.size;\n    p->pipelines = (_sg_pipeline_t*) _sg_malloc_clear(pipeline_pool_byte_size);\n\n    SOKOL_ASSERT((desc->attachments_pool_size > 0) && (desc->attachments_pool_size < _SG_MAX_POOL_SIZE));\n    _sg_init_pool(&p->attachments_pool, desc->attachments_pool_size);\n    size_t attachments_pool_byte_size = sizeof(_sg_attachments_t) * (size_t)p->attachments_pool.size;\n    p->attachments = (_sg_attachments_t*) _sg_malloc_clear(attachments_pool_byte_size);\n}\n\n_SOKOL_PRIVATE void _sg_discard_pools(_sg_pools_t* p) {\n    SOKOL_ASSERT(p);\n    _sg_free(p->attachments); p->attachments = 0;\n    _sg_free(p->pipelines);   p->pipelines = 0;\n    _sg_free(p->shaders);     p->shaders = 0;\n    _sg_free(p->samplers);    p->samplers = 0;\n    _sg_free(p->images);      p->images = 0;\n    _sg_free(p->buffers);     p->buffers = 0;\n    _sg_discard_pool(&p->attachments_pool);\n    _sg_discard_pool(&p->pipeline_pool);\n    _sg_discard_pool(&p->shader_pool);\n    _sg_discard_pool(&p->sampler_pool);\n    _sg_discard_pool(&p->image_pool);\n    _sg_discard_pool(&p->buffer_pool);\n}\n\n/* allocate the slot at slot_index:\n    - bump the slot's generation counter\n    - create a resource id from the generation counter and slot index\n    - set the slot's id to this id\n    - set the slot's state to ALLOC\n    - return the resource id\n*/\n_SOKOL_PRIVATE uint32_t _sg_slot_alloc(_sg_pool_t* pool, _sg_slot_t* slot, int slot_index) {\n    /* FIXME: add handling for an overflowing generation counter,\n       for now, just overflow (another option is to disable\n       the slot)\n    */\n    SOKOL_ASSERT(pool && pool->gen_ctrs);\n    SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < pool->size));\n    SOKOL_ASSERT(slot->id == SG_INVALID_ID);\n    SOKOL_ASSERT(slot->state == SG_RESOURCESTATE_INITIAL);\n    uint32_t ctr = ++pool->gen_ctrs[slot_index];\n    slot->id = (ctr<<_SG_SLOT_SHIFT)|(slot_index & _SG_SLOT_MASK);\n    slot->state = SG_RESOURCESTATE_ALLOC;\n    return slot->id;\n}\n\n// extract slot index from id\n_SOKOL_PRIVATE int _sg_slot_index(uint32_t id) {\n    int slot_index = (int) (id & _SG_SLOT_MASK);\n    SOKOL_ASSERT(_SG_INVALID_SLOT_INDEX != slot_index);\n    return slot_index;\n}\n\n// returns pointer to resource by id without matching id check\n_SOKOL_PRIVATE _sg_buffer_t* _sg_buffer_at(const _sg_pools_t* p, uint32_t buf_id) {\n    SOKOL_ASSERT(p && (SG_INVALID_ID != buf_id));\n    int slot_index = _sg_slot_index(buf_id);\n    SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < p->buffer_pool.size));\n    return &p->buffers[slot_index];\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_image_at(const _sg_pools_t* p, uint32_t img_id) {\n    SOKOL_ASSERT(p && (SG_INVALID_ID != img_id));\n    int slot_index = _sg_slot_index(img_id);\n    SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < p->image_pool.size));\n    return &p->images[slot_index];\n}\n\n_SOKOL_PRIVATE _sg_sampler_t* _sg_sampler_at(const _sg_pools_t* p, uint32_t smp_id) {\n    SOKOL_ASSERT(p && (SG_INVALID_ID != smp_id));\n    int slot_index = _sg_slot_index(smp_id);\n    SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < p->sampler_pool.size));\n    return &p->samplers[slot_index];\n}\n\n_SOKOL_PRIVATE _sg_shader_t* _sg_shader_at(const _sg_pools_t* p, uint32_t shd_id) {\n    SOKOL_ASSERT(p && (SG_INVALID_ID != shd_id));\n    int slot_index = _sg_slot_index(shd_id);\n    SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < p->shader_pool.size));\n    return &p->shaders[slot_index];\n}\n\n_SOKOL_PRIVATE _sg_pipeline_t* _sg_pipeline_at(const _sg_pools_t* p, uint32_t pip_id) {\n    SOKOL_ASSERT(p && (SG_INVALID_ID != pip_id));\n    int slot_index = _sg_slot_index(pip_id);\n    SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < p->pipeline_pool.size));\n    return &p->pipelines[slot_index];\n}\n\n_SOKOL_PRIVATE _sg_attachments_t* _sg_attachments_at(const _sg_pools_t* p, uint32_t atts_id) {\n    SOKOL_ASSERT(p && (SG_INVALID_ID != atts_id));\n    int slot_index = _sg_slot_index(atts_id);\n    SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < p->attachments_pool.size));\n    return &p->attachments[slot_index];\n}\n\n// returns pointer to resource with matching id check, may return 0\n_SOKOL_PRIVATE _sg_buffer_t* _sg_lookup_buffer(const _sg_pools_t* p, uint32_t buf_id) {\n    if (SG_INVALID_ID != buf_id) {\n        _sg_buffer_t* buf = _sg_buffer_at(p, buf_id);\n        if (buf->slot.id == buf_id) {\n            return buf;\n        }\n    }\n    return 0;\n}\n\n_SOKOL_PRIVATE _sg_image_t* _sg_lookup_image(const _sg_pools_t* p, uint32_t img_id) {\n    if (SG_INVALID_ID != img_id) {\n        _sg_image_t* img = _sg_image_at(p, img_id);\n        if (img->slot.id == img_id) {\n            return img;\n        }\n    }\n    return 0;\n}\n\n_SOKOL_PRIVATE _sg_sampler_t* _sg_lookup_sampler(const _sg_pools_t* p, uint32_t smp_id) {\n    if (SG_INVALID_ID != smp_id) {\n        _sg_sampler_t* smp = _sg_sampler_at(p, smp_id);\n        if (smp->slot.id == smp_id) {\n            return smp;\n        }\n    }\n    return 0;\n}\n\n_SOKOL_PRIVATE _sg_shader_t* _sg_lookup_shader(const _sg_pools_t* p, uint32_t shd_id) {\n    SOKOL_ASSERT(p);\n    if (SG_INVALID_ID != shd_id) {\n        _sg_shader_t* shd = _sg_shader_at(p, shd_id);\n        if (shd->slot.id == shd_id) {\n            return shd;\n        }\n    }\n    return 0;\n}\n\n_SOKOL_PRIVATE _sg_pipeline_t* _sg_lookup_pipeline(const _sg_pools_t* p, uint32_t pip_id) {\n    SOKOL_ASSERT(p);\n    if (SG_INVALID_ID != pip_id) {\n        _sg_pipeline_t* pip = _sg_pipeline_at(p, pip_id);\n        if (pip->slot.id == pip_id) {\n            return pip;\n        }\n    }\n    return 0;\n}\n\n_SOKOL_PRIVATE _sg_attachments_t* _sg_lookup_attachments(const _sg_pools_t* p, uint32_t atts_id) {\n    SOKOL_ASSERT(p);\n    if (SG_INVALID_ID != atts_id) {\n        _sg_attachments_t* atts = _sg_attachments_at(p, atts_id);\n        if (atts->slot.id == atts_id) {\n            return atts;\n        }\n    }\n    return 0;\n}\n\n_SOKOL_PRIVATE void _sg_discard_all_resources(_sg_pools_t* p) {\n    /*  this is a bit dumb since it loops over all pool slots to\n        find the occupied slots, on the other hand it is only ever\n        executed at shutdown\n        NOTE: ONLY EXECUTE THIS AT SHUTDOWN\n              ...because the free queues will not be reset\n              and the resource slots not be cleared!\n    */\n    for (int i = 1; i < p->buffer_pool.size; i++) {\n        sg_resource_state state = p->buffers[i].slot.state;\n        if ((state == SG_RESOURCESTATE_VALID) || (state == SG_RESOURCESTATE_FAILED)) {\n            _sg_discard_buffer(&p->buffers[i]);\n        }\n    }\n    for (int i = 1; i < p->image_pool.size; i++) {\n        sg_resource_state state = p->images[i].slot.state;\n        if ((state == SG_RESOURCESTATE_VALID) || (state == SG_RESOURCESTATE_FAILED)) {\n            _sg_discard_image(&p->images[i]);\n        }\n    }\n    for (int i = 1; i < p->sampler_pool.size; i++) {\n        sg_resource_state state = p->samplers[i].slot.state;\n        if ((state == SG_RESOURCESTATE_VALID) || (state == SG_RESOURCESTATE_FAILED)) {\n            _sg_discard_sampler(&p->samplers[i]);\n        }\n    }\n    for (int i = 1; i < p->shader_pool.size; i++) {\n        sg_resource_state state = p->shaders[i].slot.state;\n        if ((state == SG_RESOURCESTATE_VALID) || (state == SG_RESOURCESTATE_FAILED)) {\n            _sg_discard_shader(&p->shaders[i]);\n        }\n    }\n    for (int i = 1; i < p->pipeline_pool.size; i++) {\n        sg_resource_state state = p->pipelines[i].slot.state;\n        if ((state == SG_RESOURCESTATE_VALID) || (state == SG_RESOURCESTATE_FAILED)) {\n            _sg_discard_pipeline(&p->pipelines[i]);\n        }\n    }\n    for (int i = 1; i < p->attachments_pool.size; i++) {\n        sg_resource_state state = p->attachments[i].slot.state;\n        if ((state == SG_RESOURCESTATE_VALID) || (state == SG_RESOURCESTATE_FAILED)) {\n            _sg_discard_attachments(&p->attachments[i]);\n        }\n    }\n}\n\n// ██    ██  █████  ██      ██ ██████   █████  ████████ ██  ██████  ███    ██\n// ██    ██ ██   ██ ██      ██ ██   ██ ██   ██    ██    ██ ██    ██ ████   ██\n// ██    ██ ███████ ██      ██ ██   ██ ███████    ██    ██ ██    ██ ██ ██  ██\n//  ██  ██  ██   ██ ██      ██ ██   ██ ██   ██    ██    ██ ██    ██ ██  ██ ██\n//   ████   ██   ██ ███████ ██ ██████  ██   ██    ██    ██  ██████  ██   ████\n//\n// >>validation\n#if defined(SOKOL_DEBUG)\n_SOKOL_PRIVATE void _sg_validate_begin(void) {\n    _sg.validate_error = SG_LOGITEM_OK;\n}\n\n_SOKOL_PRIVATE bool _sg_validate_end(void) {\n    if (_sg.validate_error != SG_LOGITEM_OK) {\n        #if !defined(SOKOL_VALIDATE_NON_FATAL)\n            _SG_PANIC(VALIDATION_FAILED);\n            return false;\n        #else\n            return false;\n        #endif\n    } else {\n        return true;\n    }\n}\n#endif\n\n_SOKOL_PRIVATE bool _sg_validate_buffer_desc(const sg_buffer_desc* desc) {\n    #if !defined(SOKOL_DEBUG)\n        _SOKOL_UNUSED(desc);\n        return true;\n    #else\n        if (_sg.desc.disable_validation) {\n            return true;\n        }\n        SOKOL_ASSERT(desc);\n        _sg_validate_begin();\n        _SG_VALIDATE(desc->_start_canary == 0, VALIDATE_BUFFERDESC_CANARY);\n        _SG_VALIDATE(desc->_end_canary == 0, VALIDATE_BUFFERDESC_CANARY);\n        _SG_VALIDATE(desc->size > 0, VALIDATE_BUFFERDESC_SIZE);\n        bool injected = (0 != desc->gl_buffers[0]) ||\n                        (0 != desc->mtl_buffers[0]) ||\n                        (0 != desc->d3d11_buffer) ||\n                        (0 != desc->wgpu_buffer);\n        if (!injected && (desc->usage == SG_USAGE_IMMUTABLE)) {\n            _SG_VALIDATE((0 != desc->data.ptr) && (desc->data.size > 0), VALIDATE_BUFFERDESC_DATA);\n            _SG_VALIDATE(desc->size == desc->data.size, VALIDATE_BUFFERDESC_DATA_SIZE);\n        } else {\n            _SG_VALIDATE(0 == desc->data.ptr, VALIDATE_BUFFERDESC_NO_DATA);\n        }\n        if (desc->type == SG_BUFFERTYPE_STORAGEBUFFER) {\n            _SG_VALIDATE(_sg.features.storage_buffer, VALIDATE_BUFFERDESC_STORAGEBUFFER_SUPPORTED);\n            _SG_VALIDATE(_sg_multiple_u64(desc->size, 4), VALIDATE_BUFFERDESC_STORAGEBUFFER_SIZE_MULTIPLE_4);\n        }\n        return _sg_validate_end();\n    #endif\n}\n\n_SOKOL_PRIVATE void _sg_validate_image_data(const sg_image_data* data, sg_pixel_format fmt, int width, int height, int num_faces, int num_mips, int num_slices) {\n    #if !defined(SOKOL_DEBUG)\n        _SOKOL_UNUSED(data);\n        _SOKOL_UNUSED(fmt);\n        _SOKOL_UNUSED(width);\n        _SOKOL_UNUSED(height);\n        _SOKOL_UNUSED(num_faces);\n        _SOKOL_UNUSED(num_mips);\n        _SOKOL_UNUSED(num_slices);\n    #else\n        for (int face_index = 0; face_index < num_faces; face_index++) {\n            for (int mip_index = 0; mip_index < num_mips; mip_index++) {\n                const bool has_data = data->subimage[face_index][mip_index].ptr != 0;\n                const bool has_size = data->subimage[face_index][mip_index].size > 0;\n                _SG_VALIDATE(has_data && has_size, VALIDATE_IMAGEDATA_NODATA);\n                const int mip_width = _sg_miplevel_dim(width, mip_index);\n                const int mip_height = _sg_miplevel_dim(height, mip_index);\n                const int bytes_per_slice = _sg_surface_pitch(fmt, mip_width, mip_height, 1);\n                const int expected_size = bytes_per_slice * num_slices;\n                _SG_VALIDATE(expected_size == (int)data->subimage[face_index][mip_index].size, VALIDATE_IMAGEDATA_DATA_SIZE);\n            }\n        }\n    #endif\n}\n\n_SOKOL_PRIVATE bool _sg_validate_image_desc(const sg_image_desc* desc) {\n    #if !defined(SOKOL_DEBUG)\n        _SOKOL_UNUSED(desc);\n        return true;\n    #else\n        if (_sg.desc.disable_validation) {\n            return true;\n        }\n        SOKOL_ASSERT(desc);\n        _sg_validate_begin();\n        _SG_VALIDATE(desc->_start_canary == 0, VALIDATE_IMAGEDESC_CANARY);\n        _SG_VALIDATE(desc->_end_canary == 0, VALIDATE_IMAGEDESC_CANARY);\n        _SG_VALIDATE(desc->width > 0, VALIDATE_IMAGEDESC_WIDTH);\n        _SG_VALIDATE(desc->height > 0, VALIDATE_IMAGEDESC_HEIGHT);\n        const sg_pixel_format fmt = desc->pixel_format;\n        const sg_usage usage = desc->usage;\n        const bool injected = (0 != desc->gl_textures[0]) ||\n                              (0 != desc->mtl_textures[0]) ||\n                              (0 != desc->d3d11_texture) ||\n                              (0 != desc->wgpu_texture);\n        if (_sg_is_depth_or_depth_stencil_format(fmt)) {\n            _SG_VALIDATE(desc->type != SG_IMAGETYPE_3D, VALIDATE_IMAGEDESC_DEPTH_3D_IMAGE);\n        }\n        if (desc->render_target) {\n            SOKOL_ASSERT(((int)fmt >= 0) && ((int)fmt < _SG_PIXELFORMAT_NUM));\n            _SG_VALIDATE(_sg.formats[fmt].render, VALIDATE_IMAGEDESC_RT_PIXELFORMAT);\n            _SG_VALIDATE(usage == SG_USAGE_IMMUTABLE, VALIDATE_IMAGEDESC_RT_IMMUTABLE);\n            _SG_VALIDATE(desc->data.subimage[0][0].ptr==0, VALIDATE_IMAGEDESC_RT_NO_DATA);\n            if (desc->sample_count > 1) {\n                _SG_VALIDATE(_sg.formats[fmt].msaa, VALIDATE_IMAGEDESC_NO_MSAA_RT_SUPPORT);\n                _SG_VALIDATE(desc->num_mipmaps == 1, VALIDATE_IMAGEDESC_MSAA_NUM_MIPMAPS);\n                _SG_VALIDATE(desc->type != SG_IMAGETYPE_3D, VALIDATE_IMAGEDESC_MSAA_3D_IMAGE);\n            }\n        } else {\n            _SG_VALIDATE(desc->sample_count == 1, VALIDATE_IMAGEDESC_MSAA_BUT_NO_RT);\n            const bool valid_nonrt_fmt = !_sg_is_valid_rendertarget_depth_format(fmt);\n            _SG_VALIDATE(valid_nonrt_fmt, VALIDATE_IMAGEDESC_NONRT_PIXELFORMAT);\n            const bool is_compressed = _sg_is_compressed_pixel_format(desc->pixel_format);\n            const bool is_immutable = (usage == SG_USAGE_IMMUTABLE);\n            if (is_compressed) {\n                _SG_VALIDATE(is_immutable, VALIDATE_IMAGEDESC_COMPRESSED_IMMUTABLE);\n            }\n            if (!injected && is_immutable) {\n                // image desc must have valid data\n                _sg_validate_image_data(&desc->data,\n                    desc->pixel_format,\n                    desc->width,\n                    desc->height,\n                    (desc->type == SG_IMAGETYPE_CUBE) ? 6 : 1,\n                    desc->num_mipmaps,\n                    desc->num_slices);\n            } else {\n                // image desc must not have data\n                for (int face_index = 0; face_index < SG_CUBEFACE_NUM; face_index++) {\n                    for (int mip_index = 0; mip_index < SG_MAX_MIPMAPS; mip_index++) {\n                        const bool no_data = 0 == desc->data.subimage[face_index][mip_index].ptr;\n                        const bool no_size = 0 == desc->data.subimage[face_index][mip_index].size;\n                        if (injected) {\n                            _SG_VALIDATE(no_data && no_size, VALIDATE_IMAGEDESC_INJECTED_NO_DATA);\n                        }\n                        if (!is_immutable) {\n                            _SG_VALIDATE(no_data && no_size, VALIDATE_IMAGEDESC_DYNAMIC_NO_DATA);\n                        }\n                    }\n                }\n            }\n        }\n        return _sg_validate_end();\n    #endif\n}\n\n_SOKOL_PRIVATE bool _sg_validate_sampler_desc(const sg_sampler_desc* desc) {\n    #if !defined(SOKOL_DEBUG)\n        _SOKOL_UNUSED(desc);\n        return true;\n    #else\n        if (_sg.desc.disable_validation) {\n            return true;\n        }\n        SOKOL_ASSERT(desc);\n        _sg_validate_begin();\n        _SG_VALIDATE(desc->_start_canary == 0, VALIDATE_SAMPLERDESC_CANARY);\n        _SG_VALIDATE(desc->_end_canary == 0, VALIDATE_SAMPLERDESC_CANARY);\n        _SG_VALIDATE(desc->min_filter != SG_FILTER_NONE, VALIDATE_SAMPLERDESC_MINFILTER_NONE);\n        _SG_VALIDATE(desc->mag_filter != SG_FILTER_NONE, VALIDATE_SAMPLERDESC_MAGFILTER_NONE);\n        // restriction from WebGPU: when anisotropy > 1, all filters must be linear\n        if (desc->max_anisotropy > 1) {\n            _SG_VALIDATE((desc->min_filter == SG_FILTER_LINEAR)\n                      && (desc->mag_filter == SG_FILTER_LINEAR)\n                      && (desc->mipmap_filter == SG_FILTER_LINEAR),\n                      VALIDATE_SAMPLERDESC_ANISTROPIC_REQUIRES_LINEAR_FILTERING);\n        }\n        return _sg_validate_end();\n    #endif\n}\n\n_SOKOL_PRIVATE bool _sg_validate_shader_desc(const sg_shader_desc* desc) {\n    #if !defined(SOKOL_DEBUG)\n        _SOKOL_UNUSED(desc);\n        return true;\n    #else\n        if (_sg.desc.disable_validation) {\n            return true;\n        }\n        SOKOL_ASSERT(desc);\n        _sg_validate_begin();\n        _SG_VALIDATE(desc->_start_canary == 0, VALIDATE_SHADERDESC_CANARY);\n        _SG_VALIDATE(desc->_end_canary == 0, VALIDATE_SHADERDESC_CANARY);\n        #if defined(SOKOL_GLCORE) || defined(SOKOL_GLES3) || defined(SOKOL_WGPU)\n            // on GL or WebGPU, must provide shader source code\n            _SG_VALIDATE(0 != desc->vs.source, VALIDATE_SHADERDESC_SOURCE);\n            _SG_VALIDATE(0 != desc->fs.source, VALIDATE_SHADERDESC_SOURCE);\n        #elif defined(SOKOL_METAL) || defined(SOKOL_D3D11)\n            // on Metal or D3D11, must provide shader source code or byte code\n            _SG_VALIDATE((0 != desc->vs.source)||(0 != desc->vs.bytecode.ptr), VALIDATE_SHADERDESC_SOURCE_OR_BYTECODE);\n            _SG_VALIDATE((0 != desc->fs.source)||(0 != desc->fs.bytecode.ptr), VALIDATE_SHADERDESC_SOURCE_OR_BYTECODE);\n        #else\n            // Dummy Backend, don't require source or bytecode\n        #endif\n        for (int i = 0; i < SG_MAX_VERTEX_ATTRIBUTES; i++) {\n            if (desc->attrs[i].name) {\n                _SG_VALIDATE(strlen(desc->attrs[i].name) < _SG_STRING_SIZE, VALIDATE_SHADERDESC_ATTR_STRING_TOO_LONG);\n            }\n            if (desc->attrs[i].sem_name) {\n                _SG_VALIDATE(strlen(desc->attrs[i].sem_name) < _SG_STRING_SIZE, VALIDATE_SHADERDESC_ATTR_STRING_TOO_LONG);\n            }\n        }\n        // if shader byte code, the size must also be provided\n        if (0 != desc->vs.bytecode.ptr) {\n            _SG_VALIDATE(desc->vs.bytecode.size > 0, VALIDATE_SHADERDESC_NO_BYTECODE_SIZE);\n        }\n        if (0 != desc->fs.bytecode.ptr) {\n            _SG_VALIDATE(desc->fs.bytecode.size > 0, VALIDATE_SHADERDESC_NO_BYTECODE_SIZE);\n        }\n        for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {\n            const sg_shader_stage_desc* stage_desc = (stage_index == 0)? &desc->vs : &desc->fs;\n            bool uniform_blocks_continuous = true;\n            for (int ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) {\n                const sg_shader_uniform_block_desc* ub_desc = &stage_desc->uniform_blocks[ub_index];\n                if (ub_desc->size > 0) {\n                    _SG_VALIDATE(uniform_blocks_continuous, VALIDATE_SHADERDESC_NO_CONT_UBS);\n                    #if defined(_SOKOL_ANY_GL)\n                    bool uniforms_continuous = true;\n                    uint32_t uniform_offset = 0;\n                    int num_uniforms = 0;\n                    for (int u_index = 0; u_index < SG_MAX_UB_MEMBERS; u_index++) {\n                        const sg_shader_uniform_desc* u_desc = &ub_desc->uniforms[u_index];\n                        if (u_desc->type != SG_UNIFORMTYPE_INVALID) {\n                            _SG_VALIDATE(uniforms_continuous, VALIDATE_SHADERDESC_NO_CONT_UB_MEMBERS);\n                            #if defined(SOKOL_GLES3)\n                            _SG_VALIDATE(0 != u_desc->name, VALIDATE_SHADERDESC_UB_MEMBER_NAME);\n                            #endif\n                            const int array_count = u_desc->array_count;\n                            _SG_VALIDATE(array_count > 0, VALIDATE_SHADERDESC_UB_ARRAY_COUNT);\n                            const uint32_t u_align = _sg_uniform_alignment(u_desc->type, array_count, ub_desc->layout);\n                            const uint32_t u_size  = _sg_uniform_size(u_desc->type, array_count, ub_desc->layout);\n                            uniform_offset = _sg_align_u32(uniform_offset, u_align);\n                            uniform_offset += u_size;\n                            num_uniforms++;\n                            // with std140, arrays are only allowed for FLOAT4, INT4, MAT4\n                            if (ub_desc->layout == SG_UNIFORMLAYOUT_STD140) {\n                                if (array_count > 1) {\n                                    _SG_VALIDATE((u_desc->type == SG_UNIFORMTYPE_FLOAT4) || (u_desc->type == SG_UNIFORMTYPE_INT4) || (u_desc->type == SG_UNIFORMTYPE_MAT4), VALIDATE_SHADERDESC_UB_STD140_ARRAY_TYPE);\n                                }\n                            }\n                        } else {\n                            uniforms_continuous = false;\n                        }\n                    }\n                    if (ub_desc->layout == SG_UNIFORMLAYOUT_STD140) {\n                        uniform_offset = _sg_align_u32(uniform_offset, 16);\n                    }\n                    _SG_VALIDATE((size_t)uniform_offset == ub_desc->size, VALIDATE_SHADERDESC_UB_SIZE_MISMATCH);\n                    _SG_VALIDATE(num_uniforms > 0, VALIDATE_SHADERDESC_NO_UB_MEMBERS);\n                    #endif\n                } else {\n                    uniform_blocks_continuous = false;\n                }\n            }\n            bool storage_buffers_continuous = true;\n            for (int sbuf_index = 0; sbuf_index < SG_MAX_SHADERSTAGE_STORAGEBUFFERS; sbuf_index++) {\n                const sg_shader_storage_buffer_desc* sbuf_desc = &stage_desc->storage_buffers[sbuf_index];\n                if (sbuf_desc->used) {\n                    _SG_VALIDATE(storage_buffers_continuous, VALIDATE_SHADERDESC_NO_CONT_STORAGEBUFFERS);\n                    _SG_VALIDATE(sbuf_desc->readonly, VALIDATE_SHADERDESC_STORAGEBUFFER_READONLY);\n                } else {\n                    storage_buffers_continuous = false;\n                }\n            }\n            bool images_continuous = true;\n            int num_images = 0;\n            for (int img_index = 0; img_index < SG_MAX_SHADERSTAGE_IMAGES; img_index++) {\n                const sg_shader_image_desc* img_desc = &stage_desc->images[img_index];\n                if (img_desc->used) {\n                    _SG_VALIDATE(images_continuous, VALIDATE_SHADERDESC_NO_CONT_IMAGES);\n                    num_images++;\n                } else {\n                    images_continuous = false;\n                }\n            }\n            bool samplers_continuous = true;\n            int num_samplers = 0;\n            for (int smp_index = 0; smp_index < SG_MAX_SHADERSTAGE_SAMPLERS; smp_index++) {\n                const sg_shader_sampler_desc* smp_desc = &stage_desc->samplers[smp_index];\n                if (smp_desc->used) {\n                    _SG_VALIDATE(samplers_continuous, VALIDATE_SHADERDESC_NO_CONT_SAMPLERS);\n                    num_samplers++;\n                } else {\n                    samplers_continuous = false;\n                }\n            }\n            bool image_samplers_continuous = true;\n            int num_image_samplers = 0;\n            for (int img_smp_index = 0; img_smp_index < SG_MAX_SHADERSTAGE_IMAGESAMPLERPAIRS; img_smp_index++) {\n                const sg_shader_image_sampler_pair_desc* img_smp_desc = &stage_desc->image_sampler_pairs[img_smp_index];\n                if (img_smp_desc->used) {\n                    _SG_VALIDATE(image_samplers_continuous, VALIDATE_SHADERDESC_NO_CONT_IMAGE_SAMPLER_PAIRS);\n                    num_image_samplers++;\n                    const bool img_slot_in_range = (img_smp_desc->image_slot >= 0) && (img_smp_desc->image_slot < SG_MAX_SHADERSTAGE_IMAGES);\n                    const bool smp_slot_in_range = (img_smp_desc->sampler_slot >= 0) && (img_smp_desc->sampler_slot < SG_MAX_SHADERSTAGE_SAMPLERS);\n                    _SG_VALIDATE(img_slot_in_range && (img_smp_desc->image_slot < num_images), VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_IMAGE_SLOT_OUT_OF_RANGE);\n                    _SG_VALIDATE(smp_slot_in_range && (img_smp_desc->sampler_slot < num_samplers), VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_IMAGE_SLOT_OUT_OF_RANGE);\n                    #if defined(_SOKOL_ANY_GL)\n                    _SG_VALIDATE(img_smp_desc->glsl_name != 0, VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_NAME_REQUIRED_FOR_GL);\n                    #endif\n                    if (img_slot_in_range && smp_slot_in_range) {\n                        const sg_shader_image_desc* img_desc = &stage_desc->images[img_smp_desc->image_slot];\n                        const sg_shader_sampler_desc* smp_desc = &stage_desc->samplers[img_smp_desc->sampler_slot];\n                        const bool needs_nonfiltering = (img_desc->sample_type == SG_IMAGESAMPLETYPE_UINT)\n                                                     || (img_desc->sample_type == SG_IMAGESAMPLETYPE_SINT)\n                                                     || (img_desc->sample_type == SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT);\n                        const bool needs_comparison = img_desc->sample_type == SG_IMAGESAMPLETYPE_DEPTH;\n                        if (needs_nonfiltering) {\n                            _SG_VALIDATE(needs_nonfiltering && (smp_desc->sampler_type == SG_SAMPLERTYPE_NONFILTERING), VALIDATE_SHADERDESC_NONFILTERING_SAMPLER_REQUIRED);\n                        }\n                        if (needs_comparison) {\n                            _SG_VALIDATE(needs_comparison && (smp_desc->sampler_type == SG_SAMPLERTYPE_COMPARISON), VALIDATE_SHADERDESC_COMPARISON_SAMPLER_REQUIRED);\n                        }\n                    }\n                } else {\n                    _SG_VALIDATE(img_smp_desc->glsl_name == 0, VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_HAS_NAME_BUT_NOT_USED);\n                    _SG_VALIDATE(img_smp_desc->image_slot == 0, VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_HAS_IMAGE_BUT_NOT_USED);\n                    _SG_VALIDATE(img_smp_desc->sampler_slot == 0, VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_HAS_SAMPLER_BUT_NOT_USED);\n                    image_samplers_continuous = false;\n                }\n            }\n            // each image and sampler must be referenced by an image sampler\n            const uint32_t expected_img_slot_mask = (uint32_t)((1 << num_images) - 1);\n            const uint32_t expected_smp_slot_mask = (uint32_t)((1 << num_samplers) - 1);\n            uint32_t actual_img_slot_mask = 0;\n            uint32_t actual_smp_slot_mask = 0;\n            for (int img_smp_index = 0; img_smp_index < num_image_samplers; img_smp_index++) {\n                const sg_shader_image_sampler_pair_desc* img_smp_desc = &stage_desc->image_sampler_pairs[img_smp_index];\n                actual_img_slot_mask |= (1 << ((uint32_t)img_smp_desc->image_slot & 31));\n                actual_smp_slot_mask |= (1 << ((uint32_t)img_smp_desc->sampler_slot & 31));\n            }\n            _SG_VALIDATE(expected_img_slot_mask == actual_img_slot_mask, VALIDATE_SHADERDESC_IMAGE_NOT_REFERENCED_BY_IMAGE_SAMPLER_PAIRS);\n            _SG_VALIDATE(expected_smp_slot_mask == actual_smp_slot_mask, VALIDATE_SHADERDESC_SAMPLER_NOT_REFERENCED_BY_IMAGE_SAMPLER_PAIRS);\n        }\n        return _sg_validate_end();\n    #endif\n}\n\n_SOKOL_PRIVATE bool _sg_validate_pipeline_desc(const sg_pipeline_desc* desc) {\n    #if !defined(SOKOL_DEBUG)\n        _SOKOL_UNUSED(desc);\n        return true;\n    #else\n        if (_sg.desc.disable_validation) {\n            return true;\n        }\n        SOKOL_ASSERT(desc);\n        _sg_validate_begin();\n        _SG_VALIDATE(desc->_start_canary == 0, VALIDATE_PIPELINEDESC_CANARY);\n        _SG_VALIDATE(desc->_end_canary == 0, VALIDATE_PIPELINEDESC_CANARY);\n        _SG_VALIDATE(desc->shader.id != SG_INVALID_ID, VALIDATE_PIPELINEDESC_SHADER);\n        for (int buf_index = 0; buf_index < SG_MAX_VERTEX_BUFFERS; buf_index++) {\n            const sg_vertex_buffer_layout_state* l_state = &desc->layout.buffers[buf_index];\n            if (l_state->stride == 0) {\n                continue;\n            }\n            _SG_VALIDATE(_sg_multiple_u64((uint64_t)l_state->stride, 4), VALIDATE_PIPELINEDESC_LAYOUT_STRIDE4);\n        }\n        const _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, desc->shader.id);\n        _SG_VALIDATE(0 != shd, VALIDATE_PIPELINEDESC_SHADER);\n        if (shd) {\n            _SG_VALIDATE(shd->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_PIPELINEDESC_SHADER);\n            bool attrs_cont = true;\n            for (int attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {\n                const sg_vertex_attr_state* a_state = &desc->layout.attrs[attr_index];\n                if (a_state->format == SG_VERTEXFORMAT_INVALID) {\n                    attrs_cont = false;\n                    continue;\n                }\n                _SG_VALIDATE(attrs_cont, VALIDATE_PIPELINEDESC_NO_CONT_ATTRS);\n                SOKOL_ASSERT(a_state->buffer_index < SG_MAX_VERTEX_BUFFERS);\n                #if defined(SOKOL_D3D11)\n                // on D3D11, semantic names (and semantic indices) must be provided\n                _SG_VALIDATE(!_sg_strempty(&shd->d3d11.attrs[attr_index].sem_name), VALIDATE_PIPELINEDESC_ATTR_SEMANTICS);\n                #endif\n            }\n        }\n        return _sg_validate_end();\n    #endif\n}\n\n_SOKOL_PRIVATE bool _sg_validate_attachments_desc(const sg_attachments_desc* desc) {\n    #if !defined(SOKOL_DEBUG)\n        _SOKOL_UNUSED(desc);\n        return true;\n    #else\n        if (_sg.desc.disable_validation) {\n            return true;\n        }\n        SOKOL_ASSERT(desc);\n        _sg_validate_begin();\n        _SG_VALIDATE(desc->_start_canary == 0, VALIDATE_ATTACHMENTSDESC_CANARY);\n        _SG_VALIDATE(desc->_end_canary == 0, VALIDATE_ATTACHMENTSDESC_CANARY);\n        bool atts_cont = true;\n        int color_width = -1, color_height = -1, color_sample_count = -1;\n        bool has_color_atts = false;\n        for (int att_index = 0; att_index < SG_MAX_COLOR_ATTACHMENTS; att_index++) {\n            const sg_attachment_desc* att = &desc->colors[att_index];\n            if (att->image.id == SG_INVALID_ID) {\n                atts_cont = false;\n                continue;\n            }\n            _SG_VALIDATE(atts_cont, VALIDATE_ATTACHMENTSDESC_NO_CONT_COLOR_ATTS);\n            has_color_atts = true;\n            const _sg_image_t* img = _sg_lookup_image(&_sg.pools, att->image.id);\n            _SG_VALIDATE(img, VALIDATE_ATTACHMENTSDESC_IMAGE);\n            if (0 != img) {\n                _SG_VALIDATE(img->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_ATTACHMENTSDESC_IMAGE);\n                _SG_VALIDATE(img->cmn.render_target, VALIDATE_ATTACHMENTSDESC_IMAGE_NO_RT);\n                _SG_VALIDATE(att->mip_level < img->cmn.num_mipmaps, VALIDATE_ATTACHMENTSDESC_MIPLEVEL);\n                if (img->cmn.type == SG_IMAGETYPE_CUBE) {\n                    _SG_VALIDATE(att->slice < 6, VALIDATE_ATTACHMENTSDESC_FACE);\n                } else if (img->cmn.type == SG_IMAGETYPE_ARRAY) {\n                    _SG_VALIDATE(att->slice < img->cmn.num_slices, VALIDATE_ATTACHMENTSDESC_LAYER);\n                } else if (img->cmn.type == SG_IMAGETYPE_3D) {\n                    _SG_VALIDATE(att->slice < img->cmn.num_slices, VALIDATE_ATTACHMENTSDESC_SLICE);\n                }\n                if (att_index == 0) {\n                    color_width = _sg_miplevel_dim(img->cmn.width, att->mip_level);\n                    color_height = _sg_miplevel_dim(img->cmn.height, att->mip_level);\n                    color_sample_count = img->cmn.sample_count;\n                } else {\n                    _SG_VALIDATE(color_width == _sg_miplevel_dim(img->cmn.width, att->mip_level), VALIDATE_ATTACHMENTSDESC_IMAGE_SIZES);\n                    _SG_VALIDATE(color_height == _sg_miplevel_dim(img->cmn.height, att->mip_level), VALIDATE_ATTACHMENTSDESC_IMAGE_SIZES);\n                    _SG_VALIDATE(color_sample_count == img->cmn.sample_count, VALIDATE_ATTACHMENTSDESC_IMAGE_SAMPLE_COUNTS);\n                }\n                _SG_VALIDATE(_sg_is_valid_rendertarget_color_format(img->cmn.pixel_format), VALIDATE_ATTACHMENTSDESC_COLOR_INV_PIXELFORMAT);\n\n                // check resolve attachment\n                const sg_attachment_desc* res_att = &desc->resolves[att_index];\n                if (res_att->image.id != SG_INVALID_ID) {\n                    // associated color attachment must be MSAA\n                    _SG_VALIDATE(img->cmn.sample_count > 1, VALIDATE_ATTACHMENTSDESC_RESOLVE_COLOR_IMAGE_MSAA);\n                    const _sg_image_t* res_img = _sg_lookup_image(&_sg.pools, res_att->image.id);\n                    _SG_VALIDATE(res_img, VALIDATE_ATTACHMENTSDESC_RESOLVE_IMAGE);\n                    if (res_img != 0) {\n                        _SG_VALIDATE(res_img->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_ATTACHMENTSDESC_RESOLVE_IMAGE);\n                        _SG_VALIDATE(res_img->cmn.render_target, VALIDATE_ATTACHMENTSDESC_RESOLVE_IMAGE_NO_RT);\n                        _SG_VALIDATE(res_img->cmn.sample_count == 1, VALIDATE_ATTACHMENTSDESC_RESOLVE_SAMPLE_COUNT);\n                        _SG_VALIDATE(res_att->mip_level < res_img->cmn.num_mipmaps, VALIDATE_ATTACHMENTSDESC_RESOLVE_MIPLEVEL);\n                        if (res_img->cmn.type == SG_IMAGETYPE_CUBE) {\n                            _SG_VALIDATE(res_att->slice < 6, VALIDATE_ATTACHMENTSDESC_RESOLVE_FACE);\n                        } else if (res_img->cmn.type == SG_IMAGETYPE_ARRAY) {\n                            _SG_VALIDATE(res_att->slice < res_img->cmn.num_slices, VALIDATE_ATTACHMENTSDESC_RESOLVE_LAYER);\n                        } else if (res_img->cmn.type == SG_IMAGETYPE_3D) {\n                            _SG_VALIDATE(res_att->slice < res_img->cmn.num_slices, VALIDATE_ATTACHMENTSDESC_RESOLVE_SLICE);\n                        }\n                        _SG_VALIDATE(img->cmn.pixel_format == res_img->cmn.pixel_format, VALIDATE_ATTACHMENTSDESC_RESOLVE_IMAGE_FORMAT);\n                        _SG_VALIDATE(color_width == _sg_miplevel_dim(res_img->cmn.width, res_att->mip_level), VALIDATE_ATTACHMENTSDESC_RESOLVE_IMAGE_SIZES);\n                        _SG_VALIDATE(color_height == _sg_miplevel_dim(res_img->cmn.height, res_att->mip_level), VALIDATE_ATTACHMENTSDESC_RESOLVE_IMAGE_SIZES);\n                    }\n                }\n            }\n        }\n        bool has_depth_stencil_att = false;\n        if (desc->depth_stencil.image.id != SG_INVALID_ID) {\n            const sg_attachment_desc* att = &desc->depth_stencil;\n            const _sg_image_t* img = _sg_lookup_image(&_sg.pools, att->image.id);\n            _SG_VALIDATE(img, VALIDATE_ATTACHMENTSDESC_DEPTH_IMAGE);\n            has_depth_stencil_att = true;\n            if (img) {\n                _SG_VALIDATE(img->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_ATTACHMENTSDESC_DEPTH_IMAGE);\n                _SG_VALIDATE(att->mip_level < img->cmn.num_mipmaps, VALIDATE_ATTACHMENTSDESC_DEPTH_MIPLEVEL);\n                if (img->cmn.type == SG_IMAGETYPE_CUBE) {\n                    _SG_VALIDATE(att->slice < 6, VALIDATE_ATTACHMENTSDESC_DEPTH_FACE);\n                } else if (img->cmn.type == SG_IMAGETYPE_ARRAY) {\n                    _SG_VALIDATE(att->slice < img->cmn.num_slices, VALIDATE_ATTACHMENTSDESC_DEPTH_LAYER);\n                } else if (img->cmn.type == SG_IMAGETYPE_3D) {\n                    // NOTE: this can't actually happen because of VALIDATE_IMAGEDESC_DEPTH_3D_IMAGE\n                    _SG_VALIDATE(att->slice < img->cmn.num_slices, VALIDATE_ATTACHMENTSDESC_DEPTH_SLICE);\n                }\n                _SG_VALIDATE(img->cmn.render_target, VALIDATE_ATTACHMENTSDESC_DEPTH_IMAGE_NO_RT);\n                _SG_VALIDATE((color_width == -1) || (color_width == _sg_miplevel_dim(img->cmn.width, att->mip_level)), VALIDATE_ATTACHMENTSDESC_DEPTH_IMAGE_SIZES);\n                _SG_VALIDATE((color_height == -1) || (color_height == _sg_miplevel_dim(img->cmn.height, att->mip_level)), VALIDATE_ATTACHMENTSDESC_DEPTH_IMAGE_SIZES);\n                _SG_VALIDATE((color_sample_count == -1) || (color_sample_count == img->cmn.sample_count), VALIDATE_ATTACHMENTSDESC_DEPTH_IMAGE_SAMPLE_COUNT);\n                _SG_VALIDATE(_sg_is_valid_rendertarget_depth_format(img->cmn.pixel_format), VALIDATE_ATTACHMENTSDESC_DEPTH_INV_PIXELFORMAT);\n            }\n        }\n        _SG_VALIDATE(has_color_atts || has_depth_stencil_att, VALIDATE_ATTACHMENTSDESC_NO_ATTACHMENTS);\n        return _sg_validate_end();\n    #endif\n}\n\n_SOKOL_PRIVATE bool _sg_validate_begin_pass(const sg_pass* pass) {\n    #if !defined(SOKOL_DEBUG)\n        _SOKOL_UNUSED(pass);\n        return true;\n    #else\n        if (_sg.desc.disable_validation) {\n            return true;\n        }\n        _sg_validate_begin();\n        _SG_VALIDATE(pass->_start_canary == 0, VALIDATE_BEGINPASS_CANARY);\n        _SG_VALIDATE(pass->_end_canary == 0, VALIDATE_BEGINPASS_CANARY);\n        if (pass->attachments.id == SG_INVALID_ID) {\n            // this is a swapchain pass\n            _SG_VALIDATE(pass->swapchain.width > 0, VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_WIDTH);\n            _SG_VALIDATE(pass->swapchain.height > 0, VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_HEIGHT);\n            _SG_VALIDATE(pass->swapchain.sample_count > 0, VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_SAMPLECOUNT);\n            _SG_VALIDATE(pass->swapchain.color_format > SG_PIXELFORMAT_NONE, VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_COLORFORMAT);\n            // NOTE: depth buffer is optional, so depth_format is allowed to be invalid\n            // NOTE: the GL framebuffer handle may actually be 0\n            #if defined(SOKOL_METAL)\n                _SG_VALIDATE(pass->swapchain.metal.current_drawable != 0, VALIDATE_BEGINPASS_SWAPCHAIN_METAL_EXPECT_CURRENTDRAWABLE);\n                if (pass->swapchain.depth_format == SG_PIXELFORMAT_NONE) {\n                    _SG_VALIDATE(pass->swapchain.metal.depth_stencil_texture == 0, VALIDATE_BEGINPASS_SWAPCHAIN_METAL_EXPECT_DEPTHSTENCILTEXTURE_NOTSET);\n                } else {\n                    _SG_VALIDATE(pass->swapchain.metal.depth_stencil_texture != 0, VALIDATE_BEGINPASS_SWAPCHAIN_METAL_EXPECT_DEPTHSTENCILTEXTURE);\n                }\n                if (pass->swapchain.sample_count > 1) {\n                    _SG_VALIDATE(pass->swapchain.metal.msaa_color_texture != 0, VALIDATE_BEGINPASS_SWAPCHAIN_METAL_EXPECT_MSAACOLORTEXTURE);\n                } else {\n                    _SG_VALIDATE(pass->swapchain.metal.msaa_color_texture == 0, VALIDATE_BEGINPASS_SWAPCHAIN_METAL_EXPECT_MSAACOLORTEXTURE_NOTSET);\n                }\n            #elif defined(SOKOL_D3D11)\n                _SG_VALIDATE(pass->swapchain.d3d11.render_view != 0, VALIDATE_BEGINPASS_SWAPCHAIN_D3D11_EXPECT_RENDERVIEW);\n                if (pass->swapchain.depth_format == SG_PIXELFORMAT_NONE) {\n                    _SG_VALIDATE(pass->swapchain.d3d11.depth_stencil_view == 0, VALIDATE_BEGINPASS_SWAPCHAIN_D3D11_EXPECT_DEPTHSTENCILVIEW_NOTSET);\n                } else {\n                    _SG_VALIDATE(pass->swapchain.d3d11.depth_stencil_view != 0, VALIDATE_BEGINPASS_SWAPCHAIN_D3D11_EXPECT_DEPTHSTENCILVIEW);\n                }\n                if (pass->swapchain.sample_count > 1) {\n                    _SG_VALIDATE(pass->swapchain.d3d11.resolve_view != 0, VALIDATE_BEGINPASS_SWAPCHAIN_D3D11_EXPECT_RESOLVEVIEW);\n                } else {\n                    _SG_VALIDATE(pass->swapchain.d3d11.resolve_view == 0, VALIDATE_BEGINPASS_SWAPCHAIN_D3D11_EXPECT_RESOLVEVIEW_NOTSET);\n                }\n            #elif defined(SOKOL_WGPU)\n                _SG_VALIDATE(pass->swapchain.wgpu.render_view != 0, VALIDATE_BEGINPASS_SWAPCHAIN_WGPU_EXPECT_RENDERVIEW);\n                if (pass->swapchain.depth_format == SG_PIXELFORMAT_NONE) {\n                    _SG_VALIDATE(pass->swapchain.wgpu.depth_stencil_view == 0, VALIDATE_BEGINPASS_SWAPCHAIN_WGPU_EXPECT_DEPTHSTENCILVIEW_NOTSET);\n                } else {\n                    _SG_VALIDATE(pass->swapchain.wgpu.depth_stencil_view != 0, VALIDATE_BEGINPASS_SWAPCHAIN_WGPU_EXPECT_DEPTHSTENCILVIEW);\n                }\n                if (pass->swapchain.sample_count > 1) {\n                    _SG_VALIDATE(pass->swapchain.wgpu.resolve_view != 0, VALIDATE_BEGINPASS_SWAPCHAIN_WGPU_EXPECT_RESOLVEVIEW);\n                } else {\n                    _SG_VALIDATE(pass->swapchain.wgpu.resolve_view == 0, VALIDATE_BEGINPASS_SWAPCHAIN_WGPU_EXPECT_RESOLVEVIEW_NOTSET);\n                }\n            #endif\n        } else {\n            // this is an 'offscreen pass'\n            const _sg_attachments_t* atts = _sg_lookup_attachments(&_sg.pools, pass->attachments.id);\n            if (atts) {\n                _SG_VALIDATE(atts->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_BEGINPASS_ATTACHMENTS_VALID);\n                for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {\n                    const _sg_attachment_common_t* color_att = &atts->cmn.colors[i];\n                    const _sg_image_t* color_img = _sg_attachments_color_image(atts, i);\n                    if (color_img) {\n                        _SG_VALIDATE(color_img->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_BEGINPASS_COLOR_ATTACHMENT_IMAGE);\n                        _SG_VALIDATE(color_img->slot.id == color_att->image_id.id, VALIDATE_BEGINPASS_COLOR_ATTACHMENT_IMAGE);\n                    }\n                    const _sg_attachment_common_t* resolve_att = &atts->cmn.resolves[i];\n                    const _sg_image_t* resolve_img = _sg_attachments_resolve_image(atts, i);\n                    if (resolve_img) {\n                        _SG_VALIDATE(resolve_img->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_BEGINPASS_RESOLVE_ATTACHMENT_IMAGE);\n                        _SG_VALIDATE(resolve_img->slot.id == resolve_att->image_id.id, VALIDATE_BEGINPASS_RESOLVE_ATTACHMENT_IMAGE);\n                    }\n                }\n                const _sg_image_t* ds_img = _sg_attachments_ds_image(atts);\n                if (ds_img) {\n                    const _sg_attachment_common_t* att = &atts->cmn.depth_stencil;\n                    _SG_VALIDATE(ds_img->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_BEGINPASS_DEPTHSTENCIL_ATTACHMENT_IMAGE);\n                    _SG_VALIDATE(ds_img->slot.id == att->image_id.id, VALIDATE_BEGINPASS_DEPTHSTENCIL_ATTACHMENT_IMAGE);\n                }\n            } else {\n                _SG_VALIDATE(atts != 0, VALIDATE_BEGINPASS_ATTACHMENTS_EXISTS);\n            }\n            // swapchain params must be all zero!\n            _SG_VALIDATE(pass->swapchain.width == 0, VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_WIDTH_NOTSET);\n            _SG_VALIDATE(pass->swapchain.height == 0, VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_HEIGHT_NOTSET);\n            _SG_VALIDATE(pass->swapchain.sample_count == 0, VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_SAMPLECOUNT_NOTSET);\n            _SG_VALIDATE(pass->swapchain.color_format == _SG_PIXELFORMAT_DEFAULT, VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_COLORFORMAT_NOTSET);\n            _SG_VALIDATE(pass->swapchain.depth_format == _SG_PIXELFORMAT_DEFAULT, VALIDATE_BEGINPASS_SWAPCHAIN_EXPECT_DEPTHFORMAT_NOTSET);\n            #if defined(SOKOL_METAL)\n                _SG_VALIDATE(pass->swapchain.metal.current_drawable == 0, VALIDATE_BEGINPASS_SWAPCHAIN_METAL_EXPECT_CURRENTDRAWABLE_NOTSET);\n                _SG_VALIDATE(pass->swapchain.metal.depth_stencil_texture == 0, VALIDATE_BEGINPASS_SWAPCHAIN_METAL_EXPECT_DEPTHSTENCILTEXTURE_NOTSET);\n                _SG_VALIDATE(pass->swapchain.metal.msaa_color_texture == 0, VALIDATE_BEGINPASS_SWAPCHAIN_METAL_EXPECT_MSAACOLORTEXTURE_NOTSET);\n            #elif defined(SOKOL_D3D11)\n                _SG_VALIDATE(pass->swapchain.d3d11.render_view == 0, VALIDATE_BEGINPASS_SWAPCHAIN_D3D11_EXPECT_RENDERVIEW_NOTSET);\n                _SG_VALIDATE(pass->swapchain.d3d11.depth_stencil_view == 0, VALIDATE_BEGINPASS_SWAPCHAIN_D3D11_EXPECT_DEPTHSTENCILVIEW_NOTSET);\n                _SG_VALIDATE(pass->swapchain.d3d11.resolve_view == 0, VALIDATE_BEGINPASS_SWAPCHAIN_D3D11_EXPECT_RESOLVEVIEW_NOTSET);\n            #elif defined(SOKOL_WGPU)\n                _SG_VALIDATE(pass->swapchain.wgpu.render_view == 0, VALIDATE_BEGINPASS_SWAPCHAIN_WGPU_EXPECT_RENDERVIEW_NOTSET);\n                _SG_VALIDATE(pass->swapchain.wgpu.depth_stencil_view == 0, VALIDATE_BEGINPASS_SWAPCHAIN_WGPU_EXPECT_DEPTHSTENCILVIEW_NOTSET);\n                _SG_VALIDATE(pass->swapchain.wgpu.resolve_view == 0, VALIDATE_BEGINPASS_SWAPCHAIN_WGPU_EXPECT_RESOLVEVIEW_NOTSET);\n            #elif defined(_SOKOL_ANY_GL)\n                _SG_VALIDATE(pass->swapchain.gl.framebuffer == 0, VALIDATE_BEGINPASS_SWAPCHAIN_GL_EXPECT_FRAMEBUFFER_NOTSET);\n            #endif\n        }\n        return _sg_validate_end();\n    #endif\n}\n\n_SOKOL_PRIVATE bool _sg_validate_apply_pipeline(sg_pipeline pip_id) {\n    #if !defined(SOKOL_DEBUG)\n        _SOKOL_UNUSED(pip_id);\n        return true;\n    #else\n        if (_sg.desc.disable_validation) {\n            return true;\n        }\n        _sg_validate_begin();\n        // the pipeline object must be alive and valid\n        _SG_VALIDATE(pip_id.id != SG_INVALID_ID, VALIDATE_APIP_PIPELINE_VALID_ID);\n        const _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);\n        _SG_VALIDATE(pip != 0, VALIDATE_APIP_PIPELINE_EXISTS);\n        if (!pip) {\n            return _sg_validate_end();\n        }\n        _SG_VALIDATE(pip->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_APIP_PIPELINE_VALID);\n        // the pipeline's shader must be alive and valid\n        SOKOL_ASSERT(pip->shader);\n        _SG_VALIDATE(pip->shader->slot.id == pip->cmn.shader_id.id, VALIDATE_APIP_SHADER_EXISTS);\n        _SG_VALIDATE(pip->shader->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_APIP_SHADER_VALID);\n        // check that pipeline attributes match current pass attributes\n        if (_sg.cur_pass.atts_id.id != SG_INVALID_ID) {\n            // an offscreen pass\n            const _sg_attachments_t* atts = _sg.cur_pass.atts;\n            SOKOL_ASSERT(atts);\n            _SG_VALIDATE(atts->slot.id == _sg.cur_pass.atts_id.id, VALIDATE_APIP_CURPASS_ATTACHMENTS_EXISTS);\n            _SG_VALIDATE(atts->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_APIP_CURPASS_ATTACHMENTS_VALID);\n\n            _SG_VALIDATE(pip->cmn.color_count == atts->cmn.num_colors, VALIDATE_APIP_ATT_COUNT);\n            for (int i = 0; i < pip->cmn.color_count; i++) {\n                const _sg_image_t* att_img = _sg_attachments_color_image(atts, i);\n                _SG_VALIDATE(pip->cmn.colors[i].pixel_format == att_img->cmn.pixel_format, VALIDATE_APIP_COLOR_FORMAT);\n                _SG_VALIDATE(pip->cmn.sample_count == att_img->cmn.sample_count, VALIDATE_APIP_SAMPLE_COUNT);\n            }\n            const _sg_image_t* att_dsimg = _sg_attachments_ds_image(atts);\n            if (att_dsimg) {\n                _SG_VALIDATE(pip->cmn.depth.pixel_format == att_dsimg->cmn.pixel_format, VALIDATE_APIP_DEPTH_FORMAT);\n            } else {\n                _SG_VALIDATE(pip->cmn.depth.pixel_format == SG_PIXELFORMAT_NONE, VALIDATE_APIP_DEPTH_FORMAT);\n            }\n        } else {\n            // default pass\n            _SG_VALIDATE(pip->cmn.color_count == 1, VALIDATE_APIP_ATT_COUNT);\n            _SG_VALIDATE(pip->cmn.colors[0].pixel_format == _sg.cur_pass.swapchain.color_fmt, VALIDATE_APIP_COLOR_FORMAT);\n            _SG_VALIDATE(pip->cmn.depth.pixel_format == _sg.cur_pass.swapchain.depth_fmt, VALIDATE_APIP_DEPTH_FORMAT);\n            _SG_VALIDATE(pip->cmn.sample_count == _sg.cur_pass.swapchain.sample_count, VALIDATE_APIP_SAMPLE_COUNT);\n        }\n        return _sg_validate_end();\n    #endif\n}\n\n_SOKOL_PRIVATE bool _sg_validate_apply_bindings(const sg_bindings* bindings) {\n    #if !defined(SOKOL_DEBUG)\n        _SOKOL_UNUSED(bindings);\n        return true;\n    #else\n        if (_sg.desc.disable_validation) {\n            return true;\n        }\n        _sg_validate_begin();\n\n        // a pipeline object must have been applied\n        _SG_VALIDATE(_sg.cur_pipeline.id != SG_INVALID_ID, VALIDATE_ABND_PIPELINE);\n        const _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, _sg.cur_pipeline.id);\n        _SG_VALIDATE(pip != 0, VALIDATE_ABND_PIPELINE_EXISTS);\n        if (!pip) {\n            return _sg_validate_end();\n        }\n        _SG_VALIDATE(pip->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_ABND_PIPELINE_VALID);\n        SOKOL_ASSERT(pip->shader && (pip->cmn.shader_id.id == pip->shader->slot.id));\n\n        // has expected vertex buffers, and vertex buffers still exist\n        for (int i = 0; i < SG_MAX_VERTEX_BUFFERS; i++) {\n            if (bindings->vertex_buffers[i].id != SG_INVALID_ID) {\n                _SG_VALIDATE(pip->cmn.vertex_buffer_layout_active[i], VALIDATE_ABND_VBS);\n                // buffers in vertex-buffer-slots must be of type SG_BUFFERTYPE_VERTEXBUFFER\n                const _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, bindings->vertex_buffers[i].id);\n                _SG_VALIDATE(buf != 0, VALIDATE_ABND_VB_EXISTS);\n                if (buf && buf->slot.state == SG_RESOURCESTATE_VALID) {\n                    _SG_VALIDATE(SG_BUFFERTYPE_VERTEXBUFFER == buf->cmn.type, VALIDATE_ABND_VB_TYPE);\n                    _SG_VALIDATE(!buf->cmn.append_overflow, VALIDATE_ABND_VB_OVERFLOW);\n                }\n            } else {\n                // vertex buffer provided in a slot which has no vertex layout in pipeline\n                _SG_VALIDATE(!pip->cmn.vertex_buffer_layout_active[i], VALIDATE_ABND_VBS);\n            }\n        }\n\n        // index buffer expected or not, and index buffer still exists\n        if (pip->cmn.index_type == SG_INDEXTYPE_NONE) {\n            // pipeline defines non-indexed rendering, but index buffer provided\n            _SG_VALIDATE(bindings->index_buffer.id == SG_INVALID_ID, VALIDATE_ABND_IB);\n        } else {\n            // pipeline defines indexed rendering, but no index buffer provided\n            _SG_VALIDATE(bindings->index_buffer.id != SG_INVALID_ID, VALIDATE_ABND_NO_IB);\n        }\n        if (bindings->index_buffer.id != SG_INVALID_ID) {\n            // buffer in index-buffer-slot must be of type SG_BUFFERTYPE_INDEXBUFFER\n            const _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, bindings->index_buffer.id);\n            _SG_VALIDATE(buf != 0, VALIDATE_ABND_IB_EXISTS);\n            if (buf && buf->slot.state == SG_RESOURCESTATE_VALID) {\n                _SG_VALIDATE(SG_BUFFERTYPE_INDEXBUFFER == buf->cmn.type, VALIDATE_ABND_IB_TYPE);\n                _SG_VALIDATE(!buf->cmn.append_overflow, VALIDATE_ABND_IB_OVERFLOW);\n            }\n        }\n\n        // has expected vertex shader images\n        for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++) {\n            const _sg_shader_stage_t* stage = &pip->shader->cmn.stage[SG_SHADERSTAGE_VS];\n            if (stage->images[i].image_type != _SG_IMAGETYPE_DEFAULT) {\n                _SG_VALIDATE(bindings->vs.images[i].id != SG_INVALID_ID, VALIDATE_ABND_VS_EXPECTED_IMAGE_BINDING);\n                if (bindings->vs.images[i].id != SG_INVALID_ID) {\n                    const _sg_image_t* img = _sg_lookup_image(&_sg.pools, bindings->vs.images[i].id);\n                    _SG_VALIDATE(img != 0, VALIDATE_ABND_VS_IMG_EXISTS);\n                    if (img && img->slot.state == SG_RESOURCESTATE_VALID) {\n                        _SG_VALIDATE(img->cmn.type == stage->images[i].image_type, VALIDATE_ABND_VS_IMAGE_TYPE_MISMATCH);\n                        _SG_VALIDATE(img->cmn.sample_count == 1, VALIDATE_ABND_VS_IMAGE_MSAA);\n                        const _sg_pixelformat_info_t* info = &_sg.formats[img->cmn.pixel_format];\n                        switch (stage->images[i].sample_type) {\n                            case SG_IMAGESAMPLETYPE_FLOAT:\n                                _SG_VALIDATE(info->filter, VALIDATE_ABND_VS_EXPECTED_FILTERABLE_IMAGE);\n                                break;\n                            case SG_IMAGESAMPLETYPE_DEPTH:\n                                _SG_VALIDATE(info->depth, VALIDATE_ABND_VS_EXPECTED_DEPTH_IMAGE);\n                                break;\n                            default:\n                                break;\n                        }\n                    }\n                }\n            } else {\n                _SG_VALIDATE(bindings->vs.images[i].id == SG_INVALID_ID, VALIDATE_ABND_VS_UNEXPECTED_IMAGE_BINDING);\n            }\n        }\n\n        // has expected vertex shader image samplers\n        for (int i = 0; i < SG_MAX_SHADERSTAGE_SAMPLERS; i++) {\n            const _sg_shader_stage_t* stage = &pip->shader->cmn.stage[SG_SHADERSTAGE_VS];\n            if (stage->samplers[i].sampler_type != _SG_SAMPLERTYPE_DEFAULT) {\n                _SG_VALIDATE(bindings->vs.samplers[i].id != SG_INVALID_ID, VALIDATE_ABND_VS_EXPECTED_SAMPLER_BINDING);\n                if (bindings->vs.samplers[i].id != SG_INVALID_ID) {\n                    const _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, bindings->vs.samplers[i].id);\n                    _SG_VALIDATE(smp != 0, VALIDATE_ABND_VS_SMP_EXISTS);\n                    if (smp) {\n                        if (stage->samplers[i].sampler_type == SG_SAMPLERTYPE_COMPARISON) {\n                            _SG_VALIDATE(smp->cmn.compare != SG_COMPAREFUNC_NEVER, VALIDATE_ABND_VS_UNEXPECTED_SAMPLER_COMPARE_NEVER);\n                        } else {\n                            _SG_VALIDATE(smp->cmn.compare == SG_COMPAREFUNC_NEVER, VALIDATE_ABND_VS_EXPECTED_SAMPLER_COMPARE_NEVER);\n                        }\n                        if (stage->samplers[i].sampler_type == SG_SAMPLERTYPE_NONFILTERING) {\n                            const bool nonfiltering = (smp->cmn.min_filter != SG_FILTER_LINEAR)\n                                                   && (smp->cmn.mag_filter != SG_FILTER_LINEAR)\n                                                   && (smp->cmn.mipmap_filter != SG_FILTER_LINEAR);\n                            _SG_VALIDATE(nonfiltering, VALIDATE_ABND_VS_EXPECTED_NONFILTERING_SAMPLER);\n                        }\n                    }\n                }\n            } else {\n                _SG_VALIDATE(bindings->vs.samplers[i].id == SG_INVALID_ID, VALIDATE_ABND_VS_UNEXPECTED_SAMPLER_BINDING);\n            }\n        }\n\n        // has expected vertex shader storage buffers\n        for (int i = 0; i < SG_MAX_SHADERSTAGE_STORAGEBUFFERS; i++) {\n            const _sg_shader_stage_t* stage = &pip->shader->cmn.stage[SG_SHADERSTAGE_VS];\n            if (stage->storage_buffers[i].used) {\n                _SG_VALIDATE(bindings->vs.storage_buffers[i].id != SG_INVALID_ID, VALIDATE_ABND_VS_EXPECTED_STORAGEBUFFER_BINDING);\n                if (bindings->vs.storage_buffers[i].id != SG_INVALID_ID) {\n                    const _sg_buffer_t* sbuf = _sg_lookup_buffer(&_sg.pools, bindings->vs.storage_buffers[i].id);\n                    _SG_VALIDATE(sbuf != 0, VALIDATE_ABND_VS_STORAGEBUFFER_EXISTS);\n                    if (sbuf) {\n                        _SG_VALIDATE(sbuf->cmn.type == SG_BUFFERTYPE_STORAGEBUFFER, VALIDATE_ABND_VS_STORAGEBUFFER_BINDING_BUFFERTYPE);\n                    }\n                }\n            } else {\n                _SG_VALIDATE(bindings->vs.storage_buffers[i].id == SG_INVALID_ID, VALIDATE_ABND_VS_UNEXPECTED_STORAGEBUFFER_BINDING);\n            }\n        }\n\n        // has expected fragment shader images\n        for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++) {\n            const _sg_shader_stage_t* stage = &pip->shader->cmn.stage[SG_SHADERSTAGE_FS];\n            if (stage->images[i].image_type != _SG_IMAGETYPE_DEFAULT) {\n                _SG_VALIDATE(bindings->fs.images[i].id != SG_INVALID_ID, VALIDATE_ABND_FS_EXPECTED_IMAGE_BINDING);\n                if (bindings->fs.images[i].id != SG_INVALID_ID) {\n                    const _sg_image_t* img = _sg_lookup_image(&_sg.pools, bindings->fs.images[i].id);\n                    _SG_VALIDATE(img != 0, VALIDATE_ABND_FS_IMG_EXISTS);\n                    if (img && img->slot.state == SG_RESOURCESTATE_VALID) {\n                        _SG_VALIDATE(img->cmn.type == stage->images[i].image_type, VALIDATE_ABND_FS_IMAGE_TYPE_MISMATCH);\n                        _SG_VALIDATE(img->cmn.sample_count == 1, VALIDATE_ABND_FS_IMAGE_MSAA);\n                        const _sg_pixelformat_info_t* info = &_sg.formats[img->cmn.pixel_format];\n                        switch (stage->images[i].sample_type) {\n                            case SG_IMAGESAMPLETYPE_FLOAT:\n                                _SG_VALIDATE(info->filter, VALIDATE_ABND_FS_EXPECTED_FILTERABLE_IMAGE);\n                                break;\n                            case SG_IMAGESAMPLETYPE_DEPTH:\n                                _SG_VALIDATE(info->depth, VALIDATE_ABND_FS_EXPECTED_DEPTH_IMAGE);\n                                break;\n                            default:\n                                break;\n                        }\n                    }\n                }\n            } else {\n                _SG_VALIDATE(bindings->fs.images[i].id == SG_INVALID_ID, VALIDATE_ABND_FS_UNEXPECTED_IMAGE_BINDING);\n            }\n        }\n\n        // has expected fragment shader samplers\n        for (int i = 0; i < SG_MAX_SHADERSTAGE_SAMPLERS; i++) {\n            const _sg_shader_stage_t* stage = &pip->shader->cmn.stage[SG_SHADERSTAGE_FS];\n            if (stage->samplers[i].sampler_type != _SG_SAMPLERTYPE_DEFAULT) {\n                _SG_VALIDATE(bindings->fs.samplers[i].id != SG_INVALID_ID, VALIDATE_ABND_FS_EXPECTED_SAMPLER_BINDING);\n                if (bindings->fs.samplers[i].id != SG_INVALID_ID) {\n                    const _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, bindings->fs.samplers[i].id);\n                    _SG_VALIDATE(smp != 0, VALIDATE_ABND_FS_SMP_EXISTS);\n                    if (smp) {\n                        if (stage->samplers[i].sampler_type == SG_SAMPLERTYPE_COMPARISON) {\n                            _SG_VALIDATE(smp->cmn.compare != SG_COMPAREFUNC_NEVER, VALIDATE_ABND_FS_UNEXPECTED_SAMPLER_COMPARE_NEVER);\n                        } else {\n                            _SG_VALIDATE(smp->cmn.compare == SG_COMPAREFUNC_NEVER, VALIDATE_ABND_FS_EXPECTED_SAMPLER_COMPARE_NEVER);\n                        }\n                        if (stage->samplers[i].sampler_type == SG_SAMPLERTYPE_NONFILTERING) {\n                            const bool nonfiltering = (smp->cmn.min_filter != SG_FILTER_LINEAR)\n                                                   && (smp->cmn.mag_filter != SG_FILTER_LINEAR)\n                                                   && (smp->cmn.mipmap_filter != SG_FILTER_LINEAR);\n                            _SG_VALIDATE(nonfiltering, VALIDATE_ABND_FS_EXPECTED_NONFILTERING_SAMPLER);\n                        }\n                    }\n                }\n            } else {\n                _SG_VALIDATE(bindings->fs.samplers[i].id == SG_INVALID_ID, VALIDATE_ABND_FS_UNEXPECTED_SAMPLER_BINDING);\n            }\n        }\n\n        // has expected fragment shader storage buffers\n        for (int i = 0; i < SG_MAX_SHADERSTAGE_STORAGEBUFFERS; i++) {\n            const _sg_shader_stage_t* stage = &pip->shader->cmn.stage[SG_SHADERSTAGE_FS];\n            if (stage->storage_buffers[i].used) {\n                _SG_VALIDATE(bindings->fs.storage_buffers[i].id != SG_INVALID_ID, VALIDATE_ABND_FS_EXPECTED_STORAGEBUFFER_BINDING);\n                if (bindings->fs.storage_buffers[i].id != SG_INVALID_ID) {\n                    const _sg_buffer_t* sbuf = _sg_lookup_buffer(&_sg.pools, bindings->fs.storage_buffers[i].id);\n                    _SG_VALIDATE(sbuf != 0, VALIDATE_ABND_FS_STORAGEBUFFER_EXISTS);\n                    if (sbuf) {\n                        _SG_VALIDATE(sbuf->cmn.type == SG_BUFFERTYPE_STORAGEBUFFER, VALIDATE_ABND_FS_STORAGEBUFFER_BINDING_BUFFERTYPE);\n                    }\n                }\n            } else {\n                _SG_VALIDATE(bindings->fs.storage_buffers[i].id == SG_INVALID_ID, VALIDATE_ABND_FS_UNEXPECTED_STORAGEBUFFER_BINDING);\n            }\n        }\n\n        return _sg_validate_end();\n    #endif\n}\n\n_SOKOL_PRIVATE bool _sg_validate_apply_uniforms(sg_shader_stage stage_index, int ub_index, const sg_range* data) {\n    #if !defined(SOKOL_DEBUG)\n        _SOKOL_UNUSED(stage_index);\n        _SOKOL_UNUSED(ub_index);\n        _SOKOL_UNUSED(data);\n        return true;\n    #else\n        if (_sg.desc.disable_validation) {\n            return true;\n        }\n        SOKOL_ASSERT((stage_index == SG_SHADERSTAGE_VS) || (stage_index == SG_SHADERSTAGE_FS));\n        SOKOL_ASSERT((ub_index >= 0) && (ub_index < SG_MAX_SHADERSTAGE_UBS));\n        _sg_validate_begin();\n        _SG_VALIDATE(_sg.cur_pipeline.id != SG_INVALID_ID, VALIDATE_AUB_NO_PIPELINE);\n        const _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, _sg.cur_pipeline.id);\n        SOKOL_ASSERT(pip && (pip->slot.id == _sg.cur_pipeline.id));\n        SOKOL_ASSERT(pip->shader && (pip->shader->slot.id == pip->cmn.shader_id.id));\n\n        // check that there is a uniform block at 'stage' and 'ub_index'\n        const _sg_shader_stage_t* stage = &pip->shader->cmn.stage[stage_index];\n        _SG_VALIDATE(ub_index < stage->num_uniform_blocks, VALIDATE_AUB_NO_UB_AT_SLOT);\n\n        // check that the provided data size matches the uniform block size\n        _SG_VALIDATE(data->size == stage->uniform_blocks[ub_index].size, VALIDATE_AUB_SIZE);\n\n        return _sg_validate_end();\n    #endif\n}\n\n_SOKOL_PRIVATE bool _sg_validate_update_buffer(const _sg_buffer_t* buf, const sg_range* data) {\n    #if !defined(SOKOL_DEBUG)\n        _SOKOL_UNUSED(buf);\n        _SOKOL_UNUSED(data);\n        return true;\n    #else\n        if (_sg.desc.disable_validation) {\n            return true;\n        }\n        SOKOL_ASSERT(buf && data && data->ptr);\n        _sg_validate_begin();\n        _SG_VALIDATE(buf->cmn.usage != SG_USAGE_IMMUTABLE, VALIDATE_UPDATEBUF_USAGE);\n        _SG_VALIDATE(buf->cmn.size >= (int)data->size, VALIDATE_UPDATEBUF_SIZE);\n        _SG_VALIDATE(buf->cmn.update_frame_index != _sg.frame_index, VALIDATE_UPDATEBUF_ONCE);\n        _SG_VALIDATE(buf->cmn.append_frame_index != _sg.frame_index, VALIDATE_UPDATEBUF_APPEND);\n        return _sg_validate_end();\n    #endif\n}\n\n_SOKOL_PRIVATE bool _sg_validate_append_buffer(const _sg_buffer_t* buf, const sg_range* data) {\n    #if !defined(SOKOL_DEBUG)\n        _SOKOL_UNUSED(buf);\n        _SOKOL_UNUSED(data);\n        return true;\n    #else\n        if (_sg.desc.disable_validation) {\n            return true;\n        }\n        SOKOL_ASSERT(buf && data && data->ptr);\n        _sg_validate_begin();\n        _SG_VALIDATE(buf->cmn.usage != SG_USAGE_IMMUTABLE, VALIDATE_APPENDBUF_USAGE);\n        _SG_VALIDATE(buf->cmn.size >= (buf->cmn.append_pos + (int)data->size), VALIDATE_APPENDBUF_SIZE);\n        _SG_VALIDATE(buf->cmn.update_frame_index != _sg.frame_index, VALIDATE_APPENDBUF_UPDATE);\n        return _sg_validate_end();\n    #endif\n}\n\n_SOKOL_PRIVATE bool _sg_validate_update_image(const _sg_image_t* img, const sg_image_data* data) {\n    #if !defined(SOKOL_DEBUG)\n        _SOKOL_UNUSED(img);\n        _SOKOL_UNUSED(data);\n        return true;\n    #else\n        if (_sg.desc.disable_validation) {\n            return true;\n        }\n        SOKOL_ASSERT(img && data);\n        _sg_validate_begin();\n        _SG_VALIDATE(img->cmn.usage != SG_USAGE_IMMUTABLE, VALIDATE_UPDIMG_USAGE);\n        _SG_VALIDATE(img->cmn.upd_frame_index != _sg.frame_index, VALIDATE_UPDIMG_ONCE);\n        _sg_validate_image_data(data,\n            img->cmn.pixel_format,\n            img->cmn.width,\n            img->cmn.height,\n            (img->cmn.type == SG_IMAGETYPE_CUBE) ? 6 : 1,\n            img->cmn.num_mipmaps,\n            img->cmn.num_slices);\n        return _sg_validate_end();\n    #endif\n}\n\n// ██████  ███████ ███████  ██████  ██    ██ ██████   ██████ ███████ ███████\n// ██   ██ ██      ██      ██    ██ ██    ██ ██   ██ ██      ██      ██\n// ██████  █████   ███████ ██    ██ ██    ██ ██████  ██      █████   ███████\n// ██   ██ ██           ██ ██    ██ ██    ██ ██   ██ ██      ██           ██\n// ██   ██ ███████ ███████  ██████   ██████  ██   ██  ██████ ███████ ███████\n//\n// >>resources\n_SOKOL_PRIVATE sg_buffer_desc _sg_buffer_desc_defaults(const sg_buffer_desc* desc) {\n    sg_buffer_desc def = *desc;\n    def.type = _sg_def(def.type, SG_BUFFERTYPE_VERTEXBUFFER);\n    def.usage = _sg_def(def.usage, SG_USAGE_IMMUTABLE);\n    if (def.size == 0) {\n        def.size = def.data.size;\n    } else if (def.data.size == 0) {\n        def.data.size = def.size;\n    }\n    return def;\n}\n\n_SOKOL_PRIVATE sg_image_desc _sg_image_desc_defaults(const sg_image_desc* desc) {\n    sg_image_desc def = *desc;\n    def.type = _sg_def(def.type, SG_IMAGETYPE_2D);\n    def.num_slices = _sg_def(def.num_slices, 1);\n    def.num_mipmaps = _sg_def(def.num_mipmaps, 1);\n    def.usage = _sg_def(def.usage, SG_USAGE_IMMUTABLE);\n    if (desc->render_target) {\n        def.pixel_format = _sg_def(def.pixel_format, _sg.desc.environment.defaults.color_format);\n        def.sample_count = _sg_def(def.sample_count, _sg.desc.environment.defaults.sample_count);\n    } else {\n        def.pixel_format = _sg_def(def.pixel_format, SG_PIXELFORMAT_RGBA8);\n        def.sample_count = _sg_def(def.sample_count, 1);\n    }\n    return def;\n}\n\n_SOKOL_PRIVATE sg_sampler_desc _sg_sampler_desc_defaults(const sg_sampler_desc* desc) {\n    sg_sampler_desc def = *desc;\n    def.min_filter = _sg_def(def.min_filter, SG_FILTER_NEAREST);\n    def.mag_filter = _sg_def(def.mag_filter, SG_FILTER_NEAREST);\n    def.mipmap_filter = _sg_def(def.mipmap_filter, SG_FILTER_NONE);\n    def.wrap_u = _sg_def(def.wrap_u, SG_WRAP_REPEAT);\n    def.wrap_v = _sg_def(def.wrap_v, SG_WRAP_REPEAT);\n    def.wrap_w = _sg_def(def.wrap_w, SG_WRAP_REPEAT);\n    def.max_lod = _sg_def_flt(def.max_lod, FLT_MAX);\n    def.border_color = _sg_def(def.border_color, SG_BORDERCOLOR_OPAQUE_BLACK);\n    def.compare = _sg_def(def.compare, SG_COMPAREFUNC_NEVER);\n    def.max_anisotropy = _sg_def(def.max_anisotropy, 1);\n    return def;\n}\n\n_SOKOL_PRIVATE sg_shader_desc _sg_shader_desc_defaults(const sg_shader_desc* desc) {\n    sg_shader_desc def = *desc;\n    #if defined(SOKOL_METAL)\n        def.vs.entry = _sg_def(def.vs.entry, \"_main\");\n        def.fs.entry = _sg_def(def.fs.entry, \"_main\");\n    #else\n        def.vs.entry = _sg_def(def.vs.entry, \"main\");\n        def.fs.entry = _sg_def(def.fs.entry, \"main\");\n    #endif\n    #if defined(SOKOL_D3D11)\n        if (def.vs.source) {\n            def.vs.d3d11_target = _sg_def(def.vs.d3d11_target, \"vs_4_0\");\n        }\n        if (def.fs.source) {\n            def.fs.d3d11_target = _sg_def(def.fs.d3d11_target, \"ps_4_0\");\n        }\n    #endif\n    for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) {\n        sg_shader_stage_desc* stage_desc = (stage_index == SG_SHADERSTAGE_VS)? &def.vs : &def.fs;\n        for (int ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) {\n            sg_shader_uniform_block_desc* ub_desc = &stage_desc->uniform_blocks[ub_index];\n            if (0 == ub_desc->size) {\n                break;\n            }\n            ub_desc->layout = _sg_def(ub_desc->layout, SG_UNIFORMLAYOUT_NATIVE);\n            for (int u_index = 0; u_index < SG_MAX_UB_MEMBERS; u_index++) {\n                sg_shader_uniform_desc* u_desc = &ub_desc->uniforms[u_index];\n                if (u_desc->type == SG_UNIFORMTYPE_INVALID) {\n                    break;\n                }\n                u_desc->array_count = _sg_def(u_desc->array_count, 1);\n            }\n        }\n        for (int img_index = 0; img_index < SG_MAX_SHADERSTAGE_IMAGES; img_index++) {\n            sg_shader_image_desc* img_desc = &stage_desc->images[img_index];\n            if (!img_desc->used) {\n                break;\n            }\n            img_desc->image_type = _sg_def(img_desc->image_type, SG_IMAGETYPE_2D);\n            img_desc->sample_type = _sg_def(img_desc->sample_type, SG_IMAGESAMPLETYPE_FLOAT);\n        }\n        for (int smp_index = 0; smp_index < SG_MAX_SHADERSTAGE_SAMPLERS; smp_index++) {\n            sg_shader_sampler_desc* smp_desc = &stage_desc->samplers[smp_index];\n            if (!smp_desc->used) {\n                break;\n            }\n            smp_desc->sampler_type = _sg_def(smp_desc->sampler_type, SG_SAMPLERTYPE_FILTERING);\n        }\n    }\n    return def;\n}\n\n_SOKOL_PRIVATE sg_pipeline_desc _sg_pipeline_desc_defaults(const sg_pipeline_desc* desc) {\n    sg_pipeline_desc def = *desc;\n\n    def.primitive_type = _sg_def(def.primitive_type, SG_PRIMITIVETYPE_TRIANGLES);\n    def.index_type = _sg_def(def.index_type, SG_INDEXTYPE_NONE);\n    def.cull_mode = _sg_def(def.cull_mode, SG_CULLMODE_NONE);\n    def.face_winding = _sg_def(def.face_winding, SG_FACEWINDING_CW);\n    def.sample_count = _sg_def(def.sample_count, _sg.desc.environment.defaults.sample_count);\n\n    def.stencil.front.compare = _sg_def(def.stencil.front.compare, SG_COMPAREFUNC_ALWAYS);\n    def.stencil.front.fail_op = _sg_def(def.stencil.front.fail_op, SG_STENCILOP_KEEP);\n    def.stencil.front.depth_fail_op = _sg_def(def.stencil.front.depth_fail_op, SG_STENCILOP_KEEP);\n    def.stencil.front.pass_op = _sg_def(def.stencil.front.pass_op, SG_STENCILOP_KEEP);\n    def.stencil.back.compare = _sg_def(def.stencil.back.compare, SG_COMPAREFUNC_ALWAYS);\n    def.stencil.back.fail_op = _sg_def(def.stencil.back.fail_op, SG_STENCILOP_KEEP);\n    def.stencil.back.depth_fail_op = _sg_def(def.stencil.back.depth_fail_op, SG_STENCILOP_KEEP);\n    def.stencil.back.pass_op = _sg_def(def.stencil.back.pass_op, SG_STENCILOP_KEEP);\n\n    def.depth.compare = _sg_def(def.depth.compare, SG_COMPAREFUNC_ALWAYS);\n    def.depth.pixel_format = _sg_def(def.depth.pixel_format, _sg.desc.environment.defaults.depth_format);\n    if (def.colors[0].pixel_format == SG_PIXELFORMAT_NONE) {\n        // special case depth-only rendering, enforce a color count of 0\n        def.color_count = 0;\n    } else {\n        def.color_count = _sg_def(def.color_count, 1);\n    }\n    if (def.color_count > SG_MAX_COLOR_ATTACHMENTS) {\n        def.color_count = SG_MAX_COLOR_ATTACHMENTS;\n    }\n    for (int i = 0; i < def.color_count; i++) {\n        sg_color_target_state* cs = &def.colors[i];\n        cs->pixel_format = _sg_def(cs->pixel_format, _sg.desc.environment.defaults.color_format);\n        cs->write_mask = _sg_def(cs->write_mask, SG_COLORMASK_RGBA);\n        sg_blend_state* bs = &def.colors[i].blend;\n        bs->src_factor_rgb = _sg_def(bs->src_factor_rgb, SG_BLENDFACTOR_ONE);\n        bs->dst_factor_rgb = _sg_def(bs->dst_factor_rgb, SG_BLENDFACTOR_ZERO);\n        bs->op_rgb = _sg_def(bs->op_rgb, SG_BLENDOP_ADD);\n        bs->src_factor_alpha = _sg_def(bs->src_factor_alpha, SG_BLENDFACTOR_ONE);\n        bs->dst_factor_alpha = _sg_def(bs->dst_factor_alpha, SG_BLENDFACTOR_ZERO);\n        bs->op_alpha = _sg_def(bs->op_alpha, SG_BLENDOP_ADD);\n    }\n\n    for (int attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {\n        sg_vertex_attr_state* a_state = &def.layout.attrs[attr_index];\n        if (a_state->format == SG_VERTEXFORMAT_INVALID) {\n            break;\n        }\n        SOKOL_ASSERT(a_state->buffer_index < SG_MAX_VERTEX_BUFFERS);\n        sg_vertex_buffer_layout_state* l_state = &def.layout.buffers[a_state->buffer_index];\n        l_state->step_func = _sg_def(l_state->step_func, SG_VERTEXSTEP_PER_VERTEX);\n        l_state->step_rate = _sg_def(l_state->step_rate, 1);\n    }\n\n    // resolve vertex layout strides and offsets\n    int auto_offset[SG_MAX_VERTEX_BUFFERS];\n    _sg_clear(auto_offset, sizeof(auto_offset));\n    bool use_auto_offset = true;\n    for (int attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {\n        // to use computed offsets, *all* attr offsets must be 0\n        if (def.layout.attrs[attr_index].offset != 0) {\n            use_auto_offset = false;\n        }\n    }\n    for (int attr_index = 0; attr_index < SG_MAX_VERTEX_ATTRIBUTES; attr_index++) {\n        sg_vertex_attr_state* a_state = &def.layout.attrs[attr_index];\n        if (a_state->format == SG_VERTEXFORMAT_INVALID) {\n            break;\n        }\n        SOKOL_ASSERT(a_state->buffer_index < SG_MAX_VERTEX_BUFFERS);\n        if (use_auto_offset) {\n            a_state->offset = auto_offset[a_state->buffer_index];\n        }\n        auto_offset[a_state->buffer_index] += _sg_vertexformat_bytesize(a_state->format);\n    }\n    // compute vertex strides if needed\n    for (int buf_index = 0; buf_index < SG_MAX_VERTEX_BUFFERS; buf_index++) {\n        sg_vertex_buffer_layout_state* l_state = &def.layout.buffers[buf_index];\n        if (l_state->stride == 0) {\n            l_state->stride = auto_offset[buf_index];\n        }\n    }\n\n    return def;\n}\n\n_SOKOL_PRIVATE sg_attachments_desc _sg_attachments_desc_defaults(const sg_attachments_desc* desc) {\n    sg_attachments_desc def = *desc;\n    return def;\n}\n\n_SOKOL_PRIVATE sg_buffer _sg_alloc_buffer(void) {\n    sg_buffer res;\n    int slot_index = _sg_pool_alloc_index(&_sg.pools.buffer_pool);\n    if (_SG_INVALID_SLOT_INDEX != slot_index) {\n        res.id = _sg_slot_alloc(&_sg.pools.buffer_pool, &_sg.pools.buffers[slot_index].slot, slot_index);\n    } else {\n        res.id = SG_INVALID_ID;\n        _SG_ERROR(BUFFER_POOL_EXHAUSTED);\n    }\n    return res;\n}\n\n_SOKOL_PRIVATE sg_image _sg_alloc_image(void) {\n    sg_image res;\n    int slot_index = _sg_pool_alloc_index(&_sg.pools.image_pool);\n    if (_SG_INVALID_SLOT_INDEX != slot_index) {\n        res.id = _sg_slot_alloc(&_sg.pools.image_pool, &_sg.pools.images[slot_index].slot, slot_index);\n    } else {\n        res.id = SG_INVALID_ID;\n        _SG_ERROR(IMAGE_POOL_EXHAUSTED);\n    }\n    return res;\n}\n\n_SOKOL_PRIVATE sg_sampler _sg_alloc_sampler(void) {\n    sg_sampler res;\n    int slot_index = _sg_pool_alloc_index(&_sg.pools.sampler_pool);\n    if (_SG_INVALID_SLOT_INDEX != slot_index) {\n        res.id = _sg_slot_alloc(&_sg.pools.sampler_pool, &_sg.pools.samplers[slot_index].slot, slot_index);\n    } else {\n        res.id = SG_INVALID_ID;\n        _SG_ERROR(SAMPLER_POOL_EXHAUSTED);\n    }\n    return res;\n}\n\n_SOKOL_PRIVATE sg_shader _sg_alloc_shader(void) {\n    sg_shader res;\n    int slot_index = _sg_pool_alloc_index(&_sg.pools.shader_pool);\n    if (_SG_INVALID_SLOT_INDEX != slot_index) {\n        res.id = _sg_slot_alloc(&_sg.pools.shader_pool, &_sg.pools.shaders[slot_index].slot, slot_index);\n    } else {\n        res.id = SG_INVALID_ID;\n        _SG_ERROR(SHADER_POOL_EXHAUSTED);\n    }\n    return res;\n}\n\n_SOKOL_PRIVATE sg_pipeline _sg_alloc_pipeline(void) {\n    sg_pipeline res;\n    int slot_index = _sg_pool_alloc_index(&_sg.pools.pipeline_pool);\n    if (_SG_INVALID_SLOT_INDEX != slot_index) {\n        res.id =_sg_slot_alloc(&_sg.pools.pipeline_pool, &_sg.pools.pipelines[slot_index].slot, slot_index);\n    } else {\n        res.id = SG_INVALID_ID;\n        _SG_ERROR(PIPELINE_POOL_EXHAUSTED);\n    }\n    return res;\n}\n\n_SOKOL_PRIVATE sg_attachments _sg_alloc_attachments(void) {\n    sg_attachments res;\n    int slot_index = _sg_pool_alloc_index(&_sg.pools.attachments_pool);\n    if (_SG_INVALID_SLOT_INDEX != slot_index) {\n        res.id = _sg_slot_alloc(&_sg.pools.attachments_pool, &_sg.pools.attachments[slot_index].slot, slot_index);\n    } else {\n        res.id = SG_INVALID_ID;\n        _SG_ERROR(PASS_POOL_EXHAUSTED);\n    }\n    return res;\n}\n\n_SOKOL_PRIVATE void _sg_dealloc_buffer(_sg_buffer_t* buf) {\n    SOKOL_ASSERT(buf && (buf->slot.state == SG_RESOURCESTATE_ALLOC) && (buf->slot.id != SG_INVALID_ID));\n    _sg_pool_free_index(&_sg.pools.buffer_pool, _sg_slot_index(buf->slot.id));\n    _sg_reset_slot(&buf->slot);\n}\n\n_SOKOL_PRIVATE void _sg_dealloc_image(_sg_image_t* img) {\n    SOKOL_ASSERT(img && (img->slot.state == SG_RESOURCESTATE_ALLOC) && (img->slot.id != SG_INVALID_ID));\n    _sg_pool_free_index(&_sg.pools.image_pool, _sg_slot_index(img->slot.id));\n    _sg_reset_slot(&img->slot);\n}\n\n_SOKOL_PRIVATE void _sg_dealloc_sampler(_sg_sampler_t* smp) {\n    SOKOL_ASSERT(smp && (smp->slot.state == SG_RESOURCESTATE_ALLOC) && (smp->slot.id != SG_INVALID_ID));\n    _sg_pool_free_index(&_sg.pools.sampler_pool, _sg_slot_index(smp->slot.id));\n    _sg_reset_slot(&smp->slot);\n}\n\n_SOKOL_PRIVATE void _sg_dealloc_shader(_sg_shader_t* shd) {\n    SOKOL_ASSERT(shd && (shd->slot.state == SG_RESOURCESTATE_ALLOC) && (shd->slot.id != SG_INVALID_ID));\n    _sg_pool_free_index(&_sg.pools.shader_pool, _sg_slot_index(shd->slot.id));\n    _sg_reset_slot(&shd->slot);\n}\n\n_SOKOL_PRIVATE void _sg_dealloc_pipeline(_sg_pipeline_t* pip) {\n    SOKOL_ASSERT(pip && (pip->slot.state == SG_RESOURCESTATE_ALLOC) && (pip->slot.id != SG_INVALID_ID));\n    _sg_pool_free_index(&_sg.pools.pipeline_pool, _sg_slot_index(pip->slot.id));\n    _sg_reset_slot(&pip->slot);\n}\n\n_SOKOL_PRIVATE void _sg_dealloc_attachments(_sg_attachments_t* atts) {\n    SOKOL_ASSERT(atts && (atts->slot.state == SG_RESOURCESTATE_ALLOC) && (atts->slot.id != SG_INVALID_ID));\n    _sg_pool_free_index(&_sg.pools.attachments_pool, _sg_slot_index(atts->slot.id));\n    _sg_reset_slot(&atts->slot);\n}\n\n_SOKOL_PRIVATE void _sg_init_buffer(_sg_buffer_t* buf, const sg_buffer_desc* desc) {\n    SOKOL_ASSERT(buf && (buf->slot.state == SG_RESOURCESTATE_ALLOC));\n    SOKOL_ASSERT(desc);\n    if (_sg_validate_buffer_desc(desc)) {\n        _sg_buffer_common_init(&buf->cmn, desc);\n        buf->slot.state = _sg_create_buffer(buf, desc);\n    } else {\n        buf->slot.state = SG_RESOURCESTATE_FAILED;\n    }\n    SOKOL_ASSERT((buf->slot.state == SG_RESOURCESTATE_VALID)||(buf->slot.state == SG_RESOURCESTATE_FAILED));\n}\n\n_SOKOL_PRIVATE void _sg_init_image(_sg_image_t* img, const sg_image_desc* desc) {\n    SOKOL_ASSERT(img && (img->slot.state == SG_RESOURCESTATE_ALLOC));\n    SOKOL_ASSERT(desc);\n    if (_sg_validate_image_desc(desc)) {\n        _sg_image_common_init(&img->cmn, desc);\n        img->slot.state = _sg_create_image(img, desc);\n    } else {\n        img->slot.state = SG_RESOURCESTATE_FAILED;\n    }\n    SOKOL_ASSERT((img->slot.state == SG_RESOURCESTATE_VALID)||(img->slot.state == SG_RESOURCESTATE_FAILED));\n}\n\n_SOKOL_PRIVATE void _sg_init_sampler(_sg_sampler_t* smp, const sg_sampler_desc* desc) {\n    SOKOL_ASSERT(smp && (smp->slot.state == SG_RESOURCESTATE_ALLOC));\n    SOKOL_ASSERT(desc);\n    if (_sg_validate_sampler_desc(desc)) {\n        _sg_sampler_common_init(&smp->cmn, desc);\n        smp->slot.state = _sg_create_sampler(smp, desc);\n    } else {\n        smp->slot.state = SG_RESOURCESTATE_FAILED;\n    }\n    SOKOL_ASSERT((smp->slot.state == SG_RESOURCESTATE_VALID)||(smp->slot.state == SG_RESOURCESTATE_FAILED));\n}\n\n_SOKOL_PRIVATE void _sg_init_shader(_sg_shader_t* shd, const sg_shader_desc* desc) {\n    SOKOL_ASSERT(shd && (shd->slot.state == SG_RESOURCESTATE_ALLOC));\n    SOKOL_ASSERT(desc);\n    if (_sg_validate_shader_desc(desc)) {\n        _sg_shader_common_init(&shd->cmn, desc);\n        shd->slot.state = _sg_create_shader(shd, desc);\n    } else {\n        shd->slot.state = SG_RESOURCESTATE_FAILED;\n    }\n    SOKOL_ASSERT((shd->slot.state == SG_RESOURCESTATE_VALID)||(shd->slot.state == SG_RESOURCESTATE_FAILED));\n}\n\n_SOKOL_PRIVATE void _sg_init_pipeline(_sg_pipeline_t* pip, const sg_pipeline_desc* desc) {\n    SOKOL_ASSERT(pip && (pip->slot.state == SG_RESOURCESTATE_ALLOC));\n    SOKOL_ASSERT(desc);\n    if (_sg_validate_pipeline_desc(desc)) {\n        _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, desc->shader.id);\n        if (shd && (shd->slot.state == SG_RESOURCESTATE_VALID)) {\n            _sg_pipeline_common_init(&pip->cmn, desc);\n            pip->slot.state = _sg_create_pipeline(pip, shd, desc);\n        } else {\n            pip->slot.state = SG_RESOURCESTATE_FAILED;\n        }\n    } else {\n        pip->slot.state = SG_RESOURCESTATE_FAILED;\n    }\n    SOKOL_ASSERT((pip->slot.state == SG_RESOURCESTATE_VALID)||(pip->slot.state == SG_RESOURCESTATE_FAILED));\n}\n\n_SOKOL_PRIVATE void _sg_init_attachments(_sg_attachments_t* atts, const sg_attachments_desc* desc) {\n    SOKOL_ASSERT(atts && atts->slot.state == SG_RESOURCESTATE_ALLOC);\n    SOKOL_ASSERT(desc);\n    if (_sg_validate_attachments_desc(desc)) {\n        // lookup pass attachment image pointers\n        _sg_image_t* color_images[SG_MAX_COLOR_ATTACHMENTS] = { 0 };\n        _sg_image_t* resolve_images[SG_MAX_COLOR_ATTACHMENTS] = { 0 };\n        _sg_image_t* ds_image = 0;\n        // NOTE: validation already checked that all surfaces are same width/height\n        int width = 0;\n        int height = 0;\n        for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {\n            if (desc->colors[i].image.id) {\n                color_images[i] = _sg_lookup_image(&_sg.pools, desc->colors[i].image.id);\n                if (!(color_images[i] && color_images[i]->slot.state == SG_RESOURCESTATE_VALID)) {\n                    atts->slot.state = SG_RESOURCESTATE_FAILED;\n                    return;\n                }\n                const int mip_level = desc->colors[i].mip_level;\n                width = _sg_miplevel_dim(color_images[i]->cmn.width, mip_level);\n                height = _sg_miplevel_dim(color_images[i]->cmn.height, mip_level);\n            }\n            if (desc->resolves[i].image.id) {\n                resolve_images[i] = _sg_lookup_image(&_sg.pools, desc->resolves[i].image.id);\n                if (!(resolve_images[i] && resolve_images[i]->slot.state == SG_RESOURCESTATE_VALID)) {\n                    atts->slot.state = SG_RESOURCESTATE_FAILED;\n                    return;\n                }\n            }\n        }\n        if (desc->depth_stencil.image.id) {\n            ds_image = _sg_lookup_image(&_sg.pools, desc->depth_stencil.image.id);\n            if (!(ds_image && ds_image->slot.state == SG_RESOURCESTATE_VALID)) {\n                atts->slot.state = SG_RESOURCESTATE_FAILED;\n                return;\n            }\n            const int mip_level = desc->depth_stencil.mip_level;\n            width = _sg_miplevel_dim(ds_image->cmn.width, mip_level);\n            height = _sg_miplevel_dim(ds_image->cmn.height, mip_level);\n        }\n        _sg_attachments_common_init(&atts->cmn, desc, width, height);\n        atts->slot.state = _sg_create_attachments(atts, color_images, resolve_images, ds_image, desc);\n    } else {\n        atts->slot.state = SG_RESOURCESTATE_FAILED;\n    }\n    SOKOL_ASSERT((atts->slot.state == SG_RESOURCESTATE_VALID)||(atts->slot.state == SG_RESOURCESTATE_FAILED));\n}\n\n_SOKOL_PRIVATE void _sg_uninit_buffer(_sg_buffer_t* buf) {\n    SOKOL_ASSERT(buf && ((buf->slot.state == SG_RESOURCESTATE_VALID) || (buf->slot.state == SG_RESOURCESTATE_FAILED)));\n    _sg_discard_buffer(buf);\n    _sg_reset_buffer_to_alloc_state(buf);\n}\n\n_SOKOL_PRIVATE void _sg_uninit_image(_sg_image_t* img) {\n    SOKOL_ASSERT(img && ((img->slot.state == SG_RESOURCESTATE_VALID) || (img->slot.state == SG_RESOURCESTATE_FAILED)));\n    _sg_discard_image(img);\n    _sg_reset_image_to_alloc_state(img);\n}\n\n_SOKOL_PRIVATE void _sg_uninit_sampler(_sg_sampler_t* smp) {\n    SOKOL_ASSERT(smp && ((smp->slot.state == SG_RESOURCESTATE_VALID) || (smp->slot.state == SG_RESOURCESTATE_FAILED)));\n    _sg_discard_sampler(smp);\n    _sg_reset_sampler_to_alloc_state(smp);\n}\n\n_SOKOL_PRIVATE void _sg_uninit_shader(_sg_shader_t* shd) {\n    SOKOL_ASSERT(shd && ((shd->slot.state == SG_RESOURCESTATE_VALID) || (shd->slot.state == SG_RESOURCESTATE_FAILED)));\n    _sg_discard_shader(shd);\n    _sg_reset_shader_to_alloc_state(shd);\n}\n\n_SOKOL_PRIVATE void _sg_uninit_pipeline(_sg_pipeline_t* pip) {\n    SOKOL_ASSERT(pip && ((pip->slot.state == SG_RESOURCESTATE_VALID) || (pip->slot.state == SG_RESOURCESTATE_FAILED)));\n    _sg_discard_pipeline(pip);\n    _sg_reset_pipeline_to_alloc_state(pip);\n}\n\n_SOKOL_PRIVATE void _sg_uninit_attachments(_sg_attachments_t* atts) {\n    SOKOL_ASSERT(atts && ((atts->slot.state == SG_RESOURCESTATE_VALID) || (atts->slot.state == SG_RESOURCESTATE_FAILED)));\n    _sg_discard_attachments(atts);\n    _sg_reset_attachments_to_alloc_state(atts);\n}\n\n_SOKOL_PRIVATE void _sg_setup_commit_listeners(const sg_desc* desc) {\n    SOKOL_ASSERT(desc->max_commit_listeners > 0);\n    SOKOL_ASSERT(0 == _sg.commit_listeners.items);\n    SOKOL_ASSERT(0 == _sg.commit_listeners.num);\n    SOKOL_ASSERT(0 == _sg.commit_listeners.upper);\n    _sg.commit_listeners.num = desc->max_commit_listeners;\n    const size_t size = (size_t)_sg.commit_listeners.num * sizeof(sg_commit_listener);\n    _sg.commit_listeners.items = (sg_commit_listener*)_sg_malloc_clear(size);\n}\n\n_SOKOL_PRIVATE void _sg_discard_commit_listeners(void) {\n    SOKOL_ASSERT(0 != _sg.commit_listeners.items);\n    _sg_free(_sg.commit_listeners.items);\n    _sg.commit_listeners.items = 0;\n}\n\n_SOKOL_PRIVATE void _sg_notify_commit_listeners(void) {\n    SOKOL_ASSERT(_sg.commit_listeners.items);\n    for (int i = 0; i < _sg.commit_listeners.upper; i++) {\n        const sg_commit_listener* listener = &_sg.commit_listeners.items[i];\n        if (listener->func) {\n            listener->func(listener->user_data);\n        }\n    }\n}\n\n_SOKOL_PRIVATE bool _sg_add_commit_listener(const sg_commit_listener* new_listener) {\n    SOKOL_ASSERT(new_listener && new_listener->func);\n    SOKOL_ASSERT(_sg.commit_listeners.items);\n    // first check if the listener hadn't been added already\n    for (int i = 0; i < _sg.commit_listeners.upper; i++) {\n        const sg_commit_listener* slot = &_sg.commit_listeners.items[i];\n        if ((slot->func == new_listener->func) && (slot->user_data == new_listener->user_data)) {\n            _SG_ERROR(IDENTICAL_COMMIT_LISTENER);\n            return false;\n        }\n    }\n    // first try to plug a hole\n    sg_commit_listener* slot = 0;\n    for (int i = 0; i < _sg.commit_listeners.upper; i++) {\n        if (_sg.commit_listeners.items[i].func == 0) {\n            slot = &_sg.commit_listeners.items[i];\n            break;\n        }\n    }\n    if (!slot) {\n        // append to end\n        if (_sg.commit_listeners.upper < _sg.commit_listeners.num) {\n            slot = &_sg.commit_listeners.items[_sg.commit_listeners.upper++];\n        }\n    }\n    if (!slot) {\n        _SG_ERROR(COMMIT_LISTENER_ARRAY_FULL);\n        return false;\n    }\n    *slot = *new_listener;\n    return true;\n}\n\n_SOKOL_PRIVATE bool _sg_remove_commit_listener(const sg_commit_listener* listener) {\n    SOKOL_ASSERT(listener && listener->func);\n    SOKOL_ASSERT(_sg.commit_listeners.items);\n    for (int i = 0; i < _sg.commit_listeners.upper; i++) {\n        sg_commit_listener* slot = &_sg.commit_listeners.items[i];\n        // both the function pointer and user data must match!\n        if ((slot->func == listener->func) && (slot->user_data == listener->user_data)) {\n            slot->func = 0;\n            slot->user_data = 0;\n            // NOTE: since _sg_add_commit_listener() already catches duplicates,\n            // we don't need to worry about them here\n            return true;\n        }\n    }\n    return false;\n}\n\n_SOKOL_PRIVATE sg_desc _sg_desc_defaults(const sg_desc* desc) {\n    /*\n        NOTE: on WebGPU, the default color pixel format MUST be provided,\n        cannot be a default compile-time constant.\n    */\n    sg_desc res = *desc;\n    #if defined(SOKOL_WGPU)\n        SOKOL_ASSERT(SG_PIXELFORMAT_NONE < res.environment.defaults.color_format);\n    #elif defined(SOKOL_METAL) || defined(SOKOL_D3D11)\n        res.environment.defaults.color_format = _sg_def(res.environment.defaults.color_format, SG_PIXELFORMAT_BGRA8);\n    #else\n        res.environment.defaults.color_format = _sg_def(res.environment.defaults.color_format, SG_PIXELFORMAT_RGBA8);\n    #endif\n    res.environment.defaults.depth_format = _sg_def(res.environment.defaults.depth_format, SG_PIXELFORMAT_DEPTH_STENCIL);\n    res.environment.defaults.sample_count = _sg_def(res.environment.defaults.sample_count, 1);\n    res.buffer_pool_size = _sg_def(res.buffer_pool_size, _SG_DEFAULT_BUFFER_POOL_SIZE);\n    res.image_pool_size = _sg_def(res.image_pool_size, _SG_DEFAULT_IMAGE_POOL_SIZE);\n    res.sampler_pool_size = _sg_def(res.sampler_pool_size, _SG_DEFAULT_SAMPLER_POOL_SIZE);\n    res.shader_pool_size = _sg_def(res.shader_pool_size, _SG_DEFAULT_SHADER_POOL_SIZE);\n    res.pipeline_pool_size = _sg_def(res.pipeline_pool_size, _SG_DEFAULT_PIPELINE_POOL_SIZE);\n    res.attachments_pool_size = _sg_def(res.attachments_pool_size, _SG_DEFAULT_ATTACHMENTS_POOL_SIZE);\n    res.uniform_buffer_size = _sg_def(res.uniform_buffer_size, _SG_DEFAULT_UB_SIZE);\n    res.max_commit_listeners = _sg_def(res.max_commit_listeners, _SG_DEFAULT_MAX_COMMIT_LISTENERS);\n    res.wgpu_bindgroups_cache_size = _sg_def(res.wgpu_bindgroups_cache_size, _SG_DEFAULT_WGPU_BINDGROUP_CACHE_SIZE);\n    return res;\n}\n\n_SOKOL_PRIVATE sg_pass _sg_pass_defaults(const sg_pass* pass) {\n    sg_pass res = *pass;\n    if (res.attachments.id == SG_INVALID_ID) {\n        // this is a swapchain-pass\n        res.swapchain.sample_count = _sg_def(res.swapchain.sample_count, _sg.desc.environment.defaults.sample_count);\n        res.swapchain.color_format = _sg_def(res.swapchain.color_format, _sg.desc.environment.defaults.color_format);\n        res.swapchain.depth_format = _sg_def(res.swapchain.depth_format, _sg.desc.environment.defaults.depth_format);\n    }\n    res.action = _sg_pass_action_defaults(&res.action);\n    return res;\n}\n\n// ██████  ██    ██ ██████  ██      ██  ██████\n// ██   ██ ██    ██ ██   ██ ██      ██ ██\n// ██████  ██    ██ ██████  ██      ██ ██\n// ██      ██    ██ ██   ██ ██      ██ ██\n// ██       ██████  ██████  ███████ ██  ██████\n//\n// >>public\nSOKOL_API_IMPL void sg_setup(const sg_desc* desc) {\n    SOKOL_ASSERT(desc);\n    SOKOL_ASSERT((desc->_start_canary == 0) && (desc->_end_canary == 0));\n    SOKOL_ASSERT((desc->allocator.alloc_fn && desc->allocator.free_fn) || (!desc->allocator.alloc_fn && !desc->allocator.free_fn));\n    _SG_CLEAR_ARC_STRUCT(_sg_state_t, _sg);\n    _sg.desc = _sg_desc_defaults(desc);\n    _sg_setup_pools(&_sg.pools, &_sg.desc);\n    _sg_setup_commit_listeners(&_sg.desc);\n    _sg.frame_index = 1;\n    _sg.stats_enabled = true;\n    _sg_setup_backend(&_sg.desc);\n    _sg.valid = true;\n}\n\nSOKOL_API_IMPL void sg_shutdown(void) {\n    _sg_discard_all_resources(&_sg.pools);\n    _sg_discard_backend();\n    _sg_discard_commit_listeners();\n    _sg_discard_pools(&_sg.pools);\n    _SG_CLEAR_ARC_STRUCT(_sg_state_t, _sg);\n}\n\nSOKOL_API_IMPL bool sg_isvalid(void) {\n    return _sg.valid;\n}\n\nSOKOL_API_IMPL sg_desc sg_query_desc(void) {\n    SOKOL_ASSERT(_sg.valid);\n    return _sg.desc;\n}\n\nSOKOL_API_IMPL sg_backend sg_query_backend(void) {\n    SOKOL_ASSERT(_sg.valid);\n    return _sg.backend;\n}\n\nSOKOL_API_IMPL sg_features sg_query_features(void) {\n    SOKOL_ASSERT(_sg.valid);\n    return _sg.features;\n}\n\nSOKOL_API_IMPL sg_limits sg_query_limits(void) {\n    SOKOL_ASSERT(_sg.valid);\n    return _sg.limits;\n}\n\nSOKOL_API_IMPL sg_pixelformat_info sg_query_pixelformat(sg_pixel_format fmt) {\n    SOKOL_ASSERT(_sg.valid);\n    int fmt_index = (int) fmt;\n    SOKOL_ASSERT((fmt_index > SG_PIXELFORMAT_NONE) && (fmt_index < _SG_PIXELFORMAT_NUM));\n    const _sg_pixelformat_info_t* src = &_sg.formats[fmt_index];\n    sg_pixelformat_info res;\n    _sg_clear(&res, sizeof(res));\n    res.sample = src->sample;\n    res.filter = src->filter;\n    res.render = src->render;\n    res.blend = src->blend;\n    res.msaa = src->msaa;\n    res.depth = src->depth;\n    res.compressed = _sg_is_compressed_pixel_format(fmt);\n    if (!res.compressed) {\n        res.bytes_per_pixel = _sg_pixelformat_bytesize(fmt);\n    }\n    return res;\n}\n\nSOKOL_API_IMPL int sg_query_row_pitch(sg_pixel_format fmt, int width, int row_align_bytes) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(width > 0);\n    SOKOL_ASSERT((row_align_bytes > 0) && _sg_ispow2(row_align_bytes));\n    SOKOL_ASSERT(((int)fmt > SG_PIXELFORMAT_NONE) && ((int)fmt < _SG_PIXELFORMAT_NUM));\n    return _sg_row_pitch(fmt, width, row_align_bytes);\n}\n\nSOKOL_API_IMPL int sg_query_surface_pitch(sg_pixel_format fmt, int width, int height, int row_align_bytes) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT((width > 0) && (height > 0));\n    SOKOL_ASSERT((row_align_bytes > 0) && _sg_ispow2(row_align_bytes));\n    SOKOL_ASSERT(((int)fmt > SG_PIXELFORMAT_NONE) && ((int)fmt < _SG_PIXELFORMAT_NUM));\n    return _sg_surface_pitch(fmt, width, height, row_align_bytes);\n}\n\nSOKOL_API_IMPL sg_frame_stats sg_query_frame_stats(void) {\n    SOKOL_ASSERT(_sg.valid);\n    return _sg.prev_stats;\n}\n\nSOKOL_API_IMPL sg_trace_hooks sg_install_trace_hooks(const sg_trace_hooks* trace_hooks) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(trace_hooks);\n    _SOKOL_UNUSED(trace_hooks);\n    #if defined(SOKOL_TRACE_HOOKS)\n        sg_trace_hooks old_hooks = _sg.hooks;\n        _sg.hooks = *trace_hooks;\n    #else\n        static sg_trace_hooks old_hooks;\n        _SG_WARN(TRACE_HOOKS_NOT_ENABLED);\n    #endif\n    return old_hooks;\n}\n\nSOKOL_API_IMPL sg_buffer sg_alloc_buffer(void) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_buffer res = _sg_alloc_buffer();\n    _SG_TRACE_ARGS(alloc_buffer, res);\n    return res;\n}\n\nSOKOL_API_IMPL sg_image sg_alloc_image(void) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_image res = _sg_alloc_image();\n    _SG_TRACE_ARGS(alloc_image, res);\n    return res;\n}\n\nSOKOL_API_IMPL sg_sampler sg_alloc_sampler(void) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_sampler res = _sg_alloc_sampler();\n    _SG_TRACE_ARGS(alloc_sampler, res);\n    return res;\n}\n\nSOKOL_API_IMPL sg_shader sg_alloc_shader(void) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_shader res = _sg_alloc_shader();\n    _SG_TRACE_ARGS(alloc_shader, res);\n    return res;\n}\n\nSOKOL_API_IMPL sg_pipeline sg_alloc_pipeline(void) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_pipeline res = _sg_alloc_pipeline();\n    _SG_TRACE_ARGS(alloc_pipeline, res);\n    return res;\n}\n\nSOKOL_API_IMPL sg_attachments sg_alloc_attachments(void) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_attachments res = _sg_alloc_attachments();\n    _SG_TRACE_ARGS(alloc_attachments, res);\n    return res;\n}\n\nSOKOL_API_IMPL void sg_dealloc_buffer(sg_buffer buf_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n    if (buf) {\n        if (buf->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_dealloc_buffer(buf);\n        } else {\n            _SG_ERROR(DEALLOC_BUFFER_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(dealloc_buffer, buf_id);\n}\n\nSOKOL_API_IMPL void sg_dealloc_image(sg_image img_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);\n    if (img) {\n        if (img->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_dealloc_image(img);\n        } else {\n            _SG_ERROR(DEALLOC_IMAGE_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(dealloc_image, img_id);\n}\n\nSOKOL_API_IMPL void sg_dealloc_sampler(sg_sampler smp_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, smp_id.id);\n    if (smp) {\n        if (smp->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_dealloc_sampler(smp);\n        } else {\n            _SG_ERROR(DEALLOC_SAMPLER_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(dealloc_sampler, smp_id);\n}\n\nSOKOL_API_IMPL void sg_dealloc_shader(sg_shader shd_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);\n    if (shd) {\n        if (shd->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_dealloc_shader(shd);\n        } else {\n            _SG_ERROR(DEALLOC_SHADER_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(dealloc_shader, shd_id);\n}\n\nSOKOL_API_IMPL void sg_dealloc_pipeline(sg_pipeline pip_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);\n    if (pip) {\n        if (pip->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_dealloc_pipeline(pip);\n        } else {\n            _SG_ERROR(DEALLOC_PIPELINE_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(dealloc_pipeline, pip_id);\n}\n\nSOKOL_API_IMPL void sg_dealloc_attachments(sg_attachments atts_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_attachments_t* atts = _sg_lookup_attachments(&_sg.pools, atts_id.id);\n    if (atts) {\n        if (atts->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_dealloc_attachments(atts);\n        } else {\n            _SG_ERROR(DEALLOC_ATTACHMENTS_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(dealloc_attachments, atts_id);\n}\n\nSOKOL_API_IMPL void sg_init_buffer(sg_buffer buf_id, const sg_buffer_desc* desc) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_buffer_desc desc_def = _sg_buffer_desc_defaults(desc);\n    _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n    if (buf) {\n        if (buf->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_init_buffer(buf, &desc_def);\n            SOKOL_ASSERT((buf->slot.state == SG_RESOURCESTATE_VALID) || (buf->slot.state == SG_RESOURCESTATE_FAILED));\n        } else {\n            _SG_ERROR(INIT_BUFFER_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(init_buffer, buf_id, &desc_def);\n}\n\nSOKOL_API_IMPL void sg_init_image(sg_image img_id, const sg_image_desc* desc) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_image_desc desc_def = _sg_image_desc_defaults(desc);\n    _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);\n    if (img) {\n        if (img->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_init_image(img, &desc_def);\n            SOKOL_ASSERT((img->slot.state == SG_RESOURCESTATE_VALID) || (img->slot.state == SG_RESOURCESTATE_FAILED));\n        } else {\n            _SG_ERROR(INIT_IMAGE_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(init_image, img_id, &desc_def);\n}\n\nSOKOL_API_IMPL void sg_init_sampler(sg_sampler smp_id, const sg_sampler_desc* desc) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_sampler_desc desc_def = _sg_sampler_desc_defaults(desc);\n    _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, smp_id.id);\n    if (smp) {\n        if (smp->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_init_sampler(smp, &desc_def);\n            SOKOL_ASSERT((smp->slot.state == SG_RESOURCESTATE_VALID) || (smp->slot.state == SG_RESOURCESTATE_FAILED));\n        } else {\n            _SG_ERROR(INIT_SAMPLER_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(init_sampler, smp_id, &desc_def);\n}\n\nSOKOL_API_IMPL void sg_init_shader(sg_shader shd_id, const sg_shader_desc* desc) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_shader_desc desc_def = _sg_shader_desc_defaults(desc);\n    _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);\n    if (shd) {\n        if (shd->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_init_shader(shd, &desc_def);\n            SOKOL_ASSERT((shd->slot.state == SG_RESOURCESTATE_VALID) || (shd->slot.state == SG_RESOURCESTATE_FAILED));\n        } else {\n            _SG_ERROR(INIT_SHADER_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(init_shader, shd_id, &desc_def);\n}\n\nSOKOL_API_IMPL void sg_init_pipeline(sg_pipeline pip_id, const sg_pipeline_desc* desc) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_pipeline_desc desc_def = _sg_pipeline_desc_defaults(desc);\n    _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);\n    if (pip) {\n        if (pip->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_init_pipeline(pip, &desc_def);\n            SOKOL_ASSERT((pip->slot.state == SG_RESOURCESTATE_VALID) || (pip->slot.state == SG_RESOURCESTATE_FAILED));\n        } else {\n            _SG_ERROR(INIT_PIPELINE_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(init_pipeline, pip_id, &desc_def);\n}\n\nSOKOL_API_IMPL void sg_init_attachments(sg_attachments atts_id, const sg_attachments_desc* desc) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_attachments_desc desc_def = _sg_attachments_desc_defaults(desc);\n    _sg_attachments_t* atts = _sg_lookup_attachments(&_sg.pools, atts_id.id);\n    if (atts) {\n        if (atts->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_init_attachments(atts, &desc_def);\n            SOKOL_ASSERT((atts->slot.state == SG_RESOURCESTATE_VALID) || (atts->slot.state == SG_RESOURCESTATE_FAILED));\n        } else {\n            _SG_ERROR(INIT_ATTACHMENTS_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(init_attachments, atts_id, &desc_def);\n}\n\nSOKOL_API_IMPL void sg_uninit_buffer(sg_buffer buf_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n    if (buf) {\n        if ((buf->slot.state == SG_RESOURCESTATE_VALID) || (buf->slot.state == SG_RESOURCESTATE_FAILED)) {\n            _sg_uninit_buffer(buf);\n            SOKOL_ASSERT(buf->slot.state == SG_RESOURCESTATE_ALLOC);\n        } else {\n            _SG_ERROR(UNINIT_BUFFER_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(uninit_buffer, buf_id);\n}\n\nSOKOL_API_IMPL void sg_uninit_image(sg_image img_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);\n    if (img) {\n        if ((img->slot.state == SG_RESOURCESTATE_VALID) || (img->slot.state == SG_RESOURCESTATE_FAILED)) {\n            _sg_uninit_image(img);\n            SOKOL_ASSERT(img->slot.state == SG_RESOURCESTATE_ALLOC);\n        } else {\n            _SG_ERROR(UNINIT_IMAGE_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(uninit_image, img_id);\n}\n\nSOKOL_API_IMPL void sg_uninit_sampler(sg_sampler smp_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, smp_id.id);\n    if (smp) {\n        if ((smp->slot.state == SG_RESOURCESTATE_VALID) || (smp->slot.state == SG_RESOURCESTATE_FAILED)) {\n            _sg_uninit_sampler(smp);\n            SOKOL_ASSERT(smp->slot.state == SG_RESOURCESTATE_ALLOC);\n        } else {\n            _SG_ERROR(UNINIT_SAMPLER_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(uninit_sampler, smp_id);\n}\n\nSOKOL_API_IMPL void sg_uninit_shader(sg_shader shd_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);\n    if (shd) {\n        if ((shd->slot.state == SG_RESOURCESTATE_VALID) || (shd->slot.state == SG_RESOURCESTATE_FAILED)) {\n            _sg_uninit_shader(shd);\n            SOKOL_ASSERT(shd->slot.state == SG_RESOURCESTATE_ALLOC);\n        } else {\n            _SG_ERROR(UNINIT_SHADER_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(uninit_shader, shd_id);\n}\n\nSOKOL_API_IMPL void sg_uninit_pipeline(sg_pipeline pip_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);\n    if (pip) {\n        if ((pip->slot.state == SG_RESOURCESTATE_VALID) || (pip->slot.state == SG_RESOURCESTATE_FAILED)) {\n            _sg_uninit_pipeline(pip);\n            SOKOL_ASSERT(pip->slot.state == SG_RESOURCESTATE_ALLOC);\n        } else {\n            _SG_ERROR(UNINIT_PIPELINE_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(uninit_pipeline, pip_id);\n}\n\nSOKOL_API_IMPL void sg_uninit_attachments(sg_attachments atts_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_attachments_t* atts = _sg_lookup_attachments(&_sg.pools, atts_id.id);\n    if (atts) {\n        if ((atts->slot.state == SG_RESOURCESTATE_VALID) || (atts->slot.state == SG_RESOURCESTATE_FAILED)) {\n            _sg_uninit_attachments(atts);\n            SOKOL_ASSERT(atts->slot.state == SG_RESOURCESTATE_ALLOC);\n        } else {\n            _SG_ERROR(UNINIT_ATTACHMENTS_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(uninit_attachments, atts_id);\n}\n\nSOKOL_API_IMPL void sg_fail_buffer(sg_buffer buf_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n    if (buf) {\n        if (buf->slot.state == SG_RESOURCESTATE_ALLOC) {\n            buf->slot.state = SG_RESOURCESTATE_FAILED;\n        } else {\n            _SG_ERROR(FAIL_BUFFER_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(fail_buffer, buf_id);\n}\n\nSOKOL_API_IMPL void sg_fail_image(sg_image img_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);\n    if (img) {\n        if (img->slot.state == SG_RESOURCESTATE_ALLOC) {\n            img->slot.state = SG_RESOURCESTATE_FAILED;\n        } else {\n            _SG_ERROR(FAIL_IMAGE_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(fail_image, img_id);\n}\n\nSOKOL_API_IMPL void sg_fail_sampler(sg_sampler smp_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, smp_id.id);\n    if (smp) {\n        if (smp->slot.state == SG_RESOURCESTATE_ALLOC) {\n            smp->slot.state = SG_RESOURCESTATE_FAILED;\n        } else {\n            _SG_ERROR(FAIL_SAMPLER_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(fail_sampler, smp_id);\n}\n\nSOKOL_API_IMPL void sg_fail_shader(sg_shader shd_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);\n    if (shd) {\n        if (shd->slot.state == SG_RESOURCESTATE_ALLOC) {\n            shd->slot.state = SG_RESOURCESTATE_FAILED;\n        } else {\n            _SG_ERROR(FAIL_SHADER_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(fail_shader, shd_id);\n}\n\nSOKOL_API_IMPL void sg_fail_pipeline(sg_pipeline pip_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);\n    if (pip) {\n        if (pip->slot.state == SG_RESOURCESTATE_ALLOC) {\n            pip->slot.state = SG_RESOURCESTATE_FAILED;\n        } else {\n            _SG_ERROR(FAIL_PIPELINE_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(fail_pipeline, pip_id);\n}\n\nSOKOL_API_IMPL void sg_fail_attachments(sg_attachments atts_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_attachments_t* atts = _sg_lookup_attachments(&_sg.pools, atts_id.id);\n    if (atts) {\n        if (atts->slot.state == SG_RESOURCESTATE_ALLOC) {\n            atts->slot.state = SG_RESOURCESTATE_FAILED;\n        } else {\n            _SG_ERROR(FAIL_ATTACHMENTS_INVALID_STATE);\n        }\n    }\n    _SG_TRACE_ARGS(fail_attachments, atts_id);\n}\n\nSOKOL_API_IMPL sg_resource_state sg_query_buffer_state(sg_buffer buf_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n    sg_resource_state res = buf ? buf->slot.state : SG_RESOURCESTATE_INVALID;\n    return res;\n}\n\nSOKOL_API_IMPL sg_resource_state sg_query_image_state(sg_image img_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);\n    sg_resource_state res = img ? img->slot.state : SG_RESOURCESTATE_INVALID;\n    return res;\n}\n\nSOKOL_API_IMPL sg_resource_state sg_query_sampler_state(sg_sampler smp_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, smp_id.id);\n    sg_resource_state res = smp ? smp->slot.state : SG_RESOURCESTATE_INVALID;\n    return res;\n}\n\nSOKOL_API_IMPL sg_resource_state sg_query_shader_state(sg_shader shd_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);\n    sg_resource_state res = shd ? shd->slot.state : SG_RESOURCESTATE_INVALID;\n    return res;\n}\n\nSOKOL_API_IMPL sg_resource_state sg_query_pipeline_state(sg_pipeline pip_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);\n    sg_resource_state res = pip ? pip->slot.state : SG_RESOURCESTATE_INVALID;\n    return res;\n}\n\nSOKOL_API_IMPL sg_resource_state sg_query_attachments_state(sg_attachments atts_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_attachments_t* atts = _sg_lookup_attachments(&_sg.pools, atts_id.id);\n    sg_resource_state res = atts ? atts->slot.state : SG_RESOURCESTATE_INVALID;\n    return res;\n}\n\nSOKOL_API_IMPL sg_buffer sg_make_buffer(const sg_buffer_desc* desc) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(desc);\n    sg_buffer_desc desc_def = _sg_buffer_desc_defaults(desc);\n    sg_buffer buf_id = _sg_alloc_buffer();\n    if (buf_id.id != SG_INVALID_ID) {\n        _sg_buffer_t* buf = _sg_buffer_at(&_sg.pools, buf_id.id);\n        SOKOL_ASSERT(buf && (buf->slot.state == SG_RESOURCESTATE_ALLOC));\n        _sg_init_buffer(buf, &desc_def);\n        SOKOL_ASSERT((buf->slot.state == SG_RESOURCESTATE_VALID) || (buf->slot.state == SG_RESOURCESTATE_FAILED));\n    }\n    _SG_TRACE_ARGS(make_buffer, &desc_def, buf_id);\n    return buf_id;\n}\n\nSOKOL_API_IMPL sg_image sg_make_image(const sg_image_desc* desc) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(desc);\n    sg_image_desc desc_def = _sg_image_desc_defaults(desc);\n    sg_image img_id = _sg_alloc_image();\n    if (img_id.id != SG_INVALID_ID) {\n        _sg_image_t* img = _sg_image_at(&_sg.pools, img_id.id);\n        SOKOL_ASSERT(img && (img->slot.state == SG_RESOURCESTATE_ALLOC));\n        _sg_init_image(img, &desc_def);\n        SOKOL_ASSERT((img->slot.state == SG_RESOURCESTATE_VALID) || (img->slot.state == SG_RESOURCESTATE_FAILED));\n    }\n    _SG_TRACE_ARGS(make_image, &desc_def, img_id);\n    return img_id;\n}\n\nSOKOL_API_IMPL sg_sampler sg_make_sampler(const sg_sampler_desc* desc) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(desc);\n    sg_sampler_desc desc_def = _sg_sampler_desc_defaults(desc);\n    sg_sampler smp_id = _sg_alloc_sampler();\n    if (smp_id.id != SG_INVALID_ID) {\n        _sg_sampler_t* smp = _sg_sampler_at(&_sg.pools, smp_id.id);\n        SOKOL_ASSERT(smp && (smp->slot.state == SG_RESOURCESTATE_ALLOC));\n        _sg_init_sampler(smp, &desc_def);\n        SOKOL_ASSERT((smp->slot.state == SG_RESOURCESTATE_VALID) || (smp->slot.state == SG_RESOURCESTATE_FAILED));\n    }\n    _SG_TRACE_ARGS(make_sampler, &desc_def, smp_id);\n    return smp_id;\n}\n\nSOKOL_API_IMPL sg_shader sg_make_shader(const sg_shader_desc* desc) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(desc);\n    sg_shader_desc desc_def = _sg_shader_desc_defaults(desc);\n    sg_shader shd_id = _sg_alloc_shader();\n    if (shd_id.id != SG_INVALID_ID) {\n        _sg_shader_t* shd = _sg_shader_at(&_sg.pools, shd_id.id);\n        SOKOL_ASSERT(shd && (shd->slot.state == SG_RESOURCESTATE_ALLOC));\n        _sg_init_shader(shd, &desc_def);\n        SOKOL_ASSERT((shd->slot.state == SG_RESOURCESTATE_VALID) || (shd->slot.state == SG_RESOURCESTATE_FAILED));\n    }\n    _SG_TRACE_ARGS(make_shader, &desc_def, shd_id);\n    return shd_id;\n}\n\nSOKOL_API_IMPL sg_pipeline sg_make_pipeline(const sg_pipeline_desc* desc) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(desc);\n    sg_pipeline_desc desc_def = _sg_pipeline_desc_defaults(desc);\n    sg_pipeline pip_id = _sg_alloc_pipeline();\n    if (pip_id.id != SG_INVALID_ID) {\n        _sg_pipeline_t* pip = _sg_pipeline_at(&_sg.pools, pip_id.id);\n        SOKOL_ASSERT(pip && (pip->slot.state == SG_RESOURCESTATE_ALLOC));\n        _sg_init_pipeline(pip, &desc_def);\n        SOKOL_ASSERT((pip->slot.state == SG_RESOURCESTATE_VALID) || (pip->slot.state == SG_RESOURCESTATE_FAILED));\n    }\n    _SG_TRACE_ARGS(make_pipeline, &desc_def, pip_id);\n    return pip_id;\n}\n\nSOKOL_API_IMPL sg_attachments sg_make_attachments(const sg_attachments_desc* desc) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(desc);\n    sg_attachments_desc desc_def = _sg_attachments_desc_defaults(desc);\n    sg_attachments atts_id = _sg_alloc_attachments();\n    if (atts_id.id != SG_INVALID_ID) {\n        _sg_attachments_t* atts = _sg_attachments_at(&_sg.pools, atts_id.id);\n        SOKOL_ASSERT(atts && (atts->slot.state == SG_RESOURCESTATE_ALLOC));\n        _sg_init_attachments(atts, &desc_def);\n        SOKOL_ASSERT((atts->slot.state == SG_RESOURCESTATE_VALID) || (atts->slot.state == SG_RESOURCESTATE_FAILED));\n    }\n    _SG_TRACE_ARGS(make_attachments, &desc_def, atts_id);\n    return atts_id;\n}\n\nSOKOL_API_IMPL void sg_destroy_buffer(sg_buffer buf_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _SG_TRACE_ARGS(destroy_buffer, buf_id);\n    _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n    if (buf) {\n        if ((buf->slot.state == SG_RESOURCESTATE_VALID) || (buf->slot.state == SG_RESOURCESTATE_FAILED)) {\n            _sg_uninit_buffer(buf);\n            SOKOL_ASSERT(buf->slot.state == SG_RESOURCESTATE_ALLOC);\n        }\n        if (buf->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_dealloc_buffer(buf);\n            SOKOL_ASSERT(buf->slot.state == SG_RESOURCESTATE_INITIAL);\n        }\n    }\n}\n\nSOKOL_API_IMPL void sg_destroy_image(sg_image img_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _SG_TRACE_ARGS(destroy_image, img_id);\n    _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);\n    if (img) {\n        if ((img->slot.state == SG_RESOURCESTATE_VALID) || (img->slot.state == SG_RESOURCESTATE_FAILED)) {\n            _sg_uninit_image(img);\n            SOKOL_ASSERT(img->slot.state == SG_RESOURCESTATE_ALLOC);\n        }\n        if (img->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_dealloc_image(img);\n            SOKOL_ASSERT(img->slot.state == SG_RESOURCESTATE_INITIAL);\n        }\n    }\n}\n\nSOKOL_API_IMPL void sg_destroy_sampler(sg_sampler smp_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _SG_TRACE_ARGS(destroy_sampler, smp_id);\n    _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, smp_id.id);\n    if (smp) {\n        if ((smp->slot.state == SG_RESOURCESTATE_VALID) || (smp->slot.state == SG_RESOURCESTATE_FAILED)) {\n            _sg_uninit_sampler(smp);\n            SOKOL_ASSERT(smp->slot.state == SG_RESOURCESTATE_ALLOC);\n        }\n        if (smp->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_dealloc_sampler(smp);\n            SOKOL_ASSERT(smp->slot.state == SG_RESOURCESTATE_INITIAL);\n        }\n    }\n}\n\nSOKOL_API_IMPL void sg_destroy_shader(sg_shader shd_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _SG_TRACE_ARGS(destroy_shader, shd_id);\n    _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);\n    if (shd) {\n        if ((shd->slot.state == SG_RESOURCESTATE_VALID) || (shd->slot.state == SG_RESOURCESTATE_FAILED)) {\n            _sg_uninit_shader(shd);\n            SOKOL_ASSERT(shd->slot.state == SG_RESOURCESTATE_ALLOC);\n        }\n        if (shd->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_dealloc_shader(shd);\n            SOKOL_ASSERT(shd->slot.state == SG_RESOURCESTATE_INITIAL);\n        }\n    }\n}\n\nSOKOL_API_IMPL void sg_destroy_pipeline(sg_pipeline pip_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _SG_TRACE_ARGS(destroy_pipeline, pip_id);\n    _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);\n    if (pip) {\n        if ((pip->slot.state == SG_RESOURCESTATE_VALID) || (pip->slot.state == SG_RESOURCESTATE_FAILED)) {\n            _sg_uninit_pipeline(pip);\n            SOKOL_ASSERT(pip->slot.state == SG_RESOURCESTATE_ALLOC);\n        }\n        if (pip->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_dealloc_pipeline(pip);\n            SOKOL_ASSERT(pip->slot.state == SG_RESOURCESTATE_INITIAL);\n        }\n    }\n}\n\nSOKOL_API_IMPL void sg_destroy_attachments(sg_attachments atts_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _SG_TRACE_ARGS(destroy_attachments, atts_id);\n    _sg_attachments_t* atts = _sg_lookup_attachments(&_sg.pools, atts_id.id);\n    if (atts) {\n        if ((atts->slot.state == SG_RESOURCESTATE_VALID) || (atts->slot.state == SG_RESOURCESTATE_FAILED)) {\n            _sg_uninit_attachments(atts);\n            SOKOL_ASSERT(atts->slot.state == SG_RESOURCESTATE_ALLOC);\n        }\n        if (atts->slot.state == SG_RESOURCESTATE_ALLOC) {\n            _sg_dealloc_attachments(atts);\n            SOKOL_ASSERT(atts->slot.state == SG_RESOURCESTATE_INITIAL);\n        }\n    }\n}\n\nSOKOL_API_IMPL void sg_begin_pass(const sg_pass* pass) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(!_sg.cur_pass.valid);\n    SOKOL_ASSERT(!_sg.cur_pass.in_pass);\n    SOKOL_ASSERT(pass);\n    SOKOL_ASSERT((pass->_start_canary == 0) && (pass->_end_canary == 0));\n    const sg_pass pass_def = _sg_pass_defaults(pass);\n    if (!_sg_validate_begin_pass(&pass_def)) {\n        return;\n    }\n    if (pass_def.attachments.id != SG_INVALID_ID) {\n        // an offscreen pass\n        SOKOL_ASSERT(_sg.cur_pass.atts == 0);\n        _sg.cur_pass.atts = _sg_lookup_attachments(&_sg.pools, pass_def.attachments.id);\n        if (0 == _sg.cur_pass.atts) {\n            _SG_ERROR(BEGINPASS_ATTACHMENT_INVALID);\n            return;\n        }\n        _sg.cur_pass.atts_id = pass_def.attachments;\n        _sg.cur_pass.width = _sg.cur_pass.atts->cmn.width;\n        _sg.cur_pass.height = _sg.cur_pass.atts->cmn.height;\n    } else {\n        // a swapchain pass\n        SOKOL_ASSERT(pass_def.swapchain.width > 0);\n        SOKOL_ASSERT(pass_def.swapchain.height > 0);\n        SOKOL_ASSERT(pass_def.swapchain.color_format > SG_PIXELFORMAT_NONE);\n        SOKOL_ASSERT(pass_def.swapchain.sample_count > 0);\n        _sg.cur_pass.width = pass_def.swapchain.width;\n        _sg.cur_pass.height = pass_def.swapchain.height;\n        _sg.cur_pass.swapchain.color_fmt = pass_def.swapchain.color_format;\n        _sg.cur_pass.swapchain.depth_fmt = pass_def.swapchain.depth_format;\n        _sg.cur_pass.swapchain.sample_count = pass_def.swapchain.sample_count;\n    }\n    _sg.cur_pass.valid = true;  // may be overruled by backend begin-pass functions\n    _sg.cur_pass.in_pass = true;\n    _sg_begin_pass(&pass_def);\n    _SG_TRACE_ARGS(begin_pass, &pass_def);\n}\n\nSOKOL_API_IMPL void sg_apply_viewport(int x, int y, int width, int height, bool origin_top_left) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(_sg.cur_pass.in_pass);\n    _sg_stats_add(num_apply_viewport, 1);\n    if (!_sg.cur_pass.valid) {\n        return;\n    }\n    _sg_apply_viewport(x, y, width, height, origin_top_left);\n    _SG_TRACE_ARGS(apply_viewport, x, y, width, height, origin_top_left);\n}\n\nSOKOL_API_IMPL void sg_apply_viewportf(float x, float y, float width, float height, bool origin_top_left) {\n    sg_apply_viewport((int)x, (int)y, (int)width, (int)height, origin_top_left);\n}\n\nSOKOL_API_IMPL void sg_apply_scissor_rect(int x, int y, int width, int height, bool origin_top_left) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(_sg.cur_pass.in_pass);\n    _sg_stats_add(num_apply_scissor_rect, 1);\n    if (!_sg.cur_pass.valid) {\n        return;\n    }\n    _sg_apply_scissor_rect(x, y, width, height, origin_top_left);\n    _SG_TRACE_ARGS(apply_scissor_rect, x, y, width, height, origin_top_left);\n}\n\nSOKOL_API_IMPL void sg_apply_scissor_rectf(float x, float y, float width, float height, bool origin_top_left) {\n    sg_apply_scissor_rect((int)x, (int)y, (int)width, (int)height, origin_top_left);\n}\n\nSOKOL_API_IMPL void sg_apply_pipeline(sg_pipeline pip_id) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(_sg.cur_pass.in_pass);\n    _sg_stats_add(num_apply_pipeline, 1);\n    if (!_sg_validate_apply_pipeline(pip_id)) {\n        _sg.next_draw_valid = false;\n        return;\n    }\n    if (!_sg.cur_pass.valid) {\n        return;\n    }\n    _sg.cur_pipeline = pip_id;\n    _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);\n    SOKOL_ASSERT(pip);\n    _sg.next_draw_valid = (SG_RESOURCESTATE_VALID == pip->slot.state);\n    SOKOL_ASSERT(pip->shader && (pip->shader->slot.id == pip->cmn.shader_id.id));\n    _sg_apply_pipeline(pip);\n    _SG_TRACE_ARGS(apply_pipeline, pip_id);\n}\n\nSOKOL_API_IMPL void sg_apply_bindings(const sg_bindings* bindings) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(_sg.cur_pass.in_pass);\n    SOKOL_ASSERT(bindings);\n    SOKOL_ASSERT((bindings->_start_canary == 0) && (bindings->_end_canary==0));\n    _sg_stats_add(num_apply_bindings, 1);\n    if (!_sg_validate_apply_bindings(bindings)) {\n        _sg.next_draw_valid = false;\n        return;\n    }\n    if (!_sg.cur_pass.valid) {\n        return;\n    }\n\n    _sg_bindings_t bnd;\n    _sg_clear(&bnd, sizeof(bnd));\n    bnd.pip = _sg_lookup_pipeline(&_sg.pools, _sg.cur_pipeline.id);\n    if (0 == bnd.pip) {\n        _sg.next_draw_valid = false;\n    }\n\n    for (int i = 0; i < SG_MAX_VERTEX_BUFFERS; i++, bnd.num_vbs++) {\n        if (bindings->vertex_buffers[i].id) {\n            bnd.vbs[i] = _sg_lookup_buffer(&_sg.pools, bindings->vertex_buffers[i].id);\n            bnd.vb_offsets[i] = bindings->vertex_buffer_offsets[i];\n            if (bnd.vbs[i]) {\n                _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == bnd.vbs[i]->slot.state);\n                _sg.next_draw_valid &= !bnd.vbs[i]->cmn.append_overflow;\n            } else {\n                _sg.next_draw_valid = false;\n            }\n        } else {\n            break;\n        }\n    }\n\n    if (bindings->index_buffer.id) {\n        bnd.ib = _sg_lookup_buffer(&_sg.pools, bindings->index_buffer.id);\n        bnd.ib_offset = bindings->index_buffer_offset;\n        if (bnd.ib) {\n            _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == bnd.ib->slot.state);\n            _sg.next_draw_valid &= !bnd.ib->cmn.append_overflow;\n        } else {\n            _sg.next_draw_valid = false;\n        }\n    }\n\n    for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++, bnd.num_vs_imgs++) {\n        if (bindings->vs.images[i].id) {\n            bnd.vs_imgs[i] = _sg_lookup_image(&_sg.pools, bindings->vs.images[i].id);\n            if (bnd.vs_imgs[i]) {\n                _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == bnd.vs_imgs[i]->slot.state);\n            } else {\n                _sg.next_draw_valid = false;\n            }\n        } else {\n            break;\n        }\n    }\n\n    for (int i = 0; i < SG_MAX_SHADERSTAGE_SAMPLERS; i++, bnd.num_vs_smps++) {\n        if (bindings->vs.samplers[i].id) {\n            bnd.vs_smps[i] = _sg_lookup_sampler(&_sg.pools, bindings->vs.samplers[i].id);\n            if (bnd.vs_smps[i]) {\n                _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == bnd.vs_smps[i]->slot.state);\n            } else {\n                _sg.next_draw_valid = false;\n            }\n        } else {\n            break;\n        }\n    }\n\n    for (int i = 0; i < SG_MAX_SHADERSTAGE_STORAGEBUFFERS; i++, bnd.num_vs_sbufs++) {\n        if (bindings->vs.storage_buffers[i].id) {\n            bnd.vs_sbufs[i] = _sg_lookup_buffer(&_sg.pools, bindings->vs.storage_buffers[i].id);\n            if (bnd.vs_sbufs[i]) {\n                _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == bnd.vs_sbufs[i]->slot.state);\n            } else {\n                _sg.next_draw_valid = false;\n            }\n        } else {\n            break;\n        }\n    }\n\n    for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++, bnd.num_fs_imgs++) {\n        if (bindings->fs.images[i].id) {\n            bnd.fs_imgs[i] = _sg_lookup_image(&_sg.pools, bindings->fs.images[i].id);\n            if (bnd.fs_imgs[i]) {\n                _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == bnd.fs_imgs[i]->slot.state);\n            } else {\n                _sg.next_draw_valid = false;\n            }\n        } else {\n            break;\n        }\n    }\n\n    for (int i = 0; i < SG_MAX_SHADERSTAGE_SAMPLERS; i++, bnd.num_fs_smps++) {\n        if (bindings->fs.samplers[i].id) {\n            bnd.fs_smps[i] = _sg_lookup_sampler(&_sg.pools, bindings->fs.samplers[i].id);\n            if (bnd.fs_smps[i]) {\n                _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == bnd.fs_smps[i]->slot.state);\n            } else {\n                _sg.next_draw_valid = false;\n            }\n        } else {\n            break;\n        }\n    }\n\n    for (int i = 0; i < SG_MAX_SHADERSTAGE_STORAGEBUFFERS; i++, bnd.num_fs_sbufs++) {\n        if (bindings->fs.storage_buffers[i].id) {\n            bnd.fs_sbufs[i] = _sg_lookup_buffer(&_sg.pools, bindings->fs.storage_buffers[i].id);\n            if (bnd.fs_sbufs[i]) {\n                _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == bnd.fs_sbufs[i]->slot.state);\n            } else {\n                _sg.next_draw_valid = false;\n            }\n        } else {\n            break;\n        }\n    }\n    if (_sg.next_draw_valid) {\n        _sg.next_draw_valid &= _sg_apply_bindings(&bnd);\n        _SG_TRACE_ARGS(apply_bindings, bindings);\n    }\n}\n\nSOKOL_API_IMPL void sg_apply_uniforms(sg_shader_stage stage, int ub_index, const sg_range* data) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(_sg.cur_pass.in_pass);\n    SOKOL_ASSERT((stage == SG_SHADERSTAGE_VS) || (stage == SG_SHADERSTAGE_FS));\n    SOKOL_ASSERT((ub_index >= 0) && (ub_index < SG_MAX_SHADERSTAGE_UBS));\n    SOKOL_ASSERT(data && data->ptr && (data->size > 0));\n    _sg_stats_add(num_apply_uniforms, 1);\n    _sg_stats_add(size_apply_uniforms, (uint32_t)data->size);\n    if (!_sg_validate_apply_uniforms(stage, ub_index, data)) {\n        _sg.next_draw_valid = false;\n        return;\n    }\n    if (!_sg.cur_pass.valid) {\n        return;\n    }\n    if (!_sg.next_draw_valid) {\n        return;\n    }\n    _sg_apply_uniforms(stage, ub_index, data);\n    _SG_TRACE_ARGS(apply_uniforms, stage, ub_index, data);\n}\n\nSOKOL_API_IMPL void sg_draw(int base_element, int num_elements, int num_instances) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(_sg.cur_pass.in_pass);\n    SOKOL_ASSERT(base_element >= 0);\n    SOKOL_ASSERT(num_elements >= 0);\n    SOKOL_ASSERT(num_instances >= 0);\n    _sg_stats_add(num_draw, 1);\n    if (!_sg.cur_pass.valid) {\n        return;\n    }\n    if (!_sg.next_draw_valid) {\n        return;\n    }\n    /* attempting to draw with zero elements or instances is not technically an\n       error, but might be handled as an error in the backend API (e.g. on Metal)\n    */\n    if ((0 == num_elements) || (0 == num_instances)) {\n        return;\n    }\n    _sg_draw(base_element, num_elements, num_instances);\n    _SG_TRACE_ARGS(draw, base_element, num_elements, num_instances);\n}\n\nSOKOL_API_IMPL void sg_end_pass(void) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(_sg.cur_pass.in_pass);\n    _sg_stats_add(num_passes, 1);\n    // NOTE: don't exit early if !_sg.cur_pass.valid\n    _sg_end_pass();\n    _sg.cur_pipeline.id = SG_INVALID_ID;\n    _sg_clear(&_sg.cur_pass, sizeof(_sg.cur_pass));\n    _SG_TRACE_NOARGS(end_pass);\n}\n\nSOKOL_API_IMPL void sg_commit(void) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(!_sg.cur_pass.valid);\n    SOKOL_ASSERT(!_sg.cur_pass.in_pass);\n    _sg_commit();\n    _sg.stats.frame_index = _sg.frame_index;\n    _sg.prev_stats = _sg.stats;\n    _sg_clear(&_sg.stats, sizeof(_sg.stats));\n    _sg_notify_commit_listeners();\n    _SG_TRACE_NOARGS(commit);\n    _sg.frame_index++;\n}\n\nSOKOL_API_IMPL void sg_reset_state_cache(void) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_reset_state_cache();\n    _SG_TRACE_NOARGS(reset_state_cache);\n}\n\nSOKOL_API_IMPL void sg_update_buffer(sg_buffer buf_id, const sg_range* data) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(data && data->ptr && (data->size > 0));\n    _sg_stats_add(num_update_buffer, 1);\n    _sg_stats_add(size_update_buffer, (uint32_t)data->size);\n    _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n    if ((data->size > 0) && buf && (buf->slot.state == SG_RESOURCESTATE_VALID)) {\n        if (_sg_validate_update_buffer(buf, data)) {\n            SOKOL_ASSERT(data->size <= (size_t)buf->cmn.size);\n            // only one update allowed per buffer and frame\n            SOKOL_ASSERT(buf->cmn.update_frame_index != _sg.frame_index);\n            // update and append on same buffer in same frame not allowed\n            SOKOL_ASSERT(buf->cmn.append_frame_index != _sg.frame_index);\n            _sg_update_buffer(buf, data);\n            buf->cmn.update_frame_index = _sg.frame_index;\n        }\n    }\n    _SG_TRACE_ARGS(update_buffer, buf_id, data);\n}\n\nSOKOL_API_IMPL int sg_append_buffer(sg_buffer buf_id, const sg_range* data) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(data && data->ptr);\n    _sg_stats_add(num_append_buffer, 1);\n    _sg_stats_add(size_append_buffer, (uint32_t)data->size);\n    _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n    int result;\n    if (buf) {\n        // rewind append cursor in a new frame\n        if (buf->cmn.append_frame_index != _sg.frame_index) {\n            buf->cmn.append_pos = 0;\n            buf->cmn.append_overflow = false;\n        }\n        if (((size_t)buf->cmn.append_pos + data->size) > (size_t)buf->cmn.size) {\n            buf->cmn.append_overflow = true;\n        }\n        const int start_pos = buf->cmn.append_pos;\n        // NOTE: the multiple-of-4 requirement for the buffer offset is coming\n        // from WebGPU, but we want identical behaviour between backends\n        SOKOL_ASSERT(_sg_multiple_u64((uint64_t)start_pos, 4));\n        if (buf->slot.state == SG_RESOURCESTATE_VALID) {\n            if (_sg_validate_append_buffer(buf, data)) {\n                if (!buf->cmn.append_overflow && (data->size > 0)) {\n                    // update and append on same buffer in same frame not allowed\n                    SOKOL_ASSERT(buf->cmn.update_frame_index != _sg.frame_index);\n                    _sg_append_buffer(buf, data, buf->cmn.append_frame_index != _sg.frame_index);\n                    buf->cmn.append_pos += (int) _sg_roundup_u64(data->size, 4);\n                    buf->cmn.append_frame_index = _sg.frame_index;\n                }\n            }\n        }\n        result = start_pos;\n    } else {\n        // FIXME: should we return -1 here?\n        result = 0;\n    }\n    _SG_TRACE_ARGS(append_buffer, buf_id, data, result);\n    return result;\n}\n\nSOKOL_API_IMPL bool sg_query_buffer_overflow(sg_buffer buf_id) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n    bool result = buf ? buf->cmn.append_overflow : false;\n    return result;\n}\n\nSOKOL_API_IMPL bool sg_query_buffer_will_overflow(sg_buffer buf_id, size_t size) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n    bool result = false;\n    if (buf) {\n        int append_pos = buf->cmn.append_pos;\n        // rewind append cursor in a new frame\n        if (buf->cmn.append_frame_index != _sg.frame_index) {\n            append_pos = 0;\n        }\n        if ((append_pos + _sg_roundup((int)size, 4)) > buf->cmn.size) {\n            result = true;\n        }\n    }\n    return result;\n}\n\nSOKOL_API_IMPL void sg_update_image(sg_image img_id, const sg_image_data* data) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_stats_add(num_update_image, 1);\n    for (int face_index = 0; face_index < SG_CUBEFACE_NUM; face_index++) {\n        for (int mip_index = 0; mip_index < SG_MAX_MIPMAPS; mip_index++) {\n            if (data->subimage[face_index][mip_index].size == 0) {\n                break;\n            }\n            _sg_stats_add(size_update_image, (uint32_t)data->subimage[face_index][mip_index].size);\n        }\n    }\n    _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);\n    if (img && img->slot.state == SG_RESOURCESTATE_VALID) {\n        if (_sg_validate_update_image(img, data)) {\n            SOKOL_ASSERT(img->cmn.upd_frame_index != _sg.frame_index);\n            _sg_update_image(img, data);\n            img->cmn.upd_frame_index = _sg.frame_index;\n        }\n    }\n    _SG_TRACE_ARGS(update_image, img_id, data);\n}\n\nSOKOL_API_IMPL void sg_push_debug_group(const char* name) {\n    SOKOL_ASSERT(_sg.valid);\n    SOKOL_ASSERT(name);\n    _sg_push_debug_group(name);\n    _SG_TRACE_ARGS(push_debug_group, name);\n}\n\nSOKOL_API_IMPL void sg_pop_debug_group(void) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg_pop_debug_group();\n    _SG_TRACE_NOARGS(pop_debug_group);\n}\n\nSOKOL_API_IMPL bool sg_add_commit_listener(sg_commit_listener listener) {\n    SOKOL_ASSERT(_sg.valid);\n    return _sg_add_commit_listener(&listener);\n}\n\nSOKOL_API_IMPL bool sg_remove_commit_listener(sg_commit_listener listener) {\n    SOKOL_ASSERT(_sg.valid);\n    return _sg_remove_commit_listener(&listener);\n}\n\nSOKOL_API_IMPL void sg_enable_frame_stats(void) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg.stats_enabled = true;\n}\n\nSOKOL_API_IMPL void sg_disable_frame_stats(void) {\n    SOKOL_ASSERT(_sg.valid);\n    _sg.stats_enabled = false;\n}\n\nSOKOL_API_IMPL bool sg_frame_stats_enabled(void) {\n    return _sg.stats_enabled;\n}\n\nSOKOL_API_IMPL sg_buffer_info sg_query_buffer_info(sg_buffer buf_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_buffer_info info;\n    _sg_clear(&info, sizeof(info));\n    const _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n    if (buf) {\n        info.slot.state = buf->slot.state;\n        info.slot.res_id = buf->slot.id;\n        info.update_frame_index = buf->cmn.update_frame_index;\n        info.append_frame_index = buf->cmn.append_frame_index;\n        info.append_pos = buf->cmn.append_pos;\n        info.append_overflow = buf->cmn.append_overflow;\n        #if defined(SOKOL_D3D11)\n        info.num_slots = 1;\n        info.active_slot = 0;\n        #else\n        info.num_slots = buf->cmn.num_slots;\n        info.active_slot = buf->cmn.active_slot;\n        #endif\n    }\n    return info;\n}\n\nSOKOL_API_IMPL sg_image_info sg_query_image_info(sg_image img_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_image_info info;\n    _sg_clear(&info, sizeof(info));\n    const _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);\n    if (img) {\n        info.slot.state = img->slot.state;\n        info.slot.res_id = img->slot.id;\n        info.upd_frame_index = img->cmn.upd_frame_index;\n        #if defined(SOKOL_D3D11)\n        info.num_slots = 1;\n        info.active_slot = 0;\n        #else\n        info.num_slots = img->cmn.num_slots;\n        info.active_slot = img->cmn.active_slot;\n        #endif\n    }\n    return info;\n}\n\nSOKOL_API_IMPL sg_sampler_info sg_query_sampler_info(sg_sampler smp_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_sampler_info info;\n    _sg_clear(&info, sizeof(info));\n    const _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, smp_id.id);\n    if (smp) {\n        info.slot.state = smp->slot.state;\n        info.slot.res_id = smp->slot.id;\n    }\n    return info;\n}\n\nSOKOL_API_IMPL sg_shader_info sg_query_shader_info(sg_shader shd_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_shader_info info;\n    _sg_clear(&info, sizeof(info));\n    const _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);\n    if (shd) {\n        info.slot.state = shd->slot.state;\n        info.slot.res_id = shd->slot.id;\n    }\n    return info;\n}\n\nSOKOL_API_IMPL sg_pipeline_info sg_query_pipeline_info(sg_pipeline pip_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_pipeline_info info;\n    _sg_clear(&info, sizeof(info));\n    const _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);\n    if (pip) {\n        info.slot.state = pip->slot.state;\n        info.slot.res_id = pip->slot.id;\n    }\n    return info;\n}\n\nSOKOL_API_IMPL sg_attachments_info sg_query_attachments_info(sg_attachments atts_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_attachments_info info;\n    _sg_clear(&info, sizeof(info));\n    const _sg_attachments_t* atts = _sg_lookup_attachments(&_sg.pools, atts_id.id);\n    if (atts) {\n        info.slot.state = atts->slot.state;\n        info.slot.res_id = atts->slot.id;\n    }\n    return info;\n}\n\nSOKOL_API_IMPL sg_buffer_desc sg_query_buffer_desc(sg_buffer buf_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_buffer_desc desc;\n    _sg_clear(&desc, sizeof(desc));\n    const _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n    if (buf) {\n        desc.size = (size_t)buf->cmn.size;\n        desc.type = buf->cmn.type;\n        desc.usage = buf->cmn.usage;\n    }\n    return desc;\n}\n\nSOKOL_API_IMPL sg_image_desc sg_query_image_desc(sg_image img_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_image_desc desc;\n    _sg_clear(&desc, sizeof(desc));\n    const _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);\n    if (img) {\n        desc.type = img->cmn.type;\n        desc.render_target = img->cmn.render_target;\n        desc.width = img->cmn.width;\n        desc.height = img->cmn.height;\n        desc.num_slices = img->cmn.num_slices;\n        desc.num_mipmaps = img->cmn.num_mipmaps;\n        desc.usage = img->cmn.usage;\n        desc.pixel_format = img->cmn.pixel_format;\n        desc.sample_count = img->cmn.sample_count;\n    }\n    return desc;\n}\n\nSOKOL_API_IMPL sg_sampler_desc sg_query_sampler_desc(sg_sampler smp_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_sampler_desc desc;\n    _sg_clear(&desc, sizeof(desc));\n    const _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, smp_id.id);\n    if (smp) {\n        desc.min_filter = smp->cmn.min_filter;\n        desc.mag_filter = smp->cmn.mag_filter;\n        desc.mipmap_filter = smp->cmn.mipmap_filter;\n        desc.wrap_u = smp->cmn.wrap_u;\n        desc.wrap_v = smp->cmn.wrap_v;\n        desc.wrap_w = smp->cmn.wrap_w;\n        desc.min_lod = smp->cmn.min_lod;\n        desc.max_lod = smp->cmn.max_lod;\n        desc.border_color = smp->cmn.border_color;\n        desc.compare = smp->cmn.compare;\n        desc.max_anisotropy = smp->cmn.max_anisotropy;\n    }\n    return desc;\n}\n\nSOKOL_API_IMPL sg_shader_desc sg_query_shader_desc(sg_shader shd_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_shader_desc desc;\n    _sg_clear(&desc, sizeof(desc));\n    const _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);\n    if (shd) {\n        for (int stage_idx = 0; stage_idx < SG_NUM_SHADER_STAGES; stage_idx++) {\n            sg_shader_stage_desc* stage_desc = (stage_idx == 0) ? &desc.vs : &desc.fs;\n            const _sg_shader_stage_t* stage = &shd->cmn.stage[stage_idx];\n            for (int ub_idx = 0; ub_idx < stage->num_uniform_blocks; ub_idx++) {\n                sg_shader_uniform_block_desc* ub_desc = &stage_desc->uniform_blocks[ub_idx];\n                const _sg_shader_uniform_block_t* ub = &stage->uniform_blocks[ub_idx];\n                ub_desc->size = ub->size;\n            }\n            for (int img_idx = 0; img_idx < stage->num_images; img_idx++) {\n                sg_shader_image_desc* img_desc = &stage_desc->images[img_idx];\n                const _sg_shader_image_t* img = &stage->images[img_idx];\n                img_desc->used = true;\n                img_desc->image_type = img->image_type;\n                img_desc->sample_type = img->sample_type;\n                img_desc->multisampled = img->multisampled;\n            }\n            for (int smp_idx = 0; smp_idx < stage->num_samplers; smp_idx++) {\n                sg_shader_sampler_desc* smp_desc = &stage_desc->samplers[smp_idx];\n                const _sg_shader_sampler_t* smp = &stage->samplers[smp_idx];\n                smp_desc->used = true;\n                smp_desc->sampler_type = smp->sampler_type;\n            }\n            for (int img_smp_idx = 0; img_smp_idx < stage->num_image_samplers; img_smp_idx++) {\n                sg_shader_image_sampler_pair_desc* img_smp_desc = &stage_desc->image_sampler_pairs[img_smp_idx];\n                const _sg_shader_image_sampler_t* img_smp = &stage->image_samplers[img_smp_idx];\n                img_smp_desc->used = true;\n                img_smp_desc->image_slot = img_smp->image_slot;\n                img_smp_desc->sampler_slot = img_smp->sampler_slot;\n                img_smp_desc->glsl_name = 0;\n            }\n        }\n    }\n    return desc;\n}\n\nSOKOL_API_IMPL sg_pipeline_desc sg_query_pipeline_desc(sg_pipeline pip_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_pipeline_desc desc;\n    _sg_clear(&desc, sizeof(desc));\n    const _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);\n    if (pip) {\n        desc.shader = pip->cmn.shader_id;\n        desc.layout = pip->cmn.layout;\n        desc.depth = pip->cmn.depth;\n        desc.stencil = pip->cmn.stencil;\n        desc.color_count = pip->cmn.color_count;\n        for (int i = 0; i < pip->cmn.color_count; i++) {\n            desc.colors[i] = pip->cmn.colors[i];\n        }\n        desc.primitive_type = pip->cmn.primitive_type;\n        desc.index_type = pip->cmn.index_type;\n        desc.cull_mode = pip->cmn.cull_mode;\n        desc.face_winding = pip->cmn.face_winding;\n        desc.sample_count = pip->cmn.sample_count;\n        desc.blend_color = pip->cmn.blend_color;\n        desc.alpha_to_coverage_enabled = pip->cmn.alpha_to_coverage_enabled;\n    }\n    return desc;\n}\n\nSOKOL_API_IMPL sg_attachments_desc sg_query_attachments_desc(sg_attachments atts_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_attachments_desc desc;\n    _sg_clear(&desc, sizeof(desc));\n    const _sg_attachments_t* atts = _sg_lookup_attachments(&_sg.pools, atts_id.id);\n    if (atts) {\n        for (int i = 0; i < atts->cmn.num_colors; i++) {\n            desc.colors[i].image = atts->cmn.colors[i].image_id;\n            desc.colors[i].mip_level = atts->cmn.colors[i].mip_level;\n            desc.colors[i].slice = atts->cmn.colors[i].slice;\n        }\n        desc.depth_stencil.image = atts->cmn.depth_stencil.image_id;\n        desc.depth_stencil.mip_level = atts->cmn.depth_stencil.mip_level;\n        desc.depth_stencil.slice = atts->cmn.depth_stencil.slice;\n    }\n    return desc;\n}\n\nSOKOL_API_IMPL sg_buffer_desc sg_query_buffer_defaults(const sg_buffer_desc* desc) {\n    SOKOL_ASSERT(_sg.valid && desc);\n    return _sg_buffer_desc_defaults(desc);\n}\n\nSOKOL_API_IMPL sg_image_desc sg_query_image_defaults(const sg_image_desc* desc) {\n    SOKOL_ASSERT(_sg.valid && desc);\n    return _sg_image_desc_defaults(desc);\n}\n\nSOKOL_API_IMPL sg_sampler_desc sg_query_sampler_defaults(const sg_sampler_desc* desc) {\n    SOKOL_ASSERT(_sg.valid && desc);\n    return _sg_sampler_desc_defaults(desc);\n}\n\nSOKOL_API_IMPL sg_shader_desc sg_query_shader_defaults(const sg_shader_desc* desc) {\n    SOKOL_ASSERT(_sg.valid && desc);\n    return _sg_shader_desc_defaults(desc);\n}\n\nSOKOL_API_IMPL sg_pipeline_desc sg_query_pipeline_defaults(const sg_pipeline_desc* desc) {\n    SOKOL_ASSERT(_sg.valid && desc);\n    return _sg_pipeline_desc_defaults(desc);\n}\n\nSOKOL_API_IMPL sg_attachments_desc sg_query_attachments_defaults(const sg_attachments_desc* desc) {\n    SOKOL_ASSERT(_sg.valid && desc);\n    return _sg_attachments_desc_defaults(desc);\n}\n\nSOKOL_API_IMPL const void* sg_d3d11_device(void) {\n    #if defined(SOKOL_D3D11)\n        return (const void*) _sg.d3d11.dev;\n    #else\n        return 0;\n    #endif\n}\n\nSOKOL_API_IMPL const void* sg_d3d11_device_context(void) {\n    #if defined(SOKOL_D3D11)\n        return (const void*) _sg.d3d11.ctx;\n    #else\n        return 0;\n    #endif\n}\n\nSOKOL_API_IMPL sg_d3d11_buffer_info sg_d3d11_query_buffer_info(sg_buffer buf_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_d3d11_buffer_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_D3D11)\n        const _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n        if (buf) {\n            res.buf = (const void*) buf->d3d11.buf;\n        }\n    #else\n        _SOKOL_UNUSED(buf_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_d3d11_image_info sg_d3d11_query_image_info(sg_image img_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_d3d11_image_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_D3D11)\n        const _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);\n        if (img) {\n            res.tex2d = (const void*) img->d3d11.tex2d;\n            res.tex3d = (const void*) img->d3d11.tex3d;\n            res.res = (const void*) img->d3d11.res;\n            res.srv = (const void*) img->d3d11.srv;\n        }\n    #else\n        _SOKOL_UNUSED(img_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_d3d11_sampler_info sg_d3d11_query_sampler_info(sg_sampler smp_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_d3d11_sampler_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_D3D11)\n        const _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, smp_id.id);\n        if (smp) {\n            res.smp = (const void*) smp->d3d11.smp;\n        }\n    #else\n        _SOKOL_UNUSED(smp_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_d3d11_shader_info sg_d3d11_query_shader_info(sg_shader shd_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_d3d11_shader_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_D3D11)\n        const _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);\n        if (shd) {\n            for (int i = 0; i < SG_MAX_SHADERSTAGE_UBS; i++) {\n                res.vs_cbufs[i] = (const void*) shd->d3d11.stage[SG_SHADERSTAGE_VS].cbufs[i];\n                res.fs_cbufs[i] = (const void*) shd->d3d11.stage[SG_SHADERSTAGE_FS].cbufs[i];\n            }\n            res.vs = (const void*) shd->d3d11.vs;\n            res.fs = (const void*) shd->d3d11.fs;\n        }\n    #else\n        _SOKOL_UNUSED(shd_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_d3d11_pipeline_info sg_d3d11_query_pipeline_info(sg_pipeline pip_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_d3d11_pipeline_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_D3D11)\n        const _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);\n        if (pip) {\n            res.il = (const void*) pip->d3d11.il;\n            res.rs = (const void*) pip->d3d11.rs;\n            res.dss = (const void*) pip->d3d11.dss;\n            res.bs = (const void*) pip->d3d11.bs;\n        }\n    #else\n        _SOKOL_UNUSED(pip_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_d3d11_attachments_info sg_d3d11_query_attachments_info(sg_attachments atts_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_d3d11_attachments_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_D3D11)\n        const _sg_attachments_t* atts = _sg_lookup_attachments(&_sg.pools, atts_id.id);\n        if (atts) {\n            for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {\n                res.color_rtv[i] = (const void*) atts->d3d11.colors[i].view.rtv;\n                res.resolve_rtv[i] = (const void*) atts->d3d11.resolves[i].view.rtv;\n            }\n            res.dsv = (const void*) atts->d3d11.depth_stencil.view.dsv;\n        }\n    #else\n        _SOKOL_UNUSED(atts_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL const void* sg_mtl_device(void) {\n    #if defined(SOKOL_METAL)\n        if (nil != _sg.mtl.device) {\n            return (__bridge const void*) _sg.mtl.device;\n        } else {\n            return 0;\n        }\n    #else\n        return 0;\n    #endif\n}\n\nSOKOL_API_IMPL const void* sg_mtl_render_command_encoder(void) {\n    #if defined(SOKOL_METAL)\n        if (nil != _sg.mtl.cmd_encoder) {\n            return (__bridge const void*) _sg.mtl.cmd_encoder;\n        } else {\n            return 0;\n        }\n    #else\n        return 0;\n    #endif\n}\n\nSOKOL_API_IMPL sg_mtl_buffer_info sg_mtl_query_buffer_info(sg_buffer buf_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_mtl_buffer_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_METAL)\n        const _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n        if (buf) {\n            for (int i = 0; i < SG_NUM_INFLIGHT_FRAMES; i++) {\n                if (buf->mtl.buf[i] != 0) {\n                    res.buf[i] = (__bridge void*) _sg_mtl_id(buf->mtl.buf[i]);\n                }\n            }\n            res.active_slot = buf->cmn.active_slot;\n        }\n    #else\n        _SOKOL_UNUSED(buf_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_mtl_image_info sg_mtl_query_image_info(sg_image img_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_mtl_image_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_METAL)\n        const _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);\n        if (img) {\n            for (int i = 0; i < SG_NUM_INFLIGHT_FRAMES; i++) {\n                if (img->mtl.tex[i] != 0) {\n                    res.tex[i] = (__bridge void*) _sg_mtl_id(img->mtl.tex[i]);\n                }\n            }\n            res.active_slot = img->cmn.active_slot;\n        }\n    #else\n        _SOKOL_UNUSED(img_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_mtl_sampler_info sg_mtl_query_sampler_info(sg_sampler smp_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_mtl_sampler_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_METAL)\n        const _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, smp_id.id);\n        if (smp) {\n            if (smp->mtl.sampler_state != 0) {\n                res.smp = (__bridge void*) _sg_mtl_id(smp->mtl.sampler_state);\n            }\n        }\n    #else\n        _SOKOL_UNUSED(smp_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_mtl_shader_info sg_mtl_query_shader_info(sg_shader shd_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_mtl_shader_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_METAL)\n        const _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);\n        if (shd) {\n            const int vs_lib  = shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_lib;\n            const int vs_func = shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_func;\n            const int fs_lib  = shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_lib;\n            const int fs_func = shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_func;\n            if (vs_lib != 0) {\n                res.vs_lib = (__bridge void*) _sg_mtl_id(vs_lib);\n            }\n            if (fs_lib != 0) {\n                res.fs_lib = (__bridge void*) _sg_mtl_id(fs_lib);\n            }\n            if (vs_func != 0) {\n                res.vs_func = (__bridge void*) _sg_mtl_id(vs_func);\n            }\n            if (fs_func != 0) {\n                res.fs_func = (__bridge void*) _sg_mtl_id(fs_func);\n            }\n        }\n    #else\n        _SOKOL_UNUSED(shd_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_mtl_pipeline_info sg_mtl_query_pipeline_info(sg_pipeline pip_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_mtl_pipeline_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_METAL)\n        const _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);\n        if (pip) {\n            if (pip->mtl.rps != 0) {\n                res.rps = (__bridge void*) _sg_mtl_id(pip->mtl.rps);\n            }\n            if (pip->mtl.dss != 0) {\n                res.dss = (__bridge void*) _sg_mtl_id(pip->mtl.dss);\n            }\n        }\n    #else\n        _SOKOL_UNUSED(pip_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL const void* sg_wgpu_device(void) {\n    #if defined(SOKOL_WGPU)\n        return (const void*) _sg.wgpu.dev;\n    #else\n        return 0;\n    #endif\n}\n\nSOKOL_API_IMPL const void* sg_wgpu_queue(void) {\n    #if defined(SOKOL_WGPU)\n        return (const void*) _sg.wgpu.queue;\n    #else\n        return 0;\n    #endif\n}\n\nSOKOL_API_IMPL const void* sg_wgpu_command_encoder(void) {\n    #if defined(SOKOL_WGPU)\n        return (const void*) _sg.wgpu.cmd_enc;\n    #else\n        return 0;\n    #endif\n}\n\nSOKOL_API_IMPL const void* sg_wgpu_render_pass_encoder(void) {\n    #if defined(SOKOL_WGPU)\n        return (const void*) _sg.wgpu.pass_enc;\n    #else\n        return 0;\n    #endif\n}\n\nSOKOL_API_IMPL sg_wgpu_buffer_info sg_wgpu_query_buffer_info(sg_buffer buf_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_wgpu_buffer_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_WGPU)\n        const _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n        if (buf) {\n            res.buf = (const void*) buf->wgpu.buf;\n        }\n    #else\n        _SOKOL_UNUSED(buf_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_wgpu_image_info sg_wgpu_query_image_info(sg_image img_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_wgpu_image_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_WGPU)\n        const _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);\n        if (img) {\n            res.tex = (const void*) img->wgpu.tex;\n            res.view = (const void*) img->wgpu.view;\n        }\n    #else\n        _SOKOL_UNUSED(img_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_wgpu_sampler_info sg_wgpu_query_sampler_info(sg_sampler smp_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_wgpu_sampler_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_WGPU)\n        const _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, smp_id.id);\n        if (smp) {\n            res.smp = (const void*) smp->wgpu.smp;\n        }\n    #else\n        _SOKOL_UNUSED(smp_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_wgpu_shader_info sg_wgpu_query_shader_info(sg_shader shd_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_wgpu_shader_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_WGPU)\n        const _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);\n        if (shd) {\n            res.vs_mod = (const void*) shd->wgpu.stage[SG_SHADERSTAGE_VS].module;\n            res.fs_mod = (const void*) shd->wgpu.stage[SG_SHADERSTAGE_FS].module;\n            res.bgl = (const void*) shd->wgpu.bind_group_layout;\n        }\n    #else\n        _SOKOL_UNUSED(shd_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_wgpu_pipeline_info sg_wgpu_query_pipeline_info(sg_pipeline pip_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_wgpu_pipeline_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_WGPU)\n        const _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, pip_id.id);\n        if (pip) {\n            res.pip = (const void*) pip->wgpu.pip;\n        }\n    #else\n        _SOKOL_UNUSED(pip_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_wgpu_attachments_info sg_wgpu_query_attachments_info(sg_attachments atts_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_wgpu_attachments_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(SOKOL_WGPU)\n        const _sg_attachments_t* atts = _sg_lookup_attachments(&_sg.pools, atts_id.id);\n        if (atts) {\n            for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {\n                res.color_view[i] = (const void*) atts->wgpu.colors[i].view;\n                res.resolve_view[i] = (const void*) atts->wgpu.resolves[i].view;\n            }\n            res.ds_view = (const void*) atts->wgpu.depth_stencil.view;\n        }\n    #else\n        _SOKOL_UNUSED(atts_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_gl_buffer_info sg_gl_query_buffer_info(sg_buffer buf_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_gl_buffer_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(_SOKOL_ANY_GL)\n        const _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id);\n        if (buf) {\n            for (int i = 0; i < SG_NUM_INFLIGHT_FRAMES; i++) {\n                res.buf[i] = buf->gl.buf[i];\n            }\n            res.active_slot = buf->cmn.active_slot;\n        }\n    #else\n        _SOKOL_UNUSED(buf_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_gl_image_info sg_gl_query_image_info(sg_image img_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_gl_image_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(_SOKOL_ANY_GL)\n        const _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);\n        if (img) {\n            for (int i = 0; i < SG_NUM_INFLIGHT_FRAMES; i++) {\n                res.tex[i] = img->gl.tex[i];\n            }\n            res.tex_target = img->gl.target;\n            res.msaa_render_buffer = img->gl.msaa_render_buffer;\n            res.active_slot = img->cmn.active_slot;\n        }\n    #else\n        _SOKOL_UNUSED(img_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_gl_sampler_info sg_gl_query_sampler_info(sg_sampler smp_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_gl_sampler_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(_SOKOL_ANY_GL)\n        const _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, smp_id.id);\n        if (smp) {\n            res.smp = smp->gl.smp;\n        }\n    #else\n        _SOKOL_UNUSED(smp_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_gl_shader_info sg_gl_query_shader_info(sg_shader shd_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_gl_shader_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(_SOKOL_ANY_GL)\n        const _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, shd_id.id);\n        if (shd) {\n            res.prog = shd->gl.prog;\n        }\n    #else\n        _SOKOL_UNUSED(shd_id);\n    #endif\n    return res;\n}\n\nSOKOL_API_IMPL sg_gl_attachments_info sg_gl_query_attachments_info(sg_attachments atts_id) {\n    SOKOL_ASSERT(_sg.valid);\n    sg_gl_attachments_info res;\n    _sg_clear(&res, sizeof(res));\n    #if defined(_SOKOL_ANY_GL)\n        const _sg_attachments_t* atts = _sg_lookup_attachments(&_sg.pools, atts_id.id);\n        if (atts) {\n            res.framebuffer = atts->gl.fb;\n            for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {\n                res.msaa_resolve_framebuffer[i] = atts->gl.msaa_resolve_framebuffer[i];\n            }\n        }\n    #else\n        _SOKOL_UNUSED(atts_id);\n    #endif\n    return res;\n}\n\n#ifdef _MSC_VER\n#pragma warning(pop)\n#endif\n\n#endif // SOKOL_GFX_IMPL\n"
  },
  {
    "path": "thirdparty/sokol/sokol_v.post.h",
    "content": "#if defined(SOKOL_GLCORE) || defined(SOKOL_GLES3)\n\tvoid v_sapp_gl_read_rgba_pixels(int x, int y, int width, int height, unsigned char* pixels) {\n\t\tglReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);\n\t}\n#else\n\tvoid v_sapp_gl_read_rgba_pixels(int x, int y, int width, int height, unsigned char* pixels) {\n\t\t// TODO\n\t}\n#endif\n"
  },
  {
    "path": "thirdparty/sokol/tablet-unstable-v2-client-protocol.h",
    "content": "/* Generated by wayland-scanner 1.24.0 */\n\n#ifndef TABLET_UNSTABLE_V2_CLIENT_PROTOCOL_H\n#define TABLET_UNSTABLE_V2_CLIENT_PROTOCOL_H\n\n#include <stdint.h>\n#include <stddef.h>\n#include \"wayland-client.h\"\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * @page page_tablet_unstable_v2 The tablet_unstable_v2 protocol\n * Wayland protocol for graphics tablets\n *\n * @section page_desc_tablet_unstable_v2 Description\n *\n * This description provides a high-level overview of the interplay between\n * the interfaces defined this protocol. For details, see the protocol\n * specification.\n *\n * More than one tablet may exist, and device-specifics matter. Tablets are\n * not represented by a single virtual device like wl_pointer. A client\n * binds to the tablet manager object which is just a proxy object. From\n * that, the client requests wp_tablet_manager.get_tablet_seat(wl_seat)\n * and that returns the actual interface that has all the tablets. With\n * this indirection, we can avoid merging wp_tablet into the actual Wayland\n * protocol, a long-term benefit.\n *\n * The wp_tablet_seat sends a \"tablet added\" event for each tablet\n * connected. That event is followed by descriptive events about the\n * hardware; currently that includes events for name, vid/pid and\n * a wp_tablet.path event that describes a local path. This path can be\n * used to uniquely identify a tablet or get more information through\n * libwacom. Emulated or nested tablets can skip any of those, e.g. a\n * virtual tablet may not have a vid/pid. The sequence of descriptive\n * events is terminated by a wp_tablet.done event to signal that a client\n * may now finalize any initialization for that tablet.\n *\n * Events from tablets require a tool in proximity. Tools are also managed\n * by the tablet seat; a \"tool added\" event is sent whenever a tool is new\n * to the compositor. That event is followed by a number of descriptive\n * events about the hardware; currently that includes capabilities,\n * hardware id and serial number, and tool type. Similar to the tablet\n * interface, a wp_tablet_tool.done event is sent to terminate that initial\n * sequence.\n *\n * Any event from a tool happens on the wp_tablet_tool interface. When the\n * tool gets into proximity of the tablet, a proximity_in event is sent on\n * the wp_tablet_tool interface, listing the tablet and the surface. That\n * event is followed by a motion event with the coordinates. After that,\n * it's the usual motion, axis, button, etc. events. The protocol's\n * serialisation means events are grouped by wp_tablet_tool.frame events.\n *\n * Two special events (that don't exist in X) are down and up. They signal\n * \"tip touching the surface\". For tablets without real proximity\n * detection, the sequence is: proximity_in, motion, down, frame.\n *\n * When the tool leaves proximity, a proximity_out event is sent. If any\n * button is still down, a button release event is sent before this\n * proximity event. These button events are sent in the same frame as the\n * proximity event to signal to the client that the buttons were held when\n * the tool left proximity.\n *\n * If the tool moves out of the surface but stays in proximity (i.e.\n * between windows), compositor-specific grab policies apply. This usually\n * means that the proximity-out is delayed until all buttons are released.\n *\n * Moving a tool physically from one tablet to the other has no real effect\n * on the protocol, since we already have the tool object from the \"tool\n * added\" event. All the information is already there and the proximity\n * events on both tablets are all a client needs to reconstruct what\n * happened.\n *\n * Some extra axes are normalized, i.e. the client knows the range as\n * specified in the protocol (e.g. [0, 65535]), the granularity however is\n * unknown. The current normalized axes are pressure, distance, and slider.\n *\n * Other extra axes are in physical units as specified in the protocol.\n * The current extra axes with physical units are tilt, rotation and\n * wheel rotation.\n *\n * Since tablets work independently of the pointer controlled by the mouse,\n * the focus handling is independent too and controlled by proximity.\n * The wp_tablet_tool.set_cursor request sets a tool-specific cursor.\n * This cursor surface may be the same as the mouse cursor, and it may be\n * the same across tools but it is possible to be more fine-grained. For\n * example, a client may set different cursors for the pen and eraser.\n *\n * Tools are generally independent of tablets and it is\n * compositor-specific policy when a tool can be removed. Common approaches\n * will likely include some form of removing a tool when all tablets the\n * tool was used on are removed.\n *\n * Disclaimer: This protocol extension has been marked stable. This copy is\n * no longer used and only retained for backwards compatibility. The\n * canonical version can be found in the stable/ directory.\n *\n * @section page_ifaces_tablet_unstable_v2 Interfaces\n * - @subpage page_iface_zwp_tablet_manager_v2 - controller object for graphic tablet devices\n * - @subpage page_iface_zwp_tablet_seat_v2 - controller object for graphic tablet devices of a seat\n * - @subpage page_iface_zwp_tablet_tool_v2 - a physical tablet tool\n * - @subpage page_iface_zwp_tablet_v2 - graphics tablet device\n * - @subpage page_iface_zwp_tablet_pad_ring_v2 - pad ring\n * - @subpage page_iface_zwp_tablet_pad_strip_v2 - pad strip\n * - @subpage page_iface_zwp_tablet_pad_group_v2 - a set of buttons, rings and strips\n * - @subpage page_iface_zwp_tablet_pad_v2 - a set of buttons, rings and strips\n * @section page_copyright_tablet_unstable_v2 Copyright\n * <pre>\n *\n * Copyright 2014 © Stephen \"Lyude\" Chandler Paul\n * Copyright 2015-2016 © Red Hat, Inc.\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation files\n * (the \"Software\"), to deal in the Software without restriction,\n * including without limitation the rights to use, copy, modify, merge,\n * publish, distribute, sublicense, and/or sell copies of the Software,\n * and to permit persons to whom the Software is furnished to do so,\n * subject to the following conditions:\n *\n * The above copyright notice and this permission notice (including the\n * next paragraph) shall be included in all copies or substantial\n * portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n * </pre>\n */\nstruct wl_seat;\nstruct wl_surface;\nstruct zwp_tablet_manager_v2;\nstruct zwp_tablet_pad_group_v2;\nstruct zwp_tablet_pad_ring_v2;\nstruct zwp_tablet_pad_strip_v2;\nstruct zwp_tablet_pad_v2;\nstruct zwp_tablet_seat_v2;\nstruct zwp_tablet_tool_v2;\nstruct zwp_tablet_v2;\n\n#ifndef ZWP_TABLET_MANAGER_V2_INTERFACE\n#define ZWP_TABLET_MANAGER_V2_INTERFACE\n/**\n * @page page_iface_zwp_tablet_manager_v2 zwp_tablet_manager_v2\n * @section page_iface_zwp_tablet_manager_v2_desc Description\n *\n * An object that provides access to the graphics tablets available on this\n * system. All tablets are associated with a seat, to get access to the\n * actual tablets, use wp_tablet_manager.get_tablet_seat.\n * @section page_iface_zwp_tablet_manager_v2_api API\n * See @ref iface_zwp_tablet_manager_v2.\n */\n/**\n * @defgroup iface_zwp_tablet_manager_v2 The zwp_tablet_manager_v2 interface\n *\n * An object that provides access to the graphics tablets available on this\n * system. All tablets are associated with a seat, to get access to the\n * actual tablets, use wp_tablet_manager.get_tablet_seat.\n */\nextern const struct wl_interface zwp_tablet_manager_v2_interface;\n#endif\n#ifndef ZWP_TABLET_SEAT_V2_INTERFACE\n#define ZWP_TABLET_SEAT_V2_INTERFACE\n/**\n * @page page_iface_zwp_tablet_seat_v2 zwp_tablet_seat_v2\n * @section page_iface_zwp_tablet_seat_v2_desc Description\n *\n * An object that provides access to the graphics tablets available on this\n * seat. After binding to this interface, the compositor sends a set of\n * wp_tablet_seat.tablet_added and wp_tablet_seat.tool_added events.\n * @section page_iface_zwp_tablet_seat_v2_api API\n * See @ref iface_zwp_tablet_seat_v2.\n */\n/**\n * @defgroup iface_zwp_tablet_seat_v2 The zwp_tablet_seat_v2 interface\n *\n * An object that provides access to the graphics tablets available on this\n * seat. After binding to this interface, the compositor sends a set of\n * wp_tablet_seat.tablet_added and wp_tablet_seat.tool_added events.\n */\nextern const struct wl_interface zwp_tablet_seat_v2_interface;\n#endif\n#ifndef ZWP_TABLET_TOOL_V2_INTERFACE\n#define ZWP_TABLET_TOOL_V2_INTERFACE\n/**\n * @page page_iface_zwp_tablet_tool_v2 zwp_tablet_tool_v2\n * @section page_iface_zwp_tablet_tool_v2_desc Description\n *\n * An object that represents a physical tool that has been, or is\n * currently in use with a tablet in this seat. Each wp_tablet_tool\n * object stays valid until the client destroys it; the compositor\n * reuses the wp_tablet_tool object to indicate that the object's\n * respective physical tool has come into proximity of a tablet again.\n *\n * A wp_tablet_tool object's relation to a physical tool depends on the\n * tablet's ability to report serial numbers. If the tablet supports\n * this capability, then the object represents a specific physical tool\n * and can be identified even when used on multiple tablets.\n *\n * A tablet tool has a number of static characteristics, e.g. tool type,\n * hardware_serial and capabilities. These capabilities are sent in an\n * event sequence after the wp_tablet_seat.tool_added event before any\n * actual events from this tool. This initial event sequence is\n * terminated by a wp_tablet_tool.done event.\n *\n * Tablet tool events are grouped by wp_tablet_tool.frame events.\n * Any events received before a wp_tablet_tool.frame event should be\n * considered part of the same hardware state change.\n * @section page_iface_zwp_tablet_tool_v2_api API\n * See @ref iface_zwp_tablet_tool_v2.\n */\n/**\n * @defgroup iface_zwp_tablet_tool_v2 The zwp_tablet_tool_v2 interface\n *\n * An object that represents a physical tool that has been, or is\n * currently in use with a tablet in this seat. Each wp_tablet_tool\n * object stays valid until the client destroys it; the compositor\n * reuses the wp_tablet_tool object to indicate that the object's\n * respective physical tool has come into proximity of a tablet again.\n *\n * A wp_tablet_tool object's relation to a physical tool depends on the\n * tablet's ability to report serial numbers. If the tablet supports\n * this capability, then the object represents a specific physical tool\n * and can be identified even when used on multiple tablets.\n *\n * A tablet tool has a number of static characteristics, e.g. tool type,\n * hardware_serial and capabilities. These capabilities are sent in an\n * event sequence after the wp_tablet_seat.tool_added event before any\n * actual events from this tool. This initial event sequence is\n * terminated by a wp_tablet_tool.done event.\n *\n * Tablet tool events are grouped by wp_tablet_tool.frame events.\n * Any events received before a wp_tablet_tool.frame event should be\n * considered part of the same hardware state change.\n */\nextern const struct wl_interface zwp_tablet_tool_v2_interface;\n#endif\n#ifndef ZWP_TABLET_V2_INTERFACE\n#define ZWP_TABLET_V2_INTERFACE\n/**\n * @page page_iface_zwp_tablet_v2 zwp_tablet_v2\n * @section page_iface_zwp_tablet_v2_desc Description\n *\n * The wp_tablet interface represents one graphics tablet device. The\n * tablet interface itself does not generate events; all events are\n * generated by wp_tablet_tool objects when in proximity above a tablet.\n *\n * A tablet has a number of static characteristics, e.g. device name and\n * pid/vid. These capabilities are sent in an event sequence after the\n * wp_tablet_seat.tablet_added event. This initial event sequence is\n * terminated by a wp_tablet.done event.\n * @section page_iface_zwp_tablet_v2_api API\n * See @ref iface_zwp_tablet_v2.\n */\n/**\n * @defgroup iface_zwp_tablet_v2 The zwp_tablet_v2 interface\n *\n * The wp_tablet interface represents one graphics tablet device. The\n * tablet interface itself does not generate events; all events are\n * generated by wp_tablet_tool objects when in proximity above a tablet.\n *\n * A tablet has a number of static characteristics, e.g. device name and\n * pid/vid. These capabilities are sent in an event sequence after the\n * wp_tablet_seat.tablet_added event. This initial event sequence is\n * terminated by a wp_tablet.done event.\n */\nextern const struct wl_interface zwp_tablet_v2_interface;\n#endif\n#ifndef ZWP_TABLET_PAD_RING_V2_INTERFACE\n#define ZWP_TABLET_PAD_RING_V2_INTERFACE\n/**\n * @page page_iface_zwp_tablet_pad_ring_v2 zwp_tablet_pad_ring_v2\n * @section page_iface_zwp_tablet_pad_ring_v2_desc Description\n *\n * A circular interaction area, such as the touch ring on the Wacom Intuos\n * Pro series tablets.\n *\n * Events on a ring are logically grouped by the wl_tablet_pad_ring.frame\n * event.\n * @section page_iface_zwp_tablet_pad_ring_v2_api API\n * See @ref iface_zwp_tablet_pad_ring_v2.\n */\n/**\n * @defgroup iface_zwp_tablet_pad_ring_v2 The zwp_tablet_pad_ring_v2 interface\n *\n * A circular interaction area, such as the touch ring on the Wacom Intuos\n * Pro series tablets.\n *\n * Events on a ring are logically grouped by the wl_tablet_pad_ring.frame\n * event.\n */\nextern const struct wl_interface zwp_tablet_pad_ring_v2_interface;\n#endif\n#ifndef ZWP_TABLET_PAD_STRIP_V2_INTERFACE\n#define ZWP_TABLET_PAD_STRIP_V2_INTERFACE\n/**\n * @page page_iface_zwp_tablet_pad_strip_v2 zwp_tablet_pad_strip_v2\n * @section page_iface_zwp_tablet_pad_strip_v2_desc Description\n *\n * A linear interaction area, such as the strips found in Wacom Cintiq\n * models.\n *\n * Events on a strip are logically grouped by the wl_tablet_pad_strip.frame\n * event.\n * @section page_iface_zwp_tablet_pad_strip_v2_api API\n * See @ref iface_zwp_tablet_pad_strip_v2.\n */\n/**\n * @defgroup iface_zwp_tablet_pad_strip_v2 The zwp_tablet_pad_strip_v2 interface\n *\n * A linear interaction area, such as the strips found in Wacom Cintiq\n * models.\n *\n * Events on a strip are logically grouped by the wl_tablet_pad_strip.frame\n * event.\n */\nextern const struct wl_interface zwp_tablet_pad_strip_v2_interface;\n#endif\n#ifndef ZWP_TABLET_PAD_GROUP_V2_INTERFACE\n#define ZWP_TABLET_PAD_GROUP_V2_INTERFACE\n/**\n * @page page_iface_zwp_tablet_pad_group_v2 zwp_tablet_pad_group_v2\n * @section page_iface_zwp_tablet_pad_group_v2_desc Description\n *\n * A pad group describes a distinct (sub)set of buttons, rings and strips\n * present in the tablet. The criteria of this grouping is usually positional,\n * eg. if a tablet has buttons on the left and right side, 2 groups will be\n * presented. The physical arrangement of groups is undisclosed and may\n * change on the fly.\n *\n * Pad groups will announce their features during pad initialization. Between\n * the corresponding wp_tablet_pad.group event and wp_tablet_pad_group.done, the\n * pad group will announce the buttons, rings and strips contained in it,\n * plus the number of supported modes.\n *\n * Modes are a mechanism to allow multiple groups of actions for every element\n * in the pad group. The number of groups and available modes in each is\n * persistent across device plugs. The current mode is user-switchable, it\n * will be announced through the wp_tablet_pad_group.mode_switch event both\n * whenever it is switched, and after wp_tablet_pad.enter.\n *\n * The current mode logically applies to all elements in the pad group,\n * although it is at clients' discretion whether to actually perform different\n * actions, and/or issue the respective .set_feedback requests to notify the\n * compositor. See the wp_tablet_pad_group.mode_switch event for more details.\n * @section page_iface_zwp_tablet_pad_group_v2_api API\n * See @ref iface_zwp_tablet_pad_group_v2.\n */\n/**\n * @defgroup iface_zwp_tablet_pad_group_v2 The zwp_tablet_pad_group_v2 interface\n *\n * A pad group describes a distinct (sub)set of buttons, rings and strips\n * present in the tablet. The criteria of this grouping is usually positional,\n * eg. if a tablet has buttons on the left and right side, 2 groups will be\n * presented. The physical arrangement of groups is undisclosed and may\n * change on the fly.\n *\n * Pad groups will announce their features during pad initialization. Between\n * the corresponding wp_tablet_pad.group event and wp_tablet_pad_group.done, the\n * pad group will announce the buttons, rings and strips contained in it,\n * plus the number of supported modes.\n *\n * Modes are a mechanism to allow multiple groups of actions for every element\n * in the pad group. The number of groups and available modes in each is\n * persistent across device plugs. The current mode is user-switchable, it\n * will be announced through the wp_tablet_pad_group.mode_switch event both\n * whenever it is switched, and after wp_tablet_pad.enter.\n *\n * The current mode logically applies to all elements in the pad group,\n * although it is at clients' discretion whether to actually perform different\n * actions, and/or issue the respective .set_feedback requests to notify the\n * compositor. See the wp_tablet_pad_group.mode_switch event for more details.\n */\nextern const struct wl_interface zwp_tablet_pad_group_v2_interface;\n#endif\n#ifndef ZWP_TABLET_PAD_V2_INTERFACE\n#define ZWP_TABLET_PAD_V2_INTERFACE\n/**\n * @page page_iface_zwp_tablet_pad_v2 zwp_tablet_pad_v2\n * @section page_iface_zwp_tablet_pad_v2_desc Description\n *\n * A pad device is a set of buttons, rings and strips\n * usually physically present on the tablet device itself. Some\n * exceptions exist where the pad device is physically detached, e.g. the\n * Wacom ExpressKey Remote.\n *\n * Pad devices have no axes that control the cursor and are generally\n * auxiliary devices to the tool devices used on the tablet surface.\n *\n * A pad device has a number of static characteristics, e.g. the number\n * of rings. These capabilities are sent in an event sequence after the\n * wp_tablet_seat.pad_added event before any actual events from this pad.\n * This initial event sequence is terminated by a wp_tablet_pad.done\n * event.\n *\n * All pad features (buttons, rings and strips) are logically divided into\n * groups and all pads have at least one group. The available groups are\n * notified through the wp_tablet_pad.group event; the compositor will\n * emit one event per group before emitting wp_tablet_pad.done.\n *\n * Groups may have multiple modes. Modes allow clients to map multiple\n * actions to a single pad feature. Only one mode can be active per group,\n * although different groups may have different active modes.\n * @section page_iface_zwp_tablet_pad_v2_api API\n * See @ref iface_zwp_tablet_pad_v2.\n */\n/**\n * @defgroup iface_zwp_tablet_pad_v2 The zwp_tablet_pad_v2 interface\n *\n * A pad device is a set of buttons, rings and strips\n * usually physically present on the tablet device itself. Some\n * exceptions exist where the pad device is physically detached, e.g. the\n * Wacom ExpressKey Remote.\n *\n * Pad devices have no axes that control the cursor and are generally\n * auxiliary devices to the tool devices used on the tablet surface.\n *\n * A pad device has a number of static characteristics, e.g. the number\n * of rings. These capabilities are sent in an event sequence after the\n * wp_tablet_seat.pad_added event before any actual events from this pad.\n * This initial event sequence is terminated by a wp_tablet_pad.done\n * event.\n *\n * All pad features (buttons, rings and strips) are logically divided into\n * groups and all pads have at least one group. The available groups are\n * notified through the wp_tablet_pad.group event; the compositor will\n * emit one event per group before emitting wp_tablet_pad.done.\n *\n * Groups may have multiple modes. Modes allow clients to map multiple\n * actions to a single pad feature. Only one mode can be active per group,\n * although different groups may have different active modes.\n */\nextern const struct wl_interface zwp_tablet_pad_v2_interface;\n#endif\n\n#define ZWP_TABLET_MANAGER_V2_GET_TABLET_SEAT 0\n#define ZWP_TABLET_MANAGER_V2_DESTROY 1\n\n\n/**\n * @ingroup iface_zwp_tablet_manager_v2\n */\n#define ZWP_TABLET_MANAGER_V2_GET_TABLET_SEAT_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_manager_v2\n */\n#define ZWP_TABLET_MANAGER_V2_DESTROY_SINCE_VERSION 1\n\n/** @ingroup iface_zwp_tablet_manager_v2 */\nstatic inline void\nzwp_tablet_manager_v2_set_user_data(struct zwp_tablet_manager_v2 *zwp_tablet_manager_v2, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_manager_v2, user_data);\n}\n\n/** @ingroup iface_zwp_tablet_manager_v2 */\nstatic inline void *\nzwp_tablet_manager_v2_get_user_data(struct zwp_tablet_manager_v2 *zwp_tablet_manager_v2)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_manager_v2);\n}\n\nstatic inline uint32_t\nzwp_tablet_manager_v2_get_version(struct zwp_tablet_manager_v2 *zwp_tablet_manager_v2)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) zwp_tablet_manager_v2);\n}\n\n/**\n * @ingroup iface_zwp_tablet_manager_v2\n *\n * Get the wp_tablet_seat object for the given seat. This object\n * provides access to all graphics tablets in this seat.\n */\nstatic inline struct zwp_tablet_seat_v2 *\nzwp_tablet_manager_v2_get_tablet_seat(struct zwp_tablet_manager_v2 *zwp_tablet_manager_v2, struct wl_seat *seat)\n{\n\tstruct wl_proxy *tablet_seat;\n\n\ttablet_seat = wl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_manager_v2,\n\t\t\t ZWP_TABLET_MANAGER_V2_GET_TABLET_SEAT, &zwp_tablet_seat_v2_interface, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_manager_v2), 0, NULL, seat);\n\n\treturn (struct zwp_tablet_seat_v2 *) tablet_seat;\n}\n\n/**\n * @ingroup iface_zwp_tablet_manager_v2\n *\n * Destroy the wp_tablet_manager object. Objects created from this\n * object are unaffected and should be destroyed separately.\n */\nstatic inline void\nzwp_tablet_manager_v2_destroy(struct zwp_tablet_manager_v2 *zwp_tablet_manager_v2)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_manager_v2,\n\t\t\t ZWP_TABLET_MANAGER_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_manager_v2), WL_MARSHAL_FLAG_DESTROY);\n}\n\n/**\n * @ingroup iface_zwp_tablet_seat_v2\n * @struct zwp_tablet_seat_v2_listener\n */\nstruct zwp_tablet_seat_v2_listener {\n\t/**\n\t * new device notification\n\t *\n\t * This event is sent whenever a new tablet becomes available on\n\t * this seat. This event only provides the object id of the tablet,\n\t * any static information about the tablet (device name, vid/pid,\n\t * etc.) is sent through the wp_tablet interface.\n\t * @param id the newly added graphics tablet\n\t */\n\tvoid (*tablet_added)(void *data,\n\t\t\t     struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2,\n\t\t\t     struct zwp_tablet_v2 *id);\n\t/**\n\t * a new tool has been used with a tablet\n\t *\n\t * This event is sent whenever a tool that has not previously\n\t * been used with a tablet comes into use. This event only provides\n\t * the object id of the tool; any static information about the tool\n\t * (capabilities, type, etc.) is sent through the wp_tablet_tool\n\t * interface.\n\t * @param id the newly added tablet tool\n\t */\n\tvoid (*tool_added)(void *data,\n\t\t\t   struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2,\n\t\t\t   struct zwp_tablet_tool_v2 *id);\n\t/**\n\t * new pad notification\n\t *\n\t * This event is sent whenever a new pad is known to the system.\n\t * Typically, pads are physically attached to tablets and a\n\t * pad_added event is sent immediately after the\n\t * wp_tablet_seat.tablet_added. However, some standalone pad\n\t * devices logically attach to tablets at runtime, and the client\n\t * must wait for wp_tablet_pad.enter to know the tablet a pad is\n\t * attached to.\n\t *\n\t * This event only provides the object id of the pad. All further\n\t * features (buttons, strips, rings) are sent through the\n\t * wp_tablet_pad interface.\n\t * @param id the newly added pad\n\t */\n\tvoid (*pad_added)(void *data,\n\t\t\t  struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2,\n\t\t\t  struct zwp_tablet_pad_v2 *id);\n};\n\n/**\n * @ingroup iface_zwp_tablet_seat_v2\n */\nstatic inline int\nzwp_tablet_seat_v2_add_listener(struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2,\n\t\t\t\tconst struct zwp_tablet_seat_v2_listener *listener, void *data)\n{\n\treturn wl_proxy_add_listener((struct wl_proxy *) zwp_tablet_seat_v2,\n\t\t\t\t     (void (**)(void)) listener, data);\n}\n\n#define ZWP_TABLET_SEAT_V2_DESTROY 0\n\n/**\n * @ingroup iface_zwp_tablet_seat_v2\n */\n#define ZWP_TABLET_SEAT_V2_TABLET_ADDED_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_seat_v2\n */\n#define ZWP_TABLET_SEAT_V2_TOOL_ADDED_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_seat_v2\n */\n#define ZWP_TABLET_SEAT_V2_PAD_ADDED_SINCE_VERSION 1\n\n/**\n * @ingroup iface_zwp_tablet_seat_v2\n */\n#define ZWP_TABLET_SEAT_V2_DESTROY_SINCE_VERSION 1\n\n/** @ingroup iface_zwp_tablet_seat_v2 */\nstatic inline void\nzwp_tablet_seat_v2_set_user_data(struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_seat_v2, user_data);\n}\n\n/** @ingroup iface_zwp_tablet_seat_v2 */\nstatic inline void *\nzwp_tablet_seat_v2_get_user_data(struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_seat_v2);\n}\n\nstatic inline uint32_t\nzwp_tablet_seat_v2_get_version(struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) zwp_tablet_seat_v2);\n}\n\n/**\n * @ingroup iface_zwp_tablet_seat_v2\n *\n * Destroy the wp_tablet_seat object. Objects created from this\n * object are unaffected and should be destroyed separately.\n */\nstatic inline void\nzwp_tablet_seat_v2_destroy(struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_seat_v2,\n\t\t\t ZWP_TABLET_SEAT_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_seat_v2), WL_MARSHAL_FLAG_DESTROY);\n}\n\n#ifndef ZWP_TABLET_TOOL_V2_TYPE_ENUM\n#define ZWP_TABLET_TOOL_V2_TYPE_ENUM\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n * a physical tool type\n *\n * Describes the physical type of a tool. The physical type of a tool\n * generally defines its base usage.\n *\n * The mouse tool represents a mouse-shaped tool that is not a relative\n * device but bound to the tablet's surface, providing absolute\n * coordinates.\n *\n * The lens tool is a mouse-shaped tool with an attached lens to\n * provide precision focus.\n */\nenum zwp_tablet_tool_v2_type {\n\t/**\n\t * Pen\n\t */\n\tZWP_TABLET_TOOL_V2_TYPE_PEN = 0x140,\n\t/**\n\t * Eraser\n\t */\n\tZWP_TABLET_TOOL_V2_TYPE_ERASER = 0x141,\n\t/**\n\t * Brush\n\t */\n\tZWP_TABLET_TOOL_V2_TYPE_BRUSH = 0x142,\n\t/**\n\t * Pencil\n\t */\n\tZWP_TABLET_TOOL_V2_TYPE_PENCIL = 0x143,\n\t/**\n\t * Airbrush\n\t */\n\tZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH = 0x144,\n\t/**\n\t * Finger\n\t */\n\tZWP_TABLET_TOOL_V2_TYPE_FINGER = 0x145,\n\t/**\n\t * Mouse\n\t */\n\tZWP_TABLET_TOOL_V2_TYPE_MOUSE = 0x146,\n\t/**\n\t * Lens\n\t */\n\tZWP_TABLET_TOOL_V2_TYPE_LENS = 0x147,\n};\n#endif /* ZWP_TABLET_TOOL_V2_TYPE_ENUM */\n\n#ifndef ZWP_TABLET_TOOL_V2_CAPABILITY_ENUM\n#define ZWP_TABLET_TOOL_V2_CAPABILITY_ENUM\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n * capability flags for a tool\n *\n * Describes extra capabilities on a tablet.\n *\n * Any tool must provide x and y values, extra axes are\n * device-specific.\n */\nenum zwp_tablet_tool_v2_capability {\n\t/**\n\t * Tilt axes\n\t */\n\tZWP_TABLET_TOOL_V2_CAPABILITY_TILT = 1,\n\t/**\n\t * Pressure axis\n\t */\n\tZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE = 2,\n\t/**\n\t * Distance axis\n\t */\n\tZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE = 3,\n\t/**\n\t * Z-rotation axis\n\t */\n\tZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION = 4,\n\t/**\n\t * Slider axis\n\t */\n\tZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER = 5,\n\t/**\n\t * Wheel axis\n\t */\n\tZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL = 6,\n};\n#endif /* ZWP_TABLET_TOOL_V2_CAPABILITY_ENUM */\n\n#ifndef ZWP_TABLET_TOOL_V2_BUTTON_STATE_ENUM\n#define ZWP_TABLET_TOOL_V2_BUTTON_STATE_ENUM\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n * physical button state\n *\n * Describes the physical state of a button that produced the button event.\n */\nenum zwp_tablet_tool_v2_button_state {\n\t/**\n\t * button is not pressed\n\t */\n\tZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED = 0,\n\t/**\n\t * button is pressed\n\t */\n\tZWP_TABLET_TOOL_V2_BUTTON_STATE_PRESSED = 1,\n};\n#endif /* ZWP_TABLET_TOOL_V2_BUTTON_STATE_ENUM */\n\n#ifndef ZWP_TABLET_TOOL_V2_ERROR_ENUM\n#define ZWP_TABLET_TOOL_V2_ERROR_ENUM\nenum zwp_tablet_tool_v2_error {\n\t/**\n\t * given wl_surface has another role\n\t */\n\tZWP_TABLET_TOOL_V2_ERROR_ROLE = 0,\n};\n#endif /* ZWP_TABLET_TOOL_V2_ERROR_ENUM */\n\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n * @struct zwp_tablet_tool_v2_listener\n */\nstruct zwp_tablet_tool_v2_listener {\n\t/**\n\t * tool type\n\t *\n\t * The tool type is the high-level type of the tool and usually\n\t * decides the interaction expected from this tool.\n\t *\n\t * This event is sent in the initial burst of events before the\n\t * wp_tablet_tool.done event.\n\t * @param tool_type the physical tool type\n\t */\n\tvoid (*type)(void *data,\n\t\t     struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t     uint32_t tool_type);\n\t/**\n\t * unique hardware serial number of the tool\n\t *\n\t * If the physical tool can be identified by a unique 64-bit\n\t * serial number, this event notifies the client of this serial\n\t * number.\n\t *\n\t * If multiple tablets are available in the same seat and the tool\n\t * is uniquely identifiable by the serial number, that tool may\n\t * move between tablets.\n\t *\n\t * Otherwise, if the tool has no serial number and this event is\n\t * missing, the tool is tied to the tablet it first comes into\n\t * proximity with. Even if the physical tool is used on multiple\n\t * tablets, separate wp_tablet_tool objects will be created, one\n\t * per tablet.\n\t *\n\t * This event is sent in the initial burst of events before the\n\t * wp_tablet_tool.done event.\n\t * @param hardware_serial_hi the unique serial number of the tool, most significant bits\n\t * @param hardware_serial_lo the unique serial number of the tool, least significant bits\n\t */\n\tvoid (*hardware_serial)(void *data,\n\t\t\t\tstruct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t\t\tuint32_t hardware_serial_hi,\n\t\t\t\tuint32_t hardware_serial_lo);\n\t/**\n\t * hardware id notification in Wacom's format\n\t *\n\t * This event notifies the client of a hardware id available on\n\t * this tool.\n\t *\n\t * The hardware id is a device-specific 64-bit id that provides\n\t * extra information about the tool in use, beyond the wl_tool.type\n\t * enumeration. The format of the id is specific to tablets made by\n\t * Wacom Inc. For example, the hardware id of a Wacom Grip Pen (a\n\t * stylus) is 0x802.\n\t *\n\t * This event is sent in the initial burst of events before the\n\t * wp_tablet_tool.done event.\n\t * @param hardware_id_hi the hardware id, most significant bits\n\t * @param hardware_id_lo the hardware id, least significant bits\n\t */\n\tvoid (*hardware_id_wacom)(void *data,\n\t\t\t\t  struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t\t\t  uint32_t hardware_id_hi,\n\t\t\t\t  uint32_t hardware_id_lo);\n\t/**\n\t * tool capability notification\n\t *\n\t * This event notifies the client of any capabilities of this\n\t * tool, beyond the main set of x/y axes and tip up/down detection.\n\t *\n\t * One event is sent for each extra capability available on this\n\t * tool.\n\t *\n\t * This event is sent in the initial burst of events before the\n\t * wp_tablet_tool.done event.\n\t * @param capability the capability\n\t */\n\tvoid (*capability)(void *data,\n\t\t\t   struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t\t   uint32_t capability);\n\t/**\n\t * tool description events sequence complete\n\t *\n\t * This event signals the end of the initial burst of descriptive\n\t * events. A client may consider the static description of the tool\n\t * to be complete and finalize initialization of the tool.\n\t */\n\tvoid (*done)(void *data,\n\t\t     struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2);\n\t/**\n\t * tool removed\n\t *\n\t * This event is sent when the tool is removed from the system\n\t * and will send no further events. Should the physical tool come\n\t * back into proximity later, a new wp_tablet_tool object will be\n\t * created.\n\t *\n\t * It is compositor-dependent when a tool is removed. A compositor\n\t * may remove a tool on proximity out, tablet removal or any other\n\t * reason. A compositor may also keep a tool alive until shutdown.\n\t *\n\t * If the tool is currently in proximity, a proximity_out event\n\t * will be sent before the removed event. See\n\t * wp_tablet_tool.proximity_out for the handling of any buttons\n\t * logically down.\n\t *\n\t * When this event is received, the client must\n\t * wp_tablet_tool.destroy the object.\n\t */\n\tvoid (*removed)(void *data,\n\t\t\tstruct zwp_tablet_tool_v2 *zwp_tablet_tool_v2);\n\t/**\n\t * proximity in event\n\t *\n\t * Notification that this tool is focused on a certain surface.\n\t *\n\t * This event can be received when the tool has moved from one\n\t * surface to another, or when the tool has come back into\n\t * proximity above the surface.\n\t *\n\t * If any button is logically down when the tool comes into\n\t * proximity, the respective button event is sent after the\n\t * proximity_in event but within the same frame as the proximity_in\n\t * event.\n\t * @param tablet The tablet the tool is in proximity of\n\t * @param surface The current surface the tablet tool is over\n\t */\n\tvoid (*proximity_in)(void *data,\n\t\t\t     struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t\t     uint32_t serial,\n\t\t\t     struct zwp_tablet_v2 *tablet,\n\t\t\t     struct wl_surface *surface);\n\t/**\n\t * proximity out event\n\t *\n\t * Notification that this tool has either left proximity, or is\n\t * no longer focused on a certain surface.\n\t *\n\t * When the tablet tool leaves proximity of the tablet, button\n\t * release events are sent for each button that was held down at\n\t * the time of leaving proximity. These events are sent before the\n\t * proximity_out event but within the same wp_tablet.frame.\n\t *\n\t * If the tool stays within proximity of the tablet, but the focus\n\t * changes from one surface to another, a button release event may\n\t * not be sent until the button is actually released or the tool\n\t * leaves the proximity of the tablet.\n\t */\n\tvoid (*proximity_out)(void *data,\n\t\t\t      struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2);\n\t/**\n\t * tablet tool is making contact\n\t *\n\t * Sent whenever the tablet tool comes in contact with the\n\t * surface of the tablet.\n\t *\n\t * If the tool is already in contact with the tablet when entering\n\t * the input region, the client owning said region will receive a\n\t * wp_tablet.proximity_in event, followed by a wp_tablet.down event\n\t * and a wp_tablet.frame event.\n\t *\n\t * Note that this event describes logical contact, not physical\n\t * contact. On some devices, a compositor may not consider a tool\n\t * in logical contact until a minimum physical pressure threshold\n\t * is exceeded.\n\t */\n\tvoid (*down)(void *data,\n\t\t     struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t     uint32_t serial);\n\t/**\n\t * tablet tool is no longer making contact\n\t *\n\t * Sent whenever the tablet tool stops making contact with the\n\t * surface of the tablet, or when the tablet tool moves out of the\n\t * input region and the compositor grab (if any) is dismissed.\n\t *\n\t * If the tablet tool moves out of the input region while in\n\t * contact with the surface of the tablet and the compositor does\n\t * not have an ongoing grab on the surface, the client owning said\n\t * region will receive a wp_tablet.up event, followed by a\n\t * wp_tablet.proximity_out event and a wp_tablet.frame event. If\n\t * the compositor has an ongoing grab on this device, this event\n\t * sequence is sent whenever the grab is dismissed in the future.\n\t *\n\t * Note that this event describes logical contact, not physical\n\t * contact. On some devices, a compositor may not consider a tool\n\t * out of logical contact until physical pressure falls below a\n\t * specific threshold.\n\t */\n\tvoid (*up)(void *data,\n\t\t   struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2);\n\t/**\n\t * motion event\n\t *\n\t * Sent whenever a tablet tool moves.\n\t * @param x surface-local x coordinate\n\t * @param y surface-local y coordinate\n\t */\n\tvoid (*motion)(void *data,\n\t\t       struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t       wl_fixed_t x,\n\t\t       wl_fixed_t y);\n\t/**\n\t * pressure change event\n\t *\n\t * Sent whenever the pressure axis on a tool changes. The value\n\t * of this event is normalized to a value between 0 and 65535.\n\t *\n\t * Note that pressure may be nonzero even when a tool is not in\n\t * logical contact. See the down and up events for more details.\n\t * @param pressure The current pressure value\n\t */\n\tvoid (*pressure)(void *data,\n\t\t\t struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t\t uint32_t pressure);\n\t/**\n\t * distance change event\n\t *\n\t * Sent whenever the distance axis on a tool changes. The value\n\t * of this event is normalized to a value between 0 and 65535.\n\t *\n\t * Note that distance may be nonzero even when a tool is not in\n\t * logical contact. See the down and up events for more details.\n\t * @param distance The current distance value\n\t */\n\tvoid (*distance)(void *data,\n\t\t\t struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t\t uint32_t distance);\n\t/**\n\t * tilt change event\n\t *\n\t * Sent whenever one or both of the tilt axes on a tool change.\n\t * Each tilt value is in degrees, relative to the z-axis of the\n\t * tablet. The angle is positive when the top of a tool tilts along\n\t * the positive x or y axis.\n\t * @param tilt_x The current value of the X tilt axis\n\t * @param tilt_y The current value of the Y tilt axis\n\t */\n\tvoid (*tilt)(void *data,\n\t\t     struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t     wl_fixed_t tilt_x,\n\t\t     wl_fixed_t tilt_y);\n\t/**\n\t * z-rotation change event\n\t *\n\t * Sent whenever the z-rotation axis on the tool changes. The\n\t * rotation value is in degrees clockwise from the tool's logical\n\t * neutral position.\n\t * @param degrees The current rotation of the Z axis\n\t */\n\tvoid (*rotation)(void *data,\n\t\t\t struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t\t wl_fixed_t degrees);\n\t/**\n\t * Slider position change event\n\t *\n\t * Sent whenever the slider position on the tool changes. The\n\t * value is normalized between -65535 and 65535, with 0 as the\n\t * logical neutral position of the slider.\n\t *\n\t * The slider is available on e.g. the Wacom Airbrush tool.\n\t * @param position The current position of slider\n\t */\n\tvoid (*slider)(void *data,\n\t\t       struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t       int32_t position);\n\t/**\n\t * Wheel delta event\n\t *\n\t * Sent whenever the wheel on the tool emits an event. This event\n\t * contains two values for the same axis change. The degrees value\n\t * is in the same orientation as the wl_pointer.vertical_scroll\n\t * axis. The clicks value is in discrete logical clicks of the\n\t * mouse wheel. This value may be zero if the movement of the wheel\n\t * was less than one logical click.\n\t *\n\t * Clients should choose either value and avoid mixing degrees and\n\t * clicks. The compositor may accumulate values smaller than a\n\t * logical click and emulate click events when a certain threshold\n\t * is met. Thus, wl_tablet_tool.wheel events with non-zero clicks\n\t * values may have different degrees values.\n\t * @param degrees The wheel delta in degrees\n\t * @param clicks The wheel delta in discrete clicks\n\t */\n\tvoid (*wheel)(void *data,\n\t\t      struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t      wl_fixed_t degrees,\n\t\t      int32_t clicks);\n\t/**\n\t * button event\n\t *\n\t * Sent whenever a button on the tool is pressed or released.\n\t *\n\t * If a button is held down when the tool moves in or out of\n\t * proximity, button events are generated by the compositor. See\n\t * wp_tablet_tool.proximity_in and wp_tablet_tool.proximity_out for\n\t * details.\n\t * @param button The button whose state has changed\n\t * @param state Whether the button was pressed or released\n\t */\n\tvoid (*button)(void *data,\n\t\t       struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t       uint32_t serial,\n\t\t       uint32_t button,\n\t\t       uint32_t state);\n\t/**\n\t * frame event\n\t *\n\t * Marks the end of a series of axis and/or button updates from\n\t * the tablet. The Wayland protocol requires axis updates to be\n\t * sent sequentially, however all events within a frame should be\n\t * considered one hardware event.\n\t * @param time The time of the event with millisecond granularity\n\t */\n\tvoid (*frame)(void *data,\n\t\t      struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t      uint32_t time);\n};\n\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\nstatic inline int\nzwp_tablet_tool_v2_add_listener(struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,\n\t\t\t\tconst struct zwp_tablet_tool_v2_listener *listener, void *data)\n{\n\treturn wl_proxy_add_listener((struct wl_proxy *) zwp_tablet_tool_v2,\n\t\t\t\t     (void (**)(void)) listener, data);\n}\n\n#define ZWP_TABLET_TOOL_V2_SET_CURSOR 0\n#define ZWP_TABLET_TOOL_V2_DESTROY 1\n\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_TYPE_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_HARDWARE_SERIAL_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_HARDWARE_ID_WACOM_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_CAPABILITY_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_DONE_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_REMOVED_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_PROXIMITY_IN_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_PROXIMITY_OUT_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_DOWN_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_UP_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_MOTION_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_PRESSURE_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_DISTANCE_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_TILT_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_ROTATION_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_SLIDER_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_WHEEL_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_BUTTON_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_FRAME_SINCE_VERSION 1\n\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_SET_CURSOR_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n */\n#define ZWP_TABLET_TOOL_V2_DESTROY_SINCE_VERSION 1\n\n/** @ingroup iface_zwp_tablet_tool_v2 */\nstatic inline void\nzwp_tablet_tool_v2_set_user_data(struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_tool_v2, user_data);\n}\n\n/** @ingroup iface_zwp_tablet_tool_v2 */\nstatic inline void *\nzwp_tablet_tool_v2_get_user_data(struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_tool_v2);\n}\n\nstatic inline uint32_t\nzwp_tablet_tool_v2_get_version(struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) zwp_tablet_tool_v2);\n}\n\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n *\n * Sets the surface of the cursor used for this tool on the given\n * tablet. This request only takes effect if the tool is in proximity\n * of one of the requesting client's surfaces or the surface parameter\n * is the current pointer surface. If there was a previous surface set\n * with this request it is replaced. If surface is NULL, the cursor\n * image is hidden.\n *\n * The parameters hotspot_x and hotspot_y define the position of the\n * pointer surface relative to the pointer location. Its top-left corner\n * is always at (x, y) - (hotspot_x, hotspot_y), where (x, y) are the\n * coordinates of the pointer location, in surface-local coordinates.\n *\n * On surface.attach requests to the pointer surface, hotspot_x and\n * hotspot_y are decremented by the x and y parameters passed to the\n * request. Attach must be confirmed by wl_surface.commit as usual.\n *\n * The hotspot can also be updated by passing the currently set pointer\n * surface to this request with new values for hotspot_x and hotspot_y.\n *\n * The current and pending input regions of the wl_surface are cleared,\n * and wl_surface.set_input_region is ignored until the wl_surface is no\n * longer used as the cursor. When the use as a cursor ends, the current\n * and pending input regions become undefined, and the wl_surface is\n * unmapped.\n *\n * This request gives the surface the role of a wp_tablet_tool cursor. A\n * surface may only ever be used as the cursor surface for one\n * wp_tablet_tool. If the surface already has another role or has\n * previously been used as cursor surface for a different tool, a\n * protocol error is raised.\n */\nstatic inline void\nzwp_tablet_tool_v2_set_cursor(struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2, uint32_t serial, struct wl_surface *surface, int32_t hotspot_x, int32_t hotspot_y)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_tool_v2,\n\t\t\t ZWP_TABLET_TOOL_V2_SET_CURSOR, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_tool_v2), 0, serial, surface, hotspot_x, hotspot_y);\n}\n\n/**\n * @ingroup iface_zwp_tablet_tool_v2\n *\n * This destroys the client's resource for this tool object.\n */\nstatic inline void\nzwp_tablet_tool_v2_destroy(struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_tool_v2,\n\t\t\t ZWP_TABLET_TOOL_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_tool_v2), WL_MARSHAL_FLAG_DESTROY);\n}\n\n/**\n * @ingroup iface_zwp_tablet_v2\n * @struct zwp_tablet_v2_listener\n */\nstruct zwp_tablet_v2_listener {\n\t/**\n\t * tablet device name\n\t *\n\t * A descriptive name for the tablet device.\n\t *\n\t * If the device has no descriptive name, this event is not sent.\n\t *\n\t * This event is sent in the initial burst of events before the\n\t * wp_tablet.done event.\n\t * @param name the device name\n\t */\n\tvoid (*name)(void *data,\n\t\t     struct zwp_tablet_v2 *zwp_tablet_v2,\n\t\t     const char *name);\n\t/**\n\t * tablet device USB vendor/product id\n\t *\n\t * The USB vendor and product IDs for the tablet device.\n\t *\n\t * If the device has no USB vendor/product ID, this event is not\n\t * sent. This can happen for virtual devices or non-USB devices,\n\t * for instance.\n\t *\n\t * This event is sent in the initial burst of events before the\n\t * wp_tablet.done event.\n\t * @param vid USB vendor id\n\t * @param pid USB product id\n\t */\n\tvoid (*id)(void *data,\n\t\t   struct zwp_tablet_v2 *zwp_tablet_v2,\n\t\t   uint32_t vid,\n\t\t   uint32_t pid);\n\t/**\n\t * path to the device\n\t *\n\t * A system-specific device path that indicates which device is\n\t * behind this wp_tablet. This information may be used to gather\n\t * additional information about the device, e.g. through libwacom.\n\t *\n\t * A device may have more than one device path. If so, multiple\n\t * wp_tablet.path events are sent. A device may be emulated and not\n\t * have a device path, and in that case this event will not be\n\t * sent.\n\t *\n\t * The format of the path is unspecified, it may be a device node,\n\t * a sysfs path, or some other identifier. It is up to the client\n\t * to identify the string provided.\n\t *\n\t * This event is sent in the initial burst of events before the\n\t * wp_tablet.done event.\n\t * @param path path to local device\n\t */\n\tvoid (*path)(void *data,\n\t\t     struct zwp_tablet_v2 *zwp_tablet_v2,\n\t\t     const char *path);\n\t/**\n\t * tablet description events sequence complete\n\t *\n\t * This event is sent immediately to signal the end of the\n\t * initial burst of descriptive events. A client may consider the\n\t * static description of the tablet to be complete and finalize\n\t * initialization of the tablet.\n\t */\n\tvoid (*done)(void *data,\n\t\t     struct zwp_tablet_v2 *zwp_tablet_v2);\n\t/**\n\t * tablet removed event\n\t *\n\t * Sent when the tablet has been removed from the system. When a\n\t * tablet is removed, some tools may be removed.\n\t *\n\t * When this event is received, the client must wp_tablet.destroy\n\t * the object.\n\t */\n\tvoid (*removed)(void *data,\n\t\t\tstruct zwp_tablet_v2 *zwp_tablet_v2);\n};\n\n/**\n * @ingroup iface_zwp_tablet_v2\n */\nstatic inline int\nzwp_tablet_v2_add_listener(struct zwp_tablet_v2 *zwp_tablet_v2,\n\t\t\t   const struct zwp_tablet_v2_listener *listener, void *data)\n{\n\treturn wl_proxy_add_listener((struct wl_proxy *) zwp_tablet_v2,\n\t\t\t\t     (void (**)(void)) listener, data);\n}\n\n#define ZWP_TABLET_V2_DESTROY 0\n\n/**\n * @ingroup iface_zwp_tablet_v2\n */\n#define ZWP_TABLET_V2_NAME_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_v2\n */\n#define ZWP_TABLET_V2_ID_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_v2\n */\n#define ZWP_TABLET_V2_PATH_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_v2\n */\n#define ZWP_TABLET_V2_DONE_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_v2\n */\n#define ZWP_TABLET_V2_REMOVED_SINCE_VERSION 1\n\n/**\n * @ingroup iface_zwp_tablet_v2\n */\n#define ZWP_TABLET_V2_DESTROY_SINCE_VERSION 1\n\n/** @ingroup iface_zwp_tablet_v2 */\nstatic inline void\nzwp_tablet_v2_set_user_data(struct zwp_tablet_v2 *zwp_tablet_v2, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_v2, user_data);\n}\n\n/** @ingroup iface_zwp_tablet_v2 */\nstatic inline void *\nzwp_tablet_v2_get_user_data(struct zwp_tablet_v2 *zwp_tablet_v2)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_v2);\n}\n\nstatic inline uint32_t\nzwp_tablet_v2_get_version(struct zwp_tablet_v2 *zwp_tablet_v2)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) zwp_tablet_v2);\n}\n\n/**\n * @ingroup iface_zwp_tablet_v2\n *\n * This destroys the client's resource for this tablet object.\n */\nstatic inline void\nzwp_tablet_v2_destroy(struct zwp_tablet_v2 *zwp_tablet_v2)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_v2,\n\t\t\t ZWP_TABLET_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_v2), WL_MARSHAL_FLAG_DESTROY);\n}\n\n#ifndef ZWP_TABLET_PAD_RING_V2_SOURCE_ENUM\n#define ZWP_TABLET_PAD_RING_V2_SOURCE_ENUM\n/**\n * @ingroup iface_zwp_tablet_pad_ring_v2\n * ring axis source\n *\n * Describes the source types for ring events. This indicates to the\n * client how a ring event was physically generated; a client may\n * adjust the user interface accordingly. For example, events\n * from a \"finger\" source may trigger kinetic scrolling.\n */\nenum zwp_tablet_pad_ring_v2_source {\n\t/**\n\t * finger\n\t */\n\tZWP_TABLET_PAD_RING_V2_SOURCE_FINGER = 1,\n};\n#endif /* ZWP_TABLET_PAD_RING_V2_SOURCE_ENUM */\n\n/**\n * @ingroup iface_zwp_tablet_pad_ring_v2\n * @struct zwp_tablet_pad_ring_v2_listener\n */\nstruct zwp_tablet_pad_ring_v2_listener {\n\t/**\n\t * ring event source\n\t *\n\t * Source information for ring events.\n\t *\n\t * This event does not occur on its own. It is sent before a\n\t * wp_tablet_pad_ring.frame event and carries the source\n\t * information for all events within that frame.\n\t *\n\t * The source specifies how this event was generated. If the source\n\t * is wp_tablet_pad_ring.source.finger, a wp_tablet_pad_ring.stop\n\t * event will be sent when the user lifts the finger off the\n\t * device.\n\t *\n\t * This event is optional. If the source is unknown for an\n\t * interaction, no event is sent.\n\t * @param source the event source\n\t */\n\tvoid (*source)(void *data,\n\t\t       struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,\n\t\t       uint32_t source);\n\t/**\n\t * angle changed\n\t *\n\t * Sent whenever the angle on a ring changes.\n\t *\n\t * The angle is provided in degrees clockwise from the logical\n\t * north of the ring in the pad's current rotation.\n\t * @param degrees the current angle in degrees\n\t */\n\tvoid (*angle)(void *data,\n\t\t      struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,\n\t\t      wl_fixed_t degrees);\n\t/**\n\t * interaction stopped\n\t *\n\t * Stop notification for ring events.\n\t *\n\t * For some wp_tablet_pad_ring.source types, a\n\t * wp_tablet_pad_ring.stop event is sent to notify a client that\n\t * the interaction with the ring has terminated. This enables the\n\t * client to implement kinetic scrolling. See the\n\t * wp_tablet_pad_ring.source documentation for information on when\n\t * this event may be generated.\n\t *\n\t * Any wp_tablet_pad_ring.angle events with the same source after\n\t * this event should be considered as the start of a new\n\t * interaction.\n\t */\n\tvoid (*stop)(void *data,\n\t\t     struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2);\n\t/**\n\t * end of a ring event sequence\n\t *\n\t * Indicates the end of a set of ring events that logically\n\t * belong together. A client is expected to accumulate the data in\n\t * all events within the frame before proceeding.\n\t *\n\t * All wp_tablet_pad_ring events before a wp_tablet_pad_ring.frame\n\t * event belong logically together. For example, on termination of\n\t * a finger interaction on a ring the compositor will send a\n\t * wp_tablet_pad_ring.source event, a wp_tablet_pad_ring.stop event\n\t * and a wp_tablet_pad_ring.frame event.\n\t *\n\t * A wp_tablet_pad_ring.frame event is sent for every logical event\n\t * group, even if the group only contains a single\n\t * wp_tablet_pad_ring event. Specifically, a client may get a\n\t * sequence: angle, frame, angle, frame, etc.\n\t * @param time timestamp with millisecond granularity\n\t */\n\tvoid (*frame)(void *data,\n\t\t      struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,\n\t\t      uint32_t time);\n};\n\n/**\n * @ingroup iface_zwp_tablet_pad_ring_v2\n */\nstatic inline int\nzwp_tablet_pad_ring_v2_add_listener(struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,\n\t\t\t\t    const struct zwp_tablet_pad_ring_v2_listener *listener, void *data)\n{\n\treturn wl_proxy_add_listener((struct wl_proxy *) zwp_tablet_pad_ring_v2,\n\t\t\t\t     (void (**)(void)) listener, data);\n}\n\n#define ZWP_TABLET_PAD_RING_V2_SET_FEEDBACK 0\n#define ZWP_TABLET_PAD_RING_V2_DESTROY 1\n\n/**\n * @ingroup iface_zwp_tablet_pad_ring_v2\n */\n#define ZWP_TABLET_PAD_RING_V2_SOURCE_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_ring_v2\n */\n#define ZWP_TABLET_PAD_RING_V2_ANGLE_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_ring_v2\n */\n#define ZWP_TABLET_PAD_RING_V2_STOP_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_ring_v2\n */\n#define ZWP_TABLET_PAD_RING_V2_FRAME_SINCE_VERSION 1\n\n/**\n * @ingroup iface_zwp_tablet_pad_ring_v2\n */\n#define ZWP_TABLET_PAD_RING_V2_SET_FEEDBACK_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_ring_v2\n */\n#define ZWP_TABLET_PAD_RING_V2_DESTROY_SINCE_VERSION 1\n\n/** @ingroup iface_zwp_tablet_pad_ring_v2 */\nstatic inline void\nzwp_tablet_pad_ring_v2_set_user_data(struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_pad_ring_v2, user_data);\n}\n\n/** @ingroup iface_zwp_tablet_pad_ring_v2 */\nstatic inline void *\nzwp_tablet_pad_ring_v2_get_user_data(struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_pad_ring_v2);\n}\n\nstatic inline uint32_t\nzwp_tablet_pad_ring_v2_get_version(struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_ring_v2);\n}\n\n/**\n * @ingroup iface_zwp_tablet_pad_ring_v2\n *\n * Request that the compositor use the provided feedback string\n * associated with this ring. This request should be issued immediately\n * after a wp_tablet_pad_group.mode_switch event from the corresponding\n * group is received, or whenever the ring is mapped to a different\n * action. See wp_tablet_pad_group.mode_switch for more details.\n *\n * Clients are encouraged to provide context-aware descriptions for\n * the actions associated with the ring; compositors may use this\n * information to offer visual feedback about the button layout\n * (eg. on-screen displays).\n *\n * The provided string 'description' is a UTF-8 encoded string to be\n * associated with this ring, and is considered user-visible; general\n * internationalization rules apply.\n *\n * The serial argument will be that of the last\n * wp_tablet_pad_group.mode_switch event received for the group of this\n * ring. Requests providing other serials than the most recent one will be\n * ignored.\n */\nstatic inline void\nzwp_tablet_pad_ring_v2_set_feedback(struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, const char *description, uint32_t serial)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_pad_ring_v2,\n\t\t\t ZWP_TABLET_PAD_RING_V2_SET_FEEDBACK, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_ring_v2), 0, description, serial);\n}\n\n/**\n * @ingroup iface_zwp_tablet_pad_ring_v2\n *\n * This destroys the client's resource for this ring object.\n */\nstatic inline void\nzwp_tablet_pad_ring_v2_destroy(struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_pad_ring_v2,\n\t\t\t ZWP_TABLET_PAD_RING_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_ring_v2), WL_MARSHAL_FLAG_DESTROY);\n}\n\n#ifndef ZWP_TABLET_PAD_STRIP_V2_SOURCE_ENUM\n#define ZWP_TABLET_PAD_STRIP_V2_SOURCE_ENUM\n/**\n * @ingroup iface_zwp_tablet_pad_strip_v2\n * strip axis source\n *\n * Describes the source types for strip events. This indicates to the\n * client how a strip event was physically generated; a client may\n * adjust the user interface accordingly. For example, events\n * from a \"finger\" source may trigger kinetic scrolling.\n */\nenum zwp_tablet_pad_strip_v2_source {\n\t/**\n\t * finger\n\t */\n\tZWP_TABLET_PAD_STRIP_V2_SOURCE_FINGER = 1,\n};\n#endif /* ZWP_TABLET_PAD_STRIP_V2_SOURCE_ENUM */\n\n/**\n * @ingroup iface_zwp_tablet_pad_strip_v2\n * @struct zwp_tablet_pad_strip_v2_listener\n */\nstruct zwp_tablet_pad_strip_v2_listener {\n\t/**\n\t * strip event source\n\t *\n\t * Source information for strip events.\n\t *\n\t * This event does not occur on its own. It is sent before a\n\t * wp_tablet_pad_strip.frame event and carries the source\n\t * information for all events within that frame.\n\t *\n\t * The source specifies how this event was generated. If the source\n\t * is wp_tablet_pad_strip.source.finger, a wp_tablet_pad_strip.stop\n\t * event will be sent when the user lifts their finger off the\n\t * device.\n\t *\n\t * This event is optional. If the source is unknown for an\n\t * interaction, no event is sent.\n\t * @param source the event source\n\t */\n\tvoid (*source)(void *data,\n\t\t       struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,\n\t\t       uint32_t source);\n\t/**\n\t * position changed\n\t *\n\t * Sent whenever the position on a strip changes.\n\t *\n\t * The position is normalized to a range of [0, 65535], the 0-value\n\t * represents the top-most and/or left-most position of the strip\n\t * in the pad's current rotation.\n\t * @param position the current position\n\t */\n\tvoid (*position)(void *data,\n\t\t\t struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,\n\t\t\t uint32_t position);\n\t/**\n\t * interaction stopped\n\t *\n\t * Stop notification for strip events.\n\t *\n\t * For some wp_tablet_pad_strip.source types, a\n\t * wp_tablet_pad_strip.stop event is sent to notify a client that\n\t * the interaction with the strip has terminated. This enables the\n\t * client to implement kinetic scrolling. See the\n\t * wp_tablet_pad_strip.source documentation for information on when\n\t * this event may be generated.\n\t *\n\t * Any wp_tablet_pad_strip.position events with the same source\n\t * after this event should be considered as the start of a new\n\t * interaction.\n\t */\n\tvoid (*stop)(void *data,\n\t\t     struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2);\n\t/**\n\t * end of a strip event sequence\n\t *\n\t * Indicates the end of a set of events that represent one\n\t * logical hardware strip event. A client is expected to accumulate\n\t * the data in all events within the frame before proceeding.\n\t *\n\t * All wp_tablet_pad_strip events before a\n\t * wp_tablet_pad_strip.frame event belong logically together. For\n\t * example, on termination of a finger interaction on a strip the\n\t * compositor will send a wp_tablet_pad_strip.source event, a\n\t * wp_tablet_pad_strip.stop event and a wp_tablet_pad_strip.frame\n\t * event.\n\t *\n\t * A wp_tablet_pad_strip.frame event is sent for every logical\n\t * event group, even if the group only contains a single\n\t * wp_tablet_pad_strip event. Specifically, a client may get a\n\t * sequence: position, frame, position, frame, etc.\n\t * @param time timestamp with millisecond granularity\n\t */\n\tvoid (*frame)(void *data,\n\t\t      struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,\n\t\t      uint32_t time);\n};\n\n/**\n * @ingroup iface_zwp_tablet_pad_strip_v2\n */\nstatic inline int\nzwp_tablet_pad_strip_v2_add_listener(struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,\n\t\t\t\t     const struct zwp_tablet_pad_strip_v2_listener *listener, void *data)\n{\n\treturn wl_proxy_add_listener((struct wl_proxy *) zwp_tablet_pad_strip_v2,\n\t\t\t\t     (void (**)(void)) listener, data);\n}\n\n#define ZWP_TABLET_PAD_STRIP_V2_SET_FEEDBACK 0\n#define ZWP_TABLET_PAD_STRIP_V2_DESTROY 1\n\n/**\n * @ingroup iface_zwp_tablet_pad_strip_v2\n */\n#define ZWP_TABLET_PAD_STRIP_V2_SOURCE_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_strip_v2\n */\n#define ZWP_TABLET_PAD_STRIP_V2_POSITION_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_strip_v2\n */\n#define ZWP_TABLET_PAD_STRIP_V2_STOP_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_strip_v2\n */\n#define ZWP_TABLET_PAD_STRIP_V2_FRAME_SINCE_VERSION 1\n\n/**\n * @ingroup iface_zwp_tablet_pad_strip_v2\n */\n#define ZWP_TABLET_PAD_STRIP_V2_SET_FEEDBACK_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_strip_v2\n */\n#define ZWP_TABLET_PAD_STRIP_V2_DESTROY_SINCE_VERSION 1\n\n/** @ingroup iface_zwp_tablet_pad_strip_v2 */\nstatic inline void\nzwp_tablet_pad_strip_v2_set_user_data(struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_pad_strip_v2, user_data);\n}\n\n/** @ingroup iface_zwp_tablet_pad_strip_v2 */\nstatic inline void *\nzwp_tablet_pad_strip_v2_get_user_data(struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_pad_strip_v2);\n}\n\nstatic inline uint32_t\nzwp_tablet_pad_strip_v2_get_version(struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_strip_v2);\n}\n\n/**\n * @ingroup iface_zwp_tablet_pad_strip_v2\n *\n * Requests the compositor to use the provided feedback string\n * associated with this strip. This request should be issued immediately\n * after a wp_tablet_pad_group.mode_switch event from the corresponding\n * group is received, or whenever the strip is mapped to a different\n * action. See wp_tablet_pad_group.mode_switch for more details.\n *\n * Clients are encouraged to provide context-aware descriptions for\n * the actions associated with the strip, and compositors may use this\n * information to offer visual feedback about the button layout\n * (eg. on-screen displays).\n *\n * The provided string 'description' is a UTF-8 encoded string to be\n * associated with this ring, and is considered user-visible; general\n * internationalization rules apply.\n *\n * The serial argument will be that of the last\n * wp_tablet_pad_group.mode_switch event received for the group of this\n * strip. Requests providing other serials than the most recent one will be\n * ignored.\n */\nstatic inline void\nzwp_tablet_pad_strip_v2_set_feedback(struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, const char *description, uint32_t serial)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_pad_strip_v2,\n\t\t\t ZWP_TABLET_PAD_STRIP_V2_SET_FEEDBACK, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_strip_v2), 0, description, serial);\n}\n\n/**\n * @ingroup iface_zwp_tablet_pad_strip_v2\n *\n * This destroys the client's resource for this strip object.\n */\nstatic inline void\nzwp_tablet_pad_strip_v2_destroy(struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_pad_strip_v2,\n\t\t\t ZWP_TABLET_PAD_STRIP_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_strip_v2), WL_MARSHAL_FLAG_DESTROY);\n}\n\n/**\n * @ingroup iface_zwp_tablet_pad_group_v2\n * @struct zwp_tablet_pad_group_v2_listener\n */\nstruct zwp_tablet_pad_group_v2_listener {\n\t/**\n\t * buttons announced\n\t *\n\t * Sent on wp_tablet_pad_group initialization to announce the\n\t * available buttons in the group. Button indices start at 0, a\n\t * button may only be in one group at a time.\n\t *\n\t * This event is first sent in the initial burst of events before\n\t * the wp_tablet_pad_group.done event.\n\t *\n\t * Some buttons are reserved by the compositor. These buttons may\n\t * not be assigned to any wp_tablet_pad_group. Compositors may\n\t * broadcast this event in the case of changes to the mapping of\n\t * these reserved buttons. If the compositor happens to reserve all\n\t * buttons in a group, this event will be sent with an empty array.\n\t * @param buttons buttons in this group\n\t */\n\tvoid (*buttons)(void *data,\n\t\t\tstruct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,\n\t\t\tstruct wl_array *buttons);\n\t/**\n\t * ring announced\n\t *\n\t * Sent on wp_tablet_pad_group initialization to announce\n\t * available rings. One event is sent for each ring available on\n\t * this pad group.\n\t *\n\t * This event is sent in the initial burst of events before the\n\t * wp_tablet_pad_group.done event.\n\t */\n\tvoid (*ring)(void *data,\n\t\t     struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,\n\t\t     struct zwp_tablet_pad_ring_v2 *ring);\n\t/**\n\t * strip announced\n\t *\n\t * Sent on wp_tablet_pad initialization to announce available\n\t * strips. One event is sent for each strip available on this pad\n\t * group.\n\t *\n\t * This event is sent in the initial burst of events before the\n\t * wp_tablet_pad_group.done event.\n\t */\n\tvoid (*strip)(void *data,\n\t\t      struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,\n\t\t      struct zwp_tablet_pad_strip_v2 *strip);\n\t/**\n\t * mode-switch ability announced\n\t *\n\t * Sent on wp_tablet_pad_group initialization to announce that\n\t * the pad group may switch between modes. A client may use a mode\n\t * to store a specific configuration for buttons, rings and strips\n\t * and use the wl_tablet_pad_group.mode_switch event to toggle\n\t * between these configurations. Mode indices start at 0.\n\t *\n\t * Switching modes is compositor-dependent. See the\n\t * wp_tablet_pad_group.mode_switch event for more details.\n\t *\n\t * This event is sent in the initial burst of events before the\n\t * wp_tablet_pad_group.done event. This event is only sent when\n\t * more than more than one mode is available.\n\t * @param modes the number of modes\n\t */\n\tvoid (*modes)(void *data,\n\t\t      struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,\n\t\t      uint32_t modes);\n\t/**\n\t * tablet group description events sequence complete\n\t *\n\t * This event is sent immediately to signal the end of the\n\t * initial burst of descriptive events. A client may consider the\n\t * static description of the tablet to be complete and finalize\n\t * initialization of the tablet group.\n\t */\n\tvoid (*done)(void *data,\n\t\t     struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2);\n\t/**\n\t * mode switch event\n\t *\n\t * Notification that the mode was switched.\n\t *\n\t * A mode applies to all buttons, rings and strips in a group\n\t * simultaneously, but a client is not required to assign different\n\t * actions for each mode. For example, a client may have\n\t * mode-specific button mappings but map the ring to vertical\n\t * scrolling in all modes. Mode indices start at 0.\n\t *\n\t * Switching modes is compositor-dependent. The compositor may\n\t * provide visual cues to the client about the mode, e.g. by\n\t * toggling LEDs on the tablet device. Mode-switching may be\n\t * software-controlled or controlled by one or more physical\n\t * buttons. For example, on a Wacom Intuos Pro, the button inside\n\t * the ring may be assigned to switch between modes.\n\t *\n\t * The compositor will also send this event after\n\t * wp_tablet_pad.enter on each group in order to notify of the\n\t * current mode. Groups that only feature one mode will use mode=0\n\t * when emitting this event.\n\t *\n\t * If a button action in the new mode differs from the action in\n\t * the previous mode, the client should immediately issue a\n\t * wp_tablet_pad.set_feedback request for each changed button.\n\t *\n\t * If a ring or strip action in the new mode differs from the\n\t * action in the previous mode, the client should immediately issue\n\t * a wp_tablet_ring.set_feedback or wp_tablet_strip.set_feedback\n\t * request for each changed ring or strip.\n\t * @param time the time of the event with millisecond granularity\n\t * @param mode the new mode of the pad\n\t */\n\tvoid (*mode_switch)(void *data,\n\t\t\t    struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,\n\t\t\t    uint32_t time,\n\t\t\t    uint32_t serial,\n\t\t\t    uint32_t mode);\n};\n\n/**\n * @ingroup iface_zwp_tablet_pad_group_v2\n */\nstatic inline int\nzwp_tablet_pad_group_v2_add_listener(struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,\n\t\t\t\t     const struct zwp_tablet_pad_group_v2_listener *listener, void *data)\n{\n\treturn wl_proxy_add_listener((struct wl_proxy *) zwp_tablet_pad_group_v2,\n\t\t\t\t     (void (**)(void)) listener, data);\n}\n\n#define ZWP_TABLET_PAD_GROUP_V2_DESTROY 0\n\n/**\n * @ingroup iface_zwp_tablet_pad_group_v2\n */\n#define ZWP_TABLET_PAD_GROUP_V2_BUTTONS_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_group_v2\n */\n#define ZWP_TABLET_PAD_GROUP_V2_RING_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_group_v2\n */\n#define ZWP_TABLET_PAD_GROUP_V2_STRIP_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_group_v2\n */\n#define ZWP_TABLET_PAD_GROUP_V2_MODES_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_group_v2\n */\n#define ZWP_TABLET_PAD_GROUP_V2_DONE_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_group_v2\n */\n#define ZWP_TABLET_PAD_GROUP_V2_MODE_SWITCH_SINCE_VERSION 1\n\n/**\n * @ingroup iface_zwp_tablet_pad_group_v2\n */\n#define ZWP_TABLET_PAD_GROUP_V2_DESTROY_SINCE_VERSION 1\n\n/** @ingroup iface_zwp_tablet_pad_group_v2 */\nstatic inline void\nzwp_tablet_pad_group_v2_set_user_data(struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_pad_group_v2, user_data);\n}\n\n/** @ingroup iface_zwp_tablet_pad_group_v2 */\nstatic inline void *\nzwp_tablet_pad_group_v2_get_user_data(struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_pad_group_v2);\n}\n\nstatic inline uint32_t\nzwp_tablet_pad_group_v2_get_version(struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_group_v2);\n}\n\n/**\n * @ingroup iface_zwp_tablet_pad_group_v2\n *\n * Destroy the wp_tablet_pad_group object. Objects created from this object\n * are unaffected and should be destroyed separately.\n */\nstatic inline void\nzwp_tablet_pad_group_v2_destroy(struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_pad_group_v2,\n\t\t\t ZWP_TABLET_PAD_GROUP_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_group_v2), WL_MARSHAL_FLAG_DESTROY);\n}\n\n#ifndef ZWP_TABLET_PAD_V2_BUTTON_STATE_ENUM\n#define ZWP_TABLET_PAD_V2_BUTTON_STATE_ENUM\n/**\n * @ingroup iface_zwp_tablet_pad_v2\n * physical button state\n *\n * Describes the physical state of a button that caused the button\n * event.\n */\nenum zwp_tablet_pad_v2_button_state {\n\t/**\n\t * the button is not pressed\n\t */\n\tZWP_TABLET_PAD_V2_BUTTON_STATE_RELEASED = 0,\n\t/**\n\t * the button is pressed\n\t */\n\tZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED = 1,\n};\n#endif /* ZWP_TABLET_PAD_V2_BUTTON_STATE_ENUM */\n\n/**\n * @ingroup iface_zwp_tablet_pad_v2\n * @struct zwp_tablet_pad_v2_listener\n */\nstruct zwp_tablet_pad_v2_listener {\n\t/**\n\t * group announced\n\t *\n\t * Sent on wp_tablet_pad initialization to announce available\n\t * groups. One event is sent for each pad group available.\n\t *\n\t * This event is sent in the initial burst of events before the\n\t * wp_tablet_pad.done event. At least one group will be announced.\n\t */\n\tvoid (*group)(void *data,\n\t\t      struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,\n\t\t      struct zwp_tablet_pad_group_v2 *pad_group);\n\t/**\n\t * path to the device\n\t *\n\t * A system-specific device path that indicates which device is\n\t * behind this wp_tablet_pad. This information may be used to\n\t * gather additional information about the device, e.g. through\n\t * libwacom.\n\t *\n\t * The format of the path is unspecified, it may be a device node,\n\t * a sysfs path, or some other identifier. It is up to the client\n\t * to identify the string provided.\n\t *\n\t * This event is sent in the initial burst of events before the\n\t * wp_tablet_pad.done event.\n\t * @param path path to local device\n\t */\n\tvoid (*path)(void *data,\n\t\t     struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,\n\t\t     const char *path);\n\t/**\n\t * buttons announced\n\t *\n\t * Sent on wp_tablet_pad initialization to announce the available\n\t * buttons.\n\t *\n\t * This event is sent in the initial burst of events before the\n\t * wp_tablet_pad.done event. This event is only sent when at least\n\t * one button is available.\n\t * @param buttons the number of buttons\n\t */\n\tvoid (*buttons)(void *data,\n\t\t\tstruct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,\n\t\t\tuint32_t buttons);\n\t/**\n\t * pad description event sequence complete\n\t *\n\t * This event signals the end of the initial burst of descriptive\n\t * events. A client may consider the static description of the pad\n\t * to be complete and finalize initialization of the pad.\n\t */\n\tvoid (*done)(void *data,\n\t\t     struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2);\n\t/**\n\t * physical button state\n\t *\n\t * Sent whenever the physical state of a button changes.\n\t * @param time the time of the event with millisecond granularity\n\t * @param button the index of the button that changed state\n\t */\n\tvoid (*button)(void *data,\n\t\t       struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,\n\t\t       uint32_t time,\n\t\t       uint32_t button,\n\t\t       uint32_t state);\n\t/**\n\t * enter event\n\t *\n\t * Notification that this pad is focused on the specified\n\t * surface.\n\t * @param serial serial number of the enter event\n\t * @param tablet the tablet the pad is attached to\n\t * @param surface surface the pad is focused on\n\t */\n\tvoid (*enter)(void *data,\n\t\t      struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,\n\t\t      uint32_t serial,\n\t\t      struct zwp_tablet_v2 *tablet,\n\t\t      struct wl_surface *surface);\n\t/**\n\t * leave event\n\t *\n\t * Notification that this pad is no longer focused on the\n\t * specified surface.\n\t * @param serial serial number of the leave event\n\t * @param surface surface the pad is no longer focused on\n\t */\n\tvoid (*leave)(void *data,\n\t\t      struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,\n\t\t      uint32_t serial,\n\t\t      struct wl_surface *surface);\n\t/**\n\t * pad removed event\n\t *\n\t * Sent when the pad has been removed from the system. When a\n\t * tablet is removed its pad(s) will be removed too.\n\t *\n\t * When this event is received, the client must destroy all rings,\n\t * strips and groups that were offered by this pad, and issue\n\t * wp_tablet_pad.destroy the pad itself.\n\t */\n\tvoid (*removed)(void *data,\n\t\t\tstruct zwp_tablet_pad_v2 *zwp_tablet_pad_v2);\n};\n\n/**\n * @ingroup iface_zwp_tablet_pad_v2\n */\nstatic inline int\nzwp_tablet_pad_v2_add_listener(struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,\n\t\t\t       const struct zwp_tablet_pad_v2_listener *listener, void *data)\n{\n\treturn wl_proxy_add_listener((struct wl_proxy *) zwp_tablet_pad_v2,\n\t\t\t\t     (void (**)(void)) listener, data);\n}\n\n#define ZWP_TABLET_PAD_V2_SET_FEEDBACK 0\n#define ZWP_TABLET_PAD_V2_DESTROY 1\n\n/**\n * @ingroup iface_zwp_tablet_pad_v2\n */\n#define ZWP_TABLET_PAD_V2_GROUP_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_v2\n */\n#define ZWP_TABLET_PAD_V2_PATH_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_v2\n */\n#define ZWP_TABLET_PAD_V2_BUTTONS_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_v2\n */\n#define ZWP_TABLET_PAD_V2_DONE_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_v2\n */\n#define ZWP_TABLET_PAD_V2_BUTTON_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_v2\n */\n#define ZWP_TABLET_PAD_V2_ENTER_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_v2\n */\n#define ZWP_TABLET_PAD_V2_LEAVE_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_v2\n */\n#define ZWP_TABLET_PAD_V2_REMOVED_SINCE_VERSION 1\n\n/**\n * @ingroup iface_zwp_tablet_pad_v2\n */\n#define ZWP_TABLET_PAD_V2_SET_FEEDBACK_SINCE_VERSION 1\n/**\n * @ingroup iface_zwp_tablet_pad_v2\n */\n#define ZWP_TABLET_PAD_V2_DESTROY_SINCE_VERSION 1\n\n/** @ingroup iface_zwp_tablet_pad_v2 */\nstatic inline void\nzwp_tablet_pad_v2_set_user_data(struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) zwp_tablet_pad_v2, user_data);\n}\n\n/** @ingroup iface_zwp_tablet_pad_v2 */\nstatic inline void *\nzwp_tablet_pad_v2_get_user_data(struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) zwp_tablet_pad_v2);\n}\n\nstatic inline uint32_t\nzwp_tablet_pad_v2_get_version(struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_v2);\n}\n\n/**\n * @ingroup iface_zwp_tablet_pad_v2\n *\n * Requests the compositor to use the provided feedback string\n * associated with this button. This request should be issued immediately\n * after a wp_tablet_pad_group.mode_switch event from the corresponding\n * group is received, or whenever a button is mapped to a different\n * action. See wp_tablet_pad_group.mode_switch for more details.\n *\n * Clients are encouraged to provide context-aware descriptions for\n * the actions associated with each button, and compositors may use\n * this information to offer visual feedback on the button layout\n * (e.g. on-screen displays).\n *\n * Button indices start at 0. Setting the feedback string on a button\n * that is reserved by the compositor (i.e. not belonging to any\n * wp_tablet_pad_group) does not generate an error but the compositor\n * is free to ignore the request.\n *\n * The provided string 'description' is a UTF-8 encoded string to be\n * associated with this ring, and is considered user-visible; general\n * internationalization rules apply.\n *\n * The serial argument will be that of the last\n * wp_tablet_pad_group.mode_switch event received for the group of this\n * button. Requests providing other serials than the most recent one will\n * be ignored.\n */\nstatic inline void\nzwp_tablet_pad_v2_set_feedback(struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, uint32_t button, const char *description, uint32_t serial)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_pad_v2,\n\t\t\t ZWP_TABLET_PAD_V2_SET_FEEDBACK, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_v2), 0, button, description, serial);\n}\n\n/**\n * @ingroup iface_zwp_tablet_pad_v2\n *\n * Destroy the wp_tablet_pad object. Objects created from this object\n * are unaffected and should be destroyed separately.\n */\nstatic inline void\nzwp_tablet_pad_v2_destroy(struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zwp_tablet_pad_v2,\n\t\t\t ZWP_TABLET_PAD_V2_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_tablet_pad_v2), WL_MARSHAL_FLAG_DESTROY);\n}\n\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/sokol/tablet-unstable-v2-protocol.c",
    "content": "/* Generated by wayland-scanner 1.24.0 */\n\n/*\n * Copyright 2014 © Stephen \"Lyude\" Chandler Paul\n * Copyright 2015-2016 © Red Hat, Inc.\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation files\n * (the \"Software\"), to deal in the Software without restriction,\n * including without limitation the rights to use, copy, modify, merge,\n * publish, distribute, sublicense, and/or sell copies of the Software,\n * and to permit persons to whom the Software is furnished to do so,\n * subject to the following conditions:\n *\n * The above copyright notice and this permission notice (including the\n * next paragraph) shall be included in all copies or substantial\n * portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include \"wayland-util.h\"\n\n#ifndef __has_attribute\n# define __has_attribute(x) 0  /* Compatibility with non-clang compilers. */\n#endif\n\n#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)\n#define WL_PRIVATE __attribute__ ((visibility(\"hidden\")))\n#else\n#define WL_PRIVATE\n#endif\n\nextern const struct wl_interface wl_seat_interface;\nextern const struct wl_interface wl_surface_interface;\nextern const struct wl_interface zwp_tablet_pad_group_v2_interface;\nextern const struct wl_interface zwp_tablet_pad_ring_v2_interface;\nextern const struct wl_interface zwp_tablet_pad_strip_v2_interface;\nextern const struct wl_interface zwp_tablet_pad_v2_interface;\nextern const struct wl_interface zwp_tablet_seat_v2_interface;\nextern const struct wl_interface zwp_tablet_tool_v2_interface;\nextern const struct wl_interface zwp_tablet_v2_interface;\n\nstatic const struct wl_interface *tablet_unstable_v2_types[] = {\n\tNULL,\n\tNULL,\n\tNULL,\n\t&zwp_tablet_seat_v2_interface,\n\t&wl_seat_interface,\n\t&zwp_tablet_v2_interface,\n\t&zwp_tablet_tool_v2_interface,\n\t&zwp_tablet_pad_v2_interface,\n\tNULL,\n\t&wl_surface_interface,\n\tNULL,\n\tNULL,\n\tNULL,\n\t&zwp_tablet_v2_interface,\n\t&wl_surface_interface,\n\t&zwp_tablet_pad_ring_v2_interface,\n\t&zwp_tablet_pad_strip_v2_interface,\n\t&zwp_tablet_pad_group_v2_interface,\n\tNULL,\n\t&zwp_tablet_v2_interface,\n\t&wl_surface_interface,\n\tNULL,\n\t&wl_surface_interface,\n};\n\nstatic const struct wl_message zwp_tablet_manager_v2_requests[] = {\n\t{ \"get_tablet_seat\", \"no\", tablet_unstable_v2_types + 3 },\n\t{ \"destroy\", \"\", tablet_unstable_v2_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface zwp_tablet_manager_v2_interface = {\n\t\"zwp_tablet_manager_v2\", 1,\n\t2, zwp_tablet_manager_v2_requests,\n\t0, NULL,\n};\n\nstatic const struct wl_message zwp_tablet_seat_v2_requests[] = {\n\t{ \"destroy\", \"\", tablet_unstable_v2_types + 0 },\n};\n\nstatic const struct wl_message zwp_tablet_seat_v2_events[] = {\n\t{ \"tablet_added\", \"n\", tablet_unstable_v2_types + 5 },\n\t{ \"tool_added\", \"n\", tablet_unstable_v2_types + 6 },\n\t{ \"pad_added\", \"n\", tablet_unstable_v2_types + 7 },\n};\n\nWL_PRIVATE const struct wl_interface zwp_tablet_seat_v2_interface = {\n\t\"zwp_tablet_seat_v2\", 1,\n\t1, zwp_tablet_seat_v2_requests,\n\t3, zwp_tablet_seat_v2_events,\n};\n\nstatic const struct wl_message zwp_tablet_tool_v2_requests[] = {\n\t{ \"set_cursor\", \"u?oii\", tablet_unstable_v2_types + 8 },\n\t{ \"destroy\", \"\", tablet_unstable_v2_types + 0 },\n};\n\nstatic const struct wl_message zwp_tablet_tool_v2_events[] = {\n\t{ \"type\", \"u\", tablet_unstable_v2_types + 0 },\n\t{ \"hardware_serial\", \"uu\", tablet_unstable_v2_types + 0 },\n\t{ \"hardware_id_wacom\", \"uu\", tablet_unstable_v2_types + 0 },\n\t{ \"capability\", \"u\", tablet_unstable_v2_types + 0 },\n\t{ \"done\", \"\", tablet_unstable_v2_types + 0 },\n\t{ \"removed\", \"\", tablet_unstable_v2_types + 0 },\n\t{ \"proximity_in\", \"uoo\", tablet_unstable_v2_types + 12 },\n\t{ \"proximity_out\", \"\", tablet_unstable_v2_types + 0 },\n\t{ \"down\", \"u\", tablet_unstable_v2_types + 0 },\n\t{ \"up\", \"\", tablet_unstable_v2_types + 0 },\n\t{ \"motion\", \"ff\", tablet_unstable_v2_types + 0 },\n\t{ \"pressure\", \"u\", tablet_unstable_v2_types + 0 },\n\t{ \"distance\", \"u\", tablet_unstable_v2_types + 0 },\n\t{ \"tilt\", \"ff\", tablet_unstable_v2_types + 0 },\n\t{ \"rotation\", \"f\", tablet_unstable_v2_types + 0 },\n\t{ \"slider\", \"i\", tablet_unstable_v2_types + 0 },\n\t{ \"wheel\", \"fi\", tablet_unstable_v2_types + 0 },\n\t{ \"button\", \"uuu\", tablet_unstable_v2_types + 0 },\n\t{ \"frame\", \"u\", tablet_unstable_v2_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface zwp_tablet_tool_v2_interface = {\n\t\"zwp_tablet_tool_v2\", 1,\n\t2, zwp_tablet_tool_v2_requests,\n\t19, zwp_tablet_tool_v2_events,\n};\n\nstatic const struct wl_message zwp_tablet_v2_requests[] = {\n\t{ \"destroy\", \"\", tablet_unstable_v2_types + 0 },\n};\n\nstatic const struct wl_message zwp_tablet_v2_events[] = {\n\t{ \"name\", \"s\", tablet_unstable_v2_types + 0 },\n\t{ \"id\", \"uu\", tablet_unstable_v2_types + 0 },\n\t{ \"path\", \"s\", tablet_unstable_v2_types + 0 },\n\t{ \"done\", \"\", tablet_unstable_v2_types + 0 },\n\t{ \"removed\", \"\", tablet_unstable_v2_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface zwp_tablet_v2_interface = {\n\t\"zwp_tablet_v2\", 1,\n\t1, zwp_tablet_v2_requests,\n\t5, zwp_tablet_v2_events,\n};\n\nstatic const struct wl_message zwp_tablet_pad_ring_v2_requests[] = {\n\t{ \"set_feedback\", \"su\", tablet_unstable_v2_types + 0 },\n\t{ \"destroy\", \"\", tablet_unstable_v2_types + 0 },\n};\n\nstatic const struct wl_message zwp_tablet_pad_ring_v2_events[] = {\n\t{ \"source\", \"u\", tablet_unstable_v2_types + 0 },\n\t{ \"angle\", \"f\", tablet_unstable_v2_types + 0 },\n\t{ \"stop\", \"\", tablet_unstable_v2_types + 0 },\n\t{ \"frame\", \"u\", tablet_unstable_v2_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface zwp_tablet_pad_ring_v2_interface = {\n\t\"zwp_tablet_pad_ring_v2\", 1,\n\t2, zwp_tablet_pad_ring_v2_requests,\n\t4, zwp_tablet_pad_ring_v2_events,\n};\n\nstatic const struct wl_message zwp_tablet_pad_strip_v2_requests[] = {\n\t{ \"set_feedback\", \"su\", tablet_unstable_v2_types + 0 },\n\t{ \"destroy\", \"\", tablet_unstable_v2_types + 0 },\n};\n\nstatic const struct wl_message zwp_tablet_pad_strip_v2_events[] = {\n\t{ \"source\", \"u\", tablet_unstable_v2_types + 0 },\n\t{ \"position\", \"u\", tablet_unstable_v2_types + 0 },\n\t{ \"stop\", \"\", tablet_unstable_v2_types + 0 },\n\t{ \"frame\", \"u\", tablet_unstable_v2_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface zwp_tablet_pad_strip_v2_interface = {\n\t\"zwp_tablet_pad_strip_v2\", 1,\n\t2, zwp_tablet_pad_strip_v2_requests,\n\t4, zwp_tablet_pad_strip_v2_events,\n};\n\nstatic const struct wl_message zwp_tablet_pad_group_v2_requests[] = {\n\t{ \"destroy\", \"\", tablet_unstable_v2_types + 0 },\n};\n\nstatic const struct wl_message zwp_tablet_pad_group_v2_events[] = {\n\t{ \"buttons\", \"a\", tablet_unstable_v2_types + 0 },\n\t{ \"ring\", \"n\", tablet_unstable_v2_types + 15 },\n\t{ \"strip\", \"n\", tablet_unstable_v2_types + 16 },\n\t{ \"modes\", \"u\", tablet_unstable_v2_types + 0 },\n\t{ \"done\", \"\", tablet_unstable_v2_types + 0 },\n\t{ \"mode_switch\", \"uuu\", tablet_unstable_v2_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface zwp_tablet_pad_group_v2_interface = {\n\t\"zwp_tablet_pad_group_v2\", 1,\n\t1, zwp_tablet_pad_group_v2_requests,\n\t6, zwp_tablet_pad_group_v2_events,\n};\n\nstatic const struct wl_message zwp_tablet_pad_v2_requests[] = {\n\t{ \"set_feedback\", \"usu\", tablet_unstable_v2_types + 0 },\n\t{ \"destroy\", \"\", tablet_unstable_v2_types + 0 },\n};\n\nstatic const struct wl_message zwp_tablet_pad_v2_events[] = {\n\t{ \"group\", \"n\", tablet_unstable_v2_types + 17 },\n\t{ \"path\", \"s\", tablet_unstable_v2_types + 0 },\n\t{ \"buttons\", \"u\", tablet_unstable_v2_types + 0 },\n\t{ \"done\", \"\", tablet_unstable_v2_types + 0 },\n\t{ \"button\", \"uuu\", tablet_unstable_v2_types + 0 },\n\t{ \"enter\", \"uoo\", tablet_unstable_v2_types + 18 },\n\t{ \"leave\", \"uo\", tablet_unstable_v2_types + 21 },\n\t{ \"removed\", \"\", tablet_unstable_v2_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface zwp_tablet_pad_v2_interface = {\n\t\"zwp_tablet_pad_v2\", 1,\n\t2, zwp_tablet_pad_v2_requests,\n\t8, zwp_tablet_pad_v2_events,\n};\n\n"
  },
  {
    "path": "thirdparty/sokol/util/sokol_fontstash.h",
    "content": "#if defined(SOKOL_IMPL) && !defined(SOKOL_FONTSTASH_IMPL)\n#define SOKOL_FONTSTASH_IMPL\n#endif\n#ifndef SOKOL_FONTSTASH_INCLUDED\n/*\n    sokol_fontstash.h -- renderer for https://github.com/memononen/fontstash\n                         on top of sokol_gl.h\n\n    Project URL: https://github.com/floooh/sokol\n\n    Do this:\n        #define SOKOL_IMPL or\n        #define SOKOL_FONTSTASH_IMPL\n\n    before you include this file in *one* C or C++ file to create the\n    implementation.\n\n    The following defines are used by the implementation to select the\n    platform-specific embedded shader code (these are the same defines as\n    used by sokol_gfx.h and sokol_app.h):\n\n    SOKOL_GLCORE\n    SOKOL_GLES3\n    SOKOL_D3D11\n    SOKOL_METAL\n\n    ...optionally provide the following macros to override defaults:\n\n    SOKOL_ASSERT(c)     - your own assert macro (default: assert(c))\n    SOKOL_FONTSTASH_API_DECL    - public function declaration prefix (default: extern)\n    SOKOL_API_DECL      - same as SOKOL_FONTSTASH_API_DECL\n    SOKOL_API_IMPL      - public function implementation prefix (default: -)\n    SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))\n\n    Include the following headers before including sokol_fontstash.h:\n\n        sokol_gfx.h\n\n    Additionally include the following headers for including the sokol_fontstash.h\n    implementation:\n\n        sokol_gl.h\n\n    HOW TO\n    ======\n    --- First initialize sokol-gfx and sokol-gl as usual:\n\n            sg_setup(&(sg_desc){...});\n            sgl_setup(&(sgl_desc){...});\n\n    --- Create at least one fontstash context with sfons_create() (this replaces\n        glfonsCreate() from fontstash.h's example GL renderer:\n\n            FONScontext* ctx = sfons_create(&(sfons_desc_t){\n                .width = atlas_width,\n                .height = atlas_height,\n            });\n\n        Each FONScontext manages one font atlas texture which can hold rasterized\n        glyphs for multiple fonts.\n\n    --- From here on, use fontstash.h's functions \"as usual\" to add TTF\n        font data and draw text. Note that (just like with sokol-gl), text\n        rendering can happen anywhere in the frame, not only inside\n        a sokol-gfx rendering pass.\n\n    --- You can use the helper function\n\n            uint32_t sfons_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a)\n\n        To convert a 0..255 RGBA color into a packed uint32_t color value\n        expected by fontstash.h.\n\n    --- Once per frame before calling sgl_draw(), call:\n\n            sfons_flush(FONScontext* ctx)\n\n        ...this will update the dynamic sokol-gfx texture with the latest font\n        atlas content.\n\n    --- To actually render the text (and any other sokol-gl draw commands),\n        call sgl_draw() inside a sokol-gfx frame.\n\n    --- NOTE that you can mix fontstash.h calls with sokol-gl calls to mix\n        text rendering with sokol-gl rendering. You can also use\n        sokol-gl's matrix stack to position fontstash.h text in 3D.\n\n    --- finally on application shutdown, call:\n\n            sfons_destroy(FONScontext* ctx)\n\n        before sgl_shutdown() and sg_shutdown()\n\n\n    WHAT HAPPENS UNDER THE HOOD:\n    ============================\n\n    FONScontext* sfons_create(const sfons_desc_t* desc)\n        - creates a sokol-gfx shader compatible with sokol-gl\n        - creates an sgl_pipeline object with alpha-blending using\n          this shader\n        - creates a 1-byte-per-pixel font atlas texture via sokol-gfx\n          (pixel format SG_PIXELFORMAT_R8)\n\n    fonsDrawText():\n        - this will call the following sequence of sokol-gl functions:\n\n            sgl_enable_texture();\n            sgl_texture(...);\n            sgl_push_pipeline();\n            sgl_load_pipeline(...);\n            sgl_begin_triangles();\n            for each vertex:\n                sgl_v2f_t2f_c1i(...);\n            sgl_end();\n            sgl_pop_pipeline();\n            sgl_disable_texture();\n\n        - note that sokol-gl will merge several sgl_*_begin/sgl_end pairs\n          into a single draw call if no relevant state has changed, typically\n          all calls to fonsDrawText() will be merged into a single draw call\n          as long as all calls use the same FONScontext\n\n    sfons_flush(FONScontext* ctx):\n        - this will call sg_update_image() on the font atlas texture\n          if fontstash.h has added any rasterized glyphs since the last\n          frame\n\n    sfons_destroy(FONScontext* ctx):\n        - destroy the font atlas texture, sgl_pipeline and sg_shader objects\n\n\n    MEMORY ALLOCATION OVERRIDE\n    ==========================\n    You can override the memory allocation functions at initialization time\n    like this:\n\n        void* my_alloc(size_t size, void* user_data) {\n            return malloc(size);\n        }\n\n        void my_free(void* ptr, void* user_data) {\n            free(ptr);\n        }\n\n        ...\n        FONScontext* fons_context = sfons_create(&(sfons_desc_t){\n            ...\n            .allocator = {\n                .alloc_fn = my_alloc,\n                .free_fn = my_free,\n                .user_data = ...,\n            }\n        });\n        ...\n\n    If no overrides are provided, malloc and free will be used. Please\n    note that this doesn't affect any memory allocation performed\n    in fontstash.h (unfortunately those are hardwired to malloc/free).\n\n    LICENSE\n    =======\n    zlib/libpng license\n\n    Copyright (c) 2018 Andre Weissflog\n\n    This software is provided 'as-is', without any express or implied warranty.\n    In no event will the authors be held liable for any damages arising from the\n    use of this software.\n\n    Permission is granted to anyone to use this software for any purpose,\n    including commercial applications, and to alter it and redistribute it\n    freely, subject to the following restrictions:\n\n        1. The origin of this software must not be misrepresented; you must not\n        claim that you wrote the original software. If you use this software in a\n        product, an acknowledgment in the product documentation would be\n        appreciated but is not required.\n\n        2. Altered source versions must be plainly marked as such, and must not\n        be misrepresented as being the original software.\n\n        3. This notice may not be removed or altered from any source\n        distribution.\n*/\n#define SOKOL_FONTSTASH_INCLUDED (1)\n#include <stdint.h>\n#include <stdlib.h>\n#include <stddef.h> // size_t\n\n#if !defined(SOKOL_GFX_INCLUDED)\n#error \"Please include sokol_gfx.h before sokol_fontstash.h\"\n#endif\n\n#if defined(SOKOL_API_DECL) && !defined(SOKOL_FONTSTASH_API_DECL)\n#define SOKOL_FONTSTASH_API_DECL SOKOL_API_DECL\n#endif\n#ifndef SOKOL_FONTSTASH_API_DECL\n#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_FONTSTASH_IMPL)\n#define SOKOL_FONTSTASH_API_DECL __declspec(dllexport)\n#elif defined(_WIN32) && defined(SOKOL_DLL)\n#define SOKOL_FONTSTASH_API_DECL __declspec(dllimport)\n#else\n#define SOKOL_FONTSTASH_API_DECL extern\n#endif\n#endif\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n    sfonst_allocator_t\n\n    Used in sfons_desc_t to provide custom memory-alloc and -free functions\n    to sokol_fontstash.h. If memory management should be overridden, both the\n    alloc_fn and free_fn function must be provided (e.g. it's not valid to\n    override one function but not the other).\n\n    NOTE that this does not affect memory allocation calls inside\n    fontstash.h\n*/\ntypedef struct sfons_allocator_t {\n    void* (*alloc_fn)(size_t size, void* user_data);\n    void (*free_fn)(void* ptr, void* user_data);\n    void* user_data;\n} sfons_allocator_t;\n\ntypedef struct sfons_desc_t {\n    int width;    // initial width of font atlas texture (default: 512, must be power of 2)\n    int height;   // initial height of font atlas texture (default: 512, must be power of 2)\n    sfons_allocator_t allocator;    // optional memory allocation overrides\n} sfons_desc_t;\n\nSOKOL_FONTSTASH_API_DECL FONScontext* sfons_create(const sfons_desc_t* desc);\nSOKOL_FONTSTASH_API_DECL void sfons_destroy(FONScontext* ctx);\nSOKOL_FONTSTASH_API_DECL void sfons_flush(FONScontext* ctx);\nSOKOL_FONTSTASH_API_DECL uint32_t sfons_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n#endif /* SOKOL_FONTSTASH_INCLUDED */\n\n/*-- IMPLEMENTATION ----------------------------------------------------------*/\n#ifdef SOKOL_FONTSTASH_IMPL\n#define SOKOL_FONTSTASH_IMPL_INCLUDED (1)\n\n#if defined(SOKOL_MALLOC) || defined(SOKOL_CALLOC) || defined(SOKOL_FREE)\n#error \"SOKOL_MALLOC/CALLOC/FREE macros are no longer supported, please use sfons_desc_t.allocator to override memory allocation functions\"\n#endif\n\n#include <string.h>     // memset, memcpy\n#include <stdlib.h>     // malloc, free\n\n#if !defined(SOKOL_GL_INCLUDED)\n#error \"Please include sokol_gl.h before sokol_fontstash.h\"\n#endif\n#if !defined(FONS_H)\n#error \"Please include fontstash.h before sokol_fontstash.h\"\n#endif\n\n#ifndef SOKOL_API_IMPL\n    #define SOKOL_API_IMPL\n#endif\n#ifndef SOKOL_DEBUG\n    #ifndef NDEBUG\n        #define SOKOL_DEBUG\n    #endif\n#endif\n#ifndef SOKOL_ASSERT\n    #include <assert.h>\n    #define SOKOL_ASSERT(c) assert(c)\n#endif\n#ifndef SOKOL_UNREACHABLE\n    #define SOKOL_UNREACHABLE SOKOL_ASSERT(false)\n#endif\n#ifndef _SOKOL_UNUSED\n    #define _SOKOL_UNUSED(x) (void)(x)\n#endif\n\n#if defined(SOKOL_GLCORE)\n/*\n    Embedded source code compiled with:\n\n    sokol-shdc -i sfons.glsl -o sfons.h -l glsl410:glsl300es:hlsl4:metal_macos:metal_ios:metal_sim:wgsl -b\n\n    (not that for Metal and D3D11 byte code, sokol-shdc must be run\n    on macOS and Windows)\n\n    @vs vs\n    uniform vs_params {\n        uniform mat4 mvp;\n        uniform mat4 tm;\n    };\n    in vec4 position;\n    in vec2 texcoord0;\n    in vec4 color0;\n    in float psize;\n    out vec4 uv;\n    out vec4 color;\n    void main() {\n        gl_Position = mvp * position;\n        #ifndef SOKOL_WGSL\n        gl_PointSize = psize;\n        #endif\n        uv = tm * vec4(texcoord0, 0.0, 1.0);\n        color = color0;\n    }\n    @end\n\n    @fs fs\n    uniform texture2D tex;\n    uniform sampler smp;\n    in vec4 uv;\n    in vec4 color;\n    out vec4 frag_color;\n    void main() {\n        frag_color = vec4(1.0, 1.0, 1.0, texture(sampler2D(tex, smp), uv.xy).r) * color;\n    }\n    @end\n\n    @program sfontstash vs fs\n*/\nstatic const uint8_t _sfons_vs_source_glsl410[520] = {\n    0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x75,0x6e,\n    0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x76,0x73,0x5f,0x70,0x61,\n    0x72,0x61,0x6d,0x73,0x5b,0x38,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,\n    0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,\n    0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,\n    0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,\n    0x3d,0x20,0x33,0x29,0x20,0x69,0x6e,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x73,\n    0x69,0x7a,0x65,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,\n    0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,\n    0x63,0x34,0x20,0x75,0x76,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,\n    0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69,0x6e,0x20,0x76,\n    0x65,0x63,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x3b,0x0a,0x6c,\n    0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,\n    0x20,0x31,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,\n    0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,\n    0x69,0x6f,0x6e,0x20,0x3d,0x20,0x32,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,\n    0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,\n    0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,\n    0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x76,\n    0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2c,0x20,0x76,0x73,0x5f,\n    0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,\n    0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,\n    0x6d,0x73,0x5b,0x33,0x5d,0x29,0x20,0x2a,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,\n    0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x69,0x6e,0x74,0x53,\n    0x69,0x7a,0x65,0x20,0x3d,0x20,0x70,0x73,0x69,0x7a,0x65,0x3b,0x0a,0x20,0x20,0x20,\n    0x20,0x75,0x76,0x20,0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x76,0x73,0x5f,0x70,0x61,\n    0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,\n    0x6d,0x73,0x5b,0x35,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,\n    0x5b,0x36,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x37,\n    0x5d,0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x34,0x28,0x74,0x65,0x78,0x63,0x6f,0x6f,\n    0x72,0x64,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,\n    0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,\n    0x72,0x30,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,\n};\nstatic const uint8_t _sfons_fs_source_glsl410[245] = {\n    0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x75,0x6e,\n    0x69,0x66,0x6f,0x72,0x6d,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x32,0x44,0x20,\n    0x74,0x65,0x78,0x5f,0x73,0x6d,0x70,0x3b,0x0a,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,\n    0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x6f,\n    0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,\n    0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,\n    0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,\n    0x20,0x75,0x76,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,\n    0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,\n    0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,\n    0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,\n    0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x31,0x2e,\n    0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x74,0x65,0x78,\n    0x74,0x75,0x72,0x65,0x28,0x74,0x65,0x78,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x75,0x76,\n    0x2e,0x78,0x79,0x29,0x2e,0x78,0x29,0x20,0x2a,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,\n    0x0a,0x7d,0x0a,0x0a,0x00,\n};\n#elif defined(SOKOL_GLES3)\nstatic const uint8_t _sfons_vs_source_glsl300es[481] = {\n    0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a,\n    0x0a,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x76,0x73,\n    0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x38,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,\n    0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,\n    0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,\n    0x6e,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,\n    0x6f,0x6e,0x20,0x3d,0x20,0x33,0x29,0x20,0x69,0x6e,0x20,0x66,0x6c,0x6f,0x61,0x74,\n    0x20,0x70,0x73,0x69,0x7a,0x65,0x3b,0x0a,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,\n    0x20,0x75,0x76,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,\n    0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,\n    0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x3b,0x0a,0x6f,0x75,0x74,\n    0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,\n    0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x32,\n    0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,\n    0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,\n    0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,\n    0x20,0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,\n    0x73,0x5b,0x30,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,\n    0x31,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,\n    0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x33,0x5d,0x29,0x20,\n    0x2a,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,\n    0x67,0x6c,0x5f,0x50,0x6f,0x69,0x6e,0x74,0x53,0x69,0x7a,0x65,0x20,0x3d,0x20,0x70,\n    0x73,0x69,0x7a,0x65,0x3b,0x0a,0x20,0x20,0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x6d,\n    0x61,0x74,0x34,0x28,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,\n    0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x35,0x5d,0x2c,0x20,\n    0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x36,0x5d,0x2c,0x20,0x76,0x73,\n    0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x37,0x5d,0x29,0x20,0x2a,0x20,0x76,0x65,\n    0x63,0x34,0x28,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x2c,0x20,0x30,0x2e,\n    0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,\n    0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x7d,0x0a,0x0a,\n    0x00,\n};\nstatic const uint8_t _sfons_fs_source_glsl300es[276] = {\n    0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a,\n    0x70,0x72,0x65,0x63,0x69,0x73,0x69,0x6f,0x6e,0x20,0x6d,0x65,0x64,0x69,0x75,0x6d,\n    0x70,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3b,0x0a,0x70,0x72,0x65,0x63,0x69,0x73,0x69,\n    0x6f,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x69,0x6e,0x74,0x3b,0x0a,0x0a,0x75,\n    0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x73,0x61,0x6d,\n    0x70,0x6c,0x65,0x72,0x32,0x44,0x20,0x74,0x65,0x78,0x5f,0x73,0x6d,0x70,0x3b,0x0a,\n    0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,\n    0x20,0x3d,0x20,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x68,0x69,0x67,0x68,0x70,0x20,\n    0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,\n    0x0a,0x69,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x34,0x20,0x75,\n    0x76,0x3b,0x0a,0x69,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x34,\n    0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,\n    0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,\n    0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x31,0x2e,0x30,\n    0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x74,0x65,0x78,0x74,\n    0x75,0x72,0x65,0x28,0x74,0x65,0x78,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x75,0x76,0x2e,\n    0x78,0x79,0x29,0x2e,0x78,0x29,0x20,0x2a,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,\n    0x7d,0x0a,0x0a,0x00,\n};\n#elif defined(SOKOL_METAL)\nstatic const uint8_t _sfons_vs_bytecode_metal_macos[3317] = {\n    0x4d,0x54,0x4c,0x42,0x01,0x80,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0xf5,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x01,0x00,0x00,0x00,0x00,0x00,0x00,\n    0xe0,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,\n    0x4e,0x41,0x4d,0x45,0x06,0x00,0x6d,0x61,0x69,0x6e,0x30,0x00,0x54,0x59,0x50,0x45,\n    0x01,0x00,0x00,0x48,0x41,0x53,0x48,0x20,0x00,0x76,0x25,0x5f,0x37,0x22,0xd0,0x3f,\n    0x64,0xef,0xff,0xc3,0x45,0x1a,0x3d,0xb7,0x5e,0x83,0x13,0x96,0xd3,0x09,0xec,0x53,\n    0x25,0xd5,0x7e,0x0c,0xed,0xb9,0x58,0x34,0x02,0x4f,0x46,0x46,0x54,0x18,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x45,0x52,0x53,0x08,0x00,0x01,0x00,0x08,\n    0x00,0x01,0x00,0x01,0x00,0x45,0x4e,0x44,0x54,0x40,0x00,0x00,0x00,0x56,0x41,0x54,\n    0x54,0x2a,0x00,0x04,0x00,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x00,0x80,\n    0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x00,0x01,0x80,0x63,0x6f,0x6c,0x6f,\n    0x72,0x30,0x00,0x02,0x80,0x70,0x73,0x69,0x7a,0x65,0x00,0x03,0x80,0x56,0x41,0x54,\n    0x59,0x06,0x00,0x04,0x00,0x06,0x04,0x06,0x03,0x45,0x4e,0x44,0x54,0x04,0x00,0x00,\n    0x00,0x45,0x4e,0x44,0x54,0xde,0xc0,0x17,0x0b,0x00,0x00,0x00,0x00,0x14,0x00,0x00,\n    0x00,0xc4,0x0b,0x00,0x00,0xff,0xff,0xff,0xff,0x42,0x43,0xc0,0xde,0x21,0x0c,0x00,\n    0x00,0xee,0x02,0x00,0x00,0x0b,0x82,0x20,0x00,0x02,0x00,0x00,0x00,0x12,0x00,0x00,\n    0x00,0x07,0x81,0x23,0x91,0x41,0xc8,0x04,0x49,0x06,0x10,0x32,0x39,0x92,0x01,0x84,\n    0x0c,0x25,0x05,0x08,0x19,0x1e,0x04,0x8b,0x62,0x80,0x14,0x45,0x02,0x42,0x92,0x0b,\n    0x42,0xa4,0x10,0x32,0x14,0x38,0x08,0x18,0x49,0x0a,0x32,0x44,0x24,0x48,0x0a,0x90,\n    0x21,0x23,0xc4,0x52,0x80,0x0c,0x19,0x21,0x72,0x24,0x07,0xc8,0x48,0x11,0x62,0xa8,\n    0xa0,0xa8,0x40,0xc6,0xf0,0x01,0x00,0x00,0x00,0x51,0x18,0x00,0x00,0x81,0x00,0x00,\n    0x00,0x1b,0xc8,0x25,0xf8,0xff,0xff,0xff,0xff,0x01,0x90,0x80,0x8a,0x18,0x87,0x77,\n    0x90,0x07,0x79,0x28,0x87,0x71,0xa0,0x07,0x76,0xc8,0x87,0x36,0x90,0x87,0x77,0xa8,\n    0x07,0x77,0x20,0x87,0x72,0x20,0x87,0x36,0x20,0x87,0x74,0xb0,0x87,0x74,0x20,0x87,\n    0x72,0x68,0x83,0x79,0x88,0x07,0x79,0xa0,0x87,0x36,0x30,0x07,0x78,0x68,0x83,0x76,\n    0x08,0x07,0x7a,0x40,0x07,0xc0,0x1c,0xc2,0x81,0x1d,0xe6,0xa1,0x1c,0x00,0x82,0x1c,\n    0xd2,0x61,0x1e,0xc2,0x41,0x1c,0xd8,0xa1,0x1c,0xda,0x80,0x1e,0xc2,0x21,0x1d,0xd8,\n    0xa1,0x0d,0xc6,0x21,0x1c,0xd8,0x81,0x1d,0xe6,0x01,0x30,0x87,0x70,0x60,0x87,0x79,\n    0x28,0x07,0x80,0x60,0x87,0x72,0x98,0x87,0x79,0x68,0x03,0x78,0x90,0x87,0x72,0x18,\n    0x87,0x74,0x98,0x87,0x72,0x68,0x03,0x73,0x80,0x87,0x76,0x08,0x07,0x72,0x00,0xcc,\n    0x21,0x1c,0xd8,0x61,0x1e,0xca,0x01,0x20,0xdc,0xe1,0x1d,0xda,0xc0,0x1c,0xe4,0x21,\n    0x1c,0xda,0xa1,0x1c,0xda,0x00,0x1e,0xde,0x21,0x1d,0xdc,0x81,0x1e,0xca,0x41,0x1e,\n    0xda,0xa0,0x1c,0xd8,0x21,0x1d,0xda,0x01,0xa0,0x07,0x79,0xa8,0x87,0x72,0x00,0x06,\n    0x77,0x78,0x87,0x36,0x30,0x07,0x79,0x08,0x87,0x76,0x28,0x87,0x36,0x80,0x87,0x77,\n    0x48,0x07,0x77,0xa0,0x87,0x72,0x90,0x87,0x36,0x28,0x07,0x76,0x48,0x87,0x76,0x68,\n    0x03,0x77,0x78,0x07,0x77,0x68,0x03,0x76,0x28,0x87,0x70,0x30,0x07,0x80,0x70,0x87,\n    0x77,0x68,0x83,0x74,0x70,0x07,0x73,0x98,0x87,0x36,0x30,0x07,0x78,0x68,0x83,0x76,\n    0x08,0x07,0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,0xdc,0xe1,0x1d,\n    0xda,0x40,0x1d,0xea,0xa1,0x1d,0xe0,0xa1,0x0d,0xe8,0x21,0x1c,0xc4,0x81,0x1d,0xca,\n    0x61,0x1e,0x00,0x73,0x08,0x07,0x76,0x98,0x87,0x72,0x00,0x08,0x77,0x78,0x87,0x36,\n    0x70,0x87,0x70,0x70,0x87,0x79,0x68,0x03,0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,\n    0x07,0x74,0x00,0xe8,0x41,0x1e,0xea,0xa1,0x1c,0x00,0xc2,0x1d,0xde,0xa1,0x0d,0xe6,\n    0x21,0x1d,0xce,0xc1,0x1d,0xca,0x81,0x1c,0xda,0x40,0x1f,0xca,0x41,0x1e,0xde,0x61,\n    0x1e,0xda,0xc0,0x1c,0xe0,0xa1,0x0d,0xda,0x21,0x1c,0xe8,0x01,0x1d,0x00,0x7a,0x90,\n    0x87,0x7a,0x28,0x07,0x80,0x70,0x87,0x77,0x68,0x03,0x7a,0x90,0x87,0x70,0x80,0x07,\n    0x78,0x48,0x07,0x77,0x38,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xe8,0x41,\n    0x1e,0xea,0xa1,0x1c,0x00,0x62,0x1e,0xe8,0x21,0x1c,0xc6,0x61,0x1d,0xda,0x00,0x1e,\n    0xe4,0xe1,0x1d,0xe8,0xa1,0x1c,0xc6,0x81,0x1e,0xde,0x41,0x1e,0xda,0x40,0x1c,0xea,\n    0xc1,0x1c,0xcc,0xa1,0x1c,0xe4,0xa1,0x0d,0xe6,0x21,0x1d,0xf4,0xa1,0x1c,0x00,0x3c,\n    0x00,0x88,0x7a,0x70,0x87,0x79,0x08,0x07,0x73,0x28,0x87,0x36,0x30,0x07,0x78,0x68,\n    0x83,0x76,0x08,0x07,0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,0xea,\n    0x61,0x1e,0xca,0xa1,0x0d,0xe6,0xe1,0x1d,0xcc,0x81,0x1e,0xda,0xc0,0x1c,0xd8,0xe1,\n    0x1d,0xc2,0x81,0x1e,0x00,0x73,0x08,0x07,0x76,0x98,0x87,0x72,0x00,0x36,0x18,0x42,\n    0x01,0x2c,0x40,0x05,0x00,0x49,0x18,0x00,0x00,0x01,0x00,0x00,0x00,0x13,0x84,0x40,\n    0x00,0x89,0x20,0x00,0x00,0x20,0x00,0x00,0x00,0x32,0x22,0x48,0x09,0x20,0x64,0x85,\n    0x04,0x93,0x22,0xa4,0x84,0x04,0x93,0x22,0xe3,0x84,0xa1,0x90,0x14,0x12,0x4c,0x8a,\n    0x8c,0x0b,0x84,0xa4,0x4c,0x10,0x44,0x33,0x00,0xc3,0x08,0x04,0x60,0x89,0x10,0x02,\n    0x18,0x46,0x10,0x80,0x24,0x08,0x33,0x51,0xf3,0x40,0x0f,0xf2,0x50,0x0f,0xe3,0x40,\n    0x0f,0x6e,0xd0,0x0e,0xe5,0x40,0x0f,0xe1,0xc0,0x0e,0x7a,0xa0,0x07,0xed,0x10,0x0e,\n    0xf4,0x20,0x0f,0xe9,0x80,0x0f,0x28,0x20,0x07,0x49,0x53,0x44,0x09,0x93,0x5f,0x49,\n    0xff,0x03,0x44,0x00,0x23,0x21,0xa1,0x94,0x41,0x04,0x43,0x28,0x86,0x08,0x23,0x80,\n    0x43,0x68,0x20,0x60,0x8e,0x00,0x0c,0x52,0x60,0xcd,0x11,0x80,0xc2,0x20,0x42,0x20,\n    0x0c,0x23,0x10,0xcb,0x08,0x00,0x00,0x00,0x00,0x13,0xb2,0x70,0x48,0x07,0x79,0xb0,\n    0x03,0x3a,0x68,0x83,0x70,0x80,0x07,0x78,0x60,0x87,0x72,0x68,0x83,0x76,0x08,0x87,\n    0x71,0x78,0x87,0x79,0xc0,0x87,0x38,0x80,0x03,0x37,0x88,0x83,0x38,0x70,0x03,0x38,\n    0xd8,0x70,0x1b,0xe5,0xd0,0x06,0xf0,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,\n    0xa0,0x07,0x76,0x40,0x07,0x6d,0x90,0x0e,0x71,0xa0,0x07,0x78,0xa0,0x07,0x78,0xd0,\n    0x06,0xe9,0x80,0x07,0x7a,0x80,0x07,0x7a,0x80,0x07,0x6d,0x90,0x0e,0x71,0x60,0x07,\n    0x7a,0x10,0x07,0x76,0xa0,0x07,0x71,0x60,0x07,0x6d,0x90,0x0e,0x73,0x20,0x07,0x7a,\n    0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x6d,0x90,0x0e,0x76,0x40,0x07,0x7a,0x60,\n    0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x6d,0x60,0x0e,0x73,0x20,0x07,0x7a,0x30,0x07,\n    0x72,0xa0,0x07,0x73,0x20,0x07,0x6d,0x60,0x0e,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,\n    0xa0,0x07,0x76,0x40,0x07,0x6d,0x60,0x0f,0x71,0x60,0x07,0x7a,0x10,0x07,0x76,0xa0,\n    0x07,0x71,0x60,0x07,0x6d,0x60,0x0f,0x72,0x40,0x07,0x7a,0x30,0x07,0x72,0xa0,0x07,\n    0x73,0x20,0x07,0x6d,0x60,0x0f,0x73,0x20,0x07,0x7a,0x30,0x07,0x72,0xa0,0x07,0x73,\n    0x20,0x07,0x6d,0x60,0x0f,0x74,0x80,0x07,0x7a,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,\n    0x07,0x6d,0x60,0x0f,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,\n    0x6d,0x60,0x0f,0x79,0x60,0x07,0x7a,0x10,0x07,0x72,0x80,0x07,0x7a,0x10,0x07,0x72,\n    0x80,0x07,0x6d,0x60,0x0f,0x71,0x20,0x07,0x78,0xa0,0x07,0x71,0x20,0x07,0x78,0xa0,\n    0x07,0x71,0x20,0x07,0x78,0xd0,0x06,0xf6,0x10,0x07,0x79,0x20,0x07,0x7a,0x20,0x07,\n    0x75,0x60,0x07,0x7a,0x20,0x07,0x75,0x60,0x07,0x6d,0x60,0x0f,0x72,0x50,0x07,0x76,\n    0xa0,0x07,0x72,0x50,0x07,0x76,0xa0,0x07,0x72,0x50,0x07,0x76,0xd0,0x06,0xf6,0x50,\n    0x07,0x71,0x20,0x07,0x7a,0x50,0x07,0x71,0x20,0x07,0x7a,0x50,0x07,0x71,0x20,0x07,\n    0x6d,0x60,0x0f,0x71,0x00,0x07,0x72,0x40,0x07,0x7a,0x10,0x07,0x70,0x20,0x07,0x74,\n    0xa0,0x07,0x71,0x00,0x07,0x72,0x40,0x07,0x6d,0xe0,0x0e,0x78,0xa0,0x07,0x71,0x60,\n    0x07,0x7a,0x30,0x07,0x72,0x30,0x84,0x49,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,\n    0xc8,0x02,0x01,0x00,0x00,0x0b,0x00,0x00,0x00,0x32,0x1e,0x98,0x10,0x19,0x11,0x4c,\n    0x90,0x8c,0x09,0x26,0x47,0xc6,0x04,0x43,0x5a,0x25,0x30,0x02,0x50,0x04,0x05,0x18,\n    0x50,0x08,0x65,0x50,0x80,0x02,0x05,0x51,0x20,0xd4,0x46,0x00,0x88,0x8d,0x25,0x34,\n    0x01,0x00,0x00,0x00,0x00,0x79,0x18,0x00,0x00,0x02,0x01,0x00,0x00,0x1a,0x03,0x4c,\n    0x10,0x97,0x29,0xa2,0x25,0x10,0xab,0x32,0xb9,0xb9,0xb4,0x37,0xb7,0x21,0xc6,0x32,\n    0x28,0x00,0xb3,0x50,0xb9,0x1b,0x43,0x0b,0x93,0xfb,0x9a,0x4b,0xd3,0x2b,0x1b,0x62,\n    0x2c,0x81,0x22,0x2c,0x05,0xe7,0x20,0x08,0x0e,0x8e,0xad,0x0c,0xa4,0xad,0x8c,0x2e,\n    0x8c,0x0d,0xc4,0xae,0x4c,0x6e,0x2e,0xed,0xcd,0x0d,0x64,0x26,0x06,0x06,0x26,0xc6,\n    0xc5,0xc6,0xe6,0x06,0x04,0xa5,0xad,0x8c,0x2e,0x8c,0xcd,0xac,0xac,0x65,0x26,0x06,\n    0x06,0x26,0xc6,0xc5,0xc6,0xe6,0xc6,0x45,0x26,0x65,0x88,0xa0,0x10,0x43,0x8c,0x25,\n    0x58,0x90,0x45,0x60,0xd1,0x54,0x46,0x17,0xc6,0x36,0x04,0x51,0x8e,0x25,0x58,0x82,\n    0x45,0xe0,0x16,0x96,0x26,0xe7,0x32,0xf6,0xd6,0x06,0x97,0xc6,0x56,0xe6,0x42,0x56,\n    0xe6,0xf6,0x26,0xd7,0x36,0xf7,0x45,0x96,0x36,0x17,0x26,0xc6,0x56,0x36,0x44,0x50,\n    0x12,0x72,0x61,0x69,0x72,0x2e,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x2e,0x66,0x61,\n    0x73,0x74,0x5f,0x6d,0x61,0x74,0x68,0x5f,0x65,0x6e,0x61,0x62,0x6c,0x65,0x43,0x04,\n    0x65,0x61,0x19,0x84,0xa5,0xc9,0xb9,0x8c,0xbd,0xb5,0xc1,0xa5,0xb1,0x95,0xb9,0x98,\n    0xc9,0x85,0xb5,0x95,0x89,0xd5,0x99,0x99,0x95,0xc9,0x7d,0x99,0x95,0xd1,0x8d,0xa1,\n    0x7d,0x91,0xa5,0xcd,0x85,0x89,0xb1,0x95,0x0d,0x11,0x94,0x86,0x51,0x58,0x9a,0x9c,\n    0x8b,0x5d,0x99,0x1c,0x5d,0x19,0xde,0xd7,0x5b,0x1d,0x1d,0x5c,0x1d,0x1d,0x97,0xba,\n    0xb9,0x32,0x39,0x14,0xb6,0xb7,0x31,0x37,0x98,0x14,0x46,0x61,0x69,0x72,0x2e,0x61,\n    0x72,0x67,0x5f,0x74,0x79,0x70,0x65,0x5f,0x6e,0x61,0x6d,0x65,0x34,0xcc,0xd8,0xde,\n    0xc2,0xe8,0x68,0xc8,0x84,0xa5,0xc9,0xb9,0x84,0xc9,0x9d,0x7d,0xb9,0x85,0xb5,0x95,\n    0x51,0xa8,0xb3,0x1b,0xc2,0x28,0x8f,0x02,0x29,0x91,0x22,0x29,0x93,0x42,0x71,0xa9,\n    0x9b,0x2b,0x93,0x43,0x61,0x7b,0x1b,0x73,0x8b,0x49,0x61,0x31,0xf6,0xc6,0xf6,0x26,\n    0x37,0x84,0x51,0x1e,0xc5,0x52,0x22,0x45,0x52,0x26,0xe5,0x22,0x13,0x96,0x26,0xe7,\n    0x02,0xf7,0x36,0x97,0x46,0x97,0xf6,0xe6,0xc6,0xe5,0x8c,0xed,0x0b,0xea,0x6d,0x2e,\n    0x8d,0x2e,0xed,0xcd,0x6d,0x88,0xa2,0x64,0x4a,0xa4,0x48,0xca,0xa4,0x68,0x74,0xc2,\n    0xd2,0xe4,0x5c,0xe0,0xde,0xd2,0xdc,0xe8,0xbe,0xe6,0xd2,0xf4,0xca,0x58,0x98,0xb1,\n    0xbd,0x85,0xd1,0x91,0x39,0x63,0xfb,0x82,0x7a,0x4b,0x73,0xa3,0x9b,0x4a,0xd3,0x2b,\n    0x1b,0xa2,0x28,0x9c,0x12,0x29,0x9d,0x32,0x29,0xde,0x10,0x44,0xa9,0x14,0x4c,0xd9,\n    0x94,0x8f,0x50,0x58,0x9a,0x9c,0x8b,0x5d,0x99,0x1c,0x5d,0x19,0xde,0x57,0x9a,0x1b,\n    0x5c,0x1d,0x1d,0xa5,0xb0,0x34,0x39,0x17,0xb6,0xb7,0xb1,0x30,0xba,0xb4,0x37,0xb7,\n    0xaf,0x34,0x37,0xb2,0x32,0x3c,0x7a,0x67,0x65,0x6e,0x65,0x72,0x61,0x74,0x65,0x64,\n    0x28,0x5f,0x5f,0x61,0x69,0x72,0x5f,0x70,0x6c,0x61,0x63,0x65,0x68,0x6f,0x6c,0x64,\n    0x65,0x72,0x5f,0x5f,0x29,0x44,0xe0,0xde,0xe6,0xd2,0xe8,0xd2,0xde,0xdc,0x86,0x50,\n    0x8b,0xa0,0x84,0x81,0x22,0x06,0x8b,0xb0,0x04,0xca,0x18,0x28,0x91,0x22,0x29,0x93,\n    0x42,0x06,0x34,0xcc,0xd8,0xde,0xc2,0xe8,0x64,0x98,0xd0,0x95,0xe1,0x8d,0xbd,0xbd,\n    0xc9,0x91,0xc1,0x0c,0xa1,0x96,0x40,0x09,0x03,0x45,0x0c,0x96,0x60,0x09,0x94,0x31,\n    0x50,0x22,0xc5,0x0c,0x94,0x49,0x39,0x03,0x1a,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x43,\n    0xa8,0x65,0x50,0xc2,0x40,0x11,0x83,0x65,0x58,0x02,0x65,0x0c,0x94,0x48,0x91,0x94,\n    0x49,0x49,0x03,0x16,0x70,0x73,0x69,0x7a,0x65,0x43,0xa8,0xc5,0x50,0xc2,0x40,0x11,\n    0x83,0xc5,0x58,0x02,0x65,0x0c,0x94,0x48,0xe9,0x94,0x49,0x59,0x03,0x2a,0x61,0x69,\n    0x72,0x2e,0x62,0x75,0x66,0x66,0x65,0x72,0x7c,0xc2,0xd2,0xe4,0x5c,0xc4,0xea,0xcc,\n    0xcc,0xca,0xe4,0xbe,0xe6,0xd2,0xf4,0xca,0x88,0x84,0xa5,0xc9,0xb9,0xc8,0x95,0x85,\n    0x91,0x91,0x0a,0x4b,0x93,0x73,0x99,0xa3,0x93,0xab,0x1b,0xa3,0xfb,0xa2,0xcb,0x83,\n    0x2b,0xfb,0x4a,0x73,0x33,0x7b,0x23,0x62,0xc6,0xf6,0x16,0x46,0x47,0x83,0x47,0xc3,\n    0xa1,0xcd,0x0e,0x8e,0x02,0x5d,0xdb,0x10,0x6a,0x11,0x16,0x62,0x11,0x94,0x38,0x50,\n    0xe4,0x60,0x21,0x16,0x62,0x11,0x94,0x38,0x50,0xe6,0x80,0x51,0x58,0x9a,0x9c,0x4b,\n    0x98,0xdc,0xd9,0x17,0x5d,0x1e,0x5c,0xd9,0xd7,0x5c,0x9a,0x5e,0x19,0xaf,0xb0,0x34,\n    0x39,0x97,0x30,0xb9,0xb3,0x2f,0xba,0x3c,0xb8,0xb2,0xaf,0x30,0xb6,0xb4,0x33,0xb7,\n    0xaf,0xb9,0x34,0xbd,0x32,0x26,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x1c,\n    0xbe,0x62,0x72,0x86,0x90,0xc1,0x52,0x28,0x6d,0xa0,0xb8,0xc1,0x72,0x28,0x62,0xb0,\n    0x08,0x4b,0xa0,0xbc,0x81,0x02,0x07,0x0a,0x1d,0x28,0x75,0xb0,0x1c,0x8a,0x1d,0x2c,\n    0x89,0x12,0x29,0x77,0xa0,0x4c,0x0a,0x1e,0x0c,0x51,0x94,0x32,0x50,0xd0,0x40,0x51,\n    0x03,0x85,0x0d,0x94,0x3c,0x18,0x62,0x24,0x80,0x02,0x06,0x8a,0x1e,0xf0,0x79,0x6b,\n    0x73,0x4b,0x83,0x7b,0xa3,0x2b,0x73,0xa3,0x03,0x19,0x43,0x0b,0x93,0xe3,0x33,0x95,\n    0xd6,0x06,0xc7,0x56,0x06,0x32,0xb4,0xb2,0x02,0x42,0x25,0x14,0x14,0x34,0x44,0x50,\n    0xfa,0x60,0x88,0xa1,0xf0,0x81,0xe2,0x07,0x8d,0x32,0xc4,0x50,0xfe,0x40,0xf9,0x83,\n    0x46,0x19,0x11,0xb1,0x03,0x3b,0xd8,0x43,0x3b,0xb8,0x41,0x3b,0xbc,0x03,0x39,0xd4,\n    0x03,0x3b,0x94,0x83,0x1b,0x98,0x03,0x3b,0x84,0xc3,0x39,0xcc,0xc3,0x14,0x21,0x18,\n    0x46,0x28,0xec,0xc0,0x0e,0xf6,0xd0,0x0e,0x6e,0x90,0x0e,0xe4,0x50,0x0e,0xee,0x40,\n    0x0f,0x53,0x82,0x62,0xc4,0x12,0x0e,0xe9,0x20,0x0f,0x6e,0x60,0x0f,0xe5,0x20,0x0f,\n    0xf3,0x90,0x0e,0xef,0xe0,0x0e,0x53,0x02,0x63,0x04,0x15,0x0e,0xe9,0x20,0x0f,0x6e,\n    0xc0,0x0e,0xe1,0xe0,0x0e,0xe7,0x50,0x0f,0xe1,0x70,0x0e,0xe5,0xf0,0x0b,0xf6,0x50,\n    0x0e,0xf2,0x30,0x0f,0xe9,0xf0,0x0e,0xee,0x30,0x25,0x40,0x46,0x4c,0xe1,0x90,0x0e,\n    0xf2,0xe0,0x06,0xe3,0xf0,0x0e,0xed,0x00,0x0f,0xe9,0xc0,0x0e,0xe5,0xf0,0x0b,0xef,\n    0x00,0x0f,0xf4,0x90,0x0e,0xef,0xe0,0x0e,0xf3,0x30,0x65,0x50,0x18,0x67,0x84,0x12,\n    0x0e,0xe9,0x20,0x0f,0x6e,0x60,0x0f,0xe5,0x20,0x0f,0xf4,0x50,0x0e,0xf8,0x30,0x25,\n    0xd8,0x03,0x00,0x00,0x00,0x79,0x18,0x00,0x00,0x7b,0x00,0x00,0x00,0x33,0x08,0x80,\n    0x1c,0xc4,0xe1,0x1c,0x66,0x14,0x01,0x3d,0x88,0x43,0x38,0x84,0xc3,0x8c,0x42,0x80,\n    0x07,0x79,0x78,0x07,0x73,0x98,0x71,0x0c,0xe6,0x00,0x0f,0xed,0x10,0x0e,0xf4,0x80,\n    0x0e,0x33,0x0c,0x42,0x1e,0xc2,0xc1,0x1d,0xce,0xa1,0x1c,0x66,0x30,0x05,0x3d,0x88,\n    0x43,0x38,0x84,0x83,0x1b,0xcc,0x03,0x3d,0xc8,0x43,0x3d,0x8c,0x03,0x3d,0xcc,0x78,\n    0x8c,0x74,0x70,0x07,0x7b,0x08,0x07,0x79,0x48,0x87,0x70,0x70,0x07,0x7a,0x70,0x03,\n    0x76,0x78,0x87,0x70,0x20,0x87,0x19,0xcc,0x11,0x0e,0xec,0x90,0x0e,0xe1,0x30,0x0f,\n    0x6e,0x30,0x0f,0xe3,0xf0,0x0e,0xf0,0x50,0x0e,0x33,0x10,0xc4,0x1d,0xde,0x21,0x1c,\n    0xd8,0x21,0x1d,0xc2,0x61,0x1e,0x66,0x30,0x89,0x3b,0xbc,0x83,0x3b,0xd0,0x43,0x39,\n    0xb4,0x03,0x3c,0xbc,0x83,0x3c,0x84,0x03,0x3b,0xcc,0xf0,0x14,0x76,0x60,0x07,0x7b,\n    0x68,0x07,0x37,0x68,0x87,0x72,0x68,0x07,0x37,0x80,0x87,0x70,0x90,0x87,0x70,0x60,\n    0x07,0x76,0x28,0x07,0x76,0xf8,0x05,0x76,0x78,0x87,0x77,0x80,0x87,0x5f,0x08,0x87,\n    0x71,0x18,0x87,0x72,0x98,0x87,0x79,0x98,0x81,0x2c,0xee,0xf0,0x0e,0xee,0xe0,0x0e,\n    0xf5,0xc0,0x0e,0xec,0x30,0x03,0x62,0xc8,0xa1,0x1c,0xe4,0xa1,0x1c,0xcc,0xa1,0x1c,\n    0xe4,0xa1,0x1c,0xdc,0x61,0x1c,0xca,0x21,0x1c,0xc4,0x81,0x1d,0xca,0x61,0x06,0xd6,\n    0x90,0x43,0x39,0xc8,0x43,0x39,0x98,0x43,0x39,0xc8,0x43,0x39,0xb8,0xc3,0x38,0x94,\n    0x43,0x38,0x88,0x03,0x3b,0x94,0xc3,0x2f,0xbc,0x83,0x3c,0xfc,0x82,0x3b,0xd4,0x03,\n    0x3b,0xb0,0xc3,0x0c,0xc7,0x69,0x87,0x70,0x58,0x87,0x72,0x70,0x83,0x74,0x68,0x07,\n    0x78,0x60,0x87,0x74,0x18,0x87,0x74,0xa0,0x87,0x19,0xce,0x53,0x0f,0xee,0x00,0x0f,\n    0xf2,0x50,0x0e,0xe4,0x90,0x0e,0xe3,0x40,0x0f,0xe1,0x20,0x0e,0xec,0x50,0x0e,0x33,\n    0x20,0x28,0x1d,0xdc,0xc1,0x1e,0xc2,0x41,0x1e,0xd2,0x21,0x1c,0xdc,0x81,0x1e,0xdc,\n    0xe0,0x1c,0xe4,0xe1,0x1d,0xea,0x01,0x1e,0x66,0x18,0x51,0x38,0xb0,0x43,0x3a,0x9c,\n    0x83,0x3b,0xcc,0x50,0x24,0x76,0x60,0x07,0x7b,0x68,0x07,0x37,0x60,0x87,0x77,0x78,\n    0x07,0x78,0x98,0x51,0x4c,0xf4,0x90,0x0f,0xf0,0x50,0x0e,0x33,0x1e,0x6a,0x1e,0xca,\n    0x61,0x1c,0xe8,0x21,0x1d,0xde,0xc1,0x1d,0x7e,0x01,0x1e,0xe4,0xa1,0x1c,0xcc,0x21,\n    0x1d,0xf0,0x61,0x06,0x54,0x85,0x83,0x38,0xcc,0xc3,0x3b,0xb0,0x43,0x3d,0xd0,0x43,\n    0x39,0xfc,0xc2,0x3c,0xe4,0x43,0x3b,0x88,0xc3,0x3b,0xb0,0xc3,0x8c,0xc5,0x0a,0x87,\n    0x79,0x98,0x87,0x77,0x18,0x87,0x74,0x08,0x07,0x7a,0x28,0x07,0x72,0x98,0x81,0x5c,\n    0xe3,0x10,0x0e,0xec,0xc0,0x0e,0xe5,0x50,0x0e,0xf3,0x30,0x23,0xc1,0xd2,0x41,0x1e,\n    0xe4,0xe1,0x17,0xd8,0xe1,0x1d,0xde,0x01,0x1e,0x66,0x50,0x59,0x38,0xa4,0x83,0x3c,\n    0xb8,0x81,0x39,0xd4,0x83,0x3b,0x8c,0x03,0x3d,0xa4,0xc3,0x3b,0xb8,0xc3,0x2f,0x9c,\n    0x83,0x3c,0xbc,0x43,0x3d,0xc0,0xc3,0x3c,0x00,0x71,0x20,0x00,0x00,0x02,0x00,0x00,\n    0x00,0x06,0x50,0x30,0x00,0xd2,0xd0,0x00,0x00,0x61,0x20,0x00,0x00,0x3e,0x00,0x00,\n    0x00,0x13,0x04,0x41,0x2c,0x10,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0xf4,0xc6,0x22,\n    0x86,0x61,0x18,0xc6,0x22,0x04,0x41,0x10,0xc6,0x22,0x82,0x20,0x08,0xa8,0x95,0x40,\n    0x19,0x14,0x01,0xbd,0x11,0x00,0x1a,0x33,0x00,0x24,0x66,0x00,0x28,0xcc,0x00,0x00,\n    0x00,0xe3,0x15,0x4b,0x94,0x65,0x11,0x05,0x65,0x90,0x21,0x1a,0x0c,0x13,0x02,0xf9,\n    0x8c,0x57,0x3c,0x55,0xd7,0x2d,0x14,0x94,0x41,0x86,0xea,0x70,0x4c,0x08,0xe4,0x63,\n    0x41,0x01,0x9f,0xf1,0x0a,0x4a,0x13,0x03,0x31,0x70,0x28,0x28,0x83,0x0c,0x1a,0x43,\n    0x99,0x10,0xc8,0xc7,0x8a,0x00,0x3e,0xe3,0x15,0xd9,0x77,0x06,0x67,0x40,0x51,0x50,\n    0x06,0x19,0xbe,0x48,0x33,0x21,0x90,0x8f,0x15,0x01,0x7c,0xc6,0x2b,0x3c,0x32,0x68,\n    0x03,0x36,0x20,0x03,0x0a,0xca,0x20,0xc3,0x18,0x60,0x99,0x09,0x81,0x7c,0xc6,0x2b,\n    0xc4,0x00,0x0d,0xe2,0x00,0x0e,0x3c,0x0a,0xca,0x20,0xc3,0x19,0x70,0x61,0x60,0x42,\n    0x20,0x1f,0x0b,0x0a,0xf8,0x8c,0x57,0x9c,0x41,0x1b,0xd8,0x41,0x1d,0x88,0x01,0x05,\n    0xc5,0x86,0x00,0x3e,0xb3,0x0d,0x61,0x10,0x00,0xb3,0x0d,0x41,0x1b,0x04,0xb3,0x0d,\n    0xc1,0x23,0xcc,0x36,0x04,0x6e,0x30,0x64,0x10,0x10,0x03,0x00,0x00,0x09,0x00,0x00,\n    0x00,0x5b,0x86,0x20,0x00,0x85,0x2d,0x43,0x11,0x80,0xc2,0x96,0x41,0x09,0x40,0x61,\n    0xcb,0xf0,0x04,0xa0,0xb0,0x65,0xa0,0x02,0x50,0xd8,0x32,0x60,0x01,0x28,0x6c,0x19,\n    0xba,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,\n};\nstatic const uint8_t _sfons_fs_bytecode_metal_macos[2857] = {\n    0x4d,0x54,0x4c,0x42,0x01,0x80,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x29,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x50,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,\n    0x4e,0x41,0x4d,0x45,0x06,0x00,0x6d,0x61,0x69,0x6e,0x30,0x00,0x54,0x59,0x50,0x45,\n    0x01,0x00,0x01,0x48,0x41,0x53,0x48,0x20,0x00,0x38,0x3c,0x07,0x7d,0xe0,0x21,0x6b,\n    0x04,0x03,0x36,0x12,0x1d,0xbc,0x24,0x12,0xc4,0x27,0xab,0xef,0x84,0x17,0xbe,0x12,\n    0x8d,0xc7,0xbc,0x06,0xbc,0x98,0x53,0xdb,0x0b,0x4f,0x46,0x46,0x54,0x18,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x45,0x52,0x53,0x08,0x00,0x01,0x00,0x08,\n    0x00,0x01,0x00,0x01,0x00,0x45,0x4e,0x44,0x54,0x04,0x00,0x00,0x00,0x45,0x4e,0x44,\n    0x54,0x04,0x00,0x00,0x00,0x45,0x4e,0x44,0x54,0xde,0xc0,0x17,0x0b,0x00,0x00,0x00,\n    0x00,0x14,0x00,0x00,0x00,0x30,0x0a,0x00,0x00,0xff,0xff,0xff,0xff,0x42,0x43,0xc0,\n    0xde,0x21,0x0c,0x00,0x00,0x89,0x02,0x00,0x00,0x0b,0x82,0x20,0x00,0x02,0x00,0x00,\n    0x00,0x12,0x00,0x00,0x00,0x07,0x81,0x23,0x91,0x41,0xc8,0x04,0x49,0x06,0x10,0x32,\n    0x39,0x92,0x01,0x84,0x0c,0x25,0x05,0x08,0x19,0x1e,0x04,0x8b,0x62,0x80,0x14,0x45,\n    0x02,0x42,0x92,0x0b,0x42,0xa4,0x10,0x32,0x14,0x38,0x08,0x18,0x49,0x0a,0x32,0x44,\n    0x24,0x48,0x0a,0x90,0x21,0x23,0xc4,0x52,0x80,0x0c,0x19,0x21,0x72,0x24,0x07,0xc8,\n    0x48,0x11,0x62,0xa8,0xa0,0xa8,0x40,0xc6,0xf0,0x01,0x00,0x00,0x00,0x51,0x18,0x00,\n    0x00,0x89,0x00,0x00,0x00,0x1b,0xcc,0x25,0xf8,0xff,0xff,0xff,0xff,0x01,0x60,0x00,\n    0x09,0xa8,0x88,0x71,0x78,0x07,0x79,0x90,0x87,0x72,0x18,0x07,0x7a,0x60,0x87,0x7c,\n    0x68,0x03,0x79,0x78,0x87,0x7a,0x70,0x07,0x72,0x28,0x07,0x72,0x68,0x03,0x72,0x48,\n    0x07,0x7b,0x48,0x07,0x72,0x28,0x87,0x36,0x98,0x87,0x78,0x90,0x07,0x7a,0x68,0x03,\n    0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xcc,0x21,0x1c,0xd8,0x61,\n    0x1e,0xca,0x01,0x20,0xc8,0x21,0x1d,0xe6,0x21,0x1c,0xc4,0x81,0x1d,0xca,0xa1,0x0d,\n    0xe8,0x21,0x1c,0xd2,0x81,0x1d,0xda,0x60,0x1c,0xc2,0x81,0x1d,0xd8,0x61,0x1e,0x00,\n    0x73,0x08,0x07,0x76,0x98,0x87,0x72,0x00,0x08,0x76,0x28,0x87,0x79,0x98,0x87,0x36,\n    0x80,0x07,0x79,0x28,0x87,0x71,0x48,0x87,0x79,0x28,0x87,0x36,0x30,0x07,0x78,0x68,\n    0x87,0x70,0x20,0x07,0xc0,0x1c,0xc2,0x81,0x1d,0xe6,0xa1,0x1c,0x00,0xc2,0x1d,0xde,\n    0xa1,0x0d,0xcc,0x41,0x1e,0xc2,0xa1,0x1d,0xca,0xa1,0x0d,0xe0,0xe1,0x1d,0xd2,0xc1,\n    0x1d,0xe8,0xa1,0x1c,0xe4,0xa1,0x0d,0xca,0x81,0x1d,0xd2,0xa1,0x1d,0x00,0x7a,0x90,\n    0x87,0x7a,0x28,0x07,0x60,0x70,0x87,0x77,0x68,0x03,0x73,0x90,0x87,0x70,0x68,0x87,\n    0x72,0x68,0x03,0x78,0x78,0x87,0x74,0x70,0x07,0x7a,0x28,0x07,0x79,0x68,0x83,0x72,\n    0x60,0x87,0x74,0x68,0x87,0x36,0x70,0x87,0x77,0x70,0x87,0x36,0x60,0x87,0x72,0x08,\n    0x07,0x73,0x00,0x08,0x77,0x78,0x87,0x36,0x48,0x07,0x77,0x30,0x87,0x79,0x68,0x03,\n    0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xe8,0x41,0x1e,0xea,0xa1,\n    0x1c,0x00,0xc2,0x1d,0xde,0xa1,0x0d,0xd4,0xa1,0x1e,0xda,0x01,0x1e,0xda,0x80,0x1e,\n    0xc2,0x41,0x1c,0xd8,0xa1,0x1c,0xe6,0x01,0x30,0x87,0x70,0x60,0x87,0x79,0x28,0x07,\n    0x80,0x70,0x87,0x77,0x68,0x03,0x77,0x08,0x07,0x77,0x98,0x87,0x36,0x30,0x07,0x78,\n    0x68,0x83,0x76,0x08,0x07,0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,\n    0xdc,0xe1,0x1d,0xda,0x60,0x1e,0xd2,0xe1,0x1c,0xdc,0xa1,0x1c,0xc8,0xa1,0x0d,0xf4,\n    0xa1,0x1c,0xe4,0xe1,0x1d,0xe6,0xa1,0x0d,0xcc,0x01,0x1e,0xda,0xa0,0x1d,0xc2,0x81,\n    0x1e,0xd0,0x01,0xa0,0x07,0x79,0xa8,0x87,0x72,0x00,0x08,0x77,0x78,0x87,0x36,0xa0,\n    0x07,0x79,0x08,0x07,0x78,0x80,0x87,0x74,0x70,0x87,0x73,0x68,0x83,0x76,0x08,0x07,\n    0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,0xe6,0x81,0x1e,0xc2,0x61,\n    0x1c,0xd6,0xa1,0x0d,0xe0,0x41,0x1e,0xde,0x81,0x1e,0xca,0x61,0x1c,0xe8,0xe1,0x1d,\n    0xe4,0xa1,0x0d,0xc4,0xa1,0x1e,0xcc,0xc1,0x1c,0xca,0x41,0x1e,0xda,0x60,0x1e,0xd2,\n    0x41,0x1f,0xca,0x01,0xc0,0x03,0x80,0xa8,0x07,0x77,0x98,0x87,0x70,0x30,0x87,0x72,\n    0x68,0x03,0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xe8,0x41,0x1e,\n    0xea,0xa1,0x1c,0x00,0xa2,0x1e,0xe6,0xa1,0x1c,0xda,0x60,0x1e,0xde,0xc1,0x1c,0xe8,\n    0xa1,0x0d,0xcc,0x81,0x1d,0xde,0x21,0x1c,0xe8,0x01,0x30,0x87,0x70,0x60,0x87,0x79,\n    0x28,0x07,0x60,0x83,0x21,0x0c,0xc0,0x02,0x54,0x1b,0x8c,0x81,0x00,0x16,0xa0,0xda,\n    0x80,0x10,0xff,0xff,0xff,0xff,0x3f,0x00,0x0c,0x20,0x01,0xd5,0x06,0xa3,0x08,0x80,\n    0x05,0xa8,0x36,0x18,0x86,0x00,0x2c,0x40,0x05,0x49,0x18,0x00,0x00,0x03,0x00,0x00,\n    0x00,0x13,0x86,0x40,0x18,0x26,0x0c,0x44,0x61,0x00,0x00,0x00,0x00,0x89,0x20,0x00,\n    0x00,0x1e,0x00,0x00,0x00,0x32,0x22,0x48,0x09,0x20,0x64,0x85,0x04,0x93,0x22,0xa4,\n    0x84,0x04,0x93,0x22,0xe3,0x84,0xa1,0x90,0x14,0x12,0x4c,0x8a,0x8c,0x0b,0x84,0xa4,\n    0x4c,0x10,0x4c,0x33,0x00,0xc3,0x08,0x04,0x60,0x83,0x70,0x94,0x34,0x45,0x94,0x30,\n    0xf9,0xff,0x44,0x5c,0x13,0x15,0x11,0xbf,0x3d,0xfc,0xd3,0x18,0x01,0x30,0x88,0x30,\n    0x04,0x17,0x49,0x53,0x44,0x09,0x93,0xff,0x4b,0x00,0xf3,0x2c,0x44,0xf4,0x4f,0x63,\n    0x04,0xc0,0x20,0x42,0x21,0x94,0x42,0x84,0x40,0x0c,0x9d,0x61,0x04,0x01,0x98,0x23,\n    0x08,0xe6,0x08,0xc0,0x60,0x18,0x41,0x58,0x0a,0x12,0x88,0x49,0x8a,0x29,0x40,0x6d,\n    0x20,0x20,0x05,0xd6,0x30,0x02,0xb1,0x8c,0x00,0x00,0x00,0x00,0x00,0x13,0xb2,0x70,\n    0x48,0x07,0x79,0xb0,0x03,0x3a,0x68,0x83,0x70,0x80,0x07,0x78,0x60,0x87,0x72,0x68,\n    0x83,0x76,0x08,0x87,0x71,0x78,0x87,0x79,0xc0,0x87,0x38,0x80,0x03,0x37,0x88,0x83,\n    0x38,0x70,0x03,0x38,0xd8,0x70,0x1b,0xe5,0xd0,0x06,0xf0,0xa0,0x07,0x76,0x40,0x07,\n    0x7a,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x6d,0x90,0x0e,0x71,0xa0,0x07,0x78,\n    0xa0,0x07,0x78,0xd0,0x06,0xe9,0x80,0x07,0x7a,0x80,0x07,0x7a,0x80,0x07,0x6d,0x90,\n    0x0e,0x71,0x60,0x07,0x7a,0x10,0x07,0x76,0xa0,0x07,0x71,0x60,0x07,0x6d,0x90,0x0e,\n    0x73,0x20,0x07,0x7a,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x6d,0x90,0x0e,0x76,\n    0x40,0x07,0x7a,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x6d,0x60,0x0e,0x73,0x20,\n    0x07,0x7a,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x6d,0x60,0x0e,0x76,0x40,0x07,\n    0x7a,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x6d,0x60,0x0f,0x71,0x60,0x07,0x7a,\n    0x10,0x07,0x76,0xa0,0x07,0x71,0x60,0x07,0x6d,0x60,0x0f,0x72,0x40,0x07,0x7a,0x30,\n    0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x6d,0x60,0x0f,0x73,0x20,0x07,0x7a,0x30,0x07,\n    0x72,0xa0,0x07,0x73,0x20,0x07,0x6d,0x60,0x0f,0x74,0x80,0x07,0x7a,0x60,0x07,0x74,\n    0xa0,0x07,0x76,0x40,0x07,0x6d,0x60,0x0f,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xa0,\n    0x07,0x76,0x40,0x07,0x6d,0x60,0x0f,0x79,0x60,0x07,0x7a,0x10,0x07,0x72,0x80,0x07,\n    0x7a,0x10,0x07,0x72,0x80,0x07,0x6d,0x60,0x0f,0x71,0x20,0x07,0x78,0xa0,0x07,0x71,\n    0x20,0x07,0x78,0xa0,0x07,0x71,0x20,0x07,0x78,0xd0,0x06,0xf6,0x10,0x07,0x79,0x20,\n    0x07,0x7a,0x20,0x07,0x75,0x60,0x07,0x7a,0x20,0x07,0x75,0x60,0x07,0x6d,0x60,0x0f,\n    0x72,0x50,0x07,0x76,0xa0,0x07,0x72,0x50,0x07,0x76,0xa0,0x07,0x72,0x50,0x07,0x76,\n    0xd0,0x06,0xf6,0x50,0x07,0x71,0x20,0x07,0x7a,0x50,0x07,0x71,0x20,0x07,0x7a,0x50,\n    0x07,0x71,0x20,0x07,0x6d,0x60,0x0f,0x71,0x00,0x07,0x72,0x40,0x07,0x7a,0x10,0x07,\n    0x70,0x20,0x07,0x74,0xa0,0x07,0x71,0x00,0x07,0x72,0x40,0x07,0x6d,0xe0,0x0e,0x78,\n    0xa0,0x07,0x71,0x60,0x07,0x7a,0x30,0x07,0x72,0x30,0x84,0x41,0x00,0x00,0x08,0x00,\n    0x00,0x00,0x00,0x00,0x18,0xc2,0x38,0x40,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x64,\n    0x81,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x32,0x1e,0x98,0x10,0x19,0x11,0x4c,\n    0x90,0x8c,0x09,0x26,0x47,0xc6,0x04,0x43,0x5a,0x25,0x30,0x02,0x50,0x04,0x85,0x50,\n    0x10,0x65,0x40,0x70,0x2c,0xa1,0x09,0x00,0x00,0x79,0x18,0x00,0x00,0xb7,0x00,0x00,\n    0x00,0x1a,0x03,0x4c,0x10,0x97,0x29,0xa2,0x25,0x10,0xab,0x32,0xb9,0xb9,0xb4,0x37,\n    0xb7,0x21,0xc6,0x42,0x3c,0x00,0x84,0x50,0xb9,0x1b,0x43,0x0b,0x93,0xfb,0x9a,0x4b,\n    0xd3,0x2b,0x1b,0x62,0x2c,0xc2,0x23,0x2c,0x05,0xe7,0x20,0x08,0x0e,0x8e,0xad,0x0c,\n    0xa4,0xad,0x8c,0x2e,0x8c,0x0d,0xc4,0xae,0x4c,0x6e,0x2e,0xed,0xcd,0x0d,0x64,0x26,\n    0x06,0x06,0x26,0xc6,0xc5,0xc6,0xe6,0x06,0x04,0xa5,0xad,0x8c,0x2e,0x8c,0xcd,0xac,\n    0xac,0x65,0x26,0x06,0x06,0x26,0xc6,0xc5,0xc6,0xe6,0xc6,0x45,0x26,0x65,0x88,0xf0,\n    0x10,0x43,0x8c,0x45,0x58,0x8c,0x65,0x60,0xd1,0x54,0x46,0x17,0xc6,0x36,0x04,0x79,\n    0x8e,0x45,0x58,0x84,0x65,0xe0,0x16,0x96,0x26,0xe7,0x32,0xf6,0xd6,0x06,0x97,0xc6,\n    0x56,0xe6,0x42,0x56,0xe6,0xf6,0x26,0xd7,0x36,0xf7,0x45,0x96,0x36,0x17,0x26,0xc6,\n    0x56,0x36,0x44,0x78,0x12,0x72,0x61,0x69,0x72,0x2e,0x63,0x6f,0x6d,0x70,0x69,0x6c,\n    0x65,0x2e,0x66,0x61,0x73,0x74,0x5f,0x6d,0x61,0x74,0x68,0x5f,0x65,0x6e,0x61,0x62,\n    0x6c,0x65,0x43,0x84,0x67,0x61,0x19,0x84,0xa5,0xc9,0xb9,0x8c,0xbd,0xb5,0xc1,0xa5,\n    0xb1,0x95,0xb9,0x98,0xc9,0x85,0xb5,0x95,0x89,0xd5,0x99,0x99,0x95,0xc9,0x7d,0x99,\n    0x95,0xd1,0x8d,0xa1,0x7d,0x91,0xa5,0xcd,0x85,0x89,0xb1,0x95,0x0d,0x11,0x9e,0x86,\n    0x51,0x58,0x9a,0x9c,0x8b,0x5c,0x99,0x1b,0x59,0x99,0xdc,0x17,0x5d,0x98,0xdc,0x59,\n    0x19,0x1d,0xa3,0xb0,0x34,0x39,0x97,0x30,0xb9,0xb3,0x2f,0xba,0x3c,0xb8,0xb2,0x2f,\n    0xb7,0xb0,0xb6,0x32,0x1a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x64,0xc2,0xd2,0xe4,0x5c,\n    0xc2,0xe4,0xce,0xbe,0xdc,0xc2,0xda,0xca,0xa8,0x98,0xc9,0x85,0x9d,0x7d,0x8d,0xbd,\n    0xb1,0xbd,0xc9,0x0d,0x61,0x9e,0x67,0x19,0x1e,0xe8,0x89,0x1e,0xe9,0x99,0x86,0x08,\n    0x0f,0x45,0x29,0x2c,0x4d,0xce,0xc5,0x4c,0x2e,0xec,0xac,0xad,0xcc,0x8d,0xee,0x2b,\n    0xcd,0x0d,0xae,0x8e,0x8e,0x4b,0xdd,0x5c,0x99,0x1c,0x0a,0xdb,0xdb,0x98,0x1b,0x4c,\n    0x0a,0x95,0xb0,0x34,0x39,0x97,0xb1,0x32,0x37,0xba,0x32,0x39,0x3e,0x61,0x69,0x72,\n    0x2e,0x70,0x65,0x72,0x73,0x70,0x65,0x63,0x74,0x69,0x76,0x65,0x14,0xea,0xec,0x86,\n    0x48,0xcb,0xf0,0x58,0xcf,0xf5,0x60,0x4f,0xf6,0x40,0x4f,0xf4,0x48,0x8f,0xc6,0xa5,\n    0x6e,0xae,0x4c,0x0e,0x85,0xed,0x6d,0xcc,0x2d,0x26,0x85,0xc5,0xd8,0x1b,0xdb,0x9b,\n    0xdc,0x10,0x69,0x11,0x1e,0xeb,0xe1,0x1e,0xec,0xc9,0x1e,0xe8,0x89,0x1e,0xe9,0xe9,\n    0xb8,0x84,0xa5,0xc9,0xb9,0xd0,0x95,0xe1,0xd1,0xd5,0xc9,0x95,0x51,0x0a,0x4b,0x93,\n    0x73,0x61,0x7b,0x1b,0x0b,0xa3,0x4b,0x7b,0x73,0xfb,0x4a,0x73,0x23,0x2b,0xc3,0xa3,\n    0x12,0x96,0x26,0xe7,0x32,0x17,0xd6,0x06,0xc7,0x56,0x46,0x8c,0xae,0x0c,0x8f,0xae,\n    0x4e,0xae,0x4c,0x86,0x8c,0xc7,0x8c,0xed,0x2d,0x8c,0x8e,0x05,0x64,0x2e,0xac,0x0d,\n    0x8e,0xad,0xcc,0x87,0x03,0x5d,0x19,0xde,0x10,0x6a,0x21,0x9e,0xef,0x01,0x83,0x65,\n    0x58,0x84,0x27,0x0c,0x1e,0xe8,0x11,0x83,0x47,0x7a,0xc6,0x80,0x4b,0x58,0x9a,0x9c,\n    0xcb,0x5c,0x58,0x1b,0x1c,0x5b,0x99,0x1c,0x8f,0xb9,0xb0,0x36,0x38,0xb6,0x32,0x39,\n    0x0e,0x73,0x6d,0x70,0x43,0xa4,0xe5,0x78,0xca,0xe0,0x01,0x83,0x65,0x58,0x84,0x07,\n    0x7a,0xcc,0xe0,0x91,0x9e,0x33,0x18,0x82,0x3c,0xdb,0xe3,0x3d,0x64,0xf0,0xa0,0xc1,\n    0x10,0x03,0x01,0x9e,0xea,0x49,0x83,0x11,0x11,0x3b,0xb0,0x83,0x3d,0xb4,0x83,0x1b,\n    0xb4,0xc3,0x3b,0x90,0x43,0x3d,0xb0,0x43,0x39,0xb8,0x81,0x39,0xb0,0x43,0x38,0x9c,\n    0xc3,0x3c,0x4c,0x11,0x82,0x61,0x84,0xc2,0x0e,0xec,0x60,0x0f,0xed,0xe0,0x06,0xe9,\n    0x40,0x0e,0xe5,0xe0,0x0e,0xf4,0x30,0x25,0x28,0x46,0x2c,0xe1,0x90,0x0e,0xf2,0xe0,\n    0x06,0xf6,0x50,0x0e,0xf2,0x30,0x0f,0xe9,0xf0,0x0e,0xee,0x30,0x25,0x30,0x46,0x50,\n    0xe1,0x90,0x0e,0xf2,0xe0,0x06,0xec,0x10,0x0e,0xee,0x70,0x0e,0xf5,0x10,0x0e,0xe7,\n    0x50,0x0e,0xbf,0x60,0x0f,0xe5,0x20,0x0f,0xf3,0x90,0x0e,0xef,0xe0,0x0e,0x53,0x02,\n    0x64,0xc4,0x14,0x0e,0xe9,0x20,0x0f,0x6e,0x30,0x0e,0xef,0xd0,0x0e,0xf0,0x90,0x0e,\n    0xec,0x50,0x0e,0xbf,0xf0,0x0e,0xf0,0x40,0x0f,0xe9,0xf0,0x0e,0xee,0x30,0x0f,0x53,\n    0x06,0x85,0x71,0x46,0x30,0xe1,0x90,0x0e,0xf2,0xe0,0x06,0xe6,0x20,0x0f,0xe1,0x70,\n    0x0e,0xed,0x50,0x0e,0xee,0x40,0x0f,0x53,0x02,0x35,0x00,0x00,0x00,0x79,0x18,0x00,\n    0x00,0x7b,0x00,0x00,0x00,0x33,0x08,0x80,0x1c,0xc4,0xe1,0x1c,0x66,0x14,0x01,0x3d,\n    0x88,0x43,0x38,0x84,0xc3,0x8c,0x42,0x80,0x07,0x79,0x78,0x07,0x73,0x98,0x71,0x0c,\n    0xe6,0x00,0x0f,0xed,0x10,0x0e,0xf4,0x80,0x0e,0x33,0x0c,0x42,0x1e,0xc2,0xc1,0x1d,\n    0xce,0xa1,0x1c,0x66,0x30,0x05,0x3d,0x88,0x43,0x38,0x84,0x83,0x1b,0xcc,0x03,0x3d,\n    0xc8,0x43,0x3d,0x8c,0x03,0x3d,0xcc,0x78,0x8c,0x74,0x70,0x07,0x7b,0x08,0x07,0x79,\n    0x48,0x87,0x70,0x70,0x07,0x7a,0x70,0x03,0x76,0x78,0x87,0x70,0x20,0x87,0x19,0xcc,\n    0x11,0x0e,0xec,0x90,0x0e,0xe1,0x30,0x0f,0x6e,0x30,0x0f,0xe3,0xf0,0x0e,0xf0,0x50,\n    0x0e,0x33,0x10,0xc4,0x1d,0xde,0x21,0x1c,0xd8,0x21,0x1d,0xc2,0x61,0x1e,0x66,0x30,\n    0x89,0x3b,0xbc,0x83,0x3b,0xd0,0x43,0x39,0xb4,0x03,0x3c,0xbc,0x83,0x3c,0x84,0x03,\n    0x3b,0xcc,0xf0,0x14,0x76,0x60,0x07,0x7b,0x68,0x07,0x37,0x68,0x87,0x72,0x68,0x07,\n    0x37,0x80,0x87,0x70,0x90,0x87,0x70,0x60,0x07,0x76,0x28,0x07,0x76,0xf8,0x05,0x76,\n    0x78,0x87,0x77,0x80,0x87,0x5f,0x08,0x87,0x71,0x18,0x87,0x72,0x98,0x87,0x79,0x98,\n    0x81,0x2c,0xee,0xf0,0x0e,0xee,0xe0,0x0e,0xf5,0xc0,0x0e,0xec,0x30,0x03,0x62,0xc8,\n    0xa1,0x1c,0xe4,0xa1,0x1c,0xcc,0xa1,0x1c,0xe4,0xa1,0x1c,0xdc,0x61,0x1c,0xca,0x21,\n    0x1c,0xc4,0x81,0x1d,0xca,0x61,0x06,0xd6,0x90,0x43,0x39,0xc8,0x43,0x39,0x98,0x43,\n    0x39,0xc8,0x43,0x39,0xb8,0xc3,0x38,0x94,0x43,0x38,0x88,0x03,0x3b,0x94,0xc3,0x2f,\n    0xbc,0x83,0x3c,0xfc,0x82,0x3b,0xd4,0x03,0x3b,0xb0,0xc3,0x0c,0xc7,0x69,0x87,0x70,\n    0x58,0x87,0x72,0x70,0x83,0x74,0x68,0x07,0x78,0x60,0x87,0x74,0x18,0x87,0x74,0xa0,\n    0x87,0x19,0xce,0x53,0x0f,0xee,0x00,0x0f,0xf2,0x50,0x0e,0xe4,0x90,0x0e,0xe3,0x40,\n    0x0f,0xe1,0x20,0x0e,0xec,0x50,0x0e,0x33,0x20,0x28,0x1d,0xdc,0xc1,0x1e,0xc2,0x41,\n    0x1e,0xd2,0x21,0x1c,0xdc,0x81,0x1e,0xdc,0xe0,0x1c,0xe4,0xe1,0x1d,0xea,0x01,0x1e,\n    0x66,0x18,0x51,0x38,0xb0,0x43,0x3a,0x9c,0x83,0x3b,0xcc,0x50,0x24,0x76,0x60,0x07,\n    0x7b,0x68,0x07,0x37,0x60,0x87,0x77,0x78,0x07,0x78,0x98,0x51,0x4c,0xf4,0x90,0x0f,\n    0xf0,0x50,0x0e,0x33,0x1e,0x6a,0x1e,0xca,0x61,0x1c,0xe8,0x21,0x1d,0xde,0xc1,0x1d,\n    0x7e,0x01,0x1e,0xe4,0xa1,0x1c,0xcc,0x21,0x1d,0xf0,0x61,0x06,0x54,0x85,0x83,0x38,\n    0xcc,0xc3,0x3b,0xb0,0x43,0x3d,0xd0,0x43,0x39,0xfc,0xc2,0x3c,0xe4,0x43,0x3b,0x88,\n    0xc3,0x3b,0xb0,0xc3,0x8c,0xc5,0x0a,0x87,0x79,0x98,0x87,0x77,0x18,0x87,0x74,0x08,\n    0x07,0x7a,0x28,0x07,0x72,0x98,0x81,0x5c,0xe3,0x10,0x0e,0xec,0xc0,0x0e,0xe5,0x50,\n    0x0e,0xf3,0x30,0x23,0xc1,0xd2,0x41,0x1e,0xe4,0xe1,0x17,0xd8,0xe1,0x1d,0xde,0x01,\n    0x1e,0x66,0x50,0x59,0x38,0xa4,0x83,0x3c,0xb8,0x81,0x39,0xd4,0x83,0x3b,0x8c,0x03,\n    0x3d,0xa4,0xc3,0x3b,0xb8,0xc3,0x2f,0x9c,0x83,0x3c,0xbc,0x43,0x3d,0xc0,0xc3,0x3c,\n    0x00,0x71,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x16,0xb0,0x01,0x48,0xe4,0x4b,0x00,\n    0xf3,0x2c,0xc4,0x3f,0x11,0xd7,0x44,0x45,0xc4,0x6f,0x0f,0x7e,0x85,0x17,0xb7,0x6d,\n    0x00,0x05,0x03,0x20,0x0d,0x0d,0x00,0x00,0x00,0x61,0x20,0x00,0x00,0x16,0x00,0x00,\n    0x00,0x13,0x04,0x41,0x2c,0x10,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x14,0xc7,0x22,\n    0x80,0x40,0x20,0x88,0x8d,0x00,0x8c,0x25,0x00,0x01,0xa9,0x11,0x80,0x1a,0x20,0x31,\n    0x03,0x40,0x61,0x0e,0xe2,0xba,0xae,0x6a,0x06,0x80,0xc0,0x0c,0xc0,0x08,0xc0,0x18,\n    0x01,0x08,0x82,0x20,0xfe,0x01,0x00,0x00,0x00,0x83,0x0c,0x0f,0x91,0x8c,0x18,0x28,\n    0x42,0x80,0x39,0x4d,0x80,0x2c,0xc9,0x30,0xc8,0x70,0x04,0x8d,0x05,0x91,0x7c,0x66,\n    0x1b,0x94,0x00,0xc8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n};\nstatic const uint8_t _sfons_vs_bytecode_metal_ios[3317] = {\n    0x4d,0x54,0x4c,0x42,0x01,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0xf5,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x01,0x00,0x00,0x00,0x00,0x00,0x00,\n    0xe0,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,\n    0x4e,0x41,0x4d,0x45,0x06,0x00,0x6d,0x61,0x69,0x6e,0x30,0x00,0x54,0x59,0x50,0x45,\n    0x01,0x00,0x00,0x48,0x41,0x53,0x48,0x20,0x00,0x17,0x11,0x57,0x16,0x94,0x42,0x52,\n    0xfb,0x1e,0xd0,0x32,0xfd,0x87,0x16,0xb0,0xa4,0xd0,0xc2,0x43,0xbe,0x93,0x8c,0xe0,\n    0x2d,0x7a,0x5c,0x3e,0x06,0x4c,0x57,0xeb,0x4b,0x4f,0x46,0x46,0x54,0x18,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x45,0x52,0x53,0x08,0x00,0x01,0x00,0x08,\n    0x00,0x01,0x00,0x01,0x00,0x45,0x4e,0x44,0x54,0x40,0x00,0x00,0x00,0x56,0x41,0x54,\n    0x54,0x2a,0x00,0x04,0x00,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x00,0x80,\n    0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x00,0x01,0x80,0x63,0x6f,0x6c,0x6f,\n    0x72,0x30,0x00,0x02,0x80,0x70,0x73,0x69,0x7a,0x65,0x00,0x03,0x80,0x56,0x41,0x54,\n    0x59,0x06,0x00,0x04,0x00,0x06,0x04,0x06,0x03,0x45,0x4e,0x44,0x54,0x04,0x00,0x00,\n    0x00,0x45,0x4e,0x44,0x54,0xde,0xc0,0x17,0x0b,0x00,0x00,0x00,0x00,0x14,0x00,0x00,\n    0x00,0xc0,0x0b,0x00,0x00,0xff,0xff,0xff,0xff,0x42,0x43,0xc0,0xde,0x21,0x0c,0x00,\n    0x00,0xed,0x02,0x00,0x00,0x0b,0x82,0x20,0x00,0x02,0x00,0x00,0x00,0x12,0x00,0x00,\n    0x00,0x07,0x81,0x23,0x91,0x41,0xc8,0x04,0x49,0x06,0x10,0x32,0x39,0x92,0x01,0x84,\n    0x0c,0x25,0x05,0x08,0x19,0x1e,0x04,0x8b,0x62,0x80,0x14,0x45,0x02,0x42,0x92,0x0b,\n    0x42,0xa4,0x10,0x32,0x14,0x38,0x08,0x18,0x49,0x0a,0x32,0x44,0x24,0x48,0x0a,0x90,\n    0x21,0x23,0xc4,0x52,0x80,0x0c,0x19,0x21,0x72,0x24,0x07,0xc8,0x48,0x11,0x62,0xa8,\n    0xa0,0xa8,0x40,0xc6,0xf0,0x01,0x00,0x00,0x00,0x51,0x18,0x00,0x00,0x82,0x00,0x00,\n    0x00,0x1b,0xc8,0x25,0xf8,0xff,0xff,0xff,0xff,0x01,0x90,0x80,0x8a,0x18,0x87,0x77,\n    0x90,0x07,0x79,0x28,0x87,0x71,0xa0,0x07,0x76,0xc8,0x87,0x36,0x90,0x87,0x77,0xa8,\n    0x07,0x77,0x20,0x87,0x72,0x20,0x87,0x36,0x20,0x87,0x74,0xb0,0x87,0x74,0x20,0x87,\n    0x72,0x68,0x83,0x79,0x88,0x07,0x79,0xa0,0x87,0x36,0x30,0x07,0x78,0x68,0x83,0x76,\n    0x08,0x07,0x7a,0x40,0x07,0xc0,0x1c,0xc2,0x81,0x1d,0xe6,0xa1,0x1c,0x00,0x82,0x1c,\n    0xd2,0x61,0x1e,0xc2,0x41,0x1c,0xd8,0xa1,0x1c,0xda,0x80,0x1e,0xc2,0x21,0x1d,0xd8,\n    0xa1,0x0d,0xc6,0x21,0x1c,0xd8,0x81,0x1d,0xe6,0x01,0x30,0x87,0x70,0x60,0x87,0x79,\n    0x28,0x07,0x80,0x60,0x87,0x72,0x98,0x87,0x79,0x68,0x03,0x78,0x90,0x87,0x72,0x18,\n    0x87,0x74,0x98,0x87,0x72,0x68,0x03,0x73,0x80,0x87,0x76,0x08,0x07,0x72,0x00,0xcc,\n    0x21,0x1c,0xd8,0x61,0x1e,0xca,0x01,0x20,0xdc,0xe1,0x1d,0xda,0xc0,0x1c,0xe4,0x21,\n    0x1c,0xda,0xa1,0x1c,0xda,0x00,0x1e,0xde,0x21,0x1d,0xdc,0x81,0x1e,0xca,0x41,0x1e,\n    0xda,0xa0,0x1c,0xd8,0x21,0x1d,0xda,0x01,0xa0,0x07,0x79,0xa8,0x87,0x72,0x00,0x06,\n    0x77,0x78,0x87,0x36,0x30,0x07,0x79,0x08,0x87,0x76,0x28,0x87,0x36,0x80,0x87,0x77,\n    0x48,0x07,0x77,0xa0,0x87,0x72,0x90,0x87,0x36,0x28,0x07,0x76,0x48,0x87,0x76,0x68,\n    0x03,0x77,0x78,0x07,0x77,0x68,0x03,0x76,0x28,0x87,0x70,0x30,0x07,0x80,0x70,0x87,\n    0x77,0x68,0x83,0x74,0x70,0x07,0x73,0x98,0x87,0x36,0x30,0x07,0x78,0x68,0x83,0x76,\n    0x08,0x07,0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,0xdc,0xe1,0x1d,\n    0xda,0x40,0x1d,0xea,0xa1,0x1d,0xe0,0xa1,0x0d,0xe8,0x21,0x1c,0xc4,0x81,0x1d,0xca,\n    0x61,0x1e,0x00,0x73,0x08,0x07,0x76,0x98,0x87,0x72,0x00,0x08,0x77,0x78,0x87,0x36,\n    0x70,0x87,0x70,0x70,0x87,0x79,0x68,0x03,0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,\n    0x07,0x74,0x00,0xe8,0x41,0x1e,0xea,0xa1,0x1c,0x00,0xc2,0x1d,0xde,0xa1,0x0d,0xe6,\n    0x21,0x1d,0xce,0xc1,0x1d,0xca,0x81,0x1c,0xda,0x40,0x1f,0xca,0x41,0x1e,0xde,0x61,\n    0x1e,0xda,0xc0,0x1c,0xe0,0xa1,0x0d,0xda,0x21,0x1c,0xe8,0x01,0x1d,0x00,0x7a,0x90,\n    0x87,0x7a,0x28,0x07,0x80,0x70,0x87,0x77,0x68,0x03,0x7a,0x90,0x87,0x70,0x80,0x07,\n    0x78,0x48,0x07,0x77,0x38,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xe8,0x41,\n    0x1e,0xea,0xa1,0x1c,0x00,0x62,0x1e,0xe8,0x21,0x1c,0xc6,0x61,0x1d,0xda,0x00,0x1e,\n    0xe4,0xe1,0x1d,0xe8,0xa1,0x1c,0xc6,0x81,0x1e,0xde,0x41,0x1e,0xda,0x40,0x1c,0xea,\n    0xc1,0x1c,0xcc,0xa1,0x1c,0xe4,0xa1,0x0d,0xe6,0x21,0x1d,0xf4,0xa1,0x1c,0x00,0x3c,\n    0x00,0x88,0x7a,0x70,0x87,0x79,0x08,0x07,0x73,0x28,0x87,0x36,0x30,0x07,0x78,0x68,\n    0x83,0x76,0x08,0x07,0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,0xea,\n    0x61,0x1e,0xca,0xa1,0x0d,0xe6,0xe1,0x1d,0xcc,0x81,0x1e,0xda,0xc0,0x1c,0xd8,0xe1,\n    0x1d,0xc2,0x81,0x1e,0x00,0x73,0x08,0x07,0x76,0x98,0x87,0x72,0x00,0x36,0x20,0x42,\n    0x01,0x24,0xc0,0x02,0x54,0x00,0x00,0x00,0x00,0x49,0x18,0x00,0x00,0x01,0x00,0x00,\n    0x00,0x13,0x84,0x40,0x00,0x89,0x20,0x00,0x00,0x20,0x00,0x00,0x00,0x32,0x22,0x48,\n    0x09,0x20,0x64,0x85,0x04,0x93,0x22,0xa4,0x84,0x04,0x93,0x22,0xe3,0x84,0xa1,0x90,\n    0x14,0x12,0x4c,0x8a,0x8c,0x0b,0x84,0xa4,0x4c,0x10,0x44,0x33,0x00,0xc3,0x08,0x04,\n    0x60,0x89,0x10,0x02,0x18,0x46,0x10,0x80,0x24,0x08,0x33,0x51,0xf3,0x40,0x0f,0xf2,\n    0x50,0x0f,0xe3,0x40,0x0f,0x6e,0xd0,0x0e,0xe5,0x40,0x0f,0xe1,0xc0,0x0e,0x7a,0xa0,\n    0x07,0xed,0x10,0x0e,0xf4,0x20,0x0f,0xe9,0x80,0x0f,0x28,0x20,0x07,0x49,0x53,0x44,\n    0x09,0x93,0x5f,0x49,0xff,0x03,0x44,0x00,0x23,0x21,0xa1,0x94,0x41,0x04,0x43,0x28,\n    0x86,0x08,0x23,0x80,0x43,0x68,0x20,0x60,0x8e,0x00,0x0c,0x52,0x60,0xcd,0x11,0x80,\n    0xc2,0x20,0x42,0x20,0x0c,0x23,0x10,0xcb,0x08,0x00,0x00,0x00,0x00,0x13,0xa8,0x70,\n    0x48,0x07,0x79,0xb0,0x03,0x3a,0x68,0x83,0x70,0x80,0x07,0x78,0x60,0x87,0x72,0x68,\n    0x83,0x74,0x78,0x87,0x79,0xc8,0x03,0x37,0x80,0x03,0x37,0x80,0x83,0x0d,0xb7,0x51,\n    0x0e,0x6d,0x00,0x0f,0x7a,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,\n    0x74,0xd0,0x06,0xe9,0x10,0x07,0x7a,0x80,0x07,0x7a,0x80,0x07,0x6d,0x90,0x0e,0x78,\n    0xa0,0x07,0x78,0xa0,0x07,0x78,0xd0,0x06,0xe9,0x10,0x07,0x76,0xa0,0x07,0x71,0x60,\n    0x07,0x7a,0x10,0x07,0x76,0xd0,0x06,0xe9,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,\n    0x7a,0x30,0x07,0x72,0xd0,0x06,0xe9,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,\n    0x60,0x07,0x74,0xd0,0x06,0xe6,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x7a,0x30,\n    0x07,0x72,0xd0,0x06,0xe6,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,\n    0x74,0xd0,0x06,0xf6,0x10,0x07,0x76,0xa0,0x07,0x71,0x60,0x07,0x7a,0x10,0x07,0x76,\n    0xd0,0x06,0xf6,0x20,0x07,0x74,0xa0,0x07,0x73,0x20,0x07,0x7a,0x30,0x07,0x72,0xd0,\n    0x06,0xf6,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x7a,0x30,0x07,0x72,0xd0,0x06,\n    0xf6,0x40,0x07,0x78,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xd0,0x06,0xf6,\n    0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xd0,0x06,0xf6,0x90,\n    0x07,0x76,0xa0,0x07,0x71,0x20,0x07,0x78,0xa0,0x07,0x71,0x20,0x07,0x78,0xd0,0x06,\n    0xf6,0x10,0x07,0x72,0x80,0x07,0x7a,0x10,0x07,0x72,0x80,0x07,0x7a,0x10,0x07,0x72,\n    0x80,0x07,0x6d,0x60,0x0f,0x71,0x90,0x07,0x72,0xa0,0x07,0x72,0x50,0x07,0x76,0xa0,\n    0x07,0x72,0x50,0x07,0x76,0xd0,0x06,0xf6,0x20,0x07,0x75,0x60,0x07,0x7a,0x20,0x07,\n    0x75,0x60,0x07,0x7a,0x20,0x07,0x75,0x60,0x07,0x6d,0x60,0x0f,0x75,0x10,0x07,0x72,\n    0xa0,0x07,0x75,0x10,0x07,0x72,0xa0,0x07,0x75,0x10,0x07,0x72,0xd0,0x06,0xf6,0x10,\n    0x07,0x70,0x20,0x07,0x74,0xa0,0x07,0x71,0x00,0x07,0x72,0x40,0x07,0x7a,0x10,0x07,\n    0x70,0x20,0x07,0x74,0xd0,0x06,0xee,0x80,0x07,0x7a,0x10,0x07,0x76,0xa0,0x07,0x73,\n    0x20,0x07,0x43,0x98,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x80,0x2c,0x10,0x00,\n    0x00,0x0b,0x00,0x00,0x00,0x32,0x1e,0x98,0x10,0x19,0x11,0x4c,0x90,0x8c,0x09,0x26,\n    0x47,0xc6,0x04,0x43,0x5a,0x25,0x30,0x02,0x50,0x04,0x05,0x18,0x50,0x08,0x65,0x50,\n    0x80,0x02,0x05,0x51,0x20,0xd4,0x46,0x00,0x88,0x8d,0x25,0x40,0x02,0x00,0x00,0x00,\n    0x00,0x79,0x18,0x00,0x00,0x02,0x01,0x00,0x00,0x1a,0x03,0x4c,0x10,0x97,0x29,0xa2,\n    0x25,0x10,0xab,0x32,0xb9,0xb9,0xb4,0x37,0xb7,0x21,0xc6,0x32,0x28,0x00,0xb3,0x50,\n    0xb9,0x1b,0x43,0x0b,0x93,0xfb,0x9a,0x4b,0xd3,0x2b,0x1b,0x62,0x2c,0x81,0x22,0x2c,\n    0x05,0xe7,0x20,0x08,0x0e,0x8e,0xad,0x0c,0xa4,0xad,0x8c,0x2e,0x8c,0x0d,0xc4,0xae,\n    0x4c,0x6e,0x2e,0xed,0xcd,0x0d,0x64,0x26,0x06,0x06,0x26,0xc6,0xc5,0xc6,0xe6,0x06,\n    0x04,0xa5,0xad,0x8c,0x2e,0x8c,0xcd,0xac,0xac,0x65,0x26,0x06,0x06,0x26,0xc6,0xc5,\n    0xc6,0xe6,0xc6,0x45,0x26,0x65,0x88,0xa0,0x10,0x43,0x8c,0x25,0x58,0x90,0x45,0x60,\n    0xd1,0x54,0x46,0x17,0xc6,0x36,0x04,0x51,0x8e,0x25,0x58,0x82,0x45,0xe0,0x16,0x96,\n    0x26,0xe7,0x32,0xf6,0xd6,0x06,0x97,0xc6,0x56,0xe6,0x42,0x56,0xe6,0xf6,0x26,0xd7,\n    0x36,0xf7,0x45,0x96,0x36,0x17,0x26,0xc6,0x56,0x36,0x44,0x50,0x12,0x72,0x61,0x69,\n    0x72,0x2e,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x2e,0x66,0x61,0x73,0x74,0x5f,0x6d,\n    0x61,0x74,0x68,0x5f,0x65,0x6e,0x61,0x62,0x6c,0x65,0x43,0x04,0x65,0x21,0x19,0x84,\n    0xa5,0xc9,0xb9,0x8c,0xbd,0xb5,0xc1,0xa5,0xb1,0x95,0xb9,0x98,0xc9,0x85,0xb5,0x95,\n    0x89,0xd5,0x99,0x99,0x95,0xc9,0x7d,0x99,0x95,0xd1,0x8d,0xa1,0x7d,0x95,0xb9,0x85,\n    0x89,0xb1,0x95,0x0d,0x11,0x94,0x86,0x51,0x58,0x9a,0x9c,0x8b,0x5d,0x99,0x1c,0x5d,\n    0x19,0xde,0xd7,0x5b,0x1d,0x1d,0x5c,0x1d,0x1d,0x97,0xba,0xb9,0x32,0x39,0x14,0xb6,\n    0xb7,0x31,0x37,0x98,0x14,0x46,0x61,0x69,0x72,0x2e,0x61,0x72,0x67,0x5f,0x74,0x79,\n    0x70,0x65,0x5f,0x6e,0x61,0x6d,0x65,0x34,0xcc,0xd8,0xde,0xc2,0xe8,0x68,0xc8,0x84,\n    0xa5,0xc9,0xb9,0x84,0xc9,0x9d,0x7d,0xb9,0x85,0xb5,0x95,0x51,0xa8,0xb3,0x1b,0xc2,\n    0x28,0x8f,0x02,0x29,0x91,0x22,0x29,0x93,0x42,0x71,0xa9,0x9b,0x2b,0x93,0x43,0x61,\n    0x7b,0x1b,0x73,0x8b,0x49,0x61,0x31,0xf6,0xc6,0xf6,0x26,0x37,0x84,0x51,0x1e,0xc5,\n    0x52,0x22,0x45,0x52,0x26,0xe5,0x22,0x13,0x96,0x26,0xe7,0x02,0xf7,0x36,0x97,0x46,\n    0x97,0xf6,0xe6,0xc6,0xe5,0x8c,0xed,0x0b,0xea,0x6d,0x2e,0x8d,0x2e,0xed,0xcd,0x6d,\n    0x88,0xa2,0x64,0x4a,0xa4,0x48,0xca,0xa4,0x68,0x74,0xc2,0xd2,0xe4,0x5c,0xe0,0xde,\n    0xd2,0xdc,0xe8,0xbe,0xe6,0xd2,0xf4,0xca,0x58,0x98,0xb1,0xbd,0x85,0xd1,0x91,0x39,\n    0x63,0xfb,0x82,0x7a,0x4b,0x73,0xa3,0x9b,0x4a,0xd3,0x2b,0x1b,0xa2,0x28,0x9c,0x12,\n    0x29,0x9d,0x32,0x29,0xde,0x10,0x44,0xa9,0x14,0x4c,0xd9,0x94,0x8f,0x50,0x58,0x9a,\n    0x9c,0x8b,0x5d,0x99,0x1c,0x5d,0x19,0xde,0x57,0x9a,0x1b,0x5c,0x1d,0x1d,0xa5,0xb0,\n    0x34,0x39,0x17,0xb6,0xb7,0xb1,0x30,0xba,0xb4,0x37,0xb7,0xaf,0x34,0x37,0xb2,0x32,\n    0x3c,0x7a,0x67,0x65,0x6e,0x65,0x72,0x61,0x74,0x65,0x64,0x28,0x5f,0x5f,0x61,0x69,\n    0x72,0x5f,0x70,0x6c,0x61,0x63,0x65,0x68,0x6f,0x6c,0x64,0x65,0x72,0x5f,0x5f,0x29,\n    0x44,0xe0,0xde,0xe6,0xd2,0xe8,0xd2,0xde,0xdc,0x86,0x50,0x8b,0xa0,0x84,0x81,0x22,\n    0x06,0x8b,0xb0,0x04,0xca,0x18,0x28,0x91,0x22,0x29,0x93,0x42,0x06,0x34,0xcc,0xd8,\n    0xde,0xc2,0xe8,0x64,0x98,0xd0,0x95,0xe1,0x8d,0xbd,0xbd,0xc9,0x91,0xc1,0x0c,0xa1,\n    0x96,0x40,0x09,0x03,0x45,0x0c,0x96,0x60,0x09,0x94,0x31,0x50,0x22,0xc5,0x0c,0x94,\n    0x49,0x39,0x03,0x1a,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x43,0xa8,0x65,0x50,0xc2,0x40,\n    0x11,0x83,0x65,0x58,0x02,0x65,0x0c,0x94,0x48,0x91,0x94,0x49,0x49,0x03,0x16,0x70,\n    0x73,0x69,0x7a,0x65,0x43,0xa8,0xc5,0x50,0xc2,0x40,0x11,0x83,0xc5,0x58,0x02,0x65,\n    0x0c,0x94,0x48,0xe9,0x94,0x49,0x59,0x03,0x2a,0x61,0x69,0x72,0x2e,0x62,0x75,0x66,\n    0x66,0x65,0x72,0x7c,0xc2,0xd2,0xe4,0x5c,0xc4,0xea,0xcc,0xcc,0xca,0xe4,0xbe,0xe6,\n    0xd2,0xf4,0xca,0x88,0x84,0xa5,0xc9,0xb9,0xc8,0x95,0x85,0x91,0x91,0x0a,0x4b,0x93,\n    0x73,0x99,0xa3,0x93,0xab,0x1b,0xa3,0xfb,0xa2,0xcb,0x83,0x2b,0xfb,0x4a,0x73,0x33,\n    0x7b,0x23,0x62,0xc6,0xf6,0x16,0x46,0x47,0x83,0x47,0xc3,0xa1,0xcd,0x0e,0x8e,0x02,\n    0x5d,0xdb,0x10,0x6a,0x11,0x16,0x62,0x11,0x94,0x38,0x50,0xe4,0x60,0x21,0x16,0x62,\n    0x11,0x94,0x38,0x50,0xe6,0x80,0x51,0x58,0x9a,0x9c,0x4b,0x98,0xdc,0xd9,0x17,0x5d,\n    0x1e,0x5c,0xd9,0xd7,0x5c,0x9a,0x5e,0x19,0xaf,0xb0,0x34,0x39,0x97,0x30,0xb9,0xb3,\n    0x2f,0xba,0x3c,0xb8,0xb2,0xaf,0x30,0xb6,0xb4,0x33,0xb7,0xaf,0xb9,0x34,0xbd,0x32,\n    0x26,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x1c,0xbe,0x62,0x72,0x86,0x90,\n    0xc1,0x52,0x28,0x6d,0xa0,0xb8,0xc1,0x72,0x28,0x62,0xb0,0x08,0x4b,0xa0,0xbc,0x81,\n    0x02,0x07,0x0a,0x1d,0x28,0x75,0xb0,0x1c,0x8a,0x1d,0x2c,0x89,0x12,0x29,0x77,0xa0,\n    0x4c,0x0a,0x1e,0x0c,0x51,0x94,0x32,0x50,0xd0,0x40,0x51,0x03,0x85,0x0d,0x94,0x3c,\n    0x18,0x62,0x24,0x80,0x02,0x06,0x8a,0x1e,0xf0,0x79,0x6b,0x73,0x4b,0x83,0x7b,0xa3,\n    0x2b,0x73,0xa3,0x03,0x19,0x43,0x0b,0x93,0xe3,0x33,0x95,0xd6,0x06,0xc7,0x56,0x06,\n    0x32,0xb4,0xb2,0x02,0x42,0x25,0x14,0x14,0x34,0x44,0x50,0xfa,0x60,0x88,0xa1,0xf0,\n    0x81,0xe2,0x07,0x8d,0x32,0xc4,0x50,0xfe,0x40,0xf9,0x83,0x46,0x19,0x11,0xb1,0x03,\n    0x3b,0xd8,0x43,0x3b,0xb8,0x41,0x3b,0xbc,0x03,0x39,0xd4,0x03,0x3b,0x94,0x83,0x1b,\n    0x98,0x03,0x3b,0x84,0xc3,0x39,0xcc,0xc3,0x14,0x21,0x18,0x46,0x28,0xec,0xc0,0x0e,\n    0xf6,0xd0,0x0e,0x6e,0x90,0x0e,0xe4,0x50,0x0e,0xee,0x40,0x0f,0x53,0x82,0x62,0xc4,\n    0x12,0x0e,0xe9,0x20,0x0f,0x6e,0x60,0x0f,0xe5,0x20,0x0f,0xf3,0x90,0x0e,0xef,0xe0,\n    0x0e,0x53,0x02,0x63,0x04,0x15,0x0e,0xe9,0x20,0x0f,0x6e,0xc0,0x0e,0xe1,0xe0,0x0e,\n    0xe7,0x50,0x0f,0xe1,0x70,0x0e,0xe5,0xf0,0x0b,0xf6,0x50,0x0e,0xf2,0x30,0x0f,0xe9,\n    0xf0,0x0e,0xee,0x30,0x25,0x40,0x46,0x4c,0xe1,0x90,0x0e,0xf2,0xe0,0x06,0xe3,0xf0,\n    0x0e,0xed,0x00,0x0f,0xe9,0xc0,0x0e,0xe5,0xf0,0x0b,0xef,0x00,0x0f,0xf4,0x90,0x0e,\n    0xef,0xe0,0x0e,0xf3,0x30,0x65,0x50,0x18,0x67,0x84,0x12,0x0e,0xe9,0x20,0x0f,0x6e,\n    0x60,0x0f,0xe5,0x20,0x0f,0xf4,0x50,0x0e,0xf8,0x30,0x25,0xd8,0x03,0x00,0x00,0x00,\n    0x00,0x79,0x18,0x00,0x00,0x7b,0x00,0x00,0x00,0x33,0x08,0x80,0x1c,0xc4,0xe1,0x1c,\n    0x66,0x14,0x01,0x3d,0x88,0x43,0x38,0x84,0xc3,0x8c,0x42,0x80,0x07,0x79,0x78,0x07,\n    0x73,0x98,0x71,0x0c,0xe6,0x00,0x0f,0xed,0x10,0x0e,0xf4,0x80,0x0e,0x33,0x0c,0x42,\n    0x1e,0xc2,0xc1,0x1d,0xce,0xa1,0x1c,0x66,0x30,0x05,0x3d,0x88,0x43,0x38,0x84,0x83,\n    0x1b,0xcc,0x03,0x3d,0xc8,0x43,0x3d,0x8c,0x03,0x3d,0xcc,0x78,0x8c,0x74,0x70,0x07,\n    0x7b,0x08,0x07,0x79,0x48,0x87,0x70,0x70,0x07,0x7a,0x70,0x03,0x76,0x78,0x87,0x70,\n    0x20,0x87,0x19,0xcc,0x11,0x0e,0xec,0x90,0x0e,0xe1,0x30,0x0f,0x6e,0x30,0x0f,0xe3,\n    0xf0,0x0e,0xf0,0x50,0x0e,0x33,0x10,0xc4,0x1d,0xde,0x21,0x1c,0xd8,0x21,0x1d,0xc2,\n    0x61,0x1e,0x66,0x30,0x89,0x3b,0xbc,0x83,0x3b,0xd0,0x43,0x39,0xb4,0x03,0x3c,0xbc,\n    0x83,0x3c,0x84,0x03,0x3b,0xcc,0xf0,0x14,0x76,0x60,0x07,0x7b,0x68,0x07,0x37,0x68,\n    0x87,0x72,0x68,0x07,0x37,0x80,0x87,0x70,0x90,0x87,0x70,0x60,0x07,0x76,0x28,0x07,\n    0x76,0xf8,0x05,0x76,0x78,0x87,0x77,0x80,0x87,0x5f,0x08,0x87,0x71,0x18,0x87,0x72,\n    0x98,0x87,0x79,0x98,0x81,0x2c,0xee,0xf0,0x0e,0xee,0xe0,0x0e,0xf5,0xc0,0x0e,0xec,\n    0x30,0x03,0x62,0xc8,0xa1,0x1c,0xe4,0xa1,0x1c,0xcc,0xa1,0x1c,0xe4,0xa1,0x1c,0xdc,\n    0x61,0x1c,0xca,0x21,0x1c,0xc4,0x81,0x1d,0xca,0x61,0x06,0xd6,0x90,0x43,0x39,0xc8,\n    0x43,0x39,0x98,0x43,0x39,0xc8,0x43,0x39,0xb8,0xc3,0x38,0x94,0x43,0x38,0x88,0x03,\n    0x3b,0x94,0xc3,0x2f,0xbc,0x83,0x3c,0xfc,0x82,0x3b,0xd4,0x03,0x3b,0xb0,0xc3,0x0c,\n    0xc7,0x69,0x87,0x70,0x58,0x87,0x72,0x70,0x83,0x74,0x68,0x07,0x78,0x60,0x87,0x74,\n    0x18,0x87,0x74,0xa0,0x87,0x19,0xce,0x53,0x0f,0xee,0x00,0x0f,0xf2,0x50,0x0e,0xe4,\n    0x90,0x0e,0xe3,0x40,0x0f,0xe1,0x20,0x0e,0xec,0x50,0x0e,0x33,0x20,0x28,0x1d,0xdc,\n    0xc1,0x1e,0xc2,0x41,0x1e,0xd2,0x21,0x1c,0xdc,0x81,0x1e,0xdc,0xe0,0x1c,0xe4,0xe1,\n    0x1d,0xea,0x01,0x1e,0x66,0x18,0x51,0x38,0xb0,0x43,0x3a,0x9c,0x83,0x3b,0xcc,0x50,\n    0x24,0x76,0x60,0x07,0x7b,0x68,0x07,0x37,0x60,0x87,0x77,0x78,0x07,0x78,0x98,0x51,\n    0x4c,0xf4,0x90,0x0f,0xf0,0x50,0x0e,0x33,0x1e,0x6a,0x1e,0xca,0x61,0x1c,0xe8,0x21,\n    0x1d,0xde,0xc1,0x1d,0x7e,0x01,0x1e,0xe4,0xa1,0x1c,0xcc,0x21,0x1d,0xf0,0x61,0x06,\n    0x54,0x85,0x83,0x38,0xcc,0xc3,0x3b,0xb0,0x43,0x3d,0xd0,0x43,0x39,0xfc,0xc2,0x3c,\n    0xe4,0x43,0x3b,0x88,0xc3,0x3b,0xb0,0xc3,0x8c,0xc5,0x0a,0x87,0x79,0x98,0x87,0x77,\n    0x18,0x87,0x74,0x08,0x07,0x7a,0x28,0x07,0x72,0x98,0x81,0x5c,0xe3,0x10,0x0e,0xec,\n    0xc0,0x0e,0xe5,0x50,0x0e,0xf3,0x30,0x23,0xc1,0xd2,0x41,0x1e,0xe4,0xe1,0x17,0xd8,\n    0xe1,0x1d,0xde,0x01,0x1e,0x66,0x50,0x59,0x38,0xa4,0x83,0x3c,0xb8,0x81,0x39,0xd4,\n    0x83,0x3b,0x8c,0x03,0x3d,0xa4,0xc3,0x3b,0xb8,0xc3,0x2f,0x9c,0x83,0x3c,0xbc,0x43,\n    0x3d,0xc0,0xc3,0x3c,0x00,0x71,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x06,0x50,0x30,\n    0x00,0xd2,0xd0,0x00,0x00,0x61,0x20,0x00,0x00,0x3e,0x00,0x00,0x00,0x13,0x04,0x41,\n    0x2c,0x10,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0xf4,0xc6,0x22,0x86,0x61,0x18,0xc6,\n    0x22,0x04,0x41,0x10,0xc6,0x22,0x82,0x20,0x08,0xa8,0x95,0x40,0x19,0x14,0x01,0xbd,\n    0x11,0x00,0x1a,0x33,0x00,0x24,0x66,0x00,0x28,0xcc,0x00,0x00,0x00,0xe3,0x15,0x4b,\n    0x94,0x65,0x11,0x05,0x65,0x90,0x21,0x1a,0x0c,0x13,0x02,0xf9,0x8c,0x57,0x3c,0x55,\n    0xd7,0x2d,0x14,0x94,0x41,0x86,0xea,0x70,0x4c,0x08,0xe4,0x63,0x41,0x01,0x9f,0xf1,\n    0x0a,0x4a,0x13,0x03,0x31,0x70,0x28,0x28,0x83,0x0c,0x1a,0x43,0x99,0x10,0xc8,0xc7,\n    0x8a,0x00,0x3e,0xe3,0x15,0xd9,0x77,0x06,0x67,0x40,0x51,0x50,0x06,0x19,0xbe,0x48,\n    0x33,0x21,0x90,0x8f,0x15,0x01,0x7c,0xc6,0x2b,0x3c,0x32,0x68,0x03,0x36,0x20,0x03,\n    0x0a,0xca,0x20,0xc3,0x18,0x60,0x99,0x09,0x81,0x7c,0xc6,0x2b,0xc4,0x00,0x0d,0xe2,\n    0x00,0x0e,0x3c,0x0a,0xca,0x20,0xc3,0x19,0x70,0x61,0x60,0x42,0x20,0x1f,0x0b,0x0a,\n    0xf8,0x8c,0x57,0x9c,0x41,0x1b,0xd8,0x41,0x1d,0x88,0x01,0x05,0xc5,0x86,0x00,0x3e,\n    0xb3,0x0d,0x61,0x10,0x00,0xb3,0x0d,0x41,0x1b,0x04,0xb3,0x0d,0xc1,0x23,0xcc,0x36,\n    0x04,0x6e,0x30,0x64,0x10,0x10,0x03,0x00,0x00,0x09,0x00,0x00,0x00,0x5b,0x86,0x20,\n    0x00,0x85,0x2d,0x43,0x11,0x80,0xc2,0x96,0x41,0x09,0x40,0x61,0xcb,0xf0,0x04,0xa0,\n    0xb0,0x65,0xa0,0x02,0x50,0xd8,0x32,0x60,0x01,0x28,0x6c,0x19,0xba,0x00,0x14,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,\n};\nstatic const uint8_t _sfons_fs_bytecode_metal_ios[2841] = {\n    0x4d,0x54,0x4c,0x42,0x01,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x19,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x40,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,\n    0x4e,0x41,0x4d,0x45,0x06,0x00,0x6d,0x61,0x69,0x6e,0x30,0x00,0x54,0x59,0x50,0x45,\n    0x01,0x00,0x01,0x48,0x41,0x53,0x48,0x20,0x00,0x7c,0x59,0x61,0x85,0x8c,0x08,0x62,\n    0xf6,0xd0,0x45,0x0a,0x3a,0xcb,0xa8,0xa5,0x3c,0x2d,0x6c,0x6b,0x9c,0x3d,0xf0,0xf5,\n    0xc4,0xdc,0xb5,0x90,0xdc,0xee,0x5a,0x9f,0x63,0x4f,0x46,0x46,0x54,0x18,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x45,0x52,0x53,0x08,0x00,0x01,0x00,0x08,\n    0x00,0x01,0x00,0x01,0x00,0x45,0x4e,0x44,0x54,0x04,0x00,0x00,0x00,0x45,0x4e,0x44,\n    0x54,0x04,0x00,0x00,0x00,0x45,0x4e,0x44,0x54,0xde,0xc0,0x17,0x0b,0x00,0x00,0x00,\n    0x00,0x14,0x00,0x00,0x00,0x28,0x0a,0x00,0x00,0xff,0xff,0xff,0xff,0x42,0x43,0xc0,\n    0xde,0x21,0x0c,0x00,0x00,0x87,0x02,0x00,0x00,0x0b,0x82,0x20,0x00,0x02,0x00,0x00,\n    0x00,0x12,0x00,0x00,0x00,0x07,0x81,0x23,0x91,0x41,0xc8,0x04,0x49,0x06,0x10,0x32,\n    0x39,0x92,0x01,0x84,0x0c,0x25,0x05,0x08,0x19,0x1e,0x04,0x8b,0x62,0x80,0x14,0x45,\n    0x02,0x42,0x92,0x0b,0x42,0xa4,0x10,0x32,0x14,0x38,0x08,0x18,0x49,0x0a,0x32,0x44,\n    0x24,0x48,0x0a,0x90,0x21,0x23,0xc4,0x52,0x80,0x0c,0x19,0x21,0x72,0x24,0x07,0xc8,\n    0x48,0x11,0x62,0xa8,0xa0,0xa8,0x40,0xc6,0xf0,0x01,0x00,0x00,0x00,0x51,0x18,0x00,\n    0x00,0x89,0x00,0x00,0x00,0x1b,0xcc,0x25,0xf8,0xff,0xff,0xff,0xff,0x01,0x60,0x00,\n    0x09,0xa8,0x88,0x71,0x78,0x07,0x79,0x90,0x87,0x72,0x18,0x07,0x7a,0x60,0x87,0x7c,\n    0x68,0x03,0x79,0x78,0x87,0x7a,0x70,0x07,0x72,0x28,0x07,0x72,0x68,0x03,0x72,0x48,\n    0x07,0x7b,0x48,0x07,0x72,0x28,0x87,0x36,0x98,0x87,0x78,0x90,0x07,0x7a,0x68,0x03,\n    0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xcc,0x21,0x1c,0xd8,0x61,\n    0x1e,0xca,0x01,0x20,0xc8,0x21,0x1d,0xe6,0x21,0x1c,0xc4,0x81,0x1d,0xca,0xa1,0x0d,\n    0xe8,0x21,0x1c,0xd2,0x81,0x1d,0xda,0x60,0x1c,0xc2,0x81,0x1d,0xd8,0x61,0x1e,0x00,\n    0x73,0x08,0x07,0x76,0x98,0x87,0x72,0x00,0x08,0x76,0x28,0x87,0x79,0x98,0x87,0x36,\n    0x80,0x07,0x79,0x28,0x87,0x71,0x48,0x87,0x79,0x28,0x87,0x36,0x30,0x07,0x78,0x68,\n    0x87,0x70,0x20,0x07,0xc0,0x1c,0xc2,0x81,0x1d,0xe6,0xa1,0x1c,0x00,0xc2,0x1d,0xde,\n    0xa1,0x0d,0xcc,0x41,0x1e,0xc2,0xa1,0x1d,0xca,0xa1,0x0d,0xe0,0xe1,0x1d,0xd2,0xc1,\n    0x1d,0xe8,0xa1,0x1c,0xe4,0xa1,0x0d,0xca,0x81,0x1d,0xd2,0xa1,0x1d,0x00,0x7a,0x90,\n    0x87,0x7a,0x28,0x07,0x60,0x70,0x87,0x77,0x68,0x03,0x73,0x90,0x87,0x70,0x68,0x87,\n    0x72,0x68,0x03,0x78,0x78,0x87,0x74,0x70,0x07,0x7a,0x28,0x07,0x79,0x68,0x83,0x72,\n    0x60,0x87,0x74,0x68,0x87,0x36,0x70,0x87,0x77,0x70,0x87,0x36,0x60,0x87,0x72,0x08,\n    0x07,0x73,0x00,0x08,0x77,0x78,0x87,0x36,0x48,0x07,0x77,0x30,0x87,0x79,0x68,0x03,\n    0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xe8,0x41,0x1e,0xea,0xa1,\n    0x1c,0x00,0xc2,0x1d,0xde,0xa1,0x0d,0xd4,0xa1,0x1e,0xda,0x01,0x1e,0xda,0x80,0x1e,\n    0xc2,0x41,0x1c,0xd8,0xa1,0x1c,0xe6,0x01,0x30,0x87,0x70,0x60,0x87,0x79,0x28,0x07,\n    0x80,0x70,0x87,0x77,0x68,0x03,0x77,0x08,0x07,0x77,0x98,0x87,0x36,0x30,0x07,0x78,\n    0x68,0x83,0x76,0x08,0x07,0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,\n    0xdc,0xe1,0x1d,0xda,0x60,0x1e,0xd2,0xe1,0x1c,0xdc,0xa1,0x1c,0xc8,0xa1,0x0d,0xf4,\n    0xa1,0x1c,0xe4,0xe1,0x1d,0xe6,0xa1,0x0d,0xcc,0x01,0x1e,0xda,0xa0,0x1d,0xc2,0x81,\n    0x1e,0xd0,0x01,0xa0,0x07,0x79,0xa8,0x87,0x72,0x00,0x08,0x77,0x78,0x87,0x36,0xa0,\n    0x07,0x79,0x08,0x07,0x78,0x80,0x87,0x74,0x70,0x87,0x73,0x68,0x83,0x76,0x08,0x07,\n    0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,0xe6,0x81,0x1e,0xc2,0x61,\n    0x1c,0xd6,0xa1,0x0d,0xe0,0x41,0x1e,0xde,0x81,0x1e,0xca,0x61,0x1c,0xe8,0xe1,0x1d,\n    0xe4,0xa1,0x0d,0xc4,0xa1,0x1e,0xcc,0xc1,0x1c,0xca,0x41,0x1e,0xda,0x60,0x1e,0xd2,\n    0x41,0x1f,0xca,0x01,0xc0,0x03,0x80,0xa8,0x07,0x77,0x98,0x87,0x70,0x30,0x87,0x72,\n    0x68,0x03,0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xe8,0x41,0x1e,\n    0xea,0xa1,0x1c,0x00,0xa2,0x1e,0xe6,0xa1,0x1c,0xda,0x60,0x1e,0xde,0xc1,0x1c,0xe8,\n    0xa1,0x0d,0xcc,0x81,0x1d,0xde,0x21,0x1c,0xe8,0x01,0x30,0x87,0x70,0x60,0x87,0x79,\n    0x28,0x07,0x60,0x83,0x21,0x0c,0xc0,0x02,0x54,0x1b,0x8c,0x81,0x00,0x16,0xa0,0xda,\n    0x80,0x10,0xff,0xff,0xff,0xff,0x3f,0x00,0x0c,0x20,0x01,0xd5,0x06,0xa3,0x08,0x80,\n    0x05,0xa8,0x36,0x18,0x86,0x00,0x2c,0x40,0x05,0x49,0x18,0x00,0x00,0x03,0x00,0x00,\n    0x00,0x13,0x86,0x40,0x18,0x26,0x0c,0x44,0x61,0x00,0x00,0x00,0x00,0x89,0x20,0x00,\n    0x00,0x1e,0x00,0x00,0x00,0x32,0x22,0x48,0x09,0x20,0x64,0x85,0x04,0x93,0x22,0xa4,\n    0x84,0x04,0x93,0x22,0xe3,0x84,0xa1,0x90,0x14,0x12,0x4c,0x8a,0x8c,0x0b,0x84,0xa4,\n    0x4c,0x10,0x4c,0x33,0x00,0xc3,0x08,0x04,0x60,0x83,0x70,0x94,0x34,0x45,0x94,0x30,\n    0xf9,0xff,0x44,0x5c,0x13,0x15,0x11,0xbf,0x3d,0xfc,0xd3,0x18,0x01,0x30,0x88,0x30,\n    0x04,0x17,0x49,0x53,0x44,0x09,0x93,0xff,0x4b,0x00,0xf3,0x2c,0x44,0xf4,0x4f,0x63,\n    0x04,0xc0,0x20,0x42,0x21,0x94,0x42,0x84,0x40,0x0c,0x9d,0x61,0x04,0x01,0x98,0x23,\n    0x08,0xe6,0x08,0xc0,0x60,0x18,0x41,0x58,0x0a,0x12,0x88,0x49,0x8a,0x29,0x40,0x6d,\n    0x20,0x20,0x05,0xd6,0x30,0x02,0xb1,0x8c,0x00,0x00,0x00,0x00,0x00,0x13,0xa8,0x70,\n    0x48,0x07,0x79,0xb0,0x03,0x3a,0x68,0x83,0x70,0x80,0x07,0x78,0x60,0x87,0x72,0x68,\n    0x83,0x74,0x78,0x87,0x79,0xc8,0x03,0x37,0x80,0x03,0x37,0x80,0x83,0x0d,0xb7,0x51,\n    0x0e,0x6d,0x00,0x0f,0x7a,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,\n    0x74,0xd0,0x06,0xe9,0x10,0x07,0x7a,0x80,0x07,0x7a,0x80,0x07,0x6d,0x90,0x0e,0x78,\n    0xa0,0x07,0x78,0xa0,0x07,0x78,0xd0,0x06,0xe9,0x10,0x07,0x76,0xa0,0x07,0x71,0x60,\n    0x07,0x7a,0x10,0x07,0x76,0xd0,0x06,0xe9,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,\n    0x7a,0x30,0x07,0x72,0xd0,0x06,0xe9,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,\n    0x60,0x07,0x74,0xd0,0x06,0xe6,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x7a,0x30,\n    0x07,0x72,0xd0,0x06,0xe6,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,\n    0x74,0xd0,0x06,0xf6,0x10,0x07,0x76,0xa0,0x07,0x71,0x60,0x07,0x7a,0x10,0x07,0x76,\n    0xd0,0x06,0xf6,0x20,0x07,0x74,0xa0,0x07,0x73,0x20,0x07,0x7a,0x30,0x07,0x72,0xd0,\n    0x06,0xf6,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x7a,0x30,0x07,0x72,0xd0,0x06,\n    0xf6,0x40,0x07,0x78,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xd0,0x06,0xf6,\n    0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xd0,0x06,0xf6,0x90,\n    0x07,0x76,0xa0,0x07,0x71,0x20,0x07,0x78,0xa0,0x07,0x71,0x20,0x07,0x78,0xd0,0x06,\n    0xf6,0x10,0x07,0x72,0x80,0x07,0x7a,0x10,0x07,0x72,0x80,0x07,0x7a,0x10,0x07,0x72,\n    0x80,0x07,0x6d,0x60,0x0f,0x71,0x90,0x07,0x72,0xa0,0x07,0x72,0x50,0x07,0x76,0xa0,\n    0x07,0x72,0x50,0x07,0x76,0xd0,0x06,0xf6,0x20,0x07,0x75,0x60,0x07,0x7a,0x20,0x07,\n    0x75,0x60,0x07,0x7a,0x20,0x07,0x75,0x60,0x07,0x6d,0x60,0x0f,0x75,0x10,0x07,0x72,\n    0xa0,0x07,0x75,0x10,0x07,0x72,0xa0,0x07,0x75,0x10,0x07,0x72,0xd0,0x06,0xf6,0x10,\n    0x07,0x70,0x20,0x07,0x74,0xa0,0x07,0x71,0x00,0x07,0x72,0x40,0x07,0x7a,0x10,0x07,\n    0x70,0x20,0x07,0x74,0xd0,0x06,0xee,0x80,0x07,0x7a,0x10,0x07,0x76,0xa0,0x07,0x73,\n    0x20,0x07,0x43,0x18,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x80,0x21,0x8c,0x03,\n    0x04,0x80,0x00,0x00,0x00,0x00,0x00,0x40,0x16,0x08,0x00,0x00,0x00,0x08,0x00,0x00,\n    0x00,0x32,0x1e,0x98,0x10,0x19,0x11,0x4c,0x90,0x8c,0x09,0x26,0x47,0xc6,0x04,0x43,\n    0x5a,0x25,0x30,0x02,0x50,0x04,0x85,0x50,0x10,0x65,0x40,0x70,0x2c,0x01,0x12,0x00,\n    0x00,0x79,0x18,0x00,0x00,0xb7,0x00,0x00,0x00,0x1a,0x03,0x4c,0x10,0x97,0x29,0xa2,\n    0x25,0x10,0xab,0x32,0xb9,0xb9,0xb4,0x37,0xb7,0x21,0xc6,0x42,0x3c,0x00,0x84,0x50,\n    0xb9,0x1b,0x43,0x0b,0x93,0xfb,0x9a,0x4b,0xd3,0x2b,0x1b,0x62,0x2c,0xc2,0x23,0x2c,\n    0x05,0xe7,0x20,0x08,0x0e,0x8e,0xad,0x0c,0xa4,0xad,0x8c,0x2e,0x8c,0x0d,0xc4,0xae,\n    0x4c,0x6e,0x2e,0xed,0xcd,0x0d,0x64,0x26,0x06,0x06,0x26,0xc6,0xc5,0xc6,0xe6,0x06,\n    0x04,0xa5,0xad,0x8c,0x2e,0x8c,0xcd,0xac,0xac,0x65,0x26,0x06,0x06,0x26,0xc6,0xc5,\n    0xc6,0xe6,0xc6,0x45,0x26,0x65,0x88,0xf0,0x10,0x43,0x8c,0x45,0x58,0x8c,0x65,0x60,\n    0xd1,0x54,0x46,0x17,0xc6,0x36,0x04,0x79,0x8e,0x45,0x58,0x84,0x65,0xe0,0x16,0x96,\n    0x26,0xe7,0x32,0xf6,0xd6,0x06,0x97,0xc6,0x56,0xe6,0x42,0x56,0xe6,0xf6,0x26,0xd7,\n    0x36,0xf7,0x45,0x96,0x36,0x17,0x26,0xc6,0x56,0x36,0x44,0x78,0x12,0x72,0x61,0x69,\n    0x72,0x2e,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x2e,0x66,0x61,0x73,0x74,0x5f,0x6d,\n    0x61,0x74,0x68,0x5f,0x65,0x6e,0x61,0x62,0x6c,0x65,0x43,0x84,0x67,0x21,0x19,0x84,\n    0xa5,0xc9,0xb9,0x8c,0xbd,0xb5,0xc1,0xa5,0xb1,0x95,0xb9,0x98,0xc9,0x85,0xb5,0x95,\n    0x89,0xd5,0x99,0x99,0x95,0xc9,0x7d,0x99,0x95,0xd1,0x8d,0xa1,0x7d,0x95,0xb9,0x85,\n    0x89,0xb1,0x95,0x0d,0x11,0x9e,0x86,0x51,0x58,0x9a,0x9c,0x8b,0x5c,0x99,0x1b,0x59,\n    0x99,0xdc,0x17,0x5d,0x98,0xdc,0x59,0x19,0x1d,0xa3,0xb0,0x34,0x39,0x97,0x30,0xb9,\n    0xb3,0x2f,0xba,0x3c,0xb8,0xb2,0x2f,0xb7,0xb0,0xb6,0x32,0x1a,0x66,0x6c,0x6f,0x61,\n    0x74,0x34,0x64,0xc2,0xd2,0xe4,0x5c,0xc2,0xe4,0xce,0xbe,0xdc,0xc2,0xda,0xca,0xa8,\n    0x98,0xc9,0x85,0x9d,0x7d,0x8d,0xbd,0xb1,0xbd,0xc9,0x0d,0x61,0x9e,0x67,0x19,0x1e,\n    0xe8,0x89,0x1e,0xe9,0x99,0x86,0x08,0x0f,0x45,0x29,0x2c,0x4d,0xce,0xc5,0x4c,0x2e,\n    0xec,0xac,0xad,0xcc,0x8d,0xee,0x2b,0xcd,0x0d,0xae,0x8e,0x8e,0x4b,0xdd,0x5c,0x99,\n    0x1c,0x0a,0xdb,0xdb,0x98,0x1b,0x4c,0x0a,0x95,0xb0,0x34,0x39,0x97,0xb1,0x32,0x37,\n    0xba,0x32,0x39,0x3e,0x61,0x69,0x72,0x2e,0x70,0x65,0x72,0x73,0x70,0x65,0x63,0x74,\n    0x69,0x76,0x65,0x14,0xea,0xec,0x86,0x48,0xcb,0xf0,0x58,0xcf,0xf5,0x60,0x4f,0xf6,\n    0x40,0x4f,0xf4,0x48,0x8f,0xc6,0xa5,0x6e,0xae,0x4c,0x0e,0x85,0xed,0x6d,0xcc,0x2d,\n    0x26,0x85,0xc5,0xd8,0x1b,0xdb,0x9b,0xdc,0x10,0x69,0x11,0x1e,0xeb,0xe1,0x1e,0xec,\n    0xc9,0x1e,0xe8,0x89,0x1e,0xe9,0xe9,0xb8,0x84,0xa5,0xc9,0xb9,0xd0,0x95,0xe1,0xd1,\n    0xd5,0xc9,0x95,0x51,0x0a,0x4b,0x93,0x73,0x61,0x7b,0x1b,0x0b,0xa3,0x4b,0x7b,0x73,\n    0xfb,0x4a,0x73,0x23,0x2b,0xc3,0xa3,0x12,0x96,0x26,0xe7,0x32,0x17,0xd6,0x06,0xc7,\n    0x56,0x46,0x8c,0xae,0x0c,0x8f,0xae,0x4e,0xae,0x4c,0x86,0x8c,0xc7,0x8c,0xed,0x2d,\n    0x8c,0x8e,0x05,0x64,0x2e,0xac,0x0d,0x8e,0xad,0xcc,0x87,0x03,0x5d,0x19,0xde,0x10,\n    0x6a,0x21,0x9e,0xef,0x01,0x83,0x65,0x58,0x84,0x27,0x0c,0x1e,0xe8,0x11,0x83,0x47,\n    0x7a,0xc6,0x80,0x4b,0x58,0x9a,0x9c,0xcb,0x5c,0x58,0x1b,0x1c,0x5b,0x99,0x1c,0x8f,\n    0xb9,0xb0,0x36,0x38,0xb6,0x32,0x39,0x0e,0x73,0x6d,0x70,0x43,0xa4,0xe5,0x78,0xca,\n    0xe0,0x01,0x83,0x65,0x58,0x84,0x07,0x7a,0xcc,0xe0,0x91,0x9e,0x33,0x18,0x82,0x3c,\n    0xdb,0xe3,0x3d,0x64,0xf0,0xa0,0xc1,0x10,0x03,0x01,0x9e,0xea,0x49,0x83,0x11,0x11,\n    0x3b,0xb0,0x83,0x3d,0xb4,0x83,0x1b,0xb4,0xc3,0x3b,0x90,0x43,0x3d,0xb0,0x43,0x39,\n    0xb8,0x81,0x39,0xb0,0x43,0x38,0x9c,0xc3,0x3c,0x4c,0x11,0x82,0x61,0x84,0xc2,0x0e,\n    0xec,0x60,0x0f,0xed,0xe0,0x06,0xe9,0x40,0x0e,0xe5,0xe0,0x0e,0xf4,0x30,0x25,0x28,\n    0x46,0x2c,0xe1,0x90,0x0e,0xf2,0xe0,0x06,0xf6,0x50,0x0e,0xf2,0x30,0x0f,0xe9,0xf0,\n    0x0e,0xee,0x30,0x25,0x30,0x46,0x50,0xe1,0x90,0x0e,0xf2,0xe0,0x06,0xec,0x10,0x0e,\n    0xee,0x70,0x0e,0xf5,0x10,0x0e,0xe7,0x50,0x0e,0xbf,0x60,0x0f,0xe5,0x20,0x0f,0xf3,\n    0x90,0x0e,0xef,0xe0,0x0e,0x53,0x02,0x64,0xc4,0x14,0x0e,0xe9,0x20,0x0f,0x6e,0x30,\n    0x0e,0xef,0xd0,0x0e,0xf0,0x90,0x0e,0xec,0x50,0x0e,0xbf,0xf0,0x0e,0xf0,0x40,0x0f,\n    0xe9,0xf0,0x0e,0xee,0x30,0x0f,0x53,0x06,0x85,0x71,0x46,0x30,0xe1,0x90,0x0e,0xf2,\n    0xe0,0x06,0xe6,0x20,0x0f,0xe1,0x70,0x0e,0xed,0x50,0x0e,0xee,0x40,0x0f,0x53,0x02,\n    0x35,0x00,0x00,0x00,0x00,0x79,0x18,0x00,0x00,0x7b,0x00,0x00,0x00,0x33,0x08,0x80,\n    0x1c,0xc4,0xe1,0x1c,0x66,0x14,0x01,0x3d,0x88,0x43,0x38,0x84,0xc3,0x8c,0x42,0x80,\n    0x07,0x79,0x78,0x07,0x73,0x98,0x71,0x0c,0xe6,0x00,0x0f,0xed,0x10,0x0e,0xf4,0x80,\n    0x0e,0x33,0x0c,0x42,0x1e,0xc2,0xc1,0x1d,0xce,0xa1,0x1c,0x66,0x30,0x05,0x3d,0x88,\n    0x43,0x38,0x84,0x83,0x1b,0xcc,0x03,0x3d,0xc8,0x43,0x3d,0x8c,0x03,0x3d,0xcc,0x78,\n    0x8c,0x74,0x70,0x07,0x7b,0x08,0x07,0x79,0x48,0x87,0x70,0x70,0x07,0x7a,0x70,0x03,\n    0x76,0x78,0x87,0x70,0x20,0x87,0x19,0xcc,0x11,0x0e,0xec,0x90,0x0e,0xe1,0x30,0x0f,\n    0x6e,0x30,0x0f,0xe3,0xf0,0x0e,0xf0,0x50,0x0e,0x33,0x10,0xc4,0x1d,0xde,0x21,0x1c,\n    0xd8,0x21,0x1d,0xc2,0x61,0x1e,0x66,0x30,0x89,0x3b,0xbc,0x83,0x3b,0xd0,0x43,0x39,\n    0xb4,0x03,0x3c,0xbc,0x83,0x3c,0x84,0x03,0x3b,0xcc,0xf0,0x14,0x76,0x60,0x07,0x7b,\n    0x68,0x07,0x37,0x68,0x87,0x72,0x68,0x07,0x37,0x80,0x87,0x70,0x90,0x87,0x70,0x60,\n    0x07,0x76,0x28,0x07,0x76,0xf8,0x05,0x76,0x78,0x87,0x77,0x80,0x87,0x5f,0x08,0x87,\n    0x71,0x18,0x87,0x72,0x98,0x87,0x79,0x98,0x81,0x2c,0xee,0xf0,0x0e,0xee,0xe0,0x0e,\n    0xf5,0xc0,0x0e,0xec,0x30,0x03,0x62,0xc8,0xa1,0x1c,0xe4,0xa1,0x1c,0xcc,0xa1,0x1c,\n    0xe4,0xa1,0x1c,0xdc,0x61,0x1c,0xca,0x21,0x1c,0xc4,0x81,0x1d,0xca,0x61,0x06,0xd6,\n    0x90,0x43,0x39,0xc8,0x43,0x39,0x98,0x43,0x39,0xc8,0x43,0x39,0xb8,0xc3,0x38,0x94,\n    0x43,0x38,0x88,0x03,0x3b,0x94,0xc3,0x2f,0xbc,0x83,0x3c,0xfc,0x82,0x3b,0xd4,0x03,\n    0x3b,0xb0,0xc3,0x0c,0xc7,0x69,0x87,0x70,0x58,0x87,0x72,0x70,0x83,0x74,0x68,0x07,\n    0x78,0x60,0x87,0x74,0x18,0x87,0x74,0xa0,0x87,0x19,0xce,0x53,0x0f,0xee,0x00,0x0f,\n    0xf2,0x50,0x0e,0xe4,0x90,0x0e,0xe3,0x40,0x0f,0xe1,0x20,0x0e,0xec,0x50,0x0e,0x33,\n    0x20,0x28,0x1d,0xdc,0xc1,0x1e,0xc2,0x41,0x1e,0xd2,0x21,0x1c,0xdc,0x81,0x1e,0xdc,\n    0xe0,0x1c,0xe4,0xe1,0x1d,0xea,0x01,0x1e,0x66,0x18,0x51,0x38,0xb0,0x43,0x3a,0x9c,\n    0x83,0x3b,0xcc,0x50,0x24,0x76,0x60,0x07,0x7b,0x68,0x07,0x37,0x60,0x87,0x77,0x78,\n    0x07,0x78,0x98,0x51,0x4c,0xf4,0x90,0x0f,0xf0,0x50,0x0e,0x33,0x1e,0x6a,0x1e,0xca,\n    0x61,0x1c,0xe8,0x21,0x1d,0xde,0xc1,0x1d,0x7e,0x01,0x1e,0xe4,0xa1,0x1c,0xcc,0x21,\n    0x1d,0xf0,0x61,0x06,0x54,0x85,0x83,0x38,0xcc,0xc3,0x3b,0xb0,0x43,0x3d,0xd0,0x43,\n    0x39,0xfc,0xc2,0x3c,0xe4,0x43,0x3b,0x88,0xc3,0x3b,0xb0,0xc3,0x8c,0xc5,0x0a,0x87,\n    0x79,0x98,0x87,0x77,0x18,0x87,0x74,0x08,0x07,0x7a,0x28,0x07,0x72,0x98,0x81,0x5c,\n    0xe3,0x10,0x0e,0xec,0xc0,0x0e,0xe5,0x50,0x0e,0xf3,0x30,0x23,0xc1,0xd2,0x41,0x1e,\n    0xe4,0xe1,0x17,0xd8,0xe1,0x1d,0xde,0x01,0x1e,0x66,0x50,0x59,0x38,0xa4,0x83,0x3c,\n    0xb8,0x81,0x39,0xd4,0x83,0x3b,0x8c,0x03,0x3d,0xa4,0xc3,0x3b,0xb8,0xc3,0x2f,0x9c,\n    0x83,0x3c,0xbc,0x43,0x3d,0xc0,0xc3,0x3c,0x00,0x71,0x20,0x00,0x00,0x08,0x00,0x00,\n    0x00,0x16,0xb0,0x01,0x48,0xe4,0x4b,0x00,0xf3,0x2c,0xc4,0x3f,0x11,0xd7,0x44,0x45,\n    0xc4,0x6f,0x0f,0x7e,0x85,0x17,0xb7,0x6d,0x00,0x05,0x03,0x20,0x0d,0x0d,0x00,0x00,\n    0x00,0x61,0x20,0x00,0x00,0x16,0x00,0x00,0x00,0x13,0x04,0x41,0x2c,0x10,0x00,0x00,\n    0x00,0x0b,0x00,0x00,0x00,0x14,0xc7,0x22,0x80,0x40,0x20,0x88,0x8d,0x00,0x8c,0x25,\n    0x00,0x01,0xa9,0x11,0x80,0x1a,0x20,0x31,0x03,0x40,0x61,0x0e,0xe2,0xba,0xae,0x6a,\n    0x06,0x80,0xc0,0x0c,0xc0,0x08,0xc0,0x18,0x01,0x08,0x82,0x20,0xfe,0x01,0x00,0x00,\n    0x00,0x83,0x0c,0x0f,0x91,0x8c,0x18,0x28,0x42,0x80,0x39,0x4d,0x80,0x2c,0xc9,0x30,\n    0xc8,0x70,0x04,0x8d,0x05,0x91,0x7c,0x66,0x1b,0x94,0x00,0xc8,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n};\nstatic const uint8_t _sfons_vs_source_metal_sim[756] = {\n    0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,\n    0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,\n    0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,\n    0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,\n    0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x76,\n    0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,\n    0x6c,0x6f,0x61,0x74,0x34,0x78,0x34,0x20,0x6d,0x76,0x70,0x3b,0x0a,0x20,0x20,0x20,\n    0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x78,0x34,0x20,0x74,0x6d,0x3b,0x0a,0x7d,0x3b,\n    0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,\n    0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,\n    0x75,0x76,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,0x29,\n    0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,\n    0x6f,0x6c,0x6f,0x72,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,\n    0x31,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,\n    0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x5b,0x5b,0x70,\n    0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,\n    0x6c,0x6f,0x61,0x74,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x69,0x6e,0x74,0x53,0x69,0x7a,\n    0x65,0x20,0x5b,0x5b,0x70,0x6f,0x69,0x6e,0x74,0x5f,0x73,0x69,0x7a,0x65,0x5d,0x5d,\n    0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,\n    0x6e,0x30,0x5f,0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,\n    0x74,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x5b,0x5b,0x61,0x74,\n    0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,\n    0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,\n    0x64,0x30,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x31,\n    0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,\n    0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,\n    0x74,0x65,0x28,0x32,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,\n    0x61,0x74,0x20,0x70,0x73,0x69,0x7a,0x65,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,\n    0x62,0x75,0x74,0x65,0x28,0x33,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x76,\n    0x65,0x72,0x74,0x65,0x78,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,\n    0x6d,0x61,0x69,0x6e,0x30,0x28,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,\n    0x6e,0x20,0x5b,0x5b,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x2c,0x20,\n    0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,\n    0x6d,0x73,0x26,0x20,0x5f,0x31,0x39,0x20,0x5b,0x5b,0x62,0x75,0x66,0x66,0x65,0x72,\n    0x28,0x30,0x29,0x5d,0x5d,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x69,\n    0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,\n    0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,\n    0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x5f,0x31,0x39,0x2e,0x6d,0x76,0x70,0x20,0x2a,\n    0x20,0x69,0x6e,0x2e,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,\n    0x20,0x20,0x6f,0x75,0x74,0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x69,0x6e,0x74,0x53,0x69,\n    0x7a,0x65,0x20,0x3d,0x20,0x69,0x6e,0x2e,0x70,0x73,0x69,0x7a,0x65,0x3b,0x0a,0x20,\n    0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x75,0x76,0x20,0x3d,0x20,0x5f,0x31,0x39,0x2e,\n    0x74,0x6d,0x20,0x2a,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x69,0x6e,0x2e,0x74,\n    0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,\n    0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x63,0x6f,0x6c,\n    0x6f,0x72,0x20,0x3d,0x20,0x69,0x6e,0x2e,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,\n    0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,\n    0x7d,0x0a,0x0a,0x00,\n};\nstatic const uint8_t _sfons_fs_source_metal_sim[464] = {\n    0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,\n    0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,\n    0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,\n    0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,\n    0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,\n    0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,\n    0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,\n    0x20,0x5b,0x5b,0x63,0x6f,0x6c,0x6f,0x72,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,\n    0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,\n    0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,\n    0x75,0x76,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,0x29,\n    0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,\n    0x6f,0x6c,0x6f,0x72,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,\n    0x31,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x66,0x72,0x61,0x67,0x6d,0x65,\n    0x6e,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,0x69,\n    0x6e,0x30,0x28,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,0x6e,0x20,0x5b,\n    0x5b,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x2c,0x20,0x74,0x65,0x78,\n    0x74,0x75,0x72,0x65,0x32,0x64,0x3c,0x66,0x6c,0x6f,0x61,0x74,0x3e,0x20,0x74,0x65,\n    0x78,0x20,0x5b,0x5b,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x30,0x29,0x5d,0x5d,\n    0x2c,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x20,0x73,0x6d,0x70,0x20,0x5b,0x5b,\n    0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x28,0x30,0x29,0x5d,0x5d,0x29,0x0a,0x7b,0x0a,\n    0x20,0x20,0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,\n    0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,\n    0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x66,0x6c,0x6f,\n    0x61,0x74,0x34,0x28,0x31,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x31,0x2e,\n    0x30,0x2c,0x20,0x74,0x65,0x78,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,0x73,0x6d,\n    0x70,0x2c,0x20,0x69,0x6e,0x2e,0x75,0x76,0x2e,0x78,0x79,0x29,0x2e,0x78,0x29,0x20,\n    0x2a,0x20,0x69,0x6e,0x2e,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x20,0x20,\n    0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,\n\n};\n#elif defined(SOKOL_D3D11)\nstatic const uint8_t _sfons_vs_bytecode_hlsl4[1032] = {\n    0x44,0x58,0x42,0x43,0x74,0x7f,0x01,0xd9,0xf4,0xd5,0xed,0x1d,0x74,0xc1,0x30,0x27,\n    0xd8,0xe9,0x9d,0x50,0x01,0x00,0x00,0x00,0x08,0x04,0x00,0x00,0x05,0x00,0x00,0x00,\n    0x34,0x00,0x00,0x00,0x14,0x01,0x00,0x00,0x90,0x01,0x00,0x00,0x00,0x02,0x00,0x00,\n    0x8c,0x03,0x00,0x00,0x52,0x44,0x45,0x46,0xd8,0x00,0x00,0x00,0x01,0x00,0x00,0x00,\n    0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xfe,0xff,\n    0x10,0x81,0x00,0x00,0xaf,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,\n    0x73,0x00,0xab,0xab,0x3c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x60,0x00,0x00,0x00,\n    0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x98,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0xa8,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,\n    0x02,0x00,0x00,0x00,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0x31,0x39,0x5f,\n    0x6d,0x76,0x70,0x00,0x02,0x00,0x03,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x5f,0x31,0x39,0x5f,0x74,0x6d,0x00,0x4d,0x69,0x63,0x72,0x6f,\n    0x73,0x6f,0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c,0x53,0x4c,0x20,0x53,0x68,\n    0x61,0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,\n    0x2e,0x31,0x00,0xab,0x49,0x53,0x47,0x4e,0x74,0x00,0x00,0x00,0x04,0x00,0x00,0x00,\n    0x08,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x68,0x00,0x00,0x00,\n    0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,\n    0x03,0x03,0x00,0x00,0x68,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x68,0x00,0x00,0x00,\n    0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,\n    0x01,0x00,0x00,0x00,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x00,0xab,0xab,0xab,\n    0x4f,0x53,0x47,0x4e,0x68,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00,\n    0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x01,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,\n    0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,\n    0x02,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,\n    0x00,0x53,0x56,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0xab,0xab,0xab,\n    0x53,0x48,0x44,0x52,0x84,0x01,0x00,0x00,0x40,0x00,0x01,0x00,0x61,0x00,0x00,0x00,\n    0x59,0x00,0x00,0x04,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,\n    0x5f,0x00,0x00,0x03,0xf2,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x5f,0x00,0x00,0x03,\n    0x32,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x5f,0x00,0x00,0x03,0xf2,0x10,0x10,0x00,\n    0x02,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,\n    0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x01,0x00,0x00,0x00,0x67,0x00,0x00,0x04,\n    0xf2,0x20,0x10,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x68,0x00,0x00,0x02,\n    0x01,0x00,0x00,0x00,0x38,0x00,0x00,0x08,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,\n    0x56,0x15,0x10,0x00,0x01,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,\n    0x05,0x00,0x00,0x00,0x32,0x00,0x00,0x0a,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,\n    0x06,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,\n    0x04,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,\n    0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,\n    0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x36,0x00,0x00,0x05,\n    0xf2,0x20,0x10,0x00,0x01,0x00,0x00,0x00,0x46,0x1e,0x10,0x00,0x02,0x00,0x00,0x00,\n    0x38,0x00,0x00,0x08,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x56,0x15,0x10,0x00,\n    0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,\n    0x32,0x00,0x00,0x0a,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x10,0x00,\n    0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x0a,0xf2,0x00,0x10,0x00,\n    0x00,0x00,0x00,0x00,0xa6,0x1a,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,\n    0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,\n    0x32,0x00,0x00,0x0a,0xf2,0x20,0x10,0x00,0x02,0x00,0x00,0x00,0xf6,0x1f,0x10,0x00,\n    0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,\n    0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54,\n    0x74,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x06,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n};\nstatic const uint8_t _sfons_fs_bytecode_hlsl4[628] = {\n    0x44,0x58,0x42,0x43,0xb6,0x66,0xf0,0xfc,0x09,0x54,0x2a,0x35,0x84,0x1d,0x27,0xd2,\n    0xff,0xb3,0x2e,0xdb,0x01,0x00,0x00,0x00,0x74,0x02,0x00,0x00,0x05,0x00,0x00,0x00,\n    0x34,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0x14,0x01,0x00,0x00,0x48,0x01,0x00,0x00,\n    0xf8,0x01,0x00,0x00,0x52,0x44,0x45,0x46,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xff,0xff,\n    0x10,0x81,0x00,0x00,0x64,0x00,0x00,0x00,0x5c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x02,0x00,0x00,0x00,\n    0x05,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,\n    0x01,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x73,0x6d,0x70,0x00,0x74,0x65,0x78,0x00,\n    0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c,\n    0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c,\n    0x65,0x72,0x20,0x31,0x30,0x2e,0x31,0x00,0x49,0x53,0x47,0x4e,0x44,0x00,0x00,0x00,\n    0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x03,0x00,0x00,\n    0x38,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,\n    0x01,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,\n    0x00,0xab,0xab,0xab,0x4f,0x53,0x47,0x4e,0x2c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,\n    0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x53,0x56,0x5f,0x54,\n    0x61,0x72,0x67,0x65,0x74,0x00,0xab,0xab,0x53,0x48,0x44,0x52,0xa8,0x00,0x00,0x00,\n    0x40,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x5a,0x00,0x00,0x03,0x00,0x60,0x10,0x00,\n    0x00,0x00,0x00,0x00,0x58,0x18,0x00,0x04,0x00,0x70,0x10,0x00,0x00,0x00,0x00,0x00,\n    0x55,0x55,0x00,0x00,0x62,0x10,0x00,0x03,0x32,0x10,0x10,0x00,0x00,0x00,0x00,0x00,\n    0x62,0x10,0x00,0x03,0xf2,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x03,\n    0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x68,0x00,0x00,0x02,0x01,0x00,0x00,0x00,\n    0x45,0x00,0x00,0x09,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x10,0x10,0x00,\n    0x00,0x00,0x00,0x00,0x96,0x73,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x10,0x00,\n    0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x05,0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,\n    0x01,0x40,0x00,0x00,0x00,0x00,0x80,0x3f,0x38,0x00,0x00,0x07,0xf2,0x20,0x10,0x00,\n    0x00,0x00,0x00,0x00,0x06,0x0c,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x1e,0x10,0x00,\n    0x01,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54,0x74,0x00,0x00,0x00,\n    0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,\n    0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,\n};\n#elif defined(SOKOL_WGPU)\nstatic const uint8_t _sfons_vs_source_wgsl[1162] = {\n    0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20,\n    0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f,\n    0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,\n    0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x20,0x7b,0x0a,0x20,0x20,0x2f,0x2a,\n    0x20,0x40,0x6f,0x66,0x66,0x73,0x65,0x74,0x28,0x30,0x29,0x20,0x2a,0x2f,0x0a,0x20,\n    0x20,0x6d,0x76,0x70,0x20,0x3a,0x20,0x6d,0x61,0x74,0x34,0x78,0x34,0x66,0x2c,0x0a,\n    0x20,0x20,0x2f,0x2a,0x20,0x40,0x6f,0x66,0x66,0x73,0x65,0x74,0x28,0x36,0x34,0x29,\n    0x20,0x2a,0x2f,0x0a,0x20,0x20,0x74,0x6d,0x20,0x3a,0x20,0x6d,0x61,0x74,0x34,0x78,\n    0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75,0x70,0x28,0x30,0x29,\n    0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x28,0x30,0x29,0x20,0x76,0x61,0x72,\n    0x3c,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x3e,0x20,0x78,0x5f,0x31,0x39,0x20,0x3a,\n    0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x3b,0x0a,0x0a,0x76,0x61,0x72,\n    0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,\n    0x6f,0x6e,0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x76,\n    0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a,\n    0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,\n    0x76,0x61,0x74,0x65,0x3e,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x20,\n    0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,\n    0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76,\n    0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,\n    0x74,0x65,0x3e,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3a,0x20,0x76,0x65,0x63,\n    0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,\n    0x3e,0x20,0x70,0x73,0x69,0x7a,0x65,0x20,0x3a,0x20,0x66,0x33,0x32,0x3b,0x0a,0x0a,\n    0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x67,0x6c,0x5f,\n    0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,\n    0x3b,0x0a,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x20,0x7b,\n    0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x32,0x20,0x3a,0x20,0x6d,0x61,\n    0x74,0x34,0x78,0x34,0x66,0x20,0x3d,0x20,0x78,0x5f,0x31,0x39,0x2e,0x6d,0x76,0x70,\n    0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x35,0x20,0x3a,0x20,0x76,\n    0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,\n    0x31,0x3b,0x0a,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,\n    0x20,0x3d,0x20,0x28,0x78,0x5f,0x32,0x32,0x20,0x2a,0x20,0x78,0x5f,0x32,0x35,0x29,\n    0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x33,0x32,0x20,0x3a,0x20,0x6d,\n    0x61,0x74,0x34,0x78,0x34,0x66,0x20,0x3d,0x20,0x78,0x5f,0x31,0x39,0x2e,0x74,0x6d,\n    0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x33,0x36,0x20,0x3a,0x20,0x76,\n    0x65,0x63,0x32,0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,\n    0x3b,0x0a,0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x28,0x78,0x5f,0x33,0x32,0x20,0x2a,\n    0x20,0x76,0x65,0x63,0x34,0x66,0x28,0x78,0x5f,0x33,0x36,0x2e,0x78,0x2c,0x20,0x78,\n    0x5f,0x33,0x36,0x2e,0x79,0x2c,0x20,0x30,0x2e,0x30,0x66,0x2c,0x20,0x31,0x2e,0x30,\n    0x66,0x29,0x29,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x34,0x35,0x20,\n    0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,\n    0x3b,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x78,0x5f,0x34,0x35,\n    0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x7d,0x0a,0x0a,0x73,\n    0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,\n    0x0a,0x20,0x20,0x40,0x62,0x75,0x69,0x6c,0x74,0x69,0x6e,0x28,0x70,0x6f,0x73,0x69,\n    0x74,0x69,0x6f,0x6e,0x29,0x0a,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,\n    0x69,0x6f,0x6e,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x20,0x20,0x40,\n    0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x0a,0x20,0x20,0x75,0x76,\n    0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x20,0x20,0x40,0x6c,\n    0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x0a,0x20,0x20,0x63,0x6f,0x6c,\n    0x6f,0x72,0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,\n    0x0a,0x40,0x76,0x65,0x72,0x74,0x65,0x78,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,\n    0x28,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x20,0x70,0x6f,\n    0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,\n    0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,\n    0x6e,0x28,0x31,0x29,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x5f,0x70,\n    0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x2c,0x20,0x40,0x6c,\n    0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x32,0x29,0x20,0x63,0x6f,0x6c,0x6f,0x72,\n    0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,\n    0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x33,0x29,0x20,0x70,0x73,\n    0x69,0x7a,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x66,0x33,0x32,0x29,\n    0x20,0x2d,0x3e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,\n    0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x20,0x3d,0x20,0x70,0x6f,\n    0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,\n    0x20,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x20,0x3d,0x20,0x74,0x65,\n    0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,\n    0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,\n    0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x70,0x73,0x69,0x7a,0x65,0x20,\n    0x3d,0x20,0x70,0x73,0x69,0x7a,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,\n    0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,\n    0x75,0x72,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x28,0x67,0x6c,0x5f,\n    0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x75,0x76,0x2c,0x20,0x63,0x6f,\n    0x6c,0x6f,0x72,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,\n};\nstatic const uint8_t _sfons_fs_source_wgsl[674] = {\n    0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20,\n    0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f,\n    0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,\n    0x76,0x61,0x74,0x65,0x3e,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,\n    0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75,\n    0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x28,0x34,0x38,\n    0x29,0x20,0x76,0x61,0x72,0x20,0x74,0x65,0x78,0x20,0x3a,0x20,0x74,0x65,0x78,0x74,\n    0x75,0x72,0x65,0x5f,0x32,0x64,0x3c,0x66,0x33,0x32,0x3e,0x3b,0x0a,0x0a,0x40,0x67,\n    0x72,0x6f,0x75,0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,\n    0x28,0x36,0x34,0x29,0x20,0x76,0x61,0x72,0x20,0x73,0x6d,0x70,0x20,0x3a,0x20,0x73,\n    0x61,0x6d,0x70,0x6c,0x65,0x72,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,\n    0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,\n    0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,\n    0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,\n    0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20,\n    0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x34,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,\n    0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,\n    0x36,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x74,\n    0x75,0x72,0x65,0x53,0x61,0x6d,0x70,0x6c,0x65,0x28,0x74,0x65,0x78,0x2c,0x20,0x73,\n    0x6d,0x70,0x2c,0x20,0x76,0x65,0x63,0x32,0x66,0x28,0x78,0x5f,0x32,0x34,0x2e,0x78,\n    0x2c,0x20,0x78,0x5f,0x32,0x34,0x2e,0x79,0x29,0x29,0x3b,0x0a,0x20,0x20,0x6c,0x65,\n    0x74,0x20,0x78,0x5f,0x33,0x32,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,\n    0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,\n    0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x28,0x76,0x65,0x63,0x34,0x66,0x28,0x31,0x2e,\n    0x30,0x66,0x2c,0x20,0x31,0x2e,0x30,0x66,0x2c,0x20,0x31,0x2e,0x30,0x66,0x2c,0x20,\n    0x78,0x5f,0x32,0x36,0x2e,0x78,0x29,0x20,0x2a,0x20,0x78,0x5f,0x33,0x32,0x29,0x3b,\n    0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x7d,0x0a,0x0a,0x73,0x74,\n    0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,\n    0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x0a,0x20,\n    0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x5f,0x31,0x20,0x3a,0x20,\n    0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,0x66,0x72,0x61,0x67,0x6d,\n    0x65,0x6e,0x74,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x28,0x40,0x6c,0x6f,0x63,\n    0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x20,0x75,0x76,0x5f,0x70,0x61,0x72,0x61,\n    0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x20,0x40,0x6c,0x6f,0x63,0x61,\n    0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x5f,0x70,0x61,\n    0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x29,0x20,0x2d,0x3e,0x20,\n    0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x75,0x76,0x20,\n    0x3d,0x20,0x75,0x76,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x63,0x6f,\n    0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x5f,0x70,0x61,0x72,0x61,\n    0x6d,0x3b,0x0a,0x20,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x3b,0x0a,0x20,\n    0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,\n    0x28,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x29,0x3b,0x0a,0x7d,0x0a,\n    0x0a,0x00,\n};\n#elif defined(SOKOL_DUMMY_BACKEND)\nstatic const char* _sfons_vs_source_dummy = \"\";\nstatic const char* _sfons_fs_source_dummy = \"\";\n#else\n#error \"Please define one of SOKOL_GLCORE, SOKOL_GLES3, SOKOL_D3D11, SOKOL_METAL, SOKOL_WGPU or SOKOL_DUMMY_BACKEND!\"\n#endif\n\ntypedef struct _sfons_t {\n    sfons_desc_t desc;\n    sg_shader shd;\n    sgl_pipeline pip;\n    sg_image img;\n    sg_sampler smp;\n    int cur_width, cur_height;\n    bool img_dirty;\n} _sfons_t;\n\nstatic void _sfons_clear(void* ptr, size_t size) {\n    SOKOL_ASSERT(ptr && (size > 0));\n    memset(ptr, 0, size);\n}\n\nstatic void* _sfons_malloc(const sfons_allocator_t* allocator, size_t size) {\n    SOKOL_ASSERT(allocator && (size > 0));\n    void* ptr;\n    if (allocator->alloc_fn) {\n        ptr = allocator->alloc_fn(size, allocator->user_data);\n    } else {\n        ptr = malloc(size);\n    }\n    SOKOL_ASSERT(ptr);\n    return ptr;\n}\n\nstatic void* _sfons_malloc_clear(const sfons_allocator_t* allocator, size_t size) {\n    void* ptr = _sfons_malloc(allocator, size);\n    _sfons_clear(ptr, size);\n    return ptr;\n}\n\nstatic void _sfons_free(const sfons_allocator_t* allocator, void* ptr) {\n    SOKOL_ASSERT(allocator);\n    if (allocator->free_fn) {\n        allocator->free_fn(ptr, allocator->user_data);\n    } else {\n        free(ptr);\n    }\n}\n\nstatic int _sfons_render_create(void* user_ptr, int width, int height) {\n    SOKOL_ASSERT(user_ptr && (width > 8) && (height > 8));\n    _sfons_t* sfons = (_sfons_t*) user_ptr;\n\n    // sokol-gl compatible shader which treats RED channel as alpha\n    if (sfons->shd.id == SG_INVALID_ID) {\n        sg_shader_desc shd_desc;\n        _sfons_clear(&shd_desc, sizeof(shd_desc));\n        shd_desc.attrs[0].name = \"position\";\n        shd_desc.attrs[1].name = \"texcoord0\";\n        shd_desc.attrs[2].name = \"color0\";\n        shd_desc.attrs[3].name = \"psize\";\n        shd_desc.attrs[0].sem_name = \"TEXCOORD\";\n        shd_desc.attrs[0].sem_index = 0;\n        shd_desc.attrs[1].sem_name = \"TEXCOORD\";\n        shd_desc.attrs[1].sem_index = 1;\n        shd_desc.attrs[2].sem_name = \"TEXCOORD\";\n        shd_desc.attrs[2].sem_index = 2;\n        shd_desc.attrs[3].sem_name = \"TEXCOORD\";\n        shd_desc.attrs[3].sem_index = 3;\n        sg_shader_uniform_block_desc* ub = &shd_desc.vs.uniform_blocks[0];\n        ub->size = 128;\n        ub->uniforms[0].name = \"vs_params\";\n        ub->uniforms[0].type = SG_UNIFORMTYPE_FLOAT4;\n        ub->uniforms[0].array_count = 8;\n        shd_desc.fs.images[0].used = true;\n        shd_desc.fs.images[0].image_type = SG_IMAGETYPE_2D;\n        shd_desc.fs.images[0].sample_type = SG_IMAGESAMPLETYPE_FLOAT;\n        shd_desc.fs.samplers[0].used = true;\n        shd_desc.fs.samplers[0].sampler_type = SG_SAMPLERTYPE_FILTERING;\n        shd_desc.fs.image_sampler_pairs[0].used = true;\n        shd_desc.fs.image_sampler_pairs[0].glsl_name = \"tex_smp\";\n        shd_desc.fs.image_sampler_pairs[0].image_slot = 0;\n        shd_desc.fs.image_sampler_pairs[0].sampler_slot = 0;\n        shd_desc.label = \"sokol-fontstash-shader\";\n        #if defined(SOKOL_GLCORE)\n            shd_desc.vs.source = (const char*)_sfons_vs_source_glsl410;\n            shd_desc.fs.source = (const char*)_sfons_fs_source_glsl410;\n        #elif defined(SOKOL_GLES3)\n            shd_desc.vs.source = (const char*)_sfons_vs_source_glsl300es;\n            shd_desc.fs.source = (const char*)_sfons_fs_source_glsl300es;\n        #elif defined(SOKOL_METAL)\n            shd_desc.vs.entry = \"main0\";\n            shd_desc.fs.entry = \"main0\";\n            switch (sg_query_backend()) {\n                case SG_BACKEND_METAL_MACOS:\n                    shd_desc.vs.bytecode = SG_RANGE(_sfons_vs_bytecode_metal_macos);\n                    shd_desc.fs.bytecode = SG_RANGE(_sfons_fs_bytecode_metal_macos);\n                    break;\n                case SG_BACKEND_METAL_IOS:\n                    shd_desc.vs.bytecode = SG_RANGE(_sfons_vs_bytecode_metal_ios);\n                    shd_desc.fs.bytecode = SG_RANGE(_sfons_fs_bytecode_metal_ios);\n                    break;\n                default:\n                    shd_desc.vs.source = (const char*)_sfons_vs_source_metal_sim;\n                    shd_desc.fs.source = (const char*)_sfons_fs_source_metal_sim;\n                    break;\n            }\n        #elif defined(SOKOL_D3D11)\n            shd_desc.vs.bytecode = SG_RANGE(_sfons_vs_bytecode_hlsl4);\n            shd_desc.fs.bytecode = SG_RANGE(_sfons_fs_bytecode_hlsl4);\n        #elif defined(SOKOL_WGPU)\n            shd_desc.vs.source = (const char*)_sfons_vs_source_wgsl;\n            shd_desc.fs.source = (const char*)_sfons_fs_source_wgsl;\n        #else\n            shd_desc.vs.source = _sfons_vs_source_dummy;\n            shd_desc.fs.source = _sfons_fs_source_dummy;\n        #endif\n        shd_desc.label = \"sfons-shader\";\n        sfons->shd = sg_make_shader(&shd_desc);\n    }\n\n    // sokol-gl pipeline object\n    if (sfons->pip.id == SG_INVALID_ID) {\n        sg_pipeline_desc pip_desc;\n        _sfons_clear(&pip_desc, sizeof(pip_desc));\n        pip_desc.shader = sfons->shd;\n        pip_desc.colors[0].blend.enabled = true;\n        pip_desc.colors[0].blend.src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA;\n        pip_desc.colors[0].blend.dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA;\n        sfons->pip = sgl_make_pipeline(&pip_desc);\n    }\n\n    // a sampler object\n    if (sfons->smp.id == SG_INVALID_ID) {\n        sg_sampler_desc smp_desc;\n        _sfons_clear(&smp_desc, sizeof(smp_desc));\n        smp_desc.min_filter = SG_FILTER_LINEAR;\n        smp_desc.mag_filter = SG_FILTER_LINEAR;\n        smp_desc.mipmap_filter = SG_FILTER_NONE;\n        sfons->smp = sg_make_sampler(&smp_desc);\n    }\n\n    // create or re-create font atlas texture\n    if (sfons->img.id != SG_INVALID_ID) {\n        sg_destroy_image(sfons->img);\n        sfons->img.id = SG_INVALID_ID;\n    }\n    sfons->cur_width = width;\n    sfons->cur_height = height;\n\n    SOKOL_ASSERT(sfons->img.id == SG_INVALID_ID);\n    sg_image_desc img_desc;\n    _sfons_clear(&img_desc, sizeof(img_desc));\n    img_desc.width = sfons->cur_width;\n    img_desc.height = sfons->cur_height;\n    img_desc.usage = SG_USAGE_DYNAMIC;\n    img_desc.pixel_format = SG_PIXELFORMAT_R8;\n    sfons->img = sg_make_image(&img_desc);\n    return 1;\n}\n\nstatic int _sfons_render_resize(void* user_ptr, int width, int height) {\n    return _sfons_render_create(user_ptr, width, height);\n}\n\nstatic void _sfons_render_update(void* user_ptr, int* rect, const unsigned char* data) {\n    SOKOL_ASSERT(user_ptr && rect && data);\n    _SOKOL_UNUSED(rect);\n    _SOKOL_UNUSED(data);\n    _sfons_t* sfons = (_sfons_t*) user_ptr;\n    sfons->img_dirty = true;\n}\n\nstatic void _sfons_render_draw(void* user_ptr, const float* verts, const float* tcoords, const unsigned int* colors, int nverts) {\n    SOKOL_ASSERT(user_ptr && verts && tcoords && colors && (nverts > 0));\n    _sfons_t* sfons = (_sfons_t*) user_ptr;\n    sgl_enable_texture();\n    sgl_texture(sfons->img, sfons->smp);\n    sgl_push_pipeline();\n    sgl_load_pipeline(sfons->pip);\n    sgl_begin_triangles();\n    for (int i = 0; i < nverts; i++) {\n        sgl_v2f_t2f_c1i(verts[2*i+0], verts[2*i+1], tcoords[2*i+0], tcoords[2*i+1], colors[i]);\n    }\n    sgl_end();\n    sgl_pop_pipeline();\n    sgl_disable_texture();\n}\n\nstatic void _sfons_render_delete(void* user_ptr) {\n    SOKOL_ASSERT(user_ptr);\n    _sfons_t* sfons = (_sfons_t*) user_ptr;\n    if (sfons->img.id != SG_INVALID_ID) {\n        sg_destroy_image(sfons->img);\n        sfons->img.id = SG_INVALID_ID;\n    }\n    if (sfons->smp.id != SG_INVALID_ID) {\n        sg_destroy_sampler(sfons->smp);\n        sfons->smp.id = SG_INVALID_ID;\n    }\n    if (sfons->pip.id != SG_INVALID_ID) {\n        sgl_destroy_pipeline(sfons->pip);\n        sfons->pip.id = SG_INVALID_ID;\n    }\n    if (sfons->shd.id != SG_INVALID_ID) {\n        sg_destroy_shader(sfons->shd);\n        sfons->shd.id = SG_INVALID_ID;\n    }\n}\n\n#define _sfons_def(val, def) (((val) == 0) ? (def) : (val))\n\nstatic sfons_desc_t _sfons_desc_defaults(const sfons_desc_t* desc) {\n    SOKOL_ASSERT(desc);\n    sfons_desc_t res = *desc;\n    res.width = _sfons_def(res.width, 512);\n    res.height = _sfons_def(res.height, 512);\n    return res;\n}\n\nSOKOL_API_IMPL FONScontext* sfons_create(const sfons_desc_t* desc) {\n    SOKOL_ASSERT(desc);\n    SOKOL_ASSERT((desc->allocator.alloc_fn && desc->allocator.free_fn) || (!desc->allocator.alloc_fn && !desc->allocator.free_fn));\n    _sfons_t* sfons = (_sfons_t*) _sfons_malloc_clear(&desc->allocator, sizeof(_sfons_t));\n    sfons->desc = _sfons_desc_defaults(desc);\n    FONSparams params;\n    _sfons_clear(&params, sizeof(params));\n    params.width = sfons->desc.width;\n    params.height = sfons->desc.height;\n    params.flags = FONS_ZERO_TOPLEFT;\n    params.renderCreate = _sfons_render_create;\n    params.renderResize = _sfons_render_resize;\n    params.renderUpdate = _sfons_render_update;\n    params.renderDraw = _sfons_render_draw;\n    params.renderDelete = _sfons_render_delete;\n    params.userPtr = sfons;\n    return fonsCreateInternal(&params);\n}\n\nSOKOL_API_IMPL void sfons_destroy(FONScontext* ctx) {\n    SOKOL_ASSERT(ctx);\n    _sfons_t* sfons = (_sfons_t*) ctx->params.userPtr;\n    fonsDeleteInternal(ctx);\n    const sfons_allocator_t allocator = sfons->desc.allocator;\n    _sfons_free(&allocator, sfons);\n}\n\nSOKOL_API_IMPL void sfons_flush(FONScontext* ctx) {\n    SOKOL_ASSERT(ctx && ctx->params.userPtr);\n    _sfons_t* sfons = (_sfons_t*) ctx->params.userPtr;\n    if (sfons->img_dirty) {\n        sfons->img_dirty = false;\n        sg_image_data data;\n        _sfons_clear(&data, sizeof(data));\n        data.subimage[0][0].ptr = ctx->texData;\n        data.subimage[0][0].size = (size_t) (sfons->cur_width * sfons->cur_height);\n        sg_update_image(sfons->img, &data);\n    }\n}\n\nSOKOL_API_IMPL uint32_t sfons_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {\n    return ((uint32_t)r) | ((uint32_t)g<<8) | ((uint32_t)b<<16) | ((uint32_t)a<<24);\n}\n\n#endif // SOKOL_FONTSTASH_IMPL\n"
  },
  {
    "path": "thirdparty/sokol/xdg-decoration-unstable-v1-client-protocol.h",
    "content": "/* Generated by wayland-scanner 1.24.0 */\n\n#ifndef XDG_DECORATION_UNSTABLE_V1_CLIENT_PROTOCOL_H\n#define XDG_DECORATION_UNSTABLE_V1_CLIENT_PROTOCOL_H\n\n#include <stdint.h>\n#include <stddef.h>\n#include \"wayland-client.h\"\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * @page page_xdg_decoration_unstable_v1 The xdg_decoration_unstable_v1 protocol\n * @section page_ifaces_xdg_decoration_unstable_v1 Interfaces\n * - @subpage page_iface_zxdg_decoration_manager_v1 - window decoration manager\n * - @subpage page_iface_zxdg_toplevel_decoration_v1 - decoration object for a toplevel surface\n * @section page_copyright_xdg_decoration_unstable_v1 Copyright\n * <pre>\n *\n * Copyright © 2018 Simon Ser\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice (including the next\n * paragraph) shall be included in all copies or substantial portions of the\n * Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n * </pre>\n */\nstruct xdg_toplevel;\nstruct zxdg_decoration_manager_v1;\nstruct zxdg_toplevel_decoration_v1;\n\n#ifndef ZXDG_DECORATION_MANAGER_V1_INTERFACE\n#define ZXDG_DECORATION_MANAGER_V1_INTERFACE\n/**\n * @page page_iface_zxdg_decoration_manager_v1 zxdg_decoration_manager_v1\n * @section page_iface_zxdg_decoration_manager_v1_desc Description\n *\n * This interface allows a compositor to announce support for server-side\n * decorations.\n *\n * A window decoration is a set of window controls as deemed appropriate by\n * the party managing them, such as user interface components used to move,\n * resize and change a window's state.\n *\n * A client can use this protocol to request being decorated by a supporting\n * compositor.\n *\n * If compositor and client do not negotiate the use of a server-side\n * decoration using this protocol, clients continue to self-decorate as they\n * see fit.\n *\n * Warning! The protocol described in this file is experimental and\n * backward incompatible changes may be made. Backward compatible changes\n * may be added together with the corresponding interface version bump.\n * Backward incompatible changes are done by bumping the version number in\n * the protocol and interface names and resetting the interface version.\n * Once the protocol is to be declared stable, the 'z' prefix and the\n * version number in the protocol and interface names are removed and the\n * interface version number is reset.\n * @section page_iface_zxdg_decoration_manager_v1_api API\n * See @ref iface_zxdg_decoration_manager_v1.\n */\n/**\n * @defgroup iface_zxdg_decoration_manager_v1 The zxdg_decoration_manager_v1 interface\n *\n * This interface allows a compositor to announce support for server-side\n * decorations.\n *\n * A window decoration is a set of window controls as deemed appropriate by\n * the party managing them, such as user interface components used to move,\n * resize and change a window's state.\n *\n * A client can use this protocol to request being decorated by a supporting\n * compositor.\n *\n * If compositor and client do not negotiate the use of a server-side\n * decoration using this protocol, clients continue to self-decorate as they\n * see fit.\n *\n * Warning! The protocol described in this file is experimental and\n * backward incompatible changes may be made. Backward compatible changes\n * may be added together with the corresponding interface version bump.\n * Backward incompatible changes are done by bumping the version number in\n * the protocol and interface names and resetting the interface version.\n * Once the protocol is to be declared stable, the 'z' prefix and the\n * version number in the protocol and interface names are removed and the\n * interface version number is reset.\n */\nextern const struct wl_interface zxdg_decoration_manager_v1_interface;\n#endif\n#ifndef ZXDG_TOPLEVEL_DECORATION_V1_INTERFACE\n#define ZXDG_TOPLEVEL_DECORATION_V1_INTERFACE\n/**\n * @page page_iface_zxdg_toplevel_decoration_v1 zxdg_toplevel_decoration_v1\n * @section page_iface_zxdg_toplevel_decoration_v1_desc Description\n *\n * The decoration object allows the compositor to toggle server-side window\n * decorations for a toplevel surface. The client can request to switch to\n * another mode.\n *\n * The xdg_toplevel_decoration object must be destroyed before its\n * xdg_toplevel.\n * @section page_iface_zxdg_toplevel_decoration_v1_api API\n * See @ref iface_zxdg_toplevel_decoration_v1.\n */\n/**\n * @defgroup iface_zxdg_toplevel_decoration_v1 The zxdg_toplevel_decoration_v1 interface\n *\n * The decoration object allows the compositor to toggle server-side window\n * decorations for a toplevel surface. The client can request to switch to\n * another mode.\n *\n * The xdg_toplevel_decoration object must be destroyed before its\n * xdg_toplevel.\n */\nextern const struct wl_interface zxdg_toplevel_decoration_v1_interface;\n#endif\n\n#define ZXDG_DECORATION_MANAGER_V1_DESTROY 0\n#define ZXDG_DECORATION_MANAGER_V1_GET_TOPLEVEL_DECORATION 1\n\n\n/**\n * @ingroup iface_zxdg_decoration_manager_v1\n */\n#define ZXDG_DECORATION_MANAGER_V1_DESTROY_SINCE_VERSION 1\n/**\n * @ingroup iface_zxdg_decoration_manager_v1\n */\n#define ZXDG_DECORATION_MANAGER_V1_GET_TOPLEVEL_DECORATION_SINCE_VERSION 1\n\n/** @ingroup iface_zxdg_decoration_manager_v1 */\nstatic inline void\nzxdg_decoration_manager_v1_set_user_data(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) zxdg_decoration_manager_v1, user_data);\n}\n\n/** @ingroup iface_zxdg_decoration_manager_v1 */\nstatic inline void *\nzxdg_decoration_manager_v1_get_user_data(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) zxdg_decoration_manager_v1);\n}\n\nstatic inline uint32_t\nzxdg_decoration_manager_v1_get_version(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) zxdg_decoration_manager_v1);\n}\n\n/**\n * @ingroup iface_zxdg_decoration_manager_v1\n *\n * Destroy the decoration manager. This doesn't destroy objects created\n * with the manager.\n */\nstatic inline void\nzxdg_decoration_manager_v1_destroy(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zxdg_decoration_manager_v1,\n\t\t\t ZXDG_DECORATION_MANAGER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zxdg_decoration_manager_v1), WL_MARSHAL_FLAG_DESTROY);\n}\n\n/**\n * @ingroup iface_zxdg_decoration_manager_v1\n *\n * Create a new decoration object associated with the given toplevel.\n *\n * Creating an xdg_toplevel_decoration from an xdg_toplevel which has a\n * buffer attached or committed is a client error, and any attempts by a\n * client to attach or manipulate a buffer prior to the first\n * xdg_toplevel_decoration.configure event must also be treated as\n * errors.\n */\nstatic inline struct zxdg_toplevel_decoration_v1 *\nzxdg_decoration_manager_v1_get_toplevel_decoration(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1, struct xdg_toplevel *toplevel)\n{\n\tstruct wl_proxy *id;\n\n\tid = wl_proxy_marshal_flags((struct wl_proxy *) zxdg_decoration_manager_v1,\n\t\t\t ZXDG_DECORATION_MANAGER_V1_GET_TOPLEVEL_DECORATION, &zxdg_toplevel_decoration_v1_interface, wl_proxy_get_version((struct wl_proxy *) zxdg_decoration_manager_v1), 0, NULL, toplevel);\n\n\treturn (struct zxdg_toplevel_decoration_v1 *) id;\n}\n\n#ifndef ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ENUM\n#define ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ENUM\nenum zxdg_toplevel_decoration_v1_error {\n\t/**\n\t * xdg_toplevel has a buffer attached before configure\n\t */\n\tZXDG_TOPLEVEL_DECORATION_V1_ERROR_UNCONFIGURED_BUFFER = 0,\n\t/**\n\t * xdg_toplevel already has a decoration object\n\t */\n\tZXDG_TOPLEVEL_DECORATION_V1_ERROR_ALREADY_CONSTRUCTED = 1,\n\t/**\n\t * xdg_toplevel destroyed before the decoration object\n\t */\n\tZXDG_TOPLEVEL_DECORATION_V1_ERROR_ORPHANED = 2,\n\t/**\n\t * invalid mode\n\t */\n\tZXDG_TOPLEVEL_DECORATION_V1_ERROR_INVALID_MODE = 3,\n};\n#endif /* ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ENUM */\n\n#ifndef ZXDG_TOPLEVEL_DECORATION_V1_MODE_ENUM\n#define ZXDG_TOPLEVEL_DECORATION_V1_MODE_ENUM\n/**\n * @ingroup iface_zxdg_toplevel_decoration_v1\n * window decoration modes\n *\n * These values describe window decoration modes.\n */\nenum zxdg_toplevel_decoration_v1_mode {\n\t/**\n\t * no server-side window decoration\n\t */\n\tZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE = 1,\n\t/**\n\t * server-side window decoration\n\t */\n\tZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE = 2,\n};\n#endif /* ZXDG_TOPLEVEL_DECORATION_V1_MODE_ENUM */\n\n/**\n * @ingroup iface_zxdg_toplevel_decoration_v1\n * @struct zxdg_toplevel_decoration_v1_listener\n */\nstruct zxdg_toplevel_decoration_v1_listener {\n\t/**\n\t * notify a decoration mode change\n\t *\n\t * The configure event configures the effective decoration mode.\n\t * The configured state should not be applied immediately. Clients\n\t * must send an ack_configure in response to this event. See\n\t * xdg_surface.configure and xdg_surface.ack_configure for details.\n\t *\n\t * A configure event can be sent at any time. The specified mode\n\t * must be obeyed by the client.\n\t * @param mode the decoration mode\n\t */\n\tvoid (*configure)(void *data,\n\t\t\t  struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1,\n\t\t\t  uint32_t mode);\n};\n\n/**\n * @ingroup iface_zxdg_toplevel_decoration_v1\n */\nstatic inline int\nzxdg_toplevel_decoration_v1_add_listener(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1,\n\t\t\t\t\t const struct zxdg_toplevel_decoration_v1_listener *listener, void *data)\n{\n\treturn wl_proxy_add_listener((struct wl_proxy *) zxdg_toplevel_decoration_v1,\n\t\t\t\t     (void (**)(void)) listener, data);\n}\n\n#define ZXDG_TOPLEVEL_DECORATION_V1_DESTROY 0\n#define ZXDG_TOPLEVEL_DECORATION_V1_SET_MODE 1\n#define ZXDG_TOPLEVEL_DECORATION_V1_UNSET_MODE 2\n\n/**\n * @ingroup iface_zxdg_toplevel_decoration_v1\n */\n#define ZXDG_TOPLEVEL_DECORATION_V1_CONFIGURE_SINCE_VERSION 1\n\n/**\n * @ingroup iface_zxdg_toplevel_decoration_v1\n */\n#define ZXDG_TOPLEVEL_DECORATION_V1_DESTROY_SINCE_VERSION 1\n/**\n * @ingroup iface_zxdg_toplevel_decoration_v1\n */\n#define ZXDG_TOPLEVEL_DECORATION_V1_SET_MODE_SINCE_VERSION 1\n/**\n * @ingroup iface_zxdg_toplevel_decoration_v1\n */\n#define ZXDG_TOPLEVEL_DECORATION_V1_UNSET_MODE_SINCE_VERSION 1\n\n/** @ingroup iface_zxdg_toplevel_decoration_v1 */\nstatic inline void\nzxdg_toplevel_decoration_v1_set_user_data(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) zxdg_toplevel_decoration_v1, user_data);\n}\n\n/** @ingroup iface_zxdg_toplevel_decoration_v1 */\nstatic inline void *\nzxdg_toplevel_decoration_v1_get_user_data(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) zxdg_toplevel_decoration_v1);\n}\n\nstatic inline uint32_t\nzxdg_toplevel_decoration_v1_get_version(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) zxdg_toplevel_decoration_v1);\n}\n\n/**\n * @ingroup iface_zxdg_toplevel_decoration_v1\n *\n * Switch back to a mode without any server-side decorations at the next\n * commit.\n */\nstatic inline void\nzxdg_toplevel_decoration_v1_destroy(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zxdg_toplevel_decoration_v1,\n\t\t\t ZXDG_TOPLEVEL_DECORATION_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zxdg_toplevel_decoration_v1), WL_MARSHAL_FLAG_DESTROY);\n}\n\n/**\n * @ingroup iface_zxdg_toplevel_decoration_v1\n *\n * Set the toplevel surface decoration mode. This informs the compositor\n * that the client prefers the provided decoration mode.\n *\n * After requesting a decoration mode, the compositor will respond by\n * emitting an xdg_surface.configure event. The client should then update\n * its content, drawing it without decorations if the received mode is\n * server-side decorations. The client must also acknowledge the configure\n * when committing the new content (see xdg_surface.ack_configure).\n *\n * The compositor can decide not to use the client's mode and enforce a\n * different mode instead.\n *\n * Clients whose decoration mode depend on the xdg_toplevel state may send\n * a set_mode request in response to an xdg_surface.configure event and wait\n * for the next xdg_surface.configure event to prevent unwanted state.\n * Such clients are responsible for preventing configure loops and must\n * make sure not to send multiple successive set_mode requests with the\n * same decoration mode.\n *\n * If an invalid mode is supplied by the client, the invalid_mode protocol\n * error is raised by the compositor.\n */\nstatic inline void\nzxdg_toplevel_decoration_v1_set_mode(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, uint32_t mode)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zxdg_toplevel_decoration_v1,\n\t\t\t ZXDG_TOPLEVEL_DECORATION_V1_SET_MODE, NULL, wl_proxy_get_version((struct wl_proxy *) zxdg_toplevel_decoration_v1), 0, mode);\n}\n\n/**\n * @ingroup iface_zxdg_toplevel_decoration_v1\n *\n * Unset the toplevel surface decoration mode. This informs the compositor\n * that the client doesn't prefer a particular decoration mode.\n *\n * This request has the same semantics as set_mode.\n */\nstatic inline void\nzxdg_toplevel_decoration_v1_unset_mode(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) zxdg_toplevel_decoration_v1,\n\t\t\t ZXDG_TOPLEVEL_DECORATION_V1_UNSET_MODE, NULL, wl_proxy_get_version((struct wl_proxy *) zxdg_toplevel_decoration_v1), 0);\n}\n\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/sokol/xdg-shell-protocol.c",
    "content": "/* Generated by wayland-scanner 1.24.0 */\n\n/*\n * Copyright © 2008-2013 Kristian Høgsberg\n * Copyright © 2013      Rafael Antognolli\n * Copyright © 2013      Jasper St. Pierre\n * Copyright © 2010-2013 Intel Corporation\n * Copyright © 2015-2017 Samsung Electronics Co., Ltd\n * Copyright © 2015-2017 Red Hat Inc.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice (including the next\n * paragraph) shall be included in all copies or substantial portions of the\n * Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include \"wayland-util.h\"\n\n#ifndef __has_attribute\n# define __has_attribute(x) 0  /* Compatibility with non-clang compilers. */\n#endif\n\n#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)\n#define WL_PRIVATE __attribute__ ((visibility(\"hidden\")))\n#else\n#define WL_PRIVATE\n#endif\n\nextern const struct wl_interface wl_output_interface;\nextern const struct wl_interface wl_seat_interface;\nextern const struct wl_interface wl_surface_interface;\nextern const struct wl_interface xdg_popup_interface;\nextern const struct wl_interface xdg_positioner_interface;\nextern const struct wl_interface xdg_surface_interface;\nextern const struct wl_interface xdg_toplevel_interface;\n\nstatic const struct wl_interface *xdg_shell_types[] = {\n\tNULL,\n\tNULL,\n\tNULL,\n\tNULL,\n\t&xdg_positioner_interface,\n\t&xdg_surface_interface,\n\t&wl_surface_interface,\n\t&xdg_toplevel_interface,\n\t&xdg_popup_interface,\n\t&xdg_surface_interface,\n\t&xdg_positioner_interface,\n\t&xdg_toplevel_interface,\n\t&wl_seat_interface,\n\tNULL,\n\tNULL,\n\tNULL,\n\t&wl_seat_interface,\n\tNULL,\n\t&wl_seat_interface,\n\tNULL,\n\tNULL,\n\t&wl_output_interface,\n\t&wl_seat_interface,\n\tNULL,\n\t&xdg_positioner_interface,\n\tNULL,\n};\n\nstatic const struct wl_message xdg_wm_base_requests[] = {\n\t{ \"destroy\", \"\", xdg_shell_types + 0 },\n\t{ \"create_positioner\", \"n\", xdg_shell_types + 4 },\n\t{ \"get_xdg_surface\", \"no\", xdg_shell_types + 5 },\n\t{ \"pong\", \"u\", xdg_shell_types + 0 },\n};\n\nstatic const struct wl_message xdg_wm_base_events[] = {\n\t{ \"ping\", \"u\", xdg_shell_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface xdg_wm_base_interface = {\n\t\"xdg_wm_base\", 7,\n\t4, xdg_wm_base_requests,\n\t1, xdg_wm_base_events,\n};\n\nstatic const struct wl_message xdg_positioner_requests[] = {\n\t{ \"destroy\", \"\", xdg_shell_types + 0 },\n\t{ \"set_size\", \"ii\", xdg_shell_types + 0 },\n\t{ \"set_anchor_rect\", \"iiii\", xdg_shell_types + 0 },\n\t{ \"set_anchor\", \"u\", xdg_shell_types + 0 },\n\t{ \"set_gravity\", \"u\", xdg_shell_types + 0 },\n\t{ \"set_constraint_adjustment\", \"u\", xdg_shell_types + 0 },\n\t{ \"set_offset\", \"ii\", xdg_shell_types + 0 },\n\t{ \"set_reactive\", \"3\", xdg_shell_types + 0 },\n\t{ \"set_parent_size\", \"3ii\", xdg_shell_types + 0 },\n\t{ \"set_parent_configure\", \"3u\", xdg_shell_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface xdg_positioner_interface = {\n\t\"xdg_positioner\", 7,\n\t10, xdg_positioner_requests,\n\t0, NULL,\n};\n\nstatic const struct wl_message xdg_surface_requests[] = {\n\t{ \"destroy\", \"\", xdg_shell_types + 0 },\n\t{ \"get_toplevel\", \"n\", xdg_shell_types + 7 },\n\t{ \"get_popup\", \"n?oo\", xdg_shell_types + 8 },\n\t{ \"set_window_geometry\", \"iiii\", xdg_shell_types + 0 },\n\t{ \"ack_configure\", \"u\", xdg_shell_types + 0 },\n};\n\nstatic const struct wl_message xdg_surface_events[] = {\n\t{ \"configure\", \"u\", xdg_shell_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface xdg_surface_interface = {\n\t\"xdg_surface\", 7,\n\t5, xdg_surface_requests,\n\t1, xdg_surface_events,\n};\n\nstatic const struct wl_message xdg_toplevel_requests[] = {\n\t{ \"destroy\", \"\", xdg_shell_types + 0 },\n\t{ \"set_parent\", \"?o\", xdg_shell_types + 11 },\n\t{ \"set_title\", \"s\", xdg_shell_types + 0 },\n\t{ \"set_app_id\", \"s\", xdg_shell_types + 0 },\n\t{ \"show_window_menu\", \"ouii\", xdg_shell_types + 12 },\n\t{ \"move\", \"ou\", xdg_shell_types + 16 },\n\t{ \"resize\", \"ouu\", xdg_shell_types + 18 },\n\t{ \"set_max_size\", \"ii\", xdg_shell_types + 0 },\n\t{ \"set_min_size\", \"ii\", xdg_shell_types + 0 },\n\t{ \"set_maximized\", \"\", xdg_shell_types + 0 },\n\t{ \"unset_maximized\", \"\", xdg_shell_types + 0 },\n\t{ \"set_fullscreen\", \"?o\", xdg_shell_types + 21 },\n\t{ \"unset_fullscreen\", \"\", xdg_shell_types + 0 },\n\t{ \"set_minimized\", \"\", xdg_shell_types + 0 },\n};\n\nstatic const struct wl_message xdg_toplevel_events[] = {\n\t{ \"configure\", \"iia\", xdg_shell_types + 0 },\n\t{ \"close\", \"\", xdg_shell_types + 0 },\n\t{ \"configure_bounds\", \"4ii\", xdg_shell_types + 0 },\n\t{ \"wm_capabilities\", \"5a\", xdg_shell_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface xdg_toplevel_interface = {\n\t\"xdg_toplevel\", 7,\n\t14, xdg_toplevel_requests,\n\t4, xdg_toplevel_events,\n};\n\nstatic const struct wl_message xdg_popup_requests[] = {\n\t{ \"destroy\", \"\", xdg_shell_types + 0 },\n\t{ \"grab\", \"ou\", xdg_shell_types + 22 },\n\t{ \"reposition\", \"3ou\", xdg_shell_types + 24 },\n};\n\nstatic const struct wl_message xdg_popup_events[] = {\n\t{ \"configure\", \"iiii\", xdg_shell_types + 0 },\n\t{ \"popup_done\", \"\", xdg_shell_types + 0 },\n\t{ \"repositioned\", \"3u\", xdg_shell_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface xdg_popup_interface = {\n\t\"xdg_popup\", 7,\n\t3, xdg_popup_requests,\n\t3, xdg_popup_events,\n};\n\n"
  },
  {
    "path": "thirdparty/sokol/xdg-toplevel-icon-v1-client-protocol.h",
    "content": "/* Generated by wayland-scanner 1.24.0 */\n\n#ifndef XDG_TOPLEVEL_ICON_V1_CLIENT_PROTOCOL_H\n#define XDG_TOPLEVEL_ICON_V1_CLIENT_PROTOCOL_H\n\n#include <stdint.h>\n#include <stddef.h>\n#include \"wayland-client.h\"\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * @page page_xdg_toplevel_icon_v1 The xdg_toplevel_icon_v1 protocol\n * protocol to assign icons to toplevels\n *\n * @section page_desc_xdg_toplevel_icon_v1 Description\n *\n * This protocol allows clients to set icons for their toplevel surfaces\n * either via the XDG icon stock (using an icon name), or from pixel data.\n *\n * A toplevel icon represents the individual toplevel (unlike the application\n * or launcher icon, which represents the application as a whole), and may be\n * shown in window switchers, window overviews and taskbars that list\n * individual windows.\n *\n * This document adheres to RFC 2119 when using words like \"must\",\n * \"should\", \"may\", etc.\n *\n * Warning! The protocol described in this file is currently in the testing\n * phase. Backward compatible changes may be added together with the\n * corresponding interface version bump. Backward incompatible changes can\n * only be done by creating a new major version of the extension.\n *\n * @section page_ifaces_xdg_toplevel_icon_v1 Interfaces\n * - @subpage page_iface_xdg_toplevel_icon_manager_v1 - interface to manage toplevel icons\n * - @subpage page_iface_xdg_toplevel_icon_v1 - a toplevel window icon\n * @section page_copyright_xdg_toplevel_icon_v1 Copyright\n * <pre>\n *\n * Copyright © 2023-2024 Matthias Klumpp\n * Copyright ©      2024 David Edmundson\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice (including the next\n * paragraph) shall be included in all copies or substantial portions of the\n * Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n * </pre>\n */\nstruct wl_buffer;\nstruct xdg_toplevel;\nstruct xdg_toplevel_icon_manager_v1;\nstruct xdg_toplevel_icon_v1;\n\n#ifndef XDG_TOPLEVEL_ICON_MANAGER_V1_INTERFACE\n#define XDG_TOPLEVEL_ICON_MANAGER_V1_INTERFACE\n/**\n * @page page_iface_xdg_toplevel_icon_manager_v1 xdg_toplevel_icon_manager_v1\n * @section page_iface_xdg_toplevel_icon_manager_v1_desc Description\n *\n * This interface allows clients to create toplevel window icons and set\n * them on toplevel windows to be displayed to the user.\n * @section page_iface_xdg_toplevel_icon_manager_v1_api API\n * See @ref iface_xdg_toplevel_icon_manager_v1.\n */\n/**\n * @defgroup iface_xdg_toplevel_icon_manager_v1 The xdg_toplevel_icon_manager_v1 interface\n *\n * This interface allows clients to create toplevel window icons and set\n * them on toplevel windows to be displayed to the user.\n */\nextern const struct wl_interface xdg_toplevel_icon_manager_v1_interface;\n#endif\n#ifndef XDG_TOPLEVEL_ICON_V1_INTERFACE\n#define XDG_TOPLEVEL_ICON_V1_INTERFACE\n/**\n * @page page_iface_xdg_toplevel_icon_v1 xdg_toplevel_icon_v1\n * @section page_iface_xdg_toplevel_icon_v1_desc Description\n *\n * This interface defines a toplevel icon.\n * An icon can have a name, and multiple buffers.\n * In order to be applied, the icon must have either a name, or at least\n * one buffer assigned. Applying an empty icon (with no buffer or name) to\n * a toplevel should reset its icon to the default icon.\n *\n * It is up to compositor policy whether to prefer using a buffer or loading\n * an icon via its name. See 'set_name' and 'add_buffer' for details.\n * @section page_iface_xdg_toplevel_icon_v1_api API\n * See @ref iface_xdg_toplevel_icon_v1.\n */\n/**\n * @defgroup iface_xdg_toplevel_icon_v1 The xdg_toplevel_icon_v1 interface\n *\n * This interface defines a toplevel icon.\n * An icon can have a name, and multiple buffers.\n * In order to be applied, the icon must have either a name, or at least\n * one buffer assigned. Applying an empty icon (with no buffer or name) to\n * a toplevel should reset its icon to the default icon.\n *\n * It is up to compositor policy whether to prefer using a buffer or loading\n * an icon via its name. See 'set_name' and 'add_buffer' for details.\n */\nextern const struct wl_interface xdg_toplevel_icon_v1_interface;\n#endif\n\n/**\n * @ingroup iface_xdg_toplevel_icon_manager_v1\n * @struct xdg_toplevel_icon_manager_v1_listener\n */\nstruct xdg_toplevel_icon_manager_v1_listener {\n\t/**\n\t * describes a supported & preferred icon size\n\t *\n\t * This event indicates an icon size the compositor prefers to be\n\t * available if the client has scalable icons and can render to any\n\t * size.\n\t *\n\t * When the 'xdg_toplevel_icon_manager_v1' object is created, the\n\t * compositor may send one or more 'icon_size' events to describe\n\t * the list of preferred icon sizes. If the compositor has no size\n\t * preference, it may not send any 'icon_size' event, and it is up\n\t * to the client to decide a suitable icon size.\n\t *\n\t * A sequence of 'icon_size' events must be finished with a 'done'\n\t * event. If the compositor has no size preferences, it must still\n\t * send the 'done' event, without any preceding 'icon_size' events.\n\t * @param size the edge size of the square icon in surface-local coordinates, e.g. 64\n\t */\n\tvoid (*icon_size)(void *data,\n\t\t\t  struct xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager_v1,\n\t\t\t  int32_t size);\n\t/**\n\t * all information has been sent\n\t *\n\t * This event is sent after all 'icon_size' events have been\n\t * sent.\n\t */\n\tvoid (*done)(void *data,\n\t\t     struct xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager_v1);\n};\n\n/**\n * @ingroup iface_xdg_toplevel_icon_manager_v1\n */\nstatic inline int\nxdg_toplevel_icon_manager_v1_add_listener(struct xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager_v1,\n\t\t\t\t\t  const struct xdg_toplevel_icon_manager_v1_listener *listener, void *data)\n{\n\treturn wl_proxy_add_listener((struct wl_proxy *) xdg_toplevel_icon_manager_v1,\n\t\t\t\t     (void (**)(void)) listener, data);\n}\n\n#define XDG_TOPLEVEL_ICON_MANAGER_V1_DESTROY 0\n#define XDG_TOPLEVEL_ICON_MANAGER_V1_CREATE_ICON 1\n#define XDG_TOPLEVEL_ICON_MANAGER_V1_SET_ICON 2\n\n/**\n * @ingroup iface_xdg_toplevel_icon_manager_v1\n */\n#define XDG_TOPLEVEL_ICON_MANAGER_V1_ICON_SIZE_SINCE_VERSION 1\n/**\n * @ingroup iface_xdg_toplevel_icon_manager_v1\n */\n#define XDG_TOPLEVEL_ICON_MANAGER_V1_DONE_SINCE_VERSION 1\n\n/**\n * @ingroup iface_xdg_toplevel_icon_manager_v1\n */\n#define XDG_TOPLEVEL_ICON_MANAGER_V1_DESTROY_SINCE_VERSION 1\n/**\n * @ingroup iface_xdg_toplevel_icon_manager_v1\n */\n#define XDG_TOPLEVEL_ICON_MANAGER_V1_CREATE_ICON_SINCE_VERSION 1\n/**\n * @ingroup iface_xdg_toplevel_icon_manager_v1\n */\n#define XDG_TOPLEVEL_ICON_MANAGER_V1_SET_ICON_SINCE_VERSION 1\n\n/** @ingroup iface_xdg_toplevel_icon_manager_v1 */\nstatic inline void\nxdg_toplevel_icon_manager_v1_set_user_data(struct xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager_v1, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) xdg_toplevel_icon_manager_v1, user_data);\n}\n\n/** @ingroup iface_xdg_toplevel_icon_manager_v1 */\nstatic inline void *\nxdg_toplevel_icon_manager_v1_get_user_data(struct xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager_v1)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) xdg_toplevel_icon_manager_v1);\n}\n\nstatic inline uint32_t\nxdg_toplevel_icon_manager_v1_get_version(struct xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager_v1)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) xdg_toplevel_icon_manager_v1);\n}\n\n/**\n * @ingroup iface_xdg_toplevel_icon_manager_v1\n *\n * Destroy the toplevel icon manager.\n * This does not destroy objects created with the manager.\n */\nstatic inline void\nxdg_toplevel_icon_manager_v1_destroy(struct xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager_v1)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel_icon_manager_v1,\n\t\t\t XDG_TOPLEVEL_ICON_MANAGER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel_icon_manager_v1), WL_MARSHAL_FLAG_DESTROY);\n}\n\n/**\n * @ingroup iface_xdg_toplevel_icon_manager_v1\n *\n * Creates a new icon object. This icon can then be attached to a\n * xdg_toplevel via the 'set_icon' request.\n */\nstatic inline struct xdg_toplevel_icon_v1 *\nxdg_toplevel_icon_manager_v1_create_icon(struct xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager_v1)\n{\n\tstruct wl_proxy *id;\n\n\tid = wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel_icon_manager_v1,\n\t\t\t XDG_TOPLEVEL_ICON_MANAGER_V1_CREATE_ICON, &xdg_toplevel_icon_v1_interface, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel_icon_manager_v1), 0, NULL);\n\n\treturn (struct xdg_toplevel_icon_v1 *) id;\n}\n\n/**\n * @ingroup iface_xdg_toplevel_icon_manager_v1\n *\n * This request assigns the icon 'icon' to 'toplevel', or clears the\n * toplevel icon if 'icon' was null.\n * This state is double-buffered and is applied on the next\n * wl_surface.commit of the toplevel.\n *\n * After making this call, the xdg_toplevel_icon_v1 provided as 'icon'\n * can be destroyed by the client without 'toplevel' losing its icon.\n * The xdg_toplevel_icon_v1 is immutable from this point, and any\n * future attempts to change it must raise the\n * 'xdg_toplevel_icon_v1.immutable' protocol error.\n *\n * The compositor must set the toplevel icon from either the pixel data\n * the icon provides, or by loading a stock icon using the icon name.\n * See the description of 'xdg_toplevel_icon_v1' for details.\n *\n * If 'icon' is set to null, the icon of the respective toplevel is reset\n * to its default icon (usually the icon of the application, derived from\n * its desktop-entry file, or a placeholder icon).\n * If this request is passed an icon with no pixel buffers or icon name\n * assigned, the icon must be reset just like if 'icon' was null.\n */\nstatic inline void\nxdg_toplevel_icon_manager_v1_set_icon(struct xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager_v1, struct xdg_toplevel *toplevel, struct xdg_toplevel_icon_v1 *icon)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel_icon_manager_v1,\n\t\t\t XDG_TOPLEVEL_ICON_MANAGER_V1_SET_ICON, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel_icon_manager_v1), 0, toplevel, icon);\n}\n\n#ifndef XDG_TOPLEVEL_ICON_V1_ERROR_ENUM\n#define XDG_TOPLEVEL_ICON_V1_ERROR_ENUM\nenum xdg_toplevel_icon_v1_error {\n\t/**\n\t * the provided buffer does not satisfy requirements\n\t */\n\tXDG_TOPLEVEL_ICON_V1_ERROR_INVALID_BUFFER = 1,\n\t/**\n\t * the icon has already been assigned to a toplevel and must not be changed\n\t */\n\tXDG_TOPLEVEL_ICON_V1_ERROR_IMMUTABLE = 2,\n\t/**\n\t * the provided buffer has been destroyed before the toplevel icon\n\t */\n\tXDG_TOPLEVEL_ICON_V1_ERROR_NO_BUFFER = 3,\n};\n#endif /* XDG_TOPLEVEL_ICON_V1_ERROR_ENUM */\n\n#define XDG_TOPLEVEL_ICON_V1_DESTROY 0\n#define XDG_TOPLEVEL_ICON_V1_SET_NAME 1\n#define XDG_TOPLEVEL_ICON_V1_ADD_BUFFER 2\n\n\n/**\n * @ingroup iface_xdg_toplevel_icon_v1\n */\n#define XDG_TOPLEVEL_ICON_V1_DESTROY_SINCE_VERSION 1\n/**\n * @ingroup iface_xdg_toplevel_icon_v1\n */\n#define XDG_TOPLEVEL_ICON_V1_SET_NAME_SINCE_VERSION 1\n/**\n * @ingroup iface_xdg_toplevel_icon_v1\n */\n#define XDG_TOPLEVEL_ICON_V1_ADD_BUFFER_SINCE_VERSION 1\n\n/** @ingroup iface_xdg_toplevel_icon_v1 */\nstatic inline void\nxdg_toplevel_icon_v1_set_user_data(struct xdg_toplevel_icon_v1 *xdg_toplevel_icon_v1, void *user_data)\n{\n\twl_proxy_set_user_data((struct wl_proxy *) xdg_toplevel_icon_v1, user_data);\n}\n\n/** @ingroup iface_xdg_toplevel_icon_v1 */\nstatic inline void *\nxdg_toplevel_icon_v1_get_user_data(struct xdg_toplevel_icon_v1 *xdg_toplevel_icon_v1)\n{\n\treturn wl_proxy_get_user_data((struct wl_proxy *) xdg_toplevel_icon_v1);\n}\n\nstatic inline uint32_t\nxdg_toplevel_icon_v1_get_version(struct xdg_toplevel_icon_v1 *xdg_toplevel_icon_v1)\n{\n\treturn wl_proxy_get_version((struct wl_proxy *) xdg_toplevel_icon_v1);\n}\n\n/**\n * @ingroup iface_xdg_toplevel_icon_v1\n *\n * Destroys the 'xdg_toplevel_icon_v1' object.\n * The icon must still remain set on every toplevel it was assigned to,\n * until the toplevel icon is reset explicitly.\n */\nstatic inline void\nxdg_toplevel_icon_v1_destroy(struct xdg_toplevel_icon_v1 *xdg_toplevel_icon_v1)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel_icon_v1,\n\t\t\t XDG_TOPLEVEL_ICON_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel_icon_v1), WL_MARSHAL_FLAG_DESTROY);\n}\n\n/**\n * @ingroup iface_xdg_toplevel_icon_v1\n *\n * This request assigns an icon name to this icon.\n * Any previously set name is overridden.\n *\n * The compositor must resolve 'icon_name' according to the lookup rules\n * described in the XDG icon theme specification[1] using the\n * environment's current icon theme.\n *\n * If the compositor does not support icon names or cannot resolve\n * 'icon_name' according to the XDG icon theme specification it must\n * fall back to using pixel buffer data instead.\n *\n * If this request is made after the icon has been assigned to a toplevel\n * via 'set_icon', a 'immutable' error must be raised.\n *\n * [1]: https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html\n */\nstatic inline void\nxdg_toplevel_icon_v1_set_name(struct xdg_toplevel_icon_v1 *xdg_toplevel_icon_v1, const char *icon_name)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel_icon_v1,\n\t\t\t XDG_TOPLEVEL_ICON_V1_SET_NAME, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel_icon_v1), 0, icon_name);\n}\n\n/**\n * @ingroup iface_xdg_toplevel_icon_v1\n *\n * This request adds pixel data supplied as wl_buffer to the icon.\n *\n * The client should add pixel data for all icon sizes and scales that\n * it can provide, or which are explicitly requested by the compositor\n * via 'icon_size' events on xdg_toplevel_icon_manager_v1.\n *\n * The wl_buffer supplying pixel data as 'buffer' must be backed by wl_shm\n * and must be a square (width and height being equal).\n * If any of these buffer requirements are not fulfilled, a 'invalid_buffer'\n * error must be raised.\n *\n * If this icon instance already has a buffer of the same size and scale\n * from a previous 'add_buffer' request, data from the last request\n * overrides the preexisting pixel data.\n *\n * The wl_buffer must be kept alive for as long as the xdg_toplevel_icon\n * it is associated with is not destroyed, otherwise a 'no_buffer' error\n * is raised. The buffer contents must not be modified after it was\n * assigned to the icon. As a result, the region of the wl_shm_pool's\n * backing storage used for the wl_buffer must not be modified after this\n * request is sent. The wl_buffer.release event is unused.\n *\n * If this request is made after the icon has been assigned to a toplevel\n * via 'set_icon', a 'immutable' error must be raised.\n */\nstatic inline void\nxdg_toplevel_icon_v1_add_buffer(struct xdg_toplevel_icon_v1 *xdg_toplevel_icon_v1, struct wl_buffer *buffer, int32_t scale)\n{\n\twl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel_icon_v1,\n\t\t\t XDG_TOPLEVEL_ICON_V1_ADD_BUFFER, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel_icon_v1), 0, buffer, scale);\n}\n\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "thirdparty/sokol/xdg-toplevel-icon-v1-protocol.c",
    "content": "/* Generated by wayland-scanner 1.24.0 */\n\n/*\n * Copyright © 2023-2024 Matthias Klumpp\n * Copyright ©      2024 David Edmundson\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice (including the next\n * paragraph) shall be included in all copies or substantial portions of the\n * Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n#include <stdbool.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include \"wayland-util.h\"\n\n#ifndef __has_attribute\n# define __has_attribute(x) 0  /* Compatibility with non-clang compilers. */\n#endif\n\n#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)\n#define WL_PRIVATE __attribute__ ((visibility(\"hidden\")))\n#else\n#define WL_PRIVATE\n#endif\n\nextern const struct wl_interface wl_buffer_interface;\nextern const struct wl_interface xdg_toplevel_interface;\nextern const struct wl_interface xdg_toplevel_icon_v1_interface;\n\nstatic const struct wl_interface *xdg_toplevel_icon_v1_types[] = {\n\tNULL,\n\t&xdg_toplevel_icon_v1_interface,\n\t&xdg_toplevel_interface,\n\t&xdg_toplevel_icon_v1_interface,\n\t&wl_buffer_interface,\n\tNULL,\n};\n\nstatic const struct wl_message xdg_toplevel_icon_manager_v1_requests[] = {\n\t{ \"destroy\", \"\", xdg_toplevel_icon_v1_types + 0 },\n\t{ \"create_icon\", \"n\", xdg_toplevel_icon_v1_types + 1 },\n\t{ \"set_icon\", \"o?o\", xdg_toplevel_icon_v1_types + 2 },\n};\n\nstatic const struct wl_message xdg_toplevel_icon_manager_v1_events[] = {\n\t{ \"icon_size\", \"i\", xdg_toplevel_icon_v1_types + 0 },\n\t{ \"done\", \"\", xdg_toplevel_icon_v1_types + 0 },\n};\n\nWL_PRIVATE const struct wl_interface xdg_toplevel_icon_manager_v1_interface = {\n\t\"xdg_toplevel_icon_manager_v1\", 1,\n\t3, xdg_toplevel_icon_manager_v1_requests,\n\t2, xdg_toplevel_icon_manager_v1_events,\n};\n\nstatic const struct wl_message xdg_toplevel_icon_v1_requests[] = {\n\t{ \"destroy\", \"\", xdg_toplevel_icon_v1_types + 0 },\n\t{ \"set_name\", \"s\", xdg_toplevel_icon_v1_types + 0 },\n\t{ \"add_buffer\", \"oi\", xdg_toplevel_icon_v1_types + 4 },\n};\n\nWL_PRIVATE const struct wl_interface xdg_toplevel_icon_v1_interface = {\n\t\"xdg_toplevel_icon_v1\", 1,\n\t3, xdg_toplevel_icon_v1_requests,\n\t0, NULL,\n};\n\n"
  },
  {
    "path": "thirdparty/stb_image/README.md",
    "content": "# [nothings/stb](https://github.com/nothings/stb)\n\nstb_image.h is a public domain image loader for popular graphics file formats.\n\n## MIT license\n\n```\nCopyright (c) 2017 Sean Barrett\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n"
  },
  {
    "path": "thirdparty/stb_image/stb_v_header.h",
    "content": "/*\n* stbi set globals var functions\n*/\nvoid set_png_compression_level(int level);\nvoid write_force_png_filter(int level);\nvoid write_tga_with_rle(int level);\n"
  },
  {
    "path": "thirdparty/stb_vorbis/README.md",
    "content": "Source: https://github.com/nothings/stb/blob/1ee679ca2ef753a528db5ba6801e1067b40481b8/stb_vorbis.c, 2021-07-12\n\nOgg Vorbis audio decoder - v1.22 - public domain, http://nothings.org/stb_vorbis/\n\nOriginal version written by Sean Barrett in 2007.\n\nOriginally sponsored by RAD Game Tools. Seeking implementation\nsponsored by Phillip Bennefall, Marc Andersen, Aaron Baker,\nElias Software, Aras Pranckevicius, and Sean Barrett.\n\nCopyright (c) 2017 Sean Barrett\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "vlib/cli/testdata/no_execute.out",
    "content": ""
  },
  {
    "path": "vlib/encoding/xml/test/local/04_empty_file/empty.xml",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/custom_comptime_define_if_debug.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/custom_comptime_define_if_flag.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/discard_import_usage.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/generic_type_inference.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/globals_run/global_nested_struct_test.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/hex_literal_overflow.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/import_duplicate_err.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/inc_ok.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/incorrect_name_const.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/infix_and_op_expr_err.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/modules/deprecated_module/v.mod",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/modules/module_with_redeclaration/v.mod",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/no_arrays_of_references_in_translated.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/no_assign_0_to_a_reference_field_notice_in_translated.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/no_cannot_cast_a_fixed_array_in_translated.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/no_function_must_be_called_from_unsafe_in_translated.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/no_goto_requires_unsafe_in_translated.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/no_method_must_be_called_from_unsafe_in_translated.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/no_operator_can_only_be_used_as_a_statement_in_translated.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/no_pointer_arithmetic_is_only_allowed_in_translated.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/no_reading_a_union_field_in_translated.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/no_sign_notice_in_translated.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/no_uninitialized_fn_struct_field_notice_in_translated.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/no_unused_variable_in_translated.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/no_warning_for_in_mut_var_unused.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/return_working_comp_if.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/return_working_comp_if_nested.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/return_working_unsafe.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/stack_var_check_err.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/struct_init_wrong_warn.out",
    "content": ""
  },
  {
    "path": "vlib/v/checker/tests/sync_receiver_decl.out",
    "content": ""
  },
  {
    "path": "vlib/v/fmt/testdata/vmodules/submod_import_alias/vlas/internal/blas/.gitkeep",
    "content": ""
  },
  {
    "path": "vlib/v/gen/c/testdata/alias_c_parent_type_decl.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/c/testdata/alias_interface_method_call.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/c/testdata/aligned_attr_gcc_windows.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/c/testdata/aligned_attr_msvc_windows.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/c/testdata/aligned_attr_nix.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/c/testdata/array_init_no_error.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/c/testdata/autofree_mut_array_reassign.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/c/testdata/autofree_toml.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/c/testdata/comptime_if_cond.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/c/testdata/const_none_memdup.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/c/testdata/multiple_c_cources/v.mod",
    "content": ""
  },
  {
    "path": "vlib/v/gen/c/testdata/struct_field_result_init.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/c/testdata/sumtype_struct_depend_order.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/c/testdata/translated/v.mod",
    "content": ""
  },
  {
    "path": "vlib/v/gen/native/tests/float.vv.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/native/tests/libc.vv.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/native/tests/method.vv.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/native/tests/multi_assign.vv.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/native/tests/new_transformer.vv.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/native/tests/struct_with_fn.vv.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/native/tests/sumcall.vv.out",
    "content": ""
  },
  {
    "path": "vlib/v/gen/native/tests/vtest_int_cmp.vv.out",
    "content": ""
  },
  {
    "path": "vlib/v/parser/testdata/stdout/.gitkeep",
    "content": ""
  },
  {
    "path": "vlib/v/parser/tests/array_init_parenthesized_optional_elem_type.out",
    "content": ""
  },
  {
    "path": "vlib/v/parser/tests/attribute_call_syntax.out",
    "content": ""
  },
  {
    "path": "vlib/v/parser/tests/fn_call_args_without_comma_1_err.out",
    "content": ""
  },
  {
    "path": "vlib/v/parser/tests/fn_call_args_without_comma_2_err.out",
    "content": ""
  },
  {
    "path": "vlib/v/parser/tests/function_prototype_in_struct.out",
    "content": ""
  },
  {
    "path": "vlib/v/parser/tests/import_alias_selective_fn_used.out",
    "content": ""
  },
  {
    "path": "vlib/v/parser/tests/struct_with_empty_pub_mut_section.out",
    "content": ""
  },
  {
    "path": "vlib/v/parser/tests/type_fn_eof_on_same_line.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/aliasing_c_structs/v.mod",
    "content": ""
  },
  {
    "path": "vlib/v/tests/bench/math_big_gcd/prime/.skip_should_compile_all",
    "content": ""
  },
  {
    "path": "vlib/v/tests/c_structs/v.mod",
    "content": ""
  },
  {
    "path": "vlib/v/tests/generics/v.mod",
    "content": ""
  },
  {
    "path": "vlib/v/tests/modules/callback_consumer_module/v.mod",
    "content": ""
  },
  {
    "path": "vlib/v/tests/modules/sub/foo/c/v.mod",
    "content": ""
  },
  {
    "path": "vlib/v/tests/printing/dump_c_structs/v.mod",
    "content": ""
  },
  {
    "path": "vlib/v/tests/printing_c_structs/v.mod",
    "content": ""
  },
  {
    "path": "vlib/v/tests/project_compiling_to_wasm/v.mod",
    "content": ""
  },
  {
    "path": "vlib/v/tests/project_importing_v_keywords/v.mod",
    "content": ""
  },
  {
    "path": "vlib/v/tests/project_issue_21476/v.mod",
    "content": ""
  },
  {
    "path": "vlib/v/tests/project_with_c_code_ct_ifs/v.mod",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/aggregate_call.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/arr_prepend.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/array_init_from_sumtype.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/array_push.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/assert_passes_test.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/call_arguments.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/for_linked_list.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/generic_iterator_loop.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/generics_array_delete_method.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/import_json_only.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/interface_struct_unused.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/interface_unused.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/method_as_fn_pointer.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/option_array_init.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/simple_array_init.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/skip_unused/struct_field_default_expr.run.out",
    "content": ""
  },
  {
    "path": "vlib/v/tests/testdata/usecache_and_mods/v.mod",
    "content": ""
  },
  {
    "path": "vlib/vweb/tests/dynamic_template_manager_test_server/vcache_dtm/.gitkeep",
    "content": ""
  }
]